diff --git a/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/.gitignore b/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/.gitignore new file mode 100644 index 00000000..c9f61e12 --- /dev/null +++ b/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/.gitignore @@ -0,0 +1,2 @@ +linux-3.2.71* +kernel-3.2* diff --git a/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/Makefile b/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/Makefile new file mode 100644 index 00000000..06577e25 --- /dev/null +++ b/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/Makefile @@ -0,0 +1,41 @@ +############################################################ +# +# +# Copyright 2015 Big Switch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ + +THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) +include $(ONL)/make/config.mk + +ifndef K_TARGET_DIR +K_TARGET_DIR := $(THIS_DIR) +endif + +include ../../kconfig.mk +K_CONFIG := arm-iproc-all.config +K_BUILD_TARGET := Image +K_COPY_SRC := arch/arm/boot/Image +K_COPY_GZIP := 1 +ifndef K_COPY_DST +K_COPY_DST := kernel-3.2-deb7-arm-iproc-all.bin.gz +endif + +export ARCH=arm +DTS_LIST := accton_as4610_54 + +include $(ONL)/make/kbuild.mk diff --git a/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/arm-iproc-all.config b/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/arm-iproc-all.config new file mode 100644 index 00000000..0cd2c429 --- /dev/null +++ b/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/arm-iproc-all.config @@ -0,0 +1,2418 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.2.71 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y +CONFIG_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="arm-linux-gnueabi-" +CONFIG_LOCALVERSION="-OpenNetworkLinux" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="onl" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_SPARSE_IRQ is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CGROUPS 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 is not set +# CONFIG_RD_LZMA is not set +CONFIG_RD_XZ=y +# CONFIG_RD_LZO is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_HOTPLUG=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_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +# 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=y +CONFIG_OPROFILE=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_PRIMA2 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LPC32XX 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_TEGRA is not set +# CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_TCC_926 is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +# CONFIG_ARCH_ZYNQ is not set +CONFIG_ARCH_IPROC=y +CONFIG_BCM_ZRELADDR=0x61008000 +CONFIG_GPIO_PCA953X=y + +# +# Broadcom IPROC architecture based implementations +# +# CONFIG_ARCH_NORTHSTAR is not set +CONFIG_MACH_IPROC=y +# CONFIG_IPROC_64K_PAGE is not set +CONFIG_GP_TIMER_COMPARATOR_LOAD_DELAY=y +CONFIG_IPROC_DCACHE_INVALIDATION=y +# CONFIG_IPROC_TIMER_UNIT_TESTS is not set +# CONFIG_IPROC_SW_RESET_RECORD is not set +# CONFIG_BRCM_PROP_MODULES is not set +# CONFIG_BCM_STM is not set +CONFIG_BCM_PARAMS_PHYS=0x61000000 +CONFIG_BCM_RAM_BASE=0x60000000 +CONFIG_BCM_RAM_START_RESERVED_SIZE=0x200000 + +# +# iProc SoC based Machine types +# +# CONFIG_MACH_CYGNUS is not set +# CONFIG_MACH_NS is not set +# CONFIG_MACH_HX4 is not set +# CONFIG_MACH_HR2 is not set +# CONFIG_MACH_NSP is not set +# CONFIG_MACH_KT2 is not set +# CONFIG_MACH_GH is not set +# CONFIG_MACH_DNI_3448P is not set +CONFIG_MACH_ACCTON_AS4610_54=y +# CONFIG_MACH_IPROC_EMULATION is not set + +# +# System MMU +# + +# +# 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_THUMB=y +# CONFIG_ARM_THUMBEE is not set +# 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_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_CPU_HAS_PMU=y +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_PL310_ERRATA_753970 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_PL310_ERRATA_769419 is not set +CONFIG_ARM_GIC=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +CONFIG_PCI=y +CONFIG_PCI_SYSCALL=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCI_DEBUG 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_PCCARD=y +CONFIG_PCMCIA=y +# CONFIG_PCMCIA_LOAD_CIS is not set +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +# CONFIG_YENTA is not set +# CONFIG_PD6729 is not set +# CONFIG_I82092 is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=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_TWD=y +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 is not set +CONFIG_LOCAL_TIMERS=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +# 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_HW_PERF_EVENTS=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_CLEANCACHE 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_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_SUSPEND is not set +# CONFIG_PM_RUNTIME is not set +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_ARM_CPU_SUSPEND is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM=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_XFRM_IPCOMP=y +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=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_IP_MROUTE=y +# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set +# CONFIG_IP_PIMSM_V1 is not set +CONFIG_IP_PIMSM_V2=y +CONFIG_ARPD=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=y +CONFIG_TCP_CONG_HTCP=y +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_VEGAS 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_DEFAULT_BIC is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_WESTWOOD is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_TUNNEL=y +CONFIG_INET6_TUNNEL=y +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETWORK_PHY_TIMESTAMPING=y +# 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_NET_DSA is not set +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_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +# CONFIG_NET_SCH_FQ_CODEL is not set + +# +# Classification +# +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_SCH_FIFO=y +CONFIG_DCB=y +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=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_FIB_RULES=y +# 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_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# 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_CONNECTOR=y +CONFIG_PROC_EVENTS=y +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_CHAR=y +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 + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_OF_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY 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_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# 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_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_INTEL_VR_NOR is not set +CONFIG_MTD_PLATRAM=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_M25PXX_STAY_IN_3BYTE_MODE 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_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# 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_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_DENALI is not set +CONFIG_MTD_NAND_GPIO=y +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_RICOH is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_PLATFORM=y +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_DEBUG is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_GPIO=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_SPI=y +CONFIG_OF_MDIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_CPQ_DA 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_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +# 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_VIRTIO_BLK=y +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_SENSORS_LIS3LV02D is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM 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_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_BMP085 is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_EARLY_DMA_ALLOC is not set +# CONFIG_RETIMER_CLASS is not set +# CONFIG_DS100DF410 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_CLASS=y +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# 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_EEPROM_SFF_8436 is not set +# CONFIG_CB710_CORE is not set +# CONFIG_IWMC3200TOP 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 +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_TGT is not set +# CONFIG_SCSI_NETLINK 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_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# 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_LOWLEVEL_PCMCIA=y +# CONFIG_PCMCIA_AHA152X is not set +# CONFIG_PCMCIA_FDOMAIN is not set +# CONFIG_PCMCIA_NINJA_SCSI is not set +# CONFIG_PCMCIA_QLOGIC is not set +# CONFIG_PCMCIA_SYM53C500 is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +# CONFIG_SATA_PMP is not set + +# +# Controllers with non-SFF native interface +# +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_AHCI_PLATFORM 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=y + +# +# SFF controllers with custom DMA interface +# +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_ATA_BMDMA is not set + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +CONFIG_PATA_PCMCIA=y +CONFIG_PATA_PLATFORM=y +CONFIG_PATA_OF_PLATFORM=y +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_PATA_LEGACY is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y +CONFIG_MD_LINEAR=y +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=y +CONFIG_MD_RAID456=y +# CONFIG_MULTICORE_RAID456 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_DEBUG is not set +CONFIG_DM_CRYPT=y +CONFIG_DM_SNAPSHOT=y +# CONFIG_DM_THIN_PROVISIONING is not set +CONFIG_DM_MIRROR=y +CONFIG_DM_RAID=y +# CONFIG_DM_LOG_USERSPACE is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set +CONFIG_DM_UEVENT=y +# CONFIG_DM_FLAKEY 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=y +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +CONFIG_MII=y +# CONFIG_MACVLAN is not set +# CONFIG_VXLAN is not set +CONFIG_NETCONSOLE=y +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_VIRTIO_NET=y +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_ATHEROS 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_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_FUJITSU=y +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_NET_VENDOR_HP is not set +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +CONFIG_NET_VENDOR_I825XX=y +# 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_REALTEK is not set +# CONFIG_NET_VENDOR_RDC 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=y +# CONFIG_SMC91X is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SMC911X is not set +CONFIG_SMSC911X=y +# CONFIG_SMSC911X_ARCH_HOOKS is not set +# CONFIG_SMSC9420 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_XIRCOM is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# 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=y +CONFIG_BROADCOM_PHY=y +# 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_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_TR is not set + +# +# USB Network Adapters +# +# 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_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_DPAA_ETH_USE_NDO_SELECT_QUEUE is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE 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 + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=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=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_CS=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set +# CONFIG_SERIAL_8250_DW is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 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_OF_PLATFORM is not set +# CONFIG_SERIAL_TIMBERDALE 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_XILINX_PS_UART is not set +# CONFIG_TTY_PRINTK is not set +CONFIG_HVC_DRIVER=y +# CONFIG_HVC_DCC is not set +CONFIG_VIRTIO_CONSOLE=y +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_VIRTIO=y +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_IPWIRELESS is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_RAMOOPS is not set +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_GPIO=y +CONFIG_I2C_MUX_PCA9541=y +CONFIG_I2C_MUX_PCA954x=y +# CONFIG_I2C_MUX_DNI_6448 is not set +# CONFIG_I2C_MUX_QUANTA 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_GPIO is not set +# CONFIG_I2C_INTEL_MID is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set +# CONFIG_I2C_EG20T is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT 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_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_TOPCLIFF_PCH is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_IT8761E is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_VX855 is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X_IRQ is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_RDC321X is not set + +# +# 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: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +CONFIG_HWMON_VID=y +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +CONFIG_SENSORS_ADM1021=y +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_CY8CXX is not set +# CONFIG_SENSORS_CY8C3245R1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +CONFIG_SENSORS_LM75=y +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +CONFIG_SENSORS_LM85=y +# CONFIG_SENSORS_LM87 is not set +CONFIG_SENSORS_LM90=y +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4151 is not set +CONFIG_SENSORS_LTC4215=y +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +CONFIG_SENSORS_MAX6650=y +CONFIG_SENSORS_MAX6620=y +CONFIG_SENSORS_MAX6697=y +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +CONFIG_SENSORS_EMC2305=y +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +CONFIG_SENSORS_W83781D=y +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +# 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_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X 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_TWL4030_CORE is not set +# CONFIG_MFD_STMPE 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_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 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_PCF50633 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_TIMBERDALE is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_AAT2870_CORE 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_DRM is not set +# CONFIG_STUB_POULSBO is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set +# CONFIG_HID_PID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set + +# +# Special HID drivers +# +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB_ARCH_HAS_XHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB 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=y +CONFIG_USB_EHCI_TT_NEWSCHED=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_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_WHCI_HCD is not set +# CONFIG_USB_HWA_HCD 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_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +CONFIG_USB_SERIAL_CONSOLE=y +# CONFIG_USB_EZUSB is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MOTOROLA is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIEMENS_MPI is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set +# CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_DEBUG 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_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# 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_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_SDRICOH_CS is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC 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_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=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=y +CONFIG_RTC_DRV_DS1374=y +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 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_PCF8563=y +# CONFIG_RTC_DRV_PCF8583 is not set +CONFIG_RTC_DRV_M41T80=y +# CONFIG_RTC_DRV_M41T80_WDT 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_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 + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 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_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +CONFIG_VIRTIO=y +CONFIG_VIRTIO_RING=y + +# +# Virtio drivers +# +# CONFIG_VIRTIO_PCI is not set +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_MMIO=y +# CONFIG_STAGING is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_MACH_CLKDEV=y + +# +# Hardware Spinlock drivers +# +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_VIRT_DRIVERS is not set + +# +# Microsoft Hyper-V guest support +# +# CONFIG_PM_DEVFREQ is not set + +# +# Frame Manager support +# +# CONFIG_FSL_FMAN is not set + +# +# Broadcom iProc Drivers +# +# CONFIG_IPROC_CCB_TIMER is not set +CONFIG_IPROC_MDIO=y +# CONFIG_IPROC_DMA is not set +CONFIG_IPROC_GPIO=y +CONFIG_IPROC_QSPI=y +CONFIG_IPROC_QSPI_SINGLE_MODE=y +# CONFIG_IPROC_QSPI_DUAL_MODE is not set +# CONFIG_IPROC_QSPI_QUAD_MODE is not set +CONFIG_IPROC_QSPI_MAX_HZ=62500000 +# CONFIG_IPROC_MTD_NAND is not set +# CONFIG_IPROC_PWM is not set +CONFIG_IPROC_USB2H=y +CONFIG_USB_EHCI_BCM=y +CONFIG_IPROC_GMAC=y + +# +# Broadcom HND network devices +# +CONFIG_HND=y +CONFIG_ET=y +CONFIG_ET_47XX=y +# CONFIG_ET_NAPI2_POLL is not set +# CONFIG_BCM_CTF is not set +# CONFIG_BCM_CTF2 is not set +# CONFIG_BCM_IPROC_GMAC_ACP is not set +# CONFIG_BCM_IPROC_GMAC_PREFETCH is not set +# CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING is not set +# CONFIG_BCM_IPROC_GMAC_LOCK_OPT is not set +# CONFIG_BCM_IPROC_GMAC_RWREG_OPT is not set +# CONFIG_BCM_IPROC_GMAC_SG is not set +# CONFIG_WL_EMULATOR is not set +# CONFIG_BCM57XX is not set +# CONFIG_WL is not set +# CONFIG_WL_USBAP is not set +CONFIG_WL_AP="" +CONFIG_WL_AP_SDSTD="" +CONFIG_WL_STA="" +CONFIG_WL_APSTA="" +CONFIG_WL_AP_ONCHIP_G="" +CONFIG_WL_STA_ONCHIP_G="" +CONFIG_WL_HIGH="" +CONFIG_IPROC_SDK_MGT_PORT_HANDOFF=y +# CONFIG_IPROC_2STAGE_RX is not set +CONFIG_IPROC_I2C=y +# CONFIG_IPROC_PMU is not set +# CONFIG_BCM_IPROC_CA9_PREFETCH is not set +# CONFIG_BCM_BARRIER_PERFORMANCE is not set +# CONFIG_BCM_MEM_OPTIMIZATION is not set +# CONFIG_BROADCOM_CUSTOM_SENDFILE is not set +# CONFIG_BCM_CUSTOM_RECVFILE is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_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_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set +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_OVERLAYFS_FS=y + +# +# 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_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# 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_XATTR=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_XATTR=y +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_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_AUFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# 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_NFS_USE_NEW_IDMAPPER is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# 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 + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_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_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=y +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_UTF8=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_MASK=0x1 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +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_PANIC_TIMEOUT=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER 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_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_LKDTM is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_DEBUG_PAGEALLOC 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_C_RECORDMCOUNT=y +CONFIG_RING_BUFFER=y +CONFIG_RING_BUFFER_ALLOW_SWAP=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ASYNC_RAID6_TEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX 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_OC_ETM is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_KEYS_DEBUG_PROC_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_XOR_BLOCKS=y +CONFIG_ASYNC_CORE=y +CONFIG_ASYNC_MEMCPY=y +CONFIG_ASYNC_XOR=y +CONFIG_ASYNC_PQ=y +CONFIG_ASYNC_RAID6_RECOV=y +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_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_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# 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=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=y +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH 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=y +# 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_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 + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG 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_RAID6_PQ=y +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 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 is not set +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set diff --git a/packages/base/any/kernels/3.2.71-1+deb7/kconfig.mk b/packages/base/any/kernels/3.2.71-1+deb7/kconfig.mk new file mode 100644 index 00000000..ded46b73 --- /dev/null +++ b/packages/base/any/kernels/3.2.71-1+deb7/kconfig.mk @@ -0,0 +1,27 @@ +############################################################ +# +# +# Copyright 2015 Big Switch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html +# +# 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. +# +# +############################################################ + +THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) +K_MAJOR_VERSION := 3 +K_PATCH_LEVEL := 2 +K_SUB_LEVEL := 71 +K_SUFFIX := +K_PATCH_DIR := $(THIS_DIR)/patches diff --git a/packages/base/any/kernels/3.2.71-1+deb7/patches/kernel-3.2.71.patch b/packages/base/any/kernels/3.2.71-1+deb7/patches/kernel-3.2.71.patch new file mode 100644 index 00000000..1be91f23 --- /dev/null +++ b/packages/base/any/kernels/3.2.71-1+deb7/patches/kernel-3.2.71.patch @@ -0,0 +1,880075 @@ +diff --git a/.gitignore b/.gitignore +index 57af07c..7c40244 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -40,17 +40,13 @@ modules.builtin + /TAGS + /linux + /vmlinux ++/vmlinux.strip + /vmlinuz + /System.map + /Module.markers + /Module.symvers + + # +-# Debian directory (make deb-pkg) +-# +-/debian/ +- +-# + # git files that we don't want to ignore even it they are dot-files + # + !.gitignore +diff --git a/Documentation/ABI/testing/debugfs-aufs b/Documentation/ABI/testing/debugfs-aufs +new file mode 100644 +index 0000000..a58f0d0 +--- /dev/null ++++ b/Documentation/ABI/testing/debugfs-aufs +@@ -0,0 +1,50 @@ ++What: /debug/aufs/si_/ ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ Under /debug/aufs, a directory named si_ is created ++ per aufs mount, where is a unique id generated ++ internally. ++ ++What: /debug/aufs/si_/plink ++Date: Apr 2013 ++Contact: J. R. Okajima ++Description: ++ It has three lines and shows the information about the ++ pseudo-link. The first line is a single number ++ representing a number of buckets. The second line is a ++ number of pseudo-links per buckets (separated by a ++ blank). The last line is a single number representing a ++ total number of psedo-links. ++ When the aufs mount option 'noplink' is specified, it ++ will show "1\n0\n0\n". ++ ++What: /debug/aufs/si_/xib ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the consumed blocks by xib (External Inode Number ++ Bitmap), its block size and file size. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see the aufs manual. ++ ++What: /debug/aufs/si_/xino0, xino1 ... xinoN ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the consumed blocks by xino (External Inode Number ++ Translation Table), its link count, block size and file ++ size. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see the aufs manual. ++ ++What: /debug/aufs/si_/xigen ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the consumed blocks by xigen (External Inode ++ Generation Table), its block size and file size. ++ If CONFIG_AUFS_EXPORT is disabled, this entry will not ++ be created. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see the aufs manual. +diff --git a/Documentation/ABI/testing/sysfs-aufs b/Documentation/ABI/testing/sysfs-aufs +new file mode 100644 +index 0000000..7af6dc0 +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-aufs +@@ -0,0 +1,24 @@ ++What: /sys/fs/aufs/si_/ ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ Under /sys/fs/aufs, a directory named si_ is created ++ per aufs mount, where is a unique id generated ++ internally. ++ ++What: /sys/fs/aufs/si_/br0, br1 ... brN ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the abolute path of a member directory (which ++ is called branch) in aufs, and its permission. ++ ++What: /sys/fs/aufs/si_/xi_path ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the abolute path of XINO (External Inode Number ++ Bitmap, Translation Table and Generation Table) file ++ even if it is the default path. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see the aufs manual. +diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci +index 349ecf2..6572c41 100644 +--- a/Documentation/ABI/testing/sysfs-bus-pci ++++ b/Documentation/ABI/testing/sysfs-bus-pci +@@ -66,6 +66,21 @@ Description: + re-discover previously removed devices. + Depends on CONFIG_HOTPLUG. + ++What: /sys/bus/pci/devices/.../msi_irqs/ ++Date: September, 2011 ++Contact: Neil Horman ++Description: ++ The /sys/devices/.../msi_irqs directory contains a variable set ++ of files, with each file being named after a corresponding msi ++ irq vector allocated to that device. ++ ++What: /sys/bus/pci/devices/.../msi_irqs/ ++Date: September 2011 ++Contact: Neil Horman ++Description: ++ This attribute indicates the mode that the irq vector named by ++ the file is in (msi vs. msix) ++ + What: /sys/bus/pci/devices/.../remove + Date: January 2009 + Contact: Linux PCI developers +diff --git a/Documentation/ABI/testing/sysfs-driver-wacom b/Documentation/ABI/testing/sysfs-driver-wacom +index 82d4df1..5e9cbdc 100644 +--- a/Documentation/ABI/testing/sysfs-driver-wacom ++++ b/Documentation/ABI/testing/sysfs-driver-wacom +@@ -15,9 +15,10 @@ Contact: linux-input@vger.kernel.org + Description: + Attribute group for control of the status LEDs and the OLEDs. + This attribute group is only available for Intuos 4 M, L, +- and XL (with LEDs and OLEDs) and Cintiq 21UX2 (LEDs only). +- Therefore its presence implicitly signifies the presence of +- said LEDs and OLEDs on the tablet device. ++ and XL (with LEDs and OLEDs), Intuos 5 (LEDs only), and Cintiq ++ 21UX2 and Cintiq 24HD (LEDs only). Therefore its presence ++ implicitly signifies the presence of said LEDs and OLEDs on the ++ tablet device. + + What: /sys/bus/usb/devices/-:./wacom_led/status0_luminance + Date: August 2011 +@@ -40,17 +41,18 @@ What: /sys/bus/usb/devices/-:./wacom_led/status_led0 + Date: August 2011 + Contact: linux-input@vger.kernel.org + Description: +- Writing to this file sets which one of the four (for Intuos 4) +- or of the right four (for Cintiq 21UX2) status LEDs is active (0..3). +- The other three LEDs on the same side are always inactive. ++ Writing to this file sets which one of the four (for Intuos 4 ++ and Intuos 5) or of the right four (for Cintiq 21UX2 and Cintiq ++ 24HD) status LEDs is active (0..3). The other three LEDs on the ++ same side are always inactive. + + What: /sys/bus/usb/devices/-:./wacom_led/status_led1_select + Date: September 2011 + Contact: linux-input@vger.kernel.org + Description: +- Writing to this file sets which one of the left four (for Cintiq 21UX2) +- status LEDs is active (0..3). The other three LEDs on the left are always +- inactive. ++ Writing to this file sets which one of the left four (for Cintiq 21UX2 ++ and Cintiq 24HD) status LEDs is active (0..3). The other three LEDs on ++ the left are always inactive. + + What: /sys/bus/usb/devices/-:./wacom_led/buttons_luminance + Date: August 2011 +diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt +index a0b6250..41753a4 100644 +--- a/Documentation/DMA-API-HOWTO.txt ++++ b/Documentation/DMA-API-HOWTO.txt +@@ -101,14 +101,23 @@ style to do this even if your device holds the default setting, + because this shows that you did think about these issues wrt. your + device. + +-The query is performed via a call to dma_set_mask(): ++The query is performed via a call to dma_set_mask_and_coherent(): + +- int dma_set_mask(struct device *dev, u64 mask); ++ int dma_set_mask_and_coherent(struct device *dev, u64 mask); + +-The query for consistent allocations is performed via a call to +-dma_set_coherent_mask(): ++which will query the mask for both streaming and coherent APIs together. ++If you have some special requirements, then the following two separate ++queries can be used instead: + +- int dma_set_coherent_mask(struct device *dev, u64 mask); ++ The query for streaming mappings is performed via a call to ++ dma_set_mask(): ++ ++ int dma_set_mask(struct device *dev, u64 mask); ++ ++ The query for consistent allocations is performed via a call ++ to dma_set_coherent_mask(): ++ ++ int dma_set_coherent_mask(struct device *dev, u64 mask); + + Here, dev is a pointer to the device struct of your device, and mask + is a bit mask describing which bits of an address your device +@@ -137,7 +146,7 @@ exactly why. + + The standard 32-bit addressing device would do something like this: + +- if (dma_set_mask(dev, DMA_BIT_MASK(32))) { ++ if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { + printk(KERN_WARNING + "mydev: No suitable DMA available.\n"); + goto ignore_this_device; +@@ -171,22 +180,20 @@ the case would look like this: + + int using_dac, consistent_using_dac; + +- if (!dma_set_mask(dev, DMA_BIT_MASK(64))) { ++ if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) { + using_dac = 1; + consistent_using_dac = 1; +- dma_set_coherent_mask(dev, DMA_BIT_MASK(64)); +- } else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) { ++ } else if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { + using_dac = 0; + consistent_using_dac = 0; +- dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); + } else { + printk(KERN_WARNING + "mydev: No suitable DMA available.\n"); + goto ignore_this_device; + } + +-dma_set_coherent_mask() will always be able to set the same or a +-smaller mask as dma_set_mask(). However for the rare case that a ++The coherent coherent mask will always be able to set the same or a ++smaller mask as the streaming mask. However for the rare case that a + device driver only uses consistent allocations, one would have to + check the return value from dma_set_coherent_mask(). + +@@ -199,9 +206,9 @@ address you might do something like: + goto ignore_this_device; + } + +-When dma_set_mask() is successful, and returns zero, the kernel saves +-away this mask you have provided. The kernel will use this +-information later when you make DMA mappings. ++When dma_set_mask() or dma_set_mask_and_coherent() is successful, and ++returns zero, the kernel saves away this mask you have provided. The ++kernel will use this information later when you make DMA mappings. + + There is a case which we are aware of at this time, which is worth + mentioning in this documentation. If your device supports multiple +diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt +index 66bd97a..322bda4 100644 +--- a/Documentation/DMA-API.txt ++++ b/Documentation/DMA-API.txt +@@ -142,6 +142,14 @@ internal API for use by the platform than an external API for use by + driver writers. + + int ++dma_set_mask_and_coherent(struct device *dev, u64 mask) ++ ++Checks to see if the mask is possible and updates the device ++streaming and coherent DMA mask parameters if it is. ++ ++Returns: 0 if successful and a negative error if not. ++ ++int + dma_set_mask(struct device *dev, u64 mask) + + Checks to see if the mask is possible and updates the device +diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile +index 66725a3..79084fa 100644 +--- a/Documentation/DocBook/Makefile ++++ b/Documentation/DocBook/Makefile +@@ -159,7 +159,7 @@ quiet_cmd_db2html = HTML $@ + cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi + + quiet_cmd_db2man = MAN $@ +- cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; gzip -f $(obj)/man/*.9; fi ++ cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; fi + %.9 : %.xml + @(which xmlto > /dev/null 2>&1) || \ + (echo "*** You need to install xmlto ***"; \ +diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt +index fd129f6..ac12481 100644 +--- a/Documentation/cgroups/memory.txt ++++ b/Documentation/cgroups/memory.txt +@@ -47,6 +47,10 @@ Features: + Kernel memory and Hugepages are not under control yet. We just manage + pages on LRU. To add more controls, we have to take care of performance. + ++NOTE: In Debian kernel packages, the memory resource controller is ++included but disabled by default. Use the kernel parameter ++'cgroup_enable=memory' to enable it. ++ + Brief summary of control files. + + tasks # attach a task(thread) and show list of threads +diff --git a/Documentation/devicetree/bindings/hwmon/emc2305.txt b/Documentation/devicetree/bindings/hwmon/emc2305.txt +new file mode 100644 +index 0000000..ee67372 +--- /dev/null ++++ b/Documentation/devicetree/bindings/hwmon/emc2305.txt +@@ -0,0 +1,60 @@ ++EMC2305 (I2C) ++ ++This device is a RPM-based PWM Fan Speed Controller for up to 5 fans. ++ ++Each fan can beconfigured individually: ++ ++ - pwm-enable defines the PWM mode: ++ 0: PWM is disabled ++ 3: RPM based PWM ++ ++ - fan-div sets the fan divisor (for RPM mesaurement) ++ 1, 2 ,4 or 8 ++ ++ - fan-target sets the target RPM speed (for RPM based PWM mode) ++ max 16000 (according to data sheet) ++ ++ ++1) The /emc2305 node ++ ++ Required properties: ++ ++ - compatible : must be "smsc,emc2305" ++ - reg : I2C bus address of the device ++ - #address-cells : must be <1> ++ - #size-cells : must be <0> ++ ++ The node may contain child nodes for each fan that the platform uses. ++ If no child nodes are given, all possible fan control channels are exposed. ++ If at least one child node is given, only the configured fans are exposed. ++ ++ Example EMC2305 node: ++ ++ emc2305@2C { ++ compatible = "smsc,emc2305"; ++ reg = <0x2C>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ [ child node definitions... ] ++ } ++ ++2) fan nodes ++ ++ Required properties: ++ ++ - reg : the fan number (0 based) ++ ++ Optional properties: ++ ++ - fan-div : the fan divisor setting ++ - fan-target : the fan target speed ++ - pwm-enable : PWM mode ++ ++ Example EMC2305 fan node: ++ ++ fan@1 { ++ reg = <1>; ++ fan-div = <4>; ++ pwm-enable = <0>; ++ }; +diff --git a/Documentation/devicetree/bindings/i2c/max6697.txt b/Documentation/devicetree/bindings/i2c/max6697.txt +new file mode 100644 +index 0000000..5f79399 +--- /dev/null ++++ b/Documentation/devicetree/bindings/i2c/max6697.txt +@@ -0,0 +1,64 @@ ++max6697 properties ++ ++Required properties: ++- compatible: ++ Should be one of ++ maxim,max6581 ++ maxim,max6602 ++ maxim,max6622 ++ maxim,max6636 ++ maxim,max6689 ++ maxim,max6693 ++ maxim,max6694 ++ maxim,max6697 ++ maxim,max6698 ++ maxim,max6699 ++- reg: I2C address ++ ++Optional properties: ++ ++- smbus-timeout-disable ++ Set to disable SMBus timeout. If not specified, SMBus timeout will be ++ enabled. ++- extended-range-enable ++ Only valid for MAX6581. Set to enable extended temperature range. ++ Extended temperature will be disabled if not specified. ++- beta-compensation-enable ++ Only valid for MAX6693 and MX6694. Set to enable beta compensation on ++ remote temperature channel 1. ++ Beta compensation will be disabled if not specified. ++- alert-mask ++ Alert bit mask. Alert disabled for bits set. ++ Select bit 0 for local temperature, bit 1..7 for remote temperatures. ++ If not specified, alert will be enabled for all channels. ++- over-temperature-mask ++ Over-temperature bit mask. Over-temperature reporting disabled for ++ bits set. ++ Select bit 0 for local temperature, bit 1..7 for remote temperatures. ++ If not specified, over-temperature reporting will be enabled for all ++ channels. ++- resistance-cancellation ++ Boolean for all chips other than MAX6581. Set to enable resistance ++ cancellation on remote temperature channel 1. ++ For MAX6581, resistance cancellation enabled for all channels if ++ specified as boolean, otherwise as per bit mask specified. ++ Only supported for remote temperatures (bit 1..7). ++ If not specified, resistance cancellation will be disabled for all ++ channels. ++- transistor-ideality ++ For MAX6581 only. Two values; first is bit mask, second is ideality ++ select value as per MAX6581 data sheet. Select bit 1..7 for remote ++ channels. ++ Transistor ideality will be initialized to default (1.008) if not ++ specified. ++ ++Example: ++ ++temp-sensor@1a { ++ compatible = "maxim,max6697"; ++ reg = <0x1a>; ++ smbus-timeout-disable; ++ resistance-cancellation; ++ alert-mask = <0x72>; ++ over-temperature-mask = <0x7f>; ++}; +diff --git a/Documentation/devicetree/bindings/i2c/mux.txt b/Documentation/devicetree/bindings/i2c/mux.txt +new file mode 100644 +index 0000000..fc9b542 +--- /dev/null ++++ b/Documentation/devicetree/bindings/i2c/mux.txt +@@ -0,0 +1,62 @@ ++Common i2c bus multiplexer/switch properties. ++ ++An i2c bus multiplexer/switch will have several child busses that are ++numbered uniquely in a device dependent manner. The nodes for an i2c bus ++multiplexer/switch will have one child node for each child ++bus. ++ ++Required properties: ++- #address-cells = <1>; ++- #size-cells = <0>; ++ ++Required properties for child nodes: ++- #address-cells = <1>; ++- #size-cells = <0>; ++- reg : The sub-bus number. ++ ++Optional properties for child nodes: ++- Other properties specific to the multiplexer/switch hardware. ++- Child nodes conforming to i2c bus binding ++- deselect-on-exit -- if set deselect the mux after each transaction, ++ supported by the pca954x.c driver. ++ ++Example : ++ ++ /* ++ An NXP pca9548 8 channel I2C multiplexer at address 0x70 ++ with two NXP pca8574 GPIO expanders attached, one each to ++ ports 3 and 4. ++ */ ++ ++ mux@70 { ++ compatible = "nxp,pca9548"; ++ reg = <0x70>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ ++ gpio1: gpio@38 { ++ compatible = "nxp,pca8574"; ++ reg = <0x38>; ++ #gpio-cells = <2>; ++ gpio-controller; ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ ++ gpio2: gpio@38 { ++ compatible = "nxp,pca8574"; ++ reg = <0x38>; ++ #gpio-cells = <2>; ++ gpio-controller; ++ }; ++ }; ++ }; +diff --git a/Documentation/filesystems/aufs/README b/Documentation/filesystems/aufs/README +new file mode 100644 +index 0000000..c9f8097 +--- /dev/null ++++ b/Documentation/filesystems/aufs/README +@@ -0,0 +1,333 @@ ++ ++Aufs3 -- advanced multi layered unification filesystem version 3.x ++http://aufs.sf.net ++Junjiro R. Okajima ++ ++ ++0. Introduction ++---------------------------------------- ++In the early days, aufs was entirely re-designed and re-implemented ++Unionfs Version 1.x series. After many original ideas, approaches, ++improvements and implementations, it becomes totally different from ++Unionfs while keeping the basic features. ++Recently, Unionfs Version 2.x series begin taking some of the same ++approaches to aufs1's. ++Unionfs is being developed by Professor Erez Zadok at Stony Brook ++University and his team. ++ ++Aufs3 supports linux-3.0 and later. ++If you want older kernel version support, try aufs2-2.6.git or ++aufs2-standalone.git repository, aufs1 from CVS on SourceForge. ++ ++Note: it becomes clear that "Aufs was rejected. Let's give it up." ++According to Christoph Hellwig, linux rejects all union-type filesystems ++but UnionMount. ++ ++ ++ ++1. Features ++---------------------------------------- ++- unite several directories into a single virtual filesystem. The member ++ directory is called as a branch. ++- you can specify the permission flags to the branch, which are 'readonly', ++ 'readwrite' and 'whiteout-able.' ++- by upper writable branch, internal copyup and whiteout, files/dirs on ++ readonly branch are modifiable logically. ++- dynamic branch manipulation, add, del. ++- etc... ++ ++Also there are many enhancements in aufs1, such as: ++- readdir(3) in userspace. ++- keep inode number by external inode number table ++- keep the timestamps of file/dir in internal copyup operation ++- seekable directory, supporting NFS readdir. ++- whiteout is hardlinked in order to reduce the consumption of inodes ++ on branch ++- do not copyup, nor create a whiteout when it is unnecessary ++- revert a single systemcall when an error occurs in aufs ++- remount interface instead of ioctl ++- maintain /etc/mtab by an external command, /sbin/mount.aufs. ++- loopback mounted filesystem as a branch ++- kernel thread for removing the dir who has a plenty of whiteouts ++- support copyup sparse file (a file which has a 'hole' in it) ++- default permission flags for branches ++- selectable permission flags for ro branch, whether whiteout can ++ exist or not ++- export via NFS. ++- support /fs/aufs and /aufs. ++- support multiple writable branches, some policies to select one ++ among multiple writable branches. ++- a new semantics for link(2) and rename(2) to support multiple ++ writable branches. ++- no glibc changes are required. ++- pseudo hardlink (hardlink over branches) ++- allow a direct access manually to a file on branch, e.g. bypassing aufs. ++ including NFS or remote filesystem branch. ++- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX. ++- and more... ++ ++Currently these features are dropped temporary from aufs3. ++See design/08plan.txt in detail. ++- test only the highest one for the directory permission (dirperm1) ++- copyup on open (coo=) ++- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs ++ (robr) ++- statistics of aufs thread (/sys/fs/aufs/stat) ++- delegation mode (dlgt) ++ a delegation of the internal branch access to support task I/O ++ accounting, which also supports Linux Security Modules (LSM) mainly ++ for Suse AppArmor. ++- intent.open/create (file open in a single lookup) ++ ++Features or just an idea in the future (see also design/*.txt), ++- reorder the branch index without del/re-add. ++- permanent xino files for NFSD ++- an option for refreshing the opened files after add/del branches ++- 'move' policy for copy-up between two writable branches, after ++ checking free space. ++- light version, without branch manipulation. (unnecessary?) ++- copyup in userspace ++- inotify in userspace ++- readv/writev ++- xattr, acl ++ ++ ++2. Download ++---------------------------------------- ++There were three GIT trees for aufs3, aufs3-linux.git, ++aufs3-standalone.git, and aufs-util.git. Note that there is no "3" in ++"aufs-util.git." ++While the aufs-util is always necessary, you need either of aufs3-linux ++or aufs3-standalone. ++ ++The aufs3-linux tree includes the whole linux mainline GIT tree, ++git://git.kernel.org/.../torvalds/linux.git. ++And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot ++build aufs3 as an external kernel module. ++ ++On the other hand, the aufs3-standalone tree has only aufs source files ++and necessary patches, and you can select CONFIG_AUFS_FS=m. ++ ++You will find GIT branches whose name is in form of "aufs3.x" where "x" ++represents the linux kernel version, "linux-3.x". For instance, ++"aufs3.0" is for linux-3.0. For latest "linux-3.x-rcN", use ++"aufs3.x-rcN" branch. ++ ++o aufs3-linux tree ++$ git clone --reference /your/linux/git/tree \ ++ git://git.code.sf.net/p/aufs/aufs3-linux aufs-aufs3-linux \ ++ aufs3-linux.git ++- if you don't have linux GIT tree, then remove "--reference ..." ++$ cd aufs3-linux.git ++$ git checkout origin/aufs3.0 ++ ++o aufs3-standalone tree ++$ git clone git://git.code.sf.net/p/aufs/aufs3-standalone \ ++ aufs3-standalone.git ++$ cd aufs3-standalone.git ++$ git checkout origin/aufs3.0 ++ ++o aufs-util tree ++$ git clone git://git.code.sf.net/p/aufs/aufs-util \ ++ aufs-util.git ++$ cd aufs-util.git ++$ git checkout origin/aufs3.0 ++ ++Note: The 3.x-rcN branch is to be used with `rc' kernel versions ONLY. ++The minor version number, 'x' in '3.x', of aufs may not always ++follow the minor version number of the kernel. ++Because changes in the kernel that cause the use of a new ++minor version number do not always require changes to aufs-util. ++ ++Since aufs-util has its own minor version number, you may not be ++able to find a GIT branch in aufs-util for your kernel's ++exact minor version number. ++In this case, you should git-checkout the branch for the ++nearest lower number. ++ ++For (an unreleased) example: ++If you are using "linux-3.10" and the "aufs3.10" branch ++does not exist in aufs-util repository, then "aufs3.9", "aufs3.8" ++or something numerically smaller is the branch for your kernel. ++ ++Also you can view all branches by ++ $ git branch -a ++ ++ ++3. Configuration and Compilation ++---------------------------------------- ++Make sure you have git-checkout'ed the correct branch. ++ ++For aufs3-linux tree, ++- enable CONFIG_EXPERIMENTAL and CONFIG_AUFS_FS. ++- set other aufs configurations if necessary. ++ ++For aufs3-standalone tree, ++There are several ways to build. ++ ++1. ++- apply ./aufs3-kbuild.patch to your kernel source files. ++- apply ./aufs3-base.patch too. ++- apply ./aufs3-proc_map.patch too, if you want to make /proc/PID/maps (and ++ others including lsof(1)) show the file path on aufs instead of the ++ path on the branch fs. ++- apply ./aufs3-standalone.patch too, if you have a plan to set ++ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs3-standalone.patch. ++- copy ./{Documentation,fs,include/linux/aufs_type.h} files to your ++ kernel source tree. Never copy $PWD/include/linux/Kbuild. ++- enable CONFIG_EXPERIMENTAL and CONFIG_AUFS_FS, you can select either ++ =m or =y. ++- and build your kernel as usual. ++- install the built kernel. ++- install the header files too by "make headers_install" to the ++ directory where you specify. By default, it is $PWD/usr. ++ "make help" shows a brief note for headers_install. ++- and reboot your system. ++ ++2. ++- module only (CONFIG_AUFS_FS=m). ++- apply ./aufs3-base.patch to your kernel source files. ++- apply ./aufs3-proc_map.patch too to your kernel source files, ++ if you want to make /proc/PID/maps (and others including lsof(1)) show ++ the file path on aufs instead of the path on the branch fs. ++- apply ./aufs3-standalone.patch too. ++- build your kernel, don't forget "make headers_install", and reboot. ++- edit ./config.mk and set other aufs configurations if necessary. ++ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes ++ every aufs configurations. ++- build the module by simple "make". ++- you can specify ${KDIR} make variable which points to your kernel ++ source tree. ++- install the files ++ + run "make install" to install the aufs module, or copy the built ++ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply). ++ + run "make install_headers" (instead of headers_install) to install ++ the modified aufs header file (you can specify DESTDIR which is ++ available in aufs standalone version's Makefile only), or copy ++ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever ++ you like manually. By default, the target directory is $PWD/usr. ++- no need to apply aufs3-kbuild.patch, nor copying source files to your ++ kernel source tree. ++ ++Note: The header file aufs_type.h is necessary to build aufs-util ++ as well as "make headers_install" in the kernel source tree. ++ headers_install is subject to be forgotten, but it is essentially ++ necessary, not only for building aufs-util. ++ You may not meet problems without headers_install in some older ++ version though. ++ ++And then, ++- read README in aufs-util, build and install it ++- note that your distribution may contain an obsoleted version of ++ aufs_type.h in /usr/include/linux or something. When you build aufs ++ utilities, make sure that your compiler refers the correct aufs header ++ file which is built by "make headers_install." ++- if you want to use readdir(3) in userspace or pathconf(3) wrapper, ++ then run "make install_ulib" too. And refer to the aufs manual in ++ detail. ++ ++ ++4. Usage ++---------------------------------------- ++At first, make sure aufs-util are installed, and please read the aufs ++manual, aufs.5 in aufs-util.git tree. ++$ man -l aufs.5 ++ ++And then, ++$ mkdir /tmp/rw /tmp/aufs ++# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs ++ ++Here is another example. The result is equivalent. ++# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs ++ Or ++# mount -t aufs -o br:/tmp/rw none /tmp/aufs ++# mount -o remount,append:${HOME} /tmp/aufs ++ ++Then, you can see whole tree of your home dir through /tmp/aufs. If ++you modify a file under /tmp/aufs, the one on your home directory is ++not affected, instead the same named file will be newly created under ++/tmp/rw. And all of your modification to a file will be applied to ++the one under /tmp/rw. This is called the file based Copy on Write ++(COW) method. ++Aufs mount options are described in aufs.5. ++If you run chroot or something and make your aufs as a root directory, ++then you need to customize the shutdown script. See the aufs manual in ++detail. ++ ++Additionally, there are some sample usages of aufs which are a ++diskless system with network booting, and LiveCD over NFS. ++See sample dir in CVS tree on SourceForge. ++ ++ ++5. Contact ++---------------------------------------- ++When you have any problems or strange behaviour in aufs, please let me ++know with: ++- /proc/mounts (instead of the output of mount(8)) ++- /sys/module/aufs/* ++- /sys/fs/aufs/* (if you have them) ++- /debug/aufs/* (if you have them) ++- linux kernel version ++ if your kernel is not plain, for example modified by distributor, ++ the url where i can download its source is necessary too. ++- aufs version which was printed at loading the module or booting the ++ system, instead of the date you downloaded. ++- configuration (define/undefine CONFIG_AUFS_xxx) ++- kernel configuration or /proc/config.gz (if you have it) ++- behaviour which you think to be incorrect ++- actual operation, reproducible one is better ++- mailto: aufs-users at lists.sourceforge.net ++ ++Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches, ++and Feature Requests) on SourceForge. Please join and write to ++aufs-users ML. ++ ++ ++6. Acknowledgements ++---------------------------------------- ++Thanks to everyone who have tried and are using aufs, whoever ++have reported a bug or any feedback. ++ ++Especially donators: ++Tomas Matejicek(slax.org) made a donation (much more than once). ++ Since Apr 2010, Tomas M (the author of Slax and Linux Live ++ scripts) is making "doubling" donations. ++ Unfortunately I cannot list all of the donators, but I really ++ appreciate. ++ It ends Aug 2010, but the ordinary donation URL is still available. ++ ++Dai Itasaka made a donation (2007/8). ++Chuck Smith made a donation (2008/4, 10 and 12). ++Henk Schoneveld made a donation (2008/9). ++Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10). ++Francois Dupoux made a donation (2008/11). ++Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public ++ aufs2 GIT tree (2009/2). ++William Grant made a donation (2009/3). ++Patrick Lane made a donation (2009/4). ++The Mail Archive (mail-archive.com) made donations (2009/5). ++Nippy Networks (Ed Wildgoose) made a donation (2009/7). ++New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11). ++Pavel Pronskiy made a donation (2011/2). ++Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy ++ Networks (Ed Wildgoose) made a donation for hardware (2011/3). ++Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and ++11). ++Sam Liddicott made a donation (2011/9). ++ ++Thank you very much. ++Donations are always, including future donations, very important and ++helpful for me to keep on developing aufs. ++ ++ ++7. ++---------------------------------------- ++If you are an experienced user, no explanation is needed. Aufs is ++just a linux filesystem. ++ ++ ++Enjoy! ++ ++# Local variables: ; ++# mode: text; ++# End: ; +diff --git a/Documentation/filesystems/aufs/design/01intro.txt b/Documentation/filesystems/aufs/design/01intro.txt +new file mode 100644 +index 0000000..e60f8c6 +--- /dev/null ++++ b/Documentation/filesystems/aufs/design/01intro.txt +@@ -0,0 +1,162 @@ ++ ++# Copyright (C) 2005-2013 Junjiro R. Okajima ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++Introduction ++---------------------------------------- ++ ++aufs [ei ju: ef es] | [a u f s] ++1. abbrev. for "advanced multi-layered unification filesystem". ++2. abbrev. for "another unionfs". ++3. abbrev. for "auf das" in German which means "on the" in English. ++ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E). ++ But "Filesystem aufs Filesystem" is hard to understand. ++ ++AUFS is a filesystem with features: ++- multi layered stackable unification filesystem, the member directory ++ is called as a branch. ++- branch permission and attribute, 'readonly', 'real-readonly', ++ 'readwrite', 'whiteout-able', 'link-able whiteout' and their ++ combination. ++- internal "file copy-on-write". ++- logical deletion, whiteout. ++- dynamic branch manipulation, adding, deleting and changing permission. ++- allow bypassing aufs, user's direct branch access. ++- external inode number translation table and bitmap which maintains the ++ persistent aufs inode number. ++- seekable directory, including NFS readdir. ++- file mapping, mmap and sharing pages. ++- pseudo-link, hardlink over branches. ++- loopback mounted filesystem as a branch. ++- several policies to select one among multiple writable branches. ++- revert a single systemcall when an error occurs in aufs. ++- and more... ++ ++ ++Multi Layered Stackable Unification Filesystem ++---------------------------------------------------------------------- ++Most people already knows what it is. ++It is a filesystem which unifies several directories and provides a ++merged single directory. When users access a file, the access will be ++passed/re-directed/converted (sorry, I am not sure which English word is ++correct) to the real file on the member filesystem. The member ++filesystem is called 'lower filesystem' or 'branch' and has a mode ++'readonly' and 'readwrite.' And the deletion for a file on the lower ++readonly branch is handled by creating 'whiteout' on the upper writable ++branch. ++ ++On LKML, there have been discussions about UnionMount (Jan Blunck, ++Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took ++different approaches to implement the merged-view. ++The former tries putting it into VFS, and the latter implements as a ++separate filesystem. ++(If I misunderstand about these implementations, please let me know and ++I shall correct it. Because it is a long time ago when I read their ++source files last time). ++ ++UnionMount's approach will be able to small, but may be hard to share ++branches between several UnionMount since the whiteout in it is ++implemented in the inode on branch filesystem and always ++shared. According to Bharata's post, readdir does not seems to be ++finished yet. ++There are several missing features known in this implementations such as ++- for users, the inode number may change silently. eg. copy-up. ++- link(2) may break by copy-up. ++- read(2) may get an obsoleted filedata (fstat(2) too). ++- fcntl(F_SETLK) may be broken by copy-up. ++- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after ++ open(O_RDWR). ++ ++Unionfs has a longer history. When I started implementing a stacking filesystem ++(Aug 2005), it already existed. It has virtual super_block, inode, ++dentry and file objects and they have an array pointing lower same kind ++objects. After contributing many patches for Unionfs, I re-started my ++project AUFS (Jun 2006). ++ ++In AUFS, the structure of filesystem resembles to Unionfs, but I ++implemented my own ideas, approaches and enhancements and it became ++totally different one. ++ ++Comparing DM snapshot and fs based implementation ++- the number of bytes to be copied between devices is much smaller. ++- the type of filesystem must be one and only. ++- the fs must be writable, no readonly fs, even for the lower original ++ device. so the compression fs will not be usable. but if we use ++ loopback mount, we may address this issue. ++ for instance, ++ mount /cdrom/squashfs.img /sq ++ losetup /sq/ext2.img ++ losetup /somewhere/cow ++ dmsetup "snapshot /dev/loop0 /dev/loop1 ..." ++- it will be difficult (or needs more operations) to extract the ++ difference between the original device and COW. ++- DM snapshot-merge may help a lot when users try merging. in the ++ fs-layer union, users will use rsync(1). ++ ++ ++Several characters/aspects of aufs ++---------------------------------------------------------------------- ++ ++Aufs has several characters or aspects. ++1. a filesystem, callee of VFS helper ++2. sub-VFS, caller of VFS helper for branches ++3. a virtual filesystem which maintains persistent inode number ++4. reader/writer of files on branches such like an application ++ ++1. Callee of VFS Helper ++As an ordinary linux filesystem, aufs is a callee of VFS. For instance, ++unlink(2) from an application reaches sys_unlink() kernel function and ++then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it ++calls filesystem specific unlink operation. Actually aufs implements the ++unlink operation but it behaves like a redirector. ++ ++2. Caller of VFS Helper for Branches ++aufs_unlink() passes the unlink request to the branch filesystem as if ++it were called from VFS. So the called unlink operation of the branch ++filesystem acts as usual. As a caller of VFS helper, aufs should handle ++every necessary pre/post operation for the branch filesystem. ++- acquire the lock for the parent dir on a branch ++- lookup in a branch ++- revalidate dentry on a branch ++- mnt_want_write() for a branch ++- vfs_unlink() for a branch ++- mnt_drop_write() for a branch ++- release the lock on a branch ++ ++3. Persistent Inode Number ++One of the most important issue for a filesystem is to maintain inode ++numbers. This is particularly important to support exporting a ++filesystem via NFS. Aufs is a virtual filesystem which doesn't have a ++backend block device for its own. But some storage is necessary to ++maintain inode number. It may be a large space and may not suit to keep ++in memory. Aufs rents some space from its first writable branch ++filesystem (by default) and creates file(s) on it. These files are ++created by aufs internally and removed soon (currently) keeping opened. ++Note: Because these files are removed, they are totally gone after ++ unmounting aufs. It means the inode numbers are not persistent ++ across unmount or reboot. I have a plan to make them really ++ persistent which will be important for aufs on NFS server. ++ ++4. Read/Write Files Internally (copy-on-write) ++Because a branch can be readonly, when you write a file on it, aufs will ++"copy-up" it to the upper writable branch internally. And then write the ++originally requested thing to the file. Generally kernel doesn't ++open/read/write file actively. In aufs, even a single write may cause a ++internal "file copy". This behaviour is very similar to cp(1) command. ++ ++Some people may think it is better to pass such work to user space ++helper, instead of doing in kernel space. Actually I am still thinking ++about it. But currently I have implemented it in kernel space. +diff --git a/Documentation/filesystems/aufs/design/02struct.txt b/Documentation/filesystems/aufs/design/02struct.txt +new file mode 100644 +index 0000000..f54d654 +--- /dev/null ++++ b/Documentation/filesystems/aufs/design/02struct.txt +@@ -0,0 +1,226 @@ ++ ++# Copyright (C) 2005-2013 Junjiro R. Okajima ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++Basic Aufs Internal Structure ++ ++Superblock/Inode/Dentry/File Objects ++---------------------------------------------------------------------- ++As like an ordinary filesystem, aufs has its own ++superblock/inode/dentry/file objects. All these objects have a ++dynamically allocated array and store the same kind of pointers to the ++lower filesystem, branch. ++For example, when you build a union with one readwrite branch and one ++readonly, mounted /au, /rw and /ro respectively. ++- /au = /rw + /ro ++- /ro/fileA exists but /rw/fileA ++ ++Aufs lookup operation finds /ro/fileA and gets dentry for that. These ++pointers are stored in a aufs dentry. The array in aufs dentry will be, ++- [0] = NULL ++- [1] = /ro/fileA ++ ++This style of an array is essentially same to the aufs ++superblock/inode/dentry/file objects. ++ ++Because aufs supports manipulating branches, ie. add/delete/change ++dynamically, these objects has its own generation. When branches are ++changed, the generation in aufs superblock is incremented. And a ++generation in other object are compared when it is accessed. ++When a generation in other objects are obsoleted, aufs refreshes the ++internal array. ++ ++ ++Superblock ++---------------------------------------------------------------------- ++Additionally aufs superblock has some data for policies to select one ++among multiple writable branches, XIB files, pseudo-links and kobject. ++See below in detail. ++About the policies which supports copy-down a directory, see policy.txt ++too. ++ ++ ++Branch and XINO(External Inode Number Translation Table) ++---------------------------------------------------------------------- ++Every branch has its own xino (external inode number translation table) ++file. The xino file is created and unlinked by aufs internally. When two ++members of a union exist on the same filesystem, they share the single ++xino file. ++The struct of a xino file is simple, just a sequence of aufs inode ++numbers which is indexed by the lower inode number. ++In the above sample, assume the inode number of /ro/fileA is i111 and ++aufs assigns the inode number i999 for fileA. Then aufs writes 999 as ++4(8) bytes at 111 * 4(8) bytes offset in the xino file. ++ ++When the inode numbers are not contiguous, the xino file will be sparse ++which has a hole in it and doesn't consume as much disk space as it ++might appear. If your branch filesystem consumes disk space for such ++holes, then you should specify 'xino=' option at mounting aufs. ++ ++Also a writable branch has three kinds of "whiteout bases". All these ++are existed when the branch is joined to aufs and the names are ++whiteout-ed doubly, so that users will never see their names in aufs ++hierarchy. ++1. a regular file which will be linked to all whiteouts. ++2. a directory to store a pseudo-link. ++3. a directory to store an "orphan-ed" file temporary. ++ ++1. Whiteout Base ++ When you remove a file on a readonly branch, aufs handles it as a ++ logical deletion and creates a whiteout on the upper writable branch ++ as a hardlink of this file in order not to consume inode on the ++ writable branch. ++2. Pseudo-link Dir ++ See below, Pseudo-link. ++3. Step-Parent Dir ++ When "fileC" exists on the lower readonly branch only and it is ++ opened and removed with its parent dir, and then user writes ++ something into it, then aufs copies-up fileC to this ++ directory. Because there is no other dir to store fileC. After ++ creating a file under this dir, the file is unlinked. ++ ++Because aufs supports manipulating branches, ie. add/delete/change ++dynamically, a branch has its own id. When the branch order changes, aufs ++finds the new index by searching the branch id. ++ ++ ++Pseudo-link ++---------------------------------------------------------------------- ++Assume "fileA" exists on the lower readonly branch only and it is ++hardlinked to "fileB" on the branch. When you write something to fileA, ++aufs copies-up it to the upper writable branch. Additionally aufs ++creates a hardlink under the Pseudo-link Directory of the writable ++branch. The inode of a pseudo-link is kept in aufs super_block as a ++simple list. If fileB is read after unlinking fileA, aufs returns ++filedata from the pseudo-link instead of the lower readonly ++branch. Because the pseudo-link is based upon the inode, to keep the ++inode number by xino (see above) is important. ++ ++All the hardlinks under the Pseudo-link Directory of the writable branch ++should be restored in a proper location later. Aufs provides a utility ++to do this. The userspace helpers executed at remounting and unmounting ++aufs by default. ++During this utility is running, it puts aufs into the pseudo-link ++maintenance mode. In this mode, only the process which began the ++maintenance mode (and its child processes) is allowed to operate in ++aufs. Some other processes which are not related to the pseudo-link will ++be allowed to run too, but the rest have to return an error or wait ++until the maintenance mode ends. If a process already acquires an inode ++mutex (in VFS), it has to return an error. ++ ++ ++XIB(external inode number bitmap) ++---------------------------------------------------------------------- ++Addition to the xino file per a branch, aufs has an external inode number ++bitmap in a superblock object. It is also a file such like a xino file. ++It is a simple bitmap to mark whether the aufs inode number is in-use or ++not. ++To reduce the file I/O, aufs prepares a single memory page to cache xib. ++ ++Aufs implements a feature to truncate/refresh both of xino and xib to ++reduce the number of consumed disk blocks for these files. ++ ++ ++Virtual or Vertical Dir, and Readdir in Userspace ++---------------------------------------------------------------------- ++In order to support multiple layers (branches), aufs readdir operation ++constructs a virtual dir block on memory. For readdir, aufs calls ++vfs_readdir() internally for each dir on branches, merges their entries ++with eliminating the whiteout-ed ones, and sets it to file (dir) ++object. So the file object has its entry list until it is closed. The ++entry list will be updated when the file position is zero and becomes ++old. This decision is made in aufs automatically. ++ ++The dynamically allocated memory block for the name of entries has a ++unit of 512 bytes (by default) and stores the names contiguously (no ++padding). Another block for each entry is handled by kmem_cache too. ++During building dir blocks, aufs creates hash list and judging whether ++the entry is whiteouted by its upper branch or already listed. ++The merged result is cached in the corresponding inode object and ++maintained by a customizable life-time option. ++ ++Some people may call it can be a security hole or invite DoS attack ++since the opened and once readdir-ed dir (file object) holds its entry ++list and becomes a pressure for system memory. But I'd say it is similar ++to files under /proc or /sys. The virtual files in them also holds a ++memory page (generally) while they are opened. When an idea to reduce ++memory for them is introduced, it will be applied to aufs too. ++For those who really hate this situation, I've developed readdir(3) ++library which operates this merging in userspace. You just need to set ++LD_PRELOAD environment variable, and aufs will not consume no memory in ++kernel space for readdir(3). ++ ++ ++Workqueue ++---------------------------------------------------------------------- ++Aufs sometimes requires privilege access to a branch. For instance, ++in copy-up/down operation. When a user process is going to make changes ++to a file which exists in the lower readonly branch only, and the mode ++of one of ancestor directories may not be writable by a user ++process. Here aufs copy-up the file with its ancestors and they may ++require privilege to set its owner/group/mode/etc. ++This is a typical case of a application character of aufs (see ++Introduction). ++ ++Aufs uses workqueue synchronously for this case. It creates its own ++workqueue. The workqueue is a kernel thread and has privilege. Aufs ++passes the request to call mkdir or write (for example), and wait for ++its completion. This approach solves a problem of a signal handler ++simply. ++If aufs didn't adopt the workqueue and changed the privilege of the ++process, and if the mkdir/write call arises SIGXFSZ or other signal, ++then the user process might gain a privilege or the generated core file ++was owned by a superuser. ++ ++Also aufs uses the system global workqueue ("events" kernel thread) too ++for asynchronous tasks, such like handling inotify/fsnotify, re-creating a ++whiteout base and etc. This is unrelated to a privilege. ++Most of aufs operation tries acquiring a rw_semaphore for aufs ++superblock at the beginning, at the same time waits for the completion ++of all queued asynchronous tasks. ++ ++ ++Whiteout ++---------------------------------------------------------------------- ++The whiteout in aufs is very similar to Unionfs's. That is represented ++by its filename. UnionMount takes an approach of a file mode, but I am ++afraid several utilities (find(1) or something) will have to support it. ++ ++Basically the whiteout represents "logical deletion" which stops aufs to ++lookup further, but also it represents "dir is opaque" which also stop ++lookup. ++ ++In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively. ++In order to make several functions in a single systemcall to be ++revertible, aufs adopts an approach to rename a directory to a temporary ++unique whiteouted name. ++For example, in rename(2) dir where the target dir already existed, aufs ++renames the target dir to a temporary unique whiteouted name before the ++actual rename on a branch and then handles other actions (make it opaque, ++update the attributes, etc). If an error happens in these actions, aufs ++simply renames the whiteouted name back and returns an error. If all are ++succeeded, aufs registers a function to remove the whiteouted unique ++temporary name completely and asynchronously to the system global ++workqueue. ++ ++ ++Copy-up ++---------------------------------------------------------------------- ++It is a well-known feature or concept. ++When user modifies a file on a readonly branch, aufs operate "copy-up" ++internally and makes change to the new file on the upper writable branch. ++When the trigger systemcall does not update the timestamps of the parent ++dir, aufs reverts it after copy-up. +diff --git a/Documentation/filesystems/aufs/design/03lookup.txt b/Documentation/filesystems/aufs/design/03lookup.txt +new file mode 100644 +index 0000000..d3ca527 +--- /dev/null ++++ b/Documentation/filesystems/aufs/design/03lookup.txt +@@ -0,0 +1,106 @@ ++ ++# Copyright (C) 2005-2013 Junjiro R. Okajima ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++Lookup in a Branch ++---------------------------------------------------------------------- ++Since aufs has a character of sub-VFS (see Introduction), it operates ++lookup for branches as VFS does. It may be a heavy work. Generally ++speaking struct nameidata is a bigger structure and includes many ++information. But almost all lookup operation in aufs is the simplest ++case, ie. lookup only an entry directly connected to its parent. Digging ++down the directory hierarchy is unnecessary. ++ ++VFS has a function lookup_one_len() for that use, but it is not usable ++for a branch filesystem which requires struct nameidata. So aufs ++implements a simple lookup wrapper function. When a branch filesystem ++allows NULL as nameidata, it calls lookup_one_len(). Otherwise it builds ++a simplest nameidata and calls lookup_hash(). ++Here aufs applies "a principle in NFSD", ie. if the filesystem supports ++NFS-export, then it has to support NULL as a nameidata parameter for ++->create(), ->lookup() and ->d_revalidate(). So the lookup wrapper in ++aufs tests if ->s_export_op in the branch is NULL or not. ++ ++When a branch is a remote filesystem, aufs basically trusts its ++->d_revalidate(), also aufs forces the hardest revalidate tests for ++them. ++For d_revalidate, aufs implements three levels of revalidate tests. See ++"Revalidate Dentry and UDBA" in detail. ++ ++ ++Loopback Mount ++---------------------------------------------------------------------- ++Basically aufs supports any type of filesystem and block device for a ++branch (actually there are some exceptions). But it is prohibited to add ++a loopback mounted one whose backend file exists in a filesystem which is ++already added to aufs. The reason is to protect aufs from a recursive ++lookup. If it was allowed, the aufs lookup operation might re-enter a ++lookup for the loopback mounted branch in the same context, and will ++cause a deadlock. ++ ++ ++Revalidate Dentry and UDBA (User's Direct Branch Access) ++---------------------------------------------------------------------- ++Generally VFS helpers re-validate a dentry as a part of lookup. ++0. digging down the directory hierarchy. ++1. lock the parent dir by its i_mutex. ++2. lookup the final (child) entry. ++3. revalidate it. ++4. call the actual operation (create, unlink, etc.) ++5. unlock the parent dir ++ ++If the filesystem implements its ->d_revalidate() (step 3), then it is ++called. Actually aufs implements it and checks the dentry on a branch is ++still valid. ++But it is not enough. Because aufs has to release the lock for the ++parent dir on a branch at the end of ->lookup() (step 2) and ++->d_revalidate() (step 3) while the i_mutex of the aufs dir is still ++held by VFS. ++If the file on a branch is changed directly, eg. bypassing aufs, after ++aufs released the lock, then the subsequent operation may cause ++something unpleasant result. ++ ++This situation is a result of VFS architecture, ->lookup() and ++->d_revalidate() is separated. But I never say it is wrong. It is a good ++design from VFS's point of view. It is just not suitable for sub-VFS ++character in aufs. ++ ++Aufs supports such case by three level of revalidation which is ++selectable by user. ++1. Simple Revalidate ++ Addition to the native flow in VFS's, confirm the child-parent ++ relationship on the branch just after locking the parent dir on the ++ branch in the "actual operation" (step 4). When this validation ++ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still ++ checks the validation of the dentry on branches. ++2. Monitor Changes Internally by Inotify/Fsnotify ++ Addition to above, in the "actual operation" (step 4) aufs re-lookup ++ the dentry on the branch, and returns EBUSY if it finds different ++ dentry. ++ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches ++ during it is in cache. When the event is notified, aufs registers a ++ function to kernel 'events' thread by schedule_work(). And the ++ function sets some special status to the cached aufs dentry and inode ++ private data. If they are not cached, then aufs has nothing to ++ do. When the same file is accessed through aufs (step 0-3) later, ++ aufs will detect the status and refresh all necessary data. ++ In this mode, aufs has to ignore the event which is fired by aufs ++ itself. ++3. No Extra Validation ++ This is the simplest test and doesn't add any additional revalidation ++ test, and skip therevalidatin in step 4. It is useful and improves ++ aufs performance when system surely hide the aufs branches from user, ++ by over-mounting something (or another method). +diff --git a/Documentation/filesystems/aufs/design/04branch.txt b/Documentation/filesystems/aufs/design/04branch.txt +new file mode 100644 +index 0000000..f85f3a8 +--- /dev/null ++++ b/Documentation/filesystems/aufs/design/04branch.txt +@@ -0,0 +1,76 @@ ++ ++# Copyright (C) 2005-2013 Junjiro R. Okajima ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++Branch Manipulation ++ ++Since aufs supports dynamic branch manipulation, ie. add/remove a branch ++and changing its permission/attribute, there are a lot of works to do. ++ ++ ++Add a Branch ++---------------------------------------------------------------------- ++o Confirm the adding dir exists outside of aufs, including loopback ++ mount. ++- and other various attributes... ++o Initialize the xino file and whiteout bases if necessary. ++ See struct.txt. ++ ++o Check the owner/group/mode of the directory ++ When the owner/group/mode of the adding directory differs from the ++ existing branch, aufs issues a warning because it may impose a ++ security risk. ++ For example, when a upper writable branch has a world writable empty ++ top directory, a malicious user can create any files on the writable ++ branch directly, like copy-up and modify manually. If something like ++ /etc/{passwd,shadow} exists on the lower readonly branch but the upper ++ writable branch, and the writable branch is world-writable, then a ++ malicious guy may create /etc/passwd on the writable branch directly ++ and the infected file will be valid in aufs. ++ I am afraid it can be a security issue, but nothing to do except ++ producing a warning. ++ ++ ++Delete a Branch ++---------------------------------------------------------------------- ++o Confirm the deleting branch is not busy ++ To be general, there is one merit to adopt "remount" interface to ++ manipulate branches. It is to discard caches. At deleting a branch, ++ aufs checks the still cached (and connected) dentries and inodes. If ++ there are any, then they are all in-use. An inode without its ++ corresponding dentry can be alive alone (for example, inotify/fsnotify case). ++ ++ For the cached one, aufs checks whether the same named entry exists on ++ other branches. ++ If the cached one is a directory, because aufs provides a merged view ++ to users, as long as one dir is left on any branch aufs can show the ++ dir to users. In this case, the branch can be removed from aufs. ++ Otherwise aufs rejects deleting the branch. ++ ++ If any file on the deleting branch is opened by aufs, then aufs ++ rejects deleting. ++ ++ ++Modify the Permission of a Branch ++---------------------------------------------------------------------- ++o Re-initialize or remove the xino file and whiteout bases if necessary. ++ See struct.txt. ++ ++o rw --> ro: Confirm the modifying branch is not busy ++ Aufs rejects the request if any of these conditions are true. ++ - a file on the branch is mmap-ed. ++ - a regular file on the branch is opened for write and there is no ++ same named entry on the upper branch. +diff --git a/Documentation/filesystems/aufs/design/05wbr_policy.txt b/Documentation/filesystems/aufs/design/05wbr_policy.txt +new file mode 100644 +index 0000000..2bb8e58 +--- /dev/null ++++ b/Documentation/filesystems/aufs/design/05wbr_policy.txt +@@ -0,0 +1,65 @@ ++ ++# Copyright (C) 2005-2013 Junjiro R. Okajima ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++Policies to Select One among Multiple Writable Branches ++---------------------------------------------------------------------- ++When the number of writable branch is more than one, aufs has to decide ++the target branch for file creation or copy-up. By default, the highest ++writable branch which has the parent (or ancestor) dir of the target ++file is chosen (top-down-parent policy). ++By user's request, aufs implements some other policies to select the ++writable branch, for file creation two policies, round-robin and ++most-free-space policies. For copy-up three policies, top-down-parent, ++bottom-up-parent and bottom-up policies. ++ ++As expected, the round-robin policy selects the branch in circular. When ++you have two writable branches and creates 10 new files, 5 files will be ++created for each branch. mkdir(2) systemcall is an exception. When you ++create 10 new directories, all will be created on the same branch. ++And the most-free-space policy selects the one which has most free ++space among the writable branches. The amount of free space will be ++checked by aufs internally, and users can specify its time interval. ++ ++The policies for copy-up is more simple, ++top-down-parent is equivalent to the same named on in create policy, ++bottom-up-parent selects the writable branch where the parent dir ++exists and the nearest upper one from the copyup-source, ++bottom-up selects the nearest upper writable branch from the ++copyup-source, regardless the existence of the parent dir. ++ ++There are some rules or exceptions to apply these policies. ++- If there is a readonly branch above the policy-selected branch and ++ the parent dir is marked as opaque (a variation of whiteout), or the ++ target (creating) file is whiteout-ed on the upper readonly branch, ++ then the result of the policy is ignored and the target file will be ++ created on the nearest upper writable branch than the readonly branch. ++- If there is a writable branch above the policy-selected branch and ++ the parent dir is marked as opaque or the target file is whiteouted ++ on the branch, then the result of the policy is ignored and the target ++ file will be created on the highest one among the upper writable ++ branches who has diropq or whiteout. In case of whiteout, aufs removes ++ it as usual. ++- link(2) and rename(2) systemcalls are exceptions in every policy. ++ They try selecting the branch where the source exists as possible ++ since copyup a large file will take long time. If it can't be, ++ ie. the branch where the source exists is readonly, then they will ++ follow the copyup policy. ++- There is an exception for rename(2) when the target exists. ++ If the rename target exists, aufs compares the index of the branches ++ where the source and the target exists and selects the higher ++ one. If the selected branch is readonly, then aufs follows the ++ copyup policy. +diff --git a/Documentation/filesystems/aufs/design/06mmap.txt b/Documentation/filesystems/aufs/design/06mmap.txt +new file mode 100644 +index 0000000..55524d6 +--- /dev/null ++++ b/Documentation/filesystems/aufs/design/06mmap.txt +@@ -0,0 +1,47 @@ ++ ++# Copyright (C) 2005-2013 Junjiro R. Okajima ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++mmap(2) -- File Memory Mapping ++---------------------------------------------------------------------- ++In aufs, the file-mapped pages are handled by a branch fs directly, no ++interaction with aufs. It means aufs_mmap() calls the branch fs's ++->mmap(). ++This approach is simple and good, but there is one problem. ++Under /proc, several entries show the mmap-ped files by its path (with ++device and inode number), and the printed path will be the path on the ++branch fs's instead of virtual aufs's. ++This is not a problem in most cases, but some utilities lsof(1) (and its ++user) may expect the path on aufs. ++ ++To address this issue, aufs adds a new member called vm_prfile in struct ++vm_area_struct (and struct vm_region). The original vm_file points to ++the file on the branch fs in order to handle everything correctly as ++usual. The new vm_prfile points to a virtual file in aufs, and the ++show-functions in procfs refers to vm_prfile if it is set. ++Also we need to maintain several other places where touching vm_file ++such like ++- fork()/clone() copies vma and the reference count of vm_file is ++ incremented. ++- merging vma maintains the ref count too. ++ ++This is not a good approach. It just faking the printed path. But it ++leaves all behaviour around f_mapping unchanged. This is surely an ++advantage. ++Actually aufs had adopted another complicated approach which calls ++generic_file_mmap() and handles struct vm_operations_struct. In this ++approach, aufs met a hard problem and I could not solve it without ++switching the approach. +diff --git a/Documentation/filesystems/aufs/design/07export.txt b/Documentation/filesystems/aufs/design/07export.txt +new file mode 100644 +index 0000000..ecf42a4 +--- /dev/null ++++ b/Documentation/filesystems/aufs/design/07export.txt +@@ -0,0 +1,59 @@ ++ ++# Copyright (C) 2005-2013 Junjiro R. Okajima ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++Export Aufs via NFS ++---------------------------------------------------------------------- ++Here is an approach. ++- like xino/xib, add a new file 'xigen' which stores aufs inode ++ generation. ++- iget_locked(): initialize aufs inode generation for a new inode, and ++ store it in xigen file. ++- destroy_inode(): increment aufs inode generation and store it in xigen ++ file. it is necessary even if it is not unlinked, because any data of ++ inode may be changed by UDBA. ++- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise ++ build file handle by ++ + branch id (4 bytes) ++ + superblock generation (4 bytes) ++ + inode number (4 or 8 bytes) ++ + parent dir inode number (4 or 8 bytes) ++ + inode generation (4 bytes)) ++ + return value of exportfs_encode_fh() for the parent on a branch (4 ++ bytes) ++ + file handle for a branch (by exportfs_encode_fh()) ++- fh_to_dentry(): ++ + find the index of a branch from its id in handle, and check it is ++ still exist in aufs. ++ + 1st level: get the inode number from handle and search it in cache. ++ + 2nd level: if not found, get the parent inode number from handle and ++ search it in cache. and then open the parent dir, find the matching ++ inode number by vfs_readdir() and get its name, and call ++ lookup_one_len() for the target dentry. ++ + 3rd level: if the parent dir is not cached, call ++ exportfs_decode_fh() for a branch and get the parent on a branch, ++ build a pathname of it, convert it a pathname in aufs, call ++ path_lookup(). now aufs gets a parent dir dentry, then handle it as ++ the 2nd level. ++ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount ++ for every branch, but not itself. to get this, (currently) aufs ++ searches in current->nsproxy->mnt_ns list. it may not be a good ++ idea, but I didn't get other approach. ++ + test the generation of the gotten inode. ++- every inode operation: they may get EBUSY due to UDBA. in this case, ++ convert it into ESTALE for NFSD. ++- readdir(): call lockdep_on/off() because filldir in NFSD calls ++ lookup_one_len(), vfs_getattr(), encode_fh() and others. +diff --git a/Documentation/filesystems/aufs/design/08shwh.txt b/Documentation/filesystems/aufs/design/08shwh.txt +new file mode 100644 +index 0000000..18b889c +--- /dev/null ++++ b/Documentation/filesystems/aufs/design/08shwh.txt +@@ -0,0 +1,53 @@ ++ ++# Copyright (C) 2005-2013 Junjiro R. Okajima ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++Show Whiteout Mode (shwh) ++---------------------------------------------------------------------- ++Generally aufs hides the name of whiteouts. But in some cases, to show ++them is very useful for users. For instance, creating a new middle layer ++(branch) by merging existing layers. ++ ++(borrowing aufs1 HOW-TO from a user, Michael Towers) ++When you have three branches, ++- Bottom: 'system', squashfs (underlying base system), read-only ++- Middle: 'mods', squashfs, read-only ++- Top: 'overlay', ram (tmpfs), read-write ++ ++The top layer is loaded at boot time and saved at shutdown, to preserve ++the changes made to the system during the session. ++When larger changes have been made, or smaller changes have accumulated, ++the size of the saved top layer data grows. At this point, it would be ++nice to be able to merge the two overlay branches ('mods' and 'overlay') ++and rewrite the 'mods' squashfs, clearing the top layer and thus ++restoring save and load speed. ++ ++This merging is simplified by the use of another aufs mount, of just the ++two overlay branches using the 'shwh' option. ++# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \ ++ aufs /livesys/merge_union ++ ++A merged view of these two branches is then available at ++/livesys/merge_union, and the new feature is that the whiteouts are ++visible! ++Note that in 'shwh' mode the aufs mount must be 'ro', which will disable ++writing to all branches. Also the default mode for all branches is 'ro'. ++It is now possible to save the combined contents of the two overlay ++branches to a new squashfs, e.g.: ++# mksquashfs /livesys/merge_union /path/to/newmods.squash ++ ++This new squashfs archive can be stored on the boot device and the ++initramfs will use it to replace the old one at the next boot. +diff --git a/Documentation/filesystems/aufs/design/10dynop.txt b/Documentation/filesystems/aufs/design/10dynop.txt +new file mode 100644 +index 0000000..49e9a53 +--- /dev/null ++++ b/Documentation/filesystems/aufs/design/10dynop.txt +@@ -0,0 +1,47 @@ ++ ++# Copyright (C) 2010-2013 Junjiro R. Okajima ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++Dynamically customizable FS operations ++---------------------------------------------------------------------- ++Generally FS operations (struct inode_operations, struct ++address_space_operations, struct file_operations, etc.) are defined as ++"static const", but it never means that FS have only one set of ++operation. Some FS have multiple sets of them. For instance, ext2 has ++three sets, one for XIP, for NOBH, and for normal. ++Since aufs overrides and redirects these operations, sometimes aufs has ++to change its behaviour according to the branch FS type. More imporantly ++VFS acts differently if a function (member in the struct) is set or ++not. It means aufs should have several sets of operations and select one ++among them according to the branch FS definition. ++ ++In order to solve this problem and not to affect the behavour of VFS, ++aufs defines these operations dynamically. For instance, aufs defines ++aio_read function for struct file_operations, but it may not be set to ++the file_operations. When the branch FS doesn't have it, aufs doesn't ++set it to its file_operations while the function definition itself is ++still alive. So the behaviour of io_submit(2) will not change, and it ++will return an error when aio_read is not defined. ++ ++The lifetime of these dynamically generated operation object is ++maintained by aufs branch object. When the branch is removed from aufs, ++the reference counter of the object is decremented. When it reaches ++zero, the dynamically generated operation object will be freed. ++ ++This approach is designed to support AIO (io_submit), Direcit I/O and ++XIP mainly. ++Currently this approach is applied to file_operations and ++vm_operations_struct for regular files only. +diff --git a/Documentation/filesystems/aufs/design/99plan.txt b/Documentation/filesystems/aufs/design/99plan.txt +new file mode 100644 +index 0000000..a21f133 +--- /dev/null ++++ b/Documentation/filesystems/aufs/design/99plan.txt +@@ -0,0 +1,96 @@ ++ ++# Copyright (C) 2005-2013 Junjiro R. Okajima ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++Plan ++ ++Restoring some features which was implemented in aufs1. ++They were dropped in aufs2 in order to make source files simpler and ++easier to be reviewed. ++ ++ ++Test Only the Highest One for the Directory Permission (dirperm1 option) ++---------------------------------------------------------------------- ++Let's try case study. ++- aufs has two branches, upper readwrite and lower readonly. ++ /au = /rw + /ro ++- "dirA" exists under /ro, but /rw. and its mode is 0700. ++- user invoked "chmod a+rx /au/dirA" ++- then "dirA" becomes world readable? ++ ++In this case, /ro/dirA is still 0700 since it exists in readonly branch, ++or it may be a natively readonly filesystem. If aufs respects the lower ++branch, it should not respond readdir request from other users. But user ++allowed it by chmod. Should really aufs rejects showing the entries ++under /ro/dirA? ++ ++To be honest, I don't have a best solution for this case. So I ++implemented 'dirperm1' and 'nodirperm1' option in aufs1, and leave it to ++users. ++When dirperm1 is specified, aufs checks only the highest one for the ++directory permission, and shows the entries. Otherwise, as usual, checks ++every dir existing on all branches and rejects the request. ++ ++As a side effect, dirperm1 option improves the performance of aufs ++because the number of permission check is reduced. ++ ++ ++Being Another Aufs's Readonly Branch (robr) ++---------------------------------------------------------------------- ++Aufs1 allows aufs to be another aufs's readonly branch. ++This feature was developed by a user's request. But it may not be used ++currecnly. ++ ++ ++Copy-up on Open (coo=) ++---------------------------------------------------------------------- ++By default the internal copy-up is executed when it is really necessary. ++It is not done when a file is opened for writing, but when write(2) is ++done. Users who have many (over 100) branches want to know and analyse ++when and what file is copied-up. To insert a new upper branch which ++contains such files only may improve the performance of aufs. ++ ++Aufs1 implemented "coo=none | leaf | all" option. ++ ++ ++Refresh the Opened File (refrof) ++---------------------------------------------------------------------- ++This option is implemented in aufs1 but incomplete. ++ ++When user reads from a file, he expects to get its latest filedata ++generally. If the file is removed and a new same named file is created, ++the content he gets is unchanged, ie. the unlinked filedata. ++ ++Let's try case study again. ++- aufs has two branches. ++ /au = /rw + /ro ++- "fileA" exists under /ro, but /rw. ++- user opened "/au/fileA". ++- he or someone else inserts a branch (/new) between /rw and /ro. ++ /au = /rw + /new + /ro ++- the new branch has "fileA". ++- user reads from the opened "fileA" ++- which filedata should aufs return, from /ro or /new? ++ ++Some people says it has to be "from /ro" and it is a semantics of Unix. ++The others say it should be "from /new" because the file is not removed ++and it is equivalent to the case of someone else modifies the file. ++ ++Here again I don't have a best and final answer. I got an idea to ++implement 'refrof' and 'norefrof' option. When 'refrof' (REFResh the ++Opened File) is specified (by default), aufs returns the filedata from ++/new. ++Otherwise from /new. +diff --git a/Documentation/filesystems/debugfs.txt b/Documentation/filesystems/debugfs.txt +index 742cc06..ad7eb40 100644 +--- a/Documentation/filesystems/debugfs.txt ++++ b/Documentation/filesystems/debugfs.txt +@@ -14,7 +14,10 @@ Debugfs is typically mounted with a command like: + + mount -t debugfs none /sys/kernel/debug + +-(Or an equivalent /etc/fstab line). ++(Or an equivalent /etc/fstab line). ++The debugfs root directory is accessible only to the root user by ++default. To change access to the tree the "uid", "gid" and "mode" mount ++options can be used. + + Note that the debugfs API is exported GPL-only to modules. + +diff --git a/Documentation/filesystems/overlayfs.txt b/Documentation/filesystems/overlayfs.txt +new file mode 100644 +index 0000000..7161dc3 +--- /dev/null ++++ b/Documentation/filesystems/overlayfs.txt +@@ -0,0 +1,199 @@ ++Written by: Neil Brown ++ ++Overlay Filesystem ++================== ++ ++This document describes a prototype for a new approach to providing ++overlay-filesystem functionality in Linux (sometimes referred to as ++union-filesystems). An overlay-filesystem tries to present a ++filesystem which is the result over overlaying one filesystem on top ++of the other. ++ ++The result will inevitably fail to look exactly like a normal ++filesystem for various technical reasons. The expectation is that ++many use cases will be able to ignore these differences. ++ ++This approach is 'hybrid' because the objects that appear in the ++filesystem do not all appear to belong to that filesystem. In many ++cases an object accessed in the union will be indistinguishable ++from accessing the corresponding object from the original filesystem. ++This is most obvious from the 'st_dev' field returned by stat(2). ++ ++While directories will report an st_dev from the overlay-filesystem, ++all non-directory objects will report an st_dev from the lower or ++upper filesystem that is providing the object. Similarly st_ino will ++only be unique when combined with st_dev, and both of these can change ++over the lifetime of a non-directory object. Many applications and ++tools ignore these values and will not be affected. ++ ++Upper and Lower ++--------------- ++ ++An overlay filesystem combines two filesystems - an 'upper' filesystem ++and a 'lower' filesystem. When a name exists in both filesystems, the ++object in the 'upper' filesystem is visible while the object in the ++'lower' filesystem is either hidden or, in the case of directories, ++merged with the 'upper' object. ++ ++It would be more correct to refer to an upper and lower 'directory ++tree' rather than 'filesystem' as it is quite possible for both ++directory trees to be in the same filesystem and there is no ++requirement that the root of a filesystem be given for either upper or ++lower. ++ ++The lower filesystem can be any filesystem supported by Linux and does ++not need to be writable. The lower filesystem can even be another ++overlayfs. The upper filesystem will normally be writable and if it ++is it must support the creation of trusted.* extended attributes, and ++must provide valid d_type in readdir responses, at least for symbolic ++links - so NFS is not suitable. ++ ++A read-only overlay of two read-only filesystems may use any ++filesystem type. ++ ++Directories ++----------- ++ ++Overlaying mainly involved directories. If a given name appears in both ++upper and lower filesystems and refers to a non-directory in either, ++then the lower object is hidden - the name refers only to the upper ++object. ++ ++Where both upper and lower objects are directories, a merged directory ++is formed. ++ ++At mount time, the two directories given as mount options are combined ++into a merged directory: ++ ++ mount -t overlayfs overlayfs -olowerdir=/lower,upperdir=/upper /overlay ++ ++Then whenever a lookup is requested in such a merged directory, the ++lookup is performed in each actual directory and the combined result ++is cached in the dentry belonging to the overlay filesystem. If both ++actual lookups find directories, both are stored and a merged ++directory is created, otherwise only one is stored: the upper if it ++exists, else the lower. ++ ++Only the lists of names from directories are merged. Other content ++such as metadata and extended attributes are reported for the upper ++directory only. These attributes of the lower directory are hidden. ++ ++whiteouts and opaque directories ++-------------------------------- ++ ++In order to support rm and rmdir without changing the lower ++filesystem, an overlay filesystem needs to record in the upper filesystem ++that files have been removed. This is done using whiteouts and opaque ++directories (non-directories are always opaque). ++ ++The overlay filesystem uses extended attributes with a ++"trusted.overlay." prefix to record these details. ++ ++A whiteout is created as a symbolic link with target ++"(overlay-whiteout)" and with xattr "trusted.overlay.whiteout" set to "y". ++When a whiteout is found in the upper level of a merged directory, any ++matching name in the lower level is ignored, and the whiteout itself ++is also hidden. ++ ++A directory is made opaque by setting the xattr "trusted.overlay.opaque" ++to "y". Where the upper filesystem contains an opaque directory, any ++directory in the lower filesystem with the same name is ignored. ++ ++readdir ++------- ++ ++When a 'readdir' request is made on a merged directory, the upper and ++lower directories are each read and the name lists merged in the ++obvious way (upper is read first, then lower - entries that already ++exist are not re-added). This merged name list is cached in the ++'struct file' and so remains as long as the file is kept open. If the ++directory is opened and read by two processes at the same time, they ++will each have separate caches. A seekdir to the start of the ++directory (offset 0) followed by a readdir will cause the cache to be ++discarded and rebuilt. ++ ++This means that changes to the merged directory do not appear while a ++directory is being read. This is unlikely to be noticed by many ++programs. ++ ++seek offsets are assigned sequentially when the directories are read. ++Thus if ++ - read part of a directory ++ - remember an offset, and close the directory ++ - re-open the directory some time later ++ - seek to the remembered offset ++ ++there may be little correlation between the old and new locations in ++the list of filenames, particularly if anything has changed in the ++directory. ++ ++Readdir on directories that are not merged is simply handled by the ++underlying directory (upper or lower). ++ ++ ++Non-directories ++--------------- ++ ++Objects that are not directories (files, symlinks, device-special ++files etc.) are presented either from the upper or lower filesystem as ++appropriate. When a file in the lower filesystem is accessed in a way ++the requires write-access, such as opening for write access, changing ++some metadata etc., the file is first copied from the lower filesystem ++to the upper filesystem (copy_up). Note that creating a hard-link ++also requires copy_up, though of course creation of a symlink does ++not. ++ ++The copy_up may turn out to be unnecessary, for example if the file is ++opened for read-write but the data is not modified. ++ ++The copy_up process first makes sure that the containing directory ++exists in the upper filesystem - creating it and any parents as ++necessary. It then creates the object with the same metadata (owner, ++mode, mtime, symlink-target etc.) and then if the object is a file, the ++data is copied from the lower to the upper filesystem. Finally any ++extended attributes are copied up. ++ ++Once the copy_up is complete, the overlay filesystem simply ++provides direct access to the newly created file in the upper ++filesystem - future operations on the file are barely noticed by the ++overlay filesystem (though an operation on the name of the file such as ++rename or unlink will of course be noticed and handled). ++ ++ ++Non-standard behavior ++--------------------- ++ ++The copy_up operation essentially creates a new, identical file and ++moves it over to the old name. The new file may be on a different ++filesystem, so both st_dev and st_ino of the file may change. ++ ++Any open files referring to this inode will access the old data and ++metadata. Similarly any file locks obtained before copy_up will not ++apply to the copied up file. ++ ++On a file is opened with O_RDONLY fchmod(2), fchown(2), futimesat(2) ++and fsetxattr(2) will fail with EROFS. ++ ++If a file with multiple hard links is copied up, then this will ++"break" the link. Changes will not be propagated to other names ++referring to the same inode. ++ ++Symlinks in /proc/PID/ and /proc/PID/fd which point to a non-directory ++object in overlayfs will not contain vaid absolute paths, only ++relative paths leading up to the filesystem's root. This will be ++fixed in the future. ++ ++Some operations are not atomic, for example a crash during copy_up or ++rename will leave the filesystem in an inconsitent state. This will ++be addressed in the future. ++ ++Changes to underlying filesystems ++--------------------------------- ++ ++Offline changes, when the overlay is not mounted, are allowed to either ++the upper or the lower trees. ++ ++Changes to the underlying filesystems while part of a mounted overlay ++filesystem are not allowed. If the underlying filesystem is changed, ++the behavior of the overlay is undefined, though it will not result in ++a crash or deadlock. +diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt +index 404a097..d0b7a48 100644 +--- a/Documentation/filesystems/proc.txt ++++ b/Documentation/filesystems/proc.txt +@@ -41,6 +41,8 @@ Table of Contents + 3.5 /proc//mountinfo - Information about mounts + 3.6 /proc//comm & /proc//task//comm + ++ 4 Configuring procfs ++ 4.1 Mount options + + ------------------------------------------------------------------------------ + Preface +@@ -1542,3 +1544,40 @@ a task to set its own or one of its thread siblings comm value. The comm value + is limited in size compared to the cmdline value, so writing anything longer + then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated + comm value. ++ ++ ++------------------------------------------------------------------------------ ++Configuring procfs ++------------------------------------------------------------------------------ ++ ++4.1 Mount options ++--------------------- ++ ++The following mount options are supported: ++ ++ hidepid= Set /proc// access mode. ++ gid= Set the group authorized to learn processes information. ++ ++hidepid=0 means classic mode - everybody may access all /proc// directories ++(default). ++ ++hidepid=1 means users may not access any /proc// directories but their ++own. Sensitive files like cmdline, sched*, status are now protected against ++other users. This makes it impossible to learn whether any user runs ++specific program (given the program doesn't reveal itself by its behaviour). ++As an additional bonus, as /proc//cmdline is unaccessible for other users, ++poorly written programs passing sensitive information via program arguments are ++now protected against local eavesdroppers. ++ ++hidepid=2 means hidepid=1 plus all /proc// will be fully invisible to other ++users. It doesn't mean that it hides a fact whether a process with a specific ++pid value exists (it can be learned by other means, e.g. by "kill -0 $PID"), ++but it hides process' uid and gid, which may be learned by stat()'ing ++/proc// otherwise. It greatly complicates an intruder's task of gathering ++information about running processes, whether some daemon runs with elevated ++privileges, whether other user runs some sensitive program, whether other users ++run any program at all, etc. ++ ++gid= defines a group authorized to learn processes information otherwise ++prohibited by hidepid=. If you use some daemon like identd which needs to learn ++information about processes information, just add identd to this group. +diff --git a/Documentation/hwmon/emc2305 b/Documentation/hwmon/emc2305 +new file mode 100644 +index 0000000..4de033b +--- /dev/null ++++ b/Documentation/hwmon/emc2305 +@@ -0,0 +1,33 @@ ++Kernel driver emc2305 ++===================== ++ ++Supported chips: ++ * SMSC EMC2305, EMC2303, EMC2302, EMC2301 ++ Adresses scanned: I2C 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d ++ Prefixes: 'emc2305', 'emc2303', 'emc2302', 'emc2301' ++ Datasheet: Publicly available at the SMSC website : ++ http://www.smsc.com/Products/Thermal_and_Power_Management/Fan_Controllers ++ ++Authors: ++ Reinhard Pfau, Guntermann & Drunck GmbH ++ ++Description ++----------- ++ ++The SMSC EMC2305 is a fan controller for up to 5 fans. ++The EMC2303 has the same functionality but supports only up to 3 fans. ++ ++The EMC2302 supports 2 fans and the EMC2301 1 fan. These chips support less ++possible I2C addresses. ++ ++Fan rotation speeds are reported in RPM. ++The driver supports the RPM based PWM control to keep a fan at a desired speed. ++To enable this function for a fan, write 3 to pwm_enable and the desired ++fan speed to fan_target. ++ ++ ++Devicetree ++---------- ++ ++Configuration is also possible via devicetree: ++Documentation/devicetree/bindings/hwmon/emc2305.txt +diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87 +index 6f496a5..23b7def 100644 +--- a/Documentation/hwmon/it87 ++++ b/Documentation/hwmon/it87 +@@ -26,6 +26,10 @@ Supported chips: + Prefix: 'it8721' + Addresses scanned: from Super I/O config space (8 I/O ports) + Datasheet: Not publicly available ++ * IT8728F ++ Prefix: 'it8728' ++ Addresses scanned: from Super I/O config space (8 I/O ports) ++ Datasheet: Not publicly available + * SiS950 [clone of IT8705F] + Prefix: 'it87' + Addresses scanned: from Super I/O config space (8 I/O ports) +@@ -71,7 +75,7 @@ Description + ----------- + + This driver implements support for the IT8705F, IT8712F, IT8716F, +-IT8718F, IT8720F, IT8721F, IT8726F, IT8758E and SiS950 chips. ++IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E and SiS950 chips. + + These chips are 'Super I/O chips', supporting floppy disks, infrared ports, + joysticks and other miscellaneous stuff. For hardware monitoring, they +@@ -105,6 +109,9 @@ The IT8726F is just bit enhanced IT8716F with additional hardware + for AMD power sequencing. Therefore the chip will appear as IT8716F + to userspace applications. + ++The IT8728F is considered compatible with the IT8721F, until a datasheet ++becomes available (hopefully.) ++ + Temperatures are measured in degrees Celsius. An alarm is triggered once + when the Overtemperature Shutdown limit is crossed. + +@@ -121,8 +128,8 @@ alarm is triggered if the voltage has crossed a programmable minimum or + maximum limit. Note that minimum in this case always means 'closest to + zero'; this is important for negative voltage measurements. All voltage + inputs can measure voltages between 0 and 4.08 volts, with a resolution of +-0.016 volt (except IT8721F/IT8758E: 0.012 volt.) The battery voltage in8 does +-not have limit registers. ++0.016 volt (except IT8721F/IT8758E and IT8728F: 0.012 volt.) The battery ++voltage in8 does not have limit registers. + + On the IT8721F/IT8758E, some voltage inputs are internal and scaled inside + the chip (in7, in8 and optionally in3). The driver handles this transparently +diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt +new file mode 100644 +index 0000000..ab5478f +--- /dev/null ++++ b/Documentation/input/alps.txt +@@ -0,0 +1,75 @@ ++ALPS Touchpad Protocol ++---------------------- ++ ++Introduction ++------------ ++ ++Currently the ALPS touchpad driver supports two protocol versions in use by ++ALPS touchpads, the "old" and "new" protocol versions. Fundamentally these ++differ only in the format of their event packets (in reality many features may ++be found on new protocol devices that aren't found on the old protocol ++devices, but these are handled transparently as feature differences rather ++than protocol differences). ++ ++Detection ++--------- ++ ++All ALPS touchpads should respond to the "E6 report" command sequence: ++E8-E6-E6-E6-E9. An ALPS touchpad should respond with either 00-00-0A or ++00-00-64. ++ ++If the E6 report is successful, the touchpad model is identified using the "E7 ++report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is ++matched against known models in the alps_model_data_array. ++ ++Packet Format ++------------- ++ ++In the following tables, the following notation us used. ++ ++ CAPITALS = stick, miniscules = touchpad ++ ++?'s can have different meanings on different models, such as wheel rotation, ++extra buttons, stick buttons on a dualpoint, etc. ++ ++PS/2 packet format ++------------------ ++ ++ byte 0: 0 0 YSGN XSGN 1 M R L ++ byte 1: X7 X6 X5 X4 X3 X2 X1 X0 ++ byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 ++ ++Note that the device never signals overflow condition. ++ ++ALPS Absolute Mode - Old Format ++------------------------------- ++ ++ byte 0: 1 0 0 0 1 x9 x8 x7 ++ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 ++ byte 2: 0 ? ? l r ? fin ges ++ byte 3: 0 ? ? ? ? y9 y8 y7 ++ byte 4: 0 y6 y5 y4 y3 y2 y1 y0 ++ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 ++ ++ALPS Absolute Mode - New Format ++------------------------------- ++ ++ byte 0: 1 ? ? ? 1 ? ? ? ++ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 ++ byte 2: 0 x10 x9 x8 x7 ? fin ges ++ byte 3: 0 y9 y8 y7 1 M R L ++ byte 4: 0 y6 y5 y4 y3 y2 y1 y0 ++ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 ++ ++Dualpoint device -- interleaved packet format ++--------------------------------------------- ++ ++ byte 0: 1 1 0 0 1 1 1 1 ++ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 ++ byte 2: 0 x10 x9 x8 x7 0 fin ges ++ byte 3: 0 0 YSGN XSGN 1 1 1 1 ++ byte 4: X7 X6 X5 X4 X3 X2 X1 X0 ++ byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 ++ byte 6: 0 y9 y8 y7 1 m r l ++ byte 7: 0 y6 y5 y4 y3 y2 y1 y0 ++ byte 8: 0 z6 z5 z4 z3 z2 z1 z0 +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index f0001eb..5455bd4 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -446,8 +446,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + ccw_timeout_log [S390] + See Documentation/s390/CommonIO for details. + +- cgroup_disable= [KNL] Disable a particular controller +- Format: {name of the controller(s) to disable} ++ cgroup_disable= [KNL] Disable/enable a particular controller ++ cgroup_enable= Format: {name of the controller(s) to disable/enable} + {Currently supported controllers - "memory"} + + checkreqprot [SELINUX] Set initial checkreqprot flag value. +@@ -2197,6 +2197,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + + default: off. + ++ printk.always_kmsg_dump= ++ Trigger kmsg_dump for cases other than kernel oops or ++ panics ++ Format: (1/Y/y=enable, 0/N/n=disable) ++ default: disabled ++ + printk.time= Show timing data prefixed to each printk message line + Format: (1/Y/y=enable, 0/N/n=disable) + +diff --git a/Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt b/Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt +deleted file mode 100644 +index 256c2c9..0000000 +--- a/Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt ++++ /dev/null +@@ -1,791 +0,0 @@ +-IETF CIPSO Working Group +-16 July, 1992 +- +- +- +- COMMERCIAL IP SECURITY OPTION (CIPSO 2.2) +- +- +- +-1. Status +- +-This Internet Draft provides the high level specification for a Commercial +-IP Security Option (CIPSO). This draft reflects the version as approved by +-the CIPSO IETF Working Group. Distribution of this memo is unlimited. +- +-This document is an Internet Draft. Internet Drafts are working documents +-of the Internet Engineering Task Force (IETF), its Areas, and its Working +-Groups. Note that other groups may also distribute working documents as +-Internet Drafts. +- +-Internet Drafts are draft documents valid for a maximum of six months. +-Internet Drafts may be updated, replaced, or obsoleted by other documents +-at any time. It is not appropriate to use Internet Drafts as reference +-material or to cite them other than as a "working draft" or "work in +-progress." +- +-Please check the I-D abstract listing contained in each Internet Draft +-directory to learn the current status of this or any other Internet Draft. +- +- +- +- +-2. Background +- +-Currently the Internet Protocol includes two security options. One of +-these options is the DoD Basic Security Option (BSO) (Type 130) which allows +-IP datagrams to be labeled with security classifications. This option +-provides sixteen security classifications and a variable number of handling +-restrictions. To handle additional security information, such as security +-categories or compartments, another security option (Type 133) exists and +-is referred to as the DoD Extended Security Option (ESO). The values for +-the fixed fields within these two options are administered by the Defense +-Information Systems Agency (DISA). +- +-Computer vendors are now building commercial operating systems with +-mandatory access controls and multi-level security. These systems are +-no longer built specifically for a particular group in the defense or +-intelligence communities. They are generally available commercial systems +-for use in a variety of government and civil sector environments. +- +-The small number of ESO format codes can not support all the possible +-applications of a commercial security option. The BSO and ESO were +-designed to only support the United States DoD. CIPSO has been designed +-to support multiple security policies. This Internet Draft provides the +-format and procedures required to support a Mandatory Access Control +-security policy. Support for additional security policies shall be +-defined in future RFCs. +- +- +- +- +-Internet Draft, Expires 15 Jan 93 [PAGE 1] +- +- +- +-CIPSO INTERNET DRAFT 16 July, 1992 +- +- +- +- +-3. CIPSO Format +- +-Option type: 134 (Class 0, Number 6, Copy on Fragmentation) +-Option length: Variable +- +-This option permits security related information to be passed between +-systems within a single Domain of Interpretation (DOI). A DOI is a +-collection of systems which agree on the meaning of particular values +-in the security option. An authority that has been assigned a DOI +-identifier will define a mapping between appropriate CIPSO field values +-and their human readable equivalent. This authority will distribute that +-mapping to hosts within the authority's domain. These mappings may be +-sensitive, therefore a DOI authority is not required to make these +-mappings available to anyone other than the systems that are included in +-the DOI. +- +-This option MUST be copied on fragmentation. This option appears at most +-once in a datagram. All multi-octet fields in the option are defined to be +-transmitted in network byte order. The format of this option is as follows: +- +-+----------+----------+------//------+-----------//---------+ +-| 10000110 | LLLLLLLL | DDDDDDDDDDDD | TTTTTTTTTTTTTTTTTTTT | +-+----------+----------+------//------+-----------//---------+ +- +- TYPE=134 OPTION DOMAIN OF TAGS +- LENGTH INTERPRETATION +- +- +- Figure 1. CIPSO Format +- +- +-3.1 Type +- +-This field is 1 octet in length. Its value is 134. +- +- +-3.2 Length +- +-This field is 1 octet in length. It is the total length of the option +-including the type and length fields. With the current IP header length +-restriction of 40 octets the value of this field MUST not exceed 40. +- +- +-3.3 Domain of Interpretation Identifier +- +-This field is an unsigned 32 bit integer. The value 0 is reserved and MUST +-not appear as the DOI identifier in any CIPSO option. Implementations +-should assume that the DOI identifier field is not aligned on any particular +-byte boundary. +- +-To conserve space in the protocol, security levels and categories are +-represented by numbers rather than their ASCII equivalent. This requires +-a mapping table within CIPSO hosts to map these numbers to their +-corresponding ASCII representations. Non-related groups of systems may +- +- +- +-Internet Draft, Expires 15 Jan 93 [PAGE 2] +- +- +- +-CIPSO INTERNET DRAFT 16 July, 1992 +- +- +- +-have their own unique mappings. For example, one group of systems may +-use the number 5 to represent Unclassified while another group may use the +-number 1 to represent that same security level. The DOI identifier is used +-to identify which mapping was used for the values within the option. +- +- +-3.4 Tag Types +- +-A common format for passing security related information is necessary +-for interoperability. CIPSO uses sets of "tags" to contain the security +-information relevant to the data in the IP packet. Each tag begins with +-a tag type identifier followed by the length of the tag and ends with the +-actual security information to be passed. All multi-octet fields in a tag +-are defined to be transmitted in network byte order. Like the DOI +-identifier field in the CIPSO header, implementations should assume that +-all tags, as well as fields within a tag, are not aligned on any particular +-octet boundary. The tag types defined in this document contain alignment +-bytes to assist alignment of some information, however alignment can not +-be guaranteed if CIPSO is not the first IP option. +- +-CIPSO tag types 0 through 127 are reserved for defining standard tag +-formats. Their definitions will be published in RFCs. Tag types whose +-identifiers are greater than 127 are defined by the DOI authority and may +-only be meaningful in certain Domains of Interpretation. For these tag +-types, implementations will require the DOI identifier as well as the tag +-number to determine the security policy and the format associated with the +-tag. Use of tag types above 127 are restricted to closed networks where +-interoperability with other networks will not be an issue. Implementations +-that support a tag type greater than 127 MUST support at least one DOI that +-requires only tag types 1 to 127. +- +-Tag type 0 is reserved. Tag types 1, 2, and 5 are defined in this +-Internet Draft. Types 3 and 4 are reserved for work in progress. +-The standard format for all current and future CIPSO tags is shown below: +- +-+----------+----------+--------//--------+ +-| TTTTTTTT | LLLLLLLL | IIIIIIIIIIIIIIII | +-+----------+----------+--------//--------+ +- TAG TAG TAG +- TYPE LENGTH INFORMATION +- +- Figure 2: Standard Tag Format +- +-In the three tag types described in this document, the length and count +-restrictions are based on the current IP limitation of 40 octets for all +-IP options. If the IP header is later expanded, then the length and count +-restrictions specified in this document may increase to use the full area +-provided for IP options. +- +- +-3.4.1 Tag Type Classes +- +-Tag classes consist of tag types that have common processing requirements +-and support the same security policy. The three tags defined in this +-Internet Draft belong to the Mandatory Access Control (MAC) Sensitivity +- +- +- +-Internet Draft, Expires 15 Jan 93 [PAGE 3] +- +- +- +-CIPSO INTERNET DRAFT 16 July, 1992 +- +- +- +-class and support the MAC Sensitivity security policy. +- +- +-3.4.2 Tag Type 1 +- +-This is referred to as the "bit-mapped" tag type. Tag type 1 is included +-in the MAC Sensitivity tag type class. The format of this tag type is as +-follows: +- +-+----------+----------+----------+----------+--------//---------+ +-| 00000001 | LLLLLLLL | 00000000 | LLLLLLLL | CCCCCCCCCCCCCCCCC | +-+----------+----------+----------+----------+--------//---------+ +- +- TAG TAG ALIGNMENT SENSITIVITY BIT MAP OF +- TYPE LENGTH OCTET LEVEL CATEGORIES +- +- Figure 3. Tag Type 1 Format +- +- +-3.4.2.1 Tag Type +- +-This field is 1 octet in length and has a value of 1. +- +- +-3.4.2.2 Tag Length +- +-This field is 1 octet in length. It is the total length of the tag type +-including the type and length fields. With the current IP header length +-restriction of 40 bytes the value within this field is between 4 and 34. +- +- +-3.4.2.3 Alignment Octet +- +-This field is 1 octet in length and always has the value of 0. Its purpose +-is to align the category bitmap field on an even octet boundary. This will +-speed many implementations including router implementations. +- +- +-3.4.2.4 Sensitivity Level +- +-This field is 1 octet in length. Its value is from 0 to 255. The values +-are ordered with 0 being the minimum value and 255 representing the maximum +-value. +- +- +-3.4.2.5 Bit Map of Categories +- +-The length of this field is variable and ranges from 0 to 30 octets. This +-provides representation of categories 0 to 239. The ordering of the bits +-is left to right or MSB to LSB. For example category 0 is represented by +-the most significant bit of the first byte and category 15 is represented +-by the least significant bit of the second byte. Figure 4 graphically +-shows this ordering. Bit N is binary 1 if category N is part of the label +-for the datagram, and bit N is binary 0 if category N is not part of the +-label. Except for the optimized tag 1 format described in the next section, +- +- +- +-Internet Draft, Expires 15 Jan 93 [PAGE 4] +- +- +- +-CIPSO INTERNET DRAFT 16 July, 1992 +- +- +- +-minimal encoding SHOULD be used resulting in no trailing zero octets in the +-category bitmap. +- +- octet 0 octet 1 octet 2 octet 3 octet 4 octet 5 +- XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX . . . +-bit 01234567 89111111 11112222 22222233 33333333 44444444 +-number 012345 67890123 45678901 23456789 01234567 +- +- Figure 4. Ordering of Bits in Tag 1 Bit Map +- +- +-3.4.2.6 Optimized Tag 1 Format +- +-Routers work most efficiently when processing fixed length fields. To +-support these routers there is an optimized form of tag type 1. The format +-does not change. The only change is to the category bitmap which is set to +-a constant length of 10 octets. Trailing octets required to fill out the 10 +-octets are zero filled. Ten octets, allowing for 80 categories, was chosen +-because it makes the total length of the CIPSO option 20 octets. If CIPSO +-is the only option then the option will be full word aligned and additional +-filler octets will not be required. +- +- +-3.4.3 Tag Type 2 +- +-This is referred to as the "enumerated" tag type. It is used to describe +-large but sparsely populated sets of categories. Tag type 2 is in the MAC +-Sensitivity tag type class. The format of this tag type is as follows: +- +-+----------+----------+----------+----------+-------------//-------------+ +-| 00000010 | LLLLLLLL | 00000000 | LLLLLLLL | CCCCCCCCCCCCCCCCCCCCCCCCCC | +-+----------+----------+----------+----------+-------------//-------------+ +- +- TAG TAG ALIGNMENT SENSITIVITY ENUMERATED +- TYPE LENGTH OCTET LEVEL CATEGORIES +- +- Figure 5. Tag Type 2 Format +- +- +-3.4.3.1 Tag Type +- +-This field is one octet in length and has a value of 2. +- +- +-3.4.3.2 Tag Length +- +-This field is 1 octet in length. It is the total length of the tag type +-including the type and length fields. With the current IP header length +-restriction of 40 bytes the value within this field is between 4 and 34. +- +- +-3.4.3.3 Alignment Octet +- +-This field is 1 octet in length and always has the value of 0. Its purpose +-is to align the category field on an even octet boundary. This will +- +- +- +-Internet Draft, Expires 15 Jan 93 [PAGE 5] +- +- +- +-CIPSO INTERNET DRAFT 16 July, 1992 +- +- +- +-speed many implementations including router implementations. +- +- +-3.4.3.4 Sensitivity Level +- +-This field is 1 octet in length. Its value is from 0 to 255. The values +-are ordered with 0 being the minimum value and 255 representing the +-maximum value. +- +- +-3.4.3.5 Enumerated Categories +- +-In this tag, categories are represented by their actual value rather than +-by their position within a bit field. The length of each category is 2 +-octets. Up to 15 categories may be represented by this tag. Valid values +-for categories are 0 to 65534. Category 65535 is not a valid category +-value. The categories MUST be listed in ascending order within the tag. +- +- +-3.4.4 Tag Type 5 +- +-This is referred to as the "range" tag type. It is used to represent +-labels where all categories in a range, or set of ranges, are included +-in the sensitivity label. Tag type 5 is in the MAC Sensitivity tag type +-class. The format of this tag type is as follows: +- +-+----------+----------+----------+----------+------------//-------------+ +-| 00000101 | LLLLLLLL | 00000000 | LLLLLLLL | Top/Bottom | Top/Bottom | +-+----------+----------+----------+----------+------------//-------------+ +- +- TAG TAG ALIGNMENT SENSITIVITY CATEGORY RANGES +- TYPE LENGTH OCTET LEVEL +- +- Figure 6. Tag Type 5 Format +- +- +-3.4.4.1 Tag Type +- +-This field is one octet in length and has a value of 5. +- +- +-3.4.4.2 Tag Length +- +-This field is 1 octet in length. It is the total length of the tag type +-including the type and length fields. With the current IP header length +-restriction of 40 bytes the value within this field is between 4 and 34. +- +- +-3.4.4.3 Alignment Octet +- +-This field is 1 octet in length and always has the value of 0. Its purpose +-is to align the category range field on an even octet boundary. This will +-speed many implementations including router implementations. +- +- +- +- +- +-Internet Draft, Expires 15 Jan 93 [PAGE 6] +- +- +- +-CIPSO INTERNET DRAFT 16 July, 1992 +- +- +- +-3.4.4.4 Sensitivity Level +- +-This field is 1 octet in length. Its value is from 0 to 255. The values +-are ordered with 0 being the minimum value and 255 representing the maximum +-value. +- +- +-3.4.4.5 Category Ranges +- +-A category range is a 4 octet field comprised of the 2 octet index of the +-highest numbered category followed by the 2 octet index of the lowest +-numbered category. These range endpoints are inclusive within the range of +-categories. All categories within a range are included in the sensitivity +-label. This tag may contain a maximum of 7 category pairs. The bottom +-category endpoint for the last pair in the tag MAY be omitted and SHOULD be +-assumed to be 0. The ranges MUST be non-overlapping and be listed in +-descending order. Valid values for categories are 0 to 65534. Category +-65535 is not a valid category value. +- +- +-3.4.5 Minimum Requirements +- +-A CIPSO implementation MUST be capable of generating at least tag type 1 in +-the non-optimized form. In addition, a CIPSO implementation MUST be able +-to receive any valid tag type 1 even those using the optimized tag type 1 +-format. +- +- +-4. Configuration Parameters +- +-The configuration parameters defined below are required for all CIPSO hosts, +-gateways, and routers that support multiple sensitivity labels. A CIPSO +-host is defined to be the origination or destination system for an IP +-datagram. A CIPSO gateway provides IP routing services between two or more +-IP networks and may be required to perform label translations between +-networks. A CIPSO gateway may be an enhanced CIPSO host or it may just +-provide gateway services with no end system CIPSO capabilities. A CIPSO +-router is a dedicated IP router that routes IP datagrams between two or more +-IP networks. +- +-An implementation of CIPSO on a host MUST have the capability to reject a +-datagram for reasons that the information contained can not be adequately +-protected by the receiving host or if acceptance may result in violation of +-the host or network security policy. In addition, a CIPSO gateway or router +-MUST be able to reject datagrams going to networks that can not provide +-adequate protection or may violate the network's security policy. To +-provide this capability the following minimal set of configuration +-parameters are required for CIPSO implementations: +- +-HOST_LABEL_MAX - This parameter contains the maximum sensitivity label that +-a CIPSO host is authorized to handle. All datagrams that have a label +-greater than this maximum MUST be rejected by the CIPSO host. This +-parameter does not apply to CIPSO gateways or routers. This parameter need +-not be defined explicitly as it can be implicitly derived from the +-PORT_LABEL_MAX parameters for the associated interfaces. +- +- +- +-Internet Draft, Expires 15 Jan 93 [PAGE 7] +- +- +- +-CIPSO INTERNET DRAFT 16 July, 1992 +- +- +- +- +-HOST_LABEL_MIN - This parameter contains the minimum sensitivity label that +-a CIPSO host is authorized to handle. All datagrams that have a label less +-than this minimum MUST be rejected by the CIPSO host. This parameter does +-not apply to CIPSO gateways or routers. This parameter need not be defined +-explicitly as it can be implicitly derived from the PORT_LABEL_MIN +-parameters for the associated interfaces. +- +-PORT_LABEL_MAX - This parameter contains the maximum sensitivity label for +-all datagrams that may exit a particular network interface port. All +-outgoing datagrams that have a label greater than this maximum MUST be +-rejected by the CIPSO system. The label within this parameter MUST be +-less than or equal to the label within the HOST_LABEL_MAX parameter. This +-parameter does not apply to CIPSO hosts that support only one network port. +- +-PORT_LABEL_MIN - This parameter contains the minimum sensitivity label for +-all datagrams that may exit a particular network interface port. All +-outgoing datagrams that have a label less than this minimum MUST be +-rejected by the CIPSO system. The label within this parameter MUST be +-greater than or equal to the label within the HOST_LABEL_MIN parameter. +-This parameter does not apply to CIPSO hosts that support only one network +-port. +- +-PORT_DOI - This parameter is used to assign a DOI identifier value to a +-particular network interface port. All CIPSO labels within datagrams +-going out this port MUST use the specified DOI identifier. All CIPSO +-hosts and gateways MUST support either this parameter, the NET_DOI +-parameter, or the HOST_DOI parameter. +- +-NET_DOI - This parameter is used to assign a DOI identifier value to a +-particular IP network address. All CIPSO labels within datagrams destined +-for the particular IP network MUST use the specified DOI identifier. All +-CIPSO hosts and gateways MUST support either this parameter, the PORT_DOI +-parameter, or the HOST_DOI parameter. +- +-HOST_DOI - This parameter is used to assign a DOI identifier value to a +-particular IP host address. All CIPSO labels within datagrams destined for +-the particular IP host will use the specified DOI identifier. All CIPSO +-hosts and gateways MUST support either this parameter, the PORT_DOI +-parameter, or the NET_DOI parameter. +- +-This list represents the minimal set of configuration parameters required +-to be compliant. Implementors are encouraged to add to this list to +-provide enhanced functionality and control. For example, many security +-policies may require both incoming and outgoing datagrams be checked against +-the port and host label ranges. +- +- +-4.1 Port Range Parameters +- +-The labels represented by the PORT_LABEL_MAX and PORT_LABEL_MIN parameters +-MAY be in CIPSO or local format. Some CIPSO systems, such as routers, may +-want to have the range parameters expressed in CIPSO format so that incoming +-labels do not have to be converted to a local format before being compared +-against the range. If multiple DOIs are supported by one of these CIPSO +- +- +- +-Internet Draft, Expires 15 Jan 93 [PAGE 8] +- +- +- +-CIPSO INTERNET DRAFT 16 July, 1992 +- +- +- +-systems then multiple port range parameters would be needed, one set for +-each DOI supported on a particular port. +- +-The port range will usually represent the total set of labels that may +-exist on the logical network accessed through the corresponding network +-interface. It may, however, represent a subset of these labels that are +-allowed to enter the CIPSO system. +- +- +-4.2 Single Label CIPSO Hosts +- +-CIPSO implementations that support only one label are not required to +-support the parameters described above. These limited implementations are +-only required to support a NET_LABEL parameter. This parameter contains +-the CIPSO label that may be inserted in datagrams that exit the host. In +-addition, the host MUST reject any incoming datagram that has a label which +-is not equivalent to the NET_LABEL parameter. +- +- +-5. Handling Procedures +- +-This section describes the processing requirements for incoming and +-outgoing IP datagrams. Just providing the correct CIPSO label format +-is not enough. Assumptions will be made by one system on how a +-receiving system will handle the CIPSO label. Wrong assumptions may +-lead to non-interoperability or even a security incident. The +-requirements described below represent the minimal set needed for +-interoperability and that provide users some level of confidence. +-Many other requirements could be added to increase user confidence, +-however at the risk of restricting creativity and limiting vendor +-participation. +- +- +-5.1 Input Procedures +- +-All datagrams received through a network port MUST have a security label +-associated with them, either contained in the datagram or assigned to the +-receiving port. Without this label the host, gateway, or router will not +-have the information it needs to make security decisions. This security +-label will be obtained from the CIPSO if the option is present in the +-datagram. See section 4.1.2 for handling procedures for unlabeled +-datagrams. This label will be compared against the PORT (if appropriate) +-and HOST configuration parameters defined in section 3. +- +-If any field within the CIPSO option, such as the DOI identifier, is not +-recognized the IP datagram is discarded and an ICMP "parameter problem" +-(type 12) is generated and returned. The ICMP code field is set to "bad +-parameter" (code 0) and the pointer is set to the start of the CIPSO field +-that is unrecognized. +- +-If the contents of the CIPSO are valid but the security label is +-outside of the configured host or port label range, the datagram is +-discarded and an ICMP "destination unreachable" (type 3) is generated +-and returned. The code field of the ICMP is set to "communication with +-destination network administratively prohibited" (code 9) or to +- +- +- +-Internet Draft, Expires 15 Jan 93 [PAGE 9] +- +- +- +-CIPSO INTERNET DRAFT 16 July, 1992 +- +- +- +-"communication with destination host administratively prohibited" +-(code 10). The value of the code field used is dependent upon whether +-the originator of the ICMP message is acting as a CIPSO host or a CIPSO +-gateway. The recipient of the ICMP message MUST be able to handle either +-value. The same procedure is performed if a CIPSO can not be added to an +-IP packet because it is too large to fit in the IP options area. +- +-If the error is triggered by receipt of an ICMP message, the message +-is discarded and no response is permitted (consistent with general ICMP +-processing rules). +- +- +-5.1.1 Unrecognized tag types +- +-The default condition for any CIPSO implementation is that an +-unrecognized tag type MUST be treated as a "parameter problem" and +-handled as described in section 4.1. A CIPSO implementation MAY allow +-the system administrator to identify tag types that may safely be +-ignored. This capability is an allowable enhancement, not a +-requirement. +- +- +-5.1.2 Unlabeled Packets +- +-A network port may be configured to not require a CIPSO label for all +-incoming datagrams. For this configuration a CIPSO label must be +-assigned to that network port and associated with all unlabeled IP +-datagrams. This capability might be used for single level networks or +-networks that have CIPSO and non-CIPSO hosts and the non-CIPSO hosts +-all operate at the same label. +- +-If a CIPSO option is required and none is found, the datagram is +-discarded and an ICMP "parameter problem" (type 12) is generated and +-returned to the originator of the datagram. The code field of the ICMP +-is set to "option missing" (code 1) and the ICMP pointer is set to 134 +-(the value of the option type for the missing CIPSO option). +- +- +-5.2 Output Procedures +- +-A CIPSO option MUST appear only once in a datagram. Only one tag type +-from the MAC Sensitivity class MAY be included in a CIPSO option. Given +-the current set of defined tag types, this means that CIPSO labels at +-first will contain only one tag. +- +-All datagrams leaving a CIPSO system MUST meet the following condition: +- +- PORT_LABEL_MIN <= CIPSO label <= PORT_LABEL_MAX +- +-If this condition is not satisfied the datagram MUST be discarded. +-If the CIPSO system only supports one port, the HOST_LABEL_MIN and the +-HOST_LABEL_MAX parameters MAY be substituted for the PORT parameters in +-the above condition. +- +-The DOI identifier to be used for all outgoing datagrams is configured by +- +- +- +-Internet Draft, Expires 15 Jan 93 [PAGE 10] +- +- +- +-CIPSO INTERNET DRAFT 16 July, 1992 +- +- +- +-the administrator. If port level DOI identifier assignment is used, then +-the PORT_DOI configuration parameter MUST contain the DOI identifier to +-use. If network level DOI assignment is used, then the NET_DOI parameter +-MUST contain the DOI identifier to use. And if host level DOI assignment +-is employed, then the HOST_DOI parameter MUST contain the DOI identifier +-to use. A CIPSO implementation need only support one level of DOI +-assignment. +- +- +-5.3 DOI Processing Requirements +- +-A CIPSO implementation MUST support at least one DOI and SHOULD support +-multiple DOIs. System and network administrators are cautioned to +-ensure that at least one DOI is common within an IP network to allow for +-broadcasting of IP datagrams. +- +-CIPSO gateways MUST be capable of translating a CIPSO option from one +-DOI to another when forwarding datagrams between networks. For +-efficiency purposes this capability is only a desired feature for CIPSO +-routers. +- +- +-5.4 Label of ICMP Messages +- +-The CIPSO label to be used on all outgoing ICMP messages MUST be equivalent +-to the label of the datagram that caused the ICMP message. If the ICMP was +-generated due to a problem associated with the original CIPSO label then the +-following responses are allowed: +- +- a. Use the CIPSO label of the original IP datagram +- b. Drop the original datagram with no return message generated +- +-In most cases these options will have the same effect. If you can not +-interpret the label or if it is outside the label range of your host or +-interface then an ICMP message with the same label will probably not be +-able to exit the system. +- +- +-6. Assignment of DOI Identifier Numbers = +- +-Requests for assignment of a DOI identifier number should be addressed to +-the Internet Assigned Numbers Authority (IANA). +- +- +-7. Acknowledgements +- +-Much of the material in this RFC is based on (and copied from) work +-done by Gary Winiger of Sun Microsystems and published as Commercial +-IP Security Option at the INTEROP 89, Commercial IPSO Workshop. +- +- +-8. Author's Address +- +-To submit mail for distribution to members of the IETF CIPSO Working +-Group, send mail to: cipso@wdl1.wdl.loral.com. +- +- +- +-Internet Draft, Expires 15 Jan 93 [PAGE 11] +- +- +- +-CIPSO INTERNET DRAFT 16 July, 1992 +- +- +- +- +-To be added to or deleted from this distribution, send mail to: +-cipso-request@wdl1.wdl.loral.com. +- +- +-9. References +- +-RFC 1038, "Draft Revised IP Security Option", M. St. Johns, IETF, January +-1988. +- +-RFC 1108, "U.S. Department of Defense Security Options +-for the Internet Protocol", Stephen Kent, IAB, 1 March, 1991. +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-Internet Draft, Expires 15 Jan 93 [PAGE 12] +- +- +- +diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt +index 88fd7f5..171c65a 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 ++- protected_hardlinks ++- protected_symlinks + - suid_dumpable + - super-max + - super-nr +@@ -157,22 +159,68 @@ The default is 65534. + + ============================================================== + ++protected_hardlinks: ++ ++A long-standing class of security issues is the hardlink-based ++time-of-check-time-of-use race, most commonly seen in world-writable ++directories like /tmp. The common method of exploitation of this flaw ++is to cross privilege boundaries when following a given hardlink (i.e. a ++root process follows a hardlink created by another user). Additionally, ++on systems without separated partitions, this stops unauthorized users ++from "pinning" vulnerable setuid/setgid files against being upgraded by ++the administrator, or linking to special files. ++ ++When set to "0", hardlink creation behavior is unrestricted. ++ ++When set to "1" hardlinks cannot be created by users if they do not ++already own the source file, or do not have read/write access to it. ++ ++This protection is based on the restrictions in Openwall and grsecurity. ++ ++============================================================== ++ ++protected_symlinks: ++ ++A long-standing class of security issues is the symlink-based ++time-of-check-time-of-use race, most commonly seen in world-writable ++directories like /tmp. The common method of exploitation of this flaw ++is to cross privilege boundaries when following a given symlink (i.e. a ++root process follows a symlink belonging to another user). For a likely ++incomplete list of hundreds of examples across the years, please see: ++http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=/tmp ++ ++When set to "0", symlink following behavior is unrestricted. ++ ++When set to "1" symlinks are permitted to be followed only when outside ++a sticky world-writable directory, or when the uid of the symlink and ++follower match, or when the directory owner matches the symlink's owner. ++ ++This protection is based on the restrictions in Openwall and grsecurity. ++ ++============================================================== ++ + suid_dumpable: + + This value can be used to query and set the core dump mode for setuid + or otherwise protected/tainted binaries. The modes are + + 0 - (default) - traditional behaviour. Any process which has changed +- privilege levels or is execute only will not be dumped ++ privilege levels or is execute only will not be dumped. + 1 - (debug) - all processes dump core when possible. The core dump is + owned by the current user and no security is applied. This is + intended for system debugging situations only. Ptrace is unchecked. ++ This is insecure as it allows regular users to examine the memory ++ contents of privileged processes. + 2 - (suidsafe) - any binary which normally would not be dumped is dumped +- readable by root only. This allows the end user to remove +- such a dump but not access it directly. For security reasons +- core dumps in this mode will not overwrite one another or +- other files. This mode is appropriate when administrators are +- attempting to debug problems in a normal environment. ++ anyway, but only if the "core_pattern" kernel sysctl is set to ++ either a pipe handler or a fully qualified path. (For more details ++ on this limitation, see CVE-2006-2451.) This mode is appropriate ++ when administrators are attempting to debug problems in a normal ++ environment, and either have a core dump pipe handler that knows ++ to treat privileged core dumps with care, or specific directory ++ defined for catching core dumps. If a core dump happens without ++ a pipe handler or fully qualifid path, a message will be emitted ++ to syslog warning about the lack of a correct setting. + + ============================================================== + +diff --git a/MAINTAINERS b/MAINTAINERS +index 8659eba..4ea868c 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1321,6 +1321,15 @@ W: http://atl1.sourceforge.net + S: Maintained + F: drivers/net/ethernet/atheros/ + ++ALX ETHERNET DRIVERS ++M: Cloud Ren ++M: Stevent Li ++M: Wu Ken ++M: David Liu ++L: nic-devel@qualcomm.com ++W: http://wireless.kernel.org/en/users/Drivers/ethernet/alx ++F: drivers/net/ethernet/atheros/alx/ ++ + ATM + M: Chas Williams + L: linux-atm-general@lists.sourceforge.net (moderated for non-subscribers) +@@ -4901,6 +4910,13 @@ F: drivers/scsi/osd/ + F: include/scsi/osd_* + F: fs/exofs/ + ++OVERLAYFS FILESYSTEM ++M: Miklos Szeredi ++L: linux-fsdevel@vger.kernel.org ++S: Supported ++F: fs/overlayfs/* ++F: Documentation/filesystems/overlayfs.txt ++ + P54 WIRELESS DRIVER + M: Christian Lamparter + L: linux-wireless@vger.kernel.org +@@ -6026,6 +6042,14 @@ S: Supported + F: Documentation/hwmon/emc2103 + F: drivers/hwmon/emc2103.c + ++SMSC EMC2305 HARDWARE MONITOR DRIVER ++M: Reinhard Pfau ++L: lm-sensors@lm-sensors.org ++S: Maintained ++F: Documentation/hwmon/emc2305 ++F: Documentation/devicetree/bindings/hwmon/emc2305.txt ++F: drivers/hwmon/emc2305.c ++ + SMSC SCH5627 HARDWARE MONITOR DRIVER + M: Hans de Goede + L: lm-sensors@lm-sensors.org +diff --git a/Makefile b/Makefile +index 9d5fea7..6013f6e 100644 +--- a/Makefile ++++ b/Makefile +@@ -195,46 +195,6 @@ export KBUILD_BUILDHOST := $(SUBARCH) + ARCH ?= $(SUBARCH) + CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) + +-# Architecture as present in compile.h +-UTS_MACHINE := $(ARCH) +-SRCARCH := $(ARCH) +- +-# Additional ARCH settings for x86 +-ifeq ($(ARCH),i386) +- SRCARCH := x86 +-endif +-ifeq ($(ARCH),x86_64) +- SRCARCH := x86 +-endif +- +-# Additional ARCH settings for sparc +-ifeq ($(ARCH),sparc32) +- SRCARCH := sparc +-endif +-ifeq ($(ARCH),sparc64) +- SRCARCH := sparc +-endif +- +-# Additional ARCH settings for sh +-ifeq ($(ARCH),sh64) +- SRCARCH := sh +-endif +- +-# Additional ARCH settings for tile +-ifeq ($(ARCH),tilepro) +- SRCARCH := tile +-endif +-ifeq ($(ARCH),tilegx) +- SRCARCH := tile +-endif +- +-# Where to locate arch specific headers +-hdr-arch := $(SRCARCH) +- +-ifeq ($(ARCH),m68knommu) +- hdr-arch := m68k +-endif +- + KCONFIG_CONFIG ?= .config + export KCONFIG_CONFIG + +@@ -354,6 +314,44 @@ CFLAGS_KERNEL = + AFLAGS_KERNEL = + CFLAGS_GCOV = -fprofile-arcs -ftest-coverage + ++-include $(obj)/.kernelvariables ++ ++# Architecture as present in compile.h ++UTS_MACHINE := $(ARCH) ++SRCARCH := $(ARCH) ++ ++# Additional ARCH settings for x86 ++ifeq ($(ARCH),i386) ++ SRCARCH := x86 ++endif ++ifeq ($(ARCH),x86_64) ++ SRCARCH := x86 ++endif ++ ++# Additional ARCH settings for sparc ++ifeq ($(ARCH),sparc64) ++ SRCARCH := sparc ++endif ++ ++# Additional ARCH settings for sh ++ifeq ($(ARCH),sh64) ++ SRCARCH := sh ++endif ++ ++# Additional ARCH settings for tile ++ifeq ($(ARCH),tilepro) ++ SRCARCH := tile ++endif ++ifeq ($(ARCH),tilegx) ++ SRCARCH := tile ++endif ++ ++# Where to locate arch specific headers ++hdr-arch := $(SRCARCH) ++ ++ifeq ($(ARCH),m68knommu) ++ hdr-arch := m68k ++endif + + # Use LINUXINCLUDE when you must reference the include/ directory. + # Needed to be compatible with the O= option +@@ -978,7 +976,7 @@ endif + prepare2: prepare3 outputmakefile asm-generic + + prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \ +- include/config/auto.conf ++ include/config/auto.conf include/generated/package.h + $(cmd_crmodverdir) + + archprepare: archscripts prepare1 scripts_basic +@@ -1010,12 +1008,25 @@ define filechk_version.h + echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';) + endef + ++ifneq ($(DISTRIBUTION_OFFICIAL_BUILD),) ++define filechk_package.h ++ echo \#define LINUX_PACKAGE_ID \" $(DISTRIBUTOR) $(DISTRIBUTION_VERSION)\" ++endef ++else ++define filechk_package.h ++ echo \#define LINUX_PACKAGE_ID \"\" ++endef ++endif ++ + include/linux/version.h: $(srctree)/Makefile FORCE + $(call filechk,version.h) + + include/generated/utsrelease.h: include/config/kernel.release FORCE + $(call filechk,utsrelease.h) + ++include/generated/package.h: $(srctree)/Makefile FORCE ++ $(call filechk,package.h) ++ + PHONY += headerdep + headerdep: + $(Q)find $(srctree)/include/ -name '*.h' | xargs --max-args 1 \ +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 082bd36..7a06e22 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -30,6 +30,7 @@ config ARM + select HAVE_SPARSE_IRQ + select GENERIC_IRQ_SHOW + select CPU_PM if (SUSPEND || CPU_IDLE) ++ select HAVE_BPF_JIT + help + The ARM series is a line of low-power-consumption RISC chip designs + licensed by ARM Ltd and targeted at embedded applications and +@@ -161,6 +162,13 @@ config ARCH_HAS_CPUFREQ + config ARCH_HAS_CPU_IDLE_WAIT + def_bool y + ++-config ARCH_SUPPORTS_BIG_ENDIAN ++ bool ++ default y if ARCH_IXP4XX ++ help ++ Internal node to specify the architecture can run in Big Endian ++ mode. ++ + config GENERIC_HWEIGHT + bool + default y +@@ -978,6 +986,30 @@ config ARCH_ZYNQ + select USE_OF + help + Support for Xilinx Zynq ARM Cortex A9 Platform ++ ++config ARCH_IPROC ++ bool "Broadcom ARMv7 iProc boards" ++ depends on MMU ++ select CPU_V7 ++ select HAVE_CLK ++ select HAVE_SMP ++ select HAVE_MACH_CLKDEV ++ select COMMON_CLKDEV ++ select CLKDEV_LOOKUP ++ select ARM_GIC ++ select HAVE_ARM_SCU ++ select GENERIC_CLOCKEVENTS_BUILD ++ select GENERIC_CLOCKEVENTS ++ select PCI ++ select GENERIC_GPIO ++ select ARCH_REQUIRE_GPIOLIB ++ select CACHE_L2X0 ++ select ARM_AMBA ++ select ARCH_HAS_CPUFREQ ++ select MULTI_IRQ_HANDLER ++ help ++ This is a common family of Broadcom Cortex A9 based boards ++ + endchoice + + # +@@ -1013,6 +1045,8 @@ source "arch/arm/mach-iop33x/Kconfig" + + source "arch/arm/mach-iop13xx/Kconfig" + ++source "arch/arm/plat-iproc/Kconfig" ++ + source "arch/arm/mach-ixp4xx/Kconfig" + + source "arch/arm/mach-ixp2000/Kconfig" +@@ -1023,6 +1057,8 @@ source "arch/arm/mach-kirkwood/Kconfig" + + source "arch/arm/mach-ks8695/Kconfig" + ++source "arch/arm/mach-iproc/Kconfig" ++ + source "arch/arm/mach-lpc32xx/Kconfig" + + source "arch/arm/mach-msm/Kconfig" +@@ -1452,7 +1488,8 @@ config SMP + depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \ + MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \ + ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \ +- ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE || ARCH_HIGHBANK || SOC_IMX6Q ++ ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE || ARCH_HIGHBANK || SOC_IMX6Q || \ ++ ARCH_IPROC + depends on MMU + select USE_GENERIC_SMP_HELPERS + select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index 362c7ca..e11f8ee 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -198,6 +198,7 @@ machine-$(CONFIG_MACH_SPEAR310) := spear3xx + machine-$(CONFIG_MACH_SPEAR320) := spear3xx + machine-$(CONFIG_MACH_SPEAR600) := spear6xx + machine-$(CONFIG_ARCH_ZYNQ) := zynq ++machine-$(CONFIG_MACH_IPROC) := iproc + + # Platform directory name. This list is sorted alphanumerically + # by CONFIG_* macro name. +@@ -214,6 +215,7 @@ plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx samsung + plat-$(CONFIG_PLAT_S5P) := s5p samsung + plat-$(CONFIG_PLAT_SPEAR) := spear + plat-$(CONFIG_PLAT_VERSATILE) := versatile ++plat-$(CONFIG_ARCH_IPROC) := iproc + + ifeq ($(CONFIG_ARCH_EBSA110),y) + # This is what happens if you forget the IOCS16 line. +@@ -255,6 +257,7 @@ core-$(CONFIG_VFP) += arch/arm/vfp/ + + # If we have a machine-specific directory, then include it in the build. + core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ ++core-y += arch/arm/net/ + core-y += $(machdirs) $(platdirs) + + drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ +diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S +index 8c57359..6bfca86 100644 +--- a/arch/arm/boot/compressed/head.S ++++ b/arch/arm/boot/compressed/head.S +@@ -18,6 +18,7 @@ + * 100% relocatable. Any attempt to do so will result in a crash. + * Please select one of the following when turning on debugging. + */ ++#define DEBUG 1 + #ifdef DEBUG + + #if defined(CONFIG_DEBUG_ICEDCC) +diff --git a/arch/arm/boot/dts/accton_as4610_54.dts b/arch/arm/boot/dts/accton_as4610_54.dts +new file mode 100644 +index 0000000..9276c0a +--- /dev/null ++++ b/arch/arm/boot/dts/accton_as4610_54.dts +@@ -0,0 +1,250 @@ ++/* ++ * Accton AS4610 54 Device Tree Source ++ * ++ * Copyright 2015, Cumulus Networks, 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. ++ * ++ */ ++/dts-v1/; ++/include/ "helix4.dtsi" ++ ++/ { ++ model = "accton,as4610_54"; ++ compatible = "accton,as4610_54"; ++ ++ aliases { ++ serial0 = &uart0; ++ i2c-controller0 = &i2c0; ++ i2c-controller1 = &i2c1; ++ }; ++ ++ memory { ++ reg = <0x61000000 0x7f000000>; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x00>; ++ }; ++ cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x01>; ++ }; ++ }; ++ ++ localbus@1c000000 { ++ #address-cells = <0x2>; ++ #size-cells = <0x1>; ++ /* NAND Flash */ ++ ranges = < ++ 0x0 0x0 0x0 0x1c000000 0x00120000 ++ 0x1 0x0 0x0 0x1c120000 0x00040000 ++ >; ++ ++ flash@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x02000000>; ++ byteswap; ++ ++ partition@0 { ++ /* uboot */ ++ reg = <0x00000000 0x00100000>; ++ label = "uboot"; ++ }; ++ partition@1 { ++ /* uboot-env */ ++ reg = <0x00100000 0x00100000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@2 { ++ /* board_eeprom */ ++ reg = <0x00200000 0x00100000>; ++ label = "board_eeprom"; ++ }; ++ partition@3 { ++ /* shmoo */ ++ reg = <0x00300000 0x00100000>; ++ label = "shmoo"; ++ }; ++ partition@4 { ++ /* onie */ ++ reg = <0x00400000 0x00800000>; ++ label = "onie"; ++ }; ++ partition@5 { ++ /* open */ ++ reg = <0x00c00000 0x03c00000>; ++ label = "open"; ++ }; ++ partition@6 { ++ /* open2 */ ++ reg = <0x04800000 0x7d000000>; ++ label = "open2"; ++ }; ++ partition@7 { ++ /* diag */ ++ reg = <0xfec00000 0x01000000>; ++ label = "diag"; ++ }; ++ }; ++ }; ++ ++ i2c0: i2c@18038000 { ++ compatible = "iproc-smb"; ++ reg = <0x18038000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = < 127 >; ++ clock-frequency = <400000>; ++ cpld@1,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "accton,as4610-54-cpld"; ++ label = "cpld"; ++ reg = <0x30>; ++ }; ++ }; ++ ++ i2c1: i2c@1803b000 { ++ compatible = "iproc-smb"; ++ reg = <0x1803b000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = < 128 >; ++ clock-frequency = <100000>; ++ mux@70 { ++ compatible = "ti,pca9548"; ++ reg = <0x70>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ // SFP+ 1 ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port49"; ++ }; ++ }; ++ ++ // SFP+ 2 ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port50"; ++ }; ++ }; ++ ++ // SFP+ 3 ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port51"; ++ }; ++ }; ++ ++ // SFP+ 4 ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port52"; ++ }; ++ }; ++ ++ // QSFP+ STK1 ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ }; ++ }; ++ ++ // QSFP+ STK2 ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ }; ++ }; ++ ++ // PSU EEPROM ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ psu_eeprom@50 { ++ compatible = "at,24c02"; ++ reg = <0x50>; ++ label = "psu1_eeprom"; ++ read-only; ++ }; ++ psu_eeprom@51 { ++ compatible = "at,24c02"; ++ reg = <0x51>; ++ label = "psu2_eeprom"; ++ read-only; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ ++ temp@48 { ++ compatible = "nxp,lm77"; ++ reg = <0x48>; ++ }; ++ ++ rtc@68 { ++ /* Actually M41T11 */ ++ compatible = "dallas,ds1307"; ++ reg = <0x68>; ++ }; ++ ++ board_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "board_eeprom"; ++ }; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/dni_3448p.dts b/arch/arm/boot/dts/dni_3448p.dts +new file mode 100644 +index 0000000..29ce09c +--- /dev/null ++++ b/arch/arm/boot/dts/dni_3448p.dts +@@ -0,0 +1,166 @@ ++/* ++ * Delta Networks, Inc. 3448p Device Tree Source ++ * ++ * Copyright 2015, Cumulus Networks, 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. ++ * ++ */ ++/dts-v1/; ++/include/ "helix4.dtsi" ++ ++/ { ++ model = "dni,3448p"; ++ compatible = "dni,dni_3448p"; ++ ++ memory { ++ reg = <0x61000000 0x3f000000>; ++ }; ++ ++ aliases { ++ serial0 = &uart0; ++ i2c-controller0 = &i2c0; ++ i2c-controller1 = &i2c1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x00>; ++ }; ++ cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x01>; ++ }; ++ }; ++ ++ localbus@1c000000 { ++ #address-cells = <0x2>; ++ #size-cells = <0x1>; ++ /* NAND Flash */ ++ ranges = < ++ 0x0 0x0 0x0 0x1c000000 0x00120000 ++ 0x1 0x0 0x0 0x1c120000 0x00040000 ++ >; ++ ++ flash@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x02000000>; ++ byteswap; ++ ++ partition@0 { ++ /* uboot */ ++ reg = <0x00000000 0x00100000>; ++ label = "uboot"; ++ }; ++ partition@1 { ++ /* uboot-env */ ++ reg = <0x00100000 0x00400000>; ++ label = "uboot-env"; ++ env_size = <0x10000>; ++ }; ++ partition@2 { ++ /* vpd */ ++ reg = <0x00500000 0x00200000>; ++ label = "vpd"; ++ }; ++ partition@3 { ++ /* shmoo */ ++ reg = <0x00700000 0x00200000>; ++ label = "shmoo"; ++ }; ++ partition@4 { ++ /* open */ ++ reg = <0x00900000 0xf9500000>; ++ label = "open"; ++ }; ++ partition@5 { ++ /* onie */ ++ reg = <0xf9e00000 0x00c00000>; ++ label = "onie"; ++ }; ++ partition@6 { ++ /* onie2 */ ++ reg = <0xfaa00000 0x00c00000>; ++ label = "onie2"; ++ }; ++ partition@7 { ++ /* board_eeprom */ ++ reg = <0xfb600000 0x00600000>; ++ label = "board_eeprom"; ++ }; ++ partition@8 { ++ /* diags */ ++ reg = <0xfbc00000 0x02000000>; ++ label = "diag"; ++ }; ++ partition@9 { ++ /* diags2 */ ++ reg = <0xfdc00000 0x02000000>; ++ label = "diag2"; ++ }; ++ }; ++ cpld@1,0 { ++ compatible = "dni,3448p-cpld"; ++ reg = <0x1 0x0 0x00040000>; ++ }; ++ }; ++ ++ i2c0: i2c@18038000 { ++ compatible = "iproc-smb"; ++ reg = <0x18038000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <0x0 127 0x0>; ++ clock-frequency = <100000>; ++ rtc@68 { ++ compatible = "stm,m41st85"; ++ reg = <0x68>; ++ }; ++ tmon@49 { ++ compatible = "ti,tmp75"; ++ reg = <0x49>; ++ }; ++ tmon@4a { ++ compatible = "ti,tmp75"; ++ reg = <0x4a>; ++ }; ++ CPLD1@1,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "dni,3448p-cpld"; ++ label = "cpld"; ++ reg = <0x28>; ++ }; ++ }; ++ ++ i2c1: i2c@1803b000 { ++ compatible = "iproc-smb"; ++ reg = <0x1803b000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <0x0 128 0x0>; ++ clock-frequency = <100000>; ++ ++ fan@2c { ++ compatible = "maxim,max6639"; ++ reg = <0x2c>; ++ }; ++ psumux@01 { ++ compatible = "3448p-psu-mux"; ++ reg = <0x01>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/helix4.dtsi b/arch/arm/boot/dts/helix4.dtsi +new file mode 100644 +index 0000000..1a7ce9e +--- /dev/null ++++ b/arch/arm/boot/dts/helix4.dtsi +@@ -0,0 +1,59 @@ ++/include/ "skeleton.dtsi" ++ ++/ { ++ interrupt-parent = <&gic>; ++ ++ chipcommonA { ++ compatible = "simple-bus"; ++ ranges = <0x00000000 0x18000000 0x00001000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ uart0: serial@0300 { ++ compatible = "ns16550"; ++ reg = <0x0300 0x100>; ++ interrupts = <123>; ++ clock-frequency = <100000000>; ++ status = "enabled"; ++ }; ++ }; ++ ++ mpcore { ++ compatible = "simple-bus"; ++ ranges = <0x00000000 0x19020000 0x00003000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ scu@0000 { ++ compatible = "arm,cortex-a9-scu"; ++ reg = <0x0000 0x100>; ++ }; ++ ++ gic: interrupt-controller@1000 { ++ compatible = "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ reg = <0x1000 0x1000>, ++ <0x0100 0x100>; ++ }; ++ ++ L2: cache-controller@2000 { ++ compatible = "arm,pl310-cache"; ++ reg = <0x2000 0x1000>; ++ cache-unified; ++ cache-level = <2>; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ clk_periph: periph { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <400000000>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/kirkwood-dreamplug.dts b/arch/arm/boot/dts/kirkwood-dreamplug.dts +new file mode 100644 +index 0000000..a5376b8 +--- /dev/null ++++ b/arch/arm/boot/dts/kirkwood-dreamplug.dts +@@ -0,0 +1,24 @@ ++/dts-v1/; ++ ++/include/ "kirkwood.dtsi" ++ ++/ { ++ model = "Globalscale Technologies Dreamplug"; ++ compatible = "globalscale,dreamplug-003-ds2001", "globalscale,dreamplug", "mrvl,kirkwood-88f6281", "mrvl,kirkwood"; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x00000000 0x20000000>; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200n8 earlyprintk"; ++ }; ++ ++ ocp@f1000000 { ++ serial@12000 { ++ clock-frequency = <200000000>; ++ status = "ok"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/kirkwood-iconnect.dts b/arch/arm/boot/dts/kirkwood-iconnect.dts +new file mode 100644 +index 0000000..1ba75d4 +--- /dev/null ++++ b/arch/arm/boot/dts/kirkwood-iconnect.dts +@@ -0,0 +1,26 @@ ++/dts-v1/; ++ ++/include/ "kirkwood.dtsi" ++ ++/ { ++ model = "Iomega Iconnect"; ++ compatible = "iom,iconnect-1.1", "iom,iconnect", "mrvl,kirkwood-88f6281", "mrvl,kirkwood"; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x00000000 0x10000000>; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200n8 earlyprintk mtdparts=orion_nand:0xc0000@0x0(uboot),0x20000@0xa0000(env),0x300000@0x100000(zImage),0x300000@0x540000(initrd),0x1f400000@0x980000(boot)"; ++ linux,initrd-start = <0x4500040>; ++ linux,initrd-end = <0x4800000>; ++ }; ++ ++ ocp@f1000000 { ++ serial@12000 { ++ clock-frequency = <200000000>; ++ status = "ok"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi +new file mode 100644 +index 0000000..3474ef8 +--- /dev/null ++++ b/arch/arm/boot/dts/kirkwood.dtsi +@@ -0,0 +1,36 @@ ++/include/ "skeleton.dtsi" ++ ++/ { ++ compatible = "mrvl,kirkwood"; ++ ++ ocp@f1000000 { ++ compatible = "simple-bus"; ++ ranges = <0 0xf1000000 0x1000000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ serial@12000 { ++ compatible = "ns16550a"; ++ reg = <0x12000 0x100>; ++ reg-shift = <2>; ++ interrupts = <33>; ++ /* set clock-frequency in board dts */ ++ status = "disabled"; ++ }; ++ ++ serial@12100 { ++ compatible = "ns16550a"; ++ reg = <0x12100 0x100>; ++ reg-shift = <2>; ++ interrupts = <34>; ++ /* set clock-frequency in board dts */ ++ status = "disabled"; ++ }; ++ ++ rtc@10300 { ++ compatible = "mrvl,kirkwood-rtc", "mrvl,orion-rtc"; ++ reg = <0x10300 0x20>; ++ interrupts = <53>; ++ }; ++ }; ++}; +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 410a546..46d9ae8 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -40,6 +40,8 @@ + #include + + #include ++#include ++#include + #include + #include + +@@ -215,6 +217,29 @@ static int gic_set_wake(struct irq_data *d, unsigned int on) + #define gic_set_wake NULL + #endif + ++asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) ++{ ++ u32 irqstat, irqnr; ++ ++ do { ++ irqstat = readl_relaxed(gic_cpu_base_addr + GIC_CPU_INTACK); ++ irqnr = irqstat & ~0x1c00; ++ ++ if (likely(irqnr > 15 && irqnr < 1021)) { ++ handle_IRQ(irqnr, regs); ++ continue; ++ } ++ if (irqnr < 16) { ++ writel_relaxed(irqstat, gic_cpu_base_addr + GIC_CPU_EOI); ++#ifdef CONFIG_SMP ++ do_IPI(irqnr, regs); ++#endif ++ continue; ++ } ++ break; ++ } while (1); ++} ++ + static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) + { + struct gic_chip_data *chip_data = irq_get_handler_data(irq); +diff --git a/arch/arm/configs/iproc_defconfig b/arch/arm/configs/iproc_defconfig +new file mode 100644 +index 0000000..c401047 +--- /dev/null ++++ b/arch/arm/configs/iproc_defconfig +@@ -0,0 +1,2425 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.6.5 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_GENERIC_GPIO=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_VECTORS_BASE=0xffff0000 ++CONFIG_ARM_PATCH_PHYS_VIRT=y ++CONFIG_GENERIC_BUG=y ++CONFIG_HAVE_IRQ_WORK=y ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_LOCALVERSION_AUTO=y ++CONFIG_HAVE_KERNEL_GZIP=y ++CONFIG_HAVE_KERNEL_LZMA=y ++CONFIG_HAVE_KERNEL_XZ=y ++CONFIG_HAVE_KERNEL_LZO=y ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO 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_BSD_PROCESS_ACCT is not set ++# CONFIG_FHANDLE is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_AUDIT is not set ++CONFIG_HAVE_GENERIC_HARDIRQS=y ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_KTIME_SCALAR=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++# CONFIG_HIGH_RES_TIMERS is not set ++ ++# ++# RCU Subsystem ++# ++CONFIG_TREE_RCU=y ++# CONFIG_PREEMPT_RCU 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_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=14 ++# 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_ROOT_UID=0 ++CONFIG_INITRAMFS_ROOT_GID=0 ++# CONFIG_RD_GZIP is not set ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++CONFIG_INITRAMFS_COMPRESSION_NONE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_EXPERT=y ++CONFIG_UID16=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++# CONFIG_ELF_CORE is not set ++# CONFIG_BASE_FULL is not set ++CONFIG_FUTEX=y ++# CONFIG_EPOLL is not set ++# CONFIG_SIGNALFD is not set ++# CONFIG_TIMERFD is not set ++# CONFIG_EVENTFD is not set ++# CONFIG_SHMEM is not set ++# CONFIG_AIO is not set ++CONFIG_EMBEDDED=y ++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_PCI_QUIRKS=y ++# 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_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=y ++CONFIG_HAVE_DMA_CONTIGUOUS=y ++CONFIG_USE_GENERIC_SMP_HELPERS=y ++CONFIG_GENERIC_SMP_IDLE_THREAD=y ++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y ++CONFIG_HAVE_CLK=y ++CONFIG_HAVE_DMA_API_DEBUG=y ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y ++ ++# ++# GCOV-based kernel profiling ++# ++# CONFIG_GCOV_KERNEL is not set ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_RT_MUTEXES=y ++CONFIG_BASE_SMALL=1 ++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_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 ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_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 is not set ++# CONFIG_SYSV68_PARTITION is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq" ++# CONFIG_INLINE_SPIN_TRYLOCK is not set ++# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK is not set ++# CONFIG_INLINE_SPIN_LOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQ is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set ++# CONFIG_INLINE_SPIN_UNLOCK_BH is not set ++CONFIG_INLINE_SPIN_UNLOCK_IRQ=y ++# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_READ_TRYLOCK is not set ++# CONFIG_INLINE_READ_LOCK is not set ++# CONFIG_INLINE_READ_LOCK_BH is not set ++# CONFIG_INLINE_READ_LOCK_IRQ is not set ++# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set ++CONFIG_INLINE_READ_UNLOCK=y ++# CONFIG_INLINE_READ_UNLOCK_BH is not set ++CONFIG_INLINE_READ_UNLOCK_IRQ=y ++# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_WRITE_TRYLOCK is not set ++# CONFIG_INLINE_WRITE_LOCK is not set ++# CONFIG_INLINE_WRITE_LOCK_BH is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQ is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set ++CONFIG_INLINE_WRITE_UNLOCK=y ++# CONFIG_INLINE_WRITE_UNLOCK_BH is not set ++CONFIG_INLINE_WRITE_UNLOCK_IRQ=y ++# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set ++CONFIG_MUTEX_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCMRING is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CNS3XXX is not set ++# CONFIG_ARCH_GEMINI is not set ++# CONFIG_ARCH_PRIMA2 is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X 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_MVEBU is not set ++# CONFIG_ARCH_DOVE is not set ++# CONFIG_ARCH_KIRKWOOD is not set ++# CONFIG_ARCH_LPC32XX 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_TEGRA is not set ++# CONFIG_ARCH_PICOXCELL is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_MSM is not set ++# CONFIG_ARCH_SHMOBILE 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_S5P64X0 is not set ++# CONFIG_ARCH_S5PC100 is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_VT8500 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARCH_IPROC=y ++CONFIG_BCM_ZRELADDR=0x61008000 ++# CONFIG_GPIO_PCA953X is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++ ++# ++# Broadcom IPROC architecture based implementations ++# ++# CONFIG_ARCH_NORTHSTAR is not set ++CONFIG_MACH_IPROC=y ++CONFIG_GP_TIMER_COMPARATOR_LOAD_DELAY=y ++CONFIG_IPROC_DCACHE_INVALIDATION=y ++# CONFIG_IPROC_TIMER_UNIT_TESTS is not set ++# CONFIG_IPROC_SW_RESET_RECORD is not set ++# CONFIG_BRCM_PROP_MODULES is not set ++# CONFIG_BCM_STM is not set ++CONFIG_BCM_PARAMS_PHYS=0x61000000 ++CONFIG_BCM_RAM_BASE=0x60000000 ++CONFIG_BCM_RAM_START_RESERVED_SIZE=0x200000 ++ ++# ++# Broadcom iProc Drivers ++# ++# CONFIG_IPROC_CCB_TIMER is not set ++# CONFIG_IPROC_RNG is not set ++CONFIG_IPROC_MDIO=y ++# CONFIG_IPROC_GSIO_SPI is not set ++# CONFIG_IPROC_SD is not set ++# CONFIG_IPROC_DMA is not set ++CONFIG_IPROC_GPIO=y ++CONFIG_IPROC_QSPI=y ++CONFIG_IPROC_QSPI_SINGLE_MODE=y ++# CONFIG_IPROC_QSPI_DUAL_MODE is not set ++# CONFIG_IPROC_QSPI_QUAD_MODE is not set ++CONFIG_IPROC_QSPI_MAX_HZ=62500000 ++CONFIG_IPROC_MTD_NAND=y ++# CONFIG_IPROC_MTD_NAND_USE_JFFS2 is not set ++# CONFIG_IPROC_MTD_NOR is not set ++# CONFIG_IPROC_PMU is not set ++# CONFIG_IPROC_PWM is not set ++CONFIG_IPROC_USB2H=y ++CONFIG_USB_EHCI_BCM=y ++CONFIG_USB_OHCI_BCM=y ++# CONFIG_IPROC_USB3H is not set ++CONFIG_IPROC_USB2D=m ++CONFIG_IPROC_PCIE=y ++# CONFIG_IPROC_PCIE_AER is not set ++CONFIG_IPROC_GMAC=y ++ ++# ++# Broadcom HND network devices ++# ++CONFIG_HND=y ++CONFIG_ET=y ++CONFIG_ET_47XX=y ++CONFIG_ET_ALL_PASSIVE_ON=y ++# CONFIG_ET_ALL_PASSIVE_RUNTIME is not set ++# CONFIG_BCM_CTF is not set ++# CONFIG_BCM_IPROC_GMAC_ACP is not set ++# CONFIG_WL_EMULATOR is not set ++# CONFIG_BCM57XX is not set ++# CONFIG_WL is not set ++# CONFIG_WL_USBAP is not set ++CONFIG_WL_AP="wlconfig_lx_router_ap" ++CONFIG_WL_AP_SDSTD="wlconfig_lx_router_ap_sdstd" ++CONFIG_WL_STA="wlconfig_lx_router_sta" ++CONFIG_WL_APSTA="wlconfig_lx_router_apsta" ++CONFIG_WL_AP_ONCHIP_G="wlconfig_lx_router_ap_1chipG" ++CONFIG_WL_STA_ONCHIP_G="wlconfig_lx_router_sta_1chipG" ++CONFIG_WL_HIGH="wlconfig_lx_router_high" ++# CONFIG_EMF is not set ++# CONFIG_IPROC_SND is not set ++CONFIG_IPROC_I2C=y ++# CONFIG_IPROC_SRA is not set ++# CONFIG_IPROC_TDM is not set ++ ++# ++# Broadcom iProc GPL Drivers ++# ++# CONFIG_IPROC_SND_CODEC_WM8955 is not set ++# CONFIG_IPROC_SND_CODEC_WM8750 is not set ++CONFIG_IPROC_CCB_WDT=y ++ ++# ++# iProc SoC based Machine types ++# ++# CONFIG_MACH_NS is not set ++# CONFIG_MACH_HX4 is not set ++# CONFIG_MACH_HR2 is not set ++# CONFIG_MACH_NSP is not set ++# CONFIG_MACH_KT2 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_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_OUTER_CACHE=y ++CONFIG_OUTER_CACHE_SYNC=y ++CONFIG_CACHE_L2X0=y ++CONFIG_CACHE_PL310=y ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_ARM_NR_BANKS=8 ++CONFIG_CPU_HAS_PMU=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_458693 is not set ++# CONFIG_ARM_ERRATA_460075 is not set ++# CONFIG_ARM_ERRATA_742230 is not set ++# CONFIG_ARM_ERRATA_742231 is not set ++# CONFIG_PL310_ERRATA_588369 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_PL310_ERRATA_727915 is not set ++# CONFIG_ARM_ERRATA_743622 is not set ++# CONFIG_ARM_ERRATA_751472 is not set ++# CONFIG_PL310_ERRATA_753970 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_PL310_ERRATA_769419 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++CONFIG_ARM_GIC=y ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_ARCH_SUPPORTS_MSI=y ++CONFIG_PCI_MSI=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_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_ARM_ARCH_TIMER is not set ++CONFIG_HAVE_ARM_TWD=y ++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_LOCAL_TIMERS=y ++CONFIG_ARCH_NR_GPIO=0 ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++CONFIG_HZ=100 ++# 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 is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++# CONFIG_COMPACTION is not set ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_VIRT_TO_BUS=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_CROSS_MEMORY_ATTACH=y ++# CONFIG_CLEANCACHE 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_CC_STACKPROTECTOR is not set ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++ ++# ++# Boot options ++# ++# CONFIG_USE_OF is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyS0,115200n8 maxcpus=2 mem=512M" ++CONFIG_CMDLINE_FROM_BOOTLOADER=y ++# CONFIG_CMDLINE_EXTEND is not set ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++# 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_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_HAVE_AOUT=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++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_CLK=y ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++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=y ++# CONFIG_IP_FIB_TRIE_STATS is not set ++CONFIG_IP_MULTIPLE_TABLES=y ++# CONFIG_IP_ROUTE_MULTIPATH is not set ++# CONFIG_IP_ROUTE_VERBOSE is not set ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_IP_PNP_RARP is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++# CONFIG_IP_MROUTE is not set ++CONFIG_ARPD=y ++# CONFIG_SYN_COOKIES 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_LRO is not set ++# CONFIG_INET_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_NETWORK_SECMARK is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++CONFIG_NETFILTER_DEBUG=y ++CONFIG_NETFILTER_ADVANCED=y ++CONFIG_BRIDGE_NETFILTER=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_NETLINK=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++CONFIG_NETFILTER_NETLINK_QUEUE=y ++CONFIG_NETFILTER_NETLINK_LOG=y ++CONFIG_NF_CONNTRACK=y ++CONFIG_NF_CONNTRACK_MARK=y ++CONFIG_NF_CONNTRACK_PROCFS=y ++# CONFIG_NF_CONNTRACK_EVENTS is not set ++# CONFIG_NF_CONNTRACK_TIMEOUT is not set ++# CONFIG_NF_CONNTRACK_TIMESTAMP is not set ++# CONFIG_NF_CT_PROTO_DCCP is not set ++# CONFIG_NF_CT_PROTO_SCTP is not set ++# CONFIG_NF_CT_PROTO_UDPLITE is not set ++# CONFIG_NF_CONNTRACK_AMANDA is not set ++CONFIG_NF_CONNTRACK_FTP=y ++# CONFIG_NF_CONNTRACK_H323 is not set ++# CONFIG_NF_CONNTRACK_IRC is not set ++# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set ++# CONFIG_NF_CONNTRACK_SNMP is not set ++# CONFIG_NF_CONNTRACK_PPTP is not set ++# CONFIG_NF_CONNTRACK_SANE is not set ++# CONFIG_NF_CONNTRACK_SIP is not set ++CONFIG_NF_CONNTRACK_TFTP=y ++# CONFIG_NF_CT_NETLINK is not set ++# CONFIG_NF_CT_NETLINK_TIMEOUT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set ++CONFIG_NETFILTER_TPROXY=y ++CONFIG_NETFILTER_XTABLES=y ++ ++# ++# Xtables combined modules ++# ++CONFIG_NETFILTER_XT_MARK=y ++CONFIG_NETFILTER_XT_CONNMARK=y ++ ++# ++# Xtables targets ++# ++# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set ++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set ++# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set ++# CONFIG_NETFILTER_XT_TARGET_CT is not set ++# CONFIG_NETFILTER_XT_TARGET_DSCP is not set ++CONFIG_NETFILTER_XT_TARGET_HL=y ++# CONFIG_NETFILTER_XT_TARGET_HMARK is not set ++# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set ++# CONFIG_NETFILTER_XT_TARGET_LOG is not set ++# CONFIG_NETFILTER_XT_TARGET_MARK is not set ++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set ++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set ++# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set ++# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set ++# CONFIG_NETFILTER_XT_TARGET_TEE is not set ++# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set ++# CONFIG_NETFILTER_XT_TARGET_TRACE is not set ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=y ++# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set ++ ++# ++# Xtables matches ++# ++# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set ++# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set ++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set ++# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set ++# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=y ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y ++# CONFIG_NETFILTER_XT_MATCH_CPU is not set ++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set ++# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set ++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set ++CONFIG_NETFILTER_XT_MATCH_ECN=y ++# CONFIG_NETFILTER_XT_MATCH_ESP is not set ++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set ++# CONFIG_NETFILTER_XT_MATCH_HELPER is not set ++CONFIG_NETFILTER_XT_MATCH_HL=y ++# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set ++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set ++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set ++# CONFIG_NETFILTER_XT_MATCH_MAC is not set ++# CONFIG_NETFILTER_XT_MATCH_MARK is not set ++# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set ++# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set ++# CONFIG_NETFILTER_XT_MATCH_OSF is not set ++# CONFIG_NETFILTER_XT_MATCH_OWNER is not set ++# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set ++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set ++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set ++# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set ++# CONFIG_NETFILTER_XT_MATCH_REALM is not set ++# CONFIG_NETFILTER_XT_MATCH_RECENT is not set ++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set ++# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set ++CONFIG_NETFILTER_XT_MATCH_STATE=y ++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set ++# CONFIG_NETFILTER_XT_MATCH_STRING is not set ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=y ++# CONFIG_NETFILTER_XT_MATCH_TIME is not set ++# CONFIG_NETFILTER_XT_MATCH_U32 is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++CONFIG_NF_DEFRAG_IPV4=y ++CONFIG_NF_CONNTRACK_IPV4=y ++CONFIG_NF_CONNTRACK_PROC_COMPAT=y ++CONFIG_IP_NF_QUEUE=y ++CONFIG_IP_NF_IPTABLES=y ++CONFIG_IP_NF_MATCH_AH=y ++CONFIG_IP_NF_MATCH_ECN=y ++# CONFIG_IP_NF_MATCH_RPFILTER is not set ++CONFIG_IP_NF_MATCH_TTL=y ++CONFIG_IP_NF_FILTER=y ++CONFIG_IP_NF_TARGET_REJECT=y ++CONFIG_IP_NF_TARGET_ULOG=y ++CONFIG_NF_NAT=y ++CONFIG_NF_NAT_NEEDED=y ++CONFIG_IP_NF_TARGET_MASQUERADE=y ++CONFIG_IP_NF_TARGET_NETMAP=y ++CONFIG_IP_NF_TARGET_REDIRECT=y ++CONFIG_NF_NAT_FTP=y ++# CONFIG_NF_NAT_IRC is not set ++CONFIG_NF_NAT_TFTP=y ++# CONFIG_NF_NAT_AMANDA is not set ++# CONFIG_NF_NAT_PPTP is not set ++# CONFIG_NF_NAT_H323 is not set ++# CONFIG_NF_NAT_SIP is not set ++CONFIG_IP_NF_MANGLE=y ++# CONFIG_IP_NF_TARGET_CLUSTERIP is not set ++CONFIG_IP_NF_TARGET_ECN=y ++CONFIG_IP_NF_TARGET_TTL=y ++CONFIG_IP_NF_RAW=y ++CONFIG_IP_NF_ARPTABLES=y ++CONFIG_IP_NF_ARPFILTER=y ++CONFIG_IP_NF_ARP_MANGLE=y ++# CONFIG_BRIDGE_NF_EBTABLES 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_STP=y ++CONFIG_GARP=y ++CONFIG_BRIDGE=y ++CONFIG_BRIDGE_IGMP_SNOOPING=y ++# CONFIG_NET_DSA is not set ++CONFIG_VLAN_8021Q=y ++CONFIG_VLAN_8021Q_GVRP=y ++# CONFIG_DECNET is not set ++CONFIG_LLC=y ++# 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_WAN_ROUTER 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_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=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_FIB_RULES=y ++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_PATH="/sbin/mdev" ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++CONFIG_FIRMWARE_IN_KERNEL=y ++CONFIG_EXTRA_FIRMWARE="" ++# 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_DMA_SHARED_BUFFER is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=32 ++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 ++CONFIG_CMA_AREAS=7 ++# CONFIG_CONNECTOR is not set ++CONFIG_MTD=y ++# CONFIG_MTD_TESTS is not set ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++# CONFIG_MTD_AR7_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++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 ++ ++# ++# 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=y ++CONFIG_M25PXX_USE_FAST_READ=y ++CONFIG_M25PXX_STAY_IN_3BYTE_MODE=y ++# CONFIG_MTD_SST25L is not set ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++# 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_VERIFY_WRITE is not set ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_MUSEUM_IDS is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO 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_PLATFORM is not set ++# CONFIG_MTD_ALAUDA is not set ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR flash memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_RESERVE=2 ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_DA 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 ++ ++# ++# DRBD disabled because PROC_FS, INET or CONNECTOR not selected ++# ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_BLK_DEV_SX8 is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=4096 ++CONFIG_BLK_DEV_XIP=y ++# 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_ATMEL_PWM 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_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_BMP085_I2C is not set ++# CONFIG_BMP085_SPI is not set ++# CONFIG_PCH_PHUB is not set ++# CONFIG_USB_SWITCH_FSA9480 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 ++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_TGT=y ++# CONFIG_SCSI_NETLINK is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=y ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++CONFIG_CHR_DEV_SG=y ++# CONFIG_CHR_DEV_SCH is not set ++CONFIG_SCSI_MULTI_LUN=y ++CONFIG_SCSI_CONSTANTS=y ++CONFIG_SCSI_LOGGING=y ++# 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_SCSI_BNX2X_FCOE 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_AIC7XXX_OLD 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_DPT_I2O is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_LIBFC is not set ++# CONFIG_LIBFCOE is not set ++# CONFIG_FCOE 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_FC is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_LPFC is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_DC390T is not set ++# CONFIG_SCSI_NSP32 is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_SRP is not set ++# CONFIG_SCSI_BFA_FC 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_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_MII is not set ++# CONFIG_NET_TEAM is not set ++# CONFIG_MACVLAN 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_ARCNET is not set ++ ++# ++# CAIF transport 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_ALTEON=y ++# CONFIG_ACENIC is not set ++CONFIG_NET_VENDOR_AMD=y ++# CONFIG_AMD8111_ETH is not set ++# CONFIG_PCNET32 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_NET_VENDOR_BROADCOM=y ++# CONFIG_B44 is not set ++# CONFIG_BNX2 is not set ++# CONFIG_CNIC is not set ++CONFIG_TIGON3=y ++# CONFIG_BNX2X is not set ++CONFIG_NET_VENDOR_BROCADE=y ++# CONFIG_BNA is not set ++# CONFIG_NET_CALXEDA_XGMAC 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_CIRRUS=y ++# CONFIG_CS89x0 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_EXAR=y ++# CONFIG_S2IO is not set ++# CONFIG_VXGE is not set ++CONFIG_NET_VENDOR_FARADAY=y ++# CONFIG_FTMAC100 is not set ++# CONFIG_FTGMAC100 is not set ++CONFIG_NET_VENDOR_HP=y ++# CONFIG_HP100 is not set ++CONFIG_NET_VENDOR_INTEL=y ++# CONFIG_E100 is not set ++# CONFIG_E1000 is not set ++CONFIG_E1000E=y ++# CONFIG_IGB is not set ++# CONFIG_IGBVF is not set ++# CONFIG_IXGB is not set ++# CONFIG_IXGBE is not set ++CONFIG_NET_VENDOR_I825XX=y ++# CONFIG_IP1000 is not set ++# CONFIG_JME is not set ++CONFIG_NET_VENDOR_MARVELL=y ++# CONFIG_SKGE is not set ++# CONFIG_SKY2 is not set ++CONFIG_NET_VENDOR_MELLANOX=y ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX4_CORE is not set ++CONFIG_NET_VENDOR_MICREL=y ++# CONFIG_KS8851 is not set ++# CONFIG_KS8851_MLL is not set ++# CONFIG_KSZ884X_PCI is not set ++CONFIG_NET_VENDOR_MICROCHIP=y ++# CONFIG_ENC28J60 is not set ++CONFIG_NET_VENDOR_MYRI=y ++# CONFIG_MYRI10GE is not set ++# CONFIG_FEALNX is not set ++CONFIG_NET_VENDOR_NATSEMI=y ++# CONFIG_NATSEMI is not set ++# CONFIG_NS83820 is not set ++CONFIG_NET_VENDOR_8390=y ++# CONFIG_AX88796 is not set ++# CONFIG_NE2K_PCI 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_NET_VENDOR_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_R8169 is not set ++CONFIG_NET_VENDOR_RDC=y ++# CONFIG_R6040 is not set ++CONFIG_NET_VENDOR_SEEQ=y ++# CONFIG_SEEQ8005 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=y ++# CONFIG_SMC91X is not set ++# CONFIG_EPIC100 is not set ++# CONFIG_SMC911X is not set ++# CONFIG_SMSC911X is not set ++# CONFIG_SMSC9420 is not set ++CONFIG_NET_VENDOR_STMICRO=y ++# CONFIG_STMMAC_ETH 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_TEHUTI=y ++# CONFIG_TEHUTI is not set ++CONFIG_NET_VENDOR_TI=y ++# CONFIG_TLAN is not set ++CONFIG_NET_VENDOR_VIA=y ++# CONFIG_VIA_RHINE is not set ++# CONFIG_VIA_VELOCITY is not set ++CONFIG_NET_VENDOR_WIZNET=y ++# CONFIG_WIZNET_W5100 is not set ++# CONFIG_WIZNET_W5300 is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AMD_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_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_MICREL_KS8995MA is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++ ++# ++# USB Network Adapters ++# ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_ATMEL is not set ++# CONFIG_PRISM54 is not set ++# CONFIG_USB_ZD1201 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_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 is not set ++# CONFIG_INPUT_EVDEV is not set ++# 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_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_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_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_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_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_GAMEPORT is not set ++ ++# ++# Character devices ++# ++# CONFIG_VT 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_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_PCI=y ++CONFIG_SERIAL_8250_NR_UARTS=2 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++CONFIG_SERIAL_8250_EXTENDED=y ++# CONFIG_SERIAL_8250_MANY_PORTS is not set ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_DETECT_IRQ=y ++CONFIG_SERIAL_8250_RSA=y ++# CONFIG_SERIAL_8250_EM is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX3107 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_TIMBERDALE 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_XILINX_PS_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=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_HW_RANDOM_ATMEL is not set ++# CONFIG_HW_RANDOM_EXYNOS 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_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 ++# ++ ++# ++# 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_EG20T is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_INTEL_MID 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_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_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_GPIO is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_PL022 is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_TOPCLIFF_PCH 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 is not set ++# CONFIG_SPI_TLE62X0 is not set ++# CONFIG_HSI is not set ++ ++# ++# PPS support ++# ++# CONFIG_PPS is not set ++ ++# ++# PPS generators support ++# ++ ++# ++# PTP clock support ++# ++ ++# ++# Enable Device Drivers -> PPS to see the PTP clock options. ++# ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_PL061 is not set ++# CONFIG_GPIO_VX855 is not set ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX7300 is not set ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_PCF857X is not set ++# CONFIG_GPIO_SX150X is not set ++# CONFIG_GPIO_ADP5588 is not set ++ ++# ++# PCI GPIO expanders: ++# ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_AMD8111 is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_RDC321X is not set ++ ++# ++# 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: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++CONFIG_WATCHDOG=y ++CONFIG_WATCHDOG_CORE=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++# CONFIG_ARM_SP805_WATCHDOG is not set ++# CONFIG_DW_WATCHDOG is not set ++# CONFIG_MPCORE_WATCHDOG is not set ++# CONFIG_MAX63XX_WATCHDOG is not set ++# CONFIG_ALIM7101_WDT is not set ++# CONFIG_I6300ESB_WDT is not set ++ ++# ++# PCI-based Watchdog Cards ++# ++# CONFIG_PCIPCWATCHDOG is not set ++# CONFIG_WDTPCI is not set ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG 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_88PM860X is not set ++# CONFIG_MFD_88PM800 is not set ++# CONFIG_MFD_88PM805 is not set ++# CONFIG_MFD_SM501 is not set ++# CONFIG_MFD_ASIC3 is not set ++# CONFIG_HTC_EGPIO is not set ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_MFD_LM3533 is not set ++# CONFIG_TPS6105X is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_TPS6507X is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912_I2C is not set ++# CONFIG_MFD_TPS65912_SPI is not set ++# CONFIG_TWL4030_CORE is not set ++# CONFIG_TWL6040_CORE is not set ++# CONFIG_MFD_STMPE 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_PMIC_DA903X is not set ++# CONFIG_MFD_DA9052_SPI is not set ++# CONFIG_MFD_DA9052_I2C is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_MAX77686 is not set ++# CONFIG_MFD_MAX77693 is not set ++# CONFIG_MFD_MAX8925 is not set ++# CONFIG_MFD_MAX8997 is not set ++# CONFIG_MFD_MAX8998 is not set ++# CONFIG_MFD_SEC_CORE 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_PCF50633 is not set ++# CONFIG_MFD_MC13XXX_SPI is not set ++# CONFIG_MFD_MC13XXX_I2C is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_EZX_PCAP is not set ++# CONFIG_MFD_TIMBERDALE is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_MFD_RDC321X is not set ++# CONFIG_MFD_JANZ_CMODIO is not set ++# CONFIG_MFD_VX855 is not set ++# CONFIG_MFD_WL1273_CORE is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_AAT2870_CORE is not set ++# CONFIG_MFD_RC5T583 is not set ++# CONFIG_MFD_PALMAS is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_VGA_ARB is not set ++# CONFIG_DRM is not set ++# CONFIG_STUB_POULSBO is not set ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++# CONFIG_FB is not set ++# CONFIG_EXYNOS_VIDEO is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++CONFIG_HIDRAW=y ++# 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_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_EZKEY 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_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO_TPKBD is not set ++# CONFIG_HID_LOGITECH 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_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_SONY is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_SUNPLUS 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_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV is not set ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB_ARCH_HAS_EHCI=y ++CONFIG_USB_ARCH_HAS_XHCI=y ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_COMMON=y ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB=y ++CONFIG_USB_DEBUG=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DYNAMIC_MINORS=y ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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=y ++# CONFIG_USB_EHCI_TT_NEWSCHED 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_OHCI_HCD is not set ++# CONFIG_USB_EHCI_HCD_PLATFORM 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_CHIPIDEA 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=y ++# 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=y ++# CONFIG_USB_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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_ISIGHTFW is not set ++# CONFIG_USB_YUREX is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_ISP1301 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_FUSB300 is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_MV_UDC is not set ++# CONFIG_USB_M66592 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_DUMMY_HCD 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_FILE_STORAGE 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 ++ ++# ++# OTG and related infrastructure ++# ++# CONFIG_USB_GPIO_VBUS is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_NOP_USB_XCEIV 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 is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++CONFIG_DMADEVICES=y ++CONFIG_DMADEVICES_DEBUG=y ++CONFIG_DMADEVICES_VDEBUG=y ++ ++# ++# DMA Devices ++# ++# CONFIG_AMBA_PL08X is not set ++# CONFIG_DW_DMAC is not set ++# CONFIG_TIMB_DMA is not set ++# CONFIG_PL330_DMA is not set ++# CONFIG_AUXDISPLAY is not set ++# CONFIG_UIO is not set ++ ++# ++# Virtio drivers ++# ++# CONFIG_VIRTIO_PCI is not set ++# CONFIG_VIRTIO_BALLOON is not set ++# CONFIG_VIRTIO_MMIO is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++# CONFIG_STAGING is not set ++CONFIG_CLKDEV_LOOKUP=y ++CONFIG_HAVE_MACH_CLKDEV=y ++ ++# ++# Hardware Spinlock drivers ++# ++CONFIG_IOMMU_SUPPORT=y ++ ++# ++# Remoteproc drivers (EXPERIMENTAL) ++# ++ ++# ++# Rpmsg drivers (EXPERIMENTAL) ++# ++# CONFIG_VIRT_DRIVERS 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_VME_BUS is not set ++# CONFIG_PWM is not set ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_EXT2_FS=y ++# CONFIG_EXT2_FS_XATTR is not set ++# CONFIG_EXT2_FS_XIP is not set ++CONFIG_EXT3_FS=y ++# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set ++CONFIG_EXT3_FS_XATTR=y ++# CONFIG_EXT3_FS_POSIX_ACL is not set ++# CONFIG_EXT3_FS_SECURITY is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_XATTR=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD=y ++# CONFIG_JBD_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_BTRFS_FS is not set ++CONFIG_NILFS2_FS=y ++# CONFIG_FS_POSIX_ACL is not set ++CONFIG_FILE_LOCKING=y ++# CONFIG_FSNOTIFY is not set ++# CONFIG_DNOTIFY is not set ++# CONFIG_INOTIFY_USER is not set ++# CONFIG_FANOTIFY is not set ++# CONFIG_QUOTA is not set ++# CONFIG_QUOTACTL is not set ++CONFIG_AUTOFS4_FS=y ++# CONFIG_FUSE_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=y ++# CONFIG_NTFS_DEBUG is not set ++# CONFIG_NTFS_RW is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++# CONFIG_PROC_PAGE_MONITOR is not set ++CONFIG_SYSFS=y ++# CONFIG_HUGETLB_PAGE is not set ++# CONFIG_CONFIGFS_FS is not set ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_ECRYPT_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=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_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=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_LOCKD=y ++CONFIG_LOCKD_V4=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=y ++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 ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_SHIRQ is not set ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_HARDLOCKUP_DETECTOR is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_TIMER_STATS is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_STATS is not set ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_RT_MUTEX_TESTER is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_SPARSE_RCU_POINTER 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_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_INFO=y ++# CONFIG_DEBUG_INFO_REDUCED is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_WRITECOUNT is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++CONFIG_FRAME_POINTER=y ++# CONFIG_BOOT_PRINTK_DELAY 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_BACKTRACE_SELF_TEST is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_LKDTM is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_DEBUG_PAGEALLOC 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_C_RECORDMCOUNT=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++# CONFIG_DYNAMIC_DEBUG is not set ++# CONFIG_DMA_API_DEBUG is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_STRICT_DEVMEM is not set ++# CONFIG_ARM_UNWIND is not set ++CONFIG_DEBUG_USER=y ++CONFIG_DEBUG_LL=y ++CONFIG_DEBUG_LL_UART_NONE=y ++# CONFIG_DEBUG_ICEDCC is not set ++# CONFIG_DEBUG_SEMIHOSTING is not set ++# CONFIG_EARLY_PRINTK is not set ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++ ++# ++# Security options ++# ++CONFIG_KEYS=y ++# CONFIG_ENCRYPTED_KEYS is not set ++# CONFIG_KEYS_DEBUG_PROC_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_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_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_PCRYPT is not set ++CONFIG_CRYPTO_WORKQUEUE=y ++# CONFIG_CRYPTO_CRYPTD 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=y ++# 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_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_GHASH 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 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=m ++# 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_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 ++ ++# ++# Random Number Generation ++# ++CONFIG_CRYPTO_ANSI_CPRNG=m ++# 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_PCI_IOMAP=y ++CONFIG_GENERIC_IO=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_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++# CONFIG_XZ_DEC is not set ++# CONFIG_XZ_DEC_BCJ is not set ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=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 +diff --git a/arch/arm/include/asm/bug.h b/arch/arm/include/asm/bug.h +index 9abe7a0..fac79dc 100644 +--- a/arch/arm/include/asm/bug.h ++++ b/arch/arm/include/asm/bug.h +@@ -32,7 +32,6 @@ + + #define __BUG(__file, __line, __value) \ + do { \ +- BUILD_BUG_ON(sizeof(struct bug_entry) != 12); \ + asm volatile("1:\t" BUG_INSTR_TYPE #__value "\n" \ + ".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \ + "2:\t.asciz " #__file "\n" \ +diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h +index 3e91f22..b7641d6 100644 +--- a/arch/arm/include/asm/hardware/gic.h ++++ b/arch/arm/include/asm/hardware/gic.h +@@ -42,6 +42,7 @@ extern struct irq_chip gic_arch_extn; + void gic_init(unsigned int, int, void __iomem *, void __iomem *); + int gic_of_init(struct device_node *node, struct device_node *parent); + void gic_secondary_init(unsigned int); ++void gic_handle_irq(struct pt_regs *regs); + void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); + void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); + +diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h +index fcbac3c..f2a1a30 100644 +--- a/arch/arm/include/asm/pgtable.h ++++ b/arch/arm/include/asm/pgtable.h +@@ -21,7 +21,6 @@ + #else + + #include +-#include + #include + + #include +@@ -33,14 +32,13 @@ + * any out-of-bounds memory accesses will hopefully be caught. + * The vmalloc() routines leaves a hole of 4kB between each vmalloced + * area for the same reason. ;) +- * +- * Note that platforms may override VMALLOC_START, but they must provide +- * VMALLOC_END. VMALLOC_END defines the (exclusive) limit of this space, +- * which may not overlap IO space. + */ +-#ifndef VMALLOC_START + #define VMALLOC_OFFSET (8*1024*1024) + #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) ++#ifdef __ASSEMBLY__ ++#define VMALLOC_END 0xff000000 ++#else ++#define VMALLOC_END 0xff000000UL + #endif + + #define LIBRARY_TEXT_START 0x0c000000 +@@ -338,6 +336,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) + * We provide our own arch_get_unmapped_area to cope with VIPT caches. + */ + #define HAVE_ARCH_UNMAPPED_AREA ++#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN + + /* + * remap a physical page `pfn' of size `size' with page protection `prot' +diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h +index 3352451..da9f0d9 100644 +--- a/arch/arm/include/asm/processor.h ++++ b/arch/arm/include/asm/processor.h +@@ -119,6 +119,8 @@ static inline void prefetch(const void *ptr) + + #endif + ++#define HAVE_ARCH_PICK_MMAP_LAYOUT ++ + #endif + + #endif /* __ASM_ARM_PROCESSOR_H */ +diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S +index ece0996..5ad6b59 100644 +--- a/arch/arm/kernel/entry-armv.S ++++ b/arch/arm/kernel/entry-armv.S +@@ -27,25 +27,28 @@ + #include + + #include "entry-header.S" ++ + #include + ++ + /* + * Interrupt handling. + */ + .macro irq_handler ++ + #ifdef CONFIG_MULTI_IRQ_HANDLER +- ldr r1, =handle_arch_irq ++ ++ ldr r1, =handle_arch_irq + mov r0, sp +- ldr r1, [r1] + adr lr, BSYM(9997f) +- teq r1, #0 +- movne pc, r1 +-#endif ++ ldr pc, [r1] ++#else + arch_irq_handler_default ++#endif + 9997: + .endm + +- .macro pabt_helper ++ .macro pabt_helper + @ PABORT handler takes pt_regs in r2, fault address in r4 and psr in r5 + #ifdef MULTI_PABORT + ldr ip, .LCprocfns +diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S +index 9d95a46..9dd0881 100644 +--- a/arch/arm/kernel/entry-header.S ++++ b/arch/arm/kernel/entry-header.S +@@ -13,8 +13,10 @@ + #define BAD_DATA 1 + #define BAD_ADDREXCPTN 2 + #define BAD_IRQ 3 ++ + #define BAD_UNDEFINSTR 4 + ++ + @ + @ Most of the stack format comes from struct pt_regs, but with + @ the addition of 8 bytes for storing syscall args 5 and 6. +diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S +index 3606e85..f364802 100644 +--- a/arch/arm/kernel/head.S ++++ b/arch/arm/kernel/head.S +@@ -87,7 +87,26 @@ ENTRY(stext) + + setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode + @ and irqs disabled +- mrc p15, 0, r9, c0, c0 @ get processor id ++#ifdef CONFIG_ARCH_IPROC ++ ++#ifndef CONFIG_MACH_IPROC_P7 ++#ifndef CONFIG_MACH_CYGNUS ++ /* ++ * fixup the vector table so that the secondary CPU does ++ * not start executing kernel instructions until we've ++ * patched its jump address during wakeup_secondary() ++ */ ++ ldr r3,=0xffff002c ++ ldr r4,=0xffff0000 ++ str r3, [r4, #0x400] ++#endif ++#endif ++ ++ /* Make sure the cache is invalidated and MMU is disabled */ ++ bl __iproc_head_fixup ++#endif /* CONFIG_ARCH_IPROC */ ++ ++ mrc p15, 0, r9, c0, c0 @ get processor id + bl __lookup_processor_type @ r5=procinfo r9=cpuid + movs r10, r5 @ invalid processor (r5=0)? + THUMB( it eq ) @ force fixup-able long branch encoding +diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c +index 1e9be5d..7ab2fa7 100644 +--- a/arch/arm/kernel/module.c ++++ b/arch/arm/kernel/module.c +@@ -111,19 +111,20 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, + } + + offset >>= 2; ++ offset &= 0x00ffffff; + + *(u32 *)loc &= 0xff000000; + *(u32 *)loc |= offset & 0x00ffffff; + break; + +- case R_ARM_V4BX: +- /* Preserve Rm and the condition code. Alter ++ case R_ARM_V4BX: ++ /* Preserve Rm and the condition code. Alter + * other bits to re-code instruction as + * MOV PC,Rm. + */ +- *(u32 *)loc &= 0xf000000f; +- *(u32 *)loc |= 0x01a0f000; +- break; ++ *(u32 *)loc &= 0xf000000f; ++ *(u32 *)loc |= 0x01a0f000; ++ break; + + case R_ARM_PREL31: + offset = *(u32 *)loc + sym->st_value - loc; +@@ -142,7 +143,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, + + *(u32 *)loc &= 0xfff0f000; + *(u32 *)loc |= ((offset & 0xf000) << 4) | +- (offset & 0x0fff); ++ (offset & 0x0fff); ++ + break; + + #ifdef CONFIG_THUMB2_KERNEL +@@ -203,12 +205,13 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, + *(u16 *)(loc + 2) = (u16)((lower & 0xd000) | + (j1 << 13) | (j2 << 11) | + ((offset >> 1) & 0x07ff)); ++ + break; + + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: +- upper = *(u16 *)loc; +- lower = *(u16 *)(loc + 2); ++ upper = __mem_to_opcode_thumb16(*(u16 *)loc); ++ lower = __mem_to_opcode_thumb16(*(u16 *)(loc + 2)); + + /* + * MOVT/MOVW instructions encoding in Thumb-2: +@@ -229,12 +232,15 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, + if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS) + offset >>= 16; + +- *(u16 *)loc = (u16)((upper & 0xfbf0) | ++ upper = (u16)((upper & 0xfbf0) | + ((offset & 0xf000) >> 12) | + ((offset & 0x0800) >> 1)); +- *(u16 *)(loc + 2) = (u16)((lower & 0x8f00) | ++ lower = (u16)((lower & 0x8f00) | + ((offset & 0x0700) << 4) | + (offset & 0x00ff)); ++ ++ *(u16 *)loc = __opcode_to_mem_thumb16(upper); ++ *(u16 *)(loc + 2) = __opcode_to_mem_thumb16(lower); + break; + #endif + +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index d9e3c61..2dc26fd 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -263,11 +264,12 @@ void __show_regs(struct pt_regs *regs) + unsigned long flags; + char buf[64]; + +- printk("CPU: %d %s (%s %.*s)\n", ++ printk("CPU: %d %s (%s %.*s%s)\n", + raw_smp_processor_id(), print_tainted(), + init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), +- init_utsname()->version); ++ init_utsname()->version, ++ LINUX_PACKAGE_ID); + print_symbol("PC is at %s\n", instruction_pointer(regs)); + print_symbol("LR is at %s\n", regs->ARM_lr); + printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n" +diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c +index 8f5dd79..1edbb3d 100644 +--- a/arch/arm/kernel/smp_scu.c ++++ b/arch/arm/kernel/smp_scu.c +@@ -27,7 +27,7 @@ + */ + unsigned int __init scu_get_core_count(void __iomem *scu_base) + { +- unsigned int ncores = __raw_readl(scu_base + SCU_CONFIG); ++ unsigned int ncores = readl_relaxed(scu_base + SCU_CONFIG); + return (ncores & 0x03) + 1; + } + +@@ -41,19 +41,19 @@ void scu_enable(void __iomem *scu_base) + #ifdef CONFIG_ARM_ERRATA_764369 + /* Cortex-A9 only */ + if ((read_cpuid(CPUID_ID) & 0xff0ffff0) == 0x410fc090) { +- scu_ctrl = __raw_readl(scu_base + 0x30); ++ scu_ctrl = readl_relaxed(scu_base + 0x30); + if (!(scu_ctrl & 1)) +- __raw_writel(scu_ctrl | 0x1, scu_base + 0x30); ++ writel_relaxed(scu_ctrl | 0x1, scu_base + 0x30); + } + #endif + +- scu_ctrl = __raw_readl(scu_base + SCU_CTRL); ++ scu_ctrl = readl_relaxed(scu_base + SCU_CTRL); + /* already enabled? */ + if (scu_ctrl & 1) + return; + + scu_ctrl |= 1; +- __raw_writel(scu_ctrl, scu_base + SCU_CTRL); ++ writel_relaxed(scu_ctrl, scu_base + SCU_CTRL); + + /* + * Ensure that the data accessed by CPU0 before the SCU was +@@ -79,9 +79,9 @@ int scu_power_mode(void __iomem *scu_base, unsigned int mode) + if (mode > 3 || mode == 1 || cpu > 3) + return -EINVAL; + +- val = __raw_readb(scu_base + SCU_CPU_STATUS + cpu) & ~0x03; ++ val = readb_relaxed(scu_base + SCU_CPU_STATUS + cpu) & ~0x03; + val |= mode; +- __raw_writeb(val, scu_base + SCU_CPU_STATUS + cpu); ++ writeb_relaxed(val, scu_base + SCU_CPU_STATUS + cpu); + + return 0; + } +diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c +index a8a6682..0647dfa 100644 +--- a/arch/arm/kernel/smp_twd.c ++++ b/arch/arm/kernel/smp_twd.c +@@ -39,7 +39,7 @@ static void twd_set_mode(enum clock_event_mode mode, + /* timer load already set up */ + ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE + | TWD_TIMER_CONTROL_PERIODIC; +- __raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD); ++ writel_relaxed(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD); + break; + case CLOCK_EVT_MODE_ONESHOT: + /* period set, and timer enabled in 'next_event' hook */ +@@ -51,18 +51,18 @@ static void twd_set_mode(enum clock_event_mode mode, + ctrl = 0; + } + +- __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL); ++ writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL); + } + + static int twd_set_next_event(unsigned long evt, + struct clock_event_device *unused) + { +- unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL); ++ unsigned long ctrl = readl_relaxed(twd_base + TWD_TIMER_CONTROL); + + ctrl |= TWD_TIMER_CONTROL_ENABLE; + +- __raw_writel(evt, twd_base + TWD_TIMER_COUNTER); +- __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL); ++ writel_relaxed(evt, twd_base + TWD_TIMER_COUNTER); ++ writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL); + + return 0; + } +@@ -75,8 +75,8 @@ static int twd_set_next_event(unsigned long evt, + */ + int twd_timer_ack(void) + { +- if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) { +- __raw_writel(1, twd_base + TWD_TIMER_INTSTAT); ++ if (readl_relaxed(twd_base + TWD_TIMER_INTSTAT)) { ++ writel_relaxed(1, twd_base + TWD_TIMER_INTSTAT); + return 1; + } + +@@ -110,16 +110,16 @@ static void __cpuinit twd_calibrate_rate(void) + /* OK, now the tick has started, let's get the timer going */ + waitjiffies += 5; + +- /* enable, no interrupt or reload */ +- __raw_writel(0x1, twd_base + TWD_TIMER_CONTROL); ++ /* enable, no interrupt or reload */ ++ writel_relaxed(0x1, twd_base + TWD_TIMER_CONTROL); + +- /* maximum value */ +- __raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER); ++ /* maximum value */ ++ writel_relaxed(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER); + + while (get_jiffies_64() < waitjiffies) + udelay(10); + +- count = __raw_readl(twd_base + TWD_TIMER_COUNTER); ++ count = readl_relaxed(twd_base + TWD_TIMER_COUNTER); + + twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); + +diff --git a/arch/arm/mach-iproc/Kconfig b/arch/arm/mach-iproc/Kconfig +new file mode 100644 +index 0000000..c77208d +--- /dev/null ++++ b/arch/arm/mach-iproc/Kconfig +@@ -0,0 +1,107 @@ ++menu "iProc SoC based Machine types" ++ depends on MACH_IPROC ++ ++config MACH_CYGNUS ++ bool "Cygnus bring-up board" ++ help ++ Support for the Broadcom Cygnus bring-up board. ++ ++config MACH_NS ++ bool "Support Broadcom Northstar bring-up board" ++ help ++ Support for the Broadcom Northstar bring-up board. ++ ++config MACH_HX4 ++ bool "Support Broadcom Helix4 bring-up board" ++ help ++ Support for the Broadcom Helix4 bring-up board. ++ ++config MACH_HR2 ++ bool "Support Broadcom Hurricane2 bring-up board" ++ help ++ Support for the Broadcom Hurricane2 bring-up board. ++ ++config MACH_NSP ++ bool "Support Broadcom Northstar Plus bring-up board" ++ help ++ Support for the Broadcom Northstar Plus bring-up board. ++ ++config MACH_KT2 ++ bool "Support Broadcom Katana2 bring-up board" ++ help ++ Support for the Broadcom Katana2 bring-up board. ++ ++config MACH_GH ++ bool "Support Broadcom Greyhound bring-up board" ++ select MACH_IPROC_P7 ++ help ++ Support for the Broadcom Greyhound bring-up board. ++ ++config MACH_DNI_3448P ++ select ARM_L1_CACHE_SHIFT_6 ++ bool "Support Delta Networks Inc. 3448P board" ++ help ++ Support for the Broadcom Greyhound bring-up board. ++ ++config MACH_ACCTON_AS4610_54 ++ select ARM_L1_CACHE_SHIFT_6 ++ bool "Support Accton AS4610 54 POE and non-POE board" ++ help ++ Support for Accton AS4610-54 POE and non -POE board. ++ ++config MACH_IPROC_P7 ++ bool "Support iProc Profile 7 architecture" ++ depends on MACH_GH ++ help ++ Support for iProc Profile 7 architecture. ++ ++config MACH_IPROC_EMULATION ++ bool "Support iProc emulation" ++ help ++ Support for the iProc emulation. ++ ++if MACH_CYGNUS ++ ++config MACH_CYGNUS_EMULATION ++ bool "Is it Cygnus emulation ?" ++ default y ++ help ++ Support for the Broadcom Cygnus emulation ++ ++if MACH_CYGNUS_EMULATION ++ ++config CYGNUS_EMULATION_RTL_VER ++ string "specify RTL version" ++ default "Cygnus RTL-5.1" ++ help ++ running rtl version used for emulation build ++ ++config CYGNUS_EMULATION_ARM_CLK ++ int "Hz - iHost clk don't change" ++ default 250000000 ++ help ++ iHost clock in emulator ++ ++config CYGNUS_EMULATION_PCLK ++ int "Hz - axi81 (pclk) in xls" ++ default 62500000 ++ help ++ pheripheral clock in emulator ++ ++config CYGNUS_EMULATION_SCLK ++ int "Hz - sclk in xls" ++ default 154380 ++ help ++ uart clock in emulator ++ ++config CYGNUS_EMULATION_CLK_125 ++ int "Hz - axi41 clock in xls" ++ default 154380 ++ help ++ 125Mhz equialent clock in emulator ++ ++endif #MACH_CYGNUS_EMULATION ++ ++endif #MACH_CYGNUS ++ ++endmenu +diff --git a/arch/arm/mach-iproc/Makefile b/arch/arm/mach-iproc/Makefile +new file mode 100644 +index 0000000..b4a7ff3 +--- /dev/null ++++ b/arch/arm/mach-iproc/Makefile +@@ -0,0 +1,15 @@ ++ifdef CONFIG_MACH_CYGNUS ++obj-y := io_map.o northstar.o common.o northstar_dmu.o board_bu.o localtimer.o ++else ++obj-y := io_map.o northstar.o common.o northstar_dmu.o board_bu.o idm.o localtimer.o ++endif ++ ++ifdef CONFIG_BCM_CTF2 ++EXTRA_CFLAGS += -I$(srctree)/../../bcmdrivers/gmac/src/include/ ++endif ++ ++obj-$(CONFIG_PM) += pm.o ++ ++#obj-$(CONFIG_MACH_NS) += board_bu.o ++ ++obj-$(CONFIG_MTD) += flash.o +diff --git a/arch/arm/mach-iproc/Makefile.boot b/arch/arm/mach-iproc/Makefile.boot +new file mode 100644 +index 0000000..2de985c +--- /dev/null ++++ b/arch/arm/mach-iproc/Makefile.boot +@@ -0,0 +1,2 @@ ++zreladdr-y := $(CONFIG_BCM_ZRELADDR) ++params_phys-y := $(CONFIG_BCM_PARAMS_PHYS) +diff --git a/arch/arm/mach-iproc/board_bu.c b/arch/arm/mach-iproc/board_bu.c +new file mode 100644 +index 0000000..7e07ed1 +--- /dev/null ++++ b/arch/arm/mach-iproc/board_bu.c +@@ -0,0 +1,1097 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef CONFIG_EARLY_DMA_ALLOC ++#include ++#endif ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "northstar.h" ++#include "common.h" ++#ifdef HNDCTF ++#include ++#include ++#endif /* HNDCTF */ ++ ++#include ++#include ++#include ++ ++#include ++ ++/* Fast device at 0x6000 offset */ ++static AMBA_APB_DEVICE(pl020, "pl020", 0, 0x18028000, ++ { 111 }, NULL); ++static AMBA_APB_DEVICE(pl021, "pl021", 0, 0x18029000, ++ { 111 }, NULL); ++ ++struct pl022_config_chip spi_chip_info = { ++ /* available POLLING_TRANSFER, INTERRUPT_TRANSFER, DMA_TRANSFER */ ++ .com_mode = DMA_TRANSFER, ++ .iface = SSP_INTERFACE_MOTOROLA_SPI, ++ /* We can only act as master but SSP_SLAVE is possible in theory */ ++ .hierarchy = SSP_MASTER, ++ /* 0 = drive TX even as slave, 1 = do not drive TX as slave */ ++ .slave_tx_disable = 0, ++ .rx_lev_trig = SSP_RX_4_OR_MORE_ELEM, ++ .tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC, ++ .ctrl_len = SSP_BITS_12, ++ .wait_state = SSP_MWIRE_WAIT_ZERO, ++ .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, ++}; ++ ++static struct pl022_ssp_controller ssp_platform_data[] = { ++ { ++ /* If you have several SPI buses this varies, we have only bus 0 */ ++ .bus_id = 0, ++ /* ++ * On the APP CPU GPIO 4, 5 and 6 are connected as generic ++ * chip selects for SPI. (Same on U330, U335 and U365.) ++ * TODO: make sure the GPIO driver can select these properly ++ * and do padmuxing accordingly too. ++ */ ++ .num_chipselect = 1, ++ .enable_dma = 1, ++ }, ++ { ++ /* If you have several SPI buses this varies, we have only bus 0 */ ++ .bus_id = 1, ++ /* ++ * On the APP CPU GPIO 4, 5 and 6 are connected as generic ++ * chip selects for SPI. (Same on U330, U335 and U365.) ++ * TODO: make sure the GPIO driver can select these properly ++ * and do padmuxing accordingly too. ++ */ ++ .num_chipselect = 1, ++ .enable_dma = 1, ++ }, ++}; ++ ++static struct spi_board_info iproc_spi_devices[] = { ++ { ++ /* A dummy chip used for loopback tests */ ++ .modalias = "spidev0", ++ /* Really dummy, pass in additional chip config here */ ++ .platform_data = NULL, ++ /* This defines how the controller shall handle the device */ ++ .controller_data = &spi_chip_info, ++ /* .irq - no external IRQ routed from this device */ ++ .max_speed_hz = 1000000, ++ .bus_num = 0, /* Only one bus on this chip */ ++ .chip_select = 0, ++ /* Means SPI_CS_HIGH, change if e.g low CS */ ++ .mode = SPI_MODE_2 | SPI_NO_CS, ++ }, ++ { ++ /* A dummy chip used for loopback tests */ ++ .modalias = "spidev1", ++ /* Really dummy, pass in additional chip config here */ ++ .platform_data = NULL, ++ /* This defines how the controller shall handle the device */ ++ .controller_data = &spi_chip_info, ++ /* .irq - no external IRQ routed from this device */ ++ .max_speed_hz = 1000000, ++ .bus_num = 1, /* Only one bus on this chip */ ++ .chip_select = 0, ++ /* Means SPI_CS_HIGH, change if e.g low CS */ ++ .mode = SPI_MODE_2 | SPI_NO_CS, ++ }, ++}; ++ ++/* ++ * The order of device declaration may be important, since some devices ++ * have dependencies on other devices being initialized first. ++ */ ++static struct amba_device *amba_pl_devs[] __initdata = { ++ &pl020_device, ++ &pl021_device, ++ ++}; ++ ++void __init iproc_spi_init(struct amba_device *adev, int i) ++{ ++ adev->dev.platform_data = &ssp_platform_data[i]; ++} ++ ++void __init iproc_spi_register_board_devices(void) ++{ ++ /* Register any SPI devices */ ++ spi_register_board_info(iproc_spi_devices, ARRAY_SIZE(iproc_spi_devices)); ++} ++ ++void __init iproc_init_devics(void) ++{ ++ int i; ++ ++ /* Register the AMBA devices in the AMBA bus abstraction layer */ ++ for (i = 0; i < ARRAY_SIZE(amba_pl_devs); i++) { ++ struct amba_device *d = amba_pl_devs[i]; ++ iproc_spi_init(d, i); ++ amba_device_register(d, &iomem_resource); ++ } ++ ++ /* Register SPI bus */ ++ iproc_spi_register_board_devices(); ++} ++ ++ ++#if defined(CONFIG_IPROC_SD) || defined(CONFIG_IPROC_SD_MODULE) ++#define IPROC_SDIO_PA IPROC_SDIO3_REG_BASE ++#define SDIO_CORE_REG_SIZE 0x10000 ++#define BSC_CORE_REG_SIZE 0x1000 ++#define SDIO_IDM_IDM_RESET_CONTROL (0x16800) ++#define IPROC_SDIO_IRQ (177) ++#endif ++ ++#if defined(CONFIG_MACH_NSP) ++#define SATA_M0_IDM_IO_CONTROL_DIRECT_VA HW_IO_PHYS_TO_VIRT(SATA_M0_IDM_IO_CONTROL_DIRECT) ++#define SATA_M0_IDM_IDM_RESET_CONTROL_VA HW_IO_PHYS_TO_VIRT(SATA_M0_IDM_IDM_RESET_CONTROL) ++#define SATA_TOP_CTRL_BUS_CTRL_VA HW_IO_PHYS_TO_VIRT(SATA_TOP_CTRL_BUS_CTRL) ++#define SATA3_PCB_UPPER_REG15_VA HW_IO_PHYS_TO_VIRT(SATA3_PCB_UPPER_REG15) ++#define SATA3_PCB_UPPER_REG0_VA HW_IO_PHYS_TO_VIRT(SATA3_PCB_UPPER_REG0) ++#define SATA3_PCB_UPPER_REG1_VA HW_IO_PHYS_TO_VIRT(SATA3_PCB_UPPER_REG1) ++#define SATA3_PCB_UPPER_REG11_VA HW_IO_PHYS_TO_VIRT(SATA3_PCB_UPPER_REG11) ++#define SATA3_PCB_UPPER_REG5_VA HW_IO_PHYS_TO_VIRT(SATA3_PCB_UPPER_REG5) ++#define AXIIC_sata_m0_fn_mod_VA HW_IO_PHYS_TO_VIRT(AXIIC_sata_m0_fn_mod) ++#define BCM_INT_SATA 190 ++#define NSP_CHIPID 0x3F00CF1E ++#endif ++ ++#ifndef CONFIG_MACH_CYGNUS ++extern void request_idm_timeout_interrupts(void); ++#endif ++ ++extern irqreturn_t idm_timeout_handler(int val, void *ptr); ++#if (defined(CONFIG_MACH_NSP) && defined(CONFIG_IPROC_OTP)) ++extern void* bcm5301x_otp_init(void); ++extern int bcm5301x_otp_exit(void); ++extern int bcm5301x_otp_read_dword(void *oh, uint wn, u32 *data); ++#endif /* (defined(CONFIG_MACH_NSP) && defined(CONFIG_IPROC_OTP)) */ ++ ++#ifdef CONFIG_MACH_CYGNUS_EMULATION //cygnus:emulator: ++ /* This is the main reference clock 25MHz from external crystal */ ++ static struct clk clk_ref = { ++ .name = "Refclk", ++ .rate = CONFIG_CYGNUS_EMULATION_SCLK, /* run-time override */ ++ .fixed = 1, ++ .type = 0, ++ }; ++#else ++/* This is the main reference clock 25MHz from external crystal */ ++static struct clk clk_ref = { ++ .name = "Refclk", ++ .rate = 25 * 1000000, /* run-time override */ ++ .fixed = 1, ++ .type = 0, ++}; ++#endif /* END of CYGNUS */ ++ ++#ifdef HNDCTF ++ctf_t *kcih = NULL; ++EXPORT_SYMBOL(kcih); ++ctf_attach_t ctf_attach_fn = NULL; ++EXPORT_SYMBOL(ctf_attach_fn); ++#endif /* HNDCTF */ ++ ++static struct clk_lookup board_clk_lookups[] = { ++ { ++ .con_id = "refclk", ++ .clk = &clk_ref, ++ } ++}; ++ ++extern void __init northstar_timer_init(struct clk *clk_ref); ++ ++#if defined(CONFIG_IPROC_SD) || defined(CONFIG_IPROC_SD_MODULE) ++/* sdio */ ++static struct sdio_platform_cfg sdio_platform_data = { ++ .devtype = SDIO_DEV_TYPE_SDMMC, ++}; ++static struct resource sdio_resources[] = { ++ [0] = { ++ .start = IPROC_SDIO_PA, ++ .end = IPROC_SDIO_PA + BSC_CORE_REG_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IPROC_SDIO_IRQ, ++ .end = IPROC_SDIO_IRQ, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device board_sdio_device = { ++ .name = "iproc-sdio", ++ .id = 0, ++ .dev = { ++ .platform_data = &sdio_platform_data, ++ }, ++ .num_resources = ARRAY_SIZE(sdio_resources), ++ .resource = sdio_resources, ++}; ++ ++static void setup_sdio(void) ++{ ++ void __iomem *idm_base; ++ struct platform_device *sdio_plat_dev[1]; ++ idm_base = (void __iomem *)IPROC_IDM_REGISTER_VA; ++ printk("%s: %d %p\n", __FUNCTION__, __LINE__, idm_base + SDIO_IDM_IDM_RESET_CONTROL); ++ writel_relaxed(0, idm_base + SDIO_IDM_IDM_RESET_CONTROL); ++ sdio_plat_dev[0] = &board_sdio_device; ++ platform_add_devices(sdio_plat_dev, 1); ++ ++} ++#endif /* CONFIG_IPROC_SD || CONFIG_IPROC_SD_MODULE */ ++ ++#if defined(CONFIG_IPROC_PWM) || defined(CONFIG_IPROC_PWM_MODULE) ++static struct resource iproc_pwm_resources = { ++ .start = IPROC_CCB_PWM_CTL, ++ .end = IPROC_CCB_PWM_CTL + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device board_pwm_device = { ++ .name = "iproc_pwmc", ++ .id = -1, ++ .resource = &iproc_pwm_resources, ++ .num_resources = 1, ++}; ++static struct pwm_lookup board_pwm_lookup[] = { ++ PWM_LOOKUP("iproc_pwmc", 0,"iproc_pwmc","pwm-0"), ++ PWM_LOOKUP("iproc_pwmc", 1,"iproc_pwmc","pwm-1"), ++ PWM_LOOKUP("iproc_pwmc", 2,"iproc_pwmc","pwm-2"), ++ PWM_LOOKUP("iproc_pwmc", 3,"iproc_pwmc","pwm-3"), ++ ++}; ++ ++#endif /* CONFIG_IPROC_PWM || CONFIG_IPROC_PWM_MODULE */ ++ ++#if defined(CONFIG_IPROC_WDT) || defined(CONFIG_IPROC_WDT_MODULE) ++/* watchdog */ ++static struct resource wdt_resources[] = { ++ [0] = { ++ .start = IPROC_CCA_REG_BASE, ++ .end = IPROC_CCA_REG_BASE + 0x1000 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device board_wdt_device = { ++ .name = "iproc_wdt", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(wdt_resources), ++ .resource = wdt_resources, ++}; ++#endif /* CONFIG_IPROC_WDT || CONFIG_IPROC_WDT_MODULE */ ++ ++#if defined(CONFIG_ARM_SP805_WATCHDOG) || defined(CONFIG_ARM_SP805_WATCHDOG_MODULE) ++static AMBA_APB_DEVICE(sp805_wdt, "sp805-wdt", 0x00141805, ++ IPROC_SP805_WDT_REG_BASE, { }, NULL); ++#endif ++ ++#if defined(CONFIG_IPROC_CCB_TIMER) || defined(CONFIG_IPROC_CCB_TIMER_MODULE) ++static struct resource ccb_timer_resources[] = { ++ [0] = { ++ .start = IPROC_CCB_TIMER_INT_START, ++ .end = IPROC_CCB_TIMER_INT_START + IPROC_CCB_TIMER_INT_COUNT - 1, ++ .flags = IORESOURCE_IRQ, ++ }, ++ [1] = { ++ .start = IPROC_CCB_TIMER0_REGS_VA, ++ .end = IPROC_CCB_TIMER0_REGS_VA + 0x20 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { ++ .start = IPROC_CCB_TIMER1_REGS_VA, ++ .end = IPROC_CCB_TIMER1_REGS_VA + 0x20 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [3] = { ++ .start = IPROC_CCB_TIMER2_REGS_VA, ++ .end = IPROC_CCB_TIMER2_REGS_VA + 0x20 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [4] = { ++ .start = IPROC_CCB_TIMER3_REGS_VA, ++ .end = IPROC_CCB_TIMER3_REGS_VA + 0x20 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device board_timer_device = { ++ .name = "iproc_ccb_timer", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(ccb_timer_resources), ++ .resource = ccb_timer_resources, ++}; ++#endif /* CONFIG_IPROC_CCB_TIMER || CONFIG_IPROC_CCB_TIMER_MODULE */ ++ ++#if defined(CONFIG_IPROC_FA2) ++#if defined(CONFIG_MACH_NSP) ++static struct resource fa2_resources[] = { ++ [0] = { ++ .start = CTF_CONTROL_REG, /* Macro is in socregs_nsp.h */ ++ .end = CTF_CONTROL_REG + SZ_1K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = 178, ++ .end = 178, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++#endif ++#endif /* CONFIG_IPROC_FA2 */ ++ ++#if !(defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) ++/* Helix4 */ ++static struct resource smbus_resources[] = { ++ [0] = { ++ .start = ChipcommonB_SMBus_Config, /* Macro is in socregs_hx4.h */ ++ .end = ChipcommonB_SMBus_Config + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = 127, ++ .end = 127, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct resource smbus_resources1[] = { ++ [0] = { ++ .start = ChipcommonB_SMBus1_SMBus_Config, /* Macro is in socregs_hx4.h */ ++ .end = ChipcommonB_SMBus1_SMBus_Config + SZ_4K - 1, ++ .flags = IORESOURCE_MEM ++ }, ++ [1] = { ++ .start = 128, /* macro in irqs.h (plat-iproc) */ ++ .end = 128, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++#elif defined(CONFIG_MACH_NSP) ++/* Northstar plus */ ++static struct resource smbus_resources[] = { ++ [0] = { ++ .start = ChipcommonB_SMBus_Config, /* Macro is in socregs_hx4.h */ ++ .end = ChipcommonB_SMBus_Config + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = 121, ++ .end = 121, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++#else ++/* Northstar */ ++static struct resource smbus_resources[] = { ++ [0] = { ++ .start = CCB_SMBUS_START, /* Define this macro is socregs.h, or ++ in iproc_regs.h */ ++ .end = CCB_SMBUS_START + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = BCM_INT_ID_CCB_SMBUS, /* macro in irqs.h (plat-iproc) */ ++ .end = BCM_INT_ID_CCB_SMBUS, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++#endif ++ ++/* Common to Northstar, Helix4 */ ++static struct platform_device board_smbus_device = { ++ .name= "iproc-smb", ++ .id = 0, ++ .dev= { ++ .platform_data = NULL, /* Can be defined, if reqd */ ++ }, ++ .num_resources = ARRAY_SIZE(smbus_resources), ++ .resource = smbus_resources, ++}; ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) ++static struct platform_device board_smbus_device1 = { ++ .name= "iproc-smb", ++ .id = 1, ++ .dev= { ++ .platform_data = NULL, /* Can be defined, if reqd */ ++ }, ++ .num_resources = ARRAY_SIZE(smbus_resources1), ++ .resource = smbus_resources1, ++}; ++ ++#endif /* CONFIG_MACH_HX4 */ ++#endif /* Not ACCTON-AS4610-54, dni-3448p */ ++ ++#if defined(CONFIG_IPROC_FA2) ++#if defined(CONFIG_MACH_NSP) ++static struct platform_device board_fa2_device = { ++ .name= "fa2", ++ .id = 0, ++ .dev= { ++ .platform_data = NULL, /* Can be defined, if reqd */ ++ }, ++ .num_resources = ARRAY_SIZE(fa2_resources), ++ .resource = fa2_resources, ++}; ++#endif ++#endif /* CONFIG_IPROC_FA2 */ ++ ++#ifdef CONFIG_IPROC_USB3H ++static struct resource bcm_xhci_resources[] = { ++ [0] = { ++ .start = USB30_BASE, ++ .end = USB30_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = BCM_INT_ID_USB3H2CORE_USB2_INT0, ++ .end = BCM_INT_ID_USB3H2CORE_USB2_INT0, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 xhci_dmamask = DMA_BIT_MASK(32); ++ ++static struct platform_device bcm_xhci_device = { ++ .name = "bcm-xhci", ++ .id = 0, ++ .dev = { ++// .platform_data = &xhci_platform_data, ++ .dma_mask = &xhci_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm_xhci_resources, ++ .num_resources = ARRAY_SIZE(bcm_xhci_resources), ++}; ++#endif /* CONFIG_IPROC_USB3 */ ++ ++#ifdef CONFIG_USB_EHCI_BCM ++ ++static u64 ehci_dmamask = DMA_BIT_MASK(32); ++ ++static struct resource usbh_ehci_resource[] = { ++ [0] = { ++ .start = IPROC_USB20_REG_BASE, ++ .end = IPROC_USB20_REG_BASE + 0x0FFF, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ // FIXME Cumulus: Helix4 IRQ value should be 117, ++ // some #define in plat-iproc irqgs.h is messed up ++ .start = 117, ++ .end = 117, ++ //.start = BCM_INT_ID_USB2H2CORE_USB2_INT, ++ //.end = BCM_INT_ID_USB2H2CORE_USB2_INT, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device usbh_ehci_device = ++{ ++ .name = "bcm-ehci", ++ .id = 0, ++ .resource = usbh_ehci_resource, ++ .num_resources = ARRAY_SIZE(usbh_ehci_resource), ++ .dev = { ++ .dma_mask = &ehci_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++}; ++#endif ++ ++#ifdef CONFIG_USB_OHCI_BCM ++ ++static u64 ohci_dmamask = DMA_BIT_MASK(32); ++ ++static struct resource usbh_ohci_resource[] = { ++ [0] = { ++ .start = IPROC_USB20_REG_BASE + 0x1000, ++ .end = IPROC_USB20_REG_BASE + 0x1000 + 0x0FFF, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ // FIXME Cumulus: Helix4 IRQ value should be 117, ++ // some #define in plat-iproc irqgs.h is messed up ++ .start = 117, ++ .end = 117, ++ //.start = BCM_INT_ID_USB2H2CORE_USB2_INT, ++ //.end = BCM_INT_ID_USB2H2CORE_USB2_INT, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device usbh_ohci_device = ++{ ++ .name = "bcm-ohci", ++ .id = 0, ++ .resource = usbh_ohci_resource, ++ .num_resources = ARRAY_SIZE(usbh_ohci_resource), ++ .dev = { ++ .dma_mask = &ohci_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++}; ++#endif ++ ++#ifdef CONFIG_SATA_AHCI_PLATFORM ++static struct resource bcm_sata_resources[] = { ++ [0] = { ++ .start = SATA_AHCI_GHC_HBA_CAP, ++ .end = SATA_AHCI_GHC_HBA_CAP + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = BCM_INT_SATA, ++ .end = BCM_INT_SATA, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++static u64 sata_dmamask = DMA_BIT_MASK(32); ++ ++static struct platform_device bcm_sata_device = { ++ .name = "strict-ahci", ++ .id = 0, ++ .dev = { ++ .dma_mask = &sata_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm_sata_resources, ++ .num_resources = ARRAY_SIZE(bcm_sata_resources), ++}; ++#endif ++ ++#ifdef CONFIG_DMAC_PL330 ++#include "../../../../bcmdrivers/dma/pl330-pdata.h" ++static struct iproc_pl330_data iproc_pl330_pdata = { ++ /* Non Secure DMAC virtual base address */ ++ .dmac_ns_base = IPROC_DMAC_REG_VA, ++ /* Secure DMAC virtual base address */ ++ .dmac_s_base = IPROC_DMAC_REG_VA, ++ /* # of PL330 dmac channels 'configurable' */ ++ .num_pl330_chans = 8, ++ /* irq number to use */ ++ .irq_base = BCM_INT_ID_DMAC, ++ /* # of PL330 Interrupt lines connected to GIC */ ++ .irq_line_count = 16, ++}; ++ ++static struct platform_device pl330_dmac_device = { ++ .name = "iproc-dmac-pl330", ++ .id = 0, ++ .dev = { ++ .platform_data = &iproc_pl330_pdata, ++ .coherent_dma_mask = DMA_BIT_MASK(64), ++ }, ++}; ++#endif ++ ++ ++#if defined(CONFIG_MACH_NSP) ++void config_AHCI( void ) ++{ ++ volatile unsigned int sata_clk_enable; ++ volatile unsigned int bustopcfg; ++ ++ printk("\nConfigure AHCI ...\n"); ++ sata_clk_enable = readl_relaxed(SATA_M0_IDM_IO_CONTROL_DIRECT_VA); ++ sata_clk_enable |= 0x1; ++ writel_relaxed( sata_clk_enable, SATA_M0_IDM_IO_CONTROL_DIRECT_VA); ++ sata_clk_enable = readl_relaxed(SATA_M0_IDM_IO_CONTROL_DIRECT_VA); ++ udelay(1000); ++ ++ ++ /* Reset core */ ++ writel_relaxed(0x0, SATA_M0_IDM_IDM_RESET_CONTROL_VA); ++ udelay(1000); ++ sata_clk_enable = readl_relaxed(SATA_M0_IDM_IDM_RESET_CONTROL_VA); ++ bustopcfg = __raw_readl(SATA_TOP_CTRL_BUS_CTRL_VA); // JIRA:LINUXDEV-39 ++ bustopcfg &= ~ (( 3 << 2) | ( 3 << 4 )); ++ bustopcfg |= (( 2 << 2) | ( 2 << 4 ));//| ( 2<< 6 )); ++ //bustopcfg |= ( ( 0x2 << 8 ) | ( 0x2 << 17 ) ); ++ writel_relaxed(bustopcfg, SATA_TOP_CTRL_BUS_CTRL_VA); ++} ++void configure_SATA_PHY ( void ) ++{ ++ unsigned int i, tmp; ++ void __iomem *bs = ioremap(AXIIC_sata_m0_fn_mod, 4); ++ ++ void __iomem *id = IOMEM(IPROC_CCA_CORE_REG_VA); ++ ++ printk("\nConfigure PHY ...\n"); ++ ++ writel_relaxed(0x0150,SATA3_PCB_UPPER_REG15_VA); ++ writel_relaxed( 0xF6F6, SATA3_PCB_UPPER_REG0_VA); ++ writel_relaxed( 0x2e96, SATA3_PCB_UPPER_REG1_VA); ++ ++ writel_relaxed(0x0160,SATA3_PCB_UPPER_REG15_VA); ++ writel_relaxed( 0xF6F6, SATA3_PCB_UPPER_REG0_VA); ++ writel_relaxed( 0x2e96, SATA3_PCB_UPPER_REG1_VA); ++ ++ //access SATA PLL ++ writel_relaxed(0x0050,SATA3_PCB_UPPER_REG15_VA); ++ //Audio PLL 0x8B ++ i = readl_relaxed(SATA3_PCB_UPPER_REG11_VA); ++ i &= ~ (( 0x1f) << 9 ); ++ i |= ( 0xC << 9); ++ writel_relaxed( i, SATA3_PCB_UPPER_REG11_VA); ++ ++ //Sequence for restarting PLL. Please try after changing the divider. ++ //'PLL_CapCtrl[10] = 1, PLL_CapCtrl[7:0] = F0h ++ //SATA3_PLL: PLL Register Bank address 0x50 ++ ++ //set register SATA3_PLL_capControl ( 0x85 ) ++ i = readl_relaxed(SATA3_PCB_UPPER_REG5_VA); ++ i = ( i | 0x4f0 ) & 0xFF0; ++ writel_relaxed( i, SATA3_PCB_UPPER_REG5_VA); ++ ++ //'PLL_Ctrl[13:12] = 11 ++ //Set register SATA3_PLL_CONTROL ( 0x81 ) ++ i = readl_relaxed(SATA3_PCB_UPPER_REG1_VA); ++ i |= 0x3000; ++ writel_relaxed( i, SATA3_PCB_UPPER_REG1_VA); ++ ++ //'PLL_ReStart ++ i = readl_relaxed(SATA3_PCB_UPPER_REG1_VA); ++ i &= 0x7FFF; ++ writel_relaxed( i, SATA3_PCB_UPPER_REG1_VA); ++ mdelay(100); ++ i = readl_relaxed(SATA3_PCB_UPPER_REG1_VA); ++ i |= 0x8000; ++ writel_relaxed( i, SATA3_PCB_UPPER_REG1_VA); ++ mdelay(1000); ++ writel_relaxed(0x0000,SATA3_PCB_UPPER_REG15_VA); ++ i = readl_relaxed(SATA3_PCB_UPPER_REG1_VA); ++ tmp = readl(id); ++ if (tmp == NSP_CHIPID) ++ { ++ tmp = readl(bs); ++ tmp |= 0x3; ++ writel(tmp, bs); ++ tmp = readl(bs); ++ } ++} ++#endif ++ ++#ifdef CONFIG_MACH_CYGNUS ++#include "include/mach/iproc_regs.h" ++#ifdef CONFIG_IPROC_DS1WM ++#include "../../../../../bcmgpldrivers/d1w/ds1wm.h" ++ ++ ++static struct ds1wm_driver_data ds1wm_platform_data = { ++ .clock_rate = 80000000, ++ .reset_recover_delay = 1, /*ms*/ ++}; ++ ++static struct resource ds1wm_resources[] = { ++ [0] = { ++ .start = IPROC_D1W_REG_BASE, ++ .end = IPROC_D1W_REG_BASE+0x0F, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IPROC_D1W_CLK_GATE_CTRL, ++ .end = IPROC_D1W_CLK_GATE_CTRL+0x03 ++ }, ++ [2] = { ++ .start = IPROC_D1W_IO_MUX_REG, ++ .end = IPROC_D1W_IO_MUX_REG+0x03 ++ }, ++ [3] = { ++ .start = IPROC_D1W_INTR, ++ .end = IPROC_D1W_INTR, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device ds1wm_device = { ++ .name = "ds1wm", ++ .id = -1, ++ .dev = { ++ .platform_data = &ds1wm_platform_data, ++ }, ++ .num_resources = ARRAY_SIZE(ds1wm_resources), ++ .resource = ds1wm_resources, ++}; ++#endif ++ ++#ifdef CONFIG_IPROC_KEYPAD ++#include "../../../../../bcmdrivers/keypad/keypad.h" ++static iproc_keypad_t keypad_info = { ++ .max_rows = 4, ++ .max_cols = 4, ++ .StatFilEn = 1, ++ .StatFilType = 0x5, ++ .ColFilEn = 1, ++ .ColFilType = 0x05, ++ .IoMode = 0, ++ .SwapRc = 0, ++ .ScanMode = 0 ++}; ++ ++static struct resource keypad_resources[] = { ++ [0] = { ++ .start = IPROC_KEYPAD_REG_BASE, ++ .end = IPROC_KEYPAD_REG_BASE+0x4B, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IPROC_CRMU_ASIU_KEYPAD_CLK_DIV, ++ .end = IPROC_CRMU_ASIU_KEYPAD_CLK_DIV+0x03, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { ++ .start = IPROC_IO_MUX_REG_BASE, ++ .end = IPROC_IO_MUX_REG_BASE+0x07, ++ .flags = IORESOURCE_MEM, ++ }, ++ [3] = { ++ .start = IPROC_CLK_GATING_CTRL, ++ .end = IPROC_CLK_GATING_CTRL + 0x03, ++ .flags = IORESOURCE_MEM, ++ }, ++ [4] = { ++ .start = IPROC_KEYPAD_INTR, ++ .end = IPROC_KEYPAD_INTR, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device keypad_device = { ++ .name = "iproc-keypad", ++ .id = -1, ++ .dev = { ++ .platform_data = &keypad_info, ++ }, ++ .num_resources = ARRAY_SIZE(keypad_resources), ++ .resource = keypad_resources, ++}; ++#endif ++#ifdef CONFIG_IPROC_TOUCHSCREEN ++static struct resource tsc_resources[] = { ++ [0] = { ++ .start = IPROC_TSC_REG_BASE, ++ .end = IPROC_TSC_REG_BASE+0x3F, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IPROC_TSC_INTR, ++ .end = IPROC_TSC_INTR, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device tsc_device = { ++ .name = "iproc-tsc", ++ .id = -1, ++ .dev = { ++ .platform_data = NULL, ++ }, ++ .num_resources = ARRAY_SIZE(tsc_resources), ++ .resource = tsc_resources, ++}; ++#endif ++ ++#ifdef CONFIG_IPROC_ADC ++static struct resource adc_resources[] = { ++ [0] = { ++ .start = IPROC_ADC_REG_BASE, ++ .end = IPROC_ADC_REG_BASE+0x3F, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IPROC_ADC_INTR, ++ .end = IPROC_ADC_INTR, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device adc_device = { ++ .name = "iproc-adc", ++ .id = -1, ++ .dev = { ++ .platform_data = NULL, ++ }, ++ .num_resources = ARRAY_SIZE(adc_resources), ++ .resource = adc_resources, ++}; ++#endif ++ ++#endif ++ ++void __init board_map_io(void) ++{ ++ ++ /* ++ * Install clock sources in the lookup table. ++ */ ++ clkdev_add_table(board_clk_lookups, ++ ARRAY_SIZE(board_clk_lookups)); ++ ++ /* Map machine specific iodesc here */ ++ northstar_map_io(); ++} ++ ++void __init iproc_init_early(void) ++{ ++ ++ /* ++ * SDK allocates coherent buffers from atomic ++ * context. Increase size of atomic coherent pool to make sure such ++ * the allocations won't fail. ++ */ ++#ifdef CONFIG_CMA ++ init_dma_coherent_pool_size(SZ_1M * 16); ++#endif ++ /* ++ * Allocate contiguous himem block for SDK usage ++ */ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++} ++ ++static struct platform_device *board_sata_device[] __initdata = { ++#ifdef CONFIG_SATA_AHCI_PLATFORM ++ &bcm_sata_device, ++#endif ++}; ++ ++static struct of_dev_auxdata iproc_auxdata_lookup[] __initdata = ++{ ++ { /* sentinel */ }, ++}; ++static struct platform_device *board_devices[] __initdata = { ++#if !(defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ &board_smbus_device, ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) ++ &board_smbus_device1, ++#endif ++#endif /*Don't use for Accton */ ++ ++#if defined(CONFIG_IPROC_FA2) ++#if defined(CONFIG_MACH_NSP) ++ &board_fa2_device, ++#endif ++#endif /* FA+ */ ++ ++#if defined(CONFIG_IPROC_CCB_TIMER) || defined(CONFIG_IPROC_CCB_TIMER_MODULE) ++ &board_timer_device, ++#endif /* CONFIG_IPROC_CCB_TIMER || CONFIG_IPROC_CCB_TIMER_MODULE */ ++#if defined(CONFIG_IPROC_WDT) || defined(CONFIG_IPROC_WDT_MODULE) ++ &board_wdt_device, ++#endif /* CONFIG_IPROC_WDT || CONFIG_IPROC_WDT_MODULE */ ++#if defined(CONFIG_IPROC_PWM) || defined(CONFIG_IPROC_PWM_MODULE) ++ &board_pwm_device, ++#endif /* CONFIG_IPROC_PWM || CONFIG_IPROC_PWM_MODULE */ ++#ifdef CONFIG_IPROC_USB3H ++ &bcm_xhci_device, ++#endif ++#ifdef CONFIG_USB_EHCI_BCM ++ &usbh_ehci_device, ++#endif ++#ifdef CONFIG_USB_OHCI_BCM ++ &usbh_ohci_device, ++#endif ++#ifdef CONFIG_DMAC_PL330 ++ &pl330_dmac_device, ++#endif ++#ifdef CONFIG_MACH_CYGNUS ++#ifdef CONFIG_IPROC_DS1WM ++ &ds1wm_device, ++#endif ++#ifdef CONFIG_IPROC_KEYPAD ++ &keypad_device, ++#endif ++#endif ++}; ++ ++static struct amba_device *amba_devs[] __initdata = { ++#if defined(CONFIG_ARM_SP805_WATCHDOG) || defined(CONFIG_ARM_SP805_WATCHDOG_MODULE) ++ &sp805_wdt_device, ++#endif ++}; ++ ++static void __init board_add_devices(void) ++{ ++ int i; ++ ++ platform_add_devices(board_devices, ARRAY_SIZE(board_devices)); ++// if (iproc_get_chipid() == 53010) { ++// } ++ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { ++ amba_device_register(amba_devs[i], &iomem_resource); ++ } ++} ++ ++static void __init board_add_sata_device(void) ++{ ++ platform_add_devices(board_sata_device, sizeof(board_sata_device)/sizeof((board_sata_device)[0])); ++} ++ ++ ++/* SPI device info of GSIO(SPI) interface */ ++static struct spi_board_info bcm5301x_spi_device[] = { ++ { ++ .modalias = "spidev", ++ .platform_data = NULL, ++ .controller_data = NULL, ++ .max_speed_hz = 2 * 1000 * 1000, ++ .bus_num = 0, ++ .chip_select = 0, ++ .mode = SPI_MODE_0, ++ }, ++}; ++ ++void __init board_timer_init(void) ++{ ++ northstar_timer_init(&clk_ref); ++} ++ ++struct sys_timer board_timer = { ++ .init = board_timer_init, ++}; ++ ++ ++void __init board_init(void) ++{ ++ uint32_t sata_enable=0; ++ ++#if (defined(CONFIG_MACH_NSP) && defined(CONFIG_IPROC_OTP)) ++ void *oh; ++#endif /* (defined(CONFIG_MACH_NSP) && defined(CONFIG_IPROC_OTP)) */ ++ ++ /* ++ * Add common platform devices that do not have board dependent HW ++ * configurations ++ */ ++ board_add_common_devices(&clk_ref); ++#ifndef CONFIG_MACH_CYGNUS ++#ifndef CONFIG_MACH_NS ++ /* register IDM timeout interrupt handler */ ++ request_idm_timeout_interrupts(); ++#endif ++#endif ++ ++#if defined(CONFIG_MACH_NSP) ++ #if defined(CONFIG_IPROC_OTP) ++ /* read otp row 0xd to figure if sata is enabled */ ++ oh = bcm5301x_otp_init(); ++ if (oh != NULL) ++ { ++ bcm5301x_otp_read_dword(oh, 0xd, &sata_enable); ++ printk("%s: %d %08x\n", __FUNCTION__, __LINE__, sata_enable); ++ if ((sata_enable & 0x40000000) == 0x40000000) ++ { ++ config_AHCI(); ++ configure_SATA_PHY(); ++ } ++ bcm5301x_otp_exit(); ++ } ++ else ++ printk("%s: %d bcm5301x_otp_init failed\n", __FUNCTION__, __LINE__); ++ #else /* defined(CONFIG_IPROC_OTP) */ ++ printk("%s(): IPROC OTP not configured, can not determine if SATA is enabled.\n", __FUNCTION__); ++ #endif /* defined(CONFIG_IPROC_OTP) */ ++#endif ++ ++ board_add_devices(); ++ if ((sata_enable & 0x40000000) == 0x40000000) ++ board_add_sata_device(); ++ ++ ++#if defined(CONFIG_IPROC_SD) || defined(CONFIG_IPROC_SD_MODULE) ++ /* only bcm53012 support sdio */ ++ if ((__REG32(IPROC_IDM_REGISTER_VA + 0xd500) & 0xc) == 0x0) { ++ setup_sdio(); ++ } ++#endif ++ ++#if defined(CONFIG_IPROC_PWM) || defined(CONFIG_IPROC_PWM_MODULE) ++ writel_relaxed(0xf, IPROC_CCB_GPIO_REG_VA + IPROC_GPIO_CCB_AUX_SEL); ++ pwm_add_table(board_pwm_lookup, ARRAY_SIZE(board_pwm_lookup)); ++#endif ++ ++ /* Register SPI device info */ ++ spi_register_board_info(bcm5301x_spi_device, ++ ARRAY_SIZE(bcm5301x_spi_device)); ++ ++ of_platform_populate(NULL, of_default_bus_match_table, ++ iproc_auxdata_lookup, NULL); ++ printk(KERN_DEBUG "board_init: Leave\n"); ++} ++ ++MACHINE_START(IPROC, "Broadcom iProc") ++ ++// Used micro9 as a reference. Micro9 removed these two fields, ++// and replaced them with a call to ep93xx_map_io(), which in turn ++// calls iotable_init(). Northstar appears to have an equivalent ++// init (refer to northstar_io_desc[] array, in io_map.c ++ .map_io = board_map_io, ++ .init_early = iproc_init_early, ++ .init_irq = iproc_init_irq, ++ .handle_irq = gic_handle_irq, ++ .timer = &board_timer, ++ .init_machine = board_init, ++MACHINE_END ++ ++static const char * helix4_dt_board_compat[] = { ++ "dni,dni_3448p", ++ "accton,as4610_54", ++ NULL ++}; ++ ++DT_MACHINE_START(HELIX4_DT, "Broadcom Helix4 (Flattened Device Tree)") ++ .map_io = board_map_io, ++ .init_early = iproc_init_early, ++ .init_irq = iproc_init_irq, ++ .handle_irq = gic_handle_irq, ++ .timer = &board_timer, ++ .init_machine = board_init, ++ .dt_compat = helix4_dt_board_compat, ++MACHINE_END +diff --git a/arch/arm/mach-iproc/common.c b/arch/arm/mach-iproc/common.c +new file mode 100644 +index 0000000..b116ffc +--- /dev/null ++++ b/arch/arm/mach-iproc/common.c +@@ -0,0 +1,347 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++//#include ++#include ++#include ++#include ++#include ++#include ++ ++#define IPROC_UART0_PA IPROC_CCA_UART0_REG_BASE ++#define IPROC_UART1_PA IPROC_CCA_UART1_REG_BASE ++#define IPROC_UART2_PA IPROC_CCB_UART0_REG_BASE ++#define IPROC_UART3_PA IPROC_CCA_UART3_REG_BASE ++#define IPROC_CCA_UART_CLK_PA IPROC_CCA_UART_CLK_REG_BASE ++#define IPROC_CCA_CCAP_PA IPROC_CCA_CORE_CAP_REG_BASE ++#define IPROC_CCA_CCTL_PA IPROC_CCA_CORE_CTL_REG_BASE ++#define IPROC_CCA_INTMASK_PA IPROC_CCA_INTMASK_REG_BASE ++ ++#define IPROC_UART0_VA HW_IO_PHYS_TO_VIRT(IPROC_UART0_PA) ++#define IPROC_UART1_VA HW_IO_PHYS_TO_VIRT(IPROC_UART1_PA) ++#define IPROC_UART2_VA HW_IO_PHYS_TO_VIRT(IPROC_UART2_PA) ++#define IPROC_UART3_VA HW_IO_PHYS_TO_VIRT(IPROC_UART3_PA) ++#define IPROC_CCA_UART_CLK_VA HW_IO_PHYS_TO_VIRT(IPROC_CCA_UART_CLK_PA) ++#define IPROC_CCA_CCAP_VA HW_IO_PHYS_TO_VIRT(IPROC_CCA_CCAP_PA) ++#define IPROC_CCA_CCTL_VA HW_IO_PHYS_TO_VIRT(IPROC_CCA_CCTL_PA) ++#define IPROC_CCA_INTMASK_VA HW_IO_PHYS_TO_VIRT(IPROC_CCA_INTMASK_PA) ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++#define IRQ_IPROC_UART0 117 ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P)) ++#define IRQ_IPROC_UART0 123 ++#elif defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IRQ_IPROC_UART0 123 ++#define IRQ_IPROC_UART2 124 ++#elif defined(CONFIG_MACH_HR2) ++#define IRQ_IPROC_UART0 123 ++#elif defined(CONFIG_MACH_GH) ++#define IRQ_IPROC_UART0 105 ++#elif defined(CONFIG_MACH_CYGNUS) ++#define IRQ_IPROC_UART0 IPROC_INTERRUPTS__chipcommonG_uart0_intr ++ #define IRQ_IPROC_UART1 IPROC_INTERRUPTS__chipcommonG_uart1_intr//chandra:fix ++ #define IRQ_IPROC_UART2 IPROC_INTERRUPTS__chipcommonG_uart2_intr//chandra:fix ++ #define IRQ_IPROC_UART3 IPROC_INTERRUPTS__chipcommonG_uart3_intr//chandra:fix ++#else ++#error "No valid UART IRQ selected" ++#endif ++ ++#if defined(CONFIG_MACH_HR2) && defined(CONFIG_MACH_IPROC_EMULATION) ++#define IPROC_UART_CLK (76800) ++#elif defined(CONFIG_MACH_KT2) && defined(CONFIG_MACH_IPROC_EMULATION) ++#define IPROC_UART_CLK (65800) ++#elif defined(CONFIG_MACH_IPROC_P7) && defined(CONFIG_MACH_IPROC_EMULATION) ++#define IPROC_UART_CLK (56864) ++#elif defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_UART_CLK (100000000) ++#elif defined(CONFIG_MACH_CYGNUS) ++#define IPROC_UART_CLK CONFIG_CYGNUS_EMULATION_SCLK ++#else ++#define IPROC_UART_CLK (62500000) ++#endif ++ ++#ifdef CONFIG_MACH_IPROC_P7 ++#define IPROC_8250PORT(name) \ ++{ \ ++ .membase = (void __iomem *)(IPROC_##name##_VA), \ ++ .mapbase = (resource_size_t)(IPROC_##name##_PA), \ ++ .irq = IRQ_IPROC_UART0, \ ++ .uartclk = IPROC_UART_CLK, \ ++ .regshift = 2, \ ++ .iotype = UPIO_MEM32, \ ++ .type = PORT_16550A, \ ++ .flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ, \ ++ .private_data = (void __iomem *)((IPROC_##name##_VA) + 0x00), \ ++} ++#elif defined(CONFIG_MACH_CYGNUS) /* !CONFIG_MACH_IPROC_P7 */ ++#define IPROC_8250PORT(name) \ ++{ \ ++ .membase = (void __iomem *)(IPROC_##name##_VA), \ ++ .mapbase = (resource_size_t)(IPROC_##name##_PA), \ ++ .irq = IRQ_IPROC_##name, \ ++ .uartclk = CONFIG_CYGNUS_EMULATION_SCLK, /*.uartclk = 62500000,*/ \ ++ .regshift = 2, \ ++ .iotype = UPIO_MEM32, \ ++ .type = PORT_16550A, \ ++ .flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ, \ ++ .private_data = (void __iomem *)((IPROC_##name##_VA) + 0x00), \ ++} ++#else /* ! CONFIG_MACH_CYGNUS */ ++#define IPROC_8250PORT(name) \ ++{ \ ++ .membase = (void __iomem *)(IPROC_##name##_VA), \ ++ .mapbase = (resource_size_t)(IPROC_##name##_PA), \ ++ .irq = IRQ_IPROC_UART0, \ ++ .uartclk = IPROC_UART_CLK, \ ++ .regshift = 0, \ ++ .iotype = UPIO_MEM, \ ++ .type = PORT_16550A, \ ++ .flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ, \ ++ .private_data = (void __iomem *)((IPROC_##name##_VA) + 0x00), \ ++} ++ ++ ++#define IPROC_APB_CLK 125000000 ++ ++#define IPROC_8250PORT_UART2(name) \ ++{ \ ++ .membase = (void __iomem *)(IPROC_##name##_VA), \ ++ .mapbase = (resource_size_t)(IPROC_##name##_PA), \ ++ .irq = 124, \ ++ .uartclk = IPROC_APB_CLK, \ ++ .regshift = 2, \ ++ .iotype = UPIO_MEM32, \ ++ .type = PORT_16550A, \ ++ .flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ, \ ++ .private_data = (void __iomem *)((IPROC_##name##_VA) + 0x00), \ ++} ++ ++#endif /* CONFIG_MACH_IPROC_P7 */ ++ ++static struct plat_serial8250_port uart_data[] = { ++#if (defined(CONFIG_MACH_HR2) && !defined(CONFIG_MACH_IPROC_EMULATION)) ++ IPROC_8250PORT(UART1), /* Use UART2 as ttys0 */ ++ IPROC_8250PORT(UART0), ++#elif defined(CONFIG_MACH_CYGNUS) ++ IPROC_8250PORT(UART3), ++ IPROC_8250PORT(UART0), ++#else ++ IPROC_8250PORT(UART0), ++ IPROC_8250PORT(UART1), ++#endif ++ { .flags = 0, }, ++}; ++ ++static struct platform_device board_serial_device = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = uart_data, ++ }, ++}; ++ ++#if defined(CONFIG_MPCORE_WATCHDOG) ++static struct resource wdt_device_resource[] = { ++ [0] = { ++ .start = IPROC_PERIPH_PVT_TIM_REG_BASE, ++ .end = IPROC_PERIPH_PVT_TIM_REG_BASE + 0x34, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = BCM_INT_ID_CCB_TIM1_INT2, ++ .end = BCM_INT_ID_CCB_TIM1_INT2, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device wdt_device = ++{ ++ .name = "mpcore_wdt", ++ .id = -1, ++ .resource = wdt_device_resource, ++ .num_resources = ARRAY_SIZE(wdt_device_resource), ++}; ++#endif ++enum { ++ HX4_NONE = 0, ++ HX4_DNI_3448P, ++ HX4_ACCTON_AS4610_54 ++}; ++ ++/* ++ * API to return the type of platform retrieved from device tree ++ * Note: This is hack until complete device tree is supported for ++ * for all broadcom iproc device drivers ++ */ ++int brcm_get_hx4_model(void) ++{ ++ const char *model = NULL; ++ unsigned long dt_root; ++ ++ dt_root = of_get_flat_dt_root(); ++ model = of_get_flat_dt_prop(dt_root, "model", NULL); ++ if (!model) { ++ model = of_get_flat_dt_prop(dt_root, "compatible", NULL); ++ if (!model) ++ model = ""; ++ } ++ ++ if (!strcmp(model, "dni,3448p")) ++ return HX4_DNI_3448P; ++ else if (!strcmp(model, "accton,as4610_54")) ++ return HX4_ACCTON_AS4610_54; ++ ++ printk( KERN_ERR "Unknown Model %s\n", model ); ++ return HX4_NONE; ++} ++ ++/* Common devices among all Northstar boards */ ++//static struct platform_device *board_common_plat_devices[] __initdata = { ++// &board_serial_device, ++//#if defined(CONFIG_MPCORE_WATCHDOG) ++// &wdt_device, ++//#endif ++//}; ++ ++void __init iproc_config_boot_console(struct clk *ref_clk) ++{ ++ u32 i; ++ u32 clk_rate = IPROC_UART_CLK; ++ ++#ifndef CONFIG_MACH_IPROC_P7 ++ u8 uart_clk_sel; ++ u8 uart_clk_ovr; ++ u16 uart_clk_div; ++ struct clk * clk = NULL ; ++ int modelnum; ++ ++ /* Get Core Capabilities Register, and extract ++ UART Clock Select from bits 4..3 which show ++ the clock source. Values are: ++ 0 = 25Mhz clock input ++ 1 = Internal clock ++ 2 = reserved ++ 3 = reserved ++ */ ++ uart_clk_sel = (readl(IPROC_CCA_CCAP_VA) >> 3) & 0x3; ++ ++ /* Get UARTClkOvr from bit 0 of the Core Control Register ++ If set, this bit indicates that the UART clock is supplied ++ from the internal ALP (APB) clock. If clear then it indicates ++ that APBX_IDM_IO_CONTROL_DIRECT register bit UARTClkSel controls ++ the clock source ++ */ ++ uart_clk_ovr = readl(IPROC_CCA_CCTL_VA) & 0x01; ++ ++ /* uart_clk_div: ChipcommonA_ClkDiv bits 0..7 */ ++ uart_clk_div = 0xff & readl(IPROC_CCA_UART_CLK_VA); ++ if( uart_clk_div == 0 ) ++ uart_clk_div = 0x100 ; ++ ++ if( uart_clk_sel == 0 ) { ++ /* uart_clk_sel = 0 -> external reference clock source */ ++ clk = ref_clk ; ++ BUG_ON( !clk ); ++ clk_rate = clk_get_rate(clk); ++ } else if( uart_clk_sel == 1 ) { ++ /* uart_clk_sel = 1 -> Internal clock optionally divided */ ++ clk = clk_get_sys( "iproc_slow", "c_clk125" ); ++ BUG_ON( !clk ); ++#if defined(CONFIG_MACH_IPROC_EMULATION) ++ clk_rate = IPROC_UART_CLK ; ++#else ++ clk_rate = clk_get_rate(clk) ; ++#endif ++ ++ if( ! uart_clk_ovr ) ++ clk_rate /= uart_clk_div; ++ } ++ ++ printk( KERN_INFO "Sel=%d Ovr=%d Div=%d\n", uart_clk_sel, uart_clk_ovr, uart_clk_div ); ++ printk( KERN_INFO "UART clock rate %u\n", clk_rate ); ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++ ++ modelnum = brcm_get_hx4_model(); ++ if (modelnum == HX4_ACCTON_AS4610_54) { ++ for(i = 0; i < ARRAY_SIZE(uart_data); i++ ) { ++ switch (i) { ++ case 0: ++ uart_data[i].membase = (void __iomem *)(IPROC_UART1_VA); ++ uart_data[i].mapbase = (resource_size_t)(IPROC_UART1_PA); ++ uart_data[i].irq = IRQ_IPROC_UART0; ++ uart_data[i].uartclk = IPROC_UART_CLK; ++ uart_data[i].regshift = 0; ++ uart_data[i].iotype = UPIO_MEM; ++ uart_data[i].type = PORT_16550A; ++ uart_data[i].flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ; ++ uart_data[i].private_data = (void __iomem *)((IPROC_UART1_VA) + 0x00); ++ break; ++ case 1: ++ uart_data[i].membase = (void __iomem *)(IPROC_UART2_VA); ++ uart_data[i].mapbase = (resource_size_t)(IPROC_UART2_PA); ++ uart_data[i].irq = 124; ++ uart_data[i].uartclk = IPROC_APB_CLK; ++ uart_data[i].regshift = 2; ++ uart_data[i].iotype = UPIO_MEM32; ++ uart_data[i].type = PORT_16550A; ++ uart_data[i].flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ; ++ uart_data[i].private_data = (void __iomem *)((IPROC_UART2_VA) + 0x00); ++ break; ++ } ++ } ++ } ++ ++ /* fixup UART port structure */ ++ for(i = 0; i < ARRAY_SIZE(uart_data); i++ ) { ++ if( uart_data[i].flags == 0 ) ++ break; ++ if( uart_data[i].irq == 0 ) ++ uart_data[i].flags |= UPF_AUTO_IRQ; ++ ++ /* XXX TBD - UART input clock source and rate */ ++ if(i != 1) { ++ uart_data[i].uartclk = clk_rate ; ++ } ++ ++ } ++ ++ /* Install SoC devices in the system: uarts */ ++ platform_device_register(&board_serial_device); ++ ++#ifndef CONFIG_MACH_IPROC_P7 ++ /* Enable UART interrupt in ChipcommonA */ ++ i = readl(IPROC_CCA_INTMASK_VA); ++ i |= 1 << 6; ++ writel(i, IPROC_CCA_INTMASK_VA); ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++} ++ ++void __init board_add_common_devices(struct clk *ref_clk) ++{ ++ /* ++ * Configure boot console ++ */ ++ iproc_config_boot_console(ref_clk); ++} +diff --git a/arch/arm/mach-iproc/common.h b/arch/arm/mach-iproc/common.h +new file mode 100644 +index 0000000..d49a6b9 +--- /dev/null ++++ b/arch/arm/mach-iproc/common.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __MACH_NORTHSTAR_COMMON_H ++#define __MACH_NORTHSTAR_COMMON_H ++#include ++#include ++#include ++#include ++ ++#include ++ ++void __init board_add_common_devices(struct clk *ref_clk); ++ ++#endif /* __MACH_NORTHSTAR_COMMON_H */ +diff --git a/arch/arm/mach-iproc/flash.c b/arch/arm/mach-iproc/flash.c +new file mode 100644 +index 0000000..8fd637b +--- /dev/null ++++ b/arch/arm/mach-iproc/flash.c +@@ -0,0 +1,375 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#include ++ ++#ifdef CONFIG_MTD ++ ++#include ++#include ++#include ++ ++/* Since GSIO uses bus number 0, QSPI uses bus number 1 */ ++#define IPROC_QSPI_BUS_NUMBER (1) ++ ++/* Currently NAND controller only supports 2 LUNs */ ++#define IPROC_NAND_MAX_LUNS (2) ++ ++int brcm_get_hx4_model(void); ++ ++#if defined(CONFIG_IPROC_QSPI) || defined(CONFIG_IPROC_QSPI_MODULE) ++static struct mtd_partition accton_as4610_sflash_partition_map[] = { ++ { ++ .name = "nboot", ++ .offset = 0x00000000, ++ .size = 0x000e0000, ++ }, ++ { ++ .name = "shmoo", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x0010000, ++ }, ++ { ++ .name = "uboot-env", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00010000, ++ }, ++ { ++ .name = "onie", ++ .offset = MTDPART_OFS_APPEND, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++#if defined(CONFIG_MACH_HX4) ++static struct mtd_partition sflash_partition_map[] = { ++ { ++ .name = "boot", ++ .offset = 0x00000000, ++ .size = 640 * 1024, ++ }, ++ { ++ .name = "env", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 384 * 1024, ++ }, ++ { ++ .name = "system", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 15 * 1024 * 1024, ++ }, ++ { ++ .name = "rootfs", ++ .offset = MTDPART_OFS_APPEND, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++#endif /* Unused code for Accton AS4610-54 and DNI-3448P */ ++#endif /* CONFIG_IPROC_QSPI || CONFIG_IPROC_QSPI_MODULE */ ++ ++#if defined(CONFIG_IPROC_MTD_NAND) || defined(CONFIG_IPROC_MTD_NAND_MODULE) ++static struct mtd_partition dni_3448p_nand_partition_map[] = { ++ { ++ .name = "uboot", ++ .offset = 0x00000000, ++ .size = 0x00100000, ++ }, ++ { ++ .name = "uboot-env", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00400000, ++ }, ++ { ++ .name = "vpd", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00200000, ++ }, ++ { ++ .name = "shmoo", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00200000, ++ }, ++ { ++ .name = "open", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0xf9500000, ++ }, ++ { ++ .name = "onie", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00c00000, ++ }, ++ { ++ .name = "onie2", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00c00000, ++ }, ++ { ++ .name = "board_eeprom", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00600000, ++ }, ++ { ++ .name = "diag", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x02000000, ++ }, ++ { ++ .name = "diag2", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x02000000, ++ }, ++}; ++static struct mtd_partition accton_as4610_nand_partition_map[] = { ++}; ++ ++static struct mtd_partition nand_partition_map[] = { ++ { ++ .name = "nboot", ++ .offset = 0x00000000, ++ .size = 2 * 1024 * 1024, ++ }, ++ { ++ .name = "nenv", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 4 * 1024 * 1024, ++ }, ++ { ++ .name = "nsystem", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 10 * 1024 * 1024, ++ }, ++ { ++ .name = "nrootfs", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 48 * 1024 * 1024, ++ }, ++ { ++ .name = "ncustfs", ++ .offset = MTDPART_OFS_APPEND, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++#endif /* CONFIG_IPROC_MTD_NAND || CONFIG_IPROC_MTD_NAND_MODULE */ ++ ++enum { ++ HX4_NONE = 0, ++ HX4_DNI_3448P, ++ HX4_ACCTON_AS4610_54 ++}; ++ ++#if defined(CONFIG_IPROC_QSPI) || defined(CONFIG_IPROC_QSPI_MODULE) ++static int __init ++brcm_setup_spi_master(int cs, int bus_id) ++{ ++ struct brcmspi_platform_data pdata; ++ struct platform_device *pdev; ++ const struct resource res[] = { ++ { ++ .start = IPROC_QSPI_IRQ_START, ++ .end = IPROC_QSPI_IRQ_END, ++ .flags = IORESOURCE_IRQ ++ }, ++ { ++ .start = QSPI_MSPI_SPCR0_LSB, ++ .end = QSPI_MSPI_DISABLE_FLUSH_GEN + 3, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = QSPI_BSPI_REGS_REV_ID, ++ .end = QSPI_BSPI_REGS_BSPI_PIO_DATA + 3, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = QSPI_RAF_START_ADDR, ++ .end = QSPI_RAF_CURR_ADDR + 3, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = QSPI_RAF_INTERRUPT_LR_FULLNESS_REACHED, ++ .end = QSPI_MSPI_INTERRUPT_MSPI_HALT_SET_TRANSACTION_DONE + 3, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = IPROC_IDM_QSPI_REG_BASE, ++ .end = IPROC_IDM_QSPI_REG_BASE + 3, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = IPROC_CRU_REG_BASE, ++ .end = IPROC_CRU_REG_BASE + 3, ++ .flags = IORESOURCE_MEM ++ }, ++ }; ++ ++ memset(&pdata, 0, sizeof(pdata)); ++ pdata.flash_cs = cs; ++ pdev = platform_device_alloc("qspi_iproc", bus_id); ++ if (!pdev || ++ platform_device_add_resources(pdev, res, sizeof(res)/sizeof(res[0])) || ++ platform_device_add_data(pdev, &pdata, sizeof(pdata)) || ++ platform_device_add(pdev)) { ++ platform_device_put(pdev); ++ return -ENODEV; ++ } ++ return 0; ++} ++ ++static int __init ++brcm_setup_spi_flash(int cs, int bus_num, int nr_parts, struct mtd_partition *parts) ++{ ++ struct spi_board_info board_info; ++ struct flash_platform_data *pdata; ++ struct spi_master *master; ++ ++ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return -ENOMEM; ++ ++ pdata->nr_parts = nr_parts; ++ pdata->parts = parts; ++ ++ memset(&board_info, 0, sizeof(board_info)); ++ ++ strcpy(board_info.modalias, "m25p80"); ++ board_info.bus_num = bus_num; ++ board_info.chip_select = cs; ++ board_info.max_speed_hz = CONFIG_IPROC_QSPI_MAX_HZ; ++ board_info.mode = SPI_MODE_3; ++ board_info.platform_data = pdata; ++ ++ master = spi_busnum_to_master(bus_num); ++ if (master) { ++ /* Master driver already loaded */ ++ if (spi_new_device(master, &board_info) == NULL) { ++ printk(KERN_WARNING "%s: can't add SPI device\n", __func__); ++ kfree(pdata); ++ return -ENODEV; ++ } ++ } else { ++ /* Master driver not yet loaded, register the board first. */ ++ if (spi_register_board_info(&board_info, 1) != 0) { ++ printk(KERN_WARNING "%s: can't register SPI device\n", __func__); ++ kfree(pdata); ++ return -ENODEV; ++ } ++ } ++ ++ return 0; ++} ++#endif /* CONFIG_IPROC_QSPI || CONFIG_IPROC_QSPI_MODULE */ ++ ++#if defined(CONFIG_IPROC_MTD_NAND) || defined(CONFIG_IPROC_MTD_NAND_MODULE) ++static void __init ++northstar_setup_nand_flash(void) ++{ ++ u32 straps; ++ struct platform_device *pdev; ++ struct brcmnand_platform_data pdata; ++ int i, modelnum; ++ ++ straps = __REG32(IPROC_DMU_BASE_VA + IPROC_DMU_STRAPS_OFFSET); ++ pdata.strap_boot = ((straps >> IPROC_STRAP_BOOT_DEV_SHIFT) & 3) == 1; ++ pdata.strap_type = (straps >> IPROC_STRAP_NAND_TYPE_SHIFT) & 0xf; ++ pdata.strap_page_size = (straps >> IPROC_STRAP_NAND_PAGE_SHIFT) & 0x3; ++ if (!pdata.strap_boot) { ++ pdata.strap_type &= 0x7; ++ } ++ ++ modelnum = brcm_get_hx4_model(); ++ ++ if (modelnum == HX4_DNI_3448P) { ++ pdata.nr_parts = ARRAY_SIZE(dni_3448p_nand_partition_map); ++ pdata.parts = dni_3448p_nand_partition_map; ++ } else if (modelnum == HX4_ACCTON_AS4610_54) { ++ pdata.nr_parts = ARRAY_SIZE(accton_as4610_nand_partition_map); ++ pdata.parts = accton_as4610_nand_partition_map; ++ } else { ++ pdata.nr_parts = ARRAY_SIZE(nand_partition_map); ++ pdata.parts = nand_partition_map; ++ } ++ ++ for(i=0; i 0) { ++ pdata.nr_parts = 0; ++ pdata.parts = NULL; ++ } ++ ++ pdata.chip_select = i; ++ pdev = platform_device_alloc("nand_iproc", i); ++ if (!pdev || ++ platform_device_add_data(pdev, &pdata, sizeof(pdata)) || ++ platform_device_add(pdev)) { ++ platform_device_put(pdev); ++ } ++ } ++} ++#endif /* CONFIG_IPROC_MTD_NAND || CONFIG_IPROC_MTD_NAND_MODULE */ ++ ++static int __init ++northstar_mtd_setup(void) ++{ ++#if defined(CONFIG_IPROC_QSPI) || defined(CONFIG_IPROC_QSPI_MODULE) ++ if (brcm_get_hx4_model() == HX4_ACCTON_AS4610_54) { ++ /* SPI flash (currently used for primary) */ ++ brcm_setup_spi_master( ++ 0, ++ IPROC_QSPI_BUS_NUMBER ++ ); ++ brcm_setup_spi_flash( ++ 0, ++ IPROC_QSPI_BUS_NUMBER, ++ ARRAY_SIZE(accton_as4610_sflash_partition_map), ++ accton_as4610_sflash_partition_map ++ ); ++ } /* Required only for Accton AS4610 54*/ ++#endif /* CONFIG_IPROC_QSPI || CONFIG_IPROC_QSPI_MODULE */ ++ ++#if defined(CONFIG_IPROC_MTD_NAND) || defined(CONFIG_IPROC_MTD_NAND_MODULE) ++#ifdef CONFIG_MACH_NS ++ /* Don't bring up NAND driver if it's BCM53010 */ ++ if ((__REG32(IPROC_IDM_REGISTER_VA + 0xd500) & 0xc) != 0x4) ++#endif /* CONFIG_MACH_NS */ ++ northstar_setup_nand_flash(); ++#endif /* CONFIG_IPROC_MTD_NAND || CONFIG_IPROC_MTD_NAND_MODULE */ ++ ++ return 0; ++} ++ ++/* ++ * late_initcall means the flash drivers are already loaded, so we control ++ * the order in which the /dev/mtd* devices get created. ++ */ ++late_initcall(northstar_mtd_setup); ++ ++#endif /* CONFIG_MTD */ +diff --git a/arch/arm/mach-iproc/idm.c b/arch/arm/mach-iproc/idm.c +new file mode 100644 +index 0000000..444c3fe +--- /dev/null ++++ b/arch/arm/mach-iproc/idm.c +@@ -0,0 +1,723 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_MACH_NSP ++/* this is actually AXI_PCIE_S2 but for HX4, HR2, and KT2 it has been hijacked by CMICD */ ++ ++#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL AXI_PCIE_S2_IDM_IDM_ERROR_LOG_CONTROL ++#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE AXI_PCIE_S2_IDM_IDM_ERROR_LOG_COMPLETE ++#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS AXI_PCIE_S2_IDM_IDM_ERROR_LOG_STATUS ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB AXI_PCIE_S2_IDM_IDM_ERROR_LOG_ADDR_LSB ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ID AXI_PCIE_S2_IDM_IDM_ERROR_LOG_ID ++#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS AXI_PCIE_S2_IDM_IDM_ERROR_LOG_FLAGS ++#define CMICD_S0_IDM_IDM_INTERRUPT_STATUS AXI_PCIE_S2_IDM_IDM_INTERRUPT_STATUS ++ ++#endif ++ ++#ifdef CONFIG_MACH_NS ++ ++#define IHOST_S1_IDM_ERROR_LOG_CONTROL 0x18106900 ++#define IHOST_S1_IDM_ERROR_LOG_COMPLETE 0x18106904 ++#define IHOST_S1_IDM_ERROR_LOG_STATUS 0x18106908 ++#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810690C ++#define IHOST_S1_IDM_ERROR_LOG_ID 0x18106914 ++#define IHOST_S1_IDM_ERROR_LOG_FLAGS 0x1810691C ++#define IHOST_S1_IDM_INTERRUPT_STATUS 0x18106A00 ++ ++#define IHOST_S0_IDM_ERROR_LOG_CONTROL 0x18107900 ++#define IHOST_S0_IDM_ERROR_LOG_COMPLETE 0x18107904 ++#define IHOST_S0_IDM_ERROR_LOG_STATUS 0x18107908 ++#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810790C ++#define IHOST_S0_IDM_ERROR_LOG_ID 0x18107914 ++#define IHOST_S0_IDM_ERROR_LOG_FLAGS 0x1810791C ++#define IHOST_S0_IDM_INTERRUPT_STATUS 0x18107A00 ++ ++#define DDR_S1_IDM_ERROR_LOG_CONTROL 0x18108900 ++#define DDR_S1_IDM_ERROR_LOG_COMPLETE 0x18108904 ++#define DDR_S1_IDM_ERROR_LOG_STATUS 0x18108908 ++#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810890C ++#define DDR_S1_IDM_ERROR_LOG_ID 0x18108914 ++#define DDR_S1_IDM_ERROR_LOG_FLAGS 0x1810891C ++#define DDR_S1_IDM_INTERRUPT_STATUS 0x18108A00 ++ ++#define DDR_S2_IDM_ERROR_LOG_CONTROL 0x18109900 ++#define DDR_S2_IDM_ERROR_LOG_COMPLETE 0x18109904 ++#define DDR_S2_IDM_ERROR_LOG_STATUS 0x18109908 ++#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB 0x1810990C ++#define DDR_S2_IDM_ERROR_LOG_ID 0x18109914 ++#define DDR_S2_IDM_ERROR_LOG_FLAGS 0x1810991C ++#define DDR_S2_IDM_INTERRUPT_STATUS 0x18109A00 ++ ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810A900 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810A904 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810A908 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810A90C ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID 0x1810A914 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810A91C ++#define AXI_PCIE_S0_IDM_IDM_INTERRUPT_STATUS 0x1810AA00 ++ ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_CONTROL 0x1810B900 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_COMPLETE 0x1810B904 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_STATUS 0x1810B908 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810B90C ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ID 0x1810B914 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_FLAGS 0x1810B91C ++#define AXI_PCIE_S1_IDM_IDM_INTERRUPT_STATUS 0x1810BA00 ++ ++/* this is actually AXI_PCIE_S2 but for HX4, HR2, and KT2 it has been hijacked by CMICD */ ++ ++#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810C900 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810C904 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810C908 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810C90C ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ID 0x1810C914 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810C91C ++#define CMICD_S0_IDM_IDM_INTERRUPT_STATUS 0x1810CA00 ++ ++#define ROM_S0_IDM_ERROR_LOG_CONTROL 0x1810D900 ++#define ROM_S0_IDM_ERROR_LOG_COMPLETE 0x1810D904 ++#define ROM_S0_IDM_ERROR_LOG_STATUS 0x1810D908 ++#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810D90C ++#define ROM_S0_IDM_ERROR_LOG_ID 0x1810D914 ++#define ROM_S0_IDM_ERROR_LOG_FLAGS 0x1810D91C ++#define ROM_S0_IDM_INTERRUPT_STATUS 0x1810DA00 ++ ++#define NAND_IDM_IDM_ERROR_LOG_CONTROL 0x1811A900 ++#define NAND_IDM_IDM_ERROR_LOG_COMPLETE 0x1811A904 ++#define NAND_IDM_IDM_ERROR_LOG_STATUS 0x1811A908 ++#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811A90C ++#define NAND_IDM_IDM_ERROR_LOG_ID 0x1811A914 ++#define NAND_IDM_IDM_ERROR_LOG_FLAGS 0x1811A91C ++#define NAND_IDM_IDM_INTERRUPT_STATUS 0x1811AA00 ++ ++#define QSPI_IDM_IDM_ERROR_LOG_CONTROL 0x1811B900 ++#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE 0x1811B904 ++#define QSPI_IDM_IDM_ERROR_LOG_STATUS 0x1811B908 ++#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811B90C ++#define QSPI_IDM_IDM_ERROR_LOG_ID 0x1811B914 ++#define QSPI_IDM_IDM_ERROR_LOG_FLAGS 0x1811B91C ++#define QSPI_IDM_IDM_INTERRUPT_STATUS 0x1811BA00 ++ ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1811C900 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1811C904 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS 0x1811C908 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811C90C ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID 0x1811C914 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1811C91C ++#define A9JTAG_S0_IDM_IDM_INTERRUPT_STATUS 0x1811CA00 ++ ++#define APBX_IDM_IDM_ERROR_LOG_CONTROL 0x18121900 ++#define APBX_IDM_IDM_ERROR_LOG_COMPLETE 0x18121904 ++#define APBX_IDM_IDM_ERROR_LOG_STATUS 0x18121908 ++#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1812190C ++#define APBX_IDM_IDM_ERROR_LOG_ID 0x18121914 ++#define APBX_IDM_IDM_ERROR_LOG_FLAGS 0x1812191C ++#define APBX_IDM_IDM_INTERRUPT_STATUS 0x1812A900 ++ ++#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL 0x18132900 ++#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE 0x18132904 ++#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS 0x181312908 ++#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB 0x1813290c ++#define AXIIC_DS_0_IDM_ERROR_LOG_ID 0x18132910 ++#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS 0x18132904 ++#define AXIIC_DS_0_IDM_INTERRUPT_STATUS 0x18132A00 ++ ++#define AXIIC_DS_1_IDM_ERROR_LOG_CONTROL 0x18133900 ++#define AXIIC_DS_1_IDM_ERROR_LOG_COMPLETE 0x18133904 ++#define AXIIC_DS_1_IDM_ERROR_LOG_STATUS 0x181313908 ++#define AXIIC_DS_1_IDM_ERROR_LOG_ADDR_LSB 0x1813390c ++#define AXIIC_DS_1_IDM_ERROR_LOG_ID 0x18133910 ++#define AXIIC_DS_1_IDM_ERROR_LOG_FLAGS 0x18133904 ++#define AXIIC_DS_1_IDM_INTERRUPT_STATUS 0x18133A00 ++ ++#define AXIIC_DS_2_IDM_ERROR_LOG_CONTROL 0x18134900 ++#define AXIIC_DS_2_IDM_ERROR_LOG_COMPLETE 0x18134904 ++#define AXIIC_DS_2_IDM_ERROR_LOG_STATUS 0x181314908 ++#define AXIIC_DS_2_IDM_ERROR_LOG_ADDR_LSB 0x1813490c ++#define AXIIC_DS_2_IDM_ERROR_LOG_ID 0x18134910 ++#define AXIIC_DS_2_IDM_ERROR_LOG_FLAGS 0x18134904 ++#define AXIIC_DS_2_IDM_INTERRUPT_STATUS 0x18134A00 ++ ++#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL 0x18135900 ++#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE 0x18135904 ++#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS 0x181315908 ++#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB 0x1813590c ++#define AXIIC_DS_3_IDM_ERROR_LOG_ID 0x18135910 ++#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS 0x18135904 ++#define AXIIC_DS_3_IDM_INTERRUPT_STATUS 0x18135A00 ++ ++#define AXIIC_DS_4_IDM_ERROR_LOG_CONTROL 0x18136900 ++#define AXIIC_DS_4_IDM_ERROR_LOG_COMPLETE 0x18136904 ++#define AXIIC_DS_4_IDM_ERROR_LOG_STATUS 0x181316908 ++#define AXIIC_DS_4_IDM_ERROR_LOG_ADDR_LSB 0x1813690c ++#define AXIIC_DS_4_IDM_ERROR_LOG_ID 0x18136910 ++#define AXIIC_DS_4_IDM_ERROR_LOG_FLAGS 0x18136904 ++#define AXIIC_DS_4_IDM_INTERRUPT_STATUS 0x18136A00 ++ ++#define IHOST_L2C_INT_MASK 0x19022214 ++#define IHOST_GICDIST_enable_set2 0x19021108 ++ ++#endif ++ ++#define IHOST_L2C_INT_MASK_VA HW_IO_PHYS_TO_VIRT(IHOST_L2C_INT_MASK) ++#define IHOST_GICDIST_enable_set2_VA HW_IO_PHYS_TO_VIRT(IHOST_GICDIST_enable_set2) ++ ++#define IHOST_S1_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_CONTROL) ++#define IHOST_S1_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_COMPLETE) ++#define IHOST_S1_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_STATUS) ++#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_ADDR_LSB) ++#define IHOST_S1_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_ID) ++#define IHOST_S1_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_FLAGS) ++ ++#define IHOST_S0_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_CONTROL) ++#define IHOST_S0_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_COMPLETE) ++#define IHOST_S0_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_STATUS) ++#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_ADDR_LSB) ++#define IHOST_S0_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_ID) ++#define IHOST_S0_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_FLAGS) ++ ++#define DDR_S1_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_CONTROL) ++#define DDR_S1_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_COMPLETE) ++#define DDR_S1_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_STATUS) ++#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_ADDR_LSB) ++#define DDR_S1_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_ID) ++#define DDR_S1_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_FLAGS) ++ ++#define DDR_S2_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_CONTROL) ++#define DDR_S2_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_COMPLETE) ++#define DDR_S2_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_STATUS) ++#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_ADDR_LSB) ++#define DDR_S2_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_ID) ++#define DDR_S2_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_FLAGS) ++ ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL) ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE) ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS) ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID) ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL) ++#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE) ++#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_STATUS) ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_ID) ++#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define APBY_S0_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_CONTROL) ++#define APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE) ++#define APBY_S0_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_STATUS) ++#define APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define APBY_S0_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_ID) ++#define APBY_S0_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define ROM_S0_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_CONTROL) ++#define ROM_S0_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_COMPLETE) ++#define ROM_S0_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_STATUS) ++#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_ADDR_LSB) ++#define ROM_S0_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_ID) ++#define ROM_S0_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_FLAGS) ++ ++#define NAND_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_CONTROL) ++#define NAND_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_COMPLETE) ++#define NAND_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_STATUS) ++#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define NAND_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_ID) ++#define NAND_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define QSPI_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_CONTROL) ++#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_COMPLETE) ++#define QSPI_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_STATUS) ++#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define QSPI_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_ID) ++#define QSPI_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL) ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE) ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS) ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_ID) ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define SRAM_S0_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_CONTROL) ++#define SRAM_S0_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_COMPLETE) ++#define SRAM_S0_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_STATUS) ++#define SRAM_S0_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_ADDR_LSB) ++#define SRAM_S0_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_ID) ++#define SRAM_S0_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_FLAGS) ++ ++#define APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL) ++#define APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE) ++#define APBZ_S0_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_STATUS) ++#define APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define APBZ_S0_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_ID) ++#define APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_CONTROL) ++#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE) ++#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_STATUS) ++#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB) ++#define AXIIC_DS_3_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_ID) ++#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_FLAGS) ++ ++#define APBW_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_CONTROL) ++#define APBW_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_COMPLETE) ++#define APBW_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_STATUS) ++#define APBW_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define APBW_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_ID) ++#define APBW_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define APBX_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_CONTROL) ++#define APBX_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_COMPLETE) ++#define APBX_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_STATUS) ++#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define APBX_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_ID) ++#define APBX_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_CONTROL) ++#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE) ++#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_STATUS) ++#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB) ++#define AXIIC_DS_0_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_ID) ++#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_FLAGS) ++ ++#define IDM_ERROR_LOG_ENABLE 0x33A ++#define IDM_ERROR_LOG_CLEAR 0x3 ++ ++#ifdef CONFIG_MACH_IPROC_P7 ++#define IHOST_S0_IDM_IRQ 52 ++#define DDR_S1_IDM_IRQ 54 ++#define DDR_S2_IDM_IRQ 55 ++#define AXI_PCIE_S0_IDM_IRQ 56 ++#define AXI_PCIE_S1_IDM_IRQ 57 ++#define ROM_S0_IDM_IRQ 58 ++#define NAND_IDM_IRQ 59 ++#define QSPI_IDM_IRQ 60 ++#define SRAM_S0_IDM_IRQ 62 ++#define A9JTAG_S0_IDM_IRQ 64 ++#define APX_IDM_IRQ 68 ++#define CMICD_S0_IDM_IRQ 71 ++#define AXIIC_DS_0_IDM_IRQ 78 ++#define AXIIC_DS_1_IDM_IRQ 79 ++#define AXIIC_DS_2_IDM_IRQ 80 ++#define AXIIC_DS_3_IDM_IRQ 81 ++#define AXIIC_DS_4_IDM_IRQ 83 ++#else ++#define IHOST_S1_IDM_IRQ 62 ++#define IHOST_S0_IDM_IRQ 63 ++#define DDR_S1_IDM_IRQ 64 ++#define DDR_S2_IDM_IRQ 65 ++#define AXI_PCIE_S0_IDM_IRQ 66 ++#define AXI_PCIE_S1_IDM_IRQ 67 ++#define CMICD_S0_IDM_IRQ 68 ++#define ROM_S0_IDM_IRQ 69 ++#define NAND_IDM_IRQ 70 ++#define QSPI_IDM_IRQ 71 ++#define SATA_IDM_IRQ 72 ++#define A9JTAG_S0_IDM_IRQ 73 ++#define SRAM_S0_IDM_IRQ 74 ++#define APW_IDM_IRQ 75 ++#define APX_IDM_IRQ 76 ++#define APBY_S0_IDM_IRQ 77 ++#define APBZ_S0_IDM_IRQ 78 ++#define AXIIC_DS_0_IDM_IRQ 79 ++#define AXIIC_DS_1_IDM_IRQ 80 ++#define AXIIC_DS_2_IDM_IRQ 81 ++#define AXIIC_DS_3_IDM_IRQ 82 ++#define AXIIC_DS_4_IDM_IRQ 83 ++#endif ++ ++static irqreturn_t idm_timeout_handler(int val, void *ptr) ++{ ++ u32 errStat; ++// printk("%s: %d, %d entry\n", __FUNCTION__, __LINE__, val); ++ errStat = __raw_readl(IHOST_S1_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(IHOST_S1_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(IHOST_S1_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(IHOST_S1_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, IHOST_S1_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(IHOST_S1_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(IHOST_S0_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(IHOST_S0_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(IHOST_S0_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(IHOST_S0_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, IHOST_S0_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(IHOST_S0_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(DDR_S1_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(DDR_S1_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(DDR_S1_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(DDR_S1_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, DDR_S1_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(DDR_S1_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(DDR_S2_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(DDR_S2_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(DDR_S2_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(DDR_S2_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, DDR_S2_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(DDR_S2_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(CMICD_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(CMICD_S0_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(CMICD_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++#if !defined(CONFIG_MACH_NS) && !defined(CONFIG_MACH_IPROC_P7) ++ errStat = __raw_readl(APBY_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBY_S0_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBY_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(APBY_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++#endif ++ errStat = __raw_readl(ROM_S0_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(ROM_S0_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(ROM_S0_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(ROM_S0_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, ROM_S0_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(ROM_S0_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(NAND_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(NAND_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(NAND_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(NAND_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, NAND_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(NAND_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(QSPI_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(QSPI_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(QSPI_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, QSPI_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(QSPI_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++#if !defined(CONFIG_MACH_NS) && !defined(CONFIG_MACH_IPROC_P7) ++ errStat = __raw_readl(SRAM_S0_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(SRAM_S0_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(SRAM_S0_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(SRAM_S0_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, SRAM_S0_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(SRAM_S0_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(APBZ_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBZ_S0_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(APBZ_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++#endif ++ errStat = __raw_readl(AXIIC_DS_3_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXIIC_DS_3_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXIIC_DS_3_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(AXIIC_DS_3_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++#if !defined(CONFIG_MACH_NS) && !defined(CONFIG_MACH_IPROC_P7) ++ errStat = __raw_readl(APBW_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBW_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBW_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBW_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, APBW_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(APBW_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++#endif ++ errStat = __raw_readl(APBX_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBX_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBX_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBX_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, APBX_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(APBX_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(AXIIC_DS_0_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXIIC_DS_0_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXIIC_DS_0_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(AXIIC_DS_0_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++// printk("%s: %d exit\n", __FUNCTION__, __LINE__); ++ return IRQ_HANDLED; ++} ++ ++int l2cc_interrupt_error_handler(int val, void *ptr) ++{ ++ printk("%s: %d, %d entry\n", __FUNCTION__, __LINE__, val); ++ printk("%s: %d exit\n", __FUNCTION__, __LINE__); ++ return 0; ++} ++ ++void request_idm_timeout_interrupts(void) ++{ ++ u32 l2cc_mask; ++ int ret = 0; ++ ++// printk("%s: %d entry\n", __FUNCTION__, __LINE__); ++ ++ /* clear all pending idm interrupts */ ++ idm_timeout_handler(0, NULL); ++ ++ /* enable idm error log for all slaves */ ++ ++ __raw_writel(IDM_ERROR_LOG_ENABLE, IHOST_S1_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, IHOST_S0_IDM_ERROR_LOG_COMPLETE_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, DDR_S1_IDM_ERROR_LOG_COMPLETE_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, DDR_S2_IDM_ERROR_LOG_COMPLETE_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ ++#ifndef CONFIG_MACH_NS ++ __raw_writel(IDM_ERROR_LOG_ENABLE, SRAM_S0_IDM_ERROR_LOG_CONTROL_VA); ++#ifndef CONFIG_MACH_IPROC_P7 ++ __raw_writel(IDM_ERROR_LOG_ENABLE, APBY_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, APBW_IDM_IDM_ERROR_LOG_CONTROL_VA); ++#endif ++#endif ++ ++ __raw_writel(IDM_ERROR_LOG_ENABLE, ROM_S0_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, NAND_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, QSPI_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, APBX_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, AXIIC_DS_0_IDM_ERROR_LOG_CONTROL_VA); ++ ++ /* now enable the idm interrupts */ ++ ++#ifndef CONFIG_MACH_IPROC_P7 ++ ret = request_irq(IHOST_S1_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++ ret = request_irq(IHOST_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(DDR_S1_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(DDR_S2_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(AXI_PCIE_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(AXI_PCIE_S1_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(CMICD_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(ROM_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(NAND_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(QSPI_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#ifndef CONFIG_MACH_IPROC_P7 ++ ret = request_irq(SATA_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++ ret = request_irq(A9JTAG_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(SRAM_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(APX_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#ifndef CONFIG_MACH_IPROC_P7 ++ ret = request_irq(APW_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(APBY_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(APBZ_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++ ret = request_irq(AXIIC_DS_0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(AXIIC_DS_1_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(AXIIC_DS_2_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(AXIIC_DS_3_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#ifndef CONFIG_MACH_IPROC_P7 ++ ret = request_irq(AXIIC_DS_4_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++// printk("%s: %d exit\n", __FUNCTION__, __LINE__); ++} +diff --git a/arch/arm/mach-iproc/include/mach/io_map.h b/arch/arm/mach-iproc/include/mach/io_map.h +new file mode 100644 +index 0000000..01dd6fd +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/io_map.h +@@ -0,0 +1,86 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __NORTHSTAR_IO_MAP_H ++#define __NORTHSTAR_IO_MAP_H ++ ++#include ++#include ++#include ++ ++#define IPROC_CCA_CORE_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCA_REG_BASE) ++#define IPROC_CCA_UART0_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCA_UART0_REG_BASE) ++#define IPROC_CCB_GPIO_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_GPIO_REG_BASE) ++#define IPROC_CCB_PWM_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_PWM_REG_BASE) ++#define IPROC_CCB_MDIO_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_MDIO_REG_BASE) ++#define IPROC_CCB_RNG_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_RNG_REG_BASE) ++#define IPROC_CCB_TIM0_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_TIM0_REG_BASE) ++#define IPROC_CCB_TIM1_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_TIM1_REG_BASE) ++#define IPROC_CCB_SRAU_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_SRAU_REG_BASE) ++#define IPROC_CCB_UART0_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_UART0_REG_BASE) ++ ++#define IPROC_DDRC_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_DDRC_REG_BASE) ++#define IPROC_DMAC_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_DMAC_REG_BASE) ++#define IPROC_PCIE_AXIB0_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_PCIE_AXIB0_REG_BASE) ++#define IPROC_PCIE_AXIB1_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_PCIE_AXIB1_REG_BASE) ++#define IPROC_PCIE_AXIB2_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_PCIE_AXIB2_REG_BASE) ++ ++#define IPROC_SDIO3_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_SDIO3_REG_BASE) ++#define IPROC_USB20_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_USB20_REG_BASE) ++#define IPROC_USB30_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_USB30_REG_BASE) ++#define IPROC_USB20_PHY_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_USB20_PHY_REG_BASE) ++#define IPROC_GMAC0_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_GMAC0_REG_BASE) ++#define IPROC_GMAC1_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_GMAC1_REG_BASE) ++#define IPROC_GMAC2_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_GMAC2_REG_BASE) ++#define IPROC_GMAC3_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_GMAC3_REG_BASE) ++#define IPROC_DMU_BASE_VA HW_IO_PHYS_TO_VIRT(IPROC_DMU_REG_BASE) ++#define IPROC_CRU_BASE_VA HW_IO_PHYS_TO_VIRT(IPROC_CRU_REG_BASE) ++#define IPROC_IDM_REGISTER_VA HW_IO_PHYS_TO_VIRT(IPROC_IDM_REG_BASE) ++#define IPROC_USB2D_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_USB2D_REG_BASE) ++ ++#define IPROC_CTF_BASE_VA HW_IO_PHYS_TO_VIRT(IPROC_CTF_REG_BASE) ++ ++/* ARM9 Private memory region */ ++#define PERIPH_BASE IPROC_PERIPH_BASE ++#define IPROC_PERIPH_VA HW_IO_PHYS_TO_VIRT(IPROC_PERIPH_BASE) ++#define IPROC_PERIPH_SCU_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_PERIPH_BASE) ++#define IPROC_PERIPH_INT_CTRL_REG_VA HW_IO_PHYS_TO_VIRT(PERIPH_BASE + 0x100) ++#define IPROC_PERIPH_GLB_TIM_REG_VA HW_IO_PHYS_TO_VIRT(PERIPH_BASE + 0x200) ++#define IPROC_PERIPH_PVT_TIM_REG_VA HW_IO_PHYS_TO_VIRT(PERIPH_BASE + 0x600) ++#define IPROC_PERIPH_PVT_WDT_REG_VA HW_IO_PHYS_TO_VIRT(PERIPH_BASE + 0x620) ++#define IPROC_PERIPH_INT_DISTR_REG_VA HW_IO_PHYS_TO_VIRT(PERIPH_BASE + 0x1000) ++#define IPROC_L2CC_REG_VA HW_IO_PHYS_TO_VIRT(PERIPH_BASE + 0x2000) ++ ++#define IPROC_ROOT_CLK_VA HW_IO_PHYS_TO_VIRT(IPROC_CLK_WR_ACC_REG_BASE) ++#define IPROC_GICCPU_VA HW_IO_PHYS_TO_VIRT(IPROC_GICCPU_CTL_REG_BASE) ++ ++#define CCU_PROF_REG_BASE IPROC_CCU_PROF_CTL_REG_BASE ++#define IPROC_CCU_PROF_CTL_REG_VA HW_IO_PHYS_TO_VIRT(CCU_PROF_REG_BASE) ++#define IPROC_CCU_PROF_SEL_REG_VA HW_IO_PHYS_TO_VIRT(CCU_PROF_REG_BASE + 0x004) ++#define IPROC_CCU_PROF_CNT_REG_VA HW_IO_PHYS_TO_VIRT(CCU_PROF_REG_BASE + 0x008) ++#define IPROC_CCU_PROF_DBG_REG_VA HW_IO_PHYS_TO_VIRT(CCU_PROF_REG_BASE + 0x00C) ++ ++#ifdef CONFIG_MACH_CYGNUS ++ #define IPROC_UART_LLDEBUG_PA IPROC_CCA_UART3_REG_BASE ++ #define IPROC_UART_LLDEBUG_VA HW_IO_PHYS_TO_VIRT(IPROC_UART_LLDEBUG_PA) ++#else ++ #define IPROC_UART_LLDEBUG_PA IPROC_CCA_UART0_REG_BASE ++ #define IPROC_UART_LLDEBUG_VA IPROC_CCA_UART0_REG_VA ++#endif ++ ++#define IPROC_I2S_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_I2S_REG_BASE) ++ ++#endif /*__NORTHSTAR_IO_MAP_H */ +diff --git a/arch/arm/mach-iproc/include/mach/iproc_regs.h b/arch/arm/mach-iproc/include/mach/iproc_regs.h +new file mode 100644 +index 0000000..460c436 +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/iproc_regs.h +@@ -0,0 +1,824 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __IPROC_REGS_H ++#define __IPROC_REGS_H __FILE__ ++#include ++#ifdef CONFIG_MACH_CYGNUS ++#include "socregs-cygnus.h" ++#elif defined(CONFIG_MACH_NS) ++#include "socregs_ns_open.h" ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#include "socregs_ing_open.h" ++#elif defined(CONFIG_MACH_NSP) ++#include "socregs_nsp_open.h" ++#elif defined(CONFIG_MACH_IPROC_P7) ++#include "socregs_p7_open.h" ++#else ++#error "No valid iProc Machine type selected" ++#endif ++ ++#if defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_IPROC_P7) || \ ++ defined(CONFIG_MACH_CYGNUS) ++#define IPROC_NUM_CPUS (1) ++#else ++#define IPROC_NUM_CPUS (2) ++#endif ++ ++#if defined(CONFIG_MACH_CYGNUS) ++#define IPROC_NUM_IRQS (IPROC_INTERRUPTS_WIDTH) ++#else ++#define IPROC_NUM_IRQS (256) ++#endif /* end of CONFIG_MACH_CYGNUS) */ ++ ++#define IPROC_CPU0_MIN_INT_PRIORITY (0) ++#define IPROC_CPU1_MIN_INT_PRIORITY (0) ++ ++#if defined(CONFIG_MACH_CYGNUS) ++#define IPROC_DDR_MEM_BASE1 (0x02000000) ++#else ++#define IPROC_DDR_MEM_BASE1 (0x0) ++#endif /* end of CONFIG_MACH_CYGNUS */ ++ ++#if defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_CYGNUS) ++#define IPROC_DDR_MEM_BASE2 (0x60000000) ++#else ++#define IPROC_DDR_MEM_BASE2 (0x80000000) ++#endif ++ ++ ++/* remap to newer reg file defs */ ++#ifndef CONFIG_MACH_NS ++#ifdef CONFIG_MACH_CYGNUS //chandra: todo- has to check ++ #define CCA_CHIPID ICFG_CHIP_ID_REG ++#else ++ #define CCA_CHIPID ChipcommonA_ChipID ++#endif ++ ++#define NAND_NAND_FLASH_REV NAND_nand_flash_REVISION ++#define NAND_DIRECT_READ_RD_MISS NAND_direct_read_rd_miss ++#define NAND_ECC_MIPS_CORR NAND_ecc_mips_corr ++#define NAND_NAND_FLASH_FLASH_CACHE127 NAND_nand_flash_FLASH_CACHE127 ++#define QSPI_MSPI_SPCR0_LSB QSPI_mspi_SPCR0_LSB ++#define QSPI_MSPI_DISABLE_FLUSH_GEN QSPI_mspi_DISABLE_FLUSH_GEN ++#define QSPI_BSPI_REGS_REV_ID QSPI_bspi_registers_REVISION_ID ++#define QSPI_BSPI_REGS_BSPI_PIO_DATA QSPI_bspi_registers_BSPI_PIO_DATA ++#define QSPI_RAF_START_ADDR QSPI_raf_START_ADDR ++#define QSPI_RAF_CURR_ADDR QSPI_raf_CURR_ADDR ++#define QSPI_RAF_INTERRUPT_LR_FULLNESS_REACHED QSPI_raf_interrupt_LR_fullness_reached ++#define QSPI_MSPI_INTERRUPT_MSPI_HALT_SET_TRANSACTION_DONE QSPI_mspi_interrupt_MSPI_halt_set_transaction_done ++ ++#define CCB_TIM0_TIM_TMR1_LOAD ChipcommonB_tim0_TIM_TIMER1Load ++#define CCB_TIM1_TIM_TMR1_LOAD ChipcommonB_tim1_TIM_TIMER1Load ++ ++#define GMAC0_DEVCT GMAC0_DEVCONTROL ++ ++#define CCA_GPIO_EVT_BASE ChipcommonA_GPIOEvent_BASE ++#define CCA_GPIO_INPUT_BASE ChipcommonA_GPIOInput_BASE ++#define CCB_GP_INT_CLR_BASE ChipcommonB_GP_INT_TYPE_BASE ++ ++#define PAXB_0_PCIE_CTL (PAXB_0_CLK_CONTROL) ++ ++#define CCB_MII_MGMT_CTL ChipcommonB_MII_Management_Control ++ ++#endif ++ ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_NSP) || \ ++ defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define CCB_RNG_CTRL ChipcommonB_rng_CTRL ++#endif ++ ++ ++/* the below might be NS specific */ ++#ifdef CONFIG_MACH_CYGNUS //chandra: todo- only timers are mapped correctly ++ #define IPROC_CCA_REG_BASE CCA_CHIPID ++ #define IPROC_CCB_GPIO_REG_BASE (CCB_GP_DATA_IN) ++ #define IPROC_CCB_PWM_REG_BASE (CCB_PWMCTL) ++ #define IPROC_CCB_MDIO_REG_BASE (CCB_MII_MGMT_CTL) ++ #define IPROC_CCB_RNG_REG_BASE (CCB_RNG_CTRL) ++ #define IPROC_CCB_TIM0_REG_BASE (ChipcommonG_tim0_TIM_TIMER1Load) ++ #define IPROC_CCB_TIM1_REG_BASE (ChipcommonG_tim1_TIM_TIMER1Load) ++ #define IPROC_CCB_SRAU_REG_BASE (CCB_SRAB_CMDSTAT) ++ #define IPROC_D1W_REG_BASE (ASIU_D1W_DIN) ++ #define IPROC_D1W_INTR (CHIP_INTR1__ASIU_D1W_INTR) ++ #define IPROC_D1W_CLK_GATE_CTRL (ASIU_TOP_CLK_GATING_CTRL) ++ #define IPROC_D1W_IO_MUX_REG (CRMU_IOMUX_CTRL4) ++ ++ #define IPROC_KEYPAD_INTR (ASIU_INTR_STATUS__asiu_keypad_intr) ++ #define IPROC_KEYPAD_REG_BASE (KEYPAD_TOP_REGS_KPCR) ++ #define IPROC_KEYPAD_TOP_REGS_KPCR (KEYPAD_TOP_REGS_KPCR) ++ #define IPROC_KEYPAD_TOP_REGS_KPIOR (KEYPAD_TOP_REGS_KPIOR) ++ #define IPROC_KEYPAD_TOP_REGS_KPEMR0 (KEYPAD_TOP_REGS_KPEMR0) ++ #define IPROC_KEYPAD_TOP_REGS_KPEMR1 (KEYPAD_TOP_REGS_KPEMR1) ++ #define IPROC_KEYPAD_TOP_REGS_KPEMR2 (KEYPAD_TOP_REGS_KPEMR2) ++ #define IPROC_KEYPAD_TOP_REGS_KPEMR3 (KEYPAD_TOP_REGS_KPEMR3) ++ #define IPROC_KEYPAD_TOP_REGS_KPSSR0 (KEYPAD_TOP_REGS_KPSSR0) ++ #define IPROC_KEYPAD_TOP_REGS_KPSSR1 (KEYPAD_TOP_REGS_KPSSR1) ++ #define IPROC_KEYPAD_TOP_REGS_KPIMR0 (KEYPAD_TOP_REGS_KPIMR0) ++ #define IPROC_KEYPAD_TOP_REGS_KPIMR1 (KEYPAD_TOP_REGS_KPIMR1) ++ #define IPROC_KEYPAD_TOP_REGS_KPICR0 (KEYPAD_TOP_REGS_KPICR0) ++ #define IPROC_KEYPAD_TOP_REGS_KPICR1 (KEYPAD_TOP_REGS_KPICR1) ++ #define IPROC_KEYPAD_TOP_REGS_KPISR0 (KEYPAD_TOP_REGS_KPISR0) ++ #define IPROC_KEYPAD_TOP_REGS_KPISR1 (KEYPAD_TOP_REGS_KPISR1) ++ #define IPROC_KEYPAD_TOP_REGS_KPSSR0 (KEYPAD_TOP_REGS_KPSSR0) ++ #define IPROC_CRMU_ASIU_KEYPAD_CLK_DIV (CRMU_ASIU_KEYPAD_CLK_DIV) ++ #define IPROC_IO_MUX_REG_BASE (CRMU_IOMUX_CTRL1) ++ #define IPROC_CLK_GATING_CTRL (ASIU_TOP_CLK_GATING_CTRL) ++ #define IPROC_KEYPAD_CLK_GATE_EN_BIT (ASIU_TOP_CLK_GATING_CTRL__KEYPAD_CLK_GATE_EN) ++ ++ #define IPROC_TSC_REG_BASE (TSCRegCtl1) ++ #define IPROC_TSC_INTR (ASIU_INTR_STATUS__asiu_touch_screen_intr) ++ #define IPROC_ADC_REG_BASE (TSCRegCtl1) ++ #define IPROC_ADC_INTR (ASIU_INTR_STATUS__asiu_touch_screen_intr) ++// #define IPROC_CCB_UART0_REG_BASE (CCB_UART0_RBR_THR_DLL) ++#else ++#define IPROC_CCA_REG_BASE CCA_CHIPID ++#define IPROC_CCB_GPIO_REG_BASE (IPROC_GPIO_CCB_BASE) ++#define IPROC_CCB_PWM_REG_BASE (CCB_PWMCTL) ++#define IPROC_CCB_MDIO_REG_BASE (CCB_MII_MGMT_CTL) ++#define IPROC_CCB_RNG_REG_BASE (CCB_RNG_CTRL) ++#define IPROC_CCB_TIM0_REG_BASE (CCB_TIM0_TIM_TMR1_LOAD) ++#define IPROC_CCB_TIM1_REG_BASE (CCB_TIM1_TIM_TMR1_LOAD) ++#define IPROC_CCB_SRAU_REG_BASE (CCB_SRAB_CMDSTAT) ++#define CCB_UART0_RBR_THR_DLL (0x18037000) ++#define IPROC_CCB_UART0_REG_BASE (CCB_UART0_RBR_THR_DLL) ++#endif /* end of CONFIG_MACH_CYGNUS */ ++ ++/* iProc Profile 7 specific remapping */ ++#if defined(CONFIG_MACH_IPROC_P7) ++ ++#define ChipcommonA_ChipID (ICFG_CHIP_ID_REG) ++#define IPROC_CCA_UART0_REG_BASE (ChipcommonG_UART0_UART_RBR_THR_DLL) ++#define IPROC_CCA_UART1_REG_BASE (ChipcommonG_UART1_UART_RBR_THR_DLL) ++#define IPROC_CCS_RNG_REG_BASE (ChipcommonS_RNG_CTRL) ++ ++#else /* !CONFIG_MACH_IPROC_P7 */ ++ ++#define IPROC_CCA_BASE IPROC_CCA_REG_BASE ++#define IPROC_CCA_CORE_CAP_REG_BASE (IPROC_CCA_BASE + 0x04) ++#define IPROC_CCA_CORE_CTL_REG_BASE (IPROC_CCA_BASE + 0x08) ++ ++#if defined(CONFIG_MACH_CYGNUS) ++ #define IPROC_CCA_UART0_REG_BASE (ChipcommonG_UART0_UART_RBR_THR_DLL) //(IPROC_CCA_BASE + 0x300) //chandra: ++ #define IPROC_CCA_UART1_REG_BASE (ChipcommonG_UART1_UART_RBR_THR_DLL) //(IPROC_CCA_BASE + 0x400) ++ #define IPROC_CCA_UART2_REG_BASE (ChipcommonG_UART2_UART_RBR_THR_DLL) ++ #define IPROC_CCA_UART3_REG_BASE (ChipcommonG_UART3_UART_RBR_THR_DLL) ++ #define IPROC_CCA_UART4_REG_BASE (ChipcommonG_UART4_UART_RBR_THR_DLL) ++#else ++#define IPROC_CCA_UART0_REG_BASE (IPROC_CCA_BASE + 0x300) ++#define IPROC_CCA_UART1_REG_BASE (IPROC_CCA_BASE + 0x400) ++#endif /*end of CYGNUS */ ++#define IPROC_CCA_INTMASK_REG_BASE (IPROC_CCA_BASE + 0x24) ++#define IPROC_CCA_UART_CLK_REG_BASE (IPROC_CCA_BASE + 0xa4) ++ ++#endif /* CONFIG_MACH_IPROC_P7 */ ++ ++#define IPROC_CLK_WR_ACC_REG_BASE (0x19000000) ++#define IPROC_CLK_WR_ACC_REG_OFFSET (0x000) ++#define IPROC_CLK_POLICY_FREQ_REG (0x19000008) ++#define IPROC_CLK_POLICY_FREQ_OFFSET (0x008) ++#define IPROC_CLK_POLICY_CTL_REG (0x1900000C) ++#define IPROC_CLK_POLICY_CTL_OFFSET (0x00C) ++#define IPROC_CLK_POLICY0_MSK_REG (0x19000010) ++#define IPROC_CLK_POLICY0_MSK_OFFSET (0x010) ++#define IPROC_CLK_POLICY1_MSK_REG (0x19000014) ++#define IPROC_CLK_POLICY1_MSK_OFFSET (0x014) ++#define IPROC_CLK_POLICY2_MSK_REG (0x19000018) ++#define IPROC_CLK_POLICY2_MSK_OFFSET (0x018) ++#define IPROC_CLK_POLICY3_MSK_REG (0x1900001C) ++#define IPROC_CLK_POLICY3_MSK_OFFSET (0x01C) ++#define IPROC_CLK_INT_EN_REG (0x19000020) ++#define IPROC_CLK_INT_EN_OFFSET (0x020) ++#define IPROC_CLK_INT_STAT_REG (0x19000024) ++#define IPROC_CLK_INT_STAT_OFFSET (0x024) ++#define IPROC_CLK_LVM_EN_REG (0x19000034) ++#define IPROC_CLK_LVM_EN_OFFSET (0x034) ++#define IPROC_CLK_LVM0_3_REG (0x19000038) ++#define IPROC_CLK_LVM0_3_OFFSET (0x038) ++#define IPROC_CLK_LVM4_7_REG (0x1900003C) ++#define IPROC_CLK_LVM4_7_OFFSET (0x03C) ++#define IPROC_CLK_VLT0_3_REG (0x19000040) ++#define IPROC_CLK_VLT0_3_OFFSET (0x040) ++#define IPROC_CLK_VLT4_7_REG (0x19000044) ++#define IPROC_CLK_VLT4_7_OFFSET (0x044) ++#define IPROC_CLK_BUS_QUIESC_REG (0x19000100) ++#define IPROC_CLK_BUS_QUIESC_OFFSET (0x100) ++#define IPROC_CLK_CORE0_GATE_REG (0x19000200) ++#define IPROC_CLK_CORE0_GATE_OFFSET (0x200) ++#define IPROC_CLK_CORE1_GATE_REG (0x19000204) ++#define IPROC_CLK_CORE1_GATE_OFFSET (0x204) ++#define IPROC_CLK_ARM_SW_GATE_REG (0x19000210) ++#define IPROC_CLK_ARM_SW_GATE_OFFSET (0x210) ++#define IPROC_CLK_ARM_PERIPH_GATE_REG (0x19000300) ++#define IPROC_CLK_ARM_PERIPH_GATE_OFFSET (0x300) ++#define IPROC_CLK_APB0_CLKGATE_REG (0x19000400) ++#define IPROC_CLK_APB0_CLKGATE_OFFSET (0x400) ++#define IPROC_CLK_PL310_DIV_REG (0x19000A00) ++#define IPROC_CLK_PL310_DIV_OFFSET (0xA00) ++#define IPROC_CLK_PL310_TRG_REG (0x19000A04) ++#define IPROC_CLK_PL310_TRG_OFFSET (0xA04) ++#define IPROC_CLK_ARM_SW_DIV_REG (0x19000A08) ++#define IPROC_CLK_ARM_SW_DIV_OFFSET (0xA08) ++#define IPROC_CLK_ARM_SW_TRG_REG (0x19000A0C) ++#define IPROC_CLK_ARM_SW_TRG_OFFSET (0xA0C) ++#define IPROC_CLK_APB_SW_DIV_REG (0x19000A10) ++#define IPROC_CLK_APB_SW_DIV_OFFSET (0xA10) ++#define IPROC_CLK_APB_SW_TRG_REG (0x19000A14) ++#define IPROC_CLK_APB_SW_TRG_OFFSET (0xA14) ++#define IPROC_CLK_PLL_ARMA_REG (0x19000C00) ++#define IPROC_CLK_PLL_ARMA_OFFSET (0xC00) ++#define IPROC_CLK_PLL_ARMB_REG (0x19000C04) ++#define IPROC_CLK_PLL_ARMB_OFFSET (0xC04) ++#define IPROC_CLK_PLL_ARMC_REG (0x19000C08) ++#define IPROC_CLK_PLL_ARMC_OFFSET (0xC08) ++#define IPROC_CLK_PLL_ARMCTL0_REG (0x19000C0C) ++#define IPROC_CLK_PLL_ARMCTL0_OFFSET (0xC0C) ++#define IPROC_CLK_PLL_ARMCTL1_REG (0x19000C10) ++#define IPROC_CLK_PLL_ARMCTL1_OFFSET (0xC10) ++#define IPROC_CLK_PLL_ARMCTL2_REG (0x19000C14) ++#define IPROC_CLK_PLL_ARMCTL2_OFFSET (0xC14) ++#define IPROC_CLK_PLL_ARMCTL3_REG (0x19000C18) ++#define IPROC_CLK_PLL_ARMCTL3_OFFSET (0xC18) ++#define IPROC_CLK_PLL_ARMCTL4_REG (0x19000C1C) ++#define IPROC_CLK_PLL_ARMCTL4_OFFSET (0xC1C) ++#define IPROC_CLK_PLL_ARMCTL5_REG (0x19000C20) ++#define IPROC_CLK_PLL_ARMCTL5_OFFSET (0xC20) ++#define IPROC_CLK_PLL_ARM_OFFSET_REG (0x19000C24) ++#define IPROC_CLK_PLL_ARM_OFFSET_OFFSET (0xC24) ++#define IPROC_CLK_ARM_DIV_REG (0x19000E00) ++#define IPROC_CLK_ARM_DIV_OFFSET (0xE00) ++#define IPROC_CLK_ARM_SEG_TRG_REG (0x19000E04) ++#define IPROC_CLK_ARM_SEG_TRG_OFFSET (0xE04) ++#define IPROC_CLK_ARM_SEG_TRG_OVRD_REG (0x19000E08) ++#define IPROC_CLK_ARM_SEG_TRG_OVRD_OFFSET (0xE08) ++#define IPROC_CLK_PLL_DEBUG_REG (0x19000E10) ++#define IPROC_CLK_PLL_DEBUG_OFFSET (0xE10) ++#define IPROC_CLK_ACTIVITY_MON1_REG (0x19000E20) ++#define IPROC_CLK_ACTIVITY_MON1_OFFSET (0xE20) ++#define IPROC_CLK_ACTIVITY_MON2_REG (0x19000E24) ++#define IPROC_CLK_ACTIVITY_MON2_OFFSET (0xE24) ++#define IPROC_CLK_GATE_DBG_REG (0x19000E40) ++#define IPROC_CLK_GATE_DBG_OFFSET (0xE40) ++#define IPROC_CLK_APB_CLKGATE_DBG1_REG (0x19000E48) ++#define IPROC_CLK_APB_CLKGATE_DBG1_OFFSET (0xE48) ++#define IPROC_CLK_CLKMON_REG (0x19000E64) ++#define IPROC_CLK_CLKMON_OFFSET (0xE64) ++#define IPROC_CLK_KPROC_CCU_PROF_CTL_REG (0x19000E90) ++#define IPROC_CLK_KPROC_CCU_PROF_CTL_OFFSET (0xE90) ++#define IPROC_CLK_KPROC_CCU_PROF_SEL_REG (0x19000E94) ++#define IPROC_CLK_KPROC_CCU_PROF_SEL_OFFSET (0xE94) ++#define IPROC_CLK_KPROC_CCU_PROF_CNT_REG (0x19000E98) ++#define IPROC_CLK_KPROC_CCU_PROF_CNT_OFFSET (0xE98) ++#define IPROC_CLK_KPROC_CCU_PROF_DBG_REG (0x19000E9C) ++#define IPROC_CLK_KPROC_CCU_PROF_DBG_OFFSET (0xE9C) ++#define IPROC_CLK_POLICY_DBG_REG (0x19000EC0) ++#define IPROC_CLK_POLICY_DBG_OFFSET (0xEC0) ++#define IPROC_CLK_TGTMASK_DBG1_REG (0x19000EC4) ++#define IPROC_CLK_TGTMASK_DBG1_OFFSET (0xEC4) ++#define IPROC_RST_WR_ACCESS_REG (0x19000F00) ++#define IPROC_RST_WR_ACCESS_OFFSET (0xF00) ++#define IPROC_RST_SOFT_RSTN_REG (0x19000F04) ++#define IPROC_RST_SOFT_RSTN_OFFSET (0xF04) ++#define IPROC_RST_A9C_SOFT_RSTN_REG (0x19000F08) ++#define IPROC_RST_A9C_SOFT_RSTN_OFFSET (0xF08) ++#define IPROC_RST_A9CORE_SOFT_RSTN_REG (0x19000F08) ++#define IPROC_RST_A9CORE_SOFT_RSTN_OFFSET (0xF08) ++ ++#define PLLARMC_PLLARM_MDIV_SHIFT 0 ++#define PLLARMC_PLLARM_LOAD_EN_MASK (0x00000800) ++#define PLLARMA_PLLARM_NDIV_INT_MASK (0x0003FF00) ++#define PLLARMA_PLLARM_NDIV_INT_SHIFT 8 ++#define PLLARMB_PLLARM_NDIV_FRAC_MASK (0x000FFFFF) ++#define PLLARMB_PLLARM_NDIV_FRAC_SHIFT 0 ++#define ARMCTL5_PLLARM_H_MDIV_MASK (0x000000FF) ++#define ARMCTL5_PLLARM_H_MDIV_SHIFT 0 ++ ++#define IPROC_CLK_CTL_REG (IPROC_CCA_CLK_CTL_REG_BASE + 0x000) ++#define IPROC_CCA_CLK_HW_REQ_OFF 0x00000020 ++ ++#define IPROC_DDRC_REG_BASE (DDR_DENALI_CTL_00) //(0x18010000) ++#define IPROC_DMAC_REG_BASE (DMAC_P1330_NON_DS) //(0x1802C000) ++#define IPROC_PCIE_AXIB0_REG_BASE (PAXB_0_PCIE_CTL) //(0x18012000) ++#define IPROC_PCIE_AXIB1_REG_BASE (PAXB_1_PCIE_CTL) //(0x18013000) ++#define IPROC_PCIE_AXIB2_REG_BASE (PAXB_2_PCIE_CTL) //(0x18014000) ++ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_SDIO3_REG_BASE (SDIO_EMMC_SDXC_SYSADDR) //(0x18020000) ++#define IPROC_SDIO_IDM_RESET_CONTROL (0x16800) ++#define IPROC_SDIO_IRQ (177) ++#define IPROC_SDIO_IDM_IO_CONTROL_DIRECT (0x18116408) ++#define IPROC_SDIO_IDM_IO_CONTROL_DIRECT__CMD_COMFLICT_DISABLE (22) ++#elif defined(CONFIG_MACH_NSP) ++#define IPROC_SDIO3_REG_BASE (SDIO_eMMCSDXC_SYSADDR) ++#define IPROC_SDIO_IDM_RESET_CONTROL (0x17800) ++#define IPROC_SDIO_IRQ (177) ++#define IPROC_SDIO_IDM_IO_CONTROL_DIRECT (SDIO_IDM_IO_CONTROL_DIRECT) ++#define IPROC_SDIO_IDM_IO_CONTROL_DIRECT__CMD_COMFLICT_DISABLE (SDIO_IDM_IO_CONTROL_DIRECT__CMD_COMFLICT_DISABLE) ++ ++#endif ++ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_USB20_REG_BASE (0x18021000) ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_NSP) || \ ++ defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_USB20_REG_BASE (0x1802A000) ++#define IPROC_UDC_IRQ (238) ++#endif ++#define IPROC_USB30_REG_BASE (0x18023000) ++//#define IPROC_USB30_REG_BASE (0x18022000) ++#define IPROC_USB20_PHY_REG_BASE (0x18023000) /* ??*/ ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define IPROC_USB2D_REG_BASE USB2D_ENDPNT_IN_CTRL_0 ++#define IPROC_USB2D_REG_SIZE (0x2000) /* 8KB */ ++#endif ++ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_NUM_GMACS 4 ++#define IPROC_GMAC0_REG_BASE (GMAC0_DEVCTL) //(0x18024000) ++#define IPROC_GMAC1_REG_BASE (GMAC1_DEVCTL) //(0x18025000) ++#define IPROC_GMAC2_REG_BASE (GMAC2_DEVCTL) //(0x18026000) ++#define IPROC_GMAC3_REG_BASE (GMAC3_DEVCTL) //(0x18027000) ++#define IPROC_GMAC0_INT 179 ++#define IPROC_GMAC1_INT 180 ++#define IPROC_GMAC2_INT 181 ++#define IPROC_GMAC3_INT 182 ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define IPROC_NUM_GMACS 2 ++#define IPROC_GMAC0_REG_BASE (GMAC0_DEVCONTROL) //(0x18022000) ++#define IPROC_GMAC1_REG_BASE (GMAC1_DEVCONTROL) //(0x18023000) ++#define IPROC_GMAC2_REG_BASE (0) // n/a ++#define IPROC_GMAC3_REG_BASE (0) // n/a ++#define IPROC_GMAC0_INT 234 ++#define IPROC_GMAC1_INT 235 ++#define IPROC_GMAC2_INT 0 // n/a ++#define IPROC_GMAC3_INT 0 // n/a ++#elif defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_CYGNUS) ++#define IPROC_NUM_GMACS 1 ++#define IPROC_GMAC0_REG_BASE (GMAC0_DEVCONTROL) //(0x18022000) ++#define IPROC_GMAC1_REG_BASE (0) // n/a ++#define IPROC_GMAC2_REG_BASE (0) // n/a ++#define IPROC_GMAC3_REG_BASE (0) // n/a ++#define IPROC_GMAC0_INT 234 ++#define IPROC_GMAC1_INT 0 // n/a ++#define IPROC_GMAC2_INT 0 // n/a ++#define IPROC_GMAC3_INT 0 // n/a ++#elif defined(CONFIG_MACH_NSP) ++#define IPROC_NUM_GMACS 4 ++#define IPROC_GMAC0_REG_BASE (GMAC0_DEVCONTROL) //(0x18022000) ++#define IPROC_GMAC1_REG_BASE (GMAC1_DEVCONTROL) //(0x18023000) ++#define IPROC_GMAC2_REG_BASE (FA_GMAC0_DEVCONTROL) //(0x18024000) ++#define IPROC_GMAC3_REG_BASE (FA_GMAC1_DEVCONTROL) //(0x18025000) ++#define IPROC_GMAC0_INT 179 ++#define IPROC_GMAC1_INT 180 ++#define IPROC_GMAC2_INT 181 ++#define IPROC_GMAC3_INT 182 ++#endif ++ ++#define IPROC_CTF_REG_BASE (0x18027C00) ++ ++#define IPROC_I2S_REG_BASE (0x1802A000) ++#define IPROC_CCU_PROF_CTL_REG_BASE (0x19000E90) ++ ++/* IDM / CRU / DMU */ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_CRU_REG_BASE (0x1800b000) ++#define IPROC_DMU_REG_BASE (0x1800c000) ++#define IPROC_IDM_REG_BASE (0x18100000) ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_KT2) \ ++ || defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || defined (CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_CRU_REG_BASE CRU_control ++#define IPROC_DMU_REG_BASE DMU_PCU_IPROC_CONTROL ++#define IPROC_IDM_REG_BASE (IHOST_M0_IO_CONTROL_DIRECT - 0x408) ++#elif defined(CONFIG_MACH_NSP) ++#define IPROC_CRU_REG_BASE CRU_control ++#define IPROC_DMU_REG_BASE PCU_MDIO_MGT ++ ++#define IPROC_IDM_REG_BASE (IHOST_M0_IO_CONTROL_DIRECT - 0x408) ++#elif defined(CONFIG_MACH_CYGNUS) ++#define IPROC_CRU_REG_BASE (CRU_control) ++#define IPROC_DMU_REG_BASE DMU_S0_IDM_IDM_RESET_CONTROL ++#endif ++#ifndef CONFIG_MACH_GH ++#define DMU_PCU_IPROC_CONTROL 0x1803f000 ++#endif ++ ++/* Straps */ ++#if defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP) ++#define IPROC_DMU_STRAPS_OFFSET (0x2a0) ++#define IPROC_STRAP_BOOT_DEV_SHIFT (16) ++#define IPROC_STRAP_NAND_TYPE_SHIFT (12) ++#define IPROC_STRAP_NAND_PAGE_SHIFT (10) ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_KT2) \ ++ || defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_DMU_STRAPS_OFFSET DMU_PCU_IPROC_STRAPS_CAPTURED_BASE ++#define IPROC_STRAP_BOOT_DEV_SHIFT DMU_PCU_IPROC_STRAPS_CAPTURED__strap_boot_dev_R ++#define IPROC_STRAP_NAND_TYPE_SHIFT DMU_PCU_IPROC_STRAPS_CAPTURED__strap_nand_type_R ++#define IPROC_STRAP_NAND_PAGE_SHIFT DMU_PCU_IPROC_STRAPS_CAPTURED__strap_nand_page_R ++#endif ++#define IPROC_STRAP_BOOT_DEV_QSPI (0) ++#define IPROC_STRAP_BOOT_DEV_NAND (1) ++#define IPROC_STRAP_BOOT_DEV_PNOR (4) ++ ++/* NAND and QSPI */ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_IDM_NAND_REG_BASE (0x1811a408) ++#define IPROC_NAND_IRQ_START (100) ++#define IPROC_IDM_QSPI_REG_BASE (0x1811b408) ++#define IPROC_QSPI_IRQ_START (104) ++#define IPROC_QSPI_IRQ_END (109) ++#elif defined(CONFIG_MACH_NSP) ++#define IPROC_IDM_NAND_REG_BASE NAND_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_NAND_IRQ_START (100) ++#define IPROC_IDM_QSPI_REG_BASE QSPI_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_QSPI_IRQ_START (104) ++#define IPROC_QSPI_IRQ_END (109) ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_IDM_NAND_REG_BASE NAND_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_NAND_IRQ_START (106) ++#define IPROC_IDM_QSPI_REG_BASE QSPI_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_QSPI_IRQ_START (110) ++#define IPROC_QSPI_IRQ_END (116) ++#elif defined(CONFIG_MACH_CYGNUS) ++#define IPROC_IDM_QSPI_REG_BASE QSPI_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_QSPI_IRQ_START (IPROC_INTERRUPTS__chipcommonG_spi0_intr) ++#define IPROC_QSPI_IRQ_END (IPROC_INTERRUPTS__chipcommonG_spi5_intr) ++#elif defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_IDM_NAND_REG_BASE NAND_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_NAND_IRQ_START (101) ++#define IPROC_IDM_QSPI_REG_BASE QSPI_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_QSPI_IRQ_START (102) ++#define IPROC_QSPI_IRQ_END (102) ++#endif ++ ++/* PNOR */ ++#ifdef CONFIG_MACH_IPROC_P7 ++#define S29GL_FLASH_SIZE 0x04000000 ++#define S29GL_FLASH_PHYS 0xe8000000 ++#define PNOR_NAND_SEL_REG ICFG_IPROC_IOPAD_SW_OVERRIDE_CTRL ++#define PNOR_NAND_SEL_REG_OVERRIDE ICFG_IPROC_IOPAD_SW_OVERRIDE_CTRL__iproc_pnor_sel_sw_ovwr ++#define PNOR_NAND_SEL_REG_PNOR_SEL ICFG_IPROC_IOPAD_SW_OVERRIDE_CTRL__iproc_pnor_sel ++#elif defined(CONFIG_MACH_HR2) ++#define S29GL_FLASH_SIZE 0x04000000 ++#define S29GL_FLASH_PHYS 0x20000000 ++#define PNOR_NAND_SEL_REG 0x1803fc3c ++#define PNOR_NAND_SEL_REG_OVERRIDE 2 ++#define PNOR_NAND_SEL_REG_PNOR_SEL 3 ++#endif ++ ++/* ARM9 Private memory region */ ++#if defined(CONFIG_MACH_CYGNUS) ++#define IPROC_PERIPH_BASE (IHOST_SCU_CONTROL)//chandra: ++#else ++#define IPROC_PERIPH_BASE (0x19020000) //(IHOST_A9MP_scu_CONTROL) ++#endif ++#define IPROC_PERIPH_SCU_REG_BASE (IPROC_PERIPH_BASE) ++#define IPROC_PERIPH_INT_CTRL_REG_BASE (IPROC_PERIPH_BASE + 0x100) ++#define IPROC_PERIPH_GLB_TIM_REG_BASE (IPROC_PERIPH_BASE + 0x200) ++#define IPROC_PERIPH_PVT_TIM_REG_BASE (IPROC_PERIPH_BASE + 0x600) ++#define IPROC_PERIPH_PVT_WDT_REG_BASE (IPROC_PERIPH_BASE + 0x620) ++#define IPROC_PERIPH_INT_DISTR_REG_BASE (IPROC_PERIPH_BASE + 0x1000) ++#define IPROC_L2CC_REG_BASE (IPROC_PERIPH_BASE + 0x2000) ++#define IPROC_GTIM_GLB_LO (0x00000000) ++#define IPROC_GTIM_GLB_HI (0x00000004) ++#define IPROC_GTIM_GLB_CTL (0x00000008) ++#define IPROC_GTIM_GLB_STS (0x0000000C) ++#define IPROC_GTIM_GLB_CMP_LO (0x00000010) ++#define IPROC_GTIM_GLB_CMP_HI (0x00000014) ++#define IPROC_GTIM_GLB_INCR (0x00000018) ++ ++/* Structures and bit definitions */ ++/* SCU Control register */ ++#define IPROC_SCU_CTRL_SCU_EN (0x00000001) ++#define IPROC_SCU_CTRL_ADRFLT_EN (0x00000002) ++#define IPROC_SCU_CTRL_PARITY_EN (0x00000004) ++#define IPROC_SCU_CTRL_SPEC_LNFL_EN (0x00000008) ++#define IPROC_SCU_CTRL_FRC2P0_EN (0x00000010) ++#define IPROC_SCU_CTRL_SCU_STNDBY_EN (0x00000020) ++#define IPROC_SCU_CTRL_IC_STNDBY_EN (0x00000040) ++ ++/* ARM A9 Private Timer */ ++#define IPROC_PVT_TIM_CTRL_TIM_EN (0x00000001) ++#define IPROC_PVT_TIM_CTRL_AUTO_RELD (0x00000002) ++#define IPROC_PVT_TIM_CTRL_INT_EN (0x00000004) ++#define IPROC_PVT_TIM_CTRL_PRESC_MASK (0x0000FF00) ++#define IPROC_PVT_TIM_INT_STATUS_SET (0x00000001) ++ ++/* Global timer */ ++#define IPROC_GLB_TIM_CTRL_STCS_EN (0x00000000) ++#define IPROC_GLB_TIM_CTRL_TIM_EN (0x00000001) ++#define IPROC_GLB_TIM_CTRL_COMP_EN (0x00000002) ++#define IPROC_GLB_TIM_CTRL_INT_EN (0x00000004) ++#define IPROC_GLB_TIM_CTRL_AUTO_INC (0x00000008) ++#define IPROC_GLB_TIM_CTRL_STCM_SET (0x0000000C) ++#define IPROC_GLB_TIM_CTRL_PRESC_MASK (0x0000FF00) ++#define IPROC_GLB_TIM_INT_STATUS_SET (0x00000001) ++ ++#define GLBTMR_GLOB_STATUS_EVENT_G_SHIFT (0x00000000) ++#define GLBTMR_GLOB_CTRL_TIMER_EN_G_SHIFT (0x00000000) ++ ++/* GIC(Generic Interrupt controller) CPU interface registers */ ++#if defined(CONFIG_MACH_CYGNUS) ++ #define IPROC_GICCPU_CTL_REG_BASE (IHOST_GICCPU_CONTROL) ++#else ++ #define IPROC_GICCPU_CTL_REG_BASE (0x19020100) ++#endif ++#define IPROC_GICCPU_PRI_MASK_OFFSET (0x04) ++#define IPROC_GICCPU_BIN_PT_OFFSET (0x08) ++#define IPROC_GICCPU_INT_ACK_OFFSET (0x0C) ++#define IPROC_GICCPU_EOI_OFFSET (0x10) ++#define IPROC_GICCPU_RUN_PRI_OFFSET (0x14) ++#define IPROC_GICCPU_HI_PEND_OFFSET (0x18) ++#define IPROC_GICCPU_ALIAS_BIN_PT_NS_OFFSET (0x1C) ++#define IPROC_GICCPU_INT_GFC_OFFSET (0x40) ++#define IPROC_GICCPU_INT_FIQ_SET_OFFSET (0x44) ++#define IPROC_GICCPU_INTEG_MATCH_OFFSET (0x50) ++#define IPROC_GICCPU_INTEG_ENABLE_OFFSET (0x54) ++#define IPROC_GICCPU_CPU_IDENT_OFFSET (0xFC) ++ ++#define IPROC_GIC_CI_CTRL_EN (0x00000001) ++#define IPROC_GIC_CI_PMR_PRIO_MASK (0x000000FF) ++#define IPROC_GIC_CI_BPR_BP_MASK (0x00000003) ++#define IPROC_GIC_CI_IAR_INTID_MASK (0x000003FF) ++#define IPROC_GIC_CI_IAR_CPUID_MASK (0x00001C00) ++#define IPROC_GIC_CI_IAR_CPUID_OFFSET (10) ++#define IPROC_GIC_CI_EOIR_INTID_MASK (0x000003FF) ++#define IPROC_GIC_CI_EOIR_CPUID_MASK (0x00001C00) ++#define IPROC_GIC_CI_EOIR_CPUID_OFFSET (10) ++#define IPROC_GIC_CI_RPR_PRIO_MASK (0x000000FF) ++#define IPROC_GIC_CI_HPIR_PENDID_MASK (0x000003FF) ++#define IPROC_GIC_CI_HPIR_CPUID_MASK (0x00001C00) ++#define IPROC_GIC_CI_HPIR_CPUID_OFFSET (10) ++#define IPROC_GIC_CI_ABPR_BP_MASK (0x00000003) ++ ++#define IPROC_GIC_DIST_CTRL_S_EN_S (0x00000001) ++#define IPROC_GIC_DIST_CTRL_S_EN_NS (0x00000002) ++#define IPROC_GIC_DIST_CTRL_NS_EN_NS (0x00000001) ++ ++#define IPROC_GIC_DIST_ISR_BIT_SIZE (1) ++#define IPROC_GIC_DIST_ISER_BIT_SIZE (1) ++#define IPROC_GIC_DIST_ICER_BIT_SIZE (1) ++#define IPROC_GIC_DIST_ISPR_BIT_SIZE (1) ++#define IPROC_GIC_DIST_ISPR_SECURE (1) ++#define IPROC_GIC_DIST_ISPR_NON_SECURE (0) ++#define IPROC_GIC_DIST_ICPR_BIT_SIZE (1) ++#define IPROC_GIC_DIST_IPR_BIT_SIZE (8) ++#define IPROC_GIC_DIST_IPTR_BIT_SIZE (8) ++#define IPROC_GIC_DIST_IPTR_CPU0 (0x01) ++#define IPROC_GIC_DIST_IPTR_CPU1 (0x02) ++#define IPROC_GIC_DIST_SGIR_ID_MASK (0xF) ++#define IPROC_GIC_DIST_SGIR_TR_LIST_MASK (0x00FF0000) ++#define IPROC_GIC_DIST_SGIR_TR_LIST_BOFFSET (16) ++#define IPROC_GIC_DIST_SGIR_TR_FILT_MASK (0x03000000) ++#define IPROC_GIC_DIST_SGIR_TR_FILT_BOFFSET (24) ++#define IPROC_GIC_DIST_SGIR_TR_FILT_FW_LIST (0) ++#define IPROC_GIC_DIST_SGIR_TR_FILT_FW_ALL_EX_ME (0x01) ++#define IPROC_GIC_DIST_SGIR_TR_FILT_FW_ME_ONLY (0x02) ++ ++#define IPROC_INTR_LEVEL_SENSITIVE (1) ++#define IPROC_INTR_EDGE_TRIGGERED (2) ++ ++/* GPIO Driver */ ++#if defined(CONFIG_IPROC_GPIO) || defined(CONFIG_IPROC_GPIO_MODULE) || \ ++ defined(CONFIG_IPROC_PWM) || defined(CONFIG_IPROC_PWM_MODULE) ++ ++/* Chipcommon A GPIO */ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_CCA_INT_STS (CCA_INT_STS_BASE) ++#define IPROC_CCA_INT_MASK (CCA_INT_MASK_BASE) ++#define IPROC_GPIO_CCA_BASE (CCA_GPIO_INPUT) ++#define IPROC_GPIO_CCA_DIN (CCA_GPIO_INPUT_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_DOUT (CCA_GPIO_OUT_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_EN (CCA_GPIO_OUT_EN_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_INT_LEVEL (CCA_GPIO_INT_POLARITY_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_INT_LEVEL_MASK (CCA_GPIOINT_MASK_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_INT_EVENT (CCA_GPIO_EVT_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_INT_EVENT_MASK (CCA_GPIO_EVTINT_MASK_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_WATCHDOG_COUNTER (CCA_WDOG_CTR_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_INT_EDGE (CCA_GPIO_EVT_INT_POLARITY_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_TIMER_VAL (CCA_GPIO_TMR_VAL_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_TIMEOUT_MASK (CCA_GPIO_TMR_OUT_MASK_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_CLK_DIV (CCA_CLK_DIV_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_DEBUG (CCA_GPIODBG_SEL_BASE - CCA_GPIO_INPUT_BASE) ++ ++#define IPROC_DMU_BASE (0x1800c000) ++ ++#define IPROC_GPIO_CCA_PULL_UP (0x01dc) ++#define IPROC_GPIO_CCA_PULL_DOWN (0x01e0) ++#define IPROC_GPIO_CCA_CTRL0 (0x01c0) ++ ++#else ++/* CONFIG_MACH_HX4, CONFIG_MACH_HR2, CONFIG_MACH_NSP, CONFIG_MACH_KT2, CONFIG_MACH_DNI_3448P */ ++#define IPROC_CCA_INT_STS (ChipcommonA_IntStatus_BASE) ++#define IPROC_CCA_INT_MASK (ChipcommonA_IntMask_BASE) ++#define IPROC_GPIO_CCA_BASE (ChipcommonA_GPIOInput) ++#define IPROC_GPIO_CCA_DIN (ChipcommonA_GPIOInput_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_DOUT (ChipcommonA_GPIOOut_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_EN (ChipcommonA_GPIOOutEn_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_INT_LEVEL (ChipcommonA_GPIOIntPolarity_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_INT_LEVEL_MASK (ChipcommonA_GPIOIntMask_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_INT_EVENT (ChipcommonA_GPIOEvent_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_INT_EVENT_MASK (ChipcommonA_GPIOEventIntMask_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_WATCHDOG_COUNTER (ChipcommonA_WatchdogCounter_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_INT_EDGE (ChipcommonA_GPIOEventIntPolarity_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_TIMER_VAL (ChipcommonA_GPIOTimerVal_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_TIMEOUT_MASK (ChipcommonA_GPIOTimerOutMask_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_CLK_DIV (ChipcommonA_ClkDiv_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_DEBUG (ChipcommonA_GPIODebugSel_BASE - ChipcommonA_GPIOInput_BASE) ++#endif ++ ++#if defined(CONFIG_MACH_NSP) ++#define IPROC_DMU_BASE (DMAC_pl330_DS) ++#define IPROC_GPIO_CCA_PULL_UP (CRU_GPIO_CONTROL7_BASE) ++#define IPROC_GPIO_CCA_PULL_DOWN (CRU_GPIO_CONTROL8_BASE) ++#define IPROC_GPIO_CCA_CTRL0 (CRU_GPIO_CONTROL0_BASE) ++#endif ++ ++/* Chipcommon B GPIO */ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_GPIO_CCB_BASE (CCB_GP_DATA_IN) ++#define IPROC_GPIO_CCB_DIN (CCB_GP_DATA_IN_BASE) ++#define IPROC_GPIO_CCB_DOUT (CCB_GP_DATA_OUT_BASE) ++#define IPROC_GPIO_CCB_EN (CCB_GP_OUT_EN_BASE) ++#define IPROC_GPIO_CCB_INT_TYPE (CCB_GP_INT_TYPE_BASE) ++#define IPROC_GPIO_CCB_INT_DE (CCB_GP_INT_DE_BASE) ++#define IPROC_GPIO_CCB_INT_EDGE (CCB_GP_INT_EDGE_BASE) ++#define IPROC_GPIO_CCB_INT_MASK (CCB_GP_INT_MSK_BASE) ++#define IPROC_GPIO_CCB_INT_STAT (CCB_GP_INT_STAT_BASE) ++#define IPROC_GPIO_CCB_INT_MSTAT (CCB_GP_INT_MSTAT_BASE) ++#define IPROC_GPIO_CCB_INT_CLR (CCB_GP_INT_CLR_BASE) ++#define IPROC_GPIO_CCB_AUX_SEL (CCB_GP_AUX_SEL_BASE) ++#define IPROC_GPIO_CCB_INIT_VAL (CCB_GP_INIT_VAL_BASE) ++#define IPROC_GPIO_CCB_PAD_RES (CCB_GP_PAD_RES_BASE) ++#define IPROC_GPIO_CCB_RES_EN (CCB_GP_RES_EN_BASE) ++#define IPROC_GPIO_CCB_TST_IN (CCB_GP_TEST_INPUT_BASE) ++#define IPROC_GPIO_CCB_TST_OUT (CCB_GP_TEST_OUTPUT_BASE) ++#define IPROC_GPIO_CCB_TST_EN (CCB_GP_TEST_ENABLE_BASE) ++#define IPROC_GPIO_CCB_PRB_EN (CCB_GP_PRB_ENABLE_BASE) ++#define IPROC_GPIO_CCB_PRB_OE (CCB_GP_PRB_OE_BASE) ++#elif defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_GPIO_CCG_BASE (ChipcommonG_GP_DATA_IN) ++#define IPROC_GPIO_CCB_BASE (ChipcommonG_GP_DATA_IN) ++#define IPROC_GPIO_CCB_DIN (ChipcommonG_GP_DATA_IN_BASE) ++#define IPROC_GPIO_CCB_DOUT (ChipcommonG_GP_DATA_OUT_BASE) ++#define IPROC_GPIO_CCB_EN (ChipcommonG_GP_OUT_EN_BASE) ++#define IPROC_GPIO_CCB_INT_TYPE (ChipcommonG_GP_INT_TYPE_BASE) ++#define IPROC_GPIO_CCB_INT_DE (ChipcommonG_GP_INT_DE_BASE) ++#define IPROC_GPIO_CCB_INT_EDGE (ChipcommonG_GP_INT_EDGE_BASE) ++#define IPROC_GPIO_CCB_INT_MASK (ChipcommonG_GP_INT_MSK_BASE) ++#define IPROC_GPIO_CCB_INT_STAT (ChipcommonG_GP_INT_STAT_BASE) ++#define IPROC_GPIO_CCB_INT_MSTAT (ChipcommonG_GP_INT_MSTAT_BASE) ++#define IPROC_GPIO_CCB_INT_CLR (ChipcommonG_GP_INT_CLR_BASE) ++#define IPROC_GPIO_CCB_AUX_SEL (ChipcommonG_GP_AUX_SEL_BASE) ++#define IPROC_GPIO_CCB_INIT_VAL (ChipcommonG_GP_INIT_VAL_BASE) ++#define IPROC_GPIO_CCB_PAD_RES (ChipcommonG_GP_PAD_RES_BASE) ++#define IPROC_GPIO_CCB_RES_EN (ChipcommonG_GP_RES_EN_BASE) ++#define IPROC_GPIO_CCB_TST_IN (ChipcommonG_GP_TEST_INPUT_BASE) ++#define IPROC_GPIO_CCB_TST_OUT (ChipcommonG_GP_TEST_OUTPUT_BASE) ++#define IPROC_GPIO_CCB_TST_EN (ChipcommonG_GP_TEST_ENABLE_BASE) ++#define IPROC_GPIO_CCB_PRB_EN (ChipcommonG_GP_PRB_ENABLE_BASE) ++#define IPROC_GPIO_CCB_PRB_OE (ChipcommonG_GP_PRB_OE_BASE) ++#else ++/* CONFIG_MACH_HX4, CONFIG_MACH_HR2, CONFIG_MACH_NSP, CONFIG_MACH_KT2, CONFIG_MACH_DNI_3448P */ ++#define IPROC_GPIO_CCB_BASE (ChipcommonB_GP_DATA_IN) ++#define IPROC_GPIO_CCB_DIN (ChipcommonB_GP_DATA_IN_BASE) ++#define IPROC_GPIO_CCB_DOUT (ChipcommonB_GP_DATA_OUT_BASE) ++#define IPROC_GPIO_CCB_EN (ChipcommonB_GP_OUT_EN_BASE) ++#define IPROC_GPIO_CCB_INT_TYPE (ChipcommonB_GP_INT_TYPE_BASE) ++#define IPROC_GPIO_CCB_INT_DE (ChipcommonB_GP_INT_DE_BASE) ++#define IPROC_GPIO_CCB_INT_EDGE (ChipcommonB_GP_INT_EDGE_BASE) ++#define IPROC_GPIO_CCB_INT_MASK (ChipcommonB_GP_INT_MSK_BASE) ++#define IPROC_GPIO_CCB_INT_STAT (ChipcommonB_GP_INT_STAT_BASE) ++#define IPROC_GPIO_CCB_INT_MSTAT (ChipcommonB_GP_INT_MSTAT_BASE) ++#define IPROC_GPIO_CCB_INT_CLR (ChipcommonB_GP_INT_CLR_BASE) ++#define IPROC_GPIO_CCB_AUX_SEL (ChipcommonB_GP_AUX_SEL_BASE) ++#define IPROC_GPIO_CCB_INIT_VAL (ChipcommonB_GP_INIT_VAL_BASE) ++#define IPROC_GPIO_CCB_PAD_RES (ChipcommonB_GP_PAD_RES_BASE) ++#define IPROC_GPIO_CCB_RES_EN (ChipcommonB_GP_RES_EN_BASE) ++#define IPROC_GPIO_CCB_TST_IN (ChipcommonB_GP_TEST_INPUT_BASE) ++#define IPROC_GPIO_CCB_TST_OUT (ChipcommonB_GP_TEST_OUTPUT_BASE) ++#define IPROC_GPIO_CCB_TST_EN (ChipcommonB_GP_TEST_ENABLE_BASE) ++#define IPROC_GPIO_CCB_PRB_EN (ChipcommonB_GP_PRB_ENABLE_BASE) ++#define IPROC_GPIO_CCB_PRB_OE (ChipcommonB_GP_PRB_OE_BASE) ++#endif ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++#define IPROC_GPIO_CCA_INT (117) ++#define IPROC_GPIO_CCB_INT (119) ++#elif defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_GPIO_CCG_INT (116) ++#else ++/* CONFIG_MACH_HX4, CONFIG_MACH_HR2, CONFIG_MACH_KT2, CONFIG_MACH_DNI_3448P */ ++#define IPROC_GPIO_CCA_INT (123) ++#define IPROC_GPIO_CCB_INT (125) ++#endif ++#endif /* CONFIG_IPROC_GPIO || CONFIG_IPROC_GPIO_MODULE */ ++ ++/* PWM Driver */ ++#if defined(CONFIG_IPROC_PWM) || defined(CONFIG_IPROC_PWM_MODULE) ++#if defined(CONFIG_MACH_NS) ++#define IPROC_CCB_PWM_CTL (CCB_PWM_CTL) ++#define IPROC_CCB_PWM_CTL_BASE (CCB_PWM_CTL_BASE) ++#define IPROC_CCB_PWM_PRESCALE_BASE (CCB_PWM_PRESCALE_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT0_BASE (CCB_PWM_PERIOD_COUNT0_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT1_BASE (CCB_PWM_PERIOD_COUNT1_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT2_BASE (CCB_PWM_PERIOD_COUNT2_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT3_BASE (CCB_PWM_PERIOD_COUNT3_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT0_BASE (CCB_PWM_DUTY_HI_COUNT0_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT1_BASE (CCB_PWM_DUTY_HI_COUNT1_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT2_BASE (CCB_PWM_DUTY_HI_COUNT2_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT3_BASE (CCB_PWM_DUTY_HI_COUNT3_BASE) ++#endif /* CONFIG_MACH_NS */ ++ ++#if defined(CONFIG_MACH_NSP) ++#define IPROC_CCB_PWM_CTL (ChipcommonB_PWMCTL) ++#define IPROC_CCB_PWM_CTL_BASE (ChipcommonB_PWMCTL_BASE) ++#define IPROC_CCB_PWM_PRESCALE_BASE (ChipcommonB_PWM_PRESCALE_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT0_BASE (ChipcommonB_PWM_PERIOD_COUNT0_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT1_BASE (ChipcommonB_PWM_PERIOD_COUNT1_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT2_BASE (ChipcommonB_PWM_PERIOD_COUNT2_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT3_BASE (ChipcommonB_PWM_PERIOD_COUNT3_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT0_BASE (ChipcommonB_PWM_DUTYHI_COUNT0_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT1_BASE (ChipcommonB_PWM_DUTYHI_COUNT1_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT2_BASE (ChipcommonB_PWM_DUTYHI_COUNT2_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT3_BASE (ChipcommonB_PWM_DUTYHI_COUNT3_BASE) ++#endif /* CONFIG_MACH_NSP */ ++ ++#endif /* CONFIG_IPROC_PWM */ ++ ++/* ChipCommonB Timer */ ++#if defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_CCB_TIMER0_REGS_VA HW_IO_PHYS_TO_VIRT(ChipcommonG_tim0_TIM_TIMER1Load) ++#define IPROC_CCB_TIMER1_REGS_VA HW_IO_PHYS_TO_VIRT(ChipcommonG_tim1_TIM_TIMER1Load) ++#define IPROC_CCB_TIMER2_REGS_VA HW_IO_PHYS_TO_VIRT(ChipcommonG_tim2_TIM_TIMER1Load) ++#define IPROC_CCB_TIMER3_REGS_VA HW_IO_PHYS_TO_VIRT(ChipcommonG_tim3_TIM_TIMER1Load) ++#define IPROC_CCB_TIMER_INT_START (119) ++#define IPROC_CCB_TIMER_INT_COUNT (4) ++#elif (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++#define IPROC_CCB_TIMER0_REGS_VA (IPROC_CCB_TIM0_REG_VA + 0x00) ++#define IPROC_CCB_TIMER1_REGS_VA (IPROC_CCB_TIM0_REG_VA + 0x20) ++#define IPROC_CCB_TIMER2_REGS_VA (IPROC_CCB_TIM1_REG_VA + 0x00) ++#define IPROC_CCB_TIMER3_REGS_VA (IPROC_CCB_TIM1_REG_VA + 0x20) ++#define IPROC_CCB_TIMER_INT_START (122) ++#define IPROC_CCB_TIMER_INT_COUNT (4) ++#else /* CONFIG_MACH_HX4, CONFIG_MACH_HR2, CONFIG_MACH_KT2, CONFIG_MACH_DNI_3448P */ ++#define IPROC_CCB_TIMER0_REGS_VA (IPROC_CCB_TIM0_REG_VA + 0x00) ++#define IPROC_CCB_TIMER1_REGS_VA (IPROC_CCB_TIM0_REG_VA + 0x20) ++#define IPROC_CCB_TIMER2_REGS_VA (IPROC_CCB_TIM1_REG_VA + 0x00) ++#define IPROC_CCB_TIMER3_REGS_VA (IPROC_CCB_TIM1_REG_VA + 0x20) ++#define IPROC_CCB_TIMER_INT_START (129) ++#define IPROC_CCB_TIMER_INT_COUNT (4) ++#endif ++ ++/* ChipCommonB Watchdog */ ++/* ++ * CCB WDT could be set only when CONFIG_MACH_HR2, CONFIG_MACH_HX4, ++ * CONFIG_MACH_DNI_3448P or CONFIG_MACH_NSP is set ++ */ ++#define IPROC_CCB_WDT_WDOGLOAD ChipcommonB_WDT_WDOGLOAD ++#define IPROC_CCB_WDT_REG_BASE IPROC_CCB_WDT_WDOGLOAD ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_CCB_WDT_BOOTSTATUS DMU_PCU_CRU_RESET_REASON ++#define IPROC_CCB_WDT_BOOTSTATUS_BIT DMU_PCU_CRU_RESET_REASON__watchdog_reset ++#elif defined(CONFIG_MACH_NSP) ++#define IPROC_CCB_WDT_BOOTSTATUS CRU_WATCHDOG_PCIE_RESET_STATUS ++#define IPROC_CCB_WDT_BOOTSTATUS_BIT CRU_WATCHDOG_PCIE_RESET_STATUS__CCB_WATCHDOG_RESET_EVENT ++#endif ++ ++/* ChipCommonG Watchdog */ ++#if defined(CONFIG_IPROC_CCG_WDT) || defined(CONFIG_IPROC_CCG_WDT_MODULE) ++#define IPROC_CCG_WDT_REG_BASE ChipcommonG_WDT_WDOGLOAD ++#define IPROC_CCG_WDT_BOOTSTATUS DMU_PCU_CRU_RESET_REASON ++#define IPROC_CCG_WDT_BOOTSTATUS_BIT DMU_PCU_CRU_RESET_REASON__watchdog_reset ++#endif /* CONFIG_IPROC_CCG_WDT || CONFIG_IPROC_CCG_WDT_MODULE */ ++ ++#if defined(CONFIG_ARM_SP805_WATCHDOG) || defined(CONFIG_ARM_SP805_WATCHDOG_MODULE) ++#define IPROC_SP805_WDT_REG_BASE IPROC_CCB_WDT_REG_BASE ++#define IPROC_SP805_WDT_BOOTSTATUS IPROC_CCB_WDT_BOOTSTATUS ++#define IPROC_SP805_WDT_BOOTSTATUS_BIT IPROC_CCB_WDT_BOOTSTATUS_BIT ++#endif /* CONFIG_IPROC_SP805_WDT */ ++ ++#endif /*__IPROC_REGS_H */ +diff --git a/arch/arm/mach-iproc/include/mach/nand_iproc.h b/arch/arm/mach-iproc/include/mach/nand_iproc.h +new file mode 100644 +index 0000000..9c4d4fc +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/nand_iproc.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _NAND_IPROC_H_ ++#define _NAND_IPROC_H_ ++ ++/* ++ * Registers used directly in driver ++ */ ++ ++/* ++ * Shared Structure ++ */ ++struct mtd_partition; ++struct brcmnand_platform_data { ++ int chip_select; ++ int strap_boot; ++ int strap_type; ++ int strap_page_size; ++ int nr_parts; ++ struct mtd_partition *parts; ++}; ++ ++#endif /* _NAND_IPROC_H_ */ +diff --git a/arch/arm/mach-iproc/include/mach/qspi_iproc.h b/arch/arm/mach-iproc/include/mach/qspi_iproc.h +new file mode 100644 +index 0000000..14fcac8 +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/qspi_iproc.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _QSPI_IPROC_H_ ++#define _QSPI_IPROC_H_ ++ ++/* ++ * Shared Structure ++ */ ++struct brcmspi_platform_data { ++ int flash_cs; ++}; ++ ++#endif /* _SPI_IPROC_H_ */ +diff --git a/arch/arm/mach-iproc/include/mach/reg_utils.h b/arch/arm/mach-iproc/include/mach/reg_utils.h +new file mode 100644 +index 0000000..6cc36bf +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/reg_utils.h +@@ -0,0 +1,160 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef REG_UTILS ++#define REG_UTILS ++ ++/* ---- Include Files ---------------------------------------------------- */ ++ ++#include ++ ++/* ---- Public Constants and Types --------------------------------------- */ ++ ++#define __REG32(x) (*((volatile uint32_t *)(x))) ++#define __REG16(x) (*((volatile uint16_t *)(x))) ++#define __REG8(x) (*((volatile uint8_t *) (x))) ++ ++/* ---- Public Variable Externs ------------------------------------------ */ ++/* ---- Public Function Prototypes --------------------------------------- */ ++ ++/****************************************************************************/ ++/* ++ * 32-bit register access functions ++ */ ++/****************************************************************************/ ++ ++static inline void ++reg32_clear_bits(volatile uint32_t *reg, uint32_t value) ++{ ++ *reg &= ~(value); ++} ++ ++static inline void ++reg32_set_bits(volatile uint32_t *reg, uint32_t value) ++{ ++ *reg |= value; ++} ++ ++static inline void ++reg32_toggle_bits(volatile uint32_t *reg, uint32_t value) ++{ ++ *reg ^= value; ++} ++ ++static inline void ++reg32_write_masked(volatile uint32_t *reg, uint32_t mask, ++ uint32_t value) ++{ ++ *reg = (*reg & (~mask)) | (value & mask); ++} ++ ++static inline void ++reg32_write(volatile uint32_t *reg, uint32_t value) ++{ ++ *reg = value; ++} ++ ++static inline uint32_t ++reg32_read(volatile uint32_t *reg) ++{ ++ return *reg; ++} ++ ++/****************************************************************************/ ++/* ++ * 16-bit register access functions ++ */ ++/****************************************************************************/ ++ ++static inline void ++reg16_clear_bits(volatile uint16_t *reg, uint16_t value) ++{ ++ *reg &= ~(value); ++} ++ ++static inline void ++reg16_set_bits(volatile uint16_t *reg, uint16_t value) ++{ ++ *reg |= value; ++} ++ ++static inline void ++reg16_toggle_bits(volatile uint16_t *reg, uint16_t value) ++{ ++ *reg ^= value; ++} ++ ++static inline void ++reg16_write_masked(volatile uint16_t *reg, uint16_t mask, uint16_t value) ++{ ++ *reg = (*reg & (~mask)) | (value & mask); ++} ++ ++static inline void ++reg16_write(volatile uint16_t *reg, uint16_t value) ++{ ++ *reg = value; ++} ++ ++static inline uint16_t ++reg16_read(volatile uint16_t *reg) ++{ ++ return *reg; ++} ++ ++/****************************************************************************/ ++/* ++ * 8-bit register access functions ++ */ ++/****************************************************************************/ ++ ++static inline void ++reg8_clear_bits(volatile uint8_t *reg, uint8_t value) ++{ ++ *reg &= ~(value); ++} ++ ++static inline void ++reg8_set_bits(volatile uint8_t *reg, uint8_t value) ++{ ++ *reg |= value; ++} ++ ++static inline void ++reg8_toggle_bits(volatile uint8_t *reg, uint8_t value) ++{ ++ *reg ^= value; ++} ++ ++static inline void ++reg8_write_masked(volatile uint8_t *reg, uint8_t mask, uint8_t value) ++{ ++ *reg = (*reg & (~mask)) | (value & mask); ++} ++ ++static inline void ++reg8_write(volatile uint8_t *reg, uint8_t value) ++{ ++ *reg = value; ++} ++ ++static inline uint8_t ++reg8_read(volatile uint8_t *reg) ++{ ++ return *reg; ++} ++#endif /* REG_UTILS */ +diff --git a/arch/arm/mach-iproc/include/mach/socregs_ing_open.h b/arch/arm/mach-iproc/include/mach/socregs_ing_open.h +new file mode 100644 +index 0000000..2431b98 +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/socregs_ing_open.h +@@ -0,0 +1,775 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __SOCREGS_ING_OPEN_H ++#define __SOCREGS_ING_OPEN_H ++ ++#define ChipcommonA_ChipID 0x18000000 ++#define ChipcommonB_PWMCTL 0x18031000 ++#define ChipcommonB_WDT_WDOGLOAD 0x18039000 ++#define ChipcommonB_GP_DATA_IN 0x18030000 ++#define ChipcommonB_GP_AUX_SEL_BASE 0x028 ++#define ChipcommonB_SMBus_Config 0x18038000 ++#define ChipcommonA_OTPProg 0x18000018 ++#define ChipcommonA_OTPLayout 0x1800001c ++#define ChipcommonA_CoreCapabilities 0x18000004 ++#define ChipcommonA_OTPStatus 0x18000010 ++#define ChipcommonB_rng_CTRL 0x18033000 ++#define QSPI_mspi_SPCR0_LSB 0x18027200 ++#define QSPI_mspi_DISABLE_FLUSH_GEN 0x18027384 ++#define QSPI_bspi_registers_REVISION_ID 0x18027000 ++#define QSPI_bspi_registers_BSPI_PIO_DATA 0x1802704c ++#define QSPI_raf_START_ADDR 0x18027100 ++#define QSPI_raf_interrupt_LR_fullness_reached 0x180273a0 ++#define QSPI_mspi_interrupt_MSPI_halt_set_transaction_done 0x180273b8 ++#define QSPI_IDM_IDM_IO_CONTROL_DIRECT 0x1811c408 ++#define QSPI_raf_CURR_ADDR 0x18027120 ++#define CRU_control 0x1803e000 ++#define GMAC0_DEVCONTROL 0x18022000 ++#define GMAC1_DEVCONTROL 0x18023000 ++#define ChipcommonA_GPIOEvent_BASE 0x078 ++#define ChipcommonA_GPIOInput_BASE 0x060 ++#define ChipcommonB_GP_INT_CLR_BASE 0x024 ++#define ChipcommonA_GPIOEventIntMask_BASE 0x07c ++#define ChipcommonA_GPIOInput_BASE 0x060 ++#define ChipcommonB_GP_INT_MSK_BASE 0x018 ++#define ChipcommonA_GPIOIntMask_BASE 0x074 ++#define ChipcommonB_GP_INT_MSK_BASE 0x018 ++#define ChipcommonA_GPIOEventIntMask_BASE 0x07c ++#define ChipcommonB_GP_INT_MSTAT_BASE 0x020 ++#define ChipcommonA_GPIOEventIntPolarity_BASE 0x084 ++#define ChipcommonA_IntStatus_BASE 0x020 ++#define ChipcommonA_GPIOIntPolarity_BASE 0x070 ++#define ChipcommonA_IntStatus_BASE 0x020 ++#define ChipcommonB_GP_INT_DE_BASE 0x010 ++#define ChipcommonB_GP_INT_EDGE_BASE 0x014 ++#define ChipcommonB_GP_INT_TYPE_BASE 0x00c ++#define ChipcommonA_GPIOIntPolarity_BASE 0x070 ++#define ChipcommonB_GP_AUX_SEL_BASE 0x028 ++#define ChipcommonB_GP_PAD_RES_BASE 0x034 ++#define ChipcommonB_GP_RES_EN_BASE 0x038 ++#define ChipcommonA_ChipID 0x18000000 ++#define DMAC_pl330_DS 0x18020000 ++#define ChipcommonA_GPIOInput 0x18000060 ++#define ChipcommonB_GP_DATA_IN 0x18030000 ++#define PAXB_0_CLK_CONTROL 0x18012000 ++#define PAXB_0_CONFIG_IND_ADDR_BASE 0x120 ++#define ChipcommonB_MII_Management_Control 0x18032000 ++#define ChipcommonB_MII_Management_Command_Data 0x18032004 ++#define NAND_nand_flash_REVISION 0x18026000 ++#define NAND_direct_read_rd_miss 0x18026f00 ++#define NAND_IDM_IDM_IO_CONTROL_DIRECT 0x1811b408 ++#define ChipcommonB_PWM_PERIOD_COUNT0_BASE 0x004 ++#define ChipcommonB_PWM_PRESCALE_BASE 0x024 ++#define ChipcommonB_PWM_PERIOD_COUNT1_BASE 0x00c ++#define ChipcommonB_PWM_PERIOD_COUNT2_BASE 0x014 ++#define ChipcommonB_PWM_PERIOD_COUNT3_BASE 0x01c ++#define ChipcommonB_PWM_DUTYHI_COUNT0_BASE 0x008 ++#define ChipcommonB_PWM_DUTYHI_COUNT1_BASE 0x010 ++#define ChipcommonB_PWM_DUTYHI_COUNT2_BASE 0x018 ++#define ChipcommonB_PWM_DUTYHI_COUNT3_BASE 0x020 ++#define ChipcommonB_PWMCTL_BASE 0x000 ++#define ChipcommonB_rng_CTRL 0x18033000 ++#if (defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define USB2_IDM_IDM_IO_CONTROL_DIRECT 0x18115408 ++#define USB2D_IDM_IDM_IO_CONTROL_DIRECT 0x18116408 ++#define USB2D_IDM_IDM_IO_CONTROL_DIRECT__clk_enable 0 ++#define USB2D_IDM_IDM_RESET_CONTROL 0x18116800 ++#define USB2D_IDM_IDM_RESET_CONTROL__RESET 0 ++#endif ++#define DMU_CRU_RESET_BASE 0x200 ++#define ChipcommonB_SMBus1_SMBus_Config 0x1803b000 ++#if (defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define USB2D_ENDPNT_IN_CTRL_0 0x18042000 ++#endif ++#define IHOST_S1_IDM_ERROR_LOG_CONTROL 0x18107900 ++#define IHOST_S1_IDM_ERROR_LOG_COMPLETE 0x18107904 ++#define IHOST_S1_IDM_ERROR_LOG_STATUS 0x18107908 ++#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810790c ++#define IHOST_S1_IDM_ERROR_LOG_ID 0x18107914 ++#define IHOST_S1_IDM_ERROR_LOG_FLAGS 0x1810791c ++#define IHOST_S1_IDM_INTERRUPT_STATUS 0x18107a00 ++#define IHOST_S0_IDM_ERROR_LOG_CONTROL 0x18108900 ++#define IHOST_S0_IDM_ERROR_LOG_COMPLETE 0x18108904 ++#define IHOST_S0_IDM_ERROR_LOG_STATUS 0x18108908 ++#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810890c ++#define IHOST_S0_IDM_ERROR_LOG_ID 0x18108914 ++#define IHOST_S0_IDM_ERROR_LOG_FLAGS 0x1810891c ++#define IHOST_S0_IDM_INTERRUPT_STATUS 0x18108a00 ++#define DDR_S1_IDM_ERROR_LOG_CONTROL 0x18109900 ++#define DDR_S1_IDM_ERROR_LOG_COMPLETE 0x18109904 ++#define DDR_S1_IDM_ERROR_LOG_STATUS 0x18109908 ++#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810990c ++#define DDR_S1_IDM_ERROR_LOG_ID 0x18109914 ++#define DDR_S1_IDM_ERROR_LOG_FLAGS 0x1810991c ++#define DDR_S1_IDM_INTERRUPT_STATUS 0x18109a00 ++#define DDR_S2_IDM_ERROR_LOG_CONTROL 0x1810a900 ++#define DDR_S2_IDM_ERROR_LOG_COMPLETE 0x1810a904 ++#define DDR_S2_IDM_ERROR_LOG_STATUS 0x1810a908 ++#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB 0x1810a90c ++#define DDR_S2_IDM_ERROR_LOG_ID 0x1810a914 ++#define DDR_S2_IDM_ERROR_LOG_FLAGS 0x1810a91c ++#define DDR_S2_IDM_INTERRUPT_STATUS 0x1810aa00 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810b900 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810b904 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810b908 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810b90c ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID 0x1810b914 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810b91c ++#define AXI_PCIE_S0_IDM_IDM_INTERRUPT_STATUS 0x1810ba00 ++#if (defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_CONTROL 0x1810c900 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_COMPLETE 0x1810c904 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_STATUS 0x1810c908 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810c90c ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ID 0x1810c914 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_FLAGS 0x1810c91c ++#define AXI_PCIE_S1_IDM_IDM_INTERRUPT_STATUS 0x1810ca00 ++#endif ++#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810d900 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810d904 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810d908 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810d90c ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ID 0x1810d914 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810d91c ++#define CMICD_S0_IDM_IDM_INTERRUPT_STATUS 0x1810da00 ++#define APBY_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810f900 ++#define APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810f904 ++#define APBY_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810f908 ++#define APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810f90c ++#define APBY_S0_IDM_IDM_ERROR_LOG_ID 0x1810f914 ++#define APBY_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810f91c ++#define APBY_S0_IDM_IDM_INTERRUPT_STATUS 0x1810fa00 ++#define ROM_S0_IDM_ERROR_LOG_CONTROL 0x1811a900 ++#define ROM_S0_IDM_ERROR_LOG_COMPLETE 0x1811a904 ++#define ROM_S0_IDM_ERROR_LOG_STATUS 0x1811a908 ++#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1811a90c ++#define ROM_S0_IDM_ERROR_LOG_ID 0x1811a914 ++#define ROM_S0_IDM_ERROR_LOG_FLAGS 0x1811a91c ++#define ROM_S0_IDM_INTERRUPT_STATUS 0x1811aa00 ++#define NAND_IDM_IDM_ERROR_LOG_CONTROL 0x1811b900 ++#define NAND_IDM_IDM_ERROR_LOG_COMPLETE 0x1811b904 ++#define NAND_IDM_IDM_ERROR_LOG_STATUS 0x1811b908 ++#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811b90c ++#define NAND_IDM_IDM_ERROR_LOG_ID 0x1811b914 ++#define NAND_IDM_IDM_ERROR_LOG_FLAGS 0x1811b91c ++#define NAND_IDM_IDM_INTERRUPT_STATUS 0x1811ba00 ++#define QSPI_IDM_IDM_ERROR_LOG_CONTROL 0x1811c900 ++#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE 0x1811c904 ++#define QSPI_IDM_IDM_ERROR_LOG_STATUS 0x1811c908 ++#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811c90c ++#define QSPI_IDM_IDM_ERROR_LOG_ID 0x1811c914 ++#define QSPI_IDM_IDM_ERROR_LOG_FLAGS 0x1811c91c ++#define QSPI_IDM_IDM_INTERRUPT_STATUS 0x1811ca00 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1811d900 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1811d904 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS 0x1811d908 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811d90c ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID 0x1811d914 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1811d91c ++#define A9JTAG_S0_IDM_IDM_INTERRUPT_STATUS 0x1811da00 ++#define SRAM_S0_IDM_ERROR_LOG_CONTROL 0x18120900 ++#define SRAM_S0_IDM_ERROR_LOG_COMPLETE 0x18120904 ++#define SRAM_S0_IDM_ERROR_LOG_STATUS 0x18120908 ++#define SRAM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1812090c ++#define SRAM_S0_IDM_ERROR_LOG_ID 0x18120914 ++#define SRAM_S0_IDM_ERROR_LOG_FLAGS 0x1812091c ++#define SRAM_S0_IDM_INTERRUPT_STATUS 0x18120a00 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18121900 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18121904 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_STATUS 0x18121908 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1812190c ++#define APBZ_S0_IDM_IDM_ERROR_LOG_ID 0x18121914 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1812191c ++#define APBZ_S0_IDM_IDM_INTERRUPT_STATUS 0x18121a00 ++#if (defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define APBV_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18122900 ++#define APBV_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18122904 ++#define APBV_S0_IDM_IDM_ERROR_LOG_STATUS 0x18122908 ++#define APBV_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1812290c ++#define APBV_S0_IDM_IDM_ERROR_LOG_ID 0x18122914 ++#define APBV_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1812291c ++#define APBV_S0_IDM_IDM_INTERRUPT_STATUS 0x18122a00 ++#endif ++#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL 0x18123900 ++#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE 0x18123904 ++#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS 0x18123908 ++#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB 0x1812390c ++#define AXIIC_DS_3_IDM_ERROR_LOG_ID 0x18123914 ++#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS 0x1812391c ++#define AXIIC_DS_3_IDM_INTERRUPT_STATUS 0x18123a00 ++#if (defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define AXIIC_DS_4_IDM_ERROR_LOG_CONTROL 0x18124900 ++#define AXIIC_DS_4_IDM_ERROR_LOG_COMPLETE 0x18124904 ++#define AXIIC_DS_4_IDM_ERROR_LOG_STATUS 0x18124908 ++#define AXIIC_DS_4_IDM_ERROR_LOG_ADDR_LSB 0x1812490c ++#define AXIIC_DS_4_IDM_ERROR_LOG_ID 0x18124914 ++#define AXIIC_DS_4_IDM_ERROR_LOG_FLAGS 0x1812491c ++#define AXIIC_DS_4_IDM_INTERRUPT_STATUS 0x18124a00 ++#endif ++#define APBW_IDM_IDM_ERROR_LOG_CONTROL 0x18131900 ++#define APBW_IDM_IDM_ERROR_LOG_COMPLETE 0x18131904 ++#define APBW_IDM_IDM_ERROR_LOG_STATUS 0x18131908 ++#define APBW_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813190c ++#define APBW_IDM_IDM_ERROR_LOG_ID 0x18131914 ++#define APBW_IDM_IDM_ERROR_LOG_FLAGS 0x1813191c ++#define APBW_IDM_IDM_INTERRUPT_STATUS 0x18131a00 ++#define APBX_IDM_IDM_ERROR_LOG_CONTROL 0x18132900 ++#define APBX_IDM_IDM_ERROR_LOG_COMPLETE 0x18132904 ++#define APBX_IDM_IDM_ERROR_LOG_STATUS 0x18132908 ++#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813290c ++#define APBX_IDM_IDM_ERROR_LOG_ID 0x18132914 ++#define APBX_IDM_IDM_ERROR_LOG_FLAGS 0x1813291c ++#define APBX_IDM_IDM_INTERRUPT_STATUS 0x18132a00 ++#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL 0x18141900 ++#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE 0x18141904 ++#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS 0x18141908 ++#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB 0x1814190c ++#define AXIIC_DS_0_IDM_ERROR_LOG_ID 0x18141914 ++#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS 0x1814191c ++#define AXIIC_DS_0_IDM_INTERRUPT_STATUS 0x18141a00 ++#if (defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define AXIIC_DS_1_IDM_ERROR_LOG_CONTROL 0x18142900 ++#define AXIIC_DS_1_IDM_ERROR_LOG_COMPLETE 0x18142904 ++#define AXIIC_DS_1_IDM_ERROR_LOG_STATUS 0x18142908 ++#define AXIIC_DS_1_IDM_ERROR_LOG_ADDR_LSB 0x1814290c ++#define AXIIC_DS_1_IDM_ERROR_LOG_ID 0x18142914 ++#define AXIIC_DS_1_IDM_ERROR_LOG_FLAGS 0x1814291c ++#define AXIIC_DS_1_IDM_INTERRUPT_STATUS 0x18142a00 ++#endif ++#define DMU_PCU_IPROC_STRAPS_CAPTURED_BASE 0x028 ++#define DMU_PCU_IPROC_STRAPS_CAPTURED__strap_boot_dev_R 9 ++#define DMU_PCU_IPROC_STRAPS_CAPTURED__strap_nand_type_R 5 ++#define DMU_PCU_IPROC_STRAPS_CAPTURED__strap_nand_page_R 3 ++#define ChipcommonA_IntMask_BASE 0x024 ++#define DMU_PCU_CRU_RESET_REASON 0x1803f014 ++#define DMU_PCU_CRU_RESET_REASON__watchdog_reset 0 ++#define ChipcommonA_GPIOInput 0x18000060 ++#define ChipcommonA_GPIOOut 0x18000064 ++#define ChipcommonA_GPIOOutEn 0x18000068 ++#define AMAC_IDM0_IO_CONTROL_DIRECT 0x18110408 ++#define AMAC_IDM0_IO_CONTROL_DIRECT__CLK_250_SEL 6 ++#define AMAC_IDM0_IO_CONTROL_DIRECT__DIRECT_GMII_MODE 5 ++#define AMAC_IDM0_IO_CONTROL_DIRECT__DEST_SYNC_MODE_EN 3 ++#define AMAC_IDM1_IO_CONTROL_DIRECT 0x18111408 ++#define AMAC_IDM1_IO_CONTROL_DIRECT__CLK_250_SEL 6 ++#define AMAC_IDM1_IO_CONTROL_DIRECT__DIRECT_GMII_MODE 5 ++#define AMAC_IDM1_IO_CONTROL_DIRECT__DEST_SYNC_MODE_EN 3 ++#if defined(CONFIG_MACH_KT2) ++#define IPROC_WRAP_USBPHY_CTRL 0x1803fc20 ++#define IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_CTRL_SEL 1 ++#define IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL 3 ++#define IPROC_WRAP_MISC_CONTROL 0x1803fc24 ++#define IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_MDIO_SEL 2 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0 0x1803fc00 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_BASE 0xc00 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__CH0_MDEL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__CH0_MDEL_R 29 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__CH0_MDEL_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__CH0_MDEL_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__NDIV_RELOCK 28 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__NDIV_RELOCK_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__NDIV_RELOCK_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__FAST_LOCK 27 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__FAST_LOCK_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__FAST_LOCK_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DIV2 26 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DIV2_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DIV2_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DLY_L 25 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DLY_R 24 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DLY_WIDTH 2 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DLY_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__PWM_RATE_L 23 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__PWM_RATE_R 22 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__PWM_RATE_WIDTH 2 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__PWM_RATE_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_MODE_L 21 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_MODE_R 20 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_MODE_WIDTH 2 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_MODE_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__AUX_CTRL 19 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__AUX_CTRL_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__AUX_CTRL_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__TESTCLKOUT 18 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__TESTCLKOUT_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__TESTCLKOUT_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_UPDATE 17 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_UPDATE_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_UPDATE_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_SELECT_L 16 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_SELECT_R 14 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_SELECT_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_SELECT_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_RESET 13 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_RESET_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_RESET_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_ENABLE 12 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_ENABLE_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_ENABLE_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_L 11 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_WIDTH 12 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_RESETVALUE 0x000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1 0x1803fc04 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_BASE 0xc04 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KA_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KA_R 29 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KA_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KA_RESETVALUE 0x2 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KI_L 28 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KI_R 26 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KI_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KI_RESETVALUE 0x3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KP_L 25 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KP_R 22 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KP_WIDTH 4 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KP_RESETVALUE 0x7 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__SSC_LIMIT_L 21 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__SSC_LIMIT_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__SSC_LIMIT_WIDTH 22 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__SSC_LIMIT_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_RESETVALUE 0x4dc00000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2 0x1803fc08 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_BASE 0xc08 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__PDIV_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__PDIV_R 29 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__PDIV_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__PDIV_RESETVALUE 0x1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_PHASE_EN 28 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_PHASE_EN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_PHASE_EN_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_OFFSET_L 27 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_OFFSET_R 16 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_OFFSET_WIDTH 12 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_OFFSET_RESETVALUE 0x000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__SSC_STEP_L 15 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__SSC_STEP_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__SSC_STEP_WIDTH 16 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__SSC_STEP_RESETVALUE 0x0000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_RESETVALUE 0x20000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3 0x1803fc0c ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_BASE 0xc0c ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__SSC_MODE 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__SSC_MODE_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__SSC_MODE_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__PHASE8_EN 30 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__PHASE8_EN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__PHASE8_EN_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_FRAC_L 29 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_FRAC_R 10 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_FRAC_WIDTH 20 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_FRAC_RESETVALUE 0x00000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_INT_L 9 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_INT_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_INT_WIDTH 10 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_INT_RESETVALUE 0x80 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_RESETVALUE 0x80 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4 0x1803fc10 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_BASE 0xc10 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__RESERVED_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__RESERVED_R 29 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__RESERVED_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__RESERVED_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__PWRDWN 28 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__PWRDWN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__PWRDWN_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__SPARE_L 27 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__SPARE_R 24 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__SPARE_WIDTH 4 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__SPARE_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__TEST_EN 23 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__TEST_EN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__TEST_EN_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__TEST_SEL 22 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__TEST_SEL_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__TEST_SEL_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__D2C_HYST_EN 21 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__D2C_HYST_EN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__D2C_HYST_EN_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__BYPASS_POR 20 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__BYPASS_POR_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__BYPASS_POR_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__LOAD_EN_L 19 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__LOAD_EN_R 14 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__LOAD_EN_WIDTH 6 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__LOAD_EN_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__HOLD_L 13 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__HOLD_R 8 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__HOLD_WIDTH 6 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__HOLD_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__CH0_MDIV_L 7 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__CH0_MDIV_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__CH0_MDIV_WIDTH 8 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__CH0_MDIV_RESETVALUE 0x08 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_RESETVALUE 0x8 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5 0x1803fc14 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_BASE 0xc14 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__RESERVED_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__RESERVED_R 17 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__RESERVED_WIDTH 15 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__RESERVED_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_SW_OVWR 16 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_SW_OVWR_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_SW_OVWR_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_OUT1_EN 15 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_OUT1_EN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_OUT1_EN_RESETVALUE 0x1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_OUT0_EN 14 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_OUT0_EN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_OUT0_EN_RESETVALUE 0x1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_IN_SEL 13 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_IN_SEL_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_IN_SEL_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_POST_RESETB 12 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_POST_RESETB_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_POST_RESETB_RESETVALUE 0x1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_RESETB 11 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_RESETB_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_RESETB_RESETVALUE 0x1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDEL_L 10 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDEL_R 8 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDEL_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDEL_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDIV_L 7 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDIV_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDIV_WIDTH 8 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDIV_RESETVALUE 0x64 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_RESETVALUE 0xd864 ++#define IPROC_DDR_PLL_STATUS 0x1803fc18 ++#define IPROC_DDR_PLL_STATUS_BASE 0xc18 ++#define IPROC_DDR_PLL_STATUS__RESERVED_L 31 ++#define IPROC_DDR_PLL_STATUS__RESERVED_R 14 ++#define IPROC_DDR_PLL_STATUS__RESERVED_WIDTH 18 ++#define IPROC_DDR_PLL_STATUS__RESERVED_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_LOCK_LOST 13 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_LOCK_LOST_WIDTH 1 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_LOCK_LOST_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_LOCK 12 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_LOCK_WIDTH 1 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_LOCK_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_STAT_OUT_L 11 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_STAT_OUT_R 0 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_STAT_OUT_WIDTH 12 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_STAT_OUT_RESETVALUE 0x000 ++#define IPROC_DDR_PLL_STATUS_WIDTH 32 ++#define IPROC_DDR_PLL_STATUS__WIDTH 32 ++#define IPROC_DDR_PLL_STATUS_ALL_L 31 ++#define IPROC_DDR_PLL_STATUS_ALL_R 0 ++#define IPROC_DDR_PLL_STATUS__ALL_L 31 ++#define IPROC_DDR_PLL_STATUS__ALL_R 0 ++#define IPROC_DDR_PLL_STATUS_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_STATUS_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_STATUS_RESETVALUE 0x0 ++#endif ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define IPROC_WRAP_USBPHY_CTRL 0x1803fc34 ++#define IPROC_WRAP_GEN_PLL_STATUS__GEN_PLL_LOCK 0 ++#define IPROC_WRAP_GEN_PLL_CTRL1__NDIV_INT_R 0 ++#define IPROC_WRAP_GEN_PLL_CTRL1__NDIV_INT_WIDTH 10 ++#define IPROC_WRAP_GEN_PLL_CTRL1__PDIV_R 10 ++#define IPROC_WRAP_GEN_PLL_CTRL1__PDIV_WIDTH 3 ++#define IPROC_WRAP_GEN_PLL_CTRL1__CH0_MDIV_R 13 ++#define IPROC_WRAP_GEN_PLL_CTRL1__CH1_MDIV_R 21 ++#define IPROC_WRAP_GEN_PLL_CTRL2__CH2_MDIV_R 0 ++#define IPROC_WRAP_GEN_PLL_CTRL2__CH3_MDIV_R 8 ++#define IPROC_WRAP_GEN_PLL_CTRL2__CH4_MDIV_R 16 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0 0x1803fc1c ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_BASE 0xc1c ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH5_MDIV_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH5_MDIV_R 24 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH5_MDIV_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH5_MDIV_RESETVALUE 0x18 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH4_MDIV_L 23 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH4_MDIV_R 16 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH4_MDIV_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH4_MDIV_RESETVALUE 0x0f ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH3_MDIV_L 15 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH3_MDIV_R 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH3_MDIV_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH3_MDIV_RESETVALUE 0x64 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH0_MDIV_L 7 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH0_MDIV_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH0_MDIV_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH0_MDIV_RESETVALUE 0x1e ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_DATAMASK 0xffffffff ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_RDWRMASK 0x00000000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_RESETVALUE 0x180f641e ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1 0x1803fc20 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_BASE 0xc20 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__Reserved_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__Reserved_R 28 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__Reserved_WIDTH 4 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__Reserved_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__SW_OVWR 27 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__SW_OVWR_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__SW_OVWR_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__POST_RESETB 26 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__POST_RESETB_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__POST_RESETB_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__RESETB 25 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__RESETB_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__RESETB_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__PDIV_L 24 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__PDIV_R 22 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__PDIV_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__PDIV_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KP_L 21 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KP_R 18 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KP_WIDTH 4 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KP_RESETVALUE 0x8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KI_L 17 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KI_R 15 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KI_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KI_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KA_L 14 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KA_R 12 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KA_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KA_RESETVALUE 0x4 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__LOAD_EN_CH_L 11 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__LOAD_EN_CH_R 6 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__LOAD_EN_CH_WIDTH 6 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__LOAD_EN_CH_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__HOLD_CH_L 5 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__HOLD_CH_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__HOLD_CH_WIDTH 6 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__HOLD_CH_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_DATAMASK 0xffffffff ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_RDWRMASK 0x00000000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_RESETVALUE 0x660c000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2 0x1803fc24 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_BASE 0xc24 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__RSVD_0_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__RSVD_0_R 28 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__RSVD_0_WIDTH 4 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__RSVD_0_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH2_MDIV_L 27 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH2_MDIV_R 20 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH2_MDIV_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH2_MDIV_RESETVALUE 0x00 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH5_MDEL_L 19 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH5_MDEL_R 17 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH5_MDEL_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH5_MDEL_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH4_MDEL_L 16 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH4_MDEL_R 14 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH4_MDEL_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH4_MDEL_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH3_MDEL_L 13 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH3_MDEL_R 11 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH3_MDEL_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH3_MDEL_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH0_MDEL_L 10 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH0_MDEL_R 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH0_MDEL_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH0_MDEL_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH1_MDIV_L 7 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH1_MDIV_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH1_MDIV_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH1_MDIV_RESETVALUE 0x0f ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_DATAMASK 0xffffffff ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_RDWRMASK 0x00000000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_RESETVALUE 0xf ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3 0x1803fc28 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_BASE 0xc28 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__RSVD_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__RSVD_R 30 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__RSVD_WIDTH 2 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__RSVD_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__TESTOUT2_EN 29 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__TESTOUT2_EN_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__TESTOUT2_EN_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_2ED_OUT_EN 28 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_2ED_OUT_EN_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_2ED_OUT_EN_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DIG_LDO_CTRL_L 27 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DIG_LDO_CTRL_R 26 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DIG_LDO_CTRL_WIDTH 2 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DIG_LDO_CTRL_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__ANA_LDO_CTRL_L 25 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__ANA_LDO_CTRL_R 24 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__ANA_LDO_CTRL_WIDTH 2 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__ANA_LDO_CTRL_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__TESTOUT_EN 23 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__TESTOUT_EN_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__TESTOUT_EN_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_OUTPUT_EN 22 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_OUTPUT_EN_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_OUTPUT_EN_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_BYP_EN 21 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_BYP_EN_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_BYP_EN_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__VCOdiv2 20 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__VCOdiv2_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__VCOdiv2_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__AUX_CTRL 19 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__AUX_CTRL_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__AUX_CTRL_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__REFCLKOUT 18 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__REFCLKOUT_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__REFCLKOUT_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_UPDATE 17 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_UPDATE_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_UPDATE_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_SELECT_L 16 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_SELECT_R 14 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_SELECT_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_SELECT_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_RESET 13 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_RESET_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_RESET_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_ENABLE 12 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_ENABLE_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_ENABLE_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_L 11 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_WIDTH 12 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_RESETVALUE 0x000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_DATAMASK 0xffffffff ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_RDWRMASK 0x00000000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_RESETVALUE 0x15400000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4 0x1803fc2c ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_BASE 0xc2c ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__RSVD_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__RSVD_R 28 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__RSVD_WIDTH 4 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__RSVD_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_FRAC_L 27 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_FRAC_R 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_FRAC_WIDTH 20 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_FRAC_RESETVALUE 0x00000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_L 7 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_RESETVALUE 0x78 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_DATAMASK 0xffffffff ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_RDWRMASK 0x00000000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_RESETVALUE 0x78 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS 0x1803fc30 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_BASE 0xc30 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__IPROC_WRAP_XGPLL_LOCK 31 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__IPROC_WRAP_XGPLL_LOCK_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__IPROC_WRAP_XGPLL_LOCK_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__XGPLL_STATUS_L 30 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__XGPLL_STATUS_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__XGPLL_STATUS_WIDTH 31 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__XGPLL_STATUS_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_DATAMASK 0xffffffff ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_RDWRMASK 0x00000000 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_RESETVALUE 0x0 ++#if defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL 3 ++#define IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL 2 ++#define IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL 4 ++#endif ++#define IPROC_WRAP_MISC_CONTROL 0x1803fc3c ++#endif ++ ++#endif /* __SOCREGS_ING_OPEN_H */ +diff --git a/arch/arm/mach-iproc/include/mach/socregs_ns_open.h b/arch/arm/mach-iproc/include/mach/socregs_ns_open.h +new file mode 100644 +index 0000000..8f3d2eb +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/socregs_ns_open.h +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __SOCREGS_NS_OPEN_H ++#define __SOCREGS_NS_OPEN_H ++ ++ ++#define CCA_CHIPID 0x18000000 ++#define CCA_CHIPID_BASE 0x000 ++#define CCB_GP_DATA_IN 0x18001000 ++#define USB30_BASE 0x18023000 ++#define SDIO_EMMC_SDXC_SYSADDR 0x18020000 ++#define CCB_PWM_CTL 0x18002000 ++#define CCB_TIM0_TIM_TMR1_LOAD 0x18005000 ++#define CCB_TIM1_TIM_TMR1_LOAD 0x18006000 ++#define CCB_SMBUS_START 0x18009000 ++#define CCB_GP_AUX_SEL_BASE 0x028 ++#define QSPI_MSPI_SPCR0_LSB 0x18029200 ++#define QSPI_MSPI_DISABLE_FLUSH_GEN 0x18029384 ++#define QSPI_BSPI_REGS_REV_ID 0x18029000 ++#define QSPI_BSPI_REGS_BSPI_PIO_DATA 0x1802904c ++#define QSPI_RAF_START_ADDR 0x18029100 ++#define QSPI_RAF_CURR_ADDR 0x18029120 ++#define QSPI_RAF_INTERRUPT_LR_FULLNESS_REACHED 0x180293a0 ++#define QSPI_MSPI_INTERRUPT_MSPI_HALT_SET_TRANSACTION_DONE 0x180293b8 ++#define GMAC0_DEVCTL 0x18024000 ++#define GMAC1_DEVCTL 0x18025000 ++#define GMAC2_DEVCTL 0x18026000 ++#define GMAC3_DEVCTL 0x18027000 ++#define CCA_GPIO_EVT_BASE 0x078 ++#define CCA_GPIO_INPUT 0x18000060 ++#define CCA_GPIO_INPUT_BASE 0x060 ++#define CCB_GP_INT_CLR_BASE 0x024 ++#define CCA_GPIO_EVTINT_MASK_BASE 0x07c ++#define CCB_GP_INT_MSK_BASE 0x018 ++#define CCA_GPIOINT_MASK_BASE 0x074 ++#define CCA_GPIO_EVT_INT_POLARITY_BASE 0x084 ++#define CCA_GPIO_INT_POLARITY_BASE 0x070 ++#define CCA_INT_MASK_BASE 0x024 ++#define CCB_GP_INT_TYPE_BASE 0x00c ++#define CCB_GP_INT_DE_BASE 0x010 ++#define CCB_GP_INT_EDGE_BASE 0x014 ++#define CCA_INT_STS_BASE 0x020 ++#define CCB_GP_INT_MSTAT_BASE 0x020 ++#define CCB_GP_PAD_RES_BASE 0x034 ++#define CCB_GP_RES_EN_BASE 0x038 ++#define CCB_MII_MGMT_CTL 0x18003000 ++#define CCB_MII_MGMT_DATA 0x18003004 ++#define NAND_NAND_FLASH_REV 0x18028000 ++#define ChipcommonB_MII_Management_Control CCB_MII_MGMT_CTL ++#define ChipcommonB_MII_Management_Command_Data CCB_MII_MGMT_DATA ++#define NAND_DIRECT_READ_RD_MISS 0x18028f00 ++#define CCB_PWM_PRESCALE_BASE 0x024 ++#define CCB_PWM_PERIOD_COUNT0_BASE 0x004 ++#define CCB_PWM_PERIOD_COUNT1_BASE 0x00c ++#define CCB_PWM_DUTY_HI_COUNT2_BASE 0x018 ++#define CCB_PWM_PERIOD_COUNT3_BASE 0x01c ++#define CCB_PWM_DUTY_HI_COUNT0_BASE 0x008 ++#define CCB_PWM_DUTY_HI_COUNT1_BASE 0x010 ++#define CCB_PWM_DUTY_HI_COUNT2_BASE 0x018 ++#define CCB_PWM_DUTY_HI_COUNT3_BASE 0x020 ++#define CCB_PWM_CTL_BASE 0x000 ++#define CCB_PWM_PERIOD_COUNT2_BASE 0x014 ++#define CCB_RNG_CTRL 0x18004000 ++ ++ ++#endif /* __SOCREGS_NS_OPEN_H */ +diff --git a/arch/arm/mach-iproc/include/mach/socregs_nsp_open.h b/arch/arm/mach-iproc/include/mach/socregs_nsp_open.h +new file mode 100644 +index 0000000..e98c003 +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/socregs_nsp_open.h +@@ -0,0 +1,398 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __SOCREGS_NSP_OPEN_H ++#define __SOCREGS_NSP_OPEN_H ++ ++#define ChipcommonA_ChipID 0x18000000 ++#define PCU_MDIO_MGT 0x1803f000 ++#define ChipcommonB_PWMCTL 0x18031000 ++#define ChipcommonB_WDT_WDOGLOAD 0x18039000 ++#define USB3_CAPLENGTH 0x18029000 ++#define USB30_BASE USB3_CAPLENGTH ++#define SATA_AHCI_GHC_HBA_CAP 0x18041000 ++#define SATA_M0_IDM_IO_CONTROL_DIRECT 0x1811e408 ++#define SATA_M0_IDM_IDM_RESET_CONTROL 0x1811e800 ++#define SATA3_PCB_UPPER_REG1 0x18040304 ++#define SATA3_PCB_UPPER_REG0 0x18040300 ++#define SATA3_PCB_UPPER_REG1 0x18040304 ++#define SATA3_PCB_UPPER_REG11 0x1804032c ++#define SATA3_PCB_UPPER_REG5 0x18040314 ++#define SATA3_PCB_UPPER_REG15 0x1804033c ++#define SATA_TOP_CTRL_BUS_CTRL 0x18040024 ++#define ChipcommonB_GP_DATA_IN 0x18030000 ++#define ChipcommonB_GP_AUX_SEL_BASE 0x028 ++#define ChipcommonB_SMBus_Config 0x18038000 ++#define ChipcommonB_tim0_TIM_TIMER1Load 0x18034000 ++#define ChipcommonB_tim1_TIM_TIMER1Load 0x18035000 ++#define QSPI_mspi_SPCR0_LSB 0x18027200 ++#define QSPI_mspi_DISABLE_FLUSH_GEN 0x18027384 ++#define QSPI_bspi_registers_REVISION_ID 0x18027000 ++#define QSPI_bspi_registers_BSPI_PIO_DATA 0x1802704c ++#define QSPI_raf_START_ADDR 0x18027100 ++#define QSPI_raf_interrupt_LR_fullness_reached 0x180273a0 ++#define QSPI_mspi_interrupt_MSPI_halt_set_transaction_done 0x180273b8 ++#define QSPI_IDM_IDM_IO_CONTROL_DIRECT 0x1811c408 ++#define QSPI_raf_CURR_ADDR 0x18027120 ++#define CRU_control 0x1803e000 ++#define GMAC0_DEVCONTROL 0x18022000 ++#define GMAC1_DEVCONTROL 0x18023000 ++#define FA_GMAC0_DEVCONTROL 0x18024000 ++#define FA_GMAC1_DEVCONTROL 0x18025000 ++#define CRU_CLKSET_KEY_OFFSET 0x1803f180 ++#define CRU_LCPLL2_CONTROL0 0x1803f548 ++#define CRU_LCPLL2_CONTROL0__PWRDWN 12 ++#define CRU_LCPLL2_CONTROL0__RESETB 11 ++#define CRU_LCPLL2_STATUS__LOCK 12 ++#define CRU_LCPLL2_CONTROL0__PWRDWN 12 ++#define CRU_LCPLL2_CONTROL0__RESETB 11 ++#define CRU_RESET__SGMII_RESET_N 8 ++#define CRU_RESET 0x1803f184 ++#define SGMII_CONFIG 0x1803f410 ++#define SGMII_CONFIG__RSTB_PLL 17 ++#define SGMII_CONFIG__RSTB_MDIOREGS 16 ++#define SGMII_CONFIG__TXD1G_FIFO_RSTB_WIDTH 4 ++#define SGMII_CONFIG__TXD1G_FIFO_RSTB_R 11 ++#define P5_MUX_CONFIG__P5_MODE_WIDTH 3 ++#define CRU_LCPLL2_CONTROL0__POST_RESETB 10 ++#define P5_MUX_CONFIG 0x1803f308 ++#define P5_MUX_CONFIG__P5_MODE_R 0 ++#define P5_MUX_CONFIG__P5_MODE_SGMII 0x0 ++#define P5_MUX_CONFIG__P5_MODE_GPHY3 0x4 ++#define P4_MUX_CONFIG 0x1803f30c ++#define P4_MUX_CONFIG__P4_MODE_R 0 ++#define P4_MUX_CONFIG__P4_MODE_WIDTH 3 ++#define P4_MUX_CONFIG__P4_MODE_SGMII 0x0 ++#define ChipcommonA_GPIOEvent_BASE 0x078 ++#define ChipcommonA_GPIOInput_BASE 0x060 ++#define ChipcommonB_GP_INT_CLR_BASE 0x024 ++#define ChipcommonA_GPIOEventIntMask_BASE 0x07c ++#define ChipcommonA_GPIOInput_BASE 0x060 ++#define ChipcommonB_GP_INT_MSK_BASE 0x018 ++#define ChipcommonA_GPIOIntMask_BASE 0x074 ++#define ChipcommonB_GP_INT_MSK_BASE 0x018 ++#define ChipcommonA_GPIOEventIntMask_BASE 0x07c ++#define ChipcommonB_GP_INT_MSTAT_BASE 0x020 ++#define ChipcommonA_GPIOEventIntPolarity_BASE 0x084 ++#define ChipcommonA_IntStatus_BASE 0x020 ++#define ChipcommonA_GPIOIntPolarity_BASE 0x070 ++#define ChipcommonA_IntStatus_BASE 0x020 ++#define ChipcommonB_GP_INT_DE_BASE 0x010 ++#define ChipcommonB_GP_INT_EDGE_BASE 0x014 ++#define ChipcommonB_GP_INT_TYPE_BASE 0x00c ++#define ChipcommonA_GPIOIntPolarity_BASE 0x070 ++#define CRU_GPIO_CONTROL0_BASE 0x1f1c0 ++#define ChipcommonB_GP_AUX_SEL_BASE 0x028 ++#define CRU_GPIO_CONTROL7_BASE 0x1f1dc ++#define CRU_GPIO_CONTROL8_BASE 0x1f1e0 ++#define ChipcommonB_GP_PAD_RES_BASE 0x034 ++#define ChipcommonB_GP_RES_EN_BASE 0x038 ++#define ChipcommonA_ChipID 0x18000000 ++#define DMAC_pl330_DS 0x18020000 ++#define ChipcommonA_GPIOInput 0x18000060 ++#define ChipcommonB_GP_DATA_IN 0x18030000 ++#define PAXB_0_CLK_CONTROL 0x18012000 ++#define PAXB_0_CONFIG_IND_ADDR_BASE 0x120 ++#define ChipcommonB_MII_Management_Control 0x18032000 ++#define ChipcommonB_MII_Management_Command_Data 0x18032004 ++#define NAND_nand_flash_REVISION 0x18026000 ++#define NAND_direct_read_rd_miss 0x18026f00 ++#define NAND_IDM_IDM_IO_CONTROL_DIRECT 0x1811b408 ++#define ChipcommonB_PWM_PERIOD_COUNT0_BASE 0x004 ++#define ChipcommonB_PWM_PRESCALE_BASE 0x024 ++#define ChipcommonB_PWM_PERIOD_COUNT1_BASE 0x00c ++#define ChipcommonB_PWM_PERIOD_COUNT2_BASE 0x014 ++#define ChipcommonB_PWM_PERIOD_COUNT3_BASE 0x01c ++#define ChipcommonB_PWM_DUTYHI_COUNT0_BASE 0x008 ++#define ChipcommonB_PWM_DUTYHI_COUNT1_BASE 0x010 ++#define ChipcommonB_PWM_DUTYHI_COUNT2_BASE 0x018 ++#define ChipcommonB_PWM_DUTYHI_COUNT3_BASE 0x020 ++#define ChipcommonB_PWMCTL_BASE 0x000 ++#define ChipcommonB_rng_CTRL 0x18033000 ++#define USB2_IDM_IDM_IO_CONTROL_DIRECT 0x18115408 ++#define USB3_IDM_IDM_RESET_CONTROL 0x18104800 ++#define CRU_WATCHDOG_PCIE_RESET_STATUS 0x1803f564 ++#define CRU_WATCHDOG_PCIE_RESET_STATUS__CCB_WATCHDOG_RESET_EVENT 0 ++#define SDIO_eMMCSDXC_SYSADDR 0x18021000 ++#define IHOST_M0_IO_CONTROL_DIRECT 0x18100408 ++#define ChipcommonA_IntMask_BASE 0x024 ++#define ChipcommonA_OTPProg 0x18000018 ++#define ChipcommonA_OTPLayout 0x1800001c ++#define ChipcommonA_CoreCapabilities 0x18000004 ++#define ChipcommonA_OTPStatus 0x18000010 ++#define SDIO_IDM_IO_CONTROL_DIRECT 0x18117408 ++#define SDIO_IDM_IO_CONTROL_DIRECT__CMD_COMFLICT_DISABLE 22 ++ ++ ++/* IDM registers */ ++ ++#define IHOST_S1_IDM_ERROR_LOG_CONTROL 0x18107900 ++#define IHOST_S1_IDM_ERROR_LOG_COMPLETE 0x18107904 ++#define IHOST_S1_IDM_ERROR_LOG_STATUS 0x18107908 ++#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810790c ++#define IHOST_S1_IDM_ERROR_LOG_ID 0x18107914 ++#define IHOST_S1_IDM_ERROR_LOG_FLAGS 0x1810791c ++#define IHOST_S1_IDM_INTERRUPT_STATUS 0x18107a00 ++#define IHOST_S0_IDM_ERROR_LOG_CONTROL 0x18108900 ++#define IHOST_S0_IDM_ERROR_LOG_COMPLETE 0x18108904 ++#define IHOST_S0_IDM_ERROR_LOG_STATUS 0x18108908 ++#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810890c ++#define IHOST_S0_IDM_ERROR_LOG_ID 0x18108914 ++#define IHOST_S0_IDM_ERROR_LOG_FLAGS 0x1810891c ++#define IHOST_S0_IDM_INTERRUPT_STATUS 0x18108a00 ++#define DDR_S1_IDM_ERROR_LOG_CONTROL 0x18109900 ++#define DDR_S1_IDM_ERROR_LOG_COMPLETE 0x18109904 ++#define DDR_S1_IDM_ERROR_LOG_STATUS 0x18109908 ++#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810990c ++#define DDR_S1_IDM_ERROR_LOG_ID 0x18109914 ++#define DDR_S1_IDM_ERROR_LOG_FLAGS 0x1810991c ++#define DDR_S1_IDM_INTERRUPT_STATUS 0x18109a00 ++#define DDR_S2_IDM_ERROR_LOG_CONTROL 0x1810a900 ++#define DDR_S2_IDM_ERROR_LOG_COMPLETE 0x1810a904 ++#define DDR_S2_IDM_ERROR_LOG_STATUS 0x1810a908 ++#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB 0x1810a90c ++#define DDR_S2_IDM_ERROR_LOG_ID 0x1810a914 ++#define DDR_S2_IDM_ERROR_LOG_FLAGS 0x1810a91c ++#define DDR_S2_IDM_INTERRUPT_STATUS 0x1810aa00 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810b900 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810b904 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810b908 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810b90c ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID 0x1810b914 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810b91c ++#define AXI_PCIE_S0_IDM_IDM_INTERRUPT_STATUS 0x1810ba00 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_CONTROL 0x1810c900 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_COMPLETE 0x1810c904 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_STATUS 0x1810c908 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810c90c ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ID 0x1810c914 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_FLAGS 0x1810c91c ++#define AXI_PCIE_S1_IDM_IDM_INTERRUPT_STATUS 0x1810ca00 ++#define AXI_PCIE_S2_IDM_IDM_ERROR_LOG_CONTROL 0x1810d900 ++#define AXI_PCIE_S2_IDM_IDM_ERROR_LOG_COMPLETE 0x1810d904 ++#define AXI_PCIE_S2_IDM_IDM_ERROR_LOG_STATUS 0x1810d908 ++#define AXI_PCIE_S2_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810d90c ++#define AXI_PCIE_S2_IDM_IDM_ERROR_LOG_ID 0x1810d914 ++#define AXI_PCIE_S2_IDM_IDM_ERROR_LOG_FLAGS 0x1810d91c ++#define AXI_PCIE_S2_IDM_IDM_INTERRUPT_STATUS 0x1810da00 ++#define APBY_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810f900 ++#define APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810f904 ++#define APBY_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810f908 ++#define APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810f90c ++#define APBY_S0_IDM_IDM_ERROR_LOG_ID 0x1810f914 ++#define APBY_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810f91c ++#define APBY_S0_IDM_IDM_INTERRUPT_STATUS 0x1810fa00 ++#define ROM_S0_IDM_ERROR_LOG_CONTROL 0x1811a900 ++#define ROM_S0_IDM_ERROR_LOG_COMPLETE 0x1811a904 ++#define ROM_S0_IDM_ERROR_LOG_STATUS 0x1811a908 ++#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1811a90c ++#define ROM_S0_IDM_ERROR_LOG_ID 0x1811a914 ++#define ROM_S0_IDM_ERROR_LOG_FLAGS 0x1811a91c ++#define ROM_S0_IDM_INTERRUPT_STATUS 0x1811aa00 ++#define NAND_IDM_IDM_ERROR_LOG_CONTROL 0x1811b900 ++#define NAND_IDM_IDM_ERROR_LOG_COMPLETE 0x1811b904 ++#define NAND_IDM_IDM_ERROR_LOG_STATUS 0x1811b908 ++#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811b90c ++#define NAND_IDM_IDM_ERROR_LOG_ID 0x1811b914 ++#define NAND_IDM_IDM_ERROR_LOG_FLAGS 0x1811b91c ++#define NAND_IDM_IDM_INTERRUPT_STATUS 0x1811ba00 ++#define QSPI_IDM_IDM_ERROR_LOG_CONTROL 0x1811c900 ++#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE 0x1811c904 ++#define QSPI_IDM_IDM_ERROR_LOG_STATUS 0x1811c908 ++#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811c90c ++#define QSPI_IDM_IDM_ERROR_LOG_ID 0x1811c914 ++#define QSPI_IDM_IDM_ERROR_LOG_FLAGS 0x1811c91c ++#define QSPI_IDM_IDM_INTERRUPT_STATUS 0x1811ca00 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1811d900 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1811d904 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS 0x1811d908 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811d90c ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID 0x1811d914 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1811d91c ++#define A9JTAG_S0_IDM_IDM_INTERRUPT_STATUS 0x1811da00 ++#define SRAM_S0_IDM_ERROR_LOG_CONTROL 0x18120900 ++#define SRAM_S0_IDM_ERROR_LOG_COMPLETE 0x18120904 ++#define SRAM_S0_IDM_ERROR_LOG_STATUS 0x18120908 ++#define SRAM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1812090c ++#define SRAM_S0_IDM_ERROR_LOG_ID 0x18120914 ++#define SRAM_S0_IDM_ERROR_LOG_FLAGS 0x1812091c ++#define SRAM_S0_IDM_INTERRUPT_STATUS 0x18120a00 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18121900 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18121904 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_STATUS 0x18121908 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1812190c ++#define APBZ_S0_IDM_IDM_ERROR_LOG_ID 0x18121914 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1812191c ++#define APBZ_S0_IDM_IDM_INTERRUPT_STATUS 0x18121a00 ++#define APBV_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18122900 ++#define APBV_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18122904 ++#define APBV_S0_IDM_IDM_ERROR_LOG_STATUS 0x18122908 ++#define APBV_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1812290c ++#define APBV_S0_IDM_IDM_ERROR_LOG_ID 0x18122914 ++#define APBV_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1812291c ++#define APBV_S0_IDM_IDM_INTERRUPT_STATUS 0x18122a00 ++#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL 0x18123900 ++#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE 0x18123904 ++#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS 0x18123908 ++#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB 0x1812390c ++#define AXIIC_DS_3_IDM_ERROR_LOG_ID 0x18123914 ++#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS 0x1812391c ++#define AXIIC_DS_3_IDM_INTERRUPT_STATUS 0x18123a00 ++#define AXIIC_DS_4_IDM_ERROR_LOG_CONTROL 0x18124900 ++#define AXIIC_DS_4_IDM_ERROR_LOG_COMPLETE 0x18124904 ++#define AXIIC_DS_4_IDM_ERROR_LOG_STATUS 0x18124908 ++#define AXIIC_DS_4_IDM_ERROR_LOG_ADDR_LSB 0x1812490c ++#define AXIIC_DS_4_IDM_ERROR_LOG_ID 0x18124914 ++#define AXIIC_DS_4_IDM_ERROR_LOG_FLAGS 0x1812491c ++#define AXIIC_DS_4_IDM_INTERRUPT_STATUS 0x18124a00 ++#define APBW_IDM_IDM_ERROR_LOG_CONTROL 0x18131900 ++#define APBW_IDM_IDM_ERROR_LOG_COMPLETE 0x18131904 ++#define APBW_IDM_IDM_ERROR_LOG_STATUS 0x18131908 ++#define APBW_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813190c ++#define APBW_IDM_IDM_ERROR_LOG_ID 0x18131914 ++#define APBW_IDM_IDM_ERROR_LOG_FLAGS 0x1813191c ++#define APBW_IDM_IDM_INTERRUPT_STATUS 0x18131a00 ++#define APBX_IDM_IDM_ERROR_LOG_CONTROL 0x18132900 ++#define APBX_IDM_IDM_ERROR_LOG_COMPLETE 0x18132904 ++#define APBX_IDM_IDM_ERROR_LOG_STATUS 0x18132908 ++#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813290c ++#define APBX_IDM_IDM_ERROR_LOG_ID 0x18132914 ++#define APBX_IDM_IDM_ERROR_LOG_FLAGS 0x1813291c ++#define APBX_IDM_IDM_INTERRUPT_STATUS 0x18132a00 ++#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL 0x18141900 ++#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE 0x18141904 ++#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS 0x18141908 ++#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB 0x1814190c ++#define AXIIC_DS_0_IDM_ERROR_LOG_ID 0x18141914 ++#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS 0x1814191c ++#define AXIIC_DS_0_IDM_INTERRUPT_STATUS 0x18141a00 ++#define AXIIC_DS_1_IDM_ERROR_LOG_CONTROL 0x18142900 ++#define AXIIC_DS_1_IDM_ERROR_LOG_COMPLETE 0x18142904 ++#define AXIIC_DS_1_IDM_ERROR_LOG_STATUS 0x18142908 ++#define AXIIC_DS_1_IDM_ERROR_LOG_ADDR_LSB 0x1814290c ++#define AXIIC_DS_1_IDM_ERROR_LOG_ID 0x18142914 ++#define AXIIC_DS_1_IDM_ERROR_LOG_FLAGS 0x1814291c ++#define AXIIC_DS_1_IDM_INTERRUPT_STATUS 0x18142a00 ++#define CTF_CONTROL_REG 0x18025c00 ++#define CTF_CONTROL_BASE 0x5c00 ++#define CTF_FLOW_TIMER_CONFIG0__TCP_FINISHED_TIMEBASE_TWO_EXP37 0x0 ++#define CTF_FLOW_TIMER_CONFIG0__TCP_FINISHED_TIMEBASE_TWO_EXP31 0x1 ++#define CTF_FLOW_TIMER_CONFIG0__TCP_FINISHED_TIMEBASE_TWO_EXP26 0x2 ++#define CTF_FLOW_TIMER_CONFIG0__TCP_ESTABLISHED_TIMEBASE_R 2 ++#define CTF_FLOW_TIMER_CONFIG0__TCP_FINISHED_TIMEBASE_R 0 ++#define CTF_FLOW_TIMER_CONFIG1__TCP_ESTABLISHED_TIMEOUT_R 8 ++#define CTF_FLOW_TIMER_CONFIG1__UDP_ESTABLISHED_TIMEOUT_R 16 ++#define CTF_FLOW_TIMER_CONFIG1__TCP_FINISHED_TIMEOUT_R 0 ++#define CTF_FLOW_TIMER_CONFIG0__UDP_ESTABLISHED_TIMEBASE_R 4 ++#define CTF_FLOW_TIMER_CONFIG0__UDP_ESTABLISHED_TIMEBASE_R 4 ++#define CTF_FLOW_TIMER_CONFIG0__UDP_ESTABLISHED_TIMEBASE_TWO_EXP31 0x1 ++#define CTF_FLOW_TIMER_CONFIG0__TCP_ESTABLISHED_TIMEBASE_TWO_EXP31 0x1 ++#define CTF_FLOW_TIMEOUT_CONTROL__FLOW_ENTRY_POINTER_R 5 ++ ++#define CTF_DRR_CONFIG__MAC_WEIGHT_R 7 ++#define CTF_MEM_ACC_CONTROL__RD_WR_N 15 ++#define CTF_MEM_ACC_CONTROL__TABLE_SELECT_R 12 ++#define CTF_MEM_ACC_CONTROL__ALL_R 0 ++ ++#define PAE_M0_IDM_IDM_RESET_CONTROL 0x1811f800 ++#define PAE_S0_IDM_IDM_RESET_CONTROL 0x18125800 ++#define CTF_CONTROL__MEM_INIT 1 ++#define AMAC_IDM0_IO_CONTROL_DIRECT 0x18110408 ++#define AMAC_IDM0_IO_CONTROL_DIRECT__CLK_250_SEL 6 ++#define AMAC_IDM1_IO_CONTROL_DIRECT 0x18111408 ++#define AMAC_IDM1_IO_CONTROL_DIRECT__CLK_250_SEL 6 ++#define CTF_CONTROL__CTF_MODE 0 ++#define CTF_CONTROL__FRAGMENTATION_ENABLE 2 ++#define CTF_CONTROL__DISABLE_MAC_DA_CHECK 3 ++#define CTF_CONTROL__PAE_ENABLED 5 ++#define CTF_CONTROL__SPU_ENABLE 6 ++#define CTF_BRCM_HDR_CONTROL 0x18025c08 ++#define CTF_BRCM_HDR_CONTROL__BRCM_HDR_REASON_CODE_MASK_WIDTH 8 ++#define CTF_BRCM_HDR_CONTROL__BRCM_HDR_REASON_CODE_MASK_R 0 ++#define SPU_CONTROL 0x1802f000 ++#define SPU_CONTROL__OUT_ENDIAN 12 ++#define SPU_CONTROL__IN_ENDIAN 11 ++#define SPU_CONTROL__SOFT_RST 1 ++#define R5_CONFIG0 0x180490d8 ++#define R5_CONFIG0__TE_INIT 31 ++#define R5_CONFIG0__SYS_PORESET 30 ++#define R5_CONFIG0__RESET_N 29 ++#define R5_CONFIG0__PARITY_ODD 28 ++#define R5_CONFIG0__PADDR_DEBUG31 27 ++#define R5_CONFIG0__LOC_ZERO_RAMA 26 ++#define R5_CONFIG0__INTERRUPT_ASYNC 25 ++#define R5_CONFIG0__INITRAMB 24 ++#define R5_CONFIG0__INITRAMA 23 ++#define R5_CONFIG0__DEBUG_RESTART 22 ++#define R5_CONFIG0__DEBUG_RESET_N 21 ++#define R5_CONFIG0__DEBUG_RESET 20 ++#define R5_CONFIG0__DEBUG_RESET 20 ++#define R5_CONFIG0__DEBUG_NO_CLK_STOP 19 ++#define R5_CONFIG0__DEBUG_NIDEN 18 ++#define R5_CONFIG0__DEBUG_ENTCM1IF 17 ++#define R5_CONFIG0__DEBUG_EN 16 ++#define R5_CONFIG0__DEBUG_EDBGRQ 15 ++#define R5_CONFIG0__DAP_DAP_TO_DEBUG_APB_EN 14 ++#define R5_CONFIG0__CPU_HALT 13 ++#define R5_CONFIG0__CFG_ENDIAN 12 ++#define R5_CONFIG0__CFG_EE 11 ++#define R5_CONFIG0__BTCM_SPLIT 10 ++#define R5_CONFIG0__BTCM_SIZE_R 6 ++#define R5_CONFIG0__BTCM_SIZE_WIDTH 4 ++#define R5_CONFIG0__ATCM_SIZE_R 2 ++#define R5_CONFIG0__ATCM_SIZE_WIDTH 4 ++#define R5_CONFIG0__RMW_RAM_R 0 ++#define R5_CONFIG0__RMW_RAM_WIDTH 2 ++ ++#define PAE_ECC_DEBUG 0x180490cc ++#define PAE_ECC_DEBUG__ECC_DISABLE 10 ++#define PAE_BUFFER_CONFIG 0x18049010 ++#define PAE_BUFFER_CONFIG__PAE_MEM_INIT 1 ++#define PAE_BUFFER_CONFIG__PAE_SYS_INIT 0 ++#define PAE_BUFFER_CONFIG__PAE_MEM_INIT_DONE 2 ++#define PAE_BUFFER_ALLOCATION0 0x18049018 ++#define PAE_BUFFER_ALLOCATION0 0x18049018 ++#define PAE_BUFFER_ALLOCATION__INTERCEPT_PT_END_ADDR_R 16 ++#define PAE_BUFFER_ALLOCATION__INTERCEPT_PT_END_ADDR_WIDTH 12 ++#define PAE_BUFFER_ALLOCATION__INTERCEPT_PT_START_ADDR_R 0 ++#define PAE_BUFFER_ALLOCATION__INTERCEPT_PT_START_ADDR_WIDTH 12 ++ ++#define PAE_BUFFER_ALLOCATION1 0x1804901c ++#define PAE_BUFFER_BACKPRESSURE_CONFIG0 0x18049020 ++#define PAE_BUFFER_BACKPRESSURE_CONFIG__WATERMARK_DEPTH_XOFF_R 16 ++#define PAE_BUFFER_BACKPRESSURE_CONFIG__WATERMARK_DEPTH_XOFF_WIDTH 12 ++#define PAE_BUFFER_BACKPRESSURE_CONFIG__WATERMARK_DEPTH_XON_R 0 ++#define PAE_BUFFER_BACKPRESSURE_CONFIG__WATERMARK_DEPTH_XON_WIDTH 12 ++#define PAE_BUFFER_BACKPRESSURE_CONFIG1 0x18049024 ++#define PAE_BUFFER_CONGESTION_CONFIG 0x18049028 ++#define PAE_BUFFER_CONGESTION_CONFIG__ENQ0_STOP_LEVEL_R 0 ++#define PAE_BUFFER_CONGESTION_CONFIG__ENQ0_STOP_LEVEL_WIDTH 12 ++#define PAE_BUFFER_BACKPRESSURE_MAP0 0x1804902c ++#define PAE_BUFFER_BACKPRESSURE_MAP__INTERCEPT_PT_BACKPRESSURE_CONTRIBUTOR_MASK_R 0 ++#define PAE_BUFFER_BACKPRESSURE_MAP__INTERCEPT_PT_BACKPRESSURE_CONTRIBUTOR_MASK_WIDTH 2 ++#define PAE_BUFFER_BACKPRESSURE_MAP1 0x18049030 ++#define PAE_SCRATCHPAD_ALLOCATION 0x18049014 ++#define PAE_SCRATCHPAD_ALLOCATION__SCRATCHPAD_END_ADDR_R 16 ++#define PAE_SCRATCHPAD_ALLOCATION__SCRATCHPAD_END_ADDR_WIDTH 12 ++#define PAE_SCRATCHPAD_ALLOCATION__SCRATCHPAD_START_ADDR_R 0 ++#define PAE_SCRATCHPAD_ALLOCATION__SCRATCHPAD_START_ADDR_WIDTH 12 ++#define CTF_DEBUG_CONTROL 0x18025ca0 ++#define CTF_DEBUG_CONTROL__DM_FIFO_BP_LEVEL_R 10 ++#define CTF_DEBUG_CONTROL__DM_FIFO_BP_LEVEL_WIDTH 8 ++#define AXIIC_sata_m0_fn_mod 0x1a051108 ++ ++#endif /* __SOCREGS_NSP_OPEN_H */ +diff --git a/arch/arm/mach-iproc/include/mach/socregs_p7_open.h b/arch/arm/mach-iproc/include/mach/socregs_p7_open.h +new file mode 100644 +index 0000000..4ffeeba +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/socregs_p7_open.h +@@ -0,0 +1,261 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __SOCREGS_P7_OPEN_H ++#define __SOCREGS_P7_OPEN_H ++ ++#ifdef CONFIG_MACH_GH ++/* ++ * Greyhound only registers ++ */ ++#define DMU_PCU_IPROC_CONTROL 0x1800f000 ++#define DMU_CRU_RESET_BASE 0x200 ++ ++#define DMU_PCU_IPROC_STRAPS_CAPTURED_BASE 0x028 ++#define DMU_PCU_IPROC_STRAPS_CAPTURED__strap_boot_dev_R 9 ++#define DMU_PCU_IPROC_STRAPS_CAPTURED__strap_nand_type_R 5 ++#define DMU_PCU_IPROC_STRAPS_CAPTURED__strap_nand_page_R 3 ++ ++#define IPROC_WRAP_GEN_PLL_STATUS__GEN_PLL_LOCK 0 ++#define IPROC_WRAP_GEN_PLL_CTRL1__NDIV_INT_R 0 ++#define IPROC_WRAP_GEN_PLL_CTRL1__NDIV_INT_WIDTH 10 ++#define IPROC_WRAP_GEN_PLL_CTRL1__PDIV_R 10 ++#define IPROC_WRAP_GEN_PLL_CTRL1__PDIV_WIDTH 4 ++#define IPROC_WRAP_GEN_PLL_CTRL1__CH0_MDIV_R 14 ++#define IPROC_WRAP_GEN_PLL_CTRL1__CH1_MDIV_R 22 ++#define IPROC_WRAP_GEN_PLL_CTRL2__CH2_MDIV_R 0 ++#define IPROC_WRAP_GEN_PLL_CTRL2__CH3_MDIV_R 8 ++#define IPROC_WRAP_GEN_PLL_CTRL2__CH4_MDIV_R 16 ++ ++#endif /* End of Greyhound only registers */ ++ ++#define ICFG_CHIP_ID_REG 0x18000000 ++#define ChipcommonG_UART0_UART_RBR_THR_DLL 0x18020000 ++#define ChipcommonG_UART1_UART_RBR_THR_DLL 0x18021000 ++ ++#define QSPI_mspi_SPCR0_LSB 0x18047200 ++#define QSPI_mspi_DISABLE_FLUSH_GEN 0x18047384 ++#define QSPI_bspi_registers_REVISION_ID 0x18047000 ++#define QSPI_bspi_registers_BSPI_PIO_DATA 0x1804704c ++#define QSPI_raf_START_ADDR 0x18047100 ++#define QSPI_raf_CURR_ADDR 0x18047120 ++#define QSPI_raf_interrupt_LR_fullness_reached 0x180473a0 ++#define QSPI_mspi_interrupt_MSPI_halt_set_transaction_done 0x180473b8 ++#define QSPI_IDM_IDM_IO_CONTROL_DIRECT 0x1811c408 ++#define CRU_control 0x1800e000 ++ ++#define NAND_nand_flash_REVISION 0x18046000 ++#define NAND_direct_read_rd_miss 0x18046f00 ++#define NAND_IDM_IDM_IO_CONTROL_DIRECT 0xf8105408 ++ ++#define ICFG_IPROC_IOPAD_SW_OVERRIDE_CTRL 0x18000c8c ++#define ICFG_IPROC_IOPAD_SW_OVERRIDE_CTRL__iproc_pnor_sel 1 ++#define ICFG_IPROC_IOPAD_SW_OVERRIDE_CTRL__iproc_pnor_sel_sw_ovwr 0 ++#define ICFG_PNOR_STRAPS 0x18000a5c ++#define ICFG_PNOR_STRAPS__PNOR_SRAM_MW_R 0 ++#define PNOR_set_opmode 0x18045018 ++#define PNOR_set_opmode__set_mw_R 0 ++#define PNOR_direct_cmd 0x18045010 ++#define PNOR_direct_cmd__cmd_type_R 21 ++ ++#define ChipcommonG_tim0_TIM_TIMER1Load 0x18003000 ++#define ChipcommonG_tim1_TIM_TIMER1Load 0x18004000 ++#define ChipcommonG_tim2_TIM_TIMER1Load 0x18005000 ++#define ChipcommonG_tim3_TIM_TIMER1Load 0x18006000 ++ ++#define ChipcommonS_RNG_CTRL 0x18032000 ++ ++#define IHOST_S0_IDM_ERROR_LOG_CONTROL 0x18107900 ++#define IHOST_S0_IDM_ERROR_LOG_COMPLETE 0x18107904 ++#define IHOST_S0_IDM_ERROR_LOG_STATUS 0x18107908 ++#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810790c ++#define IHOST_S0_IDM_ERROR_LOG_ID 0x18107914 ++#define IHOST_S0_IDM_ERROR_LOG_FLAGS 0x1810791c ++#define IHOST_S0_IDM_INTERRUPT_STATUS 0x18107a00 ++ ++#define IHOST_S1_IDM_ERROR_LOG_CONTROL 0x18106900 ++#define IHOST_S1_IDM_ERROR_LOG_COMPLETE 0x18106904 ++#define IHOST_S1_IDM_ERROR_LOG_STATUS 0x18106908 ++#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810690c ++#define IHOST_S1_IDM_ERROR_LOG_ID 0x18106914 ++#define IHOST_S1_IDM_ERROR_LOG_FLAGS 0x1810691c ++#define IHOST_S1_IDM_INTERRUPT_STATUS 0x18106a00 ++ ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18108900 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18108904 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS 0x18108908 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810890c ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID 0x18108914 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810891c ++#define AXI_PCIE_S0_IDM_IDM_INTERRUPT_STATUS 0x18108a00 ++ ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_CONTROL 0x18109900 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_COMPLETE 0x18109904 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_STATUS 0x18109908 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810990c ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ID 0x18109914 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_FLAGS 0x1810991c ++#define AXI_PCIE_S1_IDM_IDM_INTERRUPT_STATUS 0x18109a00 ++ ++#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810a900 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810a904 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810a908 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810a90c ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ID 0x1810a914 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810a91c ++#define CMICD_S0_IDM_IDM_INTERRUPT_STATUS 0x1810aa00 ++ ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18119900 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18119904 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS 0x18119908 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811990c ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID 0x18119914 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1811991c ++#define A9JTAG_S0_IDM_IDM_INTERRUPT_STATUS 0x18119a00 ++ ++#define SRAM_S0_IDM_ERROR_LOG_CONTROL 0x1811b900 ++#define SRAM_S0_IDM_ERROR_LOG_COMPLETE 0x1811b904 ++#define SRAM_S0_IDM_ERROR_LOG_STATUS 0x1811b908 ++#define SRAM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1811b90c ++#define SRAM_S0_IDM_ERROR_LOG_ID 0x1811b914 ++#define SRAM_S0_IDM_ERROR_LOG_FLAGS 0x1811b91c ++#define SRAM_S0_IDM_INTERRUPT_STATUS 0x1811ba00 ++ ++#define APBX_IDM_IDM_ERROR_LOG_CONTROL 0x18130900 ++#define APBX_IDM_IDM_ERROR_LOG_COMPLETE 0x18130904 ++#define APBX_IDM_IDM_ERROR_LOG_STATUS 0x18130908 ++#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813090c ++#define APBX_IDM_IDM_ERROR_LOG_ID 0x18130914 ++#define APBX_IDM_IDM_ERROR_LOG_FLAGS 0x1813091c ++#define APBX_IDM_IDM_INTERRUPT_STATUS 0x18130a00 ++ ++#define APBY_IDM_IDM_ERROR_LOG_CONTROL 0x18131900 ++#define APBY_IDM_IDM_ERROR_LOG_COMPLETE 0x18131904 ++#define APBY_IDM_IDM_ERROR_LOG_STATUS 0x18131908 ++#define APBY_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813190c ++#define APBY_IDM_IDM_ERROR_LOG_ID 0x18131914 ++#define APBY_IDM_IDM_ERROR_LOG_FLAGS 0x1813191c ++#define APBY_IDM_IDM_INTERRUPT_STATUS 0x18131a00 ++ ++#define APBZ_IDM_IDM_ERROR_LOG_CONTROL 0x18132900 ++#define APBZ_IDM_IDM_ERROR_LOG_COMPLETE 0x18132904 ++#define APBZ_IDM_IDM_ERROR_LOG_STATUS 0x18132908 ++#define APBZ_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813290c ++#define APBZ_IDM_IDM_ERROR_LOG_ID 0x18132914 ++#define APBZ_IDM_IDM_ERROR_LOG_FLAGS 0x1813291c ++#define APBZ_IDM_IDM_INTERRUPT_STATUS 0x18132a00 ++ ++#define DDR_S1_IDM_ERROR_LOG_CONTROL 0xf8102900 ++#define DDR_S1_IDM_ERROR_LOG_COMPLETE 0xf8102904 ++#define DDR_S1_IDM_ERROR_LOG_STATUS 0xf8102908 ++#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB 0xf810290c ++#define DDR_S1_IDM_ERROR_LOG_ID 0xf8102914 ++#define DDR_S1_IDM_ERROR_LOG_FLAGS 0xf810291c ++#define DDR_S1_IDM_INTERRUPT_STATUS 0xf8102a00 ++ ++#define DDR_S2_IDM_ERROR_LOG_CONTROL 0xf8103900 ++#define DDR_S2_IDM_ERROR_LOG_COMPLETE 0xf8103904 ++#define DDR_S2_IDM_ERROR_LOG_STATUS 0xf8103908 ++#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB 0xf810390c ++#define DDR_S2_IDM_ERROR_LOG_ID 0xf8103914 ++#define DDR_S2_IDM_ERROR_LOG_FLAGS 0xf810391c ++#define DDR_S2_IDM_INTERRUPT_STATUS 0xf8103a00 ++ ++#define ROM_S0_IDM_ERROR_LOG_CONTROL 0xf8104900 ++#define ROM_S0_IDM_ERROR_LOG_COMPLETE 0xf8104904 ++#define ROM_S0_IDM_ERROR_LOG_STATUS 0xf8104908 ++#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB 0xf810490c ++#define ROM_S0_IDM_ERROR_LOG_ID 0xf8104914 ++#define ROM_S0_IDM_ERROR_LOG_FLAGS 0xf810491c ++#define ROM_S0_IDM_INTERRUPT_STATUS 0xf8104a00 ++ ++#define NAND_IDM_IDM_ERROR_LOG_CONTROL 0xf8105900 ++#define NAND_IDM_IDM_ERROR_LOG_COMPLETE 0xf8105904 ++#define NAND_IDM_IDM_ERROR_LOG_STATUS 0xf8105908 ++#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB 0xf810590c ++#define NAND_IDM_IDM_ERROR_LOG_ID 0xf8105914 ++#define NAND_IDM_IDM_ERROR_LOG_FLAGS 0xf810591c ++#define NAND_IDM_IDM_INTERRUPT_STATUS 0xf8105a00 ++ ++#define QSPI_IDM_IDM_ERROR_LOG_CONTROL 0xf8106900 ++#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE 0xf8106904 ++#define QSPI_IDM_IDM_ERROR_LOG_STATUS 0xf8106908 ++#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB 0xf810690c ++#define QSPI_IDM_IDM_ERROR_LOG_ID 0xf8106914 ++#define QSPI_IDM_IDM_ERROR_LOG_FLAGS 0xf810691c ++#define QSPI_IDM_IDM_INTERRUPT_STATUS 0xf8106a00 ++ ++#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL 0x18120900 ++#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE 0x18120904 ++#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS 0x18120908 ++#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB 0x1812090c ++#define AXIIC_DS_0_IDM_ERROR_LOG_ID 0x18120914 ++#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS 0x1812091c ++#define AXIIC_DS_0_IDM_INTERRUPT_STATUS 0x18120a00 ++ ++#define AXIIC_DS_1_IDM_ERROR_LOG_CONTROL 0x18121900 ++#define AXIIC_DS_1_IDM_ERROR_LOG_COMPLETE 0x18121904 ++#define AXIIC_DS_1_IDM_ERROR_LOG_STATUS 0x18121908 ++#define AXIIC_DS_1_IDM_ERROR_LOG_ADDR_LSB 0x1812190c ++#define AXIIC_DS_1_IDM_ERROR_LOG_ID 0x18121914 ++#define AXIIC_DS_1_IDM_ERROR_LOG_FLAGS 0x1812191c ++#define AXIIC_DS_1_IDM_INTERRUPT_STATUS 0x18121a00 ++ ++#define AXIIC_DS_2_IDM_ERROR_LOG_CONTROL 0x1811d900 ++#define AXIIC_DS_2_IDM_ERROR_LOG_COMPLETE 0x1811d904 ++#define AXIIC_DS_2_IDM_ERROR_LOG_STATUS 0x1811d908 ++#define AXIIC_DS_2_IDM_ERROR_LOG_ADDR_LSB 0x1811d90c ++#define AXIIC_DS_2_IDM_ERROR_LOG_ID 0x1811d914 ++#define AXIIC_DS_2_IDM_ERROR_LOG_FLAGS 0x1811d91c ++#define AXIIC_DS_2_IDM_INTERRUPT_STATUS 0x1811da00 ++ ++#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL 0x1811e900 ++#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE 0x1811e904 ++#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS 0x1811e908 ++#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB 0x1811e90c ++#define AXIIC_DS_3_IDM_ERROR_LOG_ID 0x1811e914 ++#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS 0x1811e91c ++#define AXIIC_DS_3_IDM_INTERRUPT_STATUS 0x1811ea00 ++ ++/* GPIO */ ++#define ChipcommonG_GP_DATA_IN 0x1800a000 ++#define ChipcommonG_GP_DATA_IN_BASE 0x000 ++#define ChipcommonG_GP_DATA_OUT_BASE 0x004 ++#define ChipcommonG_GP_OUT_EN_BASE 0x008 ++#define ChipcommonG_GP_INT_TYPE_BASE 0x00c ++#define ChipcommonG_GP_INT_DE_BASE 0x010 ++#define ChipcommonG_GP_INT_EDGE_BASE 0x014 ++#define ChipcommonG_GP_INT_MSK_BASE 0x018 ++#define ChipcommonG_GP_INT_STAT_BASE 0x01c ++#define ChipcommonG_GP_INT_MSTAT_BASE 0x020 ++#define ChipcommonG_GP_INT_CLR_BASE 0x024 ++#define ChipcommonG_GP_AUX_SEL_BASE 0x028 ++#define ChipcommonG_GP_INIT_VAL_BASE 0x030 ++#define ChipcommonG_GP_PAD_RES_BASE 0x034 ++#define ChipcommonG_GP_RES_EN_BASE 0x038 ++#define ChipcommonG_GP_TEST_INPUT_BASE 0x03c ++#define ChipcommonG_GP_TEST_OUTPUT_BASE 0x040 ++#define ChipcommonG_GP_TEST_ENABLE_BASE 0x044 ++#define ChipcommonG_GP_PRB_ENABLE_BASE 0x048 ++#define ChipcommonG_GP_PRB_OE_BASE 0x04c ++ ++/* Watchdog */ ++#define ChipcommonG_WDT_WDOGLOAD 0x18009000 ++#define DMU_PCU_CRU_RESET_REASON 0x1800f014 ++#define DMU_PCU_CRU_RESET_REASON__watchdog_reset 0 ++ ++#endif /* __SOCREGS_P7_OPEN_H */ +diff --git a/arch/arm/mach-iproc/include/mach/vmalloc.h b/arch/arm/mach-iproc/include/mach/vmalloc.h +new file mode 100644 +index 0000000..0611b30 +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/vmalloc.h +@@ -0,0 +1,24 @@ ++/* ++ * arch/arm/mach-iproc/include/mach/vmalloc.h ++ * ++ * Copyright (C) 2014 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifdef __ASSEMBLY__ ++#define VMALLOC_END 0xff000000 ++#else ++#define VMALLOC_END 0xff000000UL ++#endif +diff --git a/arch/arm/mach-iproc/io_map.c b/arch/arm/mach-iproc/io_map.c +new file mode 100644 +index 0000000..cbea0a2 +--- /dev/null ++++ b/arch/arm/mach-iproc/io_map.c +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define IO_DESC(va, sz) { .virtual = va, \ ++ .pfn = __phys_to_pfn(HW_IO_VIRT_TO_PHYS(va)), \ ++ .length = sz, \ ++ .type = MT_DEVICE } ++ ++ ++static struct map_desc northstar_io_desc[] __initdata = ++{ ++ IO_DESC(IO_CORE_IDM_VA,IO_CORE_IDM_SIZE), ++ IO_DESC(IO_ARMCORE_VA, IO_ARMCORE_SIZE), ++#ifdef CONFIG_MACH_IPROC_P7 ++ IO_DESC(IO_SMAU_IDM_VA, IO_SMAU_IDM_SIZE), ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++}; ++ ++extern void __init iproc_map_io(void); ++ ++void __init northstar_map_io(void) ++{ ++ iotable_init(northstar_io_desc, ARRAY_SIZE(northstar_io_desc)); ++} +diff --git a/arch/arm/mach-iproc/localtimer.c b/arch/arm/mach-iproc/localtimer.c +new file mode 100644 +index 0000000..b139cac +--- /dev/null ++++ b/arch/arm/mach-iproc/localtimer.c +@@ -0,0 +1,27 @@ ++/* ++ * linux/arch/arm/mach-iproc/localtimer.c ++ * ++ * Copyright (C) 2002 ARM Ltd. ++ * 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 as ++ * published by the Free Software Foundation. ++ */ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* ++ * Setup the local clock events for a CPU. ++ */ ++int __cpuinit local_timer_setup(struct clock_event_device *evt) ++{ ++ evt->irq = IRQ_LOCALTIMER; ++ twd_timer_setup(evt); ++ return 0; ++} +diff --git a/arch/arm/mach-iproc/northstar.c b/arch/arm/mach-iproc/northstar.c +new file mode 100644 +index 0000000..dc23a34 +--- /dev/null ++++ b/arch/arm/mach-iproc/northstar.c +@@ -0,0 +1,166 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++ ++ ++ ++#define TIMER_LOAD 0x00 ++#define TIMER_VALUE 0x04 ++#define TIMER_CTRL 0x08 ++#define TIMER_CTRL_PRESC_SHFT (8) ++#define TIMER_CTRL_IE (1 << 2) ++#define TIMER_CTRL_PERIODIC (1 << 1) ++#define TIMER_CTRL_ENABLE (1 << 0) ++ ++#define TIMER_INTCLR 0x0c ++#define IPROC_L2CC_REG_BASE_VA HW_IO_PHYS_TO_VIRT(IPROC_L2CC_REG_BASE) ++ ++extern void __iomem *twd_base; ++extern void iproc_clocksource_init(void __iomem *); ++extern void iproc_clockevents_init(void __iomem *, unsigned int); ++extern void __init northstar_dmu_init(struct clk *clk_ref); ++extern void __init iproc_cru_init(struct clk *clk_ref); ++extern void iproc_enable_data_prefetch_aborts(void); ++extern void northstar_restart(char mode, const char *cmd); ++ ++static void ++northstar_poweroff(void) ++{ ++ while(1) ++ ; ++} ++ ++ ++#ifdef CONFIG_CACHE_L2X0 ++static void __init northstar_l2x0_init(void) ++{ ++ void __iomem *l2cache_base = IOMEM(IPROC_L2CC_REG_VA); ++ void __iomem *cca = IOMEM(IPROC_CCA_CORE_REG_VA); ++ unsigned int chipid = (readl(cca) & 0x0000ffff); ++ ++ /* ++ * 16KB way size, 16-way associativity ++ */ ++#if defined(CONFIG_MACH_NS) ++ if (chipid >= 0xcf19 /* costar */) { ++#ifdef CONFIG_BCM_IPROC_CA9_PREFETCH ++ /* inst/data prefetch & Early BRESP & Fill line zero (also need A9) */ ++ l2x0_init(l2cache_base, (0x0A150000 | 0x3 << 28 | 0x1 << 30 | 0x1 << 0), ~(0x000F0000)); ++#else ++ l2x0_init(l2cache_base, 0x0A150000, ~(0x000F0000)); ++#endif /* CONFIG_BCM_IPROC_CA9_PREFETCH */ ++ } else { /* northstar */ ++ l2x0_init(l2cache_base, 0x0A130000, ~(0x000F0000)); ++ } ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ l2x0_init(l2cache_base, 0x0A150000, ~(0x000F0000)); ++#elif defined(CONFIG_MACH_HR2) ++ l2x0_init(l2cache_base, 0x0A120000, ~(0x000F0000)); ++#elif defined(CONFIG_MACH_NSP) ++#ifdef CONFIG_BCM_IPROC_CA9_PREFETCH ++ /* inst/data prefetch & Early BRESP & Fill line zero (also need A9) */ ++ l2x0_init(l2cache_base, (0x0A150000 | 0x3 << 28 | 0x1 << 30 | 0x1 << 0), ~(0x000F0000)); ++#else ++ l2x0_init(l2cache_base, 0x0A150000, ~(0x000F0000)); ++#endif /* CONFIG_BCM_IPROC_CA9_PREFETCH */ ++#elif defined(CONFIG_MACH_IPROC_P7) ++ l2x0_init(l2cache_base, 0x0A130000, ~(0x000F0000)); ++#endif ++} ++#endif ++ ++static int __init northstar_init(void) ++{ ++#ifdef CONFIG_PM ++ pm_power_off = northstar_poweroff; ++#endif ++ arm_pm_restart = northstar_restart; ++ ++#ifdef CONFIG_MACH_CYGNUS ++#else ++#ifdef CONFIG_CACHE_L2X0 ++ northstar_l2x0_init(); ++#endif ++#endif /* END of CYGNUS */ ++ ++ return 0; ++} ++early_initcall(northstar_init); ++ ++/* ++ * CPU global and MPCORE Per CPU local timer ++ */ ++#define GLB_TIMER IOMEM(IPROC_PERIPH_GLB_TIM_REG_VA); ++#define PVT_TIMER IOMEM(IPROC_PERIPH_PVT_TIM_REG_VA); ++ ++void __iomem *gtimer_va_base = GLB_TIMER; ++void __iomem *ptimer_va_base = PVT_TIMER; ++ ++/* ++ * Set up the clock source and clock events devices ++ */ ++void __init northstar_timer_init(struct clk *clk_ref) ++{ ++ int err; ++ ++ /* ++ * Setup DMU and CRU early ++ */ ++ northstar_dmu_init(clk_ref); ++ iproc_cru_init(clk_ref); ++ ++ /* ++ * Initialise to a known state (all timers off) ++ */ ++ writel(0, ptimer_va_base + TIMER_CTRL); ++ writel(0, gtimer_va_base + TIMER_CTRL); ++ ++#ifdef CONFIG_HAVE_ARM_TWD ++ /* ++ * Setup the local clock events for a CPU. ++ */ ++ twd_base = IO_ADDRESS(IPROC_PERIPH_PVT_TIM_REG_VA); ++#endif ++ ++ iproc_clocksource_init(gtimer_va_base); ++ iproc_clockevents_init(gtimer_va_base, BCM_INT_ID_PPI11); ++ ++ iproc_enable_data_prefetch_aborts(); ++} +diff --git a/arch/arm/mach-iproc/northstar.h b/arch/arm/mach-iproc/northstar.h +new file mode 100644 +index 0000000..09b3ccc +--- /dev/null ++++ b/arch/arm/mach-iproc/northstar.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __NORTHSTAR_H ++#define __NORTHSTAR_H ++ ++#include ++#include ++ ++extern struct platform_device northstar_ipc_device; ++ ++void __init northstar_map_io(void); ++ ++#endif /* __NORTHSTAR_H */ +diff --git a/arch/arm/mach-iproc/northstar_dmu.c b/arch/arm/mach-iproc/northstar_dmu.c +new file mode 100644 +index 0000000..f95b0e3 +--- /dev/null ++++ b/arch/arm/mach-iproc/northstar_dmu.c +@@ -0,0 +1,802 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define IPROC_DMU_BASE_PA IPROC_DMU_BASE_REG ++//#define IPROC_DMU_BASE_VA HW_IO_PHYS_TO_VIRT(IPROC_DMU_BASE_PA) ++ ++static struct resource dmu_regs = { ++ .name = "dmu_regs", ++ .start = (resource_size_t) IOMEM(IPROC_DMU_BASE_VA), ++ .end = (resource_size_t) (IOMEM(IPROC_DMU_BASE_VA) + SZ_4K - 1), ++ .flags = IORESOURCE_MEM, ++}; ++ ++/* ++ * Clock management scheme is a provisional implementation ++ * only intended to retreive the pre-set frequencies for each ++ * of the clocks. ++ * Better handling of post-dividers and fractional part of ++ * feedbeck dividers need to be added. ++ * Need to understand what diagnostics from CRU registers could ++ * be handy, and export that via a sysfs interface. ++ */ ++ ++/* ++ * The CRU contains two similar PLLs: LCPLL and GENPLL, ++ * both with several output channels divided from the PLL ++ * output ++ */ ++ ++/* ++ * Get PLL running status and update output frequency ++ */ ++static int lcpll_status(struct clk * clk) ++{ ++ u32 reg; ++ u64 x; ++ unsigned pdiv, ndiv_int, ndiv_frac; ++ ++ if (clk->type != CLK_PLL) ++ return -EINVAL; ++ ++ /* read status register */ ++ reg = readl(clk->regs_base + 0x10); ++ ++ /* bit 12 is "lock" signal, has to be "1" for proper PLL operation */ ++ if ((reg & (1 << 12)) == 0) { ++ clk->rate = 0; ++ } ++ ++ /* Update PLL frequency */ ++ ++ /* control1 register */ ++ reg = readl(clk->regs_base + 0x04); ++ ++ /* feedback divider integer and fraction parts */ ++ pdiv = (reg >> 28) & 7 ; ++ ndiv_int = (reg >> 20) & 0xff; ++ ndiv_frac = reg & ((1<<20)-1); ++ ++ if (pdiv == 0) ++ return -EIO; ++ ++ x = clk->parent->rate / pdiv ; ++ ++ x = x * ((u64) ndiv_int << 20 | ndiv_frac) ; ++ ++ clk->rate = x >> 20 ; ++ ++ return 0; ++} ++ ++static const struct clk_ops lcpll_ops = { ++ .status = lcpll_status, ++}; ++ ++static int lcpll_chan_status(struct clk * clk) ++{ ++ void * __iomem base; ++ u32 reg; ++ unsigned enable; ++ unsigned mdiv; ++ ++ if (clk->parent == NULL || clk->type != CLK_DIV) ++ return -EINVAL; ++ ++ /* Register address is only stored in PLL structure */ ++ base = clk->parent->regs_base; ++ BUG_ON(base == NULL); ++ ++ /* enable bit is in enableb_ch[] inversed */ ++ enable = ((readl(base + 0) >> 6) & 7) ^ 7; ++ ++ if (0 == (enable & (1 << clk->chan))) { ++ clk->rate = 0; ++ return -EIO; ++ } ++ ++ /* get divider */ ++ reg = readl(base + 0x08); ++ ++ mdiv = 0xff & (reg >> ((0x3^clk->chan) << 3)); ++ ++ /* when divisor is 0, it behaves as max+1 */ ++ if (mdiv == 0) ++ mdiv = 1 << 8; ++ ++ printk("LCPLL[%d] mdiv=%u rate=%lu\n", clk->chan, mdiv, clk->parent->rate); ++ ++ clk->rate = (clk->parent->rate / mdiv); ++ return 0; ++} ++ ++ ++static const struct clk_ops lcpll_chan_ops = { ++ .status = lcpll_chan_status, ++}; ++ ++/* ++ * LCPLL has 4 output channels ++ */ ++static struct clk clk_lcpll = { ++ .ops = &lcpll_ops, ++ .name = "LCPLL", ++ .type = CLK_PLL, ++ .chan = 4, ++}; ++ ++/* ++ * LCPLL output clocks - ++ * chan 0 - PCIe ref clock, should be 1 GHz, ++ * chan 1 - SDIO clock, e.g. 200 MHz, ++ * chan 2 - DDR clock, typical 166.667 MHz for DDR667, ++ * chan 3 - Unknown ++ */ ++ ++static struct clk clk_lcpll_ch[4] = { ++ { ++ .ops = &lcpll_chan_ops, ++ .parent = &clk_lcpll, ++ .type = CLK_DIV, ++ .name = "lcpll_ch0", ++ .chan = 0, ++ }, ++ { ++ .ops = &lcpll_chan_ops, ++ .parent = &clk_lcpll, ++ .type = CLK_DIV, ++ .name = "lcpll_ch1", ++ .chan = 1, ++ }, ++ { ++ .ops = &lcpll_chan_ops, ++ .parent = &clk_lcpll, ++ .type = CLK_DIV, ++ .name = "lcpll_ch2", ++ .chan = 2, ++ }, ++ { ++ .ops = &lcpll_chan_ops, ++ .parent = &clk_lcpll, ++ .type = CLK_DIV, ++ .name = "lcpll_ch3", ++ .chan = 3, ++ }, ++}; ++ ++/* ++ * Get PLL running status and update output frequency ++ */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++static int genpll_status(struct clk * clk) ++{ ++ u32 reg; ++ u64 x; ++ unsigned pdiv; ++ unsigned ndiv_int; ++ unsigned ndiv_frac; ++ ++ if (clk->type != CLK_PLL) ++ return -EINVAL; ++ ++ /* Offset of the PLL status register */ ++ reg = readl(clk->regs_base + 0x20); ++ ++ /* bit 12 is "lock" signal, has to be "1" for proper PLL operation */ ++ if((reg & (1 << 12)) == 0) { ++ clk->rate = 0; ++ return -EIO; ++ } ++ ++ /* Update PLL frequency */ ++ ++ /* get PLL feedback divider values from control5 */ ++ reg = readl(clk->regs_base + 0x14); ++ ++ /* feedback divider integer and fraction parts */ ++ ndiv_int = reg >> 20; ++ ndiv_frac = reg & ((1 << 20) - 1); ++ ++ /* get pdiv */ ++ reg = readl(clk->regs_base + 0x18); ++ pdiv = (reg >> 24) & 7; ++ ++ if (pdiv == 0) ++ return -EIO; ++ ++ x = clk->parent->rate / pdiv; ++ ++ x = x * ((u64) ndiv_int << 20 | ndiv_frac); ++ ++ clk->rate = x >> 20; ++ ++ return 0; ++} ++#endif ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++static int genpll_status(struct clk * clk) ++{ ++ u32 reg; ++ u64 x; ++ unsigned pdiv; ++ unsigned ndiv_int; ++ ++ if (clk->type != CLK_PLL) ++ return -EINVAL; ++ ++ /* Offset of the PLL status register */ ++ reg = readl(clk->regs_base + 0x18); ++ ++ /* bit 12 is "lock" signal, has to be "1" for proper PLL operation */ ++ if((reg & (1 << IPROC_WRAP_GEN_PLL_STATUS__GEN_PLL_LOCK)) == 0) { ++ clk->rate = 0; ++ return -EIO; ++ } ++ ++ /* Update PLL frequency */ ++ ++ /* get PLL feedback divider values from control5 */ ++ reg = readl(clk->regs_base + 0x04); ++ ++ /* feedback divider integer and fraction parts */ ++ ndiv_int = (reg >> IPROC_WRAP_GEN_PLL_CTRL1__NDIV_INT_R) & ((1 << IPROC_WRAP_GEN_PLL_CTRL1__NDIV_INT_WIDTH) -1); ++ ++ /* get pdiv */ ++ pdiv = (reg >> IPROC_WRAP_GEN_PLL_CTRL1__PDIV_R) & ((1 << IPROC_WRAP_GEN_PLL_CTRL1__PDIV_WIDTH) -1); ++ ++ if (pdiv == 0) ++ return -EIO; ++ ++ x = clk->parent->rate / pdiv; ++ ++ x = x * ((u64) ndiv_int); ++ ++ clk->rate = x; ++ ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_MACH_KT2) ++static int genpll_status(struct clk * clk) ++{ ++ clk->rate = 2475000000; ++ ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_MACH_CYGNUS) //chandra: todo ++static int genpll_status(struct clk * clk) ++{ ++ ++} ++#endif ++static const struct clk_ops genpll_ops = { ++ .status = genpll_status, ++}; ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++static int genpll_chan_status(struct clk * clk) ++{ ++ void * __iomem base; ++ u32 reg; ++ unsigned enable; ++ unsigned mdiv; ++ unsigned off, shift; ++ ++ if (clk->parent == NULL || clk->type != CLK_DIV) ++ return -EINVAL; ++ ++ /* Register address is only stored in PLL structure */ ++ base = clk->parent->regs_base; ++ ++ BUG_ON (base == NULL); ++ ++ /* enable bit is in enableb_ch[0..5] inversed */ ++ enable = ((readl(base + 0x04) >> 12) & 0x3f) ^ 0x3f ; ++ ++ if (0 == (enable & (1 << clk->chan))) { ++ clk->rate = 0; ++ return -EIO; ++ } ++ ++ /* GENPLL has the 6 channels spread over two regs */ ++ switch (clk->chan) { ++ case 0: ++ off = 0x18; shift = 16; ++ break; ++ ++ case 1: ++ off = 0x18; shift = 8; ++ break; ++ ++ case 2: ++ off = 0x18; shift = 0; ++ break; ++ ++ case 3: ++ off = 0x1c; shift = 16; ++ break; ++ ++ case 4: ++ off = 0x1c; shift = 8; ++ break; ++ ++ case 5: ++ off = 0x1c; shift = 16; /* Set to AXI clock */ ++ break; ++ ++ default: ++ BUG_ON(clk->chan); ++ off = shift = 0; /* fend off warnings */ ++ } ++ ++ reg = readl(base + off); ++ ++ mdiv = 0xff & (reg >> shift); ++ /* APB clock is always AXIclock/4 */ ++ if(clk->chan == 5) ++ mdiv = mdiv * 4; ++ ++ /* when divisor is 0, it behaves as max+1 */ ++ if (mdiv == 0) ++ mdiv = 1 << 8; ++ ++ printk("GENPLL[%d] mdiv=%u rate=%lu\n", ++ clk->chan, mdiv, clk->parent->rate); ++ ++ clk->rate = clk->parent->rate / mdiv; ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++static int genpll_chan_status(struct clk * clk) ++{ ++ void * __iomem base; ++ u32 reg; ++ unsigned enable; ++ unsigned mdiv = 0; ++ unsigned off, shift; ++ ++ if (clk->parent == NULL || clk->type != CLK_DIV) ++ return -EINVAL; ++ ++ /* Register address is only stored in PLL structure */ ++ base = clk->parent->regs_base; ++ ++ BUG_ON (base == NULL); ++ /* GENPLL has the 6 channels spread over two regs */ ++ switch (clk->chan) { ++ case 0: ++ off = 0x04; shift = IPROC_WRAP_GEN_PLL_CTRL1__CH0_MDIV_R; ++ break; ++ ++ case 1: ++ off = 0x04; shift = IPROC_WRAP_GEN_PLL_CTRL1__CH1_MDIV_R; ++ break; ++ ++ case 2: ++ off = 0x08; shift = IPROC_WRAP_GEN_PLL_CTRL2__CH2_MDIV_R; ++ break; ++ ++ case 3: ++ off = 0x08; shift = IPROC_WRAP_GEN_PLL_CTRL2__CH3_MDIV_R; ++ break; ++ ++ case 4: ++ off = 0x08; shift = IPROC_WRAP_GEN_PLL_CTRL2__CH4_MDIV_R; ++ break; ++ ++ case 5: ++ off = 0x08; shift = IPROC_WRAP_GEN_PLL_CTRL2__CH3_MDIV_R; ++ break; ++ ++ default: ++ BUG_ON(clk->chan); ++ off = shift = 0; /* fend off warnings */ ++ } ++ ++ reg = readl(base + off); ++ ++ mdiv = 0xff & (reg >> shift); ++ if(clk->chan == 5) ++ mdiv *= 4; ++ ++ /* when divisor is 0, it behaves as max+1 */ ++ if (mdiv == 0) ++ mdiv = 1 << 8; ++ ++ printk("GENPLL[%d] mdiv=%u rate=%lu\n", ++ clk->chan, mdiv, clk->parent->rate); ++ ++ clk->rate = clk->parent->rate / mdiv; ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_MACH_KT2) ++static int genpll_chan_status(struct clk * clk) ++{ ++ unsigned mdiv = 0; ++ ++ ++ if (clk->parent == NULL || clk->type != CLK_DIV) ++ return -EINVAL; ++ ++ /* GENPLL has the 6 channels spread over two regs */ ++ switch (clk->chan) { ++ case 0: ++ mdiv = 10; ++ break; ++ ++ case 3: ++ mdiv = 5; ++ break; ++ ++ case 4: ++ mdiv = 10; ++ break; ++ ++ case 5: ++ mdiv = 5; ++ break; ++ ++ default: ++ BUG_ON(clk->chan); ++ } ++ ++ if(clk->chan == 5) ++ mdiv *= 4; ++ ++ /* when divisor is 0, it behaves as max+1 */ ++ if (mdiv == 0) ++ mdiv = 1 << 8; ++ ++ printk("GENPLL[%d] mdiv=%u rate=%lu\n", ++ clk->chan, mdiv, clk->parent->rate); ++ ++ clk->rate = clk->parent->rate / mdiv; ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_MACH_CYGNUS) //chandra: todo ++static int genpll_chan_status(struct clk * clk) ++{ ++ ++} ++#endif ++ ++static const struct clk_ops genpll_chan_ops = { ++ .status = genpll_chan_status, ++}; ++ ++ ++/* ++ * GENPLL has 6 output channels ++ */ ++static struct clk clk_genpll = { ++ .ops = &genpll_ops, ++ .name = "GENPLL", ++ .type = CLK_PLL, ++ .chan = 6, ++}; ++ ++/* ++ * chan 0 - Ethernet switch and MAC, RGMII, need 250 MHz ++ * chan 1 - Ethernet switch slow clock, 150 Mhz ++ * chan 2 - USB PHY clock, need 30 MHz ++ * chan 3 - iProc N MHz clock, set from OTP ++ * chan 4 - iProc N/2 MHz clock, set from OTP ++ * chan 5 - iProc N/4 MHz clock, set from OTP ++ * ++ * To Do: which clock goes to MPCORE PERIPHCLOCK? ++ */ ++#ifdef CONFIG_MACH_CYGNUS_EMULATION //chandra:emul ++ static struct clk clk_genpll_ch[6] = { ++ { ++ .ops = NULL, ++ .parent = NULL, ++ .type = CLK_DIV, ++ .name = "genpll_ch0", ++ .chan = 0, ++ }, ++ { ++ .ops = NULL, ++ .parent = NULL, ++ .type = CLK_DIV, ++ .name = "genpll_ch1", ++ .chan = 1, ++ }, ++ { ++ .ops = NULL, ++ .parent = NULL, ++ .type = CLK_DIV, ++ .name = "genpll_ch2", ++ .chan = 2, ++ }, ++ { ++ .ops = NULL, ++ .parent = NULL, ++ .rate = 992000, ++ .type = CLK_DIV, ++ .name = "genpll_ch3", ++ .chan = 3, ++ }, ++ { ++ .ops = NULL, ++ .parent = NULL, ++ .rate = 644800, ++ .type = CLK_DIV, ++ .name = "genpll_ch4", ++ .chan = 4, ++ }, ++ { ++ .ops = NULL, ++ .parent = NULL, ++ .rate = CONFIG_CYGNUS_EMULATION_CLK_125,//25000000, ++ .type = CLK_DIV, ++ .name = "genpll_ch5", ++ .chan = 5, ++ }, ++ }; ++ ++#else ++static struct clk clk_genpll_ch[6] = { ++ { ++ .ops = &genpll_chan_ops, ++ .parent = &clk_genpll, ++ .type = CLK_DIV, ++ .name = "genpll_ch0", ++ .chan = 0, ++ }, ++ { ++ .ops = &genpll_chan_ops, ++ .parent = &clk_genpll, ++ .type = CLK_DIV, ++ .name = "genpll_ch1", ++ .chan = 1, ++ }, ++ { ++ .ops = &genpll_chan_ops, ++ .parent = &clk_genpll, ++ .type = CLK_DIV, ++ .name = "genpll_ch2", ++ .chan = 2, ++ }, ++ { ++ .ops = &genpll_chan_ops, ++ .parent = &clk_genpll, ++ .type = CLK_DIV, ++ .name = "genpll_ch3", ++ .chan = 3, ++ }, ++ { ++ .ops = &genpll_chan_ops, ++ .parent = &clk_genpll, ++ .type = CLK_DIV, ++ .name = "genpll_ch4", ++ .chan = 4, ++ }, ++ { ++ .ops = &genpll_chan_ops, ++ .parent = &clk_genpll, ++ .type = CLK_DIV, ++ .name = "genpll_ch5", ++ .chan = 5, ++ }, ++}; ++#endif ++ ++/* ++ * This table is used to locate clock sources ++ * from device drivers ++ */ ++ ++static struct clk_lookup ns_clk_lookups[] = { ++ { ++ .dev_id = "pcie", ++ .con_id = "c_clk100", ++ .clk = &clk_lcpll_ch[0], ++ },{ ++ .dev_id = "sdio", ++ .con_id = "c_clk200", ++ .clk = &clk_lcpll_ch[1], ++ },{ ++ .dev_id = "ddr", ++ .con_id = "c_clk400", ++ .clk = &clk_lcpll_ch[2], ++ },{ ++ .dev_id = "tbd", ++ .con_id = "c_clk120", ++ .clk = &clk_lcpll_ch[3], ++ },{ ++ .dev_id = "en_phy", ++ .con_id = "c_clk250", ++ .clk = &clk_genpll_ch[0], ++ },{ ++ .dev_id = "en", ++ .con_id = "c_clk150", ++ .clk = &clk_genpll_ch[1], ++ },{ ++ .dev_id = "usb_phy", ++ .con_id = "c_clk30", ++ .clk = &clk_genpll_ch[2], ++ },{ ++ .dev_id = "iproc_fast", ++ .con_id = "c_clk500", ++ .clk = &clk_genpll_ch[3], ++ },{ ++ .dev_id = "iproc_med", ++ .con_id = "c_clk250", ++ .clk = &clk_genpll_ch[4], ++ },{ ++ .dev_id = "iproc_slow", ++ .con_id = "c_clk125", ++ .clk = &clk_genpll_ch[5], ++ } ++#ifdef CONFIG_ARM_AMBA ++ ,{ ++ .con_id = "apb_pclk", ++ .clk = &clk_genpll_ch[5], ++ } ++#if defined (CONFIG_ARM_SP805_WATCHDOG) || defined(CONFIG_ARM_SP805_WATCHDOG_MODULE) ++ ,{ ++ .dev_id = "sp805-wdt", ++ .clk = &clk_genpll_ch[5], ++ } ++#endif ++#endif ++}; ++ ++/* ++ * Install above clocks into clock lookup table ++ * and initialize the register base address for each ++*/ ++static void __init northstar_clocks_init(void *__iomem cru_regs_base, ++ struct clk * clk_ref) ++{ ++ /* ++ * Registers are already mapped with the rest of DMU block ++ * Update register base address ++ */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ clk_lcpll.regs_base = cru_regs_base + 0x00 ; ++ clk_genpll.regs_base = cru_regs_base + 0x40 ; ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ clk_lcpll.regs_base = cru_regs_base + 0x1c ; ++ clk_genpll.regs_base = cru_regs_base + 0x00 ; ++#endif ++ ++ /* Set parent as reference ckock */ ++ clk_lcpll.parent = clk_ref; ++ clk_genpll.parent = clk_ref; ++ ++ /* Install clock sources into the lookup table */ ++ clkdev_add_table(ns_clk_lookups, ++ ARRAY_SIZE(ns_clk_lookups)); ++} ++ ++void __init northstar_dmu_init(struct clk *clk_ref) ++{ ++ void * __iomem reg_base; ++ ++ if (IS_ERR_OR_NULL(clk_ref )) { ++ printk(KERN_ERR "CRU no clock source - skip init\n"); ++ return; ++ } ++ ++ BUG_ON (request_resource(&iomem_resource, &dmu_regs)); ++ ++ /* DMU regs are mapped as part of the fixed mapping with CCA+CCB */ ++ reg_base = (void * __iomem) dmu_regs.start; ++ ++ BUG_ON (IS_ERR_OR_NULL(reg_base)); ++ ++ /* Initialize clocks */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ northstar_clocks_init(reg_base + 0x100, clk_ref); /* CRU LCPLL control0 */ ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ northstar_clocks_init(reg_base + 0xc00, clk_ref); /* IPROC_WRAP_GEN_PLL_CTRL0 */ ++#elif defined(CONFIG_MACH_KT2) ++ northstar_clocks_init(NULL, clk_ref); /* IPROC_WRAP_GEN_PLL_CTRL0 */ ++#endif ++} ++ ++void (*cpld_system_reset)(void); ++EXPORT_SYMBOL(cpld_system_reset); /* used in dni_3448p_cpld.c module */ ++ ++/* ++ * Reset the system ++ */ ++void northstar_restart(char mode, const char *cmd) ++{ ++ void * __iomem reg_addr; ++ u32 reg; ++ ++ if (cpld_system_reset) { ++ printk( KERN_INFO "Using CPLD reset\n"); ++ cpld_system_reset(); ++ } ++ ++ /* CRU_RESET register */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ reg_addr = (void * __iomem) dmu_regs.start + 0x184 ; ++ /* set iproc_reset_n to 0, it may come back or not ... TBD */ ++ reg = readl_relaxed(reg_addr); ++ reg &= ~((u32) 1 << 1); ++ writel_relaxed(reg, reg_addr); ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_KT2) \ ++ || defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++ reg_addr = (void * __iomem) dmu_regs.start + DMU_CRU_RESET_BASE ; ++ /* Reset iproc and cmicd/switch */ ++ writel_relaxed(0, reg_addr); ++#endif ++ ++ ++} ++ ++ ++ ++ ++ ++ ++ ++void northstar_clocks_show( void ) ++{ ++ unsigned i; ++// struct clk * clk ; ++ ++ printk("=========== CLOCKS =================\n"); ++ ++ printk( "DMU Clocks:\n" ); ++ for (i = 0; i < ARRAY_SIZE( ns_clk_lookups); i++) { ++ printk("%s, %s: (%s) %lu\n", ++ ns_clk_lookups[i].con_id, ++ ns_clk_lookups[i].dev_id, ++ ns_clk_lookups[i].clk->name, ++ clk_get_rate( ns_clk_lookups[i].clk)); ++ } ++ printk( "DMU Clocks# %u\n", i ); ++} +diff --git a/arch/arm/mach-iproc/pm.c b/arch/arm/mach-iproc/pm.c +new file mode 100644 +index 0000000..ca2eef4 +--- /dev/null ++++ b/arch/arm/mach-iproc/pm.c +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++ ++int iproc_arm_cpu_do_idle(void) ++{ ++ return cpu_do_idle(); ++} ++EXPORT_SYMBOL(iproc_arm_cpu_do_idle); ++ ++inline void iproc_arm_cpu_resume(void) ++{ ++ cpu_resume(); ++} ++EXPORT_SYMBOL(iproc_arm_cpu_resume); ++ ++int iproc_arm_cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) ++{ ++ return cpu_suspend(arg, fn); ++} ++EXPORT_SYMBOL(iproc_arm_cpu_suspend); +diff --git a/arch/arm/mach-ixp4xx/include/mach/io.h b/arch/arm/mach-ixp4xx/include/mach/io.h +index ffb9d6a..6ec5258 100644 +--- a/arch/arm/mach-ixp4xx/include/mach/io.h ++++ b/arch/arm/mach-ixp4xx/include/mach/io.h +@@ -385,6 +385,20 @@ static inline unsigned int ioread16(const void __iomem *addr) + #endif + } + ++#define ioread16be(p) ioread16be(p) ++static inline unsigned int ioread16be(const void __iomem *addr) ++{ ++ unsigned long port = (unsigned long __force)addr; ++ if (__is_io_address(port)) ++ return (unsigned int)inw(port & PIO_MASK); ++ else ++#ifndef CONFIG_IXP4XX_INDIRECT_PCI ++ return be16_to_cpu((__force __be16)__raw_readw(addr)); ++#else ++ return be16_to_cpu((__force __le16)(unsigned int)__indirect_readw(addr)); ++#endif ++} ++ + #define ioread16_rep(p, v, c) ioread16_rep(p, v, c) + static inline void ioread16_rep(const void __iomem *addr, void *vaddr, + u32 count) +@@ -415,6 +429,21 @@ static inline unsigned int ioread32(const void __iomem *addr) + } + } + ++#define ioread32be(p) ioread32be(p) ++static inline unsigned int ioread32be(const void __iomem *addr) ++{ ++ unsigned long port = (unsigned long __force)addr; ++ if (__is_io_address(port)) ++ return (unsigned int)inl(port & PIO_MASK); ++ else { ++#ifndef CONFIG_IXP4XX_INDIRECT_PCI ++ return be32_to_cpu((__force __be32)__raw_readl(addr)); ++#else ++ return be32_to_cpu((__force __be32)(unsigned int)__indirect_readl(addr)); ++#endif ++ } ++} ++ + #define ioread32_rep(p, v, c) ioread32_rep(p, v, c) + static inline void ioread32_rep(const void __iomem *addr, void *vaddr, + u32 count) +@@ -473,6 +502,20 @@ static inline void iowrite16(u16 value, void __iomem *addr) + #endif + } + ++#define iowrite16be(v, p) iowrite16be(v, p) ++static inline void iowrite16be(u16 value, void __iomem *addr) ++{ ++ unsigned long port = (unsigned long __force)addr; ++ if (__is_io_address(port)) ++ outw(value, port & PIO_MASK); ++ else ++#ifndef CONFIG_IXP4XX_INDIRECT_PCI ++ __raw_writew(cpu_to_be16(value), addr); ++#else ++ __indirect_writew(cpu_to_be16(value), addr); ++#endif ++} ++ + #define iowrite16_rep(p, v, c) iowrite16_rep(p, v, c) + static inline void iowrite16_rep(void __iomem *addr, const void *vaddr, + u32 count) +@@ -502,6 +545,20 @@ static inline void iowrite32(u32 value, void __iomem *addr) + #endif + } + ++#define iowrite32be(v, p) iowrite32be(v, p) ++static inline void iowrite32be(u32 value, void __iomem *addr) ++{ ++ unsigned long port = (unsigned long __force)addr; ++ if (__is_io_address(port)) ++ outl(value, port & PIO_MASK); ++ else ++#ifndef CONFIG_IXP4XX_INDIRECT_PCI ++ __raw_writel((u32 __force)cpu_to_be32(value), addr); ++#else ++ __indirect_writel((u32 __force)cpu_to_be32(value), addr); ++#endif ++} ++ + #define iowrite32_rep(p, v, c) iowrite32_rep(p, v, c) + static inline void iowrite32_rep(void __iomem *addr, const void *vaddr, + u32 count) +diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig +index 7fc603b..a41a90c 100644 +--- a/arch/arm/mach-kirkwood/Kconfig ++++ b/arch/arm/mach-kirkwood/Kconfig +@@ -44,6 +44,26 @@ config MACH_GURUPLUG + Say 'Y' here if you want your kernel to support the + Marvell GuruPlug Reference Board. + ++config ARCH_KIRKWOOD_DT ++ bool "Marvell Kirkwood Flattened Device Tree" ++ select USE_OF ++ help ++ Say 'Y' here if you want your kernel to support the ++ Marvell Kirkwood using flattened device tree. ++ ++config MACH_DREAMPLUG_DT ++ bool "Marvell DreamPlug (Flattened Device Tree)" ++ select ARCH_KIRKWOOD_DT ++ help ++ Say 'Y' here if you want your kernel to support the ++ Marvell DreamPlug (Flattened Device Tree). ++ ++config MACH_ICONNECT_DT ++ bool "Iomega Iconnect (Flattened Device Tree)" ++ select ARCH_KIRKWOOD_DT ++ help ++ Say 'Y' here to enable Iomega Iconnect support. ++ + config MACH_TS219 + bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS" + help +diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile +index 5dcaa81..7858070 100644 +--- a/arch/arm/mach-kirkwood/Makefile ++++ b/arch/arm/mach-kirkwood/Makefile +@@ -20,3 +20,6 @@ obj-$(CONFIG_MACH_NET5BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o + obj-$(CONFIG_MACH_T5325) += t5325-setup.o + + obj-$(CONFIG_CPU_IDLE) += cpuidle.o ++obj-$(CONFIG_ARCH_KIRKWOOD_DT) += board-dt.o ++obj-$(CONFIG_MACH_DREAMPLUG_DT) += board-dreamplug.o ++obj-$(CONFIG_MACH_ICONNECT_DT) += board-iconnect.o +diff --git a/arch/arm/mach-kirkwood/Makefile.boot b/arch/arm/mach-kirkwood/Makefile.boot +index 760a0ef..81244fb 100644 +--- a/arch/arm/mach-kirkwood/Makefile.boot ++++ b/arch/arm/mach-kirkwood/Makefile.boot +@@ -1,3 +1,6 @@ + zreladdr-y += 0x00008000 + params_phys-y := 0x00000100 + initrd_phys-y := 0x00800000 ++ ++dtb-$(CONFIG_MACH_DREAMPLUG_DT) += kirkwood-dreamplug.dtb ++dtb-$(CONFIG_MACH_ICONNECT_DT) += kirkwood-iconnect.dtb +diff --git a/arch/arm/mach-kirkwood/board-dreamplug.c b/arch/arm/mach-kirkwood/board-dreamplug.c +new file mode 100644 +index 0000000..9854539 +--- /dev/null ++++ b/arch/arm/mach-kirkwood/board-dreamplug.c +@@ -0,0 +1,152 @@ ++/* ++ * Copyright 2012 (C), Jason Cooper ++ * ++ * arch/arm/mach-kirkwood/board-dreamplug.c ++ * ++ * Marvell DreamPlug Reference Board Init for drivers not converted to ++ * flattened device tree yet. ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "common.h" ++#include "mpp.h" ++ ++struct mtd_partition dreamplug_partitions[] = { ++ { ++ .name = "u-boot", ++ .size = SZ_512K, ++ .offset = 0, ++ }, ++ { ++ .name = "u-boot env", ++ .size = SZ_64K, ++ .offset = SZ_512K + SZ_512K, ++ }, ++ { ++ .name = "dtb", ++ .size = SZ_64K, ++ .offset = SZ_512K + SZ_512K + SZ_512K, ++ }, ++}; ++ ++static const struct flash_platform_data dreamplug_spi_slave_data = { ++ .type = "mx25l1606e", ++ .name = "spi_flash", ++ .parts = dreamplug_partitions, ++ .nr_parts = ARRAY_SIZE(dreamplug_partitions), ++}; ++ ++static struct spi_board_info __initdata dreamplug_spi_slave_info[] = { ++ { ++ .modalias = "m25p80", ++ .platform_data = &dreamplug_spi_slave_data, ++ .irq = -1, ++ .max_speed_hz = 50000000, ++ .bus_num = 0, ++ .chip_select = 0, ++ }, ++}; ++ ++static struct mv643xx_eth_platform_data dreamplug_ge00_data = { ++ .phy_addr = MV643XX_ETH_PHY_ADDR(0), ++}; ++ ++static struct mv643xx_eth_platform_data dreamplug_ge01_data = { ++ .phy_addr = MV643XX_ETH_PHY_ADDR(1), ++}; ++ ++static struct mv_sata_platform_data dreamplug_sata_data = { ++ .n_ports = 1, ++}; ++ ++static struct mvsdio_platform_data dreamplug_mvsdio_data = { ++ /* unfortunately the CD signal has not been connected */ ++}; ++ ++static struct gpio_led dreamplug_led_pins[] = { ++ { ++ .name = "dreamplug:blue:bluetooth", ++ .gpio = 47, ++ .active_low = 1, ++ }, ++ { ++ .name = "dreamplug:green:wifi", ++ .gpio = 48, ++ .active_low = 1, ++ }, ++ { ++ .name = "dreamplug:green:wifi_ap", ++ .gpio = 49, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led_platform_data dreamplug_led_data = { ++ .leds = dreamplug_led_pins, ++ .num_leds = ARRAY_SIZE(dreamplug_led_pins), ++}; ++ ++static struct platform_device dreamplug_leds = { ++ .name = "leds-gpio", ++ .id = -1, ++ .dev = { ++ .platform_data = &dreamplug_led_data, ++ } ++}; ++ ++static unsigned int dreamplug_mpp_config[] __initdata = { ++ MPP0_SPI_SCn, ++ MPP1_SPI_MOSI, ++ MPP2_SPI_SCK, ++ MPP3_SPI_MISO, ++ MPP47_GPIO, /* Bluetooth LED */ ++ MPP48_GPIO, /* Wifi LED */ ++ MPP49_GPIO, /* Wifi AP LED */ ++ 0 ++}; ++ ++void __init dreamplug_init(void) ++{ ++ /* ++ * Basic setup. Needs to be called early. ++ */ ++ kirkwood_mpp_conf(dreamplug_mpp_config); ++ ++ spi_register_board_info(dreamplug_spi_slave_info, ++ ARRAY_SIZE(dreamplug_spi_slave_info)); ++ kirkwood_spi_init(); ++ ++ kirkwood_ehci_init(); ++ kirkwood_ge00_init(&dreamplug_ge00_data); ++ kirkwood_ge01_init(&dreamplug_ge01_data); ++ kirkwood_sata_init(&dreamplug_sata_data); ++ kirkwood_sdio_init(&dreamplug_mvsdio_data); ++ ++ platform_device_register(&dreamplug_leds); ++} +diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c +new file mode 100644 +index 0000000..4302b0c +--- /dev/null ++++ b/arch/arm/mach-kirkwood/board-dt.c +@@ -0,0 +1,79 @@ ++/* ++ * Copyright 2012 (C), Jason Cooper ++ * ++ * arch/arm/mach-kirkwood/board-dt.c ++ * ++ * Flattened Device Tree board initialization ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "common.h" ++ ++static struct of_device_id kirkwood_dt_match_table[] __initdata = { ++ { .compatible = "simple-bus", }, ++ { } ++}; ++ ++static void __init kirkwood_dt_init(void) ++{ ++ pr_info("Kirkwood: %s, TCLK=%d.\n", kirkwood_id(), kirkwood_tclk); ++ ++ /* ++ * Disable propagation of mbus errors to the CPU local bus, ++ * as this causes mbus errors (which can occur for example ++ * for PCI aborts) to throw CPU aborts, which we're not set ++ * up to deal with. ++ */ ++ writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG); ++ ++ kirkwood_setup_cpu_mbus(); ++ ++#ifdef CONFIG_CACHE_FEROCEON_L2 ++ kirkwood_l2_init(); ++#endif ++ ++ /* internal devices that every board has */ ++ kirkwood_wdt_init(); ++ kirkwood_xor0_init(); ++ kirkwood_xor1_init(); ++ kirkwood_crypto_init(); ++ ++#ifdef CONFIG_KEXEC ++ kexec_reinit = kirkwood_enable_pcie; ++#endif ++ ++ if (of_machine_is_compatible("globalscale,dreamplug")) ++ dreamplug_init(); ++ ++ if (of_machine_is_compatible("iom,iconnect")) ++ iconnect_init(); ++ ++ of_platform_populate(NULL, kirkwood_dt_match_table, NULL, NULL); ++} ++ ++static const char *kirkwood_dt_board_compat[] = { ++ "globalscale,dreamplug", ++ "iom,iconnect", ++ NULL ++}; ++ ++DT_MACHINE_START(KIRKWOOD_DT, "Marvell Kirkwood (Flattened Device Tree)") ++ /* Maintainer: Jason Cooper */ ++ .map_io = kirkwood_map_io, ++ .init_early = kirkwood_init_early, ++ .init_irq = kirkwood_init_irq, ++ .timer = &kirkwood_timer, ++ .init_machine = kirkwood_dt_init, ++ .dt_compat = kirkwood_dt_board_compat, ++MACHINE_END +diff --git a/arch/arm/mach-kirkwood/board-iconnect.c b/arch/arm/mach-kirkwood/board-iconnect.c +new file mode 100644 +index 0000000..2222c57 +--- /dev/null ++++ b/arch/arm/mach-kirkwood/board-iconnect.c +@@ -0,0 +1,165 @@ ++/* ++ * arch/arm/mach-kirkwood/board-iconnect.c ++ * ++ * Iomega i-connect Board Setup ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "common.h" ++#include "mpp.h" ++ ++static struct mv643xx_eth_platform_data iconnect_ge00_data = { ++ .phy_addr = MV643XX_ETH_PHY_ADDR(11), ++}; ++ ++static struct gpio_led iconnect_led_pins[] = { ++ { ++ .name = "led_level", ++ .gpio = 41, ++ .default_trigger = "default-on", ++ }, { ++ .name = "power:blue", ++ .gpio = 42, ++ .default_trigger = "timer", ++ }, { ++ .name = "power:red", ++ .gpio = 43, ++ }, { ++ .name = "usb1:blue", ++ .gpio = 44, ++ }, { ++ .name = "usb2:blue", ++ .gpio = 45, ++ }, { ++ .name = "usb3:blue", ++ .gpio = 46, ++ }, { ++ .name = "usb4:blue", ++ .gpio = 47, ++ }, { ++ .name = "otb:blue", ++ .gpio = 48, ++ }, ++}; ++ ++static struct gpio_led_platform_data iconnect_led_data = { ++ .leds = iconnect_led_pins, ++ .num_leds = ARRAY_SIZE(iconnect_led_pins), ++ .gpio_blink_set = orion_gpio_led_blink_set, ++}; ++ ++static struct platform_device iconnect_leds = { ++ .name = "leds-gpio", ++ .id = -1, ++ .dev = { ++ .platform_data = &iconnect_led_data, ++ } ++}; ++ ++static unsigned int iconnect_mpp_config[] __initdata = { ++ MPP12_GPIO, ++ MPP35_GPIO, ++ MPP41_GPIO, ++ MPP42_GPIO, ++ MPP43_GPIO, ++ MPP44_GPIO, ++ MPP45_GPIO, ++ MPP46_GPIO, ++ MPP47_GPIO, ++ MPP48_GPIO, ++ 0 ++}; ++ ++static struct i2c_board_info __initdata iconnect_board_info[] = { ++ { ++ I2C_BOARD_INFO("lm63", 0x4c), ++ }, ++}; ++ ++static struct mtd_partition iconnect_nand_parts[] = { ++ { ++ .name = "flash", ++ .offset = 0, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++ ++/* yikes... theses are the original input buttons */ ++/* but I'm not convinced by the sw event choices */ ++static struct gpio_keys_button iconnect_buttons[] = { ++ { ++ .type = EV_SW, ++ .code = SW_LID, ++ .gpio = 12, ++ .desc = "Reset Button", ++ .active_low = 1, ++ .debounce_interval = 100, ++ }, { ++ .type = EV_SW, ++ .code = SW_TABLET_MODE, ++ .gpio = 35, ++ .desc = "OTB Button", ++ .active_low = 1, ++ .debounce_interval = 100, ++ }, ++}; ++ ++static struct gpio_keys_platform_data iconnect_button_data = { ++ .buttons = iconnect_buttons, ++ .nbuttons = ARRAY_SIZE(iconnect_buttons), ++}; ++ ++static struct platform_device iconnect_button_device = { ++ .name = "gpio-keys", ++ .id = -1, ++ .num_resources = 0, ++ .dev = { ++ .platform_data = &iconnect_button_data, ++ }, ++}; ++ ++void __init iconnect_init(void) ++{ ++ kirkwood_mpp_conf(iconnect_mpp_config); ++ kirkwood_nand_init(ARRAY_AND_SIZE(iconnect_nand_parts), 25); ++ kirkwood_i2c_init(); ++ i2c_register_board_info(0, iconnect_board_info, ++ ARRAY_SIZE(iconnect_board_info)); ++ ++ kirkwood_ehci_init(); ++ kirkwood_ge00_init(&iconnect_ge00_data); ++ ++ platform_device_register(&iconnect_button_device); ++ platform_device_register(&iconnect_leds); ++} ++ ++static int __init iconnect_pci_init(void) ++{ ++ if (of_machine_is_compatible("iom,iconnect")) ++ kirkwood_pcie_init(KW_PCIE0); ++ return 0; ++} ++subsys_initcall(iconnect_pci_init); +diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c +index 06faa97..048408c 100644 +--- a/arch/arm/mach-kirkwood/common.c ++++ b/arch/arm/mach-kirkwood/common.c +@@ -282,7 +282,7 @@ void __init kirkwood_crypto_init(void) + /***************************************************************************** + * XOR0 + ****************************************************************************/ +-static void __init kirkwood_xor0_init(void) ++void __init kirkwood_xor0_init(void) + { + kirkwood_clk_ctrl |= CGC_XOR0; + +@@ -295,7 +295,7 @@ static void __init kirkwood_xor0_init(void) + /***************************************************************************** + * XOR1 + ****************************************************************************/ +-static void __init kirkwood_xor1_init(void) ++void __init kirkwood_xor1_init(void) + { + kirkwood_clk_ctrl |= CGC_XOR1; + +@@ -307,7 +307,7 @@ static void __init kirkwood_xor1_init(void) + /***************************************************************************** + * Watchdog + ****************************************************************************/ +-static void __init kirkwood_wdt_init(void) ++void __init kirkwood_wdt_init(void) + { + orion_wdt_init(kirkwood_tclk); + } +@@ -397,7 +397,7 @@ void __init kirkwood_audio_init(void) + /* + * Identify device ID and revision. + */ +-static char * __init kirkwood_id(void) ++char * __init kirkwood_id(void) + { + u32 dev, rev; + +@@ -431,6 +431,8 @@ static char * __init kirkwood_id(void) + } else if (dev == MV88F6282_DEV_ID) { + if (rev == MV88F6282_REV_A0) + return "MV88F6282-Rev-A0"; ++ else if (rev == MV88F6282_REV_A1) ++ return "MV88F6282-Rev-A1"; + else + return "MV88F6282-Rev-Unsupported"; + } else { +@@ -438,7 +440,7 @@ static char * __init kirkwood_id(void) + } + } + +-static void __init kirkwood_l2_init(void) ++void __init kirkwood_l2_init(void) + { + #ifdef CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH + writel(readl(L2_CONFIG_REG) | L2_WRITETHROUGH, L2_CONFIG_REG); +diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h +index b9b0f09..2397617 100644 +--- a/arch/arm/mach-kirkwood/common.h ++++ b/arch/arm/mach-kirkwood/common.h +@@ -51,6 +51,27 @@ void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay); + void kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts, int (*dev_ready)(struct mtd_info *)); + void kirkwood_audio_init(void); + ++/* board init functions for boards not fully converted to fdt */ ++#ifdef CONFIG_MACH_DREAMPLUG_DT ++void dreamplug_init(void); ++#else ++static inline void dreamplug_init(void) {}; ++#endif ++ ++#ifdef CONFIG_MACH_ICONNECT_DT ++void iconnect_init(void); ++#else ++static inline void iconnect_init(void) {}; ++#endif ++ ++/* early init functions not converted to fdt yet */ ++char *kirkwood_id(void); ++void kirkwood_l2_init(void); ++void kirkwood_wdt_init(void); ++void kirkwood_xor0_init(void); ++void kirkwood_xor1_init(void); ++void kirkwood_crypto_init(void); ++ + extern int kirkwood_tclk; + extern struct sys_timer kirkwood_timer; + +diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h +index 010bdeb..fede3d5 100644 +--- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h ++++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h +@@ -135,4 +135,5 @@ + + #define MV88F6282_DEV_ID 0x6282 + #define MV88F6282_REV_A0 0 ++#define MV88F6282_REV_A1 1 + #endif +diff --git a/arch/arm/mach-kirkwood/mpp.h b/arch/arm/mach-kirkwood/mpp.h +index 7afccf4..d5a0d1d 100644 +--- a/arch/arm/mach-kirkwood/mpp.h ++++ b/arch/arm/mach-kirkwood/mpp.h +@@ -102,6 +102,7 @@ + #define MPP11_SATA0_ACTn MPP( 11, 0x5, 0, 0, 0, 1, 1, 1, 1 ) + + #define MPP12_GPO MPP( 12, 0x0, 0, 1, 1, 1, 1, 1, 1 ) ++#define MPP12_GPIO MPP( 12, 0x0, 1, 1, 0, 0, 0, 1, 0 ) + #define MPP12_SD_CLK MPP( 12, 0x1, 0, 0, 1, 1, 1, 1, 1 ) + #define MPP12_AU_SPDIF0 MPP( 12, 0xa, 0, 0, 0, 0, 0, 0, 1 ) + #define MPP12_SPI_MOSI MPP( 12, 0xb, 0, 0, 0, 0, 0, 0, 1 ) +diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c +index e4cfb7e..1f3da5a 100644 +--- a/arch/arm/mach-netx/xc.c ++++ b/arch/arm/mach-netx/xc.c +@@ -127,10 +127,8 @@ int xc_request_firmware(struct xc *x) + + ret = request_firmware(&fw, name, x->dev); + +- if (ret < 0) { +- dev_err(x->dev, "request_firmware failed\n"); ++ if (ret) + return ret; +- } + + head = (struct fw_header *)fw->data; + if (head->magic != 0x4e657458) { +diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c +index 343f60e..3915dc6 100644 +--- a/arch/arm/mach-orion5x/dns323-setup.c ++++ b/arch/arm/mach-orion5x/dns323-setup.c +@@ -252,27 +252,6 @@ error_fail: + * GPIO LEDs (simple - doesn't use hardware blinking support) + */ + +-#define ORION_BLINK_HALF_PERIOD 100 /* ms */ +- +-static int dns323_gpio_blink_set(unsigned gpio, int state, +- unsigned long *delay_on, unsigned long *delay_off) +-{ +- +- if (delay_on && delay_off && !*delay_on && !*delay_off) +- *delay_on = *delay_off = ORION_BLINK_HALF_PERIOD; +- +- switch(state) { +- case GPIO_LED_NO_BLINK_LOW: +- case GPIO_LED_NO_BLINK_HIGH: +- orion_gpio_set_blink(gpio, 0); +- gpio_set_value(gpio, state); +- break; +- case GPIO_LED_BLINK: +- orion_gpio_set_blink(gpio, 1); +- } +- return 0; +-} +- + static struct gpio_led dns323ab_leds[] = { + { + .name = "power:blue", +@@ -311,13 +290,13 @@ static struct gpio_led dns323c_leds[] = { + static struct gpio_led_platform_data dns323ab_led_data = { + .num_leds = ARRAY_SIZE(dns323ab_leds), + .leds = dns323ab_leds, +- .gpio_blink_set = dns323_gpio_blink_set, ++ .gpio_blink_set = orion_gpio_led_blink_set, + }; + + static struct gpio_led_platform_data dns323c_led_data = { + .num_leds = ARRAY_SIZE(dns323c_leds), + .leds = dns323c_leds, +- .gpio_blink_set = dns323_gpio_blink_set, ++ .gpio_blink_set = orion_gpio_led_blink_set, + }; + + static struct platform_device dns323_gpio_leds = { +diff --git a/arch/arm/mach-pxa/include/mach/entry-macro.S b/arch/arm/mach-pxa/include/mach/entry-macro.S +index a73bc86..db7c433 100644 +--- a/arch/arm/mach-pxa/include/mach/entry-macro.S ++++ b/arch/arm/mach-pxa/include/mach/entry-macro.S +@@ -7,45 +7,5 @@ + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ +-#include +-#include +- + .macro disable_fiq + .endm +- +- .macro get_irqnr_preamble, base, tmp +- .endm +- +- .macro arch_ret_to_user, tmp1, tmp2 +- .endm +- +- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp +- mrc p15, 0, \tmp, c0, c0, 0 @ CPUID +- mov \tmp, \tmp, lsr #13 +- and \tmp, \tmp, #0x7 @ Core G +- cmp \tmp, #1 +- bhi 1002f +- +- @ Core Generation 1 (PXA25x) +- mov \base, #io_p2v(0x40000000) @ IIR Ctl = 0x40d00000 +- add \base, \base, #0x00d00000 +- ldr \irqstat, [\base, #0] @ ICIP +- ldr \irqnr, [\base, #4] @ ICMR +- +- ands \irqnr, \irqstat, \irqnr +- beq 1001f +- rsb \irqstat, \irqnr, #0 +- and \irqstat, \irqstat, \irqnr +- clz \irqnr, \irqstat +- rsb \irqnr, \irqnr, #(31 + PXA_IRQ(0)) +- b 1001f +-1002: +- @ Core Generation 2 (PXA27x) or Core Generation 3 (PXA3xx) +- mrc p6, 0, \irqstat, c5, c0, 0 @ ICHP +- tst \irqstat, #0x80000000 +- beq 1001f +- bic \irqstat, \irqstat, #0x80000000 +- mov \irqnr, \irqstat, lsr #16 +- add \irqnr, \irqnr, #(PXA_IRQ(0)) +-1001: +- .endm +diff --git a/arch/arm/mach-shmobile/include/mach/entry-macro.S b/arch/arm/mach-shmobile/include/mach/entry-macro.S +index 8d4a416..2b78361 100644 +--- a/arch/arm/mach-shmobile/include/mach/entry-macro.S ++++ b/arch/arm/mach-shmobile/include/mach/entry-macro.S +@@ -17,15 +17,3 @@ + + .macro disable_fiq + .endm +- +- .macro get_irqnr_preamble, base, tmp +- .endm +- +- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp +- .endm +- +- .macro test_for_ipi, irqnr, irqstat, base, tmp +- .endm +- +- .macro arch_ret_to_user, tmp1, tmp2 +- .endm +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index 4e1ef6e..c0bdd50 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -821,7 +821,8 @@ config CACHE_L2X0 + REALVIEW_EB_A9MP || ARCH_IMX_V6_V7 || MACH_REALVIEW_PBX || \ + ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \ + ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || \ +- ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX || ARCH_HIGHBANK ++ ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX || ARCH_HIGHBANK || \ ++ ARCH_IPROC + default y + select OUTER_CACHE + select OUTER_CACHE_SYNC +diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c +index cc3f35d..ee3a9f1 100644 +--- a/arch/arm/mm/init.c ++++ b/arch/arm/mm/init.c +@@ -406,8 +406,6 @@ void __init bootmem_init(void) + */ + arm_bootmem_free(min, max_low, max_high); + +- high_memory = __va(((phys_addr_t)max_low << PAGE_SHIFT) - 1) + 1; +- + /* + * This doesn't seem to be used by the Linux memory manager any + * more, but is used by ll_rw_block. If we can get rid of it, we +diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c +index bdb248c..0bf7e90 100644 +--- a/arch/arm/mm/ioremap.c ++++ b/arch/arm/mm/ioremap.c +@@ -36,12 +36,6 @@ + #include + #include "mm.h" + +-/* +- * Used by ioremap() and iounmap() code to mark (super)section-mapped +- * I/O regions in vm_struct->flags field. +- */ +-#define VM_ARM_SECTION_MAPPING 0x80000000 +- + int ioremap_page(unsigned long virt, unsigned long phys, + const struct mem_type *mtype) + { +@@ -201,12 +195,6 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, + if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK)) + return NULL; + +- /* +- * Don't allow RAM to be mapped - this causes problems with ARMv6+ +- */ +- if (WARN_ON(pfn_valid(pfn))) +- return NULL; +- + type = get_mem_type(mtype); + if (!type) + return NULL; +@@ -216,6 +204,38 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, + */ + size = PAGE_ALIGN(offset + size); + ++ /* ++ * Try to reuse one of the static mapping whenever possible. ++ */ ++ read_lock(&vmlist_lock); ++ for (area = vmlist; area; area = area->next) { ++ if (!size || (sizeof(phys_addr_t) == 4 && pfn >= 0x100000)) ++ break; ++ if (!(area->flags & VM_ARM_STATIC_MAPPING)) ++ continue; ++ if ((area->flags & VM_ARM_MTYPE_MASK) != VM_ARM_MTYPE(mtype)) ++ continue; ++ if (__phys_to_pfn(area->phys_addr) > pfn || ++ __pfn_to_phys(pfn) + size-1 > area->phys_addr + area->size-1) ++ continue; ++ /* we can drop the lock here as we know *area is static */ ++ read_unlock(&vmlist_lock); ++ addr = (unsigned long)area->addr; ++ addr += __pfn_to_phys(pfn) - area->phys_addr; ++ return (void __iomem *) (offset + addr); ++ } ++ read_unlock(&vmlist_lock); ++ ++ /* ++ * Don't allow RAM to be mapped - this causes problems with ARMv6+ ++ */ ++#ifdef CONFIG_ARCH_IPROC ++#warning "ioremap test for remapping RAM has been disabled for IPROC" ++#else ++ if (WARN_ON(pfn_valid(pfn))) ++ return NULL; ++#endif ++ + area = get_vm_area_caller(size, VM_IOREMAP, caller); + if (!area) + return NULL; +@@ -313,29 +333,43 @@ __arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached) + void __iounmap(volatile void __iomem *io_addr) + { + void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); +-#ifndef CONFIG_SMP +- struct vm_struct **p, *tmp; ++ struct vm_struct *vm; + +- /* +- * If this is a section based mapping we need to handle it +- * specially as the VM subsystem does not know how to handle +- * such a beast. We need the lock here b/c we need to clear +- * all the mappings before the area can be reclaimed +- * by someone else. +- */ +- write_lock(&vmlist_lock); +- for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) { +- if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) { +- if (tmp->flags & VM_ARM_SECTION_MAPPING) { +- unmap_area_sections((unsigned long)tmp->addr, +- tmp->size); +- } ++ read_lock(&vmlist_lock); ++ for (vm = vmlist; vm; vm = vm->next) { ++ if (vm->addr > addr) ++ break; ++ if (!(vm->flags & VM_IOREMAP)) ++ continue; ++ /* If this is a static mapping we must leave it alone */ ++ if ((vm->flags & VM_ARM_STATIC_MAPPING) && ++ (vm->addr <= addr) && (vm->addr + vm->size > addr)) { ++ read_unlock(&vmlist_lock); ++ return; ++ } ++#if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE) ++ /* ++ * If this is a section based mapping we need to handle it ++ * specially as the VM subsystem does not know how to handle ++ * such a beast. ++ */ ++ if ((vm->addr == addr) && ++ (vm->flags & VM_ARM_SECTION_MAPPING)) { ++ unmap_area_sections((unsigned long)vm->addr, vm->size); + break; + } +- } +- write_unlock(&vmlist_lock); + #endif ++ } ++ read_unlock(&vmlist_lock); + + vunmap(addr); + } ++ ++void (*arch_iounmap)(volatile void __iomem *) = __iounmap; ++ ++void __arm_iounmap(volatile void __iomem *io_addr) ++{ ++ arch_iounmap(io_addr); ++} + EXPORT_SYMBOL(__iounmap); ++EXPORT_SYMBOL(__arm_iounmap); +diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h +index ad7cce3..70f6d3ea 100644 +--- a/arch/arm/mm/mm.h ++++ b/arch/arm/mm/mm.h +@@ -21,6 +21,20 @@ const struct mem_type *get_mem_type(unsigned int type); + + extern void __flush_dcache_page(struct address_space *mapping, struct page *page); + ++/* ++ * ARM specific vm_struct->flags bits. ++ */ ++ ++/* (super)section-mapped I/O regions used by ioremap()/iounmap() */ ++#define VM_ARM_SECTION_MAPPING 0x80000000 ++ ++/* permanent static mappings from iotable_init() */ ++#define VM_ARM_STATIC_MAPPING 0x40000000 ++ ++/* mapping type (attributes) for permanent static mappings */ ++#define VM_ARM_MTYPE(mt) ((mt) << 20) ++#define VM_ARM_MTYPE_MASK (0x1f << 20) ++ + #endif + + #ifdef CONFIG_ZONE_DMA +diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c +index 44b628e..ce8cb19 100644 +--- a/arch/arm/mm/mmap.c ++++ b/arch/arm/mm/mmap.c +@@ -11,10 +11,49 @@ + #include + #include + ++static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr, ++ unsigned long pgoff) ++{ ++ unsigned long base = addr & ~(SHMLBA-1); ++ unsigned long off = (pgoff << PAGE_SHIFT) & (SHMLBA-1); ++ ++ if (base + off <= addr) ++ return base + off; ++ ++ return base - off; ++} ++ + #define COLOUR_ALIGN(addr,pgoff) \ + ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \ + (((pgoff)<personality & ADDR_COMPAT_LAYOUT) ++ return 1; ++ ++ if (rlimit(RLIMIT_STACK) == RLIM_INFINITY) ++ return 1; ++ ++ return sysctl_legacy_va_layout; ++} ++ ++static unsigned long mmap_base(unsigned long rnd) ++{ ++ unsigned long gap = rlimit(RLIMIT_STACK); ++ ++ if (gap < MIN_GAP) ++ gap = MIN_GAP; ++ else if (gap > MAX_GAP) ++ gap = MAX_GAP; ++ ++ return PAGE_ALIGN(TASK_SIZE - gap - rnd); ++} ++ + /* + * We need to ensure that shared mappings are correctly aligned to + * avoid aliasing issues with VIPT caches. We need to ensure that +@@ -68,13 +107,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + if (len > mm->cached_hole_size) { + start_addr = addr = mm->free_area_cache; + } else { +- start_addr = addr = TASK_UNMAPPED_BASE; ++ start_addr = addr = mm->mmap_base; + mm->cached_hole_size = 0; + } +- /* 8 bits of randomness in 20 address space bits */ +- if ((current->flags & PF_RANDOMIZE) && +- !(current->personality & ADDR_NO_RANDOMIZE)) +- addr += (get_random_int() % (1 << 8)) << PAGE_SHIFT; + + full_search: + if (do_align) +@@ -111,6 +146,134 @@ full_search: + } + } + ++unsigned long ++arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, ++ const unsigned long len, const unsigned long pgoff, ++ const unsigned long flags) ++{ ++ struct vm_area_struct *vma; ++ struct mm_struct *mm = current->mm; ++ unsigned long addr = addr0; ++ int do_align = 0; ++ int aliasing = cache_is_vipt_aliasing(); ++ ++ /* ++ * We only need to do colour alignment if either the I or D ++ * caches alias. ++ */ ++ if (aliasing) ++ do_align = filp || (flags & MAP_SHARED); ++ ++ /* requested length too big for entire address space */ ++ if (len > TASK_SIZE) ++ return -ENOMEM; ++ ++ if (flags & MAP_FIXED) { ++ if (aliasing && flags & MAP_SHARED && ++ (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)) ++ return -EINVAL; ++ return addr; ++ } ++ ++ /* requesting a specific address */ ++ if (addr) { ++ if (do_align) ++ addr = COLOUR_ALIGN(addr, pgoff); ++ else ++ addr = PAGE_ALIGN(addr); ++ vma = find_vma(mm, addr); ++ if (TASK_SIZE - len >= addr && ++ (!vma || addr + len <= vma->vm_start)) ++ return addr; ++ } ++ ++ /* check if free_area_cache is useful for us */ ++ if (len <= mm->cached_hole_size) { ++ mm->cached_hole_size = 0; ++ mm->free_area_cache = mm->mmap_base; ++ } ++ ++ /* either no address requested or can't fit in requested address hole */ ++ addr = mm->free_area_cache; ++ if (do_align) { ++ unsigned long base = COLOUR_ALIGN_DOWN(addr - len, pgoff); ++ addr = base + len; ++ } ++ ++ /* make sure it can fit in the remaining address space */ ++ if (addr > len) { ++ vma = find_vma(mm, addr-len); ++ if (!vma || addr <= vma->vm_start) ++ /* remember the address as a hint for next time */ ++ return (mm->free_area_cache = addr-len); ++ } ++ ++ if (mm->mmap_base < len) ++ goto bottomup; ++ ++ addr = mm->mmap_base - len; ++ if (do_align) ++ addr = COLOUR_ALIGN_DOWN(addr, pgoff); ++ ++ do { ++ /* ++ * Lookup failure means no vma is above this address, ++ * else if new region fits below vma->vm_start, ++ * return with success: ++ */ ++ vma = find_vma(mm, addr); ++ if (!vma || addr+len <= vma->vm_start) ++ /* remember the address as a hint for next time */ ++ return (mm->free_area_cache = addr); ++ ++ /* remember the largest hole we saw so far */ ++ if (addr + mm->cached_hole_size < vma->vm_start) ++ mm->cached_hole_size = vma->vm_start - addr; ++ ++ /* try just below the current vma->vm_start */ ++ addr = vma->vm_start - len; ++ if (do_align) ++ addr = COLOUR_ALIGN_DOWN(addr, pgoff); ++ } while (len < vma->vm_start); ++ ++bottomup: ++ /* ++ * A failed mmap() very likely causes application failure, ++ * so fall back to the bottom-up function here. This scenario ++ * can happen with large stack limits and large mmap() ++ * allocations. ++ */ ++ mm->cached_hole_size = ~0UL; ++ mm->free_area_cache = TASK_UNMAPPED_BASE; ++ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); ++ /* ++ * Restore the topdown base: ++ */ ++ mm->free_area_cache = mm->mmap_base; ++ mm->cached_hole_size = ~0UL; ++ ++ return addr; ++} ++ ++void arch_pick_mmap_layout(struct mm_struct *mm) ++{ ++ unsigned long random_factor = 0UL; ++ ++ /* 8 bits of randomness in 20 address space bits */ ++ if ((current->flags & PF_RANDOMIZE) && ++ !(current->personality & ADDR_NO_RANDOMIZE)) ++ random_factor = (get_random_int() % (1 << 8)) << PAGE_SHIFT; ++ ++ if (mmap_is_legacy()) { ++ mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; ++ mm->get_unmapped_area = arch_get_unmapped_area; ++ mm->unmap_area = arch_unmap_area; ++ } else { ++ mm->mmap_base = mmap_base(random_factor); ++ mm->get_unmapped_area = arch_get_unmapped_area_topdown; ++ mm->unmap_area = arch_unmap_area_topdown; ++ } ++} + + /* + * You really shouldn't be using read() or write() on /dev/mem. This +diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c +index 082fa18..704031c 100644 +--- a/arch/arm/mm/mmu.c ++++ b/arch/arm/mm/mmu.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -537,13 +538,18 @@ EXPORT_SYMBOL(phys_mem_access_prot); + + #define vectors_base() (vectors_high() ? 0xffff0000 : 0) + +-static void __init *early_alloc(unsigned long sz) ++static void __init *early_alloc_aligned(unsigned long sz, unsigned long align) + { +- void *ptr = __va(memblock_alloc(sz, sz)); ++ void *ptr = __va(memblock_alloc(sz, align)); + memset(ptr, 0, sz); + return ptr; + } + ++static void __init *early_alloc(unsigned long sz) ++{ ++ return early_alloc_aligned(sz, sz); ++} ++ + static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot) + { + if (pmd_none(*pmd)) { +@@ -693,9 +699,10 @@ static void __init create_mapping(struct map_desc *md) + } + + if ((md->type == MT_DEVICE || md->type == MT_ROM) && +- md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) { ++ md->virtual >= PAGE_OFFSET && ++ (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) { + printk(KERN_WARNING "BUG: mapping for 0x%08llx" +- " at 0x%08lx overlaps vmalloc space\n", ++ " at 0x%08lx out of vmalloc space\n", + (long long)__pfn_to_phys((u64)md->pfn), md->virtual); + } + +@@ -737,18 +744,34 @@ static void __init create_mapping(struct map_desc *md) + */ + void __init iotable_init(struct map_desc *io_desc, int nr) + { +- int i; +- +- for (i = 0; i < nr; i++) +- create_mapping(io_desc + i); ++ struct map_desc *md; ++ struct vm_struct *vm; ++ ++ if (!nr) ++ return; ++ ++ vm = early_alloc_aligned(sizeof(*vm) * nr, __alignof__(*vm)); ++ ++ for (md = io_desc; nr; md++, nr--) { ++ create_mapping(md); ++ vm->addr = (void *)(md->virtual & PAGE_MASK); ++ vm->size = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK)); ++ vm->phys_addr = __pfn_to_phys(md->pfn); ++ vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING; ++ vm->flags |= VM_ARM_MTYPE(md->type); ++ vm->caller = iotable_init; ++ vm_area_add_early(vm++); ++ } + } + +-static void * __initdata vmalloc_min = (void *)(VMALLOC_END - SZ_128M); ++ ++static void * __initdata vmalloc_min = ++ (void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET); + + /* + * vmalloc=size forces the vmalloc area to be exactly 'size' + * bytes. This can be used to increase (or decrease) the vmalloc +- * area - the default is 128m. ++ * area - the default is 240m. + */ + static int __init early_vmalloc(char *arg) + { +@@ -868,7 +891,8 @@ void __init sanity_check_meminfo(void) + } + #endif + meminfo.nr_banks = j; +- memblock_set_current_limit(lowmem_limit); ++ high_memory = __va(lowmem_limit - 1) + 1; ++ memblock_set_current_limit(lowmem_limit); + } + + static inline void prepare_page_table(void) +@@ -898,10 +922,10 @@ static inline void prepare_page_table(void) + + /* + * Clear out all the kernel space mappings, except for the first +- * memory bank, up to the end of the vmalloc region. ++ * memory bank, up to the vmalloc region. + */ + for (addr = __phys_to_virt(end); +- addr < VMALLOC_END; addr += PMD_SIZE) ++ addr < VMALLOC_START; addr += PMD_SIZE) + pmd_clear(pmd_off_k(addr)); + } + +diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c +index a5018fb..13d8194 100644 +--- a/arch/arm/mm/nommu.c ++++ b/arch/arm/mm/nommu.c +@@ -29,6 +29,8 @@ void __init arm_mm_memblock_reserve(void) + + void __init sanity_check_meminfo(void) + { ++ phys_addr_t end = bank_phys_end(&meminfo.bank[meminfo.nr_banks - 1]); ++ high_memory = __va(end - 1) + 1; + } + + /* +diff --git a/arch/arm/net/Makefile b/arch/arm/net/Makefile +new file mode 100644 +index 0000000..c2c1084 +--- /dev/null ++++ b/arch/arm/net/Makefile +@@ -0,0 +1,3 @@ ++# ARM-specific networking code ++ ++obj-$(CONFIG_BPF_JIT) += bpf_jit_32.o +diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c +new file mode 100644 +index 0000000..62135849 +--- /dev/null ++++ b/arch/arm/net/bpf_jit_32.c +@@ -0,0 +1,915 @@ ++/* ++ * Just-In-Time compiler for BPF filters on 32bit ARM ++ * ++ * Copyright (c) 2011 Mircea Gherzan ++ * ++ * This program is free software; 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "bpf_jit_32.h" ++ ++/* ++ * ABI: ++ * ++ * r0 scratch register ++ * r4 BPF register A ++ * r5 BPF register X ++ * r6 pointer to the skb ++ * r7 skb->data ++ * r8 skb_headlen(skb) ++ */ ++ ++#define r_scratch ARM_R0 ++/* r1-r3 are (also) used for the unaligned loads on the non-ARMv7 slowpath */ ++#define r_off ARM_R1 ++#define r_A ARM_R4 ++#define r_X ARM_R5 ++#define r_skb ARM_R6 ++#define r_skb_data ARM_R7 ++#define r_skb_hl ARM_R8 ++ ++#define SCRATCH_SP_OFFSET 0 ++#define SCRATCH_OFF(k) (SCRATCH_SP_OFFSET + (k)) ++ ++#define SEEN_MEM ((1 << BPF_MEMWORDS) - 1) ++#define SEEN_MEM_WORD(k) (1 << (k)) ++#define SEEN_X (1 << BPF_MEMWORDS) ++#define SEEN_CALL (1 << (BPF_MEMWORDS + 1)) ++#define SEEN_SKB (1 << (BPF_MEMWORDS + 2)) ++#define SEEN_DATA (1 << (BPF_MEMWORDS + 3)) ++ ++#define FLAG_NEED_X_RESET (1 << 0) ++ ++struct jit_ctx { ++ const struct sk_filter *skf; ++ unsigned idx; ++ unsigned prologue_bytes; ++ int ret0_fp_idx; ++ u32 seen; ++ u32 flags; ++ u32 *offsets; ++ u32 *target; ++#if __LINUX_ARM_ARCH__ < 7 ++ u16 epilogue_bytes; ++ u16 imm_count; ++ u32 *imms; ++#endif ++}; ++ ++int bpf_jit_enable __read_mostly; ++ ++static u64 jit_get_skb_b(struct sk_buff *skb, unsigned offset) ++{ ++ u8 ret; ++ int err; ++ ++ err = skb_copy_bits(skb, offset, &ret, 1); ++ ++ return (u64)err << 32 | ret; ++} ++ ++static u64 jit_get_skb_h(struct sk_buff *skb, unsigned offset) ++{ ++ u16 ret; ++ int err; ++ ++ err = skb_copy_bits(skb, offset, &ret, 2); ++ ++ return (u64)err << 32 | ntohs(ret); ++} ++ ++static u64 jit_get_skb_w(struct sk_buff *skb, unsigned offset) ++{ ++ u32 ret; ++ int err; ++ ++ err = skb_copy_bits(skb, offset, &ret, 4); ++ ++ return (u64)err << 32 | ntohl(ret); ++} ++ ++/* ++ * Wrapper that handles both OABI and EABI and assures Thumb2 interworking ++ * (where the assembly routines like __aeabi_uidiv could cause problems). ++ */ ++static u32 jit_udiv(u32 dividend, u32 divisor) ++{ ++ return dividend / divisor; ++} ++ ++static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx) ++{ ++ if (ctx->target != NULL) ++ ctx->target[ctx->idx] = inst | (cond << 28); ++ ++ ctx->idx++; ++} ++ ++/* ++ * Emit an instruction that will be executed unconditionally. ++ */ ++static inline void emit(u32 inst, struct jit_ctx *ctx) ++{ ++ _emit(ARM_COND_AL, inst, ctx); ++} ++ ++static u16 saved_regs(struct jit_ctx *ctx) ++{ ++ u16 ret = 0; ++ ++ if ((ctx->skf->len > 1) || ++ (ctx->skf->insns[0].code == BPF_S_RET_A)) ++ ret |= 1 << r_A; ++ ++#ifdef CONFIG_FRAME_POINTER ++ ret |= (1 << ARM_FP) | (1 << ARM_IP) | (1 << ARM_LR) | (1 << ARM_PC); ++#else ++ if (ctx->seen & SEEN_CALL) ++ ret |= 1 << ARM_LR; ++#endif ++ if (ctx->seen & (SEEN_DATA | SEEN_SKB)) ++ ret |= 1 << r_skb; ++ if (ctx->seen & SEEN_DATA) ++ ret |= (1 << r_skb_data) | (1 << r_skb_hl); ++ if (ctx->seen & SEEN_X) ++ ret |= 1 << r_X; ++ ++ return ret; ++} ++ ++static inline int mem_words_used(struct jit_ctx *ctx) ++{ ++ /* yes, we do waste some stack space IF there are "holes" in the set" */ ++ return fls(ctx->seen & SEEN_MEM); ++} ++ ++static inline bool is_load_to_a(u16 inst) ++{ ++ switch (inst) { ++ case BPF_S_LD_W_LEN: ++ case BPF_S_LD_W_ABS: ++ case BPF_S_LD_H_ABS: ++ case BPF_S_LD_B_ABS: ++ case BPF_S_ANC_CPU: ++ case BPF_S_ANC_IFINDEX: ++ case BPF_S_ANC_MARK: ++ case BPF_S_ANC_PROTOCOL: ++ case BPF_S_ANC_RXHASH: ++ case BPF_S_ANC_QUEUE: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static void build_prologue(struct jit_ctx *ctx) ++{ ++ u16 reg_set = saved_regs(ctx); ++ u16 first_inst = ctx->skf->insns[0].code; ++ u16 off; ++ ++#ifdef CONFIG_FRAME_POINTER ++ emit(ARM_MOV_R(ARM_IP, ARM_SP), ctx); ++ emit(ARM_PUSH(reg_set), ctx); ++ emit(ARM_SUB_I(ARM_FP, ARM_IP, 4), ctx); ++#else ++ if (reg_set) ++ emit(ARM_PUSH(reg_set), ctx); ++#endif ++ ++ if (ctx->seen & (SEEN_DATA | SEEN_SKB)) ++ emit(ARM_MOV_R(r_skb, ARM_R0), ctx); ++ ++ if (ctx->seen & SEEN_DATA) { ++ off = offsetof(struct sk_buff, data); ++ emit(ARM_LDR_I(r_skb_data, r_skb, off), ctx); ++ /* headlen = len - data_len */ ++ off = offsetof(struct sk_buff, len); ++ emit(ARM_LDR_I(r_skb_hl, r_skb, off), ctx); ++ off = offsetof(struct sk_buff, data_len); ++ emit(ARM_LDR_I(r_scratch, r_skb, off), ctx); ++ emit(ARM_SUB_R(r_skb_hl, r_skb_hl, r_scratch), ctx); ++ } ++ ++ if (ctx->flags & FLAG_NEED_X_RESET) ++ emit(ARM_MOV_I(r_X, 0), ctx); ++ ++ /* do not leak kernel data to userspace */ ++ if ((first_inst != BPF_S_RET_K) && !(is_load_to_a(first_inst))) ++ emit(ARM_MOV_I(r_A, 0), ctx); ++ ++ /* stack space for the BPF_MEM words */ ++ if (ctx->seen & SEEN_MEM) ++ emit(ARM_SUB_I(ARM_SP, ARM_SP, mem_words_used(ctx) * 4), ctx); ++} ++ ++static void build_epilogue(struct jit_ctx *ctx) ++{ ++ u16 reg_set = saved_regs(ctx); ++ ++ if (ctx->seen & SEEN_MEM) ++ emit(ARM_ADD_I(ARM_SP, ARM_SP, mem_words_used(ctx) * 4), ctx); ++ ++ reg_set &= ~(1 << ARM_LR); ++ ++#ifdef CONFIG_FRAME_POINTER ++ /* the first instruction of the prologue was: mov ip, sp */ ++ reg_set &= ~(1 << ARM_IP); ++ reg_set |= (1 << ARM_SP); ++ emit(ARM_LDM(ARM_SP, reg_set), ctx); ++#else ++ if (reg_set) { ++ if (ctx->seen & SEEN_CALL) ++ reg_set |= 1 << ARM_PC; ++ emit(ARM_POP(reg_set), ctx); ++ } ++ ++ if (!(ctx->seen & SEEN_CALL)) ++ emit(ARM_BX(ARM_LR), ctx); ++#endif ++} ++ ++static int16_t imm8m(u32 x) ++{ ++ u32 rot; ++ ++ for (rot = 0; rot < 16; rot++) ++ if ((x & ~ror32(0xff, 2 * rot)) == 0) ++ return rol32(x, 2 * rot) | (rot << 8); ++ ++ return -1; ++} ++ ++#if __LINUX_ARM_ARCH__ < 7 ++ ++static u16 imm_offset(u32 k, struct jit_ctx *ctx) ++{ ++ unsigned i = 0, offset; ++ u16 imm; ++ ++ /* on the "fake" run we just count them (duplicates included) */ ++ if (ctx->target == NULL) { ++ ctx->imm_count++; ++ return 0; ++ } ++ ++ while ((i < ctx->imm_count) && ctx->imms[i]) { ++ if (ctx->imms[i] == k) ++ break; ++ i++; ++ } ++ ++ if (ctx->imms[i] == 0) ++ ctx->imms[i] = k; ++ ++ /* constants go just after the epilogue */ ++ offset = ctx->offsets[ctx->skf->len]; ++ offset += ctx->prologue_bytes; ++ offset += ctx->epilogue_bytes; ++ offset += i * 4; ++ ++ ctx->target[offset / 4] = k; ++ ++ /* PC in ARM mode == address of the instruction + 8 */ ++ imm = offset - (8 + ctx->idx * 4); ++ ++ return imm; ++} ++ ++#endif /* __LINUX_ARM_ARCH__ */ ++ ++/* ++ * Move an immediate that's not an imm8m to a core register. ++ */ ++static inline void emit_mov_i_no8m(int rd, u32 val, struct jit_ctx *ctx) ++{ ++#if __LINUX_ARM_ARCH__ < 7 ++ emit(ARM_LDR_I(rd, ARM_PC, imm_offset(val, ctx)), ctx); ++#else ++ emit(ARM_MOVW(rd, val & 0xffff), ctx); ++ if (val > 0xffff) ++ emit(ARM_MOVT(rd, val >> 16), ctx); ++#endif ++} ++ ++static inline void emit_mov_i(int rd, u32 val, struct jit_ctx *ctx) ++{ ++ int imm12 = imm8m(val); ++ ++ if (imm12 >= 0) ++ emit(ARM_MOV_I(rd, imm12), ctx); ++ else ++ emit_mov_i_no8m(rd, val, ctx); ++} ++ ++#if __LINUX_ARM_ARCH__ < 6 ++ ++static void emit_load_be32(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx) ++{ ++ _emit(cond, ARM_LDRB_I(ARM_R3, r_addr, 1), ctx); ++ _emit(cond, ARM_LDRB_I(ARM_R1, r_addr, 0), ctx); ++ _emit(cond, ARM_LDRB_I(ARM_R2, r_addr, 3), ctx); ++ _emit(cond, ARM_LSL_I(ARM_R3, ARM_R3, 16), ctx); ++ _emit(cond, ARM_LDRB_I(ARM_R0, r_addr, 2), ctx); ++ _emit(cond, ARM_ORR_S(ARM_R3, ARM_R3, ARM_R1, SRTYPE_LSL, 24), ctx); ++ _emit(cond, ARM_ORR_R(ARM_R3, ARM_R3, ARM_R2), ctx); ++ _emit(cond, ARM_ORR_S(r_res, ARM_R3, ARM_R0, SRTYPE_LSL, 8), ctx); ++} ++ ++static void emit_load_be16(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx) ++{ ++ _emit(cond, ARM_LDRB_I(ARM_R1, r_addr, 0), ctx); ++ _emit(cond, ARM_LDRB_I(ARM_R2, r_addr, 1), ctx); ++ _emit(cond, ARM_ORR_S(r_res, ARM_R2, ARM_R1, SRTYPE_LSL, 8), ctx); ++} ++ ++static inline void emit_swap16(u8 r_dst, u8 r_src, struct jit_ctx *ctx) ++{ ++ emit(ARM_LSL_R(ARM_R1, r_src, 8), ctx); ++ emit(ARM_ORR_S(r_dst, ARM_R1, r_src, SRTYPE_LSL, 8), ctx); ++ emit(ARM_LSL_I(r_dst, r_dst, 8), ctx); ++ emit(ARM_LSL_R(r_dst, r_dst, 8), ctx); ++} ++ ++#else /* ARMv6+ */ ++ ++static void emit_load_be32(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx) ++{ ++ _emit(cond, ARM_LDR_I(r_res, r_addr, 0), ctx); ++#ifdef __LITTLE_ENDIAN ++ _emit(cond, ARM_REV(r_res, r_res), ctx); ++#endif ++} ++ ++static void emit_load_be16(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx) ++{ ++ _emit(cond, ARM_LDRH_I(r_res, r_addr, 0), ctx); ++#ifdef __LITTLE_ENDIAN ++ _emit(cond, ARM_REV16(r_res, r_res), ctx); ++#endif ++} ++ ++static inline void emit_swap16(u8 r_dst __maybe_unused, ++ u8 r_src __maybe_unused, ++ struct jit_ctx *ctx __maybe_unused) ++{ ++#ifdef __LITTLE_ENDIAN ++ emit(ARM_REV16(r_dst, r_src), ctx); ++#endif ++} ++ ++#endif /* __LINUX_ARM_ARCH__ < 6 */ ++ ++ ++/* Compute the immediate value for a PC-relative branch. */ ++static inline u32 b_imm(unsigned tgt, struct jit_ctx *ctx) ++{ ++ u32 imm; ++ ++ if (ctx->target == NULL) ++ return 0; ++ /* ++ * BPF allows only forward jumps and the offset of the target is ++ * still the one computed during the first pass. ++ */ ++ imm = ctx->offsets[tgt] + ctx->prologue_bytes - (ctx->idx * 4 + 8); ++ ++ return imm >> 2; ++} ++ ++#define OP_IMM3(op, r1, r2, imm_val, ctx) \ ++ do { \ ++ imm12 = imm8m(imm_val); \ ++ if (imm12 < 0) { \ ++ emit_mov_i_no8m(r_scratch, imm_val, ctx); \ ++ emit(op ## _R((r1), (r2), r_scratch), ctx); \ ++ } else { \ ++ emit(op ## _I((r1), (r2), imm12), ctx); \ ++ } \ ++ } while (0) ++ ++static inline void emit_err_ret(u8 cond, struct jit_ctx *ctx) ++{ ++ if (ctx->ret0_fp_idx >= 0) { ++ _emit(cond, ARM_B(b_imm(ctx->ret0_fp_idx, ctx)), ctx); ++ /* NOP to keep the size constant between passes */ ++ emit(ARM_MOV_R(ARM_R0, ARM_R0), ctx); ++ } else { ++ _emit(cond, ARM_MOV_I(ARM_R0, 0), ctx); ++ _emit(cond, ARM_B(b_imm(ctx->skf->len, ctx)), ctx); ++ } ++} ++ ++static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx) ++{ ++#if __LINUX_ARM_ARCH__ < 5 ++ emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx); ++ ++ if (elf_hwcap & HWCAP_THUMB) ++ emit(ARM_BX(tgt_reg), ctx); ++ else ++ emit(ARM_MOV_R(ARM_PC, tgt_reg), ctx); ++#else ++ emit(ARM_BLX_R(tgt_reg), ctx); ++#endif ++} ++ ++static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx) ++{ ++#if __LINUX_ARM_ARCH__ == 7 ++ if (elf_hwcap & HWCAP_IDIVA) { ++ emit(ARM_UDIV(rd, rm, rn), ctx); ++ return; ++ } ++#endif ++ if (rm != ARM_R0) ++ emit(ARM_MOV_R(ARM_R0, rm), ctx); ++ if (rn != ARM_R1) ++ emit(ARM_MOV_R(ARM_R1, rn), ctx); ++ ++ ctx->seen |= SEEN_CALL; ++ emit_mov_i(ARM_R3, (u32)jit_udiv, ctx); ++ emit_blx_r(ARM_R3, ctx); ++ ++ if (rd != ARM_R0) ++ emit(ARM_MOV_R(rd, ARM_R0), ctx); ++} ++ ++static inline void update_on_xread(struct jit_ctx *ctx) ++{ ++ if (!(ctx->seen & SEEN_X)) ++ ctx->flags |= FLAG_NEED_X_RESET; ++ ++ ctx->seen |= SEEN_X; ++} ++ ++static int build_body(struct jit_ctx *ctx) ++{ ++ void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w}; ++ const struct sk_filter *prog = ctx->skf; ++ const struct sock_filter *inst; ++ unsigned i, load_order, off, condt; ++ int imm12; ++ u32 k; ++ ++ for (i = 0; i < prog->len; i++) { ++ inst = &(prog->insns[i]); ++ /* K as an immediate value operand */ ++ k = inst->k; ++ ++ /* compute offsets only in the fake pass */ ++ if (ctx->target == NULL) ++ ctx->offsets[i] = ctx->idx * 4; ++ ++ switch (inst->code) { ++ case BPF_S_LD_IMM: ++ emit_mov_i(r_A, k, ctx); ++ break; ++ case BPF_S_LD_W_LEN: ++ ctx->seen |= SEEN_SKB; ++ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4); ++ emit(ARM_LDR_I(r_A, r_skb, ++ offsetof(struct sk_buff, len)), ctx); ++ break; ++ case BPF_S_LD_MEM: ++ /* A = scratch[k] */ ++ ctx->seen |= SEEN_MEM_WORD(k); ++ emit(ARM_LDR_I(r_A, ARM_SP, SCRATCH_OFF(k)), ctx); ++ break; ++ case BPF_S_LD_W_ABS: ++ load_order = 2; ++ goto load; ++ case BPF_S_LD_H_ABS: ++ load_order = 1; ++ goto load; ++ case BPF_S_LD_B_ABS: ++ load_order = 0; ++load: ++ /* the interpreter will deal with the negative K */ ++ if ((int)k < 0) ++ return -ENOTSUPP; ++ emit_mov_i(r_off, k, ctx); ++load_common: ++ ctx->seen |= SEEN_DATA | SEEN_CALL; ++ ++ if (load_order > 0) { ++ emit(ARM_SUB_I(r_scratch, r_skb_hl, ++ 1 << load_order), ctx); ++ emit(ARM_CMP_R(r_scratch, r_off), ctx); ++ condt = ARM_COND_HS; ++ } else { ++ emit(ARM_CMP_R(r_skb_hl, r_off), ctx); ++ condt = ARM_COND_HI; ++ } ++ ++ _emit(condt, ARM_ADD_R(r_scratch, r_off, r_skb_data), ++ ctx); ++ ++ if (load_order == 0) ++ _emit(condt, ARM_LDRB_I(r_A, r_scratch, 0), ++ ctx); ++ else if (load_order == 1) ++ emit_load_be16(condt, r_A, r_scratch, ctx); ++ else if (load_order == 2) ++ emit_load_be32(condt, r_A, r_scratch, ctx); ++ ++ _emit(condt, ARM_B(b_imm(i + 1, ctx)), ctx); ++ ++ /* the slowpath */ ++ emit_mov_i(ARM_R3, (u32)load_func[load_order], ctx); ++ emit(ARM_MOV_R(ARM_R0, r_skb), ctx); ++ /* the offset is already in R1 */ ++ emit_blx_r(ARM_R3, ctx); ++ /* check the result of skb_copy_bits */ ++ emit(ARM_CMP_I(ARM_R1, 0), ctx); ++ emit_err_ret(ARM_COND_NE, ctx); ++ emit(ARM_MOV_R(r_A, ARM_R0), ctx); ++ break; ++ case BPF_S_LD_W_IND: ++ load_order = 2; ++ goto load_ind; ++ case BPF_S_LD_H_IND: ++ load_order = 1; ++ goto load_ind; ++ case BPF_S_LD_B_IND: ++ load_order = 0; ++load_ind: ++ OP_IMM3(ARM_ADD, r_off, r_X, k, ctx); ++ goto load_common; ++ case BPF_S_LDX_IMM: ++ ctx->seen |= SEEN_X; ++ emit_mov_i(r_X, k, ctx); ++ break; ++ case BPF_S_LDX_W_LEN: ++ ctx->seen |= SEEN_X | SEEN_SKB; ++ emit(ARM_LDR_I(r_X, r_skb, ++ offsetof(struct sk_buff, len)), ctx); ++ break; ++ case BPF_S_LDX_MEM: ++ ctx->seen |= SEEN_X | SEEN_MEM_WORD(k); ++ emit(ARM_LDR_I(r_X, ARM_SP, SCRATCH_OFF(k)), ctx); ++ break; ++ case BPF_S_LDX_B_MSH: ++ /* x = ((*(frame + k)) & 0xf) << 2; */ ++ ctx->seen |= SEEN_X | SEEN_DATA | SEEN_CALL; ++ /* the interpreter should deal with the negative K */ ++ if (k < 0) ++ return -1; ++ /* offset in r1: we might have to take the slow path */ ++ emit_mov_i(r_off, k, ctx); ++ emit(ARM_CMP_R(r_skb_hl, r_off), ctx); ++ ++ /* load in r0: common with the slowpath */ ++ _emit(ARM_COND_HI, ARM_LDRB_R(ARM_R0, r_skb_data, ++ ARM_R1), ctx); ++ /* ++ * emit_mov_i() might generate one or two instructions, ++ * the same holds for emit_blx_r() ++ */ ++ _emit(ARM_COND_HI, ARM_B(b_imm(i + 1, ctx) - 2), ctx); ++ ++ emit(ARM_MOV_R(ARM_R0, r_skb), ctx); ++ /* r_off is r1 */ ++ emit_mov_i(ARM_R3, (u32)jit_get_skb_b, ctx); ++ emit_blx_r(ARM_R3, ctx); ++ /* check the return value of skb_copy_bits */ ++ emit(ARM_CMP_I(ARM_R1, 0), ctx); ++ emit_err_ret(ARM_COND_NE, ctx); ++ ++ emit(ARM_AND_I(r_X, ARM_R0, 0x00f), ctx); ++ emit(ARM_LSL_I(r_X, r_X, 2), ctx); ++ break; ++ case BPF_S_ST: ++ ctx->seen |= SEEN_MEM_WORD(k); ++ emit(ARM_STR_I(r_A, ARM_SP, SCRATCH_OFF(k)), ctx); ++ break; ++ case BPF_S_STX: ++ update_on_xread(ctx); ++ ctx->seen |= SEEN_MEM_WORD(k); ++ emit(ARM_STR_I(r_X, ARM_SP, SCRATCH_OFF(k)), ctx); ++ break; ++ case BPF_S_ALU_ADD_K: ++ /* A += K */ ++ OP_IMM3(ARM_ADD, r_A, r_A, k, ctx); ++ break; ++ case BPF_S_ALU_ADD_X: ++ update_on_xread(ctx); ++ emit(ARM_ADD_R(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_SUB_K: ++ /* A -= K */ ++ OP_IMM3(ARM_SUB, r_A, r_A, k, ctx); ++ break; ++ case BPF_S_ALU_SUB_X: ++ update_on_xread(ctx); ++ emit(ARM_SUB_R(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_MUL_K: ++ /* A *= K */ ++ emit_mov_i(r_scratch, k, ctx); ++ emit(ARM_MUL(r_A, r_A, r_scratch), ctx); ++ break; ++ case BPF_S_ALU_MUL_X: ++ update_on_xread(ctx); ++ emit(ARM_MUL(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_DIV_K: ++ /* current k == reciprocal_value(userspace k) */ ++ emit_mov_i(r_scratch, k, ctx); ++ /* A = top 32 bits of the product */ ++ emit(ARM_UMULL(r_scratch, r_A, r_A, r_scratch), ctx); ++ break; ++ case BPF_S_ALU_DIV_X: ++ update_on_xread(ctx); ++ emit(ARM_CMP_I(r_X, 0), ctx); ++ emit_err_ret(ARM_COND_EQ, ctx); ++ emit_udiv(r_A, r_A, r_X, ctx); ++ break; ++ case BPF_S_ALU_OR_K: ++ /* A |= K */ ++ OP_IMM3(ARM_ORR, r_A, r_A, k, ctx); ++ break; ++ case BPF_S_ALU_OR_X: ++ update_on_xread(ctx); ++ emit(ARM_ORR_R(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_AND_K: ++ /* A &= K */ ++ OP_IMM3(ARM_AND, r_A, r_A, k, ctx); ++ break; ++ case BPF_S_ALU_AND_X: ++ update_on_xread(ctx); ++ emit(ARM_AND_R(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_LSH_K: ++ if (unlikely(k > 31)) ++ return -1; ++ emit(ARM_LSL_I(r_A, r_A, k), ctx); ++ break; ++ case BPF_S_ALU_LSH_X: ++ update_on_xread(ctx); ++ emit(ARM_LSL_R(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_RSH_K: ++ if (unlikely(k > 31)) ++ return -1; ++ emit(ARM_LSR_I(r_A, r_A, k), ctx); ++ break; ++ case BPF_S_ALU_RSH_X: ++ update_on_xread(ctx); ++ emit(ARM_LSR_R(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_NEG: ++ /* A = -A */ ++ emit(ARM_RSB_I(r_A, r_A, 0), ctx); ++ break; ++ case BPF_S_JMP_JA: ++ /* pc += K */ ++ emit(ARM_B(b_imm(i + k + 1, ctx)), ctx); ++ break; ++ case BPF_S_JMP_JEQ_K: ++ /* pc += (A == K) ? pc->jt : pc->jf */ ++ condt = ARM_COND_EQ; ++ goto cmp_imm; ++ case BPF_S_JMP_JGT_K: ++ /* pc += (A > K) ? pc->jt : pc->jf */ ++ condt = ARM_COND_HI; ++ goto cmp_imm; ++ case BPF_S_JMP_JGE_K: ++ /* pc += (A >= K) ? pc->jt : pc->jf */ ++ condt = ARM_COND_HS; ++cmp_imm: ++ imm12 = imm8m(k); ++ if (imm12 < 0) { ++ emit_mov_i_no8m(r_scratch, k, ctx); ++ emit(ARM_CMP_R(r_A, r_scratch), ctx); ++ } else { ++ emit(ARM_CMP_I(r_A, imm12), ctx); ++ } ++cond_jump: ++ if (inst->jt) ++ _emit(condt, ARM_B(b_imm(i + inst->jt + 1, ++ ctx)), ctx); ++ if (inst->jf) ++ _emit(condt ^ 1, ARM_B(b_imm(i + inst->jf + 1, ++ ctx)), ctx); ++ break; ++ case BPF_S_JMP_JEQ_X: ++ /* pc += (A == X) ? pc->jt : pc->jf */ ++ condt = ARM_COND_EQ; ++ goto cmp_x; ++ case BPF_S_JMP_JGT_X: ++ /* pc += (A > X) ? pc->jt : pc->jf */ ++ condt = ARM_COND_HI; ++ goto cmp_x; ++ case BPF_S_JMP_JGE_X: ++ /* pc += (A >= X) ? pc->jt : pc->jf */ ++ condt = ARM_COND_CS; ++cmp_x: ++ update_on_xread(ctx); ++ emit(ARM_CMP_R(r_A, r_X), ctx); ++ goto cond_jump; ++ case BPF_S_JMP_JSET_K: ++ /* pc += (A & K) ? pc->jt : pc->jf */ ++ condt = ARM_COND_NE; ++ /* not set iff all zeroes iff Z==1 iff EQ */ ++ ++ imm12 = imm8m(k); ++ if (imm12 < 0) { ++ emit_mov_i_no8m(r_scratch, k, ctx); ++ emit(ARM_TST_R(r_A, r_scratch), ctx); ++ } else { ++ emit(ARM_TST_I(r_A, imm12), ctx); ++ } ++ goto cond_jump; ++ case BPF_S_JMP_JSET_X: ++ /* pc += (A & X) ? pc->jt : pc->jf */ ++ update_on_xread(ctx); ++ condt = ARM_COND_NE; ++ emit(ARM_TST_R(r_A, r_X), ctx); ++ goto cond_jump; ++ case BPF_S_RET_A: ++ emit(ARM_MOV_R(ARM_R0, r_A), ctx); ++ goto b_epilogue; ++ case BPF_S_RET_K: ++ if ((k == 0) && (ctx->ret0_fp_idx < 0)) ++ ctx->ret0_fp_idx = i; ++ emit_mov_i(ARM_R0, k, ctx); ++b_epilogue: ++ if (i != ctx->skf->len - 1) ++ emit(ARM_B(b_imm(prog->len, ctx)), ctx); ++ break; ++ case BPF_S_MISC_TAX: ++ /* X = A */ ++ ctx->seen |= SEEN_X; ++ emit(ARM_MOV_R(r_X, r_A), ctx); ++ break; ++ case BPF_S_MISC_TXA: ++ /* A = X */ ++ update_on_xread(ctx); ++ emit(ARM_MOV_R(r_A, r_X), ctx); ++ break; ++ case BPF_S_ANC_PROTOCOL: ++ /* A = ntohs(skb->protocol) */ ++ ctx->seen |= SEEN_SKB; ++ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, ++ protocol) != 2); ++ off = offsetof(struct sk_buff, protocol); ++ emit(ARM_LDRH_I(r_scratch, r_skb, off), ctx); ++ emit_swap16(r_A, r_scratch, ctx); ++ break; ++ case BPF_S_ANC_CPU: ++ /* r_scratch = current_thread_info() */ ++ OP_IMM3(ARM_BIC, r_scratch, ARM_SP, THREAD_SIZE - 1, ctx); ++ /* A = current_thread_info()->cpu */ ++ BUILD_BUG_ON(FIELD_SIZEOF(struct thread_info, cpu) != 4); ++ off = offsetof(struct thread_info, cpu); ++ emit(ARM_LDR_I(r_A, r_scratch, off), ctx); ++ break; ++ case BPF_S_ANC_IFINDEX: ++ /* A = skb->dev->ifindex */ ++ ctx->seen |= SEEN_SKB; ++ off = offsetof(struct sk_buff, dev); ++ emit(ARM_LDR_I(r_scratch, r_skb, off), ctx); ++ ++ emit(ARM_CMP_I(r_scratch, 0), ctx); ++ emit_err_ret(ARM_COND_EQ, ctx); ++ ++ BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ++ ifindex) != 4); ++ off = offsetof(struct net_device, ifindex); ++ emit(ARM_LDR_I(r_A, r_scratch, off), ctx); ++ break; ++ case BPF_S_ANC_MARK: ++ ctx->seen |= SEEN_SKB; ++ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4); ++ off = offsetof(struct sk_buff, mark); ++ emit(ARM_LDR_I(r_A, r_skb, off), ctx); ++ break; ++ case BPF_S_ANC_RXHASH: ++ ctx->seen |= SEEN_SKB; ++ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4); ++ off = offsetof(struct sk_buff, rxhash); ++ emit(ARM_LDR_I(r_A, r_skb, off), ctx); ++ break; ++ case BPF_S_ANC_QUEUE: ++ ctx->seen |= SEEN_SKB; ++ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, ++ queue_mapping) != 2); ++ BUILD_BUG_ON(offsetof(struct sk_buff, ++ queue_mapping) > 0xff); ++ off = offsetof(struct sk_buff, queue_mapping); ++ emit(ARM_LDRH_I(r_A, r_skb, off), ctx); ++ break; ++ default: ++ return -1; ++ } ++ } ++ ++ /* compute offsets only during the first pass */ ++ if (ctx->target == NULL) ++ ctx->offsets[i] = ctx->idx * 4; ++ ++ return 0; ++} ++ ++ ++void bpf_jit_compile(struct sk_filter *fp) ++{ ++ struct jit_ctx ctx; ++ unsigned tmp_idx; ++ unsigned alloc_size; ++ ++ if (!bpf_jit_enable) ++ return; ++ ++ memset(&ctx, 0, sizeof(ctx)); ++ ctx.skf = fp; ++ ctx.ret0_fp_idx = -1; ++ ++ ctx.offsets = kzalloc(GFP_KERNEL, 4 * (ctx.skf->len + 1)); ++ if (ctx.offsets == NULL) ++ return; ++ ++ /* fake pass to fill in the ctx->seen */ ++ if (unlikely(build_body(&ctx))) ++ goto out; ++ ++ tmp_idx = ctx.idx; ++ build_prologue(&ctx); ++ ctx.prologue_bytes = (ctx.idx - tmp_idx) * 4; ++ ++#if __LINUX_ARM_ARCH__ < 7 ++ tmp_idx = ctx.idx; ++ build_epilogue(&ctx); ++ ctx.epilogue_bytes = (ctx.idx - tmp_idx) * 4; ++ ++ ctx.idx += ctx.imm_count; ++ if (ctx.imm_count) { ++ ctx.imms = kzalloc(GFP_KERNEL, 4 * ctx.imm_count); ++ if (ctx.imms == NULL) ++ goto out; ++ } ++#else ++ /* there's nothing after the epilogue on ARMv7 */ ++ build_epilogue(&ctx); ++#endif ++ ++ alloc_size = 4 * ctx.idx; ++ ctx.target = module_alloc(max(sizeof(struct work_struct), ++ alloc_size)); ++ if (unlikely(ctx.target == NULL)) ++ goto out; ++ ++ ctx.idx = 0; ++ build_prologue(&ctx); ++ build_body(&ctx); ++ build_epilogue(&ctx); ++ ++ flush_icache_range((u32)ctx.target, (u32)(ctx.target + ctx.idx)); ++ ++#if __LINUX_ARM_ARCH__ < 7 ++ if (ctx.imm_count) ++ kfree(ctx.imms); ++#endif ++ ++ if (bpf_jit_enable > 1) ++ print_hex_dump(KERN_INFO, "BPF JIT code: ", ++ DUMP_PREFIX_ADDRESS, 16, 4, ctx.target, ++ alloc_size, false); ++ ++ fp->bpf_func = (void *)ctx.target; ++out: ++ kfree(ctx.offsets); ++ return; ++} ++ ++static void bpf_jit_free_worker(struct work_struct *work) ++{ ++ module_free(NULL, work); ++} ++ ++void bpf_jit_free(struct sk_filter *fp) ++{ ++ struct work_struct *work; ++ ++ if (fp->bpf_func != sk_run_filter) { ++ work = (struct work_struct *)fp->bpf_func; ++ ++ INIT_WORK(work, bpf_jit_free_worker); ++ schedule_work(work); ++ } ++} +diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h +new file mode 100644 +index 0000000..99ae5e3 +--- /dev/null ++++ b/arch/arm/net/bpf_jit_32.h +@@ -0,0 +1,190 @@ ++/* ++ * Just-In-Time compiler for BPF filters on 32bit ARM ++ * ++ * Copyright (c) 2011 Mircea Gherzan ++ * ++ * This program is free software; 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. ++ */ ++ ++#ifndef PFILTER_OPCODES_ARM_H ++#define PFILTER_OPCODES_ARM_H ++ ++#define ARM_R0 0 ++#define ARM_R1 1 ++#define ARM_R2 2 ++#define ARM_R3 3 ++#define ARM_R4 4 ++#define ARM_R5 5 ++#define ARM_R6 6 ++#define ARM_R7 7 ++#define ARM_R8 8 ++#define ARM_R9 9 ++#define ARM_R10 10 ++#define ARM_FP 11 ++#define ARM_IP 12 ++#define ARM_SP 13 ++#define ARM_LR 14 ++#define ARM_PC 15 ++ ++#define ARM_COND_EQ 0x0 ++#define ARM_COND_NE 0x1 ++#define ARM_COND_CS 0x2 ++#define ARM_COND_HS ARM_COND_CS ++#define ARM_COND_CC 0x3 ++#define ARM_COND_LO ARM_COND_CC ++#define ARM_COND_MI 0x4 ++#define ARM_COND_PL 0x5 ++#define ARM_COND_VS 0x6 ++#define ARM_COND_VC 0x7 ++#define ARM_COND_HI 0x8 ++#define ARM_COND_LS 0x9 ++#define ARM_COND_GE 0xa ++#define ARM_COND_LT 0xb ++#define ARM_COND_GT 0xc ++#define ARM_COND_LE 0xd ++#define ARM_COND_AL 0xe ++ ++/* register shift types */ ++#define SRTYPE_LSL 0 ++#define SRTYPE_LSR 1 ++#define SRTYPE_ASR 2 ++#define SRTYPE_ROR 3 ++ ++#define ARM_INST_ADD_R 0x00800000 ++#define ARM_INST_ADD_I 0x02800000 ++ ++#define ARM_INST_AND_R 0x00000000 ++#define ARM_INST_AND_I 0x02000000 ++ ++#define ARM_INST_BIC_R 0x01c00000 ++#define ARM_INST_BIC_I 0x03c00000 ++ ++#define ARM_INST_B 0x0a000000 ++#define ARM_INST_BX 0x012FFF10 ++#define ARM_INST_BLX_R 0x012fff30 ++ ++#define ARM_INST_CMP_R 0x01500000 ++#define ARM_INST_CMP_I 0x03500000 ++ ++#define ARM_INST_LDRB_I 0x05d00000 ++#define ARM_INST_LDRB_R 0x07d00000 ++#define ARM_INST_LDRH_I 0x01d000b0 ++#define ARM_INST_LDR_I 0x05900000 ++ ++#define ARM_INST_LDM 0x08900000 ++ ++#define ARM_INST_LSL_I 0x01a00000 ++#define ARM_INST_LSL_R 0x01a00010 ++ ++#define ARM_INST_LSR_I 0x01a00020 ++#define ARM_INST_LSR_R 0x01a00030 ++ ++#define ARM_INST_MOV_R 0x01a00000 ++#define ARM_INST_MOV_I 0x03a00000 ++#define ARM_INST_MOVW 0x03000000 ++#define ARM_INST_MOVT 0x03400000 ++ ++#define ARM_INST_MUL 0x00000090 ++ ++#define ARM_INST_POP 0x08bd0000 ++#define ARM_INST_PUSH 0x092d0000 ++ ++#define ARM_INST_ORR_R 0x01800000 ++#define ARM_INST_ORR_I 0x03800000 ++ ++#define ARM_INST_REV 0x06bf0f30 ++#define ARM_INST_REV16 0x06bf0fb0 ++ ++#define ARM_INST_RSB_I 0x02600000 ++ ++#define ARM_INST_SUB_R 0x00400000 ++#define ARM_INST_SUB_I 0x02400000 ++ ++#define ARM_INST_STR_I 0x05800000 ++ ++#define ARM_INST_TST_R 0x01100000 ++#define ARM_INST_TST_I 0x03100000 ++ ++#define ARM_INST_UDIV 0x0730f010 ++ ++#define ARM_INST_UMULL 0x00800090 ++ ++/* register */ ++#define _AL3_R(op, rd, rn, rm) ((op ## _R) | (rd) << 12 | (rn) << 16 | (rm)) ++/* immediate */ ++#define _AL3_I(op, rd, rn, imm) ((op ## _I) | (rd) << 12 | (rn) << 16 | (imm)) ++ ++#define ARM_ADD_R(rd, rn, rm) _AL3_R(ARM_INST_ADD, rd, rn, rm) ++#define ARM_ADD_I(rd, rn, imm) _AL3_I(ARM_INST_ADD, rd, rn, imm) ++ ++#define ARM_AND_R(rd, rn, rm) _AL3_R(ARM_INST_AND, rd, rn, rm) ++#define ARM_AND_I(rd, rn, imm) _AL3_I(ARM_INST_AND, rd, rn, imm) ++ ++#define ARM_BIC_R(rd, rn, rm) _AL3_R(ARM_INST_BIC, rd, rn, rm) ++#define ARM_BIC_I(rd, rn, imm) _AL3_I(ARM_INST_BIC, rd, rn, imm) ++ ++#define ARM_B(imm24) (ARM_INST_B | ((imm24) & 0xffffff)) ++#define ARM_BX(rm) (ARM_INST_BX | (rm)) ++#define ARM_BLX_R(rm) (ARM_INST_BLX_R | (rm)) ++ ++#define ARM_CMP_R(rn, rm) _AL3_R(ARM_INST_CMP, 0, rn, rm) ++#define ARM_CMP_I(rn, imm) _AL3_I(ARM_INST_CMP, 0, rn, imm) ++ ++#define ARM_LDR_I(rt, rn, off) (ARM_INST_LDR_I | (rt) << 12 | (rn) << 16 \ ++ | (off)) ++#define ARM_LDRB_I(rt, rn, off) (ARM_INST_LDRB_I | (rt) << 12 | (rn) << 16 \ ++ | (off)) ++#define ARM_LDRB_R(rt, rn, rm) (ARM_INST_LDRB_R | (rt) << 12 | (rn) << 16 \ ++ | (rm)) ++#define ARM_LDRH_I(rt, rn, off) (ARM_INST_LDRH_I | (rt) << 12 | (rn) << 16 \ ++ | (((off) & 0xf0) << 4) | ((off) & 0xf)) ++ ++#define ARM_LDM(rn, regs) (ARM_INST_LDM | (rn) << 16 | (regs)) ++ ++#define ARM_LSL_R(rd, rn, rm) (_AL3_R(ARM_INST_LSL, rd, 0, rn) | (rm) << 8) ++#define ARM_LSL_I(rd, rn, imm) (_AL3_I(ARM_INST_LSL, rd, 0, rn) | (imm) << 7) ++ ++#define ARM_LSR_R(rd, rn, rm) (_AL3_R(ARM_INST_LSR, rd, 0, rn) | (rm) << 8) ++#define ARM_LSR_I(rd, rn, imm) (_AL3_I(ARM_INST_LSR, rd, 0, rn) | (imm) << 7) ++ ++#define ARM_MOV_R(rd, rm) _AL3_R(ARM_INST_MOV, rd, 0, rm) ++#define ARM_MOV_I(rd, imm) _AL3_I(ARM_INST_MOV, rd, 0, imm) ++ ++#define ARM_MOVW(rd, imm) \ ++ (ARM_INST_MOVW | ((imm) >> 12) << 16 | (rd) << 12 | ((imm) & 0x0fff)) ++ ++#define ARM_MOVT(rd, imm) \ ++ (ARM_INST_MOVT | ((imm) >> 12) << 16 | (rd) << 12 | ((imm) & 0x0fff)) ++ ++#define ARM_MUL(rd, rm, rn) (ARM_INST_MUL | (rd) << 16 | (rm) << 8 | (rn)) ++ ++#define ARM_POP(regs) (ARM_INST_POP | (regs)) ++#define ARM_PUSH(regs) (ARM_INST_PUSH | (regs)) ++ ++#define ARM_ORR_R(rd, rn, rm) _AL3_R(ARM_INST_ORR, rd, rn, rm) ++#define ARM_ORR_I(rd, rn, imm) _AL3_I(ARM_INST_ORR, rd, rn, imm) ++#define ARM_ORR_S(rd, rn, rm, type, rs) \ ++ (ARM_ORR_R(rd, rn, rm) | (type) << 5 | (rs) << 7) ++ ++#define ARM_REV(rd, rm) (ARM_INST_REV | (rd) << 12 | (rm)) ++#define ARM_REV16(rd, rm) (ARM_INST_REV16 | (rd) << 12 | (rm)) ++ ++#define ARM_RSB_I(rd, rn, imm) _AL3_I(ARM_INST_RSB, rd, rn, imm) ++ ++#define ARM_SUB_R(rd, rn, rm) _AL3_R(ARM_INST_SUB, rd, rn, rm) ++#define ARM_SUB_I(rd, rn, imm) _AL3_I(ARM_INST_SUB, rd, rn, imm) ++ ++#define ARM_STR_I(rt, rn, off) (ARM_INST_STR_I | (rt) << 12 | (rn) << 16 \ ++ | (off)) ++ ++#define ARM_TST_R(rn, rm) _AL3_R(ARM_INST_TST, 0, rn, rm) ++#define ARM_TST_I(rn, imm) _AL3_I(ARM_INST_TST, 0, rn, imm) ++ ++#define ARM_UDIV(rd, rn, rm) (ARM_INST_UDIV | (rd) << 16 | (rn) | (rm) << 8) ++ ++#define ARM_UMULL(rd_lo, rd_hi, rn, rm) (ARM_INST_UMULL | (rd_hi) << 16 \ ++ | (rd_lo) << 12 | (rm) << 8 | rn) ++ ++#endif /* PFILTER_OPCODES_ARM_H */ +diff --git a/arch/arm/plat-iproc/Kconfig b/arch/arm/plat-iproc/Kconfig +new file mode 100644 +index 0000000..5b8675f +--- /dev/null ++++ b/arch/arm/plat-iproc/Kconfig +@@ -0,0 +1,96 @@ ++# Kernel configuration for Broadcom iProc based boards ++ ++menu "Broadcom IPROC architecture based implementations" ++ depends on ARCH_IPROC ++ ++choice ++ prompt "Broadcom iProc SoC Type" ++ default ARCH_NORTHSTAR ++ ++config ARCH_NORTHSTAR ++ bool "BROADCOM Northstar SoC" ++ help ++ Support for the Broadcom Northstar SoC platform. ++ ++config MACH_IPROC ++ bool "BROADCOM Generic IPROC SoC" ++ help ++ Support for the Broadcom IPROC SoC platform. ++ ++endchoice ++ ++config IPROC_64K_PAGE ++ bool "64K page support" ++ depends on ARCH_IPROC ++ help ++ ++config GP_TIMER_CLOCK_OFF_FIX ++ bool "Enable the fix for general purpose timer clock off issue." ++ depends on ARCH_RHEA || ARCH_SAMOA ++ help ++ Say Y if you want to enable the general purpose timer clock off fix ++ ++config GP_TIMER_COMPARATOR_LOAD_DELAY ++ bool "Enable the delay after loading general purpose timer compare register" ++ depends on ARCH_RHEA || ARCH_ISLAND || ARCH_SAMOA || ARCH_HANA || ARCH_NORTHSTAR || MACH_IPROC ++ default y ++ ++config IPROC_DCACHE_INVALIDATION ++ bool "Have Linux invalidate D-Cache" ++ default y ++ help ++ Say Y if you want Linux to invalidate primary core D-Cache during Linux ++ decompression and boot. ++ ++config IPROC_TIMER_UNIT_TESTS ++ bool "Include iProc Timer unit test code" ++ help ++ Say Y if you want to test the AON,Peripheral Timer modules using the sysfs interface ++ ++config IPROC_SW_RESET_RECORD ++ bool "Include Software Reset Records" ++ help ++ Say Y if you want to enable interface to access Software Reset Record. ++ Software Reset Record is a set of variables whose value could be retained ++ after reset (but will be cleared if powered off). ++ ++config BRCM_PROP_MODULES ++ bool "Include Broadcom proprietary modules" ++ default n ++ help ++ Say Y if you want to include the Broadcom proprietary modules. ++ ++config BCM_STM ++ bool "Enable System Trace Module" ++ default n ++ help ++ Say Y if you want to enable the Broadcom System Trace Module ++ ++config DMAC_PL330 ++ bool "PL330 DMAC driver support for Kona architecture" ++ depends on ARCH_RHEA ++ select PL330 ++ help ++ Support for PL330 DMA Controller driver for Rhea SOC/KONA architecture ++ ++config BCM_ZRELADDR ++ hex "Compressed ZREL address" ++ ++config BCM_PARAMS_PHYS ++ hex "Address where tagged parameters are to be found" ++ ++config BCM_RAM_BASE ++ hex "RAM base address" ++ help ++ Set the physical base address of RAM ++ ++config BCM_RAM_START_RESERVED_SIZE ++ hex "RAM start reserved memory size in bytes" ++ default 0 ++ help ++ Reserve memory at the start of RAM. This memory ++ may be used for LCD frame buffer, DSP, modem, etc. ++ ++#source "drivers/bcmdrivers/Kconfig" ++ ++endmenu +diff --git a/arch/arm/plat-iproc/Makefile b/arch/arm/plat-iproc/Makefile +new file mode 100644 +index 0000000..2474a9d +--- /dev/null ++++ b/arch/arm/plat-iproc/Makefile +@@ -0,0 +1,17 @@ ++ ++ ++# obj-y := irq.o iproc_timer.o timer.o sysfs.o ++obj-y := irq.o timer-sp.o sysfs.o bcm5301x.o iproc-cache.o headsmp.o shm.o ++obj-$(CONFIG_SMP) += platsmp.o ++ ++ ++obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o ++obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o ++obj-$(CONFIG_USB_GADGET_DWC_OTG) += lm.o ++obj-$(CONFIG_HAVE_CLK) += clock.o ++obj-$(CONFIG_ARCH_IPROC) += iproc_cru.o ++obj-$(CONFIG_IPROC_SW_RESET_RECORD) += swreset_rec.o ++ ++export DRIVERS_MMC_HOST_DIR := drivers/mmc/host/ ++export DRIVERS_MTD_DIR := drivers/mtd/ ++# obj-y+=../../../../../bcmdrivers/ +diff --git a/arch/arm/plat-iproc/bcm5301x.c b/arch/arm/plat-iproc/bcm5301x.c +new file mode 100644 +index 0000000..87ae083 +--- /dev/null ++++ b/arch/arm/plat-iproc/bcm5301x.c +@@ -0,0 +1,84 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++void __init iproc_map_io(void) ++{ ++ struct map_desc desc ; ++ phys_addr_t base_addr; ++ ++ /* ++ * Cortex A9 Architecture Manual specifies this as a way to get ++ * MPCORE PERHIPHBASE address at run-time ++ */ ++ asm( "mrc p15,4,%0,c15,c0,0 @ Read Configuration Base Address Register" ++ : "=&r" (base_addr) : : "cc" ); ++ ++ printk(KERN_INFO "MPCORE found at %p\n", (void *)base_addr); ++ ++ /* Fix-map the entire PERIPHBASE 2*4K register block */ ++ desc.virtual = IPROC_PERIPH_VA; ++ desc.pfn = __phys_to_pfn(base_addr); ++ desc.length = SZ_8K; ++ desc.type = MT_DEVICE ; ++ ++ iotable_init(&desc, 1); ++} ++ ++static int iproc_data_abort_handler(unsigned long addr, unsigned int fsr, ++ struct pt_regs *regs) ++{ ++ /* ++ * These happen for no good reason ++ */ ++// printk(KERN_WARNING "Data abort at addr=%#lx, fsr=%#x ignored.\n", addr, fsr); ++ return 0; ++} ++ ++void __init iproc_enable_data_prefetch_aborts(void) ++{ ++ u32 x; ++ ++ /* Install our hook */ ++ hook_fault_code(16 + 6, iproc_data_abort_handler, SIGBUS, 0, ++ "imprecise external data abort"); ++ ++ /* Enable external aborts - clear "A" bit in CPSR */ ++ ++ /* Read CPSR */ ++// asm("mrs %0,cpsr": "=&r" (x) : : ); ++ asm("mrs %0,cpsr": "=&r" (x) ); ++ ++ x &= ~ PSR_A_BIT; ++ ++ /* Update CPSR, affect bits 8-15 */ ++ asm("msr cpsr_x,%0; nop; nop": : "r" (x) : "cc"); ++ ++} +diff --git a/arch/arm/plat-iproc/clock.c b/arch/arm/plat-iproc/clock.c +new file mode 100644 +index 0000000..98da8f5 +--- /dev/null ++++ b/arch/arm/plat-iproc/clock.c +@@ -0,0 +1,165 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++int clk_enable(struct clk *clk) ++{ ++ int ret ; ++ ++ ret = atomic_inc_return(&clk->ena_cnt); ++ if (ret > 1) ++ return 0; ++ /* Continue of count was moved from 0 to 1 - reentrant */ ++ if (clk->parent) ++ ret = clk_enable( clk->parent ); ++ else ++ ret = 0; ++ ++ if (ret == 0) { ++ if (!clk->ops || !clk->ops->enable) { ++ if (clk->rate) ++ ret = 0 ; ++ else { ++ if (clk_get_rate(clk)) ++ ret = 0; ++ else ++ ret = -EIO; ++ } ++ } else { ++ ret = clk->ops->enable(clk); ++ } ++ } ++ ++ if (ret != 0) ++ atomic_dec(&clk->ena_cnt); ++ ++ return ret ; ++} ++ ++EXPORT_SYMBOL(clk_enable); ++ ++void clk_disable(struct clk *clk) ++{ ++ int ret ; ++ ++ ret = atomic_dec_return(&clk->ena_cnt); ++ ++ /* Continue if this is the last client to disable - reentrant */ ++ if (ret > 0) ++ return ; ++ BUG_ON(ret < 0); ++ ++ if (!clk->ops || !clk->ops->disable) ++ return; ++ ++ clk->ops->disable(clk); ++ ++ if (clk->parent) ++ clk_disable(clk->parent); ++ ++ return ; ++} ++ ++EXPORT_SYMBOL(clk_disable); ++ ++unsigned long clk_get_rate(struct clk *clk) ++{ ++#ifndef CONFIG_MACH_CYGNUS ++ /* Recurse to update parent's frequency */ ++ if (clk->parent) ++ clk_get_rate(clk->parent); ++ ++ /* Read hardware registers if needed */ ++ if (clk->ops && clk->ops->status) ++ clk->ops->status(clk); ++#endif ++ ++#ifdef CONFIG_MACH_CYGNUS ++ printk(KERN_INFO "INFO-Cygnus:%d:%s() clk->name= %s clk->rate= %d\n", __LINE__, __func__, clk->name, clk->rate); ++#endif ++ return clk->rate; ++ ++} ++ ++EXPORT_SYMBOL(clk_get_rate); ++ ++long clk_round_rate(struct clk *clk, unsigned long rate) ++{ ++ long ret = -EIO; ++ ++ if (clk->ops && clk->ops->round) ++ ret = clk->ops->round(clk, rate); ++ ++ return ret; ++} ++ ++EXPORT_SYMBOL(clk_round_rate); ++ ++int clk_set_rate(struct clk *clk, unsigned long rate) ++{ ++ int ret = -EIO; ++ ++ if (rate == clk->rate) ++ return 0; ++ ++ if (clk->ops && clk->ops->setrate) ++ ret = clk->ops->setrate(clk, rate); ++ ++ return ret; ++} ++ ++EXPORT_SYMBOL(clk_set_rate); ++ ++/* ++ * clk_get(), clk_put() are implemented in arch/arm/common/clock.c ++ * but it needs these two stub functions for platform-specific operations. ++ * Reeturn 1 on success 0 on failure. ++ */ ++ ++int __clk_get(struct clk *clk) ++{ ++ int ret ; ++ ++ ret = atomic_inc_return( &clk->use_cnt ); ++ if (ret > 1) ++ return 1; ++ ++ if (clk->parent) ++ return __clk_get( clk->parent ); ++ ++ return 1; ++} ++ ++void __clk_put(struct clk *clk) ++{ ++ int ret; ++ ++ ret = atomic_dec_return( &clk->use_cnt); ++ if (ret > 0) ++ return; ++ ++ BUG_ON(ret < 0); ++ ++ if (clk->parent) ++ __clk_put(clk->parent); ++} +diff --git a/arch/arm/plat-iproc/headsmp.S b/arch/arm/plat-iproc/headsmp.S +new file mode 100644 +index 0000000..4cf0efa +--- /dev/null ++++ b/arch/arm/plat-iproc/headsmp.S +@@ -0,0 +1,106 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* Based on arch/arm/mach-realview/headsmp.S */ ++/* ++ * linux/arch/arm/mach-realview/headsmp.S ++ * ++ * Copyright (c) 2003 ARM Limited ++ * 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 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * This is called from head.S to fix the u-boot not initializing ++ * MMU and cache the way Linux likes it to be. I have talked to ++ * u-boot developer to fix it in u-boot. This will remain as a ++ * safety. Don't use r1 and r2 as u-boot/CFE may pass some parameters ++ * for the kernel. ++ * When this code completes execution, we expect the following: ++ * MMU = OFF ++ * D-Cache = OFF ++ * I-Cache = Don't Care ++ * regs r0 = 0 r1 = machine id and r2 = atags pointer or 0 ++ */ ++ __HEAD ++ENTRY(__iproc_head_fixup) ++ mov r12, lr @ Save the return address ++ mrc p15, 0, r8, c1, c0, 0 @ Read SCTLR ++ mrc p15, 0, r9, c1, c0, 1 @ Read ACTLR ++ mrc p15, 0, r10, c2, c0, 0 @ Read TTBR0 ++ mrc p15, 0, r11, c2, c0, 1 @ Read TTBR1 ++ mrc p15, 0, r7, c2, c0, 2 @ Read TTBCR ++ mov r0, r8 ++ bic r0, #CR_C||CR_M ++ mcr p15, 0, r0, c1, c0, 0 @ Write the control register ++ nop ++ mrc p15, 0, r0, c1, c0, 0 @ Read the control register ++ bic r0, #CR_C|CR_A|CR_M|CR_W ++ bic r0, #CR_I|CR_Z ++ mcr p15, 0, r0, c1, c0, 0 @ Write the control register ++ nop ++ mov r0, #0 ++ @ L2 cache controller control register ++ ldr r3, =IPROC_L2CC_REG_BASE ++ str r0, [r3, #0x100] @ Disable L2 cache ++ bl __v7_invalidate_dcache_all ++ ++ mov r0, #0 ++ mov pc, r12 @ Return for regular boot ++ nop ++ENDPROC(__iproc_head_fixup) ++ ++/* ++ * iProc specific entry point for secondary CPUs. This provides ++ * a "holding pen" into which all secondary cores are held until we're ++ * ready for them to initialise. ++ */ ++#ifdef CONFIG_SMP ++ENTRY(iproc_secondary_startup) ++#ifdef CONFIG_CPU_ENDIAN_BE8 ++ setend be ++#endif ++ bl v7_invalidate_l1 ++ bl v7_flush_dcache_all ++ 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(iproc_secondary_startup) ++#endif +diff --git a/arch/arm/plat-iproc/hotplug.c b/arch/arm/plat-iproc/hotplug.c +new file mode 100644 +index 0000000..94dd062 +--- /dev/null ++++ b/arch/arm/plat-iproc/hotplug.c +@@ -0,0 +1,147 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++extern volatile int pen_release; ++ ++static DECLARE_COMPLETION(cpu_killed); ++ ++static inline void cpu_enter_lowpower(void) ++{ ++ unsigned int v; ++ ++ flush_cache_all(); ++ asm volatile( ++ " mcr p15, 0, %1, c7, c5, 0\n" ++ " mcr p15, 0, %1, c7, c10, 4\n" ++ /* ++ * Turn off coherency ++ */ ++ " mrc p15, 0, %0, c1, c0, 1\n" ++ " bic %0, %0, #0x20\n" ++ " mcr p15, 0, %0, c1, c0, 1\n" ++ " mrc p15, 0, %0, c1, c0, 0\n" ++ " bic %0, %0, #0x04\n" ++ " mcr p15, 0, %0, c1, c0, 0\n" ++ : "=&r" (v) ++ : "r" (0) ++ : "cc"); ++} ++ ++static inline void cpu_leave_lowpower(void) ++{ ++ unsigned int v; ++ ++ asm volatile( "mrc p15, 0, %0, c1, c0, 0\n" ++ " orr %0, %0, #0x04\n" ++ " mcr p15, 0, %0, c1, c0, 0\n" ++ " mrc p15, 0, %0, c1, c0, 1\n" ++ " orr %0, %0, #0x20\n" ++ " mcr p15, 0, %0, c1, c0, 1\n" ++ : "=&r" (v) ++ : ++ : "cc"); ++} ++ ++static inline void platform_do_lowpower(unsigned int cpu) ++{ ++ /* ++ * there is no power-control hardware on this platform, so all ++ * we can do is put the core into WFI; this is safe as the calling ++ * code will have already disabled interrupts ++ */ ++ for (;;) { ++ /* ++ * here's the WFI ++ */ ++ asm(".inst 0xe320f003\n" ++ : ++ : ++ : "memory", "cc"); ++ ++ if (pen_release == cpu) { ++ /* ++ * OK, proper wakeup, we're done ++ */ ++ break; ++ } ++ ++ /* ++ * getting here, means that we have come out of WFI without ++ * having been woken up - this shouldn't happen ++ * ++ * The trouble is, letting people know about this is not really ++ * possible, since we are currently running incoherently, and ++ * therefore cannot safely call printk() or anything else ++ */ ++#ifdef DEBUG ++ printk("CPU%u: spurious wakeup call\n", cpu); ++#endif ++ } ++} ++ ++int platform_cpu_kill(unsigned int cpu) ++{ ++ return wait_for_completion_timeout(&cpu_killed, 5000); ++} ++ ++/* ++ * platform-specific code to shutdown a CPU ++ * ++ * Called with IRQs disabled ++ */ ++void platform_cpu_die(unsigned int cpu) ++{ ++#ifdef DEBUG ++ unsigned int this_cpu = hard_smp_processor_id(); ++ ++ if (cpu != this_cpu) { ++ printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", ++ this_cpu, cpu); ++ BUG(); ++ } ++#endif ++ ++ printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); ++ complete(&cpu_killed); ++ ++ /* ++ * we're ready for shutdown now, so do it ++ */ ++ cpu_enter_lowpower(); ++ platform_do_lowpower(cpu); ++ ++ /* ++ * bring this CPU back into the world of cache ++ * coherency, and then restore interrupts ++ */ ++ cpu_leave_lowpower(); ++} ++ ++int platform_cpu_disable(unsigned int cpu) ++{ ++ /* ++ * we don't allow CPU 0 to be shutdown (it is still too special ++ * e.g. clock tick interrupts) ++ */ ++ return cpu == 0 ? -EPERM : 0; ++} +diff --git a/arch/arm/plat-iproc/include/mach/brcm_rdb_rng.h b/arch/arm/plat-iproc/include/mach/brcm_rdb_rng.h +new file mode 100644 +index 0000000..c17e951 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/brcm_rdb_rng.h +@@ -0,0 +1,64 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __BRCM_RDB_RNG_H__ ++#define __BRCM_RDB_RNG_H__ ++ ++#define RNG_CTRL_OFFSET 0x00000000 ++#define RNG_CTRL_TYPE UInt32 ++#define RNG_CTRL_RESERVED_MASK 0xF00000CC ++#define RNG_CTRL_RNG_COMBLK2_OSC_DIS_SHIFT 22 ++#define RNG_CTRL_RNG_COMBLK2_OSC_DIS_MASK 0x0FC00000 ++#define RNG_CTRL_RNG_COMBLK1_OSC_DIS_SHIFT 16 ++#define RNG_CTRL_RNG_COMBLK1_OSC_DIS_MASK 0x003F0000 ++#define RNG_CTRL_RNG_JCLK_BYP_DIV_CNT_SHIFT 8 ++#define RNG_CTRL_RNG_JCLK_BYP_DIV_CNT_MASK 0x0000FF00 ++#define RNG_CTRL_RNG_JCLK_BYP_SRC_SHIFT 5 ++#define RNG_CTRL_RNG_JCLK_BYP_SRC_MASK 0x00000020 ++#define RNG_CTRL_RNG_JCLK_BYP_SEL_SHIFT 4 ++#define RNG_CTRL_RNG_JCLK_BYP_SEL_MASK 0x00000010 ++#define RNG_CTRL_RNG_RBG2X_SHIFT 1 ++#define RNG_CTRL_RNG_RBG2X_MASK 0x00000002 ++#define RNG_CTRL_RNG_RBGEN_SHIFT 0 ++#define RNG_CTRL_RNG_RBGEN_MASK 0x00000001 ++ ++#define RNG_STATUS_OFFSET 0x00000004 ++#define RNG_STATUS_TYPE UInt32 ++#define RNG_STATUS_RESERVED_MASK 0x00F00000 ++#define RNG_STATUS_RND_VAL_SHIFT 24 ++#define RNG_STATUS_RND_VAL_MASK 0xFF000000 ++#define RNG_STATUS_RNG_WARM_CNT_SHIFT 0 ++#define RNG_STATUS_RNG_WARM_CNT_MASK 0x000FFFFF ++ ++#define RNG_DATA_OFFSET 0x00000008 ++#define RNG_DATA_TYPE UInt32 ++#define RNG_DATA_RESERVED_MASK 0x00000000 ++#define RNG_DATA_RNG_NUM_SHIFT 0 ++#define RNG_DATA_RNG_NUM_MASK 0xFFFFFFFF ++ ++#define RNG_FF_THRES_OFFSET 0x0000000C ++#define RNG_FF_THRES_TYPE UInt32 ++#define RNG_FF_THRES_RESERVED_MASK 0xFFFFFFE0 ++#define RNG_FF_THRES_RNG_FF_THRESH_SHIFT 0 ++#define RNG_FF_THRES_RNG_FF_THRESH_MASK 0x0000001F ++ ++#define RNG_INT_MASK_OFFSET 0x00000010 ++#define RNG_INT_MASK_TYPE UInt32 ++#define RNG_INT_MASK_RESERVED_MASK 0xFFFFFFFE ++#define RNG_INT_MASK_RNG_INT_OFF_SHIFT 0 ++#define RNG_INT_MASK_RNG_INT_OFF_MASK 0x00000001 ++ ++#endif /* __BRCM_RDB_RNG_H__ */ +diff --git a/arch/arm/plat-iproc/include/mach/bridge-regs.h b/arch/arm/plat-iproc/include/mach/bridge-regs.h +new file mode 100644 +index 0000000..1d2299b +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/bridge-regs.h +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* ++ * Mbus-L to Mbus Bridge Registers ++ * ++ */ ++ ++#ifndef __ASM_ARCH_BRIDGE_REGS_H ++#define __ASM_ARCH_BRIDGE_REGS_H ++ ++#include ++ ++#define CPU_CONFIG (BRIDGE_VIRT_BASE | 0x0000) ++ ++#define CPU_CONTROL (BRIDGE_VIRT_BASE | 0x0104) ++#define CPU_CTRL_PCIE0_LINK 0x00000001 ++#define CPU_RESET 0x00000002 ++#define CPU_CTRL_PCIE1_LINK 0x00000008 ++ ++#define RSTOUTn_MASK (BRIDGE_VIRT_BASE | 0x0108) ++#define SOFT_RESET_OUT_EN 0x00000004 ++ ++#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE | 0x010c) ++#define SOFT_RESET 0x00000001 ++ ++#define BRIDGE_CAUSE (BRIDGE_VIRT_BASE | 0x0110) ++#define BRIDGE_MASK (BRIDGE_VIRT_BASE | 0x0114) ++#define BRIDGE_INT_TIMER0 0x0002 ++#define BRIDGE_INT_TIMER1 0x0004 ++#define BRIDGE_INT_TIMER1_CLR (~0x0004) ++ ++#define IRQ_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0200) ++#define IRQ_CAUSE_LOW_OFF 0x0000 ++#define IRQ_MASK_LOW_OFF 0x0004 ++#define FIQ_MASK_LOW_OFF 0x0008 ++#define ENDPOINT_MASK_LOW_OFF 0x000c ++#define IRQ_CAUSE_HIGH_OFF 0x0010 ++#define IRQ_MASK_HIGH_OFF 0x0014 ++#define FIQ_MASK_HIGH_OFF 0x0018 ++#define ENDPOINT_MASK_HIGH_OFF 0x001c ++#define PCIE_INTERRUPT_MASK_OFF 0x0020 ++ ++#define IRQ_MASK_LOW (IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF) ++#define FIQ_MASK_LOW (IRQ_VIRT_BASE + FIQ_MASK_LOW_OFF) ++#define ENDPOINT_MASK_LOW (IRQ_VIRT_BASE + ENDPOINT_MASK_LOW_OFF) ++#define IRQ_MASK_HIGH (IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF) ++#define FIQ_MASK_HIGH (IRQ_VIRT_BASE + FIQ_MASK_HIGH_OFF) ++#define ENDPOINT_MASK_HIGH (IRQ_VIRT_BASE + ENDPOINT_MASK_HIGH_OFF) ++#define PCIE_INTERRUPT_MASK (IRQ_VIRT_BASE + PCIE_INTERRUPT_MASK_OFF) ++ ++#define POWER_MANAGEMENT (BRIDGE_VIRT_BASE | 0x011c) ++ ++#define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300) ++ ++#endif +diff --git a/arch/arm/plat-iproc/include/mach/clkdev.h b/arch/arm/plat-iproc/include/mach/clkdev.h +new file mode 100644 +index 0000000..d77f186 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/clkdev.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __MACH_CLKDEV_H ++#define __MACH_CLKDEV_H ++ ++#include ++#include ++ ++struct clk { ++ const struct clk_ops *ops; ++ const char *name; ++ atomic_t ena_cnt; ++ atomic_t use_cnt; ++ unsigned long rate; ++ unsigned gated :1; ++ unsigned fixed :1; ++ unsigned chan :6; ++ void __iomem *regs_base; ++ struct clk *parent; ++ /* TBD: could it have multiple parents to select from ? */ ++ enum { ++ CLK_XTAL, CLK_GATE, CLK_PLL, CLK_DIV, CLK_PHA ++ } type; ++}; ++ ++extern int __clk_get(struct clk *); ++extern void __clk_put(struct clk *); ++ ++#endif +diff --git a/arch/arm/plat-iproc/include/mach/clock.h b/arch/arm/plat-iproc/include/mach/clock.h +new file mode 100644 +index 0000000..3ad8a76 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/clock.h +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef CLOCK_H ++#define CLOCK_H ++ ++#include ++ ++/* ++ * Operations on clocks - ++ * See for description ++ */ ++struct clk_ops { ++ int (* enable)(struct clk *); ++ void (* disable)(struct clk *); ++ long (* round)(struct clk *, unsigned long); ++ int (* setrate)(struct clk *, unsigned long); ++ /* Update current rate and return running status */ ++ int (* status)(struct clk *); ++}; ++ ++#endif +diff --git a/arch/arm/plat-iproc/include/mach/common.h b/arch/arm/plat-iproc/include/mach/common.h +new file mode 100644 +index 0000000..69f8f95 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/common.h +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * ++ * Core functions for Broadcom Northstar SoC Chip ++ */ ++ ++#ifndef __ARCH_IPROC_COMMON_H ++#define __ARCH_IPROC_COMMON_H ++ ++struct mv643xx_eth_platform_data; ++struct mv_sata_platform_data; ++ ++extern struct sys_timer IPROC_timer; ++extern struct mbus_dram_target_info iproc_mbus_dram_info; ++ ++/* ++ * Basic IPROC init functions used early by machine-setup. ++ */ ++void IPROC_map_io(void); ++void IPROC_init(void); ++void IPROC_init_irq(void); ++void IPROC_setup_cpu_mbus(void); ++void IPROC_ge00_init(struct mv643xx_eth_platform_data *eth_data); ++void IPROC_sata_init(struct mv_sata_platform_data *sata_data); ++void IPROC_pcie_init(int init_port0, int init_port1); ++void IPROC_ehci0_init(void); ++void IPROC_ehci1_init(void); ++void IPROC_uart0_init(void); ++void IPROC_uart1_init(void); ++void IPROC_uart2_init(void); ++void IPROC_uart3_init(void); ++void IPROC_spi0_init(void); ++void IPROC_spi1_init(void); ++void IPROC_i2c_init(void); ++ ++#endif +diff --git a/arch/arm/plat-iproc/include/mach/debug-macro.S b/arch/arm/plat-iproc/include/mach/debug-macro.S +new file mode 100644 +index 0000000..6c963a4 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/debug-macro.S +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* ++ * Debugging macro include header ++ */ ++#include ++#include ++#include ++ ++ .macro addruart, tmp, tmp2, rx ++ ldr \tmp, =IPROC_UART_LLDEBUG_PA @ MMU off, Physical ++ ldr \tmp2, =IPROC_UART_LLDEBUG_VA @ MMU on, Virtual ++ .endm ++ ++#chandra: ++#ifdef CONFIG_MACH_CYGNUS ++ #define UART_SHIFT 2 //for synopsysUart has 4 byte addressing ++#else ++ #define UART_SHIFT 0 //for CCA_UART has 1 byte addressing ++#endif ++ ++#include +diff --git a/arch/arm/plat-iproc/include/mach/entry-macro.S b/arch/arm/plat-iproc/include/mach/entry-macro.S +new file mode 100644 +index 0000000..d859b49 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/entry-macro.S +@@ -0,0 +1,99 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++ ++ .macro disable_fiq ++ .endm ++ ++ /* ++ * This is the interrupt handling part of the GIC code - ++ * the base_va exists in a variable, but here is defined ++ * at compile time for effeciency (?) ++ */ ++ ++ .macro get_irqnr_preamble, base, tmp ++ ldr \base, =IPROC_GICCPU_VA ++ .endm ++ ++ /* ++ * Interrupts 0-15 are IPI ++ * 16-31 are local ++ * 32-1020 are global ++ * 1021-1022 are reserved ++ * 1023 is "spurious" (no interrupt) ++ * ++ * Spurious interrupt must be ignored in all events. ++ * When in SMP mode, then IPI interrupts must be ignored here, ++ * amd picked up later with the test_for_ipi macro. ++ * When in SMP mode and local timers are enabled, ++ * the private timer/watchdog interrupt must be ignored here ++ * so it can be handled later in test_for_ltirq routine. ++ * ++ * A simple read from the controller will tell us the number of the ++ * highest priority enabled interrupt. We then just need to check ++ * whether it is in the range that must be handled. ++ * ++ * Upon return, Z=1 tells to ignore this interrupt ++ */ ++ ++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ++ ++ /* bits 12-10 = src CPU, 9-0 = int # */ ++ ldr \irqstat, [\base, #GIC_CPU_INTACK] ++ ldr \tmp, =1021 ++ ++ bic \irqnr, \irqstat, #0x1c00 ++ ++ /* Private timers to call do_local_timer() */ ++ cmp \irqnr, #29 ++ beq 29f ++ ++ /* SPI to call asm_do_IRQ(); IPI to call do_IPI() */ ++ cmp \irqnr, #15 ++ cmpcc \irqnr, \irqnr ++ cmpne \irqnr, \tmp ++ cmpcs \irqnr, \irqnr ++ ++ /* SPI if NE; IPI (0-15) or private timer (29) if EQ */ ++29: ++ .endm ++ ++ @code taken from realview/entry-macro.S ++ /* We assume that irqstat (the raw value of the IRQ acknowledge ++ * register) is preserved from the macro above. ++ * If there is an IPI, we immediately signal end of interrupt on the ++ * controller, since this requires the original irqstat value which ++ * we won't easily be able to recreate later. ++ */ ++ .macro test_for_ipi, irqnr, irqstat, base, tmp ++ bic \irqnr, \irqstat, #0x1c00 ++ cmp \irqnr, #16 ++ strcc \irqstat, [\base, #GIC_CPU_EOI] ++ cmpcs \irqnr, \irqnr ++ .endm ++ ++ .macro test_for_ltirq, irqnr, irqstat, base,tmp ++ bic \irqnr, \irqstat, #0x1c00 ++ mov \tmp, #0 ++ cmp \irqnr, #29 ++ moveq \tmp, #1 ++ streq \irqstat, [\base, #GIC_CPU_EOI] ++ cmp \tmp, #0 ++ .endm ++ ++ .macro arch_ret_to_user, tmp1, tmp2 ++ .endm +diff --git a/arch/arm/plat-iproc/include/mach/gpio.h b/arch/arm/plat-iproc/include/mach/gpio.h +new file mode 100644 +index 0000000..326b73c +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/gpio.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_GPIO_H ++#define __PLAT_GPIO_H ++ ++#include ++#include ++ ++#include ++ ++ ++#define gpio_to_irq(gpio) __gpio_to_irq(gpio) ++//#define gpio_get_value(gpio) __gpio_get_value(gpio) ++//#define gpio_set_value(gpio,value) __gpio_set_value(gpio,value) ++//#define gpio_cansleep(gpio) __gpio_cansleep(gpio) ++ ++#endif +diff --git a/arch/arm/plat-iproc/include/mach/hardware.h b/arch/arm/plat-iproc/include/mach/hardware.h +new file mode 100644 +index 0000000..b373b58 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/hardware.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_IPROC_HARDWARE_H ++#define __PLAT_IPROC_HARDWARE_H ++ ++#include ++#include ++#include ++ ++/* Hardware addresses of major areas. ++ * *_START is the physical address ++ * *_SIZE is the size of the region ++ * *_BASE is the virtual address ++ */ ++#define RAM_START PHYS_OFFSET ++ ++#define RAM_BASE PAGE_OFFSET ++ ++#define IO_START IO_START_PA ++#define IO_BASE IO_START_VA ++ ++/* In case we use physical addresses */ ++#define IO_ADDRESS(x) (x) ++ ++#define pcibios_assign_all_busses() 1 ++ ++#define PCIBIOS_MIN_IO 0x1000 ++#define PCIBIOS_MIN_MEM 0x01000000 ++ ++#endif /* __PLAT_IPROC_HARDWARE_H */ +diff --git a/arch/arm/plat-iproc/include/mach/io.h b/arch/arm/plat-iproc/include/mach/io.h +new file mode 100644 +index 0000000..b980406 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/io.h +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_IPROC_IO_H ++#define __PLAT_IPROC_IO_H ++ ++#define IO_SPACE_LIMIT (0xffffffff) ++ ++#define __io(a) __typesafe_io(a) ++#define __mem_pci(a) (a) ++ ++#ifdef __ASSEMBLER__ ++#define IOMEM(x) (x) ++#else ++#define IOMEM(x) ((void __force __iomem *)(x)) ++#endif ++ ++#define VC_DIRECT_ACCESS_BASE 0xC0000000UL ++#define ARM_VC_PHYS_ADDR_BASE 0x40000000UL ++#define __VC_BUS_TO_ARM_PHYS_ADDR(x) ((x) - (VC_DIRECT_ACCESS_BASE) + \ ++ (ARM_VC_PHYS_ADDR_BASE)) ++ ++#endif /*__PLAT_IPROC_IO_H */ +diff --git a/arch/arm/plat-iproc/include/mach/iproc.h b/arch/arm/plat-iproc/include/mach/iproc.h +new file mode 100644 +index 0000000..bf01f6e +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/iproc.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_IPROC_H ++#define __PLAT_IPROC_H ++ ++#include ++ ++extern struct sys_timer iproc_timer; ++ ++extern void __init iproc_init_irq(void); ++//static void __init gic_dist_init(struct gic_chip_data *gic); ++ ++#endif /* __PLAT_IPROC_H */ +diff --git a/arch/arm/plat-iproc/include/mach/iproc_timer.h b/arch/arm/plat-iproc/include/mach/iproc_timer.h +new file mode 100644 +index 0000000..5809403 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/iproc_timer.h +@@ -0,0 +1,148 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_IPROC_TIMER_H ++#define __PLAT_IPROC_TIMER_H ++ ++/* Timer module specific data structures */ ++enum timer_rate { ++ KHZ_32 = 0, ++ MHZ_1, ++ MHZ_19_5, ++}; ++ ++struct iproc_timer; ++ ++/* Channel specific data structures */ ++typedef int (*intr_callback)(void *data); ++ ++enum timer_mode { ++ MODE_PERIODIC=0, ++ MODE_ONESHOT, ++}; ++ ++struct timer_ch_cfg { ++ void *arg; ++ enum timer_mode mode; ++ intr_callback cb; ++ unsigned long reload; /* Holds the reload value in ++ * case of periodic timers ++ */ ++}; ++ ++/* Timer Module related APIs */ ++ ++/* ++ * USAGE OF THIS APIs ++ * ------------------ ++ * From the board specific file, the iproc_timer_modules_init will be called ++ * After that it will call the init function of timer.c and will pass the ++ * following information in a platform structure ++ * 1) Timer name to be used as system timer ++ * 2) Frequency to be configured for system timer ++ * 3) The channel of the timer to use as clock source (optional) ++ * 4) The channel of the timer to use as clock event (optional) ++ * ++ * from the init function of timer.c iproc_timer_modules_set_rate will be called ++ * to set the system timer frequency. ++ * Then the appropriate channels would be setup for clock source/event by ++ * calling iproc_timer_request() ++ */ ++ ++/* ++ * iproc_timer_modules_init - Initialize the data structures ++ * that depcits the iProc timer modules ++ */ ++void iproc_timer_modules_init (void); ++ ++/* ++ * iproc_timer_module_set_rate - Set the speed in which a timer module should count ++ * name - Name of the Timer to configure ++ * rate - Speed ++ */ ++int iproc_timer_module_set_rate(char* name, enum timer_rate); ++ ++/* ++ * iproc_timer_module_get_rate - Get the speed in which a timer module is running ++ * name - Name of the Timer module ++ */ ++int iproc_timer_module_get_rate (char* name); ++ ++ ++/* Channel/Timer related APIs */ ++/* ++ * iproc_timer_request - Get access to a channel in the given timer ++ * name - Name of the Timer module ++ * channel - Channel number requested. If this is -1 then by default ++ * the next available channel will be returned ++ */ ++struct iproc_timer* iproc_timer_request(char* name, int channel); ++ ++/* ++ * iproc_timer_config - Configure the following parameters of the timer ++ * 1) mode of the timer - periodic/one shot ++ * 2) call back function that will be called from the ISR context ++ * 3) context to be passed back in the call back function ++ * ++ * pit - iProc timer context (returned by iproc_timer_request()) ++ * pcfg - pointer to the configuration structure ++ */ ++int iproc_timer_config (struct iproc_timer *pit, struct timer_ch_cfg *pcfg); ++ ++/* ++ * iproc_timer_set_match_start - Set the match register for the timer and start ++ * counting ++ * ++ * pit - iProc timer context (returned by iproc_timer_request()) ++ * load - The load value to be programmed. This function will internally ++ * add this value to the current counter and program the resultant in the ++ * match register. Once the timer is started when the counter ++ * reaches this value an interrupt will be raised ++ */ ++int iproc_timer_set_match_start (struct iproc_timer* pit, unsigned int load); ++ ++/* ++ * iproc_timer_free - Read the counter register of the timer ++ * ++ * pit - Timer context to be freed. ++ * msw - pointer to the Most Significant Word (32 bits) ++ * lsw - pointer to the Leas Significant Word (32 bits) ++ */ ++int iproc_timer_get_counter(struct iproc_timer* pit, ++ unsigned long *msw, unsigned long *lsw); ++/* ++ * iproc_timer_disable_and_clear - Disable the timer and clear the ++ * interrupt ++ * ++ * pit - Timer context to be freed. ++ */ ++int iproc_timer_disable_and_clear(struct iproc_timer *pit); ++ ++/* ++ * iproc_timer_stop - Stop the timer. ++ * ++ * pit - The timer context to be stopped. ++ */ ++int iproc_timer_stop (struct iproc_timer* pit); ++ ++/* ++ * iproc_timer_free - Release the timer, after this call the timer can be used ++ * again by others. ++ * ++ * pit - Timer context to be freed. ++ */ ++int iproc_timer_free (struct iproc_timer* pit); ++ ++#endif /* __PLAT_IPROC_TIMER_H */ +diff --git a/arch/arm/plat-iproc/include/mach/irqs.h b/arch/arm/plat-iproc/include/mach/irqs.h +new file mode 100644 +index 0000000..4078b05 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/irqs.h +@@ -0,0 +1,249 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_IPROC_IRQS_H ++#define __PLAT_IPROC_IRQS_H ++ ++#define IRQ_LOCALTIMER BCM_INT_ID_PPI13 ++#define BCM_INT_PRIORITY_MAX 32 /* there are only 32 priority are supported */ ++#define BCM_INT_SPI_MAX 128 /* there are 128 shared peripheral interrupt*/ ++/*=====================================================================*/ ++/* Software Trigger Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_STI0 0 ++#define BCM_INT_ID_STI1 1 ++#define BCM_INT_ID_STI2 2 ++#define BCM_INT_ID_STI3 3 ++#define BCM_INT_ID_STI4 4 ++#define BCM_INT_ID_STI5 5 ++#define BCM_INT_ID_STI6 6 ++#define BCM_INT_ID_STI7 7 ++#define BCM_INT_ID_STI8 8 ++#define BCM_INT_ID_STI9 9 ++#define BCM_INT_ID_STI10 10 ++#define BCM_INT_ID_STI11 11 ++#define BCM_INT_ID_STI12 12 ++#define BCM_INT_ID_STI13 13 ++#define BCM_INT_ID_STI14 14 ++#define BCM_INT_ID_STI15 15 ++#define BCM_INT_ID_STI_MAX 16 /* terminating ID */ ++ ++/*=====================================================================*/ ++/* Private Peripheral Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_PPI0 ( 0 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI1 ( 1 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI2 ( 2 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI3 ( 3 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI4 ( 4 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI5 ( 5 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI6 ( 6 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI7 ( 7 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI8 ( 8 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI9 ( 9 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI10 (10 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI11 (11 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI12 (12 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI13 (13 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI14 (14 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI15 (15 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI_MAX (16 + BCM_INT_ID_STI_MAX) /* terminating ID */ ++ ++/*=====================================================================*/ ++/* iHost Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_IHOST_L2CC 32 ++#define BCM_INT_ID_IHOST_PWRWDOG 33 ++#define BCM_INT_ID_IHOST_TRAP8 34 ++#define BCM_INT_ID_IHOST_TRAP1 35 ++#define BCM_INT_ID_IHOST_COMMTX 36 ++#define BCM_INT_ID_IHOST_COMMRX 38 ++#define BCM_INT_ID_IHOST_PMU 40 ++#define BCM_INT_ID_IHOST_CT 42 ++#define BCM_INT_ID_IHOST_DEFFLG_CPU0 44 ++#define BCM_INT_ID_IHOST_DEFFLG_CPU1 45 ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define BCM_INT_ID_IHOST_CPU0_PAR 46 ++#define BCM_INT_ID_IHOST_CPU1_PAR 47 ++#define BCM_INT_ID_IHOST_SCU0_PAR 48 ++#define BCM_INT_ID_IHOST_SCU1_PAR 49 ++#define BCM_INT_ID_IHOST_I2_SEC 50 ++#define BCM_INT_ID_IHOST_MAX 51 /* terminating ID */ ++#else ++#define BCM_INT_ID_IHOST_MAX 46 /* terminating ID */ ++#endif ++ ++ ++/*=====================================================================*/ ++/* IDM Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_IHOST_M1 ( 0 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_PCIE0_M0 ( 1 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_PCIE1_M0 ( 2 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_PCIE2_M0 ( 3 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DMA_M0 ( 4 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_AMAC_M0 ( 5 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_AMAC_M1 ( 6 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_AMAC_M2 ( 7 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_AMAC_M3 ( 8 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_USBH_M0 ( 9 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_USBH_M1 (10 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_SDIO_M0 (11 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_I2S_M0 (12 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_A9JTAG_M0 (13 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_INIT_SEQ_M0 (14 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_JTAG_M0 (15 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_IHOST_ACP (16 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_IHOST_S0 (17 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DDR_S1 (18 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DDR_S2 (19 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_PCIE0_S0 (20 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_PCIE1_S0 (21 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_PCIE2_S0 (22 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_ROM_S0 (23 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_NAND_S0 (24 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_QPSI_S0 (25 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_A9JTAG_S0 (26 + BCM_INT_ID_IHOST_MAX) ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define BCM_INT_ID_SATA_S0 (27 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_SRAM_S0 (28+ BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_APBW (29 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_APBX (30 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_APBY (31 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_APBZ (32 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_0 (33 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_1 (34 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_2 (35 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_3 (36 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_4 (37 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_IDM_MAX (38 + BCM_INT_ID_IHOST_MAX) ++#elif defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP) ++#define BCM_INT_ID_APBX (27 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_0 (28 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_1 (29 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_2 (30 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_3 (31 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_4 (32 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_IDM_MAX (33 + BCM_INT_ID_IHOST_MAX) ++#endif ++ ++/*=====================================================================*/ ++/* DDR Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_DDR_CONT (0 + BCM_INT_ID_IDM_MAX) ++#define BCM_INT_ID_DDR_MAX (1 + BCM_INT_ID_IDM_MAX) ++ ++/*=====================================================================*/ ++/* DMAC Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_DMAC (0 + BCM_INT_ID_DDR_MAX) ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define BCM_INT_ID_DMAC_ABORT (16 + BCM_INT_ID_DDR_MAX) ++#define BCM_INT_ID_DMAC_MAX (17 + BCM_INT_ID_DDR_MAX) ++#elif defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP) ++#define BCM_INT_ID_DMAC_MAX (16 + BCM_INT_ID_DDR_MAX) ++#endif ++ ++/*=====================================================================*/ ++/* NAND Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_NAND2CORE_RD_MISS ( 0 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_ER_COMP ( 1 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_CB_COMP ( 2 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_PP_COMP ( 3 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_ROCTL_RDY ( 4 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_NAND_RBB ( 5 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_ECC_MIPS_UNCOR ( 6 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_ECC_MIPS_COR ( 7 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_MAX ( 8 + BCM_INT_ID_DMAC_MAX) ++ ++/*=====================================================================*/ ++/* QPSI Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_QPSI2CORE_FULL_RCHD ( 0 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_TRUNCATED ( 1 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_IMAPTIENT ( 2 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_SES_DONE ( 3 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_OVERREAD ( 4 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_MPSI_DONE ( 5 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_MPSI_HLT_SET ( 6 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_MAX ( 7 + BCM_INT_ID_NAND2CORE_MAX) ++ ++/*=====================================================================*/ ++/* USB2 Host Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_USB2H2CORE_USB2_INT (0 + BCM_INT_ID_QPSI2CORE_MAX) ++#define BCM_INT_ID_USB2H2CORE_MAX (1 + BCM_INT_ID_QPSI2CORE_MAX) ++ ++/*=====================================================================*/ ++/* USB3 Host Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_USB3H2CORE_USB2_INT0 (0 + BCM_INT_ID_USB2H2CORE_MAX) ++#define BCM_INT_ID_USB3H2CORE_USB2_INT1 (1 + BCM_INT_ID_USB2H2CORE_MAX) ++#define BCM_INT_ID_USB3H2CORE_USB2_INT2 (2 + BCM_INT_ID_USB2H2CORE_MAX) ++#define BCM_INT_ID_USB3H2CORE_USB2_INT3 (3 + BCM_INT_ID_USB2H2CORE_MAX) ++#define BCM_INT_ID_USB3H2CORE_USB2_HSE (4 + BCM_INT_ID_USB2H2CORE_MAX) ++#define BCM_INT_ID_USB3H2CORE_MAX (5 + BCM_INT_ID_USB2H2CORE_MAX) ++ ++/*=====================================================================*/ ++/* CCA Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_CCA_INT (0 + BCM_INT_ID_USB3H2CORE_MAX) ++#define BCM_INT_ID_CCA_MAX (1 + BCM_INT_ID_USB3H2CORE_MAX) ++ ++/*=====================================================================*/ ++/* CCB Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_CCB_UART0 (0 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_GPIO (1 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_I2S (2 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_SMBUS (3 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_TIM0_INT1 (4 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_TIM0_INT2 (5 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_TIM1_INT1 (6 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_TIM1_INT2 (7 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_RNG (8 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_SW_SOC (9 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_PCIE_INT0 (10 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_PCIE_INT1 (11 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_PCIE_INT2 (12 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_SDIO2CORE (13 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_CTF (14 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_GMAC_INT0 (15 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_GMAC_INT1 (16 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_GMAC_INT2 (17 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_GMAC_INT3 (18 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_MAX (19 + BCM_INT_ID_CCA_MAX) ++ ++#define BCM_INT_ID_FA 178 ++ ++ ++#ifdef CONFIG_ARCH_REQUIRE_GPIOLIB ++#define IPROC_NR_IRQS (256) ++#define IPROC_IRQ_GPIO_0 (IPROC_NR_IRQS) ++#define IPROC_NR_GPIO_IRQS (32 + 4) ++#ifdef CONFIG_MACH_CYGNUS ++ #define NR_IRQS 256 ++#else ++#define NR_IRQS (IPROC_NR_IRQS + IPROC_NR_GPIO_IRQS) ++#endif ++#else ++#define NR_IRQS 256 ++#endif ++ ++#endif /* __PLAT_IPROC_IRQS_H */ +diff --git a/arch/arm/plat-iproc/include/mach/lm.h b/arch/arm/plat-iproc/include/mach/lm.h +new file mode 100644 +index 0000000..5c550a8 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/lm.h +@@ -0,0 +1,48 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _LM_DEVICE_H_ ++#define _LM_DEVICE_H_ ++ ++#include ++#include ++ ++ ++struct lm_device { ++ struct device dev; ++ struct resource resource; ++ unsigned int irq; ++ unsigned int id; ++}; ++ ++struct lm_driver { ++ struct device_driver drv; ++ int (*probe) (struct lm_device *); ++ void (*remove) (struct lm_device *); ++ int (*suspend) (struct lm_device *, pm_message_t); ++ int (*resume) (struct lm_device *); ++}; ++ ++int lm_driver_register(struct lm_driver *drv); ++void lm_driver_unregister(struct lm_driver *drv); ++ ++int lm_device_register(struct lm_device *dev); ++void lm_device_unregister(struct lm_device *dev); ++ ++#define lm_get_drvdata(lm) dev_get_drvdata(&(lm)->dev) ++#define lm_set_drvdata(lm,d) dev_set_drvdata(&(lm)->dev, d) ++ ++#endif /* _LM_DEVICE_H_ */ +diff --git a/arch/arm/plat-iproc/include/mach/memory.h b/arch/arm/plat-iproc/include/mach/memory.h +new file mode 100644 +index 0000000..87bee64 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/memory.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __PLAT_IPROC_MEMORY_H ++#define __PLAT_IPROC_MEMORY_H ++ ++#include ++ ++//#define PHYS_OFFSET (CONFIG_BCM_RAM_BASE+CONFIG_BCM_RAM_START_RESERVED_SIZE) ++ ++/* BCM5301x Reference Guide (Section 3) defines three regions of IO memory, ++ * CORE, IDM, and ARMCORE. The CORE and IDM regions are contiguous, so they ++ * are combined into a single region for mapping and translation purposes ++ */ ++ ++#define IO_CORE_IDM_PA 0x18000000 ++#define IO_CORE_IDM_SIZE 0x200000 ++#define IO_ARMCORE_PA 0x19000000 ++#define IO_ARMCORE_SIZE 0x100000 ++#define IO_SMAU_IDM_PA 0xf8100000 ++#define IO_SMAU_IDM_SIZE 0x100000 ++ ++#define IO_TOTAL_SIZE (IO_CORE_IDM_SIZE + \ ++ IO_ARMCORE_SIZE + \ ++ IO_SMAU_IDM_SIZE) ++ ++/* VA should be in the range of VMALLOC_START ~ VMALLOC_END-1 */ ++#define IO_CORE_IDM_VA (VMALLOC_END - IO_TOTAL_SIZE) ++#define IO_ARMCORE_VA (IO_CORE_IDM_VA + IO_CORE_IDM_SIZE) ++#define IO_SMAU_IDM_VA (IO_ARMCORE_VA + IO_ARMCORE_SIZE) ++ ++#define IO_CORE_IDM_PV_DELTA (IO_CORE_IDM_VA - IO_CORE_IDM_PA) ++#define IO_ARMCORE_PV_DELTA (IO_ARMCORE_VA - IO_ARMCORE_PA) ++#define IO_SMAU_IDM_PV_DELTA (IO_SMAU_IDM_VA - IO_SMAU_IDM_PA) ++ ++#define HW_IO_VIRT_TO_PHYS(virt) \ ++ (((virt) < IO_ARMCORE_VA) ? \ ++ ((virt) - IO_CORE_IDM_PV_DELTA) : \ ++ (((virt) < IO_SMAU_IDM_VA) ? \ ++ ((virt) - IO_ARMCORE_PV_DELTA) : \ ++ ((virt) - IO_SMAU_IDM_PV_DELTA))) ++ ++/* ++ * HW_IO_PHYS_TO_VIRT used in asm, so the macro that performs this conversion ++ * is written using only simple math so that the assembler's constant folding ++ * can produce the correct result. ++ ++ #define HW_IO_PHYS_TO_VIRT(phys) \ ++ (((phys) < IO_ARMCORE_PA) ? \ ++ ((phys) + IO_CORE_IDM_PV_DELTA) : \ ++ ((phys) + IO_ARMCORE_PV_DELTA)) ++ */ ++ ++#define HW_IO_PHYS_TO_VIRT(phys) \ ++ (((phys) + IO_CORE_IDM_PV_DELTA) + \ ++ (((phys) >= IO_ARMCORE_PA) * (IO_ARMCORE_PV_DELTA - IO_CORE_IDM_PV_DELTA)) + \ ++ (((phys) >= IO_SMAU_IDM_PA) * (IO_SMAU_IDM_PV_DELTA - IO_ARMCORE_PV_DELTA))) ++ ++#define CONSISTENT_DMA_SIZE SZ_128M ++ ++#ifndef PHYS_RAM_SIZE ++#define PHYS_RAM_SIZE 0x08000000 ++#endif ++ ++#endif /* __PLAT_IPROC_MEMORY_H */ +diff --git a/arch/arm/plat-iproc/include/mach/sdio_platform.h b/arch/arm/plat-iproc/include/mach/sdio_platform.h +new file mode 100644 +index 0000000..f8f17e1 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/sdio_platform.h +@@ -0,0 +1,67 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef _SDIO_PLATFORM_H ++#define _SDIO_PLATFORM_H ++ ++/* ++ * SDIO device type ++ */ ++enum sdio_devtype { ++ SDIO_DEV_TYPE_SDMMC = 0, ++ SDIO_DEV_TYPE_WIFI, ++ SDIO_DEV_TYPE_EMMC, ++ ++ /* used for internal array indexing, DO NOT modify */ ++ SDIO_DEV_TYPE_MAX, ++}; ++ ++/* ++ * SDIO WiFi GPIO configuration ++ */ ++struct sdio_wifi_gpio_cfg { ++ int reset; ++ int shutdown; ++ int reg; ++ int host_wake; ++}; ++ ++struct sdio_platform_cfg { ++ /* specify which SDIO device */ ++ unsigned id; ++ ++ /* ++ * For boards without the SDIO pullup registers, data_pullup needs to set ++ * to 1 ++ */ ++ unsigned int data_pullup; ++ ++ /* for devices with 8-bit lines */ ++ int is_8bit; ++ ++ /* card detection GPIO, required for SD/MMC */ ++ int cd_gpio; ++ enum sdio_devtype devtype; ++ ++ /* clocks */ ++ char *peri_clk_name; ++ char *ahb_clk_name; ++ char *sleep_clk_name; ++ unsigned long peri_clk_rate; ++ ++ struct sdio_wifi_gpio_cfg wifi_gpio; ++}; ++ ++#endif /* SDIO_PLATFORM_H */ +diff --git a/arch/arm/plat-iproc/include/mach/smp.h b/arch/arm/plat-iproc/include/mach/smp.h +new file mode 100644 +index 0000000..5a4b1f4 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/smp.h +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* ++ * derived from arch/arm/mach-realview/include/mach/smp.h ++ */ ++ ++#ifndef __ASM_ARCH_SMP_H ++#define __ASM_ARCH_SMP_H __FILE__ ++ ++#include ++ ++/* ++ * set_event() is used to wake up secondary core from wfe using sev. ROM ++ * code puts the second core into wfe(standby). ++ * ++ */ ++#define set_event() __asm__ __volatile__ ("sev" : : : "memory") ++ ++extern void iproc_secondary_startup(void); ++ ++#define hard_smp_processor_id() \ ++ ({ \ ++ unsigned int cpunum; \ ++ __asm__("mrc p15, 0, %0, c0, c0, 5" \ ++ : "=r" (cpunum)); \ ++ cpunum &= 0x0F; \ ++ }) ++ ++#endif /* __ASM_ARCH_SMP_H */ +diff --git a/arch/arm/plat-iproc/include/mach/system.h b/arch/arm/plat-iproc/include/mach/system.h +new file mode 100644 +index 0000000..bdabd06 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/system.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_IPROC_SYSTEM_H ++#define __PLAT_IPROC_SYSTEM_H ++ ++#include ++#include ++ ++ ++static void arch_idle(void) ++{ ++ /* ++ * This should do all the clock switching ++ * and wait for interrupt tricks ++ */ ++ cpu_do_idle(); ++} ++ ++static inline void arch_reset(char mode, const char *cmd) ++{ ++} ++ ++#endif /*__PLAT_IPROC_SYSTEM_H */ +diff --git a/arch/arm/plat-iproc/include/mach/timer.h b/arch/arm/plat-iproc/include/mach/timer.h +new file mode 100644 +index 0000000..1b28414 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/timer.h +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_TIMER_H ++#define __PLAT_TIMER_H ++ ++#ifdef __KERNEL__ ++ ++typedef unsigned int timer_tick_count_t; ++typedef unsigned int timer_tick_rate_t; ++typedef unsigned int timer_msec_t; ++ ++ ++enum gp_timer_rate { ++ GPT_KHZ_32 = 0, ++ GPT_MHZ_1, ++}; ++ ++/** ++ * timer configuration identifying the timer to use ++ * as system timer (GP Timer) ++ */ ++ struct gp_timer_setup { ++ char *name; ++ int ch_num; ++ enum gp_timer_rate rate; ++ }; ++ ++void iproc_timer_init (struct gp_timer_setup *gpt); ++ ++timer_tick_count_t timer_get_tick_count(void); ++timer_tick_rate_t timer_get_tick_rate(void); ++timer_msec_t timer_get_msec(void); ++timer_msec_t timer_ticks_to_msec(timer_tick_count_t ticks); ++ ++#endif /* __KERNEL__ */ ++#endif /* __PLAT_TIMER_H */ +diff --git a/arch/arm/plat-iproc/include/mach/timex.h b/arch/arm/plat-iproc/include/mach/timex.h +new file mode 100644 +index 0000000..265c48b +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/timex.h +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __PLAT_IPROC_TIMEX_H ++#define __PLAT_IPROC_TIMEX_H ++ ++/* ++ * Not very sure what the clock rate is. Revisit later ++*/ ++#define CLOCK_TICK_RATE (351875) ++ ++#endif /* __PLAT_IPROC_TIMEX_H */ +diff --git a/arch/arm/plat-iproc/include/mach/uncompress.h b/arch/arm/plat-iproc/include/mach/uncompress.h +new file mode 100644 +index 0000000..19002a6 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/uncompress.h +@@ -0,0 +1,54 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __ASM_ARCH_UNCOMPRESS_H ++#define __ASM_ARCH_UNCOMPRESS_H ++ ++#include ++#include ++ ++#define IPROC_UART0_PA IPROC_CCA_UART0_REG_BASE ++#define UART0_LSR_OFFSET 0x14 ++#define UART0_RBR_THR_DLL_OFFSET 0x00 ++#define UART0_LSR_THRE_MASK 0x60 ++#define UART0_LSR_TEMT_MASK 0x40 ++ ++static inline void putc(int c) ++{ ++ /* ++ * data should be written to THR register only ++ * if THRE (LSR bit5) is set) ++ */ ++ while (0 == (__raw_readl(IPROC_UART0_PA + ++ UART0_LSR_OFFSET) & UART0_LSR_THRE_MASK )) ++ { ++ } ++ ++ __raw_writel((unsigned long)c, IPROC_UART0_PA + UART0_RBR_THR_DLL_OFFSET); ++} ++ ++static inline void flush(void) ++{ ++ /* Wait for the tx fifo to be empty and last char to be sent */ ++ while (0 == (__raw_readl(IPROC_UART0_PA + ++ UART0_LSR_OFFSET) & UART0_LSR_TEMT_MASK )) ++ { ++ } ++} ++ ++#define arch_decomp_setup() ++#define arch_decomp_wdog() ++ ++#endif /* __ASM_ARCH_UNCOMPRESS_H */ +diff --git a/arch/arm/plat-iproc/include/plat/dma-pl330.h b/arch/arm/plat-iproc/include/plat/dma-pl330.h +new file mode 100644 +index 0000000..bf45e7b +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/dma-pl330.h +@@ -0,0 +1,103 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_DMA_H ++#define __PLAT_DMA_H ++ ++#include ++ ++#define MAX_CHAN_NAME_LENGTH 32 ++ ++/* DMA direction control */ ++enum dma_direction { ++ DMA_DIRECTION_MEM_TO_MEM = 0, ++ DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_DMAC = 1, ++ DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_PERI = 2, ++ DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_DMAC = 3, ++ DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_PERI = 4, ++ DMA_DIRECTION_DEV_TO_DEV = 5 /* Invalid, unsupported */ ++}; ++#define DMA_DIRECTION_MASK 0x7 ++ ++/* Channel configurations definition */ ++#define DMA_CFG_SRC_ADDR_FIXED (0x0 << 0) ++#define DMA_CFG_SRC_ADDR_INCREMENT (0x1 << 0) ++#define DMA_CFG_DST_ADDR_FIXED (0x0 << 14) ++#define DMA_CFG_DST_ADDR_INCREMENT (0x1 << 14) ++ ++#define DMA_CFG_BURST_SIZE_MASK (0x7 << 1) ++#define DMA_CFG_BURST_SIZE_1 (0x0 << 1) ++#define DMA_CFG_BURST_SIZE_2 (0x1 << 1) ++#define DMA_CFG_BURST_SIZE_4 (0x2 << 1) ++#define DMA_CFG_BURST_SIZE_8 (0x3 << 1) ++#define DMA_CFG_BURST_SIZE_16 (0x4 << 1) ++#define DMA_CFG_BURST_SIZE_32 (0x5 << 1) ++#define DMA_CFG_BURST_SIZE_64 (0x6 << 1) ++#define DMA_CFG_BURST_SIZE_128 (0x7 << 1) ++ ++#define DMA_CFG_BURST_LENGTH_MASK (0xF << 4) ++#define DMA_CFG_BURST_LENGTH_1 (0x0 << 4) ++#define DMA_CFG_BURST_LENGTH_2 (0x1 << 4) ++#define DMA_CFG_BURST_LENGTH_3 (0x2 << 4) ++#define DMA_CFG_BURST_LENGTH_4 (0x3 << 4) ++#define DMA_CFG_BURST_LENGTH_5 (0x4 << 4) ++#define DMA_CFG_BURST_LENGTH_6 (0x5 << 4) ++#define DMA_CFG_BURST_LENGTH_7 (0x6 << 4) ++#define DMA_CFG_BURST_LENGTH_8 (0x7 << 4) ++#define DMA_CFG_BURST_LENGTH_9 (0x8 << 4) ++#define DMA_CFG_BURST_LENGTH_10 (0x9 << 4) ++#define DMA_CFG_BURST_LENGTH_11 (0xA << 4) ++#define DMA_CFG_BURST_LENGTH_12 (0xB << 4) ++#define DMA_CFG_BURST_LENGTH_13 (0xC << 4) ++#define DMA_CFG_BURST_LENGTH_14 (0xD << 4) ++#define DMA_CFG_BURST_LENGTH_15 (0xE << 4) ++#define DMA_CFG_BURST_LENGTH_16 (0xF << 4) ++ ++#define DMA_CFG_BURST_LEN(x) (((x - 1) & 0xF) << 4) ++ ++/* src and dest burst size and burst length are assumed to be same */ ++ ++enum pl330_xfer_status { ++ DMA_PL330_XFER_OK, ++ DMA_PL330_XFER_ERR, ++ DMA_PL330_XFER_ABORT, ++}; ++ ++struct dma_transfer_list { ++ dma_addr_t srcaddr; /* src address */ ++ dma_addr_t dstaddr; /* dst address */ ++ unsigned int xfer_size; /* In bytes */ ++ struct list_head next; /* Next item */ ++}; ++ ++typedef void (*pl330_xfer_callback_t) (void *private_data, ++ enum pl330_xfer_status status); ++ ++int dma_request_chan(unsigned int *chan, const char *name); ++int dma_free_chan(unsigned int chan); ++int dma_map_peripheral(unsigned int chan, const char *peri_name); ++int dma_unmap_peripheral(unsigned int chan); ++int dma_setup_transfer(unsigned int chan, dma_addr_t s, dma_addr_t d, ++ unsigned int xfer_size, int ctrl, int cfg); ++int dma_setup_transfer_list(unsigned int chan, struct list_head *head, ++ int ctrl, int cfg); ++int dma_start_transfer(unsigned int chan); ++int dma_stop_transfer(unsigned int chan); ++int dma_shutdown_all_chan(void); ++int dma_register_callback(unsigned int chan, ++ pl330_xfer_callback_t cb, void *pri); ++int dma_free_callback(unsigned int chan); ++ ++#endif /* __PLAT_DMA_H */ +diff --git a/arch/arm/plat-iproc/include/plat/dma_drv.h b/arch/arm/plat-iproc/include/plat/dma_drv.h +new file mode 100644 +index 0000000..a7f8631 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/dma_drv.h +@@ -0,0 +1,603 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/** ++* ++* @file dma_drv.h ++* ++* @brief DMA device driver defines and prototypes. ++* ++****************************************************************************/ ++/** ++* ++* @defgroup DMAGroup Direct Memory Access ++* @ingroup CSLGroup ++* @brief This group defines the APIs for DMA driver ++ ++Click here to navigate back to the Chip Support Library Overview page: \ref CSLOverview. \n ++*****************************************************************************/ ++#ifndef _DMA_DRV_H_ ++#define _DMA_DRV_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @addtogroup DMAGroup ++ * @{ ++ */ ++ ++/** ++* ++* DMA driver status definition ++* ++*****************************************************************************/ ++#define DMADRV_STATUS_t DMADRV_STATUS ++typedef enum ++{ ++ DMADRV_STATUS_CLOSED, ++ DMADRV_STATUS_OPEN, ++ DMADRV_STATUS_OK, ++ DMADRV_STATUS_FAIL ++}DMADRV_STATUS_t; ++ ++/** ++* ++* DMA driver callback status definition ++* ++*****************************************************************************/ ++#define DMADRV_CALLBACK_STATUS_t DMADRV_CALLBACK_STATUS ++typedef enum ++{ ++ DMADRV_CALLBACK_OK = 0, ++ DMADRV_CALLBACK_FAIL ++} DMADRV_CALLBACK_STATUS_t; ++ ++/** ++* ++* DMA driver channel descriptor definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 src; ++ UInt32 dest; ++ UInt32 next; ++ UInt32 control; ++ UInt32 size; ++ UInt32 owner; ++} Dma_Chan_Desc; ++ ++/** ++* ++* DMA driver data buffer feature definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 srcAddr; ++ UInt32 destAddr; ++ UInt32 length; ++ UInt32 bRepeat; ++ UInt32 interrupt; ++} Dma_Buffer; ++ ++/** ++* ++* DMA driver data buffer definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ Dma_Buffer buffers[1]; ++} Dma_Buffer_List; ++ ++/** ++* ++* DMA driver data buffer list definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 numBuffer; ++ Dma_Buffer_List *pBufList; ++} Dma_Data; ++ ++ ++/** ++* ++* DMA data transfer width definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_DATA_SIZE_8BIT = 0x00, ++ DMA_DATA_SIZE_16BIT = 0x01, ++ DMA_DATA_SIZE_32BIT = 0x02 ++} DMA_DWIDTH; ++ ++/** ++* ++* DMA data transfer type definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_FCTRL_MEM_TO_MEM = 0, ++ DMA_FCTRL_MEM_TO_PERI = 1, ++ DMA_FCTRL_PERI_TO_MEM = 2, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI = 3, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI_CTRL_DESTPERI = 4, ++ DMA_FCTRL_MEM_TO_PERI_CTRL_PERI = 5, ++ DMA_FCTRL_PERI_TO_MEM_CTRL_PERI = 6, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI_CTRL_SRCPERI = 7 ++} DMA_CHAN_TYPE; ++ ++/** ++* ++* DMA burst length definition ++* ++*****************************************************************************/ ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++typedef enum { ++ DMA_BURST_LEN_1 = 0x00, ///< ++ DMA_BURST_LEN_2 = 0x01, ///< ++ DMA_BURST_LEN_3 = 0x02, ///< ++ DMA_BURST_LEN_4 = 0x03, ///< ++ DMA_BURST_LEN_5 = 0x04, ///< ++ DMA_BURST_LEN_6 = 0x05, ///< ++ DMA_BURST_LEN_7 = 0x06, ///< ++ DMA_BURST_LEN_8 = 0x07, ///< ++ DMA_BURST_LEN_9 = 0x08, ///< ++ DMA_BURST_LEN_10 = 0x09, ///< ++ DMA_BURST_LEN_11 = 0x0A, ///< ++ DMA_BURST_LEN_12 = 0x0B, ///< ++ DMA_BURST_LEN_13 = 0x0C, ///< ++ DMA_BURST_LEN_14 = 0x0D, ///< ++ DMA_BURST_LEN_15 = 0x0E, ///< ++ DMA_BURST_LEN_16 = 0x0F ///< ++} DMADRV_BLENGTH; ++ ++typedef enum ++{ ++ DMA_BURST_SIZE_1 = 0x00, ++ DMA_BURST_SIZE_2 = 0x01, ++ DMA_BURST_SIZE_4 = 0x02, ++ DMA_BURST_SIZE_8 = 0x03, ++ DMA_BURST_SIZE_16 = 0x04, ++ DMA_BURST_SIZE_32 = 0x05, ++ DMA_BURST_SIZE_64 = 0x06, ++ DMA_BURST_SIZE_128 = 0x07 ++} DMA_BSIZE; ++ ++#else ++/** ++* ++* DMA burst size definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_BURST_SIZE_1 = 0x00, ++ DMA_BURST_SIZE_4 = 0x01, ++ DMA_BURST_SIZE_8 = 0x02, ++ DMA_BURST_SIZE_16 = 0x03, ++ DMA_BURST_SIZE_32 = 0x04, ++ DMA_BURST_SIZE_64 = 0x05, ++ DMA_BURST_SIZE_128 = 0x06, ++ DMA_BURST_SIZE_256 = 0x07 ++} DMA_BSIZE; ++#endif ++ ++/** ++* ++* DMA alignment definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_ALIGNMENT_8 = 8, ++ DMA_ALIGNMENT_16 = 16, ++ DMA_ALIGNMENT_32 = 32 ++} DMA_ALIGN; ++ ++/** ++* ++* DMA data transfer incremnet definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_INC_MODE_NONE = 0, ++ DMA_INC_MODE_SRC, ++ DMA_INC_MODE_DST, ++ DMA_INC_MODE_BOTH, ++} DMA_INC_MODE; ++ ++/** ++* ++* DMA driver client type definition ++* ++*****************************************************************************/ ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++typedef enum { ++ DMA_CLIENT_EP_INVALID = 0xff, ++ DMA_CLIENT_EP_UARTB_A = 8, ++ DMA_CLIENT_EP_UARTB_B = 9, ++ DMA_CLIENT_EP_UARTB2_A = 10, ++ DMA_CLIENT_EP_UARTB2_B = 11, ++ DMA_CLIENT_EP_UARTB3_A = 12, ++ DMA_CLIENT_EP_UARTB3_B = 13, ++ DMA_CLIENT_EP_SSP_0A_RX0 = 16, ++ DMA_CLIENT_EP_SSP_0B_TX0 = 17, ++ DMA_CLIENT_EP_SSP_0C_RX1 = 18, ++ DMA_CLIENT_EP_SSP_0D_TX1 = 19, ++ DMA_CLIENT_EP_SSP_1A_RX0 = 20, ++ DMA_CLIENT_EP_SSP_1B_TX0 = 21, ++ DMA_CLIENT_EP_SSP_1C_RX1 = 22, ++ DMA_CLIENT_EP_SSP_1D_TX1 = 23, ++ DMA_CLIENT_EP_HSIA = 32, ++ DMA_CLIENT_EP_HSIB = 33, ++ DMA_CLIENT_EP_HSIC = 34, ++ DMA_CLIENT_EP_HSID = 35, ++ DMA_CLIENT_EP_EANC = 40, ++ DMA_CLIENT_EP_STEREO = 41, ++ DMA_CLIENT_EP_NVIN = 42, ++ DMA_CLIENT_EP_VIN = 43, ++ DMA_CLIENT_EP_VIBRA = 44, ++ DMA_CLIENT_EP_IHF_0 = 45, ++ DMA_CLIENT_EP_VOUT = 46, ++ DMA_CLIENT_EP_SLIMA = 47, ++ DMA_CLIENT_EP_SLIMB = 48, ++ DMA_CLIENT_EP_SLIMC = 49, ++ DMA_CLIENT_EP_SLIMD = 50, ++ DMA_CLIENT_EP_SIM_A = 51, ++ DMA_CLIENT_EP_SIM_B = 52, ++ DMA_CLIENT_EP_SIM2_A = 53, ++ DMA_CLIENT_EP_SIM2_B = 54, ++ DMA_CLIENT_EP_IHF_1 = 55, ++#if defined(_RHEA_) ++ DMA_CLIENT_EP_SSP_3A_RX0 = 56, ++ DMA_CLIENT_EP_SSP_3B_TX0 = 57, ++ DMA_CLIENT_EP_SSP_3C_RX1 = 58, ++ DMA_CLIENT_EP_SSP_3D_TX1 = 59, ++#else ++ DMA_CLIENT_EP_SSP_2A_RX0 = 56, ++ DMA_CLIENT_EP_SSP_2B_TX0 = 57, ++ DMA_CLIENT_EP_SSP_2C_RX1 = 58, ++ DMA_CLIENT_EP_SSP_2D_TX1 = 59, ++#endif ++ DMA_CLIENT_EP_SPUM_SecureA = 65, ++ DMA_CLIENT_EP_SPUM_SecureB = 66, ++ DMA_CLIENT_EP_SPUM_OpenA = 67, ++ DMA_CLIENT_EP_SPUM_OpenB = 68, ++ DMA_CLIENT_MEMORY = 69, ++#if defined(_RHEA_) ++ DMA_CLIENT_EP_SSP_4A_RX0 = 76, ++ DMA_CLIENT_EP_SSP_4B_TX0 = 77, ++ DMA_CLIENT_EP_SSP_4C_RX1 = 78, ++ DMA_CLIENT_EP_SSP_4D_TX1 = 79, ++#endif ++ DMA_CLIENT_TOTAL ++} DMA_CLIENT; ++#else ++typedef enum ++{ ++ DMA_CLIENT_BULK_CRYPT_OUT = 0, ++ DMA_CLIENT_CAM = 1, ++ DMA_CLIENT_I2S_TX = 2, ++ DMA_CLIENT_I2S_RX = 3, ++ DMA_CLIENT_SIM_RX = 4, ++ DMA_CLIENT_SIM_TX = 4, ++ DMA_CLIENT_CRC = 5, ++ DMA_CLIENT_SPI_RX = 6, ++ DMA_CLIENT_SPI_TX = 7, ++ DMA_CLIENT_UARTA_RX = 8, ++ DMA_CLIENT_UARTA_TX = 9, ++ DMA_CLIENT_UARTB_RX = 10, ++ DMA_CLIENT_UARTB_TX = 11, ++ DMA_CLIENT_DES_IN = 12, ++ DMA_CLIENT_DES_OUT = 13, ++ DMA_CLIENT_USB_RX = 14, ++ DMA_CLIENT_USB_TX = 15, ++ DMA_CLIENT_UARTC_RX = 16, ++ DMA_CLIENT_UARTC_TX = 17, ++ DMA_CLIENT_BULK_CRYPT_IN = 18, ++ DMA_CLIENT_LCD = 19, ++ DMA_CLIENT_MSPRO = 20, ++ DMA_CLIENT_DSI_CM = 21, ++ DMA_CLIENT_DSI_VM = 22, ++ DMA_CLIENT_TVENC1 = 23, ++ DMA_CLIENT_TVENC2 = 24, ++#if defined(_ATHENA_) ++ DMA_CLIENT_AUDIO_IN_FIFO = 25, ++ DMA_CLIENT_AUDIO_OUT_FIFO = 26, ++ DMA_CLIENT_POLYRING_OUT_FIFO = 27, ++ DMA_CLIENT_AUDIO_WB_MIXERTAP = 28, ++ DMA_CLIENT_MEMORY = 29, ++#else ++ DMA_CLIENT_MEMORY = 25, ++#endif ++ DMA_CLIENT_TOTAL ++} DMA_CLIENT; ++#endif ++ ++/** ++* ++* DMA driver channel definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_CHANNEL_INVALID = 0xFF, ++ DMA_CHANNEL_0 = 0, ++ DMA_CHANNEL_1 = 1, ++ DMA_CHANNEL_2 = 2, ++ DMA_CHANNEL_3 = 3, ++#if !defined(_SAMOA_) ++ DMA_CHANNEL_4 = 4, ++ DMA_CHANNEL_5 = 5, ++ DMA_CHANNEL_6 = 6, ++ DMA_CHANNEL_7 = 7, ++#if defined(_ATHENA_) ++ DMA_CHANNEL_8 = 8, //used for DMA_CLIENT_AUDIO_OUT_FIFO ++ DMA_CHANNEL_9 = 9, //used for DMA_CLIENT_POLYRING_OUT_FIFO ++ DMA_CHANNEL_10 = 10, //used for DMA_CLIENT_AUDIO_WB_MIXERTAP ++ DMA_CHANNEL_11 = 11, //used for DMA_CLIENT_AUDIO_IN_FIFO ++#endif ++#endif ++ TOTAL_DMA_CHANNELS ++} DMA_CHANNEL; ++ ++/** ++* ++* DMA driver callback function definition ++* ++*****************************************************************************/ ++#define DMADRV_CALLBACK_t DmaDrv_Callback ++typedef void (*DMADRV_CALLBACK_t)(DMADRV_CALLBACK_STATUS_t Err); ++ ++/** ++* ++* DMA driver channel info structure definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ DMA_CLIENT srcID; ++ DMA_CLIENT dstID; ++ DMA_CHAN_TYPE type; ++ DMA_ALIGN alignment; ++ DMA_BSIZE srcBstSize; ++ DMA_BSIZE dstBstSize; ++ DMA_DWIDTH srcDataWidth; ++ DMA_DWIDTH dstDataWidth; ++ UInt32 priority; ++ UInt32 chanNumber; ++ UInt32 dmaCfgReg; ++ UInt32 incMode; ++ DmaDrv_Callback xferCompleteCb; ++ UInt32 prot; ++ UInt32 dstMaster; ++ UInt32 srcMaster; ++ UInt32 dstIncrement; ++ UInt32 srcIncrement; ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++ DMADRV_BLENGTH srcBstLength; ++ DMADRV_BLENGTH dstBstLength; ++#endif ++ Boolean freeChan; ++ Boolean bCircular; ++} Dma_Chan_Info, *pChanInfo; ++ ++/** ++* ++* DMA driver LLI structure definition ++* ++*****************************************************************************/ ++typedef void *DMADRV_LLI_T; ++ ++/** ++* ++* This function initialize dma driver ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Init(void); ++ ++/** ++* ++* This function deinitialize dma driver ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_DeInit(void); ++ ++/** ++* ++* This function allocates dma channel ++* ++* @param srcID (in) source identification ++* @param dstID (in) destination identification ++* @param chanID (in) buffer to store channel number ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Obtain_Channel( ++ DMA_CLIENT srcID, ++ DMA_CLIENT dstID, ++ DMA_CHANNEL *chanID ++); ++ ++/** ++* ++* This function release dma channel ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Release_Channel(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function configure dma channel ++* ++* @param chanID (in) channel number ++* @param pChanInfo (in) pointer to dma channe info structure ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Config_Channel( ++ DMA_CHANNEL chanID, ++ Dma_Chan_Info *pChanInfo ++); ++ ++/** ++* ++* This function bind data buffer for the DMA channel ++* ++* @param chanID (in) channel to bind data ++* @param pData (in) pointer to dma channel data buffer ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Bind_Data(DMA_CHANNEL chanID, Dma_Data *pData); ++ ++/** ++* ++* This function start dma channel transfer ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Start_Transfer(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function bind data buffer for the DMA channel ++* ++* @param chanID (in) channel to bind data ++* @param pData (in) pointer to dma channel data buffer ++* @param pLLI (in) buffer to store returned LLI table ++* identification info ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Bind_Data_Ex( ++ DMA_CHANNEL chanID, ++ Dma_Data *pData, ++ DMADRV_LLI_T *pLLI ++); ++ ++/** ++* ++* This function start dma channel transfer ++* ++* @param chanID (in) channel identification ++* @param pLLI (in) one of the LLI tables needs to be used for DMA ++* transfer ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Start_Transfer_Ex( ++ DMA_CHANNEL chanID, ++ DMADRV_LLI_T pLLI ++); ++ ++/** ++* ++* This function stop dma channel trnasfer ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Stop_Transfer(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function stop dma channel trnasfer and lose all data in FIFO ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Force_Shutdown_Channel(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function register hisr for client usage ++* ++* @param client (in) client identification ++* @param hisr (in) registered hisr ++* ++* @return void ++* ++*****************************************************************************/ ++void DMADRV_Register_HISR(DMA_CLIENT client, void *hisr); ++ ++/** ++* ++* This function unregister hisr from client usage ++* ++* @param client (in) client identification ++* ++* @return void ++* ++*****************************************************************************/ ++void DMADRV_UnRegister_HISR(DMA_CLIENT client); ++ ++/** ++* ++* This function get hisr for client usage ++* ++* @param client (in) client identification ++* ++* @return hisr (out) return registered client's hisr ++* ++*****************************************************************************/ ++void *DMADRV_Get_HISR(DMA_CLIENT client); ++ ++/** ++* ++* This function get DMA driver version number ++* ++* @return driver version number ++* ++*****************************************************************************/ ++UInt32 DMADRV_Get_Version(void); ++ ++/** @} */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DMA_DRV_H_ */ +diff --git a/arch/arm/plat-iproc/include/plat/dmux.h b/arch/arm/plat-iproc/include/plat/dmux.h +new file mode 100644 +index 0000000..575f783 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/dmux.h +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __MACH_DMUX_H ++#define __MACH_DMUX_H ++ ++enum dmac_mux { ++ KONA_DMUX_UARTB_A = 8, ++ KONA_DMUX_UARTB_B = 9, ++ KONA_DMUX_UARTB2_A = 10, ++ KONA_DMUX_UARTB2_B = 11, ++ KONA_DMUX_UARTB3_A = 12, ++ KONA_DMUX_UARTB3_B = 13, ++ KONA_DMUX_SSP_0A_RX0 = 16, ++ KONA_DMUX_SSP_0B_TX0 = 17, ++ KONA_DMUX_SSP_0C_RX1 = 18, ++ KONA_DMUX_SSP_0D_TX1 = 19, ++ KONA_DMUX_SSP_1A_RX0 = 20, ++ KONA_DMUX_SSP_1B_TX0 = 21, ++ KONA_DMUX_SSP_1C_RX1 = 22, ++ KONA_DMUX_SSP_1D_TX1 = 23, ++ KONA_DMUX_HSIA = 32, ++ KONA_DMUX_HSIB = 33, ++ KONA_DMUX_HSIC = 34, ++ KONA_DMUX_HSID = 35, ++ KONA_DMUX_EANC = 40, ++ KONA_DMUX_STEREO = 41, ++ KONA_DMUX_NVIN = 42, ++ KONA_DMUX_VIN = 43, ++ KONA_DMUX_VIBRA = 44, ++ KONA_DMUX_IHF_0 = 45, ++ KONA_DMUX_VOUT = 46, ++ KONA_DMUX_SLIMA = 47, ++ KONA_DMUX_SLIMB = 48, ++ KONA_DMUX_SLIMC = 49, ++ KONA_DMUX_SLIMD = 50, ++ KONA_DMUX_SIM_A = 51, ++ KONA_DMUX_SIM_B = 52, ++ KONA_DMUX_SIM2_A = 53, ++ KONA_DMUX_SIM2_B = 54, ++ KONA_DMUX_IHF_1 = 55, ++ KONA_DMUX_SSP_2A_RX0 = 56, ++ KONA_DMUX_SSP_2B_TX0 = 57, ++ KONA_DMUX_SSP_2C_RX1 = 58, ++ KONA_DMUX_SSP_2D_TX1 = 59, ++ KONA_DMUX_SPUM_SecureA = 65, ++ KONA_DMUX_SPUM_SecureB = 66, ++ KONA_DMUX_SPUM_OpenA = 67, ++ KONA_DMUX_SPUM_OpenB = 68, ++ KONA_DMUX_INVALID = 0x7f, ++}; ++ ++enum dma_peri dmux_name_to_id(const char *name); ++int dmux_id_to_name(enum dma_peri peri, char *pname); ++int dmux_sema_protect(void); ++int dmux_sema_unprotect(void); ++int dmux_alloc_channel(u32 * pchan); ++int dmux_release_channel(u32 channel); ++int dmux_alloc_peripheral(u32 channel, enum dma_peri peri, u8 * peri_req_id); ++int dmux_alloc_multi_peripheral(u32 channel, enum dma_peri a, enum dma_peri b, ++ u8 * src_id, u8 * dst_id); ++int dmux_dealloc_peripheral(u32 channel); ++ ++#endif /* __MACH_DMUX_H */ +diff --git a/arch/arm/plat-iproc/include/plat/osdal_os.h b/arch/arm/plat-iproc/include/plat/osdal_os.h +new file mode 100644 +index 0000000..76e61a6 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/osdal_os.h +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef _OSDAL_OS_H_ ++#define _OSDAL_OS_H_ ++ ++#include ++#include "asm/posix_types.h" ++#include "asm/string.h" ++/* Heap memory */ ++#define OSDAL_ALLOCHEAPMEM(s) kzalloc((s), GFP_KERNEL) ++ ++#define OSDAL_FREEHEAPMEM(a) kfree((a)) ++ ++ ++/* IRQ */ ++#define OSDAL_IRQ_Enable(irq) enable_irq((irq)) ++#define OSDAL_IRQ_Disable(irq) disable_irq((irq)) ++#define OSDAL_IRQ_Clear(irq) ++#define OSDAL_IRQ_IsEnabled(irq) ++ ++ ++/* Synchronization */ ++#define OSDAL_SENDEVENT(e) complete((struct completion *)&(e)) ++ ++#define OSDAL_WAITEVENT(e) \ ++wait_for_completion((struct completion *)&(e)) ++ ++#define OSDAL_WAITEVENT_TIMEOUT(e, t) \ ++wait_for_completion_timeout((struct completion *)&(e), (t)) ++ ++#define OSDAL_CLEAREVENT(e) ++ ++ ++/* Time stamp in ms */ ++#define OSDAL_TIMEVAL() ++ ++ ++/* Delays */ ++#define OSDAL_MDELAY(x) mdelay(x) ++ ++#define OSDAL_UDELAY(x) udelay(x) ++ ++/* Debug Print */ ++//#define dprintf(prio, format, args...) pr_info("%s:%s"" format", __FILE__, __FUNCTION__) ++#define dprintf(prio, fmt, ...) printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) ++ ++#endif /*_OSDAL_OS_H_*/ +diff --git a/arch/arm/plat-iproc/include/plat/shm.h b/arch/arm/plat-iproc/include/plat/shm.h +new file mode 100644 +index 0000000..59fcb83 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/shm.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* ++ * Header for declaring shim layer exports. ++ */ ++ ++#ifndef __SHM_DOT_H_INCLUDED__ ++#define __SHM_DOT_H_INCLUDED__ ++ ++#include ++#include ++ ++extern int iproc_platform_get_irq(struct platform_device *dev, unsigned int num); ++extern struct resource * ++iproc_platform_get_resource_byname(struct platform_device *dev, unsigned int type, const char *name); ++extern struct resource * ++iproc_platform_get_resource(struct platform_device *dev, unsigned int type, ++ unsigned int num); ++extern int iproc_platform_device_register(struct platform_device * pdev); ++extern void iproc_platform_device_unregister(struct platform_device * pdev); ++extern int iproc_platform_driver_register(struct platform_driver *drv); ++extern void iproc_platform_driver_unregister(struct platform_driver *drv); ++ ++extern struct platform_device *iproc_platform_device_alloc(const char *name, int id); ++extern int iproc_platform_device_add(struct platform_device *pdev); ++extern void iproc_platform_device_put(struct platform_device *pdev); ++ ++extern int iproc_sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp); ++extern void iproc_sysfs_remove_group(struct kobject *kobj, const struct attribute_group *grp); ++ ++#endif /*#ifndef __SHM_DOT_H_INCLUDED__*/ +diff --git a/arch/arm/plat-iproc/include/plat/spi_iproc.h b/arch/arm/plat-iproc/include/plat/spi_iproc.h +new file mode 100644 +index 0000000..3258d69 +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/spi_iproc.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* ++ * Broadcom IPROC SSPI based SPI master controller ++ */ ++#ifndef __ARCH_PLAT_SPI_IPROC_H__ ++#define __ARCH_PLAT_SPI_IPROC_H__ ++ ++struct spi_iproc_platform_data { ++ u8 enable_dma; ++ u8 cs_line; ++ u8 mode; ++}; ++#endif /* __ARCH_PLAT_SPI_IPROC_H__ */ +diff --git a/arch/arm/plat-iproc/include/plat/swreset_rec.h b/arch/arm/plat-iproc/include/plat/swreset_rec.h +new file mode 100644 +index 0000000..924fa5a +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/swreset_rec.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef _SWRESET_REC_H_ ++#define _SWRESET_REC_H_ ++ ++/* Handle to access Software Record Record */ ++typedef void *SWRR_HANDLE; ++ ++/* Get number of software reset records for the SoC; 0 if not suppprted */ ++extern unsigned int swreset_record_get_record_count(void); ++ ++/* Get number of bits per software reset record for the SoC */ ++extern unsigned int swreset_record_get_record_width(void); ++ ++/* Register to use one software reset record; return NULL if used out */ ++extern SWRR_HANDLE swreset_record_register(const char *name); ++ ++/* Unregister to return the record */ ++extern void swreset_record_unregister(SWRR_HANDLE handle); ++ ++/* Set value of the software reset record */ ++extern int swreset_record_set(SWRR_HANDLE handle, int value); ++ ++/* Get value of the software reset record */ ++extern int swreset_record_get(SWRR_HANDLE handle, int *value); ++ ++#endif /* _SWRESET_REC_H_ */ +diff --git a/arch/arm/plat-iproc/include/plat/timer-sp.h b/arch/arm/plat-iproc/include/plat/timer-sp.h +new file mode 100644 +index 0000000..b73ef9a +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/timer-sp.h +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++void iproc_clocksource_init(void __iomem *); ++void iproc_clockevents_init(void __iomem *, unsigned int); +diff --git a/arch/arm/plat-iproc/include/plat/types.h b/arch/arm/plat-iproc/include/plat/types.h +new file mode 100644 +index 0000000..d03df1e +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/types.h +@@ -0,0 +1,20 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef _TYPES_H_ ++#define _TYPES_H_ ++ ++#include ++#endif +diff --git a/arch/arm/plat-iproc/iproc-cache.S b/arch/arm/plat-iproc/iproc-cache.S +new file mode 100644 +index 0000000..2a5e37d +--- /dev/null ++++ b/arch/arm/plat-iproc/iproc-cache.S +@@ -0,0 +1,120 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++ ++ __INIT ++ ++/* ++ * The secondary kernel init calls v7_flush_dcache_all before it enables ++ * the L1; however, the L1 comes out of reset in an undefined state, so ++ * the clean + invalidate performed by v7_flush_dcache_all causes a bunch ++ * of cache lines with uninitialized data and uninitialized tags to get ++ * written out to memory, which does really unpleasant things to the main ++ * processor. We fix this by performing an invalidate, rather than a ++ * clean + invalidate, before jumping into the kernel. ++ */ ++ ++ENTRY(v7_invalidate_l1) ++ mov r0, #0 ++ mcr p15, 2, r0, c0, c0, 0 ++ mrc p15, 1, r0, c0, c0, 0 ++ ++ ldr r1, =0x7fff ++ and r2, r1, r0, lsr #13 ++ ++ ldr r1, =0x3ff ++ ++ and r3, r1, r0, lsr #3 @ NumWays - 1 ++ add r2, r2, #1 @ NumSets ++ ++ and r0, r0, #0x7 ++ add r0, r0, #4 @ SetShift ++ ++ clz r1, r3 @ WayShift ++ add r4, r3, #1 @ NumWays ++1: sub r2, r2, #1 @ NumSets-- ++ mov r3, r4 @ Temp = NumWays ++2: subs r3, r3, #1 @ Temp-- ++ mov r5, r3, lsl r1 ++ mov r6, r2, lsl r0 ++ orr r5, r5, r6 @ Reg = (Temp< ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static struct resource ccu_regs = { ++ .name = "cru_regs", ++ .start = IPROC_ROOT_CLK_VA, ++ .end = ((IPROC_ROOT_CLK_VA) + 0x0fff), ++ .flags = IORESOURCE_MEM, ++}; ++ ++/* ++ * Clock management scheme is a provisional implementation ++ * only intended to retreive the pre-set frequencies for each ++ * of the clocks. ++ */ ++ ++/* ++ * Get PLL running status and update output frequency ++ * for ARMPLL channel 0 ++ */ ++static int a9pll0_status (struct clk * clk) ++{ ++ u32 regA; ++ u32 regB; ++ u32 regC; ++ u32 pdiv; ++ u32 ndiv_int; ++ u32 ndiv_frac; ++ u32 mdiv; ++ u64 x; ++ ++ printk(KERN_DEBUG "a9pll0_status: clk 0x%x\n", (unsigned int)clk); ++ if (clk->type != CLK_PLL) ++ return -EINVAL; ++ ++ BUG_ON (!clk->regs_base); ++ BUG_ON (!clk->parent); ++ ++ /* read status register */ ++ regA = readl(clk->regs_base + 0x0c00);/* IHOST_PROC_CLK_PLLARMA */ ++ regB = readl(clk->regs_base + 0x0c04);/* IHOST_PROC_CLK_PLLARMB */ ++ regC = readl(clk->regs_base + 0x0c08);/* IHOST_PROC_CLK_PLLARMB */ ++ ++ /* reg C bit 8 is bypass mode - input frequency to output */ ++ if ((regC & (1 << 8)) == 1) { ++ clk->rate = clk->parent->rate; ++ return 0; ++ } ++ ++ /* reg A bit 28 is "lock" signal, has to be "1" for proper operation */ ++ if ((regA & (1 << 28)) == 0 ) { ++#if defined(CONFIG_MACH_IPROC_P7) && defined(CONFIG_MACH_IPROC_EMULATION) ++ printk(KERN_WARNING "a9pll0_status: ARM PLL not locked\n"); ++#else ++ clk->rate = 0; ++ return -EIO; ++#endif ++ } ++ ++ /* Update PLL frequency */ ++ ++ ++ /* pdiv in bits 24..27 (4 bits) */ ++ // pdiv = (regA >> 24 ) & 0xf; pavan 05092012 ++ pdiv = (regA >> 24 ) & 0x7; ++ if (pdiv == 0) ++ pdiv = 0x10; ++ ++ /* feedback divider (int) in bits 8..17 (10 bits) */ ++ ndiv_int = (regA >> 8) & ((1<<10) - 1); ++ if (ndiv_int == 0) ++ ndiv_int = 1 << 10; ++ ++ /* feedback divider fraction in reg B, bits 0..19 */ ++ ndiv_frac = regB & ((1<<20) - 1); ++ ++ x = ((u64) ndiv_int << 20) | ndiv_frac; ++ printk(KERN_DEBUG "parent rate %lu\n", clk->parent->rate); ++ x = (x * clk->parent->rate) >> 20; ++ (void) do_div(x, pdiv); ++ ++ /* post-divider is in reg C bits 0..7 */ ++ mdiv = regC & 0xff ; ++ if (mdiv == 0) ++ mdiv = 0x100; ++ ++ /* ++ * Here we need to divide the resulting clock by mdiv which we ++ * are not doing now? ++ */ ++ clk->rate = (u32)(x); ++ ++ return 0; ++} ++ ++ ++/* ++ * Get PLL running status and update output frequency ++ * for ARMPLL channel 1 ++ */ ++static int a9pll1_status(struct clk * clk) ++{ ++ u32 regA; ++ u32 regB; ++ u32 regC; ++ u32 regD; ++ unsigned pdiv; ++ unsigned ndiv_int; ++ unsigned ndiv_frac; ++ unsigned mdiv; ++ u64 x; ++ ++ if (clk->type != CLK_PLL) ++ return -EINVAL; ++ ++ BUG_ON(!clk->regs_base); ++ BUG_ON(!clk->parent); ++ ++ /* read status register */ ++ regA = readl(clk->regs_base+0xc00);/* IHOST_PROC_CLK_PLLARMB */ ++ regB = readl(clk->regs_base+0xc04);/* IHOST_PROC_CLK_PLLARMB */ ++ regC = readl(clk->regs_base+0xc20);/* IHOST_PROC_CLK_PLLARMCTRL5 */ ++ regD = readl(clk->regs_base+0xc24);/* IHOST_PROC_CLK_PLLARM_OFFSET*/ ++ ++ /* reg C bit 8 is bypass mode - input frequency to output */ ++ if ((regC & (1 << 8)) == 1) { ++ clk->rate = clk->parent->rate; ++ return 0; ++ } ++ ++ /* reg A bit 28 is "lock" signal, has to be "1" for proper operation */ ++ if ((regA & (1 << 28)) == 0) { ++#if defined(CONFIG_MACH_IPROC_P7) && defined(CONFIG_MACH_IPROC_EMULATION) ++ printk(KERN_WARNING "a9pll1_status: ARM PLL not locked\n"); ++#else ++ clk->rate = 0; ++ return -EIO; ++#endif ++ } ++ ++ /* Update PLL frequency */ ++ ++ ++ /* pdiv in bits 24..27 (4 bits) */ ++ pdiv = (regA >> 24 ) & 0xf; ++ if (pdiv == 0) ++ pdiv = 0x10; ++ ++ /* Check if offset mode is active */ ++ if (regD & (1 << 29)) { ++ /* pllarm_ndiv_int_offset bits 27:20 */ ++ ndiv_int = (regD >> 20 ) & 0xff; ++ if (ndiv_int == 0) ++ ndiv_int = 1 << 8; ++ ++ /* pllarm_ndiv_frac_offset bits 19:0 */ ++ ndiv_frac = regD & ((1 << 20) - 1); ++ } else { ++ /* If offset not active, channel 0 parameters are used */ ++ /* feedback divider (int) in bits 8..17 (10 bits) */ ++ ndiv_int = (regA >> 8) & ((1 << 10) - 1); ++ if (ndiv_int == 0) ++ ndiv_int = 1 << 10; ++ ++ /* feedback divider fraction in reg B, bits 0..19 */ ++ ndiv_frac = regB & ((1 << 20) - 1); ++ } ++ ++ x = ((u64) ndiv_int << 20) | ndiv_frac; ++ x = (x * clk->parent->rate) >> 20; ++ (void) do_div(x, pdiv); ++ ++ /* post-divider is in reg C bits 0..7 */ ++ mdiv = regC & 0xff ; ++ if (mdiv == 0) ++ mdiv = 0x100; ++ ++ (void) do_div(x, mdiv); ++ clk->rate = (u32)(x); ++ ++ return 0; ++} ++ ++ ++static const struct clk_ops a9pll0_ops = { ++ .status = a9pll0_status, ++}; ++ ++static const struct clk_ops a9pll1_ops = { ++ .status = a9pll1_status, ++}; ++ ++ ++/* ++ * iProc A9 PLL ++ * could be used as source for generated clocks ++ */ ++static struct clk clk_a9pll[2] = { ++ { ++ .ops = &a9pll0_ops, ++ .name = "A9_PLL", ++ .type = CLK_PLL, ++ .chan = 0xa, ++ }, ++ { ++ .ops = &a9pll1_ops, ++ .name = "A9_PLL", ++ .type = CLK_PLL, ++ .chan = 0xb, ++ }, ++}; ++ ++/* ++ * Decode the Frequency ID setting for arm_clk ++ */ ++static int iproc_cru_arm_freq_id(void * __iomem regs_base) ++{ ++ u32 reg_f, reg; ++ unsigned policy; ++ unsigned fid; ++ unsigned i; ++ u8 arm_clk_policy_mask = 0; ++ u8 apb0_clk_policy_mask = 0; ++ ++ /* ++ * bits 0..2 freq# for policy0, 8..10 for policy1, ++ * 16..18 policy2, 24..26 policy 3 ++ */ ++ reg_f = readl(regs_base + 0x008);/*IHOST_PROC_CLK_POLICY_FREQ*/ ++ ++ for(i = 0; i < 4; i++) { ++ /* ++ * Reg IHOST_PROC_CLK_POLICY_MASK ++ * bit 20 arm policy mask, bit 21 apb0 policy mask ++ */ ++ reg = readl(regs_base + 0x010 + i*4); ++ arm_clk_policy_mask |= (1 & ( reg >> 20)) << i; ++ apb0_clk_policy_mask |= (1 & ( reg >> 21)) << i; ++ } ++ ++ /* How to obtain hardware policy setting ? */ ++ policy = 0; ++ ++ /* Check for PLL policy software override */ ++ reg = readl(regs_base + 0xe00);/* IHOST_PROC_CLK_ARM_DIV */ ++ if (reg & (1 << 4 )) ++ policy = reg & 0xf; ++ ++ fid = (reg_f >> (8 * policy)) & 0xf; ++ ++ /* Verify freq_id from debug register */ ++ reg = readl( regs_base+0xec0 );/* IHOST_PROC_CLK_POLICY_DBG */ ++ /* Bits 12..14 contain active frequency_id */ ++ i = 0x7 & (reg >> 12); ++ ++ if (fid != i) { ++ printk(KERN_WARNING ++ "IPROC CRU clock frequency id override %d->%d\n", ++ fid, i); ++ fid = i; ++ } ++ ++ printk(KERN_DEBUG "Active frequency ID %d\n", fid); ++ ++ return fid; ++} ++ ++/* ++ * Get status of any of the ARMPLL output channels ++ */ ++static int a9pll_chan_status(struct clk * clk) ++{ ++ u32 reg; ++ unsigned div; ++ unsigned freq_id; ++ ++ if(clk->type != CLK_DIV) ++ return -EINVAL; ++ ++ BUG_ON(!clk->regs_base); ++ ++ reg = readl(clk->regs_base + 0xe00); /* IHOST_PROC_CLK_ARM_DIV */ ++ ++ /* arm_pll_select 3:0 */ ++ printk(KERN_DEBUG "Clock Div = %#x\n", reg); ++ ++ freq_id = iproc_cru_arm_freq_id(clk->regs_base); ++ ++ /* clk->parent = & clk_a9pll[0]; */ ++ ++ switch (clk->chan) { ++ case 0x0a: ++ /* apb0_free_div bits 10:8 */ ++ div = (reg >> 8) & 0x7; ++ if (div == 0) ++ div = 8; ++ break; ++ ++ case 0x0b: ++ /* arm_switch_div bits 6:5 */ ++ div = (reg >> 5) & 0x3; ++ if (div == 0) ++ div = 4; ++ break; ++ ++ case 0x1a: ++ /* IHOST_PROC_CLK_APB_DIV apb_clk_div bits 1:0 */ ++ reg = readl(clk->regs_base + 0xa10); ++ div = reg & 0x3; ++ if(div == 0) ++ div = 4; ++ break; ++ ++ case 0x3a: /* arm_clk */ ++ if( freq_id == 7 ) { ++ //clk->parent = &clk_a9pll[1]; /* arm_clk_h */ ++ clk->parent = &clk_a9pll[0]; /* arm_clk_h */ ++ div = 2; ++ } else if( freq_id == 6 ) { ++ clk->parent = &clk_a9pll[0]; /* arm_clk */ ++ div = 4; ++ } else if( freq_id == 2 ) { ++ clk->parent = &clk_a9pll[0]; /* arm_clk */ ++ div = 4; ++ } else if (freq_id == 0) { ++ clk->parent = &clk_a9pll[0]; ++ div = 1; ++ } else if (freq_id == 1) { ++ struct clk * clk_lcpll_200; ++ clk_lcpll_200 = ++ clk_get_sys( NULL, "sdio_clk"); ++ BUG_ON( ! clk_lcpll_200 ); ++ clk->parent = clk_lcpll_200; ++ div = 1; ++ } else { ++ clk->parent = &clk_a9pll[0]; ++ div = 2; ++ } ++ /* Parent may have changed, refresh it */ ++ if(clk->parent->ops && clk->parent->ops->status) ++ clk->parent->ops->status( clk->parent); ++ break; ++ ++ case 0x0f: /* periph_clk */ ++ div = 2; ++ break; ++ ++ default: ++ return -EINVAL; ++ ++ } ++ ++ BUG_ON(!clk->parent); ++ printk(KERN_DEBUG "Clock divisor %d\n", div); ++ // clk->rate = clk->parent->rate / div ; ++ clk->rate = clk->parent->rate / div ; ++ printk(KERN_DEBUG "Clock rate %lu\n", clk->rate); ++ ++ return 0; ++} ++ ++ ++static const struct clk_ops a9pll_chan_ops = { ++ .status = a9pll_chan_status, ++}; ++ ++/* ++ * iProc A9 PLL output clocks ++ */ ++#ifdef CONFIG_MACH_CYGNUS_EMULATION //chandra:emul ++ static struct clk clk_a9chan[] = { ++ { ++ .ops = NULL, ++ .type = CLK_DIV, ++ .parent = NULL, ++ .rate = CONFIG_CYGNUS_EMULATION_ARM_CLK, ++ .name = "arm_clk", ++ .chan = 0x3a ++ }, ++ { ++ .ops = NULL, ++ .type = CLK_DIV, ++ .parent = NULL, ++ .rate = CONFIG_CYGNUS_EMULATION_PCLK, ++ .name = "periph_clk", ++ .chan = 0x0f ++ }, ++ { ++ .ops = NULL, ++ .type = CLK_DIV, ++ .parent = NULL, ++ .rate = CONFIG_CYGNUS_EMULATION_PCLK, ++ .name = "apb0_free", ++ .chan = 0x0a ++ }, ++ { ++ .ops = NULL, ++ .type = CLK_DIV, ++ .parent = NULL, ++ .rate = CONFIG_CYGNUS_EMULATION_ARM_CLK, ++ .name = "arm_switch", ++ .chan = 0x0b ++ }, ++ { ++ .ops = NULL, ++ .type = CLK_DIV, ++ .parent = NULL, ++ .rate = CONFIG_CYGNUS_EMULATION_PCLK, ++ .name = "apb_clk", ++ .chan = 0x1a ++ }, ++ }; ++#else ++static struct clk clk_a9chan[] = { ++ { ++ .ops = &a9pll_chan_ops, ++ .type = CLK_DIV, ++ .parent = &clk_a9chan[0], ++ .name = "arm_clk", ++ .chan = 0x3a ++ }, ++ { ++ .ops = &a9pll_chan_ops, ++ .type = CLK_DIV, ++ .parent = &clk_a9chan[0], ++ .name = "periph_clk", ++ .chan = 0x0f ++ }, ++ { ++ .ops = &a9pll_chan_ops, ++ .type = CLK_DIV, ++ .parent = &clk_a9chan[0], ++ .name = "apb0_free", ++ .chan = 0x0a ++ }, ++ { ++ .ops = &a9pll_chan_ops, ++ .type = CLK_DIV, ++ .parent = &clk_a9chan[0], ++ .name = "arm_switch", ++ .chan = 0x0b ++ }, ++ { ++ .ops = &a9pll_chan_ops, ++ .type = CLK_DIV, ++ .parent = &clk_a9chan[0], ++ .name = "apb_clk", ++ .chan = 0x1a ++ }, ++}; ++#endif /* End of CONFIG_MACH_CYGNUS */ ++ ++static struct clk_lookup cru_clk_lookups[] = { ++ { ++ .con_id= "a9pll0", ++ .clk= &clk_a9pll[0], ++ }, ++ { ++ .con_id= "a9pll1", ++ .clk= &clk_a9pll[1], ++ }, ++ { ++ .con_id= "arm_clk", ++ .clk= &clk_a9chan[0], ++ }, ++ { ++ .con_id= "periph_clk", ++ .clk= &clk_a9chan[1], ++ }, ++ { ++ .con_id= "apb0_free", ++ .clk= &clk_a9chan[2], ++ }, ++ { ++ .con_id= "axi_clk", ++ .clk= &clk_a9chan[3], ++ }, ++ { ++ .con_id= "apb_clk", ++ .clk= &clk_a9chan[4], ++ }, ++}; ++ ++void __init iproc_cru_init(struct clk * src_clk) ++{ ++ void * __iomem reg_base; ++ unsigned i; ++ ++ BUG_ON(request_resource( &iomem_resource, &ccu_regs)); ++ ++ reg_base = IOMEM(ccu_regs.start); ++ ++ BUG_ON(IS_ERR_OR_NULL(reg_base)); ++ ++ /* Initialize clocks */ ++ ++ for (i = 0; i < ARRAY_SIZE(clk_a9pll); i++) { ++ clk_a9pll[i].regs_base = reg_base ; ++ clk_a9pll[i].parent = src_clk ; ++ } ++ ++ clk_a9chan[0].parent = src_clk ; /* tentative */ ++ for (i = 0; i < ARRAY_SIZE(clk_a9chan); i++) { ++ clk_a9chan[i].regs_base = reg_base ; ++ } ++ ++ /* Install clock sources into the lookup table */ ++ clkdev_add_table(cru_clk_lookups, ++ ARRAY_SIZE(cru_clk_lookups)); ++} ++ ++void cru_clocks_show(void) ++{ ++ unsigned i; ++ ++ printk( "CRU Clocks:\n" ); ++ for (i = 0; i < ARRAY_SIZE( cru_clk_lookups); i++) { ++ printk( "%s: (%s) %lu\n", ++ cru_clk_lookups[i].con_id, ++ cru_clk_lookups[i].clk->name, ++ clk_get_rate( cru_clk_lookups[i].clk)); ++ } ++ printk( "CRU Clocks# %u\n", i ); ++ ++} +diff --git a/arch/arm/plat-iproc/irq.c b/arch/arm/plat-iproc/irq.c +new file mode 100644 +index 0000000..6d6bda2 +--- /dev/null ++++ b/arch/arm/plat-iproc/irq.c +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++ ++void __init iproc_init_irq(void) ++{ ++ unsigned int cr; ++ ++ cr = get_cr(); ++ cr |= CR_VE; ++ set_cr(cr); ++ ++ /* start with GLBTIMER */ ++ ++ gic_init(0, BCM_INT_ID_PPI0, ++ IOMEM(IPROC_PERIPH_INT_DISTR_REG_VA), ++ IOMEM(IPROC_GICCPU_VA)); ++} +diff --git a/arch/arm/plat-iproc/lm.c b/arch/arm/plat-iproc/lm.c +new file mode 100644 +index 0000000..a6ac191 +--- /dev/null ++++ b/arch/arm/plat-iproc/lm.c +@@ -0,0 +1,138 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define to_lm_device(d) container_of(d, struct lm_device, dev) ++#define to_lm_driver(d) container_of(d, struct lm_driver, drv) ++ ++static int ++lm_match(struct device *dev, struct device_driver *drv) ++{ ++ printk(KERN_INFO "lm_match()\n"); ++ return 1; ++} ++ ++static int ++lm_bus_probe(struct device *dev) ++{ ++ struct lm_device *lmdev = to_lm_device(dev); ++ struct lm_driver *lmdrv = to_lm_driver(dev->driver); ++ ++ printk(KERN_INFO "lm_bus_probe()\n"); ++ return lmdrv->probe(lmdev); ++} ++ ++static int ++lm_bus_remove(struct device *dev) ++{ ++ struct lm_device *lmdev = to_lm_device(dev); ++ struct lm_driver *lmdrv = to_lm_driver(dev->driver); ++ ++ printk(KERN_INFO "lm_bus_remove()\n"); ++ if (lmdrv->remove) ++ lmdrv->remove(lmdev); ++ return 0; ++} ++ ++static struct bus_type lm_bustype = ++{ ++ .name = "logicmodule", ++ .match = lm_match, ++ .probe = lm_bus_probe, ++ .remove = lm_bus_remove, ++ /* .suspend = lm_bus_suspend, */ ++ /* .resume = lm_bus_resume, */ ++}; ++ ++static int __init ++lm_init(void) ++{ ++ printk(KERN_INFO "lm_init()\n"); ++ return bus_register(&lm_bustype); ++} ++ ++postcore_initcall(lm_init); ++ ++int ++lm_driver_register(struct lm_driver *drv) ++{ ++ printk(KERN_INFO "lm_driver_register(): name=%s\n", drv->drv.name); ++ drv->drv.bus = &lm_bustype; ++ return driver_register(&drv->drv); ++} ++ ++void ++lm_driver_unregister(struct lm_driver *drv) ++{ ++ printk(KERN_INFO "lm_driver_unregister()\n"); ++ driver_unregister(&drv->drv); ++} ++ ++static void ++lm_device_release(struct device *dev) ++{ ++ struct lm_device *lmdev = to_lm_device(dev); ++ ++ printk(KERN_INFO "lm_device_release()\n"); ++ release_resource(&lmdev->resource); ++ kfree(lmdev); ++} ++ ++int ++lm_device_register(struct lm_device *lmdev) ++{ ++ int ret; ++ ++ printk(KERN_INFO "lm_device_register(): id=%d irq=%d start=0x%08x end=0x%08x\n", lmdev->id, lmdev->irq, lmdev->resource.start, lmdev->resource.end); ++ ++ lmdev->dev.release = lm_device_release; ++ lmdev->dev.bus = &lm_bustype; ++ dev_set_name (&lmdev->dev, "lm%d", lmdev->id); ++ lmdev->resource.name = dev_name (&lmdev->dev); ++ ++ ret = request_resource(&iomem_resource, &lmdev->resource); ++ if (ret == 0) { ++ ret = device_register(&lmdev->dev); ++ if (ret) ++ { ++ printk(KERN_ERR "lm_device_register(): device_register() failed, rc=%d\n", ret ); ++ release_resource(&lmdev->resource); ++ } ++ } ++ else ++ printk(KERN_ERR "lm_device_register(): request_resource() failed, rc=%d\n", ret ); ++ ++ return ret; ++} ++ ++void ++lm_device_unregister(struct lm_device *lmdev) ++{ ++ printk(KERN_INFO "lm_device_unregister()\n"); ++ device_unregister(&lmdev->dev); ++} ++ ++ ++EXPORT_SYMBOL(lm_device_register); ++EXPORT_SYMBOL(lm_device_unregister); ++ ++EXPORT_SYMBOL(lm_driver_register); ++EXPORT_SYMBOL(lm_driver_unregister); +diff --git a/arch/arm/plat-iproc/localtimer.c b/arch/arm/plat-iproc/localtimer.c +new file mode 100644 +index 0000000..ca13311 +--- /dev/null ++++ b/arch/arm/plat-iproc/localtimer.c +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define IRQ_LOCALTIMER BCM_INT_ID_PPI13 ++/* ++ * Setup the local clock events for a CPU. ++ */ ++ ++void iproc_local_timer_init(void) ++{ ++ twd_base = IO_ADDRESS(IPROC_PERIPH_PVT_TIM_REG_VA); ++} +diff --git a/arch/arm/plat-iproc/platsmp.c b/arch/arm/plat-iproc/platsmp.c +new file mode 100644 +index 0000000..e902c8d +--- /dev/null ++++ b/arch/arm/plat-iproc/platsmp.c +@@ -0,0 +1,265 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* Lookup table phys addr and offset */ ++#define SOC_ROM_BASE_PA 0xFFFF0000 ++#ifdef CONFIG_MACH_NS ++#define SOC_ROM_LUT_OFF 0x400 ++#elif defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define SOC_ROM_LUT_OFF 0x42c ++#elif defined(CONFIG_MACH_HR2) ++#define SOC_ROM_LUT_OFF 0x400 ++#elif defined(CONFIG_MACH_NSP) ++#define SOC_ROM_LUT_OFF 0x42c ++#elif defined(CONFIG_MACH_CYGNUS) ++#define SOC_ROM_LUT_OFF 0x400 ++#elif defined(CONFIG_MACH_KT2) ++#define SOC_ROM_LUT_OFF 0x42c ++#else ++#error "SOC_ROM_LUT_OFF is not defined" ++#endif ++ ++/* ++ * control for which core is the next to come out of the secondary ++ * boot "holding pen" ++ */ ++volatile int pen_release = -1; ++ ++/* SCU base address */ ++static void __iomem *scu_base = (void __iomem *)(IPROC_PERIPH_SCU_REG_VA); ++ ++/* ++ * Use SCU config register to count number of cores ++ */ ++static inline unsigned int get_core_count(void) ++{ ++ if (scu_base) ++ return scu_get_core_count(scu_base); ++ return 1; ++} ++ ++/* ++ * Initialise the CPU possible map early - this describes the CPUs ++ * which may be present or become present in the system. ++ */ ++void __init smp_init_cpus(void) ++{ ++unsigned int i, ncores = get_core_count(); ++ ++ printk(KERN_DEBUG "smp_init_cpus: Enter ncores %d\n", ncores); ++ ++ for (i = 0; i < ncores; i++) ++ set_cpu_possible(i, true); ++ ++ set_smp_cross_call(gic_raise_softirq); ++ ++ printk(KERN_DEBUG "smp_init_cpus: Leave ncores %d\n", ncores); ++} ++ ++static DEFINE_SPINLOCK(boot_lock); ++ ++ ++ ++#ifdef CONFIG_BCM_IPROC_CA9_PREFETCH ++ ++static void enable_a9_features(void) { ++ unsigned int a9_aux=0, a9_aux_m=0, a9_sys=0; ++ ++ // Read a9_aux Register ++ asm volatile ("MRC p15, 0, %0, c1, c0, 1\t\n": "=r"(a9_aux)); ++ ++ // Write a9_aux Register; L1/L2 prefetch enable & Fill line zero ++ asm volatile ("mcr p15, 0, %0, c1, c0, 1\t\n" : : "r"(a9_aux | (0x7 << 1))); ++ ++ // Read a9_aux Register again ++ asm volatile ("MRC p15, 0, %0, c1, c0, 1\t\n": "=r"(a9_aux_m)); ++ ++ //System Control Register ++ asm volatile ("MRC p15, 0, %0, c1, c0, 0\t\n": "=r"(a9_sys)); ++ ++ printk(KERN_INFO "\n<%s> CUP_ID %d a9_aux = 0x%x; a9_aux_m = 0x%x; a9_sys = 0x%x\n", \ ++ __FUNCTION__, smp_processor_id(), a9_aux, a9_aux_m, a9_sys); ++} ++ ++#endif ++ ++ ++void __cpuinit platform_secondary_init(unsigned int cpu) ++{ ++ printk(KERN_DEBUG "platform_secondary_init: Enter cpu %d\n", cpu); ++ ++ ++ /* ++ * If any interrupts are already enabled for the primary ++ * core (e.g. timer irq), then they will not have been enabled ++ * for us: do so ++ */ ++ ++ // modelled after omap-smp.c:platform_secondary_init() changes ++ // between 2.6.37.6 and 2.6.38.1. ++ gic_secondary_init(0); ++ ++ /* ++ * let the primary processor know we're out of the ++ * pen, then head off into the C entry point ++ */ ++ pen_release = -1; ++ ++ ++#ifdef CONFIG_BCM_IPROC_CA9_PREFETCH ++ enable_a9_features(); ++ smp_call_function((void (*)(void))enable_a9_features, NULL, 0); ++#endif ++ ++ ++ smp_wmb(); ++ ++ /* ++ * Synchronise with the boot thread. ++ */ ++ spin_lock(&boot_lock); ++ spin_unlock(&boot_lock); ++ ++ printk(KERN_DEBUG "platform_secondary_init: Leave pen_release %d\n", pen_release); ++} ++ ++int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ++{ ++ unsigned long timeout; ++ ++ printk(KERN_DEBUG "boot_secondary: Enter CPU%d\n", cpu); ++ ++ /* ++ * Set synchronisation state between this boot processor ++ * and the secondary one ++ */ ++ spin_lock(&boot_lock); ++ ++ /* ++ * 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. ++ */ ++ pen_release = cpu; ++ clean_dcache_area( (void *) &pen_release, sizeof(pen_release)); ++ outer_clean_range(__pa(&pen_release), ++ __pa(&pen_release + sizeof(pen_release))); ++ // flush_cache_all(); ++ ++ /* ++ * Now the secondary CPU must start marching on its ++ * own. ++ */ ++ dsb_sev(); ++ ++ /* wait at most 1 second for the secondary to wake up */ ++ ++ timeout = jiffies + (1 * HZ); ++ while (time_before(jiffies, timeout)) { ++ smp_rmb(); ++ if (pen_release == -1) ++ break; ++ ++ udelay(10); ++ clean_dcache_area( (void *) &pen_release, sizeof(pen_release)); ++ } ++ ++ /* ++ * Now the secondary core is starting up let it run its ++ * calibrations, then wait for it to finish ++ */ ++ spin_unlock(&boot_lock); ++ ++ printk(KERN_DEBUG "boot_secondary: Leave pen-release %d\n", pen_release); ++ ++ return pen_release != -1 ? -ENOSYS : 0; ++} ++ ++ ++static void __init wakeup_secondary(unsigned cpu, void (* _sec_entry_va)(void)) ++{ ++ void __iomem * rombase = NULL; ++ phys_addr_t lut_pa; ++ u32 offset; ++ u32 mask; ++ u32 val; ++ ++ printk(KERN_DEBUG "wakeup_secondary: Enter cpu %d\n", cpu); ++ ++ mask = (1UL << PAGE_SHIFT) -1; ++ ++ lut_pa = SOC_ROM_BASE_PA & ~mask; ++ offset = SOC_ROM_BASE_PA & mask; ++ offset += SOC_ROM_LUT_OFF; ++ ++ rombase = ioremap(lut_pa, PAGE_SIZE); ++ if(rombase == NULL) ++ return; ++ val = virt_to_phys(_sec_entry_va); ++ ++ writel(val, rombase + offset); ++ ++ smp_wmb(); /* probably not needed - io regs are not cached */ ++ ++#ifdef CONFIG_SMP ++ dsb_sev(); /* Exit WFI */ ++#endif ++ mb(); ++ ++ iounmap(rombase); ++ ++ printk(KERN_DEBUG "wakeup_secondary: Leave cpu %d\n", cpu); ++} ++ ++ ++void __init platform_smp_prepare_cpus(unsigned int max_cpus) ++{ ++ int i; ++ ++ /* ++ * Initialise the present map, which describes the set of CPUs ++ * actually populated at the present time. ++ */ ++ for (i = 0; i < max_cpus; i++) ++ set_cpu_present(i, true); ++ ++ /* ++ * Initialise the SCU and wake up the secondary core using ++ * wakeup_secondary(). ++ */ ++ scu_enable(scu_base); ++ wakeup_secondary(max_cpus, iproc_secondary_startup); ++} +diff --git a/arch/arm/plat-iproc/shm.c b/arch/arm/plat-iproc/shm.c +new file mode 100644 +index 0000000..2c59270 +--- /dev/null ++++ b/arch/arm/plat-iproc/shm.c +@@ -0,0 +1,171 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include "include/plat/shm.h" ++/** ++ * iproc_platform_get_irq - get an IRQ for a device ++ * wrapper function for platform_get_irq ++ * @dev: platform device ++ * @num: IRQ number index ++ */ ++int iproc_platform_get_irq(struct platform_device *dev, unsigned int num) ++{ ++ return platform_get_irq(dev, num); ++} ++EXPORT_SYMBOL(iproc_platform_get_irq); ++ ++ ++/** ++ * iproc_platform_get_resource_byname - ++ * wrapper function for platform_get_resource_byname ++ * @dev: platform device ++ * @type: resource type ++ * @name: resource name ++ */ ++struct resource * ++iproc_platform_get_resource_byname(struct platform_device *dev, ++ unsigned int type, ++ const char *name) ++{ ++ return platform_get_resource_byname(dev, type, name); ++} ++EXPORT_SYMBOL(iproc_platform_get_resource_byname); ++ ++ ++/** ++ * iproc_platform_get_resource - ++ * wrapper function for platform_get_resource ++ * @dev: platform device ++ * @type: resource type ++ * @num: resource index ++ */ ++struct resource * ++iproc_platform_get_resource(struct platform_device *dev, unsigned int type, ++ unsigned int num) ++{ ++ return platform_get_resource(dev, type, num); ++} ++EXPORT_SYMBOL(iproc_platform_get_resource); ++ ++ ++/** ++ * iproc_platform_driver_register - ++ * wrapper function for platform_driver_register ++ * @drv: platform driver structure ++ */ ++int iproc_platform_driver_register(struct platform_driver *drv) ++{ ++ return platform_driver_register(drv); ++} ++EXPORT_SYMBOL(iproc_platform_driver_register); ++ ++ ++/** ++ * iproc_platform_driver_unregister ++ * wrapper function for platform_driver_unregister ++ * @drv: platform driver structure ++ */ ++void iproc_platform_driver_unregister(struct platform_driver *drv) ++{ ++ return platform_driver_unregister(drv); ++} ++EXPORT_SYMBOL(iproc_platform_driver_unregister); ++ ++ ++/** ++ * iproc_platform_device_register - add a platform-level device ++ * wrapper function for platform_device_register ++ * @pdev: platform device we're adding ++ * ++ */ ++int iproc_platform_device_register(struct platform_device * pdev) ++{ ++ return platform_device_register(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_register); ++ ++ ++/** ++ * iproc_platform_device_unregister - ++ * wrapper function for platform_device_unregister ++ * @pdev: platform device we're unregistering ++ */ ++void iproc_platform_device_unregister(struct platform_device * pdev) ++{ ++ return platform_device_unregister(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_unregister); ++ ++ ++/** ++ * iproc_platform_device_alloc - ++ * wrapper function for platform_device_alloc ++ * @name: base name of the device we're adding ++ * @id: instance id ++ */ ++struct platform_device *iproc_platform_device_alloc(const char *name, int id) ++{ ++ return platform_device_alloc(name, id); ++} ++EXPORT_SYMBOL(iproc_platform_device_alloc); ++ ++/** ++ * iproc_platform_device_add - ++ * wrapper function for platform_device_add ++ * @pdev: platform device we're adding ++ */ ++int iproc_platform_device_add(struct platform_device *pdev) ++{ ++ return platform_device_add(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_add); ++ ++/** ++ * iproc_platform_device_put - ++ * wrapper function for platform_device_put ++ * @pdev: platform device to free ++ */ ++void iproc_platform_device_put(struct platform_device *pdev) ++{ ++ platform_device_put(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_put); ++ ++ ++/** ++ * iproc_platform_device_put - ++ * wrapper function for sysfs_create_group ++ * @kobj: The kobject to create the group on ++ * @grp: The attribute group to create ++ */ ++int iproc_sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) ++{ ++ return sysfs_create_group(kobj, grp); ++} ++EXPORT_SYMBOL(iproc_sysfs_create_group); ++ ++ ++/** ++ * iproc_sysfs_remove_group - ++ * wrapper function for sysfs_remove_group ++ * @kobj: The kobject which the group is on ++ * @grp: The attribute group to remove ++ */ ++void iproc_sysfs_remove_group(struct kobject * kobj, const struct attribute_group * grp) ++{ ++ sysfs_remove_group(kobj, grp); ++} ++EXPORT_SYMBOL(iproc_sysfs_remove_group); +diff --git a/arch/arm/plat-iproc/swreset_rec.c b/arch/arm/plat-iproc/swreset_rec.c +new file mode 100644 +index 0000000..aaa0d61 +--- /dev/null ++++ b/arch/arm/plat-iproc/swreset_rec.c +@@ -0,0 +1,175 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MAX_SWRESET_RECORD_COUNT (4) ++ ++struct swreset_record { ++ int position; ++}; ++ ++struct swreset_record records[MAX_SWRESET_RECORD_COUNT]; ++static unsigned int record_count; ++static unsigned int record_width; ++static DEFINE_SPINLOCK(swrr_lock); ++ ++unsigned int ++swreset_record_get_record_width(void) ++{ ++ return record_width; ++} ++ ++unsigned int ++swreset_record_get_record_count(void) ++{ ++ return record_count; ++} ++ ++SWRR_HANDLE ++swreset_record_register(const char *name) ++{ ++ int i; ++ int j; ++ ++ if (record_count == 0) { ++ return NULL; ++ } ++ ++ /* Use the name as a hash value to try to avoid race condition */ ++ j = 0; ++ while(*name != 0) { ++ j += *name; ++ if (j > 0xff) ++ j = (j & 0xff) + 1; ++ name++; ++ } ++ ++ for(i=0; iposition < 0 || swrr->position >= record_count) ++ return; ++ swrr->position = -1; ++} ++ ++int ++swreset_record_set(SWRR_HANDLE handle, int value) ++{ ++ struct swreset_record *swrr = (struct swreset_record *)handle; ++ void __iomem *reg; ++ unsigned long rval; ++ unsigned long flags; ++ ++ if (handle == NULL) ++ return -1; ++ if (swrr->position < 0 || swrr->position >= record_count) ++ return -1; ++ if (value & ~((1 << record_width) - 1)) ++ return -1; ++ ++ /* This requires atomic operation */ ++ spin_lock_irqsave(&swrr_lock, flags); ++ ++ /* CoStar specific; could require modification for newer chips */ ++ reg = IOMEM(IPROC_DMU_BASE_VA + IPROC_DMU_CLKSET_KEY_OFFSET); ++ writel(0xea68, reg); /* magic number */ ++ reg = IOMEM(IPROC_DMU_BASE_VA + IPROC_DMU_GENPLL_CONTROL5_OFFSET); ++ writel(readl(reg) | (1 << IPROC_DMU_GENPLL_CONTROL5__SEL_SW_SETTING), reg); ++ reg = IOMEM(IPROC_DMU_BASE_VA + IPROC_DMU_GENPLL_CONTROL7_OFFSET); ++ rval = readl(reg) & ~(1 << (IPROC_DMU_GENPLL_CONTROL7__SW_RESET_REC + swrr->position)); ++ rval |= value << (IPROC_DMU_GENPLL_CONTROL7__SW_RESET_REC + swrr->position); ++ writel(rval, reg); ++ ++ spin_unlock_irqrestore(&swrr_lock, flags); ++ return 0; ++} ++ ++int ++swreset_record_get(SWRR_HANDLE handle, int *value) ++{ ++ struct swreset_record *swrr = (struct swreset_record *)handle; ++ void __iomem *reg; ++ unsigned long flags; ++ ++ if (handle == NULL) ++ return -1; ++ if (swrr->position < 0 || swrr->position >= record_count) ++ return -1; ++ if (value == NULL) ++ return 0; ++ ++ /* This requires atomic operation */ ++ spin_lock_irqsave(&swrr_lock, flags); ++ ++ /* CoStar specific; could require modification for newer chips */ ++ reg = IOMEM(IPROC_DMU_BASE_VA + IPROC_DMU_CLKSET_KEY_OFFSET); ++ writel(0xea68, reg); /* magic number */ ++ reg = IOMEM(IPROC_DMU_BASE_VA + IPROC_DMU_GENPLL_CONTROL5_OFFSET); ++ writel(readl(reg) | (1 << IPROC_DMU_GENPLL_CONTROL5__SEL_SW_SETTING), reg); ++ reg = IOMEM(IPROC_DMU_BASE_VA + IPROC_DMU_GENPLL_CONTROL7_OFFSET); ++ *value = readl(reg) >> IPROC_DMU_GENPLL_CONTROL7__SW_RESET_REC; ++ *value = (*value >> swrr->position) & 1; ++ ++ spin_unlock_irqrestore(&swrr_lock, flags); ++ return 0; ++} ++ ++int __init ++init_swreset_records(void) ++{ ++ int i; ++ for(i=0; i ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct kobject *bcm_kobj; ++ ++static ssize_t ++mem_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t n) ++{ ++ uint32_t addr, val, count = 0, loop = 0; ++ void __iomem *vaddr; ++ char rw; ++ ++ if (sscanf(buf, "%c %x %x", &rw, &addr, &val) == 3) { ++ pr_info("\n"); ++ vaddr = ioremap(addr, PAGE_SIZE); ++ if (rw == 'W' || rw == 'w') { ++ writel(val, vaddr); ++ count = 4; ++ } else if (rw == 'R' || rw == 'r') { ++ count = val; /* count read in val for simplicity */ ++ if (count & 0x3) /* Align to 4 */ ++ count += (4 - (count & 0x3)); ++ } ++ for (; loop < count; loop += 4) { ++ val = readl(vaddr + loop); ++ pr_info("[0x%08x] = 0x%08x\n", addr + loop, val); ++ } ++ iounmap(vaddr); ++ return n; ++ } ++ pr_info("\nUsage: echo " ++ " /sys/bcm/mem\n" ++ "E.g. echo R 0x88CE000 0x40 > /sys/bcm/mem\n" ++ " echo w 0x88CE000 0xDEADBEAF > /sys/bcm/mem\n"); ++ return -EINVAL; ++} ++ ++#ifdef CONFIG_IPROC_TIMER_UNIT_TESTS ++static ssize_t ++iproc_timer_module_cfg(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t n) ++{ ++ char name[255]; ++ unsigned int rate; ++ ++ if (sscanf(buf, "%s %d", name, &rate) == 2) { ++ ++ pr_info("timer name:%s rate(0-32KHz, 1-1MHz, 2-19.5MHz):%d \r\n", ++ name, rate); ++ ++ /* ++ * Assuming that iproc_timer_modules_init has happend already (this is ++ * safe because this function is called during system timer init ++ * itself ++ */ ++ if ( iproc_timer_module_set_rate(name,rate) < 0) { ++ pr_err("iproc_timer_module_cfg: Unable to set the said rate \r\n"); ++ return n; ++ } ++ ++ pr_info("iproc_timer_module_cfg: Configured the module with" ++ "rate %d \r\n", rate); ++ ++ return n; ++ } ++ ++ pr_info("\r\nusage: echo [timer_name(aon-timer/slave-timer)]" ++ "[rate (0-32KHz, 1-1MHz, 2-19.5MHz)] > /sys/bcm/timer_module_cfg \r\n"); ++ ++ return -EINVAL; ++} ++ ++struct iproc_timer *kt; ++struct timer_ch_cfg cfg; ++int timer_callback (void *p); ++ ++/* Note that this is called back from ISR context */ ++int timer_callback (void *p) ++{ ++ pr_info("timer callback \r\n"); ++ return 0; ++} ++ ++static ssize_t ++iproc_timer_start_test(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t n) ++{ ++ unsigned int ch_num, mode, count; ++ char name[255]; ++ ++ if (sscanf(buf, "%s %d %d %d", name, &ch_num, &mode, &count) == 4) { ++ ++ pr_info("channel_num:%d mode(0-periodic 1-oneshot):%d count:%d \r\n", ++ ch_num, mode, count); ++ ++ if ( (kt=iproc_timer_request (name, ch_num)) < 0) { ++ pr_err("iproc_timer_request returned error \r\n"); ++ goto out; ++ } ++ ++ cfg.mode = mode; ++ cfg.arg = kt; ++ cfg.cb = timer_callback; ++ cfg.reload = count; ++ ++ if ( iproc_timer_config(kt,&cfg) < 0) { ++ pr_err("iproc_timer_config returned error \r\n"); ++ goto out; ++ } ++ ++ if (iproc_timer_set_match_start(kt,count) < 0) { ++ pr_err("iproc_timer_set_match_start returned error \r\n"); ++ goto out; ++ } ++ pr_info("Timer test started \r\n"); ++out: ++ return n; ++ } ++ ++ pr_info("\r\nusage: echo [name (aon-timer/slave-timer)] " ++ "[channel num (0-3)] [mode(0-periodic" ++ "1-oneshot)] [count value] > /sys/bcm/timer_start_test\r\n"); ++ return -EINVAL; ++} ++ ++static ssize_t ++iproc_timer_stop_test(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t n) ++{ ++ unsigned int ch_num; ++ ++ if (sscanf(buf, "%d", &ch_num) == 1) { ++ pr_info("channel_num:%d \r\n", ch_num); ++ if (iproc_timer_stop(kt) < 0) { ++ pr_err("Unable to stop the timer iproc_timer_stop " ++ "returned error \r\n"); ++ goto out; ++ } ++ ++ if (iproc_timer_free(kt) < 0) { ++ pr_err("Unable to free the timer \r\n"); ++ goto out; ++ } ++ pr_info("Stopped and freed the timer \r\n"); ++out: ++ return n; ++ } ++ ++ pr_info("\r\nusage: echo [channel num (0-3)] > " ++ "/sys/bcm/timer_stop_test\r\n"); ++ return -EINVAL; ++} ++#endif ++ ++static DEVICE_ATTR(mem, 0644, NULL, mem_store); ++ ++#ifdef CONFIG_IPROC_TIMER_UNIT_TESTS ++static DEVICE_ATTR(timer_module_cfg, 0666, NULL, iproc_timer_module_cfg); ++static DEVICE_ATTR(timer_start_test, 0666, NULL, iproc_timer_start_test); ++static DEVICE_ATTR(timer_stop_test, 0666, NULL, iproc); ++#endif ++ ++static struct attribute *bcm_attrs[] = { ++ &dev_attr_mem.attr, ++#ifdef CONFIG_IPROC_TIMER_UNIT_TESTS ++ &dev_attr_timer_module_cfg.attr, ++ &dev_attr_timer_start_test.attr, ++ &dev_attr_timer_stop_test.attr, ++#endif ++ NULL, ++}; ++ ++static struct attribute_group bcm_attr_group = { ++ .attrs = bcm_attrs, ++}; ++ ++static int __init bcm_sysfs_init(void) ++{ ++ bcm_kobj = kobject_create_and_add("bcm", NULL); ++ if (!bcm_kobj) ++ return -ENOMEM; ++ return sysfs_create_group(bcm_kobj, &bcm_attr_group); ++} ++ ++static void __exit bcm_sysfs_exit(void) ++{ ++ sysfs_remove_group(bcm_kobj, &bcm_attr_group); ++} ++ ++module_init(bcm_sysfs_init); ++module_exit(bcm_sysfs_exit); +diff --git a/arch/arm/plat-iproc/timer-sp.c b/arch/arm/plat-iproc/timer-sp.c +new file mode 100644 +index 0000000..7773e1c +--- /dev/null ++++ b/arch/arm/plat-iproc/timer-sp.c +@@ -0,0 +1,250 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++//#include ++#include ++ ++#include ++ ++/* ++ * These timers are currently setup to be clocked at 50MHz. ++ */ ++#define ONE_MHZ (1000000) ++#define TIMER_FREQ_HZ (ONE_MHZ * 500) ++#define TIMER_FREQ_KHZ (TIMER_FREQ_HZ/1000) ++#define TIMER_MIN_RANGE 4 ++ ++#define TIM_COUNT_LO 0x00 /* ACVR rw */ ++#define TIM_COUNT_HI 0x04 /* ACVR ro */ ++#define TIMER_CTRL 0x08 /* ACVR rw */ ++#define TIMER_INT_STAT 0x0C ++#define TIMER_COMP_LO 0x10 ++#define TIMER_COMP_HI 0x14 ++#define TIMER_RELOAD 0x18 ++#define TIMER_CTRL_PRESC_SHFT (8) /* ACVR */ ++ ++#define TIMER_ENABLE (1 << 0) /* ACVR */ ++#define TIMER_CMP (1 << 1) ++#define TIMER_IRQ (1 << 2) ++#define TIMER_AUTO (1 << 3) ++ ++extern unsigned long clk_get_rate(struct clk *clk); ++ ++static void __iomem *clksrc_base; ++static u32 ticks_per_jiffy; ++static u32 timer_ints = 0; ++static unsigned long cpu_clk_freq = 0; ++ ++static cycle_t iproc_read(struct clocksource *cs) ++{ ++ u32 hi; ++ u32 lo; ++ u32 ho; ++ u64 count; ++ ++ /* ++ * Read the upper half to detect a roll-over count ++ */ ++ do { ++ hi = readl(clksrc_base + TIM_COUNT_HI); ++ lo = readl(clksrc_base + TIM_COUNT_LO); ++ ho = readl(clksrc_base + TIM_COUNT_HI); ++ } while(hi != ho); ++ ++ count = (u64) hi << 32 | lo; ++ return count; ++ ++} ++static void iproc_set_mode(enum clock_event_mode mode, ++ struct clock_event_device *evt); ++ ++static int iproc_set_next_event(unsigned long next, ++ struct clock_event_device *evt); ++static struct clock_event_device iproc_clockevent = { ++ .name = "iproc_gtimer", ++ .shift = 20, ++ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, ++ .set_mode = iproc_set_mode, ++ .set_next_event = iproc_set_next_event, ++ .rating = 300, ++ .cpumask = cpu_all_mask, ++}; ++ ++ ++static struct clocksource clocksource_iproc = { ++ .name = "iproc_gtimer", ++ .rating = 300, ++ .read = iproc_read, ++ .mask = CLOCKSOURCE_MASK(64), ++ .shift = 20, ++ .flags = CLOCK_SOURCE_IS_CONTINUOUS, ++}; ++extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); ++ ++void __init iproc_clocksource_init(void __iomem *base) ++{ ++ struct clocksource *cs = &clocksource_iproc; ++ struct clk *clk; ++ ++ clksrc_base = base; ++ ++ /* ++ * setup global CPU timer as free-running clocksource ++ * obtain CPU clock frequency from clock module configuration ++ */ ++ clk = clk_get_sys(NULL, "periph_clk"); ++ BUG_ON(IS_ERR_OR_NULL(clk)); ++ clk_prepare(clk); ++ clk_enable(clk); ++ cpu_clk_freq = clk_get_rate(clk); ++ BUG_ON(!cpu_clk_freq); ++ ++ ++ printk(KERN_DEBUG ++ "iproc_clocksource_init: CPU global timer freq %lu\n", ++ cpu_clk_freq); ++ ++ /* ref - arch/arcm/mach-u300/timer.c (2.6.37 vs 2.6.38) */ ++ clocksource_register_hz(cs, cpu_clk_freq); ++} ++ ++ ++static void __iomem *clkevt_base; ++ ++/* ++ * IRQ handler for the timer ++ */ ++ irqreturn_t iproc_timer_interrupt(int irq, void *dev_id) ++{ ++ struct clock_event_device *evt = &iproc_clockevent; ++#warning "iproc_timer_interrupt: Fix this code to receive clock_event handler correctly" ++ ++ /* clear the interrupt */ ++ writel(1, clkevt_base + TIMER_INT_STAT); ++ ++ timer_ints++; ++ evt->event_handler(evt); ++ ++ return IRQ_HANDLED; ++} ++ ++static void iproc_set_mode(enum clock_event_mode mode, ++ struct clock_event_device *evt) ++{ ++ u32 ctrl; ++ u32 period; ++ u64 count; ++ ++ ctrl = readl(clkevt_base + TIMER_CTRL); ++ ++ /* Clear mode bits */ ++ ctrl &= ~(TIMER_CMP | TIMER_IRQ | TIMER_AUTO); ++ ++ switch (mode) { ++ case CLOCK_EVT_MODE_PERIODIC: ++ writel(ctrl, clkevt_base + TIMER_CTRL); ++ period = ticks_per_jiffy; ++ count = iproc_read(NULL); ++ count += period; ++ writel(ctrl, clkevt_base + TIMER_CTRL); ++ writel(period, clkevt_base + TIMER_RELOAD); ++ ctrl = (TIMER_CMP | ++ TIMER_IRQ | ++ TIMER_AUTO | ++ TIMER_ENABLE); ++ break; ++ ++ case CLOCK_EVT_MODE_ONESHOT: ++ /* period set, and timer enabled in 'next_event' hook */ ++ break; ++ ++ case CLOCK_EVT_MODE_UNUSED: ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ break; ++ default: ++ break; ++ } ++ ++ writel(ctrl, clkevt_base + TIMER_CTRL); ++} ++ ++static int iproc_set_next_event(unsigned long next, ++ struct clock_event_device *evt) ++{ ++ u64 count = iproc_read(NULL); ++ u32 ctrl = readl(clkevt_base + TIMER_CTRL); ++ ++ ctrl &= ~TIMER_CMP; ++ writel(ctrl, clkevt_base + TIMER_CTRL); ++ ++ count += next; ++ writel(count & 0xffffffffUL, clkevt_base + TIMER_COMP_LO); ++ //writel(count, clkevt_base + TIM_COUNT_LO); ++ writel(count >> 32, clkevt_base + TIMER_COMP_HI); ++ ++ ctrl |= (TIMER_CMP | TIMER_IRQ); ++ writel(ctrl, clkevt_base + TIMER_CTRL); ++ ++ return 0; ++} ++ ++static struct irqaction iproc_timer_irq = { ++ .name = "iproc_gtimer", ++ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_PERCPU, ++ .handler = iproc_timer_interrupt, ++ .dev_id = &iproc_clockevent, ++ .irq = BCM_INT_ID_PPI11, ++}; ++ ++void __init iproc_clockevents_init(void __iomem *base, unsigned int timer_irq) ++{ ++ int ret; ++ clkevt_base = base; ++ ticks_per_jiffy = (cpu_clk_freq/HZ); ++ ++ clockevents_calc_mult_shift(&iproc_clockevent, cpu_clk_freq, TIMER_MIN_RANGE); ++ iproc_clockevent.max_delta_ns = ++ clockevent_delta2ns(0x1fffffff, &iproc_clockevent); ++ iproc_clockevent.min_delta_ns = ++ clockevent_delta2ns(0xf, &iproc_clockevent); ++ iproc_clockevent.cpumask = cpumask_of(0); ++ iproc_clockevent.irq = timer_irq; ++ clockevents_register_device(&iproc_clockevent); ++#warning "iproc_clockevents_init: Fix this code to enable timer irq and pass clock_event handler correctly" ++ ret = setup_percpu_irq(timer_irq, &iproc_timer_irq); ++ if (ret) { ++ printk(KERN_ERR "Failed to register timer IRQ: %d\n", ret); ++ BUG(); ++ } ++ ++ printk(KERN_DEBUG "cpu_clk_freq: %lu\n", cpu_clk_freq); ++ printk(KERN_DEBUG "HZ: %d, ticks_per_jiffy: %u\n", HZ, ticks_per_jiffy); ++ ++ enable_percpu_irq(timer_irq, 0); ++ ++} +diff --git a/arch/arm/plat-iproc/timer.c b/arch/arm/plat-iproc/timer.c +new file mode 100644 +index 0000000..f92e244 +--- /dev/null ++++ b/arch/arm/plat-iproc/timer.c +@@ -0,0 +1,280 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_LOCAL_TIMERS ++#include ++#endif ++ ++static struct iproc_timer *gpt_evt = NULL; ++static struct iproc_timer *gpt_src = NULL; ++static void __iomem* proftmr_regbase = IOMEM(IPROC_CCU_PROF_CTL_REG_VA); ++ ++static int gptimer_set_next_event(unsigned long clc, ++ struct clock_event_device *unused) ++{ ++ /* gptimer (0) is disabled by the timer interrupt already ++ * so, here we reload the next event value and re-enable ++ * the timer ++ * ++ * This way, we are potentially losing the time between ++ * timer-interrupt->set_next_event. CPU local timers, when ++ * they come in should get rid of skew ++ */ ++ iproc_timer_set_match_start(gpt_evt,clc); ++ return 0; ++} ++ ++static void gptimer_set_mode(enum clock_event_mode mode, ++ struct clock_event_device *unused) ++{ ++ switch (mode) { ++ case CLOCK_EVT_MODE_ONESHOT: ++ /* by default mode is one shot don't do any thing */ ++ break; ++ case CLOCK_EVT_MODE_UNUSED: ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ default: ++ iproc_timer_disable_and_clear(gpt_evt); ++ } ++} ++ ++static cycle_t gptimer_clksrc_read (struct clocksource *cs) ++{ ++ unsigned long msw, lsw; ++ cycle_t count = 0; ++ ++ iproc_timer_get_counter (gpt_src, &msw, &lsw); ++ count = ((cycle_t)msw << 32) | (cycle_t)lsw; ++ return count; ++} ++ ++static struct clock_event_device clockevent_gptimer = { ++ .name = "gpt_event_1", ++ .features = CLOCK_EVT_FEAT_ONESHOT, ++ .shift = 32, ++ .set_next_event = gptimer_set_next_event, ++ .set_mode = gptimer_set_mode ++}; ++ ++static struct clocksource clksrc_gptimer = { ++ .name = "gpt_source_2", ++ .rating = 200, ++ .read = gptimer_clksrc_read, ++ .mask = CLOCKSOURCE_MASK(64), ++ .shift = 16, ++ .flags = CLOCK_SOURCE_IS_CONTINUOUS, ++}; ++ ++static void __init gptimer_clockevents_init(void) ++{ ++ clockevent_gptimer.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ++ clockevent_gptimer.shift); ++ ++ clockevent_gptimer.max_delta_ns = ++ clockevent_delta2ns(0xffffffff, &clockevent_gptimer); ++ ++ clockevent_gptimer.min_delta_ns = ++ clockevent_delta2ns(6, &clockevent_gptimer); ++ ++ clockevent_gptimer.cpumask = cpumask_of(0); ++ clockevents_register_device(&clockevent_gptimer); ++} ++ ++static void __init gptimer_clocksource_init(void) ++{ ++ clksrc_gptimer.mult = clocksource_hz2mult(CLOCK_TICK_RATE, ++ clksrc_gptimer.shift); ++ clocksource_register(&clksrc_gptimer); ++ return; ++} ++ ++static int gptimer_interrupt_cb(void *dev) ++{ ++ struct clock_event_device *evt = (struct clock_event_device *)dev; ++ evt->event_handler(evt); ++ return 0; ++} ++ ++static void profile_timer_init(void __iomem *base) ++{ ++ uint32_t reg; ++ ++ /* Reset profile/global timer */ ++ writel(0, base + IPROC_GTIM_GLB_CTL); ++ ++ /* Clear pending interrupts */ ++ reg = readl(base + IPROC_GTIM_GLB_STS); ++ reg &= ~(IPROC_GLB_TIM_CTRL_PRESC_MASK); ++ reg |= (1 << GLBTMR_GLOB_STATUS_EVENT_G_SHIFT); ++ writel(reg, base + IPROC_GTIM_GLB_STS); ++ ++ /* Enable profile timer now with ++ * prescaler = 0, so timer freq = A9 PERIPHCLK ++ * IRQ disabled ++ * Comapre disabled ++ */ ++ ++ reg = readl(base + IPROC_GTIM_GLB_CTL); ++ reg &= ~(IPROC_GLB_TIM_CTRL_PRESC_MASK); ++ reg |= (1 << GLBTMR_GLOB_CTRL_TIMER_EN_G_SHIFT); ++ writel(reg, base + IPROC_GTIM_GLB_CTL); ++} ++ ++static void ++profile_timer_get_counter(void __iomem *base, uint32_t *msw, uint32_t *lsw) ++{ ++ /* Read 64-bit free running counter ++ * 1. Read hi-word ++ * 2. Read low-word ++ * 3. Read hi-word again ++ * 4.1 ++ * if new hi-word is not equal to previously read hi-word, then ++ * start from #1 ++ * 4.2 ++ * if new hi-word is equal to previously read hi-word then stop. ++ */ ++ ++ while (1) { ++ *msw = readl(base + IPROC_GTIM_GLB_HI); ++ *lsw = readl(base + IPROC_GTIM_GLB_LO); ++ if (*msw == readl(base + IPROC_GTIM_GLB_HI)) ++ break; ++ } ++ ++ return; ++} ++ ++static void __init timers_init(struct gp_timer_setup *gpt_setup) ++{ ++ struct timer_ch_cfg evt_tm_cfg; ++ ++ iproc_timer_modules_init (); ++ iproc_timer_module_set_rate(gpt_setup->name, gpt_setup->rate); ++ ++ /* Initialize Event timer */ ++ gpt_evt = iproc_timer_request(gpt_setup->name, gpt_setup->ch_num); ++ if (gpt_evt == NULL) { ++ pr_err("timers_init: Unable to get GPT timer for event\r\n"); ++ } ++ ++ pr_info("timers_init: === SYSTEM TIMER NAME: %s CHANNEL NUMBER %d \ ++ RATE (0-32KHz, 1-1MHz) %d \r\n",gpt_setup->name, ++ gpt_setup->ch_num, gpt_setup->rate); ++ ++ evt_tm_cfg.mode = MODE_PERIODIC; ++ evt_tm_cfg.arg = &clockevent_gptimer; ++ evt_tm_cfg.cb = gptimer_interrupt_cb; ++ ++ iproc_timer_config(gpt_evt, &evt_tm_cfg); ++ ++ gptimer_set_next_event((CLOCK_TICK_RATE / HZ), NULL); ++ ++ /* ++ * IMPORTANT ++ * Note that we don't want to waste a channel for clock source. In iProc ++ * timer module by default there is a counter that keeps counting ++ * irrespective of the channels. So instead of implementing a periodic ++ * timer using a channel (which in the HW is not peridoic) we can ++ * simply read the counters of the timer that is used for event and ++ * send it for source. The only catch is that this timer should not be ++ * stopped by PM or any other sub-systems. ++ */ ++ gpt_src = gpt_evt; ++ ++ /* Initialize the profile timer */ ++ ++ return ; ++} ++ ++void __init iproc_timer_init(struct gp_timer_setup *gpt_setup) ++{ ++ timers_init(gpt_setup); ++ gptimer_clocksource_init(); ++ gptimer_clockevents_init(); ++ gptimer_set_next_event((CLOCK_TICK_RATE / HZ), NULL); ++#ifdef CONFIG_LOCAL_TIMERS ++ twd_base = IOMEM(IPROC_PERIPH_PVT_TIM_REG_VA); ++#endif ++ ++} ++ ++ ++/* Profile timer implementations */ ++ ++/* ++ * TODO: The below profile timer code is retained as it is. ++ * The clock manager is not up yet, once its ready read the ++ * correct frequency from it. ++ * ++ * Right now Global timer runs at 5000000 on FPGA (A9 PERIPHCLK) ++ * Ideally, this should be derived by timer.prof_clk and ++ * prescaler. ++ */ ++ ++#define GLOBAL_TIMER_FREQ_HZ (351875) /* For FPGA only, (temp)*/ ++//#define GLOBAL_TIMER_FREQ_HZ (500000) /* For FPGA only, (temp)*/ ++timer_tick_rate_t timer_get_tick_rate(void) ++{ ++ uint32_t prescaler; ++ ++ prescaler = readl(IPROC_PERIPH_GLB_TIM_REG_BASE); ++ prescaler &= IPROC_GLB_TIM_CTRL_PRESC_MASK; ++ //prescaler >>= IPROC_GLB_TIM_CTRL_PRESC_SHIFT; ++ ++ return (GLOBAL_TIMER_FREQ_HZ / (1 + prescaler)); ++} ++ ++timer_tick_count_t timer_get_tick_count(void) ++{ ++ uint32_t msw, lsw; ++ uint64_t tick; ++ ++ profile_timer_get_counter(proftmr_regbase, &msw, &lsw); ++ ++ tick = (((uint64_t)msw << 32) | ((uint64_t)lsw)); ++ ++ return (*(uint32_t *)(&tick)); ++} ++ ++timer_msec_t timer_ticks_to_msec(timer_tick_count_t ticks) ++{ ++ return (ticks / (timer_get_tick_rate() / 1000)); ++} ++ ++timer_msec_t timer_get_msec(void) ++{ ++ return timer_ticks_to_msec(timer_get_tick_count()); ++} ++ ++EXPORT_SYMBOL(timer_get_tick_count); ++EXPORT_SYMBOL(timer_ticks_to_msec); ++EXPORT_SYMBOL(timer_get_tick_rate); ++EXPORT_SYMBOL(timer_get_msec); +diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c +index 10d1608..af95af2 100644 +--- a/arch/arm/plat-orion/gpio.c ++++ b/arch/arm/plat-orion/gpio.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + + /* + * GPIO unit register offsets. +@@ -289,12 +290,34 @@ void orion_gpio_set_blink(unsigned pin, int blink) + return; + + spin_lock_irqsave(&ochip->lock, flags); +- __set_level(ochip, pin, 0); +- __set_blinking(ochip, pin, blink); ++ __set_level(ochip, pin & 31, 0); ++ __set_blinking(ochip, pin & 31, blink); + spin_unlock_irqrestore(&ochip->lock, flags); + } + EXPORT_SYMBOL(orion_gpio_set_blink); + ++#define ORION_BLINK_HALF_PERIOD 100 /* ms */ ++ ++int orion_gpio_led_blink_set(unsigned gpio, int state, ++ unsigned long *delay_on, unsigned long *delay_off) ++{ ++ ++ if (delay_on && delay_off && !*delay_on && !*delay_off) ++ *delay_on = *delay_off = ORION_BLINK_HALF_PERIOD; ++ ++ switch (state) { ++ case GPIO_LED_NO_BLINK_LOW: ++ case GPIO_LED_NO_BLINK_HIGH: ++ orion_gpio_set_blink(gpio, 0); ++ gpio_set_value(gpio, state); ++ break; ++ case GPIO_LED_BLINK: ++ orion_gpio_set_blink(gpio, 1); ++ } ++ return 0; ++} ++EXPORT_SYMBOL_GPL(orion_gpio_led_blink_set); ++ + + /***************************************************************************** + * Orion GPIO IRQ +diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h +index 3abf304..bec0c98 100644 +--- a/arch/arm/plat-orion/include/plat/gpio.h ++++ b/arch/arm/plat-orion/include/plat/gpio.h +@@ -19,6 +19,8 @@ + */ + void orion_gpio_set_unused(unsigned pin); + void orion_gpio_set_blink(unsigned pin, int blink); ++int orion_gpio_led_blink_set(unsigned gpio, int state, ++ unsigned long *delay_on, unsigned long *delay_off); + + #define GPIO_INPUT_OK (1 << 0) + #define GPIO_OUTPUT_OK (1 << 1) +diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types +index ccbe16f..cd2db19 100644 +--- a/arch/arm/tools/mach-types ++++ b/arch/arm/tools/mach-types +@@ -1126,3 +1126,4 @@ atdgp318 MACH_ATDGP318 ATDGP318 3494 + m28evk MACH_M28EVK M28EVK 3613 + smdk4212 MACH_SMDK4212 SMDK4212 3638 + smdk4412 MACH_SMDK4412 SMDK4412 3765 ++iproc MACH_IPROC IPROC 4735 +diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c +index e84faff..2233be7 100644 +--- a/arch/avr32/kernel/cpu.c ++++ b/arch/avr32/kernel/cpu.c +@@ -6,7 +6,7 @@ + * published by the Free Software Foundation. + */ + #include +-#include ++#include + #include + #include + #include +@@ -26,16 +26,16 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices); + * XXX: If/when a SMP-capable implementation of AVR32 will ever be + * made, we must make sure that the code executes on the correct CPU. + */ +-static ssize_t show_pc0event(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t show_pc0event(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + unsigned long pccr; + + pccr = sysreg_read(PCCR); + return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f); + } +-static ssize_t store_pc0event(struct sys_device *dev, +- struct sysdev_attribute *attr, const char *buf, ++static ssize_t store_pc0event(struct device *dev, ++ struct device_attribute *attr, const char *buf, + size_t count) + { + unsigned long val; +@@ -48,16 +48,16 @@ static ssize_t store_pc0event(struct sys_device *dev, + sysreg_write(PCCR, val); + return count; + } +-static ssize_t show_pc0count(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t show_pc0count(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + unsigned long pcnt0; + + pcnt0 = sysreg_read(PCNT0); + return sprintf(buf, "%lu\n", pcnt0); + } +-static ssize_t store_pc0count(struct sys_device *dev, +- struct sysdev_attribute *attr, ++static ssize_t store_pc0count(struct device *dev, ++ struct device_attribute *attr, + const char *buf, size_t count) + { + unsigned long val; +@@ -71,16 +71,16 @@ static ssize_t store_pc0count(struct sys_device *dev, + return count; + } + +-static ssize_t show_pc1event(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t show_pc1event(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + unsigned long pccr; + + pccr = sysreg_read(PCCR); + return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f); + } +-static ssize_t store_pc1event(struct sys_device *dev, +- struct sysdev_attribute *attr, const char *buf, ++static ssize_t store_pc1event(struct device *dev, ++ struct device_attribute *attr, const char *buf, + size_t count) + { + unsigned long val; +@@ -93,16 +93,16 @@ static ssize_t store_pc1event(struct sys_device *dev, + sysreg_write(PCCR, val); + return count; + } +-static ssize_t show_pc1count(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t show_pc1count(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + unsigned long pcnt1; + + pcnt1 = sysreg_read(PCNT1); + return sprintf(buf, "%lu\n", pcnt1); + } +-static ssize_t store_pc1count(struct sys_device *dev, +- struct sysdev_attribute *attr, const char *buf, ++static ssize_t store_pc1count(struct device *dev, ++ struct device_attribute *attr, const char *buf, + size_t count) + { + unsigned long val; +@@ -116,16 +116,16 @@ static ssize_t store_pc1count(struct sys_device *dev, + return count; + } + +-static ssize_t show_pccycles(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t show_pccycles(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + unsigned long pccnt; + + pccnt = sysreg_read(PCCNT); + return sprintf(buf, "%lu\n", pccnt); + } +-static ssize_t store_pccycles(struct sys_device *dev, +- struct sysdev_attribute *attr, const char *buf, ++static ssize_t store_pccycles(struct device *dev, ++ struct device_attribute *attr, const char *buf, + size_t count) + { + unsigned long val; +@@ -139,16 +139,16 @@ static ssize_t store_pccycles(struct sys_device *dev, + return count; + } + +-static ssize_t show_pcenable(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t show_pcenable(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + unsigned long pccr; + + pccr = sysreg_read(PCCR); + return sprintf(buf, "%c\n", (pccr & 1)?'1':'0'); + } +-static ssize_t store_pcenable(struct sys_device *dev, +- struct sysdev_attribute *attr, const char *buf, ++static ssize_t store_pcenable(struct device *dev, ++ struct device_attribute *attr, const char *buf, + size_t count) + { + unsigned long pccr, val; +@@ -167,12 +167,12 @@ static ssize_t store_pcenable(struct sys_device *dev, + return count; + } + +-static SYSDEV_ATTR(pc0event, 0600, show_pc0event, store_pc0event); +-static SYSDEV_ATTR(pc0count, 0600, show_pc0count, store_pc0count); +-static SYSDEV_ATTR(pc1event, 0600, show_pc1event, store_pc1event); +-static SYSDEV_ATTR(pc1count, 0600, show_pc1count, store_pc1count); +-static SYSDEV_ATTR(pccycles, 0600, show_pccycles, store_pccycles); +-static SYSDEV_ATTR(pcenable, 0600, show_pcenable, store_pcenable); ++static DEVICE_ATTR(pc0event, 0600, show_pc0event, store_pc0event); ++static DEVICE_ATTR(pc0count, 0600, show_pc0count, store_pc0count); ++static DEVICE_ATTR(pc1event, 0600, show_pc1event, store_pc1event); ++static DEVICE_ATTR(pc1count, 0600, show_pc1count, store_pc1count); ++static DEVICE_ATTR(pccycles, 0600, show_pccycles, store_pccycles); ++static DEVICE_ATTR(pcenable, 0600, show_pcenable, store_pcenable); + + #endif /* CONFIG_PERFORMANCE_COUNTERS */ + +@@ -186,12 +186,12 @@ static int __init topology_init(void) + register_cpu(c, cpu); + + #ifdef CONFIG_PERFORMANCE_COUNTERS +- sysdev_create_file(&c->sysdev, &attr_pc0event); +- sysdev_create_file(&c->sysdev, &attr_pc0count); +- sysdev_create_file(&c->sysdev, &attr_pc1event); +- sysdev_create_file(&c->sysdev, &attr_pc1count); +- sysdev_create_file(&c->sysdev, &attr_pccycles); +- sysdev_create_file(&c->sysdev, &attr_pcenable); ++ device_create_file(&c->dev, &dev_attr_pc0event); ++ device_create_file(&c->dev, &dev_attr_pc0count); ++ device_create_file(&c->dev, &dev_attr_pc1event); ++ device_create_file(&c->dev, &dev_attr_pc1count); ++ device_create_file(&c->dev, &dev_attr_pccycles); ++ device_create_file(&c->dev, &dev_attr_pcenable); + #endif + } + +diff --git a/arch/cris/arch-v32/drivers/iop_fw_load.c b/arch/cris/arch-v32/drivers/iop_fw_load.c +index 2f8ea0f..4b8e651 100644 +--- a/arch/cris/arch-v32/drivers/iop_fw_load.c ++++ b/arch/cris/arch-v32/drivers/iop_fw_load.c +@@ -74,12 +74,7 @@ int iop_fw_load_spu(const unsigned char *fw_name, unsigned int spu_inst) + fw_name, + &iop_spu_device[spu_inst]); + if (retval != 0) +- { +- printk(KERN_ERR +- "iop_load_spu: Failed to load firmware \"%s\"\n", +- fw_name); + return retval; +- } + data = (u32 *) fw_entry->data; + + /* acquire ownership of memory controller */ +@@ -137,12 +132,7 @@ int iop_fw_load_mpu(unsigned char *fw_name) + /* get firmware */ + retval = request_firmware(&fw_entry, fw_name, &iop_mpu_device); + if (retval != 0) +- { +- printk(KERN_ERR +- "iop_load_spu: Failed to load firmware \"%s\"\n", +- fw_name); + return retval; +- } + data = (u32 *) fw_entry->data; + + /* disable MPU */ +diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig +index bad27a6..70554ba 100644 +--- a/arch/frv/Kconfig ++++ b/arch/frv/Kconfig +@@ -8,6 +8,7 @@ config FRV + select HAVE_GENERIC_HARDIRQS + select GENERIC_IRQ_SHOW + select ARCH_HAVE_NMI_SAFE_CMPXCHG ++ select GENERIC_CPU_DEVICES + + config ZONE_DMA + bool +diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig +index d1f377f..56e890d 100644 +--- a/arch/h8300/Kconfig ++++ b/arch/h8300/Kconfig +@@ -4,6 +4,7 @@ config H8300 + select HAVE_IDE + select HAVE_GENERIC_HARDIRQS + select GENERIC_IRQ_SHOW ++ select GENERIC_CPU_DEVICES + + config SYMBOL_PREFIX + string +diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile +index be7bfa1..053b1f8 100644 +--- a/arch/ia64/Makefile ++++ b/arch/ia64/Makefile +@@ -30,16 +30,7 @@ cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \ + -falign-functions=32 -frename-registers -fno-optimize-sibling-calls + KBUILD_CFLAGS_KERNEL := -mconstant-gp + +-GAS_STATUS = $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)") +-KBUILD_CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)") +- +-ifeq ($(GAS_STATUS),buggy) +-$(error Sorry, you need a newer version of the assember, one that is built from \ +- a source-tree that post-dates 18-Dec-2002. You can find a pre-compiled \ +- static binary of such an assembler at: \ +- \ +- ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz) +-endif ++KBUILD_CPPFLAGS += -DHAVE_WORKING_TEXT_ALIGN -DHAVE_MODEL_SMALL_ATTRIBUTE -DHAVE_SERIALIZE_DIRECTIVE + + KBUILD_CFLAGS += $(cflags-y) + head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o +@@ -68,7 +59,7 @@ boot := arch/ia64/hp/sim/boot + + PHONY += boot compressed check + +-all: compressed unwcheck ++all: compressed + + compressed: vmlinux.gz + +@@ -77,9 +68,6 @@ vmlinuz: vmlinux.gz + vmlinux.gz: vmlinux + $(Q)$(MAKE) $(build)=$(boot) $@ + +-unwcheck: vmlinux +- -$(Q)READELF=$(READELF) python $(srctree)/arch/ia64/scripts/unwcheck.py $< +- + archclean: + $(Q)$(MAKE) $(clean)=$(boot) + +@@ -95,7 +83,6 @@ define archhelp + echo '* compressed - Build compressed kernel image' + echo ' install - Install compressed kernel image' + echo ' boot - Build vmlinux and bootloader for Ski simulator' +- echo '* unwcheck - Check vmlinux for invalid unwind info' + endef + + archprepare: make_nr_irqs_h FORCE +diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c +index c539c68..2d67317 100644 +--- a/arch/ia64/kernel/err_inject.c ++++ b/arch/ia64/kernel/err_inject.c +@@ -24,7 +24,7 @@ + * Copyright (C) 2006, Intel Corp. All rights reserved. + * + */ +-#include ++#include + #include + #include + #include +@@ -35,10 +35,10 @@ + #define ERR_DATA_BUFFER_SIZE 3 // Three 8-byte; + + #define define_one_ro(name) \ +-static SYSDEV_ATTR(name, 0444, show_##name, NULL) ++static DEVICE_ATTR(name, 0444, show_##name, NULL) + + #define define_one_rw(name) \ +-static SYSDEV_ATTR(name, 0644, show_##name, store_##name) ++static DEVICE_ATTR(name, 0644, show_##name, store_##name) + + static u64 call_start[NR_CPUS]; + static u64 phys_addr[NR_CPUS]; +@@ -55,7 +55,7 @@ static u64 resources[NR_CPUS]; + + #define show(name) \ + static ssize_t \ +-show_##name(struct sys_device *dev, struct sysdev_attribute *attr, \ ++show_##name(struct device *dev, struct device_attribute *attr, \ + char *buf) \ + { \ + u32 cpu=dev->id; \ +@@ -64,7 +64,7 @@ show_##name(struct sys_device *dev, struct sysdev_attribute *attr, \ + + #define store(name) \ + static ssize_t \ +-store_##name(struct sys_device *dev, struct sysdev_attribute *attr, \ ++store_##name(struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t size) \ + { \ + unsigned int cpu=dev->id; \ +@@ -78,7 +78,7 @@ show(call_start) + * processor. The cpu number in driver is only used for storing data. + */ + static ssize_t +-store_call_start(struct sys_device *dev, struct sysdev_attribute *attr, ++store_call_start(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) + { + unsigned int cpu=dev->id; +@@ -127,7 +127,7 @@ show(err_type_info) + store(err_type_info) + + static ssize_t +-show_virtual_to_phys(struct sys_device *dev, struct sysdev_attribute *attr, ++show_virtual_to_phys(struct device *dev, struct device_attribute *attr, + char *buf) + { + unsigned int cpu=dev->id; +@@ -135,7 +135,7 @@ show_virtual_to_phys(struct sys_device *dev, struct sysdev_attribute *attr, + } + + static ssize_t +-store_virtual_to_phys(struct sys_device *dev, struct sysdev_attribute *attr, ++store_virtual_to_phys(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) + { + unsigned int cpu=dev->id; +@@ -159,8 +159,8 @@ show(err_struct_info) + store(err_struct_info) + + static ssize_t +-show_err_data_buffer(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++show_err_data_buffer(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + unsigned int cpu=dev->id; + +@@ -171,8 +171,8 @@ show_err_data_buffer(struct sys_device *dev, + } + + static ssize_t +-store_err_data_buffer(struct sys_device *dev, +- struct sysdev_attribute *attr, ++store_err_data_buffer(struct device *dev, ++ struct device_attribute *attr, + const char *buf, size_t size) + { + unsigned int cpu=dev->id; +@@ -209,14 +209,14 @@ define_one_ro(capabilities); + define_one_ro(resources); + + static struct attribute *default_attrs[] = { +- &attr_call_start.attr, +- &attr_virtual_to_phys.attr, +- &attr_err_type_info.attr, +- &attr_err_struct_info.attr, +- &attr_err_data_buffer.attr, +- &attr_status.attr, +- &attr_capabilities.attr, +- &attr_resources.attr, ++ &dev_attr_call_start.attr, ++ &dev_attr_virtual_to_phys.attr, ++ &dev_attr_err_type_info.attr, ++ &dev_attr_err_struct_info.attr, ++ &dev_attr_err_data_buffer.attr, ++ &dev_attr_status.attr, ++ &dev_attr_capabilities.attr, ++ &dev_attr_resources.attr, + NULL + }; + +@@ -225,12 +225,12 @@ static struct attribute_group err_inject_attr_group = { + .name = "err_inject" + }; + /* Add/Remove err_inject interface for CPU device */ +-static int __cpuinit err_inject_add_dev(struct sys_device * sys_dev) ++static int __cpuinit err_inject_add_dev(struct device * sys_dev) + { + return sysfs_create_group(&sys_dev->kobj, &err_inject_attr_group); + } + +-static int __cpuinit err_inject_remove_dev(struct sys_device * sys_dev) ++static int __cpuinit err_inject_remove_dev(struct device * sys_dev) + { + sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group); + return 0; +@@ -239,9 +239,9 @@ static int __cpuinit err_inject_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) + { + unsigned int cpu = (unsigned long)hcpu; +- struct sys_device *sys_dev; ++ struct device *sys_dev; + +- sys_dev = get_cpu_sysdev(cpu); ++ sys_dev = get_cpu_device(cpu); + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: +@@ -283,13 +283,13 @@ static void __exit + err_inject_exit(void) + { + int i; +- struct sys_device *sys_dev; ++ struct device *sys_dev; + + #ifdef ERR_INJ_DEBUG + printk(KERN_INFO "Exit error injection driver.\n"); + #endif + for_each_online_cpu(i) { +- sys_dev = get_cpu_sysdev(i); ++ sys_dev = get_cpu_device(i); + sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group); + } + unregister_hotcpu_notifier(&err_inject_cpu_notifier); +diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c +index 6d33c5c..98f86317 100644 +--- a/arch/ia64/kernel/process.c ++++ b/arch/ia64/kernel/process.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -111,9 +112,9 @@ show_regs (struct pt_regs *regs) + print_modules(); + printk("\nPid: %d, CPU %d, comm: %20s\n", task_pid_nr(current), + smp_processor_id(), current->comm); +- printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s (%s)\n", ++ printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s (%s%s)\n", + regs->cr_ipsr, regs->cr_ifs, ip, print_tainted(), +- init_utsname()->release); ++ init_utsname()->release, LINUX_PACKAGE_ID); + print_symbol("ip is at %s\n", ip); + printk("unat: %016lx pfs : %016lx rsc : %016lx\n", + regs->ar_unat, regs->ar_pfs, regs->ar_rsc); +diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c +index 9be1f11..9deb21d 100644 +--- a/arch/ia64/kernel/topology.c ++++ b/arch/ia64/kernel/topology.c +@@ -350,7 +350,7 @@ static int __cpuinit cpu_cache_sysfs_init(unsigned int cpu) + } + + /* Add cache interface for CPU device */ +-static int __cpuinit cache_add_dev(struct sys_device * sys_dev) ++static int __cpuinit cache_add_dev(struct device * sys_dev) + { + unsigned int cpu = sys_dev->id; + unsigned long i, j; +@@ -400,7 +400,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) + } + + /* Remove cache interface for CPU device */ +-static int __cpuinit cache_remove_dev(struct sys_device * sys_dev) ++static int __cpuinit cache_remove_dev(struct device * sys_dev) + { + unsigned int cpu = sys_dev->id; + unsigned long i; +@@ -428,9 +428,9 @@ static int __cpuinit cache_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) + { + unsigned int cpu = (unsigned long)hcpu; +- struct sys_device *sys_dev; ++ struct device *sys_dev; + +- sys_dev = get_cpu_sysdev(cpu); ++ sys_dev = get_cpu_device(cpu); + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: +@@ -454,7 +454,7 @@ static int __init cache_sysfs_init(void) + int i; + + for_each_online_cpu(i) { +- struct sys_device *sys_dev = get_cpu_sysdev((unsigned int)i); ++ struct device *sys_dev = get_cpu_device((unsigned int)i); + cache_add_dev(sys_dev); + } + +diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig +index 361d540..3e29c89 100644 +--- a/arch/m68k/Kconfig ++++ b/arch/m68k/Kconfig +@@ -7,6 +7,7 @@ config M68K + select HAVE_GENERIC_HARDIRQS + select GENERIC_IRQ_SHOW + select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS ++ select GENERIC_CPU_DEVICES + + config RWSEM_GENERIC_SPINLOCK + bool +diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig +index a93ed04..7329632 100644 +--- a/arch/microblaze/Kconfig ++++ b/arch/microblaze/Kconfig +@@ -17,6 +17,7 @@ config MICROBLAZE + select HAVE_GENERIC_HARDIRQS + select GENERIC_IRQ_PROBE + select GENERIC_IRQ_SHOW ++ select GENERIC_CPU_DEVICES + + config SWAP + def_bool n +diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild +index 7dd65cf..0d37730 100644 +--- a/arch/mips/Kbuild ++++ b/arch/mips/Kbuild +@@ -1,8 +1,3 @@ +-# Fail on warnings - also for files referenced in subdirs +-# -Werror can be disabled for specific files using: +-# CFLAGS_ := -Wno-error +-subdir-ccflags-y := -Werror +- + # platform specific definitions + include arch/mips/Kbuild.platforms + obj-y := $(platform-y) +diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig +index e518a5a..978e0bd 100644 +--- a/arch/openrisc/Kconfig ++++ b/arch/openrisc/Kconfig +@@ -15,6 +15,7 @@ config OPENRISC + select GENERIC_IRQ_PROBE + select GENERIC_IRQ_SHOW + select GENERIC_IOMAP ++ select GENERIC_CPU_DEVICES + + config MMU + def_bool y +diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig +index bec952d..f492c55 100644 +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -134,7 +134,7 @@ config PPC + select GENERIC_IRQ_SHOW_LEVEL + select HAVE_RCU_TABLE_FREE if SMP + select HAVE_SYSCALL_TRACEPOINTS +- select HAVE_BPF_JIT if (PPC64 && NET) ++ select HAVE_BPF_JIT if PPC64 + select HAVE_ARCH_JUMP_LABEL + select ARCH_HAVE_NMI_SAFE_CMPXCHG + select ARCH_SUPPORTS_ATOMIC_RMW +@@ -694,6 +694,42 @@ config FSL_GTM + help + Freescale General-purpose Timers support + ++config HAS_FSL_PAMU ++ bool ++ default n ++ ++config FSL_PAMU ++ bool "PAMU/IOMMU support" ++ depends on HAS_FSL_PAMU ++ help ++ Freescale PAMU/IOMMU support ++ ++config FSL_PAMU_ERRATUM_A_004510 ++ bool "Enable PAMU work-around for erratum A-004510" ++ depends on FSL_PAMU ++ # For now, enable this by default, so that we don't have to update ++ # defconfigs. All current PAMU-enabled SOCs have the erratum. ++ default y ++ help ++ Select this option to enable a work-around for erratum A-004510 ++ in the Freescale PAMU device driver. Erratum A-004510 says that ++ under certain load conditions, modified cache lines can be discarded, ++ causing data corruption. This option enables the PAMU portion of ++ the work-around. ++ ++config FSL_FMAN_CPC_STASH ++ bool "Enable stashing of FMAN write transactions for ethernet ports" ++ depends on FSL_PAMU ++ default n ++ help ++ Select this option to enable stashing of incoming ethernet frames ++ from FMAN ports into platform cache. ++ ++config HAS_FSL_QBMAN ++ bool "Datapath Acceleration Queue and Buffer management" ++ help ++ Datapath Acceleration Queue and Buffer management ++ + # Yes MCA RS/6000s exist but Linux-PPC does not currently support any + config MCA + bool +diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug +index 1b8a9c9..aba8704 100644 +--- a/arch/powerpc/Kconfig.debug ++++ b/arch/powerpc/Kconfig.debug +@@ -132,6 +132,15 @@ config BDI_SWITCH + Unless you are intending to debug the kernel with one of these + machines, say N here. + ++config JTAG_DEBUGGER ++ bool "Kernel modifications for JTAG debuggers" ++ depends on DEBUG_KERNEL && PPC32 ++ help ++ Modify kernel to allow JTAG debuggers to work. So far, this includes ++ setting the "DE" bit in booke ppc MSR_KERNEL and set the kernel's ++ softlockup threshold to be negative, effectively disabling software based ++ watchdogs. ++ + config BOOTX_TEXT + bool "Support for early boot text console (BootX or OpenFirmware only)" + depends on PPC_OF && PPC_BOOK3S +diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore +index 12da77e..652e35d 100644 +--- a/arch/powerpc/boot/.gitignore ++++ b/arch/powerpc/boot/.gitignore +@@ -21,6 +21,7 @@ uImage + cuImage.* + dtbImage.* + treeImage.* ++vmlinux.strip + zImage + zImage.initrd + zImage.bin.* +@@ -44,4 +45,4 @@ fdt_sw.c + fdt_wip.c + libfdt.h + libfdt_internal.h +- ++*.dtb +diff --git a/arch/powerpc/boot/dts/accton_5652.dts b/arch/powerpc/boot/dts/accton_5652.dts +new file mode 100644 +index 0000000..dbecbb8 +--- /dev/null ++++ b/arch/powerpc/boot/dts/accton_5652.dts +@@ -0,0 +1,1008 @@ ++/* ++ * Accton Technology ES5652BT1 Device Tree Source ++ * ++ * Copyright 2012, Cumulus Networks, 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. ++ * ++ * Note: On current rev of Accton box eth mgmt PHY does not work at 1Gb. ++ * See PHY property accton,broken_1000 and use in gianfar.c. ++ */ ++ ++/dts-v1/; ++ ++/ { ++ model = "accton,es5652bt1"; ++ compatible = "accton,5652"; ++ #address-cells = <0x2>; ++ #size-cells = <0x2>; ++ interrupt-parent = <&MPIC>; ++ aliases { ++ ethernet0 = &ENET0; ++ serial0 = &SERIAL0; ++ pci1 = &PCI1; ++ }; ++ cpus { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ PowerPC,P2020@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <0x1>; ++ }; ++ PowerPC,P2020@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <0x1>; ++ }; ++ }; ++ memory { ++ device_type = "memory"; ++ }; ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ localbus@ff705000 { ++ #address-cells = <0x2>; ++ #size-cells = <0x1>; ++ compatible = "fsl,p2020-elbc", "fsl,elbc", "simple-bus"; ++ reg = <0x0 0xff705000 0x0 0x00001000>; ++ interrupts = <19 0x2>; ++ ranges = <0x0 0x0 0x0 0xefc00000 0x00400000 ++ 0x1 0x0 0x0 0xea000000 0x00000100>; ++ flash@0,0 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x00400000>; ++ bank-width = <0x1>; ++ device-width = <0x1>; ++ partition@0 { ++ /* Entire flash minus (u-boot + info) */ ++ reg = <0x00000000 0x00360000>; ++ label = "onie"; ++ }; ++ partition@1 { ++ reg = <0x00360000 0x00010000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@2 { ++ reg = <0x00370000 0x00010000>; ++ label = "board_eeprom"; ++ }; ++ partition@3 { ++ reg = <0x00380000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ cpld@1,0 { ++ compatible = "accton,5652-cpld"; ++ reg = <0x1 0x0 0x0000100>; ++ }; ++ }; ++ ++ soc@ff700000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ device_type = "soc"; ++ compatible = "fsl,p2020-immr", "simple-bus"; ++ ranges = <0x0 0x0 0xff700000 0x100000>; ++ bus-frequency = <0x0>; ++ memory-controller@2000 { ++ compatible = "fsl,p2020-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <0x12 0x2>; ++ }; ++ I2C0: i2c@3000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ cell-index = <0x0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <0x2b 0x2>; ++ dfsrr; ++ clock-frequency = <400000>; ++ fsl,timeout = <10000>; ++ mux@70 { ++ compatible = "ti,pca9548"; ++ reg = <0x70>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ rtc@51 { ++ compatible = "epson,rtc8564"; ++ reg = <0x51>; ++ }; ++ ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* ++ ** The eeprom utilities look for a label that ++ ** ends with "_eeprom". ++ */ ++ psu_eeprom@3a { ++ compatible = "at,24c02"; ++ reg = <0x3a>; ++ /* This one contains valid data */ ++ label = "psu2_eeprom"; ++ read-only; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* ++ ** The eeprom utilities look for a label that ++ ** ends with "_eeprom". ++ */ ++ psu_eeprom@39 { ++ compatible = "at,24c02"; ++ reg = <0x39>; ++ /* This one contains valid data */ ++ label = "psu1_eeprom"; ++ read-only; ++ }; ++ }; ++ // No devices on bus 3 ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ // SMSC USB2513i - USB Hub. ++ // Handled by u-boot, leave blank here. ++ // addr 0x2C ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ // VT1165M Voltage monitor ++ // Leave blank here. ++ // addr 0x71 ++ }; ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ // ICS83905I PCIe clock buffer ++ // Leave blank here. ++ // addr 0x6E ++ }; ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ ++ hwmon@29 { ++ compatible = "winbond,w83782d"; ++ reg = <0x29>; ++ // write 0 to 0x5c and 0x45c ++ accton,es5652bt1,clksel = <1>; ++ }; ++ tmon@18 { ++ compatible = "nxp,max1617"; ++ reg = <0x18>; ++ }; ++ tmon@1a { ++ compatible = "nxp,max1617"; ++ reg = <0x1a>; ++ }; ++ tmon@4c { ++ compatible = "nxp,max1617"; ++ reg = <0x4c>; ++ }; ++ }; ++ }; ++ }; ++ I2C1: i2c@3100 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ cell-index = <0x1>; ++ compatible = "fsl-i2c"; ++ reg = <0x3100 0x100>; ++ interrupts = <0x2b 0x2>; ++ dfsrr; ++ mux@75 { ++ compatible = "ti,pca9546"; ++ reg = <0x75>; ++ deselect-on-exit; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ mux@74 { ++ compatible = "ti,pca9548"; ++ reg = <0x74>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port1"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port2"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port3"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port4"; ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port5"; ++ }; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port6"; ++ }; ++ }; ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port7"; ++ }; ++ }; ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port8"; ++ }; ++ }; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ mux@74 { ++ compatible = "ti,pca9548"; ++ reg = <0x74>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port9"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port10"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port11"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port12"; ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port13"; ++ }; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port14"; ++ }; ++ }; ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port15"; ++ }; ++ }; ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port16"; ++ }; ++ }; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ mux@74 { ++ compatible = "ti,pca9548"; ++ reg = <0x74>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port17"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port18"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port19"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port20"; ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port21"; ++ }; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port22"; ++ }; ++ }; ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port23"; ++ }; ++ }; ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port24"; ++ }; ++ }; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ mux@74 { ++ compatible = "ti,pca9548"; ++ reg = <0x74>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port25"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port26"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port27"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port28"; ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port29"; ++ }; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port30"; ++ }; ++ }; ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port31"; ++ }; ++ }; ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port32"; ++ }; ++ }; ++ }; ++ }; ++ }; ++ mux@76 { ++ // 4 channel mux ++ compatible = "ti,pca9546"; ++ reg = <0x76>; ++ deselect-on-exit; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ mux@74 { ++ compatible = "ti,pca9548"; ++ reg = <0x74>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port33"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port34"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port35"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port36"; ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port37"; ++ }; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port38"; ++ }; ++ }; ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port39"; ++ }; ++ }; ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port40"; ++ }; ++ }; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ mux@74 { ++ // 8 channel mux ++ compatible = "ti,pca9548"; ++ reg = <0x74>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port41"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port42"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port43"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port44"; ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port45"; ++ }; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port46"; ++ }; ++ }; ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port47"; ++ }; ++ }; ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port48"; ++ }; ++ }; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ gpio@20 { ++ // SFP+ RX/TX rate select 0..19 ++ compatible = "ti,pca9506"; ++ reg = <0x20>; ++ }; ++ gpio@21 { ++ // SFP+ RX/TX rate select 20..39 ++ compatible = "ti,pca9506"; ++ reg = <0x21>; ++ }; ++ gpio@70 { ++ // LPMODE QSFP+ 0..3 ++ compatible = "ti,pca9538"; ++ reg = <0x70>; ++ }; ++ gpio@71 { ++ // RESET QSFP+ 0..3, MDOESEL QSFP+ 0..3 ++ compatible = "ti,pca9538"; ++ reg = <0x71>; ++ }; ++ gpio@72 { ++ // SFP+ RX rate select 40..47 ++ compatible = "ti,pca9538"; ++ reg = <0x72>; ++ }; ++ gpio@73 { ++ // SFP+ TX rate select 40..47 ++ compatible = "ti,pca9538"; ++ reg = <0x73>; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ gpio@20 { ++ // SFP+ MOD_ABS 0..39 ++ compatible = "ti,pca9506"; ++ reg = <0x20>; ++ }; ++ gpio@22 { ++ // SFP+ OPRXLOSS 0..39 ++ compatible = "ti,pca9506"; ++ reg = <0x22>; ++ }; ++ gpio@71 { ++ // SFP+ MOD_ABS 40..47 ++ compatible = "ti,pca9538"; ++ reg = <0x71>; ++ }; ++ gpio@72 { ++ // QSFP+ PRSNT 0..3 ++ compatible = "ti,pca9538"; ++ reg = <0x72>; ++ }; ++ gpio@73 { ++ // SFP+ OPRXLOSS 40..47 ++ compatible = "ti,pca9538"; ++ reg = <0x73>; ++ }; ++ }; ++ }; ++ mux@77 { ++ // 4 channel mux ++ compatible = "ti,pca9546"; ++ reg = <0x77>; ++ deselect-on-exit; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port50"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port49"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port52"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port51"; ++ }; ++ }; ++ }; ++ }; ++ SERIAL0: serial@4500 { ++ cell-index = <0x0>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4500 0x100>; ++ clock-frequency = <0x0>; ++ interrupts = <0x2a 0x2>; ++ }; ++/* ++ SERIAL1: serial@4600 { ++ cell-index = <0x1>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4600 0x100>; ++ clock-frequency = <0x0>; ++ interrupts = <0x2a 0x2>; ++ }; ++*/ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,p2020-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <0x20>; ++ cache-size = <0x80000>; ++ interrupts = <0x10 0x2>; ++ }; ++ ++ USB: usb@22000 { ++ compatible = "fsl-usb2-dr"; ++ reg = <0x22000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <28 0x2>; ++ phy_type = "ulpi"; ++ dr_mode = "host"; ++ }; ++ ++ MDIO1: mdio@24520 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++ PHY1: ethernet-phy@1 { ++ reg = <0x1>; ++ device_type = "ethernet-phy"; ++ }; ++ }; ++ ++ ENET0: ethernet@24000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ cell-index = <0x1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x24000 0x1000>; ++ ranges = <0x0 0x24000 0x1000>; ++ interrupts = < ++ 0x1d 0x2 ++ 0x1e 0x2 ++ 0x22 0x2>; ++ phy-handle = <&PHY1>; ++ phy-connection-type = "rgmii"; ++ }; ++ MPIC: pic@40000 { ++ interrupt-controller; ++ #address-cells = <0x0>; ++ #interrupt-cells = <0x2>; ++ reg = <0x40000 0x40000>; ++ compatible = "chrp,open-pic"; ++ device_type = "open-pic"; ++ }; ++ global-utilities@e0000 { ++ compatible = "fsl,p2020-guts", "fsl,mpc8548-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ }; ++ ++ PCI1: pcie@ff70a000 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #interrupt-cells = <0x1>; ++ #size-cells = <0x2>; ++ #address-cells = <0x3>; ++ reg = <0x0 0xff70a000 0x0 0x1000>; ++ bus-range = <0x0 0xff>; ++ ranges = <0x2000000 0x0 0xa0000000 0x0 0xa0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0x0 0xffc20000 0x0 0x00010000>; ++ clock-frequency = <0x5f5e100>; ++ interrupts = <0x1a 0x2>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0x0 0x0 0x0 0x1 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x2 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x3 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x4 &MPIC 0x0 0x1>; ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <0x2>; ++ #address-cells = <0x3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0xa0000000 0x2000000 0x0 0xa0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0x1000000 0x0 0x00000000 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/accton_as4600_54t.dts b/arch/powerpc/boot/dts/accton_as4600_54t.dts +new file mode 100644 +index 0000000..2614fe9 +--- /dev/null ++++ b/arch/powerpc/boot/dts/accton_as4600_54t.dts +@@ -0,0 +1,343 @@ ++/* ++ * Accton Technology AS4600_54T Device Tree Source ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the 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/; ++ ++/ { ++ model = "accton,as4600_54t"; ++ compatible = "accton,as4600_54t"; ++ #address-cells = <0x2>; ++ #size-cells = <0x2>; ++ interrupt-parent = <&MPIC>; ++ aliases { ++ ethernet0 = &ENET1; ++ serial0 = &SERIAL0; ++ pci1 = &PCI1; ++ }; ++ cpus { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ PowerPC,P2020@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <0x1>; ++ }; ++ PowerPC,P2020@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <0x1>; ++ }; ++ }; ++ memory { ++ device_type = "memory"; ++ }; ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ localbus@ff705000 { ++ #address-cells = <0x2>; ++ #size-cells = <0x1>; ++ compatible = "fsl,p2020-elbc", "fsl,elbc", "simple-bus"; ++ reg = <0x0 0xff705000 0x0 0x00001000>; ++ interrupts = <19 0x2>; ++ ranges = <0x0 0x0 0x0 0xef800000 0x00800000 ++ 0x1 0x0 0x0 0xea000000 0x00000100>; ++ flash@0,0 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x00800000>; ++ bank-width = <0x1>; ++ device-width = <0x1>; ++ partition@0 { ++ /* Entire flash minus (u-boot + onie) */ ++ reg = <0x00000000 0x00360000>; ++ label = "open"; ++ }; ++ partition@1 { ++ /* 4MB onie */ ++ reg = <0x00360000 0x00400000>; ++ label = "onie"; ++ }; ++ partition@2 { ++ reg = <0x00760000 0x00010000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@3 { ++ reg = <0x00770000 0x00010000>; ++ label = "board_eeprom"; ++ }; ++ partition@4 { ++ reg = <0x00780000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ cpld@1,0 { ++ compatible = "accton,as4600_54t-cpld"; ++ reg = <0x1 0x0 0x0000100>; ++ }; ++ }; ++ ++ soc@ff700000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ device_type = "soc"; ++ compatible = "fsl,p2020-immr", "simple-bus"; ++ ranges = <0x0 0x0 0xff700000 0x100000>; ++ bus-frequency = <0x0>; ++ memory-controller@2000 { ++ compatible = "fsl,p2020-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <0x12 0x2>; ++ }; ++ I2C0: i2c@3000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ cell-index = <0x0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <0x2b 0x2>; ++ dfsrr; ++ clock-frequency = <400000>; ++ fsl,timeout = <10000>; ++ mux@70 { ++ compatible = "ti,pca9548"; ++ reg = <0x70>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ // SFP+ 0 ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port49"; ++ }; ++ }; ++ ++ // SFP+ 1 ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port50"; ++ }; ++ }; ++ ++ // SFP+ 2 ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port51"; ++ }; ++ }; ++ ++ // SFP+ 3 ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port52"; ++ }; ++ }; ++ ++ /* Nothing on 4 through 6 */ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ }; ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ }; ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ tmon@49 { ++ compatible = "ti,tmp75"; ++ reg = <0x49>; ++ }; ++ }; ++ }; ++ }; ++ I2C1: i2c@3100 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ cell-index = <0x1>; ++ compatible = "fsl-i2c"; ++ reg = <0x3100 0x100>; ++ interrupts = <0x2b 0x2>; ++ dfsrr; ++ // unknown@19 { ++ /* do not know what this is */ ++ // reg = <0x19>; ++ //}; ++ hwmon@2e { ++ compatible = "onsemi,adt7473"; ++ reg = <0x2e>; ++ }; ++ psu_eeprom@51 { ++ compatible = "at,24c02"; ++ reg = <0x51>; ++ label = "psu1_eeprom"; ++ read-only; ++ }; ++ psu_eeprom@52 { ++ compatible = "at,24c02"; ++ reg = <0x52>; ++ label = "psu2_eeprom"; ++ read-only; ++ }; ++ rtc@68 { ++ compatible = "maxim,ds1672"; ++ reg = <0x68>; ++ }; ++ }; ++ ++ SERIAL0: serial@4500 { ++ cell-index = <0x0>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4500 0x100>; ++ clock-frequency = <0x0>; ++ interrupts = <0x2a 0x2>; ++ }; ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,p2020-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <0x20>; ++ cache-size = <0x80000>; ++ interrupts = <0x10 0x2>; ++ }; ++ ++ USB: usb@22000 { ++ compatible = "fsl-usb2-dr"; ++ reg = <0x22000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <28 0x2>; ++ phy_type = "ulpi"; ++ dr_mode = "host"; ++ }; ++ ++ MDIO0: mdio@24520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++ PHY1: ethernet-phy@1 { ++ interrupt-parent = <&MPIC>; ++ interrupts = <3 1>; ++ reg = <0x1>; ++ device_type = "ethernet-phy"; ++ }; ++ }; ++ ++ ENET1: ethernet@25000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ cell-index = <0x1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x25000 0x1000>; ++ ranges = <0x0 0x25000 0x1000>; ++ interrupts = < ++ 0x23 0x2 ++ 0x24 0x2 ++ 0x28 0x2>; ++ interrupt-parent = <&MPIC>; ++ tbi-handle = <&TBI1>; ++ phy-handle = <&PHY1>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ MDIO1: mdio@25520 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ compatible = "fsl,gianfar-tbi"; ++ reg = <0x520 0x20>; ++ TBI1: tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ MPIC: pic@40000 { ++ interrupt-controller; ++ #address-cells = <0x0>; ++ #interrupt-cells = <0x2>; ++ reg = <0x40000 0x40000>; ++ compatible = "chrp,open-pic"; ++ device_type = "open-pic"; ++ }; ++ ++ global-utilities@e0000 { ++ compatible = "fsl,p2020-guts", "fsl,mpc8548-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ }; ++ ++ PCI1: pcie@ff70a000 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #interrupt-cells = <0x1>; ++ #size-cells = <0x2>; ++ #address-cells = <0x3>; ++ reg = <0x0 0xff70a000 0x0 0x1000>; ++ bus-range = <0x0 0xff>; ++ ranges = <0x2000000 0x0 0xa0000000 0x0 0xa0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0x0 0xffc20000 0x0 0x00010000>; ++ clock-frequency = <0x5f5e100>; ++ interrupts = <0x1a 0x2>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0x0 0x0 0x0 0x1 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x2 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x3 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x4 &MPIC 0x0 0x1>; ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <0x2>; ++ #address-cells = <0x3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0xa0000000 0x2000000 0x0 0xa0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0x1000000 0x0 0x00000000 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/accton_as5610_52x.dts b/arch/powerpc/boot/dts/accton_as5610_52x.dts +new file mode 100644 +index 0000000..4430afa +--- /dev/null ++++ b/arch/powerpc/boot/dts/accton_as5610_52x.dts +@@ -0,0 +1,1210 @@ ++/* ++ * Accton Technology AS5610_52X Device Tree Source ++ * ++ * Copyright 2014, Cumulus Networks, 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. ++ * ++ * Note: On current rev of Accton box eth mgmt PHY does not work at 1Gb. ++ * See PHY property accton,broken_1000 and use in gianfar.c. ++ */ ++ ++/dts-v1/; ++ ++/ { ++ model = "accton,as5610_52x"; ++ compatible = "accton,as5610_52x"; ++ #address-cells = <0x2>; ++ #size-cells = <0x2>; ++ interrupt-parent = <&MPIC>; ++ ++ aliases { ++ ethernet0 = &ENET0; ++ serial0 = &SERIAL0; ++ pci1 = &PCI1; ++ }; ++ cpus { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ PowerPC,P2020@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <0x1>; ++ }; ++ PowerPC,P2020@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <0x1>; ++ }; ++ }; ++ memory { ++ device_type = "memory"; ++ }; ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ localbus@ff705000 { ++ #address-cells = <0x2>; ++ #size-cells = <0x1>; ++ compatible = "fsl,p2020-elbc", "fsl,elbc", "simple-bus"; ++ reg = <0x0 0xff705000 0x0 0x00001000>; ++ interrupts = <19 0x2>; ++ ranges = <0x0 0x0 0x0 0xefc00000 0x00400000 ++ 0x1 0x0 0x0 0xea000000 0x00000100>; ++ flash@0,0 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x00400000>; ++ bank-width = <0x1>; ++ device-width = <0x1>; ++ partition@0 { ++ /* Entire flash minus (u-boot info) */ ++ reg = <0x00000000 0x00360000>; ++ label = "onie"; ++ }; ++ partition@1 { ++ reg = <0x00360000 0x00010000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@2 { ++ reg = <0x00370000 0x00010000>; ++ label = "board_eeprom"; ++ }; ++ partition@3 { ++ reg = <0x00380000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ cpld@1,0 { ++ compatible = "accton,accton_as5610_52x-cpld"; ++ reg = <0x1 0x0 0x0000100>; ++ }; ++ }; ++ ++ soc@ff700000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ device_type = "soc"; ++ compatible = "fsl,p2020-immr", "simple-bus"; ++ ranges = <0x0 0x0 0xff700000 0x100000>; ++ bus-frequency = <0x0>; ++ memory-controller@2000 { ++ compatible = "fsl,p2020-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <0x12 0x2>; ++ }; ++ I2C0: i2c@3000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ cell-index = <0x0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <0x2b 0x2>; ++ dfsrr; ++ fsl,timeout = <10000>; ++ fsl,preserve-clocking; ++ ++ mux@70 { ++ compatible = "ti,pca9548"; ++ reg = <0x70>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ rtc@51 { ++ compatible = "epson,rtc8564"; ++ reg = <0x51>; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* Not sure what the two addr per PSU are for */ ++ /* ++ ** The eeprom utilities look for a label that ++ ** ends with "_eeprom". ++ */ ++ psu_eeprom@3a { ++ compatible = "at,24c02"; ++ reg = <0x3a>; ++ label = "psu1_eeprom"; ++ read-only; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Not sure what the two addr per PSU are for */ ++ /* ++ ** The eeprom utilities look for a label that ++ ** ends with "_eeprom". ++ */ ++ psu_eeprom@39 { ++ compatible = "at,24c02"; ++ reg = <0x39>; ++ label = "psu2_eeprom"; ++ read-only; ++ }; ++ }; ++ // No devices on bus 3 ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ }; ++ // No devices on bus 4 ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ // VT1165M Voltage monitor ++ // Leave blank here. ++ // addr 0x71 ++ }; ++ // No devices on bus 6 ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ }; ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ hwmon@4d { ++ compatible = "nxp,max6697"; ++ reg = <0x4d>; ++ }; ++ tmon@18 { ++ compatible = "nxp,max1617"; ++ reg = <0x18>; ++ }; ++ }; ++ }; ++ }; ++ I2C1: i2c@3100 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ cell-index = <0x1>; ++ compatible = "fsl-i2c"; ++ reg = <0x3100 0x100>; ++ interrupts = <0x2b 0x2>; ++ dfsrr; ++ fsl,preserve-clocking; ++ ++ mux@75 { ++ compatible = "ti,pca9546"; ++ reg = <0x75>; ++ deselect-on-exit; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ // SFP+ 0-7 and retimer RX EQ 0-3 ++ mux@74 { ++ compatible = "ti,pca9548"; ++ reg = <0x74>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port1"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_rx_eq_0"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port2"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_rx_eq_1"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port3"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_rx_eq_2"; ++ }; ++ }; ++ i2c@3 { ++ // SFP+ 3 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port4"; ++ }; ++ // RX EQ 3 ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_rx_eq_3"; ++ }; ++ }; ++ // SFP+ 4 ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port5"; ++ }; ++ }; ++ // SFP+ 5 ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port6"; ++ }; ++ }; ++ // SFP+ 6 ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port7"; ++ }; ++ }; ++ // SFP+ 7 ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port8"; ++ }; ++ }; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ // SFP+ 8-15 and retimer RX EQ 4-7 ++ mux@74 { ++ compatible = "ti,pca9548"; ++ reg = <0x74>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ // SFP+ 8 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port9"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_rx_eq_4"; ++ }; ++ }; ++ i2c@1 { ++ // SFP+ 9 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port10"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_rx_eq_5"; ++ }; ++ }; ++ i2c@2 { ++ // SFP+ 10 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port11"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_rx_eq_6"; ++ }; ++ }; ++ i2c@3 { ++ // SFP+ 11 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port12"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_rx_eq_7"; ++ }; ++ }; ++ // SFP+ 12 ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port13"; ++ }; ++ }; ++ // SFP+ 13 ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port14"; ++ }; ++ }; ++ // SFP+ 14 ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port15"; ++ }; ++ }; ++ // SFP+ 15 ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port16"; ++ }; ++ }; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ // SFP+ 16-23 and retimer RX EQ 8-11 ++ mux@74 { ++ compatible = "ti,pca9548"; ++ reg = <0x74>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ // SFP+ 16 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port17"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_rx_eq_8"; ++ }; ++ }; ++ i2c@1 { ++ // SFP+ 17 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port18"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_rx_eq_9"; ++ }; ++ }; ++ i2c@2 { ++ // SFP+ 18 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port19"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_rx_eq_10"; ++ }; ++ }; ++ i2c@3 { ++ // SFP+ 19 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port20"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_rx_eq_11"; ++ }; ++ }; ++ // SFP+ 20 ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port21"; ++ }; ++ }; ++ // SFP+ 21 ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port22"; ++ }; ++ }; ++ // SFP+ 22 ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port23"; ++ }; ++ }; ++ // SFP+ 23 ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port24"; ++ }; ++ }; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ // SFP+ 24-31 and retimer TX EQ 0-3 ++ mux@74 { ++ compatible = "ti,pca9548"; ++ reg = <0x74>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ // SFP+ 24 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port25"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_tx_eq_0"; ++ }; ++ }; ++ i2c@1 { ++ // SFP+ 25 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port26"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_tx_eq_1"; ++ }; ++ }; ++ i2c@2 { ++ // SFP+ 26 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port27"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_tx_eq_2"; ++ }; ++ }; ++ i2c@3 { ++ // SFP+ 27 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port28"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_tx_eq_3"; ++ }; ++ }; ++ // SFP+ 28 ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port29"; ++ }; ++ }; ++ // SFP+ 29 ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port30"; ++ }; ++ }; ++ // SFP+ 30 ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port31"; ++ }; ++ }; ++ // SFP+ 31 ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port32"; ++ }; ++ }; ++ }; ++ }; ++ }; ++ mux@76 { ++ // 4 channel mux ++ compatible = "ti,pca9546"; ++ reg = <0x76>; ++ deselect-on-exit; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ // SFP+ 32-39 and retimer TX EQ 4-7 ++ mux@74 { ++ compatible = "ti,pca9548"; ++ reg = <0x74>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ // SFP+ 32 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port33"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_tx_eq_4"; ++ }; ++ }; ++ i2c@1 { ++ // SFP+ 33 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port34"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_tx_eq_5"; ++ }; ++ }; ++ i2c@2 { ++ // SFP+ 34 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port35"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_tx_eq_6"; ++ }; ++ }; ++ i2c@3 { ++ // SFP+ 34 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port36"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_tx_eq_7"; ++ }; ++ }; ++ // SFP+ 36 ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port37"; ++ }; ++ }; ++ // SFP+ 37 ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port38"; ++ }; ++ }; ++ // SFP+ 38 ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port39"; ++ }; ++ }; ++ // SFP+ 39 ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port40"; ++ }; ++ }; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ // SFP+ 40-47, retimer TX EQ 8-11, retimer QSFP TX EQ 0-3 ++ mux@74 { ++ compatible = "ti,pca9548"; ++ reg = <0x74>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ // SFP+ 40 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port41"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_tx_eq_8"; ++ }; ++ }; ++ i2c@1 { ++ // SFP+ 41 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port42"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_tx_eq_9"; ++ }; ++ }; ++ i2c@2 { ++ // SFP+ 42 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port43"; ++ }; ++ // TX EQ 10 ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_tx_eq_10"; ++ }; ++ }; ++ i2c@3 { ++ // SFP+ 43 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port44"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "sfp_tx_eq_11"; ++ }; ++ }; ++ i2c@4 { ++ // SFP+ 44 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port45"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "qsfp_tx_eq_0"; ++ }; ++ ++ }; ++ i2c@5 { ++ // SFP+ 45 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port46"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "qsfp_tx_eq_1"; ++ }; ++ }; ++ i2c@6 { ++ // SFP+ 46 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port47"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "qsfp_tx_eq_2"; ++ }; ++ }; ++ i2c@7 { ++ // SFP+ 47 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port48"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "qsfp_tx_eq_3"; ++ }; ++ }; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ gpio@20 { ++ // SFP+ RX/TX rate select 0..19 ++ compatible = "ti,pca9506"; ++ reg = <0x20>; ++ }; ++ gpio@21 { ++ // SFP+ RX/TX rate select 20..39 ++ compatible = "ti,pca9506"; ++ reg = <0x21>; ++ }; ++ gpio@70 { ++ // LPMODE QSFP+ 0..3 ++ compatible = "ti,pca9538"; ++ reg = <0x70>; ++ }; ++ gpio@71 { ++ // RESET QSFP+ 0..3, MDOESEL QSFP+ 0..3 ++ compatible = "ti,pca9538"; ++ reg = <0x71>; ++ }; ++ gpio@72 { ++ // SFP+ RX rate select 40..47 ++ compatible = "ti,pca9538"; ++ reg = <0x72>; ++ }; ++ gpio@73 { ++ // SFP+ TX rate select 40..47 ++ compatible = "ti,pca9538"; ++ reg = <0x73>; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ gpio@20 { ++ // SFP+ MOD_ABS 0..39 ++ compatible = "ti,pca9506"; ++ reg = <0x20>; ++ }; ++ // Running out of GPIOs (max 256) so ++ // disabling these gpios as we are not ++ // using them. ++/* ++ gpio@21 { ++ // SFP+ OPTXFLT 0..39 ++ compatible = "ti,pca9506"; ++ reg = <0x21>; ++ }; ++ gpio@22 { ++ // SFP+ OPRXLOSS 0..39 ++ compatible = "ti,pca9506"; ++ reg = <0x22>; ++ }; ++*/ ++ gpio@23 { ++ // SFP+ OPRXLOSS 40..47, ++ // SFP+ MOD_ABS 40..47, ++ // QSFP+ PRSNT 0..3 ++ // SFP+ OPTXFLT 40..47 ++ // SFP+ OPTXENB 40..47 ++ compatible = "ti,pca9506"; ++ reg = <0x23>; ++ }; ++ gpio@24 { ++ // SFP+ OPTXENB 0..39 ++ compatible = "ti,pca9506"; ++ reg = <0x24>; ++ }; ++ }; ++ }; ++ mux@77 { ++ // 4 channel mux ++ compatible = "ti,pca9546"; ++ reg = <0x77>; ++ deselect-on-exit; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ // QSFP+ 0 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port49"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "qsfp_rx_eq_0"; ++ }; ++ }; ++ i2c@1 { ++ // QSFP+ 1 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port50"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "qsfp_rx_eq_1"; ++ }; ++ }; ++ i2c@2 { ++ // QSFP+ 2 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port51"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "qsfp_rx_eq_2"; ++ }; ++ }; ++ i2c@3 { ++ // QSFP+ 3 ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port52"; ++ }; ++ retimer@27 { ++ compatible = "ti,ds100df410"; ++ reg = <0x27>; ++ label = "qsfp_rx_eq_3"; ++ }; ++ }; ++ }; ++ }; ++ SERIAL0: serial@4500 { ++ cell-index = <0x0>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4500 0x100>; ++ clock-frequency = <0x0>; ++ interrupts = <0x2a 0x2>; ++ }; ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,p2020-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <0x20>; ++ cache-size = <0x80000>; ++ interrupts = <0x10 0x2>; ++ }; ++ USB: usb@22000 { ++ compatible = "fsl-usb2-dr"; ++ reg = <0x22000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <28 0x2>; ++ phy_type = "ulpi"; ++ dr_mode = "host"; ++ }; ++ MDIO1: mdio@24520 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++ PHY1: ethernet-phy@1 { ++ reg = <0x1>; ++ device_type = "ethernet-phy"; ++ }; ++ }; ++ ENET0: ethernet@24000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ cell-index = <0x1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x24000 0x1000>; ++ ranges = <0x0 0x24000 0x1000>; ++ interrupts = < ++ 0x1d 0x2 ++ 0x1e 0x2 ++ 0x22 0x2>; ++ phy-handle = <&PHY1>; ++ phy-connection-type = "rgmii"; ++ }; ++ MPIC: pic@40000 { ++ interrupt-controller; ++ #address-cells = <0x0>; ++ #interrupt-cells = <0x2>; ++ reg = <0x40000 0x40000>; ++ compatible = "chrp,open-pic"; ++ device_type = "open-pic"; ++ }; ++ global-utilities@e0000 { ++ compatible = "fsl,p2020-guts", "fsl,mpc8548-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ ++ }; ++ ++ PCI1: pcie@ff70a000 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #interrupt-cells = <0x1>; ++ #size-cells = <0x2>; ++ #address-cells = <0x3>; ++ reg = <0x0 0xff70a000 0x0 0x1000>; ++ bus-range = <0x0 0xff>; ++ ranges = <0x2000000 0x0 0xa0000000 0x0 0xa0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0x0 0xffc20000 0x0 0x00010000>; ++ clock-frequency = <0x5f5e100>; ++ interrupts = <0x1a 0x2>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0x0 0x0 0x0 0x1 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x2 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x3 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x4 &MPIC 0x0 0x1>; ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <0x2>; ++ #address-cells = <0x3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0xa0000000 0x2000000 0x0 0xa0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0x1000000 0x0 0x00000000 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/accton_as6700_32x.dts b/arch/powerpc/boot/dts/accton_as6700_32x.dts +new file mode 100644 +index 0000000..cab8483 +--- /dev/null ++++ b/arch/powerpc/boot/dts/accton_as6700_32x.dts +@@ -0,0 +1,349 @@ ++/* ++ * Accton AS6700_32X Device Tree Source ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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/ "fsl/p2041si-pre.dtsi" ++ ++/ { ++ model = "accton,as6700_32x"; ++ compatible = "accton,as6700_32x"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ ethernet0 = &enet3; ++ ethernet1 = &enet0; ++ phy_sgmii_2 = &phy_sgmii_2; ++ phy_sgmii_1 = &phy_sgmii_1; ++ ++ }; ++ ++ memory { ++ device_type = "memory"; ++ }; ++ ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ ++ dcsr: dcsr@f00000000 { ++ ranges = <0x00000000 0xf 0x00000000 0x01008000>; ++ }; ++ ++ bportals: bman-portals@ff4000000 { ++ ranges = <0x0 0xf 0xf4000000 0x200000>; ++ }; ++ ++ qportals: qman-portals@ff4200000 { ++ ranges = <0x0 0xf 0xf4200000 0x200000>; ++ }; ++ ++ soc: soc@ffe000000 { ++ ranges = <0x00000000 0xf 0xfe000000 0x1000000>; ++ reg = <0xf 0xfe000000 0 0x00001000>; ++ ++ spi@110000 { ++ flash@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "micron,n25q512"; ++ reg = <0>; ++ spi-max-frequency = <12000000>; /* input clock */ ++ partition@uboot { ++ label = "uboot"; ++ reg = <0x00000000 0x00100000>; ++ }; ++ partition@uboot-env { ++ label = "uboot-env"; ++ reg = <0x00100000 0x00010000>; ++ env_size = <0x2000>; ++ }; ++ partition@Fman-FW { ++ label = "Fman-FW"; ++ reg = <0x00110000 0x00010000>; ++ read-only; ++ }; ++ partition@board_eeprom { ++ label = "board_eeprom"; ++ reg = <0x00120000 0x00010000>; ++ }; ++ partition@onie { ++ label = "onie"; ++ reg = <0x00130000 0x00800000>; ++ }; ++ partition@diag { ++ label = "diag"; ++ reg = <0x00930000 0x02000000>; ++ }; ++ partition@reserved { ++ label = "reserved"; ++ reg = <0x02930000 0x016d0000>; ++ }; ++ }; ++ }; ++ ++ i2c@118000 { ++ fsl,preserve-clocking; ++ ++ rtc@68 { ++ compatible = "maxim,ds1672"; ++ reg = <0x68>; ++ }; ++ spd@50 { ++ compatible = "at24,spd"; ++ reg = <0x50>; ++ }; ++ }; ++ ++ i2c@118100 { ++ fsl,preserve-clocking; ++ ++ /include/ "accton_as670x_baseboard_i2c.dtsi" ++ }; ++ ++ i2c@119100 { ++ fsl,preserve-clocking; ++ ++ mux@70 { ++ compatible = "ti,pca9546"; ++ reg = <0x70>; ++ deselect-on-exit; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ temp@4d { ++ compatible = "maxim,max6581"; ++ reg = <0x4d>; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ power@34 { ++ compatible = "ti,ucd9090"; ++ reg = <0x34>; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Not sure what the two addr per PSU are for */ ++ /* ++ ** The eeprom utilities look for a label that ++ ** ends with "_eeprom". ++ */ ++ psu_eeprom@39 { ++ compatible = "at,24c02"; ++ reg = <0x39>; ++ /* Haven't seen this one work yet */ ++ label = "psu1_eeprom"; ++ read-only; ++ }; ++ psu_unknown@3d { ++ compatible = "at,24c02"; ++ reg = <0x3d>; ++ /* Haven't seen this one work yet */ ++ // label = "psu1_eeprom2"; ++ read-only; ++ }; ++ psu_eeprom@3a { ++ compatible = "at,24c02"; ++ reg = <0x3a>; ++ /* This one contains valid data */ ++ label = "psu2_eeprom"; ++ read-only; ++ }; ++ psu_unknown@3e { ++ compatible = "at,24c02"; ++ reg = <0x3e>; ++ /* This one is unformatted */ ++ // label = "psu2_eeprom2"; ++ read-only; ++ }; ++ }; ++ }; ++ }; ++ ++ usb1: usb@211000 { ++ dr_mode = "host"; ++ }; ++ ++ fman0: fman@400000 { ++ enet0: ethernet@e0000 { ++ tbi-handle = <&tbi0>; ++ phy-handle = <&phy_sgmii_2>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ mdio0: mdio@e1120 { ++ tbi0: tbi-phy@8 { ++ reg = <0x8>; ++ device_type = "tbi-phy"; ++ }; ++ ++ phy_sgmii_2: ethernet-phy@2 { ++ reg = <0x2>; ++ }; ++ ++ phy_sgmii_1: ethernet-phy@1 { ++ reg = <0x1>; ++ }; ++ }; ++ ++ ethernet@e4000 { ++ status = "disabled"; ++ }; ++ ++ enet3: ethernet@e6000 { ++ tbi-handle = <&tbi3>; ++ phy-handle = <&phy_sgmii_1>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ mdio@e7120 { ++ tbi3: tbi-phy@8 { ++ reg = <8>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ }; ++ }; ++ ++ rio: rapidio@ffe0c0000 { ++ reg = <0xf 0xfe0c0000 0 0x11000>; ++ ++ port1 { ++ ranges = <0 0 0xc 0x20000000 0 0x10000000>; ++ }; ++ port2 { ++ ranges = <0 0 0xc 0x30000000 0 0x10000000>; ++ }; ++ }; ++ ++ ++ lbc: localbus@ffe124000 { ++ reg = <0xf 0xfe124000 0 0x1000>; ++ ranges = <0 0 0xf 0xec000000 0x04000000>; ++ }; ++ ++ pci0: pcie@ffe200000 { ++ reg = <0xf 0xfe200000 0 0x1000>; ++ ranges = <0x02000000 0x0 0xe0000000 ++ 0x0 0xd0000000 ++ 0x0 0x08000000 ++ ++ 0x01000000 0x0 0x00000000 ++ 0x0 0xf8000000 ++ 0x0 0x00010000>; ++ pcie@0 { ++ ranges = <0x02000000 0 0xe0000000 ++ 0x02000000 0 0xe0000000 ++ 0 0x08000000 ++ ++ 0x01000000 0 0x00000000 ++ 0x01000000 0 0x00000000 ++ 0 0x00010000>; ++ }; ++ }; ++ ++ pci1: pcie@ffe201000 { ++ reg = <0xf 0xfe201000 0 0x1000>; ++ ranges = <0x02000000 0x0 0xe0000000 ++ 0x0 0xd8000000 ++ 0x0 0x08000000 ++ ++ 0x01000000 0x0 0x00000000 ++ 0x0 0xf8010000 ++ 0x0 0x00010000>; ++ pcie@0 { ++ ranges = <0x02000000 0 0xe0000000 ++ 0x02000000 0 0xe0000000 ++ 0 0x08000000 ++ ++ 0x01000000 0 0x00000000 ++ 0x01000000 0 0x00000000 ++ 0 0x00010000>; ++ }; ++ }; ++ ++ pci2: pcie@ffe202000 { ++ reg = <0xf 0xfe202000 0 0x1000>; ++ ranges = <0x02000000 0x0 0xe0000000 ++ 0x0 0xe0000000 ++ 0x0 0x08000000 ++ ++ 0x01000000 0x0 0x00000000 ++ 0x0 0xf8020000 ++ 0x0 0x00010000>; ++ ++ pcie@0 { ++ ranges = <0x02000000 0 0xe0000000 ++ 0x02000000 0 0xe0000000 ++ 0 0x08000000 ++ ++ 0x01000000 0 0x00000000 ++ 0x01000000 0 0x00000000 ++ 0 0x00010000>; ++ }; ++ }; ++ ++ fsl,dpaa { ++ compatible = "fsl,p2041-dpaa", "fsl,dpaa"; ++ ++ ethernet@0 { ++ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&enet3>; ++ }; ++ ++ ethernet@1 { ++ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&enet0>; ++ }; ++ }; ++}; ++ ++/include/ "fsl/p2041si-post.dtsi" ++/include/ "fsl/qoriq-dpaa-res1.dtsi" +diff --git a/arch/powerpc/boot/dts/accton_as6701_32x.dts b/arch/powerpc/boot/dts/accton_as6701_32x.dts +new file mode 100644 +index 0000000..2d21e97 +--- /dev/null ++++ b/arch/powerpc/boot/dts/accton_as6701_32x.dts +@@ -0,0 +1,237 @@ ++/* ++ * Accton Technology AS6701_32X Device Tree Source ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the 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/ "p2020si.dtsi" ++ ++/ { ++ model = "accton,as6701_32x"; ++ compatible = "accton,as6701_32x"; ++ ++ aliases { ++ ethernet0 = &enet1; ++ serial0 = &serial0; ++ pci2 = &pci2; ++ }; ++ memory { ++ device_type = "memory"; ++ }; ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ localbus@ffe05000 { ++ ranges = <0x0 0x0 0x0 0xec000000 0x04000000>; ++ flash@0,0 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x04000000>; ++ bank-width = <0x2>; ++ device-width = <0x2>; ++ partition@0 { ++ reg = <0x00000000 0x00020000>; ++ label = "Reserved P0"; ++ }; ++ partition@1 { ++ reg = <0x00020000 0x00020000>; ++ label = "board_eeprom"; ++ }; ++ partition@2 { ++ reg = <0x00040000 0x00d00000>; ++ label = "onie"; ++ }; ++ partition@3 { ++ reg = <0x00d40000 0x02000000>; ++ label = "diag"; ++ }; ++ partition@4 { ++ reg = <0x02d40000 0x01200000>; ++ label = "open"; ++ }; ++ partition@5 { ++ reg = <0x03f40000 0x00020000>; ++ label = "Reserved P5"; ++ }; ++ partition@6 { ++ reg = <0x03f60000 0x00020000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@7 { ++ reg = <0x03f80000 0x00080000>; ++ label = "uboot"; ++ read-only; ++ }; ++ }; ++ }; ++ ++ soc@ffe00000 { ++ i2c@3000 { ++ fsl,preserve-clocking; ++ ++ mux@70 { ++ compatible = "ti,pca9548"; ++ reg = <0x70>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ rtc@51 { ++ compatible = "epson,rtc8564"; ++ reg = <0x51>; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ spd_eeprom@50 { ++ compatible = "at,24c02"; ++ reg = <0x50>; ++ read-only; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Not sure what the two addr per PSU are for */ ++ /* ++ ** The eeprom utilities look for a label that ++ ** ends with "_eeprom". ++ */ ++ psu_eeprom@39 { ++ compatible = "at,24c02"; ++ reg = <0x39>; ++ /* Haven't seen this one work yet */ ++ label = "psu1_eeprom"; ++ read-only; ++ }; ++ psu_unknown@3d { ++ compatible = "at,24c02"; ++ reg = <0x3d>; ++ /* Haven't seen this one work yet */ ++ // label = "psu1_eeprom2"; ++ read-only; ++ }; ++ psu_eeprom@3a { ++ compatible = "at,24c02"; ++ reg = <0x3a>; ++ /* This one contains valid data */ ++ label = "psu2_eeprom"; ++ read-only; ++ }; ++ psu_unknown@3e { ++ compatible = "at,24c02"; ++ reg = <0x3e>; ++ /* This one is unformatted */ ++ // label = "psu2_eeprom2"; ++ read-only; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ ++ temp@4d { ++ compatible = "maxim,max6581"; ++ reg = <0x4d>; ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ ++ // SMSC USB2513i - USB Hub. ++ // Handled by u-boot, leave blank here. ++ // addr 0x2C ++ }; ++ }; ++ }; ++ i2c@3100 { ++ fsl,preserve-clocking; ++ ++ /include/ "accton_as670x_baseboard_i2c.dtsi" ++ }; ++ serial1: serial@4600 { ++ status = "disabled"; ++ }; ++ ++ usb@22000 { ++ status = "disabled"; ++ phy_type = "ulpi"; ++ dr_mode = "host"; ++ }; ++ ++ mdio@24520 { ++ phy0: ethernet-phy@1 { ++ reg = <0x1>; ++ device_type = "ethernet-phy"; ++ }; ++ }; ++ ++ enet0: ethernet@24000 { ++ status = "disabled"; ++ }; ++ ++ enet1: ethernet@25000 { ++ phy-handle = <&phy0>; ++ tbi-handle = <&tbi0>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ mdio@25520 { ++ tbi0: tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ enet2: ethernet@26000 { ++ status = "disabled"; ++ }; ++ }; ++ ++ pci0: pcie@ffe08000 { ++ status = "disabled"; ++ }; ++ ++ pci1: pcie@ffe09000 { ++ status = "disabled"; ++ }; ++ ++ pci2: pcie@ffe0a000 { ++ ranges = <0x2000000 0x0 0x80000000 0x0 0x80000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0x0 0xffc00000 0x0 0x00010000>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0x0 0x0 0x0 0x1 &mpic 0x0 0x1 ++ 0x0 0x0 0x0 0x2 &mpic 0x1 0x1 ++ 0x0 0x0 0x0 0x3 &mpic 0x2 0x1 ++ 0x0 0x0 0x0 0x4 &mpic 0x3 0x1>; ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <0x2>; ++ #address-cells = <0x3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0x80000000 0x2000000 0x0 0x80000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0x1000000 0x0 0x00000000 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/accton_as670x_baseboard_i2c.dtsi b/arch/powerpc/boot/dts/accton_as670x_baseboard_i2c.dtsi +new file mode 100644 +index 0000000..739d3bd +--- /dev/null ++++ b/arch/powerpc/boot/dts/accton_as670x_baseboard_i2c.dtsi +@@ -0,0 +1,696 @@ ++/* ++ * Accton AS670X Baseboard I2C devices. ++ * ++ * Copyright 2014 Cumulus Networks, 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. ++ */ ++ ++fanpld@35 { ++ compatible = "accton,as670x_32x_fanpld"; ++ reg = <0x35>; ++}; ++ ++/* XXX - decode-syseeprom can't handle i2c nodes labeled "cpld" */ ++syspld@31 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "accton,as670x_32x_syspld"; ++ reg = <0x31>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port1"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port1_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port1_rx"; ++ }; ++ rx_retimer@19 { ++ compatible = "ti,ds100df410"; ++ reg = <0x19>; ++ label = "port21_rx"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port2"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port2_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port2_rx"; ++ }; ++ rx_retimer@19 { ++ compatible = "ti,ds100df410"; ++ reg = <0x19>; ++ label = "port22_rx"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port3"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port3_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port3_rx"; ++ }; ++ rx_retimer@19 { ++ compatible = "ti,ds100df410"; ++ reg = <0x19>; ++ label = "port23_rx"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port4"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port4_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port4_rx"; ++ }; ++ rx_retimer@19 { ++ compatible = "ti,ds100df410"; ++ reg = <0x19>; ++ label = "port24_rx"; ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port5"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port5_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port5_rx"; ++ }; ++ rx_retimer@19 { ++ compatible = "ti,ds100df410"; ++ reg = <0x19>; ++ label = "port25_rx"; ++ }; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port6"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port6_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port6_rx"; ++ }; ++ rx_retimer@19 { ++ compatible = "ti,ds100df410"; ++ reg = <0x19>; ++ label = "port26_rx"; ++ }; ++ }; ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port7"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port7_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port7_rx"; ++ }; ++ rx_retimer@19 { ++ compatible = "ti,ds100df410"; ++ reg = <0x19>; ++ label = "port27_rx"; ++ }; ++ }; ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port8"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port8_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port8_rx"; ++ }; ++ rx_retimer@19 { ++ compatible = "ti,ds100df410"; ++ reg = <0x19>; ++ label = "port28_rx"; ++ }; ++ }; ++ i2c@8 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <8>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port9"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port9_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port9_rx"; ++ }; ++ rx_retimer@19 { ++ compatible = "ti,ds100df410"; ++ reg = <0x19>; ++ label = "port29_rx"; ++ }; ++ }; ++ i2c@9 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <9>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port10"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port10_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port10_rx"; ++ }; ++ rx_retimer@19 { ++ compatible = "ti,ds100df410"; ++ reg = <0x19>; ++ label = "port30_rx"; ++ }; ++ }; ++ i2c@10 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <10>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port11"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port11_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port11_rx"; ++ }; ++ rx_retimer@19 { ++ compatible = "ti,ds100df410"; ++ reg = <0x19>; ++ label = "port31_rx"; ++ }; ++ }; ++ i2c@11 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <11>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port12"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port12_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port12_rx"; ++ }; ++ rx_retimer@19 { ++ compatible = "ti,ds100df410"; ++ reg = <0x19>; ++ label = "port32_rx"; ++ }; ++ }; ++ i2c@12 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <12>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port13"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port13_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port13_rx"; ++ }; ++ }; ++ i2c@13 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <13>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port14"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port14_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port14_rx"; ++ }; ++ }; ++ i2c@14 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <14>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port15"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port15_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port15_rx"; ++ }; ++ }; ++ i2c@15 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <15>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port16"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port16_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port16_rx"; ++ }; ++ }; ++ i2c@16 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <16>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port17"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port17_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port17_rx"; ++ }; ++ }; ++ i2c@17 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <17>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port18"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port18_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port18_rx"; ++ }; ++ }; ++ i2c@18 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <18>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port19"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port19_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port19_rx"; ++ }; ++ }; ++ i2c@19 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <19>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port20"; ++ }; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x1a>; ++ label = "port20_tx"; ++ }; ++ rx_retimer@18 { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port20_rx"; ++ }; ++ }; ++ i2c@20 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <20>; ++ gpio@20 { ++ // QSFP+ discrete signals ++ compatible = "ti,pca9506"; ++ reg = <0x20>; ++ }; ++ mux@70 { ++ compatible = "ti,pca9548"; ++ reg = <0x70>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port21_tx"; ++ }; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port21"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port22_tx"; ++ }; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port22"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port23_tx"; ++ }; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port23"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port24_tx"; ++ }; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port24"; ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port25_tx"; ++ }; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port25"; ++ }; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port26_tx"; ++ }; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port26"; ++ }; ++ }; ++ }; ++ }; ++ i2c@21 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <21>; ++ gpio@20 { ++ // QSFP+ discrete signals ++ compatible = "ti,pca9506"; ++ reg = <0x20>; ++ }; ++ mux@70 { ++ compatible = "ti,pca9548"; ++ reg = <0x70>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port27_tx"; ++ }; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port27"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port28_tx"; ++ }; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port28"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port29_tx"; ++ }; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port29"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port30_tx"; ++ }; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port30"; ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port31_tx"; ++ }; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port31"; ++ }; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ tx_retimer@1a { ++ compatible = "ti,ds100df410"; ++ reg = <0x18>; ++ label = "port32_tx"; ++ }; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port32"; ++ }; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/bcm98548xmc.dts b/arch/powerpc/boot/dts/bcm98548xmc.dts +new file mode 100644 +index 0000000..98b35a6 +--- /dev/null ++++ b/arch/powerpc/boot/dts/bcm98548xmc.dts +@@ -0,0 +1,338 @@ ++/* ++ * BCM98548XMC Device Tree Source ++ * ++ * Copyright 2008 Wind River System 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. ++ */ ++ ++/dts-v1/; ++ ++/ { ++ model = "bcm,bcm98548xmc"; ++ compatible = "bcm,BCM98548XMC"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ cpus { ++ #cpus = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,8548@0 { ++ device_type = "cpu"; ++ reg = <0>; ++ d-cache-line-size = <32>; // 32 bytes ++ i-cache-line-size = <32>; // 32 bytes ++ d-cache-size = <0x8000>; // L1, 32K ++ i-cache-size = <0x8000>; // L1, 32K ++ timebase-frequency = <0x2f90838>; ++ bus-frequency = <0x17c841c0>; ++ clock-frequency = <0x3b74a460>; ++ next-level-cache = <&L2>; ++ 32-bit; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <00000000 0x20000000>; // 512M at 0x0 ++ }; ++ ++ chosen { ++ name = "chosen"; ++ bootargs = "console=ttyS0,9600 "; ++ linux,initrd-start = <0>; ++ linux,initrd-end = <0>; ++ }; ++ soc8548@e0000000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #interrupt-cells = <2>; ++ device_type = "soc"; ++ ranges = <00000000 0xe0000000 0x00100000>; ++ reg = <0xe0000000 0x00100000>; // CCSRBAR ++ bus-frequency = <0x17c841c0>; ++ ++ memory-controller@2000 { ++ compatible = "fsl,mpc8548-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupt-parent = <&mpic>; ++ interrupts = <18 2>; ++ }; ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,mpc8548-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x80000>; // L2, 512K ++ interrupt-parent = <&mpic>; ++ interrupts = <16 2>; ++ }; ++ ++ mpic: pic@40000 { ++ clock-frequency = <0x17c841c0>; ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <2>; ++ reg = <0x40000 0x40000>; ++ built-in; ++ compatible = "chrp,open-pic"; ++ device_type = "open-pic"; ++ big-endian; ++ }; ++ ++ msi@41600 { ++ compatible = "fsl,mpic-msi"; ++ reg = <0x41600 0x80>; ++ msi-available-ranges = <0 0x100>; ++ interrupts = < ++ 0x3c 0 ++ 0x3d 0 ++ 0x3e 0 ++ 0x3f 0 ++ 0x40 0 ++ 0x41 0 ++ 0x42 0 ++ 0x43 0>; ++ interrupt-parent = <&mpic>; ++ }; ++ ++ mdio@24520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ device_type = "mdio"; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++ phy0: ethernet-phy@0 { ++ reg = <0x1>; ++ device_type = "ethernet-phy"; ++ }; ++ phy1: ethernet-phy@1 { ++ reg = <0x2>; ++ device_type = "ethernet-phy"; ++ }; ++ phy2: ethernet-phy@2 { ++ reg = <0x3>; ++ device_type = "ethernet-phy"; ++ }; ++ phy3: ethernet-phy@3 { ++ reg = <0x4>; ++ device_type = "ethernet-phy"; ++ }; ++ tbi0: tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ ethernet@24000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x24000 0x1000>; ++ local-mac-address = [ 00 01 85 48 e0 10 ]; ++ interrupts = <13 2 14 2 18 2>; ++ interrupt-parent = <&mpic>; ++ phy-handle = <&phy0>; ++ }; ++ ++ ethernet@25000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x25000 0x1000>; ++ local-mac-address = [ 00 01 85 48 e1 10 ]; ++ interrupts = <19 2 20 2 24 2>; ++ interrupt-parent = <&mpic>; ++ phy-handle = <&phy1>; ++ }; ++ ++ ethernet@26000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x26000 0x1000>; ++ local-mac-address = [ 00 01 85 48 e2 10 ]; ++ interrupts = <15 2 16 2 17 2>; ++ interrupt-parent = <&mpic>; ++ phy-handle = <&phy2>; ++ }; ++ ++ ethernet@27000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x27000 0x1000>; ++ local-mac-address = [ 00 01 85 48 e2 10 ]; ++ interrupts = <5 2 22 2 23 2>; ++ interrupt-parent = <&mpic>; ++ phy-handle = <&phy3>; ++ }; ++ ++ serial@4500 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4500 0x100>; // reg base, size ++ clock-frequency = <0x17c841c0>; ++ interrupts = <26 2>; ++ interrupt-parent = <&mpic>; ++ }; ++ ++ serial@4600 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4600 0x100>; // reg base, size ++ clock-frequency = <0x17c841c0>; ++ interrupts = <26 2>; ++ interrupt-parent = <&mpic>; ++ }; ++ ++ i2c@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <27 2>; ++ interrupt-parent = <&mpic>; ++ dfsrr; ++ rtc@68 { ++ compatible = "rtc,m41t81"; ++ reg = <0x68>; ++ }; ++ }; ++ ++ i2c@3100 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <1>; ++ compatible = "fsl-i2c"; ++ reg = <0x3100 0x100>; ++ interrupts = <27 2>; ++ interrupt-parent = <&mpic>; ++ dfsrr; ++ }; ++ ++ }; ++ ++ pci@e0008000 { ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x12 (AD[18]) on BCM956820 boards */ ++ 0x9000 0x0 0x0 0x1 &mpic 0x30 0x1 ++ /* IDSEL 0x1e (AD[30]) on BCM956636 boards */ ++ 0xf000 0x0 0x0 0x1 &mpic 0x30 0x1>; ++ ++ interrupt-parent = <&mpic>; ++ interrupts = <24 2>; ++ bus-range = <0 0>; ++ ranges = <0x02000000 0x0 0x50000000 0x50000000 0x0 0x10000000 ++ 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x04000000>; ++ clock-frequency = <0x3b74a460>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ reg = <0xe0008000 0x1000>; ++ compatible = "85xx"; ++ device_type = "pci"; ++ ++ }; ++ ++ /* PCI Express */ ++ pcie@e000a000 { ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ ++ /* IDSEL 0x0 (PEX) */ ++ 00000 0x0 0x0 0x1 &mpic 0x30 0x1 ++ 00000 0x0 0x0 0x2 &mpic 0x31 0x1 ++ 00000 0x0 0x0 0x3 &mpic 0x32 0x1 ++ 00000 0x0 0x0 0x4 &mpic 0x33 0x1>; ++ ++ interrupt-parent = <&mpic>; ++ interrupts = <0xa 0x2>; ++ bus-range = <0x80 0xff>; ++ ranges = <0x02000000 0x0 0x60000000 0x60000000 0x0 0x10000000 ++ 0x01000000 0x0 0x00000000 0xe8000000 0x0 0x10000000>; ++ clock-frequency = <33333333>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ reg = <0xe000a000 0x1000>; ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ }; ++ ++ localbus@0xe0005000 { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,elbc", "simple-bus"; ++ reg = <0xe0005000 0x1000>; ++ interrupt-parent = <&mpic>; ++ ++ ranges = <0x0 0x0 0xf0000000 0x08000000 ++ 0x1 0x0 0xf8000000 0x08000000>; ++ ++ flash@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x08000000>; ++ bank-width = <2>; ++ device-width = <1>; ++ ++ partition@0 { ++ label = "kernel"; ++ reg = <0x00000000 0x003e0000>; ++ }; ++ partition@1 { ++ label = "device-tree"; ++ reg = <0x003e0000 0x00020000>; ++ }; ++ partition@2 { ++ label = "root-overlay"; ++ reg = <0x00400000 0x07b00000>; ++ }; ++ partition@3 { ++ label = "recovery-cfe-bootloader"; ++ reg = <0x07f00000 0x00100000>; ++ readonly; ++ }; ++ }; ++ ++ flash@1,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x1 0x0 0x08000000>; ++ bank-width = <2>; ++ device-width = <1>; ++ ++ partition@0 { ++ label = "root"; ++ reg = <0x00000000 0x07f00000>; ++ }; ++ partition@1 { ++ label = "root-ro"; ++ reg = <0x00000000 0x07f00000>; ++ }; ++ partition@2 { ++ label = "cfe-bootloader"; ++ reg = <0x07f00000 0x00100000>; ++ readonly; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/cel_kennisis.dts b/arch/powerpc/boot/dts/cel_kennisis.dts +new file mode 100644 +index 0000000..49e24b4 +--- /dev/null ++++ b/arch/powerpc/boot/dts/cel_kennisis.dts +@@ -0,0 +1,243 @@ ++/* ++ * Celestica Kennesis Device Tree Source ++ * ++ * Copyright 2013 Cumulus Networks, 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/ "p2020si.dtsi" ++ ++/ { ++ model = "cel,kennisis"; ++ compatible = "cel,kennisis"; ++ ++ aliases { ++ ethernet0 = &enet1; ++ serial0 = &serial0; ++ pci2 = &pci2; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ }; ++ ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ ++ localbus@ffe05000 { ++ /* NOR and NAND Flashes, CPLD */ ++ ranges = <0x0 0x0 0x0 0xec000000 0x04000000 ++ 0x1 0x0 0x0 0xffa00000 0x00100000 ++ 0x2 0x0 0x0 0xffb00000 0x00100000>; ++ ++ nor@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x04000000>; ++ bank-width = <2>; ++ device-width = <1>; ++ ++ partition@0 { ++ /* Entire flash minus (u-boot + onie) */ ++ reg = <0x00000000 0x03b60000>; ++ label = "open"; ++ }; ++ partition@1 { ++ /* 4MB onie */ ++ reg = <0x03b60000 0x00400000>; ++ label = "onie"; ++ }; ++ partition@2 { ++ /* 128KB, 1 sector */ ++ reg = <0x03f60000 0x00020000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@3 { ++ /* 512KB u-boot */ ++ reg = <0x03f80000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ ++ nand@1,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,p2020-fcm-nand", ++ "fsl,elbc-fcm-nand"; ++ reg = <0x1 0x0 0x40000>; ++ ++ partition@0 { ++ reg = <0x0 0x40000000>; ++ label = "open2"; ++ }; ++ }; ++ ++ CPLD@2,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cel,kennisis-cpld"; ++ reg = <0x2 0x0 0x40000>; ++ }; ++ }; ++ ++ soc@ffe00000 { ++ i2c@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ fsl,preserve-clocking; ++ ++ rtc@68 { ++ compatible = "dallas,ds1337"; ++ reg = <0x68>; ++ }; ++ board_eeprom@50 { ++ compatible = "at,24c64"; ++ reg = <0x50>; ++ label = "board_eeprom"; ++ }; ++ temp_ambient2@4b { ++ compatible = "nxp,lm75a"; ++ reg = <0x4b>; ++ interrupt-parent = <&mpic>; ++ interrupts = <3 3>; ++ }; ++ temp_bcm@4d { ++ compatible = "nxp,lm75a"; ++ reg = <0x4d>; ++ interrupt-parent = <&mpic>; ++ interrupts = <3 3>; ++ }; ++ psu_eeprom@51 { ++ compatible = "at,24c02"; ++ reg = <0x51>; ++ label = "psu2_eeprom"; ++ read-only; ++ }; ++ }; ++ ++ i2c@3100 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ fsl,preserve-clocking; ++ ++ pwm@4d { ++ compatible = "smsc,emc2305"; ++ reg = <0x4d>; ++ interrupt-parent = <&mpic>; ++ interrupts = <2 3>; ++ }; ++ temp_ambient1@4f { ++ compatible = "nxp,lm75a"; ++ reg = <0x4f>; ++ interrupt-parent = <&mpic>; ++ interrupts = <3 3>; ++ }; ++ temp_systemoutlet@4e { ++ compatible = "nxp,lm75a"; ++ reg = <0x4e>; ++ interrupt-parent = <&mpic>; ++ interrupts = <3 3>; ++ }; ++ temp_p2020@48 { ++ compatible = "nxp,lm75a"; ++ reg = <0x48>; ++ interrupt-parent = <&mpic>; ++ interrupts = <3 3>; ++ }; ++ power@60 { ++ compatible = "ons,ncp4200"; ++ reg = <0x60>; ++ }; ++ psu_eeprom@50 { ++ compatible = "at,24c02"; ++ reg = <0x50>; ++ label = "psu1_eeprom"; ++ read-only; ++ }; ++ }; ++ ++ serial1: serial@4600 { ++ status = "disabled"; ++ }; ++ ++ usb@22000 { ++ phy_type = "ulpi"; ++ }; ++ ++ mdio@24520 { ++ phy0: ethernet-phy@3 { ++ reg = <0x3>; ++ }; ++ }; ++ ++ mdio@25520 { ++ tbi0: tbi-phy@11 { ++ reg = <0x10>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ enet0: ethernet@24000 { ++ status = "disabled"; ++ }; ++ ++ enet1: ethernet@25000 { ++ tbi-handle = <&tbi0>; ++ phy-handle = <&phy0>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ enet2: ethernet@26000 { ++ status = "disabled"; ++ }; ++ ++ sdhci@2e000 { ++ status = "disabled"; ++ }; ++ }; ++ ++ pci0: pcie@ffe08000 { ++ status = "disabled"; ++ }; ++ ++ pci1: pcie@ffe09000 { ++ status = "disabled"; ++ }; ++ ++ pci2: pcie@ffe0a000 { ++ ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 ++ >; ++ ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0xa0000000 ++ 0x2000000 0x0 0xa0000000 ++ 0x0 0x20000000 ++ ++ 0x1000000 0x0 0x0 ++ 0x1000000 0x0 0x0 ++ 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/cel_redstone.dts b/arch/powerpc/boot/dts/cel_redstone.dts +new file mode 100644 +index 0000000..5b4762f +--- /dev/null ++++ b/arch/powerpc/boot/dts/cel_redstone.dts +@@ -0,0 +1,924 @@ ++/* ++ * Celestica Redstone Device Tree Source ++ * ++ * Copyright 2013 Cumulus Networks, 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/ "p2020si.dtsi" ++ ++/ { ++ model = "cel,redstone"; ++ compatible = "cel,redstone"; ++ ++ aliases { ++ ethernet0 = &enet1; ++ serial0 = &serial0; ++ serial1 = &serial1; ++ pci2 = &pci2; ++ }; ++ ++ cpus { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ PowerPC,P2020@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <0x1>; ++ }; ++ PowerPC,P2020@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <0x1>; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ }; ++ ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ ++ localbus@ffe05000 { ++ /* NOR and NAND Flashes, CPLD */ ++ ranges = <0x0 0x0 0x0 0xec000000 0x04000000 ++ 0x1 0x0 0x0 0xffa00000 0x00100000 ++ 0x2 0x0 0x0 0xffb80000 0x00020000 ++ 0x3 0x0 0x0 0xffb00000 0x00000400 ++ 0x4 0x0 0x0 0xffb40000 0x00000400>; ++ ++ nor@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x04000000>; ++ bank-width = <2>; ++ device-width = <1>; ++ ++ partition@0 { ++ /* Entire flash minus (u-boot + onie) */ ++ reg = <0x00000000 0x03b60000>; ++ label = "open"; ++ }; ++ partition@1 { ++ /* 4MB onie */ ++ reg = <0x03b60000 0x00400000>; ++ label = "onie"; ++ }; ++ partition@2 { ++ /* 128KB, 1 sector */ ++ reg = <0x03f60000 0x00020000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@3 { ++ /* 512KB u-boot */ ++ reg = <0x03f80000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ ++ nand@1,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,p2020-fcm-nand", ++ "fsl,elbc-fcm-nand"; ++ reg = <0x1 0x0 0x40000>; ++ ++ partition@0 { ++ reg = <0x0 0x40000000>; ++ label = "open2"; ++ }; ++ }; ++ lpsram@2,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "redstone_lpsram"; ++ reg = <0x2 0x0 0x20000>; ++ ++ partition@0 { ++ reg = <0x0 0x20000>; ++ label = "open3"; ++ }; ++ }; ++ CPLD1@3,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "redstone_cpld1"; ++ label = "cpld_1"; ++ reg = <0x3 0x0 0x400>; ++ }; ++ CPLD234@4,0 { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "redstone_cpld234"; ++ label = "cpld_234"; ++ reg = <0x4 0x0 0x400>; ++ ranges; ++ cpld_i2c@10 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <0>; ++ compatible = "cel,cpld-i2c-bus"; ++ reg = <0x4 0x10 0x30>; ++ clock-frequency = <100000>; ++ cel_cpld,timeout = <10000>; ++ mux@1 { ++ compatible = "cel,cpld-i2c-mux"; ++ reg = <0x1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ /* SFP+ 1 */ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port1"; ++ }; ++ }; ++ /* SFP+ 2 */ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port2"; ++ }; ++ }; ++ /* SFP+ 3 */ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port3"; ++ }; ++ }; ++ /* SFP+ 4 */ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port4"; ++ }; ++ }; ++ /* SFP+ 5 */ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port5"; ++ }; ++ }; ++ /* SFP+ 6 */ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port6"; ++ }; ++ }; ++ /* SFP+ 7 */ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port7"; ++ }; ++ }; ++ /* SFP+ 8 */ ++ i2c@8 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <8>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port8"; ++ }; ++ }; ++ /* SFP+ 9 */ ++ i2c@9 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <9>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port9"; ++ }; ++ }; ++ /* SFP+ 10 */ ++ i2c@10 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <10>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port10"; ++ }; ++ }; ++ /* SFP+ 11 */ ++ i2c@11 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <11>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port11"; ++ }; ++ }; ++ /* SFP+ 12 */ ++ i2c@12 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <12>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port12"; ++ }; ++ }; ++ /* SFP+ 13 */ ++ i2c@13 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <13>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port13"; ++ }; ++ }; ++ /* SFP+ 14 */ ++ i2c@14 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <14>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port14"; ++ }; ++ }; ++ /* SFP+ 15 */ ++ i2c@15 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <15>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port15"; ++ }; ++ }; ++ /* SFP+ 16 */ ++ i2c@16 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <16>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port16"; ++ }; ++ }; ++ /* SFP+ 17 */ ++ i2c@17 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <17>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port17"; ++ }; ++ }; ++ /* SFP+ 18 */ ++ i2c@18 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <18>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port18"; ++ }; ++ }; ++ }; ++ }; ++ cpld_i2c@40 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <1>; ++ compatible = "cel,cpld-i2c-bus"; ++ reg = <0x4 0x40 0x30>; ++ clock-frequency = <100000>; ++ cel_cpld,timeout = <10000>; ++ mux@2 { ++ compatible = "cel,cpld-i2c-mux"; ++ reg = <0x2>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ /* SFP+ 19 */ ++ i2c@19 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <19>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port19"; ++ }; ++ }; ++ /* SFP+ 20 */ ++ i2c@20 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <20>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port20"; ++ }; ++ }; ++ /* SFP+ 21 */ ++ i2c@21 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <21>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port21"; ++ }; ++ }; ++ /* SFP+ 22 */ ++ i2c@22 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <22>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port22"; ++ }; ++ }; ++ /* SFP+ 23 */ ++ i2c@23 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <23>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port23"; ++ }; ++ }; ++ /* SFP+ 24 */ ++ i2c@24 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <24>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port24"; ++ }; ++ }; ++ /* SFP+ 25 */ ++ i2c@25 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <25>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port25"; ++ }; ++ }; ++ /* SFP+ 26 */ ++ i2c@26 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <26>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port26"; ++ }; ++ }; ++ /* SFP+ 27 */ ++ i2c@27 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <27>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port27"; ++ }; ++ }; ++ /* SFP+ 28 */ ++ i2c@28 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <28>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port28"; ++ }; ++ }; ++ /* SFP+ 29 */ ++ i2c@29 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <29>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port29"; ++ }; ++ }; ++ /* SFP+ 30 */ ++ i2c@30 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <30>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port30"; ++ }; ++ }; ++ /* SFP+ 31 */ ++ i2c@31 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <31>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port31"; ++ }; ++ }; ++ /* SFP+ 32 */ ++ i2c@32 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <32>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port32"; ++ }; ++ }; ++ /* SFP+ 33 */ ++ i2c@33 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <33>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port33"; ++ }; ++ }; ++ /* SFP+ 34 */ ++ i2c@34 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <34>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port34"; ++ }; ++ }; ++ /* SFP+ 35 */ ++ i2c@35 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <35>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port35"; ++ }; ++ }; ++ /* SFP+ 36 */ ++ i2c@36 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <36>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port36"; ++ }; ++ }; ++ }; ++ }; ++ cpld_i2c@80 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <2>; ++ compatible = "cel,cpld-i2c-bus"; ++ reg = <0x4 0x80 0x30>; ++ clock-frequency = <100000>; ++ cel_cpld,timeout = <10000>; ++ mux@3 { ++ compatible = "cel,cpld-i2c-mux"; ++ reg = <0x3>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ /* SFP+ 37 */ ++ i2c@37 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <37>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port37"; ++ }; ++ }; ++ /* SFP+ 38 */ ++ i2c@38 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <38>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port38"; ++ }; ++ }; ++ /* SFP+ 39 */ ++ i2c@39 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <39>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port39"; ++ }; ++ }; ++ /* SFP+ 40 */ ++ i2c@40 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <40>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port40"; ++ }; ++ }; ++ /* SFP+ 41 */ ++ i2c@41 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <41>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port41"; ++ }; ++ }; ++ /* SFP+ 42 */ ++ i2c@42 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <42>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port42"; ++ }; ++ }; ++ /* SFP+ 43 */ ++ i2c@43 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <43>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port43"; ++ }; ++ }; ++ /* SFP+ 44 */ ++ i2c@44 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <44>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port44"; ++ }; ++ }; ++ /* SFP+ 45 */ ++ i2c@45 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <45>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port45"; ++ }; ++ }; ++ /* SFP+ 46 */ ++ i2c@46 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <46>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port46"; ++ }; ++ }; ++ /* SFP+ 47 */ ++ i2c@47 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <47>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port47"; ++ }; ++ }; ++ /* SFP+ 48 */ ++ i2c@48 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <48>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port48"; ++ }; ++ }; ++ /* QSFP 1 */ ++ i2c@49 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <49>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port49"; ++ }; ++ }; ++ /* QSFP 2 */ ++ i2c@50 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <50>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port50"; ++ }; ++ }; ++ /* QSFP 3 */ ++ i2c@51 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <51>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port51"; ++ }; ++ }; ++ /* QSFP 4 */ ++ i2c@52 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <52>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port52"; ++ }; ++ }; ++ }; ++ }; ++ }; ++ }; ++ ++ soc@ffe00000 { ++ i2c@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl-i2c"; ++ fsl,preserve-clocking; ++ ++ rtc@68 { ++ compatible = "dallas,ds1337"; ++ reg = <0x68>; ++ }; ++ board_eeprom@50 { ++ compatible = "at,24c64"; ++ reg = <0x50>; ++ label = "board_eeprom"; ++ }; ++ temp_ambient2@4b { ++ compatible = "nxp,lm75a"; ++ reg = <0x4b>; ++ interrupt-parent = <&mpic>; ++ interrupts = <5 3>; ++ }; ++ temp_bcm@4e { ++ compatible = "nxp,lm75a"; ++ reg = <0x4e>; ++ interrupt-parent = <&mpic>; ++ interrupts = <5 3>; ++ }; ++ psu_eeprom@51 { ++ compatible = "at,24c02"; ++ reg = <0x51>; ++ label = "psu2_eeprom"; ++ read-only; ++ }; ++ }; ++ ++ i2c@3100 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl-i2c"; ++ fsl,preserve-clocking; ++ ++ temp_p2020@48 { ++ compatible = "nxp,lm75a"; ++ reg = <0x48>; ++ interrupt-parent = <&mpic>; ++ interrupts = <5 3>; ++ }; ++ temp_rearoutput@49 { ++ compatible = "nxp,lm75a"; ++ reg = <0x49>; ++ interrupt-parent = <&mpic>; ++ interrupts = <5 3>; ++ }; ++ pwm@4d { ++ compatible = "smsc,emc2305"; ++ reg = <0x4d>; ++ interrupt-parent = <&mpic>; ++ interrupts = <6 3>; ++ }; ++ temp_ambient1@4f { ++ compatible = "nxp,lm75a"; ++ reg = <0x4f>; ++ interrupt-parent = <&mpic>; ++ interrupts = <5 3>; ++ }; ++ psu_eeprom@50 { ++ compatible = "at,24c02"; ++ reg = <0x50>; ++ label = "psu1_eeprom"; ++ read-only; ++ }; ++ power@60 { ++ compatible = "ons,ncp4200"; ++ reg = <0x60>; ++ }; ++ }; ++ ++ usb@22000 { ++ phy_type = "ulpi"; ++ }; ++ ++ enet0: ethernet@24000 { ++ status = "disabled"; ++ }; ++ ++ mdio0: mdio@24520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++ phy0: ethernet-phy@3 { ++ /* ++ * CPLD Status change bit for phys need to be cleared, for ++ * interrupts to work properly, hence instead of modifying ++ * phy driver code to clear status change bits.So commenting ++ * out for now. ++ * interrupts = < 5 1>; ++ */ ++ reg = <0x3>; ++ device_type = "ethernet-phy"; ++ }; ++ }; ++ ++ enet1: ethernet@25000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ cell-index = <0x1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x25000 0x1000>; ++ ranges = <0x0 0x25000 0x1000>; ++ interrupts = < ++ 0x23 0x2 ++ 0x24 0x2 ++ 0x28 0x2>; ++ interrupt-parent = <&mpic>; ++ tbi-handle = <&tbi0>; ++ phy-handle = <&phy0>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ mdio1: mdio@25520 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ compatible = "fsl,gianfar-tbi"; ++ reg = <0x25520 0x20>; ++ tbi0: tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ enet2: ethernet@26000 { ++ status = "disabled"; ++ }; ++ ++ sdhci@2e000 { ++ status = "disabled"; ++ }; ++ }; ++ ++ pci0: pcie@ffe08000 { ++ status = "disabled"; ++ }; ++ ++ pci1: pcie@ffe09000 { ++ status = "disabled"; ++ }; ++ ++ pci2: pcie@ffe0a000 { ++ ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 ++ >; ++ ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0xa0000000 ++ 0x2000000 0x0 0xa0000000 ++ 0x0 0x20000000 ++ ++ 0x1000000 0x0 0x0 ++ 0x1000000 0x0 0x0 ++ 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/cel_smallstone.dts b/arch/powerpc/boot/dts/cel_smallstone.dts +new file mode 100644 +index 0000000..675f806 +--- /dev/null ++++ b/arch/powerpc/boot/dts/cel_smallstone.dts +@@ -0,0 +1,676 @@ ++/* ++ * Celestica Smallstone Device Tree Source ++ * ++ * Copyright 2013 Cumulus Networks, 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/ "p2020si.dtsi" ++ ++/ { ++ model = "cel,smallstone"; ++ compatible = "cel,smallstone"; ++ ++ aliases { ++ ethernet0 = &enet1; ++ serial0 = &serial0; ++ serial1 = &serial1; ++ pci2 = &pci2; ++ }; ++ ++ cpus { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ PowerPC,P2020@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <0x1>; ++ }; ++ PowerPC,P2020@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <0x1>; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ }; ++ ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ ++ localbus@ffe05000 { ++ /* NOR and NAND Flashes, CPLD */ ++ ranges = <0x0 0x0 0x0 0xec000000 0x04000000 ++ 0x1 0x0 0x0 0xffa00000 0x00100000 ++ 0x2 0x0 0x0 0xffb80000 0x00020000 ++ 0x3 0x0 0x0 0xffb00000 0x00000400 ++ 0x4 0x0 0x0 0xffb40000 0x00000400>; ++ ++ nor@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x04000000>; ++ bank-width = <2>; ++ device-width = <1>; ++ ++ partition@0 { ++ /* Entire flash minus (u-boot + onie) */ ++ reg = <0x00000000 0x03b60000>; ++ label = "open"; ++ }; ++ partition@1 { ++ /* 4MB onie */ ++ reg = <0x03b60000 0x00400000>; ++ label = "onie"; ++ }; ++ partition@2 { ++ /* 128KB, 1 sector */ ++ reg = <0x03f60000 0x00020000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@3 { ++ /* 512KB u-boot */ ++ reg = <0x03f80000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ ++ nand@1,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,p2020-fcm-nand", ++ "fsl,elbc-fcm-nand"; ++ reg = <0x1 0x0 0x40000>; ++ ++ partition@0 { ++ reg = <0x0 0x40000000>; ++ label = "open2"; ++ }; ++ }; ++ lpsram@2,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "smallstone_lpsram"; ++ reg = <0x2 0x0 0x20000>; ++ ++ partition@0 { ++ reg = <0x0 0x20000>; ++ label = "open3"; ++ }; ++ }; ++ CPLD1@3,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "smallstone_cpld1"; ++ label = "cpld_1"; ++ reg = <0x3 0x0 0x400>; ++ }; ++ CPLD23@4,0 { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "smallstone_cpld23"; ++ label = "cpld_23"; ++ reg = <0x4 0x0 0x400>; ++ ranges; ++ cpld_i2c@10 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <0>; ++ compatible = "cel,cpld-i2c-bus"; ++ reg = <0x4 0x10 0x30>; ++ clock-frequency = <100000>; ++ cel_cpld,timeout = <10000>; ++ mux@1 { ++ compatible = "cel,cpld-i2c-mux"; ++ reg = <0x1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ /* QSFP 1 */ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port1"; ++ }; ++ }; ++ /* QSFP 2 */ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port2"; ++ }; ++ }; ++ /* QSFP 3 */ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port3"; ++ }; ++ }; ++ /* QSFP 4 */ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port4"; ++ }; ++ }; ++ /* QSFP 5 */ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port5"; ++ }; ++ }; ++ /* QSFP 6 */ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port6"; ++ }; ++ }; ++ /* QSFP 7 */ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port7"; ++ }; ++ }; ++ /* QSFP 8 */ ++ i2c@8 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <8>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port8"; ++ }; ++ }; ++ /* QSFP 9 */ ++ i2c@9 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <9>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port9"; ++ }; ++ }; ++ /* QSFP 10 */ ++ i2c@10 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <10>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port10"; ++ }; ++ }; ++ /* QSFP 11 */ ++ i2c@11 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <11>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port11"; ++ }; ++ }; ++ /* QSFP 12 */ ++ i2c@12 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <12>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port12"; ++ }; ++ }; ++ /* QSFP 13 */ ++ i2c@13 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <13>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port13"; ++ }; ++ }; ++ /* QSFP 14 */ ++ i2c@14 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <14>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port14"; ++ }; ++ }; ++ /* QSFP 15 */ ++ i2c@15 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <15>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port15"; ++ }; ++ }; ++ /* QSFP 16 */ ++ i2c@16 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <16>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port16"; ++ }; ++ }; ++ }; ++ }; ++ cpld_i2c@40 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <1>; ++ compatible = "cel,cpld-i2c-bus"; ++ reg = <0x4 0x40 0x30>; ++ clock-frequency = <100000>; ++ cel_cpld,timeout = <10000>; ++ mux@2 { ++ compatible = "cel,cpld-i2c-mux"; ++ reg = <0x2>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ /* QSFP 17 */ ++ i2c@17 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <17>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port17"; ++ }; ++ }; ++ /* QSFP 18 */ ++ i2c@18 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <18>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port18"; ++ }; ++ }; ++ /* QSFP 19 */ ++ i2c@19 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <19>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port19"; ++ }; ++ }; ++ /* QSFP 20 */ ++ i2c@20 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <20>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port20"; ++ }; ++ }; ++ /* QSFP 21 */ ++ i2c@21 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <21>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port21"; ++ }; ++ }; ++ /* QSFP 22 */ ++ i2c@22 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <22>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port22"; ++ }; ++ }; ++ /* QSFP 23 */ ++ i2c@23 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <23>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port23"; ++ }; ++ }; ++ /* QSFP 24 */ ++ i2c@24 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <24>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port24"; ++ }; ++ }; ++ /* QSFP 25 */ ++ i2c@25 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <25>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port25"; ++ }; ++ }; ++ /* QSFP 26 */ ++ i2c@26 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <26>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port26"; ++ }; ++ }; ++ /* QSFP 27 */ ++ i2c@27 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <27>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port27"; ++ }; ++ }; ++ /* QSFP 28 */ ++ i2c@28 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <28>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port28"; ++ }; ++ }; ++ /* QSFP 29 */ ++ i2c@29 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <29>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port29"; ++ }; ++ }; ++ /* QSFP 30 */ ++ i2c@30 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <30>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port30"; ++ }; ++ }; ++ /* QSFP 31 */ ++ i2c@31 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <31>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port31"; ++ }; ++ }; ++ /* QSFP 32 */ ++ i2c@32 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <32>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port32"; ++ }; ++ }; ++ }; ++ }; ++ }; ++ }; ++ ++ soc@ffe00000 { ++ i2c@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl-i2c"; ++ fsl,preserve-clocking; ++ ++ rtc@68 { ++ compatible = "dallas,ds1337"; ++ reg = <0x68>; ++ }; ++ board_eeprom@50 { ++ compatible = "at,24c64"; ++ reg = <0x50>; ++ label = "board_eeprom"; ++ }; ++ temp_ambient2@4b { ++ compatible = "nxp,lm75a"; ++ reg = <0x4b>; ++ }; ++ psu_eeprom@51 { ++ compatible = "at,24c02"; ++ reg = <0x51>; ++ label = "psu2_eeprom"; ++ read-only; ++ }; ++ }; ++ ++ i2c@3100 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl-i2c"; ++ fsl,preserve-clocking; ++ ++ temp_p2020@48 { ++ compatible = "nxp,lm75a"; ++ reg = <0x48>; ++ }; ++ temp_rearoutput@49 { ++ compatible = "nxp,lm75a"; ++ reg = <0x49>; ++ }; ++ pwm@4d { ++ compatible = "smsc,emc2305"; ++ reg = <0x4d>; ++ }; ++ temp_bcm@4e { ++ compatible = "nxp,lm75a"; ++ reg = <0x4e>; ++ }; ++ temp_ambient1@4f { ++ compatible = "nxp,lm75a"; ++ reg = <0x4f>; ++ }; ++ psu_eeprom@50 { ++ compatible = "at,24c02"; ++ reg = <0x50>; ++ label = "psu1_eeprom"; ++ }; ++ power@60 { ++ compatible = "ons,ncp4200"; ++ reg = <0x60>; ++ }; ++ }; ++ ++ usb@22000 { ++ phy_type = "ulpi"; ++ }; ++ ++ enet0: ethernet@24000 { ++ status = "disabled"; ++ }; ++ ++ mdio0: mdio@24520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++ phy0: ethernet-phy@3 { ++ /* ++ * CPLD Status change bit for phys need to be cleared, for ++ * interrupts to work properly, hence instead of modifying ++ * phy driver code to clear status change bits.So commenting ++ * out for now. ++ * interrupts = < 5 1>; ++ */ ++ reg = <0x3>; ++ device_type = "ethernet-phy"; ++ }; ++ }; ++ ++ enet1: ethernet@25000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ cell-index = <0x1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x25000 0x1000>; ++ ranges = <0x0 0x25000 0x1000>; ++ interrupts = < ++ 0x23 0x2 ++ 0x24 0x2 ++ 0x28 0x2>; ++ interrupt-parent = <&mpic>; ++ tbi-handle = <&tbi0>; ++ phy-handle = <&phy0>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ mdio1: mdio@25520 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ compatible = "fsl,gianfar-tbi"; ++ reg = <0x25520 0x20>; ++ tbi0: tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ enet2: ethernet@26000 { ++ status = "disabled"; ++ }; ++ ++ sdhci@2e000 { ++ status = "disabled"; ++ }; ++ }; ++ ++ pci0: pcie@ffe08000 { ++ status = "disabled"; ++ }; ++ ++ pci1: pcie@ffe09000 { ++ status = "disabled"; ++ }; ++ ++ pci2: pcie@ffe0a000 { ++ ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 ++ >; ++ ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0xa0000000 ++ 0x2000000 0x0 0xa0000000 ++ 0x0 0x20000000 ++ ++ 0x1000000 0x0 0x0 ++ 0x1000000 0x0 0x0 ++ 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/cumulus_p2020.dts b/arch/powerpc/boot/dts/cumulus_p2020.dts +new file mode 100644 +index 0000000..a14c0a5 +--- /dev/null ++++ b/arch/powerpc/boot/dts/cumulus_p2020.dts +@@ -0,0 +1,215 @@ ++/* ++ * Cumulus P2020 Device Tree Source ++ * ++ * Copyright 2012 Cumulus Networks, 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/ "p2020si.dtsi" ++ ++/ { ++ model = "cumulus,cumulus_p2020"; ++ compatible = "cumulus,cumulus_p2020"; ++ ++ aliases { ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ serial0 = &serial0; ++ serial1 = &serial1; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ }; ++ ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ ++ mass_storage { ++ device = "mmcblk0"; ++ }; ++ ++ localbus@ffe05000 { ++ compatible = "fsl,elbc", "simple-bus"; ++ /* ++ ** Note: We are purposefully cutting the size of the ++ ** NOR flash in half, down to 128MB. Linux vmalloc() ++ ** on ppc32 has some issues trying to vmalloc more than ++ ** 256MB. ++ ** ++ ** The 256MB region should go from 0xe0000000 to ++ ** 0xf0000000, but we are skipping the first 128MB and ++ ** starting at 0xe8000000. ++ */ ++ ranges = <0x0 0x0 0x0 0xe8000000 0x08000000>; ++ ++ nor@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x08000000>; ++ bank-width = <2>; ++ partition@0 { ++ /* Entire flash minus (u-boot + onie) */ ++ reg = <0x00000000 0x07b60000>; ++ label = "open"; ++ }; ++ partition@1 { ++ /* 4MB onie */ ++ reg = <0x07b60000 0x00400000>; ++ label = "onie"; ++ }; ++ partition@2 { ++ /* 128KB, 1 sector */ ++ reg = <0x07f60000 0x00020000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@3 { ++ /* 512KB u-boot */ ++ reg = <0x07f80000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ }; ++ ++ soc@ffe00000 { ++ i2c@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ rtc@68 { ++ compatible = "stm,m41st85"; ++ reg = <0x68>; ++ }; ++ board_eeprom@50 { ++ compatible = "at,24c08"; ++ reg = <0x50>; ++ label = "board_eeprom"; ++ }; ++ temp@4c { ++ compatible = "adi,adt7461"; ++ reg = <0x4c>; ++ }; ++ }; ++ ++ usb@22000 { ++ status = "disabled"; ++ }; ++ ++ mdio@24520 { ++ phy0: ethernet-phy@1 { ++ interrupt-parent = <&mpic>; ++ interrupts = <3 1>; ++ reg = <0x1>; ++ }; ++ phy1: ethernet-phy@2 { ++ interrupt-parent = <&mpic>; ++ interrupts = <3 1>; ++ reg = <0x2>; ++ }; ++ }; ++ ++ ptp_clock@24E00 { ++ compatible = "fsl,etsec-ptp"; ++ reg = <0x24E00 0xB0>; ++ interrupts = <68 2 69 2 70 2>; ++ interrupt-parent = < &mpic >; ++ fsl,tclk-period = <5>; ++ fsl,tmr-prsc = <200>; ++ fsl,tmr-add = <0xCCCCCCCD>; ++ fsl,tmr-fiper1 = <0x3B9AC9FB>; ++ fsl,tmr-fiper2 = <0x0001869B>; ++ fsl,max-adj = <249999999>; ++ }; ++ ++ enet0: ethernet@24000 { ++ phy-handle = <&phy0>; ++ phy-connection-type = "rgmii-id"; ++ }; ++ ++ enet1: ethernet@25000 { ++ phy-handle = <&phy1>; ++ phy-connection-type = "rgmii-id"; ++ }; ++ ++ enet2: ethernet@26000 { ++ status = "disabled"; ++ }; ++ ++ irq8@50100 { ++ reg = <0x50100 0x10>; ++ interrupt-parent = <&mpic>; ++ interrupts = <8 1>; ++ }; ++ }; ++ ++ pci0: pcie@ffe08000 { ++ ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x8 0x1 ++ 0000 0x0 0x0 0x2 &mpic 0x9 0x1 ++ 0000 0x0 0x0 0x3 &mpic 0xa 0x1 ++ 0000 0x0 0x0 0x4 &mpic 0xb 0x1 ++ >; ++ ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0x80000000 ++ 0x2000000 0x0 0x80000000 ++ 0x0 0x20000000 ++ ++ 0x1000000 0x0 0x0 ++ 0x1000000 0x0 0x0 ++ 0x0 0x10000>; ++ }; ++ }; ++ ++ pci1: pcie@ffe09000 { ++ status = "disabled"; ++ }; ++ ++ pci2: pcie@ffe0a000 { ++ ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 ++ >; ++ ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0xa0000000 ++ 0x2000000 0x0 0xa0000000 ++ 0x0 0x20000000 ++ ++ 0x1000000 0x0 0x0 ++ 0x1000000 0x0 0x0 ++ 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/dni_6448.dts b/arch/powerpc/boot/dts/dni_6448.dts +new file mode 100644 +index 0000000..749d1d9 +--- /dev/null ++++ b/arch/powerpc/boot/dts/dni_6448.dts +@@ -0,0 +1,433 @@ ++/* ++ * Delta Networks, Inc. ET-6448R Device Tree Source ++ * ++ * Copyright 2012, Cumulus Networks, 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. ++ * ++ */ ++/dts-v1/; ++ ++/ { ++ model = "dni,et-6448r"; ++ compatible = "dni,dni_6448"; ++ #address-cells = <0x2>; ++ #size-cells = <0x2>; ++ interrupt-parent = <&MPIC>; ++ aliases { ++ ethernet0 = &ENET0; ++ serial0 = &SERIAL0; ++ serial1 = &SERIAL1; ++ pci3 = &pci3; ++ }; ++ cpus { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ PowerPC,8536@0 { ++ device_type = "cpu"; ++ reg = <0>; ++ d-cache-line-size = <32>; // 32 bytes ++ i-cache-line-size = <32>; // 32 bytes ++ d-cache-size = <0x8000>; // L1, 32K ++ i-cache-size = <0x8000>; // L1, 32K ++ timebase-frequency = <0>; // From uboot ++ bus-frequency = <0>; // From uboot ++ clock-frequency = <0>; // From uboot ++ next-level-cache = <&L2>; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ }; ++ ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ ++ localbus@e0005000 { ++ #address-cells = <0x2>; ++ #size-cells = <0x1>; ++ compatible = "fsl,8536-elbc", "fsl,elbc", "simple-bus"; ++ reg = <0x0 0xe0005000 0x0 0x00001000>; ++ interrupts = <0x13 0x2>; ++ ranges = < ++ 0x0 0x0 0x0 0xfc000000 0x04000000 ++ 0x1 0x0 0x0 0xfa000000 0x00040000 ++ >; ++ flash@0,0 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x04000000>; ++ bank-width = <0x4>; ++ device-width = <0x2>; ++ byteswap; ++ partition@0 { ++ /* Entire flash minus (u-boot + info + onie) */ ++ reg = <0x00000000 0x03b00000>; ++ label = "open"; ++ }; ++ partition@1 { ++ /* 4MB onie */ ++ reg = <0x03b00000 0x00400000>; ++ label = "onie"; ++ }; ++ partition@2 { ++ /* 256KB, 1 sector */ ++ reg = <0x03f00000 0x00040000>; ++ label = "board_eeprom"; ++ }; ++ partition@3 { ++ /* 256KB, 1 sector */ ++ reg = <0x03f40000 0x00040000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@4 { ++ /* 512KB u-boot */ ++ reg = <0x03f80000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ cpld@1,0 { ++ compatible = "dni,6448-cpld"; ++ reg = <0x1 0x0 0x00040000>; ++ }; ++ }; ++ ++ soc@e0000000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ device_type = "soc"; ++ compatible = "fsl,8536-immr", "simple-bus"; ++ ranges = <0x0 0x0 0xe0000000 0x100000>; ++ bus-frequency = <0x0>; // From uboot ++ ++ memory-controller@2000 { ++ compatible = "fsl,mpc8536-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <0x12 0x2>; ++ }; ++ ++ I2C0: i2c@3000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ cell-index = <0x0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <0x2b 0x2>; ++ dfsrr; ++ clock-frequency = <400000>; ++ fsl,timeout = <10000>; ++ mux@1 { ++ compatible = "dni,6448-i2c-mux"; ++ reg = <0x1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ // front panel port 45 ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port45"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ // front panel port 46 ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port46"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ // front panel port 47 ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port47"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ // front panel port 48 ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port48"; ++ }; ++ }; ++ }; ++ spd@52 { ++ read-only; ++ compatible = "at,spd"; ++ reg = <0x53>; ++ }; ++ }; ++ ++ I2C1: i2c@3100 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ cell-index = <0x1>; ++ compatible = "fsl-i2c"; ++ reg = <0x3100 0x100>; ++ interrupts = <0x2b 0x2>; ++ dfsrr; ++ clock-frequency = <400000>; ++ fsl,timeout = <10000>; ++ mux@2 { ++ compatible = "dni,6448-i2c-mux"; ++ reg = <0x2>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ tmon@48 { ++ compatible = "ti,tmp75"; ++ reg = <0x48>; ++ }; ++ tmon@49 { ++ compatible = "ti,tmp75"; ++ reg = <0x49>; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ hwmon@40 { ++ compatible = "lt,ltc4215"; ++ reg = <0x40>; ++ }; ++ psu_eeprom@54 { ++ compatible = "at,24c08"; ++ reg = <0x54>; ++ label = "psu1_eeprom"; ++ read-only; ++ }; ++ psu_eeprom@50 { ++ compatible = "at,24c08"; ++ reg = <0x50>; ++ label = "psu2_eeprom"; ++ read-only; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ ++ fan@48 { ++ compatible = "maxim,max6651"; ++ reg = <0x48>; ++ }; ++ rtc@68 { ++ compatible = "stm,m41st85"; ++ reg = <0x68>; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ // 10G module A.1 ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port49"; ++ }; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ // 10G module A.2 ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port50"; ++ }; ++ }; ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ // 10G module B.1 ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port51"; ++ }; ++ }; ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ // 10G module B.2 ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port52"; ++ }; ++ }; ++ }; ++ }; ++ ++ SERIAL0: serial@4500 { ++ cell-index = <0x0>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4500 0x100>; ++ clock-frequency = <0x0>; ++ interrupts = <0x2a 0x2>; ++ }; ++ ++ SERIAL1: serial@4600 { ++ cell-index = <1>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4600 0x100>; ++ clock-frequency = <0>; ++ interrupts = <42 0x2>; ++ }; ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,mpc8536-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <0x20>; ++ cache-size = <0x80000>; ++ interrupts = <0x10 0x2>; ++ }; ++ ++ USB: usb@22000 { ++ compatible = "fsl-usb2-dr"; ++ reg = <0x22000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <28 0x2>; ++ phy_type = "ulpi"; ++ dr_mode = "host"; ++ }; ++ ++ MDIO1: mdio@24520 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++ PHY0: ethernet-phy@4 { ++ reg = <0x4>; ++ device_type = "ethernet-phy"; ++ }; ++ }; ++ ++ ENET0: ethernet@24000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ cell-index = <0x1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x24000 0x1000>; ++ ranges = <0x0 0x24000 0x1000>; ++ interrupts = < ++ 0x1d 0x2 ++ 0x1e 0x2 ++ 0x22 0x2>; ++ phy-handle = <&PHY0>; ++ phy-connection-type = "rgmii"; ++ }; ++ ++ MPIC: pic@40000 { ++ interrupt-controller; ++ #address-cells = <0x0>; ++ #interrupt-cells = <0x2>; ++ reg = <0x40000 0x40000>; ++ compatible = "chrp,open-pic"; ++ device_type = "open-pic"; ++ }; ++ msi@41600 { ++ compatible = "fsl,mpc8536-msi", "fsl,mpic-msi"; ++ reg = <0x41600 0x80>; ++ msi-available-ranges = <0x0 0x100>; ++ interrupts = < ++ 0xe0 0x0 ++ 0xe1 0x0 ++ 0xe2 0x0 ++ 0xe3 0x0 ++ 0xe4 0x0 ++ 0xe5 0x0 ++ 0xe6 0x0 ++ 0xe7 0x0>; ++ }; ++ global-utilities@e0000 { ++ compatible = "fsl,mpc8548-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ }; ++ ++ pci3: pcie@e000b000 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ reg = <0 0xe000b000 0 0x1000>; ++ bus-range = <0 0xff>; ++ ranges = <0x02000000 0 0xa0000000 0 0xa0000000 0 0x20000000 ++ 0x01000000 0 0x00000000 0 0xe3000000 0 0x01000000>; ++ clock-frequency = <33333333>; ++ interrupts = <27 0x2>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &MPIC 8 1 ++ 0000 0 0 2 &MPIC 9 1 ++ 0000 0 0 3 &MPIC 10 1 ++ 0000 0 0 4 &MPIC 11 1 ++ >; ++ ++ // not sure what this seciton does, but cribbed from mpc8536ds.dts ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ ranges = <0x02000000 0 0xa0000000 ++ 0x02000000 0 0xa0000000 ++ 0 0x20000000 ++ ++ 0x01000000 0 0x00000000 ++ 0x01000000 0 0x00000000 ++ 0 0x01000000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/dni_7448.dts b/arch/powerpc/boot/dts/dni_7448.dts +new file mode 100644 +index 0000000..f7a2563 +--- /dev/null ++++ b/arch/powerpc/boot/dts/dni_7448.dts +@@ -0,0 +1,331 @@ ++/* ++ * Delta Networks, Inc. ET-7448BF Device Tree Source ++ * ++ * Copyright 2012, Cumulus Networks, 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. ++ * ++ */ ++/dts-v1/; ++ ++/ { ++ model = "dni,et-7448bf"; ++ compatible = "dni,dni_7448"; ++ #address-cells = <0x2>; ++ #size-cells = <0x2>; ++ aliases { ++ ethernet0 = &ENET2; ++ serial0 = &SERIAL0; ++ serial1 = &SERIAL1; ++ pci2 = &PCI2; ++ }; ++ cpus { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ PowerPC,P2020@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <0x1>; ++ }; ++ PowerPC,P2020@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <0x1>; ++ }; ++ }; ++ memory { ++ device_type = "memory"; ++ }; ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ mass_storage { ++ device = "mmcblk0"; ++ }; ++ localbus@ffe05000 { ++ #address-cells = <0x2>; ++ #size-cells = <0x1>; ++ compatible = "fsl,p2020-elbc", "fsl,elbc", "simple-bus"; ++ reg = <0x0 0xffe05000 0x0 0x00001000>; ++ interrupts = <19 0x2>; ++ interrupt-parent = <&MPIC>; ++ ranges = <0x0 0x0 0x0 0xe8000000 0x8000000 ++ 0x1 0x0 0x0 0xffdf0000 0x0000100>; ++ nor@0,0 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x8000000>; ++ bank-width = <0x2>; ++ device-width = <0x2>; ++ byteswap; ++ partition@0 { ++ /* Entire flash minus (u-boot + onie) */ ++ reg = <0x00000000 0x07b60000>; ++ label = "open"; ++ }; ++ partition@1 { ++ /* 4MB onie */ ++ reg = <0x07b60000 0x00400000>; ++ label = "onie"; ++ }; ++ partition@2 { ++ /* 128KB, 1 sector */ ++ reg = <0x07f60000 0x00020000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@3 { ++ /* 512KB u-boot */ ++ reg = <0x07f80000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ cpld@1,0 { ++ compatible = "dni,7448-cpld"; ++ reg = <0x1 0x0 0x0000100>; ++ }; ++ }; ++ soc@ffe00000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ device_type = "soc"; ++ compatible = "fsl,p2020-immr", "simple-bus"; ++ ranges = <0x0 0x0 0xffe00000 0x100000>; ++ bus-frequency = <0x0>; ++ memory-controller@2000 { ++ compatible = "fsl,p2020-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupt-parent = <&MPIC>; ++ interrupts = <0x12 0x2>; ++ }; ++ I2C0: i2c@3000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ cell-index = <0x0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <0x2b 0x2>; ++ interrupt-parent = <&MPIC>; ++ dfsrr; ++ rtc@68 { ++ compatible = "stm,m41st85"; ++ reg = <0x68>; ++ }; ++ board_eeprom@54 { ++ compatible = "at,24c08"; ++ reg = <0x54>; ++ label = "board_eeprom"; ++ }; ++ spd@52 { ++ read-only; ++ compatible = "at,spd"; ++ reg = <0x52>; ++ }; ++ }; ++ I2C1: i2c@3100 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ cell-index = <0x1>; ++ compatible = "fsl-i2c"; ++ reg = <0x3100 0x100>; ++ interrupts = <0x2b 0x2>; ++ interrupt-parent = <&MPIC>; ++ dfsrr; ++ fan@1b { ++ compatible = "maxim,max6650"; ++ reg = <0x1b>; ++ }; ++ fan@1f { ++ compatible = "maxim,max6650"; ++ reg = <0x1f>; ++ }; ++ fan@48 { ++ compatible = "maxim,max6650"; ++ reg = <0x48>; ++ }; ++ fan@4b { ++ compatible = "maxim,max6650"; ++ reg = <0x4b>; ++ }; ++ hotswap@40 { ++ compatible = "lt,ltc4215"; ++ reg = <0x40>; ++ }; ++ hotswap@42 { ++ compatible = "lt,ltc4215"; ++ reg = <0x42>; ++ }; ++ tmon@49 { ++ compatible = "ti,tmp75"; ++ reg = <0x49>; ++ }; ++ tmon@4a { ++ compatible = "ti,tmp75"; ++ reg = <0x4a>; ++ }; ++ tmon@4c { ++ compatible = "ti,tmp75"; ++ reg = <0x4c>; ++ }; ++ tmon@4d { ++ compatible = "ti,tmp75"; ++ reg = <0x4d>; ++ }; ++ psu_eeprom@50 { ++ read-only; ++ label = "psu2_eeprom"; ++ compatible = "at,24c08"; ++ reg = <0x50>; ++ }; ++ psu_eeprom@54 { ++ read-only; ++ label = "psu1_eeprom"; ++ compatible = "at,24c08"; ++ reg = <0x54>; ++ }; ++ }; ++ SERIAL0: serial@4500 { ++ cell-index = <0x0>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4500 0x100>; ++ clock-frequency = <0x0>; ++ interrupts = <0x2a 0x2>; ++ interrupt-parent = <&MPIC>; ++ }; ++ SERIAL1: serial@4600 { ++ cell-index = <0x1>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4600 0x100>; ++ clock-frequency = <0x0>; ++ interrupts = <0x2a 0x2>; ++ interrupt-parent = <&MPIC>; ++ }; ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,p2020-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <0x20>; ++ cache-size = <0x80000>; ++ interrupt-parent = <&MPIC>; ++ interrupts = <0x10 0x2>; ++ }; ++ MDIO1: mdio@24520 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++ PHY1: ethernet-phy@1 { ++ reg = <0x1>; ++ device_type = "ethernet-phy"; ++ }; ++ TBI1: tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ENET2: ethernet@26000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ cell-index = <0x1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x26000 0x1000>; ++ ranges = <0x0 0x26000 0x1000>; ++ interrupts = < ++ 0x1f 0x2 ++ 0x20 0x2 ++ 0x21 0x2>; ++ interrupt-parent = <&MPIC>; ++ tbi-handle = <&TBI2>; ++ phy-handle = <&PHY1>; ++ phy-connection-type = "sgmii"; ++ }; ++ MDIO2: mdio@26520 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ compatible = "fsl,gianfar-tbi"; ++ reg = <0x520 0x20>; ++ TBI2: tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ SDHCI: sdhci@2e000 { ++ compatible = "fsl,p2020-esdhc", "fsl,esdhc"; ++ reg = <0x2e000 0x1000>; ++ interrupts = <0x48 0x2>; ++ interrupt-parent = <&MPIC>; ++ clock-frequency = <0x0>; ++ // P2020 requires auto-cmd12 ++ sdhci,auto-cmd12; ++ }; ++ MPIC: pic@40000 { ++ interrupt-controller; ++ #address-cells = <0x0>; ++ #interrupt-cells = <0x2>; ++ reg = <0x40000 0x40000>; ++ compatible = "chrp,open-pic"; ++ device_type = "open-pic"; ++ }; ++ msi@41600 { ++ compatible = "fsl,mpic-msi"; ++ reg = <0x41600 0x80>; ++ msi-available-ranges = <0x0 0x100>; ++ interrupts = < ++ 0xe0 0x0 ++ 0xe1 0x0 ++ 0xe2 0x0 ++ 0xe3 0x0 ++ 0xe4 0x0 ++ 0xe5 0x0 ++ 0xe6 0x0 ++ 0xe7 0x0>; ++ interrupt-parent = <&MPIC>; ++ }; ++ global-utilities@e0000 { ++ compatible = "fsl,p2020-guts", "fsl,mpc8548-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ }; ++ PCI2: pcie@ffe0a000 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #interrupt-cells = <0x1>; ++ #size-cells = <0x2>; ++ #address-cells = <0x3>; ++ reg = <0x0 0xffe0a000 0x0 0x1000>; ++ bus-range = <0x0 0xff>; ++ ranges = <0x2000000 0x0 0xc0000000 0x0 0xc0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0x0 0xffc20000 0x0 0x00010000>; ++ clock-frequency = <0x5f5e100>; ++ interrupt-parent = <&MPIC>; ++ interrupts = <0x1a 0x2>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0x0 0x0 0x0 0x1 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x2 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x3 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x4 &MPIC 0x0 0x1>; ++ ++ ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <0x2>; ++ #address-cells = <0x3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0xc0000000 0x2000000 0x0 0xc0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0x1000000 0x0 0x00000000 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/dni_c7448n.dts b/arch/powerpc/boot/dts/dni_c7448n.dts +new file mode 100644 +index 0000000..f33b3b6 +--- /dev/null ++++ b/arch/powerpc/boot/dts/dni_c7448n.dts +@@ -0,0 +1,327 @@ ++/* ++ * Delta Networks, Inc. C7448N Device Tree Source ++ * ++ * Copyright 2014, Cumulus Networks, 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. ++ * ++ */ ++/dts-v1/; ++ ++/ { ++ model = "dni,c7448n"; ++ compatible = "dni,c7448n"; ++ #address-cells = <0x2>; ++ #size-cells = <0x2>; ++ aliases { ++ ethernet0 = &ENET2; ++ serial0 = &SERIAL0; ++ serial1 = &SERIAL1; ++ pci2 = &PCI2; ++ }; ++ cpus { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ PowerPC,P2020@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <0x1>; ++ }; ++ PowerPC,P2020@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <0x1>; ++ }; ++ }; ++ memory { ++ device_type = "memory"; ++ }; ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ mass_storage { ++ device = "mmcblk0"; ++ }; ++ localbus@ffe05000 { ++ #address-cells = <0x2>; ++ #size-cells = <0x1>; ++ compatible = "fsl,p2020-elbc", "fsl,elbc", "simple-bus"; ++ reg = <0x0 0xffe05000 0x0 0x00001000>; ++ interrupts = <19 0x2>; ++ interrupt-parent = <&MPIC>; ++ ranges = <0x0 0x0 0x0 0xe8000000 0x8000000 ++ 0x1 0x0 0x0 0xffdf0000 0x0000100>; ++ nor@0,0 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x8000000>; ++ bank-width = <0x2>; ++ device-width = <0x2>; ++ byteswap; ++ partition@0 { ++ /* Entire flash minus (u-boot + onie) */ ++ reg = <0x00000000 0x07b60000>; ++ label = "open"; ++ }; ++ partition@1 { ++ /* 4MB onie */ ++ reg = <0x07b60000 0x00400000>; ++ label = "onie"; ++ }; ++ partition@2 { ++ /* 128KB, 1 sector */ ++ reg = <0x07f60000 0x00020000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@3 { ++ /* 512KB u-boot */ ++ reg = <0x07f80000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ cpld@1,0 { ++ compatible = "dni,c7448n-cpld"; ++ reg = <0x1 0x0 0x0000100>; ++ }; ++ }; ++ soc@ffe00000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ device_type = "soc"; ++ compatible = "fsl,p2020-immr", "simple-bus"; ++ ranges = <0x0 0x0 0xffe00000 0x100000>; ++ bus-frequency = <0x0>; ++ memory-controller@2000 { ++ compatible = "fsl,p2020-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupt-parent = <&MPIC>; ++ interrupts = <0x12 0x2>; ++ }; ++ I2C0: i2c@3000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ cell-index = <0x0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <0x2b 0x2>; ++ interrupt-parent = <&MPIC>; ++ dfsrr; ++ rtc@68 { ++ compatible = "stm,m41st85"; ++ reg = <0x68>; ++ }; ++ board_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "board_eeprom"; ++ }; ++ spd@52 { ++ read-only; ++ compatible = "at,spd"; ++ reg = <0x52>; ++ }; ++ }; ++ I2C1: i2c@3100 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ cell-index = <0x1>; ++ compatible = "fsl-i2c"; ++ reg = <0x3100 0x100>; ++ interrupts = <0x2b 0x2>; ++ interrupt-parent = <&MPIC>; ++ dfsrr; ++ fan@29 { ++ compatible = "maxim,max6620"; ++ reg = <0x29>; ++ }; ++ hotswap@40 { ++ compatible = "lt,ltc4215"; ++ reg = <0x40>; ++ }; ++ hotswap@42 { ++ compatible = "lt,ltc4215"; ++ reg = <0x42>; ++ }; ++ tmon@49 { ++ compatible = "ti,tmp75"; ++ reg = <0x49>; ++ }; ++ tmon@4a { ++ compatible = "ti,tmp75"; ++ reg = <0x4a>; ++ }; ++ tmon@4b { ++ compatible = "ti,tmp75"; ++ reg = <0x4b>; ++ }; ++ tmon@4c { ++ compatible = "ti,tmp75"; ++ reg = <0x4c>; ++ }; ++ psu2_eeprom@50 { ++ read-only; ++ label = "psu2_eeprom"; ++ compatible = "at,24c02"; ++ reg = <0x50>; ++ }; ++ psu1_eeprom@51 { ++ read-only; ++ label = "psu1_eeprom"; ++ compatible = "at,24c02"; ++ reg = <0x51>; ++ }; ++ psu2_fan@59 { ++ compatible = "dni_dps460"; ++ reg = <0x59>; ++ }; ++ psu1_fan@58 { ++ compatible = "dni_dps460"; ++ reg = <0x58>; ++ }; ++ }; ++ SERIAL0: serial@4500 { ++ cell-index = <0x0>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4500 0x100>; ++ clock-frequency = <0x0>; ++ interrupts = <0x2a 0x2>; ++ interrupt-parent = <&MPIC>; ++ }; ++ SERIAL1: serial@4600 { ++ cell-index = <0x1>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4600 0x100>; ++ clock-frequency = <0x0>; ++ interrupts = <0x2a 0x2>; ++ interrupt-parent = <&MPIC>; ++ }; ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,p2020-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <0x20>; ++ cache-size = <0x80000>; ++ interrupt-parent = <&MPIC>; ++ interrupts = <0x10 0x2>; ++ }; ++ MDIO1: mdio@24520 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++ PHY1: ethernet-phy@1 { ++ reg = <0x1>; ++ device_type = "ethernet-phy"; ++ }; ++ TBI1: tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ENET2: ethernet@26000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ cell-index = <0x1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x26000 0x1000>; ++ ranges = <0x0 0x26000 0x1000>; ++ interrupts = < ++ 0x1f 0x2 ++ 0x20 0x2 ++ 0x21 0x2>; ++ interrupt-parent = <&MPIC>; ++ tbi-handle = <&TBI2>; ++ phy-handle = <&PHY1>; ++ phy-connection-type = "sgmii"; ++ }; ++ MDIO2: mdio@26520 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ compatible = "fsl,gianfar-tbi"; ++ reg = <0x520 0x20>; ++ TBI2: tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ SDHCI: sdhci@2e000 { ++ compatible = "fsl,p2020-esdhc", "fsl,esdhc"; ++ reg = <0x2e000 0x1000>; ++ interrupts = <0x48 0x2>; ++ interrupt-parent = <&MPIC>; ++ clock-frequency = <0x0>; ++ // P2020 requires auto-cmd12 ++ sdhci,auto-cmd12; ++ }; ++ MPIC: pic@40000 { ++ interrupt-controller; ++ #address-cells = <0x0>; ++ #interrupt-cells = <0x2>; ++ reg = <0x40000 0x40000>; ++ compatible = "chrp,open-pic"; ++ device_type = "open-pic"; ++ }; ++ msi@41600 { ++ compatible = "fsl,mpic-msi"; ++ reg = <0x41600 0x80>; ++ msi-available-ranges = <0x0 0x100>; ++ interrupts = < ++ 0xe0 0x0 ++ 0xe1 0x0 ++ 0xe2 0x0 ++ 0xe3 0x0 ++ 0xe4 0x0 ++ 0xe5 0x0 ++ 0xe6 0x0 ++ 0xe7 0x0>; ++ interrupt-parent = <&MPIC>; ++ }; ++ global-utilities@e0000 { ++ compatible = "fsl,p2020-guts", "fsl,mpc8548-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ }; ++ PCI2: pcie@ffe0a000 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #interrupt-cells = <0x1>; ++ #size-cells = <0x2>; ++ #address-cells = <0x3>; ++ reg = <0x0 0xffe0a000 0x0 0x1000>; ++ bus-range = <0x0 0xff>; ++ ranges = <0x2000000 0x0 0xc0000000 0x0 0xc0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0x0 0xffc20000 0x0 0x00010000>; ++ clock-frequency = <0x5f5e100>; ++ interrupt-parent = <&MPIC>; ++ interrupts = <0x1a 0x2>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0x0 0x0 0x0 0x1 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x2 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x3 &MPIC 0x0 0x1 ++ 0x0 0x0 0x0 0x4 &MPIC 0x0 0x1>; ++ ++ ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <0x2>; ++ #address-cells = <0x3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0xc0000000 0x2000000 0x0 0xc0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0x1000000 0x0 0x00000000 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi +new file mode 100644 +index 0000000..0d13641 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi +@@ -0,0 +1,292 @@ ++/* ++ * B4420 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * This software is provided by Freescale Semiconductor "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 Freescale Semiconductor 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. ++ */ ++ ++&ifc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,ifc", "simple-bus"; ++ interrupts = <25 2 0 0>; ++}; ++ ++/* controller at 0x200000 */ ++&pci0 { ++ compatible = "fsl,b4420-pcie", "fsl,qoriq-pcie-v2.4"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ interrupts = <20 2 0 0>; ++ pcie@0 { ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <20 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 40 1 0 0 ++ 0000 0 0 2 &mpic 1 1 0 0 ++ 0000 0 0 3 &mpic 2 1 0 0 ++ 0000 0 0 4 &mpic 3 1 0 0 ++ >; ++ }; ++}; ++ ++&bportals { ++/include/ "qoriq-bman2-portals.dtsi" ++}; ++&qportals { ++/include/ "qoriq-qman2-portals.dtsi" ++}; ++ ++&dcsr { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,dcsr", "simple-bus"; ++ ++ dcsr-epu@0 { ++ compatible = "fsl,b4420-dcsr-epu", "fsl,dcsr-epu"; ++ interrupts = <52 2 0 0 ++ 84 2 0 0 ++ 85 2 0 0 ++ 94 2 0 0 ++ 95 2 0 0>; ++ reg = <0x0 0x1000>; ++ }; ++ dcsr-npc { ++ compatible = "fsl,b4420-dcsr-cnpc", "fsl,dcsr-cnpc"; ++ reg = <0x1000 0x1000 0x1002000 0x10000>; ++ }; ++ dcsr-nxc@2000 { ++ compatible = "fsl,dcsr-nxc"; ++ reg = <0x2000 0x1000>; ++ }; ++ dcsr-corenet { ++ compatible = "fsl,dcsr-corenet"; ++ reg = <0x8000 0x1000 0x1A000 0x1000>; ++ }; ++ dcsr-dpaa@9000 { ++ compatible = "fsl,b4420-dcsr-dpaa", "fsl,dcsr-dpaa"; ++ reg = <0x9000 0x1000>; ++ }; ++ dcsr-ocn@11000 { ++ compatible = "fsl,b4420-dcsr-ocn", "fsl,dcsr-ocn"; ++ reg = <0x11000 0x1000>; ++ }; ++ dcsr-ddr@12000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr1>; ++ reg = <0x12000 0x1000>; ++ }; ++ dcsr-nal@18000 { ++ compatible = "fsl,b4420-dcsr-nal", "fsl,dcsr-nal"; ++ reg = <0x18000 0x1000>; ++ }; ++ dcsr-rcpm@22000 { ++ compatible = "fsl,b4420-dcsr-rcpm", "fsl,dcsr-rcpm"; ++ reg = <0x22000 0x1000>; ++ }; ++ dcsr-snpc@30000 { ++ compatible = "fsl,b4420-dcsr-snpc", "fsl,dcsr-snpc"; ++ reg = <0x30000 0x1000 0x1022000 0x10000>; ++ }; ++ dcsr-snpc@31000 { ++ compatible = "fsl,b4420-dcsr-snpc", "fsl,dcsr-snpc"; ++ reg = <0x31000 0x1000 0x1042000 0x10000>; ++ }; ++ dcsr-cpu-sb-proxy@100000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu0>; ++ reg = <0x100000 0x1000 0x101000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@108000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu1>; ++ reg = <0x108000 0x1000 0x109000 0x1000>; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "simple-bus"; ++ ++ soc-sram-error { ++ compatible = "fsl,soc-sram-error"; ++ interrupts = <16 2 1 2>; ++ }; ++ ++ corenet-law@0 { ++ compatible = "fsl,corenet-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <32>; ++ }; ++ ++ ddr1: memory-controller@8000 { ++ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller"; ++ reg = <0x8000 0x1000>; ++ interrupts = <16 2 1 8>; ++ }; ++ ++ cpc: l3-cache-controller@10000 { ++ compatible = "fsl,p5020-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache"; ++ reg = <0x10000 0x1000>; ++ interrupts = <16 2 1 4>; ++ }; ++ ++ corenet-cf@18000 { ++ compatible = "fsl,corenet-cf"; ++ reg = <0x18000 0x1000>; ++ interrupts = <16 2 1 0>; ++ fsl,ccf-num-csdids = <32>; ++ fsl,ccf-num-snoopids = <32>; ++ }; ++ ++ iommu@20000 { ++ compatible = "fsl,pamu"; ++ reg = <0x20000 0x4000>; ++ interrupts = < ++ 24 2 0 0 ++ 16 2 1 1>; ++ }; ++ ++/include/ "qoriq-qman1.dtsi" ++ ++ qman: qman@318000 { ++ interrupts = <16 2 1 28>; ++ }; ++ ++/include/ "qoriq-bman1.dtsi" ++ ++ bman: bman@31a000 { ++ interrupts = <16 2 1 29>; ++ }; ++ ++/include/ "qoriq-fman3-0.dtsi" ++/include/ "qoriq-fman3-0-1g-0.dtsi" ++/include/ "qoriq-fman3-0-1g-1.dtsi" ++/include/ "qoriq-fman3-0-1g-2.dtsi" ++/include/ "qoriq-fman3-0-1g-3.dtsi" ++ fman0: fman@400000 { ++ interrupts = < ++ 96 2 0 0 ++ 16 2 1 30>; ++ ++ /* tx - 1g - 0 */ ++ port@a8000 { ++ fsl,qman-channel-id = <0x802>; ++ }; ++ /* tx - 1g - 1 */ ++ port@a9000 { ++ fsl,qman-channel-id = <0x803>; ++ }; ++ /* tx - 1g - 2 */ ++ port@aa000 { ++ fsl,qman-channel-id = <0x804>; ++ }; ++ /* tx - 1g - 3 */ ++ port@ab000 { ++ fsl,qman-channel-id = <0x805>; ++ }; ++ ++ /* offline - 0 is not usable on B4420 */ ++ /* offline - 1 */ ++ port@82000 { ++ fsl,qman-channel-id = <0x809>; ++ }; ++ /* offline - 2 */ ++ port@83000 { ++ fsl,qman-channel-id = <0x80a>; ++ }; ++ /* offline - 3 */ ++ port@84000 { ++ fsl,qman-channel-id = <0x80b>; ++ }; ++ /* offline - 4 */ ++ port@85000 { ++ fsl,qman-channel-id = <0x80c>; ++ }; ++ /* offline - 5 */ ++ port@86000 { ++ fsl,qman-channel-id = <0x80d>; ++ }; ++ /* offline - 6 */ ++ port@87000 { ++ fsl,qman-channel-id = <0x80e>; ++ }; ++ }; ++ ++/include/ "qoriq-mpic.dtsi" ++ ++ guts: global-utilities@e0000 { ++ compatible = "fsl,b4420-device-config"; ++ reg = <0xe0000 0xe00>; ++ fsl,has-rstcr; ++ fsl,liodn-bits = <12>; ++ }; ++ ++ rcpm: global-utilities@e2000 { ++ compatible = "fsl,b4420-rcpm", "fsl,qoriq-rcpm-2"; ++ reg = <0xe2000 0x1000>; ++ }; ++ ++/include/ "qoriq-dma-0.dtsi" ++/include/ "qoriq-dma-1.dtsi" ++ ++/include/ "qonverge-usb2-dr-0.dtsi" ++ usb0: usb@210000 { ++ compatible = "fsl-usb2-dr-v2.4", "fsl-usb2-dr"; ++ }; ++ ++/include/ "qoriq-espi-0.dtsi" ++ spi@110000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "qoriq-esdhc-0.dtsi" ++ sdhc@114000 { ++ sdhci,auto-cmd12; ++ }; ++/include/ "qoriq-i2c-0.dtsi" ++/include/ "qoriq-i2c-1.dtsi" ++/include/ "qoriq-duart-0.dtsi" ++/include/ "qoriq-duart-1.dtsi" ++/include/ "qoriq-sec5.3-0.dtsi" ++ ++ L2: l2-cache-controller@c20000 { ++ next-level-cache = <&cpc>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi b/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi +new file mode 100644 +index 0000000..9493fb0 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi +@@ -0,0 +1,83 @@ ++/* ++ * B4420 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * This software is provided by Freescale Semiconductor "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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++/ { ++ compatible = "fsl,B4420"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ ccsr = &soc; ++ dcsr = &dcsr; ++ ++ serial0 = &serial0; ++ serial1 = &serial1; ++ serial2 = &serial2; ++ serial3 = &serial3; ++ pci0 = &pci0; ++ dma0 = &dma0; ++ dma1 = &dma1; ++ sdhc = &sdhc; ++ ++ fman0 = &fman0; ++ crypto = &crypto; ++ sec_jr0 = &sec_jr0; ++ sec_jr1 = &sec_jr1; ++ sec_jr2 = &sec_jr2; ++ sec_jr3 = &sec_jr3; ++ rtic_a = &rtic_a; ++ rtic_b = &rtic_b; ++ rtic_c = &rtic_c; ++ rtic_d = &rtic_d; ++ sec_mon = &sec_mon; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: PowerPC,e6500@0 { ++ device_type = "cpu"; ++ reg = <0 1>; ++ next-level-cache = <&L2>; ++ }; ++ cpu1: PowerPC,e6500@1 { ++ device_type = "cpu"; ++ reg = <2 3>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi +new file mode 100644 +index 0000000..818f652 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi +@@ -0,0 +1,356 @@ ++/* ++ * B4860 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&ifc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,ifc", "simple-bus"; ++ interrupts = <25 2 0 0>; ++}; ++ ++/* controller at 0x200000 */ ++&pci0 { ++ compatible = "fsl,b4860-pcie", "fsl,qoriq-pcie-v2.4"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ interrupts = <20 2 0 0>; ++ pcie@0 { ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <20 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 40 1 0 0 ++ 0000 0 0 2 &mpic 1 1 0 0 ++ 0000 0 0 3 &mpic 2 1 0 0 ++ 0000 0 0 4 &mpic 3 1 0 0 ++ >; ++ }; ++}; ++ ++&rio { ++ compatible = "fsl,srio"; ++ interrupts = <16 2 1 11>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ port1 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <1>; ++ }; ++ ++ port2 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <2>; ++ }; ++}; ++ ++&bportals { ++/include/ "qoriq-bman2-portals.dtsi" ++}; ++&qportals { ++/include/ "qoriq-qman2-portals.dtsi" ++}; ++ ++&dcsr { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,dcsr", "simple-bus"; ++ ++ dcsr-epu@0 { ++ compatible = "fsl,b4860-dcsr-epu", "fsl,dcsr-epu"; ++ interrupts = <52 2 0 0 ++ 84 2 0 0 ++ 85 2 0 0 ++ 94 2 0 0 ++ 95 2 0 0>; ++ reg = <0x0 0x1000>; ++ }; ++ dcsr-npc { ++ compatible = "fsl,b4860-dcsr-cnpc", "fsl,dcsr-cnpc"; ++ reg = <0x1000 0x1000 0x1002000 0x10000>; ++ }; ++ dcsr-nxc@2000 { ++ compatible = "fsl,dcsr-nxc"; ++ reg = <0x2000 0x1000>; ++ }; ++ dcsr-corenet { ++ compatible = "fsl,dcsr-corenet"; ++ reg = <0x8000 0x1000 0x1A000 0x1000>; ++ }; ++ dcsr-dpaa@9000 { ++ compatible = "fsl,b4860-dcsr-dpaa", "fsl,dcsr-dpaa"; ++ reg = <0x9000 0x1000>; ++ }; ++ dcsr-ocn@11000 { ++ compatible = "fsl,b4860-dcsr-ocn", "fsl,dcsr-ocn"; ++ reg = <0x11000 0x1000>; ++ }; ++ dcsr-ddr@12000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr1>; ++ reg = <0x12000 0x1000>; ++ }; ++ dcsr-ddr@13000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr2>; ++ reg = <0x13000 0x1000>; ++ }; ++ dcsr-nal@18000 { ++ compatible = "fsl,b4860-dcsr-nal", "fsl,dcsr-nal"; ++ reg = <0x18000 0x1000>; ++ }; ++ dcsr-rcpm@22000 { ++ compatible = "fsl,b4860-dcsr-rcpm", "fsl,dcsr-rcpm"; ++ reg = <0x22000 0x1000>; ++ }; ++ dcsr-snpc@30000 { ++ compatible = "fsl,b4860-dcsr-snpc", "fsl,dcsr-snpc"; ++ reg = <0x30000 0x1000 0x1022000 0x10000>; ++ }; ++ dcsr-snpc@31000 { ++ compatible = "fsl,b4860-dcsr-snpc", "fsl,dcsr-snpc"; ++ reg = <0x31000 0x1000 0x1042000 0x10000>; ++ }; ++ dcsr-cpu-sb-proxy@100000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu0>; ++ reg = <0x100000 0x1000 0x101000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@108000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu1>; ++ reg = <0x108000 0x1000 0x109000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@110000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu2>; ++ reg = <0x110000 0x1000 0x111000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@118000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu3>; ++ reg = <0x118000 0x1000 0x119000 0x1000>; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "simple-bus"; ++ ++ soc-sram-error { ++ compatible = "fsl,soc-sram-error"; ++ interrupts = <16 2 1 2>; ++ }; ++ ++ corenet-law@0 { ++ compatible = "fsl,corenet-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <32>; ++ }; ++ ++ ddr1: memory-controller@8000 { ++ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller"; ++ reg = <0x8000 0x1000>; ++ interrupts = <16 2 1 8>; ++ }; ++ ++ ddr2: memory-controller@9000 { ++ compatible = "fsl,qoriq-memory-controller-v4.5","fsl,qoriq-memory-controller"; ++ reg = <0x9000 0x1000>; ++ interrupts = <16 2 1 9>; ++ }; ++ ++ cpc: l3-cache-controller@10000 { ++ compatible = "fsl,p5020-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache"; ++ reg = <0x10000 0x1000 ++ 0x11000 0x1000>; ++ interrupts = <16 2 1 4 ++ 16 2 1 5>; ++ }; ++ ++ corenet-cf@18000 { ++ compatible = "fsl,corenet-cf"; ++ reg = <0x18000 0x1000>; ++ interrupts = <16 2 1 0>; ++ fsl,ccf-num-csdids = <32>; ++ fsl,ccf-num-snoopids = <32>; ++ }; ++ ++ iommu@20000 { ++ compatible = "fsl,pamu-v1.0", "fsl,pamu"; ++ reg = <0x20000 0x4000>; ++ interrupts = < ++ 24 2 0 0 ++ 16 2 1 1>; ++ }; ++ ++/include/ "qoriq-qman1.dtsi" ++ ++ qman: qman@318000 { ++ interrupts = <16 2 1 28>; ++ }; ++ ++/include/ "qoriq-bman1.dtsi" ++ ++ bman: bman@31a000 { ++ interrupts = <16 2 1 29>; ++ }; ++ ++/include/ "qoriq-rman-0.dtsi" ++ rman: rman@1e0000 { ++ fsl,qman-channels-id = <0x820 0x821>; ++ }; ++ ++/include/ "qoriq-fman3-0.dtsi" ++/include/ "qoriq-fman3-0-1g-0.dtsi" ++/include/ "qoriq-fman3-0-1g-1.dtsi" ++/include/ "qoriq-fman3-0-1g-2.dtsi" ++/include/ "qoriq-fman3-0-1g-3.dtsi" ++/include/ "qoriq-fman3-0-1g-4.dtsi" ++/include/ "qoriq-fman3-0-1g-5.dtsi" ++/include/ "qoriq-fman3-0-10g-0.dtsi" ++/include/ "qoriq-fman3-0-10g-1.dtsi" ++ fman0: fman@400000 { ++ interrupts = < ++ 96 2 0 0 ++ 16 2 1 30>; ++ ++ /* tx - 1g - 0 */ ++ port@a8000 { ++ fsl,qman-channel-id = <0x802>; ++ }; ++ /* tx - 1g - 1 */ ++ port@a9000 { ++ fsl,qman-channel-id = <0x803>; ++ }; ++ /* tx - 1g - 2 */ ++ port@aa000 { ++ fsl,qman-channel-id = <0x804>; ++ }; ++ /* tx - 1g - 3 */ ++ port@ab000 { ++ fsl,qman-channel-id = <0x805>; ++ }; ++ /* tx - 1g - 4 */ ++ port@ac000 { ++ fsl,qman-channel-id = <0x806>; ++ }; ++ /* tx - 1g - 5 */ ++ port@ad000 { ++ fsl,qman-channel-id = <0x807>; ++ }; ++ /* offline - 0 is not usable on B4860 */ ++ /* offline - 1 */ ++ port@82000 { ++ fsl,qman-channel-id = <0x809>; ++ }; ++ /* offline - 2 */ ++ port@83000 { ++ fsl,qman-channel-id = <0x80a>; ++ }; ++ /* offline - 3 */ ++ port@84000 { ++ fsl,qman-channel-id = <0x80b>; ++ }; ++ /* offline - 4 */ ++ port@85000 { ++ fsl,qman-channel-id = <0x80c>; ++ }; ++ /* offline - 5 */ ++ port@86000 { ++ fsl,qman-channel-id = <0x80d>; ++ }; ++ /* offline - 6 */ ++ port@87000 { ++ fsl,qman-channel-id = <0x80e>; ++ }; ++ }; ++ ++/include/ "qoriq-mpic.dtsi" ++ ++ guts: global-utilities@e0000 { ++ compatible = "fsl,b4860-device-config"; ++ reg = <0xe0000 0xe00>; ++ fsl,has-rstcr; ++ fsl,liodn-bits = <12>; ++ }; ++ ++ clockgen: global-utilities@e1000 { ++ compatible = "fsl,b4860-clockgen", "fsl,qoriq-clockgen-2"; ++ reg = <0xe1000 0x1000>; ++ }; ++ ++ rcpm: global-utilities@e2000 { ++ compatible = "fsl,b4860-rcpm", "fsl,qoriq-rcpm-2"; ++ reg = <0xe2000 0x1000>; ++ }; ++ ++/include/ "qoriq-dma-0.dtsi" ++/include/ "qoriq-dma-1.dtsi" ++ ++/include/ "qonverge-usb2-dr-0.dtsi" ++ usb0: usb@210000 { ++ compatible = "fsl-usb2-dr-v2.4", "fsl-usb2-dr"; ++ }; ++ ++/include/ "qoriq-espi-0.dtsi" ++ spi@110000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "qoriq-esdhc-0.dtsi" ++ sdhc@114000 { ++ sdhci,auto-cmd12; ++ }; ++/include/ "qoriq-i2c-0.dtsi" ++/include/ "qoriq-i2c-1.dtsi" ++/include/ "qoriq-duart-0.dtsi" ++/include/ "qoriq-duart-1.dtsi" ++/include/ "qoriq-sec5.3-0.dtsi" ++ ++ L2: l2-cache-controller@c20000 { ++ next-level-cache = <&cpc>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi b/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi +new file mode 100644 +index 0000000..eb441da +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi +@@ -0,0 +1,93 @@ ++/* ++ * B4860 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++/ { ++ compatible = "fsl,B4860"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ ccsr = &soc; ++ dcsr = &dcsr; ++ ++ serial0 = &serial0; ++ serial1 = &serial1; ++ serial2 = &serial2; ++ serial3 = &serial3; ++ pci0 = &pci0; ++ dma0 = &dma0; ++ dma1 = &dma1; ++ sdhc = &sdhc; ++ ++ fman0 = &fman0; ++ crypto = &crypto; ++ sec_jr0 = &sec_jr0; ++ sec_jr1 = &sec_jr1; ++ sec_jr2 = &sec_jr2; ++ sec_jr3 = &sec_jr3; ++ rtic_a = &rtic_a; ++ rtic_b = &rtic_b; ++ rtic_c = &rtic_c; ++ rtic_d = &rtic_d; ++ sec_mon = &sec_mon; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: PowerPC,e6500@0 { ++ device_type = "cpu"; ++ reg = <0 1>; ++ next-level-cache = <&L2>; ++ }; ++ cpu1: PowerPC,e6500@1 { ++ device_type = "cpu"; ++ reg = <2 3>; ++ next-level-cache = <&L2>; ++ }; ++ cpu2: PowerPC,e6500@2 { ++ device_type = "cpu"; ++ reg = <4 5>; ++ next-level-cache = <&L2>; ++ }; ++ cpu3: PowerPC,e6500@3 { ++ device_type = "cpu"; ++ reg = <6 7>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi b/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi +new file mode 100644 +index 0000000..5180d9d +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi +@@ -0,0 +1,193 @@ ++/* ++ * BSC9131 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&ifc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,ifc", "simple-bus"; ++ interrupts = <16 2 0 0 20 2 0 0>; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,bsc9131-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <12>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,bsc9131-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,bsc9131-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-i2c-0.dtsi" ++ i2c@3000 { ++ interrupts = <17 2 0 0>; ++ }; ++ ++/include/ "pq3-i2c-1.dtsi" ++ i2c@3100 { ++ interrupts = <17 2 0 0>; ++ }; ++ ++/include/ "pq3-duart-0.dtsi" ++ serial0: serial@4500 { ++ interrupts = <18 2 0 0>; ++ }; ++ ++ serial1: serial@4600 { ++ interrupts = <18 2 0 0 >; ++ }; ++/include/ "pq3-espi-0.dtsi" ++ spi0: spi@7000 { ++ fsl,espi-num-chipselects = <1>; ++ interrupts = <22 0x2 0 0>; ++ }; ++ ++/include/ "pq3-gpio-0.dtsi" ++ gpio-controller@f000 { ++ interrupts = <19 0x2 0 0>; ++ }; ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,bsc9131-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x40000>; // L2,256K ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++ ++dma@21300 { ++ ++ dma-channel@0 { ++ interrupts = <62 2 0 0>; ++ }; ++ ++ dma-channel@80 { ++ interrupts = <63 2 0 0>; ++ }; ++ ++ dma-channel@100 { ++ interrupts = <64 2 0 0>; ++ }; ++ ++ dma-channel@180 { ++ interrupts = <65 2 0 0>; ++ }; ++}; ++ ++/include/ "pq3-usb2-dr-0.dtsi" ++usb@22000 { ++ compatible = "fsl-usb2-dr","fsl-usb2-dr-v2.2"; ++ interrupts = <40 0x2 0 0>; ++}; ++ ++/include/ "pq3-esdhc-0.dtsi" ++ sdhc@2e000 { ++ fsl,sdhci-auto-cmd12; ++ interrupts = <41 0x2 0 0>; ++ }; ++ ++/include/ "pq3-sec4.4-0.dtsi" ++crypto@30000 { ++ interrupts = <57 2 0 0>; ++ ++ sec_jr0: jr@1000 { ++ interrupts = <58 2 0 0>; ++ }; ++ ++ sec_jr1: jr@2000 { ++ interrupts = <59 2 0 0>; ++ }; ++ ++ sec_jr2: jr@3000 { ++ interrupts = <60 2 0 0>; ++ }; ++ ++ sec_jr3: jr@4000 { ++ interrupts = <61 2 0 0>; ++ }; ++}; ++ ++/include/ "pq3-mpic.dtsi" ++ ++timer@41100 { ++ compatible = "fsl,mpic-v1.2-msgr", "fsl,mpic-msg"; ++ reg = <0x41400 0x200>; ++ interrupts = < ++ 0xb0 2 ++ 0xb1 2 ++ 0xb2 2 ++ 0xb3 2>; ++}; ++ ++/include/ "pq3-etsec2-0.dtsi" ++enet0: ethernet@b0000 { ++ queue-group@b0000 { ++ fsl,rx-bit-map = <0xff>; ++ fsl,tx-bit-map = <0xff>; ++ interrupts = <26 2 0 0 27 2 0 0 28 2 0 0>; ++ }; ++}; ++ ++/include/ "pq3-etsec2-1.dtsi" ++enet1: ethernet@b1000 { ++ queue-group@b1000 { ++ fsl,rx-bit-map = <0xff>; ++ fsl,tx-bit-map = <0xff>; ++ interrupts = <33 2 0 0 34 2 0 0 35 2 0 0>; ++ }; ++}; ++ ++global-utilities@e0000 { ++ compatible = "fsl,bsc9131-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi b/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi +new file mode 100644 +index 0000000..743e4ae +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi +@@ -0,0 +1,59 @@ ++/* ++ * BSC9131 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++/ { ++ compatible = "fsl,BSC9131"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,BSC9131@0 { ++ device_type = "cpu"; ++ compatible = "fsl,e500v2"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi +new file mode 100644 +index 0000000..870c653 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi +@@ -0,0 +1,58 @@ ++/* ++ * e500mc Power ISA Device Tree Source (include) ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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. ++ */ ++ ++/ { ++ cpus { ++ power-isa-version = "2.06"; ++ power-isa-b; // Base ++ power-isa-e; // Embedded ++ power-isa-atb; // Alternate Time Base ++ power-isa-cs; // Cache Specification ++ power-isa-ds; // Decorated Storage ++ power-isa-e.ed; // Embedded.Enhanced Debug ++ power-isa-e.pd; // Embedded.External PID ++ power-isa-e.hv; // Embedded.Hypervisor ++ power-isa-e.le; // Embedded.Little-Endian ++ power-isa-e.pm; // Embedded.Performance Monitor ++ power-isa-e.pc; // Embedded.Processor Control ++ power-isa-ecl; // Embedded Cache Locking ++ power-isa-exp; // External Proxy ++ power-isa-fp; // Floating Point ++ power-isa-fp.r; // Floating Point.Record ++ power-isa-mmc; // Memory Coherence ++ power-isa-scpm; // Store Conditional Page Mobility ++ power-isa-wt; // Wait ++ mmu-type = "power-embedded"; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/e500v2_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e500v2_power_isa.dtsi +new file mode 100644 +index 0000000..f492814 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/e500v2_power_isa.dtsi +@@ -0,0 +1,52 @@ ++/* ++ * e500v2 Power ISA Device Tree Source (include) ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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. ++ */ ++ ++/ { ++ cpus { ++ power-isa-version = "2.03"; ++ power-isa-b; // Base ++ power-isa-e; // Embedded ++ power-isa-atb; // Alternate Time Base ++ power-isa-cs; // Cache Specification ++ power-isa-e.le; // Embedded.Little-Endian ++ power-isa-e.pm; // Embedded.Performance Monitor ++ power-isa-ecl; // Embedded Cache Locking ++ power-isa-mmc; // Memory Coherence ++ power-isa-sp; // Signal Processing Engine ++ power-isa-sp.fd; // SPE.Embedded Float Scalar Double ++ power-isa-sp.fs; // SPE.Embedded Float Scalar Single ++ power-isa-sp.fv; // SPE.Embedded Float Vector ++ mmu-type = "power-embedded"; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi +new file mode 100644 +index 0000000..3230212 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi +@@ -0,0 +1,59 @@ ++/* ++ * e5500 Power ISA Device Tree Source (include) ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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. ++ */ ++ ++/ { ++ cpus { ++ power-isa-version = "2.06"; ++ power-isa-b; // Base ++ power-isa-e; // Embedded ++ power-isa-atb; // Alternate Time Base ++ power-isa-cs; // Cache Specification ++ power-isa-ds; // Decorated Storage ++ power-isa-e.ed; // Embedded.Enhanced Debug ++ power-isa-e.pd; // Embedded.External PID ++ power-isa-e.hv; // Embedded.Hypervisor ++ power-isa-e.le; // Embedded.Little-Endian ++ power-isa-e.pm; // Embedded.Performance Monitor ++ power-isa-e.pc; // Embedded.Processor Control ++ power-isa-ecl; // Embedded Cache Locking ++ power-isa-exp; // External Proxy ++ power-isa-fp; // Floating Point ++ power-isa-fp.r; // Floating Point.Record ++ power-isa-mmc; // Memory Coherence ++ power-isa-scpm; // Store Conditional Page Mobility ++ power-isa-wt; // Wait ++ power-isa-64; // 64-bit ++ mmu-type = "power-embedded"; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/interlaken-lac-portals.dtsi b/arch/powerpc/boot/dts/fsl/interlaken-lac-portals.dtsi +new file mode 100644 +index 0000000..9cffccf +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/interlaken-lac-portals.dtsi +@@ -0,0 +1,156 @@ ++/* T4240 Interlaken LAC Portal device tree stub with 24 portals. ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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. ++ */ ++ ++#address-cells = <0x1>; ++#size-cells = <0x1>; ++compatible = "fsl,interlaken-lac-portals"; ++ ++lportal0: lac-portal@0 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x0 0x1000>; ++}; ++ ++lportal1: lac-portal@1000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x1000 0x1000>; ++}; ++ ++lportal2: lac-portal@2000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x2000 0x1000>; ++}; ++ ++lportal3: lac-portal@3000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x3000 0x1000>; ++}; ++ ++lportal4: lac-portal@4000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x4000 0x1000>; ++}; ++ ++lportal5: lac-portal@5000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x5000 0x1000>; ++}; ++ ++lportal6: lac-portal@6000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x6000 0x1000>; ++}; ++ ++lportal7: lac-portal@7000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x7000 0x1000>; ++}; ++ ++lportal8: lac-portal@8000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x8000 0x1000>; ++}; ++ ++lportal9: lac-portal@9000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x9000 0x1000>; ++}; ++ ++lportal10: lac-portal@A000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0xA000 0x1000>; ++}; ++ ++lportal11: lac-portal@B000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0xB000 0x1000>; ++}; ++ ++lportal12: lac-portal@C000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0xC000 0x1000>; ++}; ++ ++lportal13: lac-portal@D000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0xD000 0x1000>; ++}; ++ ++lportal14: lac-portal@E000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0xE000 0x1000>; ++}; ++ ++lportal15: lac-portal@F000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0xF000 0x1000>; ++}; ++ ++lportal16: lac-portal@10000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x10000 0x1000>; ++}; ++ ++lportal17: lac-portal@11000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x11000 0x1000>; ++}; ++ ++lportal18: lac-portal@1200 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x12000 0x1000>; ++}; ++ ++lportal19: lac-portal@13000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x13000 0x1000>; ++}; ++ ++lportal20: lac-portal@14000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x14000 0x1000>; ++}; ++ ++lportal21: lac-portal@15000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x15000 0x1000>; ++}; ++ ++lportal22: lac-portal@16000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x16000 0x1000>; ++}; ++ ++lportal23: lac-portal@17000 { ++ compatible = "fsl,interlaken-lac-portal-v1.0"; ++ reg = <0x17000 0x1000>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/interlaken-lac.dtsi b/arch/powerpc/boot/dts/fsl/interlaken-lac.dtsi +new file mode 100644 +index 0000000..e820872 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/interlaken-lac.dtsi +@@ -0,0 +1,45 @@ ++/* ++ * T4 Interlaken Look-aside Controller (LAC) device tree stub ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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. ++ */ ++ ++lac: lac@229000 { ++ compatible = "fsl,interlaken-lac"; ++ reg = <0x229000 0x1000>; ++ interrupts = <16 2 1 18>; ++}; ++ ++lac-hv@228000 { ++ compatible = "fsl,interlaken-lac-hv"; ++ reg = <0x228000 0x1000>; ++ fsl,non-hv-node = <&lac>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi +new file mode 100644 +index 0000000..900f117 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi +@@ -0,0 +1,262 @@ ++/* ++ * MPC8536 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8536-elbc", "fsl,elbc", "simple-bus"; ++ interrupts = <19 2 0 0>; ++}; ++ ++/* controller at 0x8000 */ ++&pci0 { ++ compatible = "fsl,mpc8540-pci"; ++ device_type = "pci"; ++ interrupts = <24 0x2 0 0>; ++ bus-range = <0 0xff>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++}; ++ ++/* controller at 0x9000 */ ++&pci1 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <25 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <25 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x4 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x5 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x6 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x7 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0xa000 */ ++&pci2 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <26 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <26 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0xb000 */ ++&pci3 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <27 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <27 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x8 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x9 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0xa 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0xb 0x1 0x0 0x0 ++ >; ++ }; ++}; ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,mpc8536-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <12>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,mpc8536-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <17 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,mpc8536-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <18 2 0 0>; ++ }; ++ ++/include/ "pq3-i2c-0.dtsi" ++/include/ "pq3-i2c-1.dtsi" ++/include/ "pq3-duart-0.dtsi" ++ ++/include/ "pq3-espi-0.dtsi" ++ spi@7000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "pq3-gpio-0.dtsi" ++ ++ /* mark compat w/8572 to get some erratum treatment */ ++ gpio-controller@f000 { ++ compatible = "fsl,mpc8572-gpio", "fsl,pq3-gpio"; ++ }; ++ ++ sata@18000 { ++ compatible = "fsl,mpc8536-sata", "fsl,pq-sata"; ++ reg = <0x18000 0x1000>; ++ cell-index = <1>; ++ interrupts = <74 0x2 0 0>; ++ }; ++ ++ sata@19000 { ++ compatible = "fsl,mpc8536-sata", "fsl,pq-sata"; ++ reg = <0x19000 0x1000>; ++ cell-index = <2>; ++ interrupts = <41 0x2 0 0>; ++ }; ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,mpc8536-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x80000>; // L2, 512K ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++/include/ "pq3-etsec1-0.dtsi" ++ enet0: ethernet@24000 { ++ fsl,wake-on-filer; ++ fsl,pmc-handle = <&etsec1_clk>; ++ }; ++/include/ "pq3-etsec1-timer-0.dtsi" ++ ++ usb@22000 { ++ compatible = "fsl-usb2-mph-v1.2", "fsl,mpc8536-usb2-mph", "fsl-usb2-mph"; ++ reg = <0x22000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <28 0x2 0 0>; ++ }; ++ ++ usb@23000 { ++ compatible = "fsl-usb2-mph-v1.2", "fsl,mpc8536-usb2-mph", "fsl-usb2-mph"; ++ reg = <0x23000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <46 0x2 0 0>; ++ }; ++ ++ ptp_clock@24e00 { ++ interrupts = <68 2 0 0 69 2 0 0 70 2 0 0 71 2 0 0>; ++ }; ++ ++/include/ "pq3-etsec1-2.dtsi" ++ enet2: ethernet@26000 { ++ cell-index = <1>; ++ fsl,wake-on-filer; ++ fsl,pmc-handle = <&etsec3_clk>; ++ }; ++ ++ usb@2b000 { ++ compatible = "fsl,mpc8536-usb2-dr", "fsl-usb2-dr"; ++ reg = <0x2b000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <60 0x2 0 0>; ++ }; ++ ++/include/ "pq3-esdhc-0.dtsi" ++ sdhc@2e000 { ++ compatible = "fsl,mpc8536-esdhc", "fsl,esdhc"; ++ }; ++ ++/include/ "pq3-sec3.0-0.dtsi" ++/include/ "pq3-mpic.dtsi" ++/include/ "pq3-mpic-timer-B.dtsi" ++ ++ global-utilities@e0000 { ++ compatible = "fsl,mpc8536-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ ++/include/ "pq3-power.dtsi" ++ power@e0070 { ++ compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc"; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8536si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8536si-pre.dtsi +new file mode 100644 +index 0000000..152906f +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/mpc8536si-pre.dtsi +@@ -0,0 +1,66 @@ ++/* ++ * MPC8536 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500v2_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,MPC8536"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ ethernet0 = &enet0; ++ ethernet1 = &enet2; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ pci3 = &pci3; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,8536@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi +new file mode 100644 +index 0000000..ea7416a +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi +@@ -0,0 +1,193 @@ ++/* ++ * MPC8544 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8544-lbc", "fsl,pq3-localbus", "simple-bus"; ++ interrupts = <19 2 0 0>; ++}; ++ ++/* controller at 0x8000 */ ++&pci0 { ++ compatible = "fsl,mpc8540-pci"; ++ device_type = "pci"; ++ interrupts = <24 0x2 0 0>; ++ bus-range = <0 0xff>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++}; ++ ++/* controller at 0x9000 */ ++&pci1 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <25 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <25 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x4 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x5 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x6 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x7 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0xa000 */ ++&pci2 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <26 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <26 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0xb000 */ ++&pci3 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <27 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <27 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x8 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x9 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0xa 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0xb 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,mpc8544-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <10>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,mpc8544-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <17 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,mpc8544-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <18 2 0 0>; ++ }; ++ ++/include/ "pq3-i2c-0.dtsi" ++/include/ "pq3-i2c-1.dtsi" ++/include/ "pq3-duart-0.dtsi" ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,mpc8544-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x40000>; // L2, 256K ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++/include/ "pq3-etsec1-0.dtsi" ++/include/ "pq3-etsec1-2.dtsi" ++ ++ ethernet@26000 { ++ cell-index = <1>; ++ }; ++ ++/include/ "pq3-sec2.1-0.dtsi" ++/include/ "pq3-mpic.dtsi" ++ ++ global-utilities@e0000 { ++ compatible = "fsl,mpc8544-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ ++/include/ "pq3-power.dtsi" ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8544si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8544si-pre.dtsi +new file mode 100644 +index 0000000..5a69baf +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/mpc8544si-pre.dtsi +@@ -0,0 +1,66 @@ ++/* ++ * MPC8544 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500v2_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,MPC8544"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ ethernet0 = &enet0; ++ ethernet1 = &enet2; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ pci3 = &pci3; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,8544@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi +new file mode 100644 +index 0000000..dddb737 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi +@@ -0,0 +1,161 @@ ++/* ++ * MPC8548 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8548-lbc", "fsl,pq3-localbus", "simple-bus"; ++ interrupts = <19 2 0 0>; ++}; ++ ++/* controller at 0x8000 */ ++&pci0 { ++ compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci"; ++ device_type = "pci"; ++ interrupts = <24 0x2 0 0>; ++ bus-range = <0 0xff>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++}; ++ ++/* controller at 0x9000 */ ++&pci1 { ++ compatible = "fsl,mpc8540-pci"; ++ device_type = "pci"; ++ interrupts = <25 0x2 0 0>; ++ bus-range = <0 0xff>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++}; ++ ++/* controller at 0xa000 */ ++&pci2 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <26 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <26 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++&rio { ++ compatible = "fsl,srio"; ++ interrupts = <48 2 0 0>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ fsl,srio-rmu-handle = <&rmu>; ++ ranges; ++ ++ port1 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <1>; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,mpc8548-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <10>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,mpc8548-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <17 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,mpc8548-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <18 2 0 0>; ++ }; ++ ++/include/ "pq3-i2c-0.dtsi" ++/include/ "pq3-i2c-1.dtsi" ++/include/ "pq3-duart-0.dtsi" ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,mpc8548-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x80000>; // L2, 512K ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++/include/ "pq3-etsec1-0.dtsi" ++/include/ "pq3-etsec1-1.dtsi" ++/include/ "pq3-etsec1-2.dtsi" ++/include/ "pq3-etsec1-3.dtsi" ++ ++/include/ "pq3-sec2.1-0.dtsi" ++/include/ "pq3-mpic.dtsi" ++/include/ "pq3-rmu-0.dtsi" ++ ++ global-utilities@e0000 { ++ compatible = "fsl,mpc8548-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ ++/include/ "pq3-power.dtsi" ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi +new file mode 100644 +index 0000000..fc1ce97 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi +@@ -0,0 +1,67 @@ ++/* ++ * MPC8548 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500v2_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,MPC8548"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ ethernet3 = &enet3; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,8548@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8568si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8568si-post.dtsi +new file mode 100644 +index 0000000..64e7075 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/mpc8568si-post.dtsi +@@ -0,0 +1,270 @@ ++/* ++ * MPC8568 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8568-localbus", "fsl,pq3-localbus", "simple-bus"; ++ interrupts = <19 2 0 0>; ++ sleep = <&pmc 0x08000000>; ++}; ++ ++/* controller at 0x8000 */ ++&pci0 { ++ compatible = "fsl,mpc8540-pci"; ++ device_type = "pci"; ++ interrupts = <24 0x2 0 0>; ++ bus-range = <0 0xff>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ sleep = <&pmc 0x80000000>; ++}; ++ ++/* controller at 0xa000 */ ++&pci1 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <26 2 0 0>; ++ sleep = <&pmc 0x20000000>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <26 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++&rio { ++ compatible = "fsl,srio"; ++ interrupts = <48 2 0 0>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ fsl,srio-rmu-handle = <&rmu>; ++ sleep = <&pmc 0x00080000>; ++ ranges; ++ ++ port1 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <1>; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,mpc8568-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <10>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,mpc8568-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <17 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,mpc8568-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <18 2 0 0>; ++ }; ++ ++ i2c-sleep-nexus { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ sleep = <&pmc 0x00000004>; ++ ranges; ++ ++/include/ "pq3-i2c-0.dtsi" ++/include/ "pq3-i2c-1.dtsi" ++ ++ }; ++ ++ duart-sleep-nexus { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ sleep = <&pmc 0x00000002>; ++ ranges; ++ ++/include/ "pq3-duart-0.dtsi" ++ ++ }; ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,mpc8568-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x80000>; // L2, 512K ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++ dma@21300 { ++ sleep = <&pmc 0x00000400>; ++ }; ++ ++/include/ "pq3-etsec1-0.dtsi" ++ ethernet@24000 { ++ sleep = <&pmc 0x00000080>; ++ }; ++ ++/include/ "pq3-etsec1-1.dtsi" ++ ethernet@25000 { ++ sleep = <&pmc 0x00000040>; ++ }; ++ ++ par_io@e0100 { ++ reg = <0xe0100 0x100>; ++ device_type = "par_io"; ++ }; ++ ++/include/ "pq3-sec2.1-0.dtsi" ++ crypto@30000 { ++ sleep = <&pmc 0x01000000>; ++ }; ++ ++/include/ "pq3-mpic.dtsi" ++/include/ "pq3-rmu-0.dtsi" ++ rmu@d3000 { ++ sleep = <&pmc 0x00040000>; ++ }; ++ ++ global-utilities@e0000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8568-guts", "fsl,mpc8548-guts"; ++ reg = <0xe0000 0x1000>; ++ ranges = <0 0xe0000 0x1000>; ++ fsl,has-rstcr; ++ ++ pmc: power@70 { ++ compatible = "fsl,mpc8568-pmc", ++ "fsl,mpc8548-pmc"; ++ reg = <0x70 0x20>; ++ }; ++ }; ++}; ++ ++&qe { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "qe"; ++ compatible = "fsl,qe"; ++ sleep = <&pmc 0x00000800>; ++ brg-frequency = <0>; ++ bus-frequency = <396000000>; ++ fsl,qe-num-riscs = <2>; ++ fsl,qe-num-snums = <28>; ++ ++ qeic: interrupt-controller@80 { ++ interrupt-controller; ++ compatible = "fsl,qe-ic"; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ reg = <0x80 0x80>; ++ interrupts = <46 2 0 0 46 2 0 0>; //high:30 low:30 ++ interrupt-parent = <&mpic>; ++ }; ++ ++ spi@4c0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,spi"; ++ reg = <0x4c0 0x40>; ++ cell-index = <0>; ++ interrupts = <2>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ spi@500 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <1>; ++ compatible = "fsl,spi"; ++ reg = <0x500 0x40>; ++ interrupts = <1>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ ucc@2000 { ++ cell-index = <1>; ++ reg = <0x2000 0x200>; ++ interrupts = <32>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ ucc@3000 { ++ cell-index = <2>; ++ reg = <0x3000 0x200>; ++ interrupts = <33>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ muram@10000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,qe-muram", "fsl,cpm-muram"; ++ ranges = <0x0 0x10000 0x10000>; ++ ++ data-only@0 { ++ compatible = "fsl,qe-muram-data", ++ "fsl,cpm-muram-data"; ++ reg = <0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8568si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8568si-pre.dtsi +new file mode 100644 +index 0000000..122ca3b +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/mpc8568si-pre.dtsi +@@ -0,0 +1,68 @@ ++/* ++ * MPC8568 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500v2_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,MPC8568"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ ethernet3 = &enet3; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,8568@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ sleep = <&pmc 0x00008000 // core ++ &pmc 0x00004000>; // timebase ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8569si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8569si-post.dtsi +new file mode 100644 +index 0000000..3e6346a +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/mpc8569si-post.dtsi +@@ -0,0 +1,304 @@ ++/* ++ * MPC8569 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8569-elbc", "fsl,elbc", "simple-bus"; ++ interrupts = <19 2 0 0>; ++ sleep = <&pmc 0x08000000>; ++}; ++ ++/* controller at 0xa000 */ ++&pci1 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <26 2 0 0>; ++ sleep = <&pmc 0x20000000>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <26 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++&rio { ++ compatible = "fsl,srio"; ++ interrupts = <48 2 0 0>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ fsl,srio-rmu-handle = <&rmu>; ++ sleep = <&pmc 0x00080000>; ++ ranges; ++ ++ port1 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <1>; ++ }; ++ ++ port2 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <2>; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,mpc8569-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <10>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,mpc8569-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <17 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,mpc8569-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <18 2 0 0>; ++ }; ++ ++ i2c-sleep-nexus { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ sleep = <&pmc 0x00000004>; ++ ranges; ++ ++/include/ "pq3-i2c-0.dtsi" ++/include/ "pq3-i2c-1.dtsi" ++ ++ }; ++ ++ duart-sleep-nexus { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ sleep = <&pmc 0x00000002>; ++ ranges; ++ ++/include/ "pq3-duart-0.dtsi" ++ ++ }; ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,mpc8569-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x80000>; // L2, 512K ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++/include/ "pq3-esdhc-0.dtsi" ++ sdhc@2e000 { ++ sleep = <&pmc 0x00200000>; ++ }; ++ ++ par_io@e0100 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0xe0100 0x100>; ++ ranges = <0x0 0xe0100 0x100>; ++ device_type = "par_io"; ++ }; ++ ++/include/ "pq3-sec3.1-0.dtsi" ++ crypto@30000 { ++ sleep = <&pmc 0x01000000>; ++ }; ++ ++/include/ "pq3-mpic.dtsi" ++/include/ "pq3-rmu-0.dtsi" ++ rmu@d3000 { ++ sleep = <&pmc 0x00040000>; ++ }; ++ ++ global-utilities@e0000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8569-guts", "fsl,mpc8548-guts"; ++ reg = <0xe0000 0x1000>; ++ ranges = <0 0xe0000 0x1000>; ++ fsl,has-rstcr; ++ ++ pmc: power@70 { ++ compatible = "fsl,mpc8569-pmc", ++ "fsl,mpc8548-pmc"; ++ reg = <0x70 0x20>; ++ }; ++ }; ++}; ++ ++&qe { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "qe"; ++ compatible = "fsl,qe"; ++ sleep = <&pmc 0x00000800>; ++ brg-frequency = <0>; ++ bus-frequency = <0>; ++ fsl,qe-num-riscs = <4>; ++ fsl,qe-num-snums = <46>; ++ ++ qeic: interrupt-controller@80 { ++ interrupt-controller; ++ compatible = "fsl,qe-ic"; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ reg = <0x80 0x80>; ++ interrupts = <46 2 0 0 46 2 0 0>; //high:30 low:30 ++ interrupt-parent = <&mpic>; ++ }; ++ ++ timer@440 { ++ compatible = "fsl,mpc8569-qe-gtm", ++ "fsl,qe-gtm", "fsl,gtm"; ++ reg = <0x440 0x40>; ++ interrupts = <12 13 14 15>; ++ interrupt-parent = <&qeic>; ++ /* Filled in by U-Boot */ ++ clock-frequency = <0>; ++ }; ++ ++ spi@4c0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,mpc8569-qe-spi", "fsl,spi"; ++ reg = <0x4c0 0x40>; ++ cell-index = <0>; ++ interrupts = <2>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ spi@500 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <1>; ++ compatible = "fsl,spi"; ++ reg = <0x500 0x40>; ++ interrupts = <1>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ usb@6c0 { ++ compatible = "fsl,mpc8569-qe-usb", ++ "fsl,mpc8323-qe-usb"; ++ reg = <0x6c0 0x40 0x8b00 0x100>; ++ interrupts = <11>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ ucc@2000 { ++ cell-index = <1>; ++ reg = <0x2000 0x200>; ++ interrupts = <32>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ ucc@2200 { ++ cell-index = <3>; ++ reg = <0x2200 0x200>; ++ interrupts = <34>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ ucc@3000 { ++ cell-index = <2>; ++ reg = <0x3000 0x200>; ++ interrupts = <33>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ ucc@3200 { ++ cell-index = <4>; ++ reg = <0x3200 0x200>; ++ interrupts = <35>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ ucc@3400 { ++ cell-index = <6>; ++ reg = <0x3400 0x200>; ++ interrupts = <41>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ ucc@3600 { ++ cell-index = <8>; ++ reg = <0x3600 0x200>; ++ interrupts = <43>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ muram@10000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,qe-muram", "fsl,cpm-muram"; ++ ranges = <0x0 0x10000 0x20000>; ++ ++ data-only@0 { ++ compatible = "fsl,qe-muram-data", ++ "fsl,cpm-muram-data"; ++ reg = <0x0 0x20000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8569si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8569si-pre.dtsi +new file mode 100644 +index 0000000..2cd15a2 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/mpc8569si-pre.dtsi +@@ -0,0 +1,67 @@ ++/* ++ * MPC8569 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500v2_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,MPC8569"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ ethernet3 = &enet3; ++ pci1 = &pci1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,8569@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ sleep = <&pmc 0x00008000 // core ++ &pmc 0x00004000>; // timebase ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi +new file mode 100644 +index 0000000..7313351 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi +@@ -0,0 +1,198 @@ ++/* ++ * MPC8572 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8572-elbc", "fsl,elbc", "simple-bus"; ++ interrupts = <19 2 0 0>; ++}; ++ ++/* controller at 0x8000 */ ++&pci0 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <24 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <24 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x8 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x9 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0xa 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0xb 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0x9000 */ ++&pci1 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <25 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <25 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x4 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x5 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x6 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x7 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0xa000 */ ++&pci2 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <26 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <26 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,mpc8572-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <12>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,mpc8572-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <17 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,mpc8572-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <18 2 0 0>; ++ }; ++ ++ memory-controller@6000 { ++ compatible = "fsl,mpc8572-memory-controller"; ++ reg = <0x6000 0x1000>; ++ interrupts = <18 2 0 0>; ++ }; ++ ++/include/ "pq3-i2c-0.dtsi" ++/include/ "pq3-i2c-1.dtsi" ++/include/ "pq3-duart-0.dtsi" ++/include/ "pq3-dma-1.dtsi" ++/include/ "pq3-gpio-0.dtsi" ++ gpio-controller@f000 { ++ compatible = "fsl,mpc8572-gpio", "fsl,pq3-gpio"; ++ }; ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,mpc8572-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x100000>; // L2,1M ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++/include/ "pq3-etsec1-0.dtsi" ++/include/ "pq3-etsec1-timer-0.dtsi" ++ ++ ptp_clock@24e00 { ++ interrupts = <68 2 0 0 69 2 0 0 70 2 0 0 71 2 0 0>; ++ }; ++ ++/include/ "pq3-etsec1-1.dtsi" ++/include/ "pq3-etsec1-2.dtsi" ++/include/ "pq3-etsec1-3.dtsi" ++/include/ "pq3-sec3.0-0.dtsi" ++/include/ "pq3-mpic.dtsi" ++/include/ "pq3-mpic-timer-B.dtsi" ++ ++ global-utilities@e0000 { ++ compatible = "fsl,mpc8572-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ ++/include/ "pq3-power.dtsi" ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8572si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8572si-pre.dtsi +new file mode 100644 +index 0000000..28c2a86 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/mpc8572si-pre.dtsi +@@ -0,0 +1,73 @@ ++/* ++ * MPC8572 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500v2_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,MPC8572"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ ethernet3 = &enet3; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,8572@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ }; ++ ++ PowerPC,8572@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi +new file mode 100644 +index 0000000..e949c47 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi +@@ -0,0 +1,211 @@ ++/* ++ * P1010/P1014 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&ifc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,ifc", "simple-bus"; ++ interrupts = <16 2 0 0 19 2 0 0>; ++}; ++ ++/* controller at 0x9000 */ ++&pci0 { ++ compatible = "fsl,p1010-pcie", "fsl,qoriq-pcie-v2.3", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x4 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x5 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x6 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x7 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0xa000 */ ++&pci1 { ++ compatible = "fsl,p1010-pcie", "fsl,qoriq-pcie-v2.3", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,p1010-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <12>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,p1010-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,p1010-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-i2c-0.dtsi" ++/include/ "pq3-i2c-1.dtsi" ++/include/ "pq3-duart-0.dtsi" ++/include/ "pq3-espi-0.dtsi" ++ spi0: spi@7000 { ++ fsl,espi-num-chipselects = <1>; ++ }; ++ ++/include/ "pq3-gpio-0.dtsi" ++/include/ "pq3-sata2-0.dtsi" ++/include/ "pq3-sata2-1.dtsi" ++/include/ "pq3-tdm1.0-0.dtsi" ++ ++ can0: can@1c000 { ++ compatible = "fsl,p1010-flexcan"; ++ reg = <0x1c000 0x1000>; ++ interrupts = <48 0x2 0 0>; ++ }; ++ ++ can1: can@1d000 { ++ compatible = "fsl,p1010-flexcan"; ++ reg = <0x1d000 0x1000>; ++ interrupts = <61 0x2 0 0>; ++ }; ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,p1010-l2-cache-controller", ++ "fsl,p1014-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x40000>; // L2,256K ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++/include/ "pq3-usb2-dr-0.dtsi" ++ usb@22000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr"; ++ }; ++/include/ "pq3-esdhc-0.dtsi" ++ sdhc@2e000 { ++ compatible = "fsl,p1010-esdhc", "fsl,esdhc"; ++ sdhci,auto-cmd12; ++ }; ++ ++/include/ "pq3-sec4.4-0.dtsi" ++/include/ "pq3-mpic.dtsi" ++/include/ "pq3-mpic-timer-B.dtsi" ++ ++/include/ "pq3-etsec2-0.dtsi" ++ enet0: ethernet@b0000 { ++ fsl,pmc-handle = <&etsec1_clk>; ++ ++ queue-group@b0000 { ++ fsl,rx-bit-map = <0xff>; ++ fsl,tx-bit-map = <0xff>; ++ }; ++ }; ++ ++/include/ "pq3-etsec2-1.dtsi" ++ enet1: ethernet@b1000 { ++ fsl,pmc-handle = <&etsec2_clk>; ++ ++ queue-group@b1000 { ++ fsl,rx-bit-map = <0xff>; ++ fsl,tx-bit-map = <0xff>; ++ }; ++ }; ++ ++/include/ "pq3-etsec2-2.dtsi" ++ enet2: ethernet@b2000 { ++ fsl,pmc-handle = <&etsec3_clk>; ++ ++ queue-group@b2000 { ++ fsl,rx-bit-map = <0xff>; ++ fsl,tx-bit-map = <0xff>; ++ }; ++ ++ }; ++ ++ global-utilities@e0000 { ++ compatible = "fsl,p1010-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ ++/include/ "pq3-power.dtsi" ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p1010si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p1010si-pre.dtsi +new file mode 100644 +index 0000000..6e76f9b +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p1010si-pre.dtsi +@@ -0,0 +1,67 @@ ++/* ++ * P1010/P1014 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500v2_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,P1010"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ can0 = &can0; ++ can1 = &can1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,P1010@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi +new file mode 100644 +index 0000000..5af0aae +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi +@@ -0,0 +1,201 @@ ++/* ++ * P1020/P1011 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,p1020-elbc", "fsl,elbc", "simple-bus"; ++ interrupts = <19 2 0 0>; ++}; ++ ++/* controller at 0x9000 */ ++&pci0 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x4 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x5 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x6 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x7 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0xa000 */ ++&pci1 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,p1020-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <12>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,p1020-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,p1020-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-i2c-0.dtsi" ++/include/ "pq3-i2c-1.dtsi" ++/include/ "pq3-duart-0.dtsi" ++ ++/include/ "pq3-espi-0.dtsi" ++ spi@7000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "pq3-gpio-0.dtsi" ++/include/ "pq3-tdm1.0-0.dtsi" ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,p1020-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x40000>; // L2,256K ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++/include/ "pq3-usb2-dr-0.dtsi" ++ usb@22000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr"; ++ }; ++/include/ "pq3-usb2-dr-1.dtsi" ++ usb@23000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr"; ++ }; ++ ++/include/ "pq3-esdhc-0.dtsi" ++ sdhc@2e000 { ++ compatible = "fsl,p1020-esdhc", "fsl,esdhc"; ++ sdhci,auto-cmd12; ++ }; ++/include/ "pq3-sec3.3-0.dtsi" ++ ++/include/ "pq3-mpic.dtsi" ++/include/ "pq3-mpic-timer-B.dtsi" ++ ++ ptp_timer: ptimer@b0e00 { ++ compatible = "fsl,gianfar-ptp-timer"; ++ reg = <0xb0e00 0xb0>; ++ fsl,ts-to-buffer; ++ fsl,tmr-prsc = <0x2>; ++ fsl,clock-source-select = <1>; ++ }; ++ ++/include/ "pq3-etsec2-0.dtsi" ++ enet0: enet0_grp2: ethernet@b0000 { ++ fsl,pmc-handle = <&etsec1_clk>; ++ ptimer-handle = <&ptp_timer>; ++ }; ++ ++/include/ "pq3-etsec2-1.dtsi" ++ enet1: enet1_grp2: ethernet@b1000 { ++ fsl,pmc-handle = <&etsec2_clk>; ++ ptimer-handle = <&ptp_timer>; ++ }; ++ ++/include/ "pq3-etsec2-2.dtsi" ++ enet2: enet2_grp2: ethernet@b2000 { ++ fsl,pmc-handle = <&etsec3_clk>; ++ ptimer-handle = <&ptp_timer>; ++ }; ++ ++ global-utilities@e0000 { ++ compatible = "fsl,p1020-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ ++/include/ "pq3-power.dtsi" ++}; ++ ++/include/ "pq3-etsec2-grp2-0.dtsi" ++/include/ "pq3-etsec2-grp2-1.dtsi" ++/include/ "pq3-etsec2-grp2-2.dtsi" +diff --git a/arch/powerpc/boot/dts/fsl/p1020si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p1020si-pre.dtsi +new file mode 100644 +index 0000000..fed9c4c +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p1020si-pre.dtsi +@@ -0,0 +1,71 @@ ++/* ++ * P1020/P1011 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500v2_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,P1020"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,P1020@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ }; ++ ++ PowerPC,P1020@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi +new file mode 100644 +index 0000000..cbdf47f +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi +@@ -0,0 +1,262 @@ ++/* ++ * P1021/P1012 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,p1021-elbc", "fsl,elbc", "simple-bus"; ++ interrupts = <19 2 0 0>; ++}; ++ ++/* controller at 0x9000 */ ++&pci0 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x4 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x5 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x6 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x7 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0xa000 */ ++&pci1 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,p1021-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <12>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,p1021-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,p1021-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-i2c-0.dtsi" ++/include/ "pq3-i2c-1.dtsi" ++/include/ "pq3-duart-0.dtsi" ++ ++/include/ "pq3-espi-0.dtsi" ++ spi@7000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "pq3-gpio-0.dtsi" ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,p1021-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x40000>; // L2,256K ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++/include/ "pq3-usb2-dr-0.dtsi" ++ usb@22000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr"; ++ }; ++ ++/include/ "pq3-esdhc-0.dtsi" ++ sdhc@2e000 { ++ sdhci,auto-cmd12; ++ }; ++ ++/include/ "pq3-sec3.3-0.dtsi" ++ ++/include/ "pq3-mpic.dtsi" ++/include/ "pq3-mpic-timer-B.dtsi" ++ ++ ptp_timer: ptimer@b0e00 { ++ compatible = "fsl,gianfar-ptp-timer"; ++ reg = <0xb0e00 0xb0>; ++ fsl,ts-to-buffer; ++ fsl,tmr-prsc = <0x2>; ++ fsl,clock-source-select = <1>; ++ }; ++ ++/include/ "pq3-etsec2-0.dtsi" ++ enet0: enet0_grp2: ethernet@b0000 { ++ fsl,pmc-handle = <&etsec1_clk>; ++ ptimer-handle = <&ptp_timer>; ++ }; ++ ++/include/ "pq3-etsec2-1.dtsi" ++ enet1: enet1_grp2: ethernet@b1000 { ++ fsl,pmc-handle = <&etsec2_clk>; ++ ptimer-handle = <&ptp_timer>; ++ }; ++ ++/include/ "pq3-etsec2-2.dtsi" ++ enet2: enet2_grp2: ethernet@b2000 { ++ fsl,pmc-handle = <&etsec3_clk>; ++ ptimer-handle = <&ptp_timer>; ++ }; ++ ++ global-utilities@e0000 { ++ compatible = "fsl,p1021-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ ++/include/ "pq3-power.dtsi" ++}; ++ ++&qe { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "qe"; ++ compatible = "fsl,qe"; ++ fsl,qe-num-riscs = <1>; ++ fsl,qe-num-snums = <28>; ++ ++ qeic: interrupt-controller@80 { ++ interrupt-controller; ++ compatible = "fsl,qe-ic"; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ reg = <0x80 0x80>; ++ interrupts = <63 2 0 0 60 2 0 0>; //high:47 low:44 ++ }; ++ ++ ucc@2000 { ++ cell-index = <1>; ++ reg = <0x2000 0x200>; ++ interrupts = <32>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ mdio@2120 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x2120 0x18>; ++ compatible = "fsl,ucc-mdio"; ++ }; ++ ++ ucc@2400 { ++ cell-index = <5>; ++ reg = <0x2400 0x200>; ++ interrupts = <40>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ ucc@2600 { ++ cell-index = <7>; ++ reg = <0x2600 0x200>; ++ interrupts = <42>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ ucc@2200 { ++ cell-index = <3>; ++ reg = <0x2200 0x200>; ++ interrupts = <34>; ++ interrupt-parent = <&qeic>; ++ }; ++ ++ muram@10000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,qe-muram", "fsl,cpm-muram"; ++ ranges = <0x0 0x10000 0x6000>; ++ ++ data-only@0 { ++ compatible = "fsl,qe-muram-data", ++ "fsl,cpm-muram-data"; ++ reg = <0x0 0x6000>; ++ }; ++ }; ++}; ++ ++/include/ "pq3-etsec2-grp2-0.dtsi" ++/include/ "pq3-etsec2-grp2-1.dtsi" ++/include/ "pq3-etsec2-grp2-2.dtsi" +diff --git a/arch/powerpc/boot/dts/fsl/p1021si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p1021si-pre.dtsi +new file mode 100644 +index 0000000..36161b5 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p1021si-pre.dtsi +@@ -0,0 +1,71 @@ ++/* ++ * P1021/P1012 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500v2_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,P1021"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,P1021@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ }; ++ ++ PowerPC,P1021@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi +new file mode 100644 +index 0000000..3f3fc1e +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi +@@ -0,0 +1,252 @@ ++/* ++ * P1022/P1013 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ /* ++ * The localbus on the P1022 is not a simple-bus because of the eLBC ++ * pin muxing when the DIU is enabled. ++ */ ++ compatible = "fsl,p1022-elbc", "fsl,elbc"; ++ interrupts = <19 2 0 0>; ++}; ++ ++/* controller at 0x9000 */ ++&pci0 { ++ compatible = "fsl,p1022-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x4 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x5 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x6 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x7 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0xa000 */ ++&pci1 { ++ compatible = "fsl,p1022-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0xb000 */ ++&pci2 { ++ compatible = "fsl,p1022-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x8 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x9 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0xa 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0xb 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,p1022-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <12>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,p1022-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,p1022-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-i2c-0.dtsi" ++/include/ "pq3-i2c-1.dtsi" ++/include/ "pq3-duart-0.dtsi" ++/include/ "pq3-espi-0.dtsi" ++ spi@7000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "pq3-dma-1.dtsi" ++ dma@c300 { ++ dma00: dma-channel@0 { ++ compatible = "fsl,ssi-dma-channel"; ++ }; ++ dma01: dma-channel@80 { ++ compatible = "fsl,ssi-dma-channel"; ++ }; ++ }; ++ ++/include/ "pq3-gpio-0.dtsi" ++ ++ display@10000 { ++ compatible = "fsl,diu", "fsl,p1022-diu"; ++ reg = <0x10000 1000>; ++ interrupts = <64 2 0 0>; ++ }; ++ ++ ssi@15000 { ++ compatible = "fsl,mpc8610-ssi"; ++ cell-index = <0>; ++ reg = <0x15000 0x100>; ++ interrupts = <75 2 0 0>; ++ fsl,playback-dma = <&dma00>; ++ fsl,capture-dma = <&dma01>; ++ fsl,fifo-depth = <15>; ++ }; ++ ++/include/ "pq3-tdm1.0-0.dtsi" ++/include/ "pq3-sata2-0.dtsi" ++/include/ "pq3-sata2-1.dtsi" ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,p1022-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x40000>; // L2,256K ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++/include/ "pq3-usb2-dr-0.dtsi" ++ usb@22000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr"; ++ }; ++/include/ "pq3-usb2-dr-1.dtsi" ++ usb@23000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr"; ++ }; ++ ++/include/ "pq3-esdhc-0.dtsi" ++ sdhc@2e000 { ++ compatible = "fsl,p1022-esdhc", "fsl,esdhc"; ++ sdhci,auto-cmd12; ++ }; ++ ++/include/ "pq3-sec3.3-0.dtsi" ++/include/ "pq3-mpic.dtsi" ++/include/ "pq3-mpic-timer-B.dtsi" ++ ++/include/ "pq3-etsec2-0.dtsi" ++ enet0: enet0_grp2: ethernet@b0000 { ++ fsl,wake-on-filer; ++ fsl,pmc-handle = <&etsec1_clk>; ++ }; ++ ++/include/ "pq3-etsec2-1.dtsi" ++ enet1: enet1_grp2: ethernet@b1000 { ++ fsl,wake-on-filer; ++ fsl,pmc-handle = <&etsec2_clk>; ++ }; ++ ++ global-utilities@e0000 { ++ compatible = "fsl,p1022-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ ++/include/ "pq3-power.dtsi" ++ power@e0070 { ++ compatible = "fsl,p1022-pmc", "fsl,mpc8536-pmc", ++ "fsl,mpc8548-pmc"; ++ }; ++ ++}; ++ ++/include/ "pq3-etsec2-grp2-0.dtsi" ++/include/ "pq3-etsec2-grp2-1.dtsi" +diff --git a/arch/powerpc/boot/dts/fsl/p1022si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p1022si-pre.dtsi +new file mode 100644 +index 0000000..1956dea +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p1022si-pre.dtsi +@@ -0,0 +1,71 @@ ++/* ++ * P1022/P1013 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500v2_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,P1022"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,P1022@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ }; ++ ++ PowerPC,P1022@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p1023si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1023si-post.dtsi +new file mode 100644 +index 0000000..7bb575a +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p1023si-post.dtsi +@@ -0,0 +1,413 @@ ++/* ++ * P1023/P1017 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,p1023-elbc", "fsl,elbc", "simple-bus"; ++ interrupts = <19 2 0 0>; ++}; ++ ++/* controller at 0xa000 */ ++&pci0 { ++ compatible = "fsl,p1023-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 0 0>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 0 0>; ++ }; ++}; ++ ++/* controller at 0x9000 */ ++&pci1 { ++ compatible = "fsl,p1023-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 0 0>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 0 0>; ++ }; ++}; ++ ++/* controller at 0xb000 */ ++&pci2 { ++ compatible = "fsl,p1023-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 0 0>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 0 0>; ++ }; ++}; ++ ++&qportals { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ compatible = "simple-bus"; ++ qportal0: qman-portal@0 { ++ cell-index = <0x0>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x0 0x4000 0x100000 0x1000>; ++ interrupts = <29 2 0 0>; ++ fsl,qman-channel-id = <0x0>; ++ }; ++ ++ qportal1: qman-portal@4000 { ++ cell-index = <0x1>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x4000 0x4000 0x101000 0x1000>; ++ interrupts = <31 2 0 0>; ++ fsl,qman-channel-id = <0x1>; ++ }; ++ ++ qportal2: qman-portal@8000 { ++ cell-index = <0x2>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x8000 0x4000 0x102000 0x1000>; ++ interrupts = <33 2 0 0>; ++ fsl,qman-channel-id = <0x2>; ++ }; ++}; ++ ++&bportals { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ compatible = "simple-bus"; ++ bman-portal@0 { ++ cell-index = <0x0>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x0 0x4000 0x100000 0x1000>; ++ interrupts = <30 2 0 0>; ++ }; ++ bman-portal@4000 { ++ cell-index = <0x1>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x4000 0x4000 0x101000 0x1000>; ++ interrupts = <32 2 0 0>; ++ }; ++ bman-portal@8000 { ++ cell-index = <2>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x8000 0x4000 0x102000 0x1000>; ++ interrupts = <34 2 0 0>; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,p1023-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <12>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,p1023-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,p1023-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-i2c-0.dtsi" ++/include/ "pq3-i2c-1.dtsi" ++/include/ "pq3-duart-0.dtsi" ++ ++/include/ "pq3-espi-0.dtsi" ++ spi@7000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "pq3-gpio-0.dtsi" ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,p1023-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x40000>; // L2,256K ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++/include/ "pq3-usb2-dr-0.dtsi" ++ usb@22000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr"; ++ }; ++ ++ crypto: crypto@300000 { ++ compatible = "fsl,sec-v4.2", "fsl,sec-v4.0"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x30000 0x10000>; ++ ranges = <0 0x30000 0x10000>; ++ interrupts = <58 2 0 0>; ++ ++ sec_jr0: jr@1000 { ++ compatible = "fsl,sec-v4.2-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x1000 0x1000>; ++ interrupts = <45 2 0 0>; ++ }; ++ ++ sec_jr1: jr@2000 { ++ compatible = "fsl,sec-v4.2-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x2000 0x1000>; ++ interrupts = <45 2 0 0>; ++ }; ++ ++ sec_jr2: jr@3000 { ++ compatible = "fsl,sec-v4.2-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x3000 0x1000>; ++ interrupts = <57 2 0 0>; ++ }; ++ ++ sec_jr3: jr@4000 { ++ compatible = "fsl,sec-v4.2-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x4000 0x1000>; ++ interrupts = <57 2 0 0>; ++ }; ++ ++ rtic@6000 { ++ compatible = "fsl,sec-v4.2-rtic", ++ "fsl,sec-v4.0-rtic"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x6000 0x100>; ++ ranges = <0x0 0x6100 0xe00>; ++ ++ rtic_a: rtic-a@0 { ++ compatible = "fsl,sec-v4.2-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x00 0x20 0x100 0x80>; ++ }; ++ ++ rtic_b: rtic-b@20 { ++ compatible = "fsl,sec-v4.2-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x20 0x20 0x200 0x80>; ++ }; ++ ++ rtic_c: rtic-c@40 { ++ compatible = "fsl,sec-v4.2-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x40 0x20 0x300 0x80>; ++ }; ++ ++ rtic_d: rtic-d@60 { ++ compatible = "fsl,sec-v4.2-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x60 0x20 0x500 0x80>; ++ }; ++ }; ++ }; ++ ++/include/ "pq3-mpic.dtsi" ++/include/ "pq3-mpic-timer-B.dtsi" ++ ++ qman: qman@88000 { ++ compatible = "fsl,qman"; ++ reg = <0x88000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++ bman: bman@8a000 { ++ compatible = "fsl,bman"; ++ reg = <0x8a000 0x1000>; ++ interrupts = <16 2 0 0>; ++ }; ++ ++ global-utilities@e0000 { ++ compatible = "fsl,p1023-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ ++ fman0: fman@100000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <0>; ++ compatible = "fsl,fman", "simple-bus"; ++ ranges = <0 0x100000 0x100000>; ++ reg = <0x100000 0x100000>; ++ clock-frequency = <0>; ++ interrupts = < ++ 24 2 0 0 ++ 16 2 0 0>; ++ cc@0 { ++ compatible = "fsl,fman-cc"; ++ }; ++ muram@0 { ++ compatible = "fsl,fman-muram"; ++ reg = <0x0 0x10000>; ++ }; ++ bmi@80000 { ++ compatible = "fsl,fman-bmi"; ++ reg = <0x80000 0x400>; ++ }; ++ qmi@80400 { ++ compatible = "fsl,fman-qmi"; ++ reg = <0x80400 0x400>; ++ }; ++ policer@c0000 { ++ compatible = "fsl,fman-policer"; ++ reg = <0xc0000 0x1000>; ++ }; ++ keygen@c1000 { ++ compatible = "fsl,fman-keygen"; ++ reg = <0xc1000 0x1000>; ++ }; ++ dma@c2000 { ++ compatible = "fsl,fman-dma"; ++ reg = <0xc2000 0x1000>; ++ }; ++ fpm@c3000 { ++ compatible = "fsl,fman-fpm"; ++ reg = <0xc3000 0x1000>; ++ }; ++ parser@c7000 { ++ compatible = "fsl,fman-parser"; ++ reg = <0xc7000 0x1000>; ++ }; ++ fman0_rx0: port@88000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x88000 0x1000>; ++ }; ++ fman0_rx1: port@89000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x89000 0x1000>; ++ }; ++ fman0_tx0: port@a8000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xa8000 0x1000>; ++ fsl,qman-channel-id = <0x40>; ++ }; ++ fman0_tx1: port@a9000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xa9000 0x1000>; ++ fsl,qman-channel-id = <0x41>; ++ }; ++ fman0_oh1: port@82000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x82000 0x1000>; ++ fsl,qman-channel-id = <0x43>; ++ }; ++ fman0_oh2: port@83000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x83000 0x1000>; ++ fsl,qman-channel-id = <0x44>; ++ }; ++ fman0_oh3: port@84000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x84000 0x1000>; ++ fsl,qman-channel-id = <0x45>; ++ }; ++ fman0_oh4: port@85000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x85000 0x1000>; ++ fsl,qman-channel-id = <0x46>; ++ }; ++ enet0: ethernet@e0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-1g-mac"; ++ reg = <0xe0000 0x1000>; ++ fsl,port-handles = <&fman0_rx0 &fman0_tx0>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ enet1: ethernet@e2000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-1g-mac"; ++ reg = <0xe2000 0x1000>; ++ fsl,port-handles = <&fman0_rx1 &fman0_tx1>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ mdio0: mdio@e1120 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-mdio"; ++ reg = <0xe1120 0xee0>; ++ interrupts = <26 1 0 0>; ++ }; ++ ++ ptp_timer0: rtc@fe000 { ++ compatible = "fsl,fman-rtc"; ++ reg = <0xfe000 0x1000>; ++ }; ++ }; ++ ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p1023si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p1023si-pre.dtsi +new file mode 100644 +index 0000000..6cfff45 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p1023si-pre.dtsi +@@ -0,0 +1,83 @@ ++/* ++ * P1023/P1017 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500v2_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,P1023"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ ++ crypto = &crypto; ++ sec_jr0 = &sec_jr0; ++ sec_jr1 = &sec_jr1; ++ sec_jr2 = &sec_jr2; ++ sec_jr3 = &sec_jr3; ++ rtic_a = &rtic_a; ++ rtic_b = &rtic_b; ++ rtic_c = &rtic_c; ++ rtic_d = &rtic_d; ++ ++ bman = &bman; ++ qman = &qman; ++ fman0 = &fman0; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: PowerPC,P1023@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ }; ++ ++ cpu1: PowerPC,P1023@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi +new file mode 100644 +index 0000000..7d155b3 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi +@@ -0,0 +1,215 @@ ++/* ++ * P2020/P2010 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,p2020-elbc", "fsl,elbc", "simple-bus"; ++ interrupts = <19 2 0 0>; ++}; ++ ++/* controller at 0xa000 */ ++&pci0 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <26 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <26 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0x9000 */ ++&pci1 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <25 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <25 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x4 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x5 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0x6 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0x7 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++/* controller at 0x8000 */ ++&pci2 { ++ compatible = "fsl,mpc8548-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 255>; ++ clock-frequency = <33333333>; ++ interrupts = <24 2 0 0>; ++ ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <24 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x8 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x2 &mpic 0x9 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x3 &mpic 0xa 0x1 0x0 0x0 ++ 0000 0x0 0x0 0x4 &mpic 0xb 0x1 0x0 0x0 ++ >; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "fsl,p2020-immr", "simple-bus"; ++ bus-frequency = <0>; // Filled out by uboot. ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <12>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,p2020-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <17 2 0 0>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,p2020-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupts = <18 2 0 0>; ++ }; ++ ++/include/ "pq3-i2c-0.dtsi" ++/include/ "pq3-i2c-1.dtsi" ++/include/ "pq3-duart-0.dtsi" ++/include/ "pq3-espi-0.dtsi" ++ spi0: spi@7000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "pq3-dma-1.dtsi" ++/include/ "pq3-gpio-0.dtsi" ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,p2020-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x80000>; // L2,512K ++ interrupts = <16 2 0 0>; ++ }; ++ ++/include/ "pq3-dma-0.dtsi" ++/include/ "pq3-usb2-dr-0.dtsi" ++ usb@22000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr"; ++ }; ++/include/ "pq3-etsec1-0.dtsi" ++ enet0: ethernet@24000 { ++ fsl,pmc-handle = <&etsec1_clk>; ++ ++ }; ++/include/ "pq3-etsec1-timer-0.dtsi" ++ ++ ptp_clock@24e00 { ++ interrupts = <68 2 0 0 69 2 0 0 70 2 0 0>; ++ }; ++ ++ ++/include/ "pq3-etsec1-1.dtsi" ++ enet1: ethernet@25000 { ++ fsl,pmc-handle = <&etsec2_clk>; ++ }; ++ ++/include/ "pq3-etsec1-2.dtsi" ++ enet2: ethernet@26000 { ++ fsl,pmc-handle = <&etsec3_clk>; ++ }; ++ ++/include/ "pq3-esdhc-0.dtsi" ++ sdhc@2e000 { ++ compatible = "fsl,p2020-esdhc", "fsl,esdhc"; ++ }; ++ ++/include/ "pq3-sec3.1-0.dtsi" ++/include/ "pq3-mpic.dtsi" ++/include/ "pq3-mpic-timer-B.dtsi" ++ ++ global-utilities@e0000 { ++ compatible = "fsl,p2020-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ ++/include/ "pq3-power.dtsi" ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p2020si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p2020si-pre.dtsi +new file mode 100644 +index 0000000..42bf3c6 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p2020si-pre.dtsi +@@ -0,0 +1,72 @@ ++/* ++ * P2020/P2010 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500v2_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,P2020"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,P2020@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ next-level-cache = <&L2>; ++ }; ++ ++ PowerPC,P2020@1 { ++ device_type = "cpu"; ++ reg = <0x1>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi +new file mode 100644 +index 0000000..d9a9bf4 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi +@@ -0,0 +1,407 @@ ++/* ++ * P2041/P2040 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ compatible = "fsl,p2041-elbc", "fsl,elbc", "simple-bus"; ++ interrupts = <25 2 0 0>; ++ #address-cells = <2>; ++ #size-cells = <1>; ++}; ++ ++/* controller at 0x200000 */ ++&pci0 { ++ compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 15>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 15>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 40 1 0 0 ++ 0000 0 0 2 &mpic 1 1 0 0 ++ 0000 0 0 3 &mpic 2 1 0 0 ++ 0000 0 0 4 &mpic 3 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x201000 */ ++&pci1 { ++ compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 14>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 14>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 41 1 0 0 ++ 0000 0 0 2 &mpic 5 1 0 0 ++ 0000 0 0 3 &mpic 6 1 0 0 ++ 0000 0 0 4 &mpic 7 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x202000 */ ++&pci2 { ++ compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 13>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 13>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 42 1 0 0 ++ 0000 0 0 2 &mpic 9 1 0 0 ++ 0000 0 0 3 &mpic 10 1 0 0 ++ 0000 0 0 4 &mpic 11 1 0 0 ++ >; ++ }; ++}; ++ ++&rio { ++ compatible = "fsl,srio"; ++ interrupts = <16 2 1 11>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ port1 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <1>; ++ }; ++ ++ port2 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <2>; ++ }; ++}; ++ ++&dcsr { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,dcsr", "simple-bus"; ++ ++ dcsr-epu@0 { ++ compatible = "fsl,p2041-dcsr-epu", "fsl,dcsr-epu"; ++ interrupts = <52 2 0 0 ++ 84 2 0 0 ++ 85 2 0 0>; ++ reg = <0x0 0x1000>; ++ }; ++ dcsr-npc { ++ compatible = "fsl,dcsr-npc"; ++ reg = <0x1000 0x1000 0x1000000 0x8000>; ++ }; ++ dcsr-nxc@2000 { ++ compatible = "fsl,dcsr-nxc"; ++ reg = <0x2000 0x1000>; ++ }; ++ dcsr-corenet { ++ compatible = "fsl,dcsr-corenet"; ++ reg = <0x8000 0x1000 0xB0000 0x1000>; ++ }; ++ dcsr-dpaa@9000 { ++ compatible = "fsl,p2041-dcsr-dpaa", "fsl,dcsr-dpaa"; ++ reg = <0x9000 0x1000>; ++ }; ++ dcsr-ocn@11000 { ++ compatible = "fsl,p2041-dcsr-ocn", "fsl,dcsr-ocn"; ++ reg = <0x11000 0x1000>; ++ }; ++ dcsr-ddr@12000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr1>; ++ reg = <0x12000 0x1000>; ++ }; ++ dcsr-nal@18000 { ++ compatible = "fsl,p2041-dcsr-nal", "fsl,dcsr-nal"; ++ reg = <0x18000 0x1000>; ++ }; ++ dcsr-rcpm@22000 { ++ compatible = "fsl,p2041-dcsr-rcpm", "fsl,dcsr-rcpm"; ++ reg = <0x22000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@40000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu0>; ++ reg = <0x40000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@41000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu1>; ++ reg = <0x41000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@42000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu2>; ++ reg = <0x42000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@43000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu3>; ++ reg = <0x43000 0x1000>; ++ }; ++}; ++ ++&bportals { ++/include/ "qoriq-bman1-portals.dtsi" ++}; ++ ++&qportals { ++/include/ "qoriq-qman1-portals.dtsi" ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "simple-bus"; ++ ++ soc-sram-error { ++ compatible = "fsl,soc-sram-error"; ++ interrupts = <16 2 1 29>; ++ }; ++ ++ corenet-law@0 { ++ compatible = "fsl,corenet-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <32>; ++ }; ++ ++ ddr1: memory-controller@8000 { ++ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller"; ++ reg = <0x8000 0x1000>; ++ interrupts = <16 2 1 23>; ++ }; ++ ++ cpc: l3-cache-controller@10000 { ++ compatible = "fsl,p2041-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache"; ++ reg = <0x10000 0x1000>; ++ interrupts = <16 2 1 27>; ++ }; ++ ++ corenet-cf@18000 { ++ compatible = "fsl,corenet-cf"; ++ reg = <0x18000 0x1000>; ++ interrupts = <16 2 1 31>; ++ fsl,ccf-num-csdids = <32>; ++ fsl,ccf-num-snoopids = <32>; ++ }; ++ ++ iommu@20000 { ++ compatible = "fsl,pamu-v1.0", "fsl,pamu"; ++ reg = <0x20000 0x4000>; ++ interrupts = < ++ 24 2 0 0 ++ 16 2 1 30>; ++ }; ++ ++/include/ "qoriq-mpic.dtsi" ++ ++ guts: global-utilities@e0000 { ++ compatible = "fsl,qoriq-device-config-1.0"; ++ reg = <0xe0000 0xe00>; ++ fsl,has-rstcr; ++ #sleep-cells = <1>; ++ fsl,liodn-bits = <12>; ++ }; ++ ++ pins: global-utilities@e0e00 { ++ compatible = "fsl,qoriq-pin-control-1.0"; ++ reg = <0xe0e00 0x200>; ++ #sleep-cells = <2>; ++ }; ++ ++ clockgen: global-utilities@e1000 { ++ compatible = "fsl,p2041-clockgen", "fsl,qoriq-clockgen-1.0"; ++ reg = <0xe1000 0x1000>; ++ clock-frequency = <0>; ++ }; ++ ++ rcpm: global-utilities@e2000 { ++ compatible = "fsl,qoriq-rcpm-1.0"; ++ reg = <0xe2000 0x1000>; ++ #sleep-cells = <1>; ++ }; ++ ++ sfp: sfp@e8000 { ++ compatible = "fsl,p2041-sfp", "fsl,qoriq-sfp-1.0"; ++ reg = <0xe8000 0x1000>; ++ }; ++ ++ serdes: serdes@ea000 { ++ compatible = "fsl,p2041-serdes"; ++ reg = <0xea000 0x1000>; ++ }; ++ ++/include/ "qoriq-dma-0.dtsi" ++/include/ "qoriq-dma-1.dtsi" ++/include/ "qoriq-espi-0.dtsi" ++ spi@110000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "qoriq-esdhc-0.dtsi" ++ sdhc@114000 { ++ sdhci,auto-cmd12; ++ }; ++ ++/include/ "qoriq-i2c-0.dtsi" ++/include/ "qoriq-i2c-1.dtsi" ++/include/ "qoriq-duart-0.dtsi" ++/include/ "qoriq-duart-1.dtsi" ++/include/ "qoriq-gpio-0.dtsi" ++/include/ "qoriq-usb2-mph-0.dtsi" ++ usb0: usb@210000 { ++ compatible = "fsl-usb2-mph-v1.6", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph"; ++ phy_type = "utmi"; ++ port0; ++ }; ++ ++/include/ "qoriq-usb2-dr-0.dtsi" ++ usb1: usb@211000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr"; ++ dr_mode = "host"; ++ phy_type = "utmi"; ++ }; ++ ++/include/ "qoriq-sata2-0.dtsi" ++ sata@220000 { ++ compatible = "fsl,p2041-sata", "fsl,pq-sata-v2"; ++ }; ++/include/ "qoriq-sata2-1.dtsi" ++ sata@221000 { ++ compatible = "fsl,p2041-sata", "fsl,pq-sata-v2"; ++ }; ++/include/ "qoriq-sec4.2-0.dtsi" ++/include/ "qoriq-pme-0.dtsi" ++/include/ "qoriq-rman-0.dtsi" ++ rman: rman@1e0000 { ++ fsl,qman-channels-id = <0x62 0x63>; ++ }; ++ ++/include/ "qoriq-qman1.dtsi" ++/include/ "qoriq-bman1.dtsi" ++ ++/include/ "qoriq-fman-0.dtsi" ++/include/ "qoriq-fman-0-1g-0.dtsi" ++/include/ "qoriq-fman-0-1g-1.dtsi" ++/include/ "qoriq-fman-0-1g-2.dtsi" ++/include/ "qoriq-fman-0-1g-3.dtsi" ++/include/ "qoriq-fman-0-1g-4.dtsi" ++/include/ "qoriq-fman-0-10g-0.dtsi" ++ fman0: fman@400000 { ++ /* tx - 1g - 0 */ ++ port@a8000 { ++ fsl,qman-channel-id = <0x41>; ++ }; ++ /* tx - 1g - 1 */ ++ port@a9000 { ++ fsl,qman-channel-id = <0x42>; ++ }; ++ /* tx - 1g - 2 */ ++ port@aa000 { ++ fsl,qman-channel-id = <0x43>; ++ }; ++ /* tx - 1g - 3 */ ++ port@ab000 { ++ fsl,qman-channel-id = <0x44>; ++ }; ++ /* tx - 1g - 4 */ ++ port@ac000 { ++ fsl,qman-channel-id = <0x45>; ++ }; ++ /* tx - 10g - 0 */ ++ port@b0000 { ++ fsl,qman-channel-id = <0x40>; ++ }; ++ /* offline 0 */ ++ port@81000 { ++ fsl,qman-channel-id = <0x46>; ++ }; ++ /* offline 1 */ ++ port@82000 { ++ fsl,qman-channel-id = <0x47>; ++ }; ++ /* offline 2 */ ++ port@83000 { ++ fsl,qman-channel-id = <0x48>; ++ }; ++ /* offline 3 */ ++ port@84000 { ++ fsl,qman-channel-id = <0x49>; ++ }; ++ /* offline 4 */ ++ port@85000 { ++ fsl,qman-channel-id = <0x4a>; ++ }; ++ /* offline 5 */ ++ port@86000 { ++ fsl,qman-channel-id = <0x4b>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p2041si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p2041si-pre.dtsi +new file mode 100644 +index 0000000..c463a0b +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p2041si-pre.dtsi +@@ -0,0 +1,120 @@ ++/* ++ * P2041 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500mc_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,P2041"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ ccsr = &soc; ++ dcsr = &dcsr; ++ ++ serial0 = &serial0; ++ serial1 = &serial1; ++ serial2 = &serial2; ++ serial3 = &serial3; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ usb0 = &usb0; ++ usb1 = &usb1; ++ dma0 = &dma0; ++ dma1 = &dma1; ++ sdhc = &sdhc; ++ msi0 = &msi0; ++ msi1 = &msi1; ++ msi2 = &msi2; ++ ++ crypto = &crypto; ++ sec_jr0 = &sec_jr0; ++ sec_jr1 = &sec_jr1; ++ sec_jr2 = &sec_jr2; ++ sec_jr3 = &sec_jr3; ++ rtic_a = &rtic_a; ++ rtic_b = &rtic_b; ++ rtic_c = &rtic_c; ++ rtic_d = &rtic_d; ++ sec_mon = &sec_mon; ++ ++ bman = &bman; ++ qman = &qman; ++ pme = &pme; ++ rman = &rman; ++ fman0 = &fman0; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: PowerPC,e500mc@0 { ++ device_type = "cpu"; ++ reg = <0>; ++ next-level-cache = <&L2_0>; ++ L2_0: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu1: PowerPC,e500mc@1 { ++ device_type = "cpu"; ++ reg = <1>; ++ next-level-cache = <&L2_1>; ++ L2_1: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu2: PowerPC,e500mc@2 { ++ device_type = "cpu"; ++ reg = <2>; ++ next-level-cache = <&L2_2>; ++ L2_2: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu3: PowerPC,e500mc@3 { ++ device_type = "cpu"; ++ reg = <3>; ++ next-level-cache = <&L2_3>; ++ L2_3: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi b/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi +new file mode 100644 +index 0000000..5a8c7e3 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi +@@ -0,0 +1,434 @@ ++/* ++ * P3041 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ compatible = "fsl,p3041-elbc", "fsl,elbc", "simple-bus"; ++ interrupts = <25 2 0 0>; ++ #address-cells = <2>; ++ #size-cells = <1>; ++}; ++ ++/* controller at 0x200000 */ ++&pci0 { ++ compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 15>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 15>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 40 1 0 0 ++ 0000 0 0 2 &mpic 1 1 0 0 ++ 0000 0 0 3 &mpic 2 1 0 0 ++ 0000 0 0 4 &mpic 3 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x201000 */ ++&pci1 { ++ compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 14>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 14>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 41 1 0 0 ++ 0000 0 0 2 &mpic 5 1 0 0 ++ 0000 0 0 3 &mpic 6 1 0 0 ++ 0000 0 0 4 &mpic 7 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x202000 */ ++&pci2 { ++ compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 13>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 13>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 42 1 0 0 ++ 0000 0 0 2 &mpic 9 1 0 0 ++ 0000 0 0 3 &mpic 10 1 0 0 ++ 0000 0 0 4 &mpic 11 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x203000 */ ++&pci3 { ++ compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 12>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 12>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 43 1 0 0 ++ 0000 0 0 2 &mpic 0 1 0 0 ++ 0000 0 0 3 &mpic 4 1 0 0 ++ 0000 0 0 4 &mpic 8 1 0 0 ++ >; ++ }; ++}; ++ ++&rio { ++ compatible = "fsl,srio"; ++ interrupts = <16 2 1 11>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ port1 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <1>; ++ }; ++ ++ port2 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <2>; ++ }; ++}; ++ ++&dcsr { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,dcsr", "simple-bus"; ++ ++ dcsr-epu@0 { ++ compatible = "fsl,p3041-dcsr-epu", "fsl,dcsr-epu"; ++ interrupts = <52 2 0 0 ++ 84 2 0 0 ++ 85 2 0 0>; ++ reg = <0x0 0x1000>; ++ }; ++ dcsr-npc { ++ compatible = "fsl,dcsr-npc"; ++ reg = <0x1000 0x1000 0x1000000 0x8000>; ++ }; ++ dcsr-nxc@2000 { ++ compatible = "fsl,dcsr-nxc"; ++ reg = <0x2000 0x1000>; ++ }; ++ dcsr-corenet { ++ compatible = "fsl,dcsr-corenet"; ++ reg = <0x8000 0x1000 0xB0000 0x1000>; ++ }; ++ dcsr-dpaa@9000 { ++ compatible = "fsl,p3041-dcsr-dpaa", "fsl,dcsr-dpaa"; ++ reg = <0x9000 0x1000>; ++ }; ++ dcsr-ocn@11000 { ++ compatible = "fsl,p3041-dcsr-ocn", "fsl,dcsr-ocn"; ++ reg = <0x11000 0x1000>; ++ }; ++ dcsr-ddr@12000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr1>; ++ reg = <0x12000 0x1000>; ++ }; ++ dcsr-nal@18000 { ++ compatible = "fsl,p3041-dcsr-nal", "fsl,dcsr-nal"; ++ reg = <0x18000 0x1000>; ++ }; ++ dcsr-rcpm@22000 { ++ compatible = "fsl,p3041-dcsr-rcpm", "fsl,dcsr-rcpm"; ++ reg = <0x22000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@40000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu0>; ++ reg = <0x40000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@41000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu1>; ++ reg = <0x41000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@42000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu2>; ++ reg = <0x42000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@43000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu3>; ++ reg = <0x43000 0x1000>; ++ }; ++}; ++ ++&bportals { ++/include/ "qoriq-bman1-portals.dtsi" ++}; ++ ++&qportals { ++/include/ "qoriq-qman1-portals.dtsi" ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "simple-bus"; ++ ++ soc-sram-error { ++ compatible = "fsl,soc-sram-error"; ++ interrupts = <16 2 1 29>; ++ }; ++ ++ corenet-law@0 { ++ compatible = "fsl,corenet-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <32>; ++ }; ++ ++ ddr1: memory-controller@8000 { ++ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller"; ++ reg = <0x8000 0x1000>; ++ interrupts = <16 2 1 23>; ++ }; ++ ++ cpc: l3-cache-controller@10000 { ++ compatible = "fsl,p3041-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache"; ++ reg = <0x10000 0x1000>; ++ interrupts = <16 2 1 27>; ++ }; ++ ++ corenet-cf@18000 { ++ compatible = "fsl,corenet-cf"; ++ reg = <0x18000 0x1000>; ++ interrupts = <16 2 1 31>; ++ fsl,ccf-num-csdids = <32>; ++ fsl,ccf-num-snoopids = <32>; ++ }; ++ ++ iommu@20000 { ++ compatible = "fsl,pamu-v1.0", "fsl,pamu"; ++ reg = <0x20000 0x4000>; ++ interrupts = < ++ 24 2 0 0 ++ 16 2 1 30>; ++ }; ++ ++/include/ "qoriq-mpic.dtsi" ++ ++ guts: global-utilities@e0000 { ++ compatible = "fsl,qoriq-device-config-1.0"; ++ reg = <0xe0000 0xe00>; ++ fsl,has-rstcr; ++ #sleep-cells = <1>; ++ fsl,liodn-bits = <12>; ++ }; ++ ++ pins: global-utilities@e0e00 { ++ compatible = "fsl,qoriq-pin-control-1.0"; ++ reg = <0xe0e00 0x200>; ++ #sleep-cells = <2>; ++ }; ++ ++ clockgen: global-utilities@e1000 { ++ compatible = "fsl,p3041-clockgen", "fsl,qoriq-clockgen-1.0"; ++ reg = <0xe1000 0x1000>; ++ clock-frequency = <0>; ++ }; ++ ++ rcpm: global-utilities@e2000 { ++ compatible = "fsl,qoriq-rcpm-1.0"; ++ reg = <0xe2000 0x1000>; ++ #sleep-cells = <1>; ++ }; ++ ++ sfp: sfp@e8000 { ++ compatible = "fsl,p3041-sfp", "fsl,qoriq-sfp-1.0"; ++ reg = <0xe8000 0x1000>; ++ }; ++ ++ serdes: serdes@ea000 { ++ compatible = "fsl,p3041-serdes"; ++ reg = <0xea000 0x1000>; ++ }; ++ ++/include/ "qoriq-dma-0.dtsi" ++/include/ "qoriq-dma-1.dtsi" ++/include/ "qoriq-espi-0.dtsi" ++ spi@110000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "qoriq-esdhc-0.dtsi" ++ sdhc@114000 { ++ sdhci,auto-cmd12; ++ }; ++ ++/include/ "qoriq-i2c-0.dtsi" ++/include/ "qoriq-i2c-1.dtsi" ++/include/ "qoriq-duart-0.dtsi" ++/include/ "qoriq-duart-1.dtsi" ++/include/ "qoriq-gpio-0.dtsi" ++/include/ "qoriq-usb2-mph-0.dtsi" ++ usb0: usb@210000 { ++ compatible = "fsl-usb2-mph-v1.6", "fsl-usb2-mph"; ++ phy_type = "utmi"; ++ port0; ++ }; ++ ++/include/ "qoriq-usb2-dr-0.dtsi" ++ usb1: usb@211000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr"; ++ dr_mode = "host"; ++ phy_type = "utmi"; ++ }; ++ ++/include/ "qoriq-sata2-0.dtsi" ++ sata@220000 { ++ compatible = "fsl,p3041-sata", "fsl,pq-sata-v2"; ++ }; ++/include/ "qoriq-sata2-1.dtsi" ++ sata@221000 { ++ compatible = "fsl,p3041-sata", "fsl,pq-sata-v2"; ++ }; ++/include/ "qoriq-sec4.2-0.dtsi" ++/include/ "qoriq-pme-0.dtsi" ++/include/ "qoriq-rman-0.dtsi" ++ rman: rman@1e0000 { ++ fsl,qman-channels-id = <0x62 0x63>; ++ }; ++ ++/include/ "qoriq-qman1.dtsi" ++/include/ "qoriq-bman1.dtsi" ++ ++/include/ "qoriq-fman-0.dtsi" ++/include/ "qoriq-fman-0-1g-0.dtsi" ++/include/ "qoriq-fman-0-1g-1.dtsi" ++/include/ "qoriq-fman-0-1g-2.dtsi" ++/include/ "qoriq-fman-0-1g-3.dtsi" ++/include/ "qoriq-fman-0-1g-4.dtsi" ++/include/ "qoriq-fman-0-10g-0.dtsi" ++ fman0: fman@400000 { ++ /* tx - 1g - 0 */ ++ port@a8000 { ++ fsl,qman-channel-id = <0x41>; ++ }; ++ /* tx - 1g - 1 */ ++ port@a9000 { ++ fsl,qman-channel-id = <0x42>; ++ }; ++ /* tx - 1g - 2 */ ++ port@aa000 { ++ fsl,qman-channel-id = <0x43>; ++ }; ++ /* tx - 1g - 3 */ ++ port@ab000 { ++ fsl,qman-channel-id = <0x44>; ++ }; ++ /* tx - 1g - 4 */ ++ port@ac000 { ++ fsl,qman-channel-id = <0x45>; ++ }; ++ /* tx - 10g - 0 */ ++ port@b0000 { ++ fsl,qman-channel-id = <0x40>; ++ }; ++ /* offline 0 */ ++ port@81000 { ++ fsl,qman-channel-id = <0x46>; ++ }; ++ /* offline 1 */ ++ port@82000 { ++ fsl,qman-channel-id = <0x47>; ++ }; ++ /* offline 2 */ ++ port@83000 { ++ fsl,qman-channel-id = <0x48>; ++ }; ++ /* offline 3 */ ++ port@84000 { ++ fsl,qman-channel-id = <0x49>; ++ }; ++ /* offline 4 */ ++ port@85000 { ++ fsl,qman-channel-id = <0x4a>; ++ }; ++ /* offline 5 */ ++ port@86000 { ++ fsl,qman-channel-id = <0x4b>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p3041si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p3041si-pre.dtsi +new file mode 100644 +index 0000000..18ba76f +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p3041si-pre.dtsi +@@ -0,0 +1,121 @@ ++/* ++ * P3041 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500mc_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,P3041"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ ccsr = &soc; ++ dcsr = &dcsr; ++ ++ serial0 = &serial0; ++ serial1 = &serial1; ++ serial2 = &serial2; ++ serial3 = &serial3; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ pci3 = &pci3; ++ usb0 = &usb0; ++ usb1 = &usb1; ++ dma0 = &dma0; ++ dma1 = &dma1; ++ sdhc = &sdhc; ++ msi0 = &msi0; ++ msi1 = &msi1; ++ msi2 = &msi2; ++ ++ crypto = &crypto; ++ sec_jr0 = &sec_jr0; ++ sec_jr1 = &sec_jr1; ++ sec_jr2 = &sec_jr2; ++ sec_jr3 = &sec_jr3; ++ rtic_a = &rtic_a; ++ rtic_b = &rtic_b; ++ rtic_c = &rtic_c; ++ rtic_d = &rtic_d; ++ sec_mon = &sec_mon; ++ ++ bman = &bman; ++ qman = &qman; ++ pme = &pme; ++ rman = &rman; ++ fman0 = &fman0; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: PowerPC,e500mc@0 { ++ device_type = "cpu"; ++ reg = <0>; ++ next-level-cache = <&L2_0>; ++ L2_0: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu1: PowerPC,e500mc@1 { ++ device_type = "cpu"; ++ reg = <1>; ++ next-level-cache = <&L2_1>; ++ L2_1: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu2: PowerPC,e500mc@2 { ++ device_type = "cpu"; ++ reg = <2>; ++ next-level-cache = <&L2_2>; ++ L2_2: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu3: PowerPC,e500mc@3 { ++ device_type = "cpu"; ++ reg = <3>; ++ next-level-cache = <&L2_3>; ++ L2_3: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi b/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi +new file mode 100644 +index 0000000..01ce97e +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi +@@ -0,0 +1,481 @@ ++/* ++ * P4080/P4040 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ compatible = "fsl,p4080-elbc", "fsl,elbc", "simple-bus"; ++ interrupts = <25 2 0 0>; ++ #address-cells = <2>; ++ #size-cells = <1>; ++}; ++ ++/* controller at 0x200000 */ ++&pci0 { ++ compatible = "fsl,p4080-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 15>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 15>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 40 1 0 0 ++ 0000 0 0 2 &mpic 1 1 0 0 ++ 0000 0 0 3 &mpic 2 1 0 0 ++ 0000 0 0 4 &mpic 3 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x201000 */ ++&pci1 { ++ compatible = "fsl,p4080-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 14>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 14>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 41 1 0 0 ++ 0000 0 0 2 &mpic 5 1 0 0 ++ 0000 0 0 3 &mpic 6 1 0 0 ++ 0000 0 0 4 &mpic 7 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x202000 */ ++&pci2 { ++ compatible = "fsl,p4080-pcie"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 13>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 13>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 42 1 0 0 ++ 0000 0 0 2 &mpic 9 1 0 0 ++ 0000 0 0 3 &mpic 10 1 0 0 ++ 0000 0 0 4 &mpic 11 1 0 0 ++ >; ++ }; ++}; ++ ++&rio { ++ compatible = "fsl,srio"; ++ interrupts = <16 2 1 11>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ fsl,srio-rmu-handle = <&rmu>; ++ ranges; ++ ++ port1 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <1>; ++ }; ++ ++ port2 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <2>; ++ }; ++}; ++ ++&dcsr { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,dcsr", "simple-bus"; ++ ++ dcsr-epu@0 { ++ compatible = "fsl,p4080-dcsr-epu", "fsl,dcsr-epu"; ++ interrupts = <52 2 0 0 ++ 84 2 0 0 ++ 85 2 0 0>; ++ reg = <0x0 0x1000>; ++ }; ++ dcsr-npc { ++ compatible = "fsl,dcsr-npc"; ++ reg = <0x1000 0x1000 0x1000000 0x8000>; ++ }; ++ dcsr-nxc@2000 { ++ compatible = "fsl,dcsr-nxc"; ++ reg = <0x2000 0x1000>; ++ }; ++ dcsr-corenet { ++ compatible = "fsl,dcsr-corenet"; ++ reg = <0x8000 0x1000 0xB0000 0x1000>; ++ }; ++ dcsr-dpaa@9000 { ++ compatible = "fsl,p4080-dcsr-dpaa", "fsl,dcsr-dpaa"; ++ reg = <0x9000 0x1000>; ++ }; ++ dcsr-ocn@11000 { ++ compatible = "fsl,p4080-dcsr-ocn", "fsl,dcsr-ocn"; ++ reg = <0x11000 0x1000>; ++ }; ++ dcsr-ddr@12000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr1>; ++ reg = <0x12000 0x1000>; ++ }; ++ dcsr-ddr@13000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr2>; ++ reg = <0x13000 0x1000>; ++ }; ++ dcsr-nal@18000 { ++ compatible = "fsl,p4080-dcsr-nal", "fsl,dcsr-nal"; ++ reg = <0x18000 0x1000>; ++ }; ++ dcsr-rcpm@22000 { ++ compatible = "fsl,p4080-dcsr-rcpm", "fsl,dcsr-rcpm"; ++ reg = <0x22000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@40000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu0>; ++ reg = <0x40000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@41000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu1>; ++ reg = <0x41000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@42000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu2>; ++ reg = <0x42000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@43000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu3>; ++ reg = <0x43000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@44000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu4>; ++ reg = <0x44000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@45000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu5>; ++ reg = <0x45000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@46000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu6>; ++ reg = <0x46000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@47000 { ++ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu7>; ++ reg = <0x47000 0x1000>; ++ }; ++ ++}; ++ ++&bportals { ++/include/ "qoriq-bman1-portals.dtsi" ++}; ++ ++&qportals { ++/include/ "qoriq-qman1-portals.dtsi" ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "simple-bus"; ++ ++ soc-sram-error { ++ compatible = "fsl,soc-sram-error"; ++ interrupts = <16 2 1 29>; ++ }; ++ ++ corenet-law@0 { ++ compatible = "fsl,corenet-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <32>; ++ }; ++ ++ ddr1: memory-controller@8000 { ++ compatible = "fsl,qoriq-memory-controller-v4.4", "fsl,qoriq-memory-controller"; ++ reg = <0x8000 0x1000>; ++ interrupts = <16 2 1 23>; ++ }; ++ ++ ddr2: memory-controller@9000 { ++ compatible = "fsl,qoriq-memory-controller-v4.4","fsl,qoriq-memory-controller"; ++ reg = <0x9000 0x1000>; ++ interrupts = <16 2 1 22>; ++ }; ++ ++ cpc: l3-cache-controller@10000 { ++ compatible = "fsl,p4080-l3-cache-controller", "cache"; ++ reg = <0x10000 0x1000 ++ 0x11000 0x1000>; ++ interrupts = <16 2 1 27 ++ 16 2 1 26>; ++ }; ++ ++ corenet-cf@18000 { ++ compatible = "fsl,corenet-cf"; ++ reg = <0x18000 0x1000>; ++ interrupts = <16 2 1 31>; ++ fsl,ccf-num-csdids = <32>; ++ fsl,ccf-num-snoopids = <32>; ++ }; ++ ++ iommu@20000 { ++ compatible = "fsl,pamu-v1.0", "fsl,pamu"; ++ reg = <0x20000 0x5000>; ++ interrupts = < ++ 24 2 0 0 ++ 16 2 1 30>; ++ }; ++ ++/include/ "qoriq-rmu-0.dtsi" ++/include/ "qoriq-mpic.dtsi" ++ ++ guts: global-utilities@e0000 { ++ compatible = "fsl,qoriq-device-config-1.0"; ++ reg = <0xe0000 0xe00>; ++ fsl,has-rstcr; ++ #sleep-cells = <1>; ++ fsl,liodn-bits = <12>; ++ }; ++ ++ pins: global-utilities@e0e00 { ++ compatible = "fsl,qoriq-pin-control-1.0"; ++ reg = <0xe0e00 0x200>; ++ #sleep-cells = <2>; ++ }; ++ ++ clockgen: global-utilities@e1000 { ++ compatible = "fsl,p4080-clockgen", "fsl,qoriq-clockgen-1.0"; ++ reg = <0xe1000 0x1000>; ++ clock-frequency = <0>; ++ }; ++ ++ rcpm: global-utilities@e2000 { ++ compatible = "fsl,qoriq-rcpm-1.0"; ++ reg = <0xe2000 0x1000>; ++ #sleep-cells = <1>; ++ }; ++ ++ sfp: sfp@e8000 { ++ compatible = "fsl,p4080-sfp", "fsl,qoriq-sfp-1.0"; ++ reg = <0xe8000 0x1000>; ++ }; ++ ++ serdes: serdes@ea000 { ++ compatible = "fsl,p4080-serdes"; ++ reg = <0xea000 0x1000>; ++ }; ++ ++/include/ "qoriq-dma-0.dtsi" ++/include/ "qoriq-dma-1.dtsi" ++/include/ "qoriq-espi-0.dtsi" ++ spi@110000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "qoriq-esdhc-0.dtsi" ++ sdhc@114000 { ++ voltage-ranges = <3300 3300>; ++ sdhci,auto-cmd12; ++ }; ++ ++/include/ "qoriq-i2c-0.dtsi" ++/include/ "qoriq-i2c-1.dtsi" ++/include/ "qoriq-duart-0.dtsi" ++/include/ "qoriq-duart-1.dtsi" ++/include/ "qoriq-gpio-0.dtsi" ++/include/ "qoriq-usb2-mph-0.dtsi" ++ usb@210000 { ++ compatible = "fsl-usb2-mph-v1.6", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph"; ++ port0; ++ }; ++/include/ "qoriq-usb2-dr-0.dtsi" ++ usb@211000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr"; ++ }; ++/include/ "qoriq-sec4.0-0.dtsi" ++/include/ "qoriq-pme-0.dtsi" ++/include/ "qoriq-qman1.dtsi" ++/include/ "qoriq-bman1.dtsi" ++/include/ "qoriq-fman-0.dtsi" ++/include/ "qoriq-fman-0-1g-0.dtsi" ++/include/ "qoriq-fman-0-1g-1.dtsi" ++/include/ "qoriq-fman-0-1g-2.dtsi" ++/include/ "qoriq-fman-0-1g-3.dtsi" ++/include/ "qoriq-fman-0-10g-0.dtsi" ++ fman0: fman@400000 { ++ /* tx - 1g - 0 */ ++ port@a8000 { ++ fsl,qman-channel-id = <0x41>; ++ }; ++ /* tx - 1g - 1 */ ++ port@a9000 { ++ fsl,qman-channel-id = <0x42>; ++ }; ++ /* tx - 1g - 2 */ ++ port@aa000 { ++ fsl,qman-channel-id = <0x43>; ++ }; ++ /* tx - 1g - 3 */ ++ port@ab000 { ++ fsl,qman-channel-id = <0x44>; ++ }; ++ /* tx - 10g - 0 */ ++ port@b0000 { ++ fsl,qman-channel-id = <0x40>; ++ }; ++ /* offline 0 */ ++ port@81000 { ++ fsl,qman-channel-id = <0x45>; ++ }; ++ /* offline 1 */ ++ port@82000 { ++ fsl,qman-channel-id = <0x46>; ++ }; ++ /* offline 2 */ ++ port@83000 { ++ fsl,qman-channel-id = <0x47>; ++ }; ++ /* offline 3 */ ++ port@84000 { ++ fsl,qman-channel-id = <0x48>; ++ }; ++ /* offline 4 */ ++ port@85000 { ++ fsl,qman-channel-id = <0x49>; ++ }; ++ /* offline 5 */ ++ port@86000 { ++ fsl,qman-channel-id = <0x4a>; ++ }; ++ /* offline 6 */ ++ port@87000 { ++ fsl,qman-channel-id = <0x4b>; ++ }; ++ }; ++ ++/include/ "qoriq-fman-1.dtsi" ++/include/ "qoriq-fman-1-1g-0.dtsi" ++/include/ "qoriq-fman-1-1g-1.dtsi" ++/include/ "qoriq-fman-1-1g-2.dtsi" ++/include/ "qoriq-fman-1-1g-3.dtsi" ++/include/ "qoriq-fman-1-10g-0.dtsi" ++ fman1: fman@500000 { ++ /* tx - 1g - 0 */ ++ port@a8000 { ++ fsl,qman-channel-id = <0x61>; ++ }; ++ /* tx - 1g - 1 */ ++ port@a9000 { ++ fsl,qman-channel-id = <0x62>; ++ }; ++ /* tx - 1g - 2 */ ++ port@aa000 { ++ fsl,qman-channel-id = <0x63>; ++ }; ++ /* tx - 1g - 3 */ ++ port@ab000 { ++ fsl,qman-channel-id = <0x64>; ++ }; ++ /* tx - 10g - 0 */ ++ port@b0000 { ++ fsl,qman-channel-id = <0x60>; ++ }; ++ /* offline 0 */ ++ port@81000 { ++ fsl,qman-channel-id = <0x65>; ++ }; ++ /* offline 1 */ ++ port@82000 { ++ fsl,qman-channel-id = <0x66>; ++ }; ++ /* offline 2 */ ++ port@83000 { ++ fsl,qman-channel-id = <0x67>; ++ }; ++ /* offline 3 */ ++ port@84000 { ++ fsl,qman-channel-id = <0x68>; ++ }; ++ /* offline 4 */ ++ port@85000 { ++ fsl,qman-channel-id = <0x69>; ++ }; ++ /* offline 5 */ ++ port@86000 { ++ fsl,qman-channel-id = <0x6a>; ++ }; ++ /* offline 6 */ ++ port@87000 { ++ fsl,qman-channel-id = <0x6b>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p4080si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p4080si-pre.dtsi +new file mode 100644 +index 0000000..aea2e14 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p4080si-pre.dtsi +@@ -0,0 +1,152 @@ ++/* ++ * P4080/P4040 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e500mc_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,P4080"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ ccsr = &soc; ++ dcsr = &dcsr; ++ ++ serial0 = &serial0; ++ serial1 = &serial1; ++ serial2 = &serial2; ++ serial3 = &serial3; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ usb0 = &usb0; ++ usb1 = &usb1; ++ dma0 = &dma0; ++ dma1 = &dma1; ++ sdhc = &sdhc; ++ msi0 = &msi0; ++ msi1 = &msi1; ++ msi2 = &msi2; ++ ++ crypto = &crypto; ++ sec_jr0 = &sec_jr0; ++ sec_jr1 = &sec_jr1; ++ sec_jr2 = &sec_jr2; ++ sec_jr3 = &sec_jr3; ++ rtic_a = &rtic_a; ++ rtic_b = &rtic_b; ++ rtic_c = &rtic_c; ++ rtic_d = &rtic_d; ++ sec_mon = &sec_mon; ++ ++ bman = &bman; ++ qman = &qman; ++ pme = &pme; ++ fman0 = &fman0; ++ fman1 = &fman1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: PowerPC,e500mc@0 { ++ device_type = "cpu"; ++ reg = <0>; ++ next-level-cache = <&L2_0>; ++ L2_0: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu1: PowerPC,e500mc@1 { ++ device_type = "cpu"; ++ reg = <1>; ++ next-level-cache = <&L2_1>; ++ L2_1: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu2: PowerPC,e500mc@2 { ++ device_type = "cpu"; ++ reg = <2>; ++ next-level-cache = <&L2_2>; ++ L2_2: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu3: PowerPC,e500mc@3 { ++ device_type = "cpu"; ++ reg = <3>; ++ next-level-cache = <&L2_3>; ++ L2_3: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu4: PowerPC,e500mc@4 { ++ device_type = "cpu"; ++ reg = <4>; ++ next-level-cache = <&L2_4>; ++ L2_4: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu5: PowerPC,e500mc@5 { ++ device_type = "cpu"; ++ reg = <5>; ++ next-level-cache = <&L2_5>; ++ L2_5: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu6: PowerPC,e500mc@6 { ++ device_type = "cpu"; ++ reg = <6>; ++ next-level-cache = <&L2_6>; ++ L2_6: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu7: PowerPC,e500mc@7 { ++ device_type = "cpu"; ++ reg = <7>; ++ next-level-cache = <&L2_7>; ++ L2_7: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi +new file mode 100644 +index 0000000..3a330c1 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi +@@ -0,0 +1,439 @@ ++/* ++ * P5020/5010 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ compatible = "fsl,p5020-elbc", "fsl,elbc", "simple-bus"; ++ interrupts = <25 2 0 0>; ++ #address-cells = <2>; ++ #size-cells = <1>; ++}; ++ ++/* controller at 0x200000 */ ++&pci0 { ++ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 15>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 15>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 40 1 0 0 ++ 0000 0 0 2 &mpic 1 1 0 0 ++ 0000 0 0 3 &mpic 2 1 0 0 ++ 0000 0 0 4 &mpic 3 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x201000 */ ++&pci1 { ++ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 14>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 14>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 41 1 0 0 ++ 0000 0 0 2 &mpic 5 1 0 0 ++ 0000 0 0 3 &mpic 6 1 0 0 ++ 0000 0 0 4 &mpic 7 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x202000 */ ++&pci2 { ++ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 13>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 13>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 42 1 0 0 ++ 0000 0 0 2 &mpic 9 1 0 0 ++ 0000 0 0 3 &mpic 10 1 0 0 ++ 0000 0 0 4 &mpic 11 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x203000 */ ++&pci3 { ++ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 12>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 12>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 43 1 0 0 ++ 0000 0 0 2 &mpic 0 1 0 0 ++ 0000 0 0 3 &mpic 4 1 0 0 ++ 0000 0 0 4 &mpic 8 1 0 0 ++ >; ++ }; ++}; ++ ++&rio { ++ compatible = "fsl,srio"; ++ interrupts = <16 2 1 11>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ port1 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <1>; ++ }; ++ ++ port2 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <2>; ++ }; ++}; ++ ++&dcsr { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,dcsr", "simple-bus"; ++ ++ dcsr-epu@0 { ++ compatible = "fsl,p5020-dcsr-epu", "fsl,dcsr-epu"; ++ interrupts = <52 2 0 0 ++ 84 2 0 0 ++ 85 2 0 0>; ++ reg = <0x0 0x1000>; ++ }; ++ dcsr-npc { ++ compatible = "fsl,dcsr-npc"; ++ reg = <0x1000 0x1000 0x1000000 0x8000>; ++ }; ++ dcsr-nxc@2000 { ++ compatible = "fsl,dcsr-nxc"; ++ reg = <0x2000 0x1000>; ++ }; ++ dcsr-corenet { ++ compatible = "fsl,dcsr-corenet"; ++ reg = <0x8000 0x1000 0xB0000 0x1000>; ++ }; ++ dcsr-dpaa@9000 { ++ compatible = "fsl,p5020-dcsr-dpaa", "fsl,dcsr-dpaa"; ++ reg = <0x9000 0x1000>; ++ }; ++ dcsr-ocn@11000 { ++ compatible = "fsl,p5020-dcsr-ocn", "fsl,dcsr-ocn"; ++ reg = <0x11000 0x1000>; ++ }; ++ dcsr-ddr@12000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr1>; ++ reg = <0x12000 0x1000>; ++ }; ++ dcsr-ddr@13000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr2>; ++ reg = <0x13000 0x1000>; ++ }; ++ dcsr-nal@18000 { ++ compatible = "fsl,p5020-dcsr-nal", "fsl,dcsr-nal"; ++ reg = <0x18000 0x1000>; ++ }; ++ dcsr-rcpm@22000 { ++ compatible = "fsl,p5020-dcsr-rcpm", "fsl,dcsr-rcpm"; ++ reg = <0x22000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@40000 { ++ compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu0>; ++ reg = <0x40000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@41000 { ++ compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu1>; ++ reg = <0x41000 0x1000>; ++ }; ++}; ++ ++&bportals { ++/include/ "qoriq-bman1-portals.dtsi" ++}; ++ ++&qportals { ++/include/ "qoriq-qman1-portals.dtsi" ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "simple-bus"; ++ ++ soc-sram-error { ++ compatible = "fsl,soc-sram-error"; ++ interrupts = <16 2 1 29>; ++ }; ++ ++ corenet-law@0 { ++ compatible = "fsl,corenet-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <32>; ++ }; ++ ++ ddr1: memory-controller@8000 { ++ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller"; ++ reg = <0x8000 0x1000>; ++ interrupts = <16 2 1 23>; ++ }; ++ ++ ddr2: memory-controller@9000 { ++ compatible = "fsl,qoriq-memory-controller-v4.5","fsl,qoriq-memory-controller"; ++ reg = <0x9000 0x1000>; ++ interrupts = <16 2 1 22>; ++ }; ++ ++ cpc: l3-cache-controller@10000 { ++ compatible = "fsl,p5020-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache"; ++ reg = <0x10000 0x1000 ++ 0x11000 0x1000>; ++ interrupts = <16 2 1 27 ++ 16 2 1 26>; ++ }; ++ ++ corenet-cf@18000 { ++ compatible = "fsl,corenet-cf"; ++ reg = <0x18000 0x1000>; ++ interrupts = <16 2 1 31>; ++ fsl,ccf-num-csdids = <32>; ++ fsl,ccf-num-snoopids = <32>; ++ }; ++ ++ iommu@20000 { ++ compatible = "fsl,pamu-v1.0", "fsl,pamu"; ++ reg = <0x20000 0x4000>; ++ interrupts = < ++ 24 2 0 0 ++ 16 2 1 30>; ++ }; ++ ++/include/ "qoriq-mpic.dtsi" ++ ++ guts: global-utilities@e0000 { ++ compatible = "fsl,qoriq-device-config-1.0"; ++ reg = <0xe0000 0xe00>; ++ fsl,has-rstcr; ++ #sleep-cells = <1>; ++ fsl,liodn-bits = <12>; ++ }; ++ ++ pins: global-utilities@e0e00 { ++ compatible = "fsl,qoriq-pin-control-1.0"; ++ reg = <0xe0e00 0x200>; ++ #sleep-cells = <2>; ++ }; ++ ++ clockgen: global-utilities@e1000 { ++ compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0"; ++ reg = <0xe1000 0x1000>; ++ clock-frequency = <0>; ++ }; ++ ++ rcpm: global-utilities@e2000 { ++ compatible = "fsl,qoriq-rcpm-1.0"; ++ reg = <0xe2000 0x1000>; ++ #sleep-cells = <1>; ++ }; ++ ++ sfp: sfp@e8000 { ++ compatible = "fsl,p5020-sfp", "fsl,qoriq-sfp-1.0"; ++ reg = <0xe8000 0x1000>; ++ }; ++ ++ serdes: serdes@ea000 { ++ compatible = "fsl,p5020-serdes"; ++ reg = <0xea000 0x1000>; ++ }; ++ ++/include/ "qoriq-dma-0.dtsi" ++/include/ "qoriq-dma-1.dtsi" ++/include/ "qoriq-espi-0.dtsi" ++ spi@110000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "qoriq-esdhc-0.dtsi" ++ sdhc@114000 { ++ sdhci,auto-cmd12; ++ }; ++ ++/include/ "qoriq-i2c-0.dtsi" ++/include/ "qoriq-i2c-1.dtsi" ++/include/ "qoriq-duart-0.dtsi" ++/include/ "qoriq-duart-1.dtsi" ++/include/ "qoriq-gpio-0.dtsi" ++/include/ "qoriq-usb2-mph-0.dtsi" ++ usb0: usb@210000 { ++ compatible = "fsl-usb2-mph-v1.6", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph"; ++ phy_type = "utmi"; ++ port0; ++ }; ++ ++/include/ "qoriq-usb2-dr-0.dtsi" ++ usb1: usb@211000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr"; ++ dr_mode = "host"; ++ phy_type = "utmi"; ++ }; ++ ++/include/ "qoriq-sata2-0.dtsi" ++ sata@220000 { ++ compatible = "fsl,p5020-sata", "fsl,pq-sata-v2"; ++ }; ++/include/ "qoriq-sata2-1.dtsi" ++ sata@221000 { ++ compatible = "fsl,p5020-sata", "fsl,pq-sata-v2"; ++ }; ++/include/ "qoriq-sec4.2-0.dtsi" ++/include/ "qoriq-pme-0.dtsi" ++/include/ "qoriq-rman-0.dtsi" ++ rman: rman@1e0000 { ++ fsl,qman-channels-id = <0x62 0x63>; ++ }; ++ ++/include/ "qoriq-qman1.dtsi" ++/include/ "qoriq-bman1.dtsi" ++ ++/include/ "qoriq-fman-0.dtsi" ++/include/ "qoriq-fman-0-1g-0.dtsi" ++/include/ "qoriq-fman-0-1g-1.dtsi" ++/include/ "qoriq-fman-0-1g-2.dtsi" ++/include/ "qoriq-fman-0-1g-3.dtsi" ++/include/ "qoriq-fman-0-1g-4.dtsi" ++/include/ "qoriq-fman-0-10g-0.dtsi" ++ fman0: fman@400000 { ++ /* tx - 1g - 0 */ ++ port@a8000 { ++ fsl,qman-channel-id = <0x41>; ++ }; ++ /* tx - 1g - 1 */ ++ port@a9000 { ++ fsl,qman-channel-id = <0x42>; ++ }; ++ /* tx - 1g - 2 */ ++ port@aa000 { ++ fsl,qman-channel-id = <0x43>; ++ }; ++ /* tx - 1g - 3 */ ++ port@ab000 { ++ fsl,qman-channel-id = <0x44>; ++ }; ++ /* tx - 1g - 4 */ ++ port@ac000 { ++ fsl,qman-channel-id = <0x45>; ++ }; ++ /* tx - 10g - 0 */ ++ port@b0000 { ++ fsl,qman-channel-id = <0x40>; ++ }; ++ /* offline 0 */ ++ port@81000 { ++ fsl,qman-channel-id = <0x46>; ++ }; ++ /* offline 1 */ ++ port@82000 { ++ fsl,qman-channel-id = <0x47>; ++ }; ++ /* offline 2 */ ++ port@83000 { ++ fsl,qman-channel-id = <0x48>; ++ }; ++ /* offline 3 */ ++ port@84000 { ++ fsl,qman-channel-id = <0x49>; ++ }; ++ /* offline 4 */ ++ port@85000 { ++ fsl,qman-channel-id = <0x4a>; ++ }; ++ /* offline 5 */ ++ port@86000 { ++ fsl,qman-channel-id = <0x4b>; ++ }; ++ }; ++ ++/include/ "qoriq-raid1.0-0.dtsi" ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi +new file mode 100644 +index 0000000..8cda17b +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi +@@ -0,0 +1,111 @@ ++/* ++ * P5020/P5010 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e5500_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,P5020"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ ccsr = &soc; ++ dcsr = &dcsr; ++ ++ serial0 = &serial0; ++ serial1 = &serial1; ++ serial2 = &serial2; ++ serial3 = &serial3; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ pci3 = &pci3; ++ usb0 = &usb0; ++ usb1 = &usb1; ++ dma0 = &dma0; ++ dma1 = &dma1; ++ sdhc = &sdhc; ++ msi0 = &msi0; ++ msi1 = &msi1; ++ msi2 = &msi2; ++ ++ crypto = &crypto; ++ sec_jr0 = &sec_jr0; ++ sec_jr1 = &sec_jr1; ++ sec_jr2 = &sec_jr2; ++ sec_jr3 = &sec_jr3; ++ rtic_a = &rtic_a; ++ rtic_b = &rtic_b; ++ rtic_c = &rtic_c; ++ rtic_d = &rtic_d; ++ sec_mon = &sec_mon; ++ ++ raideng = &raideng; ++ raideng_jr0 = &raideng_jr0; ++ raideng_jr1 = &raideng_jr1; ++ raideng_jr2 = &raideng_jr2; ++ raideng_jr3 = &raideng_jr3; ++ ++ bman = &bman; ++ qman = &qman; ++ pme = &pme; ++ rman = &rman; ++ fman0 = &fman0; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: PowerPC,e5500@0 { ++ device_type = "cpu"; ++ reg = <0>; ++ next-level-cache = <&L2_0>; ++ L2_0: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu1: PowerPC,e5500@1 { ++ device_type = "cpu"; ++ reg = <1>; ++ next-level-cache = <&L2_1>; ++ L2_1: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi b/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi +new file mode 100644 +index 0000000..7eee08c +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi +@@ -0,0 +1,448 @@ ++/* ++ * P5040 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * This software is provided by Freescale Semiconductor "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 Freescale Semiconductor 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. ++ */ ++ ++&lbc { ++ compatible = "fsl,p5040-elbc", "fsl,elbc", "simple-bus"; ++ interrupts = <25 2 0 0>; ++ #address-cells = <2>; ++ #size-cells = <1>; ++}; ++ ++/* controller at 0x200000 */ ++&pci0 { ++ compatible = "fsl,p5040-pcie", "fsl,qoriq-pcie-v2.4", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 15>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 15>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 40 1 0 0 ++ 0000 0 0 2 &mpic 1 1 0 0 ++ 0000 0 0 3 &mpic 2 1 0 0 ++ 0000 0 0 4 &mpic 3 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x201000 */ ++&pci1 { ++ compatible = "fsl,p5040-pcie", "fsl,qoriq-pcie-v2.4", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 14>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 14>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 41 1 0 0 ++ 0000 0 0 2 &mpic 5 1 0 0 ++ 0000 0 0 3 &mpic 6 1 0 0 ++ 0000 0 0 4 &mpic 7 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x202000 */ ++&pci2 { ++ compatible = "fsl,p5040-pcie", "fsl,qoriq-pcie-v2.4", "fsl,qoriq-pcie-v2.2"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <16 2 1 13>; ++ pcie@0 { ++ reg = <0 0 0 0 0>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <16 2 1 13>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 42 1 0 0 ++ 0000 0 0 2 &mpic 9 1 0 0 ++ 0000 0 0 3 &mpic 10 1 0 0 ++ 0000 0 0 4 &mpic 11 1 0 0 ++ >; ++ }; ++}; ++ ++&dcsr { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,dcsr", "simple-bus"; ++ ++ dcsr-epu@0 { ++ compatible = "fsl,p5040-dcsr-epu", "fsl,dcsr-epu"; ++ interrupts = <52 2 0 0 ++ 84 2 0 0 ++ 85 2 0 0>; ++ reg = <0x0 0x1000>; ++ }; ++ dcsr-npc { ++ compatible = "fsl,dcsr-npc"; ++ reg = <0x1000 0x1000 0x1000000 0x8000>; ++ }; ++ dcsr-nxc@2000 { ++ compatible = "fsl,dcsr-nxc"; ++ reg = <0x2000 0x1000>; ++ }; ++ dcsr-corenet { ++ compatible = "fsl,dcsr-corenet"; ++ reg = <0x8000 0x1000 0xB0000 0x1000>; ++ }; ++ dcsr-dpaa@9000 { ++ compatible = "fsl,p5040-dcsr-dpaa", "fsl,dcsr-dpaa"; ++ reg = <0x9000 0x1000>; ++ }; ++ dcsr-ocn@11000 { ++ compatible = "fsl,p5040-dcsr-ocn", "fsl,dcsr-ocn"; ++ reg = <0x11000 0x1000>; ++ }; ++ dcsr-ddr@12000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr1>; ++ reg = <0x12000 0x1000>; ++ }; ++ dcsr-ddr@13000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr2>; ++ reg = <0x13000 0x1000>; ++ }; ++ dcsr-nal@18000 { ++ compatible = "fsl,p5040-dcsr-nal", "fsl,dcsr-nal"; ++ reg = <0x18000 0x1000>; ++ }; ++ dcsr-rcpm@22000 { ++ compatible = "fsl,p5040-dcsr-rcpm", "fsl,dcsr-rcpm"; ++ reg = <0x22000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@40000 { ++ compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu0>; ++ reg = <0x40000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@41000 { ++ compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu1>; ++ reg = <0x41000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@42000 { ++ compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu2>; ++ reg = <0x42000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@43000 { ++ compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu3>; ++ reg = <0x43000 0x1000>; ++ }; ++}; ++ ++&bportals { ++/include/ "qoriq-bman1-portals.dtsi" ++}; ++ ++&qportals { ++/include/ "qoriq-qman1-portals.dtsi" ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "simple-bus"; ++ ++ soc-sram-error { ++ compatible = "fsl,soc-sram-error"; ++ interrupts = <16 2 1 29>; ++ }; ++ ++ corenet-law@0 { ++ compatible = "fsl,corenet-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <32>; ++ }; ++ ++ ddr1: memory-controller@8000 { ++ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller"; ++ reg = <0x8000 0x1000>; ++ interrupts = <16 2 1 23>; ++ }; ++ ++ ddr2: memory-controller@9000 { ++ compatible = "fsl,qoriq-memory-controller-v4.5","fsl,qoriq-memory-controller"; ++ reg = <0x9000 0x1000>; ++ interrupts = <16 2 1 22>; ++ }; ++ ++ cpc: l3-cache-controller@10000 { ++ compatible = "fsl,p5040-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache"; ++ reg = <0x10000 0x1000 ++ 0x11000 0x1000>; ++ interrupts = <16 2 1 27 ++ 16 2 1 26>; ++ }; ++ ++ corenet-cf@18000 { ++ compatible = "fsl,corenet-cf"; ++ reg = <0x18000 0x1000>; ++ interrupts = <16 2 1 31>; ++ fsl,ccf-num-csdids = <32>; ++ fsl,ccf-num-snoopids = <32>; ++ }; ++ ++ iommu@20000 { ++ compatible = "fsl,pamu-v1.0", "fsl,pamu"; ++ reg = <0x20000 0x5000>; ++ interrupts = < ++ 24 2 0 0 ++ 16 2 1 30>; ++ }; ++ ++/include/ "qoriq-mpic.dtsi" ++ ++ guts: global-utilities@e0000 { ++ compatible = "fsl,p5040-device-config", "fsl,qoriq-device-config-1.0"; ++ reg = <0xe0000 0xe00>; ++ fsl,has-rstcr; ++ #sleep-cells = <1>; ++ fsl,liodn-bits = <12>; ++ }; ++ ++ pins: global-utilities@e0e00 { ++ compatible = "fsl,p5040-pin-control", "fsl,qoriq-pin-control-1.0"; ++ reg = <0xe0e00 0x200>; ++ #sleep-cells = <2>; ++ }; ++ ++ clockgen: global-utilities@e1000 { ++ compatible = "fsl,p5040-clockgen", "fsl,qoriq-clockgen-1.0"; ++ reg = <0xe1000 0x1000>; ++ clock-frequency = <0>; ++ }; ++ ++ rcpm: global-utilities@e2000 { ++ compatible = "fsl,p5040-rcpm", "fsl,qoriq-rcpm-1.0"; ++ reg = <0xe2000 0x1000>; ++ #sleep-cells = <1>; ++ }; ++ ++ sfp: sfp@e8000 { ++ compatible = "fsl,p5040-sfp", "fsl,qoriq-sfp-1.0"; ++ reg = <0xe8000 0x1000>; ++ }; ++ ++ serdes: serdes@ea000 { ++ compatible = "fsl,p5040-serdes"; ++ reg = <0xea000 0x1000>; ++ }; ++ ++/include/ "qoriq-dma-0.dtsi" ++/include/ "qoriq-dma-1.dtsi" ++/include/ "qoriq-espi-0.dtsi" ++ spi@110000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "qoriq-esdhc-0.dtsi" ++ sdhc@114000 { ++ sdhci,auto-cmd12; ++ }; ++ ++/include/ "qoriq-i2c-0.dtsi" ++/include/ "qoriq-i2c-1.dtsi" ++/include/ "qoriq-duart-0.dtsi" ++/include/ "qoriq-duart-1.dtsi" ++/include/ "qoriq-gpio-0.dtsi" ++/include/ "qoriq-usb2-mph-0.dtsi" ++ usb0: usb@210000 { ++ compatible = "fsl-usb2-mph-v1.6", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph"; ++ phy_type = "utmi"; ++ port0; ++ }; ++ ++/include/ "qoriq-usb2-dr-0.dtsi" ++ usb1: usb@211000 { ++ compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr"; ++ dr_mode = "host"; ++ phy_type = "utmi"; ++ }; ++ ++/include/ "qoriq-sata2-0.dtsi" ++/include/ "qoriq-sata2-1.dtsi" ++/include/ "qoriq-sec5.2-0.dtsi" ++/include/ "qoriq-qman1.dtsi" ++/include/ "qoriq-bman1.dtsi" ++ ++/include/ "qoriq-fman-0.dtsi" ++/include/ "qoriq-fman-0-1g-0.dtsi" ++/include/ "qoriq-fman-0-1g-1.dtsi" ++/include/ "qoriq-fman-0-1g-2.dtsi" ++/include/ "qoriq-fman-0-1g-3.dtsi" ++/include/ "qoriq-fman-0-1g-4.dtsi" ++/include/ "qoriq-fman-0-10g-0.dtsi" ++ fman0: fman@400000 { ++ /* tx - 1g - 0 */ ++ port@a8000 { ++ fsl,qman-channel-id = <0x41>; ++ }; ++ /* tx - 1g - 1 */ ++ port@a9000 { ++ fsl,qman-channel-id = <0x42>; ++ }; ++ /* tx - 1g - 2 */ ++ port@aa000 { ++ fsl,qman-channel-id = <0x43>; ++ }; ++ /* tx - 1g - 3 */ ++ port@ab000 { ++ fsl,qman-channel-id = <0x44>; ++ }; ++ /* tx - 1g - 4 */ ++ port@ac000 { ++ fsl,qman-channel-id = <0x45>; ++ }; ++ /* tx - 10g - 0 */ ++ port@b0000 { ++ fsl,qman-channel-id = <0x40>; ++ }; ++ /* offline 0 */ ++ port@81000 { ++ fsl,qman-channel-id = <0x46>; ++ }; ++ /* offline 1 */ ++ port@82000 { ++ fsl,qman-channel-id = <0x47>; ++ }; ++ /* offline 2 */ ++ port@83000 { ++ fsl,qman-channel-id = <0x48>; ++ }; ++ /* offline 3 */ ++ port@84000 { ++ fsl,qman-channel-id = <0x49>; ++ }; ++ /* offline 4 */ ++ port@85000 { ++ fsl,qman-channel-id = <0x4a>; ++ }; ++ /* offline 5 */ ++ port@86000 { ++ fsl,qman-channel-id = <0x4b>; ++ }; ++ }; ++ ++/include/ "qoriq-fman-1.dtsi" ++/include/ "qoriq-fman-1-1g-0.dtsi" ++/include/ "qoriq-fman-1-1g-1.dtsi" ++/include/ "qoriq-fman-1-1g-2.dtsi" ++/include/ "qoriq-fman-1-1g-3.dtsi" ++/include/ "qoriq-fman-1-1g-4.dtsi" ++/include/ "qoriq-fman-1-10g-0.dtsi" ++ fman1: fman@500000 { ++ /* tx - 1g - 0 */ ++ port@a8000 { ++ fsl,qman-channel-id = <0x61>; ++ }; ++ /* tx - 1g - 1 */ ++ port@a9000 { ++ fsl,qman-channel-id = <0x62>; ++ }; ++ /* tx - 1g - 2 */ ++ port@aa000 { ++ fsl,qman-channel-id = <0x63>; ++ }; ++ /* tx - 1g - 3 */ ++ port@ab000 { ++ fsl,qman-channel-id = <0x64>; ++ }; ++ /* tx - 1g - 4 */ ++ port@ac000 { ++ fsl,qman-channel-id = <0x65>; ++ }; ++ /* tx - 10g - 0 */ ++ port@b0000 { ++ fsl,qman-channel-id = <0x60>; ++ }; ++ /* offline 0 */ ++ port@81000 { ++ fsl,qman-channel-id = <0x66>; ++ }; ++ /* offline 1 */ ++ port@82000 { ++ fsl,qman-channel-id = <0x67>; ++ }; ++ /* offline 2 */ ++ port@83000 { ++ fsl,qman-channel-id = <0x68>; ++ }; ++ /* offline 3 */ ++ port@84000 { ++ fsl,qman-channel-id = <0x69>; ++ }; ++ /* offline 4 */ ++ port@85000 { ++ fsl,qman-channel-id = <0x6a>; ++ }; ++ /* offline 5 */ ++ port@86000 { ++ fsl,qman-channel-id = <0x6b>; ++ }; ++ }; ++ ++/include/ "qoriq-raid1.0-0.dtsi" ++}; +diff --git a/arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi +new file mode 100644 +index 0000000..64edbf1 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi +@@ -0,0 +1,125 @@ ++/* ++ * P5040 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * This software is provided by Freescale Semiconductor "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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "e5500_power_isa.dtsi" ++ ++/ { ++ compatible = "fsl,P5040"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ ccsr = &soc; ++ dcsr = &dcsr; ++ ++ serial0 = &serial0; ++ serial1 = &serial1; ++ serial2 = &serial2; ++ serial3 = &serial3; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ usb0 = &usb0; ++ usb1 = &usb1; ++ dma0 = &dma0; ++ dma1 = &dma1; ++ sdhc = &sdhc; ++ msi0 = &msi0; ++ msi1 = &msi1; ++ msi2 = &msi2; ++ ++ crypto = &crypto; ++ sec_jr0 = &sec_jr0; ++ sec_jr1 = &sec_jr1; ++ sec_jr2 = &sec_jr2; ++ sec_jr3 = &sec_jr3; ++ rtic_a = &rtic_a; ++ rtic_b = &rtic_b; ++ rtic_c = &rtic_c; ++ rtic_d = &rtic_d; ++ sec_mon = &sec_mon; ++ ++ raideng = &raideng; ++ raideng_jr0 = &raideng_jr0; ++ raideng_jr1 = &raideng_jr1; ++ raideng_jr2 = &raideng_jr2; ++ raideng_jr3 = &raideng_jr3; ++ ++ bman = &bman; ++ qman = &qman; ++ fman0 = &fman0; ++ fman1 = &fman1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: PowerPC,e5500@0 { ++ device_type = "cpu"; ++ reg = <0>; ++ next-level-cache = <&L2_0>; ++ L2_0: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu1: PowerPC,e5500@1 { ++ device_type = "cpu"; ++ reg = <1>; ++ next-level-cache = <&L2_1>; ++ L2_1: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu2: PowerPC,e5500@2 { ++ device_type = "cpu"; ++ reg = <2>; ++ next-level-cache = <&L2_2>; ++ L2_2: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ cpu3: PowerPC,e5500@3 { ++ device_type = "cpu"; ++ reg = <3>; ++ next-level-cache = <&L2_3>; ++ L2_3: l2-cache { ++ next-level-cache = <&cpc>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-dma-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-dma-0.dtsi +new file mode 100644 +index 0000000..b5b37ad +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-dma-0.dtsi +@@ -0,0 +1,66 @@ ++/* ++ * PQ3 DMA device tree stub [ controller @ offset 0x21000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++dma@21300 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,eloplus-dma"; ++ reg = <0x21300 0x4>; ++ ranges = <0x0 0x21100 0x200>; ++ cell-index = <0>; ++ dma-channel@0 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x0 0x80>; ++ cell-index = <0>; ++ interrupts = <20 2 0 0>; ++ }; ++ dma-channel@80 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x80 0x80>; ++ cell-index = <1>; ++ interrupts = <21 2 0 0>; ++ }; ++ dma-channel@100 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x100 0x80>; ++ cell-index = <2>; ++ interrupts = <22 2 0 0>; ++ }; ++ dma-channel@180 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x180 0x80>; ++ cell-index = <3>; ++ interrupts = <23 2 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-dma-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-dma-1.dtsi +new file mode 100644 +index 0000000..28cb8a5 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-dma-1.dtsi +@@ -0,0 +1,66 @@ ++/* ++ * PQ3 DMA device tree stub [ controller @ offset 0xc300 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++dma@c300 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,eloplus-dma"; ++ reg = <0xc300 0x4>; ++ ranges = <0x0 0xc100 0x200>; ++ cell-index = <1>; ++ dma-channel@0 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x0 0x80>; ++ cell-index = <0>; ++ interrupts = <76 2 0 0>; ++ }; ++ dma-channel@80 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x80 0x80>; ++ cell-index = <1>; ++ interrupts = <77 2 0 0>; ++ }; ++ dma-channel@100 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x100 0x80>; ++ cell-index = <2>; ++ interrupts = <78 2 0 0>; ++ }; ++ dma-channel@180 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x180 0x80>; ++ cell-index = <3>; ++ interrupts = <79 2 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-duart-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-duart-0.dtsi +new file mode 100644 +index 0000000..5e268fd +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-duart-0.dtsi +@@ -0,0 +1,51 @@ ++/* ++ * PQ3 DUART device tree stub [ controller @ offset 0x4000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++serial0: serial@4500 { ++ cell-index = <0>; ++ device_type = "serial"; ++ compatible = "fsl,ns16550", "ns16550"; ++ reg = <0x4500 0x100>; ++ clock-frequency = <0>; ++ interrupts = <42 2 0 0>; ++}; ++ ++serial1: serial@4600 { ++ cell-index = <1>; ++ device_type = "serial"; ++ compatible = "fsl,ns16550", "ns16550"; ++ reg = <0x4600 0x100>; ++ clock-frequency = <0>; ++ interrupts = <42 2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-esdhc-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-esdhc-0.dtsi +new file mode 100644 +index 0000000..5743433 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-esdhc-0.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * PQ3 eSDHC device tree stub [ controller @ offset 0x2e000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++sdhc@2e000 { ++ compatible = "fsl,esdhc"; ++ reg = <0x2e000 0x1000>; ++ interrupts = <72 0x2 0 0>; ++ /* Filled in by U-Boot */ ++ clock-frequency = <0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-espi-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-espi-0.dtsi +new file mode 100644 +index 0000000..75854b2 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-espi-0.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * PQ3 eSPI device tree stub [ controller @ offset 0x7000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++spi@7000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,mpc8536-espi"; ++ reg = <0x7000 0x1000>; ++ interrupts = <59 0x2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec1-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec1-0.dtsi +new file mode 100644 +index 0000000..3b0650a +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec1-0.dtsi +@@ -0,0 +1,54 @@ ++/* ++ * PQ3 eTSEC device tree stub [ @ offsets 0x24000 ] ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++ethernet@24000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <0>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x24000 0x1000>; ++ ranges = <0x0 0x24000 0x1000>; ++ fsl,magic-packet; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ interrupts = <29 2 0 0 30 2 0 0 34 2 0 0>; ++}; ++ ++mdio@24520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec1-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec1-1.dtsi +new file mode 100644 +index 0000000..96693b4 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec1-1.dtsi +@@ -0,0 +1,54 @@ ++/* ++ * PQ3 eTSEC device tree stub [ @ offsets 0x25000 ] ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++ethernet@25000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x25000 0x1000>; ++ ranges = <0x0 0x25000 0x1000>; ++ fsl,magic-packet; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ interrupts = <35 2 0 0 36 2 0 0 40 2 0 0>; ++}; ++ ++mdio@25520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-tbi"; ++ reg = <0x25520 0x20>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec1-2.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec1-2.dtsi +new file mode 100644 +index 0000000..6b3fab1 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec1-2.dtsi +@@ -0,0 +1,54 @@ ++/* ++ * PQ3 eTSEC device tree stub [ @ offsets 0x26000 ] ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++ethernet@26000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <2>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x26000 0x1000>; ++ ranges = <0x0 0x26000 0x1000>; ++ fsl,magic-packet; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ interrupts = <31 2 0 0 32 2 0 0 33 2 0 0>; ++}; ++ ++mdio@26520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-tbi"; ++ reg = <0x26520 0x20>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec1-3.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec1-3.dtsi +new file mode 100644 +index 0000000..0da592d +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec1-3.dtsi +@@ -0,0 +1,54 @@ ++/* ++ * PQ3 eTSEC device tree stub [ @ offsets 0x27000 ] ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++ethernet@27000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <3>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x27000 0x1000>; ++ ranges = <0x0 0x27000 0x1000>; ++ fsl,magic-packet; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ interrupts = <37 2 0 0 38 2 0 0 39 2 0 0>; ++}; ++ ++mdio@27520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-tbi"; ++ reg = <0x27520 0x20>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec1-timer-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec1-timer-0.dtsi +new file mode 100644 +index 0000000..efe2ca0 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec1-timer-0.dtsi +@@ -0,0 +1,39 @@ ++/* ++ * PQ3 eTSEC Timer (IEEE 1588) device tree stub [ @ offsets 0x24e00 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++ptp_clock@24e00 { ++ compatible = "fsl,etsec-ptp"; ++ reg = <0x24e00 0xb0>; ++ interrupts = <68 2 0 0 69 2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi +new file mode 100644 +index 0000000..1382fec +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi +@@ -0,0 +1,60 @@ ++/* ++ * PQ3 eTSEC2 device tree stub [ @ offsets 0x24000/0xb0000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++ ++mdio@24000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,etsec2-mdio"; ++ reg = <0x24000 0x1000 0xb0030 0x4>; ++}; ++ ++ethernet@b0000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "fsl,etsec2"; ++ fsl,num_rx_queues = <0x8>; ++ fsl,num_tx_queues = <0x8>; ++ fsl,magic-packet; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ ++ queue-group@b0000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0xb0000 0x1000>; ++ interrupts = <29 2 0 0 30 2 0 0 34 2 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi +new file mode 100644 +index 0000000..221cd2e +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi +@@ -0,0 +1,60 @@ ++/* ++ * PQ3 eTSEC2 device tree stub [ @ offsets 0x25000/0xb1000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++ ++mdio@25000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,etsec2-tbi"; ++ reg = <0x25000 0x1000 0xb1030 0x4>; ++}; ++ ++ethernet@b1000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "fsl,etsec2"; ++ fsl,num_rx_queues = <0x8>; ++ fsl,num_tx_queues = <0x8>; ++ fsl,magic-packet; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ ++ queue-group@b1000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0xb1000 0x1000>; ++ interrupts = <35 2 0 0 36 2 0 0 40 2 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi +new file mode 100644 +index 0000000..61456c3 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi +@@ -0,0 +1,59 @@ ++/* ++ * PQ3 eTSEC2 device tree stub [ @ offsets 0x26000/0xb2000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++mdio@26000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,etsec2-tbi"; ++ reg = <0x26000 0x1000 0xb1030 0x4>; ++}; ++ ++ethernet@b2000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "fsl,etsec2"; ++ fsl,num_rx_queues = <0x8>; ++ fsl,num_tx_queues = <0x8>; ++ fsl,magic-packet; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ ++ queue-group@b2000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0xb2000 0x1000>; ++ interrupts = <31 2 0 0 32 2 0 0 33 2 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-grp2-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-grp2-0.dtsi +new file mode 100644 +index 0000000..034ab8f +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-grp2-0.dtsi +@@ -0,0 +1,42 @@ ++/* ++ * PQ3 eTSEC2 Group 2 device tree stub [ @ offsets 0xb4000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&enet0_grp2 { ++ queue-group@b4000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0xb4000 0x1000>; ++ interrupts = <17 2 0 0 18 2 0 0 24 2 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-grp2-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-grp2-1.dtsi +new file mode 100644 +index 0000000..3be9ba3 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-grp2-1.dtsi +@@ -0,0 +1,42 @@ ++/* ++ * PQ3 eTSEC2 Group 2 device tree stub [ @ offsets 0xb5000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&enet1_grp2 { ++ queue-group@b5000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0xb5000 0x1000>; ++ interrupts = <51 2 0 0 52 2 0 0 67 2 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-grp2-2.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-grp2-2.dtsi +new file mode 100644 +index 0000000..02a3345 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-grp2-2.dtsi +@@ -0,0 +1,42 @@ ++/* ++ * PQ3 eTSEC2 Group 2 device tree stub [ @ offsets 0xb6000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&enet2_grp2 { ++ queue-group@b6000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0xb6000 0x1000>; ++ interrupts = <25 2 0 0 26 2 0 0 27 2 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-gpio-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-gpio-0.dtsi +new file mode 100644 +index 0000000..72a3ef5 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-gpio-0.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * PQ3 GPIO device tree stub [ controller @ offset 0xf000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++gpio-controller@f000 { ++ #gpio-cells = <2>; ++ compatible = "fsl,pq3-gpio"; ++ reg = <0xf000 0x100>; ++ interrupts = <47 0x2 0 0>; ++ gpio-controller; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-i2c-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-i2c-0.dtsi +new file mode 100644 +index 0000000..d1dd6fb +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-i2c-0.dtsi +@@ -0,0 +1,43 @@ ++/* ++ * PQ3 I2C device tree stub [ controller @ offset 0x3000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++i2c@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <43 2 0 0>; ++ dfsrr; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-i2c-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-i2c-1.dtsi +new file mode 100644 +index 0000000..a9bd803 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-i2c-1.dtsi +@@ -0,0 +1,43 @@ ++/* ++ * PQ3 I2C device tree stub [ controller @ offset 0x3100 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++i2c@3100 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <1>; ++ compatible = "fsl-i2c"; ++ reg = <0x3100 0x100>; ++ interrupts = <43 2 0 0>; ++ dfsrr; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-mpic-timer-B.dtsi b/arch/powerpc/boot/dts/fsl/pq3-mpic-timer-B.dtsi +new file mode 100644 +index 0000000..8734cff +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-mpic-timer-B.dtsi +@@ -0,0 +1,42 @@ ++/* ++ * PQ3 MPIC Timer (Group B) device tree stub [ controller @ offset 0x42100 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++timer@42100 { ++ compatible = "fsl,mpic-global-timer"; ++ reg = <0x42100 0x100 0x42300 4>; ++ interrupts = <4 0 3 0 ++ 5 0 3 0 ++ 6 0 3 0 ++ 7 0 3 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi b/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi +new file mode 100644 +index 0000000..5c80460 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi +@@ -0,0 +1,66 @@ ++/* ++ * PQ3 MPIC device tree stub [ controller @ offset 0x40000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++mpic: pic@40000 { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <4>; ++ reg = <0x40000 0x40000>; ++ compatible = "fsl,mpic"; ++ device_type = "open-pic"; ++}; ++ ++timer@41100 { ++ compatible = "fsl,mpic-global-timer"; ++ reg = <0x41100 0x100 0x41300 4>; ++ interrupts = <0 0 3 0 ++ 1 0 3 0 ++ 2 0 3 0 ++ 3 0 3 0>; ++}; ++ ++msi@41600 { ++ compatible = "fsl,mpic-msi"; ++ reg = <0x41600 0x80>; ++ msi-available-ranges = <0 0x100>; ++ interrupts = < ++ 0xe0 0 0 0 ++ 0xe1 0 0 0 ++ 0xe2 0 0 0 ++ 0xe3 0 0 0 ++ 0xe4 0 0 0 ++ 0xe5 0 0 0 ++ 0xe6 0 0 0 ++ 0xe7 0 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-power.dtsi b/arch/powerpc/boot/dts/fsl/pq3-power.dtsi +new file mode 100644 +index 0000000..5aa854c +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-power.dtsi +@@ -0,0 +1,48 @@ ++/* ++ * PQ3 Power Management device tree stub ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++power@e0070 { ++ compatible = "fsl,mpc8548-pmc"; ++ reg = <0xe0070 0x20>; ++ ++ etsec1_clk: soc-clk@24 { ++ fsl,pmcdr-mask = <0x00000080>; ++ }; ++ etsec2_clk: soc-clk@25 { ++ fsl,pmcdr-mask = <0x00000040>; ++ }; ++ etsec3_clk: soc-clk@26 { ++ fsl,pmcdr-mask = <0x00000020>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-rmu-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-rmu-0.dtsi +new file mode 100644 +index 0000000..587ca9f +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-rmu-0.dtsi +@@ -0,0 +1,68 @@ ++/* ++ * PQ3 RIO Message Unit device tree stub [ controller @ offset 0xd3000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++rmu: rmu@d3000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,srio-rmu"; ++ reg = <0xd3000 0x500>; ++ ranges = <0x0 0xd3000 0x500>; ++ ++ message-unit@0 { ++ compatible = "fsl,srio-msg-unit"; ++ reg = <0x0 0x100>; ++ interrupts = < ++ 53 2 0 0 /* msg1_tx_irq */ ++ 54 2 0 0>;/* msg1_rx_irq */ ++ }; ++ message-unit@100 { ++ compatible = "fsl,srio-msg-unit"; ++ reg = <0x100 0x100>; ++ interrupts = < ++ 55 2 0 0 /* msg2_tx_irq */ ++ 56 2 0 0>;/* msg2_rx_irq */ ++ }; ++ doorbell-unit@400 { ++ compatible = "fsl,srio-dbell-unit"; ++ reg = <0x400 0x80>; ++ interrupts = < ++ 49 2 0 0 /* bell_outb_irq */ ++ 50 2 0 0>;/* bell_inb_irq */ ++ }; ++ port-write-unit@4e0 { ++ compatible = "fsl,srio-port-write-unit"; ++ reg = <0x4e0 0x20>; ++ interrupts = <48 2 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-sata2-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-sata2-0.dtsi +new file mode 100644 +index 0000000..3c28dd0 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-sata2-0.dtsi +@@ -0,0 +1,40 @@ ++/* ++ * PQ3 SATAv2 device tree stub [ controller @ offset 0x18000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++sata@18000 { ++ compatible = "fsl,pq-sata-v2"; ++ reg = <0x18000 0x1000>; ++ cell-index = <1>; ++ interrupts = <74 0x2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-sata2-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-sata2-1.dtsi +new file mode 100644 +index 0000000..eefaf28 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-sata2-1.dtsi +@@ -0,0 +1,40 @@ ++/* ++ * PQ3 SATAv2 device tree stub [ controller @ offset 0x19000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++sata@19000 { ++ compatible = "fsl,pq-sata-v2"; ++ reg = <0x19000 0x1000>; ++ cell-index = <2>; ++ interrupts = <41 0x2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-sec2.1-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-sec2.1-0.dtsi +new file mode 100644 +index 0000000..02a5c7a +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-sec2.1-0.dtsi +@@ -0,0 +1,43 @@ ++/* ++ * PQ3 Sec/Crypto 2.1 device tree stub [ controller @ offset 0x30000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++crypto@30000 { ++ compatible = "fsl,sec2.1", "fsl,sec2.0"; ++ reg = <0x30000 0x10000>; ++ interrupts = <45 2 0 0>; ++ fsl,num-channels = <4>; ++ fsl,channel-fifo-len = <24>; ++ fsl,exec-units-mask = <0xfe>; ++ fsl,descriptor-types-mask = <0x12b0ebf>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-sec3.0-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-sec3.0-0.dtsi +new file mode 100644 +index 0000000..bba1ba4 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-sec3.0-0.dtsi +@@ -0,0 +1,45 @@ ++/* ++ * PQ3 Sec/Crypto 3.0 device tree stub [ controller @ offset 0x30000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++crypto@30000 { ++ compatible = "fsl,sec3.0", ++ "fsl,sec2.4", "fsl,sec2.2", "fsl,sec2.1", ++ "fsl,sec2.0"; ++ reg = <0x30000 0x10000>; ++ interrupts = <45 2 0 0 58 2 0 0>; ++ fsl,num-channels = <4>; ++ fsl,channel-fifo-len = <24>; ++ fsl,exec-units-mask = <0x9fe>; ++ fsl,descriptor-types-mask = <0x3ab0ebf>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-sec3.1-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-sec3.1-0.dtsi +new file mode 100644 +index 0000000..8f0a566 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-sec3.1-0.dtsi +@@ -0,0 +1,45 @@ ++/* ++ * PQ3 Sec/Crypto 3.1 device tree stub [ controller @ offset 0x30000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++crypto@30000 { ++ compatible = "fsl,sec3.1", "fsl,sec3.0", ++ "fsl,sec2.4", "fsl,sec2.2", "fsl,sec2.1", ++ "fsl,sec2.0"; ++ reg = <0x30000 0x10000>; ++ interrupts = <45 2 0 0 58 2 0 0>; ++ fsl,num-channels = <4>; ++ fsl,channel-fifo-len = <24>; ++ fsl,exec-units-mask = <0xbfe>; ++ fsl,descriptor-types-mask = <0x3ab0ebf>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-sec3.3-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-sec3.3-0.dtsi +new file mode 100644 +index 0000000..c227f27 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-sec3.3-0.dtsi +@@ -0,0 +1,45 @@ ++/* ++ * PQ3 Sec/Crypto 3.3 device tree stub [ controller @ offset 0x30000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++crypto@30000 { ++ compatible = "fsl,sec3.3", "fsl,sec3.1", "fsl,sec3.0", ++ "fsl,sec2.4", "fsl,sec2.2", "fsl,sec2.1", ++ "fsl,sec2.0"; ++ reg = <0x30000 0x10000>; ++ interrupts = <45 2 0 0 58 2 0 0>; ++ fsl,num-channels = <4>; ++ fsl,channel-fifo-len = <24>; ++ fsl,exec-units-mask = <0x97c>; ++ fsl,descriptor-types-mask = <0x3a30abf>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-sec4.4-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-sec4.4-0.dtsi +new file mode 100644 +index 0000000..ffadcb5 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-sec4.4-0.dtsi +@@ -0,0 +1,66 @@ ++/* ++ * PQ3 Sec/Crypto 4.4 device tree stub [ controller @ offset 0x30000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++crypto@30000 { ++ compatible = "fsl,sec-v4.4", "fsl,sec-v4.0"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x30000 0x10000>; ++ reg = <0x30000 0x10000>; ++ interrupts = <58 2 0 0>; ++ ++ sec_jr0: jr@1000 { ++ compatible = "fsl,sec-v4.4-job-ring", "fsl,sec-v4.0-job-ring"; ++ reg = <0x1000 0x1000>; ++ interrupts = <45 2 0 0>; ++ }; ++ ++ sec_jr1: jr@2000 { ++ compatible = "fsl,sec-v4.4-job-ring", "fsl,sec-v4.0-job-ring"; ++ reg = <0x2000 0x1000>; ++ interrupts = <45 2 0 0>; ++ }; ++ ++ sec_jr2: jr@3000 { ++ compatible = "fsl,sec-v4.4-job-ring", "fsl,sec-v4.0-job-ring"; ++ reg = <0x3000 0x1000>; ++ interrupts = <45 2 0 0>; ++ }; ++ ++ sec_jr3: jr@4000 { ++ compatible = "fsl,sec-v4.4-job-ring", "fsl,sec-v4.0-job-ring"; ++ reg = <0x4000 0x1000>; ++ interrupts = <45 2 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-tdm1.0-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-tdm1.0-0.dtsi +new file mode 100644 +index 0000000..d4bdd5d +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-tdm1.0-0.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * PQ3 TDM device tree stub [ controller @ offset 0x16000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++tdm@16000 { ++ compatible = "fsl,tdm1.0"; ++ reg = <0x16000 0x200 0x2c000 0x2000>; ++ clock-frequency = <0>; ++ interrupts = <62 8 0 0>; ++ fsl,max-time-slots = <128>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-usb2-dr-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-usb2-dr-0.dtsi +new file mode 100644 +index 0000000..185ab9d +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-usb2-dr-0.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * PQ3 USB DR device tree stub [ controller @ offset 0x22000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++usb@22000 { ++ compatible = "fsl-usb2-dr"; ++ reg = <0x22000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <28 0x2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-usb2-dr-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-usb2-dr-1.dtsi +new file mode 100644 +index 0000000..fe24cd6 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/pq3-usb2-dr-1.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * PQ3 USB DR device tree stub [ controller @ offset 0x23000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++usb@23000 { ++ compatible = "fsl-usb2-dr"; ++ reg = <0x23000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <46 0x2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qonverge-usb2-dr-0.dtsi b/arch/powerpc/boot/dts/fsl/qonverge-usb2-dr-0.dtsi +new file mode 100644 +index 0000000..8bf4a72 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qonverge-usb2-dr-0.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * QorIQ Qonverge USB Host device tree stub [ controller @ offset 0x210000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++usb@210000 { ++ compatible = "fsl-usb2-dr"; ++ reg = <0x210000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <44 0x2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-bman1-portals.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-bman1-portals.dtsi +new file mode 100644 +index 0000000..88ccba4 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-bman1-portals.dtsi +@@ -0,0 +1,97 @@ ++/* ++ * QorIQ BMan Portal device tree stub for 10 portals ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++#address-cells = <0x1>; ++#size-cells = <0x1>; ++compatible = "simple-bus"; ++bman-portal@0 { ++ cell-index = <0x0>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x0 0x4000 0x100000 0x1000>; ++ interrupts = <105 2 0 0>; ++}; ++bman-portal@4000 { ++ cell-index = <0x1>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x4000 0x4000 0x101000 0x1000>; ++ interrupts = <107 2 0 0>; ++}; ++bman-portal@8000 { ++ cell-index = <2>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x8000 0x4000 0x102000 0x1000>; ++ interrupts = <109 2 0 0>; ++}; ++bman-portal@c000 { ++ cell-index = <0x3>; ++ compatible = "fsl,bman-portal"; ++ reg = <0xc000 0x4000 0x103000 0x1000>; ++ interrupts = <111 2 0 0>; ++}; ++bman-portal@10000 { ++ cell-index = <0x4>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x10000 0x4000 0x104000 0x1000>; ++ interrupts = <113 2 0 0>; ++}; ++bman-portal@14000 { ++ cell-index = <0x5>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x14000 0x4000 0x105000 0x1000>; ++ interrupts = <115 2 0 0>; ++}; ++bman-portal@18000 { ++ cell-index = <0x6>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x18000 0x4000 0x106000 0x1000>; ++ interrupts = <117 2 0 0>; ++}; ++bman-portal@1c000 { ++ cell-index = <0x7>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x1c000 0x4000 0x107000 0x1000>; ++ interrupts = <119 2 0 0>; ++}; ++bman-portal@20000 { ++ cell-index = <0x8>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x20000 0x4000 0x108000 0x1000>; ++ interrupts = <121 2 0 0>; ++}; ++bman-portal@24000 { ++ cell-index = <0x9>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x24000 0x4000 0x109000 0x1000>; ++ interrupts = <123 2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-bman1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-bman1.dtsi +new file mode 100644 +index 0000000..b05be1c +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-bman1.dtsi +@@ -0,0 +1,39 @@ ++/* ++ * QorIQ BMan device tree stub [ controller @ offset 0x31a000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++bman: bman@31a000 { ++ compatible = "fsl,bman"; ++ reg = <0x31a000 0x1000>; ++ interrupts = <16 2 1 2>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-bman2-portals.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-bman2-portals.dtsi +new file mode 100644 +index 0000000..8c0ced5 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-bman2-portals.dtsi +@@ -0,0 +1,338 @@ ++/* ++ * QorIQ BMan Portal device tree stub for 50 portals ++ * i.e BMan2.1 ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++#address-cells = <0x1>; ++#size-cells = <0x1>; ++compatible = "simple-bus"; ++bman-portal@0 { ++ cell-index = <0x0>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x0 0x4000 0x1000000 0x1000>; ++ interrupts = <105 2 0 0>; ++}; ++bman-portal@4000 { ++ cell-index = <0x1>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x4000 0x4000 0x1001000 0x1000>; ++ interrupts = <107 2 0 0>; ++}; ++bman-portal@8000 { ++ cell-index = <2>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x8000 0x4000 0x1002000 0x1000>; ++ interrupts = <109 2 0 0>; ++}; ++bman-portal@c000 { ++ cell-index = <0x3>; ++ compatible = "fsl,bman-portal"; ++ reg = <0xc000 0x4000 0x1003000 0x1000>; ++ interrupts = <111 2 0 0>; ++}; ++bman-portal@10000 { ++ cell-index = <0x4>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x10000 0x4000 0x1004000 0x1000>; ++ interrupts = <113 2 0 0>; ++}; ++bman-portal@14000 { ++ cell-index = <0x5>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x14000 0x4000 0x1005000 0x1000>; ++ interrupts = <115 2 0 0>; ++}; ++bman-portal@18000 { ++ cell-index = <0x6>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x18000 0x4000 0x1006000 0x1000>; ++ interrupts = <117 2 0 0>; ++}; ++bman-portal@1c000 { ++ cell-index = <0x7>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x1c000 0x4000 0x1007000 0x1000>; ++ interrupts = <119 2 0 0>; ++}; ++bman-portal@20000 { ++ cell-index = <0x8>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x20000 0x4000 0x1008000 0x1000>; ++ interrupts = <121 2 0 0>; ++}; ++bman-portal@24000 { ++ cell-index = <0x9>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x24000 0x4000 0x1009000 0x1000>; ++ interrupts = <123 2 0 0>; ++}; ++bman-portal@28000 { ++ cell-index = <0xa>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x28000 0x4000 0x100a000 0x1000>; ++ interrupts = <125 2 0 0>; ++}; ++bman-portal@2c000 { ++ cell-index = <0xb>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x2c000 0x4000 0x100b000 0x1000>; ++ interrupts = <127 2 0 0>; ++}; ++bman-portal@30000 { ++ cell-index = <0xc>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x30000 0x4000 0x100c000 0x1000>; ++ interrupts = <129 2 0 0>; ++}; ++bman-portal@34000 { ++ cell-index = <0xd>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x34000 0x4000 0x100d000 0x1000>; ++ interrupts = <131 2 0 0>; ++}; ++bman-portal@38000 { ++ cell-index = <0xe>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x38000 0x4000 0x100e000 0x1000>; ++ interrupts = <133 2 0 0>; ++}; ++bman-portal@3c000 { ++ cell-index = <0xf>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x3c000 0x4000 0x100f000 0x1000>; ++ interrupts = <135 2 0 0>; ++}; ++bman-portal@40000 { ++ cell-index = <0x10>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x40000 0x4000 0x1010000 0x1000>; ++ interrupts = <137 2 0 0>; ++}; ++bman-portal@44000 { ++ cell-index = <0x11>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x44000 0x4000 0x1011000 0x1000>; ++ interrupts = <139 2 0 0>; ++}; ++bman-portal@48000 { ++ cell-index = <0x12>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x48000 0x4000 0x1012000 0x1000>; ++ interrupts = <141 2 0 0>; ++}; ++bman-portal@4c000 { ++ cell-index = <0x13>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x4c000 0x4000 0x1013000 0x1000>; ++ interrupts = <143 2 0 0>; ++}; ++bman-portal@50000 { ++ cell-index = <0x14>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x50000 0x4000 0x1014000 0x1000>; ++ interrupts = <145 2 0 0>; ++}; ++bman-portal@54000 { ++ cell-index = <0x15>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x54000 0x4000 0x1015000 0x1000>; ++ interrupts = <147 2 0 0>; ++}; ++bman-portal@58000 { ++ cell-index = <0x16>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x58000 0x4000 0x1016000 0x1000>; ++ interrupts = <149 2 0 0>; ++}; ++bman-portal@5c000 { ++ cell-index = <0x17>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x5c000 0x4000 0x1017000 0x1000>; ++ interrupts = <151 2 0 0>; ++}; ++bman-portal@60000 { ++ cell-index = <0x18>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x60000 0x4000 0x1018000 0x1000>; ++ interrupts = <153 2 0 0>; ++}; ++bman-portal@64000 { ++ cell-index = <0x19>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x64000 0x4000 0x1019000 0x1000>; ++ interrupts = <155 2 0 0>; ++}; ++bman-portal@68000 { ++ cell-index = <0x1a>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x68000 0x4000 0x101a000 0x1000>; ++ interrupts = <157 2 0 0>; ++}; ++bman-portal@6c000 { ++ cell-index = <0x1b>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x6c000 0x4000 0x101b000 0x1000>; ++ interrupts = <159 2 0 0>; ++}; ++bman-portal@70000 { ++ cell-index = <0x1c>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x70000 0x4000 0x101c000 0x1000>; ++ interrupts = <161 2 0 0>; ++}; ++bman-portal@74000 { ++ cell-index = <0x1d>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x74000 0x4000 0x101d000 0x1000>; ++ interrupts = <163 2 0 0>; ++}; ++bman-portal@78000 { ++ cell-index = <0x1e>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x78000 0x4000 0x101e000 0x1000>; ++ interrupts = <165 2 0 0>; ++}; ++bman-portal@7c000 { ++ cell-index = <0x1f>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x7c000 0x4000 0x101f000 0x1000>; ++ interrupts = <167 2 0 0>; ++}; ++bman-portal@80000 { ++ cell-index = <0x20>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x80000 0x4000 0x1020000 0x1000>; ++ interrupts = <169 2 0 0>; ++}; ++bman-portal@84000 { ++ cell-index = <0x21>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x84000 0x4000 0x1021000 0x1000>; ++ interrupts = <171 2 0 0>; ++}; ++bman-portal@88000 { ++ cell-index = <0x22>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x88000 0x4000 0x1022000 0x1000>; ++ interrupts = <173 2 0 0>; ++}; ++bman-portal@8c000 { ++ cell-index = <0x23>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x8c000 0x4000 0x1023000 0x1000>; ++ interrupts = <175 2 0 0>; ++}; ++bman-portal@90000 { ++ cell-index = <0x24>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x90000 0x4000 0x1024000 0x1000>; ++ interrupts = <385 2 0 0>; ++}; ++bman-portal@94000 { ++ cell-index = <0x25>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x94000 0x4000 0x1025000 0x1000>; ++ interrupts = <387 2 0 0>; ++}; ++bman-portal@98000 { ++ cell-index = <0x26>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x98000 0x4000 0x1026000 0x1000>; ++ interrupts = <389 2 0 0>; ++}; ++bman-portal@9c000 { ++ cell-index = <0x27>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x9c000 0x4000 0x1027000 0x1000>; ++ interrupts = <391 2 0 0>; ++}; ++bman-portal@a0000 { ++ cell-index = <0x28>; ++ compatible = "fsl,bman-portal"; ++ reg = <0xa0000 0x4000 0x1028000 0x1000>; ++ interrupts = <393 2 0 0>; ++}; ++bman-portal@a4000 { ++ cell-index = <0x29>; ++ compatible = "fsl,bman-portal"; ++ reg = <0xa4000 0x4000 0x1029000 0x1000>; ++ interrupts = <395 2 0 0>; ++}; ++bman-portal@a8000 { ++ cell-index = <0x2a>; ++ compatible = "fsl,bman-portal"; ++ reg = <0xa8000 0x4000 0x102a000 0x1000>; ++ interrupts = <397 2 0 0>; ++}; ++bman-portal@ac000 { ++ cell-index = <0x2b>; ++ compatible = "fsl,bman-portal"; ++ reg = <0xac000 0x4000 0x102b000 0x1000>; ++ interrupts = <399 2 0 0>; ++}; ++bman-portal@b0000 { ++ cell-index = <0x2c>; ++ compatible = "fsl,bman-portal"; ++ reg = <0xb0000 0x4000 0x102c000 0x1000>; ++ interrupts = <401 2 0 0>; ++}; ++bman-portal@b4000 { ++ cell-index = <0x2d>; ++ compatible = "fsl,bman-portal"; ++ reg = <0xb4000 0x4000 0x102d000 0x1000>; ++ interrupts = <403 2 0 0>; ++}; ++bman-portal@b8000 { ++ cell-index = <0x2e>; ++ compatible = "fsl,bman-portal"; ++ reg = <0xb8000 0x4000 0x102e000 0x1000>; ++ interrupts = <405 2 0 0>; ++}; ++bman-portal@bc000 { ++ cell-index = <0x2f>; ++ compatible = "fsl,bman-portal"; ++ reg = <0xbc000 0x4000 0x102f000 0x1000>; ++ interrupts = <407 2 0 0>; ++}; ++bman-portal@c0000 { ++ cell-index = <0x30>; ++ compatible = "fsl,bman-portal"; ++ reg = <0xc0000 0x4000 0x1030000 0x1000>; ++ interrupts = <409 2 0 0>; ++}; ++bman-portal@c4000 { ++ cell-index = <0x31>; ++ compatible = "fsl,bman-portal"; ++ reg = <0xc4000 0x4000 0x1031000 0x1000>; ++ interrupts = <411 2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-dce-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-dce-0.dtsi +new file mode 100644 +index 0000000..9b747ba +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-dce-0.dtsi +@@ -0,0 +1,39 @@ ++/* ++ * QorIQ DCE device tree stub [ controller @ offset 0x312000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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. ++ */ ++ ++dce: dce@312000 { ++ compatible = "fsl,dce"; ++ reg = <0x312000 0x10000>; ++ interrupts = <16 2 1 4>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-dma-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-dma-0.dtsi +new file mode 100644 +index 0000000..1aebf3e +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-dma-0.dtsi +@@ -0,0 +1,66 @@ ++/* ++ * QorIQ DMA device tree stub [ controller @ offset 0x100000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++dma0: dma@100300 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,eloplus-dma"; ++ reg = <0x100300 0x4>; ++ ranges = <0x0 0x100100 0x200>; ++ cell-index = <0>; ++ dma-channel@0 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x0 0x80>; ++ cell-index = <0>; ++ interrupts = <28 2 0 0>; ++ }; ++ dma-channel@80 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x80 0x80>; ++ cell-index = <1>; ++ interrupts = <29 2 0 0>; ++ }; ++ dma-channel@100 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x100 0x80>; ++ cell-index = <2>; ++ interrupts = <30 2 0 0>; ++ }; ++ dma-channel@180 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x180 0x80>; ++ cell-index = <3>; ++ interrupts = <31 2 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-dma-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-dma-1.dtsi +new file mode 100644 +index 0000000..ecf5e18 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-dma-1.dtsi +@@ -0,0 +1,66 @@ ++/* ++ * QorIQ DMA device tree stub [ controller @ offset 0x101000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++dma1: dma@101300 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,eloplus-dma"; ++ reg = <0x101300 0x4>; ++ ranges = <0x0 0x101100 0x200>; ++ cell-index = <1>; ++ dma-channel@0 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x0 0x80>; ++ cell-index = <0>; ++ interrupts = <32 2 0 0>; ++ }; ++ dma-channel@80 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x80 0x80>; ++ cell-index = <1>; ++ interrupts = <33 2 0 0>; ++ }; ++ dma-channel@100 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x100 0x80>; ++ cell-index = <2>; ++ interrupts = <34 2 0 0>; ++ }; ++ dma-channel@180 { ++ compatible = "fsl,eloplus-dma-channel"; ++ reg = <0x180 0x80>; ++ cell-index = <3>; ++ interrupts = <35 2 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-dpaa-res1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-dpaa-res1.dtsi +new file mode 100644 +index 0000000..6c6f7d7 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-dpaa-res1.dtsi +@@ -0,0 +1,84 @@ ++/* ++ * QorIQ DPAA resources device tree stub [ FQIDs, BPIDs ] ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/* These stubs are required to alloc qbman drivers to determine what ranges of ++ * resources are available for dynamic allocation, primarily because there are ++ * some legacy "a priori" assumptions in certain subsystems (eg. networking) ++ * that certain resources are reserved for their use. When those drivers (and in ++ * some cases, their corresponding device-tree nodes) are updated to dynamically ++ * allocate their resources, then *all* resources can be managed by the ++ * allocators and there may be no further need to define these stubs. ++ * ++ * A couple of qualifiers to the above statement though: ++ * ++ * - Some resource ranges are hardware-specific, rather than being defined by ++ * software memory allocation choices. Eg. the number of available BPIDs is ++ * baked into silicon and so will probably always need to be expressed in the ++ * device-tree, though in that case it will express all BPIDs, not just those ++ * available for dynamic allocation. ++ * ++ * - Even for memory-backed resources that are software determined (FQIDs), this ++ * information may only be configured and available on the control-plane ++ * partition that manages the device, so in AMP or hypervised scenarios there ++ * may still be need to a way to provide allocation ranges. Ie. for O/S ++ * instances that don't know how many resources are available to hardware, and ++ * possibly even for O/S instances that do know how many are available but ++ * that should not "own" all of them. ++ */ ++ ++&bportals { ++ bman-bpids@0 { ++ compatible = "fsl,bpid-range"; ++ fsl,bpid-range = <32 32>; ++ }; ++}; ++ ++&qportals { ++ qman-fqids@0 { ++ compatible = "fsl,fqid-range"; ++ fsl,fqid-range = <256 256>; ++ }; ++ qman-fqids@1 { ++ compatible = "fsl,fqid-range"; ++ fsl,fqid-range = <32768 32768>; ++ }; ++ qman-pools@0 { ++ compatible = "fsl,pool-channel-range"; ++ fsl,pool-channel-range = <0x21 0xf>; ++ }; ++ qman-cgrids@0 { ++ compatible = "fsl,cgrid-range"; ++ fsl,cgrid-range = <0 256>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-dpaa-res2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-dpaa-res2.dtsi +new file mode 100644 +index 0000000..73ee049 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-dpaa-res2.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ DPAA resources device tree stub [ FQIDs, BPIDs ] ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/* The comments in qoriq-dpaa-res1.dtsi apply here too so will not be repeated. ++ * This alternative file is to support p1023 which does not have the same ++ * resource ranges as other SoCs to date. */ ++ ++&bportals { ++ bman-bpids@0 { ++ compatible = "fsl,bpid-range"; ++ fsl,bpid-range = <1 7>; ++ }; ++}; ++ ++&qportals { ++ qman-fqids@0 { ++ compatible = "fsl,fqid-range"; ++ fsl,fqid-range = <256 256>; ++ }; ++ qman-fqids@1 { ++ compatible = "fsl,fqid-range"; ++ fsl,fqid-range = <32768 32768>; ++ }; ++ qman-pools@0 { ++ compatible = "fsl,pool-channel-range"; ++ fsl,pool-channel-range = <0x21 0x3>; ++ }; ++ qman-cgrids@0 { ++ compatible = "fsl,cgrid-range"; ++ fsl,cgrid-range = <0 64>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-dpaa-res3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-dpaa-res3.dtsi +new file mode 100644 +index 0000000..1bc5af9 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-dpaa-res3.dtsi +@@ -0,0 +1,84 @@ ++/* ++ * QorIQ DPAA resources device tree stub [ FQIDs, BPIDs ] ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/* These stubs are required to alloc qbman drivers to determine what ranges of ++ * resources are available for dynamic allocation, primarily because there are ++ * some legacy "a priori" assumptions in certain subsystems (eg. networking) ++ * that certain resources are reserved for their use. When those drivers (and in ++ * some cases, their corresponding device-tree nodes) are updated to dynamically ++ * allocate their resources, then *all* resources can be managed by the ++ * allocators and there may be no further need to define these stubs. ++ * ++ * A couple of qualifiers to the above statement though: ++ * ++ * - Some resource ranges are hardware-specific, rather than being defined by ++ * software memory allocation choices. Eg. the number of available BPIDs is ++ * baked into silicon and so will probably always need to be expressed in the ++ * device-tree, though in that case it will express all BPIDs, not just those ++ * available for dynamic allocation. ++ * ++ * - Even for memory-backed resources that are software determined (FQIDs), this ++ * information may only be configured and available on the control-plane ++ * partition that manages the device, so in AMP or hypervised scenarios there ++ * may still be need to a way to provide allocation ranges. Ie. for O/S ++ * instances that don't know how many resources are available to hardware, and ++ * possibly even for O/S instances that do know how many are available but ++ * that should not "own" all of them. ++ */ ++ ++&bportals { ++ bman-bpids@0 { ++ compatible = "fsl,bpid-range"; ++ fsl,bpid-range = <32 32>; ++ }; ++}; ++ ++&qportals { ++ qman-fqids@0 { ++ compatible = "fsl,fqid-range"; ++ fsl,fqid-range = <256 512>; ++ }; ++ qman-fqids@1 { ++ compatible = "fsl,fqid-range"; ++ fsl,fqid-range = <32768 32768>; ++ }; ++ qman-pools@0 { ++ compatible = "fsl,pool-channel-range"; ++ fsl,pool-channel-range = <0x401 0xf>; ++ }; ++ qman-cgrids@0 { ++ compatible = "fsl,cgrid-range"; ++ fsl,cgrid-range = <0 256>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-duart-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-duart-0.dtsi +new file mode 100644 +index 0000000..225c07b +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-duart-0.dtsi +@@ -0,0 +1,51 @@ ++/* ++ * QorIQ DUART device tree stub [ controller @ offset 0x11c000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++serial0: serial@11c500 { ++ cell-index = <0>; ++ device_type = "serial"; ++ compatible = "fsl,ns16550", "ns16550"; ++ reg = <0x11c500 0x100>; ++ clock-frequency = <0>; ++ interrupts = <36 2 0 0>; ++}; ++ ++serial1: serial@11c600 { ++ cell-index = <1>; ++ device_type = "serial"; ++ compatible = "fsl,ns16550", "ns16550"; ++ reg = <0x11c600 0x100>; ++ clock-frequency = <0>; ++ interrupts = <36 2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-duart-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-duart-1.dtsi +new file mode 100644 +index 0000000..d23233a +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-duart-1.dtsi +@@ -0,0 +1,51 @@ ++/* ++ * QorIQ DUART device tree stub [ controller @ offset 0x11d000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++serial2: serial@11d500 { ++ cell-index = <2>; ++ device_type = "serial"; ++ compatible = "fsl,ns16550", "ns16550"; ++ reg = <0x11d500 0x100>; ++ clock-frequency = <0>; ++ interrupts = <37 2 0 0>; ++}; ++ ++serial3: serial@11d600 { ++ cell-index = <3>; ++ device_type = "serial"; ++ compatible = "fsl,ns16550", "ns16550"; ++ reg = <0x11d600 0x100>; ++ clock-frequency = <0>; ++ interrupts = <37 2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-esdhc-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-esdhc-0.dtsi +new file mode 100644 +index 0000000..20835ae +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-esdhc-0.dtsi +@@ -0,0 +1,40 @@ ++/* ++ * QorIQ eSDHC device tree stub [ controller @ offset 0x114000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++sdhc: sdhc@114000 { ++ compatible = "fsl,esdhc"; ++ reg = <0x114000 0x1000>; ++ interrupts = <48 2 0 0>; ++ clock-frequency = <0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-espi-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-espi-0.dtsi +new file mode 100644 +index 0000000..6db0697 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-espi-0.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * QorIQ eSPI device tree stub [ controller @ offset 0x110000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++spi@110000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,mpc8536-espi"; ++ reg = <0x110000 0x1000>; ++ interrupts = <53 0x2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-0-10g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-0-10g-0.dtsi +new file mode 100644 +index 0000000..c5c5086 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-0-10g-0.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ FMan 10g port #0 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_10g_rx0: port@90000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-10g-rx"; ++ reg = <0x90000 0x1000>; ++ }; ++ ++ fman0_10g_tx0: port@b0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-10g-tx"; ++ reg = <0xb0000 0x1000>; ++ fsl,qman-channel-id = <0x40>; ++ }; ++ ++ ethernet@f0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-10g-mac"; ++ reg = <0xf0000 0x1000>; ++ fsl,port-handles = <&fman0_10g_rx0 &fman0_10g_tx0>; ++ }; ++ ++ xmdio0: mdio@f1000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-xmdio"; ++ reg = <0xf1000 0x1000>; ++ interrupts = <100 1 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-0.dtsi +new file mode 100644 +index 0000000..e52cb1f +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-0.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ FMan 1g port #0 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_rx0: port@88000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x88000 0x1000>; ++ }; ++ ++ fman0_tx0: port@a8000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xa8000 0x1000>; ++ }; ++ ++ ethernet@e0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-1g-mac"; ++ reg = <0xe0000 0x1000>; ++ fsl,port-handles = <&fman0_rx0 &fman0_tx0>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio0: mdio@e1120 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-mdio"; ++ reg = <0xe1120 0xee0>; ++ interrupts = <100 1 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-1.dtsi +new file mode 100644 +index 0000000..a500a84 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-1.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ FMan 1g port #1 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_rx1: port@89000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x89000 0x1000>; ++ }; ++ ++ fman0_tx1: port@a9000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xa9000 0x1000>; ++ }; ++ ++ ethernet@e2000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-1g-mac"; ++ reg = <0xe2000 0x1000>; ++ fsl,port-handles = <&fman0_rx1 &fman0_tx1>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio@e3120 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-tbi"; ++ reg = <0xe3120 0xee0>; ++ interrupts = <100 1 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-2.dtsi +new file mode 100644 +index 0000000..14a8d22 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-2.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ FMan 1g port #2 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_rx2: port@8a000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8a000 0x1000>; ++ }; ++ ++ fman0_tx2: port@aa000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xaa000 0x1000>; ++ }; ++ ++ ethernet@e4000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-1g-mac"; ++ reg = <0xe4000 0x1000>; ++ fsl,port-handles = <&fman0_rx2 &fman0_tx2>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio@e5120 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-tbi"; ++ reg = <0xe5120 0xee0>; ++ interrupts = <100 1 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-3.dtsi +new file mode 100644 +index 0000000..fbd5887 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-3.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ FMan 1g port #3 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_rx3: port@8b000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8b000 0x1000>; ++ }; ++ ++ fman0_tx3: port@ab000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xab000 0x1000>; ++ }; ++ ++ ethernet@e6000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-1g-mac"; ++ reg = <0xe6000 0x1000>; ++ fsl,port-handles = <&fman0_rx3 &fman0_tx3>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio@e7120 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-tbi"; ++ reg = <0xe7120 0xee0>; ++ interrupts = <100 1 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-4.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-4.dtsi +new file mode 100644 +index 0000000..1c27647 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-0-1g-4.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ FMan 1g port #4 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_rx4: port@8c000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8c000 0x1000>; ++ }; ++ ++ fman0_tx4: port@ac000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xac000 0x1000>; ++ }; ++ ++ ethernet@e8000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-1g-mac"; ++ reg = <0xe8000 0x1000>; ++ fsl,port-handles = <&fman0_rx4 &fman0_tx4>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio@e9120 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-tbi"; ++ reg = <0xe9120 0xee0>; ++ interrupts = <100 1 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi +new file mode 100644 +index 0000000..b074d13 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi +@@ -0,0 +1,140 @@ ++/* ++ * QorIQ FMan device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman0: fman@400000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <0>; ++ compatible = "fsl,fman", "simple-bus"; ++ ranges = <0 0x400000 0x100000>; ++ reg = <0x400000 0x100000>; ++ clock-frequency = <0>; ++ interrupts = < ++ 96 2 0 0 ++ 16 2 1 1>; ++ ++ cc { ++ compatible = "fsl,fman-cc"; ++ }; ++ ++ muram@0 { ++ compatible = "fsl,fman-muram"; ++ reg = <0x0 0x28000>; ++ }; ++ ++ bmi@80000 { ++ compatible = "fsl,fman-bmi"; ++ reg = <0x80000 0x400>; ++ }; ++ ++ qmi@80400 { ++ compatible = "fsl,fman-qmi"; ++ reg = <0x80400 0x400>; ++ }; ++ ++ fman0_oh0: port@81000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x81000 0x1000>; ++ }; ++ ++ fman0_oh1: port@82000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x82000 0x1000>; ++ }; ++ ++ fman0_oh2: port@83000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x83000 0x1000>; ++ }; ++ ++ fman0_oh3: port@84000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x84000 0x1000>; ++ }; ++ ++ fman0_oh4: port@85000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x85000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ fman0_oh5: port@86000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x86000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ fman0_oh6: port@87000 { ++ cell-index = <6>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x87000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ policer@c0000 { ++ compatible = "fsl,fman-policer"; ++ reg = <0xc0000 0x1000>; ++ }; ++ ++ keygen@c1000 { ++ compatible = "fsl,fman-keygen"; ++ reg = <0xc1000 0x1000>; ++ }; ++ ++ dma@c2000 { ++ compatible = "fsl,fman-dma"; ++ reg = <0xc2000 0x1000>; ++ }; ++ ++ fpm@c3000 { ++ compatible = "fsl,fman-fpm"; ++ reg = <0xc3000 0x1000>; ++ }; ++ ++ parser@c7000 { ++ compatible = "fsl,fman-parser"; ++ reg = <0xc7000 0x1000>; ++ }; ++ ++ ptp_timer0: rtc@fe000 { ++ compatible = "fsl,fman-rtc"; ++ reg = <0xfe000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-1-10g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-1-10g-0.dtsi +new file mode 100644 +index 0000000..dcaf84a +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-1-10g-0.dtsi +@@ -0,0 +1,54 @@ ++/* ++ * QorIQ FMan 10g port #0 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_10g_rx0: port@90000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-10g-rx"; ++ reg = <0x90000 0x1000>; ++ }; ++ ++ fman1_10g_tx0: port@b0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-10g-tx"; ++ reg = <0xb0000 0x1000>; ++ }; ++ ++ ethernet@f0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-10g-mac"; ++ reg = <0xf0000 0x1000>; ++ fsl,port-handles = <&fman1_10g_rx0 &fman1_10g_tx0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-0.dtsi +new file mode 100644 +index 0000000..5280661 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-0.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ FMan 1g port #0 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_rx0: port@88000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x88000 0x1000>; ++ }; ++ ++ fman1_tx0: port@a8000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xa8000 0x1000>; ++ }; ++ ++ ethernet@e0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-1g-mac"; ++ reg = <0xe0000 0x1000>; ++ fsl,port-handles = <&fman1_rx0 &fman1_tx0>; ++ ptimer-handle = <&ptp_timer1>; ++ }; ++ ++ mdio@e1120 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-tbi"; ++ reg = <0xe1120 0xee0>; ++ interrupts = <101 1 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-1.dtsi +new file mode 100644 +index 0000000..1d5fcde +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-1.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ FMan 1g port #1 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_rx1: port@89000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x89000 0x1000>; ++ }; ++ ++ fman1_tx1: port@a9000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xa9000 0x1000>; ++ }; ++ ++ ethernet@e2000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-1g-mac"; ++ reg = <0xe2000 0x1000>; ++ fsl,port-handles = <&fman1_rx1 &fman1_tx1>; ++ ptimer-handle = <&ptp_timer1>; ++ }; ++ ++ mdio@e3120 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-tbi"; ++ reg = <0xe3120 0xee0>; ++ interrupts = <101 1 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-2.dtsi +new file mode 100644 +index 0000000..cf6cab1 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-2.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ FMan 1g port #2 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_rx2: port@8a000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8a000 0x1000>; ++ }; ++ ++ fman1_tx2: port@aa000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xaa000 0x1000>; ++ }; ++ ++ ethernet@e4000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-1g-mac"; ++ reg = <0xe4000 0x1000>; ++ fsl,port-handles = <&fman1_rx2 &fman1_tx2>; ++ ptimer-handle = <&ptp_timer1>; ++ }; ++ ++ mdio@e5120 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-tbi"; ++ reg = <0xe5120 0xee0>; ++ interrupts = <101 1 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-3.dtsi +new file mode 100644 +index 0000000..0d85b37 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-3.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ FMan 1g port #3 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_rx3: port@8b000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8b000 0x1000>; ++ }; ++ ++ fman1_tx3: port@ab000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xab000 0x1000>; ++ }; ++ ++ ethernet@e6000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-1g-mac"; ++ reg = <0xe6000 0x1000>; ++ fsl,port-handles = <&fman1_rx3 &fman1_tx3>; ++ ptimer-handle = <&ptp_timer1>; ++ }; ++ ++ mdio@e7120 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-tbi"; ++ reg = <0xe7120 0xee0>; ++ interrupts = <101 1 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-4.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-4.dtsi +new file mode 100644 +index 0000000..ed0f504 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-1-1g-4.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ FMan 1g port #4 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_rx4: port@8c000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8c000 0x1000>; ++ }; ++ ++ fman1_tx4: port@ac000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xac000 0x1000>; ++ }; ++ ++ ethernet@e8000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-1g-mac"; ++ reg = <0xe8000 0x1000>; ++ fsl,port-handles = <&fman1_rx4 &fman1_tx4>; ++ ptimer-handle = <&ptp_timer1>; ++ }; ++ ++ mdio@e9120 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-tbi"; ++ reg = <0xe9120 0xee0>; ++ interrupts = <101 1 0 0>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi +new file mode 100644 +index 0000000..d94f6cc +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi +@@ -0,0 +1,140 @@ ++/* ++ * QorIQ FMan device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman1: fman@500000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <1>; ++ compatible = "fsl,fman", "simple-bus"; ++ ranges = <0 0x500000 0x100000>; ++ reg = <0x500000 0x100000>; ++ clock-frequency = <0>; ++ interrupts = < ++ 97 2 0 0 ++ 16 2 1 0>; ++ ++ cc { ++ compatible = "fsl,fman-cc"; ++ }; ++ ++ muram@0 { ++ compatible = "fsl,fman-muram"; ++ reg = <0x0 0x28000>; ++ }; ++ ++ bmi@80000 { ++ compatible = "fsl,fman-bmi"; ++ reg = <0x80000 0x400>; ++ }; ++ ++ qmi@80400 { ++ compatible = "fsl,fman-qmi"; ++ reg = <0x80400 0x400>; ++ }; ++ ++ fman1_oh0: port@81000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x81000 0x1000>; ++ }; ++ ++ fman1_oh1: port@82000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x82000 0x1000>; ++ }; ++ ++ fman1_oh2: port@83000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x83000 0x1000>; ++ }; ++ ++ fman1_oh3: port@84000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x84000 0x1000>; ++ }; ++ ++ fman1_oh4: port@85000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x85000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ fman1_oh5: port@86000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x86000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ fman1_oh6: port@87000 { ++ cell-index = <6>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x87000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ policer@c0000 { ++ compatible = "fsl,fman-policer"; ++ reg = <0xc0000 0x1000>; ++ }; ++ ++ keygen@c1000 { ++ compatible = "fsl,fman-keygen"; ++ reg = <0xc1000 0x1000>; ++ }; ++ ++ dma@c2000 { ++ compatible = "fsl,fman-dma"; ++ reg = <0xc2000 0x1000>; ++ }; ++ ++ fpm@c3000 { ++ compatible = "fsl,fman-fpm"; ++ reg = <0xc3000 0x1000>; ++ }; ++ ++ parser@c7000 { ++ compatible = "fsl,fman-parser"; ++ reg = <0xc7000 0x1000>; ++ }; ++ ++ ptp_timer1: rtc@fe000 { ++ compatible = "fsl,fman-rtc"; ++ reg = <0xfe000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi +new file mode 100644 +index 0000000..72c306c +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 10g port #0 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_10g_rx0: port@90000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-10g-rx"; ++ reg = <0x90000 0x1000>; ++ }; ++ ++ fman0_10g_tx0: port@b0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-10g-tx"; ++ reg = <0xb0000 0x1000>; ++ fsl,qman-channel-id = <0x800>; ++ }; ++ ++ ethernet@f0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xf0000 0x1000>; ++ fsl,port-handles = <&fman0_10g_rx0 &fman0_10g_tx0>; ++ }; ++ ++ mdio@f1000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xf1000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi +new file mode 100644 +index 0000000..c53dadc +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 10g port #1 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_10g_rx1: port@91000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-10g-rx"; ++ reg = <0x91000 0x1000>; ++ }; ++ ++ fman0_10g_tx1: port@b1000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-10g-tx"; ++ reg = <0xb1000 0x1000>; ++ fsl,qman-channel-id = <0x801>; ++ }; ++ ++ ethernet@f2000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xf2000 0x1000>; ++ fsl,port-handles = <&fman0_10g_rx1 &fman0_10g_tx1>; ++ }; ++ ++ mdio@f3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xf3000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi +new file mode 100644 +index 0000000..5d34959 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 1g port #0 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_rx0: port@88000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x88000 0x1000>; ++ }; ++ ++ fman0_tx0: port@a8000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xa8000 0x1000>; ++ }; ++ ++ ethernet@e0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe0000 0x1000>; ++ fsl,port-handles = <&fman0_rx0 &fman0_tx0>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio@e1000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xe1000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi +new file mode 100644 +index 0000000..39620a3 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 1g port #1 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_rx1: port@89000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x89000 0x1000>; ++ }; ++ ++ fman0_tx1: port@a9000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xa9000 0x1000>; ++ }; ++ ++ ethernet@e2000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe2000 0x1000>; ++ fsl,port-handles = <&fman0_rx1 &fman0_tx1>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio@e3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xe3000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi +new file mode 100644 +index 0000000..9c1fb1a +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 1g port #2 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_rx2: port@8a000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8a000 0x1000>; ++ }; ++ ++ fman0_tx2: port@aa000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xaa000 0x1000>; ++ }; ++ ++ ethernet@e4000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe4000 0x1000>; ++ fsl,port-handles = <&fman0_rx2 &fman0_tx2>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio@e5000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xe5000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi +new file mode 100644 +index 0000000..5d2ba1a +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 1g port #3 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_rx3: port@8b000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8b000 0x1000>; ++ }; ++ ++ fman0_tx3: port@ab000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xab000 0x1000>; ++ }; ++ ++ ethernet@e6000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe6000 0x1000>; ++ fsl,port-handles = <&fman0_rx3 &fman0_tx3>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio@e7000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xe7000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi +new file mode 100644 +index 0000000..4b1820b +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 1g port #4 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_rx4: port@8c000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8c000 0x1000>; ++ }; ++ ++ fman0_tx4: port@ac000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xac000 0x1000>; ++ }; ++ ++ ethernet@e8000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe8000 0x1000>; ++ fsl,port-handles = <&fman0_rx4 &fman0_tx4>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio@e9000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xe9000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi +new file mode 100644 +index 0000000..aa06d13 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 1g port #5 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@400000 { ++ fman0_rx5: port@8d000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8d000 0x1000>; ++ }; ++ ++ fman0_tx5: port@ad000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xad000 0x1000>; ++ }; ++ ++ ethernet@ea000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xea000 0x1000>; ++ fsl,port-handles = <&fman0_rx5 &fman0_tx5>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio@eb000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xeb000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi +new file mode 100644 +index 0000000..28f38b9 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi +@@ -0,0 +1,150 @@ ++/* ++ * QorIQ FMan v3 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman0: fman@400000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <0>; ++ compatible = "fsl,fman", "simple-bus"; ++ ranges = <0 0x400000 0x100000>; ++ reg = <0x400000 0x100000>; ++ clock-frequency = <0>; ++ interrupts = < ++ 96 2 0 0 ++ 16 2 1 1>; ++ ++ cc { ++ compatible = "fsl,fman-cc"; ++ }; ++ ++ muram@0 { ++ compatible = "fsl,fman-muram"; ++ reg = <0x0 0x60000>; ++ }; ++ ++ bmi@80000 { ++ compatible = "fsl,fman-bmi"; ++ reg = <0x80000 0x400>; ++ }; ++ ++ qmi@80400 { ++ compatible = "fsl,fman-qmi"; ++ reg = <0x80400 0x400>; ++ }; ++ ++ fman0_oh1: port@82000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x82000 0x1000>; ++ }; ++ ++ fman0_oh2: port@83000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x83000 0x1000>; ++ }; ++ ++ fman0_oh3: port@84000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x84000 0x1000>; ++ }; ++ ++ fman0_oh4: port@85000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x85000 0x1000>; ++ }; ++ ++ fman0_oh5: port@86000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x86000 0x1000>; ++ }; ++ ++ fman0_oh6: port@87000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x87000 0x1000>; ++ }; ++ ++ policer@c0000 { ++ compatible = "fsl,fman-policer"; ++ reg = <0xc0000 0x1000>; ++ }; ++ ++ keygen@c1000 { ++ compatible = "fsl,fman-keygen"; ++ reg = <0xc1000 0x1000>; ++ }; ++ ++ dma@c2000 { ++ compatible = "fsl,fman-dma"; ++ reg = <0xc2000 0x1000>; ++ }; ++ ++ fpm@c3000 { ++ compatible = "fsl,fman-fpm"; ++ reg = <0xc3000 0x1000>; ++ }; ++ ++ parser@c7000 { ++ compatible = "fsl,fman-parser"; ++ reg = <0xc7000 0x1000>; ++ }; ++ ++ vsps@dc000 { ++ compatible = "fsl,fman-vsps"; ++ reg = <0xdc000 0x1000>; ++ }; ++ ++ mdio@fc000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xfc000 0x1000>; ++ }; ++ ++ mdio@fd000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xfd000 0x1000>; ++ }; ++ ++ ptp_timer0: rtc@fe000 { ++ compatible = "fsl,fman-rtc"; ++ reg = <0xfe000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi +new file mode 100644 +index 0000000..b63fb54 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 10g port #0 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_10g_rx0: port@90000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-10g-rx"; ++ reg = <0x90000 0x1000>; ++ }; ++ ++ fman1_10g_tx0: port@b0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-10g-tx"; ++ reg = <0xb0000 0x1000>; ++ fsl,qman-channel-id = <0x820>; ++ }; ++ ++ ethernet@f0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xf0000 0x1000>; ++ fsl,port-handles = <&fman1_10g_rx0 &fman1_10g_tx0>; ++ }; ++ ++ mdio@f1000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xf1000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi +new file mode 100644 +index 0000000..56cb7b1 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 10g port #1 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_10g_rx1: port@91000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-10g-rx"; ++ reg = <0x91000 0x1000>; ++ }; ++ ++ fman1_10g_tx1: port@b1000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-10g-tx"; ++ reg = <0xb1000 0x1000>; ++ fsl,qman-channel-id = <0x821>; ++ }; ++ ++ ethernet@f2000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xf2000 0x1000>; ++ fsl,port-handles = <&fman1_10g_rx1 &fman1_10g_tx1>; ++ }; ++ ++ mdio@f3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xf3000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi +new file mode 100644 +index 0000000..6a4fea5 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 1g port #0 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_rx0: port@88000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x88000 0x1000>; ++ }; ++ ++ fman1_tx0: port@a8000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xa8000 0x1000>; ++ }; ++ ++ ethernet@e0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe0000 0x1000>; ++ fsl,port-handles = <&fman1_rx0 &fman1_tx0>; ++ ptimer-handle = <&ptp_timer1>; ++ }; ++ ++ mdio@e1000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xe1000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi +new file mode 100644 +index 0000000..80f0cd9 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 1g port #1 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_rx1: port@89000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x89000 0x1000>; ++ }; ++ ++ fman1_tx1: port@a9000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xa9000 0x1000>; ++ }; ++ ++ ethernet@e2000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe2000 0x1000>; ++ fsl,port-handles = <&fman1_rx1 &fman1_tx1>; ++ ptimer-handle = <&ptp_timer1>; ++ }; ++ ++ mdio@e3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xe3000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi +new file mode 100644 +index 0000000..a0cbf96 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 1g port #2 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_rx2: port@8a000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8a000 0x1000>; ++ }; ++ ++ fman1_tx2: port@aa000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xaa000 0x1000>; ++ }; ++ ++ ethernet@e4000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe4000 0x1000>; ++ fsl,port-handles = <&fman1_rx2 &fman1_tx2>; ++ ptimer-handle = <&ptp_timer1>; ++ }; ++ ++ mdio@e5000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xe5000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi +new file mode 100644 +index 0000000..636ff3e +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 1g port #3 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_rx3: port@8b000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8b000 0x1000>; ++ }; ++ ++ fman1_tx3: port@ab000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xab000 0x1000>; ++ }; ++ ++ ethernet@e6000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe6000 0x1000>; ++ fsl,port-handles = <&fman1_rx3 &fman1_tx3>; ++ ptimer-handle = <&ptp_timer1>; ++ }; ++ ++ mdio@e7000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xe7000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi +new file mode 100644 +index 0000000..ba12e35 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 1g port #4 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_rx4: port@8c000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8c000 0x1000>; ++ }; ++ ++ fman1_tx4: port@ac000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xac000 0x1000>; ++ }; ++ ++ ethernet@e8000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe8000 0x1000>; ++ fsl,port-handles = <&fman1_rx4 &fman1_tx4>; ++ ptimer-handle = <&ptp_timer1>; ++ }; ++ ++ mdio@e9000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xe9000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi +new file mode 100644 +index 0000000..c8d145e +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * QorIQ FMan v3 1g port #5 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman@500000 { ++ fman1_rx5: port@8d000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8d000 0x1000>; ++ }; ++ ++ fman1_tx5: port@ad000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xad000 0x1000>; ++ }; ++ ++ ethernet@ea000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xea000 0x1000>; ++ fsl,port-handles = <&fman1_rx5 &fman1_tx5>; ++ ptimer-handle = <&ptp_timer1>; ++ }; ++ ++ mdio@eb000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-tbi"; ++ reg = <0xeb000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi +new file mode 100644 +index 0000000..4eeb060 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi +@@ -0,0 +1,150 @@ ++/* ++ * QorIQ FMan v3 device tree stub [ controller @ offset 0x500000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++fman1: fman@500000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <1>; ++ compatible = "fsl,fman", "simple-bus"; ++ ranges = <0 0x500000 0x100000>; ++ reg = <0x500000 0x100000>; ++ clock-frequency = <0>; ++ interrupts = < ++ 97 2 0 0 ++ 16 2 1 0>; ++ ++ cc { ++ compatible = "fsl,fman-cc"; ++ }; ++ ++ muram@0 { ++ compatible = "fsl,fman-muram"; ++ reg = <0x0 0x60000>; ++ }; ++ ++ bmi@80000 { ++ compatible = "fsl,fman-bmi"; ++ reg = <0x80000 0x400>; ++ }; ++ ++ qmi@80400 { ++ compatible = "fsl,fman-qmi"; ++ reg = <0x80400 0x400>; ++ }; ++ ++ fman1_oh1: port@82000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x82000 0x1000>; ++ }; ++ ++ fman1_oh2: port@83000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x83000 0x1000>; ++ }; ++ ++ fman1_oh3: port@84000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x84000 0x1000>; ++ }; ++ ++ fman1_oh4: port@85000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x85000 0x1000>; ++ }; ++ ++ fman1_oh5: port@86000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x86000 0x1000>; ++ }; ++ ++ fman1_oh6: port@87000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x87000 0x1000>; ++ }; ++ ++ policer@c0000 { ++ compatible = "fsl,fman-policer"; ++ reg = <0xc0000 0x1000>; ++ }; ++ ++ keygen@c1000 { ++ compatible = "fsl,fman-keygen"; ++ reg = <0xc1000 0x1000>; ++ }; ++ ++ dma@c2000 { ++ compatible = "fsl,fman-dma"; ++ reg = <0xc2000 0x1000>; ++ }; ++ ++ fpm@c3000 { ++ compatible = "fsl,fman-fpm"; ++ reg = <0xc3000 0x1000>; ++ }; ++ ++ parser@c7000 { ++ compatible = "fsl,fman-parser"; ++ reg = <0xc7000 0x1000>; ++ }; ++ ++ vsps@dc000 { ++ compatible = "fsl,fman-vsps"; ++ reg = <0xdc000 0x1000>; ++ }; ++ ++ mdio@fc000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xfc000 0x1000>; ++ }; ++ ++ mdio@fd000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xfd000 0x1000>; ++ }; ++ ++ ptp_timer1: rtc@fe000 { ++ compatible = "fsl,fman-rtc"; ++ reg = <0xfe000 0x1000>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-gpio-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-gpio-0.dtsi +new file mode 100644 +index 0000000..cf714f5 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-gpio-0.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * QorIQ GPIO device tree stub [ controller @ offset 0x130000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++gpio0: gpio@130000 { ++ compatible = "fsl,qoriq-gpio"; ++ reg = <0x130000 0x1000>; ++ interrupts = <55 2 0 0>; ++ #gpio-cells = <2>; ++ gpio-controller; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-i2c-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-i2c-0.dtsi +new file mode 100644 +index 0000000..5f9bf7d +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-i2c-0.dtsi +@@ -0,0 +1,53 @@ ++/* ++ * QorIQ I2C device tree stub [ controller @ offset 0x118000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++i2c@118000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <0>; ++ compatible = "fsl-i2c"; ++ reg = <0x118000 0x100>; ++ interrupts = <38 2 0 0>; ++ dfsrr; ++}; ++ ++i2c@118100 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <1>; ++ compatible = "fsl-i2c"; ++ reg = <0x118100 0x100>; ++ interrupts = <38 2 0 0>; ++ dfsrr; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-i2c-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-i2c-1.dtsi +new file mode 100644 +index 0000000..7989bf5 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-i2c-1.dtsi +@@ -0,0 +1,53 @@ ++/* ++ * QorIQ I2C device tree stub [ controller @ offset 0x119000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++i2c@119000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <2>; ++ compatible = "fsl-i2c"; ++ reg = <0x119000 0x100>; ++ interrupts = <39 2 0 0>; ++ dfsrr; ++}; ++ ++i2c@119100 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <3>; ++ compatible = "fsl-i2c"; ++ reg = <0x119100 0x100>; ++ interrupts = <39 2 0 0>; ++ dfsrr; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi +new file mode 100644 +index 0000000..08f4227 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi +@@ -0,0 +1,106 @@ ++/* ++ * QorIQ MPIC device tree stub [ controller @ offset 0x40000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++mpic: pic@40000 { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <4>; ++ reg = <0x40000 0x40000>; ++ compatible = "fsl,mpic", "chrp,open-pic"; ++ device_type = "open-pic"; ++ clock-frequency = <0x0>; ++}; ++ ++timer@41100 { ++ compatible = "fsl,mpic-global-timer"; ++ reg = <0x41100 0x100 0x41300 4>; ++ interrupts = <0 0 3 0 ++ 1 0 3 0 ++ 2 0 3 0 ++ 3 0 3 0>; ++}; ++ ++msi0: msi@41600 { ++ compatible = "fsl,mpic-msi"; ++ reg = <0x41600 0x200 0x44140 4>; ++ msi-available-ranges = <0 0x100>; ++ interrupts = < ++ 0xe0 0 0 0 ++ 0xe1 0 0 0 ++ 0xe2 0 0 0 ++ 0xe3 0 0 0 ++ 0xe4 0 0 0 ++ 0xe5 0 0 0 ++ 0xe6 0 0 0 ++ 0xe7 0 0 0>; ++}; ++ ++msi1: msi@41800 { ++ compatible = "fsl,mpic-msi"; ++ reg = <0x41800 0x200 0x45140 4>; ++ msi-available-ranges = <0 0x100>; ++ interrupts = < ++ 0xe8 0 0 0 ++ 0xe9 0 0 0 ++ 0xea 0 0 0 ++ 0xeb 0 0 0 ++ 0xec 0 0 0 ++ 0xed 0 0 0 ++ 0xee 0 0 0 ++ 0xef 0 0 0>; ++}; ++ ++msi2: msi@41a00 { ++ compatible = "fsl,mpic-msi"; ++ reg = <0x41a00 0x200 0x46140 4>; ++ msi-available-ranges = <0 0x100>; ++ interrupts = < ++ 0xf0 0 0 0 ++ 0xf1 0 0 0 ++ 0xf2 0 0 0 ++ 0xf3 0 0 0 ++ 0xf4 0 0 0 ++ 0xf5 0 0 0 ++ 0xf6 0 0 0 ++ 0xf7 0 0 0>; ++}; ++ ++timer@42100 { ++ compatible = "fsl,mpic-global-timer"; ++ reg = <0x42100 0x100 0x42300 4>; ++ interrupts = <4 0 3 0 ++ 5 0 3 0 ++ 6 0 3 0 ++ 7 0 3 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-pme-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-pme-0.dtsi +new file mode 100644 +index 0000000..8789df1 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-pme-0.dtsi +@@ -0,0 +1,39 @@ ++/* ++ * QorIQ PME device tree stub [ controller @ offset 0x316000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++pme: pme@316000 { ++ compatible = "fsl,pme"; ++ reg = <0x316000 0x10000>; ++ interrupts = <16 2 1 5>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-qman-ceetm0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-qman-ceetm0.dtsi +new file mode 100644 +index 0000000..9d3cf3e +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-qman-ceetm0.dtsi +@@ -0,0 +1,43 @@ ++/* ++ * QorIQ QMan CEETM stub ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&qportals { ++ qman-ceetm@0 { ++ compatible = "fsl,qman-ceetm"; ++ fsl,ceetm-lfqid-range = <0xf00000 0x1000>; ++ fsl,ceetm-sp-range = <0 12>; ++ fsl,ceetm-lni-range = <0 8>; ++ fsl,ceetm-channel-range = <0 32>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-qman-ceetm1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-qman-ceetm1.dtsi +new file mode 100644 +index 0000000..4028542 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-qman-ceetm1.dtsi +@@ -0,0 +1,43 @@ ++/* ++ * QorIQ QMan CEETM stub ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++&qportals { ++ qman-ceetm@1 { ++ compatible = "fsl,qman-ceetm"; ++ fsl,ceetm-lfqid-range = <0xf10000 0x1000>; ++ fsl,ceetm-sp-range = <0 12>; ++ fsl,ceetm-lni-range = <0 8>; ++ fsl,ceetm-channel-range = <0 32>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-qman1-portals.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-qman1-portals.dtsi +new file mode 100644 +index 0000000..8476b32 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-qman1-portals.dtsi +@@ -0,0 +1,116 @@ ++/* ++ * QorIQ QMan Portal device tree stub for 10 portals & 15 pool channels ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++#address-cells = <0x1>; ++#size-cells = <0x1>; ++compatible = "simple-bus"; ++qportal0: qman-portal@0 { ++ cell-index = <0x0>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x0 0x4000 0x100000 0x1000>; ++ interrupts = <104 0x2 0 0>; ++ fsl,qman-channel-id = <0x0>; ++}; ++ ++qportal1: qman-portal@4000 { ++ cell-index = <0x1>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x4000 0x4000 0x101000 0x1000>; ++ interrupts = <106 0x2 0 0>; ++ fsl,qman-channel-id = <0x1>; ++}; ++ ++qportal2: qman-portal@8000 { ++ cell-index = <0x2>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x8000 0x4000 0x102000 0x1000>; ++ interrupts = <108 0x2 0 0>; ++ fsl,qman-channel-id = <0x2>; ++}; ++ ++qportal3: qman-portal@c000 { ++ cell-index = <0x3>; ++ compatible = "fsl,qman-portal"; ++ reg = <0xc000 0x4000 0x103000 0x1000>; ++ interrupts = <110 0x2 0 0>; ++ fsl,qman-channel-id = <0x3>; ++}; ++ ++qportal4: qman-portal@10000 { ++ cell-index = <0x4>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x10000 0x4000 0x104000 0x1000>; ++ interrupts = <112 0x2 0 0>; ++ fsl,qman-channel-id = <0x4>; ++}; ++ ++qportal5: qman-portal@14000 { ++ cell-index = <0x5>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x14000 0x4000 0x105000 0x1000>; ++ interrupts = <114 0x2 0 0>; ++ fsl,qman-channel-id = <0x5>; ++}; ++ ++qportal6: qman-portal@18000 { ++ cell-index = <0x6>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x18000 0x4000 0x106000 0x1000>; ++ interrupts = <116 0x2 0 0>; ++ fsl,qman-channel-id = <0x6>; ++}; ++ ++qportal7: qman-portal@1c000 { ++ cell-index = <0x7>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x1c000 0x4000 0x107000 0x1000>; ++ interrupts = <118 0x2 0 0>; ++ fsl,qman-channel-id = <0x7>; ++}; ++ ++qportal8: qman-portal@20000 { ++ cell-index = <0x8>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x20000 0x4000 0x108000 0x1000>; ++ interrupts = <120 0x2 0 0>; ++ fsl,qman-channel-id = <0x8>; ++}; ++ ++qportal9: qman-portal@24000 { ++ cell-index = <0x9>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x24000 0x4000 0x109000 0x1000>; ++ interrupts = <122 0x2 0 0>; ++ fsl,qman-channel-id = <0x9>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-qman1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-qman1.dtsi +new file mode 100644 +index 0000000..8edd2c0 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-qman1.dtsi +@@ -0,0 +1,39 @@ ++/* ++ * QorIQ QMan device tree stub [ controller @ offset 0x318000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++qman: qman@318000 { ++ compatible = "fsl,qman"; ++ reg = <0x318000 0x2000>; ++ interrupts = <16 2 1 3>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-qman2-portals.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-qman2-portals.dtsi +new file mode 100644 +index 0000000..6c6010d +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-qman2-portals.dtsi +@@ -0,0 +1,436 @@ ++/* ++ * QorIQ QMan Portal device tree stub for QMan 3.0 with maximum 50 portals. ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++#address-cells = <0x1>; ++#size-cells = <0x1>; ++compatible = "simple-bus"; ++qportal0: qman-portal@0 { ++ cell-index = <0x0>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x0 0x4000 0x1000000 0x1000>; ++ interrupts = <104 0x2 0 0>; ++ fsl,qman-channel-id = <0x0>; ++}; ++ ++qportal1: qman-portal@4000 { ++ cell-index = <0x1>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x4000 0x4000 0x1001000 0x1000>; ++ interrupts = <106 0x2 0 0>; ++ fsl,qman-channel-id = <0x1>; ++}; ++ ++qportal2: qman-portal@8000 { ++ cell-index = <0x2>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x8000 0x4000 0x1002000 0x1000>; ++ interrupts = <108 0x2 0 0>; ++ fsl,qman-channel-id = <0x2>; ++}; ++ ++qportal3: qman-portal@c000 { ++ cell-index = <0x3>; ++ compatible = "fsl,qman-portal"; ++ reg = <0xc000 0x4000 0x1003000 0x1000>; ++ interrupts = <110 0x2 0 0>; ++ fsl,qman-channel-id = <0x3>; ++}; ++ ++qportal4: qman-portal@10000 { ++ cell-index = <0x4>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x10000 0x4000 0x1004000 0x1000>; ++ interrupts = <112 0x2 0 0>; ++ fsl,qman-channel-id = <0x4>; ++}; ++ ++qportal5: qman-portal@14000 { ++ cell-index = <0x5>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x14000 0x4000 0x1005000 0x1000>; ++ interrupts = <114 0x2 0 0>; ++ fsl,qman-channel-id = <0x5>; ++}; ++ ++qportal6: qman-portal@18000 { ++ cell-index = <0x6>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x18000 0x4000 0x1006000 0x1000>; ++ interrupts = <116 0x2 0 0>; ++ fsl,qman-channel-id = <0x6>; ++}; ++ ++qportal7: qman-portal@1c000 { ++ cell-index = <0x7>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x1c000 0x4000 0x1007000 0x1000>; ++ interrupts = <118 0x2 0 0>; ++ fsl,qman-channel-id = <0x7>; ++}; ++ ++qportal8: qman-portal@20000 { ++ cell-index = <0x8>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x20000 0x4000 0x1008000 0x1000>; ++ interrupts = <120 0x2 0 0>; ++ fsl,qman-channel-id = <0x8>; ++}; ++ ++qportal9: qman-portal@24000 { ++ cell-index = <0x9>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x24000 0x4000 0x1009000 0x1000>; ++ interrupts = <122 0x2 0 0>; ++ fsl,qman-channel-id = <0x9>; ++}; ++ ++qportal10: qman-portal@28000 { ++ cell-index = <0xa>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x28000 0x4000 0x100a000 0x1000>; ++ interrupts = <124 0x2 0 0>; ++ fsl,qman-channel-id = <0xa>; ++}; ++ ++qportal11: qman-portal@2c000 { ++ cell-index = <0xb>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x2c000 0x4000 0x100b000 0x1000>; ++ interrupts = <126 0x2 0 0>; ++ fsl,qman-channel-id = <0xb>; ++}; ++ ++qportal12: qman-portal@30000 { ++ cell-index = <0xc>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x30000 0x4000 0x100c000 0x1000>; ++ interrupts = <128 0x2 0 0>; ++ fsl,qman-channel-id = <0xc>; ++}; ++ ++qportal13: qman-portal@34000 { ++ cell-index = <0xd>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x34000 0x4000 0x100d000 0x1000>; ++ interrupts = <130 0x2 0 0>; ++ fsl,qman-channel-id = <0xd>; ++}; ++ ++qportal14: qman-portal@38000 { ++ cell-index = <0xe>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x38000 0x4000 0x100e000 0x1000>; ++ interrupts = <132 0x2 0 0>; ++ fsl,qman-channel-id = <0xe>; ++}; ++ ++qportal15: qman-portal@3c000 { ++ cell-index = <0xf>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x3c000 0x4000 0x100f000 0x1000>; ++ interrupts = <134 0x2 0 0>; ++ fsl,qman-channel-id = <0xf>; ++}; ++ ++qportal16: qman-portal@40000 { ++ cell-index = <0x10>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x40000 0x4000 0x1010000 0x1000>; ++ interrupts = <136 0x2 0 0>; ++ fsl,qman-channel-id = <0x10>; ++}; ++ ++qportal17: qman-portal@44000 { ++ cell-index = <0x11>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x44000 0x4000 0x1011000 0x1000>; ++ interrupts = <138 0x2 0 0>; ++ fsl,qman-channel-id = <0x11>; ++}; ++ ++qportal18: qman-portal@48000 { ++ cell-index = <0x12>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x48000 0x4000 0x1012000 0x1000>; ++ interrupts = <140 0x2 0 0>; ++ fsl,qman-channel-id = <0x12>; ++}; ++ ++qportal19: qman-portal@4c000 { ++ cell-index = <0x13>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x4c000 0x4000 0x1013000 0x1000>; ++ interrupts = <142 0x2 0 0>; ++ fsl,qman-channel-id = <0x13>; ++}; ++ ++qportal20: qman-portal@50000 { ++ cell-index = <0x14>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x50000 0x4000 0x1014000 0x1000>; ++ interrupts = <144 0x2 0 0>; ++ fsl,qman-channel-id = <0x14>; ++}; ++ ++qportal21: qman-portal@54000 { ++ cell-index = <0x15>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x54000 0x4000 0x1015000 0x1000>; ++ interrupts = <146 0x2 0 0>; ++ fsl,qman-channel-id = <0x15>; ++}; ++ ++qportal22: qman-portal@58000 { ++ cell-index = <0x16>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x58000 0x4000 0x1016000 0x1000>; ++ interrupts = <148 0x2 0 0>; ++ fsl,qman-channel-id = <0x16>; ++}; ++ ++qportal23: qman-portal@5c000 { ++ cell-index = <0x17>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x5c000 0x4000 0x1017000 0x1000>; ++ interrupts = <150 0x2 0 0>; ++ fsl,qman-channel-id = <0x17>; ++}; ++ ++qportal24: qman-portal@60000 { ++ cell-index = <0x18>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x60000 0x4000 0x1018000 0x1000>; ++ interrupts = <152 0x2 0 0>; ++ fsl,qman-channel-id = <0x18>; ++}; ++ ++qportal25: qman-portal@64000 { ++ cell-index = <0x19>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x64000 0x4000 0x1019000 0x1000>; ++ interrupts = <154 0x2 0 0>; ++ fsl,qman-channel-id = <0x19>; ++}; ++ ++qportal26: qman-portal@68000 { ++ cell-index = <0x1a>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x68000 0x4000 0x101a000 0x1000>; ++ interrupts = <156 0x2 0 0>; ++ fsl,qman-channel-id = <0x1a>; ++}; ++ ++qportal27: qman-portal@6c000 { ++ cell-index = <0x1b>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x6c000 0x4000 0x101b000 0x1000>; ++ interrupts = <158 0x2 0 0>; ++ fsl,qman-channel-id = <0x1b>; ++}; ++ ++qportal28: qman-portal@70000 { ++ cell-index = <0x1c>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x70000 0x4000 0x101c000 0x1000>; ++ interrupts = <160 0x2 0 0>; ++ fsl,qman-channel-id = <0x1c>; ++}; ++ ++qportal29: qman-portal@74000 { ++ cell-index = <0x1d>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x74000 0x4000 0x101d000 0x1000>; ++ interrupts = <162 0x2 0 0>; ++ fsl,qman-channel-id = <0x1d>; ++}; ++ ++qportal30: qman-portal@78000 { ++ cell-index = <0x1e>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x78000 0x4000 0x101e000 0x1000>; ++ interrupts = <164 0x2 0 0>; ++ fsl,qman-channel-id = <0x1e>; ++}; ++ ++qportal31: qman-portal@7c000 { ++ cell-index = <0x1f>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x7c000 0x4000 0x101f000 0x1000>; ++ interrupts = <166 0x2 0 0>; ++ fsl,qman-channel-id = <0x1f>; ++}; ++ ++qportal32: qman-portal@80000 { ++ cell-index = <0x20>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x80000 0x4000 0x1020000 0x1000>; ++ interrupts = <168 0x2 0 0>; ++ fsl,qman-channel-id = <0x20>; ++}; ++ ++qportal33: qman-portal@84000 { ++ cell-index = <0x21>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x84000 0x4000 0x1021000 0x1000>; ++ interrupts = <170 0x2 0 0>; ++ fsl,qman-channel-id = <0x21>; ++}; ++ ++qportal34: qman-portal@88000 { ++ cell-index = <0x22>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x88000 0x4000 0x1022000 0x1000>; ++ interrupts = <172 0x2 0 0>; ++ fsl,qman-channel-id = <0x22>; ++}; ++ ++qportal35: qman-portal@8c000 { ++ cell-index = <0x23>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x8c000 0x4000 0x1023000 0x1000>; ++ interrupts = <174 0x2 0 0>; ++ fsl,qman-channel-id = <0x23>; ++}; ++ ++qportal36: qman-portal@90000 { ++ cell-index = <0x24>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x90000 0x4000 0x1024000 0x1000>; ++ interrupts = <384 0x2 0 0>; ++ fsl,qman-channel-id = <0x24>; ++}; ++ ++qportal37: qman-portal@94000 { ++ cell-index = <0x25>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x94000 0x4000 0x1025000 0x1000>; ++ interrupts = <386 0x2 0 0>; ++ fsl,qman-channel-id = <0x25>; ++}; ++ ++qportal38: qman-portal@98000 { ++ cell-index = <0x26>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x98000 0x4000 0x1026000 0x1000>; ++ interrupts = <388 0x2 0 0>; ++ fsl,qman-channel-id = <0x26>; ++}; ++ ++qportal39: qman-portal@9c000 { ++ cell-index = <0x27>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x9c000 0x4000 0x1027000 0x1000>; ++ interrupts = <390 0x2 0 0>; ++ fsl,qman-channel-id = <0x27>; ++}; ++ ++qportal40: qman-portal@a0000 { ++ cell-index = <0x28>; ++ compatible = "fsl,qman-portal"; ++ reg = <0xa0000 0x4000 0x1028000 0x1000>; ++ interrupts = <392 0x2 0 0>; ++ fsl,qman-channel-id = <0x28>; ++}; ++ ++qportal41: qman-portal@a4000 { ++ cell-index = <0x29>; ++ compatible = "fsl,qman-portal"; ++ reg = <0xa4000 0x4000 0x1029000 0x1000>; ++ interrupts = <394 0x2 0 0>; ++ fsl,qman-channel-id = <0x29>; ++}; ++ ++qportal42: qman-portal@a8000 { ++ cell-index = <0x2a>; ++ compatible = "fsl,qman-portal"; ++ reg = <0xa8000 0x4000 0x102a000 0x1000>; ++ interrupts = <396 0x2 0 0>; ++ fsl,qman-channel-id = <0x2a>; ++}; ++ ++qportal43: qman-portal@ac000 { ++ cell-index = <0x2b>; ++ compatible = "fsl,qman-portal"; ++ reg = <0xac000 0x4000 0x102b000 0x1000>; ++ interrupts = <398 0x2 0 0>; ++ fsl,qman-channel-id = <0x2b>; ++}; ++ ++qportal44: qman-portal@b0000 { ++ cell-index = <0x2c>; ++ compatible = "fsl,qman-portal"; ++ reg = <0xb0000 0x4000 0x102c000 0x1000>; ++ interrupts = <400 0x2 0 0>; ++ fsl,qman-channel-id = <0x2c>; ++}; ++ ++qportal45: qman-portal@b4000 { ++ cell-index = <0x2d>; ++ compatible = "fsl,qman-portal"; ++ reg = <0xb4000 0x4000 0x102d000 0x1000>; ++ interrupts = <402 0x2 0 0>; ++ fsl,qman-channel-id = <0x2d>; ++}; ++ ++qportal46: qman-portal@b8000 { ++ cell-index = <0x2e>; ++ compatible = "fsl,qman-portal"; ++ reg = <0xb8000 0x4000 0x102e000 0x1000>; ++ interrupts = <404 0x2 0 0>; ++ fsl,qman-channel-id = <0x2e>; ++}; ++ ++qportal47: qman-portal@bc000 { ++ cell-index = <0x2f>; ++ compatible = "fsl,qman-portal"; ++ reg = <0xbc000 0x4000 0x102f000 0x1000>; ++ interrupts = <406 0x2 0 0>; ++ fsl,qman-channel-id = <0x2f>; ++}; ++ ++qportal48: qman-portal@c0000 { ++ cell-index = <0x30>; ++ compatible = "fsl,qman-portal"; ++ reg = <0xc0000 0x4000 0x1030000 0x1000>; ++ interrupts = <408 0x2 0 0>; ++ fsl,qman-channel-id = <0x30>; ++}; ++ ++qportal49: qman-portal@c4000 { ++ cell-index = <0x31>; ++ compatible = "fsl,qman-portal"; ++ reg = <0xc4000 0x4000 0x1031000 0x1000>; ++ interrupts = <410 0x2 0 0>; ++ fsl,qman-channel-id = <0x31>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi +new file mode 100644 +index 0000000..d2f1315 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi +@@ -0,0 +1,85 @@ ++/* ++ * QorIQ RAID 1.0 device tree stub [ controller @ offset 0x320000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++raideng: raideng@320000 { ++ compatible = "fsl,raideng-v1.0"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x320000 0x10000>; ++ ranges = <0 0x320000 0x10000>; ++ ++ raideng_jq0@1000 { ++ compatible = "fsl,raideng-v1.0-job-queue"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x1000 0x1000>; ++ ranges = <0x0 0x1000 0x1000>; ++ ++ raideng_jr0: jr@0 { ++ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring"; ++ reg = <0x0 0x400>; ++ interrupts = <139 2 0 0>; ++ interrupt-parent = <&mpic>; ++ }; ++ ++ raideng_jr1: jr@400 { ++ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-lp-ring"; ++ reg = <0x400 0x400>; ++ interrupts = <140 2 0 0>; ++ interrupt-parent = <&mpic>; ++ }; ++ }; ++ ++ raideng_jq1@2000 { ++ compatible = "fsl,raideng-v1.0-job-queue"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x2000 0x1000>; ++ ranges = <0x0 0x2000 0x1000>; ++ ++ raideng_jr2: jr@0 { ++ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring"; ++ reg = <0x0 0x400>; ++ interrupts = <141 2 0 0>; ++ interrupt-parent = <&mpic>; ++ }; ++ ++ raideng_jr3: jr@400 { ++ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-lp-ring"; ++ reg = <0x400 0x400>; ++ interrupts = <142 2 0 0>; ++ interrupt-parent = <&mpic>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-rman-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-rman-0.dtsi +new file mode 100644 +index 0000000..3fcfdde +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-rman-0.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * QorIQ RMan device tree stub [ controller @ offset 0x1e0000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++rman: rman@1e0000 { ++ compatible = "fsl,rman"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x1e0000 0x20000>; ++ reg = <0x1e0000 0x20000>; ++ interrupts = <16 2 1 11>; /* err_irq */ ++ ++ inbound-block@0 { ++ compatible = "fsl,rman-inbound-block"; ++ reg = <0x0 0x800>; ++ }; ++ global-cfg@b00 { ++ compatible = "fsl,rman-global-cfg"; ++ reg = <0xb00 0x500>; ++ }; ++ inbound-block@1000 { ++ compatible = "fsl,rman-inbound-block"; ++ reg = <0x1000 0x800>; ++ }; ++ inbound-block@2000 { ++ compatible = "fsl,rman-inbound-block"; ++ reg = <0x2000 0x800>; ++ }; ++ inbound-block@3000 { ++ compatible = "fsl,rman-inbound-block"; ++ reg = <0x3000 0x800>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-rmu-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-rmu-0.dtsi +new file mode 100644 +index 0000000..ca7fec7 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-rmu-0.dtsi +@@ -0,0 +1,68 @@ ++/* ++ * QorIQ RIO Message Unit device tree stub [ controller @ offset 0xd3000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++rmu: rmu@d3000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,srio-rmu"; ++ reg = <0xd3000 0x500>; ++ ranges = <0x0 0xd3000 0x500>; ++ ++ message-unit@0 { ++ compatible = "fsl,srio-msg-unit"; ++ reg = <0x0 0x100>; ++ interrupts = < ++ 60 2 0 0 /* msg1_tx_irq */ ++ 61 2 0 0>;/* msg1_rx_irq */ ++ }; ++ message-unit@100 { ++ compatible = "fsl,srio-msg-unit"; ++ reg = <0x100 0x100>; ++ interrupts = < ++ 62 2 0 0 /* msg2_tx_irq */ ++ 63 2 0 0>;/* msg2_rx_irq */ ++ }; ++ doorbell-unit@400 { ++ compatible = "fsl,srio-dbell-unit"; ++ reg = <0x400 0x80>; ++ interrupts = < ++ 56 2 0 0 /* bell_outb_irq */ ++ 57 2 0 0>;/* bell_inb_irq */ ++ }; ++ port-write-unit@4e0 { ++ compatible = "fsl,srio-port-write-unit"; ++ reg = <0x4e0 0x20>; ++ interrupts = <16 2 1 11>; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sata2-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sata2-0.dtsi +new file mode 100644 +index 0000000..b642047 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-sata2-0.dtsi +@@ -0,0 +1,39 @@ ++/* ++ * QorIQ SATAv2 device tree stub [ controller @ offset 0x220000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++sata@220000 { ++ compatible = "fsl,pq-sata-v2"; ++ reg = <0x220000 0x1000>; ++ interrupts = <68 0x2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sata2-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sata2-1.dtsi +new file mode 100644 +index 0000000..c573702 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-sata2-1.dtsi +@@ -0,0 +1,39 @@ ++/* ++ * QorIQ SATAv2 device tree stub [ controller @ offset 0x221000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++sata@221000 { ++ compatible = "fsl,pq-sata-v2"; ++ reg = <0x221000 0x1000>; ++ interrupts = <69 0x2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sec4.0-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sec4.0-0.dtsi +new file mode 100644 +index 0000000..0cbbac3 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-sec4.0-0.dtsi +@@ -0,0 +1,100 @@ ++/* ++ * QorIQ Sec/Crypto 4.0 device tree stub [ controller @ offset 0x300000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++crypto: crypto@300000 { ++ compatible = "fsl,sec-v4.0"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x300000 0x10000>; ++ ranges = <0 0x300000 0x10000>; ++ interrupts = <92 2 0 0>; ++ ++ sec_jr0: jr@1000 { ++ compatible = "fsl,sec-v4.0-job-ring"; ++ reg = <0x1000 0x1000>; ++ interrupts = <88 2 0 0>; ++ }; ++ ++ sec_jr1: jr@2000 { ++ compatible = "fsl,sec-v4.0-job-ring"; ++ reg = <0x2000 0x1000>; ++ interrupts = <89 2 0 0>; ++ }; ++ ++ sec_jr2: jr@3000 { ++ compatible = "fsl,sec-v4.0-job-ring"; ++ reg = <0x3000 0x1000>; ++ interrupts = <90 2 0 0>; ++ }; ++ ++ sec_jr3: jr@4000 { ++ compatible = "fsl,sec-v4.0-job-ring"; ++ reg = <0x4000 0x1000>; ++ interrupts = <91 2 0 0>; ++ }; ++ ++ rtic@6000 { ++ compatible = "fsl,sec-v4.0-rtic"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x6000 0x100>; ++ ranges = <0x0 0x6100 0xe00>; ++ ++ rtic_a: rtic-a@0 { ++ compatible = "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x00 0x20 0x100 0x80>; ++ }; ++ ++ rtic_b: rtic-b@20 { ++ compatible = "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x20 0x20 0x200 0x80>; ++ }; ++ ++ rtic_c: rtic-c@40 { ++ compatible = "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x40 0x20 0x300 0x80>; ++ }; ++ ++ rtic_d: rtic-d@60 { ++ compatible = "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x60 0x20 0x500 0x80>; ++ }; ++ }; ++}; ++ ++sec_mon: sec_mon@314000 { ++ compatible = "fsl,sec-v4.0-mon"; ++ reg = <0x314000 0x1000>; ++ interrupts = <93 2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sec4.1-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sec4.1-0.dtsi +new file mode 100644 +index 0000000..3308986 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-sec4.1-0.dtsi +@@ -0,0 +1,109 @@ ++/* ++ * QorIQ Sec/Crypto 4.1 device tree stub [ controller @ offset 0x300000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++crypto: crypto@300000 { ++ compatible = "fsl,sec-v4.1", "fsl,sec-v4.0"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x300000 0x10000>; ++ ranges = <0 0x300000 0x10000>; ++ interrupts = <92 2 0 0>; ++ ++ sec_jr0: jr@1000 { ++ compatible = "fsl,sec-v4.1-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x1000 0x1000>; ++ interrupts = <88 2 0 0>; ++ }; ++ ++ sec_jr1: jr@2000 { ++ compatible = "fsl,sec-v4.1-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x2000 0x1000>; ++ interrupts = <89 2 0 0>; ++ }; ++ ++ sec_jr2: jr@3000 { ++ compatible = "fsl,sec-v4.1-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x3000 0x1000>; ++ interrupts = <90 2 0 0>; ++ }; ++ ++ sec_jr3: jr@4000 { ++ compatible = "fsl,sec-v4.1-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x4000 0x1000>; ++ interrupts = <91 2 0 0>; ++ }; ++ ++ rtic@6000 { ++ compatible = "fsl,sec-v4.1-rtic", ++ "fsl,sec-v4.0-rtic"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x6000 0x100>; ++ ranges = <0x0 0x6100 0xe00>; ++ ++ rtic_a: rtic-a@0 { ++ compatible = "fsl,sec-v4.1-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x00 0x20 0x100 0x80>; ++ }; ++ ++ rtic_b: rtic-b@20 { ++ compatible = "fsl,sec-v4.1-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x20 0x20 0x200 0x80>; ++ }; ++ ++ rtic_c: rtic-c@40 { ++ compatible = "fsl,sec-v4.1-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x40 0x20 0x300 0x80>; ++ }; ++ ++ rtic_d: rtic-d@60 { ++ compatible = "fsl,sec-v4.1-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x60 0x20 0x500 0x80>; ++ }; ++ }; ++}; ++ ++sec_mon: sec_mon@314000 { ++ compatible = "fsl,sec-v4.1-mon", "fsl,sec-v4.0-mon"; ++ reg = <0x314000 0x1000>; ++ interrupts = <93 2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sec4.2-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sec4.2-0.dtsi +new file mode 100644 +index 0000000..7990e0d +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-sec4.2-0.dtsi +@@ -0,0 +1,109 @@ ++/* ++ * QorIQ Sec/Crypto 4.2 device tree stub [ controller @ offset 0x300000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++crypto: crypto@300000 { ++ compatible = "fsl,sec-v4.2", "fsl,sec-v4.0"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x300000 0x10000>; ++ ranges = <0 0x300000 0x10000>; ++ interrupts = <92 2 0 0>; ++ ++ sec_jr0: jr@1000 { ++ compatible = "fsl,sec-v4.2-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x1000 0x1000>; ++ interrupts = <88 2 0 0>; ++ }; ++ ++ sec_jr1: jr@2000 { ++ compatible = "fsl,sec-v4.2-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x2000 0x1000>; ++ interrupts = <89 2 0 0>; ++ }; ++ ++ sec_jr2: jr@3000 { ++ compatible = "fsl,sec-v4.2-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x3000 0x1000>; ++ interrupts = <90 2 0 0>; ++ }; ++ ++ sec_jr3: jr@4000 { ++ compatible = "fsl,sec-v4.2-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x4000 0x1000>; ++ interrupts = <91 2 0 0>; ++ }; ++ ++ rtic@6000 { ++ compatible = "fsl,sec-v4.2-rtic", ++ "fsl,sec-v4.0-rtic"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x6000 0x100>; ++ ranges = <0x0 0x6100 0xe00>; ++ ++ rtic_a: rtic-a@0 { ++ compatible = "fsl,sec-v4.2-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x00 0x20 0x100 0x80>; ++ }; ++ ++ rtic_b: rtic-b@20 { ++ compatible = "fsl,sec-v4.2-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x20 0x20 0x200 0x80>; ++ }; ++ ++ rtic_c: rtic-c@40 { ++ compatible = "fsl,sec-v4.2-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x40 0x20 0x300 0x80>; ++ }; ++ ++ rtic_d: rtic-d@60 { ++ compatible = "fsl,sec-v4.2-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x60 0x20 0x500 0x80>; ++ }; ++ }; ++}; ++ ++sec_mon: sec_mon@314000 { ++ compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon"; ++ reg = <0x314000 0x1000>; ++ interrupts = <93 2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sec5.0-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sec5.0-0.dtsi +new file mode 100644 +index 0000000..ffd458f +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-sec5.0-0.dtsi +@@ -0,0 +1,109 @@ ++/* ++ * QorIQ Sec/Crypto 5.0 device tree stub [ controller @ offset 0x300000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++crypto: crypto@300000 { ++ compatible = "fsl,sec-v5.0", "fsl,sec-v4.0"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x300000 0x10000>; ++ ranges = <0 0x300000 0x10000>; ++ interrupts = <92 2 0 0>; ++ ++ sec_jr0: jr@1000 { ++ compatible = "fsl,sec-v5.0-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x1000 0x1000>; ++ interrupts = <88 2 0 0>; ++ }; ++ ++ sec_jr1: jr@2000 { ++ compatible = "fsl,sec-v5.0-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x2000 0x1000>; ++ interrupts = <89 2 0 0>; ++ }; ++ ++ sec_jr2: jr@3000 { ++ compatible = "fsl,sec-v5.0-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x3000 0x1000>; ++ interrupts = <90 2 0 0>; ++ }; ++ ++ sec_jr3: jr@4000 { ++ compatible = "fsl,sec-v5.0-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x4000 0x1000>; ++ interrupts = <91 2 0 0>; ++ }; ++ ++ rtic@6000 { ++ compatible = "fsl,sec-v5.0-rtic", ++ "fsl,sec-v4.0-rtic"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x6000 0x100>; ++ ranges = <0x0 0x6100 0xe00>; ++ ++ rtic_a: rtic-a@0 { ++ compatible = "fsl,sec-v5.0-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x00 0x20 0x100 0x80>; ++ }; ++ ++ rtic_b: rtic-b@20 { ++ compatible = "fsl,sec-v5.0-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x20 0x20 0x200 0x80>; ++ }; ++ ++ rtic_c: rtic-c@40 { ++ compatible = "fsl,sec-v5.0-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x40 0x20 0x300 0x80>; ++ }; ++ ++ rtic_d: rtic-d@60 { ++ compatible = "fsl,sec-v5.0-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x60 0x20 0x500 0x80>; ++ }; ++ }; ++}; ++ ++sec_mon: sec_mon@314000 { ++ compatible = "fsl,sec-v5.0-mon", "fsl,sec-v4.0-mon"; ++ reg = <0x314000 0x1000>; ++ interrupts = <93 2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sec5.2-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sec5.2-0.dtsi +new file mode 100644 +index 0000000..7b2ab8a +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-sec5.2-0.dtsi +@@ -0,0 +1,118 @@ ++/* ++ * QorIQ Sec/Crypto 5.2 device tree stub [ controller @ offset 0x300000 ] ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++crypto: crypto@300000 { ++ compatible = "fsl,sec-v5.2", "fsl,sec-v5.0", "fsl,sec-v4.0"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x300000 0x10000>; ++ ranges = <0 0x300000 0x10000>; ++ interrupts = <92 2 0 0>; ++ ++ sec_jr0: jr@1000 { ++ compatible = "fsl,sec-v5.2-job-ring", ++ "fsl,sec-v5.0-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x1000 0x1000>; ++ interrupts = <88 2 0 0>; ++ }; ++ ++ sec_jr1: jr@2000 { ++ compatible = "fsl,sec-v5.2-job-ring", ++ "fsl,sec-v5.0-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x2000 0x1000>; ++ interrupts = <89 2 0 0>; ++ }; ++ ++ sec_jr2: jr@3000 { ++ compatible = "fsl,sec-v5.2-job-ring", ++ "fsl,sec-v5.0-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x3000 0x1000>; ++ interrupts = <90 2 0 0>; ++ }; ++ ++ sec_jr3: jr@4000 { ++ compatible = "fsl,sec-v5.2-job-ring", ++ "fsl,sec-v5.0-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x4000 0x1000>; ++ interrupts = <91 2 0 0>; ++ }; ++ ++ rtic@6000 { ++ compatible = "fsl,sec-v5.2-rtic", ++ "fsl,sec-v5.0-rtic", ++ "fsl,sec-v4.0-rtic"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x6000 0x100>; ++ ranges = <0x0 0x6100 0xe00>; ++ ++ rtic_a: rtic-a@0 { ++ compatible = "fsl,sec-v5.2-rtic-memory", ++ "fsl,sec-v5.0-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x00 0x20 0x100 0x80>; ++ }; ++ ++ rtic_b: rtic-b@20 { ++ compatible = "fsl,sec-v5.2-rtic-memory", ++ "fsl,sec-v5.0-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x20 0x20 0x200 0x80>; ++ }; ++ ++ rtic_c: rtic-c@40 { ++ compatible = "fsl,sec-v5.2-rtic-memory", ++ "fsl,sec-v5.0-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x40 0x20 0x300 0x80>; ++ }; ++ ++ rtic_d: rtic-d@60 { ++ compatible = "fsl,sec-v5.2-rtic-memory", ++ "fsl,sec-v5.0-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x60 0x20 0x500 0x80>; ++ }; ++ }; ++}; ++ ++sec_mon: sec_mon@314000 { ++ compatible = "fsl,sec-v5.2-mon", "fsl,sec-v5.0-mon", "fsl,sec-v4.0-mon"; ++ reg = <0x314000 0x1000>; ++ interrupts = <93 2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sec5.3-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sec5.3-0.dtsi +new file mode 100644 +index 0000000..0339825 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-sec5.3-0.dtsi +@@ -0,0 +1,118 @@ ++/* ++ * QorIQ Sec/Crypto 5.3 device tree stub [ controller @ offset 0x300000 ] ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++crypto: crypto@300000 { ++ compatible = "fsl,sec-v5.3", "fsl,sec-v5.0", "fsl,sec-v4.0"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x300000 0x10000>; ++ ranges = <0 0x300000 0x10000>; ++ interrupts = <92 2 0 0>; ++ ++ sec_jr0: jr@1000 { ++ compatible = "fsl,sec-v5.3-job-ring", ++ "fsl,sec-v5.0-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x1000 0x1000>; ++ interrupts = <88 2 0 0>; ++ }; ++ ++ sec_jr1: jr@2000 { ++ compatible = "fsl,sec-v5.3-job-ring", ++ "fsl,sec-v5.0-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x2000 0x1000>; ++ interrupts = <89 2 0 0>; ++ }; ++ ++ sec_jr2: jr@3000 { ++ compatible = "fsl,sec-v5.3-job-ring", ++ "fsl,sec-v5.0-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x3000 0x1000>; ++ interrupts = <90 2 0 0>; ++ }; ++ ++ sec_jr3: jr@4000 { ++ compatible = "fsl,sec-v5.3-job-ring", ++ "fsl,sec-v5.0-job-ring", ++ "fsl,sec-v4.0-job-ring"; ++ reg = <0x4000 0x1000>; ++ interrupts = <91 2 0 0>; ++ }; ++ ++ rtic@6000 { ++ compatible = "fsl,sec-v5.3-rtic", ++ "fsl,sec-v5.0-rtic", ++ "fsl,sec-v4.0-rtic"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x6000 0x100>; ++ ranges = <0x0 0x6100 0xe00>; ++ ++ rtic_a: rtic-a@0 { ++ compatible = "fsl,sec-v5.3-rtic-memory", ++ "fsl,sec-v5.0-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x00 0x20 0x100 0x80>; ++ }; ++ ++ rtic_b: rtic-b@20 { ++ compatible = "fsl,sec-v5.3-rtic-memory", ++ "fsl,sec-v5.0-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x20 0x20 0x200 0x80>; ++ }; ++ ++ rtic_c: rtic-c@40 { ++ compatible = "fsl,sec-v5.3-rtic-memory", ++ "fsl,sec-v5.0-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x40 0x20 0x300 0x80>; ++ }; ++ ++ rtic_d: rtic-d@60 { ++ compatible = "fsl,sec-v5.3-rtic-memory", ++ "fsl,sec-v5.0-rtic-memory", ++ "fsl,sec-v4.0-rtic-memory"; ++ reg = <0x60 0x20 0x500 0x80>; ++ }; ++ }; ++}; ++ ++sec_mon: sec_mon@314000 { ++ compatible = "fsl,sec-v5.3-mon", "fsl,sec-v5.0-mon", "fsl,sec-v4.0-mon"; ++ reg = <0x314000 0x1000>; ++ interrupts = <93 2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-usb2-dr-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-usb2-dr-0.dtsi +new file mode 100644 +index 0000000..4dd6f84 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-usb2-dr-0.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * QorIQ USB DR device tree stub [ controller @ offset 0x211000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++usb@211000 { ++ compatible = "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr"; ++ reg = <0x211000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <45 0x2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-usb2-mph-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-usb2-mph-0.dtsi +new file mode 100644 +index 0000000..f053835 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-usb2-mph-0.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * QorIQ USB Host device tree stub [ controller @ offset 0x210000 ] ++ * ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++usb@210000 { ++ compatible = "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph"; ++ reg = <0x210000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <44 0x2 0 0>; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi +new file mode 100644 +index 0000000..b27fb24 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi +@@ -0,0 +1,599 @@ ++/* ++ * T4240 Silicon/SoC Device Tree Source (post include) ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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. ++ */ ++ ++&ifc { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,ifc", "simple-bus"; ++ interrupts = <25 2 0 0>; ++}; ++ ++&lportals { ++/include/ "interlaken-lac-portals.dtsi" ++}; ++ ++&bportals { ++/include/ "qoriq-bman2-portals.dtsi" ++}; ++ ++&qportals { ++/include/ "qoriq-qman2-portals.dtsi" ++}; ++ ++/* controller at 0x240000 */ ++&pci0 { ++ compatible = "fsl,t4240-pcie", "fsl,qoriq-pcie-v3.0"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <20 2 0 0>; ++ pcie@0 { ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <20 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 40 1 0 0 ++ 0000 0 0 2 &mpic 1 1 0 0 ++ 0000 0 0 3 &mpic 2 1 0 0 ++ 0000 0 0 4 &mpic 3 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x250000 */ ++&pci1 { ++ compatible = "fsl,t4240-pcie", "fsl,qoriq-pcie-v3.0"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <21 2 0 0>; ++ pcie@0 { ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <21 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 41 1 0 0 ++ 0000 0 0 2 &mpic 5 1 0 0 ++ 0000 0 0 3 &mpic 6 1 0 0 ++ 0000 0 0 4 &mpic 7 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x260000 */ ++&pci2 { ++ compatible = "fsl,t4240-pcie", "fsl,qoriq-pcie-v3.0"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <22 2 0 0>; ++ pcie@0 { ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <22 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 42 1 0 0 ++ 0000 0 0 2 &mpic 9 1 0 0 ++ 0000 0 0 3 &mpic 10 1 0 0 ++ 0000 0 0 4 &mpic 11 1 0 0 ++ >; ++ }; ++}; ++ ++/* controller at 0x270000 */ ++&pci3 { ++ compatible = "fsl,t4240-pcie", "fsl,qoriq-pcie-v3.0"; ++ device_type = "pci"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ bus-range = <0x0 0xff>; ++ clock-frequency = <33333333>; ++ interrupts = <23 2 0 0>; ++ pcie@0 { ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ interrupts = <23 2 0 0>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0 0 1 &mpic 43 1 0 0 ++ 0000 0 0 2 &mpic 0 1 0 0 ++ 0000 0 0 3 &mpic 4 1 0 0 ++ 0000 0 0 4 &mpic 8 1 0 0 ++ >; ++ }; ++}; ++ ++&rio { ++ compatible = "fsl,srio"; ++ interrupts = <16 2 1 11>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ port1 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <1>; ++ }; ++ ++ port2 { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ cell-index = <2>; ++ }; ++}; ++ ++&dcsr { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,dcsr", "simple-bus"; ++ ++ dcsr-epu@0 { ++ compatible = "fsl,t4240-dcsr-epu", "fsl,dcsr-epu"; ++ interrupts = <52 2 0 0 ++ 84 2 0 0 ++ 85 2 0 0 ++ 94 2 0 0 ++ 95 2 0 0>; ++ reg = <0x0 0x1000>; ++ }; ++ dcsr-npc { ++ compatible = "fsl,t4240-dcsr-cnpc", "fsl,dcsr-cnpc"; ++ reg = <0x1000 0x1000 0x1002000 0x10000>; ++ }; ++ dcsr-nxc@2000 { ++ compatible = "fsl,dcsr-nxc"; ++ reg = <0x2000 0x1000>; ++ }; ++ dcsr-corenet { ++ compatible = "fsl,dcsr-corenet"; ++ reg = <0x8000 0x1000 0x1A000 0x1000>; ++ }; ++ dcsr-dpaa@9000 { ++ compatible = "fsl,t4240-dcsr-dpaa", "fsl,dcsr-dpaa"; ++ reg = <0x9000 0x1000>; ++ }; ++ dcsr-ocn@11000 { ++ compatible = "fsl,t4240-dcsr-ocn", "fsl,dcsr-ocn"; ++ reg = <0x11000 0x1000>; ++ }; ++ dcsr-ddr@12000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr1>; ++ reg = <0x12000 0x1000>; ++ }; ++ dcsr-ddr@13000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr2>; ++ reg = <0x13000 0x1000>; ++ }; ++ dcsr-ddr@14000 { ++ compatible = "fsl,dcsr-ddr"; ++ dev-handle = <&ddr3>; ++ reg = <0x14000 0x1000>; ++ }; ++ dcsr-nal@18000 { ++ compatible = "fsl,t4240-dcsr-nal", "fsl,dcsr-nal"; ++ reg = <0x18000 0x1000>; ++ }; ++ dcsr-rcpm@22000 { ++ compatible = "fsl,t4240-dcsr-rcpm", "fsl,dcsr-rcpm"; ++ reg = <0x22000 0x1000>; ++ }; ++ dcsr-snpc@30000 { ++ compatible = "fsl,t4240-dcsr-snpc", "fsl,dcsr-snpc"; ++ reg = <0x30000 0x1000 0x1022000 0x10000>; ++ }; ++ dcsr-snpc@31000 { ++ compatible = "fsl,t4240-dcsr-snpc", "fsl,dcsr-snpc"; ++ reg = <0x31000 0x1000 0x1042000 0x10000>; ++ }; ++ dcsr-snpc@32000 { ++ compatible = "fsl,t4240-dcsr-snpc", "fsl,dcsr-snpc"; ++ reg = <0x32000 0x1000 0x1062000 0x10000>; ++ }; ++ dcsr-cpu-sb-proxy@100000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu0>; ++ reg = <0x100000 0x1000 0x101000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@108000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu1>; ++ reg = <0x108000 0x1000 0x109000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@110000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu2>; ++ reg = <0x110000 0x1000 0x111000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@118000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu3>; ++ reg = <0x118000 0x1000 0x119000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@120000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu4>; ++ reg = <0x120000 0x1000 0x121000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@128000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu5>; ++ reg = <0x128000 0x1000 0x129000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@130000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu6>; ++ reg = <0x130000 0x1000 0x131000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@138000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu7>; ++ reg = <0x138000 0x1000 0x139000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@140000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu8>; ++ reg = <0x140000 0x1000 0x141000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@148000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu9>; ++ reg = <0x148000 0x1000 0x149000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@150000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu10>; ++ reg = <0x150000 0x1000 0x151000 0x1000>; ++ }; ++ dcsr-cpu-sb-proxy@158000 { ++ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; ++ cpu-handle = <&cpu11>; ++ reg = <0x158000 0x1000 0x159000 0x1000>; ++ }; ++}; ++ ++&soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "simple-bus"; ++ ++ soc-sram-error { ++ compatible = "fsl,soc-sram-error"; ++ interrupts = <16 2 1 29>; ++ }; ++ ++ corenet-law@0 { ++ compatible = "fsl,corenet-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <32>; ++ }; ++ ++ ddr1: memory-controller@8000 { ++ compatible = "fsl,qoriq-memory-controller-v4.7", ++ "fsl,qoriq-memory-controller"; ++ reg = <0x8000 0x1000>; ++ interrupts = <16 2 1 23>; ++ }; ++ ++ ddr2: memory-controller@9000 { ++ compatible = "fsl,qoriq-memory-controller-v4.7", ++ "fsl,qoriq-memory-controller"; ++ reg = <0x9000 0x1000>; ++ interrupts = <16 2 1 22>; ++ }; ++ ++ ddr3: memory-controller@a000 { ++ compatible = "fsl,qoriq-memory-controller-v4.7", ++ "fsl,qoriq-memory-controller"; ++ reg = <0xa000 0x1000>; ++ interrupts = <16 2 1 21>; ++ }; ++ ++ cpc: l3-cache-controller@10000 { ++ compatible = "fsl,p5020-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache"; ++ reg = <0x10000 0x1000 ++ 0x11000 0x1000>; ++ interrupts = <16 2 1 27 ++ 16 2 1 26>; ++ }; ++ ++ corenet-cf@18000 { ++ compatible = "fsl,corenet-cf"; ++ reg = <0x18000 0x1000>; ++ interrupts = <16 2 1 31>; ++ fsl,ccf-num-csdids = <32>; ++ fsl,ccf-num-snoopids = <32>; ++ }; ++ ++ iommu@20000 { ++ compatible = "fsl,pamu-v1.0", "fsl,pamu"; ++ reg = <0x20000 0x6000>; ++ interrupts = < ++ 24 2 0 0 ++ 16 2 1 30>; ++ }; ++ ++/include/ "qoriq-mpic.dtsi" ++ ++ guts: global-utilities@e0000 { ++ compatible = "fsl,t4240-device-config"; ++ reg = <0xe0000 0xe00>; ++ fsl,has-rstcr; ++ fsl,liodn-bits = <12>; ++ }; ++ ++ clockgen: global-utilities@e1000 { ++ compatible = "fsl,t4240-clockgen", "fsl,qoriq-clockgen-2"; ++ reg = <0xe1000 0x1000>; ++ }; ++ ++/include/ "interlaken-lac.dtsi" ++ ++ rcpm: global-utilities@e2000 { ++ compatible = "fsl,t4240-rcpm", "fsl,qoriq-rcpm-2"; ++ reg = <0xe2000 0x1000>; ++ }; ++ ++/include/ "qoriq-dma-0.dtsi" ++/include/ "qoriq-dma-1.dtsi" ++ ++/include/ "qoriq-espi-0.dtsi" ++ spi@110000 { ++ fsl,espi-num-chipselects = <4>; ++ }; ++ ++/include/ "qoriq-esdhc-0.dtsi" ++ sdhc@114000 { ++ compatible = "fsl,t4240-esdhc", "fsl,esdhc"; ++ sdhci,auto-cmd12; ++ }; ++/include/ "qoriq-i2c-0.dtsi" ++/include/ "qoriq-i2c-1.dtsi" ++/include/ "qoriq-duart-0.dtsi" ++/include/ "qoriq-duart-1.dtsi" ++/include/ "qoriq-sec5.0-0.dtsi" ++ ++ ++ /* ++ * Temporarily define cluster 1/2/3's L2 cache nodes in order to pass ++ * next-level-cache info to uboot to do L3 cache fixup. This can be ++ * removed once u-boot can create cpu node with cache info. ++ */ ++ L2_1: l2-cache-controller@c20000 { ++ compatible = "fsl,t4240-l2-cache-controller"; ++ reg = <0xc20000 0x40000>; ++ next-level-cache = <&cpc>; ++ }; ++ L2_2: l2-cache-controller@c60000 { ++ compatible = "fsl,t4240-l2-cache-controller"; ++ reg = <0xc60000 0x40000>; ++ next-level-cache = <&cpc>; ++ }; ++ L2_3: l2-cache-controller@ca0000 { ++ compatible = "fsl,t4240-l2-cache-controller"; ++ reg = <0xca0000 0x40000>; ++ next-level-cache = <&cpc>; ++ }; ++ ++/include/ "qoriq-qman1.dtsi" ++/include/ "qoriq-bman1.dtsi" ++ ++/include/ "qoriq-rman-0.dtsi" ++ rman: rman@1e0000 { ++ fsl,qman-channels-id = <0x880 0x881>; ++ }; ++ ++/include/ "qoriq-usb2-mph-0.dtsi" ++ usb0: usb@210000 { ++ compatible = "fsl-usb2-mph-v2.4", "fsl-usb2-mph"; ++ phy_type = "utmi"; ++ port0; ++ }; ++/include/ "qoriq-usb2-dr-0.dtsi" ++ usb1: usb@211000 { ++ compatible = "fsl-usb2-dr-v2.4", "fsl-usb2-dr"; ++ dr_mode = "host"; ++ phy_type = "utmi"; ++ }; ++/include/ "qoriq-sata2-0.dtsi" ++ sata0: sata@220000 { ++ compatible = "fsl,t4240-rev1.0-sata", "fsl,pq-sata-v2"; ++ }; ++/include/ "qoriq-sata2-1.dtsi" ++ sata1: sata@221000 { ++ compatible = "fsl,t4240-rev1.0-sata", "fsl,pq-sata-v2"; ++ }; ++/include/ "qoriq-dce-0.dtsi" ++/include/ "qoriq-pme-0.dtsi" ++ ++/include/ "qoriq-fman3-0.dtsi" ++/include/ "qoriq-fman3-0-1g-0.dtsi" ++/include/ "qoriq-fman3-0-1g-1.dtsi" ++/include/ "qoriq-fman3-0-1g-2.dtsi" ++/include/ "qoriq-fman3-0-1g-3.dtsi" ++/include/ "qoriq-fman3-0-1g-4.dtsi" ++/include/ "qoriq-fman3-0-1g-5.dtsi" ++/include/ "qoriq-fman3-0-10g-0.dtsi" ++/include/ "qoriq-fman3-0-10g-1.dtsi" ++ fman0: fman@400000 { ++ /* tx - 1g - 0 */ ++ port@a8000 { ++ fsl,qman-channel-id = <0x802>; ++ }; ++ /* tx - 1g - 1 */ ++ port@a9000 { ++ fsl,qman-channel-id = <0x803>; ++ }; ++ /* tx - 1g - 2 */ ++ port@aa000 { ++ fsl,qman-channel-id = <0x804>; ++ }; ++ /* tx - 1g - 3 */ ++ port@ab000 { ++ fsl,qman-channel-id = <0x805>; ++ }; ++ /* tx - 1g - 4 */ ++ port@ac000 { ++ fsl,qman-channel-id = <0x806>; ++ }; ++ /* tx - 1g - 5 */ ++ port@ad000 { ++ fsl,qman-channel-id = <0x807>; ++ }; ++ /* tx - 10g - 0 */ ++ port@b0000 { ++ fsl,qman-channel-id = <0x800>; ++ }; ++ /* tx - 10g - 1 */ ++ port@b1000 { ++ fsl,qman-channel-id = <0x801>; ++ }; ++ /* offline - 1 */ ++ port@82000 { ++ fsl,qman-channel-id = <0x809>; ++ }; ++ /* offline - 2 */ ++ port@83000 { ++ fsl,qman-channel-id = <0x80a>; ++ }; ++ /* offline - 3 */ ++ port@84000 { ++ fsl,qman-channel-id = <0x80b>; ++ }; ++ /* offline - 4 */ ++ port@85000 { ++ fsl,qman-channel-id = <0x80c>; ++ }; ++ /* offline - 5 */ ++ port@86000 { ++ fsl,qman-channel-id = <0x80d>; ++ }; ++ /* offline - 6 */ ++ port@87000 { ++ fsl,qman-channel-id = <0x80e>; ++ }; ++ }; ++ ++/include/ "qoriq-fman3-1.dtsi" ++/include/ "qoriq-fman3-1-1g-0.dtsi" ++/include/ "qoriq-fman3-1-1g-1.dtsi" ++/include/ "qoriq-fman3-1-1g-2.dtsi" ++/include/ "qoriq-fman3-1-1g-3.dtsi" ++/include/ "qoriq-fman3-1-1g-4.dtsi" ++/include/ "qoriq-fman3-1-1g-5.dtsi" ++/include/ "qoriq-fman3-1-10g-0.dtsi" ++/include/ "qoriq-fman3-1-10g-1.dtsi" ++ fman1: fman@500000 { ++ /* tx - 1g - 0 */ ++ port@a8000 { ++ fsl,qman-channel-id = <0x822>; ++ }; ++ /* tx - 1g - 1 */ ++ port@a9000 { ++ fsl,qman-channel-id = <0x823>; ++ }; ++ /* tx - 1g - 2 */ ++ port@aa000 { ++ fsl,qman-channel-id = <0x824>; ++ }; ++ /* tx - 1g - 3 */ ++ port@ab000 { ++ fsl,qman-channel-id = <0x825>; ++ }; ++ /* tx - 1g - 4 */ ++ port@ac000 { ++ fsl,qman-channel-id = <0x826>; ++ }; ++ /* tx - 1g - 5 */ ++ port@ad000 { ++ fsl,qman-channel-id = <0x827>; ++ }; ++ /* tx - 10g - 0 */ ++ port@b0000 { ++ fsl,qman-channel-id = <0x820>; ++ }; ++ /* tx - 10g - 1 */ ++ port@b1000 { ++ fsl,qman-channel-id = <0x821>; ++ }; ++ /* offline - 1 */ ++ port@82000 { ++ fsl,qman-channel-id = <0x829>; ++ }; ++ /* offline - 2 */ ++ port@83000 { ++ fsl,qman-channel-id = <0x82a>; ++ }; ++ /* offline - 3 */ ++ port@84000 { ++ fsl,qman-channel-id = <0x82b>; ++ }; ++ /* offline - 4 */ ++ port@85000 { ++ fsl,qman-channel-id = <0x82c>; ++ }; ++ /* offline - 5 */ ++ port@86000 { ++ fsl,qman-channel-id = <0x82d>; ++ }; ++ /* offline - 6 */ ++ port@87000 { ++ fsl,qman-channel-id = <0x82e>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi +new file mode 100644 +index 0000000..0997ef1 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi +@@ -0,0 +1,156 @@ ++/* ++ * T4240 Silicon/SoC Device Tree Source (pre include) ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++/ { ++ compatible = "fsl,T4240"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&mpic>; ++ ++ aliases { ++ ccsr = &soc; ++ dcsr = &dcsr; ++ ++ serial0 = &serial0; ++ serial1 = &serial1; ++ serial2 = &serial2; ++ serial3 = &serial3; ++ lac = &lac; ++ bman = &bman; ++ qman = &qman; ++ pme = &pme; ++ dce = &dce; ++ crypto = &crypto; ++ fman0 = &fman0; ++ fman1 = &fman1; ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ ethernet3 = &enet3; ++ ethernet4 = &enet4; ++ ethernet5 = &enet5; ++ ethernet6 = &enet6; ++ ethernet7 = &enet7; ++ ethernet8 = &enet8; ++ ethernet9 = &enet9; ++ ethernet10 = &enet10; ++ ethernet11 = &enet11; ++ ethernet12 = &enet12; ++ ethernet13 = &enet13; ++ ethernet14 = &enet14; ++ ethernet15 = &enet15; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ pci3 = &pci3; ++ rman = &rman; ++ dma0 = &dma0; ++ dma1 = &dma1; ++ sdhc = &sdhc; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* ++ * Temporarily add next-level-cache info in each cpu node so ++ * that uboot can do L2 cache fixup. This can be removed once ++ * u-boot can create cpu node with cache info. ++ */ ++ cpu0: PowerPC,e6500@0 { ++ device_type = "cpu"; ++ reg = <0 1>; ++ next-level-cache = <&L2_1>; ++ }; ++ cpu1: PowerPC,e6500@1 { ++ device_type = "cpu"; ++ reg = <2 3>; ++ next-level-cache = <&L2_1>; ++ }; ++ cpu2: PowerPC,e6500@2 { ++ device_type = "cpu"; ++ reg = <4 5>; ++ next-level-cache = <&L2_1>; ++ }; ++ cpu3: PowerPC,e6500@3 { ++ device_type = "cpu"; ++ reg = <6 7>; ++ next-level-cache = <&L2_1>; ++ }; ++ ++ cpu4: PowerPC,e6500@4 { ++ device_type = "cpu"; ++ reg = <8 9>; ++ next-level-cache = <&L2_2>; ++ }; ++ cpu5: PowerPC,e6500@5 { ++ device_type = "cpu"; ++ reg = <10 11>; ++ next-level-cache = <&L2_2>; ++ }; ++ cpu6: PowerPC,e6500@6 { ++ device_type = "cpu"; ++ reg = <12 13>; ++ next-level-cache = <&L2_2>; ++ }; ++ cpu7: PowerPC,e6500@7 { ++ device_type = "cpu"; ++ reg = <14 15>; ++ next-level-cache = <&L2_2>; ++ }; ++ ++ cpu8: PowerPC,e6500@8 { ++ device_type = "cpu"; ++ reg = <16 17>; ++ next-level-cache = <&L2_3>; ++ }; ++ cpu9: PowerPC,e6500@9 { ++ device_type = "cpu"; ++ reg = <18 19>; ++ next-level-cache = <&L2_3>; ++ }; ++ cpu10: PowerPC,e6500@10 { ++ device_type = "cpu"; ++ reg = <20 21>; ++ next-level-cache = <&L2_3>; ++ }; ++ cpu11: PowerPC,e6500@11 { ++ device_type = "cpu"; ++ reg = <22 23>; ++ next-level-cache = <&L2_3>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/p2020si.dtsi b/arch/powerpc/boot/dts/p2020si.dtsi +index 6def17f..7fcc6f4 100644 +--- a/arch/powerpc/boot/dts/p2020si.dtsi ++++ b/arch/powerpc/boot/dts/p2020si.dtsi +@@ -295,6 +295,8 @@ + interrupt-parent = <&mpic>; + /* Filled in by U-Boot */ + clock-frequency = <0>; ++ // P2020 requires auto-cmd12 ++ sdhci,auto-cmd12; + }; + + crypto@30000 { +diff --git a/arch/powerpc/boot/dts/p2041rdb-usdpaa.dts b/arch/powerpc/boot/dts/p2041rdb-usdpaa.dts +new file mode 100644 +index 0000000..2557614 +--- /dev/null ++++ b/arch/powerpc/boot/dts/p2041rdb-usdpaa.dts +@@ -0,0 +1,110 @@ ++/* ++ * P2041RDB Device Tree Source ++ * ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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/ "p2041rdb.dts" ++ ++/ { ++ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding, ++ * because apps seed these pools with buffers allocated at ++ * run-time. ++ * HOWEVER, the kernel driver requires the buffer-size so ++ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets ++ * things if the base-address is zero (hence the 0xdeadbeef ++ * values). ++ */ ++ bp7: buffer-pool@7 { ++ compatible = "fsl,p2041-bpool", "fsl,bpool"; ++ fsl,bpid = <7>; ++ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>; ++ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>; ++ }; ++ bp8: buffer-pool@8 { ++ compatible = "fsl,p2041-bpool", "fsl,bpool"; ++ fsl,bpid = <8>; ++ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>; ++ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>; ++ }; ++ bp9: buffer-pool@9 { ++ compatible = "fsl,p2041-bpool", "fsl,bpool"; ++ fsl,bpid = <9>; ++ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>; ++ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>; ++ }; ++ ++ fsl,dpaa { ++ ethernet@0 { ++ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init"; ++ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>; ++ fsl,qman-frame-queues-rx = <0x50 1 0x51 1>; ++ fsl,qman-frame-queues-tx = <0x70 1 0x71 1>; ++ }; ++ ethernet@1 { ++ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init"; ++ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>; ++ fsl,qman-frame-queues-rx = <0x52 1 0x53 1>; ++ fsl,qman-frame-queues-tx = <0x72 1 0x73 1>; ++ }; ++ ethernet@2 { ++ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init"; ++ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>; ++ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>; ++ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>; ++ }; ++ ethernet@3 { ++ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init"; ++ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>; ++ fsl,qman-frame-queues-rx = <0x56 1 0x57 1>; ++ fsl,qman-frame-queues-tx = <0x76 1 0x77 1>; ++ }; ++ ethernet@4 { ++ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init"; ++ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>; ++ fsl,qman-frame-queues-rx = <0x58 1 0x59 1>; ++ fsl,qman-frame-queues-tx = <0x78 1 0x79 1>; ++ }; ++ ethernet@5 { ++ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init"; ++ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>; ++ fsl,qman-frame-queues-rx = <0x5a 1 0x5b 1>; ++ fsl,qman-frame-queues-tx = <0x7a 1 0x7b 1>; ++ }; ++ dpa-fman0-oh@1 { ++ compatible = "fsl,dpa-oh"; ++ /* Define frame queues for the OH port*/ ++ /* */ ++ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>; ++ fsl,fman-oh-port = <&fman0_oh1>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/p2041rdb.dts b/arch/powerpc/boot/dts/p2041rdb.dts +index 79b6895..c712717 100644 +--- a/arch/powerpc/boot/dts/p2041rdb.dts ++++ b/arch/powerpc/boot/dts/p2041rdb.dts +@@ -1,7 +1,7 @@ + /* + * P2041RDB Device Tree Source + * +- * Copyright 2011 Freescale Semiconductor Inc. ++ * Copyright 2011-2012 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: +@@ -32,7 +32,7 @@ + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +-/include/ "p2041si.dtsi" ++/include/ "fsl/p2041si-pre.dtsi" + + / { + model = "fsl,P2041RDB"; +@@ -41,6 +41,25 @@ + #size-cells = <2>; + interrupt-parent = <&mpic>; + ++ aliases { ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ ethernet3 = &enet3; ++ ethernet4 = &enet4; ++ ethernet5 = &enet5; ++ phy_rgmii_0 = &phy_rgmii_0; ++ phy_rgmii_1 = &phy_rgmii_1; ++ phy_sgmii_2 = &phy_sgmii_2; ++ phy_sgmii_3 = &phy_sgmii_3; ++ phy_sgmii_4 = &phy_sgmii_4; ++ phy_sgmii_1c = &phy_sgmii_1c; ++ phy_sgmii_1d = &phy_sgmii_1d; ++ phy_sgmii_1e = &phy_sgmii_1e; ++ phy_sgmii_1f = &phy_sgmii_1f; ++ phy_xgmii_2 = &phy_xgmii_2; ++ }; ++ + memory { + device_type = "memory"; + }; +@@ -49,7 +68,17 @@ + ranges = <0x00000000 0xf 0x00000000 0x01008000>; + }; + ++ bportals: bman-portals@ff4000000 { ++ ranges = <0x0 0xf 0xf4000000 0x200000>; ++ }; ++ ++ qportals: qman-portals@ff4200000 { ++ ranges = <0x0 0xf 0xf4200000 0x200000>; ++ }; ++ + soc: soc@ffe000000 { ++ ranges = <0x00000000 0xf 0xfe000000 0x1000000>; ++ reg = <0xf 0xfe000000 0 0x00001000>; + spi@110000 { + flash@0 { + #address-cells = <1>; +@@ -92,6 +121,10 @@ + compatible = "pericom,pt7c4338"; + reg = <0x68>; + }; ++ adt7461@4c { ++ compatible = "adi,adt7461"; ++ reg = <0x4c>; ++ }; + }; + + i2c@118100 { +@@ -104,11 +137,134 @@ + usb1: usb@211000 { + dr_mode = "host"; + }; ++ ++ fman0: fman@400000 { ++ enet0: ethernet@e0000 { ++ tbi-handle = <&tbi0>; ++ phy-handle = <&phy_sgmii_2>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ mdio0: mdio@e1120 { ++ tbi0: tbi-phy@8 { ++ reg = <0x8>; ++ device_type = "tbi-phy"; ++ }; ++ ++ phy_rgmii_0: ethernet-phy@0 { ++ reg = <0x0>; ++ }; ++ phy_rgmii_1: ethernet-phy@1 { ++ reg = <0x1>; ++ }; ++ phy_sgmii_2: ethernet-phy@2 { ++ reg = <0x2>; ++ }; ++ phy_sgmii_3: ethernet-phy@3 { ++ reg = <0x3>; ++ }; ++ phy_sgmii_4: ethernet-phy@4 { ++ reg = <0x4>; ++ }; ++ phy_sgmii_1c: ethernet-phy@1c { ++ reg = <0x1c>; ++ }; ++ phy_sgmii_1d: ethernet-phy@1d { ++ reg = <0x1d>; ++ }; ++ phy_sgmii_1e: ethernet-phy@1e { ++ reg = <0x1e>; ++ }; ++ phy_sgmii_1f: ethernet-phy@1f { ++ reg = <0x1f>; ++ }; ++ }; ++ ++ enet1: ethernet@e2000 { ++ tbi-handle = <&tbi1>; ++ phy-handle = <&phy_sgmii_3>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ mdio@e3120 { ++ tbi1: tbi-phy@8 { ++ reg = <8>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ enet2: ethernet@e4000 { ++ tbi-handle = <&tbi2>; ++ phy-handle = <&phy_sgmii_4>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ mdio@e5120 { ++ tbi2: tbi-phy@8 { ++ reg = <8>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ enet3: ethernet@e6000 { ++ tbi-handle = <&tbi3>; ++ phy-handle = <&phy_rgmii_1>; ++ phy-connection-type = "rgmii"; ++ }; ++ ++ mdio@e7120 { ++ tbi3: tbi-phy@8 { ++ reg = <8>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ enet4: ethernet@e8000 { ++ tbi-handle = <&tbi4>; ++ phy-handle = <&phy_rgmii_0>; ++ phy-connection-type = "rgmii"; ++ }; ++ ++ mdio@e9120 { ++ tbi4: tbi-phy@8 { ++ reg = <8>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ enet5: ethernet@f0000 { ++ /* ++ * phy-handle will be updated by U-Boot to ++ * reflect the actual slot the XAUI card is in. ++ */ ++ phy-handle = <&phy_xgmii_2>; ++ phy-connection-type = "xgmii"; ++ }; ++ ++ mdio@f1000 { ++ /* XAUI card in slot 2 */ ++ phy_xgmii_2: ethernet-phy@0 { ++ reg = <0x0>; ++ }; ++ }; ++ }; ++ }; ++ ++ rio: rapidio@ffe0c0000 { ++ reg = <0xf 0xfe0c0000 0 0x11000>; ++ ++ port1 { ++ ranges = <0 0 0xc 0x20000000 0 0x10000000>; ++ }; ++ port2 { ++ ranges = <0 0 0xc 0x30000000 0 0x10000000>; ++ }; + }; + +- localbus@ffe124000 { ++ lbc: localbus@ffe124000 { + reg = <0xf 0xfe124000 0 0x1000>; +- ranges = <0 0 0xf 0xe8000000 0x08000000>; ++ ranges = <0 0 0xf 0xe8000000 0x08000000 ++ 1 0 0xf 0xffa00000 0x00040000>; + + flash@0,0 { + compatible = "cfi-flash"; +@@ -116,6 +272,44 @@ + bank-width = <2>; + device-width = <2>; + }; ++ ++ nand@1,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,elbc-fcm-nand"; ++ reg = <0x1 0x0 0x40000>; ++ ++ partition@0 { ++ label = "NAND U-Boot Image"; ++ reg = <0x0 0x02000000>; ++ read-only; ++ }; ++ ++ partition@2000000 { ++ label = "NAND Root File System"; ++ reg = <0x02000000 0x10000000>; ++ }; ++ ++ partition@12000000 { ++ label = "NAND Compressed RFS Image"; ++ reg = <0x12000000 0x08000000>; ++ }; ++ ++ partition@1a000000 { ++ label = "NAND Linux Kernel Image"; ++ reg = <0x1a000000 0x04000000>; ++ }; ++ ++ partition@1e000000 { ++ label = "NAND DTB Image"; ++ reg = <0x1e000000 0x01000000>; ++ }; ++ ++ partition@1f000000 { ++ label = "NAND Writable User area"; ++ reg = <0x1f000000 0x01000000>; ++ }; ++ }; + }; + + pci0: pcie@ffe200000 { +@@ -162,4 +356,37 @@ + 0 0x00010000>; + }; + }; ++ ++ fsl,dpaa { ++ compatible = "fsl,p2041-dpaa", "fsl,dpaa"; ++ ++ ethernet@0 { ++ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&enet0>; ++ }; ++ ethernet@1 { ++ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&enet1>; ++ }; ++ ethernet@2 { ++ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&enet2>; ++ }; ++ ethernet@3 { ++ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&enet3>; ++ }; ++ ethernet@4 { ++ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&enet4>; ++ }; ++ ethernet@5 { ++ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&enet5>; ++ }; ++ }; + }; ++ ++/include/ "fsl/p2041si-post.dtsi" ++ ++/include/ "fsl/qoriq-dpaa-res1.dtsi" +diff --git a/arch/powerpc/boot/dts/quanta_lb8.dts b/arch/powerpc/boot/dts/quanta_lb8.dts +new file mode 100644 +index 0000000..44f76fc +--- /dev/null ++++ b/arch/powerpc/boot/dts/quanta_lb8.dts +@@ -0,0 +1,446 @@ ++/* ++ * Quanta Computer LB8 Device Tree Source ++ * ++ * Copyright 2011, Cumulus Networks, LLC ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * IMPORTANT - This file contains the "desired" device-tree as well as a ++ * device-tree the mimics the one embedded in the FASTPATH ++ * u-boot. The desired device-tree is uncommented... mainly ++ * to facilitate memory for when we build a uboot that will ++ * accept an input DTB. The desired device tree is delimited ++ * by QUANTA_FASTPATH_HACK. ++ */ ++ ++/dts-v1/; ++/ { ++ model = "quanta,lb8"; ++ compatible = "quanta,lb8"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ aliases { ++ ethernet0 = &enet0; ++ serial0 = &serial0; ++ pcie0 = &pcie0; ++ fancontrol = &fancontrol; ++ }; ++ ++ chosen { ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x0 0x0>; // Filled by U-Boot ++ }; ++ ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ PowerPC,8548@0 { ++ device_type = "cpu"; ++ reg = <0>; ++ d-cache-line-size = <32>; // 32 bytes ++ i-cache-line-size = <32>; // 32 bytes ++ d-cache-size = <0x8000>; // L1, 32K ++ i-cache-size = <0x8000>; // L1, 32K ++ timebase-frequency = <0>; ++ bus-frequency = <0>; ++ clock-frequency = <0>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++ ++ soc8548@e0000000 { ++ device_type = "soc"; ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ bus-frequency = <0>; // Filled out by uboot. ++ ranges = <0x0000000 0xe0000000 0x00100000>; ++ reg = <0xe0000000 0x00100000>; // CCSRBAR ++ ++ memory-controller@2000 { ++ compatible = "fsl,mpc8548-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupt-parent = <&mpic>; ++ interrupts = <18 2>; ++ }; ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,mpc8548-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x80000>; // L2, 512K ++ interrupt-parent = <&mpic>; ++ interrupts = <16 2>; ++ }; ++ ++ mpic: pic@40000 { ++ interrupt-controller; ++ device_type = "open-pic"; ++ compatible = "chrp,open-pic"; ++ #address-cells = <0>; ++ #interrupt-cells = <2>; ++ built-in; ++ big-endian; ++ clock-frequency = <0>; ++ reg = <0x40000 0x40000>; ++ }; ++ ++ i2c@3000 { ++ device_type = "i2c"; ++ compatible = "fsl-i2c"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x3000 0x100>; ++ cell-index = <0>; ++ interrupt-parent = <&mpic>; ++ interrupts = <43 2>; ++ dfsrr; ++/* power supply status pins, need to determine */ ++ pca9555@24 { ++ compatible = "nxp,pca9555"; ++ reg = <0x24>; ++ }; ++/* power supply status pins, need to determine */ ++ pca9555@25 { ++ compatible = "nxp,pca9555"; ++ reg = <0x25>; ++ }; ++ fancontrol: fan@2-cd { ++ compatible = "on,adt7463"; ++ reg = <0x2c>; ++ }; ++/* unused (on the board, but not connected) ++ fan@2e { ++ compatible = "on,adt7463"; ++ reg = <0x2e>; ++ }; ++*/ ++ config@52 { ++ compatible = "at,24c02"; ++ reg = <0x52>; ++ }; ++ spd@53 { ++ compatible = "at,spd"; ++ reg = <0x53>; ++ }; ++ eeprom@54 { ++ compatible = "at,24c02"; ++ reg = <0x54>; ++ label = "board_eeprom"; ++ read-only; ++ }; ++/* unknown (redundant power supply, likely an at24 type eeprom) ++ unknown@58 { ++ compatible = "cumulus,unknown"; ++ reg = <0x58>; ++ }; ++*/ ++/* unknown (redundant power supply, likely an at24 type eeprom) ++ unknown@59 { ++ compatible = "cumulus,unknown"; ++ reg = <0x59>; ++ }; ++*/ ++ rtc@68 { ++ compatible = "dallas,ds1338"; ++ reg = <0x68>; ++ }; ++ }; ++ ++ i2c@3100 { ++ device_type = "i2c"; ++ compatible = "fsl-i2c"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x3100 0x100>; ++ cell-index = <1>; ++ interrupt-parent = <&mpic>; ++ interrupts = <43 2>; ++ dfsrr; ++/* quanta I2C mux CPLD for SFP+ on ports 1-16 */ ++ quanta-i2cmux@25 { ++ compatible = "cumulus,quanta-i2cmux-16"; ++ reg = <0x25>; ++ }; ++/* quanta I2C mux CPLD for SFP+ on ports 17-32 */ ++ quanta-i2cmux@26 { ++ compatible = "cumulus,quanta-i2cmux-16"; ++ reg = <0x26>; ++ }; ++/* quanta I2C mux CPLD for SFP+ on ports 33-48 */ ++ quanta-i2cmux@27 { ++ compatible = "cumulus,quanta-i2cmux-16"; ++ reg = <0x27>; ++ }; ++ }; ++ ++ serial0: serial@4500 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ cell-index = <0>; ++ clock-frequency = <0>; ++ interrupt-parent = <&mpic>; ++ interrupts = <42 2>; ++ reg = <0x4500 0x100>; ++ }; ++ ++ enet0: ethernet@24000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <0>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ interrupt-parent = <&mpic>; ++ interrupts = <29 2 30 2 34 2>; ++ reg = <0x00024000 0x00001000>; ++ phy-handle = <&phy1>; ++ }; ++ ++ mdio@24520 { ++ device_type = "mdio"; ++ compatible = "fsl,gianfar-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x00024520 0x00000020>; ++ phy1: ethernet-phy@1 { ++ device_type = "ethernet-phy"; ++ reg = <1>; ++ }; ++ tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ global-utilities@e0000 { //global utilities block ++ compatible = "fsl,mpc8548-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++/* ++ crypto@30000 { ++ device_type = "cruypto"; ++ compatible = "fsl,sec2.1, talitos", "fsl,sec2.0, talitos"; ++ model = "SEC3"; ++ reg = <0x30000 0x10000>; ++ interrupts = <45 2>; ++ interrupt-parent = <&mpic>; ++ fsl,num-channels = <4>; ++ fsl,channel-fifo-len = <24>; ++ fsl,exec-units-mask = <0xfe>; ++ fsl,descriptor-types-mask = <0x12b0ebf>; ++ }; ++*/ ++/* Trident does not work with MSI ++ msi@41600 { ++ compatible = "fsl,mpic-msi"; ++ reg = <0x41600 0x80>; ++ msi-available-ranges = <0 0x100>; ++ interrupts = < ++ 0xe0 0 ++ 0xe1 0 ++ 0xe2 0 ++ 0xe3 0 ++ 0xe4 0 ++ 0xe5 0 ++ 0xe6 0 ++ 0xe7 0>; ++ interrupt-parent = <&mpic>; ++ }; ++*/ ++/* ++ dma@21300 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8548-dma", "fsl,eloplus-dma"; ++ reg = <0x21300 0x4>; ++ ranges = <0x0 0x21100 0x200>; ++ cell-index = <0>; ++ dma-channel@0 { ++ compatible = "fsl,mpc8548-dma-channel", ++ "fsl,eloplus-dma-channel"; ++ reg = <0x0 0x80>; ++ cell-index = <0>; ++ interrupt-parent = <&mpic>; ++ interrupts = <20 2>; ++ }; ++ dma-channel@80 { ++ compatible = "fsl,mpc8548-dma-channel", ++ "fsl,eloplus-dma-channel"; ++ reg = <0x80 0x80>; ++ cell-index = <1>; ++ interrupt-parent = <&mpic>; ++ interrupts = <21 2>; ++ }; ++ dma-channel@100 { ++ compatible = "fsl,mpc8548-dma-channel", ++ "fsl,eloplus-dma-channel"; ++ reg = <0x100 0x80>; ++ cell-index = <2>; ++ interrupt-parent = <&mpic>; ++ interrupts = <22 2>; ++ }; ++ dma-channel@180 { ++ compatible = "fsl,mpc8548-dma-channel", ++ "fsl,eloplus-dma-channel"; ++ reg = <0x180 0x80>; ++ cell-index = <3>; ++ interrupt-parent = <&mpic>; ++ interrupts = <23 2>; ++ }; ++ }; ++*/ ++/* NOT USED ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <10>; ++ }; ++*/ ++/* ++ ecm@1000 { ++ compatible = "fsl,mpc8544-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <17 2>; ++ interrupt-parent = <&mpic>; ++ }; ++*/ ++ }; ++/* ++ pci0: pci@e0008000 { ++ device_type = "pci"; ++ compatible = "fsl,mpc8540-pci"; ++ clock-frequency = <66666666>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ reg = <0xe0008000 0x1000>; ++ bus-range = <0 0>; ++ ranges = < ++ 0x2000000 0x0 0x80000000 0x80000000 0x0 0x10000000 ++ 0x1000000 0x0 0x00000000 0xe2000000 0x0 0x00800000 ++ >; ++ interrupt-parent = <&mpic>; ++ #interrupt-cells = <1>; ++ interrupts = <24 2>; ++ interrupt-map-mask = < ++ 0x0000f800 0x00000000 0x00000000 0x00000007 ++ >; ++ interrupt-map = < ++ // IDSEL 0x12 Slot 1 ++ 0x00009000 0x00000000 0x00000000 0x00000001 &mpic 0 1 ++ >; ++ }; ++*/ ++ pcie0: pcie@e000a000 { ++ device_type = "pci"; ++ compatible = "fsl,mpc8548-pcie"; ++ clock-frequency = <33333333>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ reg = <0xe000a000 0x00001000>; ++ bus-range = <0 255>; ++ ranges = < ++ 0x02000000 0x00000000 0xa0000000 0xa0000000 0x00000000 0x20000000 ++ 0x01000000 0x00000000 0x00000000 0xe3000000 0x00000000 0x00100000 ++ >; ++ interrupt-parent = <&mpic>; ++ #interrupt-cells = <1>; ++ interrupts = <10 2>; ++ interrupt-map-mask = < ++ 0x0000f800 0x00000000 0x00000000 0x00000007 ++ >; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0x00000000 0x00000000 0x00000000 0x00000001 &mpic 0 1 ++ 0x00000000 0x00000000 0x00000000 0x00000002 &mpic 1 1 ++ 0x00000000 0x00000000 0x00000000 0x00000003 &mpic 2 1 ++ 0x00000000 0x00000000 0x00000000 0x00000004 &mpic 3 1 ++ >; ++ }; ++ ++ localbus@0xe0005000 { ++ compatible = "fsl,pq3-localbus", "simple-bus"; ++ interrupt-parent = <&mpic>; ++ interrupts = <19 2>; ++ #address-cells = <2>; ++ #size-cells = <1>; ++ reg = <0xe0005000 0x1000>; ++ ranges = < ++ 0 0 0xfe000000 0x02000000 ++ 1 0 0xfc000000 0x02000000 ++ 2 0 0xf0000000 0x00020000 ++ 3 0 0xf0010000 0x00010000 ++ 4 0 0xf2000000 0x00100000 ++ 5 0 0xe0000000 0x00000002 ++ >; ++ ++ flash@0,0 { ++ compatible = "cfi-flash"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0 0 0x02000000>; ++ bank-width = <2>; ++ device-width = <2>; ++ partition@0 { ++ label = "system image"; ++ reg = <0x00000000 0x01f80000>; ++ }; ++ partition@2 { ++ label = "uboot-env"; ++ reg = <0x01f80000 0x00020000>; ++ env_size = <0x2000>; ++ }; ++ partition@3 { ++ label = "uboot"; ++ reg = <0x01fa0000 0x00060000>; ++ }; ++ }; ++ ++ flash@1,0 { ++ compatible = "cfi-flash"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <1 0 0x02000000>; ++ bank-width = <2>; ++ device-width = <2>; ++ partition@0 { ++ label = "/var"; ++ reg = <0x00000000 0x01c00000>; ++ }; ++ partition@1 { ++ label = "/mnt/persist"; ++ reg = <0x01c00000 0x00400000>; ++ }; ++ }; ++/* ++ cfcard@2 { ++ compatible = "qci-ide"; ++ device_type = "ide"; ++ reg = < ++ 2 0 0x00020000 ++ 4 0 0x00100000 ++ >; ++ ioport_shift = <1>; ++ reg-shift = <1>; ++ #interrupt-cells = <1>; ++ interrupts = <2 2>; ++ interrupt-parent = <&mpic>; ++ }; ++*/ ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/quanta_lb9.dts b/arch/powerpc/boot/dts/quanta_lb9.dts +new file mode 100644 +index 0000000..45d32cf +--- /dev/null ++++ b/arch/powerpc/boot/dts/quanta_lb9.dts +@@ -0,0 +1,511 @@ ++/* ++ * Quanta LB9 Device Tree Source ++ * ++ * Copyright 2013 Cumulus Networks, Inc. ++ * Copyright 2006, 2008 Freescale Semiconductor 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. ++ */ ++ ++/dts-v1/; ++ ++/ { ++ model = "quanta,lb9"; ++ compatible = "quanta,lb9"; ++ reset-gpio = <&cpm_pio_a 24 1>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ aliases { ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ serial0 = &serial0; ++ serial1 = &serial1; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,8541@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ d-cache-line-size = <32>; // 32 bytes ++ i-cache-line-size = <32>; // 32 bytes ++ d-cache-size = <0x8000>; // L1, 32K ++ i-cache-size = <0x8000>; // L1, 32K ++ timebase-frequency = <0>; // 33 MHz, from uboot ++ bus-frequency = <0>; // 166 MHz ++ clock-frequency = <0>; // 825 MHz, from uboot ++ next-level-cache = <&L2>; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ }; ++ ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ ++ mass_storage { ++ device = "sda"; ++ }; ++ ++ soc8541@e0000000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "simple-bus"; ++ ranges = <0x0 0xe0000000 0x100000>; ++ bus-frequency = <0>; ++ ++ ecm-law@0 { ++ compatible = "fsl,ecm-law"; ++ reg = <0x0 0x1000>; ++ fsl,num-laws = <8>; ++ }; ++ ++ ecm@1000 { ++ compatible = "fsl,mpc8541-ecm", "fsl,ecm"; ++ reg = <0x1000 0x1000>; ++ interrupts = <17 2>; ++ interrupt-parent = <&mpic>; ++ }; ++ ++ memory-controller@2000 { ++ compatible = "fsl,mpc8541-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupt-parent = <&mpic>; ++ interrupts = <18 2>; ++ }; ++ ++ L2: l2-cache-controller@20000 { ++ compatible = "fsl,mpc8541-l2-cache-controller"; ++ reg = <0x20000 0x1000>; ++ cache-line-size = <32>; // 32 bytes ++ cache-size = <0x40000>; // L2, 256K ++ interrupt-parent = <&mpic>; ++ interrupts = <16 2>; ++ }; ++ ++ I2C0: i2c@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <43 2>; ++ interrupt-parent = <&mpic>; ++ fsl,preserve-clocking; ++ ++ rtc@68 { ++ compatible = "dallas,ds1339"; ++ reg = <0x68>; ++ }; ++ ++ board_eeprom@53 { ++ compatible = "at,24c02"; ++ reg = <0x53>; ++ label = "board_eeprom"; ++ }; ++ ++ spd@57 { ++ compatible = "at,spd"; ++ reg = <0x57>; ++ }; ++ ++ mux@70 { ++ compatible = "ti,pca9548"; ++ reg = <0x70>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ // 10G SFP+ 0 ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port49"; ++ }; ++ }; ++ // 10G SFP+ 1 ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port50"; ++ }; ++ }; ++ // 10G SFP+ 2 ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port51"; ++ }; ++ }; ++ // 10G SFP+ 3 ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port52"; ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ fancontrol-fb@2C { ++ compatible = "on,adt7470"; ++ reg = <0x2C>; ++ label = "temp fan 1"; ++ disable-smbus-timeout; ++ }; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ fancontrol-fb@2F { ++ compatible = "on,adt7470"; ++ reg = <0x2F>; ++ label = "temp fan 2"; ++ disable-smbus-timeout; ++ }; ++ }; ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ pmbus-psu1@58 { ++ compatible = "on,ps2471"; ++ reg = <0x58>; ++ label = "PSU1 PMBUS"; ++ disable-smbus-timeout; ++ }; ++ }; ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ pmbus-psu2@59 { ++ compatible = "on,ps2471"; ++ reg = <0x59>; ++ label = "PSU2 PMBUS"; ++ disable-smbus-timeout; ++ }; ++ }; ++ }; ++ ++ pca9555@24 { ++ compatible = "nxp,pca9555"; ++ reg = <0x24>; ++ label = "PSU Status 1"; ++ }; ++ pca9555@25 { ++ compatible = "nxp,pca9555"; ++ reg = <0x25>; ++ label = "PSU Status 2"; ++ }; ++ pca9555@20 { ++ compatible = "nxp,pca9555"; ++ reg = <0x20>; ++ label = "8727"; ++ }; ++ }; ++ ++ dma@21300 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8541-dma", "fsl,eloplus-dma"; ++ reg = <0x21300 0x4>; ++ ranges = <0x0 0x21100 0x200>; ++ cell-index = <0>; ++ dma-channel@0 { ++ compatible = "fsl,mpc8541-dma-channel", ++ "fsl,eloplus-dma-channel"; ++ reg = <0x0 0x80>; ++ cell-index = <0>; ++ interrupt-parent = <&mpic>; ++ interrupts = <20 2>; ++ }; ++ dma-channel@80 { ++ compatible = "fsl,mpc8541-dma-channel", ++ "fsl,eloplus-dma-channel"; ++ reg = <0x80 0x80>; ++ cell-index = <1>; ++ interrupt-parent = <&mpic>; ++ interrupts = <21 2>; ++ }; ++ dma-channel@100 { ++ compatible = "fsl,mpc8541-dma-channel", ++ "fsl,eloplus-dma-channel"; ++ reg = <0x100 0x80>; ++ cell-index = <2>; ++ interrupt-parent = <&mpic>; ++ interrupts = <22 2>; ++ }; ++ dma-channel@180 { ++ compatible = "fsl,mpc8541-dma-channel", ++ "fsl,eloplus-dma-channel"; ++ reg = <0x180 0x80>; ++ cell-index = <3>; ++ interrupt-parent = <&mpic>; ++ interrupts = <23 2>; ++ }; ++ }; ++ ++ enet0: ethernet@24000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <0>; ++ device_type = "network"; ++ model = "TSEC"; ++ compatible = "gianfar"; ++ reg = <0x24000 0x1000>; ++ ranges = <0x0 0x24000 0x1000>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ interrupts = <29 2 30 2 34 2>; ++ interrupt-parent = <&mpic>; ++ phy-handle = <&phy0>; ++ ++ mdio@520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x520 0x20>; ++ ++ phy0: ethernet-phy@0 { ++ reg = <0x0>; ++ interrupt-parent = <&mpic>; ++ interrupts = <9 1>; ++ device_type = "ethernet-phy"; ++ }; ++ }; ++ }; ++ ++ enet1: ethernet@25000 { ++ status = "disabled"; ++ }; ++ ++ serial0: serial@4500 { ++ cell-index = <0>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4500 0x100>; ++ clock-frequency = <0>; ++ interrupts = <42 2>; ++ interrupt-parent = <&mpic>; ++ }; ++ ++ serial1: serial@4600 { ++ status = "disabled"; ++ cell-index = <1>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4600 0x100>; ++ clock-frequency = <0>; ++ interrupts = <42 2>; ++ interrupt-parent = <&mpic>; ++ }; ++ ++ crypto@30000 { ++ compatible = "fsl,sec2.0"; ++ reg = <0x30000 0x10000>; ++ interrupts = <45 2>; ++ interrupt-parent = <&mpic>; ++ fsl,num-channels = <4>; ++ fsl,channel-fifo-len = <24>; ++ fsl,exec-units-mask = <0x7e>; ++ fsl,descriptor-types-mask = <0x01010ebf>; ++ }; ++ ++ mpic: pic@40000 { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <2>; ++ reg = <0x40000 0x40000>; ++ compatible = "chrp,open-pic"; ++ device_type = "open-pic"; ++ }; ++ ++ cpm@919c0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8541-cpm", "fsl,cpm2"; ++ reg = <0x919c0 0x30>; ++ ranges; ++ ++ muram@80000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x80000 0x10000>; ++ ++ data@0 { ++ compatible = "fsl,cpm-muram-data"; ++ reg = <0x0 0x2000 0x9000 0x1000>; ++ }; ++ }; ++ ++ brg@919f0 { ++ compatible = "fsl,mpc8541-brg", ++ "fsl,cpm2-brg", ++ "fsl,cpm-brg"; ++ reg = <0x919f0 0x10 0x915f0 0x10>; ++ }; ++ ++ cpmpic: pic@90c00 { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <2>; ++ interrupts = <46 2>; ++ interrupt-parent = <&mpic>; ++ reg = <0x90c00 0x80>; ++ compatible = "fsl,mpc8541-cpm-pic", "fsl,cpm2-pic"; ++ }; ++ }; ++ ++ cpm_pio_a: gpio-controller@90d00 { ++ #gpio-cells = <2>; ++ compatible = "fsl,cpm2-pario-bank"; ++ reg = <0x90d00 0x14>; ++ gpio-controller; ++ }; ++ ++ cpm_pio_b: gpio-controller@90d20 { ++ #gpio-cells = <2>; ++ compatible = "fsl,cpm2-pario-bank"; ++ reg = <0x90d20 0x14>; ++ gpio-controller; ++ }; ++ ++ cpm_pio_c: gpio-controller@90d40 { ++ #gpio-cells = <2>; ++ compatible = "fsl,cpm2-pario-bank"; ++ reg = <0x90d40 0x14>; ++ gpio-controller; ++ }; ++ ++ cpm_pio_d: gpio-controller@90d60 { ++ #gpio-cells = <2>; ++ compatible = "fsl,cpm2-pario-bank"; ++ reg = <0x90d60 0x14>; ++ gpio-controller; ++ }; ++ }; ++ ++ pci0: pci@e0008000 { ++ interrupt-map-mask = <0x1f800 0x0 0x0 0x7>; ++ interrupt-map = <0x9000 0x0 0x0 0x1 &mpic 0x3 0x1>; ++ interrupt-parent = <&mpic>; ++ interrupts = <24 2>; ++ bus-range = <0 0>; ++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000 ++ 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>; ++ clock-frequency = <66666666>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ reg = <0xe0008000 0x1000>; ++ compatible = "fsl,mpc8540-pci"; ++ device_type = "pci"; ++ }; ++ ++ pci1: pci@e0009000 { ++ status = "disabled"; ++ }; ++ ++ localbus@e0005000 { ++ #address-cells = <0x2>; ++ #size-cells = <0x1>; ++ compatible = "fsl,mpc8541-localbus", "fsl,pq2-localbus", "simple-bus"; ++ reg = <0xe0005000 0x1000>; ++ ranges = <0x0 0x0 0xfe000000 0x2000000 ++ 0x1 0x0 0xfc000000 0x2000000 ++ 0x2 0x0 0xf0010000 0x10000 ++ 0x4 0x0 0xf2000000 0x100000 ++ 0x5 0x0 0xf0000000 0x10000>; ++ interrupt-parent = <&mpic>; ++ interrupts = <19 2>; ++ ++ nor@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x02000000>; ++ bank-width = <2>; ++ partition@0 { ++ /* Entire flash minus (u-boot + onie) */ ++ reg = <0x00000000 0x01b60000>; ++ label = "open"; ++ }; ++ partition@1 { ++ /* 4MB onie */ ++ reg = <0x01b60000 0x00400000>; ++ label = "onie"; ++ }; ++ partition@2 { ++ /* 128KB, 1 sector */ ++ reg = <0x01f60000 0x00020000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@3 { ++ /* 512KB u-boot */ ++ reg = <0x01f80000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ ++ nor@1 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x1 0x0 0x02000000>; ++ bank-width = <2>; ++ partition@0 { ++ /* Entire 32MB */ ++ reg = <0x00000000 0x02000000>; ++ label = "open2"; ++ }; ++ }; ++ ++ cfcard@1 { ++ compatible = "ata-generic"; ++ device_type = "ide"; ++ reg = <0x5 0x0 0x10000 ++ 0x2 0x0 0x10000>; ++ port-width = <4>; ++ port-bswap; ++ /* XXX - broken at the moment, use poll mode ++ #interrupt-cells = <0x1>; ++ interrupts = <20 2>; ++ interrupt-parent = <&mpic>; ++ */ ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/quanta_ly2.dts b/arch/powerpc/boot/dts/quanta_ly2.dts +new file mode 100644 +index 0000000..dd6cd8e +--- /dev/null ++++ b/arch/powerpc/boot/dts/quanta_ly2.dts +@@ -0,0 +1,859 @@ ++/* ++ * Cumulus P2020 Device Tree Source ++ * ++ * Copyright 2012 Cumulus Networks, 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/ "p2020si.dtsi" ++ ++/ { ++ model = "quanta,ly2"; ++ compatible = "quanta,ly2"; ++ ++ aliases { ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ serial0 = &serial0; ++ serial1 = &serial1; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ }; ++ ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ ++ mass_storage { ++ device = "mmcblk0"; ++ }; ++ ++ localbus@ffe05000 { ++ compatible = "fsl,elbc", "simple-bus"; ++ ranges = <0x0 0x0 0x0 0xee000000 0x02000000 ++ 0x1 0x0 0x0 0xec000000 0x02000000>; ++ ++ nor@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x02000000>; ++ bank-width = <2>; ++ partition@0 { ++ /* Entire flash minus (u-boot + onie) */ ++ reg = <0x00000000 0x01b60000>; ++ label = "open"; ++ }; ++ partition@1 { ++ /* 4MB onie */ ++ reg = <0x01b60000 0x00400000>; ++ label = "onie"; ++ }; ++ partition@2 { ++ /* 128KB, 1 sector */ ++ reg = <0x01f60000 0x00020000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@3 { ++ /* 512KB u-boot */ ++ reg = <0x01f80000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ ++ nor@1,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x1 0x0 0x02000000>; ++ bank-width = <2>; ++ partition@0 { ++ reg = <0x00000000 0x02000000>; ++ label = "not-used"; ++ }; ++ }; ++ }; ++ ++ soc@ffe00000 { ++ I2C0: i2c@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ fsl,preserve-clocking; ++ rtc@68 { ++ compatible = "dallas,ds1339"; ++ reg = <0x68>; ++ }; ++ ++ mux@71 { ++ compatible = "ti,pca9546"; ++ reg = <0x71>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* ++ ** The eeprom utilities look for a label that ++ ** ends with "_eeprom". ++ */ ++ board_eeprom@54 { ++ compatible = "at,24c02"; ++ reg = <0x54>; ++ label = "board_eeprom"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Cypress PSOC fan and temp controller */ ++ cypsoc: psoc@2e { ++ compatible = "CY8C3245"; ++ reg = <0x2e>; ++ label = "Cypress PSOC"; ++ }; ++ }; ++ }; ++ ++ mux@75 { ++ compatible = "ti,pca9546"; ++ reg = <0x75>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ psu1: psu@58 { ++ compatible = "at,24c02"; ++ reg = <0x58>; ++ label = "Redundant PSU 1"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ psu2: psu@59 { ++ compatible = "at,24c02"; ++ reg = <0x59>; ++ label = "Redundant PSU 2"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ pca9555@24 { ++ compatible = "nxp,pca9555"; ++ reg = <0x24>; ++ label = "PSU Status 1"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ pca9555@25 { ++ compatible = "nxp,pca9555"; ++ reg = <0x25>; ++ label = "PSU Status 2"; ++ }; ++ }; ++ }; ++ }; ++ ++ I2C1: i2c@3100 { ++ device_type = "i2c"; ++ compatible = "fsl-i2c"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x3100 0x100>; ++ cell-index = <1>; ++ interrupt-parent = <&mpic>; ++ interrupts = <43 2>; ++ fsl,preserve-clocking; ++/* quanta I2C mux CPLD for SFP+ on ports 1-16 */ ++ mux@25 { ++ compatible = "cumulus,quanta-i2cmux-16"; ++ reg = <0x25>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ // SFP+ 1 ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port1"; ++ }; ++ }; ++ // SFP+ 2 ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port2"; ++ }; ++ }; ++ // SFP+ 3 ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port3"; ++ }; ++ }; ++ // SFP+ 4 ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port4"; ++ }; ++ }; ++ // SFP+ 5 ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port5"; ++ }; ++ }; ++ // SFP+ 6 ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port6"; ++ }; ++ }; ++ // SFP+ 7 ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port7"; ++ }; ++ }; ++ // SFP+ 8 ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port8"; ++ }; ++ }; ++ // SFP+ 9 ++ i2c@8 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <8>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port9"; ++ }; ++ }; ++ // SFP+ 10 ++ i2c@9 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <9>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port10"; ++ }; ++ }; ++ // SFP+ 11 ++ i2c@10 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <10>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port11"; ++ }; ++ }; ++ // SFP+ 12 ++ i2c@11 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <11>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port12"; ++ }; ++ }; ++ // SFP+ 13 ++ i2c@12 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <12>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port13"; ++ }; ++ }; ++ // SFP+ 14 ++ i2c@13 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <13>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port14"; ++ }; ++ }; ++ // SFP+ 15 ++ i2c@14 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <14>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port15"; ++ }; ++ }; ++ // SFP+ 16 ++ i2c@15 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <15>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port16"; ++ }; ++ }; ++ }; ++/* quanta I2C mux CPLD for SFP+ on ports 17-32 */ ++ mux@26 { ++ compatible = "cumulus,quanta-i2cmux-16"; ++ reg = <0x26>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ // SFP+ 17 ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port17"; ++ }; ++ }; ++ // SFP+ 18 ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port18"; ++ }; ++ }; ++ // SFP+ 19 ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port19"; ++ }; ++ }; ++ // SFP+ 20 ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port20"; ++ }; ++ }; ++ // SFP+ 21 ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port21"; ++ }; ++ }; ++ // SFP+ 22 ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port22"; ++ }; ++ }; ++ // SFP+ 23 ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port23"; ++ }; ++ }; ++ // SFP+ 24 ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port24"; ++ }; ++ }; ++ // SFP+ 25 ++ i2c@8 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <8>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port25"; ++ }; ++ }; ++ // SFP+ 26 ++ i2c@9 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <9>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port26"; ++ }; ++ }; ++ // SFP+ 27 ++ i2c@10 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <10>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port27"; ++ }; ++ }; ++ // SFP+ 28 ++ i2c@11 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <11>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port28"; ++ }; ++ }; ++ // SFP+ 29 ++ i2c@12 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <12>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port29"; ++ }; ++ }; ++ // SFP+ 30 ++ i2c@13 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <13>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port30"; ++ }; ++ }; ++ // SFP+ 31 ++ i2c@14 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <14>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port31"; ++ }; ++ }; ++ // SFP+ 32 ++ i2c@15 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <15>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port32"; ++ }; ++ }; ++ }; ++/* quanta I2C mux CPLD for SFP+ on ports 33-48 */ ++ mux@27 { ++ compatible = "cumulus,quanta-i2cmux-16"; ++ reg = <0x27>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ // SFP+ 33 ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port33"; ++ }; ++ }; ++ // SFP+ 34 ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port34"; ++ }; ++ }; ++ // SFP+ 35 ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port35"; ++ }; ++ }; ++ // SFP+ 36 ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port36"; ++ }; ++ }; ++ // SFP+ 37 ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port37"; ++ }; ++ }; ++ // SFP+ 38 ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port38"; ++ }; ++ }; ++ // SFP+ 39 ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port39"; ++ }; ++ }; ++ // SFP+ 40 ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port40"; ++ }; ++ }; ++ // SFP+ 41 ++ i2c@8 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <8>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port41"; ++ }; ++ }; ++ // SFP+ 42 ++ i2c@9 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <9>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port42"; ++ }; ++ }; ++ // SFP+ 43 ++ i2c@10 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <10>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port43"; ++ }; ++ }; ++ // SFP+ 44 ++ i2c@11 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <11>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port44"; ++ }; ++ }; ++ // SFP+ 45 ++ i2c@12 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <12>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port45"; ++ }; ++ }; ++ // SFP+ 46 ++ i2c@13 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <13>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port46"; ++ }; ++ }; ++ // SFP+ 47 ++ i2c@14 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <14>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port47"; ++ }; ++ }; ++ // SFP+ 48 ++ i2c@15 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <15>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port48"; ++ }; ++ }; ++ }; ++ ++ mux@73 { ++ compatible = "ti,pca9546"; ++ reg = <0x73>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ // QSFP+ 1 ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port49"; ++ }; ++ }; ++ // QSFP+ 2 ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port50"; ++ }; ++ }; ++ // QSFP+ 3 ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port51"; ++ }; ++ }; ++ // QSFP+ 4 ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port52"; ++ }; ++ }; ++ }; ++ }; ++ ++ usb@22000 { ++ status = "disabled"; ++ }; ++ ++ mdio@24520 { ++ phy0: ethernet-phy@1 { ++ interrupt-parent = <&mpic>; ++ interrupts = <3 1>; ++ reg = <0x1>; ++ }; ++ }; ++ ++ enet0: ethernet@24000 { ++ phy-handle = <&phy0>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ enet1: ethernet@25000 { ++ status = "disabled"; ++ }; ++ ++ enet2: ethernet@26000 { ++ status = "disabled"; ++ }; ++ }; ++ ++ pci0: pcie@ffe08000 { ++ status = "disabled"; ++ }; ++ ++ pci1: pcie@ffe09000 { ++ status = "disabled"; ++ }; ++ ++ pci2: pcie@ffe0a000 { ++ ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 ++ >; ++ ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0xc0000000 ++ 0x2000000 0x0 0xc0000000 ++ 0x0 0x20000000 ++ ++ 0x1000000 0x0 0x0 ++ 0x1000000 0x0 0x0 ++ 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/quanta_ly2r.dts b/arch/powerpc/boot/dts/quanta_ly2r.dts +new file mode 100644 +index 0000000..9cc1040 +--- /dev/null ++++ b/arch/powerpc/boot/dts/quanta_ly2r.dts +@@ -0,0 +1,805 @@ ++/* ++ * Quanta LY2R Device Tree Source ++ * ++ * Copyright 2014 Cumulus Networks, 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/ "p2020si.dtsi" ++ ++/ { ++ model = "quanta,ly2r"; ++ compatible = "quanta,ly2r"; ++ ++ aliases { ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ ethernet2 = &enet2; ++ serial0 = &serial0; ++ serial1 = &serial1; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ }; ++ ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ ++ mass_storage { ++ device = "mmcblk0"; ++ }; ++ ++ localbus@ffe05000 { ++ compatible = "fsl,elbc", "simple-bus"; ++ ranges = <0x0 0x0 0x0 0xec000000 0x04000000 ++ 0x1 0x0 0x0 0xe8000000 0x04000000>; ++ ++ nor@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x04000000>; ++ bank-width = <2>; ++ partition@0 { ++ /* Entire flash minus (u-boot + onie) */ ++ reg = <0x00000000 0x03b60000>; ++ label = "open"; ++ }; ++ partition@1 { ++ /* 4MB onie */ ++ reg = <0x03b60000 0x00400000>; ++ label = "onie"; ++ }; ++ partition@2 { ++ /* 128KB, 1 sector */ ++ reg = <0x03f60000 0x00020000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@3 { ++ /* 512KB u-boot */ ++ reg = <0x03f80000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ ++ nor@1,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x1 0x0 0x04000000>; ++ bank-width = <2>; ++ partition@0 { ++ reg = <0x00000000 0x04000000>; ++ label = "open2"; ++ }; ++ }; ++ }; ++ ++ soc@ffe00000 { ++ i2c@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <43 2>; ++ interrupt-parent = <&mpic>; ++ fsl,preserve-clocking; ++ ++ rtc@68 { ++ compatible = "dallas,ds1338"; ++ reg = <0x68>; ++ }; ++ board_eeprom@54 { ++ compatible = "at,24c02"; ++ reg = <0x54>; ++ label = "board_eeprom"; ++ }; ++ /* Cypress PSOC fan and temp controller */ ++ cypsoc: psoc@2e { ++ compatible = "CY8C3245"; ++ reg = <0x2e>; ++ label = "Cypress PSOC"; ++ }; ++ pca9555@26 { ++ compatible = "nxp,pca9555"; ++ reg = <0x26>; ++ label = "Fan Status and CPLD"; ++ }; ++ mux@75 { ++ compatible = "ti,pca9546"; ++ reg = <0x75>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ psu1: psu@58 { ++ compatible = "at,24c02"; ++ reg = <0x58>; ++ label = "Redundant PSU 1"; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ psu2: psu@59 { ++ compatible = "at,24c02"; ++ reg = <0x59>; ++ label = "Redundant PSU 2"; ++ }; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ pca9555@24 { ++ compatible = "nxp,pca9555"; ++ reg = <0x24>; ++ label = "PSU Control 1"; ++ }; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ pca9555@25 { ++ compatible = "nxp,pca9555"; ++ reg = <0x25>; ++ label = "PSU Control 2"; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@3100 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <1>; ++ compatible = "fsl-i2c"; ++ reg = <0x3100 0x100>; ++ interrupts = <43 2>; ++ interrupt-parent = <&mpic>; ++ fsl,preserve-clocking; ++ pca9698@21 { ++ compatible = "nxp,pca9698"; ++ reg = <0x21>; ++ label = "QSFP+ I/O Expander"; ++ }; ++ mux@72 { ++ compatible = "ti,pca9546"; ++ reg = <0x72>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ mux@38 { ++ compatible = "cumulus,quanta-i2cmux-32"; ++ reg = <0x38>; ++ label = "CPLD 1, I2C expander SFP+ 1-32"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ // SFP+ 1 ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port1"; ++ }; ++ }; ++ i2c@1{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port2"; ++ }; ++ }; ++ i2c@2{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port3"; ++ }; ++ }; ++ i2c@3{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port4"; ++ }; ++ }; ++ i2c@4{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port5"; ++ }; ++ }; ++ i2c@5{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port6"; ++ }; ++ }; ++ i2c@6{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port7"; ++ }; ++ }; ++ i2c@7{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port8"; ++ }; ++ }; ++ i2c@8{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <8>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port9"; ++ }; ++ }; ++ i2c@9{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <9>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port10"; ++ }; ++ }; ++ i2c@10{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <10>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port11"; ++ }; ++ }; ++ i2c@11{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <11>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port12"; ++ }; ++ }; ++ i2c@12{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <12>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port13"; ++ }; ++ }; ++ i2c@13{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <13>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port14"; ++ }; ++ }; ++ i2c@14{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <14>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port15"; ++ }; ++ }; ++ i2c@15{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <15>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port16"; ++ }; ++ }; ++ i2c@16{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <16>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port17"; ++ }; ++ }; ++ i2c@17{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <17>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port18"; ++ }; ++ }; ++ i2c@18{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <18>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port19"; ++ }; ++ }; ++ i2c@19{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <19>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port20"; ++ }; ++ }; ++ i2c@20{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <20>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port21"; ++ }; ++ }; ++ i2c@21{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <21>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port22"; ++ }; ++ }; ++ i2c@22{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <22>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port23"; ++ }; ++ }; ++ i2c@23{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <23>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port24"; ++ }; ++ }; ++ i2c@24{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <24>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port25"; ++ }; ++ }; ++ i2c@25{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <25>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port26"; ++ }; ++ }; ++ i2c@26{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <26>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port27"; ++ }; ++ }; ++ i2c@27{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <27>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port28"; ++ }; ++ }; ++ i2c@28{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <28>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port29"; ++ }; ++ }; ++ i2c@29{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <29>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port30"; ++ }; ++ }; ++ i2c@30{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <30>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port31"; ++ }; ++ }; ++ i2c@31{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <31>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port32"; ++ }; ++ }; ++ }; ++ mux@39 { ++ compatible = "cumulus,quanta-i2cmux-32"; ++ reg = <0x39>; ++ label = "CPLD 2, I2C expander SFP+ 33-48"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ // SFP+ 33 ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port33"; ++ }; ++ }; ++ i2c@1{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port34"; ++ }; ++ }; ++ i2c@2{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port35"; ++ }; ++ }; ++ i2c@3{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port36"; ++ }; ++ }; ++ i2c@4{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port37"; ++ }; ++ }; ++ i2c@5{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port38"; ++ }; ++ }; ++ i2c@6{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port39"; ++ }; ++ }; ++ i2c@7{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port40"; ++ }; ++ }; ++ i2c@8{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <8>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port41"; ++ }; ++ }; ++ i2c@9{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <9>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port42"; ++ }; ++ }; ++ i2c@10{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <10>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port43"; ++ }; ++ }; ++ i2c@11{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <11>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port44"; ++ }; ++ }; ++ i2c@12{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <12>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port45"; ++ }; ++ }; ++ i2c@13{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <13>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port46"; ++ }; ++ }; ++ i2c@14{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <14>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port47"; ++ }; ++ }; ++ i2c@15{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <15>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port48"; ++ }; ++ }; ++ i2c@16{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <16>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port49"; ++ }; ++ }; ++ i2c@17{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <17>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port50"; ++ }; ++ }; ++ i2c@18{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <18>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port51"; ++ }; ++ }; ++ i2c@19{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <19>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port52"; ++ }; ++ }; ++ }; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ }; ++ }; ++ }; ++ ++ usb@22000 { ++ dr_mode = "host"; ++ phy_type = "ulpi"; ++ }; ++ ++ serial1: serial@4600 { ++ status = "disabled"; ++ }; ++ ++ mdio@24520 { ++ phy0: ethernet-phy@1 { ++ reg = <0x1>; ++ }; ++ }; ++ ++ enet0: ethernet@24000 { ++ phy-handle = <&phy0>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ enet1: ethernet@25000 { ++ status = "disabled"; ++ }; ++ ++ enet2: ethernet@26000 { ++ status = "disabled"; ++ }; ++ }; ++ ++ pci0: pcie@ffe08000 { ++ status = "disabled"; ++ }; ++ ++ pci1: pcie@ffe09000 { ++ status = "disabled"; ++ }; ++ ++ pci2: pcie@ffe0a000 { ++ ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 ++ >; ++ ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0xc0000000 ++ 0x2000000 0x0 0xc0000000 ++ 0x0 0x20000000 ++ ++ 0x1000000 0x0 0x0 ++ 0x1000000 0x0 0x0 ++ 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/quanta_ly6_p2020.dts b/arch/powerpc/boot/dts/quanta_ly6_p2020.dts +new file mode 100644 +index 0000000..7a08c78 +--- /dev/null ++++ b/arch/powerpc/boot/dts/quanta_ly6_p2020.dts +@@ -0,0 +1,782 @@ ++/* ++ * Cumulus P2020 Device Tree Source ++ * ++ * Copyright 2012 Cumulus Networks, 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/ "p2020si.dtsi" ++ ++/ { ++ model = "quanta,ly6_p2020"; ++ compatible = "quanta,ly6_p2020"; ++ ++ aliases { ++ ethernet0 = &enet1; ++ serial0 = &serial0; ++ serial1 = &serial1; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ }; ++ ++ bcm_dma { ++ compatible = "early-dma-alloc"; ++ // 64MB DMA region, aligned to 1MB ++ region_size = <0x04000000>; ++ alignment = <0x00100000>; ++ }; ++ ++ mass_storage { ++ device = "mmcblk0"; ++ }; ++ ++ localbus@ffe05000 { ++ compatible = "fsl,elbc", "simple-bus"; ++ ranges = <0x0 0x0 0x0 0xec000000 0x04000000 ++ 0x1 0x0 0x0 0xe8000000 0x04000000>; ++ ++ nor@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x04000000>; ++ bank-width = <2>; ++ partition@0 { ++ /* Entire flash minus (u-boot + onie) */ ++ reg = <0x00000000 0x03b60000>; ++ label = "open"; ++ }; ++ partition@1 { ++ /* 4MB onie */ ++ reg = <0x03b60000 0x00400000>; ++ label = "onie"; ++ }; ++ partition@2 { ++ /* 128KB, 1 sector */ ++ reg = <0x03f60000 0x00020000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@3 { ++ /* 512KB u-boot */ ++ reg = <0x03f80000 0x00080000>; ++ label = "uboot"; ++ }; ++ }; ++ ++ nor@1,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x1 0x0 0x04000000>; ++ bank-width = <2>; ++ partition@0 { ++ reg = <0x00000000 0x04000000>; ++ label = "open2"; ++ }; ++ }; ++ }; ++ ++ soc@ffe00000 { ++ i2c@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <43 2>; ++ interrupt-parent = <&mpic>; ++ fsl,preserve-clocking; ++ ++ /* Cypress PSOC fan and temp controller */ ++ cypsoc: psoc@4e { ++ compatible = "CY8C3245R1"; ++ reg = <0x4e>; ++ label = "Cypress PSOC"; ++ }; ++ rtc@68 { ++ compatible = "dallas,ds1339"; ++ reg = <0x68>; ++ }; ++ mux@71 { ++ compatible = "ti,pca9546"; ++ reg = <0x71>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ pca9555@20 { ++ compatible = "nxp,pca9555"; ++ reg = <0x20>; ++ label = "PCA9555_1"; ++ }; ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ board_eeprom@53 { ++ compatible = "at,24c02"; ++ reg = <0x53>; ++ label = "board_eeprom"; ++ }; ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ pca9554@21 { ++ compatible = "nxp,pca9554"; ++ reg = <0x21>; ++ label = "PCA9554_1"; ++ }; ++ }; ++ }; ++ ++ mux@72 { ++ compatible = "ti,pca9546"; ++ reg = <0x72>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ pca9555@26 { ++ compatible = "nxp,pca9555"; ++ reg = <0x26>; ++ label = "PCA9555_PSU"; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ board_eeprom@54 { ++ compatible = "at,24c02"; ++ reg = <0x54>; ++ label = "board_eeprom"; ++ }; ++ }; ++ }; ++ ++ mux@77 { ++ compatible = "ti,pca9548"; ++ reg = <0x77>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ mux@73 { ++ compatible = "nxp,pca9548"; ++ reg = <0x73>; ++ label = "QSFP 1-8 eeprom"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ /* QSFP 1 */ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port1"; ++ }; ++ }; ++ ++ /* QSFP 2 */ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port2"; ++ }; ++ }; ++ ++ /* QSFP 3 */ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port3"; ++ }; ++ }; ++ ++ ++ /* QSFP 4 */ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port4"; ++ }; ++ }; ++ ++ ++ /* QSFP 5 */ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port5"; ++ }; ++ }; ++ ++ /* QSFP 6 */ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port6"; ++ }; ++ }; ++ ++ /* QSFP 7 */ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port7"; ++ }; ++ }; ++ ++ /* QSFP 8 */ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port8"; ++ }; ++ }; ++ ++ }; ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ mux@74 { ++ compatible = "nxp,pca9548"; ++ reg = <0x74>; ++ label = "QSFP 9-16 eeprom"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ /* QSFP 9 */ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port9"; ++ }; ++ }; ++ ++ /* QSFP 10 */ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port10"; ++ }; ++ }; ++ ++ /* QSFP 11 */ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port11"; ++ }; ++ }; ++ ++ /* QSFP 12 */ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port12"; ++ }; ++ }; ++ ++ /* QSFP 13 */ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port13"; ++ }; ++ }; ++ ++ /* QSFP 14 */ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port14"; ++ }; ++ }; ++ ++ /* QSFP 15 */ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port15"; ++ }; ++ }; ++ ++ /* QSFP 16 */ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port16"; ++ }; ++ }; ++ ++ }; ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ mux@75 { ++ compatible = "nxp,pca9548"; ++ reg = <0x75>; ++ label = "QSFP 17-24 eeprom"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ /* QSFP 17 */ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port17"; ++ }; ++ }; ++ ++ /* QSFP 18 */ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port18"; ++ }; ++ }; ++ ++ /* QSFP 19 */ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port19"; ++ }; ++ }; ++ ++ /* QSFP 20 */ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port20"; ++ }; ++ }; ++ ++ /* QSFP 21 */ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port21"; ++ }; ++ }; ++ ++ /* QSFP 22 */ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port22"; ++ }; ++ }; ++ ++ /* QSFP 23 */ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port23"; ++ }; ++ }; ++ ++ /* QSFP 24 */ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port24"; ++ }; ++ }; ++ ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ mux@76 { ++ compatible = "nxp,pca9548"; ++ reg = <0x76>; ++ label = "QSFP 25-32 eeprom"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ /* QSFP 25 */ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port25"; ++ }; ++ }; ++ ++ /* QSFP 26 */ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port26"; ++ }; ++ }; ++ ++ /* QSFP 27 */ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port27"; ++ }; ++ }; ++ ++ /* QSFP 28 */ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port28"; ++ }; ++ }; ++ ++ /* QSFP 29 */ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port29"; ++ }; ++ }; ++ ++ /* QSFP 30 */ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port30"; ++ }; ++ }; ++ ++ /* QSFP 31 */ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port31"; ++ }; ++ }; ++ ++ /* QSFP 32 */ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ sfp_eeprom@50 { ++ compatible = "sff8436"; ++ reg = <0x50>; ++ label = "port32"; ++ }; ++ }; ++ ++ }; ++ }; ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ cpld_i2c@3A { ++ compatible = "quanta,ly6_p2020_cpld"; ++ reg = <0x3A>; ++ label = "cpld_1_16"; ++ }; ++ }; ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ cpld_i2c@3B { ++ compatible = "quanta,ly6_p2020_cpld"; ++ reg = <0x3B>; ++ label = "cpld_17_32"; ++ }; ++ }; ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ pca9555@24 { ++ compatible = "nxp,pca9555"; ++ reg = <0x24>; ++ label = "pca9555_3"; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ pca9555@23 { ++ compatible = "nxp,pca9555"; ++ reg = <0x23>; ++ label = "pca9555_4"; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@3100 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <1>; ++ compatible = "fsl-i2c"; ++ reg = <0x3100 0x100>; ++ interrupts = <43 2>; ++ interrupt-parent = <&mpic>; ++ fsl,preserve-clocking; ++ }; ++ ++ usb@22000 { ++ dr_mode = "host"; ++ phy_type = "ulpi"; ++ }; ++ ++ serial1: serial@4600 { ++ status = "disabled"; ++ }; ++ ++ mdio@24520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++ phy0: ethernet-phy@5 { ++ reg = <0x5>; ++ device_type = "ethernet-phy"; ++ }; ++ }; ++ ++ mdio1: mdio@25520 { ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ compatible = "fsl,gianfar-tbi"; ++ reg = <0x25520 0x20>; ++ tbi0: tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ ++ enet0: ethernet@24000 { ++ status = "disabled"; ++ }; ++ ++ enet1: ethernet@25000 { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ cell-index = <0x1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x25000 0x1000>; ++ ranges = <0x0 0x25000 0x1000>; ++ interrupts = < ++ 0x23 0x2 ++ 0x24 0x2 ++ 0x28 0x2>; ++ interrupt-parent = <&mpic>; ++ tbi-handle = <&tbi0>; ++ phy-handle = <&phy0>; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ enet2: ethernet@26000 { ++ status = "disabled"; ++ }; ++ }; ++ ++ pci0: pcie@ffe08000 { ++ status = "disabled"; ++ }; ++ ++ pci1: pcie@ffe09000 { ++ status = "disabled"; ++ }; ++ ++ pci2: pcie@ffe0a000 { ++ ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000 ++ 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>; ++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>; ++ interrupt-map = < ++ /* IDSEL 0x0 */ ++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1 ++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1 ++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1 ++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1 ++ >; ++ ++ pcie@0 { ++ reg = <0x0 0x0 0x0 0x0 0x0>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ device_type = "pci"; ++ ranges = <0x2000000 0x0 0xc0000000 ++ 0x2000000 0x0 0xc0000000 ++ 0x0 0x20000000 ++ ++ 0x1000000 0x0 0x0 ++ 0x1000000 0x0 0x0 ++ 0x0 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig +index f087de6..fc5ece3 100644 +--- a/arch/powerpc/configs/corenet32_smp_defconfig ++++ b/arch/powerpc/configs/corenet32_smp_defconfig +@@ -26,17 +26,21 @@ CONFIG_P3041_DS=y + CONFIG_P3060_QDS=y + CONFIG_P4080_DS=y + CONFIG_P5020_DS=y ++CONFIG_P5040_DS=y + CONFIG_HIGHMEM=y + CONFIG_NO_HZ=y + CONFIG_HIGH_RES_TIMERS=y + # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set + CONFIG_BINFMT_MISC=m + CONFIG_KEXEC=y ++CONFIG_IRQ_ALL_CPUS=y + CONFIG_FORCE_MAX_ZONEORDER=13 + CONFIG_FSL_LBC=y ++CONFIG_FSL_PAMU=y + CONFIG_PCI=y + CONFIG_PCIEPORTBUS=y + # CONFIG_PCIEASPM is not set ++CONFIG_PCI_MSI=y + CONFIG_NET=y + CONFIG_PACKET=y + CONFIG_UNIX=y +@@ -67,6 +71,7 @@ CONFIG_INET_IPCOMP=y + CONFIG_IPV6=y + CONFIG_IP_SCTP=m + CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++CONFIG_DEVTMPFS=y + CONFIG_MTD=y + CONFIG_MTD_CMDLINE_PARTS=y + CONFIG_MTD_CHAR=y +@@ -78,7 +83,7 @@ CONFIG_MTD_M25P80=y + CONFIG_PROC_DEVICETREE=y + CONFIG_BLK_DEV_LOOP=y + CONFIG_BLK_DEV_RAM=y +-CONFIG_BLK_DEV_RAM_SIZE=131072 ++CONFIG_BLK_DEV_RAM_SIZE=262144 + CONFIG_MISC_DEVICES=y + CONFIG_BLK_DEV_SD=y + CONFIG_CHR_DEV_ST=y +@@ -93,13 +98,18 @@ CONFIG_SATA_FSL=y + CONFIG_SATA_SIL24=y + CONFIG_SATA_SIL=y + CONFIG_PATA_SIL680=y ++CONFIG_MD=y ++CONFIG_BLK_DEV_MD=y ++# CONFIG_MD_AUTODETECT is not set ++CONFIG_MD_RAID456=y ++CONFIG_MULTICORE_RAID456=y + CONFIG_NETDEVICES=y +-CONFIG_VITESSE_PHY=y + CONFIG_FIXED_PHY=y + CONFIG_NET_ETHERNET=y + CONFIG_E1000=y + CONFIG_E1000E=y + CONFIG_FSL_PQ_MDIO=y ++CONFIG_DPA=y + # CONFIG_INPUT_MOUSEDEV is not set + # CONFIG_INPUT_KEYBOARD is not set + # CONFIG_INPUT_MOUSE is not set +@@ -133,16 +143,25 @@ CONFIG_USB_OHCI_HCD_PPC_OF_LE=y + CONFIG_USB_STORAGE=y + CONFIG_MMC=y + CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_OF=y ++CONFIG_MMC_SDHCI_OF_ESDHC=y + CONFIG_EDAC=y + CONFIG_EDAC_MM_EDAC=y + CONFIG_EDAC_MPC85XX=y + CONFIG_RTC_CLASS=y ++CONFIG_RTC_DRV_DS1307=y + CONFIG_RTC_DRV_DS3232=y + CONFIG_RTC_DRV_CMOS=y ++CONFIG_DMADEVICES=y ++CONFIG_FSL_RAID=y ++CONFIG_ASYNC_TX_DMA=y + CONFIG_UIO=y ++CONFIG_UIO_FSL_SRIO=y ++CONFIG_UIO_FSL_DMA=y + CONFIG_STAGING=y + CONFIG_VIRT_DRIVERS=y + CONFIG_FSL_HV_MANAGER=y ++CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM=y + CONFIG_EXT2_FS=y + CONFIG_EXT3_FS=y + # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +@@ -167,6 +186,7 @@ CONFIG_MAC_PARTITION=y + CONFIG_NLS_ISO8859_1=y + CONFIG_NLS_UTF8=m + CONFIG_MAGIC_SYSRQ=y ++CONFIG_DEBUG_KERNEL=y + CONFIG_DEBUG_SHIRQ=y + CONFIG_DETECT_HUNG_TASK=y + CONFIG_DEBUG_INFO=y +diff --git a/arch/powerpc/include/asm/emulated_ops.h b/arch/powerpc/include/asm/emulated_ops.h +index 63f2a22..093359a 100644 +--- a/arch/powerpc/include/asm/emulated_ops.h ++++ b/arch/powerpc/include/asm/emulated_ops.h +@@ -44,6 +44,7 @@ extern struct ppc_emulated { + struct ppc_emulated_entry spe; + struct ppc_emulated_entry string; + struct ppc_emulated_entry unaligned; ++ struct ppc_emulated_entry lwsync; + #ifdef CONFIG_MATH_EMULATION + struct ppc_emulated_entry math; + #elif defined(CONFIG_8XX_MINIMAL_FPEMU) +diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h +index bebd124..a9a85ef 100644 +--- a/arch/powerpc/include/asm/fsl_guts.h ++++ b/arch/powerpc/include/asm/fsl_guts.h +@@ -85,7 +85,9 @@ struct ccsr_guts_86xx { + u8 res0c4[0x224 - 0xc4]; + __be32 iodelay1; /* 0x.0224 - IO delay control register 1 */ + __be32 iodelay2; /* 0x.0228 - IO delay control register 2 */ +- u8 res22c[0x800 - 0x22c]; ++ u8 res22c[0x604 - 0x22c]; ++ __be32 pamubypenr; /* 0x.0604 - PAMU bypass enable register */ ++ u8 res608[0x800 - 0x608]; + __be32 clkdvdr; /* 0x.0800 - Clock Divide Register */ + u8 res804[0x900 - 0x804]; + __be32 ircr; /* 0x.0900 - Infrared Control Register */ +diff --git a/arch/powerpc/include/asm/fsl_hcalls.h b/arch/powerpc/include/asm/fsl_hcalls.h +index 922d9b5..7e0b5b7 100644 +--- a/arch/powerpc/include/asm/fsl_hcalls.h ++++ b/arch/powerpc/include/asm/fsl_hcalls.h +@@ -45,7 +45,7 @@ + #include + #include + +-#define FH_API_VERSION 1 ++#define FH_API_VERSION 3 + + #define FH_ERR_GET_INFO 1 + #define FH_PARTITION_GET_DTPROP 2 +@@ -65,6 +65,8 @@ + #define FH_EXIT_NAP 16 + #define FH_CLAIM_DEVICE 17 + #define FH_PARTITION_STOP_DMA 18 ++#define FH_DMA_ATTR_SET 19 ++#define FH_DMA_ATTR_GET 20 + + /* vendor ID: Freescale Semiconductor */ + #define FH_HCALL_TOKEN(num) _EV_HCALL_TOKEN(EV_FSL_VENDOR_ID, num) +@@ -652,4 +654,80 @@ static inline unsigned int fh_partition_stop_dma(unsigned int handle) + + return r3; + } ++ ++#define FSL_PAMU_ATTR_STASH 2 ++ ++struct fh_dma_attr_stash { ++ uint32_t vcpu; /* vcpu number */ ++ uint32_t cache; /* cache to stash to: 1=L1, 2=L2, 3=L3 */ ++}; ++ ++/** ++ * fh_dma_attr_set - configure a DMA window ++ * @handle: value from fsl,hv-device-handle property ++ * @attr_name: the FSL_PAMU_ATTR_xxx attribute to change ++ * @attr_address: the physical address of the attribute structure ++ * ++ * FSL_PAMU_ATTR_STASH: Configure the target CPU and cache level for stashing ++ * ++ * Returns 0 for success, or an error code. ++ */ ++static inline unsigned int fh_dma_attr_set(unsigned int handle, ++ unsigned int attr_name, phys_addr_t attr_address) ++{ ++ register uintptr_t r11 __asm__("r11"); ++ register uintptr_t r3 __asm__("r3"); ++ register uintptr_t r4 __asm__("r4"); ++ register uintptr_t r5 __asm__("r5"); ++ register uintptr_t r6 __asm__("r6"); ++ ++ r11 = FH_HCALL_TOKEN(FH_DMA_ATTR_SET); ++ r3 = handle; ++ r4 = attr_name; ++ r5 = (uint64_t)attr_address >> 32; ++ r6 = (uint32_t)attr_address; ++ ++ __asm__ __volatile__ ("sc 1" ++ : "+r" (r11), ++ "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6) ++ : : EV_HCALL_CLOBBERS4 ++ ); ++ ++ return r3; ++} ++ ++/** ++ * fh_dma_attr_get - query the DMA window configuration ++ * @handle: value from fsl,hv-device-handle property ++ * @attr_name: the FSL_PAMU_ATTR_xxx attribute to change ++ * @attr_address: the physical address of the attribute structure ++ * ++ * FSL_PAMU_ATTR_STASH: Query the target CPU and cache level for stashing ++ * ++ * Returns 0 for success, or an error code. ++ */ ++static inline unsigned int fh_dma_attr_get(unsigned int handle, ++ unsigned int attr_name, phys_addr_t attr_address) ++{ ++ register uintptr_t r11 __asm__("r11"); ++ register uintptr_t r3 __asm__("r3"); ++ register uintptr_t r4 __asm__("r4"); ++ register uintptr_t r5 __asm__("r5"); ++ register uintptr_t r6 __asm__("r6"); ++ ++ r11 = FH_HCALL_TOKEN(FH_DMA_ATTR_GET); ++ r3 = handle; ++ r4 = attr_name; ++ r5 = (uint64_t)attr_address >> 32; ++ r6 = (uint32_t)attr_address; ++ ++ __asm__ __volatile__ ("sc 1" ++ : "+r" (r11), ++ "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6) ++ : : EV_HCALL_CLOBBERS4 ++ ); ++ ++ return r3; ++} ++ + #endif +diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h +index 88b0bd9..bc52378 100644 +--- a/arch/powerpc/include/asm/pgtable.h ++++ b/arch/powerpc/include/asm/pgtable.h +@@ -172,6 +172,9 @@ extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addre + + #define pgprot_writecombine pgprot_noncached_wc + ++#define pgprot_cached_noncoherent(prot) \ ++ (__pgprot(pgprot_val(prot) & ~_PAGE_CACHE_CTL)) ++ + struct file; + extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot); +diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h +index 03c48e8..cd7b5af 100644 +--- a/arch/powerpc/include/asm/reg_booke.h ++++ b/arch/powerpc/include/asm/reg_booke.h +@@ -37,7 +37,11 @@ + #define MSR_KERNEL (MSR_ME|MSR_RI|MSR_IR|MSR_DR|MSR_CE) + #define MSR_USER (MSR_KERNEL|MSR_PR|MSR_EE) + #else ++#if defined(CONFIG_JTAG_DEBUGGER) ++#define MSR_KERNEL (MSR_ME|MSR_RI|MSR_CE|MSR_DE) ++#else + #define MSR_KERNEL (MSR_ME|MSR_RI|MSR_CE) ++#endif + #define MSR_USER (MSR_KERNEL|MSR_PR|MSR_EE) + #endif + +diff --git a/arch/powerpc/include/asm/spu.h b/arch/powerpc/include/asm/spu.h +index 4e360bd..fff9213 100644 +--- a/arch/powerpc/include/asm/spu.h ++++ b/arch/powerpc/include/asm/spu.h +@@ -25,7 +25,7 @@ + #ifdef __KERNEL__ + + #include +-#include ++#include + #include + + #define LS_SIZE (256 * 1024) +@@ -166,7 +166,7 @@ struct spu { + /* beat only */ + u64 shadow_int_mask_RW[3]; + +- struct sys_device sysdev; ++ struct device dev; + + int has_mem_affinity; + struct list_head aff_list; +@@ -270,11 +270,11 @@ struct spufs_calls { + int register_spu_syscalls(struct spufs_calls *calls); + void unregister_spu_syscalls(struct spufs_calls *calls); + +-int spu_add_sysdev_attr(struct sysdev_attribute *attr); +-void spu_remove_sysdev_attr(struct sysdev_attribute *attr); ++int spu_add_dev_attr(struct device_attribute *attr); ++void spu_remove_dev_attr(struct device_attribute *attr); + +-int spu_add_sysdev_attr_group(struct attribute_group *attrs); +-void spu_remove_sysdev_attr_group(struct attribute_group *attrs); ++int spu_add_dev_attr_group(struct attribute_group *attrs); ++void spu_remove_dev_attr_group(struct attribute_group *attrs); + + int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, + unsigned long dsisr, unsigned *flt); +diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h +index e30a13d..41ec4a8 100644 +--- a/arch/powerpc/include/asm/system.h ++++ b/arch/powerpc/include/asm/system.h +@@ -197,11 +197,6 @@ extern int die(const char *, struct pt_regs *, long); + extern void _exception(int, struct pt_regs *, int, unsigned long); + extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); + +-#ifdef CONFIG_BOOKE_WDT +-extern u32 booke_wdt_enabled; +-extern u32 booke_wdt_period; +-#endif /* CONFIG_BOOKE_WDT */ +- + struct device_node; + extern void note_scsi_host(struct device_node *, void *); + +diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h +index 1e104af..eefc7df 100644 +--- a/arch/powerpc/include/asm/topology.h ++++ b/arch/powerpc/include/asm/topology.h +@@ -3,7 +3,7 @@ + #ifdef __KERNEL__ + + +-struct sys_device; ++struct device; + struct device_node; + + #ifdef CONFIG_NUMA +@@ -86,19 +86,19 @@ extern int __node_distance(int, int); + + extern void __init dump_numa_cpu_topology(void); + +-extern int sysfs_add_device_to_node(struct sys_device *dev, int nid); +-extern void sysfs_remove_device_from_node(struct sys_device *dev, int nid); ++extern int sysfs_add_device_to_node(struct device *dev, int nid); ++extern void sysfs_remove_device_from_node(struct device *dev, int nid); + + #else + + static inline void dump_numa_cpu_topology(void) {} + +-static inline int sysfs_add_device_to_node(struct sys_device *dev, int nid) ++static inline int sysfs_add_device_to_node(struct device *dev, int nid) + { + return 0; + } + +-static inline void sysfs_remove_device_from_node(struct sys_device *dev, ++static inline void sysfs_remove_device_from_node(struct device *dev, + int nid) + { + } +@@ -124,13 +124,15 @@ static inline int stop_topology_update(void) + #include + #define smt_capable() (cpu_has_feature(CPU_FTR_SMT)) + +-#ifdef CONFIG_PPC64 + #include + +-#define topology_thread_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu)) +-#define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu)) +-#define topology_core_id(cpu) (cpu_to_core_id(cpu)) ++#ifdef CONFIG_PPC64 ++#define topology_thread_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu)) ++#define topology_physical_package_id(cpu) (get_hard_smp_processor_id(cpu)) + #endif ++#define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu)) ++#define topology_core_id(cpu) (cpu_to_core_id(cpu)) ++#define topology_physical_package_id(cpu) (0) + #endif + + #endif /* __KERNEL__ */ +diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c +index 4f15565..63c4979 100644 +--- a/arch/powerpc/kernel/cacheinfo.c ++++ b/arch/powerpc/kernel/cacheinfo.c +@@ -476,15 +476,15 @@ out: + static struct cache_dir *__cpuinit cacheinfo_create_cache_dir(unsigned int cpu_id) + { + struct cache_dir *cache_dir; +- struct sys_device *sysdev; ++ struct device *dev; + struct kobject *kobj = NULL; + +- sysdev = get_cpu_sysdev(cpu_id); +- WARN_ONCE(!sysdev, "no sysdev for CPU %i\n", cpu_id); +- if (!sysdev) ++ dev = get_cpu_device(cpu_id); ++ WARN_ONCE(!dev, "no dev for CPU %i\n", cpu_id); ++ if (!dev) + goto err; + +- kobj = kobject_create_and_add("cache", &sysdev->kobj); ++ kobj = kobject_create_and_add("cache", &dev->kobj); + if (!kobj) + goto err; + +diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S +index 9f5d210..4f634e4 100644 +--- a/arch/powerpc/kernel/head_fsl_booke.S ++++ b/arch/powerpc/kernel/head_fsl_booke.S +@@ -364,7 +364,7 @@ interrupt_base: + EXCEPTION(0x3100, FixedIntervalTimer, unknown_exception, EXC_XFER_EE) + + /* Watchdog Timer Interrupt */ +-#ifdef CONFIG_BOOKE_WDT ++#if defined(CONFIG_BOOKE_WDT) || defined(CONFIG_BOOKE_WDT_MODULE) + CRITICAL_EXCEPTION(0x3200, WatchdogTimer, WatchdogException) + #else + CRITICAL_EXCEPTION(0x3200, WatchdogTimer, unknown_exception) +diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c +index 12659ab..63c2ab1 100644 +--- a/arch/powerpc/kernel/pci-common.c ++++ b/arch/powerpc/kernel/pci-common.c +@@ -1111,6 +1111,13 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) + ppc_md.pci_dma_dev_setup(dev); + + /* Read default IRQs and fixup if necessary */ ++ if (pci_read_irq_line(dev) && (dev->devfn != 0)) { ++ printk(KERN_WARNING ++ "WARNING: Unable to map IRQ in device tree for pci device " ++ "%04x:%02x:%02x.%d\n", ++ pci_domain_nr(dev->bus), dev->bus->number, PCI_SLOT(dev->devfn), ++ PCI_FUNC(dev->devfn)); ++ } + pci_read_irq_line(dev); + if (ppc_md.pci_irq_fixup) + ppc_md.pci_irq_fixup(dev); +@@ -1689,6 +1696,62 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus) + return of_node_get(hose->dn); + } + ++/* ++ * scan and set the PCIe bus payload and read request sizes. ++ */ ++static int __devinit __fixup_pcie_scan_payload(struct pci_dev * pdev, ++ void * data) ++{ ++ int * payload_size = data; ++ int rval, cap, payload_cap; ++ uint32_t devcap; ++ ++ cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); ++ if (cap == 0) { ++ return -ENODEV; ++ } ++ ++ rval = pci_read_config_dword(pdev, cap + PCI_EXP_DEVCAP, &devcap); ++ if (rval) { ++ return rval; ++ } ++ payload_cap = devcap & PCI_EXP_DEVCAP_PAYLOAD; ++ if (payload_cap < *payload_size) { ++ *payload_size = payload_cap; ++ } ++ return 0; ++} ++ ++static int __devinit __fixup_pcie_set_payload(struct pci_dev * pdev, ++ void * data) ++{ ++ int * payload_size = data; ++ int rval, cap; ++ uint16_t devctl; ++ ++ cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); ++ if (cap == 0) { ++ return -ENODEV; ++ } ++ ++ rval = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &devctl); ++ if (rval) { ++ return rval; ++ } ++ ++ devctl &= ~PCI_EXP_DEVCTL_PAYLOAD; ++ devctl |= *payload_size << 5; ++ ++ devctl &= ~PCI_EXP_DEVCTL_READRQ; ++ devctl |= *payload_size << 12; ++ ++ rval = pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, devctl); ++ if (rval) { ++ return rval; ++ } ++ return 0; ++} ++ + /** + * pci_scan_phb - Given a pci_controller, setup and scan the PCI bus + * @hose: Pointer to the PCI host controller instance structure +@@ -1698,6 +1761,7 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) + struct pci_bus *bus; + struct device_node *node = hose->dn; + int mode; ++ int payload_size; + + pr_debug("PCI: Scanning PHB %s\n", + node ? node->full_name : ""); +@@ -1731,6 +1795,24 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) + if (mode == PCI_PROBE_NORMAL) + hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); + ++ /* Set the payload size for all devices on the bus */ ++ payload_size = PCI_EXP_DEVCAP_PAYLOAD; ++ pci_walk_bus(hose->bus, __fixup_pcie_scan_payload, &payload_size); ++ if (payload_size < PCI_EXP_DEVCAP_PAYLOAD) { ++ pci_walk_bus(hose->bus, __fixup_pcie_set_payload, &payload_size); ++ dev_info(&hose->bus->dev, ++ "Set PCIe payload and read request to %d\n", ++ (payload_size == 0) ? 128 : ++ (payload_size == 1) ? 256 : ++ (payload_size == 2) ? 512 : ++ (payload_size == 3) ? 1024 : ++ (payload_size == 4) ? 2048 : ++ (payload_size == 5) ? 4096 : ++ (payload_size == 6) ? 8192 : ++ 16384 ++ ); ++ } ++ + /* Configure PCI Express settings */ + if (bus && !pci_has_flag(PCI_PROBE_ONLY)) { + struct pci_bus *child; +diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c +index d687e3f..9345817 100644 +--- a/arch/powerpc/kernel/process.c ++++ b/arch/powerpc/kernel/process.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -626,8 +627,9 @@ void show_regs(struct pt_regs * regs) + + printk("NIP: "REG" LR: "REG" CTR: "REG"\n", + regs->nip, regs->link, regs->ctr); +- printk("REGS: %p TRAP: %04lx %s (%s)\n", +- regs, regs->trap, print_tainted(), init_utsname()->release); ++ printk("REGS: %p TRAP: %04lx %s (%s%s)\n", ++ regs, regs->trap, print_tainted(), init_utsname()->release, ++ LINUX_PACKAGE_ID); + printk("MSR: "REG" ", regs->msr); + printbits(regs->msr, msr_bits); + printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer); +diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c +index 83940d7..6710fcb 100644 +--- a/arch/powerpc/kernel/setup-common.c ++++ b/arch/powerpc/kernel/setup-common.c +@@ -199,6 +199,23 @@ static void show_cpuinfo_summary(struct seq_file *m) + #endif + } + ++/* ++ * Get CPU information for use by the procfs. ++ */ ++static void show_cpuinfo_core(struct seq_file *m, unsigned int cpu) ++{ ++ ++ ++#ifdef CONFIG_SMP ++#ifdef CONFIG_PPC64 ++ seq_printf(m, "physical id\t: %d\n", get_hard_smp_processor_id(cpu)); ++#else /* Assume 32 bit archs are single package */ ++ seq_printf(m, "physical id\t: %d\n", (0)); ++#endif /* CONFIG_PPC64 */ ++ seq_printf(m, "core id\t\t: %d\n", (cpu_to_core_id(cpu))); ++#endif ++} ++ + static int show_cpuinfo(struct seq_file *m, void *v) + { + unsigned long cpu_id = (unsigned long)v - 1; +@@ -302,6 +319,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) + seq_printf(m, "revision\t: %hd.%hd (pvr %04x %04x)\n", + maj, min, PVR_VER(pvr), PVR_REV(pvr)); + ++ show_cpuinfo_core(m, cpu_id); ++ + #ifdef CONFIG_PPC32 + seq_printf(m, "bogomips\t: %lu.%02lu\n", + loops_per_jiffy / (500000/HZ), +diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c +index ac76108..01fcfc55 100644 +--- a/arch/powerpc/kernel/setup_32.c ++++ b/arch/powerpc/kernel/setup_32.c +@@ -150,27 +150,6 @@ notrace void __init machine_init(u64 dt_ptr) + ppc_md.progress("id mach(): done", 0x200); + } + +-#ifdef CONFIG_BOOKE_WDT +-/* Checks wdt=x and wdt_period=xx command-line option */ +-notrace int __init early_parse_wdt(char *p) +-{ +- if (p && strncmp(p, "0", 1) != 0) +- booke_wdt_enabled = 1; +- +- return 0; +-} +-early_param("wdt", early_parse_wdt); +- +-int __init early_parse_wdt_period (char *p) +-{ +- if (p) +- booke_wdt_period = simple_strtoul(p, NULL, 0); +- +- return 0; +-} +-early_param("wdt_period", early_parse_wdt_period); +-#endif /* CONFIG_BOOKE_WDT */ +- + /* Checks "l2cr=xxxx" command-line option */ + int __init ppc_setup_l2cr(char *str) + { +@@ -317,9 +296,6 @@ void __init setup_arch(char **cmdline_p) + if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) + ucache_bsize = icache_bsize = dcache_bsize; + +- /* reboot on panic */ +- panic_timeout = 180; +- + if (ppc_md.panic) + setup_panic(); + +diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c +index 2c8890a..38533f2 100644 +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -554,9 +554,6 @@ void __init setup_arch(char **cmdline_p) + dcache_bsize = ppc64_caches.dline_size; + icache_bsize = ppc64_caches.iline_size; + +- /* reboot on panic */ +- panic_timeout = 180; +- + if (ppc_md.panic) + setup_panic(); + +diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c +index fe04b4a..b2527c6 100644 +--- a/arch/powerpc/kernel/smp.c ++++ b/arch/powerpc/kernel/smp.c +@@ -27,7 +27,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c +index ca683a1..6f48377 100644 +--- a/arch/powerpc/kernel/sysfs.c ++++ b/arch/powerpc/kernel/sysfs.c +@@ -1,4 +1,4 @@ +-#include ++#include + #include + #include + #include +@@ -38,12 +38,12 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices); + /* Time in microseconds we delay before sleeping in the idle loop */ + DEFINE_PER_CPU(long, smt_snooze_delay) = { 100 }; + +-static ssize_t store_smt_snooze_delay(struct sys_device *dev, +- struct sysdev_attribute *attr, ++static ssize_t store_smt_snooze_delay(struct device *dev, ++ struct device_attribute *attr, + const char *buf, + size_t count) + { +- struct cpu *cpu = container_of(dev, struct cpu, sysdev); ++ struct cpu *cpu = container_of(dev, struct cpu, dev); + ssize_t ret; + long snooze; + +@@ -51,21 +51,21 @@ static ssize_t store_smt_snooze_delay(struct sys_device *dev, + if (ret != 1) + return -EINVAL; + +- per_cpu(smt_snooze_delay, cpu->sysdev.id) = snooze; ++ per_cpu(smt_snooze_delay, cpu->dev.id) = snooze; + + return count; + } + +-static ssize_t show_smt_snooze_delay(struct sys_device *dev, +- struct sysdev_attribute *attr, ++static ssize_t show_smt_snooze_delay(struct device *dev, ++ struct device_attribute *attr, + char *buf) + { +- struct cpu *cpu = container_of(dev, struct cpu, sysdev); ++ struct cpu *cpu = container_of(dev, struct cpu, dev); + +- return sprintf(buf, "%ld\n", per_cpu(smt_snooze_delay, cpu->sysdev.id)); ++ return sprintf(buf, "%ld\n", per_cpu(smt_snooze_delay, cpu->dev.id)); + } + +-static SYSDEV_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay, ++static DEVICE_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay, + store_smt_snooze_delay); + + static int __init setup_smt_snooze_delay(char *str) +@@ -118,25 +118,25 @@ static void write_##NAME(void *val) \ + ppc_enable_pmcs(); \ + mtspr(ADDRESS, *(unsigned long *)val); \ + } \ +-static ssize_t show_##NAME(struct sys_device *dev, \ +- struct sysdev_attribute *attr, \ ++static ssize_t show_##NAME(struct device *dev, \ ++ struct device_attribute *attr, \ + char *buf) \ + { \ +- struct cpu *cpu = container_of(dev, struct cpu, sysdev); \ ++ struct cpu *cpu = container_of(dev, struct cpu, dev); \ + unsigned long val; \ +- smp_call_function_single(cpu->sysdev.id, read_##NAME, &val, 1); \ ++ smp_call_function_single(cpu->dev.id, read_##NAME, &val, 1); \ + return sprintf(buf, "%lx\n", val); \ + } \ + static ssize_t __used \ +- store_##NAME(struct sys_device *dev, struct sysdev_attribute *attr, \ ++ store_##NAME(struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t count) \ + { \ +- struct cpu *cpu = container_of(dev, struct cpu, sysdev); \ ++ struct cpu *cpu = container_of(dev, struct cpu, dev); \ + unsigned long val; \ + int ret = sscanf(buf, "%lx", &val); \ + if (ret != 1) \ + return -EINVAL; \ +- smp_call_function_single(cpu->sysdev.id, write_##NAME, &val, 1); \ ++ smp_call_function_single(cpu->dev.id, write_##NAME, &val, 1); \ + return count; \ + } + +@@ -184,21 +184,21 @@ SYSFS_PMCSETUP(dscr, SPRN_DSCR); + enable write when needed with a separate function. + Lets be conservative and default to pseries. + */ +-static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra); +-static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL); +-static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr); +-static SYSDEV_ATTR(purr, 0400, show_purr, store_purr); ++static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); ++static DEVICE_ATTR(spurr, 0600, show_spurr, NULL); ++static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr); ++static DEVICE_ATTR(purr, 0400, show_purr, store_purr); + + unsigned long dscr_default = 0; + EXPORT_SYMBOL(dscr_default); + +-static void add_write_permission_dev_attr(struct sysdev_attribute *attr) ++static void add_write_permission_dev_attr(struct device_attribute *attr) + { + attr->attr.mode |= 0200; + } + +-static ssize_t show_dscr_default(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, char *buf) ++static ssize_t show_dscr_default(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + return sprintf(buf, "%lx\n", dscr_default); + } +@@ -211,8 +211,8 @@ static void update_dscr(void *dummy) + } + } + +-static ssize_t __used store_dscr_default(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, const char *buf, ++static ssize_t __used store_dscr_default(struct device *dev, ++ struct device_attribute *attr, const char *buf, + size_t count) + { + unsigned long val; +@@ -228,15 +228,14 @@ static ssize_t __used store_dscr_default(struct sysdev_class *class, + return count; + } + +-static SYSDEV_CLASS_ATTR(dscr_default, 0600, ++static DEVICE_ATTR(dscr_default, 0600, + show_dscr_default, store_dscr_default); + + static void sysfs_create_dscr_default(void) + { + int err = 0; + if (cpu_has_feature(CPU_FTR_DSCR)) +- err = sysfs_create_file(&cpu_sysdev_class.kset.kobj, +- &attr_dscr_default.attr); ++ err = device_create_file(cpu_subsys.dev_root, &dev_attr_dscr_default); + } + #endif /* CONFIG_PPC64 */ + +@@ -280,72 +279,72 @@ SYSFS_PMCSETUP(tsr3, SPRN_PA6T_TSR3); + #endif /* HAS_PPC_PMC_PA6T */ + + #ifdef HAS_PPC_PMC_IBM +-static struct sysdev_attribute ibm_common_attrs[] = { +- _SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), +- _SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), ++static struct device_attribute ibm_common_attrs[] = { ++ __ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), ++ __ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), + }; + #endif /* HAS_PPC_PMC_G4 */ + + #ifdef HAS_PPC_PMC_G4 +-static struct sysdev_attribute g4_common_attrs[] = { +- _SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), +- _SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), +- _SYSDEV_ATTR(mmcr2, 0600, show_mmcr2, store_mmcr2), ++static struct device_attribute g4_common_attrs[] = { ++ __ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), ++ __ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), ++ __ATTR(mmcr2, 0600, show_mmcr2, store_mmcr2), + }; + #endif /* HAS_PPC_PMC_G4 */ + +-static struct sysdev_attribute classic_pmc_attrs[] = { +- _SYSDEV_ATTR(pmc1, 0600, show_pmc1, store_pmc1), +- _SYSDEV_ATTR(pmc2, 0600, show_pmc2, store_pmc2), +- _SYSDEV_ATTR(pmc3, 0600, show_pmc3, store_pmc3), +- _SYSDEV_ATTR(pmc4, 0600, show_pmc4, store_pmc4), +- _SYSDEV_ATTR(pmc5, 0600, show_pmc5, store_pmc5), +- _SYSDEV_ATTR(pmc6, 0600, show_pmc6, store_pmc6), ++static struct device_attribute classic_pmc_attrs[] = { ++ __ATTR(pmc1, 0600, show_pmc1, store_pmc1), ++ __ATTR(pmc2, 0600, show_pmc2, store_pmc2), ++ __ATTR(pmc3, 0600, show_pmc3, store_pmc3), ++ __ATTR(pmc4, 0600, show_pmc4, store_pmc4), ++ __ATTR(pmc5, 0600, show_pmc5, store_pmc5), ++ __ATTR(pmc6, 0600, show_pmc6, store_pmc6), + #ifdef CONFIG_PPC64 +- _SYSDEV_ATTR(pmc7, 0600, show_pmc7, store_pmc7), +- _SYSDEV_ATTR(pmc8, 0600, show_pmc8, store_pmc8), ++ __ATTR(pmc7, 0600, show_pmc7, store_pmc7), ++ __ATTR(pmc8, 0600, show_pmc8, store_pmc8), + #endif + }; + + #ifdef HAS_PPC_PMC_PA6T +-static struct sysdev_attribute pa6t_attrs[] = { +- _SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), +- _SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), +- _SYSDEV_ATTR(pmc0, 0600, show_pa6t_pmc0, store_pa6t_pmc0), +- _SYSDEV_ATTR(pmc1, 0600, show_pa6t_pmc1, store_pa6t_pmc1), +- _SYSDEV_ATTR(pmc2, 0600, show_pa6t_pmc2, store_pa6t_pmc2), +- _SYSDEV_ATTR(pmc3, 0600, show_pa6t_pmc3, store_pa6t_pmc3), +- _SYSDEV_ATTR(pmc4, 0600, show_pa6t_pmc4, store_pa6t_pmc4), +- _SYSDEV_ATTR(pmc5, 0600, show_pa6t_pmc5, store_pa6t_pmc5), ++static struct device_attribute pa6t_attrs[] = { ++ __ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), ++ __ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), ++ __ATTR(pmc0, 0600, show_pa6t_pmc0, store_pa6t_pmc0), ++ __ATTR(pmc1, 0600, show_pa6t_pmc1, store_pa6t_pmc1), ++ __ATTR(pmc2, 0600, show_pa6t_pmc2, store_pa6t_pmc2), ++ __ATTR(pmc3, 0600, show_pa6t_pmc3, store_pa6t_pmc3), ++ __ATTR(pmc4, 0600, show_pa6t_pmc4, store_pa6t_pmc4), ++ __ATTR(pmc5, 0600, show_pa6t_pmc5, store_pa6t_pmc5), + #ifdef CONFIG_DEBUG_KERNEL +- _SYSDEV_ATTR(hid0, 0600, show_hid0, store_hid0), +- _SYSDEV_ATTR(hid1, 0600, show_hid1, store_hid1), +- _SYSDEV_ATTR(hid4, 0600, show_hid4, store_hid4), +- _SYSDEV_ATTR(hid5, 0600, show_hid5, store_hid5), +- _SYSDEV_ATTR(ima0, 0600, show_ima0, store_ima0), +- _SYSDEV_ATTR(ima1, 0600, show_ima1, store_ima1), +- _SYSDEV_ATTR(ima2, 0600, show_ima2, store_ima2), +- _SYSDEV_ATTR(ima3, 0600, show_ima3, store_ima3), +- _SYSDEV_ATTR(ima4, 0600, show_ima4, store_ima4), +- _SYSDEV_ATTR(ima5, 0600, show_ima5, store_ima5), +- _SYSDEV_ATTR(ima6, 0600, show_ima6, store_ima6), +- _SYSDEV_ATTR(ima7, 0600, show_ima7, store_ima7), +- _SYSDEV_ATTR(ima8, 0600, show_ima8, store_ima8), +- _SYSDEV_ATTR(ima9, 0600, show_ima9, store_ima9), +- _SYSDEV_ATTR(imaat, 0600, show_imaat, store_imaat), +- _SYSDEV_ATTR(btcr, 0600, show_btcr, store_btcr), +- _SYSDEV_ATTR(pccr, 0600, show_pccr, store_pccr), +- _SYSDEV_ATTR(rpccr, 0600, show_rpccr, store_rpccr), +- _SYSDEV_ATTR(der, 0600, show_der, store_der), +- _SYSDEV_ATTR(mer, 0600, show_mer, store_mer), +- _SYSDEV_ATTR(ber, 0600, show_ber, store_ber), +- _SYSDEV_ATTR(ier, 0600, show_ier, store_ier), +- _SYSDEV_ATTR(sier, 0600, show_sier, store_sier), +- _SYSDEV_ATTR(siar, 0600, show_siar, store_siar), +- _SYSDEV_ATTR(tsr0, 0600, show_tsr0, store_tsr0), +- _SYSDEV_ATTR(tsr1, 0600, show_tsr1, store_tsr1), +- _SYSDEV_ATTR(tsr2, 0600, show_tsr2, store_tsr2), +- _SYSDEV_ATTR(tsr3, 0600, show_tsr3, store_tsr3), ++ __ATTR(hid0, 0600, show_hid0, store_hid0), ++ __ATTR(hid1, 0600, show_hid1, store_hid1), ++ __ATTR(hid4, 0600, show_hid4, store_hid4), ++ __ATTR(hid5, 0600, show_hid5, store_hid5), ++ __ATTR(ima0, 0600, show_ima0, store_ima0), ++ __ATTR(ima1, 0600, show_ima1, store_ima1), ++ __ATTR(ima2, 0600, show_ima2, store_ima2), ++ __ATTR(ima3, 0600, show_ima3, store_ima3), ++ __ATTR(ima4, 0600, show_ima4, store_ima4), ++ __ATTR(ima5, 0600, show_ima5, store_ima5), ++ __ATTR(ima6, 0600, show_ima6, store_ima6), ++ __ATTR(ima7, 0600, show_ima7, store_ima7), ++ __ATTR(ima8, 0600, show_ima8, store_ima8), ++ __ATTR(ima9, 0600, show_ima9, store_ima9), ++ __ATTR(imaat, 0600, show_imaat, store_imaat), ++ __ATTR(btcr, 0600, show_btcr, store_btcr), ++ __ATTR(pccr, 0600, show_pccr, store_pccr), ++ __ATTR(rpccr, 0600, show_rpccr, store_rpccr), ++ __ATTR(der, 0600, show_der, store_der), ++ __ATTR(mer, 0600, show_mer, store_mer), ++ __ATTR(ber, 0600, show_ber, store_ber), ++ __ATTR(ier, 0600, show_ier, store_ier), ++ __ATTR(sier, 0600, show_sier, store_sier), ++ __ATTR(siar, 0600, show_siar, store_siar), ++ __ATTR(tsr0, 0600, show_tsr0, store_tsr0), ++ __ATTR(tsr1, 0600, show_tsr1, store_tsr1), ++ __ATTR(tsr2, 0600, show_tsr2, store_tsr2), ++ __ATTR(tsr3, 0600, show_tsr3, store_tsr3), + #endif /* CONFIG_DEBUG_KERNEL */ + }; + #endif /* HAS_PPC_PMC_PA6T */ +@@ -354,14 +353,14 @@ static struct sysdev_attribute pa6t_attrs[] = { + static void __cpuinit register_cpu_online(unsigned int cpu) + { + struct cpu *c = &per_cpu(cpu_devices, cpu); +- struct sys_device *s = &c->sysdev; +- struct sysdev_attribute *attrs, *pmc_attrs; ++ struct device *s = &c->dev; ++ struct device_attribute *attrs, *pmc_attrs; + int i, nattrs; + + #ifdef CONFIG_PPC64 + if (!firmware_has_feature(FW_FEATURE_ISERIES) && + cpu_has_feature(CPU_FTR_SMT)) +- sysdev_create_file(s, &attr_smt_snooze_delay); ++ device_create_file(s, &dev_attr_smt_snooze_delay); + #endif + + /* PMC stuff */ +@@ -369,14 +368,14 @@ static void __cpuinit register_cpu_online(unsigned int cpu) + #ifdef HAS_PPC_PMC_IBM + case PPC_PMC_IBM: + attrs = ibm_common_attrs; +- nattrs = sizeof(ibm_common_attrs) / sizeof(struct sysdev_attribute); ++ nattrs = sizeof(ibm_common_attrs) / sizeof(struct device_attribute); + pmc_attrs = classic_pmc_attrs; + break; + #endif /* HAS_PPC_PMC_IBM */ + #ifdef HAS_PPC_PMC_G4 + case PPC_PMC_G4: + attrs = g4_common_attrs; +- nattrs = sizeof(g4_common_attrs) / sizeof(struct sysdev_attribute); ++ nattrs = sizeof(g4_common_attrs) / sizeof(struct device_attribute); + pmc_attrs = classic_pmc_attrs; + break; + #endif /* HAS_PPC_PMC_G4 */ +@@ -384,7 +383,7 @@ static void __cpuinit register_cpu_online(unsigned int cpu) + case PPC_PMC_PA6T: + /* PA Semi starts counting at PMC0 */ + attrs = pa6t_attrs; +- nattrs = sizeof(pa6t_attrs) / sizeof(struct sysdev_attribute); ++ nattrs = sizeof(pa6t_attrs) / sizeof(struct device_attribute); + pmc_attrs = NULL; + break; + #endif /* HAS_PPC_PMC_PA6T */ +@@ -395,27 +394,27 @@ static void __cpuinit register_cpu_online(unsigned int cpu) + } + + for (i = 0; i < nattrs; i++) +- sysdev_create_file(s, &attrs[i]); ++ device_create_file(s, &attrs[i]); + + if (pmc_attrs) + for (i = 0; i < cur_cpu_spec->num_pmcs; i++) +- sysdev_create_file(s, &pmc_attrs[i]); ++ device_create_file(s, &pmc_attrs[i]); + + #ifdef CONFIG_PPC64 + if (cpu_has_feature(CPU_FTR_MMCRA)) +- sysdev_create_file(s, &attr_mmcra); ++ device_create_file(s, &dev_attr_mmcra); + + if (cpu_has_feature(CPU_FTR_PURR)) { + if (!firmware_has_feature(FW_FEATURE_LPAR)) +- add_write_permission_dev_attr(&attr_purr); +- sysdev_create_file(s, &attr_purr); ++ add_write_permission_dev_attr(&dev_attr_purr); ++ device_create_file(s, &dev_attr_purr); + } + + if (cpu_has_feature(CPU_FTR_SPURR)) +- sysdev_create_file(s, &attr_spurr); ++ device_create_file(s, &dev_attr_spurr); + + if (cpu_has_feature(CPU_FTR_DSCR)) +- sysdev_create_file(s, &attr_dscr); ++ device_create_file(s, &dev_attr_dscr); + #endif /* CONFIG_PPC64 */ + + cacheinfo_cpu_online(cpu); +@@ -425,8 +424,8 @@ static void __cpuinit register_cpu_online(unsigned int cpu) + static void unregister_cpu_online(unsigned int cpu) + { + struct cpu *c = &per_cpu(cpu_devices, cpu); +- struct sys_device *s = &c->sysdev; +- struct sysdev_attribute *attrs, *pmc_attrs; ++ struct device *s = &c->dev; ++ struct device_attribute *attrs, *pmc_attrs; + int i, nattrs; + + BUG_ON(!c->hotpluggable); +@@ -434,7 +433,7 @@ static void unregister_cpu_online(unsigned int cpu) + #ifdef CONFIG_PPC64 + if (!firmware_has_feature(FW_FEATURE_ISERIES) && + cpu_has_feature(CPU_FTR_SMT)) +- sysdev_remove_file(s, &attr_smt_snooze_delay); ++ device_remove_file(s, &dev_attr_smt_snooze_delay); + #endif + + /* PMC stuff */ +@@ -442,14 +441,14 @@ static void unregister_cpu_online(unsigned int cpu) + #ifdef HAS_PPC_PMC_IBM + case PPC_PMC_IBM: + attrs = ibm_common_attrs; +- nattrs = sizeof(ibm_common_attrs) / sizeof(struct sysdev_attribute); ++ nattrs = sizeof(ibm_common_attrs) / sizeof(struct device_attribute); + pmc_attrs = classic_pmc_attrs; + break; + #endif /* HAS_PPC_PMC_IBM */ + #ifdef HAS_PPC_PMC_G4 + case PPC_PMC_G4: + attrs = g4_common_attrs; +- nattrs = sizeof(g4_common_attrs) / sizeof(struct sysdev_attribute); ++ nattrs = sizeof(g4_common_attrs) / sizeof(struct device_attribute); + pmc_attrs = classic_pmc_attrs; + break; + #endif /* HAS_PPC_PMC_G4 */ +@@ -457,7 +456,7 @@ static void unregister_cpu_online(unsigned int cpu) + case PPC_PMC_PA6T: + /* PA Semi starts counting at PMC0 */ + attrs = pa6t_attrs; +- nattrs = sizeof(pa6t_attrs) / sizeof(struct sysdev_attribute); ++ nattrs = sizeof(pa6t_attrs) / sizeof(struct device_attribute); + pmc_attrs = NULL; + break; + #endif /* HAS_PPC_PMC_PA6T */ +@@ -468,24 +467,24 @@ static void unregister_cpu_online(unsigned int cpu) + } + + for (i = 0; i < nattrs; i++) +- sysdev_remove_file(s, &attrs[i]); ++ device_remove_file(s, &attrs[i]); + + if (pmc_attrs) + for (i = 0; i < cur_cpu_spec->num_pmcs; i++) +- sysdev_remove_file(s, &pmc_attrs[i]); ++ device_remove_file(s, &pmc_attrs[i]); + + #ifdef CONFIG_PPC64 + if (cpu_has_feature(CPU_FTR_MMCRA)) +- sysdev_remove_file(s, &attr_mmcra); ++ device_remove_file(s, &dev_attr_mmcra); + + if (cpu_has_feature(CPU_FTR_PURR)) +- sysdev_remove_file(s, &attr_purr); ++ device_remove_file(s, &dev_attr_purr); + + if (cpu_has_feature(CPU_FTR_SPURR)) +- sysdev_remove_file(s, &attr_spurr); ++ device_remove_file(s, &dev_attr_spurr); + + if (cpu_has_feature(CPU_FTR_DSCR)) +- sysdev_remove_file(s, &attr_dscr); ++ device_remove_file(s, &dev_attr_dscr); + #endif /* CONFIG_PPC64 */ + + cacheinfo_cpu_offline(cpu); +@@ -537,70 +536,70 @@ static struct notifier_block __cpuinitdata sysfs_cpu_nb = { + + static DEFINE_MUTEX(cpu_mutex); + +-int cpu_add_sysdev_attr(struct sysdev_attribute *attr) ++int cpu_add_dev_attr(struct device_attribute *attr) + { + int cpu; + + mutex_lock(&cpu_mutex); + + for_each_possible_cpu(cpu) { +- sysdev_create_file(get_cpu_sysdev(cpu), attr); ++ device_create_file(get_cpu_device(cpu), attr); + } + + mutex_unlock(&cpu_mutex); + return 0; + } +-EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr); ++EXPORT_SYMBOL_GPL(cpu_add_dev_attr); + +-int cpu_add_sysdev_attr_group(struct attribute_group *attrs) ++int cpu_add_dev_attr_group(struct attribute_group *attrs) + { + int cpu; +- struct sys_device *sysdev; ++ struct device *dev; + int ret; + + mutex_lock(&cpu_mutex); + + for_each_possible_cpu(cpu) { +- sysdev = get_cpu_sysdev(cpu); +- ret = sysfs_create_group(&sysdev->kobj, attrs); ++ dev = get_cpu_device(cpu); ++ ret = sysfs_create_group(&dev->kobj, attrs); + WARN_ON(ret != 0); + } + + mutex_unlock(&cpu_mutex); + return 0; + } +-EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr_group); ++EXPORT_SYMBOL_GPL(cpu_add_dev_attr_group); + + +-void cpu_remove_sysdev_attr(struct sysdev_attribute *attr) ++void cpu_remove_dev_attr(struct device_attribute *attr) + { + int cpu; + + mutex_lock(&cpu_mutex); + + for_each_possible_cpu(cpu) { +- sysdev_remove_file(get_cpu_sysdev(cpu), attr); ++ device_remove_file(get_cpu_device(cpu), attr); + } + + mutex_unlock(&cpu_mutex); + } +-EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr); ++EXPORT_SYMBOL_GPL(cpu_remove_dev_attr); + +-void cpu_remove_sysdev_attr_group(struct attribute_group *attrs) ++void cpu_remove_dev_attr_group(struct attribute_group *attrs) + { + int cpu; +- struct sys_device *sysdev; ++ struct device *dev; + + mutex_lock(&cpu_mutex); + + for_each_possible_cpu(cpu) { +- sysdev = get_cpu_sysdev(cpu); +- sysfs_remove_group(&sysdev->kobj, attrs); ++ dev = get_cpu_device(cpu); ++ sysfs_remove_group(&dev->kobj, attrs); + } + + mutex_unlock(&cpu_mutex); + } +-EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr_group); ++EXPORT_SYMBOL_GPL(cpu_remove_dev_attr_group); + + + /* NUMA stuff */ +@@ -614,7 +613,7 @@ static void register_nodes(void) + register_one_node(i); + } + +-int sysfs_add_device_to_node(struct sys_device *dev, int nid) ++int sysfs_add_device_to_node(struct device *dev, int nid) + { + struct node *node = &node_devices[nid]; + return sysfs_create_link(&node->sysdev.kobj, &dev->kobj, +@@ -622,7 +621,7 @@ int sysfs_add_device_to_node(struct sys_device *dev, int nid) + } + EXPORT_SYMBOL_GPL(sysfs_add_device_to_node); + +-void sysfs_remove_device_from_node(struct sys_device *dev, int nid) ++void sysfs_remove_device_from_node(struct device *dev, int nid) + { + struct node *node = &node_devices[nid]; + sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj)); +@@ -638,14 +637,14 @@ static void register_nodes(void) + #endif + + /* Only valid if CPU is present. */ +-static ssize_t show_physical_id(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t show_physical_id(struct device *dev, ++ struct device_attribute *attr, char *buf) + { +- struct cpu *cpu = container_of(dev, struct cpu, sysdev); ++ struct cpu *cpu = container_of(dev, struct cpu, dev); + +- return sprintf(buf, "%d\n", get_hard_smp_processor_id(cpu->sysdev.id)); ++ return sprintf(buf, "%d\n", get_hard_smp_processor_id(cpu->dev.id)); + } +-static SYSDEV_ATTR(physical_id, 0444, show_physical_id, NULL); ++static DEVICE_ATTR(physical_id, 0444, show_physical_id, NULL); + + static int __init topology_init(void) + { +@@ -670,7 +669,7 @@ static int __init topology_init(void) + if (cpu_online(cpu) || c->hotpluggable) { + register_cpu(c, cpu); + +- sysdev_create_file(&c->sysdev, &attr_physical_id); ++ device_create_file(&c->dev, &dev_attr_physical_id); + } + + if (cpu_online(cpu)) +diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c +index 9844662..5dd99df 100644 +--- a/arch/powerpc/kernel/traps.c ++++ b/arch/powerpc/kernel/traps.c +@@ -928,6 +928,14 @@ static int emulate_instruction(struct pt_regs *regs) + return emulate_isel(regs, instword); + } + ++ /* Emulate lwsync (Lightweight Sync) instruction */ ++ if (instword == PPC_INST_LWSYNC) { ++ PPC_WARN_EMULATED(lwsync, regs); ++ /* This is probably more pessimistic than required */ ++ mb(); ++ return 0; ++ } ++ + #ifdef CONFIG_PPC64 + /* Emulate the mfspr rD, DSCR. */ + if (((instword & PPC_INST_MFSPR_DSCR_MASK) == PPC_INST_MFSPR_DSCR) && +@@ -1488,15 +1496,24 @@ void unrecoverable_exception(struct pt_regs *regs) + die("Unrecoverable exception", regs, SIGABRT); + } + +-#ifdef CONFIG_BOOKE_WDT ++#if defined(CONFIG_BOOKE_WDT) || defined(CONFIG_BOOKE_WDT_MODULE) + /* +- * Default handler for a Watchdog exception, +- * spins until a reboot occurs ++ * Default handler for a Watchdog exception. + */ + void __attribute__ ((weak)) WatchdogHandler(struct pt_regs *regs) + { + /* Generic WatchdogHandler, implement your own */ + mtspr(SPRN_TCR, mfspr(SPRN_TCR)&(~TCR_WIE)); ++ ++ /* Show a stack backtrace for current CPU. */ ++ if (regs) { ++ printk(KERN_INFO "CPU%d:\n", smp_processor_id()); ++ show_regs(regs); ++ } ++ ++ /* Attempt to sync all mounted file systems */ ++ emergency_sync(); ++ + return; + } + +@@ -1542,6 +1559,7 @@ struct ppc_emulated ppc_emulated = { + WARN_EMULATED_SETUP(spe), + WARN_EMULATED_SETUP(string), + WARN_EMULATED_SETUP(unaligned), ++ WARN_EMULATED_SETUP(lwsync), + #ifdef CONFIG_MATH_EMULATION + WARN_EMULATED_SETUP(math), + #elif defined(CONFIG_8XX_MINIMAL_FPEMU) +diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c +index f4b78a3..98f947c 100644 +--- a/arch/powerpc/mm/numa.c ++++ b/arch/powerpc/mm/numa.c +@@ -1462,7 +1462,7 @@ int arch_update_cpu_topology(void) + { + int cpu, nid, old_nid; + unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0}; +- struct sys_device *sysdev; ++ struct device *dev; + + for_each_cpu(cpu,&cpu_associativity_changes_mask) { + vphn_get_associativity(cpu, associativity); +@@ -1483,9 +1483,9 @@ int arch_update_cpu_topology(void) + register_cpu_under_node(cpu, nid); + put_online_cpus(); + +- sysdev = get_cpu_sysdev(cpu); +- if (sysdev) +- kobject_uevent(&sysdev->kobj, KOBJ_CHANGE); ++ dev = get_cpu_device(cpu); ++ if (dev) ++ kobject_uevent(&dev->kobj, KOBJ_CHANGE); + } + + return 1; +diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig +index d7946be..0b37a01 100644 +--- a/arch/powerpc/platforms/85xx/Kconfig ++++ b/arch/powerpc/platforms/85xx/Kconfig +@@ -181,6 +181,8 @@ config P2041_RDB + select GPIO_MPC8XXX + select HAS_RAPIDIO + select PPC_EPAPR_HV_PIC ++ select HAS_FSL_PAMU ++ select HAS_FSL_QBMAN + help + This option enables support for the P2041 RDB board + +@@ -194,6 +196,9 @@ config P3041_DS + select GPIO_MPC8XXX + select HAS_RAPIDIO + select PPC_EPAPR_HV_PIC ++ select HAS_FSL_PAMU ++ select HAS_FSL_QBMAN ++ select FSL_HYDRA_DS_MDIO if PHYLIB + help + This option enables support for the P3041 DS board + +@@ -222,6 +227,130 @@ config P4080_DS + help + This option enables support for the P4080 DS board + ++config ACCTON_AS4600_54T ++ bool "Accton Technology Corporation AS4600_54T" ++ select DEFAULT_UIMAGE ++ help ++ This option enables support for the ACCTON AS4600_54T networking platform ++ ++config ACCTON_AS5610_52X ++ bool "Accton Technology Corporation AS5610_52X" ++ select DEFAULT_UIMAGE ++ help ++ This option enables support for the ACCTON AS5610_52X networking platform ++ ++config ACCTON_AS6701_32X ++ bool "Accton Technology Corporation AS6701-32X" ++ select DEFAULT_UIMAGE ++ help ++ This option enables support for the Accton AS6701-32X networking platform ++ ++config ACCTON_5652 ++ bool "Accton Technology Corporation ES5652BT1" ++ select DEFAULT_UIMAGE ++ help ++ This option enables support for the ACCTON ES5652BT1 networking platform ++ ++config BCM98548XMC ++ bool "Broadcom BCM98548XMC" ++ select DEFAULT_UIMAGE ++ help ++ This option enables support for the Broadcom BCM98548XMC board used on reference platforms ++ ++config CEL_P2020 ++ bool "Celestica P2020" ++ select DEFAULT_UIMAGE ++ help ++ This option enables support for Celestica P2020 based ++ networking platforms ++ ++config CEL_REDSTONE ++ bool "Celestica Redstone" ++ select DEFAULT_UIMAGE ++ select CEL_P2020 ++ help ++ This option enables support for the Celestica Redstone 48x10G ++ 4x40G networking platform ++ ++config CEL_KENNISIS ++ bool "Celestica Kennisis" ++ select DEFAULT_UIMAGE ++ select CEL_P2020 ++ help ++ This option enables support for the Celestica Kennisis 48x1G ++ 4x10G networking platform ++ ++config CEL_SMALLSTONE ++ bool "Celestica Smallstone" ++ select DEFAULT_UIMAGE ++ select CEL_P2020 ++ help ++ This option enables support for the Celestica Smallstone ++ 32x40G networking platform ++ ++config CUMULUS_P2020 ++ bool "Cumulus Networks P2020" ++ select DEFAULT_UIMAGE ++ help ++ This option enables support for the Cumulus P2020 networking platform ++ ++config DNI_6448 ++ bool "Delta Networks 6448" ++ select DEFAULT_UIMAGE ++ help ++ This option enables support for the DNI-6448 networking platform ++ ++config DNI_7448 ++ bool "Delta Networks 7448" ++ select DEFAULT_UIMAGE ++ help ++ This option enables support for the DNI-7448 networking platform ++ ++config DNI_C7448N ++ bool "Delta Networks C7448N" ++ select DEFAULT_UIMAGE ++ help ++ This option enables support for the DNI-C7448N networking platform ++ ++config QUANTA_LB8 ++ bool "Quanta Computer LB8" ++ select DEFAULT_UIMAGE ++ select SWIOTLB ++ help ++ Enable support for the Quanta Computer LB8 48x10GE networking platform ++ ++config QUANTA_LB9 ++ bool "Quanta Computer LB9" ++ select DEFAULT_UIMAGE ++ help ++ Enable support for the Quanta Computer LB9 48x1G networking platform ++ ++config QUANTA_LY2_LY2R ++ bool "Quanta Computer LY2 and LY2R" ++ select DEFAULT_UIMAGE ++ help ++ Enable support for the Quanta Computer LY2 based networking platforms ++ ++config QUANTA_LY2 ++ bool "Quanta Computer LY2" ++ select DEFAULT_UIMAGE ++ select QUANTA_LY2_LY2R ++ help ++ Enable support for the Quanta Computer LY2 48x10GE networking platform ++ ++config QUANTA_LY2R ++ bool "Quanta Computer LY2R" ++ select DEFAULT_UIMAGE ++ select QUANTA_LY2_LY2R ++ help ++ Enable support for the Quanta Computer LY2R 48x10GE networking platform ++ ++config QUANTA_LY6_P2020 ++ bool "Quanta Computer LY6, P2020" ++ select DEFAULT_UIMAGE ++ help ++ Enable support for the Quanta Computer LY6 32x40G networking platform ++ + endif # PPC32 + + config P5020_DS +@@ -235,6 +364,9 @@ config P5020_DS + select GPIO_MPC8XXX + select HAS_RAPIDIO + select PPC_EPAPR_HV_PIC ++ select HAS_FSL_PAMU ++ select HAS_FSL_QBMAN ++ select FSL_HYDRA_DS_MDIO if PHYLIB + help + This option enables support for the P5020 DS board + +diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile +index bc5acb9..c4653e2 100644 +--- a/arch/powerpc/platforms/85xx/Makefile ++++ b/arch/powerpc/platforms/85xx/Makefile +@@ -25,3 +25,17 @@ obj-$(CONFIG_SBC8548) += sbc8548.o + obj-$(CONFIG_SOCRATES) += socrates.o socrates_fpga_pic.o + obj-$(CONFIG_KSI8560) += ksi8560.o + obj-$(CONFIG_XES_MPC85xx) += xes_mpc85xx.o ++obj-$(CONFIG_ACCTON_AS4600_54T) += accton_as4600_54t.o ++obj-$(CONFIG_ACCTON_AS5610_52X) += accton_as5610_52x.o ++obj-$(CONFIG_ACCTON_AS6701_32X) += accton_as6701_32x.o ++obj-$(CONFIG_ACCTON_5652) += accton_5652.o ++obj-$(CONFIG_BCM98548XMC) += bcm98548xmc.o ++obj-$(CONFIG_CEL_P2020) += cel_p2020.o ++obj-$(CONFIG_CUMULUS_P2020) += cumulus_p2020.o ++obj-$(CONFIG_DNI_6448) += dni_6448.o ++obj-$(CONFIG_DNI_7448) += dni_7448.o ++obj-$(CONFIG_DNI_C7448N) += dni_c7448n.o ++obj-$(CONFIG_QUANTA_LB8) += quanta_lb8.o ++obj-$(CONFIG_QUANTA_LB9) += quanta_lb9.o ++obj-$(CONFIG_QUANTA_LY2_LY2R) += quanta_ly2_ly2r.o ++obj-$(CONFIG_QUANTA_LY6_P2020) += quanta_ly6_p2020.o +diff --git a/arch/powerpc/platforms/85xx/accton_5652.c b/arch/powerpc/platforms/85xx/accton_5652.c +new file mode 100644 +index 0000000..6192a2c +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/accton_5652.c +@@ -0,0 +1,217 @@ ++/* ++ * Accton es5652bt1 setup and early boot code plus other random bits. ++ * ++ * Copyright 2012 Cumulus Networks, 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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++// #undef DEBUG ++ ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++/* ++ * Enough of the CPLD to reset the system... full driver loads as a module ++*/ ++static uint8_t __iomem * cpld_regs; ++static uint32_t CPLD_RESET_REG = 0x10; ++ ++/******************************************************************************* ++ * ++ * Platform initialization functions ++ * ++ ******************************************************************************* ++*/ ++ ++/* ++ * Initialize the interrupt controller ++ */ ++static void __init accton_5652_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np; ++ ++ np = of_find_node_by_type(NULL, "open-pic"); ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | ++ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | ++ MPIC_SINGLE_DEST_CPU, ++ 0, 256, " OpenPIC "); ++ ++ BUG_ON(mpic == NULL); ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++#ifdef CONFIG_SMP ++extern void __init mpc85xx_smp_init(void); ++#endif ++ ++static void __init accton_5652_setup_arch(void) ++{ ++ struct device_node *cpu; ++ const unsigned int *fp; ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ struct device_node *cpld; ++ ++ if (ppc_md.progress) ++ ppc_md.progress("accton_5652_setup_arch()", 0); ++ ++ cpu = of_find_node_by_type(NULL, "cpu"); ++ if (cpu != 0) { ++ fp = of_get_property(cpu, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(cpu); ++ } ++ ++#ifdef CONFIG_PCI ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8548-pcie")) ++ fsl_add_bridge(np, 0); ++ } ++#endif ++ ++ cpld = of_find_compatible_node(NULL, NULL, "accton,5652-cpld"); ++ if (!cpld) { ++ printk(KERN_ERR "Can not find accton,5652-cpld node in device tree\n"); ++ cpld_regs = NULL; ++ } else { ++ cpld_regs = of_iomap(cpld, 0); ++ of_node_put(cpld); ++ } ++ ++ powersave_nap = 0; ++ ++#ifdef CONFIG_SMP ++ mpc85xx_smp_init(); ++#endif ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++} ++ ++static struct of_device_id __initdata accton_5652_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ { .compatible = "gianfar", }, ++ {}, ++}; ++ ++static int __init accton_5652_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, accton_5652_ids, NULL); ++} ++machine_device_initcall(accton_5652, accton_5652_publish_devices); ++ ++static void accton_5652_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu Pll setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++/* ++ * Platform specific restart... need to use the CPLD ++ */ ++static void accton_5652_restart(char *cmd) ++{ ++ printk (KERN_EMERG "Reset via the platform CPLD\n"); ++ ++ local_irq_disable(); ++ writeb(0, (cpld_regs + CPLD_RESET_REG)); ++ while (1); ++} ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init accton_5652_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "accton,5652")) ++ return 1; ++ ++ return 0; ++} ++ ++define_machine(accton_5652) { ++ .name = "Accton Technology Corporation ES5652BT1", ++ .probe = accton_5652_probe, ++ .setup_arch = accton_5652_setup_arch, ++ .init_IRQ = accton_5652_pic_init, ++ .show_cpuinfo = accton_5652_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = accton_5652_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/accton_as4600_54t.c b/arch/powerpc/platforms/85xx/accton_as4600_54t.c +new file mode 100644 +index 0000000..967698c +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/accton_as4600_54t.c +@@ -0,0 +1,215 @@ ++/* ++ * Accton as4600_54t setup and early boot code plus other random bits. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the 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 ++#include ++#include ++ ++#include ++#include ++ ++// #undef DEBUG ++ ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++/* ++ * Enough of the CPLD to reset the system... full driver loads as a module ++*/ ++static uint8_t __iomem * cpld_regs; ++static uint32_t CPLD_RESET_REG = 0x01; ++ ++/******************************************************************************* ++ * ++ * Platform initialization functions ++ * ++ ******************************************************************************* ++*/ ++ ++/* ++ * Initialize the interrupt controller ++ */ ++static void __init accton_as4600_54t_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np; ++ ++ np = of_find_node_by_type(NULL, "open-pic"); ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | ++ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | ++ MPIC_SINGLE_DEST_CPU, ++ 0, 256, " OpenPIC "); ++ ++ BUG_ON(mpic == NULL); ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++#ifdef CONFIG_SMP ++extern void __init mpc85xx_smp_init(void); ++#endif ++ ++static void __init accton_as4600_54t_setup_arch(void) ++{ ++ struct device_node *cpu; ++ const unsigned int *fp; ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ struct device_node *cpld; ++ ++ if (ppc_md.progress) ++ ppc_md.progress("accton_as4600_54t_setup_arch()", 0); ++ ++ cpu = of_find_node_by_type(NULL, "cpu"); ++ if (cpu != 0) { ++ fp = of_get_property(cpu, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(cpu); ++ } ++ ++#ifdef CONFIG_PCI ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8548-pcie")) ++ fsl_add_bridge(np, 0); ++ } ++#endif ++ ++ cpld = of_find_compatible_node(NULL, NULL, "accton,as4600_54t-cpld"); ++ if (!cpld) { ++ printk(KERN_ERR "Can not find accton,as4600_54t-cpld node in device tree\n"); ++ cpld_regs = NULL; ++ } else { ++ cpld_regs = of_iomap(cpld, 0); ++ of_node_put(cpld); ++ } ++ ++ powersave_nap = 0; ++ ++#ifdef CONFIG_SMP ++ mpc85xx_smp_init(); ++#endif ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++} ++ ++static struct of_device_id __initdata accton_as4600_54t_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ { .compatible = "gianfar", }, ++ {}, ++}; ++ ++static int __init accton_as4600_54t_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, accton_as4600_54t_ids, NULL); ++} ++machine_device_initcall(as4600_54t, accton_as4600_54t_publish_devices); ++ ++static void accton_as4600_54t_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu Pll setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++/* ++ * Platform specific restart... need to use the CPLD ++ */ ++static void accton_as4600_54t_restart(char *cmd) ++{ ++ printk (KERN_EMERG "Reset via the platform CPLD\n"); ++ ++ local_irq_disable(); ++ writeb(0x7F, (cpld_regs + CPLD_RESET_REG)); ++ while (1); ++} ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init accton_as4600_54t_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "accton,as4600_54t")) ++ return 1; ++ ++ return 0; ++} ++ ++define_machine(as4600_54t) { ++ .name = "Accton Technology Corporation AS4600_54T", ++ .probe = accton_as4600_54t_probe, ++ .setup_arch = accton_as4600_54t_setup_arch, ++ .init_IRQ = accton_as4600_54t_pic_init, ++ .show_cpuinfo = accton_as4600_54t_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = accton_as4600_54t_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/accton_as5610_52x.c b/arch/powerpc/platforms/85xx/accton_as5610_52x.c +new file mode 100644 +index 0000000..a19d35f +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/accton_as5610_52x.c +@@ -0,0 +1,188 @@ ++/* ++ * Accton as5610_52x setup and early boot code plus other random bits. ++ * ++ * Copyright 2014 Cumulus Networks, 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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++// #undef DEBUG ++ ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++/******************************************************************************* ++ * ++ * Platform initialization functions ++ * ++ ******************************************************************************* ++*/ ++ ++/* ++ * Initialize the interrupt controller ++ */ ++static void __init as5610_52x_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np; ++ ++ np = of_find_node_by_type(NULL, "open-pic"); ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | ++ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | ++ MPIC_SINGLE_DEST_CPU, ++ 0, 256, " OpenPIC "); ++ ++ BUG_ON(mpic == NULL); ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++#ifdef CONFIG_SMP ++extern void __init mpc85xx_smp_init(void); ++#endif ++ ++static void __init as5610_52x_setup_arch(void) ++{ ++ struct device_node *cpu; ++ const unsigned int *fp; ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ if (ppc_md.progress) ++ ppc_md.progress("as5610_52x_setup_arch()", 0); ++ ++ cpu = of_find_node_by_type(NULL, "cpu"); ++ if (cpu != 0) { ++ fp = of_get_property(cpu, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(cpu); ++ } ++ ++#ifdef CONFIG_PCI ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8548-pcie")) ++ fsl_add_bridge(np, 0); ++ } ++#endif ++ powersave_nap = 0; ++ ++#ifdef CONFIG_SMP ++ mpc85xx_smp_init(); ++#endif ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++} ++ ++static struct of_device_id __initdata as5610_52x_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ { .compatible = "gianfar", }, ++ {}, ++}; ++ ++static int __init as5610_52x_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, as5610_52x_ids, NULL); ++} ++machine_device_initcall(as5610_52x, as5610_52x_publish_devices); ++ ++static void as5610_52x_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu Pll setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init as5610_52x_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "accton,as5610_52x")) ++ return 1; ++ ++ return 0; ++} ++ ++define_machine(as5610_52x) { ++ .name = "Accton Technology Corporation AS5610_52X", ++ .probe = as5610_52x_probe, ++ .setup_arch = as5610_52x_setup_arch, ++ .init_IRQ = as5610_52x_pic_init, ++ .show_cpuinfo = as5610_52x_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = fsl_rstcr_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/accton_as6700_32x.c b/arch/powerpc/platforms/85xx/accton_as6700_32x.c +new file mode 100644 +index 0000000..c3c4474 +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/accton_as6700_32x.c +@@ -0,0 +1,77 @@ ++/* ++ * Accton AS6700_32X Setup ++ * ++ * Copyright 2011 Freescale Semiconductor 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "corenet_ds.h" ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init accton_as6700_32x_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "accton,as6700_32x")) ++ return 1; ++ ++ return 0; ++} ++ ++static void __init accton_as6700_32x_setup_arch(void) { ++ corenet_ds_setup_arch(); ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++} ++ ++ ++define_machine(accton_as6700_32x) { ++ .name = "Accton AS6700_32X", ++ .probe = accton_as6700_32x_probe, ++ .setup_arch = accton_as6700_32x_setup_arch, ++ .init_IRQ = corenet_ds_pic_init, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_coreint_irq, ++ .restart = fsl_rstcr_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++ .power_save = e500_idle, ++ .init_early = corenet_ds_init_early, ++}; ++ ++machine_device_initcall(accton_as6700_32x, corenet_ds_publish_devices); ++ ++#ifdef CONFIG_SWIOTLB ++machine_arch_initcall(accton_as6700_32x, swiotlb_setup_bus_notifier); ++#endif +diff --git a/arch/powerpc/platforms/85xx/accton_as6701_32x.c b/arch/powerpc/platforms/85xx/accton_as6701_32x.c +new file mode 100644 +index 0000000..aba43c3 +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/accton_as6701_32x.c +@@ -0,0 +1,183 @@ ++/* ++ * Accton AS6701-32X setup and early boot code plus other random bits. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the 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 ++#include ++#include ++ ++#include ++#include ++ ++// #undef DEBUG ++ ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++/******************************************************************************* ++ * ++ * Platform initialization functions ++ * ++ ******************************************************************************* ++*/ ++ ++/* ++ * Initialize the interrupt controller ++ */ ++static void __init as6701_32x_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np; ++ ++ np = of_find_node_by_type(NULL, "open-pic"); ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | ++ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | ++ MPIC_SINGLE_DEST_CPU, ++ 0, 256, " OpenPIC "); ++ ++ BUG_ON(mpic == NULL); ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++#ifdef CONFIG_SMP ++extern void __init mpc85xx_smp_init(void); ++#endif ++ ++static void __init as6701_32x_setup_arch(void) ++{ ++ struct device_node *cpu; ++ const unsigned int *fp; ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ ++ cpu = of_find_node_by_type(NULL, "cpu"); ++ if (cpu != 0) { ++ fp = of_get_property(cpu, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(cpu); ++ } ++ ++#ifdef CONFIG_PCI ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8548-pcie")) ++ fsl_add_bridge(np, 0); ++ } ++#endif ++ powersave_nap = 0; ++ ++#ifdef CONFIG_SMP ++ mpc85xx_smp_init(); ++#endif ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++} ++ ++static struct of_device_id __initdata as6701_32x_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ { .compatible = "gianfar", }, ++ {}, ++}; ++ ++static int __init as6701_32x_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, as6701_32x_ids, NULL); ++} ++machine_device_initcall(as6701_32x, as6701_32x_publish_devices); ++ ++static void as6701_32x_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu Pll setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init as6701_32x_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "accton,as6701_32x")) ++ return 1; ++ ++ return 0; ++} ++ ++define_machine(as6701_32x) { ++ .name = "Accton Technology Corporation AS6701-32X", ++ .probe = as6701_32x_probe, ++ .setup_arch = as6701_32x_setup_arch, ++ .init_IRQ = as6701_32x_pic_init, ++ .show_cpuinfo = as6701_32x_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = fsl_rstcr_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/bcm98548xmc.c b/arch/powerpc/platforms/85xx/bcm98548xmc.c +new file mode 100644 +index 0000000..392f231 +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/bcm98548xmc.c +@@ -0,0 +1,230 @@ ++/* ++ * MPC85xx setup and early boot code plus other random bits. ++ * ++ * Maintained by Kumar Gala (see MAINTAINERS for contact information) ++ * ++ * Copyright 2005 Freescale Semiconductor 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef CONFIG_PCI ++unsigned long isa_io_base = 0; ++unsigned long isa_mem_base = 0; ++#endif ++ ++static void __init bcm98548xmc_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np = NULL; ++ ++ np = of_find_node_by_type(np, "open-pic"); ++ ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, ++ 4, 0, " OpenPIC "); ++ BUG_ON(mpic == NULL); ++ ++ /* Return the mpic node */ ++ of_node_put(np); ++ ++ mpic_assign_isu(mpic, 0, r.start + 0x10200); ++ mpic_assign_isu(mpic, 1, r.start + 0x10280); ++ mpic_assign_isu(mpic, 2, r.start + 0x10300); ++ mpic_assign_isu(mpic, 3, r.start + 0x10380); ++ mpic_assign_isu(mpic, 4, r.start + 0x10400); ++ mpic_assign_isu(mpic, 5, r.start + 0x10480); ++ mpic_assign_isu(mpic, 6, r.start + 0x10500); ++ mpic_assign_isu(mpic, 7, r.start + 0x10580); ++ ++ /* Used only for 8548 so far, but no harm in ++ * allocating them for everyone */ ++ mpic_assign_isu(mpic, 8, r.start + 0x10600); ++ mpic_assign_isu(mpic, 9, r.start + 0x10680); ++ mpic_assign_isu(mpic, 10, r.start + 0x10700); ++ mpic_assign_isu(mpic, 11, r.start + 0x10780); ++ ++ /* External Interrupts */ ++ mpic_assign_isu(mpic, 12, r.start + 0x10000); ++ mpic_assign_isu(mpic, 13, r.start + 0x10080); ++ mpic_assign_isu(mpic, 14, r.start + 0x10100); ++ ++ mpic_init(mpic); ++ ++} ++ ++static struct of_device_id __initdata bcm98548xmc_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ {}, ++}; ++ ++static int __init bcm98548xmc_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, bcm98548xmc_ids, NULL); ++} ++machine_device_initcall(bcm98548xmc, bcm98548xmc_publish_devices); ++ ++static __be32 __iomem *rstcr; ++static __be32 __iomem *rstdr; ++ ++static int __init bcm98548xmc_init_rstcr(void) ++{ ++ /* map reset control register */ ++ printk(KERN_INFO "bcm98548xmc : map reset control register.\n"); ++ rstdr = ioremap(get_immrbase() + 0xE0040, 0xff); ++ rstcr = ioremap(get_immrbase() + 0xE0030, 0xff); ++ return 0; ++} ++ ++/* ++ * Setup the architecture ++ */ ++static void __init bcm98548xmc_setup_arch(void) ++{ ++ struct device_node *cpu; ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ ++ if (ppc_md.progress) ++ ppc_md.progress("bcm98548xmc_setup_arch()", 0); ++ ++ cpu = of_find_node_by_type(NULL, "cpu"); ++ if (cpu != 0) { ++ const unsigned int *fp; ++ ++ fp = of_get_property(cpu, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(cpu); ++ } ++ ++#ifdef CONFIG_PCI ++ for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { ++ struct resource rsrc; ++ of_address_to_resource(np, 0, &rsrc); ++ if ((rsrc.start & 0xfffff) == 0x8000) ++ fsl_add_bridge(np, 1); ++ else ++ fsl_add_bridge(np, 0); ++ } ++#endif ++ ++ powersave_nap = 0; ++ ++ bcm98548xmc_init_rstcr(); ++} ++ ++static void bcm98548xmc_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu Pll setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++void bcm98548xmc_restart(char *cmd) ++{ ++ local_irq_disable(); ++ if (rstcr && rstdr) { ++ /* set reset control register */ ++ out_be32(rstdr, ~0x0); /* HRESET_REQ */ ++ out_be32(rstcr, 0x200); /* HRESET_REQ */ ++ out_be32(rstdr, ~0x1); /* HRESET_REQ */ ++ out_be32(rstdr, ~0x3); /* HRESET_REQ */ ++ } else ++ printk (KERN_EMERG "Error: reset control register not mapped." ++ "Please power cycle board manually!\n"); ++ while(1); ++} ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init bcm98548xmc_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "bcm,BCM98548XMC")) { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++define_machine(bcm98548xmc) { ++ .name = "BCM98548 XMC", ++ .probe = bcm98548xmc_probe, ++ .setup_arch = bcm98548xmc_setup_arch, ++ .init_IRQ = bcm98548xmc_pic_init, ++ .show_cpuinfo = bcm98548xmc_show_cpuinfo, ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = bcm98548xmc_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/cel_p2020.c b/arch/powerpc/platforms/85xx/cel_p2020.c +new file mode 100644 +index 0000000..ec6023f +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/cel_p2020.c +@@ -0,0 +1,230 @@ ++/* ++ * Celestica P2020 setup and early boot code plus other random bits. ++ * ++ * Copyright 2013 Cumulus Networks, Inc. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef CONFIG_EARLY_DMA_ALLOC ++# include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#undef DEBUG ++ ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++/******************************************************************************* ++ * ++ * Platform initialization functions ++ * ++ ******************************************************************************* ++*/ ++ ++/* ++ * Initialize the interrupt controller ++ */ ++static void __init celestica_p2020_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np; ++ ++ np = of_find_node_by_type(NULL, "open-pic"); ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | ++ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | ++ MPIC_SINGLE_DEST_CPU, ++ 0, 256, " OpenPIC "); ++ ++ BUG_ON(mpic == NULL); ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++#ifdef CONFIG_SMP ++extern void __init mpc85xx_smp_init(void); ++#endif ++ ++static void __init celestica_p2020_setup_arch(void) ++{ ++ struct device_node *cpu; ++ const unsigned int *fp; ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ ++ if (ppc_md.progress) ++ ppc_md.progress("celestica_p2020_setup_arch()", 0); ++ ++ cpu = of_find_node_by_type(NULL, "cpu"); ++ if (cpu != 0) { ++ fp = of_get_property(cpu, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(cpu); ++ } ++ ++#ifdef CONFIG_PCI ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8548-pcie")) ++ fsl_add_bridge(np, 0); ++ } ++#endif ++ ++ powersave_nap = 0; ++ ++#ifdef CONFIG_SMP ++ mpc85xx_smp_init(); ++#endif ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++} ++ ++static struct of_device_id __initdata celestica_p2020_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ { .compatible = "gianfar", }, ++ { .compatible = "redstone_cpld234", }, ++ { .compatible = "smallstone_cpld23", }, ++ {}, ++}; ++ ++static int __init celestica_p2020_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, celestica_p2020_ids, NULL); ++} ++ ++machine_device_initcall(cel_kennisis, celestica_p2020_publish_devices); ++machine_device_initcall(cel_redstone, celestica_p2020_publish_devices); ++machine_device_initcall(cel_smallstone, celestica_p2020_publish_devices); ++ ++static void celestica_p2020_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu Pll setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init celestica_kennisis_probe(void) ++{ ++ return of_flat_dt_is_compatible(of_get_flat_dt_root(), "cel,kennisis"); ++} ++ ++static int __init celestica_redstone_probe(void) ++{ ++ return of_flat_dt_is_compatible(of_get_flat_dt_root(), "cel,redstone"); ++} ++ ++static int __init celestica_smallstone_probe(void) ++{ ++ return of_flat_dt_is_compatible(of_get_flat_dt_root(), "cel,smallstone"); ++} ++ ++define_machine(cel_kennisis) { ++ .name = "Celestica, Inc. Kennisis", ++ .probe = celestica_kennisis_probe, ++ .setup_arch = celestica_p2020_setup_arch, ++ .init_IRQ = celestica_p2020_pic_init, ++ .show_cpuinfo = celestica_p2020_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = fsl_rstcr_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; ++ ++define_machine(cel_redstone) { ++ .name = "Celestica, Inc. Redstone", ++ .probe = celestica_redstone_probe, ++ .setup_arch = celestica_p2020_setup_arch, ++ .init_IRQ = celestica_p2020_pic_init, ++ .show_cpuinfo = celestica_p2020_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = fsl_rstcr_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; ++ ++define_machine(cel_smallstone) { ++ .name = "Celestica, Inc. Smallstone", ++ .probe = celestica_smallstone_probe, ++ .setup_arch = celestica_p2020_setup_arch, ++ .init_IRQ = celestica_p2020_pic_init, ++ .show_cpuinfo = celestica_p2020_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = fsl_rstcr_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c +index 802ad11..5b6aebf 100644 +--- a/arch/powerpc/platforms/85xx/corenet_ds.c ++++ b/arch/powerpc/platforms/85xx/corenet_ds.c +@@ -112,6 +112,12 @@ static const struct of_device_id of_device_ids[] __devinitconst = { + .compatible = "simple-bus" + }, + { ++ .compatible = "fsl,dpaa" ++ }, ++ { ++ .compatible = "fsl,srio" ++ }, ++ { + .compatible = "fsl,rapidio-delta", + }, + { +@@ -134,3 +140,32 @@ int __init corenet_ds_publish_devices(void) + { + return of_platform_bus_probe(NULL, of_device_ids, NULL); + } ++ ++/* Early setup is required for large chunks of contiguous (and coarsely-aligned) ++ * memory. The following shoe-horns Qman/Bman "init_early" calls into the ++ * platform setup to let them parse their CCSR nodes early on. */ ++#ifdef CONFIG_FSL_QMAN_CONFIG ++void __init qman_init_early(void); ++#endif ++#ifdef CONFIG_FSL_BMAN_CONFIG ++void __init bman_init_early(void); ++#endif ++#ifdef CONFIG_FSL_PME2_CTRL ++void __init pme2_init_early(void); ++#endif ++ ++__init void corenet_ds_init_early(void) ++{ ++#ifdef CONFIG_FSL_QMAN_CONFIG ++ qman_init_early(); ++#endif ++#ifdef CONFIG_FSL_BMAN_CONFIG ++ bman_init_early(); ++#endif ++#ifdef CONFIG_FSL_PME2_CTRL ++ pme2_init_early(); ++#endif ++#ifdef CONFIG_FSL_USDPAA ++ fsl_usdpaa_init_early(); ++#endif ++} +diff --git a/arch/powerpc/platforms/85xx/corenet_ds.h b/arch/powerpc/platforms/85xx/corenet_ds.h +index ddd700b..a5b63c6 100644 +--- a/arch/powerpc/platforms/85xx/corenet_ds.h ++++ b/arch/powerpc/platforms/85xx/corenet_ds.h +@@ -15,5 +15,6 @@ + extern void __init corenet_ds_pic_init(void); + extern void __init corenet_ds_setup_arch(void); + extern int __init corenet_ds_publish_devices(void); ++extern void __init corenet_ds_init_early(void); + + #endif +diff --git a/arch/powerpc/platforms/85xx/cumulus_p2020.c b/arch/powerpc/platforms/85xx/cumulus_p2020.c +new file mode 100644 +index 0000000..c2e8bf7 +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/cumulus_p2020.c +@@ -0,0 +1,228 @@ ++/* ++ * Copyright 2011 Cumulus Networks, Inc. ++ * ++ * P2020 setup and early boot code plus other random bits. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#undef DEBUG ++ ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++/******************************************************************************* ++ * ++ * Platform initialization functions ++ * ++ ******************************************************************************* ++*/ ++ ++/* ++ * Initialize the interrupt controller ++ */ ++static void __init cumulus_p2020_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np; ++ ++ np = of_find_node_by_type(NULL, "open-pic"); ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | ++ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | ++ MPIC_SINGLE_DEST_CPU, ++ 0, 256, " OpenPIC "); ++ ++ BUG_ON(mpic == NULL); ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++#ifdef CONFIG_SMP ++extern void __init mpc85xx_smp_init(void); ++#endif ++ ++static void __init cumulus_p2020_setup_arch(void) ++{ ++ struct device_node *cpu; ++ const unsigned int *fp; ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ ++ if (ppc_md.progress) ++ ppc_md.progress("cumulus_p2020_setup_arch()", 0); ++ ++ cpu = of_find_node_by_type(NULL, "cpu"); ++ if (cpu != 0) { ++ fp = of_get_property(cpu, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(cpu); ++ } ++ ++#ifdef CONFIG_PCI ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8548-pcie")) ++ fsl_add_bridge(np, 0); ++ } ++#endif ++ ++#ifdef CONFIG_SMP ++ mpc85xx_smp_init(); ++#endif ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++ ++ printk(KERN_INFO "Cumulus P2020 board from Cumulus Networks, Inc.\n"); ++} ++ ++ ++ ++static struct of_device_id __initdata cumulus_p2020_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ { .compatible = "gianfar", }, ++ {}, ++}; ++ ++ ++ ++static int __init cumulus_p2020_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, cumulus_p2020_ids, NULL); ++} ++machine_device_initcall(cumulus_p2020, cumulus_p2020_publish_devices); ++ ++ ++ ++static void cumulus_p2020_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu PLL setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init cumulus_p2020_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "cumulus,cumulus_p2020")) ++ return 1; ++ ++ return 0; ++} ++ ++void cumulus_p2020_restart(char *cmd) ++{ ++ struct device_node *np; ++ struct i2c_client *client; ++ ++ np = of_find_compatible_node(NULL, NULL, "stm,m41st85"); ++ if (np == NULL) { ++ printk(KERN_ERR __FILE__ ": Can't find stm,m41st85\n"); ++ goto newreset; ++ } ++ ++ client = of_find_i2c_device_by_node(np); ++ if (client == NULL) { ++ of_node_put(np); ++ printk(KERN_ERR __FILE__ ": Can't find device by node\n"); ++ goto newreset; ++ } ++ ++ printk(KERN_INFO "Watchdog Reset\n"); ++ // set watchdog for 1/16 of a second ++ i2c_smbus_write_byte_data(client, 0x09, 0x84); ++ // make sure the clock is running ++ i2c_smbus_write_byte_data(client, 0x01, 0x00); ++ ++newreset: ++ // asserts HRESET_REQ which will work on new hardware ++ printk(KERN_INFO "HRESET_REQ\n"); ++ fsl_rstcr_restart(cmd); ++} ++ ++define_machine(cumulus_p2020) { ++ .name = "Cumulus Networks P2020", ++ .probe = cumulus_p2020_probe, ++ .setup_arch = cumulus_p2020_setup_arch, ++ .init_IRQ = cumulus_p2020_pic_init, ++ .show_cpuinfo = cumulus_p2020_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = cumulus_p2020_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/dni_6448.c b/arch/powerpc/platforms/85xx/dni_6448.c +new file mode 100644 +index 0000000..9c99bd9 +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/dni_6448.c +@@ -0,0 +1,225 @@ ++/* ++ * DNI 6448 - MPC8536 setup and early boot code plus other random bits. ++ * ++ * Copyright 2012 Cumulus Networks, 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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#undef DEBUG ++// #define DEBUG ++ ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_ERR "dni-6448:%s: " fmt, __func__, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++/* ++ * Enough of the CPLD to reset the system... full driver loads as a module ++*/ ++static uint8_t __iomem* cpld_regs; ++static uint32_t CPLD_REG_RESET = 0x02000; ++ ++/******************************************************************************* ++ * ++ * Platform initialization functions ++ * ++ ******************************************************************************* ++*/ ++ ++/* ++ * Initialize the interrupt controller ++ */ ++static void __init dni_6448_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np; ++ ++ np = of_find_node_by_type(NULL, "open-pic"); ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | ++ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | ++ MPIC_SINGLE_DEST_CPU, ++ 0, 256, " OpenPIC "); ++ ++ BUG_ON(mpic == NULL); ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++#ifdef CONFIG_SMP ++extern void __init mpc85xx_smp_init(void); ++#endif ++ ++static void __init dni_6448_setup_arch(void) ++{ ++ struct device_node *cpu; ++ const unsigned int *fp; ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ struct device_node *cpld; ++ ++ if (ppc_md.progress) ++ ppc_md.progress("dni_6448_setup_arch()", 0); ++ ++ cpu = of_find_node_by_type(NULL, "cpu"); ++ if (cpu != 0) { ++ fp = of_get_property(cpu, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(cpu); ++ } ++ ++#ifdef CONFIG_PCI ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8548-pcie")) ++ fsl_add_bridge(np, 0); ++ } ++#endif ++ ++ cpld = of_find_compatible_node(NULL, NULL, "dni,6448-cpld"); ++ if (!cpld) { ++ printk(KERN_ERR "Can not find 6448-cpld node in device tree\n"); ++ cpld_regs = NULL; ++ } else { ++ cpld_regs = of_iomap(cpld, 0); ++ of_node_put(cpld); ++ } ++ ++ powersave_nap = 0; ++ ++#ifdef CONFIG_SMP ++ mpc85xx_smp_init(); ++#endif ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++} ++ ++ ++ ++static struct of_device_id __initdata dni_6448_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ { .compatible = "gianfar", }, ++ {}, ++}; ++ ++ ++ ++static int __init dni_6448_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, dni_6448_ids, NULL); ++} ++machine_device_initcall(dni_6448, dni_6448_publish_devices); ++ ++ ++ ++static void dni_6448_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu Pll setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++ ++/* ++ * Platform specific restart... need to use the CPLD ++ */ ++static void dni_6448_restart(char *cmd) ++{ ++ printk (KERN_EMERG "Reset via the platform CPLD\n"); ++ ++ local_irq_disable(); ++ writeb(0, (cpld_regs + CPLD_REG_RESET)); ++ while (1); ++} ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init dni_6448_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "dni,dni_6448")) ++ return 1; ++ ++ return 0; ++} ++ ++define_machine(dni_6448) { ++ .name = "Delta Networks, Inc ET-6448", ++ .probe = dni_6448_probe, ++ .setup_arch = dni_6448_setup_arch, ++ .init_IRQ = dni_6448_pic_init, ++ .show_cpuinfo = dni_6448_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = dni_6448_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/dni_7448.c b/arch/powerpc/platforms/85xx/dni_7448.c +new file mode 100644 +index 0000000..4618bef +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/dni_7448.c +@@ -0,0 +1,261 @@ ++/* ++ * DNI 7448 - P2020 setup and early boot code plus other random bits. ++ * ++ * Copyright 2012 Cumulus Networks, 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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#undef DEBUG ++ ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++/* ++ * Enough of the CPLD to reset the system... full driver loads as a module ++*/ ++static uint8_t __iomem * cpld_regs; ++static uint32_t CPLD_RESET_REG = 0x20; ++ ++/******************************************************************************* ++ * ++ * Platform initialization functions ++ * ++ ******************************************************************************* ++*/ ++ ++/* ++ * Initialize the interrupt controller ++ */ ++static void __init dni_7448_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np; ++ ++ np = of_find_node_by_type(NULL, "open-pic"); ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | ++ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | ++ MPIC_SINGLE_DEST_CPU, ++ 0, 256, " OpenPIC "); ++ ++ BUG_ON(mpic == NULL); ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++#ifdef CONFIG_SMP ++extern void __init mpc85xx_smp_init(void); ++#endif ++ ++static void __init dni_7448_setup_arch(void) ++{ ++ struct device_node *cpu; ++ const unsigned int *fp; ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ struct device_node *cpld; ++#ifdef CONFIG_MMC_SDHCI_OF_ESDHC ++ struct device_node *esdhc; ++ struct property *clk_prop; ++ unsigned int *clk; ++#endif ++ ++ if (ppc_md.progress) ++ ppc_md.progress("dni_7448_setup_arch()", 0); ++ ++ cpu = of_find_node_by_type(NULL, "cpu"); ++ if (cpu != 0) { ++ fp = of_get_property(cpu, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(cpu); ++ } ++ ++#ifdef CONFIG_PCI ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8548-pcie")) ++ fsl_add_bridge(np, 0); ++ } ++#endif ++ ++ cpld = of_find_compatible_node(NULL, NULL, "dni,7448-cpld"); ++ if (!cpld) { ++ printk(KERN_ERR "Can not find 7448-cpld node in device tree\n"); ++ cpld_regs = NULL; ++ } else { ++ cpld_regs = of_iomap(cpld, 0); ++ of_node_put(cpld); ++ } ++ ++#ifdef CONFIG_MMC_SDHCI_OF_ESDHC ++ esdhc = of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc"); ++ if (esdhc != NULL) { ++ clk_prop = of_find_property(esdhc, "clock-frequency", NULL); ++ if (clk_prop != NULL) { ++ /* ++ ** Increase reported SDHC clock-frequency by 2x. ++ ** This will cause the actual hardware bus speed ++ ** to be 2x slower (calculated by driver). ++ ** ++ ** The 2x number is imperical. One box I had ++ ** required a 1.1x increase, while another one ++ ** required a 1.4x increase. Using 2x to ++ ** hopefully never revisit. ++ ** ++ ** The slower hardware bus speed gives the part ++ ** more margin for safe operation. Without this ++ ** fix-up the SDHC will sometimes report CRC ++ ** errors on bus transactions and never recover. ++ */ ++ clk = clk_prop->value; ++ *clk = *clk * 2; ++ } ++ else { ++ printk(KERN_ERR "dni_7448: Can not find SDHC clock-frequency\n"); ++ } ++ of_node_put(esdhc); ++ } ++ else { ++ printk(KERN_ERR "dni_7448: Can not find p2020-esdhc in device tree\n"); ++ } ++#endif ++ powersave_nap = 0; ++ ++#ifdef CONFIG_SMP ++ mpc85xx_smp_init(); ++#endif ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++} ++ ++ ++ ++static struct of_device_id __initdata dni_7448_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ { .compatible = "gianfar", }, ++ {}, ++}; ++ ++ ++ ++static int __init dni_7448_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, dni_7448_ids, NULL); ++} ++machine_device_initcall(dni_7448, dni_7448_publish_devices); ++ ++ ++ ++static void dni_7448_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu Pll setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++ ++/* ++ * Platform specific restart... need to use the CPLD ++ */ ++static void dni_7448_restart(char *cmd) ++{ ++ printk (KERN_EMERG "Reset via the platform CPLD\n"); ++ ++ local_irq_disable(); ++ writeb(0, (cpld_regs + CPLD_RESET_REG)); ++ while (1); ++} ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init dni_7448_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "dni,dni_7448")) ++ return 1; ++ ++ return 0; ++} ++ ++define_machine(dni_7448) { ++ .name = "Delta Networks, Inc ET-7448", ++ .probe = dni_7448_probe, ++ .setup_arch = dni_7448_setup_arch, ++ .init_IRQ = dni_7448_pic_init, ++ .show_cpuinfo = dni_7448_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = dni_7448_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/dni_c7448n.c b/arch/powerpc/platforms/85xx/dni_c7448n.c +new file mode 100644 +index 0000000..d4a5d7a +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/dni_c7448n.c +@@ -0,0 +1,264 @@ ++/* ++ * DNI 7448 - P2020 setup and early boot code plus other random bits. ++ * ++ * Copyright 2014 Cumulus Networks, 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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#undef DEBUG ++ ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++/* ++ * Enough of the CPLD to reset the system... full driver loads as a module ++*/ ++static uint8_t __iomem * cpld_regs; ++static uint32_t CPLD_RESET_REG = 0x20; ++ ++/******************************************************************************* ++ * ++ * Platform initialization functions ++ * ++ ******************************************************************************* ++*/ ++ ++/* ++ * Initialize the interrupt controller ++ */ ++static void __init dni_c7448n_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np; ++ ++ np = of_find_node_by_type(NULL, "open-pic"); ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | ++ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | ++ MPIC_SINGLE_DEST_CPU, ++ 0, 256, " OpenPIC "); ++ ++ BUG_ON(mpic == NULL); ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++#ifdef CONFIG_SMP ++extern void __init mpc85xx_smp_init(void); ++#endif ++ ++static void __init dni_c7448n_setup_arch(void) ++{ ++ struct device_node *cpu; ++ const unsigned int *fp; ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ struct device_node *cpld; ++#ifdef CONFIG_MMC_SDHCI_OF_ESDHC ++ struct device_node *esdhc; ++ struct property *clk_prop; ++ unsigned int *clk; ++#endif ++ ++ if (ppc_md.progress) ++ ppc_md.progress("dni_c7448n_setup_arch()", 0); ++ ++ cpu = of_find_node_by_type(NULL, "cpu"); ++ if (cpu != 0) { ++ fp = of_get_property(cpu, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(cpu); ++ } ++ ++#ifdef CONFIG_PCI ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8548-pcie")) ++ fsl_add_bridge(np, 0); ++ } ++#endif ++ ++ cpld = of_find_compatible_node(NULL, NULL, "dni,c7448n-cpld"); ++ if (!cpld) { ++ printk(KERN_ERR "Can not find c7448n-cpld node in device tree\n"); ++ cpld_regs = NULL; ++ } else { ++ cpld_regs = of_iomap(cpld, 0); ++ of_node_put(cpld); ++ } ++ ++#ifdef CONFIG_MMC_SDHCI_OF_ESDHC ++ esdhc = of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc"); ++ if (esdhc != NULL) { ++ clk_prop = of_find_property(esdhc, "clock-frequency", NULL); ++ if (clk_prop != NULL) { ++ /* ++ ** Increase reported SDHC clock-frequency by 2x. ++ ** This will cause the actual hardware bus speed ++ ** to be 2x slower (calculated by driver). ++ ** ++ ** The 2x number is imperical. One box I had ++ ** required a 1.1x increase, while another one ++ ** required a 1.4x increase. Using 2x to ++ ** hopefully never revisit. ++ ** ++ ** The slower hardware bus speed gives the part ++ ** more margin for safe operation. Without this ++ ** fix-up the SDHC will sometimes report CRC ++ ** errors on bus transactions and never recover. ++ */ ++ clk = clk_prop->value; ++ *clk = *clk * 2; ++ } ++ else { ++ printk(KERN_ERR "dni_c7448n: Can not find SDHC clock-frequency\n"); ++ } ++ of_node_put(esdhc); ++ } ++ else { ++ printk(KERN_ERR "dni_c7448n: Can not find p2020-esdhc in device tree\n"); ++ } ++#endif ++ powersave_nap = 0; ++ ++#ifdef CONFIG_SMP ++ mpc85xx_smp_init(); ++#endif ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++} ++ ++ ++ ++static struct of_device_id __initdata dni_c7448n_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ { .compatible = "gianfar", }, ++ {}, ++}; ++ ++ ++ ++static int __init dni_c7448n_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, dni_c7448n_ids, NULL); ++} ++/*machine_device_initcall(dni_c7448n, dni_c7448n_publish_devices); */ ++machine_device_initcall(c7448n, dni_c7448n_publish_devices); ++ ++ ++ ++static void dni_c7448n_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu Pll setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++ ++/* ++ * Platform specific restart... need to use the CPLD ++ */ ++static void dni_c7448n_restart(char *cmd) ++{ ++ printk (KERN_EMERG "Reset via the platform CPLD\n"); ++ ++ local_irq_disable(); ++ writeb(0, (cpld_regs + CPLD_RESET_REG)); ++ while (1); ++} ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init dni_c7448n_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ printk(KERN_WARNING "probing dni_c7448n...\n"); ++ if (of_flat_dt_is_compatible(root, "dni,c7448n")) ++ return 1; ++ ++ printk(KERN_WARNING "return zero\n"); ++ return 0; ++} ++ ++define_machine(c7448n) { ++ .name = "Delta Networks, Inc C7448N", ++ .probe = dni_c7448n_probe, ++ .setup_arch = dni_c7448n_setup_arch, ++ .init_IRQ = dni_c7448n_pic_init, ++ .show_cpuinfo = dni_c7448n_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = dni_c7448n_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/p2041_rdb.c b/arch/powerpc/platforms/85xx/p2041_rdb.c +index eda6ed5..595670e 100644 +--- a/arch/powerpc/platforms/85xx/p2041_rdb.c ++++ b/arch/powerpc/platforms/85xx/p2041_rdb.c +@@ -79,6 +79,7 @@ define_machine(p2041_rdb) { + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, + .power_save = e500_idle, ++ .init_early = corenet_ds_init_early, + }; + + machine_device_initcall(p2041_rdb, corenet_ds_publish_devices); +diff --git a/arch/powerpc/platforms/85xx/quanta_lb8.c b/arch/powerpc/platforms/85xx/quanta_lb8.c +new file mode 100644 +index 0000000..329cf75 +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/quanta_lb8.c +@@ -0,0 +1,260 @@ ++/* ++ * quanta_lb8 setup and early boot code plus other random bits. ++ * ++ * Copyright 2012 Cumulus Networks, inc. ++ * ++ * Derived from mpc8548cds.c ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#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 ++#include ++#include "quanta_lb8.h" ++ ++/*------------------------------------------------------------------------------ ++ * ++ * General-Purpose IO ++ * ++ * Output Pins : PCI2_AD[15:8], GPOUT[24:31] ++ * Input Pins : PCI2_AD[7:0] ++ * ++ *------------------------------------------------------------------------------ ++ */ ++ ++enum quanta_lb8_gpio { ++ ++ GPIOCR_EN = 0x00030200, /* PCIout, PCIin, GPout */ ++ ++ GPOUTDR_DMA_RST_N = 0x00400000, /* PCI2_AD[14] - cpld reset */ ++ GPOUTDR_CF_RST_N = 0x00200000, /* PCI2_AD[13] - reset compact flash */ ++ GPOUTDR_CF_PWR_EN_N = 0x00100000, /* PCI2_AD[12] - compact flash power */ ++ GPOUTDR_LED_RST_N = 0x00080000, /* PCI2_AD[11] - led board reset */ ++ GPOUTDR_SYS_LED_N = 0x00040000, /* PCI2_AD[10] - system led */ ++ GPOUTDR_HW_RST_N = 0x00020000, /* PCI2_AD[9] - hard reset */ ++ GPOUTDR_CF_BUS_EN_N = 0x00010000, /* PCI2_AD[8] - compact flash enable */ ++ GPOUTDR_SW_RST_N = 0x00000080, /* GPOUT[24] - software reset */ ++ GPOUTDR_PLD1_RST_N = 0x00000040, /* GPOUT[25] - pld1 reset */ ++ GPOUTDR_PLD2_RST_N = 0x00000020, /* GPOUT[26] - pld2 reset */ ++ GPOUTDR_PLD3_RST_N = 0x00000010, /* GPOUT[27] - pld3 reset */ ++ GPOUTDR_PHY_RST = 0x00000002, /* GPOUT[30] - mgmt port phy reset */ ++ ++ GPINDR_CF_DET_0_N = 0x00040000, /* PCI2_AD[2] - compact flash present 0*/ ++ GPINDR_CF_DET_1_N = 0x00020000, /* PCI2_AD[1] - compact flash present 1*/ ++ GPINDR_CF_OC_DET_N = 0x00010000 /* PCI2_AD[0] - compact flash overcurrent */ ++}; ++ ++/*------------------------------------------------------------------------------ ++ * ++ * Platform specific functions ++ * ++ *------------------------------------------------------------------------------ ++ */ ++ ++static struct ccsr_guts_85xx __iomem *quanta_lb8_guts; ++ ++static void quanta_lb8_restart(char *cmd) ++{ ++ /* from MPC8548 spec */ ++ __be32 HRESET = 0x00000002; ++ ++ local_irq_disable(); ++ /* assert HW reset via internal register */ ++ setbits32(&quanta_lb8_guts->rstcr, HRESET); ++ /* assert HW reset via GPIO */ ++ clrbits32(&quanta_lb8_guts->gpoutdr, GPOUTDR_HW_RST_N); ++ while(1); ++} ++ ++static void __init quanta_lb8_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np = NULL; ++ ++ np = of_find_node_by_type(np, "open-pic"); ++ ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, ++ 0, 256, " OpenPIC "); ++ BUG_ON(mpic == NULL); ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++static void __init quanta_lb8_setup_arch(void) ++{ ++ struct device_node *np; ++ ++ if (ppc_md.progress) ++ ppc_md.progress("quanta_lb8_setup_arch()", 0); ++ ++ /* set the clock frequency */ ++ np = of_find_node_by_type(NULL, "cpu"); ++ if (np != 0) { ++ const unsigned int *fp; ++ ++ fp = of_get_property(np, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(np); ++ } ++ ++#ifdef CONFIG_PCI ++ /* setup PCI */ ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8540-pci") || ++ of_device_is_compatible(np, "85xx") || ++ of_device_is_compatible(np, "fsl,mpc8548-pcie")) { ++ struct resource rsrc; ++ of_address_to_resource(np, 0, &rsrc); ++ if ((rsrc.start & 0xfffff) == 0x8000) ++ fsl_add_bridge(np, 1); ++ else ++ fsl_add_bridge(np, 0); ++ } ++ } ++ ++ ++#endif ++ ++ /* map the global utilities register */ ++ printk(KERN_INFO "map MPC8548 global utilities register\n"); ++ np = of_find_compatible_node(NULL, NULL, "fsl,mpc8548-guts"); ++ if (!np) { ++ pr_err("%s: missing mpc8548 GUTs device node\n", ++ __func__); ++ return; ++ } ++ quanta_lb8_guts = of_iomap(np, 0); ++ ++ if (!quanta_lb8_guts) { ++ pr_err("%s: could not map mpc8548 GUTs register space\n", ++ __func__); ++ return; ++ } ++ ++ /* initialize powersave idle to be disabled */ ++ powersave_nap = 0; ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++ ++} ++ ++static void quanta_lb8_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu Pll setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init quanta_lb8_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "quanta,lb8")) { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static struct of_device_id __initdata quanta_lb8_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ {}, ++}; ++ ++static int __init quanta_lb8_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, quanta_lb8_ids, NULL); ++} ++machine_device_initcall(quanta_lb8, quanta_lb8_publish_devices); ++ ++define_machine(quanta_lb8) { ++ .name = "Quanta Computer LB8", ++ .probe = quanta_lb8_probe, ++ .setup_arch = quanta_lb8_setup_arch, ++ .init_IRQ = quanta_lb8_pic_init, ++ .show_cpuinfo = quanta_lb8_show_cpuinfo, ++ .get_irq = mpic_get_irq, ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++ .power_save = e500_idle, ++ .restart = quanta_lb8_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/quanta_lb8.h b/arch/powerpc/platforms/85xx/quanta_lb8.h +new file mode 100644 +index 0000000..6ba745a +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/quanta_lb8.h +@@ -0,0 +1,61 @@ ++/* ++ * Copyright 2012, Cumulus Networks, inc 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 as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++ ++/* ++ * General-Purpose Output Data Register (GPOUTDR) ++ * ++ * For GPOUTDR, need: ++ * GPOUT (GPOUTDR[0:7] corresponds to TSEC2_TXD[7:0]) : GPOUTDR[0:7] = 00000000 ++ * GPOUT (GPOUTDR[8:15] corresponds to PCI2_AD[15:8]) : GPOUTDR[8:15] = 11111111 ++ * Reserved : GPOUTDR[16:23] = 00000000 ++ * GPOUT : GPOUTDR[24:31] = 1000000 ++ * ++ * 0 4 8 12 16 20 24 28 ++ * 0000 0000 1111 1111 0000 0000 1000 0000 = 0x00FF0080 ++ * ++ * LB8 GPIO Signal : ++ * ++ * output : ++ * 0 GPOUTDR[8] <--> PCI2_AD[15] : N/A ++ * 1 GPOUTDR[9] <--> PCI2_AD[14] : DMA_RST_N (Reset CPLD, active low) ++ * 1 GPOUTDR[10] <--> PCI2_AD[13] : CF_RST_N (Reset Compact Flash card, active low) ++ * 0 GPOUTDR[11] <--> PCI2_AD[12] : CF_PWR_EN_N (Power enable for Compact Flash card, active low) ++ * 0 GPOUTDR[12] <--> PCI2_AD[11] : LED_RST_N (Reset LED board, active high) ++ * 0 GPOUTDR[13] <--> PCI2_AD[10] : LED_STATUS (The LED indicate system status, active low) ++ * 1 GPOUTDR[14] <--> PCI2_AD[9] : HW_RST_N (Hardware reset, active low) ++ * 0 GPOUTDR[15] <--> PCI2_AD[8] : CF_BUS_EN_N (Bus enable for Compact Flash card, active low) ++ * ++ * input : ++ * GPINDR[8] <--> PCI2_AD[7] : N/A ++ * GPINDR[9] <--> PCI2_AD[6] : N/A ++ * GPINDR[10] <--> PCI2_AD[5] : N/A ++ * GPINDR[11] <--> PCI2_AD[4] : N/A ++ * GPINDR[12] <--> PCI2_AD[3] : N/A ++ * GPINDR[13] <--> PCI2_AD[2] : CF_DET0 (Compact Flash card present 0, active low) ++ * GPINDR[14] <--> PCI2_AD[1] : CF_DET1 (Compact Flash card present 1, active low) ++ * GPINDR[15] <--> PCI2_AD[0] : CF_OC_N (Compact Flash card over-current detect active low) ++ * ++ * output : ++ * 1 GPOUTDR[24] <--> GPOUT[24] : SW_RST_N (Software reset, active low) ++ * 1 GPOUTDR[25] <--> GPOUT[25] : PLD1_RST_N (PLD1 reset signal, active low) ++ * 1 GPOUTDR[26] <--> GPOUT[26] : PLD2_RST_N (PLD2 reset signal, active low) ++ * 1 GPOUTDR[27] <--> GPOUT[27] : PLD3_RST_N (PLD3 reset signal, active low) ++ */ ++ ++#define QUANTA_LBX_GPIORST_N 0x00020000 +diff --git a/arch/powerpc/platforms/85xx/quanta_lb9.c b/arch/powerpc/platforms/85xx/quanta_lb9.c +new file mode 100644 +index 0000000..94505c0 +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/quanta_lb9.c +@@ -0,0 +1,259 @@ ++/* ++ * Quanta LB9 setup and early boot code plus other random bits. ++ * ++ * Copyright 2013 Cumulus Networks, Inc. ++ * Copyright 2005 Freescale Semiconductor 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 ++#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 ++ ++static unsigned int gpio_reset_handle; ++static bool gpio_reset_valid; ++ ++static int quanta_lb9_find_reset_gpio(unsigned int *handle) ++{ ++ struct device_node *gpio = NULL; ++ struct gpio_chip *gpiochip = NULL; ++ unsigned int gpio_handle = 0; ++ struct device_node *root; ++ enum of_gpio_flags flags; ++ const void *gpio_spec; ++ int rv; ++ ++ root = of_find_node_by_path("/"); ++ rv = of_parse_phandles_with_args(root, "reset-gpio", ++ "#gpio-cells", 0, &gpio, &gpio_spec); ++ if (rv < 0) { ++ printk(KERN_ERR "can't determine reset GPIO from device tree (/reset-gpio)\n"); ++ goto done; ++ } ++ ++ gpiochip = of_node_to_gpiochip(gpio); ++ if (!gpiochip) { ++ printk(KERN_ERR "gpio controller %s isn't registered\n", ++ gpio->full_name); ++ rv = -ENODEV; ++ goto done; ++ } ++ ++ gpio_handle = of_gpio_simple_xlate(gpiochip, root, gpio_spec, &flags); ++ if (gpio_handle < 0) { ++ rv = -ENODEV; ++ goto done; ++ } ++ ++ gpio_handle += gpiochip->base; ++ ++done: ++ if (gpio) { ++ of_node_put(gpio); ++ } ++ if (rv >= 0) { ++ *handle = gpio_handle; ++ } ++ return rv; ++} ++ ++static int quanta_lb9_reset_probe(void) ++{ ++ int rv; ++ ++ if (gpio_reset_valid) { ++ return 0; ++ } ++ ++ rv = quanta_lb9_find_reset_gpio(&gpio_reset_handle); ++ if (rv < 0) { ++ printk(KERN_ERR "GPIO reset unavailable\n"); ++ goto done; ++ } ++ ++ ++ rv = gpio_request(gpio_reset_handle, "reset"); ++ if (rv < 0) { ++ printk(KERN_ERR "GPIO reset pin unavailable\n"); ++ goto done; ++ } ++ ++ rv = gpio_direction_output(gpio_reset_handle, 1); ++ if (rv < 0) { ++ printk(KERN_ERR "Unable to set GPIO reset pin direction\n"); ++ goto done; ++ } ++ ++ printk(KERN_INFO "RESET: registered GPIO device: %d\n", gpio_reset_handle); ++ gpio_reset_valid = true; ++ ++done: ++ if (rv < 0) { ++ gpio_free(gpio_reset_handle); ++ gpio_reset_handle = 0; ++ } ++ return rv; ++} ++machine_device_initcall(quanta_lb9, quanta_lb9_reset_probe); ++ ++static void quanta_lb9_restart(char *cmd) ++{ ++ quanta_lb9_reset_probe(); ++ if (gpio_reset_handle) { ++ gpio_set_value(gpio_reset_handle, 0); ++ } else { ++ printk(KERN_ERR "RESET: GPIO not available, power off now.\n"); ++ } ++} ++ ++static void __init quanta_lb9_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np = NULL; ++ ++ np = of_find_node_by_type(np, "open-pic"); ++ ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, ++ 0, 256, " OpenPIC "); ++ BUG_ON(mpic == NULL); ++ ++ /* Return the mpic node */ ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++static void __init quanta_lb9_setup_arch(void) ++{ ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ ++ if (ppc_md.progress) ++ ppc_md.progress("quanta_lb9_setup_arch()", 0); ++ ++#ifdef CONFIG_PCI ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8540-pci") || ++ of_device_is_compatible(np, "fsl,mpc8548-pcie")) { ++ struct resource rsrc; ++ of_address_to_resource(np, 0, &rsrc); ++ if ((rsrc.start & 0xfffff) == 0x8000) ++ fsl_add_bridge(np, 1); ++ else ++ fsl_add_bridge(np, 0); ++ } ++ } ++#endif ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++} ++ ++static void quanta_lb9_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "Machine\t\t: Quanta LB9\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu Pll setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++} ++ ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init quanta_lb9_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ return of_flat_dt_is_compatible(root, "quanta,lb9"); ++} ++ ++static struct of_device_id __initdata of_bus_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ { .compatible = "gianfar", }, ++ {}, ++}; ++ ++static int __init declare_of_platform_devices(void) ++{ ++ return of_platform_bus_probe(NULL, of_bus_ids, NULL); ++} ++machine_device_initcall(quanta_lb9, declare_of_platform_devices); ++ ++define_machine(quanta_lb9) { ++ .name = "Quanta LB9", ++ .probe = quanta_lb9_probe, ++ .setup_arch = quanta_lb9_setup_arch, ++ .init_IRQ = quanta_lb9_pic_init, ++ .show_cpuinfo = quanta_lb9_show_cpuinfo, ++ .get_irq = mpic_get_irq, ++ .restart = quanta_lb9_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/quanta_ly2_ly2r.c b/arch/powerpc/platforms/85xx/quanta_ly2_ly2r.c +new file mode 100644 +index 0000000..aa24951 +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/quanta_ly2_ly2r.c +@@ -0,0 +1,233 @@ ++/* ++ * Copyright 2014 Cumulus Networks, Inc. ++ * ++ * LY2 setup and early boot code plus other random bits. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#undef DEBUG ++ ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++/******************************************************************************* ++ * ++ * Platform initialization functions ++ * ++ ******************************************************************************* ++*/ ++ ++/* ++ * Initialize the interrupt controller ++ */ ++static void __init quanta_ly2_ly2r_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np; ++ ++ np = of_find_node_by_type(NULL, "open-pic"); ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | ++ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | ++ MPIC_SINGLE_DEST_CPU, ++ 0, 256, " OpenPIC "); ++ ++ BUG_ON(mpic == NULL); ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++#ifdef CONFIG_SMP ++extern void __init mpc85xx_smp_init(void); ++#endif ++ ++static void __init quanta_ly2_ly2r_setup_arch(void) ++{ ++ struct device_node *cpu; ++ const unsigned int *fp; ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ ++ if (ppc_md.progress) ++ ppc_md.progress("quanta_ly2_ly2r_setup_arch()", 0); ++ ++ cpu = of_find_node_by_type(NULL, "cpu"); ++ if (cpu != 0) { ++ fp = of_get_property(cpu, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(cpu); ++ } ++ ++#ifdef CONFIG_PCI ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8548-pcie")) ++ fsl_add_bridge(np, 0); ++ } ++#endif ++ ++#ifdef CONFIG_SMP ++ mpc85xx_smp_init(); ++#endif ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++ ++ printk(KERN_INFO "Quanta LY2 & LY2R from Quanta Computer, Inc.\n"); ++} ++ ++ ++ ++static struct of_device_id __initdata quanta_ly2_ly2r_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ { .compatible = "gianfar", }, ++ {}, ++}; ++ ++ ++ ++static int __init quanta_ly2_ly2r_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, quanta_ly2_ly2r_ids, NULL); ++} ++machine_device_initcall(quanta_ly2, quanta_ly2_ly2r_publish_devices); ++machine_device_initcall(quanta_ly2r, quanta_ly2_ly2r_publish_devices); ++ ++static void quanta_ly2_ly2r_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu PLL setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init quanta_ly2_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "quanta,ly2")) ++ return 1; ++ ++ return 0; ++} ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init quanta_ly2r_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "quanta,ly2r")) ++ return 1; ++ ++ return 0; ++} ++ ++void quanta_ly2_ly2r_restart(char *cmd) ++{ ++ // asserts HRESET_REQ which will work on new hardware ++ printk(KERN_INFO "HRESET_REQ\n"); ++ fsl_rstcr_restart(cmd); ++} ++ ++define_machine(quanta_ly2) { ++ .name = "Quanta Computer, Inc. LY2", ++ .probe = quanta_ly2_probe, ++ .setup_arch = quanta_ly2_ly2r_setup_arch, ++ .init_IRQ = quanta_ly2_ly2r_pic_init, ++ .show_cpuinfo = quanta_ly2_ly2r_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = quanta_ly2_ly2r_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; ++ ++define_machine(quanta_ly2r) { ++ .name = "Quanta Computer, Inc. LY2R", ++ .probe = quanta_ly2r_probe, ++ .setup_arch = quanta_ly2_ly2r_setup_arch, ++ .init_IRQ = quanta_ly2_ly2r_pic_init, ++ .show_cpuinfo = quanta_ly2_ly2r_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = quanta_ly2_ly2r_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/85xx/quanta_ly6_p2020.c b/arch/powerpc/platforms/85xx/quanta_ly6_p2020.c +new file mode 100644 +index 0000000..d90e06c +--- /dev/null ++++ b/arch/powerpc/platforms/85xx/quanta_ly6_p2020.c +@@ -0,0 +1,206 @@ ++/* ++ * Copyright 2013 Cumulus Networks, Inc. ++ * ++ * LY6 setup and early boot code. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#undef DEBUG ++ ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++/******************************************************************************* ++ * ++ * Platform initialization functions ++ * ++ ******************************************************************************* ++*/ ++ ++/* ++ * Initialize the interrupt controller ++ */ ++static void __init quanta_ly6_pic_init(void) ++{ ++ struct mpic *mpic; ++ struct resource r; ++ struct device_node *np; ++ ++ np = of_find_node_by_type(NULL, "open-pic"); ++ if (np == NULL) { ++ printk(KERN_ERR "Could not find open-pic node\n"); ++ return; ++ } ++ ++ if (of_address_to_resource(np, 0, &r)) { ++ printk(KERN_ERR "Failed to map mpic register space\n"); ++ of_node_put(np); ++ return; ++ } ++ ++ mpic = mpic_alloc(np, r.start, ++ MPIC_PRIMARY | MPIC_WANTS_RESET | ++ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | ++ MPIC_SINGLE_DEST_CPU, ++ 0, 256, " OpenPIC "); ++ ++ BUG_ON(mpic == NULL); ++ of_node_put(np); ++ ++ mpic_init(mpic); ++} ++ ++/* ++ * Setup the architecture ++ */ ++#ifdef CONFIG_SMP ++extern void __init mpc85xx_smp_init(void); ++#endif ++ ++static void __init quanta_ly6_setup_arch(void) ++{ ++ struct device_node *cpu; ++ const unsigned int *fp; ++#ifdef CONFIG_PCI ++ struct device_node *np; ++#endif ++ ++ if (ppc_md.progress) ++ ppc_md.progress("quanta_ly6_setup_arch()", 0); ++ ++ cpu = of_find_node_by_type(NULL, "cpu"); ++ if (cpu != 0) { ++ fp = of_get_property(cpu, "clock-frequency", NULL); ++ if (fp != 0) ++ loops_per_jiffy = *fp / HZ; ++ else ++ loops_per_jiffy = 500000000 / HZ; ++ of_node_put(cpu); ++ } ++ ++#ifdef CONFIG_PCI ++ for_each_node_by_type(np, "pci") { ++ if (of_device_is_compatible(np, "fsl,mpc8548-pcie")) ++ fsl_add_bridge(np, 0); ++ } ++#endif ++ ++#ifdef CONFIG_SMP ++ mpc85xx_smp_init(); ++#endif ++ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++ ++ printk(KERN_INFO "Quanta LY6 from Quanta Computer, Inc.\n"); ++} ++ ++ ++ ++static struct of_device_id __initdata quanta_ly6_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "soc", }, ++ { .compatible = "simple-bus", }, ++ { .compatible = "gianfar", }, ++ {}, ++}; ++ ++ ++ ++static int __init quanta_ly6_publish_devices(void) ++{ ++ return of_platform_bus_probe(NULL, quanta_ly6_ids, NULL); ++} ++machine_device_initcall(quanta_ly6, quanta_ly6_publish_devices); ++ ++ ++ ++static void quanta_ly6_show_cpuinfo(struct seq_file *m) ++{ ++ uint pvid, svid, phid1; ++ uint memsize = total_memory; ++ ++ pvid = mfspr(SPRN_PVR); ++ svid = mfspr(SPRN_SVR); ++ ++ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); ++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid); ++ seq_printf(m, "SVR\t\t: 0x%x\n", svid); ++ ++ /* Display cpu PLL setting */ ++ phid1 = mfspr(SPRN_HID1); ++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); ++ ++ /* Display the amount of memory */ ++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); ++} ++ ++ ++/* ++ * Called very early, device-tree isn't unflattened ++ */ ++static int __init quanta_ly6_probe(void) ++{ ++ unsigned long root = of_get_flat_dt_root(); ++ ++ if (of_flat_dt_is_compatible(root, "quanta,ly6_p2020")) ++ return 1; ++ ++ return 0; ++} ++ ++void quanta_ly6_restart(char *cmd) ++{ ++ // asserts HRESET_REQ which will work on new hardware ++ printk(KERN_INFO "HRESET_REQ\n"); ++ fsl_rstcr_restart(cmd); ++} ++ ++ ++define_machine(quanta_ly6) { ++ .name = "Quanta Computer, Inc. LY6, P2020", ++ .probe = quanta_ly6_probe, ++ .setup_arch = quanta_ly6_setup_arch, ++ .init_IRQ = quanta_ly6_pic_init, ++ .show_cpuinfo = quanta_ly6_show_cpuinfo, ++#ifdef CONFIG_PCI ++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus, ++#endif ++ .get_irq = mpic_get_irq, ++ .power_save = e500_idle, ++ .restart = quanta_ly6_restart, ++ .calibrate_decr = generic_calibrate_decr, ++ .progress = udbg_progress, ++}; +diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig +index ee56a9e..066b58a 100644 +--- a/arch/powerpc/platforms/8xx/Kconfig ++++ b/arch/powerpc/platforms/8xx/Kconfig +@@ -160,16 +160,19 @@ config NO_UCODE_PATCH + + config USB_SOF_UCODE_PATCH + bool "USB SOF patch" ++ depends on BROKEN + help + Help not implemented yet, coming soon. + + config I2C_SPI_UCODE_PATCH + bool "I2C/SPI relocation patch" ++ depends on BROKEN + help + Help not implemented yet, coming soon. + + config I2C_SPI_SMC1_UCODE_PATCH + bool "I2C/SPI/SMC1 relocation patch" ++ depends on BROKEN + help + Help not implemented yet, coming soon. + +diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c +index 4d4c8c1..94560db 100644 +--- a/arch/powerpc/platforms/cell/cbe_thermal.c ++++ b/arch/powerpc/platforms/cell/cbe_thermal.c +@@ -46,7 +46,7 @@ + */ + + #include +-#include ++#include + #include + #include + #include +@@ -59,8 +59,8 @@ + #define TEMP_MIN 65 + #define TEMP_MAX 125 + +-#define SYSDEV_PREFIX_ATTR(_prefix,_name,_mode) \ +-struct sysdev_attribute attr_ ## _prefix ## _ ## _name = { \ ++#define DEVICE_PREFIX_ATTR(_prefix,_name,_mode) \ ++struct device_attribute attr_ ## _prefix ## _ ## _name = { \ + .attr = { .name = __stringify(_name), .mode = _mode }, \ + .show = _prefix ## _show_ ## _name, \ + .store = _prefix ## _store_ ## _name, \ +@@ -76,36 +76,36 @@ static inline u8 temp_to_reg(u8 temp) + return ((temp - TEMP_MIN) >> 1) & 0x3f; + } + +-static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) ++static struct cbe_pmd_regs __iomem *get_pmd_regs(struct device *dev) + { + struct spu *spu; + +- spu = container_of(sysdev, struct spu, sysdev); ++ spu = container_of(dev, struct spu, dev); + + return cbe_get_pmd_regs(spu_devnode(spu)); + } + + /* returns the value for a given spu in a given register */ +-static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iomem *reg) ++static u8 spu_read_register_value(struct device *dev, union spe_reg __iomem *reg) + { + union spe_reg value; + struct spu *spu; + +- spu = container_of(sysdev, struct spu, sysdev); ++ spu = container_of(dev, struct spu, dev); + value.val = in_be64(®->val); + + return value.spe[spu->spe_id]; + } + +-static ssize_t spu_show_temp(struct sys_device *sysdev, struct sysdev_attribute *attr, ++static ssize_t spu_show_temp(struct device *dev, struct device_attribute *attr, + char *buf) + { + u8 value; + struct cbe_pmd_regs __iomem *pmd_regs; + +- pmd_regs = get_pmd_regs(sysdev); ++ pmd_regs = get_pmd_regs(dev); + +- value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1); ++ value = spu_read_register_value(dev, &pmd_regs->ts_ctsr1); + + return sprintf(buf, "%d\n", reg_to_temp(value)); + } +@@ -147,48 +147,48 @@ static ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char + return size; + } + +-static ssize_t spu_show_throttle_end(struct sys_device *sysdev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t spu_show_throttle_end(struct device *dev, ++ struct device_attribute *attr, char *buf) + { +- return show_throttle(get_pmd_regs(sysdev), buf, 0); ++ return show_throttle(get_pmd_regs(dev), buf, 0); + } + +-static ssize_t spu_show_throttle_begin(struct sys_device *sysdev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t spu_show_throttle_begin(struct device *dev, ++ struct device_attribute *attr, char *buf) + { +- return show_throttle(get_pmd_regs(sysdev), buf, 8); ++ return show_throttle(get_pmd_regs(dev), buf, 8); + } + +-static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t spu_show_throttle_full_stop(struct device *dev, ++ struct device_attribute *attr, char *buf) + { +- return show_throttle(get_pmd_regs(sysdev), buf, 16); ++ return show_throttle(get_pmd_regs(dev), buf, 16); + } + +-static ssize_t spu_store_throttle_end(struct sys_device *sysdev, +- struct sysdev_attribute *attr, const char *buf, size_t size) ++static ssize_t spu_store_throttle_end(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) + { +- return store_throttle(get_pmd_regs(sysdev), buf, size, 0); ++ return store_throttle(get_pmd_regs(dev), buf, size, 0); + } + +-static ssize_t spu_store_throttle_begin(struct sys_device *sysdev, +- struct sysdev_attribute *attr, const char *buf, size_t size) ++static ssize_t spu_store_throttle_begin(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) + { +- return store_throttle(get_pmd_regs(sysdev), buf, size, 8); ++ return store_throttle(get_pmd_regs(dev), buf, size, 8); + } + +-static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev, +- struct sysdev_attribute *attr, const char *buf, size_t size) ++static ssize_t spu_store_throttle_full_stop(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) + { +- return store_throttle(get_pmd_regs(sysdev), buf, size, 16); ++ return store_throttle(get_pmd_regs(dev), buf, size, 16); + } + +-static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) ++static ssize_t ppe_show_temp(struct device *dev, char *buf, int pos) + { + struct cbe_pmd_regs __iomem *pmd_regs; + u64 value; + +- pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id); ++ pmd_regs = cbe_get_cpu_pmd_regs(dev->id); + value = in_be64(&pmd_regs->ts_ctsr2); + + value = (value >> pos) & 0x3f; +@@ -199,64 +199,64 @@ static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) + + /* shows the temperature of the DTS on the PPE, + * located near the linear thermal sensor */ +-static ssize_t ppe_show_temp0(struct sys_device *sysdev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t ppe_show_temp0(struct device *dev, ++ struct device_attribute *attr, char *buf) + { +- return ppe_show_temp(sysdev, buf, 32); ++ return ppe_show_temp(dev, buf, 32); + } + + /* shows the temperature of the second DTS on the PPE */ +-static ssize_t ppe_show_temp1(struct sys_device *sysdev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t ppe_show_temp1(struct device *dev, ++ struct device_attribute *attr, char *buf) + { +- return ppe_show_temp(sysdev, buf, 0); ++ return ppe_show_temp(dev, buf, 0); + } + +-static ssize_t ppe_show_throttle_end(struct sys_device *sysdev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t ppe_show_throttle_end(struct device *dev, ++ struct device_attribute *attr, char *buf) + { +- return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 32); ++ return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 32); + } + +-static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t ppe_show_throttle_begin(struct device *dev, ++ struct device_attribute *attr, char *buf) + { +- return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 40); ++ return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 40); + } + +-static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t ppe_show_throttle_full_stop(struct device *dev, ++ struct device_attribute *attr, char *buf) + { +- return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 48); ++ return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 48); + } + +-static ssize_t ppe_store_throttle_end(struct sys_device *sysdev, +- struct sysdev_attribute *attr, const char *buf, size_t size) ++static ssize_t ppe_store_throttle_end(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) + { +- return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 32); ++ return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 32); + } + +-static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev, +- struct sysdev_attribute *attr, const char *buf, size_t size) ++static ssize_t ppe_store_throttle_begin(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) + { +- return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 40); ++ return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 40); + } + +-static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev, +- struct sysdev_attribute *attr, const char *buf, size_t size) ++static ssize_t ppe_store_throttle_full_stop(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) + { +- return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 48); ++ return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 48); + } + + +-static struct sysdev_attribute attr_spu_temperature = { ++static struct device_attribute attr_spu_temperature = { + .attr = {.name = "temperature", .mode = 0400 }, + .show = spu_show_temp, + }; + +-static SYSDEV_PREFIX_ATTR(spu, throttle_end, 0600); +-static SYSDEV_PREFIX_ATTR(spu, throttle_begin, 0600); +-static SYSDEV_PREFIX_ATTR(spu, throttle_full_stop, 0600); ++static DEVICE_PREFIX_ATTR(spu, throttle_end, 0600); ++static DEVICE_PREFIX_ATTR(spu, throttle_begin, 0600); ++static DEVICE_PREFIX_ATTR(spu, throttle_full_stop, 0600); + + + static struct attribute *spu_attributes[] = { +@@ -272,19 +272,19 @@ static struct attribute_group spu_attribute_group = { + .attrs = spu_attributes, + }; + +-static struct sysdev_attribute attr_ppe_temperature0 = { ++static struct device_attribute attr_ppe_temperature0 = { + .attr = {.name = "temperature0", .mode = 0400 }, + .show = ppe_show_temp0, + }; + +-static struct sysdev_attribute attr_ppe_temperature1 = { ++static struct device_attribute attr_ppe_temperature1 = { + .attr = {.name = "temperature1", .mode = 0400 }, + .show = ppe_show_temp1, + }; + +-static SYSDEV_PREFIX_ATTR(ppe, throttle_end, 0600); +-static SYSDEV_PREFIX_ATTR(ppe, throttle_begin, 0600); +-static SYSDEV_PREFIX_ATTR(ppe, throttle_full_stop, 0600); ++static DEVICE_PREFIX_ATTR(ppe, throttle_end, 0600); ++static DEVICE_PREFIX_ATTR(ppe, throttle_begin, 0600); ++static DEVICE_PREFIX_ATTR(ppe, throttle_full_stop, 0600); + + static struct attribute *ppe_attributes[] = { + &attr_ppe_temperature0.attr, +@@ -307,7 +307,7 @@ static int __init init_default_values(void) + { + int cpu; + struct cbe_pmd_regs __iomem *pmd_regs; +- struct sys_device *sysdev; ++ struct device *dev; + union ppe_spe_reg tpr; + union spe_reg str1; + u64 str2; +@@ -349,14 +349,14 @@ static int __init init_default_values(void) + + for_each_possible_cpu (cpu) { + pr_debug("processing cpu %d\n", cpu); +- sysdev = get_cpu_sysdev(cpu); ++ dev = get_cpu_device(cpu); + +- if (!sysdev) { +- pr_info("invalid sysdev pointer for cbe_thermal\n"); ++ if (!dev) { ++ pr_info("invalid dev pointer for cbe_thermal\n"); + return -EINVAL; + } + +- pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id); ++ pmd_regs = cbe_get_cpu_pmd_regs(dev->id); + + if (!pmd_regs) { + pr_info("invalid CBE regs pointer for cbe_thermal\n"); +@@ -379,8 +379,8 @@ static int __init thermal_init(void) + int rc = init_default_values(); + + if (rc == 0) { +- spu_add_sysdev_attr_group(&spu_attribute_group); +- cpu_add_sysdev_attr_group(&ppe_attribute_group); ++ spu_add_dev_attr_group(&spu_attribute_group); ++ cpu_add_dev_attr_group(&ppe_attribute_group); + } + + return rc; +@@ -389,8 +389,8 @@ module_init(thermal_init); + + static void __exit thermal_exit(void) + { +- spu_remove_sysdev_attr_group(&spu_attribute_group); +- cpu_remove_sysdev_attr_group(&ppe_attribute_group); ++ spu_remove_dev_attr_group(&spu_attribute_group); ++ cpu_remove_dev_attr_group(&ppe_attribute_group); + } + module_exit(thermal_exit); + +diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c +index e94d3ec..8b12139 100644 +--- a/arch/powerpc/platforms/cell/spu_base.c ++++ b/arch/powerpc/platforms/cell/spu_base.c +@@ -519,31 +519,32 @@ void spu_init_channels(struct spu *spu) + } + EXPORT_SYMBOL_GPL(spu_init_channels); + +-static struct sysdev_class spu_sysdev_class = { ++static struct bus_type spu_subsys = { + .name = "spu", ++ .dev_name = "spu", + }; + +-int spu_add_sysdev_attr(struct sysdev_attribute *attr) ++int spu_add_dev_attr(struct device_attribute *attr) + { + struct spu *spu; + + mutex_lock(&spu_full_list_mutex); + list_for_each_entry(spu, &spu_full_list, full_list) +- sysdev_create_file(&spu->sysdev, attr); ++ device_create_file(&spu->dev, attr); + mutex_unlock(&spu_full_list_mutex); + + return 0; + } +-EXPORT_SYMBOL_GPL(spu_add_sysdev_attr); ++EXPORT_SYMBOL_GPL(spu_add_dev_attr); + +-int spu_add_sysdev_attr_group(struct attribute_group *attrs) ++int spu_add_dev_attr_group(struct attribute_group *attrs) + { + struct spu *spu; + int rc = 0; + + mutex_lock(&spu_full_list_mutex); + list_for_each_entry(spu, &spu_full_list, full_list) { +- rc = sysfs_create_group(&spu->sysdev.kobj, attrs); ++ rc = sysfs_create_group(&spu->dev.kobj, attrs); + + /* we're in trouble here, but try unwinding anyway */ + if (rc) { +@@ -552,7 +553,7 @@ int spu_add_sysdev_attr_group(struct attribute_group *attrs) + + list_for_each_entry_continue_reverse(spu, + &spu_full_list, full_list) +- sysfs_remove_group(&spu->sysdev.kobj, attrs); ++ sysfs_remove_group(&spu->dev.kobj, attrs); + break; + } + } +@@ -561,45 +562,45 @@ int spu_add_sysdev_attr_group(struct attribute_group *attrs) + + return rc; + } +-EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group); ++EXPORT_SYMBOL_GPL(spu_add_dev_attr_group); + + +-void spu_remove_sysdev_attr(struct sysdev_attribute *attr) ++void spu_remove_dev_attr(struct device_attribute *attr) + { + struct spu *spu; + + mutex_lock(&spu_full_list_mutex); + list_for_each_entry(spu, &spu_full_list, full_list) +- sysdev_remove_file(&spu->sysdev, attr); ++ device_remove_file(&spu->dev, attr); + mutex_unlock(&spu_full_list_mutex); + } +-EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr); ++EXPORT_SYMBOL_GPL(spu_remove_dev_attr); + +-void spu_remove_sysdev_attr_group(struct attribute_group *attrs) ++void spu_remove_dev_attr_group(struct attribute_group *attrs) + { + struct spu *spu; + + mutex_lock(&spu_full_list_mutex); + list_for_each_entry(spu, &spu_full_list, full_list) +- sysfs_remove_group(&spu->sysdev.kobj, attrs); ++ sysfs_remove_group(&spu->dev.kobj, attrs); + mutex_unlock(&spu_full_list_mutex); + } +-EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr_group); ++EXPORT_SYMBOL_GPL(spu_remove_dev_attr_group); + +-static int spu_create_sysdev(struct spu *spu) ++static int spu_create_dev(struct spu *spu) + { + int ret; + +- spu->sysdev.id = spu->number; +- spu->sysdev.cls = &spu_sysdev_class; +- ret = sysdev_register(&spu->sysdev); ++ spu->dev.id = spu->number; ++ spu->dev.bus = &spu_subsys; ++ ret = device_register(&spu->dev); + if (ret) { + printk(KERN_ERR "Can't register SPU %d with sysfs\n", + spu->number); + return ret; + } + +- sysfs_add_device_to_node(&spu->sysdev, spu->node); ++ sysfs_add_device_to_node(&spu->dev, spu->node); + + return 0; + } +@@ -635,7 +636,7 @@ static int __init create_spu(void *data) + if (ret) + goto out_destroy; + +- ret = spu_create_sysdev(spu); ++ ret = spu_create_dev(spu); + if (ret) + goto out_free_irqs; + +@@ -692,10 +693,10 @@ static unsigned long long spu_acct_time(struct spu *spu, + } + + +-static ssize_t spu_stat_show(struct sys_device *sysdev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t spu_stat_show(struct device *dev, ++ struct device_attribute *attr, char *buf) + { +- struct spu *spu = container_of(sysdev, struct spu, sysdev); ++ struct spu *spu = container_of(dev, struct spu, dev); + + return sprintf(buf, "%s %llu %llu %llu %llu " + "%llu %llu %llu %llu %llu %llu %llu %llu\n", +@@ -714,7 +715,7 @@ static ssize_t spu_stat_show(struct sys_device *sysdev, + spu->stats.libassist); + } + +-static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL); ++static DEVICE_ATTR(stat, 0644, spu_stat_show, NULL); + + #ifdef CONFIG_KEXEC + +@@ -813,8 +814,8 @@ static int __init init_spu_base(void) + if (!spu_management_ops) + goto out; + +- /* create sysdev class for spus */ +- ret = sysdev_class_register(&spu_sysdev_class); ++ /* create system subsystem for spus */ ++ ret = subsys_system_register(&spu_subsys, NULL); + if (ret) + goto out; + +@@ -823,7 +824,7 @@ static int __init init_spu_base(void) + if (ret < 0) { + printk(KERN_WARNING "%s: Error initializing spus\n", + __func__); +- goto out_unregister_sysdev_class; ++ goto out_unregister_subsys; + } + + if (ret > 0) +@@ -833,15 +834,15 @@ static int __init init_spu_base(void) + xmon_register_spus(&spu_full_list); + crash_register_spus(&spu_full_list); + mutex_unlock(&spu_full_list_mutex); +- spu_add_sysdev_attr(&attr_stat); ++ spu_add_dev_attr(&dev_attr_stat); + register_syscore_ops(&spu_syscore_ops); + + spu_init_affinity(); + + return 0; + +- out_unregister_sysdev_class: +- sysdev_class_unregister(&spu_sysdev_class); ++ out_unregister_subsys: ++ bus_unregister(&spu_subsys); + out: + return ret; + } +diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c +index a76b228..bd4861b 100644 +--- a/arch/powerpc/platforms/pseries/nvram.c ++++ b/arch/powerpc/platforms/pseries/nvram.c +@@ -636,7 +636,6 @@ static void oops_to_nvram(struct kmsg_dumper *dumper, + /* These are almost always orderly shutdowns. */ + return; + case KMSG_DUMP_OOPS: +- case KMSG_DUMP_KEXEC: + break; + case KMSG_DUMP_PANIC: + panicking = true; +diff --git a/arch/powerpc/platforms/pseries/pseries_energy.c b/arch/powerpc/platforms/pseries/pseries_energy.c +index c8b3c69..af281dc 100644 +--- a/arch/powerpc/platforms/pseries/pseries_energy.c ++++ b/arch/powerpc/platforms/pseries/pseries_energy.c +@@ -15,7 +15,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -184,7 +184,7 @@ static ssize_t get_best_energy_list(char *page, int activate) + return s-page; + } + +-static ssize_t get_best_energy_data(struct sys_device *dev, ++static ssize_t get_best_energy_data(struct device *dev, + char *page, int activate) + { + int rc; +@@ -207,26 +207,26 @@ static ssize_t get_best_energy_data(struct sys_device *dev, + + /* Wrapper functions */ + +-static ssize_t cpu_activate_hint_list_show(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, char *page) ++static ssize_t cpu_activate_hint_list_show(struct device *dev, ++ struct device_attribute *attr, char *page) + { + return get_best_energy_list(page, 1); + } + +-static ssize_t cpu_deactivate_hint_list_show(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, char *page) ++static ssize_t cpu_deactivate_hint_list_show(struct device *dev, ++ struct device_attribute *attr, char *page) + { + return get_best_energy_list(page, 0); + } + +-static ssize_t percpu_activate_hint_show(struct sys_device *dev, +- struct sysdev_attribute *attr, char *page) ++static ssize_t percpu_activate_hint_show(struct device *dev, ++ struct device_attribute *attr, char *page) + { + return get_best_energy_data(dev, page, 1); + } + +-static ssize_t percpu_deactivate_hint_show(struct sys_device *dev, +- struct sysdev_attribute *attr, char *page) ++static ssize_t percpu_deactivate_hint_show(struct device *dev, ++ struct device_attribute *attr, char *page) + { + return get_best_energy_data(dev, page, 0); + } +@@ -241,48 +241,48 @@ static ssize_t percpu_deactivate_hint_show(struct sys_device *dev, + * Per-cpu value of the hint + */ + +-struct sysdev_class_attribute attr_cpu_activate_hint_list = +- _SYSDEV_CLASS_ATTR(pseries_activate_hint_list, 0444, ++struct device_attribute attr_cpu_activate_hint_list = ++ __ATTR(pseries_activate_hint_list, 0444, + cpu_activate_hint_list_show, NULL); + +-struct sysdev_class_attribute attr_cpu_deactivate_hint_list = +- _SYSDEV_CLASS_ATTR(pseries_deactivate_hint_list, 0444, ++struct device_attribute attr_cpu_deactivate_hint_list = ++ __ATTR(pseries_deactivate_hint_list, 0444, + cpu_deactivate_hint_list_show, NULL); + +-struct sysdev_attribute attr_percpu_activate_hint = +- _SYSDEV_ATTR(pseries_activate_hint, 0444, ++struct device_attribute attr_percpu_activate_hint = ++ __ATTR(pseries_activate_hint, 0444, + percpu_activate_hint_show, NULL); + +-struct sysdev_attribute attr_percpu_deactivate_hint = +- _SYSDEV_ATTR(pseries_deactivate_hint, 0444, ++struct device_attribute attr_percpu_deactivate_hint = ++ __ATTR(pseries_deactivate_hint, 0444, + percpu_deactivate_hint_show, NULL); + + static int __init pseries_energy_init(void) + { + int cpu, err; +- struct sys_device *cpu_sys_dev; ++ struct device *cpu_dev; + + if (!check_for_h_best_energy()) { + printk(KERN_INFO "Hypercall H_BEST_ENERGY not supported\n"); + return 0; + } + /* Create the sysfs files */ +- err = sysfs_create_file(&cpu_sysdev_class.kset.kobj, +- &attr_cpu_activate_hint_list.attr); ++ err = device_create_file(cpu_subsys.dev_root, ++ &attr_cpu_activate_hint_list); + if (!err) +- err = sysfs_create_file(&cpu_sysdev_class.kset.kobj, +- &attr_cpu_deactivate_hint_list.attr); ++ err = device_create_file(cpu_subsys.dev_root, ++ &attr_cpu_deactivate_hint_list); + + if (err) + return err; + for_each_possible_cpu(cpu) { +- cpu_sys_dev = get_cpu_sysdev(cpu); +- err = sysfs_create_file(&cpu_sys_dev->kobj, +- &attr_percpu_activate_hint.attr); ++ cpu_dev = get_cpu_device(cpu); ++ err = device_create_file(cpu_dev, ++ &attr_percpu_activate_hint); + if (err) + break; +- err = sysfs_create_file(&cpu_sys_dev->kobj, +- &attr_percpu_deactivate_hint.attr); ++ err = device_create_file(cpu_dev, ++ &attr_percpu_deactivate_hint); + if (err) + break; + } +@@ -298,23 +298,20 @@ static int __init pseries_energy_init(void) + static void __exit pseries_energy_cleanup(void) + { + int cpu; +- struct sys_device *cpu_sys_dev; ++ struct device *cpu_dev; + + if (!sysfs_entries) + return; + + /* Remove the sysfs files */ +- sysfs_remove_file(&cpu_sysdev_class.kset.kobj, +- &attr_cpu_activate_hint_list.attr); +- +- sysfs_remove_file(&cpu_sysdev_class.kset.kobj, +- &attr_cpu_deactivate_hint_list.attr); ++ device_remove_file(cpu_subsys.dev_root, &attr_cpu_activate_hint_list); ++ device_remove_file(cpu_subsys.dev_root, &attr_cpu_deactivate_hint_list); + + for_each_possible_cpu(cpu) { +- cpu_sys_dev = get_cpu_sysdev(cpu); +- sysfs_remove_file(&cpu_sys_dev->kobj, ++ cpu_dev = get_cpu_device(cpu); ++ sysfs_remove_file(&cpu_dev->kobj, + &attr_percpu_activate_hint.attr); +- sysfs_remove_file(&cpu_sys_dev->kobj, ++ sysfs_remove_file(&cpu_dev->kobj, + &attr_percpu_deactivate_hint.attr); + } + } +diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile +index 84e1325..94aa06f 100644 +--- a/arch/powerpc/sysdev/Makefile ++++ b/arch/powerpc/sysdev/Makefile +@@ -18,6 +18,7 @@ obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y) + obj-$(CONFIG_FSL_PMC) += fsl_pmc.o + obj-$(CONFIG_FSL_LBC) += fsl_lbc.o + obj-$(CONFIG_FSL_GTM) += fsl_gtm.o ++obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o + obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o + obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o + obj-$(CONFIG_FSL_RIO) += fsl_rio.o +diff --git a/arch/powerpc/sysdev/fsl_pamu.c b/arch/powerpc/sysdev/fsl_pamu.c +new file mode 100644 +index 0000000..a9e9fc7 +--- /dev/null ++++ b/arch/powerpc/sysdev/fsl_pamu.c +@@ -0,0 +1,1431 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* PAMU CCSR space */ ++#define PAMU_PGC 0x00000000 /* Allows all peripheral accesses */ ++#define PAMU_PE 0x40000000 /* enable PAMU */ ++ ++/* PAMU_OFFSET to the next pamu space in ccsr */ ++#define PAMU_OFFSET 0x1000 ++ ++#define PAMU_MMAP_REGS_BASE 0 ++ ++struct pamu_mmap_regs { ++ u32 ppbah; ++ u32 ppbal; ++ u32 pplah; ++ u32 pplal; ++ u32 spbah; ++ u32 spbal; ++ u32 splah; ++ u32 splal; ++ u32 obah; ++ u32 obal; ++ u32 olah; ++ u32 olal; ++}; ++ ++/* PAMU Error Registers */ ++#define PAMU_POES1 0x0040 ++#define PAMU_POES2 0x0044 ++#define PAMU_POEAH 0x0048 ++#define PAMU_POEAL 0x004C ++#define PAMU_AVS1 0x0050 ++#define PAMU_AVS1_AV 0x1 ++#define PAMU_AVS1_OTV 0x6 ++#define PAMU_AVS1_APV 0x78 ++#define PAMU_AVS1_WAV 0x380 ++#define PAMU_AVS1_LAV 0x1c00 ++#define PAMU_AVS1_GCV 0x2000 ++#define PAMU_AVS1_PDV 0x4000 ++#define PAMU_AV_MASK (PAMU_AVS1_AV | PAMU_AVS1_OTV | PAMU_AVS1_APV | \ ++ PAMU_AVS1_WAV | PAMU_AVS1_LAV | PAMU_AVS1_GCV | \ ++ PAMU_AVS1_PDV) ++#define PAMU_AVS1_LIODN_SHIFT 16 ++#define PAMU_LAV_LIODN_NOT_IN_PPAACT 0x400 ++ ++#define PAMU_AVS2 0x0054 ++#define PAMU_AVAH 0x0058 ++#define PAMU_AVAL 0x005C ++#define PAMU_EECTL 0x0060 ++#define PAMU_EEDIS 0x0064 ++#define PAMU_EEINTEN 0x0068 ++#define PAMU_EEDET 0x006C ++#define PAMU_EEATTR 0x0070 ++#define PAMU_EEAHI 0x0074 ++#define PAMU_EEALO 0x0078 ++#define PAMU_EEDHI 0X007C ++#define PAMU_EEDLO 0x0080 ++#define PAMU_EECC 0x0084 ++#define PAMU_UDAD 0x0090 ++ ++/* PAMU Revision Registers */ ++#define PAMU_PR1 0x0BF8 ++#define PAMU_PR2 0x0BFC ++ ++/* PAMU Capabilities Registers */ ++#define PAMU_PC1 0x0C00 ++#define PAMU_PC2 0x0C04 ++#define PAMU_PC3 0x0C08 ++#define PAMU_PC4 0x0C0C ++ ++/* PAMU Control Register */ ++#define PAMU_PC 0x0C10 ++ ++/* PAMU control defs */ ++#define PAMU_CONTROL 0x0C10 ++#define PAMU_PC_PGC 0x80000000 /* 1 = PAMU Gate Closed : block all ++peripheral access, 0 : may allow peripheral access */ ++ ++#define PAMU_PC_PE 0x40000000 /* 0 = PAMU disabled, 1 = PAMU enabled */ ++#define PAMU_PC_SPCC 0x00000010 /* sPAACE cache enable */ ++#define PAMU_PC_PPCC 0x00000001 /* pPAACE cache enable */ ++#define PAMU_PC_OCE 0x00001000 /* OMT cache enable */ ++ ++#define PAMU_PFA1 0x0C14 ++#define PAMU_PFA2 0x0C18 ++ ++/* PAMU Interrupt control and Status Register */ ++#define PAMU_PICS 0x0C1C ++#define PAMU_ACCESS_VIOLATION_STAT 0x8 ++#define PAMU_ACCESS_VIOLATION_ENABLE 0x4 ++ ++/* PAMU Debug Registers */ ++#define PAMU_PD1 0x0F00 ++#define PAMU_PD2 0x0F04 ++#define PAMU_PD3 0x0F08 ++#define PAMU_PD4 0x0F0C ++ ++#define PAACE_AP_PERMS_DENIED 0x0 ++#define PAACE_AP_PERMS_QUERY 0x1 ++#define PAACE_AP_PERMS_UPDATE 0x2 ++#define PAACE_AP_PERMS_ALL 0x3 ++#define PAACE_DD_TO_HOST 0x0 ++#define PAACE_DD_TO_IO 0x1 ++#define PAACE_PT_PRIMARY 0x0 ++#define PAACE_PT_SECONDARY 0x1 ++#define PAACE_V_INVALID 0x0 ++#define PAACE_V_VALID 0x1 ++#define PAACE_MW_SUBWINDOWS 0x1 ++ ++#define PAACE_WSE_4K 0xB ++#define PAACE_WSE_8K 0xC ++#define PAACE_WSE_16K 0xD ++#define PAACE_WSE_32K 0xE ++#define PAACE_WSE_64K 0xF ++#define PAACE_WSE_128K 0x10 ++#define PAACE_WSE_256K 0x11 ++#define PAACE_WSE_512K 0x12 ++#define PAACE_WSE_1M 0x13 ++#define PAACE_WSE_2M 0x14 ++#define PAACE_WSE_4M 0x15 ++#define PAACE_WSE_8M 0x16 ++#define PAACE_WSE_16M 0x17 ++#define PAACE_WSE_32M 0x18 ++#define PAACE_WSE_64M 0x19 ++#define PAACE_WSE_128M 0x1A ++#define PAACE_WSE_256M 0x1B ++#define PAACE_WSE_512M 0x1C ++#define PAACE_WSE_1G 0x1D ++#define PAACE_WSE_2G 0x1E ++#define PAACE_WSE_4G 0x1F ++ ++#define PAACE_DID_PCI_EXPRESS_1 0x00 ++#define PAACE_DID_PCI_EXPRESS_2 0x01 ++#define PAACE_DID_PCI_EXPRESS_3 0x02 ++#define PAACE_DID_PCI_EXPRESS_4 0x03 ++#define PAACE_DID_LOCAL_BUS 0x04 ++#define PAACE_DID_SRIO 0x0C ++#define PAACE_DID_MEM_1 0x10 ++#define PAACE_DID_MEM_2 0x11 ++#define PAACE_DID_MEM_3 0x12 ++#define PAACE_DID_MEM_4 0x13 ++#define PAACE_DID_MEM_1_2 0x14 ++#define PAACE_DID_MEM_3_4 0x15 ++#define PAACE_DID_MEM_1_4 0x16 ++#define PAACE_DID_BM_SW_PORTAL 0x18 ++#define PAACE_DID_PAMU 0x1C ++#define PAACE_DID_CAAM 0x21 ++#define PAACE_DID_QM_SW_PORTAL 0x3C ++#define PAACE_DID_CORE0_INST 0x80 ++#define PAACE_DID_CORE0_DATA 0x81 ++#define PAACE_DID_CORE1_INST 0x82 ++#define PAACE_DID_CORE1_DATA 0x83 ++#define PAACE_DID_CORE2_INST 0x84 ++#define PAACE_DID_CORE2_DATA 0x85 ++#define PAACE_DID_CORE3_INST 0x86 ++#define PAACE_DID_CORE3_DATA 0x87 ++#define PAACE_DID_CORE4_INST 0x88 ++#define PAACE_DID_CORE4_DATA 0x89 ++#define PAACE_DID_CORE5_INST 0x8A ++#define PAACE_DID_CORE5_DATA 0x8B ++#define PAACE_DID_CORE6_INST 0x8C ++#define PAACE_DID_CORE6_DATA 0x8D ++#define PAACE_DID_CORE7_INST 0x8E ++#define PAACE_DID_CORE7_DATA 0x8F ++#define PAACE_DID_BROADCAST 0xFF ++ ++#define PAACE_ATM_NO_XLATE 0x00 ++#define PAACE_ATM_WINDOW_XLATE 0x01 ++#define PAACE_ATM_PAGE_XLATE 0x02 ++#define PAACE_ATM_WIN_PG_XLATE (PAACE_ATM_WINDOW_XLATE | PAACE_ATM_PAGE_XLATE) ++#define PAACE_OTM_NO_XLATE 0x00 ++#define PAACE_OTM_IMMEDIATE 0x01 ++#define PAACE_OTM_INDEXED 0x02 ++#define PAACE_OTM_RESERVED 0x03 ++ ++#define PAACE_M_COHERENCE_REQ 0x01 ++ ++#define PAACE_TCEF_FORMAT0_8B 0x00 ++#define PAACE_TCEF_FORMAT1_RSVD 0x01 ++ ++#define PAACE_NUMBER_ENTRIES 0x500 ++ ++#define OME_NUMBER_ENTRIES 16 /* based on P4080 2.0 silicon plan */ ++ ++/* PAMU Data Structures */ ++ ++struct ppaace { ++ /* PAACE Offset 0x00 */ ++ /* Window Base Address */ ++ u32 wbah; ++ unsigned int wbal:20; ++ /* Window Size, 2^(N+1), N must be > 10 */ ++ unsigned int wse:6; ++ /* 1 Means there are secondary windows, wce is count */ ++ unsigned int mw:1; ++ /* Permissions, see PAACE_AP_PERMS_* defines */ ++ unsigned int ap:2; ++ /* ++ * Destination Domain, see PAACE_DD_* defines, ++ * defines data structure reference for ingress ops into ++ * host/coherency domain or ingress ops into I/O domain ++ */ ++ unsigned int dd:1; ++ /* PAACE Type, see PAACE_PT_* defines */ ++ unsigned int pt:1; ++ /* PAACE Valid, 0 is invalid */ ++ unsigned int v:1; ++ ++ /* PAACE Offset 0x08 */ ++ /* Interpretation of first 32 bits dependent on DD above */ ++ union { ++ struct { ++ /* Destination ID, see PAACE_DID_* defines */ ++ u8 did; ++ /* Partition ID */ ++ u8 pid; ++ /* Snoop ID */ ++ u8 snpid; ++ unsigned int coherency_required:1; ++ unsigned int reserved:7; ++ } to_host; ++ struct { ++ /* Destination ID, see PAACE_DID_* defines */ ++ u8 did; ++ unsigned int __reserved:24; ++ } to_io; ++ } __packed domain_attr; ++ /* Implementation attributes */ ++ struct { ++ unsigned int reserved1:8; ++ unsigned int cid:8; ++ unsigned int reserved2:8; ++ } __packed impl_attr; ++ /* Window Count; 2^(N+1) sub-windows; only valid for primary PAACE */ ++ unsigned int wce:4; ++ /* Address translation mode, see PAACE_ATM_* defines */ ++ unsigned int atm:2; ++ /* Operation translation mode, see PAACE_OTM_* defines */ ++ unsigned int otm:2; ++ ++ /* PAACE Offset 0x10 */ ++ /* Translated window base address */ ++ u32 twbah; ++ unsigned int twbal:20; ++ /* Subwindow size encoding; 2^(N+1), N > 10 */ ++ unsigned int swse:6; ++ unsigned int reserved4:6; ++ ++ /* PAACE Offset 0x18 */ ++ u32 fspi; ++ union { ++ struct { ++ u8 ioea; ++ u8 moea; ++ u8 ioeb; ++ u8 moeb; ++ } immed_ot; ++ struct { ++ u16 reserved; ++ u16 omi; ++ } index_ot; ++ } __packed op_encode; ++ ++ /* PAACE Offset 0x20 */ ++ u32 sbah; ++ unsigned int sbal:20; ++ unsigned int sse:6; ++ unsigned int reserved5:6; ++ ++ /* PAACE Offset 0x28 */ ++ u32 tctbah; ++ unsigned int tctbal:20; ++ unsigned int pse:6; ++ unsigned int tcef:1; ++ unsigned int reserved6:5; ++ ++ /* PAACE Offset 0x30 */ ++ u32 reserved7[2]; ++ ++ /* PAACE Offset 0x38 */ ++ u32 reserved8[2]; ++} __packed ppaace; ++ ++/* MOE : Mapped Operation Encodings */ ++#define NUM_MOE 128 ++struct ome { ++ u8 moe[NUM_MOE]; ++} __packed ome; ++ ++/* ++ * The Primary Peripheral Access Authorization and Control Table ++ * ++ * To keep things simple, we use one shared PPAACT for all PAMUs. This means ++ * that LIODNs must be unique across all PAMUs. ++ */ ++static struct ppaace *ppaact; ++static phys_addr_t ppaact_phys; ++ ++/* TRUE if we're running under the Freescale hypervisor */ ++bool has_fsl_hypervisor; ++ ++#define PAACT_SIZE (sizeof(struct ppaace) * PAACE_NUMBER_ENTRIES) ++#define OMT_SIZE (sizeof(struct ome) * OME_NUMBER_ENTRIES) ++ ++#define IOE_READ 0x00 ++#define IOE_READ_IDX 0x00 ++#define IOE_WRITE 0x81 ++#define IOE_WRITE_IDX 0x01 ++#define IOE_EREAD0 0x82 /* Enhanced read type 0 */ ++#define IOE_EREAD0_IDX 0x02 /* Enhanced read type 0 */ ++#define IOE_EWRITE0 0x83 /* Enhanced write type 0 */ ++#define IOE_EWRITE0_IDX 0x03 /* Enhanced write type 0 */ ++#define IOE_DIRECT0 0x84 /* Directive type 0 */ ++#define IOE_DIRECT0_IDX 0x04 /* Directive type 0 */ ++#define IOE_EREAD1 0x85 /* Enhanced read type 1 */ ++#define IOE_EREAD1_IDX 0x05 /* Enhanced read type 1 */ ++#define IOE_EWRITE1 0x86 /* Enhanced write type 1 */ ++#define IOE_EWRITE1_IDX 0x06 /* Enhanced write type 1 */ ++#define IOE_DIRECT1 0x87 /* Directive type 1 */ ++#define IOE_DIRECT1_IDX 0x07 /* Directive type 1 */ ++#define IOE_RAC 0x8c /* Read with Atomic clear */ ++#define IOE_RAC_IDX 0x0c /* Read with Atomic clear */ ++#define IOE_RAS 0x8d /* Read with Atomic set */ ++#define IOE_RAS_IDX 0x0d /* Read with Atomic set */ ++#define IOE_RAD 0x8e /* Read with Atomic decrement */ ++#define IOE_RAD_IDX 0x0e /* Read with Atomic decrement */ ++#define IOE_RAI 0x8f /* Read with Atomic increment */ ++#define IOE_RAI_IDX 0x0f /* Read with Atomic increment */ ++ ++#define EOE_READ 0x00 ++#define EOE_WRITE 0x01 ++#define EOE_RAC 0x0c /* Read with Atomic clear */ ++#define EOE_RAS 0x0d /* Read with Atomic set */ ++#define EOE_RAD 0x0e /* Read with Atomic decrement */ ++#define EOE_RAI 0x0f /* Read with Atomic increment */ ++#define EOE_LDEC 0x10 /* Load external cache */ ++#define EOE_LDECL 0x11 /* Load external cache with stash lock */ ++#define EOE_LDECPE 0x12 /* Load ext. cache with preferred exclusive */ ++#define EOE_LDECPEL 0x13 /* Load ext. cache w/ preferred excl. & lock */ ++#define EOE_LDECFE 0x14 /* Load external cache with forced exclusive */ ++#define EOE_LDECFEL 0x15 /* Load ext. cache w/ forced excl. & lock */ ++#define EOE_RSA 0x16 /* Read with stash allocate */ ++#define EOE_RSAU 0x17 /* Read with stash allocate and unlock */ ++#define EOE_READI 0x18 /* Read with invalidate */ ++#define EOE_RWNITC 0x19 /* Read with no intention to cache */ ++#define EOE_WCI 0x1a /* Write cache inhibited */ ++#define EOE_WWSA 0x1b /* Write with stash allocate */ ++#define EOE_WWSAL 0x1c /* Write with stash allocate and lock */ ++#define EOE_WWSAO 0x1d /* Write with stash allocate only */ ++#define EOE_WWSAOL 0x1e /* Write with stash allocate only and lock */ ++#define EOE_VALID 0x80 ++ ++/* define indexes for each operation mapping scenario */ ++#define OMI_QMAN 0x00 ++#define OMI_FMAN 0x01 ++#define OMI_QMAN_PRIV 0x02 ++#define OMI_CAAM 0x03 ++ ++/* ++ * Return the Nth integer of a given property in a given node ++ * ++ * 'index' is the index into the property (e.g. 'N'). ++ * 'property' is the name of the property. ++ * ++ * This function assumes the value of the property is <= INT_MAX. A negative ++ * return value indicates an error. ++ */ ++static int of_read_indexed_number(struct device_node *node, ++ const char *property, unsigned int index) ++{ ++ const u32 *prop; ++ int value; ++ int len; ++ ++ prop = of_get_property(node, property, &len); ++ if (!prop || (len % sizeof(uint32_t))) ++ return -ENODEV; ++ ++ if (index >= (len / sizeof(uint32_t))) ++ return -EINVAL; ++ ++ value = be32_to_cpu(prop[index]); ++ ++ return value; ++} ++ ++/** ++ * pamu_set_stash_dest() - set the stash target for a given LIODN ++ * @liodn: LIODN to set ++ * @cache_level: target cache level (1, 2, or 3) ++ * @cpu: target CPU (0, 1, 2, etc) ++ * ++ * This function sets the stash target for a given LIODN, assuming that the ++ * PAACE entry for that LIODN is already configured. ++ * ++ * The function returns 0 on success, or a negative error code on failure. ++ */ ++int pamu_set_stash_dest(struct device_node *node, unsigned int index, ++ unsigned int cpu, unsigned int cache_level) ++{ ++ int liodn; ++ const u32 *prop; ++ unsigned int i; ++ int psize; ++ ++#ifdef CONFIG_FSL_PAMU_ERRATUM_A_004510 ++ /* ++ * The work-around says that we cannot have multiple writes to the ++ * PAACT in flight simultaneously, which could happen if multiple ++ * cores try to update CID simultaneously. To prevent that, we wrap ++ * the write in a mutex, which will force the cores to perform their ++ * updates in sequence. ++ */ ++ static DEFINE_SPINLOCK(pamu_lock); ++#endif ++ ++ ++ /* If we're running under a support hypervisor, make an hcall instead */ ++ if (has_fsl_hypervisor) { ++ struct fh_dma_attr_stash attr; ++ phys_addr_t paddr = virt_to_phys(&attr); ++ int handle; ++ ++ handle = of_read_indexed_number(node, "fsl,hv-dma-handle", ++ index); ++ ++ if (handle < 0) ++ return -EINVAL; ++ ++ attr.vcpu = cpu; ++ attr.cache = cache_level; ++ ++ if (fh_dma_attr_set(handle, FSL_PAMU_ATTR_STASH, paddr)) ++ return -EINVAL; ++ ++ return 0; ++ } ++ ++ liodn = of_read_indexed_number(node, "fsl,liodn", index); ++ if (liodn < 0) ++ return liodn; ++ ++ for_each_node_by_type(node, "cpu") { ++ prop = of_get_property(node, "reg", &psize); ++ if (prop) { ++ psize /= 4; ++ for (i = 0; i < psize; i++) ++ if (be32_to_cpup(prop++) == cpu) ++ goto found_cpu; ++ } ++ } ++ ++ pr_err("fsl-pamu: could not find 'cpu' node %u\n", cpu); ++ return -EINVAL; ++ ++found_cpu: ++ /* ++ * Traverse the list of caches until we find the one we want. The CPU ++ * node is also the L1 cache node ++ */ ++ for (i = 1; i < cache_level; i++) { ++ node = of_parse_phandle(node, "next-level-cache", 0); ++ if (!node) { ++ pr_err("fsl-pamu: cache level %u invalid for cpu %u\n", ++ i, cpu); ++ return -EINVAL; ++ } ++ } ++ ++ prop = of_get_property(node, "cache-stash-id", NULL); ++ if (!prop) { ++ pr_err("fsl-pamu: missing 'cache-stash-id' in %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ ++#ifdef CONFIG_FSL_PAMU_ERRATUM_A_004510 ++ spin_lock(&pamu_lock); ++#endif ++ ++ ppaact[liodn].impl_attr.cid = be32_to_cpup(prop); ++ mb(); ++ ++#ifdef CONFIG_FSL_PAMU_ERRATUM_A_004510 ++ spin_unlock(&pamu_lock); ++#endif ++ ++ return 0; ++} ++EXPORT_SYMBOL(pamu_set_stash_dest); ++ ++/** ++ * pamu_get_liodn_count() - returns the number of LIODNs for a given node ++ * @node: the node to query ++ * ++ * This function returns the number of LIODNs in a given node. ++ * ++ * The function returns the number >= 0 on success, or a negative error code ++ * on failure. Currently, an error code cannot be returned, but that may ++ * change in the future. Callers are still expected to test for an error. ++ */ ++int pamu_get_liodn_count(struct device_node *node) ++{ ++ const u32 *prop; ++ int len; ++ ++ /* ++ * Under the hypervisor, use the "fsl,hv-dma-handle". Otherwise, ++ * use the "fsl,liodn" property. ++ */ ++ if (has_fsl_hypervisor) ++ prop = of_get_property(node, "fsl,hv-dma-handle", &len); ++ else ++ prop = of_get_property(node, "fsl,liodn", &len); ++ ++ if (!prop) ++ /* ++ * KVM sets up default stashing but does not provide an ++ * interface to the PAMU, so there are no PAMU nodes or LIODN ++ * properties in the guest device tree. Therefore, if the ++ * LIODN property is missing, that doesn't mean that 'node' is ++ * invalid. ++ */ ++ return 0; ++ ++ return len / sizeof(uint32_t); ++} ++EXPORT_SYMBOL(pamu_get_liodn_count); ++ ++ ++static void __init setup_omt(struct ome *omt) ++{ ++ struct ome *ome; ++ ++ /* Configure OMI_QMAN */ ++ ome = &omt[OMI_QMAN]; ++ ++ ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_READ; ++ ome->moe[IOE_EREAD0_IDX] = EOE_VALID | EOE_RSA; ++ ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WRITE; ++ ome->moe[IOE_EWRITE0_IDX] = EOE_VALID | EOE_WWSAO; ++ ++ /* ++ * When it comes to stashing DIRECTIVEs, the QMan BG says ++ * (1.5.6.7.1: FQD Context_A field used for dequeued etc. ++ * etc. stashing control): ++ * - AE/DE/CE == 0: don't stash exclusive. Use DIRECT0, ++ * which should be a non-PE LOADEC. ++ * - AE/DE/CE == 1: stash exclusive via DIRECT1, i.e. ++ * LOADEC-PE ++ * If one desires to alter how the three different types of ++ * stashing are done, please alter rx_conf.exclusive in ++ * ipfwd_a.c (that specifies the 3-bit AE/DE/CE field), and ++ * do not alter the settings here. - bgrayson ++ */ ++ ome->moe[IOE_DIRECT0_IDX] = EOE_VALID | EOE_LDEC; ++ ome->moe[IOE_DIRECT1_IDX] = EOE_VALID | EOE_LDECPE; ++ ++ /* Configure OMI_FMAN */ ++ ome = &omt[OMI_FMAN]; ++ ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_READI; ++ ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WWSA; ++ ++ /* Configure OMI_QMAN private */ ++ ome = &omt[OMI_QMAN_PRIV]; ++ ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_READ; ++ ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WRITE; ++ ome->moe[IOE_EREAD0_IDX] = EOE_VALID | EOE_RSA; ++ ome->moe[IOE_EWRITE0_IDX] = EOE_VALID | EOE_WWSA; ++ ++ /* Configure OMI_CAAM */ ++ ome = &omt[OMI_CAAM]; ++ ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_READI; ++ ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WRITE; ++} ++ ++static u32 __init get_stash_id(unsigned int stash_dest_hint, ++ struct device_node *portal_dn) ++{ ++ const u32 *prop; ++ struct device_node *node; ++ unsigned int cache_level; ++ ++ /* Fastpath, exit early if 3/CPC cache is target for stashing */ ++ if (stash_dest_hint == 3) { ++ node = of_find_compatible_node(NULL, NULL, ++ "fsl,p4080-l3-cache-controller"); ++ if (node) { ++ prop = of_get_property(node, "cache-stash-id", 0); ++ if (!prop) { ++ pr_err("fsl-pamu: missing cache-stash-id in " ++ " %s\n", node->full_name); ++ of_node_put(node); ++ return ~(u32)0; ++ } ++ of_node_put(node); ++ return *prop; ++ } ++ return ~(u32)0; ++ } ++ ++ prop = of_get_property(portal_dn, "cpu-handle", 0); ++ /* if no cpu-phandle assume that this is not a per-cpu portal */ ++ if (!prop) ++ return ~(u32)0; ++ ++ node = of_find_node_by_phandle(*prop); ++ if (!node) { ++ pr_err("fsl-pamu: bad cpu-handle reference in %s\n", ++ portal_dn->full_name); ++ return ~(u32)0; ++ } ++ ++ /* find the hwnode that represents the cache */ ++ for (cache_level = 1; cache_level <= 3; cache_level++) { ++ if (stash_dest_hint == cache_level) { ++ prop = of_get_property(node, "cache-stash-id", 0); ++ of_node_put(node); ++ if (!prop) { ++ pr_err("fsl-pamu: missing cache-stash-id in " ++ "%s\n", node->full_name); ++ return ~(u32)0; ++ } ++ return *prop; ++ } ++ ++ prop = of_get_property(node, "next-level-cache", 0); ++ if (!prop) { ++ pr_err("fsl-pamu: can't find next-level-cache in %s\n", ++ node->full_name); ++ of_node_put(node); ++ return ~(u32)0; /* can't traverse any further */ ++ } ++ of_node_put(node); ++ ++ /* advance to next node in cache hierarchy */ ++ node = of_find_node_by_phandle(*prop); ++ if (!node) { ++ pr_err("fsl-pamu: bad cpu phandle reference in %s\n", ++ portal_dn->full_name); ++ return ~(u32)0; ++ } ++ } ++ ++ pr_err("fsl-pamu: stash destination not found for cache level %d " ++ "on portal node %s\n", stash_dest_hint, portal_dn->full_name); ++ ++ return ~(u32)0; ++} ++ ++#ifdef CONFIG_FSL_FMAN_CPC_STASH ++static void __init enable_fman_io_stashing(struct device_node *dn) ++{ ++ const u32 *prop; ++ struct ppaace *ppaace; ++ u32 cache_id; ++ ++ prop = of_get_property(dn, "fsl,liodn", NULL); ++ if (prop) { ++ ppaace = &ppaact[*prop]; ++ ppaace->otm = PAACE_OTM_INDEXED; ++ ppaace->domain_attr.to_host.coherency_required = 1; ++ ppaace->op_encode.index_ot.omi = OMI_FMAN; ++ cache_id = get_stash_id(3, NULL); ++ pr_debug("%s cache_stash_id = %d\n", dn->full_name, cache_id); ++ if (~cache_id != 0) ++ ppaace->impl_attr.cid = cache_id; ++ } else { ++ pr_err("fsl-pamu: missing fsl,liodn property in %s\n", ++ dn->full_name); ++ } ++} ++#endif ++ ++static void __init setup_liodns(void) ++{ ++ int i, len; ++ struct ppaace *ppaace; ++ struct device_node *qman_portal_dn = NULL; ++ struct device_node *qman_dn = NULL; ++ struct device_node *bman_dn; ++ const u32 *prop; ++ u32 cache_id, prop_cnt; ++#ifdef CONFIG_FSL_FMAN_CPC_STASH ++ struct device_node *port_dn; ++#endif ++ ++ for (i = 0; i < PAACE_NUMBER_ENTRIES; i++) { ++ ppaace = &ppaact[i]; ++ ppaace->pt = PAACE_PT_PRIMARY; ++ ppaace->domain_attr.to_host.coherency_required = ++ PAACE_M_COHERENCE_REQ; ++ /* window size is 2^(WSE+1) bytes */ ++ ppaace->wse = 35; /* 36-bit phys. addr space */ ++ ppaace->wbah = ppaace->wbal = 0; ++ ppaace->atm = PAACE_ATM_NO_XLATE; ++ ppaace->ap = PAACE_AP_PERMS_ALL; ++ mb(); ++ ppaace->v = 1; ++ } ++ ++ /* ++ * Now, do specific stashing setup for qman portals. ++ * We need stashing setup for LIODNs for qman portal(s) dqrr stashing ++ * (DLIODNs), qman portal(s) data stashing (FLIODNs) ++ */ ++ ++ for_each_compatible_node(qman_portal_dn, NULL, "fsl,qman-portal") { ++ pr_debug("qman portal %s found\n", qman_portal_dn->full_name); ++ ++ prop = of_get_property(qman_portal_dn, "fsl,liodn", &len); ++ if (prop) { ++ prop_cnt = len / sizeof(u32); ++ do { ++ pr_debug("liodn = %d\n", *prop); ++ ppaace = &ppaact[*prop++]; ++ ppaace->otm = PAACE_OTM_INDEXED; ++ ppaace->op_encode.index_ot.omi = OMI_QMAN; ++ cache_id = get_stash_id(3, qman_portal_dn); ++ pr_debug("cache_stash_id = %d\n", cache_id); ++ if (~cache_id != 0) ++ ppaace->impl_attr.cid = cache_id; ++ } while (--prop_cnt); ++ } else { ++ pr_err("fsl-pamu: missing fsl,liodn property in %s\n", ++ qman_portal_dn->full_name); ++ } ++ } ++ ++ /* ++ * Next, do stashing setups for qman private memory access ++ */ ++ ++ qman_dn = of_find_compatible_node(NULL, NULL, "fsl,qman"); ++ if (qman_dn) { ++ prop = of_get_property(qman_dn, "fsl,liodn", NULL); ++ if (prop) { ++ ppaace = &ppaact[*prop]; ++ ppaace->otm = PAACE_OTM_INDEXED; ++ ppaace->domain_attr.to_host.coherency_required = 0; ++ ppaace->op_encode.index_ot.omi = OMI_QMAN_PRIV; ++ cache_id = get_stash_id(3, qman_dn); ++ pr_debug("cache_stash_id = %d\n", cache_id); ++ if (~cache_id != 0) ++ ppaace->impl_attr.cid = cache_id; ++ } else { ++ pr_err("fsl-pamu: missing fsl,liodn property in %s\n", ++ qman_dn->full_name); ++ } ++ of_node_put(qman_dn); ++ } ++ ++#ifdef CONFIG_FSL_FMAN_CPC_STASH ++ port_dn = NULL; ++ for_each_compatible_node(port_dn, NULL, "fsl,fman-port-10g-rx") ++ enable_fman_io_stashing(port_dn); ++ ++ port_dn = NULL; ++ for_each_compatible_node(port_dn, NULL, "fsl,fman-port-1g-rx") ++ enable_fman_io_stashing(port_dn); ++#endif ++ /* ++ * For liodn used by BMAN for its private memory accesses, ++ * turn the 'coherency required' off. This saves snoops to cores. ++ */ ++ ++ bman_dn = of_find_compatible_node(NULL, NULL, "fsl,bman"); ++ if (bman_dn) { ++ prop = of_get_property(bman_dn, "fsl,liodn", NULL); ++ if (prop) { ++ ppaace = &ppaact[*prop]; ++ ppaace->domain_attr.to_host.coherency_required = 0; ++ } else { ++ pr_err("fsl-pamu: missing fsl,liodn property in %s\n", ++ bman_dn->full_name); ++ } ++ of_node_put(bman_dn); ++ } ++} ++ ++static int __init setup_one_pamu(void *pamu_reg_base, struct ome *omt) ++{ ++ struct pamu_mmap_regs *pamu_regs = pamu_reg_base + PAMU_MMAP_REGS_BASE; ++ phys_addr_t phys; ++ ++ /* set up pointers to corenet control blocks */ ++ ++ phys = ppaact_phys; ++ out_be32(&pamu_regs->ppbah, upper_32_bits(phys)); ++ out_be32(&pamu_regs->ppbal, lower_32_bits(phys)); ++ ++ phys = ppaact_phys + PAACE_NUMBER_ENTRIES * sizeof(struct ppaace); ++ out_be32(&pamu_regs->pplah, upper_32_bits(phys)); ++ out_be32(&pamu_regs->pplal, lower_32_bits(phys)); ++ ++ phys = virt_to_phys(omt); ++ out_be32(&pamu_regs->obah, upper_32_bits(phys)); ++ out_be32(&pamu_regs->obal, lower_32_bits(phys)); ++ ++ phys = virt_to_phys(omt + OME_NUMBER_ENTRIES); ++ out_be32(&pamu_regs->olah, upper_32_bits(phys)); ++ out_be32(&pamu_regs->olal, lower_32_bits(phys)); ++ ++ ++ /* ++ * set PAMU enable bit, ++ * allow ppaact & omt to be cached ++ * & enable PAMU access violation interrupts. ++ */ ++ ++ out_be32(pamu_reg_base + PAMU_PICS, PAMU_ACCESS_VIOLATION_ENABLE); ++ out_be32(pamu_reg_base + PAMU_PC, ++ PAMU_PC_PE | PAMU_PC_OCE | PAMU_PC_SPCC | PAMU_PC_PPCC); ++ ++ return 0; ++} ++ ++#define make64(high, low) (((u64)(high) << 32) | (low)) ++ ++struct pamu_isr_data { ++ void __iomem *pamu_reg_base; /* Base address of PAMU regs*/ ++ unsigned int count; /* The number of PAMUs */ ++}; ++ ++static irqreturn_t pamu_av_isr(int irq, void *arg) ++{ ++ struct pamu_isr_data *data = arg; ++ phys_addr_t phys; ++ unsigned int i, j; ++ ++ pr_emerg("fsl-pamu: access violation interrupt\n"); ++ ++ for (i = 0; i < data->count; i++) { ++ void __iomem *p = data->pamu_reg_base + i * PAMU_OFFSET; ++ u32 pics = in_be32(p + PAMU_PICS); ++ ++ if (pics & PAMU_ACCESS_VIOLATION_STAT) { ++ pr_emerg("POES1=%08x\n", in_be32(p + PAMU_POES1)); ++ pr_emerg("POES2=%08x\n", in_be32(p + PAMU_POES2)); ++ pr_emerg("AVS1=%08x\n", in_be32(p + PAMU_AVS1)); ++ pr_emerg("AVS2=%08x\n", in_be32(p + PAMU_AVS2)); ++ pr_emerg("AVA=%016llx\n", make64(in_be32(p + PAMU_AVAH), ++ in_be32(p + PAMU_AVAL))); ++ pr_emerg("UDAD=%08x\n", in_be32(p + PAMU_UDAD)); ++ pr_emerg("POEA=%016llx\n", make64(in_be32(p + PAMU_POEAH), ++ in_be32(p + PAMU_POEAL))); ++ ++ phys = make64(in_be32(p + PAMU_POEAH), ++ in_be32(p + PAMU_POEAL)); ++ ++ /* Assume that POEA points to a PAACE */ ++ if (phys) { ++ u32 *paace = phys_to_virt(phys); ++ ++ /* Only the first four words are relevant */ ++ for (j = 0; j < 4; j++) ++ pr_emerg("PAACE[%u]=%08x\n", j, in_be32(paace + j)); ++ } ++ } ++ } ++ ++ panic("\n"); ++ ++ /* NOT REACHED */ ++ return IRQ_HANDLED; ++} ++ ++#ifdef CONFIG_FSL_PAMU_ERRATUM_A_004510 ++ ++/* ++ * The work-around for erratum A-004510 says we need to create a coherency ++ * subdomain (CSD), which means we need to create a LAW (local access window) ++ * just for the PAACT and OMT, and then give it a unique CSD ID. Linux ++ * normally doesn't touch the LAWs, so we define everything here. ++ */ ++ ++#define LAWAR_EN 0x80000000 ++#define LAWAR_TARGET_MASK 0x0FF00000 ++#define LAWAR_TARGET_SHIFT 20 ++#define LAWAR_SIZE_MASK 0x0000003F ++#define LAWAR_CSDID_MASK 0x000FF000 ++#define LAWAR_CSDID_SHIFT 12 ++ ++#define LAW_SIZE_4K 0xb ++ ++struct ccsr_law { ++ u32 lawbarh; /* LAWn base address high */ ++ u32 lawbarl; /* LAWn base address low */ ++ u32 lawar; /* LAWn attributes */ ++ u32 reserved; ++}; ++ ++/* ++ * Create a coherence subdomain for a given memory block. ++ */ ++static int __init create_csd(phys_addr_t phys, size_t size, u32 csd_port_id) ++{ ++ struct device_node *np; ++ const __be32 *iprop; ++ void __iomem *lac = NULL; /* Local Access Control registers */ ++ struct ccsr_law __iomem *law; ++ void __iomem *ccm = NULL; ++ u32 __iomem *csdids; ++ unsigned int i, num_laws, num_csds; ++ u32 law_target = 0; ++ u32 csd_id = 0; ++ int ret = 0; ++ ++ np = of_find_compatible_node(NULL, NULL, "fsl,corenet-law"); ++ if (!np) ++ return -ENODEV; ++ ++ iprop = of_get_property(np, "fsl,num-laws", NULL); ++ if (!iprop) { ++ ret = -ENODEV; ++ goto error; ++ } ++ ++ num_laws = be32_to_cpup(iprop); ++ if (!num_laws) { ++ ret = -ENODEV; ++ goto error; ++ } ++ ++ lac = of_iomap(np, 0); ++ if (!lac) { ++ ret = -ENODEV; ++ goto error; ++ } ++ ++ /* LAW registers are at offset 0xC00 */ ++ law = lac + 0xC00; ++ ++ of_node_put(np); ++ ++ np = of_find_compatible_node(NULL, NULL, "fsl,corenet-cf"); ++ if (!np) { ++ ret = -ENODEV; ++ goto error; ++ } ++ ++ iprop = of_get_property(np, "fsl,ccf-num-csdids", NULL); ++ if (!iprop) { ++ ret = -ENODEV; ++ goto error; ++ } ++ ++ num_csds = be32_to_cpup(iprop); ++ if (!num_csds) { ++ ret = -ENODEV; ++ goto error; ++ } ++ ++ ccm = of_iomap(np, 0); ++ if (!ccm) { ++ ret = -ENOMEM; ++ goto error; ++ } ++ ++ /* The undocumented CSDID registers are at offset 0x600 */ ++ csdids = ccm + 0x600; ++ ++ of_node_put(np); ++ np = NULL; ++ ++ /* Find an unused coherence subdomain ID */ ++ for (csd_id = 0; csd_id < num_csds; csd_id++) { ++ if (!csdids[csd_id]) ++ break; ++ } ++ ++ /* Store the Port ID in the (undocumented) proper CIDMRxx register */ ++ csdids[csd_id] = csd_port_id; ++ ++ /* Find the DDR LAW that maps to our buffer. */ ++ for (i = 0; i < num_laws; i++) { ++ if (law[i].lawar & LAWAR_EN) { ++ phys_addr_t law_start, law_end; ++ ++ law_start = make64(law[i].lawbarh, law[i].lawbarl); ++ law_end = law_start + ++ (2ULL << (law[i].lawar & LAWAR_SIZE_MASK)); ++ ++ if (law_start <= phys && phys < law_end) { ++ law_target = law[i].lawar & LAWAR_TARGET_MASK; ++ break; ++ } ++ } ++ } ++ ++ if (i == 0 || i == num_laws) { ++ /* This should never happen*/ ++ ret = -ENOENT; ++ goto error; ++ } ++ ++ /* Find a free LAW entry */ ++ while (law[--i].lawar & LAWAR_EN) { ++ if (i == 0) { ++ /* No higher priority LAW slots available */ ++ ret = -ENOENT; ++ goto error; ++ } ++ } ++ ++ law[i].lawbarh = upper_32_bits(phys); ++ law[i].lawbarl = lower_32_bits(phys); ++ wmb(); ++ law[i].lawar = LAWAR_EN | law_target | (csd_id << LAWAR_CSDID_SHIFT) | ++ (LAW_SIZE_4K + get_order(size)); ++ wmb(); ++ ++error: ++ if (ccm) ++ iounmap(ccm); ++ ++ if (lac) ++ iounmap(lac); ++ ++ if (np) ++ of_node_put(np); ++ ++ return ret; ++} ++#endif ++ ++/* ++ * Table of SVRs and the corresponding PORT_ID values. ++ * ++ * All future CoreNet-enabled SOCs will have this erratum fixed, so this table ++ * should never need to be updated. SVRs are guaranteed to be unique, so ++ * there is no worry that a future SOC will inadvertently have one of these ++ * values. ++ */ ++static const struct { ++ u32 svr; ++ u32 port_id; ++} port_id_map[] = { ++ {0x82100010, 0xFF000000}, /* P2040 1.0 */ ++ {0x82100011, 0xFF000000}, /* P2040 1.1 */ ++ {0x82100110, 0xFF000000}, /* P2041 1.0 */ ++ {0x82100111, 0xFF000000}, /* P2041 1.1 */ ++ {0x82110310, 0xFF000000}, /* P3041 1.0 */ ++ {0x82110311, 0xFF000000}, /* P3041 1.1 */ ++ {0x82010020, 0xFFF80000}, /* P4040 2.0 */ ++ {0x82000020, 0xFFF80000}, /* P4080 2.0 */ ++ {0x82210010, 0xFC000000}, /* P5010 1.0 */ ++ {0x82210020, 0xFC000000}, /* P5010 2.0 */ ++ {0x82200010, 0xFC000000}, /* P5020 1.0 */ ++ {0x82050010, 0xFF800000}, /* P5021 1.0 */ ++ {0x82040010, 0xFF800000}, /* P5040 1.0 */ ++}; ++ ++#define SVR_SECURITY 0x80000 /* The Security (E) bit */ ++ ++static struct of_device_id qoriq_device_config[] = { ++ { ++ .compatible = "fsl,qoriq-device-config-1.0", ++ }, ++ { ++ .compatible = "fsl,t4240-device-config", ++ }, ++ { ++ .compatible = "fsl,b4860-device-config", ++ }, ++ { ++ .compatible = "fsl,b4420-device-config", ++ }, ++ {} ++}; ++ ++static int __init fsl_pamu_probe(struct platform_device *pdev) ++{ ++ void __iomem *pamu_regs = NULL; ++ struct ccsr_guts_85xx __iomem *guts_regs = NULL; ++ u32 pamubypenr, pamu_counter; ++ unsigned long pamu_reg_off; ++ struct device_node *guts_node; ++ struct pamu_isr_data *data; ++ u64 size; ++ struct page *p; ++ int ret = 0; ++ struct ome *omt = NULL; ++ int irq; ++#ifdef CONFIG_FSL_PAMU_ERRATUM_A_004510 ++ size_t mem_size = 0; ++ unsigned int order = 0; ++ u32 csd_port_id = 0; ++ unsigned i; ++#endif ++ ++ /* ++ * enumerate all PAMUs and allocate and setup PAMU tables ++ * for each of them, ++ * NOTE : All PAMUs share the same LIODN tables. ++ */ ++ ++ pamu_regs = of_iomap(pdev->dev.of_node, 0); ++ if (!pamu_regs) { ++ dev_err(&pdev->dev, "ioremap of PAMU node failed\n"); ++ return -ENOMEM; ++ } ++ of_get_address(pdev->dev.of_node, 0, &size, NULL); ++ ++ data = kzalloc(sizeof(struct pamu_isr_data), GFP_KERNEL); ++ if (!data) { ++ iounmap(pamu_regs); ++ return -ENOMEM; ++ } ++ data->pamu_reg_base = pamu_regs; ++ data->count = size / PAMU_OFFSET; ++ ++ irq = irq_of_parse_and_map(pdev->dev.of_node, 0); ++ if (irq == NO_IRQ) { ++ dev_warn(&pdev->dev, "no interrupts listed in PAMU node\n"); ++ goto error; ++ } ++ ++ /* The ISR needs access to the regs, so we won't iounmap them */ ++ ret = request_irq(irq, pamu_av_isr, 0, "pamu", data); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "error %i installing ISR for irq %i\n", ++ ret, irq); ++ goto error; ++ } ++ ++ guts_node = of_find_matching_node(NULL, qoriq_device_config); ++ if (!guts_node) { ++ dev_err(&pdev->dev, "could not find GUTS node %s\n", ++ pdev->dev.of_node->full_name); ++ ret = -ENODEV; ++ goto error; ++ } ++ ++ guts_regs = of_iomap(guts_node, 0); ++ of_node_put(guts_node); ++ if (!guts_regs) { ++ dev_err(&pdev->dev, "ioremap of GUTS node failed\n"); ++ ret = -ENODEV; ++ goto error; ++ } ++ ++#ifdef CONFIG_FSL_PAMU_ERRATUM_A_004510 ++ /* ++ * To simplify the allocation of a coherency domain, we allocate the ++ * PAACT and the OMT in the same memory buffer. Unfortunately, this ++ * wastes more memory compared to allocating the buffers separately. ++ */ ++ ++ /* Determine how much memory we need */ ++ mem_size = (PAGE_SIZE << get_order(PAACT_SIZE)) + ++ (PAGE_SIZE << get_order(OMT_SIZE)); ++ order = get_order(mem_size); ++ ++ p = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); ++ if (!p) { ++ dev_err(&pdev->dev, "unable to allocate PAACT/OMT block\n"); ++ ret = -ENOMEM; ++ goto error; ++ } ++ ++ ppaact = page_address(p); ++ ppaact_phys = page_to_phys(p); ++ ++ /* Make sure the memory is naturally aligned */ ++ if (ppaact_phys & ((PAGE_SIZE << order) - 1)) { ++ dev_err(&pdev->dev, "PAACT/OMT block is unaligned\n"); ++ ret = -ENOMEM; ++ goto error; ++ } ++ ++ /* This assumes that PAACT_SIZE is larger than OMT_SIZE */ ++ omt = (void *)ppaact + (PAGE_SIZE << get_order(PAACT_SIZE)); ++ ++ dev_dbg(&pdev->dev, "ppaact virt=%p phys=0x%llx\n", ppaact, ++ (unsigned long long) ppaact_phys); ++ ++ dev_dbg(&pdev->dev, "omt virt=%p phys=0x%llx\n", omt, ++ (unsigned long long) virt_to_phys(omt)); ++ ++ /* Check to see if we need to implement the work-around on this SOC */ ++ ++ /* Determine the Port ID for our coherence subdomain */ ++ for (i = 0; i < ARRAY_SIZE(port_id_map); i++) { ++ if (port_id_map[i].svr == (mfspr(SPRN_SVR) & ~SVR_SECURITY)) { ++ csd_port_id = port_id_map[i].port_id; ++ dev_dbg(&pdev->dev, "found matching SVR %08x\n", ++ port_id_map[i].svr); ++ break; ++ } ++ } ++ ++ if (csd_port_id) { ++ dev_info(&pdev->dev, "implementing work-around for erratum " ++ "A-004510\n"); ++ dev_dbg(&pdev->dev, "creating coherency subdomain at address " ++ "0x%llx, size %zu, port id 0x%08x", ppaact_phys, ++ mem_size, csd_port_id); ++ ++ ret = create_csd(ppaact_phys, mem_size, csd_port_id); ++ if (ret) { ++ dev_err(&pdev->dev, "could not create coherence " ++ "subdomain\n"); ++ return ret; ++ } ++ } ++#else ++ p = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(PAACT_SIZE)); ++ if (!p) { ++ dev_err(&pdev->dev, "unable to allocate PAACT table\n"); ++ ret = -ENOMEM; ++ goto error; ++ } ++ ppaact = page_address(p); ++ ppaact_phys = page_to_phys(p); ++ ++ dev_dbg(&pdev->dev, "ppaact virt=%p phys=0x%llx\n", ppaact, ++ (unsigned long long) ppaact_phys); ++ ++ p = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(OMT_SIZE)); ++ if (!p) { ++ dev_err(&pdev->dev, "unable to allocate OMT table\n"); ++ ret = -ENOMEM; ++ goto error; ++ } ++ omt = page_address(p); ++ ++ dev_dbg(&pdev->dev, "omt virt=%p phys=0x%llx\n", omt, ++ (unsigned long long) page_to_phys(p)); ++#endif ++ ++ pamubypenr = in_be32(&guts_regs->pamubypenr); ++ ++ for (pamu_reg_off = 0, pamu_counter = 0x80000000; pamu_reg_off < size; ++ pamu_reg_off += PAMU_OFFSET, pamu_counter >>= 1) { ++ setup_one_pamu(pamu_regs + pamu_reg_off, omt); ++ ++ /* Disable PAMU bypass for this PAMU */ ++ pamubypenr &= ~pamu_counter; ++ } ++ ++ setup_omt(omt); ++ ++ /* ++ * setup all LIODNS(s) to define a 1:1 mapping for the entire ++ * 36-bit physical address space ++ */ ++ setup_liodns(); ++ mb(); ++ ++ /* Enable all relevant PAMU(s) */ ++ out_be32(&guts_regs->pamubypenr, pamubypenr); ++ ++ iounmap(guts_regs); ++ ++ return 0; ++ ++error: ++ if (irq != NO_IRQ) ++ free_irq(irq, 0); ++ ++ if (pamu_regs) ++ iounmap(pamu_regs); ++ ++ if (guts_regs) ++ iounmap(guts_regs); ++ ++#ifdef CONFIG_FSL_PAMU_ERRATUM_A_004510 ++ if (ppaact) ++ free_pages((unsigned long)ppaact, order); ++#else ++ if (ppaact) ++ free_pages((unsigned long)ppaact, get_order(PAACT_SIZE)); ++ ++ if (omt) ++ free_pages((unsigned long)omt, get_order(OMT_SIZE)); ++#endif ++ ++ ppaact = NULL; ++ ppaact_phys = 0; ++ ++ return ret; ++} ++ ++static struct platform_driver fsl_of_pamu_driver = { ++ .driver = { ++ .name = "fsl-of-pamu", ++ .owner = THIS_MODULE, ++ }, ++ .probe = fsl_pamu_probe, ++}; ++ ++static bool is_fsl_hypervisor(void) ++{ ++ struct device_node *np; ++ struct property *prop; ++ ++ np = of_find_node_by_path("/hypervisor"); ++ if (!np) ++ return false; ++ ++ prop = of_find_property(np, "fsl,has-stash-attr-hcall", NULL); ++ of_node_put(np); ++ ++ if (!prop) ++ pr_notice("fsl-pamu: this hypervisor does not support the " ++ "stash attribute hypercall\n"); ++ ++ return !!prop; ++} ++ ++static __init int fsl_pamu_init(void) ++{ ++ struct platform_device *pdev = NULL; ++ struct device_node *np; ++ int ret; ++ ++ /* ++ * The normal OF process calls the probe function at some ++ * indeterminate later time, after most drivers have loaded. This is ++ * too late for us, because PAMU clients (like the Qman driver) ++ * depend on PAMU being initialized early. ++ * ++ * So instead, we "manually" call our probe function by creating the ++ * platform devices ourselves. ++ */ ++ ++ /* ++ * We assume that there is only one PAMU node in the device tree. A ++ * single PAMU node represents all of the PAMU devices in the SOC ++ * already. Everything else already makes that assumption, and the ++ * binding for the PAMU nodes doesn't allow for any parent-child ++ * relationships anyway. In other words, support for more than one ++ * PAMU node would require significant changes to a lot of code. ++ */ ++ ++ np = of_find_compatible_node(NULL, NULL, "fsl,pamu"); ++ if (!np) { ++ /* No PAMU nodes, so check for a hypervisor */ ++ if (is_fsl_hypervisor()) { ++ has_fsl_hypervisor = true; ++ /* Remain resident, but we don't need a platform */ ++ return 0; ++ } ++ ++ pr_err("fsl-pamu: could not find a PAMU node\n"); ++ return -ENODEV; ++ } ++ ++ ret = platform_driver_register(&fsl_of_pamu_driver); ++ if (ret) { ++ pr_err("fsl-pamu: could not register driver (err=%i)\n", ret); ++ goto error_driver_register; ++ } ++ ++ pdev = platform_device_alloc("fsl-of-pamu", 0); ++ if (!pdev) { ++ pr_err("fsl-pamu: could not allocate device %s\n", ++ np->full_name); ++ ret = -ENOMEM; ++ goto error_device_alloc; ++ } ++ pdev->dev.of_node = of_node_get(np); ++ ++ ret = platform_device_add(pdev); ++ if (ret) { ++ pr_err("fsl-pamu: could not add device %s (err=%i)\n", ++ np->full_name, ret); ++ goto error_device_add; ++ } ++ ++ return 0; ++ ++error_device_add: ++ of_node_put(pdev->dev.of_node); ++ pdev->dev.of_node = NULL; ++ ++ platform_device_put(pdev); ++ ++error_device_alloc: ++ platform_driver_unregister(&fsl_of_pamu_driver); ++ ++error_driver_register: ++ of_node_put(np); ++ ++ return ret; ++} ++ ++arch_initcall(fsl_pamu_init); +diff --git a/arch/powerpc/sysdev/fsl_pamu.h b/arch/powerpc/sysdev/fsl_pamu.h +new file mode 100644 +index 0000000..b816812 +--- /dev/null ++++ b/arch/powerpc/sysdev/fsl_pamu.h +@@ -0,0 +1,58 @@ ++/* Copyright (c) 2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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 FSL_PAMU_H ++#define FSL_PAMU_H ++ ++#ifdef CONFIG_FSL_PAMU ++ ++/* Set the stash target for a given LIODN */ ++int pamu_set_stash_dest(struct device_node *node, unsigned int index, ++ unsigned int cpu, unsigned int cache_level); ++ ++int pamu_get_liodn_count(struct device_node *node); ++ ++#else ++ ++static inline int pamu_set_stash_dest(struct device_node *node, unsigned int index, ++ unsigned int cpu, unsigned int cache_level) ++{ ++ return -ENOSYS; ++} ++ ++static inline int pamu_get_liodn_count(struct device_node *node) ++{ ++ return 0; ++} ++ ++#endif ++ ++#endif +diff --git a/arch/powerpc/sysdev/micropatch.c b/arch/powerpc/sysdev/micropatch.c +deleted file mode 100644 +index c0bb76e..0000000 +--- a/arch/powerpc/sysdev/micropatch.c ++++ /dev/null +@@ -1,749 +0,0 @@ +- +-/* Microcode patches for the CPM as supplied by Motorola. +- * This is the one for IIC/SPI. There is a newer one that +- * also relocates SMC2, but this would require additional changes +- * to uart.c, so I am holding off on that for a moment. +- */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* +- * I2C/SPI relocation patch arrays. +- */ +- +-#ifdef CONFIG_I2C_SPI_UCODE_PATCH +- +-static uint patch_2000[] __initdata = { +- 0x7FFFEFD9, +- 0x3FFD0000, +- 0x7FFB49F7, +- 0x7FF90000, +- 0x5FEFADF7, +- 0x5F89ADF7, +- 0x5FEFAFF7, +- 0x5F89AFF7, +- 0x3A9CFBC8, +- 0xE7C0EDF0, +- 0x77C1E1BB, +- 0xF4DC7F1D, +- 0xABAD932F, +- 0x4E08FDCF, +- 0x6E0FAFF8, +- 0x7CCF76CF, +- 0xFD1FF9CF, +- 0xABF88DC6, +- 0xAB5679F7, +- 0xB0937383, +- 0xDFCE79F7, +- 0xB091E6BB, +- 0xE5BBE74F, +- 0xB3FA6F0F, +- 0x6FFB76CE, +- 0xEE0DF9CF, +- 0x2BFBEFEF, +- 0xCFEEF9CF, +- 0x76CEAD24, +- 0x90B2DF9A, +- 0x7FDDD0BF, +- 0x4BF847FD, +- 0x7CCF76CE, +- 0xCFEF7E1F, +- 0x7F1D7DFD, +- 0xF0B6EF71, +- 0x7FC177C1, +- 0xFBC86079, +- 0xE722FBC8, +- 0x5FFFDFFF, +- 0x5FB2FFFB, +- 0xFBC8F3C8, +- 0x94A67F01, +- 0x7F1D5F39, +- 0xAFE85F5E, +- 0xFFDFDF96, +- 0xCB9FAF7D, +- 0x5FC1AFED, +- 0x8C1C5FC1, +- 0xAFDD5FC3, +- 0xDF9A7EFD, +- 0xB0B25FB2, +- 0xFFFEABAD, +- 0x5FB2FFFE, +- 0x5FCE600B, +- 0xE6BB600B, +- 0x5FCEDFC6, +- 0x27FBEFDF, +- 0x5FC8CFDE, +- 0x3A9CE7C0, +- 0xEDF0F3C8, +- 0x7F0154CD, +- 0x7F1D2D3D, +- 0x363A7570, +- 0x7E0AF1CE, +- 0x37EF2E68, +- 0x7FEE10EC, +- 0xADF8EFDE, +- 0xCFEAE52F, +- 0x7D0FE12B, +- 0xF1CE5F65, +- 0x7E0A4DF8, +- 0xCFEA5F72, +- 0x7D0BEFEE, +- 0xCFEA5F74, +- 0xE522EFDE, +- 0x5F74CFDA, +- 0x0B627385, +- 0xDF627E0A, +- 0x30D8145B, +- 0xBFFFF3C8, +- 0x5FFFDFFF, +- 0xA7F85F5E, +- 0xBFFE7F7D, +- 0x10D31450, +- 0x5F36BFFF, +- 0xAF785F5E, +- 0xBFFDA7F8, +- 0x5F36BFFE, +- 0x77FD30C0, +- 0x4E08FDCF, +- 0xE5FF6E0F, +- 0xAFF87E1F, +- 0x7E0FFD1F, +- 0xF1CF5F1B, +- 0xABF80D5E, +- 0x5F5EFFEF, +- 0x79F730A2, +- 0xAFDD5F34, +- 0x47F85F34, +- 0xAFED7FDD, +- 0x50B24978, +- 0x47FD7F1D, +- 0x7DFD70AD, +- 0xEF717EC1, +- 0x6BA47F01, +- 0x2D267EFD, +- 0x30DE5F5E, +- 0xFFFD5F5E, +- 0xFFEF5F5E, +- 0xFFDF0CA0, +- 0xAFED0A9E, +- 0xAFDD0C3A, +- 0x5F3AAFBD, +- 0x7FBDB082, +- 0x5F8247F8 +-}; +- +-static uint patch_2f00[] __initdata = { +- 0x3E303430, +- 0x34343737, +- 0xABF7BF9B, +- 0x994B4FBD, +- 0xBD599493, +- 0x349FFF37, +- 0xFB9B177D, +- 0xD9936956, +- 0xBBFDD697, +- 0xBDD2FD11, +- 0x31DB9BB3, +- 0x63139637, +- 0x93733693, +- 0x193137F7, +- 0x331737AF, +- 0x7BB9B999, +- 0xBB197957, +- 0x7FDFD3D5, +- 0x73B773F7, +- 0x37933B99, +- 0x1D115316, +- 0x99315315, +- 0x31694BF4, +- 0xFBDBD359, +- 0x31497353, +- 0x76956D69, +- 0x7B9D9693, +- 0x13131979, +- 0x79376935 +-}; +-#endif +- +-/* +- * I2C/SPI/SMC1 relocation patch arrays. +- */ +- +-#ifdef CONFIG_I2C_SPI_SMC1_UCODE_PATCH +- +-static uint patch_2000[] __initdata = { +- 0x3fff0000, +- 0x3ffd0000, +- 0x3ffb0000, +- 0x3ff90000, +- 0x5f13eff8, +- 0x5eb5eff8, +- 0x5f88adf7, +- 0x5fefadf7, +- 0x3a9cfbc8, +- 0x77cae1bb, +- 0xf4de7fad, +- 0xabae9330, +- 0x4e08fdcf, +- 0x6e0faff8, +- 0x7ccf76cf, +- 0xfdaff9cf, +- 0xabf88dc8, +- 0xab5879f7, +- 0xb0925d8d, +- 0xdfd079f7, +- 0xb090e6bb, +- 0xe5bbe74f, +- 0x9e046f0f, +- 0x6ffb76ce, +- 0xee0cf9cf, +- 0x2bfbefef, +- 0xcfeef9cf, +- 0x76cead23, +- 0x90b3df99, +- 0x7fddd0c1, +- 0x4bf847fd, +- 0x7ccf76ce, +- 0xcfef77ca, +- 0x7eaf7fad, +- 0x7dfdf0b7, +- 0xef7a7fca, +- 0x77cafbc8, +- 0x6079e722, +- 0xfbc85fff, +- 0xdfff5fb3, +- 0xfffbfbc8, +- 0xf3c894a5, +- 0xe7c9edf9, +- 0x7f9a7fad, +- 0x5f36afe8, +- 0x5f5bffdf, +- 0xdf95cb9e, +- 0xaf7d5fc3, +- 0xafed8c1b, +- 0x5fc3afdd, +- 0x5fc5df99, +- 0x7efdb0b3, +- 0x5fb3fffe, +- 0xabae5fb3, +- 0xfffe5fd0, +- 0x600be6bb, +- 0x600b5fd0, +- 0xdfc827fb, +- 0xefdf5fca, +- 0xcfde3a9c, +- 0xe7c9edf9, +- 0xf3c87f9e, +- 0x54ca7fed, +- 0x2d3a3637, +- 0x756f7e9a, +- 0xf1ce37ef, +- 0x2e677fee, +- 0x10ebadf8, +- 0xefdecfea, +- 0xe52f7d9f, +- 0xe12bf1ce, +- 0x5f647e9a, +- 0x4df8cfea, +- 0x5f717d9b, +- 0xefeecfea, +- 0x5f73e522, +- 0xefde5f73, +- 0xcfda0b61, +- 0x5d8fdf61, +- 0xe7c9edf9, +- 0x7e9a30d5, +- 0x1458bfff, +- 0xf3c85fff, +- 0xdfffa7f8, +- 0x5f5bbffe, +- 0x7f7d10d0, +- 0x144d5f33, +- 0xbfffaf78, +- 0x5f5bbffd, +- 0xa7f85f33, +- 0xbffe77fd, +- 0x30bd4e08, +- 0xfdcfe5ff, +- 0x6e0faff8, +- 0x7eef7e9f, +- 0xfdeff1cf, +- 0x5f17abf8, +- 0x0d5b5f5b, +- 0xffef79f7, +- 0x309eafdd, +- 0x5f3147f8, +- 0x5f31afed, +- 0x7fdd50af, +- 0x497847fd, +- 0x7f9e7fed, +- 0x7dfd70a9, +- 0xef7e7ece, +- 0x6ba07f9e, +- 0x2d227efd, +- 0x30db5f5b, +- 0xfffd5f5b, +- 0xffef5f5b, +- 0xffdf0c9c, +- 0xafed0a9a, +- 0xafdd0c37, +- 0x5f37afbd, +- 0x7fbdb081, +- 0x5f8147f8, +- 0x3a11e710, +- 0xedf0ccdd, +- 0xf3186d0a, +- 0x7f0e5f06, +- 0x7fedbb38, +- 0x3afe7468, +- 0x7fedf4fc, +- 0x8ffbb951, +- 0xb85f77fd, +- 0xb0df5ddd, +- 0xdefe7fed, +- 0x90e1e74d, +- 0x6f0dcbf7, +- 0xe7decfed, +- 0xcb74cfed, +- 0xcfeddf6d, +- 0x91714f74, +- 0x5dd2deef, +- 0x9e04e7df, +- 0xefbb6ffb, +- 0xe7ef7f0e, +- 0x9e097fed, +- 0xebdbeffa, +- 0xeb54affb, +- 0x7fea90d7, +- 0x7e0cf0c3, +- 0xbffff318, +- 0x5fffdfff, +- 0xac59efea, +- 0x7fce1ee5, +- 0xe2ff5ee1, +- 0xaffbe2ff, +- 0x5ee3affb, +- 0xf9cc7d0f, +- 0xaef8770f, +- 0x7d0fb0c6, +- 0xeffbbfff, +- 0xcfef5ede, +- 0x7d0fbfff, +- 0x5ede4cf8, +- 0x7fddd0bf, +- 0x49f847fd, +- 0x7efdf0bb, +- 0x7fedfffd, +- 0x7dfdf0b7, +- 0xef7e7e1e, +- 0x5ede7f0e, +- 0x3a11e710, +- 0xedf0ccab, +- 0xfb18ad2e, +- 0x1ea9bbb8, +- 0x74283b7e, +- 0x73c2e4bb, +- 0x2ada4fb8, +- 0xdc21e4bb, +- 0xb2a1ffbf, +- 0x5e2c43f8, +- 0xfc87e1bb, +- 0xe74ffd91, +- 0x6f0f4fe8, +- 0xc7ba32e2, +- 0xf396efeb, +- 0x600b4f78, +- 0xe5bb760b, +- 0x53acaef8, +- 0x4ef88b0e, +- 0xcfef9e09, +- 0xabf8751f, +- 0xefef5bac, +- 0x741f4fe8, +- 0x751e760d, +- 0x7fdbf081, +- 0x741cafce, +- 0xefcc7fce, +- 0x751e70ac, +- 0x741ce7bb, +- 0x3372cfed, +- 0xafdbefeb, +- 0xe5bb760b, +- 0x53f2aef8, +- 0xafe8e7eb, +- 0x4bf8771e, +- 0x7e247fed, +- 0x4fcbe2cc, +- 0x7fbc30a9, +- 0x7b0f7a0f, +- 0x34d577fd, +- 0x308b5db7, +- 0xde553e5f, +- 0xaf78741f, +- 0x741f30f0, +- 0xcfef5e2c, +- 0x741f3eac, +- 0xafb8771e, +- 0x5e677fed, +- 0x0bd3e2cc, +- 0x741ccfec, +- 0xe5ca53cd, +- 0x6fcb4f74, +- 0x5dadde4b, +- 0x2ab63d38, +- 0x4bb3de30, +- 0x751f741c, +- 0x6c42effa, +- 0xefea7fce, +- 0x6ffc30be, +- 0xefec3fca, +- 0x30b3de2e, +- 0xadf85d9e, +- 0xaf7daefd, +- 0x5d9ede2e, +- 0x5d9eafdd, +- 0x761f10ac, +- 0x1da07efd, +- 0x30adfffe, +- 0x4908fb18, +- 0x5fffdfff, +- 0xafbb709b, +- 0x4ef85e67, +- 0xadf814ad, +- 0x7a0f70ad, +- 0xcfef50ad, +- 0x7a0fde30, +- 0x5da0afed, +- 0x3c12780f, +- 0xefef780f, +- 0xefef790f, +- 0xa7f85e0f, +- 0xffef790f, +- 0xefef790f, +- 0x14adde2e, +- 0x5d9eadfd, +- 0x5e2dfffb, +- 0xe79addfd, +- 0xeff96079, +- 0x607ae79a, +- 0xddfceff9, +- 0x60795dff, +- 0x607acfef, +- 0xefefefdf, +- 0xefbfef7f, +- 0xeeffedff, +- 0xebffe7ff, +- 0xafefafdf, +- 0xafbfaf7f, +- 0xaeffadff, +- 0xabffa7ff, +- 0x6fef6fdf, +- 0x6fbf6f7f, +- 0x6eff6dff, +- 0x6bff67ff, +- 0x2fef2fdf, +- 0x2fbf2f7f, +- 0x2eff2dff, +- 0x2bff27ff, +- 0x4e08fd1f, +- 0xe5ff6e0f, +- 0xaff87eef, +- 0x7e0ffdef, +- 0xf11f6079, +- 0xabf8f542, +- 0x7e0af11c, +- 0x37cfae3a, +- 0x7fec90be, +- 0xadf8efdc, +- 0xcfeae52f, +- 0x7d0fe12b, +- 0xf11c6079, +- 0x7e0a4df8, +- 0xcfea5dc4, +- 0x7d0befec, +- 0xcfea5dc6, +- 0xe522efdc, +- 0x5dc6cfda, +- 0x4e08fd1f, +- 0x6e0faff8, +- 0x7c1f761f, +- 0xfdeff91f, +- 0x6079abf8, +- 0x761cee24, +- 0xf91f2bfb, +- 0xefefcfec, +- 0xf91f6079, +- 0x761c27fb, +- 0xefdf5da7, +- 0xcfdc7fdd, +- 0xd09c4bf8, +- 0x47fd7c1f, +- 0x761ccfcf, +- 0x7eef7fed, +- 0x7dfdf093, +- 0xef7e7f1e, +- 0x771efb18, +- 0x6079e722, +- 0xe6bbe5bb, +- 0xae0ae5bb, +- 0x600bae85, +- 0xe2bbe2bb, +- 0xe2bbe2bb, +- 0xaf02e2bb, +- 0xe2bb2ff9, +- 0x6079e2bb +-}; +- +-static uint patch_2f00[] __initdata = { +- 0x30303030, +- 0x3e3e3434, +- 0xabbf9b99, +- 0x4b4fbdbd, +- 0x59949334, +- 0x9fff37fb, +- 0x9b177dd9, +- 0x936956bb, +- 0xfbdd697b, +- 0xdd2fd113, +- 0x1db9f7bb, +- 0x36313963, +- 0x79373369, +- 0x3193137f, +- 0x7331737a, +- 0xf7bb9b99, +- 0x9bb19795, +- 0x77fdfd3d, +- 0x573b773f, +- 0x737933f7, +- 0xb991d115, +- 0x31699315, +- 0x31531694, +- 0xbf4fbdbd, +- 0x35931497, +- 0x35376956, +- 0xbd697b9d, +- 0x96931313, +- 0x19797937, +- 0x6935af78, +- 0xb9b3baa3, +- 0xb8788683, +- 0x368f78f7, +- 0x87778733, +- 0x3ffffb3b, +- 0x8e8f78b8, +- 0x1d118e13, +- 0xf3ff3f8b, +- 0x6bd8e173, +- 0xd1366856, +- 0x68d1687b, +- 0x3daf78b8, +- 0x3a3a3f87, +- 0x8f81378f, +- 0xf876f887, +- 0x77fd8778, +- 0x737de8d6, +- 0xbbf8bfff, +- 0xd8df87f7, +- 0xfd876f7b, +- 0x8bfff8bd, +- 0x8683387d, +- 0xb873d87b, +- 0x3b8fd7f8, +- 0xf7338883, +- 0xbb8ee1f8, +- 0xef837377, +- 0x3337b836, +- 0x817d11f8, +- 0x7378b878, +- 0xd3368b7d, +- 0xed731b7d, +- 0x833731f3, +- 0xf22f3f23 +-}; +- +-static uint patch_2e00[] __initdata = { +- 0x27eeeeee, +- 0xeeeeeeee, +- 0xeeeeeeee, +- 0xeeeeeeee, +- 0xee4bf4fb, +- 0xdbd259bb, +- 0x1979577f, +- 0xdfd2d573, +- 0xb773f737, +- 0x4b4fbdbd, +- 0x25b9b177, +- 0xd2d17376, +- 0x956bbfdd, +- 0x697bdd2f, +- 0xff9f79ff, +- 0xff9ff22f +-}; +-#endif +- +-/* +- * USB SOF patch arrays. +- */ +- +-#ifdef CONFIG_USB_SOF_UCODE_PATCH +- +-static uint patch_2000[] __initdata = { +- 0x7fff0000, +- 0x7ffd0000, +- 0x7ffb0000, +- 0x49f7ba5b, +- 0xba383ffb, +- 0xf9b8b46d, +- 0xe5ab4e07, +- 0xaf77bffe, +- 0x3f7bbf79, +- 0xba5bba38, +- 0xe7676076, +- 0x60750000 +-}; +- +-static uint patch_2f00[] __initdata = { +- 0x3030304c, +- 0xcab9e441, +- 0xa1aaf220 +-}; +-#endif +- +-void __init cpm_load_patch(cpm8xx_t *cp) +-{ +- volatile uint *dp; /* Dual-ported RAM. */ +- volatile cpm8xx_t *commproc; +-#if defined(CONFIG_I2C_SPI_UCODE_PATCH) || \ +- defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH) +- volatile iic_t *iip; +- volatile struct spi_pram *spp; +-#ifdef CONFIG_I2C_SPI_SMC1_UCODE_PATCH +- volatile smc_uart_t *smp; +-#endif +-#endif +- int i; +- +- commproc = cp; +- +-#ifdef CONFIG_USB_SOF_UCODE_PATCH +- commproc->cp_rccr = 0; +- +- dp = (uint *)(commproc->cp_dpmem); +- for (i=0; i<(sizeof(patch_2000)/4); i++) +- *dp++ = patch_2000[i]; +- +- dp = (uint *)&(commproc->cp_dpmem[0x0f00]); +- for (i=0; i<(sizeof(patch_2f00)/4); i++) +- *dp++ = patch_2f00[i]; +- +- commproc->cp_rccr = 0x0009; +- +- printk("USB SOF microcode patch installed\n"); +-#endif /* CONFIG_USB_SOF_UCODE_PATCH */ +- +-#if defined(CONFIG_I2C_SPI_UCODE_PATCH) || \ +- defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH) +- +- commproc->cp_rccr = 0; +- +- dp = (uint *)(commproc->cp_dpmem); +- for (i=0; i<(sizeof(patch_2000)/4); i++) +- *dp++ = patch_2000[i]; +- +- dp = (uint *)&(commproc->cp_dpmem[0x0f00]); +- for (i=0; i<(sizeof(patch_2f00)/4); i++) +- *dp++ = patch_2f00[i]; +- +- iip = (iic_t *)&commproc->cp_dparam[PROFF_IIC]; +-# define RPBASE 0x0500 +- iip->iic_rpbase = RPBASE; +- +- /* Put SPI above the IIC, also 32-byte aligned. +- */ +- i = (RPBASE + sizeof(iic_t) + 31) & ~31; +- spp = (struct spi_pram *)&commproc->cp_dparam[PROFF_SPI]; +- spp->rpbase = i; +- +-# if defined(CONFIG_I2C_SPI_UCODE_PATCH) +- commproc->cp_cpmcr1 = 0x802a; +- commproc->cp_cpmcr2 = 0x8028; +- commproc->cp_cpmcr3 = 0x802e; +- commproc->cp_cpmcr4 = 0x802c; +- commproc->cp_rccr = 1; +- +- printk("I2C/SPI microcode patch installed.\n"); +-# endif /* CONFIG_I2C_SPI_UCODE_PATCH */ +- +-# if defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH) +- +- dp = (uint *)&(commproc->cp_dpmem[0x0e00]); +- for (i=0; i<(sizeof(patch_2e00)/4); i++) +- *dp++ = patch_2e00[i]; +- +- commproc->cp_cpmcr1 = 0x8080; +- commproc->cp_cpmcr2 = 0x808a; +- commproc->cp_cpmcr3 = 0x8028; +- commproc->cp_cpmcr4 = 0x802a; +- commproc->cp_rccr = 3; +- +- smp = (smc_uart_t *)&commproc->cp_dparam[PROFF_SMC1]; +- smp->smc_rpbase = 0x1FC0; +- +- printk("I2C/SPI/SMC1 microcode patch installed.\n"); +-# endif /* CONFIG_I2C_SPI_SMC1_UCODE_PATCH) */ +- +-#endif /* some variation of the I2C/SPI patch was selected */ +-} +- +-/* +- * Take this entire routine out, since no one calls it and its +- * logic is suspect. +- */ +- +-#if 0 +-void +-verify_patch(volatile immap_t *immr) +-{ +- volatile uint *dp; +- volatile cpm8xx_t *commproc; +- int i; +- +- commproc = (cpm8xx_t *)&immr->im_cpm; +- +- printk("cp_rccr %x\n", commproc->cp_rccr); +- commproc->cp_rccr = 0; +- +- dp = (uint *)(commproc->cp_dpmem); +- for (i=0; i<(sizeof(patch_2000)/4); i++) +- if (*dp++ != patch_2000[i]) { +- printk("patch_2000 bad at %d\n", i); +- dp--; +- printk("found 0x%X, wanted 0x%X\n", *dp, patch_2000[i]); +- break; +- } +- +- dp = (uint *)&(commproc->cp_dpmem[0x0f00]); +- for (i=0; i<(sizeof(patch_2f00)/4); i++) +- if (*dp++ != patch_2f00[i]) { +- printk("patch_2f00 bad at %d\n", i); +- dp--; +- printk("found 0x%X, wanted 0x%X\n", *dp, patch_2f00[i]); +- break; +- } +- +- commproc->cp_rccr = 0x0009; +-} +-#endif +diff --git a/arch/powerpc/sysdev/ppc4xx_cpm.c b/arch/powerpc/sysdev/ppc4xx_cpm.c +index 73b86cc..82e2cfe 100644 +--- a/arch/powerpc/sysdev/ppc4xx_cpm.c ++++ b/arch/powerpc/sysdev/ppc4xx_cpm.c +@@ -179,12 +179,12 @@ static struct kobj_attribute cpm_idle_attr = + + static void cpm_idle_config_sysfs(void) + { +- struct sys_device *sys_dev; ++ struct device *dev; + unsigned long ret; + +- sys_dev = get_cpu_sysdev(0); ++ dev = get_cpu_device(0); + +- ret = sysfs_create_file(&sys_dev->kobj, ++ ret = sysfs_create_file(&dev->kobj, + &cpm_idle_attr.attr); + if (ret) + printk(KERN_WARNING +diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c +index 1df64a8..ebd91cb 100644 +--- a/arch/s390/kernel/smp.c ++++ b/arch/s390/kernel/smp.c +@@ -831,8 +831,8 @@ int setup_profiling_timer(unsigned int multiplier) + } + + #ifdef CONFIG_HOTPLUG_CPU +-static ssize_t cpu_configure_show(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t cpu_configure_show(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + ssize_t count; + +@@ -842,8 +842,8 @@ static ssize_t cpu_configure_show(struct sys_device *dev, + return count; + } + +-static ssize_t cpu_configure_store(struct sys_device *dev, +- struct sysdev_attribute *attr, ++static ssize_t cpu_configure_store(struct device *dev, ++ struct device_attribute *attr, + const char *buf, size_t count) + { + int cpu = dev->id; +@@ -889,11 +889,11 @@ out: + put_online_cpus(); + return rc ? rc : count; + } +-static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store); ++static DEVICE_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store); + #endif /* CONFIG_HOTPLUG_CPU */ + +-static ssize_t cpu_polarization_show(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t cpu_polarization_show(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + int cpu = dev->id; + ssize_t count; +@@ -919,22 +919,22 @@ static ssize_t cpu_polarization_show(struct sys_device *dev, + mutex_unlock(&smp_cpu_state_mutex); + return count; + } +-static SYSDEV_ATTR(polarization, 0444, cpu_polarization_show, NULL); ++static DEVICE_ATTR(polarization, 0444, cpu_polarization_show, NULL); + +-static ssize_t show_cpu_address(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t show_cpu_address(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + return sprintf(buf, "%d\n", __cpu_logical_map[dev->id]); + } +-static SYSDEV_ATTR(address, 0444, show_cpu_address, NULL); ++static DEVICE_ATTR(address, 0444, show_cpu_address, NULL); + + + static struct attribute *cpu_common_attrs[] = { + #ifdef CONFIG_HOTPLUG_CPU +- &attr_configure.attr, ++ &dev_attr_configure.attr, + #endif +- &attr_address.attr, +- &attr_polarization.attr, ++ &dev_attr_address.attr, ++ &dev_attr_polarization.attr, + NULL, + }; + +@@ -942,8 +942,8 @@ static struct attribute_group cpu_common_attr_group = { + .attrs = cpu_common_attrs, + }; + +-static ssize_t show_capability(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t show_capability(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + unsigned int capability; + int rc; +@@ -953,10 +953,10 @@ static ssize_t show_capability(struct sys_device *dev, + return rc; + return sprintf(buf, "%u\n", capability); + } +-static SYSDEV_ATTR(capability, 0444, show_capability, NULL); ++static DEVICE_ATTR(capability, 0444, show_capability, NULL); + +-static ssize_t show_idle_count(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t show_idle_count(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + struct s390_idle_data *idle; + unsigned long long idle_count; +@@ -976,10 +976,10 @@ repeat: + goto repeat; + return sprintf(buf, "%llu\n", idle_count); + } +-static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL); ++static DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL); + +-static ssize_t show_idle_time(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t show_idle_time(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + struct s390_idle_data *idle; + unsigned long long now, idle_time, idle_enter; +@@ -1001,12 +1001,12 @@ repeat: + goto repeat; + return sprintf(buf, "%llu\n", idle_time >> 12); + } +-static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL); ++static DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL); + + static struct attribute *cpu_online_attrs[] = { +- &attr_capability.attr, +- &attr_idle_count.attr, +- &attr_idle_time_us.attr, ++ &dev_attr_capability.attr, ++ &dev_attr_idle_count.attr, ++ &dev_attr_idle_time_us.attr, + NULL, + }; + +@@ -1019,7 +1019,7 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, + { + unsigned int cpu = (unsigned int)(long)hcpu; + struct cpu *c = &per_cpu(cpu_devices, cpu); +- struct sys_device *s = &c->sysdev; ++ struct device *s = &c->dev; + int err = 0; + + switch (action) { +@@ -1042,7 +1042,7 @@ static struct notifier_block __cpuinitdata smp_cpu_nb = { + static int __devinit smp_add_present_cpu(int cpu) + { + struct cpu *c = &per_cpu(cpu_devices, cpu); +- struct sys_device *s = &c->sysdev; ++ struct device *s = &c->dev; + int rc; + + c->hotpluggable = 1; +@@ -1095,8 +1095,8 @@ out: + return rc; + } + +-static ssize_t __ref rescan_store(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t __ref rescan_store(struct device *dev, ++ struct device_attribute *attr, + const char *buf, + size_t count) + { +@@ -1105,11 +1105,11 @@ static ssize_t __ref rescan_store(struct sysdev_class *class, + rc = smp_rescan_cpus(); + return rc ? rc : count; + } +-static SYSDEV_CLASS_ATTR(rescan, 0200, NULL, rescan_store); ++static DEVICE_ATTR(rescan, 0200, NULL, rescan_store); + #endif /* CONFIG_HOTPLUG_CPU */ + +-static ssize_t dispatching_show(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t dispatching_show(struct device *dev, ++ struct device_attribute *attr, + char *buf) + { + ssize_t count; +@@ -1120,8 +1120,8 @@ static ssize_t dispatching_show(struct sysdev_class *class, + return count; + } + +-static ssize_t dispatching_store(struct sysdev_class *dev, +- struct sysdev_class_attribute *attr, ++static ssize_t dispatching_store(struct device *dev, ++ struct device_attribute *attr, + const char *buf, + size_t count) + { +@@ -1145,7 +1145,7 @@ out: + put_online_cpus(); + return rc ? rc : count; + } +-static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show, ++static DEVICE_ATTR(dispatching, 0644, dispatching_show, + dispatching_store); + + static int __init topology_init(void) +@@ -1156,11 +1156,11 @@ static int __init topology_init(void) + register_cpu_notifier(&smp_cpu_nb); + + #ifdef CONFIG_HOTPLUG_CPU +- rc = sysdev_class_create_file(&cpu_sysdev_class, &attr_rescan); ++ rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan); + if (rc) + return rc; + #endif +- rc = sysdev_class_create_file(&cpu_sysdev_class, &attr_dispatching); ++ rc = device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching); + if (rc) + return rc; + for_each_present_cpu(cpu) { +diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c +index fdb5b8c..6e0e29b 100644 +--- a/arch/s390/kernel/topology.c ++++ b/arch/s390/kernel/topology.c +@@ -261,7 +261,7 @@ void store_topology(struct sysinfo_15_1_x *info) + int arch_update_cpu_topology(void) + { + struct sysinfo_15_1_x *info = tl_info; +- struct sys_device *sysdev; ++ struct device *dev; + int cpu; + + if (!MACHINE_HAS_TOPOLOGY) { +@@ -273,8 +273,8 @@ int arch_update_cpu_topology(void) + tl_to_cores(info); + update_cpu_core_map(); + for_each_online_cpu(cpu) { +- sysdev = get_cpu_sysdev(cpu); +- kobject_uevent(&sysdev->kobj, KOBJ_CHANGE); ++ dev = get_cpu_device(cpu); ++ kobject_uevent(&dev->kobj, KOBJ_CHANGE); + } + return 1; + } +diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c +index a9807dd..06f1f7c 100644 +--- a/arch/s390/kernel/traps.c ++++ b/arch/s390/kernel/traps.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -166,11 +167,12 @@ static void show_last_breaking_event(struct pt_regs *regs) + */ + void dump_stack(void) + { +- printk("CPU: %d %s %s %.*s\n", ++ printk("CPU: %d %s %s %.*s%s\n", + task_thread_info(current)->cpu, print_tainted(), + init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), +- init_utsname()->version); ++ init_utsname()->version, ++ LINUX_PACKAGE_ID); + printk("Process %s (pid: %d, task: %p, ksp: %p)\n", + current->comm, current->pid, current, + (void *) current->thread.ksp); +@@ -217,11 +219,12 @@ void show_registers(struct pt_regs *regs) + void show_regs(struct pt_regs *regs) + { + print_modules(); +- printk("CPU: %d %s %s %.*s\n", ++ printk("CPU: %d %s %s %.*s%s\n", + task_thread_info(current)->cpu, print_tainted(), + init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), +- init_utsname()->version); ++ init_utsname()->version, ++ LINUX_PACKAGE_ID); + printk("Process %s (pid: %d, task: %p, ksp: %p)\n", + current->comm, current->pid, current, + (void *) current->thread.ksp); +diff --git a/arch/score/Kconfig b/arch/score/Kconfig +index beb9f21..9bcea17 100644 +--- a/arch/score/Kconfig ++++ b/arch/score/Kconfig +@@ -4,6 +4,7 @@ config SCORE + def_bool y + select HAVE_GENERIC_HARDIRQS + select GENERIC_IRQ_SHOW ++ select GENERIC_CPU_DEVICES + + choice + prompt "System type" +diff --git a/arch/sh/Makefile b/arch/sh/Makefile +index 3fc0f41..ebb6849 100644 +--- a/arch/sh/Makefile ++++ b/arch/sh/Makefile +@@ -75,7 +75,6 @@ OBJCOPYFLAGS := -O binary -R .note -R .note.gnu.build-id -R .comment \ + + # Give the various platforms the opportunity to set default image types + defaultimage-$(CONFIG_SUPERH32) := zImage +-defaultimage-$(CONFIG_SH_SH7785LCR) := uImage + defaultimage-$(CONFIG_SH_RSK) := uImage + defaultimage-$(CONFIG_SH_URQUELL) := uImage + defaultimage-$(CONFIG_SH_MIGOR) := uImage +diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c +index f090799..0a47bd3 100644 +--- a/arch/sh/kernel/cpu/sh4/sq.c ++++ b/arch/sh/kernel/cpu/sh4/sq.c +@@ -13,7 +13,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -337,9 +337,9 @@ static struct kobj_type ktype_percpu_entry = { + .default_attrs = sq_sysfs_attrs, + }; + +-static int __devinit sq_sysdev_add(struct sys_device *sysdev) ++static int sq_dev_add(struct device *dev, struct subsys_interface *sif) + { +- unsigned int cpu = sysdev->id; ++ unsigned int cpu = dev->id; + struct kobject *kobj; + int error; + +@@ -348,25 +348,27 @@ static int __devinit sq_sysdev_add(struct sys_device *sysdev) + return -ENOMEM; + + kobj = sq_kobject[cpu]; +- error = kobject_init_and_add(kobj, &ktype_percpu_entry, &sysdev->kobj, ++ error = kobject_init_and_add(kobj, &ktype_percpu_entry, &dev->kobj, + "%s", "sq"); + if (!error) + kobject_uevent(kobj, KOBJ_ADD); + return error; + } + +-static int __devexit sq_sysdev_remove(struct sys_device *sysdev) ++static int sq_dev_remove(struct device *dev, struct subsys_interface *sif) + { +- unsigned int cpu = sysdev->id; ++ unsigned int cpu = dev->id; + struct kobject *kobj = sq_kobject[cpu]; + + kobject_put(kobj); + return 0; + } + +-static struct sysdev_driver sq_sysdev_driver = { +- .add = sq_sysdev_add, +- .remove = __devexit_p(sq_sysdev_remove), ++static struct subsys_interface sq_interface = { ++ .name = "sq", ++ .subsys = &cpu_subsys, ++ .add_dev = sq_dev_add, ++ .remove_dev = sq_dev_remove, + }; + + static int __init sq_api_init(void) +@@ -386,7 +388,7 @@ static int __init sq_api_init(void) + if (unlikely(!sq_bitmap)) + goto out; + +- ret = sysdev_driver_register(&cpu_sysdev_class, &sq_sysdev_driver); ++ ret = subsys_interface_register(&sq_interface); + if (unlikely(ret != 0)) + goto out; + +@@ -401,7 +403,7 @@ out: + + static void __exit sq_api_exit(void) + { +- sysdev_driver_unregister(&cpu_sysdev_class, &sq_sysdev_driver); ++ subsys_interface_unregister(&sq_interface); + kfree(sq_bitmap); + kmem_cache_destroy(sq_cache); + } +diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c +index aaf6d59..296a3e8 100644 +--- a/arch/sh/kernel/process_32.c ++++ b/arch/sh/kernel/process_32.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -32,10 +33,11 @@ void show_regs(struct pt_regs * regs) + { + printk("\n"); + printk("Pid : %d, Comm: \t\t%s\n", task_pid_nr(current), current->comm); +- printk("CPU : %d \t\t%s (%s %.*s)\n\n", ++ printk("CPU : %d \t\t%s (%s %.*s%s)\n\n", + smp_processor_id(), print_tainted(), init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), +- init_utsname()->version); ++ init_utsname()->version, ++ LINUX_PACKAGE_ID); + + print_symbol("PC is at %s\n", instruction_pointer(regs)); + print_symbol("PR is at %s\n", regs->pr); +diff --git a/arch/sparc/kernel/sysfs.c b/arch/sparc/kernel/sysfs.c +index 7408201..654e8aa 100644 +--- a/arch/sparc/kernel/sysfs.c ++++ b/arch/sparc/kernel/sysfs.c +@@ -3,7 +3,7 @@ + * Copyright (C) 2007 David S. Miller + */ + #include +-#include ++#include + #include + #include + #include +@@ -16,13 +16,13 @@ + static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64))); + + #define SHOW_MMUSTAT_ULONG(NAME) \ +-static ssize_t show_##NAME(struct sys_device *dev, \ +- struct sysdev_attribute *attr, char *buf) \ ++static ssize_t show_##NAME(struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ + { \ + struct hv_mmu_statistics *p = &per_cpu(mmu_stats, dev->id); \ + return sprintf(buf, "%lu\n", p->NAME); \ + } \ +-static SYSDEV_ATTR(NAME, 0444, show_##NAME, NULL) ++static DEVICE_ATTR(NAME, 0444, show_##NAME, NULL) + + SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_8k_tte); + SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_8k_tte); +@@ -58,38 +58,38 @@ SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_256mb_tte); + SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_256mb_tte); + + static struct attribute *mmu_stat_attrs[] = { +- &attr_immu_tsb_hits_ctx0_8k_tte.attr, +- &attr_immu_tsb_ticks_ctx0_8k_tte.attr, +- &attr_immu_tsb_hits_ctx0_64k_tte.attr, +- &attr_immu_tsb_ticks_ctx0_64k_tte.attr, +- &attr_immu_tsb_hits_ctx0_4mb_tte.attr, +- &attr_immu_tsb_ticks_ctx0_4mb_tte.attr, +- &attr_immu_tsb_hits_ctx0_256mb_tte.attr, +- &attr_immu_tsb_ticks_ctx0_256mb_tte.attr, +- &attr_immu_tsb_hits_ctxnon0_8k_tte.attr, +- &attr_immu_tsb_ticks_ctxnon0_8k_tte.attr, +- &attr_immu_tsb_hits_ctxnon0_64k_tte.attr, +- &attr_immu_tsb_ticks_ctxnon0_64k_tte.attr, +- &attr_immu_tsb_hits_ctxnon0_4mb_tte.attr, +- &attr_immu_tsb_ticks_ctxnon0_4mb_tte.attr, +- &attr_immu_tsb_hits_ctxnon0_256mb_tte.attr, +- &attr_immu_tsb_ticks_ctxnon0_256mb_tte.attr, +- &attr_dmmu_tsb_hits_ctx0_8k_tte.attr, +- &attr_dmmu_tsb_ticks_ctx0_8k_tte.attr, +- &attr_dmmu_tsb_hits_ctx0_64k_tte.attr, +- &attr_dmmu_tsb_ticks_ctx0_64k_tte.attr, +- &attr_dmmu_tsb_hits_ctx0_4mb_tte.attr, +- &attr_dmmu_tsb_ticks_ctx0_4mb_tte.attr, +- &attr_dmmu_tsb_hits_ctx0_256mb_tte.attr, +- &attr_dmmu_tsb_ticks_ctx0_256mb_tte.attr, +- &attr_dmmu_tsb_hits_ctxnon0_8k_tte.attr, +- &attr_dmmu_tsb_ticks_ctxnon0_8k_tte.attr, +- &attr_dmmu_tsb_hits_ctxnon0_64k_tte.attr, +- &attr_dmmu_tsb_ticks_ctxnon0_64k_tte.attr, +- &attr_dmmu_tsb_hits_ctxnon0_4mb_tte.attr, +- &attr_dmmu_tsb_ticks_ctxnon0_4mb_tte.attr, +- &attr_dmmu_tsb_hits_ctxnon0_256mb_tte.attr, +- &attr_dmmu_tsb_ticks_ctxnon0_256mb_tte.attr, ++ &dev_attr_immu_tsb_hits_ctx0_8k_tte.attr, ++ &dev_attr_immu_tsb_ticks_ctx0_8k_tte.attr, ++ &dev_attr_immu_tsb_hits_ctx0_64k_tte.attr, ++ &dev_attr_immu_tsb_ticks_ctx0_64k_tte.attr, ++ &dev_attr_immu_tsb_hits_ctx0_4mb_tte.attr, ++ &dev_attr_immu_tsb_ticks_ctx0_4mb_tte.attr, ++ &dev_attr_immu_tsb_hits_ctx0_256mb_tte.attr, ++ &dev_attr_immu_tsb_ticks_ctx0_256mb_tte.attr, ++ &dev_attr_immu_tsb_hits_ctxnon0_8k_tte.attr, ++ &dev_attr_immu_tsb_ticks_ctxnon0_8k_tte.attr, ++ &dev_attr_immu_tsb_hits_ctxnon0_64k_tte.attr, ++ &dev_attr_immu_tsb_ticks_ctxnon0_64k_tte.attr, ++ &dev_attr_immu_tsb_hits_ctxnon0_4mb_tte.attr, ++ &dev_attr_immu_tsb_ticks_ctxnon0_4mb_tte.attr, ++ &dev_attr_immu_tsb_hits_ctxnon0_256mb_tte.attr, ++ &dev_attr_immu_tsb_ticks_ctxnon0_256mb_tte.attr, ++ &dev_attr_dmmu_tsb_hits_ctx0_8k_tte.attr, ++ &dev_attr_dmmu_tsb_ticks_ctx0_8k_tte.attr, ++ &dev_attr_dmmu_tsb_hits_ctx0_64k_tte.attr, ++ &dev_attr_dmmu_tsb_ticks_ctx0_64k_tte.attr, ++ &dev_attr_dmmu_tsb_hits_ctx0_4mb_tte.attr, ++ &dev_attr_dmmu_tsb_ticks_ctx0_4mb_tte.attr, ++ &dev_attr_dmmu_tsb_hits_ctx0_256mb_tte.attr, ++ &dev_attr_dmmu_tsb_ticks_ctx0_256mb_tte.attr, ++ &dev_attr_dmmu_tsb_hits_ctxnon0_8k_tte.attr, ++ &dev_attr_dmmu_tsb_ticks_ctxnon0_8k_tte.attr, ++ &dev_attr_dmmu_tsb_hits_ctxnon0_64k_tte.attr, ++ &dev_attr_dmmu_tsb_ticks_ctxnon0_64k_tte.attr, ++ &dev_attr_dmmu_tsb_hits_ctxnon0_4mb_tte.attr, ++ &dev_attr_dmmu_tsb_ticks_ctxnon0_4mb_tte.attr, ++ &dev_attr_dmmu_tsb_hits_ctxnon0_256mb_tte.attr, ++ &dev_attr_dmmu_tsb_ticks_ctxnon0_256mb_tte.attr, + NULL, + }; + +@@ -139,15 +139,15 @@ static unsigned long write_mmustat_enable(unsigned long val) + return sun4v_mmustat_conf(ra, &orig_ra); + } + +-static ssize_t show_mmustat_enable(struct sys_device *s, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t show_mmustat_enable(struct device *s, ++ struct device_attribute *attr, char *buf) + { + unsigned long val = run_on_cpu(s->id, read_mmustat_enable, 0); + return sprintf(buf, "%lx\n", val); + } + +-static ssize_t store_mmustat_enable(struct sys_device *s, +- struct sysdev_attribute *attr, const char *buf, ++static ssize_t store_mmustat_enable(struct device *s, ++ struct device_attribute *attr, const char *buf, + size_t count) + { + unsigned long val, err; +@@ -163,39 +163,39 @@ static ssize_t store_mmustat_enable(struct sys_device *s, + return count; + } + +-static SYSDEV_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable); ++static DEVICE_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable); + + static int mmu_stats_supported; + +-static int register_mmu_stats(struct sys_device *s) ++static int register_mmu_stats(struct device *s) + { + if (!mmu_stats_supported) + return 0; +- sysdev_create_file(s, &attr_mmustat_enable); ++ device_create_file(s, &dev_attr_mmustat_enable); + return sysfs_create_group(&s->kobj, &mmu_stat_group); + } + + #ifdef CONFIG_HOTPLUG_CPU +-static void unregister_mmu_stats(struct sys_device *s) ++static void unregister_mmu_stats(struct device *s) + { + if (!mmu_stats_supported) + return; + sysfs_remove_group(&s->kobj, &mmu_stat_group); +- sysdev_remove_file(s, &attr_mmustat_enable); ++ device_remove_file(s, &dev_attr_mmustat_enable); + } + #endif + + #define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \ +-static ssize_t show_##NAME(struct sys_device *dev, \ +- struct sysdev_attribute *attr, char *buf) \ ++static ssize_t show_##NAME(struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ + { \ + cpuinfo_sparc *c = &cpu_data(dev->id); \ + return sprintf(buf, "%lu\n", c->MEMBER); \ + } + + #define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \ +-static ssize_t show_##NAME(struct sys_device *dev, \ +- struct sysdev_attribute *attr, char *buf) \ ++static ssize_t show_##NAME(struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ + { \ + cpuinfo_sparc *c = &cpu_data(dev->id); \ + return sprintf(buf, "%u\n", c->MEMBER); \ +@@ -209,14 +209,14 @@ SHOW_CPUDATA_UINT_NAME(l1_icache_line_size, icache_line_size); + SHOW_CPUDATA_UINT_NAME(l2_cache_size, ecache_size); + SHOW_CPUDATA_UINT_NAME(l2_cache_line_size, ecache_line_size); + +-static struct sysdev_attribute cpu_core_attrs[] = { +- _SYSDEV_ATTR(clock_tick, 0444, show_clock_tick, NULL), +- _SYSDEV_ATTR(l1_dcache_size, 0444, show_l1_dcache_size, NULL), +- _SYSDEV_ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL), +- _SYSDEV_ATTR(l1_icache_size, 0444, show_l1_icache_size, NULL), +- _SYSDEV_ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL), +- _SYSDEV_ATTR(l2_cache_size, 0444, show_l2_cache_size, NULL), +- _SYSDEV_ATTR(l2_cache_line_size, 0444, show_l2_cache_line_size, NULL), ++static struct device_attribute cpu_core_attrs[] = { ++ __ATTR(clock_tick, 0444, show_clock_tick, NULL), ++ __ATTR(l1_dcache_size, 0444, show_l1_dcache_size, NULL), ++ __ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL), ++ __ATTR(l1_icache_size, 0444, show_l1_icache_size, NULL), ++ __ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL), ++ __ATTR(l2_cache_size, 0444, show_l2_cache_size, NULL), ++ __ATTR(l2_cache_line_size, 0444, show_l2_cache_line_size, NULL), + }; + + static DEFINE_PER_CPU(struct cpu, cpu_devices); +@@ -224,11 +224,11 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices); + static void register_cpu_online(unsigned int cpu) + { + struct cpu *c = &per_cpu(cpu_devices, cpu); +- struct sys_device *s = &c->sysdev; ++ struct device *s = &c->dev; + int i; + + for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++) +- sysdev_create_file(s, &cpu_core_attrs[i]); ++ device_create_file(s, &cpu_core_attrs[i]); + + register_mmu_stats(s); + } +@@ -237,12 +237,12 @@ static void register_cpu_online(unsigned int cpu) + static void unregister_cpu_online(unsigned int cpu) + { + struct cpu *c = &per_cpu(cpu_devices, cpu); +- struct sys_device *s = &c->sysdev; ++ struct device *s = &c->dev; + int i; + + unregister_mmu_stats(s); + for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++) +- sysdev_remove_file(s, &cpu_core_attrs[i]); ++ device_remove_file(s, &cpu_core_attrs[i]); + } + #endif + +diff --git a/arch/tile/kernel/sysfs.c b/arch/tile/kernel/sysfs.c +index 6029082..f862b00 100644 +--- a/arch/tile/kernel/sysfs.c ++++ b/arch/tile/kernel/sysfs.c +@@ -14,7 +14,7 @@ + * /sys entry support. + */ + +-#include ++#include + #include + #include + #include +@@ -32,55 +32,55 @@ static ssize_t get_hv_confstr(char *page, int query) + return n; + } + +-static ssize_t chip_width_show(struct sysdev_class *dev, +- struct sysdev_class_attribute *attr, ++static ssize_t chip_width_show(struct device *dev, ++ struct device_attribute *attr, + char *page) + { + return sprintf(page, "%u\n", smp_width); + } +-static SYSDEV_CLASS_ATTR(chip_width, 0444, chip_width_show, NULL); ++static DEVICE_ATTR(chip_width, 0444, chip_width_show, NULL); + +-static ssize_t chip_height_show(struct sysdev_class *dev, +- struct sysdev_class_attribute *attr, ++static ssize_t chip_height_show(struct device *dev, ++ struct device_attribute *attr, + char *page) + { + return sprintf(page, "%u\n", smp_height); + } +-static SYSDEV_CLASS_ATTR(chip_height, 0444, chip_height_show, NULL); ++static DEVICE_ATTR(chip_height, 0444, chip_height_show, NULL); + +-static ssize_t chip_serial_show(struct sysdev_class *dev, +- struct sysdev_class_attribute *attr, ++static ssize_t chip_serial_show(struct device *dev, ++ struct device_attribute *attr, + char *page) + { + return get_hv_confstr(page, HV_CONFSTR_CHIP_SERIAL_NUM); + } +-static SYSDEV_CLASS_ATTR(chip_serial, 0444, chip_serial_show, NULL); ++static DEVICE_ATTR(chip_serial, 0444, chip_serial_show, NULL); + +-static ssize_t chip_revision_show(struct sysdev_class *dev, +- struct sysdev_class_attribute *attr, ++static ssize_t chip_revision_show(struct device *dev, ++ struct device_attribute *attr, + char *page) + { + return get_hv_confstr(page, HV_CONFSTR_CHIP_REV); + } +-static SYSDEV_CLASS_ATTR(chip_revision, 0444, chip_revision_show, NULL); ++static DEVICE_ATTR(chip_revision, 0444, chip_revision_show, NULL); + + +-static ssize_t type_show(struct sysdev_class *dev, +- struct sysdev_class_attribute *attr, ++static ssize_t type_show(struct device *dev, ++ struct device_attribute *attr, + char *page) + { + return sprintf(page, "tilera\n"); + } +-static SYSDEV_CLASS_ATTR(type, 0444, type_show, NULL); ++static DEVICE_ATTR(type, 0444, type_show, NULL); + + #define HV_CONF_ATTR(name, conf) \ +- static ssize_t name ## _show(struct sysdev_class *dev, \ +- struct sysdev_class_attribute *attr, \ ++ static ssize_t name ## _show(struct device *dev, \ ++ struct device_attribute *attr, \ + char *page) \ + { \ + return get_hv_confstr(page, conf); \ + } \ +- static SYSDEV_CLASS_ATTR(name, 0444, name ## _show, NULL); ++ static DEVICE_ATTR(name, 0444, name ## _show, NULL); + + HV_CONF_ATTR(version, HV_CONFSTR_HV_SW_VER) + HV_CONF_ATTR(config_version, HV_CONFSTR_HV_CONFIG_VER) +@@ -96,15 +96,15 @@ HV_CONF_ATTR(mezz_description, HV_CONFSTR_MEZZ_DESC) + HV_CONF_ATTR(switch_control, HV_CONFSTR_SWITCH_CONTROL) + + static struct attribute *board_attrs[] = { +- &attr_board_part.attr, +- &attr_board_serial.attr, +- &attr_board_revision.attr, +- &attr_board_description.attr, +- &attr_mezz_part.attr, +- &attr_mezz_serial.attr, +- &attr_mezz_revision.attr, +- &attr_mezz_description.attr, +- &attr_switch_control.attr, ++ &dev_attr_board_part.attr, ++ &dev_attr_board_serial.attr, ++ &dev_attr_board_revision.attr, ++ &dev_attr_board_description.attr, ++ &dev_attr_mezz_part.attr, ++ &dev_attr_mezz_serial.attr, ++ &dev_attr_mezz_revision.attr, ++ &dev_attr_mezz_description.attr, ++ &dev_attr_switch_control.attr, + NULL + }; + +@@ -151,12 +151,11 @@ hvconfig_bin_read(struct file *filp, struct kobject *kobj, + + static int __init create_sysfs_entries(void) + { +- struct sysdev_class *cls = &cpu_sysdev_class; + int err = 0; + + #define create_cpu_attr(name) \ + if (!err) \ +- err = sysfs_create_file(&cls->kset.kobj, &attr_##name.attr); ++ err = device_create_file(cpu_subsys.dev_root, &dev_attr_##name); + create_cpu_attr(chip_width); + create_cpu_attr(chip_height); + create_cpu_attr(chip_serial); +@@ -164,7 +163,7 @@ static int __init create_sysfs_entries(void) + + #define create_hv_attr(name) \ + if (!err) \ +- err = sysfs_create_file(hypervisor_kobj, &attr_##name.attr); ++ err = sysfs_create_file(hypervisor_kobj, &dev_attr_##name); + create_hv_attr(type); + create_hv_attr(version); + create_hv_attr(config_version); +diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common +index a923483..b37ae70 100644 +--- a/arch/um/Kconfig.common ++++ b/arch/um/Kconfig.common +@@ -8,6 +8,7 @@ config UML + default y + select HAVE_GENERIC_HARDIRQS + select GENERIC_IRQ_SHOW ++ select GENERIC_CPU_DEVICES + + config MMU + bool +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index d720208..cc0ca92 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -72,7 +72,7 @@ config X86 + select GENERIC_CLOCKEVENTS_MIN_ADJUST + select IRQ_FORCED_THREADING + select USE_GENERIC_SMP_HELPERS if SMP +- select HAVE_BPF_JIT if (X86_64 && NET) ++ select HAVE_BPF_JIT if X86_64 + select CLKEVT_I8253 + select ARCH_HAVE_NMI_SAFE_CMPXCHG + select ARCH_SUPPORTS_ATOMIC_RMW +@@ -187,6 +187,9 @@ config ARCH_HAS_DEFAULT_IDLE + config ARCH_HAS_CACHE_LINE_SIZE + def_bool y + ++config ARCH_HAS_CPU_AUTOPROBE ++ def_bool y ++ + config HAVE_SETUP_PER_CPU_AREA + def_bool y + +@@ -1497,6 +1500,13 @@ config EFI + resultant kernel should continue to boot on existing non-EFI + platforms. + ++config EFI_STUB ++ bool "EFI stub support" ++ depends on EFI ++ ---help--- ++ This kernel feature allows a bzImage to be loaded directly ++ by EFI firmware without the use of a bootloader. ++ + config SECCOMP + def_bool y + prompt "Enable seccomp to safely compute untrusted bytecode" +diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile +index e80542b..8dfb1ff 100644 +--- a/arch/x86/boot/Makefile ++++ b/arch/x86/boot/Makefile +@@ -37,7 +37,8 @@ setup-y += video-bios.o + targets += $(setup-y) + hostprogs-y := mkcpustr tools/build + +-HOST_EXTRACFLAGS += $(LINUXINCLUDE) ++HOST_EXTRACFLAGS += -I$(srctree)/tools/include $(LINUXINCLUDE) \ ++ -D__EXPORTED_HEADERS__ + + $(obj)/cpu.o: $(obj)/cpustr.h + +diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile +index cda5cef..82cbf505 100644 +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -23,8 +23,20 @@ LDFLAGS := -m elf_$(UTS_MACHINE) + LDFLAGS_vmlinux := -T + + hostprogs-y := mkpiggy ++HOST_EXTRACFLAGS += -I$(srctree)/tools/include + +-$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o $(obj)/piggy.o FORCE ++VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ ++ $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ ++ $(obj)/piggy.o ++ ++$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone ++$(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone ++ ++ifeq ($(CONFIG_EFI_STUB), y) ++ VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o ++endif ++ ++$(obj)/vmlinux: $(VMLINUX_OBJS) FORCE + $(call if_changed,ld) + @: + +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +new file mode 100644 +index 0000000..8bb9070 +--- /dev/null ++++ b/arch/x86/boot/compressed/eboot.c +@@ -0,0 +1,1024 @@ ++/* ----------------------------------------------------------------------- ++ * ++ * Copyright 2011 Intel Corporation; author Matt Fleming ++ * ++ * This file is part of the Linux kernel, and is made available under ++ * the terms of the GNU General Public License version 2. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++#include ++#include ++#include ++#include ++ ++#undef memcpy /* Use memcpy from misc.c */ ++ ++#include "eboot.h" ++ ++static efi_system_table_t *sys_table; ++ ++static efi_status_t __get_map(efi_memory_desc_t **map, unsigned long *map_size, ++ unsigned long *desc_size) ++{ ++ efi_memory_desc_t *m = NULL; ++ efi_status_t status; ++ unsigned long key; ++ u32 desc_version; ++ ++ *map_size = sizeof(*m) * 32; ++again: ++ /* ++ * Add an additional efi_memory_desc_t because we're doing an ++ * allocation which may be in a new descriptor region. ++ */ ++ *map_size += sizeof(*m); ++ status = efi_call_phys3(sys_table->boottime->allocate_pool, ++ EFI_LOADER_DATA, *map_size, (void **)&m); ++ if (status != EFI_SUCCESS) ++ goto fail; ++ ++ status = efi_call_phys5(sys_table->boottime->get_memory_map, map_size, ++ m, &key, desc_size, &desc_version); ++ if (status == EFI_BUFFER_TOO_SMALL) { ++ efi_call_phys1(sys_table->boottime->free_pool, m); ++ goto again; ++ } ++ ++ if (status != EFI_SUCCESS) ++ efi_call_phys1(sys_table->boottime->free_pool, m); ++ ++fail: ++ *map = m; ++ return status; ++} ++ ++/* ++ * Allocate at the highest possible address that is not above 'max'. ++ */ ++static efi_status_t high_alloc(unsigned long size, unsigned long align, ++ unsigned long *addr, unsigned long max) ++{ ++ unsigned long map_size, desc_size; ++ efi_memory_desc_t *map; ++ efi_status_t status; ++ unsigned long nr_pages; ++ u64 max_addr = 0; ++ int i; ++ ++ status = __get_map(&map, &map_size, &desc_size); ++ if (status != EFI_SUCCESS) ++ goto fail; ++ ++ nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; ++again: ++ for (i = 0; i < map_size / desc_size; i++) { ++ efi_memory_desc_t *desc; ++ unsigned long m = (unsigned long)map; ++ u64 start, end; ++ ++ desc = (efi_memory_desc_t *)(m + (i * desc_size)); ++ if (desc->type != EFI_CONVENTIONAL_MEMORY) ++ continue; ++ ++ if (desc->num_pages < nr_pages) ++ continue; ++ ++ start = desc->phys_addr; ++ end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); ++ ++ if ((start + size) > end || (start + size) > max) ++ continue; ++ ++ if (end - size > max) ++ end = max; ++ ++ if (round_down(end - size, align) < start) ++ continue; ++ ++ start = round_down(end - size, align); ++ ++ /* ++ * Don't allocate at 0x0. It will confuse code that ++ * checks pointers against NULL. ++ */ ++ if (start == 0x0) ++ continue; ++ ++ if (start > max_addr) ++ max_addr = start; ++ } ++ ++ if (!max_addr) ++ status = EFI_NOT_FOUND; ++ else { ++ status = efi_call_phys4(sys_table->boottime->allocate_pages, ++ EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, ++ nr_pages, &max_addr); ++ if (status != EFI_SUCCESS) { ++ max = max_addr; ++ max_addr = 0; ++ goto again; ++ } ++ ++ *addr = max_addr; ++ } ++ ++free_pool: ++ efi_call_phys1(sys_table->boottime->free_pool, map); ++ ++fail: ++ return status; ++} ++ ++/* ++ * Allocate at the lowest possible address. ++ */ ++static efi_status_t low_alloc(unsigned long size, unsigned long align, ++ unsigned long *addr) ++{ ++ unsigned long map_size, desc_size; ++ efi_memory_desc_t *map; ++ efi_status_t status; ++ unsigned long nr_pages; ++ int i; ++ ++ status = __get_map(&map, &map_size, &desc_size); ++ if (status != EFI_SUCCESS) ++ goto fail; ++ ++ nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; ++ for (i = 0; i < map_size / desc_size; i++) { ++ efi_memory_desc_t *desc; ++ unsigned long m = (unsigned long)map; ++ u64 start, end; ++ ++ desc = (efi_memory_desc_t *)(m + (i * desc_size)); ++ ++ if (desc->type != EFI_CONVENTIONAL_MEMORY) ++ continue; ++ ++ if (desc->num_pages < nr_pages) ++ continue; ++ ++ start = desc->phys_addr; ++ end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); ++ ++ /* ++ * Don't allocate at 0x0. It will confuse code that ++ * checks pointers against NULL. Skip the first 8 ++ * bytes so we start at a nice even number. ++ */ ++ if (start == 0x0) ++ start += 8; ++ ++ start = round_up(start, align); ++ if ((start + size) > end) ++ continue; ++ ++ status = efi_call_phys4(sys_table->boottime->allocate_pages, ++ EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, ++ nr_pages, &start); ++ if (status == EFI_SUCCESS) { ++ *addr = start; ++ break; ++ } ++ } ++ ++ if (i == map_size / desc_size) ++ status = EFI_NOT_FOUND; ++ ++free_pool: ++ efi_call_phys1(sys_table->boottime->free_pool, map); ++fail: ++ return status; ++} ++ ++static void low_free(unsigned long size, unsigned long addr) ++{ ++ unsigned long nr_pages; ++ ++ nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; ++ efi_call_phys2(sys_table->boottime->free_pages, addr, size); ++} ++ ++static void find_bits(unsigned long mask, u8 *pos, u8 *size) ++{ ++ u8 first, len; ++ ++ first = 0; ++ len = 0; ++ ++ if (mask) { ++ while (!(mask & 0x1)) { ++ mask = mask >> 1; ++ first++; ++ } ++ ++ while (mask & 0x1) { ++ mask = mask >> 1; ++ len++; ++ } ++ } ++ ++ *pos = first; ++ *size = len; ++} ++ ++/* ++ * See if we have Graphics Output Protocol ++ */ ++static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, ++ unsigned long size) ++{ ++ struct efi_graphics_output_protocol *gop, *first_gop; ++ struct efi_pixel_bitmask pixel_info; ++ unsigned long nr_gops; ++ efi_status_t status; ++ void **gop_handle; ++ u16 width, height; ++ u32 fb_base, fb_size; ++ u32 pixels_per_scan_line; ++ int pixel_format; ++ int i; ++ ++ status = efi_call_phys3(sys_table->boottime->allocate_pool, ++ EFI_LOADER_DATA, size, &gop_handle); ++ if (status != EFI_SUCCESS) ++ return status; ++ ++ status = efi_call_phys5(sys_table->boottime->locate_handle, ++ EFI_LOCATE_BY_PROTOCOL, proto, ++ NULL, &size, gop_handle); ++ if (status != EFI_SUCCESS) ++ goto free_handle; ++ ++ first_gop = NULL; ++ ++ nr_gops = size / sizeof(void *); ++ for (i = 0; i < nr_gops; i++) { ++ struct efi_graphics_output_mode_info *info; ++ efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; ++ void *pciio; ++ void *h = gop_handle[i]; ++ ++ status = efi_call_phys3(sys_table->boottime->handle_protocol, ++ h, proto, &gop); ++ if (status != EFI_SUCCESS) ++ continue; ++ ++ efi_call_phys3(sys_table->boottime->handle_protocol, ++ h, &pciio_proto, &pciio); ++ ++ status = efi_call_phys4(gop->query_mode, gop, ++ gop->mode->mode, &size, &info); ++ if (status == EFI_SUCCESS && (!first_gop || pciio)) { ++ /* ++ * Apple provide GOPs that are not backed by ++ * real hardware (they're used to handle ++ * multiple displays). The workaround is to ++ * search for a GOP implementing the PCIIO ++ * protocol, and if one isn't found, to just ++ * fallback to the first GOP. ++ */ ++ width = info->horizontal_resolution; ++ height = info->vertical_resolution; ++ fb_base = gop->mode->frame_buffer_base; ++ fb_size = gop->mode->frame_buffer_size; ++ pixel_format = info->pixel_format; ++ pixel_info = info->pixel_information; ++ pixels_per_scan_line = info->pixels_per_scan_line; ++ ++ /* ++ * Once we've found a GOP supporting PCIIO, ++ * don't bother looking any further. ++ */ ++ if (pciio) ++ break; ++ ++ first_gop = gop; ++ } ++ } ++ ++ /* Did we find any GOPs? */ ++ if (!first_gop) ++ goto free_handle; ++ ++ /* EFI framebuffer */ ++ si->orig_video_isVGA = VIDEO_TYPE_EFI; ++ ++ si->lfb_width = width; ++ si->lfb_height = height; ++ si->lfb_base = fb_base; ++ si->lfb_size = fb_size; ++ si->pages = 1; ++ ++ if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { ++ si->lfb_depth = 32; ++ si->lfb_linelength = pixels_per_scan_line * 4; ++ si->red_size = 8; ++ si->red_pos = 0; ++ si->green_size = 8; ++ si->green_pos = 8; ++ si->blue_size = 8; ++ si->blue_pos = 16; ++ si->rsvd_size = 8; ++ si->rsvd_pos = 24; ++ } else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) { ++ si->lfb_depth = 32; ++ si->lfb_linelength = pixels_per_scan_line * 4; ++ si->red_size = 8; ++ si->red_pos = 16; ++ si->green_size = 8; ++ si->green_pos = 8; ++ si->blue_size = 8; ++ si->blue_pos = 0; ++ si->rsvd_size = 8; ++ si->rsvd_pos = 24; ++ } else if (pixel_format == PIXEL_BIT_MASK) { ++ find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size); ++ find_bits(pixel_info.green_mask, &si->green_pos, ++ &si->green_size); ++ find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size); ++ find_bits(pixel_info.reserved_mask, &si->rsvd_pos, ++ &si->rsvd_size); ++ si->lfb_depth = si->red_size + si->green_size + ++ si->blue_size + si->rsvd_size; ++ si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8; ++ } else { ++ si->lfb_depth = 4; ++ si->lfb_linelength = si->lfb_width / 2; ++ si->red_size = 0; ++ si->red_pos = 0; ++ si->green_size = 0; ++ si->green_pos = 0; ++ si->blue_size = 0; ++ si->blue_pos = 0; ++ si->rsvd_size = 0; ++ si->rsvd_pos = 0; ++ } ++ ++free_handle: ++ efi_call_phys1(sys_table->boottime->free_pool, gop_handle); ++ return status; ++} ++ ++/* ++ * See if we have Universal Graphics Adapter (UGA) protocol ++ */ ++static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto, ++ unsigned long size) ++{ ++ struct efi_uga_draw_protocol *uga, *first_uga; ++ unsigned long nr_ugas; ++ efi_status_t status; ++ u32 width, height; ++ void **uga_handle = NULL; ++ int i; ++ ++ status = efi_call_phys3(sys_table->boottime->allocate_pool, ++ EFI_LOADER_DATA, size, &uga_handle); ++ if (status != EFI_SUCCESS) ++ return status; ++ ++ status = efi_call_phys5(sys_table->boottime->locate_handle, ++ EFI_LOCATE_BY_PROTOCOL, uga_proto, ++ NULL, &size, uga_handle); ++ if (status != EFI_SUCCESS) ++ goto free_handle; ++ ++ first_uga = NULL; ++ ++ nr_ugas = size / sizeof(void *); ++ for (i = 0; i < nr_ugas; i++) { ++ efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; ++ void *handle = uga_handle[i]; ++ u32 w, h, depth, refresh; ++ void *pciio; ++ ++ status = efi_call_phys3(sys_table->boottime->handle_protocol, ++ handle, uga_proto, &uga); ++ if (status != EFI_SUCCESS) ++ continue; ++ ++ efi_call_phys3(sys_table->boottime->handle_protocol, ++ handle, &pciio_proto, &pciio); ++ ++ status = efi_call_phys5(uga->get_mode, uga, &w, &h, ++ &depth, &refresh); ++ if (status == EFI_SUCCESS && (!first_uga || pciio)) { ++ width = w; ++ height = h; ++ ++ /* ++ * Once we've found a UGA supporting PCIIO, ++ * don't bother looking any further. ++ */ ++ if (pciio) ++ break; ++ ++ first_uga = uga; ++ } ++ } ++ ++ if (!first_uga) ++ goto free_handle; ++ ++ /* EFI framebuffer */ ++ si->orig_video_isVGA = VIDEO_TYPE_EFI; ++ ++ si->lfb_depth = 32; ++ si->lfb_width = width; ++ si->lfb_height = height; ++ ++ si->red_size = 8; ++ si->red_pos = 16; ++ si->green_size = 8; ++ si->green_pos = 8; ++ si->blue_size = 8; ++ si->blue_pos = 0; ++ si->rsvd_size = 8; ++ si->rsvd_pos = 24; ++ ++ ++free_handle: ++ efi_call_phys1(sys_table->boottime->free_pool, uga_handle); ++ return status; ++} ++ ++void setup_graphics(struct boot_params *boot_params) ++{ ++ efi_guid_t graphics_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; ++ struct screen_info *si; ++ efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID; ++ efi_status_t status; ++ unsigned long size; ++ void **gop_handle = NULL; ++ void **uga_handle = NULL; ++ ++ si = &boot_params->screen_info; ++ memset(si, 0, sizeof(*si)); ++ ++ size = 0; ++ status = efi_call_phys5(sys_table->boottime->locate_handle, ++ EFI_LOCATE_BY_PROTOCOL, &graphics_proto, ++ NULL, &size, gop_handle); ++ if (status == EFI_BUFFER_TOO_SMALL) ++ status = setup_gop(si, &graphics_proto, size); ++ ++ if (status != EFI_SUCCESS) { ++ size = 0; ++ status = efi_call_phys5(sys_table->boottime->locate_handle, ++ EFI_LOCATE_BY_PROTOCOL, &uga_proto, ++ NULL, &size, uga_handle); ++ if (status == EFI_BUFFER_TOO_SMALL) ++ setup_uga(si, &uga_proto, size); ++ } ++} ++ ++struct initrd { ++ efi_file_handle_t *handle; ++ u64 size; ++}; ++ ++/* ++ * Check the cmdline for a LILO-style initrd= arguments. ++ * ++ * We only support loading an initrd from the same filesystem as the ++ * kernel image. ++ */ ++static efi_status_t handle_ramdisks(efi_loaded_image_t *image, ++ struct setup_header *hdr) ++{ ++ struct initrd *initrds; ++ unsigned long initrd_addr; ++ efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; ++ u64 initrd_total; ++ efi_file_io_interface_t *io; ++ efi_file_handle_t *fh; ++ efi_status_t status; ++ int nr_initrds; ++ char *str; ++ int i, j, k; ++ ++ initrd_addr = 0; ++ initrd_total = 0; ++ ++ str = (char *)(unsigned long)hdr->cmd_line_ptr; ++ ++ j = 0; /* See close_handles */ ++ ++ if (!str || !*str) ++ return EFI_SUCCESS; ++ ++ for (nr_initrds = 0; *str; nr_initrds++) { ++ str = strstr(str, "initrd="); ++ if (!str) ++ break; ++ ++ str += 7; ++ ++ /* Skip any leading slashes */ ++ while (*str == '/' || *str == '\\') ++ str++; ++ ++ while (*str && *str != ' ' && *str != '\n') ++ str++; ++ } ++ ++ if (!nr_initrds) ++ return EFI_SUCCESS; ++ ++ status = efi_call_phys3(sys_table->boottime->allocate_pool, ++ EFI_LOADER_DATA, ++ nr_initrds * sizeof(*initrds), ++ &initrds); ++ if (status != EFI_SUCCESS) ++ goto fail; ++ ++ str = (char *)(unsigned long)hdr->cmd_line_ptr; ++ for (i = 0; i < nr_initrds; i++) { ++ struct initrd *initrd; ++ efi_file_handle_t *h; ++ efi_file_info_t *info; ++ efi_char16_t filename_16[256]; ++ unsigned long info_sz; ++ efi_guid_t info_guid = EFI_FILE_INFO_ID; ++ efi_char16_t *p; ++ u64 file_sz; ++ ++ str = strstr(str, "initrd="); ++ if (!str) ++ break; ++ ++ str += 7; ++ ++ initrd = &initrds[i]; ++ p = filename_16; ++ ++ /* Skip any leading slashes */ ++ while (*str == '/' || *str == '\\') ++ str++; ++ ++ while (*str && *str != ' ' && *str != '\n') { ++ if ((u8 *)p >= (u8 *)filename_16 + sizeof(filename_16)) ++ break; ++ ++ *p++ = *str++; ++ } ++ ++ *p = '\0'; ++ ++ /* Only open the volume once. */ ++ if (!i) { ++ efi_boot_services_t *boottime; ++ ++ boottime = sys_table->boottime; ++ ++ status = efi_call_phys3(boottime->handle_protocol, ++ image->device_handle, &fs_proto, &io); ++ if (status != EFI_SUCCESS) ++ goto free_initrds; ++ ++ status = efi_call_phys2(io->open_volume, io, &fh); ++ if (status != EFI_SUCCESS) ++ goto free_initrds; ++ } ++ ++ status = efi_call_phys5(fh->open, fh, &h, filename_16, ++ EFI_FILE_MODE_READ, (u64)0); ++ if (status != EFI_SUCCESS) ++ goto close_handles; ++ ++ initrd->handle = h; ++ ++ info_sz = 0; ++ status = efi_call_phys4(h->get_info, h, &info_guid, ++ &info_sz, NULL); ++ if (status != EFI_BUFFER_TOO_SMALL) ++ goto close_handles; ++ ++grow: ++ status = efi_call_phys3(sys_table->boottime->allocate_pool, ++ EFI_LOADER_DATA, info_sz, &info); ++ if (status != EFI_SUCCESS) ++ goto close_handles; ++ ++ status = efi_call_phys4(h->get_info, h, &info_guid, ++ &info_sz, info); ++ if (status == EFI_BUFFER_TOO_SMALL) { ++ efi_call_phys1(sys_table->boottime->free_pool, info); ++ goto grow; ++ } ++ ++ file_sz = info->file_size; ++ efi_call_phys1(sys_table->boottime->free_pool, info); ++ ++ if (status != EFI_SUCCESS) ++ goto close_handles; ++ ++ initrd->size = file_sz; ++ initrd_total += file_sz; ++ } ++ ++ if (initrd_total) { ++ unsigned long addr; ++ ++ /* ++ * Multiple initrd's need to be at consecutive ++ * addresses in memory, so allocate enough memory for ++ * all the initrd's. ++ */ ++ status = high_alloc(initrd_total, 0x1000, ++ &initrd_addr, hdr->initrd_addr_max); ++ if (status != EFI_SUCCESS) ++ goto close_handles; ++ ++ /* We've run out of free low memory. */ ++ if (initrd_addr > hdr->initrd_addr_max) { ++ status = EFI_INVALID_PARAMETER; ++ goto free_initrd_total; ++ } ++ ++ addr = initrd_addr; ++ for (j = 0; j < nr_initrds; j++) { ++ u64 size; ++ ++ size = initrds[j].size; ++ while (size) { ++ u64 chunksize; ++ if (size > EFI_READ_CHUNK_SIZE) ++ chunksize = EFI_READ_CHUNK_SIZE; ++ else ++ chunksize = size; ++ status = efi_call_phys3(fh->read, ++ initrds[j].handle, ++ &chunksize, addr); ++ if (status != EFI_SUCCESS) ++ goto free_initrd_total; ++ addr += chunksize; ++ size -= chunksize; ++ } ++ ++ efi_call_phys1(fh->close, initrds[j].handle); ++ } ++ ++ } ++ ++ efi_call_phys1(sys_table->boottime->free_pool, initrds); ++ ++ hdr->ramdisk_image = initrd_addr; ++ hdr->ramdisk_size = initrd_total; ++ ++ return status; ++ ++free_initrd_total: ++ low_free(initrd_total, initrd_addr); ++ ++close_handles: ++ for (k = j; k < nr_initrds; k++) ++ efi_call_phys1(fh->close, initrds[k].handle); ++free_initrds: ++ efi_call_phys1(sys_table->boottime->free_pool, initrds); ++fail: ++ hdr->ramdisk_image = 0; ++ hdr->ramdisk_size = 0; ++ ++ return status; ++} ++ ++/* ++ * Because the x86 boot code expects to be passed a boot_params we ++ * need to create one ourselves (usually the bootloader would create ++ * one for us). ++ */ ++static efi_status_t make_boot_params(struct boot_params *boot_params, ++ efi_loaded_image_t *image, ++ void *handle) ++{ ++ struct efi_info *efi = &boot_params->efi_info; ++ struct apm_bios_info *bi = &boot_params->apm_bios_info; ++ struct sys_desc_table *sdt = &boot_params->sys_desc_table; ++ struct e820entry *e820_map = &boot_params->e820_map[0]; ++ struct e820entry *prev = NULL; ++ struct setup_header *hdr = &boot_params->hdr; ++ unsigned long size, key, desc_size, _size; ++ efi_memory_desc_t *mem_map; ++ void *options = image->load_options; ++ u32 load_options_size = image->load_options_size / 2; /* ASCII */ ++ int options_size = 0; ++ efi_status_t status; ++ __u32 desc_version; ++ unsigned long cmdline; ++ u8 nr_entries; ++ u16 *s2; ++ u8 *s1; ++ int i; ++ ++ hdr->type_of_loader = 0x21; ++ ++ /* Convert unicode cmdline to ascii */ ++ cmdline = 0; ++ s2 = (u16 *)options; ++ ++ if (s2) { ++ while (*s2 && *s2 != '\n' && options_size < load_options_size) { ++ s2++; ++ options_size++; ++ } ++ ++ if (options_size) { ++ if (options_size > hdr->cmdline_size) ++ options_size = hdr->cmdline_size; ++ ++ options_size++; /* NUL termination */ ++ ++ status = low_alloc(options_size, 1, &cmdline); ++ if (status != EFI_SUCCESS) ++ goto fail; ++ ++ s1 = (u8 *)(unsigned long)cmdline; ++ s2 = (u16 *)options; ++ ++ for (i = 0; i < options_size - 1; i++) ++ *s1++ = *s2++; ++ ++ *s1 = '\0'; ++ } ++ } ++ ++ hdr->cmd_line_ptr = cmdline; ++ ++ hdr->ramdisk_image = 0; ++ hdr->ramdisk_size = 0; ++ ++ status = handle_ramdisks(image, hdr); ++ if (status != EFI_SUCCESS) ++ goto free_cmdline; ++ ++ setup_graphics(boot_params); ++ ++ /* Clear APM BIOS info */ ++ memset(bi, 0, sizeof(*bi)); ++ ++ memset(sdt, 0, sizeof(*sdt)); ++ ++ memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32)); ++ ++ size = sizeof(*mem_map) * 32; ++ ++again: ++ size += sizeof(*mem_map); ++ _size = size; ++ status = low_alloc(size, 1, (unsigned long *)&mem_map); ++ if (status != EFI_SUCCESS) ++ goto free_cmdline; ++ ++ status = efi_call_phys5(sys_table->boottime->get_memory_map, &size, ++ mem_map, &key, &desc_size, &desc_version); ++ if (status == EFI_BUFFER_TOO_SMALL) { ++ low_free(_size, (unsigned long)mem_map); ++ goto again; ++ } ++ ++ if (status != EFI_SUCCESS) ++ goto free_mem_map; ++ ++ efi->efi_systab = (unsigned long)sys_table; ++ efi->efi_memdesc_size = desc_size; ++ efi->efi_memdesc_version = desc_version; ++ efi->efi_memmap = (unsigned long)mem_map; ++ efi->efi_memmap_size = size; ++ ++#ifdef CONFIG_X86_64 ++ efi->efi_systab_hi = (unsigned long)sys_table >> 32; ++ efi->efi_memmap_hi = (unsigned long)mem_map >> 32; ++#endif ++ ++ /* Might as well exit boot services now */ ++ status = efi_call_phys2(sys_table->boottime->exit_boot_services, ++ handle, key); ++ if (status != EFI_SUCCESS) ++ goto free_mem_map; ++ ++ /* Historic? */ ++ boot_params->alt_mem_k = 32 * 1024; ++ ++ /* ++ * Convert the EFI memory map to E820. ++ */ ++ nr_entries = 0; ++ for (i = 0; i < size / desc_size; i++) { ++ efi_memory_desc_t *d; ++ unsigned int e820_type = 0; ++ unsigned long m = (unsigned long)mem_map; ++ ++ d = (efi_memory_desc_t *)(m + (i * desc_size)); ++ switch (d->type) { ++ case EFI_RESERVED_TYPE: ++ case EFI_RUNTIME_SERVICES_CODE: ++ case EFI_RUNTIME_SERVICES_DATA: ++ case EFI_MEMORY_MAPPED_IO: ++ case EFI_MEMORY_MAPPED_IO_PORT_SPACE: ++ case EFI_PAL_CODE: ++ e820_type = E820_RESERVED; ++ break; ++ ++ case EFI_UNUSABLE_MEMORY: ++ e820_type = E820_UNUSABLE; ++ break; ++ ++ case EFI_ACPI_RECLAIM_MEMORY: ++ e820_type = E820_ACPI; ++ break; ++ ++ case EFI_LOADER_CODE: ++ case EFI_LOADER_DATA: ++ case EFI_BOOT_SERVICES_CODE: ++ case EFI_BOOT_SERVICES_DATA: ++ case EFI_CONVENTIONAL_MEMORY: ++ e820_type = E820_RAM; ++ break; ++ ++ case EFI_ACPI_MEMORY_NVS: ++ e820_type = E820_NVS; ++ break; ++ ++ default: ++ continue; ++ } ++ ++ /* Merge adjacent mappings */ ++ if (prev && prev->type == e820_type && ++ (prev->addr + prev->size) == d->phys_addr) ++ prev->size += d->num_pages << 12; ++ else { ++ e820_map->addr = d->phys_addr; ++ e820_map->size = d->num_pages << 12; ++ e820_map->type = e820_type; ++ prev = e820_map++; ++ nr_entries++; ++ } ++ } ++ ++ boot_params->e820_entries = nr_entries; ++ ++ return EFI_SUCCESS; ++ ++free_mem_map: ++ low_free(_size, (unsigned long)mem_map); ++free_cmdline: ++ if (options_size) ++ low_free(options_size, hdr->cmd_line_ptr); ++fail: ++ return status; ++} ++ ++/* ++ * On success we return a pointer to a boot_params structure, and NULL ++ * on failure. ++ */ ++struct boot_params *efi_main(void *handle, efi_system_table_t *_table) ++{ ++ struct boot_params *boot_params; ++ unsigned long start, nr_pages; ++ struct desc_ptr *gdt, *idt; ++ efi_loaded_image_t *image; ++ struct setup_header *hdr; ++ efi_status_t status; ++ efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID; ++ struct desc_struct *desc; ++ ++ sys_table = _table; ++ ++ /* Check if we were booted by the EFI firmware */ ++ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) ++ goto fail; ++ ++ status = efi_call_phys3(sys_table->boottime->handle_protocol, ++ handle, &proto, (void *)&image); ++ if (status != EFI_SUCCESS) ++ goto fail; ++ ++ status = low_alloc(0x4000, 1, (unsigned long *)&boot_params); ++ if (status != EFI_SUCCESS) ++ goto fail; ++ ++ memset(boot_params, 0x0, 0x4000); ++ ++ /* Copy first two sectors to boot_params */ ++ memcpy(boot_params, image->image_base, 1024); ++ ++ hdr = &boot_params->hdr; ++ ++ /* ++ * The EFI firmware loader could have placed the kernel image ++ * anywhere in memory, but the kernel has various restrictions ++ * on the max physical address it can run at. Attempt to move ++ * the kernel to boot_params.pref_address, or as low as ++ * possible. ++ */ ++ start = hdr->pref_address; ++ nr_pages = round_up(hdr->init_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; ++ ++ status = efi_call_phys4(sys_table->boottime->allocate_pages, ++ EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, ++ nr_pages, &start); ++ if (status != EFI_SUCCESS) { ++ status = low_alloc(hdr->init_size, hdr->kernel_alignment, ++ &start); ++ if (status != EFI_SUCCESS) ++ goto fail; ++ } ++ ++ hdr->code32_start = (__u32)start; ++ hdr->pref_address = (__u64)(unsigned long)image->image_base; ++ ++ memcpy((void *)start, image->image_base, image->image_size); ++ ++ status = efi_call_phys3(sys_table->boottime->allocate_pool, ++ EFI_LOADER_DATA, sizeof(*gdt), ++ (void **)&gdt); ++ if (status != EFI_SUCCESS) ++ goto fail; ++ ++ gdt->size = 0x800; ++ status = low_alloc(gdt->size, 8, (unsigned long *)&gdt->address); ++ if (status != EFI_SUCCESS) ++ goto fail; ++ ++ status = efi_call_phys3(sys_table->boottime->allocate_pool, ++ EFI_LOADER_DATA, sizeof(*idt), ++ (void **)&idt); ++ if (status != EFI_SUCCESS) ++ goto fail; ++ ++ idt->size = 0; ++ idt->address = 0; ++ ++ status = make_boot_params(boot_params, image, handle); ++ if (status != EFI_SUCCESS) ++ goto fail; ++ ++ memset((char *)gdt->address, 0x0, gdt->size); ++ desc = (struct desc_struct *)gdt->address; ++ ++ /* The first GDT is a dummy and the second is unused. */ ++ desc += 2; ++ ++ desc->limit0 = 0xffff; ++ desc->base0 = 0x0000; ++ desc->base1 = 0x0000; ++ desc->type = SEG_TYPE_CODE | SEG_TYPE_EXEC_READ; ++ desc->s = DESC_TYPE_CODE_DATA; ++ desc->dpl = 0; ++ desc->p = 1; ++ desc->limit = 0xf; ++ desc->avl = 0; ++ desc->l = 0; ++ desc->d = SEG_OP_SIZE_32BIT; ++ desc->g = SEG_GRANULARITY_4KB; ++ desc->base2 = 0x00; ++ ++ desc++; ++ desc->limit0 = 0xffff; ++ desc->base0 = 0x0000; ++ desc->base1 = 0x0000; ++ desc->type = SEG_TYPE_DATA | SEG_TYPE_READ_WRITE; ++ desc->s = DESC_TYPE_CODE_DATA; ++ desc->dpl = 0; ++ desc->p = 1; ++ desc->limit = 0xf; ++ desc->avl = 0; ++ desc->l = 0; ++ desc->d = SEG_OP_SIZE_32BIT; ++ desc->g = SEG_GRANULARITY_4KB; ++ desc->base2 = 0x00; ++ ++#ifdef CONFIG_X86_64 ++ /* Task segment value */ ++ desc++; ++ desc->limit0 = 0x0000; ++ desc->base0 = 0x0000; ++ desc->base1 = 0x0000; ++ desc->type = SEG_TYPE_TSS; ++ desc->s = 0; ++ desc->dpl = 0; ++ desc->p = 1; ++ desc->limit = 0x0; ++ desc->avl = 0; ++ desc->l = 0; ++ desc->d = 0; ++ desc->g = SEG_GRANULARITY_4KB; ++ desc->base2 = 0x00; ++#endif /* CONFIG_X86_64 */ ++ ++ asm volatile ("lidt %0" : : "m" (*idt)); ++ asm volatile ("lgdt %0" : : "m" (*gdt)); ++ ++ asm volatile("cli"); ++ ++ return boot_params; ++fail: ++ return NULL; ++} +diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h +new file mode 100644 +index 0000000..3925166 +--- /dev/null ++++ b/arch/x86/boot/compressed/eboot.h +@@ -0,0 +1,61 @@ ++#ifndef BOOT_COMPRESSED_EBOOT_H ++#define BOOT_COMPRESSED_EBOOT_H ++ ++#define SEG_TYPE_DATA (0 << 3) ++#define SEG_TYPE_READ_WRITE (1 << 1) ++#define SEG_TYPE_CODE (1 << 3) ++#define SEG_TYPE_EXEC_READ (1 << 1) ++#define SEG_TYPE_TSS ((1 << 3) | (1 << 0)) ++#define SEG_OP_SIZE_32BIT (1 << 0) ++#define SEG_GRANULARITY_4KB (1 << 0) ++ ++#define DESC_TYPE_CODE_DATA (1 << 0) ++ ++#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) ++#define EFI_READ_CHUNK_SIZE (1024 * 1024) ++ ++#define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 ++#define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 ++#define PIXEL_BIT_MASK 2 ++#define PIXEL_BLT_ONLY 3 ++#define PIXEL_FORMAT_MAX 4 ++ ++struct efi_pixel_bitmask { ++ u32 red_mask; ++ u32 green_mask; ++ u32 blue_mask; ++ u32 reserved_mask; ++}; ++ ++struct efi_graphics_output_mode_info { ++ u32 version; ++ u32 horizontal_resolution; ++ u32 vertical_resolution; ++ int pixel_format; ++ struct efi_pixel_bitmask pixel_information; ++ u32 pixels_per_scan_line; ++} __packed; ++ ++struct efi_graphics_output_protocol_mode { ++ u32 max_mode; ++ u32 mode; ++ unsigned long info; ++ unsigned long size_of_info; ++ u64 frame_buffer_base; ++ unsigned long frame_buffer_size; ++} __packed; ++ ++struct efi_graphics_output_protocol { ++ void *query_mode; ++ unsigned long set_mode; ++ unsigned long blt; ++ struct efi_graphics_output_protocol_mode *mode; ++}; ++ ++struct efi_uga_draw_protocol { ++ void *get_mode; ++ void *set_mode; ++ void *blt; ++}; ++ ++#endif /* BOOT_COMPRESSED_EBOOT_H */ +diff --git a/arch/x86/boot/compressed/efi_stub_32.S b/arch/x86/boot/compressed/efi_stub_32.S +new file mode 100644 +index 0000000..a53440e +--- /dev/null ++++ b/arch/x86/boot/compressed/efi_stub_32.S +@@ -0,0 +1,86 @@ ++/* ++ * EFI call stub for IA32. ++ * ++ * This stub allows us to make EFI calls in physical mode with interrupts ++ * turned off. Note that this implementation is different from the one in ++ * arch/x86/platform/efi/efi_stub_32.S because we're _already_ in physical ++ * mode at this point. ++ */ ++ ++#include ++#include ++ ++/* ++ * efi_call_phys(void *, ...) is a function with variable parameters. ++ * All the callers of this function assure that all the parameters are 4-bytes. ++ */ ++ ++/* ++ * In gcc calling convention, EBX, ESP, EBP, ESI and EDI are all callee save. ++ * So we'd better save all of them at the beginning of this function and restore ++ * at the end no matter how many we use, because we can not assure EFI runtime ++ * service functions will comply with gcc calling convention, too. ++ */ ++ ++.text ++ENTRY(efi_call_phys) ++ /* ++ * 0. The function can only be called in Linux kernel. So CS has been ++ * set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found ++ * the values of these registers are the same. And, the corresponding ++ * GDT entries are identical. So I will do nothing about segment reg ++ * and GDT, but change GDT base register in prelog and epilog. ++ */ ++ ++ /* ++ * 1. Because we haven't been relocated by this point we need to ++ * use relative addressing. ++ */ ++ call 1f ++1: popl %edx ++ subl $1b, %edx ++ ++ /* ++ * 2. Now on the top of stack is the return ++ * address in the caller of efi_call_phys(), then parameter 1, ++ * parameter 2, ..., param n. To make things easy, we save the return ++ * address of efi_call_phys in a global variable. ++ */ ++ popl %ecx ++ movl %ecx, saved_return_addr(%edx) ++ /* get the function pointer into ECX*/ ++ popl %ecx ++ movl %ecx, efi_rt_function_ptr(%edx) ++ ++ /* ++ * 3. Call the physical function. ++ */ ++ call *%ecx ++ ++ /* ++ * 4. Balance the stack. And because EAX contain the return value, ++ * we'd better not clobber it. We need to calculate our address ++ * again because %ecx and %edx are not preserved across EFI function ++ * calls. ++ */ ++ call 1f ++1: popl %edx ++ subl $1b, %edx ++ ++ movl efi_rt_function_ptr(%edx), %ecx ++ pushl %ecx ++ ++ /* ++ * 10. Push the saved return address onto the stack and return. ++ */ ++ movl saved_return_addr(%edx), %ecx ++ pushl %ecx ++ ret ++ENDPROC(efi_call_phys) ++.previous ++ ++.data ++saved_return_addr: ++ .long 0 ++efi_rt_function_ptr: ++ .long 0 +diff --git a/arch/x86/boot/compressed/efi_stub_64.S b/arch/x86/boot/compressed/efi_stub_64.S +new file mode 100644 +index 0000000..cedc60d +--- /dev/null ++++ b/arch/x86/boot/compressed/efi_stub_64.S +@@ -0,0 +1 @@ ++#include "../../platform/efi/efi_stub_64.S" +diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S +index 67a655a..c85e3ac 100644 +--- a/arch/x86/boot/compressed/head_32.S ++++ b/arch/x86/boot/compressed/head_32.S +@@ -32,6 +32,36 @@ + + __HEAD + ENTRY(startup_32) ++#ifdef CONFIG_EFI_STUB ++ jmp preferred_addr ++ ++ .balign 0x10 ++ /* ++ * We don't need the return address, so set up the stack so ++ * efi_main() can find its arugments. ++ */ ++ add $0x4, %esp ++ ++ call efi_main ++ cmpl $0, %eax ++ movl %eax, %esi ++ jne 2f ++1: ++ /* EFI init failed, so hang. */ ++ hlt ++ jmp 1b ++2: ++ call 3f ++3: ++ popl %eax ++ subl $3b, %eax ++ subl BP_pref_address(%esi), %eax ++ add BP_code32_start(%esi), %eax ++ leal preferred_addr(%eax), %eax ++ jmp *%eax ++ ++preferred_addr: ++#endif + cld + /* + * Test KEEP_SEGMENTS flag to see if the bootloader is asking +diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S +index 35af09d..87e03a1 100644 +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -199,6 +199,36 @@ ENTRY(startup_64) + * an identity mapped page table being provied that maps our + * entire text+data+bss and hopefully all of memory. + */ ++#ifdef CONFIG_EFI_STUB ++ /* ++ * The entry point for the PE/COFF executable is 0x210, so only ++ * legacy boot loaders will execute this jmp. ++ */ ++ jmp preferred_addr ++ ++ .org 0x210 ++ mov %rcx, %rdi ++ mov %rdx, %rsi ++ call efi_main ++ movq %rax,%rsi ++ cmpq $0,%rax ++ jne 2f ++1: ++ /* EFI init failed, so hang. */ ++ hlt ++ jmp 1b ++2: ++ call 3f ++3: ++ popq %rax ++ subq $3b, %rax ++ subq BP_pref_address(%rsi), %rax ++ add BP_code32_start(%esi), %eax ++ leaq preferred_addr(%rax), %rax ++ jmp *%rax ++ ++preferred_addr: ++#endif + + /* Setup data segments. */ + xorl %eax, %eax +diff --git a/arch/x86/boot/compressed/mkpiggy.c b/arch/x86/boot/compressed/mkpiggy.c +index 46a8238..958a641 100644 +--- a/arch/x86/boot/compressed/mkpiggy.c ++++ b/arch/x86/boot/compressed/mkpiggy.c +@@ -29,14 +29,7 @@ + #include + #include + #include +- +-static uint32_t getle32(const void *p) +-{ +- const uint8_t *cp = p; +- +- return (uint32_t)cp[0] + ((uint32_t)cp[1] << 8) + +- ((uint32_t)cp[2] << 16) + ((uint32_t)cp[3] << 24); +-} ++#include + + int main(int argc, char *argv[]) + { +@@ -69,7 +62,7 @@ int main(int argc, char *argv[]) + } + + ilen = ftell(f); +- olen = getle32(&olen); ++ olen = get_unaligned_le32(&olen); + fclose(f); + + /* +diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c +index 19b3e69..ffb9c5c 100644 +--- a/arch/x86/boot/compressed/string.c ++++ b/arch/x86/boot/compressed/string.c +@@ -1,2 +1,11 @@ + #include "misc.h" ++ ++int memcmp(const void *s1, const void *s2, size_t len) ++{ ++ u8 diff; ++ asm("repe; cmpsb; setnz %0" ++ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); ++ return diff; ++} ++ + #include "../string.c" +diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S +index bdb4d45..f1bbeeb 100644 +--- a/arch/x86/boot/header.S ++++ b/arch/x86/boot/header.S +@@ -45,6 +45,11 @@ SYSSEG = 0x1000 /* historical load address >> 4 */ + + .global bootsect_start + bootsect_start: ++#ifdef CONFIG_EFI_STUB ++ # "MZ", MS-DOS header ++ .byte 0x4d ++ .byte 0x5a ++#endif + + # Normalize the start address + ljmp $BOOTSEG, $start2 +@@ -79,6 +84,14 @@ bs_die: + # invoke the BIOS reset code... + ljmp $0xf000,$0xfff0 + ++#ifdef CONFIG_EFI_STUB ++ .org 0x3c ++ # ++ # Offset to the PE header. ++ # ++ .long pe_header ++#endif /* CONFIG_EFI_STUB */ ++ + .section ".bsdata", "a" + bugger_off_msg: + .ascii "Direct booting from floppy is no longer supported.\r\n" +@@ -87,6 +100,141 @@ bugger_off_msg: + .ascii "Remove disk and press any key to reboot . . .\r\n" + .byte 0 + ++#ifdef CONFIG_EFI_STUB ++pe_header: ++ .ascii "PE" ++ .word 0 ++ ++coff_header: ++#ifdef CONFIG_X86_32 ++ .word 0x14c # i386 ++#else ++ .word 0x8664 # x86-64 ++#endif ++ .word 2 # nr_sections ++ .long 0 # TimeDateStamp ++ .long 0 # PointerToSymbolTable ++ .long 1 # NumberOfSymbols ++ .word section_table - optional_header # SizeOfOptionalHeader ++#ifdef CONFIG_X86_32 ++ .word 0x306 # Characteristics. ++ # IMAGE_FILE_32BIT_MACHINE | ++ # IMAGE_FILE_DEBUG_STRIPPED | ++ # IMAGE_FILE_EXECUTABLE_IMAGE | ++ # IMAGE_FILE_LINE_NUMS_STRIPPED ++#else ++ .word 0x206 # Characteristics ++ # IMAGE_FILE_DEBUG_STRIPPED | ++ # IMAGE_FILE_EXECUTABLE_IMAGE | ++ # IMAGE_FILE_LINE_NUMS_STRIPPED ++#endif ++ ++optional_header: ++#ifdef CONFIG_X86_32 ++ .word 0x10b # PE32 format ++#else ++ .word 0x20b # PE32+ format ++#endif ++ .byte 0x02 # MajorLinkerVersion ++ .byte 0x14 # MinorLinkerVersion ++ ++ # Filled in by build.c ++ .long 0 # SizeOfCode ++ ++ .long 0 # SizeOfInitializedData ++ .long 0 # SizeOfUninitializedData ++ ++ # Filled in by build.c ++ .long 0x0000 # AddressOfEntryPoint ++ ++ .long 0x0000 # BaseOfCode ++#ifdef CONFIG_X86_32 ++ .long 0 # data ++#endif ++ ++extra_header_fields: ++#ifdef CONFIG_X86_32 ++ .long 0 # ImageBase ++#else ++ .quad 0 # ImageBase ++#endif ++ .long 0x1000 # SectionAlignment ++ .long 0x200 # FileAlignment ++ .word 0 # MajorOperatingSystemVersion ++ .word 0 # MinorOperatingSystemVersion ++ .word 0 # MajorImageVersion ++ .word 0 # MinorImageVersion ++ .word 0 # MajorSubsystemVersion ++ .word 0 # MinorSubsystemVersion ++ .long 0 # Win32VersionValue ++ ++ # ++ # The size of the bzImage is written in tools/build.c ++ # ++ .long 0 # SizeOfImage ++ ++ .long 0x200 # SizeOfHeaders ++ .long 0 # CheckSum ++ .word 0xa # Subsystem (EFI application) ++ .word 0 # DllCharacteristics ++#ifdef CONFIG_X86_32 ++ .long 0 # SizeOfStackReserve ++ .long 0 # SizeOfStackCommit ++ .long 0 # SizeOfHeapReserve ++ .long 0 # SizeOfHeapCommit ++#else ++ .quad 0 # SizeOfStackReserve ++ .quad 0 # SizeOfStackCommit ++ .quad 0 # SizeOfHeapReserve ++ .quad 0 # SizeOfHeapCommit ++#endif ++ .long 0 # LoaderFlags ++ .long 0x1 # NumberOfRvaAndSizes ++ ++ .quad 0 # ExportTable ++ .quad 0 # ImportTable ++ .quad 0 # ResourceTable ++ .quad 0 # ExceptionTable ++ .quad 0 # CertificationTable ++ .quad 0 # BaseRelocationTable ++ ++ # Section table ++section_table: ++ .ascii ".text" ++ .byte 0 ++ .byte 0 ++ .byte 0 ++ .long 0 ++ .long 0x0 # startup_{32,64} ++ .long 0 # Size of initialized data ++ # on disk ++ .long 0x0 # startup_{32,64} ++ .long 0 # PointerToRelocations ++ .long 0 # PointerToLineNumbers ++ .word 0 # NumberOfRelocations ++ .word 0 # NumberOfLineNumbers ++ .long 0x60500020 # Characteristics (section flags) ++ ++ # ++ # The EFI application loader requires a relocation section ++ # because EFI applications are relocatable and not having ++ # this section seems to confuse it. But since we don't need ++ # the loader to fixup any relocs for us just fill it with a ++ # single dummy reloc. ++ # ++ .ascii ".reloc" ++ .byte 0 ++ .byte 0 ++ .long reloc_end - reloc_start ++ .long reloc_start ++ .long reloc_end - reloc_start # SizeOfRawData ++ .long reloc_start # PointerToRawData ++ .long 0 # PointerToRelocations ++ .long 0 # PointerToLineNumbers ++ .word 0 # NumberOfRelocations ++ .word 0 # NumberOfLineNumbers ++ .long 0x42100040 # Characteristics (section flags) ++#endif /* CONFIG_EFI_STUB */ + + # Kernel attributes; used by setup. This is part 1 of the + # header, from the old boot sector. +@@ -318,3 +466,13 @@ die: + setup_corrupt: + .byte 7 + .string "No setup signature found...\n" ++ ++ .data ++dummy: .long 0 ++ ++ .section .reloc ++reloc_start: ++ .long dummy - reloc_start ++ .long 10 ++ .word 0 ++reloc_end: +diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c +index 3cbc405..574dedf 100644 +--- a/arch/x86/boot/string.c ++++ b/arch/x86/boot/string.c +@@ -111,3 +111,38 @@ unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int bas + + return result; + } ++ ++/** ++ * strlen - Find the length of a string ++ * @s: The string to be sized ++ */ ++size_t strlen(const char *s) ++{ ++ const char *sc; ++ ++ for (sc = s; *sc != '\0'; ++sc) ++ /* nothing */; ++ return sc - s; ++} ++ ++/** ++ * strstr - Find the first substring in a %NUL terminated string ++ * @s1: The string to be searched ++ * @s2: The string to search for ++ */ ++char *strstr(const char *s1, const char *s2) ++{ ++ size_t l1, l2; ++ ++ l2 = strlen(s2); ++ if (!l2) ++ return (char *)s1; ++ l1 = strlen(s1); ++ while (l1 >= l2) { ++ l1--; ++ if (!memcmp(s1, s2, l2)) ++ return (char *)s1; ++ s1++; ++ } ++ return NULL; ++} +diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c +index fdc60a0..09ce870 100644 +--- a/arch/x86/boot/tools/build.c ++++ b/arch/x86/boot/tools/build.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + typedef unsigned char u8; + typedef unsigned short u16; +@@ -41,6 +42,7 @@ typedef unsigned long u32; + + #define DEFAULT_MAJOR_ROOT 0 + #define DEFAULT_MINOR_ROOT 0 ++#define DEFAULT_ROOT_DEV (DEFAULT_MAJOR_ROOT << 8 | DEFAULT_MINOR_ROOT) + + /* Minimal number of setup sectors */ + #define SETUP_SECT_MIN 5 +@@ -135,6 +137,9 @@ static void usage(void) + + int main(int argc, char ** argv) + { ++#ifdef CONFIG_EFI_STUB ++ unsigned int file_sz, pe_header; ++#endif + unsigned int i, sz, setup_sectors; + int c; + u32 sys_size; +@@ -156,7 +161,7 @@ int main(int argc, char ** argv) + die("read-error on `setup'"); + if (c < 1024) + die("The setup must be at least 1024 bytes"); +- if (buf[510] != 0x55 || buf[511] != 0xaa) ++ if (get_unaligned_le16(&buf[510]) != 0xAA55) + die("Boot block hasn't got boot flag (0xAA55)"); + fclose(file); + +@@ -168,8 +173,7 @@ int main(int argc, char ** argv) + memset(buf+c, 0, i-c); + + /* Set the default root device */ +- buf[508] = DEFAULT_MINOR_ROOT; +- buf[509] = DEFAULT_MAJOR_ROOT; ++ put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]); + + fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i); + +@@ -189,10 +193,51 @@ int main(int argc, char ** argv) + + /* Patch the setup code with the appropriate size parameters */ + buf[0x1f1] = setup_sectors-1; +- buf[0x1f4] = sys_size; +- buf[0x1f5] = sys_size >> 8; +- buf[0x1f6] = sys_size >> 16; +- buf[0x1f7] = sys_size >> 24; ++ put_unaligned_le32(sys_size, &buf[0x1f4]); ++ ++#ifdef CONFIG_EFI_STUB ++ file_sz = sz + i + ((sys_size * 16) - sz); ++ ++ pe_header = get_unaligned_le32(&buf[0x3c]); ++ ++ /* Size of code */ ++ put_unaligned_le32(file_sz, &buf[pe_header + 0x1c]); ++ ++ /* Size of image */ ++ put_unaligned_le32(file_sz, &buf[pe_header + 0x50]); ++ ++#ifdef CONFIG_X86_32 ++ /* ++ * Address of entry point. ++ * ++ * The EFI stub entry point is +16 bytes from the start of ++ * the .text section. ++ */ ++ put_unaligned_le32(i + 16, &buf[pe_header + 0x28]); ++ ++ /* .text size */ ++ put_unaligned_le32(file_sz, &buf[pe_header + 0xb0]); ++ ++ /* .text size of initialised data */ ++ put_unaligned_le32(file_sz, &buf[pe_header + 0xb8]); ++#else ++ /* ++ * Address of entry point. startup_32 is at the beginning and ++ * the 64-bit entry point (startup_64) is always 512 bytes ++ * after. The EFI stub entry point is 16 bytes after that, as ++ * the first instruction allows legacy loaders to jump over ++ * the EFI stub initialisation ++ */ ++ put_unaligned_le32(i + 528, &buf[pe_header + 0x28]); ++ ++ /* .text size */ ++ put_unaligned_le32(file_sz, &buf[pe_header + 0xc0]); ++ ++ /* .text size of initialised data */ ++ put_unaligned_le32(file_sz, &buf[pe_header + 0xc8]); ++ ++#endif /* CONFIG_X86_32 */ ++#endif /* CONFIG_EFI_STUB */ + + crc = partial_crc32(buf, i, crc); + if (fwrite(buf, 1, i, stdout) != i) +diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c +index 3b3a62f..8ccef50 100644 +--- a/arch/x86/crypto/aesni-intel_glue.c ++++ b/arch/x86/crypto/aesni-intel_glue.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1253,14 +1254,19 @@ static struct crypto_alg __rfc4106_alg = { + }; + #endif + ++ ++static const struct x86_cpu_id aesni_cpu_id[] = { ++ X86_FEATURE_MATCH(X86_FEATURE_AES), ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, aesni_cpu_id); ++ + static int __init aesni_init(void) + { + int err; + +- if (!cpu_has_aes) { +- printk(KERN_INFO "Intel AES-NI instructions are not detected.\n"); ++ if (!x86_match_cpu(aesni_cpu_id)) + return -ENODEV; +- } + + if ((err = crypto_fpu_init())) + goto fpu_err; +diff --git a/arch/x86/crypto/crc32c-intel.c b/arch/x86/crypto/crc32c-intel.c +index 7dad700..8272ef4 100644 +--- a/arch/x86/crypto/crc32c-intel.c ++++ b/arch/x86/crypto/crc32c-intel.c +@@ -31,6 +31,7 @@ + #include + + #include ++#include + + #define CHKSUM_BLOCK_SIZE 1 + #define CHKSUM_DIGEST_SIZE 4 +@@ -173,13 +174,17 @@ static struct shash_alg alg = { + } + }; + ++static const struct x86_cpu_id crc32c_cpu_id[] = { ++ X86_FEATURE_MATCH(X86_FEATURE_XMM4_2), ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, crc32c_cpu_id); + + static int __init crc32c_intel_mod_init(void) + { +- if (cpu_has_xmm4_2) +- return crypto_register_shash(&alg); +- else ++ if (!x86_match_cpu(crc32c_cpu_id)) + return -ENODEV; ++ return crypto_register_shash(&alg); + } + + static void __exit crc32c_intel_mod_fini(void) +diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c +index f781251..d41e650 100644 +--- a/arch/x86/crypto/ghash-clmulni-intel_glue.c ++++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + #define GHASH_BLOCK_SIZE 16 + #define GHASH_DIGEST_SIZE 16 +@@ -302,15 +303,18 @@ static struct ahash_alg ghash_async_alg = { + }, + }; + ++static const struct x86_cpu_id pcmul_cpu_id[] = { ++ X86_FEATURE_MATCH(X86_FEATURE_PCLMULQDQ), /* Pickle-Mickle-Duck */ ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, pcmul_cpu_id); ++ + static int __init ghash_pclmulqdqni_mod_init(void) + { + int err; + +- if (!cpu_has_pclmulqdq) { +- printk(KERN_INFO "Intel PCLMULQDQ-NI instructions are not" +- " detected.\n"); ++ if (!x86_match_cpu(pcmul_cpu_id)) + return -ENODEV; +- } + + err = crypto_register_shash(&ghash_alg); + if (err) +diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h +index e020d88..2f90c51 100644 +--- a/arch/x86/include/asm/bootparam.h ++++ b/arch/x86/include/asm/bootparam.h +@@ -64,6 +64,8 @@ struct setup_header { + __u32 payload_offset; + __u32 payload_length; + __u64 setup_data; ++ __u64 pref_address; ++ __u32 init_size; + } __attribute__((packed)); + + struct sys_desc_table { +diff --git a/arch/x86/include/asm/cpu_device_id.h b/arch/x86/include/asm/cpu_device_id.h +new file mode 100644 +index 0000000..ff501e5 +--- /dev/null ++++ b/arch/x86/include/asm/cpu_device_id.h +@@ -0,0 +1,13 @@ ++#ifndef _CPU_DEVICE_ID ++#define _CPU_DEVICE_ID 1 ++ ++/* ++ * Declare drivers belonging to specific x86 CPUs ++ * Similar in spirit to pci_device_id and related PCI functions ++ */ ++ ++#include ++ ++extern const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match); ++ ++#endif +diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h +index b8a5fe5..6ee98a7 100644 +--- a/arch/x86/include/asm/cpufeature.h ++++ b/arch/x86/include/asm/cpufeature.h +@@ -176,6 +176,7 @@ + #define X86_FEATURE_PLN (7*32+ 5) /* Intel Power Limit Notification */ + #define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */ + #define X86_FEATURE_DTHERM (7*32+ 7) /* Digital Thermal Sensor */ ++#define X86_FEATURE_HW_PSTATE (7*32+ 8) /* AMD HW-PState */ + + /* Virtualization flags: Linux defined, word 8 */ + #define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ +diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h +index 035cd81..ba7daea 100644 +--- a/arch/x86/include/asm/efi.h ++++ b/arch/x86/include/asm/efi.h +@@ -3,6 +3,8 @@ + + #ifdef CONFIG_X86_32 + ++#define EFI_LOADER_SIGNATURE "EL32" ++ + extern unsigned long asmlinkage efi_call_phys(void *, ...); + + #define efi_call_phys0(f) efi_call_phys(f) +@@ -37,6 +39,8 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); + + #else /* !CONFIG_X86_32 */ + ++#define EFI_LOADER_SIGNATURE "EL64" ++ + extern u64 efi_call0(void *fp); + extern u64 efi_call1(void *fp, u64 arg1); + extern u64 efi_call2(void *fp, u64 arg1, u64 arg2); +diff --git a/arch/x86/include/asm/emergency-restart.h b/arch/x86/include/asm/emergency-restart.h +index cc70c1c..c99cfee 100644 +--- a/arch/x86/include/asm/emergency-restart.h ++++ b/arch/x86/include/asm/emergency-restart.h +@@ -11,6 +11,9 @@ enum reboot_type { + BOOT_EFI = 'e', + BOOT_CF9 = 'p', + BOOT_CF9_COND = 'q', ++ BOOT_CF9_COLD = 'd', ++ BOOT_CF9_FULL = 'g', ++ BOOT_S3000_PSU = 'y', + }; + + extern enum reboot_type reboot_type; +diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h +index 91d915a..31ce3f7 100644 +--- a/arch/x86/include/asm/gpio.h ++++ b/arch/x86/include/asm/gpio.h +@@ -16,6 +16,8 @@ + #ifndef _ASM_X86_GPIO_H + #define _ASM_X86_GPIO_H + ++#define ARCH_NR_GPIOS 512 ++ + #include + + #ifdef CONFIG_GPIOLIB +diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h +index 0e8ae57..97385cf 100644 +--- a/arch/x86/include/asm/mce.h ++++ b/arch/x86/include/asm/mce.h +@@ -149,7 +149,7 @@ static inline void enable_p5_mce(void) {} + + void mce_setup(struct mce *m); + void mce_log(struct mce *m); +-DECLARE_PER_CPU(struct sys_device, mce_sysdev); ++DECLARE_PER_CPU(struct device *, mce_device); + + /* + * Maximum banks number. +diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h +index 2421507..22677d6 100644 +--- a/arch/x86/include/asm/microcode.h ++++ b/arch/x86/include/asm/microcode.h +@@ -61,4 +61,13 @@ static inline struct microcode_ops * __init init_amd_microcode(void) + } + #endif + ++#ifdef CONFIG_MICROCODE_XEN ++extern struct microcode_ops * __init init_xen_microcode(void); ++#else ++static inline struct microcode_ops * __init init_xen_microcode(void) ++{ ++ return NULL; ++} ++#endif ++ + #endif /* _ASM_X86_MICROCODE_H */ +diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h +index 91e758b..4601084 100644 +--- a/arch/x86/include/asm/paravirt.h ++++ b/arch/x86/include/asm/paravirt.h +@@ -742,7 +742,7 @@ static inline void arch_leave_lazy_mmu_mode(void) + + static inline void arch_flush_lazy_mmu_mode(void) + { +- PVOP_VCALL0(pv_mmu_ops.lazy_mode.flush); ++ PVOP_VCALL0(pv_mmu_lazy_mode_flush); + } + + static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx, +diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h +index faf2c04..39ee6b4 100644 +--- a/arch/x86/include/asm/paravirt_types.h ++++ b/arch/x86/include/asm/paravirt_types.h +@@ -91,7 +91,6 @@ struct pv_lazy_ops { + /* Set deferred update mode, used for batching operations. */ + void (*enter)(void); + void (*leave)(void); +- void (*flush)(void); + }; + + struct pv_time_ops { +@@ -348,6 +347,9 @@ struct paravirt_patch_template { + struct pv_apic_ops pv_apic_ops; + struct pv_mmu_ops pv_mmu_ops; + struct pv_lock_ops pv_lock_ops; ++#ifndef __GENKSYMS__ ++ void (*pv_mmu_lazy_mode_flush)(void); ++#endif + }; + + extern struct pv_info pv_info; +@@ -358,6 +360,7 @@ extern struct pv_irq_ops pv_irq_ops; + extern struct pv_apic_ops pv_apic_ops; + extern struct pv_mmu_ops pv_mmu_ops; + extern struct pv_lock_ops pv_lock_ops; ++extern void (*pv_mmu_lazy_mode_flush)(void); + + #define PARAVIRT_PATCH(x) \ + (offsetof(struct paravirt_patch_template, x) / sizeof(void *)) +diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile +index 96efa3e..9ac56d1 100644 +--- a/arch/x86/kernel/Makefile ++++ b/arch/x86/kernel/Makefile +@@ -93,6 +93,7 @@ obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o + microcode-y := microcode_core.o + microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o + microcode-$(CONFIG_MICROCODE_AMD) += microcode_amd.o ++microcode-$(CONFIG_MICROCODE_XEN) += microcode_xen.o + obj-$(CONFIG_MICROCODE) += microcode.o + + obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o +diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c +index 4f13faf..68de2dc 100644 +--- a/arch/x86/kernel/asm-offsets.c ++++ b/arch/x86/kernel/asm-offsets.c +@@ -67,4 +67,6 @@ void common(void) { + OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch); + OFFSET(BP_version, boot_params, hdr.version); + OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment); ++ OFFSET(BP_pref_address, boot_params, hdr.pref_address); ++ OFFSET(BP_code32_start, boot_params, hdr.code32_start); + } +diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile +index 25f24dc..6ab6aa2 100644 +--- a/arch/x86/kernel/cpu/Makefile ++++ b/arch/x86/kernel/cpu/Makefile +@@ -16,6 +16,7 @@ obj-y := intel_cacheinfo.o scattered.o topology.o + obj-y += proc.o capflags.o powerflags.o common.o + obj-y += vmware.o hypervisor.o sched.o mshyperv.o + obj-y += rdrand.o ++obj-y += match.o + + obj-$(CONFIG_X86_32) += bugs.o + obj-$(CONFIG_X86_64) += bugs_64.o +diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c +index 0e89635..73d08ed 100644 +--- a/arch/x86/kernel/cpu/intel_cacheinfo.c ++++ b/arch/x86/kernel/cpu/intel_cacheinfo.c +@@ -872,8 +872,7 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu) + + #include + #include +- +-extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */ ++#include + + /* pointer to kobject for cpuX/cache */ + static DEFINE_PER_CPU(struct kobject *, ici_cache_kobject); +@@ -1101,9 +1100,9 @@ err_out: + static DECLARE_BITMAP(cache_dev_map, NR_CPUS); + + /* Add/Remove cache interface for CPU device */ +-static int __cpuinit cache_add_dev(struct sys_device * sys_dev) ++static int __cpuinit cache_add_dev(struct device *dev) + { +- unsigned int cpu = sys_dev->id; ++ unsigned int cpu = dev->id; + unsigned long i, j; + struct _index_kobject *this_object; + struct _cpuid4_info *this_leaf; +@@ -1115,7 +1114,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) + + retval = kobject_init_and_add(per_cpu(ici_cache_kobject, cpu), + &ktype_percpu_entry, +- &sys_dev->kobj, "%s", "cache"); ++ &dev->kobj, "%s", "cache"); + if (retval < 0) { + cpuid4_cache_sysfs_exit(cpu); + return retval; +@@ -1152,9 +1151,9 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) + return 0; + } + +-static void __cpuinit cache_remove_dev(struct sys_device * sys_dev) ++static void __cpuinit cache_remove_dev(struct device *dev) + { +- unsigned int cpu = sys_dev->id; ++ unsigned int cpu = dev->id; + unsigned long i; + + if (per_cpu(ici_cpuid4_info, cpu) == NULL) +@@ -1173,17 +1172,17 @@ static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) + { + unsigned int cpu = (unsigned long)hcpu; +- struct sys_device *sys_dev; ++ struct device *dev; + +- sys_dev = get_cpu_sysdev(cpu); ++ dev = get_cpu_device(cpu); + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: +- cache_add_dev(sys_dev); ++ cache_add_dev(dev); + break; + case CPU_DEAD: + case CPU_DEAD_FROZEN: +- cache_remove_dev(sys_dev); ++ cache_remove_dev(dev); + break; + } + return NOTIFY_OK; +@@ -1202,9 +1201,9 @@ static int __cpuinit cache_sysfs_init(void) + + for_each_online_cpu(i) { + int err; +- struct sys_device *sys_dev = get_cpu_sysdev(i); ++ struct device *dev = get_cpu_device(i); + +- err = cache_add_dev(sys_dev); ++ err = cache_add_dev(dev); + if (err) + return err; + } +diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c +new file mode 100644 +index 0000000..5502b28 +--- /dev/null ++++ b/arch/x86/kernel/cpu/match.c +@@ -0,0 +1,91 @@ ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ * x86_match_cpu - match current CPU again an array of x86_cpu_ids ++ * @match: Pointer to array of x86_cpu_ids. Last entry terminated with ++ * {}. ++ * ++ * Return the entry if the current CPU matches the entries in the ++ * passed x86_cpu_id match table. Otherwise NULL. The match table ++ * contains vendor (X86_VENDOR_*), family, model and feature bits or ++ * respective wildcard entries. ++ * ++ * A typical table entry would be to match a specific CPU ++ * { X86_VENDOR_INTEL, 6, 0x12 } ++ * or to match a specific CPU feature ++ * { X86_FEATURE_MATCH(X86_FEATURE_FOOBAR) } ++ * ++ * Fields can be wildcarded with %X86_VENDOR_ANY, %X86_FAMILY_ANY, ++ * %X86_MODEL_ANY, %X86_FEATURE_ANY or 0 (except for vendor) ++ * ++ * Arrays used to match for this should also be declared using ++ * MODULE_DEVICE_TABLE(x86_cpu, ...) ++ * ++ * This always matches against the boot cpu, assuming models and features are ++ * consistent over all CPUs. ++ */ ++const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match) ++{ ++ const struct x86_cpu_id *m; ++ struct cpuinfo_x86 *c = &boot_cpu_data; ++ ++ for (m = match; m->vendor | m->family | m->model | m->feature; m++) { ++ if (m->vendor != X86_VENDOR_ANY && c->x86_vendor != m->vendor) ++ continue; ++ if (m->family != X86_FAMILY_ANY && c->x86 != m->family) ++ continue; ++ if (m->model != X86_MODEL_ANY && c->x86_model != m->model) ++ continue; ++ if (m->feature != X86_FEATURE_ANY && !cpu_has(c, m->feature)) ++ continue; ++ return m; ++ } ++ return NULL; ++} ++EXPORT_SYMBOL(x86_match_cpu); ++ ++ssize_t arch_print_cpu_modalias(struct device *dev, ++ struct device_attribute *attr, ++ char *bufptr) ++{ ++ int size = PAGE_SIZE; ++ int i, n; ++ char *buf = bufptr; ++ ++ n = snprintf(buf, size, "x86cpu:vendor:%04X:family:%04X:" ++ "model:%04X:feature:", ++ boot_cpu_data.x86_vendor, ++ boot_cpu_data.x86, ++ boot_cpu_data.x86_model); ++ size -= n; ++ buf += n; ++ size -= 1; ++ for (i = 0; i < NCAPINTS*32; i++) { ++ if (boot_cpu_has(i)) { ++ n = snprintf(buf, size, ",%04X", i); ++ if (n >= size) { ++ WARN(1, "x86 features overflow page\n"); ++ break; ++ } ++ size -= n; ++ buf += n; ++ } ++ } ++ *buf++ = '\n'; ++ return buf - bufptr; ++} ++ ++int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env) ++{ ++ char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL); ++ if (buf) { ++ arch_print_cpu_modalias(NULL, NULL, buf); ++ add_uevent_var(env, "MODALIAS=%s", buf); ++ kfree(buf); ++ } ++ return 0; ++} +diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h +index fefcc69..ed44c8a 100644 +--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h ++++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h +@@ -1,4 +1,4 @@ +-#include ++#include + #include + + enum severity_level { +@@ -17,7 +17,7 @@ enum severity_level { + struct mce_bank { + u64 ctl; /* subevents to enable */ + unsigned char init; /* initialise bank? */ +- struct sysdev_attribute attr; /* sysdev attribute */ ++ struct device_attribute attr; /* device attribute */ + char attrname[ATTR_LEN]; /* attribute name */ + }; + +diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c +index 3b67877..48c3bee 100644 +--- a/arch/x86/kernel/cpu/mcheck/mce.c ++++ b/arch/x86/kernel/cpu/mcheck/mce.c +@@ -19,7 +19,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -1776,7 +1776,7 @@ static struct syscore_ops mce_syscore_ops = { + }; + + /* +- * mce_sysdev: Sysfs support ++ * mce_device: Sysfs support + */ + + static void mce_cpu_restart(void *data) +@@ -1812,27 +1812,28 @@ static void mce_enable_ce(void *all) + __mcheck_cpu_init_timer(); + } + +-static struct sysdev_class mce_sysdev_class = { ++static struct bus_type mce_subsys = { + .name = "machinecheck", ++ .dev_name = "machinecheck", + }; + +-DEFINE_PER_CPU(struct sys_device, mce_sysdev); ++DEFINE_PER_CPU(struct device *, mce_device); + + __cpuinitdata + void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu); + +-static inline struct mce_bank *attr_to_bank(struct sysdev_attribute *attr) ++static inline struct mce_bank *attr_to_bank(struct device_attribute *attr) + { + return container_of(attr, struct mce_bank, attr); + } + +-static ssize_t show_bank(struct sys_device *s, struct sysdev_attribute *attr, ++static ssize_t show_bank(struct device *s, struct device_attribute *attr, + char *buf) + { + return sprintf(buf, "%llx\n", attr_to_bank(attr)->ctl); + } + +-static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr, ++static ssize_t set_bank(struct device *s, struct device_attribute *attr, + const char *buf, size_t size) + { + u64 new; +@@ -1847,14 +1848,14 @@ static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr, + } + + static ssize_t +-show_trigger(struct sys_device *s, struct sysdev_attribute *attr, char *buf) ++show_trigger(struct device *s, struct device_attribute *attr, char *buf) + { + strcpy(buf, mce_helper); + strcat(buf, "\n"); + return strlen(mce_helper) + 1; + } + +-static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr, ++static ssize_t set_trigger(struct device *s, struct device_attribute *attr, + const char *buf, size_t siz) + { + char *p; +@@ -1869,8 +1870,8 @@ static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr, + return strlen(mce_helper) + !!p; + } + +-static ssize_t set_ignore_ce(struct sys_device *s, +- struct sysdev_attribute *attr, ++static ssize_t set_ignore_ce(struct device *s, ++ struct device_attribute *attr, + const char *buf, size_t size) + { + u64 new; +@@ -1893,8 +1894,8 @@ static ssize_t set_ignore_ce(struct sys_device *s, + return size; + } + +-static ssize_t set_cmci_disabled(struct sys_device *s, +- struct sysdev_attribute *attr, ++static ssize_t set_cmci_disabled(struct device *s, ++ struct device_attribute *attr, + const char *buf, size_t size) + { + u64 new; +@@ -1916,108 +1917,117 @@ static ssize_t set_cmci_disabled(struct sys_device *s, + return size; + } + +-static ssize_t store_int_with_restart(struct sys_device *s, +- struct sysdev_attribute *attr, ++static ssize_t store_int_with_restart(struct device *s, ++ struct device_attribute *attr, + const char *buf, size_t size) + { +- ssize_t ret = sysdev_store_int(s, attr, buf, size); ++ ssize_t ret = device_store_int(s, attr, buf, size); + mce_restart(); + return ret; + } + +-static SYSDEV_ATTR(trigger, 0644, show_trigger, set_trigger); +-static SYSDEV_INT_ATTR(tolerant, 0644, tolerant); +-static SYSDEV_INT_ATTR(monarch_timeout, 0644, monarch_timeout); +-static SYSDEV_INT_ATTR(dont_log_ce, 0644, mce_dont_log_ce); ++static DEVICE_ATTR(trigger, 0644, show_trigger, set_trigger); ++static DEVICE_INT_ATTR(tolerant, 0644, tolerant); ++static DEVICE_INT_ATTR(monarch_timeout, 0644, monarch_timeout); ++static DEVICE_INT_ATTR(dont_log_ce, 0644, mce_dont_log_ce); + +-static struct sysdev_ext_attribute attr_check_interval = { +- _SYSDEV_ATTR(check_interval, 0644, sysdev_show_int, +- store_int_with_restart), ++static struct dev_ext_attribute dev_attr_check_interval = { ++ __ATTR(check_interval, 0644, device_show_int, store_int_with_restart), + &check_interval + }; + +-static struct sysdev_ext_attribute attr_ignore_ce = { +- _SYSDEV_ATTR(ignore_ce, 0644, sysdev_show_int, set_ignore_ce), ++static struct dev_ext_attribute dev_attr_ignore_ce = { ++ __ATTR(ignore_ce, 0644, device_show_int, set_ignore_ce), + &mce_ignore_ce + }; + +-static struct sysdev_ext_attribute attr_cmci_disabled = { +- _SYSDEV_ATTR(cmci_disabled, 0644, sysdev_show_int, set_cmci_disabled), ++static struct dev_ext_attribute dev_attr_cmci_disabled = { ++ __ATTR(cmci_disabled, 0644, device_show_int, set_cmci_disabled), + &mce_cmci_disabled + }; + +-static struct sysdev_attribute *mce_sysdev_attrs[] = { +- &attr_tolerant.attr, +- &attr_check_interval.attr, +- &attr_trigger, +- &attr_monarch_timeout.attr, +- &attr_dont_log_ce.attr, +- &attr_ignore_ce.attr, +- &attr_cmci_disabled.attr, ++static struct device_attribute *mce_device_attrs[] = { ++ &dev_attr_tolerant.attr, ++ &dev_attr_check_interval.attr, ++ &dev_attr_trigger, ++ &dev_attr_monarch_timeout.attr, ++ &dev_attr_dont_log_ce.attr, ++ &dev_attr_ignore_ce.attr, ++ &dev_attr_cmci_disabled.attr, + NULL + }; + +-static cpumask_var_t mce_sysdev_initialized; ++static cpumask_var_t mce_device_initialized; + +-/* Per cpu sysdev init. All of the cpus still share the same ctrl bank: */ +-static __cpuinit int mce_sysdev_create(unsigned int cpu) ++static void mce_device_release(struct device *dev) + { +- struct sys_device *sysdev = &per_cpu(mce_sysdev, cpu); ++ kfree(dev); ++} ++ ++/* Per cpu device init. All of the cpus still share the same ctrl bank: */ ++static __cpuinit int mce_device_create(unsigned int cpu) ++{ ++ struct device *dev; + int err; + int i, j; + + if (!mce_available(&boot_cpu_data)) + return -EIO; + +- memset(&sysdev->kobj, 0, sizeof(struct kobject)); +- sysdev->id = cpu; +- sysdev->cls = &mce_sysdev_class; ++ dev = kzalloc(sizeof *dev, GFP_KERNEL); ++ if (!dev) ++ return -ENOMEM; ++ dev->id = cpu; ++ dev->bus = &mce_subsys; ++ dev->release = &mce_device_release; + +- err = sysdev_register(sysdev); ++ err = device_register(dev); + if (err) + return err; + +- for (i = 0; mce_sysdev_attrs[i]; i++) { +- err = sysdev_create_file(sysdev, mce_sysdev_attrs[i]); ++ for (i = 0; mce_device_attrs[i]; i++) { ++ err = device_create_file(dev, mce_device_attrs[i]); + if (err) + goto error; + } + for (j = 0; j < banks; j++) { +- err = sysdev_create_file(sysdev, &mce_banks[j].attr); ++ err = device_create_file(dev, &mce_banks[j].attr); + if (err) + goto error2; + } +- cpumask_set_cpu(cpu, mce_sysdev_initialized); ++ cpumask_set_cpu(cpu, mce_device_initialized); ++ per_cpu(mce_device, cpu) = dev; + + return 0; + error2: + while (--j >= 0) +- sysdev_remove_file(sysdev, &mce_banks[j].attr); ++ device_remove_file(dev, &mce_banks[j].attr); + error: + while (--i >= 0) +- sysdev_remove_file(sysdev, mce_sysdev_attrs[i]); ++ device_remove_file(dev, mce_device_attrs[i]); + +- sysdev_unregister(sysdev); ++ device_unregister(dev); + + return err; + } + +-static __cpuinit void mce_sysdev_remove(unsigned int cpu) ++static __cpuinit void mce_device_remove(unsigned int cpu) + { +- struct sys_device *sysdev = &per_cpu(mce_sysdev, cpu); ++ struct device *dev = per_cpu(mce_device, cpu); + int i; + +- if (!cpumask_test_cpu(cpu, mce_sysdev_initialized)) ++ if (!cpumask_test_cpu(cpu, mce_device_initialized)) + return; + +- for (i = 0; mce_sysdev_attrs[i]; i++) +- sysdev_remove_file(sysdev, mce_sysdev_attrs[i]); ++ for (i = 0; mce_device_attrs[i]; i++) ++ device_remove_file(dev, mce_device_attrs[i]); + + for (i = 0; i < banks; i++) +- sysdev_remove_file(sysdev, &mce_banks[i].attr); ++ device_remove_file(dev, &mce_banks[i].attr); + +- sysdev_unregister(sysdev); +- cpumask_clear_cpu(cpu, mce_sysdev_initialized); ++ device_unregister(dev); ++ cpumask_clear_cpu(cpu, mce_device_initialized); ++ per_cpu(mce_device, cpu) = NULL; + } + + /* Make sure there are no machine checks on offlined CPUs. */ +@@ -2067,7 +2077,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: +- mce_sysdev_create(cpu); ++ mce_device_create(cpu); + if (threshold_cpu_callback) + threshold_cpu_callback(action, cpu); + break; +@@ -2075,7 +2085,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) + case CPU_DEAD_FROZEN: + if (threshold_cpu_callback) + threshold_cpu_callback(action, cpu); +- mce_sysdev_remove(cpu); ++ mce_device_remove(cpu); + break; + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: +@@ -2109,7 +2119,7 @@ static __init void mce_init_banks(void) + + for (i = 0; i < banks; i++) { + struct mce_bank *b = &mce_banks[i]; +- struct sysdev_attribute *a = &b->attr; ++ struct device_attribute *a = &b->attr; + + sysfs_attr_init(&a->attr); + a->attr.name = b->attrname; +@@ -2129,16 +2139,16 @@ static __init int mcheck_init_device(void) + if (!mce_available(&boot_cpu_data)) + return -EIO; + +- zalloc_cpumask_var(&mce_sysdev_initialized, GFP_KERNEL); ++ zalloc_cpumask_var(&mce_device_initialized, GFP_KERNEL); + + mce_init_banks(); + +- err = sysdev_class_register(&mce_sysdev_class); ++ err = subsys_system_register(&mce_subsys, NULL); + if (err) + return err; + + for_each_online_cpu(i) { +- err = mce_sysdev_create(i); ++ err = mce_device_create(i); + if (err) + return err; + } +diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c +index d4444be..bd075d1 100644 +--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c ++++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c +@@ -17,7 +17,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -557,6 +556,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) + { + int i, err = 0; + struct threshold_bank *b = NULL; ++ struct device *dev = per_cpu(mce_device, cpu); + char name[32]; + + sprintf(name, "threshold_bank%i", bank); +@@ -578,8 +578,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) + if (!b) + goto out; + +- err = sysfs_create_link(&per_cpu(mce_sysdev, cpu).kobj, +- b->kobj, name); ++ err = sysfs_create_link(&dev->kobj, b->kobj, name); + if (err) + goto out; + +@@ -601,7 +600,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) + goto out; + } + +- b->kobj = kobject_create_and_add(name, &per_cpu(mce_sysdev, cpu).kobj); ++ b->kobj = kobject_create_and_add(name, &dev->kobj); + if (!b->kobj) + goto out_free; + +@@ -621,8 +620,9 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) + if (i == cpu) + continue; + +- err = sysfs_create_link(&per_cpu(mce_sysdev, i).kobj, +- b->kobj, name); ++ dev = per_cpu(mce_device, i); ++ if (dev) ++ err = sysfs_create_link(&dev->kobj,b->kobj, name); + if (err) + goto out; + +@@ -685,6 +685,7 @@ static void deallocate_threshold_block(unsigned int cpu, + static void threshold_remove_bank(unsigned int cpu, int bank) + { + struct threshold_bank *b; ++ struct device *dev; + char name[32]; + int i = 0; + +@@ -699,7 +700,8 @@ static void threshold_remove_bank(unsigned int cpu, int bank) + #ifdef CONFIG_SMP + /* sibling symlink */ + if (shared_bank[bank] && b->blocks->cpu != cpu) { +- sysfs_remove_link(&per_cpu(mce_sysdev, cpu).kobj, name); ++ dev = per_cpu(mce_device, cpu); ++ sysfs_remove_link(&dev->kobj, name); + per_cpu(threshold_banks, cpu)[bank] = NULL; + + return; +@@ -711,7 +713,9 @@ static void threshold_remove_bank(unsigned int cpu, int bank) + if (i == cpu) + continue; + +- sysfs_remove_link(&per_cpu(mce_sysdev, i).kobj, name); ++ dev = per_cpu(mce_device, i); ++ if (dev) ++ sysfs_remove_link(&dev->kobj, name); + per_cpu(threshold_banks, i)[bank] = NULL; + } + +diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c +index ce04b58..9f66e3f 100644 +--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c ++++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -69,16 +68,16 @@ static atomic_t therm_throt_en = ATOMIC_INIT(0); + static u32 lvtthmr_init __read_mostly; + + #ifdef CONFIG_SYSFS +-#define define_therm_throt_sysdev_one_ro(_name) \ +- static SYSDEV_ATTR(_name, 0444, \ +- therm_throt_sysdev_show_##_name, \ ++#define define_therm_throt_device_one_ro(_name) \ ++ static DEVICE_ATTR(_name, 0444, \ ++ therm_throt_device_show_##_name, \ + NULL) \ + +-#define define_therm_throt_sysdev_show_func(event, name) \ ++#define define_therm_throt_device_show_func(event, name) \ + \ +-static ssize_t therm_throt_sysdev_show_##event##_##name( \ +- struct sys_device *dev, \ +- struct sysdev_attribute *attr, \ ++static ssize_t therm_throt_device_show_##event##_##name( \ ++ struct device *dev, \ ++ struct device_attribute *attr, \ + char *buf) \ + { \ + unsigned int cpu = dev->id; \ +@@ -95,20 +94,20 @@ static ssize_t therm_throt_sysdev_show_##event##_##name( \ + return ret; \ + } + +-define_therm_throt_sysdev_show_func(core_throttle, count); +-define_therm_throt_sysdev_one_ro(core_throttle_count); ++define_therm_throt_device_show_func(core_throttle, count); ++define_therm_throt_device_one_ro(core_throttle_count); + +-define_therm_throt_sysdev_show_func(core_power_limit, count); +-define_therm_throt_sysdev_one_ro(core_power_limit_count); ++define_therm_throt_device_show_func(core_power_limit, count); ++define_therm_throt_device_one_ro(core_power_limit_count); + +-define_therm_throt_sysdev_show_func(package_throttle, count); +-define_therm_throt_sysdev_one_ro(package_throttle_count); ++define_therm_throt_device_show_func(package_throttle, count); ++define_therm_throt_device_one_ro(package_throttle_count); + +-define_therm_throt_sysdev_show_func(package_power_limit, count); +-define_therm_throt_sysdev_one_ro(package_power_limit_count); ++define_therm_throt_device_show_func(package_power_limit, count); ++define_therm_throt_device_one_ro(package_power_limit_count); + + static struct attribute *thermal_throttle_attrs[] = { +- &attr_core_throttle_count.attr, ++ &dev_attr_core_throttle_count.attr, + NULL + }; + +@@ -223,36 +222,36 @@ static int thresh_event_valid(int event) + + #ifdef CONFIG_SYSFS + /* Add/Remove thermal_throttle interface for CPU device: */ +-static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev, ++static __cpuinit int thermal_throttle_add_dev(struct device *dev, + unsigned int cpu) + { + int err; + struct cpuinfo_x86 *c = &cpu_data(cpu); + +- err = sysfs_create_group(&sys_dev->kobj, &thermal_attr_group); ++ err = sysfs_create_group(&dev->kobj, &thermal_attr_group); + if (err) + return err; + + if (cpu_has(c, X86_FEATURE_PLN)) +- err = sysfs_add_file_to_group(&sys_dev->kobj, +- &attr_core_power_limit_count.attr, ++ err = sysfs_add_file_to_group(&dev->kobj, ++ &dev_attr_core_power_limit_count.attr, + thermal_attr_group.name); + if (cpu_has(c, X86_FEATURE_PTS)) { +- err = sysfs_add_file_to_group(&sys_dev->kobj, +- &attr_package_throttle_count.attr, ++ err = sysfs_add_file_to_group(&dev->kobj, ++ &dev_attr_package_throttle_count.attr, + thermal_attr_group.name); + if (cpu_has(c, X86_FEATURE_PLN)) +- err = sysfs_add_file_to_group(&sys_dev->kobj, +- &attr_package_power_limit_count.attr, ++ err = sysfs_add_file_to_group(&dev->kobj, ++ &dev_attr_package_power_limit_count.attr, + thermal_attr_group.name); + } + + return err; + } + +-static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev) ++static __cpuinit void thermal_throttle_remove_dev(struct device *dev) + { +- sysfs_remove_group(&sys_dev->kobj, &thermal_attr_group); ++ sysfs_remove_group(&dev->kobj, &thermal_attr_group); + } + + /* Mutex protecting device creation against CPU hotplug: */ +@@ -265,16 +264,16 @@ thermal_throttle_cpu_callback(struct notifier_block *nfb, + void *hcpu) + { + unsigned int cpu = (unsigned long)hcpu; +- struct sys_device *sys_dev; ++ struct device *dev; + int err = 0; + +- sys_dev = get_cpu_sysdev(cpu); ++ dev = get_cpu_device(cpu); + + switch (action) { + case CPU_UP_PREPARE: + case CPU_UP_PREPARE_FROZEN: + mutex_lock(&therm_cpu_lock); +- err = thermal_throttle_add_dev(sys_dev, cpu); ++ err = thermal_throttle_add_dev(dev, cpu); + mutex_unlock(&therm_cpu_lock); + WARN_ON(err); + break; +@@ -283,7 +282,7 @@ thermal_throttle_cpu_callback(struct notifier_block *nfb, + case CPU_DEAD: + case CPU_DEAD_FROZEN: + mutex_lock(&therm_cpu_lock); +- thermal_throttle_remove_dev(sys_dev); ++ thermal_throttle_remove_dev(dev); + mutex_unlock(&therm_cpu_lock); + break; + } +@@ -310,7 +309,7 @@ static __init int thermal_throttle_init_device(void) + #endif + /* connect live CPUs to sysfs */ + for_each_online_cpu(cpu) { +- err = thermal_throttle_add_dev(get_cpu_sysdev(cpu), cpu); ++ err = thermal_throttle_add_dev(get_cpu_device(cpu), cpu); + WARN_ON(err); + } + #ifdef CONFIG_HOTPLUG_CPU +diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c +index ea34253..3b8a2d3 100644 +--- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c ++++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c +@@ -9,7 +9,6 @@ + #include + #include + #include +-#include + + #include + +@@ -210,18 +209,6 @@ out: + return ret; + } + +-static void ibs_eilvt_setup(void) +-{ +- /* +- * Force LVT offset assignment for family 10h: The offsets are +- * not assigned by the BIOS for this family, so the OS is +- * responsible for doing it. If the OS assignment fails, fall +- * back to BIOS settings and try to setup this. +- */ +- if (boot_cpu_data.x86 == 0x10) +- force_ibs_eilvt_setup(); +-} +- + static inline int get_ibs_lvt_offset(void) + { + u64 val; +@@ -257,36 +244,6 @@ static void clear_APIC_ibs(void *dummy) + setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1); + } + +-#ifdef CONFIG_PM +- +-static int perf_ibs_suspend(void) +-{ +- clear_APIC_ibs(NULL); +- return 0; +-} +- +-static void perf_ibs_resume(void) +-{ +- ibs_eilvt_setup(); +- setup_APIC_ibs(NULL); +-} +- +-static struct syscore_ops perf_ibs_syscore_ops = { +- .resume = perf_ibs_resume, +- .suspend = perf_ibs_suspend, +-}; +- +-static void perf_ibs_pm_init(void) +-{ +- register_syscore_ops(&perf_ibs_syscore_ops); +-} +- +-#else +- +-static inline void perf_ibs_pm_init(void) { } +- +-#endif +- + static int __cpuinit + perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) + { +@@ -313,12 +270,18 @@ static __init int amd_ibs_init(void) + if (!caps) + return -ENODEV; /* ibs not supported by the cpu */ + +- ibs_eilvt_setup(); ++ /* ++ * Force LVT offset assignment for family 10h: The offsets are ++ * not assigned by the BIOS for this family, so the OS is ++ * responsible for doing it. If the OS assignment fails, fall ++ * back to BIOS settings and try to setup this. ++ */ ++ if (boot_cpu_data.x86 == 0x10) ++ force_ibs_eilvt_setup(); + + if (!ibs_eilvt_valid()) + goto out; + +- perf_ibs_pm_init(); + get_online_cpus(); + ibs_caps = caps; + /* make ibs_caps visible to other cpus: */ +diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c +index ea6106c..ee8e9ab 100644 +--- a/arch/x86/kernel/cpu/scattered.c ++++ b/arch/x86/kernel/cpu/scattered.c +@@ -40,6 +40,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) + { X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 }, + { X86_FEATURE_XSAVEOPT, CR_EAX, 0, 0x0000000d, 1 }, + { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007, 0 }, ++ { X86_FEATURE_HW_PSTATE, CR_EDX, 7, 0x80000007, 0 }, + { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a, 0 }, + { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a, 0 }, + { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a, 0 }, +diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c +index 1aae78f..3bf8917 100644 +--- a/arch/x86/kernel/dumpstack.c ++++ b/arch/x86/kernel/dumpstack.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include + +@@ -185,11 +186,12 @@ void dump_stack(void) + unsigned long stack; + + bp = stack_frame(current, NULL); +- printk("Pid: %d, comm: %.20s %s %s %.*s\n", ++ printk("Pid: %d, comm: %.20s %s %s %.*s%s\n", + current->pid, current->comm, print_tainted(), + init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), +- init_utsname()->version); ++ init_utsname()->version, ++ LINUX_PACKAGE_ID); + show_trace(NULL, NULL, &stack, bp); + } + EXPORT_SYMBOL(dump_stack); +diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c +index f9b9eaa..e8e01e0 100644 +--- a/arch/x86/kernel/microcode_amd.c ++++ b/arch/x86/kernel/microcode_amd.c +@@ -330,10 +330,8 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device) + if (c->x86 >= 0x15) + snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); + +- if (request_firmware(&fw, (const char *)fw_name, device)) { +- pr_debug("failed to load file %s\n", fw_name); ++ if (request_firmware(&fw, (const char *)fw_name, device)) + goto out; +- } + + ret = UCODE_ERROR; + if (*(u32 *)fw->data != UCODE_MAGIC) { +diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c +index 29c95d7..d04b130 100644 +--- a/arch/x86/kernel/microcode_core.c ++++ b/arch/x86/kernel/microcode_core.c +@@ -84,6 +84,7 @@ + #include + #include + ++#include + #include + #include + +@@ -292,8 +293,8 @@ static int reload_for_cpu(int cpu) + return err; + } + +-static ssize_t reload_store(struct sys_device *dev, +- struct sysdev_attribute *attr, ++static ssize_t reload_store(struct device *dev, ++ struct device_attribute *attr, + const char *buf, size_t size) + { + unsigned long val; +@@ -329,30 +330,30 @@ static ssize_t reload_store(struct sys_device *dev, + return ret; + } + +-static ssize_t version_show(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t version_show(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + + return sprintf(buf, "0x%x\n", uci->cpu_sig.rev); + } + +-static ssize_t pf_show(struct sys_device *dev, +- struct sysdev_attribute *attr, char *buf) ++static ssize_t pf_show(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; + + return sprintf(buf, "0x%x\n", uci->cpu_sig.pf); + } + +-static SYSDEV_ATTR(reload, 0200, NULL, reload_store); +-static SYSDEV_ATTR(version, 0400, version_show, NULL); +-static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL); ++static DEVICE_ATTR(reload, 0200, NULL, reload_store); ++static DEVICE_ATTR(version, 0400, version_show, NULL); ++static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL); + + static struct attribute *mc_default_attrs[] = { +- &attr_reload.attr, +- &attr_version.attr, +- &attr_processor_flags.attr, ++ &dev_attr_reload.attr, ++ &dev_attr_version.attr, ++ &dev_attr_processor_flags.attr, + NULL + }; + +@@ -416,16 +417,16 @@ static enum ucode_state microcode_update_cpu(int cpu) + return ustate; + } + +-static int mc_sysdev_add(struct sys_device *sys_dev) ++static int mc_device_add(struct device *dev, struct subsys_interface *sif) + { +- int err, cpu = sys_dev->id; ++ int err, cpu = dev->id; + + if (!cpu_online(cpu)) + return 0; + + pr_debug("CPU%d added\n", cpu); + +- err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); ++ err = sysfs_create_group(&dev->kobj, &mc_attr_group); + if (err) + return err; + +@@ -435,22 +436,24 @@ static int mc_sysdev_add(struct sys_device *sys_dev) + return err; + } + +-static int mc_sysdev_remove(struct sys_device *sys_dev) ++static int mc_device_remove(struct device *dev, struct subsys_interface *sif) + { +- int cpu = sys_dev->id; ++ int cpu = dev->id; + + if (!cpu_online(cpu)) + return 0; + + pr_debug("CPU%d removed\n", cpu); + microcode_fini_cpu(cpu); +- sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); ++ sysfs_remove_group(&dev->kobj, &mc_attr_group); + return 0; + } + +-static struct sysdev_driver mc_sysdev_driver = { +- .add = mc_sysdev_add, +- .remove = mc_sysdev_remove, ++static struct subsys_interface mc_cpu_interface = { ++ .name = "microcode", ++ .subsys = &cpu_subsys, ++ .add_dev = mc_device_add, ++ .remove_dev = mc_device_remove, + }; + + /** +@@ -473,9 +476,9 @@ static __cpuinit int + mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) + { + unsigned int cpu = (unsigned long)hcpu; +- struct sys_device *sys_dev; ++ struct device *dev; + +- sys_dev = get_cpu_sysdev(cpu); ++ dev = get_cpu_device(cpu); + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: +@@ -483,13 +486,13 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) + case CPU_DOWN_FAILED: + case CPU_DOWN_FAILED_FROZEN: + pr_debug("CPU%d added\n", cpu); +- if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) ++ if (sysfs_create_group(&dev->kobj, &mc_attr_group)) + pr_err("Failed to create group for CPU%d\n", cpu); + break; + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + /* Suspend is in progress, only remove the interface */ +- sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); ++ sysfs_remove_group(&dev->kobj, &mc_attr_group); + pr_debug("CPU%d removed\n", cpu); + break; + +@@ -516,7 +519,9 @@ static int __init microcode_init(void) + struct cpuinfo_x86 *c = &cpu_data(0); + int error; + +- if (c->x86_vendor == X86_VENDOR_INTEL) ++ if (xen_pv_domain()) ++ microcode_ops = init_xen_microcode(); ++ else if (c->x86_vendor == X86_VENDOR_INTEL) + microcode_ops = init_intel_microcode(); + else if (c->x86_vendor == X86_VENDOR_AMD) + microcode_ops = init_amd_microcode(); +@@ -534,7 +539,7 @@ static int __init microcode_init(void) + get_online_cpus(); + mutex_lock(µcode_mutex); + +- error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver); ++ error = subsys_interface_register(&mc_cpu_interface); + + mutex_unlock(µcode_mutex); + put_online_cpus(); +@@ -544,7 +549,7 @@ static int __init microcode_init(void) + + error = microcode_dev_init(); + if (error) +- goto out_sysdev_driver; ++ goto out_driver; + + register_syscore_ops(&mc_syscore_ops); + register_hotcpu_notifier(&mc_cpu_notifier); +@@ -554,11 +559,11 @@ static int __init microcode_init(void) + + return 0; + +-out_sysdev_driver: ++out_driver: + get_online_cpus(); + mutex_lock(µcode_mutex); + +- sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); ++ subsys_interface_unregister(&mc_cpu_interface); + + mutex_unlock(µcode_mutex); + put_online_cpus(); +@@ -580,7 +585,7 @@ static void __exit microcode_exit(void) + get_online_cpus(); + mutex_lock(µcode_mutex); + +- sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); ++ subsys_interface_unregister(&mc_cpu_interface); + + mutex_unlock(µcode_mutex); + put_online_cpus(); +diff --git a/arch/x86/kernel/microcode_xen.c b/arch/x86/kernel/microcode_xen.c +new file mode 100644 +index 0000000..9e50566 +--- /dev/null ++++ b/arch/x86/kernel/microcode_xen.c +@@ -0,0 +1,202 @@ ++/* ++ * Xen microcode update driver ++ * ++ * Xen does most of the work here. We just pass the whole blob into ++ * Xen, and it will apply it to all CPUs as appropriate. Xen will ++ * worry about how different CPU models are actually updated. ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++MODULE_DESCRIPTION("Xen microcode update driver"); ++MODULE_LICENSE("GPL"); ++ ++struct xen_microcode { ++ size_t len; ++ char data[0]; ++}; ++ ++static int xen_microcode_update(int cpu) ++{ ++ int err; ++ struct xen_platform_op op; ++ struct ucode_cpu_info *uci = ucode_cpu_info + cpu; ++ struct xen_microcode *uc = uci->mc; ++ ++ if (uc == NULL || uc->len == 0) { ++ /* ++ * We do all cpus at once, so we don't need to do ++ * other cpus explicitly (besides, these vcpu numbers ++ * have no relationship to underlying physical cpus). ++ */ ++ return 0; ++ } ++ ++ op.cmd = XENPF_microcode_update; ++ set_xen_guest_handle(op.u.microcode.data, uc->data); ++ op.u.microcode.length = uc->len; ++ ++ err = HYPERVISOR_dom0_op(&op); ++ ++ if (err != 0) ++ printk(KERN_WARNING "microcode_xen: microcode update failed: %d\n", err); ++ ++ return err; ++} ++ ++static enum ucode_state xen_request_microcode_fw(int cpu, struct device *device) ++{ ++ char name[36]; ++ struct cpuinfo_x86 *c = &cpu_data(cpu); ++ const struct firmware *firmware; ++ struct ucode_cpu_info *uci = ucode_cpu_info + cpu; ++ enum ucode_state ret; ++ struct xen_microcode *uc; ++ size_t size; ++ int err; ++ ++ switch (c->x86_vendor) { ++ case X86_VENDOR_INTEL: ++ snprintf(name, sizeof(name), "intel-ucode/%02x-%02x-%02x", ++ c->x86, c->x86_model, c->x86_mask); ++ break; ++ ++ case X86_VENDOR_AMD: ++ /* Beginning with family 15h AMD uses family-specific firmware files. */ ++ if (c->x86 >= 0x15) ++ snprintf(name, sizeof(name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); ++ else ++ snprintf(name, sizeof(name), "amd-ucode/microcode_amd.bin"); ++ break; ++ ++ default: ++ return UCODE_NFOUND; ++ } ++ ++ err = request_firmware(&firmware, name, device); ++ if (err) { ++ pr_debug("microcode: data file %s load failed\n", name); ++ return UCODE_NFOUND; ++ } ++ ++ /* ++ * Only bother getting real firmware for cpu 0; the others get ++ * dummy placeholders. ++ */ ++ if (cpu == 0) ++ size = firmware->size; ++ else ++ size = 0; ++ ++ if (uci->mc != NULL) { ++ vfree(uci->mc); ++ uci->mc = NULL; ++ } ++ ++ ret = UCODE_ERROR; ++ uc = vmalloc(sizeof(*uc) + size); ++ if (uc == NULL) ++ goto out; ++ ++ ret = UCODE_OK; ++ uc->len = size; ++ memcpy(uc->data, firmware->data, uc->len); ++ ++ uci->mc = uc; ++ ++out: ++ release_firmware(firmware); ++ ++ return ret; ++} ++ ++static enum ucode_state xen_request_microcode_user(int cpu, ++ const void __user *buf, size_t size) ++{ ++ struct ucode_cpu_info *uci = ucode_cpu_info + cpu; ++ struct xen_microcode *uc; ++ enum ucode_state ret; ++ size_t unread; ++ ++ if (cpu != 0) { ++ /* No real firmware for non-zero cpus; just store a ++ placeholder */ ++ size = 0; ++ } ++ ++ if (uci->mc != NULL) { ++ vfree(uci->mc); ++ uci->mc = NULL; ++ } ++ ++ ret = UCODE_ERROR; ++ uc = vmalloc(sizeof(*uc) + size); ++ if (uc == NULL) ++ goto out; ++ ++ uc->len = size; ++ ++ ret = UCODE_NFOUND; ++ ++ unread = copy_from_user(uc->data, buf, size); ++ ++ if (unread != 0) { ++ printk(KERN_WARNING "failed to read %zd of %zd bytes at %p -> %p\n", ++ unread, size, buf, uc->data); ++ goto out; ++ } ++ ++ ret = UCODE_OK; ++ ++out: ++ if (ret == UCODE_OK) ++ uci->mc = uc; ++ else ++ vfree(uc); ++ ++ return ret; ++} ++ ++static void xen_microcode_fini_cpu(int cpu) ++{ ++ struct ucode_cpu_info *uci = ucode_cpu_info + cpu; ++ ++ vfree(uci->mc); ++ uci->mc = NULL; ++} ++ ++static int xen_collect_cpu_info(int cpu, struct cpu_signature *sig) ++{ ++ sig->sig = 0; ++ sig->pf = 0; ++ sig->rev = 0; ++ ++ return 0; ++} ++ ++static struct microcode_ops microcode_xen_ops = { ++ .request_microcode_user = xen_request_microcode_user, ++ .request_microcode_fw = xen_request_microcode_fw, ++ .collect_cpu_info = xen_collect_cpu_info, ++ .apply_microcode = xen_microcode_update, ++ .microcode_fini_cpu = xen_microcode_fini_cpu, ++}; ++ ++struct microcode_ops * __init init_xen_microcode(void) ++{ ++ if (!xen_initial_domain()) ++ return NULL; ++ return µcode_xen_ops; ++} +diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c +index 84c938f..aba9d40 100644 +--- a/arch/x86/kernel/paravirt.c ++++ b/arch/x86/kernel/paravirt.c +@@ -132,6 +132,7 @@ static void *get_call_destination(u8 type) + #ifdef CONFIG_PARAVIRT_SPINLOCKS + .pv_lock_ops = pv_lock_ops, + #endif ++ .pv_mmu_lazy_mode_flush = pv_mmu_lazy_mode_flush, + }; + return *((void **)&tmpl + type); + } +@@ -475,12 +476,13 @@ struct pv_mmu_ops pv_mmu_ops = { + .lazy_mode = { + .enter = paravirt_nop, + .leave = paravirt_nop, +- .flush = paravirt_nop, + }, + + .set_fixmap = native_set_fixmap, + }; + ++void (*pv_mmu_lazy_mode_flush)(void) = paravirt_nop; ++ + EXPORT_SYMBOL_GPL(pv_time_ops); + EXPORT_SYMBOL (pv_cpu_ops); + EXPORT_SYMBOL (pv_mmu_ops); +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index 59b9b37..cc216a7 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -105,11 +106,12 @@ void show_regs_common(void) + board = dmi_get_system_info(DMI_BOARD_NAME); + + printk(KERN_CONT "\n"); +- printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s", ++ printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s%s", + current->pid, current->comm, print_tainted(), + init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), +- init_utsname()->version); ++ init_utsname()->version, ++ LINUX_PACKAGE_ID); + printk(KERN_CONT " %s %s", vendor, product); + if (board) + printk(KERN_CONT "/%s", board); +diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c +index 78842ce..ebbba3c 100644 +--- a/arch/x86/kernel/reboot.c ++++ b/arch/x86/kernel/reboot.c +@@ -93,11 +93,14 @@ static int __init reboot_setup(char *str) + case 'b': + #endif + case 'a': ++ case 'd': ++ case 'g': + case 'k': + case 't': + case 'e': + case 'p': +- reboot_type = *str; ++ case 'y': ++ reboot_type = *str; + break; + + case 'f': +@@ -379,6 +382,26 @@ static int __init set_pci_reboot(const struct dmi_system_id *d) + return 0; + } + ++static int __init set_cold_cf9_reboot(const struct dmi_system_id *d) ++{ ++ if (reboot_type != BOOT_CF9_COLD) { ++ reboot_type = BOOT_CF9_COLD; ++ printk(KERN_INFO "%s series board detected. " ++ "Selecting CF9 Cold Reset method for reboots.\n", d->ident); ++ } ++ return 0; ++} ++ ++static int __init set_s3000_reboot(const struct dmi_system_id *d) ++{ ++ if (reboot_type != BOOT_S3000_PSU) { ++ reboot_type = BOOT_S3000_PSU; ++ printk(KERN_INFO "%s series board detected. " ++ "Selecting S3000 power cycle method for reboots.\n", d->ident); ++ } ++ return 0; ++} ++ + static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { + { /* Handle problems with rebooting on Apple MacBook5 */ + .callback = set_pci_reboot, +@@ -494,6 +517,55 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"), + }, + }, ++ { /* Perform cold reset on Dell S3000 */ ++ .callback = set_s3000_reboot, ++ .ident = "Dell S3000", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "S3000"), ++ }, ++ }, ++ { /* Perform cold reset on Penguin Computing 4804iq-r */ ++ .callback = set_s3000_reboot, ++ .ident = "Penguin Computing 4804iq-r", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Penguin Computing"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "4804iq-r"), ++ }, ++ }, ++ { /* Perform cold reset on Penguin Computing 4804iq */ ++ .callback = set_s3000_reboot, ++ .ident = "Penguin Computing 4804iq", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Penguin Computing"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "4804iq"), ++ }, ++ }, ++ { /* Perform cold reset on Celestica E1031 */ ++ .callback = set_s3000_reboot, ++ .ident = "Celestica E1031", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Celestica"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "E1031"), ++ }, ++ }, ++ { /* Perform cold reset on Dell S6000 */ ++ .callback = set_cold_cf9_reboot, ++ .ident = "Dell S6000", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "S6000"), ++ }, ++ }, ++ { /* Dell S6000 could have either manufacturer names: Dell Inc or ++ Dell Force10 Networks. Accomodating for both */ ++ .callback = set_cold_cf9_reboot, ++ .ident = "Dell S6000", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Force10 Networks"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "S6000"), ++ }, ++ }, + { /* Handle problems with rebooting on the Dell PowerEdge C6100. */ + .callback = set_pci_reboot, + .ident = "Dell PowerEdge C6100", +@@ -595,6 +667,8 @@ static void native_machine_emergency_restart(void) + int i; + int attempt = 0; + int orig_reboot_type = reboot_type; ++ u8 cf9_cold = 0; ++ u8 cf9_full = 0; + + if (reboot_emergency) + emergency_vmx_disable_all(); +@@ -667,6 +741,30 @@ static void native_machine_emergency_restart(void) + } + reboot_type = BOOT_KBD; + break; ++ ++ case BOOT_S3000_PSU: ++ iowrite8(0x03 /* power off PSUR+PSUL */, ioport_map(0x203 /* CPLD_SMC_PSU_CONTROL */, 1)); ++ udelay(50); ++ reboot_type = BOOT_KBD; ++ /* fall through in case CPLD based reset fails */ ++ ++ case BOOT_CF9_FULL: ++ cf9_full = inb(0xcf9) & ~0x0e; ++ outb(cf9_full|2, 0xcf9); /* Request hard reset */ ++ udelay(50); ++ outb(cf9_full|0x0e, 0xcf9); /* Actually do the reset */ ++ udelay(50); ++ reboot_type = BOOT_KBD; ++ break; ++ ++ case BOOT_CF9_COLD: ++ cf9_cold = inb(0xcf9) & ~6; ++ outb(cf9_cold|8, 0xcf9); /* Request cold reset */ ++ udelay(50); ++ outb(cf9_cold|12, 0xcf9); /* Actually do the reset */ ++ udelay(50); ++ reboot_type = BOOT_KBD; ++ break; + } + } + } +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index b506f41..cfaf677 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -50,6 +50,9 @@ + #include + #include + #include ++#ifdef CONFIG_EARLY_DMA_ALLOC ++#include ++#endif + + #include + #include +@@ -1144,6 +1147,9 @@ void __init setup_arch(char **cmdline_p) + mcheck_init(); + + arch_init_ideal_nops(); ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif + } + + #ifdef CONFIG_X86_32 +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 421958f..e89fcac 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -3962,12 +3962,15 @@ static bool nested_exit_on_intr(struct kvm_vcpu *vcpu) + static void enable_irq_window(struct kvm_vcpu *vcpu) + { + u32 cpu_based_vm_exec_control; +- if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu)) +- /* We can get here when nested_run_pending caused +- * vmx_interrupt_allowed() to return false. In this case, do +- * nothing - the interrupt will be injected later. ++ if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu)) { ++ /* ++ * We get here if vmx_interrupt_allowed() said we can't ++ * inject to L1 now because L2 must run. Ask L2 to exit ++ * right after entry, so we can inject to L1 more promptly. + */ ++ kvm_make_request(KVM_REQ_IMMEDIATE_EXIT, vcpu); + return; ++ } + + cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL); + cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING; +@@ -4094,11 +4097,12 @@ static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked) + static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu) + { + if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu)) { +- struct vmcs12 *vmcs12; +- if (to_vmx(vcpu)->nested.nested_run_pending) ++ struct vmcs12 *vmcs12 = get_vmcs12(vcpu); ++ if (to_vmx(vcpu)->nested.nested_run_pending || ++ (vmcs12->idt_vectoring_info_field & ++ VECTORING_INFO_VALID_MASK)) + return 0; + nested_vmx_vmexit(vcpu); +- vmcs12 = get_vmcs12(vcpu); + vmcs12->vm_exit_reason = EXIT_REASON_EXTERNAL_INTERRUPT; + vmcs12->vm_exit_intr_info = 0; + /* fall through to normal code, but now in L1, not L2 */ +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index bb179cc..560ed9f 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -5668,6 +5668,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) + int r; + bool req_int_win = !irqchip_in_kernel(vcpu->kvm) && + vcpu->run->request_interrupt_window; ++ bool req_immediate_exit = 0; + + if (vcpu->requests) { + if (kvm_check_request(KVM_REQ_MMU_RELOAD, vcpu)) +@@ -5707,7 +5708,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) + record_steal_time(vcpu); + if (kvm_check_request(KVM_REQ_NMI, vcpu)) + process_nmi(vcpu); +- ++ req_immediate_exit = ++ kvm_check_request(KVM_REQ_IMMEDIATE_EXIT, vcpu); + } + + r = kvm_mmu_reload(vcpu); +@@ -5758,6 +5760,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) + + srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); + ++ if (req_immediate_exit) ++ smp_send_reschedule(vcpu->cpu); ++ + kvm_guest_enter(); + + if (unlikely(vcpu->arch.switch_db_regs)) { +diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c +index 8f4fda4..63734f1 100644 +--- a/arch/x86/lguest/boot.c ++++ b/arch/x86/lguest/boot.c +@@ -1328,7 +1328,7 @@ __init void lguest_init(void) + pv_mmu_ops.read_cr3 = lguest_read_cr3; + pv_mmu_ops.lazy_mode.enter = paravirt_enter_lazy_mmu; + pv_mmu_ops.lazy_mode.leave = lguest_leave_lazy_mmu_mode; +- pv_mmu_ops.lazy_mode.flush = paravirt_flush_lazy_mmu; ++ pv_mmu_lazy_mode_flush = paravirt_flush_lazy_mmu; + pv_mmu_ops.pte_update = lguest_pte_update; + pv_mmu_ops.pte_update_defer = lguest_pte_update; + +diff --git a/arch/x86/mm/memtest.c b/arch/x86/mm/memtest.c +index 92faf3a..ac6bdaa 100644 +--- a/arch/x86/mm/memtest.c ++++ b/arch/x86/mm/memtest.c +@@ -30,6 +30,8 @@ static u64 patterns[] __initdata = { + + static void __init reserve_bad_mem(u64 pattern, u64 start_bad, u64 end_bad) + { ++ WARN_ONCE(1, "Bad RAM detected. Use memtest86+ to perform a thorough test\n" ++ "and the memmap= parameter to reserve the bad areas."); + printk(KERN_INFO " %016llx bad mem addr %010llx - %010llx reserved\n", + (unsigned long long) pattern, + (unsigned long long) start_bad, +diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c +index 0ed97d8..f1a970f 100644 +--- a/arch/x86/pci/acpi.c ++++ b/arch/x86/pci/acpi.c +@@ -329,6 +329,66 @@ res_alloc_fail: + return; + } + ++/* ++ * scan and set the PCIe bus payload and read request sizes. ++ */ ++static int __devinit __fixup_pcie_scan_payload(struct pci_dev *pdev, ++ void *data) ++{ ++ int *payload_size = data; ++ int rval, cap, payload_cap; ++ uint32_t devcap; ++ ++ if (!pci_is_pcie(pdev)) ++ return 0; ++ ++ cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); ++ if (cap == 0) ++ return -ENODEV; ++ ++ rval = pci_read_config_dword(pdev, cap + PCI_EXP_DEVCAP, &devcap); ++ if (rval) ++ return rval; ++ ++ payload_cap = devcap & PCI_EXP_DEVCAP_PAYLOAD; ++ if (payload_cap < *payload_size) ++ *payload_size = payload_cap; ++ ++ return 0; ++} ++ ++static int __devinit __fixup_pcie_set_payload(struct pci_dev *pdev, ++ void *data) ++{ ++ int *payload_size = data; ++ int rval, cap; ++ uint16_t devctl; ++ ++ if (!pci_is_pcie(pdev)) ++ return 0; ++ ++ cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); ++ if (cap == 0) ++ return -ENODEV; ++ ++ rval = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &devctl); ++ if (rval) ++ return rval; ++ ++ devctl &= ~PCI_EXP_DEVCTL_PAYLOAD; ++ devctl |= *payload_size << 5; ++ ++ devctl &= ~PCI_EXP_DEVCTL_READRQ; ++ devctl |= *payload_size << 12; ++ ++ rval = pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, devctl); ++ if (rval) ++ return rval; ++ ++ return 0; ++} ++ ++ + struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) + { + struct acpi_device *device = root->device; +@@ -395,6 +455,28 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) + } + } + ++/* Set the payload size for all devices on the bus */ ++ if (bus) { ++ int payload_size; ++ payload_size = PCI_EXP_DEVCAP_PAYLOAD; ++ pci_walk_bus(bus, __fixup_pcie_scan_payload, &payload_size); ++ if (payload_size < PCI_EXP_DEVCAP_PAYLOAD) { ++ pci_walk_bus(bus, __fixup_pcie_set_payload, ++ &payload_size); ++ dev_info(&bus->dev, ++ "Set PCIe payload and read request to %d\n", ++ (payload_size == 0) ? 128 : ++ (payload_size == 1) ? 256 : ++ (payload_size == 2) ? 512 : ++ (payload_size == 3) ? 1024 : ++ (payload_size == 4) ? 2048 : ++ (payload_size == 5) ? 4096 : ++ (payload_size == 6) ? 8192 : ++ 16384 ++ ); ++ } ++ } ++ + /* After the PCI-E bus has been walked and all devices discovered, + * configure any settings of the fabric that might be necessary. + */ +diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c +index e56da77..ebfd13b 100644 +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -56,6 +57,9 @@ + + static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; + ++int efi_enabled; ++EXPORT_SYMBOL(efi_enabled); ++ + struct efi __read_mostly efi = { + .mps = EFI_INVALID_TABLE_ADDR, + .acpi = EFI_INVALID_TABLE_ADDR, +@@ -84,11 +88,11 @@ unsigned long x86_efi_facility; + /* + * Returns 1 if 'facility' is enabled, 0 otherwise. + */ +-int efi_enabled(int facility) ++int efi_enabled_facility(int facility) + { + return test_bit(facility, &x86_efi_facility) != 0; + } +-EXPORT_SYMBOL(efi_enabled); ++EXPORT_SYMBOL(efi_enabled_facility); + + static bool disable_runtime = false; + static int __init setup_noefi(char *arg) +@@ -592,6 +596,7 @@ void __init efi_init(void) + efi.get_time = phys_efi_get_time; + + set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility); ++ efi_enabled = 1; + } else + printk(KERN_ERR "Could not map the EFI runtime service " + "table!\n"); +@@ -619,6 +624,20 @@ void __init efi_init(void) + #endif + } + ++#ifdef CONFIG_EFI_VARS_MODULE ++static int __init efi_load_efivars(void) ++{ ++ struct platform_device *pdev; ++ ++ if (!efi_enabled(EFI_RUNTIME_SERVICES)) ++ return 0; ++ ++ pdev = platform_device_register_simple("efivars", 0, NULL, 0); ++ return IS_ERR(pdev) ? PTR_ERR(pdev) : 0; ++} ++device_initcall(efi_load_efivars); ++#endif ++ + void __init efi_set_executable(efi_memory_desc_t *md, bool executable) + { + u64 addr, npages; +diff --git a/arch/x86/um/sysrq_64.c b/arch/x86/um/sysrq_64.c +index e891343..65bfec9 100644 +--- a/arch/x86/um/sysrq_64.c ++++ b/arch/x86/um/sysrq_64.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include "sysrq.h" +@@ -16,8 +17,9 @@ void __show_regs(struct pt_regs *regs) + { + printk("\n"); + print_modules(); +- printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current), +- current->comm, print_tainted(), init_utsname()->release); ++ printk(KERN_INFO "Pid: %d, comm: %.20s %s %s%s\n", task_pid_nr(current), ++ current->comm, print_tainted(), init_utsname()->release, ++ LINUX_PACKAGE_ID); + printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff, + PT_REGS_RIP(regs)); + printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_SP(regs), +diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig +index 26c731a..7cbcbd1 100644 +--- a/arch/x86/xen/Kconfig ++++ b/arch/x86/xen/Kconfig +@@ -48,3 +48,7 @@ config XEN_DEBUG_FS + help + Enable statistics output and various tuning options in debugfs. + Enabling this option may incur a significant performance overhead. ++ ++config MICROCODE_XEN ++ def_bool y ++ depends on XEN_DOM0 && MICROCODE +diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c +index fe00be6..ca89512 100644 +--- a/arch/x86/xen/mmu.c ++++ b/arch/x86/xen/mmu.c +@@ -2079,7 +2079,6 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = { + .lazy_mode = { + .enter = paravirt_enter_lazy_mmu, + .leave = xen_leave_lazy_mmu, +- .flush = paravirt_flush_lazy_mmu, + }, + + .set_fixmap = xen_set_fixmap, +@@ -2091,6 +2090,7 @@ void __init xen_init_mmu_ops(void) + x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start; + x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done; + pv_mmu_ops = xen_mmu_ops; ++ pv_mmu_lazy_mode_flush = paravirt_flush_lazy_mmu, + + memset(dummy_mapping, 0xff, PAGE_SIZE); + } +diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig +index c346ccd..8a3f835 100644 +--- a/arch/xtensa/Kconfig ++++ b/arch/xtensa/Kconfig +@@ -9,6 +9,7 @@ config XTENSA + select HAVE_IDE + select HAVE_GENERIC_HARDIRQS + select GENERIC_IRQ_SHOW ++ select GENERIC_CPU_DEVICES + help + Xtensa processors are 32-bit RISC machines designed by Tensilica + primarily for embedded systems. These processors are both +diff --git a/cumulus/control.linux-headers b/cumulus/control.linux-headers +new file mode 100644 +index 0000000..41b1471 +--- /dev/null ++++ b/cumulus/control.linux-headers +@@ -0,0 +1,5 @@ ++Package: linux-headers-=R ++Version: =V ++Maintainer: support@cumulusnetworks.com ++Architecture: =A ++Description: Cumulus Linux kernel headers +diff --git a/cumulus/control.linux-image b/cumulus/control.linux-image +new file mode 100644 +index 0000000..3264ec8 +--- /dev/null ++++ b/cumulus/control.linux-image +@@ -0,0 +1,6 @@ ++Package: linux-image-=R ++Version: =V ++Maintainer: support@cumulusnetworks.com ++Architecture: =A ++Description: Cumulus Linux kernel ++Breaks: clag (<< 0.3-cl25+4), libnl-3-200 (<< 3.2.7-4+cl2.5+4), iproute (<< 20120521-3+cl2.5+4), switchd (<< 1.0-cl2.5+9) +diff --git a/cumulus/control.linux-libc-dev b/cumulus/control.linux-libc-dev +new file mode 100644 +index 0000000..943a0086 +--- /dev/null ++++ b/cumulus/control.linux-libc-dev +@@ -0,0 +1,12 @@ ++Package: linux-libc-dev-=V ++Source: linux-upstream ++Version: =V ++Architecture: =A ++Maintainer: cumulus ++Provides: linux-kernel-headers ++Section: devel ++Priority: optional ++Homepage: http://www.kernel.org/ ++Description: Linux support headers for userspace development ++ This package provides userspaces headers from the Linux kernel. These headers ++ are used by the installed headers for GNU glibc and other system libraries. +diff --git a/cumulus/hooks/update-cumulus.postinst b/cumulus/hooks/update-cumulus.postinst +new file mode 100755 +index 0000000..9ea8dae +--- /dev/null ++++ b/cumulus/hooks/update-cumulus.postinst +@@ -0,0 +1,54 @@ ++#!/bin/sh -e ++ ++release="$1" ++ ++# exit if we dont need to update the kernel and initrd ++if [ "$UPDATE_CUMULUS" = 'No' ]; then ++ exit 0 ++fi ++ ++. /usr/share/cumulus/img/functions ++ ++# passing the kernel release is required ++if [ -z "${release}" ]; then ++ echo >&2 "W: cumulus-kernel: ${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a release number" ++ exit 2 ++fi ++ ++bootdir="/boot" ++kernel_newimg_src="${bootdir}/vmlinuz-${release}" ++initrd_newimg_src="${bootdir}/initrd.img-${release}" ++ ++if [ ! -e "$kernel_newimg_src" ]; then ++ echo >&2 "W: cumulus-kernel: ${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} cannot find kernel image" ++ exit 2 ++fi ++ ++if [ ! -e "$initrd_newimg_src" ]; then ++ echo >&2 "W: cumulus-kernel: ${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} cannot find initrd image" ++ exit 2 ++fi ++ ++cl_check_env root-priv ++ ++currslot=${slot_prefix}${active} ++kernel_oldimg=${bootdir}/${kernel_prefix}vmlinuz-*-${currslot} ++initrd_oldimg=${bootdir}/${kernel_prefix}initrd.img-*-${currslot} ++ ++kernel_newimg_dst=${bootdir}/${kernel_prefix}vmlinuz-${release}-${currslot} ++initrd_newimg_dst=${bootdir}/${kernel_prefix}initrd.img-${release}-${currslot} ++ ++#remove existing currslot images ++rm -f ${kernel_oldimg} ++rm -f ${initrd_oldimg} ++ ++# Move kernel/initrd files to the kernel initrd dst files ++cmd="mv -f $kernel_newimg_src $kernel_newimg_dst" ++echo "$cmd" ++$cmd ++ ++cmd="mv -f $initrd_newimg_src $initrd_newimg_dst" ++echo "$cmd" ++$cmd ++ ++depmod -a $release +diff --git a/cumulus/postinst.linux-image.powerpc b/cumulus/postinst.linux-image.powerpc +new file mode 100755 +index 0000000..3b88c77 +--- /dev/null ++++ b/cumulus/postinst.linux-image.powerpc +@@ -0,0 +1,61 @@ ++#!/bin/sh ++# postinst script for kernel ++# ++# see: dh_installdeb(1) ++ ++set -e ++ ++# summary of how this script can be called: ++# * `configure' ++# * `abort-upgrade' ++# * `abort-remove' `in-favour' ++# ++# * `abort-remove' ++# * `abort-deconfigure' `in-favour' ++# `removing' ++# ++# for details, see http://www.debian.org/doc/debian-policy/ or ++# the debian-policy package ++ ++ ++case "$1" in ++ configure) ++ ;; ++ ++ abort-upgrade|abort-remove|abort-deconfigue) ++ exit 1 ++ ;; ++ *) ++ echo "postinst called with unknown argument \`$1'" >&2 ++ exit 1 ++ ;; ++esac ++ ++. /usr/share/cumulus/img/functions ++ ++installer=/usr/lib/linux-image-=R/.installer ++install_file=${installer}/kernel_install.sh ++kimage_linkname="uImage.itb" ++kimage_name="uImage-=R-=A.itb" ++kimage_path="/boot/"$kimage_name ++ ++if [ -e "/.buildroot" ]; then ++ cd /boot && ln -sf $kimage_name $kimage_linkname ++ exit 0 ++fi ++ ++cl_check_env root-priv ++slot=$active ++ ++sh $install_file $kimage_path $slot || { ++ log_failure_msg "Kernel installtion failed." ++ log_failure_msg "Problems installing image file." ++ exit 1 ++} ++ ++cd /boot && ln -sf $kimage_name $kimage_linkname ++ ++echo "depmod -a =R" ++depmod -a =R ++ ++exit 0 +diff --git a/debian/.gitignore b/debian/.gitignore +new file mode 100644 +index 0000000..7d2fb3b +--- /dev/null ++++ b/debian/.gitignore +@@ -0,0 +1,23 @@ ++*.dump ++*.pyc ++/control* ++ ++files ++rules.gen ++ ++build/ ++stamps/ ++ ++linux-headers-* ++linux-image-* ++xen-linux-* ++kernel-image-* ++linux-doc-* ++linux-libc-* ++linux-manual-* ++linux-source-* ++linux-support-* ++*-modules-* ++ ++!patches ++!.keep +diff --git a/debian/README.Debian b/debian/README.Debian +new file mode 100644 +index 0000000..fa5b58c +--- /dev/null ++++ b/debian/README.Debian +@@ -0,0 +1,56 @@ ++Linux kernel for Debian ++----------------------- ++ ++Patches ++------- ++Debian applies small changes to the kernel source. These are split up into ++separated patches addressing individual problems. Each of the patch files ++contains a description and mentions the author. The patches can be found ++at http://svn.debian.org/wsvn/kernel/dists/trunk/linux/debian/patches/. ++ ++Config Files ++------------ ++The .config files used to build the various linux-image files are dynamically ++generated during the linux package build. See the source package for ++details. Each linux-image-* package provides the complete .config file that ++was used to generate it. This file is installed in /boot. ++ ++Scope of security support ++------------------------- ++Security support is provided not only for the binary builds, but also ++for the full source package, allowing for locally customized kernels. ++However, kernel options that are not enabled in official Debian builds are ++given a lower priority for security support. Options marked as BROKEN ++or EXPERIMENTAL are of very low priority, and should not be enabled in ++customized builds for a security-sensitive environment. ++ ++Building custom kernel binary packages ++-------------------------------------- ++We recommend using the 'make deb-pkg' target provided by the upstream ++kernel source. ++ ++Rebuilding official binary packages ++----------------------------------- ++You can build specific kernel binary packages using the targets in ++debian/rules.gen, which have names of the form: ++ binary-arch___ ++ ++Example: ++ fakeroot make -f debian/rules.gen binary-arch_i386_none_686 ++ ++Rebuilding Adaptec AIC7xxx/79xx firmware ++---------------------------------------- ++You can rebuild the firmware for the Adaptec AIC7xxx/79xx SCSI Adapters. To ++do so you need to set AIC7XXX_BUILD_FIRMWARE/AIC79XX_BUILD_FIRMWARE config ++options. Note that this requires to have the development packages for ++berkelydb (libdb4.2-dev) installed. ++ ++Non-free bits removed ++--------------------- ++See the patches under debian/patches/debian/dfsg. ++ ++Further information ++------------------- ++Debian Linux Kernel Handbook: http://kernel-handbook.alioth.debian.org ++ or debian-kernel-handbook package ++Debian Wiki: http://wiki.debian.org/DebianKernel +diff --git a/debian/README.source b/debian/README.source +new file mode 100644 +index 0000000..ad841fa +--- /dev/null ++++ b/debian/README.source +@@ -0,0 +1,80 @@ ++Updating the upstream source ++============================ ++ ++1) You can use either: ++ a) a git repository of the kernel source ++ b) a kernel tarball from kernel.org (e.g. linux-3.4.tar.bz2) ++ and, optionally, a patch (e.g. patch-3.5-rc1.bz2). ++ ++2) Run ./debian/bin/genorig.py ++ or ./debian/bin/genorig.py [patch] ++ This will produce ../orig/linux_.orig.tar.gz ++ (e.g. linux_3.5~rc1.orig.tar.gz). ++ ++ (genorig.py requires the python and unifdef packages to be ++ installed) ++ ++3) Unpack linux_.orig.tar.gz, cd into the new directory, ++ and do a 'svn export' to get the debian/ subdirectory. ++ Alternatively unpack using "make -f debian/rules orig". ++ ++ (the orig target of the Makefiles requires rsync) ++ ++Applying patches to the Debian kernel tree ++========================================== ++ ++The Debian kernel packaging uses the quilt patch system, but with ++multiple series to allow for featuresets. ++ ++Patches are stored below debian/patches, loosely sorted in bugfix/, ++features/ and debian/. Patches are in the standard kernel patch ++format (unified diff to be applied with patch -p1) and generally have ++DEP-3 headers. ++ ++The series file 'series' is used for all configurations and a series ++file 'series-' is used for each optional featureset. ++ ++If you want to generate a source tree with all patches applied, run ++make -f debian/rules source ++ ++The resulting source can be found below debian/build. ++ ++Kernel config files ++=================== ++Configuration files are constructed dynamically from a number of config ++files, as listed in debian/config//defines. ++ ++Control file ++============ ++The master control file debian/control must be generated before ++the package is uploaded. debian/rules contains the debian/control ++target, which generates the control file by invoking the ++debian/bin/gencontrol.py script, which combines the templates from ++the templates directory and architecture-specific defines file to ++produce the debian/control file. Note that this target is intentionally ++made to fail with a non-zero exit code to make sure that it is never ++run during an automatic build. The following variables are substituted ++into the templates: ++ ++@version@ Upstream kernel version, for example 2.6.11. ++@arch@ The Debian arch name, such as powerpc or i386. ++@flavour@ The build flavour, such as 686 or k7-smp. ++@class@ The CPU/architecture class; displayed in synopsis. It should ++ be fairly short, as the synopsis is supposed to be <80 chars. ++ It should be in the form "foo class", and will show up in the ++ description as "foo class machines". ++@longclass@ The CPU/architecture class; displayed in the extended ++ description. The same rules apply as in @class@. If ++ this is unset, it will default to @class@. ++@desc@ (Potentially) multi-line verbiage that's appended to ++ -image descriptions. ++@abiname@ Current abiname, a single digit. ++ ++Normally, the arch-specific contents should be controlled by ++adjusting the corresponding defines file. ++ ++TODO: ++- Patches applied to the upstream source ++- How to define a flavour ++- More detail on generation of debian/control and configs ++ +diff --git a/debian/abi/3.2.0-4/powerpc_none_powerpc-smp-cumulus b/debian/abi/3.2.0-4/powerpc_none_powerpc-smp-cumulus +new file mode 100644 +index 0000000..f461280 +--- /dev/null ++++ b/debian/abi/3.2.0-4/powerpc_none_powerpc-smp-cumulus +@@ -0,0 +1,4912 @@ ++0x897b7f0f usb_serial_generic_submit_read_urb vmlinux EXPORT_SYMBOL_GPL ++0x7de5bdf0 generic_file_splice_write vmlinux EXPORT_SYMBOL ++0x801e2bc9 set_anon_super vmlinux EXPORT_SYMBOL ++0x6fce9192 kmem_cache_alloc vmlinux EXPORT_SYMBOL ++0x96f799f3 replace_page_cache_page vmlinux EXPORT_SYMBOL_GPL ++0x70523a7a __cond_resched_softirq vmlinux EXPORT_SYMBOL ++0x9147a486 of_get_property vmlinux EXPORT_SYMBOL ++0x009a3fb6 i2c_put_adapter vmlinux EXPORT_SYMBOL ++0x495ed07e rtc_class_open vmlinux EXPORT_SYMBOL_GPL ++0x96cd2b04 scsi_sense_key_string vmlinux EXPORT_SYMBOL ++0x0a2487e0 unblock_all_signals vmlinux EXPORT_SYMBOL ++0x3dcfd253 dev_uc_sync vmlinux EXPORT_SYMBOL ++0x8bdf1749 dev_mc_sync vmlinux EXPORT_SYMBOL ++0xccd91589 hwmon_device_unregister vmlinux EXPORT_SYMBOL_GPL ++0xdf27877b register_timer_hook vmlinux EXPORT_SYMBOL_GPL ++0xfbaaf01e console_lock vmlinux EXPORT_SYMBOL ++0xe113bbbc csum_partial vmlinux EXPORT_SYMBOL ++0xa39d9220 unregister_timer_hook vmlinux EXPORT_SYMBOL_GPL ++0xc068440e __kfifo_alloc vmlinux EXPORT_SYMBOL ++0xddf5478d nf_log_register vmlinux EXPORT_SYMBOL ++0x69aa9637 scsi_execute vmlinux EXPORT_SYMBOL ++0x1b17e06c kstrtoll vmlinux EXPORT_SYMBOL ++0xc161fa2b proc_net_remove vmlinux EXPORT_SYMBOL_GPL ++0xcb8c9724 raw_seq_open vmlinux EXPORT_SYMBOL_GPL ++0x8f6f24c7 device_del vmlinux EXPORT_SYMBOL_GPL ++0x0058381b device_add vmlinux EXPORT_SYMBOL_GPL ++0x416460c6 crypto_hash_walk_done vmlinux EXPORT_SYMBOL_GPL ++0xaf063510 _raw_spin_lock_bh vmlinux EXPORT_SYMBOL ++0x3c942368 profile_event_unregister vmlinux EXPORT_SYMBOL_GPL ++0x89ff43f6 init_uts_ns vmlinux EXPORT_SYMBOL_GPL ++0xca8f2cf7 __inet6_hash vmlinux EXPORT_SYMBOL ++0x69181415 dst_release vmlinux EXPORT_SYMBOL ++0x33213a5f sock_no_mmap vmlinux EXPORT_SYMBOL ++0xba0cf4bd disk_map_sector_rcu vmlinux EXPORT_SYMBOL_GPL ++0x206e3996 sysfs_update_group vmlinux EXPORT_SYMBOL_GPL ++0xa38602cd drain_workqueue vmlinux EXPORT_SYMBOL_GPL ++0xfdb9b629 ioread32be vmlinux EXPORT_SYMBOL ++0x436708b0 tcp_initialize_rcv_mss vmlinux EXPORT_SYMBOL ++0x54e6fcdd net_enable_timestamp vmlinux EXPORT_SYMBOL ++0xea2c390d sockfd_lookup vmlinux EXPORT_SYMBOL ++0xc4f9f419 usb_serial_generic_write_bulk_callback vmlinux EXPORT_SYMBOL_GPL ++0xea9855ae blk_limits_max_hw_sectors vmlinux EXPORT_SYMBOL ++0x3dcb51c4 directly_mappable_cdev_bdi vmlinux EXPORT_SYMBOL ++0x6bc3fbc0 __unregister_chrdev vmlinux EXPORT_SYMBOL ++0xa72f6b4b srcu_notifier_chain_register vmlinux EXPORT_SYMBOL_GPL ++0xb5dea7ef g_token_size vmlinux EXPORT_SYMBOL_GPL ++0x122d10bc dev_graft_qdisc vmlinux EXPORT_SYMBOL ++0x829e76cd scsi_get_command vmlinux EXPORT_SYMBOL ++0x7ff10ccf raw_notifier_call_chain vmlinux EXPORT_SYMBOL_GPL ++0xca18d700 flush_tlb_range vmlinux EXPORT_SYMBOL ++0xd54291e6 scsi_target_quiesce vmlinux EXPORT_SYMBOL ++0x2f225631 transport_class_register vmlinux EXPORT_SYMBOL_GPL ++0x30cada8f radix_tree_next_hole vmlinux EXPORT_SYMBOL ++0x66d0ee54 vfsmount_lock_global_unlock vmlinux EXPORT_SYMBOL ++0xdad1a719 input_handler_for_each_handle vmlinux EXPORT_SYMBOL ++0xe3e619b2 transport_class_unregister vmlinux EXPORT_SYMBOL_GPL ++0xffd5a395 default_wake_function vmlinux EXPORT_SYMBOL ++0x434c3c59 pci_bus_read_config_byte vmlinux EXPORT_SYMBOL ++0x1a58b8f5 mount_subtree vmlinux EXPORT_SYMBOL ++0x7eaa917d iget_locked vmlinux EXPORT_SYMBOL ++0x9a696827 sock_get_timestampns vmlinux EXPORT_SYMBOL ++0x0f4ca848 class_interface_register vmlinux EXPORT_SYMBOL_GPL ++0xb711d84e key_type_keyring vmlinux EXPORT_SYMBOL ++0xa4b94fea iowrite8_rep vmlinux EXPORT_SYMBOL ++0x8c7a3757 of_get_named_gpio_flags vmlinux EXPORT_SYMBOL ++0x0f05e347 spi_get_device_id vmlinux EXPORT_SYMBOL_GPL ++0xfa010184 class_interface_unregister vmlinux EXPORT_SYMBOL_GPL ++0x73a903c4 vfsmount_lock_local_lock vmlinux EXPORT_SYMBOL ++0xa9c530b8 unregister_oom_notifier vmlinux EXPORT_SYMBOL_GPL ++0x2eec63c9 xdr_encode_netobj vmlinux EXPORT_SYMBOL_GPL ++0xd5cd5612 xdr_decode_word vmlinux EXPORT_SYMBOL_GPL ++0x9d92332a tty_register_device vmlinux EXPORT_SYMBOL ++0x44366cfc simple_write_to_buffer vmlinux EXPORT_SYMBOL ++0xa28d5490 __srcu_read_unlock vmlinux EXPORT_SYMBOL_GPL ++0xc2e587d1 reset_devices vmlinux EXPORT_SYMBOL ++0x9cdd28bc of_find_all_nodes vmlinux EXPORT_SYMBOL ++0xac1b6c1d mmc_app_cmd vmlinux EXPORT_SYMBOL_GPL ++0x3df5e4b2 usb_bus_list_lock vmlinux EXPORT_SYMBOL_GPL ++0xa5a633b9 sg_last vmlinux EXPORT_SYMBOL ++0xe601908d __blk_run_queue vmlinux EXPORT_SYMBOL ++0x643eaec8 param_get_string vmlinux EXPORT_SYMBOL ++0x99bb8806 memmove vmlinux EXPORT_SYMBOL ++0xf0904255 __block_page_mkwrite vmlinux EXPORT_SYMBOL ++0x76d3cd60 laptop_mode vmlinux EXPORT_SYMBOL ++0xa10b7029 generic_file_direct_write vmlinux EXPORT_SYMBOL ++0xb7032a2f end_page_writeback vmlinux EXPORT_SYMBOL ++0x50f5e532 call_rcu_sched vmlinux EXPORT_SYMBOL_GPL ++0x46e0a7f2 skb_recv_datagram vmlinux EXPORT_SYMBOL ++0xe230598d d_alloc_pseudo vmlinux EXPORT_SYMBOL ++0x871c0a7e fiemap_check_flags vmlinux EXPORT_SYMBOL ++0x51221294 generic_file_readonly_mmap vmlinux EXPORT_SYMBOL ++0x5d730e7b raw_notifier_chain_unregister vmlinux EXPORT_SYMBOL_GPL ++0x0d542439 __ipv6_addr_type vmlinux EXPORT_SYMBOL ++0x8c5e419b unregister_qdisc vmlinux EXPORT_SYMBOL ++0xe3ebc041 phy_device_register vmlinux EXPORT_SYMBOL ++0x7fd37e2b pci_map_rom vmlinux EXPORT_SYMBOL ++0xdfef1b84 crypto_shash_finup vmlinux EXPORT_SYMBOL_GPL ++0xb58965de crypto_shash_final vmlinux EXPORT_SYMBOL_GPL ++0xea9ea6f1 crypto_ahash_finup vmlinux EXPORT_SYMBOL_GPL ++0x34e42b95 crypto_ahash_final vmlinux EXPORT_SYMBOL_GPL ++0x8da17b42 scatterwalk_copychunks vmlinux EXPORT_SYMBOL_GPL ++0xf9d1164c rpc_free vmlinux EXPORT_SYMBOL_GPL ++0xc78a46ea vm_insert_page vmlinux EXPORT_SYMBOL ++0xad9cdfab register_console vmlinux EXPORT_SYMBOL ++0x243c6e2f nf_conntrack_l4proto_tcp4 net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x227491cf sock_no_socketpair vmlinux EXPORT_SYMBOL ++0x1a0cac4b input_ff_event vmlinux EXPORT_SYMBOL_GPL ++0xb7e566f8 arpt_do_table net/ipv4/netfilter/arp_tables EXPORT_SYMBOL ++0xdfcd2d6f dev_addr_del vmlinux EXPORT_SYMBOL ++0x8631f469 gnet_stats_start_copy vmlinux EXPORT_SYMBOL ++0x87a8ad19 nfs_retry_commit vmlinux EXPORT_SYMBOL_GPL ++0x7aa1a681 tcp_tso_segment vmlinux EXPORT_SYMBOL ++0x9620e18a i2c_lock_adapter vmlinux EXPORT_SYMBOL_GPL ++0xd7ea90c8 platform_device_del vmlinux EXPORT_SYMBOL_GPL ++0x1511ba61 platform_device_put vmlinux EXPORT_SYMBOL_GPL ++0x3e96ee6c __fat_fs_error vmlinux EXPORT_SYMBOL_GPL ++0xb741990c bio_copy_kern vmlinux EXPORT_SYMBOL ++0xe0878bfe __krealloc vmlinux EXPORT_SYMBOL ++0xd8605470 devm_free_irq vmlinux EXPORT_SYMBOL ++0x995d1071 prof_on vmlinux EXPORT_SYMBOL_GPL ++0xa652c4ef __kfifo_dma_in_prepare_r vmlinux EXPORT_SYMBOL ++0xa662b253 task_nice vmlinux EXPORT_SYMBOL ++0x4e9dffb5 ip_fast_csum vmlinux EXPORT_SYMBOL ++0xb9524c5c rpc_exit vmlinux EXPORT_SYMBOL_GPL ++0x5195426a kernel_accept vmlinux EXPORT_SYMBOL ++0x1a26398f pcim_iounmap vmlinux EXPORT_SYMBOL ++0x420ffdd5 kset_create_and_add vmlinux EXPORT_SYMBOL_GPL ++0xc47933f9 mm_kobj vmlinux EXPORT_SYMBOL_GPL ++0xd6d48dbb set_bdi_congested vmlinux EXPORT_SYMBOL ++0x5d9c4677 xt_proto_fini vmlinux EXPORT_SYMBOL_GPL ++0x481bf5f1 driver_find vmlinux EXPORT_SYMBOL_GPL ++0xd461ba2e sg_miter_start vmlinux EXPORT_SYMBOL ++0x4aef7e80 blk_queue_unprep_rq vmlinux EXPORT_SYMBOL ++0x54b411de lock_may_read vmlinux EXPORT_SYMBOL ++0xdbe4131c tty_mode_ioctl vmlinux EXPORT_SYMBOL_GPL ++0x0dc5ceb6 load_nls vmlinux EXPORT_SYMBOL ++0x4563a37d qe_setbrg vmlinux EXPORT_SYMBOL ++0x4859b8bb rtc_year_days vmlinux EXPORT_SYMBOL ++0x4d172ccb ehci_cf_port_reset_rwsem vmlinux EXPORT_SYMBOL_GPL ++0x0c65e73c scsi_normalize_sense vmlinux EXPORT_SYMBOL ++0xb65bd3fc add_timer_on vmlinux EXPORT_SYMBOL_GPL ++0x7e17ba7b klist_iter_exit vmlinux EXPORT_SYMBOL_GPL ++0xcbf1d339 ip6_local_out vmlinux EXPORT_SYMBOL_GPL ++0x8818a3de pci_slots_kset vmlinux EXPORT_SYMBOL_GPL ++0x215ebd78 bitrev16 vmlinux EXPORT_SYMBOL ++0x390def22 kstrtou16_from_user vmlinux EXPORT_SYMBOL ++0x9a74417e kstrtoull_from_user vmlinux EXPORT_SYMBOL ++0x72b243d4 free_dma vmlinux EXPORT_SYMBOL ++0x6e13f758 xdr_init_decode vmlinux EXPORT_SYMBOL_GPL ++0xd072d7d2 device_unregister vmlinux EXPORT_SYMBOL_GPL ++0x30e54d7e crypto_aead_type vmlinux EXPORT_SYMBOL_GPL ++0xafda2ff8 xfrm_state_add vmlinux EXPORT_SYMBOL ++0xcbf4e023 mmc_cleanup_queue vmlinux EXPORT_SYMBOL ++0xed23b4df nf_ct_l3proto_put net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x5b57fe3e scsicam_bios_param vmlinux EXPORT_SYMBOL ++0x853adf25 single_release_net vmlinux EXPORT_SYMBOL_GPL ++0xcd24efa3 I_BDEV vmlinux EXPORT_SYMBOL ++0x74abdafa task_handoff_register vmlinux EXPORT_SYMBOL_GPL ++0x68887e62 tty_port_tty_set vmlinux EXPORT_SYMBOL ++0x5791030d tty_port_tty_get vmlinux EXPORT_SYMBOL ++0x3441c3d6 gpio_set_value_cansleep vmlinux EXPORT_SYMBOL_GPL ++0x6852cd21 seq_release_net vmlinux EXPORT_SYMBOL_GPL ++0x3c0fca43 inet_csk_route_child_sock vmlinux EXPORT_SYMBOL_GPL ++0x28c3aed9 phy_stop_interrupts vmlinux EXPORT_SYMBOL ++0xea5974e8 vfs_path_lookup vmlinux EXPORT_SYMBOL ++0x4790c5b9 find_or_create_page vmlinux EXPORT_SYMBOL ++0x5b0d97e2 schedule_hrtimeout_range vmlinux EXPORT_SYMBOL_GPL ++0xd8849ae7 usb_sg_init vmlinux EXPORT_SYMBOL_GPL ++0x4af7e190 usb_sg_wait vmlinux EXPORT_SYMBOL_GPL ++0xfaf32193 scsi_reset_provider vmlinux EXPORT_SYMBOL ++0x115de368 crypto_register_pcomp vmlinux EXPORT_SYMBOL_GPL ++0x3a47e130 invalidate_bdev vmlinux EXPORT_SYMBOL ++0x9aeacb87 ring_buffer_iter_empty vmlinux EXPORT_SYMBOL_GPL ++0x1f8cee61 tcp_twsk_unique vmlinux EXPORT_SYMBOL_GPL ++0xd3984b47 netdev_info vmlinux EXPORT_SYMBOL ++0x0ba0a26c mmc_try_claim_host vmlinux EXPORT_SYMBOL ++0x11267875 scsi_extd_sense_format vmlinux EXPORT_SYMBOL ++0xeefae453 xdr_buf_from_iov vmlinux EXPORT_SYMBOL_GPL ++0x65b252e9 of_n_addr_cells vmlinux EXPORT_SYMBOL ++0x0e3ead77 pci_bus_write_config_dword vmlinux EXPORT_SYMBOL ++0xf18f172c __dev_printk vmlinux EXPORT_SYMBOL ++0x9445ac6b tty_hung_up_p vmlinux EXPORT_SYMBOL ++0x02e24269 blk_cleanup_queue vmlinux EXPORT_SYMBOL ++0x24995a6b generic_setlease vmlinux EXPORT_SYMBOL ++0x00372404 ipv6_getsockopt vmlinux EXPORT_SYMBOL ++0xdc047fc4 scsi_dev_info_list_add_keyed vmlinux EXPORT_SYMBOL ++0x06094818 pcim_enable_device vmlinux EXPORT_SYMBOL ++0xf9091ce7 timerqueue_del vmlinux EXPORT_SYMBOL_GPL ++0xc742c7f7 usb_driver_release_interface vmlinux EXPORT_SYMBOL_GPL ++0xdaa3f256 swiotlb_unmap_sg vmlinux EXPORT_SYMBOL ++0xbbfeb33c mpage_writepages vmlinux EXPORT_SYMBOL ++0xe1b2b01a write_one_page vmlinux EXPORT_SYMBOL ++0xd944d8f9 ktime_get_boottime vmlinux EXPORT_SYMBOL_GPL ++0x15892417 async_synchronize_cookie vmlinux EXPORT_SYMBOL_GPL ++0x04f58c37 inet_add_protocol vmlinux EXPORT_SYMBOL ++0xd48581cf n_tty_ioctl_helper vmlinux EXPORT_SYMBOL ++0x763793e1 nlmsvc_ops vmlinux EXPORT_SYMBOL_GPL ++0xe01bf95f sync_blockdev vmlinux EXPORT_SYMBOL ++0x4cae72a5 nobh_write_end vmlinux EXPORT_SYMBOL ++0xb753bcc8 __ashrdi3 vmlinux EXPORT_SYMBOL ++0xbd9e5d49 __lshrdi3 vmlinux EXPORT_SYMBOL ++0x6e720ff2 rtnl_unlock vmlinux EXPORT_SYMBOL ++0xfad6aff2 sock_rfree vmlinux EXPORT_SYMBOL ++0x4c4d5c41 kernel_recvmsg vmlinux EXPORT_SYMBOL ++0x9336642f sdhci_alloc_host vmlinux EXPORT_SYMBOL_GPL ++0x809ed043 __root_device_register vmlinux EXPORT_SYMBOL_GPL ++0xc0a3d105 find_next_bit vmlinux EXPORT_SYMBOL ++0x7c43ef3e disk_part_iter_init vmlinux EXPORT_SYMBOL_GPL ++0x2e3f5691 freeze_bdev vmlinux EXPORT_SYMBOL ++0x5bff2a2d srcu_batches_completed vmlinux EXPORT_SYMBOL_GPL ++0x515e24a7 flush_instruction_cache vmlinux EXPORT_SYMBOL ++0x6e44d7eb ip_xfrm_me_harder vmlinux EXPORT_SYMBOL ++0xd7f36357 __netdev_printk vmlinux EXPORT_SYMBOL ++0xc1085178 skb_kill_datagram vmlinux EXPORT_SYMBOL ++0x6d139e79 kfree_skb vmlinux EXPORT_SYMBOL ++0x0d385349 kernel_kobj vmlinux EXPORT_SYMBOL_GPL ++0x0d5b063c atomic_notifier_chain_register vmlinux EXPORT_SYMBOL_GPL ++0x7ce0ae7c param_get_long vmlinux EXPORT_SYMBOL ++0x96cbb2f4 inet_twsk_schedule vmlinux EXPORT_SYMBOL_GPL ++0x79387c50 pci_msi_off vmlinux EXPORT_SYMBOL_GPL ++0x31634792 nfnetlink_parse_nat_setup_hook net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xcc645e42 svc_set_num_threads vmlinux EXPORT_SYMBOL_GPL ++0x11ba3f13 skb_copy_datagram_iovec vmlinux EXPORT_SYMBOL ++0xf674ecb9 __kfree_skb vmlinux EXPORT_SYMBOL ++0x476b6a01 get_mtd_device_nm vmlinux EXPORT_SYMBOL_GPL ++0x55ceb682 pci_find_parent_resource vmlinux EXPORT_SYMBOL ++0x6d69fa17 ip_defrag vmlinux EXPORT_SYMBOL ++0x65b9b8a1 register_qdisc vmlinux EXPORT_SYMBOL ++0x6eab6815 mmc_interrupt_hpi vmlinux EXPORT_SYMBOL ++0x82feec40 mmc_can_discard vmlinux EXPORT_SYMBOL ++0x0d9a9ca3 scsi_flush_work vmlinux EXPORT_SYMBOL_GPL ++0x5b323547 sysdev_show_int vmlinux EXPORT_SYMBOL_GPL ++0x11cf27a9 idr_destroy vmlinux EXPORT_SYMBOL ++0xb857da73 ida_destroy vmlinux EXPORT_SYMBOL ++0x58bd4122 generic_file_aio_read vmlinux EXPORT_SYMBOL ++0x4596db6a sys_sigreturn vmlinux EXPORT_SYMBOL ++0xa9571d6d DMA_MODE_WRITE vmlinux EXPORT_SYMBOL ++0x80c07906 arpt_alloc_initial_table net/ipv4/netfilter/arp_tables EXPORT_SYMBOL_GPL ++0x5013cc99 xprt_wait_for_buffer_space vmlinux EXPORT_SYMBOL_GPL ++0x4379a238 free_netdev vmlinux EXPORT_SYMBOL ++0xc9ec4e21 free_percpu vmlinux EXPORT_SYMBOL_GPL ++0x966ae342 qe_issue_cmd vmlinux EXPORT_SYMBOL ++0x191af13e gss_mech_get_by_pseudoflavor vmlinux EXPORT_SYMBOL_GPL ++0x2764067e sk_setup_caps vmlinux EXPORT_SYMBOL_GPL ++0x6696da6c spi_sync_locked vmlinux EXPORT_SYMBOL_GPL ++0x2e89318f scsi_host_get vmlinux EXPORT_SYMBOL ++0x668da8d5 zlib_inflateIncomp vmlinux EXPORT_SYMBOL ++0xbcffe639 idr_pre_get vmlinux EXPORT_SYMBOL ++0x4430c75c ida_pre_get vmlinux EXPORT_SYMBOL ++0x28d664ff __raw_notifier_call_chain vmlinux EXPORT_SYMBOL_GPL ++0x4d3c153f sigprocmask vmlinux EXPORT_SYMBOL ++0xbafed486 sk_stream_wait_connect vmlinux EXPORT_SYMBOL ++0x2d3dc22e mtd_concat_destroy vmlinux EXPORT_SYMBOL ++0x4a3551ae do_mmap_pgoff vmlinux EXPORT_SYMBOL ++0x8d551bef sysctl_tcp_rmem vmlinux EXPORT_SYMBOL ++0x28053699 sock_no_sendmsg vmlinux EXPORT_SYMBOL ++0x11dee08f i2c_master_recv vmlinux EXPORT_SYMBOL ++0x8239ab90 vfs_unlink vmlinux EXPORT_SYMBOL ++0x7d83ac1c key_revoke vmlinux EXPORT_SYMBOL ++0x4e560ec4 pipe_unlock vmlinux EXPORT_SYMBOL ++0x9f0020c3 xprt_reserve_xprt_cong vmlinux EXPORT_SYMBOL_GPL ++0x777919af genlmsg_multicast_allns vmlinux EXPORT_SYMBOL ++0xd0a074bc bus_rescan_devices vmlinux EXPORT_SYMBOL_GPL ++0x1676e2aa put_tty_driver vmlinux EXPORT_SYMBOL ++0x1655bb05 queue_work_on vmlinux EXPORT_SYMBOL_GPL ++0x59d8223a ioport_resource vmlinux EXPORT_SYMBOL ++0xc7a4fbed rtnl_lock vmlinux EXPORT_SYMBOL ++0x73dc60ee debugfs_create_bool vmlinux EXPORT_SYMBOL_GPL ++0x490c6774 generic_file_splice_read vmlinux EXPORT_SYMBOL ++0xdd2efc0f ring_buffer_reset_cpu vmlinux EXPORT_SYMBOL_GPL ++0x1e10f34d prepare_kernel_cred vmlinux EXPORT_SYMBOL ++0x897473df mktime vmlinux EXPORT_SYMBOL ++0x582a4747 cacheable_memcpy vmlinux EXPORT_SYMBOL ++0x2288378f system_state vmlinux EXPORT_SYMBOL ++0xbe28b63a xfrm6_tunnel_alloc_spi net/ipv6/xfrm6_tunnel EXPORT_SYMBOL ++0x55e7d3c6 llc_add_pack vmlinux EXPORT_SYMBOL ++0x725c25a5 hidinput_connect vmlinux EXPORT_SYMBOL_GPL ++0x906e4ad5 splice_from_pipe_next vmlinux EXPORT_SYMBOL ++0xc3fe87c8 param_ops_uint vmlinux EXPORT_SYMBOL ++0x6f0036d9 del_timer_sync vmlinux EXPORT_SYMBOL ++0xd3187da4 pcibios_align_resource vmlinux EXPORT_SYMBOL ++0x00e8097b csum_partial_copy_fromiovecend vmlinux EXPORT_SYMBOL ++0xda7c407f pci_device_from_OF_node vmlinux EXPORT_SYMBOL ++0xb7ac4d23 __qdisc_calculate_pkt_len vmlinux EXPORT_SYMBOL ++0x0aef6a87 dev_get_by_index vmlinux EXPORT_SYMBOL ++0x8136020d mtd_do_chip_probe vmlinux EXPORT_SYMBOL ++0x75d1b1a3 pci_enable_ido vmlinux EXPORT_SYMBOL ++0x462a2e75 match_strlcpy vmlinux EXPORT_SYMBOL ++0x9eaa0939 ioctl_by_bdev vmlinux EXPORT_SYMBOL ++0x680b7306 init_net vmlinux EXPORT_SYMBOL ++0x43db0e97 mmc_power_restore_host vmlinux EXPORT_SYMBOL ++0x56dbc713 textsearch_find_continuous vmlinux EXPORT_SYMBOL ++0xf0c9ee0d __next_cpu vmlinux EXPORT_SYMBOL ++0x8741e2bf crypto_larval_lookup vmlinux EXPORT_SYMBOL_GPL ++0x6b0bc2b4 __crypto_alloc_tfm vmlinux EXPORT_SYMBOL_GPL ++0xf520946d key_unlink vmlinux EXPORT_SYMBOL ++0xc746051c keyring_search vmlinux EXPORT_SYMBOL ++0xd820c283 eventfd_ctx_remove_wait_queue vmlinux EXPORT_SYMBOL_GPL ++0x4d89bb43 generic_delete_inode vmlinux EXPORT_SYMBOL ++0xb5f17edf perf_register_guest_info_callbacks vmlinux EXPORT_SYMBOL_GPL ++0xb99f2613 nf_nat_pptp_hook_expectfn net/netfilter/nf_conntrack_pptp EXPORT_SYMBOL_GPL ++0x51fa9bbe mmc_wait_for_req vmlinux EXPORT_SYMBOL ++0xd5b037e1 kref_put vmlinux EXPORT_SYMBOL ++0xcf8bcc49 blk_run_queue vmlinux EXPORT_SYMBOL ++0xf1814894 __secpath_destroy vmlinux EXPORT_SYMBOL ++0x5ab518a3 i2c_smbus_write_i2c_block_data vmlinux EXPORT_SYMBOL ++0xaf64ad0d zlib_deflate vmlinux EXPORT_SYMBOL ++0x24fdac79 wake_bit_function vmlinux EXPORT_SYMBOL ++0xe55658d4 inet_csk_route_req vmlinux EXPORT_SYMBOL_GPL ++0xb6a61a86 qdisc_get_rtab vmlinux EXPORT_SYMBOL ++0x87b6bcc7 hid_set_field vmlinux EXPORT_SYMBOL_GPL ++0xb8d10b39 bus_remove_file vmlinux EXPORT_SYMBOL_GPL ++0x91b9e2f2 locks_release_private vmlinux EXPORT_SYMBOL_GPL ++0x06bbb24a mempool_resize vmlinux EXPORT_SYMBOL ++0x739f99ed xfrm_unregister_km vmlinux EXPORT_SYMBOL ++0xee4d52d7 in_dev_finish_destroy vmlinux EXPORT_SYMBOL ++0xadd26e5f of_find_node_by_phandle vmlinux EXPORT_SYMBOL ++0xe01c7326 hid_destroy_device vmlinux EXPORT_SYMBOL_GPL ++0xe094ef39 sg_next vmlinux EXPORT_SYMBOL ++0xe16a87dd bio_map_user vmlinux EXPORT_SYMBOL ++0x0b07abe2 unshare_fs_struct vmlinux EXPORT_SYMBOL_GPL ++0x3a746f01 smp_call_function_any vmlinux EXPORT_SYMBOL_GPL ++0x3534e2a3 system_nrt_wq vmlinux EXPORT_SYMBOL_GPL ++0xd0fb7cd4 __tasklet_hi_schedule_first vmlinux EXPORT_SYMBOL ++0x3913cd81 __nf_conntrack_confirm net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xce24147c mdiobus_scan vmlinux EXPORT_SYMBOL ++0xe4633d09 dmam_alloc_coherent vmlinux EXPORT_SYMBOL ++0xab3a9f77 tty_port_carrier_raised vmlinux EXPORT_SYMBOL ++0x58811a0b __brelse vmlinux EXPORT_SYMBOL ++0xe68e5b43 pipe_lock vmlinux EXPORT_SYMBOL ++0x7de53067 rpc_init_rtt vmlinux EXPORT_SYMBOL_GPL ++0xe05b0141 scsi_device_set_state vmlinux EXPORT_SYMBOL ++0x347fd4b3 eventfd_ctx_get vmlinux EXPORT_SYMBOL_GPL ++0x941f2aaa eventfd_ctx_put vmlinux EXPORT_SYMBOL_GPL ++0xd0d75837 mark_buffer_async_write vmlinux EXPORT_SYMBOL ++0x46d12956 wait_for_completion_interruptible_timeout vmlinux EXPORT_SYMBOL ++0x28e23139 xfrm_probe_algs vmlinux EXPORT_SYMBOL_GPL ++0xf16deeae ip_route_me_harder vmlinux EXPORT_SYMBOL ++0xb0463cdc inet_sock_destruct vmlinux EXPORT_SYMBOL ++0xab462791 nf_reinject vmlinux EXPORT_SYMBOL ++0x27ccd3d0 mmc_add_host vmlinux EXPORT_SYMBOL ++0xd4664535 tty_chars_in_buffer vmlinux EXPORT_SYMBOL ++0x3a9b6fb9 blk_unregister_region vmlinux EXPORT_SYMBOL ++0xb72e0ba9 unregister_nls vmlinux EXPORT_SYMBOL ++0x5358fc36 ring_buffer_discard_commit vmlinux EXPORT_SYMBOL_GPL ++0x2b607170 ktime_sub_ns vmlinux EXPORT_SYMBOL_GPL ++0xc17515d7 usb_hcds_loaded vmlinux EXPORT_SYMBOL_GPL ++0x97e692df skb_pull_rcsum vmlinux EXPORT_SYMBOL_GPL ++0x93055e19 __scsi_device_lookup_by_target vmlinux EXPORT_SYMBOL ++0x01902adf netpoll_trap vmlinux EXPORT_SYMBOL ++0x1a53c006 ethtool_invalid_flags vmlinux EXPORT_SYMBOL ++0xebdbe48c radix_tree_gang_lookup vmlinux EXPORT_SYMBOL ++0x07191aeb register_nls vmlinux EXPORT_SYMBOL ++0x9445cf38 locks_alloc_lock vmlinux EXPORT_SYMBOL_GPL ++0x6585e310 alloc_pages_exact_nid vmlinux EXPORT_SYMBOL ++0x1627ed72 register_dcbevent_notifier vmlinux EXPORT_SYMBOL ++0x62bc31e3 svc_prepare_thread vmlinux EXPORT_SYMBOL_GPL ++0x3dee3f15 xfrm_state_lookup vmlinux EXPORT_SYMBOL ++0x6c1c469c tcp_parse_options vmlinux EXPORT_SYMBOL ++0xd5e04f9e rps_may_expire_flow vmlinux EXPORT_SYMBOL ++0x2c1aaab6 of_gpio_simple_xlate vmlinux EXPORT_SYMBOL ++0xf52be163 i2c_smbus_write_block_data vmlinux EXPORT_SYMBOL ++0x71b46d5a svc_gss_principal vmlinux EXPORT_SYMBOL_GPL ++0x6013246a rpc_unlink vmlinux EXPORT_SYMBOL_GPL ++0x6f959b35 locks_in_grace vmlinux EXPORT_SYMBOL_GPL ++0x2749fd92 module_refcount vmlinux EXPORT_SYMBOL ++0xb1ac2e02 inet_ctl_sock_create vmlinux EXPORT_SYMBOL_GPL ++0xdee5a777 dev_addr_add_multiple vmlinux EXPORT_SYMBOL ++0x2f2c9199 firmware_kobj vmlinux EXPORT_SYMBOL_GPL ++0x91696a6a pci_store_saved_state vmlinux EXPORT_SYMBOL_GPL ++0x009653bb usb_lock_device_for_reset vmlinux EXPORT_SYMBOL_GPL ++0xb95e4ac4 mdiobus_alloc vmlinux EXPORT_SYMBOL ++0x31da061a get_qe_base vmlinux EXPORT_SYMBOL ++0xa3e75545 flush_tlb_kernel_range vmlinux EXPORT_SYMBOL ++0x371d2130 check_legacy_ioport vmlinux EXPORT_SYMBOL ++0xbc8b4faf genl_register_mc_group vmlinux EXPORT_SYMBOL ++0xb7ac5dda ___pskb_trim vmlinux EXPORT_SYMBOL ++0xbaa1069f tty_driver_flush_buffer vmlinux EXPORT_SYMBOL ++0x328b8594 pci_setup_cardbus vmlinux EXPORT_SYMBOL ++0x85df9b6c strsep vmlinux EXPORT_SYMBOL ++0x788fe103 iomem_resource vmlinux EXPORT_SYMBOL ++0xe2d5255a strcmp vmlinux EXPORT_SYMBOL ++0xea07d51b usb_serial_register vmlinux EXPORT_SYMBOL_GPL ++0x355bc233 devm_kfree vmlinux EXPORT_SYMBOL_GPL ++0x051fbdb5 mnt_unpin vmlinux EXPORT_SYMBOL ++0x94da4dd0 end_writeback vmlinux EXPORT_SYMBOL ++0x0e08028c vfs_create vmlinux EXPORT_SYMBOL ++0x2e5fb132 mtd_erase_callback vmlinux EXPORT_SYMBOL_GPL ++0x4b72a3d8 __ablkcipher_walk_complete vmlinux EXPORT_SYMBOL_GPL ++0x750794d1 sb_min_blocksize vmlinux EXPORT_SYMBOL ++0x59d696b6 register_module_notifier vmlinux EXPORT_SYMBOL ++0xf3d30d7b setup_deferrable_timer_on_stack_key vmlinux EXPORT_SYMBOL_GPL ++0xc7208c3a serial8250_resume_port vmlinux EXPORT_SYMBOL ++0xc490d869 hid_input_report vmlinux EXPORT_SYMBOL_GPL ++0xced3e4fb pcix_set_mmrbc vmlinux EXPORT_SYMBOL ++0xaf91d89f __kernel_param_lock vmlinux EXPORT_SYMBOL ++0xadd63611 unregister_sysctl_table vmlinux EXPORT_SYMBOL ++0xd9e09e0c of_find_property vmlinux EXPORT_SYMBOL ++0xb7bd1f4f del_gendisk vmlinux EXPORT_SYMBOL ++0x54d4dba9 block_write_full_page vmlinux EXPORT_SYMBOL ++0x70e009d6 machine_id vmlinux EXPORT_SYMBOL ++0x2af8b550 nf_ct_invert_tuple net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xcc75ede8 xfrm_register_type vmlinux EXPORT_SYMBOL ++0xf6933c48 lockd_up vmlinux EXPORT_SYMBOL_GPL ++0x58652a56 fat_sync_inode vmlinux EXPORT_SYMBOL_GPL ++0xe36816d8 put_mnt_ns vmlinux EXPORT_SYMBOL ++0xe16e2b9f clear_bdi_congested vmlinux EXPORT_SYMBOL ++0x1239f785 ____pagevec_lru_add vmlinux EXPORT_SYMBOL ++0x8df5da63 memstart_addr vmlinux EXPORT_SYMBOL ++0xd1cd3585 sock_no_setsockopt vmlinux EXPORT_SYMBOL ++0x13435bdb sock_no_getsockopt vmlinux EXPORT_SYMBOL ++0x6f0843c1 __blockdev_direct_IO vmlinux EXPORT_SYMBOL ++0x1336c951 splice_from_pipe_end vmlinux EXPORT_SYMBOL ++0x2261d711 migrate_page vmlinux EXPORT_SYMBOL ++0x2e45e488 rcu_note_context_switch vmlinux EXPORT_SYMBOL_GPL ++0x4ae11ab9 ip6_route_me_harder vmlinux EXPORT_SYMBOL ++0x05bfdc15 thermal_zone_device_update vmlinux EXPORT_SYMBOL ++0xe165d0ce nfs_commit_release_pages vmlinux EXPORT_SYMBOL_GPL ++0x10d4e73e nf_nat_proto_range_to_nlattr net/ipv4/netfilter/nf_nat EXPORT_SYMBOL_GPL ++0xee7d731d km_new_mapping vmlinux EXPORT_SYMBOL ++0x408bf35b napi_complete vmlinux EXPORT_SYMBOL ++0xa155dccc of_property_count_strings vmlinux EXPORT_SYMBOL_GPL ++0x96d1f2a7 mmc_assume_removable vmlinux EXPORT_SYMBOL ++0x47229b5c gpio_request vmlinux EXPORT_SYMBOL_GPL ++0x3d0b6923 swiotlb_sync_single_for_cpu vmlinux EXPORT_SYMBOL ++0x7f968718 generic_block_bmap vmlinux EXPORT_SYMBOL ++0x868784cb __symbol_get vmlinux EXPORT_SYMBOL_GPL ++0x36dc730d __ip_dev_find vmlinux EXPORT_SYMBOL ++0xbe0e5118 nla_memcmp vmlinux EXPORT_SYMBOL ++0xf1db1704 nla_memcpy vmlinux EXPORT_SYMBOL ++0x8348bb59 nfs_put_client vmlinux EXPORT_SYMBOL_GPL ++0xbca1e919 d_materialise_unique vmlinux EXPORT_SYMBOL_GPL ++0xf229af8b kmem_cache_free vmlinux EXPORT_SYMBOL ++0x617a2e8b file_remove_suid vmlinux EXPORT_SYMBOL ++0x13b77367 get_cpu_device vmlinux EXPORT_SYMBOL_GPL ++0x4ebf144b swiotlb_bounce vmlinux EXPORT_SYMBOL_GPL ++0x5edd0762 bin2bcd vmlinux EXPORT_SYMBOL ++0x2e9c1dbc lookup_hash vmlinux EXPORT_SYMBOL_GPL ++0xaf2d872c prepare_to_wait vmlinux EXPORT_SYMBOL ++0xadf42bd5 __request_region vmlinux EXPORT_SYMBOL ++0xf71521ba atomic64_add_return vmlinux EXPORT_SYMBOL ++0x5027f8ae bdev_read_only vmlinux EXPORT_SYMBOL ++0xf0009fee put_pages_list vmlinux EXPORT_SYMBOL ++0x3d043ff4 sock_wfree vmlinux EXPORT_SYMBOL ++0x2b318955 test_set_page_writeback vmlinux EXPORT_SYMBOL ++0xa3abc422 abort_exclusive_wait vmlinux EXPORT_SYMBOL ++0x091eb9b4 round_jiffies vmlinux EXPORT_SYMBOL_GPL ++0x86e66c33 gss_mech_get_by_OID vmlinux EXPORT_SYMBOL_GPL ++0xc705dfbd qdisc_destroy vmlinux EXPORT_SYMBOL ++0x5594be03 bitmap_remap vmlinux EXPORT_SYMBOL ++0x23ef48a6 truncate_inode_pages vmlinux EXPORT_SYMBOL ++0x0422fe4a inet_csk_timer_bug_msg vmlinux EXPORT_SYMBOL ++0x58fea811 input_flush_device vmlinux EXPORT_SYMBOL ++0x3b2b6b53 sysfs_notify vmlinux EXPORT_SYMBOL_GPL ++0x0948cde9 num_physpages vmlinux EXPORT_SYMBOL ++0x06295425 inet_hash vmlinux EXPORT_SYMBOL_GPL ++0x9a1dfd65 strpbrk vmlinux EXPORT_SYMBOL ++0x8734a5cd sysfs_create_file vmlinux EXPORT_SYMBOL_GPL ++0xf6a14396 seq_lseek vmlinux EXPORT_SYMBOL ++0xfb596d67 ip6_frag_match vmlinux EXPORT_SYMBOL ++0xa9647a71 sdhci_add_host vmlinux EXPORT_SYMBOL_GPL ++0xb53620d1 pci_vpd_find_info_keyword vmlinux EXPORT_SYMBOL_GPL ++0x1551dc51 bitmap_find_free_region vmlinux EXPORT_SYMBOL ++0x71fa908a cache_flush vmlinux EXPORT_SYMBOL_GPL ++0xd582227a leds_list_lock vmlinux EXPORT_SYMBOL_GPL ++0xe32cbdf9 set_disk_ro vmlinux EXPORT_SYMBOL ++0xfc765c13 journal_invalidatepage vmlinux EXPORT_SYMBOL ++0x4a541e7f bus_find_device vmlinux EXPORT_SYMBOL_GPL ++0xfb814465 blk_rq_unprep_clone vmlinux EXPORT_SYMBOL_GPL ++0xbb7929e0 relay_switch_subbuf vmlinux EXPORT_SYMBOL_GPL ++0xa7a37016 rpc_create vmlinux EXPORT_SYMBOL_GPL ++0x32d5e7fc xfrm_aalg_get_byid vmlinux EXPORT_SYMBOL_GPL ++0x50661a88 tcp_create_openreq_child vmlinux EXPORT_SYMBOL ++0xbe39e738 sk_common_release vmlinux EXPORT_SYMBOL ++0x096bfc06 skb_queue_head vmlinux EXPORT_SYMBOL ++0x03cfa4a0 skb_prepare_seq_read vmlinux EXPORT_SYMBOL ++0x0ecca40e sk_reset_timer vmlinux EXPORT_SYMBOL ++0x90c7fdae irq_get_irq_data vmlinux EXPORT_SYMBOL_GPL ++0x4dfed71c flex_array_get_ptr vmlinux EXPORT_SYMBOL ++0x98ed958c bio_alloc_bioset vmlinux EXPORT_SYMBOL ++0x281bf2dd usb_driver_set_configuration vmlinux EXPORT_SYMBOL_GPL ++0xb5c52e5f mii_ethtool_sset vmlinux EXPORT_SYMBOL ++0x267fd50e mii_ethtool_gset vmlinux EXPORT_SYMBOL ++0x3171d976 class_compat_create_link vmlinux EXPORT_SYMBOL_GPL ++0xfee5e630 vfs_cancel_lock vmlinux EXPORT_SYMBOL_GPL ++0xb602c57e nf_ct_l3proto_module_put net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x3f68a347 release_sock vmlinux EXPORT_SYMBOL ++0xd2d51180 of_gpio_count vmlinux EXPORT_SYMBOL ++0x50e7193a __i2c_first_dynamic_bus_num vmlinux EXPORT_SYMBOL_GPL ++0xcf062b87 class_remove_file vmlinux EXPORT_SYMBOL_GPL ++0xefdcf0e8 textsearch_destroy vmlinux EXPORT_SYMBOL ++0x4610c824 of_phy_connect_fixed_link vmlinux EXPORT_SYMBOL ++0xd71d1167 unmap_underlying_metadata vmlinux EXPORT_SYMBOL ++0x7cd5feb0 sync_inode vmlinux EXPORT_SYMBOL ++0xb859f38b krealloc vmlinux EXPORT_SYMBOL ++0x46ece9e7 input_register_device vmlinux EXPORT_SYMBOL ++0x50e787f3 __invalidate_device vmlinux EXPORT_SYMBOL ++0x2ba707a8 sysctl_tcp_low_latency vmlinux EXPORT_SYMBOL ++0x1163f0a7 blk_max_low_pfn vmlinux EXPORT_SYMBOL ++0x06fd5926 blk_queue_free_tags vmlinux EXPORT_SYMBOL ++0x3cca63a0 elv_unregister_queue vmlinux EXPORT_SYMBOL ++0x67b78eb3 seq_hlist_next_rcu vmlinux EXPORT_SYMBOL ++0x5a9effe0 register_sysctl_table vmlinux EXPORT_SYMBOL ++0x7c9291d1 csum_partial_copy_generic vmlinux EXPORT_SYMBOL ++0xb9a1c8b8 tty_flip_buffer_push vmlinux EXPORT_SYMBOL ++0x929d7ef0 uart_get_divisor vmlinux EXPORT_SYMBOL ++0x425c1c0b ktime_add_safe vmlinux EXPORT_SYMBOL_GPL ++0xf9a482f9 msleep vmlinux EXPORT_SYMBOL ++0x2786a8a5 unregister_netdev vmlinux EXPORT_SYMBOL ++0xdaecbaf2 proc_net_mkdir vmlinux EXPORT_SYMBOL_GPL ++0x832ad813 __bforget vmlinux EXPORT_SYMBOL ++0xcd1dafbc __audit_inode_child vmlinux EXPORT_SYMBOL_GPL ++0xaeffe8a2 xdr_reserve_space vmlinux EXPORT_SYMBOL_GPL ++0xee4de802 inet6_add_protocol vmlinux EXPORT_SYMBOL ++0xb0240e99 raw_unhash_sk vmlinux EXPORT_SYMBOL_GPL ++0xb5be6114 xt_register_table vmlinux EXPORT_SYMBOL_GPL ++0x9e43ccf6 sock_no_listen vmlinux EXPORT_SYMBOL ++0x19990104 input_mt_destroy_slots vmlinux EXPORT_SYMBOL ++0x882fd7db usb_serial_generic_unthrottle vmlinux EXPORT_SYMBOL_GPL ++0x39d7bb0a usb_unpoison_anchored_urbs vmlinux EXPORT_SYMBOL_GPL ++0x3ab69e8f scsi_device_lookup_by_target vmlinux EXPORT_SYMBOL ++0x79aa04a2 get_random_bytes vmlinux EXPORT_SYMBOL ++0xf0efa6e0 rpcauth_unregister vmlinux EXPORT_SYMBOL_GPL ++0x67e38cdf sdhci_get_of_property vmlinux EXPORT_SYMBOL_GPL ++0x3c9390db pci_vpd_find_tag vmlinux EXPORT_SYMBOL_GPL ++0xd38480a0 rb_augment_erase_end vmlinux EXPORT_SYMBOL ++0xa474d088 blk_peek_request vmlinux EXPORT_SYMBOL ++0x5cba6ab9 sock_no_poll vmlinux EXPORT_SYMBOL ++0x2c36d879 sdio_unregister_driver vmlinux EXPORT_SYMBOL_GPL ++0x055c8258 usb_serial_generic_close vmlinux EXPORT_SYMBOL_GPL ++0x8896e0d3 blk_rq_prep_clone vmlinux EXPORT_SYMBOL_GPL ++0xc55a9a33 crypto_alloc_shash vmlinux EXPORT_SYMBOL_GPL ++0xc79bf957 crypto_alloc_ahash vmlinux EXPORT_SYMBOL_GPL ++0x89cafb57 vlan_ioctl_set vmlinux EXPORT_SYMBOL ++0xb75534fa of_alias_get_id vmlinux EXPORT_SYMBOL_GPL ++0xc11d8093 iov_shorten vmlinux EXPORT_SYMBOL ++0x6a037cf1 mempool_kfree vmlinux EXPORT_SYMBOL ++0xcf29542b scsi_scan_target vmlinux EXPORT_SYMBOL ++0xfda88943 subsys_dev_iter_init vmlinux EXPORT_SYMBOL_GPL ++0x27715359 subsys_dev_iter_exit vmlinux EXPORT_SYMBOL_GPL ++0xf0ef15b4 list_sort vmlinux EXPORT_SYMBOL ++0x71d0143a remove_arg_zero vmlinux EXPORT_SYMBOL ++0x328c1012 remap_pfn_range vmlinux EXPORT_SYMBOL ++0x52760ca9 getnstimeofday vmlinux EXPORT_SYMBOL ++0xd1cc986f phy_register_fixup vmlinux EXPORT_SYMBOL ++0xf55a56b6 device_bind_driver vmlinux EXPORT_SYMBOL_GPL ++0x0b137c47 device_store_ulong vmlinux EXPORT_SYMBOL_GPL ++0xe5c97713 pci_vpd_truncate vmlinux EXPORT_SYMBOL ++0x294da23e skcipher_geniv_exit vmlinux EXPORT_SYMBOL_GPL ++0x11eaefc3 file_update_time vmlinux EXPORT_SYMBOL ++0x529c370a bdi_unregister vmlinux EXPORT_SYMBOL ++0xae946285 inet6_csk_search_req vmlinux EXPORT_SYMBOL_GPL ++0x04dfc4d6 dev_mc_init vmlinux EXPORT_SYMBOL ++0x88c994d7 dev_uc_init vmlinux EXPORT_SYMBOL ++0x865029ac __hw_addr_sync vmlinux EXPORT_SYMBOL ++0x5f46d244 of_irq_map_raw vmlinux EXPORT_SYMBOL_GPL ++0x0e516b0a scsi_setup_blk_pc_cmnd vmlinux EXPORT_SYMBOL ++0x11a13e31 _kstrtol vmlinux EXPORT_SYMBOL ++0xc72d33bf mb_cache_entry_alloc vmlinux EXPORT_SYMBOL ++0x0d8d877a relay_file_operations vmlinux EXPORT_SYMBOL_GPL ++0x132a7a5b init_timer_key vmlinux EXPORT_SYMBOL ++0xa473aea0 rpc_wake_up_status vmlinux EXPORT_SYMBOL_GPL ++0xf39bf4d9 put_cmsg vmlinux EXPORT_SYMBOL ++0xe5dd0af1 skb_free_datagram vmlinux EXPORT_SYMBOL ++0x14d5945d of_fdt_unflatten_tree vmlinux EXPORT_SYMBOL_GPL ++0xe8790d79 pci_wake_from_d3 vmlinux EXPORT_SYMBOL ++0x0e23fb6a filp_close vmlinux EXPORT_SYMBOL ++0xb9b1637c truncate_setsize vmlinux EXPORT_SYMBOL ++0x44bcfa6d system_nrt_freezable_wq vmlinux EXPORT_SYMBOL_GPL ++0x39cdf63c wait_for_completion_interruptible vmlinux EXPORT_SYMBOL ++0x86333584 svcauth_gss_flavor vmlinux EXPORT_SYMBOL_GPL ++0x8d1a827e svcauth_gss_register_pseudoflavor vmlinux EXPORT_SYMBOL_GPL ++0x38fb9933 tty_std_termios vmlinux EXPORT_SYMBOL ++0x38320348 generic_readlink vmlinux EXPORT_SYMBOL ++0xe2e0c7c6 __flush_icache_range vmlinux EXPORT_SYMBOL ++0x33b2d26d ether_setup vmlinux EXPORT_SYMBOL ++0xd200c6d4 usb_deregister_device_driver vmlinux EXPORT_SYMBOL_GPL ++0x889b7ccd device_create_file vmlinux EXPORT_SYMBOL_GPL ++0x610d2493 __break_lease vmlinux EXPORT_SYMBOL ++0x5330e4ea get_task_comm vmlinux EXPORT_SYMBOL_GPL ++0xba464a1d __get_vm_area vmlinux EXPORT_SYMBOL_GPL ++0x7a1390f7 param_set_bool vmlinux EXPORT_SYMBOL ++0x034f9e73 param_ops_byte vmlinux EXPORT_SYMBOL ++0xc88f3891 xprt_free vmlinux EXPORT_SYMBOL_GPL ++0x8ab4079e atomic64_add vmlinux EXPORT_SYMBOL ++0xc5f46566 rb_augment_insert vmlinux EXPORT_SYMBOL ++0xb0520bf3 would_dump vmlinux EXPORT_SYMBOL ++0x4a20d82f truncate_inode_pages_range vmlinux EXPORT_SYMBOL ++0x0f62d3b5 force_sig vmlinux EXPORT_SYMBOL ++0xd0417995 pci_set_dma_max_seg_size vmlinux EXPORT_SYMBOL ++0x05240ee7 percpu_counter_batch vmlinux EXPORT_SYMBOL ++0xe3646dbc d_path vmlinux EXPORT_SYMBOL ++0x116ccd8c vfs_fstatat vmlinux EXPORT_SYMBOL ++0x2228a27e sdev_evt_send vmlinux EXPORT_SYMBOL_GPL ++0x175adc1b igrab vmlinux EXPORT_SYMBOL ++0x9d95a606 rtnl_notify vmlinux EXPORT_SYMBOL ++0xc0e1c9dd __rtnl_link_register vmlinux EXPORT_SYMBOL_GPL ++0xf1c8f28f sock_recvmsg vmlinux EXPORT_SYMBOL ++0xcb649c67 mmc_can_secure_erase_trim vmlinux EXPORT_SYMBOL ++0x83ba622a usb_hcd_unmap_urb_for_dma vmlinux EXPORT_SYMBOL_GPL ++0x5bf0f5f6 pci_back_from_sleep vmlinux EXPORT_SYMBOL ++0x0c62cfe7 blk_end_request_err vmlinux EXPORT_SYMBOL_GPL ++0x59d1c938 blk_end_request_all vmlinux EXPORT_SYMBOL ++0x9dba46f5 blk_queue_bio vmlinux EXPORT_SYMBOL_GPL ++0xd16712f3 crypto_check_attr_type vmlinux EXPORT_SYMBOL_GPL ++0x6a80a3f5 cpm_muram_free vmlinux EXPORT_SYMBOL ++0x8c0279d5 nf_ct_l3protos net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x8b63beee linkwatch_fire_event vmlinux EXPORT_SYMBOL ++0xd3505d0c ndisc_build_skb vmlinux EXPORT_SYMBOL ++0x1598dc9d unregister_netevent_notifier vmlinux EXPORT_SYMBOL_GPL ++0xb2dc7101 input_mt_report_slot_state vmlinux EXPORT_SYMBOL ++0xcf0c65bc scsi_init_io vmlinux EXPORT_SYMBOL ++0x8307be63 rpc_queue_upcall vmlinux EXPORT_SYMBOL_GPL ++0xdb484b6d sdhci_remove_host vmlinux EXPORT_SYMBOL_GPL ++0x25b7fdec fib_default_rule_pref vmlinux EXPORT_SYMBOL ++0x12b20fd2 swiotlb_sync_single_for_device vmlinux EXPORT_SYMBOL ++0x6531a053 debugfs_create_x8 vmlinux EXPORT_SYMBOL_GPL ++0x03070efa of_scan_pci_bridge vmlinux EXPORT_SYMBOL ++0x6796dc42 uart_write_wakeup vmlinux EXPORT_SYMBOL ++0xc1e35bf5 pci_bus_read_config_word vmlinux EXPORT_SYMBOL ++0x0c081027 skb_append vmlinux EXPORT_SYMBOL ++0x1aec4408 read_cache_page_gfp vmlinux EXPORT_SYMBOL ++0x9fc89fd1 schedule_delayed_work_on vmlinux EXPORT_SYMBOL ++0xe3319fe9 sk_stream_error vmlinux EXPORT_SYMBOL ++0xeef4a738 usb_stor_CB_reset vmlinux EXPORT_SYMBOL_GPL ++0x6332cc1a audit_log_start vmlinux EXPORT_SYMBOL ++0x1330b831 netdev_crit vmlinux EXPORT_SYMBOL ++0x5651005a sysfs_create_files vmlinux EXPORT_SYMBOL_GPL ++0x27f4a872 sget vmlinux EXPORT_SYMBOL ++0x5f754e5a memset vmlinux EXPORT_SYMBOL ++0x5ca89b3d mtd_kmalloc_up_to vmlinux EXPORT_SYMBOL_GPL ++0xdc3fcbc9 __sw_hweight8 vmlinux EXPORT_SYMBOL ++0x02ee26c1 free_pages_exact vmlinux EXPORT_SYMBOL ++0x95edd27e tasklet_hrtimer_init vmlinux EXPORT_SYMBOL_GPL ++0x064db9a5 mark_mounts_for_expiry vmlinux EXPORT_SYMBOL_GPL ++0xacfd81f6 work_cpu vmlinux EXPORT_SYMBOL_GPL ++0xbc316de4 tty_termios_input_baud_rate vmlinux EXPORT_SYMBOL ++0x0537dc03 d_set_d_op vmlinux EXPORT_SYMBOL ++0x2e47f677 xfrm_aalg_get_byidx vmlinux EXPORT_SYMBOL_GPL ++0x5577ef9e udp_table vmlinux EXPORT_SYMBOL ++0x70bcb245 mmc_erase_group_aligned vmlinux EXPORT_SYMBOL ++0xb24c2db9 idr_get_new_above vmlinux EXPORT_SYMBOL ++0x9704e93a ida_get_new_above vmlinux EXPORT_SYMBOL ++0x2e2f1740 ring_buffer_record_disable_cpu vmlinux EXPORT_SYMBOL_GPL ++0xa1a8f438 transport_configure_device vmlinux EXPORT_SYMBOL_GPL ++0xbd903883 nla_put vmlinux EXPORT_SYMBOL ++0x429bdb0b revalidate_disk vmlinux EXPORT_SYMBOL ++0x72e50086 vm_stat vmlinux EXPORT_SYMBOL ++0xd5b1376d register_shrinker vmlinux EXPORT_SYMBOL ++0xf23fcb99 __kfifo_in vmlinux EXPORT_SYMBOL ++0x38abcc37 get_immrbase vmlinux EXPORT_SYMBOL ++0x624a6406 hwrng_register vmlinux EXPORT_SYMBOL_GPL ++0xfa21edf6 misc_register vmlinux EXPORT_SYMBOL ++0x5d558bfa block_invalidatepage vmlinux EXPORT_SYMBOL ++0x2c793286 may_umount_tree vmlinux EXPORT_SYMBOL ++0x206687ad cpm_muram_alloc_fixed vmlinux EXPORT_SYMBOL ++0x9cedf6bd dma_direct_ops vmlinux EXPORT_SYMBOL ++0x636b12c8 nf_nat_need_gre net/ipv4/netfilter/nf_nat_proto_gre EXPORT_SYMBOL_GPL ++0x0150a066 udp_lib_get_port vmlinux EXPORT_SYMBOL ++0x7b590ac8 skb_defer_rx_timestamp vmlinux EXPORT_SYMBOL_GPL ++0x594b398f tty_ldisc_ref vmlinux EXPORT_SYMBOL_GPL ++0x68d241c1 devm_ioport_map vmlinux EXPORT_SYMBOL ++0x17ce645d locks_end_grace vmlinux EXPORT_SYMBOL_GPL ++0xc3b2d983 rtnl_af_unregister vmlinux EXPORT_SYMBOL_GPL ++0xbfee3ad5 loop_unregister_transfer vmlinux EXPORT_SYMBOL ++0x43d497ca class_dev_iter_exit vmlinux EXPORT_SYMBOL_GPL ++0x7064d556 iget_failed vmlinux EXPORT_SYMBOL ++0xc3880471 xdr_decode_netobj vmlinux EXPORT_SYMBOL_GPL ++0x25c677c4 mac_pton vmlinux EXPORT_SYMBOL ++0x99caf7d2 ethtool_op_set_tso vmlinux EXPORT_SYMBOL ++0xc94c34d0 mmc_cache_ctrl vmlinux EXPORT_SYMBOL ++0x22258364 pci_restore_state vmlinux EXPORT_SYMBOL ++0x1d16856b filemap_fdatawait_range vmlinux EXPORT_SYMBOL ++0xc9833005 skb_complete_tx_timestamp vmlinux EXPORT_SYMBOL_GPL ++0x65b82e1f usb_enable_xhci_ports vmlinux EXPORT_SYMBOL_GPL ++0xa7ddce90 inode_sub_bytes vmlinux EXPORT_SYMBOL ++0x0395d6d3 inode_set_bytes vmlinux EXPORT_SYMBOL ++0x2bd8303c svc_unreg_xprt_class vmlinux EXPORT_SYMBOL_GPL ++0xc59f0fc7 arp_xmit vmlinux EXPORT_SYMBOL ++0x9cb92c72 __dev_getfirstbyhwtype vmlinux EXPORT_SYMBOL ++0xccc53d95 __dev_get_by_index vmlinux EXPORT_SYMBOL ++0xa41a68b5 usb_serial_generic_write vmlinux EXPORT_SYMBOL_GPL ++0xabe0867d mdiobus_register vmlinux EXPORT_SYMBOL ++0xaa5fb7af pci_release_selected_regions vmlinux EXPORT_SYMBOL ++0x6c665691 flex_array_shrink vmlinux EXPORT_SYMBOL ++0xcc17504d _raw_read_unlock_irqrestore vmlinux EXPORT_SYMBOL ++0xedcf6be4 qword_add vmlinux EXPORT_SYMBOL_GPL ++0x9fc77642 __inet6_lookup_established vmlinux EXPORT_SYMBOL ++0x001b7570 skb_recycle vmlinux EXPORT_SYMBOL ++0x4b54f71e sdio_claim_host vmlinux EXPORT_SYMBOL_GPL ++0x7ca60166 __nla_put_nohdr vmlinux EXPORT_SYMBOL ++0x34d8298e bdi_init vmlinux EXPORT_SYMBOL ++0x889c066f flush_tlb_page vmlinux EXPORT_SYMBOL ++0x40973662 sysctl_udp_mem vmlinux EXPORT_SYMBOL ++0x17df17bc sysctl_tcp_ecn vmlinux EXPORT_SYMBOL ++0xa0ebd14c sysctl_tcp_mem vmlinux EXPORT_SYMBOL ++0xc94834cd ethtool_op_set_tx_csum vmlinux EXPORT_SYMBOL ++0x669a989a inet_csk_accept vmlinux EXPORT_SYMBOL ++0xc0574cac inet_hash_connect vmlinux EXPORT_SYMBOL_GPL ++0x74d6ceef generic_mii_ioctl vmlinux EXPORT_SYMBOL ++0x0334da4e scsi_command_size_tbl vmlinux EXPORT_SYMBOL ++0xb58dcfa2 synchronize_sched_expedited vmlinux EXPORT_SYMBOL_GPL ++0xa18106f8 xprt_wake_pending_tasks vmlinux EXPORT_SYMBOL_GPL ++0x35e5a105 usb_bulk_msg vmlinux EXPORT_SYMBOL_GPL ++0x1bb9d4e9 xfrm_state_delete_tunnel vmlinux EXPORT_SYMBOL ++0x03198068 platform_device_add_resources vmlinux EXPORT_SYMBOL_GPL ++0x0a5cfbc7 in6_dev_finish_destroy vmlinux EXPORT_SYMBOL ++0x909a1b12 tcp_gro_receive vmlinux EXPORT_SYMBOL ++0xa9f90244 eth_header vmlinux EXPORT_SYMBOL ++0xdacdd5df scsi_rescan_device vmlinux EXPORT_SYMBOL ++0x8f48679a rb_prev vmlinux EXPORT_SYMBOL ++0x56653400 user_match vmlinux EXPORT_SYMBOL_GPL ++0x21c5a2e1 request_key_async_with_auxdata vmlinux EXPORT_SYMBOL ++0x2a20e3db bd_unlink_disk_holder vmlinux EXPORT_SYMBOL_GPL ++0xea065e01 task_handoff_unregister vmlinux EXPORT_SYMBOL_GPL ++0xfbcac494 down_killable vmlinux EXPORT_SYMBOL ++0x83f383cb napi_gro_receive vmlinux EXPORT_SYMBOL ++0x2750609c pci_reset_function vmlinux EXPORT_SYMBOL_GPL ++0x05eb2ed0 nf_unregister_queue_handler vmlinux EXPORT_SYMBOL ++0x24eb7e32 leds_list vmlinux EXPORT_SYMBOL_GPL ++0x7b6a7955 tcp_v4_tw_get_peer vmlinux EXPORT_SYMBOL ++0x34a52594 dev_get_by_flags_rcu vmlinux EXPORT_SYMBOL ++0x7647726c handle_sysrq vmlinux EXPORT_SYMBOL ++0xea3f9431 pcie_port_bus_type vmlinux EXPORT_SYMBOL_GPL ++0x996bdb64 _kstrtoul vmlinux EXPORT_SYMBOL ++0x7f859c50 __block_write_begin vmlinux EXPORT_SYMBOL ++0x1cc6719a register_reboot_notifier vmlinux EXPORT_SYMBOL ++0xf5c9012e timespec_trunc vmlinux EXPORT_SYMBOL ++0x2b5c303b smp_send_reschedule vmlinux EXPORT_SYMBOL_GPL ++0x5e15425b tcp_sockets_allocated vmlinux EXPORT_SYMBOL ++0xcc167694 inode_owner_or_capable vmlinux EXPORT_SYMBOL ++0x079a369f generic_pipe_buf_confirm vmlinux EXPORT_SYMBOL ++0xc1eecd72 scsi_device_quiesce vmlinux EXPORT_SYMBOL ++0x9748927f _outsw_ns vmlinux EXPORT_SYMBOL ++0xfbfddf0b pci_select_bars vmlinux EXPORT_SYMBOL ++0xf184d189 kernel_power_off vmlinux EXPORT_SYMBOL_GPL ++0x84d095a1 ip6t_unregister_table net/ipv6/netfilter/ip6_tables EXPORT_SYMBOL ++0xdc3ed1f8 svc_create_pooled vmlinux EXPORT_SYMBOL_GPL ++0xcb1fe4f5 genl_register_ops vmlinux EXPORT_SYMBOL ++0x544b760f tty_ldisc_ref_wait vmlinux EXPORT_SYMBOL_GPL ++0x310a0a1b debugfs_create_u64 vmlinux EXPORT_SYMBOL_GPL ++0x9f915995 block_commit_write vmlinux EXPORT_SYMBOL ++0x87e86028 __netdev_alloc_skb vmlinux EXPORT_SYMBOL ++0xfec3c2f2 bcd2bin vmlinux EXPORT_SYMBOL ++0x5d631b05 journal_get_undo_access vmlinux EXPORT_SYMBOL ++0x1fc9cb5b perf_event_create_kernel_counter vmlinux EXPORT_SYMBOL_GPL ++0x90ff6c9f nf_ct_invert_tuplepr net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xe1a5b39b tty_kref_put vmlinux EXPORT_SYMBOL ++0x60d768c8 locks_delete_block vmlinux EXPORT_SYMBOL ++0x8eec5353 dput vmlinux EXPORT_SYMBOL ++0x1314f71a is_container_init vmlinux EXPORT_SYMBOL ++0x5bd26000 rpc_proc_unregister vmlinux EXPORT_SYMBOL_GPL ++0x66df8787 rpc_delay vmlinux EXPORT_SYMBOL_GPL ++0xbefd162c fill_inquiry_response vmlinux EXPORT_SYMBOL_GPL ++0xc4536e19 usb_match_one_id vmlinux EXPORT_SYMBOL_GPL ++0xd1e93218 srcu_notifier_call_chain vmlinux EXPORT_SYMBOL_GPL ++0xe46682b1 sk_free vmlinux EXPORT_SYMBOL ++0xcacd6472 scsi_is_sdev_device vmlinux EXPORT_SYMBOL ++0x50f5d9f6 pci_bus_max_busnr vmlinux EXPORT_SYMBOL_GPL ++0xaaa286ec kobject_init vmlinux EXPORT_SYMBOL ++0x42160169 flush_workqueue vmlinux EXPORT_SYMBOL_GPL ++0x4b7ed27b sleep_on vmlinux EXPORT_SYMBOL ++0x331ac747 key_type_user vmlinux EXPORT_SYMBOL_GPL ++0x80bd6f7b bio_flush_dcache_pages vmlinux EXPORT_SYMBOL ++0xaf4e1072 simple_lookup vmlinux EXPORT_SYMBOL ++0xec4769ef qe_clock_source vmlinux EXPORT_SYMBOL ++0xf78d04ab netlink_register_notifier vmlinux EXPORT_SYMBOL ++0xf8a70670 usb_match_id vmlinux EXPORT_SYMBOL_GPL ++0x9be8ead9 xfrm_policy_insert vmlinux EXPORT_SYMBOL ++0xf360c71e __netpoll_cleanup vmlinux EXPORT_SYMBOL_GPL ++0x1bdf3140 skb_segment vmlinux EXPORT_SYMBOL_GPL ++0x184b82fb mmc_vddrange_to_ocrmask vmlinux EXPORT_SYMBOL ++0x9d02a2b9 usb_add_hcd vmlinux EXPORT_SYMBOL_GPL ++0x88355cbb blk_queue_max_segments vmlinux EXPORT_SYMBOL ++0x3d8aa9cd unlock_rename vmlinux EXPORT_SYMBOL ++0x1983094e fsl_lbc_ctrl_dev vmlinux EXPORT_SYMBOL ++0x2406dae3 pci_address_to_pio vmlinux EXPORT_SYMBOL_GPL ++0xe771423f tcp_init_congestion_ops vmlinux EXPORT_SYMBOL_GPL ++0xa7c0801f dev_gro_receive vmlinux EXPORT_SYMBOL ++0x5732e368 skb_push vmlinux EXPORT_SYMBOL ++0xbeb96094 sdio_f0_writeb vmlinux EXPORT_SYMBOL_GPL ++0x70033701 device_create vmlinux EXPORT_SYMBOL_GPL ++0x6848d183 blk_run_queue_async vmlinux EXPORT_SYMBOL ++0x09949de0 simple_rmdir vmlinux EXPORT_SYMBOL ++0xd28b05ff alloc_file vmlinux EXPORT_SYMBOL ++0xfefb0432 free_task vmlinux EXPORT_SYMBOL ++0x4a9eefcb i2c_del_adapter vmlinux EXPORT_SYMBOL ++0x5838f6c9 rtc_valid_tm vmlinux EXPORT_SYMBOL ++0xdcb944af usb_register_driver vmlinux EXPORT_SYMBOL_GPL ++0xbcda8829 scsi_block_requests vmlinux EXPORT_SYMBOL ++0xaa8a0279 sysfs_get vmlinux EXPORT_SYMBOL_GPL ++0x543ef284 seq_hlist_start vmlinux EXPORT_SYMBOL ++0x96573b80 __kfifo_dma_in_finish_r vmlinux EXPORT_SYMBOL ++0xe2f01afd mmc_release_host vmlinux EXPORT_SYMBOL ++0x3a374dcf fat_dir_empty vmlinux EXPORT_SYMBOL_GPL ++0x74cbb34b __getblk vmlinux EXPORT_SYMBOL ++0xd2f64b53 cdev_alloc vmlinux EXPORT_SYMBOL ++0xfb853c2c rpc_put_task_async vmlinux EXPORT_SYMBOL_GPL ++0x42d56457 usb_hcd_unlink_urb_from_ep vmlinux EXPORT_SYMBOL_GPL ++0xc48ee272 dev_warn vmlinux EXPORT_SYMBOL ++0xab3d1f95 nf_ct_untracked_status_or net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x9cedcd62 get_phy_device vmlinux EXPORT_SYMBOL ++0x74c134b9 __sw_hweight32 vmlinux EXPORT_SYMBOL ++0x57674fd7 __sw_hweight16 vmlinux EXPORT_SYMBOL ++0x9f46ced8 __sw_hweight64 vmlinux EXPORT_SYMBOL ++0xad0a6e0a flex_array_prealloc vmlinux EXPORT_SYMBOL ++0x93215e1d __kfifo_skip_r vmlinux EXPORT_SYMBOL ++0xa5377e1f svc_exit_thread vmlinux EXPORT_SYMBOL_GPL ++0x137b3ec2 pagevec_lookup_tag vmlinux EXPORT_SYMBOL ++0x67053080 current_kernel_time vmlinux EXPORT_SYMBOL ++0x3e187f83 print_tuple net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x4ef191e6 tcp_reno_cong_avoid vmlinux EXPORT_SYMBOL_GPL ++0x5a744b86 netlink_set_nonroot vmlinux EXPORT_SYMBOL ++0x82942563 usb_reset_device vmlinux EXPORT_SYMBOL_GPL ++0x7505bdef memchr_inv vmlinux EXPORT_SYMBOL ++0x1223591c locks_copy_lock vmlinux EXPORT_SYMBOL ++0xaa413a43 gnet_stats_start_copy_compat vmlinux EXPORT_SYMBOL ++0x1029fa00 rtc_alarm_irq_enable vmlinux EXPORT_SYMBOL_GPL ++0x785f307d pcim_iounmap_regions vmlinux EXPORT_SYMBOL ++0x7522f3ba irq_modify_status vmlinux EXPORT_SYMBOL_GPL ++0x52ccfd70 dcbnl_ieee_notify vmlinux EXPORT_SYMBOL ++0xbfd69829 inet6_del_protocol vmlinux EXPORT_SYMBOL ++0x753e1c04 xfrm_input_resume vmlinux EXPORT_SYMBOL ++0xde22dda4 udplite_prot vmlinux EXPORT_SYMBOL ++0xf19b1812 sock_create_kern vmlinux EXPORT_SYMBOL ++0x76b656be scsi_eh_restore_cmnd vmlinux EXPORT_SYMBOL ++0x00b8174b transport_remove_device vmlinux EXPORT_SYMBOL_GPL ++0x8260686f bitmap_find_next_zero_area vmlinux EXPORT_SYMBOL ++0x4a487484 i2c_del_mux_adapter vmlinux EXPORT_SYMBOL_GPL ++0x74cda2a1 sk_detach_filter vmlinux EXPORT_SYMBOL_GPL ++0xf1734ac9 sk_attach_filter vmlinux EXPORT_SYMBOL_GPL ++0x77bebd69 pci_unregister_driver vmlinux EXPORT_SYMBOL ++0xf741c793 zlib_deflateEnd vmlinux EXPORT_SYMBOL ++0x7469fcfe radix_tree_tagged vmlinux EXPORT_SYMBOL ++0x59659594 unload_nls vmlinux EXPORT_SYMBOL ++0x25673182 seq_open_private vmlinux EXPORT_SYMBOL ++0xe9d6801d sunrpc_cache_update vmlinux EXPORT_SYMBOL_GPL ++0xec56166e skb_gso_segment vmlinux EXPORT_SYMBOL ++0x4e128338 kernel_listen vmlinux EXPORT_SYMBOL ++0x76bf656d __bitmap_shift_left vmlinux EXPORT_SYMBOL ++0x291fef69 gss_mech_get vmlinux EXPORT_SYMBOL_GPL ++0x6713b9ea napi_skb_finish vmlinux EXPORT_SYMBOL ++0xdb9433e3 __scsi_device_lookup vmlinux EXPORT_SYMBOL ++0xe23ae481 blk_iopoll_complete vmlinux EXPORT_SYMBOL ++0xb11b4eca crypto_chain vmlinux EXPORT_SYMBOL_GPL ++0x9d669763 memcpy vmlinux EXPORT_SYMBOL ++0x03a5674f ip6t_do_table net/ipv6/netfilter/ip6_tables EXPORT_SYMBOL ++0x86ed218d rpc_run_task vmlinux EXPORT_SYMBOL_GPL ++0x43a0458b blk_start_plug vmlinux EXPORT_SYMBOL ++0xa67752f3 bdevname vmlinux EXPORT_SYMBOL ++0x3d4d9f3c cdev_init vmlinux EXPORT_SYMBOL ++0xbe63ee40 request_resource vmlinux EXPORT_SYMBOL ++0x697cbbb4 threads_per_core vmlinux EXPORT_SYMBOL_GPL ++0xc24dd028 nf_ct_expect_init net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x98ed718a inet_getname vmlinux EXPORT_SYMBOL ++0xe7609b0d generate_netlink_event vmlinux EXPORT_SYMBOL ++0x85e7deb2 iov_iter_fault_in_readable vmlinux EXPORT_SYMBOL ++0x15e9ff97 module_mutex vmlinux EXPORT_SYMBOL_GPL ++0xf5a62ecc _memset_io vmlinux EXPORT_SYMBOL ++0x7c1ac45d put_mtd_device vmlinux EXPORT_SYMBOL_GPL ++0xbf9bcc8d __cap_empty_set vmlinux EXPORT_SYMBOL ++0xe2504d65 xprt_register_transport vmlinux EXPORT_SYMBOL_GPL ++0xe0ead969 i2c_smbus_process_call vmlinux EXPORT_SYMBOL ++0x313f13aa platform_get_resource vmlinux EXPORT_SYMBOL_GPL ++0x42b7e450 pci_disable_pcie_error_reporting vmlinux EXPORT_SYMBOL_GPL ++0xfed042ab crypto_shoot_alg vmlinux EXPORT_SYMBOL_GPL ++0xf37d86d3 iput vmlinux EXPORT_SYMBOL ++0x245a5a94 sleep_on_timeout vmlinux EXPORT_SYMBOL ++0x30a3ce2d xprt_complete_rqst vmlinux EXPORT_SYMBOL_GPL ++0x28a82da4 snmp_mib_init vmlinux EXPORT_SYMBOL_GPL ++0xd91b9062 input_ff_upload vmlinux EXPORT_SYMBOL_GPL ++0x072e69d7 create_proc_entry vmlinux EXPORT_SYMBOL ++0x03fd2571 vm_unmap_ram vmlinux EXPORT_SYMBOL ++0xd39230da proc_doulongvec_ms_jiffies_minmax vmlinux EXPORT_SYMBOL ++0x2d2f8405 xfrm_output vmlinux EXPORT_SYMBOL_GPL ++0x62dd148f of_phy_connect vmlinux EXPORT_SYMBOL ++0x796ef373 pci_enable_device_mem vmlinux EXPORT_SYMBOL ++0xeea9dbaf bitmap_bitremap vmlinux EXPORT_SYMBOL ++0x71a50dbc register_blkdev vmlinux EXPORT_SYMBOL ++0xe1ead0f9 nf_conntrack_alter_reply net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x596ca373 neigh_event_ns vmlinux EXPORT_SYMBOL ++0x88aa1b8c sdhci_free_host vmlinux EXPORT_SYMBOL_GPL ++0xe58fb452 aer_irq vmlinux EXPORT_SYMBOL_GPL ++0x76e3aed7 elevator_change vmlinux EXPORT_SYMBOL ++0x14dc18d8 iterate_supers_type vmlinux EXPORT_SYMBOL ++0x2285200f usb_kill_anchored_urbs vmlinux EXPORT_SYMBOL_GPL ++0x09775cdc kref_get vmlinux EXPORT_SYMBOL ++0x1f46d410 netdev_change_features vmlinux EXPORT_SYMBOL ++0xaa27750a init_dummy_netdev vmlinux EXPORT_SYMBOL_GPL ++0x9e4f1cfb ring_buffer_resize vmlinux EXPORT_SYMBOL_GPL ++0xcb0c622b dst_destroy vmlinux EXPORT_SYMBOL ++0xc4b45e74 pci_disable_rom vmlinux EXPORT_SYMBOL_GPL ++0x443ddc6e pci_disable_ido vmlinux EXPORT_SYMBOL ++0x21962aa1 pci_disable_ltr vmlinux EXPORT_SYMBOL ++0x2c8d9ecf journal_errno vmlinux EXPORT_SYMBOL ++0x78e988ed svc_wake_up vmlinux EXPORT_SYMBOL_GPL ++0x3e4a8504 xprt_write_space vmlinux EXPORT_SYMBOL_GPL ++0x61a39807 ndisc_send_skb vmlinux EXPORT_SYMBOL ++0x2ab23b9b nf_unregister_queue_handlers vmlinux EXPORT_SYMBOL_GPL ++0x3f2f77c8 mtd_blktrans_cease_background vmlinux EXPORT_SYMBOL_GPL ++0x70a7409f scsi_mode_sense vmlinux EXPORT_SYMBOL ++0x2d89342a scsi_show_sense_hdr vmlinux EXPORT_SYMBOL ++0xe87b346a pci_enable_ltr vmlinux EXPORT_SYMBOL ++0x2e5a7064 journal_check_available_features vmlinux EXPORT_SYMBOL ++0x78ed3e5c __init_waitqueue_head vmlinux EXPORT_SYMBOL ++0x836afd32 nf_ct_get_tuple net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x989fa19e xfrm6_tunnel_register net/ipv6/tunnel6 EXPORT_SYMBOL ++0x3d961c15 xfrm4_tunnel_register net/ipv4/tunnel4 EXPORT_SYMBOL ++0x405d6987 of_property_read_u64 vmlinux EXPORT_SYMBOL_GPL ++0x20edb24a blk_insert_cloned_request vmlinux EXPORT_SYMBOL_GPL ++0x6f4b609a init_timer_deferrable_key vmlinux EXPORT_SYMBOL ++0x2dc5379b skb_copy_datagram_from_iovec vmlinux EXPORT_SYMBOL ++0x5f8a2728 isa_io_base vmlinux EXPORT_SYMBOL ++0x907fa9b5 dst_alloc vmlinux EXPORT_SYMBOL ++0xe93e49c3 devres_free vmlinux EXPORT_SYMBOL_GPL ++0x84ecb7cb timerqueue_iterate_next vmlinux EXPORT_SYMBOL_GPL ++0x1fad8e64 blk_put_queue vmlinux EXPORT_SYMBOL ++0xa5df3b80 single_release vmlinux EXPORT_SYMBOL ++0x23663ac5 get_user_pages vmlinux EXPORT_SYMBOL ++0xa108eb4d sysctl_optmem_max vmlinux EXPORT_SYMBOL ++0x14b1b51c enable_kernel_spe vmlinux EXPORT_SYMBOL ++0xe57878a1 in6_pton vmlinux EXPORT_SYMBOL ++0xaccabc6a in4_pton vmlinux EXPORT_SYMBOL ++0xd55d1a4c of_get_mac_address vmlinux EXPORT_SYMBOL ++0x30d70fa9 of_get_pci_address vmlinux EXPORT_SYMBOL ++0x02b1d92b scsi_mode_select vmlinux EXPORT_SYMBOL_GPL ++0xd0181f4f __bitmap_xor vmlinux EXPORT_SYMBOL ++0xed746f71 mnt_want_write vmlinux EXPORT_SYMBOL_GPL ++0xf3341268 __clear_user vmlinux EXPORT_SYMBOL ++0x9d14983a ppc_enable_pmcs vmlinux EXPORT_SYMBOL ++0x519e4247 xprt_lock_and_alloc_slot vmlinux EXPORT_SYMBOL_GPL ++0x62bdb353 __dev_remove_pack vmlinux EXPORT_SYMBOL ++0x1aa8db0c __starget_for_each_device vmlinux EXPORT_SYMBOL ++0x90a1004a crypto_has_alg vmlinux EXPORT_SYMBOL_GPL ++0xd6321e2a iget5_locked vmlinux EXPORT_SYMBOL ++0x3dcb88a0 irq_set_handler_data vmlinux EXPORT_SYMBOL ++0xa5a4e6a7 yield_to vmlinux EXPORT_SYMBOL_GPL ++0x8056c327 mii_check_media vmlinux EXPORT_SYMBOL ++0xc47af61f user_revoke vmlinux EXPORT_SYMBOL ++0x0b263573 debugfs_create_dir vmlinux EXPORT_SYMBOL_GPL ++0xb23b2262 dcache_dir_lseek vmlinux EXPORT_SYMBOL ++0x0c2cdbf1 synchronize_sched vmlinux EXPORT_SYMBOL_GPL ++0x6fff393f time_to_tm vmlinux EXPORT_SYMBOL ++0x651a4139 test_taint vmlinux EXPORT_SYMBOL ++0x6b7d903c netdev_printk vmlinux EXPORT_SYMBOL ++0x8dad55e8 of_address_to_resource vmlinux EXPORT_SYMBOL_GPL ++0x90b3ac7f thermal_zone_device_register vmlinux EXPORT_SYMBOL ++0x73cd0f30 pci_scan_bus_parented vmlinux EXPORT_SYMBOL ++0xf5a691cd invalidate_bh_lrus vmlinux EXPORT_SYMBOL_GPL ++0x518889d8 ipcomp_init_state net/xfrm/xfrm_ipcomp EXPORT_SYMBOL_GPL ++0x90599000 xt_check_match vmlinux EXPORT_SYMBOL_GPL ++0x41cb6ae6 cfi_qry_mode_on vmlinux EXPORT_SYMBOL_GPL ++0x32c3cb4e class_compat_register vmlinux EXPORT_SYMBOL_GPL ++0x24aac4d9 crypto_aes_expand_key vmlinux EXPORT_SYMBOL_GPL ++0x1eb914cc d_splice_alias vmlinux EXPORT_SYMBOL ++0x038de4b7 do_sync_read vmlinux EXPORT_SYMBOL ++0x5be5cfd3 mem_map vmlinux EXPORT_SYMBOL ++0xfedd35fc console_suspend_enabled vmlinux EXPORT_SYMBOL ++0x78f9b710 nf_ct_l3proto_try_module_get net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x199f8f28 svc_reg_xprt_class vmlinux EXPORT_SYMBOL_GPL ++0x40b1319f sdio_release_irq vmlinux EXPORT_SYMBOL_GPL ++0x6986e70b mmc_wait_for_cmd vmlinux EXPORT_SYMBOL ++0x59c20bea kobject_rename vmlinux EXPORT_SYMBOL_GPL ++0x72aa82c6 param_ops_charp vmlinux EXPORT_SYMBOL ++0x8a0e5ca2 rpc_mkpipe vmlinux EXPORT_SYMBOL_GPL ++0x9854bf90 cad_pid vmlinux EXPORT_SYMBOL ++0x5a5a94a6 kstrtou8 vmlinux EXPORT_SYMBOL ++0xb0477a75 get_task_pid vmlinux EXPORT_SYMBOL_GPL ++0x85478a0b inet6_hash_frag vmlinux EXPORT_SYMBOL_GPL ++0x6849a15f flex_array_clear vmlinux EXPORT_SYMBOL ++0x5a7bfe41 crypto_probing_notify vmlinux EXPORT_SYMBOL_GPL ++0xf0a118b4 ip6t_alloc_initial_table net/ipv6/netfilter/ip6_tables EXPORT_SYMBOL_GPL ++0x9ef5eb8e netif_receive_skb vmlinux EXPORT_SYMBOL ++0x196d40cb spi_new_device vmlinux EXPORT_SYMBOL_GPL ++0xc906a49f journal_update_format vmlinux EXPORT_SYMBOL ++0xfb6af58d recalc_sigpending vmlinux EXPORT_SYMBOL ++0x5fc7e979 nf_nat_proto_unique_tuple net/ipv4/netfilter/nf_nat EXPORT_SYMBOL_GPL ++0xdcb45617 nf_nat_mangle_udp_packet net/ipv4/netfilter/nf_nat EXPORT_SYMBOL ++0xaeb5ccdc anon_transport_class_register vmlinux EXPORT_SYMBOL_GPL ++0xf39ae0fb disk_part_iter_exit vmlinux EXPORT_SYMBOL_GPL ++0x6c85445f follow_down_one vmlinux EXPORT_SYMBOL ++0x7944e0fc tracing_off vmlinux EXPORT_SYMBOL_GPL ++0x9fa181ba rpcauth_init_credcache vmlinux EXPORT_SYMBOL_GPL ++0x81c6ed08 raw_seq_next vmlinux EXPORT_SYMBOL_GPL ++0x05f187fd ip_setsockopt vmlinux EXPORT_SYMBOL ++0x1c72d333 ip_getsockopt vmlinux EXPORT_SYMBOL ++0x38074cf6 qdisc_watchdog_schedule vmlinux EXPORT_SYMBOL ++0xed709aff tty_encode_baud_rate vmlinux EXPORT_SYMBOL_GPL ++0x80dd3e42 blk_unprep_request vmlinux EXPORT_SYMBOL_GPL ++0x6e50c56b xdr_shift_buf vmlinux EXPORT_SYMBOL_GPL ++0xf106c813 ip_options_rcv_srr vmlinux EXPORT_SYMBOL ++0x9a5a79fd device_register vmlinux EXPORT_SYMBOL_GPL ++0x3ca8a6b3 pcim_iomap_regions_request_all vmlinux EXPORT_SYMBOL ++0xc159495b dentry_open vmlinux EXPORT_SYMBOL ++0xbb2b98fa skb_checksum_help vmlinux EXPORT_SYMBOL ++0x60ee6103 unregister_netdevice_queue vmlinux EXPORT_SYMBOL ++0x40a27c37 scsi_dev_info_remove_list vmlinux EXPORT_SYMBOL ++0x9545af6d tasklet_init vmlinux EXPORT_SYMBOL ++0x68a29b9a nf_nat_setup_info net/ipv4/netfilter/nf_nat EXPORT_SYMBOL ++0xdf56dcb2 stop_machine vmlinux EXPORT_SYMBOL_GPL ++0x53986488 register_die_notifier vmlinux EXPORT_SYMBOL_GPL ++0x580dfef9 nf_ct_unlink_expect_report net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x3257c865 sock_no_recvmsg vmlinux EXPORT_SYMBOL ++0x6a2126c6 hrtimer_cancel vmlinux EXPORT_SYMBOL_GPL ++0x0a22b996 xt_unregister_matches vmlinux EXPORT_SYMBOL ++0xfdfc0b3b fiemap_fill_next_extent vmlinux EXPORT_SYMBOL ++0x4087f0c0 qdisc_watchdog_cancel vmlinux EXPORT_SYMBOL ++0x4ce6c680 crypto_shash_digest vmlinux EXPORT_SYMBOL_GPL ++0xe8d8b9c7 crypto_ahash_digest vmlinux EXPORT_SYMBOL_GPL ++0x3de9cae1 crypto_remove_final vmlinux EXPORT_SYMBOL_GPL ++0x296b5561 svc_authenticate vmlinux EXPORT_SYMBOL_GPL ++0xd0108d65 rtnl_set_sk_err vmlinux EXPORT_SYMBOL ++0x4865167d usb_hcd_pci_remove vmlinux EXPORT_SYMBOL_GPL ++0xec9ca601 driver_add_kobj vmlinux EXPORT_SYMBOL_GPL ++0x89797060 _raw_read_lock vmlinux EXPORT_SYMBOL ++0x897f061d downgrade_write vmlinux EXPORT_SYMBOL ++0x5568c553 complete vmlinux EXPORT_SYMBOL ++0x6fd12bcc ip_check_defrag vmlinux EXPORT_SYMBOL ++0xdb864d65 iov_iter_single_seg_count vmlinux EXPORT_SYMBOL ++0x9c44f35a scsi_test_unit_ready vmlinux EXPORT_SYMBOL ++0xad37975e dentry_update_name_case vmlinux EXPORT_SYMBOL ++0x8a7d1c31 high_memory vmlinux EXPORT_SYMBOL ++0xd7b213fa smp_call_function_many vmlinux EXPORT_SYMBOL ++0xbdb6ee0c usb_serial_deregister vmlinux EXPORT_SYMBOL_GPL ++0x4d9edeae simple_link vmlinux EXPORT_SYMBOL ++0xbdd2f42a rcu_bh_force_quiescent_state vmlinux EXPORT_SYMBOL_GPL ++0xc458c88f hidinput_find_field vmlinux EXPORT_SYMBOL_GPL ++0x4a6c3f1a usb_serial_suspend vmlinux EXPORT_SYMBOL ++0x14193672 scsi_remove_target vmlinux EXPORT_SYMBOL ++0xb6c5a973 scsi_show_result vmlinux EXPORT_SYMBOL ++0x03e32c1d sysdev_remove_file vmlinux EXPORT_SYMBOL_GPL ++0x99faa353 journal_blocks_per_page vmlinux EXPORT_SYMBOL ++0x63b8f6ef page_cache_async_readahead vmlinux EXPORT_SYMBOL_GPL ++0x8de0b5ac mempool_create vmlinux EXPORT_SYMBOL ++0xe3a98a71 kblockd_schedule_work vmlinux EXPORT_SYMBOL ++0x79d654ef send_sig_info vmlinux EXPORT_SYMBOL ++0x20030ecd ioremap vmlinux EXPORT_SYMBOL ++0xedc03953 iounmap vmlinux EXPORT_SYMBOL ++0xc865db6b xprt_release_xprt vmlinux EXPORT_SYMBOL_GPL ++0xc628e72a __neigh_event_send vmlinux EXPORT_SYMBOL ++0x0c61e098 sk_stream_wait_close vmlinux EXPORT_SYMBOL ++0x3c396f87 show_class_attr_string vmlinux EXPORT_SYMBOL_GPL ++0x441257b7 sysdev_store_int vmlinux EXPORT_SYMBOL_GPL ++0xf3970f1b read_cache_page_async vmlinux EXPORT_SYMBOL ++0xd0ee38b8 schedule_timeout_uninterruptible vmlinux EXPORT_SYMBOL ++0xd79b5a02 allow_signal vmlinux EXPORT_SYMBOL ++0xd3081dfa qe_upload_firmware vmlinux EXPORT_SYMBOL ++0xf4d880ae platform_get_irq vmlinux EXPORT_SYMBOL_GPL ++0x0781bf45 kill_anon_super vmlinux EXPORT_SYMBOL ++0x6676c50d nf_ct_delete_from_lists net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x730d37a5 xfrm6_rcv vmlinux EXPORT_SYMBOL ++0x119a95b0 xfrm4_rcv vmlinux EXPORT_SYMBOL ++0x309ea25a pci_enable_pcie_error_reporting vmlinux EXPORT_SYMBOL_GPL ++0x88ddfe5e xdr_buf_subsegment vmlinux EXPORT_SYMBOL_GPL ++0xed08815e inet_dgram_connect vmlinux EXPORT_SYMBOL ++0x715fb53b usb_find_alt_setting vmlinux EXPORT_SYMBOL_GPL ++0x0f6fbd82 phy_connect vmlinux EXPORT_SYMBOL ++0x34ab3ee2 driver_unregister vmlinux EXPORT_SYMBOL_GPL ++0xc87f94e8 generic_pipe_buf_unmap vmlinux EXPORT_SYMBOL ++0xddd4147d generic_pipe_buf_steal vmlinux EXPORT_SYMBOL ++0xa2c56c31 param_ops_ulong vmlinux EXPORT_SYMBOL ++0x01ca7533 inet_frags_exit_net vmlinux EXPORT_SYMBOL ++0x8e4b1069 kobject_get vmlinux EXPORT_SYMBOL ++0x3fb18605 kobject_put vmlinux EXPORT_SYMBOL ++0x9d033f64 nfs4_reset_write vmlinux EXPORT_SYMBOL_GPL ++0x46214106 files_lglock_local_unlock_cpu vmlinux EXPORT_SYMBOL ++0x58688735 relay_open vmlinux EXPORT_SYMBOL_GPL ++0x4029d238 param_set_copystring vmlinux EXPORT_SYMBOL ++0x59e70f93 __send_remote_softirq vmlinux EXPORT_SYMBOL ++0x2afbe2a5 usb_scuttle_anchored_urbs vmlinux EXPORT_SYMBOL_GPL ++0x51cc13a8 cfi_read_pri vmlinux EXPORT_SYMBOL ++0xf1deabf2 div64_u64 vmlinux EXPORT_SYMBOL ++0x52b34107 relay_close vmlinux EXPORT_SYMBOL_GPL ++0xfc39e32f ioport_unmap vmlinux EXPORT_SYMBOL ++0xbe3ce140 usb_reset_configuration vmlinux EXPORT_SYMBOL_GPL ++0x03dd0aff sysfs_merge_group vmlinux EXPORT_SYMBOL_GPL ++0xc84a0a7e seq_hlist_start_rcu vmlinux EXPORT_SYMBOL ++0xcdada4b3 d_validate vmlinux EXPORT_SYMBOL ++0xb2ebe0b7 __get_user_pages_fast vmlinux EXPORT_SYMBOL_GPL ++0x7bcc3ec6 down_trylock vmlinux EXPORT_SYMBOL ++0x16b67679 genl_register_family vmlinux EXPORT_SYMBOL ++0xc256e762 __bitmap_equal vmlinux EXPORT_SYMBOL ++0x019e7765 __init_rwsem vmlinux EXPORT_SYMBOL ++0x5342878d page_zero_new_buffers vmlinux EXPORT_SYMBOL ++0x7a6737e5 mntget vmlinux EXPORT_SYMBOL ++0x61406732 mntput vmlinux EXPORT_SYMBOL ++0x4f62563b fasync_helper vmlinux EXPORT_SYMBOL ++0x64203ccb mount_mtd vmlinux EXPORT_SYMBOL_GPL ++0x2f4113a2 dcookie_register vmlinux EXPORT_SYMBOL_GPL ++0xeee9690b locks_mandatory_area vmlinux EXPORT_SYMBOL ++0x99060d85 inet_twsk_deschedule vmlinux EXPORT_SYMBOL ++0x140d6513 xt_table_unlock vmlinux EXPORT_SYMBOL_GPL ++0x88b210e6 ethtool_op_set_ufo vmlinux EXPORT_SYMBOL ++0xb887455c sock_alloc_send_pskb vmlinux EXPORT_SYMBOL ++0x0acb1a3c __bitmap_shift_right vmlinux EXPORT_SYMBOL ++0x402b8281 __request_module vmlinux EXPORT_SYMBOL ++0xba215bc2 inet_register_protosw vmlinux EXPORT_SYMBOL ++0x9e041871 __inet_inherit_port vmlinux EXPORT_SYMBOL_GPL ++0x2b4f08e0 dev_deactivate vmlinux EXPORT_SYMBOL ++0x8eed09dc phy_find_first vmlinux EXPORT_SYMBOL ++0xb89af9bf srandom32 vmlinux EXPORT_SYMBOL ++0x23fd3028 vmalloc_node vmlinux EXPORT_SYMBOL ++0x891fbb10 mempool_destroy vmlinux EXPORT_SYMBOL ++0x054e550b kernel_halt vmlinux EXPORT_SYMBOL_GPL ++0xe0b0b13d xfrm6_tunnel_spi_lookup net/ipv6/xfrm6_tunnel EXPORT_SYMBOL ++0xe7a8d75d netpoll_cleanup vmlinux EXPORT_SYMBOL ++0x62005346 scsi_ioctl vmlinux EXPORT_SYMBOL ++0xe7bd56ce set_binfmt vmlinux EXPORT_SYMBOL ++0x9933f8fa km_policy_expired vmlinux EXPORT_SYMBOL ++0xdff2d6cd spi_unregister_master vmlinux EXPORT_SYMBOL_GPL ++0xae973946 __first_cpu vmlinux EXPORT_SYMBOL ++0xe2a6904b elv_rb_find vmlinux EXPORT_SYMBOL ++0xbee90f2f __kfifo_out_peek_r vmlinux EXPORT_SYMBOL ++0xa04a01bd qdisc_class_hash_insert vmlinux EXPORT_SYMBOL ++0xe5867808 dlci_ioctl_set vmlinux EXPORT_SYMBOL ++0x13e1e53c crypto_alg_lookup vmlinux EXPORT_SYMBOL_GPL ++0x8b4ac748 __rpc_wait_for_completion_task vmlinux EXPORT_SYMBOL_GPL ++0x742ec05d ethtool_op_set_tx_ipv6_csum vmlinux EXPORT_SYMBOL ++0x6195e83d scsi_report_device_reset vmlinux EXPORT_SYMBOL ++0x21e29754 scsi_print_sense vmlinux EXPORT_SYMBOL ++0xa34a1e0b locks_free_lock vmlinux EXPORT_SYMBOL ++0xe71c31f7 simple_attr_release vmlinux EXPORT_SYMBOL_GPL ++0xed120683 usb_submit_urb vmlinux EXPORT_SYMBOL_GPL ++0x928dc8b5 rename_lock vmlinux EXPORT_SYMBOL ++0xdebe699e page_symlink_inode_operations vmlinux EXPORT_SYMBOL ++0x99afe916 _raw_write_unlock_bh vmlinux EXPORT_SYMBOL ++0x060ea2d6 kstrtoull vmlinux EXPORT_SYMBOL ++0x5ac15bae kstrtou16 vmlinux EXPORT_SYMBOL ++0x94961283 vunmap vmlinux EXPORT_SYMBOL ++0xc97eeec5 write_cache_pages vmlinux EXPORT_SYMBOL ++0x160a0cad nf_conntrack_l4proto_tcp6 net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x3b21e0c3 xfrm_policy_alloc vmlinux EXPORT_SYMBOL ++0x81b8ae05 __nf_ct_ext_add net/netfilter/nf_conntrack EXPORT_SYMBOL ++0x117093be qdisc_class_hash_init vmlinux EXPORT_SYMBOL ++0xd4fb8ce7 sk_prot_clear_portaddr_nulls vmlinux EXPORT_SYMBOL ++0x787ae952 mtd_del_partition vmlinux EXPORT_SYMBOL_GPL ++0x25f3bd2e atomic64_xchg vmlinux EXPORT_SYMBOL ++0xfcc95cae task_current_syscall vmlinux EXPORT_SYMBOL_GPL ++0x574ed83f single_open_net vmlinux EXPORT_SYMBOL_GPL ++0xcc4c11c3 set_page_dirty_lock vmlinux EXPORT_SYMBOL ++0x8bc74143 tcp_v4_conn_request vmlinux EXPORT_SYMBOL ++0xeace373d usb_get_descriptor vmlinux EXPORT_SYMBOL_GPL ++0xf7064a0d spi_async_locked vmlinux EXPORT_SYMBOL_GPL ++0xca62af4c get_mtd_device vmlinux EXPORT_SYMBOL_GPL ++0x4897a00b blk_rq_init vmlinux EXPORT_SYMBOL ++0x26e76fb8 sysctl_udp_wmem_min vmlinux EXPORT_SYMBOL ++0x60b3b58a tcp_v4_syn_recv_sock vmlinux EXPORT_SYMBOL ++0x906c274e usb_put_dev vmlinux EXPORT_SYMBOL_GPL ++0xa7b0d968 swiotlb_tbl_sync_single vmlinux EXPORT_SYMBOL_GPL ++0x6d464175 __sg_free_table vmlinux EXPORT_SYMBOL ++0x4d6c0e8d kmem_cache_shrink vmlinux EXPORT_SYMBOL ++0x10d9d048 icmp_err_convert vmlinux EXPORT_SYMBOL ++0xf67a2d46 mii_check_link vmlinux EXPORT_SYMBOL ++0xd334a2bd tcp_hashinfo vmlinux EXPORT_SYMBOL ++0x2d140a58 genl_unlock vmlinux EXPORT_SYMBOL ++0x4256c8a3 of_n_size_cells vmlinux EXPORT_SYMBOL ++0xf040786d hid_report_raw_event vmlinux EXPORT_SYMBOL_GPL ++0x8c70d5ae scsi_unregister vmlinux EXPORT_SYMBOL ++0x0087d496 crypto_aead_setauthsize vmlinux EXPORT_SYMBOL_GPL ++0x5676c702 nlmclnt_init vmlinux EXPORT_SYMBOL_GPL ++0xcb09bf1a fd_install vmlinux EXPORT_SYMBOL ++0x4c11435a _raw_read_lock_bh vmlinux EXPORT_SYMBOL ++0x7681e3ba nf_nat_used_tuple net/ipv4/netfilter/nf_nat EXPORT_SYMBOL ++0xc927923a nf_nat_packet net/ipv4/netfilter/nf_nat EXPORT_SYMBOL_GPL ++0x9b8f7dca scsi_internal_device_unblock vmlinux EXPORT_SYMBOL_GPL ++0xbee5153c blk_init_tags vmlinux EXPORT_SYMBOL ++0x0d7d89ce vfs_fsync_range vmlinux EXPORT_SYMBOL ++0x3ce4ca6f disable_irq vmlinux EXPORT_SYMBOL ++0x87754115 raw_notifier_chain_register vmlinux EXPORT_SYMBOL_GPL ++0x20f357ca scsi_host_alloc vmlinux EXPORT_SYMBOL ++0xee146e0a bus_get_device_klist vmlinux EXPORT_SYMBOL_GPL ++0xd25133ac sysfs_remove_file vmlinux EXPORT_SYMBOL_GPL ++0x889d27ce path_put vmlinux EXPORT_SYMBOL ++0x5a9f996e apply_to_page_range vmlinux EXPORT_SYMBOL_GPL ++0xa0ceef51 out_of_line_wait_on_bit vmlinux EXPORT_SYMBOL ++0x70aca666 dst_discard vmlinux EXPORT_SYMBOL ++0xaa2a72bf __iowrite64_copy vmlinux EXPORT_SYMBOL_GPL ++0xf1bcf383 invalidate_partition vmlinux EXPORT_SYMBOL ++0xc26b1d80 kick_process vmlinux EXPORT_SYMBOL_GPL ++0xea41576c sk_release_kernel vmlinux EXPORT_SYMBOL ++0x13701441 sg_miter_stop vmlinux EXPORT_SYMBOL ++0x6f5febee key_reject_and_link vmlinux EXPORT_SYMBOL ++0xe4fe8ca1 _raw_spin_unlock_bh vmlinux EXPORT_SYMBOL ++0xc4aa788d xt_proto_init vmlinux EXPORT_SYMBOL_GPL ++0xdd1c65f6 blk_finish_plug vmlinux EXPORT_SYMBOL ++0x0b1beb31 vmalloc_32_user vmlinux EXPORT_SYMBOL ++0x756f9875 pci_get_subsys vmlinux EXPORT_SYMBOL ++0x9eecde16 do_brk vmlinux EXPORT_SYMBOL ++0x878ab3ce sysctl_tcp_adv_win_scale vmlinux EXPORT_SYMBOL ++0x7d32f0ad ip_local_out vmlinux EXPORT_SYMBOL_GPL ++0xe163a0d1 usb_hcd_check_unlink_urb vmlinux EXPORT_SYMBOL_GPL ++0xb1a9725f phy_device_free vmlinux EXPORT_SYMBOL ++0xb0104373 generic_permission vmlinux EXPORT_SYMBOL ++0xd59668e6 unlock_flocks vmlinux EXPORT_SYMBOL_GPL ++0xd7b7c7e4 uart_get_baud_rate vmlinux EXPORT_SYMBOL ++0xd6d2bfe8 pci_find_next_bus vmlinux EXPORT_SYMBOL ++0x9d3aa376 blk_iopoll_init vmlinux EXPORT_SYMBOL ++0xcbc2c8dd atomic_notifier_chain_unregister vmlinux EXPORT_SYMBOL_GPL ++0x8ba65b48 secpath_dup vmlinux EXPORT_SYMBOL ++0xe1b3830a set_user_nice vmlinux EXPORT_SYMBOL ++0x35c4c2bc gss_pseudoflavor_to_service vmlinux EXPORT_SYMBOL_GPL ++0xe7d71ad5 splice_direct_to_actor vmlinux EXPORT_SYMBOL ++0xf34806ec hrtimer_get_res vmlinux EXPORT_SYMBOL_GPL ++0x7d1541f1 nf_nat_pptp_hook_inbound net/netfilter/nf_conntrack_pptp EXPORT_SYMBOL_GPL ++0x1fdf5145 nf_conntrack_l3proto_unregister net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x895b81a5 nf_conntrack_l4proto_unregister net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x2b9da7a4 genl_lock vmlinux EXPORT_SYMBOL ++0x2d187f6f qdisc_class_hash_grow vmlinux EXPORT_SYMBOL ++0x7528c327 sock_setsockopt vmlinux EXPORT_SYMBOL ++0x7587dd64 tty_port_close_start vmlinux EXPORT_SYMBOL ++0x074989f8 ida_simple_remove vmlinux EXPORT_SYMBOL ++0xdfc46245 unlock_buffer vmlinux EXPORT_SYMBOL ++0x3429114e simple_transaction_release vmlinux EXPORT_SYMBOL ++0x5e4d4180 nfulnl_log_packet net/netfilter/nfnetlink_log EXPORT_SYMBOL_GPL ++0x01010c6d klist_add_before vmlinux EXPORT_SYMBOL_GPL ++0x9cb96e92 qdisc_put_rtab vmlinux EXPORT_SYMBOL ++0x91fd73a4 subsys_find_device_by_id vmlinux EXPORT_SYMBOL_GPL ++0x093e125a crypto_attr_alg2 vmlinux EXPORT_SYMBOL_GPL ++0xfc01e0ca nfs_commit_free vmlinux EXPORT_SYMBOL_GPL ++0x1176e07f __per_cpu_offset vmlinux EXPORT_SYMBOL ++0xbbcd407c proto_register vmlinux EXPORT_SYMBOL ++0x175b8a58 rtc_irq_unregister vmlinux EXPORT_SYMBOL_GPL ++0x9c7a72be tty_wakeup vmlinux EXPORT_SYMBOL_GPL ++0xb1f5c533 check_disk_size_change vmlinux EXPORT_SYMBOL ++0x33839ed8 d_clear_need_lookup vmlinux EXPORT_SYMBOL ++0xbc3f6afa down_read vmlinux EXPORT_SYMBOL ++0x5850f4cd km_report vmlinux EXPORT_SYMBOL ++0x1694ba86 __napi_complete vmlinux EXPORT_SYMBOL ++0xc3bc62fb skb_copy_expand vmlinux EXPORT_SYMBOL ++0xabd0c91c rtc_time_to_tm vmlinux EXPORT_SYMBOL ++0x274f1f9b dmam_free_coherent vmlinux EXPORT_SYMBOL ++0x98c6103a transport_setup_device vmlinux EXPORT_SYMBOL_GPL ++0x3da3a6f5 blk_queue_softirq_done vmlinux EXPORT_SYMBOL ++0x190c3ccc d_lookup vmlinux EXPORT_SYMBOL ++0xabdd83b5 genl_unregister_mc_group vmlinux EXPORT_SYMBOL ++0xf811e69d scsi_eh_flush_done_q vmlinux EXPORT_SYMBOL ++0x99f66401 path_is_under vmlinux EXPORT_SYMBOL ++0xfa590506 pci_iomap vmlinux EXPORT_SYMBOL ++0xa8119c49 xt_hook_unlink vmlinux EXPORT_SYMBOL_GPL ++0xc6435be3 skb_morph vmlinux EXPORT_SYMBOL_GPL ++0xdb0c48bb mmc_erase vmlinux EXPORT_SYMBOL ++0x8baf3116 percpu_counter_set vmlinux EXPORT_SYMBOL ++0x61a90c54 klist_add_head vmlinux EXPORT_SYMBOL_GPL ++0x5269ab27 ethtool_op_set_flags vmlinux EXPORT_SYMBOL ++0x7701acae scsi_remove_host vmlinux EXPORT_SYMBOL ++0x2c88b964 pci_request_selected_regions_exclusive vmlinux EXPORT_SYMBOL ++0xb6822a33 radix_tree_gang_lookup_tag vmlinux EXPORT_SYMBOL ++0xe8e99f5c flush_dcache_page vmlinux EXPORT_SYMBOL ++0xf4449388 timer_interrupt vmlinux EXPORT_SYMBOL ++0x12aab7d1 scsi_is_host_device vmlinux EXPORT_SYMBOL ++0x36ca51ab devm_ioremap_nocache vmlinux EXPORT_SYMBOL ++0xf370333d sync_dirty_buffer vmlinux EXPORT_SYMBOL ++0x6c81fae0 tcp_reno_ssthresh vmlinux EXPORT_SYMBOL_GPL ++0xca461664 netlink_has_listeners vmlinux EXPORT_SYMBOL_GPL ++0xc761c4bf pci_remove_bus_device vmlinux EXPORT_SYMBOL ++0xe075d6eb iter_div_u64_rem vmlinux EXPORT_SYMBOL ++0xd6c9eb4a nf_nat_seq_adjust_hook net/ipv4/netfilter/nf_conntrack_ipv4 EXPORT_SYMBOL_GPL ++0x53bce6b9 usb_alloc_urb vmlinux EXPORT_SYMBOL_GPL ++0x876e5b30 spi_setup vmlinux EXPORT_SYMBOL_GPL ++0x205125b9 __pci_enable_wake vmlinux EXPORT_SYMBOL ++0x1f0ffbff inode_init_once vmlinux EXPORT_SYMBOL ++0x73d69364 ring_buffer_change_overwrite vmlinux EXPORT_SYMBOL_GPL ++0x7fc827a5 __srcu_notifier_call_chain vmlinux EXPORT_SYMBOL_GPL ++0x5bc2e5a1 nf_ip6_checksum vmlinux EXPORT_SYMBOL ++0xeec2364d netpoll_send_skb_on_dev vmlinux EXPORT_SYMBOL ++0x7879bfc8 device_move vmlinux EXPORT_SYMBOL_GPL ++0xc19d6d2b scsi_cmd_ioctl vmlinux EXPORT_SYMBOL ++0x4a22c7b5 neigh_seq_stop vmlinux EXPORT_SYMBOL ++0xfad37936 usb_stor_clear_halt vmlinux EXPORT_SYMBOL_GPL ++0x77fa5d1f ns_to_timespec vmlinux EXPORT_SYMBOL ++0x95c6c48a qe_pin_set_gpio vmlinux EXPORT_SYMBOL ++0xed93f29e __kunmap_atomic vmlinux EXPORT_SYMBOL ++0x8ff80bf7 dev_mc_del_global vmlinux EXPORT_SYMBOL ++0x14880357 dev_mc_add_global vmlinux EXPORT_SYMBOL ++0x99525e3a vfsmount_lock_local_unlock vmlinux EXPORT_SYMBOL ++0xdb7cbcf1 blocking_notifier_chain_unregister vmlinux EXPORT_SYMBOL_GPL ++0x5651fb34 fifo_create_dflt vmlinux EXPORT_SYMBOL ++0x82a1419b neigh_table_init vmlinux EXPORT_SYMBOL ++0x89c4cbce mmc_register_driver vmlinux EXPORT_SYMBOL ++0x38a9c2c7 input_ff_effect_from_user vmlinux EXPORT_SYMBOL_GPL ++0x737e3d28 attribute_container_register vmlinux EXPORT_SYMBOL_GPL ++0x71da73ee blk_queue_segment_boundary vmlinux EXPORT_SYMBOL ++0x76c6ee5c blk_stop_queue vmlinux EXPORT_SYMBOL ++0x40979bcc blk_insert_request vmlinux EXPORT_SYMBOL ++0xea3210a9 blkcipher_walk_virt_block vmlinux EXPORT_SYMBOL_GPL ++0xa2bc62ac sysfs_create_link vmlinux EXPORT_SYMBOL_GPL ++0x3be9e6e8 task_active_pid_ns vmlinux EXPORT_SYMBOL_GPL ++0x94a08134 nf_nat_proto_nlattr_to_range net/ipv4/netfilter/nf_nat EXPORT_SYMBOL_GPL ++0x44dded3f svc_set_client vmlinux EXPORT_SYMBOL_GPL ++0x411b3b69 pci_add_dynid vmlinux EXPORT_SYMBOL_GPL ++0x6d294e43 clock_t_to_jiffies vmlinux EXPORT_SYMBOL ++0xe97f4ce5 qword_get vmlinux EXPORT_SYMBOL_GPL ++0x1f986505 ethtool_op_set_sg vmlinux EXPORT_SYMBOL ++0x4ccb8b94 pcim_iomap_table vmlinux EXPORT_SYMBOL ++0x669f27de crypto_larval_alloc vmlinux EXPORT_SYMBOL_GPL ++0xc7fdc711 journal_revoke vmlinux EXPORT_SYMBOL ++0x72aea9ce seq_release vmlinux EXPORT_SYMBOL ++0x3c5d0faa insert_inode_locked vmlinux EXPORT_SYMBOL ++0x4c3866c0 ring_buffer_size vmlinux EXPORT_SYMBOL_GPL ++0x838b13e7 ring_buffer_free vmlinux EXPORT_SYMBOL_GPL ++0x18852bcc module_layout vmlinux EXPORT_SYMBOL ++0x33945b7d xfrm_audit_state_notfound vmlinux EXPORT_SYMBOL_GPL ++0x37a8f9c9 hidinput_disconnect vmlinux EXPORT_SYMBOL_GPL ++0xcae03562 tun_get_socket drivers/net/tun EXPORT_SYMBOL_GPL ++0x0014c4da __blk_put_request vmlinux EXPORT_SYMBOL_GPL ++0x875ef85c elv_rb_latter_request vmlinux EXPORT_SYMBOL ++0x0ce1b711 sysfs_create_bin_file vmlinux EXPORT_SYMBOL_GPL ++0x66b2a859 nr_free_buffer_pages vmlinux EXPORT_SYMBOL_GPL ++0xeb8ae736 klist_init vmlinux EXPORT_SYMBOL_GPL ++0x0aabe623 xfrm_state_unregister_afinfo vmlinux EXPORT_SYMBOL ++0x60f4c230 of_find_node_by_name vmlinux EXPORT_SYMBOL ++0x83f9a3c9 serial8250_do_pm vmlinux EXPORT_SYMBOL ++0x05aa4eb1 pci_ltr_supported vmlinux EXPORT_SYMBOL ++0x6cdc5c6b nla_strlcpy vmlinux EXPORT_SYMBOL ++0xa46f2f1b kstrtouint vmlinux EXPORT_SYMBOL ++0x4121db0b blk_init_queue_node vmlinux EXPORT_SYMBOL ++0xe4a895fa up_write vmlinux EXPORT_SYMBOL ++0x7665e61c cpu_all_bits vmlinux EXPORT_SYMBOL ++0xb66350c3 auth_domain_put vmlinux EXPORT_SYMBOL_GPL ++0x4d8219f4 scsi_target_block vmlinux EXPORT_SYMBOL_GPL ++0x00d4f811 scsi_prep_state_check vmlinux EXPORT_SYMBOL ++0x8176ea3f free_buffer_head vmlinux EXPORT_SYMBOL ++0x6e4b5afd fget vmlinux EXPORT_SYMBOL ++0xfa1eb910 unregister_syscore_ops vmlinux EXPORT_SYMBOL_GPL ++0x44e9a829 match_token vmlinux EXPORT_SYMBOL ++0x2332418c vmtruncate vmlinux EXPORT_SYMBOL ++0xdbb24fc2 down_write vmlinux EXPORT_SYMBOL ++0xcaf2fc3d ip_route_output_flow vmlinux EXPORT_SYMBOL_GPL ++0x1b9e0ff1 scsilun_to_int vmlinux EXPORT_SYMBOL ++0x3b4572b8 posix_test_lock vmlinux EXPORT_SYMBOL ++0xd127c42a kill_block_super vmlinux EXPORT_SYMBOL ++0x14b68061 flush_signals vmlinux EXPORT_SYMBOL ++0x8c724794 nf_ct_remove_expectations net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x843a658f neigh_lookup_nodev vmlinux EXPORT_SYMBOL ++0x1b52b0d2 kernel_setsockopt vmlinux EXPORT_SYMBOL ++0xfab0ef6e kernel_getsockopt vmlinux EXPORT_SYMBOL ++0x9e4bdfff kernel_sock_ioctl vmlinux EXPORT_SYMBOL ++0x7c9208ff usb_stor_disconnect vmlinux EXPORT_SYMBOL_GPL ++0xcf39c94b mb_cache_entry_insert vmlinux EXPORT_SYMBOL ++0x5242d3b7 kallsyms_on_each_symbol vmlinux EXPORT_SYMBOL_GPL ++0xd2a8caf0 work_on_cpu vmlinux EXPORT_SYMBOL_GPL ++0x59de3119 nfnetlink_unicast net/netfilter/nfnetlink EXPORT_SYMBOL_GPL ++0xab694444 bsearch vmlinux EXPORT_SYMBOL ++0xf3dff1a3 blk_put_request vmlinux EXPORT_SYMBOL ++0x9f40a6d6 async_synchronize_full_domain vmlinux EXPORT_SYMBOL_GPL ++0x6974ef19 usb_serial_generic_throttle vmlinux EXPORT_SYMBOL_GPL ++0xf5fce407 crypto_create_tfm vmlinux EXPORT_SYMBOL_GPL ++0xa3a2d9af walk_system_ram_range vmlinux EXPORT_SYMBOL_GPL ++0xa2dc5981 of_get_cpu_node vmlinux EXPORT_SYMBOL ++0x363380e6 nf_conntrack_in net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xb77ba3a1 sock_queue_rcv_skb vmlinux EXPORT_SYMBOL ++0xfcd35070 blk_limits_io_min vmlinux EXPORT_SYMBOL ++0x05871953 sysfs_remove_files vmlinux EXPORT_SYMBOL_GPL ++0xa3f9df4e mapping_tagged vmlinux EXPORT_SYMBOL ++0x02d848d4 rpc_setbufsize vmlinux EXPORT_SYMBOL_GPL ++0x115258a5 put_disk vmlinux EXPORT_SYMBOL ++0xd9605d4c add_timer vmlinux EXPORT_SYMBOL ++0xabfbc63f irq_find_host vmlinux EXPORT_SYMBOL_GPL ++0x86d76ed4 hid_allocate_device vmlinux EXPORT_SYMBOL_GPL ++0xaaa509d1 spi_sync vmlinux EXPORT_SYMBOL_GPL ++0x732b7833 irq_cpu_rmap_add vmlinux EXPORT_SYMBOL ++0x9ba7089d argv_split vmlinux EXPORT_SYMBOL ++0xf6882e97 blk_queue_max_hw_sectors vmlinux EXPORT_SYMBOL ++0x31a89d59 rpc_debug vmlinux EXPORT_SYMBOL_GPL ++0x223326b1 svc_xprt_enqueue vmlinux EXPORT_SYMBOL_GPL ++0x162a441b bus_create_file vmlinux EXPORT_SYMBOL_GPL ++0x4872ee63 crypto_aes_set_key vmlinux EXPORT_SYMBOL_GPL ++0x5086ac3a alg_test vmlinux EXPORT_SYMBOL_GPL ++0xbef43296 console_conditional_schedule vmlinux EXPORT_SYMBOL ++0x774f22b3 svc_destroy vmlinux EXPORT_SYMBOL_GPL ++0xabb8322f pci_target_state vmlinux EXPORT_SYMBOL ++0xf2ec5b45 blkdev_issue_discard vmlinux EXPORT_SYMBOL ++0x38871428 crypto_unregister_pcomp vmlinux EXPORT_SYMBOL_GPL ++0xdf62a75b debugfs_create_symlink vmlinux EXPORT_SYMBOL_GPL ++0xece345ed fat_detach vmlinux EXPORT_SYMBOL_GPL ++0x698a899f ring_buffer_peek vmlinux EXPORT_SYMBOL_GPL ++0x96937cf7 xt_request_find_match vmlinux EXPORT_SYMBOL_GPL ++0x278d3cc1 writeback_inodes_sb_nr_if_idle vmlinux EXPORT_SYMBOL ++0x8b1b0eea xattr_getsecurity vmlinux EXPORT_SYMBOL_GPL ++0x6228c21f smp_call_function_single vmlinux EXPORT_SYMBOL ++0xc0580937 rb_erase vmlinux EXPORT_SYMBOL ++0x46a23e08 fsnotify_alloc_group vmlinux EXPORT_SYMBOL_GPL ++0xaafdc258 strcasecmp vmlinux EXPORT_SYMBOL ++0x962a13e8 save_mount_options vmlinux EXPORT_SYMBOL ++0xf69dd1ab clockevents_register_device vmlinux EXPORT_SYMBOL_GPL ++0x5672add2 nf_conntrack_set_hashsize net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xe5cf9c6b cache_check vmlinux EXPORT_SYMBOL_GPL ++0x4bc96635 ifla_policy vmlinux EXPORT_SYMBOL ++0x35cb4429 tty_unthrottle vmlinux EXPORT_SYMBOL ++0xdd9d1ca1 set_blocksize vmlinux EXPORT_SYMBOL ++0x8e13511f block_page_mkwrite vmlinux EXPORT_SYMBOL ++0x85b9e216 set_timer_slack vmlinux EXPORT_SYMBOL_GPL ++0x0569dca2 class_compat_remove_link vmlinux EXPORT_SYMBOL_GPL ++0x7d5c1ae6 uart_unregister_driver vmlinux EXPORT_SYMBOL ++0x6fd7b2a5 crypto_spawn_tfm vmlinux EXPORT_SYMBOL_GPL ++0x2e77637b generic_error_remove_page vmlinux EXPORT_SYMBOL ++0xcc344f76 nf_ct_nat_offset net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x4fb169f5 ipv6_chk_prefix vmlinux EXPORT_SYMBOL ++0xed1bfd69 ip6_dst_lookup_flow vmlinux EXPORT_SYMBOL_GPL ++0x39d847fa inet_csk_search_req vmlinux EXPORT_SYMBOL_GPL ++0x6ddfd8bc inet_unhash vmlinux EXPORT_SYMBOL_GPL ++0x6aed133e mdio_bus_type vmlinux EXPORT_SYMBOL ++0xf8ccb652 blk_execute_rq vmlinux EXPORT_SYMBOL ++0x993019f7 rpc_call_sync vmlinux EXPORT_SYMBOL_GPL ++0xef6a7e95 ip6_xmit vmlinux EXPORT_SYMBOL ++0xb5044271 vsscanf vmlinux EXPORT_SYMBOL ++0xa583f8ce seq_open_net vmlinux EXPORT_SYMBOL_GPL ++0x82d79b51 sysctl_vfs_cache_pressure vmlinux EXPORT_SYMBOL_GPL ++0x04486e88 rcu_batches_completed vmlinux EXPORT_SYMBOL_GPL ++0x0e52592a panic vmlinux EXPORT_SYMBOL ++0x96dbcca2 ioremap_prot vmlinux EXPORT_SYMBOL ++0x97f6197b pci_set_dma_seg_boundary vmlinux EXPORT_SYMBOL ++0x5c265cba sg_init_one vmlinux EXPORT_SYMBOL ++0x12da5bb2 __kmalloc vmlinux EXPORT_SYMBOL ++0x26477c07 __vmalloc vmlinux EXPORT_SYMBOL ++0xc19db54a kobject_init_and_add vmlinux EXPORT_SYMBOL_GPL ++0x0aa2fcd3 rpc_wake_up_next vmlinux EXPORT_SYMBOL_GPL ++0x7da4ef46 __ip_select_ident vmlinux EXPORT_SYMBOL ++0x81fb8fe5 skb_gro_receive vmlinux EXPORT_SYMBOL_GPL ++0xbe7e6656 pci_find_ht_capability vmlinux EXPORT_SYMBOL_GPL ++0x066cab2a pci_find_next_ht_capability vmlinux EXPORT_SYMBOL_GPL ++0x18765207 journal_load vmlinux EXPORT_SYMBOL ++0xd9bdbb86 flock_lock_file_wait vmlinux EXPORT_SYMBOL ++0x81f1044c xt_find_match vmlinux EXPORT_SYMBOL ++0x21de11a8 __skb_warn_lro_forwarding vmlinux EXPORT_SYMBOL ++0xbe6f064d idr_for_each vmlinux EXPORT_SYMBOL ++0xf3013d91 shash_ahash_digest vmlinux EXPORT_SYMBOL_GPL ++0x5fcadf66 locks_init_lock vmlinux EXPORT_SYMBOL ++0xfede227a bio_add_pc_page vmlinux EXPORT_SYMBOL ++0x71c90087 memcmp vmlinux EXPORT_SYMBOL ++0x77ec2fe2 netif_stacked_transfer_operstate vmlinux EXPORT_SYMBOL ++0xf5fc2242 d_alloc_name vmlinux EXPORT_SYMBOL ++0xaa6e4df5 _raw_write_lock_irqsave vmlinux EXPORT_SYMBOL ++0xc0a0f334 napi_frags_finish vmlinux EXPORT_SYMBOL ++0xce7ce037 of_translate_address vmlinux EXPORT_SYMBOL ++0xaba0a17d devm_ioport_unmap vmlinux EXPORT_SYMBOL ++0xe809a0f7 cont_write_begin vmlinux EXPORT_SYMBOL ++0x9a48be6f vfs_readdir vmlinux EXPORT_SYMBOL ++0x881039d0 zlib_inflate vmlinux EXPORT_SYMBOL ++0xa43b1297 vscnprintf vmlinux EXPORT_SYMBOL ++0xee4fe3e4 blk_recount_segments vmlinux EXPORT_SYMBOL ++0x94a1af32 simple_statfs vmlinux EXPORT_SYMBOL ++0x3e0e9023 param_set_long vmlinux EXPORT_SYMBOL ++0xd8326202 xfrm6_tunnel_deregister net/ipv6/tunnel6 EXPORT_SYMBOL ++0x3b5a4e82 xfrm4_tunnel_deregister net/ipv4/tunnel4 EXPORT_SYMBOL ++0x5b14ec1a rpc_put_mount vmlinux EXPORT_SYMBOL_GPL ++0x602cf2ee km_policy_notify vmlinux EXPORT_SYMBOL ++0xa47d64bf ip_mc_join_group vmlinux EXPORT_SYMBOL ++0xc099fc6f usb_is_intel_switchable_xhci vmlinux EXPORT_SYMBOL_GPL ++0x3244fd7d usb_string vmlinux EXPORT_SYMBOL_GPL ++0xdb760f52 __kfifo_free vmlinux EXPORT_SYMBOL ++0x0b8fef76 nf_ct_unexpect_related net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x328d3c91 inet_csk_reqsk_queue_hash_add vmlinux EXPORT_SYMBOL_GPL ++0xe6e1c5fe uuid_be_gen vmlinux EXPORT_SYMBOL_GPL ++0xa6fb4d71 debugfs_remove vmlinux EXPORT_SYMBOL_GPL ++0x2f4ac4ea lease_modify vmlinux EXPORT_SYMBOL ++0xf441ac43 ioread8_rep vmlinux EXPORT_SYMBOL ++0x979eddb8 xfrm_dst_ifdown vmlinux EXPORT_SYMBOL ++0x64f428d3 neigh_seq_start vmlinux EXPORT_SYMBOL ++0x59825b9a pci_assign_unassigned_bridge_resources vmlinux EXPORT_SYMBOL_GPL ++0x3f0546a8 ioread32_rep vmlinux EXPORT_SYMBOL ++0xfe7887e9 rpc_put_task vmlinux EXPORT_SYMBOL_GPL ++0xf9f40caa eth_header_cache_update vmlinux EXPORT_SYMBOL ++0xb31526ee sg_copy_from_buffer vmlinux EXPORT_SYMBOL ++0x73e20c1c strlcpy vmlinux EXPORT_SYMBOL ++0x8abacc47 get_max_files vmlinux EXPORT_SYMBOL_GPL ++0x328a05f1 strncpy vmlinux EXPORT_SYMBOL ++0x548a40b6 scsi_release_buffers vmlinux EXPORT_SYMBOL ++0x13574bbf nf_net_netfilter_sysctl_path vmlinux EXPORT_SYMBOL_GPL ++0x738196bf driver_create_file vmlinux EXPORT_SYMBOL_GPL ++0x7193680a kern_mount_data vmlinux EXPORT_SYMBOL_GPL ++0x8ef33ff8 __init_kthread_worker vmlinux EXPORT_SYMBOL_GPL ++0xa10f05a8 par_io_of_config vmlinux EXPORT_SYMBOL ++0xf6367114 blk_requeue_request vmlinux EXPORT_SYMBOL ++0x84fc4fe5 insert_inode_locked4 vmlinux EXPORT_SYMBOL ++0x41482d8b strndup_user vmlinux EXPORT_SYMBOL ++0xddd58dc0 ring_buffer_reset vmlinux EXPORT_SYMBOL_GPL ++0xfae9f8ef crypto_init_spawn vmlinux EXPORT_SYMBOL_GPL ++0x9c78b4da mount_nodev vmlinux EXPORT_SYMBOL ++0xf40fbfa7 pagevec_lookup vmlinux EXPORT_SYMBOL ++0x376591a1 xfrm_find_acq vmlinux EXPORT_SYMBOL ++0xaf7abced eth_mac_addr vmlinux EXPORT_SYMBOL ++0xe7a0dd2c scsi_scan_host vmlinux EXPORT_SYMBOL ++0xa22fa240 scsi_setup_fs_cmnd vmlinux EXPORT_SYMBOL ++0xebf65040 svc_xprt_received vmlinux EXPORT_SYMBOL_GPL ++0x12c92332 tcp_sendpage vmlinux EXPORT_SYMBOL ++0xb98a0185 rtc_tm_to_time vmlinux EXPORT_SYMBOL ++0xe5883bd9 class_compat_unregister vmlinux EXPORT_SYMBOL_GPL ++0x47b3f862 radix_tree_lookup_slot vmlinux EXPORT_SYMBOL ++0x91621d6a allocate_resource vmlinux EXPORT_SYMBOL ++0xc08647ff ring_buffer_bytes_cpu vmlinux EXPORT_SYMBOL_GPL ++0x02d81845 audit_log_task_context vmlinux EXPORT_SYMBOL ++0x6b13f214 task_ns_capable vmlinux EXPORT_SYMBOL ++0x49a08acf spi_write_then_read vmlinux EXPORT_SYMBOL_GPL ++0x264aab93 mtd_device_parse_register vmlinux EXPORT_SYMBOL_GPL ++0x40946686 splice_from_pipe_feed vmlinux EXPORT_SYMBOL ++0xf9a054b5 __round_jiffies vmlinux EXPORT_SYMBOL_GPL ++0xfe822d55 get_brgfreq vmlinux EXPORT_SYMBOL ++0x03c06156 bitmap_fold vmlinux EXPORT_SYMBOL ++0x734b6620 vfs_rmdir vmlinux EXPORT_SYMBOL ++0x92eb404f generic_shutdown_super vmlinux EXPORT_SYMBOL ++0x37e74642 get_jiffies_64 vmlinux EXPORT_SYMBOL ++0x3f3d5755 scsi_track_queue_full vmlinux EXPORT_SYMBOL ++0x45d4a34f init_buffer vmlinux EXPORT_SYMBOL ++0xfa2e134e __sock_recv_ts_and_drops vmlinux EXPORT_SYMBOL_GPL ++0xbf7fd2f5 schedule_timeout_killable vmlinux EXPORT_SYMBOL ++0xc14de4a4 rpcauth_create vmlinux EXPORT_SYMBOL_GPL ++0x286a504e sock_no_getname vmlinux EXPORT_SYMBOL ++0xb2abf6e7 vfs_link vmlinux EXPORT_SYMBOL ++0x85050965 __irq_alloc_descs vmlinux EXPORT_SYMBOL_GPL ++0x6e0778f8 call_usermodehelper_setup vmlinux EXPORT_SYMBOL ++0x46de0081 netlink_rcv_skb vmlinux EXPORT_SYMBOL ++0x7e7aea36 phy_driver_unregister vmlinux EXPORT_SYMBOL ++0xf82abc1d isa_dma_bridge_buggy vmlinux EXPORT_SYMBOL ++0x5aa2ba6e crypto_alloc_pcomp vmlinux EXPORT_SYMBOL_GPL ++0x0254aae8 journal_flush vmlinux EXPORT_SYMBOL ++0xedc2994d ktime_get_real vmlinux EXPORT_SYMBOL_GPL ++0x6258ff7a panic_notifier_list vmlinux EXPORT_SYMBOL ++0x493615f0 __xfrm_state_delete vmlinux EXPORT_SYMBOL ++0x91781620 unregister_mtd_chip_driver vmlinux EXPORT_SYMBOL ++0x82f776b7 gpio_export vmlinux EXPORT_SYMBOL_GPL ++0x8aee4b8e do_splice_from vmlinux EXPORT_SYMBOL_GPL ++0x5edbbeed d_delete vmlinux EXPORT_SYMBOL ++0x35829944 find_get_pages_tag vmlinux EXPORT_SYMBOL ++0xc8fd727e mod_timer vmlinux EXPORT_SYMBOL ++0x68e0e289 idr_remove vmlinux EXPORT_SYMBOL ++0xc61be59c ida_remove vmlinux EXPORT_SYMBOL ++0x76053cac mnt_set_expiry vmlinux EXPORT_SYMBOL ++0xd0ec1a6b use_mm vmlinux EXPORT_SYMBOL_GPL ++0x1d3865da param_get_invbool vmlinux EXPORT_SYMBOL ++0xcc964b37 flush_delayed_work_sync vmlinux EXPORT_SYMBOL ++0xbf9d1b96 nfsd_debug vmlinux EXPORT_SYMBOL_GPL ++0xb84fe6ac devres_destroy vmlinux EXPORT_SYMBOL_GPL ++0xbe3f06f3 tty_hangup vmlinux EXPORT_SYMBOL ++0x67d548bf pci_disable_device vmlinux EXPORT_SYMBOL ++0x873f76af add_page_wait_queue vmlinux EXPORT_SYMBOL_GPL ++0x1a2bc07b flush_tlb_mm vmlinux EXPORT_SYMBOL ++0x17643c44 mdiobus_read vmlinux EXPORT_SYMBOL ++0xd9bac924 tty_termios_copy_hw vmlinux EXPORT_SYMBOL ++0x2f8ebbe0 rpc_ntop vmlinux EXPORT_SYMBOL_GPL ++0x44ed046c rpc_pton vmlinux EXPORT_SYMBOL_GPL ++0xcfd9a2c0 des_ekey vmlinux EXPORT_SYMBOL_GPL ++0x1407c6e7 kmap_prot vmlinux EXPORT_SYMBOL ++0xf120872a dql_completed vmlinux EXPORT_SYMBOL ++0x43a939cc key_link vmlinux EXPORT_SYMBOL ++0x34a8b7a1 read_cache_page vmlinux EXPORT_SYMBOL ++0x1cfc799e dev_change_flags vmlinux EXPORT_SYMBOL ++0x801f5a3f __strncpy_from_user vmlinux EXPORT_SYMBOL ++0x41f9eb17 xfrm_state_walk vmlinux EXPORT_SYMBOL ++0x1165ba63 phy_scan_fixups vmlinux EXPORT_SYMBOL ++0x65420d1e nla_put_nohdr vmlinux EXPORT_SYMBOL ++0x98691115 napi_gro_flush vmlinux EXPORT_SYMBOL ++0xa51f1bdd scsi_set_medium_removal vmlinux EXPORT_SYMBOL ++0x77dab830 keyring_clear vmlinux EXPORT_SYMBOL ++0xff8862d7 rh_get_stats vmlinux EXPORT_SYMBOL_GPL ++0x8fbf37e0 profile_pc vmlinux EXPORT_SYMBOL ++0x6532831c gss_service_to_auth_domain_name vmlinux EXPORT_SYMBOL_GPL ++0x7e1183c9 async_schedule vmlinux EXPORT_SYMBOL_GPL ++0x9e1cfc90 ioremap_wc vmlinux EXPORT_SYMBOL ++0xa47434fb __nla_put vmlinux EXPORT_SYMBOL ++0x4c2ae700 strnstr vmlinux EXPORT_SYMBOL ++0xcbe78671 svc_sock_names vmlinux EXPORT_SYMBOL_GPL ++0x6415b696 inet_diag_register vmlinux EXPORT_SYMBOL_GPL ++0x41a855a9 sdhci_pltfm_unregister vmlinux EXPORT_SYMBOL_GPL ++0xf5222143 _raw_spin_lock_irqsave vmlinux EXPORT_SYMBOL ++0xe17482f0 tcp_done vmlinux EXPORT_SYMBOL_GPL ++0x7fdf3256 sysdev_show_ulong vmlinux EXPORT_SYMBOL_GPL ++0x2fb6de5d add_device_randomness vmlinux EXPORT_SYMBOL ++0xde417b81 async_schedule_domain vmlinux EXPORT_SYMBOL_GPL ++0x6ff5969a usb_init_urb vmlinux EXPORT_SYMBOL_GPL ++0xd4e0fb01 get_phy_id vmlinux EXPORT_SYMBOL ++0x35cca30f blk_free_tags vmlinux EXPORT_SYMBOL ++0xc0b2494c vfsmount_lock_lock_init vmlinux EXPORT_SYMBOL ++0xefdd5a63 ktime_get_ts vmlinux EXPORT_SYMBOL_GPL ++0xe7ce7439 _memcpy_fromio vmlinux EXPORT_SYMBOL ++0xe4ab69a4 usb_hcd_unmap_urb_setup_for_dma vmlinux EXPORT_SYMBOL_GPL ++0xadf804eb scsi_device_get vmlinux EXPORT_SYMBOL ++0xe2ab0f51 scsi_device_put vmlinux EXPORT_SYMBOL ++0x51ce5ad3 files_lglock_local_lock_cpu vmlinux EXPORT_SYMBOL ++0x37eab51b map_vm_area vmlinux EXPORT_SYMBOL_GPL ++0x0084e86d unregister_shrinker vmlinux EXPORT_SYMBOL ++0x05c1da0d isa_bridge_pcidev vmlinux EXPORT_SYMBOL_GPL ++0xcb1c9e78 ipv6_dev_get_saddr vmlinux EXPORT_SYMBOL ++0xcbbd7b2f xfrm_policy_flush vmlinux EXPORT_SYMBOL ++0xab5e43fc mmc_set_blocklen vmlinux EXPORT_SYMBOL ++0xb8aa2342 __check_region vmlinux EXPORT_SYMBOL ++0x328aa64c par_io_data_set vmlinux EXPORT_SYMBOL ++0x90dd262f nf_nat_protocol_register net/ipv4/netfilter/nf_nat EXPORT_SYMBOL ++0xf6388c56 sysctl_ip_default_ttl vmlinux EXPORT_SYMBOL ++0xba7ff9a8 napi_gro_frags vmlinux EXPORT_SYMBOL ++0x59923e50 pci_load_saved_state vmlinux EXPORT_SYMBOL_GPL ++0x15864b03 flex_array_get vmlinux EXPORT_SYMBOL ++0x0cf9a646 key_task_permission vmlinux EXPORT_SYMBOL ++0x9cbb7f29 nf_nat_protocol_unregister net/ipv4/netfilter/nf_nat EXPORT_SYMBOL ++0xfc464847 inet_diag_unregister vmlinux EXPORT_SYMBOL_GPL ++0x70a6efa3 sock_sendmsg vmlinux EXPORT_SYMBOL ++0x61308070 disk_get_part vmlinux EXPORT_SYMBOL_GPL ++0x2333005e netlink_kernel_release vmlinux EXPORT_SYMBOL ++0x0ffc7c8b __sock_create vmlinux EXPORT_SYMBOL ++0x190f4530 rtc_set_mmss vmlinux EXPORT_SYMBOL_GPL ++0x8384d453 pci_bus_resource_n vmlinux EXPORT_SYMBOL_GPL ++0x4289f7df down_interruptible vmlinux EXPORT_SYMBOL ++0x3064cd91 netif_carrier_off vmlinux EXPORT_SYMBOL ++0x26b9af4e mmc_request_done vmlinux EXPORT_SYMBOL ++0x46074c17 sdev_evt_alloc vmlinux EXPORT_SYMBOL_GPL ++0xa43e2c08 lease_get_mtime vmlinux EXPORT_SYMBOL ++0x17d3b09a sb_set_blocksize vmlinux EXPORT_SYMBOL ++0x850ac629 sdio_writew vmlinux EXPORT_SYMBOL_GPL ++0x3744cf36 vmalloc_to_pfn vmlinux EXPORT_SYMBOL ++0x4c18ad3a get_task_mm vmlinux EXPORT_SYMBOL_GPL ++0xe8b2187c nf_ct_expect_put net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xb9b9df41 usb_amd_dev_put vmlinux EXPORT_SYMBOL_GPL ++0x5a642ff0 crypto_unregister_alg vmlinux EXPORT_SYMBOL_GPL ++0x4484a83b dump_write vmlinux EXPORT_SYMBOL ++0x0fae7d45 lock_super vmlinux EXPORT_SYMBOL ++0xb8f92e75 __class_create vmlinux EXPORT_SYMBOL_GPL ++0x86e44713 filp_open vmlinux EXPORT_SYMBOL ++0xad91149b generic_file_aio_write vmlinux EXPORT_SYMBOL ++0x43af7a67 xfrm6_prepare_output vmlinux EXPORT_SYMBOL ++0x4d4fd5f1 xfrm_calg_get_byname vmlinux EXPORT_SYMBOL_GPL ++0xc6c1239b xfrm4_prepare_output vmlinux EXPORT_SYMBOL ++0x14665bed pci_read_vpd vmlinux EXPORT_SYMBOL ++0x51014234 get_disk vmlinux EXPORT_SYMBOL ++0xb2c3e937 __free_pages vmlinux EXPORT_SYMBOL ++0x4ff0cd36 inet_bind vmlinux EXPORT_SYMBOL ++0x034e17a5 qdisc_watchdog_init vmlinux EXPORT_SYMBOL ++0xe861f9ad class_find_device vmlinux EXPORT_SYMBOL_GPL ++0xfe3c4e28 __register_binfmt vmlinux EXPORT_SYMBOL ++0x058e4b7d xfrm_init_state vmlinux EXPORT_SYMBOL ++0x37ac26b3 pci_assign_resource vmlinux EXPORT_SYMBOL ++0x89ca47bf kstrtos8_from_user vmlinux EXPORT_SYMBOL ++0xff18ef68 crypto_init_spawn2 vmlinux EXPORT_SYMBOL_GPL ++0x358365c5 xfrm_user_policy vmlinux EXPORT_SYMBOL ++0x6117420a netif_notify_peers vmlinux EXPORT_SYMBOL ++0xf94b112b netif_napi_add vmlinux EXPORT_SYMBOL ++0x562ccd0e skb_split vmlinux EXPORT_SYMBOL ++0xf5b3060b input_grab_device vmlinux EXPORT_SYMBOL ++0xa177bc19 default_mtd_writev vmlinux EXPORT_SYMBOL_GPL ++0x2376e92b tty_port_block_til_ready vmlinux EXPORT_SYMBOL ++0x81b22cf9 journal_try_to_free_buffers vmlinux EXPORT_SYMBOL ++0xf10de535 ioread8 vmlinux EXPORT_SYMBOL ++0x686c703f xfrm_count_auth_supported vmlinux EXPORT_SYMBOL_GPL ++0x8c10c6f6 netlink_broadcast vmlinux EXPORT_SYMBOL ++0x66645e38 of_property_read_string_index vmlinux EXPORT_SYMBOL_GPL ++0x0343bdf1 __i2c_board_list vmlinux EXPORT_SYMBOL_GPL ++0xa07bb953 block_write_full_page_endio vmlinux EXPORT_SYMBOL ++0x317a1174 shmem_file_setup vmlinux EXPORT_SYMBOL_GPL ++0xc3cf1128 in_group_p vmlinux EXPORT_SYMBOL ++0xc631580a console_unlock vmlinux EXPORT_SYMBOL ++0x9524b0ae _outsb vmlinux EXPORT_SYMBOL ++0xcfea9e86 udp_sendmsg vmlinux EXPORT_SYMBOL ++0x318394d8 mmc_start_req vmlinux EXPORT_SYMBOL ++0xbdfcce9d elv_rb_former_request vmlinux EXPORT_SYMBOL ++0x35fbd6a1 __kfifo_dma_out_prepare_r vmlinux EXPORT_SYMBOL ++0xf34bd1d5 dcb_ieee_setapp vmlinux EXPORT_SYMBOL ++0xcbb30a2b dcb_ieee_delapp vmlinux EXPORT_SYMBOL ++0xf53d4c26 qdisc_class_hash_destroy vmlinux EXPORT_SYMBOL ++0xcc26e5cf sdio_register_driver vmlinux EXPORT_SYMBOL_GPL ++0x50deef5c usb_kill_urb vmlinux EXPORT_SYMBOL_GPL ++0xa87e68e1 usb_get_intf vmlinux EXPORT_SYMBOL_GPL ++0x9e607910 audit_log vmlinux EXPORT_SYMBOL ++0x767b18fb set_security_override_from_ctx vmlinux EXPORT_SYMBOL ++0x5ab3b29b xdr_process_buf vmlinux EXPORT_SYMBOL_GPL ++0x065f3688 sk_wait_data vmlinux EXPORT_SYMBOL ++0xc724970d pci_enable_obff vmlinux EXPORT_SYMBOL ++0x762ea593 crypto_remove_spawns vmlinux EXPORT_SYMBOL_GPL ++0x4fd4e89d ring_buffer_empty_cpu vmlinux EXPORT_SYMBOL_GPL ++0x0f28cb91 nvram_read_byte vmlinux EXPORT_SYMBOL ++0xc390630a xt_replace_table vmlinux EXPORT_SYMBOL_GPL ++0xf9943f1b __netpoll_setup vmlinux EXPORT_SYMBOL_GPL ++0x08cc84e7 __percpu_counter_init vmlinux EXPORT_SYMBOL ++0x6d6c930c irq_set_affinity_notifier vmlinux EXPORT_SYMBOL_GPL ++0x698fe0cc inet_hashinfo_init vmlinux EXPORT_SYMBOL_GPL ++0x262e9a73 input_mt_report_pointer_emulation vmlinux EXPORT_SYMBOL ++0x333bf31b usb_stor_bulk_transfer_sg vmlinux EXPORT_SYMBOL_GPL ++0x56cd1a50 pci_ioremap_bar vmlinux EXPORT_SYMBOL_GPL ++0xadd2969f end_buffer_read_sync vmlinux EXPORT_SYMBOL ++0x227badd6 mod_timer_pinned vmlinux EXPORT_SYMBOL ++0x8276963f set_cpus_allowed_ptr vmlinux EXPORT_SYMBOL_GPL ++0xfd168974 neigh_for_each vmlinux EXPORT_SYMBOL ++0x7e8699a8 rtc_initialize_alarm vmlinux EXPORT_SYMBOL_GPL ++0x6971447a rtc_month_days vmlinux EXPORT_SYMBOL ++0x7e64181d usb_calc_bus_time vmlinux EXPORT_SYMBOL_GPL ++0xabc7e656 sg_miter_next vmlinux EXPORT_SYMBOL ++0xdd8e46ba crypto_init_shash_spawn vmlinux EXPORT_SYMBOL_GPL ++0xe9b01876 crypto_init_ahash_spawn vmlinux EXPORT_SYMBOL_GPL ++0x6e50cff7 posix_timers_register_clock vmlinux EXPORT_SYMBOL_GPL ++0x8ff66782 param_get_ushort vmlinux EXPORT_SYMBOL ++0xe6dd236d clear_pages vmlinux EXPORT_SYMBOL ++0x67ef2a40 svc_sock_update_bufs vmlinux EXPORT_SYMBOL_GPL ++0x5c27b6d6 skb_pull vmlinux EXPORT_SYMBOL ++0x2aa1292b usb_find_interface vmlinux EXPORT_SYMBOL_GPL ++0x8574ca6c gpio_request_array vmlinux EXPORT_SYMBOL_GPL ++0xd988b61f swiotlb_unmap_page vmlinux EXPORT_SYMBOL_GPL ++0x6da928f4 _insw_ns vmlinux EXPORT_SYMBOL ++0x05a514a1 _insl_ns vmlinux EXPORT_SYMBOL ++0x93d2422d snmp_mib_free vmlinux EXPORT_SYMBOL_GPL ++0x1e41fddb neigh_app_ns vmlinux EXPORT_SYMBOL ++0xc9501ade phy_start_interrupts vmlinux EXPORT_SYMBOL ++0x09d998e1 scsi_get_vpd_page vmlinux EXPORT_SYMBOL_GPL ++0x9dfdf722 gpio_free_array vmlinux EXPORT_SYMBOL_GPL ++0x5d51bcf7 scatterwalk_start vmlinux EXPORT_SYMBOL_GPL ++0x53472771 sysfs_put vmlinux EXPORT_SYMBOL_GPL ++0x526c437a xfrm_state_check_expire vmlinux EXPORT_SYMBOL ++0x393c4c4e netdev_boot_setup_check vmlinux EXPORT_SYMBOL ++0x1ef1100f sock_i_uid vmlinux EXPORT_SYMBOL ++0xf4009166 sock_i_ino vmlinux EXPORT_SYMBOL ++0xc046033e seq_bitmap vmlinux EXPORT_SYMBOL ++0x3942b0c9 ip_build_and_send_pkt vmlinux EXPORT_SYMBOL_GPL ++0xb93c76a8 register_gifconf vmlinux EXPORT_SYMBOL ++0xcd07f6b1 gpiochip_find vmlinux EXPORT_SYMBOL_GPL ++0x292be0eb crypto_rng_type vmlinux EXPORT_SYMBOL_GPL ++0x457594fa crypto_alg_list vmlinux EXPORT_SYMBOL_GPL ++0xc04e7aa9 sync_inode_metadata vmlinux EXPORT_SYMBOL ++0xafff3d1d mempool_alloc vmlinux EXPORT_SYMBOL ++0x86f6b99d synchronize_rcu_expedited vmlinux EXPORT_SYMBOL_GPL ++0xaa6901ac __kfifo_out_r vmlinux EXPORT_SYMBOL ++0x52f1bf6b __srcu_read_lock vmlinux EXPORT_SYMBOL_GPL ++0xd03c7700 secure_ipv4_port_ephemeral vmlinux EXPORT_SYMBOL_GPL ++0x79578100 proc_dointvec_minmax vmlinux EXPORT_SYMBOL ++0x8581db4c i2c_bus_type vmlinux EXPORT_SYMBOL_GPL ++0xcd898fd4 do_truncate vmlinux EXPORT_SYMBOL_GPL ++0x7cd81e29 kmalloc_caches vmlinux EXPORT_SYMBOL ++0xdc43a9c8 daemonize vmlinux EXPORT_SYMBOL ++0x390dd42a rpc_malloc vmlinux EXPORT_SYMBOL_GPL ++0xb2390b29 icmpv6_send vmlinux EXPORT_SYMBOL ++0x19ade8fc put_driver vmlinux EXPORT_SYMBOL_GPL ++0xc00f7d59 blk_queue_make_request vmlinux EXPORT_SYMBOL ++0x9cb013cc put_page vmlinux EXPORT_SYMBOL ++0x74954462 timecounter_read vmlinux EXPORT_SYMBOL_GPL ++0x6fff8279 nf_conntrack_lock net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xab930e2e rpc_lookup_cred vmlinux EXPORT_SYMBOL_GPL ++0x801c8645 rtc_device_register vmlinux EXPORT_SYMBOL_GPL ++0x445fc790 input_reset_device vmlinux EXPORT_SYMBOL ++0xbc8a443b tty_ldisc_deref vmlinux EXPORT_SYMBOL_GPL ++0x7b645a57 vfs_getattr vmlinux EXPORT_SYMBOL ++0x31f79892 pci_domain_nr vmlinux EXPORT_SYMBOL ++0x5b582800 inet_del_protocol vmlinux EXPORT_SYMBOL ++0x03b7b2e4 neigh_update vmlinux EXPORT_SYMBOL ++0xe03951df phy_stop vmlinux EXPORT_SYMBOL ++0xcce40c42 put_io_context vmlinux EXPORT_SYMBOL ++0x5baf344d blk_queue_io_min vmlinux EXPORT_SYMBOL ++0xf9fbdc25 nobh_truncate_page vmlinux EXPORT_SYMBOL ++0xc9b8c308 __kfifo_dma_out_prepare vmlinux EXPORT_SYMBOL ++0x045072cd nf_ct_port_nla_policy net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xdfaecb3e ethtool_op_set_tx_hw_csum vmlinux EXPORT_SYMBOL ++0x5412c7c7 up vmlinux EXPORT_SYMBOL ++0x23f5e02a rpc_call_start vmlinux EXPORT_SYMBOL_GPL ++0x8eed1f0d icmp_send vmlinux EXPORT_SYMBOL ++0x1ed928f6 nfs4_set_ds_client vmlinux EXPORT_SYMBOL_GPL ++0x98d5de4f path_get vmlinux EXPORT_SYMBOL ++0x07077c7d iov_iter_copy_from_user_atomic vmlinux EXPORT_SYMBOL ++0x93a2cb47 reserve_pmc_hardware vmlinux EXPORT_SYMBOL_GPL ++0xa726ec8b xfrm_state_update vmlinux EXPORT_SYMBOL ++0x8a74500b usb_deregister_dev vmlinux EXPORT_SYMBOL_GPL ++0x3e2e9995 usb_hcd_is_primary_hcd vmlinux EXPORT_SYMBOL_GPL ++0x9f7d9edf crypto_grab_aead vmlinux EXPORT_SYMBOL_GPL ++0x9c57851d hrtimer_start vmlinux EXPORT_SYMBOL_GPL ++0x0a43ebfc get_pid_task vmlinux EXPORT_SYMBOL_GPL ++0x6c702af7 sysctl_udp_rmem_min vmlinux EXPORT_SYMBOL ++0x6f4d5b8b dev_open vmlinux EXPORT_SYMBOL ++0x25ae2be1 lock_sock_fast vmlinux EXPORT_SYMBOL ++0x65a76805 ilookup vmlinux EXPORT_SYMBOL ++0x4302d0eb free_pages vmlinux EXPORT_SYMBOL ++0xbfc177bc iowrite32_rep vmlinux EXPORT_SYMBOL ++0x8cc79cab iowrite16_rep vmlinux EXPORT_SYMBOL ++0x4e7df11b irq_create_of_mapping vmlinux EXPORT_SYMBOL_GPL ++0x4b48ebf0 of_irq_map_pci vmlinux EXPORT_SYMBOL_GPL ++0x6e999abc mdiobus_free vmlinux EXPORT_SYMBOL ++0x8d610fe8 generic_file_fsync vmlinux EXPORT_SYMBOL ++0x96b22cab unlock_new_inode vmlinux EXPORT_SYMBOL ++0x3f3633b3 __f_setown vmlinux EXPORT_SYMBOL ++0xf82f16b3 execute_in_process_context vmlinux EXPORT_SYMBOL_GPL ++0x11f3795f xt_find_table_lock vmlinux EXPORT_SYMBOL_GPL ++0x62737e1d sock_unregister vmlinux EXPORT_SYMBOL ++0x760a3bf8 kset_register vmlinux EXPORT_SYMBOL ++0xf2e55f98 fput vmlinux EXPORT_SYMBOL ++0x6cf0d67d qe_get_num_of_snums vmlinux EXPORT_SYMBOL ++0x6b3ec69d platform_device_alloc vmlinux EXPORT_SYMBOL_GPL ++0x60da3cf0 posix_timer_event vmlinux EXPORT_SYMBOL_GPL ++0x52e15131 ip6_frag_init vmlinux EXPORT_SYMBOL ++0x234bde50 journal_set_features vmlinux EXPORT_SYMBOL ++0x4cd38ab6 __fsnotify_parent vmlinux EXPORT_SYMBOL_GPL ++0xb78c61e8 param_ops_bool vmlinux EXPORT_SYMBOL ++0xa4274b10 usb_ep0_reinit vmlinux EXPORT_SYMBOL_GPL ++0x8b92c65b add_disk vmlinux EXPORT_SYMBOL ++0x3e1dd4ab xt_rateest_put net/netfilter/xt_RATEEST EXPORT_SYMBOL_GPL ++0xe23deb2d inet_shutdown vmlinux EXPORT_SYMBOL ++0x33ee9189 posix_lock_file_wait vmlinux EXPORT_SYMBOL ++0xc079de49 inet_csk_clone vmlinux EXPORT_SYMBOL_GPL ++0x5dc54a6c xt_unregister_table vmlinux EXPORT_SYMBOL_GPL ++0x2c5b1d98 uart_remove_one_port vmlinux EXPORT_SYMBOL ++0x4e830a3e strnicmp vmlinux EXPORT_SYMBOL ++0x4ef107d9 vmalloc_to_page vmlinux EXPORT_SYMBOL ++0x00a15cc7 usb_get_hcd vmlinux EXPORT_SYMBOL_GPL ++0x9b5913f9 blk_update_request vmlinux EXPORT_SYMBOL_GPL ++0x45c43667 journal_start_commit vmlinux EXPORT_SYMBOL ++0x235e90f3 __wake_up_bit vmlinux EXPORT_SYMBOL ++0x71504b18 xdr_encode_array2 vmlinux EXPORT_SYMBOL_GPL ++0x661a2f0b sock_release vmlinux EXPORT_SYMBOL ++0x56039b1c usb_hcd_giveback_urb vmlinux EXPORT_SYMBOL_GPL ++0x59423726 user_instantiate vmlinux EXPORT_SYMBOL_GPL ++0x75994700 add_wait_queue_exclusive vmlinux EXPORT_SYMBOL ++0xdc9b0085 nf_nat_icmp_reply_translation net/ipv4/netfilter/nf_nat EXPORT_SYMBOL_GPL ++0x34908c14 print_hex_dump_bytes vmlinux EXPORT_SYMBOL ++0x4a37f460 nlmclnt_proc vmlinux EXPORT_SYMBOL_GPL ++0x62118f48 d_add_ci vmlinux EXPORT_SYMBOL ++0xb5020657 phys_mem_access_prot vmlinux EXPORT_SYMBOL ++0x5e6947f7 unregister_dcbevent_notifier vmlinux EXPORT_SYMBOL ++0x017543f0 net_ipv6_ctl_path vmlinux EXPORT_SYMBOL_GPL ++0xa9f3f261 net_ipv4_ctl_path vmlinux EXPORT_SYMBOL_GPL ++0x5243725c netdev_set_master vmlinux EXPORT_SYMBOL ++0x82939f08 __skb_checksum_complete_head vmlinux EXPORT_SYMBOL ++0xe053341e swiotlb_map_sg vmlinux EXPORT_SYMBOL ++0x7c9ac32e __percpu_counter_sum vmlinux EXPORT_SYMBOL ++0xb770be3e __percpu_counter_add vmlinux EXPORT_SYMBOL ++0x9d9c9597 idr_init vmlinux EXPORT_SYMBOL ++0xeaf16558 ida_init vmlinux EXPORT_SYMBOL ++0x9a19604d mpage_readpage vmlinux EXPORT_SYMBOL ++0x70bc17d7 inode_wait vmlinux EXPORT_SYMBOL ++0xd6ee688f vmalloc vmlinux EXPORT_SYMBOL ++0xf31b3fd1 workqueue_set_max_active vmlinux EXPORT_SYMBOL_GPL ++0xe10c1552 tty_port_raise_dtr_rts vmlinux EXPORT_SYMBOL ++0xb32bff81 pci_request_region vmlinux EXPORT_SYMBOL ++0xfa83da2c blk_queue_io_opt vmlinux EXPORT_SYMBOL ++0xd4c14632 system_unbound_wq vmlinux EXPORT_SYMBOL_GPL ++0x576da704 cpm_muram_dma vmlinux EXPORT_SYMBOL ++0xe7420df4 scsi_adjust_queue_depth vmlinux EXPORT_SYMBOL ++0xeae958fa mb_cache_entry_find_first vmlinux EXPORT_SYMBOL ++0x10e22972 gss_mech_get_by_name vmlinux EXPORT_SYMBOL_GPL ++0xc8910e47 tcp_unregister_congestion_control vmlinux EXPORT_SYMBOL_GPL ++0x28811101 bio_split vmlinux EXPORT_SYMBOL ++0x02456663 lock_rename vmlinux EXPORT_SYMBOL ++0x1ab0d653 class_destroy vmlinux EXPORT_SYMBOL_GPL ++0x584637d7 pci_pme_active vmlinux EXPORT_SYMBOL ++0x864fd4d7 gpiochip_remove vmlinux EXPORT_SYMBOL_GPL ++0xae93b4d8 __locks_copy_lock vmlinux EXPORT_SYMBOL ++0x83df0d38 mutex_lock_killable vmlinux EXPORT_SYMBOL ++0xa17874dd nf_ct_remove_userspace_expectations net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xcc9846dc xdr_inline_decode vmlinux EXPORT_SYMBOL_GPL ++0x070f6230 tcp_check_req vmlinux EXPORT_SYMBOL ++0x4fc41dd7 netlink_unicast vmlinux EXPORT_SYMBOL ++0x6c03f58c neigh_sysctl_register vmlinux EXPORT_SYMBOL ++0x534f54dd usb_serial_generic_read_bulk_callback vmlinux EXPORT_SYMBOL_GPL ++0xdcb0349b sys_close vmlinux EXPORT_SYMBOL ++0x3f2c31ce kill_pgrp vmlinux EXPORT_SYMBOL ++0x512c741a ppc_md vmlinux EXPORT_SYMBOL ++0x09959de7 fat_build_inode vmlinux EXPORT_SYMBOL_GPL ++0xd34ed65a seq_read vmlinux EXPORT_SYMBOL ++0x7d19ed18 is_bad_inode vmlinux EXPORT_SYMBOL ++0xf612809a param_get_int vmlinux EXPORT_SYMBOL ++0x915e1208 tb_ticks_per_usec vmlinux EXPORT_SYMBOL ++0xeb903aa6 start_tty vmlinux EXPORT_SYMBOL ++0x7ffc8718 gpio_set_debounce vmlinux EXPORT_SYMBOL_GPL ++0x2b296823 shash_ahash_finup vmlinux EXPORT_SYMBOL_GPL ++0x6544cafe user_update vmlinux EXPORT_SYMBOL_GPL ++0xb454572a irqd_to_hwirq vmlinux EXPORT_SYMBOL_GPL ++0x4ea0d14b nf_ct_get_tuplepr net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x095a5e59 skb_free_datagram_locked vmlinux EXPORT_SYMBOL ++0x76fc0f60 kernel_sock_shutdown vmlinux EXPORT_SYMBOL ++0xa5b5f374 notify_change vmlinux EXPORT_SYMBOL ++0xae5c1715 follow_up vmlinux EXPORT_SYMBOL ++0x0b7086d9 param_get_short vmlinux EXPORT_SYMBOL ++0x944b9776 nf_log_bind_pf vmlinux EXPORT_SYMBOL ++0xe2b8b326 skb_copy_and_csum_datagram_iovec vmlinux EXPORT_SYMBOL ++0x304d21f5 sock_no_ioctl vmlinux EXPORT_SYMBOL ++0x2c738b3f get_user_pages_fast vmlinux EXPORT_SYMBOL_GPL ++0x644e6c65 nf_conntrack_find_get net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x2a873ac0 scsi_remove_device vmlinux EXPORT_SYMBOL ++0x738da129 simple_empty vmlinux EXPORT_SYMBOL ++0xe6e2bc75 shmem_read_mapping_page_gfp vmlinux EXPORT_SYMBOL_GPL ++0x8c3682d4 xfrm_cfg_mutex vmlinux EXPORT_SYMBOL ++0x096e161a __sk_mem_schedule vmlinux EXPORT_SYMBOL ++0xab9efe2e __hid_register_driver vmlinux EXPORT_SYMBOL_GPL ++0xc94631af hid_disconnect vmlinux EXPORT_SYMBOL_GPL ++0x70cf032f usb_hcd_irq vmlinux EXPORT_SYMBOL_GPL ++0x16edea5d __pci_register_driver vmlinux EXPORT_SYMBOL ++0xcde172ac radix_tree_gang_lookup_tag_slot vmlinux EXPORT_SYMBOL ++0xedb6385a blk_queue_merge_bvec vmlinux EXPORT_SYMBOL ++0x920fe930 journal_lock_updates vmlinux EXPORT_SYMBOL ++0x10b39a9d mnt_want_write_file vmlinux EXPORT_SYMBOL_GPL ++0xec1efa4e ip_ct_attach vmlinux EXPORT_SYMBOL ++0xabe640fc dev_set_mtu vmlinux EXPORT_SYMBOL ++0x82ae4fe5 crypto_unregister_template vmlinux EXPORT_SYMBOL_GPL ++0xcddd85e0 bd_link_disk_holder vmlinux EXPORT_SYMBOL_GPL ++0x2919b156 xdr_decode_string_inplace vmlinux EXPORT_SYMBOL_GPL ++0x565b6892 uuid_le_gen vmlinux EXPORT_SYMBOL_GPL ++0xca988dd7 svc_seq_show vmlinux EXPORT_SYMBOL_GPL ++0x52078d48 scsi_free_host_dev vmlinux EXPORT_SYMBOL ++0xd1010d6c driver_register vmlinux EXPORT_SYMBOL_GPL ++0x346c4ded rwsem_down_write_failed vmlinux EXPORT_SYMBOL ++0xc630666e should_remove_suid vmlinux EXPORT_SYMBOL ++0xe9e4c8f7 input_ff_create vmlinux EXPORT_SYMBOL_GPL ++0x103497cf device_destroy vmlinux EXPORT_SYMBOL_GPL ++0x8fae9b4b find_lock_page vmlinux EXPORT_SYMBOL ++0x022d3702 srcu_notifier_chain_unregister vmlinux EXPORT_SYMBOL_GPL ++0x917e424e local_flush_tlb_mm vmlinux EXPORT_SYMBOL ++0x1219dd23 unregister_pernet_device vmlinux EXPORT_SYMBOL_GPL ++0x5fd09748 input_ff_destroy vmlinux EXPORT_SYMBOL_GPL ++0x1b46e897 platform_get_irq_byname vmlinux EXPORT_SYMBOL_GPL ++0x48404b9a remove_wait_queue vmlinux EXPORT_SYMBOL ++0x0f59f197 param_array_ops vmlinux EXPORT_SYMBOL ++0xfe88da83 napi_get_frags vmlinux EXPORT_SYMBOL ++0x21daf6a9 sk_stream_write_space vmlinux EXPORT_SYMBOL ++0x52af66d4 scsi_verify_blk_ioctl vmlinux EXPORT_SYMBOL ++0x446ffab6 sysfs_notify_dirent vmlinux EXPORT_SYMBOL_GPL ++0x13bf0f2d ipv6_dup_options vmlinux EXPORT_SYMBOL_GPL ++0x341c8ed1 phy_register_fixup_for_id vmlinux EXPORT_SYMBOL ++0x59021bf3 add_mtd_blktrans_dev vmlinux EXPORT_SYMBOL_GPL ++0x40344dfc mmc_do_release_host vmlinux EXPORT_SYMBOL ++0x52c1fde9 zap_vma_ptes vmlinux EXPORT_SYMBOL_GPL ++0xa22bc9de rpc_init_priority_wait_queue vmlinux EXPORT_SYMBOL_GPL ++0x0e889016 xfrm_policy_bysel_ctx vmlinux EXPORT_SYMBOL ++0x35d4ae0a tcp_sendmsg vmlinux EXPORT_SYMBOL ++0xfd5866dc i2c_smbus_write_word_data vmlinux EXPORT_SYMBOL ++0x7e275ea8 scsi_complete_async_scans vmlinux EXPORT_SYMBOL_GPL ++0x3bc40f39 elv_rb_del vmlinux EXPORT_SYMBOL ++0x20223395 elv_rb_add vmlinux EXPORT_SYMBOL ++0x2115a784 init_user_ns vmlinux EXPORT_SYMBOL_GPL ++0xa5b00659 ppc_proc_freq vmlinux EXPORT_SYMBOL_GPL ++0x4a4a77e3 netif_skb_features vmlinux EXPORT_SYMBOL ++0xde0a03d6 sock_map_fd vmlinux EXPORT_SYMBOL ++0x00632780 work_busy vmlinux EXPORT_SYMBOL_GPL ++0xc368849f nvram_sync vmlinux EXPORT_SYMBOL ++0x06c5142a __sk_mem_reclaim vmlinux EXPORT_SYMBOL ++0x4be38e61 pcim_pin_device vmlinux EXPORT_SYMBOL ++0xc45755de find_next_zero_bit_le vmlinux EXPORT_SYMBOL ++0x04acf587 d_prune_aliases vmlinux EXPORT_SYMBOL ++0x12a38747 usleep_range vmlinux EXPORT_SYMBOL ++0x11e746e0 flush_icache_user_range vmlinux EXPORT_SYMBOL ++0x2691412e boot_cpuid_phys vmlinux EXPORT_SYMBOL_GPL ++0xa43b9539 memcpy_fromiovecend vmlinux EXPORT_SYMBOL ++0x86e2446c blk_make_request vmlinux EXPORT_SYMBOL ++0xd75c1a07 __pagevec_release vmlinux EXPORT_SYMBOL ++0x51b65a26 rtc_lock vmlinux EXPORT_SYMBOL_GPL ++0xdebf6baa hid_unregister_driver vmlinux EXPORT_SYMBOL_GPL ++0x62062d4b pcie_set_readrq vmlinux EXPORT_SYMBOL ++0xa73e3fb4 pcie_bus_configure_settings vmlinux EXPORT_SYMBOL_GPL ++0x0bf2c9fd nla_reserve_nohdr vmlinux EXPORT_SYMBOL ++0x6d16edba ilookup5 vmlinux EXPORT_SYMBOL ++0x1650bf27 rcutorture_record_progress vmlinux EXPORT_SYMBOL_GPL ++0xcd0529c7 _raw_spin_lock_irq vmlinux EXPORT_SYMBOL ++0x38f962da prepare_creds vmlinux EXPORT_SYMBOL ++0x44399123 mutex_unlock vmlinux EXPORT_SYMBOL ++0xdf8a2c89 genl_register_family_with_ops vmlinux EXPORT_SYMBOL ++0x27ad46ae dev_addr_flush vmlinux EXPORT_SYMBOL ++0x8acf07d0 pci_block_user_cfg_access vmlinux EXPORT_SYMBOL_GPL ++0x83a476ce bitmap_scnlistprintf vmlinux EXPORT_SYMBOL ++0xaee9c392 journal_release_buffer vmlinux EXPORT_SYMBOL ++0xce86792d sunrpc_cache_pipe_upcall vmlinux EXPORT_SYMBOL_GPL ++0x08cf1a7f blkdev_get_by_dev vmlinux EXPORT_SYMBOL ++0xd89da37f movable_zone vmlinux EXPORT_SYMBOL ++0xd87601cc ring_buffer_unlock_commit vmlinux EXPORT_SYMBOL_GPL ++0xd69b30e0 atomic64_add_unless vmlinux EXPORT_SYMBOL ++0xb792aa40 simple_fill_super vmlinux EXPORT_SYMBOL ++0xd7780596 have_submounts vmlinux EXPORT_SYMBOL ++0x07cc4a5d printk_timed_ratelimit vmlinux EXPORT_SYMBOL ++0x0a51ae5b virq_to_hw vmlinux EXPORT_SYMBOL_GPL ++0xeb62ec54 sock_queue_err_skb vmlinux EXPORT_SYMBOL ++0xe6ebc016 key_create_or_update vmlinux EXPORT_SYMBOL ++0x1f8db7f9 ring_buffer_overrun_cpu vmlinux EXPORT_SYMBOL_GPL ++0x0faef0ed __tasklet_schedule vmlinux EXPORT_SYMBOL ++0xfded48ed enable_kernel_fp vmlinux EXPORT_SYMBOL ++0x7b890c7b xprt_adjust_cwnd vmlinux EXPORT_SYMBOL_GPL ++0xf4f14de6 rtnl_trylock vmlinux EXPORT_SYMBOL ++0x1b852c21 dev_load vmlinux EXPORT_SYMBOL ++0xac0ba8c1 blk_iopoll_disable vmlinux EXPORT_SYMBOL ++0x5424df82 debugfs_create_u16 vmlinux EXPORT_SYMBOL_GPL ++0x4bbd1ffa bio_add_page vmlinux EXPORT_SYMBOL ++0x74193242 init_pid_ns vmlinux EXPORT_SYMBOL_GPL ++0x7ca341af kernel_thread vmlinux EXPORT_SYMBOL ++0x70aabf3e ipt_unregister_table net/ipv4/netfilter/ip_tables EXPORT_SYMBOL ++0x159abb63 usb_unlink_anchored_urbs vmlinux EXPORT_SYMBOL_GPL ++0x77ecac9f zlib_inflateEnd vmlinux EXPORT_SYMBOL ++0xa336c35b contig_page_data vmlinux EXPORT_SYMBOL ++0xcaaaccd0 inet_frag_evictor vmlinux EXPORT_SYMBOL ++0x68e0937e xt_unregister_target vmlinux EXPORT_SYMBOL ++0xb4fac2f9 pci_bus_add_device vmlinux EXPORT_SYMBOL_GPL ++0x23679939 __iowrite32_copy vmlinux EXPORT_SYMBOL_GPL ++0x11c5a183 nf_conntrack_unregister_notifier net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x324d7c16 xdr_enter_page vmlinux EXPORT_SYMBOL_GPL ++0x2fff2281 fib_rules_register vmlinux EXPORT_SYMBOL_GPL ++0x612390ad netpoll_set_trap vmlinux EXPORT_SYMBOL ++0xfaf98462 bitrev32 vmlinux EXPORT_SYMBOL ++0xb20a3754 simple_transaction_read vmlinux EXPORT_SYMBOL ++0x8a99a016 mempool_free_slab vmlinux EXPORT_SYMBOL ++0xe384a102 usb_speed_string vmlinux EXPORT_SYMBOL_GPL ++0x27ee902c generic_setxattr vmlinux EXPORT_SYMBOL ++0x00c37822 generic_getxattr vmlinux EXPORT_SYMBOL ++0x6e46a481 dma_mmap_coherent vmlinux EXPORT_SYMBOL_GPL ++0x3d7855c9 gss_mech_register vmlinux EXPORT_SYMBOL_GPL ++0x44a12e1b mpage_readpages vmlinux EXPORT_SYMBOL ++0x01a4494d i2c_unlock_adapter vmlinux EXPORT_SYMBOL_GPL ++0x0960ffb8 pci_request_regions vmlinux EXPORT_SYMBOL ++0x6b807a5f gpio_sysfs_set_active_low vmlinux EXPORT_SYMBOL_GPL ++0x4df119fa __bitmap_parse vmlinux EXPORT_SYMBOL ++0x6bd74d1a __wait_on_buffer vmlinux EXPORT_SYMBOL ++0xe1d61c3a cancel_delayed_work_sync vmlinux EXPORT_SYMBOL ++0xf870a8ab sock_create vmlinux EXPORT_SYMBOL ++0x4315bd81 usb_serial_handle_sysrq_char vmlinux EXPORT_SYMBOL_GPL ++0xadbc1c68 class_dev_iter_next vmlinux EXPORT_SYMBOL_GPL ++0x9dd28e76 debugfs_create_x32 vmlinux EXPORT_SYMBOL_GPL ++0xae6f72ac bprm_change_interp vmlinux EXPORT_SYMBOL ++0x673b3584 kill_litter_super vmlinux EXPORT_SYMBOL ++0x5133c2b5 inet_proto_csum_replace4 vmlinux EXPORT_SYMBOL ++0xadf3fc4c neigh_direct_output vmlinux EXPORT_SYMBOL ++0x0c8395fa usb_free_urb vmlinux EXPORT_SYMBOL_GPL ++0x7aee148f tty_prepare_flip_string_flags vmlinux EXPORT_SYMBOL_GPL ++0x119c901d tty_prepare_flip_string vmlinux EXPORT_SYMBOL_GPL ++0xf1216c75 prandom32 vmlinux EXPORT_SYMBOL ++0x55ba3776 blk_rq_check_limits vmlinux EXPORT_SYMBOL_GPL ++0x75bda77a seq_hlist_next vmlinux EXPORT_SYMBOL ++0x9fd078d4 account_page_dirtied vmlinux EXPORT_SYMBOL ++0x27d7e97e __lock_page_killable vmlinux EXPORT_SYMBOL_GPL ++0x622ef684 fib_rules_unregister vmlinux EXPORT_SYMBOL_GPL ++0x371d2b7d skb_copy_bits vmlinux EXPORT_SYMBOL ++0x189868d7 get_random_bytes_arch vmlinux EXPORT_SYMBOL ++0x6e1d6881 pcim_iomap vmlinux EXPORT_SYMBOL ++0x9b339c60 __blk_end_request_all vmlinux EXPORT_SYMBOL ++0xca601c92 crypto_register_ahash vmlinux EXPORT_SYMBOL_GPL ++0x8453215f sysfs_remove_link vmlinux EXPORT_SYMBOL_GPL ++0x8924eb1e rcu_force_quiescent_state vmlinux EXPORT_SYMBOL_GPL ++0x2827efe8 tcp_make_synack vmlinux EXPORT_SYMBOL ++0xf4979615 mii_check_gmii_support vmlinux EXPORT_SYMBOL ++0xa0d1a668 sysdev_class_create_file vmlinux EXPORT_SYMBOL_GPL ++0xc4fe793b find_get_page vmlinux EXPORT_SYMBOL ++0xae1a6d66 hrtimer_forward vmlinux EXPORT_SYMBOL_GPL ++0xf322a206 bit_waitqueue vmlinux EXPORT_SYMBOL ++0xefc93e71 threads_core_mask vmlinux EXPORT_SYMBOL_GPL ++0xae652611 sock_common_recvmsg vmlinux EXPORT_SYMBOL ++0x6a555f7c drop_file_write_access vmlinux EXPORT_SYMBOL_GPL ++0x966dd23b inet_csk_addr2sockaddr vmlinux EXPORT_SYMBOL_GPL ++0xeda0d76e gen_estimator_active vmlinux EXPORT_SYMBOL ++0x794ed58e get_driver vmlinux EXPORT_SYMBOL_GPL ++0x8251bcc3 bitmap_release_region vmlinux EXPORT_SYMBOL ++0x7054a3e4 request_dma vmlinux EXPORT_SYMBOL ++0x84f47571 ip_mc_inc_group vmlinux EXPORT_SYMBOL ++0x71621fe0 tcp_orphan_count vmlinux EXPORT_SYMBOL_GPL ++0x5f86d84e request_key_with_auxdata vmlinux EXPORT_SYMBOL ++0xaf2518eb fat_attach vmlinux EXPORT_SYMBOL_GPL ++0x22d8e440 sysfs_remove_bin_file vmlinux EXPORT_SYMBOL_GPL ++0xa53e8fbc kick_iocb vmlinux EXPORT_SYMBOL ++0xbc070ddd hid_dump_device vmlinux EXPORT_SYMBOL_GPL ++0xb81960ca snprintf vmlinux EXPORT_SYMBOL ++0x6b5064c6 get_io_context vmlinux EXPORT_SYMBOL ++0x80b3e715 proc_mkdir_mode vmlinux EXPORT_SYMBOL ++0xf57b6671 tag_pages_for_writeback vmlinux EXPORT_SYMBOL ++0x092d50a4 rpcauth_destroy_credcache vmlinux EXPORT_SYMBOL_GPL ++0x22586218 devm_kzalloc vmlinux EXPORT_SYMBOL_GPL ++0x97a8cbdc swiotlb_dma_supported vmlinux EXPORT_SYMBOL ++0x2296c00d crypto_attr_u32 vmlinux EXPORT_SYMBOL_GPL ++0x77dcb28d __bread vmlinux EXPORT_SYMBOL ++0xbba159e0 files_lglock_local_unlock vmlinux EXPORT_SYMBOL ++0xd640e8b8 follow_pfn vmlinux EXPORT_SYMBOL ++0xaa764215 hrtimer_init vmlinux EXPORT_SYMBOL_GPL ++0x954488a4 syncookie_secret vmlinux EXPORT_SYMBOL ++0x9ceb163c memcpy_toiovec vmlinux EXPORT_SYMBOL ++0x74b5d898 usb_disable_xhci_ports vmlinux EXPORT_SYMBOL_GPL ++0x1b6314fd in_aton vmlinux EXPORT_SYMBOL ++0x8bf80102 neigh_resolve_output vmlinux EXPORT_SYMBOL ++0xd6677342 journal_init_dev vmlinux EXPORT_SYMBOL ++0x176b3f91 posix_unblock_lock vmlinux EXPORT_SYMBOL ++0x9acd079c __mnt_is_readonly vmlinux EXPORT_SYMBOL_GPL ++0x500dda7f nf_nat_ftp_hook net/netfilter/nf_conntrack_ftp EXPORT_SYMBOL_GPL ++0x6b52164d tcp_close vmlinux EXPORT_SYMBOL ++0x190b6c5c __scm_send vmlinux EXPORT_SYMBOL ++0x227822d5 usb_register_dev vmlinux EXPORT_SYMBOL_GPL ++0x8fb45bb1 scsi_dma_map vmlinux EXPORT_SYMBOL ++0xa07ed110 xz_dec_init vmlinux EXPORT_SYMBOL ++0x3f906124 try_to_free_buffers vmlinux EXPORT_SYMBOL ++0xef120637 wait_iff_congested vmlinux EXPORT_SYMBOL ++0xe7b1acbe __put_cred vmlinux EXPORT_SYMBOL ++0xb15bd8fa tb_ticks_per_sec vmlinux EXPORT_SYMBOL ++0x3cd06035 add_input_randomness vmlinux EXPORT_SYMBOL_GPL ++0x9ed685ee iov_iter_advance vmlinux EXPORT_SYMBOL ++0x757f088f cpm_muram_offset vmlinux EXPORT_SYMBOL ++0x90501868 transfer_to_handler vmlinux EXPORT_SYMBOL ++0xacf5a07d xdr_set_scratch_buffer vmlinux EXPORT_SYMBOL_GPL ++0x0ac28878 scsi_unblock_requests vmlinux EXPORT_SYMBOL ++0xf6d1a555 device_remove_bin_file vmlinux EXPORT_SYMBOL_GPL ++0x980fd9e0 tty_port_free_xmit_buf vmlinux EXPORT_SYMBOL ++0x8c28d738 nf_ct_deliver_cached_events net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xaf5bf6ef nfs_debug vmlinux EXPORT_SYMBOL_GPL ++0x7267db00 hwrng_unregister vmlinux EXPORT_SYMBOL_GPL ++0x94202ff1 crypto_nivaead_type vmlinux EXPORT_SYMBOL_GPL ++0x4f0d0c17 bdi_writeout_inc vmlinux EXPORT_SYMBOL_GPL ++0xdc7776cc xfrm6_rcv_spi vmlinux EXPORT_SYMBOL ++0x27c1e63f usb_amd_find_chipset_info vmlinux EXPORT_SYMBOL_GPL ++0xcf307410 disk_stack_limits vmlinux EXPORT_SYMBOL ++0x75e8f3c3 crypto_register_notifier vmlinux EXPORT_SYMBOL_GPL ++0x57b57ebe jiffies_to_timespec vmlinux EXPORT_SYMBOL ++0x5f4e77a9 pskb_put vmlinux EXPORT_SYMBOL_GPL ++0xfa6583df i2c_master_send vmlinux EXPORT_SYMBOL ++0xcaae18ce device_reprobe vmlinux EXPORT_SYMBOL_GPL ++0x479c3c86 find_next_zero_bit vmlinux EXPORT_SYMBOL ++0x8ee69235 timeval_to_jiffies vmlinux EXPORT_SYMBOL ++0x0840985a dev_kfree_skb_any vmlinux EXPORT_SYMBOL ++0x384455fa journal_abort vmlinux EXPORT_SYMBOL ++0x2d550ef5 seq_open vmlinux EXPORT_SYMBOL ++0x88c8ae9d mnt_drop_write vmlinux EXPORT_SYMBOL_GPL ++0x297d6b80 rpc_uaddr2sockaddr vmlinux EXPORT_SYMBOL_GPL ++0x7e394c4e sysctl_local_reserved_ports vmlinux EXPORT_SYMBOL ++0x1cc4c90f pci_bus_type vmlinux EXPORT_SYMBOL ++0xeaf46b33 pci_enable_bridges vmlinux EXPORT_SYMBOL ++0x8cf4e71e simple_readpage vmlinux EXPORT_SYMBOL ++0x83f092b9 __lock_page vmlinux EXPORT_SYMBOL ++0xb140d14c ring_buffer_read vmlinux EXPORT_SYMBOL_GPL ++0xf499fdb2 rcu_barrier_bh vmlinux EXPORT_SYMBOL_GPL ++0x46b6baff synchronize_srcu_expedited vmlinux EXPORT_SYMBOL_GPL ++0xe98d2676 cpu_remove_dev_attr vmlinux EXPORT_SYMBOL_GPL ++0xfeb79024 tcp_cong_avoid_ai vmlinux EXPORT_SYMBOL_GPL ++0xab6bde28 sysctl_max_syn_backlog vmlinux EXPORT_SYMBOL ++0xca059c46 usb_altnum_to_altsetting vmlinux EXPORT_SYMBOL_GPL ++0x6f497d79 pci_create_slot vmlinux EXPORT_SYMBOL_GPL ++0xa43762aa blk_delay_queue vmlinux EXPORT_SYMBOL ++0xe6a1e7fb follow_down vmlinux EXPORT_SYMBOL ++0xc06502c4 __generic_file_aio_write vmlinux EXPORT_SYMBOL ++0x5aed6e64 filemap_write_and_wait_range vmlinux EXPORT_SYMBOL ++0xf229625e devm_ioremap_prot vmlinux EXPORT_SYMBOL ++0xd85028c2 genphy_read_status vmlinux EXPORT_SYMBOL ++0x97d977b5 tty_unregister_driver vmlinux EXPORT_SYMBOL ++0xc404cbb3 pci_reenable_device vmlinux EXPORT_SYMBOL ++0xc6a0b57b get_write_access vmlinux EXPORT_SYMBOL ++0x7c22ff1f invalidate_mapping_pages vmlinux EXPORT_SYMBOL ++0xc0c17332 pci_enable_rom vmlinux EXPORT_SYMBOL_GPL ++0xf3bf0bce __bitmap_complement vmlinux EXPORT_SYMBOL ++0xe2e8065e memdup_user vmlinux EXPORT_SYMBOL ++0x221623f5 thermal_cooling_device_unregister vmlinux EXPORT_SYMBOL ++0xcca27eeb del_timer vmlinux EXPORT_SYMBOL ++0xeb9aea7d dma_get_required_mask vmlinux EXPORT_SYMBOL_GPL ++0x4dc45be9 nf_log_unbind_pf vmlinux EXPORT_SYMBOL ++0xeaae7eca usb_get_current_frame_number vmlinux EXPORT_SYMBOL_GPL ++0x80fdefab map_destroy vmlinux EXPORT_SYMBOL ++0x3e3944d8 pcie_update_link_speed vmlinux EXPORT_SYMBOL_GPL ++0x5bb906a7 wait_rcu_gp vmlinux EXPORT_SYMBOL_GPL ++0x74046876 nf_ct_expect_find_get net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xf397c836 tcp_v4_send_check vmlinux EXPORT_SYMBOL ++0xbba15e0b dev_close vmlinux EXPORT_SYMBOL ++0x6e22c276 __mark_inode_dirty vmlinux EXPORT_SYMBOL ++0x97c92d4b noop_qdisc vmlinux EXPORT_SYMBOL ++0x1ce622fb sock_alloc_send_skb vmlinux EXPORT_SYMBOL ++0xd9ce8f0c strnlen vmlinux EXPORT_SYMBOL ++0x4953f064 unregister_filesystem vmlinux EXPORT_SYMBOL ++0xd418e1c0 adjust_resource vmlinux EXPORT_SYMBOL ++0xdd91ae2a xfrm_state_insert vmlinux EXPORT_SYMBOL ++0x030d11a8 kmsg_dump_register vmlinux EXPORT_SYMBOL_GPL ++0x4e05fd2a rpc_peeraddr2str vmlinux EXPORT_SYMBOL_GPL ++0x40728a63 xt_find_revision vmlinux EXPORT_SYMBOL_GPL ++0x82e3b54d of_node_get vmlinux EXPORT_SYMBOL ++0x08ad10e2 of_node_put vmlinux EXPORT_SYMBOL ++0x8d18a199 __destroy_inode vmlinux EXPORT_SYMBOL ++0xb18b572e nf_conntrack_l3proto_generic net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x9a1c768a tcp_is_cwnd_limited vmlinux EXPORT_SYMBOL_GPL ++0xdcc97380 pci_bus_add_devices vmlinux EXPORT_SYMBOL ++0xce9b668c blk_rq_unmap_user vmlinux EXPORT_SYMBOL ++0x768f9bc5 crypto_mod_get vmlinux EXPORT_SYMBOL_GPL ++0x0bc477a2 irq_set_irq_type vmlinux EXPORT_SYMBOL ++0xce2840e7 irq_set_irq_wake vmlinux EXPORT_SYMBOL ++0x36efd128 __remove_inode_hash vmlinux EXPORT_SYMBOL ++0xae52c20e __lru_cache_add vmlinux EXPORT_SYMBOL ++0x6128b5fc __printk_ratelimit vmlinux EXPORT_SYMBOL ++0x7db8133c switch_mmu_context vmlinux EXPORT_SYMBOL ++0xb6938e50 xdr_read_pages vmlinux EXPORT_SYMBOL_GPL ++0xad06c17e xdr_encode_pages vmlinux EXPORT_SYMBOL_GPL ++0xcc1f1c3d inet_twdr_hangman vmlinux EXPORT_SYMBOL_GPL ++0xcacd272d atomic64_sub_return vmlinux EXPORT_SYMBOL ++0x5b256543 __blk_end_request_cur vmlinux EXPORT_SYMBOL ++0x5b40de9d __blk_end_request_err vmlinux EXPORT_SYMBOL_GPL ++0xb2682405 utf8_to_utf32 vmlinux EXPORT_SYMBOL ++0x9621849f ring_buffer_event_data vmlinux EXPORT_SYMBOL_GPL ++0xd2423d66 scsi_prep_return vmlinux EXPORT_SYMBOL ++0x2cf5fa92 __bus_register vmlinux EXPORT_SYMBOL_GPL ++0x4fe99583 atomic64_dec_if_positive vmlinux EXPORT_SYMBOL ++0x2c3b9273 crypto_sha1_update vmlinux EXPORT_SYMBOL ++0x2d727890 override_creds vmlinux EXPORT_SYMBOL ++0x131db64a system_long_wq vmlinux EXPORT_SYMBOL_GPL ++0x3ca16d23 kmsg_dump_unregister vmlinux EXPORT_SYMBOL_GPL ++0x606d0b09 secure_tcpv6_sequence_number vmlinux EXPORT_SYMBOL ++0x78381b79 input_register_handle vmlinux EXPORT_SYMBOL ++0x6ca1d1a4 atomic64_read vmlinux EXPORT_SYMBOL ++0x979a2d28 blkdev_issue_zeroout vmlinux EXPORT_SYMBOL ++0x461818bb journal_get_create_access vmlinux EXPORT_SYMBOL ++0xe15b92eb handle_level_irq vmlinux EXPORT_SYMBOL_GPL ++0xd31ccb06 of_machine_is_compatible vmlinux EXPORT_SYMBOL ++0xf971d6e2 sdio_writesb vmlinux EXPORT_SYMBOL_GPL ++0x42b364ef scatterwalk_done vmlinux EXPORT_SYMBOL_GPL ++0x58ffec8b request_key vmlinux EXPORT_SYMBOL ++0x3923bd3b kern_unmount vmlinux EXPORT_SYMBOL ++0xfa9dd504 timecompare_transform vmlinux EXPORT_SYMBOL_GPL ++0xae616697 usb_control_msg vmlinux EXPORT_SYMBOL_GPL ++0x9846a085 mtd_table_mutex vmlinux EXPORT_SYMBOL_GPL ++0x0c8aadeb nla_append vmlinux EXPORT_SYMBOL ++0x351f3c81 pcim_iomap_regions vmlinux EXPORT_SYMBOL ++0xb86e4ab9 random32 vmlinux EXPORT_SYMBOL ++0x51ad88ca skcipher_geniv_free vmlinux EXPORT_SYMBOL_GPL ++0x2c204319 vfs_llseek vmlinux EXPORT_SYMBOL ++0x81d70b6e __irq_set_handler vmlinux EXPORT_SYMBOL_GPL ++0xa8bdd720 dev_set_drvdata vmlinux EXPORT_SYMBOL ++0xdca20876 dev_get_drvdata vmlinux EXPORT_SYMBOL ++0x7ceaf0d5 generic_handle_irq vmlinux EXPORT_SYMBOL_GPL ++0x9ea865cf blocking_notifier_chain_cond_register vmlinux EXPORT_SYMBOL_GPL ++0xb75cd36b __xfrm_state_destroy vmlinux EXPORT_SYMBOL ++0x400bf80a bfifo_qdisc_ops vmlinux EXPORT_SYMBOL ++0x01c4ff56 usb_unpoison_urb vmlinux EXPORT_SYMBOL_GPL ++0x4242db6e tty_port_init vmlinux EXPORT_SYMBOL ++0x74bae351 complete_request_key vmlinux EXPORT_SYMBOL ++0x1f8544b8 panic_timeout vmlinux EXPORT_SYMBOL_GPL ++0xa20ce1b8 net_msg_warn vmlinux EXPORT_SYMBOL ++0x7e7052eb __sock_recv_timestamp vmlinux EXPORT_SYMBOL_GPL ++0x6225637e md5_transform vmlinux EXPORT_SYMBOL ++0xc0d579ef noop_fsync vmlinux EXPORT_SYMBOL ++0x357d2c4a scsi_add_host_with_dma vmlinux EXPORT_SYMBOL ++0x1d119736 devres_remove_group vmlinux EXPORT_SYMBOL_GPL ++0x4f2a0c62 crypto_hash_walk_first vmlinux EXPORT_SYMBOL_GPL ++0x118f01ea putname vmlinux EXPORT_SYMBOL ++0xb74b1b5c inet_sendpage vmlinux EXPORT_SYMBOL ++0x5fa17c73 sk_filter_release_rcu vmlinux EXPORT_SYMBOL ++0x52aa3821 dev_get_by_index_rcu vmlinux EXPORT_SYMBOL ++0x161edd60 dev_set_allmulti vmlinux EXPORT_SYMBOL ++0x556b4614 mmc_can_erase vmlinux EXPORT_SYMBOL ++0x6fdc65c4 i2c_add_adapter vmlinux EXPORT_SYMBOL ++0x8c140a5a input_mt_report_finger_count vmlinux EXPORT_SYMBOL ++0xea10655a __bitmap_intersects vmlinux EXPORT_SYMBOL ++0xf313da4e sha_transform vmlinux EXPORT_SYMBOL ++0x9b6eb137 ksize vmlinux EXPORT_SYMBOL ++0xf747dd44 kstat vmlinux EXPORT_SYMBOL ++0x68748335 pci_stop_bus_device vmlinux EXPORT_SYMBOL_GPL ++0xf2334557 kobject_set_name vmlinux EXPORT_SYMBOL ++0xcf586f6d shmem_truncate_range vmlinux EXPORT_SYMBOL_GPL ++0xa3e7c113 ring_buffer_iter_peek vmlinux EXPORT_SYMBOL_GPL ++0xa5efbf4c async_synchronize_full vmlinux EXPORT_SYMBOL_GPL ++0xc141de33 set_device_ro vmlinux EXPORT_SYMBOL ++0xbb038ce4 perf_unregister_guest_info_callbacks vmlinux EXPORT_SYMBOL_GPL ++0x6c9e8a40 usb_anchor_urb vmlinux EXPORT_SYMBOL_GPL ++0xa553f1ed pci_clear_mwi vmlinux EXPORT_SYMBOL ++0x0b0c5bc2 shash_attr_alg vmlinux EXPORT_SYMBOL_GPL ++0x63eb9355 panic_blink vmlinux EXPORT_SYMBOL ++0x9b349bdd __sync_dirty_buffer vmlinux EXPORT_SYMBOL ++0xcfbb9503 kmap_high vmlinux EXPORT_SYMBOL ++0x6f86e89e cancel_dirty_page vmlinux EXPORT_SYMBOL ++0xf4fc2d6c __ring_buffer_alloc vmlinux EXPORT_SYMBOL_GPL ++0x82072614 tasklet_kill vmlinux EXPORT_SYMBOL ++0xa8de6a48 i2c_use_client vmlinux EXPORT_SYMBOL ++0xdd66b703 scsi_print_command vmlinux EXPORT_SYMBOL ++0xbb1da1d5 pci_try_set_mwi vmlinux EXPORT_SYMBOL ++0xcda0bf50 bio_endio vmlinux EXPORT_SYMBOL ++0x85c7f674 ring_buffer_normalize_time_stamp vmlinux EXPORT_SYMBOL_GPL ++0x438b62ec nf_ct_expect_unregister_notifier net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xc6f3dff4 sk_stop_timer vmlinux EXPORT_SYMBOL ++0x530e0f8a of_platform_bus_probe vmlinux EXPORT_SYMBOL ++0xffdb82bc sg_free_table vmlinux EXPORT_SYMBOL ++0xbac7a6de locks_remove_posix vmlinux EXPORT_SYMBOL ++0xb0b85f47 ring_buffer_iter_reset vmlinux EXPORT_SYMBOL_GPL ++0xbc68ed8a pcie_port_service_unregister vmlinux EXPORT_SYMBOL ++0x5d5b5a16 radix_tree_delete vmlinux EXPORT_SYMBOL ++0x76831f67 tcp_slow_start vmlinux EXPORT_SYMBOL_GPL ++0xdb9628fb proc_net_netfilter vmlinux EXPORT_SYMBOL ++0x503a9a19 dev_activate vmlinux EXPORT_SYMBOL ++0xa6abec58 __pneigh_lookup vmlinux EXPORT_SYMBOL_GPL ++0xac20b868 i2c_add_mux_adapter vmlinux EXPORT_SYMBOL_GPL ++0xe8cfb9b7 devm_ioremap vmlinux EXPORT_SYMBOL ++0x050dd9e3 devm_iounmap vmlinux EXPORT_SYMBOL ++0x5541ea93 on_each_cpu vmlinux EXPORT_SYMBOL ++0x53775014 dma_set_mask vmlinux EXPORT_SYMBOL ++0x12c21380 nla_reserve vmlinux EXPORT_SYMBOL ++0x179f2b81 bioset_create vmlinux EXPORT_SYMBOL ++0x5717b1d8 rtnl_put_cacheinfo vmlinux EXPORT_SYMBOL_GPL ++0xea124bd1 gcd vmlinux EXPORT_SYMBOL_GPL ++0xb954f080 ihold vmlinux EXPORT_SYMBOL ++0x8a6d1314 names_cachep vmlinux EXPORT_SYMBOL ++0x8aaa5d67 invalidate_inode_pages2_range vmlinux EXPORT_SYMBOL_GPL ++0xc8e96dea qword_addhex vmlinux EXPORT_SYMBOL_GPL ++0x78328e4d xfrm_policy_register_afinfo vmlinux EXPORT_SYMBOL ++0x5d63436b pci_unmap_rom vmlinux EXPORT_SYMBOL ++0x118e0f3d key_instantiate_and_link vmlinux EXPORT_SYMBOL ++0xb1aaff79 dentry_path_raw vmlinux EXPORT_SYMBOL ++0x6a28defe xfrm_sad_getinfo vmlinux EXPORT_SYMBOL ++0x0ac2bf08 netif_napi_del vmlinux EXPORT_SYMBOL ++0x8014b6af input_event_from_user vmlinux EXPORT_SYMBOL_GPL ++0x4484a5a4 wait_for_device_probe vmlinux EXPORT_SYMBOL_GPL ++0xd6244170 tty_port_put vmlinux EXPORT_SYMBOL ++0xf8fa9744 crypto_register_alg vmlinux EXPORT_SYMBOL_GPL ++0xf79a16f8 debugfs_rename vmlinux EXPORT_SYMBOL_GPL ++0xe4653d19 single_open vmlinux EXPORT_SYMBOL ++0xc794266c page_follow_link_light vmlinux EXPORT_SYMBOL ++0x4146fc0f xfrm6_find_1stfragopt vmlinux EXPORT_SYMBOL ++0xfef96e23 __scsi_print_command vmlinux EXPORT_SYMBOL ++0xc40d19d3 kthread_stop vmlinux EXPORT_SYMBOL ++0xa7b91a7b lockd_down vmlinux EXPORT_SYMBOL_GPL ++0xd3481bf6 journal_trans_will_send_data_barrier vmlinux EXPORT_SYMBOL ++0x750b2814 xprt_reserve_xprt vmlinux EXPORT_SYMBOL_GPL ++0x090ed695 hid_register_report vmlinux EXPORT_SYMBOL_GPL ++0x1963b26f rtc_set_alarm vmlinux EXPORT_SYMBOL_GPL ++0x3fe72f15 __scsi_get_command vmlinux EXPORT_SYMBOL_GPL ++0x1b97d8ce __scsi_put_command vmlinux EXPORT_SYMBOL ++0xaa4a7797 hex2bin vmlinux EXPORT_SYMBOL ++0x91d266c7 crypto_default_rng vmlinux EXPORT_SYMBOL_GPL ++0x2c103133 inet_csk_listen_start vmlinux EXPORT_SYMBOL_GPL ++0xb91453c1 of_register_spi_devices vmlinux EXPORT_SYMBOL ++0xfcc2a43c utf32_to_utf8 vmlinux EXPORT_SYMBOL ++0x800df1d7 groups_free vmlinux EXPORT_SYMBOL ++0xf611bda0 cleanup_srcu_struct vmlinux EXPORT_SYMBOL_GPL ++0x3980aac1 unregister_reboot_notifier vmlinux EXPORT_SYMBOL ++0x3aa91a68 tcf_destroy_chain vmlinux EXPORT_SYMBOL ++0x255f3a7f sk_clone vmlinux EXPORT_SYMBOL_GPL ++0x3bd2becc tty_perform_flush vmlinux EXPORT_SYMBOL_GPL ++0x447e96b6 pci_request_region_exclusive vmlinux EXPORT_SYMBOL ++0x9cdf0ec5 vfsmount_lock_global_lock_online vmlinux EXPORT_SYMBOL ++0x495c501c debugfs_remove_recursive vmlinux EXPORT_SYMBOL_GPL ++0xfdb6cedc _raw_read_unlock_bh vmlinux EXPORT_SYMBOL ++0x117b494d neigh_parms_alloc vmlinux EXPORT_SYMBOL ++0x19a304ba usb_disabled vmlinux EXPORT_SYMBOL_GPL ++0xf52321e0 atomic64_sub vmlinux EXPORT_SYMBOL ++0x0bb7c01f mount_single vmlinux EXPORT_SYMBOL ++0xef109449 interruptible_sleep_on vmlinux EXPORT_SYMBOL ++0x111d29eb __ip_route_output_key vmlinux EXPORT_SYMBOL_GPL ++0xb9c425de register_syscore_ops vmlinux EXPORT_SYMBOL_GPL ++0x91a5865c blk_queue_invalidate_tags vmlinux EXPORT_SYMBOL ++0xab5d4b6c remove_irq vmlinux EXPORT_SYMBOL_GPL ++0x93a6e0b2 io_schedule vmlinux EXPORT_SYMBOL ++0x61ce005d disk_part_iter_next vmlinux EXPORT_SYMBOL_GPL ++0xb08b4f8a block_write_end vmlinux EXPORT_SYMBOL ++0xaa8e4c8a pid_vnr vmlinux EXPORT_SYMBOL_GPL ++0x56fa71f2 __xfrm_decode_session vmlinux EXPORT_SYMBOL ++0xad5f1b39 nf_net_ipv4_netfilter_sysctl_path vmlinux EXPORT_SYMBOL_GPL ++0x576dc245 tty_port_lower_dtr_rts vmlinux EXPORT_SYMBOL ++0xf803fe39 bitmap_set vmlinux EXPORT_SYMBOL ++0x230e0698 __clocksource_updatefreq_scale vmlinux EXPORT_SYMBOL_GPL ++0x1528ad8f netlink_set_err vmlinux EXPORT_SYMBOL ++0x8e488ec3 alloc_netdev_mqs vmlinux EXPORT_SYMBOL ++0xc71e5323 bus_register_notifier vmlinux EXPORT_SYMBOL_GPL ++0x1d021d32 gpiochip_add vmlinux EXPORT_SYMBOL_GPL ++0x336154ca rcutorture_record_test_transition vmlinux EXPORT_SYMBOL_GPL ++0xf77020ef inet_listen vmlinux EXPORT_SYMBOL ++0x32e49bab register_snap_client vmlinux EXPORT_SYMBOL ++0x9287ab43 __dst_destroy_metrics_generic vmlinux EXPORT_SYMBOL ++0x3281d137 skb_queue_purge vmlinux EXPORT_SYMBOL ++0xcd0b9f77 get_unmapped_area vmlinux EXPORT_SYMBOL ++0xa196356e add_to_page_cache_lru vmlinux EXPORT_SYMBOL_GPL ++0x07b52e38 rtnl_unregister vmlinux EXPORT_SYMBOL_GPL ++0x816a4a8f platform_bus_type vmlinux EXPORT_SYMBOL_GPL ++0x8eb489cc blk_rq_map_user vmlinux EXPORT_SYMBOL ++0x95666f79 generic_pipe_buf_release vmlinux EXPORT_SYMBOL ++0x9b49a62b nf_ct_gre_keymap_add net/netfilter/nf_conntrack_proto_gre EXPORT_SYMBOL_GPL ++0x76486f91 d_find_alias vmlinux EXPORT_SYMBOL ++0x760a0f4f yield vmlinux EXPORT_SYMBOL ++0xdfce92d0 xt_check_target vmlinux EXPORT_SYMBOL_GPL ++0x693bf8ad sdio_claim_irq vmlinux EXPORT_SYMBOL_GPL ++0x6bd2a517 fsstack_copy_attr_all vmlinux EXPORT_SYMBOL_GPL ++0x7d2d68ef __nf_ct_try_assign_helper net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xf3bfc4a0 udp6_lib_lookup vmlinux EXPORT_SYMBOL_GPL ++0xa9ff0067 xfrm_init_replay vmlinux EXPORT_SYMBOL ++0x4cd13364 udp4_lib_lookup vmlinux EXPORT_SYMBOL_GPL ++0xaee50a42 genl_unregister_ops vmlinux EXPORT_SYMBOL ++0x9e2000a7 memcpy_toiovecend vmlinux EXPORT_SYMBOL ++0xcc3ad809 scsi_command_normalize_sense vmlinux EXPORT_SYMBOL ++0x2f19f806 inode_sb_list_add vmlinux EXPORT_SYMBOL_GPL ++0xc0072342 inode_init_always vmlinux EXPORT_SYMBOL ++0x37443f52 d_invalidate vmlinux EXPORT_SYMBOL ++0xa0b04675 vmalloc_32 vmlinux EXPORT_SYMBOL ++0x8a13f155 pid_task vmlinux EXPORT_SYMBOL ++0x33b84f74 copy_page vmlinux EXPORT_SYMBOL ++0x115dd19b seq_print_acct net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x447aabed stp_proto_register vmlinux EXPORT_SYMBOL_GPL ++0x40b9610d input_register_handler vmlinux EXPORT_SYMBOL ++0xc0572d04 textsearch_unregister vmlinux EXPORT_SYMBOL ++0xf54c51a2 dma_pool_free vmlinux EXPORT_SYMBOL ++0xdb274e52 monotonic_to_bootbased vmlinux EXPORT_SYMBOL_GPL ++0x86b4b68f inet6_csk_bind_conflict vmlinux EXPORT_SYMBOL_GPL ++0xa35de80f ipv4_config vmlinux EXPORT_SYMBOL ++0x94ecde24 netif_carrier_on vmlinux EXPORT_SYMBOL ++0x74b8aeab fib_rules_lookup vmlinux EXPORT_SYMBOL_GPL ++0xb0b847ac __bitmap_full vmlinux EXPORT_SYMBOL ++0x4059792f print_hex_dump vmlinux EXPORT_SYMBOL ++0x22f5f5bd ip6_route_output vmlinux EXPORT_SYMBOL ++0x98c1c63d __rta_fill vmlinux EXPORT_SYMBOL ++0x87b20911 __dst_free vmlinux EXPORT_SYMBOL ++0xfe1c56c4 inode_newsize_ok vmlinux EXPORT_SYMBOL ++0x89b3107b isa_mem_base vmlinux EXPORT_SYMBOL ++0xcbb1b165 inet_csk_destroy_sock vmlinux EXPORT_SYMBOL ++0x290bcd04 pci_disable_obff vmlinux EXPORT_SYMBOL ++0x78df6bd7 no_pci_devices vmlinux EXPORT_SYMBOL ++0xc2e00f4e nfs_pageio_reset_read_mds vmlinux EXPORT_SYMBOL_GPL ++0x1e26be3b get_anon_bdev vmlinux EXPORT_SYMBOL ++0x6b29a1fa ring_buffer_event_length vmlinux EXPORT_SYMBOL_GPL ++0x84b183ae strncmp vmlinux EXPORT_SYMBOL ++0x5ee2150e sock_kfree_s vmlinux EXPORT_SYMBOL ++0xaf67115a usb_stor_access_xfer_buf vmlinux EXPORT_SYMBOL_GPL ++0xa34f1ef5 crc32_le vmlinux EXPORT_SYMBOL ++0xf54bd49b lcm vmlinux EXPORT_SYMBOL_GPL ++0x13354608 scatterwalk_map_and_copy vmlinux EXPORT_SYMBOL_GPL ++0xf7dcfb23 empty_aops vmlinux EXPORT_SYMBOL ++0x43b911a1 __task_pid_nr_ns vmlinux EXPORT_SYMBOL ++0xe368f912 ethtool_op_get_link vmlinux EXPORT_SYMBOL ++0xa40a8590 input_event_to_user vmlinux EXPORT_SYMBOL_GPL ++0x657aa70a input_unregister_device vmlinux EXPORT_SYMBOL ++0xbfbebdf2 read_cache_pages vmlinux EXPORT_SYMBOL ++0x4aadeb9a ring_buffer_alloc_read_page vmlinux EXPORT_SYMBOL_GPL ++0x53445f68 nlm_debug vmlinux EXPORT_SYMBOL_GPL ++0x8ac6cdbe ip_generic_getfrag vmlinux EXPORT_SYMBOL ++0x825f0e72 stp_proto_unregister vmlinux EXPORT_SYMBOL_GPL ++0x42671630 call_netdevice_notifiers vmlinux EXPORT_SYMBOL ++0xdc825d6c usb_amd_quirk_pll_disable vmlinux EXPORT_SYMBOL_GPL ++0xc50de15c mii_nway_restart vmlinux EXPORT_SYMBOL ++0x208c9e61 crypto_dequeue_request vmlinux EXPORT_SYMBOL_GPL ++0x33ee71a8 crypto_enqueue_request vmlinux EXPORT_SYMBOL_GPL ++0x3a45b778 fat_add_entries vmlinux EXPORT_SYMBOL_GPL ++0x63709e0c thaw_bdev vmlinux EXPORT_SYMBOL ++0xec38d5b9 irq_create_mapping vmlinux EXPORT_SYMBOL_GPL ++0x64f9ca11 sk_run_filter vmlinux EXPORT_SYMBOL ++0xa1ec4dcb netdev_rx_csum_fault vmlinux EXPORT_SYMBOL ++0x55e74041 of_pci_address_to_resource vmlinux EXPORT_SYMBOL_GPL ++0xa7355e76 devres_release_group vmlinux EXPORT_SYMBOL_GPL ++0xa2d161c9 ipt_register_table net/ipv4/netfilter/ip_tables EXPORT_SYMBOL ++0x33274026 xdr_decode_array2 vmlinux EXPORT_SYMBOL_GPL ++0x7b594a76 ipv6_push_nfrag_opts vmlinux EXPORT_SYMBOL ++0x7a73b3d5 neigh_sysctl_unregister vmlinux EXPORT_SYMBOL ++0x7d1d23b5 blk_abort_request vmlinux EXPORT_SYMBOL_GPL ++0x7cefa3c8 __scm_destroy vmlinux EXPORT_SYMBOL ++0x88ebb649 sdio_writeb_readb vmlinux EXPORT_SYMBOL_GPL ++0x8b82c4cf d_move vmlinux EXPORT_SYMBOL ++0x5091b823 ring_buffer_read_start vmlinux EXPORT_SYMBOL_GPL ++0x77b851c4 cacheable_memzero vmlinux EXPORT_SYMBOL ++0x8d80529b virq_is_host vmlinux EXPORT_SYMBOL_GPL ++0x450872a4 ipcomp_destroy net/xfrm/xfrm_ipcomp EXPORT_SYMBOL_GPL ++0xd0035e43 dev_addr_del_multiple vmlinux EXPORT_SYMBOL ++0x5f0c41ea request_key_async vmlinux EXPORT_SYMBOL ++0x639ad9ba touch_atime vmlinux EXPORT_SYMBOL ++0x733b2383 next_tlbcam_idx vmlinux EXPORT_SYMBOL ++0x61c243fc mod_timer_pending vmlinux EXPORT_SYMBOL ++0x1f6cf216 rtnl_configure_link vmlinux EXPORT_SYMBOL ++0x5f26443b sock_wmalloc vmlinux EXPORT_SYMBOL ++0x1e6d26a8 strstr vmlinux EXPORT_SYMBOL ++0x349cba85 strchr vmlinux EXPORT_SYMBOL ++0xafba9111 qe_immr vmlinux EXPORT_SYMBOL ++0xadabd59e inet_csk_listen_stop vmlinux EXPORT_SYMBOL_GPL ++0x7ba60ec5 usb_serial_generic_resume vmlinux EXPORT_SYMBOL_GPL ++0x0cf5646d usb_wait_anchor_empty_timeout vmlinux EXPORT_SYMBOL_GPL ++0x71f78ce2 cfi_qry_mode_off vmlinux EXPORT_SYMBOL_GPL ++0xf2fca922 uart_parse_options vmlinux EXPORT_SYMBOL_GPL ++0xcfa90d57 kobject_create_and_add vmlinux EXPORT_SYMBOL_GPL ++0x589483d5 setup_new_exec vmlinux EXPORT_SYMBOL ++0xa65972b8 _memcpy_toio vmlinux EXPORT_SYMBOL ++0x109bccfc xfrm_state_lookup_byaddr vmlinux EXPORT_SYMBOL ++0xac888215 pskb_expand_head vmlinux EXPORT_SYMBOL ++0xeabea9a3 of_i2c_register_devices vmlinux EXPORT_SYMBOL ++0x6f9f1dde i2c_release_client vmlinux EXPORT_SYMBOL ++0xdf2478f7 giveup_fpu vmlinux EXPORT_SYMBOL ++0xbff12409 giveup_spe vmlinux EXPORT_SYMBOL ++0xa19aa2a4 rtnl_link_register vmlinux EXPORT_SYMBOL_GPL ++0xc53bb9d1 lock_may_write vmlinux EXPORT_SYMBOL ++0x7a461bdf bh_submit_read vmlinux EXPORT_SYMBOL ++0x1bb795cc of_create_pci_dev vmlinux EXPORT_SYMBOL ++0x91f08ce3 xdr_buf_read_netobj vmlinux EXPORT_SYMBOL_GPL ++0xad37c04e eth_change_mtu vmlinux EXPORT_SYMBOL ++0x78bb1ee1 eth_header_parse vmlinux EXPORT_SYMBOL ++0x42977ad4 __hw_addr_del_multiple vmlinux EXPORT_SYMBOL ++0x6e586165 bdev_stack_limits vmlinux EXPORT_SYMBOL ++0x1114011d threads_shift vmlinux EXPORT_SYMBOL_GPL ++0x3c9e7dc8 nf_nat_pptp_hook_exp_gre net/netfilter/nf_conntrack_pptp EXPORT_SYMBOL_GPL ++0x3c514b70 nf_conntrack_hash_insert net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xad01e7b9 sock_wake_async vmlinux EXPORT_SYMBOL ++0x506746b6 getrawmonotonic vmlinux EXPORT_SYMBOL ++0xb6599b9a machine_check_exception vmlinux EXPORT_SYMBOL ++0xfd4b9fec of_platform_device_create vmlinux EXPORT_SYMBOL ++0x0e2b0fec fat_free_clusters vmlinux EXPORT_SYMBOL_GPL ++0x7e006219 __set_page_dirty_buffers vmlinux EXPORT_SYMBOL ++0x978f24b1 __wake_up_locked vmlinux EXPORT_SYMBOL_GPL ++0x5994a0d7 sock_prot_inuse_add vmlinux EXPORT_SYMBOL_GPL ++0xbd05294b usb_hcd_platform_shutdown vmlinux EXPORT_SYMBOL_GPL ++0xf9e73082 scnprintf vmlinux EXPORT_SYMBOL ++0x1fb2a93c aead_geniv_exit vmlinux EXPORT_SYMBOL_GPL ++0x0c917640 mod_zone_page_state vmlinux EXPORT_SYMBOL ++0xf4a37928 perf_event_refresh vmlinux EXPORT_SYMBOL_GPL ++0x40f1ad10 tb_ticks_per_jiffy vmlinux EXPORT_SYMBOL ++0xae40342e blk_add_request_payload vmlinux EXPORT_SYMBOL_GPL ++0xf1a62b6f of_i8042_kbd_irq vmlinux EXPORT_SYMBOL_GPL ++0xcd5fcf06 rtnl_link_unregister vmlinux EXPORT_SYMBOL_GPL ++0xe1ad275d copy_strings_kernel vmlinux EXPORT_SYMBOL ++0x751c2917 __wait_on_bit vmlinux EXPORT_SYMBOL ++0x55467ede fsl_upm_find vmlinux EXPORT_SYMBOL ++0x002de09c vfsmount_lock_global_unlock_online vmlinux EXPORT_SYMBOL ++0xc7156d34 hrtimer_get_remaining vmlinux EXPORT_SYMBOL_GPL ++0x3b42483e tcp_enter_memory_pressure vmlinux EXPORT_SYMBOL ++0x1df3dda5 skb_add_rx_frag vmlinux EXPORT_SYMBOL ++0xe9587909 usb_unregister_notify vmlinux EXPORT_SYMBOL_GPL ++0x4982a57f probe_kernel_write vmlinux EXPORT_SYMBOL_GPL ++0x972d7aee arp_create vmlinux EXPORT_SYMBOL ++0xf1e706a7 of_modalias_node vmlinux EXPORT_SYMBOL_GPL ++0xae30905c tty_port_alloc_xmit_buf vmlinux EXPORT_SYMBOL ++0x46d4fb35 no_llseek vmlinux EXPORT_SYMBOL ++0x7da3ce6f rt_mutex_timed_lock vmlinux EXPORT_SYMBOL_GPL ++0xeded8d0e rtc_irq_set_freq vmlinux EXPORT_SYMBOL_GPL ++0xf0fd4e8f rwsem_down_read_failed vmlinux EXPORT_SYMBOL ++0xc606cd3c boot_cpuid vmlinux EXPORT_SYMBOL_GPL ++0xfab35004 generic_show_options vmlinux EXPORT_SYMBOL ++0xbf79c72e pagecache_write_begin vmlinux EXPORT_SYMBOL ++0xe6e1982f register_sysctl_paths vmlinux EXPORT_SYMBOL ++0xc6cbbc89 capable vmlinux EXPORT_SYMBOL ++0x39688afa nf_afinfo vmlinux EXPORT_SYMBOL ++0xa4f7e7fb hid_debug_event vmlinux EXPORT_SYMBOL_GPL ++0x0a0a8628 mmc_can_trim vmlinux EXPORT_SYMBOL ++0x620ed98f input_set_capability vmlinux EXPORT_SYMBOL ++0x4ef5bcf4 perf_swevent_get_recursion_context vmlinux EXPORT_SYMBOL_GPL ++0xc8b57c27 autoremove_wake_function vmlinux EXPORT_SYMBOL ++0x13e5ea13 __wake_up_sync vmlinux EXPORT_SYMBOL_GPL ++0x2e8e2944 irq_find_mapping vmlinux EXPORT_SYMBOL_GPL ++0xb9c06bda nf_ct_port_tuple_to_nlattr net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x7c60d66e getname vmlinux EXPORT_SYMBOL ++0xe7ffe877 pcpu_base_addr vmlinux EXPORT_SYMBOL_GPL ++0xa78649d2 nf_conntrack_helper_register net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x9a11a0fc crypto_attr_alg_name vmlinux EXPORT_SYMBOL_GPL ++0x0d86c5c3 par_io_config_pin vmlinux EXPORT_SYMBOL ++0x1c852e7c xfrm_calg_get_byid vmlinux EXPORT_SYMBOL_GPL ++0x8b26f12b uhci_check_and_reset_hc vmlinux EXPORT_SYMBOL_GPL ++0x05520f5f usb_hc_died vmlinux EXPORT_SYMBOL_GPL ++0xe61a6d2f gpio_unexport vmlinux EXPORT_SYMBOL_GPL ++0xf20dabd8 free_irq vmlinux EXPORT_SYMBOL ++0xa861ab6e __ioremap vmlinux EXPORT_SYMBOL ++0x7976a3fa usb_serial_probe vmlinux EXPORT_SYMBOL_GPL ++0x2b2f2776 deactivate_locked_super vmlinux EXPORT_SYMBOL ++0x432b5ac1 filemap_fdatawait vmlinux EXPORT_SYMBOL ++0x432a0255 rpcauth_register vmlinux EXPORT_SYMBOL_GPL ++0x36ac1b69 xfrm_audit_policy_delete vmlinux EXPORT_SYMBOL_GPL ++0xfb788409 netdev_class_create_file vmlinux EXPORT_SYMBOL ++0x09d44df9 in_lock_functions vmlinux EXPORT_SYMBOL ++0x27e4a550 rpc_wake_up vmlinux EXPORT_SYMBOL_GPL ++0xe67b9f1c netpoll_parse_options vmlinux EXPORT_SYMBOL ++0xe4c4673a netdev_rx_handler_unregister vmlinux EXPORT_SYMBOL_GPL ++0xf3c9e5de skb_copy_datagram_const_iovec vmlinux EXPORT_SYMBOL ++0x1b0d73b7 kernel_getpeername vmlinux EXPORT_SYMBOL ++0xcca50e42 platform_driver_probe vmlinux EXPORT_SYMBOL_GPL ++0x2bb7074d serial8250_do_set_termios vmlinux EXPORT_SYMBOL ++0x436cab8f sysfs_chmod_file vmlinux EXPORT_SYMBOL_GPL ++0x1e69be37 find_module vmlinux EXPORT_SYMBOL_GPL ++0x09b54a84 rt_mutex_lock vmlinux EXPORT_SYMBOL_GPL ++0x28a9171c input_event vmlinux EXPORT_SYMBOL ++0x11f7ed4c hex_to_bin vmlinux EXPORT_SYMBOL ++0xa4338205 simple_pin_fs vmlinux EXPORT_SYMBOL ++0x5635a60a vmalloc_user vmlinux EXPORT_SYMBOL ++0x95fcd41e posix_clock_unregister vmlinux EXPORT_SYMBOL_GPL ++0x31bd442e schedule_delayed_work vmlinux EXPORT_SYMBOL ++0x4d45d89e udp_memory_allocated vmlinux EXPORT_SYMBOL ++0x99dbcc23 tc_classify vmlinux EXPORT_SYMBOL ++0x6b8e3569 sock_no_sendpage vmlinux EXPORT_SYMBOL ++0x6a61f874 to_tm vmlinux EXPORT_SYMBOL ++0x4b4a6de0 get_current_tty vmlinux EXPORT_SYMBOL_GPL ++0x4c1182cb bitmap_scnprintf vmlinux EXPORT_SYMBOL ++0xde6daef6 proc_create_data vmlinux EXPORT_SYMBOL ++0x810b3618 param_ops_string vmlinux EXPORT_SYMBOL ++0xcafc76d2 sunrpc_cache_register_pipefs vmlinux EXPORT_SYMBOL_GPL ++0x4d15f777 kernel_getsockname vmlinux EXPORT_SYMBOL ++0xa5ea73be kernel_sendmsg vmlinux EXPORT_SYMBOL ++0x5f965ae1 uart_register_driver vmlinux EXPORT_SYMBOL ++0xd77a5aa5 __bitmap_and vmlinux EXPORT_SYMBOL ++0xf3012f6c rh_free vmlinux EXPORT_SYMBOL_GPL ++0x38df0067 xfrm_alloc_spi vmlinux EXPORT_SYMBOL ++0xce2e6bf5 netdev_set_bond_master vmlinux EXPORT_SYMBOL ++0xdab749af blk_rq_err_bytes vmlinux EXPORT_SYMBOL_GPL ++0x5390ec7d crypto_blkcipher_type vmlinux EXPORT_SYMBOL_GPL ++0xd5ce0859 crypto_givcipher_type vmlinux EXPORT_SYMBOL_GPL ++0x001425a3 nf_log_packet vmlinux EXPORT_SYMBOL ++0xc9a72270 qdisc_tree_decrease_qlen vmlinux EXPORT_SYMBOL ++0xdd671a8d dev_remove_pack vmlinux EXPORT_SYMBOL ++0x2c256e1f input_scancode_to_scalar vmlinux EXPORT_SYMBOL ++0x647e76d5 rq_flush_dcache_pages vmlinux EXPORT_SYMBOL_GPL ++0xb6a0b482 blkcipher_walk_virt vmlinux EXPORT_SYMBOL_GPL ++0x9607f187 posix_lock_file vmlinux EXPORT_SYMBOL ++0x71a672ef dmam_pool_destroy vmlinux EXPORT_SYMBOL ++0xeb6bb956 set_page_dirty vmlinux EXPORT_SYMBOL ++0xde9360ba totalram_pages vmlinux EXPORT_SYMBOL ++0x6a0a2dcc nf_conntrack_l4proto_udp4 net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x31afdcc9 udp_disconnect vmlinux EXPORT_SYMBOL ++0xc9ef093b dev_uc_unsync vmlinux EXPORT_SYMBOL ++0x92cc73cf dev_mc_unsync vmlinux EXPORT_SYMBOL ++0xde68b34d usb_free_streams vmlinux EXPORT_SYMBOL_GPL ++0x106c8a3c dump_seek vmlinux EXPORT_SYMBOL ++0x67d84b74 mtd_add_partition vmlinux EXPORT_SYMBOL_GPL ++0xd0c663ae bus_get_kset vmlinux EXPORT_SYMBOL_GPL ++0x0874bd6b journal_get_write_access vmlinux EXPORT_SYMBOL ++0x2e4d6a64 __register_chrdev vmlinux EXPORT_SYMBOL ++0xe5919cb1 xdr_encode_opaque vmlinux EXPORT_SYMBOL_GPL ++0x100e6158 rtc_class_close vmlinux EXPORT_SYMBOL_GPL ++0x61c2dac6 kstrtoll_from_user vmlinux EXPORT_SYMBOL ++0x8e010d2c svc_max_payload vmlinux EXPORT_SYMBOL_GPL ++0x4be46578 devres_alloc vmlinux EXPORT_SYMBOL_GPL ++0x2ecee7fb sysdev_unregister vmlinux EXPORT_SYMBOL_GPL ++0xdc14eda7 pci_pci_problems vmlinux EXPORT_SYMBOL ++0x956a91ba gpio_get_value_cansleep vmlinux EXPORT_SYMBOL_GPL ++0x18bff16e blk_queue_stack_limits vmlinux EXPORT_SYMBOL ++0x01e56d33 free_vm_area vmlinux EXPORT_SYMBOL_GPL ++0x748022c5 nf_conntrack_free net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x9317d258 udp_lib_setsockopt vmlinux EXPORT_SYMBOL ++0xfad5b90d udp_lib_getsockopt vmlinux EXPORT_SYMBOL ++0x96898769 sysfs_format_mac vmlinux EXPORT_SYMBOL ++0xddbc1ffe sk_send_sigurg vmlinux EXPORT_SYMBOL ++0x246f019e spi_bus_lock vmlinux EXPORT_SYMBOL_GPL ++0xaa89d28e dev_crit vmlinux EXPORT_SYMBOL ++0x8e45aa4a drop_super vmlinux EXPORT_SYMBOL ++0x27e1a049 printk vmlinux EXPORT_SYMBOL ++0x2f97857d sk_alloc vmlinux EXPORT_SYMBOL ++0xa49390ab bus_unregister_notifier vmlinux EXPORT_SYMBOL_GPL ++0xc48f3373 try_to_release_page vmlinux EXPORT_SYMBOL ++0x7e448a8f synchronize_srcu vmlinux EXPORT_SYMBOL_GPL ++0x9aad6540 klist_iter_init vmlinux EXPORT_SYMBOL_GPL ++0xc3512c1e rpcauth_lookup_credcache vmlinux EXPORT_SYMBOL_GPL ++0x03bab655 platform_driver_register vmlinux EXPORT_SYMBOL_GPL ++0xe381eae4 kobject_add vmlinux EXPORT_SYMBOL ++0xf5a87370 nfs_commitdata_release vmlinux EXPORT_SYMBOL_GPL ++0x10138352 tracing_on vmlinux EXPORT_SYMBOL_GPL ++0x9025d41c xfrm_audit_policy_add vmlinux EXPORT_SYMBOL_GPL ++0x4cedc318 platform_driver_unregister vmlinux EXPORT_SYMBOL_GPL ++0x61634f05 lock_flocks vmlinux EXPORT_SYMBOL_GPL ++0xd19a96e6 queue_kthread_work vmlinux EXPORT_SYMBOL_GPL ++0x756dd160 start_thread vmlinux EXPORT_SYMBOL ++0x219de8a0 br_should_route_hook vmlinux EXPORT_SYMBOL ++0xf6190b08 gnet_stats_copy_queue vmlinux EXPORT_SYMBOL ++0x94ae4c23 of_match_device vmlinux EXPORT_SYMBOL ++0x2bb7992e usb_get_urb vmlinux EXPORT_SYMBOL_GPL ++0x4c715546 pci_scan_single_device vmlinux EXPORT_SYMBOL ++0x12e85778 kstrtol_from_user vmlinux EXPORT_SYMBOL ++0x3aad440e simple_dir_operations vmlinux EXPORT_SYMBOL ++0x6403e338 tcp_memory_pressure vmlinux EXPORT_SYMBOL ++0xb233762c atomic64_set vmlinux EXPORT_SYMBOL ++0xab0e7894 setattr_copy vmlinux EXPORT_SYMBOL ++0xc26c0f33 inet_frags_fini vmlinux EXPORT_SYMBOL ++0xe4cf504e scsi_queue_work vmlinux EXPORT_SYMBOL_GPL ++0x90ef84ba elv_dispatch_sort vmlinux EXPORT_SYMBOL ++0x891a622e elv_add_request vmlinux EXPORT_SYMBOL ++0xf346231f seq_list_start_head vmlinux EXPORT_SYMBOL ++0xa32629f6 dns_query vmlinux EXPORT_SYMBOL ++0x73e659e1 netif_device_attach vmlinux EXPORT_SYMBOL ++0x17de79c5 netif_device_detach vmlinux EXPORT_SYMBOL ++0xe94d82f3 sdhci_pltfm_init vmlinux EXPORT_SYMBOL_GPL ++0x9c247860 device_rename vmlinux EXPORT_SYMBOL_GPL ++0xc88c586d simple_attr_read vmlinux EXPORT_SYMBOL_GPL ++0x7e620c98 relay_flush vmlinux EXPORT_SYMBOL_GPL ++0xc12435e3 rpc_calc_rto vmlinux EXPORT_SYMBOL_GPL ++0x0ffe2bd3 kernel_bind vmlinux EXPORT_SYMBOL ++0xf511e930 dev_notice vmlinux EXPORT_SYMBOL ++0xcc248d26 serial8250_suspend_port vmlinux EXPORT_SYMBOL ++0xcd279169 nla_find vmlinux EXPORT_SYMBOL ++0x3a4dd68a kernel_read vmlinux EXPORT_SYMBOL ++0x8c7b3af2 vfs_read vmlinux EXPORT_SYMBOL ++0xc8add232 ring_buffer_record_disable vmlinux EXPORT_SYMBOL_GPL ++0xf68fe563 __devm_release_region vmlinux EXPORT_SYMBOL ++0xca559706 __inet_hash_nolisten vmlinux EXPORT_SYMBOL_GPL ++0x9fb3dd30 memcpy_fromiovec vmlinux EXPORT_SYMBOL ++0x7e40b8e4 pci_bus_find_capability vmlinux EXPORT_SYMBOL ++0x8a6d8c12 blk_queue_prep_rq vmlinux EXPORT_SYMBOL ++0x262f20a8 local_clock vmlinux EXPORT_SYMBOL_GPL ++0x5b7f8452 vlan_dev_vlan_id vmlinux EXPORT_SYMBOL ++0xce3148ed of_find_matching_node vmlinux EXPORT_SYMBOL ++0xe2457ef0 sysdev_class_register vmlinux EXPORT_SYMBOL_GPL ++0xd6f88a0e journal_unlock_updates vmlinux EXPORT_SYMBOL ++0x457de0d3 sunrpc_cache_unregister_pipefs vmlinux EXPORT_SYMBOL_GPL ++0x7e72637f __class_register vmlinux EXPORT_SYMBOL_GPL ++0xd5e8444a __div64_32 vmlinux EXPORT_SYMBOL ++0xf04ae1ba idr_remove_all vmlinux EXPORT_SYMBOL ++0x3446615d bio_alloc vmlinux EXPORT_SYMBOL ++0x93fca811 __get_free_pages vmlinux EXPORT_SYMBOL ++0xbb189cad disallow_signal vmlinux EXPORT_SYMBOL ++0xd3d2de27 rawv6_mh_filter_register vmlinux EXPORT_SYMBOL ++0xdbcd416e sysctl_ip_nonlocal_bind vmlinux EXPORT_SYMBOL ++0x8fd02ebd usb_free_coherent vmlinux EXPORT_SYMBOL_GPL ++0xa675804c utf8s_to_utf16s vmlinux EXPORT_SYMBOL ++0x31212876 proc_net_fops_create vmlinux EXPORT_SYMBOL_GPL ++0x39e569fd ns_capable vmlinux EXPORT_SYMBOL ++0x979a54c8 rawv6_mh_filter_unregister vmlinux EXPORT_SYMBOL ++0x7fd28838 mmc_fixup_device vmlinux EXPORT_SYMBOL ++0x0ea29024 blk_queue_resize_tags vmlinux EXPORT_SYMBOL ++0x4301f246 nf_ct_l3proto_find_get net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xb391c0ae ipv4_specific vmlinux EXPORT_SYMBOL ++0x3aa08439 proto_unregister vmlinux EXPORT_SYMBOL ++0x70e3ab78 i2c_new_dummy vmlinux EXPORT_SYMBOL_GPL ++0x14f9849f register_mtd_chip_driver vmlinux EXPORT_SYMBOL ++0x9334e2ee __fsnotify_inode_delete vmlinux EXPORT_SYMBOL_GPL ++0xfedbb984 deregister_mtd_parser vmlinux EXPORT_SYMBOL_GPL ++0x6e09073c __any_online_cpu vmlinux EXPORT_SYMBOL ++0xb0d651f5 lookup_instantiate_filp vmlinux EXPORT_SYMBOL_GPL ++0xadf0811d get_baudrate vmlinux EXPORT_SYMBOL ++0x6f7b3dee rtnl_af_register vmlinux EXPORT_SYMBOL_GPL ++0xc6c208cb kunmap_high vmlinux EXPORT_SYMBOL ++0xea8a6c75 param_ops_long vmlinux EXPORT_SYMBOL ++0xacf4d843 match_strdup vmlinux EXPORT_SYMBOL ++0x870bf928 radix_tree_lookup vmlinux EXPORT_SYMBOL ++0x4672e88b __crypto_dequeue_request vmlinux EXPORT_SYMBOL_GPL ++0x7b0f1ab3 ring_buffer_free_read_page vmlinux EXPORT_SYMBOL_GPL ++0xff00f5a4 rt_mutex_unlock vmlinux EXPORT_SYMBOL_GPL ++0xe9d6425d neigh_seq_next vmlinux EXPORT_SYMBOL ++0xb587371d vfs_rename vmlinux EXPORT_SYMBOL ++0x8c2d546c generic_ro_fops vmlinux EXPORT_SYMBOL ++0xabc5855f nf_nat_get_offset net/ipv4/netfilter/nf_nat EXPORT_SYMBOL_GPL ++0xc7037e1e user_path_create vmlinux EXPORT_SYMBOL ++0x78c76bdd kthread_bind vmlinux EXPORT_SYMBOL ++0xc92969b1 xprt_disconnect_done vmlinux EXPORT_SYMBOL_GPL ++0xefd8281a ipv6_setsockopt vmlinux EXPORT_SYMBOL ++0x17c3edfd usb_serial_port_softint vmlinux EXPORT_SYMBOL_GPL ++0x486bfa52 del_mtd_blktrans_dev vmlinux EXPORT_SYMBOL_GPL ++0xdd19ee65 cache_register vmlinux EXPORT_SYMBOL_GPL ++0xc92254c9 inet_frag_find vmlinux EXPORT_SYMBOL ++0x2b281f0e inetdev_by_index vmlinux EXPORT_SYMBOL ++0x7c6b8d30 usb_poison_anchored_urbs vmlinux EXPORT_SYMBOL_GPL ++0x75b20f59 eventfd_signal vmlinux EXPORT_SYMBOL_GPL ++0x21f678b9 clocksource_unregister vmlinux EXPORT_SYMBOL ++0x461ebfa0 __copy_tofrom_user vmlinux EXPORT_SYMBOL ++0xc9ed05e3 fifo_set_limit vmlinux EXPORT_SYMBOL ++0x195d71f7 writeback_in_progress vmlinux EXPORT_SYMBOL ++0x76b28f53 filemap_fdatawrite vmlinux EXPORT_SYMBOL ++0x807d2b2c xt_recseq vmlinux EXPORT_SYMBOL_GPL ++0xc6ff126b __ethtool_get_settings vmlinux EXPORT_SYMBOL ++0x17648396 dev_base_lock vmlinux EXPORT_SYMBOL ++0xbfb8b0b7 _raw_read_lock_irqsave vmlinux EXPORT_SYMBOL ++0x219da672 xt_request_find_target vmlinux EXPORT_SYMBOL_GPL ++0x5ec1f3aa sg_scsi_ioctl vmlinux EXPORT_SYMBOL_GPL ++0xc22a3091 vm_unmap_aliases vmlinux EXPORT_SYMBOL_GPL ++0x0cc6165c cpu_remove_dev_attr_group vmlinux EXPORT_SYMBOL_GPL ++0x418fdef0 gnet_stats_finish_copy vmlinux EXPORT_SYMBOL ++0x5e3c3f48 scsi_get_device_flags_keyed vmlinux EXPORT_SYMBOL ++0x7282cf02 device_show_int vmlinux EXPORT_SYMBOL_GPL ++0x94552a4e swiotlb_tbl_unmap_single vmlinux EXPORT_SYMBOL_GPL ++0x5a6143d7 blk_fetch_request vmlinux EXPORT_SYMBOL ++0xcee07d7c free_inode_nonrcu vmlinux EXPORT_SYMBOL ++0xb7cb7543 dma_pool_create vmlinux EXPORT_SYMBOL ++0x4b34fbf5 block_all_signals vmlinux EXPORT_SYMBOL ++0x1e7af842 sdio_writeb vmlinux EXPORT_SYMBOL_GPL ++0x2e5f37cd usb_hcd_pci_probe vmlinux EXPORT_SYMBOL_GPL ++0x955a8e9a tty_name vmlinux EXPORT_SYMBOL ++0xb5aa7165 dma_pool_destroy vmlinux EXPORT_SYMBOL ++0x9045913c of_dev_put vmlinux EXPORT_SYMBOL ++0x78ab4762 of_dev_get vmlinux EXPORT_SYMBOL ++0xc22d32e4 sysfs_get_dirent vmlinux EXPORT_SYMBOL_GPL ++0x35f7dc5f perf_event_release_kernel vmlinux EXPORT_SYMBOL_GPL ++0x8c03d20c destroy_workqueue vmlinux EXPORT_SYMBOL_GPL ++0xd5901a2e inet6_csk_reqsk_queue_hash_add vmlinux EXPORT_SYMBOL_GPL ++0x7aff474c inet_twsk_put vmlinux EXPORT_SYMBOL_GPL ++0x6409d9b1 fib_default_rule_add vmlinux EXPORT_SYMBOL ++0xc1402a83 do_SAK vmlinux EXPORT_SYMBOL ++0xb5c93022 pci_load_and_free_saved_state vmlinux EXPORT_SYMBOL_GPL ++0x4ed00fb3 pci_save_state vmlinux EXPORT_SYMBOL ++0x5581df9d fat_get_dotdot_entry vmlinux EXPORT_SYMBOL_GPL ++0xcc19c3b6 check_disk_change vmlinux EXPORT_SYMBOL ++0xbcce8393 default_file_splice_read vmlinux EXPORT_SYMBOL ++0x32b2fbcf writeback_inodes_sb vmlinux EXPORT_SYMBOL ++0x8e555738 param_get_uint vmlinux EXPORT_SYMBOL ++0x5d650a5f elv_register vmlinux EXPORT_SYMBOL_GPL ++0x4523b9b7 page_put_link vmlinux EXPORT_SYMBOL ++0xcd70c7f7 release_pages vmlinux EXPORT_SYMBOL ++0xb4cab2ed rpc_sleep_on vmlinux EXPORT_SYMBOL_GPL ++0xc1a33294 km_state_expired vmlinux EXPORT_SYMBOL ++0xfef1d118 qdisc_list_del vmlinux EXPORT_SYMBOL ++0xb0e10781 get_option vmlinux EXPORT_SYMBOL ++0xb323ab9f nf_ct_gre_keymap_destroy net/netfilter/nf_conntrack_proto_gre EXPORT_SYMBOL_GPL ++0xce19bac5 register_inet6addr_notifier vmlinux EXPORT_SYMBOL ++0xcb117d64 inet_accept vmlinux EXPORT_SYMBOL ++0x49b07aec tcp_select_initial_window vmlinux EXPORT_SYMBOL ++0x762ff2b9 register_pernet_device vmlinux EXPORT_SYMBOL_GPL ++0x33b91f1c class_for_each_device vmlinux EXPORT_SYMBOL_GPL ++0xe697d108 __blk_iopoll_complete vmlinux EXPORT_SYMBOL ++0x13e38f5c up_read vmlinux EXPORT_SYMBOL ++0xa1c76e0a _cond_resched vmlinux EXPORT_SYMBOL ++0x595d0946 empty_zero_page vmlinux EXPORT_SYMBOL ++0x76e2075c nfnetlink_subsys_register net/netfilter/nfnetlink EXPORT_SYMBOL_GPL ++0xe5205ca9 __pskb_pull_tail vmlinux EXPORT_SYMBOL ++0x123a8ed7 mtd_is_partition vmlinux EXPORT_SYMBOL_GPL ++0x25c7b476 dev_alert vmlinux EXPORT_SYMBOL ++0xa8e85346 tty_wait_until_sent vmlinux EXPORT_SYMBOL ++0x74d1c3d7 bioset_free vmlinux EXPORT_SYMBOL ++0x7362dd1e vfs_fstat vmlinux EXPORT_SYMBOL ++0x127f1cf8 vfs_lstat vmlinux EXPORT_SYMBOL ++0x5b9828c5 dma_spin_lock vmlinux EXPORT_SYMBOL ++0x20bc3470 orderly_poweroff vmlinux EXPORT_SYMBOL_GPL ++0x0be13004 usb_storage_usb_ids vmlinux EXPORT_SYMBOL_GPL ++0x1556756b usermodehelper_is_disabled vmlinux EXPORT_SYMBOL_GPL ++0x82e704cc __netif_schedule vmlinux EXPORT_SYMBOL ++0x63f7a522 gpio_export_link vmlinux EXPORT_SYMBOL_GPL ++0x75bb9ca1 generic_fh_to_parent vmlinux EXPORT_SYMBOL_GPL ++0xc123374d generic_fillattr vmlinux EXPORT_SYMBOL ++0x183fa88b mempool_alloc_slab vmlinux EXPORT_SYMBOL ++0x379f5837 param_set_invbool vmlinux EXPORT_SYMBOL ++0xc5534d64 ioread16 vmlinux EXPORT_SYMBOL ++0x9f185a94 i2c_register_driver vmlinux EXPORT_SYMBOL ++0x343b3ac1 pci_bus_alloc_resource vmlinux EXPORT_SYMBOL ++0x6579d2f7 d_instantiate_unique vmlinux EXPORT_SYMBOL ++0xd6b8e852 request_threaded_irq vmlinux EXPORT_SYMBOL ++0x9d7ce8dd _raw_spin_trylock vmlinux EXPORT_SYMBOL ++0xc496da96 svc_drop vmlinux EXPORT_SYMBOL_GPL ++0x3a24b303 mutex_lock_interruptible vmlinux EXPORT_SYMBOL ++0xf47788cf skb_clone vmlinux EXPORT_SYMBOL ++0xad167cd8 input_get_keycode vmlinux EXPORT_SYMBOL ++0x6afa9ce8 crypto_find_alg vmlinux EXPORT_SYMBOL_GPL ++0xc6aac677 set_task_ioprio vmlinux EXPORT_SYMBOL_GPL ++0xbe5e9490 setup_arg_pages vmlinux EXPORT_SYMBOL ++0x5dc8d493 usb_serial_generic_process_read_urb vmlinux EXPORT_SYMBOL_GPL ++0x055c3bb2 inode_dio_wait vmlinux EXPORT_SYMBOL_GPL ++0xc34efe27 snmp_fold_field vmlinux EXPORT_SYMBOL_GPL ++0x9d5a6e79 tcp_init_xmit_timers vmlinux EXPORT_SYMBOL ++0x93f1e027 phy_ethtool_gset vmlinux EXPORT_SYMBOL ++0xc200ab97 phy_ethtool_sset vmlinux EXPORT_SYMBOL ++0xd67364f7 eventfd_ctx_fdget vmlinux EXPORT_SYMBOL_GPL ++0x446b3e02 thermal_zone_device_unregister vmlinux EXPORT_SYMBOL ++0x4980c504 vfs_lock_file vmlinux EXPORT_SYMBOL_GPL ++0xa00f2ea1 bio_uncopy_user vmlinux EXPORT_SYMBOL ++0x07f3051f make_bad_inode vmlinux EXPORT_SYMBOL ++0x04cb56f3 __d_drop vmlinux EXPORT_SYMBOL ++0xadb98035 __mmdrop vmlinux EXPORT_SYMBOL_GPL ++0x3065f579 gss_mech_unregister vmlinux EXPORT_SYMBOL_GPL ++0x33dbfd93 tcp_memory_allocated vmlinux EXPORT_SYMBOL ++0xea7be216 hid_check_keys_pressed vmlinux EXPORT_SYMBOL_GPL ++0x0a2e681f scsi_bus_type vmlinux EXPORT_SYMBOL_GPL ++0xa8232c78 strtobool vmlinux EXPORT_SYMBOL ++0xa807009b seq_release_private vmlinux EXPORT_SYMBOL ++0xb9ea2b35 clear_user_page vmlinux EXPORT_SYMBOL ++0x94d397ff uart_console_write vmlinux EXPORT_SYMBOL_GPL ++0x7b59e193 writeback_inodes_sb_nr vmlinux EXPORT_SYMBOL ++0x4f005ac7 vfs_removexattr vmlinux EXPORT_SYMBOL_GPL ++0x3bc25df9 find_symbol vmlinux EXPORT_SYMBOL_GPL ++0x55139b31 __mutex_init vmlinux EXPORT_SYMBOL ++0x807fb25f sdio_readsb vmlinux EXPORT_SYMBOL_GPL ++0x73883f28 mmc_host_enable vmlinux EXPORT_SYMBOL ++0xa4536a78 rtc_set_time vmlinux EXPORT_SYMBOL_GPL ++0x131e5c6e pcix_get_mmrbc vmlinux EXPORT_SYMBOL ++0x6f7d4b21 auth_domain_lookup vmlinux EXPORT_SYMBOL_GPL ++0x0b0d888b icmpv6_err_convert vmlinux EXPORT_SYMBOL ++0x6a010ac4 xfrm_audit_state_delete vmlinux EXPORT_SYMBOL_GPL ++0x7f00decc serial8250_register_port vmlinux EXPORT_SYMBOL ++0xd40d44fb vfs_readv vmlinux EXPORT_SYMBOL ++0xe10285f5 do_sync_write vmlinux EXPORT_SYMBOL ++0x3a63d1e5 mmc_detect_change vmlinux EXPORT_SYMBOL ++0xfe29a782 crypto_shash_setkey vmlinux EXPORT_SYMBOL_GPL ++0x1ad011b8 crypto_ahash_setkey vmlinux EXPORT_SYMBOL_GPL ++0x6b569c7b search_binary_handler vmlinux EXPORT_SYMBOL ++0xaa5dc44d rt_mutex_trylock vmlinux EXPORT_SYMBOL_GPL ++0xa0cc8b48 rtnl_link_get_net vmlinux EXPORT_SYMBOL ++0x4d88ec39 sdio_readw vmlinux EXPORT_SYMBOL_GPL ++0x7a1cde57 sdio_readl vmlinux EXPORT_SYMBOL_GPL ++0x1b2bbad1 sdio_readb vmlinux EXPORT_SYMBOL_GPL ++0xdc8e7a1f usb_remove_hcd vmlinux EXPORT_SYMBOL_GPL ++0x861c1a61 ahash_attr_alg vmlinux EXPORT_SYMBOL_GPL ++0xcfb5871c irq_work_queue vmlinux EXPORT_SYMBOL_GPL ++0x6bac7336 tcp_disconnect vmlinux EXPORT_SYMBOL ++0x0d030f2e put_device vmlinux EXPORT_SYMBOL_GPL ++0xb675788e nfs_initiate_write vmlinux EXPORT_SYMBOL_GPL ++0xef990a5a bio_pair_release vmlinux EXPORT_SYMBOL ++0xd44a50f2 spi_alloc_device vmlinux EXPORT_SYMBOL_GPL ++0xece65659 journal_start vmlinux EXPORT_SYMBOL ++0x77a203d6 register_filesystem vmlinux EXPORT_SYMBOL ++0xba497f13 loops_per_jiffy vmlinux EXPORT_SYMBOL ++0xd850fe94 eth_validate_addr vmlinux EXPORT_SYMBOL ++0xc5718627 sg_copy_to_buffer vmlinux EXPORT_SYMBOL ++0xc316b98c jiffies_to_clock_t vmlinux EXPORT_SYMBOL ++0x0c875058 usb_debug_root vmlinux EXPORT_SYMBOL_GPL ++0x69ef82cd generic_make_request vmlinux EXPORT_SYMBOL ++0x308c701c generic_file_llseek_size vmlinux EXPORT_SYMBOL ++0x38bd731f queue_delayed_work vmlinux EXPORT_SYMBOL_GPL ++0x1c87a811 __round_jiffies_up vmlinux EXPORT_SYMBOL_GPL ++0x98fe7882 DMA_MODE_READ vmlinux EXPORT_SYMBOL ++0x1c80de9c ip_send_check vmlinux EXPORT_SYMBOL ++0xdc8e4d19 __rtnl_register vmlinux EXPORT_SYMBOL_GPL ++0xa6c839d3 usb_serial_generic_disconnect vmlinux EXPORT_SYMBOL_GPL ++0x57db7242 mangle_path vmlinux EXPORT_SYMBOL ++0x81612cb7 pci_get_domain_bus_and_slot vmlinux EXPORT_SYMBOL ++0x4cd416fe anon_inode_getfd vmlinux EXPORT_SYMBOL_GPL ++0xef22332a filemap_flush vmlinux EXPORT_SYMBOL ++0xa4a94d26 find_next_bit_le vmlinux EXPORT_SYMBOL ++0xc1d7d179 blk_stack_limits vmlinux EXPORT_SYMBOL ++0x28ea0728 of_scan_bus vmlinux EXPORT_SYMBOL_GPL ++0x774b6448 unix_domain_find vmlinux EXPORT_SYMBOL_GPL ++0xcc8ebe78 tcp_set_state vmlinux EXPORT_SYMBOL_GPL ++0x00239c1b i2c_smbus_read_i2c_block_data vmlinux EXPORT_SYMBOL ++0x9bd59d1d tty_mutex vmlinux EXPORT_SYMBOL ++0xb28f5ef1 xt_free_table_info vmlinux EXPORT_SYMBOL ++0x0e1fa4e9 mnt_pin vmlinux EXPORT_SYMBOL ++0x616456a1 set_create_files_as vmlinux EXPORT_SYMBOL ++0xb609d16c dev_get_by_name vmlinux EXPORT_SYMBOL ++0x8848b690 __page_symlink vmlinux EXPORT_SYMBOL ++0xd2044f1c install_exec_creds vmlinux EXPORT_SYMBOL ++0xaf488b30 sched_setscheduler vmlinux EXPORT_SYMBOL_GPL ++0x6923ce63 irq_work_sync vmlinux EXPORT_SYMBOL_GPL ++0x30a80826 __kfifo_from_user vmlinux EXPORT_SYMBOL ++0x595c70ed ipcomp_input net/xfrm/xfrm_ipcomp EXPORT_SYMBOL_GPL ++0xead1e53c xdr_skb_read_bits vmlinux EXPORT_SYMBOL_GPL ++0xf20020d8 udp_prot vmlinux EXPORT_SYMBOL ++0x552567c0 inet_putpeer vmlinux EXPORT_SYMBOL_GPL ++0x6a1a16cb mmc_card_sleep vmlinux EXPORT_SYMBOL ++0x0c167229 i2c_adapter_type vmlinux EXPORT_SYMBOL_GPL ++0xebd52fa9 inet6_sk_rebuild_header vmlinux EXPORT_SYMBOL_GPL ++0xe506bc98 mb_cache_shrink vmlinux EXPORT_SYMBOL ++0x2d3385d3 system_wq vmlinux EXPORT_SYMBOL_GPL ++0xf1e98c74 avenrun vmlinux EXPORT_SYMBOL ++0x366e962c nf_ct_extend_register net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x634b5ff0 mmc_calc_max_discard vmlinux EXPORT_SYMBOL ++0xb1356813 register_mtd_parser vmlinux EXPORT_SYMBOL_GPL ++0x3281f449 mark_page_accessed vmlinux EXPORT_SYMBOL ++0x9cb8037b xfrm_count_enc_supported vmlinux EXPORT_SYMBOL_GPL ++0x02a18c74 nf_conntrack_destroy vmlinux EXPORT_SYMBOL ++0x7cac5792 scsi_report_bus_reset vmlinux EXPORT_SYMBOL ++0x5c8a36aa ip6_sk_dst_lookup_flow vmlinux EXPORT_SYMBOL_GPL ++0x460f95b8 hid_output_report vmlinux EXPORT_SYMBOL_GPL ++0xaa072d41 cdev_add vmlinux EXPORT_SYMBOL ++0xfcd7bc0b ring_buffer_empty vmlinux EXPORT_SYMBOL_GPL ++0x69447467 ring_buffer_write vmlinux EXPORT_SYMBOL_GPL ++0x82939ebd rcu_batches_completed_sched vmlinux EXPORT_SYMBOL_GPL ++0xeeacab69 rpc_update_rtt vmlinux EXPORT_SYMBOL_GPL ++0x6ee56ac5 xfrm_input vmlinux EXPORT_SYMBOL ++0x7fccf2c7 dev_mc_del vmlinux EXPORT_SYMBOL ++0xd44258b7 dev_uc_add vmlinux EXPORT_SYMBOL ++0x54a36ee2 dev_mc_add vmlinux EXPORT_SYMBOL ++0xff2dc492 dev_uc_del vmlinux EXPORT_SYMBOL ++0xe17df33d register_pernet_subsys vmlinux EXPORT_SYMBOL_GPL ++0xef850ef5 rtc_update_irq vmlinux EXPORT_SYMBOL_GPL ++0xebdef3fd blk_queue_update_dma_pad vmlinux EXPORT_SYMBOL ++0x30d8f8a2 blkdev_get_by_path vmlinux EXPORT_SYMBOL ++0x8745258d open_exec vmlinux EXPORT_SYMBOL ++0x5fc3a25a cpu_subsys vmlinux EXPORT_SYMBOL_GPL ++0x00f7937a mb_cache_entry_find_next vmlinux EXPORT_SYMBOL ++0xef3c9907 inode_init_owner vmlinux EXPORT_SYMBOL ++0x0b48677a __kfifo_init vmlinux EXPORT_SYMBOL ++0xd7d19d8c pci_find_next_capability vmlinux EXPORT_SYMBOL_GPL ++0xa166674c journal_forget vmlinux EXPORT_SYMBOL ++0xe6506d9b rt_mutex_destroy vmlinux EXPORT_SYMBOL_GPL ++0xa8b1f0bd queue_delayed_work_on vmlinux EXPORT_SYMBOL_GPL ++0xd4034828 system_freezable_wq vmlinux EXPORT_SYMBOL_GPL ++0x615be263 devres_open_group vmlinux EXPORT_SYMBOL_GPL ++0x5b19634d div_s64_rem vmlinux EXPORT_SYMBOL ++0x4a2e3575 __set_page_dirty_nobuffers vmlinux EXPORT_SYMBOL ++0x4b08f423 __nf_ct_kill_acct net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x0561fdb5 svc_xprt_copy_addrs vmlinux EXPORT_SYMBOL_GPL ++0x48000553 mempool_create_node vmlinux EXPORT_SYMBOL ++0xd853827a find_get_pid vmlinux EXPORT_SYMBOL_GPL ++0x1826f0a0 dev_set_promiscuity vmlinux EXPORT_SYMBOL ++0x42ee873c usb_stor_transparent_scsi_command vmlinux EXPORT_SYMBOL_GPL ++0x0eaa69cc scsi_bios_ptable vmlinux EXPORT_SYMBOL ++0x9f4e5960 pci_write_vpd vmlinux EXPORT_SYMBOL ++0x169d875d neigh_connected_output vmlinux EXPORT_SYMBOL ++0xe9f7149c zlib_deflate_workspacesize vmlinux EXPORT_SYMBOL ++0x11633870 param_set_ushort vmlinux EXPORT_SYMBOL ++0x7ae5d317 qe_get_snum vmlinux EXPORT_SYMBOL ++0x910e2911 qe_put_snum vmlinux EXPORT_SYMBOL ++0x4fba15b0 svc_recv vmlinux EXPORT_SYMBOL_GPL ++0x5dcfccd8 udp_flush_pending_frames vmlinux EXPORT_SYMBOL ++0xd445ec0d netlink_kernel_create vmlinux EXPORT_SYMBOL ++0xe5da4ca8 dev_get_stats vmlinux EXPORT_SYMBOL ++0x86fb9b05 bitmap_parse_user vmlinux EXPORT_SYMBOL ++0x01000e51 schedule vmlinux EXPORT_SYMBOL ++0x4f040a49 nlmsg_notify vmlinux EXPORT_SYMBOL ++0x9ac0cf66 mmput vmlinux EXPORT_SYMBOL_GPL ++0x9d438cba init_task vmlinux EXPORT_SYMBOL ++0x0a52a70f rpc_task_reset_client vmlinux EXPORT_SYMBOL_GPL ++0x871477d5 sysdev_class_remove_file vmlinux EXPORT_SYMBOL_GPL ++0x17e28473 fsl_upm_run_pattern vmlinux EXPORT_SYMBOL ++0x262e8cd3 pcibios_resource_to_bus vmlinux EXPORT_SYMBOL ++0x89d66811 build_ehash_secret vmlinux EXPORT_SYMBOL ++0x38e36730 __inet_twsk_hashdance vmlinux EXPORT_SYMBOL_GPL ++0xdfd88ae5 neigh_table_init_no_netlink vmlinux EXPORT_SYMBOL ++0x3c17abfe gnet_stats_copy_app vmlinux EXPORT_SYMBOL ++0x9567b24a i2c_verify_client vmlinux EXPORT_SYMBOL ++0xa2557f57 input_allocate_device vmlinux EXPORT_SYMBOL ++0x1cd4aca8 dev_printk vmlinux EXPORT_SYMBOL ++0x655a6117 pci_set_pcie_reset_state vmlinux EXPORT_SYMBOL_GPL ++0x1b015d25 bitmap_parselist vmlinux EXPORT_SYMBOL ++0x66e042c6 __insert_inode_hash vmlinux EXPORT_SYMBOL ++0x0619ca8a getboottime vmlinux EXPORT_SYMBOL_GPL ++0x80b9cedd revert_creds vmlinux EXPORT_SYMBOL ++0xdf929370 fs_overflowgid vmlinux EXPORT_SYMBOL ++0x9c5f81da cpu_rmap_add vmlinux EXPORT_SYMBOL ++0x0b157e07 swiotlb_unmap_sg_attrs vmlinux EXPORT_SYMBOL ++0x6b252ff6 bio_clone vmlinux EXPORT_SYMBOL ++0xedb52e09 xfrm_policy_walk vmlinux EXPORT_SYMBOL ++0x32f08411 blocking_notifier_call_chain vmlinux EXPORT_SYMBOL_GPL ++0xf6428305 nfs_init_commit vmlinux EXPORT_SYMBOL_GPL ++0x594bf15b ioport_map vmlinux EXPORT_SYMBOL ++0x8cff16ad xfrm_audit_state_add vmlinux EXPORT_SYMBOL_GPL ++0x83b50e64 __skb_checksum_complete vmlinux EXPORT_SYMBOL ++0xed302f0f tty_lock vmlinux EXPORT_SYMBOL ++0xb5a459dc unregister_blkdev vmlinux EXPORT_SYMBOL ++0x3ebc5a82 key_alloc vmlinux EXPORT_SYMBOL ++0xa4b0ca7b write_inode_now vmlinux EXPORT_SYMBOL ++0x5da7c835 sysdev_store_ulong vmlinux EXPORT_SYMBOL_GPL ++0x1bc4ff03 tty_termios_hw_change vmlinux EXPORT_SYMBOL ++0xf2d69a5d fat_search_long vmlinux EXPORT_SYMBOL_GPL ++0x5e181c16 seq_path vmlinux EXPORT_SYMBOL ++0xcc5005fe msleep_interruptible vmlinux EXPORT_SYMBOL ++0xf8b2ff6e g_verify_token_header vmlinux EXPORT_SYMBOL_GPL ++0x7345829d dev_addr_add vmlinux EXPORT_SYMBOL ++0x99544b2e netdev_err vmlinux EXPORT_SYMBOL ++0x65414e67 dev_valid_name vmlinux EXPORT_SYMBOL ++0x3be89d3c usb_register_notify vmlinux EXPORT_SYMBOL_GPL ++0xd2a941d4 sg_init_table vmlinux EXPORT_SYMBOL ++0x5642793a radix_tree_tag_clear vmlinux EXPORT_SYMBOL ++0x17115d7c fsnotify vmlinux EXPORT_SYMBOL_GPL ++0x04d7d50a generic_file_open vmlinux EXPORT_SYMBOL ++0xa357d56e ktime_get vmlinux EXPORT_SYMBOL_GPL ++0x5e4ed6a0 genphy_update_link vmlinux EXPORT_SYMBOL ++0xa0df5c38 generic_cont_expand_simple vmlinux EXPORT_SYMBOL ++0x9000a23c d_instantiate vmlinux EXPORT_SYMBOL ++0x1b6b594c blk_queue_rq_timed_out vmlinux EXPORT_SYMBOL_GPL ++0x08c473b7 xt_alloc_table_info vmlinux EXPORT_SYMBOL ++0xb2f5f9e1 sysdev_create_file vmlinux EXPORT_SYMBOL_GPL ++0xb7b61546 crc32_be vmlinux EXPORT_SYMBOL ++0xe52fec95 rpc_restart_call vmlinux EXPORT_SYMBOL_GPL ++0x660920a6 xfrm_output_resume vmlinux EXPORT_SYMBOL_GPL ++0xc84ba62e skb_find_text vmlinux EXPORT_SYMBOL ++0x500e2d6e i2c_unregister_device vmlinux EXPORT_SYMBOL_GPL ++0xb088b8f4 pci_clear_master vmlinux EXPORT_SYMBOL ++0x1b848d78 current_fs_time vmlinux EXPORT_SYMBOL ++0xc009c0f0 skb_queue_tail vmlinux EXPORT_SYMBOL ++0x953db383 free_irq_cpu_rmap vmlinux EXPORT_SYMBOL ++0x530dca11 crypto_lookup_template vmlinux EXPORT_SYMBOL_GPL ++0x1608951e vfs_test_lock vmlinux EXPORT_SYMBOL_GPL ++0x952664c5 do_exit vmlinux EXPORT_SYMBOL_GPL ++0x7dbeb00f mmc_host_lazy_disable vmlinux EXPORT_SYMBOL ++0xc46197ca mark_buffer_dirty_inode vmlinux EXPORT_SYMBOL ++0x3109b751 cpu_clock vmlinux EXPORT_SYMBOL_GPL ++0x07121133 __put_mtd_device vmlinux EXPORT_SYMBOL_GPL ++0xefbe88ae __get_mtd_device vmlinux EXPORT_SYMBOL_GPL ++0x56011f32 scsi_execute_req vmlinux EXPORT_SYMBOL ++0x33543801 queue_work vmlinux EXPORT_SYMBOL_GPL ++0xb1c3a01a oops_in_progress vmlinux EXPORT_SYMBOL ++0xf1ec57f6 tty_insert_flip_string_fixed_flag vmlinux EXPORT_SYMBOL ++0x19a433b2 tty_register_ldisc vmlinux EXPORT_SYMBOL ++0x1dad9e54 tty_throttle vmlinux EXPORT_SYMBOL ++0xb72b50d8 tty_check_change vmlinux EXPORT_SYMBOL ++0x57f7d2b8 blk_get_backing_dev_info vmlinux EXPORT_SYMBOL ++0xf1abb528 elevator_init vmlinux EXPORT_SYMBOL ++0xe0423822 kill_fasync vmlinux EXPORT_SYMBOL ++0x736c79dc param_get_byte vmlinux EXPORT_SYMBOL ++0x69708997 dev_disable_lro vmlinux EXPORT_SYMBOL ++0x446c0616 attribute_container_classdev_to_container vmlinux EXPORT_SYMBOL_GPL ++0x7d2b62e9 kblockd_schedule_delayed_work vmlinux EXPORT_SYMBOL ++0x6f2fe28d debugfs_create_u8 vmlinux EXPORT_SYMBOL_GPL ++0x6c8d5ae8 __gpio_get_value vmlinux EXPORT_SYMBOL_GPL ++0x432fd7f6 __gpio_set_value vmlinux EXPORT_SYMBOL_GPL ++0xd62c833f schedule_timeout vmlinux EXPORT_SYMBOL ++0x2cadb791 netlink_dump_start vmlinux EXPORT_SYMBOL ++0x65ccb6f0 call_netevent_notifiers vmlinux EXPORT_SYMBOL_GPL ++0xd1cc0681 percpu_counter_compare vmlinux EXPORT_SYMBOL ++0xc365ca35 crypto_alloc_base vmlinux EXPORT_SYMBOL_GPL ++0x7e92c53a aio_put_req vmlinux EXPORT_SYMBOL ++0xb8bddf33 ip6t_ext_hdr net/ipv6/netfilter/ip6_tables EXPORT_SYMBOL ++0x8e0b7743 ipv6_ext_hdr vmlinux EXPORT_SYMBOL ++0x5c311da9 neigh_destroy vmlinux EXPORT_SYMBOL ++0x914859fb netdev_warn vmlinux EXPORT_SYMBOL ++0x32445441 mmc_wait_for_app_cmd vmlinux EXPORT_SYMBOL ++0xcefcd99a serial8250_unregister_port vmlinux EXPORT_SYMBOL ++0x0c077439 blk_end_request_cur vmlinux EXPORT_SYMBOL ++0x5aed1672 replace_mount_options vmlinux EXPORT_SYMBOL ++0x37ea921e vfsmount_lock_local_lock_cpu vmlinux EXPORT_SYMBOL ++0x7303f848 __xfrm_policy_check vmlinux EXPORT_SYMBOL ++0xe9f5462d blk_lld_busy vmlinux EXPORT_SYMBOL_GPL ++0x70f16495 blk_sync_queue vmlinux EXPORT_SYMBOL ++0xf15a9bc6 skb_clone_tx_timestamp vmlinux EXPORT_SYMBOL_GPL ++0xdbba9970 pskb_copy vmlinux EXPORT_SYMBOL ++0x9da1d86b scsi_schedule_eh vmlinux EXPORT_SYMBOL_GPL ++0xa0b474d5 class_unregister vmlinux EXPORT_SYMBOL_GPL ++0xa185f0cd fat_alloc_new_dir vmlinux EXPORT_SYMBOL_GPL ++0x17368f42 simple_write_end vmlinux EXPORT_SYMBOL ++0x37d2c2c5 rh_dump_blk vmlinux EXPORT_SYMBOL_GPL ++0xd07885a5 ip_mc_rejoin_groups vmlinux EXPORT_SYMBOL ++0xa6f04ef7 netdev_update_features vmlinux EXPORT_SYMBOL ++0x45f9ef6a spi_async vmlinux EXPORT_SYMBOL_GPL ++0xd75c79df smp_call_function vmlinux EXPORT_SYMBOL ++0xef6c3f70 round_jiffies_up_relative vmlinux EXPORT_SYMBOL_GPL ++0xd5c1febc of_rescan_bus vmlinux EXPORT_SYMBOL_GPL ++0xd5b2e52a single_step_exception vmlinux EXPORT_SYMBOL ++0xe3f587bb eth_header_cache vmlinux EXPORT_SYMBOL ++0xfd3a2bf8 i2c_smbus_read_byte_data vmlinux EXPORT_SYMBOL ++0xca5dbc50 scsi_print_sense_hdr vmlinux EXPORT_SYMBOL ++0x6bedb1fb scsi_host_lookup vmlinux EXPORT_SYMBOL ++0x83ed980f uart_set_options vmlinux EXPORT_SYMBOL_GPL ++0xf385cf08 pci_find_capability vmlinux EXPORT_SYMBOL ++0x0675c7eb atomic64_cmpxchg vmlinux EXPORT_SYMBOL ++0xb9d025c9 llist_del_first vmlinux EXPORT_SYMBOL_GPL ++0xb678366f int_sqrt vmlinux EXPORT_SYMBOL ++0xfdbe54c4 dec_zone_page_state vmlinux EXPORT_SYMBOL ++0x0799aca4 local_bh_enable vmlinux EXPORT_SYMBOL ++0xf38bcdf3 nf_conntrack_max net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x60763401 tcp_syn_flood_action vmlinux EXPORT_SYMBOL ++0xb9099fb2 llc_mac_hdr_init vmlinux EXPORT_SYMBOL ++0xee8d918e journal_dirty_metadata vmlinux EXPORT_SYMBOL ++0x1eb9516e round_jiffies_relative vmlinux EXPORT_SYMBOL_GPL ++0x17aa156a __ucmpdi2 vmlinux EXPORT_SYMBOL ++0xfab60503 klist_iter_init_node vmlinux EXPORT_SYMBOL_GPL ++0x0634100a bitmap_parselist_user vmlinux EXPORT_SYMBOL ++0xf45c1434 ida_simple_get vmlinux EXPORT_SYMBOL ++0xe87ffb37 blk_queue_update_dma_alignment vmlinux EXPORT_SYMBOL ++0x18d30e30 blk_start_request vmlinux EXPORT_SYMBOL ++0x7c003aef _raw_read_lock_irq vmlinux EXPORT_SYMBOL ++0xf243a51d hrtimer_try_to_cancel vmlinux EXPORT_SYMBOL_GPL ++0xbb543a9f nf_register_hook vmlinux EXPORT_SYMBOL ++0xae870b28 __dev_get_by_name vmlinux EXPORT_SYMBOL ++0x4cfd46aa skb_copy_and_csum_dev vmlinux EXPORT_SYMBOL ++0xb02612a3 input_unregister_handle vmlinux EXPORT_SYMBOL ++0x7e6c28a6 usb_hcd_map_urb_for_dma vmlinux EXPORT_SYMBOL_GPL ++0x8e63350d idr_replace vmlinux EXPORT_SYMBOL ++0x82acfb70 blk_iopoll_sched vmlinux EXPORT_SYMBOL ++0xaa17a2e2 rh_alloc_align vmlinux EXPORT_SYMBOL_GPL ++0x2c7db649 irq_dispose_mapping vmlinux EXPORT_SYMBOL_GPL ++0x2971c44c register_netdev vmlinux EXPORT_SYMBOL ++0xa8223905 blk_limits_io_opt vmlinux EXPORT_SYMBOL ++0x612e9fe1 inet_twsk_purge vmlinux EXPORT_SYMBOL_GPL ++0x9e9f1714 __bitmap_andnot vmlinux EXPORT_SYMBOL ++0x737de5e9 radix_tree_tag_get vmlinux EXPORT_SYMBOL ++0x9941925e get_pci_dma_ops vmlinux EXPORT_SYMBOL ++0xc7041cc2 skb_seq_read vmlinux EXPORT_SYMBOL ++0x712be89f i2c_transfer vmlinux EXPORT_SYMBOL ++0x67eb757c scsi_device_lookup vmlinux EXPORT_SYMBOL ++0xe0fc24aa param_set_int vmlinux EXPORT_SYMBOL ++0x3ec32668 xdr_inline_pages vmlinux EXPORT_SYMBOL_GPL ++0x17d5b36f crypto_drop_spawn vmlinux EXPORT_SYMBOL_GPL ++0x834658ac cmxgcr_lock vmlinux EXPORT_SYMBOL ++0x9ce3f83f nvram_write_byte vmlinux EXPORT_SYMBOL ++0x13ec80f3 param_set_short vmlinux EXPORT_SYMBOL ++0xf4e2a909 nf_nat_tftp_hook net/netfilter/nf_conntrack_tftp EXPORT_SYMBOL_GPL ++0x1d39c751 nf_nat_snmp_hook net/netfilter/nf_conntrack_snmp EXPORT_SYMBOL_GPL ++0xeb810de9 skb_pad vmlinux EXPORT_SYMBOL ++0x77bc13a0 strim vmlinux EXPORT_SYMBOL ++0xc4191169 shash_register_instance vmlinux EXPORT_SYMBOL_GPL ++0xbf84d6ad seq_write vmlinux EXPORT_SYMBOL ++0x3ed6ecb7 generic_file_llseek vmlinux EXPORT_SYMBOL ++0x95922601 rtc_update_irq_enable vmlinux EXPORT_SYMBOL_GPL ++0x999e8297 vfree vmlinux EXPORT_SYMBOL ++0x6906c2dc wait_on_page_bit vmlinux EXPORT_SYMBOL ++0xcbdab685 mutex_lock vmlinux EXPORT_SYMBOL ++0x097d06aa scsi_get_host_dev vmlinux EXPORT_SYMBOL ++0x240bd3e5 swiotlb_sync_sg_for_device vmlinux EXPORT_SYMBOL ++0x6c03da58 elv_rq_merge_ok vmlinux EXPORT_SYMBOL ++0xee3496c3 dma_pool_alloc vmlinux EXPORT_SYMBOL ++0xee766000 tcp_v4_do_rcv vmlinux EXPORT_SYMBOL ++0x0ec55ed1 get_device vmlinux EXPORT_SYMBOL_GPL ++0xbee1171d blk_dump_rq_flags vmlinux EXPORT_SYMBOL ++0x3cfa0f3d sysfs_create_group vmlinux EXPORT_SYMBOL_GPL ++0xf065f629 ioread16be vmlinux EXPORT_SYMBOL ++0x00c52ef5 g_make_token_header vmlinux EXPORT_SYMBOL_GPL ++0xcd2f69d1 xprt_release_rqst_cong vmlinux EXPORT_SYMBOL_GPL ++0x05e73ebe xfrm_unregister_mode vmlinux EXPORT_SYMBOL ++0xa84245d3 consume_skb vmlinux EXPORT_SYMBOL ++0xdd978be5 scsi_add_device vmlinux EXPORT_SYMBOL ++0x2d832e72 pci_match_id vmlinux EXPORT_SYMBOL ++0x01674bbb pci_dev_run_wake vmlinux EXPORT_SYMBOL_GPL ++0x64e716c4 rpc_alloc_iostats vmlinux EXPORT_SYMBOL_GPL ++0xa2a8b984 ethtool_op_get_tso vmlinux EXPORT_SYMBOL ++0xdfc02652 i2c_add_numbered_adapter vmlinux EXPORT_SYMBOL_GPL ++0x12fa94c6 usb_unanchor_urb vmlinux EXPORT_SYMBOL_GPL ++0x8071ec90 bio_kmalloc vmlinux EXPORT_SYMBOL ++0xa62884a3 poll_schedule_timeout vmlinux EXPORT_SYMBOL ++0x30ddb019 tcp_prot vmlinux EXPORT_SYMBOL ++0xbc912b04 root_device_unregister vmlinux EXPORT_SYMBOL_GPL ++0x5ff1e29f textsearch_prepare vmlinux EXPORT_SYMBOL ++0x50ab4c6d files_lglock_global_lock vmlinux EXPORT_SYMBOL ++0x7914c68c proc_dointvec_ms_jiffies vmlinux EXPORT_SYMBOL ++0x63f22305 inet_frag_kill vmlinux EXPORT_SYMBOL ++0x4f90f253 simple_setattr vmlinux EXPORT_SYMBOL ++0xcfea7e86 simple_getattr vmlinux EXPORT_SYMBOL ++0x23f2243d mempool_free vmlinux EXPORT_SYMBOL ++0xc0b11f65 pci_iounmap vmlinux EXPORT_SYMBOL ++0x9edf6333 llc_sap_open vmlinux EXPORT_SYMBOL ++0x88164429 cred_to_ucred vmlinux EXPORT_SYMBOL_GPL ++0x3d418f49 sock_tx_timestamp vmlinux EXPORT_SYMBOL ++0x8d4097dd usb_stor_Bulk_reset vmlinux EXPORT_SYMBOL_GPL ++0x9eb18e34 attribute_container_unregister vmlinux EXPORT_SYMBOL_GPL ++0x277034d4 driver_for_each_device vmlinux EXPORT_SYMBOL_GPL ++0x5c443f95 bdget_disk vmlinux EXPORT_SYMBOL ++0x717ed11e journal_init_inode vmlinux EXPORT_SYMBOL ++0xb41c85dd tcp_v4_get_peer vmlinux EXPORT_SYMBOL ++0xa99ef722 tcp_rcv_state_process vmlinux EXPORT_SYMBOL ++0xf83a1c06 ethtool_op_get_tx_csum vmlinux EXPORT_SYMBOL ++0xf368fcf8 skb_to_sgvec vmlinux EXPORT_SYMBOL_GPL ++0x42224298 sscanf vmlinux EXPORT_SYMBOL ++0x77e35ccc nlmsvc_unlock_all_by_ip vmlinux EXPORT_SYMBOL_GPL ++0x1a24588e nlmsvc_unlock_all_by_sb vmlinux EXPORT_SYMBOL_GPL ++0xdaf873fe __breadahead vmlinux EXPORT_SYMBOL ++0x9531cde3 rpc_bind_new_program vmlinux EXPORT_SYMBOL_GPL ++0x291d6625 pfifo_fast_ops vmlinux EXPORT_SYMBOL ++0x3301ac32 platform_device_register_full vmlinux EXPORT_SYMBOL_GPL ++0x0111955c journal_stop vmlinux EXPORT_SYMBOL ++0x44eb192e wait_for_completion vmlinux EXPORT_SYMBOL ++0x72c09e5c csum_partial_copy_to_xdr vmlinux EXPORT_SYMBOL_GPL ++0xcdbc9355 dev_get_by_name_rcu vmlinux EXPORT_SYMBOL ++0x7f72cd44 i2c_smbus_write_byte_data vmlinux EXPORT_SYMBOL ++0x96786360 usb_unlink_urb vmlinux EXPORT_SYMBOL_GPL ++0xea968c96 ___ratelimit vmlinux EXPORT_SYMBOL ++0x4806976c __nf_nat_mangle_tcp_packet net/ipv4/netfilter/nf_nat EXPORT_SYMBOL ++0x9e672ff6 scsi_kmap_atomic_sg vmlinux EXPORT_SYMBOL ++0xe4c58b28 platform_device_add_data vmlinux EXPORT_SYMBOL_GPL ++0x3a26ed11 sched_clock vmlinux EXPORT_SYMBOL_GPL ++0xefde1bbe flush_dcache_range vmlinux EXPORT_SYMBOL ++0xe1286b24 put_rpccred vmlinux EXPORT_SYMBOL_GPL ++0x4bf99462 rpcauth_init_cred vmlinux EXPORT_SYMBOL_GPL ++0x3cce336f xfrm_audit_state_replay_overflow vmlinux EXPORT_SYMBOL_GPL ++0x1fcece42 inet_twdr_twcal_tick vmlinux EXPORT_SYMBOL_GPL ++0x533977ad sock_create_lite vmlinux EXPORT_SYMBOL ++0x97dba41d mmc_hw_reset_check vmlinux EXPORT_SYMBOL ++0xf1be02c3 swiotlb_dma_mapping_error vmlinux EXPORT_SYMBOL ++0xb1c3fd5a d_obtain_alias vmlinux EXPORT_SYMBOL ++0x493e60ab file_sb_list_del vmlinux EXPORT_SYMBOL_GPL ++0x656e8057 nf_conntrack_helper_try_module_get net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xe160bbbe ip4_datagram_connect vmlinux EXPORT_SYMBOL ++0x6ba0b373 tcp_timewait_state_process vmlinux EXPORT_SYMBOL ++0x75bdea12 iommu_area_alloc vmlinux EXPORT_SYMBOL ++0xc46d877e schedule_hrtimeout vmlinux EXPORT_SYMBOL_GPL ++0x587b892e qe_get_num_of_risc vmlinux EXPORT_SYMBOL ++0x9f8fb40b starget_for_each_device vmlinux EXPORT_SYMBOL ++0x585be6d1 subsys_interface_register vmlinux EXPORT_SYMBOL_GPL ++0x6fdbcab8 nobh_writepage vmlinux EXPORT_SYMBOL ++0xb34ab28b clear_page_dirty_for_io vmlinux EXPORT_SYMBOL ++0xe0573294 srcu_init_notifier_head vmlinux EXPORT_SYMBOL_GPL ++0xcfb9006e jiffies_to_timeval vmlinux EXPORT_SYMBOL ++0x60421247 tcp_reno_min_cwnd vmlinux EXPORT_SYMBOL_GPL ++0x21b65a0b tty_schedule_flip vmlinux EXPORT_SYMBOL ++0x62d55839 tty_get_baud_rate vmlinux EXPORT_SYMBOL ++0x96877ac4 locks_start_grace vmlinux EXPORT_SYMBOL_GPL ++0x2d2aefd5 vfs_follow_link vmlinux EXPORT_SYMBOL ++0xc9d29672 svc_create_xprt vmlinux EXPORT_SYMBOL_GPL ++0xc74a0c83 sysdev_class_unregister vmlinux EXPORT_SYMBOL_GPL ++0xcf038dc7 tty_shutdown vmlinux EXPORT_SYMBOL ++0xfc885e13 tty_devnum vmlinux EXPORT_SYMBOL ++0xbed06f95 sysfs_rename_link vmlinux EXPORT_SYMBOL_GPL ++0x4f391d0e nla_parse vmlinux EXPORT_SYMBOL ++0xc1868f6a write_dirty_buffer vmlinux EXPORT_SYMBOL ++0xe633499a noop_llseek vmlinux EXPORT_SYMBOL ++0xc65d3eed ring_buffer_entries_cpu vmlinux EXPORT_SYMBOL_GPL ++0xf1e28f9a llc_sap_find vmlinux EXPORT_SYMBOL ++0x30fbaf1e input_free_device vmlinux EXPORT_SYMBOL ++0x69f56098 xprt_set_retrans_timeout_rtt vmlinux EXPORT_SYMBOL_GPL ++0x3e9110fa __hw_addr_unsync vmlinux EXPORT_SYMBOL ++0x7d11c268 jiffies vmlinux EXPORT_SYMBOL ++0x3e7bb605 dev_queue_xmit vmlinux EXPORT_SYMBOL ++0x5fa8e9f9 of_device_alloc vmlinux EXPORT_SYMBOL ++0xac57677c do_map_probe vmlinux EXPORT_SYMBOL ++0x5a324753 proc_mkdir vmlinux EXPORT_SYMBOL ++0x13d0adf7 __kfifo_out vmlinux EXPORT_SYMBOL ++0x8379c763 dmam_free_noncoherent vmlinux EXPORT_SYMBOL ++0x0964a2f2 blk_rq_map_sg vmlinux EXPORT_SYMBOL ++0x9b68e095 proc_dointvec_jiffies vmlinux EXPORT_SYMBOL ++0xb53a4336 kmap_pte vmlinux EXPORT_SYMBOL ++0x9105b5ec __napi_schedule vmlinux EXPORT_SYMBOL ++0x48c6fdb8 sk_stream_wait_memory vmlinux EXPORT_SYMBOL ++0xaf78c424 usb_set_interface vmlinux EXPORT_SYMBOL_GPL ++0x8384a2c5 tty_unlock vmlinux EXPORT_SYMBOL ++0x0d3cb182 kstrtos16_from_user vmlinux EXPORT_SYMBOL ++0x9f2bdaac __bitmap_or vmlinux EXPORT_SYMBOL ++0x4b29940c get_dcookie vmlinux EXPORT_SYMBOL_GPL ++0x87480e3f netlink_broadcast_filtered vmlinux EXPORT_SYMBOL ++0x5dd67618 register_netevent_notifier vmlinux EXPORT_SYMBOL_GPL ++0xc7ec6c27 strspn vmlinux EXPORT_SYMBOL ++0x0727c4f3 iowrite8 vmlinux EXPORT_SYMBOL ++0x97255bdf strlen vmlinux EXPORT_SYMBOL ++0x3f44c83f scsi_allocate_command vmlinux EXPORT_SYMBOL ++0xedbaee5e nla_strcmp vmlinux EXPORT_SYMBOL ++0x55786827 crypto_ahash_type vmlinux EXPORT_SYMBOL_GPL ++0x26bb950b __kfifo_from_user_r vmlinux EXPORT_SYMBOL ++0xadd1e971 alignment_exception vmlinux EXPORT_SYMBOL ++0xf6cb376c skb_trim vmlinux EXPORT_SYMBOL ++0x403f9529 gpio_request_one vmlinux EXPORT_SYMBOL_GPL ++0xce3e3387 svc_proc_register vmlinux EXPORT_SYMBOL_GPL ++0x6f35aea7 xfrm_policy_delete vmlinux EXPORT_SYMBOL ++0x40cb7613 inet_frags_init vmlinux EXPORT_SYMBOL ++0x60d5f317 rtc_irq_register vmlinux EXPORT_SYMBOL_GPL ++0x4e3567f7 match_int vmlinux EXPORT_SYMBOL ++0x054434d6 radix_tree_tag_set vmlinux EXPORT_SYMBOL ++0x7c763d45 blk_queue_lld_busy vmlinux EXPORT_SYMBOL_GPL ++0xcfd8a363 shash_free_instance vmlinux EXPORT_SYMBOL_GPL ++0xb663c828 debugfs_create_x64 vmlinux EXPORT_SYMBOL_GPL ++0x7e003b33 bdi_setup_and_register vmlinux EXPORT_SYMBOL ++0x510e2136 rpcauth_generic_bind_cred vmlinux EXPORT_SYMBOL_GPL ++0x5da31da0 skb_cow_data vmlinux EXPORT_SYMBOL_GPL ++0xdc6b4513 pci_fixup_cardbus vmlinux EXPORT_SYMBOL ++0x91acac9a i2c_get_adapter vmlinux EXPORT_SYMBOL ++0x868acba5 get_options vmlinux EXPORT_SYMBOL ++0xe2d57cb8 setup_irq vmlinux EXPORT_SYMBOL_GPL ++0x7e64ffb7 xdr_partial_copy_from_skb vmlinux EXPORT_SYMBOL_GPL ++0xac01fe4e input_unregister_handler vmlinux EXPORT_SYMBOL ++0x467b133c bh_uptodate_or_lock vmlinux EXPORT_SYMBOL ++0x2ec524ad __kfifo_in_r vmlinux EXPORT_SYMBOL ++0x51dce73b xfrm_state_walk_init vmlinux EXPORT_SYMBOL ++0xabeb086a rtc_read_alarm vmlinux EXPORT_SYMBOL_GPL ++0x8841dda6 pci_remove_behind_bridge vmlinux EXPORT_SYMBOL ++0x3c9d1211 string_get_size vmlinux EXPORT_SYMBOL ++0x14a5ead6 fat_fill_super vmlinux EXPORT_SYMBOL_GPL ++0x7b03848a verify_mem_not_deleted vmlinux EXPORT_SYMBOL ++0xee1a5125 register_exec_domain vmlinux EXPORT_SYMBOL ++0x4227283f fl6_sock_lookup vmlinux EXPORT_SYMBOL_GPL ++0x4c40ef7a pci_bus_write_config_word vmlinux EXPORT_SYMBOL ++0x9330cb9f sg_alloc_table vmlinux EXPORT_SYMBOL ++0x9c8d5b93 handle_simple_irq vmlinux EXPORT_SYMBOL_GPL ++0xda1be8e1 async_synchronize_cookie_domain vmlinux EXPORT_SYMBOL_GPL ++0xabd30091 call_usermodehelper_exec vmlinux EXPORT_SYMBOL ++0xa39b4cf2 udelay vmlinux EXPORT_SYMBOL ++0xe7a664c4 nf_hooks vmlinux EXPORT_SYMBOL ++0x339f4657 pci_release_region vmlinux EXPORT_SYMBOL ++0xff1e9dd8 seq_list_start vmlinux EXPORT_SYMBOL ++0x3f5b1415 nf_ct_port_nlattr_to_tuple net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xaeea3073 xfrm_aead_get_byname vmlinux EXPORT_SYMBOL_GPL ++0x02889771 km_state_notify vmlinux EXPORT_SYMBOL ++0xac26b820 _raw_write_lock vmlinux EXPORT_SYMBOL ++0x59b3378a completion_done vmlinux EXPORT_SYMBOL ++0x357c90d2 qdisc_put_stab vmlinux EXPORT_SYMBOL ++0x96a6cb6a seq_printf vmlinux EXPORT_SYMBOL ++0x8669d18f call_usermodehelper_setfns vmlinux EXPORT_SYMBOL ++0x4b98827c rh_init vmlinux EXPORT_SYMBOL_GPL ++0xa35b2101 mmc_free_host vmlinux EXPORT_SYMBOL ++0xe0b0dd36 pci_dev_driver vmlinux EXPORT_SYMBOL ++0x0b742fd7 simple_strtol vmlinux EXPORT_SYMBOL ++0x4da7c931 rwsem_downgrade_wake vmlinux EXPORT_SYMBOL ++0xfd9e2a19 ilookup5_nowait vmlinux EXPORT_SYMBOL ++0xac6855b0 gen_kill_estimator vmlinux EXPORT_SYMBOL ++0xdacc5bd6 pci_set_power_state vmlinux EXPORT_SYMBOL ++0x0a0db355 blk_queue_alignment_offset vmlinux EXPORT_SYMBOL ++0x5f4c2d4c unlock_super vmlinux EXPORT_SYMBOL ++0xdb3aca5d qe_pin_request vmlinux EXPORT_SYMBOL ++0x796fc5ce scsi_get_sense_info_fld vmlinux EXPORT_SYMBOL ++0x16db989b pci_bus_size_bridges vmlinux EXPORT_SYMBOL ++0x7e17c66d __bio_clone vmlinux EXPORT_SYMBOL ++0x4d025d04 vfs_stat vmlinux EXPORT_SYMBOL ++0xa0fbac79 wake_up_bit vmlinux EXPORT_SYMBOL ++0xe1e5b5a7 flush_fp_to_thread vmlinux EXPORT_SYMBOL_GPL ++0x3c93c386 nf_conntrack_flush_report net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x48a488a0 sysctl_tcp_cookie_size vmlinux EXPORT_SYMBOL_GPL ++0xe3a73fdb sysdev_driver_register vmlinux EXPORT_SYMBOL_GPL ++0x48034724 zlib_deflateReset vmlinux EXPORT_SYMBOL ++0x013b835b cap_netlink_recv vmlinux EXPORT_SYMBOL ++0xcdca3691 nr_irqs vmlinux EXPORT_SYMBOL_GPL ++0x8ec04552 _raw_spin_trylock_bh vmlinux EXPORT_SYMBOL ++0x56c8799d scsi_kunmap_atomic_sg vmlinux EXPORT_SYMBOL ++0x1b54f3f0 scsi_block_when_processing_errors vmlinux EXPORT_SYMBOL ++0x2d6604af wait_for_key_construction vmlinux EXPORT_SYMBOL ++0xa85da1dd f_setown vmlinux EXPORT_SYMBOL ++0x05e807a9 xdr_encode_string vmlinux EXPORT_SYMBOL_GPL ++0x3a434310 ip6_dst_hoplimit vmlinux EXPORT_SYMBOL ++0x03e7b88a arp_invalidate vmlinux EXPORT_SYMBOL ++0x81bf1cbf mmc_can_sanitize vmlinux EXPORT_SYMBOL ++0xfb1ebb24 usb_clear_halt vmlinux EXPORT_SYMBOL_GPL ++0xb640c303 swiotlb_map_sg_attrs vmlinux EXPORT_SYMBOL ++0x6d27ef64 __bitmap_empty vmlinux EXPORT_SYMBOL ++0x7c5f611a elv_unregister vmlinux EXPORT_SYMBOL_GPL ++0xf85746f7 submit_bh vmlinux EXPORT_SYMBOL ++0x7babd7ea mnt_clone_write vmlinux EXPORT_SYMBOL_GPL ++0x4e94f614 page_mkclean vmlinux EXPORT_SYMBOL_GPL ++0x405c1144 get_seconds vmlinux EXPORT_SYMBOL ++0x0d706d2e rh_set_owner vmlinux EXPORT_SYMBOL_GPL ++0xcf56c41f unregister_8022_client vmlinux EXPORT_SYMBOL ++0x2ddee4bb usb_anchor_empty vmlinux EXPORT_SYMBOL_GPL ++0xf0f1246c kvasprintf vmlinux EXPORT_SYMBOL ++0xa6dcc773 rb_insert_color vmlinux EXPORT_SYMBOL ++0x09c27acb svcauth_unix_set_client vmlinux EXPORT_SYMBOL_GPL ++0x9cd435ec __xfrm_init_state vmlinux EXPORT_SYMBOL ++0x1b17f158 hid_dump_field vmlinux EXPORT_SYMBOL_GPL ++0xdb80a388 __module_text_address vmlinux EXPORT_SYMBOL_GPL ++0x66d87d38 symbol_put_addr vmlinux EXPORT_SYMBOL_GPL ++0x2a639aaf hrtimer_start_range_ns vmlinux EXPORT_SYMBOL_GPL ++0x7c62d042 cpu_possible_mask vmlinux EXPORT_SYMBOL ++0x65319f3d llc_set_station_handler vmlinux EXPORT_SYMBOL ++0x12500d33 i2c_smbus_read_word_data vmlinux EXPORT_SYMBOL ++0xc2ac0cfe tty_buffer_request_room vmlinux EXPORT_SYMBOL_GPL ++0x00b37551 d_alloc vmlinux EXPORT_SYMBOL ++0xf7b796cc unuse_mm vmlinux EXPORT_SYMBOL_GPL ++0x0b73663b __alloc_pages_nodemask vmlinux EXPORT_SYMBOL ++0x2b0a269a elv_abort_queue vmlinux EXPORT_SYMBOL ++0xe189aa6f journal_extend vmlinux EXPORT_SYMBOL ++0x918ad429 ring_buffer_lock_reserve vmlinux EXPORT_SYMBOL_GPL ++0xe2755929 irq_set_affinity_hint vmlinux EXPORT_SYMBOL_GPL ++0x3abc78ce dev_err vmlinux EXPORT_SYMBOL ++0xfcfa8b04 blk_execute_rq_nowait vmlinux EXPORT_SYMBOL_GPL ++0x6d02eb17 udp_proc_register vmlinux EXPORT_SYMBOL ++0x7bf1cc3b kernel_sendpage vmlinux EXPORT_SYMBOL ++0x9d7e0cfa pci_choose_state vmlinux EXPORT_SYMBOL ++0x0a6c9682 delete_from_page_cache vmlinux EXPORT_SYMBOL ++0x3b615a21 wait_for_completion_killable vmlinux EXPORT_SYMBOL ++0x50c89f23 __alloc_percpu vmlinux EXPORT_SYMBOL_GPL ++0xe7cd06a1 scsi_cmd_get_serial vmlinux EXPORT_SYMBOL ++0xbd8ed748 svc_close_xprt vmlinux EXPORT_SYMBOL_GPL ++0x2fb84137 neigh_parms_release vmlinux EXPORT_SYMBOL ++0xbfd18198 mmc_card_awake vmlinux EXPORT_SYMBOL ++0xba386aa9 usb_hcd_link_urb_to_ep vmlinux EXPORT_SYMBOL_GPL ++0x50c6ae87 device_release_driver vmlinux EXPORT_SYMBOL_GPL ++0xa01f4485 swiotlb_alloc_coherent vmlinux EXPORT_SYMBOL ++0x572e85d4 blk_lookup_devt vmlinux EXPORT_SYMBOL ++0xe415316a crypto_grab_skcipher vmlinux EXPORT_SYMBOL_GPL ++0xe953b21f get_next_ino vmlinux EXPORT_SYMBOL ++0x546c5565 ppc_tb_freq vmlinux EXPORT_SYMBOL_GPL ++0x0bf06d6d usb_serial_handle_dcd_change vmlinux EXPORT_SYMBOL_GPL ++0xcd1bbf43 usb_stor_bulk_srb vmlinux EXPORT_SYMBOL_GPL ++0x326ee682 usb_alloc_streams vmlinux EXPORT_SYMBOL_GPL ++0x984ca836 scsi_register_interface vmlinux EXPORT_SYMBOL ++0xeb72182a vfs_setlease vmlinux EXPORT_SYMBOL_GPL ++0x40d04664 console_trylock vmlinux EXPORT_SYMBOL ++0x2ee496e6 i2c_smbus_read_block_data vmlinux EXPORT_SYMBOL ++0x71d6687e usb_put_intf vmlinux EXPORT_SYMBOL_GPL ++0x5040a36f blk_queue_dma_pad vmlinux EXPORT_SYMBOL ++0x0521b2ee set_current_groups vmlinux EXPORT_SYMBOL ++0xb1c6e787 wait_for_completion_timeout vmlinux EXPORT_SYMBOL ++0x107aa06a dcb_ieee_getapp_mask vmlinux EXPORT_SYMBOL ++0x60ac991d xfrm6_input_addr vmlinux EXPORT_SYMBOL ++0x3aa32d81 usb_stor_probe2 vmlinux EXPORT_SYMBOL_GPL ++0x12cd39ae usb_stor_probe1 vmlinux EXPORT_SYMBOL_GPL ++0x81db6ebb xz_dec_reset vmlinux EXPORT_SYMBOL ++0x661601de sprint_symbol vmlinux EXPORT_SYMBOL_GPL ++0x6e8698ee scm_fp_dup vmlinux EXPORT_SYMBOL ++0x9c2b3860 mmc_card_can_sleep vmlinux EXPORT_SYMBOL ++0x6a7e90da devres_remove vmlinux EXPORT_SYMBOL_GPL ++0x30e28a09 tty_vhangup vmlinux EXPORT_SYMBOL ++0xd3434c3f kref_sub vmlinux EXPORT_SYMBOL ++0x2ce98559 kcrypto_wq vmlinux EXPORT_SYMBOL_GPL ++0x8f860b23 shrink_dcache_parent vmlinux EXPORT_SYMBOL ++0x75c8a11c inet_twdr_twkill_work vmlinux EXPORT_SYMBOL_GPL ++0x609f1c7e synchronize_net vmlinux EXPORT_SYMBOL ++0xa638cf54 bus_for_each_dev vmlinux EXPORT_SYMBOL_GPL ++0x8dcf576a bus_for_each_drv vmlinux EXPORT_SYMBOL_GPL ++0x42825ce2 rcu_scheduler_active vmlinux EXPORT_SYMBOL_GPL ++0xe523ad75 synchronize_irq vmlinux EXPORT_SYMBOL ++0xfa393103 pneigh_lookup vmlinux EXPORT_SYMBOL ++0x0ba2668c kern_path_create vmlinux EXPORT_SYMBOL ++0xc47cdf9c _raw_write_lock_bh vmlinux EXPORT_SYMBOL ++0x72dc286d xdr_terminate_string vmlinux EXPORT_SYMBOL_GPL ++0x28531ce3 blk_queue_find_tag vmlinux EXPORT_SYMBOL ++0x4bc62a81 audit_enabled vmlinux EXPORT_SYMBOL_GPL ++0xd8a2ab95 in_egroup_p vmlinux EXPORT_SYMBOL ++0x919d1163 tty_termios_baud_rate vmlinux EXPORT_SYMBOL ++0x184e6c85 radix_tree_gang_lookup_slot vmlinux EXPORT_SYMBOL ++0xcdb01877 ktime_add_ns vmlinux EXPORT_SYMBOL_GPL ++0x8b96c05a nf_conntrack_broadcast_help net/netfilter/nf_conntrack_broadcast EXPORT_SYMBOL_GPL ++0xcb6e6aa8 skb_append_datato_frags vmlinux EXPORT_SYMBOL ++0x9e0c711d vzalloc_node vmlinux EXPORT_SYMBOL ++0x7f24de73 jiffies_to_usecs vmlinux EXPORT_SYMBOL ++0x37befc70 jiffies_to_msecs vmlinux EXPORT_SYMBOL ++0x436c2179 iowrite32 vmlinux EXPORT_SYMBOL ++0x8c183cbe iowrite16 vmlinux EXPORT_SYMBOL ++0x17774e80 tcp_child_process vmlinux EXPORT_SYMBOL ++0xb6896671 crc_t10dif vmlinux EXPORT_SYMBOL ++0x9ab8808c param_get_charp vmlinux EXPORT_SYMBOL ++0x8025065c mdiobus_write vmlinux EXPORT_SYMBOL ++0x1f852c0d prepare_binprm vmlinux EXPORT_SYMBOL ++0x4db9ec4c tcp_v4_destroy_sock vmlinux EXPORT_SYMBOL ++0x6d6cbadc rb_last vmlinux EXPORT_SYMBOL ++0x7ab3ca18 eventfd_ctx_read vmlinux EXPORT_SYMBOL_GPL ++0x86eb50bf mount_bdev vmlinux EXPORT_SYMBOL ++0xe6fbe430 can_do_mlock vmlinux EXPORT_SYMBOL ++0x60a13e90 rcu_barrier vmlinux EXPORT_SYMBOL_GPL ++0xdf60cc27 __print_symbol vmlinux EXPORT_SYMBOL ++0x96c287fe ndisc_mc_map vmlinux EXPORT_SYMBOL ++0x55da0153 sysdev_register vmlinux EXPORT_SYMBOL_GPL ++0x91715312 sprintf vmlinux EXPORT_SYMBOL ++0x0d05dd4f simple_unlink vmlinux EXPORT_SYMBOL ++0xaa563302 simple_attr_write vmlinux EXPORT_SYMBOL_GPL ++0x099b48fd generic_listxattr vmlinux EXPORT_SYMBOL ++0xf6ebc03b net_ratelimit vmlinux EXPORT_SYMBOL ++0xf9c8fc44 dev_addr_init vmlinux EXPORT_SYMBOL ++0x09ae2253 mmc_host_disable vmlinux EXPORT_SYMBOL ++0x6559ae6c pci_set_ltr vmlinux EXPORT_SYMBOL ++0x1ebf6c2a pci_power_names vmlinux EXPORT_SYMBOL_GPL ++0x57e7529b shash_ahash_update vmlinux EXPORT_SYMBOL_GPL ++0x05c6b149 invalidate_inode_buffers vmlinux EXPORT_SYMBOL ++0x48bea168 scsi_register vmlinux EXPORT_SYMBOL ++0x764c2f05 crypto_shash_update vmlinux EXPORT_SYMBOL_GPL ++0x2eef0ac9 journal_dirty_data vmlinux EXPORT_SYMBOL ++0xb5e31b10 find_vma vmlinux EXPORT_SYMBOL ++0x0d0f4d51 nf_ct_extend_unregister net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x5c936853 svc_print_addr vmlinux EXPORT_SYMBOL_GPL ++0x12505fc7 kernel_connect vmlinux EXPORT_SYMBOL ++0xb8546237 inet_stream_connect vmlinux EXPORT_SYMBOL ++0xa05c03df mempool_kmalloc vmlinux EXPORT_SYMBOL ++0x8dc76dc4 qdisc_warn_nonwc vmlinux EXPORT_SYMBOL ++0x9a7a6123 pci_release_regions vmlinux EXPORT_SYMBOL ++0xc9eec5c2 splice_from_pipe_begin vmlinux EXPORT_SYMBOL ++0xfd6293c2 boot_tvec_bases vmlinux EXPORT_SYMBOL ++0x126cabd2 netdev_class_remove_file vmlinux EXPORT_SYMBOL ++0xbccdc2f6 flex_array_put vmlinux EXPORT_SYMBOL ++0x8164e310 blk_queue_physical_block_size vmlinux EXPORT_SYMBOL ++0x9b724801 nlmclnt_done vmlinux EXPORT_SYMBOL_GPL ++0xf9e2e40e dio_end_io vmlinux EXPORT_SYMBOL_GPL ++0x53735d40 relay_subbufs_consumed vmlinux EXPORT_SYMBOL_GPL ++0xc0bf6ead timecounter_cyc2time vmlinux EXPORT_SYMBOL_GPL ++0x37f6fee5 fsl_lbc_find vmlinux EXPORT_SYMBOL ++0x4f881b16 rtc_tm_to_ktime vmlinux EXPORT_SYMBOL_GPL ++0x325ffbe2 journal_ack_err vmlinux EXPORT_SYMBOL ++0x307c2fd0 generic_check_addressable vmlinux EXPORT_SYMBOL ++0xee2d8f00 perf_event_read_value vmlinux EXPORT_SYMBOL_GPL ++0xc065a455 cpu_core_index_of_thread vmlinux EXPORT_SYMBOL_GPL ++0x33dc9781 inet6_csk_addr2sockaddr vmlinux EXPORT_SYMBOL_GPL ++0x4c50029a netdev_refcnt_read vmlinux EXPORT_SYMBOL ++0xd1b2bc7a input_mt_init_slots vmlinux EXPORT_SYMBOL ++0xa16d230d devres_close_group vmlinux EXPORT_SYMBOL_GPL ++0xa92b183a __blk_end_request vmlinux EXPORT_SYMBOL ++0x7f7bc710 klist_next vmlinux EXPORT_SYMBOL_GPL ++0x0140c06a tcp_rcv_established vmlinux EXPORT_SYMBOL ++0x80c1ac2b ip_queue_rcv_skb vmlinux EXPORT_SYMBOL ++0x4865f9b3 inet_getpeer vmlinux EXPORT_SYMBOL_GPL ++0x3d0688cd xt_unregister_targets vmlinux EXPORT_SYMBOL ++0x4e592d6c spi_alloc_master vmlinux EXPORT_SYMBOL_GPL ++0xce53932d scsi_prep_fn vmlinux EXPORT_SYMBOL ++0xd7e56a4e simple_strtoll vmlinux EXPORT_SYMBOL ++0x20000329 simple_strtoul vmlinux EXPORT_SYMBOL ++0xa3c8685d nfs_initiate_commit vmlinux EXPORT_SYMBOL_GPL ++0xbedc5a25 fsnotify_destroy_mark vmlinux EXPORT_SYMBOL_GPL ++0x65400222 __irq_offset_value vmlinux EXPORT_SYMBOL ++0x540fbf55 nf_register_afinfo vmlinux EXPORT_SYMBOL_GPL ++0x783c65c7 net_ns_type_operations vmlinux EXPORT_SYMBOL_GPL ++0x0d733a10 proc_symlink vmlinux EXPORT_SYMBOL ++0x983c7494 rh_detach_region vmlinux EXPORT_SYMBOL_GPL ++0x6428da4f rh_attach_region vmlinux EXPORT_SYMBOL_GPL ++0xe0f45eeb __rtnl_link_unregister vmlinux EXPORT_SYMBOL_GPL ++0x5497669a blk_queue_dma_alignment vmlinux EXPORT_SYMBOL ++0xc51e0e79 remap_vmalloc_range vmlinux EXPORT_SYMBOL ++0xda869994 noop_backing_dev_info vmlinux EXPORT_SYMBOL_GPL ++0xd985dc99 mempool_free_pages vmlinux EXPORT_SYMBOL ++0xfcec0987 enable_irq vmlinux EXPORT_SYMBOL ++0x1e7bbcb3 kernel_restart vmlinux EXPORT_SYMBOL_GPL ++0x0cc3cab1 dev_alloc_skb vmlinux EXPORT_SYMBOL ++0xdd27fa87 memchr vmlinux EXPORT_SYMBOL ++0xc18ac88d nf_ct_expect_hsize net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x7a00ec15 inet6_release vmlinux EXPORT_SYMBOL ++0xbeff3d59 of_get_parent vmlinux EXPORT_SYMBOL ++0x15a94e65 pci_destroy_slot vmlinux EXPORT_SYMBOL_GPL ++0x2cfc679e vfs_kern_mount vmlinux EXPORT_SYMBOL_GPL ++0xd5bd7dac ring_buffer_record_enable_cpu vmlinux EXPORT_SYMBOL_GPL ++0x1a3c4cdf local_flush_tlb_page vmlinux EXPORT_SYMBOL ++0x36bc9a29 gss_mech_list_pseudoflavors vmlinux EXPORT_SYMBOL_GPL ++0x977832e8 spi_bus_type vmlinux EXPORT_SYMBOL_GPL ++0x840efb10 anon_transport_class_unregister vmlinux EXPORT_SYMBOL_GPL ++0x315c65fd zlib_deflateInit2 vmlinux EXPORT_SYMBOL ++0x6bed2572 submit_bio vmlinux EXPORT_SYMBOL ++0x1aacd048 alloc_page_buffers vmlinux EXPORT_SYMBOL_GPL ++0xfbf9be5d register_oom_notifier vmlinux EXPORT_SYMBOL_GPL ++0xcfc68341 synchronize_rcu_bh vmlinux EXPORT_SYMBOL_GPL ++0x549525ef handle_nested_irq vmlinux EXPORT_SYMBOL_GPL ++0x25a81cc5 qe_get_firmware_info vmlinux EXPORT_SYMBOL ++0xd8525ea7 fl6_update_dst vmlinux EXPORT_SYMBOL_GPL ++0xa4e81ac2 tcp_valid_rtt_meas vmlinux EXPORT_SYMBOL ++0xe0a7f614 neigh_lookup vmlinux EXPORT_SYMBOL ++0x0680ca81 mmc_remove_host vmlinux EXPORT_SYMBOL ++0x7bd25d47 usb_put_hcd vmlinux EXPORT_SYMBOL_GPL ++0x2ef63ad6 scsi_dev_info_list_del_keyed vmlinux EXPORT_SYMBOL ++0x091c824a machine_power_off vmlinux EXPORT_SYMBOL_GPL ++0x3996b31d tcp_mtup_init vmlinux EXPORT_SYMBOL ++0x0ea07ec7 kstrtou8_from_user vmlinux EXPORT_SYMBOL ++0x973d0f9e kstrtoul_from_user vmlinux EXPORT_SYMBOL ++0x45cfa828 cache_purge vmlinux EXPORT_SYMBOL_GPL ++0x222e7ce2 sysfs_streq vmlinux EXPORT_SYMBOL ++0x71dd6c34 alloc_buffer_head vmlinux EXPORT_SYMBOL ++0x49dcec10 xdr_write_pages vmlinux EXPORT_SYMBOL_GPL ++0xbb73bb5c swiotlb_tbl_map_single vmlinux EXPORT_SYMBOL_GPL ++0x1ac51c1e device_remove_file vmlinux EXPORT_SYMBOL_GPL ++0x60506751 unmap_kernel_range_noflush vmlinux EXPORT_SYMBOL_GPL ++0x289c3714 nf_ct_alloc_hashtable net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x49ffc48e ipv6_skip_exthdr vmlinux EXPORT_SYMBOL ++0x5b723c46 ip_options_compile vmlinux EXPORT_SYMBOL ++0x45a37cf4 aio_complete vmlinux EXPORT_SYMBOL ++0x44402b6f param_get_ulong vmlinux EXPORT_SYMBOL ++0x0b19ea8e kill_pid vmlinux EXPORT_SYMBOL ++0x69642f88 pcibios_bus_to_resource vmlinux EXPORT_SYMBOL ++0xea710ef9 rt6_lookup vmlinux EXPORT_SYMBOL ++0x12f99022 inet_frags_init_net vmlinux EXPORT_SYMBOL ++0x796b252b device_store_int vmlinux EXPORT_SYMBOL_GPL ++0x64999478 congestion_wait vmlinux EXPORT_SYMBOL ++0x59eae699 ring_buffer_read_prepare vmlinux EXPORT_SYMBOL_GPL ++0xe4a65c70 i2c_del_driver vmlinux EXPORT_SYMBOL ++0x419b695a blk_queue_dma_drain vmlinux EXPORT_SYMBOL_GPL ++0x9d8331c0 ring_buffer_read_page vmlinux EXPORT_SYMBOL_GPL ++0xae545f06 _raw_write_unlock_irqrestore vmlinux EXPORT_SYMBOL ++0xbad26090 __atomic_notifier_call_chain vmlinux EXPORT_SYMBOL_GPL ++0x057ce975 hex_dump_to_buffer vmlinux EXPORT_SYMBOL ++0x119db340 file_ra_state_init vmlinux EXPORT_SYMBOL_GPL ++0xcd212027 usb_alloc_coherent vmlinux EXPORT_SYMBOL_GPL ++0x74b35a2e crypto_larval_kill vmlinux EXPORT_SYMBOL_GPL ++0xfaa1f7a6 xfrm_register_mode vmlinux EXPORT_SYMBOL ++0xb0559860 inet_csk_get_port vmlinux EXPORT_SYMBOL_GPL ++0x20e9c644 mmc_flush_cache vmlinux EXPORT_SYMBOL ++0xd5f63191 i2c_clients_command vmlinux EXPORT_SYMBOL ++0xd77c0bc8 klist_remove vmlinux EXPORT_SYMBOL_GPL ++0xff121d12 ethtool_op_get_ufo vmlinux EXPORT_SYMBOL ++0x3755e17d dev_get_flags vmlinux EXPORT_SYMBOL ++0x5296e7f4 usb_get_status vmlinux EXPORT_SYMBOL_GPL ++0x790df6ca __wait_on_bit_lock vmlinux EXPORT_SYMBOL ++0x5a4eec67 svc_auth_register vmlinux EXPORT_SYMBOL_GPL ++0xe5122890 flow_cache_genid vmlinux EXPORT_SYMBOL ++0x2c919c63 gen_new_estimator vmlinux EXPORT_SYMBOL ++0x0c812da4 input_class vmlinux EXPORT_SYMBOL_GPL ++0x4e00ab3c pci_set_master vmlinux EXPORT_SYMBOL ++0xfcc8f571 crypto_alg_mod_lookup vmlinux EXPORT_SYMBOL_GPL ++0x31c5af62 freeze_super vmlinux EXPORT_SYMBOL ++0x00c0514b __devm_request_region vmlinux EXPORT_SYMBOL ++0xfb905a24 hid_connect vmlinux EXPORT_SYMBOL_GPL ++0x4b824206 mmc_set_data_timeout vmlinux EXPORT_SYMBOL ++0x1040ca42 usb_set_device_state vmlinux EXPORT_SYMBOL_GPL ++0x12c83422 scsi_eh_finish_cmd vmlinux EXPORT_SYMBOL ++0x87177c3d mmc_can_reset vmlinux EXPORT_SYMBOL ++0x5bc4f32c cpu_rmap_update vmlinux EXPORT_SYMBOL ++0xdd0a2ba2 strlcat vmlinux EXPORT_SYMBOL ++0xd627480b strncat vmlinux EXPORT_SYMBOL ++0xcfeb0be9 rb_augment_erase_begin vmlinux EXPORT_SYMBOL ++0xd6c357db blk_queue_max_discard_sectors vmlinux EXPORT_SYMBOL ++0xd2965f6f kthread_should_stop vmlinux EXPORT_SYMBOL ++0xd0ad960f nfnetlink_set_err net/netfilter/nfnetlink EXPORT_SYMBOL_GPL ++0x1c460693 netdev_notice vmlinux EXPORT_SYMBOL ++0x7f185424 blk_rq_map_kern vmlinux EXPORT_SYMBOL ++0x551de792 sync_mapping_buffers vmlinux EXPORT_SYMBOL ++0x4ac7a222 usb_serial_handle_break vmlinux EXPORT_SYMBOL_GPL ++0x204d23f2 __scsi_add_device vmlinux EXPORT_SYMBOL ++0xaaec89e2 fat_scan vmlinux EXPORT_SYMBOL_GPL ++0x4ca16694 inode_change_ok vmlinux EXPORT_SYMBOL ++0xf1a0626d datagram_poll vmlinux EXPORT_SYMBOL ++0x69d38ed9 __scsi_print_sense vmlinux EXPORT_SYMBOL ++0xf0c18cc1 blk_queue_end_tag vmlinux EXPORT_SYMBOL ++0x1e9edfb7 seq_hlist_start_head_rcu vmlinux EXPORT_SYMBOL ++0x87604ac8 dev_mc_flush vmlinux EXPORT_SYMBOL ++0xf0eb6c0e dev_uc_flush vmlinux EXPORT_SYMBOL ++0xd9fb3de3 usb_stor_Bulk_transport vmlinux EXPORT_SYMBOL_GPL ++0x0bc753c7 flush_old_exec vmlinux EXPORT_SYMBOL ++0x00c4dc87 timecounter_init vmlinux EXPORT_SYMBOL_GPL ++0x0c9b6089 nvram_get_size vmlinux EXPORT_SYMBOL ++0xad9e43be inet_addr_type vmlinux EXPORT_SYMBOL ++0xf22414e2 inet_recvmsg vmlinux EXPORT_SYMBOL ++0xd454b29f llc_sap_close vmlinux EXPORT_SYMBOL ++0x80132d25 mdiobus_unregister vmlinux EXPORT_SYMBOL ++0x65291cff timekeeping_inject_offset vmlinux EXPORT_SYMBOL ++0x7be4827c pci_dram_offset vmlinux EXPORT_SYMBOL ++0xb09c5030 phy_detach vmlinux EXPORT_SYMBOL ++0x01b08eb0 mii_link_ok vmlinux EXPORT_SYMBOL ++0xc741f047 nfs_commitdata_alloc vmlinux EXPORT_SYMBOL_GPL ++0x5892f832 release_pmc_hardware vmlinux EXPORT_SYMBOL_GPL ++0x583c4f4e nf_conntrack_l4proto_udp6 net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xb0a8c94f tcp_proc_register vmlinux EXPORT_SYMBOL ++0x2a939f0e stop_tty vmlinux EXPORT_SYMBOL ++0xb7a99781 __irq_regs vmlinux EXPORT_SYMBOL ++0x774406ff generic_write_sync vmlinux EXPORT_SYMBOL ++0xf5b52822 sdio_writel vmlinux EXPORT_SYMBOL_GPL ++0xa0088161 nfs_pageio_reset_write_mds vmlinux EXPORT_SYMBOL_GPL ++0x92a84998 xfrm_policy_destroy vmlinux EXPORT_SYMBOL ++0x0538c307 sdhci_pltfm_register vmlinux EXPORT_SYMBOL_GPL ++0x43ed8622 sdio_memcpy_toio vmlinux EXPORT_SYMBOL_GPL ++0xb0a6f554 neigh_ifdown vmlinux EXPORT_SYMBOL ++0x00d43c47 cfi_fixup vmlinux EXPORT_SYMBOL ++0x6c1ce5ce strcspn vmlinux EXPORT_SYMBOL ++0x6cc25857 thermal_zone_unbind_cooling_device vmlinux EXPORT_SYMBOL ++0xcea93771 do_kern_mount vmlinux EXPORT_SYMBOL_GPL ++0xa32cec39 nf_conntrack_l3proto_register net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xdfb4377e nf_conntrack_l4proto_register net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xd4b929a5 hid_parse_report vmlinux EXPORT_SYMBOL_GPL ++0xc9b13a79 usb_serial_resume vmlinux EXPORT_SYMBOL ++0xad85acb1 blkdev_aio_write vmlinux EXPORT_SYMBOL_GPL ++0xfc21ea7b seq_bitmap_list vmlinux EXPORT_SYMBOL ++0xaec655c7 alloc_pages_exact vmlinux EXPORT_SYMBOL ++0x283780f9 gss_svc_to_pseudoflavor vmlinux EXPORT_SYMBOL_GPL ++0xeb5f1beb svc_find_xprt vmlinux EXPORT_SYMBOL_GPL ++0xb27c96eb svc_process vmlinux EXPORT_SYMBOL_GPL ++0xf40325f9 rpc_force_rebind vmlinux EXPORT_SYMBOL_GPL ++0x031337c7 __nla_reserve vmlinux EXPORT_SYMBOL ++0x29537c9e alloc_chrdev_region vmlinux EXPORT_SYMBOL ++0xa794e5af inc_zone_page_state vmlinux EXPORT_SYMBOL ++0xbe2ae37c nf_ct_iterate_cleanup net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x159caf84 rpc_killall_tasks vmlinux EXPORT_SYMBOL_GPL ++0x7faee9ca arp_find vmlinux EXPORT_SYMBOL ++0xc9e3b1e4 skb_checksum vmlinux EXPORT_SYMBOL ++0x2ccabce7 deregister_mtd_blktrans vmlinux EXPORT_SYMBOL_GPL ++0x8d8718ca pci_pme_capable vmlinux EXPORT_SYMBOL ++0xbdf5c25c rb_next vmlinux EXPORT_SYMBOL ++0xca4c7f40 inode_permission vmlinux EXPORT_SYMBOL ++0xcc3e77da buffer_migrate_page vmlinux EXPORT_SYMBOL ++0x519b0da3 finish_wait vmlinux EXPORT_SYMBOL ++0x4a290d4d cur_cpu_spec vmlinux EXPORT_SYMBOL ++0x564f1dca klist_add_after vmlinux EXPORT_SYMBOL_GPL ++0xd329f4b2 svc_xprt_init vmlinux EXPORT_SYMBOL_GPL ++0x52d7b2fd llc_sap_list vmlinux EXPORT_SYMBOL ++0x91fe4a85 phy_start_aneg vmlinux EXPORT_SYMBOL ++0x8695c5de scsi_print_result vmlinux EXPORT_SYMBOL ++0x4cbbd171 __bitmap_weight vmlinux EXPORT_SYMBOL ++0x61b7b126 simple_strtoull vmlinux EXPORT_SYMBOL ++0x528c709d simple_read_from_buffer vmlinux EXPORT_SYMBOL ++0x349e53f1 clockevent_delta2ns vmlinux EXPORT_SYMBOL_GPL ++0x6eb85693 nf_defrag_ipv6_enable net/ipv6/netfilter/nf_defrag_ipv6 EXPORT_SYMBOL_GPL ++0x6b6c3d10 nf_defrag_ipv4_enable net/ipv4/netfilter/nf_defrag_ipv4 EXPORT_SYMBOL_GPL ++0xa681fe88 generate_random_uuid vmlinux EXPORT_SYMBOL ++0xad1bb027 nf_ct_free_hashtable net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xc181af4a get_net_ns_by_pid vmlinux EXPORT_SYMBOL_GPL ++0xa1c47d5e mmc_power_save_host vmlinux EXPORT_SYMBOL ++0x86a1aabc vfs_statfs vmlinux EXPORT_SYMBOL ++0x8a50868d iterate_mounts vmlinux EXPORT_SYMBOL_GPL ++0x45838122 udp_ioctl vmlinux EXPORT_SYMBOL ++0xa02f471b i2c_new_probed_device vmlinux EXPORT_SYMBOL_GPL ++0x2e258c1f cfi_cmdset_0003 vmlinux EXPORT_SYMBOL_GPL ++0xe5ccb818 cfi_cmdset_0001 vmlinux EXPORT_SYMBOL_GPL ++0x037508a0 cfi_cmdset_0200 vmlinux EXPORT_SYMBOL_GPL ++0xeacafb73 cfi_cmdset_0006 vmlinux EXPORT_SYMBOL_GPL ++0xa669953c cfi_cmdset_0002 vmlinux EXPORT_SYMBOL_GPL ++0x8c101558 cfi_cmdset_0701 vmlinux EXPORT_SYMBOL_GPL ++0xf32fddac cfi_cmdset_0020 vmlinux EXPORT_SYMBOL_GPL ++0x58d4f625 __pci_complete_power_transition vmlinux EXPORT_SYMBOL_GPL ++0x0223b9bf __nla_reserve_nohdr vmlinux EXPORT_SYMBOL ++0x11fac1b6 __get_page_tail vmlinux EXPORT_SYMBOL ++0x5f5fc264 rtnetlink_put_metrics vmlinux EXPORT_SYMBOL ++0xea10212a int_to_scsilun vmlinux EXPORT_SYMBOL ++0x96fae2c1 may_umount vmlinux EXPORT_SYMBOL ++0xf6f92407 pcix_get_max_mmrbc vmlinux EXPORT_SYMBOL ++0x0b508415 block_read_full_page vmlinux EXPORT_SYMBOL ++0xf7535902 console_drivers vmlinux EXPORT_SYMBOL_GPL ++0x8de519db mmc_hw_reset vmlinux EXPORT_SYMBOL ++0x015ffc4f __scsi_alloc_queue vmlinux EXPORT_SYMBOL ++0x277ba2d9 bus_sort_breadthfirst vmlinux EXPORT_SYMBOL_GPL ++0xe11c50a5 ipt_alloc_initial_table net/ipv4/netfilter/ip_tables EXPORT_SYMBOL_GPL ++0x86c14d2e tcp_v4_connect vmlinux EXPORT_SYMBOL ++0x2c2f763c tcp_sync_mss vmlinux EXPORT_SYMBOL ++0xd0c05159 emergency_restart vmlinux EXPORT_SYMBOL_GPL ++0x3ff62317 local_bh_disable vmlinux EXPORT_SYMBOL ++0x3c5a83ec tcp_death_row vmlinux EXPORT_SYMBOL_GPL ++0xe187693c kstrtouint_from_user vmlinux EXPORT_SYMBOL ++0x1f3e84a0 bio_get_nr_vecs vmlinux EXPORT_SYMBOL ++0xf92a5458 xfrm_policy_byid vmlinux EXPORT_SYMBOL ++0xc871c13b pci_prepare_to_sleep vmlinux EXPORT_SYMBOL ++0x0f6690cf ahash_register_instance vmlinux EXPORT_SYMBOL_GPL ++0x686145ef load_nls_default vmlinux EXPORT_SYMBOL ++0xf209fa23 nonseekable_open vmlinux EXPORT_SYMBOL ++0x3d9e1db6 kmem_cache_create vmlinux EXPORT_SYMBOL ++0x475100c2 inet_get_local_port_range vmlinux EXPORT_SYMBOL ++0xd5683a1b __seq_open_private vmlinux EXPORT_SYMBOL ++0x13bdfe24 seq_escape vmlinux EXPORT_SYMBOL ++0x3108ea46 xfrm_ealg_get_byname vmlinux EXPORT_SYMBOL_GPL ++0x48c5e0f4 of_mdiobus_register vmlinux EXPORT_SYMBOL ++0x22692356 d_alloc_root vmlinux EXPORT_SYMBOL ++0xa0243187 page_address vmlinux EXPORT_SYMBOL ++0x89c72573 xfrm_lookup vmlinux EXPORT_SYMBOL ++0xc4a5fb77 skb_store_bits vmlinux EXPORT_SYMBOL ++0x9565a5a2 page_cache_sync_readahead vmlinux EXPORT_SYMBOL_GPL ++0x79c480da rh_dump vmlinux EXPORT_SYMBOL_GPL ++0xfba770b8 pcibios_fixup_bus vmlinux EXPORT_SYMBOL ++0xa93da361 inet_unregister_protosw vmlinux EXPORT_SYMBOL ++0x7cef3f58 i2c_probe_func_quick_read vmlinux EXPORT_SYMBOL_GPL ++0x65c8d17e i2c_smbus_read_byte vmlinux EXPORT_SYMBOL ++0x294d91c5 platform_create_bundle vmlinux EXPORT_SYMBOL_GPL ++0x99dc6ab8 _dev_info vmlinux EXPORT_SYMBOL ++0x1e4a32eb mb_cache_entry_free vmlinux EXPORT_SYMBOL ++0xeeac816f svc_xprt_put vmlinux EXPORT_SYMBOL_GPL ++0x1345ef47 ethtool_op_get_flags vmlinux EXPORT_SYMBOL ++0xa31feac5 blkcipher_walk_phys vmlinux EXPORT_SYMBOL_GPL ++0x3dfc897c seq_hlist_start_head vmlinux EXPORT_SYMBOL ++0xc34ff0bb clocksource_change_rating vmlinux EXPORT_SYMBOL ++0x9272763d sdio_set_block_size vmlinux EXPORT_SYMBOL_GPL ++0x439751b0 usb_stor_post_reset vmlinux EXPORT_SYMBOL_GPL ++0x9924c496 __usb_get_extra_descriptor vmlinux EXPORT_SYMBOL_GPL ++0xb0b3b849 pci_bus_assign_resources vmlinux EXPORT_SYMBOL ++0x9159b9d6 profile_event_register vmlinux EXPORT_SYMBOL_GPL ++0x6ca4d6ee __nf_conntrack_helper_find net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xd251093f nfs_generic_pg_test vmlinux EXPORT_SYMBOL_GPL ++0x5460c8d8 fsnotify_get_cookie vmlinux EXPORT_SYMBOL_GPL ++0xbeeb9715 dcb_getapp vmlinux EXPORT_SYMBOL ++0xb9a9fe46 dcb_setapp vmlinux EXPORT_SYMBOL ++0xb84d7d46 register_netdevice vmlinux EXPORT_SYMBOL ++0x0c38172a usb_serial_generic_open vmlinux EXPORT_SYMBOL_GPL ++0xfc532eb4 scsi_finish_command vmlinux EXPORT_SYMBOL ++0x11f447ce __gpio_to_irq vmlinux EXPORT_SYMBOL_GPL ++0xeba6034f user_describe vmlinux EXPORT_SYMBOL_GPL ++0x1fb3a608 blkdev_put vmlinux EXPORT_SYMBOL ++0xae6c3303 blkdev_get vmlinux EXPORT_SYMBOL ++0xc7c3a66d tcp_get_info vmlinux EXPORT_SYMBOL_GPL ++0x7a39ec0d __alloc_skb vmlinux EXPORT_SYMBOL ++0x8226642f __gpio_cansleep vmlinux EXPORT_SYMBOL_GPL ++0x98c5718a mutex_trylock vmlinux EXPORT_SYMBOL ++0xe24d3a97 jiffies_64 vmlinux EXPORT_SYMBOL ++0x61eef2c9 _insb vmlinux EXPORT_SYMBOL ++0x89863b3d svc_create vmlinux EXPORT_SYMBOL_GPL ++0xe387568c rpc_lookup_machine_cred vmlinux EXPORT_SYMBOL_GPL ++0x272caed2 pci_cleanup_aer_uncorrect_error_status vmlinux EXPORT_SYMBOL_GPL ++0x6def2db2 half_md4_transform vmlinux EXPORT_SYMBOL ++0xb835b3e4 radix_tree_prev_hole vmlinux EXPORT_SYMBOL ++0xd23a5bcb dcache_readdir vmlinux EXPORT_SYMBOL ++0x0b5cb616 inode_add_bytes vmlinux EXPORT_SYMBOL ++0xdb03e514 thaw_super vmlinux EXPORT_SYMBOL ++0x992edcea generic_file_mmap vmlinux EXPORT_SYMBOL ++0x3bf0c89b abort_creds vmlinux EXPORT_SYMBOL ++0x38b92846 llc_remove_pack vmlinux EXPORT_SYMBOL ++0x4188d439 neigh_rand_reach_time vmlinux EXPORT_SYMBOL ++0x5009e8d3 dev_forward_skb vmlinux EXPORT_SYMBOL_GPL ++0x88a779be sock_common_getsockopt vmlinux EXPORT_SYMBOL ++0xf532f540 sock_common_setsockopt vmlinux EXPORT_SYMBOL ++0xfb09342d n_tty_inherit_ops vmlinux EXPORT_SYMBOL_GPL ++0x65d6d0f0 gpio_direction_input vmlinux EXPORT_SYMBOL_GPL ++0x65408378 zlib_inflate_blob vmlinux EXPORT_SYMBOL ++0x14e837a0 idr_find vmlinux EXPORT_SYMBOL ++0xf1da72e2 vfs_mknod vmlinux EXPORT_SYMBOL ++0xca0bb1d5 ethtool_op_get_sg vmlinux EXPORT_SYMBOL ++0x1c7611b9 skb_dequeue vmlinux EXPORT_SYMBOL ++0x977653c9 filemap_write_and_wait vmlinux EXPORT_SYMBOL ++0x27bbf221 disable_irq_nosync vmlinux EXPORT_SYMBOL ++0x24a79d66 call_usermodehelper_freeinfo vmlinux EXPORT_SYMBOL ++0x00000000 softirq_work_list vmlinux EXPORT_SYMBOL ++0x14e7ca7c alloc_cpu_rmap vmlinux EXPORT_SYMBOL ++0xbc3d7933 netdev_features_change vmlinux EXPORT_SYMBOL ++0x50d5aae6 platform_get_resource_byname vmlinux EXPORT_SYMBOL_GPL ++0x7272c3c8 cpu_online_mask vmlinux EXPORT_SYMBOL ++0x62813e5c nf_ct_port_nlattr_tuple_size net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xe39bc3c9 of_find_node_by_type vmlinux EXPORT_SYMBOL ++0x5fee0ee3 of_find_node_by_path vmlinux EXPORT_SYMBOL ++0x8de66ff6 phy_start vmlinux EXPORT_SYMBOL ++0x2e919a67 devres_find vmlinux EXPORT_SYMBOL_GPL ++0x5df73517 proc_dostring vmlinux EXPORT_SYMBOL ++0xb54533f7 usecs_to_jiffies vmlinux EXPORT_SYMBOL ++0x0037d54d xt_hook_link vmlinux EXPORT_SYMBOL_GPL ++0xb93e2e16 pci_bus_write_config_byte vmlinux EXPORT_SYMBOL ++0x090d7ed0 sysfs_schedule_callback vmlinux EXPORT_SYMBOL_GPL ++0xabcaa577 free_anon_bdev vmlinux EXPORT_SYMBOL ++0xfb7d26f4 files_lglock_lock_init vmlinux EXPORT_SYMBOL ++0xa601a566 raw_hash_sk vmlinux EXPORT_SYMBOL_GPL ++0xa2ef34d7 rps_sock_flow_table vmlinux EXPORT_SYMBOL ++0x9b08b01c skb_insert vmlinux EXPORT_SYMBOL ++0x87ae2dae usb_stor_control_msg vmlinux EXPORT_SYMBOL_GPL ++0x18f9dd97 dev_emerg vmlinux EXPORT_SYMBOL ++0xb012f582 journal_force_commit_nested vmlinux EXPORT_SYMBOL ++0x1c132024 request_any_context_irq vmlinux EXPORT_SYMBOL_GPL ++0xedc410d0 udplite_table vmlinux EXPORT_SYMBOL ++0xbdc36d56 tc_classify_compat vmlinux EXPORT_SYMBOL ++0xcf469f8a blk_queue_max_segment_size vmlinux EXPORT_SYMBOL ++0xf158f170 klist_add_tail vmlinux EXPORT_SYMBOL_GPL ++0x2499acdc dev_kfree_skb_irq vmlinux EXPORT_SYMBOL ++0x8e0fe91b kill_mtd_super vmlinux EXPORT_SYMBOL_GPL ++0x1a2cbf5f pci_find_ext_capability vmlinux EXPORT_SYMBOL_GPL ++0xb9592633 log_wait_commit vmlinux EXPORT_SYMBOL ++0x6e9dd606 __symbol_put vmlinux EXPORT_SYMBOL ++0x884f0c0b netpoll_send_udp vmlinux EXPORT_SYMBOL ++0x89085598 genphy_restart_aneg vmlinux EXPORT_SYMBOL ++0x651b6806 pci_claim_resource vmlinux EXPORT_SYMBOL ++0x9b388444 get_zeroed_page vmlinux EXPORT_SYMBOL ++0xe7bf317d fsl_lbc_addr vmlinux EXPORT_SYMBOL ++0xa1c4b6d2 of_translate_dma_address vmlinux EXPORT_SYMBOL ++0x36d57a24 of_device_is_available vmlinux EXPORT_SYMBOL ++0x6b90f49a input_close_device vmlinux EXPORT_SYMBOL ++0x6bd60be5 key_validate vmlinux EXPORT_SYMBOL ++0xcaea3297 rtnl_create_link vmlinux EXPORT_SYMBOL ++0x92e047fd phy_connect_direct vmlinux EXPORT_SYMBOL ++0xba6f5ed2 tty_insert_flip_string_flags vmlinux EXPORT_SYMBOL ++0xb7188ca3 address_space_init_once vmlinux EXPORT_SYMBOL ++0x8f85f835 prepare_to_wait_exclusive vmlinux EXPORT_SYMBOL ++0x1105338b xfrm_audit_state_replay vmlinux EXPORT_SYMBOL_GPL ++0x0b0fcce8 inet_dev_addr_type vmlinux EXPORT_SYMBOL ++0xe792f22e platform_device_add vmlinux EXPORT_SYMBOL_GPL ++0x035223fb debugfs_create_size_t vmlinux EXPORT_SYMBOL_GPL ++0xdc9c0fca remove_proc_entry vmlinux EXPORT_SYMBOL ++0xd547ec64 fsnotify_add_mark vmlinux EXPORT_SYMBOL_GPL ++0xa502eb8f arpt_register_table net/ipv4/netfilter/arp_tables EXPORT_SYMBOL ++0xbe27f880 ipv6_opt_accepted vmlinux EXPORT_SYMBOL_GPL ++0x46b75886 xfrm_spd_getinfo vmlinux EXPORT_SYMBOL ++0xcd13ff57 pci_walk_bus vmlinux EXPORT_SYMBOL_GPL ++0xf729527b block_is_partially_uptodate vmlinux EXPORT_SYMBOL ++0xd9ecb670 ring_buffer_overruns vmlinux EXPORT_SYMBOL_GPL ++0xcee467f3 xprt_load_transport vmlinux EXPORT_SYMBOL_GPL ++0x9a13af3e alloc_etherdev_mqs vmlinux EXPORT_SYMBOL ++0x2179d22c uart_resume_port vmlinux EXPORT_SYMBOL ++0x83d9de3d ahash_free_instance vmlinux EXPORT_SYMBOL_GPL ++0xe965217d bdi_register_dev vmlinux EXPORT_SYMBOL ++0x9a303feb xt_rateest_lookup net/netfilter/xt_RATEEST EXPORT_SYMBOL_GPL ++0x076eb1e3 nfs_commit_clear_lock vmlinux EXPORT_SYMBOL_GPL ++0x2b76aaca pagecache_write_end vmlinux EXPORT_SYMBOL ++0xc4708199 cpm_muram_addr vmlinux EXPORT_SYMBOL ++0xf5629e6e rpc_clone_client vmlinux EXPORT_SYMBOL_GPL ++0x45704bee xfrm_audit_state_icvfail vmlinux EXPORT_SYMBOL_GPL ++0xb9da2997 snmp_fold_field64 vmlinux EXPORT_SYMBOL_GPL ++0x42621f9f of_get_next_child vmlinux EXPORT_SYMBOL ++0x2618e30b hid_resolv_usage vmlinux EXPORT_SYMBOL_GPL ++0x3e44ea18 sdio_f0_readb vmlinux EXPORT_SYMBOL_GPL ++0x6b645db0 spi_register_master vmlinux EXPORT_SYMBOL_GPL ++0xcc36f32e fb_unregister_client vmlinux EXPORT_SYMBOL ++0x87925ca6 kstrtoint_from_user vmlinux EXPORT_SYMBOL ++0xfde0b92c crypto_larval_error vmlinux EXPORT_SYMBOL_GPL ++0xc8d428d1 __nf_ct_l4proto_find net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x9e9e305b xfrm_inner_extract_output vmlinux EXPORT_SYMBOL_GPL ++0x564436dc inet_csk_init_xmit_timers vmlinux EXPORT_SYMBOL ++0x1b52db1c probe_kernel_read vmlinux EXPORT_SYMBOL_GPL ++0x8111c5eb kmap_atomic_prot vmlinux EXPORT_SYMBOL ++0x900d37fb transport_add_device vmlinux EXPORT_SYMBOL_GPL ++0xbee5ca31 vfs_readlink vmlinux EXPORT_SYMBOL ++0xd00652f3 timecompare_offset vmlinux EXPORT_SYMBOL_GPL ++0x68609857 complete_and_exit vmlinux EXPORT_SYMBOL ++0x6cfe0225 inet6_lookup vmlinux EXPORT_SYMBOL_GPL ++0xae4c9e70 sysfs_remove_group vmlinux EXPORT_SYMBOL_GPL ++0xf583db29 sysfs_remove_file_from_group vmlinux EXPORT_SYMBOL_GPL ++0x83ce82eb get_monotonic_boottime vmlinux EXPORT_SYMBOL_GPL ++0xc91ff664 down_read_trylock vmlinux EXPORT_SYMBOL ++0x4235ac11 dcbnl_cee_notify vmlinux EXPORT_SYMBOL ++0x93200b86 serial8250_handle_irq vmlinux EXPORT_SYMBOL_GPL ++0x4dcec118 nf_nat_set_seq_adjust net/ipv4/netfilter/nf_nat EXPORT_SYMBOL_GPL ++0xc6721caa nf_setsockopt vmlinux EXPORT_SYMBOL ++0x66297ceb nf_getsockopt vmlinux EXPORT_SYMBOL ++0x579e0bf5 rtnl_unregister_all vmlinux EXPORT_SYMBOL_GPL ++0x28d06a1f netif_rx_ni vmlinux EXPORT_SYMBOL ++0x160c8e49 i2c_smbus_xfer vmlinux EXPORT_SYMBOL ++0x1d1183eb device_attach vmlinux EXPORT_SYMBOL_GPL ++0x7b3d0f33 tty_port_open vmlinux EXPORT_SYMBOL ++0xe6faea36 alloc_disk vmlinux EXPORT_SYMBOL ++0xfa0ff0b4 blk_rq_map_user_iov vmlinux EXPORT_SYMBOL ++0x3ec13a0e seq_puts vmlinux EXPORT_SYMBOL ++0x3c620520 seq_putc vmlinux EXPORT_SYMBOL ++0xd7112524 usb_create_shared_hcd vmlinux EXPORT_SYMBOL_GPL ++0xca91df2e uart_update_timeout vmlinux EXPORT_SYMBOL ++0xeea70e8b part_round_stats vmlinux EXPORT_SYMBOL_GPL ++0x5374fd5a d_genocide vmlinux EXPORT_SYMBOL ++0x23af09db __module_put_and_exit vmlinux EXPORT_SYMBOL ++0x0088a193 __alloc_workqueue_key vmlinux EXPORT_SYMBOL_GPL ++0xaee6643e elv_dispatch_add_tail vmlinux EXPORT_SYMBOL ++0xaa966bf7 end_buffer_write_sync vmlinux EXPORT_SYMBOL ++0xa8835c2b d_drop vmlinux EXPORT_SYMBOL ++0xf165adc2 d_rehash vmlinux EXPORT_SYMBOL ++0xdea3251f file_open_root vmlinux EXPORT_SYMBOL ++0xc154f8f2 flush_kthread_work vmlinux EXPORT_SYMBOL_GPL ++0xa89464b7 __ashldi3 vmlinux EXPORT_SYMBOL ++0xb292666e __mmc_claim_host vmlinux EXPORT_SYMBOL ++0xed6010a9 usb_poison_urb vmlinux EXPORT_SYMBOL_GPL ++0xbf7c5874 pci_get_class vmlinux EXPORT_SYMBOL ++0x6b1b67d3 __bdevname vmlinux EXPORT_SYMBOL ++0xad4ba1e4 vfs_write vmlinux EXPORT_SYMBOL ++0xbea16979 netif_rx vmlinux EXPORT_SYMBOL ++0x1fbf241d swiotlb_sync_sg_for_cpu vmlinux EXPORT_SYMBOL ++0x955b0e2e kthread_worker_fn vmlinux EXPORT_SYMBOL_GPL ++0x9d0abaf6 xfrm_stateonly_find vmlinux EXPORT_SYMBOL ++0x34733550 usb_create_hcd vmlinux EXPORT_SYMBOL_GPL ++0x72ea7b2d scsi_device_type vmlinux EXPORT_SYMBOL ++0xadf2bd53 unregister_binfmt vmlinux EXPORT_SYMBOL ++0x2d9402fe alloc_vm_area vmlinux EXPORT_SYMBOL_GPL ++0x65bb58a2 _raw_read_trylock vmlinux EXPORT_SYMBOL ++0x844404cf ISA_DMA_THRESHOLD vmlinux EXPORT_SYMBOL ++0x908169b4 xdr_init_encode vmlinux EXPORT_SYMBOL_GPL ++0xb4bd61df netdev_bonding_change vmlinux EXPORT_SYMBOL ++0xe15c2179 sk_reset_txq vmlinux EXPORT_SYMBOL ++0xb2af542a sock_no_accept vmlinux EXPORT_SYMBOL ++0x2fa50e36 set_groups vmlinux EXPORT_SYMBOL ++0xec25f967 klist_del vmlinux EXPORT_SYMBOL_GPL ++0x3c9d911f skb_dst_set_noref vmlinux EXPORT_SYMBOL ++0x839c2a1f mmc_unregister_driver vmlinux EXPORT_SYMBOL ++0x21f0b642 elevator_exit vmlinux EXPORT_SYMBOL ++0xc4fa4b8f __lock_buffer vmlinux EXPORT_SYMBOL ++0xbb0ab47b debug_locks vmlinux EXPORT_SYMBOL_GPL ++0x6d953c4b ablkcipher_walk_done vmlinux EXPORT_SYMBOL_GPL ++0xed2498e7 ablkcipher_walk_phys vmlinux EXPORT_SYMBOL_GPL ++0x3999991e aead_geniv_alloc vmlinux EXPORT_SYMBOL_GPL ++0x20a789ac irq_set_chip_data vmlinux EXPORT_SYMBOL ++0x5971a2d5 inet6_csk_xmit vmlinux EXPORT_SYMBOL_GPL ++0x4d648b71 tcp_ioctl vmlinux EXPORT_SYMBOL ++0x5d9b4dd5 vfs_symlink vmlinux EXPORT_SYMBOL ++0x3ae34d58 find_vpid vmlinux EXPORT_SYMBOL_GPL ++0xd273b1b1 __round_jiffies_up_relative vmlinux EXPORT_SYMBOL_GPL ++0x17fe13bd unmap_mapping_range vmlinux EXPORT_SYMBOL ++0xeecb92f0 inet_select_addr vmlinux EXPORT_SYMBOL ++0x51855d05 dev_getbyhwaddr_rcu vmlinux EXPORT_SYMBOL ++0xadfbdc10 skb_flow_dissect vmlinux EXPORT_SYMBOL ++0xcd336604 pci_enable_device vmlinux EXPORT_SYMBOL ++0xc86a546a cpu_present_mask vmlinux EXPORT_SYMBOL ++0x6373d84b xprt_release_xprt_cong vmlinux EXPORT_SYMBOL_GPL ++0xbbca5c26 dcache_dir_close vmlinux EXPORT_SYMBOL ++0x82e5a238 vm_get_page_prot vmlinux EXPORT_SYMBOL ++0x6450bfd7 rpc_wake_up_queued_task vmlinux EXPORT_SYMBOL_GPL ++0xa9ade535 unregister_snap_client vmlinux EXPORT_SYMBOL ++0xee6e2a28 rtc_irq_set_state vmlinux EXPORT_SYMBOL_GPL ++0xbd040986 phy_driver_register vmlinux EXPORT_SYMBOL ++0x3b555ebf scsi_dma_unmap vmlinux EXPORT_SYMBOL ++0xb4232cab relay_reset vmlinux EXPORT_SYMBOL_GPL ++0x6971a684 nf_conntrack_register_notifier net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x0dcff8e4 inet_put_port vmlinux EXPORT_SYMBOL ++0xcee525f4 sock_no_connect vmlinux EXPORT_SYMBOL ++0x036f74a7 phy_print_status vmlinux EXPORT_SYMBOL ++0x070473ec pci_remove_bus vmlinux EXPORT_SYMBOL ++0xb3305d52 send_remote_softirq vmlinux EXPORT_SYMBOL ++0xa1f8fe75 wait_for_completion_killable_timeout vmlinux EXPORT_SYMBOL ++0x10ecc52c usb_amd_quirk_pll_enable vmlinux EXPORT_SYMBOL_GPL ++0x279ef3e3 skcipher_geniv_alloc vmlinux EXPORT_SYMBOL_GPL ++0x6e224a7a need_conntrack net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x4a358252 __bitmap_subset vmlinux EXPORT_SYMBOL ++0x1c1af916 set_normalized_timespec vmlinux EXPORT_SYMBOL ++0xbeccc586 eth_type_trans vmlinux EXPORT_SYMBOL ++0xbfdff814 of_get_address vmlinux EXPORT_SYMBOL ++0xaed8bc14 debugfs_create_blob vmlinux EXPORT_SYMBOL_GPL ++0x928f76ce mb_cache_entry_get vmlinux EXPORT_SYMBOL ++0x6655f24b vm_insert_mixed vmlinux EXPORT_SYMBOL ++0x7b08c0c5 send_sig vmlinux EXPORT_SYMBOL ++0xd8d36fcd tcp_shutdown vmlinux EXPORT_SYMBOL ++0x581f6a59 usb_stor_set_xfer_buf vmlinux EXPORT_SYMBOL_GPL ++0xab303c2a scsi_nonblockable_ioctl vmlinux EXPORT_SYMBOL ++0xbe77aebe down_write_trylock vmlinux EXPORT_SYMBOL ++0x730ff363 param_set_uint vmlinux EXPORT_SYMBOL ++0x776637d2 rpc_init_wait_queue vmlinux EXPORT_SYMBOL_GPL ++0xf389fe60 __hw_addr_init vmlinux EXPORT_SYMBOL ++0x199ed0cd net_disable_timestamp vmlinux EXPORT_SYMBOL ++0x96f5cd3e sdio_set_host_pm_flags vmlinux EXPORT_SYMBOL_GPL ++0xe251fc75 usb_stor_ctrl_transfer vmlinux EXPORT_SYMBOL_GPL ++0x4afe9a77 scsi_partsize vmlinux EXPORT_SYMBOL ++0x9ac8f3af of_find_device_by_node vmlinux EXPORT_SYMBOL ++0x4aaab2b1 groups_alloc vmlinux EXPORT_SYMBOL ++0xf338d4c3 netlink_unregister_notifier vmlinux EXPORT_SYMBOL ++0xc4c41664 simple_release_fs vmlinux EXPORT_SYMBOL ++0xdc9498dd down vmlinux EXPORT_SYMBOL ++0x5ab67931 do_IRQ vmlinux EXPORT_SYMBOL ++0x8e2ea861 blk_end_request vmlinux EXPORT_SYMBOL ++0xf3a0e01f skb_put vmlinux EXPORT_SYMBOL ++0xdc5da161 mtd_concat_create vmlinux EXPORT_SYMBOL ++0x22ef965d scsi_host_put vmlinux EXPORT_SYMBOL ++0x3895cd7a nfnl_unlock net/netfilter/nfnetlink EXPORT_SYMBOL_GPL ++0x07ae60b6 nf_nat_proto_in_range net/ipv4/netfilter/nf_nat EXPORT_SYMBOL_GPL ++0xe464582e generic_block_fiemap vmlinux EXPORT_SYMBOL ++0x735d8503 add_wait_queue vmlinux EXPORT_SYMBOL ++0xd276f795 param_ops_invbool vmlinux EXPORT_SYMBOL ++0x65dabd9c dev_add_pack vmlinux EXPORT_SYMBOL ++0xbde3c08a usb_hub_clear_tt_buffer vmlinux EXPORT_SYMBOL_GPL ++0x0a3131f6 strnchr vmlinux EXPORT_SYMBOL ++0x9f984513 strrchr vmlinux EXPORT_SYMBOL ++0xd20bf6ba dcookie_unregister vmlinux EXPORT_SYMBOL_GPL ++0x557e3153 balance_dirty_pages_ratelimited_nr vmlinux EXPORT_SYMBOL ++0x7afa89fc vsnprintf vmlinux EXPORT_SYMBOL ++0x44b911c3 rb_replace_node vmlinux EXPORT_SYMBOL ++0x6ff607b6 crypto_get_default_rng vmlinux EXPORT_SYMBOL_GPL ++0x668402aa crypto_put_default_rng vmlinux EXPORT_SYMBOL_GPL ++0x07c13af6 crypto_mod_put vmlinux EXPORT_SYMBOL_GPL ++0x94a69fd0 journal_clear_err vmlinux EXPORT_SYMBOL ++0x09531a7b mount_pseudo vmlinux EXPORT_SYMBOL ++0x0530dede _raw_write_trylock vmlinux EXPORT_SYMBOL ++0x4205ad24 cancel_work_sync vmlinux EXPORT_SYMBOL_GPL ++0x37382ea4 nf_ct_gre_keymap_flush net/netfilter/nf_conntrack_proto_gre EXPORT_SYMBOL ++0x99cdc86b sysctl_tcp_reordering vmlinux EXPORT_SYMBOL ++0xa3431157 input_set_keycode vmlinux EXPORT_SYMBOL ++0x6b44d1af alloc_pci_dev vmlinux EXPORT_SYMBOL ++0x9754ec10 radix_tree_preload vmlinux EXPORT_SYMBOL ++0x9d1341ef blkdev_ioctl vmlinux EXPORT_SYMBOL_GPL ++0xd11c0dc1 __kernel_param_unlock vmlinux EXPORT_SYMBOL ++0x88279f25 cpm_muram_alloc vmlinux EXPORT_SYMBOL ++0x56a10763 csum_tcpudp_magic vmlinux EXPORT_SYMBOL ++0x9fedb268 __i2c_board_lock vmlinux EXPORT_SYMBOL_GPL ++0x65dba254 tty_ldisc_flush vmlinux EXPORT_SYMBOL_GPL ++0x29028646 crypto_register_instance vmlinux EXPORT_SYMBOL_GPL ++0x2251978a crypto_alloc_tfm vmlinux EXPORT_SYMBOL_GPL ++0x760afcf0 bdi_destroy vmlinux EXPORT_SYMBOL ++0xe88cba4b skb_tstamp_tx vmlinux EXPORT_SYMBOL_GPL ++0x28830c73 tty_set_operations vmlinux EXPORT_SYMBOL ++0x616b825d dql_init vmlinux EXPORT_SYMBOL ++0x69e27c7a bitmap_copy_le vmlinux EXPORT_SYMBOL ++0x4dec6038 memscan vmlinux EXPORT_SYMBOL ++0x239b6d58 mark_buffer_dirty vmlinux EXPORT_SYMBOL ++0x150beb03 get_super vmlinux EXPORT_SYMBOL ++0x00801678 flush_scheduled_work vmlinux EXPORT_SYMBOL ++0xffb6efb2 write_bytes_to_xdr_buf vmlinux EXPORT_SYMBOL_GPL ++0xafdc3bb7 skb_copy_and_csum_bits vmlinux EXPORT_SYMBOL ++0xe03114f3 ll_rw_block vmlinux EXPORT_SYMBOL ++0xd59e518f block_write_begin vmlinux EXPORT_SYMBOL ++0xbe2e3b75 kstrtos8 vmlinux EXPORT_SYMBOL ++0x124f2056 crypto_get_attr_type vmlinux EXPORT_SYMBOL_GPL ++0x1cbc0b01 nfnetlink_send net/netfilter/nfnetlink EXPORT_SYMBOL_GPL ++0x12e280e3 svc_proc_unregister vmlinux EXPORT_SYMBOL_GPL ++0x26c90ea4 scsi_eh_get_sense vmlinux EXPORT_SYMBOL_GPL ++0x5d83dda1 device_create_bin_file vmlinux EXPORT_SYMBOL_GPL ++0xdef35215 pci_intx vmlinux EXPORT_SYMBOL_GPL ++0x83800bfa kref_init vmlinux EXPORT_SYMBOL ++0x2d5cc8db crypto_alloc_aead vmlinux EXPORT_SYMBOL_GPL ++0xba5ad651 crypto_spawn_tfm2 vmlinux EXPORT_SYMBOL_GPL ++0x50fad434 round_jiffies_up vmlinux EXPORT_SYMBOL_GPL ++0x46c1ef6e dev_set_mac_address vmlinux EXPORT_SYMBOL ++0x05c9593c sk_receive_skb vmlinux EXPORT_SYMBOL ++0xf5c05914 generic_segment_checks vmlinux EXPORT_SYMBOL ++0xd0f36f0d audit_log_format vmlinux EXPORT_SYMBOL ++0xec15f00a tcp_cookie_generator vmlinux EXPORT_SYMBOL ++0x6d2fc5a6 net_namespace_list vmlinux EXPORT_SYMBOL_GPL ++0x37287a4f sock_register vmlinux EXPORT_SYMBOL ++0xbcbaf605 loop_register_transfer vmlinux EXPORT_SYMBOL ++0x2c7e8020 pci_find_bus vmlinux EXPORT_SYMBOL ++0x1f58e71b nfnl_lock net/netfilter/nfnetlink EXPORT_SYMBOL_GPL ++0x16bd8d7a inet6_register_protosw vmlinux EXPORT_SYMBOL ++0x3f1c88ef netif_set_real_num_tx_queues vmlinux EXPORT_SYMBOL ++0xb0819781 netif_set_real_num_rx_queues vmlinux EXPORT_SYMBOL ++0x5ad98fe1 dev_set_group vmlinux EXPORT_SYMBOL ++0x8ac0ffc6 phy_register_fixup_for_uid vmlinux EXPORT_SYMBOL ++0xfdbc60ef register_mtd_blktrans vmlinux EXPORT_SYMBOL_GPL ++0xb4709322 scsi_dev_info_add_list vmlinux EXPORT_SYMBOL ++0xf50c9445 end_buffer_async_write vmlinux EXPORT_SYMBOL ++0x111fa7c9 qe_pin_set_dedicated vmlinux EXPORT_SYMBOL ++0x2f045815 ip_nat_decode_session vmlinux EXPORT_SYMBOL ++0xbb9cfeb4 sdio_get_host_pm_caps vmlinux EXPORT_SYMBOL_GPL ++0x75de8c53 vfs_writev vmlinux EXPORT_SYMBOL ++0xb258347c svc_rpcb_cleanup vmlinux EXPORT_SYMBOL_GPL ++0x9062c322 ring_buffer_consume vmlinux EXPORT_SYMBOL_GPL ++0x1c5b1f28 irq_free_descs vmlinux EXPORT_SYMBOL_GPL ++0x4fc9418d proc_dointvec vmlinux EXPORT_SYMBOL ++0xa2a5fd77 inet_ehash_secret vmlinux EXPORT_SYMBOL ++0x7f6680dd __inet_lookup_established vmlinux EXPORT_SYMBOL_GPL ++0x2ab95de3 netdev_alert vmlinux EXPORT_SYMBOL ++0x0a540769 rpc_print_iostats vmlinux EXPORT_SYMBOL_GPL ++0x4bb15c8c udp_lib_rehash vmlinux EXPORT_SYMBOL ++0xb8f4d294 udp_lib_unhash vmlinux EXPORT_SYMBOL ++0x1d9496fc of_pci_find_child_device vmlinux EXPORT_SYMBOL_GPL ++0x05495392 hid_debug vmlinux EXPORT_SYMBOL_GPL ++0x112dcb5f device_show_ulong vmlinux EXPORT_SYMBOL_GPL ++0x79df9c12 cpumask_next_and vmlinux EXPORT_SYMBOL ++0x3969cdfb nf_hook_slow vmlinux EXPORT_SYMBOL ++0xce5ac24f zlib_inflate_workspacesize vmlinux EXPORT_SYMBOL ++0x6103edc6 tcp_recvmsg vmlinux EXPORT_SYMBOL ++0xace5c0fc usb_bus_list vmlinux EXPORT_SYMBOL_GPL ++0x80f2bf56 xfrm_audit_state_notfound_simple vmlinux EXPORT_SYMBOL_GPL ++0xe8b63ace radix_tree_range_tag_if_tagged vmlinux EXPORT_SYMBOL ++0xc2882ea4 proc_dointvec_userhz_jiffies vmlinux EXPORT_SYMBOL ++0xd48f3111 console_start vmlinux EXPORT_SYMBOL ++0x21398e9d tcp_simple_retransmit vmlinux EXPORT_SYMBOL ++0xad58729e inet_csk_bind_conflict vmlinux EXPORT_SYMBOL_GPL ++0x8d93899a xt_register_match vmlinux EXPORT_SYMBOL ++0x68f40f80 of_find_node_with_property vmlinux EXPORT_SYMBOL ++0x17eb9b10 anon_inode_getfile vmlinux EXPORT_SYMBOL_GPL ++0x8ec1678f simple_dir_inode_operations vmlinux EXPORT_SYMBOL ++0x065f1d39 fsl_pq_mdio_bus_name vmlinux EXPORT_SYMBOL_GPL ++0x75a4001c dmam_pool_create vmlinux EXPORT_SYMBOL ++0x8fc5a78b genphy_suspend vmlinux EXPORT_SYMBOL ++0x0878c365 subsys_system_register vmlinux EXPORT_SYMBOL_GPL ++0x55c887e2 __find_get_block vmlinux EXPORT_SYMBOL ++0xcc276874 dcache_dir_open vmlinux EXPORT_SYMBOL ++0x3f4547a7 put_unused_fd vmlinux EXPORT_SYMBOL ++0xd2555f19 jiffies_64_to_clock_t vmlinux EXPORT_SYMBOL ++0x9d51befe inet6_lookup_listener vmlinux EXPORT_SYMBOL_GPL ++0xfbe27a1c rb_first vmlinux EXPORT_SYMBOL ++0x7c904ded unregister_module_notifier vmlinux EXPORT_SYMBOL ++0xddc16c88 flush_delayed_work vmlinux EXPORT_SYMBOL ++0xe5ab60b2 mmc_switch vmlinux EXPORT_SYMBOL_GPL ++0xfb65ffac scsi_cmd_print_sense_hdr vmlinux EXPORT_SYMBOL ++0x616e9785 zero_fill_bio vmlinux EXPORT_SYMBOL ++0xb628f715 files_lglock_local_lock vmlinux EXPORT_SYMBOL ++0x082c3213 pci_root_buses vmlinux EXPORT_SYMBOL ++0x72d4c23c fsl_get_sys_freq vmlinux EXPORT_SYMBOL ++0xfc4d7b87 tcp_syn_ack_timeout vmlinux EXPORT_SYMBOL ++0x0397f6b0 nf_log_unregister vmlinux EXPORT_SYMBOL ++0x72975f42 mmc_alloc_host vmlinux EXPORT_SYMBOL ++0x110020ff scsi_eh_ready_devs vmlinux EXPORT_SYMBOL_GPL ++0x18f4e85e generic_file_buffered_write vmlinux EXPORT_SYMBOL ++0xc1c2dd09 __hw_addr_flush vmlinux EXPORT_SYMBOL ++0x548a8689 of_property_read_string vmlinux EXPORT_SYMBOL_GPL ++0x05b82c15 thermal_cooling_device_register vmlinux EXPORT_SYMBOL ++0xb0e70ae3 input_open_device vmlinux EXPORT_SYMBOL ++0xfe990052 gpio_free vmlinux EXPORT_SYMBOL_GPL ++0xea054b22 nla_policy_len vmlinux EXPORT_SYMBOL ++0xd92afabe bitmap_clear vmlinux EXPORT_SYMBOL ++0xa6e1a05f fsync_bdev vmlinux EXPORT_SYMBOL ++0x710fed59 cache_unregister vmlinux EXPORT_SYMBOL_GPL ++0xa3bbc0ac xprt_set_retrans_timeout_def vmlinux EXPORT_SYMBOL_GPL ++0x0d4d2a18 ip6_dst_lookup vmlinux EXPORT_SYMBOL_GPL ++0xedd0ed46 i2c_new_device vmlinux EXPORT_SYMBOL_GPL ++0xdc39e99d device_for_each_child vmlinux EXPORT_SYMBOL_GPL ++0x40a9b349 vzalloc vmlinux EXPORT_SYMBOL ++0xbaaab8ae timespec_to_jiffies vmlinux EXPORT_SYMBOL ++0x51c251f8 unregister_key_type vmlinux EXPORT_SYMBOL ++0xa38e691a ioremap_bot vmlinux EXPORT_SYMBOL ++0x8530e62e rpc_shutdown_client vmlinux EXPORT_SYMBOL_GPL ++0x11089ac7 _ctype vmlinux EXPORT_SYMBOL ++0x649ddc16 blk_get_queue vmlinux EXPORT_SYMBOL ++0x5eb6f94d bd_set_size vmlinux EXPORT_SYMBOL ++0xa28aaf29 rh_create vmlinux EXPORT_SYMBOL_GPL ++0x0e74417a udp_proc_unregister vmlinux EXPORT_SYMBOL ++0x0deebb29 mtd_device_unregister vmlinux EXPORT_SYMBOL_GPL ++0x37f614b7 __kfifo_len_r vmlinux EXPORT_SYMBOL ++0x6f868b48 svc_xprt_names vmlinux EXPORT_SYMBOL_GPL ++0x92cff065 inet_sk_rebuild_header vmlinux EXPORT_SYMBOL ++0x0ea878cd skb_copy vmlinux EXPORT_SYMBOL ++0x829b3b9d input_inject_event vmlinux EXPORT_SYMBOL ++0x17ec8f5b pci_bus_read_config_dword vmlinux EXPORT_SYMBOL ++0x7593d385 div64_s64 vmlinux EXPORT_SYMBOL ++0x27864d57 memparse vmlinux EXPORT_SYMBOL ++0x3ead9a33 block_truncate_page vmlinux EXPORT_SYMBOL ++0x9d130651 generic_write_checks vmlinux EXPORT_SYMBOL ++0x1d2e87c6 do_gettimeofday vmlinux EXPORT_SYMBOL ++0xcf015f7b do_settimeofday vmlinux EXPORT_SYMBOL ++0xd172cb8d netdev_increment_features vmlinux EXPORT_SYMBOL ++0x264b5eda uart_match_port vmlinux EXPORT_SYMBOL ++0x9e04279a cap_file_mmap vmlinux EXPORT_SYMBOL_GPL ++0xc5a37aa8 flow_cache_lookup vmlinux EXPORT_SYMBOL ++0x55da6c07 alloc_tty_driver vmlinux EXPORT_SYMBOL ++0xfda98690 pcie_port_service_register vmlinux EXPORT_SYMBOL ++0x722852be pci_request_selected_regions vmlinux EXPORT_SYMBOL ++0x45666d9b __splice_from_pipe vmlinux EXPORT_SYMBOL ++0x9c3dd03a __nf_ct_ext_destroy net/netfilter/nf_conntrack EXPORT_SYMBOL ++0x3c65c88c unregister_net_sysctl_table vmlinux EXPORT_SYMBOL_GPL ++0x24e6d442 sdio_align_size vmlinux EXPORT_SYMBOL_GPL ++0x2114d287 tty_write_room vmlinux EXPORT_SYMBOL ++0x586527c3 sysfs_add_file_to_group vmlinux EXPORT_SYMBOL_GPL ++0x8436f8e3 param_ops_ushort vmlinux EXPORT_SYMBOL ++0x546027e3 dev_trans_start vmlinux EXPORT_SYMBOL ++0x94cbd061 dql_reset vmlinux EXPORT_SYMBOL ++0x6a33ea8b blk_register_region vmlinux EXPORT_SYMBOL ++0x93dd83ef bio_put vmlinux EXPORT_SYMBOL ++0x65f9016f task_tgid_nr_ns vmlinux EXPORT_SYMBOL ++0x1b767055 of_find_compatible_node vmlinux EXPORT_SYMBOL ++0xabc50916 input_alloc_absinfo vmlinux EXPORT_SYMBOL ++0x13fe75bb scsi_is_target_device vmlinux EXPORT_SYMBOL ++0x7da357d0 journal_force_commit vmlinux EXPORT_SYMBOL ++0xef91072e each_symbol_section vmlinux EXPORT_SYMBOL_GPL ++0xe697313d sk_dst_check vmlinux EXPORT_SYMBOL ++0x6a76f3ac blk_iopoll_enable vmlinux EXPORT_SYMBOL ++0xb906fe4a inode_needs_sync vmlinux EXPORT_SYMBOL ++0x7d38f2e3 grab_cache_page_nowait vmlinux EXPORT_SYMBOL ++0x8b70e8ea __wake_up_sync_key vmlinux EXPORT_SYMBOL_GPL ++0x042333d2 dev_getfirstbyhwtype vmlinux EXPORT_SYMBOL ++0x9ea7341b scsi_internal_device_block vmlinux EXPORT_SYMBOL_GPL ++0x25820c64 fs_overflowuid vmlinux EXPORT_SYMBOL ++0x4ebd6a47 wake_up_process vmlinux EXPORT_SYMBOL ++0x53ebab1b _outsl_ns vmlinux EXPORT_SYMBOL ++0x9e2ae014 __nf_ct_refresh_acct net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x556a7629 skb_dequeue_tail vmlinux EXPORT_SYMBOL ++0x311f6ed3 input_ff_erase vmlinux EXPORT_SYMBOL_GPL ++0x8472112c scsi_target_resume vmlinux EXPORT_SYMBOL ++0x4cc325f1 nfs_initiate_read vmlinux EXPORT_SYMBOL_GPL ++0x58392cb3 __get_user_pages vmlinux EXPORT_SYMBOL ++0x0c485af1 __module_address vmlinux EXPORT_SYMBOL_GPL ++0x5b076b1b inet_stream_ops vmlinux EXPORT_SYMBOL ++0xe791c07d qdisc_reset vmlinux EXPORT_SYMBOL ++0x63ecad53 register_netdevice_notifier vmlinux EXPORT_SYMBOL ++0xb573cf83 pci_get_device vmlinux EXPORT_SYMBOL ++0x5b237650 blk_complete_request vmlinux EXPORT_SYMBOL ++0x808ec1a3 crypto_alg_tested vmlinux EXPORT_SYMBOL_GPL ++0x583c0845 bio_unmap_user vmlinux EXPORT_SYMBOL ++0xe4a5911c udp_seq_open vmlinux EXPORT_SYMBOL ++0x133b4ee4 idr_get_next vmlinux EXPORT_SYMBOL ++0xc4571a56 fail_migrate_page vmlinux EXPORT_SYMBOL ++0xdf4c8767 ns_to_timeval vmlinux EXPORT_SYMBOL ++0xcacba0a5 nf_ct_expect_register_notifier net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x721b1851 skip_spaces vmlinux EXPORT_SYMBOL ++0x0c0c015e ring_buffer_swap_cpu vmlinux EXPORT_SYMBOL_GPL ++0xdc2adb35 add_taint vmlinux EXPORT_SYMBOL ++0x60a32ea9 pm_power_off vmlinux EXPORT_SYMBOL_GPL ++0x466c14a7 __delay vmlinux EXPORT_SYMBOL ++0x3e09fbde __neigh_for_each_release vmlinux EXPORT_SYMBOL ++0x1ee9814e irq_of_parse_and_map vmlinux EXPORT_SYMBOL_GPL ++0xe0e37b4c spi_busnum_to_master vmlinux EXPORT_SYMBOL_GPL ++0xb73e0c9c device_initialize vmlinux EXPORT_SYMBOL_GPL ++0x0d558de0 blk_queue_init_tags vmlinux EXPORT_SYMBOL ++0x690a7b30 user_destroy vmlinux EXPORT_SYMBOL_GPL ++0x4f69f21d bdget vmlinux EXPORT_SYMBOL ++0x1c326670 bdput vmlinux EXPORT_SYMBOL ++0x42cdd5c5 fsstack_copy_inode_size vmlinux EXPORT_SYMBOL_GPL ++0xd5248f66 nf_conntrack_untracked net/netfilter/nf_conntrack EXPORT_SYMBOL ++0x0e93bb22 usb_usual_ignore_device vmlinux EXPORT_SYMBOL_GPL ++0xed9f8e6d kstrtos16 vmlinux EXPORT_SYMBOL ++0xfb32b30f ring_buffer_read_prepare_sync vmlinux EXPORT_SYMBOL_GPL ++0xadcac4a3 vfsmount_lock_local_unlock_cpu vmlinux EXPORT_SYMBOL ++0xaef2c83c fs_kobj vmlinux EXPORT_SYMBOL_GPL ++0x956657df crypto_alloc_ablkcipher vmlinux EXPORT_SYMBOL_GPL ++0xfb3b51e1 bio_init vmlinux EXPORT_SYMBOL ++0x7278d328 all_vm_events vmlinux EXPORT_SYMBOL_GPL ++0xfe3c4307 gss_mech_put vmlinux EXPORT_SYMBOL_GPL ++0x2ca3edba rpc_max_payload vmlinux EXPORT_SYMBOL_GPL ++0x288092c9 inet6_hash_connect vmlinux EXPORT_SYMBOL_GPL ++0x6dbad0b5 gnet_stats_copy_rate_est vmlinux EXPORT_SYMBOL ++0x115b689d skb_partial_csum_set vmlinux EXPORT_SYMBOL_GPL ++0x0f2bd6b9 sdio_enable_func vmlinux EXPORT_SYMBOL_GPL ++0x4e505436 subsys_dev_iter_next vmlinux EXPORT_SYMBOL_GPL ++0x334a0cd1 create_empty_buffers vmlinux EXPORT_SYMBOL ++0x2f1cd7a8 init_special_inode vmlinux EXPORT_SYMBOL ++0x0e4a8c58 inet_frag_destroy vmlinux EXPORT_SYMBOL ++0x48dd2a9a skb_make_writable vmlinux EXPORT_SYMBOL ++0x2eeceb42 sk_chk_filter vmlinux EXPORT_SYMBOL ++0xf8a88294 cfi_qry_present vmlinux EXPORT_SYMBOL_GPL ++0x6bb87ddb pipe_to_file vmlinux EXPORT_SYMBOL ++0x114604eb __dec_zone_page_state vmlinux EXPORT_SYMBOL ++0x4b6cb580 __inc_zone_page_state vmlinux EXPORT_SYMBOL ++0xd9c6efac __mod_zone_page_state vmlinux EXPORT_SYMBOL ++0x0b55a26a flush_kthread_worker vmlinux EXPORT_SYMBOL_GPL ++0xa5cef8ad release_resource vmlinux EXPORT_SYMBOL ++0x9ef6b7ea powerpc_debugfs_root vmlinux EXPORT_SYMBOL ++0x5e906550 brioctl_set vmlinux EXPORT_SYMBOL ++0x6a496bc1 input_set_abs_params vmlinux EXPORT_SYMBOL ++0x378abc81 spi_bus_unlock vmlinux EXPORT_SYMBOL_GPL ++0xc60fe5e9 device_schedule_callback_owner vmlinux EXPORT_SYMBOL_GPL ++0x8b498a59 vm_insert_pfn vmlinux EXPORT_SYMBOL ++0xfcaa04a0 out_of_line_wait_on_bit_lock vmlinux EXPORT_SYMBOL ++0xf0bfe668 register_net_sysctl_table vmlinux EXPORT_SYMBOL_GPL ++0x2370b4df xfrm_state_alloc vmlinux EXPORT_SYMBOL ++0x85670f1d rtnl_is_locked vmlinux EXPORT_SYMBOL ++0xedd06a1b of_parse_phandles_with_args vmlinux EXPORT_SYMBOL ++0xecc376f4 fat_remove_entries vmlinux EXPORT_SYMBOL_GPL ++0x8a2b65f0 page_symlink vmlinux EXPORT_SYMBOL ++0xbc6f931b workqueue_congested vmlinux EXPORT_SYMBOL_GPL ++0x3d6d8275 __xfrm_route_forward vmlinux EXPORT_SYMBOL ++0xe2ae4be3 gen_replace_estimator vmlinux EXPORT_SYMBOL ++0xe2353e10 scsi_target_unblock vmlinux EXPORT_SYMBOL_GPL ++0x751b2247 param_get_bool vmlinux EXPORT_SYMBOL ++0xb0146c3a param_set_byte vmlinux EXPORT_SYMBOL ++0xf5e3f6f8 rpc_call_null vmlinux EXPORT_SYMBOL_GPL ++0x9fdecc31 unregister_netdevice_many vmlinux EXPORT_SYMBOL ++0x31c11871 rtc_device_unregister vmlinux EXPORT_SYMBOL_GPL ++0x5a21f0f4 blk_abort_queue vmlinux EXPORT_SYMBOL_GPL ++0x3e6e75c0 blk_queue_logical_block_size vmlinux EXPORT_SYMBOL ++0x63f608e4 init_srcu_struct vmlinux EXPORT_SYMBOL_GPL ++0x594b47d6 sunrpc_cache_lookup vmlinux EXPORT_SYMBOL_GPL ++0xdda28e49 arp_tbl vmlinux EXPORT_SYMBOL ++0xfea540c6 __skb_recv_datagram vmlinux EXPORT_SYMBOL ++0x376e7e39 phy_attach vmlinux EXPORT_SYMBOL ++0xfe7c4287 nr_cpu_ids vmlinux EXPORT_SYMBOL ++0xf5e7f053 rh_destroy vmlinux EXPORT_SYMBOL_GPL ++0x065994f1 xdr_encode_opaque_fixed vmlinux EXPORT_SYMBOL_GPL ++0xa516a4a3 tcp_splice_read vmlinux EXPORT_SYMBOL ++0x7c478694 xt_unregister_match vmlinux EXPORT_SYMBOL ++0x36e360e3 __hw_addr_add_multiple vmlinux EXPORT_SYMBOL ++0x0d0c109d of_irq_to_resource vmlinux EXPORT_SYMBOL_GPL ++0xcbc9557f unregister_sysrq_key vmlinux EXPORT_SYMBOL ++0x74ad740d simple_transaction_set vmlinux EXPORT_SYMBOL ++0xed7d1156 simple_transaction_get vmlinux EXPORT_SYMBOL ++0x5f629129 find_pid_ns vmlinux EXPORT_SYMBOL_GPL ++0x17913f3c __nf_conntrack_find net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x56e75d47 klist_node_attached vmlinux EXPORT_SYMBOL_GPL ++0x8b0896a8 lock_sock_nested vmlinux EXPORT_SYMBOL ++0xc0ad921a hid_add_device vmlinux EXPORT_SYMBOL_GPL ++0x1605388f sdio_disable_func vmlinux EXPORT_SYMBOL_GPL ++0x45582f48 scsi_free_command vmlinux EXPORT_SYMBOL ++0xd45c92cb platform_add_devices vmlinux EXPORT_SYMBOL_GPL ++0x92b57248 flush_work vmlinux EXPORT_SYMBOL_GPL ++0x9dd6edf6 usb_deregister vmlinux EXPORT_SYMBOL_GPL ++0x3b261e90 of_device_is_compatible vmlinux EXPORT_SYMBOL ++0x851187ae crypto_alloc_instance vmlinux EXPORT_SYMBOL_GPL ++0xe18b50f9 mpage_writepage vmlinux EXPORT_SYMBOL ++0x18ef997d set_security_override vmlinux EXPORT_SYMBOL ++0x6b2dc060 dump_stack vmlinux EXPORT_SYMBOL ++0x40797035 nfnetlink_subsys_unregister net/netfilter/nfnetlink EXPORT_SYMBOL_GPL ++0xfb9b2d0e raw_seq_start vmlinux EXPORT_SYMBOL_GPL ++0x17f28d7c dst_cow_metrics_generic vmlinux EXPORT_SYMBOL ++0xfa3657fe rtc_read_time vmlinux EXPORT_SYMBOL_GPL ++0x7eacf564 swiotlb_map_page vmlinux EXPORT_SYMBOL_GPL ++0xe8850089 mount_ns vmlinux EXPORT_SYMBOL ++0xf0c82f30 cpu_add_dev_attr vmlinux EXPORT_SYMBOL_GPL ++0x11886e11 kobject_del vmlinux EXPORT_SYMBOL ++0x1343402c crypto_unregister_shash vmlinux EXPORT_SYMBOL_GPL ++0xfbacc823 crypto_unregister_ahash vmlinux EXPORT_SYMBOL_GPL ++0x5eb8e514 usb_reset_endpoint vmlinux EXPORT_SYMBOL_GPL ++0xb6a68816 find_last_bit vmlinux EXPORT_SYMBOL ++0x712dc4d8 inode_dio_done vmlinux EXPORT_SYMBOL_GPL ++0x9a030dc8 poll_initwait vmlinux EXPORT_SYMBOL ++0x5e19264c unregister_console vmlinux EXPORT_SYMBOL ++0xff6dea25 smp_hw_index vmlinux EXPORT_SYMBOL ++0xbe85ec13 nf_ct_helper_ext_add net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x293d41a8 phy_disconnect vmlinux EXPORT_SYMBOL ++0xa8cb5076 aead_geniv_free vmlinux EXPORT_SYMBOL_GPL ++0xd8e484f0 register_chrdev_region vmlinux EXPORT_SYMBOL ++0xf52f4bc3 inet_csk_reqsk_queue_prune vmlinux EXPORT_SYMBOL_GPL ++0xed5f822a netdev_state_change vmlinux EXPORT_SYMBOL ++0x310917fe sort vmlinux EXPORT_SYMBOL ++0x3d19d9ca nfs4_reset_read vmlinux EXPORT_SYMBOL_GPL ++0x541bd60a irq_work_run vmlinux EXPORT_SYMBOL_GPL ++0x6c49c4f2 clockevents_notify vmlinux EXPORT_SYMBOL_GPL ++0x6c1b16e2 usb_sg_cancel vmlinux EXPORT_SYMBOL_GPL ++0xbe3f901e kern_path vmlinux EXPORT_SYMBOL ++0x33817a73 nf_register_queue_handler vmlinux EXPORT_SYMBOL ++0xea91aa6f netpoll_print_options vmlinux EXPORT_SYMBOL ++0x29b1c366 __sg_alloc_table vmlinux EXPORT_SYMBOL ++0x79f9a580 shrink_dcache_sb vmlinux EXPORT_SYMBOL ++0x3ec8886f param_ops_int vmlinux EXPORT_SYMBOL ++0x1b87a6f0 blkdev_issue_flush vmlinux EXPORT_SYMBOL ++0x499043d3 crypto_init_queue vmlinux EXPORT_SYMBOL_GPL ++0xb11b1747 default_backing_dev_info vmlinux EXPORT_SYMBOL_GPL ++0xbdbe7378 cookie_check_timestamp vmlinux EXPORT_SYMBOL ++0x59020915 fsnotify_put_mark vmlinux EXPORT_SYMBOL_GPL ++0x6b4435a7 generic_drop_inode vmlinux EXPORT_SYMBOL_GPL ++0xf57db0bd find_inode_number vmlinux EXPORT_SYMBOL ++0xf5cf326a param_ops_short vmlinux EXPORT_SYMBOL ++0x1f925c00 rpcb_getport_async vmlinux EXPORT_SYMBOL_GPL ++0x8c354480 ip_route_input_common vmlinux EXPORT_SYMBOL ++0xa6970398 __kfifo_to_user_r vmlinux EXPORT_SYMBOL ++0x1de33a9e softnet_data vmlinux EXPORT_SYMBOL ++0x00f42699 files_lglock_global_unlock vmlinux EXPORT_SYMBOL ++0x24e1307e flush_work_sync vmlinux EXPORT_SYMBOL_GPL ++0xfe5d4bb2 sys_tz vmlinux EXPORT_SYMBOL ++0x1ae6ffc8 __skb_tx_hash vmlinux EXPORT_SYMBOL ++0x241f0763 blk_init_queue vmlinux EXPORT_SYMBOL ++0xce67b38d unlock_page vmlinux EXPORT_SYMBOL ++0xcbf10c5b sdio_memcpy_fromio vmlinux EXPORT_SYMBOL_GPL ++0x5785384a flex_array_free_parts vmlinux EXPORT_SYMBOL ++0x0f668ba9 svc_auth_unregister vmlinux EXPORT_SYMBOL_GPL ++0x45456905 xfrm_unregister_type vmlinux EXPORT_SYMBOL ++0x4e781803 nf_ip_checksum vmlinux EXPORT_SYMBOL ++0xe1982309 pci_request_regions_exclusive vmlinux EXPORT_SYMBOL ++0x773a9c94 blk_iopoll_enabled vmlinux EXPORT_SYMBOL ++0xd4d24bb4 hrtimer_init_sleeper vmlinux EXPORT_SYMBOL_GPL ++0x5e1c7425 eth_rebuild_header vmlinux EXPORT_SYMBOL ++0x533031ec neigh_compat_output vmlinux EXPORT_SYMBOL ++0xc6f2dadd user_path_at vmlinux EXPORT_SYMBOL ++0xfd46510b module_put vmlinux EXPORT_SYMBOL ++0x2459bbcc console_set_on_cmdline vmlinux EXPORT_SYMBOL ++0xe9379468 usb_get_from_anchor vmlinux EXPORT_SYMBOL_GPL ++0x2d938d67 genphy_resume vmlinux EXPORT_SYMBOL ++0xee4db89d inode_get_bytes vmlinux EXPORT_SYMBOL ++0x5e3a8a9c __wake_up vmlinux EXPORT_SYMBOL ++0x9fd9cdb0 nf_conntrack_helper_unregister net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xa8a585c0 i2c_for_each_dev vmlinux EXPORT_SYMBOL_GPL ++0x599adf11 dev_driver_string vmlinux EXPORT_SYMBOL ++0x5e52b566 pcie_get_readrq vmlinux EXPORT_SYMBOL ++0xc7a1840e llist_add_batch vmlinux EXPORT_SYMBOL_GPL ++0x0010abad vfs_mkdir vmlinux EXPORT_SYMBOL ++0x79272d01 of_match_node vmlinux EXPORT_SYMBOL ++0x2edfd91a usb_driver_claim_interface vmlinux EXPORT_SYMBOL_GPL ++0x9cfd56c5 scsi_print_status vmlinux EXPORT_SYMBOL ++0x4bf98954 eventfd_ctx_fileget vmlinux EXPORT_SYMBOL_GPL ++0x01139ffc max_mapnr vmlinux EXPORT_SYMBOL ++0xc1ef47df rpc_pipe_generic_upcall vmlinux EXPORT_SYMBOL_GPL ++0x98a76b33 xprt_unregister_transport vmlinux EXPORT_SYMBOL_GPL ++0x93b9629e of_find_i2c_device_by_node vmlinux EXPORT_SYMBOL ++0x7cee66f5 eventfd_fget vmlinux EXPORT_SYMBOL_GPL ++0xc58850d7 dget_parent vmlinux EXPORT_SYMBOL ++0xb36388b7 hid_dump_input vmlinux EXPORT_SYMBOL_GPL ++0x8541878a usb_get_dev vmlinux EXPORT_SYMBOL_GPL ++0x6ecdaa65 mb_cache_create vmlinux EXPORT_SYMBOL ++0x769ec6bc iunique vmlinux EXPORT_SYMBOL ++0x01a4ea6d unregister_die_notifier vmlinux EXPORT_SYMBOL_GPL ++0x5614b010 xfrm_policy_walk_done vmlinux EXPORT_SYMBOL ++0xe0e2d273 inet_dgram_ops vmlinux EXPORT_SYMBOL ++0x8a20e1aa input_release_device vmlinux EXPORT_SYMBOL ++0x9c1c727f scsi_put_command vmlinux EXPORT_SYMBOL ++0xa2134525 blk_alloc_queue vmlinux EXPORT_SYMBOL ++0xdcadc348 mb_cache_destroy vmlinux EXPORT_SYMBOL ++0x0903c239 vid_from_reg drivers/hwmon/hwmon-vid EXPORT_SYMBOL ++0x89253799 get_gendisk vmlinux EXPORT_SYMBOL ++0x99bfbe39 get_unused_fd vmlinux EXPORT_SYMBOL ++0x7a50a315 files_lglock_global_unlock_online vmlinux EXPORT_SYMBOL ++0xbfad4db7 proc_doulongvec_minmax vmlinux EXPORT_SYMBOL ++0x2d36c57b rh_alloc vmlinux EXPORT_SYMBOL_GPL ++0xdd56dbe7 tcp_proc_unregister vmlinux EXPORT_SYMBOL ++0x851d3cba hwmon_device_register vmlinux EXPORT_SYMBOL_GPL ++0xbf4c8a06 sdev_evt_send_simple vmlinux EXPORT_SYMBOL_GPL ++0x6746ae74 pci_renumber_slot vmlinux EXPORT_SYMBOL_GPL ++0xef17cdaf simple_attr_open vmlinux EXPORT_SYMBOL_GPL ++0x9a49d937 __wake_up_locked_key vmlinux EXPORT_SYMBOL_GPL ++0x85c10896 rcu_batches_completed_bh vmlinux EXPORT_SYMBOL_GPL ++0x4578f528 __kfifo_to_user vmlinux EXPORT_SYMBOL ++0xcc7fa952 local_bh_enable_ip vmlinux EXPORT_SYMBOL ++0x27f7e224 xfrm4_rcv_encap vmlinux EXPORT_SYMBOL ++0xc7654bfd udp_poll vmlinux EXPORT_SYMBOL ++0x51ef33b8 kstrndup vmlinux EXPORT_SYMBOL ++0x0583b1a3 irq_set_chip vmlinux EXPORT_SYMBOL ++0x4f513a91 console_stop vmlinux EXPORT_SYMBOL ++0x419cc91e nf_conntrack_tuple_taken net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xd1a9044f inet6_getname vmlinux EXPORT_SYMBOL ++0x8a2cf4b8 xdr_encode_word vmlinux EXPORT_SYMBOL_GPL ++0xf6f682ab auth_domain_find vmlinux EXPORT_SYMBOL_GPL ++0xb95bbaa0 register_mtd_user vmlinux EXPORT_SYMBOL_GPL ++0xbe91f299 debugfs_create_file vmlinux EXPORT_SYMBOL_GPL ++0xc15de2b9 new_inode vmlinux EXPORT_SYMBOL ++0xe16ce22c rpc_restart_call_prepare vmlinux EXPORT_SYMBOL_GPL ++0xa8657869 of_get_phy_mode vmlinux EXPORT_SYMBOL_GPL ++0x28a2ed02 scsi_build_sense_buffer vmlinux EXPORT_SYMBOL ++0xd11042c0 tty_port_close vmlinux EXPORT_SYMBOL ++0x65dccf13 xz_dec_end vmlinux EXPORT_SYMBOL ++0xf9348cbc xz_dec_run vmlinux EXPORT_SYMBOL ++0x76e07962 idr_get_new vmlinux EXPORT_SYMBOL ++0x92a2c46d ida_get_new vmlinux EXPORT_SYMBOL ++0xe0b13336 argv_free vmlinux EXPORT_SYMBOL ++0x3240c65b files_lglock_global_lock_online vmlinux EXPORT_SYMBOL ++0xb7a383e5 genl_unregister_family vmlinux EXPORT_SYMBOL ++0xfe769456 unregister_netdevice_notifier vmlinux EXPORT_SYMBOL ++0x3e01160a tty_register_driver vmlinux EXPORT_SYMBOL ++0xefadeaf0 sdio_release_host vmlinux EXPORT_SYMBOL_GPL ++0xc27db015 driver_remove_file vmlinux EXPORT_SYMBOL_GPL ++0x87f98b5b swiotlb_free_coherent vmlinux EXPORT_SYMBOL ++0x39cb510c kset_unregister vmlinux EXPORT_SYMBOL ++0x1abb4c45 debugfs_create_u32 vmlinux EXPORT_SYMBOL_GPL ++0x98b9e82b register_net_sysctl_rotable vmlinux EXPORT_SYMBOL_GPL ++0x76495a16 llc_build_and_send_ui_pkt vmlinux EXPORT_SYMBOL ++0x87c85967 netdev_rx_handler_register vmlinux EXPORT_SYMBOL_GPL ++0xf0ad1471 inet_csk_reset_keepalive_timer vmlinux EXPORT_SYMBOL ++0xc27d3a6d user_read vmlinux EXPORT_SYMBOL_GPL ++0x53326531 mempool_alloc_pages vmlinux EXPORT_SYMBOL ++0x47939e0d __tasklet_hi_schedule vmlinux EXPORT_SYMBOL ++0x4e4fee60 read_bytes_from_xdr_buf vmlinux EXPORT_SYMBOL_GPL ++0x84d64671 arp_send vmlinux EXPORT_SYMBOL ++0x7b9dea01 xt_register_matches vmlinux EXPORT_SYMBOL ++0x3ed63055 zlib_inflateReset vmlinux EXPORT_SYMBOL ++0xb19760c3 bitmap_onto vmlinux EXPORT_SYMBOL ++0x26faebf0 cdev_del vmlinux EXPORT_SYMBOL ++0x281823c5 __kfifo_out_peek vmlinux EXPORT_SYMBOL ++0x341c41c5 tcp_seq_open vmlinux EXPORT_SYMBOL ++0x456144b4 pneigh_enqueue vmlinux EXPORT_SYMBOL ++0xcc3f71f3 dev_alloc_name vmlinux EXPORT_SYMBOL ++0x6086fae9 rwsem_wake vmlinux EXPORT_SYMBOL ++0x51ee205d fsnotify_init_mark vmlinux EXPORT_SYMBOL_GPL ++0x6c91b04d iov_iter_copy_from_user vmlinux EXPORT_SYMBOL ++0xd5dde498 generic_fh_to_dentry vmlinux EXPORT_SYMBOL_GPL ++0xa3225eb1 try_to_del_timer_sync vmlinux EXPORT_SYMBOL ++0x70469604 ipcomp_output net/xfrm/xfrm_ipcomp EXPORT_SYMBOL_GPL ++0x77d48f27 nf_ct_expect_related_report net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x4afdeb11 svc_addsock vmlinux EXPORT_SYMBOL_GPL ++0xe266f2c3 usb_stor_bulk_transfer_buf vmlinux EXPORT_SYMBOL_GPL ++0x824b05c2 tty_init_termios vmlinux EXPORT_SYMBOL_GPL ++0x20257b88 pci_enable_device_io vmlinux EXPORT_SYMBOL ++0x5d6bdce1 flex_array_alloc vmlinux EXPORT_SYMBOL ++0x61471532 blk_queue_bounce vmlinux EXPORT_SYMBOL ++0x97b13dad __clocksource_register_scale vmlinux EXPORT_SYMBOL_GPL ++0x3145216f pci_dev_present vmlinux EXPORT_SYMBOL ++0x4ff7c43d pci_dev_get vmlinux EXPORT_SYMBOL ++0xe23d3f77 pci_dev_put vmlinux EXPORT_SYMBOL ++0x45d0d7e1 scsi_cmd_blk_ioctl vmlinux EXPORT_SYMBOL ++0x51f53371 crypto_alloc_instance2 vmlinux EXPORT_SYMBOL_GPL ++0x62916e11 read_dev_sector vmlinux EXPORT_SYMBOL ++0x31389d75 usb_ifnum_to_if vmlinux EXPORT_SYMBOL_GPL ++0xd34d1db1 debugfs_create_x16 vmlinux EXPORT_SYMBOL_GPL ++0x14ae9650 journal_create vmlinux EXPORT_SYMBOL ++0x8f6ab23e fsnotify_put_group vmlinux EXPORT_SYMBOL_GPL ++0xd81de62c ring_buffer_record_enable vmlinux EXPORT_SYMBOL_GPL ++0x7400f11e inet6_destroy_sock vmlinux EXPORT_SYMBOL_GPL ++0xc15f809f mb_cache_entry_release vmlinux EXPORT_SYMBOL ++0x5c37f319 _raw_spin_unlock_irqrestore vmlinux EXPORT_SYMBOL ++0x061651be strcat vmlinux EXPORT_SYMBOL ++0xec7e08c7 crypto_register_shash vmlinux EXPORT_SYMBOL_GPL ++0x37c68932 inet6_unregister_protosw vmlinux EXPORT_SYMBOL ++0xa869fd87 nf_register_hooks vmlinux EXPORT_SYMBOL ++0x218ce3f7 pfifo_qdisc_ops vmlinux EXPORT_SYMBOL ++0xf202c5cb radix_tree_insert vmlinux EXPORT_SYMBOL ++0xc59cbc6c vfs_listxattr vmlinux EXPORT_SYMBOL_GPL ++0x1f01c966 find_get_pages_contig vmlinux EXPORT_SYMBOL ++0x388f9128 xfrm_state_walk_done vmlinux EXPORT_SYMBOL ++0xf09c4ca9 qdisc_create_dflt vmlinux EXPORT_SYMBOL ++0x3dbda9ad uart_add_one_port vmlinux EXPORT_SYMBOL ++0xee449310 key_put vmlinux EXPORT_SYMBOL ++0x354798cd bmap vmlinux EXPORT_SYMBOL ++0xe2fae716 kmemdup vmlinux EXPORT_SYMBOL ++0x3f629ad2 __blocking_notifier_call_chain vmlinux EXPORT_SYMBOL_GPL ++0xc6314004 _copy_from_pages vmlinux EXPORT_SYMBOL_GPL ++0xcf901697 __strnlen_user vmlinux EXPORT_SYMBOL ++0x50ff1361 nf_conntrack_alloc net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x1445f5e0 tcp_register_congestion_control vmlinux EXPORT_SYMBOL_GPL ++0xbe130622 tcp_gro_complete vmlinux EXPORT_SYMBOL ++0x4d974b9c register_sysrq_key vmlinux EXPORT_SYMBOL ++0x77747da3 timerqueue_add vmlinux EXPORT_SYMBOL_GPL ++0x481b8361 sync_filesystem vmlinux EXPORT_SYMBOL_GPL ++0x15c3f98b tcp_connect vmlinux EXPORT_SYMBOL ++0xdce0a469 neigh_table_clear vmlinux EXPORT_SYMBOL ++0xb185dff3 of_phy_find_device vmlinux EXPORT_SYMBOL ++0x89f238f8 thermal_zone_bind_cooling_device vmlinux EXPORT_SYMBOL ++0x7c3b0956 do_munmap vmlinux EXPORT_SYMBOL ++0xd05dc2a3 xfrm_aalg_get_byname vmlinux EXPORT_SYMBOL_GPL ++0x2ebf2b40 xfrm_state_flush vmlinux EXPORT_SYMBOL ++0x5fd6befa mmc_align_data_size vmlinux EXPORT_SYMBOL ++0xd2fd47b5 pci_fixup_device vmlinux EXPORT_SYMBOL ++0xd6e34b40 fat_flush_inodes vmlinux EXPORT_SYMBOL_GPL ++0xbdf53fa0 xfrm_find_acq_byseq vmlinux EXPORT_SYMBOL ++0xee328371 xfrm_policy_unregister_afinfo vmlinux EXPORT_SYMBOL ++0x06aee4ce __rtnl_af_register vmlinux EXPORT_SYMBOL_GPL ++0x09c55cec schedule_timeout_interruptible vmlinux EXPORT_SYMBOL ++0x1ace138d bitmap_allocate_region vmlinux EXPORT_SYMBOL ++0x250113b4 memory_read_from_buffer vmlinux EXPORT_SYMBOL ++0xbb5d343d xfrm_get_acqseq vmlinux EXPORT_SYMBOL ++0x33deca5d __scsi_iterate_devices vmlinux EXPORT_SYMBOL ++0xa94aefc1 svc_reserve vmlinux EXPORT_SYMBOL_GPL ++0x6709e159 spi_register_driver vmlinux EXPORT_SYMBOL_GPL ++0xb03b00cd platform_bus vmlinux EXPORT_SYMBOL_GPL ++0xe92bef79 blk_queue_bounce_limit vmlinux EXPORT_SYMBOL ++0x7c543650 netpoll_setup vmlinux EXPORT_SYMBOL ++0xc6ef7368 skb_abort_seq_read vmlinux EXPORT_SYMBOL ++0x2b0ba2b0 scsi_sense_desc_find vmlinux EXPORT_SYMBOL ++0xe197c70b journal_destroy vmlinux EXPORT_SYMBOL ++0xef33727a journal_restart vmlinux EXPORT_SYMBOL ++0x5857b225 ioread16_rep vmlinux EXPORT_SYMBOL ++0x251c3936 inet6_ioctl vmlinux EXPORT_SYMBOL ++0x91fbfe0b tcp_getsockopt vmlinux EXPORT_SYMBOL ++0x1a4fb9e4 tcp_setsockopt vmlinux EXPORT_SYMBOL ++0x6d346876 rtnl_unicast vmlinux EXPORT_SYMBOL ++0x03564dce alloc_disk_node vmlinux EXPORT_SYMBOL ++0x8949858b schedule_work vmlinux EXPORT_SYMBOL ++0x503b8f3e dequeue_signal vmlinux EXPORT_SYMBOL_GPL ++0x91279f07 __rtnl_af_unregister vmlinux EXPORT_SYMBOL_GPL ++0xc8d078df skb_gro_reset_offset vmlinux EXPORT_SYMBOL ++0xb93672bb sysdev_driver_unregister vmlinux EXPORT_SYMBOL_GPL ++0xc553e282 crypto_ablkcipher_type vmlinux EXPORT_SYMBOL_GPL ++0x405b9539 ip6t_register_table net/ipv6/netfilter/ip6_tables EXPORT_SYMBOL ++0x5228f707 crypto_tfm_in_queue vmlinux EXPORT_SYMBOL_GPL ++0x8133f7e5 fget_raw vmlinux EXPORT_SYMBOL ++0x30301151 atomic_notifier_call_chain vmlinux EXPORT_SYMBOL_GPL ++0xcb3c7b08 spi_add_device vmlinux EXPORT_SYMBOL_GPL ++0xfc02b7ad sysctl_tcp_wmem vmlinux EXPORT_SYMBOL ++0xb075d9fd nf_unregister_hook vmlinux EXPORT_SYMBOL ++0x9c723b65 napi_frags_skb vmlinux EXPORT_SYMBOL ++0xe5f91be5 dev_change_net_namespace vmlinux EXPORT_SYMBOL_GPL ++0xd0243795 unregister_mtd_user vmlinux EXPORT_SYMBOL_GPL ++0xc63a5ea9 blk_queue_flush_queueable vmlinux EXPORT_SYMBOL_GPL ++0xa6c79ad9 blk_queue_rq_timeout vmlinux EXPORT_SYMBOL_GPL ++0x04f27610 xdr_init_decode_pages vmlinux EXPORT_SYMBOL_GPL ++0x39a0825d tcp_twsk_destructor vmlinux EXPORT_SYMBOL_GPL ++0xc363ac9f scm_detach_fds vmlinux EXPORT_SYMBOL ++0x1bab249b rtc_ktime_to_tm vmlinux EXPORT_SYMBOL_GPL ++0x7d7fd860 usb_stor_pre_reset vmlinux EXPORT_SYMBOL_GPL ++0x50c8b1e3 put_pid vmlinux EXPORT_SYMBOL_GPL ++0xa77ad493 driver_find_device vmlinux EXPORT_SYMBOL_GPL ++0x58918a30 posix_clock_register vmlinux EXPORT_SYMBOL_GPL ++0xcc4bd58a __par_io_config_pin vmlinux EXPORT_SYMBOL ++0xc35e28f7 llc_sap_list_lock vmlinux EXPORT_SYMBOL ++0xa03ef198 blk_get_request vmlinux EXPORT_SYMBOL ++0x6a3e01d7 pci_read_irq_line vmlinux EXPORT_SYMBOL ++0x6e7474fc xfrm_ealg_get_byid vmlinux EXPORT_SYMBOL_GPL ++0x71dc9998 crypto_il_tab vmlinux EXPORT_SYMBOL_GPL ++0x0cc1e40f crypto_it_tab vmlinux EXPORT_SYMBOL_GPL ++0x3dc916b6 crypto_fl_tab vmlinux EXPORT_SYMBOL_GPL ++0x40d46b21 crypto_ft_tab vmlinux EXPORT_SYMBOL_GPL ++0x4678aa19 down_timeout vmlinux EXPORT_SYMBOL ++0xd2d0e6b4 nfnetlink_has_listeners net/netfilter/nfnetlink EXPORT_SYMBOL_GPL ++0x3bd1b1f6 msecs_to_jiffies vmlinux EXPORT_SYMBOL ++0xce06503d misc_deregister vmlinux EXPORT_SYMBOL ++0xd03a6957 blkdev_fsync vmlinux EXPORT_SYMBOL ++0x5f945856 lookup_one_len vmlinux EXPORT_SYMBOL ++0x7e50cea1 relay_buf_full vmlinux EXPORT_SYMBOL_GPL ++0x6437bd2e inet6_bind vmlinux EXPORT_SYMBOL ++0x3e45e9ff register_inetaddr_notifier vmlinux EXPORT_SYMBOL ++0xa1f0bf08 atomic_dec_and_mutex_lock vmlinux EXPORT_SYMBOL ++0x0de06988 cpu_first_thread_of_core vmlinux EXPORT_SYMBOL_GPL ++0xc5338f4a devres_add vmlinux EXPORT_SYMBOL_GPL ++0xcacda582 devres_get vmlinux EXPORT_SYMBOL_GPL ++0x43e83ea6 journal_wipe vmlinux EXPORT_SYMBOL ++0x8fc5394e pci_set_mwi vmlinux EXPORT_SYMBOL ++0xdce39544 sync_inodes_sb vmlinux EXPORT_SYMBOL ++0x7485e15e unregister_chrdev_region vmlinux EXPORT_SYMBOL ++0x7e25ca93 generic_writepages vmlinux EXPORT_SYMBOL ++0x9d13ddee register_8022_client vmlinux EXPORT_SYMBOL ++0x3847c175 gpiochip_is_requested vmlinux EXPORT_SYMBOL_GPL ++0xf1cf3036 blk_set_default_limits vmlinux EXPORT_SYMBOL ++0x861bbc41 blk_init_allocated_queue vmlinux EXPORT_SYMBOL ++0xe7c5e070 rtnl_register vmlinux EXPORT_SYMBOL_GPL ++0x58f81e73 lookup_bdev vmlinux EXPORT_SYMBOL ++0x0ef20db1 kernstart_addr vmlinux EXPORT_SYMBOL ++0xe484e35f ioread32 vmlinux EXPORT_SYMBOL ++0xdc732024 irq_stat vmlinux EXPORT_SYMBOL ++0x88632b55 raw_seq_stop vmlinux EXPORT_SYMBOL_GPL ++0x1087ecc8 gnet_stats_copy_basic vmlinux EXPORT_SYMBOL ++0xfe35aa4a percpu_counter_destroy vmlinux EXPORT_SYMBOL ++0xa974f717 create_mnt_ns vmlinux EXPORT_SYMBOL ++0xaf8e5276 vm_map_ram vmlinux EXPORT_SYMBOL ++0x7b82dc37 filemap_fdatawrite_range vmlinux EXPORT_SYMBOL ++0xa6cf1ffb inet_sendmsg vmlinux EXPORT_SYMBOL ++0xa60ddb99 ip_cmsg_recv vmlinux EXPORT_SYMBOL ++0xb77bbb6e hidinput_report_event vmlinux EXPORT_SYMBOL_GPL ++0x397ef9ad crypto_alg_sem vmlinux EXPORT_SYMBOL_GPL ++0x3e2af9cd bio_sector_offset vmlinux EXPORT_SYMBOL ++0x2bc61da1 program_check_exception vmlinux EXPORT_SYMBOL ++0xa4beec26 rpc_call_async vmlinux EXPORT_SYMBOL_GPL ++0xed312eb2 pci_unblock_user_cfg_access vmlinux EXPORT_SYMBOL_GPL ++0x79ac1dd3 cpu_sibling_map vmlinux EXPORT_SYMBOL ++0x760b437a unregister_inetaddr_notifier vmlinux EXPORT_SYMBOL ++0x6f707520 unregister_exec_domain vmlinux EXPORT_SYMBOL ++0x262e837a nobh_write_begin vmlinux EXPORT_SYMBOL ++0xd2cd5568 interruptible_sleep_on_timeout vmlinux EXPORT_SYMBOL ++0xbcdd82e7 netlink_ack vmlinux EXPORT_SYMBOL ++0x4b24bd8a sock_no_bind vmlinux EXPORT_SYMBOL ++0x29080e5d sock_get_timestamp vmlinux EXPORT_SYMBOL ++0x4211c3c1 zlib_inflateInit2 vmlinux EXPORT_SYMBOL ++0x8fc7f839 param_set_charp vmlinux EXPORT_SYMBOL ++0xb60b5707 of_i8042_aux_irq vmlinux EXPORT_SYMBOL_GPL ++0x9dbbba05 bio_free vmlinux EXPORT_SYMBOL ++0xef1c781c vid_which_vrm drivers/hwmon/hwmon-vid EXPORT_SYMBOL ++0x6bdcfd99 qdisc_class_hash_remove vmlinux EXPORT_SYMBOL ++0x5e59780b dmam_alloc_noncoherent vmlinux EXPORT_SYMBOL ++0x495b01eb transport_destroy_device vmlinux EXPORT_SYMBOL_GPL ++0x37179733 tty_unregister_device vmlinux EXPORT_SYMBOL ++0xbf8ba54a vprintk vmlinux EXPORT_SYMBOL ++0x2e2ce9e0 sysctl_tcp_syncookies vmlinux EXPORT_SYMBOL ++0xcb40eb53 tcp_poll vmlinux EXPORT_SYMBOL ++0x2482e688 vsprintf vmlinux EXPORT_SYMBOL ++0x3d055d0f generic_splice_sendpage vmlinux EXPORT_SYMBOL ++0xdda593ad attribute_container_find_class_device vmlinux EXPORT_SYMBOL_GPL ++0x0b92397e register_key_type vmlinux EXPORT_SYMBOL ++0xeaea2b74 grab_cache_page_write_begin vmlinux EXPORT_SYMBOL ++0xc2f8a90a rt_mutex_lock_interruptible vmlinux EXPORT_SYMBOL_GPL ++0x598ee3d1 cpu_add_dev_attr_group vmlinux EXPORT_SYMBOL_GPL ++0x10e1bae1 __mtd_next_device vmlinux EXPORT_SYMBOL_GPL ++0xc62f6317 class_create_file vmlinux EXPORT_SYMBOL_GPL ++0x0cae232b utf16s_to_utf8s vmlinux EXPORT_SYMBOL ++0x2f15682e __put_task_struct vmlinux EXPORT_SYMBOL_GPL ++0xcd86c87f __cond_resched_lock vmlinux EXPORT_SYMBOL ++0x1a6a10dd rpc_get_mount vmlinux EXPORT_SYMBOL_GPL ++0x854bdca7 unregister_pernet_subsys vmlinux EXPORT_SYMBOL_GPL ++0x13bbe2f0 wait_on_sync_kiocb vmlinux EXPORT_SYMBOL ++0x7c39cb83 simple_write_begin vmlinux EXPORT_SYMBOL ++0x219087eb bdi_set_max_ratio vmlinux EXPORT_SYMBOL ++0x53bc4229 redirty_page_for_writepage vmlinux EXPORT_SYMBOL ++0x8ffe7e89 nf_conntrack_htable_size net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x44427913 netdev_emerg vmlinux EXPORT_SYMBOL ++0x610b8968 sk_stream_kill_queues vmlinux EXPORT_SYMBOL ++0xe151f34a dev_set_name vmlinux EXPORT_SYMBOL_GPL ++0xeb37101c audit_log_end vmlinux EXPORT_SYMBOL ++0x6d40a921 need_ipv4_conntrack net/ipv4/netfilter/nf_conntrack_ipv4 EXPORT_SYMBOL_GPL ++0xf8bb5353 __sk_dst_check vmlinux EXPORT_SYMBOL ++0x65dbe5b6 usb_queue_reset_device vmlinux EXPORT_SYMBOL_GPL ++0xd7592f72 cfi_varsize_frob vmlinux EXPORT_SYMBOL ++0xbfff4b41 elv_register_queue vmlinux EXPORT_SYMBOL ++0x716265c7 debugfs_initialized vmlinux EXPORT_SYMBOL_GPL ++0x73564277 __timecompare_update vmlinux EXPORT_SYMBOL_GPL ++0x003ed69a __kfifo_dma_in_prepare vmlinux EXPORT_SYMBOL ++0x6db428e3 cpu_core_map vmlinux EXPORT_SYMBOL ++0x9bf6538b usb_interrupt_msg vmlinux EXPORT_SYMBOL_GPL ++0xe30d26f6 bus_unregister vmlinux EXPORT_SYMBOL_GPL ++0x4c759827 byte_rev_table vmlinux EXPORT_SYMBOL_GPL ++0x964d2406 __elv_add_request vmlinux EXPORT_SYMBOL ++0x37305e47 skcipher_geniv_init vmlinux EXPORT_SYMBOL_GPL ++0x5e3c72b7 set_bh_page vmlinux EXPORT_SYMBOL ++0x01a5485d crypto_destroy_tfm vmlinux EXPORT_SYMBOL_GPL ++0x73331311 filemap_fault vmlinux EXPORT_SYMBOL ++0xe914e41e strcpy vmlinux EXPORT_SYMBOL ++0x1bc3edc2 usb_stor_sense_invalidCDB vmlinux EXPORT_SYMBOL_GPL ++0xa1076c97 tty_pair_get_tty vmlinux EXPORT_SYMBOL ++0xa7d098e3 tty_pair_get_pty vmlinux EXPORT_SYMBOL ++0xa0ada1ea key_payload_reserve vmlinux EXPORT_SYMBOL ++0x9da8160b blocking_notifier_chain_register vmlinux EXPORT_SYMBOL_GPL ++0x462da1bf nf_ct_insert_dying_list net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x2e4f42a4 skb_unlink vmlinux EXPORT_SYMBOL ++0x4a9e6b51 crypto_register_template vmlinux EXPORT_SYMBOL_GPL ++0xaab9f7e7 node_states vmlinux EXPORT_SYMBOL ++0x6a5fb566 rcu_sched_force_quiescent_state vmlinux EXPORT_SYMBOL_GPL ++0x6cc37c70 of_property_read_u32_array vmlinux EXPORT_SYMBOL_GPL ++0xbf1cc04b tty_termios_encode_baud_rate vmlinux EXPORT_SYMBOL_GPL ++0x0199224f inet_csk_delete_keepalive_timer vmlinux EXPORT_SYMBOL ++0x47776c55 of_parse_phandle vmlinux EXPORT_SYMBOL ++0x10daa86c usb_hcd_pci_shutdown vmlinux EXPORT_SYMBOL_GPL ++0x6b25bb62 pci_bus_set_ops vmlinux EXPORT_SYMBOL ++0x24518ffa xfrm_state_register_afinfo vmlinux EXPORT_SYMBOL ++0xd2e16256 usb_register_device_driver vmlinux EXPORT_SYMBOL_GPL ++0x8df7d3c5 subsys_interface_unregister vmlinux EXPORT_SYMBOL_GPL ++0x9ed6b52d kmem_cache_size vmlinux EXPORT_SYMBOL ++0x8be716ab inet_ioctl vmlinux EXPORT_SYMBOL ++0x8a1f2ce8 of_device_register vmlinux EXPORT_SYMBOL ++0x0c8c9e99 scsi_show_extd_sense vmlinux EXPORT_SYMBOL ++0x503084b0 __pci_reset_function vmlinux EXPORT_SYMBOL_GPL ++0x5c4260ae kobject_get_path vmlinux EXPORT_SYMBOL_GPL ++0xc55c2a9d inode_sb_list_lock vmlinux EXPORT_SYMBOL_GPL ++0xd8ce7e67 clocksource_register vmlinux EXPORT_SYMBOL ++0x66dc52b5 xt_register_target vmlinux EXPORT_SYMBOL ++0x0a882a67 ping_prot vmlinux EXPORT_SYMBOL ++0x814e7730 nf_ct_destroy vmlinux EXPORT_SYMBOL ++0xbceeac4f nf_unregister_hooks vmlinux EXPORT_SYMBOL ++0x1db99742 device_create_vargs vmlinux EXPORT_SYMBOL_GPL ++0x3668dd26 tty_port_hangup vmlinux EXPORT_SYMBOL ++0x8810ad5e crypto_xor vmlinux EXPORT_SYMBOL_GPL ++0x45bf1ff3 crypto_inc vmlinux EXPORT_SYMBOL_GPL ++0x8f784e32 cpu_bit_bitmap vmlinux EXPORT_SYMBOL_GPL ++0x35448c65 rpc_free_iostats vmlinux EXPORT_SYMBOL_GPL ++0xede6b327 rpc_destroy_wait_queue vmlinux EXPORT_SYMBOL_GPL ++0x6eea229d svcauth_unix_purge vmlinux EXPORT_SYMBOL_GPL ++0xb286adee usb_hcd_poll_rh_status vmlinux EXPORT_SYMBOL_GPL ++0xfa4b3895 device_find_child vmlinux EXPORT_SYMBOL_GPL ++0xe5404b68 fat_getattr vmlinux EXPORT_SYMBOL_GPL ++0xda5c059a fat_setattr vmlinux EXPORT_SYMBOL_GPL ++0x7a43615e generic_read_dir vmlinux EXPORT_SYMBOL ++0x88afffc0 dentry_unhash vmlinux EXPORT_SYMBOL ++0xe007de41 kallsyms_lookup_name vmlinux EXPORT_SYMBOL_GPL ++0xe99d91ed validate_sp vmlinux EXPORT_SYMBOL ++0xf0933596 xprt_lookup_rqst vmlinux EXPORT_SYMBOL_GPL ++0xfade055f do_splice_to vmlinux EXPORT_SYMBOL_GPL ++0xda28eb83 writeback_inodes_sb_if_idle vmlinux EXPORT_SYMBOL ++0xdf86ee64 truncate_pagecache vmlinux EXPORT_SYMBOL ++0x26b71fb4 ring_buffer_time_stamp vmlinux EXPORT_SYMBOL_GPL ++0x5fcdec5d xfrm_ealg_get_byidx vmlinux EXPORT_SYMBOL_GPL ++0xdf7531cb sock_no_shutdown vmlinux EXPORT_SYMBOL ++0x2764e8b7 of_device_unregister vmlinux EXPORT_SYMBOL ++0xf5f63ca5 __generic_block_fiemap vmlinux EXPORT_SYMBOL ++0xb1acbcce rcu_barrier_sched vmlinux EXPORT_SYMBOL_GPL ++0xdc2519e0 param_set_ulong vmlinux EXPORT_SYMBOL ++0xee2d0fc7 _local_bh_enable vmlinux EXPORT_SYMBOL ++0x36b0e732 try_wait_for_completion vmlinux EXPORT_SYMBOL ++0x80dfc988 nf_ct_expect_alloc net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0xc4bf0a92 sysfs_unmerge_group vmlinux EXPORT_SYMBOL_GPL ++0xcbf0b653 cpu_active_mask vmlinux EXPORT_SYMBOL ++0x4498d5aa bus_find_device_by_name vmlinux EXPORT_SYMBOL_GPL ++0x29b96a8a inet_peer_xrlim_allow vmlinux EXPORT_SYMBOL ++0x2a23b66d nf_ct_attach vmlinux EXPORT_SYMBOL ++0xe5ed5467 xfrm_policy_walk_init vmlinux EXPORT_SYMBOL ++0xb0f3f389 driver_attach vmlinux EXPORT_SYMBOL_GPL ++0x0dbd5a25 textsearch_register vmlinux EXPORT_SYMBOL ++0x74baf17a tracing_is_on vmlinux EXPORT_SYMBOL_GPL ++0x381a798a setup_max_cpus vmlinux EXPORT_SYMBOL ++0x5bfbe895 commit_creds vmlinux EXPORT_SYMBOL ++0xd772ed24 __nf_ct_expect_find net/netfilter/nf_conntrack EXPORT_SYMBOL_GPL ++0x5db93a7c platform_device_register vmlinux EXPORT_SYMBOL_GPL ++0x5934392b fb_register_client vmlinux EXPORT_SYMBOL ++0xad0413d4 match_hex vmlinux EXPORT_SYMBOL ++0x0ffce14a __inet_lookup_listener vmlinux EXPORT_SYMBOL_GPL ++0x79eb7536 nf_unregister_sockopt vmlinux EXPORT_SYMBOL ++0x63f2715f __skb_get_rxhash vmlinux EXPORT_SYMBOL ++0x6029f865 skb_realloc_headroom vmlinux EXPORT_SYMBOL ++0x183abba7 platform_device_unregister vmlinux EXPORT_SYMBOL_GPL ++0x4373b84f serial8250_set_isa_configurator vmlinux EXPORT_SYMBOL ++0x9e38fbad generic_pipe_buf_map vmlinux EXPORT_SYMBOL ++0xba1338f3 generic_pipe_buf_get vmlinux EXPORT_SYMBOL ++0xb4b61245 ipv6_find_hdr net/ipv6/netfilter/ip6_tables EXPORT_SYMBOL ++0x2a14e5c1 uhci_reset_hc vmlinux EXPORT_SYMBOL_GPL ++0xfd1f0623 tty_port_close_end vmlinux EXPORT_SYMBOL ++0x77df0847 __set_personality vmlinux EXPORT_SYMBOL ++0x0e3bcc66 blkcipher_walk_done vmlinux EXPORT_SYMBOL_GPL ++0x731705d7 page_readlink vmlinux EXPORT_SYMBOL ++0xaa181411 account_page_writeback vmlinux EXPORT_SYMBOL ++0x6976522d nf_unregister_afinfo vmlinux EXPORT_SYMBOL_GPL ++0xf5eb86ea blk_verify_command vmlinux EXPORT_SYMBOL ++0xc499ae1e kstrdup vmlinux EXPORT_SYMBOL ++0x0e8f30f6 _raw_write_lock_irq vmlinux EXPORT_SYMBOL ++0x89da4432 of_iomap vmlinux EXPORT_SYMBOL ++0x81a07f4e _atomic_dec_and_lock vmlinux EXPORT_SYMBOL ++0xea7987f1 key_update vmlinux EXPORT_SYMBOL ++0xe18ba8e7 xfrm_register_km vmlinux EXPORT_SYMBOL ++0x31a77643 ip_mc_dec_group vmlinux EXPORT_SYMBOL ++0x733c3b54 kasprintf vmlinux EXPORT_SYMBOL ++0x2a24f9c2 simple_rename vmlinux EXPORT_SYMBOL ++0xb2729dbd vfs_setxattr vmlinux EXPORT_SYMBOL_GPL ++0x7d012ee7 vfs_getxattr vmlinux EXPORT_SYMBOL_GPL ++0xa3dd3ddd sock_init_data vmlinux EXPORT_SYMBOL ++0xb2d2b9ab tty_set_termios vmlinux EXPORT_SYMBOL_GPL ++0xe02eb6d0 ring_buffer_commit_overrun_cpu vmlinux EXPORT_SYMBOL_GPL ++0x3a536bd7 ring_buffer_read_finish vmlinux EXPORT_SYMBOL_GPL ++0xde48e9ca _raw_spin_lock vmlinux EXPORT_SYMBOL ++0xba707a78 qe_get_brg_clk vmlinux EXPORT_SYMBOL ++0xc37dddf0 ip_queue_xmit vmlinux EXPORT_SYMBOL ++0x715949d4 class_dev_iter_init vmlinux EXPORT_SYMBOL_GPL ++0x2b2f7e10 pci_get_slot vmlinux EXPORT_SYMBOL ++0x2eb91dfe scatterwalk_map vmlinux EXPORT_SYMBOL_GPL ++0x69a0ca7d iowrite16be vmlinux EXPORT_SYMBOL ++0x6acb973d iowrite32be vmlinux EXPORT_SYMBOL ++0xf4a2585b km_query vmlinux EXPORT_SYMBOL ++0xf9ea6336 inet_release vmlinux EXPORT_SYMBOL ++0x85da4665 blk_queue_start_tag vmlinux EXPORT_SYMBOL ++0x5549ab6e xprt_alloc vmlinux EXPORT_SYMBOL_GPL ++0xe9492d51 neigh_create vmlinux EXPORT_SYMBOL ++0xd3af87a4 usb_stor_CB_transport vmlinux EXPORT_SYMBOL_GPL ++0x9fce80db fb_notifier_call_chain vmlinux EXPORT_SYMBOL_GPL ++0x373db350 kstrtoint vmlinux EXPORT_SYMBOL ++0xdd4a0569 log_start_commit vmlinux EXPORT_SYMBOL ++0x8f6cee77 __round_jiffies_relative vmlinux EXPORT_SYMBOL_GPL ++0x002c769b svc_pool_stats_open vmlinux EXPORT_SYMBOL ++0x536fa1b6 inet_twsk_alloc vmlinux EXPORT_SYMBOL_GPL ++0x978bfc35 tty_put_char vmlinux EXPORT_SYMBOL_GPL ++0x037a0cba kfree vmlinux EXPORT_SYMBOL ++0x5868f579 __rt_mutex_init vmlinux EXPORT_SYMBOL_GPL ++0x6e545da1 kill_pid_info_as_cred vmlinux EXPORT_SYMBOL_GPL ++0x17b07df4 vlan_dev_real_dev vmlinux EXPORT_SYMBOL ++0x3562e58c xfrm_state_delete vmlinux EXPORT_SYMBOL ++0xe492a8e1 nf_register_sockopt vmlinux EXPORT_SYMBOL ++0xbc979fa3 sock_kmalloc vmlinux EXPORT_SYMBOL ++0xb894926d schedule_work_on vmlinux EXPORT_SYMBOL ++0xb2c6eb9f pci_lost_interrupt vmlinux EXPORT_SYMBOL ++0xe7d4daac seq_list_next vmlinux EXPORT_SYMBOL ++0x538383c0 unregister_inet6addr_notifier vmlinux EXPORT_SYMBOL ++0x0d3cc82c of_irq_map_one vmlinux EXPORT_SYMBOL_GPL ++0xa06df9e1 __kfifo_dma_out_finish_r vmlinux EXPORT_SYMBOL ++0xeb7e4ace ipv6_chk_addr vmlinux EXPORT_SYMBOL ++0xdf967a1b uart_suspend_port vmlinux EXPORT_SYMBOL ++0xfb8ca5ae __blkdev_driver_ioctl vmlinux EXPORT_SYMBOL_GPL ++0x1f020c91 blk_alloc_queue_node vmlinux EXPORT_SYMBOL ++0xa3fb4a58 scsi_device_resume vmlinux EXPORT_SYMBOL ++0xafd68c33 flex_array_free vmlinux EXPORT_SYMBOL ++0xc3fb5b3d blk_queue_flush vmlinux EXPORT_SYMBOL_GPL ++0x98b9afaa bio_phys_segments vmlinux EXPORT_SYMBOL ++0xdaa57ec3 totalhigh_pages vmlinux EXPORT_SYMBOL ++0x540c4404 ipv6_find_tlv vmlinux EXPORT_SYMBOL_GPL ++0xfb3ac86b neigh_changeaddr vmlinux EXPORT_SYMBOL ++0xd59bf139 skb_recycle_check vmlinux EXPORT_SYMBOL ++0xa120d33c tty_unregister_ldisc vmlinux EXPORT_SYMBOL ++0x7dc5d0b6 crypto_unregister_notifier vmlinux EXPORT_SYMBOL_GPL ++0x9c09632d invalidate_inode_pages2 vmlinux EXPORT_SYMBOL_GPL ++0x317ce92f ipt_do_table net/ipv4/netfilter/ip_tables EXPORT_SYMBOL ++0xd726d95c scsi_calculate_bounce_limit vmlinux EXPORT_SYMBOL ++0x798959ae kmem_cache_destroy vmlinux EXPORT_SYMBOL ++0x3778ec77 add_to_page_cache_locked vmlinux EXPORT_SYMBOL ++0x4e109192 ring_buffer_entries vmlinux EXPORT_SYMBOL_GPL ++0x6d054375 xfrm_prepare_input vmlinux EXPORT_SYMBOL ++0x4333cc58 xt_find_target vmlinux EXPORT_SYMBOL ++0xb1faff50 usb_serial_disconnect vmlinux EXPORT_SYMBOL_GPL ++0xa1ba2fdb vfsmount_lock_global_lock vmlinux EXPORT_SYMBOL ++0x16947341 rpc_proc_register vmlinux EXPORT_SYMBOL_GPL ++0x6c7c7b9a rpc_queue_empty vmlinux EXPORT_SYMBOL_GPL ++0x6c394758 phy_mii_ioctl vmlinux EXPORT_SYMBOL ++0x905bba18 vm_event_states vmlinux EXPORT_SYMBOL ++0x9bce482f __release_region vmlinux EXPORT_SYMBOL ++0x43a01f90 complete_all vmlinux EXPORT_SYMBOL ++0xf020d96e tty_free_termios vmlinux EXPORT_SYMBOL ++0x347013de nla_validate vmlinux EXPORT_SYMBOL ++0x27adac45 bdi_register vmlinux EXPORT_SYMBOL ++0xc5322a9c xprt_alloc_slot vmlinux EXPORT_SYMBOL_GPL ++0x9eb0209a inet_csk_clear_xmit_timers vmlinux EXPORT_SYMBOL ++0x7129e5f8 hex_asc vmlinux EXPORT_SYMBOL ++0x7dc2f75e fat_time_unix2fat vmlinux EXPORT_SYMBOL_GPL ++0x09dfe73d nf_nat_follow_master net/ipv4/netfilter/nf_nat EXPORT_SYMBOL ++0x8ef99ed3 tty_get_pgrp vmlinux EXPORT_SYMBOL_GPL ++0x2aa0e4fc strncasecmp vmlinux EXPORT_SYMBOL ++0x53301e75 default_llseek vmlinux EXPORT_SYMBOL ++0x5e0120a8 ring_buffer_oldest_event_ts vmlinux EXPORT_SYMBOL_GPL ++0xcb3334bb tcp_read_sock vmlinux EXPORT_SYMBOL ++0xfa741e99 sdhci_pltfm_free vmlinux EXPORT_SYMBOL_GPL ++0x28535cb6 rpc_peeraddr vmlinux EXPORT_SYMBOL_GPL ++0x57958d5a ip_fragment vmlinux EXPORT_SYMBOL ++0x9aa9a810 scsi_eh_prep_cmnd vmlinux EXPORT_SYMBOL ++0x4997d11c pci_set_cacheline_size vmlinux EXPORT_SYMBOL_GPL ++0x815b5dd4 match_octal vmlinux EXPORT_SYMBOL ++0x99baa259 bio_map_kern vmlinux EXPORT_SYMBOL ++0x43969dbe rh_alloc_fixed vmlinux EXPORT_SYMBOL_GPL ++0x531c3179 xt_register_targets vmlinux EXPORT_SYMBOL ++0xf88eee18 i2c_smbus_write_byte vmlinux EXPORT_SYMBOL ++0xf77ff57d scsi_register_driver vmlinux EXPORT_SYMBOL ++0x82e96562 vfs_fsync vmlinux EXPORT_SYMBOL ++0x86acb6ae poll_freewait vmlinux EXPORT_SYMBOL ++0xb3a307c6 si_meminfo vmlinux EXPORT_SYMBOL ++0x7835cfc7 kthread_create_on_node vmlinux EXPORT_SYMBOL ++0x5e95b1cd current_umask vmlinux EXPORT_SYMBOL ++0xbd40cacd get_fs_type vmlinux EXPORT_SYMBOL ++0x377a3400 ref_module vmlinux EXPORT_SYMBOL_GPL ++0xb44478a6 qe_pin_free vmlinux EXPORT_SYMBOL ++0x8f56dfc6 nf_nat_pptp_hook_outbound net/netfilter/nf_conntrack_pptp EXPORT_SYMBOL_GPL ++0x36e46f38 tty_driver_kref_put vmlinux EXPORT_SYMBOL ++0x8e26fda2 sock_prot_inuse_get vmlinux EXPORT_SYMBOL_GPL ++0x932e22fc scsi_host_set_state vmlinux EXPORT_SYMBOL ++0x70b879e3 aead_geniv_init vmlinux EXPORT_SYMBOL_GPL ++0xf9d89d7c generic_write_end vmlinux EXPORT_SYMBOL ++0x362e23ec call_rcu_bh vmlinux EXPORT_SYMBOL_GPL ++0xbf9be642 devm_request_threaded_irq vmlinux EXPORT_SYMBOL ++0x67955ce6 profile_hits vmlinux EXPORT_SYMBOL_GPL ++0xcf764d46 __vlan_find_dev_deep vmlinux EXPORT_SYMBOL ++0x7d62fe80 of_mm_gpiochip_add vmlinux EXPORT_SYMBOL ++0x1c30dd9c genphy_config_aneg vmlinux EXPORT_SYMBOL ++0x95ad803f blk_start_queue vmlinux EXPORT_SYMBOL ++0x9c9c6a5a journal_check_used_features vmlinux EXPORT_SYMBOL ++0xe0dd2be0 bio_copy_user vmlinux EXPORT_SYMBOL ++0x7a4497db kzfree vmlinux EXPORT_SYMBOL ++0xc197d453 arpt_unregister_table net/ipv4/netfilter/arp_tables EXPORT_SYMBOL ++0x2bbf27ee sk_filter vmlinux EXPORT_SYMBOL ++0xa8f59416 gpio_direction_output vmlinux EXPORT_SYMBOL_GPL ++0x92e682eb generic_removexattr vmlinux EXPORT_SYMBOL ++0x83b88ae3 deactivate_super vmlinux EXPORT_SYMBOL ++0xa924a7ed vmap vmlinux EXPORT_SYMBOL ++0x31f0bb78 __kmap_atomic_idx vmlinux EXPORT_SYMBOL +diff --git a/debian/bin/abiupdate.py b/debian/bin/abiupdate.py +new file mode 100755 +index 0000000..69a2a23 +--- /dev/null ++++ b/debian/bin/abiupdate.py +@@ -0,0 +1,211 @@ ++#!/usr/bin/env python ++ ++import sys ++sys.path.append(sys.path[0] + "/../lib/python") ++ ++import optparse ++import os ++import shutil ++import tempfile ++import urllib2 ++ ++from debian_linux.abi import Symbols ++from debian_linux.config import * ++from debian_linux.debian import * ++ ++default_url_base = "http://ftp.de.debian.org/debian/" ++default_url_base_incoming = "http://incoming.debian.org/" ++default_url_base_ports = "http://ftp.debian-ports.org/debian/" ++ ++ ++class url_debian_flat(object): ++ def __init__(self, base): ++ self.base = base ++ ++ def __call__(self, source, filename, arch): ++ return self.base + filename ++ ++ ++class url_debian_pool(object): ++ def __init__(self, base): ++ self.base = base ++ ++ def __call__(self, source, filename, arch): ++ return self.base + "pool/main/" + source[0] + "/" + source + "/" + filename ++ ++ ++class url_debian_ports_pool(url_debian_pool): ++ def __call__(self, source, filename, arch): ++ if arch == 'all': ++ return url_debian_pool.__call__(self, source, filename, arch) ++ return self.base + "pool-" + arch + "/main/" + source[0] + "/" + source + "/" + filename ++ ++ ++class Main(object): ++ dir = None ++ ++ def __init__(self, url, url_config=None, arch=None, featureset=None, flavour=None): ++ self.log = sys.stdout.write ++ ++ self.url = self.url_config = url ++ if url_config is not None: ++ self.url_config = url_config ++ self.override_arch = arch ++ self.override_featureset = featureset ++ self.override_flavour = flavour ++ ++ changelog = Changelog(version=VersionLinux) ++ while changelog[0].distribution == 'UNRELEASED': ++ changelog.pop(0) ++ changelog = changelog[0] ++ ++ self.source = changelog.source ++ self.version = changelog.version.linux_version ++ self.version_source = changelog.version.complete ++ ++ local_config = ConfigCoreDump(fp=file("debian/config.defines.dump")) ++ ++ self.version_abi = local_config['version', ]['abiname'] ++ ++ def __call__(self): ++ self.dir = tempfile.mkdtemp(prefix='abiupdate') ++ try: ++ self.log("Retrieve config\n") ++ ++ try: ++ config = self.get_config() ++ except urllib2.HTTPError as e: ++ self.log("Failed to retrieve %s: %s\n" % (e.filename, e)) ++ sys.exit(1) ++ ++ if self.override_arch: ++ arches = [self.override_arch] ++ else: ++ arches = config[('base',)]['arches'] ++ for arch in arches: ++ self.update_arch(config, arch) ++ finally: ++ shutil.rmtree(self.dir) ++ ++ def extract_package(self, filename, base): ++ base_out = self.dir + "/" + base ++ os.mkdir(base_out) ++ os.system("dpkg-deb --extract %s %s" % (filename, base_out)) ++ return base_out ++ ++ def get_abi(self, arch, prefix): ++ filename = "linux-headers-%s-%s_%s_%s.deb" % (self.version_abi, prefix, self.version_source, arch) ++ f = self.retrieve_package(self.url, filename, arch) ++ d = self.extract_package(f, "linux-headers-%s_%s" % (prefix, arch)) ++ f1 = d + "/usr/src/linux-headers-%s-%s/Module.symvers" % (self.version_abi, prefix) ++ s = Symbols(open(f1)) ++ shutil.rmtree(d) ++ return s ++ ++ def get_config(self): ++ filename = "linux-support-%s_%s_all.deb" % (self.version_abi, self.version_source) ++ f = self.retrieve_package(self.url_config, filename, 'all') ++ d = self.extract_package(f, "linux-support") ++ c = d + "/usr/src/linux-support-" + self.version_abi + "/config.defines.dump" ++ config = ConfigCoreDump(fp=file(c)) ++ shutil.rmtree(d) ++ return config ++ ++ def retrieve_package(self, url, filename, arch): ++ u = url(self.source, filename, arch) ++ filename_out = self.dir + "/" + filename ++ ++ f_in = urllib2.urlopen(u) ++ f_out = file(filename_out, 'w') ++ while 1: ++ r = f_in.read() ++ if not r: ++ break ++ f_out.write(r) ++ return filename_out ++ ++ def save_abi(self, symbols, arch, featureset, flavour): ++ dir = "debian/abi/%s" % self.version_abi ++ if not os.path.exists(dir): ++ os.makedirs(dir) ++ out = "%s/%s_%s_%s" % (dir, arch, featureset, flavour) ++ symbols.write(open(out, 'w')) ++ ++ def update_arch(self, config, arch): ++ if self.override_featureset: ++ featuresets = [self.override_featureset] ++ else: ++ featuresets = config[('base', arch)]['featuresets'] ++ for featureset in featuresets: ++ self.update_featureset(config, arch, featureset) ++ ++ def update_featureset(self, config, arch, featureset): ++ config_base = config.merge('base', arch, featureset) ++ ++ if not config_base.get('enabled', True): ++ return ++ ++ if self.override_flavour: ++ flavours = [self.override_flavour] ++ else: ++ flavours = config_base['flavours'] ++ for flavour in flavours: ++ self.update_flavour(config, arch, featureset, flavour) ++ ++ def update_flavour(self, config, arch, featureset, flavour): ++ config_base = config.merge('base', arch, featureset, flavour) ++ ++ if not config_base.get('modules', True): ++ return ++ ++ self.log("Updating ABI for arch %s, featureset %s, flavour %s: " % (arch, featureset, flavour)) ++ try: ++ if featureset == 'none': ++ localversion = flavour ++ else: ++ localversion = featureset + '-' + flavour ++ ++ abi = self.get_abi(arch, localversion) ++ self.save_abi(abi, arch, featureset, flavour) ++ self.log("Ok.\n") ++ except urllib2.HTTPError, e: ++ self.log("Failed to retrieve %s: %s\n" % (e.filename, e)) ++ except StandardError, e: ++ self.log("FAILED!\n") ++ import traceback ++ traceback.print_exc(None, sys.stdout) ++ ++if __name__ == '__main__': ++ options = optparse.OptionParser() ++ options.add_option("-i", "--incoming", action="store_true", dest="incoming") ++ options.add_option("--incoming-config", action="store_true", dest="incoming_config") ++ options.add_option("--ports", action="store_true", dest="ports") ++ options.add_option("-u", "--url-base", dest="url_base", default=default_url_base) ++ options.add_option("--url-base-incoming", dest="url_base_incoming", default=default_url_base_incoming) ++ options.add_option("--url-base-ports", dest="url_base_ports", default=default_url_base_ports) ++ ++ opts, args = options.parse_args() ++ ++ kw = {} ++ if len(args) >= 1: ++ kw['arch'] = args[0] ++ if len(args) >= 2: ++ kw['featureset'] = args[1] ++ if len(args) >= 3: ++ kw['flavour'] = args[2] ++ ++ url_base = url_debian_pool(opts.url_base) ++ url_base_incoming = url_debian_flat(opts.url_base_incoming) ++ url_base_ports = url_debian_ports_pool(opts.url_base_ports) ++ if opts.incoming_config: ++ url = url_config = url_base_incoming ++ else: ++ url_config = url_base ++ if opts.incoming: ++ url = url_base_incoming ++ elif opts.ports: ++ url = url_base_ports ++ else: ++ url = url_base ++ ++ Main(url, url_config, **kw)() +diff --git a/debian/bin/buildcheck.py b/debian/bin/buildcheck.py +new file mode 100755 +index 0000000..a045026 +--- /dev/null ++++ b/debian/bin/buildcheck.py +@@ -0,0 +1,223 @@ ++#!/usr/bin/python ++ ++import sys ++sys.path.append('debian/lib/python') ++ ++import fnmatch ++import stat ++ ++from debian_linux.abi import Symbols ++from debian_linux.config import ConfigCoreDump ++from debian_linux.debian import * ++ ++ ++class CheckAbi(object): ++ class SymbolInfo(object): ++ def __init__(self, symbol, symbol_ref=None): ++ self.symbol = symbol ++ self.symbol_ref = symbol_ref or symbol ++ ++ @property ++ def module(self): ++ return self.symbol.module ++ ++ @property ++ def name(self): ++ return self.symbol.name ++ ++ def write(self, out, ignored): ++ info = [] ++ if ignored: ++ info.append("ignored") ++ for name in ('module', 'version', 'export'): ++ data = getattr(self.symbol, name) ++ data_ref = getattr(self.symbol_ref, name) ++ if data != data_ref: ++ info.append("%s: %s -> %s" % (name, data_ref, data)) ++ else: ++ info.append("%s: %s" % (name, data)) ++ out.write("%-48s %s\n" % (self.symbol.name, ", ".join(info))) ++ ++ def __init__(self, config, dir, arch, featureset, flavour): ++ self.config = config ++ self.arch, self.featureset, self.flavour = arch, featureset, flavour ++ ++ self.filename_new = "%s/Module.symvers" % dir ++ ++ version_abi = self.config['version', ]['abiname'] ++ self.filename_ref = "debian/abi/%s/%s_%s_%s" % (version_abi, arch, featureset, flavour) ++ ++ def __call__(self, out): ++ ret = 0 ++ ++ new = Symbols(open(self.filename_new)) ++ try: ++ ref = Symbols(open(self.filename_ref)) ++ except IOError: ++ out.write("Can't read ABI reference. ABI not checked! Continuing.\n") ++ return 0 ++ ++ symbols, add, change, remove = self._cmp(ref, new) ++ ++ ignore = self._ignore(symbols) ++ ++ add_effective = add - ignore ++ change_effective = change - ignore ++ remove_effective = remove - ignore ++ ++ if change_effective or remove_effective: ++ out.write("ABI has changed! Refusing to continue.\n") ++ ret = 1 ++ elif change or remove: ++ out.write("ABI has changed but all changes have been ignored. Continuing.\n") ++ elif add_effective: ++ out.write("New symbols have been added. Continuing.\n") ++ elif add: ++ out.write("New symbols have been added but have been ignored. Continuing.\n") ++ else: ++ out.write("No ABI changes.\n") ++ ++ if add: ++ out.write("\nAdded symbols:\n") ++ for name in sorted(add): ++ symbols[name].write(out, name in ignore) ++ ++ if change: ++ out.write("\nChanged symbols:\n") ++ for name in sorted(change): ++ symbols[name].write(out, name in ignore) ++ ++ if remove: ++ out.write("\nRemoved symbols:\n") ++ for name in sorted(remove): ++ symbols[name].write(out, name in ignore) ++ ++ return ret ++ ++ def _cmp(self, ref, new): ++ ref_names = set(ref.keys()) ++ new_names = set(new.keys()) ++ ++ add = set() ++ change = set() ++ remove = set() ++ ++ symbols = {} ++ ++ for name in new_names - ref_names: ++ add.add(name) ++ symbols[name] = self.SymbolInfo(new[name]) ++ ++ for name in ref_names.intersection(new_names): ++ s_ref = ref[name] ++ s_new = new[name] ++ ++ if s_ref != s_new: ++ change.add(name) ++ symbols[name] = self.SymbolInfo(s_new, s_ref) ++ ++ for name in ref_names - new_names: ++ remove.add(name) ++ symbols[name] = self.SymbolInfo(ref[name]) ++ ++ return symbols, add, change, remove ++ ++ def _ignore_pattern(self, pattern): ++ ret = [] ++ for i in re.split(r'(\*\*?)', pattern): ++ if i == '*': ++ ret.append(r'[^!]+') ++ elif i == '**': ++ ret.append(r'.+') ++ elif i: ++ ret.append(re.escape(i)) ++ return re.compile('^' + ''.join(ret) + '$') ++ ++ def _ignore(self, symbols): ++ # TODO: let config merge this lists ++ configs = [] ++ configs.append(self.config.get(('abi', self.arch, self.featureset, self.flavour), {})) ++ configs.append(self.config.get(('abi', self.arch, None, self.flavour), {})) ++ configs.append(self.config.get(('abi', self.arch, self.featureset), {})) ++ configs.append(self.config.get(('abi', self.arch), {})) ++ configs.append(self.config.get(('abi', None, self.featureset), {})) ++ configs.append(self.config.get(('abi',), {})) ++ ++ ignores = set() ++ for config in configs: ++ ignores.update(config.get('ignore-changes', [])) ++ ++ filtered = set() ++ for ignore in ignores: ++ type = 'name' ++ if ':' in ignore: ++ type, ignore = ignore.split(':') ++ if type in ('name', 'module'): ++ p = self._ignore_pattern(ignore) ++ for symbol in symbols.itervalues(): ++ if p.match(getattr(symbol, type)): ++ filtered.add(symbol.name) ++ else: ++ raise NotImplementedError ++ ++ return filtered ++ ++ ++class CheckImage(object): ++ def __init__(self, config, dir, arch, featureset, flavour): ++ self.dir = dir ++ self.arch, self.featureset, self.flavour = arch, featureset, flavour ++ ++ self.config_entry_build = config.merge('build', arch, featureset, flavour) ++ self.config_entry_image = config.merge('image', arch, featureset, flavour) ++ ++ def __call__(self, out): ++ image = self.config_entry_build.get('image-file') ++ ++ if not image: ++ # TODO: Bail out ++ return 0 ++ ++ image = os.path.join(self.dir, image) ++ ++ fail = 0 ++ ++ fail |= self.check_size(out, image) ++ ++ return fail ++ ++ def check_size(self, out, image): ++ value = self.config_entry_image.get('check-size') ++ ++ if not value: ++ return 0 ++ ++ value = int(value) ++ ++ size = os.stat(image)[stat.ST_SIZE] ++ ++ if size > value: ++ out.write('Image too large (%d > %d)! Refusing to continue.\n' % (size, value)) ++ return 1 ++ ++ out.write('Image fits (%d <= %d). Continuing.\n' % (size, value)) ++ return 0 ++ ++ ++class Main(object): ++ def __init__(self, dir, arch, featureset, flavour): ++ self.args = dir, arch, featureset, flavour ++ ++ self.config = ConfigCoreDump(fp=file("debian/config.defines.dump")) ++ ++ def __call__(self): ++ fail = 0 ++ ++ for c in CheckAbi, CheckImage: ++ fail |= c(self.config, *self.args)(sys.stdout) ++ ++ return fail ++ ++ ++if __name__ == '__main__': ++ sys.exit(Main(*sys.argv[1:])()) +diff --git a/debian/bin/check-patches.sh b/debian/bin/check-patches.sh +new file mode 100755 +index 0000000..2f18ea3 +--- /dev/null ++++ b/debian/bin/check-patches.sh +@@ -0,0 +1,13 @@ ++#!/bin/sh -e ++ ++TMPDIR=$(mktemp -d) ++trap "rm -rf $TMPDIR" EXIT ++sed '/^#/d; /^[[:space:]]*$/d; s/^[+X] //; s,^,debian/patches/,' debian/patches/series* | sort -u > $TMPDIR/used ++find debian/patches ! -path '*/series*' -type f -name "*.diff" -o -name "*.patch" -printf "%p\n" | sort > $TMPDIR/avail ++echo "Used patches" ++echo "==============" ++cat $TMPDIR/used ++echo ++echo "Unused patches" ++echo "==============" ++fgrep -v -f $TMPDIR/used $TMPDIR/avail +diff --git a/debian/bin/gencontrol.py b/debian/bin/gencontrol.py +new file mode 100755 +index 0000000..d8a2d6c +--- /dev/null ++++ b/debian/bin/gencontrol.py +@@ -0,0 +1,431 @@ ++#!/usr/bin/env python ++ ++import sys ++sys.path.append("debian/lib/python") ++ ++import os ++import os.path ++import subprocess ++ ++from debian_linux import config ++from debian_linux.debian import * ++from debian_linux.gencontrol import Gencontrol as Base ++from debian_linux.utils import Templates, read_control ++ ++ ++class Gencontrol(Base): ++ config_schema = { ++ 'abi': { ++ 'ignore-changes': config.SchemaItemList(), ++ }, ++ 'build': { ++ 'debug-info': config.SchemaItemBoolean(), ++ 'modules': config.SchemaItemBoolean(), ++ }, ++ 'description': { ++ 'parts': config.SchemaItemList(), ++ }, ++ 'image': { ++ 'bootloaders': config.SchemaItemList(), ++ 'configs': config.SchemaItemList(), ++ 'initramfs': config.SchemaItemBoolean(), ++ 'initramfs-generators': config.SchemaItemList(), ++ }, ++ 'relations': { ++ }, ++ 'xen': { ++ 'dom0-support': config.SchemaItemBoolean(), ++ 'flavours': config.SchemaItemList(), ++ 'versions': config.SchemaItemList(), ++ } ++ } ++ ++ def __init__(self, config_dirs=["debian/config"], template_dirs=["debian/templates"]): ++ super(Gencontrol, self).__init__(config.ConfigCoreHierarchy(self.config_schema, config_dirs), Templates(template_dirs), VersionLinux) ++ self.process_changelog() ++ self.config_dirs = config_dirs ++ ++ def _setup_makeflags(self, names, makeflags, data): ++ for src, dst, optional in names: ++ if src in data or not optional: ++ makeflags[dst] = data[src] ++ ++ def do_main_setup(self, vars, makeflags, extra): ++ super(Gencontrol, self).do_main_setup(vars, makeflags, extra) ++ makeflags.update({ ++ 'VERSION': self.version.linux_version, ++ 'UPSTREAMVERSION': self.version.linux_upstream, ++ 'ABINAME': self.abiname, ++ 'ABINAME_PART': self.abiname_part, ++ 'SOURCEVERSION': self.version.complete, ++ }) ++ ++ def do_main_makefile(self, makefile, makeflags, extra): ++ for featureset in iter(self.config['base', ]['featuresets']): ++ makeflags_featureset = makeflags.copy() ++ makeflags_featureset['FEATURESET'] = featureset ++ cmds_source = ["$(MAKE) -f debian/rules.real source-featureset %s" ++ % makeflags_featureset] ++ makefile.add('source_%s_real' % featureset, cmds=cmds_source) ++ makefile.add('source_%s' % featureset, ++ ['source_%s_real' % featureset]) ++ makefile.add('source', ['source_%s' % featureset]) ++ ++ makeflags = makeflags.copy() ++ makeflags['ALL_FEATURESETS'] = ' '.join(self.config['base', ]['featuresets']) ++ super(Gencontrol, self).do_main_makefile(makefile, makeflags, extra) ++ ++ def do_main_packages(self, packages, vars, makeflags, extra): ++ packages.extend(self.process_packages(self.templates["control.main"], self.vars)) ++ ++ arch_makeflags = ( ++ ('kernel-arch', 'KERNEL_ARCH', False), ++ ) ++ ++ def do_arch_setup(self, vars, makeflags, arch, extra): ++ config_base = self.config.merge('base', arch) ++ self._setup_makeflags(self.arch_makeflags, makeflags, config_base) ++ ++ def do_arch_packages(self, packages, makefile, arch, vars, makeflags, extra): ++ if self.version.linux_modifier is None: ++ try: ++ vars['abiname'] = '-%s' % self.config['abi', arch]['abiname'] ++ except KeyError: ++ vars['abiname'] = self.abiname ++ makeflags['ABINAME'] = vars['abiname'] ++ ++ headers_arch = self.templates["control.headers.arch"] ++ packages_headers_arch = self.process_packages(headers_arch, vars) ++ ++ libc_dev = self.templates["control.libc-dev"] ++ packages_headers_arch[0:0] = self.process_packages(libc_dev, {}) ++ ++ packages_headers_arch[-1]['Depends'].extend(PackageRelation()) ++ extra['headers_arch_depends'] = packages_headers_arch[-1]['Depends'] ++ ++ self.merge_packages(packages, packages_headers_arch, arch) ++ ++ cmds_binary_arch = ["$(MAKE) -f debian/rules.real binary-arch-arch %s" % makeflags] ++ makefile.add('binary-arch_%s_real' % arch, cmds=cmds_binary_arch) ++ ++ # Shortcut to aid architecture bootstrapping ++ makefile.add('binary-libc-dev_%s' % arch, ++ ['source_none_real'], ++ ["$(MAKE) -f debian/rules.real install-libc-dev_%s %s" % ++ (arch, makeflags)]) ++ ++ if self.changelog[0].distribution == 'UNRELEASED' or os.getenv('DEBIAN_KERNEL_DISABLE_INSTALLER'): ++ import warnings ++ warnings.warn(u'Disable building of debug infos on request (DEBIAN_KERNEL_DISABLE_INSTALLER set)') ++ else: ++ # Add udebs using kernel-wedge ++ installer_def_dir = 'debian/installer' ++ installer_arch_dir = os.path.join(installer_def_dir, arch) ++ if os.path.isdir(installer_arch_dir): ++ kw_env = os.environ.copy() ++ kw_env['KW_DEFCONFIG_DIR'] = installer_def_dir ++ kw_env['KW_CONFIG_DIR'] = installer_arch_dir ++ kw_proc = subprocess.Popen( ++ ['kernel-wedge', 'gen-control', ++ self.abiname], ++ stdout=subprocess.PIPE, ++ env=kw_env) ++ udeb_packages = read_control(kw_proc.stdout) ++ kw_proc.wait() ++ if kw_proc.returncode != 0: ++ raise RuntimeError('kernel-wedge exited with code %d' % ++ kw_proc.returncode) ++ ++ self.merge_packages(packages, udeb_packages, arch) ++ ++ # These packages must be built after the per-flavour/ ++ # per-featureset packages. ++ makefile.add( ++ 'binary-arch_%s' % arch, ++ cmds=["$(MAKE) -f debian/rules.real install-udeb_%s %s " ++ "PACKAGE_NAMES='%s'" % ++ (arch, makeflags, ++ ' '.join(p['Package'] for p in udeb_packages))]) ++ ++ def do_featureset_setup(self, vars, makeflags, arch, featureset, extra): ++ config_base = self.config.merge('base', arch, featureset) ++ makeflags['LOCALVERSION_HEADERS'] = vars['localversion_headers'] = vars['localversion'] ++ ++ def do_featureset_packages(self, packages, makefile, arch, featureset, vars, makeflags, extra): ++ headers_featureset = self.templates["control.headers.featureset"] ++ package_headers = self.process_package(headers_featureset[0], vars) ++ ++ self.merge_packages(packages, (package_headers,), arch) ++ ++ cmds_binary_arch = ["$(MAKE) -f debian/rules.real binary-arch-featureset %s" % makeflags] ++ makefile.add('binary-arch_%s_%s_real' % (arch, featureset), cmds=cmds_binary_arch) ++ ++ flavour_makeflags_base = ( ++ ('compiler', 'COMPILER', False), ++ ('kernel-arch', 'KERNEL_ARCH', False), ++ ('cflags', 'CFLAGS_KERNEL', True), ++ ('override-host-type', 'OVERRIDE_HOST_TYPE', True), ++ ) ++ ++ flavour_makeflags_image = ( ++ ('type', 'TYPE', False), ++ ('initramfs', 'INITRAMFS', True), ++ ) ++ ++ flavour_makeflags_other = ( ++ ('localversion', 'LOCALVERSION', False), ++ ('localversion-image', 'LOCALVERSION_IMAGE', True), ++ ) ++ ++ def do_flavour_setup(self, vars, makeflags, arch, featureset, flavour, extra): ++ config_base = self.config.merge('base', arch, featureset, flavour) ++ config_description = self.config.merge('description', arch, featureset, flavour) ++ config_image = self.config.merge('image', arch, featureset, flavour) ++ ++ vars['class'] = config_description['hardware'] ++ vars['longclass'] = config_description.get('hardware-long') or vars['class'] ++ ++ vars['localversion-image'] = vars['localversion'] ++ override_localversion = config_image.get('override-localversion', None) ++ if override_localversion is not None: ++ vars['localversion-image'] = vars['localversion_headers'] + '-' + override_localversion ++ ++ self._setup_makeflags(self.flavour_makeflags_base, makeflags, config_base) ++ self._setup_makeflags(self.flavour_makeflags_image, makeflags, config_image) ++ self._setup_makeflags(self.flavour_makeflags_other, makeflags, vars) ++ ++ def do_flavour_packages(self, packages, makefile, arch, featureset, flavour, vars, makeflags, extra): ++ headers = self.templates["control.headers"] ++ ++ config_entry_base = self.config.merge('base', arch, featureset, flavour) ++ config_entry_build = self.config.merge('build', arch, featureset, flavour) ++ config_entry_description = self.config.merge('description', arch, featureset, flavour) ++ config_entry_image = self.config.merge('image', arch, featureset, flavour) ++ config_entry_relations = self.config.merge('relations', arch, featureset, flavour) ++ ++ compiler = config_entry_base.get('compiler', 'gcc') ++ relations_compiler = PackageRelation(config_entry_relations[compiler]) ++ relations_compiler_build_dep = PackageRelation(config_entry_relations[compiler]) ++ for group in relations_compiler_build_dep: ++ for item in group: ++ item.arches = [arch] ++ packages['source']['Build-Depends'].extend(relations_compiler_build_dep) ++ ++ image_fields = {'Description': PackageDescription()} ++ for field in 'Depends', 'Provides', 'Suggests', 'Recommends', 'Conflicts', 'Breaks': ++ image_fields[field] = PackageRelation(config_entry_image.get(field.lower(), None), override_arches=(arch,)) ++ ++ if config_entry_image.get('initramfs', True): ++ generators = config_entry_image['initramfs-generators'] ++ l = PackageRelationGroup() ++ for i in generators: ++ i = config_entry_relations.get(i, i) ++ l.append(i) ++ a = PackageRelationEntry(i) ++ if a.operator is not None: ++ a.operator = -a.operator ++ image_fields['Breaks'].append(PackageRelationGroup([a])) ++ for item in l: ++ item.arches = [arch] ++ image_fields['Depends'].append(l) ++ ++ bootloaders = config_entry_image.get('bootloaders') ++ if bootloaders: ++ l = PackageRelationGroup() ++ for i in bootloaders: ++ i = config_entry_relations.get(i, i) ++ l.append(i) ++ a = PackageRelationEntry(i) ++ if a.operator is not None: ++ a.operator = -a.operator ++ image_fields['Breaks'].append(PackageRelationGroup([a])) ++ for item in l: ++ item.arches = [arch] ++ image_fields['Suggests'].append(l) ++ ++ desc_parts = self.config.get_merge('description', arch, featureset, flavour, 'parts') ++ if desc_parts: ++ # XXX: Workaround, we need to support multiple entries of the same name ++ parts = list(set(desc_parts)) ++ parts.sort() ++ desc = image_fields['Description'] ++ for part in parts: ++ desc.append(config_entry_description['part-long-' + part]) ++ desc.append_short(config_entry_description.get('part-short-' + part, '')) ++ ++ packages_dummy = [] ++ packages_own = [] ++ ++ if config_entry_image['type'] == 'plain-s390-tape': ++ image = self.templates["control.image.type-standalone"] ++ else: ++ image = self.templates["control.image.type-%s" % config_entry_image['type']] ++ ++ config_entry_xen = self.config.merge('xen', arch, featureset, flavour) ++ if config_entry_xen.get('dom0-support', False): ++ p = self.process_packages(self.templates['control.xen-linux-system'], vars) ++ l = PackageRelationGroup() ++ for xen_flavour in config_entry_xen['flavours']: ++ l.append("xen-system-%s" % xen_flavour) ++ p[0]['Depends'].append(l) ++ packages_dummy.extend(p) ++ ++ vars.setdefault('desc', None) ++ ++ packages_own.append(self.process_real_image(image[0], image_fields, vars)) ++ packages_own.extend(self.process_packages(image[1:], vars)) ++ ++ if config_entry_build.get('modules', True): ++ makeflags['MODULES'] = True ++ package_headers = self.process_package(headers[0], vars) ++ package_headers['Depends'].extend(relations_compiler) ++ packages_own.append(package_headers) ++ extra['headers_arch_depends'].append('%s (= ${binary:Version})' % packages_own[-1]['Package']) ++ ++ build_debug = config_entry_build.get('debug-info') ++ ++ if build_debug and self.changelog[0].distribution == 'UNRELEASED' and os.getenv('DEBIAN_KERNEL_DISABLE_DEBUG'): ++ import warnings ++ warnings.warn(u'Disable building of debug infos on request (DEBIAN_KERNEL_DISABLE_DEBUG set)') ++ build_debug = False ++ ++ if build_debug: ++ makeflags['DEBUG'] = True ++ packages_own.extend(self.process_packages(self.templates['control.image-dbg'], vars)) ++ ++ self.merge_packages(packages, packages_own + packages_dummy, arch) ++ ++ def get_config(*entry_name): ++ entry_real = ('image',) + entry_name ++ entry = self.config.get(entry_real, None) ++ if entry is None: ++ return None ++ return entry.get('configs', None) ++ ++ def check_config_default(fail, f): ++ for d in self.config_dirs[::-1]: ++ f1 = d + '/' + f ++ if os.path.exists(f1): ++ return [f1] ++ if fail: ++ raise RuntimeError("%s unavailable" % f) ++ return [] ++ ++ def check_config_files(files): ++ ret = [] ++ for f in files: ++ for d in self.config_dirs[::-1]: ++ f1 = d + '/' + f ++ if os.path.exists(f1): ++ ret.append(f1) ++ break ++ else: ++ raise RuntimeError("%s unavailable" % f) ++ return ret ++ ++ def check_config(default, fail, *entry_name): ++ configs = get_config(*entry_name) ++ if configs is None: ++ return check_config_default(fail, default) ++ return check_config_files(configs) ++ ++ kconfig = check_config('config', True) ++ kconfig.extend(check_config("%s/config" % arch, True, arch)) ++ kconfig.extend(check_config("%s/config.%s" % (arch, flavour), False, arch, None, flavour)) ++ kconfig.extend(check_config("featureset-%s/config" % featureset, False, None, featureset)) ++ kconfig.extend(check_config("%s/%s/config" % (arch, featureset), False, arch, featureset)) ++ kconfig.extend(check_config("%s/%s/config.%s" % (arch, featureset, flavour), False, arch, featureset, flavour)) ++ makeflags['KCONFIG'] = ' '.join(kconfig) ++ if build_debug: ++ makeflags['KCONFIG_OPTIONS'] = '-o DEBUG_INFO=y' ++ ++ cmds_binary_arch = ["$(MAKE) -f debian/rules.real binary-arch-flavour %s" % makeflags] ++ if packages_dummy: ++ cmds_binary_arch.append("$(MAKE) -f debian/rules.real install-dummy DH_OPTIONS='%s' %s" % (' '.join(["-p%s" % i['Package'] for i in packages_dummy]), makeflags)) ++ cmds_build = ["$(MAKE) -f debian/rules.real build-arch %s" % makeflags] ++ cmds_setup = ["$(MAKE) -f debian/rules.real setup-flavour %s" % makeflags] ++ makefile.add('binary-arch_%s_%s_%s_real' % (arch, featureset, flavour), cmds=cmds_binary_arch) ++ makefile.add('build-arch_%s_%s_%s_real' % (arch, featureset, flavour), cmds=cmds_build) ++ makefile.add('setup_%s_%s_%s_real' % (arch, featureset, flavour), cmds=cmds_setup) ++ ++ def merge_packages(self, packages, new, arch): ++ for new_package in new: ++ name = new_package['Package'] ++ if name in packages: ++ package = packages.get(name) ++ package['Architecture'].add(arch) ++ ++ for field in 'Depends', 'Provides', 'Suggests', 'Recommends', 'Conflicts': ++ if field in new_package: ++ if field in package: ++ v = package[field] ++ v.extend(new_package[field]) ++ else: ++ package[field] = new_package[field] ++ ++ else: ++ new_package['Architecture'] = arch ++ packages.append(new_package) ++ ++ def process_changelog(self): ++ act_upstream = self.changelog[0].version.upstream ++ versions = [] ++ for i in self.changelog: ++ if i.version.upstream != act_upstream: ++ break ++ versions.append(i.version) ++ self.versions = versions ++ version = self.version = self.changelog[0].version ++ if self.version.linux_modifier is not None: ++ self.abiname_part = '' ++ else: ++ self.abiname_part = '-%s' % self.config['abi', ]['abiname'] ++ # XXX: We need to add another part until after wheezy ++ self.abiname = (re.sub('^(\d+\.\d+)(?=-|$)', r'\1.0', ++ self.version.linux_upstream) ++ + self.abiname_part) ++ self.vars = { ++ 'upstreamversion': self.version.linux_upstream, ++ 'version': self.version.linux_version, ++ 'source_upstream': self.version.upstream, ++ 'source_package': self.changelog[0].source, ++ 'abiname': self.abiname, ++ } ++ self.config['version', ] = {'source': self.version.complete, 'abiname': self.abiname} ++ ++ distribution = self.changelog[0].distribution ++ if distribution in ('unstable', ): ++ if (version.linux_revision_experimental or ++ version.linux_revision_other): ++ raise RuntimeError("Can't upload to %s with a version of %s" % ++ (distribution, version)) ++ if distribution in ('experimental', ): ++ if not version.linux_revision_experimental: ++ raise RuntimeError("Can't upload to %s with a version of %s" % ++ (distribution, version)) ++ ++ def process_real_image(self, entry, fields, vars): ++ entry = self.process_package(entry, vars) ++ for key, value in fields.iteritems(): ++ if key in entry: ++ real = entry[key] ++ real.extend(value) ++ elif value: ++ entry[key] = value ++ return entry ++ ++ def write(self, packages, makefile): ++ self.write_config() ++ super(Gencontrol, self).write(packages, makefile) ++ ++ def write_config(self): ++ import pprint ++ f = file("debian/config.defines.pretty.dump", 'w') ++ pprint.pprint(self.config, stream=f) ++ f.close() ++ f = file("debian/config.defines.dump", 'w') ++ self.config.dump(f) ++ f.close() ++ ++if __name__ == '__main__': ++ Gencontrol()() +diff --git a/debian/bin/genorig.py b/debian/bin/genorig.py +new file mode 100755 +index 0000000..6ec9091 +--- /dev/null ++++ b/debian/bin/genorig.py +@@ -0,0 +1,139 @@ ++#!/usr/bin/env python ++ ++import sys ++sys.path.append("debian/lib/python") ++ ++import os ++import os.path ++import re ++import shutil ++import subprocess ++ ++from debian_linux.debian import Changelog, VersionLinux ++from debian_linux.patches import PatchSeries ++ ++ ++class Main(object): ++ def __init__(self, input_files, override_version): ++ self.log = sys.stdout.write ++ ++ self.input_files = input_files ++ ++ changelog = Changelog(version=VersionLinux)[0] ++ source = changelog.source ++ version = changelog.version ++ ++ if override_version: ++ version = VersionLinux('%s-undef' % override_version) ++ ++ self.version_dfsg = version.linux_dfsg ++ if self.version_dfsg is None: ++ self.version_dfsg = '0' ++ ++ self.log('Using source name %s, version %s, dfsg %s\n' % (source, version.upstream, self.version_dfsg)) ++ ++ self.orig = '%s-%s' % (source, version.upstream) ++ self.orig_tar = '%s_%s.orig.tar.xz' % (source, version.upstream) ++ self.tag = 'v' + version.linux_upstream_full ++ ++ def __call__(self): ++ import tempfile ++ self.dir = tempfile.mkdtemp(prefix='genorig', dir='debian') ++ try: ++ if os.path.isdir(self.input_files[0]): ++ self.upstream_export(self.input_files[0]) ++ else: ++ self.upstream_extract(self.input_files[0]) ++ if len(self.input_files) > 1: ++ self.upstream_patch(self.input_files[1]) ++ self.debian_patch() ++ self.tar() ++ finally: ++ shutil.rmtree(self.dir) ++ ++ def upstream_export(self, input_repo): ++ self.log("Exporting %s from %s\n" % (self.tag, input_repo)) ++ ++ archive_proc = subprocess.Popen(['git', 'archive', '--format=tar', ++ '--prefix=%s/' % self.orig, self.tag], ++ cwd=input_repo, ++ stdout=subprocess.PIPE) ++ extract_proc = subprocess.Popen(['tar', '-xf', '-'], cwd=self.dir, ++ stdin=archive_proc.stdout) ++ ++ if extract_proc.wait(): ++ raise RuntimeError("Can't extract tarball") ++ ++ def upstream_extract(self, input_tar): ++ self.log("Extracting tarball %s\n" % input_tar) ++ match = re.match(r'(^|.*/)(?Plinux-\d+\.\d+(\.\d+)?(-\S+)?)\.tar(\.(?P(bz2|gz)))?$', input_tar) ++ if not match: ++ raise RuntimeError("Can't identify name of tarball") ++ ++ cmdline = ['tar', '-xf', input_tar, '-C', self.dir] ++ if match.group('extension') == 'bz2': ++ cmdline.append('-j') ++ elif match.group('extension') == 'gz': ++ cmdline.append('-z') ++ ++ if subprocess.Popen(cmdline).wait(): ++ raise RuntimeError("Can't extract tarball") ++ ++ os.rename(os.path.join(self.dir, match.group('dir')), os.path.join(self.dir, self.orig)) ++ ++ def upstream_patch(self, input_patch): ++ self.log("Patching source with %s\n" % input_patch) ++ match = re.match(r'(^|.*/)patch-\d+\.\d+\.\d+(-\S+?)?(\.(?P(bz2|gz)))?$', input_patch) ++ if not match: ++ raise RuntimeError("Can't identify name of patch") ++ cmdline = [] ++ if match.group('extension') == 'bz2': ++ cmdline.append('bzcat') ++ elif match.group('extension') == 'gz': ++ cmdline.append('zcat') ++ else: ++ cmdline.append('cat') ++ cmdline.append(input_patch) ++ cmdline.append('| (cd %s; patch -p1 -f -s -t --no-backup-if-mismatch)' % os.path.join(self.dir, self.orig)) ++ if os.spawnv(os.P_WAIT, '/bin/sh', ['sh', '-c', ' '.join(cmdline)]): ++ raise RuntimeError("Can't patch source") ++ ++ def debian_patch(self): ++ name = "orig" ++ self.log("Patching source with debian patch (series %s)\n" % name) ++ fp = file("debian/patches/series-" + name) ++ series = PatchSeries(name, "debian/patches", fp) ++ series(dir=os.path.join(self.dir, self.orig)) ++ ++ def tar(self): ++ out = os.path.join("../orig", self.orig_tar) ++ try: ++ os.mkdir("../orig") ++ except OSError: ++ pass ++ try: ++ os.stat(out) ++ raise RuntimeError("Destination already exists") ++ except OSError: ++ pass ++ self.log("Generate tarball %s\n" % out) ++ cmdline = ['tar -caf', out, '-C', self.dir, self.orig] ++ try: ++ if os.spawnv(os.P_WAIT, '/bin/sh', ['sh', '-c', ' '.join(cmdline)]): ++ raise RuntimeError("Can't patch source") ++ os.chmod(out, 0644) ++ except: ++ try: ++ os.unlink(out) ++ except OSError: ++ pass ++ raise ++ ++if __name__ == '__main__': ++ from optparse import OptionParser ++ parser = OptionParser(usage="%prog [OPTION]... {TAR [PATCH] | REPO}") ++ parser.add_option("-V", "--override-version", dest="override_version", help="Override version", metavar="VERSION") ++ options, args = parser.parse_args() ++ ++ assert 1 <= len(args) <= 2 ++ Main(args, options.override_version)() +diff --git a/debian/bin/kconfig.py b/debian/bin/kconfig.py +new file mode 100755 +index 0000000..d9a88aa +--- /dev/null ++++ b/debian/bin/kconfig.py +@@ -0,0 +1,40 @@ ++#!/usr/bin/env python ++ ++import optparse ++import os.path ++import re ++import sys ++ ++from debian_linux.kconfig import * ++ ++ ++def merge(output, configs, overrides): ++ kconfig = KconfigFile() ++ for c in configs: ++ kconfig.read(file(c)) ++ for key, value in overrides.iteritems(): ++ kconfig.set(key, value) ++ file(output, "w").write(str(kconfig)) ++ ++ ++def opt_callback_dict(option, opt, value, parser): ++ match = re.match('^\s*(\S+)=(\S+)\s*$', value) ++ if not match: ++ raise optparse.OptionValueError('not key=value') ++ dest = option.dest ++ data = getattr(parser.values, dest) ++ data[match.group(1)] = match.group(2) ++ ++ ++if __name__ == '__main__': ++ parser = optparse.OptionParser(usage="%prog [OPTION]... FILE...") ++ parser.add_option('-o', '--override', ++ action='callback', ++ callback=opt_callback_dict, ++ default={}, ++ dest='overrides', ++ help="Override option", ++ type='string') ++ options, args = parser.parse_args() ++ ++ merge(args[0], args[1:], options.overrides) +diff --git a/debian/bin/no-depmod b/debian/bin/no-depmod +new file mode 100755 +index 0000000..ed5a846 +--- /dev/null ++++ b/debian/bin/no-depmod +@@ -0,0 +1,18 @@ ++#!/bin/sh ++ ++set -e ++ ++# This is a dummy substitute for depmod. Since we run depmod during ++# postinst, we do not need or want to package the files that it ++# generates. ++ ++if [ "x$1" = x-V ]; then ++ # Satisfy version test ++ echo 'not really module-init-tools' ++elif [ "x$1" = x-b -a "${2%/depmod.??????}" != "$2" ]; then ++ # Satisfy test of short kernel versions ++ mkdir -p "$2/lib/modules/$3" ++ touch "$2/lib/modules/$3/modules.dep" ++else ++ echo 'skipping depmod' ++fi +diff --git a/debian/bin/patch.apply b/debian/bin/patch.apply +new file mode 100644 +index 0000000..e69de29 +diff --git a/debian/bin/stable-update.sh b/debian/bin/stable-update.sh +new file mode 100755 +index 0000000..c3eafb7 +--- /dev/null ++++ b/debian/bin/stable-update.sh +@@ -0,0 +1,78 @@ ++#!/bin/bash -eu ++ ++if [ $# -ne 2 ]; then ++ echo >&2 "Usage: $0 REPO VERSION" ++ echo >&2 "REPO is the git repository to generate a changelog from" ++ echo >&2 "VERSION is the stable version (without leading v)" ++ exit 2 ++fi ++ ++# Get base version, i.e. the Linus stable release that a version is based on ++base_version() { ++ local ver ++ ver="${1%-rc*}" ++ case "$ver" in ++ 2.6.*.* | [3-9].*.* | ??.*.*) ++ ver="${ver%.*}" ++ ;; ++ esac ++ echo "$ver" ++} ++ ++add_update() { ++ local base update ++ base="$(base_version "$1")" ++ update="${1#$base.}" ++ if [ "$update" = "$1" ]; then ++ update=0 ++ fi ++ update="$((update + $2))" ++ if [ $update = 0 ]; then ++ echo "$base" ++ else ++ echo "$base.$update" ++ fi ++} ++ ++# Get next stable update version ++next_update() { ++ add_update "$1" 1 ++} ++ ++export GIT_DIR="$1/.git" ++ ++new_ver="$2" ++cur_pkg_ver="$(dpkg-parsechangelog | sed -n 's/^Version: //p')" ++cur_ver="${cur_pkg_ver%-*}" ++ ++if [ "$(base_version "$new_ver")" != "$(base_version "$cur_ver")" ]; then ++ echo >&2 "$new_ver is not on the same stable series as $cur_ver" ++ exit 2 ++fi ++ ++case "$cur_pkg_ver" in ++ *~experimental*) ++ new_pkg_ver="$new_ver-1~experimental.1" ++ ;; ++ *) ++ new_pkg_ver="$new_ver-1" ++ ;; ++esac ++ ++# dch insists on word-wrapping everything, so just add the URLs initially ++dch -v "$new_pkg_ver" --preserve --multimaint-merge -D UNRELEASED \ ++ --release-heuristic=changelog "$( ++ echo "New upstream stable update: " ++ while [ "v$cur_ver" != "v$new_ver" ]; do ++ cur_ver="$(next_update "$cur_ver")" ++ echo "http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-$cur_ver" ++ done)" ++ ++# Then insert the shortlogs with sed ++while [ "v$cur_ver" != "v$new_ver" ]; do ++ next_ver="$(next_update "$cur_ver")" ++ sed -i '/ChangeLog-'"${next_ver//./\\.}"'/a\ ++'"$(git log --reverse --pretty=' - %s\' "v$cur_ver..v$next_ver^")"' ++' debian/changelog ++ cur_ver="$next_ver" ++done +diff --git a/debian/bin/test-patches b/debian/bin/test-patches +new file mode 100755 +index 0000000..94d6b05 +--- /dev/null ++++ b/debian/bin/test-patches +@@ -0,0 +1,101 @@ ++#!/bin/bash ++ ++set -e ++shopt -s extglob ++ ++# Set defaults from the running kernel ++arch="$(dpkg --print-architecture)" ++kernelabi="$(uname -r)" ++ff="${kernelabi#+([^-])-@(trunk|+([0-9]))-}" ++if [ "x$ff" != "x$kernelabi" ]; then ++ flavour="${ff#@(openvz|rt|vserver|xen)-}" ++ if [ "x$flavour" != "x$ff" ]; then ++ featureset="${ff%-$flavour}" ++ else ++ featureset=none ++ fi ++else ++ flavour= ++ featureset=none ++fi ++ ++fuzz=0 ++ ++eval "set -- $(getopt -n "$0" -o "f:j:s:" -l "fuzz:" -- "$@")" ++while true; do ++ case "$1" in ++ -f) flavour="$2"; shift 2 ;; ++ -j) export MAKEFLAGS="$MAKEFLAGS -j$2"; shift 2 ;; ++ -s) featureset="$2"; shift 2 ;; ++ --fuzz) fuzz="$2"; shift 2;; ++ --) shift 1; break ;; ++ esac ++done ++ ++if [ $# -lt 1 ]; then ++ echo >&2 "Usage: $0 [] ..." ++ cat >&2 < specify the 'flavour' of kernel to build, e.g. 686-pae ++ -j specify number of compiler jobs to run in parallel ++ -s specify an optional featureset to apply, e.g. rt ++ --fuzz set the maximum patch fuzz factor (default: 0) ++EOF ++ exit 2 ++fi ++ ++if [ -z "$flavour" ]; then ++ echo >&2 "You must specify a flavour to build with the -f option" ++ exit 2 ++fi ++ ++dpkg-checkbuilddeps -B ++ ++# Append 'a~test' to Debian version; this should be less than any official ++# successor and easily recognisable ++version="$(dpkg-parsechangelog | sed 's/^Version: //; t; d')" ++if [ "${version%a~test}" = "$version" ]; then ++ version="$version"a~test ++ dch -v "$version" --distribution UNRELEASED "Testing patches $*" ++fi ++ ++# Make new directory for patches ++mkdir -p debian/patches/test ++ ++# Ignore user's .quiltrc ++alias quilt='quilt --quiltrc -' ++ ++# Try to clean up any previous test patches ++if [ "$featureset" = none ]; then ++ while patch="$(quilt next 2>/dev/null || quilt top 2>/dev/null)" && \ ++ [ "${patch#test/}" != "$patch" ]; do ++ quilt delete -r "$patch" ++ done ++else ++ sed -i '/^test\//d' debian/patches/series-${featureset} ++fi ++ ++# Prepare a new directory for the patches ++rm -rf debian/patches/test/ ++mkdir debian/patches/test ++ ++# Regenerate control and included rules ++rm debian/control debian/rules.gen ++debian/rules debian/control-real && exit 1 || true ++test -f debian/control ++test -f debian/rules.gen ++ ++# Clean up old build; apply existing patches for featureset ++debian/rules clean ++debian/rules source ++ ++# Apply the additional patches ++for patch in "$@"; do ++ patch_abs="$(readlink -f "$patch")" ++ (cd "debian/build/source_${featureset}" && \ ++ quilt import -P "test/$(basename "$patch")" "$patch_abs" && \ ++ quilt push --fuzz="$fuzz") ++done ++ ++# Build selected binaries ++fakeroot make -f debian/rules.gen binary-arch_"$arch"_"$featureset"_"$flavour" +diff --git a/debian/changelog b/debian/changelog +new file mode 100644 +index 0000000..8932bf7 +--- /dev/null ++++ b/debian/changelog +@@ -0,0 +1,16276 @@ ++linux (3.2.71-1) CumulusLinux-2.5; urgency=medium ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.69 ++ - ARM: pxa: add regulator_has_full_constraints to corgi board file ++ - ARM: pxa: add regulator_has_full_constraints to poodle board file ++ - ARM: pxa: add regulator_has_full_constraints to spitz board file ++ - hx4700: regulator: declare full constraints ++ - udf: Remove repeated loads blocksize ++ - udf: Check length of extended attributes and allocation descriptors ++ - PCI: Generate uppercase hex for modalias var in uevent ++ - kernel.h: add BUILD_BUG() macro ++ - usb: core: buffer: smallest buffer should start at ARCH_DMA_MINALIGN ++ - axonram: Fix bug in direct_access ++ - TPM: Add new TPMs to the tail of the list to prevent inadvertent change of dev ++ - Bluetooth: ath3k: Add support of AR3012 bluetooth 13d3:3423 device ++ - smack: fix possible use after frees in task_security() callers ++ - KVM: s390: base hrtimer on a monotonic clock ++ - PCI: Fix infinite loop with ROM image of size 0 ++ - USB: cp210x: add ID for RUGGEDCOM USB Serial Console ++ - iio: imu: adis16400: Fix sign extension ++ - staging: comedi: comedi_compat32.c: fix COMEDI_CMD copy back ++ - ARM: 8284/1: sa1100: clear RCSR_SMR on resume ++ - xprtrdma: Free the pd if ib_query_qp() fails ++ - nfs: don't call blocking operations while !TASK_RUNNING ++ - cdc-acm: add sanity checks ++ - USB: add flag for HCDs that can't receive wakeup requests (isp1760-hcd) ++ - USB: fix use-after-free bug in usb_hcd_unlink_urb() ++ - vt: provide notifications on selection changes ++ - tty: Prevent untrappable signals from malicious program ++ - lmedm04: Fix usb_submit_urb BOGUS urb xfer, pipe 1 != type 3 in interrupt urb ++ - xen/manage: Fix USB interaction issues when resuming ++ - rtnetlink: ifla_vf_policy: fix misuses of NLA_BINARY ++ - ALSA: off by one bug in snd_riptide_joystick_probe() ++ - fsnotify: fix handling of renames in audit ++ - NFSv4.1: Fix a kfree() of uninitialised pointers in decode_cb_sequence_args ++ - cpufreq: speedstep-smi: enable interrupts when waiting ++ - mm/hugetlb: fix getting refcount 0 page in hugetlb_fault() ++ - mm/hugetlb: add migration/hwpoisoned entry check in hugetlb_change_protection ++ - mm/hugetlb: add migration entry check in __unmap_hugepage_range ++ - mm/mmap.c: fix arithmetic overflow in __vm_enough_memory() ++ - mm/nommu.c: fix arithmetic overflow in __vm_enough_memory() ++ - iscsi-target: Drop problematic active_ts_list usage ++ - mm/memory.c: actually remap enough memory ++ - drm/radeon/dp: Set EDP_CONFIGURATION_SET for bridge chips if necessary ++ - ALSA: hdspm - Constrain periods to 2 on older cards ++ - jffs2: fix handling of corrupted summary length ++ - dm mirror: do not degrade the mirror on discard error ++ - dm io: reject unsupported DISCARD requests with EOPNOTSUPP ++ - ipv6: fix ipv6_cow_metrics for non DST_HOST case ++ - fixed invalid assignment of 64bit mask to host dma_boundary for scatter gather segment boundary limit. ++ - sg: fix read() error reporting ++ - netfilter: xt_socket: fix a stack corruption bug ++ - IB/qib: Do not write EEPROM ++ - dm: fix a race condition in dm_get_md ++ - dm snapshot: fix a possible invalid memory access on unload ++ - sched/autogroup: Fix failure to set cpu.rt_runtime_us ++ - x86, mm/ASLR: Fix stack randomization on 64-bit systems ++ - libceph: fix double __remove_osd() problem ++ - kdb: fix incorrect counts in KDB summary command output ++ - ipv4: ip_check_defrag should correctly check return value of skb_copy_bits ++ - debugfs: leave freeing a symlink body until inode eviction ++ - autofs4: check dev ioctl size before allocating ++ - autofs4 copy_dev_ioctl(): keep the value of ->size we'd used for allocation ++ - xfs: ensure truncate forces zeroed blocks to disk ++ - gpio: tps65912: fix wrong container_of arguments ++ - ALSA: pcm: Don't leave PREPARED state after draining ++ - KVM: emulate: fix CMPXCHG8B on 32-bit hosts ++ - net: compat: Ignore MSG_CMSG_COMPAT in compat_sys_{send, recv}msg ++ - xhci: Allocate correct amount of scratchpad buffers ++ - USB: usbfs: don't leak kernel data in siginfo ++ - USB: ftdi_sio: add PIDs for Actisense USB devices ++ - USB: serial: fix potential use-after-free after failed probe ++ - USB: serial: fix tty-device error handling at probe ++ - mac80211: Send EAPOL frames at lowest rate ++ - USB: serial: cp210x: Adding Seletek device id's ++ - nilfs2: fix potential memory overrun on inode ++ - NFSv4: Don't call put_rpccred() under the rcu_read_lock() ++ - usb: ftdi_sio: Add jtag quirk support for Cyber Cortex AV boards ++ - eCryptfs: don't pass fs-specific ioctl commands through ++ - drm/radeon: do a posting read in r100_set_irq ++ - drm/radeon: do a posting read in rs600_set_irq ++ - drm/radeon: do a posting read in r600_set_irq ++ - drm/radeon: do a posting read in evergreen_set_irq ++ - drm/radeon: fix DRM_IOCTL_RADEON_CS oops ++ - ACPI / video: Load the module even if ACPI is disabled ++ - ASoC: omap-pcm: Correct dma mask ++ - x86/asm/entry/64: Remove a bogus 'ret_from_fork' optimization ++ - xhci: fix reporting of 0-sized URBs in control endpoint ++ - xhci: Workaround for PME stuck issues in Intel xhci ++ - Change email address for 8250_pci ++ - tty: fix up atime/mtime mess, take four ++ - console: Fix console name size mismatch ++ - net: irda: fix wait_until_sent poll timeout ++ - TTY: fix tty_wait_until_sent on 64-bit machines ++ - sunrpc: fix braino in ->poll() ++ - gadgetfs: use-after-free in ->aio_read() ++ - gadgetfs: Fix leak on error in aio_read() ++ - ipvs: add missing ip_vs_pe_put in sync code ++ - spi: dw: revisit FIFO size detection again ++ - fuse: notify: don't move pages ++ - fuse: set stolen page uptodate ++ - dm: hold suspend_lock while suspending device during device deletion ++ - dm io: deal with wandering queue limits when handling REQ_DISCARD and REQ_WRITE_SAME ++ - mac80211: drop unencrypted frames in mesh fwding ++ - mac80211: set only VO as a U-APSD enabled AC ++ - mac80211: disable u-APSD queues by default ++ - virtio_console: avoid config access from irq ++ - bnx2x: Force fundamental reset for EEH recovery ++ - x86/vdso: Fix the build on GCC5 ++ - ASoC: sgtl5000: remove useless register write clearing CHRGPUMP_POWERUP ++ - libsas: Fix Kernel Crash in smp_execute_task ++ - Input: synaptics - query min dimensions for fw v8.1 ++ - Input: synaptics - fix middle button on Lenovo 2015 products ++ - Input: synaptics - handle spurious release of trackstick buttons ++ - can: add missing initialisations in CAN related skbuffs ++ - vt6655: RFbSetPower fix missing rate RATE_12M ++ - ftrace: Fix en(dis)able graph caller when en(dis)abling record via sysctl ++ - ftrace: Fix ftrace enable ordering of sysctl ftrace_enabled ++ - x86/asm/entry/32: Fix user_mode() misuses ++ - ASoC: adav80x: Fix wrong value references for boolean kctl ++ - ASoC: ak4641: Fix wrong value references for boolean kctl ++ - ASoC: cs4271: Fix wrong value references for boolean kctl ++ - ASoC: wm2000: Fix wrong value references for boolean kctl ++ - ASoC: wm8731: Fix wrong value references for boolean kctl ++ - ASoC: wm8903: Fix wrong value references for boolean kctl ++ - ASoC: wm8904: Fix wrong value references for boolean kctl ++ - ASoC: wm8955: Fix wrong value references for boolean kctl ++ - ASoC: wm8960: Fix wrong value references for boolean kctl ++ - xen-pciback: limit guest control of command register ++ - drm/vmwgfx: Reorder device takedown somewhat ++ - ALSA: control: Add sanity checks for user ctl id name string ++ - ALSA: snd-usb: add quirks for Roland UA-22 ++ - nilfs2: fix deadlock of segment constructor during recovery ++ - crypto: aesni - fix memory usage in GCM decryption ++ - nl80211: ignore HT/VHT capabilities without QoS/WMM ++ - pagemap: do not leak physical addresses to non-privileged userspace ++ - IB/mlx4: Saturate RoCE port PMA counters in case of overflow ++ - tcm_fc: missing curly braces in ft_invl_hw_context() ++ - target/pscsi: Fix NULL pointer dereference in get_device_type ++ - writeback: add missing INITIAL_JIFFIES init in global_update_bandwidth() ++ - nbd: fix possible memory leak ++ - iio: core: Fix double free. ++ - USB: ftdi_sio: Added custom PID for Synapse Wireless product ++ - USB: serial: keyspan_pda: fix Entrega company name spelling ++ - USB: keyspan_pda: add new device id ++ - net: ethernet: pcnet32: Setup the SRAM and NOUFLO on Am79C97{3, 5} ++ - net: compat: Update get_compat_msghdr() to match copy_msghdr_from_user() behaviour ++ - cifs: fix use-after-free bug in find_writable_file ++ - perf: Fix irq_work 'tail' recursion ++ - sched: Fix RLIMIT_RTTIME when PI-boosting to RT ++ - writeback: fix possible underflow in write bandwidth calculation ++ - usb: xhci: handle Config Error Change (CEC) in xhci driver ++ - usb: xhci: apply XHCI_AVOID_BEI quirk to all Intel xHCI controllers ++ - net: use for_each_netdev_safe() in rtnl_group_changelink() ++ - USB: ftdi_sio: Use jtag quirk for SNAP Connect E10 ++ - selinux: fix sel_write_enforce broken return value ++ - mm: fix anon_vma->degree underflow in anon_vma endless growing prevention ++ - hfsplus: fix B-tree corruption after insertion at position 0 ++ - ALSA: hda - Add one more node in the EAPD supporting candidate list ++ - radeon: Do not directly dereference pointers to BIOS area. ++ - x86/reboot: Remove VersaLogic Menlow reboot quirk ++ - ACPI, x86: fix Dell M6600 ACPI reboot regression via DMI ++ - x86/reboot: Remove quirk entry for SBC FITPC ++ - x86/reboot: Add quirk to make Dell C6100 use reboot=pci automatically ++ - x86/reboot: Fix apparent cut-n-paste mistake in Dell reboot workaround ++ - x86/reboot: Remove the duplicate C6100 entry in the reboot quirks list ++ - x86/reboot: Add reboot quirk for Dell Latitude E5410 ++ - x86/reboot: Add reboot quirk for Certec BPC600 ++ - x86/reboot: Add ASRock Q1900DC-ITX mainboard reboot quirk ++ - mac80211: fix RX A-MPDU session reorder timer deletion ++ - IB/uverbs: Prevent integer overflow in ib_umem_get address arithmetic ++ - xen-netfront: transmit fully GSO-sized packets ++ - be2iscsi: Fix kernel panic when device initialization fails ++ - Defer processing of REQ_PREEMPT requests for blocked devices ++ - ocfs2: _really_ sync the right range ++ - ALSA: usb - Creative USB X-Fi Pro SB1095 volume knob support ++ - netfilter: nf_conntrack: reserve two bytes for nf_ct_ext->len ++ - net: llc: use correct size for sysctl timeout entries ++ - net: rds: use correct size for max unacked packets and bytes ++ - ipv6: Don't reduce hop limit for an interface ++ - fs: take i_mutex during prepare_binprm for set[ug]id executables ++ - ipv4: Missing sk_nulls_node_init() in ping_unhash(). ++ - net:socket: set msg_namelen to 0 if msg_name is passed as NULL in msghdr struct from userland. ++ - NFSv4: Minor cleanups for nfs4_handle_exception and nfs4_async_handle_error ++ - jfs: fix readdir regression ++ - ip: zero sockaddr returned on error queue ++ - net: rps: fix cpu unplug ++ - ipv6: stop sending PTB packets for MTU < 1280 ++ - netxen: fix netxen_nic_poll() logic ++ - ping: Fix race in free in receive path ++ - ppp: deflate: never return len larger than output buffer ++ - rtnetlink: call ->dellink on failure when ->newlink exists ++ - gen_stats.c: Duplicate xstats buffer for later use ++ - ipv4: ip_check_defrag should not assume that skb_network_offset is zero ++ - ematch: Fix auto-loading of ematch modules. ++ - net: reject creation of netdev names with colons ++ - macvtap: limit head length of skb allocated ++ - macvtap: make sure neighbour code can push ethernet header ++ - usb: plusb: Add support for National Instruments host-to-host cable ++ - udp: only allow UFO for packets from SOCK_DGRAM sockets ++ - net: ping: Return EAFNOSUPPORT when appropriate. ++ - net: avoid to hang up on sending due to sysctl configuration overflow. ++ - net: sysctl_net_core: check SNDBUF and RCVBUF for min length ++ - rds: avoid potential stack overflow ++ - caif: fix MSG_OOB test in caif_seqpkt_recvmsg() ++ - rxrpc: bogus MSG_PEEK test in rxrpc_recvmsg() ++ - tcp: make connect() mem charging friendly ++ - 8139cp: Call dev_kfree_skby_any instead of kfree_skb. ++ - 8139too: Call dev_kfree_skby_any instead of dev_kfree_skb. ++ - r8169: Call dev_kfree_skby_any instead of dev_kfree_skb. ++ - tg3: Call dev_kfree_skby_any instead of dev_kfree_skb. ++ - ixgb: Call dev_kfree_skby_any instead of dev_kfree_skb. ++ - benet: Call dev_kfree_skby_any instead of kfree_skb. ++ - gianfar: Carefully free skbs in functions called by netpoll. ++ - ip_forward: Drop frames with attached skb->sk ++ - tcp: avoid looping in tcp_send_fin() ++ - net: make skb_gso_segment error handling more robust ++ - spi: spidev: fix possible arithmetic overflow for multi-transfer message ++ - IB/core: Avoid leakage from kernel to user space ++ - ipvs: rerouting to local clients is not needed anymore ++ - ipvs: uninitialized data with IP_VS_IPV6 ++ - Revert "KVM: s390: flush CPU on load control" ++ ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.70 ++ - Bluetooth: ath3k: Add support Atheros AR5B195 combo Mini PCIe card ++ - Drivers: hv: vmbus: Fix a bug in the error path in vmbus_open() ++ - e1000: add dummy allocator to fix race condition between mtu change and netpoll ++ - KVM: s390: Zero out current VMDB of STSI before including level3 data. ++ - usb: musb: core: fix TX/RX endpoint order ++ - compal-laptop: Check return value of power_supply_register ++ - pinctrl: fix example .get_group_pins implementation signature ++ - drm/radeon: fix doublescan modes (v2) ++ - lib: memzero_explicit: use barrier instead of OPTIMIZER_HIDE_VAR ++ - ASoC: wm8741: Fix rates constraints values ++ - cdc-wdm: fix endianness bug in debug statements ++ - staging: panel: fix lcd type ++ - UBI: account for bitflips in both the VID header and data ++ - UBI: fix out of bounds write ++ - UBI: initialize LEB number variable ++ - UBI: fix check for "too many bytes" ++ - Drivers: hv: vmbus: Don't wait after requesting offers ++ - Btrfs: fix log tree corruption when fs mounted with -o discard ++ - btrfs: don't accept bare namespace as a valid xattr ++ - ARM: 8320/1: fix integer overflow in ELF_ET_DYN_BASE ++ - rtlwifi: rtl8192cu: Add new USB ID ++ - MIPS: Hibernate: flush TLB entries earlier ++ - ASoC: cs4271: Increase delay time after reset ++ - ext4: make fsync to sync parent dir in no-journal for real this time ++ - jhash: Update jhash_[321]words functions to use correct initval ++ - Input: elantech - fix absolute mode setting on some ASUS laptops ++ - RDS: Documentation: Document AF_RDS, PF_RDS and SOL_RDS correctly. ++ - selinux/nlmsg: add XFRM_MSG_GETSPDINFO ++ - selinux/nlmsg: add XFRM_MSG_[NEW|GET]SADINFO ++ - x86/iommu: Fix header comments regarding standard and _FINISH macros ++ - scsi: storvsc: Fix a bug in copy_from_bounce_buffer() ++ - ALSA: emu10k1: don't deadlock in proc-functions ++ - powerpc: Fix missing L2 cache size in /sys/devices/system/cpu ++ - sg_start_req(): make sure that there's not too many elements in iovec ++ - selinux/nlmsg: add XFRM_MSG_REPORT ++ - selinux/nlmsg: add XFRM_MSG_MIGRATE ++ - selinux/nlmsg: add XFRM_MSG_MAPPING ++ - s390/hibernate: fix save and restore of kernel text section ++ - Btrfs: fix inode eviction infinite loop after cloning into it ++ - powerpc/perf: Cap 64bit userspace backtraces to PERF_MAX_STACK_DEPTH ++ - ACPICA: Utilities: split IO address types from data type models. ++ - fs/binfmt_elf.c: fix bug in loading of PIE binaries ++ - IB/core: disallow registering 0-sized memory region ++ - IB/core: don't disallow registering region starting at 0x0 ++ - IB/mlx4: Fix WQE LSO segment calculation ++ - megaraid_sas: use raw_smp_processor_id() ++ - firmware/ihex2fw.c: restore missing default in switch statement ++ - ptrace: fix race between ptrace_resume() and wait_task_stopped() ++ - memstick: mspro_block: add missing curly braces ++ - KVM: VMX: Preserve host CR4.MCE value while in guest mode. ++ - writeback: use |1 instead of +1 to protect against div by zero ++ - libata: Add helper to determine when PHY events should be ignored ++ - libata: Ignore spurious PHY event on LPM policy change ++ - ALSA: emu10k1: Fix card shortname string buffer overflow ++ - ALSA: emux: Fix mutex deadlock at unloading ++ - 3w-sas: fix command completion race ++ - 3w-xxxx: fix command completion race ++ - 3w-9xxx: fix command completion race ++ - cdc-acm: prevent infinite loop when parsing CDC headers. ++ - rtlwifi: rtl8192cu: Fix kernel deadlock ++ - serial: xilinx: Use platform_get_irq to get irq description structure ++ - serial: of-serial: Remove device_type = "serial" registration ++ - ALSA: emux: Fix mutex deadlock in OSS emulation ++ - ALSA: emu10k1: Emu10k2 32 bit DMA mode ++ - USB: cp210x: add ID for KCF Technologies PRN device ++ - USB: pl2303: Remove support for Samsung I330 ++ - xen-pciback: Add name prefix to global 'permissive' variable ++ - gpio: unregister gpiochip device before removing it ++ - gpio: sysfs: fix memory leaks and device hotplug ++ - powerpc/pseries: Correct cpu affinity for dlpar added cpus ++ - ext4: move check under lock scope to close a race. ++ - mmc: core: add missing pm event in mmc_pm_notify to fix hib restore ++ - nfsd: fix the check for confirmed openowner in nfs4_preprocess_stateid_op ++ - nilfs2: fix sanity check of btree level in nilfs_btree_root_broken() ++ - ocfs2: dlm: fix race between purge and get lock resource ++ - ACPI / init: Fix the ordering of acpi_reserve_resources() ++ - md/raid5: don't record new size if resize_stripes fails. ++ - ipvs: fix memory leak in ip_vs_ctl.c ++ - xhci: fix isoc endpoint dequeue from advancing too far on transaction error ++ - xhci: Solve full event ring by increasing TRBS_PER_SEGMENT to 256 ++ - xhci: gracefully handle xhci_irq dead device ++ - usb-storage: Add NO_WP_DETECT quirk for Lacie 059f:0651 devices ++ - ahci: un-staticize ahci_dev_classify ++ - ahci: avoton port-disable reset-quirk ++ - mac80211: move WEP tailroom size check ++ - KVM: MMU: fix CR4.SMEP=1, CR0.WP=0 with shadow pages ++ - ASoC: dapm: Modify widget stream name according to prefix ++ - ASoC: wm8960: fix "RINPUT3" audio route error ++ - ASoC: wm8994: correct BCLK DIV 348 to 384 ++ - Input: elantech - fix semi-mt protocol for v3 HW ++ - powerpc: Align TOC to 256 bytes ++ - dmi_scan: refactor dmi_scan_machine(), {smbios,dmi}_present() ++ - firmware: dmi_scan: Fix ordering of product_uuid ++ - ext4: check for zero length extent explicitly ++ - jbd2: fix r_count overflows leading to buffer overflow in journal recovery ++ - ALSA: hda - Add Conexant codecs CX20721, CX20722, CX20723 and CX20724 ++ - sd: Disable support for 256 byte/sector disks ++ - xen/events: don't bind non-percpu VIRQs with percpu chip ++ - USB: serial: ftdi_sio: Add support for a Motion Tracker Development Board ++ - crypto: s390/ghash - Fix incorrect ghash icv buffer handling. ++ - bridge: fix parsing of MLDv2 reports ++ - x86: bpf_jit: fix compilation of large bpf programs ++ - lguest: fix out-by-one error in address checking. ++ - fs/binfmt_elf.c:load_elf_binary(): return -EINVAL on zero-length mappings ++ - fs, omfs: add NULL terminator in the end up the token list ++ - d_walk() might skip too much ++ - ALSA: usb-audio: Fix invalid volume resolution for Logitech HD Webcam C525 ++ - ALSA: usb-audio: Add mic volume fix quirk for Logitech Quickcam Fusion ++ - target/pscsi: Don't leak scsi_host if hba is VIRTUAL_HOST ++ - x86_64: Fix strnlen_user() to not touch memory after specified maximum ++ - vfs: read file_handle only once in handle_to_path ++ - Input: elantech - fix detection of touchpads where the revision matches a known rate ++ - ALSA: usb-audio: add MAYA44 USB+ mixer control names ++ - ALSA: usb-audio: fix missing input volume controls in MAYA44 USB(+) ++ - USB: cp210x: add ID for HubZ dual ZigBee and Z-Wave dongle ++ - Input: elantech - fix for newer hardware versions (v7) ++ - Input: elantech - add support for newer (August 2013) devices ++ - Input: elantech - add support for newer elantech touchpads ++ - Input: elantech - support new ICs types for version 4 ++ - Input: elantech - add new icbody type ++ - MIPS: Fix enabling of DEBUG_STACKOVERFLOW ++ - bridge: fix multicast router rlist endless loop ++ - ring-buffer-benchmark: Fix the wrong sched_priority of producer ++ - tracing: Have filter check for balanced ops ++ - pipe: iovec: Fix memory corruption when retrying atomic copy as non-atomic ++ - udp: fix behavior of wrong checksums ++ - sctp: fix ASCONF list handling ++ - ipvs: kernel oops - do_ip_vs_get_ctl ++ - of: Add of_property_match_string() to find index into a string list ++ - dt: Add empty of_property_match_string() function ++ - powerpc: Make logical to real cpu mapping code endian safe ++ - powerpc: Don't skip ePAPR spin-table CPUs ++ - net: dp83640: fix broken calibration routine. ++ - unix/caif: sk_socket can disappear when state is unlocked ++ - xen: netback: read hotplug script once at start of day. ++ - bridge: fix br_stp_set_bridge_priority race conditions ++ - packet: read num_members once in packet_rcv_fanout() ++ - packet: avoid out of bounds read in round robin fanout ++ - neigh: do not modify unlinked entries ++ - sctp: Fix race between OOTB responce and route removal ++ - debugfs: Fix statfs() regression in 3.2.69 ++ - slub: refactoring unfreeze_partials() ++ - net: socket: Fix the wrong returns for recvmsg and sendmsg ++ - config: Enable NEED_DMA_MAP_STATE by default when SWIOTLB is selected ++ - Fix sb_edac compilation with 32 bits kernels ++ - sb_edac: Fix erroneous bytes->gigabytes conversion ++ - x86/reboot: Fix a warning message triggered by stop_other_cpus() ++ - include/linux/sched.h: don't use task->pid/tgid in same_thread_group/has_group_leader_pid ++ - __ptrace_may_access() should not deny sub-threads ++ - powerpc+sparc64/mm: Remove hack in mmap randomize layout ++ - softirq: reduce latencies ++ - Fix lockup related to stop_machine being stuck in __do_softirq. ++ - MIPS: Fix race condition in lazy cache flushing. ++ - MIPS: Octeon: Remove udelay() causing huge IRQ latency ++ - MIPS: Fix cpu_has_mips_r2_exec_hazard. ++ - MIPS: Octeon: Delete override of cpu_has_mips_r2_exec_hazard. ++ - UBI: fix soft lockup in ubi_check_volume() ++ - parisc: Provide __ucmpdi2 to resolve undefined references in 32 bit builds. ++ - staging: line6: avoid __sync_fetch_and_{and,or} ++ - sparc32,leon: fix leon build ++ - ACPICA: Tables: Change acpi_find_root_pointer() to use acpi_physical_address. ++ - ACPICA: Debug output: Update output for Processor object. ++ - ACPICA: Utilities: Cleanup to convert physical address printing formats. ++ - ACPICA: Utilities: Cleanup to remove useless ACPI_PRINTF/FORMAT_xxx helpers. ++ ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.71 ++ - hrtimer: Allow concurrent hrtimer_start() for self restarting timers ++ - s5h1420: fix a buffer overflow when checking userspace params ++ - cx24116: fix a buffer overflow when checking userspace params ++ - mtd: fix: avoid race condition when accessing mtd->usecount ++ - crypto: talitos - avoid memleak in talitos_alg_alloc() ++ - ASoC: wm8737: Fixup setting VMID Impedance control register ++ - ASoC: wm8903: Fix define for WM8903_VMID_RES_250K ++ - ASoC: wm8955: Fix setting wrong register for WM8955_K_8_0_MASK bits ++ - pktgen: adjust spacing in proc file interface output ++ - tty/serial: at91: RS485 mode: 0 is valid for delay_rts_after_send ++ - drm/radeon: take the mode_config mutex when dealing with hpds (v2) ++ - usb: dwc3: gadget: return error if command sent to DEPCMD register fails ++ - rcu: Correctly handle non-empty Tiny RCU callback list with none ready ++ - mtd: dc21285: use raw spinlock functions for nw_gpio_lock ++ - staging: rtl8712: prevent buffer overrun in recvbuf2recvframe ++ - usb: core: Fix USB 3.0 devices lost in NOTATTACHED state after a hub port reset ++ - staging: vt6655: device_rx_srv check sk_buff is NULL ++ - fixing infinite OPEN loop in 4.0 stateid recovery ++ - NFS: Fix size of NFSACL SETACL operations ++ - SUNRPC: Fix a memory leak in the backchannel code ++ - ipr: Increase default adapter init stage change timeout ++ - ath3k: Add support of 0489:e076 AR3012 device ++ - ath3k: add support of 13d3:3474 AR3012 device ++ - ath9k: fix DMA stop sequence for AR9003+ ++ - cdc-acm: Add support of ATOL FPrint fiscal printers ++ - regulator: core: fix constraints output buffer ++ - dmaengine: mv_xor: bug fix for racing condition in descriptors cleanup ++ - ASoC: wm8960: the enum of "DAC Polarity" should be wm8960_enum[1] ++ - ext4: fix race between truncate and __ext4_journalled_writepage() ++ - Disable write buffering on Toshiba ToPIC95 ++ - jbd2: split updating of journal superblock and marking journal empty ++ - jbd2: issue cache flush after checkpointing even with internal journal ++ - jbd2: use GFP_NOFS in jbd2_cleanup_journal_tail() ++ - jbd2: fix ocfs2 corrupt when updating journal superblock fails ++ - ideapad: fix software rfkill setting ++ - mmc: card: Fixup request missing in mmc_blk_issue_rw_rq ++ - nfs: increase size of EXCHANGE_ID name string buffer ++ - Bluetooth: ath3k: add support of 04ca:300f AR3012 device ++ - ext4: call sync_blockdev() before invalidate_bdev() in put_super() ++ - iio: DAC: ad5624r_spi: fix bit shift of output data value ++ - ext4: don't retry file block mapping on bigalloc fs with non-extent file ++ - watchdog: omap: assert the counter being stopped before reprogramming ++ - NET: ROSE: Don't dereference NULL neighbour pointer. ++ - bridge: multicast: restore router configuration on port link down/up ++ - fs: Fix S_NOSEC handling ++ - stmmac: troubleshoot unexpected bits in des0 & des1 ++ - mm: kmemleak: allow safe memory scanning during kmemleak disabling ++ - dell-laptop: Fix allocating & freeing SMI buffer page ++ - tracing/filter: Do not WARN on operand count going below zero ++ - tracing/filter: Do not allow infix to exceed end of string ++ - __bitmap_parselist: fix bug in empty string handling ++ - agp/intel: Fix typo in needs_ilk_vtd_wa() ++ - Btrfs: use kmem_cache_free when freeing entry in inode cache ++ - Btrfs: fix race between caching kthread and returning inode to inode cache ++ - crush: fix a bug in tree bucket decode ++ - fuse: initialize fc->release before calling it ++ - ALSA: usb-audio: Add MIDI support for Steinberg MI2/MI4 ++ - ACPICA: Tables: Fix an issue that FACS initialization is performed twice ++ - fs/buffer.c: support buffer cache allocations with gfp modifiers ++ - bufferhead: Add _gfp version for sb_getblk() ++ - ext4: avoid deadlocks in the writeback path by using sb_getblk_gfp ++ - netfilter: bridge: don't leak skb in error paths ++ - KVM: x86: make vapics_in_nmi_mode atomic ++ - KVM: x86: properly restore LVT0 ++ - 9p: forgetting to cancel request on interrupted zero-copy RPC ++ - ext4: replace open coded nofail allocation in ext4_free_blocks() ++ - dm btree remove: fix bug in redistribute3 ++ - dm thin: allocate the cell_sort_array dynamically ++ - USB: cp210x: add ID for Aruba Networks controllers ++ - dm btree: silence lockdep lock inversion in dm_btree_del() ++ - s390/sclp: clear upper register halves in _sclp_print_early ++ - drm: Check crtc x and y coordinates ++ - drm: add a check for x/y in drm_mode_setcrtc ++ - rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver ++ - mm: avoid setting up anonymous pages into file mapping ++ - net: do not process device backlog during unregistration ++ - net: call rcu_read_lock early in process_backlog ++ - 9p: don't leave a half-initialized inode sitting around ++ - s390/process: fix sfpc inline assembly ++ - Btrfs: fix file corruption after cloning inline extents ++ - rds: rds_ib_device.refcount overflow ++ - ata: pmp: add quirk for Marvell 4140 SATA PMP ++ - libata: add ATA_HORKAGE_BROKEN_FPDMA_AA quirk for HP 250GB SATA disk VB0250EAVER ++ - libata: add ATA_HORKAGE_NOTRIM ++ - libata: force disable trim for SuperSSpeed S238 ++ - libata: increase the timeout when setting transfer mode ++ - datagram: Factor out sk queue referencing ++ - drm/radeon: Don't flush the GART TLB if rdev->gart.ptr == NULL ++ - mac80211: clear subdir_stations when removing debugfs ++ - inet: frags: fix defragmented packet's IP header for af_packet ++ - usb: dwc3: Reset the transfer resource index on SET_INTERFACE ++ - netfilter: nf_conntrack: Support expectations in different zones ++ - usb: xhci: Bugfix for NULL pointer deference in xhci_endpoint_init() function ++ - xhci: Calculate old endpoints correctly on device reset ++ - xhci: report U3 when link is in resume state ++ - xhci: do not report PLC when link is in internal resume state ++ - usb-storage: ignore ZTE MF 823 card reader in mode 0x1225 ++ - tile: use free_bootmem_late() for initrd ++ - Input: usbtouchscreen - avoid unresponsive TSC-30 touch screen ++ - md/raid1: fix test for 'was read error from last working device'. ++ - iscsi-target: Fix use-after-free during TPG session shutdown ++ - niu: don't count tx error twice in case of headroom realloc fails ++ - vhost: actually track log eventfd file ++ - ALSA: usb-audio: add dB range mapping for some devices ++ - drm/radeon/combios: add some validation of lvds values ++ - x86/xen: Probe target addresses in set_aliased_prot() before the hypercall ++ ++ [ Jonathan Toppins ] ++ * config: fixup AUFS config change ++ * config: amd64: enable frame pointers (Closes: CM-7319) ++ * hwmon: cy8c3245r1: fix compile warnings (Closes: CM-7060) ++ * hwmon: max6620: fix compile warnings (Closes: CM-7060) ++ * misc: early_dma_alloc: fix compile warnings (Closes: CM-7060) ++ * eeprom: sff_8436_eeprom: fix compile warnings (Closes: CM-7060) ++ * mmc: card block fix compile warnings (Closes: CM-7060) ++ * netfilter: ERSPAN: fix compile warnings (Closes: CM-7059) ++ * ipv6: route: fix compile warnings no type defined (Closes: CM-7060) ++ * ipv6: route: fix compile warnings missing static (Closes: CM-7060) ++ ++ [ Ben Hutchings ] ++ * Revert "ACPICA: Utilities: split IO address types from data type models." ++ (Closes: CM-7611) ++ * Revert "libata: Ignore spurious PHY event on LPM policy change" ++ (Closes: CM-7611) ++ * USB: Avoid ABI change in 3.2.69 (Closes: CM-7611) ++ * bh: Avoid ABI change in 3.2.71 (Closes: CM-7611) ++ ++ [ Nikolay Aleksandrov ] ++ * bridge: fix multicast router rlist endless loop ++ * bridge: fix br_stp_set_bridge_priority race conditions ++ * config: amd64: increase HZ to 1000 (Closes: CM-7144) ++ * bridge: fix compiler warnings (Closes: CM-7697) ++ * bcmdrivers: gmac: change add_timer to mod_timer (Closes: CM-8052) ++ * bcmdrivers: gmac: initialize carrier properly (Closes: CM-7898) ++ * bcmdrivers: gmac: don't release mdio ownership (Closes: CM-7898) ++ ++ [ Satish Ashok ] ++ * bridge: multicast: restore router configuration on port link down/up ++ * bridge: fix setlink/dellink notifications (Closes: CM-8042) ++ * bridge: avoid duplicate notification for up/down/change netdev event ++ (Closes: CM-8042) ++ ++ [ Puneet ] ++ * x86: kernel/reboot: Celestica E1031 do "cold" reboot prevent hang ++ (Closes: CM-7826) ++ * pmbus: Added support for PMBUS based PSU fan PWM ++ * Revert "CUMULUS: s6000: Add driver for pmbus based power supply" ++ ++ [ Balakrishnan Raman ] ++ * vxlan: flush fdb entries on vxlan oper down (Closes: CM-7681) ++ ++ [ Han Shen ] ++ * Removed unused typedef to avoid "unused local typedef" warnings. ++ (Closes: CM-7060) ++ ++ [ Hannes Frederic Sowa ] ++ * ipv6: avoid high order memory allocations for /proc/net/ipv6_route ++ (Closes: CM-4910) ++ * ipv6: compare sernum when walking fib for /proc/net/ipv6_route as safety net ++ (Closes: CM-4910) ++ ++ [ Roopa Prabhu ] ++ * config: powerpc: disable sctp debug config (Closes: CM-8047) ++ * debian: use kernel release in package name instead of kernel version ++ (Closes: CM-7916) ++ ++ [ Andy Gospodarek ] ++ * bonding: fix stat calculation error when port stats are cleared ++ (Closes: CM-7385) ++ * debian: adding Breaks line to the kernel deb (Closes: CM-8083) ++ ++ [ Puneet Shenoy ] ++ * pmbus: Driver for Delta Power Supplies DPS460 and DPS200 ++ * pmbus: Add Driver for Lite-ON PS2471 Power Supply ++ * pmbus: Add driver support for Compuware CPR-4011-4M11/21 PSUs ++ * pmbus: Make the 3 pmbus drivers loadable modules ++ * quanta_lb9: Add PMBUS support for LB9. ++ * pmbus: Add support to read manufacturer info ++ ++ [ Vidya Sagar Ravipati ] ++ * QSFP+ eeprom: support eeprom parsing based on SFF-8472 (Closes: CM-7444) ++ ++ -- Jonathan Toppins Tue, 01 Dec 2015 13:21:19 -0500 ++ ++linux (3.2.68-6+cl25u2) CumulusLinux-2.5; urgency=medium ++ ++ [ Roopa Prabhu ] ++ * bridge: set is_local and is_static before fdb entry is added to the fdb hash ++ (Closes: CM-7942) ++ ++ [ Balakrishnan Raman ] ++ * bridge: fix NULL pointer dereference when fdb->dst is NULL (Closes: CM-7925) ++ ++ -- Jonathan Toppins Wed, 21 Oct 2015 18:55:44 -0500 ++ ++linux (3.2.68-6+cl25u1) CumulusLinux-2.5; urgency=medium ++ ++ [ Puneet ] ++ * x86: kernel/reboot: Celestica E1031 do "cold" reboot prevent hang ++ (Closes: CM-7826) ++ ++ -- Jonathan Toppins Wed, 14 Oct 2015 12:01:50 -0400 ++ ++linux (3.2.68-6) CumulusLinux-2.5; urgency=medium ++ ++ [ Roopa Prabhu ] ++ * bridge: fix NULL pointer dereference when fdb->dst is NULL (Closes: CM-7764) ++ ++ -- Jonathan Toppins Fri, 02 Oct 2015 17:06:35 -0400 ++ ++linux (3.2.68-5) CumulusLinux-2.5; urgency=medium ++ ++ * Revert "powerpc: enable usb controller on as6701" introduced by CM-7489 ++ (Closes: CM-7735) ++ ++ -- Jonathan Toppins Thu, 01 Oct 2015 12:11:45 -0400 ++ ++linux (3.2.68-4) CumulusLinux-2.5; urgency=medium ++ ++ [ Roopa Prabhu ] ++ * rtnetlink: fix event formatting for link up/down reports (Closes: CM-7680) ++ ++ [ Jonathan Toppins ] ++ * sysctl: ipv4: ipv6: fix max allowed default iif (Closes: CM-7719) ++ ++ [ Vidya Sagar Ravipati ] ++ * arm: make platforms use DTS (Closes: CM-6600) ++ ++ -- Jonathan Toppins Wed, 30 Sep 2015 17:03:09 -0400 ++ ++linux (3.2.68-3) CumulusLinux-2.5; urgency=medium ++ ++ [ Jonathan Toppins ] ++ * ipv6: addrconf: validate new MTU before applying it ++ (Closes: CM-7610, CVE-2015-0272) ++ * virtio-net: drop NETIF_F_FRAGLIST (Closes: CM-7610, CVE-2015-5156) ++ * vhost: actually track log eventfd file (Closes: CM-7610, CVE-2015-6252) ++ * RDS: verify the underlying transport exists before creating a connection ++ (Closes: CM-7610, CVE-2015-6937) ++ * powerpc: enable usb controller on as6701 (Closes: CM-7489) ++ ++ -- Jonathan Toppins Thu, 24 Sep 2015 22:59:39 -0400 ++ ++linux (3.2.68-2) CumulusLinux-2.5; urgency=medium ++ ++ [ Nikolay Aleksandrov ] ++ * bcmdrivers: gmac: remove unconditional netif_carrier_off (Closes: CM-6315) ++ ++ [ Jonathan Toppins ] ++ * config: fixup powerpc config due to incorrect crypto settings ++ (Closes: CM-7567) ++ * config: fixup amd64 config (Closes: CM-7567) ++ ++ -- Jonathan Toppins Tue, 22 Sep 2015 15:52:46 -0400 ++ ++linux (3.2.68-1) CumulusLinux-2.5; urgency=medium ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.66 ++ - net: sctp: fix memory leak in auth key management ++ - tcp: md5: remove spinlock usage in fast path ++ - tcp: md5: do not use alloc_percpu() ++ - ipv4: dst_entry leak in ip_send_unicast_reply() ++ - net: sctp: use MAX_HEADER for headroom reserve in output path ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.67 ++ - eCryptfs: Force RO mount when encrypted view is enabled ++ - ipv4: Remove all uses of LL_ALLOCATED_SPACE ++ - ipv6: Remove all uses of LL_ALLOCATED_SPACE ++ - ipv6: mld: fix add_grhead skb_over_panic for devs with large MTUs ++ - [s390*] KVM: flush CPU on load control ++ - UBI: Fix invalid vfree() ++ - drbd: merge_bvec_fn: properly remap bvm->bi_bdev ++ - PCI: Restore detection of read-only BARs ++ - genhd: check for int overflow in disk_expand_part_tbl() ++ - USB: cdc-acm: check for valid interfaces ++ - dm space map metadata: fix sm_bootstrap_get_nr_blocks() ++ - [x86] iommu/vt-d: Fix an off-by-one bug in __domain_mapping() ++ - KEYS: Fix stale key registration at error path ++ - Btrfs: fix fs corruption on transaction abort if device supports discard ++ - ncpfs: return proper error from NCP_IOC_SETROOT ioctl ++ - mac80211: fix multicast LED blinking and counter (regression in 3.2.65) ++ - genirq: Prevent proc race against freeing of irq descriptors ++ - decompress_bunzip2: off by one in get_next_block() ++ - [x86] tls: Disallow unusual TLS segments ++ - iscsi-target: Fail connection on short sendmsg writes ++ - ceph: introduce global empty snap context ++ - [x86] tls: Don't validate lm in set_thread_area() after all ++ - ocfs2: fix journal commit deadlock ++ - udf: Verify i_size when loading inode ++ - udf: Verify symlink size before loading it ++ - udf: Treat symlink component of type 2 as / ++ - udf: Check path length when reading symlink ++ - udf: Check component length before reading it ++ - crypto: af_alg - fix backlog handling ++ - Revert "tcp: Apply device TSO segment limit earlier" ++ (regression in 3.2.30) ++ - virtio_pci: defer kfree until release callback ++ - mm: propagate error from stack expansion even for guard page ++ - time: settimeofday: Validate the values of tv from user ++ - regulator: core: fix race condition in regulator_put() ++ - mm: prevent endless growth of anon_vma hierarchy ++ - mm: protect set_page_dirty() from ongoing truncation ++ - HID: roccat: potential out of bounds in pyra_sysfs_write_settings() ++ - USB: console: fix potential use after free ++ - mm: Don't count the stack guard page towards RLIMIT_STACK ++ - mm: fix corner case in anon_vma endless growing prevention ++ - can: dev: fix crtlmode_supported check ++ - net: sctp: fix race for one-to-many sockets in sendmsg's auto associate ++ - libata: allow sata_sil24 to opt-out of tag ordered submission ++ (regression in 3.2.62) ++ - nl80211: fix per-station group key get/del and memory leak ++ - vm: add VM_FAULT_SIGSEGV handling support ++ - vm: make stack guard page errors return VM_FAULT_SIGSEGV rather than ++ SIGBUS ++ - ACPI / EC: Fix regression due to conflicting firmware behavior between ++ Samsung and Acer. (regression in 3.2.63) ++ - [s390*] 3215: fix tty output containing tabs (Closes: #758264) ++ - fsnotify: next_i is freed during fsnotify_unmount_inodes. ++ - PCI: Handle read-only BARs on AMD CS553x devices ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.68 ++ - mm: pagewalk: call pte_hole() for VM_PFNMAP during walk_page_range ++ (regression in 3.2.46) ++ - nilfs2: fix deadlock of segment constructor over I_SYNC flag ++ - staging: comedi: cb_pcidas64: fix incorrect AI range code handling ++ - time: adjtimex: Validate the ADJ_FREQUENCY values ++ - ntp: Fixup adjtimex freq validation on 32-bit systems ++ - Bluetooth: ath3k: workaround the compatibility issue with xHCI controller ++ (maybe fixes #778463) ++ ++ [ Ben Hutchings ] ++ * drm, agp: Update to 3.4.106: ++ - [x86] drm/vmwgfx: Filter out modes those cannot be supported by the ++ current VRAM size. ++ - drm/radeon: add missing crtc unlock when setting up the MC ++ * [rt] Update to 3.2.68-rt99: ++ - Replace the plist functions with rt_mutex_enqueue{_pi}() and ++ rt_mutex_dequeue{_pi}() like upstream -rt does ++ - rtmutex: Simplify rtmutex_slowtrylock() ++ - rtmutex: Simplify and document try_to_take_rtmutex() ++ - rtmutex: No need to keep task ref for lock owner check ++ - rtmutex: Clarify the boost/deboost part ++ - rtmutex: Document pi chain walk ++ - rtmutex: Simplify remove_waiter() ++ - rtmutex: Confine deadlock logic to futex ++ - rtmutex: Cleanup deadlock detector debug logic ++ - rtmutex: Avoid pointless requeueing in the deadlock detection chain walk ++ - futex: Make unlock_pi more robust ++ - futex: Use futex_top_waiter() in lookup_pi_state() ++ - futex: Split out the waiter check from lookup_pi_state() ++ - futex: Split out the first waiter attachment from lookup_pi_state() ++ - futex: Simplify futex_lock_pi_atomic() and make it more robust ++ - rt-mutex: avoid a NULL pointer dereference on deadlock ++ - x86: UV: raw_spinlock conversion ++ - scheduling while atomic in cgroup code ++ - work-simple: Simple work queue implemenation ++ - sunrpc: make svc_xprt_do_enqueue() use get_cpu_light() ++ - fs,btrfs: fix rt deadlock on extent_buffer->lock ++ * hpsa: Update device ID tables (Closes: #781548) ++ * NFSv4: Fix oops in nfs4_handle_exception when server returns ++ NFS4ERR_OPENMODE (Closes: #731439) ++ * netfilter: ipset: Check and reject crazy /0 input parameters ++ (Closes: #732689) ++ * udp: fix behavior of wrong checksums (CVE-2015-5364, CVE-2015-5366) ++ * sctp: fix ASCONF list handling (CVE-2015-3212) ++ * [x86] bpf_jit: fix compilation of large bpf programs (CVE-2015-4700) ++ * sg_start_req(): make sure that there's not too many elements in iovec ++ (CVE-2015-5707) ++ * md: use kzalloc() when bitmap is disabled (CVE-2015-5697) ++ * pipe: iovec: Fix memory corruption when retrying atomic copy as non-atomic ++ (CVE-2015-1805) ++ * udf: Remove repeated loads blocksize ++ * udf: Check length of extended attributes and allocation descriptors ++ (CVE-2015-4167) ++ * ipv4: Missing sk_nulls_node_init() in ping_unhash(). (CVE-2015-3636) ++ * IB/core: Prevent integer overflow in ib_umem_get address arithmetic ++ (CVE-2014-8159) ++ * netfilter: nf_conntrack: reserve two bytes for nf_ct_ext->len ++ (CVE-2014-9715) ++ * net: llc: use correct size for sysctl timeout entries (CVE-2015-2041) ++ * net: rds: use correct size for max unacked packets and bytes ++ (CVE-2015-2042) ++ * xen-pciback: limit guest control of command register (CVE-2015-2150) ++ * [amd64] asm/entry: Remove a bogus 'ret_from_fork' optimization ++ (CVE-2015-2830) ++ * ipv6: Don't reduce hop limit for an interface (CVE-2015-2922) ++ * [x86] crypto: aesni - fix memory usage in GCM decryption (Closes: #782561) ++ (CVE-2015-3331) ++ * fs: take i_mutex during prepare_binprm for set[ug]id executables ++ (CVE-2015-3339) ++ * dvb-usb-af9005: mark as broken ++ * video: Remove nvidiafb and rivafb ++ * Include package version along with kernel release in stack traces ++ * af9005: Use request_firmware() to load register init script ++ * cs46xx: Use request_firmware() for old DSP code ++ * aufs: mark as staging ++ * Partially revert "MIPS: Add -Werror to arch/mips/Kbuild" ++ * Fix console selection in PowerPC LPAR environment ++ * af_802154: Disable auto-loading as mitigation against local exploits ++ * rds: Disable auto-loading as mitigation against local exploits ++ * decnet: Disable auto-loading as mitigation against local exploits ++ * dm: Deal with merge_bvec_fn in component devices better ++ * Kbuild: kconfig: Verbose version of --listnewconfig ++ * sched: Do not enable autogrouping by default ++ * cgroups: Allow memory cgroup support to be included but disabled ++ * cgroups: Document the Debian memory resource controller config change ++ * x86: Add amilo-rfkill driver for some Fujitsu-Siemens Amilo laptops ++ * bcma: Do not claim PCI device IDs also claimed by brcmsmac ++ * staging: lirc_serial: Fix bogus error codes ++ * x86: memtest: WARN if bad RAM found ++ * PM / Hibernate: Implement compat_ioctl for /dev/snapshot ++ * ARM: Remove use of possibly-undefined BUILD_BUG_ON in ++ * topology: Provide CPU topology in sysfs in !SMP configurations ++ * cpu: Do not return errors from cpu_dev_init() which will be ignored ++ * cpu: Register a generic CPU device on architectures that currently do not ++ * x86/cpu: Fix overrun check in arch_print_cpu_modalias() ++ * x86/cpu: Clean up modalias feature matching ++ * intel_idle: Fix ID for Nehalem-EX Xeon in device ID table ++ * powernow-k7: Fix CPU family number ++ * powernow-k6: Really enable auto-loading ++ * intel_idle: Revert change of auto_demotion_disable_flags for Nehalem ++ * Partially revert "cpufreq: Add support for x86 cpuinfo auto loading v4" ++ * ahci: Add JMicron 362 device IDs ++ * perf: Hide ABI change in 3.2.30 ++ * iwlwifi: Do not request unreleased firmware ++ * hid: Avoid ABI change in 3.2.31 ++ * xfrm: Avoid ABI change in 3.2.31 ++ * fs-writeback: Avoid ABI changes in 3.2.32 ++ * ALSA: avoid ABI change in 3.2.34 ++ * rtnetlink: avoid ABI change in 3.2.34 ++ * mm: avoid ABI change in 3.2.33 ++ * cassini: Make missing firmware non-fatal ++ * firmware_class: Log every success and failure against given device ++ * firmware: Remove redundant log messages from drivers ++ * audit: Increase maximum number of names logged per syscall to 30 ++ * net: Avoid ABI break in 3.2.37 ++ * net: define netdev_features_t ++ * ethernet: define eth_hw_add_random() ++ * alx: remove atl1c devices ++ * alx: mark as staging ++ * Revert "VM: add vm_munmap() helper function" in i810 ++ * nouveau: ACPI support is dependent on X86 ++ * radeon: Firmware is required for DRM and KMS on R600 onward ++ * mm: Try harder to allocate vmemmap blocks ++ * efi: Avoid ABI change in 3.2.38 ++ * pps: avoid ABI change in 3.2.40 ++ * x86/efi: Autoload efivars ++ * dm: Avoid ABI change in 3.2.41 ++ * skb: avoid ABI change in 3.2.42 ++ * tracing: Avoid ABI change in 3.2.42 ++ * inet_frag: Avoid ABI change in 3.2.42 ++ * x86, mm: Avoid ABI change in 3.2.44 ++ * jbd2: Avoid ABI change in 3.2.45 ++ * ipw2200: Fix order of device registration ++ * ipw2100: Fix order of device registration ++ * kbuild: Fix missing ' ' for NEW symbols in yes "" | make oldconfig >conf.new ++ * viafb: Autoload on OLPC XO 1.5 only ++ * perf: Avoid ABI change in 3.2.49 ++ * tracing: Avoid ABI change in 3.10.7 ++ * mm: Avoid ABI change in 3.2.51 ++ * mvsas: Recognise device/subsystem 9485/9485 as 88SE9485 ++ * aufs: Mark ad debian version ++ * perf: Avoid ABI change in 3.2.52 ++ * inetpeer: Avoid ABI change in 3.2.52 ++ * sched: Avoid ABI change in 3.2.55 ++ * net: Avoid ABI change in 3.2.55 ++ * mm: Avoid ABI change in 3.2.55 ++ * net: Avoid ABI change in 3.2.57 ++ * Revert "ALSA: Enable CONFIG_ZONE_DMA for smaller PCI DMA masks" ++ * drivers/net/ethernet: Fix (nearly-)kernel-doc comments for various functions ++ * e1000e: Validate hwtstamp_config completely before applying it ++ * e1000e: Add config symbol for PTP functionality ++ * drivers/net/ethernet: Fix (nearly-)kernel-doc comments for various functions ++ * igb: Disable EEE ++ * Revert "perf/x86/amd/ibs: Fix waking up from S3 for AMD family 10h" ++ * libata: Avoid ABI change in 3.2.59 ++ * dmi: Avoid ABI change in 3.2.59 ++ * PCI: msi_desc: remove unused kobject ++ * ALSA: Avoid ABI change for CVE-2014-4652 fix ++ * irq: Avoid ABI change in 3.2.61 ++ * ptrace: Avoid ABI change in 3.2.61 ++ * trace/syscall: Avoid ABI change in 3.2.61 ++ * SCSI: Avoid ABI change in 3.2.61 ++ * libata: Avoid ABI change in 3.2.62 ++ * ip_ident: Avoid ABI change in 3.2.63 ++ * SCSI: Avoid ABI change in 3.2.62 ++ * nlattr: Avoid ABI change in 3.2.61 ++ * sp5100_tco: Reject SB8x0 chips ++ * drivers/net: Avoid ABI change for UFO/IPv6 fix ++ * regulatory: Avoid ABI change in 3.2.64 ++ * ceph: Avoid ABI change in 3.2.64 ++ * perf: Avoid ABI change in 3.2.65 ++ * mm/truncate: Avoid ABI change in 3.2.65 ++ * aufs: move d_rcu from overlapping d_child to overlapping d_alias ++ * vfs: Avoid ABI change for dentry union changes ++ * sock: Fix ABI change in 3.2.67 ++ * rmap: Fix ABI change in 3.2.67 ++ * pipe: iovec: Fix memory corruption when retrying atomic copy as non-atomic ++ * ethtool: Make more commands available to unprivileged processes ++ ++ [ Anonymous Debian Developer ] ++ * debian/dfsg/arch-powerpc-platforms-8xx-ucode-disable ++ * debian/dfsg/drivers-net-appletalk-cops ++ * debian/dfsg/drivers-staging-wlags49_h2-disable ++ * debian/dfsg/drivers-staging-wlags49_h25-disable ++ * debian/dfsg/r8192e-remove-firmware-again ++ * debian/dfsg/firmware-cleanup ++ * debian/dfsg/sound-pci ++ * debian/dfsg/files-1 ++ * features/all/aufs3/aufs3-base ++ * features/all/aufs3/aufs3-standalone ++ * features/all/aufs3/aufs3-kbuild ++ * features/all/aufs3/aufs3-add ++ * features/all/aufs3/aufs3-fix-export-__devcgroup_inode_permission ++ * debian/arch-sh4-fix-uimage-build ++ * features/all/xen/microcode-typo ++ * features/all/drm/drm-3.4 ++ ++ [ Bastian Blank ] ++ * kbuild: Make the toolchain variables easily overwritable ++ * DocBook: Make Documentation/DocBook -j clean ++ * Allow access to sensitive SysRq keys to be restricted by default ++ ++ [ dann frazier ] ++ * Hardcode arch script output ++ ++ [ Martin Michlmayr ] ++ * Disable Advansys ++ * ARM: Kirkwood: Recognize A1 revision of 6282 chip ++ ++ [ Arnaud Patard ] ++ * ixp4xx: add io{read,write}{16,32}be functions ++ * ARM: Kirkwood: Add configuration for MPP12 as GPIO ++ ++ [ Rob Herring ] ++ * ARM: 7169/1: topdown mmap support ++ ++ [ Seth Forshee ] ++ * Input: ALPS - move protocol information to Documentation ++ * Input: ALPS - add protocol version field in alps_model_info ++ * Input: ALPS - remove assumptions about packet size ++ * Input: ALPS - add support for protocol versions 3 and 4 ++ * Input: ALPS - add semi-MT support for v3 protocol ++ ++ [ Nadav Har'El ] ++ * KVM: nVMX: Add KVM_REQ_IMMEDIATE_EXIT ++ * KVM: nVMX: Fix warning-causing idt-vectoring-info behavior ++ ++ [ Jean Delvare ] ++ * hwmon: (it87) Add IT8728F support ++ ++ [ Kees Cook ] ++ * fs: add link restrictions ++ * fs: add link restriction audit reporting ++ * debugfs: more tightly restrict default mount mode ++ ++ [ Sasha Levin ] ++ * fs: handle failed audit_log_start properly ++ * fs: prevent use after free in auditing when symlink following was denied ++ * net: codel: fix build errors ++ * vfs: read file_handle only once in handle_to_path ++ * net: llc: use correct size for sysctl timeout entries ++ * net: rds: use correct size for max unacked packets and bytes ++ ++ [ K. Y. Srinivasan ] ++ * HID: Move the hid-hyperv driver out of staging ++ * Staging: hv: storvsc: Use mempools to allocate struct storvsc_cmd_request ++ * Staging: hv: storvsc: Cleanup error handling in the probe function ++ * Staging: hv: storvsc: Fixup the error when processing SET_WINDOW command ++ * Staging: hv: storvsc: Fix error handling storvsc_host_reset() ++ * Staging: hv: storvsc: Use the accessor function shost_priv() ++ * Staging: hv: storvsc: Use the unlocked version queuecommand ++ * Staging: hv: storvsc: use the macro KBUILD_MODNAME ++ * Staging: hv: storvsc: Get rid of an unnecessary forward declaration ++ * Staging: hv: storvsc: Upgrade the vmstor protocol version ++ * Staging: hv: storvsc: Support hot add of scsi disks ++ * Staging: hv: storvsc: Support hot-removing of scsi devices ++ * Staging: hv: vmbus: Support building the vmbus driver as part of the kernel ++ * Staging: hv: mousevsc: Remove the mouse driver from the staging tree ++ * Staging: hv: storvsc: Disable clustering ++ * Staging: hv: storvsc: Cleanup storvsc_device_alloc() ++ * Staging: hv: storvsc: Fix a bug in storvsc_command_completion() ++ * Staging: hv: storvsc: Fix a bug in copy_from_bounce_buffer() ++ * Staging: hv: storvsc: Implement per device memory pools ++ * HID: hv_mouse: Properly add the hid device ++ * Staging: hv: storvsc: Fix a bug in create_bounce_buffer() ++ * Drivers: hv: Fix a memory leak ++ * Drivers: hv: Make the vmbus driver unloadable ++ * Drivers: hv: Get rid of an unnecessary check in hv.c ++ * drivers: hv: Get rid of some unnecessary code ++ * HID: hyperv: Properly disconnect the input device ++ * drivers: hv: kvp: Add/cleanup connector defines ++ * drivers: hv: kvp: Move the contents of hv_kvp.h to hyperv.h ++ * Staging: hv: storvsc: Cleanup some comments ++ * Staging: hv: storvsc: Cleanup storvsc_probe() ++ * Staging: hv: storvsc: Cleanup storvsc_queuecommand() ++ * Staging: hv: storvsc: Introduce defines for srb status codes ++ * Staging: hv: storvsc: Cleanup storvsc_host_reset_handler() ++ * Staging: hv: storvsc: Move and cleanup storvsc_remove() ++ * Staging: hv: storvsc: Add a comment to explain life-cycle management ++ * Staging: hv: storvsc: Get rid of the on_io_completion in hv_storvsc_request ++ * Staging: hv: storvsc: Rename the context field in hv_storvsc_request ++ * Staging: hv: storvsc: Miscellaneous cleanup of storvsc driver ++ * Staging: hv: storvsc: Cleanup the code for generating protocol version ++ * Staging: hv: storvsc: Cleanup some protocol related constants ++ * Staging: hv: storvsc: Get rid of some unused defines ++ * Staging: hv: storvsc: Consolidate the request structure ++ * Staging: hv: storvsc: Consolidate all the wire protocol definitions ++ * drivers: hv: Cleanup the kvp related state in hyperv.h ++ * tools: hv: Use hyperv.h to get the KVP definitions ++ * drivers: hv: kvp: Cleanup the kernel/user protocol ++ * drivers: hv: Increase the number of VCPUs supported in the guest ++ * Staging: hv: storvsc: Move the storage driver out of the staging area ++ * Drivers: hv: Add new message types to enhance KVP ++ * Drivers: hv: Support the newly introduced KVP messages in the driver ++ * Tools: hv: Fully support the new KVP verbs in the user level daemon ++ * Tools: hv: Support enumeration from all the pools ++ ++ [ Thomas Meyer ] ++ * staging: hv: Use kmemdup rather than duplicating its implementation ++ * Staging: line6: Use kmemdup rather than duplicating its implementation ++ ++ [ Bart Van Assche ] ++ * hv: Add Kconfig menu entry ++ ++ [ Haiyang Zhang ] ++ * staging: hv: move hv_netvsc out of staging area ++ * net/hyperv: Fix long lines in netvsc.c ++ * net/hyperv: Add support for promiscuous mode setting ++ * net/hyperv: Fix the stop/wake queue mechanism ++ * net/hyperv: Remove unnecessary kmap_atomic in netvsc driver ++ * net/hyperv: Add NETVSP protocol version negotiation ++ * net/hyperv: Add support for jumbo frame up to 64KB ++ * net/hyperv: Use netif_tx_disable() instead of netif_stop_queue() when necessary ++ * net/hyperv: Fix the page buffer when an RNDIS message goes beyond page boundary ++ * net/hyperv: Convert camel cased variables in rndis_filter.c to lower cases ++ * net/hyperv: Correct the assignment in netvsc_recv_callback() ++ * net/hyperv: Remove the unnecessary memset in rndis_filter_send() ++ * net/hyperv: Use the built-in macro KBUILD_MODNAME for this driver ++ * net/hyperv: Fix data corruption in rndis_filter_receive() ++ * net/hyperv: Add support for vlan trunking from guests ++ * net/hyperv: Fix the code handling tx busy ++ ++ [ Greg Kroah-Hartman ] ++ * Staging: hv: update TODO file ++ * mce: fix warning messages about static struct mce_device ++ * x86/mce: Convert static array of pointers to per-cpu variables ++ * driver core: cpu: remove kernel warning when removing a cpu ++ * driver-core: cpu: fix kobject warning when hotplugging a cpu ++ * driver core: remove __must_check from device_create_file ++ * USB: Add helper macro for usb_driver boilerplate ++ * PCI: Add helper macro for pci_register_driver boilerplate ++ * Staging: line6: remove unneeded initialization ++ * Staging: line6: only allocate a buffer if it is needed ++ * Staging: line6: remove teardown code from module_exit path ++ * Staging: line6: use module_usb_driver() ++ * staging: line6: toneport.c: remove err() usage ++ * drivers/net: fix up function prototypes after __dev* removals ++ * drivers/net: fix up function prototypes after __dev* removals ++ * PCI/MSI: Export MSI mode using attributes, not kobjects ++ * PCI/MSI: Check kmalloc() return value, fix leak of name ++ * PCI/MSI: Fix leak of msi_attrs ++ ++ [ Wei Yongjun ] ++ * net/hyperv: fix possible memory leak in do_set_multicast() ++ * net/hyperv: rx_bytes should account the ether header size ++ * net/hyperv: fix the issue that large packets be dropped under bridge ++ ++ [ Eric Dumazet ] ++ * net/hyperv: fix erroneous NETDEV_TX_BUSY use ++ * be2net: allocate more headroom in incoming skbs ++ * be2net: dont pull too much data in skb linear part ++ * net: introduce skb_flow_dissect() ++ * flow_dissector: use a 64bit load/store ++ * codel: Controlled Delay AQM ++ * codel: use Newton method instead of sqrt() and divides ++ * fq_codel: Fair Queue Codel AQM ++ * codel: use u16 field instead of 31bits for rec_inv_sqrt ++ * fq_codel: should use qdisc backlog as threshold ++ * codel: refine one condition to avoid a nul rec_inv_sqrt ++ * bql: fix CONFIG_XPS=n build ++ * sfc: fix race in efx_enqueue_skb_tso() ++ * bnx2: Support for byte queue limits ++ * igb: Add support for byte queue limits. ++ * net: remove netdev_alloc_page and use __GFP_COLD ++ * igb: reduce Rx header size ++ * udp: fix behavior of wrong checksums (Closes: CM-7048) ++ * bridge: fix lockdep splat (Closes: CM-7359) ++ ++ [ Cong Wang ] ++ * hv: remove the second argument of k[un]map_atomic() ++ * net: remove the second argument of k[un]map_atomic() ++ ++ [ Andy Whitcroft ] ++ * libata: add a host flag to ignore detected ATA devices ++ * ata_piix: defer disks to the Hyper-V drivers by default ++ ++ [ Olaf Hering ] ++ * ata_piix: reenable MS Virtual PC guests ++ ++ [ Matt Fleming ] ++ * x86: Add missing bzImage fields to struct setup_header ++ * x86: Don't use magic strings for EFI loader signature ++ * efi.h: Add struct definition for boot time services ++ * efi.h: Add efi_image_loaded_t ++ * efi.h: Add allocation types for boottime->allocate_pages() ++ * efi.h: Add graphics protocol guids ++ * efi.h: Add boottime->locate_handle search types ++ * efi: Add EFI file I/O data types ++ * x86, efi: EFI boot stub support ++ * tools/include: Add byteshift headers for endian access ++ * x86, mkpiggy: Don't open code put_unaligned_le32() ++ * x86, boot: Restrict CFLAGS for hostprogs ++ * x86, efi: Fix endian issues and unaligned accesses ++ * x86, efi: Add dedicated EFI stub entry point ++ * x86, efi: Fix processor-specific memcpy() build error ++ ++ [ Maarten Lankhorst ] ++ * x86, efi: Break up large initrd reads ++ ++ [ Dan Carpenter ] ++ * x86, efi: Fix pointer math issue in handle_ramdisks() ++ * Input: wacom - check for allocation failure in probe() ++ * Staging: line6: NULL dereference in dev_err() ++ ++ [ H. Peter Anvin ] ++ * x86, boot: Correct CFLAGS for hostprogs ++ * x86, cpufeature: Rename X86_FEATURE_DTS to X86_FEATURE_DTHERM ++ ++ [ Matthew Garrett ] ++ * efi: Build EFI stub with EFI-appropriate options ++ * kmsg_dump: don't run on non-error paths by default ++ ++ [ Chris Bagwell ] ++ * Input: wacom - cleanup feature report for bamboos ++ * Input: wacom - remove unused bamboo HID parsing ++ * Input: wacom - add some comments to wacom_parse_hid ++ * Input: wacom - read 3rd gen Bamboo Touch HID data ++ * Input: wacom - 3rd gen Bamboo P&Touch packet support ++ * Input: wacom - ignore unwanted bamboo packets ++ * Input: wacom - add missing LEDS_CLASS to Kconfig ++ * Input: wacom - isolate input registration ++ * Input: wacom - wireless monitor framework ++ * Input: wacom - create inputs when wireless connect ++ * Input: wacom - wireless battery status ++ ++ [ Jason Gerecke ] ++ * Input: wacom - add support for Cintiq 24HD ++ * Input: wacom - add LED support for Cintiq 24HD ++ * Input: wacom - fix 3rd-gen Bamboo MT when 4+ fingers are in use ++ * Input: wacom - fix physical size calculation for 3rd-gen Bamboo ++ * Input: wacom - add basic Intuos5 support ++ * Input: wacom - add Intuos5 Touch Ring/ExpressKey support ++ * Input: wacom - add Intuos5 Touch Ring LED support ++ * Input: wacom - add Intuos5 multitouch sensor support ++ ++ [ Ping Cheng ] ++ * Input: wacom - use BTN_TOOL_FINGER to indicate touch device type ++ * Input: wacom - use switch statement for wacom_tpc_irq() ++ * Input: wacom - retrieve maximum number of touch points ++ * Input: wacom - add 0xE5 (MT device) support ++ * Input: wacom - fix retrieving touch_max bug ++ * Input: wacom - don't retrieve touch_max when it is predefined ++ * wacom: do not request tablet data on MT Tablet PC pen interface ++ * Input: wacom - TPC2FG doesn't store touch id for slots ++ ++ [ Dmitry Torokhov ] ++ * Input: wacom - return proper error if usb_get_extra_descriptor() fails ++ ++ [ Diego Calleja ] ++ * Input: wacom - fix touch support for Bamboo Fun CTH-461 ++ ++ [ John Li ] ++ * rt2x00:Add debug message for new chipset ++ * rt2x00:Add RT5372 chipset support ++ ++ [ Rick Jones ] ++ * sweep the floors and convert some .get_drvinfo routines to strlcpy ++ * Sweep the last of the active .get_drvinfo floors under ethernet/ ++ * net: sweep-up some straglers in strlcpy conversion of .get_drvinfo routines ++ * Sweep the last of the active .get_drvinfo floors under ethernet/ ++ ++ [ Sathya Perla ] ++ * be2net: init (vf)_if_handle/vf_pmac_id to handle failure scenarios ++ * be2net: stop checking the UE registers after an EEH error ++ * be2net: don't log more than one error on detecting EEH/UE errors ++ * be2net: stop issuing FW cmds if any cmd times out ++ * be2net: fix ethtool ringparam reporting ++ * be2net: refactor/cleanup vf configuration code ++ * be2net: create RSS rings even in multi-channel configs ++ * be2net: add descriptions for stat counters reported via ethtool ++ * be2net: event queue re-design ++ * be2net: cancel be_worker during EEH recovery ++ * be2net: fix tx completion cleanup ++ * be2net: reset queue address after freeing ++ * be2net: enable RSS for ipv6 pkts ++ * be2net: update driver version ++ * be2net: avoid disabling sriov while VFs are assigned ++ * be2net: do not modify PCI MaxReadReq size ++ * be2net: fix reporting number of actual rx queues ++ * be2net: do not use SCRATCHPAD register ++ ++ [ Padmanabh Ratnakar ] ++ * be2net: Fix TX queue create for Lancer ++ * be2net: add register dump feature for Lancer ++ * be2net: Add EEPROM dump feature for Lancer ++ * be2net: Fix VLAN promiscous mode for Lancer ++ * be2net: Use V1 query link status command for lancer ++ * be2net: Move to new SR-IOV implementation in Lancer ++ * be2net: Fix error recovery paths ++ * be2net: Add error handling for Lancer ++ * be2net: Use new hash key ++ * be2net: Fix non utilization of RX queues ++ * be2net: Fix INTx processing for Lancer ++ * be2net: Fix link status query command ++ * be2net: Use new implementation of get mac list command ++ * be2net: Fix VLAN/multicast packet reception ++ * be2net: Fix FW download in Lancer ++ * be2net: Fix ethtool self test for Lancer ++ * be2net: Fix traffic stall INTx mode ++ * be2net: Fix Lancer statistics ++ * be2net: Fix wrong status getting returned for MCC commands ++ * be2net: Fix FW download for BE ++ * be2net: Enable RSS UDP hashing for Lancer and Skyhawk ++ ++ [ Ivan Vecera ] ++ * be2net: netpoll support ++ ++ [ Ajit Khaparde ] ++ * be2net: update some counters to display via ethtool ++ * be2net: workaround to fix a bug in BE ++ * be2net: Add support for Skyhawk cards ++ * be2net: fix be_vlan_add/rem_vid ++ * be2net: fix range check for set_qos for a VF ++ * be2net: query link status in be_open() ++ * be2net: enable WOL by default if h/w supports it ++ * be2net: Program secondary UC MAC address into MAC filter ++ * be2net: Fix number of vlan slots in flex mode ++ * be2net: fix programming of VLAN tags for VF ++ * be2net: fix ethtool get settings ++ * be2net: Ignore status of some ioctls during driver load ++ * be2net: fix speed displayed by ethtool on certain SKUs ++ * be2net: update the driver version ++ ++ [ stephen hemminger ] ++ * netdev: make net_device_ops const ++ * sky2: add bql support ++ * skge: add byte queue limit support ++ * intel: make wired ethernet driver message level consistent (rev2) ++ * intel: make wired ethernet driver message level consistent (rev2) ++ ++ [ Roland Dreier ] ++ * be2net: Remove unused OFFSET_IN_PAGE() macro ++ ++ [ Somnath Kotur ] ++ * be2net: Fix to not set link speed for disabled functions of a UMC card ++ * be2net: Fix to apply duplex value as unknown when link is down. ++ * be2net: Record receive queue index in skb to aid RPS. ++ * be2net: Fix EEH error reset before a flash dump completes ++ * be2net: Explicitly clear the reserved field in the Tx Descriptor ++ * be2net: Regression bug wherein VFs creation broken for multiple cards. ++ * be2net: Fix to trim skb for padded vlan packets to workaround an ASIC Bug ++ ++ [ Sarveshwar Bandi ] ++ * be2net: reduce gso_max_size setting to account for ethernet header. ++ * be2net: Fix to parse RSS hash from Receive completions correctly. ++ ++ [ Vasundhara Volam ] ++ * be2net: Increase statistics structure size for skyhawk. ++ ++ [ Li RongQing ] ++ * be2net: Fix Endian ++ ++ [ Amerigo Wang ] ++ * netpoll: revert 6bdb7fe3104 and fix be_poll() instead ++ ++ [ Jesper Dangaard Brouer ] ++ * net: flow_dissector.c missing include linux/export.h ++ ++ [ Geert Uytterhoeven ] ++ * net/codel: Add missing #include ++ * treewide: relase -> release ++ ++ [ John Johansen ] ++ * AppArmor: compatibility patch for v5 interface ++ * apparmor: remove advertising the support of network rules from compat iface ++ ++ [ Vasiliy Kulikov ] ++ * procfs: parse mount options ++ * procfs: add hidepid= and gid= mount options ++ * proc: fix mount -t proc -o AAA ++ ++ [ Xiaotian Feng ] ++ * proc: fix null pointer deref in proc_pid_permission() ++ ++ [ Kay Sievers ] ++ * driver-core: implement 'sysdev' functionality for regular devices and buses ++ * cpu: convert 'cpu' and 'machinecheck' sysdev_class to a regular subsystem ++ ++ [ Srivatsa S. Bhat ] ++ * x86/mce: Fix CPU hotplug and suspend regression related to MCE ++ ++ [ Andi Kleen ] ++ * Add driver auto probing for x86 features v4 ++ * crypto: Add support for x86 cpuid auto loading for x86 crypto drivers ++ * intel-idle: convert to x86_cpu_id auto probing ++ * ACPI: Load acpi-cpufreq from processor driver automatically ++ * HWMON: Convert via-cputemp to x86 cpuid autoprobing ++ * HWMON: Convert coretemp to x86 cpuid autoprobing ++ * cpufreq: Add support for x86 cpuinfo auto loading v4 ++ * igb: limit udelay for phy changes to 10000us ++ ++ [ Thomas Renninger ] ++ * CPU: Introduce ARCH_HAS_CPU_AUTOPROBE and X86 parts ++ * X86: Introduce HW-Pstate scattered cpuid feature ++ ++ [ Alan Cox ] ++ * cpufreq/gx: Fix the compile error ++ ++ [ Steven Rostedt ] ++ * tracing/mm: Move include of trace/events/kmem.h out of header into slab.c ++ ++ [ Paul Mundt ] ++ * sh: Fix up store queue code for subsys_interface changes. ++ ++ [ Jason Cooper ] ++ * ARM: kirkwood: add dreamplug (fdt) support. ++ * ARM: kirkwood: convert uart0 to devicetree. ++ * ARM: kirkwood: fdt: use mrvl ticker symbol ++ * ARM: kirkwood: fdt: absorb kirkwood_init() ++ * ARM: kirkwood: fdt: facilitate new boards during fdt migration ++ * ARM: kirkwood: fdt: define uart[01] as disabled, enable uart0 ++ * ARM: kirkwood: rtc-mv devicetree bindings ++ * ARM: kirkwood: use devicetree for rtc-mv ++ ++ [ Ian Campbell ] ++ * ARM: kirkwood: add missing kexec.h include ++ * microcode_xen: Add support for AMD family >= 15h ++ ++ [ Arnaud Patard (Rtp) ] ++ * kirkwood/orion: fix orion_gpio_set_blink ++ * orion/kirkwood: create a generic function for gpio led blinking ++ * kirkwood: Add iconnect support ++ ++ [ Jan Steinhoff ] ++ * Input: add Synaptics USB device driver ++ ++ [ Mircea Gherzan ] ++ * ARM: 7259/3: net: JIT compiler for packet filters ++ ++ [ Russell King ] ++ * ARM: fix Kconfig warning for HAVE_BPF_JIT ++ * i2c: mv64xxx: work around signals causing I2C transactions to be aborted ++ * I2C: mv64xxx: remove I2C_M_NOSTART code ++ * I2C: mv64xxx: move mv64xxx_i2c_prepare_for_io() ++ * I2C: mv64xxx: fix race between FSM/interrupt and process context ++ * DMA-API: provide a helper to set both DMA and coherent DMA masks ++ * DMA-API: net: intel/e1000e: fix 32-bit DMA mask handling ++ * DMA-API: net: intel/igb: fix 32-bit DMA mask handling ++ ++ [ Sam Ravnborg ] ++ * net: drop NET dependency from HAVE_BPF_JIT ++ ++ [ Bjørn Mork ] ++ * net: e100: ucode is optional in some cases ++ ++ [ Ludwig Nussel ] ++ * debugfs: add mode, uid and gid options ++ ++ [ david decotigny ] ++ * net: new counter for tx_timeout errors in sysfs ++ * net-sysfs: expose number of carrier on/off changes (Closes: CM-4415) ++ ++ [ Tom Herbert ] ++ * dql: Dynamic queue limits ++ * net: Add queue state xoff flag for stack ++ * net: Add netdev interfaces for recording sends/comp ++ * xps: Add xps_queue_release function ++ * bql: Byte queue limits ++ * dql: Fix undefined jiffies ++ * e1000e: Support for byte queue limits ++ * forcedeth: Support for byte queue limits ++ * tg3: Support for byte queue limits ++ * tg3: Fix to use multi queue BQL interfaces ++ * bnx2x: Support for byte queue limits ++ * sfc: Support for byte queue limits ++ ++ [ Hiroaki SHIMODA ] ++ * bql: Fix inconsistency between file mode and attr method. ++ * bql: Fix POSDIFF() to integer overflow aware. ++ * bql: Avoid unneeded limit decrement. ++ * bql: Avoid possible inconsistent calculation. ++ * e1000e: Change wthresh to 1 to avoid possible Tx stalls ++ ++ [ Igor Maravic ] ++ * forcedeath: Fix bql support for forcedeath ++ ++ [ Dmitry Kravkov ] ++ * bnx2x: remove unused variable ++ * bnx2x: fix crash while ethtool -t ++ ++ [ Jeff Kirsher ] ++ * igb: fix ethtool offline test ++ * e1000e: Convert printks to pr_ ++ * e1000e: Fix default interrupt throttle rate not set in NIC HW ++ * e1000e: Fix merge conflict (net->net-next) ++ * igb: Convert printks to pr_ ++ * igb: Fix code comments and whitespace ++ ++ [ Alexander Duyck ] ++ * net: Fix issue with netdev_tx_reset_queue not resetting queue from XOFF state ++ * ixgbe: add support for byte queue limits ++ * igb: Fix register defines for all non-82575 hardware ++ * igb: Remove logic that was doing NUMA pseudo-aware allocations ++ * igb: Change Tx cleanup loop to do/while instead of for ++ * igb: Change how we populate the RSS indirection table ++ * igb: Simplify how we populate the RSS key ++ * igb: Use dma_unmap_addr and dma_unmap_len defines ++ * igb: Split Rx timestamping into two separate functions ++ * igb: Do not use header split, instead receive all frames into a single buffer ++ * igb: Combine post-processing of skb into a single function ++ * igb: Map entire page and sync half instead of mapping and unmapping half pages ++ * igb: Move rx_buffer related code in Rx cleanup path into separate function ++ * igb: Lock buffer size at 2K even on systems with larger pages ++ * igb: Combine q_vector and ring allocation into a single function ++ * igb: Move the calls to set the Tx and Rx queues into igb_open ++ * igb: Split igb_update_dca into separate Tx and Rx functions ++ * igb: Fix sparse warning in igb_ptp_rx_pktstamp ++ * igb: Make TSO check for CHECKSUM_PARTIAL to avoid skb_is_gso check ++ * igb: Update igb Tx flags to improve code efficiency ++ * igb: Improve performance and reduce size of igb_tx_map ++ * igb: Do not parse past IP header on fragments beyond the first ++ * igb: Replace rmb in Tx cleanup with read_barrier_depends ++ * igb: Update igb to use a path similar to ixgbe to determine when to stop Tx ++ * igb: Mask off check of frag_off as we only want fragment offset ++ * igb: Pull adapter out of main path in igb_xmit_frame_ring ++ * igb: Use rx/tx_itr_setting when setting up initial value of itr ++ * igb: Update MTU so that it is always at least a standard frame size ++ ++ [ John Fastabend ] ++ * igb, ixgbe: netdev_tx_reset_queue incorrectly called from tx init path ++ ++ [ Vincent Palatin ] ++ * PCI/PM/Runtime: make PCI traces quieter ++ ++ [ Gustavo Padovan ] ++ * USB: add USB_VENDOR_AND_INTERFACE_INFO() macro ++ ++ [ Jeremy Fitzhardinge ] ++ * xen: add CPU microcode update driver ++ ++ [ Alexey I. Froloff ] ++ * Treat ND option 31 as userland (DNSSL support) ++ ++ [ Xose Vazquez Perez ] ++ * wireless: rt2x00: rt2800pci add more RT539x ids ++ ++ [ Zero.Lin ] ++ * rt2x00:Add RT539b chipset support ++ ++ [ Quinlan Pfiffer ] ++ * asix: Adds support for Lenovo 10/100 USB dongle. ++ ++ [ Lars-Peter Clausen ] ++ * drivercore: Generalize module_platform_driver ++ * I2C: Add helper macro for i2c_driver boilerplate ++ ++ [ Sean Young ] ++ * Add support for the IguanaWorks USB IR Transceiver ++ * iguanair: reuse existing urb callback for command responses ++ * iguanair: ignore unsupported firmware versions ++ * iguanair: support suspend and resume ++ * iguanair: fix return value for transmit ++ * iguanair: reset the IR state after rx overflow or receiver enable ++ * iguanair: advertise the resolution and timeout properly ++ * iguanair: fix receiver overflow ++ * rc: do not wake up rc thread unless there is something to do ++ * iguanair: do not modify transmit buffer ++ * iguanair: cannot send data from the stack ++ ++ [ Anisse Astier ] ++ * rt2800: add chipset revision RT5390R support ++ ++ [ Luis R. Rodriguez ] ++ * net: add new QCA alx ethernet driver which supercedes atl1c ++ ++ [ Michael Langer ] ++ * drivers/rtc/rtc-s35390a.c: add wakealarm support for rtc-s35390A rtc chip ++ ++ [ Daniel Vetter ] ++ * i2c: export bit-banging algo functions ++ ++ [ Konrad Rzeszutek Wilk ] ++ * swiotlb: Expose swiotlb_nr_tlb function to modules ++ ++ [ Julien Cristau ] ++ * drm/i915: revert switch to simple_open ++ * Revert "VM: add "vm_mmap()" helper function" ++ * drm: revert part of 2c9ede55ecec58099b72e4bb8eab719f32f72c31 ++ * Remove gma500 driver from staging ++ * Revert "drm: base prime/dma-buf support (v5)" ++ ++ [ Chris Wilson ] ++ * drm/i915: Only kick out vesafb if we takeover the fbcon with KMS ++ * drm/i915: i8xx interrupt handler ++ * drm/i915: Disable AsyncFlip performance optimisations ++ * drm/i915: Unconditionally initialise the interrupt workers ++ ++ [ Paolo Bonzini ] ++ * virtio-scsi: SCSI driver for QEMU based virtual machines ++ * virtio_scsi: fix TMF use-after-free ++ * virtio-scsi: unlock during kick ++ * virtio-scsi: split locking per vq ++ * virtio-scsi: release sg_lock after add_buf ++ * virtio-scsi: split scatterlist per target ++ * virtio-scsi: fix LUNs greater than 255 ++ * virtio-scsi: support online resizing of disks ++ ++ [ Rusty Russell ] ++ * virtio: support unlocked queue kick ++ * net: fix assignment of 0/1 to bool variables. ++ ++ [ Cong Meng ] ++ * virtio-scsi: hotplug support for virtio-scsi ++ ++ [ Nicholas Bellinger ] ++ * virtio-scsi: Add vdrv->scan for post VIRTIO_CONFIG_S_DRIVER_OK LUN scanning ++ ++ [ Wang Sen ] ++ * scsi: virtio-scsi: Fix address translation failure of HighMem pages used by sg list ++ ++ [ Richard W.M. Jones ] ++ * virtio-scsi: initialize scatterlist structure ++ ++ [ Jesper Juhl ] ++ * line6: fix memory leaks in line6_init_midi() ++ * igb: correct hardware type (i210/i211) check in igb_loopback_test() ++ * igb: don't break user visible strings over multiple lines in igb_ethtool.c ++ ++ [ Stefan Hajnoczi ] ++ * staging: line6: add Pod HD300 support ++ * staging: line6: add missing MIDI postprocessing case for POD HD300 ++ * staging: line6: use smallest iso ep packet size ++ * staging: line6: alloc/free buffers in hw_params/hw_free ++ * staging: line6: fix memory leak in .hw_params() ++ * staging: line6: fix playback urb transfer buffer calculation ++ * staging: line6: eliminate useless index_out variable ++ * staging: line6: eliminate useless NULL checks ++ * staging: line6: wait for urbs in snd_line6_prepare() ++ * staging: line6: drop unused line6_devices[] array ++ * staging: line6: drop unused line6_index and line6_id arrays ++ * staging: line6: wrap >80 char lines in capture.c ++ * staging: line6: fix quoted string across lines in midibuf.c ++ * staging: line6: shorten comment below 80 chars in pcm.c ++ * staging: line6: drop trailing whitespace in pcm.h ++ * staging: line6: wrap lines to 80 chars in playback.c ++ * staging: line6: replace deprecated strict_strtol() in toneport.c ++ * staging: line6: wrap lines to 80 chars in usbdefs.h ++ * staging: line6: wrap comment to 80 chars in variax.c ++ * staging: line6: replace DEBUG_MESSAGES() with dev_dbg() ++ * staging: line6: drop unused DEBUG_MESSAGES() macro ++ * staging: line6: drop unused CONFIG_LINE6_USB_DEBUG ++ * staging: line6: drop control URB dumping code ++ * staging: line6: drop CONTROL from CONFIG_LINE6_USB_DUMP_ANY ++ * staging: line6: drop unused CONFIG_LINE6_USB_DUMP_CTRL ++ * staging: line6: drop MIDI dumping code ++ * staging: line6: drop MIDI from CONFIG_LINE6_USB_DUMP_ANY ++ * staging: line6: drop unused CONFIG_LINE6_USB_DUMP_MIDI ++ * staging: line6: drop channel sysfs attr ++ * staging: line6: drop clip sysfs attr ++ * staging: line6: drop unused param_dirty bitmap ++ * staging: line6: drop dirty sysfs attr ++ * staging: line6: drop dump sysfs attr ++ * staging: line6: drop dump_buf sysfs attr ++ * staging: line6: drop monitor_level sysfs attr ++ * staging: line6: change monitor_level type ValueWait -> int ++ * staging: line6: drop name sysfs attr ++ * staging: line6: drop name_buf sysfs attr ++ * staging: line6: drop retrieve_amp_setup sysfs attr ++ * staging: line6: drop retrieve_channel sysfs attr ++ * staging: line6: drop retrieve_effects_setup sysfs attr ++ * staging: line6: drop store_amp_setup sysfs attr ++ * staging: line6: drop store_channel sysfs attr ++ * staging: line6: drop store_effects_setup sysfs attr ++ * staging: line6: drop routing sysfs attr ++ * staging: line6: drop tuner_freq sysfs attr ++ * staging: line6: drop tuner_note sysfs attr ++ * staging: line6: drop tuner_mute sysfs attr ++ * staging: line6: drop tuner_pitch sysfs attr ++ * staging: line6: drop finish sysfs attr ++ * staging: line6: drop midi_postprocess sysfs attr ++ * staging: line6: drop midi_mask_receive ++ * staging: line6: drop midi_mask_transmit ++ * staging: line6: drop midi_postprocess flag ++ * staging: line6: drop pod.c raw sysfs attr ++ * staging: line6: drop tuner param filtering ++ * staging: line6: drop variax model sysfs attr ++ * staging: line6: drop variax volume sysfs attr ++ * staging: line6: drop variax tone sysfs attr ++ * staging: line6: drop variax name sysfs attr ++ * staging: line6: drop variax bank sysfs attr ++ * staging: line6: drop variax dump sysfs attr ++ * staging: line6: drop variax active sysfs attr ++ * staging: line6: drop variax guitar sysfs attr ++ * staging: line6: drop variax raw sysfs attrs ++ * staging: line6: drop CONFIG_LINE6_USB_RAW ++ * staging: line6: drop amp/effects dump request triggers ++ * staging: line6: drop MIDI parameter sysfs attrs ++ * staging: line6: drop pod prog_data buffers ++ * staging: line6: drop unused pod atomic_flags field ++ * staging: line6: drop variax model_data field ++ * staging: line6: drop dump requests from variax startup ++ * staging: line6: drop dump requests from pod startup ++ * staging: line6: drop unused dumprequest code ++ ++ [ Andor Daam ] ++ * Staging: line6/midi.c: Fixed call of obsolete function strict_strtoul ++ * Staging: line6/midi.c: Fixed call of obsolete function strict_strtoul ++ ++ [ Markus Grabner ] ++ * staging/line6: Remove obsolete code ++ * staging/line6: refactor device information and add POD HD 500 ++ * staging: line6: fixed ALSA/PCM interaction ++ * staging: line6: removed obsolete code ++ * staging: line6: use source select control for UX2 devices ++ * staging: line6: separate handling of buffer allocation and stream startup ++ ++ [ Johannes Thumshirn ] ++ * staging: line6/midibuf.c changed printk(KERN_DEBUG, ... to pr_debug( ++ * staging: line6/midi.c: Added space between switch and open parenthesis ++ * staging: line6/pcm.c: Removed trailing whitespace ++ * staging: line6/config.h: Remove CHECKPOINT macro ++ * staging: line6/config.h: Delete unused header ++ * staging: line6: changed interface of line6_transmit_parameter() ++ * staging: line6: Changed some strict_strtouls to kstrtou8 ++ * staging: line6: changed interface of line6_pod_transmit_parameter() ++ * staging: line6: adjusted interface of line6_send_program() ++ * staging: line6: changed interface of pod_send_channel() ++ * staging: line6: control.c eliminate strict_strtoul() in pod_set_param_int() ++ * staging: line6: Exchanged strict_strtoul with kstrtou8() in pod.c:pod_resolve() ++ * staging: line6: Changed strict_strtoul() to kstrtou8() in pod_set_channel() ++ * staging: line6: Changed strict_strtoul() to kstrtou8() in pod_set_midi_postprocess() ++ * staging: line6: pcm.c: Changed simple_strtoul to kstrtoint ++ * staging: line6: variax.c: Eliminated remaining strict_stroul()s ++ ++ [ WANG Cong ] ++ * kexec: remove KMSG_DUMP_KEXEC ++ ++ [ Henrik Rydberg ] ++ * Input: MT - Add flags to input_mt_init_slots() ++ * Input: MT - Handle frame synchronization in core ++ * Input: MT - Add in-kernel tracking ++ ++ [ Dudley Du ] ++ * Input: add support for Cypress PS/2 Trackpads ++ ++ [ Kamal Mostafa ] ++ * Input: cypress_ps2 - fix trackpadi found in Dell XPS12 ++ ++ [ RafaÅ‚ Bilski ] ++ * cpufreq / Longhaul: Disable driver by default ++ ++ [ Benjamin Poirier ] ++ * sctp: Export sctp_do_peeloff ++ * dlm: Do not allocate a fd for peeloff ++ * igb: fix rtnl race in PM resume path ++ ++ [ J. Bruce Fields ] ++ * nfsd4: maintain one seqid stream per (lockowner, file) ++ * nfsd4: hash lockowners to simplify RELEASE_LOCKOWNER ++ ++ [ Stanislav Yakovlev ] ++ * net/wireless: ipw2200: Fix WARN_ON occurring in wiphy_register called by ipw_pci_probe ++ * net/wireless: ipw2100: Fix WARN_ON occurring in wiphy_register called by ipw2100_pci_init_one ++ ++ [ Jan Kara ] ++ * udf: Fix handling of i_blocks ++ * udf: Remove repeated loads blocksize ++ * udf: Check length of extended attributes and allocation descriptors ++ ++ [ Jan Luebbe ] ++ * mtd: m25p80: add support for Micron N25Q128 ++ ++ [ Liming Wang ] ++ * mtd: m25p80: modify info for Micron N25Q128 ++ ++ [ J. R. Okajima ] ++ * aufs: tiny, update SF URLs ++ * aufs: version 3.2.x ++ * aufs: tiny for 3.3, arg of ->migratepage() ++ * aufs: possible bugfix, make sure the target branch is upper ++ * aufs: possible bugfix, error handling in reopen_nondir() ++ * aufs: plink hlist 1/5, tiny, split au_plink_half_refresh() ++ * aufs: plink hlist 2/5, tiny, implement au_sphl for hlist ++ * aufs: plink hlist 3/5, convert the plink list into hlist ++ * aufs: plink hlist 4/5, make it a hashed array ++ * aufs: plink hlist 5/5, implement /debug/aufs/si_/plink ++ * aufs: possible bugfix, barrier for i_nlink ++ * aufs: bugfix, retval from au_pin() call in au_file_refresh_by_inode() ++ * aufs: bugfix, clear S_AUTOMOUNT ++ ++ [ David Herrmann ] ++ * drm: fix DRM_IOCTL_MODE_GETFB handle-leak ++ ++ [ Jason Wang ] ++ * net: flow_dissector: fail on evil iph->ihl ++ ++ [ Eric Northup ] ++ * virtio_scsi: fix memory leak on full queue condition. ++ ++ [ Vasily Khoruzhick ] ++ * ALSA: usb-audio: add front jack channel selector for EMU0204 ++ ++ [ Dave Airlie ] ++ * pci_regs: define LNKSTA2 pcie cap + bits. ++ ++ [ Yijing Wang ] ++ * PCI: Add pcie_flags_reg to cache PCIe capabilities register ++ ++ [ Jiang Liu ] ++ * PCI: Add accessors for PCI Express Capability ++ * e1000e: Use PCI Express Capability accessors ++ * igb: Use PCI Express Capability accessors ++ ++ [ Giuseppe CAVALLARO ] ++ * phy: add the EEE support and the way to access to the MMD registers. ++ ++ [ Bjorn Helgaas ] ++ * PCI: Add standard PCIe Capability Link ASPM field names ++ * e1000e: Use standard #defines for PCIe Capability ASPM fields ++ ++ [ Duan Jiong ] ++ * etherdevice: introduce help function eth_zero_addr() ++ ++ [ Jesse Brandeburg ] ++ * e1000e: convert to real ndo_set_rx_mode ++ * igb: implement 580 MDI setting support ++ ++ [ MichaÅ‚ MirosÅ‚aw ] ++ * net: introduce and use netdev_features_t for device features sets ++ * net: introduce and use netdev_features_t for device features sets ++ ++ [ Bruce Allan ] ++ * e1000e: hitting BUG_ON() from napi_enable ++ * e1000e: cleanup Rx checksum offload code ++ * e1000e: add Receive Packet Steering (RPS) support ++ * e1000e: re-enable alternate MAC address for all devices which support it ++ * e1000e: convert head, tail and itr_register offsets to __iomem pointers ++ * e1000e: pass pointer to ring struct instead of adapter struct ++ * e1000e: re-factor ethtool get/set ring parameter ++ * e1000e: default IntMode based on kernel config & available hardware support ++ * e1000e: always set transmit descriptor control registers the same ++ * e1000e: 82579: workaround for link drop issue ++ * e1000e: use default settings for Tx Inter Packet Gap timer ++ * e1000e: use hardware default values for Transmit Control register ++ * e1000e: 82574/82583 Tx hang workaround ++ * e1000e: disable Early Receive DMA on ICH LOMs ++ * e1000e: update workaround for 82579 intermittently disabled during S0->Sx ++ * e1000e: ICHx/PCHx LOMs should use LPLU setting in NVM when going to Sx ++ * e1000e: increase Rx PBA to prevent dropping received packets on 82566/82567 ++ * e1000e: conditionally restart autoneg on 82577/8/9 when setting LPLU state ++ * e1000e: concatenate long debug strings which span multiple lines ++ * e1000e: convert final strncpy() to strlcpy() ++ * e1000e: increase version number ++ * e1000e: call er16flash() instead of __er16flash() ++ * e1000e: split lib.c into three more-appropriate files ++ * e1000e: update copyright year ++ * e1000e: add missing initializers reported when compiling with W=1 ++ * e1000e: cleanup - check return values consistently ++ * e1000e: cleanup e1000_init_mac_params_80003es2lan() ++ * e1000e: cleanup e1000_init_mac_params_82571() ++ * e1000e: cleanup e1000_set_phys_id ++ * e1000e: cleanup - use braces in both branches of a conditional statement ++ * e1000e: fix checkpatch warning from MINMAX test ++ * e1000e: fix sparse warnings with -D__CHECK_ENDIAN__ ++ * e1000e: minor whitespace and indentation cleanup ++ * e1000e: remove test that is always false ++ * e1000e: remove unnecessary returns from void functions ++ * e1000e: remove unnecessary parentheses ++ * e1000e: use true/false for bool autoneg_false ++ * e1000e: pass pointer to hw struct for e1000_init_mac_params_XXX() ++ * e1000e: replace '1' with 'true' for boolean get_link_status ++ * e1000e: cleanup: use goto for common work needed by multiple exit points ++ * e1000e: cleanup: rename goto labels to be more meaningful ++ * e1000e: potentially incorrect return for e1000_cfg_kmrn_10_100_80003es2lan ++ * e1000e: potential incorrect return for e1000_setup_copper_link_80003es2lan ++ * e1000e: cleanup: remove unnecessary assignments just before returning ++ * e1000e: cleanup: always return 0 ++ * e1000e: potentially incorrect return for e1000_set_d3_lplu_state_ich8lan ++ * e1000e: cleanup: remove unreachable statement ++ * e1000e: cleanup: remove unnecessary variable ret_val ++ * e1000e: cleanup: remove unnecessary test and return ++ * e1000e: cleanup: remove unnecessary variable initializations ++ * e1000e: cleanup: minor whitespace addition (insert blank line separator) ++ * e1000e: potentially incorrect return for e1000_init_hw_ich8lan ++ * e1000e: potentially incorrect return for e1000e_setup_fiber_serdes_link ++ * e1000e: cleanup goto statements to exit points without common work ++ * e1000e: cosmetic change to boolean comparisons ++ * e1000e: cosmetic comment changes to make lines less than 80 characters ++ * e1000e: cleanup: rename e1000e_id_led_init() and call as function pointer ++ * e1000e: cleanup: rename e1000e_setup_link() and call as function pointer ++ * e1000e: cleanup use of check_mng_mode function pointer ++ * e1000e: cleanup use of check_reset_block function pointer ++ * e1000e: cleanup calls to setup_physical_interface function pointer ++ * e1000e: comment correction in e1000e_set_kmrn_lock_loss_workaround_ich8lan ++ * e1000e: rename e1000e_config_collision_dist() and call as function pointer ++ * e1000e: cleanup comment in e1000_hash_mc_addr() ++ * e1000e: use true/false for boolean send_xon, do not assume always true ++ * e1000e: cleanup - remove unnecessary variable ++ * e1000e: rename e1000e_reload_nvm() and call as function pointer ++ * e1000e: cleanup incorrect filename in comment ++ * e1000e: cleanup whitespace and indentation ++ * e1000e: use msleep instead of mdelay ++ * e1000e: prevent oops when adapter is being closed and reset simultaneously ++ * e1000e: cleanup NAPI routine ++ * e1000e: cleanup indexed register arrays ++ * e1000e: update driver version number ++ * e1000e: issues in Sx on 82577/8/9 ++ * e1000e: cleanup remaining strings split across multiple lines ++ * e1000e: cleanup boolean logic ++ * e1000e: 82579 packet drop workaround ++ * e1000e: 82579 potential system hang on stress when ME enabled ++ * e1000e: workaround EEPROM configuration change on 82579 ++ * e1000e: PHY initialization flow changes for 82577/8/9 ++ * e1000e: fix .ndo_set_rx_mode for 82579 ++ * e1000e: suggest a possible workaround to a device hang on 82577/8 ++ * e1000e: cleanup long [read|write]_reg_locked PHY ops function pointers ++ * e1000e: initial support for i217 ++ * e1000e: enable forced master/slave on 82577 ++ * e1000e: increase version number ++ * e1000e: fix typo in definition of E1000_CTRL_EXT_FORCE_SMBUS ++ * e1000e: fix Rapid Start Technology support for i217 ++ * e1000e: test for valid check_reset_block function pointer ++ * e1000e: use more informative logging macros when netdev not yet registered ++ * e1000e: remove use of IP payload checksum ++ * e1000e: fix test for PHY being accessible on 82577/8/9 and I217 ++ * e1000e: use correct type for read of 32-bit register ++ * e1000e: cleanup strict checkpatch MEMORY_BARRIER checks ++ * e1000e: cleanup strict checkpatch check ++ * e1000e: cleanup - remove inapplicable comment ++ * e1000e: cleanup - remove unnecessary variable ++ * e1000e: update driver version number ++ * e1000e: add device IDs for i218 ++ * e1000e: cosmetic cleanup of comments ++ * e1000e: SerDes autoneg flow control ++ * e1000e: Acquire/release semaphore when writing each EEPROM page ++ * e1000e: Invalid Image CSUM bit changed for I217 ++ * e1000e: helper functions for accessing EMI registers ++ * e1000e: 82577: workaround for link drop issue ++ * e1000e: fix enabling of EEE on 82579 and I217 ++ * e1000e: unexpected "Reset adapter" message when cable pulled ++ * e1000e: add missing bailout on error ++ * e1000e: resolve checkpatch PREFER_PR_LEVEL warning ++ * e1000e: cleanup redundant statistics counter ++ * e1000e: cleanup unusual comment placement ++ * e1000e: cleanup unnecessary line wrap ++ * e1000e: cleanup magic number ++ * e1000e: cleanup code duplication ++ * e1000e: merge multiple conditional statements into one ++ * e1000e: add ethtool .get_eee/.set_eee ++ * e1000e: add support for hardware timestamping on some devices ++ * e1000e: fix ethtool offline register test for I217 ++ * e1000e: fix flow-control thresholds for jumbo frames on 82579/I217/I218 ++ * e1000e: add support for IEEE-1588 PTP ++ * e1000e: enable ECC on I217/I218 to catch packet buffer memory errors ++ * e1000e: prevent hardware from automatically configuring PHY on I217/I218 ++ * e1000e: remove prototype of non-existent function ++ * e1000e: update copyright date ++ * e1000e: correct maximum frame size on i217/i218 ++ * e1000e: fix PHY init workarounds for i217/i218 ++ * e1000e: remove definition of struct which is no longer used ++ * e1000e: add comment to spinlock_t definition ++ * e1000e: cleanup: remove unnecessary function prototypes ++ * e1000e: do not ignore variables which get set a value ++ * e1000e: cleanup: do not assign a variable a value when not necessary ++ * e1000e: cleanup: remove e1000_set_d0_lplu_state() ++ * e1000e: cleanup: remove e1000_force_speed_duplex() ++ * e1000e: cleanup: rename e1000_get_cfg_done() ++ * e1000e: cleanup: remove e1000_get_phy_cfg_done() ++ * e1000e: cleanup: remove e1000_get_cable_length() ++ * e1000e: cleanup: remove e1000e_commit_phy() ++ * e1000e: correct maximum frame size on 82579 ++ * e1000e: adjust PM QoS request ++ * e1000e: cleanup: remove unused #define ++ * e1000e: cleanup hw.h ++ * e1000e: cleanup: remove comments which are no longer applicable ++ * e1000e: cleanup defines.h ++ * e1000e: cleanup: group OR'ed bit settings with parens ++ * e1000e: cleanup some whitespace and indentation issues ++ * e1000e: update driver version string ++ * e1000e: resolve -Wunused-parameter compile warnings ++ * e1000e: use generic IEEE MII definitions ++ * e1000e: cosmetic move of #defines and prototypes to the new 82571.h ++ * e1000e: cosmetic move of #defines to the new 80003es2lan.h ++ * e1000e: cosmetic move of #defines and prototypes to the new ich8lan.h ++ * e1000e: cosmetic move of function prototypes to the new mac.h ++ * e1000e: cosmetic move of #defines and function prototypes to the new phy.h ++ * e1000e: cosmetic move of #defines and function prototypes to the new nvm.h ++ * e1000e: cosmetic move of #defines and prototypes to the new manage.h ++ * e1000e: convert enums of register offsets and move #defines to regs.h ++ * e1000e: cleanup checkpatch braces checks ++ * e1000e: workaround DMA unit hang on I218 ++ * e1000e: cleanup CODE_INDENT checkpatch errors ++ * e1000e: cleanup SPACING checkpatch errors and warnings ++ * e1000e: cleanup LONG_LINE checkpatch warnings ++ * e1000e: cleanup LEADING_SPACE checkpatch warnings ++ * e1000e: cleanup PARENTHESIS_ALIGNMENT checkpatch checks ++ * e1000e: cleanup SPACING checkpatch checks ++ * e1000e: cleanup (add/remove) blank lines where appropriate ++ * e1000e: cleanup unusually placed comments ++ * e1000e: cleanup formatting of static structs ++ * e1000e: cleanup unnecessary line breaks ++ * e1000e: cleanup USLEEP_RANGE checkpatch checks ++ * e1000e: cleanup format of struct e1000_opt_list struct ++ * e1000e: cleanup - move defines to appropriate header file ++ * e1000e: additional error handling on PHY register accesses ++ * e1000e: slow performance between two 82579 connected via 10Mbit hub ++ * e1000e: fix LED blink logic for designs with LEDs driven by cathode ++ * e1000e: long access timeouts when I217/I218 MAC and PHY are out of sync ++ * e1000e: EEE capability advertisement not set/disabled as required ++ * e1000e: add support for LTR on I217/I218 ++ * e1000e: cleanup unused defines ++ * e1000e: increase driver version number ++ * e1000e: fix scheduling while atomic bugs ++ * e1000e: panic caused by Rx traffic arriving while interface going down ++ * e1000e: fix scheduling while atomic bug ++ * e1000e: cleanup whitespace ++ * e1000e: disable ASPM L1 on 82583 ++ * e1000e: iAMT connections drop on driver unload when jumbo frames enabled ++ * e1000e: low throughput using 4K jumbos on I218 ++ * e1000e: Tx hang on I218 when linked at 100Half and slow response at 10Mbps ++ * e1000e: ethtool unnecessarily takes device out of RPM suspend ++ * e1000e: enable support for new device IDs ++ * e1000e: do not resume device from RPM suspend to read PHY status registers ++ * e1000e: fix I217/I218 PHY initialization flow ++ * e1000e: cleanup whitespace in recent commit ++ * e1000e: resolve checkpatch JIFFIES_COMPARISON warning ++ ++ [ David S. Miller ] ++ * e1000e: Need to include vmalloc.h ++ * ipv4: Missing sk_nulls_node_init() in ping_unhash(). ++ ++ [ Matthew Vick ] ++ * e1000e: Guarantee descriptor writeback flush success. ++ * e1000e: Minor comment clean-up. ++ * e1000e: Disable Far-End LoopBack following reset on 80003ES2LAN. ++ * e1000e: Enable DMA Burst Mode on 82574 by default. ++ * e1000e: Resolve intermittent negotiation issue on 82574/82583. ++ * e1000e: Driver workaround for IPv6 Header Extension Erratum. ++ * e1000e: Update driver version number ++ * e1000e: Program the correct register for ITR when using MSI-X. ++ * igb: Update DMA Coalescing threshold calculation. ++ * igb: Force flow control off during reset when forcing speed. ++ * igb: Disable the BMC-to-OS Watchdog Enable bit for DMAC. ++ * igb: Streamline RSS queue and queue pairing assignment logic. ++ * igb: Tidy up wrapping for CONFIG_IGB_PTP. ++ * igb: Update PTP function names/variables and locations. ++ * igb: Store the MAC address in the name in the PTP struct. ++ * igb: Prevent dropped Tx timestamps via work items and interrupts. ++ * igb: Add 1588 support to I210/I211. ++ * igb: Enable auto-crossover during forced operation on 82580 and above. ++ * igb: Update PTP Rx filters ++ * igb: No longer rely on APME to determine WoL settings ++ * igb: Use a 32-bit mask when calculating the flow control watermarks ++ * igb: Add support for SW timestamping ++ * igb: Add timeout for PTP Tx work item ++ * igb: Add mechanism for detecting latched hardware Rx timestamp ++ * igb: Free any held skb that should have been timestamped on remove ++ * igb: Use in-kernel PTP_EV_PORT #define ++ * igb: Enable EEE LP advertisement ++ * igb: Add SMBI semaphore to I210/I211 ++ * igb: Remove dead code path ++ * igb: Add update to last_rx_timestamp in Rx rings ++ ++ [ Prasanna S Panchamukhi ] ++ * e1000e: MSI interrupt test failed, using legacy interrupt ++ ++ [ Willem de Bruijn ] ++ * e1000e: add transmit timestamping support ++ ++ [ Richard Alpe ] ++ * e1000e: clear REQ and GNT in EECD (82571 && 82572) ++ ++ [ Tushar Dave ] ++ * e1000e: Cleanup code logic in e1000_check_for_serdes_link_82571() ++ * e1000e: 82571 Tx Data Corruption during Tx hang recovery ++ * e1000e: Minimum packet size must be 17 bytes ++ * igb: Correcting and improving small packet check and padding ++ ++ [ Emil Tantilov ] ++ * e1000e: fix panic while dumping packets on Tx hang with IOMMU ++ * igb: fix warning about unused function ++ * igb: fix panic while dumping packets on Tx hang with IOMMU ++ * igb: fix vlan filtering in promisc mode when not in VT mode ++ ++ [ Bruce W Allan ] ++ * e1000e: implement 82577/579 MDI setting support ++ ++ [ Bill Pemberton ] ++ * net/intel: remove __dev* attributes ++ * net/intel: remove __dev* attributes ++ ++ [ Koki Sanagi ] ++ * e1000e: display a warning message when SmartSpeed works ++ * igb: reset PHY after recovering from PHY power down ++ * igb: output register's information related to RX/TX queue[4-15] ++ * igb: display a warning message when SmartSpeed works ++ ++ [ Konstantin Khlebnikov ] ++ * e1000e: fix runtime power management transitions ++ * e1000e: fix accessing to suspended device ++ ++ [ Christoph Paasch ] ++ * e1000e: Add missing dma_mapping_error-call in e1000_alloc_jumbo_rx_buffers ++ ++ [ Richard Cochran ] ++ * e1000e: fix numeric overflow in phc settime method ++ * igb: add PTP Hardware Clock code ++ * igb: offer a PTP Hardware Clock instead of the timecompare method ++ ++ [ Akeem G. Abodunrin ] ++ * e1000e: Release mutex lock only if it has been initially acquired ++ * igb: reset PHY in the link_up process to recover PHY setting after power down. ++ * igb: Supported and Advertised Pause Frame ++ * igb: Support to enable EEE on all eee_supported devices ++ * igb: Support for modifying UDP RSS flow hashing ++ * igb: Acquire, release semaphore for writing each EEPROM page ++ * igb: Copyright string update to year 2013 ++ * igb: Initialize PHY function pointers ++ * igb: Initialize NVM function pointers ++ * igb: Intialize MAC function pointers ++ * igb: Refractoring function pointers in igb_get_invariants function ++ * igb: Support for 100base-fx SFP ++ * igb: Implement support to power sfp cage and turn on I2C ++ * igb: random code and comments fix ++ * igb: Fix sparse warnings on function pointers ++ * igb: SERDES loopback sigdetect bit on i210 devices ++ * igb: Changed LEDs blink mechanism to include designs using cathode ++ * igb: Support for SFP modules discovery ++ * igb: SerDes flow control setting ++ * igb: Implementation of i210/i211 LED support ++ * igb: Removed unused i2c function ++ ++ [ Wei Yang ] ++ * e1000e: Remove duplicate assignment of default rx/tx ring size ++ * e1000e: Use marco instead of digit for defining e1000_rx_desc_packet_split ++ ++ [ Carolyn Wyborny ] ++ * e1000e: Add code to check for failure of pci_disable_link_state call ++ * igb: Add flow control advertising to ethtool setting. ++ * igb: Update Copyright on all Intel copyrighted files. ++ * igb: Update version to 3.4.7. ++ * igb: Add function and pointers for 82580 low power state settings. ++ * igb: Add Support for new i210/i211 devices. ++ * igb: Fix incorrect RAR address entries for i210/i211 device. ++ * Kconfig: Fix Kconfig for Intel ixgbe and igb PTP support. ++ * igb: Add switch case for supported hardware to igb_ptp_remove. ++ * igb: Update firmware info output ++ * igb: Version bump ++ * igb: Fix for failure to init on some 82576 devices. ++ * igb: Add loopback test support for i210 ++ * igb: Fix stats output on i210/i211 parts. ++ * igb: Update get cable length function for i210/i211 ++ * igb: Update version ++ * igb: Update firmware version info for ethtool output. ++ * igb: Remove workaround for EEE configuration on i210/I211 ++ * igb: Add function to read i211's invm version ++ * igb: Fix EEPROM writes via ethtool on i210 ++ * igb: Clear Go Link Disconnect for 82580 and later devices ++ * igb: Updates to read nvm function for i211 device ++ * igb: Refactoring of i210 file. ++ * igb: Workaround for global device reset problem on 82580. ++ * igb: Unset sigdetect for SERDES loopback on 82580 and i350 ++ * igb: Fix SerDes autoneg flow control. ++ * igb: Update igb version to 4.1.2 ++ * igb: Add i2c interface to igb. ++ * igb: Add support functions to access thermal data. ++ * igb: Enable hwmon data output for thermal sensors via I2C. ++ * igb: Fix for improper exit in igb_get_i2c_client ++ * igb: Fix for improper allocation flag in igb_get_i2c_client ++ * igb: Refix sparse warning in igb_get_i2c_client ++ * igb: Fix link setup for I210 devices ++ * igb: Fix for lockdep issue in igb_get_i2c_client ++ * igb: Add support for i354 devices ++ * igb: Remove id's that will not be productized for Linux. ++ * igb: Bump version of driver ++ * igb: Fix set_ethtool function to call update nvm for entire image ++ * igb: Fix possible panic caused by Rx traffic arrival while interface is down ++ * igb: Refactor of init_nvm_params ++ * igb: Refactor NVM read functions to accommodate devices with no flash ++ * igb: Add device support for flashless SKU of i210 device ++ * igb: Fix get_fw_version function for all parts ++ * igb: Add additional get_phy_id call for i354 devices ++ * igb: Fix master/slave mode for all m88 i354 PHY's ++ * igb: Update link modes display in ethtool ++ * igb: Fix for issue where values could be too high for udelay function. ++ ++ [ Li Zhang ] ++ * e1000e: Avoid kernel crash during shutdown ++ ++ [ Steven La ] ++ * e1000e: balance semaphore put/get for 82573 ++ ++ [ David Ertman ] ++ * e1000e: cleanup boolean comparison to true ++ * e1000e: fix overrun of PHY RAR array ++ * e1000e: fix compiler warnings ++ * e1000e: fix compiler warning (maybe-unitialized variable) ++ * e1000e: Fix a compile flag mis-match for suspend/resume ++ ++ [ Joe Perches ] ++ * intel: Remove extern from function prototypes ++ * igb: Convert bare printk to pr_notice ++ * ethernet: Remove unnecessary alloc/OOM messages, alloc cleanups ++ * intel: Remove extern from function prototypes ++ * net:drivers/net: Miscellaneous conversions to ETH_ALEN ++ ++ [ Mika Westerberg ] ++ * e1000e: Fix compilation warning when !CONFIG_PM_SLEEP ++ ++ [ Yan, Zheng ] ++ * igb: add basic runtime PM support ++ ++ [ Stephen Hemminger ] ++ * igb: make local functions static ++ * igb: make sensor info static ++ ++ [ Lior Levy ] ++ * igb: A fix to VF TX rate limit ++ * igb: fix i350 anti spoofing config ++ * igb: add support for spoofchk config ++ ++ [ Stefan Assmann ] ++ * igb: add delay to allow igb loopback test to succeed on 8086:10c9 ++ * igb: Change how we check for pre-existing and assigned VFs ++ * igb: remove duplicate code for fallback interrupt initialization ++ * igb: increase timeout for ethtool offline self-test ++ ++ [ Mitch A Williams ] ++ * igb: Don't give VFs random MAC addresses ++ ++ [ Alex Williamson ] ++ * igb: Fix null pointer dereference ++ ++ [ Jiri Benc ] ++ * igb: fix PHC stopping on max freq ++ ++ [ Greg Rose ] ++ * igb: Retain HW VLAN filtering while in promiscuous + VT mode ++ ++ [ Akeem G Abodunrin ] ++ * igb: Read register for latch_on without return value ++ * igb: Added rcu_lock to avoid race ++ * igb: Implementation of 1-sec delay for i210 devices ++ * igb: New PHY_ID for i354 device ++ * igb: M88E1543 PHY downshift implementation ++ * igb: No PHPM support in i354 devices ++ * igb: Support to get 2_5G link status for appropriate media type ++ * igb: Get speed and duplex for 1G non_copper devices ++ * igb: Implementation to report advertised/supported link on i354 devices ++ * igb: Update version number ++ * igb: Fixed Wake On LAN support ++ ++ [ Laura Mihaela Vasilescu ] ++ * igb: Add macro for size of RETA indirection table ++ * igb: Expose RSS indirection table for ethtool ++ * igb: Add ethtool support to configure number of channels ++ ++ [ Todd Fujinaka ] ++ * igb: Don't look for a PBA in the iNVM when flashless ++ * igb: Fix ethtool loopback test for 82580 copper ++ ++ [ Fujinaka, Todd ] ++ * igb: Read flow control for i350 from correct EEPROM section ++ * igb: Add ethtool offline tests for i354 ++ * igb: Don't let ethtool try to write to iNVM in i210/i211 ++ ++ [ Florian Westphal ] ++ * netfilter: ipv4: defrag: set local_df flag on defragmented skb ++ ++ [ Neil Horman ] ++ * PCI/sysfs: add per pci device msi[x] irq listing (v5) ++ * PCI: msi: fix imbalanced refcount of msi irq sysfs objects ++ ++ [ Alexander Gordeev ] ++ * PCI/MSI: Return msix_capability_init() failure if populate_msi_sysfs() fails ++ ++ [ Alexei Starovoitov ] ++ * PCI/MSI: Fix memory leak in free_msi_irqs() ++ * x86: bpf_jit: fix compilation of large bpf programs (Closes: CM--7048) ++ ++ [ Naoya Horiguchi ] ++ * mm: add !pte_present() check on existing hugetlb_entry callbacks ++ ++ [ Hector Marco-Gisbert ] ++ * ASLR: fix stack randomization on 64-bit systems ++ ++ [ Mike Miller ] ++ * hpsa: add HP Smart Array Gen9 PCI ID's ++ * hpsa: add HP Smart Array Gen8 names ++ * hpsa: housekeeping patch for device_id and product arrays ++ * hpsa: remove unused Smart Array ID ++ * hpsa: remove P822se PCI ID ++ ++ [ Stephen M. Cameron ] ++ * hpsa: add HP/3PAR vendor id to pci_ids.h ++ * hpsa: Add support for a few HP Storage controllers ++ * hpsa: fix a couple pci id table mistakes ++ ++ [ Joe Handzik ] ++ * hpsa: add new Smart Array PCI IDs (May 2014) ++ ++ [ Don Brace ] ++ * hpsa: add in gen9 controller model names ++ * hpsa: add in P840ar controller model name ++ ++ [ Trond Myklebust ] ++ * NFSv4: Minor cleanups for nfs4_handle_exception and nfs4_async_handle_error ++ ++ [ Jozsef Kadlecsik ] ++ * netfilter: ipset: Check and reject crazy /0 input parameters ++ ++ [ Shachar Raindel ] ++ * IB/core: Prevent integer overflow in ib_umem_get address arithmetic ++ ++ [ Andrey Vagin ] ++ * netfilter: nf_conntrack: reserve two bytes for nf_ct_ext->len ++ ++ [ Jan Beulich ] ++ * xen-pciback: limit guest control of command register ++ ++ [ Andy Lutomirski ] ++ * x86/asm/entry/64: Remove a bogus 'ret_from_fork' optimization ++ ++ [ D.S. Ljungmark ] ++ * ipv6: Don't reduce hop limit for an interface ++ ++ [ Stephan Mueller ] ++ * crypto: aesni - fix memory usage in GCM decryption ++ ++ [ Jann Horn ] ++ * fs: take i_mutex during prepare_binprm for set[ug]id executables ++ ++ [ Jonathan Toppins ] ++ * debian: include debian directory from src pkg 3.2.68-1+deb7u2 ++ * debian: remove realtime patchset from configs ++ * debian: remove xen package support ++ * debian: fixup debian makefiles to build out of git repo ++ * debian: fixup maintainer target in debian/rules ++ * debian: fixup control file maintainers and vcs ++ * debian: disable generation of udebs ++ * debian: stop removal of debian directory ++ * CUMULUS: kernel: add rtnl dump support for bonding ++ * CUMULUS: kernel: add rtnl dump support for bonding ++ * CUMULUS: kernel: add rtnl dump support for bonding ++ * CUMULUS: kernel: add support dumping bonding lacp fallback options ++ * CUMULUS: kernel: set timeout_panic to 5 seconds ++ * CUMULUS: kernel: set timeout_panic to 5 seconds ++ * CUMULUS: kernel: lockdep squash bootup warnings in ethtool ++ * CUMULUS: kernel: lacp_fallback_* bonding attribute check bond mode first ++ * CUMULUS: kernel: deb install needs to call depmod ++ * CUMULUS: kernel and iproute: rename fallback to bypass ++ * CUMULUS: kernel: fix bcm98548xmc printing board specific call for every ppc platform ++ * CUMULUS: kernel: bridge fix crash when set mac address of bridge interface ++ * CUMULUS: kernel: update base kernel to Debian 3.2.65-1+deb7u1 ++ * CUMULUS: kernel: powerpc: fix quanta_lb9_restart() section mismatch ++ (Closes: CM-4952) ++ * CUMULUS: kernel: update base kernel to Debian 3.2.65-1+deb7u2 ++ * debian: print pretty config output ++ * debian: remove common configs and reference cumulus configs ++ * config: add initial cumulus kernel configs ++ * config: copy over ITS files for powerpc ++ * retimer: fix Kconfig dependency ++ * debian: add arm support for iproc ++ * config: add arm config to debian directory ++ * config: copy over ITS files for arm ++ * bcmdriver: fixup makefiles ++ * debian: update changelog to include 3.2.68-1+deb7u3 security fixes ++ (Closes: CM-7048) ++ * bcmdrivers: fix makefiles so individual .o's can be built ++ * bcmdrivers: fix relative path include in iproc_nand.c ++ ++ [ JR Rivers ] ++ * CUMULUS: Update to linux-3.0 ++ * CUMULUS: Finishing up the commits for the Broadcom development platform support. ++ * CUMULUS: This patch makes some modifications to the kernel and allow JTAG debuggers to work. ++ * CUMULUS: Changes that make interupts work on the BCM98548XMC. These changes address bug id 2 (https://dev.cumulusnetworks.com/ticket/2). ++ * CUMULUS: Add ability for Linux to set up PCIe max_payload and read_request_size. ++ * CUMULUS: Add overlayfs to linux and build both a jffs2 and squash root file system ++ * CUMULUS: Reduce the printk loglevel r.e. using deprecated oom_adj file ++ * CUMULUS: Allow run time configuration of CFI byte swapping via device tree spec ++ * CUMULUS: Add support for the DNI ET7448 boxes. ++ * CUMULUS: Finishing up the commits for the Broadcom development platform support. ++ * CUMULUS: Add support for the DNI ET7448 boxes. ++ * CUMULUS: Add support for the DNI ET7448 boxes. ++ * CUMULUS: Fix a problem with the script (it got munged somewhere along the way) ++ * CUMULUS: Initialize bridge with an address of 00:00:00:00:00:00 ++ * CUMULUS: Allow full functionality of static bridge MAC addresses ++ ++ [ Shrijeet Mukherjee ] ++ * CUMULUS: Add proc and sysfs nodes for core and package id's ++ * CUMULUS: Use DEBUG for defunct sysctl scan_unevictable ++ * CUMULUS: Initial support for CY8C3xx driver ++ * CUMULUS: Initial support for CY8C3xx driver ++ * CUMULUS: Backport upstream patch to enable arp_accept per device ++ ++ [ Curt Brune ] ++ * CUMULUS: kernel: add support for Intel Centerton CPUs ++ * CUMULUS: kernel: enable compiling firmware into kernel binary ++ * CUMULUS: Fix up invalid RTC hardware clock settings ++ * CUMULUS: Back port i2c-mux-device-tree.patch from upstream ++ * CUMULUS: Modify pca954x driver to check for "deselect_on_exit" property in the dtb ++ * CUMULUS: Re-organize kernel stgit patches ++ * CUMULUS: Allocate BCM DMA memory early in the boot process ++ * CUMULUS: quanta_lb9: update ADT7470 driver for i2c errors ++ * CUMULUS: gpio: mpc8xxx: don't set IRQ_TYPE_NONE when creating irq mapping ++ * CUMULUS: driver at24 fix odd length two byte access ++ * CUMULUS: Create eeprom_dev hardware class for EEPROM devices ++ * CUMULUS: Create eeprom_dev hardware class for EEPROM devices ++ * CUMULUS: kernel: add support for Intel Centerton CPUs ++ * CUMULUS: kernel: add support for Intel Centerton CPUs ++ * CUMULUS: kernel: add support for Intel Centerton CPUs ++ * CUMULUS: Re-organize kernel stgit patches ++ * CUMULUS: Add kernel and image support for accton_5652 ++ * CUMULUS: Add kernel and image support for accton_5652 ++ * CUMULUS: cel_redstone: add custom i2c driver for SFP+/QSFP ++ * CUMULUS: Kernel patches for DNI-6448 support ++ * CUMULUS: DNI 6448 i2c mux driver moved into the kernel ++ * CUMULUS: Update TUNSETCOUNTERS ioctl() to use 64-bit counters ++ * CUMULUS: adt7475 driver: clear pwm invert bit ++ * CUMULUS: powerpc watchdog: add kernel support for BookE watchdog driver ++ * CUMULUS: powerpc watchdog: add kernel support for BookE watchdog driver ++ * trivial: clean up white space in uImage-arm.its ++ * armel: Use gzip compressed kernel image (Closes: CM-6105) ++ * armel: update kernel config to be on par with amd64 (Closes: CM-7097) ++ * armel: remove initramfs from uImage-arm.its (Closes: CM-7023, CM-7025) ++ * armel: remove legacy Debian postinst script (Closes: CM-7023) ++ * minor clean up: remove unused static function (Closes: CM-7057) ++ ++ [ Puneet ] ++ * CUMULUS: S6000 should do cold reset on reboot ++ * CUMULUS: at24 eeprom driver x86 eeprom write support ++ * CUMULUS: Disable I2C block reads based on disable_features module param. ++ * CUMULUS: CM-2953: "ismt_smbus 0000:00:13.1: completion wait timed out" seen on S6000 ++ * CUMULUS: DELL S6000: Platform driver should detect ismt bus based on PCIe address + some cleanup ++ * CUMULUS: as5712: i801 smbus timeout ++ * CUMULUS: Add max6620 driver to the kernel ++ * CUMULUS: Fix RPM calculation in max6620 driver and add to linux config ++ * CUMULUS: s6000: Add driver for pmbus based power supply ++ * Remove CONFIF_CRYPTO_* built in modules and make loadable ++ * CUMULUS: DNI-3448P: Update fan driver DNI3448 to make it more configurable ++ * CUMULUS: DNI-3448P: RTC Support ++ * CUMULUS: DNI-3448P: Remove LTC4215 from the list of sensors ++ * Accton AS4610-54X: Fix RTC driver ++ ++ [ anuradhak ] ++ * CUMULUS: Have the OS set up all PCI device maxpayload and maxreadrequest on the PCIe bus ++ * CUMULUS: Changes for displaying vxlan stats via ethtool and netdev (ifconfig, ip -s link show, /proc/net/dev). The VNI (VPN/VFI) stats are displayed via the bridge device and the vxlan local interface (SVP) stats are displayed via the vlan device. ++ * CUMULUS: Changes to replace clagid setting in the bonding driver with - 1. clag_enable flag in the bonding driver 2. And clagid in clagd ++ * CUMULUS: Support for proto_down (errDisabled) state ++ * CUMULUS: Static clag (part 1) - Introducing proto_down (errDisabled) bond state. ++ * CUMULUS: Move the protodown changes from the tun driver to virtio. ++ * Revert "CUMULUS: Support for proto_down (errDisabled) state" ++ * netlink: changes for setting and clearing protodown via netlink. ++ (Closes: CM-6387) ++ * CUMULUS: bonding: proto_down setting API has changed upstream ++ * CUMULUS: virtio: Handle protodown notifications. ++ * CUMULUS: tun: Handle proto_down notification. ++ * CUMULUS: vxlan: Handle proto_down notification. ++ * CUMULUS: net: moved proto_down rtnl notification to dev_change_proto_down. ++ (Closes: CM-7120) ++ ++ [ alanl ] ++ * CUMULUS: kernel: fix problem caused by increase of GPIOs ++ * CUMULUS: Support for new platform: Celestica Redstone XP ++ * CUMULUS: Support for new platform: Celestica Redstone XP ++ * CUMULUS: Support for new platform: Celestica Redstone XP ++ * CUMULUS: Update intel igb driver for master branch ++ ++ [ roopa ] ++ * CUMULUS: Add null check in generic_access_phys ++ * CUMULUS: Set fs.setuid_dumpable to 2 ++ * CUMULUS: Set fs.setuid_dumpable to 2 ++ * CUMULUS: lb8 i2c mux driver for sfp's. This is a first working version. More testing in progress ++ * CUMULUS: Pull parts of upstream patch "rearrange fdb notifications". This invalidates one our patches network-bridge-fdb-add-state-to-fdb-create.patch ++ * CUMULUS: Fix bridge fdb bugs ++ * CUMULUS: Pull hemmingers upstream proposed patch (with some changes) for making bridge path cost persistent accross link changes ++ * CUMULUS: Add master index to neigh RTM_*NEIGH msgs (for bridge fdb updates). Kernel and libnl support ++ * CUMULUS: Pull upstream version of '-send-unsolicited-ND-on-link-layer-address-change' ++ * CUMULUS: Pull upstream version of blackhole route patch ++ * CUMULUS: pulled kernel patch to send netlink notification for ipv4 dead routes during fib flush ++ * CUMULUS: Picked up ipv6_del_addr on lo fixes from upstream ++ * CUMULUS: Add support for kernel abi check ++ * CUMULUS: Add notification for neigh entry state changes ++ * CUMULUS: Add support for libnl append + non-exclusive routes ++ * CUMULUS: vxlan kernel + libnl fixes for fdb entry add/deletions ++ * CUMULUS: Fix ipv6 duplicate nexthop cleanup on error ++ * CUMULUS: Fix ordering of netlink notifications during bond deletes ++ * CUMULUS: ethtool support for 40G/4 gang ports ++ * CUMULUS: move bridge driver logging to debug level (br_debug inturn uses pr_debug) ++ ++ [ Dustin Byford ] ++ * CUMULUS: kernel - ubifs xattr on symlink support ++ * CUMULUS: kernel - merge onie changes for Quanta LB9 and LY2 ++ * CUMULUS: kernel: FSL DPAA drivers ++ * CUMULUS: kernel: FSL DPAA drivers ++ * CUMULUS: kernel: add ds100df410 retimer driver ++ * CUMULUS: kernel: add pca9505/pca9506 gpio support to the pca953x driver ++ * CUMULUS: kernel: backport max6697 kernel driver ++ * CUMULUS: kernel: as6700_32x P2041 support ++ * CUMULUS: kernel: accton-as6700-32x-p2020 ++ * CUMULUS: kernel - add Cumulus P2020 support ++ * CUMULUS: kernel - add Cumulus P2020 support ++ * CUMULUS: Quanta LB9 - kernel changes ++ * CUMULUS: kernel - add Cumulus P2020 support ++ ++ [ Vidya Sagar Ravipati ] ++ * CUMULUS: EMC2305 Driver support ++ * CUMULUS: SFF-8436 based QSFP EEPROM driver support ++ * CUMULUS: Quanta LY6: Cumulus Linux Support ++ * CUMULUS: Post install script for kernel deb ++ * CUMULUS: Kernel Disable HW ACL stats ++ * CUMULUS: Pebble: Back port Baytrail CPU support to 3.2 kernel ++ * CUMULUS: Pebble: Back port Baytrail CPU support to 3.2 kernel ++ * CUMULUS: Pebble: Back port Baytrail CPU support to 3.2 kernel ++ * CUMULUS: Pebble: Back port Baytrail CPU support to 3.2 kernel ++ * CUMULUS: Powerpc: Fix for MMC FSL driver to program INTERRUPT/SIGNAL enable during reset ++ * CUMULUS: Accton AS4610-54P: Platform support in Kernel ++ * CUMULUS: Accton AS4610-54P: Platform support in Kernel ++ * CUMULUS: Accton AS4610-54P: Platform support in Kernel ++ * Accton AS4610-54P: Kernel Config and uImage changes ++ * Accton AS4610-54P: Enabling Support for AS4610-54P ++ * Accton AS4610-54P: Support for PSU eeproms ++ * Accton AS4610-54p: Remove Port labels for unsupported QSFP+ ports 53 and 54 ++ * ARM:Support for LVM kernel configuration ++ * ARM: Revert bcm_dma entry change ++ * arm: Remove BCM DMA entry in DNI 3448P dts file ++ * usb-iproc: Removce access Helix4 GPIO pins ++ * usb-iproc:Enabling automatic enablement of IPROC OHCI drivere ++ * USB: Disabbling OHCI HCD in ARM KERNEL CONFIG ++ * ARM: Renaming act-4610-54p to act-4610-54 ++ ++ [ Wilson Kok ] ++ * CUMULUS: Bridge support fixes. ++ * CUMULUS: Add erpan and police targets for iptables and ebtables ++ * CUMULUS: OVSDB - added service node support ++ * CUMULUS: Add vlan aware bridging support. ++ * CUMULUS: Add vlan aware bridging support. ++ * CUMULUS: Add vlan aware bridging support. ++ * CUMULUS: Support per vlan igmp querier configuration ++ * CUMULUS: Add LACP fall back support to bonding driver ++ * CUMULUS: Fixed kernel fdb delete which incorrectly ignores the interface ++ * CUMULUS: Fixed kernel fdb dump handling. ++ * CUMULUS: Fixed incorrect rx drop count for l2 protocol frames on bridge port. ++ * CUMULUS: Changed allow_multiple_vlans from module parameter to sysctl. ++ * CUMULUS: Ported upstream bridge default pvid support ++ * CUMULUS: Ported upstream bridge default pvid support ++ * CUMULUS: Ported upstream bridge default pvid support ++ * CUMULUS: Ported upstream bridge default pvid support ++ * CUMULUS: Ported upstream bridge default pvid support ++ * CUMULUS: Ported upstream bridge default pvid support ++ * CUMULUS: Ported upstream bridge default pvid support ++ * CUMULUS: Fixed incorrect bond slave active state when slave is not in active aggregator. ++ * CUMULUS: Allow fdb replace when bridge port is in blocking state. ++ * CUMULUS: Suppress the installation of bridge member port local mac in fdb. ++ * CUMULUS: Fixed incorrect lacp mux state when actor or partner's aggregator is not active ++ * CUMULUS: Fixes for bond mode 2 ++ * CUMULUS: Modified vxlan driver's head end replication support based on upstream ++ * CUMULUS: Add support for lacp bypass with multiple active links ++ * CUMULUS: bridge: fixed spin lock issue in br_fdb_update() ++ * config: enable for amd64 kernel netfilter features enabled on powerpc ++ (Closes: CM-6699) ++ * bridge: update 'updated' as well as 'used' of fdb during replace ++ (Closes: CM-6830) ++ * bridge: enforce peerlink duallink forwarding check beyond igmp frames ++ (Closes: CM-6852) ++ * Revert "bridge: update 'updated' as well as 'used' of fdb during replace" ++ * bridge: fixed peerlink to duallink check in br_nf_forward_finish() ++ (Closes: CM-6973) ++ * Revert "CUMULUS: Ported upstream bridge default pvid support" ++ * bridge: exclude invalid pvid in netlink notification ++ * bridge: netlink: fixed fdb dump issue caused by incorrect message fragmentation handling ++ (Closes: CM-7223) ++ ++ [ Scott Feldman ] ++ * CUMULUS: Add IPv6 ECMP kernel support ++ * CUMULUS: Enable Phase I of LAG ++ * CUMULUS: Enable Phase I of LAG ++ * CUMULUS: LAG updates to advertised slave active status and bond speed/duplex ++ * CUMULUS: LAG updates to advertised slave active status and bond speed/duplex ++ * CUMULUS: LAG: signal high-level protocols of bond active/inactive status ++ * CUMULUS: tap: set speed/duplex before indicating carrier UP ++ * CUMULUS: ethtool infrastructure changes ++ * CUMULUS: Cleanup kernel tun patches in kernel ++ ++ [ Satish Ashok ] ++ * CUMULUS: bridge down procesing in mstpd ++ * CUMULUS: knob to select userspace/kernel stp ++ * CUMULUS: ipoptions fix for bridge with ebtables module ++ * CUMULUS: stp state sync ++ * CUMULUS: Enable igmp snooping ++ * CUMULUS: Enable igmp snooping ++ * CUMULUS: Enable igmp snooping ++ * CUMULUS: Enable igmp snooping ++ * CUMULUS: Enable igmp snooping ++ * CUMULUS: Enable igmp snooping ++ * CUMULUS: Enable igmp snooping ++ * CUMULUS: Enable igmp snooping ++ * CUMULUS: Enable igmp snooping ++ * CUMULUS: pull in upstream patch for mdb_init ++ * CUMULUS: pull in patches for querier/fast leave ++ * CUMULUS: pull in patches for querier/fast leave ++ * CUMULUS: pull in patches for querier/fast leave ++ * CUMULUS: pull in patches for querier/fast leave ++ * CUMULUS: pull in patches for querier/fast leave ++ * CUMULUS: pull in patches for querier/fast leave ++ * CUMULUS: pull in patches for querier/fast leave ++ * CUMULUS: pull in patches for querier/fast leave ++ * CUMULUS: pull in patches for querier/fast leave ++ * CUMULUS: pull in patches for querier/fast leave ++ * CUMULUS: pull in patches for querier/fast leave ++ * CUMULUS: ifupdown support, brctl commands, manpages ++ * CUMULUS: bridge driver mdb fixes ++ * CUMULUS: bridge driver mdb fixes ++ * CUMULUS: bridge driver mdb fixes ++ * CUMULUS: bridge mdb add fixes ++ * CUMULUS: pvst/rpvst interop fix ++ * CUMULUS: change defaults for mdb hash_max/elasticity ++ * CUMULUS: fast leave, querier IP fixes ++ * CUMULUS: fast leave, querier IP fixes ++ * CUMULUS: igmpv3/mldv2 report as leave processing ++ * CUMULUS: pvst/rpvst interop fix ++ * CUMULUS: Check for max mtu for tap device ++ * CUMULUS: stp disabled, BPDU received, to be forwarded ++ * CUMULUS: LACP PDU not sent on slave port sometimes ++ * CUMULUS: ignore solicited node multicast groups ++ * CUMULUS: static mdb entry add/del fixes ++ * CUMULUS: static mdb entry add/del fixes ++ * CUMULUS: mdb timer and temp router port ++ * CUMULUS: Add replace command for mdb ++ * CUMULUS: bridge address exclude all 0 mac ++ * CUMULUS: mdb replay on switchd restart ++ * CUMULUS: igmp/stp topology change convergence ++ * CUMULUS: fdb netlink notification on mac move for VM ++ * CUMULUS: exclude solicited node multicast from optimized router forwarding ++ * CUMULUS: IGMP report suppression in software, disable report/leave fwd in hw ++ * CUMULUS: Add peerLink/DualLink bridge port attributes ++ * CUMULUS: flush neighbor entries when carrier is off ++ * CUMULUS: fix mdb leave for dually-connected ++ * CUMULUS: remove wrong use of NLM_F_MULTI ++ * CUMULUS: remove wrong use of NLM_F_MULTI ++ * CUMULUS: disable config_bridge_vlan_filtering, fix compilation ++ * CUMULUS: fix for igmp/mld packet loop on peer link when dual link is present ++ * ipv4[cumulus-3.2.y]: remove unused variable in inet_dev_select_addr() ++ (Closes: CM-7056) ++ * ipv6[cumulus-3.2.y]: flush IPv6 neighbor entries when carrier is off ++ (Closes: CM-7155) ++ ++ [ mfine ] ++ * CUMULUS: Increase multicast max vifs ++ ++ [ Scott Emery ] ++ * CUMULUS: Allow Configuration of System ID in Bonding Driver ++ ++ [ Roopa Prabhu ] ++ * CUMULUS: Move neighbour.h to upstream latest (NDA_MASTER patch was accepted upstream) ++ * CUMULUS: Pull a few fdb dump in-kernel filtering patches from upstream ++ * CUMULUS: Pull a few fdb dump in-kernel filtering patches from upstream ++ * CUMULUS: Fix ethtool settings reset due to switchd restart ++ * CUMULUS: Support for fdb adds on a bridge device ++ * CUMULUS: Fix bridge fdb show when dev filter is bridge device ++ * CUMULUS: Add support for ethtool set settings in virtio-net driver. ++ * CUMULUS: First attempt to fix port locking issues around ethtool (re-checkin for shm as a separate patch) ++ * CUMULUS: backport rollback_registered_many fix for delete notification (details in the patch comment) ++ * CUMULUS: remove check for vid_end in bridge driver vlan setlink/dellink calls ++ * CUMULUS: Pull upstream commit that removes IFF_UP check during mtu change notification ++ * CUMULUS: make ethtool_get_settings not return -ENODATA to the user. Its ok to return 0 values when the driver has not sent us the data. ++ * CUMULUS: fix return of errors from switchd to the user ++ * CUMULUS: Include a check to physical and vlan interface on the physical (swp1 and swp1.100) in the allow multiple vlans check ++ * CUMULUS: Add support for NETIF_F_HW_SWITCH_OFFLOAD flag on swp ports and modify bridge driver to use the flag on making software forwarding decisions ++ * CUMULUS: cherry-pick vlan_features update in tun ++ * This patch is a cherry-pick from upstream but heavily modified for cumulus. We dont support a default vxlan remote dst today and so the upstream vxlan_mtu_change function is not really applicable (CCR-2905) ++ (Closes: CM-5198) ++ * kbuild: include kernel version in the package name (Closes: CM-5840) ++ * rtnetlink: remove unused func rtnl_fdb_notify (Closes: CM-6742) ++ * Revert "CUMULUS: Fix ipv6 duplicate nexthop cleanup on error" ++ (Closes: CM-5607) ++ * ipv6: replacing a rt6_info needs to purge possible propagated rt6_infos too ++ (Closes: CM-5607) ++ * ipv6: fix ECMP route replacement (Closes: CM-5607) ++ * ipv6: include NLM_F_REPLACE in route replace notifications (Closes: CM-5607) ++ * ipv6: fix multipath route replace error recovery (Closes: CM-7205) ++ * ipv6: fix typo in rt6_info compare function (Closes: CM-7310) ++ * ipv6: fix warning to print from fib6_config instead of rt6_info ++ (Closes: CM-7205) ++ * ipv6: fixes to some leaks in the ip6_multipath_add cleanup path ++ (Closes: CM-7205) ++ * ipv6: remove unnecessary in6_dev_put (Closes: CM-7205) ++ * rtnetlink: add an info level print to print NETDEV_UP/DOWN/CHANGE events ++ (Closes: CM-7024) ++ * vxlan: add tb null check during vxlan fdb delete (Closes: CM-3344) ++ * rtnetlink: dont print protodown state of an interface if it is not on ++ (Closes: CM-7504) ++ ++ [ Balakrishnan Raman ] ++ * CUMULUS: Enforce precedence for static over dynamic entry. use "bridge fdb replace" instead of "bridge fdb add" in vtepd ++ * CUMULUS: Support for VXLAN Head-end or Self Replication ++ * CUMULUS: Changes to optimize vxlan convergence issues ++ * CUMULUS: change ip_select_ident argument in vxlan driver to conform to kernel-3.2.57 changes ++ * CUMULUS: ++ * CUMULUS: ++ * vxlan: svcnode setting for vxlan device Changes to "ip link set" syntax for vxlan devices to not modify service node addresses if svcnode attribute is not specified. "svcnode 0.0.0.0" is needed to wipe out service node addresses. svcnode setting in vxlan driver is handled as follows: ++ * vxlan: vxlan fdb entry refresh should not send netlink notifications ++ (Closes: CM-6993) ++ * bridge: fdb cleanup in vxlan driver on move from remote vtep to local ++ (Closes: CM-3344) ++ * bridge: fdb cleanup in vxlan driver on mac move from remote vtep to local ++ (Closes: CM-7532) ++ ++ [ Andy Gospodarek ] ++ * CUMULUS: tun: restore default link/status behavior ++ * CUMULUS: bonding: make global bonding stats more reliable ++ * CUMULUS: deactivate routes assigned to an interface on carrier down ++ * CUMULUS: bonding: fix race between sysfs and bond_enslave ++ * CUMULUS: net: fixup dead route issues ++ * CUMULUS: ipv6: fix issues with routes on interfaces with down link ++ * CUMULUS: ipv6: don't disable interface if last ipv6 address is removed ++ * CUMULUS: kernel: fix route lookup failures when link down ++ * CUMULUS: bonding: fix scheduling while atomic on slave release ++ * CUMULUS: kernel: fix BUG-halt when eth0 receives VLAN tagged traffic ++ * config: enable CONFIG_AUFS ++ ++ [ Dave Olson ] ++ * CUMULUS: Size of L2 cache was not in /sys, and caused lscpu to fail ++ * CUMULUS: Add x86 watchdog support by backporting ie6xx_wdt.c and patches for iTCO_wdt.c ++ * CUMULUS: Add x86 watchdog support by backporting ie6xx_wdt.c and patches for iTCO_wdt.c ++ * CUMULUS: Implement using CPLD reset for ARM DNI-3448, rather than normal ACPI method ++ ++ [ Sam Tannous ] ++ * CUMULUS: Forgot to add the actual patch network-bridge-reset-bridge-mtu-after-deleting-an-interface.patch ++ ++ [ samer ] ++ * CUMULUS: S3000: Power cycle the switch (via CPLD) in response to CL reboot command ++ * CUMULUS: BCM56150 (Hurricane2): Force PCIe link speed to Gen1 (2.5GT/s) to work around Hurricane2 uncorrectable PCIe errors ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: ARM: Preliminary ARM kernel / DNI 3448 platform support ++ * CUMULUS: DNI3448P: Add support for 4GB NAND flash ++ * CUMULUS: ARM: Fix Linux reboot issue, added ARM watchdog infra ++ * CUMULUS: Increase per-CPU dynamic reserved memory ++ * CUMULUS: DNI3448P: Add support for 4GB NAND Flash ++ * CUMULUS: ARM/Helix4: Update Broadcom (iProc) GMAC (eth0) driver relevant to Helix4 to the version contained in Broadcom LDK 3.5.5_RC1 ++ * CUMULUS: ARM: Bump i2c speed to 400KHz ++ * CUMULUS: DNI-3448P: Fix u-boot environment partition offsets ++ * ARM: Enable CONFIG_HIGHMEM (required to take advantage of full DRAM range on 2GB ARM systems) ++ * ARM: Set smbus speeds to 100KHz with the exception of AS4610-54P bus 0 (needs to be 400KHz) ++ * ARM: Temporarily disable CONFIG_HIGHMEM due to instability ++ * ARM: Re-enable CONFIG_HIGHMEM in order to take advantage of full DRAM range on 1G and 2G ARM platforms ++ * dts: update Accton AS4610-54P device tree source (Closes: CM-6881) ++ * dts/arch/driver: Updates to reflect DNI-supplied 3448P ONIE flash layout ++ (Closes: CM-6882) ++ ++ [ Dinesh G Dutt ] ++ * CUMULUS: Add support for mgmt VRF via ip rules ++ * CUMULUS: Add support for mgmt VRF via ip rules ++ * net: Fix compilation warnings caused by mgmtMRF patch ++ (Closes: CM-7054, CM-7055) ++ ++ [ Ellen Wang ] ++ * Fix size mismatch in dni_dps460.c. ++ * Fix i2c-i801 driver to recover from PEC errors. ++ * Add adt7470 driver to the amd64 build. ++ ++ [ Thadeu Lima de Souza Cascardo ] ++ * bridge: fix parsing of MLDv2 reports ++ ++ [ Grant Likely ] ++ * of: Add of_property_match_string() to find index into a string list ++ (Closes: CM-6836) ++ ++ [ Thierry Reding ] ++ * dt: Add empty of_property_match_string() function (Closes: CM-6836) ++ ++ [ Anton Blanchard ] ++ * powerpc: Make logical to real cpu mapping code endian safe (Closes: CM-6836) ++ ++ [ Scott Wood ] ++ * powerpc: Don't skip ePAPR spin-table CPUs (Closes: CM-6836) ++ ++ [ Vlad Yasevich ] ++ * bridge: Allow clearing of pvid and untagged bitmap ++ ++ [ Nikolay Aleksandrov ] ++ * bridge: netlink: add support for vlan_filtering attribute (Closes: CM-6806) ++ * net: make rtnl_fdb_dump release rcu lock on device lookup failure ++ (Closes: CM-7330) ++ * net: port: initialize err in port_send_cached_settings (Closes: CM-7332) ++ ++ [ Anuradha Karuppiah ] ++ * net core: Add protodown support. (Closes: CM-6387) ++ ++ [ Marcelo Ricardo Leitner ] ++ * sctp: fix ASCONF list handling (Closes: CM-7048) ++ ++ [ Al Viro ] ++ * sg_start_req(): make sure that there's not too many elements in iovec ++ (Closes: CM-7048) ++ ++ [ Benjamin Randazzo ] ++ * md: use kzalloc() when bitmap is disabled (Closes: CM-7048) ++ ++ [ Matti Vaittinen ] ++ * IPv6 routing, NLM_F_* flag support: REPLACE and EXCL flags support, warn about missing CREATE flag ++ (Closes: CM-5607) ++ * IPv6: Removing unnecessary NULL checks. (Closes: CM-5607) ++ * IPV6 Fix a crash when trying to replace non existing route (Closes: CM-5607) ++ ++ [ Hannes Frederic Sowa ] ++ * ipv6: only static routes qualify for equal cost multipathing ++ (Closes: CM-5607) ++ ++ [ Michal KubeÄek ] ++ * ipv6: do not delete previously existing ECMP routes if add fails ++ (Closes: CM-2669, CM-5607) ++ ++ [ David Ahern ] ++ * net: Flush cached IPv6 route entries on NETDEV_CHANGEADDR event ++ (Closes: CM-7265) ++ ++ -- Jonathan Toppins Mon, 21 Sep 2015 19:35:02 -0400 ++ ++linux (3.2.65-1+deb7u2) wheezy-security; urgency=medium ++ ++ * splice: Apply generic position and size checks to each write ++ (CVE-2014-7822) ++ * crypto: Fix unprivileged arbitrary module loading (CVE-2013-7421, ++ CVE-2014-9644) ++ - prefix module autoloading with "crypto-" ++ - include crypto- module prefix in template ++ - add missing crypto module aliases ++ * netfilter: conntrack: disable generic tracking for known protocols ++ (CVE-2014-8160) ++ * [amd64] vdso: Fix the vdso address randomization algorithm (CVE-2014-9585) ++ * [x86] KVM: x86 emulator: reject SYSENTER in compatibility mode on AMD ++ guests ++ * [x86] KVM: SYSENTER emulation is broken (CVE-2015-0239) ++ * vfs: move d_rcu from overlapping d_child to overlapping d_alias ++ * aufs: move d_rcu from overlapping d_child to overlapping d_alias ++ * vfs: deal with deadlock in d_walk() (CVE-2014-8559) ++ * vfs: read file_handle only once in handle_to_path (CVE-2015-1420) ++ * ASLR: fix stack randomization on 64-bit systems (CVE-2015-1593) ++ * vfs: Fix vfsmount_lock imbalance in path_init() (regression in 3.2.64) ++ * net: sctp: fix slab corruption from use after free on INIT collisions ++ (CVE-2015-1421) ++ * Fix regressions caused by CVE-2014-8133 fix: ++ - [amd64] tls, ldt: Stop checking lm in LDT_empty ++ - [x86] tls: Interpret an all-zero struct user_desc as "no segment" ++ * eCryptfs: Remove buggy and unnecessary write in file name decode ++ routine (CVE-2014-9683) ++ ++ -- Ben Hutchings Fri, 20 Feb 2015 02:39:08 +0000 ++ ++linux (3.2.65-1+deb7u1) wheezy-security; urgency=medium ++ ++ * [amd64] Revert NX changes that caused a regresion in 3.2.65 ++ (Closes: #774436) ++ - Revert "x86, mm: Set NX across entire PMD at boot" ++ - Revert "x86, 64bit, mm: Mark data/bss/brk to nx" ++ * [x86] cpu, amd: Add workaround for family 16h, erratum 793 (CVE-2013-6885) ++ * [x86] tls: Validate TLS entries to protect espfix (CVE-2014-8133) ++ * [amd64] switch_to(): Load TLS descriptors before switching DS and ES ++ (CVE-2014-9419) ++ * KEYS: close race between key lookup and freeing (CVE-2014-9529) ++ * isofs: Fix unchecked printing of ER records (CVE-2014-9584) ++ ++ -- Ben Hutchings Mon, 12 Jan 2015 16:06:56 +0000 ++ ++linux (3.2.65-1) wheezy; urgency=medium ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.64 ++ - percpu: fix pcpu_alloc_pages() failure path ++ - percpu: perform tlb flush after pcpu_map_pages() failure ++ - cgroup: reject cgroup names with '\n' ++ - [s390*] KVM: Fix user triggerable bug in dead code ++ - regmap: Fix handling of volatile registers for format_write() chips ++ - Revert "iwlwifi: dvm: don't enable CTS to self" (regression in 3.2.62) ++ - aio: add missing smp_rmb() in read_events_ring ++ - block: Fix dev_t minor allocation lifetime ++ - uwb: init beacon cache entry before registering uwb device ++ - perf: Fix a race condition in perf_remove_from_context() ++ - libceph: gracefully handle large reply messages from the mon ++ - libceph: add process_one_ticket() helper ++ - libceph: do not hard code max auth ticket len ++ - usb: hub: take hub->hdev reference when processing from eventlist ++ - futex: Unlock hb->lock in futex_wait_requeue_pi() error path ++ - alarmtimer: Return relative times in timer_gettime ++ - alarmtimer: Do not signal SIGEV_NONE timers ++ - alarmtimer: Lock k_itimer during timer callback ++ - vfs: don't bugger nd->seq on set_root_rcu() from follow_dotdot_rcu() ++ - vfs: Fold follow_mount_rcu() into follow_dotdot_rcu() ++ - vfs: be careful with nd->inode in path_init() and follow_dotdot_rcu() ++ - iscsi-target: Fix memory corruption in iscsit_logout_post_handler_diffcid ++ - NFSv4: Fix another bug in the close/open_downgrade code ++ - libiscsi: fix potential buffer overrun in __iscsi_conn_send_pdu ++ - nl80211: clear skb cb before passing to netlink ++ - ALSA: pcm: fix fifo_size frame calculation ++ - Fix nasty 32-bit overflow bug in buffer i/o code. ++ - sched: Fix unreleased llc_shared_mask bit during CPU hotplug ++ - [armhf] 8165/1: alignment: don't break misaligned NEON load/store ++ - nilfs2: fix data loss with mmap() ++ - ocfs2/dlm: do not get resource spinlock if lockres is new ++ (regression in 3.2) ++ - shmem: fix nlink for rename overwrite directory ++ - mm: migrate: Close race between migration completion and mprotect ++ - perf: fix perf bug in fork() ++ - [mips*] Fix forgotten preempt_enable() when CPU has inclusive pcaches ++ - ipv4: move route garbage collector to work queue ++ - ipv4: avoid parallel route cache gc executions ++ - ipv4: disable bh while doing route gc ++ - ipv6: reallocate addrconf router for ipv6 address when lo device up ++ (regression in 3.2.50) ++ - [x86] kvm,vmx: Preserve CR4 across VM entry ++ - ipvs: avoid netns exit crash on ip_vs_conn_drop_conntrack ++ - ring-buffer: Fix infinite spin in reading buffer (regression in 3.2.63) ++ - genhd: fix leftover might_sleep() in blk_free_devt() ++ - [x86] KVM: Fix far-jump to non-canonical check ++ (regression in 3.2.63-2+deb7u1) ++ - l2tp: fix race while getting PMTU on PPP pseudo-wire ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.65 ++ - [x86] kvm: fix stale mmio cache bug ++ - UBIFS: fix a race condition ++ - [s390*] KVM: unintended fallthrough for external call ++ - ext4: check EA value offset when loading ++ - v4l2-common: fix overflow in v4l_bound_align_image() ++ - Revert "lzo: properly check for overruns" ++ - lzo: check for length overrun in variable length encoding. ++ - NFSv4: fix open/lock state recovery error handling ++ - NFSv4.1: Fix an NFSv4.1 state renewal regression ++ - target: Fix queue full status NULL pointer for SCF_TRANSPORT_TASK_SENSE ++ - vfs: fix data corruption when blocksize < pagesize for mmaped data ++ - dm bufio: update last_accessed when relinking a buffer ++ - ext4: don't orphan or truncate the boot loader inode ++ - ext4: add ext4_iget_normal() which is to be used for dir tree lookups ++ - ecryptfs: avoid to access NULL pointer when write metadata in xattr ++ - fs: make cont_expand_zero interruptible ++ - fix misuses of f_count() in ppp and netlink ++ - block: fix alignment_offset math that assumes io_min is a power-of-2 ++ - fanotify: enable close-on-exec on events' fd when requested in ++ fanotify_init() ++ - selinux: fix inode security list corruption ++ - random: add and use memzero_explicit() for clearing data ++ - dm raid: ensure superblock's size matches device's logical block size ++ - scsi: Fix error handling in SCSI_IOCTL_SEND_COMMAND ++ - usb: serial: ftdi_sio: add "bricked" FTDI device PID ++ - nfsd4: fix crash on unknown operation number ++ - [x86] kvm: don't kill guest on unknown exit reason ++ - posix-timers: Fix stack info leak in timer_create() ++ - futex: Fix a race condition between REQUEUE_PI and task death ++ - ALSA: pcm: Zero-clear reserved fields of PCM status ioctl in compat mode ++ - zap_pte_range: update addr when forcing flush after TLB batching faiure ++ - mm, thp: fix collapsing of hugepages on madvise ++ - lib/bitmap.c: fix undefined shift in __bitmap_shift_{left|right}() ++ - ext4: fix overflow when updating superblock backups after resize ++ - ext4: bail out from make_indexed_dir() on first error ++ - tracing/syscalls: Fix perf syscall tracing when syscall_nr == -1 ++ - tracing/syscalls: Ignore numbers outside NR_syscalls' range ++ - mac80211: fix use-after-free in defragmentation ++ - xhci: no switching back on non-ULT Haswell (regression in 3.2.53) ++ - audit: keep inode pinned ++ - libceph: do not crash on large auth tickets ++ - firewire: cdev: prevent kernel stack leaking into ioctl arguments ++ - iio: Fix IIO_EVENT_CODE_EXTRACT_DIR bit mask ++ - [x86] Require exact match for 'noxsave' command line option ++ - [amd64] mm: Mark data/bss/brk to nx ++ - [amd64] mm: Set NX across entire PMD at boot ++ - SUNRPC: Fix locking around callback channel reply receive ++ - bnx2fc: do not add shared skbs to the fcoe_rx_list ++ - Revert "xhci: clear root port wake on bits if controller isn't wake-up ++ capable" (regression in 3.2.62) ++ - [amd64] ALSA: hda - Limit 40bit DMA for AMD HDMI controllers ++ - mei: add mei_quirk_probe function ++ - tcp: be more strict before accepting ECN negociation ++ - hpsa: fix a race in cmd_free/scsi_done ++ - mm: Remove false WARN_ON from pagecache_isize_extended() ++ ++ [ Ben Hutchings ] ++ * [rt] Update to 3.2.64-rt94: ++ - sched: Do not clear PF_NO_SETAFFINITY flag in select_fallback_rq() ++ - workqueue: Prevent deadlock/stall on RT ++ - hrtimer:fix the miss of hrtimer_peek_ahead_timers in nort code ++ - lockdep: Fix backport of "Correctly annotate hardirq context in ++ irq_exit()" ++ * drm, agp: Update to 3.4.105: ++ - drm/i915: Remove bogus __init annotation from DMI callbacks ++ - drm/vmwgfx: Fix a potential infinite spin waiting for fifo idle ++ - drm/radeon: add connector quirk for fujitsu board ++ * [x86] KVM: Don't report guest userspace emulation error to userspace ++ (CVE-2014-7842) ++ * [x86] kvm: Clear paravirt_enabled on KVM guests for espfix32's benefit ++ (CVE-2014-8134) ++ * isofs: Fix infinite looping over CE entries (CVE-2014-9420) ++ ++ -- Ben Hutchings Mon, 29 Dec 2014 02:50:43 +0100 ++ ++linux (3.2.63-2+deb7u2) wheezy-security; urgency=high ++ ++ * Revert "drivers/net: Disable UFO through virtio" in macvtap and tun. ++ This removes the need to shut down VMs if migrating to a patched ++ host. ++ * ip: Fix backport of "ip: make IP identifiers less predictable" ++ (regression in 3.2.63) (thanks to Jeffrey Knockel) ++ * net: sctp: fix NULL pointer dereference in af->from_addr_param on ++ malformed packet (CVE-2014-7841) ++ * kvm: fix excessive pages un-pinning in kvm_iommu_map error path. ++ (CVE-2014-8369) ++ * media: ttusb-dec: buffer overflow in ioctl (CVE-2014-8884) ++ * [amd64] traps: Stop using IST for #SS (CVE-2014-9090) ++ * [amd64] traps: Fix the espfix64 #DF fixup and rewrite it in C ++ * [amd64] traps: Rework bad_iret ++ ++ -- Ben Hutchings Sun, 07 Dec 2014 03:42:14 +0000 ++ ++linux (3.2.63-2+deb7u1) wheezy-security; urgency=high ++ ++ * drivers/net,ipv6: Fix virtio/IPv6 regression in 3.2.63: ++ - ipv6: reuse ip6_frag_id from ip6_ufo_append_data (Closes: #766195) ++ (CVE-2014-7207) ++ - drivers/net: Disable UFO through virtio ++ - drivers/net,ipv6: Select IPv6 fragment idents for virtio UFO packets ++ * [x86] KVM: Check non-canonical addresses upon WRMSR (CVE-2014-3610) ++ * [x86] KVM: Improve thread safety in pit (CVE-2014-3611) ++ * [x86] KVM: nEPT: Nested INVEPT (CVE-2014-3645) ++ * [x86] kvm: vmx: handle invvpid vm exit gracefully (CVE-2014-3646) ++ * [x86] KVM: emulator: Use opcode::execute for CALL ++ * [x86] KVM: Fix wrong masking on relative jump/call ++ * [x86] KVM: Emulator fixes for eip canonical checks on near branches ++ (CVE-2014-3647) ++ * [x86] KVM: use new CS.RPL as CPL during task switch ++ * [x86] KVM: Handle errors when RIP is set during far jumps (CVE-2014-3647) ++ * net: sctp: fix skb_over_panic when receiving malformed ASCONF chunks ++ (CVE-2014-3673) ++ * net: sctp: fix panic on duplicate ASCONF chunks (CVE-2014-3687) ++ * net: sctp: fix remote memory pressure from excessive queueing ++ (CVE-2014-3688) ++ * [x86] kvm,vmx: Preserve CR4 across VM entry (CVE-2014-3690) ++ ++ -- Ben Hutchings Wed, 29 Oct 2014 23:35:20 +0000 ++ ++linux (3.2.63-2) wheezy; urgency=medium ++ ++ * [s390*] Ignore ABI change in lowcore structure (fixes FTBFS) ++ ++ -- Ben Hutchings Mon, 29 Sep 2014 22:35:33 +0100 ++ ++linux (3.2.63-1) wheezy; urgency=medium ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.61 ++ - mm: highmem: don't treat PKMAP_ADDR(LAST_PKMAP) as a highmem address ++ - UBIFS: fix an mmap and fsync race condition ++ - HID: core: fix validation of report id 0 ++ - IB/srp: Fix a sporadic crash triggered by cable pulling ++ - reiserfs: drop vmtruncate ++ - reiserfs: call truncate_setsize under tailpack mutex ++ - [arm] 8051/1: put_user: fix possible data corruption in put_user ++ - ext4: fix zeroing of page during writeback ++ - ext4: fix wrong assert in ext4_mb_normalize_request() ++ - USB: sierra: fix remote wakeup ++ - USB: option: fix runtime PM handling ++ - USB: usb_wwan: fix race between write and resume ++ - USB: usb_wwan: fix write and suspend race ++ - USB: usb_wwan: fix urb leak at shutdown ++ - USB: cdc-acm: Fix various bugs in power management ++ - USB: io_ti: fix firmware download on big-endian machines (part 2) ++ - md: always set MD_RECOVERY_INTR when aborting a reshape or other ++ "resync". ++ - [s390] lowcore: reserve 96 bytes for IRB in lowcore ++ - rtmutex: Fix deadlock detector for real ++ - xhci: delete endpoints from bandwidth list before freeing whole device ++ - IB/umad: Fix error handling ++ - RDMA/cxgb4: Fix four byte info leak in c4iw_create_cq() ++ - nfsd: getattr for FATTR4_WORD0_FILES_AVAIL needs the statfs buffer ++ - UBIFS: Remove incorrect assertion in shrink_tnc() ++ - nfsd4: use recall_lock for delegation hashing ++ - iscsi-target: Reject mutual authentication with reflected CHAP_C ++ - ptrace: fix fork event messages across pid namespaces ++ - idr: fix overflow bug during maximum ID calculation at maximum height ++ - Input: synaptics - fix resolution for manually provided min/max ++ (regression in 3.2.57) ++ - nfsd4: fix FREE_STATEID lockowner leak (regression in 3.2.60) ++ - Btrfs: fix double free in find_lock_delalloc_range ++ - mm: rmap: fix use-after-free in __put_anon_vma ++ - rtmutex: Handle deadlock detection smarter ++ - rtmutex: Detect changes in the pi lock chain ++ - rtmutex: Plug slow unlock race ++ - Bluetooth: Fix check for connection encryption ++ - Bluetooth: Fix SSP acceptor just-works confirmation without MITM ++ - tracing: Fix syscall_*regfunc() vs copy_process() race ++ - lib/lzo: Update LZO compression to current upstream version ++ - lzo: properly check for overruns (CVE-2014-4608) ++ - hugetlb: fix copy_hugetlb_page_range() to handle migration/hwpoisoned ++ entry ++ - mm: fix crashes from mbind() merging vmas ++ - [mips] MSC: Prevent out-of-bounds writes to MIPS SC ioremap'd region ++ - SCSI: Stop accepting SCSI requests before removing a device ++ - SCSI: fix our current target reap infrastructure ++ - SCSI: dual scan thread bug fix ++ - perf: Fix race in removing an event ++ - netlink: rate-limit leftover bytes warning and print process name ++ - net: tunnels - enable module autoloading ++ - net: fix inet_getid() and ipv6_select_ident() bugs ++ - target: Explicitly clear ramdisk_mcp backend pages ++ - iommu/vt-d: Fix missing IOTLB flush in intel_iommu_unmap() ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.62 ++ - ibmvscsi: Add memory barriers for send / receive ++ - cpuset,mempolicy: fix sleeping function called from invalid context ++ - nfsd: fix rare symlink decoding bug ++ - md: flush writes before starting a recovery. ++ - drm/vmwgfx: Fix incorrect write to read-only register v2: ++ (regression in 3.2.58) ++ - ACPI / EC: Avoid race condition related to advance_transaction() ++ - ACPI / EC: Fix race condition in ec_transaction_completed() ++ - hwmon: (adm1031) Fix writes to limit registers ++ - alarmtimer: Fix bug where relative alarm timers were treated as absolute ++ - dm io: fix a race condition in the wake up code for sync_io ++ - sched: Fix possible divide by zero in avg_atom() calculation ++ - locking/mutex: Disable optimistic spinning on some architectures ++ - hwmon: (adt7470) Fix writes to temperature limit registers ++ - usb: Check if port status is equal to RxDetect (regression in 3.2.38) ++ - tcp: fix tcp_match_skb_to_sack() for unaligned SACK at end of an skb ++ - igmp: fix the problem when mc leave group ++ - appletalk: Fix socket referencing in skb ++ - net: sctp: fix information leaks in ulpevent layer ++ - dns_resolver: assure that dns_query() result is null-terminated ++ - dns_resolver: Null-terminate the right string ++ - rtnetlink: fix userspace API breakage for iproute2 < v3.9.0 ++ (regression in 3.2.45) ++ - netfilter: ipt_ULOG: fix info leaks ++ - xfs: fix allocbt cursor leak in xfs_alloc_ag_vextent_near ++ - xfs: really fix the cursor leak in xfs_alloc_ag_vextent_near ++ - shmem: fix faulting into a hole, not taking i_mutex (CVE-2014-4171) ++ - shmem: fix splicing from a hole while it's punched (CVE-2014-4171) ++ - [x86] x86-32, espfix: Remove filter for espfix32 due to race ++ - sym53c8xx_2: Set DID_REQUEUE return code when aborting squeue ++ - mm: hugetlb: fix copy_hugetlb_page_range() (regression in 3.2.61) ++ - [arm*] 7668/1: fix memset-related crashes caused by recent GCC (4.7.2) ++ optimizations ++ - [arm*] 7670/1: fix the memset fix ++ - ceph: fix overflow check in build_snap_context() ++ - libata: support the ata host which implements a queue depth less than 32 ++ (regression in 3.2.59) ++ - libata: introduce ata_host->n_tags to avoid oops on SAS controllers ++ - [x86] x86_32, entry: Store badsys error code in %eax ++ (regression in 3.2.60-1) ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.63 ++ - [x86] KVM: Inter-privilege level ret emulation is not implemeneted ++ - block: don't assume last put of shared tags is for the host ++ - debugfs: Fix corrupted loop in debugfs_remove_recursive ++ - mtd/ftl: fix the double free of the buffers allocated in build_maps() ++ - [x86] don't exclude low BIOS area when allocating address space for ++ non-PCI cards (regression in 2.6.37) ++ - scsi: handle flush errors properly ++ - hwmon: (smsc47m192) Fix temperature limit and vrm write operations ++ - staging: vt6655: Fix Warning on boot handle_irq_event_percpu. ++ - [mips,powerpc] bfa: Fix undefined bit shift on big-endian architectures ++ with 32-bit DMA address ++ - Drivers: scsi: storvsc: Implement a eh_timed_out handler ++ - iommu/vt-d: Exclude devices using RMRRs from IOMMU API domains ++ - net: sendmsg: fix NULL pointer dereference ++ - hwmon: (ads1015) Fix off-by-one for valid channel index checking ++ - [mips*] tlbex: Fix a missing statement for HUGETLB ++ - [mips*] Prevent user from setting FCSR cause bits ++ - md/raid1,raid10: always abort recover on write error. ++ - ext4: fix ext4_discard_allocated_blocks() if we can't allocate the pa ++ struct ++ - hwmon: (lm85) Fix various errors on attribute writes ++ - hwmon: (amc6821) Fix possible race condition bug ++ - crypto: af_alg - properly label AF_ALG socket ++ - mnt: Change the default remount atime from relatime to the existing value ++ - netlabel: fix a problem when setting bits below the previously lowest bit ++ - ALSA: virtuoso: Xonar DSX support (Closes: #721346) ++ - hwmon: (ads1015) Fix out-of-bounds array access ++ - [s390*] locking: Reenable optimistic spinning ++ - ring-buffer: Always reset iterator to reader page ++ - reiserfs: Fix use after free in journal teardown ++ - [powerpc*] mm: Use read barrier when creating real_pte ++ - Btrfs: fix csum tree corruption, duplicate and outdated checksums ++ - CIFS: Fix wrong directory attributes after rename ++ - md/raid6: avoid data corruption during recovery of double-degraded RAID6 ++ - iommu/amd: Fix cleanup_domain for mass device removal ++ - pata_scc: propagate return value of scc_wait_after_reset ++ - kvm: iommu: fix the third parameter of kvm_iommu_put_pages ++ (CVE-2014-3601) ++ - [mips*/octeon] make get_system_type() thread-safe ++ - xhci: rework cycle bit checking for new dequeue pointers ++ (regression in 3.2.59) ++ - isofs: Fix unbounded recursion when processing relocated directories ++ (CVE-2014-5471, CVE-2014-5472) ++ - HID: logitech: perform bounds checking on device_id early enough ++ (CVE-2014-3182) ++ - USB: whiteheat: Added bounds checking for bulk command response ++ (CVE-2014-3183, CVE-2014-3184, CVE-2014-3185) ++ - HID: logitech-dj: prevent false errors to be shown ++ - ACPI / EC: Add support to disallow QR_EC to be issued when SCI_EVT isn't ++ set (regression in 3.2.62) ++ - HID: magicmouse: sanity check report size in raw_event() callback ++ (CVE-2014-3181) ++ - HID: picolcd: sanity check report size in raw_event() callback ++ (CVE-2014-3186) ++ - [armhf] 8128/1: abort: don't clear the exclusive monitors ++ - [armhf] 8129/1: errata: work around Cortex-A15 erratum 830321 using dummy ++ strex ++ - USB: serial: fix potential stack buffer overflow ++ - USB: serial: fix potential heap buffer overflow ++ - [mips*] Fix accessing to per-cpu data when flushing the cache ++ - inetpeer: get rid of ip_id_count ++ - ip: make IP identifiers less predictable ++ - tcp: Fix integer-overflows in TCP veno ++ - tcp: Fix integer-overflow in TCP vegas ++ - net: sctp: inherit auth_capable on INIT collisions (CVE-2014-5077) ++ - iovec: make sure the caller actually wants anything in ++ memcpy_fromiovecend ++ - sctp: fix possible seqlock seadlock in sctp_packet_transmit() ++ - [sparc] Fix argument sign extension for compat_sys_futex(). ++ - [sparc] Handle 32-bit tasks properly in compute_effective_address(). ++ - [sparc] Fix top-level fault handling bugs. ++ - [sparc] Don't bark so loudly about 32-bit tasks generating 64-bit fault ++ addresses. ++ - [sparc] Fix huge TSB mapping on pre-UltraSPARC-III cpus. ++ - [sparc] Add membar to Niagara2 memcpy code. ++ - [sparc] Do not insert non-valid PTEs into the TSB hash table. ++ - [sparc] arch/sparc/math-emu/math_32.c: drop stray break operator ++ - [amd64] Revert "x86-64, modify_ldt: Make support for 16-bit segments a ++ runtime option" ++ - [amd64] x86-64, espfix: Don't leak bits 31:16 of %esp returning to 16-bit ++ stack ++ - [amd64] x86_64/entry/xen: Do not invoke espfix64 on Xen ++ - [amd64] x86/espfix/xen: Fix allocation of pages for paravirt page tables ++ ++ [ Ben Hutchings ] ++ * drm, agp: Update to 3.4.103: ++ - drm/radeon: only apply hdmi bpc pll flags when encoder mode is hdmi ++ - drm/radeon: fix typo in radeon_connector_is_dp12_capable() ++ - drm/radeon/atom: fix dithering on certain panels ++ - drm/vmwgfx: Fix incorrect write to read-only register v2: ++ - drm/radeon: stop poisoning the GART TLB ++ * nfsd: Fix ACL null pointer deref (thanks to Sergio Gelato) ++ (Closes: #754420) ++ * ext4: fix BUG_ON in mb_free_blocks() (regression in 3.2.63) ++ * udf: Avoid infinite loop when processing indirect ICBs (CVE-2014-6410) ++ * libceph: do not hard code max auth ticket len (CVE-2014-6416, ++ CVE-2014-6417, CVE-2014-6418) ++ * sp5100_tco: Reject SB8x0 chips (Closes: #726150) ++ * udeb: Add pata_rdc to pata-modules (Closes: #633128) ++ ++ [ Cyril Brulebois ] ++ * udeb: Add virtio_scsi to virtio-modules (Closes: #756249). ++ ++ -- Ben Hutchings Sat, 27 Sep 2014 13:36:53 +0100 ++ ++linux (3.2.60-1+deb7u3) wheezy-security; urgency=medium ++ ++ * net/l2tp: don't fall back on UDP [get|set]sockopt (CVE-2014-4943) ++ * sctp: Fix sk_ack_backlog wrap-around problem (CVE-2014-4667) ++ * [s390,s390x] ptrace: fix PSW mask check (CVE-2014-3534) (Closes: #728705) ++ ++ -- Ben Hutchings Wed, 23 Jul 2014 13:12:02 +0100 ++ ++linux (3.2.60-1+deb7u2) wheezy-security; urgency=medium ++ ++ * Revert "net: ipv4: ip_forward: fix inverted local_df test" ++ (regression in 3.2.60) (Closes: #754173) ++ * Revert "net: ip, ipv6: handle gso skbs in forwarding path" ++ (regression in 3.2.57) ++ ++ -- Ben Hutchings Sun, 20 Jul 2014 23:54:34 +0100 ++ ++linux (3.2.60-1+deb7u1) wheezy-security; urgency=high ++ ++ * Non-maintainer upload by the Security Team. ++ * CVE-2014-4699: ptrace,x86: force IRET path after a ptrace_stop() ++ ++ -- Salvatore Bonaccorso Fri, 04 Jul 2014 23:21:05 +0200 ++ ++linux (3.2.60-1) wheezy; urgency=medium ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.58 ++ - net: sctp: fix skb leakage in COOKIE ECHO path of chunk->auth_chunk ++ - bridge: multicast: add sanity check for query source addresses ++ - net: unix: non blocking recvmsg() should not return -EINTR ++ (regression in 2.6.38) ++ - net: socket: error on a negative msg_namelen (regression in 3.2.53-1) ++ - ipv6: ip6_append_data_mtu do not handle the mtu of the second fragment ++ properly (regression in 3.2.50) ++ - xen-netback: remove pointless clause from if statement ++ - ipv6: some ipv6 statistic counters failed to disable bh ++ - netlink: don't compare the nul-termination in nla_strcmp ++ - [sparc] PCI: Fix incorrect address calculation of PCI Bridge windows on ++ Simba-bridges ++ - [sparc] Revert "sparc64: Fix __copy_{to,from}_user_inatomic defines." ++ - [sparc] sparc64: don't treat 64-bit syscall return codes as 32-bit ++ - [arm] mm: introduce present, faulting entries for PAGE_NONE ++ - Btrfs: skip submitting barrier for missing device ++ - jffs2: remove from wait queue after schedule() ++ - jffs2: Fix segmentation fault found in stress test ++ - jffs2: Fix crash due to truncation of csize ++ - iwlwifi: dvm: take mutex when sending SYNC BT config command ++ - ext4: fix partial cluster handling for bigalloc file systems ++ - IB/ipath: Fix potential buffer overrun in sending diag packet routine ++ - IB/nes: Return an error on ib_copy_from_udata() failure instead of NULL ++ - mfd: Include all drivers in subsystem menu ++ - audit: convert PPIDs to the inital PID namespace. ++ - Btrfs: fix deadlock with nested trans handles ++ - nfsd4: buffer-length check for SUPPATTR_EXCLCREAT ++ - nfsd4: session needs room for following op to error out ++ - dm thin: fix dangling bio in process_deferred_bios error path ++ - nfsd4: fix setclientid encode size ++ - [mips] Hibernate: Flush TLB entries in swsusp_arch_resume() ++ - IB/mthca: Return an error on ib_copy_to_udata() failure ++ - IB/ehca: Returns an error on ib_copy_to_udata() failure ++ - reiserfs: fix race in readdir ++ - ocfs2: dlm: fix lock migration crash ++ - ocfs2: do not put bh when buffer_uptodate failed ++ - iscsi-target: Fix ERL=2 ASYNC_EVENT connection pointer bug ++ - wait: fix reparent_leader() vs EXIT_DEAD->EXIT_ZOMBIE race ++ - [amd64] modify_ldt: Ban 16-bit segments on 64-bit kernels ++ - target/tcm_fc: Fix use-after-free of ft_tpg ++ - [x86] drivers: hv: additional switch to use mb() instead of smp_mb() ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.59 ++ - ext4: FIBMAP ioctl causes BUG_ON due to handle EXT_MAX_BLOCKS ++ - ext4: note the error in ext4_end_bio() ++ - ext4: use i_size_read in ext4_unaligned_aio() ++ - locks: allow __break_lease to sleep even when break_time is 0 ++ - libata/ahci: accommodate tag ordered controllers ++ - mm: make fixup_user_fault() check the vma access rights too ++ - Btrfs: Don't allocate inode that is already in use ++ - Btrfs: fix inode caching vs tree log ++ - USB: io_ti: fix firmware download on big-endian machines ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.60 ++ - netfilter: Can't fail and free after table replacement ++ - net: core: don't account for udp header size when computing seglen ++ (regression in 3.2.57) ++ - rtnetlink: Only supply IFLA_VF_PORTS information when RTEXT_FILTER_VF ++ is set ++ - sctp: reset flowi4_oif parameter on route lookup (regression in 3.0) ++ - Revert "macvlan : fix checksums error when we are in bridge mode" ++ (regression in 2.6.39) ++ - tcp_cubic: fix the range of delayed_ack ++ - net: ipv4: ip_forward: fix inverted local_df test (regression in 3.2.57) ++ - ipv4: fib_semantics: increment fib_info_cnt after fib_info allocation ++ - act_mirred: do not drop packets when fails to mirror it ++ - ipv4: initialise the itag variable in __mkroute_input ++ - net-gro: reset skb->truesize in napi_reuse_skb() ++ - [x86] thinkpad-acpi: fix issuing duplicated key events for brightness ++ up/down ++ - KVM: async_pf: mm->mm_users can not pin apf->mm ++ - hrtimer: Prevent remote enqueue of leftmost timers ++ - timer: Prevent overflow in apply_slack ++ - media-device: fix infoleak in ioctl media_enum_entities() ++ - usb: storage: shuttle_usbat: fix discs being detected twice ++ - USB: Nokia 305 should be treated as unusual dev ++ - USB: Nokia 5300 should be treated as unusual dev ++ - NFSd: Move default initialisers from create_client() to alloc_client() ++ - NFSd: call rpc_destroy_wait_queue() from free_client() ++ - posix_acl: handle NULL ACL in posix_acl_equiv_mode ++ - mm/page-writeback: Negative (setpoint-dirty) in bdi_position_ratio() ++ (see #695182) ++ - mm/page-writeback.c: fix divide by zero in pos_ratio_polynom ++ - NFSD: Call ->set_acl with a NULL ACL structure if no entries ++ - hrtimer: Set expiry time before switch_hrtimer_base() ++ - V4L2: ov7670: fix a wrong index, potentially Oopsing the kernel from ++ user-space ++ - [x86] mm, hugetlb: Add missing TLB page invalidation for hugetlb_cow() ++ - i2c: s3c2410: resume race fix ++ - [amd64] modify_ldt: Make support for 16-bit segments a runtime option ++ - libceph: fix corruption when using page_count 0 page in rbd ++ - perf: Limit perf_event_attr::sample_period to 63 bits ++ - perf: Prevent false warning in perf_swevent_add ++ - nfsd4: remove lockowner when removing lock stateid ++ - nfsd4: warn on finding lockowner without stateid's ++ - [armel] dma: mv_xor: Flush descriptors before activating a channel ++ - hwpoison, hugetlb: lock_page/unlock_page does not match for handling a ++ free hugepage ++ ++ [ Ben Hutchings ] ++ * drm, agp: Update to 3.4.92: ++ - i915: Skip intel_crt_init for Dell XPS 8700 ++ - drm/vmwgfx: correct fb_fix_screeninfo.line_length ++ - drm/radeon: call drm_edid_to_eld when we update the edid ++ - drm/radeon: fix ATPX detection on non-VGA GPUs ++ - drm/nouveau/acpi: allow non-optimus setups to load vbios from acpi ++ - drm/i915/sdvo: clean up connectors on intel_sdvo_init() failures ++ - drm: fix documentation for drm_crtc_set_mode() ++ - drm/radeon: fix typo in evergreen_mc_resume() ++ - drm/i915: add missing \n to UTS_RELEASE in the error_state ++ - DRM/i915: Add QUIRK_INVERT_BRIGHTNESS for NCR machines. ++ - drm/radeon: use frac fb div on RS780/RS880 ++ - drm/radeon: cleanup properly if mmio mapping fails ++ - drm/i915: Workaround incoherence between fences and LLC across multiple ++ CPUs ++ - drm/i915: ensure single initialization and cleanup of backlight device ++ - drm/radeon: Another card with wrong primary dac adj ++ - drm/i915: try not to lose backlight CBLV precision ++ - drm/radeon: fix panel scaling with eDP and LVDS bridges ++ - drm/ttm: Fix memory type compatibility check ++ - drm/radeon: fix hdmi mode enable on RS600/RS690/RS740 ++ - drm/radeon: always program the MC on startup ++ * [rt] Update to 3.2.60-rt87: ++ - net: gianfar: do not disable interrupt ++ - rcu: make RCU_BOOST default on RT ++ * [mips] seccomp: Check system calls whenever seccomp is enabled, ++ even if audit and trace are disabled (Closes: #751417) (CVE-2014-4157) ++ * netfilter: ipv4: defrag: set local_df flag on defragmented skb ++ (fixes regression in 3.2.57 and another in 3.2.60) ++ * PCI/sysfs: add per pci device msi[x] irq listing (Closes: #748595) ++ - PCI/MSI: Export MSI mode using attributes, not kobjects ++ - Fix various memory leaks in this feature ++ * [rt] Fix latency histogram after "hrtimer: Set expiry time before ++ switch_hrtimer_base()" in 3.2.60 ++ * auditsc: audit_krule mask accesses need bounds checking (CVE-2014-3917) ++ * mm: add !pte_present() check on existing hugetlb_entry callbacks ++ (CVE-2014-3940) ++ * [x86] x86_32, entry: Do syscall exit work on badsys (CVE-2014-4508) ++ * ALSA: control: Protect user controls against concurrent access ++ (CVE-2014-4652) ++ * ALSA: control: Don't access controls outside of protected regions ++ (CVE-2014-4653) ++ * ALSA: control: Fix replacing user controls (CVE-2014-4654, CVE-2014-4655) ++ * ALSA: control: Make sure that id->index does not overflow; ++ Handle numid overflow (CVE-2014-4656) ++ * target: Explicitly clear ramdisk_mcp backend pages (CVE-2014-4027) ++ ++ -- Ben Hutchings Sun, 29 Jun 2014 02:09:50 +0100 ++ ++linux (3.2.57-3+deb7u2) wheezy-security; urgency=high ++ ++ * futex: Add another early deadlock detection check ++ * futex: Prevent attaching to kernel threads ++ * futex: Forbid uaddr == uaddr2 in futex_requeue(..., requeue_pi=1) ++ (CVE-2014-3153) ++ * futex: Validate atomic acquisition in futex_lock_pi_atomic() ++ * futex: Always cleanup owner tid in unlock_pi ++ * futex: Make lookup_pi_state more robust ++ * filter: prevent nla extensions to peek beyond the end of the message ++ (CVE-2014-3145) ++ ++ -- Ben Hutchings Wed, 04 Jun 2014 22:29:31 +0100 ++ ++linux (3.2.57-3+deb7u1) wheezy-security; urgency=high ++ ++ * n_tty: Fix n_tty_write crash when echoing in raw mode (CVE-2014-0196) ++ * floppy: ignore kernel-only members in FDRAWCMD ioctl input (CVE-2014-1737) ++ * floppy: don't write kernel-only members to FDRAWCMD ioctl output ++ (CVE-2014-1738) ++ * mm: try_to_unmap_cluster() should lock_page() before mlocking ++ (CVE-2014-3122) ++ * net: ipv4: current group_info should be put after using. (CVE-2014-2851) ++ * Revert "isci: fix reset timeout handling" (Closes: #746642) ++ * skbuff: export skb_copy_ubufs (Closes: #746602) ++ * Revert "perf/x86/amd/ibs: Fix waking up from S3 for AMD family 10h" ++ (Closes: #746411) ++ ++ -- Ben Hutchings Sat, 10 May 2014 21:20:57 +0100 ++ ++linux (3.2.57-3) wheezy; urgency=medium ++ ++ * rtl8192ce: Fix null dereference in watchdog (Closes: #745137) ++ ++ -- Ben Hutchings Tue, 22 Apr 2014 20:48:59 +0100 ++ ++linux (3.2.57-2) wheezy; urgency=medium ++ ++ * Revert "ALSA: Enable CONFIG_ZONE_DMA for smaller PCI DMA masks" ++ (fixes FTBFS on several architectures where it changed ABI) ++ * e1000e,igb: Backport changes up to Linux 3.13 (Closes: #705959) ++ - e1000e: add RX hash support ++ - e1000e: add support for i217 and i218 ++ - e1000e: 82571 Tx Data Corruption during Tx hang recovery ++ - igb: add basic runtime PM support ++ - igb: Add Support for new i210/i211 devices. ++ - igb: Add 1588 support to I210/I211. ++ - igb: Enable hwmon data output for thermal sensors via I2C. [!sparc] ++ - igb: Add support for SW timestamping ++ - igb: Don't give VFs random MAC addresses ++ - igb: Support for 100base-fx SFP ++ - igb: Enable EEE LP advertisement ++ - igb: Add support for i354 devices ++ - igb: Support for SFP modules discovery ++ - igb: Expose RSS indirection table for ethtool ++ * [x86] crypto: ghash-clmulni-intel - use C implementation for setkey() ++ * [x86] powernow-k6: disable cache when changing frequency ++ ++ -- Ben Hutchings Wed, 16 Apr 2014 23:29:10 +0100 ++ ++linux (3.2.57-1) wheezy; urgency=medium ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.55 ++ - net: do not pretend FRAGLIST support ++ - ipv6: don't count addrconf generated routes against gc limit ++ - net: drop_monitor: fix the value of maxattr ++ - net: unix: allow bind to fail on mutex lock ++ - net: inet_diag: zero out uninitialized idiag_{src,dst} fields ++ - drivers/net/hamradio: Integer overflow in hdlcdrv_ioctl() ++ - rds: prevent dereference of a NULL device (CVE-2013-7339) ++ - net: rose: restore old recvmsg behavior (regression in 3.2.54) ++ - vlan: Fix header ops passthru when doing TX VLAN offload. ++ - net: llc: fix use after free in llc_ui_recvmsg ++ - net: avoid reference counter overflows on fib_rules in multicast ++ forwarding ++ - xfs: Account log unmount transaction correctly (Closes: #737036) ++ - staging: comedi: cb_pcidio: fix for newer PCI-DIO48H ++ - hpfs: fix warnings when the filesystem fills up ++ - ext4: call ext4_error_inode() if jbd2_journal_dirty_metadata() fails ++ - ext4: fix use-after-free in ext4_mb_new_blocks ++ - ext4: check for overlapping extents in ext4_valid_extent_entries() ++ - ext2: Fix oops in ext2_get_block() called from ext2_quota_write() ++ - ext4: fix del_timer() misuse for ->s_err_report ++ - xhci: Limit the spurious wakeup fix only to HP machines ++ (regression in 3.2.53) ++ - radiotap: fix bitmap-end-finding buffer overrun ++ - sched/rt: Fix rq's cpupri leak while enqueue/dequeue child RT entities ++ - rtlwifi: pci: Fix oops on driver unload ++ - net_dma: mark broken ++ - ext4: add explicit casts when masking cluster sizes ++ - selinux: fix broken peer recv check ++ - selinux: selinux_setprocattr()->ptrace_parent() needs rcu_read_lock() ++ - [powerpc] Fix bad stack check in exception entry ++ - md/raid5: Fix possible confusion when multiple write errors occur. ++ - md/raid10: fix two bugs in handling of known-bad-blocks. ++ - md/raid10: fix bug when raid10 recovery fails to recover a block. ++ - nilfs2: fix segctor bug that causes file system corruption ++ - perf/x86/amd/ibs: Fix waking up from S3 for AMD family 10h ++ - mm: fix aio performance regression for database caused by THP ++ - mm: hugetlbfs: fix hugetlbfs optimization ++ - sched/rt: Fix SCHED_RR across cgroups ++ - sched,rt: fix isolated CPUs leaving root_task_group indefinitely ++ throttled ++ - sched: Unthrottle rt runqueues in __disable_runtime() ++ - sched/rt: Avoid updating RT entry timeout twice within one tick period ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.56 ++ - selinux: process labeled IPsec TCP SYN-ACK packets properly in ++ selinux_ip_postroute() ++ - USB: pl2303: fix data corruption on termios updates ++ - USB: Nokia 502 is an unusual device ++ - sunrpc: Fix infinite loop in RPC state machine ++ - USB: ftdi_sio: added CS5 quirk for broken smartcard readers ++ (regression in 3.2.54) ++ - dm: wait until embedded kobject is released before destroying a device ++ - ftrace: Use schedule_on_each_cpu() as a heavy synchronize_sched() ++ - ftrace: Fix synchronization location disabling and freeing ftrace_ops ++ - dm sysfs: fix a module unload race ++ - [x86] KVM: limit PIT timer frequency ++ - md/raid5: fix long-standing problem with bitmap handling on write failure. ++ - libata: disable LPM for some WD SATA-I devices ++ - intel-iommu: fix off-by-one in pagetable freeing (Closes: #743263) ++ - fuse: fix pipe_buf_operations ++ - [powerpc] KVM: e500: Fix bad address type in deliver_tlb_misss() ++ - btrfs: restrict snapshotting to own subvolumes ++ - Btrfs: setup inode location during btrfs_init_inode_locked ++ - KVM: return an error code in kvm_vm_ioctl_register_coalesced_mmio() ++ - [s390] crypto: Don't panic after crypto instruction failures ++ - [s390] crypto: fix concurrency issue in aes-ctr mode ++ - [s390] crypto: fix des and des3_ede cbc concurrency issue ++ - [s390] crypto: fix des and des3_ede ctr concurrency issue ++ - mm, oom: base root bonus on current usage ++ - sata_sil: apply MOD15WRITE quirk to TOSHIBA MK2561GSYN ++ - SELinux: Fix kernel BUG on empty security contexts. (CVE-2014-1874) ++ - mac80211: fix fragmentation code, particularly for encryption ++ - mm/swap: fix race on swap_info reuse between swapoff and swapon ++ - mm: __set_page_dirty_nobuffers() uses spin_lock_irqsave() instead of ++ spin_lock_irq() ++ - mm: __set_page_dirty uses spin_lock_irqsave instead of spin_lock_irq ++ - raw: test against runtime value of max_raw_minors ++ - staging: comedi: adv_pci1710: fix analog output readback value ++ - [armhf] 7953/1: mm: ensure TLB invalidation is complete before ++ enabling MMU ++ - [arm] 7955/1: spinlock: ensure we have a compiler barrier before sev ++ - fs/file.c:fdtable: avoid triggering OOMs from alloc_fdmem ++ - SUNRPC: Fix races in xs_nospace() ++ - block: add cond_resched() to potentially long running ioctl discard loop ++ - lockd: send correct lock when granting a delayed lock. ++ - [mips] Fix potential corruption of DMA buffers ++ - [mips] rtl8187: fix regression on MIPS without coherent DMA ++ - EDAC: Correct workqueue setup path ++ - PCI: Enable INTx if BIOS left them disabled ++ - PCI: Enable INTx in pci_reenable_device() only when MSI/MSI-X not enabled ++ - ext4: don't leave i_crtime.tv_sec uninitialized ++ - [arm] 7957/1: add DSB after icache flush in __flush_icache_all() ++ - workqueue: ensure @task is valid across kthread_stop() ++ - cgroup: update cgroup_enable_task_cg_lists() to grab siglock ++ - mac80211: fix AP powersave TX vs. wakeup race (CVE-2014-2706) ++ - SELinux: bigendian problems with filename trans rules ++ - ath9k: protect tid->sched check (CVE-2014-2672) ++ - ath9k: Fix ETSI compliance for AR9462 2.0 ++ - quota: Fix race between dqput() and dquot_scan_active() ++ - [x86] i7core_edac: Fix PCI device reference count ++ - [x86] i7300_edac: Fix device reference count ++ - [x86] ioat: fix tasklet tear down (regression in 3.2.55) ++ - genirq: Remove racy waitqueue_active check ++ - sched: Fix double normalization of vruntime ++ - [x86] perf: Fix event scheduling ++ - perf: Fix hotplug splat ++ - cpuset: fix a race condition in __cpuset_node_allowed_softwall() ++ - can: flexcan: flexcan_remove(): add missing netif_napi_del() ++ - ocfs2: fix quota file corruption ++ - mac80211: clear sequence/fragment number in QoS-null frames ++ - net: unix socket code abuses csum_partial ++ - ocfs2 syncs the wrong range... ++ - [x86] vmxnet3: fix netpoll race condition ++ - staging: comedi: ssv_dnp: correct insn_bits result ++ - mm/hugetlb: check for pte NULL pointer in __page_check_address() ++ - hpfs: deadlock and race in directory lseek() ++ - timekeeping: fix 32-bit overflow in get_monotonic_boottime ++ - net: fix 'ip rule' iif/oif device rename ++ - saa7134: Fix unlocked snd_pcm_stop() call ++ - net: sctp: fix sctp_sf_do_5_1D_ce to verify if we/peer is AUTH capable ++ (CVE-2014-0101) ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.57 ++ - ext4: atomically set inode->i_flags in ext4_set_inode_flags() ++ - netfilter: nf_conntrack_dccp: fix skb_header_pointer API usages ++ (CVE-2014-2523) ++ - net: add and use skb_gso_transport_seglen() ++ - net: ip, ipv6: handle gso skbs in forwarding path ++ - deb-pkg: Fix cross-building linux-headers package (Closes: #649748) ++ - KVM: MMU: handle invalid root_hpa at __direct_map ++ - KVM: VMX: fix use after free of vmx->loaded_vmcs ++ - cifs: ensure that uncached writes handle unmapped areas correctly ++ (CVE-2014-0069) ++ - [s390] fix kernel crash due to linkage stack instructions (CVE-2014-2039) ++ ++ [ Ben Hutchings ] ++ * [rt] Update to 3.2.55-rt81: ++ - cpu_down: move migrate_enable() back ++ - lockdep: Correctly annotate hardirq context in irq_exit() ++ - rtmutex: use a trylock for waiter lock in trylock ++ - smp: introduce a generic on_each_cpu_mask() function ++ - smp: add func to IPI cpus based on parameter func ++ - fs: only send IPI to invalidate LRU BH when needed ++ - rcutree/rcu_bh_qs: disable irq while calling rcu_preempt_qs() ++ - Revert "x86: Disable IST stacks for debug/int 3/stack fault for ++ PREEMPT_RT" ++ - rt: Make cpu_chill() use hrtimer instead of msleep( ++ - kernel/hrtimer: be non-freezeable in cpu_chill() ++ - arm/unwind: use a raw_spin_lock ++ - net: sched: dev_deactivate_many(): use msleep(1) instead of yield() to ++ wait for outstanding qdisc_run calls ++ - fs: jbd2: pull your plug when waiting for space ++ - cpu_chill: Add a UNINTERRUPTIBLE hrtimer_nanosleep ++ * drm, agp: Update to 3.4.86: ++ - drm/radeon: warn users when hw_i2c is enabled (v2) ++ - radeon/pm: Guard access to rdev->pm.power_state array ++ - drm/radeon: skip colorbuffer checking if COLOR_INFO.FORMAT is set to ++ INVALID ++ - drm/radeon: set the full cache bit for fences on r7xx+ ++ - drm/radeon/DCE4+: clear bios scratch dpms bit (v2) ++ - drm/i915: kick any firmware framebuffers before claiming the gtt ++ - drm/ttm: don't oops if no invalidate_caches() ++ - drm/radeon/atom: select the proper number of lanes in transmitter setup ++ * ipc/msg: fix race around refcount (CVE-2013-4483) ++ * ALSA: usb-audio: add front jack channel selector for EMU0204 ++ (thanks to Mark Hymers) (Closes: #742139) ++ * vhost: validate vhost_get_vq_desc return value (CVE-2014-0055) ++ * vhost: fix total length when packets are too short (CVE-2014-0077) ++ * rds: prevent dereference of a NULL device in rds_iw_laddr_check ++ (CVE-2014-2678) ++ * skbuff: skb_segment: orphan frags before copying (CVE-2014-0131) ++ * ipv6: don't set DST_NOCOUNT for remotely added routes (CVE-2014-2309) ++ * vlan: Set correct source MAC address with TX VLAN offload enabled ++ (regression in 3.2.55) ++ ++ -- Ben Hutchings Mon, 14 Apr 2014 01:38:31 +0100 ++ ++linux (3.2.54-2) wheezy; urgency=high ++ ++ * [arm] Ignore ABI change in omap_dsp_get_mempool_base (fixes FTBFS) ++ ++ -- dann frazier Sat, 01 Feb 2014 13:08:46 +0000 ++ ++linux (3.2.54-1) wheezy; urgency=high ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.54 ++ - NFSv4: Fix a use-after-free situation in _nfs4_proc_getlk() ++ - USB: mos7840: fix tiocmget error handling ++ - ALSA: 6fire: Fix probe of multiple cards ++ - can: c_can: Fix RX message handling, handle lost message before EOB ++ - dm mpath: fix race condition between multipath_dtr and pg_init_done ++ - ext4: avoid bh leak in retry path of ext4_expand_extra_isize_ea() ++ - KVM: IOMMU: hva align mapping page size ++ - crypto: s390 - Fix aes-cbc IV corruption ++ - audit: printk USER_AVC messages when audit isn't enabled ++ - audit: fix info leak in AUDIT_GET requests ++ - audit: use nlmsg_len() to get message payload length ++ - PM / hibernate: Avoid overflow in hibernate_preallocate_memory() ++ - blk-core: Fix memory corruption if blkcg_init_queue fails ++ - block: fix a probe argument to blk_register_region ++ - SUNRPC: Fix a data corruption issue when retransmitting RPC calls ++ - mwifiex: correct packet length for packets from SDIO interface ++ - vsprintf: check real user/group id for %pK ++ - ipc, msg: fix message length check for negative values ++ - hwmon: (lm90) Fix max6696 alarm handling ++ - rtlwifi: rtl8192cu: Fix more pointer arithmetic errors ++ - setfacl removes part of ACL when setting POSIX ACLs to Samba ++ - nfsd: make sure to balance get/put_write_access ++ - nfsd4: fix xdr decoding of large non-write compounds (regression ++ in 3.2.49) ++ - NFSv4 wait on recovery for async session errors ++ - powerpc/signals: Mark VSX not saved with small contexts ++ - iscsi-target: fix extract_param to handle buffer length corner case ++ - iscsi-target: chap auth shouldn't match username with trailing garbage ++ - configfs: fix race between dentry put and lookup ++ - [powerpc] signals: Improved mark VSX not saved with small contexts fix ++ - mac80211: don't attempt to reorder multicast frames ++ - Staging: zram: Fix access of NULL pointer ++ - Staging: zram: Fix memory leak by refcount mismatch ++ - irq: Enable all irqs unconditionally in irq_resume ++ - tracing: Allow events to have NULL strings ++ - [armhf/omap] Staging: tidspbridge: disable driver ++ - cpuset: Fix memory allocator deadlock ++ - crypto: authenc - Find proper IV address in ablkcipher callback ++ - crypto: scatterwalk - Set the chain pointer indication bit ++ - [s390] crypto: s390 - Fix aes-xts parameter corruption ++ - crypto: ccm - Fix handling of zero plaintext when computing mac ++ - net: update consumers of MSG_MORE to recognize MSG_SENDPAGE_NOTLAST ++ (fixes regression in 3.2.17) ++ - hpsa: do not discard scsi status on aborted commands ++ - hpsa: return 0 from driver probe function on success, not 1 ++ - [arm] 7912/1: check stack pointer in get_wchan ++ - [arm] 7913/1: fix framepointer check in unwind_frame ++ - ALSA: memalloc.h - fix wrong truncation of dma_addr_t ++ - dm snapshot: avoid snapshot space leak on crash ++ - dm table: fail dm_table_create on dm_round_up overflow ++ - hwmon: (w83l786ng) Fix fan speed control mode setting and reporting ++ - hwmon: (w83l768ng) Fix fan speed control range ++ - futex: fix handling of read-only-mapped hugepages ++ - KVM: Improve create VCPU parameter (CVE-2013-4587) ++ - [x86] KVM: Fix potential divide by 0 in lapic (CVE-2013-6367) ++ - net: Fix "ip rule delete table 256" (Closes: #724783) ++ - 6lowpan: Uncompression of traffic class field was incorrect ++ - ipv4: fix possible seqlock deadlock ++ - inet: prevent leakage of uninitialized memory to user in recv syscalls ++ - net: rework recvmsg handler msg_name and msg_namelen logic ++ - net: add BUG_ON if kernel advertises msg_namelen > ++ sizeof(struct sockaddr_storage) ++ - inet: fix addr_len/msg->msg_namelen assignment in recv_error and rxpmtu ++ functions ++ - ipv6: fix leaking uninitialized port number of offender sockaddr ++ - net: core: Always propagate flag changes to interfaces ++ - packet: fix use after free race in send path when dev is released ++ - inet: fix possible seqlock deadlocks ++ - ipv6: fix possible seqlock deadlock in ip6_finish_output2 ++ - ftrace: Check module functions being traced on reload ++ - ftrace: Fix function graph with loading of modules ++ - mmc: block: fix a bug of error handling in MMC driver ++ ++ [ Ben Hutchings ] ++ * SCSI: virtio_scsi: fix memory leak on full queue condition ++ (Closes: #730138) ++ * drm, agp: Update to 3.4.76: ++ - drm/radeon: fix asic gfx values for scrapper asics ++ - drm/edid: add quirk for BPC in Samsung NP700G7A-S01PL notebook ++ - drm/radeon: fixup bad vram size on SI ++ ++ [ dann frazier ] ++ * ath9k_htc: properly set MAC address and BSSID mask (CVE-2013-4579) ++ * KVM: x86: Convert vapic synchronization to _cached functions (CVE-2013-6368) ++ * x86, fpu, amd: Clear exceptions in AMD FXSAVE workaround (CVE-2014-1438) ++ * hamradio/yam: fix info leak in ioctl (CVE-2014-1446) ++ ++ -- dann frazier Wed, 29 Jan 2014 13:42:01 -0700 ++ ++linux (3.2.53-2) wheezy; urgency=high ++ ++ * [sparc] Ignore insignificant ABI changes (fixes FTBFS) ++ * [powerpc] Update CPU device backport to work after 'powerpc/sysfs: ++ Disable writing to PURR in guest mode' in 3.2.52 (fixes FTBFS) ++ * exec/ptrace: Fix typo in backport of 'fix get_dumpable() incorrect tests' ++ (CVE-2013-2929) (Closes: #732208) ++ * net: Fix infinite loop in in skb_flow_dissect() (CVE-2013-4348) ++ ++ -- Ben Hutchings Tue, 17 Dec 2013 03:24:07 +0000 ++ ++linux (3.2.53-1) wheezy; urgency=medium ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.52 ++ - 8139cp: Add dma_mapping_error checking ++ - ipv6: drop packets with multiple fragmentation headers ++ - ipv6: Don't depend on per socket memory for neighbour discovery messages ++ - HID: hidraw: correctly deallocate memory on device disconnect ++ - xen-gnt: prevent adding duplicate gnt callbacks ++ - usb: config->desc.bLength may not exceed amount of data returned by the ++ device ++ - USB: cdc-wdm: fix race between interrupt handler and tasklet ++ - [powerpc] Handle unaligned ldbrx/stdbrx ++ - intel-iommu: Fix leaks in pagetable freeing ++ - ath9k: fix rx descriptor related race condition ++ - ath9k: avoid accessing MRC registers on single-chain devices ++ - rculist: list_first_or_null_rcu() should use list_entry_rcu() ++ - USB: mos7720: fix big-endian control requests ++ - of: Fix missing memory initialization on FDT unflattening ++ - fuse: postpone end_page_writeback() in fuse_writepage_locked() ++ - fuse: invalidate inode attributes on xattr modification ++ - fuse: hotfix truncate_pagecache() issue ++ - hdpvr: register the video node at the end of probe ++ - hdpvr: fix iteration over uninitialized lists in hdpvr_probe() ++ - fuse: readdir: check for slash in names ++ - crypto: api - Fix race condition in larval lookup ++ - sd: Fix potential out-of-bounds access ++ - ocfs2: fix the end cluster offset of FIEMAP ++ - mm/huge_memory.c: fix potential NULL pointer dereference ++ - sched/fair: Fix small race where child->se.parent,cfs_rq might point to ++ invalid ones ++ - HID: zeroplus: validate output report details (CVE-2013-2889) ++ - HID: LG: validate HID output report details (CVE-2013-2893) ++ - HID: validate feature and input report details (CVE-2013-2897) ++ - HID: logitech-dj: validate output report details (CVE-2013-2895) ++ - nilfs2: fix issue with race condition of competition between segments ++ for dirty blocks ++ - powerpc: Fix parameter clobber in csum_partial_copy_generic() ++ - powerpc: Restore registers on error exit from csum_partial_copy_generic() ++ - net: sctp: fix smatch warning in sctp_send_asconf_del_ip ++ - net: sctp: fix ipv6 ipsec encryption bug in sctp_v6_xmit (CVE-2013-4350) ++ - ip: generate unique IP identificator if local fragmentation is allowed ++ - ipv6: udp packets following an UFO enqueued packet need also be handled ++ by UFO (CVE-2013-4387) ++ - esp_scsi: Fix tag state corruption when autosensing. ++ - [sparc] Fix not SRA'ed %o5 in 32-bit traced syscall ++ - perf: Use css_tryget() to avoid propping up css refcount ++ - Revert "zram: use zram->lock to protect zram_free_page() in swap free ++ notify path" (regression in 3.2.49) ++ - macvtap: do not zerocopy if iov needs more pages than MAX_SKB_FRAGS ++ - sfc: Fix efx_rx_buf_offset() for recycled pages ++ - cgroup: fail if monitored file and event_control are in different cgroup ++ - perf: Fix perf_cgroup_switch for sw-events ++ - Revert "sctp: fix call to SCTP_CMD_PROCESS_SACK in ++ sctp_cmd_interpreter()" (regression in 3.2.34) ++ - iscsi: don't hang in endless loop if no targets present ++ - cpqarray: fix info leak in ida_locked_ioctl() (CVE-2013-2147) ++ - cciss: fix info leak in cciss_ioctl32_passthru() (CVE-2013-2147) ++ - staging: comedi: ni_65xx: (bug fix) confine insn_bits to one subdevice ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.53 ++ - tcp: must unclone packets before mangling them ++ - tcp: do not forget FIN in tcp_shifted_skb() (fixes regression in 2.6.39) ++ - net: do not call sock_put() on TIMEWAIT sockets ++ - net: heap overflow in __audit_sockaddr() ++ - proc connector: fix info leaks ++ - ipv6: restrict neighbor entry creation to output flow ++ (fixes regression in 3.2.39) ++ - farsync: fix info leak in ioctl ++ - connector: use nlmsg_len() to check message length ++ - wanxl: fix info leak in ioctl ++ - net: unix: inherit SOCK_PASS{CRED, SEC} flags from socket to fix race ++ (fixes regression in 3.2) ++ - net: fix cipso packet validation when !NETLABEL ++ - zram: allow request end to coincide with disksize ++ - perf: Fix perf ring buffer memory ordering ++ - inet: fix possible memory corruption with UDP_CORK and UFO ++ (CVE-2013-4470) ++ - tracing: Fix potential out-of-bounds in trace_get_user() ++ - include/linux/fs.h: disable preempt when acquire i_size_seqcount write ++ lock ++ - jfs: fix error path in ialloc ++ - random: run random_int_secret_init() run after all late_initcalls ++ - mac80211: drop spoofed packets in ad-hoc mode ++ - libata: make ata_eh_qc_retry() bump scmd->allowed on bogus failures ++ - [powerpc] KVM: PPC: Book3S HV: Fix typo in saving DSCR ++ - compiler/gcc4: Add quirk for 'asm goto' miscompilation bug ++ - ext4: fix memory leak in xattr ++ - [hppa] fix interruption handler to respect pagefault_disable() ++ - dm snapshot: fix data corruption (CVE-2013-4299) ++ - ecryptfs: Fix memory leakage in keystore.c ++ - target/pscsi: fix return value check ++ - Fix a few incorrectly checked [io_]remap_pfn_range() calls ++ (CVE-2013-4511) ++ - uml: check length in exitcode_proc_write() (CVE-2013-4512) ++ - aacraid: missing capable() check in compat ioctl ++ - staging: wlags49_h2: buffer overflow setting station name ++ - Staging: bcm: info leak in ioctl ++ - lib/scatterlist.c: don't flush_kernel_dcache_page on slab page ++ ++ * [armel/orion5x] i2c: mv64xxx: work around signals causing I2C transactions ++ to be aborted ++ * [armel/orion5x] I2C: mv64xxx: fix race between FSM/interrupt and process ++ context (Closes: #622325) ++ * aufs: Set version to 3.2.x-debian ++ * drm: fix DRM_IOCTL_MODE_GETFB handle-leak ++ * drm, agp: Update to 3.4.72: ++ - drm/edid: add quirk for Medion MD30217PG ++ - drm/ttm: fix the tt_populated check in ttm_tt_destroy() ++ - drm/radeon: fix LCD record parsing ++ - drm/radeon: fix endian bugs in hw i2c atom routines ++ - drm/radeon: update line buffer allocation for dce4.1/5 ++ - drm/radeon: update line buffer allocation for dce6 ++ - drm/radeon: fix resume on some rs4xx boards (v2) ++ - drm/radeon: fix handling of variable sized arrays for router objects ++ - drm/radeon/atom: workaround vbios bug in transmitter table on rs880 (v2) ++ - drm/i915/dp: increase i2c-over-aux retry interval on AUX DEFER ++ - drm/radeon: disable tests/benchmarks if accel is disabled ++ - drm/radeon: fix hw contexts for SUMO2 asics ++ - drm: Prevent overwriting from userspace underallocating core ioctl structs ++ - drm/radeon/atom: workaround vbios bug in transmitter table on rs780 ++ - drm/ttm: Handle in-memory region copies ++ - drm/i915: flush cursors harder ++ - drm/nouveau: when bailing out of a pushbuf ioctl, do not remove previous ++ fence ++ - drm/radeon/si: fix define for MC_SEQ_TRAIN_WAKEUP_CNTL ++ - radeon: workaround pinning failure on low ram gpu ++ * [rt] Update to 3.2.53-rt75: ++ - genirq: Set the irq thread policy without checking CAP_SYS_NICE ++ - hwlat-detector: Don't ignore threshold module ++ - mm/memcontrol: Don't call schedule_work_on in preemption disabled context ++ - drm: remove preempt_disable() from ++ drm_calc_vbltimestamp_from_scanoutpos() ++ * net: clamp ->msg_namelen instead of returning an error (fixes ++ regression in 3.2.53) ++ * rds: prevent BUG_ON triggered on congestion update to loopback ++ (CVE-2012-2372) ++ * HID: multitouch: validate indexes details (CVE-2013-2897) ++ * exec/ptrace: fix get_dumpable() incorrect tests (CVE-2013-2929) ++ * crypto: ansi_cprng - Fix off by one error in non-block size request ++ (CVE-2013-4345) ++ * KVM: perform an invalid memslot step for gpa base change ++ * KVM: Fix iommu map/unmap to handle memory slot moves (CVE-2013-4592) ++ * [armhf] 7527/1: uaccess: explicitly check __user pointer when ++ !CPU_USE_DOMAINS (CVE-2013-6282) ++ * libertas: potential oops in debugfs (CVE-2013-6378) ++ * aacraid: prevent invalid pointer dereference (CVE-2013-6380) ++ * [s390,s390x] qeth: avoid buffer overflow in snmp ioctl (CVE-2013-6381) ++ * xfs: underflow bug in xfs_attrlist_by_handle() (CVE-2013-6382) ++ ++ -- Ben Hutchings Fri, 06 Dec 2013 07:23:56 +0000 ++ ++linux (3.2.51-1) wheezy; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.47 ++ - xfs: kill suid/sgid through the truncate path. ++ - ALSA: usb-audio: fix possible hang and overflow in ++ parse_uac2_sample_rate_range() ++ - ALSA: usb-audio: avoid integer overflow in create_fixed_stream_quirk() ++ - xen-netfront: reduce gso_max_size to account for max TCP header ++ - jfs: fix a couple races ++ - USB: revert periodic scheduling bugfix (fixes regression in 3.2.39) ++ - USB: keyspan: fix bogus array index ++ - Bluetooth: Fix missing length checks for L2CAP signalling PDUs ++ - swap: avoid read_swap_cache_async() race to deadlock while waiting on ++ discard I/O completion ++ - mm: migration: add migrate_entry_wait_huge() ++ - USB: spcp8x5: fix device initialisation at open ++ - USB: pl2303: fix device initialisation at open ++ - md/raid1: consider WRITE as successful only if at least one non-Faulty ++ and non-rebuilding drive completed it. ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.48 ++ - ARM: 7755/1: handle user space mapped pages in flush_kernel_dcache_page ++ - ARM: 7772/1: Fix missing flush_kernel_dcache_page() for noMMU ++ - [x86] Modify UEFI anti-bricking code ++ - tcp: fix tcp_md5_hash_skb_data() ++ - ipv6: fix possible crashes in ip6_cork_release() ++ - r8169: fix 8168evl frame padding. ++ - ip_tunnel: fix kernel panic with icmp_dest_unreach ++ - net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg ++ - net: force a reload of first item in hlist_nulls_for_each_entry_rcu ++ - net: sctp: fix NULL pointer dereference in socket destruction ++ - l2tp: Fix PPP header erasure and memory leak ++ - ncpfs: fix rmdir returns Device or resource busy (regression in 3.1) ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.49 ++ - zram: avoid invalid memory access in zram_exit() ++ - zram: use zram->lock to protect zram_free_page() in swap free notify path ++ - zram: avoid access beyond the zram device ++ - zram: protect sysfs handler from invalid memory access ++ - Bluetooth: Fix crash in l2cap_build_cmd() with small MTU ++ - xhci: check for failed dma pool allocation ++ - drivers: hv: switch to use mb() instead of smp_mb() ++ - media: dmxdev: remove dvb_ringbuffer_flush() on writer side ++ - hw_breakpoint: Use cpu_possible_mask in {reserve,release}_bp_slot() ++ - iommu/amd: Only unmap large pages from the first pte ++ - futex: Take hugepages into account when generating futex_key ++ - perf: Disable monitoring on setuid processes for regular users ++ - cgroup: fix RCU accesses to task->cgroups ++ - dlci: acquire rtnl_lock before calling __dev_get_by_name() ++ - dlci: validate the net device in dlci_del() ++ - genirq: Fix can_request_irq() for IRQs without an action ++ (Closes: #709647) ++ - writeback: Fix periodic writeback after fs mount ++ - UBIFS: fix a horrid bug - data race between readdir and llseek ++ - powerpc/smp: Section mismatch from smp_release_cpus to __initdata ++ spinning_secondaries ++ - ext3,ext4: don't mess with dir_file->f_pos in htree_dirblock_to_tree() ++ - jbd2: fix theoretical race in jbd2__journal_restart ++ - drivers/dma/pl330.c: fix locking in pl330_free_chan_resources() ++ - ocfs2: xattr: fix inlined xattr reflink ++ - crypto: sanitize argument for format string ++ - hpfs: better test for errors ++ - iscsi-target: Fix tfc_tpg_nacl_auth_cit configfs length overflow ++ - perf: Clone child context from parent context pmu ++ - perf: Remove WARN_ON_ONCE() check in __perf_event_enable() for valid ++ scenario ++ - perf: Fix perf_lock_task_context() vs RCU ++ - perf: Fix perf mmap bugs ++ - perf: Fix mmap() accounting hole ++ - ext4: fix overflow when counting used blocks on 32-bit architectures ++ - ext4: fix data offset overflow in ext4_xattr_fiemap() on 32-bit archs ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.50 ++ - macvtap: fix recovery from gup errors ++ - neighbour: fix a race in neigh_destroy() ++ - net: Swap ver and type in pppoe_hdr ++ - ipv6,mcast: always hold idev->lock before mca_lock ++ - macvtap: correctly linearize skb when zerocopy is used ++ - 9p: fix off by one causing access violations and memory corruption ++ - atl1e: fix dma mapping warnings ++ - atl1e: unmap partially mapped skb on dma error and free skb ++ - vlan: fix a race in egress prio management ++ - [sparc] tsb must be flushed before tlb ++ - virtio_net: fix race in RX VQ processing ++ - bnx2fc: Fix incorrect memset in bnx2fc_parse_fcp_rsp ++ - xen/blkback: Check for insane amounts of request on the ring (v6). ++ - lockd: protect nlm_blocked access in nlmsvc_retry_blocked ++ - ext4: don't allow ext4_free_blocks() to fail due to ENOMEM ++ - ACPI / memhotplug: Fix a stale pointer in error path ++ - ALSA: Fix unlocked snd_pcm_stop() calls in various drivers ++ - Btrfs: fix lock leak when resuming snapshot deletion ++ - Btrfs: re-add root to dead root list if we stop dropping it ++ - ALSA: usb-audio: 6fire: return correct XRUN indication ++ - [x86] isci: Fix a race condition in the SSP task management path ++ - sd: fix crash when UA received on DIF enabled device ++ - nfsd: nfsd_open: when dentry_open returns an error do not propagate as ++ struct file ++ - staging: comedi: fix a race between do_cmd_ioctl() and read/write ++ - usb: host: xhci: Enable XHCI_SPURIOUS_SUCCESS for all controllers with ++ xhci 1.0 ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.51 ++ - sctp: fully initialize sctp_outq in sctp_outq_init ++ - ipv6: take rtnl_lock and mark mrt6 table as freed on namespace cleanup ++ - net_sched: Fix stack info leak in cbq_dump_wrr(). ++ - af_key: more info leaks in pfkey messages ++ - net_sched: info leak in atm_tc_dump_class() ++ - ALSA: ak4xx-adda: info leak in ak4xxx_capture_source_info() ++ - NFSv4.1: integer overflow in decode_cb_sequence_args() ++ - jfs: fix readdir cookie incompatibility with NFSv4 (Closes: #714974) ++ - mac80211: fix duplicate retransmission detection ++ - [arm] 7791/1: a.out: remove partial a.out support ++ - [x86] fpu: correct the asm constraints for fxsave, unbreak mxcsr.daz ++ - USB: mos7840: fix race in register handling ++ - serial/mxs-auart: fix race condition in interrupt handler ++ - serial/mxs-auart: increase time to wait for transmitter to become idle ++ - ixgbe: Fix Tx Hang issue with lldpad on 82598EB ++ - virtio: console: fix race with port unplug and open/close ++ - virtio: console: fix race in port_fops_open() and port unplug ++ - virtio: console: clean up port data immediately at time of unplug ++ - ACPI / battery: Fix parsing _BIX return value (Closes: #721468) ++ - cifs: extend the buffer length enought for sprintf() using ++ - iwlwifi: dvm: fix calling ieee80211_chswitch_done() with NULL ++ - ALSA: 6fire: fix DMA issues with URB transfer_buffer usage ++ - cifs: don't instantiate new dentries in readdir for inodes that need ++ to be revalidated immediately (fixes regression in 3.2.46) ++ - hwmon: (adt7470) Fix incorrect return code check ++ - zd1201: do not use stack as URB transfer_buffer ++ - Hostap: copying wrong data prism2_ioctl_giwaplist() ++ - ALSA: 6fire: make buffers DMA-able (pcm) ++ - ALSA: 6fire: make buffers DMA-able (midi) ++ - jbd2: Fix use after free after error in jbd2_journal_dirty_metadata() ++ - [arm] 7809/1: perf: fix event validation for software group leaders ++ - [arm] perf: Fix armpmu_map_hw_event() ++ - fs/proc/task_mmu.c: fix buffer overflow in add_page_map() ++ - USB: mos7720: fix broken control requests ++ - USB: keyspan: fix null-deref at disconnect and release ++ - block: Add bio_for_each_segment_all() ++ - sg: Fix user memory corruption when SG_IO is interrupted by a signal ++ - of: fdt: fix memory initialization for expanded DT ++ - nilfs2: remove double bio_put() in nilfs_end_bio_write() for ++ BIO_EOPNOTSUPP error ++ - nilfs2: fix issue with counting number of bio requests for ++ BIO_EOPNOTSUPP error detection ++ - ath9k_htc: Restore skb headroom when returning skb to mac80211 ++ - [powerpc] Don't Oops when accessing /proc/powerpc/lparcfg without ++ hypervisor ++ - [powerpc] Work around gcc miscompilation of __pa() on 64-bit ++ - SUNRPC: Fix memory corruption issue on 32-bit highmem systems ++ - drivers/base/memory.c: fix show_mem_removable() to handle missing sections ++ - [x86] get_unmapped_area: Access mmap_legacy_base through mm_struct member ++ - [s390] KVM: move kvm_guest_enter,exit closer to sie ++ ++ [ Ben Hutchings ] ++ * cassini: Make missing firmware non-fatal (Closes: #714128) ++ * drm, agp: Update to 3.4.61: ++ - drm/radeon: fix card_posted check for newer asics ++ - radeon: Fix system hang issue when using KMS with older cards ++ - drm/radeon: don't allow audio on DCE6 ++ - drm: fix a use-after-free when GPU acceleration disabled ++ - drm/i915/sdvo: Use &intel_sdvo->ddc instead of intel_sdvo->i2c for DDC. ++ - drm/i915: no lvds quirk for hp t5740 ++ - drm/gma500: Increase max resolution for mode setting ++ - drm/gma500/psb: Unpin framebuffer on crtc disable ++ - drm/gma500/cdv: Unpin framebuffer on crtc disable ++ - drm/i915: prefer VBT modes for SVDO-LVDS over EDID ++ - drm/radeon: fix endian issues with DP handling (v3) ++ - drm/radeon: fix combios tables on older cards ++ - drm/radeon: improve dac adjust heuristics for legacy pdac ++ - drm/radeon/atom: initialize more atom interpretor elements to 0 ++ - drm/i915: quirk no PCH_PWM_ENABLE for Dell XPS13 backlight ++ - drm/i915/lvds: ditch ->prepare special case ++ - drm/i915: Invalidate TLBs for the rings after a reset ++ - drm/vmwgfx: Split GMR2_REMAP commands if they are to large ++ - drm/i915: ivb: fix edp voltage swing reg val ++ * m25p80: Add support for Micron N25Q128 including 3V variant ++ (Closes: #714092) ++ * [x86] Revert "drm/i915: GFX_MODE Flush TLB Invalidate Mode must be '1' ++ for scanline waits" (possibly fixes: #703715, #704987 and others) ++ * ata: Disable SATA_INIC162X - this driver corrupts data and is not ++ expected to be fixed (Closes: #714295) ++ * Update debconf template translations: ++ - Update Brazilian Portugese (Fernando Ike de Oliveira) (Closes: #719725) ++ - Update Japanese ('victory') (Closes: #719939) ++ * [x86] efivars: Enable the improved check for free space; this should ++ avoid either risk of bricking Samsung systems or refusing to set the ++ boot configuration on Asus systems ++ * mvsas: Recognise device/subsystem 9485/9485 as 88SE9485 ++ * ipv6: remove max_addresses check from ipv6_create_tempaddr (CVE-2013-0343) ++ * Revert "zram: use zram->lock to protect zram_free_page() in swap free ++ notify path" (regression in 3.2.49) ++ * HID: validate HID report id size (CVE-2013-2888) ++ * HID: pantherlord: validate output report details (CVE-2013-2892) ++ * HID: ntrig: validate feature report details (CVE-2013-2896) ++ * HID: picolcd_core: validate output report details (CVE-2013-2899) ++ * HID: check for NULL field when setting values ++ * [rt] Update to 3.2.51-rt72: ++ - sched/workqueue: Only wake up idle workers if not blocked on sleeping ++ spin lock ++ - x86/mce: fix mce timer interval ++ - genirq: Set irq thread to RT priority on creation ++ - list_bl.h: make list head locking RT safe ++ - list_bl.h: fix it for for !SMP && !DEBUG_SPINLOCK ++ - timers: prepare for full preemption improve ++ - kernel/cpu: fix cpu down problem if kthread's cpu is going down ++ - kernel/hotplug: restore original cpu mask oncpu/down ++ - drm/i915: drop trace_i915_gem_ring_dispatch on rt ++ - rt,ntp: Move call to schedule_delayed_work() to helper thread ++ - hwlat-detector: Update hwlat_detector to add outer loop detection ++ - hwlat-detect/trace: Export trace_clock_local for hwlat-detector ++ - hwlat-detector: Use trace_clock_local if available ++ - hwlat-detector: Use thread instead of stop machine ++ - genirq: do not invoke the affinity callback via a workqueue ++ * linux-doc: Include aufs documentation ++ * aufs: Apply bug fixes from 3.2.x branch: ++ - Update Sourceforge URLs in documentation ++ - Fix build with CONFIG_AUFS_DEBUG=y ++ - Make sure the target branch is upper before copy-up ++ - Fix error handling in au_reopen_nondir() ++ - Track pseudo-links with hlist, addressing poor performance and ++ WARNING during package installation ++ - Add necessary memory barriers around i_nlink updates ++ - Fix unbalanced au_unpin() in au_file_refresh_by_inode() ++ - Do not copy-up the S_AUTOMOUNT inode flag ++ * kernel-doc: bugfix - multi-line macros (fixes build failure in 3.2.51) ++ ++ [ Aurelien Jarno ] ++ * [s390] Revert "s390: Use direct ktime path for s390 clockevent device" ++ to fix kernel hard hang after a few hours (Closes: #719993). ++ ++ -- Ben Hutchings Wed, 18 Sep 2013 14:22:20 +0100 ++ ++linux (3.2.46-1+deb7u1) wheezy-security; urgency=low ++ ++ [ Ian Campbell ] ++ * Fix regression in "xen: netback: shutdown the ring if it contains garbage ++ (CVE-2013-0216)" (Closes: #701744) ++ ++ [ dann frazier ] ++ * libceph: Fix NULL pointer dereference in auth client code (CVE-2013-1059) ++ * fanotify: info leak in copy_event_to_user() (CVE-2013-2148) ++ * drivers/cdrom/cdrom.c: use kzalloc() for failing hardware (CVE-2013-2164) ++ * ipv6: ip6_sk_dst_check() must not assume ipv6 dst (CVE-2013-2232) ++ * af_key: fix info leaks in notify messages (CVE-2013-2234) ++ * af_key: initialize satype in key_notify_policy_flush() (CVE-2013-2237) ++ * block: do not pass disk names as format strings (CVE-2013-2851) ++ * b43: stop format string leaking into error msgs (CVE-2013-2852) ++ * ipv6: call udp_push_pending_frames when uncorking a socket (CVE-2013-4162) ++ * ipv6: ip6_append_data_mtu did not care about pmtudisc and frag_size ++ (CVE-2013-4163) ++ ++ -- dann frazier Mon, 12 Aug 2013 22:00:56 -0600 ++ ++linux (3.2.46-1) wheezy; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.42 ++ - TTY: do not reset master's packet mode ++ - l2tp: Restore socket refcount when sendmsg succeeds ++ - tun: add a missing nf_reset() in tun_net_xmit() ++ - netlabel: correctly list all the static label mappings ++ - sctp: Use correct sideffect command in duplicate cookie handling ++ - rtlwifi: rtl8192cu: Fix problem that prevents reassociation ++ (Closes: #661860) ++ - inet: limit length of fragment queue hash table bucket lists ++ - sfc: Properly sync RX DMA buffer when it is not the last in the page ++ - sfc: Fix efx_rx_buf_offset() in the presence of swiotlb ++ - sfc: Only use TX push if a single descriptor is to be written ++ - ext4: fix the wrong number of the allocated blocks in ext4_split_extent() ++ - jbd2: fix use after free in jbd2_journal_dirty_metadata() ++ - ext4: convert number of blocks to clusters properly ++ - ext4: use atomic64_t for the per-flexbg free_clusters count ++ - cifs: delay super block destruction until all cifsFileInfo objects are ++ gone ++ - USB: xhci: correctly enable interrupts (possibly fix for #703470) ++ - [amd64] Fix the failure case in copy_user_handle_tail() ++ - dm thin: fix discard corruption ++ - USB: serial: fix interface refcounting ++ - vfs,proc: guarantee unique inodes in /proc ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.43 ++ - [armhf/mx5] ASoC: imx-ssi: Fix occasional AC97 reset failure ++ - rtlwifi: usb: add missing freeing of skbuff ++ - xen-blkback: fix dispatch_rw_block_io() error path ++ - net/irda: add missing error path release_sock call ++ - sysfs: fix race between readdir and lseek ++ - sysfs: handle failure path correctly for readdir() ++ - NFSv4.1: Fix a race in pNFS layoutcommit ++ - usb: xhci: Fix TRB transfer length macro used for Event TRB. ++ - nfsd4: reject "negative" acl lengths ++ - Nest rename_lock inside vfsmount_lock ++ - [x86] iommu/amd: Make sure dma_ops are set for hotplug devices ++ - b43: A fix for DMA transmission sequence errors ++ - reiserfs: Fix warning and inode leak when deleting inode with xattrs ++ - virtio: console: add locking around c_ovq operations ++ - mm: prevent mmap_cache race in find_vma() ++ - ixgbe: fix registration order of driver and DCA nofitication ++ - key: Fix resource leak ++ - udf: Fix bitmap overflow on large filesystems with small block size ++ - NFS: nfs_getaclargs.acl_len is a size_t ++ - loop: prevent bdev freeing while device in use ++ - sky2: Threshold for Pause Packet is set wrong ++ - 8021q: fix a potential use-after-free ++ - unix: fix a race condition in unix_release() ++ - atl1e: drop pci-msi support because of packet corruption ++ (possibly fixes: #577747) ++ - ipv6: don't accept multicast traffic with scope 0 ++ - ipv6: don't accept node local multicast traffic from the wire ++ - pch_gbe: fix ip_summed checksum reporting on rx ++ - HID: microsoft: do not use compound literal (fixes FTBFS on m68k) ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.44 ++ - USB: serial: fix use-after-free in TIOCMIWAIT ++ - hrtimer: Don't reinitialize a cpu_base lock on CPU_UP ++ - crypto: gcm - fix assumption that assoc has one segment ++ - sched_clock: Prevent 64bit inatomicity on 32bit systems ++ - can: gw: use kmem_cache_free() instead of kfree() ++ - spinlocks and preemption points need to be at least compiler barriers ++ - [x86] mm, paravirt: Fix vmalloc_fault oops during lazy MMU updates ++ - Btrfs: make sure nbytes are right after log replay ++ - kobject: fix kset_find_obj() race with concurrent last kobject_put() ++ - vfs: Revert spurious fix to spinning prevention in prune_icache_sb ++ - ath9k_htc: accept 1.x firmware newer than 1.3 ++ - [armel] Fix kexec by setting outer_cache.inv_all for Feroceon ++ - hugetlbfs: add swap entry check in follow_hugetlb_page() ++ - writeback: fix dirtied pages accounting on redirty ++ - Btrfs: fix race between mmap writes and compression ++ - mtd: Disable mtdchar mmap on MMU systems ++ - fbcon: fix locking harder (Closes: #704933) ++ - hfsplus: fix potential overflow in hfsplus_file_truncate() ++ - sched: Convert BUG_ON()s in try_to_wake_up_local() to WARN_ON_ONCE()s ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.45 ++ - [ia64] Wrong asm register contraints in the futex implementation ++ (Closes: #702641) ++ - [ia64] Wrong asm register contraints in the kvm implementation ++ (Closes: #702639) ++ - [ia64] Fix initialization of CMCI/CMCP interrupts ++ - sysfs: fix use after free in case of concurrent read/write and readdir ++ - nfsd: don't run get_file if nfs4_preprocess_stateid_op return error ++ - ext4/jbd2: don't wait (forever) for stale tid caused by wraparound ++ - jbd2: fix race between jbd2_journal_remove_checkpoint and ++ ->j_commit_callback ++ - hrtimer: Fix ktime_add_ns() overflow on 32bit architectures ++ - nfsd4: don't close read-write opens too soon ++ - wireless: regulatory: fix channel disabling race condition ++ - iwlwifi: dvm: don't send zeroed LQ cmd ++ - powerpc/spufs: Initialise inode->i_ino in spufs_new_inode() ++ (possibly fixes: #707175) ++ - clockevents: Set dummy handler on CPU_DEAD shutdown (Closes: #700333) ++ - powerpc: Add isync to copy_and_flush ++ - fs/fscache/stats.c: fix memory leak ++ - md: bad block list should default to disabled. (fixes regression in 3.1) ++ - inotify: invalid mask should return a error number but not set it ++ (fixes regression in 3.2.40) ++ - fs/dcache.c: add cond_resched() to shrink_dcache_parent() ++ - perf: Fix error return code ++ - [x86] perf: Fix offcore_rsp valid mask for SNB/IVB (CVE-2013-2146) ++ - vm: Introduce and use vm_iomap_memory() helper function ++ - atl1e: limit gso segment size to prevent generation of wrong ip length ++ fields (Closes: #565404) ++ - netfilter: don't reset nf_trace in nf_reset() ++ - rtnetlink: Call nlmsg_parse() with correct header length ++ - tcp: incoming connections might use wrong route under synflood ++ - esp4: fix error return code in esp_output() ++ - net: sctp: sctp_auth_key_put: use kzfree instead of kfree ++ - netrom: fix info leak via msg_name in nr_recvmsg() ++ - netrom: fix invalid use of sizeof in nr_recvmsg() ++ - net: drop dst before queueing fragments ++ - [sparc] sparc64: Fix race in TLB batch processing. ++ - r8169: fix 8168evl frame padding. ++ - ixgbe: add missing rtnl_lock in PM resume path ++ - kernel/audit_tree.c: tree will leak memory when failure occurs in ++ audit_trim_trees() ++ - r8169: fix vlan tag read ordering. ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.46 ++ - nfsd4: don't allow owner override on 4.1 CLAIM_FH opens ++ - ext4: limit group search loop for non-extent files ++ - iscsi-target: Fix processing of OOO commands ++ - cifs: only set ops for inodes in I_NEW state ++ - KVM: VMX: fix halt emulation while emulating invalid guest sate ++ - [armel/kirkwood] Enable PCIe port 1 on QNAP TS-11x/TS-21x ++ - drivers/char/ipmi: memcpy, need additional 2 bytes to avoid memory ++ overflow ++ - ipmi: ipmi_devintf: compat_ioctl method fails to take ipmi_mutex ++ - btrfs: don't stop searching after encountering the wrong item ++ - TTY: Fix tty miss restart after we turn off flow-control ++ (Closes: #465823) ++ - SUNRPC: Prevent an rpc_task wakeup race ++ - fat: fix possible overflow for fat_clusters ++ - mm: mmu_notifier: re-fix freed page still mapped in secondary MMU ++ - mm compaction: fix of improper cache flush in migration code ++ - mm/THP: use pmd_populate() to update the pmd with pgtable_t pointer ++ - nilfs2: fix issue of nilfs_set_page_dirty() for page at EOF boundary ++ - random: fix accounting race condition with lockless irq entropy_count ++ update ++ - mm/pagewalk.c: walk_page_range should avoid VM_PFNMAP areas ++ - ipvs: ip_vs_sip_fill_param() BUG: bad check of return value ++ - x86,efi: Check max_size only if it is non-zero. ++ - x86,efi: Implement efi_no_storage_paranoia parameter ++ - tcp: force a dst refcount when prequeue packet ++ - packet: tpacket_v3: do not trigger bug() on wrong header status ++ - macvlan: fix passthru mode race between dev removal and rx path ++ - ipv6: do not clear pinet6 field ++ ++ [ Ben Hutchings ] ++ * Input: MT: add tracking and frame synchronisation to core ++ * Input: add support for Cypress PS/2 Trackpads (Closes: #703607), ++ thanks to Apollon Oikonomopoulos ++ * drm, agp: Update to 3.4.47: ++ - drm/i915: restrict kernel address leak in debugfs ++ - KMS: fix EDID detailed timing vsync parsing ++ - KMS: fix EDID detailed timing frame rate ++ - drm/radeon: add support for Richland APUs ++ - drm/radeon/benchmark: make sure bo blit copy exists before using it ++ - drm/i915: Don't clobber crtc->fb when queue_flip fails ++ - drm/i915: Use the correct size of the GTT for placing the per-process ++ entries ++ - udl: handle EDID failure properly. ++ - drm/i915: Add no-lvds quirk for Fujitsu Esprimo Q900 ++ - drm/i915: Fall back to bit banging mode for DVO transmitter detection ++ - drm/radeon: don't use get_engine_clock() on APUs ++ - drm/radeon/dce6: add missing display reg for tiling setup ++ - drm/radeon: properly lock disp in mc_stop/resume for evergreen+ ++ - drm/radeon: disable the crtcs in mc_stop (evergreen+) (v2) ++ - drm/radeon/evergreen+: don't enable HPD interrupts on eDP/LVDS ++ - drm/radeon: fix endian bugs in atom_allocate_fb_scratch() ++ - drm/radeon: fix possible segfault when parsing pm tables ++ - drm/radeon: add new richland pci ids ++ - drm/radeon: fix handling of v6 power tables ++ - drm/radeon: Fix VRAM size calculation for VRAM >= 4GB ++ - drm/radeon: check incoming cliprects pointer ++ - drm/mm: fix dump table BUG ++ * [rt] Update to 3.2.45-rt66: ++ - rcutiny: Fix typo of using swake_up() instead of swait_wake() ++ - tcp: force a dst refcount when prequeue packet ++ - x86/mce: Defer mce wakeups to threads for PREEMPT_RT ++ - swap: Use unique local lock name for swap_lock ++ - sched: Add is_idle_task() to handle invalidated uses of idle_cpu() ++ * debugfs: Document change of default mode ++ * iwlwifi: Do not request firmware API version 6 for IWL6005/6205 ++ (Closes: #705655) ++ * bug script: Remove broken sound functions (Closes: #705619) ++ * [i386/486] udeb: Add lxfb to fb-modules (Closes: #705780) ++ * [i386] cpufreq / Longhaul: Disable driver by default (Closes: #707047) ++ * iscsi-target: fix heap buffer overflow on error (CVE-2013-2850) ++ * ath9k: Disable PowerSave by default (Closes: #695968) ++ * dlm: Do not allocate a fd for peeloff (Closes: #706010) ++ * nfsd4: Fix performance problem with RELEASE_LOCKOWNER (Closes: #699361) ++ - hash lockowners to simplify RELEASE_LOCKOWNER ++ - maintain one seqid stream per (lockowner, file) ++ * ipw2100,ipw2200: Fix order of device registration (Closes: #656813) ++ * udf: Fix handling of i_blocks (Closes: #704269) ++ * kbuild: Fix missing '\n' for NEW symbols in yes "" | make oldconfig ++ >conf.new (Closes: #636029) ++ * [i386] udeb: Add viafb to fb-modules (Closes: #705788) ++ - [i386] udeb: Move i2c-algo-bit to i2c-modules and make fb-modules ++ depend on it ++ - viafb: Autoload on OLPC XO 1.5 only ++ * cifs: fix potential buffer overrun when composing a new options string ++ ++ [ Jonathan Nieder ] ++ * ext3,ext4,nfsd: dir_index: Return 64-bit readdir cookies for NFSv3 and 4 ++ (Closes: #685407) ++ ++ -- Ben Hutchings Sat, 08 Jun 2013 22:36:14 +0100 ++ ++linux (3.2.41-2+deb7u2) wheezy-security; urgency=high ++ ++ * s390/kvm: Ignore ABI changes, it should not be used OOT ++ ++ -- dann frazier Wed, 15 May 2013 12:07:33 -0600 ++ ++linux (3.2.41-2+deb7u1) wheezy-security; urgency=high ++ ++ [ dann frazier ] ++ * perf: Treat attr.config as u64 in perf_swevent_init() (CVE-2013-2094) ++ * TTY: fix timing leak with /dev/ptmx (CVE-2013-0160) ++ * ext4: avoid hang when mounting non-journal filesystems with orphan list ++ (CVE-2013-2015) ++ * crypto: algif - suppress sending source address information in recvmsg ++ (CVE-2013-3076) ++ * atm: update msg_namelen in vcc_recvmsg() (CVE-2013-3222) ++ * ax25: fix info leak via msg_name in ax25_recvmsg() (CVE-2013-3223) ++ * Bluetooth: fix possible info leak in bt_sock_recvmsg() (CVE-2013-3224) ++ * Bluetooth: RFCOMM - Fix missing msg_namelen update in rfcomm_sock_recvmsg() ++ (CVE-2013-3225) ++ * caif: Fix missing msg_namelen update in caif_seqpkt_recvmsg() ++ (CVE-2013-3227) ++ * irda: Fix missing msg_namelen update in irda_recvmsg_dgram() (CVE-2013-3228) ++ * iucv: Fix missing msg_namelen update in iucv_sock_recvmsg() (CVE-2013-3229) ++ * llc: Fix missing msg_namelen update in llc_ui_recvmsg() (CVE-2013-3231) ++ * rose: fix info leak via msg_name in rose_recvmsg() (CVE-2013-3234) ++ * tipc: fix info leaks via msg_name in recv_msg/recv_stream (CVE-2013-3235) ++ * tracing: Fix possible NULL pointer dereferences (CVE-2013-3301) ++ ++ [ Ben Hutchings ] ++ * [x86] KVM: Allow cross page reads and writes from cached translations. ++ (fixes regression in fix for CVE-2013-1796) ++ * net: fix incorrect credentials passing (CVE-2013-1979) ++ * tg3: fix length overflow in VPD firmware parsing (CVE-2013-1929) ++ * kernel/signal.c: stop info leak via the tkill and the tgkill syscalls ++ ++ -- dann frazier Tue, 14 May 2013 22:17:43 -0600 ++ ++linux (3.2.41-2) unstable; urgency=low ++ ++ * [ia64] udeb: Remove efi-modules package; make kernel-image provide ++ efi-modules (fixes FTBFS) ++ * linux-headers: Fix file installation on architectures without ++ Kbuild.platforms (Closes: #703800) ++ * [x86] drm/i915: bounds check execbuffer relocation count (CVE-2013-0913) ++ * [x86] drm: Enable DRM_GMA500 as module, replacing DRM_PSB (Closes: #703506) ++ - Enable DRM_GMA600, DRM_GMA3600, DRM_MEDFIELD ++ * [x86] KVM: x86: fix for buffer overflow in handling of MSR_KVM_SYSTEM_TIME ++ (CVE-2013-1796) ++ * [x86] KVM: x86: Convert MSR_KVM_SYSTEM_TIME to use gfn_to_hva_cache ++ functions (CVE-2013-1797) ++ * KVM: Fix bounds checking in ioapic indirect register reads (CVE-2013-1798) ++ ++ -- Ben Hutchings Mon, 25 Mar 2013 15:17:44 +0000 ++ ++linux (3.2.41-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.40 ++ - ext4: return ENOMEM if sb_getblk() fails ++ - ext4: fix possible use-after-free with AIO ++ - s390/kvm: Fix store status for ACRS/FPRS ++ - staging: comedi: disallow COMEDI_DEVCONFIG on non-board minors ++ - ext4: fix race in ext4_mb_add_n_trim() ++ - UBIFS: fix double free of ubifs_orphan objects ++ - hrtimer: Prevent hrtimer_enqueue_reprogram race ++ - nfsd: Fix memleak ++ - x86: Do not leak kernel page mapping locations ++ - USB: usb-storage: unusual_devs update for Super TOP SATA bridge ++ - posix-cpu-timers: Fix nanosleep task_struct leak ++ - NFSv4.1: Don't decode skipped layoutgets ++ - cgroup: fix exit() vs rmdir() race ++ - cpuset: fix cpuset_print_task_mems_allowed() vs rename() race ++ - ext4: fix xattr block allocation/release with bigalloc ++ - mm: fix pageblock bitmap allocation ++ - target: Add missing mapped_lun bounds checking during make_mappedlun ++ setup ++ - b43: Increase number of RX DMA slots ++ - posix-timer: Don't call idr_find() with out-of-range ID ++ - fs: Fix possible use-after-free with AIO ++ - powerpc/kexec: Disable hard IRQ before kexec ++ - mmu_notifier_unregister NULL Pointer deref and multiple ->release() ++ callouts ++ - tmpfs: fix use-after-free of mempolicy object (CVE-2013-1767) ++ - ocfs2: fix possible use-after-free with AIO ++ - ocfs2: fix ocfs2_init_security_and_acl() to initialize acl correctly ++ - ocfs2: ac->ac_allow_chain_relink=0 won't disable group relink ++ - idr: fix a subtle bug in idr_get_next() ++ - idr: make idr_get_next() good for rcu_read_lock() ++ - idr: fix top layer handling ++ - sysctl: fix null checking in bin_dn_node_address() ++ - nbd: fsync and kill block device on shutdown ++ - s390/timer: avoid overflow when programming clock comparator ++ (regression in 3.2.38) ++ - xen-pciback: rate limit error messages from xen_pcibk_enable_msi{,x}() ++ (CVE-2013-0231) ++ - xen-netback: correctly return errors from netbk_count_requests() ++ - xen-netback: cancel the credit timer when taking the vif down ++ - ipv6: use a stronger hash for tcp ++ - staging: comedi: ni_labpc: correct differential channel sequence for ++ AI commands ++ - staging: comedi: ni_labpc: set up command4 register *after* command3 ++ - vhost: fix length for cross region descriptor (CVE-2013-0311) ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.41 ++ - NFS: Don't allow NFS silly-renamed files to be deleted, no signal ++ - ARM: VFP: fix emulation of second VFP instruction ++ - md: fix two bugs when attempting to resize RAID0 array. ++ - proc connector: reject unprivileged listener bumps ++ - cifs: ensure that cifs_get_root() only traverses directories ++ - dm: fix truncated status strings ++ - hw_random: make buffer usable in scatterlist. (real fix for #701784) ++ - efi_pstore: Check remaining space with QueryVariableInfo() before ++ writing data ++ - efi: be more paranoid about available space when creating variables ++ (Closes: #703574) ++ - vfs: fix pipe counter breakage ++ - xen/pciback: Don't disable a PCI device that is already disabled. ++ - ALSA: seq: Fix missing error handling in snd_seq_timer_open() ++ - ext3: Fix format string issues (CVE-2013-1848) ++ - keys: fix race with concurrent install_user_keyrings() (CVE-2013-1792) ++ - USB: cdc-wdm: fix buffer overflow (CVE-2013-1860) ++ - signal: always clear sa_restorer on execve (CVE-2013-0914) ++ - crypto: user - fix info leaks in report API (CVE-2013-2546, ++ CVE-2013-2547, CVE-2013-2548) ++ - Fix: compat_rw_copy_check_uvector() misuse in aio, readv, writev, and ++ security keys ++ - batman-adv: bat_socket_read missing checks ++ - batman-adv: Only write requested number of byte to user buffer ++ - mm/hotplug: correctly add new zone to all other nodes' zone lists ++ (CVE-2012-5517) ++ - btrfs: use rcu_barrier() to wait for bdev puts at unmount ++ ++ [ Aurelien Jarno] ++ * [mips,mipsel] Disable VGA_CONSOLE and ignore the corresponding ABI ++ change. It is completely broken on MIPS. ++ * headers: Include Kbuild.platforms and Platform files in -common to ++ fix out-of-tree building on mips and mipsel. ++ * [{mips,mipsel}/{4,5}kc-malta] Enable HW_RANDOM as module so that both ++ flavours have a consistent configuration. ++ ++ [ Ben Hutchings ] ++ * [x86] ata_piix: reenable MS Virtual PC guests (fixes regression in ++ 3.2.19-1) ++ * test-patches: Clean up all previous test patches, whether or not they ++ were applied ++ * test-patches: Add --fuzz option to allow testing patches that have fuzz ++ * [x86] efi: Fix processor-specific memcpy() build error (Closes: #698581) ++ * udeb: Add hid-topseed to input-modules (Closes: #702611) ++ * [x86] drm/i915: Unconditionally initialise the interrupt workers, ++ thanks to Bjørn Mork (Closes: #692607) ++ * efi: Ensure efivars is loaded on EFI systems (Closes: #703363) ++ - [x86] Use a platform device to trigger loading of efivars ++ - [ia64] Change EFI_VARS from module to built-in ++ * efivars: Work around serious firmware bugs ++ - Allow disabling use as a pstore backend ++ - Add module parameter to disable use as a pstore backend ++ * [x86] Set EFI_VARS_PSTORE_DEFAULT_DISABLE=y ++ - explicitly calculate length of VariableName ++ - Handle duplicate names from get_next_variable() ++ * efi_pstore: Introducing workqueue updating sysfs ++ * efivars: pstore: Do not check size when erasing variable ++ * efivars: Remove check for 50% full on write ++ * kmsg_dump: Only dump kernel log in error cases (Closes: #703386) ++ - kexec: remove KMSG_DUMP_KEXEC ++ - kmsg_dump: don't run on non-error paths by default ++ * [x86] i915: initialize CADL in opregion (Closes: #703271) ++ * drm, agp: Update to 3.4.37: ++ - drm/radeon/dce6: fix display powergating ++ - drm: don't add inferred modes for monitors that don't support them ++ - drm/i915: Increase the RC6p threshold. ++ * signal: Fix use of missing sa_restorer field (build regression ++ introduced by fix for CVE-2013-0914) ++ * rds: limit the size allocated by rds_message_alloc() ++ * rtnl: fix info leak on RTM_GETLINK request for VF devices ++ * dcbnl: fix various netlink info leaks ++ * [s390] mm: fix flush_tlb_kernel_range() ++ * [powerpc] Fix cputable entry for 970MP rev 1.0 ++ * vhost/net: fix heads usage of ubuf_info ++ * udf: avoid info leak on export (CVE-2012-6548) ++ * isofs: avoid info leak on export (CVE-2012-6549) ++ * [x86,powerpc/powerpc64] random: Change HW_RANDOM back from built-in to ++ module, as we now have a real fix for #701784 ++ * [rt] Update to 3.2.40-rt60 ++ ++ -- Ben Hutchings Sat, 23 Mar 2013 03:54:34 +0000 ++ ++linux (3.2.39-2) unstable; urgency=high ++ ++ * [s390,s390x] virtio: Ignore ABI changes in 3.2.39 (fixes FTBFS) ++ * [sparc] drm: Ignore ABI changes in 3.2.39 (fixes FTBFS) ++ * [sparc] drm: Change from built-in to module ++ * [rt] Update to 3.2.39-rt59: ++ - acpi/rt: Convert acpi_gbl_hardware lock back to a raw_spinlock_t ++ - printk: Fix rq->lock vs logbuf_lock unlock lock inversion ++ - wait-simple: Simple waitqueue implementation ++ - rcutiny: Use simple waitqueue ++ * [x86] efi: Fix ABI change for introduction of efi_enabled() function ++ in 3.2.38 (Closes: #701690) ++ * [armel/versatile] i2c: Re-enable I2C_PCA_PLATFORM as module, erroneously ++ disabled in 3.2.39-1 (fixes FTBFS) ++ * [x86,powerpc/powerpc64] random: Change HW_RANDOM from module to built-in, ++ to work around virtio-rng bug (Closes: #701784) ++ ++ -- Ben Hutchings Wed, 27 Feb 2013 03:48:30 +0000 ++ ++linux (3.2.39-1) unstable; urgency=high ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.36 ++ - freezer: PF_FREEZER_NOSIG should be cleared along with PF_NOFREEZE ++ (Closes: #697077) ++ - tmpfs: fix shared mempolicy leak ++ - virtio: 9p: correctly pass physical address to userspace for high pages ++ - virtio: force vring descriptors to be allocated from lowmem ++ - USB: EHCI: bugfix: urb->hcpriv should not be NULL ++ - rcu: Fix batch-limit size problem ++ - Bluetooth: ath3k: Add support for VAIO VPCEH [0489:e027] ++ (Closes: #700550) ++ - mvsas: fix undefined bit shift ++ - ALSA: usb-audio: Avoid autopm calls after disconnection; Fix missing ++ autopm for MIDI input (Closes: #664068) ++ - target/file: Fix 32-bit highmem breakage for SGL -> iovec mapping ++ - SCSI: fix Null pointer dereference on disk error ++ - proc: pid/status: show all supplementary groups ++ - nfsd4: fix oops on unusual readlike compound ++ - ARM: missing ->mmap_sem around find_vma() in swp_emulate.c ++ - sctp: fix memory leak in sctp_datamsg_from_user() when copy from user ++ space fails ++ - ne2000: add the right platform device ++ - irda: sir_dev: Fix copy/paste typo ++ - ipv4: ip_check_defrag must not modify skb before unsharing ++ - telephony: ijx: buffer overflow in ixj_write_cid() ++ - udf: fix memory leak while allocating blocks during write ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.37 ++ - ext4: fix extent tree corruption caused by hole punch ++ - jbd2: fix assertion failure in jbd2_journal_flush() ++ - tmpfs mempolicy: fix /proc/mounts corrupting memory ++ - sparc: huge_ptep_set_* functions need to call set_huge_pte_at() ++ - inet: Fix kmemleak in tcp_v4/6_syn_recv_sock and ++ dccp_v4/6_request_recv_sock ++ - net: sched: integer overflow fix ++ - tcp: implement RFC 5961 3.2 ++ - tcp: implement RFC 5961 4.2 ++ - tcp: refine SYN handling in tcp_validate_incoming ++ - tcp: tcp_replace_ts_recent() should not be called from ++ tcp_validate_incoming() ++ - tcp: RFC 5961 5.2 Blind Data Injection Attack Mitigation ++ - RDMA/nes: Fix for crash when registering zero length MR for CQ ++ - ACPI : do not use Lid and Sleep button for S5 wakeup ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.38 ++ - staging: comedi: comedi_test: fix race when cancelling command ++ - mm: use aligned zone start for pfn_to_bitidx calculation ++ - [s390] s390/time: fix sched_clock() overflow (Closes: #698382) ++ - [i386] xen: Fix stack corruption in xen_failsafe_callback for 32bit ++ PVOPS guests. (CVE-2013-0190) ++ - KVM: PPC: Emulate dcbf ++ - evm: checking if removexattr is not a NULL ++ - ath9k_htc: Fix memory leak ++ - ath9k: do not link receive buffers during flush ++ - ath9k: fix double-free bug on beacon generate failure ++ - x86/msr: Add capabilities check ++ - can: c_can: fix invalid error codes ++ - can: ti_hecc: fix invalid error codes ++ - can: pch_can: fix invalid error codes ++ - smp: Fix SMP function call empty cpu mask race ++ - xfs: Fix possible use-after-free with AIO ++ - EDAC: Test correct variable in ->store function ++ - samsung-laptop: Disable on EFI hardware, to avoid damaging it ++ - NFS: Don't silently fail setattr() requests on mountpoints ++ - intel-iommu: Prevent devices with RMRRs from being placed into SI Domain ++ - ALSA: usb-audio: Fix regression by disconnection-race-fix patch ++ (Closes: #696321) ++ - printk: fix buffer overflow when calling log_prefix function from ++ call_console_drivers ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.39 ++ - USB: XHCI: fix memory leak of URB-private data ++ - sched/rt: Use root_domain of rt_rq not current processor ++ - mwifiex: fix incomplete scan in case of IE parsing error ++ - x86-64: Replace left over sti/cli in ia32 audit exit code ++ - Bluetooth: Fix handling of unexpected SMP PDUs ++ - ptrace/x86: Partly fix set_task_blockstep()->update_debugctlmsr() logic ++ - Fix race condition with PTRACE_SETREGS and fatal signal (CVE-2013-0871) ++ + ptrace: introduce signal_wake_up_state() and ptrace_signal_wake_up() ++ + ptrace: ensure arch_ptrace/ptrace_request can never race with SIGKILL ++ + wake_up_process() should be never used to wakeup a TASK_STOPPED/TRACED ++ task ++ - net: prevent setting ttl=0 via IP_TTL ++ - ipv6: fix header length calculation in ip6_append_data() ++ - netxen: fix off by one bug in netxen_release_tx_buffer() ++ - r8169: remove the obsolete and incorrect AMD workaround ++ - net: loopback: fix a dst refcounting issue ++ - packet: fix leakage of tx_ring memory ++ - net: sctp: sctp_setsockopt_auth_key: use kzfree instead of kfree ++ - net: sctp: sctp_endpoint_free: zero out secret key data ++ - xen/netback: shutdown the ring if it contains garbage. (CVE-2013-0216) ++ - xen/netback: don't leak pages on failure in xen_netbk_tx_check_gop. ++ - xen/netback: free already allocated memory on failure in ++ xen_netbk_get_requests ++ - netback: correct netbk_tx_err to handle wrap around. (CVE-2013-0217) ++ - tcp: frto should not set snd_cwnd to 0 ++ - tcp: fix for zero packets_in_flight was too broad ++ - tcp: fix MSG_SENDPAGE_NOTLAST logic ++ - bridge: Pull ip header into skb->data before looking into ip header. ++ (Closes: #697903) ++ - x86/xen: don't assume %ds is usable in xen_iret for 32-bit PVOPS. ++ (CVE-2013-0228) ++ ++ [ Aurelien Jarno ] ++ * [armhf/vexpress] Add kernel udebs. ++ ++ [ Julien Cristau ] ++ * Backport drm and agp subsystems from Linux 3.4.29 (closes: #687442) ++ - [x86] i915: Fixes freezes on Ivy Bridge (Closes: #689268) ++ - nouveau: Support for newer nvidia chipsets (Closes: #690284) ++ - radeon: Support for HD7000 'Southern Islands' chips ++ - [x86] drm/i915: add Ivy Bridge GT2 Server entries (Closes: #684767) ++ - [x86] drm/i915: Close race between processing unpin task and queueing ++ the flip ++ ++ [ Ben Hutchings ] ++ * Input: wacom - fix touch support for Bamboo Fun CTH-461 ++ * media/rc: Add iguanair driver from Linux 3.7 (Closes: #696925) ++ * rt2800: add chipset revision RT5390R support (Closes: #696592) ++ * [armhf/mx5] mtd: Enable MTD_BLOCK as module ++ * [armhf/mx5] udeb: Add missing storage drivers (Closes: #697128) ++ - Add ata-modules including libata, pata-modules including pata_imx, ++ sata-modules including ahci_platform ++ - Add sdhci-esdhc-imx to mmc-modules ++ - Add mtd-modules including mtd, mtdblock and m25p80 ++ * [armhf] udeb: Fix network driver selection ++ - [armhf/mx5] Remove nic-modules ++ - [armhf/vexpress] Add usb-modules ++ - Add standard set of USB drivers to nic-usb-modules ++ - Add nic-wireless-modules ++ * be2net: Apply backported fixes requested by Emulex (Closes: #697479) ++ - be2net: do not modify PCI MaxReadReq size ++ - be2net: fix reporting number of actual rx queues ++ - be2net: do not use SCRATCHPAD register ++ - be2net: reduce gso_max_size setting to account for ethernet header. ++ - be2net: Increase statistics structure size for skyhawk. ++ - be2net: Explicitly clear the reserved field in the Tx Descriptor ++ - be2net: Regression bug wherein VFs creation broken for multiple cards. ++ - be2net: Fix to trim skb for padded vlan packets to workaround an ASIC Bug ++ - be2net: Fix Endian ++ - be2net: Enable RSS UDP hashing for Lancer and Skyhawk ++ - be2net: dont pull too much data in skb linear part ++ - be2net: Fix to parse RSS hash from Receive completions correctly. ++ - be2net: Avoid disabling BH in be_poll() ++ * udeb: Add specialised USB keyboard/mouse drivers to input-modules: ++ hid-a4tech, hid-cypress, hid-ezkey (Closes: #697035), hid-kensington, ++ hid-keytouch, hid-kye, hid-multitouch, hid-ortek, hid-primax, ++ hid-quanta, hid-samsung, hid-speedlink ++ * radeon: Firmware is required for DRM and KMS on R600 onward, but not ++ for KMS on earlier chips (Closes: #697229) ++ * [!powerpc] radeon: Reenable DRM_RADEON_KMS, as it apparently works on ++ most non-PowerMac systems ++ * fs: cachefiles: add support for large files in filesystem caching ++ (Closes: #698376) ++ * [rt] Update to 3.2.38-rt57: ++ - sched: Adjust sched_reset_on_fork when nothing else changes ++ - sched: Queue RT tasks to head when prio drops ++ - sched: Consider pi boosting in setscheduler ++ - sched: Init idle->on_rq in init_idle() ++ - sched: Check for idle task in might_sleep() ++ - mm: swap: Initialize local locks early ++ * [armel/versatile,armhf/vexpress] i2c: Enable I2C, I2C_VERSATILE as modules ++ (Closes: #696182) ++ * ext4: Fix corruption by hole punch in large files (Closes: #685726) ++ - rewrite punch hole to use ext4_ext_remove_space() ++ - fix hole punch failure when depth is greater than 0 ++ - fix kernel BUG on large-scale rm -rf commands ++ * md: protect against crash upon fsync on ro array (Closes: #696650) ++ * net: Add alx driver for Atheros AR8161 and AR8162 (Closes: #699129) ++ - Mark as staging, since it has not been accepted upstream ++ * [armel/kirkwood] rtc-s35390a: add wakealarm support (Closes: #693997) ++ * [x86] i915: Invert backlight brightness control for various models ++ including Packard Bell NCL20 (Closes: #627372) and eMachines G725 ++ (Closes: #680737) ++ - Also allow this behaviour to be enabled via module parameter ++ invert_brightness=1 ++ * [amd64] edac: Enable EDAC_SBRIDGE as module (Closes: #699283) ++ * SCSI: Add virtio_scsi driver (Closes: #686636) ++ * [x86] sound: Enable LINE6_USB as module (Closes: #700211) ++ - Apply upstream changes up to Linux 3.8-rc1 ++ * [armhf/mx5] Update description to mention i.MX53 ++ * mm: Try harder to allocate vmemmap blocks (Closes: #699913) ++ * aufs: Update to aufs3.2-20130204: ++ - support for syncfs(2) ++ - possible bugfix, race in lookup ++ - bugfix, half refreshed iinfo ++ - possible bugfix, au_lkup_by_ino() returns ESTALE ++ * [x86] efi: Clear EFI_RUNTIME_SERVICES rather than EFI_BOOT by "noefi" boot ++ parameter ++ * [x86] efi: Make "noefi" really disable EFI runtime serivces ++ * drm, agp: Update to 3.4.32 ++ - drm/radeon: add WAIT_UNTIL to the non-VM safe regs list for cayman/TN ++ - drm/radeon: prevent crash in the ring space allocation ++ * linux-image-dbg: Add symlinks to vmlinux from the locations expected by ++ kdump-tools (Closes: #700418), systemtap and others ++ * mm: fix pageblock bitmap allocation (fixes regression in 3.2.38) ++ * USB: usb-storage: unusual_devs update for Super TOP SATA bridge ++ ++ [ Cyril Brulebois ] ++ * Bump python build-dep, needed since the switch from local SortedDict ++ to collections.OrderedDict (new in version 2.7). (Closes: #697740) ++ ++ -- Ben Hutchings Mon, 25 Feb 2013 00:36:51 +0000 ++ ++linux (3.2.35-2) unstable; urgency=low ++ ++ * [ia64] Make IPV6 built-in (fixes FTBFS) ++ * [rt] Update to 3.2.35-rt52 ++ * audit: Increase maximum number of names logged per syscall to 30 ++ (Closes: #631799) ++ * asix: Add support for Lenovo 10/100 USB dongle (Closes: #696248) ++ * udeb: Add ums-eneub6250, ums-realtek (Closes: #694348) to ++ usb-storage-modules ++ ++ -- Ben Hutchings Wed, 19 Dec 2012 03:41:35 +0000 ++ ++linux (3.2.35-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.33 ++ - samsung-laptop: don't handle backlight if handled by acpi/video ++ (Closes: #693190) ++ - e1000: fix vlan processing regression (Closes: #690956) ++ - [x86] drm/i915: no lvds quirk for Zotac ZDBOX SD ID12/ID13 ++ (Closes: #691122) ++ - au0828: fix case where STREAMOFF being called on stopped stream ++ causes BUG() ++ - net: Fix skb_under_panic oops in neigh_resolve_output ++ - vlan: don't deliver frames for unknown vlans to protocols ++ - RDS: fix rds-ping spinlock recursion ++ - tcp: resets are misrouted ++ - nfsd4: fix nfs4 stateid leak ++ - [arm] vfp: fix saving d16-d31 vfp registers on v6+ kernels ++ - scsi_debug: Fix off-by-one bug when unmapping region ++ - storvsc: Account for in-transit packets in the RESET path ++ - tmpfs,ceph,gfs2,isofs,reiserfs,xfs: fix fh_len checking ++ - ext4: race-condition protection for ext4_convert_unwritten_extents_endio ++ (CVE-2012-4508) ++ - md/raid10: use correct limit variable ++ - net/wireless: ipw2200: Fix panic occurring in ipw_handle_promiscuous_tx() ++ - USB: cdc-acm: fix pipe type of write endpoint ++ - [x86] xen: don't corrupt %eip when returning from a signal handler ++ - sysfs: sysfs_pathname/sysfs_add_one: Use strlcat() instead of strcat() ++ - fs/compat_ioctl.c: VIDEO_SET_SPU_PALETTE missing error check ++ - netfilter: nf_conntrack: fix racy timer handling with reliable events ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.34 ++ - x86: Remove the ancient and deprecated disable_hlt() and enable_hlt() ++ facility (Closes: #667501) ++ - ALSA: PCM: Fix some races at disconnection ++ - ALSA: usb-audio: Fix races at disconnection ++ - crypto: cryptd - disable softirqs in cryptd_queue_worker to prevent ++ data corruption ++ - mac80211: Only process mesh config header on frames that RA_MATCH ++ - mac80211: fix SSID copy on IBSS JOIN ++ - mac80211: check management frame header length ++ - mac80211: verify that skb data is present ++ - mac80211: make sure data is accessible in EAPOL check ++ - ath9k: Test for TID only in BlockAcks while checking tx status ++ - nfs: Show original device name verbatim in /proc/*/mount{s,info} ++ (Closes: #669314) ++ - target: Avoid integer overflow in se_dev_align_max_sectors() ++ - hwmon: (w83627ehf) Force initial bank selection ++ - xfs: fix reading of wrapped log data ++ - fanotify: fix missing break ++ - drm/vmwgfx: Fix a case where the code would BUG when trying to pin ++ GMR memory ++ - sctp: fix call to SCTP_CMD_PROCESS_SACK in sctp_cmd_interpreter() ++ - netlink: use kfree_rcu() in netlink_release() ++ - tcp: fix FIONREAD/SIOCINQ ++ - net: fix divide by zero in tcp algorithm illinois (CVE-2012-4565) ++ - af-packet: fix oops when socket is not present ++ - r8169: Fix WoL on RTL8168d/8111d. (Closes: #674154) ++ - sky2: Fix for interrupt handler (Closes: #681280) ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.35 ++ - UBIFS: fix mounting problems after power cuts ++ - [s390] gup: add missing TASK_SIZE check to get_user_pages_fast() ++ - [x86] Exclude E820_RESERVED regions and memory holes above 4 GB from ++ direct mapping. ++ - netfilter: Mark SYN/ACK packets as invalid from original direction ++ - netfilter: Validate the sequence number of dataless ACK packets as well ++ - ipv4: avoid undefined behavior in do_ip_setsockopt() ++ - Input: i8042 - also perform controller reset when suspending ++ (Closes: #693934) ++ - brcm80211: smac: only print block-ack timeout message at trace level ++ (Closes: #674430) ++ - GFS2: Test bufdata with buffer locked and gfs2_log_lock held ++ - [x86] mce, therm_throt: Don't report power limit and package level ++ thermal throttle events in mcelog (Closes: #695209) ++ - [hppa] fix virtual aliasing issue in get_shared_area() ++ - xfs: drop buffer io reference when a bad bio is built ++ - reiserfs: Protect reiserfs_quota_{on,write}() with write lock ++ - md: Reassigned the parameters if read_seqretry returned true in func ++ md_is_badblock. ++ - md: Avoid write invalid address if read_seqretry returned true. ++ - [i386] Fix invalid stack address while in softirq ++ - selinux: fix sel_netnode_insert() suspicious rcu dereference ++ - [hppa] fix user-triggerable panic on parisc ++ - block: Don't access request after it might be freed ++ - futex: avoid wake_futex() for a PI futex_q ++ ++ [ Ben Hutchings ] ++ * [x86] udeb: Re-add isci to scsi-extra-modules (Closes: #690886; ++ regression of #652897 in version 3.2~rc7-1~experimental.1 due to ++ mis-merge) ++ * udeb: Add missing net drivers: ++ - Add 8021q (Closes: #689159), cxgb4, cxgb4vf, igbvf, ixgbevf, micrel, ++ mlx4_en, pch_gbe, qlge, smsc9420, tehuti, vxge to nic-extra-modules ++ - Add int51x1, smsc75xx, smsc95xx to nic-usb-modules ++ - Add adm8211, at76c50x-usb, b43legacy, iwl4965, libertas_tf_usb, ++ mwifiex_pcie, mwl8k, orinoco_usb, prism2_usb, r8187se, r8192e_pci, ++ r8712u, rtl8192ce (Closes: #686605), rtl8192cu, rtl8192de, rtl8192se ++ vt6656_stage to nic-wireless-modules ++ - Move broadcom to nic-modules, as it may be needed by tg3 ++ * udeb: Add bnx2fc, fnic, pmcraid to scsi-extra-modules ++ * udeb: Move rtl8180 to nic-wireless-modules ++ * [x86] asus-laptop: Do not call HWRS on init (Closes: #692436) ++ * [x86] drm/i915: Only kick out vesafb if we takeover the fbcon with KMS ++ (Closes: #686284) ++ * [!x86] radeon: Disable DRM_RADEON_KMS, as this is still not expected to ++ work (Closes: #628972) ++ * radeon: Disable KMS earlier if firmware is not installed (Closes: #607194) ++ * [amd64] linux-image: Include VIA Nano in package description ++ * linux-image-dbg: Change package description to use the phrase ++ 'debugging symbols' and correct grammar ++ * usb: Disable UAS; it is known to be broken, and the supported devices ++ can also work with usb-storage ++ * ipv6: Treat ND option 31 as userland (DNSSL support) (Closes: #694522) ++ * rt2x00: Add device IDs 5362, 5392, 539b (Closes: #694312) ++ * udeb: Add pata_piccolo to pata-modules (Closes: #695437) ++ * firmware_class: Log every success and failure against given device ++ * firmware: Remove redundant log messages from drivers ++ * [x86] ACPI / video: ignore BIOS initial backlight value for ++ HP Folio 13-2000 (Closes: #692361) ++ * [x86] KVM: x86: invalid opcode oops on SET_SREGS with OSXSAVE bit set ++ (CVE-2012-4461) ++ * kmod: make __request_module() killable (CVE-2012-4398) ++ * exec: do not leave bprm->interp on stack (CVE-2012-4530) ++ * exec: use -ELOOP for max recursion depth ++ * [rt] Update to 3.2.34-rt51: ++ - hrtimer: Raise softirq if hrtimer irq stalled ++ - rcu: Disable RCU_FAST_NO_HZ on RT ++ - net: netfilter: Serialize xt_write_recseq sections on RT ++ * megaraid_sas: fix memory leak if SGL has zero length entries ++ (Closes: #688198) ++ ++ [ Ian Campbell ] ++ * [xen] add support for microcode updating. (Closes: #693053) ++ ++ -- Ben Hutchings Mon, 10 Dec 2012 00:14:55 +0000 ++ ++linux (3.2.32-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.31 ++ - target: Fix ->data_length re-assignment bug with SCSI overflow ++ - hpsa: fix handling of protocol error ++ - cifs: fix return value in cifsConvertToUTF16 ++ - asix: Support DLink DUB-E100 H/W Ver C1 (Closes: #687567) ++ - dj: memory scribble in logi_dj ++ - dm: handle requests beyond end of device instead of using BUG_ON ++ - md/raid10: fix "enough" function for detecting if array is failed. ++ - libata: Prevent interface errors with Seagate FreeAgent GoFlex ++ - vfs: dcache: fix deadlock in tree traversal ++ - Revert "drm/radeon: rework pll selection (v3)" (regression in 3.2.30) ++ - HID: hidraw: don't deallocate memory when it is in use ++ - xfrm: Workaround incompatibility of ESN and async crypto ++ - xfrm_user: fix various information leaks ++ - xfrm_user: ensure user supplied esn replay window is valid ++ - net: guard tcp_set_keepalive() to tcp sockets ++ - ipv4: raw: fix icmp_filter() ++ - ipv6: raw: fix icmpv6_filter() ++ - ipv6: mip6: fix mip6_mh_filter() ++ - netrom: copy_datagram_iovec can fail ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.32 ++ - mtd: nand: Use the mirror BBT descriptor when reading its version ++ - TTY: ttyprintk, don't touch behind tty->write_buf ++ - n_gsm: fix various serious bugs ++ - hpsa: Use LUN reset instead of target reset ++ - staging: comedi: don't dereference user memory for INSN_INTTRIG ++ - ext4: fix potential deadlock in ext4_nonda_switch() ++ - staging: comedi: fix memory leak for saved channel list ++ - scsi_remove_target: fix softlockup regression on hot remove ++ (Closes: #690990) ++ - usb: host: xhci: Fix Null pointer dereferencing with 71c731a for ++ non-x86 systems (regression in 3.2.30) ++ - ext4: online defrag is not supported for journaled files ++ - staging: comedi: s626: don't dereference insn->data ++ - serial: pl011: handle corruption at high clock speeds ++ - ext4: always set i_op in ext4_mknod() ++ - ext4: fix fdatasync() for files with only i_size changes ++ - [x86] drm/i915: use adjusted_mode instead of mode for checking the ++ 6bpc force flag (regression in 3.2.29) ++ - staging: comedi: jr3_pci: fix iomem dereference ++ - JFFS2: don't fail on bitflips in OOB ++ - mtd: nandsim: bugfix: fail if overridesize is too big ++ - pnfsblock: fix partial page buffer wirte ++ - target/file: Re-enable optional fd_buffered_io=1 operation ++ - iscsit: remove incorrect unlock in iscsit_build_sendtargets_resp ++ - rapidio/rionet: fix multicast packet transmit logic ++ - ALSA: aloop - add locking to timer access ++ - [armhf/omap] counter: add locking to read_persistent_clock ++ - mm: fix invalidate_complete_page2() lock ordering ++ - mm: thp: fix pmd_present for split_huge_page and PROT_NONE with THP ++ - mm: hugetlb: fix pgoff computation when unmapping page from vma ++ - hugetlb: do not use vma_hugecache_offset() for vma_prio_tree_foreach ++ - [x86] firewire: cdev: fix user memory corruption (i386 userland on ++ amd64 kernel) ++ - udf: fix retun value on error path in udf_load_logicalvol ++ - eCryptfs: Unlink lower inode when ecryptfs_create() fails ++ - eCryptfs: Initialize empty lower files when opening them ++ - eCryptfs: Revert to a writethrough cache model ++ - eCryptfs: Write out all dirty pages just before releasing the lower file ++ - eCryptfs: Call lower ->flush() from ecryptfs_flush() ++ - mempolicy: remove mempolicy sharing ++ - mempolicy: fix a race in shared_policy_replace() ++ - mempolicy: fix refcount leak in mpol_set_shared_policy() ++ - mempolicy: fix a memory corruption by refcount imbalance in ++ alloc_pages_vma() ++ - hpsa: dial down lockup detection during firmware flash ++ - netfilter: nf_ct_ipv4: packets with wrong ihl are invalid ++ - netfilter: nf_nat_sip: fix incorrect handling of EBUSY for RTCP ++ expectation ++ - netfilter: nf_ct_expect: fix possible access to uninitialized timer ++ - ipvs: fix oops on NAT reply in br_nf context ++ ++ [ Ben Hutchings ] ++ * codel: refine one condition to avoid a nul rec_inv_sqrt ++ * [mips,mipsel] Ignore NFS/SunRPC ABI changes in 3.2.30 (fixes FTBFS) ++ * tg3: Fix TSO CAP for 5704 devs w / ASF enabled ++ * SUNRPC: Set alloc_slot for backchannel tcp ops (regression in 3.2.30) ++ * iwlwifi: Do not request unreleased firmware for IWL6000 (Closes: #689416) ++ * aufs: Update to aufs3.2-20120827: ++ - Fix statfs() values when different block sizes are in use ++ * udeb: Add hid-logitech-dj to input-modules (Closes: #661379) ++ * connector: Make CONNECTOR built-in; enable PROC_EVENTS (Closes: #588200) ++ * e1000e: Change wthresh to 1 to avoid possible Tx stalls ++ * [x86] efi: Build EFI stub with EFI-appropriate options ++ * [rt] Update to 3.2.32-rt48: ++ - random: Make add_interrupt_randomness() work on rt ++ - softirq: Init softirq local lock after per cpu section is set up ++ - mm: slab: Fix potential deadlock ++ - mm: page_alloc: Use local_lock_on() instead of plain spinlock ++ - rt: rwsem/rwlock: lockdep annotations ++ - sched: Better debug output for might sleep ++ - stomp_machine: Use mutex_trylock when called from inactive cpu ++ * [x86] storvsc: Account for in-transit packets in the RESET path ++ * fs: handle failed audit_log_start properly ++ * fs: prevent use after free in auditing when symlink following was denied ++ * kernel/sys.c: fix stack memory content leak via UNAME26 (CVE-2012-0957) ++ * ALSA: hda: Fix oops caused by "Fix internal mic for Lenovo Ideapad U300s" ++ in 3.2.32 ++ ++ -- Ben Hutchings Mon, 22 Oct 2012 06:25:37 +0100 ++ ++linux (3.2.30-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.30 ++ - ext3: Fix fdatasync() for files with only i_size changes ++ - UBI: fix a horrible memory deallocation bug ++ - fuse: fix retrieve length ++ - mmc: card: Skip secure erase on MoviNAND; causes unrecoverable corruption ++ - udf: Fix data corruption for files in ICB ++ - xen: Use correct masking in xen_swiotlb_alloc_coherent. ++ - CIFS: Fix error handling in cifs_push_mandatory_locks ++ - [x86] drm/i915: Wait for all pending operations to the fb before ++ disabling the pipe ++ - xhci: Fix bug after deq ptr set to link TRB ++ - NFS: Fix the initialisation of the readdir 'cookieverf' array ++ - staging: comedi: das08: Correct AI encoding for das08jr-16-ao ++ - staging: comedi: das08: Correct AO output for das08jr-16-ao ++ - rt2800usb: Added rx packet length validity check ++ - staging: zcache: fix cleancache race condition with shrinker ++ - NFS: return error from decode_getfh in decode open ++ - ARM: 7526/1: traps: send SIGILL if get_user fails on undef handling path ++ - ahci: Add alternate identifier for the 88SE9172 ++ ++ [ Ben Hutchings ] ++ * [s390/s390x-tape] udeb: Remove fuse-modules configuration (fixes FTBFS) ++ ++ -- dann frazier Wed, 26 Sep 2012 16:00:58 +0900 ++ ++linux (3.2.29-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.24 ++ - sched/nohz: Rewrite and fix load-avg computation -- again ++ (Closes: #674153) ++ - libsas: fix taskfile corruption in sas_ata_qc_fill_rtf ++ - md/raid1: fix use-after-free bug in RAID1 data-check code. ++ - PCI: EHCI: fix crash during suspend on ASUS computers ++ - cpufreq / ACPI: Fix not loading acpi-cpufreq driver (regression in 3.2.2) ++ - block: fix infinite loop in __getblk_slow (regression in 3.2.19) ++ (Closes: #684293) ++ - PM / Hibernate: Hibernate/thaw fixes/improvements ++ - tcm_fc: Fix crash seen with aborts and large reads ++ - fifo: Do not restart open() if it already found a partner ++ - cifs: on CONFIG_HIGHMEM machines, limit the rsize/wsize to the kmap space ++ - UBIFS: fix a bug in empty space fix-up ++ - ore: Fix NFS crash by supporting any unaligned RAID IO ++ - ore: Remove support of partial IO request (NFS crash) ++ - pnfs-obj: don't leak objio_state if ore_write/read fails ++ - pnfs-obj: Fix __r4w_get_page when offset is beyond i_size ++ - dm raid1: fix crash with mirror recovery and discard ++ - dm raid1: set discard_zeroes_data_unsupported ++ - time: Fix bugs in leap-second handling (Closes: #679882) ++ + ntp: Fix leap-second hrtimer livelock ++ + timekeeping: Fix leapsecond triggered load spike issue ++ - bnx2x: fix checksum validation ++ - bnx2x: fix panic when TX ring is full ++ - eCryptfs: Gracefully refuse miscdev file ops on inherited/passed files ++ - ACPI / PM: Make acpi_pm_device_sleep_state() follow the specification ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.25 ++ - mm: Fix various performance problems, particularly affecting use of ++ transparent hugepages (Closes: #675493) ++ - target: Add range checking to UNMAP emulation ++ - target: Fix reading of data length fields for UNMAP commands ++ - target: Fix possible integer underflow in UNMAP emulation ++ - target: Check number of unmap descriptors against our limit ++ - ext4: don't let i_reserved_meta_blocks go negative ++ - ext4: undo ext4_calc_metadata_amount if we fail to claim space ++ - locks: fix checking of fcntl_setlease argument ++ - Btrfs: call the ordered free operation without any locks held ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.26 ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.27 ++ - lirc_sir: make device registration work (Closes: #680762) ++ - random: Improve random number generation on non-interactive systems ++ + random: Use arch_get_random_int instead of cycle counter if avail ++ + random: Use arch-specific RNG to initialize the entropy store ++ + random: make 'add_interrupt_randomness()' do something sane ++ + usb: feed USB device information to the /dev/random driver ++ + net: feed /dev/random with the MAC address when registering a device ++ + rtc: wm831x: Feed the write counter into device_add_randomness() ++ + mfd: wm831x: Feed the device UUID into device_add_randomness() ++ - futex: Test for pi_mutex on fault in futex_wait_requeue_pi() ++ - futex: Forbid uaddr == uaddr2 in futex_wait_requeue_pi() ++ - s390/mm: downgrade page table after fork of a 31 bit process ++ - asus-wmi: use ASUS_WMI_METHODID_DSTS2 as default DSTS ID. ++ (Closes: #679158) ++ - md/raid1: don't abort a resync on the first badblock. ++ - [arm] 7467/1: mutex: use generic xchg-based implementation for ARMv6+ ++ - [arm] 7476/1: vfp: only clear vfp state for current cpu in vfp_pm_suspend ++ - [arm] 7477/1: vfp: Always save VFP state in vfp_pm_suspend on UP ++ - [arm] 7478/1: errata: extend workaround for erratum #720789 ++ - [arm] Fix undefined instruction exception handling ++ - mm: mmu_notifier: fix freed page still mapped in secondary MMU ++ - mm: hugetlbfs: close race during teardown of hugetlbfs shared page tables ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.28 ++ - bnx2: Fix bug in bnx2_free_tx_skbs(). ++ - sch_sfb: Fix missing NULL check ++ - sctp: Fix list corruption resulting from freeing an association on a list ++ - cipso: don't follow a NULL pointer when setsockopt() is called ++ - caif: fix NULL pointer check ++ - net/tun: fix ioctl() based info leaks ++ - rtlwifi: rtl8192cu: Change buffer allocation for synchronous reads ++ - hfsplus: fix overflow in sector calculations in hfsplus_submit_bio ++ - drm/i915: fixup seqno allocation logic for lazy_request ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.29 ++ - pnfs: defer release of pages in layoutget ++ - fuse: verify all ioctl retry iov elements ++ - usb: serial: mos7840: Fixup mos7840_chars_in_buffer() ++ - sched: fix divide by zero at {thread_group,task}_times ++ - vfs: canonicalize create mode in build_open_flags() ++ - dccp: check ccid before dereferencing ++ - md: Don't truncate size at 4TB for RAID0 and Linear ++ - target: fix NULL pointer dereference bug alloc_page() fails to get memory ++ - USB: CDC ACM: Fix NULL pointer dereference ++ - alpha: Don't export SOCK_NONBLOCK to user space. (Closes: #658460) ++ - radeon: Fix various bugs in reading vbios (Closes: #685604) ++ - vfs: missed source of ->f_pos races ++ - svcrpc: fix BUG() in svc_tcp_clear_pages ++ - svcrpc: sends on closed socket should stop immediately ++ - fbcon: fix race condition between console lock and cursor timer (v1.1) ++ - mm: hugetlbfs: correctly populate shared pmd ++ - fs/buffer.c: remove BUG() in possible but rare condition ++ - block: replace __getblk_slow misfix by grow_dev_page fix ++ - Staging: speakup: fix an improperly-declared variable. (Closes: #685953) ++ - NFS: Fix Oopses in nfs_lookup_revalidate and nfs4_lookup_revalidate ++ ++ [ Ben Hutchings ] ++ * Bump ABI to 4 ++ * linux-image: Include package version in utsname version string ++ ('uname -v' output) (Closes: #638878) ++ * linux-source: Drop support for version.$DISTRIBUTION ++ * [arm,ia64,powerpc,s390,sh,x86] linux-image: Include package version ++ in stack traces from WARN, BUG, Oops etc. ++ * udeb: Add snd-hda-codec-ca0132 to sound-modules (Closes: #682368) ++ * linux-source: Suggest pkg-config, needed to build kconfig GUIs ++ (Closes: #682726) ++ * debugfs: Add mode, uid and gid mount options; set default mode to 700 ++ (Closes: #681418) ++ * net: new counter for tx_timeout errors in sysfs ++ * net: Add byte queue limits (bql) for reduced buffer-bloat ++ * bnx2,bnx2x,e1000e,forcedeth,igb,ixgbe,sfc,skge,sky2,tg3: ++ Add support for bql ++ * fs: Update link security restrictions to match Linux 3.6: ++ - Drop kconfig options; restrictions can only be disabled by sysctl ++ - Change the audit message type from AUDIT_AVC (1400) to ++ AUDIT_ANON_LINK (1702) ++ * [rt] Update to 3.2.28-rt42: ++ - time/rt: Fix up leap-second backport for RT changes ++ - fix printk flush of messages ++ * rds: set correct msg_namelen (CVE-2012-3430) ++ * e1000: add dropped DMA receive enable back in for WoL (Closes: #684618) ++ * PCI/PM/Runtime: make PCI traces quieter (Closes: #684049) ++ * rc: ite-cir: Initialise ite_dev::rdev earlier (Closes: #684441) ++ * input: Enable TOUCHSCREEN_ATMEL_MXT as module (Closes: #685123) ++ * usb: Add USB_QUIRK_RESET_RESUME for all Logitech UVC webcams ++ (Closes: #668211) ++ * [alpha] Use gcc-4.6 (Closes: #685894) ++ - Use large data model to work around link failure ++ * [i386/486] video: Change FB_GEODE_LX from built-in to module (lxfb) ++ (Closes: #686528) ++ * [i386/686-pae] video: Disable Geode framebuffer drivers, not used with ++ any chips that support PAE ++ * [x86] drm/i915: Fix i8xx interrupt handling (Closes: #655152) ++ * [armel/kirkwood] ahci: Add JMicron 362 device IDs (Closes: #634180) ++ * speakup: lower default software speech rate (Closes: #686742) ++ * e1000e: Fix potential DoS when TSO enabled ++ * mm: Remove user-triggerable BUG from mpol_to_str ++ * sfc: Fix maximum number of TSO segments and minimum TX queue size ++ (CVE-2012-3412) ++ - tcp: Apply device TSO segment limit earlier ++ * net_sched: gact: Fix potential panic in tcf_gact(). ++ * af_packet: remove BUG statement in tpacket_destruct_skb ++ * net: Fix various information leaks ++ * af_packet: don't emit packet on orig fanout group ++ * af_netlink: force credentials passing (CVE-2012-3520) ++ * netlink: fix possible spoofing from non-root processes ++ * net: ipv4: ipmr_expire_timer causes crash when removing net namespace ++ * [i386] i810fb: Enable FB_I810_GTF, FB_I810_I2C (Closes: #687644) ++ * udeb: Add fuse-modules to support os-prober (see #684265) ++ ++ [ Bastian Blank ] ++ * Make xen-linux-system meta-packages depend on xen-system. This allows ++ automatic updates. (closes: #681637) ++ ++ -- Ben Hutchings Sun, 16 Sep 2012 06:16:38 +0100 ++ ++linux (3.2.23-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.22 ++ - nilfs2: ensure proper cache clearing for gc-inodes ++ - ath9k_hw: avoid possible infinite loop in ar9003_get_pll_sqsum_dvc ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.23 ++ - splice: fix racy pipe->buffers uses ++ - NFC: Prevent multiple buffer overflows in NCI (CVE-2012-3364) ++ - NFC: Return from rawsock_release when sk is NULL ++ - md/raid5: Do not add data_offset before call to is_badblock ++ - md/raid5: In ops_run_io, inc nr_pending before calling ++ md_wait_for_blocked_rdev ++ - md/raid10: fix failure when trying to repair a read error. ++ - udf: Improve sanity checking of filesystem metadata (CVE-2012-3400) ++ + udf: Avoid run away loop when partition table length is corrupted ++ + udf: Fortify loading of sparing table ++ - l2tp: fix a race in l2tp_ip_sendmsg() ++ - netpoll: fix netpoll_send_udp() bugs ++ - Btrfs: run delayed directory updates during log replay ++ - ocfs2: clear unaligned io flag when dio fails ++ - aio: make kiocb->private NUll in init_sync_kiocb() ++ - mm: Hold a file reference in madvise_remove ++ ++ [ Ben Hutchings ] ++ * linux-libc-dev: Fix redundant 'GNU glibc' in description (Closes: #631228) ++ * README.source: Correct name of main patch series file ++ * [sh] Fix up store queue code for subsys_interface changes (Closes: #680025) ++ * scsi: Silence unnecessary warnings about ioctl to partition ++ (Closes: #656899) ++ * Update Czech debconf template translations (Michal Simunek) ++ (Closes: #679674) ++ * linux-image: Remove versioned relations where stable version is new enough ++ * udf: Improve table length check to avoid possible overflow ++ * CIFS: Respect negotiated MaxMpxCount (deferred from 3.2.14) ++ * epoll: clear the tfile_check_list on -ELOOP (CVE-2012-3375) ++ * nouveau: Update to support Fermi (NVC0+) acceleration (Closes: #679566) ++ - Refactor sub-channel use ++ - Bump version to 1.0.0 ++ * e100: ucode is optional in some cases ++ * [x86] drm/i915: prefer wide & slow to fast & narrow in DP configs ++ (Closes: #658662) ++ * cipso: don't follow a NULL pointer when setsockopt() is called ++ * [x86] hwmon: Enable SENSORS_SCH5636 as module (Closes: #680934) ++ * atl1c: fix issue of transmit queue 0 timed out ++ * raid5: delayed stripe fix (Closes: #680366) ++ * fs: Remove easily user-triggerable BUG from generic_setlease ++ * tcp: drop SYN+FIN messages ++ * fifo: Do not restart open() if it already found a partner (Closes: #678852) ++ * [rt] linux-source: Include -rt version suffix ++ * [rt] Update to 3.2.23-rt37: ++ - Latency histogramms: Cope with backwards running local trace clock ++ - Latency histograms: Adjust timer, if already elapsed when programmed ++ - Disable RT_GROUP_SCHED in PREEMPT_RT_FULL ++ - Latency histograms: Detect another yet overlooked sharedprio condition ++ - slab: Prevent local lock deadlock ++ - fs, jbd: pull your plug when waiting for space ++ - perf: Make swevent hrtimer run in irq instead of softirq ++ - cpu/rt: Rework cpu down for PREEMPT_RT ++ - cpu/rt: Fix cpu_hotplug variable initialization ++ - workqueue: Revert workqueue: Fix PF_THREAD_BOUND abuse ++ - workqueue: Revert workqueue: Fix cpuhotplug trainwreck ++ ++ [ Arnaud Patard ] ++ * [mipsel] add r8169 to d-i udeb. ++ ++ -- Ben Hutchings Sun, 22 Jul 2012 23:25:47 +0100 ++ ++linux (3.2.21-3) unstable; urgency=low ++ ++ * driver core: remove __must_check from device_create_file ++ (fixes FTBFS on sparc) ++ * i2400m: Disable I2400M_SDIO; hardware did not reach production ++ * apparmor: remove advertising the support of network rules from ++ compat iface (Closes: #676515) ++ * xen/netfront: teardown the device before unregistering it (Closes: #675190) ++ * linux-{doc,manual,source,support}: Mark as capable of satisfying ++ relations from foreign packages (Multi-Arch: foreign) (Closes: #679202) ++ ++ -- Ben Hutchings Thu, 28 Jun 2012 04:58:18 +0100 ++ ++linux (3.2.21-2) unstable; urgency=low ++ ++ * [i386] cpufreq/gx: Fix the compile error ++ * [powerpc] Enable PPC_DISABLE_WERROR (fixes FTBFS) ++ * tracing/mm: Move include of trace/events/kmem.h out of header into slab.c ++ (fixes FTBFS on sparc) ++ * [i386] Disable incomplete lguest support ++ * udeb: Add missing dependencies for various modules (see #678587) ++ - [armel/kirkwood] fb-modules depends on kernel-image ++ - [ia64] nic-usb-modules depends on kernel-image, nic-shared-modules, ++ usb-modules ++ - [ia64] sata-modules depends on kernel-image, scsi-core-modules ++ - [ia64] scsi-modules depends on scsi-core-modules ++ - [ia64,powerpc,ppc64] pcmcia-modules depends on kernel-image ++ - [powerpc,ppc64] nic-pcmcia-modules depends on kernel-image, ++ nic-shared-modules, pcmcia-modules ++ - [powerpc,ppc64,x86] scsi-modules depends on ata-modules ++ - [x86] nic-extra-modules depends on i2c-modules ++ * wacom: do not crash when retrieving touch_max (Closes: #678798) ++ * wacom: Revert unintended changes to handling of Tablet PCs ++ (Closes: #677164) ++ * linux-image, README.Debian: Suggest debian-kernel-handbook package ++ ++ [ Arnaud Patard ] ++ * [armel, armhf] backport BPF JIT support ++ ++ -- Ben Hutchings Tue, 26 Jun 2012 01:56:42 +0100 ++ ++linux (3.2.21-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.21 ++ - NFSv4.1: Fix a request leak on the back channel ++ - target: Return error to initiator if SET TARGET PORT GROUPS emulation ++ fails ++ - USB: add NO_D3_DURING_SLEEP flag and revert 151b61284776be2 ++ - USB: fix gathering of interface associations ++ ++ [ Ben Hutchings ] ++ * [ia64,powerpc] udeb: Add crc-itu-t to crc-modules; make ++ firewire-core-modules depend on it (fixes FTBFS) ++ * [arm,m68k,sh4] udeb: Build ipv6-modules ++ * ethtool: allow ETHTOOL_GSSET_INFO for users ++ * [rt] bump version to 3.2.20-rt32 ++ * cpu: Convert 'cpu' and 'machinecheck' sysdev_class to a regular subsystem ++ * [x86] Add driver auto probing for x86 features ++ - crypto: Add support for x86 cpuid auto loading for x86 crypto drivers ++ (Closes: #568008) ++ - intel-idle: convert to x86_cpu_id auto probing ++ - HWMON: Convert coretemp to x86 cpuid autoprobing ++ - HWMON: Convert via-cputemp to x86 cpuid autoprobing ++ - cpufreq: Add support for x86 cpuinfo auto loading (Closes: #664813) ++ * [x86] ACPI: Load acpi-cpufreq from processor driver automatically ++ * Bump ABI to 3 ++ * input: Add Synaptics USB device driver (Closes: #678071) ++ * [x86] udeb: Fix dependencies for nic-wireless-modules ++ ++ [ Aurelien Jarno ] ++ * [mips,mipsel] udeb: Remove rivafb and nvidiafb. ++ * [ppc64]: add udebs, based on powerpc/powerpc64. ++ ++ [ Bastian Blank ] ++ * Support build-arch and build-indep make targets. ++ ++ [ Arnaud Patard ] ++ * [armel/kirkwood] Add dreamplug and iconnect support (Closes: #675922) ++ ++ -- Ben Hutchings Fri, 22 Jun 2012 13:54:15 +0100 ++ ++linux (3.2.20-1) unstable; urgency=low ++ ++ * The "Confused? You Won't Be" release ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.20 ++ - cifs: fix oops while traversing open file list (try #4) ++ - mm/fork: fix overflow in vma length when copying mmap on clone ++ - mm: fix faulty initialization in vmalloc_init() ++ - x86, amd, xen: Avoid NULL pointer paravirt references ++ - ext4: force ro mount if ext4_setup_super() fails ++ - ext4: disallow hard-linked directory in ext4_lookup ++ - ext4: add missing save_error_info() to ext4_error() ++ - ALSA: usb-audio: fix rate_list memory leak ++ - Bluetooth: btusb: typo in Broadcom SoftSailing id (Closes: #674565) ++ - ipv4: Do not use dead fib_info entries. ++ - ipv4: fix the rcu race between free_fib_info and ip_route_output_slow ++ - l2tp: fix oops in L2TP IP sockets for connect() AF_UNSPEC case ++ - btree: fix tree corruption in btree_get_prev() ++ - asix: allow full size 8021Q frames to be received (Closes: #676545) ++ - ext4: don't trash state flags in EXT4_IOC_SETFLAGS ++ - ext4: fix the free blocks calculation for ext3 file systems w/ uninit_bg ++ ++ [ Ben Hutchings ] ++ * Rename source package to 'linux' (Closes: #636010) ++ * Convert source package format to 3.0 (quilt) ++ - Convert patch system to quilt, except for the 'orig' patch series ++ - Use xz compression for upstream and Debian tarballs ++ - README.source: Update description of patch system to match current ++ usage ++ - linux-patch-debian: Remove; it is no longer necessary for GPL ++ compliance and does not work with our current patch management ++ * linux-image: Change package name for bugs to 'src:linux' (Closes: #644198) ++ * DFSG: video: Remove nvidiafb and rivafb, which include apparently ++ obfuscated code (Closes: #383481, #609615). The nouveau driver supports ++ all the same hardware, aside from RIVA 128 (NV3). ++ * udeb: Add udf-modules containing UDF filesystem module (Closes: #613972) ++ * [mipsel/loongson2f] linux-image: Recommend libc6-loongson2f ++ (Closes: #629410) ++ * Build-Depend on kmod or module-init-tools, not just the latter ++ * test-patches: Recognise the rt featureset automatically ++ * udeb: Build-Depend on kernel-wedge >= 2.84; this allows us to list ++ modules as required even if they are built-in in some configurations ++ * filter: Allow to create sk-unattached filters ++ * proc: Backport hidepid mount option from Linux 3.4 (Closes: #669028) ++ * NFSv4: Reduce the footprint of the idmapper (Closes: #657078) ++ * [i386] thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE ++ (Closes: #676360) ++ * linux-source: Add single patch for each featureset ++ * [x86] Enable CRASH_DUMP, PROC_VMCORE (Closes: #623177) ++ * media/dvb: Enable DVB_DDBRIDGE as module (Closes: #676952) ++ * net: sock: validate data_len before allocating skb in ++ sock_alloc_send_pskb() (CVE-2012-2136) ++ * macvtap: zerocopy: fix offset calculation when building skb ++ * macvtap: zerocopy: fix truesize underestimation ++ * macvtap: zerocopy: put page when fail to get all requested user pages ++ * macvtap: zerocopy: set SKBTX_DEV_ZEROCOPY only when skb is built ++ successfully ++ * macvtap: zerocopy: validate vectors before building skb (CVE-2012-2119) ++ * KVM: Fix buffer overflow in kvm_set_irq() (CVE-2012-2137) ++ ++ [ Bastian Blank ] ++ * [s390/s390x,s390x/s390x] Build debugging symbols. ++ ++ -- Ben Hutchings Mon, 11 Jun 2012 02:46:34 +0100 ++ ++linux-2.6 (3.2.19-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.19 ++ - hpsa: Fix problem with MSA2xxx devices (Closes: #661057) ++ - IB/core: Fix mismatch between locked and pinned pages ++ - iommu: Fix off by one in dmar_get_fault_reason() ++ - vfs: make AIO use the proper rw_verify_area() area helpers ++ - HID: logitech: read all 32 bits of report type bitfield (Closes: #671292) ++ - USB: Remove races in devio.c ++ - ext{3,4}: Fix error handling on inode bitmap corruption ++ - uvcvideo: Fix ENUMINPUT handling ++ - dl2k: Clean up rio_ioctl (CVE-2012-2313) ++ - [x86] MCE: Fix vm86 handling for 32bit mce handler ++ - [x86] mce: Fix check for processor context when machine check was taken. ++ - ethtool: Null-terminate filename passed to ethtool_ops::flash_device ++ - NFSv4: Fix buffer overflows in ACL support (CVE-2012-2375) ++ + Avoid reading past buffer when calling GETACL ++ + Avoid beyond bounds copy while caching ACL ++ ++ [ Ben Hutchings ] ++ * be2net: Backport most changes up to Linux 3.5-rc1, thanks to ++ Sarveshwar Bandi (Closes: #673391) ++ - Add support for Skyhawk cards ++ * net/sched: Add codel and fq_codel from Linux 3.5-rc1 ++ * [x86] udeb: Add hyperv-modules containing Hyper-V paravirtualised drivers ++ * [x86] ata_piix: defer disks to the Hyper-V drivers by default ++ * [x86] drm/i915:: Disable FBC on SandyBridge (Closes: #675022) ++ * AppArmor: compatibility patch for v5 interface (Closes: #661151) ++ * hugepages: fix use after free bug in "quota" handling (CVE-2012-2133) ++ * [x86] mm: pmd_read_atomic: fix 32bit PAE pmd walk vs pmd_populate SMP race ++ condition (CVE-2012-2373) ++ * hugetlb: fix resv_map leak in error path (CVE-2012-2390) ++ * [SCSI] fix scsi_wait_scan (Closes: #647436) ++ ++ -- Ben Hutchings Fri, 01 Jun 2012 13:15:48 +0100 ++ ++linux-2.6 (3.2.18-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.18 ++ - hugetlb: prevent BUG_ON in hugetlb_fault() -> hugetlb_cow() ++ - net: l2tp: unlock socket lock before returning from l2tp_ip_sendmsg ++ - [sparc] sparc64: Do not clobber %g2 in xcall_fetch_glob_regs(). ++ - ext4: avoid deadlock on sync-mounted FS w/o journal ++ - brcm80211: smac: fix endless retry of A-MPDU transmissions ++ (Closes: #672891) ++ - target: Fix SPC-2 RELEASE bug for multi-session iSCSI client setups ++ - ALSA: hda/idt - Fix power-map for speaker-pins with some HP laptops ++ (Closes: #672582) ++ - usbnet: fix skb traversing races during unlink(v2) ++ - [arm] prevent VM_GROWSDOWN mmaps extending below FIRST_USER_ADDRESS ++ ++ [ Jonathan Nieder ] ++ * wacom: Add support for various tablet models (Closes: #671801) ++ * rt2800usb: Add support for Ralink RT5392/RF5372 chipset (Closes: #673186) ++ ++ [ Ben Hutchings ] ++ * test-patches: Fix -j option, broken since 3.1.0-1~experimental.1 ++ * rt2800usb: Re-enable powersaving by default, as it should work better ++ than in 2.6.38 ++ * [sparc,sparc64] Build virtio-modules-udeb for use in qemu (Closes: #673320) ++ * KVM: mmu_notifier: Flush TLBs before releasing mmu_lock ++ * [x86] KVM: nVMX: Fix erroneous exception bitmap check ++ * [x86] KVM: VMX: vmx_set_cr0 expects kvm->srcu locked ++ * [s390] KVM: do store status after handling STOP_ON_STOP bit ++ * [s390] KVM: Sanitize fpc registers for KVM_SET_FPU ++ * ACPI battery: only refresh the sysfs files when pertinent information ++ changes (Closes: #670958) ++ ++ -- Ben Hutchings Mon, 21 May 2012 04:07:08 +0100 ++ ++linux-2.6 (3.2.17-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.17 ++ - md: fix possible corruption of array metadata on shutdown. ++ - ext4: fix endianness breakage in ext4_split_extent_at() ++ - KVM: unmap pages from the iommu when slots are removed (CVE-2012-2121) ++ - btrfs: btrfs_root_readonly() broken on big-endian ++ - ocfs2: Fix various bugs affecting big-endian architectures ++ - lockd: fix the endianness bug ++ - phonet: Check input from user before allocating ++ - netlink: fix races after skb queueing ++ - net: fix a race in sock_queue_err_skb() ++ - net/ethernet: ks8851_mll fix rx frame buffer overflow ++ - x86, apic: APIC code touches invalid MSR on P5 class machines ++ - drm/i915: fix integer overflow in i915_gem_execbuffer2() ++ - drm/i915: fix integer overflow in i915_gem_do_execbuffer() ++ - USB: cdc-wdm: fix race leading leading to memory corruption ++ - autofs: make the autofsv5 packet file descriptor use a packetized pipe ++ (Closes: #633423) ++ - efi: Validate UEFI boot variables ++ - efivars: Improve variable validation ++ - fs/cifs: fix parsing of dfs referrals ++ - hfsplus: Fix potential buffer overflows (CVE-2012-2319) ++ - exit_signal: fix the "parent has changed security domain" logic ++ ++ [ Ben Hutchings ] ++ * aufs: Enable AUFS_EXPORT ++ * ext4: Report max_batch_time option correctly (Closes: #654206) ++ * [i386/rt-686-pae] Enable HIGHMEM64G as intended for this configuration ++ * NFSv4: Revalidate uid/gid after open (Closes: #659111) ++ * sky2: propogate rx hash when packet is copied ++ * sky2: fix receive length error in mixed non-VLAN/VLAN traffic ++ (Closes: #492853) ++ * KVM: Ensure all vcpus are consistent with in-kernel irqchip settings ++ (CVE-2012-1601) ++ * KVM: lock slots_lock around device assignment (CVE-2012-2121) ++ * [rt] bump version to 3.2.16-rt27 ++ ++ [ Bastian Blank ] ++ * [s390] Enable IUCV special message support. (closes: #671238) ++ ++ [ Arnaud Patard ] ++ * [armhf] Add vexpress support from Vagrant Cascadian with a slightly ++ modified kernel configuration (Closes: #670462) ++ * [armel] Introduce a new udeb module for leds and use it on kirkwoord ++ kernel thanks to Simon Guinot (Closes: #671200) ++ ++ -- Ben Hutchings Sat, 12 May 2012 15:29:09 +0100 ++ ++linux-2.6 (3.2.16-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.16 ++ - drm/i915: properly compute dp dithering for user-created modes ++ (Closes: #666360) ++ - md/bitmap: prevent bitmap_daemon_work running while initialising bitmap ++ - [ia64] Fix futex_atomic_cmpxchg_inatomic() (Closes: #659485) ++ - USB: serial: fix race between probe and open ++ - fcaps: clear the same personality flags as suid when fcaps are used ++ (CVE-2012-2123) ++ - ACPICA: Fix to allow region arguments to reference other scopes ++ (Closes: #661581) ++ - futex: Do not leak robust list to unprivileged process ++ - drm/radeon/kms: fix the regression of DVI connector check ++ (Closes: #670047) ++ ++ [ Ben Hutchings ] ++ * rt2x00: Identify rt2800usb chipsets. (Closes: #658067) ++ * [x86] Add EFI boot stub support (Closes: #669033) ++ * brcmsmac: "INTERMEDIATE but not AMPDU" only when tracing ++ * NFSv4: Fix error handling and improve error reporting for file locking ++ (Closes: #669270) ++ - Rate limit the state manager for lock reclaim warning messages ++ - Ensure that the LOCK code sets exception->inode ++ - Ensure that we check lock exclusive/shared type against open modes ++ * [x86] i915: Fix integer overflows in i915_gem_{do_execbuffer,execbuffer2} ++ * Revert "autofs: work around unhappy compat problem on x86-64". ++ Reopens #633423. ++ ++ -- Ben Hutchings Sun, 29 Apr 2012 08:00:53 +0100 ++ ++linux-2.6 (3.2.15-1) unstable; urgency=high ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.15 ++ - drm/radeon/kms: fix fans after resume (Closes: #596741) ++ - sysctl: fix write access to dmesg_restrict/kptr_restrict ++ - [x86] PCI: use host bridge _CRS info on MSI MS-7253 (Closes: #619034) ++ - nfs: Fix length of buffer copied in __nfs4_get_acl_uncached ++ - [x86] ioat: fix size of 'completion' for Xen (Closes: #660554) ++ - cred: copy_process() should clear child->replacement_session_keyring ++ ++ [ Ben Hutchings ] ++ * net: fix /proc/net/dev regression (Closes: #659499) ++ * [armel/orion5x] Fix GPIO enable bits for MPP9 (Closes: #667446) ++ * [x86] drm/i915: mask transcoder select bits before setting them on LVDS ++ * [armhf/mx5,mipsel/loongson-2f] input: Enable INPUT_TOUCHSCREEN ++ (Closes: #668036) ++ * [x86] hv: Update all Hyper-V drivers to 3.4-rc1 (Closes: #661318) ++ * hugetlb: fix race condition in hugetlb_fault() ++ ++ -- Ben Hutchings Sat, 14 Apr 2012 18:23:44 +0100 ++ ++linux-2.6 (3.2.14-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.14 ++ - mm: thp: fix pmd_bad() triggering in code paths holding mmap_sem ++ read mode (CVE-2012-1179) ++ - hugetlbfs: avoid taking i_mutex from hugetlbfs_read() ++ - md/bitmap: ensure to load bitmap when creating via sysfs ++ (Closes: #661558) ++ - md: dont set md arrays to readonly on shutdown ++ - md/raid1,raid10: avoid deadlock during resync/recovery (Closes: #584881) ++ - md: fix clearing of the changed flags for the bad blocks list ++ - xfs: fix inode lookup race ++ - sysctl: protect poll() in entries that may go away ++ - NFSv4: Rate limit the state manager warning messages (Closes: #666121) ++ - jbd2: clear BH_Delay & BH_Unwritten in journal_unmap_buffer ++ - ext4: ignore EXT4_INODE_JOURNAL_DATA flag with delalloc ++ - ext4: fix race between sync and completed io work ++ - ext4: check for zero length extent ++ - vfs: fix d_ancestor() case in d_materialize_unique ++ - udf: Fix deadlock in udf_release_file() ++ - dm crypt: add missing error handling ++ - dm thin: fix stacked bi_next usage ++ - xfs: Fix oops on IO error during xlog_recover_process_iunlinks() ++ - NFSv4: Fix two infinite loops in the mount code ++ - drm/i915: suspend fbdev device around suspend/hibernate ++ (Closes: #645547) ++ - net: fix a potential rcu_read_lock() imbalance in rt6_fill_node() ++ - [x86] tls: Off by one limit check ++ - PCI: ASPM: Fix pcie devices with non-pcie children (Closes: #665420) ++ ++ [ Jonathan Nieder ] ++ * ata: Enable PATA_IT8213 as module (Closes: #666506) ++ ++ -- Ben Hutchings Thu, 05 Apr 2012 05:02:45 +0100 ++ ++linux-2.6 (3.2.13-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.13 ++ ++ [ Ben Hutchings ] ++ * kbuild: do not check for ancient modutils tools ++ ++ [ Uwe Kleine-König ] ++ * [rt] bump version to 3.2.12-rt22 ++ ++ [ Bastian Blank ] ++ * [s390x] Ignore ABI change. ++ ++ -- Bastian Blank Wed, 28 Mar 2012 13:40:26 +0200 ++ ++linux-2.6 (3.2.12-1) unstable; urgency=high ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.11 ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.12 ++ - aio: fix io_setup/io_destroy race ++ - aio: fix the "too late munmap()" race ++ - vfs: fix double put after complete_walk() ++ - acer-wmi: No wifi rfkill on Lenovo machines (Closes: #655941) ++ - tcp: fix false reordering signal in tcp_shifted_skb ++ - r8169: corrupted IP fragments fix for large mtu ++ - tcp: don't fragment SACKed skbs in tcp_mark_head_lost() ++ - tcp: fix tcp_shift_skb_data() to not shift SACKed data below snd_una ++ - block: Fix NULL pointer dereference in sd_revalidate_disk ++ (Closes: #649735) ++ - block: fix __blkdev_get and add_disk race condition ++ ++ [ Ben Hutchings ] ++ * [powerpc] Enable KVM_GUEST ++ * [s390] Ignore arch_pick_mmap_layout version change; it should not be ++ needed by modules (fixes FTBFS) ++ * [x86] Disable POHMELFS; this version is obsolete ++ * epoll: Don't limit non-nested epoll paths ++ * CIFS: Fix a spurious error in cifs_push_posix_locks ++ * [rt] bump rt patch to version 3.2.11-rt20 ++ * aufs: Update to aufs3.2-20120312 ++ * tcp: fix syncookie regression ++ * ipv6: Don't dev_hold(dev) in ip6_mc_find_dev_rcu ++ ++ [ Jonathan Nieder ] ++ * [x86] Enable RTS5139 as module (Closes: #663912) ++ ++ -- Ben Hutchings Tue, 20 Mar 2012 04:32:51 +0000 ++ ++linux-2.6 (3.2.10-1) unstable; urgency=high ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.10 ++ - regset: Prevent null pointer reference on readonly regsets ++ (CVE-2012-1097) ++ ++ [ Uwe Kleine-König ] ++ * [rt] bump rt patch to version 3.2.9-rt17 ++ * [rt] fix conflict between the security restrictions on links introduced in ++ 3.2.9-1 and rt (Closes: #663269) ++ ++ [ Aurelien Jarno ] ++ * [mips,mipsel] Mark ext4-modules as provided by the kernel-image udeb, remove ++ ide-core-modules provide. ++ ++ [ Ben Hutchings ] ++ * [x86,ia64] PCI/hotplug: Build-in common hotplug drivers: ++ - Change HOTPLUG_PCI, HOTPLUG_PCI_PCIE to built-in ++ - [x86] Change HOTPLUG_PCI_ACPI to built-in (Closes: #663433) ++ - [ia64] Enable HOTPLUG_PCI_SGI as built-in ++ * linux-headers: Remove unused, broken symlinks to Kbuild (Closes: #663597) ++ * udeb: Remove dependency of {pcmcia,usb}-storage-modules on ide-core-modules ++ * [mips,mipsel] Mark ata-modules as provided by the kernel-image udeb ++ for most flavours ++ ++ -- Bastian Blank Tue, 13 Mar 2012 17:19:32 +0100 ++ ++linux-2.6 (3.2.9-1) unstable; urgency=high ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.8 ++ - [i386] i387: move TS_USEDFPU flag from thread_info to task_struct ++ - [x86] additional refactoring of FPU/SSE state save and restore ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.9 ++ - vfs: fix d_inode_lookup() dentry ref leak ++ - target: Allow control CDBs with data > 1 page ++ - epoll: introduce POLLFREE to flush ->signalfd_wqh before kfree() ++ - epoll: ep_unregister_pollwait() can use the freed pwq->whead ++ - epoll: limit paths (CVE-2011-1083) ++ - cdrom: use copy_to_user() without the underscores ++ ++ [ Bastian Blank ] ++ * [mips,mipsel] Also remove ext4 modules from installer. ++ ++ [ Ben Hutchings ] ++ * Update debconf template translations: ++ - Update Dutch (Willem Kuyn) (Closes: #658736) ++ - Add Polish (MichaÅ‚ KuÅ‚ach) (Closes: #658912) ++ * Bump ABI to 2 ++ * fs: Introduce and enable security restrictions on links: ++ - Do not follow symlinks in /tmp that are owned by other users ++ (sysctl: fs.protected_symlinks) ++ - Do not allow unprivileged users to create hard links to sensitive files ++ (sysctl: fs.protected_hardlinks) (Closes: #609455) ++ + This breaks the 'at' package in stable, which will be fixed shortly ++ (see #597130) ++ The precise restrictions are specified in Documentation/sysctl/fs.txt in ++ the linux-doc-3.2 and linux-source-3.2 packages. ++ * iwlwifi: fix key removal (Closes: #651199) ++ * cgroups: Set CGROUP_PERF ++ * hid: Enable HID_HOLTEK, HID_PRIMAX, HID_SPEEDLINK, HID_WIIMOTE as modules, ++ HID_ACRUX_FF ++ * media/rc: Enable RC_ATI_REMOTE as module ++ * gspca: Enable USB_GSPCA_TOPRO as module ++ * dvb-usb: Enable DVB_USB_PCTV452E, DVB_USB_MXL111SF as modules ++ ++ [ Uwe Kleine-König ] ++ * [x86] Update rt featureset to 3.2.9-rt15 ++ ++ -- Ben Hutchings Sun, 04 Mar 2012 15:32:20 +0000 ++ ++linux-2.6 (3.2.7-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.7 ++ ++ [ Ben Hutchings ] ++ * Add Turkish debconf template translations (Mert Dirik) (Closes: #660117) ++ * [amd64] Disable BLK_DEV_IDEPNP, BLK_DEV_OPTI621, IDE_GENERIC ++ * Use libata-based drivers for most of the remaining PATA controllers: ++ - pata_legacy replaces ide-generic ++ - pata_isapnp replaces ide-pnp ++ - pata_opti replaces opti621 ++ - pata_hpt366 and pata_hpt37x replace hpt366 ++ - pata_ninja32 replaces delkin_cb ++ - pata_cs5535 replaces cs5535 ++ - pata_winbond replaces sl82c105 ++ - [alpha] pata_cypress replaces cy82c693 ++ - [hppa] pata_ns87415 replaces ns87415 ++ - [sparc] Various replacements, as for x86 in 2.6.32-10 ++ * Disable old IDE subsystem [!ia64,m68k]: ++ - Disable BLK_DEV_IT8172, BLK_DEV_IT8213, BLK_DEV_TC86C001, BLK_DEV_TRM290 ++ - [alpha] Disable BLK_DEV_4DRIVES, BLK_DEV_ALI14XX, BLK_DEV_DTC2278, ++ BLK_DEV_HT6560B, BLK_DEV_QD65XX, BLK_DEV_UMC8672 ++ * fs: Enable EFI_PARTITION in all configurations (Closes: #660582) ++ * [i386] Re-enable INTEL_IOMMU, IRQ_REMAP ++ * [mips/r5k-ip32] Enable INPUT_SGI_BTNS (previously INPUT_SGIO2_BTNS) ++ * [powerpc/powerpc64] Enable IBM_EMAC (previously IBM_NEW_EMAC) ++ * [x86] drm/i915: do not enable RC6p on Sandy Bridge (Closes: #660265) ++ * ipsec: be careful of non existing mac headers (Closes: #660804) ++ * version: Use maintainer rather than uploader address for official ++ binary packages ++ ++ [ Bastian Blank ] ++ * Don't advertise Xen support for rt images. (closes: #659988) ++ * [m68k,mips,mipsel] Use ext4 for all ext-variants. (closes: #660446) ++ * [m68k,mips,mipsel] Don't built-in ramdisk support. ++ * [hppa,mips,mipsel] Don't built-in cramfs support. ++ * [alpha,hppa] Don't built-in ext2. ++ * Remove IDE trigger for LED support. ++ * Remove all framebuffer bootup logos. ++ * NFSv4: Fix an Oops in the NFSv4 getacl code. ++ ++ -- Bastian Blank Tue, 28 Feb 2012 16:00:41 +0100 ++ ++linux-2.6 (3.2.6-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.5 ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.6 ++ - ALSA: hda - Apply 0x0f-VREF fix to all ASUS laptops with ALC861/660 ++ (Closes: #657302) ++ - [armhf] vfp: flush thread hwstate before restoring context from sigframe ++ - proc: mem_release() should check mm != NULL ++ - proc: make sure mem_open() doesnt pin the targets memory ++ - [arm] sched/rt: Fix task stack corruption under ++ __ARCH_WANT_INTERRUPTS_ON_CTXSW ++ - eCryptfs: Infinite loop due to overflow in ecryptfs_write() ++ - iscsi-target: Fix reject release handling in iscsit_free_cmd() ++ - iscsi-target: Fix double list_add with iscsit_alloc_buffs reject ++ - pcmcia: fix socket refcount decrementing on each resume ++ ++ [ Aurelien Jarno ] ++ * hwmon: backport IT8728F support for linux 3.3. ++ ++ [ Uwe Kleine-König ] ++ * [amd64] Update rt featureset to 3.2.5-rt12 ++ * [i386] enable rt featureset for 686-pae ++ ++ [ Arnaud Patard ] ++ * Merge ixp4xx oops fix when probing mtd. ++ ++ [ Ben Hutchings ] ++ * Change linux-image dependencies to allow kmod as an alternative to ++ module-init-tools ++ * relay: prevent integer overflow in relay_open() ++ * builddeb: Don't create files in /tmp with predictable names ++ * ath9k: fix a WEP crypto related regression (Closes: #659484) ++ ++ -- Ben Hutchings Thu, 16 Feb 2012 02:38:38 +0000 ++ ++linux-2.6 (3.2.4-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.3 ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.4 ++ - eCryptfs: Sanitize write counts of /dev/ecryptfs ++ - eCryptfs: Make truncate path killable ++ - eCryptfs: Check inode changes in setattr ++ - drm/i915: paper over missed irq issues with force wake voodoo ++ - tpm_tis: add delay after aborting command (Closes: #649033) ++ - USB: ftdi_sio: fix initial baud rate (Closes: #658164) ++ - USB: Realtek cr: fix autopm scheduling while atomic (Closes: #656724) ++ ++ [ Ben Hutchings ] ++ * [armel] Add mv78xx0 flavour; thanks to Steve McIntyre for the config ++ * net: Disable FIXED_PHY; this driver only causes trouble ++ * PCI: Rework ASPM disable code (fixes power usage regression on some ++ systems) ++ ++ [ Bastian Blank ] ++ * Remove unneeded scmversion workaround. ++ ++ -- Bastian Blank Sun, 05 Feb 2012 15:42:21 +0100 ++ ++linux-2.6 (3.2.2-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.2 ++ - ext4: fix undefined behavior in ext4_fill_flex_info() (CVE-2009-4307) ++ - Unused iocbs in a batch should not be accounted as active (CVE-2012-0058) ++ - uvcvideo: Fix integer overflow in uvc_ioctl_ctrl_map() ++ - [arm] proc: clear_refs: do not clear reserved pages ++ ++ [ Ben Hutchings ] ++ * Clean up linux-image maintainer scripts: ++ - Stop changing 'build' and 'source' symlinks; these now belong to the ++ linux-headers packages ++ - Remove unused configuration variables ++ - prerm: Remove last vestige of /usr/doc transition ++ - postrm: Remove modules.*.bin; currently modules.builtin.bin is left ++ behind ++ * [alpha] Build with gcc-4.5 (Closes: #657112) ++ * aufs: Update to aufs3.2-20120109 (fixes FTBFS on m68k) ++ * [m68k] Fix assembler constraint to prevent overeager gcc optimisation ++ * sdhci-pci: Include driver in installer ++ * [armel] udeb: Do not attempt to build lzo-modules udeb as lzo_compress ++ is now built-in (fixes FTBFS) ++ * [armhf] udeb: Include rt2800usb in nic-modules, replacing rt2870sta ++ which was removed from the kernel ++ * drm: Fix authentication kernel crash ++ * xfs: Fix missing xfs_iunlock() on error recovery path in xfs_readlink() ++ * jbd: Issue cache flush after checkpointing ++ * crypto: sha512 - make it work, undo percpu message schedule ++ - crypto: sha512 - reduce stack usage to safe number ++ * [x86] xen: size struct xen_spinlock to always fit in arch_spinlock_t ++ * l2tp: l2tp_ip - fix possible oops on packet receive ++ * macvlan: fix a possible use after free ++ * tcp: fix tcp_trim_head() to adjust segment count with skb MSS ++ * [x86] KVM: fix missing checks in syscall emulation (CVE-2012-0045) ++ ++ [ Thorsten Glaser ] ++ * [m68k] Use gcc-4.6 like (almost) all other architectures ++ * Pass the cflags define as CFLAGS_KERNEL and CFLAGS_MODULE to kbuild ++ * [m68k] Use cflags -ffreestanding (Closes: #648996) ++ ++ [ Aurelien Jarno ] ++ * [mips,octeon] Disabled CONFIG_FIXED_PHY as it conflicts with the octeon ++ phy driver. ++ ++ -- Ben Hutchings Wed, 01 Feb 2012 01:44:05 +0000 ++ ++linux-2.6 (3.2.1-2) unstable; urgency=high ++ ++ [ Stefan Lippers-Hollmann ] ++ * udeb: Add missing modules to nic-wireless-modules: ++ - lib80211 encryption algorithms (lib80211_crypt_{wep,ccmptkip}) ++ needed for e.g. ipw2x00 wlan modules (Closes: #636259) ++ - ath9k_htc, carl9170 and rt2800{pci,usb} drivers ++ (Closes: #636321, #636353, #636385) ++ ++ [ Ben Hutchings ] ++ * Update Vcs-Browser URL for the switch to ViewVC ++ * Point Vcs-{Svn,Browser} at trunk branch, since the sid branch does ++ not always exist ++ * Build linux-libc-dev without multiarch if dpkg does not support it, ++ to support backports ++ * proc: clean up and fix /proc//mem handling (CVE-2012-0056) ++ ++ [ Aurelien Jarno ] ++ * [x86] Backport KVM nested VMX fixes from 3.3 to fix warnings and ++ crashes of L1 guests. ++ ++ -- Ben Hutchings Mon, 23 Jan 2012 15:10:04 +0000 ++ ++linux-2.6 (3.2.1-1) unstable; urgency=low ++ ++ * New upstream release: http://kernelnewbies.org/Linux_3.2 ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.1 ++ ++ [ Aurelien Jarno ] ++ * [arm, mips, mipsel, sh4] Add a virtio-modules udeb on flavours which ++ can be emulated by QEMU. ++ ++ [ Ben Hutchings ] ++ * media/dvb: Enable DVB_USB_IT913X as module (Closes: #653776) ++ * [arm] Remove use of possibly undefined BUILD_BUG_ON in ++ (fixes FTBFS) ++ * Install /lib/modules//modules.builtin in linux-image ++ packages ++ * [ia64] Add accept4() syscall (Closes: #647825) ++ * [x86] staging: Enable STAGING_MEDIA, which various drivers now depend on ++ (Closes: #654800) ++ * [um,m68k] Register a generic CPU device (fixes regression introduced by ++ the fix for #649216) ++ * [alpha] add io{read,write}{16,32}be functions, thanks to Michael Cree ++ * net: reintroduce missing rcu_assign_pointer() calls ++ * Input: ALPS - add support for protocol versions 3 and 4 ++ (Closes: #618422, #648207) ++ * [powerpc/powerpc64] udeb: Drop zlib-modules; ZLIB_DEFLATE is built-in ++ * [amd64] iommu: Enable INTEL_IOMMU, INTEL_IOMMU_FLOPPY_WA, IRQ_REMAP ++ * [amd64] cpufreq: Enable X86_P4_CLOCKMOD (Closes: #656328) ++ * Refresh list of related firmware packages for bug script ++ ++ [ Bastian Blank ] ++ * [amd64] crypt: Enable some amd64 only ciphers. ++ * Packaging updates: ++ - Use unicode. ++ - Cleanup config handling. ++ - Remove support for plain-xen image type. ++ - Allow disabling debug infos for unreleased builds. ++ ++ [ Arnaud Patard ] ++ * [armel] disable tomoyo and apparmor to allow kernel image to fit into flash. ++ * [armel] add back ixp4xx gpiolib patch ++ * [arm] backport topdown mmap support from rmk's tree ++ * [armel] Enable support from LaCIE kirkwood devices, thanks to Simon Guinot ++ (Closes: #655344) ++ * [armel] Backport 88f6282 A1 support ++ ++ [ Jurij Smakov ] ++ * [sparc] Add mpt2sas to scsi-common-modules udeb on sparc and sparc64, ++ needed by Niagara T3 machines. ++ ++ -- Ben Hutchings Wed, 18 Jan 2012 16:14:12 +0000 ++ ++linux-2.6 (3.2~rc7-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ - [powerpc] pasemi_mac: Fix building as module ++ - [x86] mpparse: Account for bus types other than ISA and PCI ++ (Closes: #586494) ++ - EHCI : Fix a regression in the ISO scheduler (Closes: #651382) ++ - [arm] setup: initialize arm_dma_zone_size earlier (Closes: #651215) ++ ++ [ Ben Hutchings ] ++ * [x86] et131x: Include driver in installer (Closes: #651440) ++ * security: Enable APPARMOR (Closes: #598408) ++ ++ [ Uwe Kleine-König ] ++ * [amd64] Update rt featureset to 3.2-rc5-rt8 ++ ++ [ Bastian Blank ] ++ * Use xz compression for all packages. ++ ++ -- Bastian Blank Wed, 28 Dec 2011 14:55:38 +0100 ++ ++linux-2.6 (3.2~rc4-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ Ben Hutchings ] ++ * aufs: Update to aufs3.x-rcN-20111114 ++ * ieee802154: Enable IEEE802154_6LOWPAN as module ++ * can: Enable CAN_GW, CAN_EMS_PCMCIA, CAN_PEAK_PCI as modules ++ * nfc: enable NFC_NCI as module ++ * scsi: Enable MVUMI as module ++ * dm: Enable DM_THIN_PROVISIONING as module ++ * b43: Enable B43_PHY_HT ++ * [ia64,powerpc,sparc,x86] wireless: Enable MWIFIEX_PCIE as module ++ * udeb: Update configuration for 3.2: ++ - Provide the default configuration instead of including it from the ++ kernel-wedge package ++ - iwlagn is renamed to iwlwifi ++ - blowfish is renamed to blowfish_generic ++ ++ [ Uwe Kleine-König ] ++ * [amd64] reenable rt featureset with 3.2-rc4-rt5 ++ ++ -- Ben Hutchings Sat, 03 Dec 2011 23:07:41 +0000 ++ ++linux-2.6 (3.1.8-2) unstable; urgency=high ++ ++ * igmp: Avoid zero delay when receiving odd mixture of IGMP queries ++ (Closes: #654876) (CVE-2012-0207) ++ ++ -- Ben Hutchings Tue, 10 Jan 2012 00:14:39 +0000 ++ ++linux-2.6 (3.1.8-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.1.7 ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.1.8 ++ - Revert "clockevents: Set noop handler in clockevents_exchange_device()", ++ included in stable update 3.1.5 (Closes: #653398) ++ - cfq-iosched: fix cfq_cic_link() race condition ++ - binary_sysctl(): fix memory leak ++ - cgroups: fix a css_set not found bug in cgroup_attach_proc ++ - iwlwifi: allow to switch to HT40 if not associated (Closes: #653423) ++ - futex: Fix uninterruptible loop due to gate_area ++ - drm/radeon/kms: bail on BTC parts if MC ucode is missing ++ - [sparc] sparc64: Fix masking and shifting in VIS fpcmp emulation. ++ - llc: llc_cmsg_rcv was getting called after sk_eat_skb. ++ - ipv4: reintroduce route cache garbage collector ++ - Revert "rtc: Disable the alarm in the hardware" (Closes: #652869) ++ ++ [ Ben Hutchings ] ++ * snapshot: Implement compat_ioctl (Closes: #502816) ++ * drm/radeon: flush read cache for gtt with fence on r6xx and newer GPU ++ (Closes: #646376) ++ * rtc: Fix alarm rollover when day or month is out-of-range (Closes: #646429) ++ * l2tp: ensure sk->dst is still valid (Closes: #652503) ++ * Update Russian debconf template translations (Yuri Kozlov) ++ (Closes: #653716) ++ * v4l2-ioctl: integer overflow in video_usercopy() ++ * Restrict ioctl forwarding on partitions and logical volumes (CVE-2011-4127) ++ * [x86] KVM: Prevent starting PIT timers in the absence of irqchip support ++ (CVE-2011-4622) ++ ++ [ Jonathan Nieder ] ++ * prerm: Print an error message when aborting removal of the running ++ kernel (Closes: #601962) ++ ++ [ Aurelien Jarno ] ++ * [sh4] Remove core-modules udeb as it is empty. ++ * [sh4/sh7751r] Disable CONFIG_RTS7751R2D_1. Support for this board ++ implies IRQless IDE, which causes data corruption. ++ ++ -- Ben Hutchings Sun, 08 Jan 2012 16:31:16 +0000 ++ ++linux-2.6 (3.1.6-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.1.6 ++ - staging: r8712u: Add new USB ID (Closes: #651622) ++ - [arm] setup: initialize arm_dma_zone_size earlier (Closes: #651215) ++ ++ [ Ben Hutchings ] ++ * [x86] Enable HYPERV, HYPERV_STORAGE, HYPERV_NET, HYPERV_UTILS, ++ HYPERV_MOUSE as modules (Closes: #652014) ++ * cciss: Add IRQF_SHARED back in for the non-MSI(X) interrupt handler ++ (Closes: #650119) ++ * udeb: Update configuration: ++ - Provide the default configuration instead of including it from the ++ kernel-wedge package ++ - [x86] Include et131x (Closes: #651440) ++ - [x86] Include isci (Closes: #652897) ++ ++ -- Bastian Blank Fri, 23 Dec 2011 17:02:26 +0100 ++ ++linux-2.6 (3.1.5-1) unstable; urgency=low ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.1.5 ++ - bridge: correct IPv6 checksum after pull (Closes: #651469) ++ - USB: EHCI: fix HUB TT scheduling issue with iso transfer ++ (Closes: #651015) ++ - [x86] mpparse: Account for bus types other than ISA and PCI ++ (Closes: #586494) ++ ++ [ Bastian Blank ] ++ * Fix generation of revisions for the patch list. ++ ++ [ Hector Oron ] ++ * regulator: backport fix for nullpointer dereference in core. ++ ++ [ Ben Hutchings ] ++ * [x86] Enable MEMTEST (Closes: #613321, #646361) ++ - If bad RAM is detected, WARN and recommend a more thorough test ++ * brcmsmac: Fix I/O functions for MIPS and for big-endian architectures ++ * [x86] Enable GPIO_PCH, GPIO_ML_IOH, I2C_EG20T, PCH_CAN, PCH_DMA, ++ PCH_GBE, PCH_PHUB, SERIAL_PCH_UART, SPI_TOPCLIFF_PCH, USB_GADGET, ++ USB_EG20T as modules ++ ++ -- Ben Hutchings Sun, 11 Dec 2011 05:28:40 +0000 ++ ++linux-2.6 (3.1.4-1) unstable; urgency=low ++ ++ * New upstream stable updates: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.1.2 ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.1.3 ++ - TTY: ldisc, wait for ldisc infinitely in hangup (Closes: #645071) ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.1.4 ++ ++ [ Martin Michlmayr ] ++ * [armel] Set the priority of pata-modules to standard since the ++ GLAN Tank uses PATA. ++ ++ [ Ben Hutchings ] ++ * Enable BCMA as module, BCMA_HOST_PCI and B43_BCMA (Closes: #649567) ++ but limit these to devices not supported by brcmsmac ++ * brcmsmac: Enable as module for all architectures ++ * Include module taint flags in bug reports ++ * lirc_serial: Fix various bugs that may result in a crash, deadlock or ++ other failure (Closes: #645811) ++ * amilo-rfkill: Use proper functions to write to the i8042 safely ++ * topology: Provide CPU topology in sysfs in !SMP configurations ++ (Closes: #649216) ++ ++ [ Bastian Blank ] ++ * Include generated headers. (closes: #650085) ++ ++ -- Bastian Blank Tue, 29 Nov 2011 14:14:14 +0100 ++ ++linux-2.6 (3.1.1-1) unstable; urgency=high ++ ++ * New upstream stable update: ++ http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.1.1 ++ ++ [ Aurelien Jarno ] ++ * [s390x] Add s390x udebs, based on linux-kernel-di-s390x-2.6. ++ * [sparc64] Sync udebs with sparc. ++ ++ [ Ben Hutchings ] ++ * [powerpc] Fix module selection for {ata,ide,scsi-core}-modules udebs ++ * [alpha] wire up accept4 syscall, thanks to Michael Cree ++ * iwlagn: fix modinfo display for 135 ucode (Closes: #647958) ++ * [powerpc] ptrace: Fix build with gcc 4.6 ++ * [arm] add io{read,write}{16,32}be functions (fixes FTBFS) ++ * cifs, freezer: add wait_event_freezekillable and have cifs use it ++ (Closes: #488794) ++ * [alpha] Remove old, broken udeb configuration (Closes: #647586) ++ * DFSG: Remove drivers/staging/ft1000/ft1000-*/*.img, non-free ++ firmware for drivers we don't build ++ * hfs: fix hfs_find_init() sb->ext_tree NULL ptr oops (CVE-2011-2203) ++ * vmscan: fix shrinker callback bug in fs/super.c ++ * block: Always check length of all iov entries in blk_rq_map_user_iov() ++ * [x86] Add amilo-rfkill driver for some Fujitsu-Siemens Amilo laptops ++ (Closes: #631664) ++ ++ [ Arnaud Patard ] ++ * [arm] add missing ioread/write be functions to ixp4xx to fix FTBFS ++ * [armhf] allow to build kernel image for iMX51 and iMX53 and enable some ++ iMX53 platforms. ++ * [armhf] add ahci for iMX53, pata for iMX51 ++ ++ -- Ben Hutchings Sun, 13 Nov 2011 20:08:09 +0000 ++ ++linux-2.6 (3.1.0-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release: http://kernelnewbies.org/Linux_3.1 ++ - drm/i915: FBC off for ironlake and older, otherwise on by default ++ (Closes: #641622) ++ - drm/radeon: Update AVIVO cursor coordinate origin before x/yorigin ++ calculation (Closes: #585130) ++ - crypto: ghash - Avoid null pointer dereference if no key is set ++ ++ [ Ben Hutchings ] ++ * [powerpc/powerpc64] Add missing #include to LPAR console selection fix ++ * Make kernel-wedge package checks non-fatal in experimental builds ++ * [x86/!486] Enable INTEL_IDLE ++ * aufs: Update to aufs3.1-20111031 (Closes: #644687) ++ ++ [ Bastian Blank ] ++ * Use xz compression for debug packages. ++ * Make gcc-4.6 the default compiler. ++ * Use shorter versions in the package names. ++ * Remove linux-tools-* binary package. ++ * Drop external module packages stuff. ++ * Set default security module to Unix Discretionary Access Controls. ++ - Remove unneeded selinux boot parameter. ++ ++ -- Bastian Blank Thu, 03 Nov 2011 20:03:14 +0100 ++ ++linux-2.6 (3.1.0~rc7-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ Ben Hutchings ] ++ * Build udebs for the installer ++ ++ -- Ben Hutchings Sun, 25 Sep 2011 22:52:50 +0100 ++ ++linux-2.6 (3.1.0~rc6-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ Ben Hutchings ] ++ * [ia64] Disable GENERIC_GPIO (fixes FTBFS) ++ * [i386] libertas: prioritize usb8388_olpc.bin firmware on OLPC machines ++ * [armel/ixp4xx] Add gpioblib support (fixes FTBFS) ++ * [i386] Fix alignment of alternative instruction entries (Closes: #640964) ++ ++ -- Ben Hutchings Wed, 21 Sep 2011 05:45:40 +0100 ++ ++linux-2.6 (3.1.0~rc4-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ Ben Hutchings ] ++ * aufs: Disable until it is updated for Linux 3.1 ++ * rt: Disable until it is updated for Linux 3.1 ++ * nfs: Enable NFSv4.1/pNFS (Closes: #627655) ++ * [x86] ACPI: Enable ACPI_APEI_GHES as built-in (no longer modular). ++ Enable ACPI_APEI_MEMORY_FAILURE. ++ * netfilter: Enable IP_SET_HASH_NETIFACE as module ++ * net: Enable NFC, NFC_PN533 as modules ++ * video: Enable FB_UDL as module (Closes: #618261) ++ * target: Enable ISCSI_TARGET as module ++ * skge: Enable SKGE_GENESIS ++ * net/wireless: Enable RTL8192DE as module ++ * hwmon: Enable SENSORS_EMC2103, SENSORS_LM95245, SENSORS_MAX1668, ++ SENSORS_NTC_THERMISTOR, SENSORS_SMM665 as modules ++ * [i386] Enable GPIO_CS5535, MFD_CS5535, CS5535_MFGPT, ++ CS5535_CLOCK_EVENT_SRC, GPIO_VX855, MFD_VX855 as modules; ++ [i386/486] Enable OLPC_XO1_PM, OLPC_XO1_RTC, OLPC_XO1_SCI, OLPC_XO15_SCI ++ (Closes: #639113) ++ * media/dvb: Enable DVB_NET ++ * media/rc: Enable IR_MCE_KBD_DECODER as module ++ * gspca: Enable USB_GSPCA_SE401 as module ++ * de4x5: Disable on all architectures except alpha (Closes: #639538) ++ * wl128x: Disable on all flavours except armhf/omap ++ * Make bug script accept failure of lspci (Closes: #639439) ++ * [alpha] Disable GENERIC_GPIO (Closes: #638696) ++ ++ -- Ben Hutchings Mon, 29 Aug 2011 14:48:28 +0100 ++ ++linux-2.6 (3.0.0-6) unstable; urgency=high ++ ++ [ Uwe Kleine-König ] ++ * [amd64] Update rt featureset to 3.0.7-rt20 ++ ++ [ Bastian Blank ] ++ * Add stable 3.0.7, including: ++ - drm/radeon: Update AVIVO cursor coordinate origin before x/yorigin ++ calculation (Closes: #585130) ++ - ipv6: fix NULL dereference in udp6_ufo_fragment() (Closes: #643817) ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.0.7 ++ ++ [ Ben Hutchings ] ++ * [powerpc] Change ATA, PATA_MACIO from module to built-in (Closes: #641210) ++ * [powerpc] Change IDE, IDE_GD from built-in to module ++ * Add stable 3.0.8, including: ++ - cputimer: Cure lock inversion ++ - drm/ttm: ensure ttm for new node is bound before calling move_notify() ++ - drm/ttm: unbind ttm before destroying node in accel move cleanup ++ - CIFS: Fix ERR_PTR dereference in cifs_get_root ++ - xfs: start periodic workers later ++ - mm: fix race between mremap and removing migration entry ++ - x25: Prevent skb overreads when checking call user data ++ - crypto: ghash - Avoid null pointer dereference if no key is set ++ (CVE-2011-4081) ++ - hfsplus: Fix kfree of wrong pointers in hfsplus_fill_super() error path ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.0.8 ++ * [{mips,mipsel}/{4,5}kc-malta] Disable X.25, as in all other configurations ++ * ark3116: Fix initialisation order (Closes: #640391) ++ * Add empty files to trigger generation of kernel-image udebs ++ * aufs: Update to aufs3.0-20111031 (Closes: #644687) ++ * xfs: Fix possible memory corruption in xfs_readlink (CVE-2011-4077) ++ * oom: fix integer overflow of points in oom_badness (CVE-2011-4097) ++ ++ -- Ben Hutchings Tue, 01 Nov 2011 14:50:06 +0000 ++ ++linux-2.6 (3.0.0-5) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * Bump ABI to 2 ++ * kobj_uevent: Ignore if some listeners cannot handle message ++ (Closes: #641661) ++ * Build udebs for the installer ++ * Add stable 3.0.5 and 3.0.6, including: ++ - TTY: pty, fix pty counting ++ - pata_via: disable ATAPI DMA on AVERATEC 3200 ++ - atm: br2684: Fix oops due to skb->dev being NULL ++ - alarmtimers: Avoid possible null pointer traversal ++ - alarmtimers: Memset itimerspec passed into alarm_timer_get ++ - alarmtimers: Avoid possible denial of service with high freq periodic ++ timers ++ - rtc: Fix RTC PIE frequency limit ++ - x86, perf: Check that current->mm is alive before getting user callchain ++ - xen/smp: Warn user why they keel over - nosmp or noapic and what to use ++ instead. (Closes: #637308) ++ - drm/nouveau: properly handle allocation failure in nouveau_sgdma_populate ++ - net/9p: fix client code to fail more gracefully on protocol error ++ - virtio: Fix the size of receive buffer packing onto VirtIO ring. ++ - virtio: VirtIO can transfer VIRTQUEUE_NUM of pages. ++ - fs/9p: Fid is not valid after a failed clunk. ++ - fs/9p: When doing inode lookup compare qid details and inode mode bits. ++ - fs/9p: Always ask new inode in create ++ - net/9p: Fix the msize calculation. ++ - 9p: close ACL leaks ++ - fs/9p: Add fid before dentry instantiation ++ - net/9p: Fix kernel crash with msize 512K ++ - fs/9p: Always ask new inode in lookup for cache mode disabled ++ - vfs: restore pinning the victim dentry in vfs_rmdir()/vfs_rename_dir() ++ - cifs: fix possible memory corruption in CIFSFindNext (CVE-2011-3191) ++ - writeback: introduce .tagged_writepages for the WB_SYNC_NONE sync stage ++ - writeback: update dirtied_when for synced inode to prevent livelock ++ - fib:fix BUG_ON in fib_nl_newrule when add new fib rule ++ - scm: Capture the full credentials of the scm sender ++ - vlan: reset headers on accel emulation path ++ - xfrm: Perform a replay check after return from async codepaths ++ - bridge: Pseudo-header required for the checksum of ICMPv6 ++ - bridge: fix a possible use after free ++ - TPM: Call tpm_transmit with correct size (CVE-2011-1161) ++ - TPM: Zero buffer after copying to userspace (CVE-2011-1162) ++ - ALSA: fm801: Gracefully handle failure of tuner auto-detect ++ (Closes: #641946) ++ - btrfs: fix d_off in the first dirent ++ - ARM: 7091/1: errata: D-cache line maintenance operation by MVA may not ++ succeed ++ - ARM: 7099/1: futex: preserve oldval in SMP __futex_atomic_op ++ - ALSA: usb-audio: Check for possible chip NULL pointer before clearing ++ probing flag ++ - cfg80211: Fix validation of AKM suites ++ - iwlagn: fix dangling scan request ++ - block: Free queue resources at blk_release_queue() (Closes: #631187) ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.0.5 ++ http://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.0.6 ++ * Make taskstats require root access (CVE-2011-2494) ++ ++ [ Uwe Kleine-König ] ++ * [amd64] Update rt featureset to 3.0.6-rt16 (Closes: #643301) ++ ++ -- Ben Hutchings Wed, 05 Oct 2011 15:14:34 +0100 ++ ++linux-2.6 (3.0.0-4) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * Make bug script accept failure of lspci (Closes: #639439) ++ * [alpha] Disable GENERIC_GPIO (Closes: #638696) ++ * Add stable 3.0.4, including: ++ - loop: fix deadlock when sysfs and LOOP_CLR_FD race against each other ++ - Btrfs: fix an oops of log replay ++ - ext4: Fix ext4_should_writeback_data() for no-journal mode ++ - ext4: call ext4_ioend_wait and ext4_flush_completed_IO in ext4_evict_inode ++ - ext4: Resolve the hang of direct i/o read in handling ++ EXT4_IO_END_UNWRITTEN. ++ - ext4: fix nomblk_io_submit option so it correctly converts uninit blocks ++ - xen-blkfront: Drop name and minor adjustments for emulated scsi devices ++ - xen/x86: replace order-based range checking of M2P table by linear one ++ - rt2x00: fix order of entry flags modification ++ - Add a personality to report 2.6.x version numbers ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.0.4 ++ * sendmmsg/sendmsg: fix unsafe user pointer access ++ * rt2x00: fix crash in rt2800usb_write_tx_desc ++ * rt2x00: fix crash in rt2800usb_get_txwi (Closes: #636531) ++ * [sparc] Only Panther cheetah+ chips have POPC (Closes: #639949) ++ * uvcvideo: Fix crash when linking entities (Closes: #637740) ++ * Update Spanish debconf template translations (Omar Campagne) ++ (Closes: #636242) ++ ++ [ Moritz Muehlenhoff ] ++ * Update German Debconf translation. Thanks to Holger Wansing ++ (Closes: #641487) ++ ++ [ Uwe Kleine-König ] ++ * [amd64] Update rt featureset to 3.0.4-rt14 ++ ++ -- Ben Hutchings Mon, 19 Sep 2011 14:40:42 +0100 ++ ++linux-2.6 (3.0.0-3) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * Disable SENSORS_SHT15, unlikely to be usable on any supported platform ++ (Closes: #638696) ++ * Add stable 3.0.3, including: ++ - atm: br2864: sent packets truncated in VC routed mode (Closes: #638656) ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.0.3 ++ * netfilter: TCP and raw fix for ip_route_me_harder (fixes case where ++ SNAT/masquerading is not done) ++ * Remove net device features from bug reports (Closes: #638956) ++ * [mips,mipsel] Ignore nfs ABI changes made in 3.0.0-2; fixes FTBFS ++ * genirq: Fix wrong bit operation ++ * befs: Validate length of long symbolic links (CVE-2011-2928) ++ * CIFS: Fix memory corruption on mount (Closes: #635344) ++ * x86-32, vdso: On system call restart after SYSENTER, use int $0x80 ++ * drm/ttm: fix ttm_bo_add_ttm(user) failure path ++ * fuse: check size of FUSE_NOTIFY_INVAL_ENTRY message ++ ++ -- Ben Hutchings Sat, 27 Aug 2011 08:04:02 +0100 ++ ++linux-2.6 (3.0.0-2) unstable; urgency=high ++ ++ [ Aurelien Jarno ] ++ * Add configuration files for s390x architecture. ++ ++ [ Ben Hutchings ] ++ * linux-libc-dev: Install include/asm under arch-specific directory ++ (thanks to Aurelien for correcting the directory); mark package as ++ multi-arch-coinstallable (Multi-Arch: same) ++ * [powerpc] Use libata-based drivers for most PATA controllers ++ (Closes: #636854): ++ - Various drivers replaced as for x86 in 2.6.32-10 ++ - pata_macio replaces ide_pmac ++ * Add stable 3.0.2, including: ++ - net: Cap number of elements for sendmmsg ++ - net: Fix security_socket_sendmsg() bypass problem ++ - [x86] xen: allow enable use of VGA console on dom0 ++ - net: Compute protocol sequence numbers and fragment IDs using MD5 ++ - cifs: cope with negative dentries in cifs_get_root ++ - ALSA: snd-usb: avoid dividing by zero on invalid input ++ - ipv6: make fragment identifications less predictable (CVE-2011-2699) ++ - sch_sfq: fix sfq_enqueue() (Closes: #631945) ++ - gre: fix improper error handling ++ - ecryptfs: Add mount option to check uid of device being mounted ++ = expect uid ++ - ecryptfs: Return error when lower file pointer is NULL ++ - ext{3,4}: Properly count journal credits for long symlinks ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.0.2 ++ * [x86] Enable RTS_PSTOR as module ++ ++ [ maximilian attems ] ++ * Add stable 3.0.1, including: ++ - gro: Only reset frag0 when skb can be pulled (CVE-2011-2723) ++ - staging: comedi: fix infoleak to userspace (CVE-2011-2909) ++ - rtc: limit frequency ++ - CIFS: Fix oops while mounting with prefixpath ++ - [SCSI] fix crash in scsi_dispatch_cmd() ++ - tracing: Fix bug when reading system filters on module removal ++ - tracing: Have "enable" file use refcounts like the "filter" file ++ - ext4: fix i_blocks/quota accounting when extent insertion fails ++ - ext4: free allocated and pre-allocated blocks when check_eofblocks_fl ++ fails ++ - ext3: Fix oops in ext3_try_to_allocate_with_rsv() ++ - nfsd4: remember to put RW access on stateid destruction ++ - nfsd4: fix file leak on open_downgrade ++ - NFS: Fix spurious readdir cookie loop messages ++ - proc: fix a race in do_io_accounting() ++ - ipc/sem.c: fix race with concurrent semtimedop() timeouts and IPC_RMID ++ - [armel,armhf,hppa] dm io: flush cpu cache with vmapped io ++ - dm snapshot: flush disk cache when merging ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.0.1 ++ ++ [ Jonathan Nieder ] ++ * perf: do not look at ./config for configuration (Closes: #632923) ++ (CVE-2011-2905) ++ ++ [ Uwe Kleine-König ] ++ * [amd64] Update rt featureset to 3.0.1-rt11 ++ ++ -- Ben Hutchings Tue, 16 Aug 2011 06:08:53 +0100 ++ ++linux-2.6 (3.0.0-1) unstable; urgency=low ++ ++ * New upstream release: http://kernelnewbies.org/Linux_3.0 ++ ++ [ maximilian attems ] ++ * Topconfig enable modular VIDEO_SR030PC30, VIDEO_NOON010PC30, ++ SOC_CAMERA_IMX074, SOC_CAMERA_OV2640, SOC_CAMERA_OV6650, ++ SOC_CAMERA_OV9740, USB_YUREX. ++ * [x86] enable modular VIDEO_VIA_CAMERA. ++ * [x86_32] enable modular XO15_EBOOK. ++ * ALSA: hda - Enable auto-parser as default for Conexant codecs. ++ ++ [ Ben Hutchings ] ++ * linux-support, linux-tools: Use dh_python2 instead of dh_pysupport ++ * aufs: Update for 3.0 ++ * [amd64] Enable PCMCIA_AHA152X as module (Closes: #632929) ++ * Update debconf template translations: ++ - Slovak (Slavko) ++ * [x86] comedi: Enable the same drivers as in stable (squeeze), except ++ for ISA drivers on amd64 (Closes: #633516) ++ * Reduce required initramfs-tools version to 0.99~, to ease backporting ++ * [armhf/mx5] Explicitly configure this flavour to support i.MX51; it ++ is not currently possible to support other i.MX5x processors as well ++ ++ [ Arnaud Patard ] ++ * Merge ixp4xx build fix and enable ixp4xx back ++ ++ [ Aurelien Jarno ] ++ * [mips/octeon] Disable MEGARAID_SAS, SUSPEND, HIBERNATION, PM_RUNTIME. ++ Enable FUSION, FUSION_SAS, HW_RANDOM, HW_RANDOM_OCTEON, ++ OCTEON_MGMT_ETHERNET, CONFIG_OCTEON_ETHERNET. ++ ++ [ Bastian Blank ] ++ * [xen] Allow autoloading of backend drivers. ++ ++ [ Uwe Kleine-König ] ++ * [amd64] Add rt featureset with 3.0-rt2 patch set ++ ++ -- Ben Hutchings Sun, 24 Jul 2011 02:42:27 +0200 ++ ++linux-2.6 (3.0.0~rc6-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ maximilian attems ] ++ * Topconfig enable modular USB_NET_KALMIA, I2C_DIOLAN_U2C, SMBUS, ++ SENSORS_SMBUS, SENSORS_SHT21, SENSORS_EMC6W201, SENSORS_SCH5627, ++ SENSORS_ADS1015, SENSORS_W83795, SENSORS_DS620, SENSORS_LINEAGE, ++ SENSORS_LTC4151, SENSORS_LTC4261, SENSORS_MAX16065, SENSORS_MAX6639, ++ SENSORS_MAX6642, BT_WILINK. ++ * [x86_32] enable modular I2C_PXA. ++ * [x86] enable modular SENSORS_FAM15H_POWER. ++ * drm/i915: Hold struct_mutex during i915_save_state/i915_restore_state. ++ * [thinkpad]: Add KEY_MICMUTE and enable it on Lenovo X220. ++ * [m68k]: resources: Add lookup_resource(). ++ * m68k/atari: Reserve some ST-RAM early on for device buffer use. ++ * ALSA: hda - Handle -1 as invalid position, too ++ * ALSA: hda - Judge playback stream from stream id in azx_via_get_position() ++ ++ [ Ben Hutchings ] ++ * [x86] Enable SCSI_ISCI as module ++ ++ -- maximilian attems Tue, 05 Jul 2011 11:05:43 +0200 ++ ++linux-2.6 (3.0.0~rc5-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ - fix wrong iput on d_inod. (closes: #631255, #631802) ++ ++ [ maximilian attems ] ++ * [x86] enable some comedi modules. (closes: #631199) ++ * [kirkwood] Enable sound support for the HP t5325 (closes: #631762) ++ ++ [ Arnaud Patard ] ++ * [armel] disable ixp4xx, until upstream agrees on how to fix ++ the build error ++ * [armel] Remove configuration options which don't exist anymore ++ * [armhf] disable net dma/async tx on mx5 as it can't work ++ ++ -- maximilian attems Tue, 28 Jun 2011 11:55:21 +0200 ++ ++linux-2.6 (3.0.0~rc4-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ - drm/i915: Fixes. (closes: #627976) ++ ++ [ maximilian attems ] ++ * [x86] enable modular INTEL_OAKTRAIL, ACPI_APEI_PCIEAER. ++ * Topconfig enable modular RADIO_WL1273, RADIO_WL128X. ++ ++ [ Ben Hutchings ] ++ * rt2800pci: Add device ID for RT539F device (Closes: #630960) ++ * atm: Enable for all architectures except m68k, s390 (Closes: #630900) ++ ++ -- maximilian attems Tue, 21 Jun 2011 15:00:23 +0200 ++ ++linux-2.6 (3.0.0~rc3-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ Ben Hutchings ] ++ * [i386] idle: EXPORT_SYMBOL(default_idle, pm_idle) if ++ CONFIG_APM_MODULE (only); fixes FTBFS ++ ++ [ maximilian attems ] ++ * Update configs. ++ * Topconfig enable BPF_JIT. (closes: #630553) ++ * Update debconf pt (Américo Monteiro) translations. (closes: #627631) ++ * Add kbuild fixes out of linux-next. ++ ++ -- maximilian attems Thu, 16 Jun 2011 15:04:33 +0200 ++ ++linux-2.6 (3.0.0~rc2-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ maximilian attems ] ++ * Newer Standards-Version 3.9.2 without changes. ++ ++ [ Hector Oron ] ++ * [armel/iop32x] Fix FTBFS (Closes: #629342) ++ ++ [ Aurelien Jarno ] ++ * [mips,mipsel] Update arch/mips/kernel/i8259.c to fix FTBFS. ++ * [mips,mipsel] Remove explicit disable of CONFIG_DRM_NOUVEAU and ++ CONFIG_DRM_RADEON_KMS. ++ ++ [ Ben Hutchings ] ++ * perf: Cancel -Werror compiler option; fixes FTBFS with perl 5.14 ++ * qla4xxx: Remove our fix for #598503; it has now been fixed upstream ++ in a different way and the two changes resulted in FTBFS ++ * [ia64] nouveau: Disable ACPI support. It probably wasn't very useful ++ on ia64, and now depends on mxm-wmi which is definitely x86-only. ++ * Make gcc-4.5 the default compiler (except for alpha, hppa and m68k) ++ * Restore xen-linux-system-- packages ++ ++ -- Ben Hutchings Thu, 09 Jun 2011 01:10:53 +0100 ++ ++linux-2.6 (3.0.0~rc1-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ Ben Hutchings ] ++ * [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA ++ (Closes: #627492) ++ * cgroups: Disable memory resource controller by default. Allow it ++ to be enabled using kernel parameter 'cgroup_enable=memory'. ++ * rt2800usb: Enable support for more USB devices including ++ Linksys WUSB600N (Closes: #596626) (this change was accidentally ++ omitted from 2.6.39-1) ++ * fs: Enable FHANDLE ++ * cgroups: Enable CGROUP_MEM_RES_CTLR_SWAP but not ++ CGROUP_MEM_RES_CTLR_SWAP_ENABLED. Swap accounting can be enabled ++ using kernel parameter 'swapaccount'. ++ * ipv4: Enable IP_FIB_TRIE_STATS ++ * netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC, ++ IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT, ++ IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET, ++ IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules ++ * net/sched: Enable NET_SCH_QFQ as module ++ * can: Enable CAN_SOFTING, CAN_SOFTING_CS as modules ++ * mtd: Enable MTD_SWAP as module ++ * of, proc: Enable PROC_DEVICETREE ++ * dm: Enable DM_RAID, DM_FLAKEY as modules. Note these are currently ++ experimental. ++ * target: Enable TCM_FC as module ++ * net/wireless/ath: Enable CARL9170 as module (carl9170, replacing ++ ar9170usb) ++ * rtlwifi: Enable RTL8192SE as module (Closes: #590280) ++ * net/wireless: Enable MWIFIEX, MWIFIEX_SDIO as modules ++ * net/usb: Enable USB_VL600 as module ++ * tablet: Enable drivers for all possible architectures and flavours ++ * tablet: Enable TABLET_USB_HANWANG as module ++ * pps: Enable PPS_CLIENT_PARPORT as module ++ * ptp: Enable PTP_1588_CLOCK, PTP_1588_CLOCK_GIANFAR, ++ PTP_1588_CLOCK_IXP46X as modules ++ * [x86] watchdog: Enable SP5100_TCO, NV_TCO as modules ++ * media/rc: Enable IR_REDRAT3, RC_LOOPBACK as module ++ * [x86] media/rc: Enable IR_ITE_CIR, IR_FINTEK as modules ++ * gspca: Enable USB_GSPCA_KINECT as module ++ * [i386] radio: Enable RADIO_MIROPCM20 as module ++ * s3fb: Enable FB_S3_DDC ++ * viafb: Enable FB_VIA_X_COMPATIBILITY ++ * es1968: Enable SND_ES1968_RADIO ++ * sound: Enable SND_ISIGHT, SND_LOLA as modules ++ * hid: Enable HID_ACRUX, HID_EMS_FF, HID_KEYTOUCH, HID_LCPOWER, ++ HID_MULTITOUCH, HID_ROCCAT_ARVO, HID_ROCCAT_KONEPLUS, ++ HID_ROCCAT_KOVAPLUS as modules ++ * usb-storage: Enable USB_STORAGE_REALTEK, USB_STORAGE_ENE_UB6250 as ++ modules ++ * mmc: Enable MMC_VUB300, MMC_USHC as modules ++ * memstick: Enable MEMSTICK_R592 as module ++ * [x86] edac: Enable EDAC_I7300 as module ++ * [i386] staging, video: Enable FB_OLPC_DCON as module ++ * [x86] staging, drm: Enable DRM_PSB as module ++ * crypto, net: Enable CRYPTO_USER_API_HASH, CRYPTO_USER_API_SKCIPHER as ++ modules ++ * [x86] block, xen: Enable XEN_BLKDEV_BACKEND as module ++ ++ -- Ben Hutchings Wed, 01 Jun 2011 06:41:14 +0100 ++ ++linux-2.6 (2.6.39-3) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * [x86] i915: Revert "drm/i915: Enable GMBUS for post-gen2 chipsets" ++ (Closes: #627575) ++ * linux-source-: Suggest libqt4-dev (for 'make xconfig') ++ instead of libqt3-mt-dev (Closes: #631666) ++ * [armhf] Add omap flavour, thanks to Sebastian Reichel ++ * [armhf] rtc-twl: Switch to using threaded irq ++ * bridge/netfilter: provide a cow_metrics method for fake_ops ++ (Closes: #629932) ++ * Update debconf template translations: ++ - Danish (Joe Dalton) (Closes: #632551) ++ - Slovak (Slavko) (Closes: #608684) ++ * partitions/efi: Fix crash (oops) caused by corrupted GUID partition ++ table (CVE-2011-1577) ++ * ksm: fix NULL pointer dereference in scan_get_next_rmap_item() ++ (CVE-2011-2183) ++ * inet_diag: Fix infinite loop in inet_diag_bc_audit() (CVE-2011-2213) ++ * taskstats: don't allow duplicate entries in listener mode (CVE-2011-2484) ++ * bluetooth: Prevent buffer overflow in l2cap config request ++ (CVE-2011-2497) ++ ++ [ maximilian attems ] ++ * Add stable 2.6.39.2, including: ++ - block: Fix crash (oops) in blkdev_get() on failed exclusive open ++ (Closes: #631574) ++ - nl80211: fix check for valid SSID size in scan operations (CVE-2011-2517) ++ - drm/radeon/kms: viewport height has to be even ++ - drm/radeon/kms: fix for radeon on systems >4GB without hardware iommu ++ - fat: Fix corrupt inode flags when remove ATTR_SYS flag ++ - scsi: Fix oops caused by queue refcounting failure ++ - cifs: don't allow cifs_reconnect to exit with NULL socket pointer ++ - drm/radeon/kms: do bounds checking for 3D_LOAD_VBPNTR and bump array ++ limit ++ - TOMOYO: Fix oops in tomoyo_mount_acl() (CVE-2011-2518) ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.2 ++ ++ -- Ben Hutchings Mon, 04 Jul 2011 07:08:10 +0100 ++ ++linux-2.6 (2.6.39-2) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA ++ (Closes: #627492) ++ * cgroups: Disable memory resource controller by default. Allow it ++ to be enabled using kernel parameter 'cgroup_enable=memory'. ++ * rt2800usb: Enable support for more USB devices including ++ Linksys WUSB600N (Closes: #596626) (this change was accidentally ++ omitted from 2.6.39-1) ++ * [x86] Remove Celeron from list of processors supporting PAE. Most ++ 'Celeron M' models do not. ++ * Update debconf template translations: ++ - Swedish (Martin Bagge) (Closes: #628932) ++ - French (David Prévot) (Closes: #628191) ++ * aufs: Update for 2.6.39 (Closes: #627837) ++ * Add stable 2.6.39.1, including: ++ - ext4: dont set PageUptodate in ext4_end_bio() ++ - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745) ++ - ext3: Fix fs corruption when make_indexed_dir() fails ++ - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages ++ - sctp: fix race between sctp_bind_addr_free() and ++ sctp_bind_addr_conflict() ++ - sctp: fix memory leak of the ASCONF queue when free asoc ++ - md/bitmap: fix saving of events_cleared and other state ++ - cdc_acm: Fix oops when Droids MuIn LCD is connected ++ - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827) ++ - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184) ++ - tmpfs: fix race between truncate and writepage ++ - nfs41: Correct offset for LAYOUTCOMMIT ++ - xen/mmu: fix a race window causing leave_mm BUG() ++ - ext4: fix possible use-after-free in ext4_remove_li_request() ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1 ++ * Bump ABI to 2 ++ * netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC, ++ IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT, ++ IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET, ++ IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules ++ (Closes: #629401) ++ ++ [ Aurelien Jarno ] ++ * [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE. ++ ++ -- Ben Hutchings Tue, 07 Jun 2011 12:14:05 +0100 ++ ++linux-2.6 (2.6.39-1) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * [x86] Enable CRYPTO_AES_NI_INTEL for all flavours. (closes: #623631) ++ * topconfig: Enable SND_USB_6FIRE, SND_FIREWIRE_SPEAKERS, ++ MEDIA_CONTROLLER, DVB_USB_TECHNISAT_USB2, USB_GSPCA_NW80X, ++ USB_GSPCA_VICAM, XEN_WDT, LOOPBACK_TARGET. ++ * [x86] Enable modular XEN_NETDEV_BACKEND. ++ * topconfig enable mem cgroup RESOURCE_COUNTERS, CGROUP_MEM_RES_CTLR. ++ (closes: #534964) ++ * Cleanup configs. ++ ++ [ Ben Hutchings ] ++ * [!x86] Disable TPM drivers. TPMs are currently only fitted in PCs. ++ * rt2800usb: Enable support for more USB devices including ++ Linksys WUSB600N (Closes: #596626) ++ * mm: Select SLAB allocator again. Although SLUB is currently the ++ upstream default, this was set as an experiment rather than a ++ recommendation! SLUB generally has poorer performance than SLAB on ++ larger systems. ++ * postinst: Remove specific support for running a ramdisk creator; ++ warn users that specify one in /etc/kernel-img.conf ++ * Require initramfs-tools >= 0.99, which installs a postinst hook ++ ++ [ Arnaud Patard ] ++ * [armel] Disable eeti touchscreen driver due to missing irq_to_gpio on ++ several platforms. ++ ++ -- maximilian attems Thu, 19 May 2011 15:34:37 +0200 ++ ++linux-2.6 (2.6.39~rc7-1~experimental.1) experimental; urgency=low ++ ++ * [x86] Enable modular ASUS_WMI and ASUS_NB_WMI. (closes: #626141) ++ * [x86] Enable modular DELL_WMI_AIO, HP_ACCEL, INTEL_IPS, ACPI_IPMI. ++ * [x86/486] Enable modular XO1_RFKILL, XO15_EBOOK. ++ * topconfig: Enable modular NF_CONNTRACK_TIMESTAMP, NF_CONNTRACK_SNMP, ++ NETFILTER_XT_TARGET_AUDIT, NETFILTER_XT_MATCH_ADDRTYPE, ++ NETFILTER_XT_MATCH_DEVGROUP, NET_SCH_SFB, NET_SCH_MQPRIO, NET_SCH_CHOKE, ++ SATA_ACARD_AHCI, PATA_ARASAN_CF, SCSI_BNX2X_FCOE. ++ * Add nl debconf template translation. (closes: #622967) ++ Thanks willem kuyn . ++ * topconfig Enable modular RTL8192CU. (closes: #625613) ++ ++ -- maximilian attems Tue, 10 May 2011 15:11:00 +0200 ++ ++linux-2.6 (2.6.39~rc6-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ maximilian attems ] ++ * Enable SQUASHFS_{LZO,XZ}. (closes: #613658) ++ * [x86] Enable EASYCAP. (closes: #624505) ++ ++ [ Ben Hutchings ++ * xhci-hcd: Include in xhci-pci.c (fixes FTBFS on armel) ++ * [x86] Enable BRCMSMAC; the brcmsmac module replaces brcm80211 ++ (Closes: #625510) ++ ++ [ Aurelien Jarno ] ++ * drm/nouveau, drm/radeon: remove fix for non-powerpc/sparc/x86. ++ * [mips,mipsel] Disabled CONFIG_DRM_NOUVEAU and CONFIG_DRM_RADEON_KMS. ++ * [mips/octeon] Disabled CONFIG_HOTPLUG_CPU and CONFIG_PM. ++ ++ -- maximilian attems Sun, 08 May 2011 12:23:15 +0200 ++ ++linux-2.6 (2.6.39~rc5-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ Ben Hutchings ] ++ * [powerpc] kexec: Fix build failure on 32-bit SMP ++ * net/wireless: Adjust config for iwlegacy/iwlwifi split (Closes: #624124) ++ - Enable IWLWIFI_LEGACY as module ++ - Enable IWL4965 as module; it is no longer part of the iwlagn module ++ * [armhf] Actually install zImage into the linux-image package, thanks to ++ Sebastian Reichel ++ * [armhf] Build a linux-tools package ++ * Fix configuration for features that are no longer modular, thanks to ++ Sedat Dilek (Closes: #624372): ++ - bluetooth: Re-enable BT_L2CAP and BT_SCO as part of bluetooth module ++ - leds: Explicitly enable LEDS_CLASS as built-in ++ - mfd: Explicitly disable MFD_WM8994 ++ ++ [ Aurelien Jarno ] ++ * drm/nouveau, drm/radeon: fix build failure on mips. ++ ++ -- Ben Hutchings Fri, 29 Apr 2011 06:04:13 +0100 ++ ++linux-2.6 (2.6.39~rc4-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ Ben Hutchings ] ++ * [i386] Rename '686-bigmem' flavour to '686-pae'; remove '686' flavour. ++ For 686-class systems without PAE, the '486' flavour is more efficient ++ than the '686' flavour due to optimisation for uniprocessor systems. ++ * Add armhf architecture with mx5 flavour, thanks to Hector Oron and ++ Vagrant Cascadian (Closes: #621032) ++ ++ -- Ben Hutchings Sun, 24 Apr 2011 03:21:31 +0100 ++ ++linux-2.6 (2.6.38-5) unstable; urgency=medium ++ ++ [ Thorsten Glaser ] ++ * [m68k] atari: Enable and compile in generic RTC ++ * [m68k] Backport the most urgent fixes from 2.6.39 ++ - Add helper functions to handle kernel faults, traps and ++ exceptions better (used by the other patches below) ++ - Add improved support for running under the ARAnyM emulator ++ (its native features interface) and emulated hardware ++ + block access (similar to virtio-block) ++ + console access (redirection to stdout) ++ + network access (Ethernet) (Closes: #599121) ++ * [m68k] Add patch from queue fixing atarifb console output on ++ machines with a lot of FastRAM by reserving some ST-RAM early ++ * [m68k] Add patch from mm mailing list to fix SLUB breakage ++ ++ [ Aurelien Jarno ] ++ * [mips/octeon] Disable CONFIG_HOTPLUG_CPU. ++ ++ [ Ben Hutchings ] ++ * rt2800pci, rt2800usb: Enable experimental support for more recent ++ chips (Closes: #623808) ++ * [x86] staging: Enable EASYCAP as module (Closes: #624505) ++ * Add stable 2.6.38.5, including: ++ - p54: Initialize extra_len in p54_tx_80211 ++ - nfsd4: Fix filp leak (regression introduced in 2.6.38.3) ++ - radeon: PLL tweaks for R7xx ++ - nouveau: Fix notifier memory corruption bug ++ - radeon: Fix bad shift in atom iio table parser ++ - [x86] i915: Sanitize the output registers after resume ++ - [x86] ideapad: Read brightness setting on brightness key notify ++ - ath9k_hw: Partially revert "fix dma descriptor rx error bit parsing" ++ - [s390] pfault: fix token handling ++ - ACPI/PM: Avoid infinite recurrence while registering power resources ++ - [hppa] slub: Disable use with DISCONTIGMEM && !NUMA ++ - vfs: avoid large kmalloc()s for the fdtable ++ - agp: Fix arbitrary kernel memory writes (CVE-2011-1745) ++ - agp: Fix OOM and buffer overflow (CVE-2011-1746) ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.38.5 ++ * [hppa] Bump ABI to 2a ++ * mpt2sas: Prevent heap overflows and unchecked reads ++ (CVE-2011-1494, CVE-2011-1495) ++ * [armel] Prevent heap corruption in OABI semtimedop ++ * can: Add missing socket check in can/bcm release (CVE-2011-1598) ++ * ldm: Disable broken support for VBLK fragments (CVE-2011-1017) ++ ++ -- Ben Hutchings Sat, 07 May 2011 21:24:55 +0100 ++ ++linux-2.6 (2.6.38-4) unstable; urgency=low ++ ++ * usb-audio: Define another USB ID for a buggy USB MIDI cable ++ (Closes: #617743) ++ * net: Enable BATMAN_ADV as module (Closes: #622361) ++ * Add stable 2.6.38.3, including: ++ - eCryptfs: Unlock page in write_begin error path ++ - irda: validate peer name and attribute lengths (CVE-2011-1180) ++ - irda: prevent heap corruption on invalid nickname ++ - nilfs2: fix data loss in mmap page write for hole blocks ++ - ALSA: pcm: fix infinite loop in snd_pcm_update_hw_ptr0() ++ - inotify: fix double free/corruption of stuct user ++ - perf: Fix task_struct reference leak ++ - ROSE: prevent heap corruption with bad facilities (CVE-2011-1493) ++ - [x86] mtrr, pat: Fix one cpu getting out of sync during resume ++ - Input: synaptics - fix crash in synaptics_module_init() ++ - ath9k: fix a chip wakeup related crash in ath9k_start ++ - mac80211: fix a crash in minstrel_ht in HT mode with no supported MCS ++ rates ++ - UBIFS: fix oops on error path in read_pnode ++ - quota: Don't write quota info in dquot_commit() ++ - mm: avoid wrapping vm_pgoff in mremap() ++ - wl12xx: fix potential buffer overflow in testmode nvs push ++ - Bluetooth: sco: fix information leak to userspace (CVE-2011-1078) ++ - bridge: netfilter: fix information leak (CVE-2011-1080) ++ - Bluetooth: bnep: fix buffer overflow (CVE-2011-1079) ++ - netfilter: ip_tables: fix infoleak to userspace (CVE-2011-1171) ++ - netfilter: arp_tables: fix infoleak to userspace (CVE-2011-1170) ++ - [x86] Revert "x86: Cleanup highmap after brk is concluded" ++ (Closes: #621072) ++ - Squashfs: handle corruption of directory structure ++ - ext4: fix a double free in ext4_register_li_request ++ - ext4: fix credits computing for indirect mapped files ++ - nfsd: fix auth_domain reference leak on nlm operations ++ - nfsd4: fix oops on lock failure ++ - char/tpm: Fix unitialized usage of data buffer (CVE-2011-1160) ++ - ipv6: netfilter: ip6_tables: fix infoleak to userspace (CVE-2011-1172) ++ - econet: 4 byte infoleak to the network (CVE-2011-1173) ++ - sound/oss: remove offset from load_patch callbacks ++ (CVE-2011-1476, CVE-2011-1477) ++ - inotify: fix double free/corruption of stuct user (CVE-2011-1479) ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.38.3 ++ * Add stable 2.6.38.4, including: ++ - vm: Fix vm_pgoff wrap in stack expansion ++ - cifs: Always do is_path_accessible check in cifs_mount ++ - cifs: Check for private_data before trying to put it ++ - sn9c102: Restrict world-wirtable sysfs files ++ - UBIFS: Restrict world-writable debugfs files ++ - vm: Fix mlock() on stack guard page ++ - UBIFS: Fix assertion warnings ++ - perf: Fix task context scheduling ++ - fib: Add rtnl locking in ip_fib_net_exit ++ - l2tp: Fix possible oops on l2tp_eth module unload ++ - ipv6: Fix duplicate /proc/sys/net/ipv6/neigh directory entries. ++ - net_sched: fix ip_tos2prio ++ - pppoe: drop PPPOX_ZOMBIEs in pppoe_flush_dev ++ - xfrm: Refcount destination entry on xfrm_lookup ++ - vlan: Take into account needed_headroom ++ - bridge: Reset IPCB when entering IP stack on NF_FORWARD ++ - futex: Set FLAGS_HAS_TIMEOUT during futex_wait restart setup ++ - oom-kill: Remove boost_dying_task_prio() ++ - UBIFS: Fix oops when R/O file-system is fsync'ed ++ - sched: Fix erroneous all_pinned logic ++ - vmscan: all_unreclaimable() use zone->all_unreclaimable as a name ++ - next_pidmap: fix overflow condition ++ - proc: Do proper range check on readdir offset ++ - [powerpc] Fix oops if scan_dispatch_log is called too early ++ - ehci: Unlink unused QHs when the controller is stopped ++ - USB: Fix formatting of SuperSpeed endpoints in /proc/bus/usb/devices ++ - xhci: Fix math in xhci_get_endpoint_interval() ++ - xhci: Also free streams when resetting devices ++ - USB: Fix unplug of device with active streams ++ - bluetooth: Fix HCI_RESET command synchronization ++ - bridge: Reset IPCB in br_parse_ip_options ++ - ip: ip_options_compile() resilient to NULL skb route ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.38.4 ++ * [s390] pfault: fix token handling (Closes: #622570) ++ ++ -- Ben Hutchings Sat, 23 Apr 2011 03:17:53 +0100 ++ ++linux-2.6 (2.6.38-3) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * [ppc64] Add to linux-tools package architectures (Closes: #620124) ++ * [amd64] Save cr4 to mmu_cr4_features at boot time (Closes: #620284) ++ * appletalk: Fix bugs introduced when removing use of BKL ++ * ALSA: Fix yet another race in disconnection ++ * cciss: Fix lost command issue ++ * ath9k: Fix kernel panic in AR2427 ++ * ses: Avoid kernel panic when lun 0 is not mapped ++ * PCI/ACPI: Report ASPM support to BIOS if not disabled from command line ++ ++ [ Aurelien Jarno ] ++ * rtlwifi: fix build when PCI is not enabled. ++ ++ [ Martin Michlmayr ] ++ * rtlwifi: Eliminate udelay calls with too large values (Closes: #620204) ++ ++ -- Ben Hutchings Wed, 06 Apr 2011 13:53:30 +0100 ++ ++linux-2.6 (2.6.38-2) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * kconfig: Avoid buffer underrun in choice input (fixes FTBFS on mips) ++ * rt2800usb: Disable powersaving by default (Closes: #618930) ++ * b43: Enable B43_PHY_N (Closes: #619070) ++ * net/wireless: Enable RTL8192CE as module (Closes: #619051) ++ * Add configuration for Debian architecture ppc64, matching the ++ powerpc/powerpc64 flavour (Closes: #618976) ++ * Enable BOOT_PRINTK_DELAY (support for the boot_delay kernel parameter) ++ * [x86/!486] Enable TRANSPARENT_HUGEPAGE, TRANSPARENT_HUGEPAGE_MADVISE ++ (Closes: #618924) ++ * [x86/486] Enable X86_32_IRIS (IRIS power-off support) (Closes: #619493) ++ * Add stable 2.6.38.1, including: ++ - RDMA/cma: Fix crash in request handlers (CVE-2011-0695) ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.38.1 ++ * radeon: Add some sanity checks to obj info record parsing, thanks ++ to John Lindgren (Closes: #618847) ++ * [x86] KVM: remove isr_ack logic from PIC (Closes: #612105) ++ * Add stable 2.6.38.2, including: ++ - cgroups: If you list_empty() a head then don't list_del() it ++ - oom: Fix various bugs in victim task selection ++ - xen-kbdfront: Advertise either absolute or relative coordinates ++ - signal: Prevent rt_sigqueueinfo and rt_tgsigqueueinfo from spoofing ++ the signal code (CVE-2011-1182) ++ - ext3: Skip orphan cleanup on rocompat fs ++ - sysctl: Restrict write access to dmesg_restrict ++ - proc: Protect mm start_code/end_code in /proc/pid/stat ++ - nfsd: Fix internal NFSv4.1 operation flags to be non-overlapping ++ - nfsd: Fix wrong limit used in NFSv4 session creation ++ - USB: Do not pass negative length to snoop_urb() ++ - cdc-acm: Fix various bugs that can lead to a crash or memory corruption ++ - fs: Fix deadlock in pivot_root() ++ - fs: Assign sb->s_bdi to default_backing_dev_info if the bdi is going away ++ - x86: Cleanup highmap after brk is concluded ++ - NFS: Fix a hang/infinite loop in nfs_wb_page() ++ - ext4: Skip orphan cleanup if fs has unknown ROCOMPAT features ++ For the complete list of changes, see: ++ http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.38.2 ++ * [amd64] media/rc: Enable IR_NUVOTON as module (Closes: #619937) ++ * [x86] media/rc: Enable IR_WINBOND_CIR as module ++ * [x86] Enable DEBUG_SET_MODULE_RONX (Closes: #619838) ++ * SCSI: Enable TARGET_CORE and related modules (Closes: #619298) ++ * [hppa] Remove .size directive for flush_alias_page (should fix FTBFS) ++ ++ [ Jurij Smakov ] ++ * Bump CONFIG_NR_CPUS on sparc to 256 to accomodate T2+ machines ++ (Closes: #619435) ++ * Bump ABI to 2 ++ ++ -- Ben Hutchings Tue, 29 Mar 2011 05:31:03 +0100 ++ ++linux-2.6 (2.6.38-1) unstable; urgency=low ++ ++ * New upstream release: http://kernelnewbies.org/Linux_2_6_38 ++ ++ [ Ben Hutchings ] ++ * Move firmware-linux-free to separate source package (firmware-free) ++ * Move linux-base to separate source package ++ * net/can: Enable CAN_SLCAN as module (Closes: #617629) ++ * sound: Enable SND_ALOOP as module (Closes: #617869) ++ * Remove the Big Kernel Lock: ++ - adfs,appletalk,i810,ufs,usbip: Refactor locking ++ - hpfs: Disable HPFS_FS ++ * ext4: Disable FS_IOC_FIEMAP ioctl temporarily (together with fixes ++ for btrfs in 2.6.38, closes: #615035) ++ * sched: Build with SCHED_AUTOGROUP, but do not enable autogrouping by ++ default (use sysctl kernel.sched_autogroup_enabled=1) (Closes: #618486) ++ * Set ABI to 1 ++ ++ [ Aurelien Jarno] ++ * mips/malta-[45]kc: ++ - disable ATM, TR, WAN. ++ - synchronize options in malta-4kc and malta-5kc. ++ ++ -- Ben Hutchings Wed, 16 Mar 2011 04:47:57 +0000 ++ ++linux-2.6 (2.6.38~rc8-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ Ben Hutchings ] ++ * [sparc] Fix .size directive for do_int_load ++ * [arm] Fix .size directive for xscale_dma_a0_map_area ++ ++ -- Ben Hutchings Sat, 12 Mar 2011 03:31:52 +0000 ++ ++linux-2.6 (2.6.38~rc7-1~experimental.1) experimental; urgency=low ++ ++ [ maximilian attems ] ++ * New upstream release candidate ++ - swiotlb: Fix wrong panic (Closes: #615990) ++ * x86: Set DRM_I915_KMS on request by xorg team. ++ ++ [ Ben Hutchings ] ++ * [x86] Correct typos in label names in two asm functions (Closes: #616426) ++ * [x86] Enable VT6656, loading firmware from a separate file (requires ++ firmware-linux-nonfree 0.29) (Closes: #568454) ++ * perf: Build with libdwarf for improved analysis capabilities ++ * perf: Build with newt for improved user interface (Closes: #615868) ++ * aufs: Update for 2.6.38 ++ * aufs: Fix device numbers passed to security_path_mknod() ++ * dib0700/dib7000m: Add pid filtering (Closes: #614837) ++ * [powerpc] Revert fb module changes (Closes: #614221) ++ ++ -- Ben Hutchings Tue, 08 Mar 2011 02:34:04 +0000 ++ ++linux-2.6 (2.6.38~rc6-1~experimental.1) experimental; urgency=low ++ ++ [ Ben Hutchings ] ++ * New upstream release candidate ++ - drm/radeon/kms: hopefully fix pll issues for real (v3) (Closes: #614566) ++ - r8169: Keep firmware in memory (Closes: #609538) ++ - [sparc] Fix misaligned tracing information which the module loader ++ does not support (Closes: #609371) ++ - [sh4] Export cpu_core_map to fix build failure with CONFIG_SFC=m. ++ - [armel] Support for Buffalo LS-CHL (Closes: #590105). ++ - btrfs: Prevent heap corruption in btrfs_ioctl_space_info() ++ (CVE-2011-0699) ++ - [s390] Remove task_show_regs (CVE-2011-0710) ++ * DFSG: Remove drivers/staging/ft1000/ft1000-pcmcia/boot.h, non-free ++ firmware for a driver we don't build (Closes: #609448) ++ * module,bug: Add TAINT_OOT_MODULE flag for modules that weren't built ++ in-tree ++ ++ [ maximilian attems ] ++ * [x86] linux-images suggest extlinux, s/grub/grub-pc/. (closes: #613909) ++ ++ [ Aurelien Jarno] ++ * mips/swarm: enable PATA drivers that have been lost during IDE -> PATA ++ conversion. ++ * mips/malta-[45]kc: set VIRTUALIZATION. ++ ++ -- maximilian attems Tue, 22 Feb 2011 14:36:33 +0100 ++ ++linux-2.6 (2.6.37-2) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * Add stable 2.6.37.1: ++ - libata: Set queue DMA alignment to sector size for ATAPI too ++ - USB: serial: add missing .usb_driver field in serial drivers ++ - USB: EHCI: fix scheduling while atomic during suspend ++ - zram: Fix data corruption issue ++ - brcm80211: Fix suspend/resume issue ++ - ath9k: Fix system hang when resuming from S3/S4 ++ - SCSI: Fix medium error problems with some arrays which can cause ++ data corruption ++ - libsas: Fix runaway error handler problem ++ - NFS: Don't use vm_map_ram() in readdir ++ - NFS: Fix NFSv3 exclusive open semantics ++ - /proc/kcore: Fix seeking ++ - mm: Fix migration hangs on anon_vma lock ++ - writeback: Stop background/kupdate works from livelocking other works ++ - writeback: Avoid livelocking WB_SYNC_ALL writeback ++ - ext4: Fix trimming of a single group ++ - af_unix: Avoid socket->sk NULL OOPS in stream connect security hooks ++ - virtio_net: Add schedule check to napi_enable call ++ - ptrace: Use safer wake up on ptrace_detach() ++ - net: Fix ip link add netns oops ++ - SMP: Fix smp_call_function_many() SMP race ++ - md: Ensure no IO request to get md device before it is properly ++ initialised ++ - PM/runtime: Don't enable interrupts while running in_interrupt ++ - [x86] mm: Avoid possible bogus TLB entries by clearing prev ++ mm_cpumask after switching mm ++ * Kbuild: Include localversion file in linux-headers-*; fixes output ++ of 'make kernelrelease' ++ * Add stable 2.6.37.2: ++ - nfsd: Memory corruption due to writing beyond the stat array ++ - xen: p2m: Correctly initialize partial p2m leaf ++ - av7110: Check for negative array offset (CVE-2011-0521) ++ - cred: Fix kernel panic upon security_file_alloc() failure ++ - btrfs: Prevent heap corruption in btrfs_ioctl_space_info() ++ (CVE-2011-0699) ++ - cred: Fix BUG() upon security_cred_alloc_blank() failure ++ - cred: Fix memory and refcount leaks upon security_prepare_creds() ++ failure ++ - PCI: Use security_capable() when checking capablities during config ++ space read ++ - [s390] Remove task_show_regs (CVE-2011-0710) ++ - PM/hibernate: Return error code when alloc_image_page() fails ++ - fs/partitions: Validate map_count in Mac partition tables ++ - workqueue: Wake up a worker when a rescuer is leaving a gcwq ++ - ALSA: caiaq - Fix possible string-buffer overflow ++ * Set ABI to 2 ++ ++ [ Martin Michlmayr ] ++ * [armel/orion5x] Re-enable all devices. ++ * [armel/kirkwood] Re-enable Seagate FreeAgent DockStar support. ++ ++ -- Ben Hutchings Sat, 26 Feb 2011 03:16:16 +0000 ++ ++linux-2.6 (2.6.37-1) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * [arm] ixp4xx: Revert build fix, now applied upstream which resulted ++ in another build failure ++ * r8169: Keep firmware in memory (Closes: #609538) ++ * r8712u: Firmware filename is rtlwifi/rtl8712u.bin (Closes: #602450) ++ * [sparc] Fix misaligned tracing information which the module loader ++ does not support (Closes: #609371) ++ * Set ABI to 1 ++ * Add aufs2.1, marked as staging (Closes: #573189, #613248) ++ * fs/notify: Enable FANOTIFY (Closes: #599877) ++ * acer-wmi, aic94xx, asus_acpi, iscsi, janz-ican3, rtc-ds1511, tc1100-wmi: ++ Restrict write permissions on files in procfs/sysfs ++ * nbd: Remove module-level ioctl mutex mistakenly introduced in 2.6.37 ++ * [x86] crypto: Re-enable AES_NI_INTEL as module (Closes: #597658) ++ * [powerpc] video/fb: Enable FB_VGA16 as built-in; build FB_CT65550, ++ FB_NVIDIA, FB_MATROX, FB_RADEON, FB_ATY128, FB_ATY, FB_SIS, FB_3DFX ++ as modules (Closes: #609615) ++ ++ [ Aurelien Jarno ] ++ * [sh4] Export cpu_core_map to fix build failure with CONFIG_SFC=m. ++ * [mips/5kc-malta] Enable CONFIG_VGA_CONSOLE. ++ ++ [ Bastian Blank ] ++ * Enable CIFS fscache and ACL support. ++ * Enable Xen PCI frontend. ++ ++ -- Ben Hutchings Tue, 15 Feb 2011 04:14:09 +0000 ++ ++linux-2.6 (2.6.37-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release: http://kernelnewbies.org/Linux_2_6_37 ++ - starfire: Fix dma_addr_t size test for MIPS (fixes FTBFS) ++ - watchdog: Improve failure message and documentation (Closes: #608138) ++ ++ [ Ben Hutchings ] ++ * i2c-i801: Include (fixes FTBFS on alpha) ++ * [x86] Staging: Enable R8712U as module (r8712u, replacing r8192s_usb) ++ - Enable loading external firmware, thanks to Stefan Lippers-Hollmann ++ * linux-base: Look for GRUB 1 configuration in both /boot/grub and ++ /boot/boot/grub (Closes: #607863) ++ * btrfs: Require CAP_SYS_ADMIN for filesystem rebalance (Closes: #608185) ++ * r8169: Change RTL8111D/RTL8168D initialisation and firmware loading to ++ match upstream version (Closes: #596390 with firmware-realtek 0.28) ++ ++ -- Ben Hutchings Wed, 05 Jan 2011 02:44:28 +0000 ++ ++linux-2.6 (2.6.37~rc7-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ - [mips] Rename mips_dma_cache_sync back to dma_cache_sync (fixes FTBFS) ++ ++ [ Ben Hutchings ] ++ * debian/copyright: Add explanation of indirect linking of perf to ++ OpenSSL (Closes: #606520) ++ * [powerpc,x86] Enable PATA_PCMCIA (Closes: #606324) ++ * Disable BLK_DEV_IDECS ++ * [alpha] Use libata-based drivers for most PATA controllers ++ * [powerpc] linux-base: Run ybin after updating yaboot.conf ++ (Closes: #607284) ++ * Update debconf template translations: ++ - Add Catalan (Jordi Mallach) ++ - Update Danish (Joe Hansen) ++ - Update Spanish (Omar Campagne, Javier Fernández-Sanguino) ++ - Add Italian (Luca Bruno) ++ - Update Japanese (Nobuhiro Iwamatsu) ++ - Add Brazilian Portugese (Flamarion Jorge) ++ - Update Vietnamese (Clytie Siddall) ++ * debian/bin/test-patches: Restrict patches to featureset when building ++ with a featureset (thanks to Tim Small) ++ * Recommend use of 'make deb-pkg' to build custom kernel packages ++ * [ia64] drm/nouveau: Revert unnecessary exclusion of ACPI support code ++ ++ -- Ben Hutchings Sat, 25 Dec 2010 16:21:09 +0000 ++ ++linux-2.6 (2.6.37~rc5-1~experimental.3) experimental; urgency=low ++ ++ * Really apply patches added in the previous version ++ ++ -- Ben Hutchings Sat, 11 Dec 2010 16:27:21 +0000 ++ ++linux-2.6 (2.6.37~rc5-1~experimental.2) experimental; urgency=low ++ ++ * Second attempt to fix FTBFS on various architectures: ++ - [alpha] Do not use -Werror for arch/alpha ++ - [arm/ixp4xx] Rename FREQ macro to avoid collisions (v2) ++ - drm/nouveau: Only select ACPI_VIDEO if its dependencies are met ++ - [mips] Change mips_sc_is_activated() to do what the comment says ++ ++ -- Ben Hutchings Sat, 11 Dec 2010 06:27:51 +0000 ++ ++linux-2.6 (2.6.37~rc5-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ Ben Hutchings ] ++ * Attempt to fix FTBFS on various architectures: ++ - [alpha] Do not use -Werror for arch/alpha/kernel ++ - [arm/ixp4xx] Rename FREQ macro to avoid collisions ++ - [mips] Add the necessary parameter to mips_sc_is_activated() ++ ++ -- Ben Hutchings Fri, 10 Dec 2010 02:59:12 +0000 ++ ++linux-2.6 (2.6.37~rc4-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ maximilian attems ] ++ * Newer Standards-Version 3.9.1 without changes. ++ ++ [ Martin Michlmayr ] ++ * Add ixp4xx build fix from Arnaud Patard (Closes: #602669) ++ * [armel/kirkwood] Enable sound. ++ * ASoC: Add support for OpenRD Ultimate (Arnaud Patard). ++ ++ [ Ben Hutchings ] ++ * Enable PM_ADVANCED_DEBUG (Closes: #603254) ++ * Disable X.25 protocol and related drivers. This 10 year old experiment ++ has stalled and is a source of security bugs. ++ * Disable Econet protocol. It is unmaintained upstream, probably broken, ++ and of historical interest only. ++ * af_802154,decnet,rds: Disable auto-loading as mitigation against local ++ exploits. These protocol modules are not widely used and can be ++ explicitly loaded or aliased on systems where they are wanted. ++ * debian/rules: Change 'clean' rule to remove package build directories ++ even after a version bump, thanks to Timo Juhani Lindfors ++ * dm: Deal with merge_bvec_fn in component devices better (Closes: #604457) ++ * 9p: Enable 9P_FS_POSIX_ACL ++ * netfilter/ipvs: Enable IP_VS_PE_SIP as module ++ * net/sched: Enable NET_ACT_CSUM as module ++ * can: Enable CAN_SJA1000_ISA, CAN_TSCAN1 as modules ++ * block: Enable BLK_DEV_RBD (Rados) as module ++ * sensors: Enable AD525X_DPOT_SPI, APDS9802ALS, ISL29020, SENSORS_BH1780, ++ SENSORS_BH1770, SENSORS_APDS990X, HMC6352, BMP085 as modules ++ * scsi: Enable SCSI_CXGB4_ISCSI as module ++ * net/ppp: Enable PPTP as module ++ * net: Enable BNA, SMCTR, USB_NET_CX82310_ETH as modules ++ * IR: Enable IR_RC5_SZ_DECODER as module ++ * [i386] IR: Enable IR_NUVOTON as module ++ * V4L: Enable GSPCA_KONICA, GSPCA_XIRLINK_CIT as modules ++ * DVB: Enable USB_LME2510 as module ++ * [i386] sound/isa: Enable SND_AZT1605, SND_AZT2316, SND_JAZZ16, ++ SND_MSND_PINNACLE, SND_MSND_CLASSIC as modules ++ * HID: Enable HID_UCLOGIC, HID_WALTOP, HID_ROCCAT_PYRA as modules ++ * hid-logitech: Enable LOGIWII_FF ++ * Enable USB_UAS (USB-attached SCSI) as module ++ * serial: Enable USB_SERIAL_SAMBA as module ++ * drm/nouveau: Enable DRM_I2C_SIL164 as module ++ * perf: Use libiberty, not libbfd, for symbol demangling ++ (Closes: #604750, #606050) ++ * firmware: Correct copyright information and add source for CIS files ++ (accidentally omitted when merging from sid branch) ++ ++ -- Ben Hutchings Sun, 05 Dec 2010 23:19:38 +0000 ++ ++linux-2.6 (2.6.36-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release: http://kernelnewbies.org/Linux_2_6_36 ++ - writeback: always use sb->s_bdi for writeback purposes (Closes: #599466) ++ - i7core_edac: fix panic in udimm sysfs attributes registration ++ (Closes: #600528) ++ ++ [ Ben Hutchings ] ++ * qla4xxx: Fix build on some architectures lacking 64-bit I/O ++ (Closes: #598503) ++ * [x86] Enable modular TM6000, TM6000_ALSA, TM6000_DVB ++ * [x86] Staging: fix Makefile so brcm80211 will actually build ++ (Closes: #599465) ++ * [x86] Enable modular IDEAPAD_ACPI (Closes: #599444) ++ * perf: Enable Perl and Python scripting ++ - Move scripts to /usr/share/perf_-core (Closes: #599624) ++ * crypto: Explicitly enable algorithm self-tests (Closes: #599441) ++ * [x86] Skip looking for ioapic overrides when ioapics are not present ++ (Closes: #598533) ++ * [x86] ata_piix: Add device ID for ICH4-L ++ * [armel/iop32x,ia64,x86] Disable BLK_DEV_PIIX as obsolete ++ * [amd64] Disable DRM_I810; i81x chipsets do not support 64-bit processors ++ * [x86] Disable DRM_I830; the i915 driver is now used instead ++ ++ [ Martin Michlmayr ] ++ * Kirkwood: restrict the scope of the PCIe reset workaround ++ ++ -- maximilian attems Wed, 27 Oct 2010 13:23:11 +0200 ++ ++linux-2.6 (2.6.36~rc6-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ - drm/i915: Ensure that the crtcinfo is populated during mode_fixup() ++ (Closes: #592415) ++ - USB: fix bug in initialization of interface minor numbers ++ (Closes: #598207) ++ ++ [ Ben Hutchings ] ++ * linux-base: Remove dependency on libapt-pkg-perl (Closes: #589996, really) ++ * Disable INTEL_IDLE. It can no longer be built as a module and so was ++ actually disabled by the previous version, but I do not consider it ready ++ to build-in yet. ++ * Enable modular NETFILTER_XT_TARGET_CHECKSUM, NETFILTER_XT_TARGET_IDLETIMER, ++ NETFILTER_XT_MATCH_CPU, NETFILTER_XT_MATCH_IPVS ++ * Reenable LOCKUP_DETECTOR, accidentally disabled by the previous version ++ * Enable modular AD525X_DPOT_I2C, ATM_NICSTAR, CAN_ESD_USB2, CHELSIO_T4VF, ++ FIREWIRE_NOSY, HID_ACRUX_FF, HID_ELECOM, INFINIBAND_CXGB4, INFINIBAND_QIB, ++ MTD_PCMCIA, ORINOCO_USB, PPS_CLIENT_LDISC, RAMOOPS, SERIAL_MFD_HSU, ++ UIO_NETX, USB_GSPCA_SPCA1528, USB_GSPCA_SQ930X, USB_SERIAL_SSU100, ++ USB_SERIAL_ZIO, WL1271_SDIO, WL1271_SPI ++ * Enable BT_HCIUART_ATH3K, USB_SERIAL_MOS7715_PARPORT ++ * [x86] Enable modular SENSORS_PKGTEMP ++ * Enable modular IR_CORE, RC_MAP, all IR decoders, IR_IMON, IR_MCEUSB, ++ IR_ENE, IR_STREAMZAP ++ * [x86] Enable modular LIRC drivers ++ ++ -- Ben Hutchings Sun, 03 Oct 2010 21:18:41 +0100 ++ ++linux-2.6 (2.6.36~rc5-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ - 3c59x: Fix deadlock in vortex_error() (Closes: #595554) ++ ++ [ Ben Hutchings ] ++ * speakup: Update to match Debian package version 3.1.5.dfsg.1-1 ++ * [x86] Add brcm80211 driver for Broadcom 802.11n wireless network ++ controllers ++ * [x86] Set XEN_PLATFORM_PCI=y ++ ++ -- Ben Hutchings Tue, 21 Sep 2010 02:15:33 +0100 ++ ++linux-2.6 (2.6.35-1~experimental.3) experimental; urgency=low ++ ++ [ Ritesh Raj Sarraf ] ++ * Add .gnu_debuglink information into kernel modules (Closes: #555549) ++ ++ [ Ben Hutchings ] ++ * linux-base: Remove dependency on libapt-pkg-perl (Closes: #589996) ++ * Update debconf template translations: ++ - Czech (Michal Simunek) (Closes: #590546) ++ - Portugese (Américo Monteiro) (Closes: #590557) ++ - French (David Prévot) (Closes: #591149) ++ - Russian (Yuri Kozlov) (Closes: #591241) ++ - Swedish (Martin Bagge) (Closes: #592045) ++ - German (Holger Wansing) (Closes: #592226) ++ * [x86] Enable samsung-laptop driver ++ * [sparc] Enable XVR1000 driver (Closes: #574243) ++ * Change BLK_CGROUP from module to built-in so that cfq can be the ++ default I/O scheduler again (Closes: #593720) ++ * [mipsel/loongson-2f] Enable smtcfb (FB_SM7XX) driver (Closes: #594642) ++ ++ [ Ian Campbell ] ++ * Fixes/overrides for Linitan warnings: ++ - Add "(meta package)" to short description of linux-headers ++ metapackages, resolves empty-binary-package. ++ - Add dependency on ${misc:Depends} to all packages, resolves ++ debhelper-but-no-misc-depends. Required update to gencontrol.py to ++ augment rather than override headers_arch_depends read from templates. ++ - Override dbg-package-missing-depends for linux-image-*-dbg. It is not ++ necessary to install the kernel image package to use the dbg package ++ since the dbg package already contains a complete image with symbols. ++ ++ [ Bastian Blank ] ++ * Disable Ralink staging drivers, the in-tree ones reached "works-for-me" ++ status. ++ ++ [ Aurelien Jarno ] ++ * Fix netfilter CONFIG_COMPAT support. ++ * [sh4] set VIRTUALIZATION. ++ * [mips] Add an octeon flavour. ++ ++ [ maximilian attems] ++ * Add stable 2.6.35.3 and 2.6.35.4. ++ ++ -- maximilian attems Mon, 06 Sep 2010 15:16:17 +0200 ++ ++linux-2.6 (2.6.35-1~experimental.2) experimental; urgency=low ++ ++ * images: Nuke modules.devname on removal. (closes: #590607) ++ * Add stable 2.6.35.1 and 2.6.35.2. ++ * mm: fix page table unmap for stack guard page properly. ++ * mm: fix up some user-visible effects of the stack guard page. ++ * config.loongson-2f: Enable USB and RTC for loongson-2f. ++ Thanks Geert Stappers (closes: #583689) ++ ++ -- maximilian attems Mon, 16 Aug 2010 23:49:32 +0200 ++ ++linux-2.6 (2.6.35-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release: http://kernelnewbies.org/Linux_2_6_35 ++ - [ia64] Fix crash when gcore reads gate area (Closes: #588574) ++ - tpm_tis: fix subsequent suspend failures (Closes: #591031) ++ ++ * topconfig enable BLK_CGROUP, NETFILTER_XT_TARGET_TEE, VMWARE_BALLOON, ++ ATH9K_HTC, TOUCHSCREEN_HAMPSHIRE, TOUCHSCREEN_TPS6507X, SND_ASIHPI, ++ SQUASHFS_XATTRS, RCU_FAST_NO_HZ, COMPACTION, IP_MROUTE_MULTIPLE_TABLES, ++ IPV6_MROUTE_MULTIPLE_TABLES, NET_DCCPPROBE, NET_SCTPPROBE, L2TP, ++ BT_L2CAP_EXT_FEATURES, MTD_NAND_RICOH, ATA_BMDMA, KEYBOARD_QT2160, ++ N_GSM, SENSORS_SHT15, SENSORS_EMC1403, SENSORS_ADS7871, SENSORS_TMP102, ++ SND_ES1968_INPUT, SND_MAESTRO3_INPUT, LEDS_LT3593, LEDS_MC13783. ++ * x86 enable INTEL_IDLE, ACPI_HED, ACPI_APEI, ACPI_APEI_GHES, ++ PCI_CNB20LE_QUIRK. ++ ++ -- maximilian attems Tue, 03 Aug 2010 16:21:16 +0200 ++ ++linux-2.6 (2.6.35~rc6-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ - drm/i915: Add 'reclaimable' to i915 self-reclaimable page allocations ++ (Closes: #534422) ++ ++ [ Ben Hutchings ] ++ * [!x86] Disable FB_VIA; these GPUs are only found on x86 motherboards ++ * ds2782_battery: Fix build failure on several architectures ++ * postinst: Remove support for 'default' boot loaders. Warn users on ++ upgrade if the current configuration may rely on this. ++ * [i386/686] Remove AMD K6 from the list of supported processors; it ++ does not implement the CMOV instruction ++ * 3c59x: Fix call to mdio_sync() with the wrong argument (Closes: #589989) ++ ++ -- Ben Hutchings Sat, 24 Jul 2010 01:00:26 +0100 ++ ++linux-2.6 (2.6.35~rc5-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release candidate ++ ++ [ Ben Hutchings ] ++ * Consistently name the linux-tools package and perf binary using the ++ upstream version without any -rcN suffix ++ ++ -- Ben Hutchings Tue, 13 Jul 2010 01:09:27 +0100 ++ ++linux-2.6 (2.6.35~rc4-1~experimental.1) experimental; urgency=low ++ ++ * New upstream snapshot ++ - [hppa] clear floating point exception flag on SIGFPE signal ++ (Closes: #559406) ++ - Add mantis and hopper DVB drivers (Closes: #577264) ++ - eeepc-laptop: Disable wireless hotplug on more models where the ++ controller is not at the expected address (Closes: #576199) ++ - qcserial: Add support for Qualcomm Gobi 2000 devices ++ (Closes: #585661) ++ - radeon: Fix MacBook Pro connector quirk (Closes: #585943) ++ - r8169: Fix MDIO timing (Closes: #583139) ++ - asix: fix setting mac address for AX88772 (Closes: #587580) ++ - Update Marvell CESA (mv_cesa) driver (Closes: #585790): ++ ++ [ Ben Hutchings ] ++ * ipr: add writeq definition if needed (Closes: #584840) ++ * [mips] Fix boot from ATA hard drives (Closes: #584784): ++ - Set io_map_base for several PCI bridges lacking it ++ - Replace per-platform built-in IDE drivers with libata-based drivers ++ - Enable BLK_DEV_SD as built-in on all platforms ++ * Update Spanish debconf templates, thanks to Omar Campagne ++ (Closes: #580538) ++ * [powerpc] Enable pata_amd driver, replacing amd74xx ++ * linux-base: Don't identify LVM2 PVs by UUID (Closes: #585852) ++ * Move NEWS to linux-latest-2.6 (Closes: #586401) ++ * 3c59x: Change locking to avoid use of disable_irq() (Closes: #586967) ++ * Enable IPv6 support for IPVS (IP_VS_IPV6) (Closes: #584549) ++ * linux-base: If the disk ID update process fails, give the user a ++ chance to retry or change their answers (Closes: #585609) ++ * ipv6: Clamp reported valid_lft to a minimum of 0 (Closes: #514644) ++ * ipv6: Use interface max_desync_factor instead of static default ++ (Closes: #514646) ++ * [ia64, powerpc, sparc, x86] Enable KPROBES and KRETPROBES ++ (Closes: #584130) ++ * r8192s_usb: Fix various bugs: ++ - Clean up in case of an error in module initialisation ++ - Rename and remove proc directories correctly if an interface is ++ not called wlan0 (Closes: #582972) ++ - Correct device ID table (Closes: #584945, #587985) ++ * [x86] Enable r8192u_usb driver ++ * Add linux-tools- package containing the perf tool ++ (Closes: #548715) ++ * Enable SERIAL_USB_TI (Closes: #588096) and SERIAL_USB_WHITEHEAT ++ * [x86] Enable EDAC_I7CORE ++ ++ [ maximilian attems ] ++ * Enable DRM_RADEON_KMS. ++ ++ [ Martin Michlmayr ] ++ * OpenRD-Base: revert patch "allow SD/UART1 selection" since it ++ never made it upstream. ++ * ARM: update mach types. ++ * Add support for OpenRD-Ultimate. ++ * QNAP TS-11x/TS-21x: Add MPP44 (board ID). ++ * Add support for the HP t5325 Thin Client. ++ * m25p80: Add support for Macronix 25L8005. ++ * [armel/kirkwood] Enable FB_XGI and FRAMEBUFFER_CONSOLE. ++ * [armel] Make MOUSE_PS2 modular. ++ * [armel] Build INPUT_UINPUT for all flavours. ++ * [armel/kirkwood] Enable FB_UDL. ++ * [armel] Disable PARPORT_PC (Closes: #588164) ++ ++ [ Bastian Blank ] ++ * Disable mISDN support for NETJet cards. The driver binds a generic PCI ++ bridge. ++ * Disable ISDN4Linux drivers. ++ ++ -- Ben Hutchings Sat, 10 Jul 2010 21:53:57 +0100 ++ ++linux-2.6 (2.6.34-1~experimental.2) experimental; urgency=low ++ ++ [ Ben Hutchings ] ++ * [x86] Reenable rtl8192su, accidentally disabled in previous version ++ (Closes: #580740) ++ * writeback: Update dirty flags in two steps ++ * writeback: ensure that WB_SYNC_NONE writeback with sb pinned is sync ++ (Closes: #582808) ++ * writeback: fix non-integrity write-back ++ * [mipsel] Add a loongson-2f flavour ++ * [mipsel] Loongson: Define rtc device on MC146818-equipped systems ++ * Make gcc-4.4 the default compiler ++ * [ia64] Hardcode the output of the scripts under arch/ia64/scripts so ++ that we can build out-of-tree modules correctly (refresh and re-add ++ dropped patch) (Closes: #392592) ++ * [ia64] Enable SGI SN support and mspec driver (Closes: #582224) ++ * iwlwifi: Disable QoS when connected to a non-QoS-capable AP ++ (Closes: #578262) ++ * [x86] Disable e_powersaver cpufreq driver as unsafe. It has already ++ been blacklisted by cpufrequtils. The acpi-cpufreq driver can be used ++ instead on some VIA C7 systems. (Closes: #566208) ++ * [amd64] ext4: Fix compat EXT4_IOC_ADD_GROUP (used by online resize) ++ * Install debug kernel image in /usr/lib/debug/boot (Closes: #582810) ++ * Build inet_lro as a module ++ * [sparc] Enable CONFIG_FB_XVR500, CONFIG_FB_XVR2500 (Closes: #508108) ++ ++ [ maximilian attems ] ++ * topconfig enable CFQ_GROUP_IOSCHED, MFD_WM8994, REGULATOR_MAX8649, ++ REGULATOR_WM8994, VHOST_NET, BT_ATH3K, CRYPTO_PCRYPT. ++ * [x86] Enable X86_PCC_CPUFREQ, VGA_SWITCHEROO (closes: #582637). ++ ++ [ Martin Michlmayr ] ++ * QNAP TS-419P: Export GPIO indicating jumper setting of JP1. ++ ++ [ dann frazier ] ++ * [hppa] clear floating point exception flag on SIGFPE signal ++ (Closes: #559406) ++ ++ [ Aurelien Jarno ] ++ * [sh4] fix sh_tmu clocksource following recent nohz changes. ++ ++ [ Moritz Muehlenhoff ] ++ * Enable X86 board specific fixups for reboot (Closes: #536537) ++ ++ -- Ben Hutchings Sun, 06 Jun 2010 18:53:04 +0100 ++ ++linux-2.6 (2.6.34-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release: http://kernelnewbies.org/Linux_2_6_34 ++ ++ * New upstream release ++ - rtl8192su: Add IDs for several more devices (Closes: #580740) ++ ++ [ maximilian attems ] ++ * topconfig enable IPV6_SIT_6RD, NETFILTER_XT_TARGET_CT, IP_VS_PROTO_SCTP, ++ NF_CONNTRACK_ZONES, CAN_PLX_PCI, TI_DAC7512, SCSI_HPSA, PATA_TOSHIBA, ++ MACVTAP, CHELSIO_T4, IXGBEVF, QLCNIC, LIBERTAS_MESH, ++ USB_NET_SMSC75XX, USB_SIERRA_NET, VIDEO_CX18_ALSA, USB_GSPCA_BENQ, ++ USB_GSPCA_CPIA1, USB_GSPCA_OV534_9, USB_GSPCA_SN9C2028, RADIO_TEF6862, ++ RADIO_SAA7706H, SND_USB_UA101, CEPH_FS, MICREL_PHY, KSZ884X_PCI, ++ SENSORS_ADT7411, SENSORS_ASC7621, VIDEO_TLG2300, DVB_USB_AZ6027, ++ DVB_NGENE, HID_3M_PCT, LOGIG940_FF, HID_MAGICMOUSE, HID_MOSART, ++ HID_NTRIG, HID_QUANTA, HID_STANTUM, HID_WACOM, USB_SERIAL_QCAUX, ++ USB_SERIAL_VIVOPAY_SERIAL, MMC_RICOH_MMC, LEDS_DELL_NETBOOKS, LOGFS. ++ * [x86] Enable EEEPC_WMI. ++ * Fix backlight support on some recent Thinkpads. ++ * acpi: Fall back to manually changing SCI_EN. ++ * Explicitly pass in whether sb is pinned or not. ++ ++ [ Ben Hutchings ] ++ * Prepare debconf templates for translation (Closes: #576758) ++ * [x86] Enable r8187se driver, previously named rtl8187se ++ ++ [ Aurelien Jarno ] ++ * mips/swarm: fix boot from IDE based media (Sebastian Andrzej Siewior) ++ (closes: #466977). ++ * mips/*: remove SND_* options, as they are already enabled in topconfig. ++ ++ -- maximilian attems Wed, 19 May 2010 17:06:13 +0200 ++ ++linux-2.6 (2.6.33-1~experimental.5) experimental; urgency=low ++ ++ [ Ian Campbell ] ++ * Include Xen hypervisor in reportbug "related to" list. ++ ++ [ maximilian attems] ++ * Add stable 2.6.33.2. ++ ++ [ Ben Hutchings ] ++ * [x86] Enable ramzswap driver (Closes: #573912) ++ * [x86] Re-enable rt2860sta and rt2870sta drivers which were accidentally ++ disabled when moving to Linux 2.6.33 (Closes: #576723) ++ * Add stable 2.6.33.3: ++ - ACPI: EC: Allow multibyte access to EC; fixes temperature monitoring ++ on some Dell laptops (Closes: #563313) ++ ++ [ Aurelien Jarno ] ++ * Add support for sh4 architecture, patch by Nobuhiro Iwamatsu ++ (Closes: #569034) ++ * [mips*/*malta] Remove options that are present in topconfig. ++ ++ -- maximilian attems Wed, 05 May 2010 16:38:53 +0200 ++ ++linux-2.6 (2.6.33-1~experimental.4) experimental; urgency=low ++ ++ [ Ben Hutchings ] ++ * Include aufs2, marked as staging (Closes: #573189) ++ * Remove /usr/include/drm from linux-libc-dev; let libdrm-dev provide it ++ again (Closes: #572067) ++ * [x86] Enable rtl8192su driver using external firmware ++ ++ [ maximilian attems] ++ * Add stable 2.6.33.1. ++ ++ -- maximilian attems Wed, 17 Mar 2010 18:13:53 +0100 ++ ++linux-2.6 (2.6.33-1~experimental.3) experimental; urgency=low ++ ++ [ Ben Hutchings ] ++ * Fix regexp for binNMU versions in modules/rules.include (Closes: #524632) ++ * linux-base: Fix bugs and improve libata transition code: ++ - Fix calls to disk_id_to_path (renamed to id_to_path) (Closes: #572283) ++ - Don't show empty list of devices to be relabelled ++ - Don't update udev CD rules unnecessarily ++ - Show the device paths to be added to udev CD rules ++ - Ignore nonexistent devices and properly handle devices of unknown ++ filesystem type (Closes: #572341, #572445) ++ - Don't accept empty filesystem labels as identifiers (Closes: #572438) ++ - For consistency with fresh installations, use or assign UUIDs rather ++ than labels where both are available (Closes: #572376) ++ - Replace CD/DVD/BD device names with udev-provided persistent aliases ++ - Fix update of boot device name for LILO and related loaders ++ - Update uswsusp resume device name ++ ++ -- maximilian attems Thu, 11 Mar 2010 05:58:02 +0100 ++ ++linux-2.6 (2.6.33-1~experimental.2) experimental; urgency=low ++ ++ [ Ben Hutchings ] ++ * Add missing debconf templates for linux-base (Closes: #571558) ++ * Fix libata transition code for GRUB 1 config (Closes: #571662) ++ ++ -- maximilian attems Sun, 28 Feb 2010 17:48:11 +0100 ++ ++linux-2.6 (2.6.33-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release: http://kernelnewbies.org/Linux_2_6_33 ++ ++ [ maximilian attems] ++ * [topconfig] set BLK_DEV_DRBD, DRM_NOUVEAU, DRM_NOUVEAU_BACKLIGHT, ++ DRM_VMWGFX, SENSORS_LM73, SENSORS_AMC682, SENSORS_LIS3_I2C, ++ SENSORS_MC13783_ADC, TOUCHSCREEN_DYNAPRO, TOUCHSCREEN_MC13783, ++ GIGASET_CAPI, LEDS_DAC124S085, LEDS_INTEL_SS4200, LEDS_INTEL_SS4200, ++ DVB_FIREDTV, DVB_USB_EC168, SOC_CAMERA_MT9T112, SOC_CAMERA_OV9640, ++ USB_GSPCA_PAC7302, USB_GSPCA_STV0680, AD525X_DPOT, CAN_MCP251X, ++ RT2800PCI, REGULATOR_MAX8660, RTC_DRV_BQ32K, RTC_DRV_MSM6242, ++ RTC_DRV_RP5C01, VMWARE_PVSCSI, SCSI_PM8001, WIMAX_IWMC3200_SDIO, ++ INPUT_SPARSEKMAP, SERIO_ALTERA_PS2, MANTIS_CORE, DVB_MANTIS, ++ DVB_HOPPER. ++ * [x86] set CS5535_MFGPT, SENSORS_K10TEMP, GEODE_WDT, MSI_WMI, ++ TOSHIBA_BT_RFKILL, ACPI_CMPC, CRYPTO_GHASH_CLMUL_NI_INTE. ++ ++ [ Ben Hutchings ] ++ * Use libata-based drivers for most PATA controllers (Closes: #444182): ++ - pata_triflex replaces triflex ++ - pata_atiixp replaces atiixp ++ - pata_ns87415 replaces ns87415 ++ - pata_sc1200 replaces sc1200 ++ - pata_cs5536 replaces cs5536 ++ - pata_amd replaces amd74xx ++ - pata_sis replaces sis5513 ++ - pata_rz1000 replaces rz1000 ++ - pata_efar replaces slc90e66 ++ - pata_pdc202xx_old replaces pdc202xx_old ++ - pata_pdc2027x replaces pdc202xx_new ++ - pata_cs5520 replaces cs5520 ++ - pata_cs5530 replaces cs5530 ++ - pata_cmd64x replaces cmd64x ++ - pata_sil680 replaces siimage ++ - pata_ali replaces alim15x3 ++ - pata_via replaces via82cxxx ++ - pata_serverworks replaces serverworks ++ - pata_artop replaces aec62xx ++ - pata_it821x replaces it821x ++ - ata_piix, pata_oldpiix, pata_mpiix mostly replace piix ++ - ata_generic, pata_ns87410, pata_netcell replace ide-pci-generic ++ * Add libata transition script ++ ++ -- maximilian attems Thu, 25 Feb 2010 15:21:38 +0100 ++ ++linux-2.6 (2.6.32-30) unstable; urgency=high ++ ++ [ Ben Hutchings ] ++ * mpt2sas: Fix incorrect scsi_dma_map error checking (Closes: #606968) ++ * Update Spanish debconf template translation (Omar Campagne, Javier ++ Fernández-Sanguino) (Really closes: #600694) ++ * intel-iommu: Force-disable IOMMU for iGFX on broken Cantiga revisions ++ (Closes: #607095) ++ * [powerpc] linux-base: Run ybin after updating yaboot.conf ++ (Closes: #607284) ++ * tehuti: Firmware filename is tehuti/bdx.bin ++ * iwlwifi: Reduce a failure-prone memory allocation (Closes: #599345) ++ * linux-base: Look for GRUB 1 configuration in both /boot/grub and ++ /boot/boot/grub (Closes: #607863) ++ * rt28x0: Add ieee80211_regdom module parameter mimicking cfg80211 as a ++ workaround for incorrect region code in NVRAM (Closes: #594561) ++ * btrfs: Require CAP_SYS_ADMIN for filesystem rebalance (Closes: #608185) ++ * [x86] dell-laptop: Enable for some newer Dell models ++ * r8169: Change RTL8111D/RTL8168D initialisation and firmware loading to ++ match upstream version (Closes: #596390 with firmware-realtek 0.28) ++ * Add stable 2.6.32.28: ++ - NFS: Fix panic after nfs_umount() ++ - usb-storage/libusual: Add support for Samsung YP-CP3 MP4 Player, ++ thanks to Vitaly Kuznetsov (Closes: #555835) ++ - bfa: Fix system crash when reading sysfs fc_host statistics ++ (CVE-2010-4343) ++ - IB/uverbs: Handle large number of entries in poll CQ (CVE-2010-4649) ++ - orinoco: Fix TKIP countermeasure behaviour (CVE-2010-4648) ++ - mm: Add security_file_mmap check to install_special_mapping ++ (CVE-2010-4346) ++ - sctp: Fix a race between ICMP protocol unreachable and connect() ++ (CVE-2010-4526) ++ - hvc_console: Fix race between hvc_close and hvc_remove (CVE-2010-2653) ++ (previously applied as an isolated fix in 2.6.32-25) ++ - fuse/cuse: Verify ioctl retries (CVE-2010-4650) ++ * [powerpc] Restore device tree source files to linux-image packages ++ (Closes: #609155) ++ ++ [ maximilian attems ] ++ * [openvz] Reenable NF_CONNTRACK_IPV6. (closes: #580507) ++ * cifs: fix another memleak, in cifs_root_iget. ++ * b43: Fix warning at drivers/mmc/core/core.c:237 in mmc_wait_for_cmd. ++ * drm/radeon/kms: MC vram map needs to be >= pci aperture size. ++ * drm/radeon/kms: make sure blit addr masks are 64 bit. ++ * drm/radeon/kms: fix handling of tex lookup disable in cs checker on r2xx. ++ * drm/i915: Free hardware status page on unload when physically mapped. ++ * drm/i915/overlay: Ensure that the reg_bo is in the GTT prior to writing. ++ * drm/radeon/kms/atom: set sane defaults in atombios_get_encoder_mode(). ++ * drm/radeon/kms: fix typos in disabled vbios code. ++ * drm/radeon/kms: add workaround for dce3 ddc line vbios bug. ++ * drm/radeon/kms: fix interlaced and doublescan handling. ++ * drm/i915/sdvo: Always add a 30ms delay to make SDVO TV detection reliable. ++ * wireless: b43: fix error path in SDIO. ++ * drm/radeon/kms: don't apply 7xx HDP flush workaround on AGP. ++ ++ [ Ian Campbell ] ++ * xen: backport TTM patches to use PCI API. Fixes PCIe GPU (specifically ++ Radeon and Nouveau) on Xen (Closes: #601341). ++ * xen: netback: drop SKBs which are GSO but do not have a partial ++ checksum set (Closes: #608144). ++ ++ [ dann frazier ] ++ * exec: make argv/envp memory visible to oom-killer (CVE-2010-4243) ++ * irda: Fix information leak in IRLMP_ENUMDEVICES (CVE-2010-4529) ++ * af_unix: limit unix_tot_inflight (CVE-2010-4249) ++ ++ [ Moritz Muehlenhoff ] ++ * net: ax25: fix information leak to userland (CVE-2010-3875) ++ * net: packet: fix information leak to userland (CVE-2010-3876) ++ * net: tipc: fix information leak to userland (CVE-2010-3877) ++ * inet_diag: Make sure we actually run the same bytecode we audited ++ (CVE-2010-3880) ++ * econet: Fix crash in aun_incoming() (CVE-2010-4342) ++ ++ -- Ben Hutchings Tue, 11 Jan 2011 05:42:11 +0000 ++ ++linux-2.6 (2.6.32-29) unstable; urgency=high ++ ++ [ Ben Hutchings ] ++ * megaraid_sas: Add support for 'entry-level' SAS controllers including ++ the 9240 family (Closes: #604083) ++ * tcp: Make TCP_MAXSEG minimum more correct (refinement of fix for ++ CVE-2010-4165) ++ * l2tp: Fix UDP socket reference count bugs in the pppol2tp driver ++ (Closes: #604748) ++ * USB: Retain device power/wakeup setting across reconfiguration; ++ don't enable remote wakeup by default (Closes: #605246) ++ * dm: Deal with merge_bvec_fn in component devices better (Closes: #604457) ++ * Update Spanish debconf template translation (Aaron H Farias Martinez) ++ (Closes: #600694) ++ * perf: Use libiberty, not libbfd, for symbol demangling ++ (Closes: #590226, #606050) ++ * [x86] Add support for Fintek hardware watchdogs (Closes: #601187) ++ - resource: Add shared I/O region support ++ - hwmon: f71882fg: Use a muxed resource lock for the Super I/O port ++ - watchdog: Add f71808e_wdt driver ++ * bcm5974: Add reporting of multitouch events (Closes: #605450) ++ * fusion: Set FUSION_MAX_SGE=128, the upstream default (Closes: #606096) ++ * Add stable 2.6.32.27: ++ - block: limit vec count in bio_kmalloc() and bio_alloc_map_data() ++ - block: take care not to overflow when calculating total iov length ++ - block: check for proper length of iov entries in blk_rq_map_user_iov() ++ (CVE-2010-4163) ++ - net: clear heap allocation for ETHTOOL_GRXCLSRLALL (CVE-2010-3861) ++ - asus_oled: fix up some sysfs attribute permissions ++ - ipc: initialize structure memory to zero for compat functions ++ (CVE-2010-4073) ++ - ipc/shm: fix information leak to userland (CVE-2010-4072) ++ - ipc/sem: sys_semctl: fix kernel stack information leakage (CVE-2010-4083) ++ - tty: prevent DOS in the flush_to_ldisc ++ - [x86] KVM: VMX: Fix host userspace gsbase corruption (Closes: #604956) ++ - KVM: VMX: fix vmx null pointer dereference on debug register access ++ (CVE-2010-0435) ++ - KVM: x86: fix information leak to userland (CVE-2010-3881) ++ - firewire/cdev: fix information leak ++ - firewire-core: fix an information leak ++ - firewire-ohci: fix buffer overflow in AR split packet handling ++ - bio: take care not overflow page count when mapping/copying user data ++ (CVE-2010-4162) ++ - sisusbvga: fix information leak to userland ++ - iowarrior: fix information leak to userland ++ - usb: core: fix information leak to userland ++ - usb-storage/sierra_ms: fix sysfs file attribute ++ - ueagle-atm: fix up some permissions on the sysfs files ++ - cypress_cy7c63: fix up some sysfs attribute permissions ++ - usbled: fix up some sysfs attribute permissions ++ - trancevibrator: fix up a sysfs attribute permission ++ - usbsevseg: fix up some sysfs attribute permissions ++ - do_exit(): make sure that we run with get_fs() == USER_DS (CVE-2010-4258) ++ - DECnet: don't leak uninitialized stack byte ++ - perf_events: Fix perf_counter_mmap() hook in mprotect() (CVE-2010-4169) ++ - frontier: fix up some sysfs attribute permissions ++ - net/sched: fix kernel information leak in act_police ++ - can-bcm: fix minor heap overflow (CVE-2010-3874) ++ - ivtvfb: prevent reading uninitialized stack memory (CVE-2010-4079) ++ - net/sched: fix some kernel information leaks ++ * TTY: Fix error return from tty_ldisc_open() (regression in 2.6.32.27) ++ * filter: make sure filters dont read uninitialized memory (CVE-2010-4158) ++ * posix-cpu-timers: workaround to suppress the problems with mt exec ++ (CVE-2010-4248) ++ ++ [ Ian Campbell ] ++ * xen: disable ACPI NUMA for PV guests and allow IRQ desc allocation on any ++ node (Closes: #603632) ++ * xen: handle potential time discontinuity on resume (Closes: #602273) ++ * xen: don't bother to stop other cpus on shutdown/reboot (Closes: #605448) ++ * xen: Add cpu hotplug support to prevent crash while parsing ACPI processor ++ tables (Closes: #602109) ++ ++ [ Martin Michlmayr ] ++ * Kirkwood: Add support for 6282 based QNAP devices. ++ ++ -- Ben Hutchings Fri, 10 Dec 2010 05:45:11 +0000 ++ ++linux-2.6 (2.6.32-28) unstable; urgency=high ++ ++ [ maximilian attems ] ++ * ipc: initialize structure memory to zero for shmctl. ++ * drm/i915: set DIDL using the ACPI video output device _ADR method return. ++ * images: Nuke modules.devname on removal. (closes: #590607) ++ * Newer Standards-Version 3.9.1 without changes. ++ * drm/ttm: Clear the ghost cpu_writers flag on ttm_buffer_object_transfer. ++ * [openvz] Update upstream patch to 2.6.32-dzhanibekov. ++ * [openvz] ubc: Fix orphan count checks after merge. ++ ++ [ Martin Michlmayr ] ++ * Update udlfb to 2.6.37: ++ - udlfb: minor cleanups ++ - udlfb: fix coding style issues ++ - udlfb: fbdev character read and write support ++ - udlfb: add DPMS support ++ - udlfb: remove metrics_misc sysfs attribute ++ - udlfb: revamp reference handling to insure successful shutdown ++ - udlfb: enhance EDID and mode handling support ++ - udlfb: fix big endian rendering error ++ - udlfb: support for writing backup EDID to sysfs file ++ - udlfb: add module options for console and fb_defio ++ - udlfb: fix incorrect fb_defio implementation for multiple framebuffers ++ - udlfb: fix checkpatch and style ++ ++ [ Ben Hutchings ] ++ * Update debconf template translations: ++ - Update Japanese (Nobuhiro Iwamatsu) (Closes: #602152) ++ - Update Catalan (Jordi Mallach) (Closes: #602520) ++ - Add Italian (Luca Bruno) (Closes: #602945) ++ * sunrpc: Fix NFS client over TCP hangs due to packet loss (Closes: #589945) ++ * brcm80211: Update to 2.6.37-rc1 ++ * [powerpc] ALSA: Fix headphone and line-out detection on PowerMac G4 DA ++ (Closes: #603419) ++ * [x86] snd-hda-codec-cirrus: Add quirks for IMac 27", MacBookPro 5,5 and 7,1 ++ * [x86] btusb: Add device IDs for MacBookPro 6,2 and 7,1 (Closes: #603651) ++ * [x86] applesmc: Add support for iMac 9,1 and MacBookPro 2,2, 5,3, 5,4, 6,* ++ and 7,* ++ * [x86] applesmc, bcm5974, btusb, HID, mbp_nvidia_bl, snd-hda-codec-cirrus: ++ Add support for MacBookAir 3,1 and 3,2 (Closes: #603395) ++ * [x86] mbp_nvidia_bl: Add support for MacBookPro 7,1 ++ * x25: Fix remote denial-of-service vulnerabilities: ++ - x25 accesses fields beyond end of packet ++ - memory corruption in X.25 facilities parsing (CVE-2010-3873) ++ - Prevent crashing when parsing bad X.25 facilities (CVE-2010-4164) ++ * tcp: Increase TCP_MAXSEG socket option minimum (CVE-2010-4165) ++ * rds: Fix integer overflow in RDS cmsg handling ++ * af_802154,decnet,econet,rds,x25: Disable auto-loading as mitigation ++ against local exploits. These protocol modules are not widely used ++ and can be explicitly loaded or aliased on systems where they are ++ wanted. ++ * atl1c: Add support for Atheros AR8151 and AR8152 (Closes: #599771) ++ * Add stable 2.6.32.26: ++ - synclink_cs: Fix information leak to userland ++ - bluetooth: Fix missing NULL check ++ - [x86] KVM: VMX: Fix host GDT.LIMIT corruption ++ - [x86] KVM: Fix fs/gs reload oops with invalid ldt (CVE-2010-3698) ++ - gdth: Fix integer overflow in ioctl (CVE-2010-4157) ++ * [x86] KVM: SVM: Fix wrong intercept masks for KVM_{GET,SET}_VCPU_EVENTS ++ on 32 bit, thanks to Philipp Matthias Hahn (Closes: #599507) ++ ++ [ dann frazier ] ++ * [vserver] Update patch to 2.6.32.25-vs2.3.0.36.29.6 ++ * add qlcnic driver ++ * econet: Avoid stack overflow w/ large msgiovlen (CVE-2010-3848) ++ * econet: disallow NULL remote addr for sendmsg() (CVE-2010-3849) ++ * econet: Add mising CAP_NET_ADMIN check in SIOCSIFADDR (CVE-2010-3850) ++ ++ -- Ben Hutchings Thu, 25 Nov 2010 01:20:50 +0000 ++ ++linux-2.6 (2.6.32-27) unstable; urgency=high ++ ++ * The "We'll Always Have Paris" release ++ ++ [ Ben Hutchings ] ++ * rndis_host: Restrict fix for #576929 to specific devices ++ (Closes: #589403, #600660) ++ * Add stable 2.6.32.25: ++ - rme9652: prevent reading uninitialized stack memory ++ (CVE-2010-4080, CVE-2010-4081) ++ - ocfs2: Don't walk off the end of fast symlinks ++ - ip: fix truesize mismatch in ip fragmentation ++ - net: clear heap allocations for privileged ethtool actions ++ - execve: setup_arg_pages: diagnose excessive argument size ++ - execve: improve interactivity with large arguments ++ - execve: make responsive to SIGKILL with large arguments ++ - rose: Fix signedness issues wrt. digi count. (CVE-2010-3310) ++ - ALSA: prevent heap corruption in snd_ctl_new() (CVE-2010-3442) ++ - setup_arg_pages: diagnose excessive argument size (CVE-2010-3858) ++ * btrfs: add a "df" ioctl for btrfs (Closes: #600190) ++ * Update debconf template translations: ++ - Add Catalan (Jordi Mallach) (Closes: #601146) ++ - Add Brazilian Portugese (Flamarion Jorge) (Closes: #601102) ++ - Update Vietnamese (Clytie Siddall) (Closes: #601534) ++ * phonet: device notifier only runs on initial namespace ++ (Really closes: #597904) ++ * net/socket: Limit sendto()/recvfrom() length (CVE-2010-1187) ++ [Original reference is incorrect; should be CVE-2010-3859.] ++ ++ [ Ian Campbell ] ++ * xen: import additional fixes for disabling netfront smartpoll mode ++ (Closes: #600992). ++ ++ [ dann frazier ] ++ * e1000e: Reset 82577/82578 PHY before first PHY register read ++ (Closes: #601017) ++ ++ [ Martin Michlmayr ] ++ * Kirkwood: reset PCIe unit on boot ++ * Kirkwood: restrict the scope of the PCIe reset workaround ++ ++ [ maximilian attems ] ++ * Update abi files, readd Xen as ABI stable. ++ * 2.6.33.stable-queue: drm/radeon: fix PCI ID 5657 to be an RV410. ++ * Add drm changes from 2.6.32.24+drm33.11: ++ - i915: return -EFAULT if copy_to_user fails. ++ - drm/i915: Prevent double dpms on ++ - drm: Only decouple the old_fb from the crtc is we call mode_set* ++ - drm/i915: Unset cursor if out-of-bounds upon mode change (v4) ++ - drm/i915,agp/intel: Add second set of PCI-IDs for B43 ++ * net: Limit socket I/O iovec total length to INT_MAX. (CVE-2010-1187) ++ [Original reference is incorrect; should be CVE-2010-3859.] ++ * numa: fix slab_node(MPOL_BIND). ++ ++ -- maximilian attems Sat, 30 Oct 2010 12:24:37 +0200 ++ ++linux-2.6 (2.6.32-26) unstable; urgency=high ++ ++ [ Ian Campbell ] ++ * xen: fix PVHVM hang at boot when Xen does not support vector callbacks. ++ * xen: fix race between PV drivers and xenstore initialisation which caused ++ breakage in drivers for both regular PV and PVHVM guests. ++ ++ [ maximilian attems ] ++ * [openvz] Enable ioprio. (closes: #596772) ++ Thanks Daniel Hahler ++ ++ [ Ben Hutchings ] ++ * [x86] radeon: Add quirks to make HP nx6125 and dv5000 laptops resume ++ (Closes: #583968) ++ * dm-crypt: Add 'plain64' IV; this avoids watermarking attacks that are ++ possible with 'plain' IV on devices larger than 2TB (Closes: #600384) ++ * [x86] ahci,ata_generic: let ata_generic handle new MBP w/ MCP89 ++ (Closes: #600305) ++ * debian/.../patches.py: Open files as needed, rather than all at once ++ (Closes: #600423) ++ * [openvz] printk: Handle global log buffer reallocation (Closes: #600299) ++ * debian/bin/test-patches: Restrict patches to featureset when building ++ with a featureset (thanks to Tim Small) ++ * sata_via: Delay on vt6420 when starting ATAPI DMA write (Closes: #488566) ++ * r6040: Fix various bugs in r6040_multicast_list() (Closes: #600155) ++ ++ [ dann frazier ] ++ * Force enable DMA on MBP w/ MCP 7,1 ++ * RDS sockets: remove unsafe kmap_atomic optimization (CVE-2010-3904) ++ * v4l: disable dangerous buggy compat function (CVE-2010-2963) ++ ++ -- dann frazier Tue, 19 Oct 2010 07:50:55 -0600 ++ ++linux-2.6 (2.6.32-25) unstable; urgency=high ++ ++ [ Ben Hutchings ] ++ * mmc: build fix: mmc_pm_notify is only available with CONFIG_PM=y ++ * Add stable 2.6.32.24 (trivial fix, already applied) ++ * ipg: Remove device claimed by dl2k from pci id table (Closes: #599021) ++ * linux-image: Include modules.order in image packages (Closes: #598518) ++ * [x86] isdn/i4l: Reenable ISDN4Linux drivers, but mark them as staging ++ (Closes: #588551) ++ - hisax: Disable device aliases that conflict with mISDN ++ * Update Danish debconf template translation (Joe Hansen) (Closes: #599457) ++ * [x86] KVM: SVM: Fix wrong intercept masks on 32 bit (Closes: #599507) ++ * e1000: fix Tx hangs by disabling 64-bit DMA (Closes: #518182) ++ * rt2x00: Fix calculation of required TX headroom (Closes: #599395) ++ * Add drm changes from 2.6.32.22+drm33.10: ++ - i915: Don't touch PORT_HOTPLUG_EN in intel_dp_detect() ++ - i915: Kill dangerous pending-flip debugging ++ - radeon: release AGP bridge at suspend ++ - radeon: initialize set_surface_reg for rs600 asic ++ * [x86] toshiba_acpi: Add full hotkey support (Closes: #599768) ++ ++ [ Stephen R. Marenka ] ++ * m68k: fix missing io macros. ++ * m68k: modular swim on mac. ++ * m68k: never build staging drivers on m68k. ++ * m68k: build in rtc class on atari. ++ ++ [ Ian Campbell ] ++ * xen: do not truncate machine address on gnttab_copy_grant_page hypercall ++ (Closes: #599089) ++ ++ [ dann frazier ] ++ * drm/i915: Sanity check pread/pwrite (CVE-2010-2962) ++ * drm/i915: Rephrase pwrite bounds checking to avoid any potential overflow ++ * GFS2: Fix writing to non-page aligned gfs2_quota structures (CVE-2010-1436) ++ * hvc_console: Fix race between hvc_close and hvc_remove (CVE-2010-2653) ++ * net sched: fix some kernel memory leaks (CVE-2010-2942) ++ * niu: Fix kernel buffer overflow for ETHTOOL_GRXCLSRLALL (CVE-2010-3084) ++ * rose: Fix signedness issues wrt. digi count (CVE-2010-3310) ++ * Fix pktcdvd ioctl dev_minor range check (CVE-2010-3437) ++ * ALSA: prevent heap corruption in snd_ctl_new() (CVE-2010-3442) ++ * net sched: fix kernel leak in act_police (CVE-2010-3477) ++ * sctp: Fix out-of-bounds reading in sctp_asoc_get_hmac() (CVE-2010-3705) ++ ++ -- dann frazier Thu, 14 Oct 2010 01:08:05 -0600 ++ ++linux-2.6 (2.6.32-24) unstable; urgency=high ++ ++ [ Ben Hutchings ] ++ * speakup: Update to match Debian package version 3.1.5.dfsg.1-1 ++ * scsi_dh_emc: Fix mode select request setup (Closes: #591540) ++ * snd-hda-codec-via: Fix syntax error when CONFIG_SND_HDA_POWER_SAVE is ++ disabled (Closes: #597043) ++ * Add stable 2.6.32.22: ++ - [vserver] Revert sched changes since they conflict. ++ * Recommend use of 'make deb-pkg' to build custom kernel packages ++ * [x86] Revert "i915: Blacklist i830, i845, i855 for KMS". The current X ++ driver (xserver-xorg-video-intel version 2.12.0+shadow-1) should work ++ properly with KMS on these chips. (Closes: #596453) ++ * phonet: Restrict to initial namespace (Closes: #597904) ++ * Add stable 2.6.32.23: ++ - serial/mos*: prevent reading uninitialized stack memory ++ - net: Fix oops from tcp_collapse() when using splice() ++ - rds: fix a leak of kernel memory ++ - hso: prevent reading uninitialized memory (CVE-2010-3298) ++ - cxgb3: prevent reading uninitialized stack memory (CVE-2010-3296) ++ - eql: prevent reading uninitialized stack memory (CVE-2010-3297) ++ - vt6655: fix buffer overflow ++ - net/llc: make opt unsigned in llc_ui_setsockopt() ++ - sisfb: prevent reading uninitialized stack memory ++ - aio: check for multiplication overflow in do_io_submit (CVE-2010-3067) ++ - xfs: prevent reading uninitialized stack memory (CVE-2010-3078) ++ - viafb: prevent reading uninitialized stack memory ++ - [hppa,ia64] mm: guard page for stacks that grow upwards (CVE-2010-2240) ++ - sctp: Do not reset the packet during sctp_packet_config() ++ (CVE-2010-3432) ++ * xen: Fix typo in xen_percpu_chip definition ++ * 3c59x: Remove incorrect locking (Closes: #598103) ++ * f71882fg: Add support for the f71889fg (Closes: #597820) ++ * drm/radeon: Fix regressions introduced in 2.6.34.3 (Closes: #597636) ++ * mmc: fix hangs related to mmc/sd card insert/removal during suspend/resume ++ (Closes: #598147) ++ ++ [ Martin Michlmayr ] ++ * ARM: update mach types. ++ * [armel/config.kirkwood] Enable MACH_DOCKSTAR. ++ ++ [ Ian Campbell ] ++ * [x86/xen] Disable netfront's smartpoll mode by default. (Closes: #596635) ++ ++ [ maximilian attems ] ++ * [openvz] Update upstream patch to 2.6.32-dyomin. ++ ++ -- Ben Hutchings Thu, 30 Sep 2010 00:46:16 +0100 ++ ++linux-2.6 (2.6.32-23) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * cgroupfs: create /sys/fs/cgroup to mount cgroupfs on (Closes: #595964) ++ * r8169: Fix MDIO timing (Closes: #583139; mistakenly reverted in 2.6.32-19) ++ * gro: Fix bogus gso_size on the first fraglist entry (Closes: #596802) ++ * vgaarb: Fix VGA arbiter to accept PCI domains other than 0 (from stable ++ 2.6.32.12; mistakenly omitted in 2.6.32-12) ++ ++ [ maximilian attems ] ++ * openvz: cfq-iosched: do not force idling for sync workload. ++ ++ [ Stephen R. Marenka ] ++ * m68k: switch to generic siginfo layout. ++ * m68k: NPTL support. ++ ++ [ dann frazier ] ++ * compat: Make compat_alloc_user_space() incorporate the access_ok() ++ (CVE-2010-3081) ++ * x86-64, compat (CVE-2010-3301): ++ - Retruncate rax after ia32 syscall entry tracing ++ - Test %rax for the syscall number, not %eax ++ * wireless extensions: fix kernel heap content leak (CVE-2010-2955) ++ * KEYS (CVE-2010-2960): ++ - Fix RCU no-lock warning in keyctl_session_to_parent() ++ - Fix bug in keyctl_session_to_parent() if parent has no session keyring ++ ++ -- dann frazier Fri, 17 Sep 2010 15:27:04 -0600 ++ ++linux-2.6 (2.6.32-22) unstable; urgency=low ++ ++ [ Ian Campbell ] ++ * xen: backport pvhvm drivers from upstream. ++ * Fixes/overrides for Lintian warnings: ++ - Add "(meta package)" to short description of linux-headers ++ metapackages, resolves empty-binary-package. ++ - Add dependency on ${misc:Depends} to all packages, resolves ++ debhelper-but-no-misc-depends. Required update to gencontrol.py to ++ augment rather than override headers_arch_depends read from templates. ++ - Override dbg-package-missing-depends for linux-image-*-dbg. It is not ++ necessary to install the kernel image package to use the dbg package ++ since the dbg package already contains a complete image with symbols. ++ ++ [ Ben Hutchings ] ++ * [x86/xen] Restore stack guard page (CVE-2010-2240) ++ * Add stable 2.6.32.21: ++ - ext4: consolidate in_range() definitions (CVE-2010-3015) ++ - mm: make the mlock() stack guard page checks stricter ++ (avoids regression for Xen tools; closes: 594756) ++ - [sparc] sunxvr500: Ignore secondary output PCI devices ++ (Closes: #594604) ++ - ocfs2: fix o2dlm dlm run purgelist (Closes: #593679) ++ - Avoid ABI change in mm ++ - Ignore ABI change in snd-emu10k1 ++ * Add drm changes from stable 2.6.34.6: ++ - drm: stop information leak of old kernel stack (CVE-2010-2803) ++ * rt2870sta: Add more device IDs from vendor drivers ++ * rt2860sta, rt2870sta: Enable channels 12-14 (Closes: #594561) ++ * SCSI/mptsas: fix hangs caused by ATA pass-through (Closes: #594690) ++ * sky2: Apply fixes and new hardware support from 2.6.33-2.6.35 ++ (Closes: #571526) ++ * postinst: Really warn users on upgrade if the current configuration may ++ rely on running a default boot loader. ++ * input: add compat support for sysfs and /proc capabilities output ++ (Closes: #579017) ++ * snd-hda-intel: Add support for VIA V1708S, VT1718S, VT1828S, VT2020, ++ VT1716S, VT2002P, VT1812, VT1818S ++ * hwmon/w83627ehf: Add support for W83667HG-B ++ * 3c59x: Fix deadlock in vortex_error() (Closes: #595554) ++ * [x86] paravirt: Add a global synchronization point for pvclock (from ++ 2.6.32.16; reverted due to a regression which was addressed in 2.6.32.19) ++ * sched, cputime: Introduce thread_group_times() (from 2.6.32.19; reverted ++ due to the potential ABI change which we now carefully avoid) ++ * net/{tcp,udp,llc,sctp,tipc,x25}: Add limit for socket backlog ++ (Closes: #592187) ++ * tun: Don't add sysfs attributes to devices without sysfs directories ++ (Closes: #594845) ++ * [x86] Add brcm80211 driver for Broadcom 802.11n wireless network ++ controllers ++ * r8169: Remove MODULE_FIRMWARE declarations since the firmware is ++ non-essential and we do not distribute it ++ * [x86] HPET: unmap unused I/O space ++ * ipheth: add support for iPhone 4 ++ * ipheth: remove incorrect devtype of WWAN ++ * ALSA: emux: Add trivial compat ioctl handler (Closes: #596478) ++ * hostap_pci: set dev->base_addr during probe (Closes: #595802) ++ * ethtool: allow non-netadmin to query settings (see #520724) ++ * ACPI: add boot option acpi=copy_dsdt to fix corrupt DSDT, and enable this ++ automatically for known-bad Toshiba models (Closes: #596709) ++ ++ [ Bastian Blank ] ++ * Use Breaks instead of Conflicts. ++ ++ [ Aurelien Jarno ] ++ * [mips,mipsel] Fix computation of DMA flags from device's ++ coherent_dma_mask. ++ ++ [ Martin Michlmayr ] ++ * Add some patches from the Orion tree: ++ - OpenRD: Enable SD/UART selection for serial port 1 ++ - kirkwood: Unbreak PCIe I/O port ++ - Kirkwood: support for Seagate DockStar ++ ++ [ dann frazier ] ++ * netxen_nic: add support for loading unified firmware images ++ * irda: Correctly clean up self->ias_obj on irda_bind() failure. ++ (CVE-2010-2954) ++ ++ [ maximilian attems ] ++ * [powerpc] Enable WINDFARM_PM121. (closes: #596515) ++ Thanks Étienne BERSAC ++ * nouveau: disable acceleration on NVA3/NVA5/NVA8 by default. ++ * openvz: disable KSM. Thanks Dietmar Maurer . ++ (closes: #585864) ++ * Update openvz patch to d38b56fd0dca. ++ * openvz: enalbe modular VZ_EVENT. ++ ++ -- maximilian attems Tue, 14 Sep 2010 14:17:11 +0200 ++ ++linux-2.6 (2.6.32-21) unstable; urgency=high ++ ++ [ Ben Hutchings ] ++ * Add stable 2.6.32.19: ++ - ext4: Make sure the MOVE_EXT ioctl can't overwrite append-only files ++ (CVE-2010-2066) ++ - mm: keep a guard page below a grow-down stack segment (CVE-2010-2240) ++ (not applied to xen featureset) ++ - md/raid10: fix deadlock with unaligned read during resync ++ (Closes: #591415) ++ - Revert "sched, cputime: Introduce thread_group_times()" which would ++ result in an ABI change ++ * Add stable 2.6.32.20: ++ - Fix regressions introduced by original fix for CVE-2010-2240 ++ * Add drm and other relevant changes from stable 2.6.34.4 ++ * Add 'breaks' relation from image packages to boot loader packages that ++ do not install required hooks (Closes: #593683) ++ * [x86] i915: Blacklist i830, i845, i855 for KMS ++ (Closes: #568207, #582105, #593432, #593507) ++ ++ [ Bastian Blank ] ++ * Update Xen patch. ++ - Notify Xen on crash. ++ - Several blktap fixes. ++ ++ [ Ritesh Raj Sarraf ] ++ * Add .gnu_debuglink information into kernel modules (Closes: #555549) ++ ++ [ Ian Campbell ] ++ * [x86/xen] temporarily remove stack guard page, it breaks the xen ++ toolstack. ++ ++ [ Aurelien Jarno ] ++ * [mips,mipsel] Fix 64-bit atomics. ++ ++ -- Ben Hutchings Wed, 25 Aug 2010 01:06:18 +0100 ++ ++linux-2.6 (2.6.32-20) unstable; urgency=low ++ ++ [ Moritz Muehlenhoff ] ++ * Backport XVR1000 driver (Closes: #574243) ++ ++ [ Ben Hutchings ] ++ * Add stable 2.6.32.18: ++ - CIFS: Fix compile error with __init in cifs_init_dns_resolver() ++ definition (FTBFS for most architectures) ++ - GFS2: rename causes kernel Oops (CVE-2010-2798) ++ - xfs: prevent swapext from operating on write-only files ++ (CVE-2010-2226) ++ * Update debconf template translations: ++ - Swedish (Martin Bagge) (Closes: #592045) ++ - German (Holger Wansing) (Closes: #592226) ++ * [i386/openvz-686] Remove AMD Geode LX and VIA C3 "Nehemiah" from the ++ list of supported processors; they do not implement PAE ++ * V4L/DVB: Add Elgato EyeTV Diversity to dibcom driver (Closes: #591710) ++ * [s390] dasd: use correct label location for diag fba disks ++ (Closes: #582281) ++ * Add drm changes from stable 2.6.34.2 (thanks to Stefan Bader) and ++ 2.6.34.3 ++ * drm/i915: disable FBC when more than one pipe is active ++ (Closes: #589077) ++ * IB/ipath: Fix probe failure path (Closes: #579393) ++ * ext4: fix freeze deadlock under IO (regression introduced in 2.6.32.17) ++ * xen: Completely disable use of XSAVE (Closes: #592428) ++ ++ [ Martin Michlmayr ] ++ * [armel/orion5x] Add a missing #include to fix a build issue. ++ * [armel/kirkwood, armel/orion5x] Build-in support for more devices. ++ ++ [ dann frazier ] ++ * can: add limit for nframes and clean up signed/unsigned variables ++ ++ -- Ben Hutchings Thu, 12 Aug 2010 03:26:39 +0100 ++ ++linux-2.6 (2.6.32-19) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * inotify send IN_UNMOUNT events. ++ * inotify fix oneshot support. ++ ++ [ Ben Hutchings ] ++ * linux-base: Remove dependency on libapt-pkg-perl (Closes: #589996) ++ * pata_pdc202xx_old: Fix UDMA mode for PDC2024x and PDC2026x controllers ++ (Closes: #590532) ++ * Update debconf template translations: ++ - Czech (Michal Simunek) (Closes: #590546) ++ - Portugese (Américo Monteiro) (Closes: #590557) ++ - French (David Prévot) (Closes: #591149) ++ - Russian (Yuri Kozlov) (Closes: #591241) ++ * Add stable 2.6.32.17: ++ - ethtool: Fix potential kernel buffer overflow in ETHTOOL_GRXCLSRLALL ++ (CVE-2010-2478) ++ - GFS2: Fix up system xattrs (CVE-2010-2525) ++ - Revert ABI changes in firmware_class and ssb ++ - Ignore ABI changes in acpi_processor, hostap and jbd2 ++ * Add drm changes from stable 2.6.33.7: ++ - drm/i915: Enable low-power render writes on GEN3 hardware (915, 945, ++ G33 and Atom "Pineview") (Closes: #590193, maybe others) ++ * [i386/xen-686] Remove AMD Geode LX and VIA C3 "Nehemiah" from the list ++ of supported processors; they do not implement PAE ++ * [x86] Add samsung-laptop driver ++ ++ [ dann frazier ] ++ * [ia64] Fix crash when gcore reads gate area (Closes: #588574) ++ ++ [ Bastian Blank ] ++ * Update Xen patch. ++ - Ignore ABI changes. ++ ++ -- Ben Hutchings Thu, 05 Aug 2010 02:43:19 +0100 ++ ++linux-2.6 (2.6.32-18) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * iwlwifi: Allocate pages for RX buffers, reducing the probability of ++ allocation failure (Closes: #580124) ++ * postinst: Remove support for 'default' boot loaders. Warn users on ++ upgrade if the current configuration may rely on this. ++ * rt2860sta, rt2870sta: Apply changes from Linux 2.6.33 and 2.6.34 ++ - rt2860sta: Fix WPA(2)PSK issue when group cipher of AP is WEP40 ++ or WEP104 (Closes: #574766) ++ * rt3090sta: Replace with rt2860sta (Closes: #588863) ++ * [i386/686] Remove AMD K6 from the list of supported processors; it ++ does not implement the CMOV instruction ++ * drm/i915: Add 'reclaimable' to i915 self-reclaimable page allocations ++ (really closes: #534422, we hope) ++ * Revert "x86, paravirt: Add a global synchronization point for pvclock", ++ included in stable 2.6.32.16 (Closes: #588426) ++ * 3c59x: Fix call to mdio_sync() with the wrong argument (Closes: #589989) ++ ++ [ Martin Michlmayr ] ++ * Add some patches from the Orion tree, including support for Marvell's ++ Armada 300 (88F6282): ++ - Kirkwood: update MPP definition. ++ - Kirkwood: fix HP t5325 after updating MPP definitions ++ - leds: leds-gpio: Change blink_set callback to be able to turn off ++ blinking ++ - net/phy/marvell: Expose IDs and flags in a .h and add dns323 LEDs ++ setup flag ++ - orion5x: Base support for DNS-323 rev C1 ++ - orion5x: Fix soft-reset for some platforms ++ - mtd: orion/kirkwood: add RnB line support to orion mtd driver ++ - mtd: kirkwood: allow machines to register RnB callback ++ - Kirkwood: add support for rev A1 of the 88f6192 and 88f6180 chips ++ - Kirkwood: Add support for 88f6282 ++ - PCI: add platform private data to pci_sys_data ++ - Kirkwood: add support for PCIe1 ++ - Kirkwood: more factorization of the PCIe init code ++ ++ [ maximilian attems ] ++ * sched: Fix over-scheduling bug. ++ ++ -- Ben Hutchings Fri, 23 Jul 2010 03:48:08 +0100 ++ ++linux-2.6 (2.6.32-17) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * agp: add no warn since we have a fallback to vmalloc paths. ++ ++ [ Ben Hutchings ] ++ * linux-tools: Fix build for hppa and do not attempt to build for ++ architectures where perf events are not available (Closes: #588409) ++ * linux-tools: Add build-dependency on binutils-dev to enable symbol ++ demangling in perf ++ * drm/i915: Fix memory corruption on resume from hibernation ++ (Closes: #534422) ++ ++ -- Ben Hutchings Sat, 10 Jul 2010 16:40:38 +0100 ++ ++linux-2.6 (2.6.32-16) unstable; urgency=low ++ ++ [ dann frazier ] ++ * [hppa] clear floating point exception flag on SIGFPE signal ++ (Closes: #559406) ++ ++ [ Ben Hutchings ] ++ * Add stable 2.6.32.15 ++ * Add mantis and hopper DVB drivers with mb86a16 and tda665x DVB ++ front-ends, backported by Bjørn Mork (Closes: #577264) ++ * Build inet_lro as a module ++ * [sparc] Enable CONFIG_FB_XVR500, CONFIG_FB_XVR2500 (Closes: #508108) ++ * Update Spanish debconf templates, thanks to Omar Campagne ++ (Closes: #580538) ++ * Revert "Add EC path for Thinkpad X100."; it is incomplete and broken ++ * sctp: fix append error cause to ERROR chunk correctly (regression due ++ to fix for CVE-2010-1173) ++ * [powerpc] Enable pata_amd driver, replacing amd74xx ++ * eeepc-laptop: Disable wireless hotplug on more models where the ++ controller is not at the expected address (Closes: #576199) ++ * [mips] Fix boot from ATA hard drives (Closes: #584784): ++ - Set io_map_base for several PCI bridges lacking it ++ - Replace per-platform built-in IDE drivers with libata-based drivers ++ - Enable BLK_DEV_SD as built-in on all platforms ++ * Revert "vlan/macvlan: propagate transmission state to upper layers" ++ (Closes: #585770) ++ * linux-base: Don't identify LVM2 PVs by UUID (Closes: #585852) ++ * usb-serial: Add generic USB WWAN code, backported by Mark Hymers ++ (Closes: #585661) ++ - option, qcserial: Use generic USB WWAN code ++ - qcserial: Add support for Qualcomm Gobi 2000 devices ++ * radeon: Fix MacBook Pro connector quirk (Closes: #585943) ++ * r8169: Fix MDIO timing (Closes: #583139) ++ * Move NEWS to linux-latest-2.6 (Closes: #586401) ++ * 3c59x: Change locking to avoid use of disable_irq() (Closes: #586967) ++ * Enable IPv6 support for IPVS (IP_VS_IPV6) (Closes: #584549) ++ * Revert "tpm: autoload tpm_tis based on system PnP IDs", included in ++ stable 2.6.32.12 (Closes: #584273) ++ * linux-base: If the disk ID update process fails, give the user a ++ chance to retry or change their answers (Closes: #585609) ++ * asix: fix setting mac address for AX88772 (Closes: #587580) ++ * ipv6: Clamp reported valid_lft to a minimum of 0 (Closes: #514644) ++ * ipv6: Use interface max_desync_factor instead of static default ++ (Closes: #514646) ++ * Add stable 2.6.32.16: ++ - Fixes CVE-2010-1641, CVE-2010-1187, CVE-2010-1148, CVE-2010-1173 ++ and CVE-2010-2071 ++ - libata: disable ATAPI AN by default (Closes: #582737, #582903) ++ * Add drm changes from stable 2.6.33.6 ++ * [ia64, powerpc, sparc, x86] Enable KPROBES and KRETPROBES ++ (Closes: #584130) ++ * r8192s_usb: Fix various bugs: ++ - Check for skb allocation failure in 2 more places ++ - Update LED control code ++ - Clean up in case of an error in module initialisation ++ - Rename and remove proc directories correctly if an interface is ++ not called wlan0 (Closes: #582972) ++ - Correct device ID table (Closes: #584945, #587985) ++ * Add r8192u_usb driver ++ * Add linux-tools- package containing the perf tool ++ (Closes: #548715) ++ * Enable USB_SERIAL_TI (Closes: #588096) and USB_SERIAL_WHITEHEAT ++ ++ [ Aurelien Jarno ] ++ * [sh4] optimize runtime disabling of trapped I/O. ++ * [mips] backport mips/swarm: fix M3 TLB exception handler. ++ ++ [ Moritz Muehlenhoff ] ++ * Enable X86 board specific fixups for reboot (Closes: #536537) ++ ++ [ Martin Michlmayr ] ++ * OpenRD-Base: revert patch "allow SD/UART1 selection" since it ++ never made it upstream. ++ * ARM: update mach types. ++ * Add support for OpenRD-Ultimate. ++ * QNAP TS-11x/TS-21x: Add MPP36 (RAM) and MPP44 (board ID). ++ * Add support for the HP t5325 Thin Client. ++ * m25p80: Add support for Macronix 25L8005. ++ * Add framebuffer driver for XGI chipsets. ++ * [armel/kirkwood] Enable FB_XGI and FRAMEBUFFER_CONSOLE. ++ * [armel] Make MOUSE_PS2 modular. ++ * [armel] Build INPUT_UINPUT for all flavours. ++ * Update Marvell CESA (mv_cesa) driver (Closes: #585790): ++ - Invoke the user callback from a softirq context ++ - Remove compiler warning in mv_cesa driver ++ - Fix situation where the dest sglist is organized differently than... ++ - Fix situations where the src sglist spans more data than the reques... ++ - Enqueue generic async requests ++ - Rename a variable to a more suitable name ++ - Execute some code via function pointers rathr than direct calls ++ - Make the copy-back of data optional ++ - Support processing of data from previous requests ++ - Add sha1 and hmac(sha1) async hash drivers ++ * Update DisplayLink (udlfb) driver: ++ - add dynamic modeset support ++ - checkpatch cleanup ++ - reorganize function order ++ - pre-allocated urb list helpers ++ - clean up function naming ++ - Add functions to expose sysfs metrics and controls ++ - Rework startup and teardown to fix race conditions ++ - improved rendering performance ++ - Support for fbdev mmap clients (defio) ++ - explicit dependencies and warnings ++ - remove printk and small cleanup ++ * [armel/kirkwood] Enable FB_UDL. ++ * [armel] Disable PARPORT_PC (Closes: #588164) ++ ++ [ Bastian Blank ] ++ * Disable mISDN support for NETJet cards. The driver binds a generic PCI ++ bridge. ++ * Disable ISDN4Linux drivers. ++ ++ [ maximilian attems] ++ * Update openvz patch to 5fd638726a69. ++ ++ -- Ben Hutchings Mon, 05 Jul 2010 22:13:33 +0100 ++ ++linux-2.6 (2.6.32-15) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * [hppa] Ignore ABI change caused by disabling CONFIG_IDE_TIMINGS ++ * [powerpc] Fix unnecessary ABI change ++ ++ [ Bastian Blank ] ++ * xen: Fix crash in netback. ++ ++ -- Ben Hutchings Tue, 01 Jun 2010 01:31:05 +0100 ++ ++linux-2.6 (2.6.32-14) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * [ia64] Hardcode the output of the scripts under arch/ia64/scripts so ++ that we can build out-of-tree modules correctly (refresh and re-add ++ dropped patch) (Closes: #392592) ++ * vlan/macvlan: propagate transmission state to upper layers ++ * macvlan: add GRO bit to features mask ++ * macvlan: allow multiple driver backends ++ * Add macvtap driver (Closes: #568755) ++ * [ia64] Enable SGI SN support and mspec driver (Closes: #582224) ++ * iwlwifi: Disable QoS when connected to a non-QoS-capable AP ++ (Closes: #578262) ++ * [x86] Disable e_powersaver cpufreq driver as unsafe. It has already ++ been blacklisted by cpufrequtils. The acpi-cpufreq driver can be used ++ instead on some VIA C7 systems. (Closes: #566208) ++ * nouveau: Fix fbcon corruption with font width not divisible by 8 ++ (Closes: #583162) ++ * [amd64] ext4: Fix compat EXT4_IOC_ADD_GROUP (used by online resize) ++ * Install debug kernel image in /usr/lib/debug/boot (Closes: #582810) ++ * net: sysfs: Check for null ethtool_ops before getting speed/duplex ++ * Add stable 2.6.32.14: ++ - [hppa] Revert "parisc: Set PCI CLS early in boot.", erroneously ++ included in 2.6.32.13 causing FTBFS ++ - btrfs: check for read permission on src file in the clone ioctl ++ (CVE-2010-1636) ++ ++ [ Bastian Blank ] ++ * Update Xen patch. ++ - Fix checksum offloading in netback. (closes: #583366) ++ ++ [ maximilian attems] ++ * Add drm changes from stable 2.6.33.5: ++ - i915: Disable FBC on 915GM and 945GM (Closes: #582427) ++ * Update openvz patch to e7399c239fad. ++ ++ [ Martin Michlmayr ] ++ * QNAP TS-419P: Export GPIO indicating jumper setting of JP1. ++ ++ -- Ben Hutchings Sat, 29 May 2010 00:32:44 +0100 ++ ++linux-2.6 (2.6.32-13) unstable; urgency=low ++ ++ [ Frederik Schueler ] ++ * sparc: Fix use of uid16_t and gid16_t in asm/stat.h ++ ++ [ Moritz Muehlenhoff ] ++ * Enable tomoyo (Closes: #562486) ++ ++ [ maximilian attems] ++ * backport KVM: x86: Extend KVM_SET_VCPU_EVENTS with selective updates. ++ (closes: #580652) ++ * KEYS: find_keyring_by_name() can gain access to a freed keyring. ++ CVE-2010-1437 ++ * hppa, sparc, powerpc disable BLK_DEV_CMD64X. ++ * topconfig enable PATA_CMD64X. (closes: #580799) ++ * x86: Disable CRYPTO_AES_NI_INTEL as it causes boot failures on T410. ++ * Add stable 2.6.32.13: ++ - [SCSI] Enable retries for SYNCRONIZE_CACHE commands to fix I/O error. ++ - [SCSI] Retry commands with UNIT_ATTENTION sense codes to fix ext3/ext4 ++ I/O errors. ++ - [SCSI] skip sense logging for some ATA PASS-THROUGH cdbs ++ (Closes: #578129) ++ - raid6: fix recovery performance regression. ++ - raid456: Enable error-correction on singly-degraded RAID6 ++ (Closes: #581392) ++ - r8169: fix broken register writes (Closes: #407217, #573007) ++ - V4L/DVB: budget: Fix crash in case of failure to attach frontend ++ (Closes: #575207) ++ * drm/edid: Fix 1024x768@85Hz. ++ ++ [ Ben Hutchings ] ++ * linux-base: Fix typo in disk relabelling code (Closes: #580467) ++ * linux-base: Don't quote boot device name in elilo.conf ++ (Closes: #580710; works-around: #581173) ++ * rtl8192su: Add IDs for several more devices (Closes: #580740) ++ * Add drm and sfc changes from stable 2.6.33.4 ++ * Improve workaround for HPAs (Host Protected Areas) overlapping ++ partitions, thanks to Tejun Heo: ++ - SCSI/libata: Disable HPA if it overlaps a partition (Closes: #572618) ++ - buffer: Make invalidate_bdev() drain all percpu LRU add caches ++ - block: Rescan partition tables after HPA is disabled ++ - libata: Disable HPA if it is only enabled after suspend ++ * V4L/DVB: budget: Select correct frontend drivers (Closes: #575223) ++ * 3c503: Fix IRQ probing (Closes: #566522) ++ * sis-agp: Remove SIS 760, handled by amd64-agp ++ * amd64-agp: Probe unknown AGP devices the right way (Closes: #548090) ++ ++ [ Aurelien Jarno ] ++ * mips/swarm: fix boot from IDE based media (Sebastian Andrzej Siewior) ++ (closes: #466977). ++ * backport mips/swarm: fix M3 TLB exception handler. ++ [This patch was actually reverted and never applied in version 2.6.32-13] ++ * backport MIPS FPU emulator: allow Cause bits of FCSR to be writeable ++ by ctc1. (closes: #580602). ++ * mips/swarm: enable adm* hwmon drivers. ++ * backport Input: Add support of Synaptics Clickpad device (Closes: #572842) ++ ++ [ Bastian Blank ] ++ * Fix symlinks in several packages. ++ * Update Xen patch. ++ * [amd64, i386/{686-bigmem,openvz-686,vserver-686-bigmem,xen-686}] ++ Build debugging symbols. (closes: #365349) ++ * Ignore crypto ABI changes. ++ ++ [ Martin Michlmayr ] ++ * Backport GuruPlug support. ++ ++ [ Christian Perrier ] ++ * Update debconf templates: ++ - English revised by the debian-l10n-english team as part of the Smith ++ review project (Closes: #578349) ++ - Vietnamese (Clytie Siddall) (Closes: #579234) ++ - German (Holger Wansing) (Closes: #579864) ++ - Russian (Yuri Kozlov) (Closes: #578994) ++ - Estonian (mihkel) (Closes: #579019) ++ - Czech (Michal Simunek) (Closes: #579268) ++ - Swedish (Martin Bagge) (Closes: #579308) ++ - French (David Prévot) (Closes: #579763) ++ - Spanish (Omar Campagne) (Closes: #580538) ++ - Portuguese (Américo Monteiro) (Closes: #577227) ++ - Japanese (Kenshi Muto) (Closes: #580855) ++ - Danish (Joe Hansen) (Closes: #580915) ++ - Czech (Michal Simunek) (Closes: #581399) ++ ++ -- maximilian attems Mon, 17 May 2010 15:29:27 +0200 ++ ++linux-2.6 (2.6.32-12) unstable; urgency=low ++ ++ * The "Microwave Background" release ++ ++ [ Ben Hutchings ] ++ * Prepare debconf templates for translation. (closes: #576758) ++ * [x86] PCI/forcedeth: Disable MSI for MCP55 on P5N32-E SLI ++ (Closes: #552299) ++ * phylib: Fix typo in bcm63xx PHY driver table ++ * linux-base: Fix bugs and improve libata transition code: ++ - Fix scope of _system() function (Closes: #576925) ++ - Fix case where a file may wrongly be listed as automatically converted ++ (Closes: #577047) ++ - Check device IDs in mdadm.conf rather than assuming it needs manual ++ conversion ++ - Use vol_id if available since the version of blkid in lenny does not ++ support the output format we need (Closes: #576608) ++ - Fix missing line breaks in updated crypttab (Closes: #577735) ++ * i915: Stop trying to use ACPI lid status to determine LVDS connection ++ (Closes: #577724) ++ * forcedeth: Fix hardware version check for TX bug workaround ++ (Closes: #572201) ++ * rndis_host: Poll status channel before control channel (Closes: #576929) ++ * megaraid_sas: Fix copying of sense data for 32-bit management tools on ++ 64-bit kernel (Closes: #578398) ++ * Add ipheth driver for iPhone tethering ++ * virtio_net: Make delayed refill more reliable (Closes: #576838) ++ ++ [ maximilian attems] ++ * [ia64] Built in fbcon. ++ * Update openvz patch to c05f95fcb04e. (closes: #574598) ++ * Reenable nouveau autoloading. ++ * reiserfs: Fix permissions on .reiserfs_priv. CVE-2010-1146 ++ * libata,ata_piix: detect and clear spurious IRQs. ++ * libata/SCSI: fix locking around blk_abort_request(). ++ * topconfig enable NET_DROP_MONITOR. (closes: #578568) ++ * Add stable 2.6.32.12: ++ - ACPI: EC: Allow multibyte access to EC; fixes temperature monitoring ++ on some Dell laptops (Closes: #563313) ++ - [x86] KVM: disable paravirt mmu reporting (Closes: #573071) ++ - thinkpad-acpi: lock down video output state access (Closes: #565790) ++ - xfs update (closes: #579410) ++ * Add drm changes from stable 2.6.33.3: ++ - drm/radeon: R300 AD only has one quad pipe (Closes: #575681) ++ * libata: Fix accesses at LBA28 boundary (old bug, but nasty) (v2) ++ * Add EC path for Thinkpad X100. ++ * Bump ABI to 5, apply: ++ - hrtimer: Tune hrtimer_interrupt hang logic ++ * Add libata TRIM support. ++ * Backport radeon r800 modesetting support. ++ * drm/radeon/kms: further spread spectrum fixes. ++ * Backport p54 fixes. ++ * net: export device speed and duplex via sysfs. ++ * postrm: rm modules.softdep. (closes: #579175) ++ * Backport KVM: Xen PV-on-HVM guest support. ++ * Backport KVM: x86: Add KVM_GET/SET_VCPU_EVENTS. ++ * hugetlb: fix infinite loop in get_futex_key() when backed by huge pages ++ * ext4: Issue the discard operation *before* releasing the blocks to be ++ reused. ++ * libiscsi: regression: fix header digest errors. ++ * Revert module.c and module.h changes from -stable update. ++ ++ [ dann frazier ] ++ * Add DRBD backport ++ * sctp: Fix skb_over_panic resulting from multiple invalid parameter ++ errors (CVE-2010-1173) ++ * [CIFS] Allow null nd (as nfs server uses) on create (CVE-2010-1148) ++ * tipc: Fix oops on send prior to entering networked mode (CVE-2010-1187) ++ * [powerpc] KGDB: don't needlessly skip PAGE_USER test for Fsl booke ++ Note: KGDB is not currently enabled in debian builds (CVE-2010-1446) ++ ++ [ Aurelien Jarno ] ++ * [sh4] Add a sh7751r flavour. ++ * [mips/*malta] Remove options that are present in topconfig. ++ ++ [ Martin Michlmayr ] ++ * dns323-setup.c: fix WARN() when booting (Arnaud Patard). ++ * mips: enable PATA platform on SWARM and LITTLESUR (Sebastian Andrzej ++ Siewior). ++ * [mips/sb1-bcm91250a] Enable PATA_PLATFORM. ++ ++ [ Bastian Blank ] ++ * Update Xen patch. ++ ++ -- Ben Hutchings Sat, 01 May 2010 02:58:31 +0100 ++ ++linux-2.6 (2.6.32-11) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * [sparc] Provide io{read,write}{16,32}be() (Closes: #574421) ++ * Use libata-based drivers for most PATA controllers on all architectures ++ (previously applied only to x86) ++ * linux-base: Fix bugs and improve libata transition code: ++ - Handle duplicates in /etc/udev/rules.d/70-persistent-cd.rules ++ (Closes: #574630) ++ - Always attempt conversion if $DEBCONF_RECONFIGURE is set ++ - Never attempt conversion during a fresh installation (Closes: #576243) ++ - Convert disk IDs in crypttab (Closes: #575056) ++ - Redirect stdin and stdout of child processes to avoid interfering with ++ debconf (Closes: #574987) ++ - Report when hdparm.conf or mdadm.conf may need to be updated ++ (Closes: #576442) ++ - Where a device has both a UUID and a label, prefer to identify it by ++ UUID, consistent with fresh installations ++ - Do not use device labels including certain unsafe characters ++ (Closes: #576537) ++ * iwlwifi: Fix repeated warnings about tfds_in_queue (Closes: #574526) ++ * eeepc-laptop: Disable CPU speed control on 701 and 702 since it can ++ cause the system to hang (Closes: #559578) ++ * eeepc-laptop: Disable wireless hotplug on 1005HA, 1201N and 1005PE ++ since it disconnects the wrong device (Closes: #573607) ++ * linux-headers-*: Support postinst hooks in /etc/kernel/header_postinst.d, ++ thanks to Michael Gilbert (Closes: #569724) ++ * rt2860sta: Fix argument to linux_pci_unmap_single() (Closes: #575726) ++ * nouveau: nv50: Implement ctxprog/state generation ++ * phylib: Support PHY module autoloading (Closes: #553024) ++ * [x86] Add ramzswap driver (Closes: #573912) ++ ++ [ maximilian attems] ++ * [alpha, hppa] Disable oprofile as tracing code is unsupported here. ++ (closes: #574368) ++ * Update openvz patch to 14a9729fab67. (closes: #574598, #575189) ++ * [x86]: Disable FB_INTEL. (closes: #447575, #503766, #574401) ++ * ssb: do not read SPROM if it does not exist. ++ * ssb: Avoid null pointer dereference by aboves. ++ * Add stable 2.6.32.11. ++ - MIPS: Cleanup forgotten label_module_alloc in tlbex.c (Closes: #571305) ++ - ath5k: fix setup for CAB queue (closes: #576213) ++ - NFS: Prevent another deadlock in nfs_release_page() (Closes: #574348) ++ * Revert to keep ABI: ++ - hrtimer: Tune hrtimer_interrupt hang logic ++ ++ [ Moritz Muehlenhoff ] ++ * Add support for sh4 architecture, patch by Nobuhiro Iwamatsu ++ (Closes: #569034) ++ ++ [ Bastian Blank ] ++ * Update Xen patch. ++ - Fix free interrupt problem on uni-processor machines. ++ ++ [ Ian Campbell ] ++ * Include Xen hypervisor in reportbug "related to" list. ++ ++ -- maximilian attems Mon, 05 Apr 2010 20:31:15 +0200 ++ ++linux-2.6 (2.6.32-10) unstable; urgency=low ++ ++ * The "Big Bang" release ++ ++ [ maximilian attems] ++ * tcp: fix ICMP-RTO war. ++ * Add stable 2.6.32.10. ++ - net/via-rhine: Fix scheduling while atomic bugs (closes: #549606) ++ - HID: remove TENX iBuddy from blacklist (Closes: #551312) ++ - USB: SIS USB2VGA DRIVER: support KAIREN's USB VGA adaptor ++ USB20SVGA-MB-PLUS (Closes: #565857) ++ * Bump ABI to 4. ++ * [x86] Add openvz flavour. ++ - adds ppp support (closes: #550975) ++ * Prevent nouveau from autoloading until xserver-xorg-video-nouveau lands. ++ ++ [ Moritz Muehlenhoff ] ++ * Enable CONFIG_KEYS_DEBUG_PROC_KEYS (Closes: #400932) ++ * Amend README.source with documentation on how to generate a ++ source tree with all patches applied (Closes: #509156) ++ * Document needed packages for preparatory packaging ++ steps (Closes: #548028) ++ ++ [ Aurelien Jarno ] ++ * Fix signal stack alignement on sparc64 (Closes: #569797) ++ ++ [ Bastian Blank ] ++ * Add support for Xen dom0 into its featureset. ++ (Closes: #499745, #503857, #504805, #505545, #506118, #507785, #509085, ++ #509733, #511963, #513835, #514511, #516223, #516374, #516635, #517048, ++ #519586, #520702, #522452, #524571, #524596, #526695, #533132, #533432, ++ #534880, #534978, #541227, #542299, #542614, #543489, #544525, #548345, ++ #554564, #554621, #559175, #559634) ++ * [alpha, amd64, i386, amd64, powerpc] Make all AGP driver built-in to ++ workaround race-condition between DRM and AGP. ++ ++ [ Ben Hutchings ] ++ * drm: Apply all changes from 2.6.33 and 2.6.33.1: ++ - Add nouveau driver ++ - i915: Fix disappearing mouse pointer (Closes: #551330) ++ - i915: Restore video overlay support (Closes: #560033) ++ - i915: Fix DDC on some systems by clearing BIOS GMBUS (Closes: #567747) ++ - radeon: Enable KMS support ++ * qla2xxx: Disable MSI/MSI-X on some chips or as selected by module parameter ++ (Closes: #572322) ++ - MSI is disabled on QLA24xx chips other than QLA2432 (MSI-X already was) ++ - MSI-X is disabled if qlx2enablemsix=2 ++ - MSI and MSI-X are disabled if qlx2enablemsix=0 ++ * [sparc64] Make prom entry spinlock NMI safe (Closes: #572442) ++ * firmware: Correct copyright information and add source for CIS files ++ * Fix first line of kernel-doc for a few functions so that they get valid ++ manual pages ++ * Remove /usr/include/drm from linux-libc-dev; let libdrm-dev provide it ++ again ++ * [x86] Enable rtl8192su driver using external firmware ++ * [x86] Use libata-based drivers for most PATA controllers (Closes: #444182): ++ - pata_triflex replaces triflex ++ - pata_atiixp replaces atiixp ++ - pata_ns87415 replaces ns87415 ++ - pata_sc1200 replaces sc1200 ++ - pata_cs5536 replaces cs5536 ++ - pata_amd replaces amd74xx ++ - pata_sis replaces sis5513 ++ - pata_rz1000 replaces rz1000 ++ - pata_efar replaces slc90e66 ++ - pata_pdc202xx_old replaces pdc202xx_old ++ - pata_pdc2027x replaces pdc202xx_new ++ - pata_cs5520 replaces cs5520 ++ - pata_cs5530 replaces cs5530 ++ - pata_cmd64x replaces cmd64x ++ - pata_sil680 replaces siimage ++ - pata_ali replaces alim15x3 ++ - pata_via replaces via82cxxx ++ - pata_serverworks replaces serverworks ++ - pata_artop replaces aec62xx ++ - pata_it821x replaces it821x ++ - ata_piix, pata_oldpiix, pata_mpiix mostly replace piix ++ - ata_generic, pata_ns87410, pata_netcell replace ide-pci-generic ++ * linux-base: Add libata transition script ++ * Hide sensitive information when including network configuration in bug ++ reports and running a different kernel version ++ ++ [ Martin Michlmayr ] ++ * Add some ARM patches from git: ++ - Update mach types ++ - eSATA SheevaPlug: basic board support ++ - eSATA SheevaPlug: configure SoC SATA interface ++ - eSATA SheevaPlug: correlate MPP to SD CD and SD WP ++ * [armel/kirkwood] Enable MACH_ESATA_SHEEVAPLUG. ++ ++ -- maximilian attems Tue, 16 Mar 2010 23:39:05 +0100 ++ ++linux-2.6 (2.6.32-9) unstable; urgency=high ++ ++ [ Ben Hutchings ] ++ * Do not build obsolete lgs8gl5 driver ++ * [x86] Enable USB IP drivers (Closes: #568903) ++ * Ignore failure of lsusb when gathering information for bug reports ++ (Closes: #569725) ++ * macvlan: Add bridge, VEPA and private modes (Closes: #568756) ++ * [sparc] sunxvr500: Support Intergraph graphics chips again ++ (Closes: #508108) ++ * sfc: Apply fixes from 2.6.33 ++ * ath9k: Add support for AR2427 ++ * fs/exec.c: fix initial stack reservation (regression in 2.6.32.9) ++ ++ [ maximilian attems] ++ * Postinst don't refercence k-p related manpage. (closes: #542208) ++ * Postinst only write kernel-img.conf for palo boxes. ++ * Enable VT_HW_CONSOLE_BINDING for unbinding efifb. (closes: #569314) ++ * hwmon: Add driver for VIA CPU core temperature. ++ * wireless: report reasonable bitrate for MCS rates through wext. ++ * efifb: fix framebuffer handoff. (bugzilla.k.o #15151) ++ * Add stable 2.6.32.9: ++ - drm/i915: Fix DDC on some systems by clearing BIOS GMBUS setup. ++ (closes: #567747) ++ - futex: Handle futex value corruption gracefully. (CVE-2010-0623) ++ - futex_lock_pi() key refcnt fix. (CVE-2010-0623) ++ - Staging: fix rtl8187se compilation errors with mac80211. ++ (closes: #566726) ++ * r8169 patch for rx length check errors. (CVE-2009-4537) ++ * vgaarb: fix incorrect dereference of userspace pointer. ++ * Bump ABI to 3. ++ * drm/i915: give up on 8xx lid status. ++ * vgaarb: fix "target=default" passing. ++ * drm/radeon: block ability for userspace app to trash 0 page and beyond. ++ (closes: #550562) ++ ++ [ Bastian Blank ] ++ * Restrict access to sensitive SysRq keys by default. ++ * debian/rules.real: Install arch specific scripts. ++ ++ [ Moritz Muehlenhoff ] ++ * Set source format to 1.0 ++ ++ [ Martin Michlmayr ] ++ * [armel/iop32x] Enable ARCH_IQ80321 and ARCH_IQ31244 (Thanks Arnaud ++ Patard). ++ * [armel/kirkwood] Disable MTD_NAND_VERIFY_WRITE to avoid errors ++ with ubifs on OpenRD (Thanks Gert Doering) (Closes: #570407) ++ * OpenRD-Base: allow SD/UART1 selection (Closes: #571019) ++ * D-Link DNS-323 revision A1: implement power LED (Closes: 503172). ++ ++ -- maximilian attems Wed, 24 Feb 2010 17:06:27 +0100 ++ ++linux-2.6 (2.6.32-8) unstable; urgency=high ++ ++ [ Bastian Blank ] ++ * Don't let default compiler flags escape into build. ++ ++ [ dann frazier ] ++ * KVM: PIT: control word is write-only (CVE-2010-0309) ++ * Fix potential crash with sys_move_pages (CVE-2010-0415) ++ ++ [ Ben Hutchings ] ++ * Build lgs8gxx driver along with cxusb (Closes: #568414) ++ * Revert incorrect change to powerpc clocksource setup (Closes: #568457) ++ * Add stable release 2.6.32.8: ++ - Remove TIF_ABI_PENDING bit from x86, sparc & powerpc, fixing ++ 32-bit userland/64-bit kernel breakage (Closes: #568416) ++ - connector: Delete buggy notification code. (CVE-2010-0410) ++ * [x86] KVM: Add IOPL/CPL checks to emulator, to prevent privilege ++ escalation within a guest. (CVE-2010-0298, CVE-2010-0306) ++ ++ [ Martin Michlmayr ] ++ * Implement power-off for D-Link DNS-323 rev B1 and fix the blinking ++ power LED (Erik Benada) (Closes: #503172). ++ ++ [ Aurelien Jarno ] ++ * Enable CONFIG_FB_CIRRUS and CONFIG_LOGO on 4kc-malta and 5kc-malta. ++ ++ -- Ben Hutchings Thu, 11 Feb 2010 02:17:17 +0000 ++ ++linux-2.6 (2.6.32-7) unstable; urgency=low ++ ++ [ maximilian attems] ++ * [x86] Disable deprecated X86_CPU_DEBUG, causes boot failures. ++ * Newer Standards-Version 3.8.4 without changes. ++ ++ [ Ben Hutchings ] ++ * clocksource/events: Fix fallout of generic code changes ++ (Closes: #568030) ++ * Set ABI to 2. ++ ++ [ dann frazier ] ++ * Disable FUNCTION_TRACER due to performance/build issues. ++ (Closes: #568025) ++ * Split 'flush_old_exec' into two functions (CVE-2010-0307) ++ ++ -- dann frazier Wed, 03 Feb 2010 18:35:21 -0700 ++ ++linux-2.6 (2.6.32-6) unstable; urgency=high ++ ++ [ Ben Hutchings ] ++ * Documentation/3c509: document ethtool support (Closes: #564743) ++ * Add MODULE_FIRMWARE declarations to several drivers that lacked them ++ * [x86] Update rt2860sta/rt2870sta firmware loader patch ++ - Accept 8K versions of rt2870.bin ++ - Fix hang on resume ++ * [x86] Enable rt3090sta using firmware loader ++ * Add stable release 2.6.32.4: ++ - untangle the do_mremap() mess (CVE-2010-0291) ++ - fasync: split 'fasync_helper()' into separate add/remove functions ++ (CVE-2009-4141) ++ - kernel/signal.c: fix kernel information leak with print-fatal-signals=1 ++ (CVE-2010-0003) ++ - netfilter: ebtables: enforce CAP_NET_ADMIN (CVE-2010-0007) ++ - quota: Fix dquot_transfer for filesystems different from ext4 ++ (Closes: #566532) ++ - audit: Fix memory management bugs (Closes: #562815) ++ + fix braindamage in audit_tree.c untag_chunk() ++ + fix more leaks in audit_tree.c tag_chunk() ++ - ipv6: skb_dst() can be NULL in ipv6_hop_jumbo(). (CVE-2010-0006) ++ - Fix DMA mapping for i915 driver (Closes: #558237, #567352) ++ + drm: remove address mask param for drm_pci_alloc() ++ + agp/intel-agp: Clear entire GTT on startup ++ * e1000,e1000e: Discard all fragments of received over-length packets ++ (CVE-2009-4536, CVE-2009-4538) ++ * Enable the '686' configuration options in '686-vserver' packages and ++ the '686-bigmem' configuration options in '686-bigmem-vserver' packages ++ (Closes: #566213) ++ * Add stable release 2.6.32.5: ++ - inotify: do not reuse watch descriptors (Closes: #561880) ++ - megaraid_sas: remove sysfs poll_mode_io world writeable permissions ++ (CVE-2009-3939) (Closes: #562975) ++ * Force distribution=UNRELEASED in debian/bin/test-patches so that it ++ works in released source packages ++ * Add stable release 2.6.32.6 ++ * postinst: Enable escape sequences in debconf notes (Closes: #566539) ++ * Add 3w-sas driver for LSI 3ware 9750 SAS controllers ++ * aufs2: Update to snapshot from 2010-01-25 (Closes: #567391) ++ * cdc_ether: Do not set link down initially; not all devices send link ++ change interrupts (Closes: #567689) ++ * Add stable release 2.6.32.7: ++ - clockevent: Don't remove broadcast device on halt or CPU hotplug ++ (Closes: #566547) ++ * sfc: Apply fixes from 2.6.33-rc{5,6} ++ * Set ABI to 1. ++ ++ [ Ian Campbell ] ++ * xen: Enable up to 32G of guest memory on i386. ++ ++ [ Julien Cristau ] ++ * drm/i915: disable powersave by default (closes: #564807) ++ ++ [ Bastian Blank ] ++ * Enable all NCP file system options. ++ * [amd64] Make AGP support again built-in to fullfill the not completely ++ documented dependency with GART IOMMU support. (closes: #561552) ++ * Enable dynamic minor allocations for ALSA, DVB and USB. (closes: #510593) ++ ++ [ maximilian attems ] ++ * [topconfig] set MEMORY_FAILURE, 9P_FSCACHE, INFINIBAND_IPOIB_CM ++ (closes: #565494), ITCO_VENDOR_SUPPORT (closes: #525232), PCIEASPM ++ (closes: #545417), HWPOISON_INJECT. ++ * Enable easier debugging of Power Managment code. (closes: #478315) ++ * Pass `DEB_MAINT_PARAMS' to hook scripts. (closes: #563161) ++ * Enable more mobile IPv6 needs. (closes: #528834) ++ ++ [ dann frazier ] ++ * [vserver] explicitly disable CFS_HARD_LIMITS ++ * Enable FUNCTION_TRACER and STACK_TRACER (Closes: #563847) ++ ++ -- Ben Hutchings Sun, 31 Jan 2010 23:09:28 +0000 ++ ++linux-2.6 (2.6.32-5) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * sfc: Apply fixes from 2.6.33-rc3 ++ * ath5k: Fix eeprom checksum check for custom sized eeproms ++ (Closes: #563136) ++ ++ [ maximilian attems ] ++ * topconfig unset USB_ISP1362_HCD FTBFS on armel and useless. ++ (closes: #564156) ++ * topconfig set PATA_ATP867X, PATA_RDC, SND_CS5535AUDIO, PM_RUNTIME, ++ ATA_VERBOSE_ERROR, RTC_DRV_WM831X, RTC_DRV_PCF2123, RTC_DRV_AB3100, ++ SND_HDA_PATCH_LOADER, DEVTMPFS (closes: #560040). ++ * [x86] set RTL8192E, TOPSTAR_LAPTOP, I2C_SCMI. ++ * Explicitly disable diverse staging drivers. ++ ++ -- Ben Hutchings Sun, 10 Jan 2010 03:22:23 +0000 ++ ++linux-2.6 (2.6.32-4) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * Correct comments referring to dpkg --print-installation-architecture ++ in maintainer scripts (Closes: #558077) ++ * modules: Skip empty sections when exporting section notes ++ (Closes: #563036) ++ * via-velocity: Give RX descriptors to the NIC later on open or MTU change ++ (Closes: #508527) ++ * dmfe/tulip: Let dmfe handle DM910x except for SPARC on-board chips ++ (Closes: #515533) ++ * Add stable release 2.6.32.3: ++ - ath5k: fix SWI calibration interrupt storm (may fix #563466) ++ - iwl3945: disable power save (Closes: #563693) ++ - rt2x00: Disable powersaving for rt61pci and rt2800pci (may fix #561087) ++ ++ [ maximilian attems ] ++ * topconfig set CAN_EMS_USB, BT_MRVL, BT_MRVL_SDIO, BE2ISCSI, SCSI_PMCRAID, ++ SCSI_BFA_FC, USB_GL860, USB_GSPCA_JEILINJ, I2C_SI4713, RADIO_SI4713, ++ RADIO_SI470X, DVB_USB_FRIIO, EDAC_I3200, SENSORS_TMP421, SENSORS_WM8350, ++ SBC_FITPC2_WATCHDOG, TOUCHSCREEN_MCS5000, UIO_PCI_GENERIC, KSZ8842, ++ KS8851, KS8851_MLL, MISDN_AVMFRITZ, MISDN_SPEEDFAX, MISDN_INFINEON, ++ MISDN_W6692, MISDN_NETJET, INPUT_WINBOND_CIR, BATTERY_DS2782, MFD_WM831X, ++ MFD_MC13783, MTD_SST25L, TOUCHSCREEN_USB_E2I, INPUT_WM831X_ON, ++ SENSORS_WM831X, WM831X_WATCHDOG, AB3100_OTP, REGULATOR_WM831X, ++ REGULATOR_MC13783, REGULATOR_AB3100, REGULATOR_TPS65023, ++ REGULATOR_TPS6507X, VIDEO_SAA7164, DVB_PT1, BACKLIGHT_WM831X, ++ SND_HDA_CODEC_CIRRUS, USB_ISP1362_HCD, LEDS_WM831X_STATUS, ++ MTD_ONENAND_GENERIC, B43_SDIO, B43_PHY_LP, KEYBOARD_ADP5588, QT2160, ++ KEYBOARD_LM8323, KEYBOARD_MAX7359, KEYBOARD_OPENCORES, MOUSE_PS2_SENTELIC, ++ WM831X_POWER. ++ * [x86] set ACPI_POWER_METER, ACPI_PROCESSOR_AGGREGATOR, SFI, ++ EDAC_DECODE_MCE. ++ * Set MOUSE_PS2_ELANTECH for various EeePc. (closes: #522920) ++ ++ [ dann frazier ] ++ * Fix vserver build on ia64 (Closes: #563356) ++ * Fix vserver build on s390 (Closes: #563355) ++ ++ [ Martin Michlmayr ] ++ * Report model information on armel when filing a bug. ++ * ARM: Add an earlyprintk debug console (Catalin Marinas) ++ * [armel] Enable EARLY_PRINTK. ++ ++ -- Ben Hutchings Thu, 07 Jan 2010 03:33:39 +0000 ++ ++linux-2.6 (2.6.32-3) unstable; urgency=high ++ ++ * The "Not a Suitable Christmas Present" release ++ ++ [ Martin Michlmayr ] ++ * [armel/orion5x] Build MTD_CFI_AMDSTD into the kernel again since ++ it's needed on the D-Link DNS-323 (thanks Manuel Roeder). ++ (Closes: #562205) ++ ++ [ dann frazier ] ++ * Input: ALPS - add support for touchpads with 4-directional button ++ * Input: ALPS - add interleaved protocol support (Dell E6x00 series) ++ (Closes: #561589) ++ * Re-enable vserver ++ ++ [ Ben Hutchings ] ++ * sfc: Apply changes from 2.6.33-rc1 adding support for SFC9000 family ++ * Add stable release 2.6.32.2: ++ - KVM: x86 emulator: limit instructions to 15 bytes (CVE-2009-4031) ++ - hfs: fix a potential buffer overflow (CVE-2009-4020) ++ * radeon: fix crtc vblank update for r600 (regression in 2.6.32.2) ++ * ia64: Include header in ; fixes ++ FTBFS ++ * r8169: Allow RTL8168D v1 and v2 to be used without firmware files ++ (Closes: #561309) ++ * Enable vmxnet3 (VMware guest paravirt net driver) (Closes: #562046) ++ ++ -- Ben Hutchings Thu, 24 Dec 2009 04:28:55 +0000 ++ ++linux-2.6 (2.6.32-2) unstable; urgency=high ++ ++ [ Bastian Blank ] ++ * Allow memory hot-add and -remove if possible. ++ * Enable USB suspend. ++ * Enable kernel samepage merging. (closes: #558200) ++ * [s390] ++ - Enable SECCOMP. ++ - Enable z/VM Watchdog Timer. ++ ++ [ Moritz Muehlenhoff ] ++ * Disable cryptoloop (Closes: #559755) ++ * Initial work on a README.source file as suggested by current policy ++ ++ [ Ben Hutchings ] ++ * aufs2: Update to snapshot from 2009-12-05 ++ * postinst: Fix failure paths in check for missing firmware ++ (Closes: #560263) ++ * atl1c: Fix system hang when link drops (Closes: #559577) ++ * netfilter: xtables: fix conntrack match v1 ipt-save output ++ (Closes: #556587) ++ ++ [ Aurelien Jarno ] ++ * Add support for the sparc64 architecture. ++ ++ [ dann frazier ] ++ * Add stable release 2.6.32.1: ++ - ext4: Fix double-free of blocks with EXT4_IOC_MOVE_EXT (CVE-2009-4306) ++ - ext4: avoid divide by zero when trying to mount a corrupted file system ++ (CVE-2009-4307) ++ - ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT (CVE-2009-4131) ++ ++ -- Ben Hutchings Wed, 16 Dec 2009 21:42:49 +0000 ++ ++linux-2.6 (2.6.32-1) unstable; urgency=low ++ ++ * New upstream release candidate: ++ - Fixes wifi with rt73usb (Closes: #555640) ++ ++ [ Martin Michlmayr ] ++ * [armel/kirkwood] Turn on USB_SUSPEND (on the request of a SheevaPlug ++ user). ++ * [mips/4kc-malta, mips/5kc-malta] Compile USB as a module rather than ++ into the kernel. ++ ++ [ Bastian Blank ] ++ * Enable PCI_MSI. ++ * [powerpc] Properly enable Apple PMU battery. ++ * [mips/mipsel] Drop remaining OSS drivers. ++ * [powerpc] Enable PCIe support. ++ * Move contents of linux-support package to /usr/share. ++ * Make linux-patch package depend against python. ++ * Use python-support instead of python-central. ++ * Always enable software watchdog support. ++ * Always enable complete USB mass storage support. ++ * [amd64, powerpc, sparc] Build USB support as module. ++ * [amd64] Build AGP support as module. ++ * Always enable dummy net driver support. ++ * Drop linux-tree package, it have no users left. ++ ++ [ Ben Hutchings ] ++ * Re-enable accidentally omitted drivers, thanks to Uwe Kleine-König ++ (Closes: #558011): ++ - Atheros wireless drivers (ar9170, ath5k, ath9k) ++ - TI wl12xx wireless drivers (wl1251_spi, wl1251_sdio and wl1271 ++ replace wl12xx) ++ - Silicon Labs Si470x FM Radio Receiver driver (radio-usb-si470x) ++ * Add 'removable' option to the mmc module. Setting this to 0 causes ++ MMC/SD cards to be assumed non-removable, and filesystems on them ++ will remain mounted over a suspend/resume cycle. (Closes: #504391) ++ * Add MODULE_FIRMWARE declarations to many drivers that lacked them, so ++ that missing firmware will be reported automatically during upgrades ++ * atl1e: Remove broken implementation of TSO for TCP/IPv6 ++ (Closes: #558426) and allow other hardware offloads to be disabled in ++ case they are also buggy ++ * usbnet: Set link down initially for drivers that update link state ++ (Closes: #444043) ++ * aufs2: Update to snapshot from 2009-11-29 ++ * i915: Enable auto-loading even though CONFIG_DRM_I915_KMS is not set ++ ++ [ dann frazier ] ++ * mac80211 (CVE-2009-4026, CVE-2009-4027): ++ - fix two remote exploits ++ - fix spurious delBA handling ++ ++ -- Bastian Blank Sun, 06 Dec 2009 18:17:39 +0100 ++ ++linux-2.6 (2.6.32~rc8-1~experimental.1) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * New upstream release candidate. ++ - slip: Clean up create and destroy (Closes: #408635) ++ - signal: Fix alternate signal stack check (Closes: #544905) ++ * README.Debian: Add brief information about building specific binary ++ packages (Closes: #546182) ++ * lgs8gxx: Remove firmware for lgs8g75 and use request_firmware() to ++ load it ++ * r8169: Remove firmware for RTL8168D v1 and v2 and use ++ request_firmware() to load it ++ * DocBook: Fix build breakage ++ * Hide WPA authentication parameters and comments when including network ++ configuration in bug reports ++ ++ [ Bastian Blank ] ++ * [mips] Don't force EMBEDDED on. ++ * [sparc] Don't builtin Ext2 support. ++ * Enable PERF_EVENTS, EVENT_PROFILE, CRYPTO_VMAC, CRYPTO_GHASH, TREE_RCU. ++ * Use SLUB as default SLAB allocator. ++ ++ [ Martin Michlmayr ] ++ * [armel] Make some options modular (since there's no reason for them ++ to be built in): FTL, NFTL, MTD_CFI_AMDSTD, MTD_CFI_STAA. ++ * [armel/orion5x, armel/kirkwood] Enable ISDN (requested by Markus ++ Krebs). ++ * Add patch from Albin Tonnerre to add HAVE_KERNEL_LZMA to arm. ++ * [armel] Enable KERNEL_LZMA, i.e. compress kernels with lzma to get ++ much better compression. ++ * [armel] Re-enable options that were turned off recently because of ++ size constraints: DEBUG_USER, DEBUG_KERNEL, BOOT_TRACER, ARM_UNWIND, ++ BLK_DEV_IO_TRACE and SECURITY_SELINUX. ++ ++ [ maximilian attems ] ++ * Simplify postinst nuke reverse symlinks handling. Patch from ++ Sebastian Andrzej Siewior . ++ ++ -- Bastian Blank Sat, 21 Nov 2009 21:41:45 +0100 ++ ++linux-2.6 (2.6.31-2) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * [armel/orion5x, armel/kirkwood] Make sure VGA_CONSOLE is disabled, ++ otherwise the kernel won't boot. ++ * [armel/kirkwood] Enable CRYPTO_DEV_MV_CESA (Closes: #552270). ++ * [armel/kirkwood, armel/orion5x] Enable ORION_WATCHDOG (the ++ name of the config variable changed). ++ * Add OpenRD-Client support again. ++ * Add QNAP TS-41x support. ++ * [armel/orion5x, armel/kirkwood] Enable ISDN (requested by Markus ++ Krebs). ++ * Fix a build failure of the ISDN hisax elsa driver on ARM. ++ * mips: fix build of vmlinux.lds (Closes: #552422). ++ ++ [ Ben Hutchings ] ++ * postinst: Accept absolute paths in modules.dep generated by the ++ lenny version of module-init-tools (Closes: #552610) ++ * aufs2: Remove incorrect static assertion (Closes: #554120) ++ * Add stable release 2.6.31.6: ++ - fs: pipe.c null pointer dereference (CVE-2009-3547) ++ - KEYS: get_instantiation_keyring() should inc the keyring refcount ++ in all cases (CVE-2009-3624) ++ - netlink: fix typo in initialization (CVE-2009-3612) ++ * Undo PCMCIA ABI change in 2.6.31.6 ++ * Hide wireless keys and wake-on-LAN password when including network ++ configuration in bug reports ++ * Add Geode LX/NX to list of 686-class processors ++ ++ [ Bastian Blank ] ++ * [powerpc] Remove SMP warning from PowerMac cpufreq (Closes: #554124) ++ ++ [ maximilian Attems ] ++ * Really fix making a debian kernel installable without kernel-img.conf. ++ Thanks for patch to Sebastian Andrzej Siewior . ++ (closes: #555093). ++ ++ -- Ben Hutchings Sun, 15 Nov 2009 18:47:49 +0000 ++ ++linux-2.6 (2.6.31-1) unstable; urgency=low ++ ++ [ Ben Hutchings ] ++ * Include aufs2, marked as staging (Closes: #541828) ++ * Include speakup modules under staging ++ * Add stable release 2.6.31.5 ++ * [x86_64] Enable NUMA_EMU (Closes: #541389) ++ ++ [ Martin Michlmayr ] ++ * CPUidle: always return with interrupts enabled. ++ * [armel/orion5x, armel/kirkwood] Enable FB since some Kirkwood ++ machines have a VGA chip (e.g. OpenRD-Client) and because it's ++ possible to use a DisplayLink USB virtual graphics adapter. ++ ++ [ maximilian attems ] ++ * [alpha] Disable SND_MIXART, causes gcc ICE. ++ * [x86] Enable modular X86_MCE_INJECT. ++ * [x86_32] Set LSM_MMAP_MIN_ADDR to zero to unbreak dosemu and 16-bit Wine, ++ ia64 and x86_64 to 65536 otherwise default to 32768. ++ * Unset UEVENT_HELPER_PATH to save some boot cycles. ++ ++ [ Bastian Blank ] ++ * Set ABI to 1. ++ * Enable Apple PMU battery. (closes: #544264) ++ ++ -- Bastian Blank Sat, 24 Oct 2009 19:17:30 +0200 ++ ++linux-2.6 (2.6.31-1~experimental.2) experimental; urgency=low ++ ++ [ Ben Hutchings ] ++ * Include more information in bug reports: ++ - Model information ++ - Firmware package status ++ - Network configuration and status (optional) ++ - USB device list ++ * nfs: Avoid overrun when copying client IP address string ++ (Closes: #549002) ++ * Add support for DEB_BUILD_OPTIONS=parallel=N (Closes: #458560) ++ * sfc: Fix initial link state ++ * Improve package descriptions ++ - Clarify the differences between i386 flavours (Closes: #414690) ++ - Simplify wording of the description template ++ * Add stable release 2.6.31.3 ++ * Remove /usr/include/scsi from linux-libc-dev; these headers are ++ provided by libc6-dev (Closes: #550130) ++ * Remove dummy dot-files from linux-libc-dev ++ * hfsplus: Refuse to mount volumes larger than 2TB, which may otherwise ++ be corrupted (Closes: #550010) ++ * Add stable release 2.6.31.4 ++ - x86: Don't leak 64-bit kernel register values to 32-bit processes ++ (CVE-2009-2910) ++ - appletalk: Fix skb leak when ipddp interface is not loaded ++ (CVE-2009-2903) ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.31.2 ++ - ax25: Fix signed comparison in the sockopt handler (CVE-2009-2909) ++ - PM / yenta: Fix cardbus suspend/resume regression (Closes: #522828) ++ ++ [ dann frazier ] ++ * [sparc] build zImage by default, fixes build ++ * [ia64] Fix call to elilo in postinst ++ ++ -- maximilian attems Mon, 12 Oct 2009 23:54:52 +0200 ++ ++linux-2.6 (2.6.31-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release. ++ - Support for W83627DHG-P (closes: #535646). ++ - Restore MAC address and MTU change operations on Orinoco and others ++ (Closes: #536455) ++ - Remove incorrect ACPI blacklisting of ASUS P4B266 mainboards ++ (Closes: #525625) ++ - atl1c fixes for Eee PC model 1005HA-H. (closes: #538410) ++ - parisc64-smp boot fix on J5600. (closes: #539369) ++ - parisc: Fix GOT overflow during module load on 64bit kernel ++ (closes: #539378) ++ - xfs: fix freeing of inodes not yet added to the inode cache ++ (Closes: #527517) ++ - IPv6: add "disable" module parameter support to ipv6.ko. ++ (closes: #542470) ++ - IPv6: avoid wraparound for expired preferred lifetime ++ (Closes: #518710) ++ - Fixes lockups with older dual-CPU machines (Closes: #542551) ++ - x86, pat: Allow ISA memory range uncacheable mapping requests ++ (Closes: #538159) ++ - drm/i915: Hook connector to encoder during load detection ++ (Closes: #522358) ++ - module: workaround duplicate section names (Closes: #545229) ++ - b43: Add fw capabilities (Closes: #533357) ++ - procfs: Fix idle time in uptime (Closes: #545981) ++ - e1000, e1000e, igb, ixgb, ixgbe: Fix initial link state ++ (Closes: #546041) ++ - CIFS: Handle port= mount option correctly (Closes: #524142) ++ - i915: Prevent screen flickering in X11 (Closes: #545377) ++ - hppa: Ensure broadcast tlb purge runs single threaded ++ (Closes: #539215) ++ ++ [ maximilian attems ] ++ * [powerpc64] Enable modular RTC_DRV_PS3, PS3_VRAM. ++ (Closes: #528694) ++ * Set new NETFILTER_XT_MATCH_OSF, FIREWIRE_NET, SND_CTXFI, USB_XHCI_HCD, ++ IEEE802154, CAN_DEV, EEPROM_MAX6875, DM_LOG_USERSPACE, DM_MULTIPATH_QL, ++ DM_MULTIPATH_ST, LIBERTAS_SPI, CAN_SJA1000, CAN_SJA1000_PLATFORM, ++ CAN_EMS_PCI, CAN_KVASER_PCI, CB710_CORE, CNIC, RT2800USB, ++ USB_NET_INT51X1, SND_LX6464ES, BLK_DEV_OSD, SCSI_BNX2_ISCSI, IWM, ++ IEEE802154_DRIVERS, TOUCHSCREEN_EETI, TOUCHSCREEN_W90X900, ++ BATTERY_MAX17040, SENSORS_TMP401, REGULATOR_USERSPACE_CONSUMER, ++ REGULATOR_MAX1586, REGULATOR_LP3971, MEDIA_SUPPORT, CUSE, ++ WL12XX, PPS, AB3100_CORE, SND_HDA_INPUT_JACK,MMC_SDHCI_PLTFM, ++ MMC_CB710, MMC_VIA_SDMMC, LEDS_LP3944, RTC_DRV_RX8025, ++ SMARTJOYPLUS_FF, USB_CDC_PHONET, USB_GSPCA_SN9C20X, MOUSE_SYNAPTICS_I2C, ++ PCIEAER_INJECT. ++ * Disable v4l1 ov511 and quickcam_messenger drivers. ++ * [x86_64] Enable HW_RANDOM_VIA. ++ * [x86] Keep divers staging stuff enabled. ++ * [x86] Enable RT3070, COMEDI_PCMCIA_DRIVERS, ACERHDF, EDAC_AMD64, ++ XEN_DEV_EVTCHN, XEN_SYS_HYPERVISOR, PERF_COUNTERS, ++ CC_STACKPROTECTOR, DEFAULT_MMAP_MIN_ADDR=65536. ++ * rtl8192su: remove firmware and disable. ++ * Newer Standards-Version 3.8.2 without changes. ++ * Allow install in chroot without do_initrd check for piuparts. ++ * Cleanup Maintainer scripts from ancient pre linux-2.6 assumptions. ++ (Also closes: #536333) ++ * Disable DEVKMEM. ++ * [ppc, sparc] Enable EFI_PARTITION. (closes: #540486) ++ * Disable old USB_DEVICE_CLASS. (Closes: #510279) ++ * Drop yaird initramfs generator support. ++ * Add stable release 2.6.31.1. ++ * Enable PREEMPT_VOLUNTARY. ++ ++ [ Ben Hutchings ] ++ * mga: remove unnecessary change from firmware-loading patch ++ * cxgb3: remove PHY firmware and use request_firmware() to load it ++ * Add firmware-linux-free package containing DFSG-free firmware ++ * av7110: include firmware source and binary ++ * snd-cs46xx: reenable using external firmware (closes: #464197, ++ but note that Debian cannot currently distribute the firmware), ++ thanks to Kalle Olavi Niemitalo ++ * ib_ipath: remove firmware for QLogic IBA7220 and use ++ request_firmware() to load it ++ * dvb-usb-af9005: remove initialisation script derived from Windows ++ driver and use request_firmware() to extract it at run-time ++ (closes: #494119) ++ * Add warning on upgrade to a new upstream version where the system ++ appears to be missing necessary firmware files (closes: #541702) ++ * qla1280: Release spinlock when requesting firmware (closes: #543244) ++ * r128: Add test for initialisation to all ioctls that require it ++ (closes: #541630) ++ * rt{2860,2870,3070}sta: Use existing CCITT CRC implementation on ++ firmware rather than adding an equivalent variant of ITU-T CRC ++ * rd: Build as a module since we do not require initrd support ++ * x86: Fix crash in text_poke_early() on 486-class processors ++ (Closes: #515982) ++ * intel-agp: Fix cache flushing on i8xx chipsets, avoiding graphics ++ corruption and GPU lock-ups (Closes: #541307) ++ * Generate architecture-qualified package relations as needed for ++ flavours that exist for multiple architectures (Closes: #278729) ++ * Prompt bug reporters to run the kernel version they're reporting on ++ or otherwise record boot messages ++ * Include PCI device list in bug reports even if the running kernel ++ doesn't match ++ ++ [ Martin Michlmayr ] ++ * [armel/orion5x, armel/kirkwood] Set GPIO_SYSFS=y since these ++ platforms have been converted to GPIOLIB. ++ * [armel/orion5x, armel/kirkwood] Disable MARVELL_PHY since it may ++ lead to conflicts with the built-in Ethernet. ++ * Add features from 2.6.32: ++ - crypto: mv_cesa - Add support for Orion5X crypto engine ++ * [armel/orion5x] Enable CRYPTO_DEV_MV_CESA. ++ * Disable SYS_HAS_EARLY_PRINTK on SGI IP22 to work around a hang ++ during bootup (Closes: #507557) ++ * [armel] Enable BPQETHER (on the request of Iain Young) and some ++ other AX25 drivers. ++ ++ [ Bastian Blank ] ++ * Disable staging drivers by default. ++ * Force all bugs against images to be reported to linux-2.6. ++ (closes: #539176) ++ * [arm] Remove old arm architecture. ++ * Use kernel architecture for libc-dev build. ++ ++ [ Moritz Muehlenhoff ] ++ * Fix Linus' name in copyright file (Closes: #530620) ++ * More verbose explanation on difference between Alpha flavour ++ (Closes: #497230) ++ * Add Vcs-Svn and Vcs-Browser stanzas pointing to the SVN branch ++ used for development in unstable. There are other branches ++ used for experimental (trunk), oldstable and stable, but Vcs-* ++ doesn't yet provide the ability to distinguish branches in a ++ more fine-grained manner. (Closes: #471495) ++ * Update Standards-Version to 3.8.3, no changes needed ++ * Disable PROM console support (Closes: #525958) ++ * Make the description of linux-support a little more verbose ++ (Closes: #400825) ++ * This upload fixes the following security issues: ++ - CVE-2009-3290 (2.6.31) ++ - CVE-2009-3288 (2.6.31.1) ++ - CVE-2009-3280 (2.6.31.1) ++ - CVE-2009-3234 (2.6.31.1) ++ - CVE-2009-3043 (2.6.31) ++ - CVE-2009-3002 (2.6.31) ++ - CVE-2009-3001 (2.6.31) ++ - CVE-2009-2844 (2.6.31) ++ - CVE-2009-2695 (2.6.31) ++ - CVE-2009-2691 (2.6.31) ++ ++ [ dann frazier ] ++ * n_tty: Fix echo race ++ * [ia64] Stop disabling CONFIG_HOTPLUG_CPU, which was blocking ++ CONFIG_KEXEC from being enabled ++ * [hppa] Disable CONFIG_AB3100_CORE, it fails to build ++ ++ -- maximilian attems Sun, 04 Oct 2009 20:27:05 +0200 ++ ++linux-2.6 (2.6.30-8) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * Disable SYS_HAS_EARLY_PRINTK on SGI IP22 to work around a hang ++ during bootup (Closes: #507557) ++ * module: workaround duplicate section names to fix a panic on ++ boot on hppa (Closes: #545229). ++ * Add stable release 2.6.30.8. ++ * [armel/kirkwood] Add Marvell OpenRD-Client support (Dhaval Vasa). ++ Thanks Stefan Kaltenbrunner. ++ ++ -- Bastian Blank Fri, 25 Sep 2009 23:47:56 +0200 ++ ++linux-2.6 (2.6.30-7) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * [armel/kirkwood] Enable eSATA on QNAP TS-219P (John Holland). ++ * [armel/kirkwood] Marvell OpenRD-Base board support (Dhaval Vasa). ++ * [armel/kirkwood] Initialise SATA for OpenRD-Base (Ron Lee). ++ * [armel/kirkwood] Enable SATA_AHCI. ++ ++ [ Ben Hutchings ] ++ * qla1280: Release spinlock when requesting firmware (closes: #543244) ++ * r128: Add test for initialisation to all ioctls that require it ++ (closes: #541630) ++ * [i386] Fix crash in text_poke_early() on 486-class processors ++ (Closes: #515982) ++ * intel-agp: Fix cache flushing on i8xx chipsets, avoiding graphics ++ corruption and GPU lock-ups (Closes: #541307) ++ * [i386] Allow ISA memory range uncacheable mapping requests ++ (Closes: #538159) ++ * Fix idle time in /proc/uptime (Closes: #545981) ++ * e1000, e1000e, igb, ixgb, ixgbe, sfc: Fix initial link state ++ (Closes: #546041) ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.30.5. ++ - drm/i915: Hook connector to encoder during load detection ++ (fixes tv/vga detect) (Closes: #522358) ++ * Add stable release 2.6.30.6. ++ - x86: Fix lock-up on SMP Pentium Pro, Pentium 2, Pentium 3, and ++ Athlon MP systems (Closes: #542551) ++ - NET: Fix information leaks from getsockname() (CVE-2009-3001, ++ CVE-2009-3002) ++ - iwl3945/rfkill: Reenable radio when hardware switch turned back on ++ (Closes: #530554) ++ * Bump ABI to 2. ++ * Apply missing fixes: ++ - block: fix sg SG_DXFER_TO_FROM_DEV regression. ++ - sched_rt: Fix overload bug on rt group scheduling. ++ * Add stable release 2.6.30.7. ++ * [sparc] Disable PROM console. (closes: #525958) ++ ++ -- Bastian Blank Wed, 16 Sep 2009 17:23:13 +0200 ++ ++linux-2.6 (2.6.30-6) unstable; urgency=high ++ ++ [ Bastian Blank ] ++ * Set default low address space protection to default value. ++ ++ [ dann frazier ] ++ * Make sock_sendpage() use kernel_sendpage() (CVE-2009-2692) ++ * flat: fix uninitialized ptr with shared libs ++ * [parisc] isa-eeprom - Fix loff_t usage ++ * do_sigaltstack: avoid copying 'stack_t' as a structure to user space ++ * posix-timers: Fix oops in clock_nanosleep() with CLOCK_MONOTONIC_RAW ++ ++ -- Bastian Blank Sat, 15 Aug 2009 15:50:02 +0200 ++ ++linux-2.6 (2.6.30-5) unstable; urgency=high ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.30.4. ++ - cifs: fix regression with O_EXCL creates and optimize away lookup ++ (closes: #536426) ++ - ecryptfs: check tag 11 literal data buffer size (CVE-2009-2406) ++ - ecryptfs: check tag 3 package encrypted size (CVE-2009-2407) ++ * Ignore nf_conntrack ABI change. ++ * Revert to keep ABI: ++ - block: fix sg SG_DXFER_TO_FROM_DEV regression. ++ - sched_rt: Fix overload bug on rt group scheduling. ++ * [hppa]: Ignore any ABI (broke on 2.6.30.2). ++ ++ -- maximilian attems Mon, 03 Aug 2009 12:08:56 +0200 ++ ++linux-2.6 (2.6.30-4) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.30.2. ++ * Fix pci access in x86 startup code. (closes: #537783) ++ * Ignore ABI changes. ++ * Include all plattform and mach specific headers on arm. ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.30.3. ++ ++ -- Bastian Blank Thu, 30 Jul 2009 11:55:11 +0200 ++ ++linux-2.6 (2.6.30-3) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Build-Depend against cpio. (closes: #536196) ++ ++ [ Martin Michlmayr ] ++ * [arm] Export __cpu_flush_dcache_page. ++ ++ [ Aurelien Jarno ] ++ * [ia64] Fix asm/fpu.h includes. ++ ++ [ dann frazier ] ++ * Fix NULL pointer dereference in tun_chr_pool() (CVE-2009-1897) ++ * personality: fix PER_CLEAR_ON_SETID (CVE-2009-1895) ++ * Add -fno-delete-null-pointer-checks to CFLAGS ++ ++ -- Bastian Blank Sat, 18 Jul 2009 10:00:01 +0200 ++ ++linux-2.6 (2.6.30-2) unstable; urgency=low ++ ++ [ dann frazier ] ++ * [powerpc] Use generic rtc (closes: #535354) ++ * [parisc] ++ - ensure broadcast tlb purge runs single threaded ++ - fix ldcw inline assembler ++ (closes: #535844) ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.30.1: ++ - KVM: x86: check for cr3 validity in ioctl_set_sregs (CVE-2009-2287) ++ - ALSA: intel8x0 - Fix PCM position craziness (closes: #533780) ++ - ide-cd: prevent null pointer deref via cdrom_newpc_intr (closes: #535342) ++ * Ignore ABI changes. ++ ++ [ maximilian attems ] ++ * [alpha] Add upstream smp buildfix. ++ * [parisc] Disable vxge and niu. ++ ++ -- Bastian Blank Tue, 07 Jul 2009 14:45:43 +0200 ++ ++linux-2.6 (2.6.30-1) unstable; urgency=low ++ ++ * New upstream release. ++ - radeonfb: suspend/resume for ATI Mobility Radeon RV350. ++ (closes: #506964) ++ - tcp: fix MSG_PEEK race check (closes: #513695) ++ - e100 fixes (closes: #527056) ++ - mos7840: fix miscalculation of minor numbers (closes: #498293) ++ - reiserfs update (closes: #531804) ++ - bluetooth stack suspend/resume (closes: #508426, #529785) ++ - e1000e: Remove mutex_trylock and associated WARN on failure ++ (closes: #524699) ++ ++ [ maximilian attems ] ++ * [sparc] Enable BLK_DEV_CRYPTOLOOP. (closes: #521829) ++ * Enable PATA_JMICRON instead of legacy BLK_DEV_JMICRON. ++ (closes: #431500, #458493) ++ * Set new NILFS2, AT76C50X_USB, MWL8K, P54_SPI, AR9170_USB, ++ NETFILTER_XT_MATCH_CLUSTER, RDS, SCSI_MPT2SAS, SCSI_OSD_INITIATOR, ++ ETHOC, IGBVF, VXGE, TOUCHSCREEN_AD7877, SENSORS_ATK0110, ++ NETFILTER_XT_TARGET_LED, 3C359, HW_RANDOM_TIMERIOMEM, SENSORS_G760A, ++ SENSORS_LTC4215, SENSORS_LM95241, USB_GSPCA_MR97310A, USB_GSPCA_SQ905, ++ USB_GSPCA_SQ905C, USB_PWC_INPUT_EVDEV, DVB_USB_CE6230, SND_INDIGOIOX, ++ SND_INDIGODJX, USB_SERIAL_CP210X, USB_SERIAL_QUALCOMM, ++ USB_SERIAL_SYMBOL, ISL29003, SERIAL_MAX3100, VIDEO_HDPVR, VIDEO_CX231XX, ++ DRAGONRISE_FF, LEDS_LP5521, LEDS_DAC124S085, LEDS_BD2802, ++ UIO_AEC, CRYPTO_ZLIB, REGULATOR_FIXED_VOLTAGE, NOP_USB_XCEIV, ++ POHMELFS, FSCACHE, CACHEFILES, EXOFS, NFS_FSCACHE, AFS_FSCACHE, ++ MTD_NAND_NANDSIM, STRIP_ASM_SYMS, FCOE_FNIC, USB_NET_CDC_EEM, ++ PCI_IOV, ASYNC_TX_DMA, ROMFS_BACKED_BY_BOTH, DETECT_HUNG_TASK. ++ * [amd64, i386] Set new DELL_WMI, EDAC_AMD8131, EDAC_AMD8111, X86_PAT, DMAR, ++ X86_CPU_DEBUG, CRYPTO_AES_NI_INTEL, X86_X2APIC. ++ * Newer Standards-Version 3.8.1 without changes. ++ * xfs: fix freeing memory in xfs_getbmap(). ++ ++ [ Ben Hutchings ] ++ * Remove firmware from drivers/staging (closes: #521553) ++ - make rt2860sta and rt2870sta use request_firmware(), ++ thanks to Darren Salt ++ * Remove some sourceless firmware not included in Debian kernel images ++ ++ [ Martin Michlmayr ] ++ * [mipsel/r5k-cobalt] Enable SCSI_SYM53C8XX_2 (closes: #526836). ++ * [arm/iop32x, arm/ixp4xx, arm/orion5x] Turn off BOOT_TRACER, ++ BLK_DEV_IO_TRACE, CONTEXT_SWITCH_TRACER, ARM_UNWIND and ++ SECURITY_SELINUX because of size constraints. ++ * [mips/sb1-bcm91250a] There is a platform PATA driver for SWARM IDE ++ these days, so disable IDE and build in ATA, SCSI and BLK_DEV_SD. ++ * [mips/sb1-bcm91250a, mips/sb1a-bcm91480b] Compile in SB1250_MAC and ++ BROADCOM_PHY. ++ * [mips/r4k-ip22] Enable NET_ISA and various ISA network modules on ++ the request of Damian Dimmich since they might be useful on the ++ SGI Indigo2. ++ * Add patches from git.marvell.com: ++ - alternative copy_to_user: more precise fallback threshold ++ - lower overhead with alternative copy_to_user for small copies ++ - Kirkwood: Add CPU idle driver ++ - Kirkwood: clock gating for unused peripherals ++ ++ [ Aurelien Jarno ] ++ * [mips(el)/sb1-bcm91250a] Set CONFIG_SCSI_AIC7XXX=y, it is needed ++ on the build daemons. ++ * topconfig set CONFIG_RD_GZIP, CONFIG_RD_BZIP2, CONFIG_RD_LZMA. ++ ++ [ Bastian Blank ] ++ * [i386] Disable PentiumPro errata workaround. ++ * [i386] Enable support for big SMP systems. ++ * Disable OSS. ++ * [s390] Use Sparse Memory layout. ++ * [amd64, i386, powerpc, sparc] Make IPv6 support built-in. ++ * Centralize Sound core options. ++ * Centralize Power Management options. ++ * Centralize CPU Frequency scaling options. ++ * [sparc] Enable CPU Frequency scaling. ++ * Enable Network console logging support. ++ * [s390/s390x-tape] Add image. ++ * [s390/s390, s390/s390-tape] Remove images. ++ * [i386/486] Enable High Memory Support. ++ * [i386] Allocate pagetables from High Memory. ++ * [amd64, i386] Write protect kernel read-only data structures. ++ * [amd64, i386] Make kernel relocatable. ++ * Move images and headers into kernel section. ++ ++ [ dann frazier ] ++ * Enable bnx2x, using firmware-split patches from net-next and mirroring ++ the per-subarch config settings used for bnx2 ++ ++ -- Bastian Blank Sun, 14 Jun 2009 11:45:08 +0200 ++ ++linux-2.6 (2.6.29-5) unstable; urgency=low ++ ++ [ dann frazier ] ++ * [ia64] Backport rtc-efi driver from mainline ++ ++ [ maximilian attems ] ++ * qla1280: Fix off-by-some error in firmware loading. (closes: #527265) ++ ++ [ Martin Michlmayr ] ++ * Broadcom SB: fix locking in set_irq_affinity. ++ * mmc: load mvsdio automatically when it's a platform device. ++ * mmc: mvsdio: ignore high speed timing requests from the core ++ * USB: ftdi_sio: add vendor/product id for the Marvell SheevaPlug. ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.29.3: ++ - ath9k: Fix FIF_BCN_PRBRESP_PROMISC handling ++ - tracing: x86, mmiotrace: fix range test ++ - sched: account system time properly ++ - rndis_wlan: fix initialization order for workqueue&workers ++ - mm: fix Committed_AS underflow on large NR_CPUS environment ++ - Ignore madvise(MADV_WILLNEED) for hugetlbfs-backed regions ++ - clockevents: prevent endless loop in tick_handle_periodic() ++ - intel-iommu: Avoid panic() for DRHD at address zero. ++ - intel-iommu: Fix oops in device_to_iommu() when devices not found. ++ - intel-iommu: Fix device-to-iommu mapping for PCI-PCI bridges. ++ - cs5536: define dma_sff_read_status() method ++ - proc: avoid information leaks to non-privileged processes ++ - ath5k: fix buffer overrun in rate debug code ++ - mv643xx_eth: OOM handling fixes ++ - mv643xx_eth: 64bit mib counter read fix ++ - check_unsafe_exec: s/lock_task_sighand/rcu_read_lock/ ++ - do_execve() must not clear fs->in_exec if it was set by another thread ++ - check_unsafe_exec() doesn't care about signal handlers sharing ++ - New locking/refcounting for fs_struct ++ - Take fs_struct handling to new file (fs/fs_struct.c) ++ - Get rid of bumping fs_struct refcount in pivot_root(2) ++ - Kill unsharing fs_struct in __set_personality() ++ - Annotate struct fs_struct's usage count restriction ++ - fix setuid sometimes wouldn't ++ - fix setuid sometimes doesn't ++ - compat_do_execve should unshare_files ++ - powerpc: Sanitize stack pointer in signal handling code ++ - ACPI: Revert conflicting workaround for BIOS w/ mangled PRT entries ++ - USB: serial: fix lifetime and locking problems ++ - ptrace: ptrace_attach: fix the usage of ->cred_exec_mutex ++ - kbuild: fix Module.markers permission error under cygwin ++ - pagemap: require aligned-length, non-null reads of /proc/pid/pagemap ++ - drm/i915: allow tiled front buffers on 965+ ++ - bio: fix memcpy corruption in bio_copy_user_iov() ++ - PCI quirk: disable MSI on VIA VT3364 chipsets ++ - ASoC: Fix offset of freqmode in WM8580 PLL configuration ++ - x86/PCI: don't call e820_all_mapped with -1 in the mmconfig case ++ - x86-64: fix FPU corruption with signals and preemption ++ - drm/i915: add support for G41 chipset ++ - unreached code in selinux_ip_postroute_iptables_compat() (CVE-2009-1184) ++ - PCI: fix incorrect mask of PM No_Soft_Reset bit ++ - exit_notify: kill the wrong capable(CAP_KILL) check (CVE-2009-1337) ++ - crypto: ixp4xx - Fix handling of chained sg buffers ++ - block: include empty disks in /proc/diskstats ++ - b44: Use kernel DMA addresses for the kernel DMA API ++ - virtio-rng: Remove false BUG for spurious callbacks ++ - USB: Unusual Device support for Gold MP3 Player Energy ++ - KVM: x86: release time_page on vcpu destruction ++ - KVM: Fix overlapping check for memory slots ++ - KVM: MMU: disable global page optimization ++ - KVM: MMU: Fix off-by-one calculating large page count ++ - mac80211: fix basic rate bitmap calculation ++ - ALSA: us122l: add snd_us122l_free() ++ - thinkpad-acpi: fix LED blinking through timer trigger ++ - b43: Refresh RX poison on buffer recycling ++ - b43: Poison RX buffers ++ - mac80211: Fix bug in getting rx status for frames pending in reorder ++ buffer ++ - forcedeth: Fix resume from hibernation regression. ++ * Ignore ABI change. ++ ++ [ Jurij Smakov ] ++ * [sparc] Fix build ++ ++ -- Bastian Blank Sun, 17 May 2009 12:45:13 +0200 ++ ++linux-2.6 (2.6.29-4) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * drm/i915: allow tiled front buffers on 965+. ++ ++ [ Martin Michlmayr ] ++ * Extend erase timeout in M25P80 SPI Flash driver (Peter Horton). ++ * Add driver for GMT G760A fan speed PWM controller chip. ++ * [arm/orion5x] Enable SENSORS_G760A. ++ * Add patches from git.marvell.com: ++ - allow for alternative __copy_to_user/__clear_user implementations ++ - alternative copy_to_user/clear_user implementation copy_user ++ * [arm/orion5x, armel/kirkwood] Enable UACCESS_WITH_MEMCPY. ++ * [MMC] give Sandisk/Kingston SDHC cards some slack before the SWITCH ++ command. ++ ++ [ dann frazier ] ++ * [parisc] Fix macro expansion in atomic.h fixing PHONET compilation issue ++ * [parisc] reenable PHONET ++ * Btrfs: fix __ucmpdi2 compile bug on 32 bit builds ++ ++ [ Stephen R. Marenka ] ++ * [m68k] Add 2.6.29 patches. ++ * [m68k] Enable RTC for aranym (2.6.29 solution). ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.29.2: ++ - Bonding: fix zero address hole bug in arp_ip_target list ++ - skge: fix occasional BUG during MTU change ++ - scsi: mpt: suppress debugobjects warning ++ - hugetlbfs: return negative error code for bad mount option ++ - NFS: Fix the XDR iovec calculation in nfs3_xdr_setaclargs ++ - gso: Fix support for linear packets ++ - agp: zero pages before sending to userspace ++ - virtio: fix suspend when using virtio_balloon ++ - Revert "console ASCII glyph 1:1 mapping" ++ - Input: gameport - fix attach driver code ++ - x86, PAT: Remove page granularity tracking for vm_insert_pfn maps ++ - KVM: is_long_mode() should check for EFER.LMA ++ - KVM: VMX: Update necessary state when guest enters long mode ++ - KVM: fix kvm_vm_ioctl_deassign_device ++ - KVM: MMU: handle compound pages in kvm_is_mmio_pfn ++ - KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked ++ - KVM: Interrupt mask notifiers for ioapic ++ - KVM: Add CONFIG_HAVE_KVM_IRQCHIP ++ - KVM: Fix missing smp tlb flush in invlpg ++ - USB: usb-storage: augment unusual_devs entry for Simple Tech/Datafab ++ - USB: fix oops in cdc-wdm in case of malformed descriptors ++ - USB: ftdi_sio: add vendor/project id for JETI specbos 1201 spectrometer ++ - usb gadget: fix ethernet link reports to ethtool ++ - x86: disable X86_PTRACE_BTS for now ++ - SCSI: sg: fix q->queue_lock on scsi_error_handler path ++ - SCSI: sg: avoid blk_put_request/blk_rq_unmap_user in interrupt ++ - SCSI: sg: fix races with ioctl(SG_IO) ++ - SCSI: sg: fix races during device removal ++ - mm: pass correct mm when growing stack ++ - pata_hpt37x: fix HPT370 DMA timeouts ++ - hpt366: fix HPT370 DMA timeouts ++ - powerpc: Fix data-corrupting bug in __futex_atomic_op ++ - ALSA: hda - Fix the cmd cache keys for amp verbs ++ - sfc: Match calls to netif_napi_add() and netif_napi_del() ++ - tty: Fix leak in ti-usb ++ - spi: spi_write_then_read() bugfixes ++ - add some long-missing capabilities to fs_mask ++ - hrtimer: fix rq->lock inversion (again) ++ - x86: fix broken irq migration logic while cleaning up multiple vectors ++ - sched: do not count frozen tasks toward load ++ - dm kcopyd: fix callback race ++ - dm kcopyd: prepare for callback race fix ++ - posix-timers: fix RLIMIT_CPU && setitimer(CPUCLOCK_PROF) ++ - posix-timers: fix RLIMIT_CPU && fork() ++ - posixtimers, sched: Fix posix clock monotonicity ++ - cap_prctl: don't set error to 0 at 'no_change' ++ - SCSI: libiscsi: fix iscsi pool error path ++ - SCSI: libiscsi: fix iscsi pool error path ++ - sparc64: Fix bug in ("sparc64: Flush TLB before releasing pages.") ++ - ALSA: hda - add missing comma in ad1884_slave_vols ++ - splice: fix deadlock in splicing to file ++ - netfilter: {ip, ip6, arp}_tables: fix incorrect loop detection ++ - kprobes: Fix locking imbalance in kretprobes ++ - acer-wmi: Blacklist Acer Aspire One ++ - crypto: shash - Fix unaligned calculation with short length ++ - net/netrom: Fix socket locking ++ - af_rose/x25: Sanity check the maximum user frame size ++ - dm table: fix upgrade mode race ++ - dm: path selector use module refcount directly ++ - dm target: use module refcount directly ++ - dm snapshot: avoid having two exceptions for the same chunk ++ - dm snapshot: avoid dropping lock in __find_pending_exception ++ - dm snapshot: refactor __find_pending_exception ++ - dm io: make sync_io uninterruptible ++ - dm raid1: switch read_record from kmalloc to slab to save memory ++ - vfs: skip I_CLEAR state inodes ++ - dm: preserve bi_io_vec when resubmitting bios ++ - ixgbe: Fix potential memory leak/driver panic issue while setting up Tx & ++ Rx ring parameters ++ - mm: do_xip_mapping_read: fix length calculation ++ - mm: define a UNIQUE value for AS_UNEVICTABLE flag ++ - sysctl: fix suid_dumpable and lease-break-time sysctls ++ - cpumask: fix slab corruption caused by alloc_cpumask_var_node() ++ - ide-atapi: start DMA after issuing a packet command ++ - ide: drivers/ide/ide-atapi.c needs ++ - V4L/DVB (10943): cx88: Prevent general protection fault on rmmod ++ - r8169: Reset IntrStatus after chip reset ++ - md/raid1 - don't assume newly allocated bvecs are initialised. ++ - SCSI: sg: fix iovec bugs introduced by the block layer conversion ++ - drm/i915: fix TV mode setting in property change ++ - drm/i915: only set TV mode when any property changed ++ - drm: Use pgprot_writecombine in GEM GTT mapping to get the right bits for ++ !PAT. ++ - drm/i915: check for -EINVAL from vm_insert_pfn ++ - drm/i915: Check for dev->primary->master before dereference. ++ - drm/i915: Sync crt hotplug detection with intel video driver ++ - drm/i915: Read the right SDVO register when detecting SVDO/HDMI. ++ - drm/i915: Change DCC tiling detection case to cover only mobile parts. ++ - dock: fix dereference after kfree() ++ - ACPI: cap off P-state transition latency from buggy BIOSes ++ - x86, setup: mark %esi as clobbered in E820 BIOS call ++ - tracing/core: fix early free of cpumasks ++ - rt2x00: Fix SLAB corruption during rmmod ++ - ext4: fix locking typo in mballoc which could cause soft lockup hangs ++ - ext4: fix typo which causes a memory leak on error path ++ - MIPS: Compat: Zero upper 32-bit of offset_high and offset_low. ++ - PCI/x86: detect host bridge config space size w/o using quirks ++ - ide: Fix code dealing with sleeping devices in do_ide_request() ++ - fbdev: fix info->lock deadlock in fbcon_event_notify() ++ - fbmem: fix fb_info->lock and mm->mmap_sem circular locking dependency ++ - security/smack: fix oops when setting a size 0 SMACK64 xattr ++ * Bump ABI to 2. ++ * [sparc] Make the kernels again 64bit. (closes: #525926) ++ ++ -- Bastian Blank Sun, 03 May 2009 09:38:42 +0200 ++ ++linux-2.6 (2.6.29-3) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * [powerpc] Pipe mkimage postinst call to stderr for debconf. ++ Thanks Jordi Mallach for the patch. (closes: #518231) ++ * [parisc] Disable PHONET. ++ * [sparc] Disable BTRFS. ++ ++ [ Bastian Blank ] ++ * [alpha] Fix location of kernel image. ++ * Add source link to headers packages. (closes: #523726) ++ ++ [ Martin Michlmayr ] ++ * Add some sata_mv fixes for Kirkwood from Marvell: ++ - use new sata phy register settings for new devices ++ - increate the IORDY timeout for the soc controllers ++ ++ -- maximilian attems Fri, 17 Apr 2009 10:36:03 +0200 ++ ++linux-2.6 (2.6.29-2) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * [arm/ixp4xx] Build in LEDS_TRIGGER_TIMER (closes: #521141). ++ * [mips*/4kc-malta, mips*/5kc-malta] Build in RTC_DRV_CMOS. ++ ++ [ maximilian attems ] ++ * linux-libc-dev: Bump versioned replaces libdrm-dev. ++ * parisc: hardcode gcc-4.3 usage. ++ * Postrm cleanup new module-init-tools 3.7 files. ++ ++ [ Bastian Blank ] ++ * Install all needed Makefiles into common headers package. ++ (closes: #521472) ++ * Add stable release 2.6.29.1: ++ - V4L: v4l2-common: remove incorrect MODULE test ++ - sparc64: Fix reset hangs on Niagara systems. ++ - sparc64: Flush TLB before releasing pages. ++ - sparc64: Fix MM refcount check in smp_flush_tlb_pending(). ++ - KVM: MMU: Fix another largepage memory leak ++ - cfg80211: fix incorrect assumption on last_request for 11d ++ - lguest: fix spurious BUG_ON() on invalid guest stack. ++ - lguest: wire up pte_update/pte_update_defer ++ - VM, x86, PAT: Change is_linear_pfn_mapping to not use vm_pgoff ++ - x86: mtrr: don't modify RdDram/WrDram bits of fixed MTRRs ++ - x86: ptrace, bts: fix an unreachable statement ++ - x86: fix 64k corruption-check ++ - x86, uv: fix cpumask iterator in uv_bau_init() ++ - x86, PAT, PCI: Change vma prot in pci_mmap to reflect inherited prot ++ - Add a missing unlock_kernel() in raw_open() ++ - fuse: fix fuse_file_lseek returning with lock held ++ - ARM: 5435/1: fix compile warning in sanity_check_meminfo() ++ - ARM: twl4030 - leak fix ++ - ARM: fix leak in iop13xx/pci ++ - ARM: cumana: Fix a long standing bogon ++ - ARM: 5428/1: Module relocation update for R_ARM_V4BX ++ - ARM: pxa: fix overlay being un-necessarily initialized on pxa25x ++ - DVB: firedtv: FireDTV S2 problems with tuning solved ++ - cfg80211: force last_request to be set for OLD_REG if regdom is EU ++ - CIFS: Fix memory overwrite when saving nativeFileSystem field during mount ++ - ath5k: warn and correct rate for unknown hw rate indexes ++ - ath5k: disable MIB interrupts ++ - b43: fix b43_plcp_get_bitrate_idx_ofdm return type ++ - ath9k: fix dma mapping leak of rx buffer upon rmmod ++ - ath5k: use spin_lock_irqsave for beacon lock ++ - cifs: fix buffer format byte on NT Rename/hardlink ++ - ath9k: downgrade xmit queue full message to xmit debug ++ - KVM: SVM: set accessed bit for VMCB segment selectors ++ - KVM: VMX: Don't allow uninhibited access to EFER on i386 ++ - USB: add quirk to avoid config and interface strings ++ - USB: gadget: fix rndis regression ++ - USB: usb-storage: increase max_sectors for tape drives ++ - USB: fix USB_STORAGE_CYPRESS_ATACB ++ - USB: EHCI: add software retry for transaction errors ++ - xfrm: spin_lock() should be spin_unlock() in xfrm_state.c ++ - ipv6: Plug sk_buff leak in ipv6_rcv (net/ipv6/ip6_input.c) ++ - GRO: Disable GRO on legacy netif_rx path (closes: #521691) ++ - bridge: bad error handling when adding invalid ether address ++ - dnet: drivers/net/dnet.c needs ++ - udp: Wrong locking code in udp seq_file infrastructure ++ - netfilter: nf_conntrack_tcp: fix unaligned memory access in tcp_sack ++ ++ [ dann frazier ] ++ * bnx2: correct firmware revisions (closes: #522049) ++ * [mips] Zero upper 32-bits of compat llseek (closes: #521016) ++ ++ -- Bastian Blank Sat, 04 Apr 2009 15:13:33 +0200 ++ ++linux-2.6 (2.6.29-1) unstable; urgency=low ++ ++ * New upstream release ++ - tg3 use request_firmware and firmware nuked. ++ - acenic use request_firmware and firmware nuked. ++ - e100 use request_firmware and firmware nuked. (closes: #494308) ++ - cassini use request_firmware and firmware nuked. ++ - starfire use request_firmware and firmware nuked. (closes: #501152) ++ - cxgb3 use request_firmware and firmware nuked. ++ - NR_CPUS setting no longer affects size of modules. (closes: #516709) ++ - orinoco: use KERN_DEBUG for link status messages. (closes: #447549) ++ - [CIFS] Fix oops in cifs_strfromUCS_le mounting to servers which do ++ not specify their OS. (closes: #463402) ++ - fixes conflict between and on mips ++ (closes: #519761) ++ ++ [ maximilian attems ] ++ * topconfig set new NET_NS, NET_SCH_DRR, NET_CLS_CGROUP, LIB80211, ++ SCSI_CXGB3_ISCSI, NATIONAL_PHY, STE10XP, LSI_ET1011C_PHY, BTRFS_FS, ++ SQUASHFS, PCI_STUB, WIMAX, MTD_LPDDR, EEPROM_AT24, EEPROM_AT25, ++ EEPROM_LEGACY, BLK_DEV_IT8172, SMSC9420, WIMAX_I2400M_USB, ++ WIMAX_I2400M_SDIO, MISDN_HFCUSB, SENSORS_ADT7475, SENSORS_LTC4245, ++ RADIO_TEA5764, SND_HDA_CODEC_INTELHDMI, RT2860, RT2870, RTL8187SE, ++ LIBFC, FCOE, ATL1C, JOYSTICK_WALKERA0701, TOUCHSCREEN_WACOM_W8001, ++ TOUCHSCREEN_TSC2007, W1_SLAVE_DS2431, WM8350_POWER, SOC_CAMERA_MT9T031, ++ SOC_CAMERA_TW9910, SOC_CAMERA_OV772X, USB_STV06XX, USB_GSPCA_OV534, ++ DVB_LGDT3304, WM8350_WATCHDOG, SMSC_SCH311X_WDT, SND_HRTIMER, ++ SND_HDA_RECONFIG, GREENASIA_FF, USB_SERIAL_SIEMENS_MPI, ++ USB_SERIAL_OPTICON, LEDS_ALIX2, LEDS_WM8350, OCFS2_FS_POSIX_ACL, ++ BTRFS_FS_POSIX_ACL, ATM_SOLOS, MFD_PCF50633, PCF50633_ADC, PCF50633_GPIO, ++ REGULATOR_PCF50633, DVB_S921, EDAC_I5400, RTC_DRV_PCF50633, ++ INPUT_PCF50633_PMU, CHARGER_PCF50633, DEVPTS_MULTIPLE_INSTANCES, ++ SCHED_OMIT_FRAME_POINTER, DCB, IXGBE_DCB, SFC_MTD, BE2NET, DNET. ++ * topconfig enable SND_HDA_HWDEP for sound debugging purpose. ++ * topconfig enable USB_HIDDEV (closes: #517771) ++ * [x86] set DELL_LAPTOP, COMEDI, X86_PTRACE_BTS, XENFS, XEN_COMPAT_XENFS, ++ X86_REROUTE_FOR_BROKEN_BOOT_IRQS, OPTIMIZE_INLINING. ++ * [x86] unset DRM_I915_KMS due to upgrade path from Lenny override with ++ modeset module param. ++ * temp.image.plain/preinst: Consistent output. ++ * [x86_64] set SPARSE_IRQ, NUMA_MIGRATE_IRQ_DESC, TREE_RCU. ++ * [x86_32] set BLK_DEV_CS5536. ++ * [powerpc] set PHANTOM, HP_ILO, MV643XX_ETH, MOUSE_BCM5974, VIRTUALIZATION. ++ * topconfig unset legacy SCSI_PROC_FS, PCMCIA_IOCTL, ACPI_PROCFS_POWER, ++ ACPI_PROC_EVENT. ++ ++ [ Bastian Blank ] ++ * Use external source directory for all builds. ++ * Use external source directory for all header packages. ++ * Use dh_prep. ++ * Update copyright file. ++ * [s390/s390] Disable BTRFS. ++ * [sparc] Use sparc as kernel architecture. ++ * Update kconfig report changes patch. ++ * [s390] Enable KVM. ++ * Use debhelper compat level 7. ++ ++ [ Martin Michlmayr ] ++ * [mips/r4k-ip22] Build in RTC_DRV_DS1286. ++ * [mips/r5k-ip32] Build in RTC_DRV_CMOS (Closes: #516775). ++ * [arm/versatile, arm/iop32x, arm/ixp4xx] Make LLC2 modular. ++ * [arm, mips, mipsel] Make MII modular. ++ * [arm/ixp4xx] Make IXP4XX_WATCHDOG modular. ++ * topconfig: Disable NET_DSA since this hardware is special purpose and ++ the option cannot be made modular at the moment and bloats the kernel ++ image too much. ++ * [arm, armel] Enable various V4L USB devices. (Closes: #518582) ++ * [arm/orion5x] Build the SENSORS_LM75 module since it's needed on the ++ D-Link DNS-323. ++ * [arm/iop32x, arm/ixp4xx, arm/orion5x] Enable INPUT_TOUCHSCREEN. ++ * [arm/iop32x, arm/ixp4xx, arm/orion5x] Enable INPUT_JOYDEV, GAMEPORT ++ and INPUT_JOYSTICK (Closes: #520433). ++ * [arm/iop32x, arm/ixp4xx, arm/orion5x] Add a size check to ensure that ++ the kernel will fit in flash. ++ * Add patches from git.marvell.com to improve Kirkwood support: ++ - make gpio /input/output validation separate ++ - MPP initialization code ++ - SDIO driver for Marvell SoCs ++ - SDIO driver registration for DB6281 and RD6281 ++ - register internal devices in a common place ++ - Marvell SheevaPlug support ++ - SheevaPlug USB Power Enable setup ++ - SheevaPlug LED support ++ - Hook up I2C on Kirkwood ++ - Add support for QNAP TS-119/TS-219 Turbo NAS ++ * [armel/kirkwood] Add an image for Marvell's Kirkwood platform. ++ ++ [ Ben Hutchings ] ++ * Remove firmware from drivers and make them use request_firmware(): ++ - mga (closes: #502666) ++ - qla1280 (closes: #502667) ++ - r128 (closes: #494007) ++ - radeon (closes: #494009) ++ - tehuti (closes: #501153) ++ - typhoon (closes: #502669) ++ ++ -- Bastian Blank Tue, 24 Mar 2009 14:32:11 +0100 ++ ++linux-2.6 (2.6.28-1) unstable; urgency=low ++ ++ * New upstream release ++ - new btusb. (closes: #505184) ++ - iwlagn driver for Intel Wifi Link 5100 and 5300. (closes: #501157) ++ - drm git branch vblank-rework merged. (closes: #456219) ++ - netfilter.h got in.h include. (closes: #487103) ++ - netlink errno propageted. (closes: #489340) ++ - agp g41 support (closes: #513228) ++ - Includes atl2 driver (Closes: #500065) ++ - Fixes loading of video module on Samsung systems ++ (Closes: #475319, #495697) ++ - Fix rf_kill handling of iwl3945 driver (Closes: #503688) ++ - Fix adjtimex frequency offset (Closes: #432877) ++ - Fix oopses with Canon PIXMA MP150 (Closes: #487725) ++ - Fix excessive interrrupts with compiz (Closes: #456219) ++ - dsp56k: use request_firmware and firmware nuked (closes: #494010) ++ - dabusb: use request_firmware and firmware nuked (closes: #502663) ++ - kaweth: use request_firmware and firmware nuked (closes: #502665) ++ ++ [ maximilian attems ] ++ * Reenable new Juju firewire stack. ++ * topconfig set ATH9K, IWL5000, IP_NF_SECURITY, IP6_NF_SECURITY, ++ BRIDGE_EBT_IP6, BT_HCIBTUSB, TOUCHSCREEN_INEXIO, TOUCHSCREEN_TOUCHIT213, ++ VIRTIO_CONSOLE, VIDEO_ZORAN_ZR36060, USB_VIDEO_CLASS_INPUT_EVDEV, ++ USB_GSPCA, USB_S2255, OCFS2_FS_STATS, OMFS_FS, CRYPTO_RMD128, ++ CRYPTO_RMD160, CRYPTO_RMD256, CRYPTO_RMD320, VLAN_8021Q_GVRP, HP_WMI, ++ COMPAL_LAPTOP, SCSI_DH, SCSI_DH_RDAC, SCSI_DH_HP_SW, SCSI_DH_EMC, ++ SCSI_DH_ALUA, MAC80211_HWSIM, USB_HSO, BLK_DEV_INTEGRITY, SGI_XP, SGI_GRU, ++ TLAN, ATM_IA, ATM_FORE200E, MISDN, I2C_HELPER_AUTO, I2C_ISCH, ++ I2C_NFORCE2_S4985, AT24, SENSORS_AD7414, SENSORS_ADCXX, ++ SOC_CAMERA_PLATFORM, VIDEO_SH_MOBILE_CEU, DVB_USB_DW2102, DVB_USB_ANYSEE, ++ DVB_SIANO_SMS1XXX, DVB_DRX397XD, MMC_SDHCI_PCI (closes: #507150), ++ MMC_SDRICOH_CS (closes: #509979), EDAC_I5100, RTC_DRV_M41T94, ++ RTC_DRV_DS1305, UBIFS, EXT4 (closes: #512266), CGROUP_FREEZER, ++ NETFILTER_TPROXY, NETFILTER_XT_TARGET_TPROXY, NETFILTER_XT_MATCH_RECENT, ++ NETFILTER_XT_MATCH_SOCKET, NET_ACT_SKBEDIT, PHONET, NET_9P_RDMA, ATL2, JME, ++ ENIC, MLX4_EN, USB_NET_SMSC95XX, I7300_IDLE, NET_SCH_MULTIQ, ICS932S401, ++ PANASONIC_LAPTOP, QLGE, LIBERTAS_THINFIRM, LIBERTAS_THINFIRM_USB, ++ INPUT_CM109, W1_SLAVE_BQ27000, SENSORS_ADT7462, SENSORS_MAX1111, ++ SENSORS_LIS3LV02D, MFD_WM8400, MFD_WM8350_I2C, SOC_CAMERA_MT9M111, ++ USB_M5602, USB_GSPCA_CONEX, USB_GSPCA_ETOMS, USB_GSPCA_FINEPIX, ++ USB_GSPCA_MARS, USB_GSPCA_OV519, USB_GSPCA_PAC207, USB_GSPCA_PAC7311, ++ USB_GSPCA_SONIXB, USB_GSPCA_SONIXJ, USB_GSPCA_SPCA500, USB_GSPCA_SPCA501, ++ USB_GSPCA_SPCA505, USB_GSPCA_SPCA506, USB_GSPCA_SPCA508, USB_GSPCA_SPCA561, ++ USB_GSPCA_STK014, USB_GSPCA_SUNPLUS, USB_GSPCA_T613, USB_GSPCA_TV8532, ++ USB_GSPCA_VC032X, USB_GSPCA_ZC3XX, C2PORT, C2PORT_DURAMAR_2150, ++ W83697UG_WDT, USB_MR800, DVB_USB_CINERGY_T2, DVB_USB_DTV5100, ++ DVB_USB_AF9015, DVB_DM1105, DVB_LGS8GL5, DVB_DUMMY_FE, ++ SND_HDA_CODEC_NVHDMI, SND_USB_US122L, USB_VST, LEDS_PCA9532, LEDS_HP_DISK, ++ LEDS_PCA955X, LEDS_TRIGGER_BACKLIGHT, EDAC_X38, RTC_DRV_RX8581, ++ RTC_DRV_DS1390, RTC_DRV_DS3234, RTC_DRV_DS1286, RTC_DRV_M48T35, ++ RTC_DRV_BQ4802, RTC_DRV_WM8350, UNEVICTABLE_LRU, MAC80211_RC_MINSTREL, ++ BATTERY_BQ27x00, REGULATOR, REGULATOR_BQ24022, REGULATOR_WM8350, ++ REGULATOR_WM8400, FB_VIA, FB_METRONOME, FB_MB862XX, UIO_SERCOS3, ++ CORE_DUMP_DEFAULT_ELF_HEADERS, NET_DSA, NET_DSA_MV88E6060, ++ NET_DSA_MV88E6131, NET_DSA_MV88E6123_61_65, IT87_WDT, ++ BACKLIGHT_MBP_NVIDIA, SND_HDA_INPUT_BEEP, USB_WUSB, USB_TMC, IDE_GD, ++ IDE_GD_ATA, IDE_GD_ATAPI, PCMCIA_IBMTR, USB_EMI62, USB_EMI26, USB_SEVSEG, ++ UWB, UWB_WLP, UWB_I1480U, UWB_I1480U_WLP, CRYPTO_FIPS, ANSI_CPRNG, ++ CRC_T10DIF, STAGING, ET131X, CRYPTO_ANSI_CPRNG, PRISM2_USB, HID_COMPAT, ++ SYSCTL_SYSCALL_CHECK, BOOT_TRACER. ++ * [x86] set MOUSE_BCM5974, X86_RESERVE_LOW_64K, OPROFILE_IBS, ++ MICROCODE_INTEL, MICROCODE_AMD, X86_VERBOSE_BOOTUP, MTRR_SANITIZER, ++ CRYPTO_CRC32C_INTEL, STRICT_DEVMEM. ++ * [x86_64] set AMD_IOMMU, INTR_REMAP. ++ * [x86_32] set TOUCHSCREEN_HTCPEN, MOUSE_PS2_OLPC. ++ * Add stable releases 2.6.28.1-6. ++ * Turn off SYSFS_DEPRECATED* for newer udev and proper /sys/. ++ * linux-libc-dev: Add versioned replaces libdrm-dev. (closes: #513604) ++ * topconfig: Enable MACVLAN. (closes: #504611) ++ * [ppc] BAYCOM_PAR, BAYCOM_EPP. ++ * [x86_64] set NR_CPUS to 512. (closes: #491309) ++ * [686-bigmem] set modular XEN_FBDEV_FRONTEND. ++ * Newer Standards-Version 3.8.0 without changes. ++ * Use update-initramfs for initramfs-tools. ++ * Fix preinst and postinst call to not use deprecated mkinitramfs-kpkg ++ interfaces. ++ ++ [ Martin Michlmayr ] ++ * [mips/r4k-ip22, mips/sb1-bcm91250a] Don't build in ISO9660. ++ * [mipsel/r5k-cobalt] Enable INPUT_COBALT_BTNS. ++ * [mipsel/r5k-cobalt] Enable the new Cobalt LCD driver (FB_COBALT). ++ * [mips/r4k-ip22] Enable the new ALSA sound driver (SND_SGI_HAL2). ++ * [arm/iop32x, arm/ixp4xx] Don't build in KEYBOARD_ATKBD, MOUSE_PS2, ++ SERIO, JFFS2_FS, and CRAMFS. ++ * [arm/iop32x, arm/ixp4xx] Unset DEBUG_KERNEL so the kernel will ++ fit in flash. ++ * [arm/orion5x] Unset FIXED_PHY to work around a clash with fixed ++ mdio bus and mv643xx_eth. ++ * Migrate arm, armel, mips and mipsel away from kernel-package. ++ ++ [ Ian Campbell ] ++ * [x86]: Enable Xen guest support in amd64 flavour. (closes: #495590) ++ ++ [ dann frazier ] ++ * [x86, ia64] Enable ACPI_PCI_SLOT ++ ++ [ Bastian Blank ] ++ * Make gcc-4.3 the default compiler. (closes: #463295) ++ * Add optional image size check. ++ * debian/rules.real: Setup image installation rules for alpha, hppa, ++ ia64 and sparc. ++ * Remove support to build images using kernel-package. ++ ++ -- maximilian attems Wed, 18 Feb 2009 16:36:04 +0100 ++ ++linux-2.6 (2.6.26-12) unstable; urgency=high ++ ++ [ Ian Campbell ] ++ * xen: fix ACPI processor throttling for when processor id is -1. (closes: #502849) ++ ++ [ dann frazier ] ++ * Make sendmsg() block during UNIX garbage collection (CVE-2008-5300) ++ * Fix race conditions between inotify removal and umount (CVE-2008-5182) ++ * Fix DoS when calling svc_listen twice on the same socket while reading ++ /proc/net/atm/*vc (CVE-2008-5079) ++ ++ [ Bastian Blank ] ++ * [openvz, vserver] Fix descriptions. ++ * [sparc] Enable Sun Logical Domains support. (closes: #501684) ++ * Fix coexistence of pata_marvell and ahci. (closes: #507432) ++ * [sparc] Support Intergraph graphics chips. (closes: #508108) ++ ++ -- Bastian Blank Mon, 15 Dec 2008 12:57:18 +0100 ++ ++linux-2.6 (2.6.26-11) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * [sparc] Reintroduce dummy PCI host controller to workaround broken X.org. ++ * [sparc] Fix size checks in PCI maps. ++ * Add stable release 2.6.26.8: ++ - netfilter: restore lost ifdef guarding defrag exception ++ - netfilter: snmp nat leaks memory in case of failure ++ - netfilter: xt_iprange: fix range inversion match ++ - ACPI: dock: avoid check _STA method ++ - ACPI: video: fix brightness allocation ++ - sparc64: Fix race in arch/sparc64/kernel/trampoline.S ++ - math-emu: Fix signalling of underflow and inexact while packing result. ++ - tcpv6: fix option space offsets with md5 ++ - net: Fix netdev_run_todo dead-lock ++ - scx200_i2c: Add missing class parameter ++ - DVB: s5h1411: Power down s5h1411 when not in use ++ - DVB: s5h1411: Perform s5h1411 soft reset after tuning ++ - DVB: s5h1411: bugfix: Setting serial or parallel mode could destroy bits ++ - V4L: pvrusb2: Keep MPEG PTSs from drifting away ++ - ACPI: Always report a sync event after a lid state change ++ - ALSA: use correct lock in snd_ctl_dev_disconnect() ++ - file caps: always start with clear bprm->caps_* ++ - libertas: fix buffer overrun ++ - net: Fix recursive descent in __scm_destroy(). ++ - SCSI: qla2xxx: Skip FDMI registration on ISP21xx/22xx parts. ++ (Closes: #502552) ++ - edac cell: fix incorrect edac_mode ++ - ext[234]: Avoid printk floods in the face of directory corruption ++ (CVE-2008-3528) ++ - gpiolib: fix oops in gpio_get_value_cansleep() ++ * Override ABI changes. ++ * [xen] Update description. (closes: #505961) ++ * Revert parts of 2.6.26.6 to fix resume breakage. (closes: #504167) ++ - clockevents: prevent multiple init/shutdown ++ - clockevents: broadcast fixup possible waiters ++ ++ [ dann frazier ] ++ * Fix buffer overflow in hfsplus (CVE-2008-4933) ++ * Fix BUG() in hfsplus (CVE-2008-4934) ++ * Fix stack corruption in hfs (CVE-2008-5025) ++ * Fix oops in tvaudio when controlling bass/treble (CVE-2008-5033) ++ ++ [ Martin Michlmayr ] ++ * [arm/iop32x, arm/ixp4xx, arm/orion5x] Enable support for more partition ++ tables, including MAC_PARTITION (requested by Benoît Knecht). ++ * leds-pca9532: Fix memory leak and properly handle errors (Sven Wegener) ++ * leds-pca9532: Move i2c work to a workqueque (Riku Voipio). (closes: ++ #506116) ++ ++ -- Bastian Blank Wed, 26 Nov 2008 11:43:48 +0100 ++ ++linux-2.6 (2.6.26-10) unstable; urgency=low ++ ++ [ dann frazier ] ++ * sctp: Fix possible kernel panic in sctp_sf_abort_violation (CVE-2008-4618) ++ ++ [ Martin Michlmayr ] ++ * DNS-323: add support for revision B1 machines (Matthew Palmer). ++ * ext3/ext4: Add support for non-native signed/unsigned htree hash ++ algorithms (Theodore Ts'o). (closes: #493957) ++ * [arm/ixp4xx] Enable USB_ACM (closes: #504723). ++ ++ [ Bastian Blank ] ++ * agp: Fix stolen memory counting on Intel G4X. (closes: #502606) ++ * Add stable release 2.6.26.7: ++ - security: avoid calling a NULL function pointer in drivers/video/tvaudio.c ++ - DVB: au0828: add support for another USB id for Hauppauge HVR950Q ++ - drm/i915: fix ioremap of a user address for non-root (CVE-2008-3831) ++ - ACPI: Ignore _BQC object when registering backlight device ++ - hwmon: (it87) Prevent power-off on Shuttle SN68PT ++ - Check mapped ranges on sysfs resource files ++ - x86: avoid dereferencing beyond stack + THREAD_SIZE ++ - PCI: disable ASPM on pre-1.1 PCIe devices ++ - PCI: disable ASPM per ACPI FADT setting ++ - V4L/DVB (9053): fix buffer overflow in uvc-video ++ - V4L/DVB (8617): uvcvideo: don't use stack-based buffers for USB transfers. ++ - V4L/DVB (8498): uvcvideo: Return sensible min and max values when querying ++ a boolean control. ++ - V4L: zr36067: Fix RGBR pixel format ++ - V4L: bttv: Prevent NULL pointer dereference in radio_open ++ - libata: fix EH action overwriting in ata_eh_reset() ++ - libata: always do follow-up SRST if hardreset returned -EAGAIN ++ - fbcon_set_all_vcs: fix kernel crash when switching the rotated consoles ++ - modules: fix module "notes" kobject leak ++ - b43legacy: Fix failure in rate-adjustment mechanism ++ - CIFS: make sure we have the right resume info before calling CIFSFindNext ++ - sched_rt.c: resch needed in rt_rq_enqueue() for the root rt_rq ++ - tty: Termios locking - sort out real_tty confusions and lock reads ++ - x86, early_ioremap: fix fencepost error ++ - x86: improve UP kernel when CPU-hotplug and SMP is enabled ++ - x86: Reserve FIRST_DEVICE_VECTOR in used_vectors bitmap. ++ * [xen] Remove pte file workaround. ++ ++ [ Ian Campbell ] ++ * [xen] Disable usage of PAT. (closes: #503821) ++ ++ -- Bastian Blank Sat, 08 Nov 2008 10:50:58 +0100 ++ ++linux-2.6 (2.6.26-9) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.26.6: ++ - mm owner: fix race between swapoff and exit ++ - rtc: fix kernel panic on second use of SIGIO nofitication ++ - fbcon: fix monochrome color value calculation ++ - ALSA: snd-powermac: HP detection for 1st iMac G3 SL ++ - ALSA: snd-powermac: mixers for PowerMac G4 AGP ++ - sparc64: Fix missing devices due to PCI bridge test in ++ of_create_pci_dev(). ++ - sparc64: Fix disappearing PCI devices on e3500. ++ - sparc64: Fix OOPS in psycho_pcierr_intr_other(). ++ - sparc64: Fix interrupt register calculations on Psycho and Sabre. ++ - sparc64: Fix PCI error interrupt registry on PSYCHO. ++ - udp: Fix rcv socket locking ++ - sctp: Fix oops when INIT-ACK indicates that peer doesn't support AUTH ++ (CVE-2008-4576) ++ - sctp: do not enable peer features if we can't do them. ++ - ipsec: Fix pskb_expand_head corruption in xfrm_state_check_space ++ - netlink: fix overrun in attribute iteration ++ - niu: panic on reset ++ - ipv6: Fix OOPS in ip6_dst_lookup_tail(). ++ - XFRM,IPv6: initialize ip6_dst_blackhole_ops.kmem_cachep ++ - af_key: Free dumping state on socket close ++ - pcmcia: Fix broken abuse of dev->driver_data ++ - clockevents: remove WARN_ON which was used to gather information ++ - ntp: fix calculation of the next jiffie to trigger RTC sync ++ - x86: HPET: read back compare register before reading counter ++ - x86: HPET fix moronic 32/64bit thinko ++ - clockevents: broadcast fixup possible waiters ++ - HPET: make minimum reprogramming delta useful ++ - clockevents: prevent endless loop lockup ++ - clockevents: prevent multiple init/shutdown ++ - clockevents: enforce reprogram in oneshot setup ++ - clockevents: prevent endless loop in periodic broadcast handler ++ - clockevents: prevent clockevent event_handler ending up handler_noop ++ - x86: fix memmap=exactmap boot argument ++ - x86: add io delay quirk for Presario F700 ++ - ACPI: Avoid bogus EC timeout when EC is in Polling mode ++ - x86: fix SMP alternatives: use mutex instead of spinlock, text_poke is ++ sleepable ++ - rtc: fix deadlock ++ - mm: dirty page tracking race fix ++ - x86-64: fix overlap of modules and fixmap areas ++ - x86: PAT proper tracking of set_memory_uc and friends ++ - x86: fix oprofile + hibernation badness ++ - x86: fdiv bug detection fix ++ - rt2x00: Use ieee80211_hw->workqueue again ++ - x86: Fix 27-rc crash on vsmp due to paravirt during module load ++ - sg: disable interrupts inside sg_copy_buffer ++ - ocfs2: Increment the reference count of an already-active stack. ++ - APIC routing fix ++ - sched: fix process time monotonicity ++ - block: submit_bh() inadvertently discards barrier flag on a sync write ++ - x64, fpu: fix possible FPU leakage in error conditions ++ - x86-64: Clean up save/restore_i387() usage ++ - KVM: SVM: fix guest global tlb flushes with NPT ++ - KVM: SVM: fix random segfaults with NPT enabled ++ - ALSA: remove unneeded power_mutex lock in snd_pcm_drop ++ - ALSA: fix locking in snd_pcm_open*() and snd_rawmidi_open*() ++ - ALSA: oxygen: fix distorted output on AK4396-based cards ++ - ALSA: hda - Fix model for Dell Inspiron 1525 ++ - SCSI: qla2xxx: Defer enablement of RISC interrupts until ISP ++ initialization completes. ++ - USB: fix hcd interrupt disabling ++ - smb.h: do not include linux/time.h in userspace ++ - pxa2xx_spi: fix build breakage ++ - pxa2xx_spi: chipselect bugfixes ++ - pxa2xx_spi: dma bugfixes ++ - mm: mark the correct zone as full when scanning zonelists ++ - async_tx: fix the bug in async_tx_run_dependencies ++ - drivers/mmc/card/block.c: fix refcount leak in mmc_block_open() ++ - ixgbe: initialize interrupt throttle rate ++ - i2c-dev: Return correct error code on class_create() failure ++ - x86-32: AMD c1e force timer broadcast late ++ * [x86] Update patch to detect not properly announced cmos RTC devices. ++ * [xen] Overtake hvc console by default. ++ ++ [ maximilian attems ] ++ * [openvz] ip: NULL pointer dereferrence in tcp_v(4|6)_send_ack ++ (closes: #500472) ++ * [openvz] unset NF_CONNTRACK_IPV6 for now until abi bump. ++ ++ [ Stephen R. Marenka ] ++ * [m68k] add patches to fix atari ethernec per Michael Schmitz: ++ atari-ethernec-IRQF_SHARED.diff and atari-ethernec-fixes.diff. ++ * [m68k] add mac-esp-fix-for-quadras-with-two-esp-chips.diff to fix macs ++ with dual scsi busses and a problem with xorg, per Finn Thain. ++ * [m68k] add atari-atari_keyb_init-operator-precedence.diff per ++ Michael Schmitz. ++ * [m68k] more mac patches, per Finn Thain. ++ ++ [ Martin Michlmayr ] ++ * [arm/ixp4xx] Enable USB_ATM and USB_SPEEDTOUCH (closes: #502182). ++ * [arm/iop32x, arm/orion5x] Likewise. ++ * DNS-323: read MAC address from flash (Matthew Palmer). ++ ++ [ dann frazier ] ++ * Restrict access to the DRM_I915_HWS_ADDR ioctl (CVE-2008-3831) ++ * Don't allow splicing to files opened with O_APPEND (CVE-2008-4554) ++ ++ -- Bastian Blank Sat, 18 Oct 2008 12:14:22 +0200 ++ ++linux-2.6 (2.6.26-8) unstable; urgency=medium ++ ++ [ dann frazier ] ++ * [x86] Fix broken LDT access in VMI (CVE-2008-4410) ++ * ata: Fix off-by-one-error that causes errors when reading a ++ block on the LBA28-LBA48 boundary ++ * [s390] prevent ptrace padding area read/write in 31-bit mode ++ (CVE-2008-1514) ++ ++ [ Bastian Blank ] ++ * Fix generation of i386 Xen image information. ++ * [i386] Restrict the usage of long NOPs. (closes: #464962) ++ * Fix access to uninitialized user keyring. (closes: #500279) ++ * [x86] Fix detection of non-PNP RTC devices. (closes: #499230) ++ ++ -- Bastian Blank Thu, 09 Oct 2008 12:07:21 +0200 ++ ++linux-2.6 (2.6.26-7) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * [xen] Add SuSE Xen patch. (closes: #495895) ++ * Only register notifiers in braille console if used, fixes Insert key. ++ (closes: #494374) ++ * Fix ACPI EC GPE storm detection. (closes: #494546) ++ * Disable useless support for ISP1760 USB host controller. ++ (closes: #498304) ++ * rt61pci: Add a sleep after firmware upload. (closes: #498828) ++ ++ [ Stephen R. Marenka ] ++ * [m68k] Set CONFIG_ATARI_ETHERNEC=m for atari, since it only works ++ in modular form. ++ * [m68k] Enable CONFIG_ADB_PMU68K=y for mac. ++ * [m68k] Add atari-aranym-nf-wrappers.diff patch to fix atari LBD ++ problems, set CONFIG_LBD=y for atari. ++ ++ [ Martin Michlmayr ] ++ * [arm/orion5x] Enable CONFIG_ATALK (requested by Ben Schwarz). ++ * [arm/versatile] Enable CONFIG_VFP. (closes: #499463) ++ * ath5k: Fix bad udelay calls on AR5210 code (Nick Kossifidis). ++ * [arm] No longer disable ATH5K. ++ ++ [ dann frazier ] ++ * Add missing capability checks in sbni_ioctl (CVE-2008-3525) ++ ++ -- Bastian Blank Wed, 01 Oct 2008 09:02:30 +0200 ++ ++linux-2.6 (2.6.26-6) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * [openvz] Enable checkpointing. (closes: #497292) ++ ++ [ Bastian Blank ] ++ * Allow forced module loading again. (closes: #494144) ++ * Set IEEE 802.11 (wireless) regulatory domain default to EU. ++ (closes: #497971) ++ * [i386] Enable IDE ACPI support. Override ABI changes. (closes: #470528) ++ * [i386/686-bigmem] Promote to generic subarch. (closes: #476120) ++ ++ [ Martin Michlmayr ] ++ * Fix dead 21041 ethernet after ifconfig down (Thomas Bogendoerfer). ++ ++ [ dann frazier ] ++ * [hppa] Enable the FPU before using it, fixes booting on A500s ++ with our CONFIG_PRINTK_TIME=y setting. (closes: #499458) ++ ++ -- Bastian Blank Wed, 24 Sep 2008 12:06:47 +0200 ++ ++linux-2.6 (2.6.26-5) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * Backport power-off method for Kurobox Pro. ++ * [arm/versatile] Really enable CONFIG_RTC_DRV_PL031 (closes: #484432). ++ ++ [ Stephen R. Marenka ] ++ * [m68k] Set CONFIG_LBD=n for atari, since it conflicts with nfblock. ++ ++ [ Bastian Blank ] ++ * Reenable SiS SATA support. (closes: #496603) ++ * [amd64,i386] Disable new-style SiS PATA support. ++ * Add stable release 2.6.26.4: ++ - sata_mv: don't issue two DMA commands concurrently ++ - KVM: MMU: Fix torn shadow pte ++ - x86: work around MTRR mask setting, v2 ++ - nfsd: fix buffer overrun decoding NFSv4 acl (CVE-2008-3915) ++ - sunrpc: fix possible overrun on read of /proc/sys/sunrpc/transports ++ (CVE-2008-3911) ++ - r8169: balance pci_map / pci_unmap pair ++ - tg3: Fix firmware event timeouts ++ - crypto: authenc - Avoid using clobbered request pointer ++ - sparc64: Fix cmdline_memory_size handling bugs. ++ - sparc64: Fix overshoot in nid_range(). ++ - ipsec: Fix deadlock in xfrm_state management. (closes: #497796) ++ - sctp: fix random memory dereference with SCTP_HMAC_IDENT option. ++ - sctp: correct bounds check in sctp_setsockopt_auth_key ++ - sch_prio: Fix nla_parse_nested_compat() regression ++ - sctp: add verification checks to SCTP_AUTH_KEY option ++ - sctp: fix potential panics in the SCTP-AUTH API. ++ - udp: Drop socket lock for encapsulated packets ++ - pkt_sched: Fix actions referencing ++ - pkt_sched: Fix return value corruption in HTB and TBF. ++ - netns: Add network namespace argument to rt6_fill_node() and ++ ipv6_dev_get_saddr() ++ - ipv6: Fix OOPS, ip -f inet6 route get fec0::1, linux-2.6.26, ++ ip6_route_output, rt6_fill_node+0x175 (CVE-2008-3686) ++ - AX.25: Fix sysctl registration if !CONFIG_AX25_DAMA_SLAVE ++ - mm: make setup_zone_migrate_reserve() aware of overlapping nodes ++ - 8250: improve workaround for UARTs that don't re-assert THRE correctly ++ - rtc_time_to_tm: fix signed/unsigned arithmetic ++ - drivers/char/random.c: fix a race which can lead to a bogus BUG() ++ - cifs: fix O_APPEND on directio mounts ++ - atl1: disable TSO by default ++ - forcedeth: fix checksum flag ++ - bio: fix bio_copy_kern() handling of bio->bv_len ++ - bio: fix __bio_copy_iov() handling of bio->bv_len ++ - ALSA: oxygen: prevent muting of nonexistent AC97 controls ++ - S390 dasd: fix data size for PSF/PRSSD command ++ - x86: fix "kernel won't boot on a Cyrix MediaGXm (Geode)" ++ - x86: work around MTRR mask setting ++ - USB: cdc-acm: don't unlock acm->mutex on error path ++ - binfmt_misc: fix false -ENOEXEC when coupled with other binary handlers ++ - fbdefio: add set_page_dirty handler to deferred IO FB ++ - eeepc-laptop: fix use after free ++ - PCI: fix reference leak in pci_get_dev_by_id() ++ - cramfs: fix named-pipe handling ++ * Override ABI changes. ++ * [hppa] Disable new-style RTC support. Override ABI changes. ++ ++ [ maximilian attems ] ++ * openvz: Add upstream fixes up to 24cebf40278cb071ff8b. (closes: #497528) ++ ++ -- Bastian Blank Wed, 10 Sep 2008 12:55:16 +0200 ++ ++linux-2.6 (2.6.26-4) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * x86: Reset ACPI_PROCFS_POWER for Lenny as buggy apps depend on it. ++ (closes: #495541) ++ * x86: ACPI: Fix thermal shutdowns ++ * openvz: Add upstream fixes up to 0f14912e3d2251aff. (closes: #494384) ++ * Add stable release 2.6.26.3: ++ - USB: fix interface unregistration logic ++ - usb-storage: unusual_devs entries for iRiver T10 and Datafab CF+SM reader ++ - usb-serial: don't release unregistered minors ++ - usb-storage: revert DMA-alignment change for Wireless USB ++ - usb-storage: automatically recognize bad residues ++ - USB: ftdi_sio: Add USB Product Id for ELV HS485 ++ - qla2xxx: Set an rport's dev_loss_tmo value in a consistent manner. ++ - dccp: change L/R must have at least one byte in the dccpsf_val field ++ (CVE-2008-3276) ++ - KVM: Avoid instruction emulation when event delivery is pending ++ - cs5520: add enablebits checking ++ - acer-wmi: Fix wireless and bluetooth on early AMW0 v2 laptops ++ - USB: usb-storage: quirk around v1.11 firmware on Nikon D4 ++ - radeonfb: fix accel engine hangs ++ - radeon: misc corrections ++ - sparc64: Fix global reg snapshotting on self-cpu. ++ - sparc64: Do not clobber %g7 in setcontext() trap. ++ - sparc64: Fix end-of-stack checking in save_stack_trace(). ++ - sparc64: Fix recursion in stack overflow detection handling. ++ - sparc64: Make global reg dumping even more useful. ++ - sparc64: Implement IRQ stacks. ++ - sparc64: Handle stack trace attempts before irqstacks are setup. ++ - PCI: Limit VPD length for Broadcom 5708S ++ - ide: it821x in pass-through mode segfaults in 2.6.26-stable ++ - syncookies: Make sure ECN is disabled ++ - USB: ftdi_sio: add support for Luminance Stellaris Evaluation/Development ++ Kits ++ - i2c: Fix NULL pointer dereference in i2c_new_probed_device ++ - SCSI: hptiop: add more PCI device IDs ++ - SCSI: ses: fix VPD inquiry overrun ++ - SCSI: scsi_transport_spi: fix oops in revalidate ++ - CIFS: Fix compiler warning on 64-bit ++ - x86: fix spin_is_contended() ++ - matrox maven: fix a broken error path ++ - i2c: Let users select algorithm drivers manually again ++ - CIFS: properly account for new user= field in SPNEGO upcall string ++ allocation ++ - x86: fix setup code crashes on my old 486 box ++ - KVM: ia64: Fix irq disabling leak in error handling code ++ - mlock() fix return values ++ - rtl8187: Fix lockups due to concurrent access to config routine ++ - KVM: task switch: segment base is linear address ++ - KVM: task switch: use seg regs provided by subarch instead of reading ++ from GDT ++ - KVM: task switch: translate guest segment limit to virt-extension byte ++ granular field ++ - r8169: avoid thrashing PCI conf space above RTL_GIGA_MAC_VER_06 ++ - sparc64: FUTEX_OP_ANDN fix ++ - posix-timers: do_schedule_next_timer: fix the setting of ->si_overrun ++ - posix-timers: fix posix_timer_event() vs dequeue_signal() race ++ - vt8623fb: fix kernel oops ++ - ide-cd: fix endianity for the error message in cdrom_read_capacity ++ - qla2xxx: Add dev_loss_tmo_callbk/terminate_rport_io callback support. ++ - random32: seeding improvement ++ - CIFS: mount of IPC$ breaks with iget patch ++ - CIFS: if get root inode fails during mount, cleanup tree connection ++ - crypto: padlock - fix VIA PadLock instruction usage with ++ irq_ts_save/restore() ++ - ipvs: Fix possible deadlock in estimator code ++ - SCSI: block: Fix miscalculation of sg_io timeout in CDROM_SEND_PACKET ++ handler. ++ - ALSA: asoc: restrict sample rate and size in Freescale MPC8610 sound ++ drivers ++ - ALSA: ASoC: fix SNDCTL_DSP_SYNC support in Freescale 8610 sound drivers ++ - USB: pl2023: Remove USB id (4348:5523) handled by ch341 ++ - relay: fix "full buffer with exactly full last subbuffer" accounting ++ problem ++ - ipv6: Fix ip6_xmit to send fragments if ipfragok is true ++ - x86: amd opteron TOM2 mask val fix ++ ++ [ dann frazier ] ++ * [ia64] Fix boot-time hang w/ PRINTK_TIME by ensuring that cpu0 can access ++ per-cpu vars in early boot ++ * delay calls to sched_clock() until after sched_clock_init() to prevent ++ inaccurate printk timings on ia64 and presumably other architectures ++ ++ [ Ian Campbell ] ++ * [xen] import upstream fix to fb-defio driver used by Xen framebuffer. ++ ++ [ Bastian Blank ] ++ * [powerpc] Enable proper RTC support. (closes: #484693) ++ ++ [ Martin Michlmayr ] ++ * Add Marvell Orion fixes: ++ - sata_mv: add the Gen IIE flag to the SoC devices. ++ - sata_mv: don't avoid clearing interrupt status on SoC host adapters ++ ++ [ dann frazier ] ++ * Fix overflow condition in sctp_setsockopt_auth_key (CVE-2008-3526) ++ * Fix panics that may occur if SCTP AUTH is disabled (CVE-2008-3792) ++ * [x86] Fix memory leak in the copy_user routine ++ (CVE-2008-0598, closes: #490910) ++ ++ -- Bastian Blank Thu, 28 Aug 2008 08:46:42 +0200 ++ ++linux-2.6 (2.6.26-3) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Disable Emagic Audiowerk 2 soundcard support. The PCI IDs clashes with ++ many DVB cards. ++ * Update VServer patch to 2.3.0.35. ++ * [armel/versatile] Override ABI changes. ++ * [i386/686-bigmem] Add VServer image. ++ ++ [ Aurelien Jarno ] ++ * [armel/versatile] Disable CONFIG_NO_HZ, CONFIG_HIGH_RES_TIMERS for ++ dynticks. (closes: #494842) ++ ++ [ Martin Michlmayr ] ++ * Fix PCIe on the Kurobox Pro (Lennert Buytenhek). ++ * Fix regressions caused by the "use software GSO for SG+CSUM capable ++ netdevices" patch: ++ - loopback: Enable TSO (Herbert Xu) ++ - net: Preserve netfilter attributes in skb_gso_segment using ++ __copy_skb_header (Herbert Xu) ++ ++ [ dann frazier ] ++ * [amd64] Fix typo in TOM2 mask value, preventing a hang on some opteron ++ systems. (closes: #494365) ++ ++ -- Bastian Blank Mon, 18 Aug 2008 15:34:38 +0200 ++ ++linux-2.6 (2.6.26-2) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * [powerpc] Install arch/powerpc/lib/crtsavres.o into the headers, it is ++ used during module linking. ++ * Add stable release 2.6.26.1: ++ - Fix off-by-one error in iov_iter_advance() ++ - ath5k: don't enable MSI, we cannot handle it yet ++ - b43legacy: Release mutex in error handling code ++ - cpufreq acpi: only call _PPC after cpufreq ACPI init funcs got called already ++ - VFS: increase pseudo-filesystem block size to PAGE_SIZE ++ - markers: fix markers read barrier for multiple probes ++ - tmpfs: fix kernel BUG in shmem_delete_inode ++ - mpc52xx_psc_spi: fix block transfer ++ - ixgbe: remove device ID for unsupported device ++ - UML - Fix boot crash ++ - eCryptfs: use page_alloc not kmalloc to get a page of memory ++ - x86: fix kernel_physical_mapping_init() for large x86 systems ++ - DVB: cx23885: SRAM changes for the 885 and 887 silicon parts ++ - DVB: cx23885: Reallocated the sram to avoid concurrent VIDB/C issues ++ - DVB: cx23885: DVB Transport cards using DVB port VIDB/TS1 did not stream ++ - DVB: cx23885: Ensure PAD_CTRL is always reset to a sensible default ++ - V4L: cx23885: Bugfix for concurrent use of /dev/video0 and /dev/video1 ++ - V4L: saa7134: Copy tuner data earlier to avoid overwriting manual tuner type ++ - V4L: uvcvideo: Add support for Medion Akoya Mini E1210 integrated webcam ++ - V4L: uvcvideo: Make input device support optional ++ - V4L: uvcvideo: Don't free URB buffers on suspend ++ - V4L: uvcvideo: Use GFP_NOIO when allocating memory during resume ++ - V4L: uvcvideo: Fix a buffer overflow in format descriptor parsing ++ - DVB: dib0700: add support for Hauppauge Nova-TD Stick 52009 ++ - V4L: cx18: Upgrade to newer firmware & update documentation ++ - ALSA: trident - pause s/pdif output ++ - myri10ge: do not use mgp->max_intr_slots before loading the firmware ++ - myri10ge: do not forget to setup the single slice pointers ++ - iop-adma: fix platform driver hotplug/coldplug ++ - sparc64: Do not define BIO_VMERGE_BOUNDARY. ++ - sparc64: Fix cpufreq notifier registry. ++ - sparc64: Fix lockdep issues in LDC protocol layer. ++ - tcp: Clear probes_out more aggressively in tcp_ack(). ++ - ARM: fix fls() for 64-bit arguments ++ - vmlinux.lds: move __attribute__((__cold__)) functions back into final .text section ++ - rtc-at91rm9200: avoid spurious irqs ++ - ide-cd: fix oops when using growisofs ++ - x86: fix crash due to missing debugctlmsr on AMD K6-3 ++ - cpusets: fix wrong domain attr updates ++ - proc: fix /proc/*/pagemap some more ++ - Fix build on COMPAT platforms when CONFIG_EPOLL is disabled ++ - markers: fix duplicate modpost entry ++ - x86, suspend, acpi: enter Big Real Mode ++ - USB: fix usb serial pm counter decrement for disconnected interfaces ++ - x86 reboot quirks: add Dell Precision WorkStation T5400 ++ - Fix typos from signal_32/64.h merge ++ - rcu: fix rcu_try_flip_waitack_needed() to prevent grace-period stall ++ - Patch Upstream: x86 ptrace: fix PTRACE_GETFPXREGS error ++ - KVM: MMU: Fix potential race setting upper shadow ptes on nonpae hosts ++ - KVM: MMU: nuke shadowed pgtable pages and ptes on memslot destruction ++ - KVM: x86 emulator: Fix HLT instruction ++ - KVM: VMX: Add ept_sync_context in flush_tlb ++ - KVM: mmu_shrink: kvm_mmu_zap_page requires slots_lock to be held ++ - KVM: SVM: fix suspend/resume support ++ - KVM: VMX: Fix a wrong usage of vmcs_config ++ - isofs: fix minor filesystem corruption ++ - quota: fix possible infinite loop in quota code ++ - hdlcdrv: Fix CRC calculation. ++ - ipv6: __KERNEL__ ifdef struct ipv6_devconf ++ - ipv6: use timer pending ++ - udplite: Protection against coverage value wrap-around ++ - pxamci: trivial fix of DMA alignment register bit clearing ++ * [sparc] Install asm-sparc headers again. ++ * Force RTC on by default and set clock on startup. Override ABI changes. ++ * [i386, amd64] Make the CMOS RTC support builtin. (closes: #493567) ++ * Add stable release 2.6.26.2: ++ - sound: ensure device number is valid in snd_seq_oss_synth_make_info ++ - Ath5k: kill tasklets on shutdown ++ - Ath5k: fix memory corruption ++ - vfs: fix lookup on deleted directory ++ - ALSA: emu10k1 - Fix inverted Analog/Digital mixer switch on Audigy2 ++ - ALSA: hda - Add missing Thinkpad Z60m support ++ - ALSA: hda - Fix DMA position inaccuracy ++ - ALSA: hda - Fix wrong volumes in AD1988 auto-probe mode ++ - Add compat handler for PTRACE_GETSIGINFO ++ - Bluetooth: Signal user-space for HIDP and BNEP socket errors ++ - Input: i8042 - add Acer Aspire 1360 to nomux blacklist ++ - Input: i8042 - add Gericom Bellagio to nomux blacklist ++ - Input: i8042 - add Intel D845PESV to nopnp list ++ - jbd: fix race between free buffer and commit transaction ++ - NFS: Ensure we zap only the access and acl caches when setting new acls ++ - SCSI: ch: fix ch_remove oops ++ - linear: correct disk numbering error check ++ - netfilter: xt_time: fix time's time_mt()'s use of do_div() ++ - Kprobe smoke test lockdep warning ++ - Close race in md_probe ++ - x86: io delay - add checking for NULL early param ++ - x86: idle process - add checking for NULL early param ++ - SCSI: bsg: fix bsg_mutex hang with device removal ++ - netfilter: nf_nat_sip: c= is optional for session ++ - romfs_readpage: don't report errors for pages beyond i_size ++ - ftrace: remove unneeded documentation ++ ++ [ Martin Michlmayr ] ++ * METH: fix MAC address setup (Thomas Bogendoerfer) ++ * Export the reset button of the QNAP TS-409. ++ * net: use software GSO for SG+CSUM capable netdevices (Lennert Buytenhek) ++ ++ [ dann frazier ] ++ * device_create interface changed between 2.6.26 and 2.6.27; adjust hpilo ++ backport appropriately. Fixes a NULL pointer dereference in ilo_probe(). ++ ++ -- Bastian Blank Fri, 08 Aug 2008 08:09:00 +0200 ++ ++linux-2.6 (2.6.26-1) unstable; urgency=low ++ ++ * New upstream release see http://kernelnewbies.org/Linux_2_6_26 ++ - UDF 2.50 support. (closes: #480910) ++ - mmc: increase power up delay (closes: #481190) ++ - snd-hda-intel suspend troubles fixed. (closes: #469727, #481613, #480034) ++ - cifs QueryUnixPathInfo fix (closes: #480995) ++ - r8169 oops in r8169_get_mac_version (closes: #471892) ++ - netfilter headers cleanup (closes: #482331) ++ - iwlwifi led support (closes: #469095) ++ - ath5k associates on AR5213A (closes: #463785) ++ - T42 suspend fix (closes: #485873) ++ - cpuidle acpi driver: fix oops on AC<->DC (closes: #477201) ++ - opti621 ide fixes (closes: #475561) ++ - ssh connection hangs with mac80211 (closes: #486089) ++ - ocfs2: Allow uid/gid/perm changes of symlinks (closes: #479475) ++ - xircom_tulip_cb: oboslete driver removed (closes: #416900) ++ - r8169 properly detect link status (closes: #487586) ++ - iwl3945 connection + support fixes (closes: #481436, #482196) ++ - longrun cpufreq min freq fix (closes: #468149) ++ - emux midi synthesizer SOFT_PEDAL-release event (closes: #474312) ++ - vmemmap fixes to use smaller pages (closes: #483489) ++ - x86 freeze fixes (closes: #482100, #482074) ++ - xen boot failure fix (closes: #488284) ++ - gdb read floating-point and SSE registers (closes: #485375) ++ - USB_PERSIST is default on (closes: #489963) ++ - alsa snd-hda Dell Inspiron fix (closes: #490649) ++ - ipw2200: queue direct scans (closes: #487721) ++ - better gcc-4.3 support (closes: #492301) ++ - iwl3945 monitor mode. (closes: #482387) ++ ++ [ maximilian attems ] ++ * topconfig set CRYPTO_CTS, SND_PCSP, SND_AW2, IWL4965_LEDS, IWL3945_LEDS, ++ RT2400PCI_LEDS, RT2500PCI_LEDS, RT61PCI_LEDS, RT2500USB_LEDS, ++ RT73USB_LEDS, NF_CT_PROTO_DCCP, BRIDGE_EBT_NFLOG, IWLWIFI_RFKILL, ++ USB_SERIAL_SPCP8X5, USB_STORAGE_CYPRESS_ATACB, DVB_ISL6405, DVB_AU8522, ++ VIDEO_EM28XX_DVB, VIDEO_CX18, VIDEO_AU0828, SOC_CAMERA_MT9M001, ++ SOC_CAMERA_MT9V022, DVB_TUNER_ITD1000, VIDEO_PVRUSB2_DVB, USB_C67X00_HCD, ++ USB_ISP1760_HCD, HTC_PASIC3, I2C_PCA_PLATFORM, TOUCHSCREEN_WM97XX, ++ JOYSTICK_ZHENHUA, SFC, ACCESSIBILITY, UIO_SMX, LOGIRUMBLEPAD2_FF, ++ A11Y_BRAILLE_CONSOLE, EDS_TRIGGER_DEFAULT_ON, VIDEO_ALLOW_V4L1, ATA_ACPI, ++ SATA_PMP, ATA_SFF, USB_SERIAL_MOTOROLA, USB_WDM, MAC80211_MESH, ++ IPV6_MROUTE, IPV6_PIMSM_V2, MTD_AR7_PARTS, SENSORS_IBMAEM, PATA_SCH, ++ CGROUP_DEVICE, USB_ISIGHTFW, HW_RANDOM_VIRTIO, RTC_DRV_FM3130, ++ USB_VIDEO_CLASS, CIFS_DFS_UPCALL. ++ * [amd64, i386]: KVM_CLOCK, KVM_GUEST, ISCSI_IBFT_FIND, ISCSI_IBFT, THERMAL, ++ EEEPC_LAPTOP, FB_N411, THERMAL_HWMON. ++ * [amd64]: Enable SCSI_DPT_I2O as 64 bit now. ++ * Reenable USB_SERIAL_EDGEPORT, USB_SERIAL_EDGEPORT_TI. (closes: #480195) ++ * Enable TCP_MD5SIG for BGP sessions. (closes: #443742) ++ * Add recognised alsa cards to bug report. ++ * topconfig: Enable HYSDN, no longer broken on smp. ++ * Add request_firmware patch for keyspan. (closes: #448900) ++ * [x86]: Enable dma engine. (closes: #473331) ++ * [ppc64]: Enable IBMEBUS and EHEA. (closes: #484888) ++ * topconfig: Enable PROFILING across all flavours. (closes: #484885) ++ * 486: enable OLPC support thanks Andres Salomon for merge. ++ Kconfig variable patch by Robert Millan (closes: #485063). ++ * Add request_firmware patch for ip2. ++ * Add request_firmware patch for acenic. (closes: #284221) ++ * [x86, ia64]: Set HPET_RTC_IRQ. (closes: #479709, #476970) ++ * [ppc]: Set SND_VIRMIDI. (closes: #290090) ++ * Fallback for userspace compatibility to old IEEE 1394 FireWire stack. ++ (closes: #451367, #475295, #478419) ++ * [x86]: Enable modular FB_UVESA. (closes: #473180) ++ * JFFS2 enable summary and compressor support. (closes: #488242) ++ * Add OLPC sdhci quirks. Thanks Andres Salomon ++ (closes: #485192) ++ * [ppc]: Enable RTC_DRV_PPC. (closes: #484693) Thanks for the patch to ++ Geoff Levand . ++ * Enable BLK_DEV_BSG for SG v4 support. ++ * [amd64] Enable default disabled memtest boot param. ++ * topconfig: Enable PATA_SIS instead of SATA_SIS. (closes: #485609) ++ * Add OpenVZ countainer flavour for amd64, i386. (closes: #392015) ++ * atl1e driver for Atheros(R) L1e Fast Ethernet. (closes: #492029) ++ * [ALSA] hda - Add ICH9 controller support (8086:2911) ++ * [ALSA] hda - support intel DG33 motherboards ++ * HP iLO driver ++ * Input: i8042 - add Arima-Rioworks HDAMB board to noloop list ++ (closes: #489190) thanks Guillaume Morin ++ ++ [ Martin Michlmayr ] ++ * [arm/orion5x] Update the config to reflect upstream renaming this ++ subarch. ++ * [arm/orion5x] Add some patches from Marvell's Orion tree: ++ - Feroceon: speed up flushing of the entire cache ++ - support for 5281 D0 stepping ++ - cache align destination pointer when copying memory for some processors ++ - cache align memset and memzero ++ - DMA engine driver for Marvell XOR engine ++ - Orion hardware watchdog support ++ * [arm/orion5x] Enable NETCONSOLE. ++ * [arm/orion5x] Disable more SCSI drivers. ++ * [arm/ixp4xx] Disable most ATA and more SCSI and network drivers. ++ * [arm/versatile] Enable CONFIG_RTC_DRV_PL031 (closes: #484432). ++ * [arm/iop32x, arm/ixp4xx, arm/versatile] Enable ARM_THUMB (closes: #484524). ++ * [arm/iop32x] Add LED driver for Thecus N2100 (Riku Voipio). ++ * [mips/r5k-ip32] Enable USB. ++ * [arm/orion5x, arm/iop32x, arm/ixp4xx, mipsel/r5k-cobalt] Enable HAMRADIO ++ on the request of Heinz Janssen. ++ * [arm/orion5x] Add support for QNAP TS-409 and HP mv2120; thanks ++ Sylver Bruneau. ++ * [mips] Add patches from Thomas Bogendoerfer: ++ - gbefb: fix cmap FIFO timeout (closes: #487257) ++ - IP32: Enable FAST-20 for onboard scsi ++ - IP32: SGI O2 sound driver ++ * [arm/ixp4xx] Add support for Freecom FSG-3 (Rod Whitby). ++ * [arm/ixp4xx] Enable CONFIG_MACH_DSMG600. ++ * [arm/iop32x] Unset NET_DMA since it actually leads to worse network ++ performance. ++ * [arm/orion5x] Fix a boot crash on the Kurobox Pro. ++ * [arm/orion5x] use better key codes for the TS-209/TS-409 buttons ++ * [arm/orion5x] export red SATA lights on TS-409, fix SATA presence/activity ++ * [arm] Enable KEXEC (closes: #492268). ++ * [arm/orion5x] Enable USB_PRINTER, requested by Mike Arthur. ++ * [arm/orion5x] Enable binfmt aout, x25, wireless and ATM. ++ * [arm/iop32x, arm/orion5x] Enable USB_SISUSBVGA. ++ * [arm] xfs: pack some shortform dir2 structures for the ARM old ABI ++ architecture (closes: #414932). ++ ++ [ Ian Campbell ] ++ * Readme.build updated on how to generate orig tarballs. ++ * Forward port vmlinuz-target.patch. ++ * Enable Xen save/restore and memory ballooning for Xen enabled kernels. ++ ++ [ Bastian Blank ] ++ * [powerpc/powerpc-miboot] Disable. (closes: #481358) ++ * [powerpc/powerpc64] Support IBM Cell based plattforms and PS3. ++ (closes: #462529) ++ * [s390] Synchronize block device, network bridge, network scheduler and CRC ++ support. ++ * [s390] Enable support for PCI-attached cryptographic adapters. ++ * Use control group as base for group CPU scheduler. This reenabled ++ traditional nice behaviour. (closes: #489223) ++ * Bump yaird dependencies to at least 0.0.13. ++ * Reenable SECCOMP. There is no longer additional overhead. ++ (closes: #474648) ++ * Export symbol required for MOL again. (closes: #460667) ++ * [powerpc/powerpc64] Fix console selection in LPAR environment. ++ (closes: #492703) ++ * Fix several userspace compatibility problems. ++ ++ [ Christian T. Steigies ] ++ * [m68k] enable SERIAL_CONSOLE for amiga and atari ++ ++ [ Thiemo Seufer ] ++ * [mips] Fix logic bug in atomic_sub_if_positive. ++ ++ [ Stephen R. Marenka ] ++ * [m68k] Update pending m68k patches. ++ * [m68k] Enable nfcon and nfblock for atari. ++ * [m68k] Change compiler to default. ++ ++ [ Aurelien Jarno ] ++ * [arm/versatile] Switch scsi/ext3/smc91x to modules now that we have proper ++ d-i support. Remove options defined in toplevel config file. ++ ++ -- Bastian Blank Wed, 30 Jul 2008 10:17:29 +0200 ++ ++linux-2.6 (2.6.25-7) unstable; urgency=high ++ ++ * Add stable release 2.6.25.10: ++ - TTY: fix for tty operations bugs (CVE-2008-2812) ++ - sched: fix cpu hotplug ++ - IB/mthca: Clear ICM pages before handing to FW ++ - DRM: enable bus mastering on i915 at resume time ++ - x86: shift bits the right way in native_read_tscp ++ - x86_64 ptrace: fix sys32_ptrace task_struct leak (CVE-2008-3077) ++ - ptrace GET/SET FPXREGS broken ++ - futexes: fix fault handling in futex_lock_pi ++ - x86: fix cpu hotplug crash ++ * Add stable release 2.6.25.11: ++ - x86: fix ldt limit for 64 bit ++ ++ -- maximilian attems Mon, 14 Jul 2008 10:58:14 +0200 ++ ++linux-2.6 (2.6.25-6) unstable; urgency=high ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.25.7: ++ - double-free of inode on alloc_file() failure exit in create_write_pipe() ++ - m68k: Add ext2_find_{first,next}_bit() for ext4 ++ - bluetooth: fix locking bug in the rfcomm socket cleanup handling ++ - serial: fix enable_irq_wake/disable_irq_wake imbalance in serial_core.c ++ - bttv: Fix a deadlock in the bttv driver (closes: #487594) ++ - forcedeth: msi interrupts ++ - CPUFREQ: Fix format string bug. ++ - mmc: wbsd: initialize tasklets before requesting interrupt ++ - ecryptfs: fix missed mutex_unlock ++ - mac80211: send association event on IBSS create ++ - bluetooth: rfcomm_dev_state_change deadlock fix ++ - sunhv: Fix locking in non-paged I/O case. ++ - cassini: Only use chip checksum for ipv4 packets. ++ - ipwireless: Fix blocked sending ++ - net: Fix call to ->change_rx_flags(dev, IFF_MULTICAST) in ++ dev_change_flags() ++ - fbdev: export symbol fb_mode_option ++ - ipsec: Use the correct ip_local_out function ++ - tcp: fix skb vs fack_count out-of-sync condition ++ - tcp FRTO: Fix fallback to conventional recovery ++ - tcp FRTO: SACK variant is errorneously used with NewReno ++ - tcp FRTO: work-around inorder receivers ++ - tcp: Fix inconsistency source (CA_Open only when !tcp_left_out(tp)) ++ - l2tp: avoid skb truesize bug if headroom is increased ++ - l2tp: Fix possible WARN_ON from socket code when UDP socket is closed ++ - l2tp: Fix possible oops if transmitting or receiving when tunnel goes down ++ - ax25: Fix NULL pointer dereference and lockup. ++ - sound: emu10k1 - fix system hang with Audigy2 ZS Notebook PCMCIA card ++ - tcp: Allow send-limited cwnd to grow up to max_burst when gso disabled ++ - tcp: Limit cwnd growth when deferring for GSO ++ - af_key: Fix selector family initialization. ++ - hgafb: resource management fix ++ - cifs: fix oops on mount when CONFIG_CIFS_DFS_UPCALL is enabled ++ - b43: Fix controller restart crash ++ - ssb: Fix context assertion in ssb_pcicore_dev_irqvecs_enable ++ - eCryptfs: protect crypt_stat->flags in ecryptfs_open() ++ - cciss: add new hardware support ++ - ecryptfs: add missing lock around notify_change ++ - ecryptfs: clean up (un)lock_parent ++ - Add 'rd' alias to new brd ramdisk driver ++ - net_sched: cls_api: fix return value for non-existant classifiers ++ - vlan: Correctly handle device notifications for layered VLAN devices ++ - IB/umem: Avoid sign problems when demoting npages to integer ++ - x86: fix recursive dependencies ++ - can: Fix copy_from_user() results interpretation ++ - Kconfig: introduce ARCH_DEFCONFIG to DEFCONFIG_LIST ++ - tcp: TCP connection times out if ICMP frag needed is delayed ++ - ALSA: hda - Fix resume of auto-config mode with Realtek codecs ++ - netlink: Fix nla_parse_nested_compat() to call nla_parse() directly ++ * Add stable release 2.6.25.9: ++ - Add return value to reserve_bootmem_node() ++ - x86: use BOOTMEM_EXCLUSIVE on 32-bit ++ - sctp: Make sure N * sizeof(union sctp_addr) does not overflow. ++ - hwmon: (lm85) Fix function RANGE_TO_REG() ++ - hwmon: (adt7473) Initialize max_duty_at_overheat before use ++ - x86: set PAE PHYSICAL_MASK_SHIFT to 44 bits. ++ - Reinstate ZERO_PAGE optimization in 'get_user_pages()' and fix XIP ++ - watchdog: hpwdt: fix use of inline assembly ++ - Fix ZERO_PAGE breakage with vmware ++ - atl1: relax eeprom mac address error check ++ ++ [ Martin Michlmayr] ++ * [arm/orion5x] Enable INPUT_EVDEV and KEYBOARD_GPIO. ++ ++ [ Steve Langasek ] ++ * Enable CONFIG_CIFS_EXPERIMENTAL and CONFIG_CIFS_UPCALL, required for ++ CIFS mounts to be able to use Kerberos authentication. Closes: #480663. ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.25.8: ++ - x86: disable mwait for AMD family 10H/11H CPUs ++ - x86: remove mwait capability C-state check ++ - nf_conntrack_h323: fix memory leak in module initialization error path ++ - nf_conntrack_h323: fix module unload crash ++ - nf_conntrack: fix ctnetlink related crash in nf_nat_setup_info() ++ - SCSI: sr: fix corrupt CD data after media change and delay ++ - ACPICA: Ignore ACPI table signature for Load() operator ++ - scsi_host regression: fix scsi host leak ++ - b43: Fix possible NULL pointer dereference in DMA code ++ - b43: Fix noise calculation WARN_ON ++ - virtio_net: Fix skb->csum_start computation ++ - opti621: remove DMA support ++ - opti621: disable read prefetch ++ - Fix tty speed handling on 8250 ++ - x86-64: Fix "bytes left to copy" return value for copy_from_user() ++ * Fix alpha build due too inconsistent kallsyms data. ++ ++ -- maximilian attems Fri, 27 Jun 2008 00:33:53 +0200 ++ ++linux-2.6 (2.6.25-5) unstable; urgency=low ++ ++ [ maximilian attems ] ++ [ Bastian Blank ] ++ * Reenable VServer images. ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.25.5: ++ - asn1: additional sanity checking during BER decoding (CVE-2008-1673) ++ * Add stable release 2.6.25.6: ++ - atl1: fix 4G memory corruption bug ++ - capabilities: remain source compatible with 32-bit raw legacy capability ++ support. ++ - usb-serial: Use ftdi_sio driver for RATOC REX-USB60F ++ - cpufreq: fix null object access on Transmeta CPU ++ - Smack: fuse mount hang fix ++ - cgroups: remove node_ prefix_from ns subsystem ++ - XFS: Fix memory corruption with small buffer reads ++ - x86: don't read maxlvt before checking if APIC is mapped ++ - USB: option: add new Dell 5520 HSDPA variant ++ - md: do not compute parity unless it is on a failed drive ++ - md: fix uninitialized use of mddev->recovery_wait ++ - md: fix prexor vs sync_request race ++ - HID: split Numlock emulation quirk from HID_QUIRK_APPLE_HAS_FN. ++ - USB: do not handle device 1410:5010 in 'option' driver ++ - USB: unusual_devs: Add support for GI 0401 SD-Card interface ++ - USB: add Telstra NextG CDMA id to option driver ++ - USB: fix build errors in ohci-omap.c and ohci-sm501.c ++ - USB: add TELIT HDSPA UC864-E modem to option driver ++ - memory_hotplug: always initialize pageblock bitmap ++ - x86: fix bad pmd ffff810000207xxx(9090909090909090) ++ - USB: add Zoom Telephonics Model 3095F V.92 USB Mini External modem to ++ cdc-acm ++ - x86: prevent PGE flush from interruption/preemption ++ - IPoIB: Test for NULL broadcast object in ipiob_mcast_join_finish() ++ - i386: fix asm constraint in do_IRQ() ++ - i2c-nforce2: Disable the second SMBus channel on the DFI Lanparty NF4 ++ Expert ++ - i2c/max6875: Really prevent 24RF08 corruption ++ - brk: make sys_brk() honor COMPAT_BRK when computing lower bound ++ - Revert "PCI: remove default PCI expansion ROM memory allocation" ++ - PS3: gelic: fix memory leak ++ - eCryptfs: remove unnecessary page decrypt call ++ - netfilter: nf_conntrack_expect: fix error path unwind in ++ nf_conntrack_expect_init() ++ - netfilter: xt_connlimit: fix accouning when receive RST packet in ++ ESTABLISHED state ++ - netfilter: nf_conntrack_ipv6: fix inconsistent lock state in ++ nf_ct_frag6_gather() ++ - POWERPC Bolt in SLB entry for kernel stack on secondary cpus ++ - netfilter: xt_iprange: module aliases for xt_iprange ++ - x86: user_regset_view table fix for ia32 on 64-bit ++ - x86: if we cannot calibrate the TSC, we panic. ++ - CIFS: Fix UNC path prefix on QueryUnixPathInfo to have correct slash ++ - x86, fpu: fix CONFIG_PREEMPT=y corruption of application's FPU stack ++ - libata: force hardreset if link is in powersave mode ++ - x86: fix setup of cyc2ns in tsc_64.c ++ - x86: distangle user disabled TSC from unstable ++ - x86: disable TSC for sched_clock() when calibration failed ++ - pagemap: fix bug in add_to_pagemap, require aligned-length reads of ++ /proc/pid/pagemap ++ - ext3/4: fix uninitialized bs in ext3/4_xattr_set_handle() ++ - proc: calculate the correct /proc/ link count ++ - CPUFREQ: Make acpi-cpufreq more robust against BIOS freq changes behind ++ our back. ++ - USB: remove PICDEM FS USB demo (04d8:000c) device from ldusb ++ - types.h: don't expose struct ustat to userspace ++ ++ [ Bastian Blank ] ++ * Ignore ABI change in internal XFS symbol. ++ ++ -- Bastian Blank Thu, 12 Jun 2008 08:47:11 +0200 ++ ++linux-2.6 (2.6.25-4) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * Fix arm Kconfig logic disabling random drivers. (closes: #481410) ++ * Add stable release 2.6.25.4: ++ - OHCI: fix regression upon awakening from hibernation ++ - V4L/DVB (7473): PATCH for various Dibcom based devices ++ - {nfnetlink, ip, ip6}_queue: fix skb_over_panic when enlarging packets ++ - dccp: return -EINVAL on invalid feature length ++ - md: fix raid5 'repair' operations ++ - sparc: Fix SA_ONSTACK signal handling. ++ - sparc: Fix fork/clone/vfork system call restart. ++ - sparc64: Stop creating dummy root PCI host controller devices. ++ - sparc64: Fix wedged irq regression. ++ - SPARC64: Fix args to 64-bit sys_semctl() via sys_ipc(). ++ - serial: Fix sparc driver name strings. ++ - sparc: Fix ptrace() detach. ++ - sparc: Fix mremap address range validation. ++ - sparc: Fix debugger syscall restart interactions. ++ - sparc32: Don't twiddle PT_DTRACE in exec. ++ - r8169: fix oops in r8169_get_mac_version ++ - SCSI: aha152x: Fix oops on module removal ++ - SCSI: aha152x: fix init suspiciously returned 1, it should follow ++ 0/-E convention ++ - sch_htb: remove from event queue in htb_parent_to_leaf() ++ - i2c-piix4: Blacklist two mainboards ++ - SCSI: qla1280: Fix queue depth problem ++ - ipvs: fix oops in backup for fwmark conn templates ++ - USB: airprime: unlock mutex instead of trying to lock it again ++ - rtc: rtc_time_to_tm: use unsigned arithmetic ++ - SCSI: libiscsi regression in 2.6.25: fix nop timer handling ++ - SCSI: libiscsi regression in 2.6.25: fix setting of recv timer ++ - can: Fix can_send() handling on dev_queue_xmit() failures ++ - macvlan: Fix memleak on device removal/crash on module removal ++ - nf_conntrack: padding breaks conntrack hash on ARM ++ - sparc: sunzilog uart order ++ - r8169: fix past rtl_chip_info array size for unknown chipsets ++ - x86: use defconfigs from x86/configs/* ++ - vt: fix canonical input in UTF-8 mode ++ - ata_piix: verify SIDPR access before enabling it ++ - serial: access after NULL check in uart_flush_buffer() ++ - x86: sysfs cpu?/topology is empty in 2.6.25 (32-bit Intel system) ++ - XFRM: AUDIT: Fix flowlabel text format ambibuity. ++ * Update userspace merged HZ alpha fixed version. ++ * Backport netfilter: Move linux/types.h inclusions outside of #ifdef ++ __KERNEL__. (closes: #479899) ++ * types.h: don't expose struct ustat to userspace. (closes: #429064) ++ ++ [ Bastian Blank ] ++ * Fix ABI changes from: ipvs: fix oops in backup for fwmark conn templates ++ ++ -- maximilian attems Tue, 27 May 2008 11:46:11 +0200 ++ ++linux-2.6 (2.6.25-3) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.25.3: ++ - sit: Add missing kfree_skb() on pskb_may_pull() failure. ++ - sparc: Fix mmap VA span checking. ++ - CRYPTO: eseqiv: Fix off-by-one encryption ++ - CRYPTO: authenc: Fix async crypto crash in crypto_authenc_genicv() ++ - CRYPTO: cryptd: Correct kzalloc error test ++ - CRYPTO: api: Fix scatterwalk_sg_chain ++ - x86 PCI: call dmi_check_pciprobe() ++ - b43: Fix some TX/RX locking issues ++ - kprobes/arm: fix decoding of arithmetic immediate instructions ++ - kprobes/arm: fix cache flush address for instruction stub ++ - b43: Fix dual-PHY devices ++ - POWERPC: mpc5200: Fix unterminated of_device_id table ++ - reiserfs: Unpack tails on quota files ++ - sched: fix hrtick_start_fair and CPU-Hotplug ++ - vfs: fix permission checking in sys_utimensat ++ - md: fix use after free when removing rdev via sysfs ++ - mm: fix usemap initialization ++ - 2.6.25 regression: powertop says 120K wakeups/sec ++ ++ [ maximilian attems ] ++ * Redisable old dup prism54 driver. ++ * Reenable accidentaly disabled SIS190. (closes: #478773) ++ * Add lmkl patch to unbreak HZ userspace aka perl5.10 build fix. ++ (closes: #480130) ++ ++ [ Martin Michlmayr ] ++ * [armel] Disable some SCSI drives (that are disabled on arm) so the ++ ramdisk will fit in flash on NSLU2 (closes: #480310). ++ ++ -- maximilian attems Wed, 14 May 2008 11:16:56 +0200 ++ ++linux-2.6 (2.6.25-2) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.25.1: ++ - Fix dnotify/close race (CVE-2008-1375) ++ - V4L: Fix VIDIOCGAP corruption in ivtv ++ - USB: log an error message when USB enumeration fails ++ - USB: OHCI: fix bug in controller resume ++ - SCSI: qla2xxx: Correct regression in relogin code. ++ - rose: Socket lock was not released before returning to user space ++ - x86, pci: fix off-by-one errors in some pirq warnings ++ - hrtimer: timeout too long when using HRTIMER_CB_SOFTIRQ ++ - RDMA/nes: Fix adapter reset after PXE boot ++ - rtc-pcf8583 build fix ++ - JFFS2: Fix free space leak with in-band cleanmarkers ++ - SELinux: no BUG_ON(!ss_initialized) in selinux_clone_mnt_opts ++ - tehuti: check register size (CVE-2008-1675) ++ - IPSEC: Fix catch-22 with algorithm IDs above 31 ++ - alpha: unbreak OSF/1 (a.out) binaries ++ - tehuti: move ioctl perm check closer to function start (CVE-2008-1675) ++ - aio: io_getevents() should return if io_destroy() is invoked ++ - mm: fix possible off-by-one in walk_pte_range() ++ - TCP: Increase the max_burst threshold from 3 to tp->reordering. ++ - ssb: Fix all-ones boardflags ++ - cgroup: fix a race condition in manipulating tsk->cg_list ++ - drivers/net/tehuti: use proper capability check for raw IO access ++ - tg3: 5701 DMA corruption fix ++ - V4L: tea5761: bugzilla #10462: tea5761 autodetection code were broken ++ - b43: Workaround invalid bluetooth settings ++ - b43: Add more btcoexist workarounds ++ - b43: Workaround DMA quirks ++ - dm snapshot: fix chunksize sector conversion ++ - x86: Fix 32-bit x86 MSI-X allocation leakage ++ - RTNETLINK: Fix bogus ASSERT_RTNL warning ++ - net: Fix wrong interpretation of some copy_to_user() results. ++ - dz: test after postfix decrement fails in dz_console_putchar() ++ - RDMA/nes: Free IRQ before killing tasklet ++ - S2io: Fix memory leak during free_tx_buffers ++ - S2io: Version update for memory leak fix during free_tx_buffers ++ - USB: Add HP hs2300 Broadband Wireless Module to sierra.c ++ - V4L: cx88: enable radio GPIO correctly ++ - hrtimer: raise softirq unlocked to avoid circular lock dependency ++ - tcp: tcp_probe buffer overflow and incorrect return value ++ * [ide] Add upstream piix patch for asus eee pc. (closes: #479217) ++ ++ [ Christian T. Steigies ] ++ * [m68k] Add patches for 2.6.25. ++ * [m68k] Disable EXT4DEV_FS for now. ++ * [m68k] Enable SCSI_MAC_ESP for mac. ++ ++ [ Ian Campbell ] ++ * [x86]: Enable Xen guest support in all i386 flavours. ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.25.2: ++ - fix SMP ordering hole in fcntl_setlk() (CVE-2008-1669) ++ ++ -- Bastian Blank Thu, 08 May 2008 14:46:48 +0200 ++ ++linux-2.6 (2.6.25-1) unstable; urgency=low ++ ++ * New upstream release (closes: #456799, #468440, #475161, #475134, #475441) ++ - Add oabi shim for fstatat64 (closes: #462677) ++ ++ [ maximilian attems ] ++ * topconfig set NOZOMI, CRYPTO_SEQIV, CRYPTO_CTR, CRYPTO_GCM, CRYPTO_CCM, ++ CRYPTO_SALSA20, CRYPTO_LZO, CRYPTO_DEV_HIFN_795X, USB_SI470X, ++ USB_STKWEBCAM, VIDEO_PVRUSB2_ONAIR_USB2, VIDEO_PVRUSB2_ONAIR_CREATOR, ++ VIDEO_EM28XX_ALSA, CRYPTO_DEV_HIFN_795X_RNG, PCF8575, TPS65010, RTL8180, ++ ENC28J60, R6040, CAN, NETFILTER_XT_MATCH_OWNER, MAC80211_RC_DEFAULT_PI, ++ NETFILTER_XT_TARGET_RATEEST, NETFILTER_XT_TARGET_TCPOPTSTRIP, ++ NETFILTER_XT_MATCH_IPRANGE, NETFILTER_XT_MATCH_RATEEST, SND_OXYGEN, ++ SND_HIFIER, SND_VIRTUOSO, USB_NET_RNDIS_WLAN, USB_ANNOUNCE_NEW_DEVICES, ++ USB_SERIAL_IUU, NET_CLS_FLOW, INFINIBAND_NES, RTC_DRV_R9701, ++ RTC_DRV_DS1511, MEMSTICK, SENSORS_W83L786NG, SENSORS_ADS7828, IPWIRELESS, ++ RISCOM8, IGB, UTS_NS, IPC_NS, IPV6_ROUTE_INFO, ENCLOSURE_SERVICES, ++ SCSI_ENCLOSURE, SENSORS_ADT7473, SCSI_MVSAS, REALTEK_PHY, RTC_DRV_S35390A, ++ MEMSTICK_JMICRON_38X, IWL4965_HT. ++ * [amd64] Enable CRYPTO_SALSA20_X86_64, EDAC_I3000, EFI, EFI_VARS, I8K, ++ PARAVIRT_GUEST, PARAVIRT, VIRTIO_PCI, VIRTIO_BALLOON, SPARSEMEM_VMEMMAP. ++ * [amd64, i386]: Enable LEDS_CLEVO_MAIL, INPUT_APANEL, ACER_WMI, ++ THINKPAD_ACPI_HOTKEY_POLL, HP_WATCHDOG, THINKPAD_ACPI_VIDEO, ++ VIRTION_CONSOLE, ACPI_WMI, IO_DELAY_0X80. ++ * topconfig disable PARPORT_PC_FIFO due to instabilities. ++ (closes: #366165, #388309, #406056, #407816, #453911) ++ * [amd64, i386]: Enable SONYPI_COMPAT for better sony laptop support. ++ * topconfig: Enable HID_FF for some HID devices. (closes: #441348) ++ * topconfig: Enable IPV6_ROUTER_PREF for multi-homed net. (closes: #449247) ++ * topconfig: Set UTF8 as default encoding. (closes: #417324) ++ * Tighten yaird dependency. (closes: #403171) ++ * Configs general cleanup, centralize USB_NET, disable IRDA_DEBUG. ++ * postinst: Nuke confusing postinst message. (closes: #465512) ++ * [sparc]: Enable SCSI_SCAN_ASYNC. ++ * [i386]: Enable TC1100_WMI, SND_SIS7019, CRYPTO_SALSA20_586. ++ * topconfig: Centralize old IEEE80211 stack options. (closes: #470558) ++ * control.source.in: Newer standard version without changes. ++ * copyright: adapt to latest lintian recommendation. ++ * input: Add 4 additional exports for modular speakup and braille support. ++ * firewire: Add firewire-git.patch for latest firewire tree features. ++ * 686: Set USB_PERSIST for eee pc suspend support. (closes: #468213) ++ * topconfig disable PATA_SIS as sis5513 enabled. (closes: #475525) ++ * [xen]: Support direct load of bzImage under Xen. (closes: #474509) ++ Thanks Ian Campbell for patches. ++ * [xen]: Module autoprobing support for frontend drivers. ++ * [arm]: Don't ovverride topconfig SENSORS_W83792D setting. ++ (closes: #477745) ++ ++ [ Martin Michlmayr ] ++ * [arm/armel] Add a kernel for Orion based devices, such as the QNAP ++ TS-109/TS-209. ++ * [mips(el)/sb1*] Enable SB1250_MAC (thanks Thomas Bogendoerfer). ++ * [mipsel/r5k-cobalt] Enable DUMMY_CONSOLE since this might ++ fix the debian-installer startup hang on Qube 2700. ++ * [arm/footbridge] Disable KEYS and SECURITY for smaller d-i image. ++ * [arm/footbridge] Build NFS as a module to make the image smaller. ++ * [mips/r5k-ip32] Don't build in NFS. ++ * [mips/r5k-ip32] Use the generic config options for NFS, which will ++ enable NFSv4. (closes: #471007) ++ * [mips/r5k-ip32] Enable R8169, requested by Giuseppe Sacco. ++ * [arm/iop32x] Enable MACH_EM7210. (closes: #473136) ++ * [arm/orion] Add patch to set the MAC address on QNAP TS-109/TS-209 ++ (Lennert Buytenhek). ++ * [arm/orion] Add support for Buffalo Linkstation Pro/Live (Byron Bradley). ++ * [arm/orion] Fix hang when Write Allocate is enabled (Lennert Buytenhek). ++ * [arm/orion] Add support for QNAP TS-409 (Sylver Bruneau). ++ * [arm/orion] Add preliminary support for HP mv2120. ++ ++ [ Daniel Baumann ] ++ * Added patch from unionfs upstream to export release_open_intent symbol. ++ ++ [ Gordon Farquharson ] ++ * [arm/ixp4xx] Use GPIO LED driver as opposed to ixp4xx LED driver. ++ * [arm/ixp4xx] Fix ixp4xx-beeper module so that udev loads it ++ automatically. ++ * [arm/iop32x] Enable support for the GLAN Tank flash chip (M29W400DB). ++ * [arm/iop32x] Do not build the ARTOP PATA driver (PATA_ARTOP). ++ * [arm/iop32x] Register the F75375 device in the GLAN Tank platform code. ++ * Prevent physmap from calling request_module() too early. ++ * [arm/ixp4xx] Fix used_sram_bitmap corruption in qmgr_release_queue(). ++ ++ [ Aurelien Jarno ] ++ * [mips/mipsel] Enable CONFIG_NO_HZ, CONFIG_HIGH_RES_TIMERS for dynticks ++ and true high-resolution timers on 4kc-malta and 5kc-malta flavours. ++ * [i386, amd64] Set modular VIRTIO, VIRTIO_RING, VIRTIO_BLK, VIRTIO_NET. ++ ++ [ Bastian Blank ] ++ * Remove binary only firmwares for: ++ - Broadcom NetXtremeII 10Gb support ++ * Disable now broken drivers: ++ - Broadcom NetXtremeII 10Gb support ++ * Fix broken drivers: ++ - Broadcom NetXtremeII support ++ * [powerpc] Use new wrapper install support. ++ * [s390] Enable DM_MULTIPATH_EMC. ++ * Enable AF_RXRPC, RXKAD, PRINTK_TIME, DEBUG_KERNEL, SCHED_DEBUG, ++ TIMER_STATS, DEBUG_FS. ++ * Disable R3964, USB_GADGET. ++ * [hppa] Enable several filesystems. ++ * Make NLS modular. ++ * [i386/486] Make ext2 modular. ++ * [alpha,amd64,i386] Make ATM modular. ++ * [powerpc/powerpc64] Support PA Semi based plattforms. (closes: #463200) ++ * Follow upstream change for default TCP congestion control. ++ (closes: #477589) ++ ++ [ Steve Langasek ] ++ * topconfig: Enable CONFIG_CIFS_WEAK_PW_HASH, required for compatibility ++ with legacy (pre-NTLM) fileservers. ++ ++ [ Christian Perrier ] ++ * Debconf template rewrite + mark them as translatable. ++ Thanks to Justin B Rye for review. ++ ++ -- Bastian Blank Fri, 25 Apr 2008 16:27:23 +0200 ++ ++linux-2.6 (2.6.24-6) unstable; urgency=high ++ ++ [ Martin Michlmayr ] ++ * [armel] Fix FTBFS on armel by enabling CONFIG_USB_USBNET=m in ++ armel/config, as it was done for arm/config already. ++ * [armel] Add oabi shim for fstatat64 (Riku Voipio) ++ ++ [ Gordon Farquharson ] ++ * [arm/iop32x] Do not build the ARTOP PATA driver (PATA_ARTOP). ++ * [arm/iop32x] Enable MTD_CMDLINE_PARTS. ++ ++ [ Kyle McMartin ] ++ * [hppa] fix pdc_console panic at boot (closes: #476292). ++ * [hppa] properly flush user signal tramps ++ * [hppa] special case futex cmpxchg on kernel space NULL (closes: 476285). ++ ++ -- Bastian Blank Fri, 18 Apr 2008 19:41:30 +0200 ++ ++linux-2.6 (2.6.24-5) unstable; urgency=low ++ ++ [ Gordon Farquharson ] ++ * [arm] Enable asix driver (USB_NET_AX8817X). ++ * [arm] Enable CONFIG_USB_CATC, CONFIG_USB_KAWETH, CONFIG_USB_PEGASUS, ++ and CONFIG_USB_RTL8150. ++ * [arm/ixp4xx] Update Ethernet driver (closes: #471062). ++ * [arm/ixp4xx] Add HSS driver. ++ ++ [ Bastian Blank ] ++ * [s390/s390-tape]: Override localversion correctly. ++ * Add stable release 2.6.24.3: ++ - x86_64: CPA, fix cache attribute inconsistency bug ++ - bonding: fix NULL pointer deref in startup processing ++ - POWERPC: Revert chrp_pci_fixup_vt8231_ata devinit to fix libata on pegasos ++ - PCMCIA: Fix station address detection in smc ++ - SCSI: gdth: scan for scsi devices ++ - USB: fix pm counter leak in usblp ++ - S390: Fix futex_atomic_cmpxchg_std inline assembly. ++ - genirq: do not leave interupts enabled on free_irq ++ - hrtimer: catch expired CLOCK_REALTIME timers early ++ - hrtimer: check relative timeouts for overflow ++ - SLUB: Deal with annoying gcc warning on kfree() ++ - hrtimer: fix *rmtp/restarts handling in compat_sys_nanosleep() ++ - hrtimer: fix *rmtp handling in hrtimer_nanosleep() ++ - Disable G5 NAP mode during SMU commands on U3 ++ - Be more robust about bad arguments in get_user_pages() ++ - AUDIT: Increase skb->truesize in audit_expand ++ - BLUETOOTH: Add conn add/del workqueues to avoid connection fail. ++ - INET: Prevent out-of-sync truesize on ip_fragment slow path ++ - INET_DIAG: Fix inet_diag_lock_handler error path. ++ - IPCOMP: Fetch nexthdr before ipch is destroyed ++ - IPCOMP: Fix reception of incompressible packets ++ - IPV4: fib: fix route replacement, fib_info is shared ++ - IPV4: fib_trie: apply fixes from fib_hash ++ - PKT_SCHED: ematch: oops from uninitialized variable (resend) ++ - SELinux: Fix double free in selinux_netlbl_sock_setsid() ++ - TC: oops in em_meta ++ - TCP: Fix a bug in strategy_allowed_congestion_control ++ - SCSI: sd: handle bad lba in sense information ++ - Fix dl2k constants ++ - XFS: Fix oops in xfs_file_readdir() ++ - hugetlb: add locking for overcommit sysctl ++ - inotify: fix check for one-shot watches before destroying them ++ - NFS: Fix a potential file corruption issue when writing ++ - NETFILTER: nf_conntrack_tcp: conntrack reopening fix ++ - SPARC/SPARC64: Fix usage of .section .sched.text in assembler code. ++ * Add stable release 2.6.24.4: ++ - S390 futex: let futex_atomic_cmpxchg_pt survive early functional tests. ++ - slab: NUMA slab allocator migration bugfix ++ - relay: fix subbuf_splice_actor() adding too many pages ++ - BLUETOOTH: Fix bugs in previous conn add/del workqueue changes. ++ - SCSI advansys: Fix bug in AdvLoadMicrocode ++ - async_tx: avoid the async xor_zero_sum path when src_cnt > device->max_xor ++ - aio: bad AIO race in aio_complete() leads to process hang ++ - jbd: correctly unescape journal data blocks ++ - jbd2: correctly unescape journal data blocks ++ - zisofs: fix readpage() outside i_size ++ - NETFILTER: nfnetlink_log: fix computation of netlink skb size ++ - NETFILTER: nfnetlink_queue: fix computation of allocated size for netlink skb ++ - NETFILTER: xt_time: fix failure to match on Sundays ++ - sched_nr_migrate wrong mode bits ++ - nfsd: fix oops on access from high-numbered ports ++ - sched: fix race in schedule() ++ - SCSI: mpt fusion: don't oops if NumPhys==0 ++ - SCSI: gdth: fix to internal commands execution ++ - SCSI: gdth: bugfix for the at-exit problems ++ - Fix default compose table initialization ++ - x86: don't use P6_NOPs if compiling with CONFIG_X86_GENERIC ++ - SCSI: fix BUG when sum(scatterlist) > bufflen ++ - USB: ehci: handle large bulk URBs correctly (again) ++ - USB: ftdi_sio - really enable EM1010PC ++ - USB: ftdi_sio: Workaround for broken Matrix Orbital serial port ++ - VT notifier fix for VT switch ++ - eCryptfs: make ecryptfs_prepare_write decrypt the page ++ - ioat: fix 'ack' handling, driver must ensure that 'ack' is zero ++ - macb: Fix speed setting ++ - x86: move out tick_nohz_stop_sched_tick() call from the loop ++ - atmel_spi: fix clock polarity ++ - b43: Backport bcm4311 fix ++ - arcmsr: fix IRQs disabled warning spew ++ - e1000e: Fix CRC stripping in hardware context bug ++ - PCI x86: always use conf1 to access config space below 256 bytes ++ - moduleparam: fix alpha, ia64 and ppc64 compile failures ++ - pata_hpt*, pata_serverworks: fix UDMA masking ++ - SCSI advansys: fix overrun_buf aligned bug ++ - NETFILTER: fix ebtable targets return ++ - NETFILTER: Fix incorrect use of skb_make_writable ++ - NETFILTER: nfnetlink_queue: fix SKB_LINEAR_ASSERT when mangling packet data ++ - spi: pxa2xx_spi clock polarity fix ++ - ufs: fix parenthesisation in ufs_set_fs_state() ++ - hugetlb: ensure we do not reference a surplus page after handing it to buddy ++ - file capabilities: simplify signal check ++ - futex: runtime enable pi and robust functionality ++ - futex: fix init order ++ - ARM pxa: fix clock lookup to find specific device clocks ++ - x86: replace LOCK_PREFIX in futex.h ++ - SCSI aic94xx: fix REQ_TASK_ABORT and REQ_DEVICE_RESET ++ - SCSI gdth: don't call pci_free_consistent under spinlock ++ - SCSI ips: fix data buffer accessors conversion bug ++ - usb-storage: don't access beyond the end of the sg buffer ++ - fuse: fix permission checking ++ - CRYPTO xts: Use proper alignment ++ - CRYPTO xcbc: Fix crash with IPsec ++ - SCSI ips: handle scsi_add_host() failure, and other err cleanups ++ - x86: adjust enable_NMI_through_LVT0() ++ - drivers: fix dma_get_required_mask ++ - iov_iter_advance() fix ++ - x86: Clear DF before calling signal handler (closes: #469058) ++ - ub: fix up the conversion to sg_init_table() ++ - MIPS: Mark all but i8259 interrupts as no-probe. ++ - IRQ_NOPROBE helper functions ++ - IPCOMP: Disable BH on output when using shared tfm ++ - IPCONFIG: The kernel gets no IP from some DHCP servers ++ - IPV4: Remove IP_TOS setting privilege checks. ++ - IPV6: dst_entry leak in ip4ip6_err. ++ - IPV6: Fix IPsec datagram fragmentation ++ - NET: Fix race in dev_close(). (Bug 9750) ++ - NET: Messed multicast lists after dev_mc_sync/unsync (closes: #466719) ++ - NIU: Bump driver version and release date. ++ - NIU: Fix BMAC alternate MAC address indexing. ++ - NIU: More BMAC alt MAC address fixes. ++ - TCP: Improve ipv4 established hash function. ++ - SPARC: Fix link errors with gcc-4.3 ++ - SPARC64: Loosen checks in exception table handling. ++ ++ [ Martin Michlmayr ] ++ * [mips/r4k-ip22] Enable BLK_DEV_LOOP and BLK_DEV_CRYPTOLOOP. ++ * [mips/r5k-ip32] Enable BLK_DEV_LOOP and BLK_DEV_CRYPTOLOOP. ++ * [mips/r4k-ip22] Enable PPP, PPPOE and SLIP. ++ * [mips/r5k-ip32] Enable PPP, PPPOE and SLIP. ++ * Don't check the section size when we're cross compiling. ++ ++ [ dann frazier ] ++ * Remove cap_task_kill (closes: #463669) ++ ++ -- Bastian Blank Thu, 27 Mar 2008 12:40:16 +0100 ++ ++linux-2.6 (2.6.24-4) unstable; urgency=low ++ ++ * Add stable release 2.6.24.1: ++ - splice: missing user pointer access verification (CVE-2008-0009/10) ++ - drm: the drm really should call pci_set_master.. ++ - Driver core: Revert "Fix Firmware class name collision" ++ - fix writev regression: pan hanging unkillable and un-straceable ++ - sched: fix high wake up latencies with FAIR_USER_SCHED ++ - sched: let +nice tasks have smaller impact ++ - b43: Reject new firmware early ++ - selinux: fix labeling of /proc/net inodes ++ - b43legacy: fix DMA slot resource leakage ++ - b43legacy: drop packets we are not able to encrypt ++ - b43legacy: fix suspend/resume ++ - b43legacy: fix PIO crash ++ - b43: Fix dma-slot resource leakage ++ - b43: Drop packets we are not able to encrypt ++ - b43: Fix suspend/resume ++ - sky2: fix for WOL on some devices ++ - sky2: restore multicast addresses after recovery ++ - x86: restore correct module name for apm ++ - ACPI: update ACPI blacklist ++ - PCI: Fix fakephp deadlock ++ - sys_remap_file_pages: fix ->vm_file accounting ++ - lockdep: annotate epoll ++ - forcedeth: mac address mcp77/79 ++ - USB: Fix usb_serial_driver structure for Kobil cardreader driver. ++ - USB: handle idVendor of 0x0000 ++ - USB: fix usbtest halt check on big endian systems ++ - USB: storage: Add unusual_dev for HP r707 ++ - USB: Variant of the Dell Wireless 5520 driver ++ - USB: use GFP_NOIO in reset path ++ - USB: ftdi driver - add support for optical probe device ++ - USB: pl2303: add support for RATOC REX-USB60F ++ - USB: remove duplicate entry in Option driver and Pl2303 driver for Huawei modem ++ - USB: sierra: add support for Onda H600/Zte MF330 datacard to USB Driver for Sierra Wireless ++ - USB: ftdi-sio: Patch to add vendor/device id for ATK_16IC CCD ++ - USB: ftdi_sio - enabling multiple ELV devices, adding EM1010PC ++ - USB: sierra driver - add devices ++ - USB: Adding YC Cable USB Serial device to pl2303 ++ - USB: Sierra - Add support for Aircard 881U ++ - USB: add support for 4348:5523 WinChipHead USB->RS 232 adapter ++ - USB: CP2101 New Device IDs ++ - usb gadget: fix fsl_usb2_udc potential OOPS ++ - USB: keyspan: Fix oops ++ - vm audit: add VM_DONTEXPAND to mmap for drivers that need it (CVE-2008-0007) ++ - slab: fix bootstrap on memoryless node ++ - DVB: cx23885: add missing subsystem ID for Hauppauge HVR1800 Retail ++ ++ [ Martin Michlmayr ] ++ * [arm/ixp4xx] Enble ATA_OVER_ETH, requested by Nicola Fankhauser. ++ * [arm/iop32x] Enble ATA_OVER_ETH. ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.24.2: ++ - splice: fix user pointer access in get_iovec_page_array() ++ (CVE-2008-0600, closes: #464945) ++ ++ -- Bastian Blank Mon, 11 Feb 2008 12:29:23 +0100 ++ ++linux-2.6 (2.6.24-3) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * [scsi]: hptiop: add more adapter models and fixes. ++ * [amd64, i386]: Reenable ACPI_PROCFS_POWER. (closes: #463253) ++ ++ [ Gordon Farquharson ] ++ * [arm/ixp4xx] Update Ethernet driver so that it can be loaded by udev ++ automatically. ++ ++ [ Martin Michlmayr ] ++ * [mips/r5k-ip32] Enable R8169, requested by Giuseppe Sacco. (Closes: ++ #463705) ++ ++ -- Bastian Blank Wed, 06 Feb 2008 13:05:18 +0100 ++ ++linux-2.6 (2.6.24-2) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Fix broken merge of flavour specific settings. ++ - [i386]: Recommends are fixed. ++ - [s390/s390-tape]: Built as small image again. ++ ++ [ maximilian attems ] ++ * Disable old dup prism54 driver. ++ * Stable queue: slab: fix bootstrap on memoryless node. ++ ++ [ Aurelien Jarno ] ++ * [arm]: Remove options that are present in topconfig from config.versatile. ++ * [arm]: Turn off B44 since it fails to compile on armel. ++ ++ -- Bastian Blank Thu, 31 Jan 2008 17:37:00 +0100 ++ ++linux-2.6 (2.6.24-1) unstable; urgency=low ++ ++ * New upstream release ++ (closes: #461639) ++ ++ [ Martin Michlmayr ] ++ * Don't build the AdvanSys driver on ARM since it fails to compile. ++ * Disable ATH5K on ARM since it fails to compile. ++ * [arm/iop32x] Activate DMADEVICES. ++ * [mips/mipsel] Turn off CONFIG_NIU since it fails to compile. ++ ++ [ maximilian attems ] ++ * [amd64, i386]: Enable ACPI_SYSFS_POWER and disable ACPI_PROCFS_POWER. ++ * [fw] Sync with latest git-ieee1394 for sbp2 fixes. ++ ++ [ Bastian Blank ] ++ * Kill reboot warning from old templates. ++ * Fix strange default value for link_in_boot. (closes: #425056) ++ * [powerpc/powerpc]: Enable Efika support. ++ * [powerpc]: Lower mkvmlinuz to the state of a bootloader. ++ * [powerpc]: Remove ppc and m68k include dirs from headers. ++ * Remove versions from relations fullfilled in stable. ++ ++ [ Aurelien Jarno ] ++ * [arm]: Update versatile config. ++ ++ [ Gordon Farquharson ] ++ * [arm/ixp4xx] Change the ixp4xx network driver from the driver ++ written by Christian Hohnstaedt to the driver written by Krzysztof ++ Hasala which has partially been accepted upstream. ++ ++ -- Bastian Blank Sat, 26 Jan 2008 11:35:11 +0100 ++ ++linux-2.6 (2.6.24~rc8-1~experimental.1) experimental; urgency=low ++ ++ * New upstream release ++ (closes: #454776, #458142, #457992, #458899, #426124, #459732, #455566). ++ ++ [ maximilian attems ] ++ * New upstream release, rebase dfsg stuff plus drivers-atm.patch, ++ scripts-kconfig-reportoldconfig.patch. ++ * [amd64, powerpc] Set HIGH_RES_TIMERS and NO_HZ (closes: #458312). ++ * topconfig set NETFILTER_XT_MATCH_TIME, NET_ACT_NAT, KSDAZZLE_DONGLE, ++ KS959_DONGLE, NET_9P_FD, IP1000, VETH, IXGBE, NIU, TEHUTI, LIBERTAS_CS, ++ LIBERTAS_SDIO, RT2X00, SENSORS_ADT7470, SENSORS_I5K_AMB, SENSORS_F71882FG, ++ SENSORS_FSCHMD, SENSORS_IBMPEX, CRYPTO_XTS, CRYPTO_SEED, CRYPTO_AUTHENC, ++ DVB_S5H1409, DVB_TUNER_MT2131, INET_LRO, MMC_RICOH_MMC, MMC_SPI, ++ RTC_DRV_DS1374, VIDEO_CX23885, VIDEO_FB_IVTV, USB_SERIAL_CH341, ++ SCSI_SRP_TGT_ATTRS, ADM8211, MTD_INTEL_VR_NOR, MTD_ALAUDA, ++ MTD_ONENAND_2X_PROGRAM, MTD_ONENAND_SIM, DM_MULTIPATH_HP, FUJITSU_LAPTOP, ++ QUOTA_NETLINK_INTERFACE, DM_UEVENT, SCSI_FC_TGT_ATTRS, SSB, BT_HCIUART_LL, ++ BT_HCIBTSDIO, MTD_OOPS, CGROUPS, MDIO_BITBANG, HIDRAW, P54, SDIO_UART, ++ NETCONSOLE_DYNAMIC, SECURITY_FILE_CAPABILITIES. ++ * Disable smbfs in topconfig, not supported upstream, use cifs. ++ * Disable bcm43xx, deprecated by upstream. Enable B43 (needs v4 firmware) ++ and B43LEGACY (needs v3 firmware). ++ * [i386]: Set SND_SC6000, EDAC_I3000, EDAC_I5000, SBC7240_WDT, ++ NET_9P_VIRTIO, FB_GEODE_LX, VIRTIO_NET, VIRTIO_BLK. ++ * Set USB_EHCI_TT_NEWSCHED fills USB 2.0 bandwith better. (closes: #454797) ++ * postrm: Nuke initramfs sha1sum on linux-image removal. (closes: #420245) ++ * Unifiy BSD_PROCESS_ACCT settings across configs. (closes: #455892) ++ * Reenable DABUSB as firmware is BSD licensed. ++ * [hppa]: Disable OCFS2, due build trouble. ++ * topconfig: Enable delay accounting TASKSTATS. (closes: #433204) ++ * Add git-ieee1394.patch for latest firewire fixes. ++ * [i386] Enable PARAVIRT_GUEST. (closes: #457562) ++ * [amd64, i386] Enable CPU_IDLE for software-controlled idle pm. ++ * [amd64, i386] Enable IT8712F_WDT, FB_EFI. ++ * Add and enable at76.patch wireless driver for Atmel USB cards. ++ * Add and enable ath5k.patch wireless driver for Atheros 5xxx cards. ++ * Unify VLAN_8021Q setting, needed also on r5k-cobalt. ++ * Double max SERIAL_8250_NR_UARTS to 32. (closes: #440807) ++ * topconfig: Enable AUDITSYSCALL for better SELinux support. ++ ++ [ Bastian Blank ] ++ * [amd64, i386]: Set kernel architecture to x86. ++ * [i386]: Remove linux-libc-dev arch override. ++ ++ [ Martin Michlmayr ] ++ * [mipsel/r5k-cobalt] Enable the new LEDs driver for Cobalt RaQ. ++ * [arm/iop32x] Re-enable USB_NET and PPP, thanks Daniel Hess (closes: ++ #456416). ++ * [arm/iop32x] Enable BSD_PROCESS_ACCT and POSIX_MQUEUE (closes: #455892). ++ * [mips] Disable AdvanSys SCSI since it doesn't compile. ++ * [arm/ixp4xx] Enable IP_ADVANCED_ROUTER, requested by Oliver Urbann. ++ * [arm/iop32x] Enable IP_ADVANCED_ROUTER. ++ ++ [ dann frazier ] ++ * [ia64]: Enable BLK_CPQ_DA ++ ++ [ Frederik Schüler ] ++ * Add GFS2 locking symbols export patch. ++ ++ [ Aurelien Jarno ] ++ * [mips/mipsel] Remove QEMU flavour, as the Malta platform is now correctly ++ emulated in QEMU. ++ ++ [ Christian T. Steigies ] ++ * [m68k]: Update patches from linux-m68k CVS ++ * [m68k]: Enable building for bvme6000, mvme147, and mvme16x again ++ ++ -- Bastian Blank Fri, 18 Jan 2008 12:23:26 +0100 ++ ++linux-2.6 (2.6.23-2) unstable; urgency=low ++ ++ [ dann frazier ] ++ * [ia64]: Enable BLK_CPQ_DA ++ ++ [ Gordon Farquharson ] ++ * [arm/iop32x] Use the new i2c framework to load rtc-rs5c372 for the ++ GLAN Tank. ++ ++ [ Frederik Schüler ] ++ * Export gfs2 locking symbols required to build gfs1 module. ++ ++ [ maximilian attems ] ++ * [ppc] Reenable PMAC_BACKLIGHT. ++ * [sparc] Add davem get_cpu() SunFire boot patch. (closes: #440720) ++ * Add stable release 2.6.23.10: ++ - IPV4: Remove bogus ifdef mess in arp_process ++ - KVM: x86 emulator: Use emulator_write_emulated and not emulator_write_std ++ - KVM: SVM: Fix FPU leak while emulating clts ++ - revert "dpt_i2o: convert to SCSI hotplug model" ++ - KVM: x86 emulator: fix access registers for instructions with ModR/M ++ byte and Mod = 3 ++ - KVM: x86 emulator: invd instruction ++ - KVM: SVM: Intercept the 'invd' and 'wbinvd' instructions ++ - KVM: Skip pio instruction when it is emulated, not executed ++ - KVM: VMX: Force vm86 mode if setting flags during real mode ++ - forcedeth: new mcp79 pci ids ++ - forcedeth boot delay fix ++ - PFKEY: Sending an SADB_GET responds with an SADB_GET ++ - rd: fix data corruption on memory pressure. ++ - create /sys/.../power when CONFIG_PM is set ++ - USB: fix up EHCI startup synchronization ++ - RXRPC: Add missing select on CRYPTO ++ - KVM: VMX: Reset mmu context when entering real mode ++ - NET: random : secure_tcp_sequence_number should not assume ++ CONFIG_KTIME_SCALAR ++ - NET: Corrects a bug in ip_rt_acct_read() ++ - NETFILTER: Fix NULL pointer dereference in nf_nat_move_storage() ++ - netfilter: Fix kernel panic with REDIRECT target. ++ - IPV6: Restore IPv6 when MTU is big enough ++ - UNIX: EOF on non-blocking SOCK_SEQPACKET ++ - x86 setup: add a near jump to serialize %cr0 on 386/486 ++ - Fix synchronize_irq races with IRQ handler ++ - CRYPTO api: Fix potential race in crypto_remove_spawn ++ - TCP: Fix TCP header misalignment ++ - tmpfs: restore missing clear_highpage (CVE-2007-6417) ++ - TCP: MTUprobe: fix potential sk_send_head corruption ++ - NETFILTER: fix forgotten module release in xt_CONNMARK and xt_CONNSECMARK ++ - fb_ddc: fix DDC lines quirk ++ - VLAN: Fix nested VLAN transmit bug ++ - I4L: fix isdn_ioctl memory overrun vulnerability (CVE-2007-6151) ++ - isdn: avoid copying overly-long strings ++ - nf_nat: fix memset error ++ - esp_scsi: fix reset cleanup spinlock recursion ++ - libertas: properly account for queue commands ++ - KVM: Fix hang on uniprocessor ++ - USB: make the microtek driver and HAL cooperate ++ - TEXTSEARCH: Do not allow zero length patterns in the textsearch ++ infrastructure ++ - XFRM: Fix leak of expired xfrm_states ++ - NETFILTER: xt_TCPMSS: remove network triggerable WARN_ON ++ - BRIDGE: Lost call to br_fdb_fini() in br_init() error path ++ - DECNET: dn_nl_deladdr() almost always returns no error ++ - BRIDGE: Properly dereference the br_should_route_hook ++ - PKT_SCHED: Check subqueue status before calling hard_start_xmit ++ - Freezer: Fix APM emulation breakage ++ - XFS: Make xfsbufd threads freezable ++ - TCP: Problem bug with sysctl_tcp_congestion_control function ++ - wait_task_stopped(): pass correct exit_code to wait_noreap_copyout() ++ - KVM: x86 emulator: implement 'movnti mem, reg' ++ - TCP: illinois: Incorrect beta usage ++ - futex: fix for futex_wait signal stack corruption ++ - libata: kill spurious NCQ completion detection ++ - hrtimers: avoid overflow for large relative timeouts (CVE-2007-5966) ++ - Input: ALPS - add support for model found in Dell Vostro 1400 ++ (closes: #448818) ++ - PNP: increase the maximum number of resources ++ - sched: some proc entries are missed in sched_domain sys_ctl debug code ++ - ATM: [he] initialize lock and tasklet earlier ++ * Add stable release 2.6.23.11: ++ - BRIDGE: Section fix. ++ - Revert "Freezer: Fix APM emulation breakage" ++ * Backport fix for CVE-2007-5938 ++ - iwlwifi: fix possible NULL dereference in iwl_set_rate() ++ * Add stable release 2.6.23.12: ++ - Revert "PNP: increase the maximum number of resources" ++ * VM/Security: add security hook to do_brk (CVE-2007-6434) ++ * security: protect from stack expantion into low vm addresses ++ * [hppa]: Disable OCFS2, due build trouble. ++ ++ [ Aurelien Jarno ] ++ * [arm/versatile] Disable ACENIC and MYRI10GE as they are useless on this ++ platform. ++ * Add em28xx-dv100.patch to add support for Pinnacle Dazzle DVC 100. ++ ++ [ Bastian Blank ] ++ * Fix abi change in 2.6.23.10. ++ ++ -- maximilian attems Fri, 21 Dec 2007 11:47:55 +0100 ++ ++linux-2.6 (2.6.23-1) unstable; urgency=low ++ ++ * New upstream release (closes: #447682). ++ - r8169: fix confusion between hardware and IP header alignment ++ (closes: #452069). ++ ++ [ maximilian attems ] ++ * [ppc] Enable for powerpc config the ams (Apple Motion Sensor). ++ (closes: #426210) ++ * Add to linux-doc the missing toplevel text files. ++ (closes: #360876, #438697) ++ * Set CONFIG_BLK_DEV_IO_TRACE for blktrace(8) support. (closes: #418442) ++ * ipw2200: Enable IPW2200_RADIOTAP and IPW2200_PROMISCUOUS for optional ++ rtap interface. (closes: #432555) ++ * Enable in topconfig NF_CT_PROTO_UDPLITE, NETFILTER_XT_TARGET_TRACE, ++ NETFILTER_XT_MATCH_CONNLIMIT, NETFILTER_XT_MATCH_U32, SENSORS_ABITUGURU3, ++ SENSORS_LM93, SENSORS_DME1737, SENSORS_THMC50, DVB_USB_AF9005, ++ DVB_USB_AF9005_REMOTE, CRC7, I2C_TAOS_EVM, DS1682, SENSORS_TSL2550, ++ SPI_LM70_LLP, SPI_TLE62X0, W1_SLAVE_DS2760, TUNER_TEA5761, NET_9P, ++ DM_MULTIPATH_RDAC, NET_SCH_RR, EEPROM_93CX6, PPPOL2TP, CRYPTO_HW, UIO, ++ UIO_CIF, SND_CS5530, RTL8187, PC300TOO, TCG_TIS, SCSI_SAS_ATA, ++ PATA_MARVELL. ++ * [i386] Enable lguest. ++ * [amd64, i386] Enable VIDEO_OUTPUT_CONTROL, NETDEVICES_MULTIQUEUE. ++ * linux-image bugscript add cmdline. ++ * [amd64, i386, ia64]: Enable DMIID, ACPI_PROC_EVENT. ++ * Enable TCG_TPM various userspace accesses it. (closes: #439020) ++ * Add and enable IWLWIFI. ++ * Add git-ieee1394.patch for latest firewire fixes. ++ * [ipv6] Enable IPV6_MULTIPLE_TABLES, IPV6_SUBTREES. (closes: #441226) ++ * Add and enable E1000E. ++ * Add stable release 2.6.23.1: ++ - libata: sata_mv: more S/G fixes ++ ++ [ Martin Michlmayr ] ++ * [mips] Add a bcm1480 PCI build fix. ++ * Update Riku Voipio's Fintek F75375/SP driver to the latest version. ++ * [arm/iop32x] Set the fan on Thecus N2100 to full speed (Riku Voipio). ++ * [arm/iop32x] Remove the IPv6 and filesystem info from the config file ++ so we will get the values from the main config file. This should ++ enable NFSv4 and ip6tables support requested by Wouter Verhelst. ++ * [arm/iop32x] Remove even more options to receive the default options. ++ * [arm/ixp4xx] Remove a lot of options to receive the default options. ++ * [mips/r4k-ip22] Remove a lot of options to receive the default options. ++ This will enable ISCSI requested by Martin Zobel-Helas. ++ * [mips/r5k-ip32] Remove a lot of options to receive the default options. ++ This will enable PCI Ethernet devices requested by Giuseppe Sacco. ++ * [mipsel/r5k-cobalt] Remove a lot of options to receive the default ++ options. ++ * [mipsel/r5k-cobalt] Enable the modern Cobalt LEDs driver. ++ * [arm/iop32x] Enable Intel IOP ADMA support. ++ * [arm] Mark BCM43XX as broken on ARM. ++ * [mips/r4k-ip22] Disable EARLY PRINTK because it breaks serial console. ++ * [mips] Add some IP22 fixes from Thomas Bogendoerfer: ++ - Fix broken EISA interrupt setup by switching to generic i8259 ++ - Fix broken eeprom access by using __raw_readl/__raw_writel ++ ++ [ Bastian Blank ] ++ * Add unpriviledged only Xen support. ++ * [i386] Drop k7 images. ++ * Drop maybe IETF document. (closes: #423040) ++ * Drop drivers because of binary only firmwares: ++ - DABUSB driver ++ - COPS LocalTalk PC support ++ - Digi Intl. RightSwitch SE-X support ++ - 3Com 3C359 Token Link Velocity XL adapter support ++ - SMC ISA/MCA adapter support ++ - EMI 6|2m USB Audio interface support ++ - EMI 2|6 USB Audio interface support ++ - Computone IntelliPort Plus serial support ++ * Remove binary only firmwares for: ++ - Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support ++ - Broadcom Tigon3 support ++ - USB Keyspan USA-xxx Serial Driver ++ - Korg 1212 IO ++ - ESS Allegro/Maestro3 ++ - Yamaha YMF724/740/744/754 ++ - Technotrend/Hauppauge Nova-USB devices ++ - YAM driver for AX.25 ++ - MyriCOM Gigabit Ethernet support ++ - PTI Qlogic, ISP Driver ++ - Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x ++ - Madge Ambassador (Collage PCI 155 Server) ++ - PCA-200E support ++ - SBA-200E support ++ - Broadcom NetXtremeII support ++ * Disable now broken drivers: ++ - Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support ++ - USB Keyspan USA-xxx Serial Driver ++ - Technotrend/Hauppauge Nova-USB devices ++ - YAM driver for AX.25 ++ - MyriCOM Gigabit Ethernet support ++ - PTI Qlogic, ISP Driver ++ - Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x ++ - Madge Ambassador (Collage PCI 155 Server) ++ - PCA-200E support ++ - SBA-200E support ++ - Broadcom NetXtremeII support ++ * Add -common to common header package names. ++ * Drop provides from common header packages. ++ * Update plain image type. ++ * Put only a config dump into linux-support. ++ ++ [ Aurelien Jarno ] ++ * [mips, mipsel] Add a 64-bit image (5kc-malta) for the MIPS Malta board. ++ (closes: #435677) ++ [sparc] Enable r8169 module on sparc64 and sparc64-smp flavours (closes: ++ #431977) ++ ++ [ Frederik Schüler ] ++ * Move all PATA options into the global config file, exept PATA_ARTOP ++ (arm/ixp4xx) and PATA_MPC52xx (powerpc). ++ * Move new global options into the global config file ++ * Clean up new amd64 options ++ ++ [ dann frazier ] ++ * [ia64] Re-enable various unintentionally disabled config options ++ * Enable hugetlbfs on i386, amd64, sparc64 and powerpc64. Closes: #450939 ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.23.2: ++ - BLOCK: Fix bad sharing of tag busy list on queues with shared tag maps ++ - fix tmpfs BUG and AOP_WRITEPAGE_ACTIVATE ++ - Fix compat futex hangs. (closes: #433187) ++ - sched: keep utime/stime monotonic ++ - fix the softlockup watchdog to actually work ++ - splice: fix double kunmap() in vmsplice copy path ++ - writeback: don't propagate AOP_WRITEPAGE_ACTIVATE ++ - SLUB: Fix memory leak by not reusing cpu_slab ++ - HOWTO: update ja_JP/HOWTO with latest changes ++ - fix param_sysfs_builtin name length check ++ - param_sysfs_builtin memchr argument fix ++ - Remove broken ptrace() special-case code from file mapping ++ - locks: fix possible infinite loop in posix deadlock detection ++ - lockdep: fix mismatched lockdep_depth/curr_chain_hash ++ * Add stable release 2.6.23.3: ++ - revert "x86_64: allocate sparsemem memmap above 4G" ++ - x86: fix TSC clock source calibration error ++ - x86 setup: sizeof() is unsigned, unbreak comparisons ++ - x86 setup: handle boot loaders which set up the stack incorrectly ++ - x86: fix global_flush_tlb() bug ++ - xfs: eagerly remove vmap mappings to avoid upsetting Xen ++ - xen: fix incorrect vcpu_register_vcpu_info hypercall argument ++ - xen: deal with stale cr3 values when unpinning pagetables ++ - xen: add batch completion callbacks ++ - UML - kill subprocesses on exit ++ - UML - stop using libc asm/user.h ++ - UML - Fix kernel vs libc symbols clash ++ - UML - Stop using libc asm/page.h ++ - POWERPC: Make sure to of_node_get() the result of pci_device_to_OF_node() ++ - POWERPC: Fix handling of stfiwx math emulation ++ - MIPS: R1: Fix hazard barriers to make kernels work on R2 also. ++ - MIPS: MT: Fix bug in multithreaded kernels. ++ - Fix sparc64 MAP_FIXED handling of framebuffer mmaps ++ - Fix sparc64 niagara optimized RAID xor asm ++ * Add stable release 2.6.23.4: ++ - mac80211: make ieee802_11_parse_elems return void ++ - mac80211: only honor IW_SCAN_THIS_ESSID in STA, IBSS, and AP modes ++ - mac80211: honor IW_SCAN_THIS_ESSID in siwscan ioctl ++ - mac80211: store SSID in sta_bss_list ++ - mac80211: store channel info in sta_bss_list ++ - mac80211: reorder association debug output ++ - ieee80211: fix TKIP QoS bug ++ - NETFILTER: nf_conntrack_tcp: fix connection reopening ++ - Fix netlink timeouts. ++ - Fix crypto_alloc_comp() error checking. ++ - Fix SET_VLAN_INGRESS_PRIORITY_CMD error return. ++ - Fix VLAN address syncing. ++ - Fix endianness bug in U32 classifier. ++ - Fix TEQL oops. ++ - Fix error returns in sys_socketpair() ++ - softmac: fix wext MLME request reason code endianness ++ - Fix kernel_accept() return handling. ++ - TCP: Fix size calculation in sk_stream_alloc_pskb ++ - Fix SKB_WITH_OVERHEAD calculations. ++ - Fix 9P protocol build ++ - Fix advertised packet scheduler timer resolution ++ - Add get_unaligned to ieee80211_get_radiotap_len ++ - mac80211: Improve sanity checks on injected packets ++ - mac80211: filter locally-originated multicast frames ++ * Add stable release 2.6.23.5: ++ - zd1211rw, fix oops when ejecting install media ++ - rtl8187: Fix more frag bit checking, rts duration calc ++ - ipw2100: send WEXT scan events ++ - zd1201: avoid null ptr access of skb->dev ++ - sky2: fix power settings on Yukon XL ++ - sky2: ethtool register reserved area blackout ++ - sky2: status ring race fix ++ - skge: XM PHY handling fixes ++ - Fix L2TP oopses. ++ - TG3: Fix performance regression on 5705. ++ - forcedeth: add MCP77 device IDs ++ - forcedeth msi bugfix ++ - ehea: 64K page kernel support fix ++ - libertas: fix endianness breakage ++ - libertas: more endianness breakage ++ * Add stable release 2.6.23.6: ++ - ACPI: suspend: Wrong order of GPE restore. ++ - ACPI: sleep: Fix GPE suspend cleanup ++ - libata: backport ATA_FLAG_NO_SRST and ATA_FLAG_ASSUME_ATA, part 2 ++ - libata: backport ATA_FLAG_NO_SRST and ATA_FLAG_ASSUME_ATA ++ - libata: add HTS542525K9SA00 to NCQ blacklist ++ - radeon: set the address to access the GART table on the CPU side correctly ++ - Char: moxa, fix and optimise empty timer ++ - Char: rocket, fix dynamic_dev tty ++ - hptiop: avoid buffer overflow when returning sense data ++ - ide: Fix cs5535 driver accessing beyond array boundary ++ - ide: Fix siimage driver accessing beyond array boundary ++ - ide: Add ide_get_paired_drive() helper ++ - ide: fix serverworks.c UDMA regression ++ - i4l: fix random freezes with AVM B1 drivers ++ - i4l: Fix random hard freeze with AVM c4 card ++ - ALSA: hda-codec - Add array terminator for dmic in STAC codec ++ - USB: usbserial - fix potential deadlock between write() and IRQ ++ - USB: add URB_FREE_BUFFER to permissible flags ++ - USB: mutual exclusion for EHCI init and port resets ++ - usb-gadget-ether: prevent oops caused by error interrupt race ++ - USB: remove USB_QUIRK_NO_AUTOSUSPEND ++ - MSI: Use correct data offset for 32-bit MSI in read_msi_msg() ++ - md: raid5: fix clearing of biofill operations ++ - md: fix an unsigned compare to allow creation of bitmaps with v1.0 metadata ++ - dm: fix thaw_bdev ++ - dm delay: fix status ++ - libata: sync NCQ blacklist with upstream ++ - ALSA: hdsp - Fix zero division ++ - ALSA: emu10k1 - Fix memory corruption ++ - ALSA: Fix build error without CONFIG_HAS_DMA ++ - ALSA: fix selector unit bug affecting some USB speakerphones ++ - ALSA: hda-codec - Avoid zero NID in line_out_pins[] of STAC codecs ++ - IB/mthca: Use mmiowb() to avoid firmware commands getting jumbled up ++ - IB/uverbs: Fix checking of userspace object ownership ++ - hwmon/lm87: Disable VID when it should be ++ - hwmon/lm87: Fix a division by zero ++ - hwmon/w83627hf: Don't assume bank 0 ++ - hwmon/w83627hf: Fix setting fan min right after driver load ++ - i915: fix vbl swap allocation size. ++ - POWERPC: Fix platinumfb framebuffer ++ * Add stable release 2.6.23.7: ++ - NFS: Fix a writeback race... ++ - ocfs2: fix write() performance regression ++ - minixfs: limit minixfs printks on corrupted dir i_size (CVE-2006-6058) ++ * Add stable release 2.6.23.8: ++ - wait_task_stopped: Check p->exit_state instead of TASK_TRACED (CVE-2007-5500) ++ - TCP: Make sure write_queue_from does not begin with NULL ptr (CVE-2007-5501) ++ * Add stable release 2.6.23.9: ++ - ipw2200: batch non-user-requested scan result notifications ++ - USB: Nikon D40X unusual_devs entry ++ - USB: unusual_devs modification for Nikon D200 ++ - softlockup: use cpu_clock() instead of sched_clock() ++ - softlockup watchdog fixes and cleanups ++ - x86: fix freeze in x86_64 RTC update code in time_64.c ++ - ntp: fix typo that makes sync_cmos_clock erratic ++ - x86: return correct error code from child_rip in x86_64 entry.S ++ - x86: NX bit handling in change_page_attr() ++ - x86: mark read_crX() asm code as volatile ++ - x86: fix off-by-one in find_next_zero_string ++ - i386: avoid temporarily inconsistent pte-s ++ - libcrc32c: keep intermediate crc state in cpu order ++ - geode: Fix not inplace encryption ++ - Fix divide-by-zero in the 2.6.23 scheduler code ++ - ACPI: VIDEO: Adjust current level to closest available one. ++ - libata: sata_sis: use correct S/G table size ++ - sata_sis: fix SCR read breakage ++ - reiserfs: don't drop PG_dirty when releasing sub-page-sized dirty file ++ - x86: disable preemption in delay_tsc() ++ - dmaengine: fix broken device refcounting ++ - nfsd4: recheck for secure ports in fh_verify ++ - knfsd: fix spurious EINVAL errors on first access of new filesystem ++ - raid5: fix unending write sequence ++ - oProfile: oops when profile_pc() returns ~0LU ++ - drivers/video/ps3fb: fix memset size error ++ - i2c/eeprom: Hide Sony Vaio serial numbers ++ - i2c/eeprom: Recognize VGN as a valid Sony Vaio name prefix ++ - i2c-pasemi: Fix NACK detection ++ ++ -- maximilian attems Fri, 30 Nov 2007 11:40:09 +0100 ++ ++linux-2.6 (2.6.22-6) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * [mips] Add IP22 (SGI Indy) patches from Thomas Bogendoerfer: ++ - Disable EARLY PRINTK because it breaks serial. ++ - fix wrong argument order. ++ - wrong check for second HPC. Closes: #448488 ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.22.11 - minus ipv6 abi breaker: ++ - libertas: fix endianness breakage ++ - libertas: more endianness breakage ++ - Fix ROSE module unload oops. ++ - Add get_unaligned to ieee80211_get_radiotap_len ++ - Fix ipv6 redirect processing, leads to TAHI failures. ++ - i915: fix vbl swap allocation size. ++ - Fix ESP host instance numbering. ++ - Fix TCP MD5 on big-endian. ++ - Fix zero length socket write() semantics. ++ - Fix sys_ipc() SEMCTL on sparc64. ++ - Fix TCP initial sequence number selection. ++ - lockdep: fix mismatched lockdep_depth/curr_chain_hash ++ - V4L: ivtv: fix udma yuv bug ++ - Fix TCP's ->fastpath_cnt_hit handling. ++ - hwmon/lm87: Fix a division by zero ++ - hwmon/lm87: Disable VID when it should be ++ - hwmon/w83627hf: Fix setting fan min right after driver load ++ - hwmon/w83627hf: Don't assume bank 0 ++ - netdrvr: natsemi: Fix device removal bug ++ - Fix ieee80211 handling of bogus hdrlength field ++ - mac80211: filter locally-originated multicast frames ++ - POWERPC: Fix handling of stfiwx math emulation ++ - dm9601: Fix receive MTU ++ - firewire: fix unloading of fw-ohci while devices are attached ++ - Fix cls_u32 error return handling. ++ - ACPI: disable lower idle C-states across suspend/resume ++ * Add stable release 2.6.22.12-rc1: ++ - genirq: cleanup mismerge artifact ++ - genirq: suppress resend of level interrupts ++ - genirq: mark io_apic level interrupts to avoid resend ++ - IB/uverbs: Fix checking of userspace object ownership ++ - minixfs: limit minixfs printks on corrupted dir i_size (CVE-2006-6058) ++ - param_sysfs_builtin memchr argument fix ++ - x86: fix global_flush_tlb() bug ++ - dm snapshot: fix invalidation deadlock ++ - Revert "x86_64: allocate sparsemem memmap above 4G" ++ ++ [ Bastian Blank ] ++ * Update vserver patch to 2.2.0.5. ++ - Ignore symbols from never to be merged patch. ++ ++ -- maximilian attems Sun, 4 Nov 2007 17:35:51 +0100 ++ ++linux-2.6 (2.6.22-5) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.22.6: ++ - USB: allow retry on descriptor fetch errors ++ - PCI: lets kill the 'PCI hidden behind bridge' message ++ - Netfilter: Missing Kbuild entry for netfilter ++ - Fix soft-fp underflow handling. ++ - SPARC64: Fix sparc64 task stack traces. ++ - TCP: Do not autobind ports for TCP sockets ++ - DCCP: Fix DCCP GFP_KERNEL allocation in atomic context ++ - NET: Share correct feature code between bridging and bonding ++ - SNAP: Fix SNAP protocol header accesses. ++ - NET: Fix missing rcu unlock in __sock_create() ++ - IPv6: Invalid semicolon after if statement ++ - TCP: Fix TCP rate-halving on bidirectional flows. ++ - TCP: Fix TCP handling of SACK in bidirectional flows. ++ - uml: fix previous request size limit fix ++ - usb: add PRODUCT, TYPE to usb-interface events ++ - PPP: Fix PPP buffer sizing. ++ - ocfs2: Fix bad source start calculation during kernel writes ++ - signalfd: fix interaction with posix-timers ++ - signalfd: make it group-wide, fix posix-timers scheduling ++ - USB: fix DoS in pwc USB video driver ++ - sky2: don't clear phy power bits ++ - PCI: disable MSI on RS690 ++ - PCI: disable MSI on RD580 ++ - PCI: disable MSI on RX790 ++ - IPV6: Fix kernel panic while send SCTP data with IP fragments ++ - i386: fix lazy mode vmalloc synchronization for paravirt ++ * Set abi to 3. ++ * Add stable release 2.6.22.7: (CVE-2007-4573) ++ - x86_64: Zero extend all registers after ptrace in 32bit entry path. ++ * Add stable release 2.6.22.8: (CVE-2007-4571) ++ - Convert snd-page-alloc proc file to use seq_file ++ * Add stable release 2.6.22.9: ++ - 3w-9xxx: Fix dma mask setting ++ - Fix pktgen src_mac handling. ++ - nfs: fix oops re sysctls and V4 support ++ - DVB: get_dvb_firmware: update script for new location of tda10046 firmware ++ - afs: mntput called before dput ++ - disable sys_timerfd() ++ - Fix "Fix DAC960 driver on machines which don't support 64-bit DMA" ++ - futex_compat: fix list traversal bugs ++ - MTD: Initialise s_flags in get_sb_mtd_aux() ++ - Fix sparc64 v100 platform booting. ++ - Fix IPV6 DAD handling ++ - ext34: ensure do_split leaves enough free space in both blocks ++ - dir_index: error out instead of BUG on corrupt dx dirs ++ - Fix oops in vlan and bridging code ++ - V4L: ivtv: fix VIDIOC_S_FBUF: new OSD values were never set ++ - crypto: blkcipher_get_spot() handling of buffer at end of page ++ - Fix datagram recvmsg NULL iov handling regression. ++ - Handle snd_una in tcp_cwnd_down() ++ - Fix TCP DSACK cwnd handling ++ - JFFS2: fix write deadlock regression ++ - hwmon: End of I/O region off-by-one ++ - Fix debug regression in video/pwc ++ - splice: fix direct splice error handling ++ - Fix race with shared tag queue maps ++ - Fix ipv6 source address handling. ++ - POWERPC: Flush registers to proper task context ++ - bcm43xx: Fix cancellation of work queue crashes ++ - Fix DAC960 driver on machines which don't support 64-bit DMA ++ - DVB: get_dvb_firmware: update script for new location of sp8870 firmware ++ - USB: fix linked list insertion bugfix for usb core ++ - Correctly close old nfsd/lockd sockets. ++ - Fix IPSEC AH4 options handling ++ - setpgid(child) fails if the child was forked by sub-thread ++ - sigqueue_free: fix the race with collect_signal() ++ - Fix decnet device address listing. ++ - Fix inet_diag OOPS. ++ - Leases can be hidden by flocks ++ - kconfig: oldconfig shall not set symbols if it does not need to ++ - MTD: Makefile fix for mtdsuper ++ - firewire: fw-ohci: ignore failure of pci_set_power_state ++ (fix suspend regression) ++ - ieee1394: ohci1394: fix initialization if built non-modular ++ - Fix device address listing for ipv4. ++ - Fix tc_ematch kbuild ++ - V4L: cx88: Avoid a NULL pointer dereference during mpeg_open() ++ - DVB: b2c2-flexcop: fix Airstar HD5000 tuning regression ++ - fix realtek phy id in forcedeth ++ - rpc: fix garbage in printk in svc_tcp_accept() ++ - Fix IPV6 append OOPS. ++ - Fix ipv6 double-sock-release with MSG_CONFIRM ++ - ACPI: Validate XSDT, use RSDT if XSDT fails ++ * Update vserver patch to 2.2.0.4. ++ * Add stable release 2.6.22.10: ++ - i386: Use global flag to disable broken local apic timer on AMD CPUs. ++ - Fix timer_stats printout of events/sec ++ - libata: update drive blacklists ++ - i2c-algo-bit: Read block data bugfix ++ - scsi_transport_spi: fix domain validation failure from incorrect width ++ setting ++ - Fix SMP poweroff hangs ++ - Fix ppp_mppe kernel stack usage. ++ - sky2: reduce impact of watchdog timer ++ - sky2: fix VLAN receive processing ++ - sky2: fix transmit state on resume ++ - SELinux: clear parent death signal on SID transitions ++ - NLM: Fix a circular lock dependency in lockd ++ - NLM: Fix a memory leak in nlmsvc_testlock ++ ++ [ Martin Michlmayr ] ++ * [mips] Add a fix so qemu NE2000 will work again. ++ * [mipsel/r5k-cobalt] Enable MTD. ++ * [mips] Backport "Fix CONFIG_BUILD_ELF64 kernels with symbols in ++ CKSEG0" to fix crash on boot on IP32 (SGI O2). Closes: #444104. ++ ++ [ Steve Langasek ] ++ * Set CONFIG_MATHEMU=y on alpha, which is required for proper fp math on ++ at least ev4-ev56 systems. Closes: #411813. ++ * linux-image packages need to depend on a newer version of coreutils, ++ because of the use of readlink -q -m inherited from kernel-package. ++ Closes: #413311. ++ ++ [ Bastian Blank ] ++ * Fix tainted check in bug scripts. ++ ++ [ dann frazier ] ++ * [ia64] Re-enable various unintentionally disabled config options ++ ++ -- Maximilian Attems Thu, 11 Oct 2007 13:31:38 +0000 ++ ++linux-2.6 (2.6.22-4) unstable; urgency=low ++ ++ [ dann frazier ] ++ * [hppa] Use generic compat_sys_getdents (closes: #431773) ++ ++ [ Martin Michlmayr ] ++ * [powerpc] Fix PS/2 keyboard detection on Pegasos (closes: #435378). ++ ++ [ Emanuele Rocca ] ++ * [sparc] Add patch to fix PCI config space accesses on sun4u. ++ * [sparc] Disable CONFIG_SCSI_SCAN_ASYNC. ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.22.2: ++ - usb-serial: Fix edgeport regression on non-EPiC devices ++ - Missing header include in ipt_iprange.h ++ - drivers/video/macmodes.c:mac_find_mode() mustn't be __devinit ++ - Fix ipv6 tunnel endianness bug. ++ - aacraid: fix security hole ++ - USB: cdc-acm: fix sysfs attribute registration bug ++ - USB: fix warning caused by autosuspend counter going negative ++ - Fix sparc32 memset() ++ - Fix leak on /proc/lockdep_stats ++ - Fix leaks on /proc/{*/sched, sched_debug, timer_list, timer_stats} ++ - futex: pass nr_wake2 to futex_wake_op ++ - md: handle writes to broken raid10 arrays gracefully ++ - forcedeth bug fix: cicada phy ++ - forcedeth bug fix: vitesse phy ++ - forcedeth bug fix: realtek phy ++ - ACPI: dock: fix opps after dock driver fails to initialize ++ - pcmcia: give socket time to power down ++ - drm/i915: Fix i965 secured batchbuffer usage (CVE-2007-3851) ++ - Fix console write locking in sparc drivers. ++ - Sparc64 bootup assembler bug ++ - IPV6: /proc/net/anycast6 unbalanced inet6_dev refcnt ++ - make timerfd return a u64 and fix the __put_user ++ - Fix error queue socket lookup in ipv6 ++ - Input: lifebook - fix an oops on Panasonic CF-18 ++ - readahead: MIN_RA_PAGES/MAX_RA_PAGES macros ++ - V4L: Add check for valid control ID to v4l2_ctrl_next ++ - V4L: ivtv: fix broken VBI output support ++ - V4L: ivtv: fix DMA timeout when capturing VBI + another stream ++ - V4L: ivtv: Add locking to ensure stream setup is atomic ++ - V4L: wm8775/wm8739: Fix memory leak when unloading module ++ - do not limit locked memory when RLIMIT_MEMLOCK is RLIM_INFINITY ++ - Include serial_reg.h with userspace headers (closes: #433755) ++ - TCP FRTO retransmit bug fix ++ - Fix rfkill IRQ flags. ++ - nfsd: fix possible read-ahead cache and export table corruption ++ - nfsd: fix possible oops on re-insertion of rpcsec_gss modules ++ - jbd commit: fix transaction dropping ++ - jbd2 commit: fix transaction dropping ++ - softmac: Fix ESSID problem ++ - uml: limit request size on COWed devices ++ - UML: exports for hostfs ++ - splice: fix double page unlock ++ - cfq-iosched: fix async queue behaviour ++ - cr_backlight_probe() allocates too little storage for struct cr_panel ++ - sx: switch subven and subid values ++ - hugetlb: fix race in alloc_fresh_huge_page() ++ - KVM: SVM: Reliably detect if SVM was disabled by BIOS ++ - dm io: fix another panic on large request ++ - md: raid10: fix use-after-free of bio ++ - fs: 9p/conv.c error path fix ++ - Fix sparc32 udelay() rounding errors. ++ - sony-laptop: fix bug in event handling ++ - eCryptfs: ecryptfs_setattr() bugfix ++ - Hangup TTY before releasing rfcomm_dev ++ - dm io: fix panic on large request ++ - dm raid1: fix status ++ - dm snapshot: permit invalid activation ++ - "ext4_ext_put_in_cache" uses __u32 to receive physical block number ++ - destroy_workqueue() can livelock ++ - USB: fix for ftdi_sio quirk handling ++ - Fix TC deadlock. ++ - Fix IPCOMP crashes. ++ - gen estimator timer unload race ++ - Netfilter: Fix logging regression ++ - Fix user struct leakage with locked IPC shem segment ++ - Fix reported task file values in sense data ++ - gen estimator deadlock fix ++ - Netpoll leak ++ - dm: disable barriers ++ - firewire: fw-sbp2: set correct maximum payload (fixes CardBus adapters) ++ - fw-ohci: fix "scheduling while atomic" ++ - firewire: fix memory leak of fw_request instances ++ - ieee1394: revert "sbp2: enforce 32bit DMA mapping" ++ - libata: add FUJITSU MHV2080BH to NCQ blacklist ++ - i386: HPET, check if the counter works ++ - CPU online file permission ++ - acpi-cpufreq: Proper ReadModifyWrite of PERF_CTL MSR ++ - Keep rfcomm_dev on the list until it is freed ++ - SCTP scope_id handling fix ++ - Fix ipv6 link down handling. ++ - Fix TCP IPV6 MD5 bug. ++ - sysfs: release mutex when kmalloc() failed in sysfs_open_file(). ++ - nf_conntrack: don't track locally generated special ICMP error ++ * Bump abi due to firewire, ivtv and xrfm changes. ++ * Add stable release 2.6.22.3: ++ - fix oops in __audit_signal_info() ++ - direct-io: fix error-path crashes ++ - powerpc: Fix size check for hugetlbfs ++ - stifb: detect cards in double buffer mode more reliably ++ - pata_atiixp: add SB700 PCI ID ++ - PPC: Revert "[POWERPC] Add 'mdio' to bus scan id list for platforms ++ with QE UEC" ++ - random: fix bound check ordering (CVE-2007-3105) ++ - softmac: Fix deadlock of wx_set_essid with assoc work ++ - PPC: Revert "[POWERPC] Don't complain if size-cells == 0 in prom_parse()" ++ - ata_piix: update map 10b for ich8m ++ - CPUFREQ: ondemand: fix tickless accounting and software coordination bug ++ - CPUFREQ: ondemand: add a check to avoid negative load calculation ++ * Add stable release 2.6.22.4: ++ - Reset current->pdeath_signal on SUID binary execution (CVE-2007-3848) ++ * Add stable release 2.6.22.5: ++ - x86_64: Check for .cfi_rel_offset in CFI probe ++ - x86_64: Change PMDS invocation to single macro ++ - i386: Handle P6s without performance counters in nmi watchdog ++ - revert "x86, serial: convert legacy COM ports to platform devices" ++ - ACPICA: Fixed possible corruption of global GPE list ++ - ACPICA: Clear reserved fields for incoming ACPI 1.0 FADTs ++ - i386: Fix double fault handler ++ - JFFS2 locking regression fix. ++ - r8169: avoid needless NAPI poll scheduling ++ - Linux 2.6.22.5 ++ - AVR32: Fix atomic_add_unless() and atomic_sub_unless() ++ - i386: allow debuggers to access the vsyscall page with compat vDSO ++ - hwmon: (smsc47m1) restore missing name attribute ++ - hwmon: fix w83781d temp sensor type setting ++ - Hibernation: do not try to mark invalid PFNs as nosave ++ - sky2: restore workarounds for lost interrupts ++ - sky2: carrier management ++ - sky2: check for more work before leaving NAPI ++ - sky2: check drop truncated packets ++ - forcedeth: fix random hang in forcedeth driver when using netconsole ++ - libata: add ATI SB700 device IDs to AHCI driver ++ ++ [ dann frazier ] ++ * [ia64] Restore config cleanup now that its safe to break the ABI ++ ++ [ Bastian Blank ] ++ * Update vserver patch to 2.2.0.3. ++ ++ -- Bastian Blank Thu, 30 Aug 2007 20:19:44 +0200 ++ ++linux-2.6 (2.6.22-3) unstable; urgency=low ++ ++ [ dann frazier ] ++ * [ia64] Config cleanup in 2.6.22-2 broke the ABI; revert most of it ++ for now (everything but the efivars and sym53c8xx modules) ++ ++ [ Martin Michlmayr ] ++ * [mipsel/r5k-cobalt] Fix a typo in the config file. ++ * [mipsel/4kc-malta] Update the config file, thanks Aurelien Jarno. ++ * [mipsel] Add patch from Yoichi Yuasa to fix IDE on Cobalt. ++ ++ -- Bastian Blank Sun, 29 Jul 2007 13:47:38 +0200 ++ ++linux-2.6 (2.6.22-2) unstable; urgency=low ++ ++ [ Steve Langasek ] ++ * [alpha] request_irq-retval.patch: capture the return value of all ++ request_irq() calls in sys_titan.c to suppress the warning (and ++ build failure with -Werror); failures still aren't being handled, but ++ there's nothing that needs to be done -- or nothing that can be done ++ -- if these requests fail anyway. ++ ++ [ Christian T. Steigies ] ++ * Add module.lds to kernel headers (closes: #396220) ++ * Enable INPUT_UINPUT on mac ++ * Add 2.6.22 patches from linux-m68k CVS ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.22.1: ++ - nf_conntrack_h323: add checking of out-of-range on choices' index values ++ (CVE-2007-3642) ++ ++ [ dann frazier ] ++ * [ia64] Re-enable various config options which were unintentionally ++ disabled somewhere between 2.6.21 and 2.6.22 ++ * [ia64] Re-enable vserver flavour - this was somehow lost when 2.6.22 ++ was merged from trunk to the sid branch ++ ++ [ Bastian Blank ] ++ * Update vserver patch to 2.2.0.3-rc1. ++ ++ -- Bastian Blank Mon, 23 Jul 2007 09:38:01 +0200 ++ ++linux-2.6 (2.6.22-1) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Drop asfs options. ++ * Drop linux-libc-headers references. ++ * Update vserver patch to 2.2.0-rc5. ++ ++ [ maximilian attems ] ++ * Fullfils policy 3.7.2.2. ++ * Add Sempron to the k7 image description (closes: #384737) ++ Thanks Robert Millan . ++ * [powerpc] Enable CONFIG_ADB_PMU_LED. ++ * [hppa] Disable a bunch of topconfig enabled fb devices. Thanks Frank ++ Lichtenheld for build fix. ++ ++ [ Christian T. Steigies ] ++ * Add module.lds to kernel headers ++ * Enable INPUT_UINPUT on mac ++ * Add 2.6.22 patches from linux-m68k CVS ++ ++ [ dann frazier ] ++ * Enable vserver flavour for ia64 (closes: #423232) ++ ++ -- Bastian Blank Sun, 15 Jul 2007 15:03:40 +0200 ++ ++linux-2.6 (2.6.22~rc5-1~experimental.1) experimental; urgency=low ++ ++ [ Bastian Blank ] ++ * [powerpc]: Disable prep. ++ * [powerpc]: Disable apm emulation. ++ * Drop inactive members from Uploaders. ++ ++ [ maximilian attems ] ++ * Cleanup configs of old unused variables. ++ * Enable TCP_CONG_YEAH, TCP_CONG_ILLINOIS, NF_CONNTRACK_SANE, DM_DELAY, ++ GIGASET_M101, SATA_INIC162X, VIDEO_IVTV, USB_ZR364XX, INFINIBAND_CXGB3, ++ MLX4_INFINIBAND, SPI_AT25, MFD_SM501, DVB_USB_M920X, DVB_USB_GL861, ++ DVB_USB_AU6610, DVB_USB_OPERA1, SENSORS_AD7418, SENSORS_ADM1029, ++ SENSORS_F75375S, SENSORS_CORETEMP, SENSORS_MAX6650, SENSORS_APPLESMC, ++ I2C_SIMTEC, I2C_TINY_USB, SC92031, LIBERTAS_USB, RFKILL, RFKILL_INPUT, ++ MTD_UBI, SND_USB_CAIAQ, SND_USB_CAIAQ_INPUT, USB_BERRY_CHARGE, ++ RTC_DRV_MAX6900, SUNRPC_BIND34, SND_PORTMAN2X4, FB_VT8623, FUSION_LAN, ++ DISPLAY_SUPPORT, FB_ARK, FB_SM501 ++ and disable SCSI_ESP_CORE, SPI_SPIDEV, CRYPT_CRYPTD, SYSV68_PARTITION, ++ MOUSE_PS2_TOUCHKIT, INPUT_POLLDEV in topconfig. ++ * [amd64, i386]: Take care of the renaming acpi-ibm to thinkpad-acpi. ++ Enable KINGSUN_DONGLE, AF_RXRPC, RXKAD, MTD_NAND_PLATFORM, BLINK, PHANTOM, ++ BACKLIGHT_PROGEAR, FB_HECUBA, FB_LE80578, FB_CARILLO_RANCH. ++ Disable OSS_OBSOLETE. ++ * Enable WLAN_PRE80211 and WLAN_80211 on all archs with NET_RADIO enabled. ++ * Fix RTC_INTF_{DEV,SYSFS,PROC}=y where enabled modular. ++ * Enable new wirless stack mac80211 and improved wireless conf api. ++ * Enable new USB Touchscreen Driver on all configs with touchscreens. ++ * Enable the newly added crypto algorythm: fcrypt, pcbc and camellia. ++ * Unify CONFIG_TR to toplevel config, also enable new drivers 3C359 ++ and SMCTR. ++ * Enable the moved USB tablets config options where wacom is enabled. ++ * [i386] Enable driver for Crystalfontz 128x64 2-color LCD. ++ * [amd64] Enable KS0108 LCD controller. ++ * Enable the new firewire stack labeled to be more simple and robust. ++ * [i386] Enable VMI paravirtualized interface. ++ * [powerpc] Enable fb for IBM GXT4500P adaptor. ++ * [amd64] Enable timerstats too. ++ ++ [ Martin Michlmayr ] ++ * mipsel/r5k-cobalt: Use the new RTC system. ++ ++ [ dann frazier ] ++ * Add Xen licensing info to the copyright file. (closes: #368912) ++ ++ [ Gordon Farquharson ] ++ * arm: Mark CHELSIO_T3, NETXEN_NIC, BCM43XX, VIDEO_BT848, ++ DVB_B2C2_FLEXCOP, and DVB_BUDGET as broken on ARM. ++ * arm/ixp4xx: Add support for the new generic I2C GPIO driver on the ++ NSLU2 and the NAS100D. Thanks to Michael-Luke Jones and Rod Whitby. ++ * arm/ixp4xx: Update Artop PATA support patch for the NAS 100d. ++ ++ [ Christian T. Steigies ] ++ * m68k: Disable already included patches (611, 618, 630) ++ ++ -- Bastian Blank Tue, 19 Jun 2007 17:49:52 +0200 ++ ++linux-2.6 (2.6.21-6) unstable; urgency=low ++ ++ * Add stable release 2.6.21.6: ++ - nf_conntrack_h323: add checking of out-of-range on choices' index values ++ (CVE-2007-3642) ++ * Update vserver patch to 2.2.0. ++ ++ -- Bastian Blank Tue, 10 Jul 2007 18:36:17 +0200 ++ ++linux-2.6 (2.6.21-5) unstable; urgency=low ++ ++ [ Christian T. Steigies ] ++ * [m68k] Add atari isa and scsi fixes ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.21.4: ++ - cpuset: prevent information leak in cpuset_tasks_read (CVE-2007-2875) ++ - random: fix error in entropy extraction (CVE-2007-2453 1 of 2) ++ - random: fix seeding with zero entropy (CVE-2007-2453 2 of 2) ++ - NETFILTER: {ip, nf}_conntrack_sctp: fix remotely triggerable NULL ptr ++ dereference (CVE-2007-2876) ++ * Add stable release 2.6.21.5: ++ - acpi: fix potential call to a freed memory section. ++ - USB: set the correct Interrupt interval in usb_bulk_msg ++ - i386: Fix K8/core2 oprofile on multiple CPUs ++ - ntfs_init_locked_inode(): fix array indexing ++ - ALSA: wm8750 typo fix ++ - neofb: Fix pseudo_palette array overrun in neofb_setcolreg ++ - e1000: disable polling before registering netdevice ++ - timer statistics: fix race ++ - x86: fix oprofile double free ++ - ALSA: usb-audio: explicitly match Logitech QuickCam ++ - zd1211rw: Add AL2230S RF support ++ - IPV4: Correct rp_filter help text. ++ - Fix AF_UNIX OOPS ++ - ICMP: Fix icmp_errors_use_inbound_ifaddr sysctl ++ - NET: Fix BMSR_100{HALF,FULL}2 defines in linux/mii.h ++ - SPARC64: Fix _PAGE_EXEC_4U check in sun4u I-TLB miss handler. ++ - SPARC64: Don't be picky about virtual-dma values on sun4v. ++ - SPARC64: Fix two bugs wrt. kernel 4MB TSB. ++ - cciss: fix pci_driver.shutdown while device is still active ++ - fix compat console unimap regression ++ - timer stats: speedups ++ - SPARC: Linux always started with 9600 8N1 ++ - pci_ids: update patch for Intel ICH9M ++ - PCI: quirk disable MSI on via vt3351 ++ - UML - Improve host PTRACE_SYSEMU check ++ - NET: parse ip:port strings correctly in in4_pton ++ - Char: cyclades, fix deadlock ++ - IPSEC: Fix panic when using inter address familiy IPsec on loopback. ++ - TCP: Use default 32768-61000 outgoing port range in all cases. ++ - TG3: Fix link problem on Dell's onboard 5906. ++ - fuse: fix mknod of regular file ++ - md: Avoid overflow in raid0 calculation with large components. ++ - md: Don't write more than is required of the last page of a bitmap ++ - make freezeable workqueues singlethread ++ - tty: fix leakage of -ERESTARTSYS to userland ++ - V4L/DVB (5593): Budget-ci: Fix tuning for TDM 1316 (160..200 MHz) ++ - Input: i8042 - fix AUX port detection with some chips ++ - SCSI: aacraid: Correct sa platform support. ++ (Was: [Bug 8469] Bad EIP value on pentium3 SMP kernel-2.6.21.1) ++ - BLUETOOTH: Fix locking in hci_sock_dev_event(). ++ - hpt366: don't check enablebits for HPT36x ++ - ieee1394: eth1394: bring back a parent device ++ - NET: Fix race condition about network device name allocation. ++ - ALSA: hda-intel - Probe additional slots only if necessary ++ - ALSA: hda-intel - Fix detection of audio codec on Toshiba A100 ++ - ahci: disable 64bit dma on sb600 ++ - i386: HPET, check if the counter works ++ - Ignore bogus ACPI info for offline CPUs ++ - NOHZ: Rate limit the local softirq pending warning output ++ - Prevent going idle with softirq pending ++ - Work around Dell E520 BIOS reboot bug ++ - NET: "wrong timeout value" in sk_wait_data() v2 ++ - IPV6 ROUTE: No longer handle ::/0 specially. ++ - x86_64: allocate sparsemem memmap above 4G ++ * Bump ABI to 2. ++ ++ [ Bastian Blank ] ++ * Back out ABI fixing changes. ++ * Update vserver patch to 2.2.0-rc3. ++ ++ -- Bastian Blank Fri, 22 Jun 2007 12:39:47 +0200 ++ ++linux-2.6 (2.6.21-4) unstable; urgency=low ++ ++ * [powerpc] Fix mkvmlinuz support. ++ * [s390] Add exception handler for diagnose 224. ++ ++ -- Bastian Blank Sat, 26 May 2007 14:08:44 +0200 ++ ++linux-2.6 (2.6.21-3) unstable; urgency=low ++ ++ [ Gordon Farquharson ] ++ * arm/ixp4xx: Add patch to set NSLU2 timer frequency. ++ ++ [ maximilian attems ] ++ * sparc64: enable USB_SERIAL. (closes: #412740) ++ * Apply stable 2.6.21.1. ++ * Add stable release 2.6.21.2: ++ - slob: fix page order calculation on not 4KB page ++ - libata-sff: Undo bug introduced with pci_iomap changes ++ - kbuild: fixdep segfault on pathological string-o-death ++ - IPMI: fix SI address space settings ++ - IPV6: Reverse sense of promisc tests in ip6_mc_input ++ - iop: fix iop_getttimeoffset ++ - iop13xx: fix i/o address translation ++ - arm: fix handling of svc mode undefined instructions ++ - CPUFREQ: powernow-k7: fix MHz rounding issue with perflib ++ - CPUFREQ: Support rev H AMD64s in powernow-k8 ++ - CPUFREQ: Correct revision mask for powernow-k8 ++ - JFS: Fix race waking up jfsIO kernel thread ++ - IPV6: Send ICMPv6 error on scope violations. ++ - SPARC64: Add missing cpus_empty() check in hypervisor xcall handling. ++ - SPARC64: Fix recursion in PROM tree building. ++ - SERIAL SUNHV: Add an ID string. ++ - SPARC64: Bump PROMINTR_MAX to 32. ++ - SPARC64: Be more resiliant with PCI I/O space regs. ++ - oom: fix constraint deadlock ++ - fix for bugzilla 8426: massive slowdown on SCSI CD/DVD drive connected to ++ mptspi driver ++ - x86_64 : Fix vgettimeofday() ++ - IPV6: Fix slab corruption running ip6sic ++ - IPSEC: Check validity of direction in xfrm_policy_byid ++ - CRYPTO: api: Read module pointer before freeing algorithm ++ - NET_SCHED: prio qdisc boundary condition ++ - reiserfs: suppress lockdep warning ++ - USB HID: hiddev - fix race between hiddev_send_event() and ++ hiddev_release() ++ - NETFILTER: {ip,nf}_nat_proto_gre: do not modify/corrupt GREv0 packets ++ through NAT ++ - fix leaky resv_huge_pages when cpuset is in use ++ - ACPI: Fix 2.6.21 boot regression on P4/HT ++ - TG3: Fix TSO bugs. ++ - TG3: Remove reset during MAC address changes. ++ - TG3: Update version and reldate. ++ - BNX2: Fix TSO problem with small MSS. ++ - BNX2: Block MII access when ifdown. ++ - BNX2: Save PCI state during suspend. ++ - BNX2: Update version and reldate. ++ - sis900: Allocate rx replacement buffer before rx operation ++ - knfsd: Avoid use of unitialised variables on error path when nfs exports. ++ - knfsd: rpc: fix server-side wrapping of krb5i replies ++ - md: Avoid a possibility that a read error can wrongly propagate through ++ - md/raid1 to a filesystem. ++ - fat: fix VFAT compat ioctls on 64-bit systems ++ - NETFILTER: {ip,nf}_conntrack: fix use-after-free in helper destroy ++ callback invocation ++ - ppp: Fix ppp_deflate issues with recent zlib_inflate changes ++ - NETPOLL: Fix TX queue overflow in trapped mode. ++ - NETPOLL: Remove CONFIG_NETPOLL_RX ++ - cxacru: Fix infinite loop when trying to cancel polling task ++ - TCP: zero out rx_opt in tcp_disconnect() ++ - ipv6: track device renames in snmp6 ++ - skge: default WOL should be magic only (rev2) ++ - skge: allow WOL except for known broken chips ++ - sky2: allow 88E8056 ++ - sky2: 88e8071 support not ready ++ - skge: crash on shutdown/suspend ++ - sky2: fix oops on shutdown ++ - udf: decrement correct link count in udf_rmdir ++ - ALSA: hda-codec - Fix resume of STAC92xx codecs ++ - sata_via: add missing PM hooks ++ - driver-core: don't free devt_attr till the device is released ++ - pci-quirks: disable MSI on RS400-200 and RS480 ++ - highres/dyntick: prevent xtime lock contention ++ - clocksource: fix resume logic ++ - smc911x: fix compilation breakage wjen debug is on ++ - SCTP: Fix sctp_getsockopt_local_addrs_old() to use local storage. ++ - SCTP: Correctly copy addresses in sctp_copy_laddrs ++ - SCTP: Prevent OOPS if hmac modules didn't load ++ - IPV6: Do no rely on skb->dst before it is assigned. ++ - IPV6 ROUTE: Assign rt6i_idev for ip6_{prohibit,blk_hole}_entry. ++ ++ [ Christian T. Steigies ] ++ * m68k: enable ATARI_SCSI and ATARI_ROM_ISA ++ ++ [ Bastian Blank ] ++ * Fix linux/version.h in linux-libc-dev. ++ * Make it possible to specifiy special CFLAGS. ++ * [hppa] Reenable. ++ * [hppa] Workaround hppa64 failure. ++ * [hppa] Fix debugging in lws syscalls. ++ * Fix abi change. ++ * Add stable release 2.6.21.3: ++ - [PATCH] GEODE-AES: Allow in-place operations [CVE-2007-2451] ++ ++ -- Bastian Blank Fri, 25 May 2007 10:57:48 +0200 ++ ++linux-2.6 (2.6.21-2) unstable; urgency=low ++ ++ [ Christian T. Steigies ] ++ * m68k: fix atari scc patch ++ * m68k: install compressed vmlinuz images so the post-inst script can find it ++ ++ [ Steve Langasek ] ++ * [alpha] isa-mapping-support.patch: add isa_page_to_bus and ++ isa_bus_to_virt defines to complement the existing isa_virt_to_bus ++ define; untested, but these should all be straightforward on alpha and ++ defining them is certainly a better option for getting user feedback ++ than disabling the affected drivers. ++ ++ [ Bastian Blank ] ++ * [powerpc] Readd mkvmlinuz support. (closes: #419033) ++ * [sparc]: Disable sparc32 image. ++ * [hppa]: Temporary disable all images. ++ ++ -- Bastian Blank Fri, 18 May 2007 19:52:36 +0200 ++ ++linux-2.6 (2.6.21-1) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * New upstream release see http://kernelnewbies.org/Linux_2_6_21 ++ (closes: #423874) ++ * Disable CONFIG_IP_ROUTE_MULTIPATH_CACHED in topconfig. ++ * Enable CONFIG_IP6_NF_MATCH_MH, CONFIG_CHELSIO_T3, CONFIG_USB_NET_DM9601, ++ CONFIG_NETFILTER_XT_TARGET_TCPMSS, CONFIG_RTC_DRV_CMOS, ++ CONFIG_ASUS_LAPTOP, CONFIG_SONY_LAPTOP, CONFIG_DVB_TUNER_QT1010, ++ CONFIG_USB_IOWARRIOR, CONFIG_ATL1 in topconfig. ++ * [i386] Enable CONFIG_ACPI_BAY, CONFIG_X86_LONGHAUL, CONFIG_BLK_DEV_DELKIN, ++ CONFIG_BLK_DEV_IT8213, CONFIG_BLK_DEV_TC86C001, CONFIG_INPUT_ATLAS_BTNS, ++ CONFIG_SENSORS_ADM1029, CONFIG_FB_SVGALIB, CONFIG_FB_S3, ++ CONFIG_USB_KC2190, CONFIG_KS0108. ++ * Add stable release 2.6.21.1: ++ - IPV4: Fix OOPS'er added to netlink fib. ++ - IPV6: Fix for RT0 header ipv6 change. ++ * [i386] Enable CONFIG_NO_HZ, CONFIG_HIGH_RES_TIMERS for dynticks and true ++ high-resolution timers. ++ * [i386] Enable CONFIG_TIMER_STATS to collect stats about kernel/userspace ++ timer aka power usage (see powertop). (closes: #423694) ++ * [i386] Disable obsolete CONFIG_IRQBALANCE due to bad timer behaviour. ++ ++ [ Martin Michlmayr ] ++ * Add armel (arm with EABI) support. Thanks, Lennert Buytenhek and ++ Joey Hess. (closes: #410853) ++ * Mark CHELSIO_T3 as broken on ARM. ++ * Take arch/arm/tools/mach-types from current git to fix build failure ++ because MACH_TYPE_EP80219 is not defined. ++ * mips/sb1: Don't build CONFIG_ATA into the kernel. ++ * mips/sb1: Unset CONFIG_USB_{KBD,MOUSE} since the generic HID is used. ++ * arm/iop32x: Don't build CONFIG_ATA into the kernel. ++ * arm/ixp4xx: Enable more SATA drivers. ++ * arm/ixp4xx: Enable PATA_ARTOP which is needed by the nas100d. ++ * arm/ixp4xx: Set CONFIG_USB_EHCI_TT_NEWSCHED. ++ * mips/4kc-malta: Add an image for the MIPS Malta board. Thanks, ++ Aurelien Jarno. (closes: #421377) ++ ++ [ Emanuele Rocca ] ++ * sparc: Enable CONFIG_SCSI_QLOGIC_1280. (closes: #423177) ++ ++ [ Christian T. Steigies ] ++ * Add m68k patches for 2.6.21 ++ * Add type: plain to [image] in arch/m68k/defines to fix missing ++ Modules.symvers problem ++ ++ [ Steve Langasek ] ++ * Revert change to disable image building on alpha. ++ ++ [ Bastian Blank ] ++ * Update vserver patch to 2.2.0-rc1. ++ ++ -- Bastian Blank Wed, 16 May 2007 13:46:38 +0200 ++ ++linux-2.6 (2.6.20-3) unstable; urgency=low ++ ++ [ Gordon Farquharson ] ++ * arm: Mark CONFIG_MTD_NAND_CAFE and CONFIG_NETXEN_NIC as broken to ++ fix FTBFS. ++ ++ [ Bastian Blank ] ++ * Disable new pata drivers. (closes: #419458) ++ * Disable pata in ata_piix. ++ ++ -- Bastian Blank Tue, 24 Apr 2007 09:54:44 +0200 ++ ++linux-2.6 (2.6.20-2) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Rename linux-libc-headers into linux-libc-dev. ++ * [mips] Drop sb1250 uart support. ++ * [alpha] Temporary disable alpha images. ++ * Add stable release 2.6.20.7: ++ - Linux 2.6.20.7 ++ - Update libata drive blacklist to the latest from 2.6.21 ++ - fix page leak during core dump ++ - revert "retries in ext4_prepare_write() violate ordering requirements" ++ - revert "retries in ext3_prepare_write() violate ordering requirements" ++ - libata: Clear tf before doing request sense (take 3) ++ - fix lba48 bug in libata fill_result_tf() ++ - ahci.c: walkaround for SB600 SATA internal error issue ++ - libata bugfix: preserve LBA bit for HDIO_DRIVE_TASK ++ - softmac: avoid assert in ieee80211softmac_wx_get_rate ++ - knfsd: allow nfsd READDIR to return 64bit cookies ++ - Fix TCP slow_start_after_idle sysctl ++ - Fix tcindex classifier ABI borkage... ++ - Fix IPSEC replay window handling ++ - Fix TCP receiver side SWS handling. ++ - Fix scsi sense handling ++ - Fix length validation in rawv6_sendmsg() ++ - NETFILTER: ipt_CLUSTERIP: fix oops in checkentry function ++ - 8139too: RTNL and flush_scheduled_work deadlock ++ - Fix calculation for size of filemap_attr array in md/bitmap. ++ - HID: Do not discard truncated input reports ++ - DVB: pluto2: fix incorrect TSCR register setting ++ - DVB: tda10086: fix DiSEqC message length ++ - sky2: phy workarounds for Yukon EC-U A1 ++ - sky2: turn on clocks when doing resume ++ - sky2: turn carrier off when down ++ - skge: turn carrier off when down ++ - sky2: reliable recovery ++ - i386: fix file_read_actor() and pipe_read() for original i386 systems ++ - kbuild: fix dependency generation ++ ++ [ dann frazier ] ++ * [hppa] Add parisc arch patch from Kyle McMartin ++ * [hppa] Enable CONFIG_TULIP_MMIO (closes: #332962) ++ * [hppa] Disable ni52 driver, it doesn't build (and wouldn't work if it did) ++ ++ -- Bastian Blank Sun, 15 Apr 2007 16:04:16 +0200 ++ ++linux-2.6 (2.6.20-1) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * mipsel: Drop DECstation support (both r3k-kn02 and r4k-kn04). ++ * arm: Drop RiscPC (rpc) support. ++ * arm: Update configs for 2.6.19-rc6. ++ * arm: source drivers/ata/Kconfig so SATA can be enabled on ARM. ++ * arm/footbridge: Unset SATA. ++ * arm/s3c2410: Drop this flavour since no such device is supported ++ in debian-installer and the ARM build resources are limited. ++ ++ [ Sven Luther ] ++ * [powerpc] Added Genesi Efika support patch ++ ++ [ Bastian Blank ] ++ * Remove legacy pty support. (closes: #338404) ++ * Enable new scsi parts. ++ * powerpc: Enable ibmvscsis. ++ * Add stable release 2.6.20.1: ++ - Linux 2.6.20.1 ++ - [PATCH] Fix a free-wrong-pointer bug in nfs/acl server (CVE-2007-0772) ++ * Add stable release 2.6.20.2: ++ - Linux 2.6.20.2 ++ - IPV6: Handle np->opt being NULL in ipv6_getsockopt_sticky() [CVE-2007-1000] ++ - x86-64: survive having no irq mapping for a vector ++ - Fix buffer overflow in Omnikey CardMan 4040 driver (CVE-2007-0005) ++ - TCP: Fix minisock tcp_create_openreq_child() typo. ++ - gfs2: fix locking mistake ++ - ATA: convert GSI to irq on ia64 ++ - pktcdvd: Correctly set cmd_len field in pkt_generic_packet ++ - video/aty/mach64_ct.c: fix bogus delay loop ++ - revert "drivers/net/tulip/dmfe: support basic carrier detection" ++ - throttle_vm_writeout(): don't loop on GFP_NOFS and GFP_NOIO allocations ++ - fix section mismatch warning in lockdep ++ - ueagle-atm.c needs sched.h ++ - kvm: Fix asm constraint for lldt instruction ++ - lockdep: forward declare struct task_struct ++ - Char: specialix, isr have 2 params ++ - buffer: memorder fix ++ - kernel/time/clocksource.c needs struct task_struct on m68k ++ - m32r: build fix for processors without ISA_DSP_LEVEL2 ++ - hugetlb: preserve hugetlb pte dirty state ++ - enable mouse button 2+3 emulation for x86 macs ++ - v9fs_vfs_mkdir(): fix a double free ++ - ufs: restore back support of openstep ++ - Fix MTRR compat ioctl ++ - kexec: Fix CONFIG_SMP=n compilation V2 (ia64) ++ - NLM: Fix double free in __nlm_async_call ++ - RPM: fix double free in portmapper code ++ - Revert "[PATCH] LOG2: Alter get_order() so that it can make use of ilog2() on a constant" ++ - Backport of psmouse suspend/shutdown cleanups ++ - USB: usbnet driver bugfix ++ - sched: fix SMT scheduler bug ++ - tty_io: fix race in master pty close/slave pty close path ++ - forcedeth: disable msix ++ - export blk_recount_segments ++ - Fix reference counting (memory leak) problem in __nfulnl_send() and callers related to packet queueing. ++ - Fix anycast procfs device leak ++ - Don't add anycast reference to device multiple times ++ - Fix TCP MD5 locking. ++ - Fix %100 cpu spinning on sparc64 ++ - Fix skb data reallocation handling in IPSEC ++ - Fix xfrm_add_sa_expire() return value ++ - Fix interrupt probing on E450 sparc64 systems ++ - HID: fix possible double-free on error path in hid parser ++ - POWERPC: Fix performance monitor exception ++ - libata: add missing CONFIG_PM in LLDs ++ - libata: add missing PM callbacks ++ - bcm43xx: Fix assertion failures in interrupt handler ++ - mmc: Power quirk for ENE controllers ++ - UML - Fix 2.6.20 hang ++ - fix umask when noACL kernel meets extN tuned for ACLs ++ - sata_sil: ignore and clear spurious IRQs while executing commands by polling ++ - swsusp: Fix possible oops in userland interface ++ - Fix posix-cpu-timer breakage caused by stale p->last_ran value ++ - V4L: cx88-blackbird: allow usage of 376836 and 262144 sized firmware images ++ - V4L: fix cx25840 firmware loading ++ - DVB: digitv: open nxt6000 i2c_gate for TDED4 tuner handling ++ - DVB: cxusb: fix firmware patch for big endian systems ++ - V4L: pvrusb2: Handle larger cx2341x firmware images ++ - V4L: pvrusb2: Fix video corruption on stream start ++ - dvbdev: fix illegal re-usage of fileoperations struct ++ - md: Fix raid10 recovery problem. ++ - bcm43xx: fix for 4309 ++ - i386: Fix broken CONFIG_COMPAT_VDSO on i386 ++ - x86: Don't require the vDSO for handling a.out signals ++ - x86_64: Fix wrong gcc check in bitops.h ++ - sky2: transmit timeout deadlock ++ - sky2: dont flush good pause frames ++ - Fix oops in xfrm_audit_log() ++ - Prevent pseudo garbage in SYN's advertized window ++ - Fix IPX module unload ++ - Clear TCP segmentation offload state in ipt_REJECT ++ - Fix atmarp.h for userspace ++ - UHCI: fix port resume problem ++ - Fix recently introduced problem with shutting down a busy NFS server. ++ - Avoid using nfsd process pools on SMP machines. ++ - EHCI: turn off remote wakeup during shutdown ++ - IPV6: HASHTABLES: Use appropriate seed for caluculating ehash index. ++ - MTD: Fatal regression in drivers/mtd/redboot.c in 2.6.20 ++ - Kconfig: FAULT_INJECTION can be selected only if LOCKDEP is enabled. ++ - USB HID: Fix USB vendor and product IDs endianness for USB HID devices ++ - Fix null pointer dereference in appledisplay driver ++ - ieee1394: fix host device registering when nodemgr disabled ++ - ieee1394: video1394: DMA fix ++ - Fix compile error for e500 core based processors ++ - md: Avoid possible BUG_ON in md bitmap handling. ++ - Fix allocation failure handling in multicast ++ - Fix TCP FIN handling ++ - Fix ATM initcall ordering. ++ - Fix various bugs with aligned reads in RAID5. ++ - hda-intel - Don't try to probe invalid codecs ++ - usbaudio - Fix Oops with unconventional sample rates ++ - usbaudio - Fix Oops with broken usb descriptors ++ - USB: fix concurrent buffer access in the hub driver ++ - Missing critical phys_to_virt in lib/swiotlb.c ++ - AGP: intel-agp bugfix ++ - bcm43xx: Fix for oops on ampdu status ++ - bcm43xx: Fix for oops on resume ++ - ide: fix drive side 80c cable check ++ - Keys: Fix key serial number collision handling ++ - knfsd: Fix a race in closing NFSd connections. ++ - pata_amd: fix an obvious bug in cable detection ++ - prism54: correct assignment of DOT1XENABLE in WE-19 codepaths ++ - rtc-pcf8563: detect polarity of century bit automatically ++ - x86_64: fix 2.6.18 regression - PTRACE_OLDSETOPTIONS should be accepted ++ - ocfs2: ocfs2_link() journal credits update ++ * Update xen patch to changeset 48670 from fedora 2.6.20 branch. ++ * Support xen versions 3.0.4-1 and 3.0.3-1. ++ ++ [ Rod Whitby ] ++ * arm/ixp4xx: Enable PATA_ARTOP for the nas100d and dsmg600. ++ * arm/ixp4xx: Enable RTC for the nas100d ++ * Add nas100d Ethernet MAC setup support. ++ * Add temporary hack to get Artop PATA support going on the nas100d. ++ ++ [ maximilian attems ] ++ * i386: Enable kvm. ++ * Add stable release 2.6.20.3: ++ - Fix sparc64 device register probing ++ - Fix bug 7994 sleeping function called from invalid context ++ - Fix timewait jiffies ++ - Fix UDP header pointer after pskb_trim_rcsum() ++ - Fix compat_getsockopt ++ - bcm43xx: Fix problem with >1 GB RAM ++ - nfnetlink_log: fix NULL pointer dereference ++ - nfnetlink_log: fix possible NULL pointer dereference ++ - conntrack: fix {nf, ip}_ct_iterate_cleanup endless loops ++ - nf_conntrack/nf_nat: fix incorrect config ifdefs ++ - tcp conntrack: accept SYN|URG as valid ++ - nfnetlink_log: fix reference leak ++ - nfnetlink_log: fix use after free ++ - nf_conntrack: fix incorrect classification of IPv6 fragments as ++ ESTABLISHED ++ - nfnetlink_log: zero-terminate prefix ++ - nfnetlink_log: fix crash on bridged packet ++ - Fix callback bug in connector ++ - fix for bugzilla #7544 (keyspan USB-to-serial converter) ++ - ip6_route_me_harder should take into account mark ++ * Add myself to uploaders field, entry got lost after 2.6.16-2 ++ * Add stable release 2.6.20.4: ++ - fix deadlock in audit_log_task_context() ++ - EHCI: add delay to bus_resume before accessing ports ++ - Copy over mac_len when cloning an skb ++ - fix read past end of array in md/linear.c ++ - oom fix: prevent oom from killing a process with children/sibling unkillable ++ - Fix sparc64 hugepage bugs ++ - Fix page allocation debugging on sparc64 ++ - Fix niagara memory corruption ++ - Input: i8042 - really suppress ACK/NAK during panic blink ++ - Input: i8042 - fix AUX IRQ delivery check ++ - Input: i8042 - another attempt to fix AUX delivery checks ++ - Fix rtm_to_ifaddr() error return. ++ - r8169: fix a race between PCI probe and dev_open ++ - futex: PI state locking fix ++ - adjust legacy IDE resource setting (v2) ++ - UML - arch_prctl should set thread fs ++ - gdth: fix oops in gdth_copy_cmd() ++ - Fix extraneous IPSEC larval SA creation ++ - IA64: fix NULL pointer in ia64/irq_chip-mask/unmask function ++ - st: fix Tape dies if wrong block size used, bug 7919 ++ - Fix ipv6 flow label inheritance ++ - NETFILTER: nfnetlink_log: fix reference counting ++ - mm: fix madvise infinine loop ++ - Fix another NULL pointer deref in ipv6_sockglue.c ++ - NetLabel: Verify sensitivity level has a valid CIPSO mapping ++ - Fix GFP_KERNEL with preemption disabled in fib_trie ++ - IrDA: irttp_dup spin_lock initialisation ++ - hda-intel - Fix codec probe with ATI controllers ++ - hrtimer: prevent overrun DoS in hrtimer_forward() ++ - fix MTIME_SEC_MAX on 32-bit ++ - nfs: nfs_getattr() can't call nfs_sync_mapping_range() for non-regular files ++ - dio: invalidate clean pages before dio write ++ - initialise pi_lock if CONFIG_RT_MUTEXES=N ++ * Add stable release 2.6.20.5: ++ - FRA_{DST,SRC} are le16 for decnet ++ - CIFS: reset mode when client notices that ATTR_READONLY is no longer set ++ - ide: clear bmdma status in ide_intr() for ICHx controllers (revised #4) ++ - ide: remove clearing bmdma status from cdrom_decode_status() (rev #4) ++ - NET: Fix sock_attach_fd() failure in sys_accept() ++ - DCCP: Fix exploitable hole in DCCP socket options ++ - ide: revert "ide: fix drive side 80c cable check, take 2" for now ++ - generic_serial: fix decoding of baud rate ++ - IPV6: Fix ipv6 round-robin locking. ++ - VIDEO: Fix FFB DAC revision probing ++ - PPP: Fix PPP skb leak ++ - V4L: msp_attach must return 0 if no msp3400 was found. ++ - CRYPTO: api: scatterwalk_copychunks() fails to advance through scatterlist ++ - APPLETALK: Fix a remotely triggerable crash (CVE-2007-1357) ++ - UML - fix epoll ++ - UML - host VDSO fix ++ - UML - Fix static linking ++ - UML - use correct register file size everywhere ++ - libata: sata_mv: don't touch reserved bits in EDMA config register ++ - libata: sata_mv: Fix 50xx irq mask ++ - libata bugfix: HDIO_DRIVE_TASK ++ - V4L: Fix SECAM handling on saa7115 ++ - DVB: fix nxt200x rf input switching ++ - SPARC: Fix sparc builds with gcc-4.2.x ++ - V4L: saa7146: Fix allocation of clipping memory ++ - uml: fix unreasonably long udelay ++ - NET: Fix packet classidier NULL pointer OOPS ++ - NET_SCHED: Fix ingress qdisc locking. ++ - sata_nv: delay on switching between NCQ and non-NCQ commands ++ - dvb-core: fix several locking related problems ++ - ieee1394: dv1394: fix CardBus card ejection ++ - CIFS: Allow reset of file to ATTR_NORMAL when archive bit not set ++ - jmicron: make ide jmicron driver play nice with libata ones ++ - libata: clear TF before IDENTIFYing ++ - NET: Fix FIB rules compatability ++ - DVB: isl6421: don't reference freed memory ++ - V4L: radio: Fix error in Kbuild file ++ - i2o: block IO errors on i2o disk ++ * Add stable release 2.6.20.6: ++ - CRYPTO api: Use the right value when advancing scatterwalk_copychunks ++ - uml: fix static linking for real ++ ++ [ Gordon Farquharson ] ++ * Disable broken config options on ARM. ++ ++ [ Frederik Schüler ] ++ * Disable NAPI on forcedeth, it is broken. ++ ++ [ dann frazier ] ++ * Hardcode the output of the scripts under arch/ia64/scripts as executed ++ in an etch environment so that we can build out of tree modules correctly ++ (re-add; patch seems to have been dropped during a merge.) ++ See: #392592 ++ * Allow '.' and '+' in the target dist field of the changelog. dpkg has ++ supported this since 1.13.20, see #361171. ++ ++ -- Bastian Blank Mon, 09 Apr 2007 19:21:52 +0200 ++ ++linux-2.6 (2.6.18.dfsg.1-10) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * Add patches out of stable queue 2.6.18 ++ - [amd64] Don't leak NT bit into next task (CVE-2006-5755) ++ - IB/srp: Fix FMR mapping for 32-bit kernels and addresses above 4G ++ - SCSI: add missing cdb clearing in scsi_execute() ++ * Xen postinst: Use takeover for update-initramfs. Makes postinst idempotent. ++ On creation it should always overwrite. (closes: #401183) ++ * Hand-picked from stable release 2.6.16.38: ++ - i2c-viapro: Add support for the VT8237A and VT8251 ++ - PCI: irq: irq and pci_ids patch for Intel ICH9 ++ - i2c-i801: SMBus patch for Intel ICH9 ++ - fix the UML compilation ++ - drm: allow detection of new VIA chipsets ++ - drm: Add the P4VM800PRO PCI ID. ++ - rio: typo in bitwise AND expression. ++ - i2c-mv64xxx: Fix random oops at boot ++ - i2c: fix broken ds1337 initialization ++ - [SUNKBD]: Fix sunkbd_enable(sunkbd, 0); obvious. ++ - Call init_timer() for ISDN PPP CCP reset state timer (CVE-2006-5749) ++ - V4L: cx88: Fix leadtek_eeprom tagging ++ - SPI/MTD: mtd_dataflash oops prevention ++ - grow_buffers() infinite loop fix (CVE-2006-5757/CVE-2006-6060) ++ - corrupted cramfs filesystems cause kernel oops (CVE-2006-5823) ++ - ext2: skip pages past number of blocks in ext2_find_entry ++ (CVE-2006-6054) ++ - handle ext3 directory corruption better (CVE-2006-6053) ++ - hfs_fill_super returns success even if no root inode (CVE-2006-6056) ++ backout previous fix, was not complete. ++ - Fix for shmem_truncate_range() BUG_ON() ++ - ebtables: check struct type before computing gap ++ - [IPV4/IPV6]: Fix inet{,6} device initialization order. ++ - [IPV6] Fix joining all-node multicast group. ++ - [SOUND] Sparc CS4231: Use 64 for period_bytes_min ++ * [PKTGEN]: Convert to kthread API. Thanks David Miller for patch. ++ * [IDE] Add driver for Jmicron JMB36x devices by Alan Cox. ++ Enable jmicron on i386 and amd64 archs. ++ * Hand-picked from stable release 2.6.16.39: ++ - atiixp: hang fix ++ - V4L/DVB: Flexcop-usb: fix debug printk ++ - V4L/DVB: Fix uninitialised variable in dvb_frontend_swzigzag ++ - read_zero_pagealigned() locking fix ++ - adfs: fix filename handling ++ - sparc32: add offset in pci_map_sg() ++ - cdrom: set default timeout to 7 seconds ++ - [SCSI] qla1280 command timeout ++ - [SCSI] qla1280 bus reset typo ++ - [Bluetooth] Check if DLC is still attached to the TTY ++ - [Bluetooth] Fix uninitialized return value for RFCOMM sendmsg() ++ - [Bluetooth] Return EINPROGRESS for non-blocking socket calls ++ - [Bluetooth] Handle command complete event for exit periodic inquiry ++ - [Bluetooth] Fix compat ioctl for BNEP, CMTP and HIDP ++ - [Bluetooth] Add locking for bt_proto array manipulation ++ - i386: fix CPU hotplug with 2GB VMSPLIT ++ ++ [ dann frazier ] ++ * Fix raid1 recovery (closes: #406181) ++ ++ [ Jurij Smakov ] ++ * Add dtlb-prot-bug-niagara.patch by David Miller, fixing the bug in the ++ Niagara's DTLB-PROT trap. ++ ++ [ Bastian Blank ] ++ * i386: Add amd64 image. (closes: #379090) ++ ++ -- Bastian Blank Fri, 2 Feb 2007 12:50:35 +0100 ++ ++linux-2.6 (2.6.18.dfsg.1-9) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * arm/iop32x: Enable CONFIG_IP_NF_CONNTRACK_EVENTS and _NETLINK. ++ * arm/ixp4xx: Enable some more I2C sensor modules. ++ * arm/ixp4xx: Enable CONFIG_USB_NET_RNDIS_HOST. ++ * arm/footbridge: Enable CONFIG_NATSEMI. ++ * Revert mm/msync patches because they cause filesystem corruption ++ (closes: #401006, #401980, #402707) ... ++ * ... and add an alternative msync patch from Hugh Dickins that ++ doesn't depend on the mm changes (closes: #394392). ++ * mips: provide pci_get_legacy_ide_irq needed by some IDE drivers ++ (see #404950). ++ * arm: Implement flush_anon_page(), which is needed for FUSE ++ (closes: #402876) and possibly dm-crypt/LUKS (see #403426). ++ * arm: Turn off PCI burst on the Cyber2010, otherwise X11 on ++ Netwinder will crash. ++ * arm/iop32x: Enable CONFIG_IEEE80211_SOFTMAC and drivers based ++ on it. ++ * arm/ixp4xx: Upgrade to version 0.3.1 of the IXP4xx NPE Ethernet ++ driver. This version fixes stuck connections, e.g. with scp and ++ NFS (closes: #404447). ++ * arm/ixp4xx: Enable CONFIG_VIDEO_CPIA_USB. ++ * arm/ixp4xx: Enable CONFIG_ISCSI_TCP. ++ * arm/iop32x: Likewise. ++ ++ [ Bastian Blank ] ++ * Bump ABI to 4. ++ * Update vserver patch to 2.0.2.2-rc9. (closes: #402743, #403790) ++ * Update xen patch to changeset 36186 from Fedora 2.6.18 branch. ++ * i386/xen: Build only the pae version. (closes: #390862) ++ * hppa: Override host type when necessary. ++ * Fix tg3 reset. (closes: #405085) ++ ++ [ dann frazier ] ++ * Fix potential fragmentation attacks in ip6_tables (CVE-2006-4572) ++ * Backport a number of fixes for the cciss driver ++ - Fix a bug with 1TB disks caused by converting total_size to an int ++ - Claim devices that are of the HP RAID class and have a valid cciss sig ++ - Make NR_CMDS a per-controller define - most can do 1024 commands, but ++ the E200 family can only support 128 ++ - Change the SSID on the E500 as a workaround for a firmware bug ++ - Disable prefetch on the P600 controller. An ASIC bug may result in ++ prefetching beyond the end of physical memory ++ - Increase blk_queue_max_sectors from 512 to 2048 to increase performance ++ - Map out more memor for the PCI config table, required to reach offset ++ 0x214 to disable DMA on the P600 ++ - Set a default raid level on a volume that either does not support ++ reading the geometry or reports an invalid geometry for whatever reason ++ to avoid problems with buggy firmware ++ - Revert change that replaed XFER_READ/XFER_WRITE macros with ++ h->cciss_read/h->cciss_write that caused command timeouts on older ++ controllers on ia32 (closes: #402787) ++ * Fix mincore hang (CVE-2006-4814) ++ * ia64: turn on IOC4 modules for SGI Altix systems. Thanks to Stephane Larose ++ for suggesting this. ++ * Add versioned build dep on findutils to make sure the system find command ++ supports the -execdir action (closes: #405150) ++ * Hardcode the output of the scripts under arch/ia64/scripts as executed ++ in an etch environment so that we can build out of tree modules correctly ++ (closes: #392592) ++ * Update unusual_devs entry for ipod to fix an eject issue (closes: #406124) ++ * Re-add verify_pmtmr_rate, resolving problems seen on older K6 ASUS ++ boards where the ACPI PM timer runs too fast (closes: #394753) ++ * Avoid condition where /proc/swaps header may not be printed ++ (closes: #292318) ++ * [hppa] disable XFS until it works (closes: #350482) ++ ++ [ Norbert Tretkowski ] ++ * libata: handle 0xff status properly. (closes: #391867) ++ * alpha: enabled CONFIG_SCSI_ARCMSR. (closes: #401187) ++ * removed BROKEN_ON_SMP dependency from I2C_ELEKTOR. (closes: #402253) ++ ++ [ Christian T. Steigies ] ++ * m68k/atari: enable keyboard, mouse and fb drivers ++ * m68k/atari: fixes for ethernec and video driver by Michael Schmitz ++ * m68k/atari: fixes for scsi driver by Michael Schmitz ++ * m68k/mac: fixes for mace and cuda driver by Finn Thain ++ * m68k/atari: fixes for ide driver by Michael Schmitz ++ * m68k/atari: fixes for ide driver by Michael Schmitz ++ * m68k/atari: fixes for ethernec and atakeyb driver by Michael Schmitz, build ethernec as module ++ * m68k/mac: fixes for mace and adb driver by Finn Thain ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.18.6: ++ - EBTABLES: Fix wraparounds in ebt_entries verification. ++ - EBTABLES: Verify that ebt_entries have zero ->distinguisher. ++ - EBTABLES: Deal with the worst-case behaviour in loop checks. ++ - EBTABLES: Prevent wraparounds in checks for entry components' sizes. ++ - skip data conversion in compat_sys_mount when data_page is NULL ++ - bonding: incorrect bonding state reported via ioctl ++ - x86-64: Mark rdtsc as sync only for netburst, not for core2 ++ (closes: #406767) ++ - dm crypt: Fix data corruption with dm-crypt over RAID5 (closes: #402812) ++ - forcedeth: Disable INTx when enabling MSI in forcedeth ++ - PKT_SCHED act_gact: division by zero ++ - XFRM: Use output device disable_xfrm for forwarded packets ++ - IPSEC: Fix inetpeer leak in ipv4 xfrm dst entries. ++ - V4L: Fix broken TUNER_LG_NTSC_TAPE radio support ++ - m32r: make userspace headers platform-independent ++ - IrDA: Incorrect TTP header reservation ++ - SUNHME: Fix for sunhme failures on x86 ++ - Bluetooth: Add packet size checks for CAPI messages (CVE-2006-6106) ++ - softmac: remove netif_tx_disable when scanning ++ - DVB: lgdt330x: fix signal / lock status detection bug ++ - dm snapshot: fix freeing pending exception ++ - NET_SCHED: policer: restore compatibility with old iproute binaries ++ - NETFILTER: ip_tables: revision support for compat code ++ - ARM: Add sys_*at syscalls ++ - ieee1394: ohci1394: add PPC_PMAC platform code to driver probe ++ - softirq: remove BUG_ONs which can incorrectly trigger ++ * Hand-picked from stable release 2.6.16.30: ++ - [PPPOE]: Advertise PPPoE MTU ++ * Hand-picked from stable release 2.6.16.31: ++ - [NETFILTER]: Fix ip6_tables extension header bypass bug (CVE-2006-4572) ++ - fix RARP ic_servaddr breakage ++ * Hand-picked from stable release 2.6.16.32: ++ - drivers/telephony/ixj: fix an array overrun ++ - flush D-cache in failure path ++ * Hand-picked from stable release 2.6.16.33: ++ - Add new PHY to sis900 supported list ++ - ipmi_si_intf.c: fix "&& 0xff" typos ++ - drivers/scsi/psi240i.c: fix an array overrun ++ * Hand-picked from stable release 2.6.16.34: ++ - [IPX]: Annotate and fix IPX checksum ++ - [IGMP]: Fix IGMPV3_EXP() normalization bit shift value. ++ * Hand-picked from stable release 2.6.16.35: ++ - sgiioc4: Disable module unload ++ - Fix a masking bug in the 6pack driver. ++ - drivers/usb/input/ati_remote.c: fix cut'n'paste error ++ - proper flags type of spin_lock_irqsave() ++ * Hand-picked from stable release 2.6.16.37: ++ - [CRYPTO] sha512: Fix sha384 block size ++ - [SCSI] gdth: Fix && typos ++ - Fix SUNRPC wakeup/execute race condition ++ * Enable DEBUG_FS for usbmon in generic config. Don't disable it on alpha, ++ amd64, hppa and ia64. (closes: 378542) ++ * Backport a number of upstream fixes for the r8169 driver, needed for ++ network performance (closes: 388870, 400524) ++ - r8169: more alignment for the 0x8168 ++ - r8169: phy program update ++ - r8169: more magic during initialization of the hardware ++ - r8169: perform a PHY reset before any other operation at boot time ++ - r8169: Fix iteration variable sign ++ - r8169: remove extraneous Cmd{Tx/Rx}Enb write ++ * sound: hda: detect ALC883 on MSI K9A Platinum motherboards (MS-7280) ++ patch from Leonard Norrgard ++ * tulip: Add i386 specific patch to remove duplicate pci ids. ++ Thanks Jurij Smakov (closes: #334104, #405203) ++ * amd64, i386: Disable SK98LIN as SKGE is the modern capable driver. ++ (closes: 405196) ++ * Backout net-bcm43xx_netdev_watchdog.patch and push 2.6.18.2 fix. ++ (closes: 402475) ++ ++ [ Jurij Smakov ] ++ * Add bugfix/sparc/isa-dev-no-reg.patch to make sure that ++ isa_dev_get_resource() can deal with devices which do not have a 'reg' ++ PROM property. Failure to handle such devices properly resulted in an ++ oops during boot on Netra X1. Thanks to Richard Mortimer for debugging ++ and patch. (closes: #404216) ++ * Add bugfix/sparc/ehci-hub-contol-alignment.patch to prevent unaligned ++ memory accesses in ehci-hub-control() by adding an alignment attribute ++ to the tbuf array declaration. Thanks to David Miller for the patch. ++ ++ [ Sven Luther ] ++ * [powerpc] Enable CONFIG_PMAC_BACKLIGHT_LEGACY (Closes: #407671). ++ ++ -- Bastian Blank Wed, 24 Jan 2007 13:21:51 +0100 ++ ++linux-2.6 (2.6.18-8) unstable; urgency=low ++ ++ * Fix relations in the generated control file. (closes: #400544) ++ * Add stable release 2.6.18.4: ++ - bridge: fix possible overflow in get_fdb_entries (CVE-2006-5751) ++ * Add stable release 2.6.18.5: ++ - pcmcia: fix 'rmmod pcmcia' with unbound devices ++ - BLUETOOTH: Fix unaligned access in hci_send_to_sock. ++ - alpha: Fix ALPHA_EV56 dependencies typo ++ - TG3: Add missing unlock in tg3_open() error path. ++ - softmac: fix a slab corruption in WEP restricted key association ++ - AGP: Allocate AGP pages with GFP_DMA32 by default ++ - V4L: Do not enable VIDEO_V4L2 unconditionally ++ - bcm43xx: Drain TX status before starting IRQs ++ - fuse: fix Oops in lookup ++ - UDP: Make udp_encap_rcv use pskb_may_pull ++ - NETFILTER: Missing check for CAP_NET_ADMIN in iptables compat layer ++ - NETFILTER: ip_tables: compat error way cleanup ++ - NETFILTER: ip_tables: fix module refcount leaks in compat error paths ++ - NETFILTER: Missed and reordered checks in {arp,ip,ip6}_tables ++ - NETFILTER: arp_tables: missing unregistration on module unload ++ - NETFILTER: Kconfig: fix xt_physdev dependencies ++ - NETFILTER: xt_CONNSECMARK: fix Kconfig dependencies ++ - NETFILTER: H.323 conntrack: fix crash with CONFIG_IP_NF_CT_ACCT ++ - IA64: bte_unaligned_copy() transfers one extra cache line. ++ - x86 microcode: don't check the size ++ - scsi: clear garbage after CDBs on SG_IO ++ - IPV6: Fix address/interface handling in UDP and DCCP, according to the scoping architecture. ++ * Revert abi changing patch from 2.6.18.5. ++ ++ -- Bastian Blank Sun, 10 Dec 2006 17:51:53 +0100 ++ ++linux-2.6 (2.6.18-7) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Emit conflict lines for initramfs generators. (closes: #400305) ++ * Update vserver patch to 2.0.2.2-rc8. ++ * s390: Add patch to fix posix types. ++ ++ [ Martin Michlmayr ] ++ * r8169: Add an option to ignore parity errors. ++ * r8169: Ignore parity errors on the Thecus N2100. ++ * rtc: Add patch from Riku Voipio to get RS5C372 going on the N2100. ++ * arm/iop32x: Build RS5C372 support into the kernel. ++ ++ [ maximilian attems ] ++ * hfs: Fix up error handling in HFS. (MOKB-14-11-2006) ++ * sata: Avoid null pointer dereference in SATA Promise. ++ * cifs: Set CIFS preferred IO size. ++ ++ [ Jurij Smakov ] ++ * Add bugfix/sunhme-pci-enable.patch, fixing the failure of sunhme ++ driver on x86/PCI hosts due to missing pci_enable_device() and ++ pci_set_master() calls, lost during code refactoring upstream. ++ (closes: #397460) ++ ++ -- Bastian Blank Mon, 4 Dec 2006 15:20:30 +0100 ++ ++linux-2.6 (2.6.18-6) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * Enable the new ACT modules globally. They were already set for amd64, hppa ++ and mips/mipsel - needed by newer iproute2. (closes: #395882, #398172) ++ * Fix msync() for LSB 3.1 compliance, backport fedora patches from 2.6.19 ++ - mm: tracking shared dirty pages ++ - mm: balance dirty pages ++ - mm: optimize the new mprotect() code a bit ++ - mm: small cleanup of install_page() ++ - mm: fixup do_wp_page() ++ - mm: msync() cleanup (closes: #394392) ++ * [amd64,i386] Enable CONFIG_USB_APPLETOUCH=m (closes: #382298) ++ * Add stable release 2.6.18.3: ++ - x86_64: Fix FPU corruption ++ - e1000: Fix regression: garbled stats and irq allocation during swsusp ++ - POWERPC: Make alignment exception always check exception table ++ - usbtouchscreen: use endpoint address from endpoint descriptor ++ - fix via586 irq routing for pirq 5 ++ - init_reap_node() initialization fix ++ - CPUFREQ: Make acpi-cpufreq unsticky again. ++ - SPARC64: Fix futex_atomic_cmpxchg_inatomic implementation. ++ - SPARC: Fix missed bump of NR_SYSCALLS. ++ - NET: __alloc_pages() failures reported due to fragmentation ++ - pci: don't try to remove sysfs files before they are setup. ++ - fix UFS superblock alignment issues ++ - NET: Set truesize in pskb_copy ++ - block: Fix bad data direction in SG_IO (closes: #394690) ++ - cpqarray: fix iostat ++ - cciss: fix iostat ++ - Char: isicom, fix close bug ++ - TCP: Don't use highmem in tcp hash size calculation. ++ - S390: user readable uninitialised kernel memory, take 2. ++ - correct keymapping on Powerbook built-in USB ISO keyboards ++ - USB: failure in usblp's error path ++ - Input: psmouse - fix attribute access on 64-bit systems ++ - Fix sys_move_pages when a NULL node list is passed. ++ - CIFS: report rename failure when target file is locked by Windows ++ - CIFS: New POSIX locking code not setting rc properly to zero on successful ++ - Patch for nvidia divide by zero error for 7600 pci-express card ++ (maybe fixes 398258) ++ - ipmi_si_intf.c sets bad class_mask with PCI_DEVICE_CLASS ++ ++ [ Steve Langasek ] ++ * [alpha] new titan-video patch, for compatibility with TITAN and similar ++ systems with non-standard VGA hose configs ++ * [alpha] bugfix for srm_env module from upstream (Jan-Benedict Glaw), ++ makes the module compatible with the current /proc interface so that ++ reads no longer return EFAULT. (closes: #353079) ++ * Bump ABI to 3 for the msync fixes above. ++ ++ [ Martin Michlmayr ] ++ * arm: Set CONFIG_BINFMT_MISC=m ++ * arm/ixp4xx: Set CONFIG_ATM=m (and related modules) so CONFIG_USB_ATM has ++ an effect. ++ * arm/iop32x: Likewise. ++ * arm/s3c2410: Unset CONFIG_PM_LEGACY. ++ * arm/versatile: Fix Versatile PCI config byte accesses ++ * arm/ixp4xx: Swap the disk 1 and disk 2 LED definitions so they're right. ++ * mipsel/r5k-cobalt: Unset CONFIG_SCSI_SYM53C8XX_2 because the timeout is ++ just too long. ++ * arm/ixp4xx: Enable more V4L USB devices. ++ ++ [ dann frazier ] ++ * Backport various SCTP changesets from 2.6.19, recommended by Vlad Yasevich ++ (closes: #397946) ++ * Add a "Scope of security support" section to README.Debian, recommended ++ by Moritz Muehlenhoff ++ ++ [ Thiemo Seufer ] ++ * Enable raid456 for mips/mipsel qemu kernel. ++ ++ [ dann frazier ] ++ * The scope of the USR-61S2B unusual_dev entry was tightened, but too ++ strictly. Loosen it to apply to additional devices with a smaller bcd. ++ (closes: #396375) ++ ++ [ Sven Luther ] ++ * Added support for TI ez430 development tool ID in ti_usb. ++ Thanks to Oleg Verych for providing the patch. ++ ++ [ Christian T. Steigies ] ++ * Added support for Atari EtherNEC, Aranym, video, keyboard, mouse, and serial ++ by Michael Schmitz ++ ++ [ Bastian Blank ] ++ * [i386] Reenable AVM isdn card modules. (closes: #386872) ++ ++ -- Bastian Blank Tue, 21 Nov 2006 11:28:09 +0100 ++ ++linux-2.6 (2.6.18-5) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * [s390] readd the fix for "S390: user readable uninitialised kernel memory ++ (CVE-2006-5174)" ++ * [s390] temporarily add patch queued for 2.6.18.3 fixing 32 bit opcodes and ++ instructions. ++ ++ [ Thiemo Seufer ] ++ * Fix build failure of hugetlbfs (closes: #397139). ++ * Add kernel configuration for qemu's mips/mipsel emulation, thanks to ++ Aurelien Jarno. ++ ++ [ Bastian Blank ] ++ * Update vserver patch to 2.0.2.2-rc6. ++ * Update xen parts for vserver. (closes: #397281) ++ ++ [ dann frazier ] ++ * [ia64] Move to upstream version of sal-flush-fix patch, which is slightly ++ different than the early version added in 2.6.18-3. ++ ++ [ Frederik Schüler ] ++ * [i386] Acticate CONFIG_SX for all flavours. (closes: #391275) ++ ++ [ Steve Langasek ] ++ * [alpha] new asm-subarchs patch: tell the compiler that we're ++ deliberately emitting ev56 or ev6 instructions, so that this code ++ will still compile without having to cripple gcc-4.1's checking of ++ whether the correct instruction set is used. Closes: #397139. ++ ++ [ Martin Michlmayr ] ++ * arm/ixp4xx: Enable CONFIG_USB_ATM. ++ * arm/iop32x: Enable CONFIG_PPPOE. ++ * arm/iop32x: Enable CONFIG_USB_ATM. ++ ++ -- Bastian Blank Wed, 8 Nov 2006 17:15:55 +0100 ++ ++linux-2.6 (2.6.18-4) unstable; urgency=low ++ ++ [ Norbert Tretkowski ] ++ * [alpha] Switched to gcc-4.1. ++ ++ [ Jurij Smakov ] ++ * [sparc] Remove sparc64-atyfb-xl-gr.patch, it does more harm than ++ good in 2.6.18. ++ * [sparc] Add bugfix/sparc/compat-alloc-user-space-alignment.patch ++ (thanks to David Miller) to make sure that compat_alloc_user_space() ++ always returns memory aligned on a 8-byte boundary on sparc. This ++ prevents a number of unaligned memory accesses, like the ones in ++ sys_msgrcv() and compat_sys_msgrcv(), triggered every 5 seconds whenever ++ fakeroot is running. ++ * [sparc] Add bugfix/sparc/bus-id-size.patch (thanks to David Miller) ++ to ensure that the size of the strings stored in the bus_id field of ++ struct device never exceeds the amount of memory allocated for them ++ (20 bytes). It fixes the situations in which storing longer device ++ names in this field would cause corruption of adjacent memory regions. ++ (closes: #394697). ++ * [sparc] Add bugfix/sparc/sunblade1k-boot-fix.patch (thanks to David ++ Miller) to fix a boottime crash on SunBlade1000. ++ * [sparc] Add bugfix/sparc/t1k-cpu-lockup.patch (thanks to David Miller) ++ to prevent soft CPU lockup on T1000 servers, which can be triggered from ++ userspace, resulting in denial of service. ++ ++ [ Martin Michlmayr ] ++ * arm/iop32x: Fix the interrupt of the 2nd Ethernet slot on N2100. ++ * arm/iop32x: Allow USB and serial to co-exist on N2100. ++ * arm/ixp4xx: Add clocksource for Intel IXP4xx platforms. ++ * arm: Enable CONFIG_AUDIT=y again. ++ * arm/ixp4xx: Add the IXP4xx Ethernet driver. ++ * arm/ixp4xx: Build LED support into the kernel. ++ * Add a driver for Fintek F75375S/SP and F75373. ++ * arm/iop32x: Build F75375S/SP support in. ++ * arm/iop32x: Fix the size of the RedBoot config partition. ++ ++ [ maximilian attems ] ++ * Add netpoll leak fix. ++ * Add upstream forcedeth swsusp support. ++ * r8169: PCI ID for Corega Gigabit network card. ++ * r8169: the MMIO region of the 8167 stands behin BAR#1. ++ * r8169: Add upstream fix for infinite loop during hotplug. ++ * Bump build-dependency on kernel-package to 10.063. ++ * r8169: pull revert mac address change support. ++ * bcm43xx: Add full netdev watchout timeout patch. (closes: 392065) ++ Thanks Sjoerd Simons for the testing. ++ * Add stable release 2.6.18.2: ++ - Remove not yet released, revert the included patches. ++ - Keep aboves bcm43xx fix, it's more complete. ++ - Watchdog: sc1200wdt - fix missing pnp_unregister_driver() ++ - fix missing ifdefs in syscall classes hookup for generic targets ++ - JMB 368 PATA detection ++ - usbfs: private mutex for open, release, and remove ++ - sound/pci/au88x0/au88x0.c: ioremap balanced with iounmap ++ - x86-64: Fix C3 timer test ++ - Reintroduce NODES_SPAN_OTHER_NODES for powerpc ++ - ALSA: emu10k1: Fix outl() in snd_emu10k1_resume_regs() ++ - IB/mthca: Use mmiowb after doorbell ring ++ - SCSI: DAC960: PCI id table fixup ++ - ALSA: snd_rtctimer: handle RTC interrupts with a tasklet ++ - JFS: pageno needs to be long ++ - SPARC64: Fix central/FHC bus handling on Ex000 systems. ++ - SPARC64: Fix memory corruption in pci_4u_free_consistent(). ++ - SPARC64: Fix PCI memory space root resource on Hummingbird. ++ (closes: #392078) ++ - Fix uninitialised spinlock in via-pmu-backlight code. ++ - SCSI: aic7xxx: pause sequencer before touching SBLKCTL ++ - IPoIB: Rejoin all multicast groups after a port event ++ - ALSA: Dereference after free in snd_hwdep_release() ++ - rtc-max6902: month conversion fix ++ - NET: Fix skb_segment() handling of fully linear SKBs ++ - SCTP: Always linearise packet on input ++ - SCSI: aic7xxx: avoid checking SBLKCTL register for certain cards ++ - IPV6: fix lockup via /proc/net/ip6_flowlabel [CVE-2006-5619] ++ - fix Intel RNG detection ++ - ISDN: check for userspace copy faults ++ - ISDN: fix drivers, by handling errors thrown by ->readstat() ++ - splice: fix pipe_to_file() ->prepare_write() error path ++ - ALSA: Fix bug in snd-usb-usx2y's usX2Y_pcms_lock_check() ++ - ALSA: Repair snd-usb-usx2y for usb 2.6.18 ++ - PCI: Remove quirk_via_abnormal_poweroff ++ - Bluetooth: Check if DLC is still attached to the TTY ++ - vmscan: Fix temp_priority race ++ - Use min of two prio settings in calculating distress for reclaim ++ - __div64_32 for 31 bit. Fixes funny clock speed on hercules emulator. ++ (closes: 395247) ++ - DVB: fix dvb_pll_attach for mt352/zl10353 in cx88-dvb, and nxt200x ++ - fuse: fix hang on SMP ++ - md: Fix bug where spares don't always get rebuilt properly when they become live. ++ - md: Fix calculation of ->degraded for multipath and raid10 ++ - knfsd: Fix race that can disable NFS server. ++ - md: check bio address after mapping through partitions. ++ - fill_tgid: fix task_struct leak and possible oops ++ - uml: fix processor selection to exclude unsupported processors and features ++ - uml: remove warnings added by previous -stable patch ++ - Fix sfuzz hanging on 2.6.18 ++ - SERIAL: Fix resume handling bug ++ - SERIAL: Fix oops when removing suspended serial port ++ - sky2: MSI test race and message ++ - sky2: pause parameter adjustment ++ - sky2: turn off PHY IRQ on shutdown ++ - sky2: accept multicast pause frames ++ - sky2: GMAC pause frame ++ - sky2: 88E803X transmit lockup (2.6.18) ++ - tcp: cubic scaling error ++ - mm: fix a race condition under SMC + COW ++ - ALSA: powermac - Fix Oops when conflicting with aoa driver ++ - ALSA: Fix re-use of va_list ++ - posix-cpu-timers: prevent signal delivery starvation ++ - NFS: nfs_lookup - don't hash dentry when optimising away the lookup ++ - uml: make Uml compile on FC6 kernel headers ++ - Fix potential interrupts during alternative patching ++ * Backport atkbd - supress "too many keys" error message. ++ * [s390] Revert temporarly 2.6.18.1 "S390: user readable uninitialised ++ kernel memory (CVE-2006-5174)" fix as it causes ftfbs ++ ++ [ Sven Luther ] ++ * [powerpc] Added exception alignement patch from Benjamin Herrenschmidt. ++ ++ [ Frederik Schüler ] ++ * Bump ABI to 2. ++ * Update vserver patch to 2.0.2.2-rc4. ++ ++ [ Thiemo Seufer ] ++ * Add patches from linux-mips.org's 2.6.18-stable branch: ++ - bugfix/copy-user-highpage.patch, needed for cache alias handling ++ on mips/mipsel/hppa. ++ - bugfix/mips/syscall-wiring.patch, fixes TLS register access, and ++ n32 rt_sigqueueinfo. ++ - bugfix/mips/sb1-flush-cache-data-page.patch, missing cache flush ++ on SB-1. ++ - bugfix/mips/trylock.patch, fix trylock implementation for R1x000 ++ and R3xxx. ++ - bugfix/mips/smp-cpu-bringup.patch, correct initialization of ++ non-contiguous CPU topology. ++ - bugfix/mips/header-exports.patch, clean up userland exports of ++ kernel headers. ++ - bugfix/mips/sb1-interrupt-handler.patch, fix broken interrupt ++ routing on SB-1. ++ - bugfix/mips/cache-alias.patch, fixes #387498 for mips/mipsel. ++ - bugfix/mips/ip22-zilog-console.patch, fix long delays seen with ++ SGI ip22 serial console. ++ - bugfix/mips/signal-handling.patch, fixes a signal handling race ++ condition shown with gdb. ++ - bugfix/mips/sb1-duart-tts.patch, replaces mips-sb1-duart-tts.patch, ++ use standard Linux names for SB-1 consoles. ++ - bugfix/mips/wait-race.patch, correct behaviour of the idle loop. ++ - bugfix/mips/sgi-ioc3.patch, checksumming fix for IOC3 network ++ driver. ++ - features/mips/qemu-kernel.patch, support for the mips/mipsel ++ machine emulated by Qemu. ++ - features/mips/backtrace.patch, reimplementation of stack analysis ++ and backtrace printing, useful for in-kernel debugging. ++ - bugfix/mips/dec-scsi.patch, replaces mips-dec-scsi.patch, fixes DSP ++ SCSI driver for DECstations. ++ - bugfix/mips/dec-serial.patch, replaces mips-dec-serial.patch, fix ++ serial console handling on DECstations. ++ ++ -- Frederik Schüler Sat, 4 Nov 2006 18:45:02 +0100 ++ ++linux-2.6 (2.6.18-3) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Fix home of patch apply script. ++ * Unify CPUSET option. (closes: #391931) ++ * Support xen version 3.0.3-1. ++ * Add AHCI suspend support. ++ * Add patch to support bindmount without nodev on vserver. ++ * Update fedora xen patch to changeset 36252. ++ ++ [ Steve Langasek ] ++ * [alpha] restore alpha-prctl.patch, which keeps disappearing every time ++ there's a kernel upgrade :/ ++ ++ [ Frederik Schüler ] ++ * Activate CONFIG_NET_CLS_* globaly. (Closes: #389918) ++ * Make CONFIG_EFI_VARS modular on i386. (Closes: #381951) ++ * Activate CONFIG_SCSI_ARCMSR on amd64, powerpc, sparc too. ++ * [vserver] Activate HARDCPU and HARDCPU_IDLE. ++ * [vserver] Upgrade to vs2.0.2.2-rc2. ++ ++ [ maximilian attems ] ++ * [mipsel] Disable CONFIG_SECURITY_SECLVL on DECstations too. ++ * Add stable release 2.6.18.1: ++ - add utsrelease.h to the dontdiff file ++ - V4L: copy-paste bug in videodev.c ++ - block layer: elv_iosched_show should get elv_list_lock ++ - NETFILTER: NAT: fix NOTRACK checksum handling ++ - bcm43xx: fix regressions in 2.6.18 (Closes: #392065) ++ - x86-64: Calgary IOMMU: Fix off by one when calculating register space ++ location ++ - ide-generic: jmicron fix ++ - scx200_hrt: fix precedence bug manifesting as 27x clock in 1 MHz mode ++ - invalidate_inode_pages2(): ignore page refcounts ++ - rtc driver rtc-pcf8563 century bit inversed ++ - fbdev: correct buffer size limit in fbmem_read_proc() ++ - mm: bug in set_page_dirty_buffers ++ - TCP: Fix and simplify microsecond rtt sampling ++ - MD: Fix problem where hot-added drives are not resynced. ++ - IPV6: Disable SG for GSO unless we have checksum ++ - PKT_SCHED: cls_basic: Use unsigned int when generating handle ++ - sata_mv: fix oops ++ - [SPARC64]: Kill bogus check from bootmem_init(). ++ - IPV6: bh_lock_sock_nested on tcp_v6_rcv ++ - [CPUFREQ] Fix some more CPU hotplug locking. ++ - SPARC64: Fix serious bug in sched_clock() on sparc64 ++ - Fix VIDIOC_ENUMSTD bug ++ - load_module: no BUG if module_subsys uninitialized ++ - i386: fix flat mode numa on a real numa system ++ - cpu to node relationship fixup: map cpu to node ++ - cpu to node relationship fixup: acpi_map_cpu2node ++ - backlight: fix oops in __mutex_lock_slowpath during head ++ /sys/class/graphics/fb0/* ++ - do not free non slab allocated per_cpu_pageset ++ - rtc: lockdep fix/workaround ++ - powerpc: Fix ohare IDE irq workaround on old powermacs ++ - sysfs: remove duplicated dput in sysfs_update_file ++ - powerpc: fix building gdb against asm/ptrace.h ++ - Remove offsetof() from user-visible ++ - Clean up exported headers on CRIS ++ - Fix v850 exported headers ++ - Don't advertise (or allow) headers_{install,check} where inappropriate. ++ - Remove UML header export ++ - Remove ARM26 header export. ++ - Fix H8300 exported headers. ++ - Fix m68knommu exported headers ++ - Fix exported headers for SPARC, SPARC64 ++ - Fix 'make headers_check' on m32r ++ - Fix 'make headers_check' on sh64 ++ - Fix 'make headers_check' on sh ++ - Fix ARM 'make headers_check' ++ - One line per header in Kbuild files to reduce conflicts ++ - sky2 network driver device ids ++ - sky2: tx pause bug fix ++ - netdrvr: lp486e: fix typo ++ - mv643xx_eth: fix obvious typo, which caused build breakage ++ - zone_reclaim: dynamic slab reclaim ++ - Fix longstanding load balancing bug in the scheduler ++ - jbd: fix commit of ordered data buffers ++ - ALSA: Fix initiailization of user-space controls ++ - USB: Allow compile in g_ether, fix typo ++ - IB/mthca: Fix lid used for sending traps ++ - S390: user readable uninitialised kernel memory (CVE-2006-5174) ++ - zd1211rw: ZD1211B ASIC/FWT, not jointly decoder ++ - V4L: pvrusb2: Limit hor res for 24xxx devices ++ - V4L: pvrusb2: Suppress compiler warning ++ - V4L: pvrusb2: improve 24XXX config option description ++ - V4L: pvrusb2: Solve mutex deadlock ++ - DVB: cx24123: fix PLL divisor setup ++ - V4L: Fix msp343xG handling regression ++ - UML: Fix UML build failure ++ - uml: use DEFCONFIG_LIST to avoid reading host's config ++ - uml: allow using again x86/x86_64 crypto code ++ - NET_SCHED: Fix fallout from dev->qdisc RCU change ++ * Add backported git patch remving BSD secure level - request by the ++ Debian Security Team. (closes: 389282) ++ * [powerpc] Add DAC960-ipr PCI id table fixup. ++ * [powerpc] Fix uninitialised spinlock in via-pmu-backlight code. ++ * Fix serial_cs resume handling. ++ * Fix oops when removing suspended serial port. ++ * Check if DLC is still attached to the TTY. ++ * Add fedora backport of i965 DRM support. ++ ++ [ Martin Michlmayr ] ++ * [mips] Apply some patches from linux-mips' linux-2.6.18-stable GIT tree: ++ - The o32 fstatat syscall behaves differently on 32 and 64 bit kernels ++ - fstatat syscall names ++ - BCM1480: Mask pending interrupts against c0_status.im. ++ - Cobalt: Time runs too quickly ++ - Show actual CPU information in /proc/cpuinfo ++ - Workaround for bug in gcc -EB / -EL options ++ - Do not use -msym32 option for modules ++ - Fix O32 personality(2) call with 0xffffffff argument ++ - Use compat_sys_mount ++ ++ [ dann frazier ] ++ * [ia64]: Fix booting on HP cell systems, thanks to Troy Heber ++ - Enable CONFIG_HUGETLBFS ++ - bugfix/ia64/sal-flush-fix.patch: delay sal cache flush ++ * bugfix/sky2-receive-FIFO-fix.patch: fix sky2 hangs on some chips ++ Thanks to Stephen Hemminger for the patch. (Closes: #391382) ++ * features/all/drivers/cciss-support-for-gt-2TB-volumes.patch: ++ Add support for > 2TB volumes ++ * bugfix/sym2-dont-claim-raid-devs.patch: Prevent cpqarray/sym2 conflict ++ by telling sym2 not to claim raid devices. (Closes: #391384) ++ ++ [ Sven Luther ] ++ * [powerpc] Added AMD74xx driver module to the powerpc64 flavour ++ (Closes: #391861). ++ ++ [ Kyle McMartin ] ++ * [hppa] Force CROSS_COMPILE=hppa64-linux-gnu- (closes: #389296) ++ ++ -- Bastian Blank Sat, 21 Oct 2006 15:59:43 +0200 ++ ++linux-2.6 (2.6.18-2) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * hppa: Fix compiler dependencies. (closes: #389296) ++ * Make cfq the default io scheduler. ++ * Add arcmsr (Areca) driver. ++ * powerpc/prep: Fix compatibility asm symlink. ++ * m68k: Disable initramfs support. ++ ++ [ Kyle McMartin ] ++ * hppa: Add parisc patchset. ++ ++ [ Norbert Tretkowski ] ++ * [alpha] Workaround undefined symbols by setting CONFIG_SCSI=y for smp flavour. ++ (closes: #369517) ++ ++ [ Christian T. Steiges ] ++ * m68k: Update patches for 2.6.18. ++ * m68k: Re-Add m68k-as and m68k-macro patch which allow building with current binutils. ++ * m68k: disable CONFIG_AUDIT for m68k. ++ * m68k/mac: add m68k-no-backlight and m68k-fbcon patch. ++ * m68k/mac: enable SONIC, disable all ADB but CUDA. ++ ++ [ Jurij Smakov ] ++ * Add bugfix/proc-fb-reading.patch to fix the inconsistent behaviour ++ of /proc/fb. (Closes: #388815) ++ * sparc: Enable vserver flavour for sparc64. (Closes: #386656) ++ ++ -- Bastian Blank Fri, 29 Sep 2006 14:12:19 +0200 ++ ++linux-2.6 (2.6.18-1) unstable; urgency=low ++ ++ The unpruned release ++ ++ [ Martin Michlmayr ] ++ * Bump build-dependency on kernel-package to 10.054. ++ * arm/iop32x: Build ext2/3 as modules. ++ * arm/iop32x: Disable CONFIG_EMBEDDED. ++ * mipsel/r5k-cobalt: Enable ISDN. ++ * arm/footbridge: Enable the CIFS module (closes: #274808). ++ * arm/nslu2: Drop flavour since this machine is supported by arm/ixp4xx. ++ * arm: Make get_unaligned() work with const pointers and GCC 4.1. ++ * mipsel/r5k-cobalt: Enable CONFIG_BONDING as a module. ++ * arm/iop32x: Likewise. ++ * arm/ixp4xx: Likewise. ++ * arm: Disable CONFIG_AUDIT for now since it's broken. ++ ++ [ Sven Luther ] ++ * [powerpc] Enabled the -prep flavour. (Closes: #359025) ++ * [powerpc] The sisfb framebuffer device is now builtin. ++ * [powerpc] Updated the powerpc serial patch. This fixes the XServe serial ++ port, but at the cost powermac pcmcia serial cards support. ++ Thanks go to Mark Hymers for providing the patch. ++ (Closes: #364637, #375194) ++ * [powerpc] Added patch to fix oldworld/quik booting. ++ Thanks fo to Christian Aichinger for investigating to Benjamin ++ Herrenschmidt for providing the patch. (Closes: #366620, #375035). ++ * [powerpc] Fixes hvc_console caused suspsend-to-disk breakage. Thanks to ++ Andrew Morton for providing the patch. (Closes: #387178) ++ * [powerpc] Disabled mv643xx_eth on powerpc64 flavours, as there never was a ++ Marvell Discovery northbrige for 64bit powerpc cpus. ++ ++ [ Frederik Schüler ] ++ * Remove obsolete options from amd64 and i386 configs. ++ * Deactivate EVBUG. ++ * Make PARPORT options global. ++ * [i386] Add class definition for 486 flavour. ++ ++ [ maximilian attems ] ++ * Enable CONFIG_PRINTER=m for all powerpc flavours. ++ * Enable the new alsa CONFIG_SND_AOA framework for powerpc. ++ * Add the merged advansys pci table patch. ++ ++ [ Bastian Blank ] ++ * hppa: Use gcc-4.1. ++ * Only provide 16 legacy ptys. ++ ++ [ Norbert Tretkowski ] ++ * [alpha] Updated configs. ++ * [alpha] Disabled CONFIG_AUDIT, broken. ++ * [alpha] Added vserver flavour. ++ ++ -- Bastian Blank Sun, 24 Sep 2006 15:55:37 +0200 ++ ++linux-2.6 (2.6.17-9) unstable; urgency=medium ++ ++ [ Bastian Blank ] ++ * Update vserver patch to 2.0.2. ++ - Fix possible priviledge escalation in remount code. (CVE-2006-4243) ++ ++ [ Frederik Schüler ] ++ * Add stable release 2.5.17.12: ++ - sky2: version 1.6.1 ++ - sky2: fix fiber support ++ - sky2: MSI test timing ++ - sky2: use dev_alloc_skb for receive buffers ++ - sky2: clear status IRQ after empty ++ - sky2: accept flow control ++ - dm: Fix deadlock under high i/o load in raid1 setup. ++ - Remove redundant up() in stop_machine() ++ - Missing PCI id update for VIA IDE ++ - PKTGEN: Fix oops when used with balance-tlb bonding ++ - PKTGEN: Make sure skb->{nh,h} are initialized in fill_packet_ipv6() too. ++ - Silent data corruption caused by XPC ++ - uhci-hcd: fix list access bug ++ - binfmt_elf: fix checks for bad address ++ - [s390] bug in futex unqueue_me ++ - fcntl(F_SETSIG) fix ++ - IPV6 OOPS'er triggerable by any user ++ - SCTP: Fix sctp_primitive_ABORT() call in sctp_close(). ++ - SPARC64: Fix X server crashes on sparc64 ++ - TG3: Disable TSO by default ++ - dm: mirror sector offset fix ++ - dm: fix block device initialisation ++ - dm: add module ref counting ++ - dm: fix mapped device ref counting ++ - dm: add DMF_FREEING ++ - dm: change minor_lock to spinlock ++ - dm: move idr_pre_get ++ - dm: fix idr minor allocation ++ - dm snapshot: unify chunk_size ++ - Have ext2 reject file handles with bad inode numbers early. ++ - Allow per-route window scale limiting ++ - bridge-netfilter: don't overwrite memory outside of skb ++ - fix compilation error on IA64 ++ - Fix output framentation of paged-skbs ++ - spectrum_cs: Fix firmware uploading errors ++ - TEXTSEARCH: Fix Boyer Moore initialization bug ++ * Add stable release 2.6.17.13: ++ - lib: add idr_replace ++ - pci_ids.h: add some VIA IDE identifiers ++ * Remove patches merged upstream: ++ - s390-kernel-futex-barrier.patch ++ * Unpatch ia64-mman.h-fix.patch ++ ++ -- Bastian Blank Wed, 13 Sep 2006 14:54:14 +0200 ++ ++linux-2.6 (2.6.17-8) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * arm/ixp4xx: Enable CONFIG_W1. ++ ++ [ dann frazier ] ++ * sound-pci-hda-mac-mini-quirks.diff, sound-pci-hda-intel-d965.diff ++ sound-pci-hda-mac-mini-intel945.diff: ++ Updates to patch_sigmatel.c to add x86 mac-mini sound support ++ Thanks to Matt Kraai. (closes: #384972) ++ ++ [ Kyle McMartin ] ++ * hppa: Re-enable pa8800 fixing patches from James Bottomley. ++ Pulled fresh from parisc-linux git tree. ++ * ia64: Pull in compile-failure fix from Christian Cotte-Barrot. ++ Pulled from linux-ia64 mailing list. Fix is correct. ++ * hppa/alpha/mips: Fix compile-failure due to missing arch_mmap_check. Patch sent ++ upstream to stable@kernel.org. ++ ++ [ dann frazier ] ++ * sym2: only claim "Storage" class devices - the cpqarray driver should be ++ used for 5c1510 devices in RAID mode. (closes: #380272) ++ ++ [ Bastian Blank ] ++ * Backport change to allow all hypercalls for xen. ++ ++ -- Bastian Blank Thu, 31 Aug 2006 12:12:51 +0200 ++ ++linux-2.6 (2.6.17-7) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * arm/iop32x: Enable CONFIG_BLK_DEV_OFFBOARD. ++ * arm/iop32x: Unset CONFIG_BLK_DEV_AMD74XX since it fails on ARM ++ with "Unknown symbol pci_get_legacy_ide_irq". ++ * arm/iop32x: Enable a number of MD and DM modules. ++ * arm/iop32x: Enable some more USB network modules. ++ * mipsel/r5k-cobalt: Increase 8250 NR_UARTS and RUNTIME_UARTS to 4. ++ * mipsel/r5k-cobalt: Fix MAC detection problem on Qube 2700. ++ ++ [ Bastian Blank ] ++ * Update vserver patch to 2.0.2-rc29. ++ * Add stable release 2.6.17.10: ++ - Fix possible UDF deadlock and memory corruption (CVE-2006-4145) ++ - elv_unregister: fix possible crash on module unload ++ - Fix sctp privilege elevation (CVE-2006-3745) ++ ++ [ maximilian attems ] ++ * Add RAM range to longclass for -bigmem. (closes: 382799) ++ * Add stable release 2.6.17.9: ++ - powerpc: Clear HID0 attention enable on PPC970 at boot time ++ (CVE-2006-4093) ++ * Add stable release 2.6.17.11: ++ - Fix ipv4 routing locking bug ++ - disable debugging version of write_lock() ++ - PCI: fix ICH6 quirks ++ - 1394: fix for recently added firewire patch that breaks things on ppc ++ - Fix IFLA_ADDRESS handling ++ - Fix BeFS slab corruption ++ - Fix timer race in dst GC code ++ - Have ext3 reject file handles with bad inode numbers early ++ - Kill HASH_HIGHMEM from route cache hash sizing ++ - sys_getppid oopses on debug kernel ++ - IA64: local DoS with corrupted ELFs ++ - tpm: interrupt clear fix ++ - ulog: fix panic on SMP kernels ++ - dm: BUG/OOPS fix ++ - MD: Fix a potential NULL dereference in md/raid1 ++ - ip_tables: fix table locking in ipt_do_table ++ - swsusp: Fix swap_type_of ++ - sky2: phy power problem on 88e805x ++ - ipx: header length validation needed ++ ++ [ Frederik Schüler ] ++ * Activate CONFIG_R8169_VLAN on amd64. (closes: #383707) ++ * Activate EFI boot support on i386. (closes: #381951) ++ ++ [ dann frazier ] ++ * Include module.lds in headers package if it exists. (closes: #342246) ++ * Add Apple MacBook product IDs to usbhid and set ++ CONFIG_USB_HIDINPUT_POWERBOOK=y on i386 and amd64. (closes: #383620) ++ ++ -- Bastian Blank Thu, 24 Aug 2006 15:54:51 +0000 ++ ++linux-2.6 (2.6.17-6) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * debian/arch/i386/defines: Activate 686-bigmem flavour for enterprise ++ usage. ++ * Add ubuntu pci table patch for scsi drivers advansys and fdomain. ++ ++ [ Martin Michlmayr ] ++ * arm/armeb: Use gcc-4.1. ++ * mips/mipsel: Use gcc-4.1. ++ * arm/ixp4xx: Update config based on the NSLU2 config. ++ * arm/s3c2410: Unset CONFIG_DEBUG_INFO. ++ * arm/iop32x: xscale: don't mis-report 80219 as an iop32x ++ * arm/iop32x: Add an MTD map for IOP3xx boards ++ * arm/iop32x: Add support for the Thecus N2100. ++ * arm/iop32x: Add support for the GLAN Tank. ++ * arm/iop32x: Add a flavour for IOP32x based machines. ++ ++ [ Bastian Blank ] ++ * Shrink short descriptions. ++ * Make gcc-4.1 the default compiler. ++ * [powerpc]: Use gcc-4.1. ++ * Move latest and transitional packages to linux-latest-2.6. ++ ++ [ Frederik Schüler ] ++ * [amd64] Add smp-alternatives backport. ++ * [amd64] Drop smp flavours. ++ * [amd64] Merge k8 and p4 flavours into a generic one, following upstreams ++ advice. ++ * Activate BSD_PROCESS_ACCT_V3. ++ * Add stable release 2.6.17.8: ++ - ALSA: Don't reject O_RDWR at opening PCM OSS ++ - Add stable branch to maintainers file ++ - tty serialize flush_to_ldisc ++ - S390: fix futex_atomic_cmpxchg_inatomic ++ - Fix budget-av compile failure ++ - cond_resched() fix ++ - e1000: add forgotten PCI ID for supported device ++ - ext3: avoid triggering ext3_error on bad NFS file handle ++ - ext3 -nobh option causes oops ++ - Fix race related problem when adding items to and svcrpc auth cache. ++ - ieee1394: sbp2: enable auto spin-up for Maxtor disks ++ - invalidate_bdev() speedup ++ - Sparc64 quad-float emulation fix ++ - VLAN state handling fix ++ - Update frag_list in pskb_trim ++ - UHCI: Fix handling of short last packet ++ - sky2: NAPI bug ++ - i2c: Fix 'ignore' module parameter handling in i2c-core ++ - scx200_acb: Fix the block transactions ++ - scx200_acb: Fix the state machine ++ - H.323 helper: fix possible NULL-ptr dereference ++ - Don't allow chmod() on the /proc// files ++ - PCI: fix issues with extended conf space when MMCONFIG disabled because of e820 ++ ++ [ Sven Luther ] ++ * [powerpc] Added console=hvsi0 too to CMDLINE to the powerpc64 flavour, for ++ non-virtualized IBM power machines serial console. ++ ++ -- Bastian Blank Fri, 11 Aug 2006 19:58:06 +0200 ++ ++linux-2.6 (2.6.17-5) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * [arm/nslu2] Enable CONFIG_USB_EHCI_SPLIT_ISO. Closes: #378554 ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.17.7: ++ - BLOCK: Fix bounce limit address check ++ - v4l/dvb: Fix budget-av frontend detection ++ - v4l/dvb: Fix CI on old KNC1 DVBC cards ++ - v4l/dvb: Fix CI interface on PRO KNC1 cards ++ - v4l/dvb: Backport fix to artec USB DVB devices ++ - v4l/dvb: Backport the DISEQC regression fix to 2.6.17.x ++ - v4l/dvb: stradis: dont export MODULE_DEVICE_TABLE ++ - pnp: suppress request_irq() warning ++ - generic_file_buffered_write(): handle zero-length iovec segments ++ - serial 8250: sysrq deadlock fix ++ - Reduce ACPI verbosity on null handle condition ++ - ieee80211: TKIP requires CRC32 ++ - Make powernow-k7 work on SMP kernels. ++ - via-velocity: the link is not correctly detected when the device starts ++ - Add missing UFO initialisations ++ - USB serial ftdi_sio: Prevent userspace DoS (CVE-2006-2936) ++ - cdrom: fix bad cgc.buflen assignment ++ - splice: fix problems with sys_tee() ++ - fix fdset leakage ++ - struct file leakage ++ - XFS: corruption fix ++ - v4l/dvb: Kconfig: fix description and dependencies for saa7115 module ++ - dvb-bt8xx: fix frontend detection for DViCO FusionHDTV DVB-T Lite rev 1.2 ++ - IB/mthca: restore missing PCI registers after reset ++ - v4l/dvb: Backport the budget driver DISEQC instability fix ++ - Fix IPv4/DECnet routing rule dumping ++ - pdflush: handle resume wakeups ++ - x86_64: Fix modular pc speaker ++ - Fix powernow-k8 SMP kernel on UP hardware bug. ++ - ALSA: RME HDSP - fixed proc interface (missing {}) ++ - ALSA: au88x0 - Fix 64bit address of MPU401 MMIO port ++ - ALSA: Fix a deadlock in snd-rtctimer ++ - ALSA: Fix missing array terminators in AD1988 codec support ++ - ALSA: Fix model for HP dc7600 ++ - ALSA: Fix mute switch on VAIO laptops with STAC7661 ++ - ALSA: fix the SND_FM801_TEA575X dependencies ++ - ALSA: Fix undefined (missing) references in ISA MIRO sound driver ++ - ALSA: Fix workaround for AD1988A rev2 codec ++ - ALSA: hda-intel - Fix race in remove ++ - Suppress irq handler mismatch messages in ALSA ISA drivers ++ - PKT_SCHED: Fix illegal memory dereferences when dumping actions ++ - PKT_SCHED: Return ENOENT if action module is unavailable ++ - PKT_SCHED: Fix error handling while dumping actions ++ - generic_file_buffered_write(): deadlock on vectored write ++ - ethtool: oops in ethtool_set_pauseparam() ++ - memory hotplug: solve config broken: undefined reference to `online_page' ++ * Add budget-av-compile-fix.patch stable compile fix. ++ * Enable in all configs setting SND_FM801_TEA575X SND_FM801_TEA575X_BOOL=y. ++ ++ -- Bastian Blank Sat, 29 Jul 2006 13:30:06 +0200 ++ ++linux-2.6 (2.6.17-4) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.17.5: ++ - Fix nasty /proc vulnerability (CVE-2006-3626) ++ * Add stable release 2.6.17.6: ++ - Relax /proc fix a bit ++ * Set section of images to admin. ++ ++ [ dann frazier ] ++ * [ia64] Drop the non-SMP flavours; they are not well maintained upstream. ++ Note that the non-SMP flavours have been identical to the SMP builds ++ since 2.6.13-1; this was to avoid having to drop then re-add these ++ flavours if upstream resolved the issue - but that never happened. ++ Note that this is a measurable performance penalty on non-SMP systems. ++ ++ -- Bastian Blank Mon, 17 Jul 2006 11:08:41 +0200 ++ ++linux-2.6 (2.6.17-3) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.17.2: ++ - ide-io: increase timeout value to allow for slave wakeup ++ - NTFS: Critical bug fix (affects MIPS and possibly others) ++ - Link error when futexes are disabled on 64bit architectures ++ - SCTP: Reset rtt_in_progress for the chunk when processing its sack. ++ - SPARC32: Fix iommu_flush_iotlb end address ++ - ETHTOOL: Fix UFO typo ++ - UML: fix uptime ++ - x86: compile fix for asm-i386/alternatives.h ++ - bcm43xx: init fix for possible Machine Check ++ - SCTP: Fix persistent slowdown in sctp when a gap ack consumes rx buffer. ++ - kbuild: bugfix with initramfs ++ - Input: return correct size when reading modalias attribute ++ - ohci1394: Fix broken suspend/resume in ohci1394 ++ - idr: fix race in idr code ++ - USB: Whiteheat: fix firmware spurious errors ++ - libata: minor patch for ATA_DFLAG_PIO ++ - SCTP: Send only 1 window update SACK per message. ++ - PFKEYV2: Fix inconsistent typing in struct sadb_x_kmprivate. ++ - SCTP: Limit association max_retrans setting in setsockopt. ++ - SCTP: Reject sctp packets with broadcast addresses. ++ - IPV6: Sum real space for RTAs. ++ - IPV6 ADDRCONF: Fix default source address selection without ++ CONFIG_IPV6_PRIVACY ++ - IPV6: Fix source address selection. ++ * Add stable release 2.6.17.3: ++ - NETFILTER: SCTP conntrack: fix crash triggered by packet without chunks ++ [CVE-2006-2934] ++ * Deapply merged sparc32-iotlb.patch. ++ * Fix README.Debian: Correct svn location, remove old boot param bswap ++ reference, the asfs patch is in the Debian kernel. Remove reference to ++ AMD 768 erratum 10, it was solved in 2.6.12. Add wording corrections. ++ * Set CONFIG_SERIAL_8250_RN_UARTS=16 for all archs beside mips/m68k unless ++ explicitly set on a specific value. (closes: 377151) ++ * Add stable release 2.6.17.4: ++ - fix prctl privilege escalation and suid_dumpable (CVE-2006-2451) ++ ++ [ Sven Luther ] ++ * Re-enabled fs-asfs patch. ++ ++ [ Thiemo Seufer ] ++ * [mips,mipsel] Fix sb1 interrupt handlers. ++ * [mips,mipsel] Fix devfs-induced build failure in sb1250 serial driver. ++ * [mips] SGI ip22 RTC was broken, fixed thanks to Julien Blache. ++ * [mips] Fix SGI ip22 serial console, thanks to Julien Blache. ++ ++ [ Martin Michlmayr ] ++ * [arm/nslu2] Enable HFS and some other filesystems. ++ * [arm/nslu2] Unset CONFIG_USB_STORAGE_DEBUG. Closes: #377853. ++ ++ -- Bastian Blank Thu, 13 Jul 2006 13:14:53 +0200 ++ ++linux-2.6 (2.6.17-2) unstable; urgency=low ++ ++ [ Jurij Smakov ] ++ * [sparc] Switch to gcc-4.1 as it produces a working kernel, ++ while gcc-4.0 does not. No ABI bump neccessary, because ++ 2.6.17-1 sparc binaries never made it to the archive. ++ * [sparc32] Add sparc32-iotlb.patch to fix DMA errors on sparc32. ++ ++ [ Sven Luther ] ++ * [powerpc] Added console=hvc0 default commandline option to powerpc64 flavour. ++ * [powerpc] Fixed mkvmlinuz support, which was missing from -1. (Closes: #375645) ++ * [powerpc] Added PowerBook HID support for last-gen PowerBook keyboards. ++ (Closes: #307327) ++ ++ [ Martin Michlmayr ] ++ * [mipsel] Fix compilation error in dz serial driver. ++ * [mipsel] Update configs. ++ * [mipsel] Add a build fix for the Cobalt early console support. ++ * [arm/nslu2] Disable SE Linux support for now so the kernel fits into flash. ++ ++ [ Christian T. Steigies ] ++ * [m68k] Update patches for 2.6.17. ++ * [m68k] Add m68k-as and m68k-macro patch which allow building with current binutils. ++ * [m68k] Disable all subarches but amiga and mac for official linux-images. ++ ++ [ Kyle McMartin ] ++ * [hppa] Update patchset (2.6.17-pa6) from parisc-linux.org. ++ Which fixes relocation errors in modules with 64-bit kernels, and ++ a softlockup on non-SMP flavours with gettimeofday. ++ ++ -- Bastian Blank Thu, 29 Jun 2006 18:49:35 +0200 ++ ++linux-2.6 (2.6.17-1) unstable; urgency=low ++ ++ [ Frederik Schüler ] ++ * New upstream release. ++ * [amd64] Use gcc 4.1. ++ * [amd64] Drop amd64-generic flavor. We will use amd64-k8 for the ++ installer. ++ ++ [ Martin Michlmayr ] ++ * [mips] Update patches for 2.6.17. ++ * [arm] Update configs. ++ * [armeb] Update configs. ++ ++ [ Thiemo Seufer ] ++ * [mips] Fix SWARM FPU detection. ++ * [mips] Update configurations. ++ ++ [ Kyle McMartin ] ++ * [hppa] Set PDC_CHASSIS_WARN to y. ++ * [hppa] Update patchset (2.6.17-pa2) from parisc-linux.org. ++ * [hppa] Change NR_CPUS to 8 from 32 on both SMP flavours. ++ * [hppa] Set PARISC_PAGE_SIZE to 4K on all platforms. ++ ++ [ Bastian Blank ] ++ * [s390] Use gcc 4.1. ++ * [i386] Enable REGPARM. ++ * [i386] Use gcc 4.1. ++ * [powerpc] Disable prep. ++ ++ [ dann frazier ] ++ * [ia64] Update configs ++ * [ia64] Use gcc 4.1. ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.17.1: ++ - xt_sctp: fix endless loop caused by 0 chunk length (CVE-2006-3085) ++ ++ -- Bastian Blank Thu, 22 Jun 2006 12:13:15 +0200 ++ ++linux-2.6 (2.6.16+2.6.17-rc3-0experimental.1) experimental; urgency=low ++ ++ [ Frederik Schüler ] ++ * New upstream release candidate. ++ * Switch HZ from 1000 to 250, following upstreams default. ++ * Activate CONFIG_BCM43XX_DEBUG. ++ ++ [ maximilian attems ] ++ * Disable broken and known unsecure LSM modules: CONFIG_SECURITY_SECLVL, ++ CONFIG_SECURITY_ROOTPLUG. Upstream plans to remove them for 2.6.18 ++ ++ -- Frederik Schüler Sun, 7 May 2006 17:06:29 +0200 ++ ++linux-2.6.16 (2.6.16-18) unstable; urgency=high ++ ++ [ Sven Luther ] ++ * [powerpc] Added console=hvsi0 too to CMDLINE to the powerpc64 flavour, ++ for non-virtualized IBM power machines serial console. ++ ++ [ dann frazier ] ++ * fs-ext3-bad-nfs-handle.patch: avoid triggering ext3_error on bad NFS ++ file handle (CVE-2006-3468) ++ * cdrom-bad-cgc.buflen-assign.patch: fix buffer overflow in dvd_read_bca ++ * usb-serial-ftdi_sio-dos.patch: fix userspace DoS in ftdi_sio driver ++ ++ [ Bastian Blank ] ++ * Update xen patch to changeset 9762. ++ ++ -- Frederik Schüler Fri, 18 Aug 2006 20:29:17 +0200 ++ ++linux-2.6.16 (2.6.16-17) unstable; urgency=high ++ ++ [ Martin Michlmayr ] ++ * Add stable release 2.6.16.22: ++ - powernow-k8 crash workaround ++ - NTFS: Critical bug fix (affects MIPS and possibly others) ++ - JFS: Fix multiple errors in metapage_releasepage ++ - SPARC64: Fix D-cache corruption in mremap ++ - SPARC64: Respect gfp_t argument to dma_alloc_coherent(). ++ - SPARC64: Fix missing fold at end of checksums. ++ - scsi_lib.c: properly count the number of pages in scsi_req_map_sg() ++ - I2O: Bugfixes to get I2O working again ++ - Missed error checking for intent's filp in open_namei(). ++ - tmpfs: time granularity fix for [acm]time going backwards ++ - USB: Whiteheat: fix firmware spurious errors ++ - fs/namei.c: Call to file_permission() under a spinlock in do_lookup_path() ++ * Add stable release 2.6.16.23: ++ - revert PARPORT_SERIAL should depend on SERIAL_8250_PCI patch ++ - NETFILTER: SCTP conntrack: fix crash triggered by packet without ++ chunks (CVE-2006-2934) ++ * Add stable release 2.6.16.24: ++ - fix prctl privilege escalation and suid_dumpable (CVE-2006-2451) ++ * Add stable release 2.6.16.25: ++ - Fix nasty /proc vulnerability (CVE-2006-3626) ++ * Relax /proc fix a bit (Linus Torvalds) ++ ++ * [arm/nslu2] Unset CONFIG_USB_STORAGE_DEBUG. Closes: #377853. ++ * [mips] SGI ip22 RTC was broken, fixed thanks to Julien Blache. ++ * [mips] Fix SGI ip22 serial console, thanks to Julien Blache. ++ ++ [ Bastian Blank ] ++ * Fix vserver patch. ++ ++ -- Bastian Blank Sat, 15 Jul 2006 17:18:49 +0200 ++ ++linux-2.6.16 (2.6.16-16) unstable; urgency=low ++ ++ [ Sven Luther ] ++ * [powerpc] Added console=hvc0 default commandline option to powerpc64 flavour. ++ * [powerpc] Now THERM_PM72 and all WINDFARMs are builtin, for better fan control. ++ ++ [ Martin Michlmayr ] ++ * [arm/nslu2] Disable SE Linux support for now so the kernel fits into ++ flash. Closes: #376926. ++ ++ [ Bastian Blank ] ++ * [powerpc,powerpc-miboot] Enable OpenFirmware device tree support. ++ (closes: #376012) ++ ++ -- Bastian Blank Sat, 8 Jul 2006 17:57:57 +0200 ++ ++linux-2.6.16 (2.6.16-15) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.16.18: ++ - NETFILTER: SNMP NAT: fix memory corruption (CVE-2006-2444) ++ * Add stable release 2.6.16.19: ++ - NETFILTER: Fix small information leak in SO_ORIGINAL_DST (CVE-2006-1343) ++ * Add stable release 2.6.16.20: ++ - x86_64: Don't do syscall exit tracing twice ++ - Altix: correct ioc4 port order ++ - Input: psmouse - fix new device detection logic ++ - PowerMac: force only suspend-to-disk to be valid ++ - the latest consensus libata resume fix ++ - Altix: correct ioc3 port order ++ - Cpuset: might sleep checking zones allowed fix ++ - ohci1394, sbp2: fix "scsi_add_device failed" with PL-3507 based devices ++ - sbp2: backport read_capacity workaround for iPod ++ - sbp2: fix check of return value of hpsb_allocate_and_register_addrspace ++ - x86_64: x86_64 add crashdump trigger points ++ - ipw2200: Filter unsupported channels out in ad-hoc mode ++ * Add stable release 2.6.16.21: ++ - check_process_timers: fix possible lockup ++ - run_posix_cpu_timers: remove a bogus BUG_ON() (CVE-2006-2445) ++ - xt_sctp: fix endless loop caused by 0 chunk length (CVE-2006-3085) ++ - powerpc: Fix machine check problem on 32-bit kernels (CVE-2006-2448) ++ ++ [ Christian T. Steigies ] ++ * [m68k] Add mac via patch from Finn Thain. ++ * [m68k] Enable INPUT_EVDEV. ++ ++ [ Martin Michlmayr ] ++ * [mips/b1-bcm91250a] Enable SMP. ++ * [mips] Add a compile fix for the Maxine fb. ++ * [mipsel] Add a patch that let's you enable serial console on DECstation. ++ * [mipsel] Add a patch to get SCSI working on DECstation. ++ * [mipsel] Handle memory-mapped RTC chips properly. ++ * [mipsel] Add configs for r3k-kn02 and r4k-kn04 DECstation. ++ * [arm] Allow RiscPC machines to boot an initrd (tagged list fix). ++ * [arm/nslu2] Enable many modules. ++ * [arm] Build loop support as a module. ++ * [arm] Use the generic netfilter configuration. ++ * [arm/footbridge] Enable sound. ++ ++ [ Kyle McMartin ] ++ * [hppa] Pulled patch from cvs to fix build of kernel/ptrace.c which needs ++ {read,write}_can_lock. ++ * [hppa] Disable CONFIG_DETECT_SOFTLOCKUP to fix boot on pa8800 machines. ++ ++ [ Sven Luther ] ++ * [powerpc,prep] Added a new ARCH=ppc PReP flavour, currently mostly a copy ++ of the -powerpc one. ++ * Upgraded mkvmlinuz dependency to mkvmlinuz 21. ++ ++ [ Bastian Blank ] ++ * Update vserver patch to 2.0.2-rc21. ++ * Bump build-dependency on kernel-package to 10.049. ++ ++ [ Jurij Smakov ] ++ * Add dcache-memory-corruption.patch to fix the mremap(), occasionally ++ triggered on sparc in the form of dpkg database corruption. Affects ++ sparc64, mips and generic includes. Thanks to David Miller, original ++ patch is included in 2.6.17. ++ Ref: http://marc.theaimsgroup.com/?l=linux-sparc&m=114920963824047&w=2 ++ * Add sparc32-iotlb.patch to fix the DMA errors encountered with latest ++ kernels on sparc32, in particularly HyperSparcs. Thanks to Bob Breuer. ++ Ref: http://marc.theaimsgroup.com/?l=linux-sparc&m=115077649707675&w=2 ++ ++ -- Bastian Blank Wed, 21 Jun 2006 14:09:11 +0200 ++ ++linux-2.6 (2.6.16-14) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.16.16: ++ - fs/locks.c: Fix lease_init (CVE-2006-1860) ++ * Make i386 xen images recommend libc6-xen. ++ * Update vserver patch to 2.0.2-rc20. ++ * Update xen patch to changeset 9687. ++ ++ [ Christian T. Steigies ] ++ * [m68k] Add generic m68k ide fix. ++ * [m68k] Add cross-compile instructions. ++ * [m68k] Enable INPUT_EVDEV for yaird. ++ * [m68k] sun3 general compile and scsi fixes, enable sun3 SCSI again. ++ ++ [ dann frazier ] ++ * cs4281 - Fix the check of timeout in probe to deal with variable HZ. ++ (closes: #361197) ++ ++ [ Norbert Tretkowski ] ++ * [alpha] Readded patch to support prctl syscall, got lost when upgrading ++ to 2.6.16. ++ ++ [ Frederik Schüler ] ++ * Add stable release 2.6.16.17: ++ - SCTP: Validate the parameter length in HB-ACK chunk (CVE-2006-1857) ++ - SCTP: Respect the real chunk length when walking parameters ++ (CVE-2006-1858) ++ - ptrace_attach: fix possible deadlock schenario with irqs ++ - Fix ptrace_attach()/ptrace_traceme()/de_thread() race ++ - page migration: Fix fallback behavior for dirty pages ++ - add migratepage address space op to shmem ++ - Remove cond_resched in gather_stats() ++ - VIA quirk fixup, additional PCI IDs ++ - PCI quirk: VIA IRQ fixup should only run for VIA southbridges ++ - Fix udev device creation ++ - limit request_fn recursion ++ - PCI: correctly allocate return buffers for osc calls ++ - selinux: check for failed kmalloc in security_sid_to_context() ++ - TG3: ethtool always report port is TP. ++ - Netfilter: do_add_counters race, possible oops or info leak ++ (CVE-2006-0039) ++ - scx200_acb: Fix resource name use after free ++ - smbus unhiding kills thermal management ++ - fs/compat.c: fix 'if (a |= b )' typo ++ - smbfs: Fix slab corruption in samba error path ++ - fs/locks.c: Fix sys_flock() race ++ - USB: ub oops in block_uevent ++ - via-rhine: zero pad short packets on Rhine I ethernet cards ++ - md: Avoid oops when attempting to fix read errors on raid10 ++ ++ -- Bastian Blank Mon, 22 May 2006 14:56:11 +0200 ++ ++linux-2.6 (2.6.16-13) unstable; urgency=low ++ ++ [ Frederik Schüler ] ++ * Add stable release 2.6.16.14: ++ - smbfs chroot issue (CVE-2006-1864) ++ ++ [ Bastian Blank ] ++ * Don't make headers packages depend on images. ++ * Bump abiname to 2. (closes: #366291) ++ * Update vserver patch to 2.0.2-rc19. ++ * Update xen patch to changeset 9668. ++ * Remove abi fixes. ++ * Add stable release 2.6.16.15: ++ - SCTP: Allow spillover of receive buffer to avoid deadlock. (CVE-2006-2275) ++ - SCTP: Fix panic's when receiving fragmented SCTP control chunks. (CVE-2006-2272) ++ - SCTP: Fix state table entries for chunks received in CLOSED state. (CVE-2006-2271) ++ - SCTP: Prevent possible infinite recursion with multiple bundled DATA. (CVE-2006-2274) ++ * Switch HZ from 1000 to 250. ++ ++ [ Christian T. Steigies ] ++ * [m68k] Add patches that allow building images for atari ++ * [m68k] Enable atyfb driver for atari ++ ++ -- Bastian Blank Wed, 10 May 2006 18:58:44 +0200 ++ ++linux-2.6 (2.6.16-12) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.16.12: ++ - dm snapshot: fix kcopyd destructor ++ - x86_64: Pass -32 to the assembler when compiling the 32bit vsyscall pages ++ - for_each_possible_cpu ++ - Simplify proc/devices and fix early termination regression ++ - sonypi: correct detection of new ICH7-based laptops ++ - MIPS: Fix tx49_blast_icache32_page_indexed. ++ - NET: e1000: Update truesize with the length of the packet for packet split ++ - i386: fix broken FP exception handling ++ - tipar oops fix ++ - USB: fix array overrun in drivers/usb/serial/option.c ++ - Altix snsc: duplicate kobject fix ++ - Alpha: strncpy() fix ++ - LSM: add missing hook to do_compat_readv_writev() ++ - Fix reiserfs deadlock ++ - make vm86 call audit_syscall_exit ++ - fix saa7129 support in saa7127 module for pvr350 tv out ++ - dm flush queue EINTR ++ - get_dvb_firmware: download nxt2002 firmware from new driver location ++ - cxusb-bluebird: bug-fix: power down corrupts frontend ++ - x86_64: Fix a race in the free_iommu path. ++ - MIPS: Use "R" constraint for cache_op. ++ - MIPS: R2 build fixes for gcc < 3.4. ++ - cs5535_gpio.c: call cdev_del() during module_exit to unmap kobject references and other cleanups ++ - MIPS: Fix branch emulation for floating-point exceptions. ++ - x86/PAE: Fix pte_clear for the >4GB RAM case ++ * Add stable release 2.6.16.13: ++ - NETFILTER: SCTP conntrack: fix infinite loop (CVE-2006-1527) ++ * Remove merged patches. ++ * Rediff xen patch. ++ * Bump build-dependency on kernel-package to 10.047. ++ ++ [ Martin Michlmayr ] ++ * [arm] Enable cramfs for ixp4xx and rpc. ++ ++ -- Bastian Blank Thu, 4 May 2006 11:37:26 +0200 ++ ++linux-2.6 (2.6.16-11) unstable; urgency=low ++ ++ * Update vserver patch to 2.0.2-rc18. ++ - Limit ccaps to root inside a guest (CVE-2006-2110) ++ * Conflict with known broken grub versions. (closes: #361308) ++ * Enable s390 vserver image. ++ * Enable xen and xen-vserver images. ++ * Use localversion for kernel-package images. (closes: #365505) ++ ++ -- Bastian Blank Mon, 1 May 2006 16:38:45 +0200 ++ ++linux-2.6 (2.6.16-10) unstable; urgency=low ++ ++ [ Norbert Tretkowski ] ++ * [alpha] Added backport of for_each_possible_cpu() to fix alpha build. ++ (closes: #364206) ++ * Add stable release 2.6.16.10: ++ - IPC: access to unmapped vmalloc area in grow_ary() ++ - Add more prevent_tail_call() ++ - alim15x3: ULI M-1573 south Bridge support ++ - apm: fix Armada laptops again ++ - fbdev: Fix return error of fb_write ++ - Fix file lookup without ref ++ - m41t00: fix bitmasks when writing to chip ++ - Open IPMI BT overflow ++ - x86: be careful about tailcall breakage for sys_open[at] too ++ - x86: don't allow tail-calls in sys_ftruncate[64]() ++ - IPV6: XFRM: Fix decoding session with preceding extension header(s). ++ - IPV6: XFRM: Don't use old copy of pointer after pskb_may_pull(). ++ - IPV6: Ensure to have hop-by-hop options in our header of &sk_buff. ++ - selinux: Fix MLS compatibility off-by-one bug ++ - PPC: fix oops in alsa powermac driver ++ - MTD_NAND_SHARPSL and MTD_NAND_NANDSIM should be tristate's ++ - i2c-i801: Fix resume when PEC is used ++ - Fix hotplug race during device registration ++ - Fix truesize underflow ++ - efficeon-agp: Add missing memory mask ++ - 3ware 9000 disable local irqs during kmap_atomic ++ - 3ware: kmap_atomic() fix ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.16.11: ++ - Don't allow a backslash in a path component (CVE-2006-1863) ++ ++ -- Bastian Blank Tue, 25 Apr 2006 13:56:19 +0200 ++ ++linux-2.6 (2.6.16-9) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.16.8: ++ - ip_route_input panic fix (CVE-2006-1525) ++ * Add stable release 2.6.16.9: ++ - i386/x86-64: Fix x87 information leak between processes (CVE-2006-1056) ++ ++ [ Bastian Blank ] ++ * Update vserver patch to 2.0.2-rc17. ++ ++ -- Bastian Blank Thu, 20 Apr 2006 15:37:28 +0200 ++ ++linux-2.6 (2.6.16-8) unstable; urgency=low ++ ++ * Fix ABI-breakage introduced in -7. (closes: #363032) ++ * Add stable release 2.6.16.6: ++ - ext3: Fix missed mutex unlock ++ - RLIMIT_CPU: fix handling of a zero limit ++ - alpha: SMP boot fixes ++ - m32r: security fix of {get, put}_user macros ++ - m32r: Fix cpu_possible_map and cpu_present_map initialization for SMP kernel ++ - shmat: stop mprotect from giving write permission to a readonly attachment (CVE-2006-1524) ++ - powerpc: fix incorrect SA_ONSTACK behaviour for 64-bit processes ++ - MPBL0010 driver sysfs permissions wide open ++ - cciss: bug fix for crash when running hpacucli ++ - fuse: fix oops in fuse_send_readpages() ++ - Fix utime(2) in the case that no times parameter was passed in. ++ - Fix buddy list race that could lead to page lru list corruptions ++ - NETFILTER: Fix fragmentation issues with bridge netfilter ++ - USB: remove __init from usb_console_setup ++ - Fix suspend with traced tasks ++ - isd200: limit to BLK_DEV_IDE ++ - edac_752x needs CONFIG_HOTPLUG ++ - fix non-leader exec under ptrace ++ - sky2: bad memory reference on dual port cards ++ - atm: clip causes unregister hang ++ - powerpc: iSeries needs slb_initialize to be called ++ - Fix block device symlink name ++ - Incorrect signature sent on SMB Read ++ * Add stable release 2.6.16.7: ++ - fix MADV_REMOVE vulnerability (CVE-2006-1524 for real this time) ++ ++ -- Bastian Blank Tue, 18 Apr 2006 16:22:31 +0200 ++ ++linux-2.6 (2.6.16-7) unstable; urgency=low ++ ++ [ Frederik Schüler ] ++ * Add stable release 2.6.16.3: ++ - Keys: Fix oops when adding key to non-keyring (CVE-2006-1522) ++ ++ [ Bastian Blank ] ++ * Add stable release 2.6.16.4: ++ - RCU signal handling (CVE-2006-1523) ++ ++ [ Sven Luther ] ++ * [powerpc] Transitioned mkvmlinuz support patch to the 2.6.16 ARCH=powerpc ++ tree. PReP is broken in 2.6.16 though. ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.16.5: ++ - x86_64: Clean up execve ++ - x86_64: When user could have changed RIP always force IRET (CVE-2006-0744) ++ * Disable CONFIG_SECCOMP (adds useless overhead on context-switch) - ++ thanks to fs for checking abi. ++ ++ [ Christian T. Steigies ] ++ * [m68k] update m68k patch and config to 2.6.16, temporarily disable atari ++ ++ -- Bastian Blank Sat, 15 Apr 2006 13:56:05 +0200 ++ ++linux-2.6 (2.6.16-6) unstable; urgency=medium ++ ++ [ Bastian Blank ] ++ * Provide version infos in support package and don't longer rely on the ++ changelog. ++ * [amd64/i386] Enable cpu hotplug support. ++ ++ [ maximilian attems ] ++ * Add stable release 2.6.16.2: ++ - PCMCIA_SPECTRUM must select FW_LOADER ++ - drivers/net/wireless/ipw2200.c: fix an array overun ++ - AIRO{,_CS} <-> CRYPTO fixes ++ - tlclk: fix handling of device major ++ - fbcon: Fix big-endian bogosity in slow_imageblit() ++ - Fix NULL pointer dereference in node_read_numastat() ++ - USB: EHCI full speed ISO bugfixes ++ - Mark longhaul driver as broken. ++ - fib_trie.c node freeing fix ++ - USB: Fix irda-usb use after use ++ - sysfs: zero terminate sysfs write buffers (CVE-2006-1055) ++ - USB: usbcore: usb_set_configuration oops (NULL ptr dereference) ++ - pcmcia: permit single-character-identifiers ++ - hostap: Fix EAPOL frame encryption ++ - wrong error path in dup_fd() leading to oopses in RCU ++ - {ip, nf}_conntrack_netlink: fix expectation notifier unregistration ++ - isicom must select FW_LOADER ++ - knfsd: Correct reserved reply space for read requests. ++ - Fix module refcount leak in __set_personality() ++ - sbp2: fix spinlock recursion ++ - powerpc: make ISA floppies work again ++ - opti9x - Fix compile without CONFIG_PNP ++ - Add default entry for CTL Travel Master U553W ++ - Fix the p4-clockmod N60 errata workaround. ++ - kdump proc vmcore size oveflow fix ++ ++ -- Bastian Blank Mon, 10 Apr 2006 16:09:51 +0200 ++ ++linux-2.6 (2.6.16-5) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Provide real dependency packages for module building. ++ - Add linux-headers-$version-$abiname-all and ++ linux-headers-$version-$abiname-all-$arch. ++ * Rename support package to linux-support-$version-$abiname. ++ * Fix module package output. ++ * Include .kernelrelease in headers packages. (closes: #359813) ++ * Disable Cumana partition support completely. (closes: #359207) ++ * Update vserver patch to 2.0.2-rc15. ++ ++ [ dann frazier ] ++ * [ia64] initramfs-tools works now, no longer restrict initramfs-generators ++ ++ -- Bastian Blank Mon, 3 Apr 2006 14:00:08 +0200 ++ ++linux-2.6 (2.6.16-4) unstable; urgency=medium ++ ++ [ Martin Michlmayr ] ++ * [arm/armeb] Update nslu2 config. ++ * Add stable release 2.6.16.1: ++ - Fix speedstep-smi assembly bug in speedstep_smi_ownership ++ - DMI: fix DMI onboard device discovery ++ - cciss: fix use-after-free in cciss_init_one ++ - DM: Fix bug: BIO_RW_BARRIER requests to md/raid1 hang. ++ - fix scheduler deadlock ++ - proc: fix duplicate line in /proc/devices ++ - rtc.h broke strace(1) builds ++ - dm: bio split bvec fix ++ - v9fs: assign dentry ops to negative dentries ++ - i810fb_cursor(): use GFP_ATOMIC ++ - NET: Ensure device name passed to SO_BINDTODEVICE is NULL terminated. ++ - XFS writeout fix ++ - sysfs: fix a kobject leak in sysfs_add_link on the error path ++ - get_cpu_sysdev() signedness fix ++ - firmware: fix BUG: in fw_realloc_buffer ++ - sysfs: sysfs_remove_dir() needs to invalidate the dentry ++ - TCP: Do not use inet->id of global tcp_socket when sending RST (CVE-2006-1242) ++ - 2.6.xx: sata_mv: another critical fix ++ - Kconfig: VIDEO_DECODER must select FW_LOADER ++ - V4L/DVB (3324): Fix Samsung tuner frequency ranges ++ - sata_mv: fix irq port status usage ++ ++ -- Bastian Blank Tue, 28 Mar 2006 17:19:10 +0200 ++ ++linux-2.6 (2.6.16-3) unstable; urgency=low ++ ++ [ Frederik Schüler ] ++ * [amd64] Add asm-i386 to the linux-headers packages. ++ ++ [ Jonas Smedegaard ] ++ * Tighten yaird dependency to at least 0.0.12-8 (supporting Linux ++ 2.6.16 uppercase hex in Kconfig and new IDE sysfs naming, and VIA ++ IDE on powerpc). ++ ++ [ Martin Michlmayr ] ++ * [arm/armeb] Enable CONFIG_NFSD on NSLU2 again. Closes: #358709. ++ * [arm/footbridge] CONFIG_NE2K_PCI should be a module, not built-in. ++ * [arm/footbridge] Enable CONFIG_BLK_DEV_IDECD=m since the CATS can ++ have a CD-ROM drive. ++ * [mips/sb1*] Use ttyS rather than duart as the name for the serial ++ console since the latter causes problems with debian-installer. ++ ++ [ Bastian Blank ] ++ * Update vserver patch to 2.0.2-rc14. ++ - Fix sendfile. (closes: #358391, #358752) ++ ++ -- Bastian Blank Mon, 27 Mar 2006 16:08:20 +0200 ++ ++linux-2.6 (2.6.16-2) unstable; urgency=low ++ ++ [ dann frazier ] ++ * [ia64] Set unconfigured options: ++ CONFIG_PNP_DEBUG=n and CONFIG_NET_SB1000=m ++ * [hppa] Update config for 2.6.16 ++ ++ [ Martin Michlmayr ] ++ * [mips/mipsel] Put something in the generic config file because diff ++ will otherwise remove the empty file, causing the build to fail. ++ * [mipsel/r5k-cobalt] Set CONFIG_PACKET=y. ++ * [arm] Set CONFIG_MACLIST=y for ixp4xx because nas100d needs it. ++ ++ [ Frederik Schüler ] ++ * Add Maximilian Attems to uploaders list. ++ ++ -- Martin Michlmayr Wed, 22 Mar 2006 15:15:14 +0000 ++ ++linux-2.6 (2.6.16-1) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * New upstream release. ++ * Default to initramfs-tools 0.55 or higher on s390. ++ ++ [ maximilian attems ] ++ * Default to initramfs-tools on arm and armeb. ++ ++ [ Martin Michlmayr ] ++ * [mips/mipsel] Add an image for the Broadcom BCM91480B evaluation board ++ (aka "BigSur"). ++ * [arm, armeb] Enable the netconsole module. ++ * [mipsel/cobalt] Enable the netconsole module. ++ * [mips] SB1: Fix interrupt disable hazard (Ralf Baechle). ++ * [mips] SB1: Support for 1480 ethernet (Broadcom). ++ * [mips] SB1: Support for NAPI (Tom Rix). ++ * [mips] SB1: DUART support (Broadcom). ++ * [mips] Work around bad code generation for (Ralf Baechle). ++ * [mips] Fix VINO drivers when using a 64-bit kernel (Mikael Nousiainen). ++ * [arm/armeb] Update configs for 2.6.16. ++ * [mips/mipsel] Update configs for 2.6.16. ++ * [arm/armeb] Enable the SMB module on NSLU2. ++ * [mipsel] Enable parallel port modules for Cobalt since there are PCI ++ cards that can be used in a Qube. ++ * [mipsel] Enable the JFS module on Cobalt. ++ ++ [ dann frazier ] ++ * [ia64] use yaird on ia64 until #357414 is fixed ++ * [ia64] Update configs for 2.6.16 ++ ++ -- Bastian Blank Tue, 21 Mar 2006 16:12:16 +0100 ++ ++linux-2.6 (2.6.15+2.6.16-rc5-0experimental.1) experimental; urgency=low ++ ++ [ Frederik Schüler ] ++ * New upstream release candidate. ++ ++ [ Martin Michlmayr ] ++ * Add initial mips/mipsel 2.6 kernels. ++ * Important changes compared to the 2.4 kernels: ++ - Drop the XXS1500 flavour since there's little interest in it. ++ - Drop the LASAT flavour since these machines never went into ++ production. ++ - Drop the IP22 R5K (Indy, Indigo2) flavour since the IP22 R4K ++ image now also works on machines with a R5K CPU. ++ - Add an image for SGI IP32 (O2). ++ - Rename the sb1-swarm-bn flavour to sb1-bcm91250a. ++ - Enable PCI network (and other) modules on Cobalt. Closes: #315895. ++ * Add various MIPS related patches: ++ - Fix iomap compilation on machines without COW. ++ - Improve gettimeofday on MIPS. ++ - Fix an oops on IP22 zerilog (serial console). ++ - Improve IDE probing so it won't take so long on Cobalt. ++ - Probe for IDE disks on SWARM. ++ - Test whether there's a scache (fixes Cobalt crash). ++ - Add Tulip fixes for Cobalt. ++ * Fix a typo in the description of the linux-doc-* package, ++ thanks Justin Pryzby. Closes: #343424. ++ * [arm] Enable nfs and nfsd modules. ++ * [arm/footbride] Suggest nwutil (Netwinder utilities). ++ ++ -- Frederik Schüler Thu, 9 Mar 2006 14:13:17 +0000 ++ ++linux-2.6 (2.6.15+2.6.16-rc4-0experimental.1) experimental; urgency=low ++ ++ [ Frederik Schüler ] ++ * New upstream release. ++ * Activate CONFIG_DVB_AV7110_OSD on alpha amd64 and ia64. ++ Closes: #353292 ++ * Globally enable NAPI on all network card drivers which support it. ++ ++ [ maximilian attems ] ++ * Drop fdutils from i386 and amd64 Suggests. ++ * Swap lilo and grub Suggests for i386 and amd64. ++ ++ [ Jurij Smakov ] ++ * Make sure that LOCALVERSION environment variable is not ++ passed to a shell while invoking make-kpkg, since it ++ appends it to the version string, breaking the build. ++ Closes: #349472 ++ * [sparc32] Re-enable the building of sparc32 images. ++ * [sparc64] Re-add (partial) sparc64-atyf-xl-gr.patch, since it ++ was only partially applied upstream, so the problem (garbled ++ screen output on SunBlade 100) is still present. Thanks to ++ Luis Ortiz for pointing it out. ++ * Bump the build-dep on kernel-package to 10.035, which fixes ++ the problem with building documentation packages. ++ ++ [ Martin Michlmayr ] ++ * [sparc] Add sys_newfstatat -> sys_fstatat64 fix from git. ++ * [arm] Update configs for 2.6.16-rc3. ++ * [armeb] Update configs for 2.6.16-rc3. ++ * [arm/armeb] Fix compilation error on NSLU2 due to recent flash ++ changes. ++ * [arm/armeb] Fix a compilation error in the IXP4xx beeper support ++ (Alessandro Zummo). ++ ++ [ Norbert Tretkowski ] ++ * [alpha] Update arch/alpha/config* for 2.6.16-rc3. ++ ++ -- Bastian Blank Fri, 24 Feb 2006 16:02:11 +0000 ++ ++linux-2.6 (2.6.15-8) unstable; urgency=high ++ ++ [ maximilian attems ] ++ * Add stable Release 2.6.15.5: ++ - Fix deadlock in br_stp_disable_bridge ++ - Fix a severe bug ++ - i386: Move phys_proc_id/early intel workaround to correct function ++ - ramfs: update dir mtime and ctime ++ - sys_mbind sanity checking ++ - Fix s390 build failure. ++ - Revert skb_copy_datagram_iovec() recursion elimination. ++ - s390: add #ifdef __KERNEL__ to asm-s390/setup.h ++ - netfilter missing symbol has_bridge_parent ++ - hugetlbfs mmap ENOMEM failure ++ - IB/mthca: max_inline_data handling tweaks ++ - it87: Fix oops on removal ++ - hwmon it87: Probe i2c 0x2d only ++ - reiserfs: disable automatic enabling of reiserfs inode attributes ++ - Fix snd-usb-audio in 32-bit compat environment ++ - dm: missing bdput/thaw_bdev at removal ++ - dm: free minor after unlink gendisk ++ - gbefb: IP32 gbefb depth change fix ++ - shmdt cannot detach not-alined shm segment cleanly. ++ - Address autoconfiguration does not work after device down/up cycle ++ - gbefb: Set default of FB_GBE_MEM to 4 MB ++ - XFS ftruncate() bug could expose stale data (CVE-2006-0554) ++ - sys_signal: initialize ->sa_mask ++ - do_sigaction: cleanup ->sa_mask manipulation ++ - fix zap_thread's ptrace related problems ++ - fix deadlock in ext2 ++ - cfi: init wait queue in chip struct ++ - sd: fix memory corruption with broken mode page headers ++ - sbp2: fix another deadlock after disconnection ++ - skge: speed setting ++ - skge: fix NAPI/irq race ++ - skge: genesis phy initialization fix ++ - skge: fix SMP race ++ - x86_64: Check for bad elf entry address (CVE-2006-0741) ++ - alsa: fix bogus snd_device_free() in opl3-oss.c ++ - ppc32: Put cache flush routines back into .relocate_code section ++ - sys32_signal() forgets to initialize ->sa_mask ++ - Normal user can panic NFS client with direct I/O (CVE-2006-0555) ++ * Deactivate merged duplicates: s390-klibc-buildfix.patch, ++ powerpc-relocate_code.patch. ++ * Add stable Release 2.6.15.6: ++ - Don't reset rskq_defer_accept in reqsk_queue_alloc ++ - fs/nfs/direct.c compile fix ++ - mempolicy.c compile fix, make sure BITS_PER_BYTE is defined ++ - [IA64] die_if_kernel() can return (CVE-2006-0742) ++ ++ [ Sven Luther ] ++ * [powerpc] Disabled CONFIG_IEEE1394_SBP2_PHYS_DMA, which was broken on ++ powerpc64, as it used the long deprecated bus_to_virt symbol. ++ (Closes: #330225) ++ * [powerpc] Fixed gettimeofday breakage causing clock drift. ++ ++ -- Bastian Blank Mon, 6 Mar 2006 11:06:28 +0100 ++ ++linux-2.6 (2.6.15-7) unstable; urgency=low ++ ++ [ Norbert Tretkowski ] ++ * [alpha] Disabled CONFIG_ALPHA_LEGACY_START_ADDRESS for -alpha-generic and ++ -alpha-smp flavours, and introduced a new -alpha-legacy flavour for MILO ++ based machines, which has CONFIG_ALPHA_LEGACY_START_ADDRESS enabled. ++ (closes: #352186) ++ * [alpha] Added new patch to support prctl syscall. (closes: #349765) ++ * [i386] Renamed kernel-image-2.6-486 to kernel-image-2.6-386, it's meant for ++ transition only, and kernel-image-2.6-386 is the package name in sarge. ++ ++ [ Jurij Smakov ] ++ * Bump build-dependency on kernel-package to 10.035, which is fixed ++ to build the documentation packages again. ++ Closes: #352000, #348332 ++ ++ [ Frederik Schüler ] ++ * Activate CONFIG_DVB_AV7110_OSD on alpha amd64 and ia64. ++ Closes: #353292 ++ * Deactivate CONFIG_FB_ATY_XL_INIT on all architectures: it is broken and ++ already removed in 2.6.16-rc. ++ Closes: #353310 ++ ++ [ Christian T. Steigies ] ++ * [m68k] build in cirrusfb driver ++ ++ -- Bastian Blank Tue, 21 Feb 2006 17:35:21 +0000 ++ ++linux-2.6 (2.6.15-6) unstable; urgency=low ++ ++ [ Bastian Blank ] ++ * Moved the mkvmlinuz support patch modification to a -1 version of the ++ patch. ++ ++ [ maximilian attems ] ++ * Add stable treee 2.6.15.4 ++ - PCMCIA=m, HOSTAP_CS=y is not a legal configuration ++ - Input: iforce - do not return ENOMEM upon successful allocation ++ - x86_64: Let impossible CPUs point to reference per cpu data ++ - x86_64: Clear more state when ignoring empty node in SRAT parsing ++ - x86_64: Dont record local apic ids when they are disabled in MADT ++ - Fix keyctl usage of strnlen_user() ++ - Kill compat_sys_clock_settime sign extension stub. ++ - Input: grip - fix crash when accessing device ++ - Input: db9 - fix possible crash with Saturn gamepads ++ - Input: iforce - fix detection of USB devices ++ - Fixed hardware RX checksum handling ++ - SCSI: turn off ordered flush barriers ++ - Input: mousedev - fix memory leak ++ - seclvl settime fix ++ - fix regression in xfs_buf_rele ++ - md: remove slashes from disk names when creation dev names in sysfs ++ - d_instantiate_unique / NFS inode leakage ++ - dm-crypt: zero key before freeing it ++ - bridge: netfilter races on device removal ++ - bridge: fix RCU race on device removal ++ - SELinux: fix size-128 slab leak ++ - __cmpxchg() must really always be inlined ++ - emu10k1 - Fix the confliction of 'Front' control ++ - Input: sidewinder - fix an oops ++ * Deactivate merged alpha-cmpxchg-inline.patch, sparc64-clock-settime.patch. ++ ++ [ Christian T. Steigies ] ++ * [m68k] Add fix for m68k/buddha IDE and m68k/mac SCSI driver ++ * [m68k] Patch by Peter Krummrich to stop flickering pixels with PicassoII ++ * [m68k] make Amiga keyboard usable again, patch by Roman Zippel ++ * [m68k] prevent wd33c93 SCSI driver from crashing the kernel, patch by Roman Zippel ++ * [m68k] remove SBCs from VME descriptions (closes: #351924) ++ ++ -- Frederik Schüler Fri, 10 Feb 2006 15:33:21 +0000 ++ ++linux-2.6 (2.6.15-5) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * Add a fix for the input support for the ixp4xx beeper driver from ++ 2.6.16-rc2. ++ * Add stable tree 2.6.15.3: ++ - Fix extra dst release when ip_options_echo fails (CVE-2006-0454) ++ ++ [ Sven Luther ] ++ * [powerpc] Removed -o root -g root option to mkvmlinuz support patch. ++ (Closes: #351412) ++ ++ -- Sven Luther Tue, 7 Feb 2006 19:23:14 +0000 ++ ++linux-2.6 (2.6.15-4) unstable; urgency=low ++ ++ [ Jurij Smakov ] ++ * [sparc64] Add sparc64-clock-settime.patch to fix the incorrect ++ handling of the clock_settime syscall arguments, which resulted ++ in a hang when trying to set the date using 'date -s'. Patch ++ by David Miller is applied upstream. Thanks to Ludovic Courtes ++ and Frans Pop for reporting and testing. ++ Ref: http://marc.theaimsgroup.com/?t=113861017400002&r=1&w=2 ++ ++ [ Christian T. Steigies ] ++ * [m68k] update m68k patch and config to 2.6.15 ++ * [m68k] SCSI drivers need to be built in until ramdisk generator tools ++ supports loading scsi modules ++ * [m68k] ISCSI and IDE-TAPE don't compile, disabled ++ * [m68k] set CC_OPTIMIZE_FOR_SIZE=n ++ * [m68k] added vmeints patch which fixes building for vme ++ ++ [ maximilian attems ] ++ * Use initramfs-tools for ia64 - fixed klibc. ++ * Add stable tree 2.6.15.2: ++ - Fix double decrement of mqueue_mnt->mnt_count in sys_mq_open ++ - (CVE-2005-3356) ++ - Mask off GFP flags before swiotlb_alloc_coherent ++ - usb-audio: don't use empty packets at start of playback ++ - Make second arg to skb_reserved() signed. ++ - Input: HID - fix an oops in PID initialization code ++ - Fix oops in ufs_fill_super at mount time ++ - Kill blk_attempt_remerge() ++ - Fix i2o_scsi oops on abort ++ - Fix mkiss locking bug ++ - Fix timekeeping on sparc64 ultra-IIe machines ++ - Someone broke reiserfs v3 mount options and this fixes it ++ * Deactivate sparc64-jumping-time.patch, amd64-pppd-fix.patch incl in aboves. ++ * Add s390-klibc-buildfix.patch, regression due to header file changes. ++ ++ [ Steve Langasek ] ++ * [alpha] set __attribute__((always_inline)) on __cmpxchg(), to avoid ++ wrong optimizations with -Os (Closes: #347556). ++ ++ [ Martin Michlmayr ] ++ * Add input support for the ixp4xx beeper driver (Alessandro Zummo). ++ * [arm] Add NSLU2 specific portion of ixp4xx beeper driver (Alessandro Zummo). ++ * [arm/nslu2] Build PPP as a module. ++ * [arm/nslu2] Enable wireless. ++ * [arm/nslu2] Enable most USB modules. ++ * [arm/nslu2] Enable ALSA and USB sound modules. ++ * [arm/nslu2] Set 4 MB as the size of the initrd in the kernel cmd line. ++ * [arm/footbridge] Set CONFIG_BLK_DEV_RAM_SIZE to 8192. ++ * [armeb] Add support for big-endian ARM. ++ * [armeb/nslu2] Use the nslu2 config from arm. ++ ++ [ Frederik Schüler ] ++ * [amd64] Add amd64-pppd-fix.patch to fix kernel panic when using pppd. ++ (Closes: #347711) ++ * Add 64bit-vidiocswin-ioctl-fix.patch to fix VIDIOCSWIN ioctl on 64bit ++ kernel 32bit userland setups. (Closes: #349338) ++ ++ [ Sven Luther ] ++ * [powerpc] Adapted apus config file to be more modular and in sync with the ++ other powerpc configs. Scsi drivers are disabled as they don't build ++ cleanly though (need some esp stuff). ++ * [powerpc] Default to initramfs-tools as initramfs generator, as klibc ++ build is fixed now. ++ ++ [ Bastian Blank ] ++ * [powerpc] Fix dependencies of image packages. ++ ++ -- maximilian attems Wed, 1 Feb 2006 11:34:20 +0100 ++ ++linux-2.6 (2.6.15-3) unstable; urgency=low ++ ++ [ Martin Michlmayr ] ++ * [arm] Update configs for 2.6.15; closes: #347998. ++ * [arm] Activate tmpfs. ++ * [arm] Allow modules to be unloaded. ++ * [arm] Enable CONFIG_INPUT_EVDEV since yaird needs this module in ++ order to generate initrds. ++ * [arm/footbridge] Activate IDEPCI so SL82C105 will really be ++ compiled in. ++ * [arm/footbridge] Activate the right network drivers (Tulip and ++ NE2K). ++ * [arm/footbridge] Enable more framebuffer drivers. ++ * debian/patches/arm-fix-dc21285.patch: Fix compilation of DC21285 ++ flash driver. ++ * [arm/footbridge] Enable MTD and the DC21285 flash driver. ++ * [arm/footbridge] Enable RAID and LVM modules. ++ * [arm/footbridge] Enable USB modules. ++ * [arm/nslu2] Add an image for Network Storage Link for USB 2.0 Disk ++ Drives. ++ * debian/patches/arm-memory-h-page-shift.patch: Fix error "PAGE_SHIFT ++ undeclared" (Rod Whitby). ++ * debian/patches/mtdpart-redboot-fis-byteswap.patch: recognise a foreign ++ endian RedBoot partition table (John Bowler). ++ * debian/patches/maclist.patch: Add support for the maclist interface ++ (John Bowler). ++ * debian/patches/arm-nslu2-maclist.patch: Add NSLU2 maclist support ++ (John Bowler). ++ * [arm/nslu2] Activate maclist. ++ ++ [ maximilian attems ] ++ * Add stable tree 2.6.15.1: ++ - arch/sparc64/Kconfig: fix HUGETLB_PAGE_SIZE_64K dependencies ++ - moxa serial: add proper capability check ++ - fix /sys/class/net//wireless without dev->get_wireless_stats ++ - Don't match tcp/udp source/destination port for IP fragments ++ - Fix sys_fstat64() entry in 64-bit syscall table. ++ - UFS: inode->i_sem is not released in error path ++ - netlink oops fix due to incorrect error code ++ - Fix onboard video on SPARC Blade 100 for 2.6.{13,14,15} ++ - Fix DoS in netlink_rcv_skb() (CVE-2006-0035) ++ - fix workqueue oops during cpu offline ++ - Fix crash in ip_nat_pptp (CVE-2006-0036) ++ - Fix another crash in ip_nat_pptp (CVE-2006-0037) ++ - ppc32: Re-add embed_config.c to ml300/ep405 ++ - Fix ptrace/strace ++ - vgacon: fix doublescan mode ++ - BRIDGE: Fix faulty check in br_stp_recalculate_bridge_id() ++ - skge: handle out of memory on ring changes ++ * Drop merged patch: ++ - sparc64-atyfb-xl-gr-final.patch ++ ++ [ Simon Horman ] ++ * Fix booting on PReP machines ++ (Closes: #348040) ++ powerpc-relocate_code.patch ++ ++ -- Simon Horman Tue, 17 Jan 2006 18:01:17 +0900 ++ ++linux-2.6 (2.6.15-2) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * Default to initramfs-tools as initramfs generator for amd64, hppa, i386, ++ alpha and sparc. More archs will be added once klibc matures. ++ (Closes: #346141, #343147, #341524, #346305) ++ * Backport alsa patch for opl3 - Fix the unreleased resources. ++ (Closes: #346273) ++ * Readd buslogic-pci-id-table.patch. ++ ++ [ dann frazier ] ++ * [ia64] Update config for 2.6.15. ++ ++ [ Frederik Schüler ] ++ * Make CONFIG_IPW2100 a per-architecture option and deactivate it on all ++ architectures but i386. (Closes: #344515) ++ ++ [ Sven Luther ] ++ * Removed spurious file from powerpc-apus patch. (Closes: #346159) ++ ++ [ Norbert Tretkowski ] ++ * Backport the generic irq framework for alpha. (closes: #339080) ++ ++ [ Bastian Blank ] ++ * Remove pre-sarge conflict with hotplug. ++ * Fix hppa diff to apply. ++ * Make the latest packages depend on the corect version of the real images. ++ (closes: #346366) ++ ++ -- Bastian Blank Tue, 10 Jan 2006 16:54:21 +0100 ++ ++linux-2.6 (2.6.15-1) unstable; urgency=low ++ ++ [ Sven Luther ] ++ * New upstream release. ++ * [powerpc] Now use ARCH=powerpc for 64bit powerpc flavours, 32bit still ++ stays with ARCH=ppc for now. ++ * [powerpc] Readded PReP Motorola PowerStack II Utah IDE interrupt ++ (Closes: #345424) ++ * [powerpc] Fixed apus patch. ++ * Added make-kpkg --arch option support to gencontrol.py. ++ * Added debian/bin/kconfig.ml to process config file snipplet, so we can ++ preserve the pre 2.6.15 ordering of config file snipplets. Upto 2.6.15 ++ the kernel Kconfig magic apparently kept the later occuring config options, ++ but it seems that this is no more the case. Instead of catting the config ++ files together, not use the kconfig.ml script to read in the files from ++ more generic to more specific, and keep only the more specific. ++ ++ [ Bastian Blank ] ++ * [s390] Update configs. ++ ++ [ Kyle McMartin ] ++ * [hppa] Snag latest hppa.diff from cvs.parisc-linux.org. ++ * [hppa] Update configs for 2.6.15. ++ * [hppa] Change parisc kernel names to something less ambiguous. ++ ++ [ dann frazier ] ++ * [ia64] Update ia64 configs ++ ++ [ maximilian attems ] ++ * Drop modular-ide.patch, nacked by ide upstream. Prevents udev to load ++ ide-generic and those successfull boots with initramfs-tools. ++ * Disable CONFIG_USB_BANDWIDTH, causes major trouble for alsa usb cards. ++ ++ [ Norbert Tretkowski ] ++ * [alpha] Removed conflict with initramfs-tools, thanks vorlon for finding ++ the klibc bug! ++ ++ [ Jonas Smedegaard ] ++ * Adjust short description of transitional package kernel-image-2.6- ++ 486 to mention 2.6 (not 2.6.12). ++ * Clean duplicate Kconfig options. ++ ++ [ Frederik Schüler ] ++ * Add updated version of drivers-scsi-megaraid_splitup.patch. ++ * Deactivate CONFIG_IDE_TASK_IOCTL on alpha and ia64 and make it a global ++ option. ++ * Make CONFIG_VIDEO_SAA7134 a global option. ++ * New option CONFIG_CC_OPTIMIZE_FOR_SIZE set per-arch. ++ * Rename i386 368 flavour to 486. ++ * Add myself to uploaders. ++ * Readdition of qla2xxx drivers, as firmware license has been fixed. ++ * Make CONFIG_PACKET, PACKET_MM and UNIX builtin on all architectures: ++ statically linked has better performance then modules due to TLB issue. ++ * clean up debian-patches dir: remove all obsolete patches: ++ - alpha-compile-fix.patch: obsolete ++ - amd64-int3-fix.patch: fixed since 2.6.12 ++ - net-ipconntrack-nat-fix.patch: merged upstream after 2.6.14 release ++ - net-nf_queue-oops.patch: merged upstream after 2.6.14 release ++ - qla2xxx-removed.patch: obsolete ++ * Drop M386 support remains from the i386 386 flavour: built with M486 ++ from now on. ++ ++ [ Martin Michlmayr ] ++ * [arm] Don't define "compiler" since GCC 4.x is the default now anyway. ++ * [arm] Add descriptions for "class" and "longclass". ++ * [arm] Compile CONFIG_BLK_DEV_SL82C105 support into the kernel on ++ Footbridge. ++ * [arm] Compile ext3 support into the kernel on Footbridge. ++ * [arm] Turn on CONFIG_SERIAL_8250 support on Footbridge. ++ ++ [ Jurij Smakov ] ++ * [sparc] Correct the patch for the atyfb framebuffer driver ++ (sparc64-atyfb-xl-gr.patch) to finally fix the console and X ++ image defects on Blade 100/150. The new patch is named ++ sparc64-atyfb-xl-gr-final.patch to avoid the confusion. ++ Thanks to Luis F. Ortiz for fixing the patch and Luigi Gangitano ++ for testing it out. ++ * Drop tty-locking-fixes9.patch, which was preventing the oops during ++ shutdown on some sparc machines with serial console. Proper fix has ++ been incorporated upstream. ++ ++ [ Simon Horman ] ++ * Enable MKISS globally (closes: #340215) ++ * Add recommends libc6-i686 to 686 and k7 image packages ++ (closes: #278729) ++ * Enable OBSOLETE_OSS_USB_DRIVER and USB_AUDIO ++ as alsa snd-usb-audio still isn't quite there. ++ I expect this to be re-disabled at some stage, ++ possibly soon if it proves to be a source of bugs. ++ (closes: #340388) ++ ++ -- Sven Luther Tue, 3 Jan 2006 06:48:07 +0000 ++ ++linux-2.6 (2.6.14-7) unstable; urgency=low ++ ++ [ maximilian attems ] ++ * Add stable tree 2.6.14.5 fixes: ++ - setting ACLs on readonly mounted NFS filesystems (CVE-2005-3623) ++ - Fix bridge-nf ipv6 length check ++ - Perform SA switchover immediately. ++ - Input: fix an OOPS in HID driver ++ - Fix hardware checksum modification ++ - kernel/params.c: fix sysfs access with CONFIG_MODULES=n ++ - Fix RTNLGRP definitions in rtnetlink.h ++ - Fix CTA_PROTO_NUM attribute size in ctnetlink ++ - Fix unbalanced read_unlock_bh in ctnetlink ++ - Fix NAT init order ++ - Fix incorrect dependency for IP6_NF_TARGET_NFQUEUE ++ - dpt_i2o fix for deadlock condition ++ - SCSI: fix transfer direction in sd (kernel panic when ejecting iPod) ++ - SCSI: fix transfer direction in scsi_lib and st ++ - Fix hardware rx csum errors ++ - Fix route lifetime. ++ - apci: fix NULL deref in video/lcd/brightness ++ * Disable CONFIG_USB_BANDWIDTH, causes major trouble on alsa usb cards. ++ (Closes: #344939) ++ ++ -- maximilian attems Tue, 27 Dec 2005 20:50:28 +0100 ++ ++linux-2.6 (2.6.14-6) unstable; urgency=low ++ ++ [ Kyle McMartin ] ++ * Change parisc kernel names to something less ambiguous. ++ ++ [ maximilian attems ] ++ * Drop modular-ide.patch, nacked by ide upstream. Prevents udev to load ++ ide-generic and those successfull boots with initramfs-tools. ++ * Add stable tree 2.6.14.4 with the following fixes: ++ - drivers/scsi/dpt_i2o.c: fix a user-after-free ++ - drivers/message/i2o/pci.c: fix a use-after-free ++ - drivers/infiniband/core/mad.c: fix a use-after-free ++ - DVB: BUDGET CI card depends on STV0297 demodulator ++ - setkeys needs root ++ - Fix listxattr() for generic security attributes ++ - AGPGART: Fix serverworks TLB flush. ++ - Fix crash when ptrace poking hugepage areas ++ - I8K: fix /proc reporting of blank service tags ++ - i82365: release all resources if no devices are found ++ - bonding: fix feature consolidation ++ - libata: locking rewrite (== fix) ++ - cciss: bug fix for BIG_PASS_THRU ++ - ALSA: nm256: reset workaround for Latitude CSx ++ - cciss: bug fix for hpacucli ++ - V4L/DVB: Fix analog NTSC for Thomson DTT 761X hybrid tuner ++ - BRIDGE: recompute features when adding a new device ++ - 32bit integer overflow in invalidate_inode_pages2() ++ - USB: Adapt microtek driver to new scsi features ++ - ide-floppy: software eject not working with LS-120 drive ++ - Add try_to_freeze to kauditd ++ - V4L/DVB (3135) Fix tuner init for Pinnacle PCTV Stereo ++ - NETLINK: Fix processing of fib_lookup netlink messages ++ - ACPI: fix HP nx8220 boot hang regression ++ ++ [ Norbert Tretkowski ] ++ * [alpha] Removed conflict with initramfs-tools, thanks vorlon for finding ++ the klibc bug! ++ ++ [ Frederik Schüler ] ++ * Add updated drivers-scsi-megaraid_splitup.patch. (Closes: #317258) ++ * Add ppc64-thermal-overtemp.patch to fix a thermal control bug in G5 ++ machines. (Closes: #343980) ++ * Unpatch the following patches which are included in 2.6.14.4: ++ - setkeys-needs-root-1.patch ++ - setkeys-needs-root-2.patch ++ - mm-invalidate_inode_pages2-overflow.patch ++ - net-bonding-consolidation-fix.patch ++ ++ -- Frederik Schüler Tue, 20 Dec 2005 18:50:41 +0000 ++ ++linux-2.6 (2.6.14-5) unstable; urgency=low ++ ++ [ dann frazier ] ++ * ia64-new-assembler-fix.patch ++ Fix ia64 builds with newer assembler (Closes: #341257) ++ ++ [ Sven Luther ] ++ * [powerpc] incremented ramdisk size to 24576 from 8192, needed by the ++ graphical installer, maybe we can bring this to 16384 later. ++ ++ [ Simon Horman ] ++ * Add recommends libc6-i686 to 686 and k7 image packages ++ (closes: #278729) ++ * Enable OBSOLETE_OSS_USB_DRIVER and USB_AUDIO ++ as alsa snd-usb-audio still isn't quite there. ++ I expect this to be re-disabled at some stage, ++ possibly soon if it proves to be a source of bugs. ++ (closes: #340388) ++ ++ [ dann frazier ] ++ * buslogic-pci-id-table.patch ++ add a pci device id table to fix initramfs-tools discovery. ++ (closes #342057) ++ * fix feature consolidation in bonding driver. (closes #340068) ++ ++ -- dann frazier Thu, 8 Dec 2005 10:59:31 -0700 ++ ++linux-2.6 (2.6.14-4) unstable; urgency=low ++ ++ [ dann frazier ] ++ * setkeys-needs-root-1.patch, setkeys-needs-root-2.patch: ++ [SECURITY] Require root privilege to write the current ++ function key string entry of other user's terminals. ++ See CVE-2005-3257 (Closes: #334113) ++ ++ [ Simon Horman ] ++ * Enable MKISS globally (closes: #340215) ++ * mm-invalidate_inode_pages2-overflow.patch ++ [SECURITY] 32bit integer overflow in invalidate_inode_pages2() (local DoS) ++ * ctnetlink-check-if-protoinfo-is-present.patch ++ [SECURITY] ctnetlink: check if protoinfo is present (local DoS) ++ * ctnetlink-fix-oops-when-no-icmp-id-info-in-message.patch ++ [SECURITY] ctnetlink: Fix oops when no ICMP ID info in message (local DoS) ++ ++ [ Sven Luther ] ++ * Re-added powerpc/apus patch, now that Roman Zippel merged it in. ++ * Let's create asm-(ppc|ppc64) -> asm-powerpc symlink farm. (Closes: #340571) ++ ++ [ maximilian attems ] ++ * Add 2.6.14.3 patch - features changelog: ++ - isdn/hardware/eicon/os_4bri.c: correct the xdiLoadFile() signature ++ - x86_64/i386: Compute correct MTRR mask on early Noconas ++ - PPTP helper: Fix endianness bug in GRE key / CallID NAT ++ - nf_queue: Fix Ooops when no queue handler registered ++ - ctnetlink: check if protoinfo is present ++ - ip_conntrack: fix ftp/irc/tftp helpers on ports >= 32768 ++ - VFS: Fix memory leak with file leases ++ - hwmon: Fix lm78 VID conversion ++ - hwmon: Fix missing it87 fan div init ++ - ppc64 memory model depends on NUMA ++ - Generic HDLC WAN drivers - disable netif_carrier_off() ++ - ctnetlink: Fix oops when no ICMP ID info in message ++ - Don't auto-reap traced children ++ - packet writing oops fix ++ - PPTP helper: fix PNS-PAC expectation call id ++ - NAT: Fix module refcount dropping too far ++ - Fix soft lockup with ALSA rtc-timer ++ - Fix calculation of AH length during filling ancillary data. ++ - ip_conntrack TCP: Accept SYN+PUSH like SYN ++ - refcount leak of proto when ctnetlink dumping tuple ++ - Fix memory management error during setting up new advapi sockopts. ++ - Fix sending extension headers before and including routing header. ++ - hwmon: Fix missing boundary check when setting W83627THF in0 limits ++ * Remove ctnetlink-check-if-protoinfo-is-present.patch, ++ net-nf_queue-oops.patch - already included in 2.6.14.3. ++ ++ [ Frederik Schüler ] ++ * Make CONFIG_PACKET, PACKET_MM and UNIX builtin on all architectures: ++ statically linked has better performance then modules due to TLB issue. ++ * Add myself to uploaders. ++ ++ -- Frederik Schüler Sat, 26 Nov 2005 13:18:41 +0100 ++ ++linux-2.6 (2.6.14-3) unstable; urgency=low ++ ++ [ Norbert Tretkowski ] ++ * [alpha] Switch to gcc 4.0. ++ * [alpha] Conflict with initramfs-tools, klibc is broken on alpha. ++ * [alpha] Enabled CONFIG_KOBJECT_UEVENT in arch/alphaconfig to fix trouble ++ with latest udev, thanks to Uwe Schindler for reporting. (closes: #338911) ++ * Bumped ABI revision: ++ + ABI changes on sparc and alpha because of compiler switch. ++ + 2.6.14.1 changes ABI of procfs. ++ ++ [ Sven Luther ] ++ * Set default TCP congestion algorithm to NewReno + BIC (Closes: #337089) ++ ++ [ maximilian attems ] ++ * Reenable CONFIG_SOFTWARE_SUSPEND on i386 and ppc, resume=/dev/ ++ must be set by boot loader. (Closes: #267600) ++ * Set CONFIG_USB_SUSPEND on i386. Usefull for suspend to ram and apm suspend. ++ * Add 2.6.14.1 patch: ++ - Al Viro: CVE-2005-2709 sysctl unregistration oops ++ * Add 2.6.14.2 patch: ++ - airo.c/airo_cs.c: correct prototypes ++ - fix XFS_QUOTA for modular XFS (closes: #337072) ++ - USB: always export interface information for modalias ++ - NET: Fix zero-size datagram reception ++ - fix alpha breakage ++ - Oops on suspend after on-the-fly switch to anticipatory i/o scheduler ++ - ipvs: fix connection leak if expire_nodest_conn=1 ++ - Fix ptrace self-attach rule ++ - fix signal->live leak in copy_process() ++ - fix de_thread() vs send_group_sigqueue() race ++ - prism54 : Fix frame length ++ - tcp: BIC max increment too large ++ * Remove alpha compile fix as contained in 2.6.14.2 ++ * Readd CONFIG_XFS_QUOTA=y. ++ * Disable ACPI cutoff year on i386, was set to 2001. ++ No need for acpi=force on boot. ++ ++ [ Jurij Smakov ] ++ * Fix the install-image script to correctly include all the necessary ++ stuff in scripts. (Closes: #336424) ++ * Enable CONFIG_SND_ALI5451 on sparc. ++ * Switch sparc to gcc-4.0. Thanks to Norbert for making sure it successfully ++ builds a working kernel now. ++ * Apply patch to fix ATI framebuffer output corruption on SunBlade 100 ++ (sparc64-atyfb-xl-gr.patch). Thanks to Luigi Gangitano. (Closes: #321200) ++ * Disable CONFIG_PARPORT_PC_FIFO on sparc, since it causes a hang whenever ++ something is sent to the parallel port device. Thanks to Attilla ++ (boera at rdslink.ro) for pointing that out. ++ ++ [ Simon Horman ] ++ * [386, AMD64] Set CONFIG_FRAMEBUFFER_CONSOLE=y instead of m. ++ As vesadb now built into the kernel, after finally dropping the ++ debian-specific patch to make it modular, make fbcons builtin too, else ++ all sorts of weird stuff happens which is hard for the inird builders to ++ automatically compenste for. (Closes: #336450) ++ * Redisable CONFIG_SOFTWARE_SUSPEND on ppc/miboot as it required ++ CONFIG_PM to compile. ++ * [NETFILTER] nf_queue: Fix Ooops when no queue handler registered ++ This is a regression introduced in 2.6.14. ++ net-nf_queue-oops.patch. (Closes: #337713) ++ * Make manuals with defconfig, as is required for kernel-package 10.008 ++ ++ [ dann frazier ] ++ * net-ipconntrack-nat-fix.patch - fix compilation of ++ ip_conntrack_helper_pptp.c when NAT is disabled. (Closes: #336431) ++ ++ [ Christian T. Steigies ] ++ * update m68k.diff to 2.6.14 ++ * add m68k-*vme* patches ++ * disable macsonic driver until the dma patch is fixed ++ * disable IEEE80211 drivers for all of m68k ++ ++ [ Frederik Schüler ] ++ * activate CONFIG_SECURITY_NETWORK to fix SElinux operation. ++ (Closes: #338543) ++ ++ -- Norbert Tretkowski Mon, 14 Nov 2005 10:23:05 +0100 ++ ++linux-2.6 (2.6.14-2) unstable; urgency=low ++ ++ [ Simon Horman ] ++ * [SECURITY] Avoid 'names_cache' memory leak with CONFIG_AUDITSYSCALL ++ This fix, included as part of the 2.6.13.4 patch in ++ 2.6.13+2.6.14-rc4-0experimental.1 is CVE-2005-3181 ++ * Fix genearation of .extraversion, again (closes: #333842) ++ * Add missing kernel-arch and kernel-header-dirs to defines ++ so headers get included. (closes: #336521) ++ N.B: I only filled in arches where other's hadn't done so alread. ++ Please fix if its wrong. ++ * Allow powerpc64 to compile with AUDIT enabled but ++ AUDITSYSCALL disabled. powerpc64-audit_sysctl-build.patch ++ ++ [ dann frazier ] ++ * Update hppa.diff to 2.6.14-pa0 ++ ++ [ Norbert Tretkowski ] ++ * [alpha] New patch to include compiler.h in barrier.h, barrier() is used in ++ non-SMP case. ++ * [alpha] Added kernel-header-dirs and kernel-arch to debian/arch/alpha/defines ++ to include asm-alpha in linux-headers package. ++ * Added myself to Uploaders. ++ ++ [ Frederik Schüler ] ++ * [amd64] use DISCONTIGMEM instead of SPARSEMEM on amd64-k8-smp flavour to ++ fix bootup kernel panic. ++ * [amd64] include asm-x86_64 in linux-headers package. ++ * Deactivate AUDITSYSCALL globally, it slows down the kernel and is not ++ needed for selinux at all. ++ ++ -- Simon Horman Tue, 1 Nov 2005 15:27:40 +0900 ++ ++linux-2.6 (2.6.14-1) unstable; urgency=low ++ ++ [ Sven Luther ] ++ * New upstream release. ++ ++ [ Norbert Tretkowski ] ++ * [alpha] Update arch/alpha/config* for 2.6.14. ++ ++ [ Simon Horman ] ++ * Fix misformatting of long description of ++ linux-patch-debian-linux-patch-debian-X.Y.Z. ++ templates/control.main.in ++ (closes: #335088) ++ * Make sure version is seeded in apply and unapply scripts. ++ Actually changed in some earlier, post 2.6.12, release, ++ but the changelog seems to be missing. ++ (closes: #324583) ++ ++ [ dann frazier ] ++ * [ia64] Disable the CONFIG_IA64_SGI_SN_XP module. This forces ++ CONFIG_GENERIC_ALLOCATOR and CONFIG_IA64_UNCACHED_ALLOCATOR to y, which ++ appears to break on zx1 systems. ++ ++ -- Simon Horman Fri, 28 Oct 2005 16:26:03 +0900 ++ ++linux-2.6 (2.6.13+2.6.14-rc5-0experimental.1) experimental; urgency=low ++ ++ [ Sven Luther ] ++ * Upgraded to 2.6.14-rc5. ++ ++ [ Jonas Smedegaard ] ++ * Quote variables in debian/rules.real and postinstall (making it ++ safer to run with weird characters in path of build environment). ++ ++ [ Bastian Blank ] ++ * Add some missing files from scripts to headers packages. ++ * Add new patch powerpc-build-links.patch: Emit relative symlinks in ++ arch/ppc{,64}/include. ++ * Include arch/*/include into headers package. ++ ++ -- Sven Luther Tue, 25 Oct 2005 03:56:11 +0000 ++ ++linux-2.6 (2.6.13+2.6.14-rc4-0experimental.1) experimental; urgency=low ++ ++ [ Sven Luther ] ++ * Upgraded to 2.6.14-rc4. ++ ++ [ Simon Horman ] ++ * Fix genearation of .extraversion (closes: #333842) ++ ++ [ dann frazier ] ++ * Enhance the linux-source description to explain the types of patches ++ Debian adds to it. (closes: #258043) ++ * Correct linux-patch-debian description. It replaces the ++ kernel-patch-debian packages, not the kernel-source packages. ++ ++ [ Jonas Smedegaard ] ++ * Fix building from within a very long dir (all patches was applied at ++ once - exhausting shell commandline, now applied one by one). ++ * Add Simon Horman, Sven Luther and myself as Uploaders. ++ ++ [ Bastian Blank ] ++ * Use list of revisions in patch scripts. ++ * Use correct names for tarball and scripts. ++ ++ [ Jurij Smakov ] ++ * [i386] Set the CONFIG_HPET_EMULATE_RTC option to make the clock ++ work properly on certain Dell machines. This required setting the ++ CONFIG_RTC option to 'y' instead of 'm'. (closes: #309909) ++ [i386] Enable VIDEO_CX88 and VIDEO_CX88_DVB (both set to 'm') by ++ popular demand. (closes: #330916) ++ ++ [ Norbert Tretkowski ] ++ * [alpha] Update arch/alpha/config for 2.6.13. ++ ++ [ Kyle McMartin ] ++ * [hppa] Oops. Fix linux-headers not including asm-parisc by adding ++ headers_dirs = parisc to Makefile.inc. ++ ++ [ maximilian attems ] ++ * Set CONFIG_FB_VESA=y for i386 and amd64 configs. (closes: #333003) ++ ++ [ Sven Luther ] ++ * [powerpc] Fixed apus build, now use mkvmlinuz too to generate the vmlinuz ++ kernel. ++ * Fixed control.image.in to depend on : ++ initramfs-tools | yaird | linux-ramdisk-tool ++ where linux-ramdisk-tools is the virtual package provided by all ++ initrd/initramfs generating tools. ++ ++ [ Frederik Schüler ] ++ * deactivate FB_RIVA on all architectures. ++ * deactivate BLK_DEV_IDESCSI on all architectures. ++ * Added patch-2.6.13.4: ++ - [SECURITY] key: plug request_key_auth memleak ++ See CAN-2005-3119 ++ - [SECURITY] Fix drm 'debug' sysfs permissions ++ See CAN-2005-3179 ++ - [SECURITY] Avoid 'names_cache' memory leak with CONFIG_AUDITSYSCALL ++ - [SPARC64] Fix userland FPU state corruption. ++ - BIC coding bug in Linux 2.6.13 ++ - [SECURITY] orinoco: Information leakage due to incorrect padding ++ See CAN-2005-3180 ++ - ieee1394/sbp2: fixes for hot-unplug and module unloading ++ ++ [ Christian T. Steigies ] ++ * disable CONFIG_EXT2_FS_XIP for m68k like on all(?) other arches ++ * deactivate OKTAGON_SCSI for amiga/m68k until it can be compiled again ++ * deactivate CONFIG_KEYBOARD_HIL_OLD, CONFIG_KEYBOARD_HIL, CONFIG_MOUSE_HIL, ++ CONFIG_HIL_MLC, and CONFIG_HP_SDC for hp/m68k ++ * update m68k.diff for 2.6.13 ++ * split out patches that do not intefere with other arches to ++ patches-debian/m68k-* ++ ++ -- Bastian Blank Fri, 21 Oct 2005 12:17:47 +0000 ++ ++linux-2.6 (2.6.13-1) experimental; urgency=low ++ ++ * New upstream release "git booost": ++ - new arch xtensa ++ - kexec/kdump ++ - execute-in-place ++ - inotify (closes: #304387) ++ - time-sharing cfq I/O scheduler ++ - manual driver binding ++ - voluntary preemption ++ - user-space I/O initiation for InfiniBand ++ - new speedy DES (crypto) implementation ++ - uml "almost-skas" mode support ++ - 250 HZ default (closes: #320366) ++ - fixes all over (alsa, archs, ide, input, ntfs, scsi, swsusp, usb, ..) ++ - orinoco driver updates (closes: #291684) ++ - md, dm updates (closes: #317787) ++ ++ [ Frederik Schüler ] ++ * [amd64] Added class and longclass descriptions for amd64 flavours. ++ * [amd64] add amd64-tlb-flush-sigsegv-fix.patch: disable tlb flush ++ filtering on smp systems to workaround processor errata. ++ * backport kernel-api-documentation-generation-fix.diff from git to fix ++ documentation build. ++ * Added patch-2.6.13.1: ++ - raw_sendmsg DoS (CAN-2005-2492) ++ - 32bit sendmsg() flaw (CAN-2005-2490) ++ - Reassembly trim not clearing CHECKSUM_HW ++ - Use SA_SHIRQ in sparc specific code. ++ - Fix boundary check in standard multi-block cipher processors ++ - 2.6.13 breaks libpcap (and tcpdump) ++ - x86: pci_assign_unassigned_resources() update ++ - Fix PCI ROM mapping ++ - aacraid: 2.6.13 aacraid bad BUG_ON fix ++ - Kconfig: saa7134-dvb must select tda1004x ++ ++ [ Simon Horman ] ++ * Disable BSDv3 accounting on hppa and alpha, it was already ++ disabled on all other architectures. Also unify BSD accounting ++ config into top level config, rather than per flavour configs. ++ * [SECURITY] The seq_file memory leak fix included in 2.6.12-6 ++ as part of upstream's 2.6.12.6 patchset is now CAN-2005-2800. ++ ++ [ Jurij Smakov, Simon Horman ] ++ * Ensure that only one kernel-manual/linux-manual package can ++ be installed at a time to avoid file conflicts. (closes: #320042) ++ ++ [ Bastian Blank ] ++ * Move audit, preempt and security settings to core config file. ++ * Fix powerpc configuration. ++ * Add debian version information to kernel version string. ++ * Drop coreutils | fileutils dependencies. ++ * Drop modular-vesafb patch. (closes: #222374, #289810) ++ ++ [ Christian T. Steigies ] ++ * update m68k.diff for linux-2.6.13 ++ * add m68k-42_dma.patch and m68k-sonic.patch that will be in upstream 2.6.14 ++ (which makes sun3 build fail, needs fixing) ++ ++ [ maximilian attems ] ++ * Drop drivers-add-scsi_changer.patch (merged) ++ * Drop drivers-ide-dma-blacklist-toshiba.patch (merged) ++ * Drop drivers-ide-__devinit.patch (merged) ++ * Added patch-2.6.13.2: ++ - USB: ftdi_sio: custom baud rate fix ++ - Fix up more strange byte writes to the PCI_ROM_ADDRESS config word ++ - Fix MPOL_F_VERIFY ++ - jfs: jfs_delete_inode must call clear_inode ++ - Fix DHCP + MASQUERADE problem ++ - Sun HME: enable and map PCI ROM properly ++ - Sun GEM ethernet: enable and map PCI ROM properly ++ - hpt366: write the full 4 bytes of ROM address, not just low 1 byte ++ - forcedeth: Initialize link settings in every nv_open() ++ - Lost sockfd_put() in routing_ioctl() ++ - lost fput in 32bit ioctl on x86-64 ++ * Added patch-2.6.13.3: ++ - Fix fs/exec.c:788 (de_thread()) BUG_ON ++ - Don't over-clamp window in tcp_clamp_window() ++ - fix IPv6 per-socket multicast filtering in exact-match case ++ - yenta oops fix ++ - ipvs: ip_vs_ftp breaks connections using persistence ++ - uml - Fix x86_64 page leak ++ - skge: set mac address oops with bonding ++ - tcp: set default congestion control correctly for incoming connections ++ ++ [ Sven Luther ] ++ * [powerpc] Added hotplug support to the mv643xx_eth driver : ++ powerpc-mv643xx-hotplug-support.patch ++ thanks go to Nicolas Det for providing the patch. ++ * [powerpc] Modified a couple of configuration options for the powerpc64 ++ flavour, fixes and enhances Apple G5 support (Closes: #323724, #328324) ++ * [powerpc] Added powerpc-miboot flavour to use exclusively with oldworld ++ powermac miboot floppies for debian-installer. ++ * [powerpc] Checked upgraded version of the apus patches, separated them in ++ a part which is safe to apply, and one which needs checking, and is thus ++ not applied yet. ++ ++ [ Kyle McMartin ] ++ * [hppa] Update hppa.diff to 2.6.13-pa4. ++ * [hppa] Add space register fix to pacache.S to hppa.diff. ++ ++ [ dann frazier ] ++ * Add a note to README.Debian that explains where users can find the .config ++ files used to generate the linux-image packages. Closes: #316809 ++ * [ia64] Workaround #325070 until upstream works out an acceptable solution. ++ This bug breaks module loading on non-SMP ia64 kernels. The workaround ++ is to temporarily use an SMP config for the non-SMP kernels. (Note that ++ John Wright is running benchmarks to determine the overhead of running ++ an SMP kernel on UP systems to help decide if this should be a ++ permanent change). ++ * [ia64] Update arch/ia64/config for 2.6.13 ++ ++ -- Simon Horman Thu, 6 Oct 2005 15:45:21 +0900 ++ ++linux-2.6 (2.6.12-6) unstable; urgency=high ++ ++ [ Andres Salomon, Bastian Blank ] ++ * Change ATM and Classical-IP-over-ATM to be modular, instead of being ++ statically included. (closes: #323143) ++ ++ [ Sven Luther ] ++ * [powerpc] powerpc-pmac-sound-check.patch: Added pmac-sound sanity check. ++ * [powerpc] powerpc-apus.patch: ++ Added preliminary apus patch to package, not applied to kernel tree yet. ++ ++ [ Simon Horman ] ++ * Unset CC_OPTIMIZE_FOR_SIZE in i386 config, ++ it breaks iproute's (and other netlink users) ability ++ to set routes. (closes: #322723) ++ * Added 2.6.12.6 ++ - [SECURITY: CAN-2005-2555] Restrict socket policy loading to ++ CAP_NET_ADMIN. ++ - [SECURITY] Fix DST leak in icmp_push_reply(). Possible remote ++ DoS? ++ - [SECURITY] NPTL signal delivery deadlock fix; possible local ++ DoS. ++ - fix gl_skb/skb type error in genelink driver in usbnet ++ - [SECURITY] fix a memory leak in devices seq_file implementation; ++ local DoS. ++ - [SECURITY] Fix SKB leak in ip6_input_finish(); local DoS. ++ ++ [ Andres Salomon ] ++ * [hppa] enable discontiguous memory support for 32bit hppa images, so ++ they build. ++ ++ -- Andres Salomon Tue, 06 Sep 2005 10:14:35 -0400 ++ ++linux-2.6 (2.6.12-5) unstable; urgency=low ++ ++ * Change ARM to use GCC 3.3 to avoid FTBFS errors with GCC 4 ++ (dann frazier) ++ ++ * Remove spurious double quote character from ia64 package descriptions. ++ (dann frazier) ++ ++ * Add transitional meta packages (kernel-image-2.6-*) for ia64. ++ (dann frazier) ++ ++ * Change fuzz factor to 1, stricter patch appliance. (Maximilian Attems) ++ ++ * Enabled CONFIG_THERM_PM72 on powerpc64 flavour. (Sven Luther) ++ ++ -- Bastian Blank Tue, 16 Aug 2005 21:43:31 +0200 ++ ++linux-2.6 (2.6.12-4) unstable; urgency=low ++ ++ * Supply correct subarch values for the powerpc images. ++ ++ -- Bastian Blank Mon, 15 Aug 2005 21:06:18 +0200 ++ ++linux-2.6 (2.6.12-3) unstable; urgency=low ++ ++ * Added reference to old kernel-* package names to make ++ transition a little more obvious to end users. ++ A Dan Jacobson special. (Simon Horman) Closes: #321167 ++ ++ * By the time this makes it into the archive, it will ++ be handling kernel-image-2.6-* packages. (Simon Horman) ++ Closes: #321867 ++ ++ * Link palinfo statically on ia64. (dann frazier) (Closes: #321885) ++ ++ * [hppa] : ++ - Add hppa arch specific patch. ++ - Build-Depend on binutils-hppa64 and gcc-4.0-hppa64. ++ (Kyle McMartin) ++ ++ * Fix permissions in source tarball. (Bastian Blank) (Closes: #322409) ++ ++ * Enable the CONFIG_IP_ADVANCED_ROUTER and related options on ++ sparc64 to sync with other architectures. (Jurij Smakov) ++ Closes: #321236 ++ ++ * Include all executables as well as *.sh and *.pl files found in ++ scripts directory in the headers package. (Bastian Blank) ++ Closes: #322612, #322680, #322765 ++ ++ * Include m68k headers into the arch-common headers package on ++ powerpc and make sure that all the directories are linked to ++ properly from the flavour-specific headers packages. (Jurij Smakov) ++ Closes: #322610 ++ ++ * [powerpc] Enabled the powerpc64 flavour, now that we have a real biarch ++ toolchain in sid. Many thanks go to GOTO Masanori and Matthias Klose as ++ well as any other who worked on the biarch toolchain to make this happen. ++ ++ * Added 2.6.12.5 (Simon Horman) ++ - Fix BUG() is triggered by a call to set_mempolicy() with a negativ ++ first argument. ++ - [amd64] Fix a SRAT handling on systems with dual cores. ++ - [amd64] SMP timing problem ++ - [security] Zlib fixes See CAN-2005-2458, CAN-2005-2459 ++ http://sources.redhat.com/ml/bug-gnu-utils/1999-06/msg00183.html ++ http://bugs.gentoo.org/show_bug.cgi ++ - Add zlib deflateBound() ++ - [security] Fix error during session join. See CAN-2005-2098 ++ - [security] Fix keyring destructor. See CAN-2005-2099 ++ - Module per-cpu alignment cannot always be met ++ http://www.ussg.iu.edu/hypermail/linux/kernel/0409.0/0768.html ++ Closes: #323039 ++ ++ -- Bastian Blank Mon, 15 Aug 2005 16:42:05 +0200 ++ ++linux-2.6 (2.6.12-2) unstable; urgency=low ++ ++ * The Kernel Team offers its condolences to the family of Jens Schmalzing ++ (jensen@debian), who died Saturday, July 30, 2005 in a tragic accident in ++ Munich. Jens was a member of the Kernel Team, and was instrumental in ++ taking the powerpc kernel package to 2.6, as well as maintaining MOL ++ and its kernel modules. ++ ++ * Add @longclass@ variable to control file autogeneration. (Andres Salomon) ++ ++ * Bump build-depends on kernel-package to a fixed version (>= 9.005). ++ (Jurij Smakov, Sven Luther) (closes: #319657, #320422, #321625) ++ ++ * Change default ramdisk size for sparc to 16,384K to accomodate a fatter ++ d-i initrd for netboot installs. ++ (Joshua Kwan) ++ ++ * Don't build-depend on console-tools on s390. (Bastian Blank) ++ ++ * Add ARM support. (Vincent Sanders) ++ ++ * Add ia64 descriptions. (dann frazier) ++ ++ * Strip down the scripts dir in the headers packages. (Bastian Blank) ++ ++ * Add m68k support. (Christian T. Steigies) ++ ++ * Added 2.6.12.4 (Frederik Schüler) ++ - Fix powernow oops on dual-core athlon ++ - Fix early vlan adding leads to not functional device ++ - sys_get_thread_area does not clear the returned argument ++ - bio_clone fix ++ - Fix possible overflow of sock->sk_policy (CAN-2005-2456) ++ (closes: #321401) ++ - Wait until all references to ip_conntrack_untracked are dropped on ++ unload ++ - Fix potential memory corruption in NAT code (aka memory NAT) ++ - Fix deadlock in ip6_queue ++ - Fix signedness issues in net/core/filter.c ++ - x86_64 memleak from malicious 32bit elf program ++ - rocket.c: Fix ldisc ref count handling ++ - kbuild: build TAGS problem with O= ++ ++ * Enable CONFIG_6PACK=m for all archs (Andres Salomon) ++ (closes: #319646) ++ ++ * Overhaul the generation of the control file. Now it is handled ++ by debian/bin/gencontrol.py. The debian/control target in rules ++ also fails now, since we don't want the control file generated ++ during build. Arch-specific Depends and suggests are now generated ++ correctly. (Bastian Blank) (Closes: #319896) ++ ++ * [powerpc] Fixed typo which made asm-ppc and asm-ppc64 not being included ++ in the header package. (Sven Luther) (Closes: #320817) ++ ++ * Added list of flavours built to common header package. (Sven Luther) ++ ++ -- Bastian Blank Tue, 09 Aug 2005 11:12:40 +0200 ++ ++linux-2.6 (2.6.12-1) unstable; urgency=low ++ ++ * New upstream release: ++ - "git rocks" ++ - address space randomization ++ - conversion of ide driver code to the device model ++ - restored Philips webcam driver ++ - new Broadcom bcm5706 gigabit driver ++ - new resource limits for the audio community ++ - Multipath device mapper ++ - Intel HD Audio alsa driver ++ - fixes + arch updates.. ++ - readdition of tg3 driver, as firmware license has been fixed ++ ++ * Dropped the following patches: ++ - patch-2.6.11.*.patch (merged) ++ - powerpc-ppc64-ibmvscsi.patch (Christoph didn't like it, and it failed ++ to build anyways) (Sven Luther) ++ - doc-post_halloween.patch (unless someone can come up w/ a valid ++ reason for carrying around rapidly bitrotting documentation...) ++ (Andres Salomon) ++ - sparc32-hypersparc-srmmu.patch (dropped until sparc32 is working ++ again, and we can figure out whether it's necessary) ++ - fix-alpha-ext3-oops.patch (no longer needed, fixed by compiler) ++ - x86-i486_emu.patch (buggy and insecure 80486 instruction emulation ++ for 80386; we're no longer supporting this) (closes: #250468) ++ - amd64-outs.patch (according to ++ http://www.ussg.iu.edu/hypermail/linux/kernel/0502.3/1095.html, this ++ is unnecessary for us) (Andres Salomon) ++ - sparc64-rtc-mostek.patch (merged) ++ - sparc64-compat-nanoseconds.patch (merged) ++ - sparc64-sunsu-init-2.6.11.patch (merged) ++ - sunsab-uart-update-timeout.patch (merged) ++ - alpha-read-trylock.patch (different version got merged) ++ - powerpc-prep-motorola-irq-fix.patch (merged) ++ - drivers-media-video-saa7134-update.patch (merged) ++ - drivers-media-video-saa7134-update-2.patch (merged) ++ - drivers-media-video-pll-lib.patch (merged) ++ - drivers-media-video-pll-lib-2.patch (merged) ++ - drivers-media-video-tuner-update-1.patch (merged) ++ - drivers-media-video-tuner-update-2.patch (merged) ++ - drivers-media-video-v4l-mpeg-support.patch (merged) ++ - drivers-media-video-mt352-update.patch (merged) ++ - arch-ppc64-hugepage-aio-panic.patch (merged) ++ - drivers-input-serio-nmouse.patch (merged) ++ - sparc64-sb1500-clock-2.6.patch (merged) ++ - docbook-allow-preprocessor-directives-... (merged) ++ - docbook-fix-function-parameter-descriptin-in-fbmem.patch (merged) ++ - docbook-move-kernel-doc-comment-next-to-function.patch (merged) ++ - powerpc-therm-adt746x-new-i2c-fix.patch (merged) ++ - powerpc-mv643xx-enet.patch (merged) ++ - powerpc-mv643xx-eth-pegasos.patch (merged) ++ - powerpc-pmac-agp-sleep.patch (merged) ++ - drivers-input-serio-8042-resume.patch (merged) ++ ++ * Premiere of the common-source kernel package ++ (Jurij Smakov, Andres Salomon) ++ - build all architectures out of kernel source package ++ - rename source and binary packages ++ - create a common config for different architectures, and management ++ tools to allow for easier modification of config options ++ - drop default configs, autogenerate them instead; requires ++ kernel-package >= 9.002. ++ ++ * Add 2.6.12.1 (Maximilian Attems) ++ - Clean up subthread exec (CAN-2005-1913) ++ - ia64 ptrace + sigrestore_context (CAN-2005-1761) ++ ++ * Add 2.6.12.2 (Frederik Schüler) ++ - Fix two socket hashing bugs. ++ - ACPI: Make sure we call acpi_register_gsi() even for default PCI ++ interrupt assignment ++ - Add "memory" clobbers to the x86 inline asm of strncmp and friends ++ - e1000: fix spinlock bug ++ - fix remap_pte_range BUG ++ - Fix typo in drivers/pci/pci-driver.c ++ ++ * Add 2.6.12.3 (Joshua Kwan) ++ - Fix semaphore handling in __unregister_chrdev ++ - Fix TT mode in UML. ++ - Check for a null return in tty_ldisc_ref. ++ - v4l: cx88 hue offset fix ++ - Fix 8139cp breakage that occurs with tpm driver. ++ - Fix the 6pack driver in SMP environments. ++ - Switch to spinlocks in the shaper driver. ++ - ppc32: stop misusing NTP's time_offset value ++ - netfilter: go back to dropping conntrack references manually ++ - ACPI: don't accept 0 as a PCI IRQ. ++ ++ * Enable CONFIG_SCSI_INITIO. (Maximilian Attems) (closes: #318121) ++ ++ * [powerpc] : ++ - Added powerpc-mkvmlinuz-support patch which allows, together with ++ kernel-package 9.0002 to add mkvmlinuz support to hand built packages. ++ - Removed powerpc-ppc64-ibmvscsi.patch, FTBFS, and Christoph doesn't like ++ it and thinks it is not needed. ++ - Disabled swim3 on powerpc-smp, FTBFS. ++ - Disabled software-suspend on powerpc-smp, FTBFS, amd64/i386 only smp code. ++ - Rediffed and readded the G4 L2 hardware flush assist patch from Jacob Pan. ++ (Sven Luther) ++ ++ * [sparc] ++ - Drop sparc32 flavour for now. sparc32 kernel is currently in the ++ category "too buggy for us to support". In spite of numerous efforts ++ I still see occasional random filesystem corruptions in my tests. ++ That does NOT mean that we are dropping sparc32 support, we will ++ work with upstream trying to solve these problems for the next ++ kernel release. Those interested in helping/testing are encouraged ++ to subscribe to debian-sparc mailing list. ++ (Jurij Smakov) ++ ++ * [alpha] ++ - Renamed resulting binary packages for alpha, kernel-image-x.y.z-generic ++ wasn't a generic kernel, it was a generic kernel for alpha machines, so ++ we're now using linux-image-x.y.z-alpha-generic (and of course, the same ++ change for the smp kernel-image). This change was postponed after the ++ sarge release. (closes: #260003) ++ (Norbert Tretkowski) ++ ++ * [amd64] ++ - Now using the default compiler (gcc-4.0), thus we get rid of the ++ annoying MAKEFLAGS="CC=gcc-3.4" make-kpkg... invocation for third-party ++ modules. ++ This release lacks 64bit kernels for i386 userland; support will be ++ added in a later release as soon as the toolchain has stabilized again. ++ (Frederik Schüler) ++ ++ -- Andres Salomon Wed, 20 Jul 2005 17:16:04 -0400 ++ +diff --git a/debian/compat b/debian/compat +new file mode 100644 +index 0000000..7f8f011 +--- /dev/null ++++ b/debian/compat +@@ -0,0 +1 @@ ++7 +diff --git a/debian/config/alpha/config b/debian/config/alpha/config +new file mode 100644 +index 0000000..52cbfbb +--- /dev/null ++++ b/debian/config/alpha/config +@@ -0,0 +1,1198 @@ ++## ++## file: arch/Kconfig ++## ++# CONFIG_OPROFILE is not set ++ ++## ++## file: arch/alpha/Kconfig ++## ++## choice: Alpha system type ++CONFIG_ALPHA_GENERIC=y ++# CONFIG_ALPHA_ALCOR is not set ++# CONFIG_ALPHA_XL is not set ++# CONFIG_ALPHA_BOOK1 is not set ++# CONFIG_ALPHA_AVANTI_CH is not set ++# CONFIG_ALPHA_CABRIOLET is not set ++# CONFIG_ALPHA_DP264 is not set ++# CONFIG_ALPHA_EB164 is not set ++# CONFIG_ALPHA_EB64P_CH is not set ++# CONFIG_ALPHA_EB66 is not set ++# CONFIG_ALPHA_EB66P is not set ++# CONFIG_ALPHA_EIGER is not set ++# CONFIG_ALPHA_JENSEN is not set ++# CONFIG_ALPHA_LX164 is not set ++# CONFIG_ALPHA_LYNX is not set ++# CONFIG_ALPHA_MARVEL is not set ++# CONFIG_ALPHA_MIATA is not set ++# CONFIG_ALPHA_MIKASA is not set ++# CONFIG_ALPHA_NAUTILUS is not set ++# CONFIG_ALPHA_NONAME_CH is not set ++# CONFIG_ALPHA_NORITAKE is not set ++# CONFIG_ALPHA_PC164 is not set ++# CONFIG_ALPHA_P2K is not set ++# CONFIG_ALPHA_RAWHIDE is not set ++# CONFIG_ALPHA_RUFFIAN is not set ++# CONFIG_ALPHA_RX164 is not set ++# CONFIG_ALPHA_SX164 is not set ++# CONFIG_ALPHA_SABLE is not set ++# CONFIG_ALPHA_SHARK is not set ++# CONFIG_ALPHA_TAKARA is not set ++# CONFIG_ALPHA_TITAN is not set ++# CONFIG_ALPHA_WILDFIRE is not set ++## end choice ++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set ++# CONFIG_VERBOSE_MCHECK is not set ++CONFIG_SRM_ENV=m ++ ++## ++## file: arch/alpha/Kconfig.debug ++## ++CONFIG_MATHEMU=y ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_PATA_ALI=m ++CONFIG_PATA_AMD=m ++CONFIG_PATA_CS5520=m ++CONFIG_PATA_CS5530=m ++CONFIG_PATA_CYPRESS=m ++CONFIG_PATA_EFAR=m ++CONFIG_PATA_HPT366=m ++CONFIG_PATA_HPT37X=m ++CONFIG_PATA_NS87415=m ++CONFIG_PATA_OLDPIIX=m ++CONFIG_PATA_PDC2027X=m ++CONFIG_PATA_PDC_OLD=m ++CONFIG_PATA_SC1200=m ++CONFIG_PATA_SERVERWORKS=m ++CONFIG_PATA_SIL680=m ++CONFIG_PATA_TRIFLEX=m ++CONFIG_PATA_VIA=m ++CONFIG_PATA_ISAPNP=y ++CONFIG_PATA_MPIIX=m ++CONFIG_PATA_OPTI=m ++CONFIG_PATA_LEGACY=m ++ ++## ++## file: drivers/atm/Kconfig ++## ++CONFIG_ATM_DRIVERS=y ++CONFIG_ATM_TCP=m ++CONFIG_ATM_LANAI=m ++CONFIG_ATM_ENI=m ++# CONFIG_ATM_ENI_DEBUG is not set ++# CONFIG_ATM_ENI_TUNE_BURST is not set ++CONFIG_ATM_FIRESTREAM=m ++CONFIG_ATM_ZATM=m ++# CONFIG_ATM_ZATM_DEBUG is not set ++CONFIG_ATM_IDT77252=m ++# CONFIG_ATM_IDT77252_DEBUG is not set ++# CONFIG_ATM_IDT77252_RCV_ALL is not set ++CONFIG_ATM_AMBASSADOR=m ++# CONFIG_ATM_AMBASSADOR_DEBUG is not set ++CONFIG_ATM_HORIZON=m ++# CONFIG_ATM_HORIZON_DEBUG is not set ++# CONFIG_ATM_FORE200E_USE_TASKLET is not set ++CONFIG_ATM_FORE200E_TX_RETRY=16 ++CONFIG_ATM_FORE200E_DEBUG=0 ++CONFIG_ATM_HE=m ++CONFIG_ATM_HE_USE_SUNI=y ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_DEV_FD=m ++CONFIG_BLK_DEV_XD=m ++CONFIG_PARIDE=m ++CONFIG_BLK_CPQ_DA=m ++CONFIG_BLK_CPQ_CISS_DA=m ++CONFIG_CISS_SCSI_TAPE=y ++CONFIG_BLK_DEV_DAC960=m ++CONFIG_BLK_DEV_UMEM=m ++CONFIG_BLK_DEV_SX8=m ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM_SIZE=8192 ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_CDROM_PKTCDVD_BUFFERS=8 ++CONFIG_CDROM_PKTCDVD_WCACHE=y ++ ++## ++## file: drivers/block/paride/Kconfig ++## ++CONFIG_PARIDE_PD=m ++CONFIG_PARIDE_PCD=m ++CONFIG_PARIDE_PF=m ++CONFIG_PARIDE_PT=m ++CONFIG_PARIDE_PG=m ++CONFIG_PARIDE_ATEN=m ++CONFIG_PARIDE_BPCK=m ++CONFIG_PARIDE_COMM=m ++CONFIG_PARIDE_DSTR=m ++CONFIG_PARIDE_FIT2=m ++CONFIG_PARIDE_FIT3=m ++CONFIG_PARIDE_EPAT=m ++CONFIG_PARIDE_EPATC8=y ++CONFIG_PARIDE_EPIA=m ++CONFIG_PARIDE_FRIQ=m ++CONFIG_PARIDE_FRPW=m ++CONFIG_PARIDE_KBIC=m ++CONFIG_PARIDE_KTTI=m ++CONFIG_PARIDE_ON20=m ++CONFIG_PARIDE_ON26=m ++ ++## ++## file: drivers/bluetooth/Kconfig ++## ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_H4=y ++CONFIG_BT_HCIUART_BCSP=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIDTL1=m ++CONFIG_BT_HCIBT3C=m ++CONFIG_BT_HCIBLUECARD=m ++CONFIG_BT_HCIBTUART=m ++CONFIG_BT_HCIVHCI=m ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_STALDRV=y ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++CONFIG_PPDEV=m ++CONFIG_RTC=m ++CONFIG_GEN_RTC=m ++CONFIG_GEN_RTC_X=y ++CONFIG_DTLK=m ++CONFIG_APPLICOM=m ++CONFIG_RAW_DRIVER=m ++CONFIG_MAX_RAW_DEVS=256 ++ ++## ++## file: drivers/char/agp/Kconfig ++## ++#. Workaround ++CONFIG_AGP=y ++#. Workaround ++CONFIG_AGP_ALPHA_CORE=y ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++CONFIG_IPMI_HANDLER=m ++# CONFIG_IPMI_PANIC_EVENT is not set ++CONFIG_IPMI_DEVICE_INTERFACE=m ++CONFIG_IPMI_SI=m ++CONFIG_IPMI_WATCHDOG=m ++CONFIG_IPMI_POWEROFF=m ++ ++## ++## file: drivers/eisa/Kconfig ++## ++CONFIG_EISA_PCI_EISA=y ++CONFIG_EISA_VIRTUAL_ROOT=y ++CONFIG_EISA_NAMES=y ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++CONFIG_DRM=m ++CONFIG_DRM_TDFX=m ++CONFIG_DRM_R128=m ++CONFIG_DRM_RADEON=m ++CONFIG_DRM_MGA=m ++CONFIG_DRM_SIS=m ++ ++## ++## file: drivers/gpu/drm/nouveau/Kconfig ++## ++CONFIG_DRM_NOUVEAU=m ++# CONFIG_DRM_NOUVEAU_BACKLIGHT is not set ++# CONFIG_DRM_NOUVEAU_DEBUG is not set ++CONFIG_DRM_I2C_CH7006=m ++CONFIG_DRM_I2C_SIL164=m ++ ++## ++## file: drivers/hid/usbhid/Kconfig ++## ++CONFIG_USB_HID=m ++CONFIG_USB_KBD=m ++CONFIG_USB_MOUSE=m ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_SENSORS_ADM1021=m ++CONFIG_SENSORS_ADM1025=m ++CONFIG_SENSORS_ADM1026=m ++CONFIG_SENSORS_ADM1031=m ++CONFIG_SENSORS_ASB100=m ++CONFIG_SENSORS_DS1621=m ++CONFIG_SENSORS_F71805F=m ++CONFIG_SENSORS_GL518SM=m ++CONFIG_SENSORS_GL520SM=m ++CONFIG_SENSORS_IT87=m ++CONFIG_SENSORS_LM63=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_LM77=m ++CONFIG_SENSORS_LM78=m ++CONFIG_SENSORS_LM80=m ++CONFIG_SENSORS_LM83=m ++CONFIG_SENSORS_LM85=m ++CONFIG_SENSORS_LM87=m ++CONFIG_SENSORS_LM90=m ++CONFIG_SENSORS_LM92=m ++CONFIG_SENSORS_MAX1619=m ++CONFIG_SENSORS_PC87360=m ++CONFIG_SENSORS_PCF8591=m ++CONFIG_SENSORS_SIS5595=m ++CONFIG_SENSORS_SMSC47M1=m ++CONFIG_SENSORS_SMSC47B397=m ++CONFIG_SENSORS_VIA686A=m ++CONFIG_SENSORS_W83781D=m ++CONFIG_SENSORS_W83L785TS=m ++CONFIG_SENSORS_W83627HF=m ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=m ++CONFIG_I2C_CHARDEV=m ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_ALI1535=m ++CONFIG_I2C_ALI1563=m ++CONFIG_I2C_ALI15X3=m ++CONFIG_I2C_AMD756=m ++# CONFIG_I2C_AMD756_S4882 is not set ++CONFIG_I2C_AMD8111=m ++CONFIG_I2C_I801=m ++CONFIG_I2C_PIIX4=m ++CONFIG_I2C_NFORCE2=m ++CONFIG_I2C_SIS5595=m ++CONFIG_I2C_SIS630=m ++CONFIG_I2C_SIS96X=m ++CONFIG_I2C_VIA=m ++CONFIG_I2C_VIAPRO=m ++CONFIG_I2C_PARPORT=m ++CONFIG_I2C_PARPORT_LIGHT=m ++CONFIG_I2C_ELEKTOR=m ++CONFIG_I2C_PCA_ISA=m ++CONFIG_I2C_STUB=m ++CONFIG_SCx200_ACB=m ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_GAMEPORT_EMU10K1=m ++CONFIG_GAMEPORT_FM801=m ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++CONFIG_INPUT_JOYSTICK=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++CONFIG_KEYBOARD_LKKBD=m ++CONFIG_KEYBOARD_NEWTON=m ++CONFIG_KEYBOARD_SUNKBD=m ++CONFIG_KEYBOARD_XTKBD=m ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_PCSPKR=m ++CONFIG_INPUT_UINPUT=m ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=m ++CONFIG_MOUSE_SERIAL=m ++CONFIG_MOUSE_INPORT=m ++# CONFIG_MOUSE_ATIXL is not set ++CONFIG_MOUSE_LOGIBM=m ++CONFIG_MOUSE_PC110PAD=m ++CONFIG_MOUSE_VSXXXAA=m ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++CONFIG_SERIO_I8042=y ++CONFIG_SERIO_SERPORT=m ++CONFIG_SERIO_PARKBD=m ++CONFIG_SERIO_PCIPS2=m ++CONFIG_SERIO_LIBPS2=y ++CONFIG_SERIO_RAW=m ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++CONFIG_INPUT_TOUCHSCREEN=y ++ ++## ++## file: drivers/isdn/Kconfig ++## ++CONFIG_ISDN=y ++CONFIG_ISDN_CAPI=m ++ ++## ++## file: drivers/isdn/capi/Kconfig ++## ++CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y ++CONFIG_ISDN_CAPI_MIDDLEWARE=y ++CONFIG_ISDN_CAPI_CAPI20=m ++CONFIG_ISDN_CAPI_CAPIDRV=m ++ ++## ++## file: drivers/isdn/hardware/avm/Kconfig ++## ++CONFIG_CAPI_AVM=y ++CONFIG_ISDN_DRV_AVMB1_B1ISA=m ++CONFIG_ISDN_DRV_AVMB1_B1PCI=m ++CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y ++CONFIG_ISDN_DRV_AVMB1_T1ISA=m ++CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m ++CONFIG_ISDN_DRV_AVMB1_AVM_CS=m ++CONFIG_ISDN_DRV_AVMB1_T1PCI=m ++CONFIG_ISDN_DRV_AVMB1_C4=m ++ ++## ++## file: drivers/isdn/hardware/eicon/Kconfig ++## ++CONFIG_CAPI_EICON=y ++CONFIG_ISDN_DIVAS=m ++CONFIG_ISDN_DIVAS_BRIPCI=y ++CONFIG_ISDN_DIVAS_PRIPCI=y ++CONFIG_ISDN_DIVAS_DIVACAPI=m ++CONFIG_ISDN_DIVAS_USERIDI=m ++CONFIG_ISDN_DIVAS_MAINT=m ++ ++## ++## file: drivers/media/Kconfig ++## ++CONFIG_DVB_CORE=m ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++CONFIG_RADIO_CADET=m ++CONFIG_RADIO_RTRACK=m ++CONFIG_RADIO_RTRACK2=m ++CONFIG_RADIO_AZTECH=m ++CONFIG_RADIO_GEMTEK=m ++CONFIG_RADIO_MAXIRADIO=m ++CONFIG_RADIO_SF16FMI=m ++CONFIG_RADIO_SF16FMR2=m ++CONFIG_RADIO_TERRATEC=m ++CONFIG_RADIO_TRUST=m ++CONFIG_RADIO_TYPHOON=m ++CONFIG_RADIO_ZOLTRIX=m ++CONFIG_USB_DSBR=m ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++CONFIG_I2O=m ++CONFIG_I2O_CONFIG=m ++CONFIG_I2O_BLOCK=m ++CONFIG_I2O_SCSI=m ++CONFIG_I2O_PROC=m ++ ++## ++## file: drivers/mmc/Kconfig ++## ++CONFIG_MMC=m ++# CONFIG_MMC_DEBUG is not set ++ ++## ++## file: drivers/mmc/card/Kconfig ++## ++CONFIG_MMC_BLOCK=m ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=m ++CONFIG_MTD_REDBOOT_PARTS=y ++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 ++CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y ++CONFIG_MTD_REDBOOT_PARTS_READONLY=y ++CONFIG_MTD_CMDLINE_PARTS=y ++CONFIG_MTD_CHAR=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_BLOCK_RO=m ++CONFIG_FTL=m ++CONFIG_NFTL=m ++CONFIG_NFTL_RW=y ++CONFIG_INFTL=m ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++CONFIG_MTD_CFI=m ++CONFIG_MTD_JEDECPROBE=m ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++## choice: Flash cmd/query data swapping ++# CONFIG_MTD_CFI_NOSWAP is not set ++CONFIG_MTD_CFI_BE_BYTE_SWAP=y ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++## end choice ++CONFIG_MTD_CFI_GEOMETRY=y ++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=y ++CONFIG_MTD_MAP_BANK_WIDTH_16=y ++CONFIG_MTD_MAP_BANK_WIDTH_32=y ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++CONFIG_MTD_CFI_I4=y ++CONFIG_MTD_CFI_I8=y ++# CONFIG_MTD_OTP is not set ++CONFIG_MTD_CFI_INTELEXT=m ++CONFIG_MTD_CFI_AMDSTD=m ++CONFIG_MTD_CFI_STAA=m ++CONFIG_MTD_RAM=m ++CONFIG_MTD_ROM=m ++CONFIG_MTD_ABSENT=m ++CONFIG_MTD_XIP=y ++ ++## ++## file: drivers/mtd/devices/Kconfig ++## ++CONFIG_MTD_PMC551=m ++# CONFIG_MTD_PMC551_BUGFIX is not set ++# CONFIG_MTD_PMC551_DEBUG is not set ++CONFIG_MTD_SLRAM=m ++CONFIG_MTD_PHRAM=m ++CONFIG_MTD_MTDRAM=m ++CONFIG_MTDRAM_TOTAL_SIZE=4096 ++CONFIG_MTDRAM_ERASE_SIZE=128 ++CONFIG_MTD_BLOCK2MTD=m ++CONFIG_MTD_DOC2000=m ++CONFIG_MTD_DOC2001=m ++CONFIG_MTD_DOC2001PLUS=m ++CONFIG_MTD_DOCPROBE_ADVANCED=y ++CONFIG_MTD_DOCPROBE_ADDRESS=0x0000 ++CONFIG_MTD_DOCPROBE_HIGH=y ++CONFIG_MTD_DOCPROBE_55AA=y ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++CONFIG_MTD_PHYSMAP=m ++CONFIG_MTD_PHYSMAP_START=0x8000000 ++CONFIG_MTD_PHYSMAP_LEN=0x4000000 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=2 ++CONFIG_MTD_PCI=m ++ ++## ++## file: drivers/mtd/nand/Kconfig ++## ++CONFIG_MTD_NAND=m ++# CONFIG_MTD_NAND_VERIFY_WRITE is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++ ++## ++## file: drivers/net/Kconfig ++## ++CONFIG_NET_FC=y ++CONFIG_NETPOLL_TRAP=y ++CONFIG_NET_SB1000=m ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++CONFIG_ARCNET=m ++CONFIG_ARCNET_1201=m ++CONFIG_ARCNET_1051=m ++CONFIG_ARCNET_RAW=m ++CONFIG_ARCNET_CAP=m ++CONFIG_ARCNET_COM90xx=m ++CONFIG_ARCNET_COM90xxIO=m ++CONFIG_ARCNET_RIM_I=m ++CONFIG_ARCNET_COM20020=m ++CONFIG_ARCNET_COM20020_ISA=m ++CONFIG_ARCNET_COM20020_PCI=m ++CONFIG_ARCNET_COM20020_CS=m ++ ++## ++## file: drivers/net/ethernet/Kconfig ++## ++CONFIG_FEALNX=m ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++CONFIG_NET_VENDOR_3COM=y ++CONFIG_EL1=m ++CONFIG_EL3=m ++CONFIG_3C515=m ++CONFIG_PCMCIA_3C574=m ++CONFIG_PCMCIA_3C589=m ++CONFIG_VORTEX=m ++CONFIG_TYPHOON=m ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_EL2=m ++CONFIG_AC3200=m ++CONFIG_PCMCIA_AXNET=m ++CONFIG_E2100=m ++CONFIG_ES3210=m ++CONFIG_HPLAN_PLUS=m ++CONFIG_HPLAN=m ++CONFIG_LNE390=m ++CONFIG_NE2000=m ++CONFIG_NE2K_PCI=m ++CONFIG_NE3210=m ++CONFIG_PCMCIA_PCNET=m ++CONFIG_ULTRA=m ++CONFIG_ULTRA32=m ++CONFIG_WD80x3=m ++ ++## ++## file: drivers/net/ethernet/adaptec/Kconfig ++## ++CONFIG_ADAPTEC_STARFIRE=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_AMD8111_ETH=m ++CONFIG_LANCE=m ++CONFIG_DEPCA=m ++CONFIG_PCMCIA_NMCLAN=m ++CONFIG_NI65=m ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++CONFIG_B44=m ++ ++## ++## file: drivers/net/ethernet/cirrus/Kconfig ++## ++CONFIG_CS89x0=m ++ ++## ++## file: drivers/net/ethernet/dec/Kconfig ++## ++CONFIG_EWRK3=m ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++CONFIG_NET_TULIP=y ++CONFIG_DE2104X=m ++CONFIG_TULIP=m ++# CONFIG_TULIP_MWI is not set ++# CONFIG_TULIP_MMIO is not set ++CONFIG_DE4X5=m ++CONFIG_WINBOND_840=m ++CONFIG_DM9102=m ++CONFIG_PCMCIA_XIRCOM=m ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++CONFIG_DE600=m ++CONFIG_DE620=m ++CONFIG_SUNDANCE=m ++# CONFIG_SUNDANCE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/fujitsu/Kconfig ++## ++CONFIG_AT1700=m ++CONFIG_PCMCIA_FMVJ18X=m ++CONFIG_ETH16I=m ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++CONFIG_HP100=m ++ ++## ++## file: drivers/net/ethernet/i825xx/Kconfig ++## ++CONFIG_ELPLUS=m ++CONFIG_EL16=m ++CONFIG_APRICOT=m ++CONFIG_EEXPRESS=m ++CONFIG_EEXPRESS_PRO=m ++CONFIG_LP486E=m ++CONFIG_NI52=m ++CONFIG_ZNET=m ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++CONFIG_E100=m ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_NATSEMI=m ++ ++## ++## file: drivers/net/ethernet/nvidia/Kconfig ++## ++CONFIG_FORCEDETH=m ++ ++## ++## file: drivers/net/ethernet/racal/Kconfig ++## ++CONFIG_NET_VENDOR_RACAL=y ++CONFIG_NI5010=m ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_8139CP=m ++CONFIG_8139TOO=m ++# CONFIG_8139TOO_PIO is not set ++CONFIG_8139TOO_TUNE_TWISTER=y ++CONFIG_8139TOO_8129=y ++# CONFIG_8139_OLD_RX_RESET is not set ++ ++## ++## file: drivers/net/ethernet/seeq/Kconfig ++## ++CONFIG_SEEQ8005=m ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++CONFIG_SIS900=m ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_SMC9194=m ++CONFIG_PCMCIA_SMC91C92=m ++CONFIG_EPIC100=m ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++CONFIG_HAPPYMEAL=m ++CONFIG_SUNGEM=m ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++CONFIG_VIA_RHINE=m ++# CONFIG_VIA_RHINE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/xircom/Kconfig ++## ++CONFIG_PCMCIA_XIRC2PS=m ++ ++## ++## file: drivers/net/fddi/Kconfig ++## ++CONFIG_FDDI=y ++CONFIG_SKFP=m ++ ++## ++## file: drivers/net/hamradio/Kconfig ++## ++CONFIG_DMASCC=m ++CONFIG_SCC=m ++# CONFIG_SCC_DELAY is not set ++# CONFIG_SCC_TRXECHO is not set ++ ++## ++## file: drivers/net/hippi/Kconfig ++## ++CONFIG_HIPPI=y ++CONFIG_ROADRUNNER=m ++# CONFIG_ROADRUNNER_LARGE_RINGS is not set ++ ++## ++## file: drivers/net/irda/Kconfig ++## ++CONFIG_IRTTY_SIR=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_NSC_FIR=m ++CONFIG_WINBOND_FIR=m ++CONFIG_SMC_IRCC_FIR=m ++CONFIG_ALI_FIR=m ++CONFIG_VLSI_FIR=m ++CONFIG_VIA_FIR=m ++ ++## ++## file: drivers/net/plip/Kconfig ++## ++CONFIG_PLIP=m ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++CONFIG_WAN=y ++CONFIG_HOSTESS_SV11=m ++CONFIG_COSA=m ++CONFIG_LANMEDIA=m ++CONFIG_SEALEVEL_4021=m ++CONFIG_PCI200SYN=m ++CONFIG_WANXL=m ++CONFIG_PC300=m ++CONFIG_PC300_MLPPP=y ++CONFIG_N2=m ++CONFIG_C101=m ++CONFIG_FARSYNC=m ++CONFIG_DSCC4=m ++CONFIG_DSCC4_PCISYNC=y ++CONFIG_DSCC4_PCI_RST=y ++CONFIG_DLCI=m ++CONFIG_DLCI_MAX=8 ++CONFIG_SDLA=m ++ ++## ++## file: drivers/net/wireless/Kconfig ++## ++CONFIG_PCMCIA_RAYCS=m ++CONFIG_ATMEL=m ++CONFIG_PCI_ATMEL=m ++CONFIG_PCMCIA_ATMEL=m ++CONFIG_AIRO_CS=m ++CONFIG_PCMCIA_WL3501=m ++CONFIG_USB_ZD1201=m ++ ++## ++## file: drivers/net/wireless/ipw2x00/Kconfig ++## ++# CONFIG_IPW2100 is not set ++ ++## ++## file: drivers/net/wireless/mwifiex/Kconfig ++## ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++ ++## ++## file: drivers/net/wireless/orinoco/Kconfig ++## ++CONFIG_HERMES=m ++CONFIG_PLX_HERMES=m ++CONFIG_TMD_HERMES=m ++CONFIG_PCI_HERMES=m ++CONFIG_PCMCIA_HERMES=m ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++CONFIG_PCCARD=m ++CONFIG_PCMCIA=m ++CONFIG_CARDBUS=y ++CONFIG_YENTA=m ++CONFIG_PD6729=m ++CONFIG_I82092=m ++CONFIG_I82365=m ++CONFIG_TCIC=m ++CONFIG_PCMCIA_DEBUG=y ++ ++## ++## file: drivers/pnp/Kconfig ++## ++CONFIG_PNP=y ++ ++## ++## file: drivers/pnp/isapnp/Kconfig ++## ++CONFIG_ISAPNP=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI_IN2000=m ++CONFIG_SCSI_ARCMSR=m ++CONFIG_SCSI_BUSLOGIC=m ++CONFIG_SCSI_DMX3191D=m ++CONFIG_SCSI_DTC3280=m ++CONFIG_SCSI_EATA=m ++CONFIG_SCSI_EATA_TAGGED_QUEUE=y ++CONFIG_SCSI_EATA_LINKED_COMMANDS=y ++CONFIG_SCSI_EATA_MAX_TAGS=16 ++CONFIG_SCSI_FUTURE_DOMAIN=m ++CONFIG_SCSI_GDTH=m ++CONFIG_SCSI_GENERIC_NCR5380=m ++CONFIG_SCSI_GENERIC_NCR5380_MMIO=m ++CONFIG_SCSI_GENERIC_NCR53C400=y ++CONFIG_SCSI_IPS=m ++CONFIG_SCSI_INITIO=m ++CONFIG_SCSI_INIA100=m ++CONFIG_SCSI_IZIP_EPP16=y ++CONFIG_SCSI_IZIP_SLOW_CTR=y ++CONFIG_SCSI_NCR53C406A=m ++CONFIG_SCSI_SYM53C8XX_2=m ++CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 ++CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 ++CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 ++CONFIG_SCSI_IPR=m ++CONFIG_SCSI_IPR_TRACE=y ++CONFIG_SCSI_IPR_DUMP=y ++CONFIG_SCSI_PAS16=m ++CONFIG_SCSI_QLOGIC_FAS=m ++CONFIG_SCSI_QLOGIC_1280=m ++CONFIG_SCSI_SIM710=m ++CONFIG_SCSI_SYM53C416=m ++CONFIG_SCSI_DC395x=m ++CONFIG_SCSI_DC390T=m ++CONFIG_SCSI_T128=m ++CONFIG_SCSI_U14_34F=m ++CONFIG_SCSI_U14_34F_TAGGED_QUEUE=y ++CONFIG_SCSI_U14_34F_LINKED_COMMANDS=y ++CONFIG_SCSI_U14_34F_MAX_TAGS=8 ++CONFIG_SCSI_DEBUG=m ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++CONFIG_MEGARAID_NEWGEN=y ++CONFIG_MEGARAID_MM=m ++CONFIG_MEGARAID_MAILBOX=m ++CONFIG_MEGARAID_LEGACY=m ++ ++## ++## file: drivers/scsi/pcmcia/Kconfig ++## ++CONFIG_PCMCIA_FDOMAIN=m ++CONFIG_PCMCIA_QLOGIC=m ++CONFIG_PCMCIA_SYM53C500=m ++ ++## ++## file: drivers/telephony/Kconfig ++## ++CONFIG_PHONE=m ++CONFIG_PHONE_IXJ=m ++CONFIG_PHONE_IXJ_PCMCIA=m ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++CONFIG_ROCKETPORT=m ++CONFIG_CYCLADES=m ++# CONFIG_CYZ_INTR is not set ++CONFIG_MOXA_INTELLIO=m ++CONFIG_SYNCLINK=m ++CONFIG_SYNCLINKMP=m ++CONFIG_ISI=m ++CONFIG_N_HDLC=m ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_CS=m ++CONFIG_SERIAL_8250_NR_UARTS=32 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_MANY_PORTS=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++# CONFIG_SERIAL_8250_DETECT_IRQ is not set ++CONFIG_SERIAL_8250_RSA=y ++CONFIG_SERIAL_JSM=m ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++CONFIG_USB_USS720=m ++ ++## ++## file: drivers/usb/atm/Kconfig ++## ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++CONFIG_USB_SL811_HCD=m ++CONFIG_USB_SL811_CS=m ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++CONFIG_FB_MODE_HELPERS=y ++CONFIG_FB_TILEBLITTING=y ++CONFIG_FB_CIRRUS=m ++CONFIG_FB_PM2=m ++CONFIG_FB_PM2_FIFO_DISCONNECT=y ++CONFIG_FB_CYBER2000=m ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++CONFIG_FB_TGA=m ++CONFIG_FB_S1D13XXX=m ++CONFIG_FB_MATROX=m ++CONFIG_FB_MATROX_MILLENIUM=y ++CONFIG_FB_MATROX_MYSTIQUE=y ++CONFIG_FB_MATROX_G=y ++CONFIG_FB_MATROX_I2C=m ++CONFIG_FB_MATROX_MAVEN=m ++CONFIG_FB_RADEON=m ++CONFIG_FB_RADEON_I2C=y ++# CONFIG_FB_RADEON_DEBUG is not set ++CONFIG_FB_ATY128=m ++CONFIG_FB_ATY=m ++CONFIG_FB_ATY_CT=y ++# CONFIG_FB_ATY_GENERIC_LCD is not set ++CONFIG_FB_ATY_GX=y ++CONFIG_FB_SAVAGE=m ++# CONFIG_FB_SAVAGE_I2C is not set ++# CONFIG_FB_SAVAGE_ACCEL is not set ++CONFIG_FB_SIS=m ++CONFIG_FB_SIS_300=y ++CONFIG_FB_SIS_315=y ++CONFIG_FB_NEOMAGIC=m ++CONFIG_FB_KYRO=m ++CONFIG_FB_VOODOO1=m ++CONFIG_FB_TRIDENT=m ++CONFIG_FB_VIRTUAL=m ++ ++## ++## file: drivers/video/backlight/Kconfig ++## ++CONFIG_LCD_CLASS_DEVICE=m ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_VGA_CONSOLE=y ++CONFIG_MDA_CONSOLE=m ++CONFIG_FRAMEBUFFER_CONSOLE=m ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_PCWATCHDOG=m ++CONFIG_MIXCOMWD=m ++CONFIG_WDT=m ++CONFIG_PCIPCWATCHDOG=m ++CONFIG_WDTPCI=m ++CONFIG_USBPCWATCHDOG=m ++ ++## ++## file: fs/Kconfig.binfmt ++## ++CONFIG_BINFMT_AOUT=m ++CONFIG_OSF4_COMPAT=y ++CONFIG_BINFMT_EM86=m ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_ACORN_PARTITION=y ++# CONFIG_ACORN_PARTITION_CUMANA is not set ++# CONFIG_ACORN_PARTITION_EESOX is not set ++CONFIG_ACORN_PARTITION_ICS=y ++# CONFIG_ACORN_PARTITION_ADFS is not set ++# CONFIG_ACORN_PARTITION_POWERTEC is not set ++CONFIG_ACORN_PARTITION_RISCIX=y ++CONFIG_OSF_PARTITION=y ++CONFIG_AMIGA_PARTITION=y ++CONFIG_ATARI_PARTITION=y ++CONFIG_MAC_PARTITION=y ++CONFIG_BSD_DISKLABEL=y ++CONFIG_MINIX_SUBPARTITION=y ++CONFIG_SOLARIS_X86_PARTITION=y ++CONFIG_UNIXWARE_DISKLABEL=y ++CONFIG_LDM_PARTITION=y ++# CONFIG_LDM_DEBUG is not set ++CONFIG_SGI_PARTITION=y ++CONFIG_ULTRIX_PARTITION=y ++CONFIG_SUN_PARTITION=y ++ ++## ++## file: init/Kconfig ++## ++#. TODO ++# CONFIG_AUDIT is not set ++ ++## ++## file: lib/Kconfig ++## ++#. TODO ++CONFIG_CRC32=m ++ ++## ++## file: net/ax25/Kconfig ++## ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++# CONFIG_AX25_DAMA_SLAVE is not set ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++ ++## ++## file: net/decnet/Kconfig ++## ++CONFIG_DECNET=m ++# CONFIG_DECNET_ROUTER is not set ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++# CONFIG_IPX_INTERN is not set ++ ++## ++## file: net/irda/Kconfig ++## ++CONFIG_IRDA=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++# CONFIG_IRDA_DEBUG is not set ++ ++## ++## file: net/irda/ircomm/Kconfig ++## ++CONFIG_IRCOMM=m ++ ++## ++## file: net/irda/irlan/Kconfig ++## ++CONFIG_IRLAN=m ++ ++## ++## file: net/irda/irnet/Kconfig ++## ++CONFIG_IRNET=m ++ ++## ++## file: net/lapb/Kconfig ++## ++CONFIG_LAPB=m ++ ++## ++## file: sound/drivers/Kconfig ++## ++CONFIG_SND_DUMMY=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++ ++## ++## file: sound/isa/Kconfig ++## ++CONFIG_SND_ADLIB=m ++CONFIG_SND_AD1816A=m ++CONFIG_SND_AD1848=m ++CONFIG_SND_ALS100=m ++CONFIG_SND_AZT2320=m ++CONFIG_SND_CMI8330=m ++CONFIG_SND_CS4231=m ++CONFIG_SND_CS4236=m ++CONFIG_SND_ES1688=m ++CONFIG_SND_ES18XX=m ++CONFIG_SND_GUSCLASSIC=m ++CONFIG_SND_GUSEXTREME=m ++CONFIG_SND_GUSMAX=m ++CONFIG_SND_INTERWAVE=m ++CONFIG_SND_INTERWAVE_STB=m ++CONFIG_SND_OPL3SA2=m ++CONFIG_SND_OPTI92X_AD1848=m ++CONFIG_SND_OPTI92X_CS4231=m ++CONFIG_SND_OPTI93X=m ++CONFIG_SND_MIRO=m ++CONFIG_SND_SB8=m ++CONFIG_SND_SB16=m ++CONFIG_SND_SBAWE=m ++CONFIG_SND_SB16_CSP=y ++CONFIG_SND_SSCAPE=m ++CONFIG_SND_WAVEFRONT=m ++ ++## ++## file: sound/pci/Kconfig ++## ++CONFIG_SND_ALS4000=m ++CONFIG_SND_ALI5451=m ++CONFIG_SND_ATIIXP=m ++CONFIG_SND_ATIIXP_MODEM=m ++CONFIG_SND_AU8810=m ++CONFIG_SND_AU8820=m ++CONFIG_SND_AU8830=m ++CONFIG_SND_AZT3328=m ++CONFIG_SND_BT87X=m ++# CONFIG_SND_BT87X_OVERCLOCK is not set ++CONFIG_SND_CA0106=m ++CONFIG_SND_CMIPCI=m ++CONFIG_SND_CS4281=m ++CONFIG_SND_CS46XX=m ++CONFIG_SND_CS46XX_NEW_DSP=y ++CONFIG_SND_EMU10K1=m ++CONFIG_SND_EMU10K1X=m ++CONFIG_SND_ENS1370=m ++CONFIG_SND_ENS1371=m ++CONFIG_SND_ES1938=m ++CONFIG_SND_ES1968=m ++CONFIG_SND_FM801=m ++CONFIG_SND_FM801_TEA575X_BOOL=y ++CONFIG_SND_HDSP=m ++CONFIG_SND_ICE1712=m ++CONFIG_SND_ICE1724=m ++CONFIG_SND_INTEL8X0=m ++CONFIG_SND_INTEL8X0M=m ++CONFIG_SND_KORG1212=m ++CONFIG_SND_MAESTRO3=m ++# CONFIG_SND_MIXART is not set ++CONFIG_SND_NM256=m ++CONFIG_SND_RME32=m ++CONFIG_SND_RME96=m ++CONFIG_SND_RME9652=m ++CONFIG_SND_SONICVIBES=m ++CONFIG_SND_TRIDENT=m ++CONFIG_SND_VIA82XX=m ++CONFIG_SND_VIA82XX_MODEM=m ++CONFIG_SND_VX222=m ++CONFIG_SND_YMFPCI=m ++ ++## ++## file: sound/pci/hda/Kconfig ++## ++CONFIG_SND_HDA_INTEL=m ++ +diff --git a/debian/config/alpha/config.alpha-generic b/debian/config/alpha/config.alpha-generic +new file mode 100644 +index 0000000..d63bf76 +--- /dev/null ++++ b/debian/config/alpha/config.alpha-generic +@@ -0,0 +1,10 @@ ++## ++## file: arch/alpha/Kconfig ++## ++# CONFIG_SMP is not set ++ ++## ++## file: arch/alpha/Kconfig.debug ++## ++# CONFIG_ALPHA_LEGACY_START_ADDRESS is not set ++ +diff --git a/debian/config/alpha/config.alpha-legacy b/debian/config/alpha/config.alpha-legacy +new file mode 100644 +index 0000000..256ad21 +--- /dev/null ++++ b/debian/config/alpha/config.alpha-legacy +@@ -0,0 +1,10 @@ ++## ++## file: arch/alpha/Kconfig ++## ++# CONFIG_SMP is not set ++ ++## ++## file: arch/alpha/Kconfig.debug ++## ++CONFIG_ALPHA_LEGACY_START_ADDRESS=y ++ +diff --git a/debian/config/alpha/config.alpha-smp b/debian/config/alpha/config.alpha-smp +new file mode 100644 +index 0000000..19288e3 +--- /dev/null ++++ b/debian/config/alpha/config.alpha-smp +@@ -0,0 +1,16 @@ ++## ++## file: arch/alpha/Kconfig ++## ++CONFIG_SMP=y ++CONFIG_NR_CPUS=64 ++ ++## ++## file: arch/alpha/Kconfig.debug ++## ++# CONFIG_ALPHA_LEGACY_START_ADDRESS is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++ +diff --git a/debian/config/alpha/defines b/debian/config/alpha/defines +new file mode 100644 +index 0000000..1e7a5cb +--- /dev/null ++++ b/debian/config/alpha/defines +@@ -0,0 +1,18 @@ ++[base] ++flavours: alpha-generic alpha-smp alpha-legacy ++kernel-arch: alpha ++ ++[image] ++suggests: aboot, fdutils ++ ++[alpha-generic_description] ++hardware: Alpha ++hardware-long: DEC Alpha systems with extended kernel start address (Wildfire, Titan, Marvel) ++ ++[alpha-smp_description] ++hardware: Alpha SMP ++hardware-long: DEC Alpha SMP systems with extended kernel start address (Wildfire, Titan, Marvel) ++ ++[alpha-legacy_description] ++hardware: Alpha Legacy ++hardware-long: DEC Alpha systems with legacy kernel start address +diff --git a/debian/config/amd64/config-cumulus b/debian/config/amd64/config-cumulus +new file mode 100644 +index 0000000..6455f86 +--- /dev/null ++++ b/debian/config/amd64/config-cumulus +@@ -0,0 +1,2771 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/x86_64 3.2.71 Kernel Configuration ++# ++CONFIG_64BIT=y ++# CONFIG_X86_32 is not set ++CONFIG_X86_64=y ++CONFIG_X86=y ++CONFIG_INSTRUCTION_DECODER=y ++CONFIG_OUTPUT_FORMAT="elf64-x86-64" ++CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" ++CONFIG_GENERIC_CMOS_UPDATE=y ++CONFIG_CLOCKSOURCE_WATCHDOG=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_MMU=y ++CONFIG_ZONE_DMA=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_GENERIC_ISA_DMA=y ++CONFIG_GENERIC_IOMAP=y ++CONFIG_GENERIC_BUG=y ++CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_GPIO=y ++CONFIG_ARCH_MAY_HAVE_PC_FDC=y ++# CONFIG_RWSEM_GENERIC_SPINLOCK is not set ++CONFIG_RWSEM_XCHGADD_ALGORITHM=y ++CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_ARCH_HAS_CPU_RELAX=y ++CONFIG_ARCH_HAS_DEFAULT_IDLE=y ++CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y ++CONFIG_ARCH_HAS_CPU_AUTOPROBE=y ++CONFIG_HAVE_SETUP_PER_CPU_AREA=y ++CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y ++CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ZONE_DMA32=y ++CONFIG_ARCH_POPULATES_NODE_MAP=y ++CONFIG_AUDIT_ARCH=y ++CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y ++CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y ++CONFIG_X86_64_SMP=y ++CONFIG_X86_HT=y ++CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" ++# CONFIG_KTIME_SCALAR is not set ++CONFIG_ARCH_CPU_PROBE_RELEASE=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_HAVE_IRQ_WORK=y ++CONFIG_IRQ_WORK=y ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_HAVE_KERNEL_GZIP=y ++CONFIG_HAVE_KERNEL_BZIP2=y ++CONFIG_HAVE_KERNEL_LZMA=y ++CONFIG_HAVE_KERNEL_XZ=y ++CONFIG_HAVE_KERNEL_LZO=y ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_BZIP2 is not set ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++CONFIG_DEFAULT_HOSTNAME="cumulus" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_POSIX_MQUEUE_SYSCTL=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_FHANDLE=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_AUDIT=y ++CONFIG_AUDITSYSCALL=y ++CONFIG_AUDIT_WATCH=y ++CONFIG_AUDIT_TREE=y ++CONFIG_HAVE_GENERIC_HARDIRQS=y ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_HAVE_SPARSE_IRQ=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_GENERIC_PENDING_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++ ++# ++# RCU Subsystem ++# ++CONFIG_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_RCU_TRACE is not set ++CONFIG_RCU_FANOUT=64 ++# CONFIG_RCU_FANOUT_EXACT is not set ++CONFIG_RCU_FAST_NO_HZ=y ++# CONFIG_TREE_RCU_TRACE is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=20 ++CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CPUSETS=y ++CONFIG_PROC_PID_CPUSET=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_RESOURCE_COUNTERS=y ++CONFIG_CGROUP_MEM_RES_CTLR=y ++CONFIG_CGROUP_MEM_RES_CTLR_DISABLED=y ++CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y ++# CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set ++CONFIG_CGROUP_PERF=y ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++CONFIG_RT_GROUP_SCHED=y ++CONFIG_BLK_CGROUP=y ++# CONFIG_DEBUG_BLK_CGROUP is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++CONFIG_USER_NS=y ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_MM_OWNER=y ++# CONFIG_SYSFS_DEPRECATED is not set ++CONFIG_RELAY=y ++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_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_EXPERT=y ++CONFIG_UID16=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_PCSPKR_PLATFORM=y ++CONFIG_HAVE_PCSPKR_PLATFORM=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++# CONFIG_EMBEDDED is not set ++CONFIG_HAVE_PERF_EVENTS=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++CONFIG_PERF_COUNTERS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_PCI_QUIRKS=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_SLAB=y ++# CONFIG_SLUB is not set ++# CONFIG_SLOB is not set ++CONFIG_PROFILING=y ++CONFIG_TRACEPOINTS=y ++CONFIG_OPROFILE=m ++# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set ++CONFIG_HAVE_OPROFILE=y ++CONFIG_KPROBES=y ++# CONFIG_JUMP_LABEL is not set ++CONFIG_OPTPROBES=y ++CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y ++CONFIG_KRETPROBES=y ++CONFIG_USER_RETURN_NOTIFIER=y ++CONFIG_HAVE_IOREMAP_PROT=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_OPTPROBES=y ++CONFIG_HAVE_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=y ++CONFIG_USE_GENERIC_SMP_HELPERS=y ++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y ++CONFIG_HAVE_DMA_API_DEBUG=y ++CONFIG_HAVE_HW_BREAKPOINT=y ++CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y ++CONFIG_HAVE_USER_RETURN_NOTIFIER=y ++CONFIG_HAVE_PERF_EVENTS_NMI=y ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y ++ ++# ++# GCOV-based kernel profiling ++# ++# CONFIG_GCOV_KERNEL is not set ++# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set ++CONFIG_SLABINFO=y ++CONFIG_RT_MUTEXES=y ++CONFIG_BASE_SMALL=0 ++CONFIG_MODULES=y ++CONFIG_MODULE_FORCE_LOAD=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_BLK_DEV_BSG=y ++CONFIG_BLK_DEV_BSGLIB=y ++CONFIG_BLK_DEV_INTEGRITY=y ++# CONFIG_BLK_DEV_THROTTLING is not set ++CONFIG_BLOCK_COMPAT=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq" ++CONFIG_PREEMPT_NOTIFIERS=y ++# CONFIG_INLINE_SPIN_TRYLOCK is not set ++# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK is not set ++# CONFIG_INLINE_SPIN_LOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQ is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set ++CONFIG_INLINE_SPIN_UNLOCK=y ++# CONFIG_INLINE_SPIN_UNLOCK_BH is not set ++CONFIG_INLINE_SPIN_UNLOCK_IRQ=y ++# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_READ_TRYLOCK is not set ++# CONFIG_INLINE_READ_LOCK is not set ++# CONFIG_INLINE_READ_LOCK_BH is not set ++# CONFIG_INLINE_READ_LOCK_IRQ is not set ++# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set ++CONFIG_INLINE_READ_UNLOCK=y ++# CONFIG_INLINE_READ_UNLOCK_BH is not set ++CONFIG_INLINE_READ_UNLOCK_IRQ=y ++# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_WRITE_TRYLOCK is not set ++# CONFIG_INLINE_WRITE_LOCK is not set ++# CONFIG_INLINE_WRITE_LOCK_BH is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQ is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set ++CONFIG_INLINE_WRITE_UNLOCK=y ++# CONFIG_INLINE_WRITE_UNLOCK_BH is not set ++CONFIG_INLINE_WRITE_UNLOCK_IRQ=y ++# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set ++CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y ++CONFIG_MUTEX_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# Processor type and features ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y ++CONFIG_SMP=y ++CONFIG_X86_MPPARSE=y ++# CONFIG_X86_EXTENDED_PLATFORM is not set ++CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y ++CONFIG_SCHED_OMIT_FRAME_POINTER=y ++# CONFIG_PARAVIRT_GUEST is not set ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMTEST=y ++# CONFIG_MK8 is not set ++# CONFIG_MPSC is not set ++# CONFIG_MCORE2 is not set ++# CONFIG_MATOM is not set ++CONFIG_GENERIC_CPU=y ++CONFIG_X86_INTERNODE_CACHE_SHIFT=6 ++CONFIG_X86_CMPXCHG=y ++CONFIG_CMPXCHG_LOCAL=y ++CONFIG_CMPXCHG_DOUBLE=y ++CONFIG_X86_L1_CACHE_SHIFT=6 ++CONFIG_X86_XADD=y ++CONFIG_X86_WP_WORKS_OK=y ++CONFIG_X86_TSC=y ++CONFIG_X86_CMPXCHG64=y ++CONFIG_X86_CMOV=y ++CONFIG_X86_MINIMUM_CPU_FAMILY=64 ++CONFIG_X86_DEBUGCTLMSR=y ++# CONFIG_PROCESSOR_SELECT is not set ++CONFIG_CPU_SUP_INTEL=y ++CONFIG_CPU_SUP_AMD=y ++CONFIG_CPU_SUP_CENTAUR=y ++CONFIG_HPET_TIMER=y ++CONFIG_HPET_EMULATE_RTC=y ++CONFIG_DMI=y ++CONFIG_GART_IOMMU=y ++CONFIG_CALGARY_IOMMU=y ++CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y ++CONFIG_SWIOTLB=y ++CONFIG_IOMMU_HELPER=y ++# CONFIG_MAXSMP is not set ++CONFIG_NR_CPUS=512 ++CONFIG_SCHED_SMT=y ++CONFIG_SCHED_MC=y ++# CONFIG_IRQ_TIME_ACCOUNTING is not set ++# CONFIG_PREEMPT_NONE is not set ++CONFIG_PREEMPT_VOLUNTARY=y ++# CONFIG_PREEMPT is not set ++CONFIG_X86_LOCAL_APIC=y ++CONFIG_X86_IO_APIC=y ++CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y ++CONFIG_X86_MCE=y ++CONFIG_X86_MCE_INTEL=y ++CONFIG_X86_MCE_AMD=y ++CONFIG_X86_MCE_THRESHOLD=y ++CONFIG_X86_MCE_INJECT=m ++CONFIG_X86_THERMAL_VECTOR=y ++CONFIG_X86_16BIT=y ++CONFIG_X86_ESPFIX64=y ++CONFIG_I8K=m ++CONFIG_MICROCODE=m ++CONFIG_MICROCODE_INTEL=y ++CONFIG_MICROCODE_AMD=y ++CONFIG_MICROCODE_OLD_INTERFACE=y ++CONFIG_X86_MSR=m ++CONFIG_X86_CPUID=m ++CONFIG_ARCH_PHYS_ADDR_T_64BIT=y ++CONFIG_ARCH_DMA_ADDR_T_64BIT=y ++CONFIG_DIRECT_GBPAGES=y ++# CONFIG_NUMA is not set ++CONFIG_ARCH_SPARSEMEM_ENABLE=y ++CONFIG_ARCH_SPARSEMEM_DEFAULT=y ++CONFIG_ARCH_SELECT_MEMORY_MODEL=y ++CONFIG_ARCH_PROC_KCORE_TEXT=y ++CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 ++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_ALLOC_MEM_MAP_TOGETHER=y ++CONFIG_SPARSEMEM_VMEMMAP=y ++CONFIG_HAVE_MEMBLOCK=y ++# CONFIG_MEMORY_HOTPLUG is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++CONFIG_PHYS_ADDR_T_64BIT=y ++CONFIG_ZONE_DMA_FLAG=1 ++CONFIG_BOUNCE=y ++CONFIG_VIRT_TO_BUS=y ++CONFIG_MMU_NOTIFIER=y ++CONFIG_KSM=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 ++CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y ++CONFIG_MEMORY_FAILURE=y ++CONFIG_HWPOISON_INJECT=m ++CONFIG_TRANSPARENT_HUGEPAGE=y ++# CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS is not set ++CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y ++# CONFIG_CLEANCACHE is not set ++# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set ++CONFIG_X86_RESERVE_LOW=64 ++CONFIG_MTRR=y ++# CONFIG_MTRR_SANITIZER is not set ++# CONFIG_X86_PAT is not set ++CONFIG_ARCH_RANDOM=y ++# CONFIG_EFI is not set ++CONFIG_SECCOMP=y ++CONFIG_CC_STACKPROTECTOR=y ++# 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=y ++CONFIG_KEXEC=y ++# CONFIG_CRASH_DUMP is not set ++CONFIG_PHYSICAL_START=0x1000000 ++CONFIG_RELOCATABLE=y ++CONFIG_PHYSICAL_ALIGN=0x1000000 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_COMPAT_VDSO is not set ++# CONFIG_CMDLINE_BOOL is not set ++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y ++ ++# ++# Power management and ACPI options ++# ++# CONFIG_SUSPEND is not set ++# CONFIG_HIBERNATION is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_ACPI=y ++# CONFIG_ACPI_PROCFS is not set ++# CONFIG_ACPI_PROCFS_POWER is not set ++# CONFIG_ACPI_EC_DEBUGFS is not set ++# CONFIG_ACPI_PROC_EVENT is not set ++# CONFIG_ACPI_AC is not set ++# CONFIG_ACPI_BATTERY is not set ++CONFIG_ACPI_BUTTON=y ++CONFIG_ACPI_FAN=y ++# CONFIG_ACPI_DOCK is not set ++CONFIG_ACPI_PROCESSOR=y ++CONFIG_ACPI_HOTPLUG_CPU=y ++# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set ++# CONFIG_ACPI_THERMAL is not set ++# CONFIG_ACPI_CUSTOM_DSDT is not set ++CONFIG_ACPI_BLACKLIST_YEAR=0 ++# CONFIG_ACPI_DEBUG is not set ++# CONFIG_ACPI_PCI_SLOT is not set ++CONFIG_X86_PM_TIMER=y ++CONFIG_ACPI_CONTAINER=y ++# CONFIG_ACPI_SBS is not set ++# CONFIG_ACPI_HED is not set ++# CONFIG_ACPI_CUSTOM_METHOD is not set ++# CONFIG_ACPI_APEI is not set ++# CONFIG_SFI is not set ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_TABLE=y ++CONFIG_CPU_FREQ_STAT=m ++# 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=m ++CONFIG_CPU_FREQ_GOV_USERSPACE=m ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m ++ ++# ++# x86 CPU frequency scaling drivers ++# ++# CONFIG_X86_PCC_CPUFREQ is not set ++# CONFIG_X86_ACPI_CPUFREQ is not set ++# CONFIG_X86_POWERNOW_K8 is not set ++# CONFIG_X86_SPEEDSTEP_CENTRINO is not set ++CONFIG_X86_P4_CLOCKMOD=m ++ ++# ++# shared options ++# ++CONFIG_X86_SPEEDSTEP_LIB=m ++CONFIG_CPU_IDLE=y ++CONFIG_CPU_IDLE_GOV_LADDER=y ++CONFIG_CPU_IDLE_GOV_MENU=y ++# CONFIG_INTEL_IDLE is not set ++ ++# ++# Memory power savings ++# ++# CONFIG_I7300_IDLE is not set ++ ++# ++# Bus options (PCI etc.) ++# ++CONFIG_PCI=y ++CONFIG_PCI_DIRECT=y ++CONFIG_PCI_MMCONFIG=y ++CONFIG_PCI_DOMAINS=y ++# CONFIG_PCI_CNB20LE_QUIRK is not set ++# CONFIG_PCIEPORTBUS is not set ++CONFIG_ARCH_SUPPORTS_MSI=y ++CONFIG_PCI_MSI=y ++# CONFIG_PCI_DEBUG is not set ++CONFIG_PCI_STUB=m ++CONFIG_HT_IRQ=y ++CONFIG_PCI_ATS=y ++CONFIG_PCI_IOV=y ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++CONFIG_PCI_IOAPIC=y ++CONFIG_PCI_LABEL=y ++CONFIG_ISA_DMA_API=y ++CONFIG_AMD_NB=y ++# CONFIG_PCCARD is not set ++# CONFIG_HOTPLUG_PCI is not set ++# CONFIG_RAPIDIO is not set ++ ++# ++# Executable file formats / Emulations ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_COMPAT_BINFMT_ELF=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++# CONFIG_HAVE_AOUT is not set ++CONFIG_BINFMT_MISC=m ++CONFIG_IA32_EMULATION=y ++CONFIG_IA32_AOUT=y ++CONFIG_COMPAT=y ++CONFIG_COMPAT_FOR_U64_ALIGNMENT=y ++CONFIG_SYSVIPC_COMPAT=y ++CONFIG_KEYS_COMPAT=y ++CONFIG_HAVE_TEXT_POKE_SMP=y ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++CONFIG_XFRM_USER=m ++CONFIG_XFRM_SUB_POLICY=y ++CONFIG_XFRM_MIGRATE=y ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_XFRM_IPCOMP=m ++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=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_ROUTE_CLASSID=y ++# CONFIG_IP_PNP is not set ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_NET_IPGRE_BROADCAST=y ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_ARPD=y ++CONFIG_SYN_COOKIES=y ++# 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 is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++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_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_DEFAULT_CUBIC=y ++# CONFIG_DEFAULT_RENO is not set ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_TCP_MD5SIG=y ++CONFIG_IPV6=y ++CONFIG_IPV6_PRIVACY=y ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_IPV6_ROUTE_INFO=y ++CONFIG_IPV6_OPTIMISTIC_DAD=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_MIP6=m ++CONFIG_INET6_XFRM_TUNNEL=m ++CONFIG_INET6_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m ++CONFIG_IPV6_SIT=m ++CONFIG_IPV6_SIT_6RD=y ++CONFIG_IPV6_NDISC_NODETYPE=y ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++CONFIG_BRIDGE_NETFILTER=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_NETLINK=m ++CONFIG_NETFILTER_NETLINK_QUEUE=m ++CONFIG_NETFILTER_NETLINK_LOG=m ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_MARK=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++# CONFIG_NF_CT_PROTO_DCCP is not set ++CONFIG_NF_CT_PROTO_GRE=m ++# CONFIG_NF_CT_PROTO_SCTP is not set ++# CONFIG_NF_CT_PROTO_UDPLITE is not set ++# CONFIG_NF_CONNTRACK_AMANDA is not set ++CONFIG_NF_CONNTRACK_FTP=m ++# CONFIG_NF_CONNTRACK_H323 is not set ++# CONFIG_NF_CONNTRACK_IRC is not set ++CONFIG_NF_CONNTRACK_BROADCAST=m ++# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++# CONFIG_NF_CONNTRACK_SANE is not set ++# CONFIG_NF_CONNTRACK_SIP is not set ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++# CONFIG_NETFILTER_TPROXY is not set ++CONFIG_NETFILTER_XTABLES=y ++ ++# ++# Xtables combined modules ++# ++CONFIG_NETFILTER_XT_MARK=m ++CONFIG_NETFILTER_XT_CONNMARK=m ++ ++# ++# Xtables targets ++# ++CONFIG_NETFILTER_XT_TARGET_AUDIT=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++# CONFIG_NETFILTER_XT_TARGET_CT is not set ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HL=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_RATEEST=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set ++CONFIG_NETFILTER_XT_TARGET_ERSPAN=y ++CONFIG_NETFILTER_XT_TARGET_SPAN=y ++CONFIG_NETFILTER_XT_TARGET_POLICE=y ++CONFIG_NETFILTER_XT_TARGET_TRICOLORPOLICE=y ++CONFIG_NETFILTER_XT_TARGET_SETCLASS=y ++CONFIG_NETFILTER_XT_TARGET_SETQOS=y ++ ++# ++# Xtables matches ++# ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_HL=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SCTP=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++CONFIG_NF_DEFRAG_IPV4=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_NF_CONNTRACK_PROC_COMPAT=y ++# CONFIG_IP_NF_QUEUE is not set ++CONFIG_IP_NF_IPTABLES=y ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=y ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_TARGET_LOG=m ++CONFIG_IP_NF_TARGET_ULOG=m ++CONFIG_NF_NAT=m ++CONFIG_NF_NAT_NEEDED=y ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_NF_NAT_SNMP_BASIC=m ++CONFIG_NF_NAT_PROTO_GRE=m ++CONFIG_NF_NAT_FTP=m ++# CONFIG_NF_NAT_IRC is not set ++CONFIG_NF_NAT_TFTP=m ++# CONFIG_NF_NAT_AMANDA is not set ++CONFIG_NF_NAT_PPTP=m ++# CONFIG_NF_NAT_H323 is not set ++# CONFIG_NF_NAT_SIP is not set ++CONFIG_IP_NF_MANGLE=y ++# CONFIG_IP_NF_TARGET_CLUSTERIP is not set ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=y ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++ ++# ++# IPv6: Netfilter Configuration ++# ++CONFIG_NF_DEFRAG_IPV6=m ++CONFIG_NF_CONNTRACK_IPV6=m ++# CONFIG_IP6_NF_QUEUE is not set ++CONFIG_IP6_NF_IPTABLES=y ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_TARGET_LOG=m ++CONFIG_IP6_NF_FILTER=y ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=y ++CONFIG_IP6_NF_RAW=y ++CONFIG_BRIDGE_NF_EBTABLES=y ++# CONFIG_BRIDGE_EBT_BROUTE is not set ++CONFIG_BRIDGE_EBT_T_FILTER=y ++CONFIG_BRIDGE_EBT_T_NAT=y ++CONFIG_BRIDGE_EBT_802_3=m ++# CONFIG_BRIDGE_EBT_AMONG is not set ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++# CONFIG_BRIDGE_EBT_LIMIT is not set ++# CONFIG_BRIDGE_EBT_MARK is not set ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++# CONFIG_BRIDGE_EBT_STP is not set ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=y ++# CONFIG_BRIDGE_EBT_MARK_T is not set ++# CONFIG_BRIDGE_EBT_REDIRECT is not set ++CONFIG_BRIDGE_EBT_SNAT=y ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_ULOG=m ++# CONFIG_BRIDGE_EBT_NFLOG is not set ++CONFIG_BRIDGE_EBT_ERSPAN=y ++CONFIG_BRIDGE_EBT_SPAN=y ++CONFIG_BRIDGE_EBT_POLICE=y ++CONFIG_BRIDGE_EBT_TRICOLORPOLICE=y ++CONFIG_BRIDGE_EBT_SETCLASS=y ++# CONFIG_IP_DCCP is not set ++CONFIG_IP_SCTP=m ++# CONFIG_NET_SCTPPROBE is not set ++# CONFIG_SCTP_DBG_MSG is not set ++# CONFIG_SCTP_DBG_OBJCNT is not set ++# CONFIG_SCTP_HMAC_NONE is not set ++# CONFIG_SCTP_HMAC_SHA1 is not set ++CONFIG_SCTP_HMAC_MD5=y ++# CONFIG_RDS is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_L2TP is not set ++CONFIG_STP=y ++CONFIG_BRIDGE=y ++CONFIG_BRIDGE_IGMP_SNOOPING=y ++CONFIG_BRIDGE_VLAN_FILTERING=y ++# CONFIG_NET_DSA is not set ++CONFIG_VLAN_8021Q=m ++# CONFIG_VLAN_8021Q_GVRP is not set ++# CONFIG_VLAN_8021Q_MVRP is not set ++# CONFIG_DECNET is not set ++CONFIG_LLC=y ++CONFIG_LLC2=m ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_PHONET is not set ++# CONFIG_IEEE802154 is not set ++CONFIG_NET_SCHED=y ++ ++# ++# Queueing/Scheduling ++# ++# CONFIG_NET_SCH_CBQ is not set ++# CONFIG_NET_SCH_HTB is not set ++# CONFIG_NET_SCH_HFSC is not set ++# CONFIG_NET_SCH_PRIO is not set ++# CONFIG_NET_SCH_MULTIQ is not set ++# CONFIG_NET_SCH_RED is not set ++# CONFIG_NET_SCH_SFB is not set ++# CONFIG_NET_SCH_SFQ is not set ++# CONFIG_NET_SCH_TEQL is not set ++# CONFIG_NET_SCH_TBF is not set ++# CONFIG_NET_SCH_GRED is not set ++# CONFIG_NET_SCH_DSMARK is not set ++# CONFIG_NET_SCH_NETEM is not set ++# CONFIG_NET_SCH_DRR is not set ++# CONFIG_NET_SCH_MQPRIO is not set ++# CONFIG_NET_SCH_CHOKE is not set ++# CONFIG_NET_SCH_QFQ is not set ++# CONFIG_NET_SCH_CODEL is not set ++# CONFIG_NET_SCH_FQ_CODEL is not set ++ ++# ++# Classification ++# ++# CONFIG_NET_CLS_BASIC is not set ++# CONFIG_NET_CLS_TCINDEX is not set ++# CONFIG_NET_CLS_ROUTE4 is not set ++# CONFIG_NET_CLS_FW is not set ++# CONFIG_NET_CLS_U32 is not set ++# CONFIG_NET_CLS_RSVP is not set ++# CONFIG_NET_CLS_RSVP6 is not set ++# CONFIG_NET_CLS_FLOW is not set ++# CONFIG_NET_CLS_CGROUP is not set ++# CONFIG_NET_EMATCH is not set ++# CONFIG_NET_CLS_ACT is not set ++CONFIG_NET_SCH_FIFO=y ++CONFIG_DCB=y ++CONFIG_DNS_RESOLVER=y ++# CONFIG_BATMAN_ADV is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++ ++# ++# Network testing ++# ++CONFIG_NET_PKTGEN=m ++# CONFIG_NET_TCPPROBE is not set ++# CONFIG_NET_DROP_MONITOR 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_FIB_RULES=y ++# CONFIG_WIRELESS is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++CONFIG_NET_9P=m ++CONFIG_NET_9P_VIRTIO=m ++# CONFIG_NET_9P_DEBUG 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_PATH="" ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# 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_CONNECTOR is not set ++CONFIG_MTD=y ++# CONFIG_MTD_TESTS is not set ++# CONFIG_MTD_REDBOOT_PARTS is not set ++# CONFIG_MTD_CMDLINE_PARTS is not set ++# CONFIG_MTD_AR7_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++# CONFIG_MTD_BLOCK is not set ++# CONFIG_MTD_BLOCK_RO is not set ++# 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 ++ ++# ++# 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_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_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++# CONFIG_MTD_DOCG3 is not set ++# CONFIG_MTD_NAND is not set ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR flash memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_RESERVE=1 ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_DEBUG is not set ++# CONFIG_PARPORT is not set ++CONFIG_PNP=y ++CONFIG_PNP_DEBUG_MESSAGES=y ++ ++# ++# Protocols ++# ++CONFIG_PNPACPI=y ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_FD is not set ++# CONFIG_BLK_CPQ_DA 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=m ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++ ++# ++# DRBD disabled because PROC_FS, INET or CONNECTOR not selected ++# ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++# CONFIG_BLK_DEV_UB 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_VIRTIO_BLK=y ++# CONFIG_BLK_DEV_HD is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_SENSORS_LIS3LV02D is not set ++CONFIG_MISC_DEVICES=y ++CONFIG_AD525X_DPOT=m ++CONFIG_AD525X_DPOT_I2C=m ++# CONFIG_IBM_ASM 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_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_VMWARE_BALLOON is not set ++# CONFIG_BMP085 is not set ++# CONFIG_PCH_PHUB is not set ++# CONFIG_USB_SWITCH_FSA9480 is not set ++CONFIG_EARLY_DMA_ALLOC=y ++CONFIG_EDA_DEF_SIZE=0x04000000 ++CONFIG_EDA_DEF_ALIGN=0x00100000 ++# CONFIG_DS100DF410 is not set ++# CONFIG_C2PORT is not set ++ ++# ++# EEPROM support ++# ++CONFIG_EEPROM_CLASS=m ++CONFIG_EEPROM_AT24=m ++# CONFIG_EEPROM_LEGACY is not set ++# CONFIG_EEPROM_MAX6875 is not set ++# CONFIG_EEPROM_93CX6 is not set ++CONFIG_EEPROM_SFF_8436=m ++# CONFIG_CB710_CORE is not set ++# CONFIG_IWMC3200TOP 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 ++CONFIG_HAVE_IDE=y ++CONFIG_IDE=y ++ ++# ++# Please see Documentation/ide/ide.txt for help/info on IDE drives ++# ++# CONFIG_BLK_DEV_IDE_SATA is not set ++CONFIG_IDE_GD=y ++CONFIG_IDE_GD_ATA=y ++# CONFIG_IDE_GD_ATAPI is not set ++# CONFIG_BLK_DEV_IDECD is not set ++# CONFIG_BLK_DEV_IDETAPE is not set ++# CONFIG_BLK_DEV_IDEACPI is not set ++# CONFIG_IDE_TASK_IOCTL is not set ++CONFIG_IDE_PROC_FS=y ++ ++# ++# IDE chipset support/bugfixes ++# ++# CONFIG_IDE_GENERIC is not set ++# CONFIG_BLK_DEV_PLATFORM is not set ++# CONFIG_BLK_DEV_CMD640 is not set ++# CONFIG_BLK_DEV_IDEPNP is not set ++ ++# ++# PCI IDE chipsets support ++# ++# CONFIG_BLK_DEV_GENERIC is not set ++# CONFIG_BLK_DEV_OPTI621 is not set ++# CONFIG_BLK_DEV_RZ1000 is not set ++# CONFIG_BLK_DEV_AEC62XX is not set ++# CONFIG_BLK_DEV_ALI15X3 is not set ++# CONFIG_BLK_DEV_AMD74XX is not set ++# CONFIG_BLK_DEV_ATIIXP is not set ++# CONFIG_BLK_DEV_CMD64X is not set ++# CONFIG_BLK_DEV_TRIFLEX is not set ++# CONFIG_BLK_DEV_CS5520 is not set ++# CONFIG_BLK_DEV_CS5530 is not set ++# CONFIG_BLK_DEV_HPT366 is not set ++# CONFIG_BLK_DEV_JMICRON is not set ++# CONFIG_BLK_DEV_SC1200 is not set ++# CONFIG_BLK_DEV_PIIX is not set ++# CONFIG_BLK_DEV_IT8172 is not set ++# CONFIG_BLK_DEV_IT8213 is not set ++# CONFIG_BLK_DEV_IT821X is not set ++# CONFIG_BLK_DEV_NS87415 is not set ++# CONFIG_BLK_DEV_PDC202XX_OLD is not set ++# CONFIG_BLK_DEV_PDC202XX_NEW is not set ++# CONFIG_BLK_DEV_SVWKS is not set ++# CONFIG_BLK_DEV_SIIMAGE is not set ++# CONFIG_BLK_DEV_SIS5513 is not set ++# CONFIG_BLK_DEV_SLC90E66 is not set ++# CONFIG_BLK_DEV_TRM290 is not set ++# CONFIG_BLK_DEV_VIA82CXXX is not set ++# CONFIG_BLK_DEV_TC86C001 is not set ++# CONFIG_BLK_DEV_IDEDMA 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_TGT is not set ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_PROC_FS is not set ++ ++# ++# 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=y ++CONFIG_CHR_DEV_SG=y ++# CONFIG_CHR_DEV_SCH is not set ++CONFIG_SCSI_MULTI_LUN=y ++CONFIG_SCSI_CONSTANTS=y ++CONFIG_SCSI_LOGGING=y ++# CONFIG_SCSI_SCAN_ASYNC is not set ++CONFIG_SCSI_WAIT_SCAN=m ++ ++# ++# 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=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_ATA_ACPI=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++CONFIG_SATA_AHCI=y ++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=y ++ ++# ++# SFF controllers with custom DMA interface ++# ++# CONFIG_PDC_ADMA is not set ++# CONFIG_SATA_QSTOR is not set ++# CONFIG_SATA_SX4 is not set ++CONFIG_ATA_BMDMA=y ++ ++# ++# SATA SFF controllers with BMDMA ++# ++CONFIG_ATA_PIIX=y ++# CONFIG_SATA_MV is not set ++# CONFIG_SATA_NV is not set ++# CONFIG_SATA_PROMISE is not set ++# CONFIG_SATA_SIL is not set ++# CONFIG_SATA_SIS is not set ++# CONFIG_SATA_SVW is not set ++# CONFIG_SATA_ULI is not set ++# CONFIG_SATA_VIA is not set ++# CONFIG_SATA_VITESSE is not set ++ ++# ++# PATA SFF controllers with BMDMA ++# ++# CONFIG_PATA_ALI is not set ++# CONFIG_PATA_AMD is not set ++# CONFIG_PATA_ARTOP is not set ++# CONFIG_PATA_ATIIXP is not set ++# CONFIG_PATA_ATP867X is not set ++# CONFIG_PATA_CMD64X is not set ++# CONFIG_PATA_CS5520 is not set ++# CONFIG_PATA_CS5530 is not set ++# CONFIG_PATA_CS5536 is not set ++# CONFIG_PATA_CYPRESS is not set ++# CONFIG_PATA_EFAR is not set ++# CONFIG_PATA_HPT366 is not set ++# CONFIG_PATA_HPT37X is not set ++# CONFIG_PATA_HPT3X2N is not set ++# CONFIG_PATA_HPT3X3 is not set ++# CONFIG_PATA_IT8213 is not set ++# CONFIG_PATA_IT821X is not set ++# CONFIG_PATA_JMICRON is not set ++# CONFIG_PATA_MARVELL is not set ++# CONFIG_PATA_NETCELL is not set ++# CONFIG_PATA_NINJA32 is not set ++# CONFIG_PATA_NS87415 is not set ++# CONFIG_PATA_OLDPIIX is not set ++# CONFIG_PATA_OPTIDMA is not set ++# CONFIG_PATA_PDC2027X is not set ++# CONFIG_PATA_PDC_OLD is not set ++# CONFIG_PATA_RADISYS is not set ++# CONFIG_PATA_RDC is not set ++# CONFIG_PATA_SC1200 is not set ++# CONFIG_PATA_SCH is not set ++# CONFIG_PATA_SERVERWORKS is not set ++# CONFIG_PATA_SIL680 is not set ++# CONFIG_PATA_SIS is not set ++# CONFIG_PATA_TOSHIBA is not set ++# CONFIG_PATA_TRIFLEX is not set ++# CONFIG_PATA_VIA is not set ++# CONFIG_PATA_WINBOND is not set ++ ++# ++# PIO-only SFF controllers ++# ++# CONFIG_PATA_CMD640_PCI is not set ++# CONFIG_PATA_MPIIX is not set ++# CONFIG_PATA_NS87410 is not set ++# CONFIG_PATA_OPTI is not set ++# CONFIG_PATA_PLATFORM is not set ++# CONFIG_PATA_RZ1000 is not set ++ ++# ++# Generic fallback / legacy drivers ++# ++# CONFIG_PATA_ACPI is not set ++CONFIG_ATA_GENERIC=y ++# CONFIG_PATA_LEGACY is not set ++CONFIG_MD=y ++CONFIG_BLK_DEV_MD=m ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_MD_RAID1=m ++CONFIG_MD_RAID10=m ++CONFIG_MD_RAID456=m ++# CONFIG_MULTICORE_RAID456 is not set ++# CONFIG_MD_MULTIPATH is not set ++# CONFIG_MD_FAULTY is not set ++CONFIG_BLK_DEV_DM_BUILTIN=y ++CONFIG_BLK_DEV_DM=m ++# CONFIG_DM_DEBUG is not set ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++# CONFIG_DM_THIN_PROVISIONING is not set ++CONFIG_DM_MIRROR=m ++CONFIG_DM_RAID=m ++# CONFIG_DM_LOG_USERSPACE is not set ++CONFIG_DM_ZERO=m ++# CONFIG_DM_MULTIPATH is not set ++# CONFIG_DM_DELAY is not set ++# CONFIG_DM_UEVENT is not set ++# CONFIG_DM_FLAKEY 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_MACINTOSH_DRIVERS is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++CONFIG_BONDING=y ++CONFIG_DUMMY=m ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC is not set ++CONFIG_MII=y ++CONFIG_MACVLAN=m ++# CONFIG_MACVTAP is not set ++CONFIG_VXLAN=m ++# CONFIG_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++CONFIG_TUN=m ++CONFIG_VETH=y ++CONFIG_VIRTIO_NET=y ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++CONFIG_ETHERNET=y ++# CONFIG_NET_VENDOR_3COM is not set ++# CONFIG_NET_VENDOR_ADAPTEC is not set ++# CONFIG_NET_VENDOR_ALTEON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_VENDOR_ATHEROS 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_CISCO 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_HP is not set ++CONFIG_NET_VENDOR_INTEL=y ++# CONFIG_E100 is not set ++CONFIG_E1000=m ++CONFIG_E1000E=m ++# CONFIG_E1000E_PTP is not set ++CONFIG_IGB=m ++CONFIG_IGB_HWMON=y ++# CONFIG_IGB_PTP is not set ++# CONFIG_IGBVF is not set ++# CONFIG_IXGB is not set ++# CONFIG_IXGBE is not set ++# CONFIG_IXGBEVF is not set ++CONFIG_NET_VENDOR_I825XX=y ++# CONFIG_ZNET is not set ++# CONFIG_IP1000 is not set ++# CONFIG_JME is not set ++CONFIG_NET_VENDOR_MARVELL=y ++# CONFIG_SKGE is not set ++# CONFIG_SKY2 is not set ++# CONFIG_NET_VENDOR_MELLANOX is not set ++# CONFIG_NET_VENDOR_MICREL 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_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++CONFIG_R8169=y ++# CONFIG_NET_VENDOR_RDC 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_FDDI is not set ++# CONFIG_HIPPI is not set ++# CONFIG_NET_SB1000 is not set ++# CONFIG_PHYLIB is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++# CONFIG_TR is not set ++ ++# ++# USB Network Adapters ++# ++# 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_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_DPAA_ETH_USE_NDO_SELECT_QUEUE is not set ++# CONFIG_ISDN is not set ++# CONFIG_PHONE 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 ++ ++# ++# 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 is not set ++# 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_MATRIX 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_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_XTKBD 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=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_PCSPKR is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_ATLAS_BTNS 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 is not set ++# 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_I8042=y ++# CONFIG_SERIO_SERPORT is not set ++# CONFIG_SERIO_CT82C710 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_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++CONFIG_DEVPTS_MULTIPLE_INSTANCES=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_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_FIX_EARLYCON_MEM=y ++CONFIG_SERIAL_8250_PCI=y ++CONFIG_SERIAL_8250_PNP=y ++CONFIG_SERIAL_8250_NR_UARTS=32 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_MANY_PORTS=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++# CONFIG_SERIAL_8250_DETECT_IRQ is not set ++CONFIG_SERIAL_8250_RSA=y ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_MFD_HSU is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_PCH_UART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_VIRTIO_CONSOLE is not set ++# CONFIG_IPMI_HANDLER is not set ++# CONFIG_HW_RANDOM is not set ++CONFIG_NVRAM=m ++# CONFIG_R3964 is not set ++# CONFIG_APPLICOM is not set ++# CONFIG_MWAVE is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_HPET is not set ++# CONFIG_HANGCHECK_TIMER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_TELCLOCK is not set ++CONFIG_DEVPORT=y ++# CONFIG_RAMOOPS is not set ++CONFIG_I2C=m ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_MUX=m ++ ++# ++# Multiplexer I2C Chip support ++# ++CONFIG_I2C_MUX_GPIO=m ++CONFIG_I2C_MUX_PCA9541=m ++CONFIG_I2C_MUX_PCA954x=m ++# CONFIG_I2C_MUX_DNI_6448 is not set ++# CONFIG_I2C_MUX_QUANTA is not set ++CONFIG_I2C_HELPER_AUTO=y ++CONFIG_I2C_ALGOBIT=m ++ ++# ++# 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=m ++# CONFIG_I2C_AMD756_S4882 is not set ++CONFIG_I2C_AMD8111=m ++CONFIG_I2C_I801=m ++CONFIG_I2C_ISCH=m ++CONFIG_I2C_ISMT=m ++CONFIG_I2C_PIIX4=m ++# 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 ++ ++# ++# ACPI drivers ++# ++# CONFIG_I2C_SCMI is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++CONFIG_I2C_DESIGNWARE_CORE=m ++CONFIG_I2C_DESIGNWARE_PCI=m ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_INTEL_MID is not set ++# CONFIG_I2C_OCORES is not set ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_PXA_PCI is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_XILINX is not set ++# CONFIG_I2C_EG20T is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_DIOLAN_U2C is not set ++# CONFIG_I2C_PARPORT_LIGHT 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 is not set ++ ++# ++# PPS support ++# ++# CONFIG_PPS is not set ++ ++# ++# PPS generators support ++# ++ ++# ++# PTP clock support ++# ++ ++# ++# Enable Device Drivers -> PPS to see the PTP clock options. ++# ++CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_GPIOLIB=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_IT8761E is not set ++CONFIG_GPIO_SCH=m ++# CONFIG_GPIO_VX855 is not set ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX7300 is not set ++# CONFIG_GPIO_MAX732X is not set ++CONFIG_GPIO_PCA953X=m ++# CONFIG_GPIO_PCF857X is not set ++# CONFIG_GPIO_ADP5588 is not set ++ ++# ++# PCI GPIO expanders: ++# ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_LANGWELL is not set ++# CONFIG_GPIO_PCH is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_RDC321X is not set ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MCP23S08 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++CONFIG_HWMON=m ++CONFIG_HWMON_VID=m ++# CONFIG_HWMON_DEBUG_CHIP is not set ++ ++# ++# Native drivers ++# ++# CONFIG_SENSORS_ABITUGURU is not set ++# CONFIG_SENSORS_ABITUGURU3 is not set ++# CONFIG_SENSORS_AD7414 is not set ++# CONFIG_SENSORS_AD7418 is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1029 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ADT7411 is not set ++# CONFIG_SENSORS_ADT7462 is not set ++CONFIG_SENSORS_ADT7470=m ++# CONFIG_SENSORS_ADT7475 is not set ++# CONFIG_SENSORS_ASC7621 is not set ++# CONFIG_SENSORS_K8TEMP is not set ++CONFIG_SENSORS_K10TEMP=m ++# CONFIG_SENSORS_FAM15H_POWER is not set ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++# CONFIG_SENSORS_CY8CXX is not set ++CONFIG_SENSORS_CY8C3245R1=m ++# CONFIG_SENSORS_DS620 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_I5K_AMB is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_F71882FG is not set ++# CONFIG_SENSORS_F75375S is not set ++# CONFIG_SENSORS_FSCHMD is not set ++# CONFIG_SENSORS_G760A is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_GPIO_FAN is not set ++CONFIG_SENSORS_CORETEMP=m ++# CONFIG_SENSORS_IT87 is not set ++CONFIG_SENSORS_JC42=m ++# CONFIG_SENSORS_LINEAGE is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM73 is not set ++CONFIG_SENSORS_LM75=m ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_LM93 is not set ++# CONFIG_SENSORS_LTC4151 is not set ++CONFIG_SENSORS_LTC4215=m ++# CONFIG_SENSORS_LTC4245 is not set ++# CONFIG_SENSORS_LTC4261 is not set ++# CONFIG_SENSORS_LM95241 is not set ++# CONFIG_SENSORS_LM95245 is not set ++# CONFIG_SENSORS_MAX16065 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_MAX1668 is not set ++# CONFIG_SENSORS_MAX6639 is not set ++# CONFIG_SENSORS_MAX6642 is not set ++# CONFIG_SENSORS_MAX6650 is not set ++CONFIG_SENSORS_MAX6620=m ++CONFIG_SENSORS_MAX6697=m ++# CONFIG_SENSORS_NTC_THERMISTOR is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PC87427 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++CONFIG_PMBUS=m ++CONFIG_SENSORS_PMBUS=m ++CONFIG_SENSORS_ADM1275=m ++CONFIG_SENSORS_LM25066=m ++CONFIG_SENSORS_LTC2978=m ++CONFIG_SENSORS_MAX16064=m ++CONFIG_SENSORS_MAX34440=m ++# CONFIG_SENSORS_MAX8688 is not set ++CONFIG_SENSORS_UCD9000=m ++CONFIG_SENSORS_UCD9200=m ++CONFIG_SENSORS_ZL6100=m ++CONFIG_SENSORS_DPS460=m ++CONFIG_SENSORS_PS2471=m ++CONFIG_SENSORS_CPR4011=m ++# CONFIG_SENSORS_SHT15 is not set ++# CONFIG_SENSORS_SHT21 is not set ++# CONFIG_SENSORS_SIS5595 is not set ++# CONFIG_SENSORS_SMM665 is not set ++# CONFIG_SENSORS_DME1737 is not set ++CONFIG_SENSORS_EMC1403=m ++# CONFIG_SENSORS_EMC2103 is not set ++CONFIG_SENSORS_EMC2305=m ++# CONFIG_SENSORS_EMC6W201 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47M192 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_SCH56XX_COMMON is not set ++# CONFIG_SENSORS_SCH5627 is not set ++# CONFIG_SENSORS_SCH5636 is not set ++# CONFIG_SENSORS_ADS1015 is not set ++# CONFIG_SENSORS_ADS7828 is not set ++# CONFIG_SENSORS_AMC6821 is not set ++# CONFIG_SENSORS_THMC50 is not set ++# CONFIG_SENSORS_TMP102 is not set ++# CONFIG_SENSORS_TMP401 is not set ++# CONFIG_SENSORS_TMP421 is not set ++# CONFIG_SENSORS_VIA_CPUTEMP is not set ++# CONFIG_SENSORS_VIA686A is not set ++# CONFIG_SENSORS_VT1211 is not set ++# CONFIG_SENSORS_VT8231 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83791D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83793 is not set ++# CONFIG_SENSORS_W83795 is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83L786NG is not set ++# CONFIG_SENSORS_W83627HF is not set ++CONFIG_SENSORS_W83627EHF=m ++# CONFIG_SENSORS_APPLESMC is not set ++ ++# ++# ACPI drivers ++# ++# CONFIG_SENSORS_ACPI_POWER is not set ++# CONFIG_SENSORS_ATK0110 is not set ++CONFIG_THERMAL=y ++CONFIG_WATCHDOG=y ++CONFIG_WATCHDOG_CORE=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++# CONFIG_ACQUIRE_WDT is not set ++# CONFIG_ADVANTECH_WDT is not set ++# CONFIG_ALIM1535_WDT is not set ++# CONFIG_ALIM7101_WDT is not set ++# CONFIG_F71808E_WDT is not set ++# CONFIG_SP5100_TCO is not set ++# CONFIG_SC520_WDT is not set ++# CONFIG_SBC_FITPC2_WATCHDOG is not set ++# CONFIG_EUROTECH_WDT is not set ++# CONFIG_IB700_WDT is not set ++# CONFIG_IBMASR is not set ++# CONFIG_WAFER_WDT is not set ++# CONFIG_I6300ESB_WDT is not set ++CONFIG_IE6XX_WDT=m ++CONFIG_ITCO_WDT=m ++# CONFIG_ITCO_VENDOR_SUPPORT is not set ++# CONFIG_IT8712F_WDT is not set ++# CONFIG_IT87_WDT is not set ++# CONFIG_HP_WATCHDOG is not set ++# CONFIG_SC1200_WDT is not set ++# CONFIG_PC87413_WDT is not set ++# CONFIG_NV_TCO is not set ++# CONFIG_60XX_WDT is not set ++# CONFIG_SBC8360_WDT is not set ++# CONFIG_CPU5_WDT is not set ++# CONFIG_SMSC_SCH311X_WDT is not set ++# CONFIG_SMSC37B787_WDT is not set ++# CONFIG_W83627HF_WDT is not set ++# CONFIG_W83697HF_WDT is not set ++# CONFIG_W83697UG_WDT is not set ++# CONFIG_W83877F_WDT is not set ++# CONFIG_W83977F_WDT is not set ++# CONFIG_MACHZ_WDT is not set ++# CONFIG_SBC_EPX_C3_WATCHDOG is not set ++ ++# ++# PCI-based Watchdog Cards ++# ++# CONFIG_PCIPCWATCHDOG is not set ++# CONFIG_WDTPCI is not set ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG 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_SM501 is not set ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_TPS6105X is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_TPS6507X is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_WM8400 is not set ++# CONFIG_MFD_PCF50633 is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_CS5535 is not set ++# CONFIG_MFD_TIMBERDALE is not set ++CONFIG_LPC_SCH=y ++# CONFIG_MFD_RDC321X is not set ++# CONFIG_MFD_JANZ_CMODIO is not set ++# CONFIG_MFD_VX855 is not set ++# CONFIG_MFD_WL1273_CORE is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_AGP is not set ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_VGA_SWITCHEROO is not set ++# CONFIG_DRM is not set ++# CONFIG_STUB_POULSBO is not set ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++# CONFIG_FB is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Display device support ++# ++# CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++CONFIG_VGA_CONSOLE=y ++# CONFIG_VGACON_SOFT_SCROLLBACK is not set ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_SOUND is not set ++# CONFIG_HID_SUPPORT is not set ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_COMMON=y ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB_ARCH_HAS_EHCI=y ++CONFIG_USB_ARCH_HAS_XHCI=y ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEVICEFS is not set ++CONFIG_USB_DEVICE_CLASS=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_DWC3 is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB 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=m ++# CONFIG_USB_XHCI_HCD_DEBUGGING 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_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_OHCI_HCD=y ++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set ++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set ++CONFIG_USB_OHCI_LITTLE_ENDIAN=y ++CONFIG_USB_UHCI_HCD=m ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_WHCI_HCD is not set ++# CONFIG_USB_HWA_HCD 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_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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_ISIGHTFW is not set ++# CONFIG_USB_YUREX is not set ++# CONFIG_USB_GADGET is not set ++ ++# ++# OTG and related infrastructure ++# ++# CONFIG_USB_GPIO_VBUS is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=m ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PCI=y ++# CONFIG_MMC_RICOH_MMC is not set ++# CONFIG_MMC_SDHCI_ACPI is not set ++# CONFIG_MMC_SDHCI_PLTFM is not set ++# CONFIG_MMC_WBSD is not set ++# CONFIG_MMC_TIFM_SD is not set ++# CONFIG_MMC_CB710 is not set ++# CONFIG_MMC_VIA_SDMMC is not set ++# CONFIG_MMC_VUB300 is not set ++CONFIG_MMC_USHC=m ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS 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=y ++CONFIG_RTC_HCTOSYS=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=m ++# CONFIG_RTC_DRV_DS1374 is not set ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_DS3232 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_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_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 ++# ++ ++# ++# Platform RTC drivers ++# ++CONFIG_RTC_DRV_CMOS=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_DS1742 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_DMADEVICES is not set ++# CONFIG_AUXDISPLAY is not set ++# CONFIG_UIO is not set ++CONFIG_VIRTIO=y ++CONFIG_VIRTIO_RING=y ++ ++# ++# Virtio drivers ++# ++CONFIG_VIRTIO_PCI=y ++CONFIG_VIRTIO_BALLOON=y ++# CONFIG_VIRTIO_MMIO is not set ++# CONFIG_STAGING is not set ++# CONFIG_X86_PLATFORM_DEVICES is not set ++ ++# ++# Hardware Spinlock drivers ++# ++CONFIG_CLKEVT_I8253=y ++CONFIG_I8253_LOCK=y ++CONFIG_CLKBLD_I8253=y ++CONFIG_IOMMU_SUPPORT=y ++# CONFIG_AMD_IOMMU is not set ++# CONFIG_INTEL_IOMMU is not set ++# CONFIG_IRQ_REMAP is not set ++# CONFIG_VIRT_DRIVERS is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++# CONFIG_HYPERV is not set ++# CONFIG_PM_DEVFREQ is not set ++ ++# ++# Frame Manager support ++# ++# CONFIG_FSL_FMAN is not set ++ ++# ++# Firmware Drivers ++# ++# CONFIG_EDD is not set ++CONFIG_FIRMWARE_MEMMAP=y ++# CONFIG_DELL_RBU is not set ++# CONFIG_DCDBAS is not set ++# CONFIG_DMIID is not set ++# CONFIG_DMI_SYSFS is not set ++# CONFIG_ISCSI_IBFT_FIND is not set ++# CONFIG_SIGMA is not set ++# CONFIG_GOOGLE_FIRMWARE is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++# CONFIG_EXT2_FS_XIP is not set ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_DEFAULTS_TO_ORDERED=y ++CONFIG_EXT3_FS_XATTR=y ++CONFIG_EXT3_FS_POSIX_ACL=y ++CONFIG_EXT3_FS_SECURITY=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_XATTR=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD=y ++# CONFIG_JBD_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_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_EXPORTFS=y ++CONFIG_FILE_LOCKING=y ++CONFIG_FSNOTIFY=y ++# CONFIG_DNOTIFY is not set ++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=y ++CONFIG_OVERLAYFS_FS=y ++# CONFIG_CUSE is not set ++CONFIG_GENERIC_ACL=y ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++# 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_KCORE=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_TMPFS_XATTR=y ++CONFIG_HUGETLBFS=y ++CONFIG_HUGETLB_PAGE=y ++# CONFIG_CONFIGFS_FS is not set ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_ECRYPT_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++# CONFIG_JFFS2_FS is not set ++# CONFIG_UBIFS_FS is not set ++# CONFIG_LOGFS is not set ++# CONFIG_CRAMFS is not set ++CONFIG_SQUASHFS=y ++# CONFIG_SQUASHFS_XATTR is not set ++# CONFIG_SQUASHFS_ZLIB 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_ROMFS_FS is not set ++# CONFIG_PSTORE is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_AUFS_FS=m ++CONFIG_AUFS_BRANCH_MAX_127=y ++# CONFIG_AUFS_BRANCH_MAX_511 is not set ++# CONFIG_AUFS_BRANCH_MAX_1023 is not set ++# CONFIG_AUFS_BRANCH_MAX_32767 is not set ++CONFIG_AUFS_SBILIST=y ++# CONFIG_AUFS_HNOTIFY is not set ++# CONFIG_AUFS_EXPORT is not set ++# CONFIG_AUFS_RDU is not set ++# CONFIG_AUFS_PROC_MAP is not set ++# CONFIG_AUFS_SP_IATTR is not set ++# CONFIG_AUFS_SHWH is not set ++# CONFIG_AUFS_BR_RAMFS is not set ++# CONFIG_AUFS_BR_FUSE is not set ++CONFIG_AUFS_BDEV_LOOP=y ++# CONFIG_AUFS_DEBUG is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++# CONFIG_NFS_V4_1 is not set ++# CONFIG_NFS_USE_LEGACY_DNS is not set ++CONFIG_NFS_USE_KERNEL_DNS=y ++# CONFIG_NFS_USE_NEW_IDMAPPER is not set ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=y ++# 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_9P_FS=m ++CONFIG_9P_FS_POSIX_ACL=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_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_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=m ++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_UTF8=y ++ ++# ++# Kernel hacking ++# ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_PRINTK_TIME=y ++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=2048 ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAGIC_SYSRQ_DEFAULT_MASK=0x1 ++CONFIG_STRIP_ASM_SYMS=y ++CONFIG_UNUSED_SYMBOLS=y ++CONFIG_DEBUG_FS=y ++CONFIG_HEADERS_CHECK=y ++CONFIG_DEBUG_SECTION_MISMATCH=y ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_SHIRQ is not set ++CONFIG_LOCKUP_DETECTOR=y ++CONFIG_HARDLOCKUP_DETECTOR=y ++CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y ++CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=1 ++# 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_PANIC_TIMEOUT=5 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++CONFIG_TIMER_STATS=y ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_DEBUG_SLAB is not set ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_RT_MUTEX_TESTER is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_SPARSE_RCU_POINTER 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_STACKTRACE=y ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_INFO=y ++# CONFIG_DEBUG_INFO_REDUCED is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_VIRTUAL is not set ++# CONFIG_DEBUG_WRITECOUNT is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++CONFIG_ARCH_WANT_FRAME_POINTERS=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_KPROBES_SANITY_TEST is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_LKDTM is not set ++# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP is not set ++# CONFIG_SYSCTL_SYSCALL_CHECK is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++CONFIG_USER_STACKTRACE_SUPPORT=y ++CONFIG_NOP_TRACER=y ++CONFIG_HAVE_FUNCTION_TRACER=y ++CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y ++CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y ++CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y ++CONFIG_HAVE_DYNAMIC_FTRACE=y ++CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y ++CONFIG_HAVE_SYSCALL_TRACEPOINTS=y ++CONFIG_HAVE_C_RECORDMCOUNT=y ++CONFIG_RING_BUFFER=y ++CONFIG_EVENT_TRACING=y ++CONFIG_EVENT_POWER_TRACING_DEPRECATED=y ++CONFIG_CONTEXT_SWITCH_TRACER=y ++CONFIG_RING_BUFFER_ALLOW_SWAP=y ++CONFIG_TRACING=y ++CONFIG_GENERIC_TRACER=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_FTRACE_SYSCALLS 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=y ++# CONFIG_KPROBE_EVENT is not set ++# CONFIG_FTRACE_STARTUP_TEST is not set ++# CONFIG_MMIOTRACE is not set ++# CONFIG_RING_BUFFER_BENCHMARK is not set ++# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set ++# CONFIG_BUILD_DOCSRC is not set ++CONFIG_DYNAMIC_DEBUG=y ++# CONFIG_DMA_API_DEBUG is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_ASYNC_RAID6_TEST is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++CONFIG_HAVE_ARCH_KMEMCHECK=y ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_STRICT_DEVMEM is not set ++# CONFIG_X86_VERBOSE_BOOTUP is not set ++# CONFIG_EARLY_PRINTK is not set ++# CONFIG_DEBUG_STACKOVERFLOW is not set ++# CONFIG_X86_PTDUMP is not set ++CONFIG_DEBUG_RODATA=y ++# CONFIG_DEBUG_RODATA_TEST is not set ++CONFIG_DEBUG_SET_MODULE_RONX=y ++# CONFIG_DEBUG_NX_TEST is not set ++# CONFIG_IOMMU_DEBUG is not set ++# CONFIG_IOMMU_STRESS is not set ++CONFIG_HAVE_MMIOTRACE_SUPPORT=y ++# CONFIG_X86_DECODER_SELFTEST is not set ++CONFIG_IO_DELAY_TYPE_0X80=0 ++CONFIG_IO_DELAY_TYPE_0XED=1 ++CONFIG_IO_DELAY_TYPE_UDELAY=2 ++CONFIG_IO_DELAY_TYPE_NONE=3 ++CONFIG_IO_DELAY_0X80=y ++# CONFIG_IO_DELAY_0XED is not set ++# CONFIG_IO_DELAY_UDELAY is not set ++# CONFIG_IO_DELAY_NONE is not set ++CONFIG_DEFAULT_IO_DELAY_TYPE=0 ++# CONFIG_DEBUG_BOOT_PARAMS is not set ++# CONFIG_CPA_DEBUG is not set ++CONFIG_OPTIMIZE_INLINING=y ++# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set ++ ++# ++# Security options ++# ++CONFIG_KEYS=y ++# CONFIG_ENCRYPTED_KEYS is not set ++# CONFIG_KEYS_DEBUG_PROC_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_XOR_BLOCKS=m ++CONFIG_ASYNC_CORE=m ++CONFIG_ASYNC_MEMCPY=m ++CONFIG_ASYNC_XOR=m ++CONFIG_ASYNC_PQ=m ++CONFIG_ASYNC_RAID6_RECOV=m ++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_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++CONFIG_CRYPTO_WORKQUEUE=y ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=m ++# 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=m ++# 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_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=m ++CONFIG_CRYPTO_CRC32C_INTEL=m ++# CONFIG_CRYPTO_GHASH 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=m ++# CONFIG_CRYPTO_SHA1_SSSE3 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 ++# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=m ++CONFIG_CRYPTO_AES_X86_64=m ++# CONFIG_CRYPTO_AES_NI_INTEL is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_BLOWFISH_X86_64 is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=m ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SALSA20_X86_64 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 ++# CONFIG_CRYPTO_TWOFISH_X86_64 is not set ++# CONFIG_CRYPTO_TWOFISH_X86_64_3WAY is not set ++ ++# ++# Compression ++# ++CONFIG_CRYPTO_DEFLATE=m ++# CONFIG_CRYPTO_ZLIB is not set ++# CONFIG_CRYPTO_LZO is not set ++ ++# ++# Random Number Generation ++# ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_HW is not set ++CONFIG_HAVE_KVM=y ++CONFIG_HAVE_KVM_IRQCHIP=y ++CONFIG_HAVE_KVM_EVENTFD=y ++CONFIG_KVM_APIC_ARCHITECTURE=y ++CONFIG_KVM_MMIO=y ++CONFIG_KVM_ASYNC_PF=y ++CONFIG_VIRTUALIZATION=y ++CONFIG_KVM=m ++CONFIG_KVM_INTEL=m ++CONFIG_KVM_AMD=m ++# CONFIG_KVM_MMU_AUDIT is not set ++CONFIG_VHOST_NET=m ++CONFIG_BINARY_PRINTF=y ++ ++# ++# Library routines ++# ++CONFIG_RAID6_PQ=m ++CONFIG_BITREVERSE=y ++CONFIG_GENERIC_FIND_FIRST_BIT=y ++# CONFIG_CRC_CCITT is not set ++CONFIG_CRC16=y ++CONFIG_CRC_T10DIF=y ++# CONFIG_CRC_ITU_T is not set ++CONFIG_CRC32=y ++# CONFIG_CRC7 is not set ++CONFIG_LIBCRC32C=m ++# CONFIG_CRC8 is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=m ++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_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_TEXTSEARCH=y ++CONFIG_TEXTSEARCH_KMP=m ++CONFIG_TEXTSEARCH_BM=m ++CONFIG_TEXTSEARCH_FSM=m ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y ++CONFIG_CHECK_SIGNATURE=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set +diff --git a/debian/config/amd64/defines b/debian/config/amd64/defines +new file mode 100644 +index 0000000..6d1b390 +--- /dev/null ++++ b/debian/config/amd64/defines +@@ -0,0 +1,21 @@ ++[abi] ++ignore-changes: ++# Only for use by the vendor-specific KVM modules ++ module:arch/x86/kvm/kvm ++ ++[base] ++featuresets: ++ none ++kernel-arch: x86 ++ ++[build] ++debug-info: true ++ ++[image] ++bootloaders: grub-pc extlinux lilo ++configs: ++ amd64/config-cumulus ++ ++[amd64_description] ++hardware: 64-bit PCs ++hardware-long: PCs with AMD64, Intel 64 or VIA Nano processors +diff --git a/debian/config/amd64/none/defines b/debian/config/amd64/none/defines +new file mode 100644 +index 0000000..090dc41 +--- /dev/null ++++ b/debian/config/amd64/none/defines +@@ -0,0 +1,3 @@ ++[base] ++flavours: ++ amd64 +diff --git a/debian/config/armel/config b/debian/config/armel/config +new file mode 100644 +index 0000000..3cf7e9e +--- /dev/null ++++ b/debian/config/armel/config +@@ -0,0 +1,116 @@ ++## ++## file: arch/arm/Kconfig ++## ++CONFIG_MMU=y ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++ ++## ++## file: arch/arm/Kconfig.debug ++## ++CONFIG_DEBUG_LL=y ++CONFIG_EARLY_PRINTK=y ++ ++## ++## file: arch/arm/mm/Kconfig ++## ++#. Support Thumb user binaries ++CONFIG_ARM_THUMB=y ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_UINPUT=m ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=m ++CONFIG_MOUSE_APPLETOUCH=m ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_TOUCHSCREEN_EETI is not set ++ ++## ++## file: drivers/net/hamradio/Kconfig ++## ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_BAYCOM_PAR=m ++CONFIG_BAYCOM_EPP=m ++CONFIG_YAM=m ++ ++## ++## file: drivers/net/wireless/ipw2x00/Kconfig ++## ++# CONFIG_IPW2100 is not set ++ ++## ++## file: drivers/parport/Kconfig ++## ++#. Causes lockups on ARM (see #588164) ++# CONFIG_PARPORT_PC is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX_OLD is not set ++# CONFIG_SCSI_HPTIOP is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic79xx ++## ++# CONFIG_SCSI_AIC79XX is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++# CONFIG_SCSI_AIC7XXX is not set ++ ++## ++## file: drivers/scsi/aic94xx/Kconfig ++## ++# CONFIG_SCSI_AIC94XX is not set ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++# CONFIG_MEGARAID_SAS is not set ++ ++## ++## file: drivers/scsi/qla2xxx/Kconfig ++## ++# CONFIG_SCSI_QLA_FC is not set ++ ++## ++## file: drivers/scsi/qla4xxx/Kconfig ++## ++# CONFIG_SCSI_QLA_ISCSI is not set ++ ++## ++## file: init/Kconfig ++## ++## choice: Kernel compression mode ++# CONFIG_KERNEL_GZIP is not set ++# CONFIG_KERNEL_BZIP2 is not set ++CONFIG_KERNEL_LZMA=y ++## end choice ++ ++## ++## file: security/apparmor/Kconfig ++## ++# CONFIG_SECURITY_APPARMOR is not set ++ ++## ++## file: security/tomoyo/Kconfig ++## ++# CONFIG_SECURITY_TOMOYO is not set ++ +diff --git a/debian/config/armel/config-cumulus b/debian/config/armel/config-cumulus +new file mode 100644 +index 0000000..a5d297f +--- /dev/null ++++ b/debian/config/armel/config-cumulus +@@ -0,0 +1,2657 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.2.71 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_GENERIC_GPIO=y ++# CONFIG_ARCH_USES_GETTIMEOFFSET is not set ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++CONFIG_KTIME_SCALAR=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_ARCH_HAS_CPUFREQ=y ++CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_VECTORS_BASE=0xffff0000 ++CONFIG_ARM_PATCH_PHYS_VIRT=y ++CONFIG_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_HAVE_IRQ_WORK=y ++CONFIG_IRQ_WORK=y ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="arm" ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_HAVE_KERNEL_GZIP=y ++CONFIG_HAVE_KERNEL_LZMA=y ++CONFIG_HAVE_KERNEL_LZO=y ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_LZO is not set ++CONFIG_DEFAULT_HOSTNAME="cumulus" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_POSIX_MQUEUE_SYSCTL=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_FHANDLE=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_AUDIT=y ++CONFIG_HAVE_GENERIC_HARDIRQS=y ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_HAVE_SPARSE_IRQ=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_IRQ_DOMAIN=y ++# CONFIG_SPARSE_IRQ is not set ++ ++# ++# RCU Subsystem ++# ++CONFIG_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_RCU_TRACE is not set ++CONFIG_RCU_FANOUT=32 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_TREE_RCU_TRACE is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=20 ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CPUSETS=y ++CONFIG_PROC_PID_CPUSET=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_RESOURCE_COUNTERS=y ++CONFIG_CGROUP_MEM_RES_CTLR=y ++CONFIG_CGROUP_MEM_RES_CTLR_DISABLED=y ++CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y ++# CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set ++CONFIG_CGROUP_PERF=y ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++CONFIG_RT_GROUP_SCHED=y ++CONFIG_BLK_CGROUP=y ++# CONFIG_DEBUG_BLK_CGROUP is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++CONFIG_USER_NS=y ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_MM_OWNER=y ++# 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=y ++# CONFIG_RD_LZO is not set ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_EXPERT=y ++CONFIG_UID16=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_HOTPLUG=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_SHMEM=y ++CONFIG_AIO=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++CONFIG_PERF_USE_VMALLOC=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_PERF_COUNTERS is not set ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_PCI_QUIRKS=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_SLAB=y ++# CONFIG_SLUB is not set ++# CONFIG_SLOB is not set ++CONFIG_PROFILING=y ++CONFIG_TRACEPOINTS=y ++CONFIG_OPROFILE=m ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_USE_GENERIC_SMP_HELPERS=y ++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y ++CONFIG_HAVE_CLK=y ++CONFIG_HAVE_DMA_API_DEBUG=y ++CONFIG_HAVE_HW_BREAKPOINT=y ++ ++# ++# GCOV-based kernel profiling ++# ++# CONFIG_GCOV_KERNEL is not set ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=y ++CONFIG_RT_MUTEXES=y ++CONFIG_BASE_SMALL=0 ++CONFIG_MODULES=y ++CONFIG_MODULE_FORCE_LOAD=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++CONFIG_BLK_DEV_BSGLIB=y ++CONFIG_BLK_DEV_INTEGRITY=y ++# CONFIG_BLK_DEV_THROTTLING is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq" ++# CONFIG_INLINE_SPIN_TRYLOCK is not set ++# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK is not set ++# CONFIG_INLINE_SPIN_LOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQ is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set ++CONFIG_INLINE_SPIN_UNLOCK=y ++# CONFIG_INLINE_SPIN_UNLOCK_BH is not set ++CONFIG_INLINE_SPIN_UNLOCK_IRQ=y ++# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_READ_TRYLOCK is not set ++# CONFIG_INLINE_READ_LOCK is not set ++# CONFIG_INLINE_READ_LOCK_BH is not set ++# CONFIG_INLINE_READ_LOCK_IRQ is not set ++# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set ++CONFIG_INLINE_READ_UNLOCK=y ++# CONFIG_INLINE_READ_UNLOCK_BH is not set ++CONFIG_INLINE_READ_UNLOCK_IRQ=y ++# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_WRITE_TRYLOCK is not set ++# CONFIG_INLINE_WRITE_LOCK is not set ++# CONFIG_INLINE_WRITE_LOCK_BH is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQ is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set ++CONFIG_INLINE_WRITE_UNLOCK=y ++# CONFIG_INLINE_WRITE_UNLOCK_BH is not set ++CONFIG_INLINE_WRITE_UNLOCK_IRQ=y ++# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set ++CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y ++CONFIG_MUTEX_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCMRING is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CNS3XXX is not set ++# CONFIG_ARCH_GEMINI is not set ++# CONFIG_ARCH_PRIMA2 is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_DOVE is not set ++# CONFIG_ARCH_KIRKWOOD is not set ++# CONFIG_ARCH_LPC32XX 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_TEGRA is not set ++# CONFIG_ARCH_PICOXCELL is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_MSM is not set ++# CONFIG_ARCH_SHMOBILE is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_S5P64X0 is not set ++# CONFIG_ARCH_S5PC100 is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_TCC_926 is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_VT8500 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARCH_IPROC=y ++CONFIG_BCM_ZRELADDR=0x61008000 ++# CONFIG_GPIO_PCA953X is not set ++ ++# ++# Broadcom IPROC architecture based implementations ++# ++# CONFIG_ARCH_NORTHSTAR is not set ++CONFIG_MACH_IPROC=y ++# CONFIG_IPROC_64K_PAGE is not set ++CONFIG_GP_TIMER_COMPARATOR_LOAD_DELAY=y ++CONFIG_IPROC_DCACHE_INVALIDATION=y ++# CONFIG_IPROC_TIMER_UNIT_TESTS is not set ++# CONFIG_IPROC_SW_RESET_RECORD is not set ++# CONFIG_BRCM_PROP_MODULES is not set ++# CONFIG_BCM_STM is not set ++CONFIG_BCM_PARAMS_PHYS=0x61000000 ++CONFIG_BCM_RAM_BASE=0x60000000 ++CONFIG_BCM_RAM_START_RESERVED_SIZE=0x200000 ++ ++# ++# iProc SoC based Machine types ++# ++# CONFIG_MACH_CYGNUS is not set ++# CONFIG_MACH_NS is not set ++# CONFIG_MACH_HX4 is not set ++# CONFIG_MACH_HR2 is not set ++# CONFIG_MACH_NSP is not set ++# CONFIG_MACH_KT2 is not set ++# CONFIG_MACH_GH is not set ++CONFIG_MACH_DNI_3448P=y ++CONFIG_MACH_ACCTON_AS4610_54=y ++# CONFIG_MACH_IPROC_EMULATION is not set ++ ++# ++# System MMU ++# ++ ++# ++# 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_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++# 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_OUTER_CACHE=y ++CONFIG_OUTER_CACHE_SYNC=y ++CONFIG_CACHE_L2X0=y ++CONFIG_CACHE_PL310=y ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_CPU_HAS_PMU=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_458693 is not set ++# CONFIG_ARM_ERRATA_460075 is not set ++# CONFIG_ARM_ERRATA_742230 is not set ++# CONFIG_ARM_ERRATA_742231 is not set ++# CONFIG_PL310_ERRATA_588369 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_PL310_ERRATA_727915 is not set ++# CONFIG_ARM_ERRATA_743622 is not set ++# CONFIG_ARM_ERRATA_751472 is not set ++# CONFIG_PL310_ERRATA_753970 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_PL310_ERRATA_769419 is not set ++CONFIG_ARM_GIC=y ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++CONFIG_PCI=y ++CONFIG_PCI_SYSCALL=y ++# CONFIG_ARCH_SUPPORTS_MSI is not set ++# CONFIG_PCI_DEBUG 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_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_TICK_ONESHOT=y ++# CONFIG_NO_HZ is not set ++# CONFIG_HIGH_RES_TIMERS is not set ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=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_TWD=y ++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 is not set ++CONFIG_LOCAL_TIMERS=y ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++CONFIG_HZ=100 ++# 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_HW_PERF_EVENTS=y ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++# CONFIG_COMPACTION is not set ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++CONFIG_VIRT_TO_BUS=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_CLEANCACHE 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_CC_STACKPROTECTOR is not set ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ZBOOT_ROM_TEXT=0 ++CONFIG_ZBOOT_ROM_BSS=0 ++# CONFIG_ARM_APPENDED_DTB is not set ++CONFIG_CMDLINE="console=ttyS0,115200n8 maxcpus=2 mem=700M" ++CONFIG_CMDLINE_FROM_BOOTLOADER=y ++# CONFIG_CMDLINE_EXTEND is not set ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_XIP_KERNEL is not set ++CONFIG_KEXEC=y ++CONFIG_ATAGS_PROC=y ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++# CONFIG_CPU_FREQ is not set ++CONFIG_CPU_IDLE=y ++CONFIG_CPU_IDLE_GOV_LADDER=y ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++# CONFIG_VFP is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Power management options ++# ++# CONFIG_SUSPEND is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++# CONFIG_ARM_CPU_SUSPEND is not set ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++CONFIG_XFRM_USER=m ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_XFRM_IPCOMP=m ++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=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++# CONFIG_IP_ROUTE_VERBOSE is not set ++CONFIG_IP_ROUTE_CLASSID=y ++# CONFIG_IP_PNP is not set ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_NET_IPGRE_BROADCAST=y ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_ARPD=y ++CONFIG_SYN_COOKIES=y ++# 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 is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++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_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_DEFAULT_CUBIC=y ++# CONFIG_DEFAULT_RENO is not set ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_TCP_MD5SIG=y ++CONFIG_IPV6=y ++CONFIG_IPV6_PRIVACY=y ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_IPV6_ROUTE_INFO=y ++CONFIG_IPV6_OPTIMISTIC_DAD=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_MIP6=m ++CONFIG_INET6_XFRM_TUNNEL=m ++CONFIG_INET6_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m ++CONFIG_IPV6_SIT=m ++CONFIG_IPV6_SIT_6RD=y ++CONFIG_IPV6_NDISC_NODETYPE=y ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++CONFIG_BRIDGE_NETFILTER=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_NETLINK=m ++CONFIG_NETFILTER_NETLINK_QUEUE=m ++CONFIG_NETFILTER_NETLINK_LOG=m ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_MARK=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++# CONFIG_NF_CT_PROTO_DCCP is not set ++CONFIG_NF_CT_PROTO_GRE=m ++# CONFIG_NF_CT_PROTO_SCTP is not set ++# CONFIG_NF_CT_PROTO_UDPLITE is not set ++# CONFIG_NF_CONNTRACK_AMANDA is not set ++CONFIG_NF_CONNTRACK_FTP=m ++# CONFIG_NF_CONNTRACK_H323 is not set ++# CONFIG_NF_CONNTRACK_IRC is not set ++CONFIG_NF_CONNTRACK_BROADCAST=m ++# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++# CONFIG_NF_CONNTRACK_SANE is not set ++# CONFIG_NF_CONNTRACK_SIP is not set ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++# CONFIG_NETFILTER_TPROXY is not set ++CONFIG_NETFILTER_XTABLES=y ++ ++# ++# Xtables combined modules ++# ++CONFIG_NETFILTER_XT_MARK=m ++CONFIG_NETFILTER_XT_CONNMARK=m ++ ++# ++# Xtables targets ++# ++CONFIG_NETFILTER_XT_TARGET_AUDIT=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++# CONFIG_NETFILTER_XT_TARGET_CT is not set ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HL=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_RATEEST=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set ++CONFIG_NETFILTER_XT_TARGET_ERSPAN=y ++CONFIG_NETFILTER_XT_TARGET_SPAN=y ++CONFIG_NETFILTER_XT_TARGET_POLICE=y ++CONFIG_NETFILTER_XT_TARGET_TRICOLORPOLICE=y ++CONFIG_NETFILTER_XT_TARGET_SETCLASS=y ++CONFIG_NETFILTER_XT_TARGET_SETQOS=y ++ ++# ++# Xtables matches ++# ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_HL=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SCTP=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++CONFIG_NF_DEFRAG_IPV4=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_NF_CONNTRACK_PROC_COMPAT=y ++# CONFIG_IP_NF_QUEUE is not set ++CONFIG_IP_NF_IPTABLES=y ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=y ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_TARGET_LOG=m ++CONFIG_IP_NF_TARGET_ULOG=m ++CONFIG_NF_NAT=m ++CONFIG_NF_NAT_NEEDED=y ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_NF_NAT_SNMP_BASIC=m ++CONFIG_NF_NAT_PROTO_GRE=m ++CONFIG_NF_NAT_FTP=m ++# CONFIG_NF_NAT_IRC is not set ++CONFIG_NF_NAT_TFTP=m ++# CONFIG_NF_NAT_AMANDA is not set ++CONFIG_NF_NAT_PPTP=m ++# CONFIG_NF_NAT_H323 is not set ++# CONFIG_NF_NAT_SIP is not set ++CONFIG_IP_NF_MANGLE=y ++# CONFIG_IP_NF_TARGET_CLUSTERIP is not set ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=y ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++ ++# ++# IPv6: Netfilter Configuration ++# ++CONFIG_NF_DEFRAG_IPV6=m ++CONFIG_NF_CONNTRACK_IPV6=m ++# CONFIG_IP6_NF_QUEUE is not set ++CONFIG_IP6_NF_IPTABLES=y ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_TARGET_LOG=m ++CONFIG_IP6_NF_FILTER=y ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=y ++CONFIG_IP6_NF_RAW=y ++CONFIG_BRIDGE_NF_EBTABLES=y ++# CONFIG_BRIDGE_EBT_BROUTE is not set ++CONFIG_BRIDGE_EBT_T_FILTER=y ++CONFIG_BRIDGE_EBT_T_NAT=y ++CONFIG_BRIDGE_EBT_802_3=m ++# CONFIG_BRIDGE_EBT_AMONG is not set ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++# CONFIG_BRIDGE_EBT_LIMIT is not set ++# CONFIG_BRIDGE_EBT_MARK is not set ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++# CONFIG_BRIDGE_EBT_STP is not set ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=y ++# CONFIG_BRIDGE_EBT_MARK_T is not set ++# CONFIG_BRIDGE_EBT_REDIRECT is not set ++CONFIG_BRIDGE_EBT_SNAT=y ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_ULOG=m ++# CONFIG_BRIDGE_EBT_NFLOG is not set ++CONFIG_BRIDGE_EBT_ERSPAN=y ++CONFIG_BRIDGE_EBT_SPAN=y ++CONFIG_BRIDGE_EBT_POLICE=y ++CONFIG_BRIDGE_EBT_TRICOLORPOLICE=y ++CONFIG_BRIDGE_EBT_SETCLASS=y ++# CONFIG_IP_DCCP is not set ++CONFIG_IP_SCTP=m ++# CONFIG_SCTP_DBG_MSG is not set ++# CONFIG_SCTP_DBG_OBJCNT is not set ++# CONFIG_SCTP_HMAC_NONE is not set ++# CONFIG_SCTP_HMAC_SHA1 is not set ++CONFIG_SCTP_HMAC_MD5=y ++# CONFIG_RDS is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_L2TP is not set ++CONFIG_STP=y ++CONFIG_BRIDGE=y ++CONFIG_BRIDGE_IGMP_SNOOPING=y ++CONFIG_BRIDGE_VLAN_FILTERING=y ++# CONFIG_NET_DSA is not set ++CONFIG_VLAN_8021Q=m ++# CONFIG_VLAN_8021Q_GVRP is not set ++# CONFIG_VLAN_8021Q_MVRP is not set ++# CONFIG_DECNET is not set ++CONFIG_LLC=y ++CONFIG_LLC2=m ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_PHONET is not set ++# CONFIG_IEEE802154 is not set ++CONFIG_NET_SCHED=y ++ ++# ++# Queueing/Scheduling ++# ++# CONFIG_NET_SCH_CBQ is not set ++# CONFIG_NET_SCH_HTB is not set ++# CONFIG_NET_SCH_HFSC is not set ++# CONFIG_NET_SCH_PRIO is not set ++# CONFIG_NET_SCH_MULTIQ is not set ++# CONFIG_NET_SCH_RED is not set ++# CONFIG_NET_SCH_SFB is not set ++# CONFIG_NET_SCH_SFQ is not set ++# CONFIG_NET_SCH_TEQL is not set ++# CONFIG_NET_SCH_TBF is not set ++# CONFIG_NET_SCH_GRED is not set ++# CONFIG_NET_SCH_DSMARK is not set ++# CONFIG_NET_SCH_NETEM is not set ++# CONFIG_NET_SCH_DRR is not set ++# CONFIG_NET_SCH_MQPRIO is not set ++# CONFIG_NET_SCH_CHOKE is not set ++# CONFIG_NET_SCH_QFQ is not set ++# CONFIG_NET_SCH_CODEL is not set ++# CONFIG_NET_SCH_FQ_CODEL is not set ++ ++# ++# Classification ++# ++# CONFIG_NET_CLS_BASIC is not set ++# CONFIG_NET_CLS_TCINDEX is not set ++# CONFIG_NET_CLS_ROUTE4 is not set ++# CONFIG_NET_CLS_FW is not set ++# CONFIG_NET_CLS_U32 is not set ++# CONFIG_NET_CLS_RSVP is not set ++# CONFIG_NET_CLS_RSVP6 is not set ++# CONFIG_NET_CLS_FLOW is not set ++# CONFIG_NET_CLS_CGROUP is not set ++# CONFIG_NET_EMATCH is not set ++# CONFIG_NET_CLS_ACT is not set ++CONFIG_NET_SCH_FIFO=y ++CONFIG_DCB=y ++CONFIG_DNS_RESOLVER=y ++# CONFIG_BATMAN_ADV is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++ ++# ++# Network testing ++# ++CONFIG_NET_PKTGEN=m ++# CONFIG_NET_DROP_MONITOR 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_FIB_RULES=y ++# 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_PATH="" ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# 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_CONNECTOR is not set ++CONFIG_MTD=y ++# CONFIG_MTD_TESTS is not set ++# CONFIG_MTD_REDBOOT_PARTS is not set ++# CONFIG_MTD_CMDLINE_PARTS is not set ++# 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_CHAR=y ++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 ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++CONFIG_MTD_CFI=y ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_GEN_PROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++# CONFIG_MTD_CFI_NOSWAP is not set ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++CONFIG_MTD_CFI_OF_BYTE_SWAP=y ++# CONFIG_MTD_CFI_GEOMETRY 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_OTP is not set ++CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_STAA=y ++CONFIG_MTD_CFI_UTIL=y ++# 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_PHYSMAP=y ++# CONFIG_MTD_PHYSMAP_COMPAT is not set ++# CONFIG_MTD_PHYSMAP_OF 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=y ++CONFIG_M25PXX_USE_FAST_READ=y ++# CONFIG_M25PXX_STAY_IN_3BYTE_MODE 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_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++# 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_VERIFY_WRITE is not set ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_MUSEUM_IDS is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO 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_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++CONFIG_MTD_NAND_PLATFORM=y ++# CONFIG_MTD_ALAUDA is not set ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR flash memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_RESERVE=1 ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_DEBUG is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++CONFIG_PROC_DEVICETREE=y ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_DEVICE=y ++CONFIG_OF_GPIO=y ++CONFIG_OF_I2C=y ++CONFIG_OF_NET=y ++CONFIG_OF_SPI=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_CPQ_DA 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=m ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++ ++# ++# DRBD disabled because PROC_FS, INET or CONNECTOR not selected ++# ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++# CONFIG_BLK_DEV_UB 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 ++# CONFIG_SENSORS_LIS3LV02D is not set ++CONFIG_MISC_DEVICES=y ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_ATMEL_PWM 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_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_BMP085 is not set ++# CONFIG_PCH_PHUB is not set ++# CONFIG_USB_SWITCH_FSA9480 is not set ++CONFIG_EARLY_DMA_ALLOC=y ++CONFIG_EDA_DEF_SIZE=0x04000000 ++CONFIG_EDA_DEF_ALIGN=0x00100000 ++CONFIG_RETIMER_CLASS=m ++CONFIG_DS100DF410=m ++# CONFIG_C2PORT is not set ++ ++# ++# EEPROM support ++# ++CONFIG_EEPROM_CLASS=m ++CONFIG_EEPROM_AT24=m ++CONFIG_EEPROM_AT25=m ++# 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_EEPROM_SFF_8436=m ++# 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 ++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_TGT is not set ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_PROC_FS is not set ++ ++# ++# 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=y ++CONFIG_CHR_DEV_SG=y ++# CONFIG_CHR_DEV_SCH is not set ++CONFIG_SCSI_MULTI_LUN=y ++CONFIG_SCSI_CONSTANTS=y ++CONFIG_SCSI_LOGGING=y ++# CONFIG_SCSI_SCAN_ASYNC is not set ++CONFIG_SCSI_WAIT_SCAN=m ++ ++# ++# 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=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++# CONFIG_SATA_PMP is not set ++ ++# ++# Controllers with non-SFF native interface ++# ++# CONFIG_SATA_AHCI is not set ++# CONFIG_SATA_AHCI_PLATFORM 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=y ++ ++# ++# SFF controllers with custom DMA interface ++# ++# CONFIG_PDC_ADMA is not set ++# CONFIG_SATA_QSTOR is not set ++# CONFIG_SATA_SX4 is not set ++# CONFIG_ATA_BMDMA is not set ++ ++# ++# PIO-only SFF controllers ++# ++# CONFIG_PATA_CMD640_PCI is not set ++# CONFIG_PATA_MPIIX is not set ++# CONFIG_PATA_NS87410 is not set ++# CONFIG_PATA_OPTI is not set ++CONFIG_PATA_PLATFORM=y ++CONFIG_PATA_OF_PLATFORM=y ++# CONFIG_PATA_RZ1000 is not set ++ ++# ++# Generic fallback / legacy drivers ++# ++# CONFIG_PATA_LEGACY is not set ++CONFIG_MD=y ++CONFIG_BLK_DEV_MD=m ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_MD_RAID1=m ++CONFIG_MD_RAID10=m ++CONFIG_MD_RAID456=m ++# CONFIG_MULTICORE_RAID456 is not set ++# CONFIG_MD_MULTIPATH is not set ++# CONFIG_MD_FAULTY is not set ++CONFIG_BLK_DEV_DM_BUILTIN=y ++CONFIG_BLK_DEV_DM=m ++# CONFIG_DM_DEBUG is not set ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++# CONFIG_DM_THIN_PROVISIONING is not set ++CONFIG_DM_MIRROR=m ++CONFIG_DM_RAID=m ++# CONFIG_DM_LOG_USERSPACE is not set ++CONFIG_DM_ZERO=m ++# CONFIG_DM_MULTIPATH is not set ++# CONFIG_DM_DELAY is not set ++# CONFIG_DM_UEVENT is not set ++# CONFIG_DM_FLAKEY 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=y ++CONFIG_DUMMY=m ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC is not set ++CONFIG_MII=y ++CONFIG_MACVLAN=m ++# CONFIG_MACVTAP is not set ++CONFIG_VXLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_NETPOLL=y ++# CONFIG_NETPOLL_TRAP is not set ++CONFIG_NET_POLL_CONTROLLER=y ++CONFIG_TUN=m ++CONFIG_VETH=y ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++CONFIG_ETHERNET=y ++# CONFIG_NET_VENDOR_3COM is not set ++# CONFIG_NET_VENDOR_ADAPTEC is not set ++# CONFIG_NET_VENDOR_ALTEON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_VENDOR_ATHEROS 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_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_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_REALTEK is not set ++# CONFIG_NET_VENDOR_RDC 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_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++CONFIG_MARVELL_PHY=y ++# 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=y ++# 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_PPP is not set ++# CONFIG_SLIP is not set ++# CONFIG_TR is not set ++ ++# ++# USB Network Adapters ++# ++# 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_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_DPAA_ETH_USE_NDO_SELECT_QUEUE is not set ++# CONFIG_ISDN is not set ++# CONFIG_PHONE 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 ++ ++# ++# Userland interfaces ++# ++# CONFIG_INPUT_MOUSEDEV is not set ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_EVDEV is not set ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++# CONFIG_SERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++# CONFIG_VT is not set ++CONFIG_UNIX98_PTYS=y ++CONFIG_DEVPTS_MULTIPLE_INSTANCES=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_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_PCI=y ++CONFIG_SERIAL_8250_NR_UARTS=4 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++CONFIG_SERIAL_8250_EXTENDED=y ++# CONFIG_SERIAL_8250_MANY_PORTS is not set ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++# CONFIG_SERIAL_8250_DETECT_IRQ is not set ++# CONFIG_SERIAL_8250_RSA is not set ++# CONFIG_SERIAL_8250_DW is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX3107 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_OF_PLATFORM is not set ++# CONFIG_SERIAL_TIMBERDALE 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_XILINX_PS_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=y ++# CONFIG_HW_RANDOM_TIMERIOMEM 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_RAMOOPS is not set ++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_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++CONFIG_I2C_MUX_PCA954x=y ++# CONFIG_I2C_MUX_DNI_6448 is not set ++# CONFIG_I2C_MUX_QUANTA 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_GPIO is not set ++# CONFIG_I2C_INTEL_MID is not set ++# CONFIG_I2C_OCORES is not set ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_PXA_PCI is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_XILINX is not set ++# CONFIG_I2C_EG20T is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_DIOLAN_U2C is not set ++# CONFIG_I2C_PARPORT_LIGHT 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_GPIO is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_PL022 is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_TOPCLIFF_PCH is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++# CONFIG_SPI_SPIDEV is not set ++# CONFIG_SPI_TLE62X0 is not set ++ ++# ++# PPS support ++# ++# CONFIG_PPS is not set ++ ++# ++# PPS generators support ++# ++ ++# ++# PTP clock support ++# ++ ++# ++# Enable Device Drivers -> PPS to see the PTP clock options. ++# ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_IT8761E is not set ++# CONFIG_GPIO_PL061 is not set ++# CONFIG_GPIO_VX855 is not set ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX7300 is not set ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_PCF857X is not set ++# CONFIG_GPIO_SX150X is not set ++# CONFIG_GPIO_ADP5588 is not set ++ ++# ++# PCI GPIO expanders: ++# ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_RDC321X is not set ++ ++# ++# 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: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++CONFIG_HWMON=m ++CONFIG_HWMON_VID=m ++# CONFIG_HWMON_DEBUG_CHIP is not set ++ ++# ++# Native drivers ++# ++# CONFIG_SENSORS_AD7314 is not set ++# CONFIG_SENSORS_AD7414 is not set ++# CONFIG_SENSORS_AD7418 is not set ++# CONFIG_SENSORS_ADCXX is not set ++CONFIG_SENSORS_ADM1021=m ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1029 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ADT7411 is not set ++# CONFIG_SENSORS_ADT7462 is not set ++CONFIG_SENSORS_ADT7470=m ++CONFIG_SENSORS_ADT7475=m ++# CONFIG_SENSORS_ASC7621 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++CONFIG_SENSORS_CY8CXX=m ++CONFIG_SENSORS_CY8C3245R1=m ++# CONFIG_SENSORS_DS620 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_I5K_AMB is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_F71882FG is not set ++# CONFIG_SENSORS_F75375S is not set ++# CONFIG_SENSORS_G760A is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_GPIO_FAN is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_JC42 is not set ++# CONFIG_SENSORS_LINEAGE is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM70 is not set ++# CONFIG_SENSORS_LM73 is not set ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_LM77=m ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++CONFIG_SENSORS_LM85=m ++# CONFIG_SENSORS_LM87 is not set ++CONFIG_SENSORS_LM90=m ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_LM93 is not set ++# CONFIG_SENSORS_LTC4151 is not set ++CONFIG_SENSORS_LTC4215=m ++# CONFIG_SENSORS_LTC4245 is not set ++# CONFIG_SENSORS_LTC4261 is not set ++# CONFIG_SENSORS_LM95241 is not set ++# CONFIG_SENSORS_LM95245 is not set ++# CONFIG_SENSORS_MAX1111 is not set ++# CONFIG_SENSORS_MAX16065 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_MAX1668 is not set ++CONFIG_SENSORS_MAX6639=m ++# CONFIG_SENSORS_MAX6642 is not set ++CONFIG_SENSORS_MAX6650=m ++CONFIG_SENSORS_MAX6620=m ++CONFIG_SENSORS_MAX6697=m ++# CONFIG_SENSORS_NTC_THERMISTOR is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PC87427 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++CONFIG_PMBUS=m ++CONFIG_SENSORS_PMBUS=m ++# CONFIG_SENSORS_ADM1275 is not set ++# CONFIG_SENSORS_LM25066 is not set ++# CONFIG_SENSORS_LTC2978 is not set ++# CONFIG_SENSORS_MAX16064 is not set ++# CONFIG_SENSORS_MAX34440 is not set ++# CONFIG_SENSORS_MAX8688 is not set ++# CONFIG_SENSORS_UCD9000 is not set ++# CONFIG_SENSORS_UCD9200 is not set ++# CONFIG_SENSORS_ZL6100 is not set ++CONFIG_SENSORS_DPS460=m ++CONFIG_SENSORS_PS2471=m ++CONFIG_SENSORS_CPR4011=m ++# CONFIG_SENSORS_SHT15 is not set ++# CONFIG_SENSORS_SHT21 is not set ++# CONFIG_SENSORS_SIS5595 is not set ++# CONFIG_SENSORS_SMM665 is not set ++# CONFIG_SENSORS_DME1737 is not set ++# CONFIG_SENSORS_EMC1403 is not set ++# CONFIG_SENSORS_EMC2103 is not set ++CONFIG_SENSORS_EMC2305=m ++# CONFIG_SENSORS_EMC6W201 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47M192 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_SCH56XX_COMMON is not set ++# CONFIG_SENSORS_SCH5627 is not set ++# CONFIG_SENSORS_SCH5636 is not set ++# CONFIG_SENSORS_ADS1015 is not set ++# CONFIG_SENSORS_ADS7828 is not set ++# CONFIG_SENSORS_ADS7871 is not set ++# CONFIG_SENSORS_AMC6821 is not set ++# CONFIG_SENSORS_THMC50 is not set ++# CONFIG_SENSORS_TMP102 is not set ++# CONFIG_SENSORS_TMP401 is not set ++# CONFIG_SENSORS_TMP421 is not set ++# CONFIG_SENSORS_VIA686A is not set ++# CONFIG_SENSORS_VT1211 is not set ++# CONFIG_SENSORS_VT8231 is not set ++CONFIG_SENSORS_W83781D=m ++# CONFIG_SENSORS_W83791D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83793 is not set ++# CONFIG_SENSORS_W83795 is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83L786NG is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++CONFIG_THERMAL=y ++CONFIG_WATCHDOG=y ++CONFIG_WATCHDOG_CORE=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++CONFIG_ARM_SP805_WATCHDOG=y ++# CONFIG_DW_WATCHDOG is not set ++# CONFIG_MPCORE_WATCHDOG is not set ++# CONFIG_MAX63XX_WATCHDOG is not set ++# CONFIG_ALIM7101_WDT is not set ++ ++# ++# PCI-based Watchdog Cards ++# ++# CONFIG_PCIPCWATCHDOG is not set ++# CONFIG_WDTPCI is not set ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG 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_88PM860X is not set ++# CONFIG_MFD_SM501 is not set ++# CONFIG_MFD_ASIC3 is not set ++# CONFIG_HTC_EGPIO is not set ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_TPS6105X is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_TPS6507X 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_TWL4030_CORE is not set ++# CONFIG_MFD_STMPE 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_PMIC_DA903X is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_MAX8925 is not set ++# CONFIG_MFD_MAX8997 is not set ++# CONFIG_MFD_MAX8998 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_PCF50633 is not set ++# CONFIG_MFD_MC13XXX is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_EZX_PCAP is not set ++# CONFIG_MFD_TIMBERDALE is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_MFD_RDC321X is not set ++# CONFIG_MFD_JANZ_CMODIO is not set ++# CONFIG_MFD_VX855 is not set ++# CONFIG_MFD_WL1273_CORE is not set ++# CONFIG_MFD_AAT2870_CORE is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_VGA_ARB is not set ++# CONFIG_DRM is not set ++# CONFIG_STUB_POULSBO is not set ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++# CONFIG_FB is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Display device support ++# ++# CONFIG_DISPLAY_SUPPORT is not set ++# CONFIG_SOUND is not set ++CONFIG_HID_SUPPORT=y ++CONFIG_HID=y ++# CONFIG_HIDRAW is not set ++ ++# ++# USB Input Devices ++# ++# CONFIG_USB_HID is not set ++# CONFIG_HID_PID is not set ++ ++# ++# USB HID Boot Protocol drivers ++# ++# CONFIG_USB_KBD is not set ++# CONFIG_USB_MOUSE is not set ++ ++# ++# Special HID drivers ++# ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_COMMON=y ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB_ARCH_HAS_EHCI=y ++CONFIG_USB_ARCH_HAS_XHCI=y ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEVICEFS is not set ++CONFIG_USB_DEVICE_CLASS=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_DWC3 is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB 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=y ++CONFIG_USB_EHCI_TT_NEWSCHED=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_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_WHCI_HCD is not set ++# CONFIG_USB_HWA_HCD 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_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB port drivers ++# ++CONFIG_USB_SERIAL=y ++CONFIG_USB_SERIAL_CONSOLE=y ++# CONFIG_USB_EZUSB is not set ++# CONFIG_USB_SERIAL_GENERIC is not set ++# CONFIG_USB_SERIAL_AIRCABLE is not set ++# CONFIG_USB_SERIAL_ARK3116 is not set ++# CONFIG_USB_SERIAL_BELKIN is not set ++# CONFIG_USB_SERIAL_CH341 is not set ++# CONFIG_USB_SERIAL_WHITEHEAT is not set ++# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set ++# CONFIG_USB_SERIAL_CP210X is not set ++# CONFIG_USB_SERIAL_CYPRESS_M8 is not set ++# CONFIG_USB_SERIAL_EMPEG is not set ++# CONFIG_USB_SERIAL_FTDI_SIO is not set ++# CONFIG_USB_SERIAL_FUNSOFT is not set ++# CONFIG_USB_SERIAL_VISOR is not set ++# CONFIG_USB_SERIAL_IPAQ is not set ++# CONFIG_USB_SERIAL_IR is not set ++# CONFIG_USB_SERIAL_EDGEPORT is not set ++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set ++# CONFIG_USB_SERIAL_GARMIN is not set ++# CONFIG_USB_SERIAL_IPW is not set ++# CONFIG_USB_SERIAL_IUU is not set ++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set ++# CONFIG_USB_SERIAL_KEYSPAN is not set ++# CONFIG_USB_SERIAL_KLSI is not set ++# CONFIG_USB_SERIAL_KOBIL_SCT is not set ++# CONFIG_USB_SERIAL_MCT_U232 is not set ++# CONFIG_USB_SERIAL_MOS7720 is not set ++# CONFIG_USB_SERIAL_MOS7840 is not set ++# CONFIG_USB_SERIAL_MOTOROLA is not set ++# CONFIG_USB_SERIAL_NAVMAN is not set ++# CONFIG_USB_SERIAL_PL2303 is not set ++# CONFIG_USB_SERIAL_OTI6858 is not set ++# CONFIG_USB_SERIAL_QCAUX is not set ++# CONFIG_USB_SERIAL_QUALCOMM is not set ++# CONFIG_USB_SERIAL_SPCP8X5 is not set ++# CONFIG_USB_SERIAL_HP4X is not set ++# CONFIG_USB_SERIAL_SAFE is not set ++# CONFIG_USB_SERIAL_SIEMENS_MPI is not set ++# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set ++# CONFIG_USB_SERIAL_SYMBOL is not set ++# CONFIG_USB_SERIAL_TI is not set ++# CONFIG_USB_SERIAL_CYBERJACK is not set ++# CONFIG_USB_SERIAL_XIRCOM is not set ++# CONFIG_USB_SERIAL_OPTION is not set ++# CONFIG_USB_SERIAL_OMNINET is not set ++# CONFIG_USB_SERIAL_OPTICON is not set ++# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set ++# CONFIG_USB_SERIAL_ZIO is not set ++# CONFIG_USB_SERIAL_SSU100 is not set ++# CONFIG_USB_SERIAL_DEBUG 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_ISIGHTFW is not set ++# CONFIG_USB_YUREX is not set ++# CONFIG_USB_GADGET is not set ++ ++# ++# OTG and related infrastructure ++# ++# CONFIG_USB_GPIO_VBUS is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_NOP_USB_XCEIV 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_RTC_LIB=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_HCTOSYS=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=y ++CONFIG_RTC_DRV_DS1374=y ++CONFIG_RTC_DRV_DS1672=y ++# CONFIG_RTC_DRV_DS3232 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_PCF8563=y ++# CONFIG_RTC_DRV_PCF8583 is not set ++CONFIG_RTC_DRV_M41T80=y ++# CONFIG_RTC_DRV_M41T80_WDT 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_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 ++ ++# ++# Platform RTC drivers ++# ++# CONFIG_RTC_DRV_CMOS is not set ++# CONFIG_RTC_DRV_DS1286 is not set ++# CONFIG_RTC_DRV_DS1511 is not set ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 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_DMADEVICES is not set ++# CONFIG_AUXDISPLAY is not set ++# CONFIG_UIO is not set ++ ++# ++# Virtio drivers ++# ++# CONFIG_VIRTIO_PCI is not set ++# CONFIG_VIRTIO_BALLOON is not set ++# CONFIG_VIRTIO_MMIO is not set ++# CONFIG_STAGING is not set ++CONFIG_CLKDEV_LOOKUP=y ++CONFIG_HAVE_MACH_CLKDEV=y ++ ++# ++# Hardware Spinlock drivers ++# ++# CONFIG_IOMMU_SUPPORT is not set ++# CONFIG_VIRT_DRIVERS is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++# CONFIG_PM_DEVFREQ is not set ++ ++# ++# Frame Manager support ++# ++# CONFIG_FSL_FMAN is not set ++ ++# ++# Broadcom iProc Drivers ++# ++# CONFIG_IPROC_CCB_TIMER is not set ++CONFIG_IPROC_MDIO=y ++# CONFIG_IPROC_DMA is not set ++CONFIG_IPROC_GPIO=y ++CONFIG_IPROC_QSPI=y ++CONFIG_IPROC_QSPI_SINGLE_MODE=y ++# CONFIG_IPROC_QSPI_DUAL_MODE is not set ++# CONFIG_IPROC_QSPI_QUAD_MODE is not set ++CONFIG_IPROC_QSPI_MAX_HZ=62500000 ++CONFIG_IPROC_MTD_NAND=y ++# CONFIG_IPROC_MTD_NAND_USE_JFFS2 is not set ++# CONFIG_IPROC_PWM is not set ++CONFIG_IPROC_USB2H=y ++CONFIG_USB_EHCI_BCM=y ++CONFIG_IPROC_GMAC=y ++ ++# ++# Broadcom HND network devices ++# ++CONFIG_HND=y ++CONFIG_ET=y ++CONFIG_ET_47XX=y ++CONFIG_ET_ALL_PASSIVE_ON=y ++# CONFIG_ET_ALL_PASSIVE_RUNTIME is not set ++# CONFIG_BCM_CTF is not set ++# CONFIG_BCM_CTF2 is not set ++# CONFIG_BCM_IPROC_GMAC_ACP is not set ++# CONFIG_BCM_IPROC_GMAC_PREFETCH is not set ++# CONFIG_BCM_IPROC_GMAC_TXONCPU1 is not set ++# CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING is not set ++# CONFIG_BCM_IPROC_GMAC_LOCK_OPT is not set ++# CONFIG_BCM_IPROC_GMAC_RWREG_OPT is not set ++# CONFIG_BCM_IPROC_GMAC_SG is not set ++# CONFIG_WL_EMULATOR is not set ++# CONFIG_BCM57XX is not set ++# CONFIG_WL is not set ++# CONFIG_WL_USBAP is not set ++CONFIG_WL_AP="" ++CONFIG_WL_AP_SDSTD="" ++CONFIG_WL_STA="" ++CONFIG_WL_APSTA="" ++CONFIG_WL_AP_ONCHIP_G="" ++CONFIG_WL_STA_ONCHIP_G="" ++CONFIG_WL_HIGH="" ++# CONFIG_EMF is not set ++CONFIG_IPROC_SDK_MGT_PORT_HANDOFF=y ++# CONFIG_IPROC_2STAGE_RX is not set ++CONFIG_IPROC_I2C=y ++# CONFIG_IPROC_PMU is not set ++# CONFIG_BCM_IPROC_CA9_PREFETCH is not set ++# CONFIG_BCM_BARRIER_PERFORMANCE is not set ++# CONFIG_BCM_MEM_OPTIMIZATION is not set ++# CONFIG_BROADCOM_CUSTOM_SENDFILE is not set ++# CONFIG_BCM_CUSTOM_RECVFILE is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++# CONFIG_EXT2_FS_XIP is not set ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_DEFAULTS_TO_ORDERED=y ++CONFIG_EXT3_FS_XATTR=y ++CONFIG_EXT3_FS_POSIX_ACL=y ++CONFIG_EXT3_FS_SECURITY=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_XATTR=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD=y ++# CONFIG_JBD_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_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_EXPORTFS=y ++CONFIG_FILE_LOCKING=y ++CONFIG_FSNOTIFY=y ++# CONFIG_DNOTIFY is not set ++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=y ++CONFIG_OVERLAYFS_FS=y ++# CONFIG_CUSE is not set ++CONFIG_GENERIC_ACL=y ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++# 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_SYSFS=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_TMPFS_XATTR=y ++# CONFIG_HUGETLB_PAGE is not set ++# CONFIG_CONFIGFS_FS is not set ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_ECRYPT_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set ++CONFIG_JFFS2_SUMMARY=y ++# 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_XATTR=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_FS_DEBUG is not set ++# CONFIG_LOGFS is not set ++# CONFIG_CRAMFS is not set ++CONFIG_SQUASHFS=y ++# CONFIG_SQUASHFS_XATTR is not set ++# CONFIG_SQUASHFS_ZLIB 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_ROMFS_FS is not set ++# CONFIG_PSTORE is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_AUFS_FS=m ++CONFIG_AUFS_BRANCH_MAX_127=y ++# CONFIG_AUFS_BRANCH_MAX_511 is not set ++# CONFIG_AUFS_BRANCH_MAX_1023 is not set ++# CONFIG_AUFS_BRANCH_MAX_32767 is not set ++CONFIG_AUFS_SBILIST=y ++# CONFIG_AUFS_HNOTIFY is not set ++# CONFIG_AUFS_EXPORT is not set ++# CONFIG_AUFS_RDU is not set ++# CONFIG_AUFS_PROC_MAP is not set ++# CONFIG_AUFS_SP_IATTR is not set ++# CONFIG_AUFS_SHWH is not set ++# CONFIG_AUFS_BR_RAMFS is not set ++# CONFIG_AUFS_BR_FUSE is not set ++CONFIG_AUFS_BDEV_LOOP=y ++# CONFIG_AUFS_DEBUG is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++# CONFIG_NFS_V4_1 is not set ++# CONFIG_NFS_USE_LEGACY_DNS is not set ++CONFIG_NFS_USE_KERNEL_DNS=y ++# CONFIG_NFS_USE_NEW_IDMAPPER is not set ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=y ++# 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 ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_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_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=y ++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_UTF8=y ++ ++# ++# Kernel hacking ++# ++CONFIG_PRINTK_TIME=y ++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=2048 ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAGIC_SYSRQ_DEFAULT_MASK=0x1 ++CONFIG_STRIP_ASM_SYMS=y ++# CONFIG_UNUSED_SYMBOLS is not set ++CONFIG_DEBUG_FS=y ++CONFIG_HEADERS_CHECK=y ++CONFIG_DEBUG_SECTION_MISMATCH=y ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_SHIRQ is not set ++CONFIG_LOCKUP_DETECTOR=y ++# CONFIG_HARDLOCKUP_DETECTOR is not set ++CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y ++CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=1 ++# 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_PANIC_TIMEOUT=5 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++CONFIG_TIMER_STATS=y ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_DEBUG_SLAB is not set ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_RT_MUTEX_TESTER is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_SPARSE_RCU_POINTER 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_STACKTRACE=y ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_KOBJECT is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_INFO=y ++# CONFIG_DEBUG_INFO_REDUCED is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_WRITECOUNT is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_LKDTM is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_SYSCTL_SYSCALL_CHECK is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++CONFIG_NOP_TRACER=y ++CONFIG_HAVE_FUNCTION_TRACER=y ++CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y ++CONFIG_HAVE_DYNAMIC_FTRACE=y ++CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y ++CONFIG_HAVE_C_RECORDMCOUNT=y ++CONFIG_RING_BUFFER=y ++CONFIG_EVENT_TRACING=y ++CONFIG_EVENT_POWER_TRACING_DEPRECATED=y ++CONFIG_CONTEXT_SWITCH_TRACER=y ++CONFIG_RING_BUFFER_ALLOW_SWAP=y ++CONFIG_TRACING=y ++CONFIG_GENERIC_TRACER=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_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=y ++# CONFIG_FTRACE_STARTUP_TEST is not set ++# CONFIG_RING_BUFFER_BENCHMARK is not set ++# CONFIG_BUILD_DOCSRC is not set ++CONFIG_DYNAMIC_DEBUG=y ++# CONFIG_DMA_API_DEBUG is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_ASYNC_RAID6_TEST is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_TEST_KSTRTOX 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_OC_ETM is not set ++ ++# ++# Security options ++# ++CONFIG_KEYS=y ++# CONFIG_ENCRYPTED_KEYS is not set ++# CONFIG_KEYS_DEBUG_PROC_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_XOR_BLOCKS=m ++CONFIG_ASYNC_CORE=m ++CONFIG_ASYNC_MEMCPY=m ++CONFIG_ASYNC_XOR=m ++CONFIG_ASYNC_PQ=m ++CONFIG_ASYNC_RAID6_RECOV=m ++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_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++CONFIG_CRYPTO_WORKQUEUE=y ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=m ++# 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=m ++# 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_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=m ++# CONFIG_CRYPTO_GHASH 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=m ++# 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=m ++# 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=m ++# 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 ++ ++# ++# Random Number Generation ++# ++# CONFIG_CRYPTO_ANSI_CPRNG 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=y ++ ++# ++# Library routines ++# ++CONFIG_RAID6_PQ=m ++CONFIG_BITREVERSE=y ++# CONFIG_CRC_CCITT is not set ++CONFIG_CRC16=y ++CONFIG_CRC_T10DIF=y ++# CONFIG_CRC_ITU_T is not set ++CONFIG_CRC32=y ++# CONFIG_CRC7 is not set ++CONFIG_LIBCRC32C=m ++# CONFIG_CRC8 is not set ++CONFIG_AUDIT_GENERIC=y ++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_DECOMPRESS_XZ=y ++CONFIG_TEXTSEARCH=y ++CONFIG_TEXTSEARCH_KMP=m ++CONFIG_TEXTSEARCH_BM=m ++CONFIG_TEXTSEARCH_FSM=m ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set +diff --git a/debian/config/armel/config.iop32x b/debian/config/armel/config.iop32x +new file mode 100644 +index 0000000..e25df77 +--- /dev/null ++++ b/debian/config/armel/config.iop32x +@@ -0,0 +1,686 @@ ++## ++## file: arch/arm/Kconfig ++## ++## choice: ARM system type ++# 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_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++CONFIG_ARCH_IOP32X=y ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_OMAP is not set ++## end choice ++CONFIG_PCI=y ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++CONFIG_KEXEC=y ++CONFIG_ATAGS_PROC=y ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++# CONFIG_ARTHUR is not set ++ ++## ++## file: arch/arm/mach-iop32x/Kconfig ++## ++CONFIG_MACH_GLANTANK=y ++CONFIG_ARCH_IQ80321=y ++CONFIG_ARCH_IQ31244=y ++CONFIG_MACH_N2100=y ++CONFIG_MACH_EM7210=y ++ ++## ++## file: arch/arm/mm/Kconfig ++## ++CONFIG_ARM_THUMB=y ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=m ++CONFIG_SATA_AHCI=m ++CONFIG_SATA_SIL24=m ++CONFIG_PDC_ADMA=m ++CONFIG_SATA_QSTOR=m ++CONFIG_SATA_SX4=m ++CONFIG_ATA_PIIX=m ++CONFIG_SATA_MV=m ++CONFIG_SATA_NV=m ++CONFIG_SATA_PROMISE=m ++CONFIG_SATA_SIL=m ++CONFIG_SATA_SIS=m ++CONFIG_SATA_SVW=m ++CONFIG_SATA_ULI=m ++CONFIG_SATA_VIA=m ++CONFIG_SATA_VITESSE=m ++CONFIG_PATA_ALI=m ++CONFIG_PATA_CMD64X=m ++CONFIG_PATA_CS5520=m ++CONFIG_PATA_CS5530=m ++CONFIG_PATA_EFAR=m ++CONFIG_PATA_HPT366=m ++CONFIG_PATA_HPT37X=m ++CONFIG_PATA_NETCELL=m ++CONFIG_PATA_NS87415=m ++CONFIG_PATA_OLDPIIX=m ++CONFIG_PATA_PDC2027X=m ++CONFIG_PATA_PDC_OLD=m ++CONFIG_PATA_SC1200=m ++CONFIG_PATA_SERVERWORKS=m ++CONFIG_PATA_SIL680=m ++CONFIG_PATA_TRIFLEX=m ++CONFIG_PATA_VIA=m ++CONFIG_PATA_WINBOND=m ++CONFIG_PATA_MPIIX=m ++CONFIG_PATA_NS87410=m ++CONFIG_PATA_OPTI=m ++CONFIG_PATA_LEGACY=m ++ ++## ++## file: drivers/block/Kconfig ++## ++# CONFIG_BLK_CPQ_DA 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_SX8 is not set ++# CONFIG_BLK_DEV_UB is not set ++# CONFIG_CDROM_PKTCDVD is not set ++ ++## ++## file: drivers/bluetooth/Kconfig ++## ++# CONFIG_BT_HCIUART is not set ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++ ++## ++## file: drivers/char/Kconfig ++## ++# CONFIG_NVRAM is not set ++# CONFIG_DTLK is not set ++# CONFIG_APPLICOM is not set ++# CONFIG_TELCLOCK is not set ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++# CONFIG_IPMI_HANDLER is not set ++ ++## ++## file: drivers/char/tpm/Kconfig ++## ++# CONFIG_TCG_TPM is not set ++ ++## ++## file: drivers/dma/Kconfig ++## ++CONFIG_DMADEVICES=y ++CONFIG_INTEL_IOP_ADMA=y ++# CONFIG_NET_DMA is not set ++ ++## ++## file: drivers/firewire/Kconfig ++## ++# CONFIG_FIREWIRE is not set ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++# CONFIG_DRM is not set ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_HWMON=y ++# CONFIG_HWMON_DEBUG_CHIP is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_F71805F is not set ++CONFIG_SENSORS_F75375S=y ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM75 is not set ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_SIS5595 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_VIA686A is not set ++# CONFIG_SENSORS_VT8231 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++# 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_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 ++CONFIG_I2C_IOP3XX=y ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_PCA_ISA is not set ++# CONFIG_I2C_STUB is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++CONFIG_GAMEPORT=m ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++CONFIG_INPUT_JOYSTICK=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=m ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=m ++CONFIG_SERIO_SERPORT=m ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=m ++# CONFIG_SERIO_RAW is not set ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++CONFIG_INPUT_TOUCHSCREEN=y ++ ++## ++## file: drivers/leds/Kconfig ++## ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_PCA9532=y ++ ++## ++## file: drivers/media/Kconfig ++## ++CONFIG_DVB_CORE=m ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++# CONFIG_RADIO_MAXIRADIO is not set ++ ++## ++## file: drivers/message/fusion/Kconfig ++## ++CONFIG_FUSION=y ++CONFIG_FUSION_SPI=m ++CONFIG_FUSION_FC=m ++CONFIG_FUSION_SAS=m ++CONFIG_FUSION_MAX_SGE=40 ++CONFIG_FUSION_CTL=m ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++# CONFIG_I2O is not set ++ ++## ++## file: drivers/mmc/Kconfig ++## ++# CONFIG_MMC is not set ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=y ++CONFIG_MTD_REDBOOT_PARTS=y ++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 ++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set ++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLOCK=y ++CONFIG_FTL=m ++CONFIG_NFTL=m ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++CONFIG_MTD_CFI=y ++CONFIG_MTD_JEDECPROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++## choice: Flash cmd/query data swapping ++CONFIG_MTD_CFI_NOSWAP=y ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++## end choice ++CONFIG_MTD_CFI_GEOMETRY=y ++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_OTP is not set ++CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_CFI_AMDSTD=m ++CONFIG_MTD_CFI_STAA=m ++CONFIG_MTD_RAM=m ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++## ++## file: drivers/mtd/devices/Kconfig ++## ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 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 ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_PHYSMAP_START=0x0 ++CONFIG_MTD_PHYSMAP_LEN=0x0 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=1 ++# CONFIG_MTD_PCI is not set ++CONFIG_MTD_PLATRAM=m ++ ++## ++## file: drivers/mtd/nand/Kconfig ++## ++CONFIG_MTD_NAND=m ++# CONFIG_MTD_NAND_VERIFY_WRITE is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++ ++## ++## file: drivers/mtd/onenand/Kconfig ++## ++# CONFIG_MTD_ONENAND is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++# CONFIG_NET_VENDOR_3COM is not set ++ ++## ++## file: drivers/net/ethernet/davicom/Kconfig ++## ++# CONFIG_DM9000 is not set ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++# CONFIG_NET_TULIP is not set ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++# CONFIG_HP100 is not set ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++# CONFIG_SMC91X is not set ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++ ++## ++## file: drivers/net/phy/Kconfig ++## ++CONFIG_PHYLIB=m ++CONFIG_MARVELL_PHY=m ++CONFIG_DAVICOM_PHY=m ++CONFIG_QSEMI_PHY=m ++CONFIG_LXT_PHY=m ++CONFIG_CICADA_PHY=m ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++# CONFIG_TR is not set ++ ++## ++## file: drivers/net/wireless/Kconfig ++## ++CONFIG_ATMEL=m ++CONFIG_PCI_ATMEL=m ++ ++## ++## file: drivers/net/wireless/ipw2x00/Kconfig ++## ++CONFIG_IPW2100=m ++# CONFIG_IPW2100_MONITOR is not set ++# CONFIG_IPW2100_DEBUG is not set ++CONFIG_IPW2200=m ++CONFIG_IPW2200_MONITOR=y ++# CONFIG_IPW2200_DEBUG is not set ++ ++## ++## file: drivers/net/wireless/orinoco/Kconfig ++## ++CONFIG_HERMES=m ++CONFIG_PLX_HERMES=m ++CONFIG_TMD_HERMES=m ++CONFIG_NORTEL_HERMES=m ++CONFIG_PCI_HERMES=m ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++# CONFIG_RTC_DRV_DS1672 is not set ++CONFIG_RTC_DRV_RS5C372=y ++# CONFIG_RTC_DRV_X1205 is not set ++# CONFIG_RTC_DRV_PCF8563 is not set ++# CONFIG_RTC_DRV_M48T86 is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_ACARD is not set ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI=y ++# CONFIG_SPI_BITBANG is not set ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=2 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++# CONFIG_SERIAL_8250_EXTENDED is not set ++# CONFIG_SERIAL_JSM is not set ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++ ++## ++## file: drivers/usb/atm/Kconfig ++## ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_ISP116X_HCD=m ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++CONFIG_USB_SL811_HCD=m ++ ++## ++## file: drivers/video/Kconfig ++## ++# CONFIG_FB is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++# CONFIG_VGA_CONSOLE is not set ++ ++## ++## file: drivers/w1/Kconfig ++## ++# CONFIG_W1 is not set ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++# CONFIG_PCIPCWATCHDOG is not set ++# CONFIG_WDTPCI is not set ++# CONFIG_USBPCWATCHDOG is not set ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_ACORN_PARTITION=y ++# CONFIG_ACORN_PARTITION_CUMANA is not set ++# CONFIG_ACORN_PARTITION_EESOX is not set ++CONFIG_ACORN_PARTITION_ICS=y ++# CONFIG_ACORN_PARTITION_ADFS is not set ++# CONFIG_ACORN_PARTITION_POWERTEC is not set ++CONFIG_ACORN_PARTITION_RISCIX=y ++CONFIG_OSF_PARTITION=y ++CONFIG_AMIGA_PARTITION=y ++CONFIG_ATARI_PARTITION=y ++CONFIG_MAC_PARTITION=y ++CONFIG_BSD_DISKLABEL=y ++CONFIG_MINIX_SUBPARTITION=y ++CONFIG_SOLARIS_X86_PARTITION=y ++CONFIG_UNIXWARE_DISKLABEL=y ++CONFIG_LDM_PARTITION=y ++# CONFIG_LDM_DEBUG is not set ++CONFIG_SGI_PARTITION=y ++CONFIG_ULTRIX_PARTITION=y ++CONFIG_SUN_PARTITION=y ++ ++## ++## file: init/Kconfig ++## ++CONFIG_LOG_BUF_SHIFT=14 ++ ++## ++## file: kernel/Kconfig.preempt ++## ++## choice: Preemption Model ++# CONFIG_PREEMPT is not set ++## end choice ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/ax25/Kconfig ++## ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++# CONFIG_AX25_DAMA_SLAVE is not set ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++ ++## ++## file: net/bridge/netfilter/Kconfig ++## ++# CONFIG_BRIDGE_NF_EBTABLES is not set ++ ++## ++## file: net/decnet/Kconfig ++## ++CONFIG_DECNET=m ++# CONFIG_DECNET_ROUTER is not set ++ ++## ++## file: net/decnet/netfilter/Kconfig ++## ++# CONFIG_DECNET_NF_GRABULATOR is not set ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++CONFIG_IPX_INTERN=y ++ ++## ++## file: net/irda/Kconfig ++## ++# CONFIG_IRDA is not set ++ ++## ++## file: net/lapb/Kconfig ++## ++# CONFIG_LAPB is not set ++ ++## ++## file: sound/drivers/Kconfig ++## ++CONFIG_SND_DUMMY=m ++# CONFIG_SND_VIRMIDI is not set ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++ ++## ++## file: sound/pci/Kconfig ++## ++# CONFIG_SND_AD1889 is not set ++CONFIG_SND_ALS300=m ++# CONFIG_SND_ALI5451 is not set ++# CONFIG_SND_ATIIXP is not set ++# CONFIG_SND_ATIIXP_MODEM is not set ++# CONFIG_SND_AU8810 is not set ++# CONFIG_SND_AU8820 is not set ++# CONFIG_SND_AU8830 is not set ++# CONFIG_SND_AZT3328 is not set ++# CONFIG_SND_BT87X is not set ++# CONFIG_SND_CA0106 is not set ++# CONFIG_SND_CMIPCI is not set ++# CONFIG_SND_CS4281 is not set ++# CONFIG_SND_CS46XX is not set ++# CONFIG_SND_EMU10K1 is not set ++# CONFIG_SND_EMU10K1X is not set ++# CONFIG_SND_ENS1370 is not set ++# CONFIG_SND_ENS1371 is not set ++# CONFIG_SND_ES1938 is not set ++# CONFIG_SND_ES1968 is not set ++# CONFIG_SND_FM801 is not set ++# CONFIG_SND_HDSP is not set ++# CONFIG_SND_HDSPM is not set ++# CONFIG_SND_ICE1712 is not set ++# CONFIG_SND_ICE1724 is not set ++# CONFIG_SND_INTEL8X0 is not set ++# CONFIG_SND_INTEL8X0M is not set ++# CONFIG_SND_KORG1212 is not set ++# CONFIG_SND_MAESTRO3 is not set ++# CONFIG_SND_MIXART is not set ++# CONFIG_SND_NM256 is not set ++CONFIG_SND_PCXHR=m ++CONFIG_SND_RIPTIDE=m ++# CONFIG_SND_RME32 is not set ++# CONFIG_SND_RME96 is not set ++# CONFIG_SND_RME9652 is not set ++# CONFIG_SND_SONICVIBES is not set ++# CONFIG_SND_TRIDENT is not set ++# CONFIG_SND_VIA82XX is not set ++# CONFIG_SND_VIA82XX_MODEM is not set ++# CONFIG_SND_VX222 is not set ++# CONFIG_SND_YMFPCI is not set ++ ++## ++## file: sound/pci/hda/Kconfig ++## ++# CONFIG_SND_HDA_INTEL is not set ++ +diff --git a/debian/config/armel/config.ixp4xx b/debian/config/armel/config.ixp4xx +new file mode 100644 +index 0000000..2539bb0 +--- /dev/null ++++ b/debian/config/armel/config.ixp4xx +@@ -0,0 +1,814 @@ ++## ++## file: arch/arm/Kconfig ++## ++## choice: ARM system type ++# 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_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++CONFIG_ARCH_IXP4XX=y ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_OMAP is not set ++## end choice ++CONFIG_PCI=y ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyS0,115200" ++# CONFIG_XIP_KERNEL is not set ++CONFIG_KEXEC=y ++CONFIG_ATAGS_PROC=y ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++# CONFIG_ARTHUR is not set ++ ++## ++## file: arch/arm/mach-ixp4xx/Kconfig ++## ++CONFIG_MACH_NSLU2=y ++CONFIG_ARCH_ADI_COYOTE=y ++CONFIG_ARCH_IXDP425=y ++CONFIG_MACH_IXDPG425=y ++CONFIG_MACH_IXDP465=y ++CONFIG_ARCH_PRPMC1100=y ++CONFIG_MACH_NAS100D=y ++CONFIG_MACH_DSMG600=y ++CONFIG_MACH_FSG=y ++# CONFIG_MACH_GTWX5715 is not set ++# CONFIG_IXP4XX_INDIRECT_PCI is not set ++CONFIG_IXP4XX_QMGR=m ++CONFIG_IXP4XX_NPE=m ++ ++## ++## file: arch/arm/mm/Kconfig ++## ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_BIG_ENDIAN is not set ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=m ++# CONFIG_SATA_PMP is not set ++# CONFIG_SATA_AHCI is not set ++# CONFIG_SATA_SIL24 is not set ++CONFIG_ATA_SFF=y ++# CONFIG_PDC_ADMA is not set ++# CONFIG_SATA_QSTOR is not set ++# CONFIG_SATA_SX4 is not set ++# CONFIG_ATA_PIIX is not set ++# CONFIG_SATA_MV is not set ++# CONFIG_SATA_NV is not set ++# CONFIG_SATA_PROMISE is not set ++# CONFIG_SATA_SIL is not set ++# CONFIG_SATA_SIS is not set ++# CONFIG_SATA_SVW is not set ++# CONFIG_SATA_ULI is not set ++CONFIG_SATA_VIA=m ++# CONFIG_SATA_VITESSE is not set ++# CONFIG_PATA_ALI is not set ++# CONFIG_PATA_AMD is not set ++# CONFIG_PATA_ARTOP is not set ++# CONFIG_PATA_ATIIXP is not set ++# CONFIG_PATA_CMD64X is not set ++# CONFIG_PATA_CS5520 is not set ++# CONFIG_PATA_CS5530 is not set ++# CONFIG_PATA_CYPRESS is not set ++# CONFIG_PATA_EFAR is not set ++# CONFIG_PATA_HPT366 is not set ++# CONFIG_PATA_HPT37X is not set ++# CONFIG_PATA_HPT3X2N is not set ++# CONFIG_PATA_HPT3X3 is not set ++# CONFIG_PATA_IT8213 is not set ++# CONFIG_PATA_IT821X is not set ++# CONFIG_PATA_JMICRON is not set ++# CONFIG_PATA_MARVELL is not set ++# CONFIG_PATA_NETCELL is not set ++# CONFIG_PATA_NINJA32 is not set ++# CONFIG_PATA_NS87415 is not set ++# CONFIG_PATA_OLDPIIX is not set ++# CONFIG_PATA_OPTIDMA is not set ++# CONFIG_PATA_PDC2027X is not set ++# CONFIG_PATA_PDC_OLD is not set ++# CONFIG_PATA_RADISYS is not set ++# CONFIG_PATA_SC1200 is not set ++# CONFIG_PATA_SCH is not set ++# CONFIG_PATA_SERVERWORKS is not set ++# CONFIG_PATA_SIL680 is not set ++# CONFIG_PATA_SIS is not set ++# CONFIG_PATA_TRIFLEX is not set ++# CONFIG_PATA_VIA is not set ++# CONFIG_PATA_WINBOND is not set ++# CONFIG_PATA_CMD640_PCI is not set ++# CONFIG_PATA_IXP4XX_CF is not set ++# CONFIG_PATA_MPIIX is not set ++# CONFIG_PATA_NS87410 is not set ++# CONFIG_PATA_OPTI is not set ++# CONFIG_PATA_RZ1000 is not set ++# CONFIG_ATA_GENERIC is not set ++ ++## ++## file: drivers/block/Kconfig ++## ++# CONFIG_BLK_CPQ_DA 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_SX8 is not set ++# CONFIG_BLK_DEV_UB is not set ++# CONFIG_CDROM_PKTCDVD is not set ++ ++## ++## file: drivers/bluetooth/Kconfig ++## ++# CONFIG_BT_HCIUART is not set ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++ ++## ++## file: drivers/char/Kconfig ++## ++# CONFIG_NVRAM is not set ++# CONFIG_DTLK is not set ++# CONFIG_APPLICOM is not set ++CONFIG_TELCLOCK=m ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++# CONFIG_IPMI_HANDLER is not set ++ ++## ++## file: drivers/char/tpm/Kconfig ++## ++# CONFIG_TCG_TPM is not set ++ ++## ++## file: drivers/firewire/Kconfig ++## ++# CONFIG_FIREWIRE is not set ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++# CONFIG_DRM is not set ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_HWMON=y ++# CONFIG_HWMON_DEBUG_CHIP is not set ++CONFIG_SENSORS_ADM1021=m ++CONFIG_SENSORS_ADM1025=m ++CONFIG_SENSORS_ADM1026=m ++CONFIG_SENSORS_ADM1031=m ++CONFIG_SENSORS_ADM9240=m ++# CONFIG_SENSORS_ASB100 is not set ++CONFIG_SENSORS_ATXP1=m ++CONFIG_SENSORS_DS1621=m ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++CONFIG_SENSORS_LM63=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_LM77=m ++CONFIG_SENSORS_LM78=m ++CONFIG_SENSORS_LM80=m ++CONFIG_SENSORS_LM83=m ++CONFIG_SENSORS_LM85=m ++CONFIG_SENSORS_LM87=m ++CONFIG_SENSORS_LM90=m ++CONFIG_SENSORS_LM92=m ++CONFIG_SENSORS_MAX1619=m ++# CONFIG_SENSORS_PC87360 is not set ++CONFIG_SENSORS_PCF8591=m ++# CONFIG_SENSORS_SIS5595 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_VIA686A is not set ++CONFIG_SENSORS_VT8231=m ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++CONFIG_SENSORS_W83627EHF=m ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++# 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_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 ++CONFIG_I2C_GPIO=y ++# CONFIG_I2C_IOP3XX is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_PCA_ISA is not set ++# CONFIG_I2C_STUB is not set ++# CONFIG_SCx200_ACB is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++CONFIG_GAMEPORT=m ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++CONFIG_INPUT_JOYSTICK=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=m ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_IXP4XX_BEEPER=m ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=m ++CONFIG_SERIO_SERPORT=m ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=m ++# CONFIG_SERIO_RAW is not set ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++CONFIG_INPUT_TOUCHSCREEN=y ++ ++## ++## file: drivers/leds/Kconfig ++## ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_FSG=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGERS=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++ ++## ++## file: drivers/media/Kconfig ++## ++CONFIG_DVB_CORE=m ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++# CONFIG_RADIO_MAXIRADIO is not set ++# CONFIG_USB_DSBR is not set ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++# CONFIG_I2O is not set ++ ++## ++## file: drivers/mmc/Kconfig ++## ++# CONFIG_MMC is not set ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=y ++CONFIG_MTD_REDBOOT_PARTS=y ++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 ++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set ++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set ++# CONFIG_MTD_CMDLINE_PARTS is not set ++# CONFIG_MTD_AFS_PARTS is not set ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLOCK=y ++CONFIG_FTL=m ++CONFIG_NFTL=m ++# CONFIG_INFTL is not set ++CONFIG_RFD_FTL=m ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++CONFIG_MTD_CFI=y ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++## choice: Flash cmd/query data swapping ++# CONFIG_MTD_CFI_NOSWAP is not set ++CONFIG_MTD_CFI_BE_BYTE_SWAP=y ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++## end choice ++CONFIG_MTD_CFI_GEOMETRY=y ++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set ++# 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_OTP is not set ++CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_CFI_AMDSTD=m ++CONFIG_MTD_CFI_STAA=m ++CONFIG_MTD_RAM=m ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++## ++## file: drivers/mtd/devices/Kconfig ++## ++# CONFIG_MTD_PMC551 is not set ++CONFIG_MTD_DATAFLASH=m ++CONFIG_MTD_M25P80=m ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++# CONFIG_MTD_PHYSMAP is not set ++CONFIG_MTD_IXP4XX=y ++# CONFIG_MTD_PCI is not set ++CONFIG_MTD_PLATRAM=m ++ ++## ++## file: drivers/mtd/nand/Kconfig ++## ++CONFIG_MTD_NAND=m ++# CONFIG_MTD_NAND_VERIFY_WRITE is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++ ++## ++## file: drivers/mtd/onenand/Kconfig ++## ++# CONFIG_MTD_ONENAND is not set ++ ++## ++## file: drivers/net/Kconfig ++## ++# CONFIG_NET_FC is not set ++# CONFIG_NETPOLL_TRAP is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++# CONFIG_NET_VENDOR_3COM is not set ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++# CONFIG_AX88796 is not set ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++# CONFIG_B44 is not set ++ ++## ++## file: drivers/net/ethernet/davicom/Kconfig ++## ++# CONFIG_DM9000 is not set ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++# CONFIG_NET_TULIP is not set ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++# CONFIG_HP100 is not set ++ ++## ++## file: drivers/net/ethernet/microchip/Kconfig ++## ++CONFIG_ENC28J60=m ++# CONFIG_ENC28J60_WRITEVERIFY is not set ++ ++## ++## file: drivers/net/ethernet/neterion/Kconfig ++## ++# CONFIG_S2IO is not set ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++# CONFIG_SMC91X is not set ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++ ++## ++## file: drivers/net/ethernet/xscale/Kconfig ++## ++CONFIG_IXP4XX_ETH=m ++ ++## ++## file: drivers/net/fddi/Kconfig ++## ++# CONFIG_FDDI is not set ++ ++## ++## file: drivers/net/hippi/Kconfig ++## ++# CONFIG_HIPPI is not set ++ ++## ++## file: drivers/net/phy/Kconfig ++## ++CONFIG_PHYLIB=m ++CONFIG_MARVELL_PHY=m ++CONFIG_DAVICOM_PHY=m ++CONFIG_QSEMI_PHY=m ++CONFIG_LXT_PHY=m ++CONFIG_CICADA_PHY=m ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++# CONFIG_TR is not set ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++# CONFIG_WAN is not set ++ ++## ++## file: drivers/net/wireless/Kconfig ++## ++CONFIG_ATMEL=m ++# CONFIG_PCI_ATMEL is not set ++ ++## ++## file: drivers/net/wireless/hostap/Kconfig ++## ++#. TODO ++# CONFIG_HOSTAP_FIRMWARE is not set ++#. TODO ++# CONFIG_HOSTAP_PCI is not set ++ ++## ++## file: drivers/net/wireless/ipw2x00/Kconfig ++## ++CONFIG_IPW2100=m ++# CONFIG_IPW2100_MONITOR is not set ++# CONFIG_IPW2100_DEBUG is not set ++CONFIG_IPW2200=m ++# CONFIG_IPW2200_DEBUG is not set ++ ++## ++## file: drivers/net/wireless/orinoco/Kconfig ++## ++CONFIG_HERMES=m ++CONFIG_PLX_HERMES=m ++CONFIG_TMD_HERMES=m ++CONFIG_NORTEL_HERMES=m ++CONFIG_PCI_HERMES=m ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_RS5C372 is not set ++CONFIG_RTC_DRV_ISL1208=y ++CONFIG_RTC_DRV_X1205=y ++CONFIG_RTC_DRV_PCF8563=y ++# CONFIG_RTC_DRV_M48T86 is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX_OLD is not set ++# CONFIG_SCSI_DPT_I2O is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_HPTIOP 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_PPA is not set ++# CONFIG_SCSI_IMM 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_LPFC is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_DC390T is not set ++# CONFIG_SCSI_NSP32 is not set ++# CONFIG_SCSI_SRP is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic79xx ++## ++# CONFIG_SCSI_AIC79XX is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++# CONFIG_SCSI_AIC7XXX is not set ++ ++## ++## file: drivers/scsi/aic94xx/Kconfig ++## ++# CONFIG_SCSI_AIC94XX is not set ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++ ++## ++## file: drivers/scsi/mvsas/Kconfig ++## ++# CONFIG_SCSI_MVSAS is not set ++ ++## ++## file: drivers/scsi/qla2xxx/Kconfig ++## ++# CONFIG_SCSI_QLA_FC is not set ++ ++## ++## file: drivers/scsi/qla4xxx/Kconfig ++## ++# CONFIG_SCSI_QLA_ISCSI is not set ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI=y ++CONFIG_SPI_BITBANG=m ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=2 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++# CONFIG_SERIAL_8250_EXTENDED is not set ++# CONFIG_SERIAL_JSM is not set ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++ ++## ++## file: drivers/usb/atm/Kconfig ++## ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_ISP116X_HCD=m ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++CONFIG_USB_SL811_HCD=m ++ ++## ++## file: drivers/video/Kconfig ++## ++# CONFIG_FB is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++# CONFIG_VGA_CONSOLE is not set ++# CONFIG_VGACON_SOFT_SCROLLBACK is not set ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_IXP4XX_WATCHDOG=m ++# CONFIG_PCIPCWATCHDOG is not set ++# CONFIG_WDTPCI is not set ++# CONFIG_USBPCWATCHDOG is not set ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_ACORN_PARTITION=y ++# CONFIG_ACORN_PARTITION_CUMANA is not set ++# CONFIG_ACORN_PARTITION_EESOX is not set ++CONFIG_ACORN_PARTITION_ICS=y ++# CONFIG_ACORN_PARTITION_ADFS is not set ++# CONFIG_ACORN_PARTITION_POWERTEC is not set ++CONFIG_ACORN_PARTITION_RISCIX=y ++CONFIG_OSF_PARTITION=y ++CONFIG_AMIGA_PARTITION=y ++CONFIG_ATARI_PARTITION=y ++CONFIG_MAC_PARTITION=y ++CONFIG_BSD_DISKLABEL=y ++CONFIG_MINIX_SUBPARTITION=y ++CONFIG_SOLARIS_X86_PARTITION=y ++CONFIG_UNIXWARE_DISKLABEL=y ++CONFIG_LDM_PARTITION=y ++# CONFIG_LDM_DEBUG is not set ++CONFIG_SGI_PARTITION=y ++CONFIG_ULTRIX_PARTITION=y ++CONFIG_SUN_PARTITION=y ++ ++## ++## file: init/Kconfig ++## ++CONFIG_LOG_BUF_SHIFT=14 ++ ++## ++## file: kernel/Kconfig.preempt ++## ++## choice: Preemption Model ++# CONFIG_PREEMPT is not set ++## end choice ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/ax25/Kconfig ++## ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++# CONFIG_AX25_DAMA_SLAVE is not set ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++ ++## ++## file: net/bridge/netfilter/Kconfig ++## ++# CONFIG_BRIDGE_NF_EBTABLES is not set ++ ++## ++## file: net/decnet/Kconfig ++## ++CONFIG_DECNET=m ++CONFIG_DECNET_ROUTER=y ++ ++## ++## file: net/decnet/netfilter/Kconfig ++## ++# CONFIG_DECNET_NF_GRABULATOR is not set ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++CONFIG_IPX_INTERN=y ++ ++## ++## file: net/irda/Kconfig ++## ++# CONFIG_IRDA is not set ++ ++## ++## file: net/lapb/Kconfig ++## ++CONFIG_LAPB=m ++ ++## ++## file: sound/drivers/Kconfig ++## ++CONFIG_SND_DUMMY=m ++# CONFIG_SND_VIRMIDI is not set ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++ ++## ++## file: sound/pci/Kconfig ++## ++# CONFIG_SND_AD1889 is not set ++# CONFIG_SND_ALI5451 is not set ++# CONFIG_SND_ATIIXP is not set ++# CONFIG_SND_ATIIXP_MODEM is not set ++# CONFIG_SND_AU8810 is not set ++# CONFIG_SND_AU8820 is not set ++# CONFIG_SND_AU8830 is not set ++# CONFIG_SND_AZT3328 is not set ++# CONFIG_SND_BT87X is not set ++# CONFIG_SND_CA0106 is not set ++# CONFIG_SND_CMIPCI is not set ++# CONFIG_SND_CS4281 is not set ++# CONFIG_SND_CS46XX is not set ++# CONFIG_SND_EMU10K1 is not set ++# CONFIG_SND_EMU10K1X is not set ++# CONFIG_SND_ENS1370 is not set ++# CONFIG_SND_ENS1371 is not set ++# CONFIG_SND_ES1938 is not set ++# CONFIG_SND_ES1968 is not set ++# CONFIG_SND_FM801 is not set ++# CONFIG_SND_HDSP is not set ++# CONFIG_SND_HDSPM is not set ++# CONFIG_SND_ICE1712 is not set ++# CONFIG_SND_ICE1724 is not set ++# CONFIG_SND_INTEL8X0 is not set ++# CONFIG_SND_INTEL8X0M is not set ++# CONFIG_SND_KORG1212 is not set ++# CONFIG_SND_MAESTRO3 is not set ++# CONFIG_SND_MIXART is not set ++# CONFIG_SND_NM256 is not set ++CONFIG_SND_PCXHR=m ++# CONFIG_SND_RME32 is not set ++# CONFIG_SND_RME96 is not set ++# CONFIG_SND_RME9652 is not set ++# CONFIG_SND_SONICVIBES is not set ++# CONFIG_SND_TRIDENT is not set ++# CONFIG_SND_VIA82XX is not set ++# CONFIG_SND_VIA82XX_MODEM is not set ++# CONFIG_SND_VX222 is not set ++# CONFIG_SND_YMFPCI is not set ++ ++## ++## file: sound/pci/hda/Kconfig ++## ++# CONFIG_SND_HDA_INTEL is not set ++ +diff --git a/debian/config/armel/config.kirkwood b/debian/config/armel/config.kirkwood +new file mode 100644 +index 0000000..6f48f57 +--- /dev/null ++++ b/debian/config/armel/config.kirkwood +@@ -0,0 +1,692 @@ ++## ++## file: arch/arm/Kconfig ++## ++## choice: ARM system type ++# 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_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++CONFIG_ARCH_KIRKWOOD=y ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++## end choice ++CONFIG_PCI=y ++CONFIG_LEDS=y ++CONFIG_LEDS_CPU=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_ARM_APPENDED_DTB=y ++CONFIG_ARM_ATAG_DTB_COMPAT=y ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++CONFIG_KEXEC=y ++CONFIG_ATAGS_PROC=y ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++# CONFIG_VFP is not set ++# CONFIG_ARTHUR is not set ++ ++## ++## file: arch/arm/mach-kirkwood/Kconfig ++## ++CONFIG_MACH_DB88F6281_BP=y ++CONFIG_MACH_RD88F6192_NAS=y ++CONFIG_MACH_RD88F6281=y ++CONFIG_MACH_MV88F6281GTW_GE=y ++CONFIG_MACH_SHEEVAPLUG=y ++CONFIG_MACH_ESATA_SHEEVAPLUG=y ++CONFIG_MACH_GURUPLUG=y ++CONFIG_ARCH_KIRKWOOD_DT=y ++CONFIG_MACH_DREAMPLUG_DT=y ++CONFIG_MACH_ICONNECT_DT=y ++CONFIG_MACH_TS219=y ++CONFIG_MACH_TS41X=y ++CONFIG_MACH_DOCKSTAR=y ++CONFIG_MACH_OPENRD_BASE=y ++CONFIG_MACH_OPENRD_CLIENT=y ++CONFIG_MACH_OPENRD_ULTIMATE=y ++CONFIG_MACH_NETSPACE_V2=y ++CONFIG_MACH_INETSPACE_V2=y ++CONFIG_MACH_NETSPACE_MAX_V2=y ++CONFIG_MACH_D2NET_V2=y ++CONFIG_MACH_NET2BIG_V2=y ++CONFIG_MACH_NET5BIG_V2=y ++CONFIG_MACH_T5325=y ++ ++## ++## file: arch/arm/mm/Kconfig ++## ++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 ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=m ++CONFIG_SATA_AHCI=m ++# CONFIG_SATA_SIL24 is not set ++CONFIG_ATA_SFF=y ++# CONFIG_PDC_ADMA is not set ++# CONFIG_SATA_QSTOR is not set ++# CONFIG_SATA_SX4 is not set ++# CONFIG_ATA_PIIX is not set ++CONFIG_SATA_MV=m ++# CONFIG_SATA_NV is not set ++# CONFIG_SATA_PROMISE is not set ++# CONFIG_SATA_SIL is not set ++# CONFIG_SATA_SIS is not set ++# CONFIG_SATA_SVW is not set ++# CONFIG_SATA_ULI is not set ++# CONFIG_SATA_VIA is not set ++# CONFIG_SATA_VITESSE is not set ++# CONFIG_PATA_ALI is not set ++# CONFIG_PATA_AMD is not set ++# CONFIG_PATA_ARTOP is not set ++# CONFIG_PATA_ATIIXP is not set ++# CONFIG_PATA_CMD64X is not set ++# CONFIG_PATA_CS5520 is not set ++# CONFIG_PATA_CS5530 is not set ++# CONFIG_PATA_CYPRESS is not set ++# CONFIG_PATA_EFAR is not set ++# CONFIG_PATA_HPT366 is not set ++# CONFIG_PATA_HPT37X is not set ++# CONFIG_PATA_HPT3X2N is not set ++# CONFIG_PATA_HPT3X3 is not set ++# CONFIG_PATA_IT8213 is not set ++# CONFIG_PATA_IT821X is not set ++# CONFIG_PATA_JMICRON is not set ++# CONFIG_PATA_MARVELL is not set ++# CONFIG_PATA_NETCELL is not set ++# CONFIG_PATA_NINJA32 is not set ++# CONFIG_PATA_NS87415 is not set ++# CONFIG_PATA_OLDPIIX is not set ++# CONFIG_PATA_OPTIDMA is not set ++# CONFIG_PATA_PDC2027X is not set ++# CONFIG_PATA_PDC_OLD is not set ++# CONFIG_PATA_RADISYS is not set ++# CONFIG_PATA_SC1200 is not set ++# CONFIG_PATA_SCH is not set ++# CONFIG_PATA_SERVERWORKS is not set ++# CONFIG_PATA_SIL680 is not set ++# CONFIG_PATA_SIS is not set ++# CONFIG_PATA_TRIFLEX is not set ++# CONFIG_PATA_VIA is not set ++# CONFIG_PATA_WINBOND is not set ++# CONFIG_PATA_CMD640_PCI is not set ++# CONFIG_PATA_MPIIX is not set ++# CONFIG_PATA_NS87410 is not set ++# CONFIG_PATA_OPTI is not set ++# CONFIG_PATA_PLATFORM is not set ++# CONFIG_PATA_RZ1000 is not set ++# CONFIG_ATA_GENERIC is not set ++ ++## ++## file: drivers/bluetooth/Kconfig ++## ++# CONFIG_BT_HCIUART is not set ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++ ++## ++## file: drivers/cpuidle/Kconfig ++## ++CONFIG_CPU_IDLE=y ++ ++## ++## file: drivers/crypto/Kconfig ++## ++CONFIG_CRYPTO_DEV_MV_CESA=m ++ ++## ++## file: drivers/dma/Kconfig ++## ++CONFIG_DMADEVICES=y ++CONFIG_MV_XOR=y ++# CONFIG_NET_DMA is not set ++ ++## ++## file: drivers/gpio/Kconfig ++## ++CONFIG_GPIO_SYSFS=y ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++# CONFIG_DRM is not set ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_SENSORS_GPIO_FAN=m ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_MV64XXX=y ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++CONFIG_GAMEPORT=m ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++CONFIG_INPUT_JOYSTICK=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_KEYBOARD_GPIO=m ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++CONFIG_INPUT_TOUCHSCREEN=y ++ ++## ++## file: drivers/isdn/Kconfig ++## ++CONFIG_ISDN=y ++CONFIG_ISDN_CAPI=m ++ ++## ++## file: drivers/isdn/capi/Kconfig ++## ++CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y ++CONFIG_ISDN_CAPI_MIDDLEWARE=y ++CONFIG_ISDN_CAPI_CAPI20=m ++CONFIG_ISDN_CAPI_CAPIDRV=m ++ ++## ++## file: drivers/isdn/hardware/avm/Kconfig ++## ++CONFIG_CAPI_AVM=y ++CONFIG_ISDN_DRV_AVMB1_B1PCI=m ++CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y ++CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m ++CONFIG_ISDN_DRV_AVMB1_AVM_CS=m ++CONFIG_ISDN_DRV_AVMB1_T1PCI=m ++CONFIG_ISDN_DRV_AVMB1_C4=m ++ ++## ++## file: drivers/isdn/hardware/eicon/Kconfig ++## ++CONFIG_CAPI_EICON=y ++CONFIG_ISDN_DIVAS=m ++CONFIG_ISDN_DIVAS_BRIPCI=y ++CONFIG_ISDN_DIVAS_PRIPCI=y ++CONFIG_ISDN_DIVAS_DIVACAPI=m ++CONFIG_ISDN_DIVAS_USERIDI=m ++CONFIG_ISDN_DIVAS_MAINT=m ++ ++## ++## file: drivers/leds/Kconfig ++## ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_NS2=m ++CONFIG_LEDS_NETXBIG=m ++CONFIG_LEDS_TRIGGERS=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++ ++## ++## file: drivers/media/Kconfig ++## ++CONFIG_DVB_CORE=m ++ ++## ++## file: drivers/mmc/Kconfig ++## ++CONFIG_MMC=m ++ ++## ++## file: drivers/mmc/card/Kconfig ++## ++CONFIG_MMC_BLOCK=m ++ ++## ++## file: drivers/mmc/host/Kconfig ++## ++CONFIG_MMC_MVSDIO=m ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++CONFIG_MTD_OF_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLOCK=y ++CONFIG_FTL=m ++CONFIG_NFTL=m ++# CONFIG_NFTL_RW is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set ++# CONFIG_MTD_OOPS is not set ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++CONFIG_MTD_CFI=y ++CONFIG_MTD_JEDECPROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++## choice: Flash cmd/query data swapping ++CONFIG_MTD_CFI_NOSWAP=y ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++## end choice ++CONFIG_MTD_CFI_GEOMETRY=y ++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=y ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_OTP is not set ++CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_CFI_AMDSTD=m ++CONFIG_MTD_CFI_STAA=m ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++## ++## file: drivers/mtd/devices/Kconfig ++## ++# CONFIG_MTD_PMC551 is not set ++CONFIG_MTD_M25P80=y ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_PHYSMAP_START=0x0 ++CONFIG_MTD_PHYSMAP_LEN=0x0 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=0 ++CONFIG_MTD_PHYSMAP_OF=y ++# CONFIG_MTD_IMPA7 is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++## ++## file: drivers/mtd/nand/Kconfig ++## ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_VERIFY_WRITE is not set ++# CONFIG_MTD_NAND_MUSEUM_IDS is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_ALAUDA is not set ++CONFIG_MTD_NAND_ORION=y ++ ++## ++## file: drivers/mtd/onenand/Kconfig ++## ++# CONFIG_MTD_ONENAND is not set ++ ++## ++## file: drivers/mtd/ubi/Kconfig ++## ++CONFIG_MTD_UBI=y ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/atheros/Kconfig ++## ++# CONFIG_ATL1 is not set ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++# CONFIG_BNX2 is not set ++# CONFIG_TIGON3 is not set ++# CONFIG_BNX2X is not set ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++# CONFIG_DL2K is not set ++ ++## ++## file: drivers/net/ethernet/icplus/Kconfig ++## ++# CONFIG_IP1000 is not set ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++# CONFIG_E1000 is not set ++# CONFIG_E1000E is not set ++# CONFIG_IGB is not set ++ ++## ++## file: drivers/net/ethernet/marvell/Kconfig ++## ++CONFIG_MV643XX_ETH=m ++# CONFIG_SKGE is not set ++# CONFIG_SKY2 is not set ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++# CONFIG_NS83820 is not set ++ ++## ++## file: drivers/net/ethernet/packetengines/Kconfig ++## ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++ ++## ++## file: drivers/net/ethernet/qlogic/Kconfig ++## ++# CONFIG_QLA3XXX is not set ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++# CONFIG_R8169 is not set ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++# CONFIG_SIS190 is not set ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++# CONFIG_VIA_VELOCITY is not set ++ ++## ++## file: drivers/net/phy/Kconfig ++## ++#. Turned off because this causes networking on some Kirkwood machines to fail ++# CONFIG_MARVELL_PHY is not set ++ ++## ++## file: drivers/net/wireless/mwifiex/Kconfig ++## ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++ ++## ++## file: drivers/of/Kconfig ++## ++CONFIG_PROC_DEVICETREE=y ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_S35390A=y ++CONFIG_RTC_DRV_MV=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX_OLD is not set ++# CONFIG_SCSI_DPT_I2O is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_HPTIOP 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_PPA is not set ++# CONFIG_SCSI_IMM 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_LPFC is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_DC390T is not set ++# CONFIG_SCSI_NSP32 is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic79xx ++## ++# CONFIG_SCSI_AIC79XX is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++# CONFIG_SCSI_AIC7XXX is not set ++ ++## ++## file: drivers/scsi/aic94xx/Kconfig ++## ++# CONFIG_SCSI_AIC94XX is not set ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++ ++## ++## file: drivers/scsi/mvsas/Kconfig ++## ++# CONFIG_SCSI_MVSAS is not set ++ ++## ++## file: drivers/scsi/qla2xxx/Kconfig ++## ++# CONFIG_SCSI_QLA_FC is not set ++ ++## ++## file: drivers/scsi/qla4xxx/Kconfig ++## ++# CONFIG_SCSI_QLA_ISCSI is not set ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI_ORION=y ++ ++## ++## file: drivers/ssb/Kconfig ++## ++# CONFIG_SSB is not set ++ ++## ++## file: drivers/staging/xgifb/Kconfig ++## ++CONFIG_FB_XGI=m ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_PCI=y ++CONFIG_SERIAL_8250_NR_UARTS=4 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++# CONFIG_SERIAL_8250_EXTENDED is not set ++# CONFIG_SERIAL_8250_DW is not set ++CONFIG_SERIAL_OF_PLATFORM=y ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB_SUPPORT=y ++CONFIG_USB=m ++ ++## ++## file: drivers/usb/atm/Kconfig ++## ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++# CONFIG_USB_ISP116X_HCD is not set ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++CONFIG_USB_SL811_HCD=m ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=m ++ ++## ++## file: drivers/video/console/Kconfig ++## ++# CONFIG_VGA_CONSOLE is not set ++CONFIG_FRAMEBUFFER_CONSOLE=m ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_ORION_WATCHDOG=m ++ ++## ++## file: fs/jffs2/Kconfig ++## ++CONFIG_JFFS2_FS=y ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_ACORN_PARTITION=y ++# CONFIG_ACORN_PARTITION_CUMANA is not set ++# CONFIG_ACORN_PARTITION_EESOX is not set ++CONFIG_ACORN_PARTITION_ICS=y ++# CONFIG_ACORN_PARTITION_ADFS is not set ++# CONFIG_ACORN_PARTITION_POWERTEC is not set ++CONFIG_ACORN_PARTITION_RISCIX=y ++CONFIG_OSF_PARTITION=y ++CONFIG_AMIGA_PARTITION=y ++CONFIG_ATARI_PARTITION=y ++CONFIG_MAC_PARTITION=y ++CONFIG_BSD_DISKLABEL=y ++CONFIG_MINIX_SUBPARTITION=y ++CONFIG_SOLARIS_X86_PARTITION=y ++CONFIG_UNIXWARE_DISKLABEL=y ++CONFIG_LDM_PARTITION=y ++# CONFIG_LDM_DEBUG is not set ++CONFIG_SGI_PARTITION=y ++CONFIG_ULTRIX_PARTITION=y ++CONFIG_SUN_PARTITION=y ++ ++## ++## file: fs/ubifs/Kconfig ++## ++CONFIG_UBIFS_FS=y ++ ++## ++## file: kernel/power/Kconfig ++## ++# CONFIG_SUSPEND is not set ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/atm/Kconfig ++## ++CONFIG_ATM=m ++ ++## ++## file: net/ax25/Kconfig ++## ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++# CONFIG_AX25_DAMA_SLAVE is not set ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++ ++## ++## file: sound/soc/Kconfig ++## ++CONFIG_SND_SOC=m ++ ++## ++## file: sound/soc/codecs/Kconfig ++## ++# CONFIG_SND_SOC_ALL_CODECS is not set ++ ++## ++## file: sound/soc/kirkwood/Kconfig ++## ++CONFIG_SND_KIRKWOOD_SOC=m ++CONFIG_SND_KIRKWOOD_SOC_OPENRD=m ++CONFIG_SND_KIRKWOOD_SOC_T5325=m ++ +diff --git a/debian/config/armel/config.mv78xx0 b/debian/config/armel/config.mv78xx0 +new file mode 100644 +index 0000000..337d21b +--- /dev/null ++++ b/debian/config/armel/config.mv78xx0 +@@ -0,0 +1,589 @@ ++## ++## file: arch/arm/Kconfig ++## ++CONFIG_MMU=y ++## choice: ARM system type ++# 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_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++CONFIG_ARCH_MV78XX0=y ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++## end choice ++CONFIG_PCI=y ++CONFIG_HIGHMEM=y ++CONFIG_LEDS=y ++CONFIG_LEDS_CPU=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++CONFIG_KEXEC=y ++CONFIG_ATAGS_PROC=y ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++# CONFIG_ARTHUR is not set ++ ++## ++## file: arch/arm/mach-mv78xx0/Kconfig ++## ++CONFIG_MACH_DB78X00_BP=y ++CONFIG_MACH_RD78X00_MASA=y ++CONFIG_MACH_TERASTATION_WXL=y ++ ++## ++## file: arch/arm/mm/Kconfig ++## ++CONFIG_CPU_FEROCEON_OLD_ID=y ++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 ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=m ++# CONFIG_SATA_AHCI is not set ++# CONFIG_SATA_SIL24 is not set ++CONFIG_ATA_SFF=y ++# CONFIG_PDC_ADMA is not set ++# CONFIG_SATA_QSTOR is not set ++# CONFIG_SATA_SX4 is not set ++# CONFIG_ATA_PIIX is not set ++CONFIG_SATA_MV=m ++# CONFIG_SATA_NV is not set ++# CONFIG_SATA_PROMISE is not set ++# CONFIG_SATA_SIL is not set ++# CONFIG_SATA_SIS is not set ++# CONFIG_SATA_SVW is not set ++# CONFIG_SATA_ULI is not set ++# CONFIG_SATA_VIA is not set ++# CONFIG_SATA_VITESSE is not set ++# CONFIG_PATA_ALI is not set ++# CONFIG_PATA_AMD is not set ++# CONFIG_PATA_ARTOP is not set ++# CONFIG_PATA_ATIIXP is not set ++# CONFIG_PATA_CMD64X is not set ++# CONFIG_PATA_CS5520 is not set ++# CONFIG_PATA_CS5530 is not set ++# CONFIG_PATA_CYPRESS is not set ++# CONFIG_PATA_EFAR is not set ++# CONFIG_PATA_HPT366 is not set ++# CONFIG_PATA_HPT37X is not set ++# CONFIG_PATA_HPT3X2N is not set ++# CONFIG_PATA_HPT3X3 is not set ++# CONFIG_PATA_IT8213 is not set ++# CONFIG_PATA_IT821X is not set ++# CONFIG_PATA_JMICRON is not set ++# CONFIG_PATA_MARVELL is not set ++# CONFIG_PATA_NETCELL is not set ++# CONFIG_PATA_NINJA32 is not set ++# CONFIG_PATA_NS87415 is not set ++# CONFIG_PATA_OLDPIIX is not set ++# CONFIG_PATA_OPTIDMA is not set ++# CONFIG_PATA_PDC2027X is not set ++# CONFIG_PATA_PDC_OLD is not set ++# CONFIG_PATA_RADISYS is not set ++# CONFIG_PATA_SC1200 is not set ++# CONFIG_PATA_SCH is not set ++# CONFIG_PATA_SERVERWORKS is not set ++# CONFIG_PATA_SIL680 is not set ++# CONFIG_PATA_SIS is not set ++# CONFIG_PATA_TRIFLEX is not set ++# CONFIG_PATA_VIA is not set ++# CONFIG_PATA_WINBOND is not set ++# CONFIG_PATA_CMD640_PCI is not set ++# CONFIG_PATA_MPIIX is not set ++# CONFIG_PATA_NS87410 is not set ++# CONFIG_PATA_OPTI is not set ++# CONFIG_PATA_PLATFORM is not set ++# CONFIG_PATA_RZ1000 is not set ++# CONFIG_ATA_GENERIC is not set ++ ++## ++## file: drivers/bluetooth/Kconfig ++## ++# CONFIG_BT_HCIUART is not set ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++ ++## ++## file: drivers/crypto/Kconfig ++## ++CONFIG_CRYPTO_DEV_MV_CESA=m ++ ++## ++## file: drivers/dma/Kconfig ++## ++CONFIG_DMADEVICES=y ++CONFIG_MV_XOR=y ++# CONFIG_NET_DMA is not set ++ ++## ++## file: drivers/gpio/Kconfig ++## ++CONFIG_GPIO_SYSFS=y ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++# CONFIG_DRM is not set ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_SENSORS_G760A=m ++CONFIG_SENSORS_GPIO_FAN=m ++CONFIG_SENSORS_LM75=m ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_MV64XXX=y ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++CONFIG_GAMEPORT=m ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++CONFIG_INPUT_JOYSTICK=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_KEYBOARD_GPIO=m ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++CONFIG_INPUT_TOUCHSCREEN=y ++ ++## ++## file: drivers/isdn/Kconfig ++## ++CONFIG_ISDN=y ++CONFIG_ISDN_CAPI=m ++ ++## ++## file: drivers/isdn/capi/Kconfig ++## ++CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y ++CONFIG_ISDN_CAPI_MIDDLEWARE=y ++CONFIG_ISDN_CAPI_CAPI20=m ++CONFIG_ISDN_CAPI_CAPIDRV=m ++ ++## ++## file: drivers/isdn/hardware/avm/Kconfig ++## ++CONFIG_CAPI_AVM=y ++CONFIG_ISDN_DRV_AVMB1_B1PCI=m ++CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y ++CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m ++CONFIG_ISDN_DRV_AVMB1_AVM_CS=m ++CONFIG_ISDN_DRV_AVMB1_T1PCI=m ++CONFIG_ISDN_DRV_AVMB1_C4=m ++ ++## ++## file: drivers/isdn/hardware/eicon/Kconfig ++## ++CONFIG_CAPI_EICON=y ++CONFIG_ISDN_DIVAS=m ++CONFIG_ISDN_DIVAS_BRIPCI=y ++CONFIG_ISDN_DIVAS_PRIPCI=y ++CONFIG_ISDN_DIVAS_DIVACAPI=m ++CONFIG_ISDN_DIVAS_USERIDI=m ++CONFIG_ISDN_DIVAS_MAINT=m ++ ++## ++## file: drivers/leds/Kconfig ++## ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGERS=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++ ++## ++## file: drivers/media/Kconfig ++## ++CONFIG_DVB_CORE=m ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++CONFIG_FTL=m ++CONFIG_NFTL=m ++# CONFIG_NFTL_RW is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set ++# CONFIG_MTD_OOPS is not set ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++CONFIG_MTD_CFI=y ++CONFIG_MTD_JEDECPROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++## choice: Flash cmd/query data swapping ++CONFIG_MTD_CFI_NOSWAP=y ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++## end choice ++CONFIG_MTD_CFI_GEOMETRY=y ++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=y ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_OTP is not set ++#. Needed e.g. on QNAP devices ++CONFIG_MTD_CFI_INTELEXT=y ++#. Needed e.g. on the D-Link DNS-323 ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_STAA=m ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++## ++## file: drivers/mtd/devices/Kconfig ++## ++# CONFIG_MTD_PMC551 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 ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_PHYSMAP_START=0x0 ++CONFIG_MTD_PHYSMAP_LEN=0x0 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=0 ++# CONFIG_MTD_IMPA7 is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++## ++## file: drivers/mtd/nand/Kconfig ++## ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++CONFIG_MTD_NAND_VERIFY_WRITE=y ++# CONFIG_MTD_NAND_MUSEUM_IDS is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_ALAUDA is not set ++CONFIG_MTD_NAND_ORION=y ++ ++## ++## file: drivers/mtd/onenand/Kconfig ++## ++# CONFIG_MTD_ONENAND is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/atheros/Kconfig ++## ++# CONFIG_ATL1 is not set ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++# CONFIG_BNX2 is not set ++# CONFIG_TIGON3 is not set ++# CONFIG_BNX2X is not set ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++# CONFIG_DL2K is not set ++ ++## ++## file: drivers/net/ethernet/icplus/Kconfig ++## ++# CONFIG_IP1000 is not set ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++# CONFIG_E1000 is not set ++# CONFIG_E1000E is not set ++# CONFIG_IGB is not set ++ ++## ++## file: drivers/net/ethernet/marvell/Kconfig ++## ++CONFIG_MV643XX_ETH=m ++# CONFIG_SKGE is not set ++# CONFIG_SKY2 is not set ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++# CONFIG_NS83820 is not set ++ ++## ++## file: drivers/net/ethernet/packetengines/Kconfig ++## ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++ ++## ++## file: drivers/net/ethernet/qlogic/Kconfig ++## ++# CONFIG_QLA3XXX is not set ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++# CONFIG_R8169 is not set ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++# CONFIG_SIS190 is not set ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++# CONFIG_VIA_VELOCITY is not set ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_DS1307=y ++CONFIG_RTC_DRV_RS5C372=y ++CONFIG_RTC_DRV_PCF8563=y ++CONFIG_RTC_DRV_M41T80=y ++CONFIG_RTC_DRV_S35390A=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX_OLD is not set ++# CONFIG_SCSI_DPT_I2O is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_HPTIOP 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_PPA is not set ++# CONFIG_SCSI_IMM 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_LPFC is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_DC390T is not set ++# CONFIG_SCSI_NSP32 is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic79xx ++## ++# CONFIG_SCSI_AIC79XX is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++# CONFIG_SCSI_AIC7XXX is not set ++ ++## ++## file: drivers/scsi/aic94xx/Kconfig ++## ++# CONFIG_SCSI_AIC94XX is not set ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++ ++## ++## file: drivers/scsi/mvsas/Kconfig ++## ++# CONFIG_SCSI_MVSAS is not set ++ ++## ++## file: drivers/scsi/qla2xxx/Kconfig ++## ++# CONFIG_SCSI_QLA_FC is not set ++ ++## ++## file: drivers/scsi/qla4xxx/Kconfig ++## ++# CONFIG_SCSI_QLA_ISCSI is not set ++ ++## ++## file: drivers/ssb/Kconfig ++## ++# CONFIG_SSB is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_PCI=y ++CONFIG_SERIAL_8250_NR_UARTS=4 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++# CONFIG_SERIAL_8250_EXTENDED is not set ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB_SUPPORT=y ++CONFIG_USB=m ++ ++## ++## file: drivers/usb/atm/Kconfig ++## ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++# CONFIG_USB_ISP116X_HCD is not set ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++CONFIG_USB_SL811_HCD=m ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=m ++ ++## ++## file: drivers/video/console/Kconfig ++## ++# CONFIG_VGA_CONSOLE is not set ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_ORION_WATCHDOG=m ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_ACORN_PARTITION=y ++# CONFIG_ACORN_PARTITION_CUMANA is not set ++# CONFIG_ACORN_PARTITION_EESOX is not set ++CONFIG_ACORN_PARTITION_ICS=y ++# CONFIG_ACORN_PARTITION_ADFS is not set ++# CONFIG_ACORN_PARTITION_POWERTEC is not set ++CONFIG_ACORN_PARTITION_RISCIX=y ++CONFIG_OSF_PARTITION=y ++CONFIG_AMIGA_PARTITION=y ++CONFIG_ATARI_PARTITION=y ++CONFIG_MAC_PARTITION=y ++CONFIG_BSD_DISKLABEL=y ++CONFIG_MINIX_SUBPARTITION=y ++CONFIG_SOLARIS_X86_PARTITION=y ++CONFIG_UNIXWARE_DISKLABEL=y ++CONFIG_LDM_PARTITION=y ++# CONFIG_LDM_DEBUG is not set ++CONFIG_SGI_PARTITION=y ++CONFIG_ULTRIX_PARTITION=y ++CONFIG_SUN_PARTITION=y ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/atm/Kconfig ++## ++CONFIG_ATM=m ++ ++## ++## file: net/ax25/Kconfig ++## ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++# CONFIG_AX25_DAMA_SLAVE is not set ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++ +diff --git a/debian/config/armel/config.orion5x b/debian/config/armel/config.orion5x +new file mode 100644 +index 0000000..f7aefa9 +--- /dev/null ++++ b/debian/config/armel/config.orion5x +@@ -0,0 +1,612 @@ ++## ++## file: arch/arm/Kconfig ++## ++## choice: ARM system type ++# 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_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++CONFIG_ARCH_ORION5X=y ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++## end choice ++CONFIG_PCI=y ++CONFIG_LEDS=y ++CONFIG_LEDS_CPU=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++CONFIG_KEXEC=y ++CONFIG_ATAGS_PROC=y ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++# CONFIG_ARTHUR is not set ++ ++## ++## file: arch/arm/mach-orion5x/Kconfig ++## ++CONFIG_MACH_DB88F5281=y ++CONFIG_MACH_RD88F5182=y ++CONFIG_MACH_KUROBOX_PRO=y ++CONFIG_MACH_DNS323=y ++CONFIG_MACH_TS209=y ++CONFIG_MACH_TERASTATION_PRO2=y ++CONFIG_MACH_LINKSTATION_PRO=y ++CONFIG_MACH_LINKSTATION_LSCHL=y ++CONFIG_MACH_LINKSTATION_MINI=y ++CONFIG_MACH_LINKSTATION_LS_HGL=y ++CONFIG_MACH_TS409=y ++CONFIG_MACH_WRT350N_V2=y ++CONFIG_MACH_TS78XX=y ++CONFIG_MACH_MV2120=y ++CONFIG_MACH_EDMINI_V2=y ++CONFIG_MACH_D2NET=y ++CONFIG_MACH_BIGDISK=y ++CONFIG_MACH_NET2BIG=y ++CONFIG_MACH_MSS2=y ++CONFIG_MACH_WNR854T=y ++CONFIG_MACH_RD88F5181L_GE=y ++CONFIG_MACH_RD88F5181L_FXO=y ++CONFIG_MACH_RD88F6183AP_GE=y ++ ++## ++## file: arch/arm/mm/Kconfig ++## ++CONFIG_CPU_FEROCEON_OLD_ID=y ++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 ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=m ++# CONFIG_SATA_AHCI is not set ++# CONFIG_SATA_SIL24 is not set ++CONFIG_ATA_SFF=y ++# CONFIG_PDC_ADMA is not set ++# CONFIG_SATA_QSTOR is not set ++# CONFIG_SATA_SX4 is not set ++# CONFIG_ATA_PIIX is not set ++CONFIG_SATA_MV=m ++# CONFIG_SATA_NV is not set ++# CONFIG_SATA_PROMISE is not set ++# CONFIG_SATA_SIL is not set ++# CONFIG_SATA_SIS is not set ++# CONFIG_SATA_SVW is not set ++# CONFIG_SATA_ULI is not set ++# CONFIG_SATA_VIA is not set ++# CONFIG_SATA_VITESSE is not set ++# CONFIG_PATA_ALI is not set ++# CONFIG_PATA_AMD is not set ++# CONFIG_PATA_ARTOP is not set ++# CONFIG_PATA_ATIIXP is not set ++# CONFIG_PATA_CMD64X is not set ++# CONFIG_PATA_CS5520 is not set ++# CONFIG_PATA_CS5530 is not set ++# CONFIG_PATA_CYPRESS is not set ++# CONFIG_PATA_EFAR is not set ++# CONFIG_PATA_HPT366 is not set ++# CONFIG_PATA_HPT37X is not set ++# CONFIG_PATA_HPT3X2N is not set ++# CONFIG_PATA_HPT3X3 is not set ++# CONFIG_PATA_IT8213 is not set ++# CONFIG_PATA_IT821X is not set ++# CONFIG_PATA_JMICRON is not set ++# CONFIG_PATA_MARVELL is not set ++# CONFIG_PATA_NETCELL is not set ++# CONFIG_PATA_NINJA32 is not set ++# CONFIG_PATA_NS87415 is not set ++# CONFIG_PATA_OLDPIIX is not set ++# CONFIG_PATA_OPTIDMA is not set ++# CONFIG_PATA_PDC2027X is not set ++# CONFIG_PATA_PDC_OLD is not set ++# CONFIG_PATA_RADISYS is not set ++# CONFIG_PATA_SC1200 is not set ++# CONFIG_PATA_SCH is not set ++# CONFIG_PATA_SERVERWORKS is not set ++# CONFIG_PATA_SIL680 is not set ++# CONFIG_PATA_SIS is not set ++# CONFIG_PATA_TRIFLEX is not set ++# CONFIG_PATA_VIA is not set ++# CONFIG_PATA_WINBOND is not set ++# CONFIG_PATA_CMD640_PCI is not set ++# CONFIG_PATA_MPIIX is not set ++# CONFIG_PATA_NS87410 is not set ++# CONFIG_PATA_OPTI is not set ++# CONFIG_PATA_PLATFORM is not set ++# CONFIG_PATA_RZ1000 is not set ++# CONFIG_ATA_GENERIC is not set ++ ++## ++## file: drivers/bluetooth/Kconfig ++## ++# CONFIG_BT_HCIUART is not set ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++ ++## ++## file: drivers/crypto/Kconfig ++## ++CONFIG_CRYPTO_DEV_MV_CESA=m ++ ++## ++## file: drivers/dma/Kconfig ++## ++CONFIG_DMADEVICES=y ++CONFIG_MV_XOR=y ++# CONFIG_NET_DMA is not set ++ ++## ++## file: drivers/gpio/Kconfig ++## ++CONFIG_GPIO_SYSFS=y ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++# CONFIG_DRM is not set ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_SENSORS_G760A=m ++CONFIG_SENSORS_GPIO_FAN=m ++CONFIG_SENSORS_LM75=m ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_MV64XXX=y ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++CONFIG_GAMEPORT=m ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++CONFIG_INPUT_JOYSTICK=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_KEYBOARD_GPIO=m ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++CONFIG_INPUT_TOUCHSCREEN=y ++ ++## ++## file: drivers/isdn/Kconfig ++## ++CONFIG_ISDN=y ++CONFIG_ISDN_CAPI=m ++ ++## ++## file: drivers/isdn/capi/Kconfig ++## ++CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y ++CONFIG_ISDN_CAPI_MIDDLEWARE=y ++CONFIG_ISDN_CAPI_CAPI20=m ++CONFIG_ISDN_CAPI_CAPIDRV=m ++ ++## ++## file: drivers/isdn/hardware/avm/Kconfig ++## ++CONFIG_CAPI_AVM=y ++CONFIG_ISDN_DRV_AVMB1_B1PCI=m ++CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y ++CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m ++CONFIG_ISDN_DRV_AVMB1_AVM_CS=m ++CONFIG_ISDN_DRV_AVMB1_T1PCI=m ++CONFIG_ISDN_DRV_AVMB1_C4=m ++ ++## ++## file: drivers/isdn/hardware/eicon/Kconfig ++## ++CONFIG_CAPI_EICON=y ++CONFIG_ISDN_DIVAS=m ++CONFIG_ISDN_DIVAS_BRIPCI=y ++CONFIG_ISDN_DIVAS_PRIPCI=y ++CONFIG_ISDN_DIVAS_DIVACAPI=m ++CONFIG_ISDN_DIVAS_USERIDI=m ++CONFIG_ISDN_DIVAS_MAINT=m ++ ++## ++## file: drivers/leds/Kconfig ++## ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGERS=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++ ++## ++## file: drivers/media/Kconfig ++## ++CONFIG_DVB_CORE=m ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++CONFIG_FTL=m ++CONFIG_NFTL=m ++# CONFIG_NFTL_RW is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set ++# CONFIG_MTD_OOPS is not set ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++CONFIG_MTD_CFI=y ++CONFIG_MTD_JEDECPROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++## choice: Flash cmd/query data swapping ++CONFIG_MTD_CFI_NOSWAP=y ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++## end choice ++CONFIG_MTD_CFI_GEOMETRY=y ++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=y ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_OTP is not set ++#. Needed e.g. on QNAP devices ++CONFIG_MTD_CFI_INTELEXT=y ++#. Needed e.g. on the D-Link DNS-323 ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_STAA=m ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++## ++## file: drivers/mtd/devices/Kconfig ++## ++# CONFIG_MTD_PMC551 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 ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_PHYSMAP_START=0x0 ++CONFIG_MTD_PHYSMAP_LEN=0x0 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=0 ++# CONFIG_MTD_IMPA7 is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++## ++## file: drivers/mtd/nand/Kconfig ++## ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++CONFIG_MTD_NAND_VERIFY_WRITE=y ++# CONFIG_MTD_NAND_MUSEUM_IDS is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_ALAUDA is not set ++CONFIG_MTD_NAND_ORION=y ++ ++## ++## file: drivers/mtd/onenand/Kconfig ++## ++# CONFIG_MTD_ONENAND is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/atheros/Kconfig ++## ++# CONFIG_ATL1 is not set ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++# CONFIG_BNX2 is not set ++# CONFIG_TIGON3 is not set ++# CONFIG_BNX2X is not set ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++# CONFIG_DL2K is not set ++ ++## ++## file: drivers/net/ethernet/icplus/Kconfig ++## ++# CONFIG_IP1000 is not set ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++# CONFIG_E1000 is not set ++# CONFIG_E1000E is not set ++# CONFIG_IGB is not set ++ ++## ++## file: drivers/net/ethernet/marvell/Kconfig ++## ++CONFIG_MV643XX_ETH=m ++# CONFIG_SKGE is not set ++# CONFIG_SKY2 is not set ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++# CONFIG_NS83820 is not set ++ ++## ++## file: drivers/net/ethernet/packetengines/Kconfig ++## ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++ ++## ++## file: drivers/net/ethernet/qlogic/Kconfig ++## ++# CONFIG_QLA3XXX is not set ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++# CONFIG_R8169 is not set ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++# CONFIG_SIS190 is not set ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++# CONFIG_VIA_VELOCITY is not set ++ ++## ++## file: drivers/net/phy/Kconfig ++## ++#. Turned off because this causes networking on some Orion machines to fail ++# CONFIG_MARVELL_PHY is not set ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_DS1307=y ++CONFIG_RTC_DRV_RS5C372=y ++CONFIG_RTC_DRV_PCF8563=y ++CONFIG_RTC_DRV_M41T80=y ++CONFIG_RTC_DRV_S35390A=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX_OLD is not set ++# CONFIG_SCSI_DPT_I2O is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_HPTIOP 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_PPA is not set ++# CONFIG_SCSI_IMM 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_LPFC is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_DC390T is not set ++# CONFIG_SCSI_NSP32 is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic79xx ++## ++# CONFIG_SCSI_AIC79XX is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++# CONFIG_SCSI_AIC7XXX is not set ++ ++## ++## file: drivers/scsi/aic94xx/Kconfig ++## ++# CONFIG_SCSI_AIC94XX is not set ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++ ++## ++## file: drivers/scsi/mvsas/Kconfig ++## ++# CONFIG_SCSI_MVSAS is not set ++ ++## ++## file: drivers/scsi/qla2xxx/Kconfig ++## ++# CONFIG_SCSI_QLA_FC is not set ++ ++## ++## file: drivers/scsi/qla4xxx/Kconfig ++## ++# CONFIG_SCSI_QLA_ISCSI is not set ++ ++## ++## file: drivers/ssb/Kconfig ++## ++# CONFIG_SSB is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_PCI=y ++CONFIG_SERIAL_8250_NR_UARTS=4 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++# CONFIG_SERIAL_8250_EXTENDED is not set ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB_SUPPORT=y ++CONFIG_USB=m ++ ++## ++## file: drivers/usb/atm/Kconfig ++## ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++# CONFIG_USB_ISP116X_HCD is not set ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++CONFIG_USB_SL811_HCD=m ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=m ++ ++## ++## file: drivers/video/console/Kconfig ++## ++# CONFIG_VGA_CONSOLE is not set ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_ORION_WATCHDOG=m ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_ACORN_PARTITION=y ++# CONFIG_ACORN_PARTITION_CUMANA is not set ++# CONFIG_ACORN_PARTITION_EESOX is not set ++CONFIG_ACORN_PARTITION_ICS=y ++# CONFIG_ACORN_PARTITION_ADFS is not set ++# CONFIG_ACORN_PARTITION_POWERTEC is not set ++CONFIG_ACORN_PARTITION_RISCIX=y ++CONFIG_OSF_PARTITION=y ++CONFIG_AMIGA_PARTITION=y ++CONFIG_ATARI_PARTITION=y ++CONFIG_MAC_PARTITION=y ++CONFIG_BSD_DISKLABEL=y ++CONFIG_MINIX_SUBPARTITION=y ++CONFIG_SOLARIS_X86_PARTITION=y ++CONFIG_UNIXWARE_DISKLABEL=y ++CONFIG_LDM_PARTITION=y ++# CONFIG_LDM_DEBUG is not set ++CONFIG_SGI_PARTITION=y ++CONFIG_ULTRIX_PARTITION=y ++CONFIG_SUN_PARTITION=y ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/atm/Kconfig ++## ++CONFIG_ATM=m ++ ++## ++## file: net/ax25/Kconfig ++## ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++# CONFIG_AX25_DAMA_SLAVE is not set ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++ +diff --git a/debian/config/armel/config.versatile b/debian/config/armel/config.versatile +new file mode 100644 +index 0000000..a2ce2bc +--- /dev/null ++++ b/debian/config/armel/config.versatile +@@ -0,0 +1,519 @@ ++## ++## file: arch/arm/Kconfig ++## ++## choice: ARM system type ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++CONFIG_ARCH_VERSATILE=y ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++## end choice ++CONFIG_PCI=y ++# CONFIG_LEDS is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++CONFIG_KEXEC=y ++CONFIG_ATAGS_PROC=y ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++# CONFIG_ARTHUR is not set ++ ++## ++## file: arch/arm/Kconfig.debug ++## ++# CONFIG_DEBUG_USER is not set ++ ++## ++## file: arch/arm/mach-versatile/Kconfig ++## ++CONFIG_ARCH_VERSATILE_PB=y ++CONFIG_MACH_VERSATILE_AB=y ++ ++## ++## file: arch/arm/mm/Kconfig ++## ++CONFIG_CPU_ARM926T=y ++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 ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=m ++CONFIG_SATA_AHCI=m ++CONFIG_SATA_SIL24=m ++# CONFIG_PDC_ADMA is not set ++# CONFIG_SATA_QSTOR is not set ++CONFIG_SATA_SX4=m ++# CONFIG_ATA_PIIX is not set ++# CONFIG_SATA_MV is not set ++# CONFIG_SATA_NV is not set ++CONFIG_SATA_PROMISE=m ++CONFIG_SATA_SIL=m ++# CONFIG_SATA_SIS is not set ++# CONFIG_SATA_SVW is not set ++# CONFIG_SATA_ULI is not set ++CONFIG_SATA_VIA=m ++# CONFIG_SATA_VITESSE is not set ++# CONFIG_PATA_ALI is not set ++# CONFIG_PATA_AMD is not set ++# CONFIG_PATA_ARTOP is not set ++# CONFIG_PATA_ATIIXP is not set ++# CONFIG_PATA_CMD64X is not set ++# CONFIG_PATA_CS5520 is not set ++# CONFIG_PATA_CS5530 is not set ++# CONFIG_PATA_CYPRESS is not set ++# CONFIG_PATA_EFAR is not set ++# CONFIG_PATA_HPT366 is not set ++# CONFIG_PATA_HPT37X is not set ++# CONFIG_PATA_HPT3X2N is not set ++# CONFIG_PATA_HPT3X3 is not set ++# CONFIG_PATA_IT8213 is not set ++# CONFIG_PATA_IT821X is not set ++# CONFIG_PATA_JMICRON is not set ++# CONFIG_PATA_MARVELL is not set ++# CONFIG_PATA_NETCELL is not set ++# CONFIG_PATA_NS87415 is not set ++# CONFIG_PATA_OLDPIIX is not set ++# CONFIG_PATA_OPTIDMA is not set ++# CONFIG_PATA_PDC2027X is not set ++# CONFIG_PATA_PDC_OLD is not set ++# CONFIG_PATA_RADISYS is not set ++# CONFIG_PATA_SC1200 is not set ++# CONFIG_PATA_SERVERWORKS is not set ++# CONFIG_PATA_SIL680 is not set ++# CONFIG_PATA_SIS is not set ++# CONFIG_PATA_TRIFLEX is not set ++# CONFIG_PATA_VIA is not set ++# CONFIG_PATA_WINBOND is not set ++# CONFIG_PATA_CMD640_PCI is not set ++# CONFIG_PATA_MPIIX is not set ++# CONFIG_PATA_NS87410 is not set ++# CONFIG_PATA_OPTI is not set ++# CONFIG_PATA_RZ1000 is not set ++# CONFIG_ATA_GENERIC is not set ++ ++## ++## file: drivers/atm/Kconfig ++## ++CONFIG_ATM_DRIVERS=y ++# CONFIG_ATM_DUMMY is not set ++# CONFIG_ATM_TCP is not set ++# CONFIG_ATM_LANAI is not set ++# CONFIG_ATM_ENI is not set ++# CONFIG_ATM_FIRESTREAM is not set ++# CONFIG_ATM_ZATM is not set ++# CONFIG_ATM_NICSTAR is not set ++# CONFIG_ATM_IDT77252 is not set ++# CONFIG_ATM_AMBASSADOR is not set ++# CONFIG_ATM_HORIZON is not set ++# CONFIG_ATM_IA is not set ++# CONFIG_ATM_HE is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++# CONFIG_NVRAM is not set ++# CONFIG_APPLICOM is not set ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=m ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_OCORES is not set ++CONFIG_I2C_PCA_PLATFORM=m ++# CONFIG_I2C_SIMTEC is not set ++CONFIG_I2C_VERSATILE=m ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++CONFIG_KEYBOARD_STOWAWAY=m ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++CONFIG_SERIO_AMBAKMI=y ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_INPUT_TOUCHSCREEN is not set ++ ++## ++## file: drivers/leds/Kconfig ++## ++# CONFIG_NEW_LEDS is not set ++ ++## ++## file: drivers/net/Kconfig ++## ++# CONFIG_NET_FC is not set ++CONFIG_IFB=m ++# CONFIG_NETPOLL_TRAP is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/Kconfig ++## ++CONFIG_FEALNX=m ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++CONFIG_NET_VENDOR_3COM=y ++CONFIG_VORTEX=m ++CONFIG_TYPHOON=m ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++# CONFIG_AX88796 is not set ++CONFIG_NE2K_PCI=m ++ ++## ++## file: drivers/net/ethernet/adaptec/Kconfig ++## ++CONFIG_ADAPTEC_STARFIRE=m ++ ++## ++## file: drivers/net/ethernet/alteon/Kconfig ++## ++# CONFIG_ACENIC is not set ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_AMD8111_ETH=m ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++# CONFIG_B44 is not set ++# CONFIG_BNX2 is not set ++# CONFIG_TIGON3 is not set ++# CONFIG_BNX2X is not set ++ ++## ++## file: drivers/net/ethernet/davicom/Kconfig ++## ++# CONFIG_DM9000 is not set ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++CONFIG_SUNDANCE=m ++# CONFIG_SUNDANCE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++CONFIG_HP100=m ++ ++## ++## file: drivers/net/ethernet/icplus/Kconfig ++## ++# CONFIG_IP1000 is not set ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++CONFIG_E100=m ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_NATSEMI=m ++ ++## ++## file: drivers/net/ethernet/nvidia/Kconfig ++## ++# CONFIG_FORCEDETH is not set ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_8139CP=m ++CONFIG_8139TOO=m ++# CONFIG_8139TOO_PIO is not set ++CONFIG_8139TOO_TUNE_TWISTER=y ++CONFIG_8139TOO_8129=y ++# CONFIG_8139_OLD_RX_RESET is not set ++ ++## ++## file: drivers/net/ethernet/silan/Kconfig ++## ++CONFIG_SC92031=m ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++CONFIG_SIS900=m ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_SMC91X=m ++CONFIG_EPIC100=m ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++ ++## ++## file: drivers/net/ethernet/ti/Kconfig ++## ++# CONFIG_TLAN is not set ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++CONFIG_VIA_RHINE=m ++# CONFIG_VIA_RHINE_MMIO is not set ++ ++## ++## file: drivers/net/fddi/Kconfig ++## ++# CONFIG_FDDI is not set ++ ++## ++## file: drivers/net/hippi/Kconfig ++## ++# CONFIG_HIPPI is not set ++ ++## ++## file: drivers/net/phy/Kconfig ++## ++CONFIG_PHYLIB=m ++CONFIG_MARVELL_PHY=m ++CONFIG_DAVICOM_PHY=m ++CONFIG_QSEMI_PHY=m ++CONFIG_LXT_PHY=m ++CONFIG_CICADA_PHY=m ++CONFIG_VITESSE_PHY=m ++CONFIG_SMSC_PHY=m ++CONFIG_BROADCOM_PHY=m ++CONFIG_ICPLUS_PHY=m ++# CONFIG_MDIO_BITBANG is not set ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_PL031=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI_SYM53C8XX_2=m ++ ++## ++## file: drivers/spi/Kconfig ++## ++# CONFIG_SPI is not set ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++# CONFIG_SERIAL_8250 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB_SUPPORT=y ++CONFIG_USB=m ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_ISP116X_HCD=m ++CONFIG_USB_OHCI_HCD=m ++# CONFIG_USB_OHCI_HCD_SSB is not set ++CONFIG_USB_UHCI_HCD=m ++# CONFIG_USB_U132_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_VIDEO_OUTPUT_CONTROL=m ++CONFIG_FB=y ++CONFIG_FIRMWARE_EDID=y ++CONFIG_FB_MODE_HELPERS=y ++CONFIG_FB_TILEBLITTING=y ++CONFIG_FB_CIRRUS=m ++# CONFIG_FB_PM2 is not set ++CONFIG_FB_ARMCLCD=y ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_S1D13XXX 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=m ++CONFIG_FB_S3_DDC=y ++# 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=m ++CONFIG_FB_PM3=m ++CONFIG_FB_SM501=m ++CONFIG_FB_VIRTUAL=m ++ ++## ++## file: drivers/video/backlight/Kconfig ++## ++CONFIG_BACKLIGHT_CLASS_DEVICE=m ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y ++CONFIG_FONTS=y ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++# CONFIG_FONT_6x11 is not set ++# CONFIG_FONT_7x14 is not set ++# CONFIG_FONT_PEARL_8x8 is not set ++# CONFIG_FONT_ACORN_8x8 is not set ++# CONFIG_FONT_MINI_4x6 is not set ++# CONFIG_FONT_SUN8x16 is not set ++# CONFIG_FONT_SUN12x22 is not set ++# CONFIG_FONT_10x18 is not set ++ ++## ++## file: drivers/video/display/Kconfig ++## ++CONFIG_DISPLAY_SUPPORT=m ++ ++## ++## file: kernel/Kconfig.preempt ++## ++## choice: Preemption Model ++# CONFIG_PREEMPT is not set ++## end choice ++ ++## ++## file: kernel/time/Kconfig ++## ++# CONFIG_NO_HZ is not set ++# CONFIG_HIGH_RES_TIMERS is not set ++ ++## ++## file: lib/Kconfig.debug ++## ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_UNUSED_SYMBOLS=y ++# CONFIG_HEADERS_CHECK is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_FRAME_POINTER is not set ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/decnet/Kconfig ++## ++CONFIG_DECNET=m ++CONFIG_DECNET_ROUTER=y ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++CONFIG_IPX_INTERN=y ++ ++## ++## file: net/irda/Kconfig ++## ++# CONFIG_IRDA is not set ++ ++## ++## file: net/lapb/Kconfig ++## ++# CONFIG_LAPB is not set ++ +diff --git a/debian/config/armel/defines b/debian/config/armel/defines +new file mode 100644 +index 0000000..b8ab2bf +--- /dev/null ++++ b/debian/config/armel/defines +@@ -0,0 +1,77 @@ ++[base] ++flavours: ++ iop32x ++ ixp4xx ++ kirkwood ++ mv78xx0 ++ orion5x ++ versatile ++ cumulus ++kernel-arch: arm ++ ++[image] ++suggests: fdutils ++ ++[iop32x_build] ++image-file: arch/arm/boot/zImage ++ ++[iop32x_description] ++hardware: IOP32x ++hardware-long: IOP32x based systems (Thecus N2100, etc) ++ ++[iop32x_image] ++# Thecus N2100: 1441792 - 8 = 1441784 ++check-size: 1441784 ++ ++[ixp4xx_build] ++image-file: arch/arm/boot/zImage ++ ++[ixp4xx_description] ++hardware: IXP4xx ++hardware-long: IXP4xx based systems (Linksys NSLU2, etc) ++ ++[ixp4xx_image] ++# Linksys NSLU2: 1441792 - 16 - 16 = 1441760 ++check-size: 1441760 ++ ++[kirkwood_build] ++image-file: arch/arm/boot/zImage ++ ++[kirkwood_description] ++hardware: Marvell Kirkwood ++hardware-long: Marvell Kirkwood based systems (SheevaPlug, QNAP TS-119/TS-219, etc) ++ ++[kirkwood_image] ++recommends: uboot-mkimage ++# SheevaPlug: 4194304 - 8 - 64 = 4194232 ++# QNAP TS-119/TS-219: 2097152 - 8 - 64 = 2097080 ++check-size: 2097080 ++ ++[mv78xx0_build] ++image-file: arch/arm/boot/zImage ++ ++[mv78xx0_description] ++hardware: Marvell 78xx0 ++hardware-long: Marvell DB-78xx0-BP Development Board ++ ++[orion5x_build] ++image-file: arch/arm/boot/zImage ++ ++[orion5x_description] ++hardware: Marvell Orion ++hardware-long: Marvell Orion 5181, 5182 and 5281 based systems (QNAP TS-109/TS-209, etc) ++ ++[orion5x_image] ++recommends: uboot-mkimage ++# D-Link DNS-323: 1572864 - 8 - 64 = 1572792 ++# HP Media Vault mv2120: ca 2 MB ++# QNAP TS-109/TS-209 & TS-409: 2097152 - 8 - 64 = 2097080 ++check-size: 1572792 ++ ++[versatile_description] ++hardware: Versatile ++hardware-long: Versatile systems (PB, AB, Qemu) ++ ++[cumulus_description] ++hardware: Broadcom iProc ++hardware-long: Broadcom iProc (ARMv7) based systems +diff --git a/debian/config/armel/uImage-arm.its b/debian/config/armel/uImage-arm.its +new file mode 100644 +index 0000000..ccc71d4 +--- /dev/null ++++ b/debian/config/armel/uImage-arm.its +@@ -0,0 +1,75 @@ ++/* ++** ++** Copyright 2014 Cumulus Networks, Inc. ++** All rights reserved. ++** ++** ++** U-boot uImage source file with a kernel and multiple FDT blobs. ++** ++** ++** Note: The /incbin/() paths used below are relative to the location ++** of this file. That's just how the tool works. ++** ++** ++*/ ++ ++/dts-v1/; ++ ++/ { ++ description = "ARM kernel and FDT blobs"; ++ #address-cells = <1>; ++ ++ images { ++ kernel { ++ description = "ARM Kernel"; ++ data = /incbin/("arch/arm/boot/compressed/piggy.gzip"); ++ type = "kernel"; ++ arch = "arm"; ++ os = "linux"; ++ compression = "gzip"; ++ load = <0x61008000>; ++ entry = <0x61008000>; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ /* Device Tree Blobs */ ++ dni_3448p_dtb { ++ description = "dni_3448p.dtb"; ++ data = /incbin/("../dtb/dni_3448p.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ accton_as4610_54_dtb { ++ description = "accton_as4610_54.dtb"; ++ data = /incbin/("../dtb/accton_as4610_54.dtb"); ++ type = "flat_dt"; ++ arch = "arm"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ }; ++ ++ configurations { ++ dni_3448p { ++ description = "DNI 3448p"; ++ kernel = "kernel"; ++ fdt = "dni_3448p_dtb"; ++ }; ++ accton_as4610_54 { ++ description = "Accton AS4610-54"; ++ kernel = "kernel"; ++ fdt = "accton_as4610_54_dtb"; ++ }; ++ }; ++}; +diff --git a/debian/config/armhf/config b/debian/config/armhf/config +new file mode 100644 +index 0000000..07dc8d6 +--- /dev/null ++++ b/debian/config/armhf/config +@@ -0,0 +1,34 @@ ++## ++## file: arch/arm/Kconfig ++## ++CONFIG_KEXEC=y ++CONFIG_ATAGS_PROC=y ++#. Enable floating point unit ++CONFIG_VFP=y ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++ ++## ++## file: drivers/net/hamradio/Kconfig ++## ++# CONFIG_BPQETHER is not set ++# CONFIG_BAYCOM_SER_FDX is not set ++# CONFIG_BAYCOM_SER_HDX is not set ++# CONFIG_BAYCOM_PAR is not set ++# CONFIG_BAYCOM_EPP is not set ++# CONFIG_YAM is not set ++ ++## ++## file: init/Kconfig ++## ++## choice: Kernel compression mode ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_BZIP2 is not set ++# CONFIG_KERNEL_LZMA is not set ++## end choice ++ +diff --git a/debian/config/armhf/config.mx5 b/debian/config/armhf/config.mx5 +new file mode 100644 +index 0000000..d13264d +--- /dev/null ++++ b/debian/config/armhf/config.mx5 +@@ -0,0 +1,183 @@ ++## ++## file: arch/arm/Kconfig ++## ++## choice: ARM system type ++CONFIG_ARCH_MXC=y ++## end choice ++CONFIG_HIGHMEM=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++#. cpufreq driver for i.MX CPU ++CONFIG_CPU_FREQ_IMX=m ++#. Enable NEON SIMD support ++CONFIG_NEON=y ++ ++## ++## file: arch/arm/Kconfig.debug ++## ++# CONFIG_DEBUG_LL is not set ++ ++## ++## file: arch/arm/mach-mx5/Kconfig ++## ++CONFIG_MACH_MX51_EFIKAMX=y ++CONFIG_MACH_MX53_EVK=y ++CONFIG_MACH_MX53_SMD=y ++CONFIG_MACH_MX53_LOCO=y ++CONFIG_MACH_MX53_ARD=y ++ ++## ++## file: arch/arm/plat-mxc/Kconfig ++## ++## choice: Freescale CPU family: ++CONFIG_ARCH_MX5=y ++## end choice ++#. Enable PWM driver ++CONFIG_MXC_PWM=y ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_SATA_AHCI_PLATFORM=m ++CONFIG_PATA_IMX=m ++ ++## ++## file: drivers/dma/Kconfig ++## ++CONFIG_DMADEVICES=y ++CONFIG_IMX_SDMA=y ++# CONFIG_NET_DMA is not set ++# CONFIG_ASYNC_TX_DMA is not set ++ ++## ++## file: drivers/gpio/Kconfig ++## ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++ ++## ++## file: drivers/hid/usbhid/Kconfig ++## ++CONFIG_USB_HID=y ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_IMX=y ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++CONFIG_INPUT_TOUCHSCREEN=y ++ ++## ++## file: drivers/leds/Kconfig ++## ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_TRIGGER_GPIO=y ++ ++## ++## file: drivers/mfd/Kconfig ++## ++CONFIG_MFD_MC13XXX=y ++ ++## ++## file: drivers/mmc/Kconfig ++## ++CONFIG_MMC=m ++ ++## ++## file: drivers/mmc/card/Kconfig ++## ++CONFIG_MMC_BLOCK=m ++ ++## ++## file: drivers/mmc/host/Kconfig ++## ++CONFIG_MMC_SDHCI_ESDHC_IMX=m ++CONFIG_MMC_MXC=m ++ ++## ++## file: drivers/mtd/Kconfig ++## ++#. Efika has SPI NOR MTD device ++CONFIG_MTD=m ++CONFIG_MTD_BLOCK=m ++ ++## ++## file: drivers/net/wireless/mwifiex/Kconfig ++## ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++ ++## ++## file: drivers/power/Kconfig ++## ++CONFIG_POWER_SUPPLY=y ++ ++## ++## file: drivers/regulator/Kconfig ++## ++#. Provide dummy if lookup fails ++CONFIG_REGULATOR_DUMMY=y ++#. It is not set at top level ++CONFIG_REGULATOR_VIRTUAL_CONSUMER=y ++#. Included as module, should not be regulator stuff included as built-in? ++CONFIG_REGULATOR_USERSPACE_CONSUMER=y ++CONFIG_REGULATOR_MC13892=y ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_INTF_DEV_UIE_EMUL=y ++CONFIG_RTC_DRV_MC13XXX=y ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI_GPIO=y ++CONFIG_SPI_IMX=y ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_IMX=y ++CONFIG_SERIAL_IMX_CONSOLE=y ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=y ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_MXC=y ++ ++## ++## file: drivers/usb/otg/Kconfig ++## ++CONFIG_USB_ULPI=y ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_IMX2_WDT=y ++ ++## ++## file: sound/soc/Kconfig ++## ++CONFIG_SND_SOC=m ++ ++## ++## file: sound/soc/imx/Kconfig ++## ++CONFIG_SND_IMX_SOC=m ++ ++## ++## file: unknown ++## ++CONFIG_SND_SOC_IMX_SGTL5000=m ++ +diff --git a/debian/config/armhf/config.omap b/debian/config/armhf/config.omap +new file mode 100644 +index 0000000..f49d03d +--- /dev/null ++++ b/debian/config/armhf/config.omap +@@ -0,0 +1,332 @@ ++## ++## file: arch/arm/Kconfig ++## ++## choice: ARM system type ++CONFIG_ARCH_OMAP=y ++## end choice ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_HIGHMEM=y ++CONFIG_LEDS=y ++CONFIG_LEDS_CPU=y ++CONFIG_NEON=y ++ ++## ++## file: arch/arm/mach-omap2/Kconfig ++## ++CONFIG_ARCH_OMAP2PLUS_TYPICAL=y ++# CONFIG_ARCH_OMAP2 is not set ++ ++## ++## file: arch/arm/mm/Kconfig ++## ++CONFIG_ARM_THUMBEE=y ++ ++## ++## file: arch/arm/plat-omap/Kconfig ++## ++## choice: OMAP System Type ++CONFIG_ARCH_OMAP2PLUS=y ++## end choice ++CONFIG_OMAP_RESET_CLOCKS=y ++CONFIG_OMAP_MUX=y ++# CONFIG_OMAP_MUX_DEBUG is not set ++CONFIG_OMAP_MUX_WARNINGS=y ++CONFIG_OMAP_MCBSP=y ++CONFIG_OMAP_MBOX_FWK=y ++CONFIG_OMAP_MBOX_KFIFO_SIZE=256 ++# CONFIG_OMAP_MPU_TIMER is not set ++CONFIG_OMAP_32K_TIMER=y ++# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set ++CONFIG_OMAP_32K_TIMER_HZ=128 ++CONFIG_OMAP_DM_TIMER=y ++CONFIG_OMAP_SERIAL_WAKE=y ++## choice: OMAP PM layer selection ++CONFIG_OMAP_PM_NOOP=y ++## end choice ++ ++## ++## file: drivers/bluetooth/Kconfig ++## ++CONFIG_BT_WILINK=m ++ ++## ++## file: drivers/cpufreq/Kconfig ++## ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++ ++## ++## file: drivers/crypto/Kconfig ++## ++CONFIG_CRYPTO_DEV_OMAP_SHAM=m ++CONFIG_CRYPTO_DEV_OMAP_AES=m ++ ++## ++## file: drivers/gpio/Kconfig ++## ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_TWL4030=y ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_GPIO=y ++CONFIG_I2C_OMAP=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_KEYBOARD_GPIO=y ++CONFIG_KEYBOARD_OMAP4=y ++CONFIG_KEYBOARD_TWL4030=y ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_TWL4030_PWRBUTTON=m ++CONFIG_INPUT_TWL4030_VIBRA=m ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_TSC2005=m ++ ++## ++## file: drivers/iommu/Kconfig ++## ++# CONFIG_OMAP_IOMMU_DEBUG is not set ++ ++## ++## file: drivers/leds/Kconfig ++## ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=m ++CONFIG_LEDS_LP5523=m ++CONFIG_LEDS_TRIGGER_GPIO=m ++ ++## ++## file: drivers/media/Kconfig ++## ++CONFIG_MEDIA_SUPPORT=y ++CONFIG_MEDIA_CONTROLLER=y ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++CONFIG_RADIO_ADAPTERS=y ++CONFIG_I2C_SI4713=m ++CONFIG_RADIO_SI4713=m ++ ++## ++## file: drivers/media/radio/wl128x/Kconfig ++## ++CONFIG_RADIO_WL128X=m ++ ++## ++## file: drivers/media/video/omap/Kconfig ++## ++CONFIG_VIDEO_OMAP2_VOUT=m ++ ++## ++## file: drivers/misc/ti-st/Kconfig ++## ++CONFIG_TI_ST=m ++ ++## ++## file: drivers/mmc/Kconfig ++## ++CONFIG_MMC=y ++ ++## ++## file: drivers/mmc/host/Kconfig ++## ++CONFIG_MMC_SDHCI=m ++CONFIG_MMC_OMAP=y ++CONFIG_MMC_OMAP_HS=y ++CONFIG_MMC_SPI=m ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=y ++ ++## ++## file: drivers/mtd/nand/Kconfig ++## ++CONFIG_MTD_NAND=y ++CONFIG_MTD_NAND_OMAP2=y ++ ++## ++## file: drivers/mtd/onenand/Kconfig ++## ++CONFIG_MTD_ONENAND=y ++CONFIG_MTD_ONENAND_OMAP2=y ++ ++## ++## file: drivers/net/wireless/wl1251/Kconfig ++## ++CONFIG_WL1251=m ++CONFIG_WL1251_SPI=m ++ ++## ++## file: drivers/net/wireless/wl12xx/Kconfig ++## ++CONFIG_WL12XX=m ++ ++## ++## file: drivers/power/Kconfig ++## ++CONFIG_BATTERY_BQ27x00=m ++CONFIG_CHARGER_ISP1704=m ++ ++## ++## file: drivers/regulator/Kconfig ++## ++CONFIG_REGULATOR=y ++CONFIG_REGULATOR_TWL4030=y ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_TWL4030=m ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI=y ++CONFIG_SPI_GPIO=y ++CONFIG_SPI_OMAP24XX=y ++CONFIG_SPI_SPIDEV=y ++ ++## ++## file: drivers/staging/iio/Kconfig ++## ++CONFIG_IIO=m ++ ++## ++## file: drivers/staging/iio/accel/Kconfig ++## ++CONFIG_LIS3L02DQ=m ++ ++## ++## file: drivers/staging/iio/light/Kconfig ++## ++CONFIG_SENSORS_TSL2563=m ++ ++## ++## file: drivers/staging/tidspbridge/Kconfig ++## ++CONFIG_TIDSPBRIDGE=m ++CONFIG_TIDSPBRIDGE_DVFS=y ++CONFIG_TIDSPBRIDGE_RECOVERY=y ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=y ++ ++## ++## file: drivers/usb/gadget/Kconfig ++## ++CONFIG_USB_GADGET=y ++## choice: USB Peripheral Controller ++CONFIG_USB_GADGET_MUSB_HDRC=y ++## end choice ++## choice: USB Gadget Drivers ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++CONFIG_USB_GADGETFS=m ++CONFIG_USB_G_NOKIA=m ++## end choice ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_EHCI_HCD_OMAP=y ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_OHCI_HCD_OMAP3=y ++ ++## ++## file: drivers/usb/musb/Kconfig ++## ++CONFIG_USB_MUSB_HDRC=y ++## choice: Platform Glue Layer ++CONFIG_USB_MUSB_OMAP2PLUS=y ++## end choice ++ ++## ++## file: drivers/usb/otg/Kconfig ++## ++CONFIG_TWL4030_USB=y ++CONFIG_TWL6030_USB=y ++CONFIG_NOP_USB_XCEIV=y ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_VIDEO_OUTPUT_CONTROL=y ++CONFIG_FB=y ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++ ++## ++## file: drivers/video/omap/Kconfig ++## ++CONFIG_FB_OMAP_BOOTLOADER_INIT=y ++ ++## ++## file: drivers/video/omap2/displays/Kconfig ++## ++CONFIG_PANEL_GENERIC_DPI=y ++CONFIG_PANEL_ACX565AKM=y ++ ++## ++## file: drivers/video/omap2/dss/Kconfig ++## ++CONFIG_OMAP2_DSS=y ++CONFIG_OMAP2_DSS_VENC=y ++CONFIG_OMAP4_DSS_HDMI=y ++CONFIG_OMAP2_DSS_SDI=y ++ ++## ++## file: drivers/video/omap2/omapfb/Kconfig ++## ++CONFIG_FB_OMAP2=y ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_OMAP_WATCHDOG=m ++CONFIG_TWL4030_WATCHDOG=m ++ ++## ++## file: kernel/power/Kconfig ++## ++CONFIG_SUSPEND=y ++CONFIG_PM_RUNTIME=y ++CONFIG_APM_EMULATION=y ++ ++## ++## file: net/phonet/Kconfig ++## ++CONFIG_PHONET=m ++ ++## ++## file: sound/soc/Kconfig ++## ++CONFIG_SND_SOC=m ++ ++## ++## file: sound/soc/omap/Kconfig ++## ++CONFIG_SND_OMAP_SOC=m ++CONFIG_SND_OMAP_SOC_RX51=m ++CONFIG_SND_OMAP_SOC_SDP4430=m ++ +diff --git a/debian/config/armhf/config.vexpress b/debian/config/armhf/config.vexpress +new file mode 100644 +index 0000000..15bbcb5 +--- /dev/null ++++ b/debian/config/armhf/config.vexpress +@@ -0,0 +1,69 @@ ++## ++## file: arch/arm/Kconfig ++## ++## choice: ARM system type ++CONFIG_ARCH_VEXPRESS=y ++## end choice ++ ++## arch/arm/mach-vexpress/Kconfig ++CONFIG_ARCH_VEXPRESS_CA9X4=y ++ ++CONFIG_OPROFILE=m ++ ++CONFIG_SMP=y ++CONFIG_VMSPLIT_2G=y ++CONFIG_HOTPLUG_CPU=y ++ ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++ ++CONFIG_NEON=y ++ ++CONFIG_PATA_PLATFORM=m ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=m ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_OCORES is not set ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_SIMTEC is not set ++CONFIG_I2C_VERSATILE=m ++ ++CONFIG_MTD=m ++CONFIG_MTD_CONCAT=m ++CONFIG_MTD_PARTITIONS=m ++CONFIG_MTD_CMDLINE_PARTS=m ++CONFIG_MTD_CHAR=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_CFI=m ++CONFIG_MTD_CFI_INTELEXT=m ++CONFIG_MTD_CFI_AMDSTD=m ++CONFIG_MTD_PHYSMAP=m ++CONFIG_MISC_DEVICES=m ++ ++CONFIG_NET_ETHERNET=m ++CONFIG_SMSC911X=m ++ ++CONFIG_SERIO_AMBAKMI=y ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++ ++CONFIG_FB=y ++CONFIG_FB_ARMCLCD=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++ ++CONFIG_SND_ARMAACI=m ++ ++CONFIG_USB=m ++CONFIG_USB_ISP1760_HCD=m ++CONFIG_MMC=y ++CONFIG_MMC_ARMMMCI=y ++ ++CONFIG_RTC_DRV_PL031=y ++ +diff --git a/debian/config/armhf/defines b/debian/config/armhf/defines +new file mode 100644 +index 0000000..a9f9437 +--- /dev/null ++++ b/debian/config/armhf/defines +@@ -0,0 +1,37 @@ ++[base] ++flavours: ++ mx5 ++ omap ++ vexpress ++kernel-arch: arm ++ ++[image] ++suggests: fdutils ++configs: ++ armel/config ++ armhf/config ++ ++[mx5_build] ++image-file: arch/arm/boot/zImage ++ ++[mx5_description] ++hardware: Freescale i.MX51/53 ++hardware-long: Freescale i.MX51 or i.MX53 based systems ++ ++[omap_build] ++image-file: arch/arm/boot/zImage ++ ++[omap_description] ++hardware: TI OMAP3+ ++hardware-long: Texas Instruments OMAP3 or OMAP4 based systems ++ ++[omap_image] ++recommends: uboot-mkimage ++ ++[vexpress_build] ++image-file: arch/arm/boot/zImage ++ ++[vexpress_description] ++hardware: ARM Ltd. Versatile Express ++hardware-long: ARM Ltd. Versatile Express family of processors ++ +diff --git a/debian/config/config b/debian/config/config +new file mode 100644 +index 0000000..e69de29 +diff --git a/debian/config/defines b/debian/config/defines +new file mode 100644 +index 0000000..b20bae0 +--- /dev/null ++++ b/debian/config/defines +@@ -0,0 +1,118 @@ ++[abi] ++abiname: cl1 ++ignore-changes: ++ module:net/l2tp/* ++# A bunch of NFS/SunRPC exports, not selected by module because MIPS has ++# them built-in ++ __rpc_wait_for_completion_task ++ bc_svc_process ++ nfs4* ++ nfs_* ++ nlmclnt_* ++ nlmsvc_* ++ pnfs_* ++ put_lseg ++ put_rpccred ++ rpc_* ++ rpcauth_* ++ rpcb_getport_async ++ svc_* ++ svcauth_unix_set_client ++ unix_domain_find ++ xprt_* ++# Inline function, did not need to be exported at all ++ get_write_access ++# AGP and DRM were bumped to 3.4, but no-one tries to use these from OOT ++ module:drivers/gpu/drm/* ++ drm_sman_* ++ intel_agp_enabled ++ intel_gmch_* ++ intel_gtt_* ++# wanrouter was totally broken ++ module:drivers/net/wan/cycx_drv ++ module:net/wanrouter/wanrouter ++# No-one tries to use virtio from OOT ++ register_virtio_* ++ unregister_virtio_* ++ virtio_* ++ virtqueue_* ++ vring_* ++# No-one should depend on staging from OOT ++ module:drivers/staging/* ++# Private to each family of drivers ++ module:drivers/net/wireless/ath/* ++ module:drivers/net/wireless/rtlwifi/* ++# Should not be used from OOT ++ kmsg_dump_register ++ kmsg_dump_unregister ++# Only used by Google firmware module ++ register_efivars ++ unregister_efivars ++# Should not be used from OOT ++ module:drivers/usb/serial/* ++ module:arch/s390/kvm/kvm ++ module:drivers/scsi/esp_scsi ++ module:drivers/char/tpm/tpm ++# Only exported for tidspbridge, disabled for security reasons in 3.2.54 ++ omap_dsp_get_mempool_base ++# Should only be used by ioatdma ++ sysctl_tcp_dma_copybreak ++# Should not be used from OOT ++ module:fs/exofs/libore ++# Private to the matroxfb modules (why are they even separate modules?!) ++ DAC1064_global_* ++ g450_mnp2f ++ matrox_* ++ matroxfb_* ++# Should not be used from OOT ++ tcp_alloc_md5sig_pool ++ tcp_free_md5sig_pool ++ tcp_get_md5sig_pool ++ tcp_put_md5sig_pool ++ module:sound/i2c/other/snd-ak4113 ++ module:sound/i2c/other/snd-ak4114 ++ module:net/ipv4/netfilter/nf_conntrac* ++ module:net/ipv4/netfilter/nf_nat ++ module:net/netfilter/ipvs/* ++ module:net/netfilter/nf_conntrac* ++ ++[base] ++arches: ++ alpha ++ amd64 ++ armel ++ armhf ++ hppa ++ i386 ++ ia64 ++ m68k ++ mips ++ mipsel ++ powerpc ++ ppc64 ++ s390 ++ s390x ++ sh4 ++ sparc ++ sparc64 ++compiler: gcc-4.6 ++featuresets: ++ none ++ ++[description] ++part-long-up: This kernel is not suitable for SMP (multi-processor, ++ multi-core or hyper-threaded) systems. ++ ++[image] ++initramfs-generators: initramfs-tools initramfs-fallback ++type: plain ++ ++[relations] ++# compilers ++gcc-4.4: gcc-4.4 ++gcc-4.5: gcc-4.5 ++gcc-4.6: gcc-4.6 ++ ++# initramfs-generators ++initramfs-fallback: linux-initramfs-tool ++initramfs-tools: initramfs-tools (>= 0.99~) +diff --git a/debian/config/featureset-rt/config b/debian/config/featureset-rt/config +new file mode 100644 +index 0000000..247fe31 +--- /dev/null ++++ b/debian/config/featureset-rt/config +@@ -0,0 +1,8 @@ ++# CONFIG_PREEMPT_VOLUNTARY is not set ++CONFIG_PREEMPT_RT_FULL=y ++CONFIG_SCHED_TRACER=y ++CONFIG_MISSED_TIMER_OFFSETS_HIST=y ++CONFIG_WAKEUP_LATENCY_HIST=y ++ ++## disable aufs as it's not needed on rt and conflicts with fs-dentry-use-seqlock.patch ++# CONFIG_AUFS_FS is not set +diff --git a/debian/config/featureset-rt/defines b/debian/config/featureset-rt/defines +new file mode 100644 +index 0000000..44e2f2b +--- /dev/null ++++ b/debian/config/featureset-rt/defines +@@ -0,0 +1,7 @@ ++[abi] ++ignore-changes: * ++ ++[description] ++part-long-rt: This kernel includes the PREEMPT_RT realtime patch set. ++part-short-rt: PREEMPT_RT ++parts: rt +diff --git a/debian/config/hppa/config b/debian/config/hppa/config +new file mode 100644 +index 0000000..63d32ce +--- /dev/null ++++ b/debian/config/hppa/config +@@ -0,0 +1,782 @@ ++## ++## file: arch/Kconfig ++## ++# CONFIG_OPROFILE is not set ++ ++## ++## file: arch/parisc/Kconfig ++## ++## choice: Processor type ++# CONFIG_PA7100LC is not set ++# CONFIG_PA7200 is not set ++# CONFIG_PA7300LC is not set ++## end choice ++## choice: Kernel page size ++CONFIG_PARISC_PAGE_SIZE_4KB=y ++# CONFIG_PARISC_PAGE_SIZE_16KB is not set ++# CONFIG_PARISC_PAGE_SIZE_64KB is not set ++## end choice ++ ++## ++## file: arch/parisc/Kconfig.debug ++## ++# CONFIG_DEBUG_RODATA is not set ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_PATA_NS87415=m ++CONFIG_PATA_LEGACY=m ++ ++## ++## file: drivers/block/Kconfig ++## ++# CONFIG_BLK_DEV_FD is not set ++# CONFIG_BLK_DEV_XD is not set ++# CONFIG_PARIDE is not set ++# CONFIG_BLK_CPQ_DA 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_SX8 is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM_SIZE=8192 ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_CDROM_PKTCDVD_BUFFERS=8 ++# CONFIG_CDROM_PKTCDVD_WCACHE is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++# CONFIG_PPDEV is not set ++CONFIG_GEN_RTC=y ++# CONFIG_GEN_RTC_X is not set ++# CONFIG_DTLK is not set ++# CONFIG_APPLICOM is not set ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++# CONFIG_IPMI_HANDLER is not set ++ ++## ++## file: drivers/eisa/Kconfig ++## ++CONFIG_EISA_NAMES=y ++ ++## ++## file: drivers/firewire/Kconfig ++## ++# CONFIG_FIREWIRE is not set ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++# CONFIG_DRM is not set ++ ++## ++## file: drivers/hid/usbhid/Kconfig ++## ++CONFIG_USB_HID=m ++CONFIG_USB_KBD=m ++CONFIG_USB_MOUSE=m ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++# CONFIG_SENSORS_F71805F is not set ++ ++## ++## file: drivers/i2c/Kconfig ++## ++# CONFIG_I2C is not set ++ ++## ++## file: drivers/input/Kconfig ++## ++# CONFIG_INPUT_JOYDEV is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++# CONFIG_GAMEPORT is not set ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++# CONFIG_INPUT_JOYSTICK is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y ++# CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++CONFIG_KEYBOARD_HIL_OLD=m ++CONFIG_KEYBOARD_HIL=m ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_UINPUT is not set ++CONFIG_HP_SDC_RTC=m ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=m ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_INPORT is not set ++# CONFIG_MOUSE_LOGIBM is not set ++# CONFIG_MOUSE_PC110PAD is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++# CONFIG_SERIO_SERPORT is not set ++# CONFIG_SERIO_PARKBD is not set ++CONFIG_SERIO_GSCPS2=y ++CONFIG_HP_SDC=m ++CONFIG_HIL_MLC=m ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++CONFIG_SERIO_RAW=m ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_INPUT_TOUCHSCREEN is not set ++ ++## ++## file: drivers/media/Kconfig ++## ++# CONFIG_VIDEO_DEV is not set ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++CONFIG_I2O=m ++CONFIG_I2O_CONFIG=m ++CONFIG_I2O_BLOCK=m ++CONFIG_I2O_SCSI=m ++CONFIG_I2O_PROC=m ++ ++## ++## file: drivers/mfd/Kconfig ++## ++# CONFIG_AB3100_CORE is not set ++ ++## ++## file: drivers/mmc/Kconfig ++## ++# CONFIG_MMC is not set ++ ++## ++## file: drivers/mtd/Kconfig ++## ++# CONFIG_MTD is not set ++ ++## ++## file: drivers/net/Kconfig ++## ++# CONFIG_BONDING is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC is not set ++# CONFIG_NETPOLL_TRAP is not set ++ ++## ++## file: drivers/net/appletalk/Kconfig ++## ++# CONFIG_ATALK is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/Kconfig ++## ++CONFIG_FEALNX=m ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++CONFIG_NET_VENDOR_3COM=y ++CONFIG_EL1=m ++CONFIG_EL3=m ++# CONFIG_3C515 is not set ++CONFIG_PCMCIA_3C574=m ++CONFIG_PCMCIA_3C589=m ++CONFIG_VORTEX=m ++CONFIG_TYPHOON=m ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_EL2=m ++CONFIG_AC3200=m ++CONFIG_PCMCIA_AXNET=m ++CONFIG_E2100=m ++CONFIG_ES3210=m ++CONFIG_HPLAN_PLUS=m ++CONFIG_HPLAN=m ++CONFIG_LNE390=m ++CONFIG_NE2000=m ++CONFIG_NE2K_PCI=m ++CONFIG_NE3210=m ++CONFIG_PCMCIA_PCNET=m ++CONFIG_ULTRA=m ++CONFIG_ULTRA32=m ++CONFIG_WD80x3=m ++ ++## ++## file: drivers/net/ethernet/adaptec/Kconfig ++## ++CONFIG_ADAPTEC_STARFIRE=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_AMD8111_ETH=m ++# CONFIG_LANCE is not set ++CONFIG_DEPCA=m ++CONFIG_PCMCIA_NMCLAN=m ++# CONFIG_NI65 is not set ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++CONFIG_B44=m ++ ++## ++## file: drivers/net/ethernet/cirrus/Kconfig ++## ++CONFIG_CS89x0=m ++ ++## ++## file: drivers/net/ethernet/dec/Kconfig ++## ++CONFIG_EWRK3=m ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++CONFIG_NET_TULIP=y ++# CONFIG_DE2104X is not set ++CONFIG_TULIP=m ++# CONFIG_TULIP_MWI is not set ++CONFIG_TULIP_MMIO=y ++# CONFIG_WINBOND_840 is not set ++# CONFIG_DM9102 is not set ++CONFIG_PCMCIA_XIRCOM=m ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++CONFIG_SUNDANCE=m ++# CONFIG_SUNDANCE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/fujitsu/Kconfig ++## ++CONFIG_AT1700=m ++CONFIG_PCMCIA_FMVJ18X=m ++CONFIG_ETH16I=m ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++CONFIG_HP100=m ++ ++## ++## file: drivers/net/ethernet/i825xx/Kconfig ++## ++CONFIG_ELPLUS=m ++CONFIG_EL16=m ++CONFIG_APRICOT=m ++CONFIG_EEXPRESS=m ++CONFIG_EEXPRESS_PRO=m ++CONFIG_LASI_82596=m ++CONFIG_LP486E=m ++# CONFIG_NI52 is not set ++CONFIG_ZNET=m ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++CONFIG_E100=m ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_NATSEMI=m ++ ++## ++## file: drivers/net/ethernet/neterion/Kconfig ++## ++# CONFIG_VXGE is not set ++ ++## ++## file: drivers/net/ethernet/nvidia/Kconfig ++## ++CONFIG_FORCEDETH=m ++ ++## ++## file: drivers/net/ethernet/racal/Kconfig ++## ++CONFIG_NET_VENDOR_RACAL=y ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_8139CP=m ++CONFIG_8139TOO=m ++# CONFIG_8139TOO_PIO is not set ++# CONFIG_8139TOO_TUNE_TWISTER is not set ++# CONFIG_8139TOO_8129 is not set ++# CONFIG_8139_OLD_RX_RESET is not set ++ ++## ++## file: drivers/net/ethernet/seeq/Kconfig ++## ++CONFIG_SEEQ8005=m ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++CONFIG_SIS900=m ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_SMC9194=m ++CONFIG_PCMCIA_SMC91C92=m ++CONFIG_EPIC100=m ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++CONFIG_HAPPYMEAL=m ++CONFIG_SUNGEM=m ++# CONFIG_NIU is not set ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++CONFIG_VIA_RHINE=m ++# CONFIG_VIA_RHINE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/xircom/Kconfig ++## ++CONFIG_PCMCIA_XIRC2PS=m ++ ++## ++## file: drivers/net/fddi/Kconfig ++## ++# CONFIG_FDDI is not set ++ ++## ++## file: drivers/net/hippi/Kconfig ++## ++# CONFIG_HIPPI is not set ++ ++## ++## file: drivers/net/plip/Kconfig ++## ++CONFIG_PLIP=m ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++# CONFIG_TR is not set ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++# CONFIG_WAN is not set ++ ++## ++## file: drivers/net/wireless/Kconfig ++## ++CONFIG_PCMCIA_RAYCS=m ++# CONFIG_ATMEL is not set ++CONFIG_AIRO_CS=m ++CONFIG_PCMCIA_WL3501=m ++# CONFIG_USB_ZD1201 is not set ++ ++## ++## file: drivers/net/wireless/ipw2x00/Kconfig ++## ++# CONFIG_IPW2100 is not set ++ ++## ++## file: drivers/net/wireless/orinoco/Kconfig ++## ++CONFIG_HERMES=m ++# CONFIG_PLX_HERMES is not set ++# CONFIG_TMD_HERMES is not set ++# CONFIG_PCI_HERMES is not set ++CONFIG_PCMCIA_HERMES=m ++ ++## ++## file: drivers/parisc/Kconfig ++## ++CONFIG_GSC=y ++CONFIG_HPPB=y ++CONFIG_IOMMU_CCIO=y ++CONFIG_GSC_LASI=y ++CONFIG_GSC_WAX=y ++CONFIG_EISA=y ++CONFIG_ISA=y ++CONFIG_PCI=y ++CONFIG_GSC_DINO=y ++CONFIG_PCI_LBA=y ++CONFIG_SUPERIO=y ++CONFIG_CHASSIS_LCD_LED=y ++CONFIG_PDC_CHASSIS=y ++CONFIG_PDC_CHASSIS_WARN=y ++CONFIG_PDC_STABLE=y ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++# CONFIG_HOTPLUG_PCI is not set ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++CONFIG_PCCARD=m ++CONFIG_PCMCIA=m ++CONFIG_CARDBUS=y ++CONFIG_YENTA=m ++CONFIG_PD6729=m ++CONFIG_I82092=m ++CONFIG_I82365=m ++# CONFIG_TCIC is not set ++# CONFIG_PCMCIA_DEBUG is not set ++ ++## ++## file: drivers/pnp/Kconfig ++## ++# CONFIG_PNP is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++# CONFIG_RTC_CLASS is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++# CONFIG_SCSI_IN2000 is not set ++# CONFIG_SCSI_BUSLOGIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_DTC3280 is not set ++# CONFIG_SCSI_EATA is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_GDTH is not set ++# CONFIG_SCSI_GENERIC_NCR5380 is not set ++# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set ++# CONFIG_SCSI_IPS is not set ++CONFIG_SCSI_INITIO=m ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_PPA is not set ++# CONFIG_SCSI_IMM is not set ++# CONFIG_SCSI_NCR53C406A is not set ++CONFIG_SCSI_LASI700=m ++CONFIG_SCSI_SYM53C8XX_2=m ++CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 ++CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 ++CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 ++# CONFIG_SCSI_IPR is not set ++CONFIG_SCSI_ZALON=m ++CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 ++CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 ++CONFIG_SCSI_NCR53C8XX_SYNC=20 ++# CONFIG_SCSI_PAS16 is not set ++# CONFIG_SCSI_QLOGIC_FAS is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_SIM710 is not set ++# CONFIG_SCSI_SYM53C416 is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_DC390T is not set ++# CONFIG_SCSI_T128 is not set ++# CONFIG_SCSI_U14_34F is not set ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++# CONFIG_MEGARAID_NEWGEN is not set ++CONFIG_MEGARAID_MM=m ++CONFIG_MEGARAID_MAILBOX=m ++CONFIG_MEGARAID_LEGACY=m ++ ++## ++## file: drivers/scsi/pcmcia/Kconfig ++## ++CONFIG_PCMCIA_FDOMAIN=m ++CONFIG_PCMCIA_QLOGIC=m ++CONFIG_PCMCIA_SYM53C500=m ++ ++## ++## file: drivers/telephony/Kconfig ++## ++# CONFIG_PHONE is not set ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_CS=m ++CONFIG_SERIAL_8250_NR_UARTS=32 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_MANY_PORTS=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++# CONFIG_SERIAL_8250_DETECT_IRQ is not set ++# CONFIG_SERIAL_8250_RSA is not set ++CONFIG_SERIAL_MUX=y ++CONFIG_SERIAL_MUX_CONSOLE=y ++CONFIG_SERIAL_JSM=m ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++# CONFIG_USB_USS720 is not set ++ ++## ++## file: drivers/usb/core/Kconfig ++## ++CONFIG_USB_DEBUG=y ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_OHCI_HCD=m ++# CONFIG_USB_UHCI_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++CONFIG_FB_MODE_HELPERS=y ++# CONFIG_FB_TILEBLITTING is not set ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++CONFIG_FB_STI=y ++# CONFIG_FB_S1D13XXX 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_VIRTUAL is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_DUMMY_CONSOLE_COLUMNS=160 ++CONFIG_DUMMY_CONSOLE_ROWS=64 ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_STI_CONSOLE=y ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: drivers/w1/Kconfig ++## ++# CONFIG_W1 is not set ++ ++## ++## file: fs/nfs/Kconfig ++## ++CONFIG_ROOT_NFS=y ++ ++## ++## file: fs/partitions/Kconfig ++## ++# CONFIG_PARTITION_ADVANCED is not set ++ ++## ++## file: lib/Kconfig.debug ++## ++# CONFIG_LOCKUP_DETECTOR is not set ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/ax25/Kconfig ++## ++# CONFIG_HAMRADIO is not set ++ ++## ++## file: net/bluetooth/Kconfig ++## ++#. TODO ++# CONFIG_BT is not set ++ ++## ++## file: net/decnet/Kconfig ++## ++# CONFIG_DECNET is not set ++ ++## ++## file: net/ipv4/Kconfig ++## ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_PNP=y ++# CONFIG_IP_PNP_DHCP is not set ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_IP_PNP_RARP is not set ++ ++## ++## file: net/ipx/Kconfig ++## ++# CONFIG_IPX is not set ++ ++## ++## file: net/irda/Kconfig ++## ++# CONFIG_IRDA is not set ++ ++## ++## file: net/lapb/Kconfig ++## ++# CONFIG_LAPB is not set ++ ++## ++## file: net/llc/Kconfig ++## ++# CONFIG_LLC2 is not set ++ ++## ++## file: sound/drivers/Kconfig ++## ++CONFIG_SND_DUMMY=m ++# CONFIG_SND_VIRMIDI is not set ++# CONFIG_SND_MTPAV is not set ++# CONFIG_SND_SERIAL_U16550 is not set ++# CONFIG_SND_MPU401 is not set ++ ++## ++## file: sound/isa/Kconfig ++## ++# CONFIG_SND_AD1848 is not set ++# CONFIG_SND_CMI8330 is not set ++# CONFIG_SND_CS4231 is not set ++# CONFIG_SND_CS4236 is not set ++# CONFIG_SND_ES1688 is not set ++# CONFIG_SND_ES18XX is not set ++# CONFIG_SND_GUSCLASSIC is not set ++# CONFIG_SND_GUSEXTREME is not set ++# CONFIG_SND_GUSMAX is not set ++# CONFIG_SND_INTERWAVE is not set ++# CONFIG_SND_INTERWAVE_STB is not set ++# CONFIG_SND_OPL3SA2 is not set ++# CONFIG_SND_OPTI92X_AD1848 is not set ++# CONFIG_SND_OPTI92X_CS4231 is not set ++# CONFIG_SND_OPTI93X is not set ++# CONFIG_SND_SB8 is not set ++# CONFIG_SND_SB16 is not set ++# CONFIG_SND_SBAWE is not set ++# CONFIG_SND_SSCAPE is not set ++# CONFIG_SND_WAVEFRONT is not set ++ ++## ++## file: sound/parisc/Kconfig ++## ++CONFIG_SND_HARMONY=m ++ ++## ++## file: sound/pci/Kconfig ++## ++# CONFIG_SND_ALS4000 is not set ++# CONFIG_SND_ALI5451 is not set ++# CONFIG_SND_ATIIXP is not set ++# CONFIG_SND_ATIIXP_MODEM is not set ++# CONFIG_SND_AU8810 is not set ++# CONFIG_SND_AU8820 is not set ++# CONFIG_SND_AU8830 is not set ++# CONFIG_SND_AZT3328 is not set ++# CONFIG_SND_BT87X is not set ++# CONFIG_SND_CA0106 is not set ++# CONFIG_SND_CMIPCI is not set ++# CONFIG_SND_CS4281 is not set ++# CONFIG_SND_CS46XX is not set ++# CONFIG_SND_EMU10K1 is not set ++# CONFIG_SND_EMU10K1X is not set ++# CONFIG_SND_ENS1370 is not set ++# CONFIG_SND_ENS1371 is not set ++# CONFIG_SND_ES1938 is not set ++# CONFIG_SND_ES1968 is not set ++# CONFIG_SND_FM801 is not set ++# CONFIG_SND_HDSP is not set ++# CONFIG_SND_ICE1712 is not set ++# CONFIG_SND_ICE1724 is not set ++# CONFIG_SND_INTEL8X0 is not set ++# CONFIG_SND_INTEL8X0M is not set ++# CONFIG_SND_KORG1212 is not set ++# CONFIG_SND_MAESTRO3 is not set ++# CONFIG_SND_MIXART is not set ++# CONFIG_SND_NM256 is not set ++# CONFIG_SND_RME32 is not set ++# CONFIG_SND_RME96 is not set ++# CONFIG_SND_RME9652 is not set ++# CONFIG_SND_SONICVIBES is not set ++# CONFIG_SND_TRIDENT is not set ++# CONFIG_SND_VIA82XX is not set ++# CONFIG_SND_VIA82XX_MODEM is not set ++# CONFIG_SND_VX222 is not set ++# CONFIG_SND_YMFPCI is not set ++ ++## ++## file: sound/pci/hda/Kconfig ++## ++# CONFIG_SND_HDA_INTEL is not set ++ +diff --git a/debian/config/hppa/config.parisc b/debian/config/hppa/config.parisc +new file mode 100644 +index 0000000..cf39102 +--- /dev/null ++++ b/debian/config/hppa/config.parisc +@@ -0,0 +1,32 @@ ++## ++## file: arch/parisc/Kconfig ++## ++## choice: Processor type ++CONFIG_PA7000=y ++# CONFIG_PA8X00 is not set ++## end choice ++# CONFIG_SMP is not set ++# CONFIG_HPUX is not set ++ ++## ++## file: drivers/net/ethernet/racal/Kconfig ++## ++# CONFIG_NI5010 is not set ++ ++## ++## file: drivers/net/ethernet/ti/Kconfig ++## ++CONFIG_TLAN=m ++ ++## ++## file: drivers/scsi/Kconfig ++## ++# CONFIG_SCSI_DPT_I2O is not set ++# CONFIG_SCSI_NSP32 is not set ++ ++## ++## file: drivers/scsi/pcmcia/Kconfig ++## ++CONFIG_PCMCIA_AHA152X=m ++CONFIG_PCMCIA_NINJA_SCSI=m ++ +diff --git a/debian/config/hppa/config.parisc-smp b/debian/config/hppa/config.parisc-smp +new file mode 100644 +index 0000000..8c9cc9a +--- /dev/null ++++ b/debian/config/hppa/config.parisc-smp +@@ -0,0 +1,28 @@ ++## ++## file: arch/parisc/Kconfig ++## ++## choice: Processor type ++CONFIG_PA7000=y ++# CONFIG_PA8X00 is not set ++## end choice ++CONFIG_SMP=y ++# CONFIG_HPUX is not set ++CONFIG_NR_CPUS=8 ++ ++## ++## file: drivers/net/ethernet/ti/Kconfig ++## ++CONFIG_TLAN=m ++ ++## ++## file: drivers/scsi/Kconfig ++## ++# CONFIG_SCSI_DPT_I2O is not set ++# CONFIG_SCSI_NSP32 is not set ++ ++## ++## file: drivers/scsi/pcmcia/Kconfig ++## ++CONFIG_PCMCIA_AHA152X=m ++CONFIG_PCMCIA_NINJA_SCSI=m ++ +diff --git a/debian/config/hppa/config.parisc64 b/debian/config/hppa/config.parisc64 +new file mode 100644 +index 0000000..a936332 +--- /dev/null ++++ b/debian/config/hppa/config.parisc64 +@@ -0,0 +1,22 @@ ++## ++## file: arch/parisc/Kconfig ++## ++## choice: Processor type ++# CONFIG_PA7000 is not set ++CONFIG_PA8X00=y ++## end choice ++CONFIG_64BIT=y ++# CONFIG_SMP is not set ++ ++## ++## file: drivers/net/ethernet/racal/Kconfig ++## ++# CONFIG_NI5010 is not set ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++# CONFIG_FLATMEM_MANUAL is not set ++## end choice ++ +diff --git a/debian/config/hppa/config.parisc64-smp b/debian/config/hppa/config.parisc64-smp +new file mode 100644 +index 0000000..143936d +--- /dev/null ++++ b/debian/config/hppa/config.parisc64-smp +@@ -0,0 +1,18 @@ ++## ++## file: arch/parisc/Kconfig ++## ++## choice: Processor type ++# CONFIG_PA7000 is not set ++CONFIG_PA8X00=y ++## end choice ++CONFIG_64BIT=y ++CONFIG_SMP=y ++CONFIG_NR_CPUS=8 ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++# CONFIG_FLATMEM_MANUAL is not set ++## end choice ++ +diff --git a/debian/config/hppa/defines b/debian/config/hppa/defines +new file mode 100644 +index 0000000..cdc7818 +--- /dev/null ++++ b/debian/config/hppa/defines +@@ -0,0 +1,35 @@ ++[base] ++flavours: ++ parisc ++ parisc-smp ++ parisc64 ++ parisc64-smp ++kernel-arch: parisc ++compiler: gcc-4.4 ++ ++[image] ++suggests: palo ++ ++[parisc_description] ++hardware: 32-bit PA-RISC ++ ++[parisc-smp_description] ++hardware: multiprocessor 32-bit PA-RISC ++ ++[parisc64_base] ++cflags: -fno-cse-follow-jumps ++override-host-type: hppa64-linux-gnu ++ ++[parisc64_description] ++hardware: 64-bit PA-RISC ++ ++[parisc64-smp_base] ++cflags: -fno-cse-follow-jumps ++override-host-type: hppa64-linux-gnu ++ ++[parisc64-smp_description] ++hardware: multiprocessor 64-bit PA-RISC ++ ++[relations] ++gcc-4.4: gcc-4.4, binutils-hppa64, gcc-4.4-hppa64 ++ +diff --git a/debian/config/i386/defines b/debian/config/i386/defines +new file mode 100644 +index 0000000..acc4c53 +--- /dev/null ++++ b/debian/config/i386/defines +@@ -0,0 +1,53 @@ ++[abi] ++ignore-changes: ++ disable_hlt ++ enable_hlt ++# Only for use by the vendor-specific KVM modules ++ module:arch/x86/kvm/kvm ++ ++[base] ++featuresets: ++ none ++kernel-arch: x86 ++ ++[description] ++part-long-pae: This kernel requires PAE (Physical Address Extension). ++ This feature is supported by the Intel Pentium Pro/II/III/4/4M/D, Xeon, ++ Core and Atom; AMD Geode NX, Athlon (K7), Duron, Opteron, Sempron, ++ Turion or Phenom; Transmeta Efficeon; VIA C7; and some other processors. ++ ++[image] ++bootloaders: grub-pc extlinux lilo ++configs: ++ kernelarch-x86/config ++ ++[486_description] ++hardware: older PCs ++hardware-long: PCs with a single processor not supporting PAE ++parts: up ++ ++[486_image] ++configs: ++ kernelarch-x86/config-arch-32 ++ ++[686-pae_build] ++debug-info: true ++ ++[686-pae_description] ++hardware: modern PCs ++hardware-long: PCs with one or more processors supporting PAE ++parts: pae ++ ++[686-pae_image] ++configs: ++ kernelarch-x86/config-arch-32 ++recommends: libc6-i686 ++ ++[amd64_description] ++hardware: 64-bit PCs ++hardware-long: PCs with AMD64, Intel 64 or VIA Nano processors ++ ++[amd64_image] ++configs: ++ kernelarch-x86/config-arch-64 ++recommends: libc6-i686 +diff --git a/debian/config/i386/none/config.486 b/debian/config/i386/none/config.486 +new file mode 100644 +index 0000000..7d86f60 +--- /dev/null ++++ b/debian/config/i386/none/config.486 +@@ -0,0 +1,148 @@ ++## ++## file: arch/x86/Kconfig ++## ++# CONFIG_SMP is not set ++CONFIG_X86_32_IRIS=m ++CONFIG_X86_UP_APIC=y ++CONFIG_X86_UP_IOAPIC=y ++# CONFIG_X86_MCE is not set ++CONFIG_MATH_EMULATION=y ++CONFIG_EISA=y ++CONFIG_MCA=y ++CONFIG_OLPC=y ++CONFIG_OLPC_XO1_PM=y ++CONFIG_OLPC_XO1_RTC=y ++CONFIG_OLPC_XO1_SCI=y ++CONFIG_OLPC_XO15_SCI=y ++ ++## ++## file: arch/x86/Kconfig.cpu ++## ++## choice: Processor family ++CONFIG_M486=y ++# CONFIG_M686 is not set ++## end choice ++ ++## ++## file: drivers/eisa/Kconfig ++## ++CONFIG_EISA_VLB_PRIMING=y ++CONFIG_EISA_PCI_EISA=y ++CONFIG_EISA_VIRTUAL_ROOT=y ++CONFIG_EISA_NAMES=y ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_ELEKTOR=m ++CONFIG_I2C_STUB=m ++ ++## ++## file: drivers/idle/Kconfig ++## ++# CONFIG_INTEL_IDLE is not set ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_MOUSE_PS2_OLPC=y ++ ++## ++## file: drivers/mca/Kconfig ++## ++CONFIG_MCA_LEGACY=y ++# CONFIG_MCA_PROC_FS is not set ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++# CONFIG_MTD_XIP is not set ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_NET_VENDOR_8390=y ++CONFIG_ES3210=m ++CONFIG_LNE390=m ++CONFIG_NE2_MCA=m ++CONFIG_NE3210=m ++CONFIG_ULTRAMCA=m ++CONFIG_ULTRA32=m ++ ++## ++## file: drivers/net/ethernet/i825xx/Kconfig ++## ++CONFIG_NET_VENDOR_I825XX=y ++CONFIG_ELMC=m ++CONFIG_ELMC_II=m ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_NET_VENDOR_NATSEMI=y ++CONFIG_IBMLANA=m ++ ++## ++## file: drivers/net/ethernet/racal/Kconfig ++## ++CONFIG_NET_VENDOR_RACAL=y ++CONFIG_NI5010=m ++ ++## ++## file: drivers/net/hamradio/Kconfig ++## ++CONFIG_DMASCC=m ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++CONFIG_MADGEMC=m ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM=y ++ ++## ++## file: drivers/platform/x86/Kconfig ++## ++CONFIG_XO1_RFKILL=m ++CONFIG_XO15_EBOOK=m ++ ++## ++## file: drivers/power/Kconfig ++## ++CONFIG_BATTERY_OLPC=m ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI_FD_MCS=m ++CONFIG_SCSI_IBMMCA=m ++CONFIG_IBMMCA_SCSI_ORDER_STANDARD=y ++# CONFIG_IBMMCA_SCSI_DEV_RESET is not set ++CONFIG_SCSI_NCR_D700=m ++CONFIG_SCSI_NCR_Q720=m ++CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 ++CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4 ++CONFIG_SCSI_NCR53C8XX_SYNC=5 ++CONFIG_SCSI_SIM710=m ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_MOXA_INTELLIO=m ++ ++## ++## file: drivers/video/geode/Kconfig ++## ++CONFIG_FB_GEODE=y ++CONFIG_FB_GEODE_LX=m ++CONFIG_FB_GEODE_GX=m ++CONFIG_FB_GEODE_GX1=m ++ ++## ++## file: mm/Kconfig ++## ++# CONFIG_TRANSPARENT_HUGEPAGE is not set ++ +diff --git a/debian/config/i386/none/config.686-pae b/debian/config/i386/none/config.686-pae +new file mode 100644 +index 0000000..cb40354 +--- /dev/null ++++ b/debian/config/i386/none/config.686-pae +@@ -0,0 +1,53 @@ ++## ++## file: arch/x86/Kconfig ++## ++# CONFIG_X86_32_IRIS is not set ++## choice: High Memory Support ++# CONFIG_NOHIGHMEM is not set ++# CONFIG_HIGHMEM4G is not set ++CONFIG_HIGHMEM64G=y ++## end choice ++CONFIG_X86_PAE=y ++# CONFIG_MATH_EMULATION is not set ++# CONFIG_EISA is not set ++# CONFIG_MCA is not set ++ ++## ++## file: arch/x86/Kconfig.cpu ++## ++## choice: Processor family ++# CONFIG_M486 is not set ++CONFIG_M686=y ++## end choice ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++# CONFIG_I2C_ELEKTOR is not set ++CONFIG_I2C_STUB=m ++ ++## ++## file: drivers/net/ethernet/racal/Kconfig ++## ++# CONFIG_NI5010 is not set ++ ++## ++## file: drivers/net/hamradio/Kconfig ++## ++# CONFIG_DMASCC is not set ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set ++ ++## ++## file: drivers/tty/Kconfig ++## ++# CONFIG_MOXA_INTELLIO is not set ++ ++## ++## file: lib/Kconfig.debug ++## ++# CONFIG_DEBUG_HIGHMEM is not set ++ +diff --git a/debian/config/i386/none/defines b/debian/config/i386/none/defines +new file mode 100644 +index 0000000..fb94a4e +--- /dev/null ++++ b/debian/config/i386/none/defines +@@ -0,0 +1,5 @@ ++[base] ++flavours: ++ 486 ++ 686-pae ++ amd64 +diff --git a/debian/config/ia64/config b/debian/config/ia64/config +new file mode 100644 +index 0000000..6d8841e +--- /dev/null ++++ b/debian/config/ia64/config +@@ -0,0 +1,877 @@ ++## ++## file: arch/Kconfig ++## ++CONFIG_OPROFILE=m ++CONFIG_KPROBES=y ++ ++## ++## file: arch/ia64/Kconfig ++## ++CONFIG_HOTPLUG_CPU=y ++CONFIG_SCHED_SMT=y ++CONFIG_PERMIT_BSP_REMOVE=y ++CONFIG_NODES_SHIFT=8 ++CONFIG_IA64_MCA_RECOVERY=m ++CONFIG_PERFMON=y ++CONFIG_IA64_PALINFO=m ++CONFIG_KEXEC=y ++CONFIG_CRASH_DUMP=y ++CONFIG_MSPEC=m ++ ++## ++## file: arch/ia64/Kconfig.debug ++## ++## choice: Physical memory granularity ++CONFIG_IA64_GRANULE_16MB=y ++# CONFIG_IA64_GRANULE_64MB is not set ++## end choice ++CONFIG_IA64_PRINT_HAZARDS=y ++# CONFIG_DISABLE_VHPT is not set ++# CONFIG_IA64_DEBUG_CMPXCHG is not set ++# CONFIG_IA64_DEBUG_IRQ is not set ++ ++## ++## file: arch/ia64/hp/sim/Kconfig ++## ++# CONFIG_HP_SIMETH is not set ++# CONFIG_HP_SIMSERIAL is not set ++# CONFIG_HP_SIMSCSI is not set ++ ++## ++## file: arch/ia64/kernel/cpufreq/Kconfig ++## ++CONFIG_IA64_ACPI_CPUFREQ=m ++ ++## ++## file: drivers/acpi/Kconfig ++## ++CONFIG_ACPI_DOCK=y ++CONFIG_ACPI_PCI_SLOT=m ++CONFIG_ACPI_CONTAINER=y ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_PATA_ALI=m ++CONFIG_PATA_AMD=m ++CONFIG_PATA_CMD64X=m ++CONFIG_PATA_CS5520=m ++CONFIG_PATA_CS5530=m ++CONFIG_PATA_EFAR=m ++CONFIG_PATA_HPT366=m ++CONFIG_PATA_HPT37X=m ++CONFIG_PATA_NETCELL=m ++CONFIG_PATA_NS87415=m ++CONFIG_PATA_OLDPIIX=m ++CONFIG_PATA_PDC2027X=m ++CONFIG_PATA_PDC_OLD=m ++CONFIG_PATA_SC1200=m ++CONFIG_PATA_SERVERWORKS=m ++CONFIG_PATA_SIL680=m ++CONFIG_PATA_TRIFLEX=m ++CONFIG_PATA_VIA=m ++CONFIG_PATA_MPIIX=m ++CONFIG_PATA_NS87410=m ++CONFIG_PATA_OPTI=m ++CONFIG_PATA_LEGACY=m ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_CPQ_DA=m ++CONFIG_BLK_CPQ_CISS_DA=m ++CONFIG_CISS_SCSI_TAPE=y ++CONFIG_BLK_DEV_DAC960=m ++CONFIG_BLK_DEV_UMEM=m ++CONFIG_BLK_DEV_SX8=m ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_CDROM_PKTCDVD_BUFFERS=8 ++# CONFIG_CDROM_PKTCDVD_WCACHE is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_STALDRV=y ++CONFIG_SGI_SNSC=y ++CONFIG_SGI_TIOCX=y ++CONFIG_SGI_MBCS=m ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++CONFIG_PPDEV=m ++CONFIG_DTLK=m ++CONFIG_APPLICOM=m ++CONFIG_RAW_DRIVER=m ++CONFIG_MAX_RAW_DEVS=256 ++CONFIG_HPET=y ++# CONFIG_HPET_MMAP is not set ++CONFIG_MMTIMER=m ++ ++## ++## file: drivers/char/agp/Kconfig ++## ++#. Workaround ++CONFIG_AGP=y ++#. Workaround ++CONFIG_AGP_I460=y ++#. Workaround ++CONFIG_AGP_HP_ZX1=y ++#. Workaround ++CONFIG_AGP_SGI_TIOCA=y ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++CONFIG_IPMI_HANDLER=m ++# CONFIG_IPMI_PANIC_EVENT is not set ++CONFIG_IPMI_DEVICE_INTERFACE=m ++CONFIG_IPMI_SI=m ++CONFIG_IPMI_WATCHDOG=m ++CONFIG_IPMI_POWEROFF=m ++ ++## ++## file: drivers/firmware/Kconfig ++## ++CONFIG_EFI_VARS=y ++CONFIG_EFI_VARS_PSTORE=y ++CONFIG_DMIID=y ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++CONFIG_DRM=m ++CONFIG_DRM_TDFX=m ++CONFIG_DRM_R128=m ++CONFIG_DRM_RADEON=m ++CONFIG_DRM_MGA=m ++CONFIG_DRM_SIS=m ++ ++## ++## file: drivers/gpu/drm/nouveau/Kconfig ++## ++CONFIG_DRM_NOUVEAU=m ++# CONFIG_DRM_NOUVEAU_BACKLIGHT is not set ++# CONFIG_DRM_NOUVEAU_DEBUG is not set ++CONFIG_DRM_I2C_CH7006=m ++CONFIG_DRM_I2C_SIL164=m ++ ++## ++## file: drivers/hid/usbhid/Kconfig ++## ++CONFIG_USB_HID=m ++# CONFIG_HID_PID is not set ++CONFIG_USB_KBD=m ++CONFIG_USB_MOUSE=m ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_SENSORS_ADM1021=m ++CONFIG_SENSORS_ADM1025=m ++CONFIG_SENSORS_ADM1026=m ++CONFIG_SENSORS_ADM1031=m ++CONFIG_SENSORS_ASB100=m ++CONFIG_SENSORS_DS1621=m ++CONFIG_SENSORS_F71805F=m ++CONFIG_SENSORS_GL518SM=m ++CONFIG_SENSORS_GL520SM=m ++CONFIG_SENSORS_IT87=m ++CONFIG_SENSORS_LM63=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_LM77=m ++CONFIG_SENSORS_LM78=m ++CONFIG_SENSORS_LM80=m ++CONFIG_SENSORS_LM83=m ++CONFIG_SENSORS_LM85=m ++CONFIG_SENSORS_LM87=m ++CONFIG_SENSORS_LM90=m ++CONFIG_SENSORS_LM92=m ++CONFIG_SENSORS_MAX1619=m ++CONFIG_SENSORS_PC87360=m ++CONFIG_SENSORS_PCF8591=m ++CONFIG_SENSORS_SIS5595=m ++CONFIG_SENSORS_SMSC47M1=m ++CONFIG_SENSORS_SMSC47B397=m ++CONFIG_SENSORS_VIA686A=m ++CONFIG_SENSORS_W83781D=m ++CONFIG_SENSORS_W83L785TS=m ++CONFIG_SENSORS_W83627HF=m ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=m ++CONFIG_I2C_CHARDEV=m ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_ALI1535=m ++CONFIG_I2C_ALI1563=m ++CONFIG_I2C_ALI15X3=m ++CONFIG_I2C_AMD756=m ++CONFIG_I2C_AMD756_S4882=m ++CONFIG_I2C_AMD8111=m ++CONFIG_I2C_I801=m ++CONFIG_I2C_PIIX4=m ++CONFIG_I2C_NFORCE2=m ++CONFIG_I2C_SIS5595=m ++CONFIG_I2C_SIS630=m ++CONFIG_I2C_SIS96X=m ++CONFIG_I2C_VIA=m ++CONFIG_I2C_VIAPRO=m ++CONFIG_I2C_PARPORT=m ++CONFIG_I2C_PARPORT_LIGHT=m ++CONFIG_I2C_PCA_ISA=m ++CONFIG_I2C_STUB=m ++CONFIG_SCx200_ACB=m ++ ++## ++## file: drivers/ide/Kconfig ++## ++CONFIG_IDE=m ++CONFIG_IDE_GD=m ++# CONFIG_BLK_DEV_IDECS is not set ++CONFIG_BLK_DEV_IDECD=m ++CONFIG_BLK_DEV_IDETAPE=m ++# CONFIG_IDE_GENERIC is not set ++# CONFIG_BLK_DEV_IDEPNP is not set ++# CONFIG_BLK_DEV_GENERIC is not set ++# CONFIG_BLK_DEV_OPTI621 is not set ++# CONFIG_BLK_DEV_AEC62XX is not set ++# CONFIG_BLK_DEV_ALI15X3 is not set ++# CONFIG_BLK_DEV_AMD74XX is not set ++# CONFIG_BLK_DEV_CMD64X is not set ++# CONFIG_BLK_DEV_TRIFLEX is not set ++# CONFIG_BLK_DEV_CS5520 is not set ++# CONFIG_BLK_DEV_CS5530 is not set ++# CONFIG_BLK_DEV_HPT366 is not set ++# CONFIG_BLK_DEV_SC1200 is not set ++# CONFIG_BLK_DEV_PIIX is not set ++# CONFIG_BLK_DEV_NS87415 is not set ++# CONFIG_BLK_DEV_PDC202XX_OLD is not set ++# CONFIG_BLK_DEV_PDC202XX_NEW is not set ++# CONFIG_BLK_DEV_SVWKS is not set ++CONFIG_BLK_DEV_SGIIOC4=m ++# CONFIG_BLK_DEV_SIIMAGE is not set ++# CONFIG_BLK_DEV_SLC90E66 is not set ++CONFIG_BLK_DEV_TRM290=m ++# CONFIG_BLK_DEV_VIA82CXXX is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_GAMEPORT_EMU10K1=m ++CONFIG_GAMEPORT_FM801=m ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++CONFIG_INPUT_JOYSTICK=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++CONFIG_KEYBOARD_LKKBD=m ++CONFIG_KEYBOARD_NEWTON=m ++CONFIG_KEYBOARD_SUNKBD=m ++CONFIG_KEYBOARD_XTKBD=m ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_UINPUT=m ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=m ++CONFIG_MOUSE_SERIAL=m ++CONFIG_MOUSE_VSXXXAA=m ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++CONFIG_SERIO_I8042=y ++CONFIG_SERIO_SERPORT=m ++CONFIG_SERIO_PARKBD=m ++CONFIG_SERIO_PCIPS2=m ++CONFIG_SERIO_LIBPS2=y ++CONFIG_SERIO_RAW=m ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_INPUT_TOUCHSCREEN is not set ++ ++## ++## file: drivers/isdn/Kconfig ++## ++CONFIG_ISDN=y ++CONFIG_ISDN_CAPI=m ++ ++## ++## file: drivers/isdn/capi/Kconfig ++## ++CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y ++# CONFIG_ISDN_CAPI_MIDDLEWARE is not set ++CONFIG_ISDN_CAPI_CAPI20=m ++ ++## ++## file: drivers/isdn/hardware/avm/Kconfig ++## ++CONFIG_CAPI_AVM=y ++CONFIG_ISDN_DRV_AVMB1_B1PCI=m ++CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y ++CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m ++CONFIG_ISDN_DRV_AVMB1_AVM_CS=m ++CONFIG_ISDN_DRV_AVMB1_T1PCI=m ++CONFIG_ISDN_DRV_AVMB1_C4=m ++ ++## ++## file: drivers/isdn/hardware/eicon/Kconfig ++## ++CONFIG_CAPI_EICON=y ++CONFIG_ISDN_DIVAS=m ++CONFIG_ISDN_DIVAS_BRIPCI=y ++CONFIG_ISDN_DIVAS_PRIPCI=y ++CONFIG_ISDN_DIVAS_DIVACAPI=m ++CONFIG_ISDN_DIVAS_USERIDI=m ++CONFIG_ISDN_DIVAS_MAINT=m ++ ++## ++## file: drivers/media/Kconfig ++## ++CONFIG_DVB_CORE=m ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++CONFIG_RADIO_MAXIRADIO=m ++CONFIG_USB_DSBR=m ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++CONFIG_I2O=m ++CONFIG_I2O_CONFIG=m ++CONFIG_I2O_BLOCK=m ++CONFIG_I2O_SCSI=m ++CONFIG_I2O_PROC=m ++ ++## ++## file: drivers/mmc/Kconfig ++## ++CONFIG_MMC=m ++# CONFIG_MMC_DEBUG is not set ++ ++## ++## file: drivers/mmc/card/Kconfig ++## ++CONFIG_MMC_BLOCK=m ++ ++## ++## file: drivers/net/Kconfig ++## ++CONFIG_NET_FC=y ++CONFIG_NET_SB1000=m ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++CONFIG_ARCNET=m ++CONFIG_ARCNET_1201=m ++CONFIG_ARCNET_1051=m ++CONFIG_ARCNET_RAW=m ++CONFIG_ARCNET_CAP=m ++CONFIG_ARCNET_COM90xx=m ++CONFIG_ARCNET_COM90xxIO=m ++CONFIG_ARCNET_RIM_I=m ++CONFIG_ARCNET_COM20020=m ++CONFIG_ARCNET_COM20020_PCI=m ++CONFIG_ARCNET_COM20020_CS=m ++ ++## ++## file: drivers/net/ethernet/Kconfig ++## ++CONFIG_FEALNX=m ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++CONFIG_NET_VENDOR_3COM=y ++CONFIG_PCMCIA_3C574=m ++CONFIG_PCMCIA_3C589=m ++CONFIG_VORTEX=m ++CONFIG_TYPHOON=m ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_PCMCIA_AXNET=m ++CONFIG_NE2K_PCI=m ++CONFIG_PCMCIA_PCNET=m ++ ++## ++## file: drivers/net/ethernet/adaptec/Kconfig ++## ++CONFIG_ADAPTEC_STARFIRE=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_AMD8111_ETH=m ++CONFIG_PCMCIA_NMCLAN=m ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++CONFIG_B44=m ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++CONFIG_NET_TULIP=y ++CONFIG_DE2104X=m ++CONFIG_TULIP=m ++# CONFIG_TULIP_MWI is not set ++# CONFIG_TULIP_MMIO is not set ++CONFIG_WINBOND_840=m ++CONFIG_DM9102=m ++CONFIG_PCMCIA_XIRCOM=m ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++CONFIG_SUNDANCE=m ++# CONFIG_SUNDANCE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/fujitsu/Kconfig ++## ++CONFIG_PCMCIA_FMVJ18X=m ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++# CONFIG_HP100 is not set ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++CONFIG_E100=m ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_NATSEMI=m ++ ++## ++## file: drivers/net/ethernet/nvidia/Kconfig ++## ++CONFIG_FORCEDETH=m ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_8139CP=m ++CONFIG_8139TOO=m ++# CONFIG_8139TOO_PIO is not set ++# CONFIG_8139TOO_TUNE_TWISTER is not set ++# CONFIG_8139TOO_8129 is not set ++# CONFIG_8139_OLD_RX_RESET is not set ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++CONFIG_SIS900=m ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_PCMCIA_SMC91C92=m ++CONFIG_EPIC100=m ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++CONFIG_VIA_RHINE=m ++# CONFIG_VIA_RHINE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/xircom/Kconfig ++## ++CONFIG_PCMCIA_XIRC2PS=m ++ ++## ++## file: drivers/net/fddi/Kconfig ++## ++CONFIG_FDDI=y ++CONFIG_SKFP=m ++ ++## ++## file: drivers/net/hippi/Kconfig ++## ++# CONFIG_HIPPI is not set ++ ++## ++## file: drivers/net/irda/Kconfig ++## ++CONFIG_IRTTY_SIR=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_VLSI_FIR=m ++ ++## ++## file: drivers/net/plip/Kconfig ++## ++CONFIG_PLIP=m ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++CONFIG_WAN=y ++CONFIG_LANMEDIA=m ++CONFIG_PCI200SYN=m ++CONFIG_WANXL=m ++CONFIG_PC300=m ++CONFIG_PC300_MLPPP=y ++CONFIG_FARSYNC=m ++CONFIG_DSCC4=m ++# CONFIG_DSCC4_PCISYNC is not set ++# CONFIG_DSCC4_PCI_RST is not set ++CONFIG_DLCI=m ++CONFIG_DLCI_MAX=8 ++ ++## ++## file: drivers/net/wireless/Kconfig ++## ++CONFIG_PCMCIA_RAYCS=m ++CONFIG_ATMEL=m ++CONFIG_PCI_ATMEL=m ++CONFIG_PCMCIA_ATMEL=m ++CONFIG_AIRO_CS=m ++CONFIG_PCMCIA_WL3501=m ++CONFIG_USB_ZD1201=m ++ ++## ++## file: drivers/net/wireless/ipw2x00/Kconfig ++## ++CONFIG_IPW2100=m ++CONFIG_IPW2100_MONITOR=y ++ ++## ++## file: drivers/net/wireless/mwifiex/Kconfig ++## ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_MWIFIEX_PCIE=m ++ ++## ++## file: drivers/net/wireless/orinoco/Kconfig ++## ++CONFIG_HERMES=m ++CONFIG_PLX_HERMES=m ++CONFIG_TMD_HERMES=m ++CONFIG_PCI_HERMES=m ++CONFIG_PCMCIA_HERMES=m ++CONFIG_PCMCIA_SPECTRUM=m ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++CONFIG_HOTPLUG_PCI=y ++CONFIG_HOTPLUG_PCI_SGI=y ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++CONFIG_PCCARD=m ++CONFIG_PCMCIA=m ++CONFIG_CARDBUS=y ++CONFIG_YENTA=m ++CONFIG_PD6729=m ++CONFIG_I82092=m ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_EFI=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI_ARCMSR=m ++CONFIG_SCSI_DMX3191D=m ++CONFIG_SCSI_IPS=m ++CONFIG_SCSI_INITIO=m ++CONFIG_SCSI_INIA100=m ++CONFIG_SCSI_SYM53C8XX_2=m ++CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 ++CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 ++CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 ++CONFIG_SCSI_IPR=m ++CONFIG_SCSI_IPR_TRACE=y ++CONFIG_SCSI_IPR_DUMP=y ++CONFIG_SCSI_QLOGIC_1280=m ++CONFIG_SCSI_DC395x=m ++CONFIG_SCSI_DC390T=m ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++CONFIG_MEGARAID_NEWGEN=y ++CONFIG_MEGARAID_MM=m ++CONFIG_MEGARAID_MAILBOX=m ++CONFIG_MEGARAID_LEGACY=m ++ ++## ++## file: drivers/scsi/pcmcia/Kconfig ++## ++CONFIG_PCMCIA_FDOMAIN=m ++CONFIG_PCMCIA_QLOGIC=m ++CONFIG_PCMCIA_SYM53C500=m ++ ++## ++## file: drivers/sn/Kconfig ++## ++CONFIG_SGI_IOC3=m ++ ++## ++## file: drivers/staging/wlan-ng/Kconfig ++## ++# CONFIG_PRISM2_USB is not set ++ ++## ++## file: drivers/telephony/Kconfig ++## ++CONFIG_PHONE=m ++CONFIG_PHONE_IXJ=m ++CONFIG_PHONE_IXJ_PCMCIA=m ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++CONFIG_SERIAL_NONSTANDARD=y ++CONFIG_ROCKETPORT=m ++# CONFIG_CYCLADES is not set ++CONFIG_MOXA_INTELLIO=m ++# CONFIG_MOXA_SMARTIO is not set ++CONFIG_SYNCLINKMP=m ++# CONFIG_ISI is not set ++CONFIG_N_HDLC=m ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_CS=m ++CONFIG_SERIAL_8250_NR_UARTS=32 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++# CONFIG_SERIAL_8250_DETECT_IRQ is not set ++CONFIG_SERIAL_8250_RSA=y ++CONFIG_SERIAL_SGI_L1_CONSOLE=y ++CONFIG_SERIAL_JSM=m ++CONFIG_SERIAL_SGI_IOC4=m ++CONFIG_SERIAL_SGI_IOC3=m ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++CONFIG_USB_USS720=m ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++CONFIG_USB_SL811_HCD=m ++CONFIG_USB_SL811_CS=m ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++CONFIG_FB_MODE_HELPERS=y ++CONFIG_FB_TILEBLITTING=y ++CONFIG_FB_CIRRUS=m ++CONFIG_FB_PM2=m ++# CONFIG_FB_PM2_FIFO_DISCONNECT is not set ++CONFIG_FB_CYBER2000=m ++CONFIG_FB_ASILIANT=y ++# CONFIG_FB_IMSTT is not set ++CONFIG_FB_S1D13XXX=m ++CONFIG_FB_MATROX=m ++CONFIG_FB_MATROX_MILLENIUM=y ++CONFIG_FB_MATROX_MYSTIQUE=y ++CONFIG_FB_MATROX_G=y ++CONFIG_FB_MATROX_I2C=m ++CONFIG_FB_MATROX_MAVEN=m ++CONFIG_FB_RADEON=m ++CONFIG_FB_RADEON_I2C=y ++# CONFIG_FB_RADEON_DEBUG is not set ++CONFIG_FB_ATY128=m ++CONFIG_FB_ATY=m ++CONFIG_FB_ATY_CT=y ++CONFIG_FB_ATY_GENERIC_LCD=y ++CONFIG_FB_ATY_GX=y ++CONFIG_FB_SAVAGE=m ++CONFIG_FB_SAVAGE_I2C=y ++# CONFIG_FB_SAVAGE_ACCEL is not set ++CONFIG_FB_SIS=m ++CONFIG_FB_SIS_300=y ++CONFIG_FB_SIS_315=y ++CONFIG_FB_NEOMAGIC=m ++CONFIG_FB_KYRO=m ++CONFIG_FB_VOODOO1=m ++CONFIG_FB_TRIDENT=m ++# CONFIG_FB_VIRTUAL is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_VGA_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_ACORN_PARTITION=y ++# CONFIG_ACORN_PARTITION_CUMANA is not set ++CONFIG_ACORN_PARTITION_EESOX=y ++CONFIG_ACORN_PARTITION_ICS=y ++CONFIG_ACORN_PARTITION_ADFS=y ++CONFIG_ACORN_PARTITION_POWERTEC=y ++CONFIG_ACORN_PARTITION_RISCIX=y ++CONFIG_OSF_PARTITION=y ++CONFIG_AMIGA_PARTITION=y ++CONFIG_ATARI_PARTITION=y ++CONFIG_MAC_PARTITION=y ++CONFIG_BSD_DISKLABEL=y ++CONFIG_MINIX_SUBPARTITION=y ++CONFIG_SOLARIS_X86_PARTITION=y ++CONFIG_UNIXWARE_DISKLABEL=y ++CONFIG_LDM_PARTITION=y ++CONFIG_LDM_DEBUG=y ++CONFIG_SGI_PARTITION=y ++CONFIG_ULTRIX_PARTITION=y ++CONFIG_SUN_PARTITION=y ++ ++## ++## file: net/ax25/Kconfig ++## ++CONFIG_HAMRADIO=y ++ ++## ++## file: net/ipv6/Kconfig ++## ++CONFIG_IPV6=y ++ ++## ++## file: net/irda/Kconfig ++## ++CONFIG_IRDA=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++ ++## ++## file: net/irda/ircomm/Kconfig ++## ++CONFIG_IRCOMM=m ++ ++## ++## file: net/irda/irlan/Kconfig ++## ++CONFIG_IRLAN=m ++ ++## ++## file: net/irda/irnet/Kconfig ++## ++CONFIG_IRNET=m ++ ++## ++## file: security/Kconfig ++## ++CONFIG_LSM_MMAP_MIN_ADDR=65536 ++ ++## ++## file: sound/drivers/Kconfig ++## ++CONFIG_SND_DUMMY=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++ ++## ++## file: sound/pci/Kconfig ++## ++CONFIG_SND_ALS4000=m ++CONFIG_SND_ALI5451=m ++CONFIG_SND_ATIIXP=m ++CONFIG_SND_ATIIXP_MODEM=m ++CONFIG_SND_AU8810=m ++CONFIG_SND_AU8820=m ++CONFIG_SND_AU8830=m ++CONFIG_SND_AZT3328=m ++CONFIG_SND_BT87X=m ++# CONFIG_SND_BT87X_OVERCLOCK is not set ++CONFIG_SND_CA0106=m ++CONFIG_SND_CMIPCI=m ++CONFIG_SND_CS4281=m ++CONFIG_SND_CS46XX=m ++CONFIG_SND_CS46XX_NEW_DSP=y ++CONFIG_SND_EMU10K1=m ++CONFIG_SND_EMU10K1X=m ++CONFIG_SND_ENS1370=m ++CONFIG_SND_ENS1371=m ++CONFIG_SND_ES1938=m ++CONFIG_SND_ES1968=m ++CONFIG_SND_FM801=m ++CONFIG_SND_FM801_TEA575X_BOOL=y ++CONFIG_SND_HDSP=m ++CONFIG_SND_ICE1712=m ++CONFIG_SND_ICE1724=m ++CONFIG_SND_INTEL8X0=m ++CONFIG_SND_INTEL8X0M=m ++CONFIG_SND_KORG1212=m ++CONFIG_SND_MAESTRO3=m ++CONFIG_SND_MIXART=m ++CONFIG_SND_NM256=m ++CONFIG_SND_RME32=m ++CONFIG_SND_RME96=m ++CONFIG_SND_RME9652=m ++CONFIG_SND_SONICVIBES=m ++CONFIG_SND_TRIDENT=m ++CONFIG_SND_VIA82XX=m ++CONFIG_SND_VIA82XX_MODEM=m ++CONFIG_SND_VX222=m ++CONFIG_SND_YMFPCI=m ++ ++## ++## file: sound/pci/hda/Kconfig ++## ++CONFIG_SND_HDA_INTEL=m ++ +diff --git a/debian/config/ia64/config.itanium b/debian/config/ia64/config.itanium +new file mode 100644 +index 0000000..e683b84 +--- /dev/null ++++ b/debian/config/ia64/config.itanium +@@ -0,0 +1,11 @@ ++## ++## file: arch/ia64/Kconfig ++## ++## choice: Processor type ++CONFIG_ITANIUM=y ++# CONFIG_MCKINLEY is not set ++## end choice ++CONFIG_SMP=y ++CONFIG_NR_CPUS=64 ++# CONFIG_SCHED_SMT is not set ++ +diff --git a/debian/config/ia64/config.mckinley b/debian/config/ia64/config.mckinley +new file mode 100644 +index 0000000..6da8535 +--- /dev/null ++++ b/debian/config/ia64/config.mckinley +@@ -0,0 +1,11 @@ ++## ++## file: arch/ia64/Kconfig ++## ++## choice: Processor type ++# CONFIG_ITANIUM is not set ++CONFIG_MCKINLEY=y ++## end choice ++CONFIG_SMP=y ++CONFIG_NR_CPUS=64 ++# CONFIG_SCHED_SMT is not set ++ +diff --git a/debian/config/ia64/defines b/debian/config/ia64/defines +new file mode 100644 +index 0000000..d699fa3 +--- /dev/null ++++ b/debian/config/ia64/defines +@@ -0,0 +1,15 @@ ++[base] ++flavours: ++ itanium ++ mckinley ++kernel-arch: ia64 ++ ++[image] ++bootloaders: elilo ++suggests: fdutils ++ ++[itanium_description] ++hardware: Itanium ++ ++[mckinley_description] ++hardware: Itanium II +diff --git a/debian/config/kernelarch-mips/config b/debian/config/kernelarch-mips/config +new file mode 100644 +index 0000000..27b5c84 +--- /dev/null ++++ b/debian/config/kernelarch-mips/config +@@ -0,0 +1,31 @@ ++## ++## file: arch/mips/Kconfig ++## ++CONFIG_SECCOMP=y ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++# CONFIG_NIU is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++# CONFIG_VGA_CONSOLE is not set ++ ++## ++## file: fs/ext2/Kconfig ++## ++# CONFIG_EXT2_FS is not set ++ ++## ++## file: fs/ext3/Kconfig ++## ++# CONFIG_EXT3_FS is not set ++ ++## ++## file: fs/ext4/Kconfig ++## ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++ +diff --git a/debian/config/kernelarch-x86/config b/debian/config/kernelarch-x86/config +new file mode 100644 +index 0000000..cc15594 +--- /dev/null ++++ b/debian/config/kernelarch-x86/config +@@ -0,0 +1,1753 @@ ++## ++## file: arch/Kconfig ++## ++CONFIG_OPROFILE=m ++# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set ++CONFIG_KPROBES=y ++ ++## ++## file: arch/x86/Kconfig ++## ++CONFIG_X86_MPPARSE=y ++# CONFIG_X86_EXTENDED_PLATFORM is not set ++CONFIG_SCHED_OMIT_FRAME_POINTER=y ++CONFIG_PARAVIRT_GUEST=y ++# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set ++CONFIG_KVM_CLOCK=y ++CONFIG_KVM_GUEST=y ++CONFIG_PARAVIRT=y ++# CONFIG_PARAVIRT_SPINLOCKS is not set ++# CONFIG_PARAVIRT_DEBUG is not set ++CONFIG_MEMTEST=y ++CONFIG_HPET_TIMER=y ++CONFIG_SCHED_SMT=y ++CONFIG_SCHED_MC=y ++# CONFIG_IRQ_TIME_ACCOUNTING is not set ++CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y ++CONFIG_X86_MCE=y ++CONFIG_X86_MCE_INTEL=y ++CONFIG_X86_MCE_AMD=y ++# CONFIG_X86_ANCIENT_MCE is not set ++CONFIG_X86_MCE_INJECT=m ++CONFIG_I8K=m ++CONFIG_MICROCODE=m ++CONFIG_MICROCODE_INTEL=y ++CONFIG_MICROCODE_AMD=y ++CONFIG_X86_MSR=m ++CONFIG_X86_CPUID=m ++CONFIG_NODES_SHIFT=6 ++# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set ++CONFIG_X86_RESERVE_LOW=64 ++CONFIG_MTRR=y ++CONFIG_MTRR_SANITIZER=y ++CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0 ++CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 ++CONFIG_X86_PAT=y ++CONFIG_EFI=y ++CONFIG_EFI_STUB=y ++CONFIG_SECCOMP=y ++CONFIG_CC_STACKPROTECTOR=y ++CONFIG_KEXEC=y ++CONFIG_CRASH_DUMP=y ++# CONFIG_KEXEC_JUMP is not set ++CONFIG_RELOCATABLE=y ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_COMPAT_VDSO is not set ++# CONFIG_CMDLINE_BOOL is not set ++CONFIG_PCI=y ++CONFIG_PCI_CNB20LE_QUIRK=y ++# CONFIG_RAPIDIO is not set ++CONFIG_IA32_EMULATION=y ++CONFIG_IA32_AOUT=y ++ ++## ++## file: arch/x86/Kconfig.debug ++## ++CONFIG_STRICT_DEVMEM=y ++CONFIG_X86_VERBOSE_BOOTUP=y ++# CONFIG_EARLY_PRINTK_DBGP is not set ++# CONFIG_DEBUG_STACKOVERFLOW is not set ++# CONFIG_X86_PTDUMP is not set ++CONFIG_DEBUG_RODATA=y ++# CONFIG_DEBUG_RODATA_TEST is not set ++CONFIG_DEBUG_SET_MODULE_RONX=y ++# CONFIG_DEBUG_NX_TEST is not set ++# CONFIG_IOMMU_DEBUG is not set ++# CONFIG_IOMMU_STRESS is not set ++# CONFIG_X86_DECODER_SELFTEST is not set ++## choice: IO delay type ++CONFIG_IO_DELAY_0X80=y ++# CONFIG_IO_DELAY_0XED is not set ++# CONFIG_IO_DELAY_UDELAY is not set ++# CONFIG_IO_DELAY_NONE is not set ++## end choice ++# CONFIG_DEBUG_BOOT_PARAMS is not set ++# CONFIG_CPA_DEBUG is not set ++CONFIG_OPTIMIZE_INLINING=y ++# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set ++ ++## ++## file: arch/x86/kvm/Kconfig ++## ++CONFIG_VIRTUALIZATION=y ++CONFIG_KVM=m ++CONFIG_KVM_INTEL=m ++CONFIG_KVM_AMD=m ++ ++## ++## file: arch/x86/xen/Kconfig ++## ++CONFIG_XEN=y ++# CONFIG_XEN_DEBUG_FS is not set ++ ++## ++## file: crypto/Kconfig ++## ++CONFIG_CRYPTO_CRC32C_INTEL=m ++CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m ++CONFIG_CRYPTO_AES_NI_INTEL=m ++ ++## ++## file: drivers/acpi/Kconfig ++## ++CONFIG_ACPI=y ++# CONFIG_ACPI_PROCFS is not set ++# CONFIG_ACPI_PROCFS_POWER is not set ++# CONFIG_ACPI_EC_DEBUGFS is not set ++# CONFIG_ACPI_PROC_EVENT is not set ++CONFIG_ACPI_AC=m ++CONFIG_ACPI_BATTERY=m ++CONFIG_ACPI_BUTTON=m ++CONFIG_ACPI_VIDEO=m ++CONFIG_ACPI_FAN=m ++CONFIG_ACPI_DOCK=y ++CONFIG_ACPI_PROCESSOR=m ++CONFIG_ACPI_IPMI=m ++CONFIG_ACPI_PROCESSOR_AGGREGATOR=m ++CONFIG_ACPI_THERMAL=m ++# CONFIG_ACPI_DEBUG is not set ++CONFIG_ACPI_PCI_SLOT=m ++CONFIG_ACPI_CONTAINER=m ++CONFIG_ACPI_HOTPLUG_MEMORY=m ++CONFIG_ACPI_SBS=m ++CONFIG_ACPI_HED=m ++# CONFIG_ACPI_CUSTOM_METHOD is not set ++ ++## ++## file: drivers/acpi/apei/Kconfig ++## ++CONFIG_ACPI_APEI=y ++CONFIG_ACPI_APEI_GHES=y ++CONFIG_ACPI_APEI_PCIEAER=y ++CONFIG_ACPI_APEI_MEMORY_FAILURE=y ++# CONFIG_ACPI_APEI_EINJ is not set ++# CONFIG_ACPI_APEI_ERST_DEBUG is not set ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_PATA_ALI=m ++CONFIG_PATA_AMD=m ++CONFIG_PATA_ATIIXP=m ++CONFIG_PATA_CMD64X=m ++CONFIG_PATA_CS5520=m ++CONFIG_PATA_CS5530=m ++CONFIG_PATA_EFAR=m ++CONFIG_PATA_HPT366=m ++CONFIG_PATA_HPT37X=m ++CONFIG_PATA_NETCELL=m ++CONFIG_PATA_NS87415=m ++CONFIG_PATA_OLDPIIX=m ++CONFIG_PATA_PDC2027X=m ++CONFIG_PATA_PDC_OLD=m ++CONFIG_PATA_SC1200=m ++CONFIG_PATA_SERVERWORKS=m ++CONFIG_PATA_SIL680=m ++CONFIG_PATA_TRIFLEX=m ++CONFIG_PATA_VIA=m ++CONFIG_PATA_MPIIX=m ++CONFIG_PATA_NS87410=m ++CONFIG_PATA_PCMCIA=m ++CONFIG_PATA_RZ1000=m ++ ++## ++## file: drivers/atm/Kconfig ++## ++CONFIG_ATM_DRIVERS=y ++CONFIG_ATM_TCP=m ++CONFIG_ATM_LANAI=m ++CONFIG_ATM_ENI=m ++# CONFIG_ATM_ENI_DEBUG is not set ++# CONFIG_ATM_ENI_TUNE_BURST is not set ++CONFIG_ATM_FIRESTREAM=m ++CONFIG_ATM_ZATM=m ++# CONFIG_ATM_ZATM_DEBUG is not set ++CONFIG_ATM_IDT77252=m ++# CONFIG_ATM_IDT77252_DEBUG is not set ++# CONFIG_ATM_IDT77252_RCV_ALL is not set ++CONFIG_ATM_AMBASSADOR=m ++# CONFIG_ATM_AMBASSADOR_DEBUG is not set ++CONFIG_ATM_HORIZON=m ++# CONFIG_ATM_HORIZON_DEBUG is not set ++# CONFIG_ATM_FORE200E_USE_TASKLET is not set ++CONFIG_ATM_FORE200E_TX_RETRY=16 ++CONFIG_ATM_FORE200E_DEBUG=0 ++CONFIG_ATM_HE=m ++CONFIG_ATM_HE_USE_SUNI=y ++ ++## ++## file: drivers/auxdisplay/Kconfig ++## ++CONFIG_KS0108=m ++CONFIG_KS0108_PORT=0x378 ++CONFIG_KS0108_DELAY=2 ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_DEV_FD=m ++CONFIG_PARIDE=m ++CONFIG_BLK_CPQ_DA=m ++CONFIG_BLK_CPQ_CISS_DA=m ++CONFIG_CISS_SCSI_TAPE=y ++CONFIG_BLK_DEV_DAC960=m ++CONFIG_BLK_DEV_UMEM=m ++CONFIG_BLK_DEV_SX8=m ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_CDROM_PKTCDVD_BUFFERS=8 ++# CONFIG_CDROM_PKTCDVD_WCACHE is not set ++CONFIG_XEN_BLKDEV_FRONTEND=m ++CONFIG_XEN_BLKDEV_BACKEND=m ++ ++## ++## file: drivers/block/paride/Kconfig ++## ++CONFIG_PARIDE_PD=m ++CONFIG_PARIDE_PCD=m ++CONFIG_PARIDE_PF=m ++CONFIG_PARIDE_PT=m ++CONFIG_PARIDE_PG=m ++CONFIG_PARIDE_ATEN=m ++CONFIG_PARIDE_BPCK=m ++CONFIG_PARIDE_COMM=m ++CONFIG_PARIDE_DSTR=m ++CONFIG_PARIDE_FIT2=m ++CONFIG_PARIDE_FIT3=m ++CONFIG_PARIDE_EPAT=m ++# CONFIG_PARIDE_EPATC8 is not set ++CONFIG_PARIDE_EPIA=m ++CONFIG_PARIDE_FRIQ=m ++CONFIG_PARIDE_FRPW=m ++CONFIG_PARIDE_KBIC=m ++CONFIG_PARIDE_KTTI=m ++CONFIG_PARIDE_ON20=m ++CONFIG_PARIDE_ON26=m ++ ++## ++## file: drivers/bluetooth/Kconfig ++## ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_H4=y ++CONFIG_BT_HCIUART_BCSP=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIDTL1=m ++CONFIG_BT_HCIBT3C=m ++CONFIG_BT_HCIBLUECARD=m ++CONFIG_BT_HCIBTUART=m ++CONFIG_BT_HCIVHCI=m ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_STALDRV=y ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++CONFIG_PPDEV=m ++CONFIG_NVRAM=m ++CONFIG_DTLK=m ++CONFIG_R3964=m ++CONFIG_APPLICOM=m ++CONFIG_MWAVE=m ++CONFIG_RAW_DRIVER=m ++CONFIG_MAX_RAW_DEVS=256 ++CONFIG_HPET=y ++CONFIG_HPET_MMAP=y ++ ++## ++## file: drivers/char/agp/Kconfig ++## ++#. Workaround ++CONFIG_AGP=y ++#. Workaround ++CONFIG_AGP_AMD64=y ++#. Workaround ++CONFIG_AGP_INTEL=y ++#. Workaround ++CONFIG_AGP_SIS=y ++#. Workaround ++CONFIG_AGP_VIA=y ++ ++## ++## file: drivers/char/hw_random/Kconfig ++## ++CONFIG_HW_RANDOM=m ++CONFIG_HW_RANDOM_INTEL=m ++CONFIG_HW_RANDOM_AMD=m ++CONFIG_HW_RANDOM_GEODE=m ++CONFIG_HW_RANDOM_VIA=m ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++CONFIG_IPMI_HANDLER=m ++# CONFIG_IPMI_PANIC_EVENT is not set ++CONFIG_IPMI_DEVICE_INTERFACE=m ++CONFIG_IPMI_SI=m ++CONFIG_IPMI_WATCHDOG=m ++CONFIG_IPMI_POWEROFF=m ++ ++## ++## file: drivers/char/tpm/Kconfig ++## ++CONFIG_TCG_TPM=m ++CONFIG_TCG_TIS=m ++CONFIG_TCG_NSC=m ++CONFIG_TCG_ATMEL=m ++CONFIG_TCG_INFINEON=m ++ ++## ++## file: drivers/cpufreq/Kconfig ++## ++## choice: Default CPUFreq governor ++# 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 ++## end choice ++ ++## ++## file: drivers/cpufreq/Kconfig.x86 ++## ++CONFIG_X86_PCC_CPUFREQ=m ++CONFIG_X86_ACPI_CPUFREQ=m ++CONFIG_X86_POWERNOW_K8=m ++CONFIG_X86_SPEEDSTEP_CENTRINO=m ++CONFIG_X86_P4_CLOCKMOD=m ++ ++## ++## file: drivers/cpuidle/Kconfig ++## ++CONFIG_CPU_IDLE=y ++ ++## ++## file: drivers/crypto/Kconfig ++## ++CONFIG_CRYPTO_DEV_PADLOCK=m ++CONFIG_CRYPTO_DEV_PADLOCK_AES=m ++CONFIG_CRYPTO_DEV_PADLOCK_SHA=m ++ ++## ++## file: drivers/dma/Kconfig ++## ++CONFIG_DMADEVICES=y ++CONFIG_INTEL_IOATDMA=m ++CONFIG_PCH_DMA=m ++CONFIG_NET_DMA=y ++ ++## ++## file: drivers/edac/Kconfig ++## ++CONFIG_EDAC=y ++# CONFIG_EDAC_DEBUG is not set ++CONFIG_EDAC_DECODE_MCE=m ++CONFIG_EDAC_MM_EDAC=m ++CONFIG_EDAC_AMD64=m ++# CONFIG_EDAC_AMD64_ERROR_INJECTION is not set ++CONFIG_EDAC_AMD76X=m ++CONFIG_EDAC_E7XXX=m ++CONFIG_EDAC_E752X=m ++CONFIG_EDAC_I82875P=m ++CONFIG_EDAC_I3000=m ++CONFIG_EDAC_I82860=m ++CONFIG_EDAC_R82600=m ++CONFIG_EDAC_I5000=m ++CONFIG_EDAC_I7300=m ++CONFIG_EDAC_AMD8131=m ++CONFIG_EDAC_AMD8111=m ++ ++## ++## file: drivers/firmware/Kconfig ++## ++CONFIG_EDD=m ++# CONFIG_EDD_OFF is not set ++CONFIG_EFI_VARS=m ++CONFIG_EFI_VARS_PSTORE=y ++#. Runtime-disabled by default ++CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y ++CONFIG_DELL_RBU=m ++CONFIG_DCDBAS=m ++CONFIG_DMIID=y ++CONFIG_ISCSI_IBFT_FIND=y ++CONFIG_ISCSI_IBFT=y ++ ++## ++## file: drivers/firmware/google/Kconfig ++## ++# CONFIG_GOOGLE_FIRMWARE is not set ++ ++## ++## file: drivers/gpio/Kconfig ++## ++CONFIG_GPIO_PCH=m ++CONFIG_GPIO_ML_IOH=m ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++CONFIG_DRM=m ++CONFIG_DRM_TDFX=m ++CONFIG_DRM_R128=m ++CONFIG_DRM_RADEON=m ++# CONFIG_DRM_I810 is not set ++CONFIG_DRM_I915=m ++CONFIG_DRM_I915_KMS=y ++CONFIG_DRM_MGA=m ++CONFIG_DRM_SIS=m ++ ++## ++## file: drivers/staging/gma500/Kconfig ++## ++CONFIG_DRM_GMA500=m ++CONFIG_DRM_GMA600=y ++CONFIG_DRM_GMA3600=y ++CONFIG_DRM_MEDFIELD=y ++ ++## ++## file: drivers/gpu/drm/nouveau/Kconfig ++## ++CONFIG_DRM_NOUVEAU=m ++CONFIG_DRM_NOUVEAU_BACKLIGHT=y ++# CONFIG_DRM_NOUVEAU_DEBUG is not set ++CONFIG_DRM_I2C_CH7006=m ++CONFIG_DRM_I2C_SIL164=m ++ ++## ++## file: drivers/gpu/stub/Kconfig ++## ++# CONFIG_STUB_POULSBO is not set ++ ++## ++## file: drivers/gpu/vga/Kconfig ++## ++CONFIG_VGA_ARB_MAX_GPUS=16 ++CONFIG_VGA_SWITCHEROO=y ++ ++## ++## file: drivers/hid/usbhid/Kconfig ++## ++CONFIG_USB_HID=m ++CONFIG_USB_KBD=m ++CONFIG_USB_MOUSE=m ++ ++## ++## file: drivers/hv/Kconfig ++## ++CONFIG_HYPERV=m ++CONFIG_HYPERV_UTILS=m ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_SENSORS_ADM1021=m ++CONFIG_SENSORS_ADM1025=m ++CONFIG_SENSORS_ADM1026=m ++CONFIG_SENSORS_ADM1031=m ++CONFIG_SENSORS_K8TEMP=m ++CONFIG_SENSORS_K10TEMP=m ++CONFIG_SENSORS_FAM15H_POWER=m ++CONFIG_SENSORS_ASB100=m ++CONFIG_SENSORS_DS1621=m ++CONFIG_SENSORS_F71805F=m ++CONFIG_SENSORS_GL518SM=m ++CONFIG_SENSORS_GL520SM=m ++CONFIG_SENSORS_IT87=m ++CONFIG_SENSORS_LM63=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_LM77=m ++CONFIG_SENSORS_LM78=m ++CONFIG_SENSORS_LM80=m ++CONFIG_SENSORS_LM83=m ++CONFIG_SENSORS_LM85=m ++CONFIG_SENSORS_LM87=m ++CONFIG_SENSORS_LM90=m ++CONFIG_SENSORS_LM92=m ++CONFIG_SENSORS_MAX1619=m ++CONFIG_SENSORS_PC87360=m ++CONFIG_SENSORS_PCF8591=m ++CONFIG_SENSORS_SCH5636=m ++CONFIG_SENSORS_SIS5595=m ++CONFIG_SENSORS_SMSC47M1=m ++CONFIG_SENSORS_SMSC47B397=m ++CONFIG_SENSORS_VIA686A=m ++CONFIG_SENSORS_W83781D=m ++CONFIG_SENSORS_W83L785TS=m ++CONFIG_SENSORS_W83627HF=m ++CONFIG_SENSORS_ACPI_POWER=m ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=m ++CONFIG_I2C_CHARDEV=m ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_ALI1535=m ++CONFIG_I2C_ALI1563=m ++CONFIG_I2C_ALI15X3=m ++CONFIG_I2C_AMD756=m ++CONFIG_I2C_AMD756_S4882=m ++CONFIG_I2C_AMD8111=m ++CONFIG_I2C_I801=m ++CONFIG_I2C_PIIX4=m ++CONFIG_I2C_NFORCE2=m ++CONFIG_I2C_SIS5595=m ++CONFIG_I2C_SIS630=m ++CONFIG_I2C_SIS96X=m ++CONFIG_I2C_VIA=m ++CONFIG_I2C_VIAPRO=m ++CONFIG_I2C_SCMI=m ++CONFIG_I2C_EG20T=m ++CONFIG_I2C_PARPORT=m ++CONFIG_I2C_PARPORT_LIGHT=m ++CONFIG_I2C_PCA_ISA=m ++CONFIG_SCx200_ACB=m ++ ++## ++## file: drivers/idle/Kconfig ++## ++CONFIG_INTEL_IDLE=y ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_GAMEPORT_EMU10K1=m ++CONFIG_GAMEPORT_FM801=m ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++CONFIG_INPUT_JOYSTICK=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++CONFIG_KEYBOARD_LKKBD=m ++CONFIG_KEYBOARD_NEWTON=m ++CONFIG_KEYBOARD_SUNKBD=m ++CONFIG_KEYBOARD_XTKBD=m ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_PCSPKR=m ++CONFIG_INPUT_APANEL=m ++CONFIG_INPUT_ATLAS_BTNS=m ++CONFIG_INPUT_UINPUT=m ++CONFIG_INPUT_XEN_KBDDEV_FRONTEND=y ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=m ++CONFIG_MOUSE_SERIAL=m ++CONFIG_MOUSE_APPLETOUCH=m ++CONFIG_MOUSE_BCM5974=m ++CONFIG_MOUSE_VSXXXAA=m ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++CONFIG_SERIO_I8042=y ++CONFIG_SERIO_SERPORT=m ++CONFIG_SERIO_CT82C710=m ++CONFIG_SERIO_PARKBD=m ++CONFIG_SERIO_PCIPS2=m ++CONFIG_SERIO_LIBPS2=y ++CONFIG_SERIO_RAW=m ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++CONFIG_INPUT_TOUCHSCREEN=y ++ ++## ++## file: drivers/iommu/Kconfig ++## ++CONFIG_INTEL_IOMMU=y ++# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set ++CONFIG_IRQ_REMAP=y ++ ++## ++## file: drivers/isdn/Kconfig ++## ++CONFIG_ISDN=y ++CONFIG_ISDN_CAPI=m ++ ++## ++## file: drivers/isdn/capi/Kconfig ++## ++CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y ++CONFIG_ISDN_CAPI_MIDDLEWARE=y ++CONFIG_ISDN_CAPI_CAPI20=m ++CONFIG_ISDN_CAPI_CAPIDRV=m ++ ++## ++## file: drivers/isdn/hardware/avm/Kconfig ++## ++CONFIG_CAPI_AVM=y ++CONFIG_ISDN_DRV_AVMB1_B1PCI=m ++CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y ++CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m ++CONFIG_ISDN_DRV_AVMB1_AVM_CS=m ++CONFIG_ISDN_DRV_AVMB1_T1PCI=m ++CONFIG_ISDN_DRV_AVMB1_C4=m ++ ++## ++## file: drivers/isdn/hardware/eicon/Kconfig ++## ++CONFIG_CAPI_EICON=y ++CONFIG_ISDN_DIVAS=m ++CONFIG_ISDN_DIVAS_BRIPCI=y ++CONFIG_ISDN_DIVAS_PRIPCI=y ++CONFIG_ISDN_DIVAS_DIVACAPI=m ++CONFIG_ISDN_DIVAS_USERIDI=m ++CONFIG_ISDN_DIVAS_MAINT=m ++ ++## ++## file: drivers/leds/Kconfig ++## ++CONFIG_LEDS_CLEVO_MAIL=m ++ ++## ++## file: drivers/media/Kconfig ++## ++CONFIG_DVB_CORE=m ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++CONFIG_RADIO_MAXIRADIO=m ++CONFIG_USB_DSBR=m ++ ++## ++## file: drivers/media/rc/Kconfig ++## ++CONFIG_IR_ITE_CIR=m ++CONFIG_IR_FINTEK=m ++CONFIG_IR_NUVOTON=m ++CONFIG_IR_WINBOND_CIR=m ++ ++## ++## file: drivers/media/video/Kconfig ++## ++CONFIG_VIDEO_VIA_CAMERA=m ++ ++## ++## file: drivers/media/video/tm6000/Kconfig ++## ++CONFIG_VIDEO_TM6000=m ++CONFIG_VIDEO_TM6000_ALSA=m ++CONFIG_VIDEO_TM6000_DVB=m ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++CONFIG_I2O=m ++CONFIG_I2O_CONFIG=m ++CONFIG_I2O_BLOCK=m ++CONFIG_I2O_SCSI=m ++CONFIG_I2O_PROC=m ++ ++## ++## file: drivers/misc/Kconfig ++## ++CONFIG_IBM_ASM=m ++CONFIG_PHANTOM=m ++CONFIG_CS5535_MFGPT=m ++CONFIG_HP_ILO=m ++CONFIG_PCH_PHUB=m ++ ++## ++## file: drivers/mmc/Kconfig ++## ++CONFIG_MMC=m ++# CONFIG_MMC_DEBUG is not set ++ ++## ++## file: drivers/mmc/card/Kconfig ++## ++CONFIG_MMC_BLOCK=m ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=m ++CONFIG_MTD_REDBOOT_PARTS=y ++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 ++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set ++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set ++# CONFIG_MTD_CMDLINE_PARTS is not set ++CONFIG_MTD_CHAR=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_BLOCK_RO=m ++CONFIG_FTL=m ++CONFIG_NFTL=m ++CONFIG_NFTL_RW=y ++CONFIG_INFTL=m ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++CONFIG_MTD_CFI=m ++CONFIG_MTD_JEDECPROBE=m ++# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT=m ++CONFIG_MTD_CFI_AMDSTD=m ++CONFIG_MTD_CFI_STAA=m ++CONFIG_MTD_RAM=m ++CONFIG_MTD_ROM=m ++CONFIG_MTD_ABSENT=m ++ ++## ++## file: drivers/mtd/devices/Kconfig ++## ++CONFIG_MTD_PMC551=m ++# CONFIG_MTD_PMC551_BUGFIX is not set ++# CONFIG_MTD_PMC551_DEBUG is not set ++CONFIG_MTD_SLRAM=m ++CONFIG_MTD_PHRAM=m ++CONFIG_MTD_MTDRAM=m ++CONFIG_MTDRAM_TOTAL_SIZE=4096 ++CONFIG_MTDRAM_ERASE_SIZE=128 ++CONFIG_MTD_BLOCK2MTD=m ++CONFIG_MTD_DOC2000=m ++CONFIG_MTD_DOC2001=m ++CONFIG_MTD_DOC2001PLUS=m ++# CONFIG_MTD_DOCPROBE_ADVANCED is not set ++CONFIG_MTD_DOCPROBE_ADDRESS=0 ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++CONFIG_MTD_PHYSMAP=m ++# CONFIG_MTD_PHYSMAP_COMPAT is not set ++CONFIG_MTD_PHYSMAP_START=0x8000000 ++CONFIG_MTD_PHYSMAP_LEN=0x4000000 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=2 ++CONFIG_MTD_SC520CDP=m ++CONFIG_MTD_NETSC520=m ++CONFIG_MTD_TS5500=m ++CONFIG_MTD_SBC_GXX=m ++# CONFIG_MTD_AMD76XROM is not set ++# CONFIG_MTD_ICHXROM is not set ++# CONFIG_MTD_SCB2_FLASH is not set ++CONFIG_MTD_NETtel=m ++CONFIG_MTD_DILNETPC=m ++CONFIG_MTD_DILNETPC_BOOTSIZE=0x80000 ++# CONFIG_MTD_L440GX is not set ++CONFIG_MTD_PCI=m ++ ++## ++## file: drivers/mtd/nand/Kconfig ++## ++CONFIG_MTD_NAND=m ++# CONFIG_MTD_NAND_VERIFY_WRITE is not set ++CONFIG_MTD_NAND_DISKONCHIP=m ++# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set ++CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 ++# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set ++CONFIG_MTD_NAND_PLATFORM=m ++ ++## ++## file: drivers/net/Kconfig ++## ++CONFIG_DUMMY=m ++CONFIG_NET_FC=y ++# CONFIG_NETPOLL_TRAP is not set ++CONFIG_NET_SB1000=m ++CONFIG_XEN_NETDEV_FRONTEND=m ++CONFIG_XEN_NETDEV_BACKEND=m ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++CONFIG_ARCNET=m ++CONFIG_ARCNET_1201=m ++CONFIG_ARCNET_1051=m ++CONFIG_ARCNET_RAW=m ++CONFIG_ARCNET_CAP=m ++CONFIG_ARCNET_COM90xx=m ++CONFIG_ARCNET_COM90xxIO=m ++CONFIG_ARCNET_RIM_I=m ++CONFIG_ARCNET_COM20020=m ++CONFIG_ARCNET_COM20020_PCI=m ++CONFIG_ARCNET_COM20020_CS=m ++ ++## ++## file: drivers/net/can/Kconfig ++## ++CONFIG_PCH_CAN=m ++ ++## ++## file: drivers/net/ethernet/Kconfig ++## ++CONFIG_FEALNX=m ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++CONFIG_NET_VENDOR_3COM=y ++CONFIG_PCMCIA_3C574=m ++CONFIG_PCMCIA_3C589=m ++CONFIG_VORTEX=m ++CONFIG_TYPHOON=m ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_NET_VENDOR_8390=y ++CONFIG_PCMCIA_AXNET=m ++CONFIG_NE2K_PCI=m ++CONFIG_PCMCIA_PCNET=m ++ ++## ++## file: drivers/net/ethernet/adaptec/Kconfig ++## ++CONFIG_NET_VENDOR_ADAPTEC=y ++CONFIG_ADAPTEC_STARFIRE=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_NET_VENDOR_AMD=y ++CONFIG_AMD8111_ETH=m ++CONFIG_PCMCIA_NMCLAN=m ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++CONFIG_NET_VENDOR_BROADCOM=y ++CONFIG_B44=m ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++CONFIG_NET_TULIP=y ++CONFIG_DE2104X=m ++CONFIG_TULIP=m ++# CONFIG_TULIP_MWI is not set ++# CONFIG_TULIP_MMIO is not set ++CONFIG_WINBOND_840=m ++CONFIG_DM9102=m ++CONFIG_PCMCIA_XIRCOM=m ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++CONFIG_NET_VENDOR_DLINK=y ++CONFIG_DE600=m ++CONFIG_DE620=m ++CONFIG_SUNDANCE=m ++# CONFIG_SUNDANCE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/fujitsu/Kconfig ++## ++CONFIG_NET_VENDOR_FUJITSU=y ++CONFIG_PCMCIA_FMVJ18X=m ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++CONFIG_NET_VENDOR_HP=y ++CONFIG_HP100=m ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++CONFIG_NET_VENDOR_INTEL=y ++CONFIG_E100=m ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_NET_VENDOR_NATSEMI=y ++CONFIG_NATSEMI=m ++ ++## ++## file: drivers/net/ethernet/nvidia/Kconfig ++## ++CONFIG_NET_VENDOR_NVIDIA=y ++CONFIG_FORCEDETH=m ++ ++## ++## file: drivers/net/ethernet/oki-semi/pch_gbe/Kconfig ++## ++CONFIG_PCH_GBE=m ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_NET_VENDOR_REALTEK=y ++CONFIG_ATP=m ++CONFIG_8139CP=m ++CONFIG_8139TOO=m ++CONFIG_8139TOO_TUNE_TWISTER=y ++CONFIG_8139TOO_8129=y ++# CONFIG_8139_OLD_RX_RESET is not set ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++CONFIG_NET_VENDOR_SIS=y ++CONFIG_SIS900=m ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_NET_VENDOR_SMSC=y ++CONFIG_PCMCIA_SMC91C92=m ++CONFIG_EPIC100=m ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++CONFIG_NET_VENDOR_SUN=y ++CONFIG_HAPPYMEAL=m ++CONFIG_SUNGEM=m ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++CONFIG_NET_VENDOR_VIA=y ++CONFIG_VIA_RHINE=m ++# CONFIG_VIA_RHINE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/xircom/Kconfig ++## ++CONFIG_NET_VENDOR_XIRCOM=y ++CONFIG_PCMCIA_XIRC2PS=m ++ ++## ++## file: drivers/net/fddi/Kconfig ++## ++CONFIG_FDDI=y ++CONFIG_SKFP=m ++ ++## ++## file: drivers/net/hippi/Kconfig ++## ++CONFIG_HIPPI=y ++CONFIG_ROADRUNNER=m ++# CONFIG_ROADRUNNER_LARGE_RINGS is not set ++ ++## ++## file: drivers/net/irda/Kconfig ++## ++CONFIG_IRTTY_SIR=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_NSC_FIR=m ++CONFIG_WINBOND_FIR=m ++CONFIG_SMC_IRCC_FIR=m ++CONFIG_ALI_FIR=m ++CONFIG_VLSI_FIR=m ++CONFIG_VIA_FIR=m ++ ++## ++## file: drivers/net/plip/Kconfig ++## ++CONFIG_PLIP=m ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++CONFIG_WAN=y ++CONFIG_LANMEDIA=m ++CONFIG_PCI200SYN=m ++CONFIG_WANXL=m ++CONFIG_PC300=m ++CONFIG_PC300_MLPPP=y ++CONFIG_FARSYNC=m ++CONFIG_DSCC4=m ++CONFIG_DSCC4_PCISYNC=y ++CONFIG_DSCC4_PCI_RST=y ++CONFIG_DLCI=m ++CONFIG_DLCI_MAX=8 ++CONFIG_SBNI=m ++# CONFIG_SBNI_MULTILINE is not set ++ ++## ++## file: drivers/net/wireless/Kconfig ++## ++CONFIG_PCMCIA_RAYCS=m ++CONFIG_ATMEL=m ++CONFIG_PCI_ATMEL=m ++CONFIG_PCMCIA_ATMEL=m ++CONFIG_AIRO_CS=m ++CONFIG_PCMCIA_WL3501=m ++CONFIG_USB_ZD1201=m ++ ++## ++## file: drivers/net/wireless/mwifiex/Kconfig ++## ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_MWIFIEX_PCIE=m ++ ++## ++## file: drivers/net/wireless/orinoco/Kconfig ++## ++CONFIG_HERMES=m ++CONFIG_PLX_HERMES=m ++CONFIG_TMD_HERMES=m ++CONFIG_PCI_HERMES=m ++CONFIG_PCMCIA_HERMES=m ++ ++## ++## file: drivers/pci/Kconfig ++## ++CONFIG_XEN_PCIDEV_FRONTEND=m ++CONFIG_HT_IRQ=y ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++CONFIG_HOTPLUG_PCI=y ++CONFIG_HOTPLUG_PCI_FAKE=m ++CONFIG_HOTPLUG_PCI_ACPI=y ++CONFIG_HOTPLUG_PCI_ACPI_IBM=m ++CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m ++CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m ++CONFIG_HOTPLUG_PCI_SHPC=m ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++CONFIG_PCCARD=m ++CONFIG_PCMCIA=m ++CONFIG_CARDBUS=y ++CONFIG_YENTA=m ++CONFIG_PD6729=m ++CONFIG_I82092=m ++CONFIG_TCIC=m ++# CONFIG_PCMCIA_DEBUG is not set ++ ++## ++## file: drivers/platform/x86/Kconfig ++## ++CONFIG_X86_PLATFORM_DEVICES=y ++CONFIG_ACER_WMI=m ++CONFIG_ACERHDF=m ++CONFIG_DELL_LAPTOP=m ++CONFIG_DELL_WMI=m ++CONFIG_DELL_WMI_AIO=m ++CONFIG_AMILO_RFKILL=m ++CONFIG_HP_ACCEL=m ++CONFIG_SONYPI_COMPAT=y ++CONFIG_IDEAPAD_LAPTOP=m ++CONFIG_THINKPAD_ACPI=m ++CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y ++# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set ++# CONFIG_THINKPAD_ACPI_DEBUG is not set ++# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set ++CONFIG_THINKPAD_ACPI_VIDEO=y ++CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y ++CONFIG_SENSORS_HDAPS=m ++# CONFIG_INTEL_MENLOW is not set ++CONFIG_EEEPC_LAPTOP=m ++CONFIG_ASUS_WMI=m ++CONFIG_ASUS_NB_WMI=m ++CONFIG_EEEPC_WMI=m ++CONFIG_ACPI_WMI=m ++CONFIG_MSI_WMI=m ++CONFIG_ACPI_ASUS=m ++CONFIG_TOPSTAR_LAPTOP=m ++CONFIG_ACPI_TOSHIBA=m ++CONFIG_TOSHIBA_BT_RFKILL=m ++CONFIG_ACPI_CMPC=m ++CONFIG_INTEL_IPS=m ++CONFIG_SAMSUNG_LAPTOP=m ++CONFIG_INTEL_OAKTRAIL=m ++ ++## ++## file: drivers/pnp/Kconfig ++## ++CONFIG_PNP=y ++ ++## ++## file: drivers/power/Kconfig ++## ++CONFIG_POWER_SUPPLY=m ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++CONFIG_PDA_POWER=m ++CONFIG_BATTERY_DS2760=m ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_CMOS=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI_DPT_I2O=m ++CONFIG_SCSI_ARCMSR=m ++CONFIG_SCSI_BUSLOGIC=m ++CONFIG_SCSI_DMX3191D=m ++CONFIG_SCSI_EATA=m ++CONFIG_SCSI_EATA_TAGGED_QUEUE=y ++CONFIG_SCSI_EATA_LINKED_COMMANDS=y ++CONFIG_SCSI_EATA_MAX_TAGS=16 ++CONFIG_SCSI_FUTURE_DOMAIN=m ++CONFIG_SCSI_GDTH=m ++CONFIG_SCSI_ISCI=m ++CONFIG_SCSI_IPS=m ++CONFIG_SCSI_INITIO=m ++CONFIG_SCSI_SYM53C8XX_2=m ++CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 ++CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 ++CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 ++CONFIG_SCSI_IPR=m ++# CONFIG_SCSI_IPR_TRACE is not set ++# CONFIG_SCSI_IPR_DUMP is not set ++CONFIG_SCSI_QLOGIC_1280=m ++CONFIG_SCSI_DC395x=m ++CONFIG_SCSI_DC390T=m ++CONFIG_SCSI_DEBUG=m ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++CONFIG_MEGARAID_NEWGEN=y ++CONFIG_MEGARAID_MM=m ++CONFIG_MEGARAID_MAILBOX=m ++CONFIG_MEGARAID_LEGACY=m ++ ++## ++## file: drivers/scsi/pcmcia/Kconfig ++## ++CONFIG_PCMCIA_AHA152X=m ++CONFIG_PCMCIA_FDOMAIN=m ++CONFIG_PCMCIA_QLOGIC=m ++CONFIG_PCMCIA_SYM53C500=m ++ ++## ++## file: drivers/sfi/Kconfig ++## ++CONFIG_SFI=y ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI_TOPCLIFF_PCH=m ++ ++## ++## file: drivers/staging/comedi/Kconfig ++## ++CONFIG_COMEDI=m ++# CONFIG_COMEDI_DEBUG is not set ++CONFIG_COMEDI_MISC_DRIVERS=m ++CONFIG_COMEDI_KCOMEDILIB=m ++CONFIG_COMEDI_BOND=m ++CONFIG_COMEDI_TEST=m ++CONFIG_COMEDI_PARPORT=m ++CONFIG_COMEDI_SERIAL2002=m ++CONFIG_COMEDI_PCI_DRIVERS=m ++CONFIG_COMEDI_ADDI_APCI_035=m ++CONFIG_COMEDI_ADDI_APCI_1032=m ++CONFIG_COMEDI_ADDI_APCI_1500=m ++CONFIG_COMEDI_ADDI_APCI_1516=m ++CONFIG_COMEDI_ADDI_APCI_1564=m ++CONFIG_COMEDI_ADDI_APCI_16XX=m ++CONFIG_COMEDI_ADDI_APCI_2016=m ++CONFIG_COMEDI_ADDI_APCI_2032=m ++CONFIG_COMEDI_ADDI_APCI_2200=m ++CONFIG_COMEDI_ADDI_APCI_3001=m ++CONFIG_COMEDI_ADDI_APCI_3120=m ++CONFIG_COMEDI_ADDI_APCI_3501=m ++CONFIG_COMEDI_ADDI_APCI_3XXX=m ++CONFIG_COMEDI_ADL_PCI6208=m ++CONFIG_COMEDI_ADL_PCI7296=m ++CONFIG_COMEDI_ADL_PCI7432=m ++CONFIG_COMEDI_ADL_PCI8164=m ++CONFIG_COMEDI_ADL_PCI9111=m ++CONFIG_COMEDI_ADL_PCI9118=m ++CONFIG_COMEDI_ADV_PCI1710=m ++CONFIG_COMEDI_ADV_PCI1723=m ++CONFIG_COMEDI_ADV_PCI_DIO=m ++CONFIG_COMEDI_AMPLC_DIO200=m ++CONFIG_COMEDI_AMPLC_PC236=m ++CONFIG_COMEDI_AMPLC_PC263=m ++CONFIG_COMEDI_AMPLC_PCI224=m ++CONFIG_COMEDI_AMPLC_PCI230=m ++CONFIG_COMEDI_CONTEC_PCI_DIO=m ++CONFIG_COMEDI_DT3000=m ++CONFIG_COMEDI_UNIOXX5=m ++CONFIG_COMEDI_GSC_HPDI=m ++CONFIG_COMEDI_ICP_MULTI=m ++CONFIG_COMEDI_II_PCI20KC=m ++CONFIG_COMEDI_DAQBOARD2000=m ++CONFIG_COMEDI_JR3_PCI=m ++CONFIG_COMEDI_KE_COUNTER=m ++CONFIG_COMEDI_CB_PCIDAS64=m ++CONFIG_COMEDI_CB_PCIDAS=m ++CONFIG_COMEDI_CB_PCIDDA=m ++CONFIG_COMEDI_CB_PCIDIO=m ++CONFIG_COMEDI_CB_PCIMDAS=m ++CONFIG_COMEDI_CB_PCIMDDA=m ++CONFIG_COMEDI_ME4000=m ++CONFIG_COMEDI_ME_DAQ=m ++CONFIG_COMEDI_NI_6527=m ++CONFIG_COMEDI_NI_65XX=m ++CONFIG_COMEDI_NI_660X=m ++CONFIG_COMEDI_NI_670X=m ++CONFIG_COMEDI_NI_PCIDIO=m ++CONFIG_COMEDI_NI_PCIMIO=m ++CONFIG_COMEDI_RTD520=m ++CONFIG_COMEDI_S526=m ++CONFIG_COMEDI_S626=m ++CONFIG_COMEDI_SSV_DNP=m ++CONFIG_COMEDI_PCMCIA_DRIVERS=m ++CONFIG_COMEDI_CB_DAS16_CS=m ++CONFIG_COMEDI_DAS08_CS=m ++CONFIG_COMEDI_NI_DAQ_700_CS=m ++CONFIG_COMEDI_NI_DAQ_DIO24_CS=m ++CONFIG_COMEDI_NI_LABPC_CS=m ++CONFIG_COMEDI_NI_MIO_CS=m ++CONFIG_COMEDI_QUATECH_DAQP_CS=m ++CONFIG_COMEDI_USB_DRIVERS=m ++CONFIG_COMEDI_DT9812=m ++CONFIG_COMEDI_USBDUX=m ++CONFIG_COMEDI_USBDUXFAST=m ++CONFIG_COMEDI_VMK80XX=m ++CONFIG_COMEDI_NI_COMMON=m ++CONFIG_COMEDI_MITE=m ++CONFIG_COMEDI_NI_TIO=m ++CONFIG_COMEDI_NI_LABPC=m ++CONFIG_COMEDI_8255=m ++CONFIG_COMEDI_DAS08=m ++CONFIG_COMEDI_FC=m ++ ++## ++## file: drivers/staging/et131x/Kconfig ++## ++CONFIG_ET131X=m ++ ++## ++## file: drivers/staging/hv/Kconfig ++## ++CONFIG_HYPERV_STORAGE=m ++CONFIG_HYPERV_NET=m ++CONFIG_HYPERV_MOUSE=m ++ ++## ++## file: drivers/staging/media/Kconfig ++## ++CONFIG_STAGING_MEDIA=y ++ ++## ++## file: drivers/staging/media/easycap/Kconfig ++## ++CONFIG_EASYCAP=m ++ ++## ++## file: drivers/staging/line6/Kconfig ++## ++CONFIG_LINE6_USB=m ++# CONFIG_LINE6_USB_DUMP_PCM is not set ++# CONFIG_LINE6_USB_IMPULSE_RESPONSE is not set ++ ++## ++## file: drivers/staging/media/go7007/Kconfig ++## ++# CONFIG_VIDEO_GO7007 is not set ++ ++## ++## file: drivers/staging/media/lirc/Kconfig ++## ++CONFIG_LIRC_STAGING=y ++CONFIG_LIRC_BT829=m ++CONFIG_LIRC_IGORPLUGUSB=m ++CONFIG_LIRC_IMON=m ++CONFIG_LIRC_SASEM=m ++CONFIG_LIRC_SERIAL=m ++CONFIG_LIRC_SERIAL_TRANSMITTER=y ++CONFIG_LIRC_SIR=m ++CONFIG_LIRC_TTUSBIR=m ++CONFIG_LIRC_ZILOG=m ++ ++## ++## file: drivers/staging/rtl8187se/Kconfig ++## ++CONFIG_R8187SE=m ++ ++## ++## file: drivers/staging/rtl8192e/Kconfig ++## ++CONFIG_RTL8192E=m ++ ++## ++## file: drivers/staging/rtl8192u/Kconfig ++## ++CONFIG_RTL8192U=m ++ ++## ++## file: drivers/staging/rtl8712/Kconfig ++## ++CONFIG_R8712U=m ++ ++## ++## file: drivers/staging/rts5139/Kconfig ++## ++CONFIG_RTS5139=m ++# CONFIG_RTS5139_DEBUG is not set ++ ++## ++## file: drivers/staging/rts_pstor/Kconfig ++## ++CONFIG_RTS_PSTOR=m ++ ++## ++## file: drivers/staging/usbip/Kconfig ++## ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_HOST=m ++# CONFIG_USBIP_DEBUG is not set ++ ++## ++## file: drivers/staging/vt6656/Kconfig ++## ++CONFIG_VT6656=m ++ ++## ++## file: drivers/staging/wlan-ng/Kconfig ++## ++CONFIG_PRISM2_USB=m ++ ++## ++## file: drivers/staging/zram/Kconfig ++## ++CONFIG_ZRAM=m ++ ++## ++## file: drivers/telephony/Kconfig ++## ++CONFIG_PHONE=m ++CONFIG_PHONE_IXJ=m ++CONFIG_PHONE_IXJ_PCMCIA=m ++ ++## ++## file: drivers/thermal/Kconfig ++## ++CONFIG_THERMAL=m ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++CONFIG_SERIAL_NONSTANDARD=y ++CONFIG_ROCKETPORT=m ++CONFIG_CYCLADES=m ++# CONFIG_CYZ_INTR is not set ++CONFIG_SYNCLINK=m ++CONFIG_SYNCLINKMP=m ++CONFIG_N_HDLC=m ++ ++## ++## file: drivers/tty/hvc/Kconfig ++## ++CONFIG_HVC_XEN=y ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_CS=m ++CONFIG_SERIAL_8250_NR_UARTS=32 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_MANY_PORTS=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++# CONFIG_SERIAL_8250_DETECT_IRQ is not set ++CONFIG_SERIAL_8250_RSA=y ++CONFIG_SERIAL_JSM=m ++CONFIG_SERIAL_PCH_UART=m ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++CONFIG_USB_USS720=m ++ ++## ++## file: drivers/usb/atm/Kconfig ++## ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++ ++## ++## file: drivers/usb/gadget/Kconfig ++## ++CONFIG_USB_GADGET=m ++## choice: USB Peripheral Controller ++CONFIG_USB_EG20T=m ++## end choice ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_OHCI_HCD=m ++# CONFIG_USB_OHCI_HCD_SSB is not set ++CONFIG_USB_UHCI_HCD=m ++CONFIG_USB_SL811_HCD=m ++CONFIG_USB_SL811_CS=m ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_VIDEO_OUTPUT_CONTROL=m ++CONFIG_FB=y ++CONFIG_FB_MODE_HELPERS=y ++CONFIG_FB_TILEBLITTING=y ++CONFIG_FB_CIRRUS=m ++CONFIG_FB_PM2=m ++CONFIG_FB_PM2_FIFO_DISCONNECT=y ++CONFIG_FB_CYBER2000=m ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++CONFIG_FB_VGA16=m ++CONFIG_FB_UVESA=m ++CONFIG_FB_VESA=y ++CONFIG_FB_EFI=y ++CONFIG_FB_N411=m ++CONFIG_FB_HGA=m ++CONFIG_FB_S1D13XXX=m ++CONFIG_FB_LE80578=m ++CONFIG_FB_CARILLO_RANCH=m ++# CONFIG_FB_INTEL is not set ++CONFIG_FB_MATROX=m ++CONFIG_FB_MATROX_MILLENIUM=y ++CONFIG_FB_MATROX_MYSTIQUE=y ++CONFIG_FB_MATROX_I2C=m ++CONFIG_FB_RADEON=m ++CONFIG_FB_RADEON_I2C=y ++CONFIG_FB_RADEON_BACKLIGHT=y ++# CONFIG_FB_RADEON_DEBUG is not set ++CONFIG_FB_ATY128=m ++CONFIG_FB_ATY128_BACKLIGHT=y ++CONFIG_FB_ATY=m ++CONFIG_FB_ATY_CT=y ++CONFIG_FB_ATY_GX=y ++CONFIG_FB_ATY_BACKLIGHT=y ++CONFIG_FB_SAVAGE=m ++# CONFIG_FB_SAVAGE_ACCEL is not set ++CONFIG_FB_SIS=m ++CONFIG_FB_SIS_300=y ++CONFIG_FB_SIS_315=y ++CONFIG_FB_NEOMAGIC=m ++CONFIG_FB_KYRO=m ++CONFIG_FB_VOODOO1=m ++CONFIG_FB_TRIDENT=m ++CONFIG_FB_VIRTUAL=m ++CONFIG_XEN_FBDEV_FRONTEND=y ++ ++## ++## file: drivers/video/backlight/Kconfig ++## ++CONFIG_BACKLIGHT_PROGEAR=m ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_VGA_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: drivers/video/geode/Kconfig ++## ++# CONFIG_FB_GEODE is not set ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_ACQUIRE_WDT=m ++CONFIG_ADVANTECH_WDT=m ++CONFIG_ALIM1535_WDT=m ++CONFIG_ALIM7101_WDT=m ++CONFIG_F71808E_WDT=m ++CONFIG_SP5100_TCO=m ++CONFIG_GEODE_WDT=m ++CONFIG_SC520_WDT=m ++CONFIG_EUROTECH_WDT=m ++CONFIG_IB700_WDT=m ++CONFIG_IBMASR=m ++CONFIG_WAFER_WDT=m ++CONFIG_I6300ESB_WDT=m ++CONFIG_IT8712F_WDT=m ++CONFIG_HP_WATCHDOG=m ++CONFIG_HPWDT_NMI_DECODING=y ++CONFIG_SC1200_WDT=m ++CONFIG_NV_TCO=m ++CONFIG_60XX_WDT=m ++CONFIG_SBC8360_WDT=m ++CONFIG_CPU5_WDT=m ++CONFIG_W83627HF_WDT=m ++CONFIG_W83877F_WDT=m ++CONFIG_W83977F_WDT=m ++CONFIG_MACHZ_WDT=m ++CONFIG_PCIPCWATCHDOG=m ++CONFIG_WDTPCI=m ++CONFIG_USBPCWATCHDOG=m ++ ++## ++## file: drivers/xen/Kconfig ++## ++CONFIG_XEN_BALLOON=y ++CONFIG_XEN_SCRUB_PAGES=y ++CONFIG_XEN_DEV_EVTCHN=m ++CONFIG_XEN_BACKEND=y ++CONFIG_XENFS=m ++CONFIG_XEN_COMPAT_XENFS=y ++CONFIG_XEN_SYS_HYPERVISOR=y ++CONFIG_XEN_GNTDEV=m ++CONFIG_XEN_GRANT_DEV_ALLOC=m ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_ACORN_PARTITION=y ++# CONFIG_ACORN_PARTITION_CUMANA is not set ++# CONFIG_ACORN_PARTITION_EESOX is not set ++CONFIG_ACORN_PARTITION_ICS=y ++# CONFIG_ACORN_PARTITION_ADFS is not set ++# CONFIG_ACORN_PARTITION_POWERTEC is not set ++CONFIG_ACORN_PARTITION_RISCIX=y ++CONFIG_OSF_PARTITION=y ++CONFIG_AMIGA_PARTITION=y ++CONFIG_ATARI_PARTITION=y ++CONFIG_MAC_PARTITION=y ++CONFIG_BSD_DISKLABEL=y ++CONFIG_MINIX_SUBPARTITION=y ++CONFIG_SOLARIS_X86_PARTITION=y ++CONFIG_UNIXWARE_DISKLABEL=y ++CONFIG_LDM_PARTITION=y ++# CONFIG_LDM_DEBUG is not set ++CONFIG_SGI_PARTITION=y ++CONFIG_ULTRIX_PARTITION=y ++CONFIG_SUN_PARTITION=y ++ ++## ++## file: fs/proc/Kconfig ++## ++CONFIG_PROC_VMCORE=y ++ ++## ++## file: kernel/irq/Kconfig ++## ++CONFIG_SPARSE_IRQ=y ++ ++## ++## file: kernel/power/Kconfig ++## ++# CONFIG_PM_TEST_SUSPEND is not set ++# CONFIG_PM_TRACE_RTC is not set ++ ++## ++## file: kernel/trace/Kconfig ++## ++# CONFIG_MMIOTRACE is not set ++ ++## ++## file: lib/Kconfig.debug ++## ++# CONFIG_DEBUG_SHIRQ is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_FRAME_POINTER is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set ++ ++## ++## file: mm/Kconfig ++## ++CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 ++CONFIG_TRANSPARENT_HUGEPAGE=y ++## choice: Transparent Hugepage Support sysfs defaults ++CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y ++## end choice ++ ++## ++## file: mm/Kconfig.debug ++## ++# CONFIG_DEBUG_PAGEALLOC is not set ++ ++## ++## file: net/ax25/Kconfig ++## ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++# CONFIG_AX25_DAMA_SLAVE is not set ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++ ++## ++## file: net/decnet/Kconfig ++## ++CONFIG_DECNET=m ++# CONFIG_DECNET_ROUTER is not set ++ ++## ++## file: net/decnet/netfilter/Kconfig ++## ++CONFIG_DECNET_NF_GRABULATOR=m ++ ++## ++## file: net/ipv6/Kconfig ++## ++CONFIG_IPV6=y ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++# CONFIG_IPX_INTERN is not set ++ ++## ++## file: net/irda/Kconfig ++## ++CONFIG_IRDA=m ++# CONFIG_IRDA_ULTRA is not set ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++# CONFIG_IRDA_DEBUG is not set ++ ++## ++## file: net/irda/ircomm/Kconfig ++## ++CONFIG_IRCOMM=m ++ ++## ++## file: net/irda/irlan/Kconfig ++## ++CONFIG_IRLAN=m ++ ++## ++## file: net/irda/irnet/Kconfig ++## ++CONFIG_IRNET=m ++ ++## ++## file: net/lapb/Kconfig ++## ++CONFIG_LAPB=m ++ ++## ++## file: sound/drivers/Kconfig ++## ++CONFIG_SND_DUMMY=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++ ++## ++## file: sound/pci/Kconfig ++## ++CONFIG_SND_ALS4000=m ++CONFIG_SND_ALI5451=m ++CONFIG_SND_ATIIXP=m ++CONFIG_SND_ATIIXP_MODEM=m ++CONFIG_SND_AU8810=m ++CONFIG_SND_AU8820=m ++CONFIG_SND_AU8830=m ++CONFIG_SND_AZT3328=m ++CONFIG_SND_BT87X=m ++# CONFIG_SND_BT87X_OVERCLOCK is not set ++CONFIG_SND_CA0106=m ++CONFIG_SND_CMIPCI=m ++CONFIG_SND_CS4281=m ++CONFIG_SND_CS46XX=m ++CONFIG_SND_CS46XX_NEW_DSP=y ++CONFIG_SND_EMU10K1=m ++CONFIG_SND_EMU10K1X=m ++CONFIG_SND_ENS1370=m ++CONFIG_SND_ENS1371=m ++CONFIG_SND_ES1938=m ++CONFIG_SND_ES1968=m ++CONFIG_SND_FM801=m ++CONFIG_SND_FM801_TEA575X_BOOL=y ++CONFIG_SND_HDSP=m ++CONFIG_SND_ICE1712=m ++CONFIG_SND_ICE1724=m ++CONFIG_SND_INTEL8X0=m ++CONFIG_SND_INTEL8X0M=m ++CONFIG_SND_KORG1212=m ++CONFIG_SND_MAESTRO3=m ++CONFIG_SND_MIXART=m ++CONFIG_SND_NM256=m ++CONFIG_SND_RME32=m ++CONFIG_SND_RME96=m ++CONFIG_SND_RME9652=m ++CONFIG_SND_SONICVIBES=m ++CONFIG_SND_TRIDENT=m ++CONFIG_SND_VIA82XX=m ++CONFIG_SND_VIA82XX_MODEM=m ++CONFIG_SND_VX222=m ++CONFIG_SND_YMFPCI=m ++ ++## ++## file: sound/pci/hda/Kconfig ++## ++CONFIG_SND_HDA_INTEL=m ++ +diff --git a/debian/config/kernelarch-x86/config-arch-32 b/debian/config/kernelarch-x86/config-arch-32 +new file mode 100644 +index 0000000..6575672 +--- /dev/null ++++ b/debian/config/kernelarch-x86/config-arch-32 +@@ -0,0 +1,559 @@ ++## ++## file: arch/x86/Kconfig ++## ++# CONFIG_64BIT is not set ++CONFIG_SMP=y ++CONFIG_X86_BIGSMP=y ++CONFIG_NR_CPUS=32 ++CONFIG_VM86=y ++CONFIG_TOSHIBA=m ++CONFIG_X86_REBOOTFIXUPS=y ++## choice: High Memory Support ++# CONFIG_NOHIGHMEM is not set ++CONFIG_HIGHMEM4G=y ++# CONFIG_HIGHMEM64G is not set ++## end choice ++# CONFIG_X86_PAE is not set ++# CONFIG_NUMA is not set ++CONFIG_HIGHPTE=y ++CONFIG_PHYSICAL_ALIGN=0x1000000 ++CONFIG_APM=m ++# CONFIG_APM_IGNORE_USER_SUSPEND is not set ++# CONFIG_APM_DO_ENABLE is not set ++# CONFIG_APM_CPU_IDLE is not set ++# CONFIG_APM_DISPLAY_BLANK is not set ++# CONFIG_APM_ALLOW_INTS is not set ++## choice: PCI access mode ++# CONFIG_PCI_GOBIOS is not set ++# CONFIG_PCI_GOMMCONFIG is not set ++# CONFIG_PCI_GODIRECT is not set ++# CONFIG_PCI_GOOLPC is not set ++CONFIG_PCI_GOANY=y ++## end choice ++CONFIG_PCI_MMCONFIG=y ++CONFIG_ISA=y ++CONFIG_SCx200=m ++CONFIG_SCx200HR_TIMER=m ++# CONFIG_OLPC is not set ++ ++## ++## file: arch/x86/Kconfig.cpu ++## ++CONFIG_X86_GENERIC=y ++# CONFIG_X86_PPRO_FENCE is not set ++ ++## ++## file: arch/x86/lguest/Kconfig ++## ++# CONFIG_LGUEST_GUEST is not set ++ ++## ++## file: crypto/Kconfig ++## ++CONFIG_CRYPTO_AES_586=m ++CONFIG_CRYPTO_SALSA20_586=m ++CONFIG_CRYPTO_TWOFISH_586=m ++ ++## ++## file: drivers/acpi/Kconfig ++## ++CONFIG_ACPI_BLACKLIST_YEAR=0 ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_PATA_CS5535=m ++CONFIG_PATA_CS5536=m ++CONFIG_PATA_ISAPNP=m ++CONFIG_PATA_OPTI=m ++CONFIG_PATA_LEGACY=m ++ ++## ++## file: drivers/atm/Kconfig ++## ++CONFIG_ATM_NICSTAR=m ++# CONFIG_ATM_NICSTAR_USE_SUNI is not set ++# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set ++CONFIG_ATM_IA=m ++# CONFIG_ATM_IA_DEBUG is not set ++ ++## ++## file: drivers/auxdisplay/Kconfig ++## ++CONFIG_CFAG12864B=m ++CONFIG_CFAG12864B_RATE=20 ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_DEV_XD=m ++CONFIG_BLK_DEV_RAM_SIZE=8192 ++ ++## ++## file: drivers/block/paride/Kconfig ++## ++CONFIG_PARIDE_BPCK6=m ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_SONYPI=m ++CONFIG_SCx200_GPIO=m ++ ++## ++## file: drivers/char/agp/Kconfig ++## ++#. Workaround ++CONFIG_AGP_ALI=y ++#. Workaround ++CONFIG_AGP_ATI=y ++#. Workaround ++CONFIG_AGP_AMD=y ++#. Workaround ++CONFIG_AGP_NVIDIA=y ++#. Workaround ++CONFIG_AGP_SWORKS=y ++#. Workaround ++CONFIG_AGP_EFFICEON=y ++ ++## ++## file: drivers/cpufreq/Kconfig.x86 ++## ++CONFIG_X86_POWERNOW_K6=m ++CONFIG_X86_POWERNOW_K7=m ++CONFIG_X86_GX_SUSPMOD=m ++CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y ++CONFIG_X86_SPEEDSTEP_ICH=m ++CONFIG_X86_SPEEDSTEP_SMI=m ++CONFIG_X86_CPUFREQ_NFORCE2=m ++CONFIG_X86_LONGRUN=m ++CONFIG_X86_LONGHAUL=m ++# CONFIG_X86_E_POWERSAVER is not set ++CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK=y ++ ++## ++## file: drivers/crypto/Kconfig ++## ++CONFIG_CRYPTO_DEV_GEODE=m ++ ++## ++## file: drivers/gpio/Kconfig ++## ++CONFIG_GPIO_VX855=m ++CONFIG_GPIO_CS5535=m ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++CONFIG_DRM_I810=m ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_PXA=m ++CONFIG_SCx200_I2C=m ++CONFIG_SCx200_I2C_SCL=12 ++CONFIG_SCx200_I2C_SDA=13 ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_WISTRON_BTNS=m ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++# CONFIG_MOUSE_PS2_OLPC is not set ++CONFIG_MOUSE_INPORT=m ++# CONFIG_MOUSE_ATIXL is not set ++CONFIG_MOUSE_LOGIBM=m ++CONFIG_MOUSE_PC110PAD=m ++ ++## ++## file: drivers/iommu/Kconfig ++## ++# CONFIG_INTEL_IOMMU is not set ++ ++## ++## file: drivers/isdn/hardware/avm/Kconfig ++## ++CONFIG_ISDN_DRV_AVMB1_B1ISA=m ++CONFIG_ISDN_DRV_AVMB1_T1ISA=m ++ ++## ++## file: drivers/leds/Kconfig ++## ++CONFIG_LEDS_WRAP=m ++ ++## ++## file: drivers/lguest/Kconfig ++## ++# CONFIG_LGUEST is not set ++ ++## ++## file: drivers/macintosh/Kconfig ++## ++# CONFIG_MACINTOSH_DRIVERS is not set ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++CONFIG_RADIO_CADET=m ++CONFIG_RADIO_RTRACK=m ++CONFIG_RADIO_RTRACK2=m ++CONFIG_RADIO_AZTECH=m ++CONFIG_RADIO_GEMTEK=m ++CONFIG_RADIO_MIROPCM20=m ++CONFIG_RADIO_SF16FMI=m ++CONFIG_RADIO_SF16FMR2=m ++CONFIG_RADIO_TERRATEC=m ++CONFIG_RADIO_TRUST=m ++CONFIG_RADIO_TYPHOON=m ++CONFIG_RADIO_ZOLTRIX=m ++ ++## ++## file: drivers/mfd/Kconfig ++## ++CONFIG_MFD_CS5535=m ++CONFIG_MFD_VX855=m ++ ++## ++## file: drivers/misc/Kconfig ++## ++CONFIG_CS5535_MFGPT=m ++CONFIG_CS5535_CLOCK_EVENT_SRC=m ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++CONFIG_MTD_SCx200_DOCFLASH=m ++CONFIG_MTD_PCMCIA=m ++# CONFIG_MTD_PCMCIA_ANONYMOUS is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++CONFIG_ARCNET_COM20020_ISA=m ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++CONFIG_NET_VENDOR_3COM=y ++CONFIG_EL1=m ++CONFIG_EL3=m ++CONFIG_3C515=m ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_NET_VENDOR_8390=y ++CONFIG_EL2=m ++CONFIG_AC3200=m ++CONFIG_E2100=m ++CONFIG_HPLAN_PLUS=m ++CONFIG_HPLAN=m ++CONFIG_NE2000=m ++CONFIG_ULTRA=m ++CONFIG_WD80x3=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_NET_VENDOR_AMD=y ++CONFIG_LANCE=m ++CONFIG_DEPCA=m ++CONFIG_NI65=m ++ ++## ++## file: drivers/net/ethernet/cirrus/Kconfig ++## ++CONFIG_NET_VENDOR_CIRRUS=y ++CONFIG_CS89x0=m ++ ++## ++## file: drivers/net/ethernet/dec/Kconfig ++## ++CONFIG_NET_VENDOR_DEC=y ++CONFIG_EWRK3=m ++ ++## ++## file: drivers/net/ethernet/fujitsu/Kconfig ++## ++CONFIG_NET_VENDOR_FUJITSU=y ++CONFIG_AT1700=m ++CONFIG_ETH16I=m ++ ++## ++## file: drivers/net/ethernet/i825xx/Kconfig ++## ++CONFIG_NET_VENDOR_I825XX=y ++CONFIG_ELPLUS=m ++CONFIG_EL16=m ++CONFIG_APRICOT=m ++CONFIG_EEXPRESS=m ++CONFIG_EEXPRESS_PRO=m ++CONFIG_LP486E=m ++CONFIG_NI52=m ++CONFIG_ZNET=m ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_8139TOO_PIO=y ++ ++## ++## file: drivers/net/ethernet/seeq/Kconfig ++## ++CONFIG_NET_VENDOR_SEEQ=y ++CONFIG_SEEQ8005=m ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_NET_VENDOR_SMSC=y ++CONFIG_SMC9194=m ++ ++## ++## file: drivers/net/hamradio/Kconfig ++## ++CONFIG_SCC=m ++# CONFIG_SCC_DELAY is not set ++# CONFIG_SCC_TRXECHO is not set ++ ++## ++## file: drivers/net/irda/Kconfig ++## ++CONFIG_TOSHIBA_FIR=m ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++CONFIG_HOSTESS_SV11=m ++CONFIG_COSA=m ++CONFIG_SEALEVEL_4021=m ++CONFIG_N2=m ++CONFIG_C101=m ++CONFIG_SDLA=m ++ ++## ++## file: drivers/net/wireless/ipw2x00/Kconfig ++## ++CONFIG_IPW2100=m ++CONFIG_IPW2100_MONITOR=y ++# CONFIG_IPW2100_DEBUG is not set ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++CONFIG_HOTPLUG_PCI_COMPAQ=m ++CONFIG_HOTPLUG_PCI_IBM=m ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++CONFIG_I82365=m ++ ++## ++## file: drivers/platform/x86/Kconfig ++## ++CONFIG_TC1100_WMI=m ++CONFIG_XO15_EBOOK=m ++ ++## ++## file: drivers/pnp/isapnp/Kconfig ++## ++CONFIG_ISAPNP=y ++ ++## ++## file: drivers/pnp/pnpbios/Kconfig ++## ++CONFIG_PNPBIOS=y ++CONFIG_PNPBIOS_PROC_FS=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI_IN2000=m ++# CONFIG_SCSI_FLASHPOINT is not set ++CONFIG_SCSI_DTC3280=m ++CONFIG_SCSI_EATA_PIO=m ++# CONFIG_SCSI_GENERIC_NCR5380 is not set ++# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set ++# CONFIG_SCSI_GENERIC_NCR53C400 is not set ++# CONFIG_SCSI_INIA100 is not set ++CONFIG_SCSI_NCR53C406A=m ++CONFIG_SCSI_PAS16=m ++CONFIG_SCSI_QLOGIC_FAS=m ++CONFIG_SCSI_SYM53C416=m ++CONFIG_SCSI_T128=m ++CONFIG_SCSI_U14_34F=m ++CONFIG_SCSI_U14_34F_TAGGED_QUEUE=y ++CONFIG_SCSI_U14_34F_LINKED_COMMANDS=y ++CONFIG_SCSI_U14_34F_MAX_TAGS=8 ++CONFIG_SCSI_ULTRASTOR=m ++CONFIG_SCSI_NSP32=m ++ ++## ++## file: drivers/scsi/pcmcia/Kconfig ++## ++CONFIG_PCMCIA_NINJA_SCSI=m ++ ++## ++## file: drivers/staging/comedi/Kconfig ++## ++CONFIG_COMEDI_ISA_DRIVERS=m ++CONFIG_COMEDI_ACL7225B=m ++CONFIG_COMEDI_PCL711=m ++CONFIG_COMEDI_PCL724=m ++CONFIG_COMEDI_PCL725=m ++CONFIG_COMEDI_PCL726=m ++CONFIG_COMEDI_PCL730=m ++CONFIG_COMEDI_PCL812=m ++CONFIG_COMEDI_PCL816=m ++CONFIG_COMEDI_PCL818=m ++CONFIG_COMEDI_PCM3724=m ++CONFIG_COMEDI_PCM3730=m ++CONFIG_COMEDI_RTI800=m ++CONFIG_COMEDI_RTI802=m ++CONFIG_COMEDI_DAS16M1=m ++CONFIG_COMEDI_DAS16=m ++CONFIG_COMEDI_DAS800=m ++CONFIG_COMEDI_DAS1800=m ++CONFIG_COMEDI_DAS6402=m ++CONFIG_COMEDI_DT2801=m ++CONFIG_COMEDI_DT2811=m ++CONFIG_COMEDI_DT2814=m ++CONFIG_COMEDI_DT2815=m ++CONFIG_COMEDI_DT2817=m ++CONFIG_COMEDI_DT282X=m ++CONFIG_COMEDI_DMM32AT=m ++CONFIG_COMEDI_FL512=m ++CONFIG_COMEDI_AIO_AIO12_8=m ++CONFIG_COMEDI_AIO_IIRO_16=m ++CONFIG_COMEDI_C6XDIGIO=m ++CONFIG_COMEDI_MPC624=m ++CONFIG_COMEDI_ADQ12B=m ++CONFIG_COMEDI_NI_AT_A2150=m ++CONFIG_COMEDI_NI_AT_AO=m ++CONFIG_COMEDI_NI_ATMIO=m ++CONFIG_COMEDI_NI_ATMIO16D=m ++CONFIG_COMEDI_PCMAD=m ++CONFIG_COMEDI_PCMDA12=m ++CONFIG_COMEDI_PCMMIO=m ++CONFIG_COMEDI_PCMUIO=m ++CONFIG_COMEDI_MULTIQ3=m ++CONFIG_COMEDI_POC=m ++ ++## ++## file: drivers/staging/olpc_dcon/Kconfig ++## ++CONFIG_FB_OLPC_DCON=m ++CONFIG_FB_OLPC_DCON_1=y ++CONFIG_FB_OLPC_DCON_1_5=y ++ ++## ++## file: drivers/tty/Kconfig ++## ++# CONFIG_ISI is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250_EXAR_ST16C554=m ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB_I810=m ++CONFIG_FB_I810_GTF=y ++CONFIG_FB_I810_I2C=y ++CONFIG_FB_MATROX_G=y ++CONFIG_FB_MATROX_MAVEN=m ++CONFIG_FB_ATY_GENERIC_LCD=y ++CONFIG_FB_SAVAGE_I2C=y ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_MDA_CONSOLE=m ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_SCx200_WDT=m ++CONFIG_SBC7240_WDT=m ++CONFIG_PCWATCHDOG=m ++CONFIG_MIXCOMWD=m ++CONFIG_WDT=m ++ ++## ++## file: fs/Kconfig.binfmt ++## ++CONFIG_BINFMT_AOUT=m ++ ++## ++## file: kernel/irq/Kconfig ++## ++# CONFIG_SPARSE_IRQ is not set ++ ++## ++## file: lib/Kconfig.debug ++## ++CONFIG_FRAME_WARN=1024 ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: security/Kconfig ++## ++CONFIG_LSM_MMAP_MIN_ADDR=0 ++ ++## ++## file: sound/isa/Kconfig ++## ++CONFIG_SND_ISA=y ++CONFIG_SND_ADLIB=m ++CONFIG_SND_AD1816A=m ++CONFIG_SND_AD1848=m ++CONFIG_SND_ALS100=m ++CONFIG_SND_AZT1605=m ++CONFIG_SND_AZT2316=m ++CONFIG_SND_AZT2320=m ++CONFIG_SND_CMI8330=m ++CONFIG_SND_CS4231=m ++CONFIG_SND_CS4236=m ++CONFIG_SND_ES1688=m ++CONFIG_SND_ES18XX=m ++CONFIG_SND_SC6000=m ++CONFIG_SND_GUSCLASSIC=m ++CONFIG_SND_GUSEXTREME=m ++CONFIG_SND_GUSMAX=m ++CONFIG_SND_INTERWAVE=m ++CONFIG_SND_INTERWAVE_STB=m ++CONFIG_SND_JAZZ16=m ++CONFIG_SND_OPL3SA2=m ++CONFIG_SND_OPTI92X_AD1848=m ++CONFIG_SND_OPTI92X_CS4231=m ++CONFIG_SND_OPTI93X=m ++CONFIG_SND_MIRO=m ++CONFIG_SND_SB8=m ++CONFIG_SND_SB16=m ++CONFIG_SND_SBAWE=m ++CONFIG_SND_SB16_CSP=y ++CONFIG_SND_SSCAPE=m ++CONFIG_SND_WAVEFRONT=m ++CONFIG_SND_MSND_PINNACLE=m ++CONFIG_SND_MSND_CLASSIC=m ++ ++## ++## file: sound/pci/Kconfig ++## ++CONFIG_SND_SIS7019=m ++ +diff --git a/debian/config/kernelarch-x86/config-arch-64 b/debian/config/kernelarch-x86/config-arch-64 +new file mode 100644 +index 0000000..c663d5f +--- /dev/null ++++ b/debian/config/kernelarch-x86/config-arch-64 +@@ -0,0 +1,131 @@ ++## ++## file: arch/x86/Kconfig ++## ++CONFIG_64BIT=y ++CONFIG_SMP=y ++CONFIG_X86_X2APIC=y ++CONFIG_CALGARY_IOMMU=y ++CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y ++# CONFIG_MAXSMP is not set ++CONFIG_NR_CPUS=512 ++CONFIG_NUMA=y ++CONFIG_AMD_NUMA=y ++CONFIG_X86_64_ACPI_NUMA=y ++CONFIG_NUMA_EMU=y ++CONFIG_PCI_MMCONFIG=y ++ ++## ++## file: arch/x86/Kconfig.cpu ++## ++## choice: Processor family ++# CONFIG_MK8 is not set ++# CONFIG_MPSC is not set ++# CONFIG_MCORE2 is not set ++# CONFIG_MATOM is not set ++CONFIG_GENERIC_CPU=y ++## end choice ++ ++## ++## file: crypto/Kconfig ++## ++CONFIG_CRYPTO_SHA1_SSSE3=m ++CONFIG_CRYPTO_AES_X86_64=m ++CONFIG_CRYPTO_BLOWFISH_X86_64=m ++CONFIG_CRYPTO_SALSA20_X86_64=m ++CONFIG_CRYPTO_TWOFISH_X86_64=m ++CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++ ++## ++## file: drivers/char/agp/Kconfig ++## ++CONFIG_AGP=y ++#. Needed by GART_IOMMU ++CONFIG_AGP_AMD64=y ++ ++## ++## file: drivers/edac/Kconfig ++## ++CONFIG_EDAC_SBRIDGE=m ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_STUB=m ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_LIFEBOOK=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++ ++## ++## file: drivers/iommu/Kconfig ++## ++CONFIG_AMD_IOMMU=y ++# CONFIG_AMD_IOMMU_STATS is not set ++ ++## ++## file: drivers/macintosh/Kconfig ++## ++CONFIG_MACINTOSH_DRIVERS=y ++CONFIG_MAC_EMUMOUSEBTN=y ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++# CONFIG_8139TOO_PIO is not set ++ ++## ++## file: drivers/net/wireless/ipw2x00/Kconfig ++## ++# CONFIG_IPW2100 is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI_INIA100=m ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_MOXA_INTELLIO=m ++CONFIG_ISI=m ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB_MATROX_G=y ++CONFIG_FB_MATROX_MAVEN=m ++# CONFIG_FB_ATY_GENERIC_LCD is not set ++# CONFIG_FB_SAVAGE_I2C is not set ++ ++## ++## file: init/Kconfig ++## ++CONFIG_RCU_FANOUT=64 ++ ++## ++## file: lib/Kconfig.debug ++## ++CONFIG_FRAME_WARN=2048 ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_SPARSEMEM_MANUAL=y ++## end choice ++CONFIG_SPARSEMEM_VMEMMAP=y ++ ++## ++## file: security/Kconfig ++## ++CONFIG_LSM_MMAP_MIN_ADDR=65536 ++ +diff --git a/debian/config/m68k/README.build b/debian/config/m68k/README.build +new file mode 100644 +index 0000000..8941608 +--- /dev/null ++++ b/debian/config/m68k/README.build +@@ -0,0 +1,26 @@ ++HOWTO cross-build m68k linux-image ++ ++Building linux-image packages takes a while, especially on the "slower ++arches", ie m68k. Cross-compiling is an alternative, and it works very well ++for m68k. ++ ++You need to set up a cross-compiler. The toolchain-source package has some ++limitations, I prefer using cross-tools, see this page for instructions: ++ ++ http://people.debian.org/~cts/debian-m68k/cross-compile/ ++ ++Now you only have to tell the debian build system, that you do want to build ++packages for m68k. It used to be sufficient to pass an option to debuild, ++since recently you also have to set an environment variable, like this: ++ ++ DEB_HOST_ARCH=m68k debuild -B -am68k ++ ++If you also want to build source packages, omit the -B. ++ ++If you want to build images for just one of the currently nine subarches, ++you can uncomment some lines in the flavours section in: ++ debian/arch/m68k/defines ++ ++The first run of debuild will give you an error message that updating the ++configs suceeded, the second run will build the images. ++ +diff --git a/debian/config/m68k/config b/debian/config/m68k/config +new file mode 100644 +index 0000000..f93ff40 +--- /dev/null ++++ b/debian/config/m68k/config +@@ -0,0 +1,303 @@ ++## ++## file: arch/m68k/Kconfig.cpu ++## ++# CONFIG_ADVANCED is not set ++ ++## ++## file: arch/m68k/Kconfig.devices ++## ++CONFIG_PROC_HARDWARE=y ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_DEV_RAM_SIZE=4096 ++# CONFIG_CDROM_PKTCDVD is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_GEN_RTC_X=y ++# CONFIG_DTLK is not set ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++# CONFIG_IPMI_HANDLER is not set ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++# CONFIG_DRM is not set ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++# CONFIG_SENSORS_F71805F is not set ++ ++## ++## file: drivers/i2c/Kconfig ++## ++# CONFIG_I2C is not set ++ ++## ++## file: drivers/infiniband/Kconfig ++## ++# CONFIG_INFINIBAND is not set ++ ++## ++## file: drivers/input/Kconfig ++## ++# CONFIG_INPUT_JOYDEV is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++# CONFIG_GAMEPORT is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++# CONFIG_MOUSE_VSXXXAA is not set ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++# CONFIG_SERIO_RAW is not set ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_INPUT_TOUCHSCREEN is not set ++ ++## ++## file: drivers/media/Kconfig ++## ++# CONFIG_VIDEO_DEV is not set ++ ++## ++## file: drivers/mmc/Kconfig ++## ++# CONFIG_MMC is not set ++ ++## ++## file: drivers/mtd/Kconfig ++## ++# CONFIG_MTD is not set ++ ++## ++## file: drivers/net/Kconfig ++## ++CONFIG_NETDEVICES=y ++# CONFIG_BONDING is not set ++# CONFIG_NETPOLL_TRAP is not set ++# CONFIG_TUN is not set ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++# CONFIG_WAN is not set ++ ++## ++## file: drivers/net/wireless/ipw2x00/Kconfig ++## ++# CONFIG_IPW2100 is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_ISCSI_TCP is not set ++ ++## ++## file: drivers/staging/Kconfig ++## ++# CONFIG_STAGING is not set ++ ++## ++## file: drivers/telephony/Kconfig ++## ++# CONFIG_PHONE is not set ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++ ++## ++## file: drivers/w1/Kconfig ++## ++# CONFIG_W1 is not set ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++# CONFIG_WATCHDOG is not set ++ ++## ++## file: fs/adfs/Kconfig ++## ++# CONFIG_ADFS_FS is not set ++ ++## ++## file: fs/afs/Kconfig ++## ++# CONFIG_AFS_FS is not set ++ ++## ++## file: fs/befs/Kconfig ++## ++# CONFIG_BEFS_FS is not set ++ ++## ++## file: fs/bfs/Kconfig ++## ++# CONFIG_BFS_FS is not set ++ ++## ++## file: fs/Kconfig.binfmt ++## ++CONFIG_BINFMT_ELF=y ++CONFIG_BINFMT_AOUT=m ++CONFIG_BINFMT_MISC=m ++ ++## ++## file: fs/cifs/Kconfig ++## ++# CONFIG_CIFS is not set ++ ++## ++## file: fs/efs/Kconfig ++## ++# CONFIG_EFS_FS is not set ++ ++## ++## file: fs/ext2/Kconfig ++## ++# CONFIG_EXT2_FS is not set ++ ++## ++## file: fs/ext3/Kconfig ++## ++# CONFIG_EXT3_FS is not set ++ ++## ++## file: fs/ext4/Kconfig ++## ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++ ++## ++## file: fs/freevxfs/Kconfig ++## ++# CONFIG_VXFS_FS is not set ++ ++## ++## file: fs/jbd/Kconfig ++## ++# CONFIG_JBD_DEBUG is not set ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_MSDOS_PARTITION=y ++ ++## ++## file: fs/qnx4/Kconfig ++## ++# CONFIG_QNX4FS_FS is not set ++ ++## ++## file: fs/sysfs/Kconfig ++## ++CONFIG_SYSFS=y ++ ++## ++## file: init/Kconfig ++## ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++ ++## ++## file: lib/Kconfig.debug ++## ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_FRAME_POINTER is not set ++ ++## ++## file: net/atm/Kconfig ++## ++# CONFIG_ATM is not set ++ ++## ++## file: net/ax25/Kconfig ++## ++# CONFIG_HAMRADIO is not set ++ ++## ++## file: net/bluetooth/Kconfig ++## ++#. TODO ++# CONFIG_BT is not set ++ ++## ++## file: net/bridge/Kconfig ++## ++#. TODO ++# CONFIG_BRIDGE is not set ++ ++## ++## file: net/decnet/Kconfig ++## ++# CONFIG_DECNET is not set ++ ++## ++## file: net/ipv4/Kconfig ++## ++#. TODO ++# CONFIG_IP_ADVANCED_ROUTER is not set ++ ++## ++## file: net/irda/Kconfig ++## ++# CONFIG_IRDA is not set ++ ++## ++## file: net/lapb/Kconfig ++## ++# CONFIG_LAPB is not set ++ ++## ++## file: net/llc/Kconfig ++## ++# CONFIG_LLC2 is not set ++ ++## ++## file: net/sched/Kconfig ++## ++#. TODO ++# CONFIG_NET_SCHED is not set ++ ++## ++## file: net/xfrm/Kconfig ++## ++#. TODO ++CONFIG_NET_KEY=y ++ +diff --git a/debian/config/m68k/config.amiga b/debian/config/m68k/config.amiga +new file mode 100644 +index 0000000..38ead29 +--- /dev/null ++++ b/debian/config/m68k/config.amiga +@@ -0,0 +1,308 @@ ++## ++## file: arch/m68k/Kconfig.bus ++## ++CONFIG_ZORRO=y ++CONFIG_AMIGA_PCMCIA=y ++ ++## ++## file: arch/m68k/Kconfig.cpu ++## ++CONFIG_M68020=y ++CONFIG_M68030=y ++CONFIG_M68040=y ++CONFIG_M68060=y ++CONFIG_M68KFPU_EMU=y ++CONFIG_M68KFPU_EMU_EXTRAPREC=y ++# CONFIG_M68KFPU_EMU_ONLY is not set ++ ++## ++## file: arch/m68k/Kconfig.devices ++## ++# CONFIG_HEARTBEAT is not set ++CONFIG_AMIGA_BUILTIN_SERIAL=y ++CONFIG_MULTIFACE_III_TTY=m ++CONFIG_SERIAL_CONSOLE=y ++ ++## ++## file: arch/m68k/Kconfig.machine ++## ++CONFIG_AMIGA=y ++# CONFIG_ATARI is not set ++# CONFIG_MAC is not set ++# CONFIG_APOLLO is not set ++# CONFIG_VME is not set ++# CONFIG_HP300 is not set ++# CONFIG_SUN3X is not set ++# CONFIG_Q40 is not set ++# CONFIG_SUN3 is not set ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_AMIGA_FLOPPY=y ++CONFIG_AMIGA_Z2RAM=y ++# CONFIG_PARIDE is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++# CONFIG_PPDEV is not set ++CONFIG_GEN_RTC=m ++ ++## ++## file: drivers/firewire/Kconfig ++## ++# CONFIG_FIREWIRE is not set ++ ++## ++## file: drivers/ide/Kconfig ++## ++CONFIG_IDE=y ++# CONFIG_BLK_DEV_IDE_SATA is not set ++CONFIG_IDE_GD=y ++CONFIG_IDE_GD_ATA=y ++CONFIG_BLK_DEV_IDECD=y ++# CONFIG_BLK_DEV_IDETAPE is not set ++CONFIG_IDE_GENERIC=y ++CONFIG_BLK_DEV_GAYLE=y ++CONFIG_BLK_DEV_BUDDHA=y ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++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_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_DB9 is not set ++# CONFIG_JOYSTICK_GAMECON is not set ++# CONFIG_JOYSTICK_TURBOGRAFX is not set ++CONFIG_JOYSTICK_AMIGA=m ++# CONFIG_JOYSTICK_JOYDUMP is not set ++ ++## ++## file: drivers/input/joystick/iforce/Kconfig ++## ++# CONFIG_JOYSTICK_IFORCE is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_KEYBOARD_AMIGA=y ++# CONFIG_KEYBOARD_ATKBD is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++# CONFIG_INPUT_MISC is not set ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++# CONFIG_MOUSE_PS2 is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_INPORT is not set ++# CONFIG_MOUSE_LOGIBM is not set ++# CONFIG_MOUSE_PC110PAD is not set ++CONFIG_MOUSE_AMIGA=y ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=m ++CONFIG_SERIO_SERPORT=m ++# CONFIG_SERIO_PARKBD is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++# CONFIG_NET_VENDOR_3COM is not set ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_HYDRA=m ++CONFIG_APNE=m ++CONFIG_ZORRO8390=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_A2065=m ++CONFIG_ARIADNE=m ++# CONFIG_DEPCA is not set ++ ++## ++## file: drivers/net/ethernet/fujitsu/Kconfig ++## ++# CONFIG_AT1700 is not set ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++# CONFIG_HP100 is not set ++ ++## ++## file: drivers/net/ethernet/racal/Kconfig ++## ++# CONFIG_NET_VENDOR_RACAL is not set ++ ++## ++## file: drivers/net/plip/Kconfig ++## ++CONFIG_PLIP=m ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++# CONFIG_TR is not set ++ ++## ++## file: drivers/parport/Kconfig ++## ++CONFIG_PARPORT_AMIGA=m ++CONFIG_PARPORT_MFC3=m ++ ++## ++## file: drivers/pnp/Kconfig ++## ++# CONFIG_PNP is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI_SPI_ATTRS=y ++# CONFIG_SCSI_AIC7XXX_OLD is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_IN2000 is not set ++# CONFIG_SCSI_DTC3280 is not set ++# CONFIG_SCSI_EATA_PIO is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_GENERIC_NCR5380 is not set ++# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set ++# CONFIG_SCSI_PPA is not set ++# CONFIG_SCSI_IMM is not set ++# CONFIG_SCSI_NCR53C406A is not set ++# CONFIG_SCSI_PAS16 is not set ++# CONFIG_SCSI_QLOGIC_FAS is not set ++# CONFIG_SCSI_SYM53C416 is not set ++# CONFIG_SCSI_T128 is not set ++CONFIG_A3000_SCSI=y ++CONFIG_A2091_SCSI=y ++CONFIG_GVP11_SCSI=y ++CONFIG_SCSI_A4000T=y ++CONFIG_SCSI_ZORRO7XX=y ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++# CONFIG_SERIAL_8250 is not set ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++CONFIG_FB_CIRRUS=y ++# CONFIG_FB_PM2 is not set ++CONFIG_FB_AMIGA=y ++CONFIG_FB_AMIGA_OCS=y ++CONFIG_FB_AMIGA_ECS=y ++CONFIG_FB_AMIGA_AGA=y ++CONFIG_FB_FM2=y ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_VIRTUAL is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++CONFIG_FONT_PEARL_8x8=y ++ ++## ++## file: drivers/zorro/Kconfig ++## ++CONFIG_ZORRO_NAMES=y ++ ++## ++## file: fs/affs/Kconfig ++## ++CONFIG_AFFS_FS=y ++ ++## ++## file: fs/partitions/Kconfig ++## ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_AMIGA_PARTITION=y ++ ++## ++## file: fs/ufs/Kconfig ++## ++# CONFIG_UFS_FS_WRITE is not set ++ ++## ++## file: init/Kconfig ++## ++#. TODO ++# CONFIG_AUDIT is not set ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++# CONFIG_IPX_INTERN is not set ++ ++## ++## file: sound/Kconfig ++## ++# CONFIG_SND is not set ++ ++## ++## file: sound/oss/dmasound/Kconfig ++## ++CONFIG_DMASOUND_PAULA=m ++ ++## ++## file: unknown ++## ++CONFIG_BLK_DEV_IDEDOUBLER=y ++CONFIG_BLZ1230_SCSI=y ++CONFIG_BLZ2060_SCSI=y ++CONFIG_CYBERSTORMII_SCSI=y ++CONFIG_CYBERSTORM_SCSI=y ++CONFIG_FASTLANE_SCSI=y ++# CONFIG_FB_CYBER is not set ++# CONFIG_FB_RETINAZ3 is not set ++# CONFIG_FB_VIRGE is not set ++# CONFIG_NET_VENDOR_SMC is not set ++# CONFIG_OKTAGON_SCSI is not set ++CONFIG_SCSI_AMIGA7XX=y ++# CONFIG_SCSI_NCR53C7xx_FAST is not set ++# CONFIG_WHIPPET_SERIAL is not set ++ +diff --git a/debian/config/m68k/config.atari b/debian/config/m68k/config.atari +new file mode 100644 +index 0000000..4d8d785 +--- /dev/null ++++ b/debian/config/m68k/config.atari +@@ -0,0 +1,205 @@ ++## ++## file: arch/m68k/Kconfig.cpu ++## ++CONFIG_M68020=y ++CONFIG_M68030=y ++CONFIG_M68040=y ++CONFIG_M68060=y ++CONFIG_M68KFPU_EMU=y ++CONFIG_M68KFPU_EMU_EXTRAPREC=y ++# CONFIG_M68KFPU_EMU_ONLY is not set ++ ++## ++## file: arch/m68k/Kconfig.devices ++## ++CONFIG_HEARTBEAT=y ++CONFIG_NATFEAT=y ++CONFIG_NFBLOCK=y ++CONFIG_NFCON=y ++CONFIG_NFETH=y ++CONFIG_ATARI_MFPSER=m ++CONFIG_ATARI_MIDI=m ++CONFIG_ATARI_DSP56K=m ++CONFIG_SERIAL_CONSOLE=y ++ ++## ++## file: arch/m68k/Kconfig.machine ++## ++# CONFIG_AMIGA is not set ++CONFIG_ATARI=y ++# CONFIG_MAC is not set ++# CONFIG_APOLLO is not set ++# CONFIG_VME is not set ++# CONFIG_HP300 is not set ++# CONFIG_SUN3X is not set ++# CONFIG_Q40 is not set ++# CONFIG_SUN3 is not set ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_ATARI_FLOPPY=y ++# CONFIG_PARIDE is not set ++# CONFIG_BLK_DEV_HD is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++# CONFIG_PPDEV is not set ++CONFIG_NVRAM=y ++CONFIG_RTC=y ++CONFIG_GEN_RTC=y ++ ++## ++## file: drivers/ide/Kconfig ++## ++CONFIG_IDE=y ++# CONFIG_BLK_DEV_IDE_SATA is not set ++CONFIG_IDE_GD=y ++CONFIG_IDE_GD_ATA=y ++CONFIG_BLK_DEV_IDECD=y ++# CONFIG_BLK_DEV_IDETAPE is not set ++CONFIG_IDE_GENERIC=y ++CONFIG_BLK_DEV_FALCON_IDE=y ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++# CONFIG_INPUT_JOYSTICK is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_KEYBOARD_ATARI=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_SUNKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_M68K_BEEP=m ++CONFIG_INPUT_UINPUT=m ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_MOUSE_PS2=y ++# CONFIG_MOUSE_SERIAL is not set ++CONFIG_MOUSE_ATARI=y ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_PARKBD is not set ++CONFIG_SERIO_LIBPS2=y ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_ATARILANCE=y ++ ++## ++## file: drivers/net/plip/Kconfig ++## ++# CONFIG_PLIP is not set ++ ++## ++## file: drivers/net/ppp/Kconfig ++## ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++ ++## ++## file: drivers/parport/Kconfig ++## ++# CONFIG_PARPORT is not set ++CONFIG_PARPORT_ATARI=m ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_GENERIC=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++# CONFIG_SCSI_PPA is not set ++# CONFIG_SCSI_IMM is not set ++CONFIG_ATARI_SCSI=y ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++# CONFIG_SERIAL_8250 is not set ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++CONFIG_FB_ATARI=y ++# CONFIG_FB_S1D13XXX is not set ++CONFIG_FB_ATY=y ++# CONFIG_FB_VIRTUAL is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: fs/nfs/Kconfig ++## ++# CONFIG_NFS_V4 is not set ++ ++## ++## file: fs/nfsd/Kconfig ++## ++# CONFIG_NFSD_V4 is not set ++ ++## ++## file: fs/partitions/Kconfig ++## ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_ATARI_PARTITION=y ++ ++## ++## file: fs/ufs/Kconfig ++## ++# CONFIG_UFS_FS_WRITE is not set ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++# CONFIG_IPX_INTERN is not set ++ ++## ++## file: sound/Kconfig ++## ++# CONFIG_SND is not set ++ ++## ++## file: sound/oss/dmasound/Kconfig ++## ++CONFIG_DMASOUND_ATARI=m ++ ++## ++## file: unknown ++## ++CONFIG_ATARI_ETHERNEC=m ++CONFIG_ATARI_ROM_ISA=y ++CONFIG_ATARI_SCC=y ++CONFIG_ATARI_SCC_DMA=y ++CONFIG_STRAM_PROC=y ++ +diff --git a/debian/config/m68k/config.bvme6000 b/debian/config/m68k/config.bvme6000 +new file mode 100644 +index 0000000..b6fe534 +--- /dev/null ++++ b/debian/config/m68k/config.bvme6000 +@@ -0,0 +1,131 @@ ++## ++## file: arch/m68k/Kconfig.cpu ++## ++# CONFIG_M68020 is not set ++# CONFIG_M68030 is not set ++CONFIG_M68040=y ++CONFIG_M68060=y ++# CONFIG_M68KFPU_EMU is not set ++ ++## ++## file: arch/m68k/Kconfig.devices ++## ++CONFIG_SERIAL_CONSOLE=y ++ ++## ++## file: arch/m68k/Kconfig.machine ++## ++# CONFIG_AMIGA is not set ++# CONFIG_ATARI is not set ++# CONFIG_MAC is not set ++# CONFIG_APOLLO is not set ++CONFIG_VME=y ++# CONFIG_MVME147 is not set ++# CONFIG_MVME16x is not set ++CONFIG_BVME6000=y ++# CONFIG_HP300 is not set ++# CONFIG_SUN3X is not set ++# CONFIG_Q40 is not set ++# CONFIG_SUN3 is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_GEN_RTC=m ++ ++## ++## file: drivers/firewire/Kconfig ++## ++# CONFIG_FIREWIRE is not set ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++# CONFIG_INPUT_JOYSTICK is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++# CONFIG_KEYBOARD_ATKBD is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++# CONFIG_INPUT_MISC is not set ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_MOUSE_PS2=m ++CONFIG_MOUSE_SERIAL=m ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=m ++CONFIG_SERIO_SERPORT=m ++CONFIG_SERIO_LIBPS2=m ++ ++## ++## file: drivers/net/ethernet/i825xx/Kconfig ++## ++CONFIG_BVME6000_NET=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_BVME6000_SCSI=y ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=m ++CONFIG_SERIAL_8250_NR_UARTS=4 ++# CONFIG_SERIAL_8250_EXTENDED is not set ++ ++## ++## file: drivers/video/Kconfig ++## ++# CONFIG_FB is not set ++ ++## ++## file: fs/nfs/Kconfig ++## ++CONFIG_NFS_FS=y ++CONFIG_ROOT_NFS=y ++ ++## ++## file: fs/partitions/Kconfig ++## ++# CONFIG_PARTITION_ADVANCED is not set ++ ++## ++## file: lib/Kconfig ++## ++#. TODO ++CONFIG_CRC32=m ++ ++## ++## file: net/ipv4/Kconfig ++## ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++CONFIG_IP_PNP_RARP=y ++ ++## ++## file: net/ipx/Kconfig ++## ++# CONFIG_IPX is not set ++ ++## ++## file: sound/Kconfig ++## ++# CONFIG_SOUND is not set ++ ++## ++## file: unknown ++## ++CONFIG_BVME6000_SCC=y ++ +diff --git a/debian/config/m68k/config.mac b/debian/config/m68k/config.mac +new file mode 100644 +index 0000000..9add505 +--- /dev/null ++++ b/debian/config/m68k/config.mac +@@ -0,0 +1,211 @@ ++## ++## file: arch/m68k/Kconfig.cpu ++## ++CONFIG_M68020=y ++CONFIG_M68030=y ++CONFIG_M68040=y ++# CONFIG_M68060 is not set ++CONFIG_M68KFPU_EMU=y ++CONFIG_M68KFPU_EMU_EXTRAPREC=y ++# CONFIG_M68KFPU_EMU_ONLY is not set ++ ++## ++## file: arch/m68k/Kconfig.devices ++## ++# CONFIG_HEARTBEAT is not set ++CONFIG_SERIAL_CONSOLE=y ++ ++## ++## file: arch/m68k/Kconfig.machine ++## ++# CONFIG_AMIGA is not set ++# CONFIG_ATARI is not set ++CONFIG_MAC=y ++# CONFIG_APOLLO is not set ++# CONFIG_VME is not set ++# CONFIG_HP300 is not set ++# CONFIG_SUN3X is not set ++# CONFIG_Q40 is not set ++# CONFIG_SUN3 is not set ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_DEV_SWIM=m ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_GEN_RTC=m ++ ++## ++## file: drivers/ide/Kconfig ++## ++CONFIG_IDE=y ++# CONFIG_BLK_DEV_IDE_SATA is not set ++CONFIG_IDE_GD=y ++CONFIG_IDE_GD_ATA=y ++CONFIG_BLK_DEV_IDECD=y ++# CONFIG_BLK_DEV_IDETAPE is not set ++CONFIG_IDE_GENERIC=y ++CONFIG_BLK_DEV_MAC_IDE=y ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++# CONFIG_INPUT_JOYSTICK is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++# CONFIG_KEYBOARD_ATKBD is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_UINPUT=m ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_MOUSE_PS2=m ++CONFIG_MOUSE_SERIAL=m ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=m ++CONFIG_SERIO_SERPORT=m ++CONFIG_SERIO_LIBPS2=m ++ ++## ++## file: drivers/macintosh/Kconfig ++## ++CONFIG_ADB=y ++CONFIG_ADB_MACII=y ++# CONFIG_ADB_MACIISI is not set ++CONFIG_ADB_IOP=y # switched on for the benefit of IIfx, Q900, Q950 ++CONFIG_ADB_PMU68K=y ++CONFIG_ADB_CUDA=y ++CONFIG_INPUT_ADBHID=y ++CONFIG_MAC_EMUMOUSEBTN=y ++# CONFIG_WINDFARM is not set ++ ++## ++## file: drivers/net/appletalk/Kconfig ++## ++CONFIG_IPDDP=m ++CONFIG_IPDDP_ENCAP=y ++CONFIG_IPDDP_DECAP=y ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_MAC8390=y ++ ++## ++## file: drivers/net/ethernet/apple/Kconfig ++## ++CONFIG_MACMACE=y ++ ++## ++## file: drivers/net/ethernet/cirrus/Kconfig ++## ++CONFIG_MAC89x0=y ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_MACSONIC=y # switched back on as requested by Finn Thain ++ ++## ++## file: drivers/parport/Kconfig ++## ++# CONFIG_PARPORT is not set ++# CONFIG_PARPORT_PC is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_MAC_SCSI=y ++CONFIG_SCSI_MAC_ESP=y ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++# CONFIG_SERIAL_8250 is not set ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++CONFIG_FB_VALKYRIE=y ++CONFIG_FB_MAC=y ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_VIRTUAL is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++CONFIG_FONT_6x11=y ++ ++## ++## file: fs/hfs/Kconfig ++## ++CONFIG_HFS_FS=y ++ ++## ++## file: fs/hfsplus/Kconfig ++## ++CONFIG_HFSPLUS_FS=y ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_AMIGA_PARTITION=y ++CONFIG_ATARI_PARTITION=y ++CONFIG_MAC_PARTITION=y ++CONFIG_BSD_DISKLABEL=y ++CONFIG_MINIX_SUBPARTITION=y ++CONFIG_SOLARIS_X86_PARTITION=y ++CONFIG_UNIXWARE_DISKLABEL=y ++CONFIG_LDM_PARTITION=y ++CONFIG_LDM_DEBUG=y ++CONFIG_SUN_PARTITION=y ++ ++## ++## file: fs/ufs/Kconfig ++## ++# CONFIG_UFS_FS_WRITE is not set ++ ++## ++## file: init/Kconfig ++## ++#. TODO ++# CONFIG_AUDIT is not set ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++# CONFIG_IPX_INTERN is not set ++ ++## ++## file: sound/Kconfig ++## ++# CONFIG_SOUND is not set ++ ++## ++## file: unknown ++## ++CONFIG_MAC_SCC=y ++# CONFIG_NET_VENDOR_SMC is not set ++ +diff --git a/debian/config/m68k/config.mvme147 b/debian/config/m68k/config.mvme147 +new file mode 100644 +index 0000000..1fd28f5 +--- /dev/null ++++ b/debian/config/m68k/config.mvme147 +@@ -0,0 +1,131 @@ ++## ++## file: arch/m68k/Kconfig.cpu ++## ++# CONFIG_M68020 is not set ++CONFIG_M68030=y ++# CONFIG_M68040 is not set ++# CONFIG_M68060 is not set ++# CONFIG_M68KFPU_EMU is not set ++ ++## ++## file: arch/m68k/Kconfig.devices ++## ++CONFIG_SERIAL_CONSOLE=y ++ ++## ++## file: arch/m68k/Kconfig.machine ++## ++# CONFIG_AMIGA is not set ++# CONFIG_ATARI is not set ++# CONFIG_MAC is not set ++# CONFIG_APOLLO is not set ++CONFIG_VME=y ++CONFIG_MVME147=y ++# CONFIG_MVME16x is not set ++# CONFIG_BVME6000 is not set ++# CONFIG_HP300 is not set ++# CONFIG_SUN3X is not set ++# CONFIG_Q40 is not set ++# CONFIG_SUN3 is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_GEN_RTC=m ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++# CONFIG_INPUT_JOYSTICK is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++# CONFIG_KEYBOARD_ATKBD is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++# CONFIG_INPUT_MISC is not set ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_MOUSE_PS2=m ++CONFIG_MOUSE_SERIAL=m ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=m ++CONFIG_SERIO_SERPORT=m ++CONFIG_SERIO_LIBPS2=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_MVME147_NET=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_MVME147_SCSI=y ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++# CONFIG_SERIAL_8250 is not set ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_VIRTUAL is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: fs/nfs/Kconfig ++## ++CONFIG_NFS_FS=y ++CONFIG_ROOT_NFS=y ++ ++## ++## file: fs/partitions/Kconfig ++## ++# CONFIG_PARTITION_ADVANCED is not set ++ ++## ++## file: net/ipv4/Kconfig ++## ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++CONFIG_IP_PNP_RARP=y ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++# CONFIG_IPX_INTERN is not set ++ ++## ++## file: sound/Kconfig ++## ++# CONFIG_SOUND is not set ++ ++## ++## file: unknown ++## ++CONFIG_MVME147_SCC=y ++ +diff --git a/debian/config/m68k/config.mvme16x b/debian/config/m68k/config.mvme16x +new file mode 100644 +index 0000000..6ab42f6 +--- /dev/null ++++ b/debian/config/m68k/config.mvme16x +@@ -0,0 +1,136 @@ ++## ++## file: arch/m68k/Kconfig.cpu ++## ++# CONFIG_M68020 is not set ++# CONFIG_M68030 is not set ++CONFIG_M68040=y ++CONFIG_M68060=y ++# CONFIG_M68KFPU_EMU is not set ++ ++## ++## file: arch/m68k/Kconfig.devices ++## ++CONFIG_SERIAL_CONSOLE=y ++ ++## ++## file: arch/m68k/Kconfig.machine ++## ++# CONFIG_AMIGA is not set ++# CONFIG_ATARI is not set ++# CONFIG_MAC is not set ++# CONFIG_APOLLO is not set ++CONFIG_VME=y ++# CONFIG_MVME147 is not set ++CONFIG_MVME16x=y ++# CONFIG_BVME6000 is not set ++# CONFIG_HP300 is not set ++# CONFIG_SUN3X is not set ++# CONFIG_Q40 is not set ++# CONFIG_SUN3 is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_GEN_RTC=m ++ ++## ++## file: drivers/firewire/Kconfig ++## ++# CONFIG_FIREWIRE is not set ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++# CONFIG_INPUT_JOYSTICK is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++# CONFIG_KEYBOARD_ATKBD is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++# CONFIG_INPUT_MISC is not set ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_MOUSE_PS2=m ++CONFIG_MOUSE_SERIAL=m ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=m ++CONFIG_SERIO_SERPORT=m ++CONFIG_SERIO_LIBPS2=m ++ ++## ++## file: drivers/net/ethernet/i825xx/Kconfig ++## ++CONFIG_MVME16x_NET=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_MVME16x_SCSI=y ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++# CONFIG_SERIAL_8250 is not set ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_VIRTUAL is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: fs/nfs/Kconfig ++## ++CONFIG_NFS_FS=y ++CONFIG_ROOT_NFS=y ++ ++## ++## file: fs/partitions/Kconfig ++## ++# CONFIG_PARTITION_ADVANCED is not set ++ ++## ++## file: net/ipv4/Kconfig ++## ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++CONFIG_IP_PNP_RARP=y ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++# CONFIG_IPX_INTERN is not set ++ ++## ++## file: sound/Kconfig ++## ++# CONFIG_SOUND is not set ++ ++## ++## file: unknown ++## ++CONFIG_MVME162_SCC=y ++ +diff --git a/debian/config/m68k/defines b/debian/config/m68k/defines +new file mode 100644 +index 0000000..a51392b +--- /dev/null ++++ b/debian/config/m68k/defines +@@ -0,0 +1,34 @@ ++[base] ++compiler: gcc-4.6 ++cflags: -ffreestanding ++flavours: ++ amiga ++ atari ++ bvme6000 ++ mac ++ mvme147 ++ mvme16x ++kernel-arch: m68k ++ ++[image] ++initramfs: false ++suggests: vmelilo, fdutils ++ ++[amiga_description] ++hardware: Amiga ++ ++[atari_description] ++hardware: Atari ++ ++[bvme6000_description] ++hardware: BVM BVME4000 and BVME6000 ++ ++[mac_description] ++hardware: Macintosh ++ ++[mvme147_description] ++hardware: Motorola MVME147 ++ ++[mvme16x_description] ++hardware: Motorola MVME162/6/7, MVME172/7 ++ +diff --git a/debian/config/mips/config b/debian/config/mips/config +new file mode 100644 +index 0000000..a3dd4c0 +--- /dev/null ++++ b/debian/config/mips/config +@@ -0,0 +1,8 @@ ++## ++## file: arch/mips/Kconfig ++## ++## choice: Endianess selection ++CONFIG_CPU_BIG_ENDIAN=y ++# CONFIG_CPU_LITTLE_ENDIAN is not set ++## end choice ++# CONFIG_RAPIDIO is not set +diff --git a/debian/config/mips/config.4kc-malta b/debian/config/mips/config.4kc-malta +new file mode 100644 +index 0000000..ee9b2e7 +--- /dev/null ++++ b/debian/config/mips/config.4kc-malta +@@ -0,0 +1,1234 @@ ++## ++## file: arch/Kconfig ++## ++CONFIG_OPROFILE=m ++ ++## ++## file: arch/mips/Kconfig ++## ++## choice: System type ++# CONFIG_MIPS_COBALT is not set ++# CONFIG_MACH_DECSTATION is not set ++# CONFIG_MACH_JAZZ is not set ++# CONFIG_LASAT is not set ++CONFIG_MIPS_MALTA=y ++# CONFIG_MIPS_SIM is not set ++# CONFIG_MACH_VR41XX is not set ++# CONFIG_PNX8550_JBS is not set ++# CONFIG_PNX8550_STB810 is not set ++# CONFIG_PMC_YOSEMITE is not set ++# CONFIG_SGI_IP22 is not set ++# CONFIG_SGI_IP27 is not set ++# CONFIG_SGI_IP32 is not set ++# CONFIG_SIBYTE_CRHINE is not set ++# CONFIG_SIBYTE_CARMEL is not set ++# CONFIG_SIBYTE_CRHONE is not set ++# CONFIG_SIBYTE_RHONE is not set ++# CONFIG_SIBYTE_SWARM is not set ++# CONFIG_SIBYTE_LITTLESUR is not set ++# CONFIG_SIBYTE_SENTOSA is not set ++# CONFIG_SIBYTE_BIGSUR is not set ++# CONFIG_SNI_RM is not set ++# CONFIG_WR_PPMC is not set ++## end choice ++## choice: CPU type ++CONFIG_CPU_MIPS32_R1=y ++# CONFIG_CPU_MIPS32_R2 is not set ++# CONFIG_CPU_MIPS64_R1 is not set ++# CONFIG_CPU_MIPS64_R2 is not set ++# CONFIG_CPU_R3000 is not set ++# CONFIG_CPU_TX39XX is not set ++# CONFIG_CPU_VR41XX is not set ++# CONFIG_CPU_R4300 is not set ++# CONFIG_CPU_R4X00 is not set ++# CONFIG_CPU_TX49XX is not set ++# CONFIG_CPU_R5000 is not set ++# CONFIG_CPU_R5432 is not set ++# CONFIG_CPU_R6000 is not set ++# CONFIG_CPU_NEVADA is not set ++# CONFIG_CPU_R8000 is not set ++# CONFIG_CPU_R10000 is not set ++# CONFIG_CPU_RM7000 is not set ++# CONFIG_CPU_RM9000 is not set ++# CONFIG_CPU_SB1 is not set ++## end choice ++## choice: Kernel code model ++CONFIG_32BIT=y ++# CONFIG_64BIT is not set ++## end choice ++## choice: Kernel page size ++CONFIG_PAGE_SIZE_4KB=y ++# CONFIG_PAGE_SIZE_8KB is not set ++# CONFIG_PAGE_SIZE_16KB is not set ++# CONFIG_PAGE_SIZE_64KB is not set ++## end choice ++## choice: MIPS MT options ++CONFIG_MIPS_MT_DISABLED=y ++# CONFIG_MIPS_MT_SMP is not set ++# CONFIG_MIPS_MT_SMTC is not set ++## end choice ++# CONFIG_MIPS_VPE_LOADER is not set ++# CONFIG_CPU_HAS_SMARTMIPS is not set ++## choice: Timer frequency ++# CONFIG_HZ_48 is not set ++# CONFIG_HZ_100 is not set ++# CONFIG_HZ_128 is not set ++CONFIG_HZ_250=y ++# CONFIG_HZ_256 is not set ++# CONFIG_HZ_1000 is not set ++# CONFIG_HZ_1024 is not set ++## end choice ++# CONFIG_KEXEC is not set ++CONFIG_PCI=y ++ ++## ++## file: arch/mips/Kconfig.debug ++## ++CONFIG_CMDLINE="" ++ ++## ++## file: arch/mips/txx9/Kconfig ++## ++# CONFIG_TOSHIBA_JMR3927 is not set ++# CONFIG_TOSHIBA_RBTX4927 is not set ++# CONFIG_TOSHIBA_RBTX4938 is not set ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=y ++CONFIG_SATA_AHCI=y ++CONFIG_SATA_SIL24=y ++# CONFIG_PDC_ADMA is not set ++# CONFIG_SATA_QSTOR is not set ++CONFIG_SATA_SX4=y ++CONFIG_ATA_PIIX=y ++CONFIG_SATA_MV=y ++# CONFIG_SATA_NV is not set ++CONFIG_SATA_PROMISE=y ++CONFIG_SATA_SIL=y ++# CONFIG_SATA_SIS is not set ++# CONFIG_SATA_SVW is not set ++# CONFIG_SATA_ULI is not set ++# CONFIG_SATA_VIA is not set ++# CONFIG_SATA_VITESSE is not set ++CONFIG_PATA_CMD64X=y ++CONFIG_PATA_HPT366=y ++CONFIG_PATA_NETCELL=y ++CONFIG_PATA_OLDPIIX=y ++CONFIG_PATA_PDC2027X=y ++CONFIG_PATA_PDC_OLD=y ++CONFIG_PATA_SIL680=y ++CONFIG_PATA_MPIIX=y ++CONFIG_PATA_NS87410=y ++CONFIG_PATA_PLATFORM=y ++CONFIG_ATA_GENERIC=y ++ ++## ++## file: drivers/atm/Kconfig ++## ++# CONFIG_ATM_DRIVERS is not set ++ ++## ++## file: drivers/auxdisplay/Kconfig ++## ++# CONFIG_KS0108 is not set ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_DEV_FD=m ++CONFIG_PARIDE=m ++# CONFIG_BLK_CPQ_DA is not set ++CONFIG_BLK_CPQ_CISS_DA=m ++CONFIG_CISS_SCSI_TAPE=y ++CONFIG_BLK_DEV_DAC960=m ++CONFIG_BLK_DEV_UMEM=m ++CONFIG_BLK_DEV_SX8=m ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_CDROM_PKTCDVD_BUFFERS=8 ++# CONFIG_CDROM_PKTCDVD_WCACHE is not set ++ ++## ++## file: drivers/block/paride/Kconfig ++## ++CONFIG_PARIDE_PD=m ++CONFIG_PARIDE_PCD=m ++CONFIG_PARIDE_PF=m ++CONFIG_PARIDE_PT=m ++CONFIG_PARIDE_PG=m ++CONFIG_PARIDE_ATEN=m ++CONFIG_PARIDE_BPCK=m ++CONFIG_PARIDE_COMM=m ++CONFIG_PARIDE_DSTR=m ++CONFIG_PARIDE_FIT2=m ++CONFIG_PARIDE_FIT3=m ++CONFIG_PARIDE_EPAT=m ++# CONFIG_PARIDE_EPATC8 is not set ++CONFIG_PARIDE_EPIA=m ++CONFIG_PARIDE_FRIQ=m ++CONFIG_PARIDE_FRPW=m ++CONFIG_PARIDE_KBIC=m ++CONFIG_PARIDE_KTTI=m ++CONFIG_PARIDE_ON20=m ++CONFIG_PARIDE_ON26=m ++ ++## ++## file: drivers/bluetooth/Kconfig ++## ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_H4=y ++CONFIG_BT_HCIUART_BCSP=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++CONFIG_PPDEV=m ++CONFIG_R3964=m ++CONFIG_APPLICOM=m ++ ++## ++## file: drivers/char/hw_random/Kconfig ++## ++CONFIG_HW_RANDOM=m ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++CONFIG_IPMI_HANDLER=m ++# CONFIG_IPMI_PANIC_EVENT is not set ++# CONFIG_IPMI_DEVICE_INTERFACE is not set ++CONFIG_IPMI_SI=m ++CONFIG_IPMI_WATCHDOG=m ++CONFIG_IPMI_POWEROFF=m ++ ++## ++## file: drivers/char/tpm/Kconfig ++## ++# CONFIG_TCG_TPM is not set ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++CONFIG_DRM=m ++CONFIG_DRM_TDFX=m ++CONFIG_DRM_R128=m ++CONFIG_DRM_RADEON=m ++CONFIG_DRM_MGA=m ++CONFIG_DRM_VIA=m ++CONFIG_DRM_SAVAGE=m ++ ++## ++## file: drivers/gpu/drm/nouveau/Kconfig ++## ++CONFIG_DRM_NOUVEAU=m ++# CONFIG_DRM_NOUVEAU_BACKLIGHT is not set ++# CONFIG_DRM_NOUVEAU_DEBUG is not set ++CONFIG_DRM_I2C_CH7006=m ++CONFIG_DRM_I2C_SIL164=m ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_HWMON=y ++# CONFIG_HWMON_DEBUG_CHIP is not set ++# CONFIG_SENSORS_ABITUGURU is not set ++CONFIG_SENSORS_AD7418=m ++CONFIG_SENSORS_ADM1021=m ++CONFIG_SENSORS_ADM1025=m ++CONFIG_SENSORS_ADM1026=m ++CONFIG_SENSORS_ADM1029=m ++CONFIG_SENSORS_ADM1031=m ++CONFIG_SENSORS_ADM9240=m ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++CONFIG_SENSORS_DS1621=m ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++CONFIG_SENSORS_LM63=m ++CONFIG_SENSORS_LM70=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_LM77=m ++CONFIG_SENSORS_LM78=m ++CONFIG_SENSORS_LM80=m ++CONFIG_SENSORS_LM83=m ++CONFIG_SENSORS_LM85=m ++CONFIG_SENSORS_LM87=m ++CONFIG_SENSORS_LM90=m ++CONFIG_SENSORS_LM92=m ++CONFIG_SENSORS_MAX1619=m ++CONFIG_SENSORS_MAX6650=m ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PC87427 is not set ++CONFIG_SENSORS_PCF8591=m ++# CONFIG_SENSORS_SIS5595 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47M192 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_VIA686A is not set ++# CONFIG_SENSORS_VT1211 is not set ++# CONFIG_SENSORS_VT8231 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83791D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83793 is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=m ++CONFIG_I2C_CHARDEV=m ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++# 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_PIIX4=m ++# 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 ++# CONFIG_I2C_OCORES is not set ++CONFIG_I2C_SIMTEC=m ++CONFIG_I2C_PARPORT=m ++CONFIG_I2C_PARPORT_LIGHT=m ++CONFIG_I2C_TINY_USB=m ++# CONFIG_I2C_STUB is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++CONFIG_GAMEPORT=m ++# CONFIG_GAMEPORT_NS558 is not set ++# CONFIG_GAMEPORT_L4 is not set ++CONFIG_GAMEPORT_EMU10K1=m ++CONFIG_GAMEPORT_FM801=m ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++CONFIG_INPUT_JOYSTICK=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++CONFIG_KEYBOARD_LKKBD=m ++CONFIG_KEYBOARD_NEWTON=m ++CONFIG_KEYBOARD_STOWAWAY=m ++CONFIG_KEYBOARD_SUNKBD=m ++CONFIG_KEYBOARD_XTKBD=m ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++# CONFIG_INPUT_MISC is not set ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=m ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_LIFEBOOK=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_SERIAL=m ++CONFIG_MOUSE_APPLETOUCH=m ++CONFIG_MOUSE_VSXXXAA=m ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++CONFIG_SERIO_I8042=y ++CONFIG_SERIO_SERPORT=m ++CONFIG_SERIO_PARKBD=m ++CONFIG_SERIO_PCIPS2=y ++CONFIG_SERIO_LIBPS2=y ++CONFIG_SERIO_RAW=m ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++CONFIG_INPUT_TOUCHSCREEN=y ++ ++## ++## file: drivers/isdn/Kconfig ++## ++CONFIG_ISDN=y ++CONFIG_ISDN_CAPI=m ++ ++## ++## file: drivers/isdn/capi/Kconfig ++## ++CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y ++CONFIG_ISDN_CAPI_MIDDLEWARE=y ++CONFIG_ISDN_CAPI_CAPI20=m ++CONFIG_ISDN_CAPI_CAPIDRV=m ++ ++## ++## file: drivers/isdn/gigaset/Kconfig ++## ++CONFIG_ISDN_DRV_GIGASET=m ++CONFIG_GIGASET_BASE=m ++CONFIG_GIGASET_M105=m ++CONFIG_GIGASET_M101=m ++# CONFIG_GIGASET_DEBUG is not set ++ ++## ++## file: drivers/isdn/hardware/avm/Kconfig ++## ++CONFIG_CAPI_AVM=y ++CONFIG_ISDN_DRV_AVMB1_B1PCI=m ++CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y ++CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m ++CONFIG_ISDN_DRV_AVMB1_T1PCI=m ++CONFIG_ISDN_DRV_AVMB1_C4=m ++ ++## ++## file: drivers/isdn/hardware/eicon/Kconfig ++## ++CONFIG_CAPI_EICON=y ++CONFIG_ISDN_DIVAS=m ++CONFIG_ISDN_DIVAS_BRIPCI=y ++CONFIG_ISDN_DIVAS_PRIPCI=y ++CONFIG_ISDN_DIVAS_DIVACAPI=m ++CONFIG_ISDN_DIVAS_USERIDI=m ++CONFIG_ISDN_DIVAS_MAINT=m ++ ++## ++## file: drivers/leds/Kconfig ++## ++# CONFIG_NEW_LEDS is not set ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++CONFIG_I2O=m ++CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y ++CONFIG_I2O_EXT_ADAPTEC=y ++CONFIG_I2O_CONFIG=m ++CONFIG_I2O_CONFIG_OLD_IOCTL=y ++CONFIG_I2O_BUS=m ++CONFIG_I2O_BLOCK=m ++CONFIG_I2O_SCSI=m ++CONFIG_I2O_PROC=m ++ ++## ++## file: drivers/mfd/Kconfig ++## ++CONFIG_MFD_SM501=m ++ ++## ++## file: drivers/misc/Kconfig ++## ++# CONFIG_PHANTOM is not set ++# CONFIG_SGI_IOC4 is not set ++CONFIG_TIFM_CORE=m ++CONFIG_TIFM_7XX1=m ++ ++## ++## file: drivers/mmc/Kconfig ++## ++CONFIG_MMC=m ++# CONFIG_MMC_DEBUG is not set ++ ++## ++## file: drivers/mmc/card/Kconfig ++## ++CONFIG_MMC_BLOCK=m ++ ++## ++## file: drivers/mmc/core/Kconfig ++## ++# CONFIG_MMC_UNSAFE_RESUME is not set ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=m ++CONFIG_MTD_REDBOOT_PARTS=y ++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 ++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set ++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set ++CONFIG_MTD_CHAR=m ++CONFIG_MTD_BLKDEVS=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_BLOCK_RO=m ++CONFIG_FTL=m ++CONFIG_NFTL=m ++CONFIG_NFTL_RW=y ++CONFIG_INFTL=m ++CONFIG_RFD_FTL=m ++CONFIG_SSFDC=m ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++CONFIG_MTD_CFI=m ++CONFIG_MTD_JEDECPROBE=m ++# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT=m ++CONFIG_MTD_CFI_AMDSTD=m ++CONFIG_MTD_CFI_STAA=m ++CONFIG_MTD_RAM=m ++CONFIG_MTD_ROM=m ++CONFIG_MTD_ABSENT=m ++ ++## ++## file: drivers/mtd/devices/Kconfig ++## ++CONFIG_MTD_PMC551=m ++# CONFIG_MTD_PMC551_BUGFIX is not set ++# CONFIG_MTD_PMC551_DEBUG is not set ++CONFIG_MTD_DATAFLASH=m ++CONFIG_MTD_M25P80=m ++CONFIG_MTD_SLRAM=m ++CONFIG_MTD_PHRAM=m ++CONFIG_MTD_MTDRAM=m ++CONFIG_MTDRAM_TOTAL_SIZE=4096 ++CONFIG_MTDRAM_ERASE_SIZE=128 ++CONFIG_MTD_BLOCK2MTD=m ++CONFIG_MTD_DOC2000=m ++CONFIG_MTD_DOC2001=m ++CONFIG_MTD_DOC2001PLUS=m ++# CONFIG_MTD_DOCPROBE_ADVANCED is not set ++CONFIG_MTD_DOCPROBE_ADDRESS=0 ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++CONFIG_MTD_PHYSMAP=m ++CONFIG_MTD_PHYSMAP_START=0x8000000 ++CONFIG_MTD_PHYSMAP_LEN=0x0 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=2 ++CONFIG_MTD_PCI=m ++CONFIG_MTD_PLATRAM=m ++ ++## ++## file: drivers/mtd/nand/Kconfig ++## ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=m ++# CONFIG_MTD_NAND_VERIFY_WRITE is not set ++# CONFIG_MTD_NAND_MUSEUM_IDS is not set ++CONFIG_MTD_NAND_DISKONCHIP=m ++# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set ++CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 ++# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set ++CONFIG_MTD_NAND_CAFE=m ++# CONFIG_MTD_NAND_PLATFORM is not set ++ ++## ++## file: drivers/mtd/onenand/Kconfig ++## ++CONFIG_MTD_ONENAND=m ++CONFIG_MTD_ONENAND_VERIFY_WRITE=y ++# CONFIG_MTD_ONENAND_OTP is not set ++ ++## ++## file: drivers/mtd/ubi/Kconfig ++## ++CONFIG_MTD_UBI=m ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_RESERVE=1 ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_DEBUG is not set ++ ++## ++## file: drivers/net/Kconfig ++## ++CONFIG_NET_FC=y ++# CONFIG_NETPOLL_TRAP is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++CONFIG_ARCNET=m ++CONFIG_ARCNET_1201=m ++CONFIG_ARCNET_1051=m ++CONFIG_ARCNET_RAW=m ++CONFIG_ARCNET_CAP=m ++CONFIG_ARCNET_COM90xx=m ++CONFIG_ARCNET_COM90xxIO=m ++CONFIG_ARCNET_RIM_I=m ++CONFIG_ARCNET_COM20020=m ++CONFIG_ARCNET_COM20020_PCI=m ++ ++## ++## file: drivers/net/ethernet/Kconfig ++## ++CONFIG_FEALNX=m ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++CONFIG_NET_VENDOR_3COM=y ++CONFIG_VORTEX=m ++CONFIG_TYPHOON=m ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_NE2K_PCI=m ++ ++## ++## file: drivers/net/ethernet/adaptec/Kconfig ++## ++CONFIG_ADAPTEC_STARFIRE=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_AMD8111_ETH=m ++CONFIG_PCNET32=y ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++CONFIG_B44=m ++ ++## ++## file: drivers/net/ethernet/davicom/Kconfig ++## ++# CONFIG_DM9000 is not set ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++CONFIG_NET_TULIP=y ++CONFIG_DE2104X=m ++CONFIG_TULIP=m ++# CONFIG_TULIP_MWI is not set ++# CONFIG_TULIP_MMIO is not set ++# CONFIG_TULIP_NAPI is not set ++# CONFIG_WINBOND_840 is not set ++CONFIG_DM9102=m ++# CONFIG_ULI526X is not set ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++CONFIG_DE600=m ++CONFIG_DE620=m ++CONFIG_SUNDANCE=m ++# CONFIG_SUNDANCE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++# CONFIG_HP100 is not set ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++CONFIG_E100=m ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_NATSEMI=m ++ ++## ++## file: drivers/net/ethernet/nvidia/Kconfig ++## ++# CONFIG_FORCEDETH is not set ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_8139CP=m ++CONFIG_8139TOO=m ++# CONFIG_8139TOO_PIO is not set ++CONFIG_8139TOO_TUNE_TWISTER=y ++CONFIG_8139TOO_8129=y ++# CONFIG_8139_OLD_RX_RESET is not set ++ ++## ++## file: drivers/net/ethernet/silan/Kconfig ++## ++CONFIG_SC92031=m ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++CONFIG_SIS900=m ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_EPIC100=m ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++ ++## ++## file: drivers/net/ethernet/toshiba/Kconfig ++## ++# CONFIG_TC35815 is not set ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++CONFIG_VIA_RHINE=m ++# CONFIG_VIA_RHINE_MMIO is not set ++ ++## ++## file: drivers/net/fddi/Kconfig ++## ++CONFIG_FDDI=y ++CONFIG_SKFP=m ++ ++## ++## file: drivers/net/hippi/Kconfig ++## ++CONFIG_HIPPI=y ++CONFIG_ROADRUNNER=m ++# CONFIG_ROADRUNNER_LARGE_RINGS is not set ++ ++## ++## file: drivers/net/irda/Kconfig ++## ++CONFIG_IRTTY_SIR=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_VLSI_FIR=m ++CONFIG_MCS_FIR=m ++ ++## ++## file: drivers/net/phy/Kconfig ++## ++CONFIG_PHYLIB=m ++CONFIG_MARVELL_PHY=m ++CONFIG_DAVICOM_PHY=m ++# CONFIG_QSEMI_PHY is not set ++CONFIG_LXT_PHY=m ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++CONFIG_SMSC_PHY=m ++CONFIG_BROADCOM_PHY=m ++ ++## ++## file: drivers/net/plip/Kconfig ++## ++CONFIG_PLIP=m ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++# CONFIG_TR is not set ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++# CONFIG_WAN is not set ++ ++## ++## file: drivers/net/wireless/Kconfig ++## ++CONFIG_ATMEL=m ++CONFIG_PCI_ATMEL=m ++CONFIG_USB_ZD1201=m ++ ++## ++## file: drivers/net/wireless/ipw2x00/Kconfig ++## ++CONFIG_IPW2100=m ++CONFIG_IPW2100_MONITOR=y ++# CONFIG_IPW2100_DEBUG is not set ++CONFIG_IPW2200=m ++# CONFIG_IPW2200_MONITOR is not set ++CONFIG_IPW2200_QOS=y ++# CONFIG_IPW2200_DEBUG is not set ++ ++## ++## file: drivers/net/wireless/libertas/Kconfig ++## ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++# CONFIG_LIBERTAS_DEBUG is not set ++ ++## ++## file: drivers/net/wireless/mwifiex/Kconfig ++## ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++ ++## ++## file: drivers/net/wireless/orinoco/Kconfig ++## ++CONFIG_HERMES=m ++CONFIG_PLX_HERMES=m ++CONFIG_TMD_HERMES=m ++CONFIG_NORTEL_HERMES=m ++CONFIG_PCI_HERMES=m ++ ++## ++## file: drivers/net/wireless/zd1211rw/Kconfig ++## ++CONFIG_ZD1211RW=m ++# CONFIG_ZD1211RW_DEBUG is not set ++ ++## ++## file: drivers/parport/Kconfig ++## ++# CONFIG_PARPORT_AX88796 is not set ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++# CONFIG_HOTPLUG_PCI is not set ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_CMOS=y ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 is not set ++CONFIG_RTC_DRV_M48T86=m ++# CONFIG_RTC_DRV_V3020 is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_SCSI_ARCMSR=m ++CONFIG_SCSI_HPTIOP=m ++CONFIG_SCSI_DMX3191D=m ++CONFIG_SCSI_FUTURE_DOMAIN=m ++CONFIG_SCSI_IPS=m ++CONFIG_SCSI_INITIO=m ++CONFIG_SCSI_INIA100=m ++CONFIG_SCSI_STEX=m ++CONFIG_SCSI_SYM53C8XX_2=m ++CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 ++CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 ++CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 ++CONFIG_SCSI_SYM53C8XX_MMIO=y ++# CONFIG_SCSI_IPR is not set ++CONFIG_SCSI_QLOGIC_1280=m ++CONFIG_SCSI_DC395x=m ++CONFIG_SCSI_DC390T=m ++CONFIG_SCSI_DEBUG=m ++CONFIG_SCSI_SRP=m ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic79xx ++## ++CONFIG_SCSI_AIC79XX=m ++CONFIG_AIC79XX_CMDS_PER_DEVICE=32 ++CONFIG_AIC79XX_RESET_DELAY_MS=15000 ++CONFIG_AIC79XX_DEBUG_ENABLE=y ++CONFIG_AIC79XX_DEBUG_MASK=0 ++CONFIG_AIC79XX_REG_PRETTY_PRINT=y ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++CONFIG_SCSI_AIC7XXX=m ++CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 ++CONFIG_AIC7XXX_RESET_DELAY_MS=15000 ++CONFIG_AIC7XXX_DEBUG_ENABLE=y ++CONFIG_AIC7XXX_DEBUG_MASK=0 ++CONFIG_AIC7XXX_REG_PRETTY_PRINT=y ++ ++## ++## file: drivers/scsi/aic94xx/Kconfig ++## ++CONFIG_SCSI_AIC94XX=m ++# CONFIG_AIC94XX_DEBUG is not set ++ ++## ++## file: drivers/scsi/libsas/Kconfig ++## ++CONFIG_SCSI_SAS_LIBSAS=m ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++CONFIG_MEGARAID_NEWGEN=y ++CONFIG_MEGARAID_MM=m ++CONFIG_MEGARAID_MAILBOX=m ++CONFIG_MEGARAID_LEGACY=m ++CONFIG_MEGARAID_SAS=m ++ ++## ++## file: drivers/scsi/qla2xxx/Kconfig ++## ++CONFIG_SCSI_QLA_FC=m ++ ++## ++## file: drivers/scsi/qla4xxx/Kconfig ++## ++CONFIG_SCSI_QLA_ISCSI=m ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI=y ++CONFIG_SPI_BITBANG=m ++CONFIG_SPI_BUTTERFLY=m ++# CONFIG_SPI_SPIDEV is not set ++ ++## ++## file: drivers/telephony/Kconfig ++## ++CONFIG_PHONE=m ++CONFIG_PHONE_IXJ=m ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_PCI=y ++CONFIG_SERIAL_8250_NR_UARTS=4 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++CONFIG_SERIAL_8250_EXTENDED=y ++# CONFIG_SERIAL_8250_MANY_PORTS is not set ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++# CONFIG_SERIAL_8250_DETECT_IRQ is not set ++CONFIG_SERIAL_8250_RSA=y ++CONFIG_SERIAL_JSM=m ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++CONFIG_USB_USS720=m ++ ++## ++## file: drivers/usb/atm/Kconfig ++## ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++# CONFIG_USB_EHCI_TT_NEWSCHED is not set ++CONFIG_USB_ISP116X_HCD=m ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=y ++CONFIG_USB_U132_HCD=m ++CONFIG_USB_SL811_HCD=m ++ ++## ++## file: drivers/usb/mon/Kconfig ++## ++CONFIG_USB_MON=y ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++CONFIG_FIRMWARE_EDID=y ++CONFIG_FB_MODE_HELPERS=y ++CONFIG_FB_TILEBLITTING=y ++CONFIG_FB_CIRRUS=y ++CONFIG_FB_PM2=m ++CONFIG_FB_PM2_FIFO_DISCONNECT=y ++CONFIG_FB_CYBER2000=m ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++CONFIG_FB_S1D13XXX=m ++CONFIG_FB_MATROX=m ++CONFIG_FB_MATROX_MILLENIUM=y ++CONFIG_FB_MATROX_MYSTIQUE=y ++CONFIG_FB_MATROX_G=y ++CONFIG_FB_MATROX_I2C=m ++CONFIG_FB_MATROX_MAVEN=m ++CONFIG_FB_RADEON=m ++CONFIG_FB_RADEON_I2C=y ++CONFIG_FB_RADEON_BACKLIGHT=y ++# CONFIG_FB_RADEON_DEBUG is not set ++CONFIG_FB_ATY128=m ++CONFIG_FB_ATY128_BACKLIGHT=y ++CONFIG_FB_ATY=m ++CONFIG_FB_ATY_CT=y ++# CONFIG_FB_ATY_GENERIC_LCD is not set ++CONFIG_FB_ATY_GX=y ++CONFIG_FB_ATY_BACKLIGHT=y ++CONFIG_FB_SAVAGE=m ++# CONFIG_FB_SAVAGE_I2C is not set ++# CONFIG_FB_SAVAGE_ACCEL is not set ++CONFIG_FB_SIS=m ++CONFIG_FB_SIS_300=y ++CONFIG_FB_SIS_315=y ++CONFIG_FB_NEOMAGIC=m ++CONFIG_FB_KYRO=m ++CONFIG_FB_VOODOO1=m ++CONFIG_FB_VT8623=m ++CONFIG_FB_TRIDENT=m ++CONFIG_FB_ARK=m ++CONFIG_FB_PM3=m ++CONFIG_FB_SM501=m ++CONFIG_FB_VIRTUAL=m ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: drivers/video/display/Kconfig ++## ++CONFIG_DISPLAY_SUPPORT=m ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_PCIPCWATCHDOG=m ++CONFIG_WDTPCI=m ++CONFIG_USBPCWATCHDOG=m ++ ++## ++## file: fs/dlm/Kconfig ++## ++CONFIG_DLM=m ++# CONFIG_DLM_DEBUG is not set ++ ++## ++## file: fs/nfs/Kconfig ++## ++CONFIG_NFS_FS=y ++ ++## ++## file: fs/partitions/Kconfig ++## ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_MSDOS_PARTITION=y ++ ++## ++## file: init/Kconfig ++## ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++ ++## ++## file: lib/Kconfig.debug ++## ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_UNUSED_SYMBOLS=y ++# CONFIG_HEADERS_CHECK is not set ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/ax25/Kconfig ++## ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++# CONFIG_AX25_DAMA_SLAVE is not set ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++ ++## ++## file: net/decnet/Kconfig ++## ++CONFIG_DECNET=m ++# CONFIG_DECNET_ROUTER is not set ++ ++## ++## file: net/decnet/netfilter/Kconfig ++## ++CONFIG_DECNET_NF_GRABULATOR=m ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++# CONFIG_IPX_INTERN is not set ++ ++## ++## file: net/irda/Kconfig ++## ++CONFIG_IRDA=m ++# CONFIG_IRDA_ULTRA is not set ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++# CONFIG_IRDA_DEBUG is not set ++ ++## ++## file: net/irda/ircomm/Kconfig ++## ++CONFIG_IRCOMM=m ++ ++## ++## file: net/irda/irlan/Kconfig ++## ++CONFIG_IRLAN=m ++ ++## ++## file: net/irda/irnet/Kconfig ++## ++CONFIG_IRNET=m ++ ++## ++## file: net/lapb/Kconfig ++## ++CONFIG_LAPB=m ++ ++## ++## file: net/netlabel/Kconfig ++## ++# CONFIG_NETLABEL is not set ++ ++## ++## file: sound/drivers/Kconfig ++## ++CONFIG_SND_DUMMY=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_MTS64=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_PORTMAN2X4=m ++CONFIG_SND_AC97_POWER_SAVE=y ++ ++## ++## file: sound/pci/Kconfig ++## ++CONFIG_SND_AD1889=m ++CONFIG_SND_ALS300=m ++CONFIG_SND_ALI5451=m ++CONFIG_SND_ATIIXP=m ++CONFIG_SND_ATIIXP_MODEM=m ++CONFIG_SND_AU8810=m ++CONFIG_SND_AU8820=m ++CONFIG_SND_AU8830=m ++CONFIG_SND_AZT3328=m ++CONFIG_SND_BT87X=m ++# CONFIG_SND_BT87X_OVERCLOCK is not set ++CONFIG_SND_CA0106=m ++CONFIG_SND_CMIPCI=m ++CONFIG_SND_CS4281=m ++CONFIG_SND_CS46XX=m ++CONFIG_SND_CS46XX_NEW_DSP=y ++CONFIG_SND_DARLA20=m ++CONFIG_SND_GINA20=m ++CONFIG_SND_LAYLA20=m ++CONFIG_SND_DARLA24=m ++CONFIG_SND_GINA24=m ++CONFIG_SND_LAYLA24=m ++CONFIG_SND_MONA=m ++CONFIG_SND_MIA=m ++CONFIG_SND_ECHO3G=m ++CONFIG_SND_INDIGO=m ++CONFIG_SND_INDIGOIO=m ++CONFIG_SND_INDIGODJ=m ++CONFIG_SND_EMU10K1=m ++CONFIG_SND_EMU10K1X=m ++CONFIG_SND_ENS1370=m ++CONFIG_SND_ENS1371=m ++CONFIG_SND_ES1938=m ++CONFIG_SND_ES1968=m ++CONFIG_SND_FM801=m ++CONFIG_SND_FM801_TEA575X_BOOL=y ++CONFIG_SND_HDSP=m ++CONFIG_SND_HDSPM=m ++CONFIG_SND_ICE1712=m ++CONFIG_SND_ICE1724=m ++CONFIG_SND_INTEL8X0=m ++CONFIG_SND_INTEL8X0M=m ++CONFIG_SND_KORG1212=m ++CONFIG_SND_MAESTRO3=m ++CONFIG_SND_MIXART=m ++CONFIG_SND_NM256=m ++CONFIG_SND_PCXHR=m ++CONFIG_SND_RIPTIDE=m ++CONFIG_SND_RME32=m ++CONFIG_SND_RME96=m ++CONFIG_SND_RME9652=m ++CONFIG_SND_SONICVIBES=m ++CONFIG_SND_TRIDENT=m ++CONFIG_SND_VIA82XX=m ++CONFIG_SND_VIA82XX_MODEM=m ++CONFIG_SND_VX222=m ++CONFIG_SND_YMFPCI=m ++ ++## ++## file: sound/pci/hda/Kconfig ++## ++CONFIG_SND_HDA_INTEL=m ++ +diff --git a/debian/config/mips/config.5kc-malta b/debian/config/mips/config.5kc-malta +new file mode 100644 +index 0000000..25cb6d0 +--- /dev/null ++++ b/debian/config/mips/config.5kc-malta +@@ -0,0 +1,1238 @@ ++## ++## file: arch/Kconfig ++## ++CONFIG_OPROFILE=m ++ ++## ++## file: arch/mips/Kconfig ++## ++## choice: System type ++# CONFIG_MIPS_COBALT is not set ++# CONFIG_MACH_DECSTATION is not set ++# CONFIG_MACH_JAZZ is not set ++# CONFIG_LASAT is not set ++CONFIG_MIPS_MALTA=y ++# CONFIG_MIPS_SIM is not set ++# CONFIG_MACH_VR41XX is not set ++# CONFIG_PNX8550_JBS is not set ++# CONFIG_PNX8550_STB810 is not set ++# CONFIG_PMC_YOSEMITE is not set ++# CONFIG_SGI_IP22 is not set ++# CONFIG_SGI_IP27 is not set ++# CONFIG_SGI_IP32 is not set ++# CONFIG_SIBYTE_CRHINE is not set ++# CONFIG_SIBYTE_CARMEL is not set ++# CONFIG_SIBYTE_CRHONE is not set ++# CONFIG_SIBYTE_RHONE is not set ++# CONFIG_SIBYTE_SWARM is not set ++# CONFIG_SIBYTE_LITTLESUR is not set ++# CONFIG_SIBYTE_SENTOSA is not set ++# CONFIG_SIBYTE_BIGSUR is not set ++# CONFIG_SNI_RM is not set ++# CONFIG_WR_PPMC is not set ++## end choice ++## choice: CPU type ++# CONFIG_CPU_MIPS32_R1 is not set ++# CONFIG_CPU_MIPS32_R2 is not set ++CONFIG_CPU_MIPS64_R1=y ++# CONFIG_CPU_MIPS64_R2 is not set ++# CONFIG_CPU_R3000 is not set ++# CONFIG_CPU_TX39XX is not set ++# CONFIG_CPU_VR41XX is not set ++# CONFIG_CPU_R4300 is not set ++# CONFIG_CPU_R4X00 is not set ++# CONFIG_CPU_TX49XX is not set ++# CONFIG_CPU_R5000 is not set ++# CONFIG_CPU_R5432 is not set ++# CONFIG_CPU_R6000 is not set ++# CONFIG_CPU_NEVADA is not set ++# CONFIG_CPU_R8000 is not set ++# CONFIG_CPU_R10000 is not set ++# CONFIG_CPU_RM7000 is not set ++# CONFIG_CPU_RM9000 is not set ++# CONFIG_CPU_SB1 is not set ++## end choice ++## choice: Kernel code model ++# CONFIG_32BIT is not set ++CONFIG_64BIT=y ++## end choice ++## choice: Kernel page size ++CONFIG_PAGE_SIZE_4KB=y ++# CONFIG_PAGE_SIZE_8KB is not set ++# CONFIG_PAGE_SIZE_16KB is not set ++# CONFIG_PAGE_SIZE_64KB is not set ++## end choice ++## choice: MIPS MT options ++CONFIG_MIPS_MT_DISABLED=y ++# CONFIG_MIPS_MT_SMP is not set ++# CONFIG_MIPS_MT_SMTC is not set ++## end choice ++# CONFIG_MIPS_VPE_LOADER is not set ++# CONFIG_CPU_HAS_SMARTMIPS is not set ++## choice: Timer frequency ++# CONFIG_HZ_48 is not set ++# CONFIG_HZ_100 is not set ++# CONFIG_HZ_128 is not set ++CONFIG_HZ_250=y ++# CONFIG_HZ_256 is not set ++# CONFIG_HZ_1000 is not set ++# CONFIG_HZ_1024 is not set ++## end choice ++# CONFIG_KEXEC is not set ++CONFIG_PCI=y ++CONFIG_MIPS32_COMPAT=y ++CONFIG_MIPS32_O32=y ++CONFIG_MIPS32_N32=y ++ ++## ++## file: arch/mips/Kconfig.debug ++## ++CONFIG_CMDLINE="" ++ ++## ++## file: arch/mips/txx9/Kconfig ++## ++# CONFIG_TOSHIBA_JMR3927 is not set ++# CONFIG_TOSHIBA_RBTX4927 is not set ++# CONFIG_TOSHIBA_RBTX4938 is not set ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=y ++CONFIG_SATA_AHCI=y ++CONFIG_SATA_SIL24=y ++# CONFIG_PDC_ADMA is not set ++# CONFIG_SATA_QSTOR is not set ++CONFIG_SATA_SX4=y ++CONFIG_ATA_PIIX=y ++CONFIG_SATA_MV=y ++# CONFIG_SATA_NV is not set ++CONFIG_SATA_PROMISE=y ++CONFIG_SATA_SIL=y ++# CONFIG_SATA_SIS is not set ++# CONFIG_SATA_SVW is not set ++# CONFIG_SATA_ULI is not set ++# CONFIG_SATA_VIA is not set ++# CONFIG_SATA_VITESSE is not set ++CONFIG_PATA_CMD64X=y ++CONFIG_PATA_HPT366=y ++CONFIG_PATA_NETCELL=y ++CONFIG_PATA_OLDPIIX=y ++CONFIG_PATA_PDC2027X=y ++CONFIG_PATA_PDC_OLD=y ++CONFIG_PATA_SIL680=y ++CONFIG_PATA_MPIIX=y ++CONFIG_PATA_NS87410=y ++CONFIG_PATA_PLATFORM=y ++CONFIG_ATA_GENERIC=y ++ ++## ++## file: drivers/atm/Kconfig ++## ++# CONFIG_ATM_DRIVERS is not set ++ ++## ++## file: drivers/auxdisplay/Kconfig ++## ++# CONFIG_KS0108 is not set ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_DEV_FD=m ++CONFIG_PARIDE=m ++# CONFIG_BLK_CPQ_DA is not set ++CONFIG_BLK_CPQ_CISS_DA=m ++CONFIG_CISS_SCSI_TAPE=y ++CONFIG_BLK_DEV_DAC960=m ++CONFIG_BLK_DEV_UMEM=m ++CONFIG_BLK_DEV_SX8=m ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_CDROM_PKTCDVD_BUFFERS=8 ++# CONFIG_CDROM_PKTCDVD_WCACHE is not set ++ ++## ++## file: drivers/block/paride/Kconfig ++## ++CONFIG_PARIDE_PD=m ++CONFIG_PARIDE_PCD=m ++CONFIG_PARIDE_PF=m ++CONFIG_PARIDE_PT=m ++CONFIG_PARIDE_PG=m ++CONFIG_PARIDE_ATEN=m ++CONFIG_PARIDE_BPCK=m ++CONFIG_PARIDE_COMM=m ++CONFIG_PARIDE_DSTR=m ++CONFIG_PARIDE_FIT2=m ++CONFIG_PARIDE_FIT3=m ++CONFIG_PARIDE_EPAT=m ++# CONFIG_PARIDE_EPATC8 is not set ++CONFIG_PARIDE_EPIA=m ++CONFIG_PARIDE_FRIQ=m ++CONFIG_PARIDE_FRPW=m ++CONFIG_PARIDE_KBIC=m ++CONFIG_PARIDE_KTTI=m ++CONFIG_PARIDE_ON20=m ++CONFIG_PARIDE_ON26=m ++ ++## ++## file: drivers/bluetooth/Kconfig ++## ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_H4=y ++CONFIG_BT_HCIUART_BCSP=y ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++CONFIG_PPDEV=m ++CONFIG_R3964=m ++CONFIG_APPLICOM=m ++ ++## ++## file: drivers/char/hw_random/Kconfig ++## ++CONFIG_HW_RANDOM=m ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++CONFIG_IPMI_HANDLER=m ++# CONFIG_IPMI_PANIC_EVENT is not set ++# CONFIG_IPMI_DEVICE_INTERFACE is not set ++CONFIG_IPMI_SI=m ++CONFIG_IPMI_WATCHDOG=m ++CONFIG_IPMI_POWEROFF=m ++ ++## ++## file: drivers/char/tpm/Kconfig ++## ++# CONFIG_TCG_TPM is not set ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++CONFIG_DRM=m ++CONFIG_DRM_TDFX=m ++CONFIG_DRM_R128=m ++CONFIG_DRM_RADEON=m ++CONFIG_DRM_MGA=m ++CONFIG_DRM_VIA=m ++CONFIG_DRM_SAVAGE=m ++ ++## ++## file: drivers/gpu/drm/nouveau/Kconfig ++## ++CONFIG_DRM_NOUVEAU=m ++# CONFIG_DRM_NOUVEAU_BACKLIGHT is not set ++# CONFIG_DRM_NOUVEAU_DEBUG is not set ++CONFIG_DRM_I2C_CH7006=m ++CONFIG_DRM_I2C_SIL164=m ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_HWMON=y ++# CONFIG_HWMON_DEBUG_CHIP is not set ++# CONFIG_SENSORS_ABITUGURU is not set ++CONFIG_SENSORS_AD7418=m ++CONFIG_SENSORS_ADM1021=m ++CONFIG_SENSORS_ADM1025=m ++CONFIG_SENSORS_ADM1026=m ++CONFIG_SENSORS_ADM1029=m ++CONFIG_SENSORS_ADM1031=m ++CONFIG_SENSORS_ADM9240=m ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++CONFIG_SENSORS_DS1621=m ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++CONFIG_SENSORS_LM63=m ++CONFIG_SENSORS_LM70=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_LM77=m ++CONFIG_SENSORS_LM78=m ++CONFIG_SENSORS_LM80=m ++CONFIG_SENSORS_LM83=m ++CONFIG_SENSORS_LM85=m ++CONFIG_SENSORS_LM87=m ++CONFIG_SENSORS_LM90=m ++CONFIG_SENSORS_LM92=m ++CONFIG_SENSORS_MAX1619=m ++CONFIG_SENSORS_MAX6650=m ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PC87427 is not set ++CONFIG_SENSORS_PCF8591=m ++# CONFIG_SENSORS_SIS5595 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47M192 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_VIA686A is not set ++# CONFIG_SENSORS_VT1211 is not set ++# CONFIG_SENSORS_VT8231 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83791D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83793 is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=m ++CONFIG_I2C_CHARDEV=m ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++# 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_PIIX4=m ++# 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 ++# CONFIG_I2C_OCORES is not set ++CONFIG_I2C_SIMTEC=m ++CONFIG_I2C_PARPORT=m ++CONFIG_I2C_PARPORT_LIGHT=m ++CONFIG_I2C_TINY_USB=m ++# CONFIG_I2C_STUB is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++CONFIG_GAMEPORT=m ++# CONFIG_GAMEPORT_NS558 is not set ++# CONFIG_GAMEPORT_L4 is not set ++CONFIG_GAMEPORT_EMU10K1=m ++CONFIG_GAMEPORT_FM801=m ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++CONFIG_INPUT_JOYSTICK=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++CONFIG_KEYBOARD_LKKBD=m ++CONFIG_KEYBOARD_NEWTON=m ++CONFIG_KEYBOARD_STOWAWAY=m ++CONFIG_KEYBOARD_SUNKBD=m ++CONFIG_KEYBOARD_XTKBD=m ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++# CONFIG_INPUT_MISC is not set ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=m ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_LIFEBOOK=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_SERIAL=m ++CONFIG_MOUSE_APPLETOUCH=m ++CONFIG_MOUSE_VSXXXAA=m ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++CONFIG_SERIO_I8042=y ++CONFIG_SERIO_SERPORT=m ++CONFIG_SERIO_PARKBD=m ++CONFIG_SERIO_PCIPS2=y ++CONFIG_SERIO_LIBPS2=y ++CONFIG_SERIO_RAW=m ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++CONFIG_INPUT_TOUCHSCREEN=y ++ ++## ++## file: drivers/isdn/Kconfig ++## ++CONFIG_ISDN=y ++CONFIG_ISDN_CAPI=m ++ ++## ++## file: drivers/isdn/capi/Kconfig ++## ++CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y ++CONFIG_ISDN_CAPI_MIDDLEWARE=y ++CONFIG_ISDN_CAPI_CAPI20=m ++CONFIG_ISDN_CAPI_CAPIDRV=m ++ ++## ++## file: drivers/isdn/gigaset/Kconfig ++## ++CONFIG_ISDN_DRV_GIGASET=m ++CONFIG_GIGASET_BASE=m ++CONFIG_GIGASET_M105=m ++CONFIG_GIGASET_M101=m ++# CONFIG_GIGASET_DEBUG is not set ++ ++## ++## file: drivers/isdn/hardware/avm/Kconfig ++## ++CONFIG_CAPI_AVM=y ++CONFIG_ISDN_DRV_AVMB1_B1PCI=m ++CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y ++CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m ++CONFIG_ISDN_DRV_AVMB1_T1PCI=m ++CONFIG_ISDN_DRV_AVMB1_C4=m ++ ++## ++## file: drivers/isdn/hardware/eicon/Kconfig ++## ++CONFIG_CAPI_EICON=y ++CONFIG_ISDN_DIVAS=m ++CONFIG_ISDN_DIVAS_BRIPCI=y ++CONFIG_ISDN_DIVAS_PRIPCI=y ++CONFIG_ISDN_DIVAS_DIVACAPI=m ++CONFIG_ISDN_DIVAS_USERIDI=m ++CONFIG_ISDN_DIVAS_MAINT=m ++ ++## ++## file: drivers/leds/Kconfig ++## ++# CONFIG_NEW_LEDS is not set ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++CONFIG_I2O=m ++CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y ++CONFIG_I2O_EXT_ADAPTEC=y ++CONFIG_I2O_EXT_ADAPTEC_DMA64=y ++CONFIG_I2O_CONFIG=m ++CONFIG_I2O_CONFIG_OLD_IOCTL=y ++CONFIG_I2O_BUS=m ++CONFIG_I2O_BLOCK=m ++CONFIG_I2O_SCSI=m ++CONFIG_I2O_PROC=m ++ ++## ++## file: drivers/mfd/Kconfig ++## ++CONFIG_MFD_SM501=m ++ ++## ++## file: drivers/misc/Kconfig ++## ++# CONFIG_PHANTOM is not set ++# CONFIG_SGI_IOC4 is not set ++CONFIG_TIFM_CORE=m ++CONFIG_TIFM_7XX1=m ++ ++## ++## file: drivers/mmc/Kconfig ++## ++CONFIG_MMC=m ++# CONFIG_MMC_DEBUG is not set ++ ++## ++## file: drivers/mmc/card/Kconfig ++## ++CONFIG_MMC_BLOCK=m ++ ++## ++## file: drivers/mmc/core/Kconfig ++## ++# CONFIG_MMC_UNSAFE_RESUME is not set ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=m ++CONFIG_MTD_REDBOOT_PARTS=y ++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 ++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set ++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set ++CONFIG_MTD_CHAR=m ++CONFIG_MTD_BLKDEVS=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_BLOCK_RO=m ++CONFIG_FTL=m ++CONFIG_NFTL=m ++CONFIG_NFTL_RW=y ++CONFIG_INFTL=m ++CONFIG_RFD_FTL=m ++CONFIG_SSFDC=m ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++CONFIG_MTD_CFI=m ++CONFIG_MTD_JEDECPROBE=m ++# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT=m ++CONFIG_MTD_CFI_AMDSTD=m ++CONFIG_MTD_CFI_STAA=m ++CONFIG_MTD_RAM=m ++CONFIG_MTD_ROM=m ++CONFIG_MTD_ABSENT=m ++ ++## ++## file: drivers/mtd/devices/Kconfig ++## ++CONFIG_MTD_PMC551=m ++# CONFIG_MTD_PMC551_BUGFIX is not set ++# CONFIG_MTD_PMC551_DEBUG is not set ++CONFIG_MTD_DATAFLASH=m ++CONFIG_MTD_M25P80=m ++CONFIG_MTD_SLRAM=m ++CONFIG_MTD_PHRAM=m ++CONFIG_MTD_MTDRAM=m ++CONFIG_MTDRAM_TOTAL_SIZE=4096 ++CONFIG_MTDRAM_ERASE_SIZE=128 ++CONFIG_MTD_BLOCK2MTD=m ++CONFIG_MTD_DOC2000=m ++CONFIG_MTD_DOC2001=m ++CONFIG_MTD_DOC2001PLUS=m ++# CONFIG_MTD_DOCPROBE_ADVANCED is not set ++CONFIG_MTD_DOCPROBE_ADDRESS=0 ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++CONFIG_MTD_PHYSMAP=m ++CONFIG_MTD_PHYSMAP_START=0x8000000 ++CONFIG_MTD_PHYSMAP_LEN=0x0 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=2 ++CONFIG_MTD_PCI=m ++CONFIG_MTD_PLATRAM=m ++ ++## ++## file: drivers/mtd/nand/Kconfig ++## ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=m ++# CONFIG_MTD_NAND_VERIFY_WRITE is not set ++# CONFIG_MTD_NAND_MUSEUM_IDS is not set ++CONFIG_MTD_NAND_DISKONCHIP=m ++# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set ++CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 ++# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set ++CONFIG_MTD_NAND_CAFE=m ++# CONFIG_MTD_NAND_PLATFORM is not set ++ ++## ++## file: drivers/mtd/onenand/Kconfig ++## ++CONFIG_MTD_ONENAND=m ++CONFIG_MTD_ONENAND_VERIFY_WRITE=y ++# CONFIG_MTD_ONENAND_OTP is not set ++ ++## ++## file: drivers/mtd/ubi/Kconfig ++## ++CONFIG_MTD_UBI=m ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_RESERVE=1 ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_DEBUG is not set ++ ++## ++## file: drivers/net/Kconfig ++## ++CONFIG_NET_FC=y ++# CONFIG_NETPOLL_TRAP is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++CONFIG_ARCNET=m ++CONFIG_ARCNET_1201=m ++CONFIG_ARCNET_1051=m ++CONFIG_ARCNET_RAW=m ++CONFIG_ARCNET_CAP=m ++CONFIG_ARCNET_COM90xx=m ++CONFIG_ARCNET_COM90xxIO=m ++CONFIG_ARCNET_RIM_I=m ++CONFIG_ARCNET_COM20020=m ++CONFIG_ARCNET_COM20020_PCI=m ++ ++## ++## file: drivers/net/ethernet/Kconfig ++## ++CONFIG_FEALNX=m ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++CONFIG_NET_VENDOR_3COM=y ++CONFIG_VORTEX=m ++CONFIG_TYPHOON=m ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_NE2K_PCI=m ++ ++## ++## file: drivers/net/ethernet/adaptec/Kconfig ++## ++CONFIG_ADAPTEC_STARFIRE=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_AMD8111_ETH=m ++CONFIG_PCNET32=y ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++CONFIG_B44=m ++ ++## ++## file: drivers/net/ethernet/davicom/Kconfig ++## ++# CONFIG_DM9000 is not set ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++CONFIG_NET_TULIP=y ++CONFIG_DE2104X=m ++CONFIG_TULIP=m ++# CONFIG_TULIP_MWI is not set ++# CONFIG_TULIP_MMIO is not set ++# CONFIG_TULIP_NAPI is not set ++# CONFIG_WINBOND_840 is not set ++CONFIG_DM9102=m ++# CONFIG_ULI526X is not set ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++CONFIG_DE600=m ++CONFIG_DE620=m ++CONFIG_SUNDANCE=m ++# CONFIG_SUNDANCE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++# CONFIG_HP100 is not set ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++CONFIG_E100=m ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_NATSEMI=m ++ ++## ++## file: drivers/net/ethernet/nvidia/Kconfig ++## ++# CONFIG_FORCEDETH is not set ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_8139CP=m ++CONFIG_8139TOO=m ++# CONFIG_8139TOO_PIO is not set ++CONFIG_8139TOO_TUNE_TWISTER=y ++CONFIG_8139TOO_8129=y ++# CONFIG_8139_OLD_RX_RESET is not set ++ ++## ++## file: drivers/net/ethernet/silan/Kconfig ++## ++CONFIG_SC92031=m ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++CONFIG_SIS900=m ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_EPIC100=m ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++ ++## ++## file: drivers/net/ethernet/toshiba/Kconfig ++## ++# CONFIG_TC35815 is not set ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++CONFIG_VIA_RHINE=m ++# CONFIG_VIA_RHINE_MMIO is not set ++ ++## ++## file: drivers/net/fddi/Kconfig ++## ++CONFIG_FDDI=y ++CONFIG_SKFP=m ++ ++## ++## file: drivers/net/hippi/Kconfig ++## ++CONFIG_HIPPI=y ++CONFIG_ROADRUNNER=m ++# CONFIG_ROADRUNNER_LARGE_RINGS is not set ++ ++## ++## file: drivers/net/irda/Kconfig ++## ++CONFIG_IRTTY_SIR=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_VLSI_FIR=m ++CONFIG_MCS_FIR=m ++ ++## ++## file: drivers/net/phy/Kconfig ++## ++CONFIG_PHYLIB=m ++CONFIG_MARVELL_PHY=m ++CONFIG_DAVICOM_PHY=m ++# CONFIG_QSEMI_PHY is not set ++CONFIG_LXT_PHY=m ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++CONFIG_SMSC_PHY=m ++CONFIG_BROADCOM_PHY=m ++ ++## ++## file: drivers/net/plip/Kconfig ++## ++CONFIG_PLIP=m ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++# CONFIG_TR is not set ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++# CONFIG_WAN is not set ++ ++## ++## file: drivers/net/wireless/Kconfig ++## ++CONFIG_ATMEL=m ++CONFIG_PCI_ATMEL=m ++CONFIG_USB_ZD1201=m ++ ++## ++## file: drivers/net/wireless/ipw2x00/Kconfig ++## ++CONFIG_IPW2100=m ++CONFIG_IPW2100_MONITOR=y ++# CONFIG_IPW2100_DEBUG is not set ++CONFIG_IPW2200=m ++# CONFIG_IPW2200_MONITOR is not set ++CONFIG_IPW2200_QOS=y ++# CONFIG_IPW2200_DEBUG is not set ++ ++## ++## file: drivers/net/wireless/libertas/Kconfig ++## ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++# CONFIG_LIBERTAS_DEBUG is not set ++ ++## ++## file: drivers/net/wireless/mwifiex/Kconfig ++## ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++ ++## ++## file: drivers/net/wireless/orinoco/Kconfig ++## ++CONFIG_HERMES=m ++CONFIG_PLX_HERMES=m ++CONFIG_TMD_HERMES=m ++CONFIG_NORTEL_HERMES=m ++CONFIG_PCI_HERMES=m ++ ++## ++## file: drivers/net/wireless/zd1211rw/Kconfig ++## ++CONFIG_ZD1211RW=m ++# CONFIG_ZD1211RW_DEBUG is not set ++ ++## ++## file: drivers/parport/Kconfig ++## ++# CONFIG_PARPORT_AX88796 is not set ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++# CONFIG_HOTPLUG_PCI is not set ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_CMOS=y ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 is not set ++CONFIG_RTC_DRV_M48T86=m ++# CONFIG_RTC_DRV_V3020 is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_SCSI_ARCMSR=m ++CONFIG_SCSI_HPTIOP=m ++CONFIG_SCSI_DMX3191D=m ++CONFIG_SCSI_FUTURE_DOMAIN=m ++CONFIG_SCSI_IPS=m ++CONFIG_SCSI_INITIO=m ++CONFIG_SCSI_INIA100=m ++CONFIG_SCSI_STEX=m ++CONFIG_SCSI_SYM53C8XX_2=m ++CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 ++CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 ++CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 ++CONFIG_SCSI_SYM53C8XX_MMIO=y ++# CONFIG_SCSI_IPR is not set ++CONFIG_SCSI_QLOGIC_1280=m ++CONFIG_SCSI_DC395x=m ++CONFIG_SCSI_DC390T=m ++CONFIG_SCSI_DEBUG=m ++CONFIG_SCSI_SRP=m ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic79xx ++## ++CONFIG_SCSI_AIC79XX=m ++CONFIG_AIC79XX_CMDS_PER_DEVICE=32 ++CONFIG_AIC79XX_RESET_DELAY_MS=15000 ++CONFIG_AIC79XX_DEBUG_ENABLE=y ++CONFIG_AIC79XX_DEBUG_MASK=0 ++CONFIG_AIC79XX_REG_PRETTY_PRINT=y ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++CONFIG_SCSI_AIC7XXX=m ++CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 ++CONFIG_AIC7XXX_RESET_DELAY_MS=15000 ++CONFIG_AIC7XXX_DEBUG_ENABLE=y ++CONFIG_AIC7XXX_DEBUG_MASK=0 ++CONFIG_AIC7XXX_REG_PRETTY_PRINT=y ++ ++## ++## file: drivers/scsi/aic94xx/Kconfig ++## ++CONFIG_SCSI_AIC94XX=m ++# CONFIG_AIC94XX_DEBUG is not set ++ ++## ++## file: drivers/scsi/libsas/Kconfig ++## ++CONFIG_SCSI_SAS_LIBSAS=m ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++CONFIG_MEGARAID_NEWGEN=y ++CONFIG_MEGARAID_MM=m ++CONFIG_MEGARAID_MAILBOX=m ++CONFIG_MEGARAID_LEGACY=m ++CONFIG_MEGARAID_SAS=m ++ ++## ++## file: drivers/scsi/qla2xxx/Kconfig ++## ++CONFIG_SCSI_QLA_FC=m ++ ++## ++## file: drivers/scsi/qla4xxx/Kconfig ++## ++CONFIG_SCSI_QLA_ISCSI=m ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI=y ++CONFIG_SPI_BITBANG=m ++CONFIG_SPI_BUTTERFLY=m ++# CONFIG_SPI_SPIDEV is not set ++ ++## ++## file: drivers/telephony/Kconfig ++## ++CONFIG_PHONE=m ++CONFIG_PHONE_IXJ=m ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_PCI=y ++CONFIG_SERIAL_8250_NR_UARTS=4 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++CONFIG_SERIAL_8250_EXTENDED=y ++# CONFIG_SERIAL_8250_MANY_PORTS is not set ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++# CONFIG_SERIAL_8250_DETECT_IRQ is not set ++CONFIG_SERIAL_8250_RSA=y ++CONFIG_SERIAL_JSM=m ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++CONFIG_USB_USS720=m ++ ++## ++## file: drivers/usb/atm/Kconfig ++## ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++# CONFIG_USB_EHCI_TT_NEWSCHED is not set ++CONFIG_USB_ISP116X_HCD=m ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=y ++CONFIG_USB_U132_HCD=m ++CONFIG_USB_SL811_HCD=m ++ ++## ++## file: drivers/usb/mon/Kconfig ++## ++CONFIG_USB_MON=y ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++CONFIG_FIRMWARE_EDID=y ++CONFIG_FB_MODE_HELPERS=y ++CONFIG_FB_TILEBLITTING=y ++CONFIG_FB_CIRRUS=y ++CONFIG_FB_PM2=m ++CONFIG_FB_PM2_FIFO_DISCONNECT=y ++CONFIG_FB_CYBER2000=m ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++CONFIG_FB_S1D13XXX=m ++CONFIG_FB_MATROX=m ++CONFIG_FB_MATROX_MILLENIUM=y ++CONFIG_FB_MATROX_MYSTIQUE=y ++CONFIG_FB_MATROX_G=y ++CONFIG_FB_MATROX_I2C=m ++CONFIG_FB_MATROX_MAVEN=m ++CONFIG_FB_RADEON=m ++CONFIG_FB_RADEON_I2C=y ++CONFIG_FB_RADEON_BACKLIGHT=y ++# CONFIG_FB_RADEON_DEBUG is not set ++CONFIG_FB_ATY128=m ++CONFIG_FB_ATY128_BACKLIGHT=y ++CONFIG_FB_ATY=m ++CONFIG_FB_ATY_CT=y ++# CONFIG_FB_ATY_GENERIC_LCD is not set ++CONFIG_FB_ATY_GX=y ++CONFIG_FB_ATY_BACKLIGHT=y ++CONFIG_FB_SAVAGE=m ++# CONFIG_FB_SAVAGE_I2C is not set ++# CONFIG_FB_SAVAGE_ACCEL is not set ++CONFIG_FB_SIS=m ++CONFIG_FB_SIS_300=y ++CONFIG_FB_SIS_315=y ++CONFIG_FB_NEOMAGIC=m ++CONFIG_FB_KYRO=m ++CONFIG_FB_VOODOO1=m ++CONFIG_FB_VT8623=m ++CONFIG_FB_TRIDENT=m ++CONFIG_FB_ARK=m ++CONFIG_FB_PM3=m ++CONFIG_FB_SM501=m ++CONFIG_FB_VIRTUAL=m ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: drivers/video/display/Kconfig ++## ++CONFIG_DISPLAY_SUPPORT=m ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_PCIPCWATCHDOG=m ++CONFIG_WDTPCI=m ++CONFIG_USBPCWATCHDOG=m ++ ++## ++## file: fs/dlm/Kconfig ++## ++CONFIG_DLM=m ++# CONFIG_DLM_DEBUG is not set ++ ++## ++## file: fs/nfs/Kconfig ++## ++CONFIG_NFS_FS=y ++ ++## ++## file: fs/partitions/Kconfig ++## ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_MSDOS_PARTITION=y ++ ++## ++## file: init/Kconfig ++## ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++ ++## ++## file: lib/Kconfig.debug ++## ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_UNUSED_SYMBOLS=y ++# CONFIG_HEADERS_CHECK is not set ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/ax25/Kconfig ++## ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++# CONFIG_AX25_DAMA_SLAVE is not set ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++ ++## ++## file: net/decnet/Kconfig ++## ++CONFIG_DECNET=m ++# CONFIG_DECNET_ROUTER is not set ++ ++## ++## file: net/decnet/netfilter/Kconfig ++## ++CONFIG_DECNET_NF_GRABULATOR=m ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++# CONFIG_IPX_INTERN is not set ++ ++## ++## file: net/irda/Kconfig ++## ++CONFIG_IRDA=m ++# CONFIG_IRDA_ULTRA is not set ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++# CONFIG_IRDA_DEBUG is not set ++ ++## ++## file: net/irda/ircomm/Kconfig ++## ++CONFIG_IRCOMM=m ++ ++## ++## file: net/irda/irlan/Kconfig ++## ++CONFIG_IRLAN=m ++ ++## ++## file: net/irda/irnet/Kconfig ++## ++CONFIG_IRNET=m ++ ++## ++## file: net/lapb/Kconfig ++## ++CONFIG_LAPB=m ++ ++## ++## file: net/netlabel/Kconfig ++## ++# CONFIG_NETLABEL is not set ++ ++## ++## file: sound/drivers/Kconfig ++## ++CONFIG_SND_DUMMY=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_MTS64=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_PORTMAN2X4=m ++CONFIG_SND_AC97_POWER_SAVE=y ++ ++## ++## file: sound/pci/Kconfig ++## ++CONFIG_SND_AD1889=m ++CONFIG_SND_ALS300=m ++CONFIG_SND_ALI5451=m ++CONFIG_SND_ATIIXP=m ++CONFIG_SND_ATIIXP_MODEM=m ++CONFIG_SND_AU8810=m ++CONFIG_SND_AU8820=m ++CONFIG_SND_AU8830=m ++CONFIG_SND_AZT3328=m ++CONFIG_SND_BT87X=m ++# CONFIG_SND_BT87X_OVERCLOCK is not set ++CONFIG_SND_CA0106=m ++CONFIG_SND_CMIPCI=m ++CONFIG_SND_CS4281=m ++CONFIG_SND_CS46XX=m ++CONFIG_SND_CS46XX_NEW_DSP=y ++CONFIG_SND_DARLA20=m ++CONFIG_SND_GINA20=m ++CONFIG_SND_LAYLA20=m ++CONFIG_SND_DARLA24=m ++CONFIG_SND_GINA24=m ++CONFIG_SND_LAYLA24=m ++CONFIG_SND_MONA=m ++CONFIG_SND_MIA=m ++CONFIG_SND_ECHO3G=m ++CONFIG_SND_INDIGO=m ++CONFIG_SND_INDIGOIO=m ++CONFIG_SND_INDIGODJ=m ++CONFIG_SND_EMU10K1=m ++CONFIG_SND_EMU10K1X=m ++CONFIG_SND_ENS1370=m ++CONFIG_SND_ENS1371=m ++CONFIG_SND_ES1938=m ++CONFIG_SND_ES1968=m ++CONFIG_SND_FM801=m ++CONFIG_SND_FM801_TEA575X_BOOL=y ++CONFIG_SND_HDSP=m ++CONFIG_SND_HDSPM=m ++CONFIG_SND_ICE1712=m ++CONFIG_SND_ICE1724=m ++CONFIG_SND_INTEL8X0=m ++CONFIG_SND_INTEL8X0M=m ++CONFIG_SND_KORG1212=m ++CONFIG_SND_MAESTRO3=m ++CONFIG_SND_MIXART=m ++CONFIG_SND_NM256=m ++CONFIG_SND_PCXHR=m ++CONFIG_SND_RIPTIDE=m ++CONFIG_SND_RME32=m ++CONFIG_SND_RME96=m ++CONFIG_SND_RME9652=m ++CONFIG_SND_SONICVIBES=m ++CONFIG_SND_TRIDENT=m ++CONFIG_SND_VIA82XX=m ++CONFIG_SND_VIA82XX_MODEM=m ++CONFIG_SND_VX222=m ++CONFIG_SND_YMFPCI=m ++ ++## ++## file: sound/pci/hda/Kconfig ++## ++CONFIG_SND_HDA_INTEL=m ++ +diff --git a/debian/config/mips/config.octeon b/debian/config/mips/config.octeon +new file mode 100644 +index 0000000..5395d1b +--- /dev/null ++++ b/debian/config/mips/config.octeon +@@ -0,0 +1,137 @@ ++## ++## file: arch/mips/Kconfig ++## ++## choice: System type ++CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD=y ++## end choice ++# CONFIG_HOTPLUG_CPU is not set ++## choice: Kernel code model ++# CONFIG_32BIT is not set ++CONFIG_64BIT=y ++## end choice ++CONFIG_SMP=y ++CONFIG_PCI=y ++CONFIG_MIPS32_COMPAT=y ++CONFIG_MIPS32_O32=y ++CONFIG_MIPS32_N32=y ++ ++## ++## file: arch/mips/cavium-octeon/Kconfig ++## ++# CONFIG_CAVIUM_OCTEON_2ND_KERNEL is not set ++CONFIG_CAVIUM_OCTEON_HW_FIX_UNALIGNED=y ++CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE=1 ++CONFIG_CAVIUM_OCTEON_LOCK_L2=y ++CONFIG_CAVIUM_OCTEON_LOCK_L2_TLB=y ++CONFIG_CAVIUM_OCTEON_LOCK_L2_EXCEPTION=y ++CONFIG_CAVIUM_OCTEON_LOCK_L2_LOW_LEVEL_INTERRUPT=y ++CONFIG_CAVIUM_OCTEON_LOCK_L2_INTERRUPT=y ++CONFIG_CAVIUM_OCTEON_LOCK_L2_MEMCPY=y ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=y ++CONFIG_ATA_SFF=y ++CONFIG_PATA_OCTEON_CF=y ++ ++## ++## file: drivers/char/hw_random/Kconfig ++## ++CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_OCTEON=y ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=y ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_OCTEON=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_INPUT_TOUCHSCREEN is not set ++ ++## ++## file: drivers/message/fusion/Kconfig ++## ++CONFIG_FUSION=y ++CONFIG_FUSION_SAS=y ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=y ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLOCK=y ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++CONFIG_MTD_CFI=y ++CONFIG_MTD_CFI_AMDSTD=y ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++CONFIG_MTD_PHYSMAP=y ++ ++## ++## file: drivers/net/ethernet/octeon/Kconfig ++## ++CONFIG_OCTEON_MGMT_ETHERNET=y ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_DS1307=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++ ++## ++## file: drivers/staging/octeon/Kconfig ++## ++CONFIG_OCTEON_ETHERNET=y ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=2 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++ ++## ++## file: kernel/power/Kconfig ++## ++# CONFIG_SUSPEND is not set ++# CONFIG_HIBERNATION is not set ++# CONFIG_PM_RUNTIME is not set ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_SPARSEMEM_MANUAL=y ++## end choice ++ +diff --git a/debian/config/mips/config.r4k-ip22 b/debian/config/mips/config.r4k-ip22 +new file mode 100644 +index 0000000..7a0ad0c +--- /dev/null ++++ b/debian/config/mips/config.r4k-ip22 +@@ -0,0 +1,544 @@ ++## ++## file: arch/Kconfig ++## ++# CONFIG_OPROFILE is not set ++ ++## ++## file: arch/mips/Kconfig ++## ++## choice: System type ++# CONFIG_MIPS_COBALT is not set ++# CONFIG_MACH_DECSTATION is not set ++# CONFIG_MACH_JAZZ is not set ++# CONFIG_LASAT is not set ++# CONFIG_MIPS_MALTA is not set ++# CONFIG_MIPS_SIM is not set ++# CONFIG_MACH_VR41XX is not set ++# CONFIG_PNX8550_JBS is not set ++# CONFIG_PMC_YOSEMITE is not set ++CONFIG_SGI_IP22=y ++# CONFIG_SGI_IP27 is not set ++# CONFIG_SGI_IP32 is not set ++# CONFIG_SIBYTE_CRHINE is not set ++# CONFIG_SIBYTE_CARMEL is not set ++# CONFIG_SIBYTE_CRHONE is not set ++# CONFIG_SIBYTE_RHONE is not set ++# CONFIG_SIBYTE_SWARM is not set ++# CONFIG_SIBYTE_LITTLESUR is not set ++# CONFIG_SIBYTE_SENTOSA is not set ++# CONFIG_SIBYTE_BIGSUR is not set ++## end choice ++CONFIG_ARC_CONSOLE=y ++## choice: CPU type ++# CONFIG_CPU_MIPS32_R1 is not set ++# CONFIG_CPU_MIPS32_R2 is not set ++# CONFIG_CPU_MIPS64_R1 is not set ++# CONFIG_CPU_MIPS64_R2 is not set ++# CONFIG_CPU_R3000 is not set ++# CONFIG_CPU_TX39XX is not set ++# CONFIG_CPU_VR41XX is not set ++# CONFIG_CPU_R4300 is not set ++CONFIG_CPU_R4X00=y ++# CONFIG_CPU_TX49XX is not set ++# CONFIG_CPU_R5000 is not set ++# CONFIG_CPU_R5432 is not set ++# CONFIG_CPU_R6000 is not set ++# CONFIG_CPU_NEVADA is not set ++# CONFIG_CPU_R8000 is not set ++# CONFIG_CPU_R10000 is not set ++# CONFIG_CPU_RM7000 is not set ++# CONFIG_CPU_RM9000 is not set ++# CONFIG_CPU_SB1 is not set ++## end choice ++## choice: Kernel code model ++# CONFIG_32BIT is not set ++CONFIG_64BIT=y ++## end choice ++## choice: Kernel page size ++CONFIG_PAGE_SIZE_4KB=y ++# CONFIG_PAGE_SIZE_8KB is not set ++# CONFIG_PAGE_SIZE_16KB is not set ++# CONFIG_PAGE_SIZE_64KB is not set ++## end choice ++CONFIG_EISA=y ++CONFIG_MIPS32_COMPAT=y ++CONFIG_MIPS32_O32=y ++CONFIG_MIPS32_N32=y ++ ++## ++## file: arch/mips/alchemy/Kconfig ++## ++## choice: Machine type ++# CONFIG_MIPS_MTX1 is not set ++# CONFIG_MIPS_BOSPORUS is not set ++# CONFIG_MIPS_DB1000 is not set ++# CONFIG_MIPS_DB1100 is not set ++# CONFIG_MIPS_DB1200 is not set ++# CONFIG_MIPS_DB1500 is not set ++# CONFIG_MIPS_DB1550 is not set ++# CONFIG_MIPS_MIRAGE is not set ++# CONFIG_MIPS_PB1000 is not set ++# CONFIG_MIPS_PB1100 is not set ++# CONFIG_MIPS_PB1200 is not set ++# CONFIG_MIPS_PB1500 is not set ++# CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_XXS1500 is not set ++## end choice ++ ++## ++## file: arch/mips/Kconfig.debug ++## ++CONFIG_CMDLINE="" ++ ++## ++## file: arch/mips/txx9/Kconfig ++## ++# CONFIG_TOSHIBA_JMR3927 is not set ++# CONFIG_TOSHIBA_RBTX4927 is not set ++# CONFIG_TOSHIBA_RBTX4938 is not set ++ ++## ++## file: drivers/ata/Kconfig ++## ++# CONFIG_ATA is not set ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_DEV_RAM_SIZE=8192 ++# CONFIG_CDROM_PKTCDVD is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++# CONFIG_PPDEV is not set ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++# CONFIG_TELCLOCK is not set ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++# CONFIG_IPMI_HANDLER is not set ++ ++## ++## file: drivers/char/tpm/Kconfig ++## ++# CONFIG_TCG_TPM is not set ++ ++## ++## file: drivers/eisa/Kconfig ++## ++CONFIG_EISA_NAMES=y ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_HWMON=y ++# CONFIG_HWMON_DEBUG_CHIP is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM75 is not set ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=m ++CONFIG_I2C_CHARDEV=m ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++# CONFIG_I2C_PARPORT is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_ELEKTOR is not set ++# CONFIG_I2C_PCA_ISA is not set ++# CONFIG_I2C_STUB is not set ++ ++## ++## file: drivers/input/Kconfig ++## ++# CONFIG_INPUT_JOYDEV is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++# CONFIG_GAMEPORT is not set ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++# CONFIG_INPUT_JOYSTICK is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++# CONFIG_INPUT_MISC is not set ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_INPORT is not set ++# CONFIG_MOUSE_LOGIBM is not set ++# CONFIG_MOUSE_PC110PAD is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++CONFIG_SERIO_I8042=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_PARKBD is not set ++CONFIG_SERIO_LIBPS2=y ++CONFIG_SERIO_RAW=y ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_INPUT_TOUCHSCREEN is not set ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++# CONFIG_RADIO_CADET is not set ++# CONFIG_RADIO_RTRACK is not set ++# CONFIG_RADIO_RTRACK2 is not set ++# CONFIG_RADIO_AZTECH is not set ++# CONFIG_RADIO_GEMTEK is not set ++# CONFIG_RADIO_SF16FMI is not set ++# CONFIG_RADIO_SF16FMR2 is not set ++# CONFIG_RADIO_TERRATEC is not set ++# CONFIG_RADIO_TRUST is not set ++# CONFIG_RADIO_TYPHOON is not set ++# CONFIG_RADIO_ZOLTRIX is not set ++ ++## ++## file: drivers/media/video/Kconfig ++## ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_PMS is not set ++# CONFIG_VIDEO_BWQCAM is not set ++# CONFIG_VIDEO_CQCAM is not set ++# CONFIG_VIDEO_W9966 is not set ++CONFIG_VIDEO_VINO=m ++ ++## ++## file: drivers/message/fusion/Kconfig ++## ++# CONFIG_FUSION is not set ++ ++## ++## file: drivers/mmc/Kconfig ++## ++# CONFIG_MMC is not set ++ ++## ++## file: drivers/mtd/Kconfig ++## ++# CONFIG_MTD is not set ++ ++## ++## file: drivers/net/appletalk/Kconfig ++## ++# CONFIG_ATALK is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++# CONFIG_NET_VENDOR_3COM is not set ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_E2100=m ++CONFIG_HPLAN_PLUS=m ++CONFIG_HPLAN=m ++CONFIG_NE2000=m ++CONFIG_ULTRA=m ++CONFIG_ULTRA32=m ++CONFIG_WD80x3=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++# CONFIG_DEPCA is not set ++ ++## ++## file: drivers/net/ethernet/davicom/Kconfig ++## ++# CONFIG_DM9000 is not set ++ ++## ++## file: drivers/net/ethernet/dec/Kconfig ++## ++CONFIG_EWRK3=m ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++# CONFIG_NET_TULIP is not set ++ ++## ++## file: drivers/net/ethernet/fujitsu/Kconfig ++## ++# CONFIG_AT1700 is not set ++CONFIG_ETH16I=m ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++# CONFIG_HP100 is not set ++ ++## ++## file: drivers/net/ethernet/i825xx/Kconfig ++## ++CONFIG_EEXPRESS=m ++CONFIG_EEXPRESS_PRO=m ++CONFIG_LP486E=m ++ ++## ++## file: drivers/net/ethernet/racal/Kconfig ++## ++# CONFIG_NET_VENDOR_RACAL is not set ++ ++## ++## file: drivers/net/ethernet/seeq/Kconfig ++## ++CONFIG_SEEQ8005=m ++CONFIG_SGISEEQ=y ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_SMC9194=m ++CONFIG_SMC91X=m ++ ++## ++## file: drivers/net/phy/Kconfig ++## ++# CONFIG_PHYLIB is not set ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++# CONFIG_TR is not set ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/pnp/Kconfig ++## ++# CONFIG_PNP is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_DS1286=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_SCSI_LOGGING is not set ++CONFIG_SGIWD93_SCSI=y ++# CONFIG_SCSI_AHA1740 is not set ++# CONFIG_SCSI_AIC7XXX_OLD is not set ++# CONFIG_SCSI_IN2000 is not set ++# CONFIG_SCSI_DTC3280 is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_GENERIC_NCR5380 is not set ++# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set ++# CONFIG_SCSI_NCR53C406A is not set ++# CONFIG_SCSI_PAS16 is not set ++# CONFIG_SCSI_QLOGIC_FAS is not set ++# CONFIG_SCSI_SIM710 is not set ++# CONFIG_SCSI_SYM53C416 is not set ++# CONFIG_SCSI_T128 is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++# CONFIG_SCSI_AIC7XXX is not set ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI=y ++CONFIG_SPI_BITBANG=m ++CONFIG_SPI_BUTTERFLY=m ++ ++## ++## file: drivers/telephony/Kconfig ++## ++# CONFIG_PHONE is not set ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++# CONFIG_SERIAL_8250 is not set ++CONFIG_SERIAL_IP22_ZILOG=y ++CONFIG_SERIAL_IP22_ZILOG_CONSOLE=y ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_VIRTUAL is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++# CONFIG_MDA_CONSOLE is not set ++CONFIG_SGI_NEWPORT_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: drivers/w1/Kconfig ++## ++# CONFIG_W1 is not set ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_INDYDOG=m ++# CONFIG_PCWATCHDOG is not set ++# CONFIG_MIXCOMWD is not set ++# CONFIG_WDT is not set ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_SGI_PARTITION=y ++CONFIG_KARMA_PARTITION=y ++ ++## ++## file: init/Kconfig ++## ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/ax25/Kconfig ++## ++# CONFIG_HAMRADIO is not set ++ ++## ++## file: net/bluetooth/Kconfig ++## ++# CONFIG_BT is not set ++ ++## ++## file: net/decnet/Kconfig ++## ++# CONFIG_DECNET is not set ++ ++## ++## file: net/ipx/Kconfig ++## ++# CONFIG_IPX is not set ++ ++## ++## file: net/irda/Kconfig ++## ++# CONFIG_IRDA is not set ++ ++## ++## file: net/lapb/Kconfig ++## ++# CONFIG_LAPB is not set ++ ++## ++## file: sound/drivers/Kconfig ++## ++# CONFIG_SND_DUMMY is not set ++# CONFIG_SND_MTPAV is not set ++# CONFIG_SND_SERIAL_U16550 is not set ++# CONFIG_SND_MPU401 is not set ++ ++## ++## file: sound/mips/Kconfig ++## ++CONFIG_SND_MIPS=y ++CONFIG_SND_SGI_HAL2=m ++ +diff --git a/debian/config/mips/config.r5k-ip32 b/debian/config/mips/config.r5k-ip32 +new file mode 100644 +index 0000000..449af7d +--- /dev/null ++++ b/debian/config/mips/config.r5k-ip32 +@@ -0,0 +1,684 @@ ++## ++## file: arch/Kconfig ++## ++# CONFIG_OPROFILE is not set ++ ++## ++## file: arch/mips/Kconfig ++## ++## choice: System type ++# CONFIG_MIPS_COBALT is not set ++# CONFIG_MACH_DECSTATION is not set ++# CONFIG_MACH_JAZZ is not set ++# CONFIG_LASAT is not set ++# CONFIG_MIPS_MALTA is not set ++# CONFIG_MIPS_SIM is not set ++# CONFIG_MACH_VR41XX is not set ++# CONFIG_PNX8550_JBS is not set ++# CONFIG_PMC_YOSEMITE is not set ++# CONFIG_SGI_IP22 is not set ++# CONFIG_SGI_IP27 is not set ++CONFIG_SGI_IP32=y ++# CONFIG_SIBYTE_CRHINE is not set ++# CONFIG_SIBYTE_CARMEL is not set ++# CONFIG_SIBYTE_CRHONE is not set ++# CONFIG_SIBYTE_RHONE is not set ++# CONFIG_SIBYTE_SWARM is not set ++# CONFIG_SIBYTE_LITTLESUR is not set ++# CONFIG_SIBYTE_SENTOSA is not set ++# CONFIG_SIBYTE_BIGSUR is not set ++## end choice ++## choice: CPU type ++# CONFIG_CPU_MIPS32_R1 is not set ++# CONFIG_CPU_MIPS32_R2 is not set ++# CONFIG_CPU_MIPS64_R1 is not set ++# CONFIG_CPU_MIPS64_R2 is not set ++# CONFIG_CPU_R3000 is not set ++# CONFIG_CPU_TX39XX is not set ++# CONFIG_CPU_VR41XX is not set ++# CONFIG_CPU_R4300 is not set ++# CONFIG_CPU_R4X00 is not set ++# CONFIG_CPU_TX49XX is not set ++CONFIG_CPU_R5000=y ++# CONFIG_CPU_R5432 is not set ++# CONFIG_CPU_R6000 is not set ++# CONFIG_CPU_NEVADA is not set ++# CONFIG_CPU_R8000 is not set ++# CONFIG_CPU_R10000 is not set ++# CONFIG_CPU_RM7000 is not set ++# CONFIG_CPU_RM9000 is not set ++# CONFIG_CPU_SB1 is not set ++## end choice ++## choice: Kernel code model ++# CONFIG_32BIT is not set ++CONFIG_64BIT=y ++## end choice ++## choice: Kernel page size ++CONFIG_PAGE_SIZE_4KB=y ++# CONFIG_PAGE_SIZE_8KB is not set ++# CONFIG_PAGE_SIZE_16KB is not set ++# CONFIG_PAGE_SIZE_64KB is not set ++## end choice ++CONFIG_PCI=y ++CONFIG_MIPS32_COMPAT=y ++CONFIG_MIPS32_O32=y ++CONFIG_MIPS32_N32=y ++ ++## ++## file: arch/mips/alchemy/Kconfig ++## ++## choice: Machine type ++# CONFIG_MIPS_MTX1 is not set ++# CONFIG_MIPS_BOSPORUS is not set ++# CONFIG_MIPS_DB1000 is not set ++# CONFIG_MIPS_DB1100 is not set ++# CONFIG_MIPS_DB1200 is not set ++# CONFIG_MIPS_DB1500 is not set ++# CONFIG_MIPS_DB1550 is not set ++# CONFIG_MIPS_MIRAGE is not set ++# CONFIG_MIPS_PB1000 is not set ++# CONFIG_MIPS_PB1100 is not set ++# CONFIG_MIPS_PB1200 is not set ++# CONFIG_MIPS_PB1500 is not set ++# CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_XXS1500 is not set ++## end choice ++ ++## ++## file: arch/mips/Kconfig.debug ++## ++CONFIG_CMDLINE="" ++ ++## ++## file: arch/mips/txx9/Kconfig ++## ++# CONFIG_TOSHIBA_JMR3927 is not set ++# CONFIG_TOSHIBA_RBTX4927 is not set ++# CONFIG_TOSHIBA_RBTX4938 is not set ++ ++## ++## file: drivers/ata/Kconfig ++## ++# CONFIG_ATA is not set ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_DEV_RAM_SIZE=8192 ++# CONFIG_CDROM_PKTCDVD is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++# CONFIG_PPDEV is not set ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++# CONFIG_APPLICOM is not set ++# CONFIG_TELCLOCK is not set ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++# CONFIG_IPMI_HANDLER is not set ++ ++## ++## file: drivers/char/tpm/Kconfig ++## ++# CONFIG_TCG_TPM is not set ++ ++## ++## file: drivers/firewire/Kconfig ++## ++# CONFIG_FIREWIRE is not set ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++# CONFIG_DRM is not set ++ ++## ++## file: drivers/hid/usbhid/Kconfig ++## ++CONFIG_USB_KBD=m ++CONFIG_USB_MOUSE=m ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_HWMON=y ++# CONFIG_HWMON_DEBUG_CHIP is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM75 is not set ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_SIS5595 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_VIA686A is not set ++# CONFIG_SENSORS_VT8231 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=m ++CONFIG_I2C_CHARDEV=m ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++# 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_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 ++# CONFIG_I2C_PARPORT is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_PCA_ISA is not set ++# CONFIG_I2C_STUB is not set ++# CONFIG_SCx200_ACB is not set ++ ++## ++## file: drivers/infiniband/Kconfig ++## ++# CONFIG_INFINIBAND is not set ++ ++## ++## file: drivers/input/Kconfig ++## ++# CONFIG_INPUT_JOYDEV is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++# CONFIG_GAMEPORT is not set ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++# CONFIG_INPUT_JOYSTICK is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_SGI_BTNS=m ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++# CONFIG_SERIO_I8042 is not set ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_PARKBD is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_MACEPS2=y ++CONFIG_SERIO_LIBPS2=y ++CONFIG_SERIO_RAW=y ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_INPUT_TOUCHSCREEN is not set ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++# CONFIG_RADIO_MAXIRADIO is not set ++ ++## ++## file: drivers/media/video/Kconfig ++## ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_BWQCAM is not set ++# CONFIG_VIDEO_CQCAM is not set ++# CONFIG_VIDEO_W9966 is not set ++# CONFIG_VIDEO_MXB is not set ++# CONFIG_VIDEO_HEXIUM_ORION is not set ++# CONFIG_VIDEO_HEXIUM_GEMINI is not set ++ ++## ++## file: drivers/media/video/bt8xx/Kconfig ++## ++# CONFIG_VIDEO_BT848 is not set ++ ++## ++## file: drivers/media/video/cx88/Kconfig ++## ++# CONFIG_VIDEO_CX88 is not set ++ ++## ++## file: drivers/media/video/saa7134/Kconfig ++## ++# CONFIG_VIDEO_SAA7134 is not set ++ ++## ++## file: drivers/message/fusion/Kconfig ++## ++# CONFIG_FUSION is not set ++# CONFIG_FUSION_SPI is not set ++# CONFIG_FUSION_FC is not set ++# CONFIG_FUSION_SAS is not set ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++# CONFIG_I2O is not set ++ ++## ++## file: drivers/mmc/Kconfig ++## ++# CONFIG_MMC is not set ++ ++## ++## file: drivers/mtd/Kconfig ++## ++# CONFIG_MTD is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++# CONFIG_NET_VENDOR_3COM is not set ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++# CONFIG_BNX2 is not set ++# CONFIG_TIGON3 is not set ++# CONFIG_BNX2X is not set ++ ++## ++## file: drivers/net/ethernet/chelsio/Kconfig ++## ++# CONFIG_CHELSIO_T1 is not set ++ ++## ++## file: drivers/net/ethernet/davicom/Kconfig ++## ++# CONFIG_DM9000 is not set ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++CONFIG_NET_TULIP=y ++CONFIG_DE2104X=m ++CONFIG_TULIP=m ++CONFIG_WINBOND_840=m ++CONFIG_DM9102=m ++CONFIG_ULI526X=m ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++# CONFIG_DL2K is not set ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++CONFIG_E100=m ++# CONFIG_E1000 is not set ++# CONFIG_IXGB is not set ++ ++## ++## file: drivers/net/ethernet/marvell/Kconfig ++## ++# CONFIG_SKGE is not set ++# CONFIG_SKY2 is not set ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++# CONFIG_NS83820 is not set ++ ++## ++## file: drivers/net/ethernet/neterion/Kconfig ++## ++# CONFIG_S2IO is not set ++ ++## ++## file: drivers/net/ethernet/packetengines/Kconfig ++## ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++ ++## ++## file: drivers/net/ethernet/sgi/Kconfig ++## ++CONFIG_SGI_O2MACE_ETH=y ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++# CONFIG_SIS190 is not set ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++ ++## ++## file: drivers/net/phy/Kconfig ++## ++# CONFIG_PHYLIB is not set ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++# CONFIG_TR is not set ++ ++## ++## file: drivers/parport/Kconfig ++## ++CONFIG_PARPORT_IP32=m ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++# CONFIG_HOTPLUG_PCI is not set ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_CMOS=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX_OLD 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_SYM53C8XX_2 is not set ++# CONFIG_SCSI_IPR is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_LPFC is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_DC390T is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic79xx ++## ++# CONFIG_SCSI_AIC79XX is not set ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++CONFIG_SCSI_AIC7XXX=y ++CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 ++CONFIG_AIC7XXX_RESET_DELAY_MS=15000 ++CONFIG_AIC7XXX_DEBUG_ENABLE=y ++CONFIG_AIC7XXX_DEBUG_MASK=0 ++CONFIG_AIC7XXX_REG_PRETTY_PRINT=y ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++ ++## ++## file: drivers/scsi/qla2xxx/Kconfig ++## ++# CONFIG_SCSI_QLA_FC is not set ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI=y ++CONFIG_SPI_BITBANG=m ++CONFIG_SPI_BUTTERFLY=m ++ ++## ++## file: drivers/telephony/Kconfig ++## ++# CONFIG_PHONE is not set ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=4 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++# CONFIG_SERIAL_8250_EXTENDED is not set ++# CONFIG_SERIAL_JSM is not set ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++CONFIG_FB_GBE=y ++CONFIG_FB_GBE_MEM=4 ++# CONFIG_FB_S1D13XXX 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_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_TRIDENT is not set ++# CONFIG_FB_VIRTUAL is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: drivers/w1/Kconfig ++## ++# CONFIG_W1 is not set ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++# CONFIG_PCIPCWATCHDOG is not set ++# CONFIG_WDTPCI is not set ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_SGI_PARTITION=y ++CONFIG_KARMA_PARTITION=y ++ ++## ++## file: init/Kconfig ++## ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/ipv4/Kconfig ++## ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++ ++## ++## file: sound/drivers/Kconfig ++## ++# CONFIG_SND_DUMMY is not set ++# CONFIG_SND_MTPAV is not set ++# CONFIG_SND_SERIAL_U16550 is not set ++# CONFIG_SND_MPU401 is not set ++ ++## ++## file: sound/mips/Kconfig ++## ++CONFIG_SND_MIPS=y ++CONFIG_SND_SGI_O2=m ++ ++## ++## file: sound/pci/Kconfig ++## ++# CONFIG_SND_AD1889 is not set ++# CONFIG_SND_ALI5451 is not set ++# CONFIG_SND_ATIIXP is not set ++# CONFIG_SND_ATIIXP_MODEM is not set ++# CONFIG_SND_AU8810 is not set ++# CONFIG_SND_AU8820 is not set ++# CONFIG_SND_AU8830 is not set ++# CONFIG_SND_AZT3328 is not set ++# CONFIG_SND_BT87X is not set ++CONFIG_SND_BT87X_OVERCLOCK=y ++# CONFIG_SND_CA0106 is not set ++# CONFIG_SND_CMIPCI is not set ++# CONFIG_SND_CS4281 is not set ++# CONFIG_SND_CS46XX is not set ++CONFIG_SND_CS46XX_NEW_DSP=y ++# CONFIG_SND_EMU10K1 is not set ++# CONFIG_SND_EMU10K1X is not set ++# CONFIG_SND_ENS1370 is not set ++# CONFIG_SND_ENS1371 is not set ++# CONFIG_SND_ES1938 is not set ++# CONFIG_SND_ES1968 is not set ++# CONFIG_SND_FM801 is not set ++CONFIG_SND_FM801_TEA575X_BOOL=y ++# CONFIG_SND_HDSP is not set ++# CONFIG_SND_HDSPM is not set ++# CONFIG_SND_ICE1712 is not set ++# CONFIG_SND_ICE1724 is not set ++# CONFIG_SND_INTEL8X0 is not set ++# CONFIG_SND_INTEL8X0M is not set ++CONFIG_SND_KORG1212=m ++# CONFIG_SND_MAESTRO3 is not set ++# CONFIG_SND_MIXART is not set ++# CONFIG_SND_NM256 is not set ++# CONFIG_SND_PCXHR is not set ++# CONFIG_SND_RME32 is not set ++# CONFIG_SND_RME96 is not set ++# CONFIG_SND_RME9652 is not set ++# CONFIG_SND_SONICVIBES is not set ++# CONFIG_SND_TRIDENT is not set ++# CONFIG_SND_VIA82XX is not set ++# CONFIG_SND_VIA82XX_MODEM is not set ++# CONFIG_SND_VX222 is not set ++# CONFIG_SND_YMFPCI is not set ++ ++## ++## file: sound/pci/hda/Kconfig ++## ++# CONFIG_SND_HDA_INTEL is not set ++ +diff --git a/debian/config/mips/config.sb1-bcm91250a b/debian/config/mips/config.sb1-bcm91250a +new file mode 100644 +index 0000000..73c5f78 +--- /dev/null ++++ b/debian/config/mips/config.sb1-bcm91250a +@@ -0,0 +1,801 @@ ++## ++## file: arch/Kconfig ++## ++# CONFIG_OPROFILE is not set ++ ++## ++## file: arch/mips/Kconfig ++## ++## choice: System type ++# CONFIG_MIPS_COBALT is not set ++# CONFIG_MACH_DECSTATION is not set ++# CONFIG_MACH_JAZZ is not set ++# CONFIG_LASAT is not set ++# CONFIG_MIPS_MALTA is not set ++# CONFIG_MIPS_SIM is not set ++# CONFIG_MACH_VR41XX is not set ++# CONFIG_PNX8550_JBS is not set ++# CONFIG_PMC_YOSEMITE is not set ++# CONFIG_SGI_IP22 is not set ++# CONFIG_SGI_IP27 is not set ++# CONFIG_SGI_IP32 is not set ++# CONFIG_SIBYTE_CRHINE is not set ++# CONFIG_SIBYTE_CARMEL is not set ++# CONFIG_SIBYTE_CRHONE is not set ++# CONFIG_SIBYTE_RHONE is not set ++CONFIG_SIBYTE_SWARM=y ++# CONFIG_SIBYTE_LITTLESUR is not set ++# CONFIG_SIBYTE_SENTOSA is not set ++# CONFIG_SIBYTE_BIGSUR is not set ++## end choice ++## choice: CPU type ++# CONFIG_CPU_MIPS32_R1 is not set ++# CONFIG_CPU_MIPS32_R2 is not set ++# CONFIG_CPU_MIPS64_R1 is not set ++# CONFIG_CPU_MIPS64_R2 is not set ++# CONFIG_CPU_R3000 is not set ++# CONFIG_CPU_TX39XX is not set ++# CONFIG_CPU_VR41XX is not set ++# CONFIG_CPU_R4300 is not set ++# CONFIG_CPU_R4X00 is not set ++# CONFIG_CPU_TX49XX is not set ++# CONFIG_CPU_R5000 is not set ++# CONFIG_CPU_R5432 is not set ++# CONFIG_CPU_R6000 is not set ++# CONFIG_CPU_NEVADA is not set ++# CONFIG_CPU_R8000 is not set ++# CONFIG_CPU_R10000 is not set ++# CONFIG_CPU_RM7000 is not set ++# CONFIG_CPU_RM9000 is not set ++CONFIG_CPU_SB1=y ++## end choice ++## choice: Kernel code model ++# CONFIG_32BIT is not set ++CONFIG_64BIT=y ++## end choice ++## choice: Kernel page size ++CONFIG_PAGE_SIZE_4KB=y ++# CONFIG_PAGE_SIZE_8KB is not set ++# CONFIG_PAGE_SIZE_16KB is not set ++# CONFIG_PAGE_SIZE_64KB is not set ++## end choice ++# CONFIG_SIBYTE_DMA_PAGEOPS is not set ++CONFIG_SMP=y ++CONFIG_NR_CPUS=2 ++CONFIG_PCI=y ++CONFIG_MIPS32_COMPAT=y ++CONFIG_MIPS32_O32=y ++CONFIG_MIPS32_N32=y ++ ++## ++## file: arch/mips/alchemy/Kconfig ++## ++## choice: Machine type ++# CONFIG_MIPS_MTX1 is not set ++# CONFIG_MIPS_BOSPORUS is not set ++# CONFIG_MIPS_DB1000 is not set ++# CONFIG_MIPS_DB1100 is not set ++# CONFIG_MIPS_DB1200 is not set ++# CONFIG_MIPS_DB1500 is not set ++# CONFIG_MIPS_DB1550 is not set ++# CONFIG_MIPS_MIRAGE is not set ++# CONFIG_MIPS_PB1000 is not set ++# CONFIG_MIPS_PB1100 is not set ++# CONFIG_MIPS_PB1200 is not set ++# CONFIG_MIPS_PB1500 is not set ++# CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_XXS1500 is not set ++## end choice ++ ++## ++## file: arch/mips/Kconfig.debug ++## ++CONFIG_CMDLINE="" ++# CONFIG_SB1XXX_CORELIS is not set ++ ++## ++## file: arch/mips/sibyte/Kconfig ++## ++## choice: SiByte SOC Stepping ++# CONFIG_CPU_SB1_PASS_1 is not set ++# CONFIG_CPU_SB1_PASS_2_1250 is not set ++CONFIG_CPU_SB1_PASS_2_2=y ++# CONFIG_CPU_SB1_PASS_4 is not set ++# CONFIG_CPU_SB1_PASS_2_112x is not set ++# CONFIG_CPU_SB1_PASS_3 is not set ++## end choice ++# CONFIG_SB1_CEX_ALWAYS_FATAL is not set ++# CONFIG_SB1_CERR_STALL is not set ++# CONFIG_SIBYTE_CFE_CONSOLE is not set ++# CONFIG_SIBYTE_BUS_WATCHER is not set ++# CONFIG_SIBYTE_TBPROF is not set ++ ++## ++## file: arch/mips/txx9/Kconfig ++## ++# CONFIG_TOSHIBA_JMR3927 is not set ++# CONFIG_TOSHIBA_RBTX4927 is not set ++# CONFIG_TOSHIBA_RBTX4938 is not set ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=y ++CONFIG_SATA_AHCI=m ++CONFIG_SATA_SIL24=m ++CONFIG_PDC_ADMA=m ++CONFIG_SATA_QSTOR=m ++CONFIG_SATA_SX4=m ++CONFIG_ATA_PIIX=m ++CONFIG_SATA_MV=m ++CONFIG_SATA_NV=m ++CONFIG_SATA_PROMISE=m ++CONFIG_SATA_SIL=m ++CONFIG_SATA_SIS=m ++CONFIG_SATA_SVW=m ++CONFIG_SATA_ULI=m ++CONFIG_SATA_VIA=m ++CONFIG_SATA_VITESSE=m ++CONFIG_PATA_ALI=m ++CONFIG_PATA_AMD=m ++CONFIG_PATA_CMD64X=m ++CONFIG_PATA_CS5530=m ++CONFIG_PATA_CYPRESS=y ++CONFIG_PATA_EFAR=m ++CONFIG_PATA_NS87415=m ++CONFIG_PATA_OLDPIIX=m ++CONFIG_PATA_PDC2027X=m ++CONFIG_PATA_PDC_OLD=m ++CONFIG_PATA_SC1200=m ++CONFIG_PATA_SERVERWORKS=m ++CONFIG_PATA_SIL680=m ++CONFIG_PATA_TRIFLEX=m ++CONFIG_PATA_VIA=m ++CONFIG_PATA_MPIIX=m ++CONFIG_PATA_PLATFORM=y ++ ++## ++## file: drivers/block/Kconfig ++## ++# CONFIG_BLK_CPQ_DA 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_SX8 is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM_SIZE=8192 ++# CONFIG_CDROM_PKTCDVD is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++# CONFIG_PPDEV is not set ++CONFIG_RTC=m ++CONFIG_GEN_RTC=y ++CONFIG_GEN_RTC_X=y ++# CONFIG_DTLK is not set ++# CONFIG_APPLICOM is not set ++# CONFIG_TELCLOCK is not set ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++# CONFIG_IPMI_HANDLER is not set ++ ++## ++## file: drivers/char/tpm/Kconfig ++## ++# CONFIG_TCG_TPM is not set ++ ++## ++## file: drivers/firewire/Kconfig ++## ++# CONFIG_FIREWIRE is not set ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++# CONFIG_DRM is not set ++ ++## ++## file: drivers/hid/usbhid/Kconfig ++## ++CONFIG_USB_HID=m ++# CONFIG_USB_KBD is not set ++# CONFIG_USB_MOUSE is not set ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_HWMON=y ++# CONFIG_HWMON_DEBUG_CHIP is not set ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM75 is not set ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_SIS5595 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_VIA686A is not set ++CONFIG_SENSORS_VT8231=m ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=m ++CONFIG_I2C_CHARDEV=m ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++# 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_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 ++# CONFIG_I2C_PARPORT is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_PCA_ISA is not set ++CONFIG_I2C_SIBYTE=m ++CONFIG_I2C_STUB=m ++# CONFIG_SCx200_ACB is not set ++ ++## ++## file: drivers/infiniband/Kconfig ++## ++# CONFIG_INFINIBAND is not set ++ ++## ++## file: drivers/input/Kconfig ++## ++# CONFIG_INPUT_JOYDEV is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++# CONFIG_GAMEPORT is not set ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++# CONFIG_INPUT_JOYSTICK is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++# CONFIG_INPUT_MISC is not set ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++# CONFIG_SERIO_I8042 is not set ++# CONFIG_SERIO_SERPORT is not set ++# CONFIG_SERIO_PARKBD is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_INPUT_TOUCHSCREEN is not set ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++# CONFIG_RADIO_MAXIRADIO is not set ++# CONFIG_USB_DSBR is not set ++ ++## ++## file: drivers/media/video/Kconfig ++## ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_BWQCAM is not set ++# CONFIG_VIDEO_CQCAM is not set ++# CONFIG_VIDEO_W9966 is not set ++# CONFIG_VIDEO_MXB is not set ++# CONFIG_VIDEO_HEXIUM_ORION is not set ++# CONFIG_VIDEO_HEXIUM_GEMINI is not set ++ ++## ++## file: drivers/media/video/bt8xx/Kconfig ++## ++# CONFIG_VIDEO_BT848 is not set ++ ++## ++## file: drivers/media/video/cx88/Kconfig ++## ++# CONFIG_VIDEO_CX88 is not set ++ ++## ++## file: drivers/media/video/em28xx/Kconfig ++## ++# CONFIG_VIDEO_EM28XX is not set ++ ++## ++## file: drivers/media/video/et61x251/Kconfig ++## ++CONFIG_USB_ET61X251=m ++ ++## ++## file: drivers/media/video/pwc/Kconfig ++## ++# CONFIG_USB_PWC is not set ++ ++## ++## file: drivers/media/video/saa7134/Kconfig ++## ++# CONFIG_VIDEO_SAA7134 is not set ++ ++## ++## file: drivers/media/video/sn9c102/Kconfig ++## ++# CONFIG_USB_SN9C102 is not set ++ ++## ++## file: drivers/media/video/zoran/Kconfig ++## ++# CONFIG_VIDEO_ZORAN is not set ++ ++## ++## file: drivers/message/fusion/Kconfig ++## ++# CONFIG_FUSION is not set ++# CONFIG_FUSION_SPI is not set ++# CONFIG_FUSION_FC is not set ++# CONFIG_FUSION_SAS is not set ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++# CONFIG_I2O is not set ++ ++## ++## file: drivers/mmc/Kconfig ++## ++# CONFIG_MMC is not set ++ ++## ++## file: drivers/mtd/Kconfig ++## ++# CONFIG_MTD is not set ++ ++## ++## file: drivers/net/Kconfig ++## ++# CONFIG_NET_FC is not set ++ ++## ++## file: drivers/net/appletalk/Kconfig ++## ++# CONFIG_ATALK is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/Kconfig ++## ++CONFIG_FEALNX=m ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++# CONFIG_NET_VENDOR_3COM is not set ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_NE2K_PCI=m ++ ++## ++## file: drivers/net/ethernet/adaptec/Kconfig ++## ++CONFIG_ADAPTEC_STARFIRE=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_AMD8111_ETH=m ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++CONFIG_B44=m ++CONFIG_SB1250_MAC=y ++ ++## ++## file: drivers/net/ethernet/chelsio/Kconfig ++## ++# CONFIG_CHELSIO_T1 is not set ++ ++## ++## file: drivers/net/ethernet/davicom/Kconfig ++## ++# CONFIG_DM9000 is not set ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++# CONFIG_NET_TULIP is not set ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++CONFIG_SUNDANCE=m ++# CONFIG_SUNDANCE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++# CONFIG_HP100 is not set ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++CONFIG_E100=m ++# CONFIG_IXGB is not set ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_NATSEMI=m ++ ++## ++## file: drivers/net/ethernet/neterion/Kconfig ++## ++# CONFIG_S2IO is not set ++ ++## ++## file: drivers/net/ethernet/nvidia/Kconfig ++## ++CONFIG_FORCEDETH=m ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_8139CP=m ++CONFIG_8139TOO=m ++CONFIG_8139TOO_PIO=y ++# CONFIG_8139TOO_TUNE_TWISTER is not set ++CONFIG_8139TOO_8129=y ++# CONFIG_8139_OLD_RX_RESET is not set ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++CONFIG_SIS900=m ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_EPIC100=m ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++CONFIG_VIA_RHINE=m ++# CONFIG_VIA_RHINE_MMIO is not set ++ ++## ++## file: drivers/net/fddi/Kconfig ++## ++# CONFIG_FDDI is not set ++ ++## ++## file: drivers/net/hippi/Kconfig ++## ++# CONFIG_HIPPI is not set ++ ++## ++## file: drivers/net/phy/Kconfig ++## ++CONFIG_BROADCOM_PHY=y ++ ++## ++## file: drivers/net/plip/Kconfig ++## ++# CONFIG_PLIP is not set ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++# CONFIG_TR is not set ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++# CONFIG_WAN is not set ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++# CONFIG_HOTPLUG_PCI is not set ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++CONFIG_SCSI_DMX3191D=m ++CONFIG_SCSI_FUTURE_DOMAIN=m ++CONFIG_SCSI_IPS=m ++CONFIG_SCSI_INITIO=m ++CONFIG_SCSI_INIA100=m ++CONFIG_SCSI_SYM53C8XX_2=m ++CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 ++CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 ++CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 ++# CONFIG_SCSI_IPR is not set ++CONFIG_SCSI_QLOGIC_1280=m ++CONFIG_SCSI_DC395x=m ++CONFIG_SCSI_DC390T=m ++CONFIG_SCSI_DEBUG=m ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic79xx ++## ++CONFIG_SCSI_AIC79XX=m ++CONFIG_AIC79XX_CMDS_PER_DEVICE=32 ++CONFIG_AIC79XX_RESET_DELAY_MS=15000 ++CONFIG_AIC79XX_DEBUG_ENABLE=y ++CONFIG_AIC79XX_DEBUG_MASK=0 ++CONFIG_AIC79XX_REG_PRETTY_PRINT=y ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++CONFIG_SCSI_AIC7XXX=y ++CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 ++CONFIG_AIC7XXX_RESET_DELAY_MS=15000 ++CONFIG_AIC7XXX_DEBUG_ENABLE=y ++CONFIG_AIC7XXX_DEBUG_MASK=0 ++CONFIG_AIC7XXX_REG_PRETTY_PRINT=y ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++# CONFIG_MEGARAID_NEWGEN is not set ++CONFIG_MEGARAID_LEGACY=m ++CONFIG_MEGARAID_SAS=m ++ ++## ++## file: drivers/scsi/qla2xxx/Kconfig ++## ++CONFIG_SCSI_QLA_FC=m ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI=y ++CONFIG_SPI_BITBANG=m ++CONFIG_SPI_BUTTERFLY=m ++ ++## ++## file: drivers/telephony/Kconfig ++## ++# CONFIG_PHONE is not set ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++# CONFIG_SERIAL_8250 is not set ++CONFIG_SERIAL_SB1250_DUART=y ++CONFIG_SERIAL_SB1250_DUART_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++# CONFIG_USB_USS720 is not set ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_ISP116X_HCD=m ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++CONFIG_USB_SL811_HCD=m ++ ++## ++## file: drivers/usb/mon/Kconfig ++## ++CONFIG_USB_MON=y ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++CONFIG_FB_MODE_HELPERS=y ++CONFIG_FB_TILEBLITTING=y ++# CONFIG_FB_CIRRUS is not set ++CONFIG_FB_PM2=m ++# CONFIG_FB_PM2_FIFO_DISCONNECT is not set ++CONFIG_FB_CYBER2000=m ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_S1D13XXX is not set ++CONFIG_FB_MATROX=m ++CONFIG_FB_MATROX_MILLENIUM=y ++CONFIG_FB_MATROX_MYSTIQUE=y ++CONFIG_FB_MATROX_G=y ++# CONFIG_FB_MATROX_I2C is not set ++CONFIG_FB_RADEON=m ++CONFIG_FB_RADEON_I2C=y ++# CONFIG_FB_RADEON_DEBUG is not set ++CONFIG_FB_ATY128=m ++CONFIG_FB_ATY=m ++# CONFIG_FB_ATY_CT is not set ++# CONFIG_FB_ATY_GX is not set ++CONFIG_FB_SAVAGE=m ++# CONFIG_FB_SAVAGE_I2C is not set ++# CONFIG_FB_SAVAGE_ACCEL is not set ++CONFIG_FB_SIS=m ++CONFIG_FB_SIS_300=y ++CONFIG_FB_SIS_315=y ++CONFIG_FB_NEOMAGIC=m ++CONFIG_FB_KYRO=m ++CONFIG_FB_VOODOO1=m ++CONFIG_FB_TRIDENT=m ++# CONFIG_FB_VIRTUAL is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: drivers/w1/Kconfig ++## ++# CONFIG_W1 is not set ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++# CONFIG_PCIPCWATCHDOG is not set ++# CONFIG_WDTPCI is not set ++# CONFIG_USBPCWATCHDOG is not set ++ ++## ++## file: fs/nfs/Kconfig ++## ++CONFIG_NFS_FS=y ++CONFIG_ROOT_NFS=y ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_SGI_PARTITION=y ++CONFIG_KARMA_PARTITION=y ++ ++## ++## file: init/Kconfig ++## ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/ax25/Kconfig ++## ++# CONFIG_HAMRADIO is not set ++ ++## ++## file: net/decnet/Kconfig ++## ++# CONFIG_DECNET is not set ++ ++## ++## file: net/ipv4/Kconfig ++## ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++ ++## ++## file: net/ipx/Kconfig ++## ++# CONFIG_IPX is not set ++ ++## ++## file: net/irda/Kconfig ++## ++# CONFIG_IRDA is not set ++ ++## ++## file: net/lapb/Kconfig ++## ++# CONFIG_LAPB is not set ++ +diff --git a/debian/config/mips/config.sb1a-bcm91480b b/debian/config/mips/config.sb1a-bcm91480b +new file mode 100644 +index 0000000..affe4bc +--- /dev/null ++++ b/debian/config/mips/config.sb1a-bcm91480b +@@ -0,0 +1,807 @@ ++## ++## file: arch/Kconfig ++## ++# CONFIG_OPROFILE is not set ++ ++## ++## file: arch/mips/Kconfig ++## ++## choice: System type ++# CONFIG_MIPS_COBALT is not set ++# CONFIG_MACH_DECSTATION is not set ++# CONFIG_MACH_JAZZ is not set ++# CONFIG_LASAT is not set ++# CONFIG_MIPS_MALTA is not set ++# CONFIG_MIPS_SIM is not set ++# CONFIG_MACH_VR41XX is not set ++# CONFIG_PNX8550_JBS is not set ++# CONFIG_PMC_YOSEMITE is not set ++# CONFIG_SGI_IP22 is not set ++# CONFIG_SGI_IP27 is not set ++# CONFIG_SGI_IP32 is not set ++# CONFIG_SIBYTE_CRHINE is not set ++# CONFIG_SIBYTE_CARMEL is not set ++# CONFIG_SIBYTE_CRHONE is not set ++# CONFIG_SIBYTE_RHONE is not set ++# CONFIG_SIBYTE_SWARM is not set ++# CONFIG_SIBYTE_LITTLESUR is not set ++# CONFIG_SIBYTE_SENTOSA is not set ++CONFIG_SIBYTE_BIGSUR=y ++## end choice ++## choice: CPU type ++# CONFIG_CPU_MIPS32_R1 is not set ++# CONFIG_CPU_MIPS32_R2 is not set ++# CONFIG_CPU_MIPS64_R1 is not set ++# CONFIG_CPU_MIPS64_R2 is not set ++# CONFIG_CPU_R3000 is not set ++# CONFIG_CPU_TX39XX is not set ++# CONFIG_CPU_VR41XX is not set ++# CONFIG_CPU_R4300 is not set ++# CONFIG_CPU_R4X00 is not set ++# CONFIG_CPU_TX49XX is not set ++# CONFIG_CPU_R5000 is not set ++# CONFIG_CPU_R5432 is not set ++# CONFIG_CPU_R6000 is not set ++# CONFIG_CPU_NEVADA is not set ++# CONFIG_CPU_R8000 is not set ++# CONFIG_CPU_R10000 is not set ++# CONFIG_CPU_RM7000 is not set ++# CONFIG_CPU_RM9000 is not set ++CONFIG_CPU_SB1=y ++## end choice ++## choice: Kernel code model ++# CONFIG_32BIT is not set ++CONFIG_64BIT=y ++## end choice ++## choice: Kernel page size ++CONFIG_PAGE_SIZE_4KB=y ++# CONFIG_PAGE_SIZE_8KB is not set ++# CONFIG_PAGE_SIZE_16KB is not set ++# CONFIG_PAGE_SIZE_64KB is not set ++## end choice ++# CONFIG_SIBYTE_DMA_PAGEOPS is not set ++CONFIG_SMP=y ++CONFIG_NR_CPUS=4 ++CONFIG_PCI=y ++CONFIG_MIPS32_COMPAT=y ++CONFIG_MIPS32_O32=y ++CONFIG_MIPS32_N32=y ++ ++## ++## file: arch/mips/alchemy/Kconfig ++## ++## choice: Machine type ++# CONFIG_MIPS_MTX1 is not set ++# CONFIG_MIPS_BOSPORUS is not set ++# CONFIG_MIPS_DB1000 is not set ++# CONFIG_MIPS_DB1100 is not set ++# CONFIG_MIPS_DB1200 is not set ++# CONFIG_MIPS_DB1500 is not set ++# CONFIG_MIPS_DB1550 is not set ++# CONFIG_MIPS_MIRAGE is not set ++# CONFIG_MIPS_PB1000 is not set ++# CONFIG_MIPS_PB1100 is not set ++# CONFIG_MIPS_PB1200 is not set ++# CONFIG_MIPS_PB1500 is not set ++# CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_XXS1500 is not set ++## end choice ++ ++## ++## file: arch/mips/Kconfig.debug ++## ++CONFIG_CMDLINE="" ++# CONFIG_SB1XXX_CORELIS is not set ++ ++## ++## file: arch/mips/sibyte/Kconfig ++## ++## choice: SiByte SOC Stepping ++# CONFIG_CPU_SB1_PASS_1 is not set ++# CONFIG_CPU_SB1_PASS_2_1250 is not set ++# CONFIG_CPU_SB1_PASS_2_2 is not set ++# CONFIG_CPU_SB1_PASS_4 is not set ++# CONFIG_CPU_SB1_PASS_2_112x is not set ++# CONFIG_CPU_SB1_PASS_3 is not set ++## end choice ++# CONFIG_SB1_CEX_ALWAYS_FATAL is not set ++# CONFIG_SB1_CERR_STALL is not set ++# CONFIG_SIBYTE_CFE_CONSOLE is not set ++# CONFIG_SIBYTE_BUS_WATCHER is not set ++# CONFIG_SIBYTE_TBPROF is not set ++ ++## ++## file: arch/mips/txx9/Kconfig ++## ++# CONFIG_TOSHIBA_JMR3927 is not set ++# CONFIG_TOSHIBA_RBTX4927 is not set ++# CONFIG_TOSHIBA_RBTX4938 is not set ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=y ++CONFIG_SATA_AHCI=m ++CONFIG_SATA_SIL24=m ++CONFIG_PDC_ADMA=m ++CONFIG_SATA_QSTOR=m ++CONFIG_SATA_SX4=m ++CONFIG_ATA_PIIX=m ++CONFIG_SATA_MV=m ++CONFIG_SATA_NV=m ++CONFIG_SATA_PROMISE=m ++CONFIG_SATA_SIL=m ++CONFIG_SATA_SIS=m ++CONFIG_SATA_SVW=m ++CONFIG_SATA_ULI=m ++CONFIG_SATA_VIA=m ++CONFIG_SATA_VITESSE=m ++CONFIG_PATA_ALI=m ++CONFIG_PATA_AMD=m ++CONFIG_PATA_CMD64X=m ++CONFIG_PATA_CS5530=m ++CONFIG_PATA_CYPRESS=y ++CONFIG_PATA_EFAR=m ++CONFIG_PATA_NS87415=m ++CONFIG_PATA_OLDPIIX=m ++CONFIG_PATA_PDC2027X=m ++CONFIG_PATA_PDC_OLD=m ++CONFIG_PATA_SC1200=m ++CONFIG_PATA_SERVERWORKS=m ++CONFIG_PATA_SIL680=m ++CONFIG_PATA_TRIFLEX=m ++CONFIG_PATA_VIA=m ++CONFIG_PATA_MPIIX=m ++CONFIG_PATA_PLATFORM=y ++ ++## ++## file: drivers/block/Kconfig ++## ++# CONFIG_BLK_CPQ_DA 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_SX8 is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM_SIZE=8192 ++# CONFIG_CDROM_PKTCDVD is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++# CONFIG_PPDEV is not set ++CONFIG_RTC=m ++CONFIG_GEN_RTC=y ++CONFIG_GEN_RTC_X=y ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++# CONFIG_APPLICOM is not set ++# CONFIG_TELCLOCK is not set ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++# CONFIG_IPMI_HANDLER is not set ++ ++## ++## file: drivers/char/tpm/Kconfig ++## ++# CONFIG_TCG_TPM is not set ++ ++## ++## file: drivers/firewire/Kconfig ++## ++# CONFIG_FIREWIRE is not set ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++# CONFIG_DRM is not set ++ ++## ++## file: drivers/hid/usbhid/Kconfig ++## ++CONFIG_USB_HID=m ++# CONFIG_USB_KBD is not set ++# CONFIG_USB_MOUSE is not set ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++CONFIG_HWMON=y ++# CONFIG_HWMON_DEBUG_CHIP is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM75 is not set ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_SIS5595 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_VIA686A is not set ++CONFIG_SENSORS_VT8231=m ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=m ++CONFIG_I2C_CHARDEV=m ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++# 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_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 ++# CONFIG_I2C_PARPORT is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_PCA_ISA is not set ++CONFIG_I2C_SIBYTE=m ++CONFIG_I2C_STUB=m ++# CONFIG_SCx200_ACB is not set ++ ++## ++## file: drivers/infiniband/Kconfig ++## ++# CONFIG_INFINIBAND is not set ++ ++## ++## file: drivers/input/Kconfig ++## ++# CONFIG_INPUT_JOYDEV is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++# CONFIG_GAMEPORT is not set ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++# CONFIG_INPUT_JOYSTICK is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++# CONFIG_INPUT_MISC is not set ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++# CONFIG_SERIO_I8042 is not set ++# CONFIG_SERIO_SERPORT is not set ++# CONFIG_SERIO_PARKBD is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_INPUT_TOUCHSCREEN is not set ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++# CONFIG_RADIO_MAXIRADIO is not set ++# CONFIG_USB_DSBR is not set ++ ++## ++## file: drivers/media/video/Kconfig ++## ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_BWQCAM is not set ++# CONFIG_VIDEO_CQCAM is not set ++# CONFIG_VIDEO_W9966 is not set ++# CONFIG_VIDEO_MXB is not set ++# CONFIG_VIDEO_HEXIUM_ORION is not set ++# CONFIG_VIDEO_HEXIUM_GEMINI is not set ++ ++## ++## file: drivers/media/video/bt8xx/Kconfig ++## ++# CONFIG_VIDEO_BT848 is not set ++ ++## ++## file: drivers/media/video/cx88/Kconfig ++## ++# CONFIG_VIDEO_CX88 is not set ++ ++## ++## file: drivers/media/video/em28xx/Kconfig ++## ++# CONFIG_VIDEO_EM28XX is not set ++ ++## ++## file: drivers/media/video/et61x251/Kconfig ++## ++CONFIG_USB_ET61X251=m ++ ++## ++## file: drivers/media/video/pwc/Kconfig ++## ++# CONFIG_USB_PWC is not set ++ ++## ++## file: drivers/media/video/saa7134/Kconfig ++## ++# CONFIG_VIDEO_SAA7134 is not set ++ ++## ++## file: drivers/media/video/sn9c102/Kconfig ++## ++# CONFIG_USB_SN9C102 is not set ++ ++## ++## file: drivers/media/video/zoran/Kconfig ++## ++# CONFIG_VIDEO_ZORAN is not set ++ ++## ++## file: drivers/message/fusion/Kconfig ++## ++# CONFIG_FUSION is not set ++# CONFIG_FUSION_SPI is not set ++# CONFIG_FUSION_FC is not set ++# CONFIG_FUSION_SAS is not set ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++# CONFIG_I2O is not set ++ ++## ++## file: drivers/mmc/Kconfig ++## ++# CONFIG_MMC is not set ++ ++## ++## file: drivers/mtd/Kconfig ++## ++# CONFIG_MTD is not set ++ ++## ++## file: drivers/net/Kconfig ++## ++# CONFIG_NET_FC is not set ++ ++## ++## file: drivers/net/appletalk/Kconfig ++## ++# CONFIG_ATALK is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/Kconfig ++## ++CONFIG_FEALNX=m ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++# CONFIG_NET_VENDOR_3COM is not set ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_NE2K_PCI=m ++ ++## ++## file: drivers/net/ethernet/adaptec/Kconfig ++## ++CONFIG_ADAPTEC_STARFIRE=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_AMD8111_ETH=m ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++CONFIG_B44=m ++CONFIG_SB1250_MAC=y ++ ++## ++## file: drivers/net/ethernet/chelsio/Kconfig ++## ++# CONFIG_CHELSIO_T1 is not set ++ ++## ++## file: drivers/net/ethernet/davicom/Kconfig ++## ++# CONFIG_DM9000 is not set ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++# CONFIG_NET_TULIP is not set ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++CONFIG_SUNDANCE=m ++# CONFIG_SUNDANCE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++# CONFIG_HP100 is not set ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++CONFIG_E100=m ++# CONFIG_IXGB is not set ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_NATSEMI=m ++ ++## ++## file: drivers/net/ethernet/neterion/Kconfig ++## ++# CONFIG_S2IO is not set ++ ++## ++## file: drivers/net/ethernet/nvidia/Kconfig ++## ++CONFIG_FORCEDETH=m ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_8139CP=m ++CONFIG_8139TOO=m ++CONFIG_8139TOO_PIO=y ++# CONFIG_8139TOO_TUNE_TWISTER is not set ++CONFIG_8139TOO_8129=y ++# CONFIG_8139_OLD_RX_RESET is not set ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++CONFIG_SIS900=m ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_EPIC100=m ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++CONFIG_VIA_RHINE=m ++# CONFIG_VIA_RHINE_MMIO is not set ++ ++## ++## file: drivers/net/fddi/Kconfig ++## ++# CONFIG_FDDI is not set ++ ++## ++## file: drivers/net/hippi/Kconfig ++## ++# CONFIG_HIPPI is not set ++ ++## ++## file: drivers/net/phy/Kconfig ++## ++CONFIG_BROADCOM_PHY=y ++ ++## ++## file: drivers/net/plip/Kconfig ++## ++# CONFIG_PLIP is not set ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++# CONFIG_TR is not set ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++# CONFIG_WAN is not set ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++# CONFIG_HOTPLUG_PCI is not set ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++CONFIG_SCSI_DMX3191D=m ++CONFIG_SCSI_FUTURE_DOMAIN=m ++CONFIG_SCSI_IPS=m ++CONFIG_SCSI_INITIO=m ++CONFIG_SCSI_INIA100=m ++CONFIG_SCSI_SYM53C8XX_2=m ++CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 ++CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 ++CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 ++# CONFIG_SCSI_IPR is not set ++CONFIG_SCSI_QLOGIC_1280=m ++CONFIG_SCSI_DC395x=m ++CONFIG_SCSI_DC390T=m ++CONFIG_SCSI_DEBUG=m ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic79xx ++## ++CONFIG_SCSI_AIC79XX=m ++CONFIG_AIC79XX_CMDS_PER_DEVICE=32 ++CONFIG_AIC79XX_RESET_DELAY_MS=15000 ++CONFIG_AIC79XX_DEBUG_ENABLE=y ++CONFIG_AIC79XX_DEBUG_MASK=0 ++CONFIG_AIC79XX_REG_PRETTY_PRINT=y ++ ++## ++## file: drivers/scsi/aic7xxx/Kconfig.aic7xxx ++## ++CONFIG_SCSI_AIC7XXX=m ++CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 ++CONFIG_AIC7XXX_RESET_DELAY_MS=15000 ++CONFIG_AIC7XXX_DEBUG_ENABLE=y ++CONFIG_AIC7XXX_DEBUG_MASK=0 ++CONFIG_AIC7XXX_REG_PRETTY_PRINT=y ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++# CONFIG_MEGARAID_NEWGEN is not set ++CONFIG_MEGARAID_LEGACY=m ++CONFIG_MEGARAID_SAS=m ++ ++## ++## file: drivers/scsi/qla2xxx/Kconfig ++## ++CONFIG_SCSI_QLA_FC=m ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI=y ++CONFIG_SPI_BITBANG=m ++CONFIG_SPI_BUTTERFLY=m ++ ++## ++## file: drivers/telephony/Kconfig ++## ++# CONFIG_PHONE is not set ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++# CONFIG_SERIAL_8250 is not set ++CONFIG_SERIAL_SB1250_DUART=y ++CONFIG_SERIAL_SB1250_DUART_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++# CONFIG_USB_USS720 is not set ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_ISP116X_HCD=m ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++CONFIG_USB_SL811_HCD=m ++ ++## ++## file: drivers/usb/mon/Kconfig ++## ++CONFIG_USB_MON=y ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++CONFIG_FB_MODE_HELPERS=y ++CONFIG_FB_TILEBLITTING=y ++# CONFIG_FB_CIRRUS is not set ++CONFIG_FB_PM2=m ++# CONFIG_FB_PM2_FIFO_DISCONNECT is not set ++CONFIG_FB_CYBER2000=m ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_S1D13XXX is not set ++CONFIG_FB_MATROX=m ++CONFIG_FB_MATROX_MILLENIUM=y ++CONFIG_FB_MATROX_MYSTIQUE=y ++CONFIG_FB_MATROX_G=y ++# CONFIG_FB_MATROX_I2C is not set ++CONFIG_FB_RADEON=m ++CONFIG_FB_RADEON_I2C=y ++# CONFIG_FB_RADEON_DEBUG is not set ++CONFIG_FB_ATY128=m ++CONFIG_FB_ATY=m ++# CONFIG_FB_ATY_CT is not set ++# CONFIG_FB_ATY_GX is not set ++CONFIG_FB_SAVAGE=m ++# CONFIG_FB_SAVAGE_I2C is not set ++# CONFIG_FB_SAVAGE_ACCEL is not set ++CONFIG_FB_SIS=m ++CONFIG_FB_SIS_300=y ++CONFIG_FB_SIS_315=y ++CONFIG_FB_NEOMAGIC=m ++CONFIG_FB_KYRO=m ++CONFIG_FB_VOODOO1=m ++CONFIG_FB_TRIDENT=m ++# CONFIG_FB_VIRTUAL is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: drivers/w1/Kconfig ++## ++# CONFIG_W1 is not set ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++# CONFIG_PCIPCWATCHDOG is not set ++# CONFIG_WDTPCI is not set ++# CONFIG_USBPCWATCHDOG is not set ++ ++## ++## file: fs/nfs/Kconfig ++## ++CONFIG_NFS_FS=y ++CONFIG_ROOT_NFS=y ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_SGI_PARTITION=y ++CONFIG_KARMA_PARTITION=y ++ ++## ++## file: init/Kconfig ++## ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/ax25/Kconfig ++## ++# CONFIG_HAMRADIO is not set ++ ++## ++## file: net/decnet/Kconfig ++## ++# CONFIG_DECNET is not set ++ ++## ++## file: net/ipv4/Kconfig ++## ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++ ++## ++## file: net/ipx/Kconfig ++## ++# CONFIG_IPX is not set ++ ++## ++## file: net/irda/Kconfig ++## ++# CONFIG_IRDA is not set ++ ++## ++## file: net/lapb/Kconfig ++## ++# CONFIG_LAPB is not set ++ +diff --git a/debian/config/mips/defines b/debian/config/mips/defines +new file mode 100644 +index 0000000..41578b3 +--- /dev/null ++++ b/debian/config/mips/defines +@@ -0,0 +1,49 @@ ++[abi] ++ignore-changes: ++# vgacon is broken and unusable on MIPS ++ vgacon_* ++ ++[base] ++flavours: ++ r4k-ip22 ++ r5k-ip32 ++ sb1-bcm91250a ++ sb1a-bcm91480b ++ 4kc-malta ++ 5kc-malta ++ octeon ++kernel-arch: mips ++ ++[image] ++configs: ++ kernelarch-mips/config ++ mips/config ++initramfs: false ++ ++[r4k-ip22_description] ++hardware: SGI IP22 ++hardware-long: SGI IP22 systems (Indy, Indigo2) ++ ++[r5k-ip32_description] ++hardware: SGI IP32 ++hardware-long: SGI IP32 systems (O2) ++ ++[sb1-bcm91250a_description] ++hardware: BCM91250A ++hardware-long: Broadcom BCM91250A systems (aka SWARM) ++ ++[sb1a-bcm91480b_description] ++hardware: BCM91480B ++hardware-long: Broadcom BCM91480B systems (aka BigSur) ++ ++[4kc-malta_description] ++hardware: MIPS Malta ++hardware-long: MIPS Malta boards ++ ++[5kc-malta_description] ++hardware: MIPS Malta (64-bit) ++hardware-long: MIPS Malta boards (64-bit) ++ ++[octeon_description] ++hardware: Octeon ++hardware-long: Cavium Networks Octeon +diff --git a/debian/config/mipsel/config b/debian/config/mipsel/config +new file mode 100644 +index 0000000..3acfa44 +--- /dev/null ++++ b/debian/config/mipsel/config +@@ -0,0 +1,7 @@ ++## ++## file: arch/mips/Kconfig ++## ++## choice: Endianess selection ++# CONFIG_CPU_BIG_ENDIAN is not set ++CONFIG_CPU_LITTLE_ENDIAN=y ++## end choice +diff --git a/debian/config/mipsel/config.loongson-2f b/debian/config/mipsel/config.loongson-2f +new file mode 100644 +index 0000000..80d4e63 +--- /dev/null ++++ b/debian/config/mipsel/config.loongson-2f +@@ -0,0 +1,132 @@ ++## ++## file: arch/mips/Kconfig ++## ++## choice: System type ++CONFIG_MACH_LOONGSON=y ++## end choice ++## choice: Kernel code model ++# CONFIG_32BIT is not set ++CONFIG_64BIT=y ++## end choice ++CONFIG_PCI=y ++CONFIG_MIPS32_COMPAT=y ++CONFIG_MIPS32_O32=y ++CONFIG_MIPS32_N32=y ++ ++## ++## file: arch/mips/kernel/cpufreq/Kconfig ++## ++CONFIG_LOONGSON2_CPUFREQ=m ++ ++## ++## file: arch/mips/loongson/Kconfig ++## ++## choice: Machine Type ++CONFIG_LEMOTE_MACH2F=y ++## end choice ++CONFIG_CS5536_MFGPT=y ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=y ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_PATA_AMD=y ++ ++## ++## file: drivers/cpufreq/Kconfig ++## ++## choice: Default CPUFreq governor ++# 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 ++## end choice ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++CONFIG_INPUT_TOUCHSCREEN=y ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++# CONFIG_PCNET32 is not set ++ ++## ++## file: drivers/net/ethernet/micrel/Kconfig ++## ++# CONFIG_KSZ884X_PCI is not set ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_8139TOO=m ++CONFIG_8139TOO_TUNE_TWISTER=y ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++# CONFIG_SCSI_LPFC is not set ++ ++## ++## file: drivers/staging/sm7xx/Kconfig ++## ++CONFIG_FB_SM7XX=y ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_EXTENDED is not set ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_ISP116X_HCD=m ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++CONFIG_USB_SL811_HCD=m ++ ++## ++## file: drivers/usb/mon/Kconfig ++## ++CONFIG_USB_MON=y ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_VIDEO_OUTPUT_CONTROL=y ++CONFIG_FB=y ++CONFIG_FB_SIS=y ++CONFIG_FB_SIS_300=y ++CONFIG_FB_SIS_315=y ++ ++## ++## file: drivers/video/backlight/Kconfig ++## ++CONFIG_LCD_CLASS_DEVICE=y ++CONFIG_LCD_PLATFORM=y ++CONFIG_BACKLIGHT_GENERIC=m ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++ +diff --git a/debian/config/mipsel/config.r5k-cobalt b/debian/config/mipsel/config.r5k-cobalt +new file mode 100644 +index 0000000..7e45b50 +--- /dev/null ++++ b/debian/config/mipsel/config.r5k-cobalt +@@ -0,0 +1,816 @@ ++## ++## file: arch/mips/Kconfig ++## ++## choice: System type ++CONFIG_MIPS_COBALT=y ++# CONFIG_MACH_DECSTATION is not set ++# CONFIG_MACH_JAZZ is not set ++# CONFIG_LASAT is not set ++# CONFIG_MIPS_MALTA is not set ++# CONFIG_MIPS_SIM is not set ++# CONFIG_MACH_VR41XX is not set ++# CONFIG_PNX8550_JBS is not set ++# CONFIG_PMC_YOSEMITE is not set ++# CONFIG_SGI_IP22 is not set ++# CONFIG_SGI_IP27 is not set ++# CONFIG_SGI_IP32 is not set ++# CONFIG_SIBYTE_CRHINE is not set ++# CONFIG_SIBYTE_CARMEL is not set ++# CONFIG_SIBYTE_CRHONE is not set ++# CONFIG_SIBYTE_RHONE is not set ++# CONFIG_SIBYTE_SWARM is not set ++# CONFIG_SIBYTE_LITTLESUR is not set ++# CONFIG_SIBYTE_SENTOSA is not set ++# CONFIG_SIBYTE_BIGSUR is not set ++## end choice ++## choice: CPU type ++# CONFIG_CPU_MIPS32_R1 is not set ++# CONFIG_CPU_MIPS32_R2 is not set ++# CONFIG_CPU_MIPS64_R1 is not set ++# CONFIG_CPU_MIPS64_R2 is not set ++# CONFIG_CPU_R3000 is not set ++# CONFIG_CPU_TX39XX is not set ++# CONFIG_CPU_VR41XX is not set ++# CONFIG_CPU_R4300 is not set ++# CONFIG_CPU_R4X00 is not set ++# CONFIG_CPU_TX49XX is not set ++# CONFIG_CPU_R5000 is not set ++# CONFIG_CPU_R5432 is not set ++# CONFIG_CPU_R6000 is not set ++CONFIG_CPU_NEVADA=y ++# CONFIG_CPU_R8000 is not set ++# CONFIG_CPU_R10000 is not set ++# CONFIG_CPU_RM7000 is not set ++# CONFIG_CPU_RM9000 is not set ++# CONFIG_CPU_SB1 is not set ++## end choice ++## choice: Kernel code model ++CONFIG_32BIT=y ++# CONFIG_64BIT is not set ++## end choice ++## choice: Kernel page size ++CONFIG_PAGE_SIZE_4KB=y ++# CONFIG_PAGE_SIZE_8KB is not set ++# CONFIG_PAGE_SIZE_16KB is not set ++# CONFIG_PAGE_SIZE_64KB is not set ++## end choice ++CONFIG_PCI=y ++ ++## ++## file: arch/mips/alchemy/Kconfig ++## ++## choice: Machine type ++# CONFIG_MIPS_MTX1 is not set ++# CONFIG_MIPS_BOSPORUS is not set ++# CONFIG_MIPS_DB1000 is not set ++# CONFIG_MIPS_DB1100 is not set ++# CONFIG_MIPS_DB1200 is not set ++# CONFIG_MIPS_DB1500 is not set ++# CONFIG_MIPS_DB1550 is not set ++# CONFIG_MIPS_MIRAGE is not set ++# CONFIG_MIPS_PB1000 is not set ++# CONFIG_MIPS_PB1100 is not set ++# CONFIG_MIPS_PB1200 is not set ++# CONFIG_MIPS_PB1500 is not set ++# CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_XXS1500 is not set ++## end choice ++ ++## ++## file: arch/mips/Kconfig.debug ++## ++CONFIG_CMDLINE="" ++ ++## ++## file: arch/mips/txx9/Kconfig ++## ++# CONFIG_TOSHIBA_JMR3927 is not set ++# CONFIG_TOSHIBA_RBTX4927 is not set ++# CONFIG_TOSHIBA_RBTX4938 is not set ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=y ++CONFIG_PATA_VIA=y ++CONFIG_PATA_PLATFORM=y ++ ++## ++## file: drivers/base/Kconfig ++## ++# CONFIG_STANDALONE is not set ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++ ++## ++## file: drivers/block/Kconfig ++## ++# CONFIG_PARIDE is not set ++# CONFIG_BLK_CPQ_DA 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_SX8 is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM_SIZE=8192 ++# CONFIG_CDROM_PKTCDVD is not set ++ ++## ++## file: drivers/char/Kconfig ++## ++# CONFIG_PRINTER is not set ++# CONFIG_PPDEV is not set ++# CONFIG_RTC is not set ++# CONFIG_GEN_RTC is not set ++# CONFIG_DTLK is not set ++# CONFIG_APPLICOM is not set ++# CONFIG_TELCLOCK is not set ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++# CONFIG_IPMI_HANDLER is not set ++ ++## ++## file: drivers/char/tpm/Kconfig ++## ++# CONFIG_TCG_TPM is not set ++ ++## ++## file: drivers/firewire/Kconfig ++## ++# CONFIG_FIREWIRE is not set ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++# CONFIG_DRM is not set ++ ++## ++## file: drivers/hid/usbhid/Kconfig ++## ++# CONFIG_USB_HID is not set ++# CONFIG_USB_KBD is not set ++# CONFIG_USB_MOUSE is not set ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++# CONFIG_HWMON is not set ++ ++## ++## file: drivers/i2c/Kconfig ++## ++# CONFIG_I2C is not set ++ ++## ++## file: drivers/infiniband/Kconfig ++## ++# CONFIG_INFINIBAND is not set ++ ++## ++## file: drivers/input/Kconfig ++## ++# CONFIG_INPUT_JOYDEV is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++# CONFIG_GAMEPORT is not set ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++# CONFIG_INPUT_JOYSTICK is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=m ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_PCSPKR is not set ++CONFIG_INPUT_COBALT_BTNS=m ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=m ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=m ++CONFIG_SERIO_I8042=m ++CONFIG_SERIO_SERPORT=m ++# CONFIG_SERIO_PARKBD is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=m ++# CONFIG_SERIO_RAW is not set ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_INPUT_TOUCHSCREEN is not set ++ ++## ++## file: drivers/isdn/Kconfig ++## ++CONFIG_ISDN=y ++CONFIG_ISDN_CAPI=m ++ ++## ++## file: drivers/isdn/capi/Kconfig ++## ++CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y ++CONFIG_ISDN_CAPI_MIDDLEWARE=y ++CONFIG_ISDN_CAPI_CAPI20=m ++ ++## ++## file: drivers/isdn/hardware/avm/Kconfig ++## ++CONFIG_CAPI_AVM=y ++CONFIG_ISDN_DRV_AVMB1_B1PCI=m ++CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y ++CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m ++CONFIG_ISDN_DRV_AVMB1_T1PCI=m ++CONFIG_ISDN_DRV_AVMB1_C4=m ++ ++## ++## file: drivers/isdn/hardware/eicon/Kconfig ++## ++CONFIG_CAPI_EICON=y ++CONFIG_ISDN_DIVAS=m ++CONFIG_ISDN_DIVAS_BRIPCI=y ++CONFIG_ISDN_DIVAS_PRIPCI=y ++CONFIG_ISDN_DIVAS_DIVACAPI=m ++CONFIG_ISDN_DIVAS_USERIDI=m ++CONFIG_ISDN_DIVAS_MAINT=m ++ ++## ++## file: drivers/leds/Kconfig ++## ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_COBALT_QUBE=y ++CONFIG_LEDS_COBALT_RAQ=y ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++# CONFIG_RADIO_MAXIRADIO is not set ++# CONFIG_USB_DSBR is not set ++ ++## ++## file: drivers/media/video/Kconfig ++## ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_BWQCAM is not set ++# CONFIG_VIDEO_CQCAM is not set ++# CONFIG_VIDEO_W9966 is not set ++# CONFIG_VIDEO_MXB is not set ++# CONFIG_VIDEO_HEXIUM_ORION is not set ++# CONFIG_VIDEO_HEXIUM_GEMINI is not set ++ ++## ++## file: drivers/media/video/et61x251/Kconfig ++## ++CONFIG_USB_ET61X251=m ++ ++## ++## file: drivers/media/video/pwc/Kconfig ++## ++# CONFIG_USB_PWC is not set ++ ++## ++## file: drivers/media/video/sn9c102/Kconfig ++## ++# CONFIG_USB_SN9C102 is not set ++ ++## ++## file: drivers/message/fusion/Kconfig ++## ++# CONFIG_FUSION is not set ++# CONFIG_FUSION_SPI is not set ++# CONFIG_FUSION_FC is not set ++# CONFIG_FUSION_SAS is not set ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++# CONFIG_I2O is not set ++ ++## ++## file: drivers/mmc/Kconfig ++## ++# CONFIG_MMC is not set ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++# CONFIG_MTD_CMDLINE_PARTS is not set ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++# CONFIG_MTD_BLOCK is not set ++# CONFIG_MTD_BLOCK_RO is not set ++# 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 ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++# CONFIG_MTD_CFI is not set ++CONFIG_MTD_JEDECPROBE=y ++# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT is not set ++CONFIG_MTD_CFI_AMDSTD=y ++# CONFIG_MTD_CFI_STAA is not set ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++## ++## file: drivers/mtd/devices/Kconfig ++## ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 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 ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_PHYSMAP_START=0x0 ++CONFIG_MTD_PHYSMAP_LEN=0x0 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=0 ++# CONFIG_MTD_PLATRAM is not set ++ ++## ++## file: drivers/mtd/nand/Kconfig ++## ++# CONFIG_MTD_NAND is not set ++ ++## ++## file: drivers/mtd/onenand/Kconfig ++## ++# CONFIG_MTD_ONENAND is not set ++ ++## ++## file: drivers/mtd/ubi/Kconfig ++## ++# CONFIG_MTD_UBI is not set ++ ++## ++## file: drivers/net/Kconfig ++## ++#. TODO ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC is not set ++# CONFIG_NETPOLL_TRAP is not set ++ ++## ++## file: drivers/net/appletalk/Kconfig ++## ++# CONFIG_ATALK is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/Kconfig ++## ++CONFIG_FEALNX=m ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++# CONFIG_NET_VENDOR_3COM is not set ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_NE2K_PCI=m ++ ++## ++## file: drivers/net/ethernet/adaptec/Kconfig ++## ++CONFIG_ADAPTEC_STARFIRE=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++CONFIG_AMD8111_ETH=m ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++CONFIG_B44=m ++# CONFIG_BNX2 is not set ++# CONFIG_TIGON3 is not set ++# CONFIG_BNX2X is not set ++ ++## ++## file: drivers/net/ethernet/chelsio/Kconfig ++## ++# CONFIG_CHELSIO_T1 is not set ++ ++## ++## file: drivers/net/ethernet/davicom/Kconfig ++## ++# CONFIG_DM9000 is not set ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++CONFIG_NET_TULIP=y ++CONFIG_DE2104X=y ++CONFIG_TULIP=y ++CONFIG_TULIP_MWI=y ++CONFIG_TULIP_MMIO=y ++# CONFIG_TULIP_NAPI is not set ++# CONFIG_WINBOND_840 is not set ++# CONFIG_DM9102 is not set ++# CONFIG_ULI526X is not set ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++# CONFIG_DL2K is not set ++CONFIG_SUNDANCE=m ++# CONFIG_SUNDANCE_MMIO is not set ++ ++## ++## file: drivers/net/ethernet/hp/Kconfig ++## ++# CONFIG_HP100 is not set ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++CONFIG_E100=m ++# CONFIG_E1000 is not set ++# CONFIG_IXGB is not set ++ ++## ++## file: drivers/net/ethernet/marvell/Kconfig ++## ++# CONFIG_SKGE is not set ++# CONFIG_SKY2 is not set ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_NATSEMI=m ++# CONFIG_NS83820 is not set ++ ++## ++## file: drivers/net/ethernet/neterion/Kconfig ++## ++# CONFIG_S2IO is not set ++ ++## ++## file: drivers/net/ethernet/nvidia/Kconfig ++## ++# CONFIG_FORCEDETH is not set ++ ++## ++## file: drivers/net/ethernet/packetengines/Kconfig ++## ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_8139CP=m ++CONFIG_8139TOO=m ++CONFIG_8139TOO_PIO=y ++# CONFIG_8139TOO_TUNE_TWISTER is not set ++# CONFIG_8139TOO_8129 is not set ++# CONFIG_8139_OLD_RX_RESET is not set ++# CONFIG_R8169 is not set ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++CONFIG_SIS900=m ++# CONFIG_SIS190 is not set ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_EPIC100=m ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++ ++## ++## file: drivers/net/ethernet/ti/Kconfig ++## ++# CONFIG_TLAN is not set ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++CONFIG_VIA_RHINE=m ++# CONFIG_VIA_RHINE_MMIO is not set ++# CONFIG_VIA_VELOCITY is not set ++ ++## ++## file: drivers/net/fddi/Kconfig ++## ++# CONFIG_FDDI is not set ++ ++## ++## file: drivers/net/hippi/Kconfig ++## ++# CONFIG_HIPPI is not set ++ ++## ++## file: drivers/net/phy/Kconfig ++## ++# CONFIG_PHYLIB is not set ++ ++## ++## file: drivers/net/plip/Kconfig ++## ++CONFIG_PLIP=m ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++# CONFIG_TR is not set ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++# CONFIG_WAN is not set ++ ++## ++## file: drivers/net/wireless/Kconfig ++## ++CONFIG_ATMEL=m ++CONFIG_PCI_ATMEL=m ++CONFIG_USB_ZD1201=m ++ ++## ++## file: drivers/net/wireless/ipw2x00/Kconfig ++## ++CONFIG_IPW2100=m ++# CONFIG_IPW2100_MONITOR is not set ++# CONFIG_IPW2100_DEBUG is not set ++CONFIG_IPW2200=m ++# CONFIG_IPW2200_DEBUG is not set ++ ++## ++## file: drivers/net/wireless/orinoco/Kconfig ++## ++CONFIG_HERMES=m ++CONFIG_PLX_HERMES=m ++CONFIG_TMD_HERMES=m ++CONFIG_NORTEL_HERMES=m ++CONFIG_PCI_HERMES=m ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++# CONFIG_HOTPLUG_PCI is not set ++ ++## ++## file: drivers/pcmcia/Kconfig ++## ++# CONFIG_PCCARD is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_CMOS=y ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 is not set ++# CONFIG_RTC_DRV_M48T86 is not set ++# CONFIG_RTC_DRV_V3020 is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++CONFIG_SCSI_SYM53C8XX_2=m ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI=y ++CONFIG_SPI_BITBANG=m ++# CONFIG_SPI_BUTTERFLY is not set ++ ++## ++## file: drivers/telephony/Kconfig ++## ++# CONFIG_PHONE is not set ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=4 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++# CONFIG_SERIAL_8250_EXTENDED is not set ++# CONFIG_SERIAL_JSM is not set ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++# CONFIG_USB_USS720 is not set ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_ISP116X_HCD=m ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++CONFIG_USB_SL811_HCD=m ++ ++## ++## file: drivers/usb/mon/Kconfig ++## ++CONFIG_USB_MON=y ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=m ++CONFIG_FB_COBALT=m ++ ++## ++## file: drivers/w1/Kconfig ++## ++# CONFIG_W1 is not set ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_MSDOS_PARTITION=y ++ ++## ++## file: init/Kconfig ++## ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ ++## ++## file: net/ax25/Kconfig ++## ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++# CONFIG_AX25_DAMA_SLAVE is not set ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++ ++## ++## file: net/bluetooth/Kconfig ++## ++# CONFIG_BT is not set ++ ++## ++## file: net/decnet/Kconfig ++## ++# CONFIG_DECNET is not set ++ ++## ++## file: net/ipx/Kconfig ++## ++# CONFIG_IPX is not set ++ ++## ++## file: net/irda/Kconfig ++## ++# CONFIG_IRDA is not set ++ ++## ++## file: net/lapb/Kconfig ++## ++# CONFIG_LAPB is not set ++ ++## ++## file: sound/drivers/Kconfig ++## ++# CONFIG_SND_DUMMY is not set ++# CONFIG_SND_VIRMIDI is not set ++# CONFIG_SND_MTPAV is not set ++# CONFIG_SND_SERIAL_U16550 is not set ++# CONFIG_SND_MPU401 is not set ++ ++## ++## file: sound/pci/Kconfig ++## ++CONFIG_SND_AD1889=m ++CONFIG_SND_ALI5451=m ++CONFIG_SND_ATIIXP=m ++CONFIG_SND_ATIIXP_MODEM=m ++CONFIG_SND_AU8810=m ++CONFIG_SND_AU8820=m ++CONFIG_SND_AU8830=m ++CONFIG_SND_AZT3328=m ++CONFIG_SND_BT87X=m ++# CONFIG_SND_BT87X_OVERCLOCK is not set ++CONFIG_SND_CA0106=m ++CONFIG_SND_CMIPCI=m ++CONFIG_SND_CS4281=m ++CONFIG_SND_CS46XX=m ++# CONFIG_SND_CS46XX_NEW_DSP is not set ++CONFIG_SND_EMU10K1=m ++CONFIG_SND_EMU10K1X=m ++CONFIG_SND_ENS1370=m ++CONFIG_SND_ENS1371=m ++CONFIG_SND_ES1938=m ++CONFIG_SND_ES1968=m ++CONFIG_SND_FM801=m ++CONFIG_SND_FM801_TEA575X_BOOL=y ++CONFIG_SND_HDSP=m ++CONFIG_SND_HDSPM=m ++CONFIG_SND_ICE1712=m ++CONFIG_SND_ICE1724=m ++CONFIG_SND_INTEL8X0=m ++CONFIG_SND_INTEL8X0M=m ++CONFIG_SND_KORG1212=m ++CONFIG_SND_MAESTRO3=m ++CONFIG_SND_MIXART=m ++CONFIG_SND_NM256=m ++CONFIG_SND_PCXHR=m ++CONFIG_SND_RME32=m ++CONFIG_SND_RME96=m ++CONFIG_SND_RME9652=m ++CONFIG_SND_SONICVIBES=m ++CONFIG_SND_TRIDENT=m ++CONFIG_SND_VIA82XX=m ++CONFIG_SND_VIA82XX_MODEM=m ++CONFIG_SND_VX222=m ++CONFIG_SND_YMFPCI=m ++ ++## ++## file: sound/pci/hda/Kconfig ++## ++CONFIG_SND_HDA_INTEL=m ++ +diff --git a/debian/config/mipsel/defines b/debian/config/mipsel/defines +new file mode 100644 +index 0000000..1a111fb +--- /dev/null ++++ b/debian/config/mipsel/defines +@@ -0,0 +1,59 @@ ++[abi] ++ignore-changes: ++# vgacon is broken and unusable on MIPS ++ vgacon_* ++ ++[base] ++flavours: ++ r5k-cobalt ++ sb1-bcm91250a ++ sb1a-bcm91480b ++ 4kc-malta ++ 5kc-malta ++ loongson-2f ++kernel-arch: mips ++ ++[image] ++configs: ++ kernelarch-mips/config ++ mipsel/config ++initramfs: false ++ ++[r5k-cobalt_description] ++hardware: Cobalt ++hardware-long: Cobalt systems (Qube, RaQ, Qube2, RaQ2) ++ ++[sb1-bcm91250a_description] ++hardware: BCM91250A ++hardware-long: Broadcom BCM91250A systems (aka SWARM) ++ ++[sb1-bcm91250a_image] ++configs: mips/config.sb1-bcm91250a ++ ++[sb1a-bcm91480b_description] ++hardware: BCM91480B ++hardware-long: Broadcom BCM91480B systems (aka BigSur) ++ ++[sb1a-bcm91480b_image] ++configs: mips/config.sb1a-bcm91480b ++ ++[4kc-malta_description] ++hardware: MIPS Malta ++hardware-long: MIPS Malta boards ++ ++[4kc-malta_image] ++configs: mips/config.4kc-malta ++ ++[5kc-malta_description] ++hardware: MIPS Malta (64-bit) ++hardware-long: MIPS Malta boards (64-bit) ++ ++[5kc-malta_image] ++configs: mips/config.5kc-malta ++ ++[loongson-2f_description] ++hardware: Loongson 2F ++hardware-long: Lemote Loongson 2F systems ++ ++[loongson-2f_image] ++recommends: libc6-loongson2f +diff --git a/debian/config/powerpc/config b/debian/config/powerpc/config +new file mode 100644 +index 0000000..e69de29 +diff --git a/debian/config/powerpc/config-cumulus b/debian/config/powerpc/config-cumulus +new file mode 100644 +index 0000000..e322326 +--- /dev/null ++++ b/debian/config/powerpc/config-cumulus +@@ -0,0 +1,2584 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/powerpc 3.2.71 Kernel Configuration ++# ++# CONFIG_PPC64 is not set ++ ++# ++# Processor support ++# ++# CONFIG_PPC_BOOK3S_32 is not set ++CONFIG_PPC_85xx=y ++# CONFIG_PPC_8xx is not set ++# CONFIG_40x is not set ++# CONFIG_44x is not set ++# CONFIG_E200 is not set ++CONFIG_E500=y ++# CONFIG_PPC_E500MC is not set ++CONFIG_FSL_EMB_PERFMON=y ++CONFIG_FSL_EMB_PERF_EVENT=y ++CONFIG_FSL_EMB_PERF_EVENT_E500=y ++CONFIG_BOOKE=y ++CONFIG_FSL_BOOKE=y ++CONFIG_PPC_FSL_BOOK3E=y ++# CONFIG_PHYS_64BIT is not set ++CONFIG_SPE=y ++CONFIG_PPC_MMU_NOHASH=y ++CONFIG_PPC_BOOK3E_MMU=y ++# CONFIG_PPC_MM_SLICES is not set ++CONFIG_SMP=y ++CONFIG_NR_CPUS=2 ++CONFIG_PPC32=y ++CONFIG_32BIT=y ++CONFIG_WORD_SIZE=32 ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set ++CONFIG_MMU=y ++CONFIG_GENERIC_CMOS_UPDATE=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set ++# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set ++CONFIG_NR_IRQS=512 ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=y ++CONFIG_ARCH_HAS_ILOG2_U32=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_GPIO=y ++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set ++CONFIG_PPC=y ++CONFIG_EARLY_PRINTK=y ++CONFIG_GENERIC_NVRAM=y ++CONFIG_SCHED_OMIT_FRAME_POINTER=y ++CONFIG_ARCH_MAY_HAVE_PC_FDC=y ++CONFIG_PPC_OF=y ++CONFIG_PPC_UDBG_16550=y ++CONFIG_GENERIC_TBSYNC=y ++CONFIG_AUDIT_ARCH=y ++CONFIG_GENERIC_BUG=y ++# CONFIG_EPAPR_BOOT is not set ++CONFIG_DEFAULT_UIMAGE=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++# CONFIG_PPC_DCR_NATIVE is not set ++# CONFIG_PPC_DCR_MMIO is not set ++CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y ++CONFIG_PPC_ADV_DEBUG_REGS=y ++CONFIG_PPC_ADV_DEBUG_IACS=2 ++CONFIG_PPC_ADV_DEBUG_DACS=2 ++CONFIG_PPC_ADV_DEBUG_DVCS=0 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_HAVE_IRQ_WORK=y ++CONFIG_IRQ_WORK=y ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="powerpc" ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_DEFAULT_HOSTNAME="cumulus" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_FHANDLE=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_AUDIT=y ++CONFIG_AUDITSYSCALL=y ++CONFIG_AUDIT_WATCH=y ++CONFIG_AUDIT_TREE=y ++CONFIG_HAVE_GENERIC_HARDIRQS=y ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_HAVE_SPARSE_IRQ=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_GENERIC_IRQ_SHOW_LEVEL=y ++# CONFIG_SPARSE_IRQ is not set ++ ++# ++# RCU Subsystem ++# ++CONFIG_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_RCU_TRACE is not set ++CONFIG_RCU_FANOUT=32 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_TREE_RCU_TRACE is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=20 ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CPUSETS=y ++CONFIG_PROC_PID_CPUSET=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_RESOURCE_COUNTERS=y ++CONFIG_CGROUP_MEM_RES_CTLR=y ++CONFIG_CGROUP_MEM_RES_CTLR_DISABLED=y ++CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y ++# CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set ++CONFIG_CGROUP_PERF=y ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++CONFIG_RT_GROUP_SCHED=y ++# CONFIG_BLK_CGROUP is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++CONFIG_USER_NS=y ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_MM_OWNER=y ++# 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=y ++# CONFIG_RD_LZO is not set ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_EXPERT=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++# CONFIG_HOTPLUG 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_SHMEM=y ++CONFIG_AIO=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_PERF_COUNTERS is not set ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_PCI_QUIRKS=y ++# CONFIG_SLUB_DEBUG is not set ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++CONFIG_PROFILING=y ++CONFIG_TRACEPOINTS=y ++CONFIG_OPROFILE=y ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y ++CONFIG_HAVE_IOREMAP_PROT=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=y ++CONFIG_USE_GENERIC_SMP_HELPERS=y ++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y ++CONFIG_HAVE_CLK=y ++CONFIG_HAVE_DMA_API_DEBUG=y ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_HAVE_RCU_TABLE_FREE=y ++CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y ++ ++# ++# GCOV-based kernel profiling ++# ++# CONFIG_GCOV_KERNEL is not set ++# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set ++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=y ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_STOP_MACHINE=y ++CONFIG_BLOCK=y ++# CONFIG_LBDAF is not set ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq" ++# CONFIG_INLINE_SPIN_TRYLOCK is not set ++# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK is not set ++# CONFIG_INLINE_SPIN_LOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQ is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set ++CONFIG_INLINE_SPIN_UNLOCK=y ++# CONFIG_INLINE_SPIN_UNLOCK_BH is not set ++CONFIG_INLINE_SPIN_UNLOCK_IRQ=y ++# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_READ_TRYLOCK is not set ++# CONFIG_INLINE_READ_LOCK is not set ++# CONFIG_INLINE_READ_LOCK_BH is not set ++# CONFIG_INLINE_READ_LOCK_IRQ is not set ++# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set ++CONFIG_INLINE_READ_UNLOCK=y ++# CONFIG_INLINE_READ_UNLOCK_BH is not set ++CONFIG_INLINE_READ_UNLOCK_IRQ=y ++# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_WRITE_TRYLOCK is not set ++# CONFIG_INLINE_WRITE_LOCK is not set ++# CONFIG_INLINE_WRITE_LOCK_BH is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQ is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set ++CONFIG_INLINE_WRITE_UNLOCK=y ++# CONFIG_INLINE_WRITE_UNLOCK_BH is not set ++CONFIG_INLINE_WRITE_UNLOCK_IRQ=y ++# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set ++CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y ++CONFIG_MUTEX_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++# CONFIG_PPC_XICS is not set ++# CONFIG_PPC_ICP_NATIVE is not set ++# CONFIG_PPC_ICP_HV is not set ++# CONFIG_PPC_ICS_RTAS is not set ++ ++# ++# Platform support ++# ++# CONFIG_PPC_CELL is not set ++# CONFIG_PPC_CELL_NATIVE is not set ++# CONFIG_PQ2ADS is not set ++CONFIG_FSL_SOC_BOOKE=y ++# CONFIG_MPC8540_ADS is not set ++# CONFIG_MPC8560_ADS is not set ++# CONFIG_MPC85xx_CDS is not set ++# CONFIG_MPC85xx_MDS is not set ++# CONFIG_MPC8536_DS is not set ++# CONFIG_MPC85xx_DS is not set ++# CONFIG_MPC85xx_RDB is not set ++# CONFIG_P1010_RDB is not set ++# CONFIG_P1022_DS is not set ++# CONFIG_P1023_RDS is not set ++# CONFIG_SOCRATES is not set ++# CONFIG_KSI8560 is not set ++# CONFIG_XES_MPC85xx is not set ++# CONFIG_STX_GP3 is not set ++# CONFIG_TQM8540 is not set ++# CONFIG_TQM8541 is not set ++# CONFIG_TQM8548 is not set ++# CONFIG_TQM8555 is not set ++# CONFIG_TQM8560 is not set ++# CONFIG_SBC8548 is not set ++# CONFIG_SBC8560 is not set ++# CONFIG_P2041_RDB is not set ++# CONFIG_P3041_DS is not set ++# CONFIG_P3060_QDS is not set ++# CONFIG_P4080_DS is not set ++CONFIG_ACCTON_AS4600_54T=y ++CONFIG_ACCTON_AS5610_52X=y ++CONFIG_ACCTON_AS6701_32X=y ++CONFIG_ACCTON_5652=y ++CONFIG_BCM98548XMC=y ++CONFIG_CEL_P2020=y ++CONFIG_CEL_REDSTONE=y ++CONFIG_CEL_KENNISIS=y ++CONFIG_CEL_SMALLSTONE=y ++CONFIG_CUMULUS_P2020=y ++CONFIG_DNI_6448=y ++CONFIG_DNI_7448=y ++CONFIG_DNI_C7448N=y ++CONFIG_QUANTA_LB8=y ++CONFIG_QUANTA_LB9=y ++CONFIG_QUANTA_LY2_LY2R=y ++CONFIG_QUANTA_LY2=y ++CONFIG_QUANTA_LY2R=y ++CONFIG_QUANTA_LY6_P2020=y ++# CONFIG_P5020_DS is not set ++# CONFIG_PPC_WSP is not set ++# CONFIG_KVM_GUEST is not set ++CONFIG_PPC_SMP_MUXED_IPI=y ++# CONFIG_IPIC is not set ++CONFIG_MPIC=y ++# CONFIG_PPC_EPAPR_HV_PIC is not set ++# CONFIG_MPIC_WEIRD is not set ++# CONFIG_PPC_I8259 is not set ++# CONFIG_PPC_RTAS is not set ++# CONFIG_MMIO_NVRAM is not set ++# CONFIG_MPIC_U3_HT_IRQS is not set ++# CONFIG_PPC_MPC106 is not set ++# CONFIG_PPC_970_NAP is not set ++# CONFIG_PPC_P7_NAP is not set ++ ++# ++# CPU Frequency scaling ++# ++# CONFIG_CPU_FREQ is not set ++CONFIG_QUICC_ENGINE=y ++CONFIG_QE_GPIO=y ++CONFIG_CPM2=y ++# CONFIG_FSL_ULI1575 is not set ++CONFIG_CPM=y ++CONFIG_SIMPLE_GPIO=y ++ ++# ++# Kernel options ++# ++CONFIG_HIGHMEM=y ++CONFIG_TICK_ONESHOT=y ++# CONFIG_NO_HZ is not set ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++# 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=y ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++CONFIG_BINFMT_ELF=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_MATH_EMULATION=y ++CONFIG_IOMMU_HELPER=y ++CONFIG_SWIOTLB=y ++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y ++CONFIG_ARCH_HAS_WALK_MEMORY=y ++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_IRQ_ALL_CPUS is not set ++CONFIG_MAX_ACTIVE_REGIONS=32 ++CONFIG_ARCH_FLATMEM_ENABLE=y ++CONFIG_ARCH_POPULATES_NODE_MAP=y ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++# CONFIG_COMPACTION is not set ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=1 ++CONFIG_BOUNCE=y ++CONFIG_VIRT_TO_BUS=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_CLEANCACHE is not set ++CONFIG_PPC_4K_PAGES=y ++CONFIG_FORCE_MAX_ZONEORDER=11 ++# CONFIG_CMDLINE_BOOL is not set ++CONFIG_EXTRA_TARGETS="" ++# CONFIG_HIBERNATION is not set ++# CONFIG_PM_RUNTIME is not set ++# CONFIG_SECCOMP is not set ++CONFIG_ISA_DMA_API=y ++ ++# ++# Bus options ++# ++CONFIG_ZONE_DMA=y ++# CONFIG_NEED_DMA_MAP_STATE is not set ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_GENERIC_ISA_DMA=y ++CONFIG_PPC_INDIRECT_PCI=y ++CONFIG_FSL_SOC=y ++CONFIG_FSL_PCI=y ++CONFIG_FSL_LBC=y ++# CONFIG_HAS_FSL_PAMU is not set ++# CONFIG_HAS_FSL_QBMAN is not set ++CONFIG_PPC_PCI_CHOICE=y ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=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 is not set ++CONFIG_ARCH_SUPPORTS_MSI=y ++# CONFIG_PCI_MSI is not set ++# CONFIG_PCI_DEBUG 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_HAS_RAPIDIO is not set ++# CONFIG_RAPIDIO is not set ++ ++# ++# Advanced setup ++# ++# CONFIG_ADVANCED_OPTIONS is not set ++ ++# ++# Default settings for advanced configuration options are used ++# ++CONFIG_LOWMEM_SIZE=0x30000000 ++CONFIG_LOWMEM_CAM_NUM=3 ++CONFIG_PAGE_OFFSET=0xc0000000 ++CONFIG_KERNEL_START=0xc0000000 ++CONFIG_PHYSICAL_START=0x00000000 ++CONFIG_PHYSICAL_ALIGN=0x04000000 ++CONFIG_TASK_SIZE=0xc0000000 ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++CONFIG_XFRM_USER=m ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_XFRM_IPCOMP=m ++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=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++# CONFIG_IP_ROUTE_VERBOSE is not set ++CONFIG_IP_ROUTE_CLASSID=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_IP_PNP_RARP is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++CONFIG_IP_MROUTE=y ++# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set ++# CONFIG_IP_PIMSM_V1 is not set ++CONFIG_IP_PIMSM_V2=y ++CONFIG_ARPD=y ++CONFIG_SYN_COOKIES=y ++# 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 is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++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_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_DEFAULT_CUBIC=y ++# CONFIG_DEFAULT_RENO is not set ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_TCP_MD5SIG=y ++CONFIG_IPV6=y ++CONFIG_IPV6_PRIVACY=y ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_IPV6_ROUTE_INFO=y ++CONFIG_IPV6_OPTIMISTIC_DAD=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_MIP6=m ++CONFIG_INET6_XFRM_TUNNEL=m ++CONFIG_INET6_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++CONFIG_BRIDGE_NETFILTER=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_NETLINK=m ++CONFIG_NETFILTER_NETLINK_QUEUE=m ++CONFIG_NETFILTER_NETLINK_LOG=m ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_MARK=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++# CONFIG_NF_CT_PROTO_DCCP is not set ++CONFIG_NF_CT_PROTO_GRE=m ++# CONFIG_NF_CT_PROTO_SCTP is not set ++# CONFIG_NF_CT_PROTO_UDPLITE is not set ++# CONFIG_NF_CONNTRACK_AMANDA is not set ++CONFIG_NF_CONNTRACK_FTP=m ++# CONFIG_NF_CONNTRACK_H323 is not set ++# CONFIG_NF_CONNTRACK_IRC is not set ++CONFIG_NF_CONNTRACK_BROADCAST=m ++# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++# CONFIG_NF_CONNTRACK_SANE is not set ++# CONFIG_NF_CONNTRACK_SIP is not set ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++# CONFIG_NETFILTER_TPROXY is not set ++CONFIG_NETFILTER_XTABLES=y ++ ++# ++# Xtables combined modules ++# ++CONFIG_NETFILTER_XT_MARK=m ++CONFIG_NETFILTER_XT_CONNMARK=m ++ ++# ++# Xtables targets ++# ++CONFIG_NETFILTER_XT_TARGET_AUDIT=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++# CONFIG_NETFILTER_XT_TARGET_CT is not set ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HL=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_RATEEST=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set ++CONFIG_NETFILTER_XT_TARGET_ERSPAN=y ++CONFIG_NETFILTER_XT_TARGET_SPAN=y ++CONFIG_NETFILTER_XT_TARGET_POLICE=y ++CONFIG_NETFILTER_XT_TARGET_TRICOLORPOLICE=y ++CONFIG_NETFILTER_XT_TARGET_SETCLASS=y ++CONFIG_NETFILTER_XT_TARGET_SETQOS=y ++ ++# ++# Xtables matches ++# ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_HL=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SCTP=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++CONFIG_NF_DEFRAG_IPV4=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_NF_CONNTRACK_PROC_COMPAT=y ++# CONFIG_IP_NF_QUEUE is not set ++CONFIG_IP_NF_IPTABLES=y ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=y ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_TARGET_LOG=m ++CONFIG_IP_NF_TARGET_ULOG=m ++CONFIG_NF_NAT=m ++CONFIG_NF_NAT_NEEDED=y ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_NF_NAT_SNMP_BASIC=m ++CONFIG_NF_NAT_PROTO_GRE=m ++CONFIG_NF_NAT_FTP=m ++# CONFIG_NF_NAT_IRC is not set ++CONFIG_NF_NAT_TFTP=m ++# CONFIG_NF_NAT_AMANDA is not set ++CONFIG_NF_NAT_PPTP=m ++# CONFIG_NF_NAT_H323 is not set ++# CONFIG_NF_NAT_SIP is not set ++CONFIG_IP_NF_MANGLE=y ++# CONFIG_IP_NF_TARGET_CLUSTERIP is not set ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=y ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++ ++# ++# IPv6: Netfilter Configuration ++# ++CONFIG_NF_DEFRAG_IPV6=m ++CONFIG_NF_CONNTRACK_IPV6=m ++# CONFIG_IP6_NF_QUEUE is not set ++CONFIG_IP6_NF_IPTABLES=y ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_TARGET_LOG=m ++CONFIG_IP6_NF_FILTER=y ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=y ++CONFIG_IP6_NF_RAW=y ++CONFIG_BRIDGE_NF_EBTABLES=y ++# CONFIG_BRIDGE_EBT_BROUTE is not set ++CONFIG_BRIDGE_EBT_T_FILTER=y ++CONFIG_BRIDGE_EBT_T_NAT=y ++CONFIG_BRIDGE_EBT_802_3=m ++# CONFIG_BRIDGE_EBT_AMONG is not set ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++# CONFIG_BRIDGE_EBT_LIMIT is not set ++# CONFIG_BRIDGE_EBT_MARK is not set ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++# CONFIG_BRIDGE_EBT_STP is not set ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=y ++# CONFIG_BRIDGE_EBT_MARK_T is not set ++# CONFIG_BRIDGE_EBT_REDIRECT is not set ++CONFIG_BRIDGE_EBT_SNAT=y ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_ULOG=m ++# CONFIG_BRIDGE_EBT_NFLOG is not set ++CONFIG_BRIDGE_EBT_ERSPAN=y ++CONFIG_BRIDGE_EBT_SPAN=y ++CONFIG_BRIDGE_EBT_POLICE=y ++CONFIG_BRIDGE_EBT_TRICOLORPOLICE=y ++CONFIG_BRIDGE_EBT_SETCLASS=y ++# CONFIG_IP_DCCP is not set ++CONFIG_IP_SCTP=m ++# CONFIG_SCTP_DBG_MSG is not set ++# CONFIG_SCTP_DBG_OBJCNT is not set ++# CONFIG_SCTP_HMAC_NONE is not set ++# CONFIG_SCTP_HMAC_SHA1 is not set ++CONFIG_SCTP_HMAC_MD5=y ++# CONFIG_RDS is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_L2TP is not set ++CONFIG_STP=y ++CONFIG_BRIDGE=y ++CONFIG_BRIDGE_IGMP_SNOOPING=y ++CONFIG_BRIDGE_VLAN_FILTERING=y ++# CONFIG_NET_DSA is not set ++CONFIG_VLAN_8021Q=m ++# CONFIG_VLAN_8021Q_GVRP is not set ++# CONFIG_VLAN_8021Q_MVRP is not set ++# CONFIG_DECNET is not set ++CONFIG_LLC=y ++# 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_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_PHONET is not set ++# CONFIG_IEEE802154 is not set ++CONFIG_NET_SCHED=y ++ ++# ++# Queueing/Scheduling ++# ++# CONFIG_NET_SCH_CBQ is not set ++# CONFIG_NET_SCH_HTB is not set ++# CONFIG_NET_SCH_HFSC is not set ++# CONFIG_NET_SCH_PRIO is not set ++# CONFIG_NET_SCH_MULTIQ is not set ++# CONFIG_NET_SCH_RED is not set ++# CONFIG_NET_SCH_SFB is not set ++# CONFIG_NET_SCH_SFQ is not set ++# CONFIG_NET_SCH_TEQL is not set ++# CONFIG_NET_SCH_TBF is not set ++# CONFIG_NET_SCH_GRED is not set ++# CONFIG_NET_SCH_DSMARK is not set ++# CONFIG_NET_SCH_NETEM is not set ++# CONFIG_NET_SCH_DRR is not set ++# CONFIG_NET_SCH_MQPRIO is not set ++# CONFIG_NET_SCH_CHOKE is not set ++# CONFIG_NET_SCH_QFQ is not set ++# CONFIG_NET_SCH_CODEL is not set ++# CONFIG_NET_SCH_FQ_CODEL is not set ++ ++# ++# Classification ++# ++CONFIG_NET_CLS=y ++# CONFIG_NET_CLS_BASIC is not set ++# CONFIG_NET_CLS_TCINDEX is not set ++# CONFIG_NET_CLS_ROUTE4 is not set ++# CONFIG_NET_CLS_FW is not set ++# CONFIG_NET_CLS_U32 is not set ++# CONFIG_NET_CLS_RSVP is not set ++# CONFIG_NET_CLS_RSVP6 is not set ++# CONFIG_NET_CLS_FLOW is not set ++CONFIG_NET_CLS_CGROUP=y ++# CONFIG_NET_EMATCH is not set ++# CONFIG_NET_CLS_ACT is not set ++CONFIG_NET_SCH_FIFO=y ++CONFIG_DCB=y ++CONFIG_DNS_RESOLVER=y ++# CONFIG_BATMAN_ADV is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++CONFIG_BQL=y ++ ++# ++# Network testing ++# ++CONFIG_NET_PKTGEN=m ++# CONFIG_NET_DROP_MONITOR 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_FIB_RULES=y ++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 ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++# CONFIG_FW_LOADER is not set ++# 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_CONNECTOR=y ++CONFIG_PROC_EVENTS=y ++CONFIG_MTD=y ++# CONFIG_MTD_TESTS is not set ++# CONFIG_MTD_REDBOOT_PARTS is not set ++# CONFIG_MTD_CMDLINE_PARTS is not set ++CONFIG_MTD_OF_PARTS=y ++# CONFIG_MTD_AR7_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++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 ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++CONFIG_MTD_CFI=y ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_GEN_PROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++# CONFIG_MTD_CFI_NOSWAP is not set ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++CONFIG_MTD_CFI_OF_BYTE_SWAP=y ++# CONFIG_MTD_CFI_GEOMETRY 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_OTP is not set ++CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_STAA=y ++CONFIG_MTD_CFI_UTIL=y ++# 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_PHYSMAP=y ++# CONFIG_MTD_PHYSMAP_COMPAT is not set ++CONFIG_MTD_PHYSMAP_OF=y ++# 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_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++# 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_VERIFY_WRITE is not set ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_MUSEUM_IDS is not set ++# CONFIG_MTD_NAND_DENALI 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_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++CONFIG_MTD_NAND_PLATFORM=y ++# CONFIG_MTD_ALAUDA is not set ++CONFIG_MTD_NAND_FSL_ELBC=y ++CONFIG_MTD_NAND_FSL_UPM=y ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR flash memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_RESERVE=1 ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_DEBUG is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++CONFIG_PROC_DEVICETREE=y ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_DYNAMIC=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_DEVICE=y ++CONFIG_OF_GPIO=y ++CONFIG_OF_I2C=y ++CONFIG_OF_NET=y ++CONFIG_OF_SPI=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_FD is not set ++# CONFIG_BLK_CPQ_DA 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_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=32768 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_HD is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_SENSORS_LIS3LV02D is not set ++CONFIG_MISC_DEVICES=y ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_ATMEL_PWM 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_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_BMP085 is not set ++# CONFIG_PCH_PHUB is not set ++# CONFIG_USB_SWITCH_FSA9480 is not set ++CONFIG_EARLY_DMA_ALLOC=y ++CONFIG_EDA_DEF_SIZE=0x04000000 ++CONFIG_EDA_DEF_ALIGN=0x00100000 ++CONFIG_RETIMER_CLASS=y ++CONFIG_DS100DF410=m ++# CONFIG_C2PORT is not set ++ ++# ++# EEPROM support ++# ++CONFIG_EEPROM_CLASS=y ++CONFIG_EEPROM_AT24=m ++CONFIG_EEPROM_AT25=m ++# 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_EEPROM_SFF_8436=m ++# CONFIG_CB710_CORE is not set ++# CONFIG_IWMC3200TOP 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 ++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_TGT is not set ++# CONFIG_SCSI_NETLINK 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_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++CONFIG_SCSI_WAIT_SCAN=m ++ ++# ++# 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=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++# CONFIG_SATA_PMP is not set ++ ++# ++# Controllers with non-SFF native interface ++# ++# CONFIG_SATA_AHCI is not set ++# CONFIG_SATA_AHCI_PLATFORM is not set ++# CONFIG_SATA_FSL 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=y ++ ++# ++# SFF controllers with custom DMA interface ++# ++# CONFIG_PDC_ADMA is not set ++# CONFIG_SATA_QSTOR is not set ++# CONFIG_SATA_SX4 is not set ++# CONFIG_ATA_BMDMA is not set ++ ++# ++# PIO-only SFF controllers ++# ++# CONFIG_PATA_CMD640_PCI is not set ++# CONFIG_PATA_MPIIX is not set ++# CONFIG_PATA_NS87410 is not set ++# CONFIG_PATA_OPTI is not set ++CONFIG_PATA_PLATFORM=y ++CONFIG_PATA_OF_PLATFORM=y ++# CONFIG_PATA_RZ1000 is not set ++ ++# ++# Generic fallback / legacy drivers ++# ++# CONFIG_PATA_LEGACY 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_MACINTOSH_DRIVERS is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++CONFIG_BONDING=y ++CONFIG_DUMMY=m ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC is not set ++CONFIG_MII=y ++CONFIG_MACVLAN=m ++# CONFIG_MACVTAP is not set ++CONFIG_VXLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_NETPOLL=y ++# CONFIG_NETPOLL_TRAP is not set ++CONFIG_NET_POLL_CONTROLLER=y ++CONFIG_TUN=m ++CONFIG_VETH=y ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++CONFIG_ETHERNET=y ++# CONFIG_NET_VENDOR_3COM is not set ++# CONFIG_NET_VENDOR_ADAPTEC is not set ++# CONFIG_NET_VENDOR_ALTEON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_VENDOR_ATHEROS 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_CISCO 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_FREESCALE=y ++# CONFIG_FS_ENET is not set ++CONFIG_FSL_PQ_MDIO=y ++# CONFIG_UCC_GETH is not set ++CONFIG_GIANFAR=y ++# CONFIG_NET_VENDOR_HP is not set ++CONFIG_NET_VENDOR_INTEL=y ++# CONFIG_E100 is not set ++# CONFIG_E1000 is not set ++# CONFIG_E1000E is not set ++# CONFIG_IGB is not set ++# CONFIG_IGBVF is not set ++# CONFIG_IXGB is not set ++# CONFIG_IXGBE is not set ++# CONFIG_NET_VENDOR_I825XX 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_REALTEK is not set ++# CONFIG_NET_VENDOR_RDC 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_XILINX is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++CONFIG_MARVELL_PHY=y ++# 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=y ++# 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_PPP is not set ++# CONFIG_SLIP is not set ++# CONFIG_TR is not set ++ ++# ++# USB Network Adapters ++# ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_AIRO is not set ++# CONFIG_ATMEL is not set ++# CONFIG_PRISM54 is not set ++# CONFIG_USB_ZD1201 is not set ++# CONFIG_HOSTAP is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_DPAA_ETH_USE_NDO_SELECT_QUEUE is not set ++# CONFIG_ISDN is not set ++# CONFIG_PHONE 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 ++ ++# ++# Userland interfaces ++# ++# CONFIG_INPUT_MOUSEDEV is not set ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_EVDEV is not set ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++# CONFIG_SERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++# CONFIG_VT is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++CONFIG_LEGACY_PTYS=y ++CONFIG_LEGACY_PTY_COUNT=256 ++# CONFIG_SERIAL_NONSTANDARD is not set ++# CONFIG_NOZOMI is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++# CONFIG_PPC_EPAPR_HV_BYTECHAN is not set ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_PCI is not set ++CONFIG_SERIAL_8250_NR_UARTS=4 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++CONFIG_SERIAL_8250_EXTENDED=y ++# CONFIG_SERIAL_8250_MANY_PORTS is not set ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++# CONFIG_SERIAL_8250_DETECT_IRQ is not set ++# CONFIG_SERIAL_8250_RSA is not set ++# CONFIG_SERIAL_8250_DW is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX3107 is not set ++# CONFIG_SERIAL_MFD_HSU is not set ++# CONFIG_SERIAL_UARTLITE is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_CPM is not set ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_OF_PLATFORM is not set ++# CONFIG_SERIAL_QE is not set ++# CONFIG_SERIAL_TIMBERDALE 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_XILINX_PS_UART is not set ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_HVC_UDBG is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_NVRAM 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_RAMOOPS is not set ++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_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++CONFIG_I2C_MUX_PCA954x=y ++CONFIG_I2C_MUX_DNI_6448=y ++CONFIG_I2C_MUX_QUANTA=m ++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_CEL_CPLD=m ++# CONFIG_I2C_CPM is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_INTEL_MID is not set ++CONFIG_I2C_MPC=y ++# CONFIG_I2C_OCORES is not set ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_PXA_PCI is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_XILINX is not set ++# CONFIG_I2C_EG20T is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_DIOLAN_U2C is not set ++# CONFIG_I2C_PARPORT_LIGHT 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_GPIO is not set ++CONFIG_SPI_FSL_LIB=y ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_FSL_ESPI=y ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_TOPCLIFF_PCH is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++# CONFIG_SPI_SPIDEV is not set ++# CONFIG_SPI_TLE62X0 is not set ++ ++# ++# PPS support ++# ++# CONFIG_PPS is not set ++ ++# ++# PPS generators support ++# ++ ++# ++# PTP clock support ++# ++ ++# ++# Enable Device Drivers -> PPS to see the PTP clock options. ++# ++CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_IT8761E is not set ++CONFIG_GPIO_MPC8XXX=y ++# CONFIG_GPIO_XILINX is not set ++# CONFIG_GPIO_VX855 is not set ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX7300 is not set ++# CONFIG_GPIO_MAX732X is not set ++CONFIG_GPIO_PCA953X=m ++# CONFIG_GPIO_PCF857X is not set ++# CONFIG_GPIO_SX150X is not set ++# CONFIG_GPIO_ADP5588 is not set ++ ++# ++# PCI GPIO expanders: ++# ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_RDC321X is not set ++ ++# ++# 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: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++CONFIG_HWMON=y ++CONFIG_HWMON_VID=m ++# CONFIG_HWMON_DEBUG_CHIP is not set ++ ++# ++# Native drivers ++# ++# CONFIG_SENSORS_AD7314 is not set ++# CONFIG_SENSORS_AD7414 is not set ++# CONFIG_SENSORS_AD7418 is not set ++# CONFIG_SENSORS_ADCXX is not set ++CONFIG_SENSORS_ADM1021=m ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1029 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ADT7411 is not set ++# CONFIG_SENSORS_ADT7462 is not set ++CONFIG_SENSORS_ADT7470=m ++CONFIG_SENSORS_ADT7475=m ++# CONFIG_SENSORS_ASC7621 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++CONFIG_SENSORS_CY8CXX=m ++CONFIG_SENSORS_CY8C3245R1=m ++# CONFIG_SENSORS_DS620 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_I5K_AMB is not set ++# CONFIG_SENSORS_F75375S is not set ++# CONFIG_SENSORS_G760A is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_GPIO_FAN is not set ++# CONFIG_SENSORS_JC42 is not set ++# CONFIG_SENSORS_LINEAGE is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM70 is not set ++# CONFIG_SENSORS_LM73 is not set ++CONFIG_SENSORS_LM75=m ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++CONFIG_SENSORS_LM85=m ++# CONFIG_SENSORS_LM87 is not set ++CONFIG_SENSORS_LM90=m ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_LM93 is not set ++# CONFIG_SENSORS_LTC4151 is not set ++CONFIG_SENSORS_LTC4215=m ++# CONFIG_SENSORS_LTC4245 is not set ++# CONFIG_SENSORS_LTC4261 is not set ++# CONFIG_SENSORS_LM95241 is not set ++# CONFIG_SENSORS_LM95245 is not set ++# CONFIG_SENSORS_MAX1111 is not set ++# CONFIG_SENSORS_MAX16065 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_MAX1668 is not set ++# CONFIG_SENSORS_MAX6639 is not set ++# CONFIG_SENSORS_MAX6642 is not set ++CONFIG_SENSORS_MAX6650=m ++CONFIG_SENSORS_MAX6620=m ++CONFIG_SENSORS_MAX6697=m ++# CONFIG_SENSORS_NTC_THERMISTOR is not set ++# CONFIG_SENSORS_PCF8591 is not set ++CONFIG_PMBUS=m ++CONFIG_SENSORS_PMBUS=m ++# CONFIG_SENSORS_ADM1275 is not set ++# CONFIG_SENSORS_LM25066 is not set ++# CONFIG_SENSORS_LTC2978 is not set ++# CONFIG_SENSORS_MAX16064 is not set ++# CONFIG_SENSORS_MAX34440 is not set ++# CONFIG_SENSORS_MAX8688 is not set ++# CONFIG_SENSORS_UCD9000 is not set ++# CONFIG_SENSORS_UCD9200 is not set ++# CONFIG_SENSORS_ZL6100 is not set ++CONFIG_SENSORS_DPS460=m ++CONFIG_SENSORS_PS2471=m ++CONFIG_SENSORS_CPR4011=m ++# CONFIG_SENSORS_SHT15 is not set ++# CONFIG_SENSORS_SHT21 is not set ++# CONFIG_SENSORS_SIS5595 is not set ++# CONFIG_SENSORS_SMM665 is not set ++# CONFIG_SENSORS_EMC1403 is not set ++# CONFIG_SENSORS_EMC2103 is not set ++CONFIG_SENSORS_EMC2305=m ++# CONFIG_SENSORS_EMC6W201 is not set ++# CONFIG_SENSORS_SMSC47M192 is not set ++# CONFIG_SENSORS_SCH56XX_COMMON is not set ++# CONFIG_SENSORS_ADS1015 is not set ++# CONFIG_SENSORS_ADS7828 is not set ++# CONFIG_SENSORS_ADS7871 is not set ++# CONFIG_SENSORS_AMC6821 is not set ++# CONFIG_SENSORS_THMC50 is not set ++# CONFIG_SENSORS_TMP102 is not set ++# CONFIG_SENSORS_TMP401 is not set ++# CONFIG_SENSORS_TMP421 is not set ++# CONFIG_SENSORS_VIA686A is not set ++# CONFIG_SENSORS_VT8231 is not set ++CONFIG_SENSORS_W83781D=m ++# CONFIG_SENSORS_W83791D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83793 is not set ++# CONFIG_SENSORS_W83795 is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83L786NG is not set ++CONFIG_THERMAL=y ++CONFIG_THERMAL_HWMON=y ++CONFIG_WATCHDOG=y ++CONFIG_WATCHDOG_CORE=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++# CONFIG_ALIM7101_WDT is not set ++CONFIG_BOOKE_WDT=m ++CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT=20 ++ ++# ++# PCI-based Watchdog Cards ++# ++# CONFIG_PCIPCWATCHDOG is not set ++# CONFIG_WDTPCI is not set ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG 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_88PM860X is not set ++# CONFIG_MFD_SM501 is not set ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_TPS6105X is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_TPS6507X 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_TWL4030_CORE is not set ++# CONFIG_MFD_STMPE is not set ++# CONFIG_MFD_TC3589X is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_PMIC_DA903X is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_MAX8925 is not set ++# CONFIG_MFD_MAX8997 is not set ++# CONFIG_MFD_MAX8998 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_PCF50633 is not set ++# CONFIG_MFD_MC13XXX is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_EZX_PCAP is not set ++# CONFIG_MFD_TIMBERDALE is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_MFD_RDC321X is not set ++# CONFIG_MFD_JANZ_CMODIO is not set ++# CONFIG_MFD_VX855 is not set ++# CONFIG_MFD_WL1273_CORE is not set ++# CONFIG_MFD_AAT2870_CORE is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_AGP is not set ++# CONFIG_VGA_ARB is not set ++# CONFIG_DRM is not set ++# CONFIG_STUB_POULSBO is not set ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++# CONFIG_FB is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Display device support ++# ++# CONFIG_DISPLAY_SUPPORT is not set ++# CONFIG_SOUND is not set ++CONFIG_HID_SUPPORT=y ++CONFIG_HID=y ++# CONFIG_HIDRAW is not set ++ ++# ++# USB Input Devices ++# ++# CONFIG_USB_HID is not set ++# CONFIG_HID_PID is not set ++ ++# ++# USB HID Boot Protocol drivers ++# ++# CONFIG_USB_KBD is not set ++# CONFIG_USB_MOUSE is not set ++ ++# ++# Special HID drivers ++# ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_COMMON=y ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB_ARCH_HAS_EHCI=y ++CONFIG_USB_ARCH_HAS_XHCI=y ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEVICEFS is not set ++CONFIG_USB_DEVICE_CLASS=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_DWC3 is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB 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=y ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++# CONFIG_XPS_USB_HCD_XILINX is not set ++CONFIG_USB_FSL_MPH_DR_OF=y ++CONFIG_USB_EHCI_FSL=y ++CONFIG_USB_EHCI_HCD_PPC_OF=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_OHCI_HCD is not set ++# CONFIG_USB_UHCI_HCD is not set ++# CONFIG_USB_FHCI_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_WHCI_HCD is not set ++# CONFIG_USB_HWA_HCD 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_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB port drivers ++# ++CONFIG_USB_SERIAL=y ++CONFIG_USB_SERIAL_CONSOLE=y ++# CONFIG_USB_EZUSB is not set ++# CONFIG_USB_SERIAL_GENERIC is not set ++# CONFIG_USB_SERIAL_AIRCABLE is not set ++# CONFIG_USB_SERIAL_ARK3116 is not set ++# CONFIG_USB_SERIAL_BELKIN is not set ++# CONFIG_USB_SERIAL_CH341 is not set ++# CONFIG_USB_SERIAL_WHITEHEAT is not set ++# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set ++# CONFIG_USB_SERIAL_CP210X is not set ++# CONFIG_USB_SERIAL_CYPRESS_M8 is not set ++# CONFIG_USB_SERIAL_EMPEG is not set ++# CONFIG_USB_SERIAL_FTDI_SIO is not set ++# CONFIG_USB_SERIAL_FUNSOFT is not set ++# CONFIG_USB_SERIAL_VISOR is not set ++# CONFIG_USB_SERIAL_IPAQ is not set ++# CONFIG_USB_SERIAL_IR is not set ++# CONFIG_USB_SERIAL_EDGEPORT is not set ++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set ++# CONFIG_USB_SERIAL_GARMIN is not set ++# CONFIG_USB_SERIAL_IPW is not set ++# CONFIG_USB_SERIAL_IUU is not set ++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set ++# CONFIG_USB_SERIAL_KEYSPAN is not set ++# CONFIG_USB_SERIAL_KLSI is not set ++# CONFIG_USB_SERIAL_KOBIL_SCT is not set ++# CONFIG_USB_SERIAL_MCT_U232 is not set ++# CONFIG_USB_SERIAL_MOS7720 is not set ++# CONFIG_USB_SERIAL_MOS7840 is not set ++# CONFIG_USB_SERIAL_MOTOROLA is not set ++# CONFIG_USB_SERIAL_NAVMAN is not set ++# CONFIG_USB_SERIAL_PL2303 is not set ++# CONFIG_USB_SERIAL_OTI6858 is not set ++# CONFIG_USB_SERIAL_QCAUX is not set ++# CONFIG_USB_SERIAL_QUALCOMM is not set ++# CONFIG_USB_SERIAL_SPCP8X5 is not set ++# CONFIG_USB_SERIAL_HP4X is not set ++# CONFIG_USB_SERIAL_SAFE is not set ++# CONFIG_USB_SERIAL_SIEMENS_MPI is not set ++# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set ++# CONFIG_USB_SERIAL_SYMBOL is not set ++# CONFIG_USB_SERIAL_TI is not set ++# CONFIG_USB_SERIAL_CYBERJACK is not set ++# CONFIG_USB_SERIAL_XIRCOM is not set ++# CONFIG_USB_SERIAL_OPTION is not set ++# CONFIG_USB_SERIAL_OMNINET is not set ++# CONFIG_USB_SERIAL_OPTICON is not set ++# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set ++# CONFIG_USB_SERIAL_ZIO is not set ++# CONFIG_USB_SERIAL_SSU100 is not set ++# CONFIG_USB_SERIAL_DEBUG 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_ISIGHTFW is not set ++# CONFIG_USB_YUREX is not set ++# CONFIG_USB_GADGET is not set ++ ++# ++# OTG and related infrastructure ++# ++# CONFIG_USB_GPIO_VBUS is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_IO_ACCESSORS=y ++CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER=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_ESDHC=y ++# CONFIG_MMC_SDHCI_OF_HLWD is not set ++# CONFIG_MMC_WBSD is not set ++# CONFIG_MMC_TIFM_SD is not set ++# CONFIG_MMC_CB710 is not set ++# CONFIG_MMC_VIA_SDMMC is not set ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MEMSTICK is not set ++CONFIG_NEW_LEDS=y ++# CONFIG_LEDS_CLASS is not set ++ ++# ++# LED drivers ++# ++ ++# ++# LED Triggers ++# ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_INFINIBAND is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_HCTOSYS=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=y ++CONFIG_RTC_DRV_DS1374=y ++CONFIG_RTC_DRV_DS1672=y ++# CONFIG_RTC_DRV_DS3232 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_PCF8563=y ++# CONFIG_RTC_DRV_PCF8583 is not set ++CONFIG_RTC_DRV_M41T80=y ++# CONFIG_RTC_DRV_M41T80_WDT 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_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 ++ ++# ++# Platform RTC drivers ++# ++# CONFIG_RTC_DRV_CMOS is not set ++# CONFIG_RTC_DRV_DS1286 is not set ++# CONFIG_RTC_DRV_DS1511 is not set ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 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_GENERIC is not set ++# CONFIG_DMADEVICES is not set ++# CONFIG_AUXDISPLAY is not set ++# CONFIG_UIO is not set ++ ++# ++# Virtio drivers ++# ++# CONFIG_VIRTIO_PCI is not set ++# CONFIG_VIRTIO_BALLOON is not set ++# CONFIG_VIRTIO_MMIO is not set ++# CONFIG_STAGING is not set ++ ++# ++# Hardware Spinlock drivers ++# ++# CONFIG_IOMMU_SUPPORT is not set ++# CONFIG_VIRT_DRIVERS is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++# CONFIG_PM_DEVFREQ is not set ++ ++# ++# Frame Manager support ++# ++# CONFIG_FSL_FMAN is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++# CONFIG_EXT2_FS_POSIX_ACL is not set ++# CONFIG_EXT2_FS_SECURITY is not set ++# CONFIG_EXT2_FS_XIP is not set ++CONFIG_EXT3_FS=y ++# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set ++CONFIG_EXT3_FS_XATTR=y ++# CONFIG_EXT3_FS_POSIX_ACL is not set ++# CONFIG_EXT3_FS_SECURITY is not set ++# CONFIG_EXT4_FS is not set ++CONFIG_JBD=y ++# CONFIG_JBD_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_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++# CONFIG_FS_POSIX_ACL is not set ++CONFIG_EXPORTFS=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=y ++CONFIG_OVERLAYFS_FS=y ++# CONFIG_CUSE is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++# 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_KCORE=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++# CONFIG_TMPFS_POSIX_ACL is not set ++CONFIG_TMPFS_XATTR=y ++# CONFIG_HUGETLB_PAGE is not set ++# CONFIG_CONFIGFS_FS is not set ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_ECRYPT_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set ++CONFIG_JFFS2_SUMMARY=y ++# 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_XATTR=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_FS_DEBUG is not set ++# CONFIG_LOGFS is not set ++# CONFIG_CRAMFS is not set ++CONFIG_SQUASHFS=y ++# CONFIG_SQUASHFS_XATTR is not set ++# CONFIG_SQUASHFS_ZLIB 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_ROMFS_FS is not set ++# CONFIG_PSTORE is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_AUFS_FS=m ++CONFIG_AUFS_BRANCH_MAX_127=y ++# CONFIG_AUFS_BRANCH_MAX_511 is not set ++# CONFIG_AUFS_BRANCH_MAX_1023 is not set ++# CONFIG_AUFS_BRANCH_MAX_32767 is not set ++CONFIG_AUFS_SBILIST=y ++# CONFIG_AUFS_HNOTIFY is not set ++# CONFIG_AUFS_EXPORT is not set ++# CONFIG_AUFS_RDU is not set ++# CONFIG_AUFS_PROC_MAP is not set ++# CONFIG_AUFS_SP_IATTR is not set ++# CONFIG_AUFS_SHWH is not set ++# CONFIG_AUFS_BR_RAMFS is not set ++# CONFIG_AUFS_BR_FUSE is not set ++CONFIG_AUFS_BDEV_LOOP=y ++# CONFIG_AUFS_DEBUG is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++CONFIG_NFS_V4=y ++# 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_NFS_USE_NEW_IDMAPPER is not set ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=y ++# 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 ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_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 is not set ++# CONFIG_SYSV68_PARTITION 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=m ++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_UTF8=y ++CONFIG_BINARY_PRINTF=y ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++# CONFIG_CRC_CCITT is not set ++CONFIG_CRC16=y ++CONFIG_CRC_T10DIF=y ++# CONFIG_CRC_ITU_T is not set ++CONFIG_CRC32=y ++# CONFIG_CRC7 is not set ++CONFIG_LIBCRC32C=m ++# CONFIG_CRC8 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 is not set ++# CONFIG_XZ_DEC_ARM is not set ++# CONFIG_XZ_DEC_ARMTHUMB is not set ++# CONFIG_XZ_DEC_SPARC is not set ++CONFIG_XZ_DEC_BCJ=y ++# CONFIG_XZ_DEC_TEST is not set ++CONFIG_DECOMPRESS_GZIP=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_TEXTSEARCH=y ++CONFIG_TEXTSEARCH_KMP=m ++CONFIG_TEXTSEARCH_BM=m ++CONFIG_TEXTSEARCH_FSM=m ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_GENERIC_ATOMIC64=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++ ++# ++# Kernel hacking ++# ++CONFIG_PRINTK_TIME=y ++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAGIC_SYSRQ_DEFAULT_MASK=0x1 ++CONFIG_STRIP_ASM_SYMS=y ++# CONFIG_UNUSED_SYMBOLS is not set ++CONFIG_DEBUG_FS=y ++CONFIG_HEADERS_CHECK=y ++CONFIG_DEBUG_SECTION_MISMATCH=y ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_SHIRQ is not set ++CONFIG_LOCKUP_DETECTOR=y ++# CONFIG_HARDLOCKUP_DETECTOR is not set ++CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y ++CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=1 ++# 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_PANIC_TIMEOUT=5 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++CONFIG_TIMER_STATS=y ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_STATS is not set ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_RT_MUTEX_TESTER is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_SPARSE_RCU_POINTER 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_STACKTRACE=y ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_KOBJECT is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_INFO=y ++# CONFIG_DEBUG_INFO_REDUCED is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_WRITECOUNT is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_LKDTM is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP is not set ++# CONFIG_SYSCTL_SYSCALL_CHECK is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++CONFIG_NOP_TRACER=y ++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_RING_BUFFER=y ++CONFIG_EVENT_TRACING=y ++CONFIG_EVENT_POWER_TRACING_DEPRECATED=y ++CONFIG_CONTEXT_SWITCH_TRACER=y ++CONFIG_RING_BUFFER_ALLOW_SWAP=y ++CONFIG_TRACING=y ++CONFIG_GENERIC_TRACER=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_FTRACE_SYSCALLS 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=y ++# CONFIG_FTRACE_STARTUP_TEST is not set ++# CONFIG_RING_BUFFER_BENCHMARK is not set ++# CONFIG_BUILD_DOCSRC is not set ++CONFIG_DYNAMIC_DEBUG=y ++# CONFIG_DMA_API_DEBUG is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_PPC_DISABLE_WERROR is not set ++CONFIG_PPC_WERROR=y ++CONFIG_PRINT_STACK_DEPTH=64 ++# CONFIG_DEBUG_STACKOVERFLOW is not set ++# CONFIG_PPC_EMULATED_STATS is not set ++# CONFIG_CODE_PATCHING_SELFTEST is not set ++# CONFIG_FTR_FIXUP_SELFTEST is not set ++# CONFIG_MSI_BITMAP_SELFTEST is not set ++# CONFIG_XMON is not set ++# CONFIG_VIRQ_DEBUG is not set ++# CONFIG_BDI_SWITCH is not set ++# CONFIG_JTAG_DEBUGGER is not set ++# CONFIG_PPC_EARLY_DEBUG is not set ++ ++# ++# Security options ++# ++CONFIG_KEYS=y ++# CONFIG_ENCRYPTED_KEYS is not set ++# CONFIG_KEYS_DEBUG_PROC_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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=m ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=m ++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_PCRYPT is not set ++CONFIG_CRYPTO_WORKQUEUE=y ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=m ++# 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=m ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++CONFIG_CRYPTO_ECB=m ++# CONFIG_CRYPTO_LRW is not set ++CONFIG_CRYPTO_PCBC=m ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=m ++# CONFIG_CRYPTO_GHASH 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=m ++CONFIG_CRYPTO_SHA256=m ++CONFIG_CRYPTO_SHA512=m ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=m ++# 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=m ++# 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 ++ ++# ++# Random Number Generation ++# ++# CONFIG_CRYPTO_ANSI_CPRNG 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_CRYPTO_DEV_FSL_CAAM is not set ++CONFIG_CRYPTO_DEV_TALITOS=m ++CONFIG_PPC_CLOCK=y ++CONFIG_PPC_LIB_RHEAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/debian/config/powerpc/config.powerpc b/debian/config/powerpc/config.powerpc +new file mode 100644 +index 0000000..7e1f73b +--- /dev/null ++++ b/debian/config/powerpc/config.powerpc +@@ -0,0 +1,106 @@ ++## ++## file: arch/powerpc/Kconfig ++## ++CONFIG_HIGHMEM=y ++# CONFIG_ISA is not set ++ ++## ++## file: arch/powerpc/platforms/512x/Kconfig ++## ++# CONFIG_MPC5121_ADS is not set ++ ++## ++## file: arch/powerpc/platforms/52xx/Kconfig ++## ++CONFIG_PPC_MPC52xx=y ++# CONFIG_PPC_MPC5200_SIMPLE is not set ++CONFIG_PPC_EFIKA=y ++# CONFIG_PPC_LITE5200 is not set ++CONFIG_PPC_MPC5200_BUGFIX=y ++ ++## ++## file: arch/powerpc/platforms/chrp/Kconfig ++## ++CONFIG_PPC_CHRP=y ++ ++## ++## file: arch/powerpc/platforms/Kconfig.cputype ++## ++# CONFIG_PPC64 is not set ++## choice: Processor Type ++# CONFIG_PPC_85xx is not set ++# CONFIG_PPC_8xx is not set ++# CONFIG_40x is not set ++# CONFIG_44x is not set ++# CONFIG_E200 is not set ++## end choice ++CONFIG_ALTIVEC=y ++# CONFIG_SMP is not set ++ ++## ++## file: arch/powerpc/platforms/prep/Kconfig ++## ++# CONFIG_PPC_PREP is not set ++ ++## ++## file: arch/powerpc/sysdev/bestcomm/Kconfig ++## ++CONFIG_PPC_BESTCOMM=m ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_PATA_MPC52xx=m ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_MAC_FLOPPY=y ++ ++## ++## file: drivers/macintosh/Kconfig ++## ++CONFIG_SENSORS_AMS=m ++CONFIG_SENSORS_AMS_PMU=y ++CONFIG_SENSORS_AMS_I2C=y ++ ++## ++## file: drivers/net/Kconfig ++## ++CONFIG_MII=y ++ ++## ++## file: drivers/net/ethernet/freescale/Kconfig ++## ++CONFIG_FEC_MPC52xx=m ++CONFIG_FEC_MPC52xx_MDIO=y ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI_MPC52xx_PSC=m ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_MPC52xx=y ++CONFIG_SERIAL_MPC52xx_CONSOLE=y ++CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200 ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB_CONTROL=y ++CONFIG_FB_PLATINUM=y ++CONFIG_FB_VALKYRIE=y ++CONFIG_FB_IMSTT=y ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++## end choice ++ +diff --git a/debian/config/powerpc/config.powerpc-smp b/debian/config/powerpc/config.powerpc-smp +new file mode 100644 +index 0000000..494c00d +--- /dev/null ++++ b/debian/config/powerpc/config.powerpc-smp +@@ -0,0 +1,5 @@ ++## ++## file: arch/powerpc/platforms/Kconfig.cputype ++## ++CONFIG_SMP=y ++ +diff --git a/debian/config/powerpc/config.powerpc64 b/debian/config/powerpc/config.powerpc64 +new file mode 100644 +index 0000000..5b29c83 +--- /dev/null ++++ b/debian/config/powerpc/config.powerpc64 +@@ -0,0 +1,212 @@ ++## ++## file: arch/powerpc/Kconfig ++## ++# CONFIG_CRASH_DUMP is not set ++CONFIG_IRQ_ALL_CPUS=y ++CONFIG_NUMA=y ++## choice: Page size ++# CONFIG_PPC_64K_PAGES is not set ++## end choice ++CONFIG_SCHED_SMT=y ++CONFIG_CMDLINE="console=hvsi0 console=hvc0 console=ttyS0,9600 console=tty0" ++CONFIG_KERNEL_START=0xc000000000000000 ++ ++## ++## file: arch/powerpc/platforms/Kconfig ++## ++CONFIG_RTAS_PROC=y ++CONFIG_RTAS_FLASH=m ++CONFIG_IBMEBUS=y ++CONFIG_CPU_FREQ_PMAC64=y ++#. It's a bool ++CONFIG_PPC_PASEMI_CPUFREQ=y ++ ++## ++## file: arch/powerpc/platforms/cell/Kconfig ++## ++CONFIG_PPC_IBM_CELL_BLADE=y ++# CONFIG_PPC_CELLEB is not set ++CONFIG_SPU_FS=m ++CONFIG_SPU_FS_64K_LS=y ++CONFIG_CBE_RAS=y ++CONFIG_CBE_THERM=m ++CONFIG_CBE_CPUFREQ=m ++ ++## ++## file: arch/powerpc/platforms/Kconfig.cputype ++## ++CONFIG_PPC64=y ++# CONFIG_POWER4_ONLY is not set ++# CONFIG_TUNE_CELL is not set ++CONFIG_ALTIVEC=y ++CONFIG_VIRT_CPU_ACCOUNTING=y ++CONFIG_SMP=y ++CONFIG_NR_CPUS=32 ++ ++## ++## file: arch/powerpc/platforms/iseries/Kconfig ++## ++# CONFIG_PPC_ISERIES is not set ++ ++## ++## file: arch/powerpc/platforms/maple/Kconfig ++## ++CONFIG_PPC_MAPLE=y ++ ++## ++## file: arch/powerpc/platforms/pasemi/Kconfig ++## ++CONFIG_PPC_PASEMI=y ++CONFIG_PPC_PASEMI_MDIO=m ++ ++## ++## file: arch/powerpc/platforms/ps3/Kconfig ++## ++CONFIG_PPC_PS3=y ++CONFIG_PS3_ADVANCED=y ++CONFIG_PS3_HTAB_SIZE=20 ++# CONFIG_PS3_DYNAMIC_DMA is not set ++CONFIG_PS3_PS3AV=y ++CONFIG_PS3_SYS_MANAGER=y ++CONFIG_PS3_DISK=m ++CONFIG_PS3_ROM=m ++CONFIG_PS3_FLASH=m ++CONFIG_PS3_VRAM=m ++CONFIG_PS3_LPM=m ++ ++## ++## file: arch/powerpc/platforms/pseries/Kconfig ++## ++CONFIG_PPC_PSERIES=y ++CONFIG_PPC_SPLPAR=y ++CONFIG_SCANLOG=m ++# CONFIG_LPARCFG is not set ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_PATA_AMD=m ++ ++## ++## file: drivers/block/Kconfig ++## ++# CONFIG_MAC_FLOPPY is not set ++ ++## ++## file: drivers/char/hw_random/Kconfig ++## ++CONFIG_HW_RANDOM=m ++CONFIG_HW_RANDOM_PASEMI=m ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_PASEMI=m ++ ++## ++## file: drivers/macintosh/Kconfig ++## ++CONFIG_WINDFARM=m ++CONFIG_WINDFARM_PM81=m ++CONFIG_WINDFARM_PM91=m ++CONFIG_WINDFARM_PM112=m ++ ++## ++## file: drivers/net/ethernet/ibm/Kconfig ++## ++CONFIG_IBMVETH=m ++CONFIG_EHEA=m ++ ++## ++## file: drivers/net/ethernet/ibm/emac/Kconfig ++## ++CONFIG_IBM_EMAC=m ++# CONFIG_IBM_EMAC_DEBUG is not set ++CONFIG_IBM_EMAC_POLL_WEIGHT=32 ++CONFIG_IBM_EMAC_RXB=128 ++CONFIG_IBM_EMAC_RX_COPY_THRESHOLD=256 ++CONFIG_IBM_EMAC_RX_SKB_HEADROOM=0 ++CONFIG_IBM_EMAC_TXB=64 ++ ++## ++## file: drivers/net/ethernet/marvell/Kconfig ++## ++# CONFIG_MV643XX_ETH is not set ++ ++## ++## file: drivers/net/ethernet/pasemi/Kconfig ++## ++CONFIG_PASEMI_MAC=m ++ ++## ++## file: drivers/net/ethernet/toshiba/Kconfig ++## ++CONFIG_GELIC_NET=m ++CONFIG_GELIC_WIRELESS=y ++CONFIG_SPIDER_NET=m ++ ++## ++## file: drivers/pci/hotplug/Kconfig ++## ++# CONFIG_HOTPLUG_PCI is not set ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_PS3=m ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI_IBMVSCSI=m ++CONFIG_SCSI_IBMVSCSIS=m ++CONFIG_SCSI_QLOGIC_1280=m ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++CONFIG_MEGARAID_LEGACY=m ++ ++## ++## file: drivers/tty/hvc/Kconfig ++## ++CONFIG_HVC_CONSOLE=y ++CONFIG_HVCS=m ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++# CONFIG_SERIAL_ICOM is not set ++ ++## ++## file: drivers/video/Kconfig ++## ++# CONFIG_FB_CONTROL is not set ++# CONFIG_FB_PLATINUM is not set ++# CONFIG_FB_VALKYRIE is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_ATY128 is not set ++CONFIG_FB_PS3=y ++CONFIG_FB_PS3_DEFAULT_SIZE_M=9 ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_WATCHDOG_RTAS=m ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++# CONFIG_FLATMEM_MANUAL is not set ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++CONFIG_SPARSEMEM_MANUAL=y ++## end choice ++CONFIG_SPARSEMEM_VMEMMAP=y ++ ++## ++## file: sound/ppc/Kconfig ++## ++CONFIG_SND_PS3=m ++CONFIG_SND_PS3_DEFAULT_START_DELAY=2000 ++ +diff --git a/debian/config/powerpc/defines b/debian/config/powerpc/defines +new file mode 100644 +index 0000000..c88f091 +--- /dev/null ++++ b/debian/config/powerpc/defines +@@ -0,0 +1,21 @@ ++[base] ++flavours: ++ powerpc ++ powerpc-smp ++ powerpc64 ++kernel-arch: powerpc ++ ++[image] ++suggests: mkvmlinuz ++ ++[powerpc_description] ++hardware: uniprocessor 32-bit PowerPC ++ ++[powerpc-smp_description] ++hardware: multiprocessor 32-bit PowerPC ++ ++[powerpc-smp_image] ++configs: powerpc/config-cumulus ++ ++[powerpc64_description] ++hardware: 64-bit PowerPC +diff --git a/debian/config/powerpc/uImage-powerpc.its b/debian/config/powerpc/uImage-powerpc.its +new file mode 100644 +index 0000000..9ca4ca2 +--- /dev/null ++++ b/debian/config/powerpc/uImage-powerpc.its +@@ -0,0 +1,339 @@ ++/* ++** ++** Copyright 2014 Cumulus Networks, Inc. ++** All rights reserved. ++** ++** ++** U-boot uImage source file with multiple kernels, ramdisks and FDT ++** blobs. ++** ++** ++** Note: The /incbin/() paths used below are relative to the location ++** of this file. That's just how the tool works. ++** ++** ++*/ ++ ++/dts-v1/; ++ ++/ { ++ description = "PowerPC kernel, initramfs and FDT blobs"; ++ #address-cells = <1>; ++ ++ images { ++ kernel { ++ description = "PowerPC Kernel"; ++ data = /incbin/("vmlinux.bin.gz"); ++ type = "kernel"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "gzip"; ++ load = <00000000>; ++ entry = <00000000>; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ initramfs { ++ description = "initramfs"; ++ data = /incbin/("../../initramfs-powerpc.cpio.xz"); ++ type = "ramdisk"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ load = <00000000>; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ /* Device Tree Blobs */ ++ accton_as4600_54t_dtb { ++ description = "accton_as4600_54t.dtb"; ++ data = /incbin/("../dtb/accton_as4600_54t.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ accton_as6701_32x_dtb { ++ description = "accton_as6701_32x.dtb"; ++ data = /incbin/("../dtb/accton_as6701_32x.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ accton_5652_dtb { ++ description = "accton_5652.dtb"; ++ data = /incbin/("../dtb/accton_5652.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ accton_as5610_52x_dtb { ++ description = "accton_as5610_52x.dtb"; ++ data = /incbin/("../dtb/accton_as5610_52x.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ dni_6448_dtb { ++ description = "dni_6448.dtb"; ++ data = /incbin/("../dtb/dni_6448.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ dni_7448_dtb { ++ description = "dni_7448.dtb"; ++ data = /incbin/("../dtb/dni_7448.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ dni_c7448n_dtb { ++ description = "dni_c7448n.dtb"; ++ data = /incbin/("../dtb/dni_c7448n.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ cel_kennisis_dtb { ++ description = "cel_kennisis.dtb"; ++ data = /incbin/("../dtb/cel_kennisis.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ cel_redstone_dtb { ++ description = "cel_redstone.dtb"; ++ data = /incbin/("../dtb/cel_redstone.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ cel_smallstone_dtb { ++ description = "cel_smallstone.dtb"; ++ data = /incbin/("../dtb/cel_smallstone.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ cumulus_p2020_dtb { ++ description = "cumulus_p2020.dtb"; ++ data = /incbin/("../dtb/cumulus_p2020.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ quanta_lb9_dtb { ++ description = "quanta_lb9.dtb"; ++ data = /incbin/("../dtb/quanta_lb9.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ quanta_ly2_dtb { ++ description = "quanta_ly2.dtb"; ++ data = /incbin/("../dtb/quanta_ly2.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++ quanta_ly2r_dtb { ++ description = "quanta_ly2r.dtb"; ++ data = /incbin/("../dtb/quanta_ly2r.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ ++quanta_ly6_p2020_dtb { ++ description = "quanta_ly6_p2020.dtb"; ++ data = /incbin/("../dtb/quanta_ly6_p2020.dtb"); ++ type = "flat_dt"; ++ arch = "ppc"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "crc32"; ++ }; ++ }; ++ }; ++ ++ configurations { ++ ++ accton_as4600_54t { ++ description = "Accton as4600_54t"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "accton_as4600_54t_dtb"; ++ }; ++ ++ accton_as6701_32x { ++ description = "Accton AS6701-32X"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "accton_as6701_32x_dtb"; ++ }; ++ ++ accton_5652 { ++ description = "Accton 5652"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "accton_5652_dtb"; ++ }; ++ accton_as5610_52x { ++ description = "Accton AS5610_52X"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "accton_as5610_52x_dtb"; ++ }; ++ ++ dni_6448 { ++ description = "DNI 6448"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "dni_6448_dtb"; ++ }; ++ ++ dni_7448 { ++ description = "DNI 7448"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "dni_7448_dtb"; ++ }; ++ ++ dni_c7448n { ++ description = "DNI C7448N"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "dni_c7448n_dtb"; ++ }; ++ ++ cel_kennisis { ++ description = "Celestica Kennisis"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "cel_kennisis_dtb"; ++ }; ++ ++ cel_redstone { ++ description = "Celestica Redstone"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "cel_redstone_dtb"; ++ }; ++ ++ cel_smallstone { ++ description = "Celestica Smallstone"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "cel_smallstone_dtb"; ++ }; ++ ++ cumulus_p2020 { ++ description = "Cumulus P2020"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "cumulus_p2020_dtb"; ++ }; ++ ++ quanta_lb9 { ++ description = "Quanta LB9"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "quanta_lb9_dtb"; ++ }; ++ ++ quanta_ly2 { ++ description = "Quanta LY2"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "quanta_ly2_dtb"; ++ }; ++ ++ quanta_ly2r { ++ description = "Quanta LY2R"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "quanta_ly2r_dtb"; ++ }; ++ ++ quanta_ly6_p2020 { ++ description = "Quanta LY6, P2020"; ++ kernel = "kernel"; ++ ramdisk = "initramfs"; ++ fdt = "quanta_ly6_p2020_dtb"; ++ }; ++ }; ++}; +diff --git a/debian/config/ppc64/defines b/debian/config/ppc64/defines +new file mode 100644 +index 0000000..db1957a +--- /dev/null ++++ b/debian/config/ppc64/defines +@@ -0,0 +1,14 @@ ++[base] ++flavours: ++ powerpc64 ++kernel-arch: powerpc ++ ++[image] ++configs: powerpc/config ++suggests: mkvmlinuz ++ ++[powerpc64_description] ++hardware: 64-bit PowerPC ++ ++[powerpc64_image] ++configs: powerpc/config.powerpc64 +diff --git a/debian/config/s390/config b/debian/config/s390/config +new file mode 100644 +index 0000000..589f96d +--- /dev/null ++++ b/debian/config/s390/config +@@ -0,0 +1,194 @@ ++## ++## file: arch/s390/Kconfig ++## ++CONFIG_SMP=y ++CONFIG_NR_CPUS=32 ++CONFIG_HOTPLUG_CPU=y ++CONFIG_MATHEMU=y ++CONFIG_COMPAT=y ++CONFIG_PACK_STACK=y ++# CONFIG_SMALL_STACK is not set ++# CONFIG_CHECK_STACK is not set ++CONFIG_QDIO=y ++CONFIG_IPL=y ++CONFIG_PFAULT=y ++# CONFIG_SHARED_KERNEL is not set ++CONFIG_CMM=y ++CONFIG_CMM_IUCV=y ++CONFIG_APPLDATA_BASE=y ++CONFIG_APPLDATA_MEM=m ++CONFIG_APPLDATA_OS=m ++CONFIG_APPLDATA_NET_SUM=m ++CONFIG_S390_HYPFS_FS=y ++CONFIG_KEXEC=y ++# CONFIG_ZFCPDUMP is not set ++CONFIG_S390_GUEST=y ++CONFIG_SECCOMP=y ++ ++## ++## file: arch/s390/kvm/Kconfig ++## ++CONFIG_VIRTUALIZATION=y ++CONFIG_KVM=m ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_DEV_RAM_SIZE=24576 ++# CONFIG_CDROM_PKTCDVD is not set ++ ++## ++## file: drivers/crypto/Kconfig ++## ++CONFIG_ZCRYPT=m ++# CONFIG_ZCRYPT_MONOLITHIC is not set ++CONFIG_CRYPTO_SHA1_S390=m ++CONFIG_CRYPTO_SHA256_S390=m ++CONFIG_CRYPTO_SHA512_S390=m ++CONFIG_CRYPTO_DES_S390=m ++CONFIG_CRYPTO_AES_S390=m ++CONFIG_S390_PRNG=m ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_INPUT_TOUCHSCREEN is not set ++ ++## ++## file: drivers/memstick/Kconfig ++## ++# CONFIG_MEMSTICK is not set ++ ++## ++## file: drivers/net/appletalk/Kconfig ++## ++# CONFIG_ATALK is not set ++ ++## ++## file: drivers/net/ppp/Kconfig ++## ++# CONFIG_PPP is not set ++ ++## ++## file: drivers/net/slip/Kconfig ++## ++# CONFIG_SLIP is not set ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++# CONFIG_WAN is not set ++ ++## ++## file: drivers/s390/block/Kconfig ++## ++CONFIG_BLK_DEV_XPRAM=m ++CONFIG_DCSSBLK=m ++CONFIG_DASD=m ++# CONFIG_DASD_PROFILE is not set ++CONFIG_DASD_ECKD=m ++CONFIG_DASD_FBA=m ++CONFIG_DASD_DIAG=m ++# CONFIG_DASD_EER is not set ++ ++## ++## file: drivers/s390/char/Kconfig ++## ++CONFIG_TN3270=y ++CONFIG_TN3270_TTY=y ++CONFIG_TN3270_FS=m ++CONFIG_TN3270_CONSOLE=y ++CONFIG_TN3215=y ++CONFIG_TN3215_CONSOLE=y ++CONFIG_SCLP_TTY=y ++CONFIG_SCLP_CONSOLE=y ++CONFIG_SCLP_VT220_TTY=y ++CONFIG_SCLP_VT220_CONSOLE=y ++CONFIG_SCLP_CPI=m ++CONFIG_S390_TAPE=m ++CONFIG_S390_TAPE_34XX=m ++CONFIG_S390_TAPE_3590=m ++CONFIG_VMLOGRDR=m ++CONFIG_VMCP=m ++CONFIG_MONREADER=m ++CONFIG_MONWRITER=m ++CONFIG_S390_VMUR=m ++ ++## ++## file: drivers/s390/net/Kconfig ++## ++CONFIG_LCS=m ++CONFIG_CTCM=m ++CONFIG_NETIUCV=m ++CONFIG_SMSGIUCV=y ++CONFIG_CLAW=m ++CONFIG_QETH=m ++CONFIG_QETH_L2=m ++CONFIG_QETH_L3=m ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_ZFCP=m ++ ++## ++## file: drivers/tty/hvc/Kconfig ++## ++CONFIG_HVC_IUCV=y ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_ZVM_WATCHDOG=m ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_IBM_PARTITION=y ++CONFIG_BSD_DISKLABEL=y ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++# CONFIG_FLATMEM_MANUAL is not set ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++CONFIG_SPARSEMEM_MANUAL=y ++## end choice ++ ++## ++## file: net/atm/Kconfig ++## ++# CONFIG_ATM is not set ++ ++## ++## file: net/decnet/Kconfig ++## ++# CONFIG_DECNET is not set ++ ++## ++## file: net/ipv6/Kconfig ++## ++CONFIG_IPV6=y ++ ++## ++## file: net/ipx/Kconfig ++## ++# CONFIG_IPX is not set ++ ++## ++## file: net/iucv/Kconfig ++## ++CONFIG_IUCV=y ++CONFIG_AFIUCV=m ++ ++## ++## file: net/lapb/Kconfig ++## ++# CONFIG_LAPB is not set ++ ++## ++## file: net/llc/Kconfig ++## ++# CONFIG_LLC2 is not set ++ +diff --git a/debian/config/s390/config.s390 b/debian/config/s390/config.s390 +new file mode 100644 +index 0000000..a6e9ae1 +--- /dev/null ++++ b/debian/config/s390/config.s390 +@@ -0,0 +1,21 @@ ++## ++## file: arch/s390/Kconfig ++## ++# CONFIG_64BIT is not set ++## choice: Processor type ++CONFIG_MARCH_G5=y ++# CONFIG_MARCH_Z900 is not set ++# CONFIG_MARCH_Z990 is not set ++# CONFIG_MARCH_Z9_109 is not set ++## end choice ++## choice: IPL method generated into head.S ++# CONFIG_IPL_TAPE is not set ++CONFIG_IPL_VM=y ++## end choice ++ ++## ++## file: fs/btrfs/Kconfig ++## ++#. Needs __ucmpdi2 ++# CONFIG_BTRFS_FS is not set ++ +diff --git a/debian/config/s390/config.s390-tape b/debian/config/s390/config.s390-tape +new file mode 100644 +index 0000000..2c77cc4 +--- /dev/null ++++ b/debian/config/s390/config.s390-tape +@@ -0,0 +1,15 @@ ++## ++## file: arch/s390/Kconfig ++## ++# CONFIG_64BIT is not set ++## choice: Processor type ++CONFIG_MARCH_G5=y ++# CONFIG_MARCH_Z900 is not set ++# CONFIG_MARCH_Z990 is not set ++# CONFIG_MARCH_Z9_109 is not set ++## end choice ++## choice: IPL method generated into head.S ++CONFIG_IPL_TAPE=y ++# CONFIG_IPL_VM is not set ++## end choice ++ +diff --git a/debian/config/s390/config.s390x b/debian/config/s390/config.s390x +new file mode 100644 +index 0000000..fde67e7 +--- /dev/null ++++ b/debian/config/s390/config.s390x +@@ -0,0 +1,16 @@ ++## ++## file: arch/s390/Kconfig ++## ++CONFIG_64BIT=y ++## choice: Processor type ++# CONFIG_MARCH_G5 is not set ++CONFIG_MARCH_Z900=y ++# CONFIG_MARCH_Z990 is not set ++# CONFIG_MARCH_Z9_109 is not set ++# CONFIG_MARCH_Z10 is not set ++## end choice ++## choice: IPL method generated into head.S ++# CONFIG_IPL_TAPE is not set ++CONFIG_IPL_VM=y ++## end choice ++ +diff --git a/debian/config/s390/config.s390x-tape b/debian/config/s390/config.s390x-tape +new file mode 100644 +index 0000000..b59b87e +--- /dev/null ++++ b/debian/config/s390/config.s390x-tape +@@ -0,0 +1,16 @@ ++## ++## file: arch/s390/Kconfig ++## ++CONFIG_64BIT=y ++## choice: Processor type ++# CONFIG_MARCH_G5 is not set ++CONFIG_MARCH_Z900=y ++# CONFIG_MARCH_Z990 is not set ++# CONFIG_MARCH_Z9_109 is not set ++# CONFIG_MARCH_Z10 is not set ++## end choice ++## choice: IPL method generated into head.S ++CONFIG_IPL_TAPE=y ++# CONFIG_IPL_VM is not set ++## end choice ++ +diff --git a/debian/config/s390/defines b/debian/config/s390/defines +new file mode 100644 +index 0000000..714282f +--- /dev/null ++++ b/debian/config/s390/defines +@@ -0,0 +1,56 @@ ++[abi] ++ignore-changes: ++# Seems to be exported by mistake; no other architecture does ++ arch_pick_mmap_layout ++# Not used in any in-tree module, nor obviously used OOT either ++ lowcore_ptr ++ ++[base] ++flavours: ++ s390x ++ s390x-tape ++kernel-arch: s390 ++ ++[description] ++part-long-reader: This kernel has support to IPL (boot) from a VM reader or DASD device. ++part-long-tape: This kernel has support to IPL (boot) from a tape. ++part-short-tape: IPL from tape ++ ++[image] ++bootloaders: s390-tools ++ ++[s390_description] ++hardware: IBM S/390 ++parts: reader ++ ++[s390-tape_build] ++modules: false ++ ++[s390-tape_description] ++hardware: IBM S/390 ++parts: tape ++ ++[s390-tape_image] ++initramfs: false ++override-localversion: s390 ++type: plain-s390-tape ++ ++[s390x_build] ++debug-info: true ++ ++[s390x_description] ++hardware: IBM zSeries ++parts: reader ++ ++[s390x-tape_build] ++modules: false ++ ++[s390x-tape_description] ++hardware: IBM zSeries ++parts: tape ++ ++[s390x-tape_image] ++initramfs: false ++override-localversion: s390x ++type: plain-s390-tape ++ +diff --git a/debian/config/s390x/defines b/debian/config/s390x/defines +new file mode 100644 +index 0000000..740ca52 +--- /dev/null ++++ b/debian/config/s390x/defines +@@ -0,0 +1,45 @@ ++[abi] ++ignore-changes: ++# Seems to be exported by mistake; no other architecture does ++ arch_pick_mmap_layout ++# Not used in any in-tree module, nor obviously used OOT either ++ lowcore_ptr ++ ++[base] ++flavours: ++ s390x ++ s390x-tape ++kernel-arch: s390 ++ ++[description] ++part-long-reader: This kernel has support to IPL (boot) from a VM reader or DASD device. ++part-long-tape: This kernel has support to IPL (boot) from a tape. ++part-short-tape: IPL from tape ++ ++[image] ++bootloaders: s390-tools ++configs: s390/config ++ ++[s390x_build] ++debug-info: true ++ ++[s390x_description] ++hardware: IBM zSeries ++parts: reader ++ ++[s390x_image] ++configs: s390/config.s390x ++ ++[s390x-tape_build] ++modules: false ++ ++[s390x-tape_description] ++hardware: IBM zSeries ++parts: tape ++ ++[s390x-tape_image] ++configs: s390/config.s390x-tape ++initramfs: false ++override-localversion: s390x ++type: plain-s390-tape ++ +diff --git a/debian/config/sh4/config b/debian/config/sh4/config +new file mode 100644 +index 0000000..2a43447 +--- /dev/null ++++ b/debian/config/sh4/config +@@ -0,0 +1,55 @@ ++## ++## file: arch/sh/Kconfig ++## ++CONFIG_SH_CPU_FREQ=y ++CONFIG_KEXEC=y ++CONFIG_SECCOMP=y ++ ++## ++## file: arch/sh/Kconfig.cpu ++## ++## choice: Endianess selection ++CONFIG_CPU_LITTLE_ENDIAN=y ++## end choice ++CONFIG_SH_FPU=y ++CONFIG_SH_STORE_QUEUES=y ++ ++## ++## file: arch/sh/drivers/Kconfig ++## ++CONFIG_HEARTBEAT=y ++ ++## ++## file: arch/sh/mm/Kconfig ++## ++## choice: Cache mode ++CONFIG_CACHE_WRITEBACK=y ++## end choice ++ ++## ++## file: drivers/cpufreq/Kconfig ++## ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_STAT_DETAILS=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++ ++## ++## file: kernel/Kconfig.hz ++## ++## choice: Timer frequency ++CONFIG_HZ_250=y ++## end choice ++ ++## ++## file: kernel/irq/Kconfig ++## ++CONFIG_SPARSE_IRQ=y ++ ++## ++## file: kernel/Kconfig.preempt ++## ++## choice: Preemption Model ++CONFIG_PREEMPT_NONE=y ++## end choice ++ +diff --git a/debian/config/sh4/config.sh7751r b/debian/config/sh4/config.sh7751r +new file mode 100644 +index 0000000..817999e +--- /dev/null ++++ b/debian/config/sh4/config.sh7751r +@@ -0,0 +1,192 @@ ++## ++## file: arch/sh/Kconfig ++## ++## choice: Processor sub-type selection ++CONFIG_CPU_SUBTYPE_SH7751R=y ++## end choice ++CONFIG_SH_TIMER_TMU=y ++CONFIG_SH_PCLK_FREQ=60000000 ++CONFIG_PCI=y ++ ++## ++## file: arch/sh/boards/Kconfig ++## ++CONFIG_SH_RTS7751R2D=y ++ ++## ++## file: arch/sh/boards/mach-r2d/Kconfig ++## ++CONFIG_RTS7751R2D_PLUS=y ++ ++## ++## file: arch/sh/Kconfig.cpu ++## ++## choice: Endianess selection ++CONFIG_CPU_LITTLE_ENDIAN=y ++## end choice ++CONFIG_SH_FPU=y ++ ++## ++## file: arch/sh/mm/Kconfig ++## ++CONFIG_MMU=y ++CONFIG_FORCE_MAX_ZONEORDER=11 ++CONFIG_MEMORY_START=0x0c000000 ++CONFIG_MEMORY_SIZE=0x04000000 ++CONFIG_VSYSCALL=y ++## choice: Kernel page size ++CONFIG_PAGE_SIZE_4KB=y ++## end choice ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=y ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++CONFIG_ATA_SFF=y ++CONFIG_PATA_PLATFORM=y ++ ++## ++## file: drivers/hid/Kconfig ++## ++CONFIG_HID_SUPPORT=y ++CONFIG_HID=y ++ ++## ++## file: drivers/hid/usbhid/Kconfig ++## ++CONFIG_USB_HID=y ++ ++## ++## file: drivers/input/Kconfig ++## ++CONFIG_INPUT=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++ ++## ++## file: drivers/mfd/Kconfig ++## ++CONFIG_MFD_SM501=y ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=y ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++CONFIG_MTD_CFI=y ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++CONFIG_MTD_CFI_AMDSTD=y ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++CONFIG_MTD_PHYSMAP=y ++ ++## ++## file: drivers/net/Kconfig ++## ++CONFIG_NETDEVICES=y ++CONFIG_MII=y ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_8139CP=y ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_R9701=y ++# CONFIG_RTC_DRV_SH is not set ++# CONFIG_RTC_DRV_GENERIC is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++ ++## ++## file: drivers/spi/Kconfig ++## ++CONFIG_SPI=y ++CONFIG_SPI_BITBANG=y ++CONFIG_SPI_SH_SCI=y ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_HW_CONSOLE_BINDING=y ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_SH_SCI=y ++CONFIG_SERIAL_SH_SCI_NR_UARTS=6 ++CONFIG_SERIAL_SH_SCI_CONSOLE=y ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB_SUPPORT=y ++CONFIG_USB=y ++ ++## ++## file: drivers/usb/core/Kconfig ++## ++CONFIG_USB_DEVICE_CLASS=y ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_OHCI_HCD=y ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++CONFIG_FB_SM501=y ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: fs/ext3/Kconfig ++## ++CONFIG_EXT3_FS=y ++ ++## ++## file: kernel/time/Kconfig ++## ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_FLATMEM_MANUAL=y ++## end choice ++ +diff --git a/debian/config/sh4/config.sh7785lcr b/debian/config/sh4/config.sh7785lcr +new file mode 100644 +index 0000000..37dedb2 +--- /dev/null ++++ b/debian/config/sh4/config.sh7785lcr +@@ -0,0 +1,253 @@ ++## ++## file: arch/sh/Kconfig ++## ++## choice: Processor sub-type selection ++CONFIG_CPU_SUBTYPE_SH7785=y ++## end choice ++CONFIG_SH_TIMER_TMU=y ++CONFIG_SH_PCLK_FREQ=50000000 ++CONFIG_PCI=y ++ ++## ++## file: arch/sh/boards/Kconfig ++## ++CONFIG_SH_SH7785LCR=y ++ ++## ++## file: arch/sh/Kconfig.cpu ++## ++## choice: Endianess selection ++CONFIG_CPU_LITTLE_ENDIAN=y ++## end choice ++CONFIG_SH_FPU=y ++CONFIG_SH_STORE_QUEUES=y ++ ++## ++## file: arch/sh/mm/Kconfig ++## ++CONFIG_MMU=y ++CONFIG_FORCE_MAX_ZONEORDER=11 ++CONFIG_MEMORY_START=0x48000000 ++CONFIG_MEMORY_SIZE=0x18000000 ++CONFIG_VSYSCALL=y ++## choice: Kernel page size ++CONFIG_PAGE_SIZE_4KB=y ++## end choice ++## choice: HugeTLB page size ++CONFIG_HUGETLB_PAGE_SIZE_64K=y ++## end choice ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_ATA=y ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++CONFIG_ATA_SFF=y ++CONFIG_SATA_SIL=y ++ ++## ++## file: drivers/dma/Kconfig ++## ++CONFIG_DMADEVICES=y ++ ++## ++## file: drivers/hid/Kconfig ++## ++CONFIG_HID_SUPPORT=y ++CONFIG_HID=y ++ ++## ++## file: drivers/hid/usbhid/Kconfig ++## ++CONFIG_USB_HID=y ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_HELPER_AUTO=y ++ ++## ++## file: drivers/i2c/algos/Kconfig ++## ++CONFIG_I2C_ALGOPCA=y ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++CONFIG_I2C_PCA_PLATFORM=y ++ ++## ++## file: drivers/input/Kconfig ++## ++CONFIG_INPUT=y ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_EVDEV=y ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++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_TRACKPOINT=y ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++CONFIG_SERIO_I8042=y ++CONFIG_SERIO_SERPORT=y ++CONFIG_SERIO_LIBPS2=y ++ ++## ++## file: drivers/mfd/Kconfig ++## ++CONFIG_MFD_SM501=y ++ ++## ++## file: drivers/mtd/Kconfig ++## ++CONFIG_MTD=y ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++ ++## ++## file: drivers/mtd/chips/Kconfig ++## ++CONFIG_MTD_CFI=y ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++CONFIG_MTD_CFI_AMDSTD=y ++ ++## ++## file: drivers/mtd/maps/Kconfig ++## ++CONFIG_MTD_PHYSMAP=y ++ ++## ++## file: drivers/net/Kconfig ++## ++CONFIG_NETDEVICES=y ++CONFIG_MII=y ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++CONFIG_R8169=y ++ ++## ++## file: drivers/rtc/Kconfig ++## ++CONFIG_RTC_DRV_RS5C372=y ++# CONFIG_RTC_DRV_SH is not set ++# CONFIG_RTC_DRV_GENERIC is not set ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_HW_CONSOLE_BINDING=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_DEVPTS_MULTIPLE_INSTANCES=y ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_SH_SCI=y ++CONFIG_SERIAL_SH_SCI_NR_UARTS=6 ++CONFIG_SERIAL_SH_SCI_CONSOLE=y ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB_SUPPORT=y ++CONFIG_USB=y ++ ++## ++## file: drivers/usb/core/Kconfig ++## ++CONFIG_USB_DEVICE_CLASS=y ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_R8A66597_HCD=y ++ ++## ++## file: drivers/usb/storage/Kconfig ++## ++CONFIG_USB_STORAGE=y ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++CONFIG_FB_SM501=y ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++## ++## file: drivers/watchdog/Kconfig ++## ++CONFIG_WATCHDOG=y ++CONFIG_SH_WDT=y ++# CONFIG_USBPCWATCHDOG is not set ++ ++## ++## file: fs/ext3/Kconfig ++## ++CONFIG_EXT3_FS=y ++ ++## ++## file: kernel/time/Kconfig ++## ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++CONFIG_SPARSEMEM_MANUAL=y ++## end choice ++CONFIG_MIGRATION=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++ ++## ++## file: unknown ++## ++CONFIG_PMB_ENABLE=y ++CONFIG_PMB_FIXED=y ++ +diff --git a/debian/config/sh4/defines b/debian/config/sh4/defines +new file mode 100644 +index 0000000..7dd028a +--- /dev/null ++++ b/debian/config/sh4/defines +@@ -0,0 +1,28 @@ ++[base] ++flavours: ++ sh7751r ++ sh7785lcr ++kernel-arch: sh ++ ++[image] ++suggests: fdutils ++ ++[sh7751r_build] ++image-file: arch/sh/boot/zImage ++ ++[sh7751r_description] ++hardware: sh7751r ++hardware-long: Renesas SH7751R R2D plus board ++ ++[sh7785lcr_build] ++image-file: arch/sh/boot/zImage ++ ++[sh7785lcr_description] ++hardware: sh7785lcr ++hardware-long: Renesas SH7785 reference board ++ ++[sh7785lcr_image] ++recommends: uboot-mkimage ++# Kernel partition size: 4MB ++check-size: 4194304 ++ +diff --git a/debian/config/sparc/config b/debian/config/sparc/config +new file mode 100644 +index 0000000..3a5b28a +--- /dev/null ++++ b/debian/config/sparc/config +@@ -0,0 +1,670 @@ ++## ++## file: arch/Kconfig ++## ++CONFIG_KPROBES=y ++ ++## ++## file: arch/sparc/Kconfig ++## ++CONFIG_64BIT=y ++## choice: Kernel page size ++CONFIG_SPARC64_PAGE_SIZE_8KB=y ++# CONFIG_SPARC64_PAGE_SIZE_64KB is not set ++## end choice ++CONFIG_SECCOMP=y ++# CONFIG_CMDLINE_BOOL is not set ++CONFIG_SUN_LDOMS=y ++CONFIG_PCI=y ++CONFIG_SUN_OPENPROMFS=m ++ ++## ++## file: drivers/ata/Kconfig ++## ++CONFIG_PATA_ALI=m ++CONFIG_PATA_CS5520=m ++CONFIG_PATA_CS5530=m ++CONFIG_PATA_NETCELL=m ++CONFIG_PATA_NS87415=m ++CONFIG_PATA_PDC2027X=m ++CONFIG_PATA_PDC_OLD=m ++CONFIG_PATA_SERVERWORKS=m ++CONFIG_PATA_SIL680=m ++CONFIG_PATA_VIA=m ++CONFIG_PATA_NS87410=m ++CONFIG_PATA_LEGACY=m ++ ++## ++## file: drivers/block/Kconfig ++## ++CONFIG_BLK_DEV_FD=y ++# CONFIG_PARIDE is not set ++# CONFIG_BLK_CPQ_DA 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_SX8=m ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM_SIZE=16384 ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_CDROM_PKTCDVD_BUFFERS=8 ++# CONFIG_CDROM_PKTCDVD_WCACHE is not set ++CONFIG_SUNVDC=m ++ ++## ++## file: drivers/char/Kconfig ++## ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++# CONFIG_PPDEV is not set ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++# CONFIG_APPLICOM is not set ++ ++## ++## file: drivers/char/ipmi/Kconfig ++## ++# CONFIG_IPMI_HANDLER is not set ++ ++## ++## file: drivers/gpu/drm/Kconfig ++## ++CONFIG_DRM=m ++CONFIG_DRM_TDFX=m ++CONFIG_DRM_R128=m ++CONFIG_DRM_RADEON=m ++CONFIG_DRM_MGA=m ++ ++## ++## file: drivers/gpu/drm/nouveau/Kconfig ++## ++CONFIG_DRM_NOUVEAU=m ++# CONFIG_DRM_NOUVEAU_BACKLIGHT is not set ++# CONFIG_DRM_NOUVEAU_DEBUG is not set ++CONFIG_DRM_I2C_CH7006=m ++CONFIG_DRM_I2C_SIL164=m ++ ++## ++## file: drivers/hid/usbhid/Kconfig ++## ++CONFIG_USB_HID=y ++ ++## ++## file: drivers/hwmon/Kconfig ++## ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM75 is not set ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_SIS5595 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_VIA686A is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++ ++## ++## file: drivers/i2c/Kconfig ++## ++CONFIG_I2C=m ++CONFIG_I2C_CHARDEV=m ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++ ++## ++## file: drivers/i2c/busses/Kconfig ++## ++# 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_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 ++CONFIG_I2C_PARPORT=m ++CONFIG_I2C_PARPORT_LIGHT=m ++# CONFIG_I2C_PCA_ISA is not set ++# CONFIG_I2C_STUB is not set ++ ++## ++## file: drivers/input/Kconfig ++## ++# CONFIG_INPUT_JOYDEV is not set ++ ++## ++## file: drivers/input/gameport/Kconfig ++## ++# CONFIG_GAMEPORT is not set ++ ++## ++## file: drivers/input/joystick/Kconfig ++## ++# CONFIG_INPUT_JOYSTICK is not set ++ ++## ++## file: drivers/input/keyboard/Kconfig ++## ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++CONFIG_KEYBOARD_LKKBD=m ++# CONFIG_KEYBOARD_NEWTON is not set ++CONFIG_KEYBOARD_SUNKBD=y ++# CONFIG_KEYBOARD_XTKBD is not set ++ ++## ++## file: drivers/input/misc/Kconfig ++## ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_SPARCSPKR=m ++# CONFIG_INPUT_UINPUT is not set ++ ++## ++## file: drivers/input/mouse/Kconfig ++## ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_SERIAL=y ++# CONFIG_MOUSE_VSXXXAA is not set ++ ++## ++## file: drivers/input/serio/Kconfig ++## ++CONFIG_SERIO=y ++CONFIG_SERIO_I8042=y ++# CONFIG_SERIO_SERPORT is not set ++# CONFIG_SERIO_PARKBD is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++ ++## ++## file: drivers/input/touchscreen/Kconfig ++## ++# CONFIG_INPUT_TOUCHSCREEN is not set ++ ++## ++## file: drivers/media/radio/Kconfig ++## ++# CONFIG_RADIO_MAXIRADIO is not set ++# CONFIG_USB_DSBR is not set ++ ++## ++## file: drivers/media/video/Kconfig ++## ++# CONFIG_VIDEO_BWQCAM is not set ++# CONFIG_VIDEO_CQCAM is not set ++# CONFIG_VIDEO_W9966 is not set ++# CONFIG_VIDEO_MXB is not set ++# CONFIG_VIDEO_HEXIUM_ORION is not set ++# CONFIG_VIDEO_HEXIUM_GEMINI is not set ++ ++## ++## file: drivers/media/video/bt8xx/Kconfig ++## ++CONFIG_VIDEO_BT848=m ++ ++## ++## file: drivers/media/video/cx88/Kconfig ++## ++# CONFIG_VIDEO_CX88 is not set ++ ++## ++## file: drivers/media/video/zoran/Kconfig ++## ++# CONFIG_VIDEO_ZORAN is not set ++ ++## ++## file: drivers/message/i2o/Kconfig ++## ++# CONFIG_I2O is not set ++ ++## ++## file: drivers/mmc/Kconfig ++## ++# CONFIG_MMC is not set ++ ++## ++## file: drivers/mtd/Kconfig ++## ++# CONFIG_MTD is not set ++ ++## ++## file: drivers/net/Kconfig ++## ++CONFIG_NET_FC=y ++# CONFIG_NETPOLL_TRAP is not set ++ ++## ++## file: drivers/net/arcnet/Kconfig ++## ++# CONFIG_ARCNET is not set ++ ++## ++## file: drivers/net/ethernet/Kconfig ++## ++CONFIG_FEALNX=m ++ ++## ++## file: drivers/net/ethernet/3com/Kconfig ++## ++CONFIG_NET_VENDOR_3COM=y ++CONFIG_VORTEX=m ++CONFIG_TYPHOON=m ++ ++## ++## file: drivers/net/ethernet/8390/Kconfig ++## ++CONFIG_NE2K_PCI=m ++ ++## ++## file: drivers/net/ethernet/adaptec/Kconfig ++## ++CONFIG_ADAPTEC_STARFIRE=m ++ ++## ++## file: drivers/net/ethernet/amd/Kconfig ++## ++# CONFIG_AMD8111_ETH is not set ++CONFIG_SUNLANCE=m ++ ++## ++## file: drivers/net/ethernet/broadcom/Kconfig ++## ++CONFIG_B44=m ++ ++## ++## file: drivers/net/ethernet/dec/tulip/Kconfig ++## ++CONFIG_NET_TULIP=y ++# CONFIG_DE2104X is not set ++CONFIG_TULIP=m ++# CONFIG_TULIP_MWI is not set ++# CONFIG_TULIP_MMIO is not set ++CONFIG_WINBOND_840=m ++CONFIG_DM9102=m ++ ++## ++## file: drivers/net/ethernet/dlink/Kconfig ++## ++CONFIG_SUNDANCE=m ++CONFIG_SUNDANCE_MMIO=y ++ ++## ++## file: drivers/net/ethernet/intel/Kconfig ++## ++CONFIG_E100=m ++#. This adds dependencies on i2c, i2c-algo-bit which will break udebs ++# CONFIG_IGB_HWMON is not set ++ ++## ++## file: drivers/net/ethernet/natsemi/Kconfig ++## ++CONFIG_NATSEMI=m ++ ++## ++## file: drivers/net/ethernet/nvidia/Kconfig ++## ++# CONFIG_FORCEDETH is not set ++ ++## ++## file: drivers/net/ethernet/realtek/Kconfig ++## ++# CONFIG_8139CP is not set ++CONFIG_8139TOO=m ++# CONFIG_8139TOO_PIO is not set ++# CONFIG_8139TOO_TUNE_TWISTER is not set ++# CONFIG_8139TOO_8129 is not set ++# CONFIG_8139_OLD_RX_RESET is not set ++ ++## ++## file: drivers/net/ethernet/sis/Kconfig ++## ++CONFIG_SIS900=m ++ ++## ++## file: drivers/net/ethernet/smsc/Kconfig ++## ++CONFIG_EPIC100=m ++ ++## ++## file: drivers/net/ethernet/sun/Kconfig ++## ++CONFIG_HAPPYMEAL=m ++CONFIG_SUNBMAC=m ++CONFIG_SUNQE=m ++CONFIG_SUNGEM=m ++CONFIG_SUNVNET=m ++ ++## ++## file: drivers/net/ethernet/via/Kconfig ++## ++CONFIG_VIA_RHINE=m ++# CONFIG_VIA_RHINE_MMIO is not set ++ ++## ++## file: drivers/net/fddi/Kconfig ++## ++CONFIG_FDDI=y ++CONFIG_SKFP=m ++ ++## ++## file: drivers/net/hippi/Kconfig ++## ++# CONFIG_HIPPI is not set ++ ++## ++## file: drivers/net/plip/Kconfig ++## ++CONFIG_PLIP=m ++ ++## ++## file: drivers/net/tokenring/Kconfig ++## ++# CONFIG_TR is not set ++ ++## ++## file: drivers/net/wan/Kconfig ++## ++# CONFIG_WAN is not set ++ ++## ++## file: drivers/net/wireless/mwifiex/Kconfig ++## ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_PCIE=m ++ ++## ++## file: drivers/parport/Kconfig ++## ++CONFIG_PARPORT_SUNBPP=m ++ ++## ++## file: drivers/sbus/char/Kconfig ++## ++CONFIG_SUN_OPENPROMIO=y ++CONFIG_OBP_FLASH=m ++CONFIG_BBC_I2C=m ++CONFIG_ENVCTRL=m ++CONFIG_DISPLAY7SEG=m ++ ++## ++## file: drivers/scsi/Kconfig ++## ++CONFIG_SCSI_ARCMSR=m ++CONFIG_SCSI_DMX3191D=m ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++CONFIG_SCSI_INITIO=m ++# CONFIG_SCSI_INIA100 is not set ++CONFIG_SCSI_SYM53C8XX_2=m ++CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 ++CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 ++CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 ++CONFIG_SCSI_IPR=m ++# CONFIG_SCSI_IPR_TRACE is not set ++# CONFIG_SCSI_IPR_DUMP is not set ++CONFIG_SCSI_QLOGIC_1280=m ++CONFIG_SCSI_QLOGICPTI=m ++CONFIG_SCSI_DC395x=m ++# CONFIG_SCSI_DC390T is not set ++CONFIG_SCSI_SUNESP=m ++ ++## ++## file: drivers/scsi/megaraid/Kconfig.megaraid ++## ++CONFIG_MEGARAID_NEWGEN=y ++CONFIG_MEGARAID_MM=m ++CONFIG_MEGARAID_MAILBOX=m ++CONFIG_MEGARAID_LEGACY=m ++ ++## ++## file: drivers/telephony/Kconfig ++## ++# CONFIG_PHONE is not set ++ ++## ++## file: drivers/tty/Kconfig ++## ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++## ++## file: drivers/tty/serial/Kconfig ++## ++CONFIG_SERIAL_SUNZILOG=y ++CONFIG_SERIAL_SUNZILOG_CONSOLE=y ++CONFIG_SERIAL_SUNSU=y ++CONFIG_SERIAL_SUNSU_CONSOLE=y ++CONFIG_SERIAL_SUNSAB=y ++CONFIG_SERIAL_SUNSAB_CONSOLE=y ++CONFIG_SERIAL_SUNHV=y ++CONFIG_SERIAL_JSM=m ++ ++## ++## file: drivers/usb/Kconfig ++## ++CONFIG_USB=m ++# CONFIG_USB_USS720 is not set ++ ++## ++## file: drivers/usb/host/Kconfig ++## ++CONFIG_USB_EHCI_HCD=m ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_OHCI_HCD=m ++CONFIG_USB_UHCI_HCD=m ++# CONFIG_USB_SL811_HCD is not set ++ ++## ++## file: drivers/video/Kconfig ++## ++CONFIG_FB=y ++CONFIG_FB_MODE_HELPERS=y ++# CONFIG_FB_TILEBLITTING is not set ++# CONFIG_FB_CIRRUS is not set ++CONFIG_FB_PM2=y ++# CONFIG_FB_PM2_FIFO_DISCONNECT is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++CONFIG_FB_SBUS=y ++# CONFIG_FB_BW2 is not set ++# CONFIG_FB_CG3 is not set ++CONFIG_FB_CG6=y ++CONFIG_FB_FFB=y ++# CONFIG_FB_TCX is not set ++# CONFIG_FB_CG14 is not set ++# CONFIG_FB_P9100 is not set ++# CONFIG_FB_LEO is not set ++CONFIG_FB_XVR500=y ++CONFIG_FB_XVR2500=y ++CONFIG_FB_XVR1000=y ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_MATROX is not set ++CONFIG_FB_RADEON=y ++# CONFIG_FB_RADEON_I2C is not set ++# CONFIG_FB_RADEON_DEBUG is not set ++CONFIG_FB_ATY128=y ++CONFIG_FB_ATY=y ++CONFIG_FB_ATY_CT=y ++# CONFIG_FB_ATY_GENERIC_LCD is not set ++CONFIG_FB_ATY_GX=y ++# 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_TRIDENT is not set ++# CONFIG_FB_VIRTUAL is not set ++ ++## ++## file: drivers/video/backlight/Kconfig ++## ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++## ++## file: drivers/video/console/Kconfig ++## ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x16=y ++CONFIG_FONT_SUN8x16=y ++# CONFIG_FONT_SUN12x22 is not set ++ ++## ++## file: drivers/w1/Kconfig ++## ++# CONFIG_W1 is not set ++ ++## ++## file: fs/partitions/Kconfig ++## ++CONFIG_SUN_PARTITION=y ++ ++## ++## file: mm/Kconfig ++## ++## choice: Memory model ++# CONFIG_FLATMEM_MANUAL is not set ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++CONFIG_SPARSEMEM_MANUAL=y ++## end choice ++ ++## ++## file: net/ax25/Kconfig ++## ++# CONFIG_HAMRADIO is not set ++ ++## ++## file: net/bluetooth/Kconfig ++## ++# CONFIG_BT is not set ++ ++## ++## file: net/decnet/Kconfig ++## ++CONFIG_DECNET=m ++CONFIG_DECNET_ROUTER=y ++ ++## ++## file: net/ipv4/Kconfig ++## ++CONFIG_IP_PNP=y ++# CONFIG_IP_PNP_DHCP is not set ++# CONFIG_IP_PNP_BOOTP is not set ++CONFIG_IP_PNP_RARP=y ++#. TODO ++# CONFIG_NET_IPGRE is not set ++#. TODO ++CONFIG_ARPD=y ++ ++## ++## file: net/ipv6/Kconfig ++## ++CONFIG_IPV6=y ++ ++## ++## file: net/ipx/Kconfig ++## ++CONFIG_IPX=m ++# CONFIG_IPX_INTERN is not set ++ ++## ++## file: net/irda/Kconfig ++## ++# CONFIG_IRDA is not set ++ ++## ++## file: net/lapb/Kconfig ++## ++# CONFIG_LAPB is not set ++ ++## ++## file: sound/drivers/Kconfig ++## ++# CONFIG_SND_DUMMY is not set ++CONFIG_SND_VIRMIDI=m ++# CONFIG_SND_MTPAV is not set ++# CONFIG_SND_SERIAL_U16550 is not set ++# CONFIG_SND_MPU401 is not set ++ ++## ++## file: sound/pci/Kconfig ++## ++CONFIG_SND_ALI5451=m ++# CONFIG_SND_ATIIXP is not set ++# CONFIG_SND_ATIIXP_MODEM is not set ++# CONFIG_SND_AU8810 is not set ++# CONFIG_SND_AU8820 is not set ++# CONFIG_SND_AU8830 is not set ++# CONFIG_SND_AZT3328 is not set ++# CONFIG_SND_BT87X is not set ++# CONFIG_SND_CA0106 is not set ++CONFIG_SND_CMIPCI=m ++# CONFIG_SND_CS4281 is not set ++# CONFIG_SND_CS46XX is not set ++CONFIG_SND_EMU10K1=m ++# CONFIG_SND_EMU10K1X is not set ++CONFIG_SND_ENS1370=m ++CONFIG_SND_ENS1371=m ++# CONFIG_SND_ES1938 is not set ++# CONFIG_SND_ES1968 is not set ++# CONFIG_SND_FM801 is not set ++# CONFIG_SND_HDSP is not set ++# CONFIG_SND_ICE1712 is not set ++# CONFIG_SND_ICE1724 is not set ++# CONFIG_SND_INTEL8X0 is not set ++# CONFIG_SND_INTEL8X0M is not set ++# CONFIG_SND_KORG1212 is not set ++CONFIG_SND_MAESTRO3=m ++# CONFIG_SND_MIXART is not set ++# CONFIG_SND_NM256 is not set ++# CONFIG_SND_RME32 is not set ++# CONFIG_SND_RME96 is not set ++# CONFIG_SND_RME9652 is not set ++# CONFIG_SND_SONICVIBES is not set ++# CONFIG_SND_TRIDENT is not set ++# CONFIG_SND_VIA82XX is not set ++# CONFIG_SND_VIA82XX_MODEM is not set ++# CONFIG_SND_VX222 is not set ++# CONFIG_SND_YMFPCI is not set ++ ++## ++## file: sound/pci/hda/Kconfig ++## ++# CONFIG_SND_HDA_INTEL is not set ++ ++## ++## file: sound/sparc/Kconfig ++## ++CONFIG_SND_SUN_AMD7930=m ++CONFIG_SND_SUN_CS4231=m ++CONFIG_SND_SUN_DBRI=m ++ +diff --git a/debian/config/sparc/config.sparc64 b/debian/config/sparc/config.sparc64 +new file mode 100644 +index 0000000..7586217 +--- /dev/null ++++ b/debian/config/sparc/config.sparc64 +@@ -0,0 +1,5 @@ ++## ++## file: arch/sparc/Kconfig ++## ++# CONFIG_SMP is not set ++ +diff --git a/debian/config/sparc/config.sparc64-smp b/debian/config/sparc/config.sparc64-smp +new file mode 100644 +index 0000000..f6412c2 +--- /dev/null ++++ b/debian/config/sparc/config.sparc64-smp +@@ -0,0 +1,7 @@ ++## ++## file: arch/sparc/Kconfig ++## ++CONFIG_SMP=y ++CONFIG_NR_CPUS=256 ++CONFIG_SCHED_SMT=y ++ +diff --git a/debian/config/sparc/defines b/debian/config/sparc/defines +new file mode 100644 +index 0000000..ac45b75 +--- /dev/null ++++ b/debian/config/sparc/defines +@@ -0,0 +1,32 @@ ++[abi] ++ignore-changes: ++# Inline functions, did not need to be exported at all ++ __down_read ++ __down_read_trylock ++ __down_write ++ __down_write_trylock ++ __downgrade_write ++ __up_read ++ __up_write ++ ++[base] ++flavours: ++ sparc64 ++ sparc64-smp ++kernel-arch: sparc ++ ++[image] ++suggests: silo, fdutils ++ ++[sparc32_description] ++hardware: uniprocessor sparc32 (sun4m) ++ ++[sparc32_image] ++image-postproc: sparc32-image-postproc ++ ++[sparc64_description] ++hardware: uniprocessor 64-bit UltraSPARC ++ ++[sparc64-smp_description] ++hardware: multiprocessor 64-bit UltraSPARC ++ +diff --git a/debian/config/sparc64/defines b/debian/config/sparc64/defines +new file mode 100644 +index 0000000..3ed4077 +--- /dev/null ++++ b/debian/config/sparc64/defines +@@ -0,0 +1,32 @@ ++[abi] ++ignore-changes: ++# Inline functions, did not need to be exported at all ++ __down_read ++ __down_read_trylock ++ __down_write ++ __down_write_trylock ++ __downgrade_write ++ __up_read ++ __up_write ++ ++[base] ++flavours: ++ sparc64 ++ sparc64-smp ++kernel-arch: sparc ++ ++[image] ++configs: sparc/config ++suggests: silo, fdutils ++ ++[sparc64_description] ++hardware: uniprocessor 64-bit UltraSPARC ++ ++[sparc64_image] ++configs: sparc/config.sparc64 ++ ++[sparc64-smp_description] ++hardware: multiprocessor 64-bit UltraSPARC ++ ++[sparc64-smp_image] ++configs: sparc/config.sparc64-smp +diff --git a/debian/copyright b/debian/copyright +new file mode 100644 +index 0000000..efbbc08 +--- /dev/null ++++ b/debian/copyright +@@ -0,0 +1,54 @@ ++This is the Debian GNU/Linux prepackaged version of the Linux kernel. ++ ++It was downloaded from http://ftp.kernel.org/pub/linux/kernel/. ++ ++Copyright: ++ ++ Copyright (C) 1991-2009 Linus Torvalds ++ and many others ++ ++License: ++ ++ This package 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 package is distributed in the hope that it will be useful, ++ but WITHOUT 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 package; if not, write to the Free Software ++ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++On Debian systems, the complete text of the GNU General Public License version ++2 can be found in `/usr/share/common-licenses/GPL-2'. ++ ++License for the Xen interface headers: ++ ++ 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. ++ ++The 'perf' tool is dynamically linked with the Python interpreter, ++which is itself dynamically linked with OpenSSL, which is not ++GPL-compatible. However, since perf itself does not link with or use ++OpenSSL, we believe that this indirect linking does not require ++additional permissions beyond the GPL. ++ ++The Debian packaging is licensed under the GPL, see above. +diff --git a/debian/installer/amd64/TODO b/debian/installer/amd64/TODO +new file mode 100644 +index 0000000..d02dd6c +--- /dev/null ++++ b/debian/installer/amd64/TODO +@@ -0,0 +1,3 @@ ++* The 2.6 kernel is missing a lot of modules, need to get a list of all ++ modules included in the udebs, and compare vs. the full module list and ++ add missing stuff. +diff --git a/debian/installer/amd64/kernel-versions b/debian/installer/amd64/kernel-versions +new file mode 100644 +index 0000000..1700a94 +--- /dev/null ++++ b/debian/installer/amd64/kernel-versions +@@ -0,0 +1,2 @@ ++# arch version flavour installedname suffix build-depends ++amd64 - amd64 - - - +diff --git a/debian/installer/amd64/modules/amd64/acpi-modules b/debian/installer/amd64/modules/amd64/acpi-modules +new file mode 100644 +index 0000000..307528f +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/acpi-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/ata-modules b/debian/installer/amd64/modules/amd64/ata-modules +new file mode 100644 +index 0000000..9409e7c +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/ata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/btrfs-modules b/debian/installer/amd64/modules/amd64/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/cdrom-core-modules b/debian/installer/amd64/modules/amd64/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/core-modules b/debian/installer/amd64/modules/amd64/core-modules +new file mode 100644 +index 0000000..21826c6 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/core-modules +@@ -0,0 +1,2 @@ ++#include ++mbcache +diff --git a/debian/installer/amd64/modules/amd64/crc-modules b/debian/installer/amd64/modules/amd64/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/crypto-dm-modules b/debian/installer/amd64/modules/amd64/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/crypto-modules b/debian/installer/amd64/modules/amd64/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/efi-modules b/debian/installer/amd64/modules/amd64/efi-modules +new file mode 100644 +index 0000000..e1dc05e +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/efi-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/event-modules b/debian/installer/amd64/modules/amd64/event-modules +new file mode 100644 +index 0000000..f8819af +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/event-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/ext2-modules b/debian/installer/amd64/modules/amd64/ext2-modules +new file mode 100644 +index 0000000..c407140 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/ext2-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/ext3-modules b/debian/installer/amd64/modules/amd64/ext3-modules +new file mode 100644 +index 0000000..55ef7d7 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/ext3-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/ext4-modules b/debian/installer/amd64/modules/amd64/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/fat-modules b/debian/installer/amd64/modules/amd64/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/fb-modules b/debian/installer/amd64/modules/amd64/fb-modules +new file mode 100644 +index 0000000..1601467 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/fb-modules +@@ -0,0 +1,3 @@ ++fbcon ? ++vesafb ? ++vga16fb +diff --git a/debian/installer/amd64/modules/amd64/firewire-core-modules b/debian/installer/amd64/modules/amd64/firewire-core-modules +new file mode 100644 +index 0000000..dcac80a +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/firewire-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/floppy-modules b/debian/installer/amd64/modules/amd64/floppy-modules +new file mode 100644 +index 0000000..169fde5 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/floppy-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/fuse-modules b/debian/installer/amd64/modules/amd64/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/hyperv-modules b/debian/installer/amd64/modules/amd64/hyperv-modules +new file mode 100644 +index 0000000..69fdd5d +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/hyperv-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/i2c-modules b/debian/installer/amd64/modules/amd64/i2c-modules +new file mode 100644 +index 0000000..203a607 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/i2c-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/input-modules b/debian/installer/amd64/modules/amd64/input-modules +new file mode 100644 +index 0000000..5ecb595 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/input-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/irda-modules b/debian/installer/amd64/modules/amd64/irda-modules +new file mode 100644 +index 0000000..7cc1f44 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/irda-modules +@@ -0,0 +1,15 @@ ++act200l-sir ++actisys-sir ++irda-usb ++irtty-sir ++litelink-sir ++ma600-sir ++mcp2120-sir ++old_belkin-sir ++tekram-sir ++vlsi_ir ++ircomm-tty ++ircomm ++irda ++irnet ++via-ircc ? +diff --git a/debian/installer/amd64/modules/amd64/isofs-modules b/debian/installer/amd64/modules/amd64/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/jfs-modules b/debian/installer/amd64/modules/amd64/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/kernel-image b/debian/installer/amd64/modules/amd64/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/amd64/modules/amd64/loop-modules b/debian/installer/amd64/modules/amd64/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/md-modules b/debian/installer/amd64/modules/amd64/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/mmc-core-modules b/debian/installer/amd64/modules/amd64/mmc-core-modules +new file mode 100644 +index 0000000..7bf3846 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/mmc-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/mmc-modules b/debian/installer/amd64/modules/amd64/mmc-modules +new file mode 100644 +index 0000000..dadfd53 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/mmc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/mouse-modules b/debian/installer/amd64/modules/amd64/mouse-modules +new file mode 100644 +index 0000000..15fcb00 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/mouse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/multipath-modules b/debian/installer/amd64/modules/amd64/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/nbd-modules b/debian/installer/amd64/modules/amd64/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/nic-extra-modules b/debian/installer/amd64/modules/amd64/nic-extra-modules +new file mode 100644 +index 0000000..3e59d86 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/nic-extra-modules +@@ -0,0 +1,2 @@ ++#include ++eexpress - +diff --git a/debian/installer/amd64/modules/amd64/nic-modules b/debian/installer/amd64/modules/amd64/nic-modules +new file mode 100644 +index 0000000..2512e83 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/nic-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/nic-pcmcia-modules b/debian/installer/amd64/modules/amd64/nic-pcmcia-modules +new file mode 100644 +index 0000000..7a0702c +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/nic-pcmcia-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/nic-shared-modules b/debian/installer/amd64/modules/amd64/nic-shared-modules +new file mode 100644 +index 0000000..b52153d +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/nic-shared-modules +@@ -0,0 +1,3 @@ ++8390 ++mii ++libphy +diff --git a/debian/installer/amd64/modules/amd64/nic-usb-modules b/debian/installer/amd64/modules/amd64/nic-usb-modules +new file mode 100644 +index 0000000..c479669 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/nic-usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/nic-wireless-modules b/debian/installer/amd64/modules/amd64/nic-wireless-modules +new file mode 100644 +index 0000000..53fd18d +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/nic-wireless-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/ntfs-modules b/debian/installer/amd64/modules/amd64/ntfs-modules +new file mode 100644 +index 0000000..ac1bc6a +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/ntfs-modules +@@ -0,0 +1 @@ ++ntfs +diff --git a/debian/installer/amd64/modules/amd64/parport-modules b/debian/installer/amd64/modules/amd64/parport-modules +new file mode 100644 +index 0000000..6ea7b6f +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/parport-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/pata-modules b/debian/installer/amd64/modules/amd64/pata-modules +new file mode 100644 +index 0000000..8c4e514 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/pata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/pcmcia-modules b/debian/installer/amd64/modules/amd64/pcmcia-modules +new file mode 100644 +index 0000000..2bb5350 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/pcmcia-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/pcmcia-storage-modules b/debian/installer/amd64/modules/amd64/pcmcia-storage-modules +new file mode 100644 +index 0000000..f73ae5b +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/pcmcia-storage-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/plip-modules b/debian/installer/amd64/modules/amd64/plip-modules +new file mode 100644 +index 0000000..eab43fa +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/plip-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/ppp-modules b/debian/installer/amd64/modules/amd64/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/qnx4-modules b/debian/installer/amd64/modules/amd64/qnx4-modules +new file mode 100644 +index 0000000..cd0c96d +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/qnx4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/reiserfs-modules b/debian/installer/amd64/modules/amd64/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/sata-modules b/debian/installer/amd64/modules/amd64/sata-modules +new file mode 100644 +index 0000000..01318c2 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/sata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/scsi-common-modules b/debian/installer/amd64/modules/amd64/scsi-common-modules +new file mode 100644 +index 0000000..71103dd +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/scsi-common-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/scsi-core-modules b/debian/installer/amd64/modules/amd64/scsi-core-modules +new file mode 100644 +index 0000000..dd65d66 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/scsi-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/scsi-extra-modules b/debian/installer/amd64/modules/amd64/scsi-extra-modules +new file mode 100644 +index 0000000..61c0e66 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/scsi-extra-modules +@@ -0,0 +1,4 @@ ++#include ++dpt_i2o - ++i2o_block ++i2o_scsi +diff --git a/debian/installer/amd64/modules/amd64/scsi-modules b/debian/installer/amd64/modules/amd64/scsi-modules +new file mode 100644 +index 0000000..8909dfb +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/scsi-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/serial-modules b/debian/installer/amd64/modules/amd64/serial-modules +new file mode 100644 +index 0000000..6ab8b8c +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/sound-modules b/debian/installer/amd64/modules/amd64/sound-modules +new file mode 100644 +index 0000000..68395ab +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/sound-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/speakup-modules b/debian/installer/amd64/modules/amd64/speakup-modules +new file mode 100644 +index 0000000..2959272 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/speakup-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/squashfs-modules b/debian/installer/amd64/modules/amd64/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/udf-modules b/debian/installer/amd64/modules/amd64/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/ufs-modules b/debian/installer/amd64/modules/amd64/ufs-modules +new file mode 100644 +index 0000000..69745ca +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/ufs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/uinput-modules b/debian/installer/amd64/modules/amd64/uinput-modules +new file mode 100644 +index 0000000..58a8337 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/uinput-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/usb-modules b/debian/installer/amd64/modules/amd64/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/usb-serial-modules b/debian/installer/amd64/modules/amd64/usb-serial-modules +new file mode 100644 +index 0000000..c0a0dc3 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/usb-serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/usb-storage-modules b/debian/installer/amd64/modules/amd64/usb-storage-modules +new file mode 100644 +index 0000000..272d95e +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/virtio-modules b/debian/installer/amd64/modules/amd64/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/modules/amd64/xfs-modules b/debian/installer/amd64/modules/amd64/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/amd64/modules/amd64/zlib-modules b/debian/installer/amd64/modules/amd64/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/amd64/modules/amd64/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/amd64/package-list b/debian/installer/amd64/package-list +new file mode 100644 +index 0000000..96cd119 +--- /dev/null ++++ b/debian/installer/amd64/package-list +@@ -0,0 +1,26 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++ ++Package: ext2-modules ++Depends: kernel-image, core-modules ++ ++Package: ext3-modules ++Depends: kernel-image, core-modules ++ ++Package: fat-modules ++Priority: standard ++ ++Package: nic-modules ++Depends: kernel-image, nic-shared-modules, core-modules, firewire-core-modules ++ ++Package: scsi-modules ++Depends: kernel-image, scsi-core-modules, scsi-common-modules, parport-modules, cdrom-core-modules, core-modules, ata-modules ++ ++Package: pcmcia-modules ++Depends: kernel-image, core-modules ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/armel/kernel-versions b/debian/installer/armel/kernel-versions +new file mode 100644 +index 0000000..c6972e4 +--- /dev/null ++++ b/debian/installer/armel/kernel-versions +@@ -0,0 +1,5 @@ ++# arch version flavour installedname suffix build-depends ++armel - iop32x - y - ++armel - kirkwood - y - ++armel - orion5x - y - ++armel - versatile - y - +diff --git a/debian/installer/armel/modules/armel-iop32x/ata-modules b/debian/installer/armel/modules/armel-iop32x/ata-modules +new file mode 100644 +index 0000000..9409e7c +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/ata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-iop32x/btrfs-modules b/debian/installer/armel/modules/armel-iop32x/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/cdrom-core-modules b/debian/installer/armel/modules/armel-iop32x/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-iop32x/core-modules b/debian/installer/armel/modules/armel-iop32x/core-modules +new file mode 100644 +index 0000000..21826c6 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/core-modules +@@ -0,0 +1,2 @@ ++#include ++mbcache +diff --git a/debian/installer/armel/modules/armel-iop32x/crc-modules b/debian/installer/armel/modules/armel-iop32x/crc-modules +new file mode 100644 +index 0000000..a642ead +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/crc-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-iop32x/crypto-dm-modules b/debian/installer/armel/modules/armel-iop32x/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/crypto-modules b/debian/installer/armel/modules/armel-iop32x/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/event-modules b/debian/installer/armel/modules/armel-iop32x/event-modules +new file mode 100644 +index 0000000..f8819af +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/event-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/ext2-modules b/debian/installer/armel/modules/armel-iop32x/ext2-modules +new file mode 100644 +index 0000000..c407140 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/ext2-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/ext3-modules b/debian/installer/armel/modules/armel-iop32x/ext3-modules +new file mode 100644 +index 0000000..bbdd7f4 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/ext3-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/ext4-modules b/debian/installer/armel/modules/armel-iop32x/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/fat-modules b/debian/installer/armel/modules/armel-iop32x/fat-modules +new file mode 100644 +index 0000000..274584e +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/fat-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/fuse-modules b/debian/installer/armel/modules/armel-iop32x/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/ipv6-modules b/debian/installer/armel/modules/armel-iop32x/ipv6-modules +new file mode 100644 +index 0000000..1e3fc33 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/ipv6-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/isofs-modules b/debian/installer/armel/modules/armel-iop32x/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/jffs2-modules b/debian/installer/armel/modules/armel-iop32x/jffs2-modules +new file mode 100644 +index 0000000..245c7d8 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/jffs2-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/jfs-modules b/debian/installer/armel/modules/armel-iop32x/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/kernel-image b/debian/installer/armel/modules/armel-iop32x/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/armel/modules/armel-iop32x/loop-modules b/debian/installer/armel/modules/armel-iop32x/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-iop32x/md-modules b/debian/installer/armel/modules/armel-iop32x/md-modules +new file mode 100644 +index 0000000..26115e1 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/md-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/multipath-modules b/debian/installer/armel/modules/armel-iop32x/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/nbd-modules b/debian/installer/armel/modules/armel-iop32x/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/nic-modules b/debian/installer/armel/modules/armel-iop32x/nic-modules +new file mode 100644 +index 0000000..381606c +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/nic-modules +@@ -0,0 +1,5 @@ ++r8169 ++e1000 ++sis190 ? ++skge ? ++tg3 ? +diff --git a/debian/installer/armel/modules/armel-iop32x/nic-shared-modules b/debian/installer/armel/modules/armel-iop32x/nic-shared-modules +new file mode 100644 +index 0000000..4071438 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/nic-shared-modules +@@ -0,0 +1,2 @@ ++mii ++libphy +diff --git a/debian/installer/armel/modules/armel-iop32x/nic-usb-modules b/debian/installer/armel/modules/armel-iop32x/nic-usb-modules +new file mode 100644 +index 0000000..c479669 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/nic-usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/pata-modules b/debian/installer/armel/modules/armel-iop32x/pata-modules +new file mode 100644 +index 0000000..8c4e514 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/pata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-iop32x/ppp-modules b/debian/installer/armel/modules/armel-iop32x/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-iop32x/reiserfs-modules b/debian/installer/armel/modules/armel-iop32x/reiserfs-modules +new file mode 100644 +index 0000000..fad554f +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/reiserfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/sata-modules b/debian/installer/armel/modules/armel-iop32x/sata-modules +new file mode 100644 +index 0000000..071cb86 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/sata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-iop32x/scsi-core-modules b/debian/installer/armel/modules/armel-iop32x/scsi-core-modules +new file mode 100644 +index 0000000..dd65d66 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/scsi-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/squashfs-modules b/debian/installer/armel/modules/armel-iop32x/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/udf-modules b/debian/installer/armel/modules/armel-iop32x/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/usb-modules b/debian/installer/armel/modules/armel-iop32x/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/usb-serial-modules b/debian/installer/armel/modules/armel-iop32x/usb-serial-modules +new file mode 100644 +index 0000000..c0a0dc3 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/usb-serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/usb-storage-modules b/debian/installer/armel/modules/armel-iop32x/usb-storage-modules +new file mode 100644 +index 0000000..8c5e81b +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/usb-storage-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-iop32x/zlib-modules b/debian/installer/armel/modules/armel-iop32x/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-iop32x/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/btrfs-modules b/debian/installer/armel/modules/armel-kirkwood/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/cdrom-core-modules b/debian/installer/armel/modules/armel-kirkwood/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-kirkwood/core-modules b/debian/installer/armel/modules/armel-kirkwood/core-modules +new file mode 100644 +index 0000000..21826c6 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/core-modules +@@ -0,0 +1,2 @@ ++#include ++mbcache +diff --git a/debian/installer/armel/modules/armel-kirkwood/crc-modules b/debian/installer/armel/modules/armel-kirkwood/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/crypto-dm-modules b/debian/installer/armel/modules/armel-kirkwood/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/crypto-modules b/debian/installer/armel/modules/armel-kirkwood/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/event-modules b/debian/installer/armel/modules/armel-kirkwood/event-modules +new file mode 100644 +index 0000000..0bc9f77 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/event-modules +@@ -0,0 +1,2 @@ ++#include ++gpio_keys +diff --git a/debian/installer/armel/modules/armel-kirkwood/ext2-modules b/debian/installer/armel/modules/armel-kirkwood/ext2-modules +new file mode 100644 +index 0000000..c407140 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/ext2-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/ext3-modules b/debian/installer/armel/modules/armel-kirkwood/ext3-modules +new file mode 100644 +index 0000000..bbdd7f4 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/ext3-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/ext4-modules b/debian/installer/armel/modules/armel-kirkwood/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/fat-modules b/debian/installer/armel/modules/armel-kirkwood/fat-modules +new file mode 100644 +index 0000000..274584e +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/fat-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/fb-modules b/debian/installer/armel/modules/armel-kirkwood/fb-modules +new file mode 100644 +index 0000000..4654768 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/fb-modules +@@ -0,0 +1,3 @@ ++fbcon ++udlfb ++xgifb +diff --git a/debian/installer/armel/modules/armel-kirkwood/fuse-modules b/debian/installer/armel/modules/armel-kirkwood/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/input-modules b/debian/installer/armel/modules/armel-kirkwood/input-modules +new file mode 100644 +index 0000000..5ecb595 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/input-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/ipv6-modules b/debian/installer/armel/modules/armel-kirkwood/ipv6-modules +new file mode 100644 +index 0000000..1e3fc33 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/ipv6-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/isofs-modules b/debian/installer/armel/modules/armel-kirkwood/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/jfs-modules b/debian/installer/armel/modules/armel-kirkwood/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/kernel-image b/debian/installer/armel/modules/armel-kirkwood/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/armel/modules/armel-kirkwood/leds-modules b/debian/installer/armel/modules/armel-kirkwood/leds-modules +new file mode 100644 +index 0000000..b18bac1 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/leds-modules +@@ -0,0 +1,2 @@ ++leds-ns2 ++leds-netxbig +diff --git a/debian/installer/armel/modules/armel-kirkwood/loop-modules b/debian/installer/armel/modules/armel-kirkwood/loop-modules +new file mode 100644 +index 0000000..c1c948f +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/loop-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/md-modules b/debian/installer/armel/modules/armel-kirkwood/md-modules +new file mode 100644 +index 0000000..26115e1 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/md-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/minix-modules b/debian/installer/armel/modules/armel-kirkwood/minix-modules +new file mode 100644 +index 0000000..82b9843 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/minix-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/mmc-modules b/debian/installer/armel/modules/armel-kirkwood/mmc-modules +new file mode 100644 +index 0000000..e8c7b46 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/mmc-modules +@@ -0,0 +1,2 @@ ++#include ++mvsdio +diff --git a/debian/installer/armel/modules/armel-kirkwood/mouse-modules b/debian/installer/armel/modules/armel-kirkwood/mouse-modules +new file mode 100644 +index 0000000..15fcb00 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/mouse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/multipath-modules b/debian/installer/armel/modules/armel-kirkwood/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/nbd-modules b/debian/installer/armel/modules/armel-kirkwood/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/nic-modules b/debian/installer/armel/modules/armel-kirkwood/nic-modules +new file mode 100644 +index 0000000..1cc5839 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/nic-modules +@@ -0,0 +1,2 @@ ++inet_lro ++mv643xx_eth +diff --git a/debian/installer/armel/modules/armel-kirkwood/nic-shared-modules b/debian/installer/armel/modules/armel-kirkwood/nic-shared-modules +new file mode 100644 +index 0000000..4071438 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/nic-shared-modules +@@ -0,0 +1,2 @@ ++mii ++libphy +diff --git a/debian/installer/armel/modules/armel-kirkwood/nic-usb-modules b/debian/installer/armel/modules/armel-kirkwood/nic-usb-modules +new file mode 100644 +index 0000000..c479669 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/nic-usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/ppp-modules b/debian/installer/armel/modules/armel-kirkwood/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-kirkwood/reiserfs-modules b/debian/installer/armel/modules/armel-kirkwood/reiserfs-modules +new file mode 100644 +index 0000000..fad554f +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/reiserfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/sata-modules b/debian/installer/armel/modules/armel-kirkwood/sata-modules +new file mode 100644 +index 0000000..3adbfa1 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/sata-modules +@@ -0,0 +1,2 @@ ++ahci ++sata_mv +diff --git a/debian/installer/armel/modules/armel-kirkwood/scsi-core-modules b/debian/installer/armel/modules/armel-kirkwood/scsi-core-modules +new file mode 100644 +index 0000000..dd65d66 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/scsi-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/squashfs-modules b/debian/installer/armel/modules/armel-kirkwood/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/udf-modules b/debian/installer/armel/modules/armel-kirkwood/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/uinput-modules b/debian/installer/armel/modules/armel-kirkwood/uinput-modules +new file mode 100644 +index 0000000..58a8337 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/uinput-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/usb-modules b/debian/installer/armel/modules/armel-kirkwood/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/usb-serial-modules b/debian/installer/armel/modules/armel-kirkwood/usb-serial-modules +new file mode 100644 +index 0000000..c0a0dc3 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/usb-serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-kirkwood/usb-storage-modules b/debian/installer/armel/modules/armel-kirkwood/usb-storage-modules +new file mode 100644 +index 0000000..8c5e81b +--- /dev/null ++++ b/debian/installer/armel/modules/armel-kirkwood/usb-storage-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/btrfs-modules b/debian/installer/armel/modules/armel-orion5x/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/cdrom-core-modules b/debian/installer/armel/modules/armel-orion5x/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-orion5x/core-modules b/debian/installer/armel/modules/armel-orion5x/core-modules +new file mode 100644 +index 0000000..21826c6 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/core-modules +@@ -0,0 +1,2 @@ ++#include ++mbcache +diff --git a/debian/installer/armel/modules/armel-orion5x/crc-modules b/debian/installer/armel/modules/armel-orion5x/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/crypto-dm-modules b/debian/installer/armel/modules/armel-orion5x/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/crypto-modules b/debian/installer/armel/modules/armel-orion5x/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/event-modules b/debian/installer/armel/modules/armel-orion5x/event-modules +new file mode 100644 +index 0000000..0bc9f77 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/event-modules +@@ -0,0 +1,2 @@ ++#include ++gpio_keys +diff --git a/debian/installer/armel/modules/armel-orion5x/ext2-modules b/debian/installer/armel/modules/armel-orion5x/ext2-modules +new file mode 100644 +index 0000000..c407140 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/ext2-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/ext3-modules b/debian/installer/armel/modules/armel-orion5x/ext3-modules +new file mode 100644 +index 0000000..bbdd7f4 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/ext3-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/ext4-modules b/debian/installer/armel/modules/armel-orion5x/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/fat-modules b/debian/installer/armel/modules/armel-orion5x/fat-modules +new file mode 100644 +index 0000000..274584e +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/fat-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/fuse-modules b/debian/installer/armel/modules/armel-orion5x/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/ipv6-modules b/debian/installer/armel/modules/armel-orion5x/ipv6-modules +new file mode 100644 +index 0000000..1e3fc33 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/ipv6-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/isofs-modules b/debian/installer/armel/modules/armel-orion5x/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/jffs2-modules b/debian/installer/armel/modules/armel-orion5x/jffs2-modules +new file mode 100644 +index 0000000..245c7d8 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/jffs2-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/jfs-modules b/debian/installer/armel/modules/armel-orion5x/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/kernel-image b/debian/installer/armel/modules/armel-orion5x/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/armel/modules/armel-orion5x/loop-modules b/debian/installer/armel/modules/armel-orion5x/loop-modules +new file mode 100644 +index 0000000..c1c948f +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/loop-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/md-modules b/debian/installer/armel/modules/armel-orion5x/md-modules +new file mode 100644 +index 0000000..26115e1 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/md-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/minix-modules b/debian/installer/armel/modules/armel-orion5x/minix-modules +new file mode 100644 +index 0000000..82b9843 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/minix-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/multipath-modules b/debian/installer/armel/modules/armel-orion5x/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/nbd-modules b/debian/installer/armel/modules/armel-orion5x/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/nic-modules b/debian/installer/armel/modules/armel-orion5x/nic-modules +new file mode 100644 +index 0000000..1cc5839 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/nic-modules +@@ -0,0 +1,2 @@ ++inet_lro ++mv643xx_eth +diff --git a/debian/installer/armel/modules/armel-orion5x/nic-shared-modules b/debian/installer/armel/modules/armel-orion5x/nic-shared-modules +new file mode 100644 +index 0000000..d4cf5db +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/nic-shared-modules +@@ -0,0 +1 @@ ++mii +diff --git a/debian/installer/armel/modules/armel-orion5x/nic-usb-modules b/debian/installer/armel/modules/armel-orion5x/nic-usb-modules +new file mode 100644 +index 0000000..c479669 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/nic-usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/ppp-modules b/debian/installer/armel/modules/armel-orion5x/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-orion5x/reiserfs-modules b/debian/installer/armel/modules/armel-orion5x/reiserfs-modules +new file mode 100644 +index 0000000..fad554f +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/reiserfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/sata-modules b/debian/installer/armel/modules/armel-orion5x/sata-modules +new file mode 100644 +index 0000000..fad6193 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/sata-modules +@@ -0,0 +1 @@ ++sata_mv +diff --git a/debian/installer/armel/modules/armel-orion5x/scsi-core-modules b/debian/installer/armel/modules/armel-orion5x/scsi-core-modules +new file mode 100644 +index 0000000..dd65d66 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/scsi-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/squashfs-modules b/debian/installer/armel/modules/armel-orion5x/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/udf-modules b/debian/installer/armel/modules/armel-orion5x/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/usb-modules b/debian/installer/armel/modules/armel-orion5x/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/usb-serial-modules b/debian/installer/armel/modules/armel-orion5x/usb-serial-modules +new file mode 100644 +index 0000000..c0a0dc3 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/usb-serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/usb-storage-modules b/debian/installer/armel/modules/armel-orion5x/usb-storage-modules +new file mode 100644 +index 0000000..8c5e81b +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/usb-storage-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-orion5x/zlib-modules b/debian/installer/armel/modules/armel-orion5x/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-orion5x/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/btrfs-modules b/debian/installer/armel/modules/armel-versatile/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/cdrom-core-modules b/debian/installer/armel/modules/armel-versatile/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-versatile/core-modules b/debian/installer/armel/modules/armel-versatile/core-modules +new file mode 100644 +index 0000000..21826c6 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/core-modules +@@ -0,0 +1,2 @@ ++#include ++mbcache +diff --git a/debian/installer/armel/modules/armel-versatile/crc-modules b/debian/installer/armel/modules/armel-versatile/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/crypto-dm-modules b/debian/installer/armel/modules/armel-versatile/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/crypto-modules b/debian/installer/armel/modules/armel-versatile/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/ext2-modules b/debian/installer/armel/modules/armel-versatile/ext2-modules +new file mode 100644 +index 0000000..c407140 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/ext2-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/ext3-modules b/debian/installer/armel/modules/armel-versatile/ext3-modules +new file mode 100644 +index 0000000..bbdd7f4 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/ext3-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/ext4-modules b/debian/installer/armel/modules/armel-versatile/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/fat-modules b/debian/installer/armel/modules/armel-versatile/fat-modules +new file mode 100644 +index 0000000..274584e +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/fat-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/fuse-modules b/debian/installer/armel/modules/armel-versatile/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/ipv6-modules b/debian/installer/armel/modules/armel-versatile/ipv6-modules +new file mode 100644 +index 0000000..1e3fc33 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/ipv6-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/isofs-modules b/debian/installer/armel/modules/armel-versatile/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/kernel-image b/debian/installer/armel/modules/armel-versatile/kernel-image +new file mode 100644 +index 0000000..8b13789 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/kernel-image +@@ -0,0 +1 @@ ++ +diff --git a/debian/installer/armel/modules/armel-versatile/loop-modules b/debian/installer/armel/modules/armel-versatile/loop-modules +new file mode 100644 +index 0000000..c1c948f +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/loop-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/md-modules b/debian/installer/armel/modules/armel-versatile/md-modules +new file mode 100644 +index 0000000..26115e1 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/md-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/multipath-modules b/debian/installer/armel/modules/armel-versatile/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/nbd-modules b/debian/installer/armel/modules/armel-versatile/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/nic-modules b/debian/installer/armel/modules/armel-versatile/nic-modules +new file mode 100644 +index 0000000..2fcb2d3 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/nic-modules +@@ -0,0 +1,6 @@ ++3c59x ? ++8139too ? ++e100 ? ++natsemi ? ++ne2k-pci ? ++smc91x +diff --git a/debian/installer/armel/modules/armel-versatile/nic-shared-modules b/debian/installer/armel/modules/armel-versatile/nic-shared-modules +new file mode 100644 +index 0000000..4071438 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/nic-shared-modules +@@ -0,0 +1,2 @@ ++mii ++libphy +diff --git a/debian/installer/armel/modules/armel-versatile/nic-usb-modules b/debian/installer/armel/modules/armel-versatile/nic-usb-modules +new file mode 100644 +index 0000000..c479669 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/nic-usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/ppp-modules b/debian/installer/armel/modules/armel-versatile/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/armel/modules/armel-versatile/reiserfs-modules b/debian/installer/armel/modules/armel-versatile/reiserfs-modules +new file mode 100644 +index 0000000..fad554f +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/reiserfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/sata-modules b/debian/installer/armel/modules/armel-versatile/sata-modules +new file mode 100644 +index 0000000..01318c2 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/sata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/scsi-common-modules b/debian/installer/armel/modules/armel-versatile/scsi-common-modules +new file mode 100644 +index 0000000..325241c +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/scsi-common-modules +@@ -0,0 +1 @@ ++sym53c8xx +diff --git a/debian/installer/armel/modules/armel-versatile/scsi-core-modules b/debian/installer/armel/modules/armel-versatile/scsi-core-modules +new file mode 100644 +index 0000000..dd65d66 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/scsi-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/squashfs-modules b/debian/installer/armel/modules/armel-versatile/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/udf-modules b/debian/installer/armel/modules/armel-versatile/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/usb-modules b/debian/installer/armel/modules/armel-versatile/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/usb-serial-modules b/debian/installer/armel/modules/armel-versatile/usb-serial-modules +new file mode 100644 +index 0000000..c0a0dc3 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/usb-serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/usb-storage-modules b/debian/installer/armel/modules/armel-versatile/usb-storage-modules +new file mode 100644 +index 0000000..8c5e81b +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/usb-storage-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/virtio-modules b/debian/installer/armel/modules/armel-versatile/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/modules/armel-versatile/zlib-modules b/debian/installer/armel/modules/armel-versatile/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/armel/modules/armel-versatile/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armel/package-list b/debian/installer/armel/package-list +new file mode 100644 +index 0000000..3f3d9fd +--- /dev/null ++++ b/debian/installer/armel/package-list +@@ -0,0 +1,32 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: kernel-image ++Provides_iop32x: rtc-modules ++Provides_kirkwood: rtc-modules, jffs2-modules, zlib-modules ++Provides_orion5x: rtc-modules ++Provides_versatile: rtc-modules ++ ++Package: ext2-modules ++Depends: kernel-image, core-modules ++ ++Package: ext3-modules ++Depends: kernel-image, core-modules ++ ++Package: beeper-modules ++Depends: event-modules ++Priority: extra ++Description: Beeper support ++ This package contains beeper drivers for the kernel. ++ ++Package: fb-modules ++Depends: kernel-image, usb-modules, nls-core-modules ++ ++Package: pata-modules ++Depends: kernel-image, ata-modules ++Priority: standard ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/armhf/kernel-versions b/debian/installer/armhf/kernel-versions +new file mode 100644 +index 0000000..cf3465a +--- /dev/null ++++ b/debian/installer/armhf/kernel-versions +@@ -0,0 +1,3 @@ ++# arch version flavour installedname suffix build-depends ++armhf - mx5 - y - ++armhf - vexpress - y - +diff --git a/debian/installer/armhf/modules/armhf-mx5/ata-modules b/debian/installer/armhf/modules/armhf-mx5/ata-modules +new file mode 100644 +index 0000000..04d9c88 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/ata-modules +@@ -0,0 +1 @@ ++libata +diff --git a/debian/installer/armhf/modules/armhf-mx5/btrfs-modules b/debian/installer/armhf/modules/armhf-mx5/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/core-modules b/debian/installer/armhf/modules/armhf-mx5/core-modules +new file mode 100644 +index 0000000..21826c6 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/core-modules +@@ -0,0 +1,2 @@ ++#include ++mbcache +diff --git a/debian/installer/armhf/modules/armhf-mx5/crc-modules b/debian/installer/armhf/modules/armhf-mx5/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/crypto-dm-modules b/debian/installer/armhf/modules/armhf-mx5/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/crypto-modules b/debian/installer/armhf/modules/armhf-mx5/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/ext2-modules b/debian/installer/armhf/modules/armhf-mx5/ext2-modules +new file mode 100644 +index 0000000..c407140 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/ext2-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/ext3-modules b/debian/installer/armhf/modules/armhf-mx5/ext3-modules +new file mode 100644 +index 0000000..bbdd7f4 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/ext3-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/ext4-modules b/debian/installer/armhf/modules/armhf-mx5/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/fat-modules b/debian/installer/armhf/modules/armhf-mx5/fat-modules +new file mode 100644 +index 0000000..274584e +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/fat-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/fuse-modules b/debian/installer/armhf/modules/armhf-mx5/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/input-modules b/debian/installer/armhf/modules/armhf-mx5/input-modules +new file mode 100644 +index 0000000..1a24866 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/input-modules +@@ -0,0 +1,4 @@ ++#include ++usbhid - ++usbmouse - ++usbkbd - +diff --git a/debian/installer/armhf/modules/armhf-mx5/ipv6-modules b/debian/installer/armhf/modules/armhf-mx5/ipv6-modules +new file mode 100644 +index 0000000..1e3fc33 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/ipv6-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/isofs-modules b/debian/installer/armhf/modules/armhf-mx5/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/jfs-modules b/debian/installer/armhf/modules/armhf-mx5/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/kernel-image b/debian/installer/armhf/modules/armhf-mx5/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/armhf/modules/armhf-mx5/loop-modules b/debian/installer/armhf/modules/armhf-mx5/loop-modules +new file mode 100644 +index 0000000..c1c948f +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/loop-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/md-modules b/debian/installer/armhf/modules/armhf-mx5/md-modules +new file mode 100644 +index 0000000..26115e1 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/md-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/minix-modules b/debian/installer/armhf/modules/armhf-mx5/minix-modules +new file mode 100644 +index 0000000..82b9843 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/minix-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/mmc-modules b/debian/installer/armhf/modules/armhf-mx5/mmc-modules +new file mode 100644 +index 0000000..5f0b5d7 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/mmc-modules +@@ -0,0 +1,2 @@ ++#include ++sdhci-esdhc-imx +diff --git a/debian/installer/armhf/modules/armhf-mx5/mtd-modules b/debian/installer/armhf/modules/armhf-mx5/mtd-modules +new file mode 100644 +index 0000000..86c5fe2 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/mtd-modules +@@ -0,0 +1,4 @@ ++#include ++ ++# SPI NOR flash for Efika ++m25p80 +diff --git a/debian/installer/armhf/modules/armhf-mx5/multipath-modules b/debian/installer/armhf/modules/armhf-mx5/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/nbd-modules b/debian/installer/armhf/modules/armhf-mx5/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/nic-shared-modules b/debian/installer/armhf/modules/armhf-mx5/nic-shared-modules +new file mode 100644 +index 0000000..9d2c44c +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/nic-shared-modules +@@ -0,0 +1,2 @@ ++mii ++#libphy +diff --git a/debian/installer/armhf/modules/armhf-mx5/nic-usb-modules b/debian/installer/armhf/modules/armhf-mx5/nic-usb-modules +new file mode 100644 +index 0000000..c479669 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/nic-usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/nic-wireless-modules b/debian/installer/armhf/modules/armhf-mx5/nic-wireless-modules +new file mode 100644 +index 0000000..53fd18d +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/nic-wireless-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/pata-modules b/debian/installer/armhf/modules/armhf-mx5/pata-modules +new file mode 100644 +index 0000000..2ff7276 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/pata-modules +@@ -0,0 +1 @@ ++pata_imx +diff --git a/debian/installer/armhf/modules/armhf-mx5/reiserfs-modules b/debian/installer/armhf/modules/armhf-mx5/reiserfs-modules +new file mode 100644 +index 0000000..fad554f +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/reiserfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/sata-modules b/debian/installer/armhf/modules/armhf-mx5/sata-modules +new file mode 100644 +index 0000000..a2ff9d0 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/sata-modules +@@ -0,0 +1 @@ ++ahci_platform +diff --git a/debian/installer/armhf/modules/armhf-mx5/scsi-core-modules b/debian/installer/armhf/modules/armhf-mx5/scsi-core-modules +new file mode 100644 +index 0000000..4cdf2474 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/scsi-core-modules +@@ -0,0 +1,3 @@ ++#include ++scsi_mod - ++sd_mod - +diff --git a/debian/installer/armhf/modules/armhf-mx5/squashfs-modules b/debian/installer/armhf/modules/armhf-mx5/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/udf-modules b/debian/installer/armhf/modules/armhf-mx5/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/uinput-modules b/debian/installer/armhf/modules/armhf-mx5/uinput-modules +new file mode 100644 +index 0000000..58a8337 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/uinput-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-mx5/usb-storage-modules b/debian/installer/armhf/modules/armhf-mx5/usb-storage-modules +new file mode 100644 +index 0000000..6938b5c +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-mx5/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++usb-storage - +diff --git a/debian/installer/armhf/modules/armhf-vexpress/btrfs-modules b/debian/installer/armhf/modules/armhf-vexpress/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/core-modules b/debian/installer/armhf/modules/armhf-vexpress/core-modules +new file mode 100644 +index 0000000..21826c6 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/core-modules +@@ -0,0 +1,2 @@ ++#include ++mbcache +diff --git a/debian/installer/armhf/modules/armhf-vexpress/crc-modules b/debian/installer/armhf/modules/armhf-vexpress/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/crypto-dm-modules b/debian/installer/armhf/modules/armhf-vexpress/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/crypto-modules b/debian/installer/armhf/modules/armhf-vexpress/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/ext2-modules b/debian/installer/armhf/modules/armhf-vexpress/ext2-modules +new file mode 100644 +index 0000000..c407140 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/ext2-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/ext3-modules b/debian/installer/armhf/modules/armhf-vexpress/ext3-modules +new file mode 100644 +index 0000000..bbdd7f4 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/ext3-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/ext4-modules b/debian/installer/armhf/modules/armhf-vexpress/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/fat-modules b/debian/installer/armhf/modules/armhf-vexpress/fat-modules +new file mode 100644 +index 0000000..274584e +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/fat-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/fuse-modules b/debian/installer/armhf/modules/armhf-vexpress/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/input-modules b/debian/installer/armhf/modules/armhf-vexpress/input-modules +new file mode 100644 +index 0000000..1a24866 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/input-modules +@@ -0,0 +1,4 @@ ++#include ++usbhid - ++usbmouse - ++usbkbd - +diff --git a/debian/installer/armhf/modules/armhf-vexpress/ipv6-modules b/debian/installer/armhf/modules/armhf-vexpress/ipv6-modules +new file mode 100644 +index 0000000..1e3fc33 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/ipv6-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/isofs-modules b/debian/installer/armhf/modules/armhf-vexpress/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/jfs-modules b/debian/installer/armhf/modules/armhf-vexpress/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/kernel-image b/debian/installer/armhf/modules/armhf-vexpress/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/armhf/modules/armhf-vexpress/loop-modules b/debian/installer/armhf/modules/armhf-vexpress/loop-modules +new file mode 100644 +index 0000000..c1c948f +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/loop-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/md-modules b/debian/installer/armhf/modules/armhf-vexpress/md-modules +new file mode 100644 +index 0000000..26115e1 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/md-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/mmc-modules b/debian/installer/armhf/modules/armhf-vexpress/mmc-modules +new file mode 100644 +index 0000000..0349f6c +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/mmc-modules +@@ -0,0 +1,2 @@ ++#include ++tifm_sd - +diff --git a/debian/installer/armhf/modules/armhf-vexpress/multipath-modules b/debian/installer/armhf/modules/armhf-vexpress/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/nbd-modules b/debian/installer/armhf/modules/armhf-vexpress/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/nic-modules b/debian/installer/armhf/modules/armhf-vexpress/nic-modules +new file mode 100644 +index 0000000..d62600c +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/nic-modules +@@ -0,0 +1 @@ ++smsc911x +diff --git a/debian/installer/armhf/modules/armhf-vexpress/nic-shared-modules b/debian/installer/armhf/modules/armhf-vexpress/nic-shared-modules +new file mode 100644 +index 0000000..4071438 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/nic-shared-modules +@@ -0,0 +1,2 @@ ++mii ++libphy +diff --git a/debian/installer/armhf/modules/armhf-vexpress/nic-usb-modules b/debian/installer/armhf/modules/armhf-vexpress/nic-usb-modules +new file mode 100644 +index 0000000..c479669 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/nic-usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/nic-wireless-modules b/debian/installer/armhf/modules/armhf-vexpress/nic-wireless-modules +new file mode 100644 +index 0000000..53fd18d +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/nic-wireless-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/scsi-core-modules b/debian/installer/armhf/modules/armhf-vexpress/scsi-core-modules +new file mode 100644 +index 0000000..4cdf2474 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/scsi-core-modules +@@ -0,0 +1,3 @@ ++#include ++scsi_mod - ++sd_mod - +diff --git a/debian/installer/armhf/modules/armhf-vexpress/squashfs-modules b/debian/installer/armhf/modules/armhf-vexpress/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/udf-modules b/debian/installer/armhf/modules/armhf-vexpress/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/uinput-modules b/debian/installer/armhf/modules/armhf-vexpress/uinput-modules +new file mode 100644 +index 0000000..58a8337 +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/uinput-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/usb-modules b/debian/installer/armhf/modules/armhf-vexpress/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/armhf/modules/armhf-vexpress/usb-storage-modules b/debian/installer/armhf/modules/armhf-vexpress/usb-storage-modules +new file mode 100644 +index 0000000..6938b5c +--- /dev/null ++++ b/debian/installer/armhf/modules/armhf-vexpress/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++usb-storage - +diff --git a/debian/installer/armhf/package-list b/debian/installer/armhf/package-list +new file mode 100644 +index 0000000..a53bb37 +--- /dev/null ++++ b/debian/installer/armhf/package-list +@@ -0,0 +1,32 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: kernel-image ++Provides_mx5: rtc-modules ++Provides_vexpress: rtc-modules ++ ++Package: ext2-modules ++Depends: kernel-image, core-modules ++ ++Package: ext3-modules ++Depends: kernel-image, core-modules ++ ++# Package: beeper-modules ++# Depends: event-modules ++# Priority: extra ++# Description: Beeper support ++# This package contains beeper drivers for the kernel. ++ ++# Package: fb-modules ++# Depends: usb-modules, nls-core-modules ++ ++Package: pata-modules ++Depends: kernel-image, ata-modules ++Priority: extra ++ ++Package: ext4-modules ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/hppa/kernel-versions b/debian/installer/hppa/kernel-versions +new file mode 100644 +index 0000000..7522814 +--- /dev/null ++++ b/debian/installer/hppa/kernel-versions +@@ -0,0 +1,3 @@ ++# arch version flavour installedname suffix build-depends ++hppa - parisc - y - ++hppa - parisc64 - y - +diff --git a/debian/installer/hppa/modules/hppa/btrfs-modules b/debian/installer/hppa/modules/hppa/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/hppa/modules/hppa/cdrom-core-modules b/debian/installer/hppa/modules/hppa/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/hppa/modules/hppa/crypto-dm-modules b/debian/installer/hppa/modules/hppa/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/hppa/modules/hppa/crypto-modules b/debian/installer/hppa/modules/hppa/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/hppa/modules/hppa/ext3-modules b/debian/installer/hppa/modules/hppa/ext3-modules +new file mode 100644 +index 0000000..55ef7d7 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/ext3-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/hppa/modules/hppa/ext4-modules b/debian/installer/hppa/modules/hppa/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/hppa/modules/hppa/fat-modules b/debian/installer/hppa/modules/hppa/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/hppa/modules/hppa/fuse-modules b/debian/installer/hppa/modules/hppa/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/hppa/modules/hppa/input-modules b/debian/installer/hppa/modules/hppa/input-modules +new file mode 100644 +index 0000000..9d4cbf6 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/input-modules +@@ -0,0 +1,6 @@ ++#include ++hil_kbd ? ++hilkbd ? ++hp_sdc_mlc ? ++hil_mlc ? ++hp_sdc ? +diff --git a/debian/installer/hppa/modules/hppa/ipv6-modules b/debian/installer/hppa/modules/hppa/ipv6-modules +new file mode 100644 +index 0000000..cadae6f +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/ipv6-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/hppa/modules/hppa/kernel-image b/debian/installer/hppa/modules/hppa/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/hppa/modules/hppa/loop-modules b/debian/installer/hppa/modules/hppa/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/hppa/modules/hppa/md-modules b/debian/installer/hppa/modules/hppa/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/hppa/modules/hppa/multipath-modules b/debian/installer/hppa/modules/hppa/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/hppa/modules/hppa/nbd-modules b/debian/installer/hppa/modules/hppa/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/hppa/modules/hppa/nic-modules b/debian/installer/hppa/modules/hppa/nic-modules +new file mode 100644 +index 0000000..8a4b656 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/nic-modules +@@ -0,0 +1,4 @@ ++lasi_82596 ++tg3 ++tulip ++e1000 +diff --git a/debian/installer/hppa/modules/hppa/pata-modules b/debian/installer/hppa/modules/hppa/pata-modules +new file mode 100644 +index 0000000..8c4e514 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/pata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/hppa/modules/hppa/ppp-modules b/debian/installer/hppa/modules/hppa/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/hppa/modules/hppa/scsi-core-modules b/debian/installer/hppa/modules/hppa/scsi-core-modules +new file mode 100644 +index 0000000..dd65d66 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/scsi-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/hppa/modules/hppa/scsi-modules b/debian/installer/hppa/modules/hppa/scsi-modules +new file mode 100644 +index 0000000..0f18fba +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/scsi-modules +@@ -0,0 +1,12 @@ ++53c700 ++ch ++lasi700 ++osst ++sg ++st ++sym53c8xx ++zalon7xx ++megaraid ++qlogicfas408 ++mptbase ++mptspi +diff --git a/debian/installer/hppa/modules/hppa/usb-modules b/debian/installer/hppa/modules/hppa/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/hppa/modules/hppa/usb-storage-modules b/debian/installer/hppa/modules/hppa/usb-storage-modules +new file mode 100644 +index 0000000..272d95e +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/hppa/modules/hppa/zlib-modules b/debian/installer/hppa/modules/hppa/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/hppa/modules/hppa/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/hppa/package-list b/debian/installer/hppa/package-list +new file mode 100644 +index 0000000..16d8c11 +--- /dev/null ++++ b/debian/installer/hppa/package-list +@@ -0,0 +1,19 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: kernel-image ++Provides: ext2-modules ++ ++Package: usb-storage-modules ++Depends: kernel-image, ide-modules, scsi-modules, usb-modules ++ ++Package: ide-modules ++Depends: kernel-image, ide-core-modules, nls-core-modules ++ ++Package: pata-modules ++Depends: kernel-image, scsi-core-modules ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/i386/kernel-versions b/debian/installer/i386/kernel-versions +new file mode 100644 +index 0000000..d11e761 +--- /dev/null ++++ b/debian/installer/i386/kernel-versions +@@ -0,0 +1,3 @@ ++# arch version flavour installedname suffix build-depends ++i386 - 486 - - - ++i386 - 686-pae - - - +diff --git a/debian/installer/i386/modules/i386/acpi-modules b/debian/installer/i386/modules/i386/acpi-modules +new file mode 100644 +index 0000000..307528f +--- /dev/null ++++ b/debian/installer/i386/modules/i386/acpi-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/ata-modules b/debian/installer/i386/modules/i386/ata-modules +new file mode 100644 +index 0000000..9409e7c +--- /dev/null ++++ b/debian/installer/i386/modules/i386/ata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/btrfs-modules b/debian/installer/i386/modules/i386/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/cdrom-core-modules b/debian/installer/i386/modules/i386/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/i386/modules/i386/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/core-modules b/debian/installer/i386/modules/i386/core-modules +new file mode 100644 +index 0000000..21826c6 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/core-modules +@@ -0,0 +1,2 @@ ++#include ++mbcache +diff --git a/debian/installer/i386/modules/i386/crc-modules b/debian/installer/i386/modules/i386/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/crypto-dm-modules b/debian/installer/i386/modules/i386/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/crypto-modules b/debian/installer/i386/modules/i386/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/efi-modules b/debian/installer/i386/modules/i386/efi-modules +new file mode 100644 +index 0000000..e1dc05e +--- /dev/null ++++ b/debian/installer/i386/modules/i386/efi-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/event-modules b/debian/installer/i386/modules/i386/event-modules +new file mode 100644 +index 0000000..f8819af +--- /dev/null ++++ b/debian/installer/i386/modules/i386/event-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/ext2-modules b/debian/installer/i386/modules/i386/ext2-modules +new file mode 100644 +index 0000000..c407140 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/ext2-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/ext3-modules b/debian/installer/i386/modules/i386/ext3-modules +new file mode 100644 +index 0000000..55ef7d7 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/ext3-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/ext4-modules b/debian/installer/i386/modules/i386/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/fat-modules b/debian/installer/i386/modules/i386/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/fb-modules b/debian/installer/i386/modules/i386/fb-modules +new file mode 100644 +index 0000000..3180564 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/fb-modules +@@ -0,0 +1,5 @@ ++fbcon ? ++lxfb ? ++vesafb ? ++vga16fb ++viafb +diff --git a/debian/installer/i386/modules/i386/firewire-core-modules b/debian/installer/i386/modules/i386/firewire-core-modules +new file mode 100644 +index 0000000..dcac80a +--- /dev/null ++++ b/debian/installer/i386/modules/i386/firewire-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/floppy-modules b/debian/installer/i386/modules/i386/floppy-modules +new file mode 100644 +index 0000000..169fde5 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/floppy-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/fuse-modules b/debian/installer/i386/modules/i386/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/i386/modules/i386/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/hyperv-modules b/debian/installer/i386/modules/i386/hyperv-modules +new file mode 100644 +index 0000000..69fdd5d +--- /dev/null ++++ b/debian/installer/i386/modules/i386/hyperv-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/i2c-modules b/debian/installer/i386/modules/i386/i2c-modules +new file mode 100644 +index 0000000..965248d +--- /dev/null ++++ b/debian/installer/i386/modules/i386/i2c-modules +@@ -0,0 +1,2 @@ ++#include ++i2c-algo-bit +diff --git a/debian/installer/i386/modules/i386/input-modules b/debian/installer/i386/modules/i386/input-modules +new file mode 100644 +index 0000000..5ecb595 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/input-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/irda-modules b/debian/installer/i386/modules/i386/irda-modules +new file mode 100644 +index 0000000..4cf34ae +--- /dev/null ++++ b/debian/installer/i386/modules/i386/irda-modules +@@ -0,0 +1,18 @@ ++act200l-sir ++actisys-sir ++ali-ircc ++irda-usb ++irtty-sir ++litelink-sir ++ma600-sir ++mcp2120-sir ++nsc-ircc ++old_belkin-sir ++tekram-sir ++vlsi_ir ++w83977af_ir ++ircomm-tty ++ircomm ++irda ++irnet ++via-ircc ? +diff --git a/debian/installer/i386/modules/i386/isofs-modules b/debian/installer/i386/modules/i386/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/i386/modules/i386/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/jfs-modules b/debian/installer/i386/modules/i386/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/kernel-image b/debian/installer/i386/modules/i386/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/i386/modules/i386/loop-modules b/debian/installer/i386/modules/i386/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/md-modules b/debian/installer/i386/modules/i386/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/i386/modules/i386/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/mmc-core-modules b/debian/installer/i386/modules/i386/mmc-core-modules +new file mode 100644 +index 0000000..7bf3846 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/mmc-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/mmc-modules b/debian/installer/i386/modules/i386/mmc-modules +new file mode 100644 +index 0000000..dadfd53 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/mmc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/mouse-modules b/debian/installer/i386/modules/i386/mouse-modules +new file mode 100644 +index 0000000..15fcb00 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/mouse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/multipath-modules b/debian/installer/i386/modules/i386/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/nbd-modules b/debian/installer/i386/modules/i386/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/nic-extra-modules b/debian/installer/i386/modules/i386/nic-extra-modules +new file mode 100644 +index 0000000..75e2d78 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/nic-extra-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/nic-modules b/debian/installer/i386/modules/i386/nic-modules +new file mode 100644 +index 0000000..2512e83 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/nic-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/nic-pcmcia-modules b/debian/installer/i386/modules/i386/nic-pcmcia-modules +new file mode 100644 +index 0000000..7a0702c +--- /dev/null ++++ b/debian/installer/i386/modules/i386/nic-pcmcia-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/nic-shared-modules b/debian/installer/i386/modules/i386/nic-shared-modules +new file mode 100644 +index 0000000..b52153d +--- /dev/null ++++ b/debian/installer/i386/modules/i386/nic-shared-modules +@@ -0,0 +1,3 @@ ++8390 ++mii ++libphy +diff --git a/debian/installer/i386/modules/i386/nic-usb-modules b/debian/installer/i386/modules/i386/nic-usb-modules +new file mode 100644 +index 0000000..c479669 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/nic-usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/nic-wireless-modules b/debian/installer/i386/modules/i386/nic-wireless-modules +new file mode 100644 +index 0000000..53fd18d +--- /dev/null ++++ b/debian/installer/i386/modules/i386/nic-wireless-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/ntfs-modules b/debian/installer/i386/modules/i386/ntfs-modules +new file mode 100644 +index 0000000..ac1bc6a +--- /dev/null ++++ b/debian/installer/i386/modules/i386/ntfs-modules +@@ -0,0 +1 @@ ++ntfs +diff --git a/debian/installer/i386/modules/i386/parport-modules b/debian/installer/i386/modules/i386/parport-modules +new file mode 100644 +index 0000000..6ea7b6f +--- /dev/null ++++ b/debian/installer/i386/modules/i386/parport-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/pata-modules b/debian/installer/i386/modules/i386/pata-modules +new file mode 100644 +index 0000000..8c4e514 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/pata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/pcmcia-modules b/debian/installer/i386/modules/i386/pcmcia-modules +new file mode 100644 +index 0000000..2bb5350 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/pcmcia-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/pcmcia-storage-modules b/debian/installer/i386/modules/i386/pcmcia-storage-modules +new file mode 100644 +index 0000000..f73ae5b +--- /dev/null ++++ b/debian/installer/i386/modules/i386/pcmcia-storage-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/plip-modules b/debian/installer/i386/modules/i386/plip-modules +new file mode 100644 +index 0000000..eab43fa +--- /dev/null ++++ b/debian/installer/i386/modules/i386/plip-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/ppp-modules b/debian/installer/i386/modules/i386/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/qnx4-modules b/debian/installer/i386/modules/i386/qnx4-modules +new file mode 100644 +index 0000000..cd0c96d +--- /dev/null ++++ b/debian/installer/i386/modules/i386/qnx4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/reiserfs-modules b/debian/installer/i386/modules/i386/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/sata-modules b/debian/installer/i386/modules/i386/sata-modules +new file mode 100644 +index 0000000..071cb86 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/sata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/scsi-common-modules b/debian/installer/i386/modules/i386/scsi-common-modules +new file mode 100644 +index 0000000..4973901 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/scsi-common-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/scsi-core-modules b/debian/installer/i386/modules/i386/scsi-core-modules +new file mode 100644 +index 0000000..4684cab +--- /dev/null ++++ b/debian/installer/i386/modules/i386/scsi-core-modules +@@ -0,0 +1,2 @@ ++#include ++scsi_transport_spi +diff --git a/debian/installer/i386/modules/i386/scsi-extra-modules b/debian/installer/i386/modules/i386/scsi-extra-modules +new file mode 100644 +index 0000000..cd13ede +--- /dev/null ++++ b/debian/installer/i386/modules/i386/scsi-extra-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/scsi-modules b/debian/installer/i386/modules/i386/scsi-modules +new file mode 100644 +index 0000000..8909dfb +--- /dev/null ++++ b/debian/installer/i386/modules/i386/scsi-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/serial-modules b/debian/installer/i386/modules/i386/serial-modules +new file mode 100644 +index 0000000..6ab8b8c +--- /dev/null ++++ b/debian/installer/i386/modules/i386/serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/sound-modules b/debian/installer/i386/modules/i386/sound-modules +new file mode 100644 +index 0000000..68395ab +--- /dev/null ++++ b/debian/installer/i386/modules/i386/sound-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/speakup-modules b/debian/installer/i386/modules/i386/speakup-modules +new file mode 100644 +index 0000000..2959272 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/speakup-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/squashfs-modules b/debian/installer/i386/modules/i386/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/udf-modules b/debian/installer/i386/modules/i386/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/i386/modules/i386/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/ufs-modules b/debian/installer/i386/modules/i386/ufs-modules +new file mode 100644 +index 0000000..69745ca +--- /dev/null ++++ b/debian/installer/i386/modules/i386/ufs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/uinput-modules b/debian/installer/i386/modules/i386/uinput-modules +new file mode 100644 +index 0000000..58a8337 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/uinput-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/usb-modules b/debian/installer/i386/modules/i386/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/i386/modules/i386/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/usb-serial-modules b/debian/installer/i386/modules/i386/usb-serial-modules +new file mode 100644 +index 0000000..c0a0dc3 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/usb-serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/usb-storage-modules b/debian/installer/i386/modules/i386/usb-storage-modules +new file mode 100644 +index 0000000..272d95e +--- /dev/null ++++ b/debian/installer/i386/modules/i386/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/virtio-modules b/debian/installer/i386/modules/i386/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/modules/i386/xfs-modules b/debian/installer/i386/modules/i386/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/i386/modules/i386/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/i386/modules/i386/zlib-modules b/debian/installer/i386/modules/i386/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/i386/modules/i386/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/i386/package-list b/debian/installer/i386/package-list +new file mode 100644 +index 0000000..da534ce +--- /dev/null ++++ b/debian/installer/i386/package-list +@@ -0,0 +1,32 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++ ++Package: kernel-image ++Provides: rtc-modules ++ ++Package: ext2-modules ++Depends: kernel-image, core-modules ++ ++Package: ext3-modules ++Depends: kernel-image, core-modules ++ ++Package: fat-modules ++Priority: standard ++ ++Package: nic-modules ++Depends: kernel-image, nic-shared-modules, core-modules, firewire-core-modules ++ ++Package: scsi-modules ++Depends: kernel-image, scsi-core-modules, parport-modules, cdrom-core-modules, core-modules, ata-modules ++ ++Package: pcmcia-modules ++Depends: kernel-image, core-modules ++ ++Package: nbd-modules ++Depends: kernel-image ++ ++Package: fb-modules ++Depends: kernel-image, i2c-modules +diff --git a/debian/installer/ia64/TODO b/debian/installer/ia64/TODO +new file mode 100644 +index 0000000..d02dd6c +--- /dev/null ++++ b/debian/installer/ia64/TODO +@@ -0,0 +1,3 @@ ++* The 2.6 kernel is missing a lot of modules, need to get a list of all ++ modules included in the udebs, and compare vs. the full module list and ++ add missing stuff. +diff --git a/debian/installer/ia64/kernel-versions b/debian/installer/ia64/kernel-versions +new file mode 100644 +index 0000000..24043ff +--- /dev/null ++++ b/debian/installer/ia64/kernel-versions +@@ -0,0 +1,2 @@ ++# arch version flavour installedname suffix build-depends ++ia64 - itanium - - - +diff --git a/debian/installer/ia64/modules/ia64/ata-modules b/debian/installer/ia64/modules/ia64/ata-modules +new file mode 100644 +index 0000000..b81c0f3 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/ata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/btrfs-modules b/debian/installer/ia64/modules/ia64/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/cdrom-core-modules b/debian/installer/ia64/modules/ia64/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/core-modules b/debian/installer/ia64/modules/ia64/core-modules +new file mode 100644 +index 0000000..21826c6 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/core-modules +@@ -0,0 +1,2 @@ ++#include ++mbcache +diff --git a/debian/installer/ia64/modules/ia64/crc-modules b/debian/installer/ia64/modules/ia64/crc-modules +new file mode 100644 +index 0000000..a642ead +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/crc-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/crypto-dm-modules b/debian/installer/ia64/modules/ia64/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/crypto-modules b/debian/installer/ia64/modules/ia64/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/event-modules b/debian/installer/ia64/modules/ia64/event-modules +new file mode 100644 +index 0000000..f8819af +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/event-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/ext2-modules b/debian/installer/ia64/modules/ia64/ext2-modules +new file mode 100644 +index 0000000..bbaebc8 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/ext2-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/ext3-modules b/debian/installer/ia64/modules/ia64/ext3-modules +new file mode 100644 +index 0000000..55ef7d7 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/ext3-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/ext4-modules b/debian/installer/ia64/modules/ia64/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/fat-modules b/debian/installer/ia64/modules/ia64/fat-modules +new file mode 100644 +index 0000000..274584e +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/fat-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/fb-modules b/debian/installer/ia64/modules/ia64/fb-modules +new file mode 100644 +index 0000000..1442c89 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/fb-modules +@@ -0,0 +1,2 @@ ++fbcon ? ++vgastate +diff --git a/debian/installer/ia64/modules/ia64/firewire-core-modules b/debian/installer/ia64/modules/ia64/firewire-core-modules +new file mode 100644 +index 0000000..8e5fff1 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/firewire-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/fuse-modules b/debian/installer/ia64/modules/ia64/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/ide-core-modules b/debian/installer/ia64/modules/ia64/ide-core-modules +new file mode 100644 +index 0000000..049d93f +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/ide-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/ide-modules b/debian/installer/ia64/modules/ia64/ide-modules +new file mode 100644 +index 0000000..bac4ee1 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/ide-modules +@@ -0,0 +1,2 @@ ++#include ++sgiioc4 +diff --git a/debian/installer/ia64/modules/ia64/input-modules b/debian/installer/ia64/modules/ia64/input-modules +new file mode 100644 +index 0000000..5ecb595 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/input-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/irda-modules b/debian/installer/ia64/modules/ia64/irda-modules +new file mode 100644 +index 0000000..66a92f2 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/irda-modules +@@ -0,0 +1,9 @@ ++irda-usb ++irtty-sir ++sir-dev ++stir4200 ++ircomm-tty ++ircomm ++irda ++irlan ++irnet +diff --git a/debian/installer/ia64/modules/ia64/isofs-modules b/debian/installer/ia64/modules/ia64/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/jfs-modules b/debian/installer/ia64/modules/ia64/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/kernel-image b/debian/installer/ia64/modules/ia64/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/ia64/modules/ia64/loop-modules b/debian/installer/ia64/modules/ia64/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/md-modules b/debian/installer/ia64/modules/ia64/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/mouse-modules b/debian/installer/ia64/modules/ia64/mouse-modules +new file mode 100644 +index 0000000..15fcb00 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/mouse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/multipath-modules b/debian/installer/ia64/modules/ia64/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/nbd-modules b/debian/installer/ia64/modules/ia64/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/nic-modules b/debian/installer/ia64/modules/ia64/nic-modules +new file mode 100644 +index 0000000..718821b +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/nic-modules +@@ -0,0 +1,2 @@ ++#include ++#include +diff --git a/debian/installer/ia64/modules/ia64/nic-shared-modules b/debian/installer/ia64/modules/ia64/nic-shared-modules +new file mode 100644 +index 0000000..b52153d +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/nic-shared-modules +@@ -0,0 +1,3 @@ ++8390 ++mii ++libphy +diff --git a/debian/installer/ia64/modules/ia64/nic-usb-modules b/debian/installer/ia64/modules/ia64/nic-usb-modules +new file mode 100644 +index 0000000..c479669 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/nic-usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/ntfs-modules b/debian/installer/ia64/modules/ia64/ntfs-modules +new file mode 100644 +index 0000000..ac1bc6a +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/ntfs-modules +@@ -0,0 +1 @@ ++ntfs +diff --git a/debian/installer/ia64/modules/ia64/parport-modules b/debian/installer/ia64/modules/ia64/parport-modules +new file mode 100644 +index 0000000..6ea7b6f +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/parport-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/pata-modules b/debian/installer/ia64/modules/ia64/pata-modules +new file mode 100644 +index 0000000..b0cd633 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/pata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/pcmcia-modules b/debian/installer/ia64/modules/ia64/pcmcia-modules +new file mode 100644 +index 0000000..d7a54f3 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/pcmcia-modules +@@ -0,0 +1,4 @@ ++pcmcia ++pcmcia_core ++pd6729 ++rsrc_nonstatic ? +diff --git a/debian/installer/ia64/modules/ia64/plip-modules b/debian/installer/ia64/modules/ia64/plip-modules +new file mode 100644 +index 0000000..eab43fa +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/plip-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/ppp-modules b/debian/installer/ia64/modules/ia64/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/reiserfs-modules b/debian/installer/ia64/modules/ia64/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/sata-modules b/debian/installer/ia64/modules/ia64/sata-modules +new file mode 100644 +index 0000000..071cb86 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/sata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/scsi-core-modules b/debian/installer/ia64/modules/ia64/scsi-core-modules +new file mode 100644 +index 0000000..4684cab +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/scsi-core-modules +@@ -0,0 +1,2 @@ ++#include ++scsi_transport_spi +diff --git a/debian/installer/ia64/modules/ia64/scsi-modules b/debian/installer/ia64/modules/ia64/scsi-modules +new file mode 100644 +index 0000000..781aeed +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/scsi-modules +@@ -0,0 +1,3 @@ ++#include ++#include ++#include +diff --git a/debian/installer/ia64/modules/ia64/serial-modules b/debian/installer/ia64/modules/ia64/serial-modules +new file mode 100644 +index 0000000..13dac04 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/serial-modules +@@ -0,0 +1,3 @@ ++#include ++ioc3_serial ++ioc4_serial +diff --git a/debian/installer/ia64/modules/ia64/sn-modules b/debian/installer/ia64/modules/ia64/sn-modules +new file mode 100644 +index 0000000..4274c5f +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/sn-modules +@@ -0,0 +1,2 @@ ++ioc3 ++ioc4 +diff --git a/debian/installer/ia64/modules/ia64/squashfs-modules b/debian/installer/ia64/modules/ia64/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/udf-modules b/debian/installer/ia64/modules/ia64/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/ufs-modules b/debian/installer/ia64/modules/ia64/ufs-modules +new file mode 100644 +index 0000000..69745ca +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/ufs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/uinput-modules b/debian/installer/ia64/modules/ia64/uinput-modules +new file mode 100644 +index 0000000..58a8337 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/uinput-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/usb-modules b/debian/installer/ia64/modules/ia64/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/modules/ia64/usb-storage-modules b/debian/installer/ia64/modules/ia64/usb-storage-modules +new file mode 100644 +index 0000000..272d95e +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/xfs-modules b/debian/installer/ia64/modules/ia64/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ia64/modules/ia64/zlib-modules b/debian/installer/ia64/modules/ia64/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/ia64/modules/ia64/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ia64/package-list b/debian/installer/ia64/package-list +new file mode 100644 +index 0000000..84637be +--- /dev/null ++++ b/debian/installer/ia64/package-list +@@ -0,0 +1,37 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: fat-modules ++Priority: standard ++ ++Package: ide-modules ++Depends: kernel-image, ide-core-modules, sn-modules ++ ++Package: nic-modules ++Depends: kernel-image, nic-shared-modules, core-modules, firewire-core-modules, crc-modules ++ ++Package: pcmcia-modules ++Depends: kernel-image, core-modules ++ ++Package: serial-modules ++Depends: kernel-image, pcmcia-modules, sn-modules ++ ++Package: sn-modules ++Depends: kernel-image ++Priority: extra ++Description: SN modules ++ This package contains SN modules for Altix systems ++ ++Package: ext2-modules ++Depends: kernel-image, core-modules ++ ++Package: ext3-modules ++Depends: kernel-image, core-modules ++ ++Package: nbd-modules ++Depends: kernel-image ++ ++Package: kernel-image ++Provides: efi-modules +diff --git a/debian/installer/m68k/kernel-versions b/debian/installer/m68k/kernel-versions +new file mode 100644 +index 0000000..5c36774 +--- /dev/null ++++ b/debian/installer/m68k/kernel-versions +@@ -0,0 +1,4 @@ ++# arch version flavour installedname suffix build-depends ++m68k - amiga - y - ++m68k - atari - y - ++m68k - mac - y - +diff --git a/debian/installer/m68k/modules/m68k-mac/btrfs-modules b/debian/installer/m68k/modules/m68k-mac/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/cdrom-core-modules b/debian/installer/m68k/modules/m68k-mac/cdrom-core-modules +new file mode 100644 +index 0000000..3ff69b4 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/cdrom-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/crypto-modules b/debian/installer/m68k/modules/m68k-mac/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/fat-modules b/debian/installer/m68k/modules/m68k-mac/fat-modules +new file mode 100644 +index 0000000..274584e +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/fat-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/fuse-modules b/debian/installer/m68k/modules/m68k-mac/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/ipv6-modules b/debian/installer/m68k/modules/m68k-mac/ipv6-modules +new file mode 100644 +index 0000000..1e3fc33 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/ipv6-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/isofs-modules b/debian/installer/m68k/modules/m68k-mac/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/jfs-modules b/debian/installer/m68k/modules/m68k-mac/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/kernel-image b/debian/installer/m68k/modules/m68k-mac/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/m68k/modules/m68k-mac/md-modules b/debian/installer/m68k/modules/m68k-mac/md-modules +new file mode 100644 +index 0000000..26115e1 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/md-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/nbd-modules b/debian/installer/m68k/modules/m68k-mac/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/nic-shared-modules b/debian/installer/m68k/modules/m68k-mac/nic-shared-modules +new file mode 100644 +index 0000000..3cf0df9 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/nic-shared-modules +@@ -0,0 +1,2 @@ ++#include "../m68k/nic-shared-modules" ++libphy +diff --git a/debian/installer/m68k/modules/m68k-mac/ppp-modules b/debian/installer/m68k/modules/m68k-mac/ppp-modules +new file mode 100644 +index 0000000..1f26aa1 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/ppp-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/reiserfs-modules b/debian/installer/m68k/modules/m68k-mac/reiserfs-modules +new file mode 100644 +index 0000000..fad554f +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/reiserfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/scsi-modules b/debian/installer/m68k/modules/m68k-mac/scsi-modules +new file mode 100644 +index 0000000..b9219d3 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/scsi-modules +@@ -0,0 +1 @@ ++#include "../m68k/scsi-modules" +diff --git a/debian/installer/m68k/modules/m68k-mac/squashfs-modules b/debian/installer/m68k/modules/m68k-mac/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/udf-modules b/debian/installer/m68k/modules/m68k-mac/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k-mac/zlib-modules b/debian/installer/m68k/modules/m68k-mac/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k-mac/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/btrfs-modules b/debian/installer/m68k/modules/m68k/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/cdrom-core-modules b/debian/installer/m68k/modules/m68k/cdrom-core-modules +new file mode 100644 +index 0000000..3ff69b4 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/cdrom-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/crypto-modules b/debian/installer/m68k/modules/m68k/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/fat-modules b/debian/installer/m68k/modules/m68k/fat-modules +new file mode 100644 +index 0000000..274584e +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/fat-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/fuse-modules b/debian/installer/m68k/modules/m68k/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/ipv6-modules b/debian/installer/m68k/modules/m68k/ipv6-modules +new file mode 100644 +index 0000000..1e3fc33 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/ipv6-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/isofs-modules b/debian/installer/m68k/modules/m68k/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/jfs-modules b/debian/installer/m68k/modules/m68k/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/kernel-image b/debian/installer/m68k/modules/m68k/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/m68k/modules/m68k/md-modules b/debian/installer/m68k/modules/m68k/md-modules +new file mode 100644 +index 0000000..26115e1 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/md-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/nbd-modules b/debian/installer/m68k/modules/m68k/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/nic-shared-modules b/debian/installer/m68k/modules/m68k/nic-shared-modules +new file mode 100644 +index 0000000..6822f97 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/nic-shared-modules +@@ -0,0 +1,11 @@ ++8390 ? ++a2065 ? ++apne ? ++ariadne ? ++ariadne2 ? ++dummy ++hydra ? ++zorro8390 ? ++ne ? ++atari_ethernec ? ++libphy +diff --git a/debian/installer/m68k/modules/m68k/ppp-modules b/debian/installer/m68k/modules/m68k/ppp-modules +new file mode 100644 +index 0000000..1f26aa1 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/ppp-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/reiserfs-modules b/debian/installer/m68k/modules/m68k/reiserfs-modules +new file mode 100644 +index 0000000..fad554f +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/reiserfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/scsi-modules b/debian/installer/m68k/modules/m68k/scsi-modules +new file mode 100644 +index 0000000..3a411a3 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/scsi-modules +@@ -0,0 +1 @@ ++sg +diff --git a/debian/installer/m68k/modules/m68k/squashfs-modules b/debian/installer/m68k/modules/m68k/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/udf-modules b/debian/installer/m68k/modules/m68k/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/modules/m68k/zlib-modules b/debian/installer/m68k/modules/m68k/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/m68k/modules/m68k/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/m68k/package-list b/debian/installer/m68k/package-list +new file mode 100644 +index 0000000..1cf8b72 +--- /dev/null ++++ b/debian/installer/m68k/package-list +@@ -0,0 +1,12 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: kernel-image ++Provides: loop-modules, ext2-modules, ext3-modules ++#Provides_mac: loop-modules, ext2-modules, ext3-modules, hfs-modules ++ ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/mips/kernel-versions b/debian/installer/mips/kernel-versions +new file mode 100644 +index 0000000..8267e14 +--- /dev/null ++++ b/debian/installer/mips/kernel-versions +@@ -0,0 +1,5 @@ ++# arch version flavour installedname suffix build-depends ++mips - sb1-bcm91250a - y - ++mips - r4k-ip22 - y - ++mips - r5k-ip32 - y - ++mips - 4kc-malta - y - +diff --git a/debian/installer/mips/modules/mips-4kc-malta/btrfs-modules b/debian/installer/mips/modules/mips-4kc-malta/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-4kc-malta/cdrom-core-modules b/debian/installer/mips/modules/mips-4kc-malta/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/crypto-dm-modules b/debian/installer/mips/modules/mips-4kc-malta/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-4kc-malta/crypto-modules b/debian/installer/mips/modules/mips-4kc-malta/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-4kc-malta/fat-modules b/debian/installer/mips/modules/mips-4kc-malta/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/fuse-modules b/debian/installer/mips/modules/mips-4kc-malta/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-4kc-malta/input-modules b/debian/installer/mips/modules/mips-4kc-malta/input-modules +new file mode 100644 +index 0000000..5ecb595 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/input-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-4kc-malta/ipv6-modules b/debian/installer/mips/modules/mips-4kc-malta/ipv6-modules +new file mode 100644 +index 0000000..cadae6f +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/ipv6-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/isofs-modules b/debian/installer/mips/modules/mips-4kc-malta/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-4kc-malta/jfs-modules b/debian/installer/mips/modules/mips-4kc-malta/jfs-modules +new file mode 100644 +index 0000000..925a43a +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/jfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/kernel-image b/debian/installer/mips/modules/mips-4kc-malta/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/mips/modules/mips-4kc-malta/loop-modules b/debian/installer/mips/modules/mips-4kc-malta/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/md-modules b/debian/installer/mips/modules/mips-4kc-malta/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/multipath-modules b/debian/installer/mips/modules/mips-4kc-malta/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-4kc-malta/nbd-modules b/debian/installer/mips/modules/mips-4kc-malta/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-4kc-malta/ppp-modules b/debian/installer/mips/modules/mips-4kc-malta/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/reiserfs-modules b/debian/installer/mips/modules/mips-4kc-malta/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/sata-modules b/debian/installer/mips/modules/mips-4kc-malta/sata-modules +new file mode 100644 +index 0000000..071cb86 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/sata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/squashfs-modules b/debian/installer/mips/modules/mips-4kc-malta/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-4kc-malta/udf-modules b/debian/installer/mips/modules/mips-4kc-malta/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-4kc-malta/usb-modules b/debian/installer/mips/modules/mips-4kc-malta/usb-modules +new file mode 100644 +index 0000000..2a947a6 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/usb-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/usb-storage b/debian/installer/mips/modules/mips-4kc-malta/usb-storage +new file mode 100644 +index 0000000..2a947a6 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/usb-storage +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/usb-storage-modules b/debian/installer/mips/modules/mips-4kc-malta/usb-storage-modules +new file mode 100644 +index 0000000..272d95e +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/virtio-modules b/debian/installer/mips/modules/mips-4kc-malta/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-4kc-malta/xfs-modules b/debian/installer/mips/modules/mips-4kc-malta/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-4kc-malta/zlib-modules b/debian/installer/mips/modules/mips-4kc-malta/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-4kc-malta/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/btrfs-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/cdrom-core-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/crypto-dm-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/crypto-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/fat-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/fb-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/fb-modules +new file mode 100644 +index 0000000..8c86def +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/fb-modules +@@ -0,0 +1,24 @@ ++aty128fb ++atyfb ++radeonfb ++cfbcopyarea ++cfbfillrect ++cfbimgblt ++cyber2000fb ++kyrofb ++macmodes ++g450_pll ++matroxfb_DAC1064 ++matroxfb_Ti3026 ++matroxfb_accel ++matroxfb_base ++matroxfb_crtc2 ++matroxfb_g450 ++matroxfb_misc ++neofb ++pm2fb ++savagefb ++sisfb ++sstfb ++tdfxfb ++tridentfb +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/fuse-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/input-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/input-modules +new file mode 100644 +index 0000000..5ecb595 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/input-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/ipv6-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/ipv6-modules +new file mode 100644 +index 0000000..cadae6f +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/ipv6-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/isofs-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/jfs-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/jfs-modules +new file mode 100644 +index 0000000..925a43a +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/jfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/kernel-image b/debian/installer/mips/modules/mips-sb1-bcm91250a/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/loop-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/md-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/multipath-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/nbd-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/nic-shared-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/nic-shared-modules +new file mode 100644 +index 0000000..d4cf5db +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/nic-shared-modules +@@ -0,0 +1 @@ ++mii +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/ppp-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/reiserfs-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/rtc-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/rtc-modules +new file mode 100644 +index 0000000..e20e792 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/rtc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/sata-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/sata-modules +new file mode 100644 +index 0000000..071cb86 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/sata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/scsi-common-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/scsi-common-modules +new file mode 100644 +index 0000000..1f1985a +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/scsi-common-modules +@@ -0,0 +1,5 @@ ++aic79xx ++BusLogic ? ++sym53c8xx ++sym53c8xx_2 ? ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/scsi-core-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/scsi-core-modules +new file mode 100644 +index 0000000..1fde8ee +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/scsi-core-modules +@@ -0,0 +1 @@ ++scsi_dh +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/scsi-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/scsi-modules +new file mode 100644 +index 0000000..c49d250 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/scsi-modules +@@ -0,0 +1,15 @@ ++3w-9xxx ++3w-xxxx ++a100u2w ++aacraid ++atp870u ? ++ch ++dc395x ++fdomain ++iscsi_tcp ++lpfc ++qla1280 ++qla2xxx ++qlogicfc ? ++sg ++tmscsim +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/squashfs-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/udf-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/usb-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/usb-modules +new file mode 100644 +index 0000000..2a947a6 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/usb-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/usb-storage b/debian/installer/mips/modules/mips-sb1-bcm91250a/usb-storage +new file mode 100644 +index 0000000..2a947a6 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/usb-storage +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/usb-storage-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/usb-storage-modules +new file mode 100644 +index 0000000..272d95e +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/xfs-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips-sb1-bcm91250a/zlib-modules b/debian/installer/mips/modules/mips-sb1-bcm91250a/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/mips/modules/mips-sb1-bcm91250a/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips/btrfs-modules b/debian/installer/mips/modules/mips/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/mips/modules/mips/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips/crypto-dm-modules b/debian/installer/mips/modules/mips/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/mips/modules/mips/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips/crypto-modules b/debian/installer/mips/modules/mips/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/mips/modules/mips/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips/fuse-modules b/debian/installer/mips/modules/mips/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/mips/modules/mips/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips/ipv6-modules b/debian/installer/mips/modules/mips/ipv6-modules +new file mode 100644 +index 0000000..cadae6f +--- /dev/null ++++ b/debian/installer/mips/modules/mips/ipv6-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips/isofs-modules b/debian/installer/mips/modules/mips/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/mips/modules/mips/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips/jfs-modules b/debian/installer/mips/modules/mips/jfs-modules +new file mode 100644 +index 0000000..925a43a +--- /dev/null ++++ b/debian/installer/mips/modules/mips/jfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips/kernel-image b/debian/installer/mips/modules/mips/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/mips/modules/mips/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/mips/modules/mips/loop-modules b/debian/installer/mips/modules/mips/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/mips/modules/mips/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips/md-modules b/debian/installer/mips/modules/mips/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/mips/modules/mips/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips/multipath-modules b/debian/installer/mips/modules/mips/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/mips/modules/mips/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips/nbd-modules b/debian/installer/mips/modules/mips/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/mips/modules/mips/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips/nic-shared-modules b/debian/installer/mips/modules/mips/nic-shared-modules +new file mode 100644 +index 0000000..4071438 +--- /dev/null ++++ b/debian/installer/mips/modules/mips/nic-shared-modules +@@ -0,0 +1,2 @@ ++mii ++libphy +diff --git a/debian/installer/mips/modules/mips/reiserfs-modules b/debian/installer/mips/modules/mips/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/mips/modules/mips/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips/squashfs-modules b/debian/installer/mips/modules/mips/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/mips/modules/mips/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips/udf-modules b/debian/installer/mips/modules/mips/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/mips/modules/mips/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/modules/mips/xfs-modules b/debian/installer/mips/modules/mips/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/mips/modules/mips/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mips/modules/mips/zlib-modules b/debian/installer/mips/modules/mips/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/mips/modules/mips/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mips/package-list b/debian/installer/mips/package-list +new file mode 100644 +index 0000000..873fe22 +--- /dev/null ++++ b/debian/installer/mips/package-list +@@ -0,0 +1,12 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: kernel-image ++Provides: ext2-modules, ext3-modules, ext4-modules, rtc-modules ++Provides_4kc-malta: ata-modules, ext2-modules, ext3-modules, ext4-modules, rtc-modules ++Provides_sb1-bcm91250a: ata-modules, ext2-modules, ext3-modules, ext4-modules, rtc-modules ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/mipsel/kernel-versions b/debian/installer/mipsel/kernel-versions +new file mode 100644 +index 0000000..2a1e485 +--- /dev/null ++++ b/debian/installer/mipsel/kernel-versions +@@ -0,0 +1,5 @@ ++# arch version flavour installedname suffix build-depends ++mipsel - sb1-bcm91250a - y - ++mipsel - r5k-cobalt - y - ++mipsel - 4kc-malta - y - ++mipsel - loongson-2f - y - +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/btrfs-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/cdrom-core-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/crypto-dm-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/crypto-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/fat-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/fuse-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/input-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/input-modules +new file mode 100644 +index 0000000..5ecb595 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/input-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/ipv6-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/ipv6-modules +new file mode 100644 +index 0000000..cadae6f +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/ipv6-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/isofs-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/jfs-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/jfs-modules +new file mode 100644 +index 0000000..925a43a +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/jfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/kernel-image b/debian/installer/mipsel/modules/mipsel-4kc-malta/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/loop-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/md-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/multipath-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/nbd-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/ppp-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/reiserfs-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/sata-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/sata-modules +new file mode 100644 +index 0000000..071cb86 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/sata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/squashfs-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/udf-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/usb-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/usb-modules +new file mode 100644 +index 0000000..2a947a6 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/usb-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/usb-storage b/debian/installer/mipsel/modules/mipsel-4kc-malta/usb-storage +new file mode 100644 +index 0000000..2a947a6 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/usb-storage +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/usb-storage-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/usb-storage-modules +new file mode 100644 +index 0000000..272d95e +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/virtio-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/xfs-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-4kc-malta/zlib-modules b/debian/installer/mipsel/modules/mipsel-4kc-malta/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-4kc-malta/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/btrfs-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/cdrom-core-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/cdrom-core-modules +new file mode 100644 +index 0000000..3ff69b4 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/cdrom-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/crypto-dm-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/crypto-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/fat-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/fat-modules +new file mode 100644 +index 0000000..274584e +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/fat-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/fuse-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/input-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/input-modules +new file mode 100644 +index 0000000..5ecb595 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/input-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/ipv6-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/ipv6-modules +new file mode 100644 +index 0000000..1e3fc33 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/ipv6-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/isofs-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/jfs-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/kernel-image b/debian/installer/mipsel/modules/mipsel-loongson-2f/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/loop-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/loop-modules +new file mode 100644 +index 0000000..c1c948f +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/loop-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/md-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/md-modules +new file mode 100644 +index 0000000..26115e1 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/md-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/multipath-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/nbd-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/nic-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/nic-modules +new file mode 100644 +index 0000000..361c75a +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/nic-modules +@@ -0,0 +1,2 @@ ++8139too ++r8169 +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/nic-shared-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/nic-shared-modules +new file mode 100644 +index 0000000..d4cf5db +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/nic-shared-modules +@@ -0,0 +1 @@ ++mii +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/nic-usb-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/nic-usb-modules +new file mode 100644 +index 0000000..c479669 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/nic-usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/ppp-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/ppp-modules +new file mode 100644 +index 0000000..1f26aa1 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/ppp-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/reiserfs-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/reiserfs-modules +new file mode 100644 +index 0000000..fad554f +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/reiserfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/sata-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/sata-modules +new file mode 100644 +index 0000000..01318c2 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/sata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/squashfs-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/udf-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/usb-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/usb-storage-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/usb-storage-modules +new file mode 100644 +index 0000000..8c5e81b +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/usb-storage-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/virtio-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/xfs-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/xfs-modules +new file mode 100644 +index 0000000..98374e2 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/xfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-loongson-2f/zlib-modules b/debian/installer/mipsel/modules/mipsel-loongson-2f/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-loongson-2f/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/btrfs-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/crypto-dm-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/crypto-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/fat-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/fuse-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/ipv6-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/ipv6-modules +new file mode 100644 +index 0000000..cadae6f +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/ipv6-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/jfs-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/jfs-modules +new file mode 100644 +index 0000000..925a43a +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/jfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/kernel-image b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/loop-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/md-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/multipath-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/nbd-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/nfs-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/nfs-modules +new file mode 100644 +index 0000000..c0f1fe4 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/nfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/nic-shared-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/nic-shared-modules +new file mode 100644 +index 0000000..4071438 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/nic-shared-modules +@@ -0,0 +1,2 @@ ++mii ++libphy +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/ppp-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/reiserfs-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/squashfs-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/xfs-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-r5k-cobalt/zlib-modules b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-r5k-cobalt/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/btrfs-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/cdrom-core-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/crypto-dm-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/crypto-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/fat-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/fb-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/fb-modules +new file mode 100644 +index 0000000..8c86def +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/fb-modules +@@ -0,0 +1,24 @@ ++aty128fb ++atyfb ++radeonfb ++cfbcopyarea ++cfbfillrect ++cfbimgblt ++cyber2000fb ++kyrofb ++macmodes ++g450_pll ++matroxfb_DAC1064 ++matroxfb_Ti3026 ++matroxfb_accel ++matroxfb_base ++matroxfb_crtc2 ++matroxfb_g450 ++matroxfb_misc ++neofb ++pm2fb ++savagefb ++sisfb ++sstfb ++tdfxfb ++tridentfb +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/fuse-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/input-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/input-modules +new file mode 100644 +index 0000000..5ecb595 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/input-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/ipv6-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/ipv6-modules +new file mode 100644 +index 0000000..cadae6f +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/ipv6-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/isofs-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/jfs-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/jfs-modules +new file mode 100644 +index 0000000..925a43a +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/jfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/kernel-image b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/loop-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/md-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/multipath-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/nbd-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/nic-shared-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/nic-shared-modules +new file mode 100644 +index 0000000..d4cf5db +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/nic-shared-modules +@@ -0,0 +1 @@ ++mii +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/ppp-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/reiserfs-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/rtc-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/rtc-modules +new file mode 100644 +index 0000000..e20e792 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/rtc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/sata-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/sata-modules +new file mode 100644 +index 0000000..071cb86 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/sata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/scsi-common-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/scsi-common-modules +new file mode 100644 +index 0000000..1f1985a +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/scsi-common-modules +@@ -0,0 +1,5 @@ ++aic79xx ++BusLogic ? ++sym53c8xx ++sym53c8xx_2 ? ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/scsi-core-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/scsi-core-modules +new file mode 100644 +index 0000000..1fde8ee +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/scsi-core-modules +@@ -0,0 +1 @@ ++scsi_dh +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/scsi-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/scsi-modules +new file mode 100644 +index 0000000..c49d250 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/scsi-modules +@@ -0,0 +1,15 @@ ++3w-9xxx ++3w-xxxx ++a100u2w ++aacraid ++atp870u ? ++ch ++dc395x ++fdomain ++iscsi_tcp ++lpfc ++qla1280 ++qla2xxx ++qlogicfc ? ++sg ++tmscsim +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/squashfs-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/udf-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/usb-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/usb-modules +new file mode 100644 +index 0000000..2a947a6 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/usb-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/usb-storage b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/usb-storage +new file mode 100644 +index 0000000..2a947a6 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/usb-storage +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/usb-storage-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/usb-storage-modules +new file mode 100644 +index 0000000..272d95e +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/xfs-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/zlib-modules b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/mipsel/modules/mipsel-sb1-bcm91250a/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/mipsel/package-list b/debian/installer/mipsel/package-list +new file mode 100644 +index 0000000..76c81fd +--- /dev/null ++++ b/debian/installer/mipsel/package-list +@@ -0,0 +1,13 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: kernel-image ++Provides_sb1-bcm91250a: ata-modules, ext2-modules, ext3-modules, ext4-modules, rtc-modules ++Provides_r5k-cobalt: ata-modules, ext2-modules, ext3-modules, ext4-modules, rtc-modules ++Provides_4kc-malta: ata-modules, ext2-modules, ext3-modules, ext4-modules, rtc-modules ++Provides_loongson-2f: ata-modules, ext2-modules, ext3-modules, ext4-modules, rtc-modules ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/modules/acpi-modules b/debian/installer/modules/acpi-modules +new file mode 100644 +index 0000000..d4723a1 +--- /dev/null ++++ b/debian/installer/modules/acpi-modules +@@ -0,0 +1,2 @@ ++fan ++thermal +diff --git a/debian/installer/modules/affs-modules b/debian/installer/modules/affs-modules +new file mode 100644 +index 0000000..ac28259 +--- /dev/null ++++ b/debian/installer/modules/affs-modules +@@ -0,0 +1 @@ ++affs +diff --git a/debian/installer/modules/ata-modules b/debian/installer/modules/ata-modules +new file mode 100644 +index 0000000..6ca33ce +--- /dev/null ++++ b/debian/installer/modules/ata-modules +@@ -0,0 +1,2 @@ ++libata ++ata_generic +diff --git a/debian/installer/modules/btrfs-modules b/debian/installer/modules/btrfs-modules +new file mode 100644 +index 0000000..00531f6 +--- /dev/null ++++ b/debian/installer/modules/btrfs-modules +@@ -0,0 +1 @@ ++btrfs +diff --git a/debian/installer/modules/cdrom-core-modules b/debian/installer/modules/cdrom-core-modules +new file mode 100644 +index 0000000..07d1178 +--- /dev/null ++++ b/debian/installer/modules/cdrom-core-modules +@@ -0,0 +1,3 @@ ++cdrom ? ++sr_mod ? ++ide-cd_mod ? +diff --git a/debian/installer/modules/core-modules b/debian/installer/modules/core-modules +new file mode 100644 +index 0000000..d06c2be +--- /dev/null ++++ b/debian/installer/modules/core-modules +@@ -0,0 +1,2 @@ ++bitrev ? ++led-class ? +diff --git a/debian/installer/modules/crc-modules b/debian/installer/modules/crc-modules +new file mode 100644 +index 0000000..8f86016 +--- /dev/null ++++ b/debian/installer/modules/crc-modules +@@ -0,0 +1,4 @@ ++crc-ccitt ++libcrc32c ++crc32c ++crc-itu-t +diff --git a/debian/installer/modules/crypto-dm-modules b/debian/installer/modules/crypto-dm-modules +new file mode 100644 +index 0000000..189131f +--- /dev/null ++++ b/debian/installer/modules/crypto-dm-modules +@@ -0,0 +1 @@ ++dm-crypt +diff --git a/debian/installer/modules/crypto-modules b/debian/installer/modules/crypto-modules +new file mode 100644 +index 0000000..7ffa664 +--- /dev/null ++++ b/debian/installer/modules/crypto-modules +@@ -0,0 +1,7 @@ ++aes_generic ++blowfish_generic ++twofish_generic ++serpent ++sha256_generic ++cbc ? ++xts +diff --git a/debian/installer/modules/efi-modules b/debian/installer/modules/efi-modules +new file mode 100644 +index 0000000..9173272 +--- /dev/null ++++ b/debian/installer/modules/efi-modules +@@ -0,0 +1 @@ ++efivars +diff --git a/debian/installer/modules/event-modules b/debian/installer/modules/event-modules +new file mode 100644 +index 0000000..97a5e58 +--- /dev/null ++++ b/debian/installer/modules/event-modules +@@ -0,0 +1 @@ ++evdev +diff --git a/debian/installer/modules/ext2-modules b/debian/installer/modules/ext2-modules +new file mode 100644 +index 0000000..43d7af3 +--- /dev/null ++++ b/debian/installer/modules/ext2-modules +@@ -0,0 +1 @@ ++ext2 +diff --git a/debian/installer/modules/ext3-modules b/debian/installer/modules/ext3-modules +new file mode 100644 +index 0000000..1c28572 +--- /dev/null ++++ b/debian/installer/modules/ext3-modules +@@ -0,0 +1,2 @@ ++ext3 ++jbd +diff --git a/debian/installer/modules/ext4-modules b/debian/installer/modules/ext4-modules +new file mode 100644 +index 0000000..6100342 +--- /dev/null ++++ b/debian/installer/modules/ext4-modules +@@ -0,0 +1,2 @@ ++ext4 ++jbd2 +diff --git a/debian/installer/modules/fat-modules b/debian/installer/modules/fat-modules +new file mode 100644 +index 0000000..37e6d05 +--- /dev/null ++++ b/debian/installer/modules/fat-modules +@@ -0,0 +1,6 @@ ++fat ? ++vfat ++# the default codepage for fat (as of 2.6.8) ++nls_cp437 ? ++# the default i/o character set for fat (as of 2.6.25) ++nls_utf8 ? +diff --git a/debian/installer/modules/firewire-core-modules b/debian/installer/modules/firewire-core-modules +new file mode 100644 +index 0000000..ebfcb22 +--- /dev/null ++++ b/debian/installer/modules/firewire-core-modules +@@ -0,0 +1,5 @@ ++ieee1394 ? ++ohci1394 ? ++sbp2 ? ++firewire-ohci ? ++firewire-sbp2 ? +diff --git a/debian/installer/modules/floppy-modules b/debian/installer/modules/floppy-modules +new file mode 100644 +index 0000000..8b54ec8 +--- /dev/null ++++ b/debian/installer/modules/floppy-modules +@@ -0,0 +1 @@ ++floppy +diff --git a/debian/installer/modules/fuse-modules b/debian/installer/modules/fuse-modules +new file mode 100644 +index 0000000..a517c48 +--- /dev/null ++++ b/debian/installer/modules/fuse-modules +@@ -0,0 +1 @@ ++fuse +diff --git a/debian/installer/modules/hfs-modules b/debian/installer/modules/hfs-modules +new file mode 100644 +index 0000000..4a31155 +--- /dev/null ++++ b/debian/installer/modules/hfs-modules +@@ -0,0 +1,2 @@ ++hfs ++hfsplus +diff --git a/debian/installer/modules/hyperv-modules b/debian/installer/modules/hyperv-modules +new file mode 100644 +index 0000000..f40837f +--- /dev/null ++++ b/debian/installer/modules/hyperv-modules +@@ -0,0 +1,6 @@ ++# All Hyper-V paravirtual drivers ++hid-hyperv ++hv_netvsc ++hv_storvsc ++hv_utils ++hv_vmbus +diff --git a/debian/installer/modules/i2c-modules b/debian/installer/modules/i2c-modules +new file mode 100644 +index 0000000..8c51c24 +--- /dev/null ++++ b/debian/installer/modules/i2c-modules +@@ -0,0 +1 @@ ++i2c-core +diff --git a/debian/installer/modules/ide-core-modules b/debian/installer/modules/ide-core-modules +new file mode 100644 +index 0000000..96284d1 +--- /dev/null ++++ b/debian/installer/modules/ide-core-modules +@@ -0,0 +1 @@ ++ide-core +diff --git a/debian/installer/modules/ide-modules b/debian/installer/modules/ide-modules +new file mode 100644 +index 0000000..637d42f +--- /dev/null ++++ b/debian/installer/modules/ide-modules +@@ -0,0 +1,3 @@ ++ide-generic ? ++ide-gd_mod ? ++trm290 ? +diff --git a/debian/installer/modules/input-modules b/debian/installer/modules/input-modules +new file mode 100644 +index 0000000..349695b +--- /dev/null ++++ b/debian/installer/modules/input-modules +@@ -0,0 +1,25 @@ ++hid ++usbhid ++hid-a4tech ? ++hid-apple ? ++hid-belkin ? ++hid-cherry ? ++hid-cypress ? ++hid-ezkey ? ++hid-kensington ? ++hid-keytouch ? ++hid-kye ? ++hid-logitech ? ++hid-logitech-dj ++hid-microsoft ? ++hid-monterey ? ++hid-multitouch ? ++hid-ortek ? ++hid-primax ? ++hid-quanta ? ++hid-samsung ? ++hid-speedlink ? ++hid-sunplus ? ++hid-topseed ? ++synaptics_usb ? ++wistron_btns ? +diff --git a/debian/installer/modules/ipv6-modules b/debian/installer/modules/ipv6-modules +new file mode 100644 +index 0000000..13ac34b +--- /dev/null ++++ b/debian/installer/modules/ipv6-modules +@@ -0,0 +1 @@ ++ipv6 +diff --git a/debian/installer/modules/isofs-modules b/debian/installer/modules/isofs-modules +new file mode 100644 +index 0000000..0f41779 +--- /dev/null ++++ b/debian/installer/modules/isofs-modules +@@ -0,0 +1 @@ ++isofs +diff --git a/debian/installer/modules/jffs2-modules b/debian/installer/modules/jffs2-modules +new file mode 100644 +index 0000000..19f4e10 +--- /dev/null ++++ b/debian/installer/modules/jffs2-modules +@@ -0,0 +1 @@ ++jffs2 +diff --git a/debian/installer/modules/jfs-modules b/debian/installer/modules/jfs-modules +new file mode 100644 +index 0000000..aa604c4 +--- /dev/null ++++ b/debian/installer/modules/jfs-modules +@@ -0,0 +1 @@ ++jfs +diff --git a/debian/installer/modules/loop-modules b/debian/installer/modules/loop-modules +new file mode 100644 +index 0000000..1ef2ddf +--- /dev/null ++++ b/debian/installer/modules/loop-modules +@@ -0,0 +1 @@ ++loop +diff --git a/debian/installer/modules/lzo-modules b/debian/installer/modules/lzo-modules +new file mode 100644 +index 0000000..d1a1583 +--- /dev/null ++++ b/debian/installer/modules/lzo-modules +@@ -0,0 +1 @@ ++lzo_compress +diff --git a/debian/installer/modules/md-modules b/debian/installer/modules/md-modules +new file mode 100644 +index 0000000..83f3925 +--- /dev/null ++++ b/debian/installer/modules/md-modules +@@ -0,0 +1,11 @@ ++linear ++md-mod ++dm-mod ++multipath ++raid0 ++raid1 ++raid456 ++raid10 ++xor ++dm-mirror ++dm-snapshot +diff --git a/debian/installer/modules/minix-modules b/debian/installer/modules/minix-modules +new file mode 100644 +index 0000000..aa6ca5d +--- /dev/null ++++ b/debian/installer/modules/minix-modules +@@ -0,0 +1 @@ ++minix +diff --git a/debian/installer/modules/mmc-core-modules b/debian/installer/modules/mmc-core-modules +new file mode 100644 +index 0000000..67128ea +--- /dev/null ++++ b/debian/installer/modules/mmc-core-modules +@@ -0,0 +1 @@ ++mmc_core +diff --git a/debian/installer/modules/mmc-modules b/debian/installer/modules/mmc-modules +new file mode 100644 +index 0000000..636ceda +--- /dev/null ++++ b/debian/installer/modules/mmc-modules +@@ -0,0 +1,5 @@ ++mmc_block ++sdhci ++sdhci-pci ? ++ricoh_mmc ? ++tifm_sd ? +diff --git a/debian/installer/modules/mouse-modules b/debian/installer/modules/mouse-modules +new file mode 100644 +index 0000000..8d65ba4 +--- /dev/null ++++ b/debian/installer/modules/mouse-modules +@@ -0,0 +1 @@ ++psmouse +diff --git a/debian/installer/modules/mtd-modules b/debian/installer/modules/mtd-modules +new file mode 100644 +index 0000000..637116f +--- /dev/null ++++ b/debian/installer/modules/mtd-modules +@@ -0,0 +1,2 @@ ++mtd ++mtdblock +diff --git a/debian/installer/modules/multipath-modules b/debian/installer/modules/multipath-modules +new file mode 100644 +index 0000000..5fa964c +--- /dev/null ++++ b/debian/installer/modules/multipath-modules +@@ -0,0 +1,2 @@ ++dm-multipath ++dm-round-robin +diff --git a/debian/installer/modules/nbd-modules b/debian/installer/modules/nbd-modules +new file mode 100644 +index 0000000..cb3ca60 +--- /dev/null ++++ b/debian/installer/modules/nbd-modules +@@ -0,0 +1 @@ ++nbd +diff --git a/debian/installer/modules/nfs-modules b/debian/installer/modules/nfs-modules +new file mode 100644 +index 0000000..a5bfd2c +--- /dev/null ++++ b/debian/installer/modules/nfs-modules +@@ -0,0 +1,3 @@ ++nfs ++lockd ++sunrpc +diff --git a/debian/installer/modules/nic-extra-modules b/debian/installer/modules/nic-extra-modules +new file mode 100644 +index 0000000..0364476 +--- /dev/null ++++ b/debian/installer/modules/nic-extra-modules +@@ -0,0 +1,142 @@ ++82596 ? ++abyss ? ++ac3200 ? ++alx ? ++amd8111e ? ++at1700 ? ++cs89x0 ? ++depca ? ++dl2k ++dmfe ++e2100 ? ++eepro ? ++enc28j60 ++et131x ? ++forcedeth ? ++hamachi ++hp-plus ? ++hp100 ? ++ibmtr ? ++igb ++ipg ? ++lance ? ++lanstreamer ? ++lne390 ? ++lp486e ? ++ne ? ++ne2 ? ++ni5010 ? ++ni52 ? ++ni65 ? ++niu ? ++r8169 ++rrunner ? ++skfp ++sky2 ++skge ++smc-ultra ? ++tlan ? ++tmspci ? ++typhoon ++yellowfin ++3c501 ? ++3c503 ? ++3c505 ? ++3c507 ? ++3c509 ? ++3c515 ? ++3c523 ? ++3c527 ? ++3c359 ? ++8139cp ++eexpress ? ++epic100 ++es3210 ? ++eth16i ? ++ewrk3 ? ++fealnx ++ns83820 ++smc-ultra32 ? ++smc9194 ? ++starfire ++sundance ++olympic ++arlan ? ++de2104x ? ++de600 ? ++de620 ? ++defxx ? ++e1000 ? ++e1000e ? ++hp ? ++ixgb ? ++ixgbe ? ++ne3210 ? ++pcnet32 ? ++s2io ? ++sis190 ? ++sis900 ? ++via-rhine ? ++via-velocity ? ++wd ? ++znet ? ++bnx2 ? ++bnx2x ? ++cassini ? ++cxgb ? ++sis190 ? ++skge ? ++uli526x ? ++sky2 ? ++acenic ? ++netxen_nic ? ++qla3xxx ? ++cxgb3 ? ++atl1 ? ++atl1c ? ++atl1e ? ++atl2 ? ++r6040 ++sfc ++jme ? ++enic ? ++be2net ? ++myri10ge ? ++# inet_lro is shared but now only used by myri10ge (and the iw_nes IB driver) ++inet_lro ? ++sc92031 ? ++qlcnic ? ++bna ? ++cxgb4 ? ++cxgb4vf ? ++igbvf ? ++ixgbevf ? ++mlx4_en ? ++vxge ? ++pch_gbe ? ++qlge ? ++smsc9420 ? ++tehuti ? ++ ++# phy drivers ++# broadcom is in nic-modules ++cicada ? ++davicom ? ++et1011c ? ++icplus ? ++lxt ? ++marvell ? ++mdio-bitbang ? ++micrel ? ++national ? ++qsemi ? ++realtek ? ++smsc ? ++ste10Xp ? ++vitesse ? ++ ++# VMWare ++vmxnet3 ? ++ ++# VLAN ++8021q +diff --git a/debian/installer/modules/nic-modules b/debian/installer/modules/nic-modules +new file mode 100644 +index 0000000..6fc0863 +--- /dev/null ++++ b/debian/installer/modules/nic-modules +@@ -0,0 +1,14 @@ ++# Some historically common net drivers ++3c59x ++8139too ++e100 ++natsemi ++ne2k-pci ++tg3 ? ++tulip ++winbond-840 ++eth1394 ? ++xen-netfront ? ++ ++# PHY driver, may be needed by tg3 ++broadcom ? +diff --git a/debian/installer/modules/nic-pcmcia-modules b/debian/installer/modules/nic-pcmcia-modules +new file mode 100644 +index 0000000..414d132 +--- /dev/null ++++ b/debian/installer/modules/nic-pcmcia-modules +@@ -0,0 +1,20 @@ ++# Common pcmcia nic modules. ++3c574_cs ++3c589_cs ++airo_cs ? ++axnet_cs ++b44 ? ++com20020_cs ? ++fmvj18x_cs ? ++ibmtr_cs ? ++netwave_cs ? ++nmclan_cs ++orinoco_cs ++pcnet_cs ++ray_cs ++smc91c92_cs ++wavelan_cs ? ++xirc2ps_cs ++xircom_cb ++atmel_cs ? ++wl3501_cs ? +diff --git a/debian/installer/modules/nic-usb-modules b/debian/installer/modules/nic-usb-modules +new file mode 100644 +index 0000000..11d29a6 +--- /dev/null ++++ b/debian/installer/modules/nic-usb-modules +@@ -0,0 +1,18 @@ ++catc ++kaweth ++pegasus ++rtl8150 ++usbnet ++# New in 2.6 ++asix ? ++zd1201 ? ++cdc_ether ? ++mcs7830 ? ++dm9601 ? ++zd1211rw ? ++rndis_wlan ? ++rtl8187 ? ++g_ether ? ++int51x1 ? ++smsc75xx ? ++smsc95xx ? +diff --git a/debian/installer/modules/nic-wireless-modules b/debian/installer/modules/nic-wireless-modules +new file mode 100644 +index 0000000..83f06cf +--- /dev/null ++++ b/debian/installer/modules/nic-wireless-modules +@@ -0,0 +1,57 @@ ++ieee80211_crypt_wep ? ++atmel_pci ? ++hermes ? ++ipw2100 ? ++ipw2200 ? ++orinoco ? ++hostap_pci ? ++orinoco_plx ? ++orinoco_nortel ? ++orinoco_tmd ? ++prism54 ? ++p54pci ? ++p54usb ++wavelan ? ++usb8xxx ? ++ath5k ? ++ath9k ? ++ath9k_htc ? ++carl9170 ? ++iwlwifi ? ++iwl3945 ? ++iwl4965 ? ++b43 ? ++brcmsmac ? ++rt2400pci ? ++rt2500pci ? ++rt2500usb ? ++rt2800pci ? ++rt2800usb ? ++rt61pci ? ++rt73usb ? ++adm8211 ? ++at76c50x-usb ? ++b43legacy ? ++libertas_tf_usb ? ++mwifiex_pcie ? ++mwl8k ? ++orinoco_usb ? ++rtl8180 ? ++rtl8192ce ? ++rtl8192cu ? ++rtl8192de ? ++rtl8192se ? ++r8187se ? ++r8192e_pci ? ++r8712u ? ++vt6656_stage ? ++prism2_usb ? ++ ++# lib80211 encryption algorithms ++lib80211_crypt_wep ? ++lib80211_crypt_ccmp ? ++lib80211_crypt_tkip ? ++ ++# Crypto modules needed for ieee80211 WEP support ++ecb ? ++arc4 ? +diff --git a/debian/installer/modules/parport-modules b/debian/installer/modules/parport-modules +new file mode 100644 +index 0000000..2d9f698 +--- /dev/null ++++ b/debian/installer/modules/parport-modules +@@ -0,0 +1,2 @@ ++parport ++parport_pc +diff --git a/debian/installer/modules/pata-modules b/debian/installer/modules/pata-modules +new file mode 100644 +index 0000000..dd8450d +--- /dev/null ++++ b/debian/installer/modules/pata-modules +@@ -0,0 +1,40 @@ ++pata_ali ? ++pata_amd ? ++pata_artop ? ++pata_atiixp ? ++pata_cmd64x ? ++pata_cs5520 ? ++pata_cs5530 ? ++pata_cs5535 ? ++pata_cypress ? ++pata_efar ? ++pata_hpt366 ? ++pata_hpt37x ? ++pata_hpt3x2n ? ++pata_hpt3x3 ? ++pata_isapnp ? ++pata_it821x ? ++pata_jmicron ? ++pata_legacy ? ++pata_marvell ? ++pata_mpiix ? ++pata_netcell ? ++pata_ns87410 ? ++pata_oldpiix ? ++pata_opti ? ++pata_optidma ? ++pata_pdc2027x ? ++pata_pdc202xx_old ? ++pata_piccolo ? ++pata_qdi ? ++pata_radisys ? ++pata_rdc ? ++pata_rz1000 ? ++pata_sc1200 ? ++pata_serverworks ? ++pata_sil680 ? ++pata_sch ? ++pata_sl82c105 ? ++pata_triflex ? ++pata_via ? ++pata_winbond ? +diff --git a/debian/installer/modules/pcmcia-modules b/debian/installer/modules/pcmcia-modules +new file mode 100644 +index 0000000..ab5b4b2 +--- /dev/null ++++ b/debian/installer/modules/pcmcia-modules +@@ -0,0 +1,8 @@ ++pcmcia ++ ++i82092 ++i82365 ? ++pcmcia_core ++tcic ? ++yenta_socket ++pd6729 ? +diff --git a/debian/installer/modules/pcmcia-storage-modules b/debian/installer/modules/pcmcia-storage-modules +new file mode 100644 +index 0000000..b6b1721 +--- /dev/null ++++ b/debian/installer/modules/pcmcia-storage-modules +@@ -0,0 +1,2 @@ ++pata_ninja32 ? ++pata_pcmcia ? +diff --git a/debian/installer/modules/plip-modules b/debian/installer/modules/plip-modules +new file mode 100644 +index 0000000..bcb0ea8 +--- /dev/null ++++ b/debian/installer/modules/plip-modules +@@ -0,0 +1 @@ ++plip +diff --git a/debian/installer/modules/ppp-modules b/debian/installer/modules/ppp-modules +new file mode 100644 +index 0000000..0dd77f0 +--- /dev/null ++++ b/debian/installer/modules/ppp-modules +@@ -0,0 +1,5 @@ ++ppp_async ? ++ppp_deflate ++ppp_synctty ? ++pppoe ++pppox +diff --git a/debian/installer/modules/qnx4-modules b/debian/installer/modules/qnx4-modules +new file mode 100644 +index 0000000..05d4adc +--- /dev/null ++++ b/debian/installer/modules/qnx4-modules +@@ -0,0 +1 @@ ++qnx4 +diff --git a/debian/installer/modules/reiserfs-modules b/debian/installer/modules/reiserfs-modules +new file mode 100644 +index 0000000..5a01360 +--- /dev/null ++++ b/debian/installer/modules/reiserfs-modules +@@ -0,0 +1 @@ ++reiserfs +diff --git a/debian/installer/modules/rtc-modules b/debian/installer/modules/rtc-modules +new file mode 100644 +index 0000000..0a78e78 +--- /dev/null ++++ b/debian/installer/modules/rtc-modules +@@ -0,0 +1,2 @@ ++rtc ? ++rtc-cmos +diff --git a/debian/installer/modules/sata-modules b/debian/installer/modules/sata-modules +new file mode 100644 +index 0000000..d38206d +--- /dev/null ++++ b/debian/installer/modules/sata-modules +@@ -0,0 +1,19 @@ ++ata_piix ? ++sata_nv ? ++sata_promise ? ++sata_sil ? ++sata_sis ? ++# sata-sis depends on pata-sis; avoid a dependency ++pata_sis ? ++sata_sil24 ? ++sata_svw ? ++sata_sx4 ? ++sata_via ? ++sata_vsc ? ++sata_qstor ? ++sata_uli ? ++ahci ? ++sx8 ? ++sata_sx4 ? ++sata_mv ? ++pdc_adma ? +diff --git a/debian/installer/modules/scsi-common-modules b/debian/installer/modules/scsi-common-modules +new file mode 100644 +index 0000000..736afe11 +--- /dev/null ++++ b/debian/installer/modules/scsi-common-modules +@@ -0,0 +1,6 @@ ++# Some historically common SCSI drivers ++aic79xx ++aic7xxx ++BusLogic ? ++sym53c8xx ++sym53c8xx_2 ? +diff --git a/debian/installer/modules/scsi-core-modules b/debian/installer/modules/scsi-core-modules +new file mode 100644 +index 0000000..372fed5 +--- /dev/null ++++ b/debian/installer/modules/scsi-core-modules +@@ -0,0 +1,3 @@ ++scsi_dh ++scsi_mod ++sd_mod +diff --git a/debian/installer/modules/scsi-extra-modules b/debian/installer/modules/scsi-extra-modules +new file mode 100644 +index 0000000..6ab42bc +--- /dev/null ++++ b/debian/installer/modules/scsi-extra-modules +@@ -0,0 +1,44 @@ ++3w-xxxx ++DAC960 ++aacraid ++aha152x ? ++aic7xxx_old ++cciss ++cpqarray ? ++i2o_block ? ++dtc ? ++eata ? ++fdomain ? ++gdth ? ++hpsa ? ++ibmmca ? ++ips ++megaraid ? ++megaraid_mbox ? ++megaraid_mm ? ++megaraid_sas ? ++mptbase ++mptscsih ++mptspi ? ++mptsas ? ++mpt2sas ? ++mptfc ? ++mvsas ++3w-9xxx ? ++3w-sas ? ++lpfc ? ++osst ++st ++sym53c416 ? ++arcmsr ? ++hptiop ? ++qla4xxx ? ++qla2xxx ? ++pm8001 ? ++isci ? ++bnx2fc ? ++fnic ? ++pmcraid ? ++ ++# VMWare ++vmw_pvscsi ? +diff --git a/debian/installer/modules/scsi-modules b/debian/installer/modules/scsi-modules +new file mode 100644 +index 0000000..48361bc +--- /dev/null ++++ b/debian/installer/modules/scsi-modules +@@ -0,0 +1,30 @@ ++NCR53c406a ? ++advansys ? ++aha1542 ? ++aha1740 ? ++atp870u ? ++dmx3191d ++fd_mcs ? ++g_NCR5380 ? ++imm ++in2000 ? ++pas16 ? ++ppa ++qla1280 ? ++qlogicfas ? ++sg ++sim710 ? ++t128 ? ++tmscsim ++u14-34f ? ++ultrastor ? ++wd7000 ? ++initio ? ++ipr ? ++qlogicfas408 ? ++dc395x ? ++aic94xx ? ++stex ? ++xen-blkfront ? ++iscsi_tcp ? ++iscsi_ibft ? +diff --git a/debian/installer/modules/serial-modules b/debian/installer/modules/serial-modules +new file mode 100644 +index 0000000..d842d4b +--- /dev/null ++++ b/debian/installer/modules/serial-modules +@@ -0,0 +1,2 @@ ++serial_cs ++synclink_cs ? +diff --git a/debian/installer/modules/sound-modules b/debian/installer/modules/sound-modules +new file mode 100644 +index 0000000..d300530 +--- /dev/null ++++ b/debian/installer/modules/sound-modules +@@ -0,0 +1,150 @@ ++snd-aaci ? ++snd-ad1816a ? ++snd-ad1848 ? ++snd-ad1889 ? ++snd-aica ? ++snd-ak4113 ? ++snd-ak4114 ? ++snd-ak4117 ? ++snd-ak4xxx-adda ? ++snd-ali5451 ? ++snd-als100 ? ++snd-als300 ? ++snd-als4000 ? ++snd-aoa-codec-onyx ? ++snd-aoa-codec-tas ? ++snd-aoa-codec-toonie ? ++snd-aoa-fabric-layout ? ++snd-aoa-i2sbus ? ++snd-aoa ? ++snd-asihpi ? ++snd-at73c213 ? ++snd-atiixp ? ++snd-atmel-abdac ? ++snd-atmel-ac97c ? ++snd-au1x00 ? ++snd-au8810 ? ++snd-au8820 ? ++snd-au8830 ? ++snd-aw2 ? ++snd-azt1605 ? ++snd-azt2316 ? ++snd-azt2320 ? ++snd-azt3328 ? ++snd-bt87x ? ++snd-ca0106 ? ++snd-cmi8330 ? ++snd-cmipci ? ++snd-cs4231 ? ++snd-cs4236 ? ++snd-cs4281 ? ++snd-cs46xx ? ++snd-cs5530 ? ++snd-cs5535audio ? ++snd-cs8427 ? ++snd-ctxfi ? ++snd-darla20 ? ++snd-darla24 ? ++snd-echo3g ? ++snd-emu10k1 ? ++snd-emu10k1x ? ++snd-ens1370 ? ++snd-ens1371 ? ++snd-es1688 ? ++snd-es18xx ? ++snd-es1938 ? ++snd-es1968 ? ++snd-firewire-speakers ? ++snd-fm801 ? ++snd-gina20 ? ++snd-gina24 ? ++snd-gusclassic ? ++snd-gusextreme ? ++snd-gusmax ? ++snd-harmony ? ++snd-hda-codec-analog ? ++snd-hda-codec-ca0110 ? ++snd-hda-codec-ca0132 ? ++snd-hda-codec-cirrus ? ++snd-hda-codec-cmedia ? ++snd-hda-codec-conexant ? ++snd-hda-codec-hdmi ? ++snd-hda-codec-idt ? ++snd-hda-codec-realtek ? ++snd-hda-codec-si3054 ? ++snd-hda-codec-via ? ++snd-hda-codec ? ++snd-hda-intel ? ++snd-hdsp ? ++snd-hdspm ? ++snd-ice1712 ? ++snd-ice1724 ? ++snd-ice17xx-ak4xxx ? ++snd-indigo ? ++snd-indigodj ? ++snd-indigodjx ? ++snd-indigoio ? ++snd-indigoiox ? ++snd-intel8x0 ? ++snd-interwave ? ++snd-interwave-stb ? ++snd-interwave ? ++snd-isight ? ++snd-jazz16 ? ++snd-korg1212 ? ++snd-layla20 ? ++snd-layla24 ? ++snd-lola ? ++snd-lx6464es ? ++snd-maestro3 ? ++snd-mia ? ++snd-miro ? ++snd-mixart ? ++snd-ml403-ac97cr ? ++snd-mona ? ++snd-msnd-classic ? ++snd-msnd-pinnacle ? ++snd-nm256 ? ++snd-opl3sa2 ? ++snd-opti92x-ad1848 ? ++snd-opti92x-cs4231 ? ++snd-opti93x ? ++snd-oxygen ? ++snd-pcsp ? ++snd-pcxhr ? ++snd-pdaudiocf ? ++snd-powermac ? ++snd-pt2258 ? ++snd-pxa2xx-ac97 ? ++snd-pxa2xx-pcm ? ++snd-riptide ? ++snd-rme32 ? ++snd-rme96 ? ++snd-rme9652 ? ++snd-sb16 ? ++snd-sb8 ? ++snd-sbawe ? ++snd-sc6000 ? ++snd-sgi-hal2 ? ++snd-sgi-o2 ? ++snd-sh_dac_audio ? ++snd-sis7019 ? ++snd-sonicvibes ? ++snd-sscape ? ++snd-sun-amd7930 ? ++snd-sun-cs4231 ? ++snd-sun-dbri ? ++snd-trident ? ++snd-ua101 ? ++snd-usb-6fire ? ++snd-usb-audio ? ++snd-usb-caiaq ? ++snd-usb-us122l ? ++snd-usb-usx2y ? ++snd-via82xx ? ++snd-virtuoso ? ++snd-vx222 ? ++snd-vxpocket ? ++snd-wavefront ? ++snd-ymfpci ? ++snd_ps3 ? +diff --git a/debian/installer/modules/speakup-modules b/debian/installer/modules/speakup-modules +new file mode 100644 +index 0000000..59e3f9e +--- /dev/null ++++ b/debian/installer/modules/speakup-modules +@@ -0,0 +1,15 @@ ++speakup ++speakup_acntpc ++speakup_acntsa ++speakup_apollo ++speakup_audptr ++speakup_bns ++speakup_decext ++speakup_dectlk ++speakup_dtlk ++speakup_dummy ++speakup_keypc ++speakup_ltlk ++speakup_soft ++speakup_spkout ++speakup_txprt +diff --git a/debian/installer/modules/squashfs-modules b/debian/installer/modules/squashfs-modules +new file mode 100644 +index 0000000..7c1157f +--- /dev/null ++++ b/debian/installer/modules/squashfs-modules +@@ -0,0 +1 @@ ++squashfs +diff --git a/debian/installer/modules/udf-modules b/debian/installer/modules/udf-modules +new file mode 100644 +index 0000000..97c604f +--- /dev/null ++++ b/debian/installer/modules/udf-modules +@@ -0,0 +1 @@ ++udf +diff --git a/debian/installer/modules/ufs-modules b/debian/installer/modules/ufs-modules +new file mode 100644 +index 0000000..19173e9 +--- /dev/null ++++ b/debian/installer/modules/ufs-modules +@@ -0,0 +1 @@ ++ufs +diff --git a/debian/installer/modules/uinput-modules b/debian/installer/modules/uinput-modules +new file mode 100644 +index 0000000..42bc005 +--- /dev/null ++++ b/debian/installer/modules/uinput-modules +@@ -0,0 +1 @@ ++uinput +diff --git a/debian/installer/modules/usb-modules b/debian/installer/modules/usb-modules +new file mode 100644 +index 0000000..d96074f +--- /dev/null ++++ b/debian/installer/modules/usb-modules +@@ -0,0 +1,5 @@ ++ehci-hcd ? ++ohci-hcd ? ++uhci-hcd ? ++xhci-hcd ? ++usbcore ? +diff --git a/debian/installer/modules/usb-serial-modules b/debian/installer/modules/usb-serial-modules +new file mode 100644 +index 0000000..7726ac5 +--- /dev/null ++++ b/debian/installer/modules/usb-serial-modules +@@ -0,0 +1,7 @@ ++usbserial ++belkin_sa ? ++digi_acceleport ? ++ftdi_sio ? ++mct_u232 ? ++pl2303 ? ++spcp8x5 ? +diff --git a/debian/installer/modules/usb-storage-modules b/debian/installer/modules/usb-storage-modules +new file mode 100644 +index 0000000..b567b94 +--- /dev/null ++++ b/debian/installer/modules/usb-storage-modules +@@ -0,0 +1,14 @@ ++usb-storage ++ums-alauda ++ums-cypress ++ums-datafab ++ums-eneub6250 ++ums-freecom ++ums-isd200 ++ums-jumpshot ++ums-karma ++ums-onetouch ++ums-realtek ++ums-sddr09 ++ums-sddr55 ++ums-usbat +diff --git a/debian/installer/modules/virtio-modules b/debian/installer/modules/virtio-modules +new file mode 100644 +index 0000000..04ae7e8 +--- /dev/null ++++ b/debian/installer/modules/virtio-modules +@@ -0,0 +1,7 @@ ++virtio_net ++virtio_blk ++virtio_balloon ++virtio_scsi ++ ++# Some architectures do not have PCI bus ++virtio_pci ? +diff --git a/debian/installer/modules/xfs-modules b/debian/installer/modules/xfs-modules +new file mode 100644 +index 0000000..7bd8fb2 +--- /dev/null ++++ b/debian/installer/modules/xfs-modules +@@ -0,0 +1,2 @@ ++# Not available currently on all kernel versions, so marked optional. ++xfs ? +diff --git a/debian/installer/modules/zlib-modules b/debian/installer/modules/zlib-modules +new file mode 100644 +index 0000000..322c546 +--- /dev/null ++++ b/debian/installer/modules/zlib-modules +@@ -0,0 +1 @@ ++zlib_deflate +diff --git a/debian/installer/package-list b/debian/installer/package-list +new file mode 100644 +index 0000000..ffe96eb +--- /dev/null ++++ b/debian/installer/package-list +@@ -0,0 +1,474 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# ++Package: kernel-image ++Priority: extra ++Description: Linux kernel binary image for the Debian installer ++ This package contains the kernel image for the Debian installer ++ boot images. It does _not_ provide a usable kernel for your full ++ Debian system. ++ ++Package: nic-modules ++Depends: kernel-image, nic-shared-modules, core-modules ++Priority: standard ++Description: Common NIC drivers ++ This package contains common NIC drivers for the kernel. ++ ++Package: nic-extra-modules ++Depends: kernel-image, nic-shared-modules, core-modules, i2c-modules, crc-modules ++Priority: standard ++Description: Rare NIC drivers ++ This package contains rare NIC drivers for the kernel. ++ ++Package: nic-wireless-modules ++Depends: kernel-image, nic-shared-modules, core-modules, usb-modules, mmc-modules, pcmcia-modules, crypto-core-modules, crc-modules ++Priority: standard ++Description: Wireless NIC drivers ++ This package contains wireless NIC drivers for the kernel. ++ Includes crypto modules only needed for wireless (WEP). ++ ++Package: nic-shared-modules ++Depends: kernel-image ++Priority: standard ++Description: Shared NIC drivers ++ This package contains NIC drivers needed by combinations of nic-modules, ++ nic-extra-modules, nic-pcmcia-modules, and nic-wireless-modules. ++ ++Package: serial-modules ++Depends: kernel-image, pcmcia-modules ++Priority: optional ++Description: Serial drivers ++ This package contains serial drivers for the kernel. ++ ++Package: usb-serial-modules ++Depends: kernel-image, usb-modules ++Priority: optional ++Description: USB serial drivers ++ This package contains USB serial drivers for the kernel. ++ ++Package: ppp-modules ++Depends: kernel-image, serial-modules, zlib-modules, crc-modules ++Priority: optional ++Description: PPP drivers ++ This package contains PPP drivers for the kernel. ++ ++Package: ide-modules ++Depends: kernel-image, ide-core-modules ++Priority: standard ++Description: IDE drivers ++ This package contains IDE drivers for the kernel. ++ ++Package: pata-modules ++Depends: kernel-image, ata-modules ++Priority: standard ++Description: PATA drivers ++ This package contains PATA drivers for the kernel. ++ ++Package: ide-core-modules ++Depends: kernel-image ++Priority: standard ++Description: IDE support ++ This package contains core IDE support for the kernel. ++ ++Package: cdrom-core-modules ++Depends: kernel-image, scsi-core-modules, ide-modules, isofs-modules ++Priority: standard ++Description: CDROM support ++ This package contains core CDROM support for the kernel. ++ ++Package: firewire-core-modules ++Depends: kernel-image, scsi-core-modules, crc-modules ++Priority: standard ++Description: Core FireWire drivers ++ This package contains core FireWire drivers for the kernel. ++ ++Package: scsi-core-modules ++Depends: kernel-image ++Priority: standard ++Description: Core SCSI subsystem ++ This package contains the core SCSI subsystem for the kernel. ++ ++Package: scsi-modules ++Depends: kernel-image, scsi-core-modules, parport-modules, cdrom-core-modules, core-modules, ata-modules ++Priority: standard ++Description: SCSI drivers ++ This package contains SCSI drivers for the kernel. ++ ++Package: scsi-common-modules ++Depends: kernel-image, scsi-core-modules, cdrom-core-modules ++Priority: standard ++Description: Very common SCSI drivers ++ This package contains very common SCSI drivers for the kernel. ++ ++Package: scsi-extra-modules ++Depends: scsi-modules, scsi-core-modules ++Priority: standard ++Description: Uncommon SCSI drivers ++ This package contains uncommon SCSI drivers for the kernel. ++ This includes SCSI RAID drivers, and some of the less common SCSI ++ controllers. ++ ++Package: plip-modules ++Depends: kernel-image, parport-modules ++Priority: optional ++Description: PLIP drivers ++ This package contains PLIP drivers for the kernel. ++ ++Package: floppy-modules ++Depends: kernel-image ++Priority: standard ++Description: Floppy driver ++ This package contains the floppy driver for the kernel. ++ ++Package: loop-modules ++Depends: kernel-image ++Priority: standard ++Description: Loopback filesystem support ++ This package contains loopback filesystem support for the kernel. ++ ++Package: ipv6-modules ++Depends: kernel-image ++Priority: extra ++Description: IPv6 driver ++ This package contains the IPv6 driver for the kernel. ++ ++Package: btrfs-modules ++Depends: kernel-image, core-modules, crc-modules, zlib-modules, lzo-modules ++Priority: extra ++Description: BTRFS filesystem support ++ This package contains the BTRFS filesystem module for the kernel. ++ ++Package: ext2-modules ++Depends: kernel-image ++Priority: standard ++Description: EXT2 filesystem support ++ This package contains the EXT2 filesystem module for the kernel. ++ ++Package: ext3-modules ++Depends: kernel-image ++Priority: standard ++Description: EXT3 filesystem support ++ This package contains the EXT3 filesystem module for the kernel. ++ ++Package: ext4-modules ++Depends: kernel-image, core-modules ++Priority: standard ++Description: EXT4 filesystem support ++ This package contains the EXT4 filesystem module for the kernel. ++ ++Package: isofs-modules ++Depends: kernel-image, nls-core-modules ++Priority: standard ++Description: ISOFS filesystem support ++ This package contains the ISOFS filesystem module for the kernel. ++ ++Package: jffs2-modules ++Depends: kernel-image, zlib-modules, lzo-modules ++Priority: extra ++Description: JFFS2 filesystem support ++ This package contains the JFFS2 filesystem module for the kernel. ++ ++Package: jfs-modules ++Depends: kernel-image, nls-core-modules ++Priority: standard ++Description: JFS filesystem support ++ This package contains the JFS filesystem module for the kernel. ++ ++Package: ntfs-modules ++Depends: kernel-image, nls-core-modules ++Priority: extra ++Description: NTFS filesystem support ++ This package contains the NTFS file system module for the kernel. ++ ++Package: reiserfs-modules ++Depends: kernel-image ++Priority: extra ++Description: Reiser filesystem support ++ This package contains the Reiser filesystem module for the kernel. ++ ++Package: xfs-modules ++Depends: kernel-image ++Priority: standard ++Description: XFS filesystem support ++ This package contains the XFS filesystem module for the kernel. ++ ++Package: fat-modules ++Depends: kernel-image, nls-core-modules ++Priority: extra ++Description: FAT filesystem support ++ This package contains the FAT and VFAT filesystem modules for the kernel. ++ ++Package: hfs-modules ++Depends: kernel-image, nls-core-modules ++Priority: extra ++Description: HFS filesystem support ++ This package contains the HFS and HFS+ filesystem modules for the kernel. ++ ++Package: affs-modules ++Depends: kernel-image ++Priority: extra ++Description: Amiga filesystem support ++ This package contains the Amiga filesystem module for the kernel. ++ ++Package: ufs-modules ++Depends: kernel-image ++Priority: extra ++Description: UFS filesystem support ++ This package contains the UFS filesystem module for the kernel. ++ ++Package: qnx4-modules ++Depends: kernel-image ++Priority: extra ++Description: QNX4 filesystem support ++ This package contains the QNX4 filesystem module for the kernel. ++ ++Package: minix-modules ++Depends: kernel-image ++Priority: extra ++Description: Minix filesystem support ++ This package contains the Minix filesystem module for the kernel. ++ ++Package: nfs-modules ++Depends: kernel-image ++Priority: extra ++Description: NFS filesystem support ++ This package contains the NFS filesystem module for the kernel. ++ ++Package: md-modules ++Depends: kernel-image ++Priority: extra ++Description: RAID and LVM support ++ This package contains RAID and LVM modules for the kernel. ++ ++Package: multipath-modules ++Depends: kernel-image, md-modules, scsi-core-modules ++Priority: extra ++Description: Multipath support ++ This package contains DM-Multipath modules for the kernel. ++ ++Package: usb-modules ++Depends: kernel-image, nls-core-modules ++Priority: extra ++Description: USB support ++ This package contains core USB drivers for the kernel. ++ ++Package: usb-storage-modules ++Depends: kernel-image, scsi-core-modules, usb-modules ++Priority: standard ++Description: USB storage support ++ This package contains the USB storage driver for the kernel. ++ ++Package: pcmcia-storage-modules ++Depends: kernel-image, cdrom-core-modules, pcmcia-modules, ata-modules ++Priority: standard ++Description: PCMCIA storage drivers ++ This package contains PCMCIA storage drivers for the kernel. ++ ++Package: fb-modules ++Depends: kernel-image ++Priority: extra ++Description: Frame buffer support ++ This package contains Frame buffer drivers for the kernel. ++ ++Package: input-modules ++Depends: kernel-image, usb-modules ++Priority: extra ++Description: Input devices support ++ This package contains input device drivers for the kernel. ++ ++Package: event-modules ++Depends: kernel-image ++Priority: extra ++Description: Event support ++ This package contains event drivers for the kernel. ++ ++Package: mouse-modules ++Depends: kernel-image, event-modules, input-modules, usb-modules ++Priority: extra ++Description: Mouse support ++ This package contains mouse drivers for the kernel. ++ ++Package: irda-modules ++Depends: kernel-image, ppp-modules, usb-modules ++Priority: extra ++Description: Infrared devices support ++ This package contains infrared device drivers for the kernel. ++ ++Package: parport-modules ++Depends: kernel-image ++Priority: extra ++Description: Parallel port support ++ This package contains parallel port drivers for the kernel. ++ ++Package: nic-pcmcia-modules ++Depends: kernel-image, nic-shared-modules, nic-wireless-modules, pcmcia-modules, mmc-core-modules ++Priority: standard ++Description: Common PCMCIA NIC drivers ++ This package contains common PCMCIA NIC drivers for the kernel. ++ ++Package: pcmcia-modules ++Depends: kernel-image ++Priority: standard ++Description: Common PCMCIA drivers ++ This package contains common PCMCIA drivers for the kernel. ++ ++Package: nic-usb-modules ++Depends: kernel-image, nic-shared-modules, nic-wireless-modules, usb-modules, core-modules ++Priority: standard ++Description: USB NIC drivers ++ This package contains USB network adapter drivers for the kernel. ++ ++Package: sata-modules ++Depends: kernel-image, scsi-core-modules, ata-modules ++Priority: standard ++Description: SATA drivers ++ This package contains SATA drivers for the kernel. ++ ++Package: core-modules ++Depends: kernel-image ++Priority: standard ++Description: Core modules ++ This package contains core modules for the kernel, that will almost ++ always be needed. ++ ++Package: acpi-modules ++Depends: kernel-image ++Priority: extra ++Description: ACPI support modules ++ This package contains kernel modules for ACPI. ++ ++Package: i2c-modules ++Depends: kernel-image ++Priority: extra ++Description: i2c support modules ++ This package contains basic i2c support modules. ++ ++Package: crc-modules ++Depends: kernel-image ++Priority: extra ++Description: CRC modules ++ This package contains CRC support modules. ++ ++Package: crypto-modules ++Depends: kernel-image ++Priority: extra ++Description: crypto modules ++ This package contains crypto modules. ++ ++Package: crypto-dm-modules ++Depends: kernel-image, md-modules ++Priority: extra ++Description: devicemapper crypto module ++ This package contains the devicemapper crypto (dm-crypt) module. ++ ++Package: efi-modules ++Depends: kernel-image ++Priority: extra ++Description: EFI modules ++ This package contains EFI modules. ++ ++Package: ata-modules ++Depends: kernel-image, scsi-core-modules ++Priority: extra ++Description: ATA disk modules ++ This package contains core ATA disk modules used by both PATA and SATA ++ disk drivers. ++ ++Package: mmc-core-modules ++Depends: kernel-image, core-modules ++Priority: extra ++Description: MMC/SD/SDIO core modules ++ This package contains core modules for MMC/SD/SDIO support. ++ ++Package: mmc-modules ++Depends: kernel-image, core-modules, mmc-core-modules ++Priority: extra ++Description: MMC/SD card modules ++ This package contains modules needed to support MMC (multimedia) and ++ SD cards. ++ ++Package: nbd-modules ++Depends: kernel-image ++Priority: extra ++Description: Network Block Device modules ++ This package contains the modules required for support of the Network Block ++ Device ++ ++Package: squashfs-modules ++Depends: kernel-image ++Priority: extra ++Description: squashfs modules ++ This package contains squashfs modules. ++ ++Package: speakup-modules ++Depends: kernel-image! ++Priority: extra ++Description: speakup modules ++ This package contains speakup modules. ++ ++Package: rtc-modules ++Depends: kernel-image ++Priority: extra ++Description: RTC modules ++ This package contains RTC modules. ++ ++Package: virtio-modules ++Depends: kernel-image, scsi-core-modules ++Priority: extra ++Description: virtio modules ++ This package contains virtio modules. ++ ++Package: uinput-modules ++Depends: kernel-image ++Priority: extra ++Description: uinput support ++ This package contains the uinput module. ++ ++Package: sound-modules ++Depends: kernel-image, core-modules, i2c-modules, usb-modules, pcmcia-modules, firewire-core-modules, crc-modules ++Priority: extra ++Description: sound support ++ This package contains sound modules. ++ ++Package: zlib-modules ++Depends: kernel-image ++Priority: extra ++Description: zlib modules ++ This package contains zlib modules. ++ ++Package: lzo-modules ++Depends: kernel-image ++Priority: extra ++Description: lzo modules ++ This package contains lzo modules. ++ ++Package: leds-modules ++Depends: kernel-image ++Priority: extra ++Description: LED modules ++ This package contains LED modules. ++ ++Package: hyperv-modules ++Depends: kernel-image, input-modules, scsi-core-modules ++Priority: extra ++Description: Hyper-V modules ++ This package contains Hyper-V paravirtualised drivers for the kernel. ++ ++Package: udf-modules ++Depends: kernel-image, crc-modules ++Priority: extra ++Description: UDF modules ++ This package contains the UDF filesystem module. ++ ++Package: fuse-modules ++Depends: kernel-image ++Priority: extra ++Description: FUSE modules ++ This package contains the Filesystem in Userspace (FUSE) module. ++ ++Package: mtd-modules ++Depends: kernel-image ++Priority: extra ++Description: MTD modules ++ This package contains MTD modules. +diff --git a/debian/installer/powerpc/kernel-versions b/debian/installer/powerpc/kernel-versions +new file mode 100644 +index 0000000..50cf212 +--- /dev/null ++++ b/debian/installer/powerpc/kernel-versions +@@ -0,0 +1,3 @@ ++# arch version flavour installedname suffix build-depends ++powerpc - powerpc - - - ++powerpc - powerpc64 - - - +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/affs-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/affs-modules +new file mode 100644 +index 0000000..f12f6ac +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/affs-modules +@@ -0,0 +1 @@ ++#include "../powerpc/affs-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ata-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ata-modules +new file mode 100644 +index 0000000..39540d4 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ata-modules +@@ -0,0 +1 @@ ++#include "../powerpc/ata-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/btrfs-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/cdrom-core-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/cdrom-core-modules +new file mode 100644 +index 0000000..feed89a +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/cdrom-core-modules +@@ -0,0 +1 @@ ++#include "../powerpc/cdrom-core-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/core-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/core-modules +new file mode 100644 +index 0000000..21826c6 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/core-modules +@@ -0,0 +1,2 @@ ++#include ++mbcache +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/crc-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/crypto-dm-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/crypto-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/event-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/event-modules +new file mode 100644 +index 0000000..f8819af +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/event-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ext2-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ext2-modules +new file mode 100644 +index 0000000..b8cca99 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ext2-modules +@@ -0,0 +1 @@ ++#include "../powerpc/ext2-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ext3-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ext3-modules +new file mode 100644 +index 0000000..3f963c9 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ext3-modules +@@ -0,0 +1 @@ ++#include "../powerpc/ext3-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ext4-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/fat-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/fat-modules +new file mode 100644 +index 0000000..043dc56 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/fat-modules +@@ -0,0 +1 @@ ++#include "../powerpc/fat-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/firewire-core-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/firewire-core-modules +new file mode 100644 +index 0000000..035ab31 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/firewire-core-modules +@@ -0,0 +1 @@ ++#include "../powerpc/firewire-core-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/floppy-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/floppy-modules +new file mode 100644 +index 0000000..fc290d9 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/floppy-modules +@@ -0,0 +1 @@ ++#include "../powerpc/floppy-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/fuse-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/fuse-modules +new file mode 100644 +index 0000000..49bdce4 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/fuse-modules +@@ -0,0 +1 @@ ++#include "../powerpc/fuse-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/hfs-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/hfs-modules +new file mode 100644 +index 0000000..a85f691 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/hfs-modules +@@ -0,0 +1 @@ ++#include "../powerpc/hfs-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/input-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/input-modules +new file mode 100644 +index 0000000..38a8889 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/input-modules +@@ -0,0 +1 @@ ++#include "../powerpc/input-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/irda-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/irda-modules +new file mode 100644 +index 0000000..c266dec +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/irda-modules +@@ -0,0 +1 @@ ++#include "../powerpc/irda-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/isofs-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/jfs-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/jfs-modules +new file mode 100644 +index 0000000..b71ebd3 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/jfs-modules +@@ -0,0 +1 @@ ++#include "../powerpc/jfs-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/kernel-image b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/kernel-image +new file mode 100644 +index 0000000..a0b7d0c +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/kernel-image +@@ -0,0 +1 @@ ++#include "../powerpc/kernel-image" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/loop-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/loop-modules +new file mode 100644 +index 0000000..e227368 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/loop-modules +@@ -0,0 +1 @@ ++#include "../powerpc/loop-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/md-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/md-modules +new file mode 100644 +index 0000000..93be33f +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/md-modules +@@ -0,0 +1 @@ ++#include "../powerpc/md-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/mouse-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/mouse-modules +new file mode 100644 +index 0000000..22aca94 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/mouse-modules +@@ -0,0 +1 @@ ++#include "../powerpc/mouse-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/multipath-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nbd-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nic-extra-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nic-extra-modules +new file mode 100644 +index 0000000..b2697d7 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nic-extra-modules +@@ -0,0 +1,23 @@ ++dl2k ++fealnx ++hamachi ++ixgb ++ns83820 ++r8169 ++s2io ++starfire ++tlan ++3c359 ? ++abyss ++lanstreamer ++olympic ++tms380tr ++tmspci ++de2104x ++dmfe ++winbond-840 ++prism54 ? ++p54pci ++p54usb ++yellowfin ++8021q +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nic-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nic-modules +new file mode 100644 +index 0000000..7578f43 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nic-modules +@@ -0,0 +1 @@ ++#include "../powerpc/nic-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nic-pcmcia-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nic-pcmcia-modules +new file mode 100644 +index 0000000..3f521e9d +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nic-pcmcia-modules +@@ -0,0 +1 @@ ++#include "../powerpc/nic-pcmcia-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nic-shared-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nic-shared-modules +new file mode 100644 +index 0000000..d93c8f3 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/nic-shared-modules +@@ -0,0 +1,2 @@ ++8390 ++libphy +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/pata-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/pata-modules +new file mode 100644 +index 0000000..bb9cbe3 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/pata-modules +@@ -0,0 +1 @@ ++#include "../powerpc/pata-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/pcmcia-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/pcmcia-modules +new file mode 100644 +index 0000000..e508df6 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/pcmcia-modules +@@ -0,0 +1 @@ ++#include "../powerpc/pcmcia-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/pcmcia-storage-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/pcmcia-storage-modules +new file mode 100644 +index 0000000..f00f246 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/pcmcia-storage-modules +@@ -0,0 +1 @@ ++#include "../powerpc/pcmcia-storage-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ppp-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ppp-modules +new file mode 100644 +index 0000000..eb7ab74 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ppp-modules +@@ -0,0 +1 @@ ++#include "../powerpc/ppp-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/reiserfs-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/reiserfs-modules +new file mode 100644 +index 0000000..3136f7a +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/reiserfs-modules +@@ -0,0 +1 @@ ++#include "../powerpc/reiserfs-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/sata-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/sata-modules +new file mode 100644 +index 0000000..591ad74 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/sata-modules +@@ -0,0 +1 @@ ++#include "../powerpc/sata-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/scsi-common-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/scsi-common-modules +new file mode 100644 +index 0000000..17ad4c4 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/scsi-common-modules +@@ -0,0 +1 @@ ++#include "../powerpc/scsi-common-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/scsi-core-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/scsi-core-modules +new file mode 100644 +index 0000000..c972a47 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/scsi-core-modules +@@ -0,0 +1 @@ ++#include "../powerpc/scsi-core-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/scsi-extra-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/scsi-extra-modules +new file mode 100644 +index 0000000..2b98d8b +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/scsi-extra-modules +@@ -0,0 +1 @@ ++#include "../powerpc/scsi-extra-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/scsi-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/scsi-modules +new file mode 100644 +index 0000000..dd5ae9c +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/scsi-modules +@@ -0,0 +1 @@ ++#include "../powerpc/scsi-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/serial-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/serial-modules +new file mode 100644 +index 0000000..349196e +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/serial-modules +@@ -0,0 +1 @@ ++#include "../powerpc/serial-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/squashfs-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/udf-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ufs-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ufs-modules +new file mode 100644 +index 0000000..d8dbfd3 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/ufs-modules +@@ -0,0 +1 @@ ++#include "../powerpc/ufs-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/uinput-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/uinput-modules +new file mode 100644 +index 0000000..58a8337 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/uinput-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/usb-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/usb-modules +new file mode 100644 +index 0000000..9c5b10a +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/usb-modules +@@ -0,0 +1 @@ ++#include "../powerpc/usb-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/usb-serial-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/usb-serial-modules +new file mode 100644 +index 0000000..e25b558 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/usb-serial-modules +@@ -0,0 +1 @@ ++#include "../powerpc/usb-serial-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/usb-storage-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/usb-storage-modules +new file mode 100644 +index 0000000..5f278e6 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/usb-storage-modules +@@ -0,0 +1 @@ ++#include "../powerpc/usb-storage-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/xfs-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/xfs-modules +new file mode 100644 +index 0000000..c850127 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/xfs-modules +@@ -0,0 +1 @@ ++#include "../powerpc/xfs-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc-miboot/zlib-modules b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc-miboot/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/affs-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/affs-modules +new file mode 100644 +index 0000000..f12f6ac +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/affs-modules +@@ -0,0 +1 @@ ++#include "../powerpc/affs-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/ata-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/ata-modules +new file mode 100644 +index 0000000..39540d4 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/ata-modules +@@ -0,0 +1 @@ ++#include "../powerpc/ata-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/btrfs-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/cdrom-core-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/cdrom-core-modules +new file mode 100644 +index 0000000..feed89a +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/cdrom-core-modules +@@ -0,0 +1 @@ ++#include "../powerpc/cdrom-core-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/core-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/core-modules +new file mode 100644 +index 0000000..e789d4b +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/core-modules +@@ -0,0 +1 @@ ++#include "../powerpc/core-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/crc-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/crypto-dm-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/crypto-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/event-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/event-modules +new file mode 100644 +index 0000000..f8819af +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/event-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/ext2-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/ext2-modules +new file mode 100644 +index 0000000..b8cca99 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/ext2-modules +@@ -0,0 +1 @@ ++#include "../powerpc/ext2-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/ext3-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/ext3-modules +new file mode 100644 +index 0000000..3f963c9 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/ext3-modules +@@ -0,0 +1 @@ ++#include "../powerpc/ext3-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/ext4-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/fancontrol-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/fancontrol-modules +new file mode 100644 +index 0000000..f069ca1 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/fancontrol-modules +@@ -0,0 +1,14 @@ ++i2c-powermac ? ++therm_pm72 ? ++windfarm_core ? ++windfarm_cpufreq_clamp ? ++windfarm_lm75_sensor ? ++windfarm_max6690_sensor ? ++windfarm_pid ? ++windfarm_pm121 ? ++windfarm_pm112 ? ++windfarm_pm81 ? ++windfarm_pm91 ? ++windfarm_smu_controls ? ++windfarm_smu_sat ? ++windfarm_smu_sensors ? +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/fat-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/fat-modules +new file mode 100644 +index 0000000..043dc56 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/fat-modules +@@ -0,0 +1 @@ ++#include "../powerpc/fat-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/firewire-core-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/firewire-core-modules +new file mode 100644 +index 0000000..035ab31 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/firewire-core-modules +@@ -0,0 +1 @@ ++#include "../powerpc/firewire-core-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/floppy-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/floppy-modules +new file mode 100644 +index 0000000..fc290d9 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/floppy-modules +@@ -0,0 +1 @@ ++#include "../powerpc/floppy-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/fuse-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/fuse-modules +new file mode 100644 +index 0000000..49bdce4 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/fuse-modules +@@ -0,0 +1 @@ ++#include "../powerpc/fuse-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/hfs-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/hfs-modules +new file mode 100644 +index 0000000..a85f691 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/hfs-modules +@@ -0,0 +1 @@ ++#include "../powerpc/hfs-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/hypervisor-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/hypervisor-modules +new file mode 100644 +index 0000000..29ceb61 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/hypervisor-modules +@@ -0,0 +1,2 @@ ++hvcserver ++hvcs +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/input-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/input-modules +new file mode 100644 +index 0000000..38a8889 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/input-modules +@@ -0,0 +1 @@ ++#include "../powerpc/input-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/irda-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/irda-modules +new file mode 100644 +index 0000000..c266dec +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/irda-modules +@@ -0,0 +1 @@ ++#include "../powerpc/irda-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/isofs-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/jfs-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/jfs-modules +new file mode 100644 +index 0000000..b71ebd3 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/jfs-modules +@@ -0,0 +1 @@ ++#include "../powerpc/jfs-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/kernel-image b/debian/installer/powerpc/modules/powerpc-powerpc64/kernel-image +new file mode 100644 +index 0000000..a0b7d0c +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/kernel-image +@@ -0,0 +1 @@ ++#include "../powerpc/kernel-image" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/loop-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/loop-modules +new file mode 100644 +index 0000000..e227368 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/loop-modules +@@ -0,0 +1 @@ ++#include "../powerpc/loop-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/md-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/md-modules +new file mode 100644 +index 0000000..93be33f +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/md-modules +@@ -0,0 +1 @@ ++#include "../powerpc/md-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/mouse-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/mouse-modules +new file mode 100644 +index 0000000..22aca94 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/mouse-modules +@@ -0,0 +1 @@ ++#include "../powerpc/mouse-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/multipath-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/nbd-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/nic-extra-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/nic-extra-modules +new file mode 100644 +index 0000000..9bce44d +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/nic-extra-modules +@@ -0,0 +1,4 @@ ++#include "../powerpc/nic-extra-modules" ++ ++ehea ++ps3_gelic +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/nic-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/nic-modules +new file mode 100644 +index 0000000..a8c580c +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/nic-modules +@@ -0,0 +1,5 @@ ++#include "../powerpc/nic-modules" ++ ++ibmveth ++spidernet ++pasemi_mac ? +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/nic-pcmcia-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/nic-pcmcia-modules +new file mode 100644 +index 0000000..7a0702c +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/nic-pcmcia-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/nic-shared-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/nic-shared-modules +new file mode 100644 +index 0000000..b52153d +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/nic-shared-modules +@@ -0,0 +1,3 @@ ++8390 ++mii ++libphy +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/pata-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/pata-modules +new file mode 100644 +index 0000000..bb9cbe3 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/pata-modules +@@ -0,0 +1 @@ ++#include "../powerpc/pata-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/pcmcia-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/pcmcia-modules +new file mode 100644 +index 0000000..e508df6 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/pcmcia-modules +@@ -0,0 +1 @@ ++#include "../powerpc/pcmcia-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/pcmcia-storage-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/pcmcia-storage-modules +new file mode 100644 +index 0000000..f00f246 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/pcmcia-storage-modules +@@ -0,0 +1 @@ ++#include "../powerpc/pcmcia-storage-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/ppp-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/ppp-modules +new file mode 100644 +index 0000000..eb7ab74 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/ppp-modules +@@ -0,0 +1 @@ ++#include "../powerpc/ppp-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/reiserfs-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/reiserfs-modules +new file mode 100644 +index 0000000..3136f7a +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/reiserfs-modules +@@ -0,0 +1 @@ ++#include "../powerpc/reiserfs-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/sata-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/sata-modules +new file mode 100644 +index 0000000..591ad74 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/sata-modules +@@ -0,0 +1 @@ ++#include "../powerpc/sata-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/scsi-common-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/scsi-common-modules +new file mode 100644 +index 0000000..17ad4c4 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/scsi-common-modules +@@ -0,0 +1 @@ ++#include "../powerpc/scsi-common-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/scsi-core-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/scsi-core-modules +new file mode 100644 +index 0000000..c972a47 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/scsi-core-modules +@@ -0,0 +1 @@ ++#include "../powerpc/scsi-core-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/scsi-extra-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/scsi-extra-modules +new file mode 100644 +index 0000000..f37aaaa +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/scsi-extra-modules +@@ -0,0 +1,3 @@ ++#include ++ ++ps3disk ? +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/scsi-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/scsi-modules +new file mode 100644 +index 0000000..29722a1 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/scsi-modules +@@ -0,0 +1,4 @@ ++#include ++ ++ibmvscsic ++ps3rom +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/serial-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/serial-modules +new file mode 100644 +index 0000000..349196e +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/serial-modules +@@ -0,0 +1 @@ ++#include "../powerpc/serial-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/squashfs-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/udf-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/ufs-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/ufs-modules +new file mode 100644 +index 0000000..d8dbfd3 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/ufs-modules +@@ -0,0 +1 @@ ++#include "../powerpc/ufs-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/uinput-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/uinput-modules +new file mode 100644 +index 0000000..58a8337 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/uinput-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/usb-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/usb-modules +new file mode 100644 +index 0000000..9c5b10a +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/usb-modules +@@ -0,0 +1 @@ ++#include "../powerpc/usb-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/usb-serial-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/usb-serial-modules +new file mode 100644 +index 0000000..e25b558 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/usb-serial-modules +@@ -0,0 +1 @@ ++#include "../powerpc/usb-serial-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/usb-storage-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/usb-storage-modules +new file mode 100644 +index 0000000..5f278e6 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/usb-storage-modules +@@ -0,0 +1 @@ ++#include "../powerpc/usb-storage-modules" +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/virtio-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc-powerpc64/xfs-modules b/debian/installer/powerpc/modules/powerpc-powerpc64/xfs-modules +new file mode 100644 +index 0000000..c850127 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc-powerpc64/xfs-modules +@@ -0,0 +1 @@ ++#include "../powerpc/xfs-modules" +diff --git a/debian/installer/powerpc/modules/powerpc/affs-modules b/debian/installer/powerpc/modules/powerpc/affs-modules +new file mode 100644 +index 0000000..3f0e4bb +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/affs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/ata-modules b/debian/installer/powerpc/modules/powerpc/ata-modules +new file mode 100644 +index 0000000..be78de0 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/ata-modules +@@ -0,0 +1,2 @@ ++#include ++libata - +diff --git a/debian/installer/powerpc/modules/powerpc/btrfs-modules b/debian/installer/powerpc/modules/powerpc/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/cdrom-core-modules b/debian/installer/powerpc/modules/powerpc/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/core-modules b/debian/installer/powerpc/modules/powerpc/core-modules +new file mode 100644 +index 0000000..d90987b +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/core-modules +@@ -0,0 +1,3 @@ ++#include ++mbcache ++bestcomm-core ? +diff --git a/debian/installer/powerpc/modules/powerpc/crc-modules b/debian/installer/powerpc/modules/powerpc/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/crypto-dm-modules b/debian/installer/powerpc/modules/powerpc/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/crypto-modules b/debian/installer/powerpc/modules/powerpc/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/event-modules b/debian/installer/powerpc/modules/powerpc/event-modules +new file mode 100644 +index 0000000..f8819af +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/event-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/ext2-modules b/debian/installer/powerpc/modules/powerpc/ext2-modules +new file mode 100644 +index 0000000..bbaebc8 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/ext2-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/ext3-modules b/debian/installer/powerpc/modules/powerpc/ext3-modules +new file mode 100644 +index 0000000..55ef7d7 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/ext3-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/ext4-modules b/debian/installer/powerpc/modules/powerpc/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/fat-modules b/debian/installer/powerpc/modules/powerpc/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/firewire-core-modules b/debian/installer/powerpc/modules/powerpc/firewire-core-modules +new file mode 100644 +index 0000000..dcac80a +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/firewire-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/floppy-modules b/debian/installer/powerpc/modules/powerpc/floppy-modules +new file mode 100644 +index 0000000..169fde5 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/floppy-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/fuse-modules b/debian/installer/powerpc/modules/powerpc/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/hfs-modules b/debian/installer/powerpc/modules/powerpc/hfs-modules +new file mode 100644 +index 0000000..57d12f6 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/hfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/input-modules b/debian/installer/powerpc/modules/powerpc/input-modules +new file mode 100644 +index 0000000..51e37ce +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/input-modules +@@ -0,0 +1,3 @@ ++#include ++atkbd ++i8042 +diff --git a/debian/installer/powerpc/modules/powerpc/irda-modules b/debian/installer/powerpc/modules/powerpc/irda-modules +new file mode 100644 +index 0000000..b141b58 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/irda-modules +@@ -0,0 +1,7 @@ ++irtty-sir ++sir-dev ++ircomm-tty ++ircomm ++irda ++irlan ++irnet +diff --git a/debian/installer/powerpc/modules/powerpc/isofs-modules b/debian/installer/powerpc/modules/powerpc/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/jfs-modules b/debian/installer/powerpc/modules/powerpc/jfs-modules +new file mode 100644 +index 0000000..925a43a +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/jfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/kernel-image b/debian/installer/powerpc/modules/powerpc/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/powerpc/modules/powerpc/loop-modules b/debian/installer/powerpc/modules/powerpc/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/md-modules b/debian/installer/powerpc/modules/powerpc/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/mouse-modules b/debian/installer/powerpc/modules/powerpc/mouse-modules +new file mode 100644 +index 0000000..15fcb00 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/mouse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/multipath-modules b/debian/installer/powerpc/modules/powerpc/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/nbd-modules b/debian/installer/powerpc/modules/powerpc/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/nic-extra-modules b/debian/installer/powerpc/modules/powerpc/nic-extra-modules +new file mode 100644 +index 0000000..071e7b2 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/nic-extra-modules +@@ -0,0 +1,3 @@ ++#include ++ ++tms380tr +diff --git a/debian/installer/powerpc/modules/powerpc/nic-modules b/debian/installer/powerpc/modules/powerpc/nic-modules +new file mode 100644 +index 0000000..fa15106 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/nic-modules +@@ -0,0 +1,8 @@ ++#include ++ ++ipddp ++sunhme ++airport ++sungem ++sungem_phy ++bmac ? +diff --git a/debian/installer/powerpc/modules/powerpc/nic-pcmcia-modules b/debian/installer/powerpc/modules/powerpc/nic-pcmcia-modules +new file mode 100644 +index 0000000..7a0702c +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/nic-pcmcia-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/nic-shared-modules b/debian/installer/powerpc/modules/powerpc/nic-shared-modules +new file mode 100644 +index 0000000..d93c8f3 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/nic-shared-modules +@@ -0,0 +1,2 @@ ++8390 ++libphy +diff --git a/debian/installer/powerpc/modules/powerpc/pata-modules b/debian/installer/powerpc/modules/powerpc/pata-modules +new file mode 100644 +index 0000000..4c7d429 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/pata-modules +@@ -0,0 +1,3 @@ ++#include ++pata_mpc52xx ? ++pata_macio ? +diff --git a/debian/installer/powerpc/modules/powerpc/pcmcia-modules b/debian/installer/powerpc/modules/powerpc/pcmcia-modules +new file mode 100644 +index 0000000..2bb5350 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/pcmcia-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/pcmcia-storage-modules b/debian/installer/powerpc/modules/powerpc/pcmcia-storage-modules +new file mode 100644 +index 0000000..9fbaff3 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/pcmcia-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/ppp-modules b/debian/installer/powerpc/modules/powerpc/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/reiserfs-modules b/debian/installer/powerpc/modules/powerpc/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/sata-modules b/debian/installer/powerpc/modules/powerpc/sata-modules +new file mode 100644 +index 0000000..071cb86 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/sata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/scsi-common-modules b/debian/installer/powerpc/modules/powerpc/scsi-common-modules +new file mode 100644 +index 0000000..4973901 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/scsi-common-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/scsi-core-modules b/debian/installer/powerpc/modules/powerpc/scsi-core-modules +new file mode 100644 +index 0000000..6ec85bb +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/scsi-core-modules +@@ -0,0 +1,3 @@ ++#include ++scsi_mod - ++scsi_transport_spi +diff --git a/debian/installer/powerpc/modules/powerpc/scsi-extra-modules b/debian/installer/powerpc/modules/powerpc/scsi-extra-modules +new file mode 100644 +index 0000000..cd13ede +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/scsi-extra-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/scsi-modules b/debian/installer/powerpc/modules/powerpc/scsi-modules +new file mode 100644 +index 0000000..c75c32d +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/scsi-modules +@@ -0,0 +1,5 @@ ++#include ++ ++a100u2w ++mac53c94 ++mesh +diff --git a/debian/installer/powerpc/modules/powerpc/serial-modules b/debian/installer/powerpc/modules/powerpc/serial-modules +new file mode 100644 +index 0000000..6ab8b8c +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/squashfs-modules b/debian/installer/powerpc/modules/powerpc/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/udf-modules b/debian/installer/powerpc/modules/powerpc/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/ufs-modules b/debian/installer/powerpc/modules/powerpc/ufs-modules +new file mode 100644 +index 0000000..69745ca +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/ufs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/uinput-modules b/debian/installer/powerpc/modules/powerpc/uinput-modules +new file mode 100644 +index 0000000..58a8337 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/uinput-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/usb-modules b/debian/installer/powerpc/modules/powerpc/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/usb-serial-modules b/debian/installer/powerpc/modules/powerpc/usb-serial-modules +new file mode 100644 +index 0000000..c0a0dc3 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/usb-serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/usb-storage-modules b/debian/installer/powerpc/modules/powerpc/usb-storage-modules +new file mode 100644 +index 0000000..272d95e +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/virtio-modules b/debian/installer/powerpc/modules/powerpc/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/modules/powerpc/xfs-modules b/debian/installer/powerpc/modules/powerpc/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/powerpc/modules/powerpc/zlib-modules b/debian/installer/powerpc/modules/powerpc/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/powerpc/modules/powerpc/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/powerpc/package-list b/debian/installer/powerpc/package-list +new file mode 100644 +index 0000000..c112f51 +--- /dev/null ++++ b/debian/installer/powerpc/package-list +@@ -0,0 +1,42 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: ext2-modules ++Depends: kernel-image, core-modules ++ ++Package: ext3-modules ++Depends: kernel-image, core-modules ++ ++Package: ext4-modules ++Depends: kernel-image, core-modules ++ ++Package: pata-modules ++Depends: kernel-image, ata-modules, core-modules ++ ++Package: scsi-modules ++Depends: kernel-image, scsi-core-modules, parport-modules, cdrom-core-modules, core-modules, ata-modules ++ ++Package: pcmcia-modules ++Depends: kernel-image, core-modules ++ ++Package: nic-pcmcia-modules ++Depends: kernel-image, nic-modules, nic-shared-modules, nic-wireless-modules, pcmcia-modules, core-modules ++ ++Package: hypervisor-modules ++Depends: kernel-image ++Priority: standard ++Description: IBM 64bit hypervisor console modules ++ Contains drivers for the hypervisor console, used as console for linux ++ running in logical partitions of IBM hardware supporting it. ++ ++Package: fancontrol-modules ++Depends: kernel-image ++Priority: standard ++Description: Apple powermac fancontrol modules ++ Contains drivers for macintosh i2c bus as well as for the monitoring devices ++ connected to it. This allows to control the fans during installation. ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/ppc64/kernel-versions b/debian/installer/ppc64/kernel-versions +new file mode 100644 +index 0000000..359bd10 +--- /dev/null ++++ b/debian/installer/ppc64/kernel-versions +@@ -0,0 +1,2 @@ ++# arch version flavour installedname suffix build-depends ++ppc64 - powerpc64 - - - +diff --git a/debian/installer/ppc64/modules/ppc64/affs-modules b/debian/installer/ppc64/modules/ppc64/affs-modules +new file mode 100644 +index 0000000..3f0e4bb +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/affs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/ata-modules b/debian/installer/ppc64/modules/ppc64/ata-modules +new file mode 100644 +index 0000000..be78de0 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/ata-modules +@@ -0,0 +1,2 @@ ++#include ++libata - +diff --git a/debian/installer/ppc64/modules/ppc64/btrfs-modules b/debian/installer/ppc64/modules/ppc64/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/cdrom-core-modules b/debian/installer/ppc64/modules/ppc64/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/core-modules b/debian/installer/ppc64/modules/ppc64/core-modules +new file mode 100644 +index 0000000..d90987b +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/core-modules +@@ -0,0 +1,3 @@ ++#include ++mbcache ++bestcomm-core ? +diff --git a/debian/installer/ppc64/modules/ppc64/crc-modules b/debian/installer/ppc64/modules/ppc64/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/crypto-dm-modules b/debian/installer/ppc64/modules/ppc64/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/crypto-modules b/debian/installer/ppc64/modules/ppc64/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/event-modules b/debian/installer/ppc64/modules/ppc64/event-modules +new file mode 100644 +index 0000000..f8819af +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/event-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/ext2-modules b/debian/installer/ppc64/modules/ppc64/ext2-modules +new file mode 100644 +index 0000000..bbaebc8 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/ext2-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/ext3-modules b/debian/installer/ppc64/modules/ppc64/ext3-modules +new file mode 100644 +index 0000000..55ef7d7 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/ext3-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/ext4-modules b/debian/installer/ppc64/modules/ppc64/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/fancontrol-modules b/debian/installer/ppc64/modules/ppc64/fancontrol-modules +new file mode 100644 +index 0000000..f069ca1 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/fancontrol-modules +@@ -0,0 +1,14 @@ ++i2c-powermac ? ++therm_pm72 ? ++windfarm_core ? ++windfarm_cpufreq_clamp ? ++windfarm_lm75_sensor ? ++windfarm_max6690_sensor ? ++windfarm_pid ? ++windfarm_pm121 ? ++windfarm_pm112 ? ++windfarm_pm81 ? ++windfarm_pm91 ? ++windfarm_smu_controls ? ++windfarm_smu_sat ? ++windfarm_smu_sensors ? +diff --git a/debian/installer/ppc64/modules/ppc64/fat-modules b/debian/installer/ppc64/modules/ppc64/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/firewire-core-modules b/debian/installer/ppc64/modules/ppc64/firewire-core-modules +new file mode 100644 +index 0000000..dcac80a +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/firewire-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/floppy-modules b/debian/installer/ppc64/modules/ppc64/floppy-modules +new file mode 100644 +index 0000000..169fde5 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/floppy-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/fuse-modules b/debian/installer/ppc64/modules/ppc64/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/hfs-modules b/debian/installer/ppc64/modules/ppc64/hfs-modules +new file mode 100644 +index 0000000..57d12f6 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/hfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/hypervisor-modules b/debian/installer/ppc64/modules/ppc64/hypervisor-modules +new file mode 100644 +index 0000000..29ceb61 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/hypervisor-modules +@@ -0,0 +1,2 @@ ++hvcserver ++hvcs +diff --git a/debian/installer/ppc64/modules/ppc64/input-modules b/debian/installer/ppc64/modules/ppc64/input-modules +new file mode 100644 +index 0000000..51e37ce +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/input-modules +@@ -0,0 +1,3 @@ ++#include ++atkbd ++i8042 +diff --git a/debian/installer/ppc64/modules/ppc64/irda-modules b/debian/installer/ppc64/modules/ppc64/irda-modules +new file mode 100644 +index 0000000..b141b58 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/irda-modules +@@ -0,0 +1,7 @@ ++irtty-sir ++sir-dev ++ircomm-tty ++ircomm ++irda ++irlan ++irnet +diff --git a/debian/installer/ppc64/modules/ppc64/isofs-modules b/debian/installer/ppc64/modules/ppc64/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/jfs-modules b/debian/installer/ppc64/modules/ppc64/jfs-modules +new file mode 100644 +index 0000000..925a43a +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/jfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/kernel-image b/debian/installer/ppc64/modules/ppc64/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/ppc64/modules/ppc64/loop-modules b/debian/installer/ppc64/modules/ppc64/loop-modules +new file mode 100644 +index 0000000..1644677 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/loop-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/md-modules b/debian/installer/ppc64/modules/ppc64/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/mouse-modules b/debian/installer/ppc64/modules/ppc64/mouse-modules +new file mode 100644 +index 0000000..15fcb00 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/mouse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/multipath-modules b/debian/installer/ppc64/modules/ppc64/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/nbd-modules b/debian/installer/ppc64/modules/ppc64/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/nic-extra-modules b/debian/installer/ppc64/modules/ppc64/nic-extra-modules +new file mode 100644 +index 0000000..8eabd91 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/nic-extra-modules +@@ -0,0 +1,4 @@ ++#include ++tms380tr ++ehea ++ps3_gelic +diff --git a/debian/installer/ppc64/modules/ppc64/nic-modules b/debian/installer/ppc64/modules/ppc64/nic-modules +new file mode 100644 +index 0000000..a7d0d0b +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/nic-modules +@@ -0,0 +1,11 @@ ++#include ++ ++ipddp ++sunhme ++airport ++sungem ++sungem_phy ++bmac ? ++ibmveth ++spidernet ++pasemi_mac ? +diff --git a/debian/installer/ppc64/modules/ppc64/nic-pcmcia-modules b/debian/installer/ppc64/modules/ppc64/nic-pcmcia-modules +new file mode 100644 +index 0000000..7a0702c +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/nic-pcmcia-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/nic-shared-modules b/debian/installer/ppc64/modules/ppc64/nic-shared-modules +new file mode 100644 +index 0000000..b52153d +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/nic-shared-modules +@@ -0,0 +1,3 @@ ++8390 ++mii ++libphy +diff --git a/debian/installer/ppc64/modules/ppc64/pata-modules b/debian/installer/ppc64/modules/ppc64/pata-modules +new file mode 100644 +index 0000000..4c7d429 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/pata-modules +@@ -0,0 +1,3 @@ ++#include ++pata_mpc52xx ? ++pata_macio ? +diff --git a/debian/installer/ppc64/modules/ppc64/pcmcia-modules b/debian/installer/ppc64/modules/ppc64/pcmcia-modules +new file mode 100644 +index 0000000..2bb5350 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/pcmcia-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/pcmcia-storage-modules b/debian/installer/ppc64/modules/ppc64/pcmcia-storage-modules +new file mode 100644 +index 0000000..9fbaff3 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/pcmcia-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/ppp-modules b/debian/installer/ppc64/modules/ppc64/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/reiserfs-modules b/debian/installer/ppc64/modules/ppc64/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/sata-modules b/debian/installer/ppc64/modules/ppc64/sata-modules +new file mode 100644 +index 0000000..071cb86 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/sata-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/scsi-common-modules b/debian/installer/ppc64/modules/ppc64/scsi-common-modules +new file mode 100644 +index 0000000..4973901 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/scsi-common-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/scsi-core-modules b/debian/installer/ppc64/modules/ppc64/scsi-core-modules +new file mode 100644 +index 0000000..6ec85bb +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/scsi-core-modules +@@ -0,0 +1,3 @@ ++#include ++scsi_mod - ++scsi_transport_spi +diff --git a/debian/installer/ppc64/modules/ppc64/scsi-extra-modules b/debian/installer/ppc64/modules/ppc64/scsi-extra-modules +new file mode 100644 +index 0000000..f37aaaa +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/scsi-extra-modules +@@ -0,0 +1,3 @@ ++#include ++ ++ps3disk ? +diff --git a/debian/installer/ppc64/modules/ppc64/scsi-modules b/debian/installer/ppc64/modules/ppc64/scsi-modules +new file mode 100644 +index 0000000..29722a1 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/scsi-modules +@@ -0,0 +1,4 @@ ++#include ++ ++ibmvscsic ++ps3rom +diff --git a/debian/installer/ppc64/modules/ppc64/serial-modules b/debian/installer/ppc64/modules/ppc64/serial-modules +new file mode 100644 +index 0000000..6ab8b8c +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/squashfs-modules b/debian/installer/ppc64/modules/ppc64/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/udf-modules b/debian/installer/ppc64/modules/ppc64/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/ufs-modules b/debian/installer/ppc64/modules/ppc64/ufs-modules +new file mode 100644 +index 0000000..69745ca +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/ufs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/uinput-modules b/debian/installer/ppc64/modules/ppc64/uinput-modules +new file mode 100644 +index 0000000..58a8337 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/uinput-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/usb-modules b/debian/installer/ppc64/modules/ppc64/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/usb-serial-modules b/debian/installer/ppc64/modules/ppc64/usb-serial-modules +new file mode 100644 +index 0000000..c0a0dc3 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/usb-serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/usb-storage-modules b/debian/installer/ppc64/modules/ppc64/usb-storage-modules +new file mode 100644 +index 0000000..272d95e +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/modules/ppc64/virtio-modules b/debian/installer/ppc64/modules/ppc64/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/ppc64/modules/ppc64/xfs-modules b/debian/installer/ppc64/modules/ppc64/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/ppc64/modules/ppc64/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/ppc64/package-list b/debian/installer/ppc64/package-list +new file mode 100644 +index 0000000..c112f51 +--- /dev/null ++++ b/debian/installer/ppc64/package-list +@@ -0,0 +1,42 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: ext2-modules ++Depends: kernel-image, core-modules ++ ++Package: ext3-modules ++Depends: kernel-image, core-modules ++ ++Package: ext4-modules ++Depends: kernel-image, core-modules ++ ++Package: pata-modules ++Depends: kernel-image, ata-modules, core-modules ++ ++Package: scsi-modules ++Depends: kernel-image, scsi-core-modules, parport-modules, cdrom-core-modules, core-modules, ata-modules ++ ++Package: pcmcia-modules ++Depends: kernel-image, core-modules ++ ++Package: nic-pcmcia-modules ++Depends: kernel-image, nic-modules, nic-shared-modules, nic-wireless-modules, pcmcia-modules, core-modules ++ ++Package: hypervisor-modules ++Depends: kernel-image ++Priority: standard ++Description: IBM 64bit hypervisor console modules ++ Contains drivers for the hypervisor console, used as console for linux ++ running in logical partitions of IBM hardware supporting it. ++ ++Package: fancontrol-modules ++Depends: kernel-image ++Priority: standard ++Description: Apple powermac fancontrol modules ++ Contains drivers for macintosh i2c bus as well as for the monitoring devices ++ connected to it. This allows to control the fans during installation. ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/s390/kernel-versions b/debian/installer/s390/kernel-versions +new file mode 100644 +index 0000000..d130e0e +--- /dev/null ++++ b/debian/installer/s390/kernel-versions +@@ -0,0 +1,3 @@ ++# arch version flavour installedname suffix build-depends ++s390 - s390x - - - ++s390 - s390x-tape - -tape - +diff --git a/debian/installer/s390/modules/s390x-tape/kernel-image b/debian/installer/s390/modules/s390x-tape/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x-tape/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/s390/modules/s390x/core-modules b/debian/installer/s390/modules/s390x/core-modules +new file mode 100644 +index 0000000..433f0a5 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/core-modules +@@ -0,0 +1,2 @@ ++vmcp ? ++mbcache +diff --git a/debian/installer/s390/modules/s390x/crypto-dm-modules b/debian/installer/s390/modules/s390x/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390/modules/s390x/crypto-modules b/debian/installer/s390/modules/s390x/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390/modules/s390x/dasd-extra-modules b/debian/installer/s390/modules/s390x/dasd-extra-modules +new file mode 100644 +index 0000000..ddd10cd +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/dasd-extra-modules +@@ -0,0 +1 @@ ++dasd_diag_mod +diff --git a/debian/installer/s390/modules/s390x/dasd-modules b/debian/installer/s390/modules/s390x/dasd-modules +new file mode 100644 +index 0000000..d3df219 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/dasd-modules +@@ -0,0 +1,2 @@ ++dasd_eckd_mod ++dasd_fba_mod +diff --git a/debian/installer/s390/modules/s390x/ext2-modules b/debian/installer/s390/modules/s390x/ext2-modules +new file mode 100644 +index 0000000..bbaebc8 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/ext2-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/s390/modules/s390x/ext3-modules b/debian/installer/s390/modules/s390x/ext3-modules +new file mode 100644 +index 0000000..55ef7d7 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/ext3-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/s390/modules/s390x/ext4-modules b/debian/installer/s390/modules/s390x/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390/modules/s390x/fat-modules b/debian/installer/s390/modules/s390x/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/s390/modules/s390x/fuse-modules b/debian/installer/s390/modules/s390x/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390/modules/s390x/kernel-image b/debian/installer/s390/modules/s390x/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/s390/modules/s390x/md-modules b/debian/installer/s390/modules/s390x/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/s390/modules/s390x/multipath-modules b/debian/installer/s390/modules/s390x/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390/modules/s390x/nbd-modules b/debian/installer/s390/modules/s390x/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390/modules/s390x/nic-modules b/debian/installer/s390/modules/s390x/nic-modules +new file mode 100644 +index 0000000..3205651 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/nic-modules +@@ -0,0 +1,6 @@ ++netiucv ++ctcm ++lcs ++qeth ++qeth_l2 ++qeth_l3 +diff --git a/debian/installer/s390/modules/s390x/scsi-core-modules b/debian/installer/s390/modules/s390x/scsi-core-modules +new file mode 100644 +index 0000000..3537f82 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/scsi-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/s390/modules/s390x/scsi-modules b/debian/installer/s390/modules/s390x/scsi-modules +new file mode 100644 +index 0000000..1f0171d +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/scsi-modules +@@ -0,0 +1 @@ ++zfcp +diff --git a/debian/installer/s390/modules/s390x/virtio-modules b/debian/installer/s390/modules/s390x/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390/modules/s390x/xfs-modules b/debian/installer/s390/modules/s390x/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/s390/modules/s390x/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/s390/package-list b/debian/installer/s390/package-list +new file mode 100644 +index 0000000..e480fba +--- /dev/null ++++ b/debian/installer/s390/package-list +@@ -0,0 +1,29 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: kernel-image ++ ++Package: dasd-modules ++Depends: kernel-image ++Priority: standard ++Description: dasd modules ++ This package contains dasd modules. ++ ++Package: dasd-extra-modules ++Depends: kernel-image, dasd-modules ++Priority: extra ++Description: optional dasd DIAG support ++ This package contains the module for dasd DIAG support. The udeb is ++ not loaded by default as the installer does not actually support this. ++ It can however be useful to have available in rescue situations. ++ ++Package: ext2-modules ++Depends: kernel-image, core-modules ++ ++Package: ext3-modules ++Depends: kernel-image, core-modules ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/s390x/kernel-versions b/debian/installer/s390x/kernel-versions +new file mode 100644 +index 0000000..dff5e12 +--- /dev/null ++++ b/debian/installer/s390x/kernel-versions +@@ -0,0 +1,3 @@ ++# arch version flavour installedname suffix build-depends ++s390x - s390x - - - ++s390x - s390x-tape - -tape - +diff --git a/debian/installer/s390x/modules/s390x-tape/kernel-image b/debian/installer/s390x/modules/s390x-tape/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x-tape/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/s390x/modules/s390x/core-modules b/debian/installer/s390x/modules/s390x/core-modules +new file mode 100644 +index 0000000..433f0a5 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/core-modules +@@ -0,0 +1,2 @@ ++vmcp ? ++mbcache +diff --git a/debian/installer/s390x/modules/s390x/crypto-dm-modules b/debian/installer/s390x/modules/s390x/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390x/modules/s390x/crypto-modules b/debian/installer/s390x/modules/s390x/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390x/modules/s390x/dasd-extra-modules b/debian/installer/s390x/modules/s390x/dasd-extra-modules +new file mode 100644 +index 0000000..ddd10cd +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/dasd-extra-modules +@@ -0,0 +1 @@ ++dasd_diag_mod +diff --git a/debian/installer/s390x/modules/s390x/dasd-modules b/debian/installer/s390x/modules/s390x/dasd-modules +new file mode 100644 +index 0000000..d3df219 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/dasd-modules +@@ -0,0 +1,2 @@ ++dasd_eckd_mod ++dasd_fba_mod +diff --git a/debian/installer/s390x/modules/s390x/ext2-modules b/debian/installer/s390x/modules/s390x/ext2-modules +new file mode 100644 +index 0000000..bbaebc8 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/ext2-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/s390x/modules/s390x/ext3-modules b/debian/installer/s390x/modules/s390x/ext3-modules +new file mode 100644 +index 0000000..55ef7d7 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/ext3-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/s390x/modules/s390x/ext4-modules b/debian/installer/s390x/modules/s390x/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390x/modules/s390x/fat-modules b/debian/installer/s390x/modules/s390x/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/s390x/modules/s390x/fuse-modules b/debian/installer/s390x/modules/s390x/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390x/modules/s390x/kernel-image b/debian/installer/s390x/modules/s390x/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/s390x/modules/s390x/md-modules b/debian/installer/s390x/modules/s390x/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/s390x/modules/s390x/multipath-modules b/debian/installer/s390x/modules/s390x/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390x/modules/s390x/nbd-modules b/debian/installer/s390x/modules/s390x/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390x/modules/s390x/nic-modules b/debian/installer/s390x/modules/s390x/nic-modules +new file mode 100644 +index 0000000..3205651 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/nic-modules +@@ -0,0 +1,6 @@ ++netiucv ++ctcm ++lcs ++qeth ++qeth_l2 ++qeth_l3 +diff --git a/debian/installer/s390x/modules/s390x/scsi-core-modules b/debian/installer/s390x/modules/s390x/scsi-core-modules +new file mode 100644 +index 0000000..3537f82 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/scsi-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/s390x/modules/s390x/scsi-modules b/debian/installer/s390x/modules/s390x/scsi-modules +new file mode 100644 +index 0000000..1f0171d +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/scsi-modules +@@ -0,0 +1 @@ ++zfcp +diff --git a/debian/installer/s390x/modules/s390x/virtio-modules b/debian/installer/s390x/modules/s390x/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/s390x/modules/s390x/xfs-modules b/debian/installer/s390x/modules/s390x/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/s390x/modules/s390x/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/s390x/package-list b/debian/installer/s390x/package-list +new file mode 100644 +index 0000000..e480fba +--- /dev/null ++++ b/debian/installer/s390x/package-list +@@ -0,0 +1,29 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: kernel-image ++ ++Package: dasd-modules ++Depends: kernel-image ++Priority: standard ++Description: dasd modules ++ This package contains dasd modules. ++ ++Package: dasd-extra-modules ++Depends: kernel-image, dasd-modules ++Priority: extra ++Description: optional dasd DIAG support ++ This package contains the module for dasd DIAG support. The udeb is ++ not loaded by default as the installer does not actually support this. ++ It can however be useful to have available in rescue situations. ++ ++Package: ext2-modules ++Depends: kernel-image, core-modules ++ ++Package: ext3-modules ++Depends: kernel-image, core-modules ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/sh4/kernel-versions b/debian/installer/sh4/kernel-versions +new file mode 100644 +index 0000000..b39e3cf +--- /dev/null ++++ b/debian/installer/sh4/kernel-versions +@@ -0,0 +1,3 @@ ++# arch version flavour installedname suffix build-depends ++sh4 - sh7751r - y - ++sh4 - sh7785lcr - y - +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/btrfs-modules b/debian/installer/sh4/modules/sh4-sh7751r/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/cdrom-core-modules b/debian/installer/sh4/modules/sh4-sh7751r/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/crc-modules b/debian/installer/sh4/modules/sh4-sh7751r/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/crypto-dm-modules b/debian/installer/sh4/modules/sh4-sh7751r/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/crypto-modules b/debian/installer/sh4/modules/sh4-sh7751r/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/ext2-modules b/debian/installer/sh4/modules/sh4-sh7751r/ext2-modules +new file mode 100644 +index 0000000..c407140 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/ext2-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/ext4-modules b/debian/installer/sh4/modules/sh4-sh7751r/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/fat-modules b/debian/installer/sh4/modules/sh4-sh7751r/fat-modules +new file mode 100644 +index 0000000..274584e +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/fat-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/firewire-core-modules b/debian/installer/sh4/modules/sh4-sh7751r/firewire-core-modules +new file mode 100644 +index 0000000..dcac80a +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/firewire-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/fuse-modules b/debian/installer/sh4/modules/sh4-sh7751r/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/i2c-modules b/debian/installer/sh4/modules/sh4-sh7751r/i2c-modules +new file mode 100644 +index 0000000..203a607 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/i2c-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/ipv6-modules b/debian/installer/sh4/modules/sh4-sh7751r/ipv6-modules +new file mode 100644 +index 0000000..1e3fc33 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/ipv6-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/isofs-modules b/debian/installer/sh4/modules/sh4-sh7751r/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/jfs-modules b/debian/installer/sh4/modules/sh4-sh7751r/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/kernel-image b/debian/installer/sh4/modules/sh4-sh7751r/kernel-image +new file mode 100644 +index 0000000..8b13789 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/kernel-image +@@ -0,0 +1 @@ ++ +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/loop-modules b/debian/installer/sh4/modules/sh4-sh7751r/loop-modules +new file mode 100644 +index 0000000..c1c948f +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/loop-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/md-modules b/debian/installer/sh4/modules/sh4-sh7751r/md-modules +new file mode 100644 +index 0000000..26115e1 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/md-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/minix-modules b/debian/installer/sh4/modules/sh4-sh7751r/minix-modules +new file mode 100644 +index 0000000..82b9843 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/minix-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/multipath-modules b/debian/installer/sh4/modules/sh4-sh7751r/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/nbd-modules b/debian/installer/sh4/modules/sh4-sh7751r/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/nic-modules b/debian/installer/sh4/modules/sh4-sh7751r/nic-modules +new file mode 100644 +index 0000000..67761a6 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/nic-modules +@@ -0,0 +1,6 @@ ++3c59x ? ++8139too ? ++e100 ? ++e1000 ? ++ne2k-pci ? ++r8169 ? +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/nic-usb-modules b/debian/installer/sh4/modules/sh4-sh7751r/nic-usb-modules +new file mode 100644 +index 0000000..c479669 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/nic-usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/parport-modules b/debian/installer/sh4/modules/sh4-sh7751r/parport-modules +new file mode 100644 +index 0000000..83966f7 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/parport-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/pata-modules b/debian/installer/sh4/modules/sh4-sh7751r/pata-modules +new file mode 100644 +index 0000000..b0cd633 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/pata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/ppp-modules b/debian/installer/sh4/modules/sh4-sh7751r/ppp-modules +new file mode 100644 +index 0000000..1f26aa1 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/ppp-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/reiserfs-modules b/debian/installer/sh4/modules/sh4-sh7751r/reiserfs-modules +new file mode 100644 +index 0000000..fad554f +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/reiserfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/sata-modules b/debian/installer/sh4/modules/sh4-sh7751r/sata-modules +new file mode 100644 +index 0000000..01318c2 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/sata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/scsi-core-modules b/debian/installer/sh4/modules/sh4-sh7751r/scsi-core-modules +new file mode 100644 +index 0000000..1fde8ee +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/scsi-core-modules +@@ -0,0 +1 @@ ++scsi_dh +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/sound-modules b/debian/installer/sh4/modules/sh4-sh7751r/sound-modules +new file mode 100644 +index 0000000..68395ab +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/sound-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/speakup-modules b/debian/installer/sh4/modules/sh4-sh7751r/speakup-modules +new file mode 100644 +index 0000000..2959272 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/speakup-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/squashfs-modules b/debian/installer/sh4/modules/sh4-sh7751r/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/udf-modules b/debian/installer/sh4/modules/sh4-sh7751r/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/ufs-modules b/debian/installer/sh4/modules/sh4-sh7751r/ufs-modules +new file mode 100644 +index 0000000..163ead0 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/ufs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/usb-serial-modules b/debian/installer/sh4/modules/sh4-sh7751r/usb-serial-modules +new file mode 100644 +index 0000000..c0a0dc3 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/usb-serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/usb-storage-modules b/debian/installer/sh4/modules/sh4-sh7751r/usb-storage-modules +new file mode 100644 +index 0000000..8c5e81b +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/usb-storage-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/virtio-modules b/debian/installer/sh4/modules/sh4-sh7751r/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/xfs-modules b/debian/installer/sh4/modules/sh4-sh7751r/xfs-modules +new file mode 100644 +index 0000000..98374e2 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/xfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7751r/zlib-modules b/debian/installer/sh4/modules/sh4-sh7751r/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7751r/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/btrfs-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/cdrom-core-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/crc-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/crc-modules +new file mode 100644 +index 0000000..7e00de7 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/crc-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/crypto-dm-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/crypto-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/ext2-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/ext2-modules +new file mode 100644 +index 0000000..c407140 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/ext2-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/ext4-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/fat-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/fat-modules +new file mode 100644 +index 0000000..274584e +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/fat-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/firewire-core-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/firewire-core-modules +new file mode 100644 +index 0000000..dcac80a +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/firewire-core-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/fuse-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/ipv6-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/ipv6-modules +new file mode 100644 +index 0000000..1e3fc33 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/ipv6-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/isofs-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/jfs-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/kernel-image b/debian/installer/sh4/modules/sh4-sh7785lcr/kernel-image +new file mode 100644 +index 0000000..8b13789 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/kernel-image +@@ -0,0 +1 @@ ++ +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/loop-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/loop-modules +new file mode 100644 +index 0000000..c1c948f +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/loop-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/md-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/md-modules +new file mode 100644 +index 0000000..26115e1 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/md-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/minix-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/minix-modules +new file mode 100644 +index 0000000..82b9843 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/minix-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/multipath-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/nbd-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/nic-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/nic-modules +new file mode 100644 +index 0000000..67761a6 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/nic-modules +@@ -0,0 +1,6 @@ ++3c59x ? ++8139too ? ++e100 ? ++e1000 ? ++ne2k-pci ? ++r8169 ? +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/nic-usb-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/nic-usb-modules +new file mode 100644 +index 0000000..c479669 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/nic-usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/parport-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/parport-modules +new file mode 100644 +index 0000000..83966f7 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/parport-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/pata-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/pata-modules +new file mode 100644 +index 0000000..b0cd633 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/pata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/ppp-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/ppp-modules +new file mode 100644 +index 0000000..1f26aa1 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/ppp-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/reiserfs-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/reiserfs-modules +new file mode 100644 +index 0000000..fad554f +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/reiserfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/sata-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/sata-modules +new file mode 100644 +index 0000000..01318c2 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/sata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/scsi-core-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/scsi-core-modules +new file mode 100644 +index 0000000..1fde8ee +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/scsi-core-modules +@@ -0,0 +1 @@ ++scsi_dh +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/sound-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/sound-modules +new file mode 100644 +index 0000000..68395ab +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/sound-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/speakup-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/speakup-modules +new file mode 100644 +index 0000000..2959272 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/speakup-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/squashfs-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/udf-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/ufs-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/ufs-modules +new file mode 100644 +index 0000000..163ead0 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/ufs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/usb-serial-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/usb-serial-modules +new file mode 100644 +index 0000000..c0a0dc3 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/usb-serial-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/xfs-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/xfs-modules +new file mode 100644 +index 0000000..98374e2 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/xfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/modules/sh4-sh7785lcr/zlib-modules b/debian/installer/sh4/modules/sh4-sh7785lcr/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/sh4/modules/sh4-sh7785lcr/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sh4/package-list b/debian/installer/sh4/package-list +new file mode 100644 +index 0000000..8e9a053 +--- /dev/null ++++ b/debian/installer/sh4/package-list +@@ -0,0 +1,19 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: kernel-image ++Provides: event-modules, ext3-modules, fb-modules, input-modules, mouse-modules, nic-shared-modules, rtc-modules, uinput-modules, usb-modules ++ ++Package: ext2-modules ++Depends: kernel-image, core-modules ++ ++Package: nic-modules ++Depends: kernel-image, core-modules, firewire-core-modules ++ ++Package: firewire-core-modules ++Depends: kernel-image, scsi-core-modules, crc-modules ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/sparc/kernel-versions b/debian/installer/sparc/kernel-versions +new file mode 100644 +index 0000000..4a9ad56 +--- /dev/null ++++ b/debian/installer/sparc/kernel-versions +@@ -0,0 +1,2 @@ ++# arch version flavour installedname suffix build-depends ++sparc - sparc64 - y - +diff --git a/debian/installer/sparc/modules/sparc/ata-modules b/debian/installer/sparc/modules/sparc/ata-modules +new file mode 100644 +index 0000000..b81c0f3 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/ata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/btrfs-modules b/debian/installer/sparc/modules/sparc/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/cdrom-core-modules b/debian/installer/sparc/modules/sparc/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc/modules/sparc/core-modules b/debian/installer/sparc/modules/sparc/core-modules +new file mode 100644 +index 0000000..ec6342b +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/core-modules +@@ -0,0 +1 @@ ++mbcache +diff --git a/debian/installer/sparc/modules/sparc/crypto-dm-modules b/debian/installer/sparc/modules/sparc/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/crypto-modules b/debian/installer/sparc/modules/sparc/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/ext2-modules b/debian/installer/sparc/modules/sparc/ext2-modules +new file mode 100644 +index 0000000..bbaebc8 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/ext2-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc/modules/sparc/ext3-modules b/debian/installer/sparc/modules/sparc/ext3-modules +new file mode 100644 +index 0000000..55ef7d7 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/ext3-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc/modules/sparc/ext4-modules b/debian/installer/sparc/modules/sparc/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/fat-modules b/debian/installer/sparc/modules/sparc/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc/modules/sparc/fuse-modules b/debian/installer/sparc/modules/sparc/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/input-modules b/debian/installer/sparc/modules/sparc/input-modules +new file mode 100644 +index 0000000..5ecb595 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/input-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/isofs-modules b/debian/installer/sparc/modules/sparc/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/jfs-modules b/debian/installer/sparc/modules/sparc/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/kernel-image b/debian/installer/sparc/modules/sparc/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/sparc/modules/sparc/md-modules b/debian/installer/sparc/modules/sparc/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc/modules/sparc/multipath-modules b/debian/installer/sparc/modules/sparc/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/nbd-modules b/debian/installer/sparc/modules/sparc/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/nic-modules b/debian/installer/sparc/modules/sparc/nic-modules +new file mode 100644 +index 0000000..171d878 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/nic-modules +@@ -0,0 +1,47 @@ ++3c59x ++8139too ++8390 ++b44 ++dl2k ++epic100 ++eql ++fealnx ++mii ++natsemi ++ne2k-pci ++ns83820 ++pcnet32 ++sis900 ++starfire ++sundance ++typhoon ++via-rhine ++yellowfin ++e100 ++e1000 ++e1000e ++skfp ++tg3 ++sungem ++sungem_phy ++tulip ++winbond-840 ++dmfe ++sunhme ++sunqe ++sunlance ++sunbmac ++myri_sbus ? ++cassini ++cxgb ++sis190 ++skge ++uli526x ++qla3xxx ++atl1 ++niu ++igb ++igbvf ++ ++# Support for virtual network devices under Sun Logical Domains. ++sunvnet ? +diff --git a/debian/installer/sparc/modules/sparc/pata-modules b/debian/installer/sparc/modules/sparc/pata-modules +new file mode 100644 +index 0000000..b0cd633 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/pata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/plip-modules b/debian/installer/sparc/modules/sparc/plip-modules +new file mode 100644 +index 0000000..eab43fa +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/plip-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc/modules/sparc/ppp-modules b/debian/installer/sparc/modules/sparc/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc/modules/sparc/reiserfs-modules b/debian/installer/sparc/modules/sparc/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc/modules/sparc/sata-modules b/debian/installer/sparc/modules/sparc/sata-modules +new file mode 100644 +index 0000000..01318c2 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/sata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/scsi-common-modules b/debian/installer/sparc/modules/sparc/scsi-common-modules +new file mode 100644 +index 0000000..2d8c1d9 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/scsi-common-modules +@@ -0,0 +1,9 @@ ++sun_esp ++aic79xx ++aic7xxx ++aic7xxx_old ++qlogicpti ? ++sym53c8xx ++mptsas ++mptspi ++mpt2sas +diff --git a/debian/installer/sparc/modules/sparc/scsi-core-modules b/debian/installer/sparc/modules/sparc/scsi-core-modules +new file mode 100644 +index 0000000..d1834e5 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/scsi-core-modules +@@ -0,0 +1,8 @@ ++#include ++scsi_transport_spi ++scsi_transport_sas ++ ++# Support for virtual disk devices as a client under Sun Logical Domains. ++# Does not really belong here, but it's better than adding a new kernel ++# udeb just for this module. ++sunvdc ? +diff --git a/debian/installer/sparc/modules/sparc/scsi-modules b/debian/installer/sparc/modules/sparc/scsi-modules +new file mode 100644 +index 0000000..e2f1eb8 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/scsi-modules +@@ -0,0 +1,19 @@ ++3w-9xxx ++3w-xxxx ++aacraid ++aic94xx ++arcmsr ++atp870u ? ++dc395x ++dmx3191d ++hptiop ++initio ++lpfc ++megaraid ++megaraid_sas ++osst ++ipr ++stex ++qla1280 ? ++qla2xxx ? ++qla4xxx ? +diff --git a/debian/installer/sparc/modules/sparc/squashfs-modules b/debian/installer/sparc/modules/sparc/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/udf-modules b/debian/installer/sparc/modules/sparc/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/usb-modules b/debian/installer/sparc/modules/sparc/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/usb-storage-modules b/debian/installer/sparc/modules/sparc/usb-storage-modules +new file mode 100644 +index 0000000..272d95e +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc/modules/sparc/virtio-modules b/debian/installer/sparc/modules/sparc/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/modules/sparc/xfs-modules b/debian/installer/sparc/modules/sparc/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc/modules/sparc/zlib-modules b/debian/installer/sparc/modules/sparc/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/sparc/modules/sparc/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc/package-list b/debian/installer/sparc/package-list +new file mode 100644 +index 0000000..a682580 +--- /dev/null ++++ b/debian/installer/sparc/package-list +@@ -0,0 +1,25 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: kernel-image ++ ++Package: ext2-modules ++Depends: kernel-image, core-modules ++ ++Package: ext3-modules ++Depends: kernel-image, core-modules ++ ++Package: nic-modules ++Priority: standard ++Description: Network card modules for Sparc kernels ++ This package contains the drivers for the Happy Meal/Big Mac 10/100BaseT, ++ Sun QuadEthernet and MyriCOM Gigabit Ethernet SBus devices for SPARC ++ systems, as well as various PCI NIC drivers (only on sparc64.) ++ . ++ Do not install this package on a real Debian system! You probably ++ want a kernel-image package instead. ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/installer/sparc64/kernel-versions b/debian/installer/sparc64/kernel-versions +new file mode 100644 +index 0000000..4811933 +--- /dev/null ++++ b/debian/installer/sparc64/kernel-versions +@@ -0,0 +1,2 @@ ++# arch version flavour installedname suffix build-depends ++sparc64 - sparc64 - y - +diff --git a/debian/installer/sparc64/modules/sparc64/ata-modules b/debian/installer/sparc64/modules/sparc64/ata-modules +new file mode 100644 +index 0000000..b81c0f3 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/ata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/btrfs-modules b/debian/installer/sparc64/modules/sparc64/btrfs-modules +new file mode 100644 +index 0000000..e261e13 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/btrfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/cdrom-core-modules b/debian/installer/sparc64/modules/sparc64/cdrom-core-modules +new file mode 100644 +index 0000000..e264d7a +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/cdrom-core-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc64/modules/sparc64/core-modules b/debian/installer/sparc64/modules/sparc64/core-modules +new file mode 100644 +index 0000000..ec6342b +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/core-modules +@@ -0,0 +1 @@ ++mbcache +diff --git a/debian/installer/sparc64/modules/sparc64/crypto-dm-modules b/debian/installer/sparc64/modules/sparc64/crypto-dm-modules +new file mode 100644 +index 0000000..4c8f235 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/crypto-dm-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/crypto-modules b/debian/installer/sparc64/modules/sparc64/crypto-modules +new file mode 100644 +index 0000000..3a1e862 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/crypto-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/ext2-modules b/debian/installer/sparc64/modules/sparc64/ext2-modules +new file mode 100644 +index 0000000..bbaebc8 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/ext2-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc64/modules/sparc64/ext3-modules b/debian/installer/sparc64/modules/sparc64/ext3-modules +new file mode 100644 +index 0000000..55ef7d7 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/ext3-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc64/modules/sparc64/ext4-modules b/debian/installer/sparc64/modules/sparc64/ext4-modules +new file mode 100644 +index 0000000..394c577 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/ext4-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/fat-modules b/debian/installer/sparc64/modules/sparc64/fat-modules +new file mode 100644 +index 0000000..cce8fd3 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/fat-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc64/modules/sparc64/fuse-modules b/debian/installer/sparc64/modules/sparc64/fuse-modules +new file mode 100644 +index 0000000..0b6ba0c +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/fuse-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/input-modules b/debian/installer/sparc64/modules/sparc64/input-modules +new file mode 100644 +index 0000000..5ecb595 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/input-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/isofs-modules b/debian/installer/sparc64/modules/sparc64/isofs-modules +new file mode 100644 +index 0000000..da4fa9a +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/isofs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/jfs-modules b/debian/installer/sparc64/modules/sparc64/jfs-modules +new file mode 100644 +index 0000000..7e4d912 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/jfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/kernel-image b/debian/installer/sparc64/modules/sparc64/kernel-image +new file mode 100644 +index 0000000..1bb8bf6 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/kernel-image +@@ -0,0 +1 @@ ++# empty +diff --git a/debian/installer/sparc64/modules/sparc64/md-modules b/debian/installer/sparc64/modules/sparc64/md-modules +new file mode 100644 +index 0000000..ade088d +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/md-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc64/modules/sparc64/multipath-modules b/debian/installer/sparc64/modules/sparc64/multipath-modules +new file mode 100644 +index 0000000..a8b69b2 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/multipath-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/nbd-modules b/debian/installer/sparc64/modules/sparc64/nbd-modules +new file mode 100644 +index 0000000..3c9b3e5 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/nbd-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/nic-modules b/debian/installer/sparc64/modules/sparc64/nic-modules +new file mode 100644 +index 0000000..171d878 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/nic-modules +@@ -0,0 +1,47 @@ ++3c59x ++8139too ++8390 ++b44 ++dl2k ++epic100 ++eql ++fealnx ++mii ++natsemi ++ne2k-pci ++ns83820 ++pcnet32 ++sis900 ++starfire ++sundance ++typhoon ++via-rhine ++yellowfin ++e100 ++e1000 ++e1000e ++skfp ++tg3 ++sungem ++sungem_phy ++tulip ++winbond-840 ++dmfe ++sunhme ++sunqe ++sunlance ++sunbmac ++myri_sbus ? ++cassini ++cxgb ++sis190 ++skge ++uli526x ++qla3xxx ++atl1 ++niu ++igb ++igbvf ++ ++# Support for virtual network devices under Sun Logical Domains. ++sunvnet ? +diff --git a/debian/installer/sparc64/modules/sparc64/pata-modules b/debian/installer/sparc64/modules/sparc64/pata-modules +new file mode 100644 +index 0000000..b0cd633 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/pata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/plip-modules b/debian/installer/sparc64/modules/sparc64/plip-modules +new file mode 100644 +index 0000000..eab43fa +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/plip-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc64/modules/sparc64/ppp-modules b/debian/installer/sparc64/modules/sparc64/ppp-modules +new file mode 100644 +index 0000000..f1ae9b3 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/ppp-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc64/modules/sparc64/reiserfs-modules b/debian/installer/sparc64/modules/sparc64/reiserfs-modules +new file mode 100644 +index 0000000..3726696 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/reiserfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc64/modules/sparc64/sata-modules b/debian/installer/sparc64/modules/sparc64/sata-modules +new file mode 100644 +index 0000000..01318c2 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/sata-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/scsi-common-modules b/debian/installer/sparc64/modules/sparc64/scsi-common-modules +new file mode 100644 +index 0000000..2d8c1d9 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/scsi-common-modules +@@ -0,0 +1,9 @@ ++sun_esp ++aic79xx ++aic7xxx ++aic7xxx_old ++qlogicpti ? ++sym53c8xx ++mptsas ++mptspi ++mpt2sas +diff --git a/debian/installer/sparc64/modules/sparc64/scsi-core-modules b/debian/installer/sparc64/modules/sparc64/scsi-core-modules +new file mode 100644 +index 0000000..d1834e5 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/scsi-core-modules +@@ -0,0 +1,8 @@ ++#include ++scsi_transport_spi ++scsi_transport_sas ++ ++# Support for virtual disk devices as a client under Sun Logical Domains. ++# Does not really belong here, but it's better than adding a new kernel ++# udeb just for this module. ++sunvdc ? +diff --git a/debian/installer/sparc64/modules/sparc64/scsi-modules b/debian/installer/sparc64/modules/sparc64/scsi-modules +new file mode 100644 +index 0000000..e2f1eb8 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/scsi-modules +@@ -0,0 +1,19 @@ ++3w-9xxx ++3w-xxxx ++aacraid ++aic94xx ++arcmsr ++atp870u ? ++dc395x ++dmx3191d ++hptiop ++initio ++lpfc ++megaraid ++megaraid_sas ++osst ++ipr ++stex ++qla1280 ? ++qla2xxx ? ++qla4xxx ? +diff --git a/debian/installer/sparc64/modules/sparc64/squashfs-modules b/debian/installer/sparc64/modules/sparc64/squashfs-modules +new file mode 100644 +index 0000000..42d7788 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/squashfs-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/udf-modules b/debian/installer/sparc64/modules/sparc64/udf-modules +new file mode 100644 +index 0000000..b90d7ee +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/udf-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/usb-modules b/debian/installer/sparc64/modules/sparc64/usb-modules +new file mode 100644 +index 0000000..c598ded +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/usb-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/usb-storage-modules b/debian/installer/sparc64/modules/sparc64/usb-storage-modules +new file mode 100644 +index 0000000..272d95e +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/usb-storage-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc64/modules/sparc64/virtio-modules b/debian/installer/sparc64/modules/sparc64/virtio-modules +new file mode 100644 +index 0000000..61da396 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/virtio-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/modules/sparc64/xfs-modules b/debian/installer/sparc64/modules/sparc64/xfs-modules +new file mode 100644 +index 0000000..c020b5d +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/xfs-modules +@@ -0,0 +1,2 @@ ++#include ++ +diff --git a/debian/installer/sparc64/modules/sparc64/zlib-modules b/debian/installer/sparc64/modules/sparc64/zlib-modules +new file mode 100644 +index 0000000..e02ad64 +--- /dev/null ++++ b/debian/installer/sparc64/modules/sparc64/zlib-modules +@@ -0,0 +1 @@ ++#include +diff --git a/debian/installer/sparc64/package-list b/debian/installer/sparc64/package-list +new file mode 100644 +index 0000000..a682580 +--- /dev/null ++++ b/debian/installer/sparc64/package-list +@@ -0,0 +1,25 @@ ++# This file is used to build up the control file. The kernel version and ++# "-di" are appended to the package names. Section can be left out. So can ++# architecture, which is derived from the files in the modules directory. ++# It overwrites specifications from /usr/share/kernel-wedge/package-list. ++# ++Package: kernel-image ++ ++Package: ext2-modules ++Depends: kernel-image, core-modules ++ ++Package: ext3-modules ++Depends: kernel-image, core-modules ++ ++Package: nic-modules ++Priority: standard ++Description: Network card modules for Sparc kernels ++ This package contains the drivers for the Happy Meal/Big Mac 10/100BaseT, ++ Sun QuadEthernet and MyriCOM Gigabit Ethernet SBus devices for SPARC ++ systems, as well as various PCI NIC drivers (only on sparc64.) ++ . ++ Do not install this package on a real Debian system! You probably ++ want a kernel-image package instead. ++ ++Package: nbd-modules ++Depends: kernel-image +diff --git a/debian/lib/python/debian_linux/__init__.py b/debian/lib/python/debian_linux/__init__.py +new file mode 100644 +index 0000000..b785ceb +--- /dev/null ++++ b/debian/lib/python/debian_linux/__init__.py +@@ -0,0 +1 @@ ++# Module +diff --git a/debian/lib/python/debian_linux/abi.py b/debian/lib/python/debian_linux/abi.py +new file mode 100644 +index 0000000..1dcf632 +--- /dev/null ++++ b/debian/lib/python/debian_linux/abi.py +@@ -0,0 +1,44 @@ ++class Symbol(object): ++ def __init__(self, name, module, version, export): ++ self.name, self.module = name, module ++ self.version, self.export = version, export ++ ++ def __eq__(self, other): ++ if not isinstance(other, Symbol): ++ return NotImplemented ++ ++ # Symbols are resolved to modules by depmod at installation/ ++ # upgrade time, not compile time, so moving a symbol between ++ # modules is not an ABI change. Compare everything else. ++ if self.name != other.name: ++ return False ++ if self.version != other.version: ++ return False ++ if self.export != other.export: ++ return False ++ ++ return True ++ ++ def __ne__(self, other): ++ ret = self.__eq__(other) ++ if ret is NotImplemented: ++ return ret ++ return not ret ++ ++ ++class Symbols(dict): ++ def __init__(self, file=None): ++ if file: ++ self.read(file) ++ ++ def read(self, file): ++ for line in file: ++ version, name, module, export = line.strip().split() ++ self[name] = Symbol(name, module, version, export) ++ ++ def write(self, file): ++ symbols = self.values() ++ symbols.sort(key=lambda i: i.name) ++ for s in symbols: ++ file.write("%s %s %s %s\n" % ++ (s.version, s.name, s.module, s.export)) +diff --git a/debian/lib/python/debian_linux/config.py b/debian/lib/python/debian_linux/config.py +new file mode 100644 +index 0000000..17211dd +--- /dev/null ++++ b/debian/lib/python/debian_linux/config.py +@@ -0,0 +1,249 @@ ++import os ++import os.path ++import re ++import sys ++import textwrap ++import cPickle ++ ++__all__ = [ ++ 'ConfigCoreDump', ++ 'ConfigCoreHierarchy', ++ 'ConfigParser', ++] ++ ++ ++class SchemaItemBoolean(object): ++ def __call__(self, i): ++ i = i.strip().lower() ++ if i in ("true", "1"): ++ return True ++ if i in ("false", "0"): ++ return False ++ raise Error ++ ++ ++class SchemaItemList(object): ++ def __init__(self, type="\s+"): ++ self.type = type ++ ++ def __call__(self, i): ++ i = i.strip() ++ if not i: ++ return [] ++ return [j.strip() for j in re.split(self.type, i)] ++ ++ ++class ConfigCore(dict): ++ def get_merge(self, section, arch, featureset, flavour, key, default=None): ++ temp = [] ++ ++ if arch and featureset and flavour: ++ temp.append(self.get((section, arch, featureset, flavour), {}).get(key)) ++ temp.append(self.get((section, arch, None, flavour), {}).get(key)) ++ if arch and featureset: ++ temp.append(self.get((section, arch, featureset), {}).get(key)) ++ if arch: ++ temp.append(self.get((section, arch), {}).get(key)) ++ if featureset: ++ temp.append(self.get((section, None, featureset), {}).get(key)) ++ temp.append(self.get((section,), {}).get(key)) ++ ++ ret = [] ++ ++ for i in temp: ++ if i is None: ++ continue ++ elif isinstance(i, (list, tuple)): ++ ret.extend(i) ++ elif ret: ++ # TODO ++ return ret ++ else: ++ return i ++ ++ return ret or default ++ ++ def merge(self, section, arch=None, featureset=None, flavour=None): ++ ret = {} ++ ret.update(self.get((section,), {})) ++ if featureset: ++ ret.update(self.get((section, None, featureset), {})) ++ if arch: ++ ret.update(self.get((section, arch), {})) ++ if arch and featureset: ++ ret.update(self.get((section, arch, featureset), {})) ++ if arch and featureset and flavour: ++ ret.update(self.get((section, arch, None, flavour), {})) ++ ret.update(self.get((section, arch, featureset, flavour), {})) ++ return ret ++ ++ def dump(self, fp): ++ cPickle.dump(self, fp, 0) ++ ++ ++class ConfigCoreDump(object): ++ def __new__(self, fp): ++ return cPickle.load(fp) ++ ++ ++class ConfigCoreHierarchy(object): ++ schema_base = { ++ 'base': { ++ 'arches': SchemaItemList(), ++ 'enabled': SchemaItemBoolean(), ++ 'featuresets': SchemaItemList(), ++ 'flavours': SchemaItemList(), ++ }, ++ } ++ ++ def __new__(cls, schema, dirs=[]): ++ schema_complete = cls.schema_base.copy() ++ for key, value in schema.iteritems(): ++ schema_complete.setdefault(key, {}).update(value) ++ return cls.Reader(dirs, schema_complete)() ++ ++ class Reader(object): ++ config_name = "defines" ++ ++ def __init__(self, dirs, schema): ++ self.dirs, self.schema = dirs, schema ++ ++ def __call__(self): ++ ret = ConfigCore() ++ self.read(ret) ++ return ret ++ ++ def get_files(self, *dirs): ++ dirs = list(dirs) ++ dirs.append(self.config_name) ++ return (os.path.join(i, *dirs) for i in self.dirs if i) ++ ++ def read_arch(self, ret, arch): ++ config = ConfigParser(self.schema) ++ config.read(self.get_files(arch)) ++ ++ featuresets = config['base', ].get('featuresets', []) ++ flavours = config['base', ].get('flavours', []) ++ ++ for section in iter(config): ++ if section[0] in featuresets: ++ real = (section[-1], arch, section[0]) ++ elif len(section) > 1: ++ real = (section[-1], arch, None) + section[:-1] ++ else: ++ real = (section[-1], arch) + section[:-1] ++ s = ret.get(real, {}) ++ s.update(config[section]) ++ ret[tuple(real)] = s ++ ++ for featureset in featuresets: ++ self.read_arch_featureset(ret, arch, featureset) ++ ++ if flavours: ++ base = ret['base', arch] ++ featuresets.insert(0, 'none') ++ base['featuresets'] = featuresets ++ del base['flavours'] ++ ret['base', arch] = base ++ ret['base', arch, 'none'] = {'flavours': flavours, 'implicit-flavour': True} ++ ++ def read_arch_featureset(self, ret, arch, featureset): ++ config = ConfigParser(self.schema) ++ config.read(self.get_files(arch, featureset)) ++ ++ flavours = config['base', ].get('flavours', []) ++ ++ for section in iter(config): ++ real = (section[-1], arch, featureset) + section[:-1] ++ s = ret.get(real, {}) ++ s.update(config[section]) ++ ret[tuple(real)] = s ++ ++ def read(self, ret): ++ config = ConfigParser(self.schema) ++ config.read(self.get_files()) ++ ++ arches = config['base', ]['arches'] ++ featuresets = config['base', ].get('featuresets', []) ++ ++ for section in iter(config): ++ if section[0].startswith('featureset-'): ++ real = (section[-1], None, section[0][11:]) ++ else: ++ real = (section[-1],) + section[1:] ++ ret[real] = config[section] ++ ++ for arch in arches: ++ self.read_arch(ret, arch) ++ for featureset in featuresets: ++ self.read_featureset(ret, featureset) ++ ++ def read_featureset(self, ret, featureset): ++ config = ConfigParser(self.schema) ++ config.read(self.get_files('featureset-%s' % featureset)) ++ ++ for section in iter(config): ++ real = (section[-1], None, featureset) ++ s = ret.get(real, {}) ++ s.update(config[section]) ++ ret[real] = s ++ ++ ++class ConfigParser(object): ++ __slots__ = '_config', 'schemas' ++ ++ def __init__(self, schemas): ++ self.schemas = schemas ++ ++ from ConfigParser import RawConfigParser ++ self._config = config = RawConfigParser() ++ ++ def __getitem__(self, key): ++ return self._convert()[key] ++ ++ def __iter__(self): ++ return iter(self._convert()) ++ ++ def __str__(self): ++ return '<%s(%s)>' % (self.__class__.__name__, self._convert()) ++ ++ def _convert(self): ++ ret = {} ++ for section in self._config.sections(): ++ data = {} ++ for key, value in self._config.items(section): ++ data[key] = value ++ section_list = section.split('_') ++ section_base = section_list[-1] ++ if section_base in self.schemas: ++ section_ret = tuple(section_list) ++ data = self._convert_one(self.schemas[section_base], data) ++ else: ++ section_ret = (section, ) ++ ret[section_ret] = data ++ return ret ++ ++ def _convert_one(self, schema, data): ++ ret = {} ++ for key, value in data.iteritems(): ++ if key in schema: ++ value = schema[key](value) ++ ret[key] = value ++ return ret ++ ++ def keys(self): ++ return self._convert().keys() ++ ++ def read(self, data): ++ return self._config.read(data) ++ ++ ++if __name__ == '__main__': ++ import sys ++ sys.path.append('debian/lib/python') ++ config = ConfigCoreDump(open('debian/config.defines.dump')) ++ for section, items in sorted(config.iteritems()): ++ print u"[%s]" % (section,) ++ for item, value in sorted(items.iteritems()): ++ print u"%s: %s" % (item, value) ++ print +diff --git a/debian/lib/python/debian_linux/debian.py b/debian/lib/python/debian_linux/debian.py +new file mode 100644 +index 0000000..7daaa03 +--- /dev/null ++++ b/debian/lib/python/debian_linux/debian.py +@@ -0,0 +1,427 @@ ++import collections ++import itertools ++import os.path ++import re ++ ++from . import utils ++ ++ ++class Changelog(list): ++ _rules = r""" ++^ ++(?P ++ \w[-+0-9a-z.]+ ++) ++\ ++\( ++(?P ++ [^\(\)\ \t]+ ++) ++\) ++\s+ ++(?P ++ [-+0-9a-zA-Z.]+ ++) ++\; ++""" ++ _re = re.compile(_rules, re.X) ++ ++ class Entry(object): ++ __slot__ = 'distribution', 'source', 'version' ++ ++ def __init__(self, distribution, source, version): ++ self.distribution, self.source, self.version = distribution, source, version ++ ++ def __init__(self, dir='', version=None): ++ if version is None: ++ version = Version ++ f = file(os.path.join(dir, "debian/changelog")) ++ while True: ++ line = f.readline() ++ if not line: ++ break ++ match = self._re.match(line) ++ if not match: ++ continue ++ try: ++ v = version(match.group('version')) ++ except Exception: ++ if not len(self): ++ raise ++ v = Version(match.group('version')) ++ self.append(self.Entry(match.group('distribution'), match.group('source'), v)) ++ ++ ++class Version(object): ++ _version_rules = ur""" ++^ ++(?: ++ (?P ++ \d+ ++ ) ++ : ++)? ++(?P ++ .+? ++) ++(?: ++ - ++ (?P[^-]+) ++)? ++$ ++""" ++ _version_re = re.compile(_version_rules, re.X) ++ ++ def __init__(self, version): ++ match = self._version_re.match(version) ++ if match is None: ++ raise RuntimeError(u"Invalid debian version") ++ self.epoch = None ++ if match.group("epoch") is not None: ++ self.epoch = int(match.group("epoch")) ++ self.upstream = match.group("upstream") ++ self.revision = match.group("revision") ++ ++ def __unicode__(self): ++ return self.complete ++ ++ @property ++ def complete(self): ++ if self.epoch is not None: ++ return u"%d:%s" % (self.epoch, self.complete_noepoch) ++ return self.complete_noepoch ++ ++ @property ++ def complete_noepoch(self): ++ if self.revision is not None: ++ return u"%s-%s" % (self.upstream, self.revision) ++ return self.upstream ++ ++ @property ++ def debian(self): ++ from warnings import warn ++ warn(u"debian argument was replaced by revision", DeprecationWarning, stacklevel=2) ++ return self.revision ++ ++ ++class VersionLinux(Version): ++ _version_linux_rules = ur""" ++^ ++(?P ++ \d+\.\d+ ++) ++(?P ++ \.\d+ ++)? ++(?: ++ ~ ++ (?P ++ .+? ++ ) ++)? ++(?: ++ \.dfsg\. ++ (?P ++ \d+ ++ ) ++)? ++- ++\d+ ++(\.\d+)? ++(?: ++ (?P ++ ~experimental\.\d+ ++ ) ++ | ++ (?P ++ [^-]+ ++ ) ++)? ++$ ++""" ++ _version_linux_re = re.compile(_version_linux_rules, re.X) ++ ++ def __init__(self, version): ++ super(VersionLinux, self).__init__(version) ++ match = self._version_linux_re.match(version) ++ if match is None: ++ raise RuntimeError(u"Invalid debian linux version") ++ d = match.groupdict() ++ self.linux_modifier = d['modifier'] ++ self.linux_version = d['version'] ++ if d['modifier'] is not None: ++ assert not d['update'] ++ self.linux_upstream = u'-'.join((d['version'], d['modifier'])) ++ else: ++ self.linux_upstream = d['version'] ++ self.linux_upstream_full = d['version'] + (d['update'] or u'') ++ self.linux_dfsg = d['dfsg'] ++ self.linux_revision_experimental = match.group('revision_experimental') and True ++ self.linux_revision_other = match.group('revision_other') and True ++ ++ ++class PackageArchitecture(collections.MutableSet): ++ __slots__ = '_data' ++ ++ def __init__(self, value=None): ++ self._data = set() ++ if value: ++ self.extend(value) ++ ++ def __contains__(self, value): ++ return self._data.__contains__(value) ++ ++ def __iter__(self): ++ return self._data.__iter__() ++ ++ def __len__(self): ++ return self._data.__len__() ++ ++ def __unicode__(self): ++ return u' '.join(sorted(self)) ++ ++ def add(self, value): ++ self._data.add(value) ++ ++ def discard(self, value): ++ self._data.discard(value) ++ ++ def extend(self, value): ++ if isinstance(value, basestring): ++ for i in re.split('\s', value.strip()): ++ self.add(i) ++ else: ++ raise RuntimeError ++ ++ ++class PackageDescription(object): ++ __slots__ = "short", "long" ++ ++ def __init__(self, value=None): ++ self.short = [] ++ self.long = [] ++ if value is not None: ++ short, long = value.split(u"\n", 1) ++ self.append(long) ++ self.append_short(short) ++ ++ def __unicode__(self): ++ wrap = utils.TextWrapper(width=74, fix_sentence_endings=True).wrap ++ short = u', '.join(self.short) ++ long_pars = [] ++ for i in self.long: ++ long_pars.append(wrap(i)) ++ long = u'\n .\n '.join([u'\n '.join(i) for i in long_pars]) ++ return short + u'\n ' + long ++ ++ def append(self, str): ++ str = str.strip() ++ if str: ++ self.long.extend(str.split(u"\n.\n")) ++ ++ def append_short(self, str): ++ for i in [i.strip() for i in str.split(u",")]: ++ if i: ++ self.short.append(i) ++ ++ def extend(self, desc): ++ if isinstance(desc, PackageDescription): ++ self.short.extend(desc.short) ++ self.long.extend(desc.long) ++ else: ++ raise TypeError ++ ++ ++class PackageRelation(list): ++ def __init__(self, value=None, override_arches=None): ++ if value: ++ self.extend(value, override_arches) ++ ++ def __unicode__(self): ++ return u', '.join((unicode(i) for i in self)) ++ ++ def _search_value(self, value): ++ for i in self: ++ if i._search_value(value): ++ return i ++ return None ++ ++ def append(self, value, override_arches=None): ++ if isinstance(value, basestring): ++ value = PackageRelationGroup(value, override_arches) ++ elif not isinstance(value, PackageRelationGroup): ++ raise ValueError(u"got %s" % type(value)) ++ j = self._search_value(value) ++ if j: ++ j._update_arches(value) ++ else: ++ super(PackageRelation, self).append(value) ++ ++ def extend(self, value, override_arches=None): ++ if isinstance(value, basestring): ++ value = (j.strip() for j in re.split(u',', value.strip())) ++ for i in value: ++ self.append(i, override_arches) ++ ++ ++class PackageRelationGroup(list): ++ def __init__(self, value=None, override_arches=None): ++ if value: ++ self.extend(value, override_arches) ++ ++ def __unicode__(self): ++ return u' | '.join((unicode(i) for i in self)) ++ ++ def _search_value(self, value): ++ for i, j in itertools.izip(self, value): ++ if i.name != j.name or i.version != j.version: ++ return None ++ return self ++ ++ def _update_arches(self, value): ++ for i, j in itertools.izip(self, value): ++ if i.arches: ++ for arch in j.arches: ++ if arch not in i.arches: ++ i.arches.append(arch) ++ ++ def append(self, value, override_arches=None): ++ if isinstance(value, basestring): ++ value = PackageRelationEntry(value, override_arches) ++ elif not isinstance(value, PackageRelationEntry): ++ raise ValueError ++ super(PackageRelationGroup, self).append(value) ++ ++ def extend(self, value, override_arches=None): ++ if isinstance(value, basestring): ++ value = (j.strip() for j in re.split('\|', value.strip())) ++ for i in value: ++ self.append(i, override_arches) ++ ++ ++class PackageRelationEntry(object): ++ __slots__ = "name", "operator", "version", "arches" ++ ++ _re = re.compile(r'^(\S+)(?: \((<<|<=|=|!=|>=|>>)\s*([^)]+)\))?(?: \[([^]]+)\])?$') ++ ++ class _operator(object): ++ OP_LT = 1 ++ OP_LE = 2 ++ OP_EQ = 3 ++ OP_NE = 4 ++ OP_GE = 5 ++ OP_GT = 6 ++ ++ operators = { ++ u'<<': OP_LT, ++ u'<=': OP_LE, ++ u'=': OP_EQ, ++ u'!=': OP_NE, ++ u'>=': OP_GE, ++ u'>>': OP_GT, ++ } ++ ++ operators_neg = { ++ OP_LT: OP_GE, ++ OP_LE: OP_GT, ++ OP_EQ: OP_NE, ++ OP_NE: OP_EQ, ++ OP_GE: OP_LT, ++ OP_GT: OP_LE, ++ } ++ ++ operators_text = dict([(b, a) for a, b in operators.iteritems()]) ++ ++ __slots__ = '_op', ++ ++ def __init__(self, value): ++ self._op = self.operators[value] ++ ++ def __neg__(self): ++ return self.__class__(self.operators_text[self.operators_neg[self._op]]) ++ ++ def __unicode__(self): ++ return self.operators_text[self._op] ++ ++ def __init__(self, value=None, override_arches=None): ++ if not isinstance(value, basestring): ++ raise ValueError ++ ++ self.parse(value) ++ ++ if override_arches: ++ self.arches = list(override_arches) ++ ++ def __unicode__(self): ++ ret = [self.name] ++ if self.operator is not None and self.version is not None: ++ ret.extend((u' (', unicode(self.operator), u' ', self.version, u')')) ++ if self.arches: ++ ret.extend((u' [', u' '.join(self.arches), u']')) ++ return u''.join(ret) ++ ++ def parse(self, value): ++ match = self._re.match(value) ++ if match is None: ++ raise RuntimeError(u"Can't parse dependency %s" % value) ++ match = match.groups() ++ self.name = match[0] ++ if match[1] is not None: ++ self.operator = self._operator(match[1]) ++ else: ++ self.operator = None ++ self.version = match[2] ++ if match[3] is not None: ++ self.arches = re.split('\s+', match[3]) ++ else: ++ self.arches = [] ++ ++ ++class Package(dict): ++ _fields = collections.OrderedDict(( ++ ('Package', unicode), ++ ('Source', unicode), ++ ('Architecture', PackageArchitecture), ++ ('Section', unicode), ++ ('Priority', unicode), ++ ('Maintainer', unicode), ++ ('Uploaders', unicode), ++ ('Standards-Version', unicode), ++ ('Build-Depends', PackageRelation), ++ ('Build-Depends-Indep', PackageRelation), ++ ('Provides', PackageRelation), ++ ('Pre-Depends', PackageRelation), ++ ('Depends', PackageRelation), ++ ('Recommends', PackageRelation), ++ ('Suggests', PackageRelation), ++ ('Replaces', PackageRelation), ++ ('Breaks', PackageRelation), ++ ('Conflicts', PackageRelation), ++ ('Description', PackageDescription), ++ )) ++ ++ def __setitem__(self, key, value): ++ try: ++ cls = self._fields[key] ++ if not isinstance(value, cls): ++ value = cls(value) ++ except KeyError: ++ pass ++ super(Package, self).__setitem__(key, value) ++ ++ def iterkeys(self): ++ keys = set(self.keys()) ++ for i in self._fields.iterkeys(): ++ if i in self: ++ keys.remove(i) ++ yield i ++ for i in keys: ++ yield i ++ ++ def iteritems(self): ++ for i in self.iterkeys(): ++ yield (i, self[i]) ++ ++ def itervalues(self): ++ for i in self.iterkeys(): ++ yield self[i] +diff --git a/debian/lib/python/debian_linux/firmware.py b/debian/lib/python/debian_linux/firmware.py +new file mode 100644 +index 0000000..ece3743 +--- /dev/null ++++ b/debian/lib/python/debian_linux/firmware.py +@@ -0,0 +1,89 @@ ++import re ++ ++ ++class FirmwareFile(object): ++ def __init__(self, binary, desc=None, source=None, version=None): ++ self.binary = binary ++ self.desc = desc ++ self.source = source ++ self.version = version ++ ++ ++class FirmwareSection(object): ++ def __init__(self, driver, files, licence): ++ self.driver = driver ++ self.files = files ++ self.licence = licence ++ ++ ++class FirmwareWhence(list): ++ def __init__(self, file): ++ self.read(file) ++ ++ def read(self, file): ++ in_header = True ++ driver = None ++ files = {} ++ licence = None ++ binary = [] ++ desc = None ++ source = [] ++ version = None ++ ++ for line in file: ++ if line.startswith('----------'): ++ if in_header: ++ in_header = False ++ else: ++ # Finish old section ++ if driver: ++ self.append(FirmwareSection(driver, files, licence)) ++ driver = None ++ files = {} ++ licence = None ++ continue ++ ++ if in_header: ++ continue ++ ++ if line == '\n': ++ # End of field; end of file fields ++ for b in binary: ++ # XXX The WHENCE file isn't yet consistent in its ++ # association of binaries and their sources and ++ # metadata. This associates all sources and ++ # metadata in a group with each binary. ++ files[b] = FirmwareFile(b, desc, source, version) ++ binary = [] ++ desc = None ++ source = [] ++ version = None ++ continue ++ ++ match = re.match( ++ r'(Driver|File|Info|Licen[cs]e|Source|Version' ++ r'|Original licen[cs]e info(?:rmation)?):\s*(.*)\n', ++ line) ++ if match: ++ keyword, value = match.group(1, 2) ++ if keyword == 'Driver': ++ driver = value.split(' ')[0].lower() ++ elif keyword == 'File': ++ match = re.match(r'(\S+)(?:\s+--\s+(.*))?', value) ++ binary.append(match.group(1)) ++ desc = match.group(2) ++ elif keyword in ['Info', 'Version']: ++ version = value ++ elif keyword == 'Source': ++ source.append(value) ++ else: ++ licence = value ++ elif licence is not None: ++ licence = (licence + '\n' + ++ re.sub(r'^(?:[/ ]\*| \*/)?\s*(.*?)\s*$', r'\1', line)) ++ ++ # Finish last section if non-empty ++ for b in binary: ++ files[b] = FirmwareFile(b, desc, source, version) ++ if driver: ++ self.append(FirmwareSection(driver, files, licence)) +diff --git a/debian/lib/python/debian_linux/gencontrol.py b/debian/lib/python/debian_linux/gencontrol.py +new file mode 100644 +index 0000000..aac564c +--- /dev/null ++++ b/debian/lib/python/debian_linux/gencontrol.py +@@ -0,0 +1,306 @@ ++import codecs ++from collections import OrderedDict ++ ++from .debian import * ++ ++ ++class PackagesList(OrderedDict): ++ def append(self, package): ++ self[package['Package']] = package ++ ++ def extend(self, packages): ++ for package in packages: ++ self[package['Package']] = package ++ ++ ++class Makefile(object): ++ def __init__(self): ++ self.rules = {} ++ self.add('.NOTPARALLEL') ++ ++ def add(self, name, deps=None, cmds=None): ++ if name in self.rules: ++ self.rules[name].add(deps, cmds) ++ else: ++ self.rules[name] = self.Rule(name, deps, cmds) ++ if deps is not None: ++ for i in deps: ++ if i not in self.rules: ++ self.rules[i] = self.Rule(i) ++ ++ def write(self, out): ++ r = self.rules.keys() ++ r.sort() ++ for i in r: ++ self.rules[i].write(out) ++ ++ class Rule(object): ++ def __init__(self, name, deps=None, cmds=None): ++ self.name = name ++ self.deps, self.cmds = set(), [] ++ self.add(deps, cmds) ++ ++ def add(self, deps=None, cmds=None): ++ if deps is not None: ++ self.deps.update(deps) ++ if cmds is not None: ++ self.cmds.append(cmds) ++ ++ def write(self, out): ++ deps_string = '' ++ if self.deps: ++ deps = list(self.deps) ++ deps.sort() ++ deps_string = ' ' + ' '.join(deps) ++ ++ if self.cmds: ++ if deps_string: ++ out.write('%s::%s\n' % (self.name, deps_string)) ++ for c in self.cmds: ++ out.write('%s::\n' % self.name) ++ for i in c: ++ out.write('\t%s\n' % i) ++ else: ++ out.write('%s:%s\n' % (self.name, deps_string)) ++ ++ ++class MakeFlags(dict): ++ def __repr__(self): ++ repr = super(flags, self).__repr__() ++ return "%s(%s)" % (self.__class__.__name__, repr) ++ ++ def __str__(self): ++ return ' '.join(["%s='%s'" % i for i in sorted(self.iteritems())]) ++ ++ def copy(self): ++ return self.__class__(super(MakeFlags, self).copy()) ++ ++ ++class Gencontrol(object): ++ makefile_targets = ('binary-arch', 'build-arch', 'setup') ++ ++ def __init__(self, config, templates, version=Version): ++ self.config, self.templates = config, templates ++ self.changelog = Changelog(version=version) ++ ++ def __call__(self): ++ packages = PackagesList() ++ makefile = Makefile() ++ ++ self.do_source(packages) ++ self.do_main(packages, makefile) ++ self.do_extra(packages, makefile) ++ ++ self.write(packages, makefile) ++ ++ def do_source(self, packages): ++ source = self.templates["control.source"][0] ++ source['Source'] = self.changelog[0].source ++ packages['source'] = self.process_package(source) ++ ++ def do_main(self, packages, makefile): ++ config_entry = self.config['base', ] ++ vars = self.vars.copy() ++ ++ makeflags = MakeFlags() ++ extra = {} ++ ++ self.do_main_setup(vars, makeflags, extra) ++ self.do_main_makefile(makefile, makeflags, extra) ++ self.do_main_packages(packages, vars, makeflags, extra) ++ self.do_main_recurse(packages, makefile, vars, makeflags, extra) ++ ++ def do_main_setup(self, vars, makeflags, extra): ++ pass ++ ++ def do_main_makefile(self, makefile, makeflags, extra): ++ makefile.add('build-indep', cmds=["$(MAKE) -f debian/rules.real build-indep %s" % makeflags]) ++ makefile.add('binary-indep', cmds=["$(MAKE) -f debian/rules.real binary-indep %s" % makeflags]) ++ ++ def do_main_packages(self, packages, vars, makeflags, extra): ++ pass ++ ++ def do_main_recurse(self, packages, makefile, vars, makeflags, extra): ++ for arch in iter(self.config['base', ]['arches']): ++ self.do_arch(packages, makefile, arch, vars.copy(), makeflags.copy(), extra) ++ ++ def do_extra(self, packages, makefile): ++ templates_extra = self.templates.get("control.extra", None) ++ if templates_extra is None: ++ return ++ ++ packages.extend(self.process_packages(templates_extra, {})) ++ extra_arches = {} ++ for package in templates_extra: ++ arches = package['Architecture'] ++ for arch in arches: ++ i = extra_arches.get(arch, []) ++ i.append(package) ++ extra_arches[arch] = i ++ archs = extra_arches.keys() ++ archs.sort() ++ for arch in archs: ++ cmds = [] ++ for i in extra_arches[arch]: ++ tmp = [] ++ if 'X-Version-Overwrite-Epoch' in i: ++ tmp.append("-v1:%s" % self.version['source']) ++ cmds.append("$(MAKE) -f debian/rules.real install-dummy DH_OPTIONS='-p%s' GENCONTROL_ARGS='%s'" % (i['Package'], ' '.join(tmp))) ++ makefile.add('binary-arch_%s' % arch['binary-arch_%s_extra' % arch]) ++ makefile.add("binary-arch_%s_extra" % arch, cmds=cmds) ++ ++ def do_arch(self, packages, makefile, arch, vars, makeflags, extra): ++ vars['arch'] = arch ++ ++ self.do_arch_setup(vars, makeflags, arch, extra) ++ self.do_arch_makefile(makefile, arch, makeflags, extra) ++ self.do_arch_packages(packages, makefile, arch, vars, makeflags, extra) ++ self.do_arch_recurse(packages, makefile, arch, vars, makeflags, extra) ++ ++ def do_arch_setup(self, vars, makeflags, arch, extra): ++ pass ++ ++ def do_arch_makefile(self, makefile, arch, makeflags, extra): ++ makeflags['ARCH'] = arch ++ ++ for i in self.makefile_targets: ++ target1 = i ++ target2 = '_'.join((target1, arch)) ++ target3 = '_'.join((target2, 'real')) ++ makefile.add(target1, [target2]) ++ makefile.add(target2, [target3]) ++ ++ def do_arch_packages(self, packages, makefile, arch, vars, makeflags, extra): ++ pass ++ ++ def do_arch_recurse(self, packages, makefile, arch, vars, makeflags, extra): ++ for featureset in self.config['base', arch].get('featuresets', ()): ++ self.do_featureset(packages, makefile, arch, featureset, vars.copy(), makeflags.copy(), extra) ++ ++ def do_featureset(self, packages, makefile, arch, featureset, vars, makeflags, extra): ++ config_base = self.config.merge('base', arch, featureset) ++ if not config_base.get('enabled', True): ++ return ++ ++ vars['localversion'] = '' ++ if featureset != 'none': ++ vars['localversion'] = '-' + featureset ++ ++ self.do_featureset_setup(vars, makeflags, arch, featureset, extra) ++ self.do_featureset_makefile(makefile, arch, featureset, makeflags, extra) ++ self.do_featureset_packages(packages, makefile, arch, featureset, vars, makeflags, extra) ++ self.do_featureset_recurse(packages, makefile, arch, featureset, vars, makeflags, extra) ++ ++ def do_featureset_setup(self, vars, makeflags, arch, featureset, extra): ++ pass ++ ++ def do_featureset_makefile(self, makefile, arch, featureset, makeflags, extra): ++ makeflags['FEATURESET'] = featureset ++ ++ for i in self.makefile_targets: ++ target1 = '_'.join((i, arch)) ++ target2 = '_'.join((target1, featureset)) ++ target3 = '_'.join((target2, 'real')) ++ makefile.add(target1, [target2]) ++ makefile.add(target2, [target3]) ++ ++ def do_featureset_packages(self, packages, makefile, arch, featureset, vars, makeflags, extra): ++ pass ++ ++ def do_featureset_recurse(self, packages, makefile, arch, featureset, vars, makeflags, extra): ++ for flavour in self.config['base', arch, featureset]['flavours']: ++ self.do_flavour(packages, makefile, arch, featureset, flavour, vars.copy(), makeflags.copy(), extra) ++ ++ def do_flavour(self, packages, makefile, arch, featureset, flavour, vars, makeflags, extra): ++ config_base = self.config.merge('base', arch, featureset, flavour) ++ ++ vars['localversion'] += '-' + flavour ++ ++ self.do_flavour_setup(vars, makeflags, arch, featureset, flavour, extra) ++ self.do_flavour_makefile(makefile, arch, featureset, flavour, makeflags, extra) ++ self.do_flavour_packages(packages, makefile, arch, featureset, flavour, vars, makeflags, extra) ++ ++ def do_flavour_setup(self, vars, makeflags, arch, featureset, flavour, extra): ++ for i in ( ++ ('kernel-arch', 'KERNEL_ARCH'), ++ ('localversion', 'LOCALVERSION'), ++ ): ++ if i[0] in vars: ++ makeflags[i[1]] = vars[i[0]] ++ ++ def do_flavour_makefile(self, makefile, arch, featureset, flavour, makeflags, extra): ++ makeflags['FLAVOUR'] = flavour ++ ++ for i in self.makefile_targets: ++ target1 = '_'.join((i, arch, featureset)) ++ target2 = '_'.join((target1, flavour)) ++ target3 = '_'.join((target2, 'real')) ++ makefile.add(target1, [target2]) ++ makefile.add(target2, [target3]) ++ ++ def do_flavour_packages(self, packages, makefile, arch, featureset, flavour, vars, makeflags, extra): ++ pass ++ ++ def process_relation(self, dep, vars): ++ import copy ++ dep = copy.deepcopy(dep) ++ for groups in dep: ++ for item in groups: ++ item.name = self.substitute(item.name, vars) ++ if item.version: ++ item.version = self.substitute(item.version, vars) ++ return dep ++ ++ def process_description(self, in_desc, vars): ++ desc = in_desc.__class__() ++ desc.short = self.substitute(in_desc.short, vars) ++ for i in in_desc.long: ++ desc.append(self.substitute(i, vars)) ++ return desc ++ ++ def process_package(self, in_entry, vars={}): ++ entry = in_entry.__class__() ++ for key, value in in_entry.iteritems(): ++ if isinstance(value, PackageRelation): ++ value = self.process_relation(value, vars) ++ elif isinstance(value, PackageDescription): ++ value = self.process_description(value, vars) ++ else: ++ value = self.substitute(value, vars) ++ entry[key] = value ++ return entry ++ ++ def process_packages(self, entries, vars): ++ return [self.process_package(i, vars) for i in entries] ++ ++ def substitute(self, s, vars): ++ if isinstance(s, (list, tuple)): ++ return [self.substitute(i, vars) for i in s] ++ ++ def subst(match): ++ return vars[match.group(1)] ++ ++ return re.sub(r'@([-_a-z]+)@', subst, unicode(s)) ++ ++ def write(self, packages, makefile): ++ self.write_control(packages.itervalues()) ++ self.write_makefile(makefile) ++ ++ def write_config(self): ++ f = file("debian/config.dump", 'w') ++ self.config.write(f) ++ f.close() ++ ++ def write_control(self, list): ++ self.write_rfc822(codecs.open("debian/control", 'w', 'utf-8'), list) ++ ++ def write_makefile(self, makefile): ++ f = file("debian/rules.gen", 'w') ++ makefile.write(f) ++ f.close() ++ ++ def write_rfc822(self, f, list): ++ for entry in list: ++ for key, value in entry.iteritems(): ++ f.write(u"%s: %s\n" % (key, value)) ++ f.write(u'\n') +diff --git a/debian/lib/python/debian_linux/kconfig.py b/debian/lib/python/debian_linux/kconfig.py +new file mode 100644 +index 0000000..23e459a +--- /dev/null ++++ b/debian/lib/python/debian_linux/kconfig.py +@@ -0,0 +1,77 @@ ++from collections import OrderedDict ++ ++__all__ = ( ++ "KconfigFile", ++) ++ ++ ++class EntryString(object): ++ __slots__ = "name", "value" ++ ++ def __init__(self, name, value): ++ self.name = name ++ self.value = value ++ ++ def __str__(self): ++ return "CONFIG_%s=%s" % (self.name, self.value) ++ ++ ++class EntryTristate(object): ++ __slots__ = "name", "value" ++ ++ VALUE_NO = 0 ++ VALUE_YES = 1 ++ VALUE_MOD = 2 ++ ++ def __init__(self, name, value=None): ++ self.name = name ++ if value == 'n' or value is None: ++ self.value = self.VALUE_NO ++ elif value == 'y': ++ self.value = self.VALUE_YES ++ elif value == 'm': ++ self.value = self.VALUE_MOD ++ ++ def __str__(self): ++ conf = "CONFIG_%s" % self.name ++ if self.value == self.VALUE_NO: ++ return "# %s is not set" % conf ++ elif self.value == self.VALUE_YES: ++ return "%s=y" % conf ++ elif self.value == self.VALUE_MOD: ++ return "%s=m" % conf ++ ++ ++class KconfigFile(OrderedDict): ++ def __str__(self): ++ ret = [] ++ for i in self.str_iter(): ++ ret.append(i) ++ return '\n'.join(ret) + '\n' ++ ++ def read(self, f): ++ for line in iter(f.readlines()): ++ line = line.strip() ++ if line.startswith("CONFIG_"): ++ i = line.find('=') ++ option = line[7:i] ++ value = line[i + 1:] ++ self.set(option, value) ++ elif line.startswith("# CONFIG_"): ++ option = line[9:-11] ++ self.set(option, 'n') ++ elif line.startswith("#") or not line: ++ pass ++ else: ++ raise RuntimeError("Can't recognize %s" % line) ++ ++ def set(self, key, value): ++ if value in ('y', 'm', 'n'): ++ entry = EntryTristate(key, value) ++ else: ++ entry = EntryString(key, value) ++ self[key] = entry ++ ++ def str_iter(self): ++ for key, value in self.iteritems(): ++ yield str(value) +diff --git a/debian/lib/python/debian_linux/patches.py b/debian/lib/python/debian_linux/patches.py +new file mode 100644 +index 0000000..2f0737b +--- /dev/null ++++ b/debian/lib/python/debian_linux/patches.py +@@ -0,0 +1,190 @@ ++import glob ++import os ++import shutil ++ ++ ++class Operation(object): ++ def __init__(self, name, data): ++ self.name, self.data = name, data ++ ++ def __call__(self, dir='.', reverse=False): ++ try: ++ if not reverse: ++ self.do(dir) ++ else: ++ self.do_reverse(dir) ++ self._log(True) ++ except: ++ self._log(False) ++ raise ++ ++ def _log(self, result): ++ if result: ++ s = "OK" ++ else: ++ s = "FAIL" ++ print """ (%s) %-4s %s""" % (self.operation, s, self.name) ++ ++ def do(self, dir): ++ raise NotImplementedError ++ ++ def do_reverse(self, dir): ++ raise NotImplementedError ++ ++ ++class OperationPatch(Operation): ++ def __init__(self, name, fopen, data): ++ super(OperationPatch, self).__init__(name, data) ++ self.fopen = fopen ++ ++ def _call(self, dir, extraargs): ++ cmdline = "cd %s; patch -p1 -f -s -t --no-backup-if-mismatch %s" % (dir, extraargs) ++ f = os.popen(cmdline, 'wb') ++ shutil.copyfileobj(self.fopen(), f) ++ if f.close(): ++ raise RuntimeError("Patch failed") ++ ++ def patch_push(self, dir): ++ self._call(dir, '--fuzz=1') ++ ++ def patch_pop(self, dir): ++ self._call(dir, '-R') ++ ++ ++class OperationPatchPush(OperationPatch): ++ operation = '+' ++ ++ do = OperationPatch.patch_push ++ do_reverse = OperationPatch.patch_pop ++ ++ ++class OperationPatchPop(OperationPatch): ++ operation = '-' ++ ++ do = OperationPatch.patch_pop ++ do_reverse = OperationPatch.patch_push ++ ++ ++class SubOperation(Operation): ++ def _log(self, result): ++ if result: ++ s = "OK" ++ else: ++ s = "FAIL" ++ print """ %-10s %-4s %s""" % ('(%s)' % self.operation, s, self.name) ++ ++ ++class SubOperationFilesRemove(SubOperation): ++ operation = "remove" ++ ++ def do(self, dir): ++ name = os.path.join(dir, self.name) ++ for n in glob.iglob(name): ++ if os.path.isdir(n): ++ shutil.rmtree(n) ++ else: ++ os.unlink(n) ++ ++ ++class SubOperationFilesUnifdef(SubOperation): ++ operation = "unifdef" ++ ++ def do(self, dir): ++ filename = os.path.join(dir, self.name) ++ cmdline = "unifdef %s %s" % (filename, ' '.join(self.data)) ++ f = os.popen(cmdline, 'rb') ++ data = f.read() ++ ret = f.close() ++ if ret is None: ++ raise RuntimeError("unifdef of %s removed nothing" % self.name) ++ elif ret != 256: ++ raise RuntimeError("unifdef failed") ++ f1 = file(filename, 'wb') ++ f1.write(data) ++ f1.close() ++ ++ ++class OperationFiles(Operation): ++ operation = 'X' ++ ++ suboperations = { ++ 'remove': SubOperationFilesRemove, ++ 'rm': SubOperationFilesRemove, ++ 'unifdef': SubOperationFilesUnifdef, ++ } ++ ++ def __init__(self, name, fopen, data): ++ super(OperationFiles, self).__init__(name, data) ++ ++ ops = [] ++ ++ for line in fopen(): ++ line = line.strip() ++ if not line or line[0] == '#': ++ continue ++ ++ items = line.split() ++ operation, filename = items[:2] ++ data = items[2:] ++ ++ if operation not in self.suboperations: ++ raise RuntimeError('Undefined operation "%s" in series %s' % (operation, name)) ++ ++ ops.append(self.suboperations[operation](filename, data)) ++ ++ self.ops = ops ++ ++ def do(self, dir): ++ for i in self.ops: ++ i(dir=dir) ++ ++ ++class PatchSeries(list): ++ operations = { ++ '+': OperationPatchPush, ++ '-': OperationPatchPop, ++ 'X': OperationFiles, ++ } ++ ++ def __init__(self, name, root, fp): ++ self.name, self.root = name, root ++ ++ from gzip import GzipFile ++ from bz2 import BZ2File ++ ++ for line in fp: ++ line = line.strip() ++ ++ if not len(line) or line[0] == '#': ++ continue ++ ++ items = line.split(' ') ++ operation, filename = items[:2] ++ data = items[2:] ++ ++ if operation in self.operations: ++ f = os.path.join(self.root, filename) ++ for suffix, cls in (('', file), ('.bz2', BZ2File), ('.gz', GzipFile)): ++ f1 = f + suffix ++ if os.path.exists(f1): ++ # Must copy current bindings into the lambda-function ++ fopen = lambda cls=cls, f1=f1: cls(f1) ++ break ++ else: ++ raise RuntimeError("Can't find patch %s for series %s" % (filename, self.name)) ++ else: ++ raise RuntimeError('Undefined operation "%s" in series %s' % (operation, name)) ++ ++ self.append(self.operations[operation](filename, fopen, data)) ++ ++ def __call__(self, cond=bool, dir='.', reverse=False): ++ if not reverse: ++ l = self ++ else: ++ l = self[::-1] ++ for i in l: ++ if cond(i): ++ i(dir=dir, reverse=reverse) ++ ++ def __repr__(self): ++ return '<%s object for %s>' % (self.__class__.__name__, self.name) +diff --git a/debian/lib/python/debian_linux/utils.py b/debian/lib/python/debian_linux/utils.py +new file mode 100644 +index 0000000..563104e +--- /dev/null ++++ b/debian/lib/python/debian_linux/utils.py +@@ -0,0 +1,81 @@ ++import codecs ++import os ++import re ++import textwrap ++ ++ ++class Templates(object): ++ def __init__(self, dirs=["debian/templates"]): ++ self.dirs = dirs ++ ++ self._cache = {} ++ ++ def __getitem__(self, key): ++ ret = self.get(key) ++ if ret is not None: ++ return ret ++ raise KeyError(key) ++ ++ def _read(self, name): ++ prefix, id = name.split('.', 1) ++ ++ for dir in self.dirs: ++ filename = "%s/%s.in" % (dir, name) ++ if os.path.exists(filename): ++ f = codecs.open(filename, 'r', 'utf-8') ++ if prefix == 'control': ++ return read_control(f) ++ return f.read() ++ ++ def get(self, key, default=None): ++ if key in self._cache: ++ return self._cache[key] ++ ++ value = self._cache.setdefault(key, self._read(key)) ++ if value is None: ++ return default ++ return value ++ ++ ++def read_control(f): ++ from .debian import Package ++ ++ entries = [] ++ eof = False ++ ++ while not eof: ++ e = Package() ++ last = None ++ lines = [] ++ while True: ++ line = f.readline() ++ if not line: ++ eof = True ++ break ++ line = line.strip('\n') ++ if not line: ++ break ++ if line[0] in ' \t': ++ if not last: ++ raise ValueError(u'Continuation line seen before first header') ++ lines.append(line.lstrip()) ++ continue ++ if last: ++ e[last] = u'\n'.join(lines) ++ i = line.find(':') ++ if i < 0: ++ raise ValueError(u"Not a header, not a continuation: ``%s''" % line) ++ last = line[:i] ++ lines = [line[i + 1:].lstrip()] ++ if last: ++ e[last] = '\n'.join(lines) ++ if e: ++ entries.append(e) ++ ++ return entries ++ ++ ++class TextWrapper(textwrap.TextWrapper): ++ wordsep_re = re.compile( ++ r'(\s+|' # any whitespace ++ r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash +diff --git a/debian/po/POTFILES.in b/debian/po/POTFILES.in +new file mode 100644 +index 0000000..cff14fd +--- /dev/null ++++ b/debian/po/POTFILES.in +@@ -0,0 +1 @@ ++[type: gettext/rfc822deb] templates/temp.image.plain/templates +diff --git a/debian/po/ca.po b/debian/po/ca.po +new file mode 100644 +index 0000000..dd82e27 +--- /dev/null ++++ b/debian/po/ca.po +@@ -0,0 +1,129 @@ ++# Catalan translation of linux debconf templates. ++# Copyright © 2010 Software in the Public Interest, Inc. ++# This file is distributed under the same license as linux's packaging. ++# Jordi Mallach , 2010. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: linux-2.6 2.6.32-24\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2010-07-16 15:55+0100\n" ++"PO-Revision-Date: 2010-10-25 00:24+0200\n" ++"Last-Translator: Jordi Mallach \n" ++"Language-Team: Catalan \n" ++"Language: ca\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++ ++#. Type: error ++#. Description ++#: ../linux-base.templates:8001 ../templates/temp.image.plain/templates:5001 ++msgid "" ++"If the boot loader needs to be updated whenever a new kernel is installed, " ++"the boot loader package should install a script in /etc/kernel/postinst.d. " ++"Alternately, you can specify the command to update the boot loader by " ++"setting the 'postinst_hook' variable in /etc/kernel-img.conf." ++msgstr "Si s'ha d'actualitzar el carregador cada vegada que s'instaÅ€la un nou nucli, el paquet del carregador hauria d'instaÅ€lar un script en /etc/kernel/postinst.d. Alternativament, podeu especificar l'ordre per a actualitzar el carregador establint la variable «postinst_hook» en /etc/kernel-img.conf." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Voleu avortar la instaÅ€lació degut a un error de depmod?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "L'ordre «depmod» ha sortit amb el codi d'error ${exit_value} (${SIGNAL}${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "Com aquesta imatge empra un initrd, no es suprimirà el fitxer ${modules_base}/=V/modules.dep, tot i que potser és invàlid." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "Hauríeu d'avortar la instaÅ€lació i corregir els errors de depmod, o regenerar la imatge initrd amb un fitxer modules.dep que siga correcte amb certesa. Si no avorteu la instaÅ€lació, hi ha el perill que l'arrencada del sistema falle." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Voleu avortar la supressió del nucli?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "Esteu executant un nucli (versió ${running}) i esteu intentant suprimir la mateixa versió." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "Això pot fer que el sistema no arrenque perquè suprimirà /boot/vmlinuz-${running} i tots els mòduls sota el directori /lib/modules/${running}. Això només es pot corregir amb una còpia de la imatge del nucli i els mòduls corresponents." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "És molt recomanable que avorteu la supressió del nucli si no esteu preparat per a reparar el sistema després de la supressió." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "És possible que manquen fitxers de microprogramari requerits" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "Actualment, el sistema està executant el Linux ${runningversion} i esteu instaÅ€lant el Linux ${version}. A la nova versió, és possible que alguns dels dispositius emprats en el sistema requereixen fitxers de microprogramari addicionals:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "La major part dels fitxers de microprogramari no estan inclosos al sistema perquè no compleixen els principis del programari lliure de Debian. És possible que necessiteu reconfigurar el gestor de paquets per a incloure les seccions «contrib» i «non-free» de l'arxiu de paquets abans de poder instaÅ€lar aquests fitxers de microprogramari." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Boot loader configuration must be updated" ++msgstr "S'ha d'actualitzar la configuració del carregador" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages no longer update a default boot loader. You should remove " ++"'do_bootloader = yes' from /etc/kernel-img.conf." ++msgstr "Els paquets del nucli ja no actualitzen el carregador per defecte. Hauríeu de suprimir la línia «do_bootloader = yes» del fitxer /etc/kernel-img.conf." +diff --git a/debian/po/cs.po b/debian/po/cs.po +new file mode 100644 +index 0000000..e83ca25 +--- /dev/null ++++ b/debian/po/cs.po +@@ -0,0 +1,141 @@ ++# Czech PO debconf template translation of linux. ++# Copyright (C) 2010 Michal Simunek ++# This file is distributed under the same license as the linux package. ++# Michal Simunek , 2010 - 2012. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: linux 3.2.21-3\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2011-07-04 04:24+0100\n" ++"PO-Revision-Date: 2012-06-30 13:02+0200\n" ++"Last-Translator: Michal Simunek \n" ++"Language-Team: Czech \n" ++"Language: cs\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=utf-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "PÅ™eruÅ¡it po chybÄ› depmod instalaci?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "Příkaz 'depmod' skonÄil s chybou ${exit_value} (${SIGNAL}${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Vzhledem k tomu, že tento obraz používá initrd, nebude soubor " ++"${modules_base}/=V/modules.dep smazán, pÅ™esto že může být neplatný." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"MÄ›li byste pÅ™eruÅ¡it instalaci a opravit chyby v depmod, nebo vytvoÅ™it obraz " ++"initrd s prověřeným souborem modules.dep. NepÅ™erušíte-li instalaci, " ++"vystavujete se riziku, že se nepodaří systém zavést." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "PÅ™eruÅ¡it odstraňování jádra?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Pokoušíte se odstranit verzi jádra (version ${running}), která nyní běží." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"To může způsobit, že se nepodaří zavést systém, a také bude odstranÄ›no /boot/" ++"vmlinuz-${running} a vÅ¡echny moduly v adresáři /lib/modules/${running}. Toto " ++"je možné opravit pouze nakopírováním obrazu jádra a přísluÅ¡ných modulů." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"Je silnÄ› doporuÄeno pÅ™eruÅ¡it odstraňování jádra, pokud nejste pÅ™ipraveni " ++"opravovat systém po jeho odstranÄ›ní." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Mohou chybÄ›t potÅ™ebné soubory s firmwarem" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"Systém nyní běží na Linuxu ${runningversion} a vy instalujete Linux " ++"${version}. V nové verzi mohou nÄ›které ovladaÄe používané v tomto systému, " ++"vyžadovat dodateÄné soubory s firmwarem:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"VÄ›tÅ¡ina souborů s firmwarem není zahrnuta v systému, protože nejsou v " ++"souladu se Zásadami svobodného softwaru Debianu. Než budete moci tyto " ++"soubory s firmwarem nainstalovat, budete možná muset nastavit správce " ++"balíÄků, aby zahrnoval archiv sekce balíÄků non-free." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "Nastavení ramdisku musí být aktualizováno" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" ++"Jaderný balíÄek již nespouÅ¡tí konkrétního tvůrce ramdisku. BalíÄek s tvůrcem " ++"ramdisku musí do adresáře /etc/kernel/postinst.d nainstalovat skript, a vy " ++"byste mÄ›li ze souboru /etc/kernel-img.conf odstranit řádek zaÄínající 'ramdisk ='." +diff --git a/debian/po/da.po b/debian/po/da.po +new file mode 100644 +index 0000000..c1a0830 +--- /dev/null ++++ b/debian/po/da.po +@@ -0,0 +1,145 @@ ++# Danish translation linux. ++# Copyright (C) 2011 Joe Hansen. ++# This file is distributed under the same license as the linux package. ++# Joe Hansen , 2010, 2011. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: linux\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2011-06-09 10:31+0200\n" ++"PO-Revision-Date: 2011-07-03 05:26+0100\n" ++"Last-Translator: Joe Hansen \n" ++"Language-Team: Danish \n" ++"Language: da\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Afbryd installation efter depmod-fejl?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++"Kommandoen depmod afsluttedes med koden afslutningskoden ${exit_value} " ++"(${SIGNAL} ${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Da dette aftryk bruger initrd, vil filen ${modules_base}/=V/modules.dep ikke " ++"blive slettet, selvom den mÃ¥ske er ugyldig." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Du skal afbryde installationen og rette fejlene i depmod, eller gendanne " ++"initrd-aftrykket med en kendt god fil af typen modules-dep. Hvis du ikke " ++"afbryder installationen, er der fare for at systemet vil fejle ved opstart." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Afbryd kernefjernelse?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Du kører en kerne (version ${running}) og forsøger at fjerne den samme " ++"version." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"Dette kan gøre at systemet ikke kan starte op da det vil fjerne /boot/" ++"vmlinuz-${running} og alle moduler i mappen /lib/modules//${running}. Dette " ++"kan kun rettes med en kopi af kerneaftrykket og de tilsvarende moduler." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"Det anbefales stærkt, at afbryde kernefjernelsen med mindre du er forberedt " ++"pÃ¥ at rette systemet op efter fjernelsen." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Krævet firmwarefiler mangler mÃ¥ske" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"Dette system kører aktuelt Linux ${runningversion}, og du installerer Linux " ++"${version}. I den nye version kræver nogle af driverne pÃ¥ dette system mÃ¥ske " ++"yderligere firmwarefiler:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"De fleste firmwarefiler er ikke inkluderet i Debiansystemet, da de ikke " ++"overholder Debian Free Softwares retningslinjer. Du skal mÃ¥ske rekonfigurere " ++"pakkehÃ¥ndteringen for at inkludere contrib og det ikke frie afsnit af " ++"Debianarkivet, før du kan installere disse firmwarefiler." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "Konfiguration af ramdisk skal opdateres" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" ++"Kernepakker vil ikke længere køre et specifikt ramdiskoprettelsesprogram. " ++"Pakken for ramdiskrettelsesprogrammet skal installere et skript i /etc/kernel" ++"/postinst.d, og du skal fjerne linjen der begynder med »ramdisk =« fra " ++"/etc/kernel-img.conf." +diff --git a/debian/po/de.po b/debian/po/de.po +new file mode 100644 +index 0000000..de89b54 +--- /dev/null ++++ b/debian/po/de.po +@@ -0,0 +1,149 @@ ++# Translation of linux templates to german. ++# Copyright (C) 2010 Holger Wansing. ++# This file is distributed under the same license as the linux package. ++# Holger Wansing , 2010, 2011. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: linux-2.6 3.0.0-3\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2011-07-04 04:24+0100\n" ++"PO-Revision-Date: 2011-09-13 20:41+0200\n" ++"Last-Translator: Holger Wansing \n" ++"Language-Team: Debian German \n" ++"Language: de\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Installation nach depmod-Fehler abbrechen?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++"Der »depmod«-Befehl wurde beendet: Rückgabewert ${exit_value} " ++"(${SIGNAL}${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Da dieses Image eine initrd verwendet, wird die Datei ${modules_base}/=V/" ++"modules.dep nicht gelöscht, obwohl sie ungültig sein könnte." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Sie sollten die Installation abbrechen und die Fehler bezüglich depmod " ++"beheben, oder erstellen Sie das initrd-Image neu mit einer bekanntermaßen " ++"korrekten modules.dep-Datei. Falls Sie die Installation nicht abbrechen, " ++"besteht die Gefahr, dass das System nicht mehr neu starten kann." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Entfernen des Kernels abbrechen?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Es läuft derzeit ein Kernel Version ${running} und Sie versuchen, die " ++"gleiche Version zu entfernen." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"Das kann dazu führen, dass das System nicht mehr startfähig ist, da dadurch /" ++"boot/vmlinuz-${running} und alle Module unterhalb des Verzeichnisses /lib/" ++"modules/${running} entfernt werden. Dies kann nur mit einer Kopie des Kernel-" ++"Images und der dazugehörigen Module behoben werden." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"Es wird dringend empfohlen, das Entfernen des Kernels abzubrechen, " ++"ausgenommen Sie sind darauf vorbereitet, das System nach der Entfernung " ++"wieder instandzusetzen." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Benötigte Firmware-Dateien möglicherweise nicht vorhanden" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"Auf diesem System läuft derzeit Linux ${runningversion} und Sie installieren " ++"gerade Linux ${version}. In der neuen Version könnten einige Treiber, die " ++"auf diesem System verwendet werden, zusätzliche Firmware-Dateien benötigen:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"Die meisten Firmware-Dateien sind nicht im System enthalten, da sie nicht " ++"mit den Debian-Richtlinien für Freie Software (DFSG) konform sind. Sie " ++"müssen unter Umständen den Paketmanager neu konfigurieren, so dass die " ++"contrib- und non-free-Sektionen des Paketarchivs ebenfalls enthalten sind, " ++"bevor Sie diese Firmware-Dateien installieren können." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "Aktualisierung der Ramdisk-Konfiguration erforderlich" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" ++"Kernel-Pakete werden keinen spezifischen Ramdisk-Ersteller mehr ausführen. " ++"Das Ramdisk-Ersteller-Paket muss ein Skript in /etc/kernel/postinst.d " ++"installieren und Sie sollten in /etc/kernel-img.conf die Zeile entfernen, " ++"die mit »ramdisk =« beginnt." +diff --git a/debian/po/es.po b/debian/po/es.po +new file mode 100644 +index 0000000..c16a726 +--- /dev/null ++++ b/debian/po/es.po +@@ -0,0 +1,179 @@ ++# linux po-debconf translation to Spanish ++# This file is distributed under the same license as the linux package. ++# ++# Changes: ++# - Initial translation ++# Omar Campagne 2010, 2011 ++# ++# - Review and update ++# Javier Fernandez-Sanguino, December 2010 ++# ++# Traductores, si no conocen el formato PO, merece la pena leer la ++# documentación de gettext, especialmente las secciones dedicadas a este ++# formato, por ejemplo ejecutando: ++# info -n '(gettext)PO Files' ++# info -n '(gettext)Header Entry' ++# ++# Equipo de traducción al español, por favor lean antes de traducir ++# los siguientes documentos: ++# ++# - El proyecto de traducción de Debian al español ++# http://www.debian.org/intl/spanish/ ++# especialmente las notas y normas de traducción en ++# http://www.debian.org/intl/spanish/notas ++# ++# - La guía de traducción de po's de debconf: ++# /usr/share/doc/po-debconf/README-trans ++# o http://www.debian.org/intl/l10n/po-debconf/README-trans ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: linux-2.6 2.6.32+5\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2011-07-04 04:24+0100\n" ++"PO-Revision-Date: 2011-07-16 17:59+0200\n" ++"Last-Translator: Omar Campagne \n" ++"Language-Team: Debian l10n Spanish \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Language: es\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Virtaal 0.6.1\n" ++"X-POFile-SpellExtra: initrd postinsthook conf lib contrib yes IDE depmod\n" ++"X-POFile-SpellExtra: runningversion img script boot Free exitvalue version\n" ++"X-POFile-SpellExtra: Debian CORE free running dobootloader UUID dep SIGNAL\n" ++"X-POFile-SpellExtra: Guidelines modulesbase vmlinuz postinst\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "¿Desea interrumpir la instalación cuando se produzca un fallo de depmod?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++"La orden «depmod» finalizó con el código de salida «${exit_value} " ++"(${SIGNAL}${CORE})»." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Debido a que esta imagen usa una imagen de arranque «initrd», no se " ++"eliminará el fichero «${modules_base}/=V/modules.dep», aún cuando no sea " ++"válido." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Debería cancelar la instalación y arreglar los errores de depmod, o " ++"regenerar la imagen de arranque «initrd» con un fichero «modules.dep» " ++"fiable. Si no cancela la instalación, existe el peligro de que el sistema no " ++"pueda arrancar." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "¿Desea cancelar la eliminación del núcleo?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Su sistema está ejecutando el núcleo (versión ${running}), y está intentando " ++"eliminar la misma versión del núcleo." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"Puede que el sistema no pueda arrancar posteriormente, ya que eliminaría «/" ++"boot/vmlinuz-${running}» y todos los módulos en el directorio «/lib/modules/" ++"${running}». Esto sólo se puede arreglar esto con una copia de la imagen del " ++"núcleo y los correspondientes módulos." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"Se recomienda encarecidamente cancelar la eliminación del núcleo, a menos " ++"que esté preparado para arreglar el sistema después de la eliminación." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Puede que los ficheros de firmware requeridos no estén disponibles" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"Este sistema ejecuta actualmente la versión ${runningversion} de Linux, y se " ++"está instalando la versión ${version}. Puede que los controladores incluidos " ++"en la nueva versión requieran ficheros de firmware adicionales:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"La mayoría de ficheros de firmware no se incluyen en el sistema porque no " ++"cumplen las normas de software libre de Debian («Debian Free Software " ++"Guidelines»). Puede que tenga que reconfigurar el gestor de paquetes para " ++"incluir las secciones «contrib» y «non-free» del archivo de Debian antes de " ++"instalar estos ficheros de firmware." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "Se debe actualizar la configuración del disco RAM" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" ++"Los paquetes de núcleo ya no ejecutarán un creador de disco RAM. El " ++"paquete de creador de disco RAM debe instalar un script en " ++"«/etc/kernel/postinst.d», y el usuario debería eliminar manualmente la línea " ++"que empieza con «ramdisk =» del fichero «/etc/kernel-img.conf»." ++ +diff --git a/debian/po/et.po b/debian/po/et.po +new file mode 100644 +index 0000000..4aa29f5 +--- /dev/null ++++ b/debian/po/et.po +@@ -0,0 +1,156 @@ ++# linux debconf estonian translation ++# linux debconf eesti keele tõlge ++# Copyright (C) 2010 Debian GNU/Linux ++# This file is distributed under the same license as the linux package. ++# ++# mihkel , 2010. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: linux 2.6.32-11\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2010-07-16 15:55+0100\n" ++"PO-Revision-Date: 2010-04-24 14:20+0300\n" ++"Last-Translator: mihkel \n" ++"Language-Team: Estonian \n" ++"Language: et\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"X-Generator: Emacs\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++ ++#. Type: error ++#. Description ++#: ../linux-base.templates:8001 ../templates/temp.image.plain/templates:5001 ++msgid "" ++"If the boot loader needs to be updated whenever a new kernel is installed, " ++"the boot loader package should install a script in /etc/kernel/postinst.d. " ++"Alternately, you can specify the command to update the boot loader by " ++"setting the 'postinst_hook' variable in /etc/kernel-img.conf." ++msgstr "" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Katkesta paigaldus peale depmod veateadet?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++"'depmod' käsk lõpetas väljumise koodiga ${exit_value} (${SIGNAL}${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Kuna tõmmis kasutab initrd-d, siis ${modules_base}/=V/modules.dep faili ei " ++"kustutata, kuigi ta võib olla vigane." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Sa peaksid paigaldamise katkestama ja parandama depmodi vead või " ++"regenereerima initrd tõmmise heade modules.dep failiga. Kui sa ei katkesta, " ++"siis suure tõenäosusega süsteem enam ei käivitu alglaadimisel." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Katkesta tuuma eemaldamine?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Sa kasutad tuuma versiooni (version ${running}) ning üritad seda sama " ++"versiooni eemaldada." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"See võib süsteemi muuta mitte käivitatavaks kuna eemaldatakse /boot/vmlinuz-" ++"${running} ja kõik moodulid kataloogist /lib/modules/${running}. Seda saab " ++"parandada ainult sama tumma ja vastavate moodulite kopeerimisega õigetesse " ++"kohtadesse." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"On äärmiselt soovituslik katkestada tuuma eemaldamine, kui sa just pole " ++"valmistunud süsteemi ise parandama." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Vajalikud püsivara failid võivad olla puudu" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"See süsteem kasutab praegu Linuxi versiooni ${runningversion} ja sina " ++"paigaldad versiooni ${version}. Uues versionis võivad mõned ajurid vajada " ++"lisaks püsivara faile:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"Enamik püsivara faile ei ole kaasatud süsteemi, sest nad ei vasta Debian " ++"vaba tarkvara juhtnööridele (Debian Free Software Guidelines). Võimalik, et " ++"pead enne oma pakimajandajat ümber seadistama, et kaasata varamutesse ka " ++"contrib ja non-free harud, kui saad need püsivara failid paigaldada." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++#, fuzzy ++#| msgid "Boot loader configuration check needed" ++msgid "Boot loader configuration must be updated" ++msgstr "Vajalik alglaaduri konfiguratsiooni kontroll" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages no longer update a default boot loader. You should remove " ++"'do_bootloader = yes' from /etc/kernel-img.conf." ++msgstr "" +diff --git a/debian/po/fr.po b/debian/po/fr.po +new file mode 100644 +index 0000000..f85d726 +--- /dev/null ++++ b/debian/po/fr.po +@@ -0,0 +1,150 @@ ++# Translation of linux debconf templates to French ++# Copyright (C) 2010, 2011 Debian French l10n team ++# This file is distributed under the same license as the linux package. ++# ++# David Prévot , 2010, 2011. ++msgid "" ++msgstr "" ++"Project-Id-Version: linux-2.6 2.6.39-1\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2011-05-21 10:31+0200\n" ++"PO-Revision-Date: 2011-05-22 08:48-0400\n" ++"Last-Translator: David Prévot \n" ++"Language-Team: French \n" ++"Language: fr\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"X-Generator: Lokalize 1.0\n" ++"Plural-Forms: nplurals=2; plural=(n > 1);\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Abandonner l'installation après l'erreur de depmod ?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++"La commande depmod s'est terminée avec le code de retour ${exit_value} " ++"(${SIGNAL} ${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Puisque cette image du noyau utilise initrd, le fichier ${modules_base}/=V/" ++"modules.dep ne sera pas effacé, mais il peut ne pas être valable." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Vous devriez abandonner l'installation et corriger les erreurs de dépendance " ++"entre les modules du noyau (depmod), ou créer une nouvelle image initrd avec " ++"un fichier modules.dep valable. Si vous n'annulez pas l'installation, le " ++"système risque de ne pas redémarrer correctement." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Abandonner la suppression du noyau ?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Le noyau actuellement utilisé (version ${running}) est en train d'être " ++"supprimé." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"Le système risque de ne plus pouvoir démarrer car /boot/vmlinuz-${running} " ++"sera enlevé ainsi que tous les modules du répertoire /lib/modules/" ++"${running}. Cela peut seulement être réparé avec une copie de l'image du " ++"noyau et des modules correspondants." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"Il est fortement recommandé d'interrompre la suppression du noyau à moins " ++"d'être ensuite prêt à réparer le système." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Microprogrammes (« firmwares ») probablement manquants" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"Ce système utilise actuellement Linux ${runningversion}, et Linux ${version} " ++"va être installé. Dans la nouvelle version, certains pilotes utilisés par ce " ++"système peuvent avoir besoin des microprogrammes additionnels :" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"La plupart des microprogrammes ne sont pas intégrés car ils ne sont pas " ++"conformes aux principes du logiciel libre selon Debian. Il est probablement " ++"nécessaire de modifier la configuration du gestionnaire de paquets et " ++"d'ajouter les sections « contrib » (contributions) et « non-free » (non " ++"libre) de l'archive avant de pouvoir installer ces fichiers." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "Mise à jour indispensable de la configuration du disque virtuel initial" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" ++"Les paquets du noyau ne s'occupent plus de la création du disque virtuel " ++"(RAM disque). Le programme en charge de la création du disque virtuel " ++"doivent installer un script dans /etc/kernel/postinst.d, et vous devriez " ++"supprimer la ligne commençant par « ramdisk = » de /etc/kernel-img.conf." +diff --git a/debian/po/it.po b/debian/po/it.po +new file mode 100644 +index 0000000..0d0668c +--- /dev/null ++++ b/debian/po/it.po +@@ -0,0 +1,158 @@ ++# This file is distributed under the same license as the linux package. ++# Collaboratively translated during an online sprint, thanks to all contributors! ++# Luca Bruno , 2010. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: linux-2.6 2.6.32-27\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2010-11-01 10:31+0100\n" ++"PO-Revision-Date: 2010-11-09 18:24+0100\n" ++"Last-Translator: Luca Bruno \n" ++"Language-Team: Italian \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++ ++#. Type: error ++#. Description ++#: ../linux-base.templates:8001 ../templates/temp.image.plain/templates:5001 ++msgid "" ++"If the boot loader needs to be updated whenever a new kernel is installed, " ++"the boot loader package should install a script in /etc/kernel/postinst.d. " ++"Alternately, you can specify the command to update the boot loader by " ++"setting the 'postinst_hook' variable in /etc/kernel-img.conf." ++msgstr "" ++"Se il boot loader necessita di essere aggiornato ad ogni installazione di " ++"nuovi kernel, il pacchetto relativo dovrebbe installare uno script in /etc/" ++"kernel/postinst.d. In alternativa, è possibile specificare il comando di " ++"aggiornamento tramite la variabile «postinst_hook» in /etc/kernel-img.conf." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Interrompere l'installazione a seguito dell'errore di depmod?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++"Il comando «depmod» è terminato con codice d'uscita ${exit_value} " ++"(${SIGNAL}${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Poiché questa immagine usa un initrd, il file ${modules_base}/=V/modules.dep " ++"non viene eliminato, anche se potrebbe risultare non più valido." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Si consiglia di interrompere l'installazione e correggere gli errori di " ++"depmod, o ricreare l'immagine initrd con un file modules.dep valido. Se " ++"l'installazione non viene interrotta, è possibile che il sistema possa " ++"risultare non avviabile." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Interrompere la rimozione del kernel?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Nel sistema è in esecuzione un kernel (versione ${running}) e si sta " ++"cercando di rimuovere la stessa versione." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"Ciò potrebbe rendere il sistema non avviabile poiché rimuoverà /boot/vmlinuz-" ++"${running} e tutti i moduli nella directory /lib/modules/${running}. A " ++"questo si potrà rimediare solo con una copia dell'immagine del kernel e dei " ++"moduli corrispondenti." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"Si consiglia vivamente di interrompere la rimozione del kernel a meno che " ++"non si sia preparati a riparare il sistema in seguito." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Alcuni firmware richiesti potrebbero non essere presenti" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"Su questo sistema è attualmente in esecuzione Linux ${runningversion} e si " ++"sta installando Linux ${version}. Nella nuova versione alcuni dei driver " ++"utilizzati su questo sistema potrebbero richiedere firmware aggiuntivi:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"La maggior parte dei firmware non sono inclusi nel sistema in quanto non " ++"conformi alle Linee Guida Debian per il Software Libero. Potrebbe essere " ++"necessario riconfigurare il gestore dei pacchetti ed includere le sezioni " ++"contrib e non-free per poterli installare." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Boot loader configuration must be updated" ++msgstr "La configurazione del boot loader deve essere aggiornata" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages no longer update a default boot loader. You should remove " ++"'do_bootloader = yes' from /etc/kernel-img.conf." ++msgstr "" ++"I pacchetti del kernel non provvedono più all'aggiornamento del boot loader " ++"predefinito. Si dovrebbe rimuovere la riga «do_bootloader = yes» da /etc/" ++"kernel-img.conf." +diff --git a/debian/po/ja.po b/debian/po/ja.po +new file mode 100644 +index 0000000..118a22f +--- /dev/null ++++ b/debian/po/ja.po +@@ -0,0 +1,106 @@ ++# Copyright (C) 2010 Kenshi Muto ++# Copyright (C) 2010 Nobuhiro Iwamatsu ++# Copyright (C) 2013 victory ++# This file is distributed under the same license as the linux package. ++# Kenshi Muto , 2010. ++# Nobuhiro Iwamatsu , 2010. ++# victory , 2013. ++msgid "" ++msgstr "" ++"Project-Id-Version: linux\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2011-07-04 04:24+0100\n" ++"PO-Revision-Date: 2013-08-17 23:03+0900\n" ++"Last-Translator: Nobuhiro Iwamatsu \n" ++"Language-Team: Japanese \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Language: ja\n" ++"X-Poedit-Language: Japanese\n" ++"X-Poedit-Country: JAPAN\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "depmod ã®ã‚¨ãƒ©ãƒ¼å¾Œã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’中止ã—ã¾ã™ã‹?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "The 'depmod' command exited with the exit code ${exit_value} (${SIGNAL}${CORE})." ++msgstr "'depmod' コマンドã¯çµ‚了コード ${exit_value} (${SIGNAL}${CORE}) ã§çµ‚了ã—ã¾ã—ãŸã€‚" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Since this image uses initrd, the ${modules_base}/=V/modules.dep file will not be deleted, even though it may be invalid." ++msgstr "ã“ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã¯ initrd を使ã£ã¦ã„ã‚‹ã®ã§ã€${modules_base}/=V/modules.dep ファイル㯠(ãŸã¨ãˆç„¡åйãªã‚‚ã®ã§ã‚ã£ãŸã¨ã—ã¦ã‚‚) 削除ã•れã¾ã›ã‚“。" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "You should abort the installation and fix the errors in depmod, or regenerate the initrd image with a known good modules.dep file. If you don't abort the installation, there is a danger that the system will fail to boot." ++msgstr "インストールを中止ã—㦠depmod ã®ã‚¨ãƒ©ãƒ¼ã‚’修正ã™ã‚‹ã‹ã€å•題ãŒãªã„ã¨ã‚ã‹ã£ã¦ã„ã‚‹ modules.dep ファイル㧠initrd イメージをå†ç”Ÿæˆã™ã¹ãã§ã™ã€‚インストールを中止ã—ãªã„ã¨ã€ã‚·ã‚¹ãƒ†ãƒ ã®èµ·å‹•ã«å¤±æ•—ã™ã‚‹æã‚ŒãŒã‚りã¾ã™ã€‚" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "カーãƒãƒ«ã®å‰Šé™¤ã‚’中止ã—ã¾ã™ã‹?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "You are running a kernel (version ${running}) and attempting to remove the same version." ++msgstr "ç¾åœ¨ã‚«ãƒ¼ãƒãƒ« (ãƒãƒ¼ã‚¸ãƒ§ãƒ³ ${running}) を実行ã—ã¦ãŠã‚Šã€åŒä¸€ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚«ãƒ¼ãƒãƒ«ã®å‰Šé™¤ã‚’試ã¿ã¦ã„ã¾ã™ã€‚" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "This can make the system unbootable as it will remove /boot/vmlinuz-${running} and all modules under the directory /lib/modules/${running}. This can only be fixed with a copy of the kernel image and the corresponding modules." ++msgstr "ã“ã®æ“作㯠/boot/vmlinuz-${running} ãŠã‚ˆã³ /lib/modules/${running} ディレクトリ下ã®ã™ã¹ã¦ã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’削除ã™ã‚‹ã®ã§ã€ã‚·ã‚¹ãƒ†ãƒ ã‚’èµ·å‹•ä¸èƒ½ã«ã™ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚ã“れã¯ã€ã‚«ãƒ¼ãƒãƒ«ã‚¤ãƒ¡ãƒ¼ã‚¸ãŠã‚ˆã³é–¢é€£ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã®ã‚³ãƒ”ーãŒãªã„é™ã‚Šç›´ã›ã¾ã›ã‚“。" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "It is highly recommended to abort the kernel removal unless you are prepared to fix the system after removal." ++msgstr "削除後ã§ã‚‚システムã«å•題ãŒãªã„よã†ãªæº–備を済ã¾ã›ã‚‹ã¾ã§ã€ã‚«ãƒ¼ãƒãƒ«ã®å‰Šé™¤ã‚’中止ã™ã‚‹ã“ã¨ã‚’å¼·ããŠå‹§ã‚ã—ã¾ã™ã€‚" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "å¿…è¦ãªãƒ•ァームウェアファイルãŒãªããªã£ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "This system is currently running Linux ${runningversion} and you are installing Linux ${version}. In the new version some of the drivers used on this system may require additional firmware files:" ++msgstr "ã“ã®ã‚·ã‚¹ãƒ†ãƒ ã¯ç¾åœ¨ Linux ${runningversion} を実行ã—ã¦ãŠã‚Šã€Linux ${version} をインストールã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ã€ã“ã®ã‚·ã‚¹ãƒ†ãƒ ã§ä½¿ã‚れるドライãƒã®ã„ãã¤ã‹ã¯è¿½åŠ ã®ãƒ•ァームウェアファイルを必è¦ã¨ã™ã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Most firmware files are not included in the system because they do not conform to the Debian Free Software Guidelines. You may need to reconfigure the package manager to include the contrib and non-free sections of the package archive before you can install these firmware files." ++msgstr "ã»ã¨ã‚“ã©ã®ãƒ•ァームウェアファイルã¯ã€Debian フリーソフトウェアガイドラインã«åˆè‡´ã—ãªã„ãŸã‚ã€ã‚·ã‚¹ãƒ†ãƒ ã«å«ã¾ã‚Œã¦ã„ã¾ã›ã‚“。ã“れらã®ãƒ•ァームウェアファイルをインストールå¯èƒ½ã«ã™ã‚‹ãŸã‚ã«ã€ãƒ‘ッケージアーカイブ㮠contrib ãŠã‚ˆã³ non-free セクションをå«ã‚€ã‚ˆã†ãƒ‘ッケージマãƒãƒ¼ã‚¸ãƒ£ã‚’å†è¨­å®šã™ã‚‹å¿…è¦ãŒã‚ã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "RAM ディスク設定を更新ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" ++"カーãƒãƒ«ãƒ‘ッケージã¯ç‰¹å®šã® RAM ディスク作æˆãƒ—ログラムを実行ã—ãªããªã£ã¦ã„ã¾" ++"ã™ã€‚RAM ディスクを作æˆã™ã‚‹ãƒ‘ッケージã¯ã‚¹ã‚¯ãƒªãƒ—トを /etc/kernel/postinst.d ã«" ++"インストールã—ãªã‘れã°ãªã‚Šã¾ã›ã‚“。ã¾ãŸã€ã€Œramdisk =ã€ã§å§‹ã¾ã‚‹è¡Œã‚’ /etc/kernel-" ++"img.conf ã‹ã‚‰å‰Šé™¤ã™ã‚‹ã‚ˆã†ã«ã—ã¦ãã ã•ã„。" +diff --git a/debian/po/nl.po b/debian/po/nl.po +new file mode 100644 +index 0000000..439ccb2 +--- /dev/null ++++ b/debian/po/nl.po +@@ -0,0 +1,96 @@ ++# Dutch translation of linux po-debconf templates. ++# Copyright (C) 2011 Willem Kuyn ++# This file is distributed under the same license as the linux package. ++# Willem Kuyn , 2011. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: linux\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2011-07-04 04:24+0100\n" ++"PO-Revision-Date: 2012-02-04 12:27+0100\n" ++"Last-Translator: willem kuyn \n" ++"Language-Team: Debian-Dutch \n" ++"Language: \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Installatie afbreken na depmod fout?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "The 'depmod' command exited with the exit code ${exit_value} (${SIGNAL}${CORE})." ++msgstr "De 'depmod' opdracht stopte met foutcode ${exit_value} (${SIGNAL}${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Since this image uses initrd, the ${modules_base}/=V/modules.dep file will not be deleted, even though it may be invalid." ++msgstr "Omdat deze afbeelding initrd gebruikt, zal het ${modules_base}/=V/modules.dep bestand niet verwijderd worden, ook al is het niet correct." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "You should abort the installation and fix the errors in depmod, or regenerate the initrd image with a known good modules.dep file. If you don't abort the installation, there is a danger that the system will fail to boot." ++msgstr "U zou de installatie moeten afbreken en de fouten in depmod herstellen, of het initrd-bestand opnieuw moeten genereren met een correct modules.dep bestand. Als u de installatie niet afbreekt dan bestaat het gevaar dat het systeem niet zal starten." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Het verwijderen van de kernel afbreken?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "You are running a kernel (version ${running}) and attempting to remove the same version." ++msgstr "U gebruikt kernel (versie ${running}) en probeert dezelfde versie te verwijderen." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "This can make the system unbootable as it will remove /boot/vmlinuz-${running} and all modules under the directory /lib/modules/${running}. This can only be fixed with a copy of the kernel image and the corresponding modules." ++msgstr "Het resultaat kan zijn dat het systeem niet start omdat het /boot/vmlinuz-${running} en alle modules onder /lib/modules/${running} verwijdert. Dit kan alleen gerepareerd worden met een kopie van het kernel bestand en de bijbehorende modules." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "It is highly recommended to abort the kernel removal unless you are prepared to fix the system after removal." ++msgstr "Het wordt ten sterkste aanbevolen om het verwijderen van de kernel af te breken tenzij u bent voorbereid om het systeem te repareren na het verwijderen." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "De vereiste firmware-bestanden kunnen ontbreken" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "This system is currently running Linux ${runningversion} and you are installing Linux ${version}. In the new version some of the drivers used on this system may require additional firmware files:" ++msgstr "Het systeem draait op dit moment Linux ${runningversion} en u installeert Linux ${version}. In de nieuwe versie kunnen enkele stuurprogramma's van het systeem aparte firmware-bestanden nodig hebben." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Most firmware files are not included in the system because they do not conform to the Debian Free Software Guidelines. You may need to reconfigure the package manager to include the contrib and non-free sections of the package archive before you can install these firmware files." ++msgstr "Veel firmware-bestanden zijn niet in het systeem opgenomen omdat zij niet voldoen aan de Debian Richtlijnen voor Vrije Software (DFSG). Mogelijk moet u de configuratie van de pakketbeheerprogramma aanpassen en de contrib en non-free secties van het pakketarchief toevoegen voordat u deze firmware bestanden kunt installeren. " ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++#| msgid "Boot loader configuration must be updated" ++msgid "Ramdisk configuration must be updated" ++msgstr "De ramdisk-configuratie moet worden aangepast." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Kernel packages will no longer run a specific ramdisk creator. The ramdisk creator package must install a script in /etc/kernel/postinst.d, and you should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "Kernel pakketten starten niet langer een bepaalde ramdisk generator. Het ramdisk generator pakket moet een script in /etc/kernel/postinst.d installeren en u dient de regel te verwijderen die begint met 'ramdisk =' uit /etc/kernel-img.conf." +diff --git a/debian/po/pl.po b/debian/po/pl.po +new file mode 100644 +index 0000000..7f909ef +--- /dev/null ++++ b/debian/po/pl.po +@@ -0,0 +1,153 @@ ++# Translation of linux debconf templates to Polish. ++# Copyright (C) 2011 MichaÅ‚ KuÅ‚ach ++# This file is distributed under the same license as the linux package. ++# ++# MichaÅ‚ KuÅ‚ach , 2012. ++msgid "" ++msgstr "" ++"Project-Id-Version: \n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2011-07-04 04:24+0100\n" ++"PO-Revision-Date: 2012-02-05 18:38+0100\n" ++"Last-Translator: MichaÅ‚ KuÅ‚ach \n" ++"Language-Team: Polish \n" ++"Language: \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"X-Generator: Lokalize 1.2\n" ++"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " ++"|| n%100>=20) ? 1 : 2);\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Przerwać instalacjÄ™ po błędzie depmod?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++"Polecenie \"depmod\" zakoÅ„czyÅ‚o siÄ™ z kodem wyjÅ›cia ${exit_value} " ++"(${SIGNAL}${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Ponieważ ten obraz używa initrd, plik ${modules_base}/=V/modules.dep nie " ++"zostanie usuniÄ™ty, nawet jeÅ›li może być nieprawidÅ‚owy." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Należy przerwać instalacjÄ™ i naprawić błędy depmod lub wygenerować obraz " ++"initrd ponownie z poprawnym, znanym plikiem modules.dep. JeÅ›li instalacja nie " ++"zostanie przerwana, istnieje niebezpieczeÅ„stwo, że system może siÄ™ nie " ++"uruchomić." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Przerwać usuwanie jÄ…dra?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Aktualnie używane jest jÄ…dro (wersja ${running}) i próbuje siÄ™ usunąć tÄ™ samÄ… " ++"wersjÄ™." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"Skutkiem mogÄ… być problemy z rozruchem systemu, ponieważ zostanie usuniÄ™ty " ++"/boot/vmlinuz-${running} i wszystkie moduÅ‚y z katalogu " ++"/lib/modules/${running}. Jedynym rozwiÄ…zaniem w takim wypadku jest " ++"skopiowanie obrazu jÄ…dra i towarzyszÄ…cych mu modułów." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"Jest wysoce zalecane, aby przerwać usuwanie jÄ…dra, chyba że użytkownik jest " ++"przygotowany do naprawy systemu po usuniÄ™ciu." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Wymagane pliki firmware mogÄ… być niedostÄ™pne" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"System dziaÅ‚a obecnie na jÄ…drze Linux ${runningversion}, a instalowany jest " ++"Linux ${version}. W nowej wersji niektóre ze sterowników używanych przez " ++"system, mogÄ… wymagać dodatkowych plików firmware:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"WiÄ™kszość plików firmware nie jest dołączonych do systemu, ponieważ nie " ++"speÅ‚niajÄ… Wytycznych Debiana dotyczÄ…cych Wolnego Oprogramowania. Może zajść " ++"potrzeba ponownej konfiguracji menedżera pakietów, aby dołączyć sekcje " ++"contrib i non-free archiwum pakietów, przed możliwoÅ›ciÄ… zainstalowania " ++"potrzebnych plików firmware." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "Konfiguracja ramdisku musi zostać zaktualizowana" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" ++"Pakiety jÄ…dra nie uruchamiajÄ… dÅ‚użej specjalnego kreatora ramdisku. Pakiet " ++"kreatora ramdisku musi zainstalować skrypt w /etc/kernel/postinst.d, a " ++"użytkownik powinien usunąć wszystkie wiersze zaczynajÄ…ce siÄ™ od \"ramdisk =\" " ++"z pliku /etc/kernel-img.conf." ++ ++ +diff --git a/debian/po/pt.po b/debian/po/pt.po +new file mode 100644 +index 0000000..a0df5f3 +--- /dev/null ++++ b/debian/po/pt.po +@@ -0,0 +1,168 @@ ++# Translation of linux debconf messages to Portuguese ++# Copyright (C) 2010 Américo Monteiro ++# This file is distributed under the same license as the linux package. ++# ++# Américo Monteiro , 2010, 2011. ++msgid "" ++msgstr "" ++"Project-Id-Version: linux 2.6.39.1\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2011-05-21 10:31+0200\n" ++"PO-Revision-Date: 2011-05-22 23:53+0100\n" ++"Last-Translator: Américo Monteiro \n" ++"Language-Team: Portuguese \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Language: pt\n" ++"X-Generator: Lokalize 1.2\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Abortar a instalação após erro do depmod?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} (${SIGNAL}" ++"${CORE})." ++msgstr "" ++"O comando 'depmod' terminou com o código de erro ${exit_value} (${SIGNAL}" ++"${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Como esta imagem usa initrd, o ficheiro ${modules_base}/=V/modules.dep não " ++"será apagado, apesar de poder ser inválido." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Você deve abortar a instalação e corrigir os erros do depmod, ou gerar " ++"novamente a imagem initrd com um ficheiro modules.dep conhecido como bom. Se " ++"não abortar a instalação, existe o perigo do sistema falhar no arranque." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Abortar a remoção do kernel?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Você está a correr um kernel (versão ${running}) e a tentar remover essa " ++"mesma versão." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"Isto pode fazer com que o sistema não arranque porque irá remover /boot/" ++"vmlinuz-${running} e todos os módulos no directório /lib/modules/${running}. " ++"Isto só pode ser corrigido com uma cópia da imagem do kernel e dos " ++"correspondentes módulos." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"É altamente recomendado abortar a remoção do kernel a menos que esteja " ++"preparado para corrigir o sistema após a remoção." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Podem estar em falta ficheiros de firmware necessários" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"Este sistema está actualmente a correr Linux ${runningversion} e você está a " ++"instalar Linux ${version}. Na nova versão algumas das drivers usadas neste " ++"sistema podem necessitar dos ficheiros de firmware adicionais:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"A maioria dos ficheiros de firmware não estão incluídos no sistema porque " ++"não respeitam as Guidelines da Debian Free Software. Você pode precisar de " ++"reconfigurar o gestor de pacotes para incluir as secções contrib e non-free " ++"do arquivo de pacotes antes de poder instalar estes ficheiros de firmware." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++#| msgid "Boot loader configuration must be updated" ++msgid "Ramdisk configuration must be updated" ++msgstr "A configuração de ramdisk tem de ser actualizada" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" ++"Os pacotes de kernel não irão mais correr um criador de ramdisk especificado. " ++"O pacote do criador de ramdisk deve instalar um script em /etc/kernel/" ++"postinst.d, e você deve remover a linha que começa com 'ramdisk =' do " ++"ficheiro /etc/kernel-img.conf." ++ ++#~ msgid "" ++#~ "If the boot loader needs to be updated whenever a new kernel is " ++#~ "installed, the boot loader package should install a script in /etc/kernel/" ++#~ "postinst.d. Alternately, you can specify the command to update the boot " ++#~ "loader by setting the 'postinst_hook' variable in /etc/kernel-img.conf." ++#~ msgstr "" ++#~ "Se o gestor de arranque precisa de ser actualizado sempre que um novo " ++#~ "kernel é instalado, o pacote do gestor de arranque deve instalar um " ++#~ "script em /etc/kernel/postinst.d. Em alternativa, você pode especificar o " ++#~ "comando para actualizar o gestor de arranque ao definir a variável " ++#~ "'postinst_hook' em /etc/kernel-img.conf." ++ ++#~ msgid "" ++#~ "Kernel packages no longer update a default boot loader. You should " ++#~ "remove 'do_bootloader = yes' from /etc/kernel-img.conf." ++#~ msgstr "" ++#~ "Os pacotes do kernel já não actualizam um gestor de arranque predefinido. " ++#~ "Você deve remover 'do_bootloader = yes' de /etc/kernel-img.conf." +diff --git a/debian/po/pt_BR.po b/debian/po/pt_BR.po +new file mode 100644 +index 0000000..45afcd1 +--- /dev/null ++++ b/debian/po/pt_BR.po +@@ -0,0 +1,152 @@ ++# linux Brazilian Portuguese debconf template translation. ++# Copyright (C) 2010 Flamarion Jorge ++# This file is distributed under the same license as the linux package. ++# Flamarion Jorge , 2010. ++# Fernando Ike de Oliveira (fike) , 2013. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: linux 3.10.3-1\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2011-07-04 04:24+0100\n" ++"PO-Revision-Date: 2013-08-08 13:10-0300\n" ++"Last-Translator: Fernando Ike de Oliveira (fike) \n" ++"Language-Team: Brazilian Portuguese \n" ++"Language: pt_BR\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n > 1);\n" ++"pt_BR utf-8\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Cancelar instalação após erro do depmod?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++"O comando 'depmod' terminou com o código de saída ${exit_value} " ++"(${SIGNAL}${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Uma vez que esta imagem usa o initrd, o arquivo ${modules_base}/=V/modules." ++"dep não será removido, embora possa ser considerado inválido." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Você deve cancelar a instalação e consertar os erros no depmod, ou regerar a " ++"imagem do initrd com um arquivo modules.dep em bom estado. Se você não " ++"cancelar a instalação, existe um perigo de seu sistema falhar na " ++"inicialização." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Cancelar remoção do kernel?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Você está executando um kernel (versão ${running}) e tentando remover a " ++"mesma versão." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"Isto pode tornar o sistema não inicializável, pois removerá /boot/vmlinuz-" ++"${running} e todos os módulos sob o diretório /lib/modules/${running}. Isto " ++"só pode ser consertado com uma cópia da imagem do kernel e dos módulos " ++"correspondentes." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"É altamente recomendável cancelar a remoção do kernel, a menos que você " ++"esteja preparado para consertar o sistema após a remoção." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Arquivos de firmware necessários podem estar faltando" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"Este sistema atualmente está executando o Linux ${runningversion} e você " ++"está instalando o Linux ${version}. Na nova versão alguns dos drivers usados " ++"neste sistema podem precisar de arquivos de firmware adicionais:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"A maioria dos arquivos de firmware não estão incluídos no sistema porque não " ++"estão em conformidade com a Definição Debian de Software Livre (\"Debian " ++"Free Software Guidelines\"). Você poderá precisar reconfigurar o gerenciador " ++"de pacotes para incluir as seções contrib e non-free do repositório de " ++"pacotes antes de poder instalar estes arquivos de firmware." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "A configuração de ramdisk deve ser atualizada" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" ++"Os pacotes do kernel não executarão mais um criador específico de ramdisk. O " ++"pacote criador de ramdisk deve instalar um script em /etc/kernel/postinst.d, " ++"e você deve remover a linha começando com 'ramdisk =' do /etc/kernel-img." ++"conf." +diff --git a/debian/po/ru.po b/debian/po/ru.po +new file mode 100644 +index 0000000..892d0b1 +--- /dev/null ++++ b/debian/po/ru.po +@@ -0,0 +1,148 @@ ++# translation of linux debconf templates to Russian ++# Copyright (C) 2010, 2011 Yuri Kozlov ++# This file is distributed under the same license as the linux package. ++# ++# Yuri Kozlov , 2010, 2011. ++msgid "" ++msgstr "" ++"Project-Id-Version: linux-2.6 3.1.6-1\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2011-07-04 04:24+0100\n" ++"PO-Revision-Date: 2011-12-30 18:35+0400\n" ++"Last-Translator: Yuri Kozlov \n" ++"Language-Team: Russian \n" ++"Language: ru\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"X-Generator: Lokalize 1.0\n" ++"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " ++"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Прервать уÑтановку поÑле ошибки depmod?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++"Команда depmod завершилаÑÑŒ Ñ ÐºÐ¾Ð´Ð¾Ð¼ ошибки ${exit_value} (${SIGNAL}${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Так как Ñтот образ иÑпользует initrd, файл ${modules_base}/=V/modules.dep не " ++"будет удалён, даже еÑли он может быть неправильным." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Ð’Ñ‹ должны прервать уÑтановку и иÑправить ошибки depmod, или переÑобрать " ++"образ initrd Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ð°ÑŽÑ‰Ð¸Ð¼ файлом modules.dep. ЕÑли вы не прервёте уÑтановку, " ++"то ÑиÑтема больше не Ñможет загружатьÑÑ." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Прервать удаление Ñдра?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "Ð’Ñ‹ пытаетеÑÑŒ удалить запущенную верÑию Ñдра (${running})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"Это может привеÑти к неÑпоÑобноÑти загрузки ÑиÑтемы, так как будут удалён " ++"файл /boot/vmlinuz-${running} и вÑе модули из каталога /lib/modules/" ++"${running}. Это можно будет иÑправить только копированием образа Ñдра и " ++"ÑоответÑтвующих модулей." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"ÐаÑтоÑтельно рекомендуетÑÑ Ð¿Ñ€ÐµÑ€Ð²Ð°Ñ‚ÑŒ удаление Ñдра, еÑли вы не готовы чинить " ++"ÑиÑтему поÑле его удалениÑ." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Могут отÑутÑтвовать необходимые файлы микропрограмм" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"Ð’ Ñтой ÑиÑтеме ÑÐµÐ¹Ñ‡Ð°Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ð°ÐµÑ‚ Ñдро Linux ${runningversion} и производитÑÑ " ++"уÑтановка Linux ${version}. Ð’ новой верÑии некоторым драйверам, иÑпользуемым " ++"в данной ÑиÑтеме, могут потребоватьÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ðµ файлы микропрограмм:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"БольшинÑтва файлов микропрограмм нет в диÑтрибутиве, так как они не " ++"удовлетворÑÑŽÑ‚ критериÑм Ñвободного ПО Debian. Ð”Ð»Ñ ÑƒÑтановки Ñтих файлов из " ++"архива вам может потребоватьÑÑ Ð¿ÐµÑ€ÐµÐ½Ð°Ñтроить менеджер пакетов, чтобы " ++"включить разделы contrib и non-free." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "ТребуетÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ðµ наÑтроек Ramdisk" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" ++"Пакеты Ñ Ñдрами больше не запуÑкают какую-то определённую программу Ð´Ð»Ñ " ++"ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ " ++"ramdisk. Пакет Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð¾Ð¹ Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ramdisk " ++"должен уÑтанавливать Ñценарий в /etc/kernel/postinst.d, а вы должны удалить " ++"Ñтроку, " ++"начинающуюÑÑ Ñ Â«ramdisk =» из файла /etc/kernel-img.conf." +diff --git a/debian/po/sk.po b/debian/po/sk.po +new file mode 100644 +index 0000000..70f8798 +--- /dev/null ++++ b/debian/po/sk.po +@@ -0,0 +1,146 @@ ++# Slovak translations for linux package ++# Slovenské preklady pre balík linux. ++# Copyright (C) 2011 Slavko ++# This file is distributed under the same license as the linux package. ++# Slavko , 2011. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: linux-2.6 2.6.32-29\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2011-06-09 10:31+0200\n" ++"PO-Revision-Date: 2011-07-10 09:19+0200\n" ++"Last-Translator: Slavko \n" ++"Language-Team: Slovak \n" ++"Language: sk\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "PreruÅ¡iÅ¥ inÅ¡taláciu po chybe depmod?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++"Príkaz „depmod†skonÄil s návratovým kódom ${exit_value} (${SIGNAL}${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"KeÄže tento obraz používa initrd, nebude súbor ${modules_base}/=V/modules." ++"dep zmazaný, hoci môže byÅ¥ neplatný." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Mali by ste preruÅ¡iÅ¥ inÅ¡taláciu a opraviÅ¥ chyby v depmod, alebo znova " ++"vytvoriÅ¥ obraz initrd s funkÄným súborom modules.dep. Ak teraz neprerušíte " ++"inÅ¡taláciu, môže sa staÅ¥, že sa nepodarí zaviesÅ¥ systém." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "PreruÅ¡iÅ¥ odstraňovanie jadra?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Pokúšate sa odstrániÅ¥ rovnakú verziu jadra, akú práve používate (version " ++"${running})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"Toto môže spôsobiÅ¥, že sa systém nezavedie, pretože bude odstránený /boot/" ++"vmlinuz-${running} a vÅ¡etky moduly z adresára /lib/modules/${running}. " ++"Opravené to môže byÅ¥ len prekopírovaním obrazu jadra a prísluÅ¡ných modulov." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"Dôrazne odporúÄame preruÅ¡iÅ¥ odstraňovanie jadra, ak nie ste pripravený na " ++"opravu systému po jeho odstránení." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Vyžadované súbory s firmware môžu chýbaÅ¥" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"Tento systém práve používa Linux ${runningversion} a vy inÅ¡talujete Linux " ++"${version}. V novej verzii môžu niektoré ovládaÄe používané týmto systémom " ++"vyžadovaÅ¥ dodatoÄné súbory s firmware:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"VäÄÅ¡ina súborov s firmware nie je v systéme zahrnutá, pretože nie sú v " ++"súlade so Zásadami slobodného softvéru Debianu. Pred inÅ¡taláciou týchto " ++"súborov s firmware, budete možno musieÅ¥ nastaviÅ¥ správcu balíkov tak, aby " ++"zahŕňal sekcie archívu balíkov contrib a non-free." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "Nastavenie ramdisku musí byÅ¥ aktualizované" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" ++"Balíky jadra už nebudú viac spúšťaÅ¥ vytváranie Å¡pecifického ramdisku. " ++"Nástroj na vytváranie ramdisku musí nainÅ¡talovaÅ¥ skript do /etc/kernel/" ++"postinst.d a vy musíte odstrániÅ¥ riadok, ktorý zaÄína „ramdisk =†z /etc/" ++"kernel-img.conf." +diff --git a/debian/po/sv.po b/debian/po/sv.po +new file mode 100644 +index 0000000..663c8e2 +--- /dev/null ++++ b/debian/po/sv.po +@@ -0,0 +1,146 @@ ++# Translation of linux debconf template to Swedish ++# Copyright (C) 2010 Martin Bagge ++# This file is distributed under the same license as the linux package. ++# ++# Martin Bagge , 2010 ++msgid "" ++msgstr "" ++"Project-Id-Version: linux\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2011-05-21 10:31+0200\n" ++"PO-Revision-Date: 2011-06-02 14:52+0100\n" ++"Last-Translator: Martin Bagge / brother \n" ++"Language-Team: Swedish \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=utf-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Language: sv\n" ++"X-Poedit-Language: Swedish\n" ++"X-Poedit-Country: Sweden\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Avbryt installation efter fel i depmod?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++"Kommandot \"depmod\" avslutades med felkod ${exit_value} (${SIGNAL}${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Eftersom denna avbildning använder initrd kommer inte filen ${modules_base}/" ++"=V/modules.dep att raderas, trots att den kan vara felaktig." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Du bör avbryta installationen och laga felen i depmod eller skapa en ny " ++"initrd-avbildning med en fungerande modules.dep-fil. Om du inte avbryter " ++"installationen kan systemet hamna i ett läge där det inte kan starta." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Avbryt radering av kärnan?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Den kärna du kör (version ${running}) och den du försöker ta bort är samma " ++"version." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"Detta kan göra systemet ostartbart eftersom det kommer att innebära att /" ++"boot/vmlinuz-${running} och alla moduler i /lib/modules/${running} raderas. " ++"Detta kan endast Ã¥terställas med en kopia av kärnavbildningen och " ++"motsvarande moduler." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"Det rekomenderas starkt att du avbryter raderingen av kärnan om du inte är " ++"beredd pÃ¥ att laga systemet efter raderingen." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Firmware-filer som krävs kan saknas" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"Detta system kör Linux ${runningversion} och du installerar Linux " ++"${version}. I den nya versionen kan vissa drivrutiner behöva ytterligare " ++"firmware-filer:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"PÃ¥ grund av bestämmelserna i Debian Free Software Guidelines kan de flesta " ++"firmware-filer inte inkluderas i systemet. Du kan behöva anpassa " ++"pakethanteraren för att inkludera sektionerna \"contrib\" och \"non-free\" i " ++"paketarkivet innan du kan installera dessa filer." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "Inställningarna för ramdisk behöver uppdateras" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" ++"Kärnpaketen kör inte längre en specifik ramdiskskapare. Ramdiskskaparen " ++"mÃ¥ste installera ett skript i /etc/kernel/postinst.d och du ska ta bort " ++"raden som börjar med \"ramdisk=\" frÃ¥n /etc/kernel-img.conf." +diff --git a/debian/po/templates.pot b/debian/po/templates.pot +new file mode 100644 +index 0000000..f309840 +--- /dev/null ++++ b/debian/po/templates.pot +@@ -0,0 +1,121 @@ ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# FIRST AUTHOR , YEAR. ++# ++#, fuzzy ++msgid "" ++msgstr "" ++"Project-Id-Version: PACKAGE VERSION\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2011-07-04 04:24+0100\n" ++"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" ++"Last-Translator: FULL NAME \n" ++"Language-Team: LANGUAGE \n" ++"Language: \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=CHARSET\n" ++"Content-Transfer-Encoding: 8bit\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages will no longer run a specific ramdisk creator. The ramdisk " ++"creator package must install a script in /etc/kernel/postinst.d, and you " ++"should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "" +diff --git a/debian/po/tr.po b/debian/po/tr.po +new file mode 100644 +index 0000000..a049c68 +--- /dev/null ++++ b/debian/po/tr.po +@@ -0,0 +1,96 @@ ++# Turkish translation of linux debconf template. ++# Copyright (C) 2012 Mert Dirik ++# This file is distributed under the same license as the linux package. ++# Mert Dirik , 2012. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: linux-2.6 3.2.4-1\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2011-07-04 04:24+0100\n" ++"PO-Revision-Date: 2012-02-12 22:36+0200\n" ++"Last-Translator: Mert Dirik \n" ++"Language-Team: Debian L10n Turkish \n" ++"Language: \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "depmod hatasından sonra kurulum iptal edilsin mi?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "The 'depmod' command exited with the exit code ${exit_value} (${SIGNAL}${CORE})." ++msgstr "'depmod' komutu ${exit_value} (${SIGNAL}${CORE}) çıkış koduyla sonlandı." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Since this image uses initrd, the ${modules_base}/=V/modules.dep file will not be deleted, even though it may be invalid." ++msgstr "Bu görüntü initrd kullandığından ötürü ${modules_base}/=V/modules.dep dosyası, dosya geçersiz olsa da silinmeyecektir." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "You should abort the installation and fix the errors in depmod, or regenerate the initrd image with a known good modules.dep file. If you don't abort the installation, there is a danger that the system will fail to boot." ++msgstr "Ya kurulumu iptal edip depmod'daki hataları düzeltmeli ya da initrd görüntüsünü düzgün olduÄŸu bilinen bir modules.dep dosyasıyla yeniden oluÅŸturmalısınız. Kurulumu iptal etmediÄŸiniz takdirde sisteminizin baÅŸlamama olasılığı vardır." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "ÇekirdeÄŸi kaldırma iÅŸlemi iptal edilsin mi?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "You are running a kernel (version ${running}) and attempting to remove the same version." ++msgstr "Kullandığınız çekirdekle (${running}) aynı sürümdeki çekirdeÄŸi kaldırmaya çalışıyorsunuz." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "This can make the system unbootable as it will remove /boot/vmlinuz-${running} and all modules under the directory /lib/modules/${running}. This can only be fixed with a copy of the kernel image and the corresponding modules." ++msgstr "Bu eylem sisteminizi baÅŸlatılamaz hale getirebilir ( /boot/vmlinuz-${running} dosyasını ve /lib/modules/${running} dizinindeki tüm modülleri kaldıracağından dolayı). Bu durum yalnızca bir çekirdek görüntüsü ve bu görüntüye uygun modüller yardımıyla düzeltilebilir." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "It is highly recommended to abort the kernel removal unless you are prepared to fix the system after removal." ++msgstr "Kaldırma iÅŸlemi sonrasında sistemi düzeltmeye hazır olmadığınız takdirde kaldırma iÅŸleminden vazgeçmeniz ÅŸiddetle tavsiye edilir." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Gerekli aygıt yazılımları eksik" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "This system is currently running Linux ${runningversion} and you are installing Linux ${version}. In the new version some of the drivers used on this system may require additional firmware files:" ++msgstr "Bu sistem ÅŸu anda Linux ${runningversion} kullanıyor ve siz Linux ${version} sürümünü kurmak üzeresiniz. Yeni sürümde bu sistemde kullanmakta olduÄŸunuz bazı sürücüler ek aygıt yazılımları (firmware) gerektirebilir:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Most firmware files are not included in the system because they do not conform to the Debian Free Software Guidelines. You may need to reconfigure the package manager to include the contrib and non-free sections of the package archive before you can install these firmware files." ++msgstr "ÇoÄŸu aygıt yazılımı Debian Özgür Yazılım Yönergeleri'ne uymadığı için sisteme dahil edilmez. Bu aygıt yazılımlarını kurabilmek için öncelikle paket yöneticisini paket arÅŸivinin contrib ve non-free kısımlarını kullanacak ÅŸekilde ayarlamanız gerekir." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Ramdisk configuration must be updated" ++msgstr "Ramdisk yapılandırılmasının güncellenmesi gerekli" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Kernel packages will no longer run a specific ramdisk creator. The ramdisk creator package must install a script in /etc/kernel/postinst.d, and you should remove the line beginning 'ramdisk =' from /etc/kernel-img.conf." ++msgstr "Çekirdek paketleri bundan böyle özel ramdisk oluÅŸturucularını kullanamaz. ramdisk oluÅŸturucu paket /etc/kernel/postinst.d konumuna bir betik kurmalıdır. Sizin de /etc/kernel-img.conf dosyasında 'ramdisk =' ile baÅŸlayan satırı kaldırmanız gerekmektedir." ++ +diff --git a/debian/po/vi.po b/debian/po/vi.po +new file mode 100644 +index 0000000..a1b920d +--- /dev/null ++++ b/debian/po/vi.po +@@ -0,0 +1,151 @@ ++# Vietnamese Debconf translation for Linux 2.6. ++# Copyright © 2010 Free Software Foundation, Inc. ++# Clytie Siddall , 2010. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: linux-2.6 2.6.32-26\n" ++"Report-Msgid-Bugs-To: linux@packages.debian.org\n" ++"POT-Creation-Date: 2010-10-21 10:37+0200\n" ++"PO-Revision-Date: 2010-10-27 15:21+1030\n" ++"Last-Translator: Clytie Siddall \n" ++"Language-Team: Vietnamese \n" ++"Language: vi\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=1; plural=0;\n" ++"X-Generator: LocFactoryEditor 1.8\n" ++ ++#. Type: error ++#. Description ++#: ../linux-base.templates:8001 ../templates/temp.image.plain/templates:5001 ++msgid "" ++"If the boot loader needs to be updated whenever a new kernel is installed, " ++"the boot loader package should install a script in /etc/kernel/postinst.d. " ++"Alternately, you can specify the command to update the boot loader by " ++"setting the 'postinst_hook' variable in /etc/kernel-img.conf." ++msgstr "Nếu bá»™ nạp khởi động cần phải được cập nhật khi nào cài đặt má»™t hạt nhân má»›i thì gói bá»™ nạp khởi động nên cài đặt má»™t văn lệnh vào « /etc/kernel/postinst.d ». Hoặc bạn có thể ghi rõ câu lệnh cập nhật bá»™ nạp khởi động bằng cách lập biến « postinst_hook » (hàm móc hậu xá»­ lý) trong tập tin cấu hình « /etc/kernel-img.conf »." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "Abort installation after depmod error?" ++msgstr "Há»§y bá» tiến trình cài đặt sau khi gặp lá»—i depmod ?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"The 'depmod' command exited with the exit code ${exit_value} " ++"(${SIGNAL}${CORE})." ++msgstr "" ++"Lệnh « depmod » đã thoát vá»›i mã thoát ${exit_value} (${SIGNAL}${CORE})." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"Since this image uses initrd, the ${modules_base}/=V/modules.dep file will " ++"not be deleted, even though it may be invalid." ++msgstr "" ++"Vì ảnh này sá»­ dụng initrd, tập tin ${modules_base}/=V/modules.dep sẽ không " ++"bị xoá, dù là nó có thể không thích hợp." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:2001 ++msgid "" ++"You should abort the installation and fix the errors in depmod, or " ++"regenerate the initrd image with a known good modules.dep file. If you don't " ++"abort the installation, there is a danger that the system will fail to boot." ++msgstr "" ++"Bạn nên há»§y bá» tiến trình cài đặt và sá»­a chữa các lá»—i trong depmod, hoặc tạo " ++"lại ảnh initrd vá»›i má»™t tập tin « modules.dep » tốt. Không há»§y bá» tiến trình " ++"cài đặt thì hệ thống có thể không khởi động được." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "Abort kernel removal?" ++msgstr "Há»§y bá» tiến trình gỡ bá» hạt nhân ?" ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"You are running a kernel (version ${running}) and attempting to remove the " ++"same version." ++msgstr "" ++"Bạn Ä‘ang chạy má»™t hạt nhân phiên bản ${running} trong khi thá»­ gỡ bá» phiên " ++"bản đó." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"This can make the system unbootable as it will remove /boot/vmlinuz-" ++"${running} and all modules under the directory /lib/modules/${running}. This " ++"can only be fixed with a copy of the kernel image and the corresponding " ++"modules." ++msgstr "" ++"Hành động này có thể làm cho hệ thống không có khả năng khởi động, vì nó gỡ " ++"bỠ« /boot/vmlinuz-${running} » và tất cả các mô-đụn nằm dưới thư mục « /lib/" ++"modules/${running} »." ++ ++#. Type: boolean ++#. Description ++#: ../templates/temp.image.plain/templates:3001 ++msgid "" ++"It is highly recommended to abort the kernel removal unless you are prepared " ++"to fix the system after removal." ++msgstr "" ++"Rất khuyên bạn há»§y bá» tiến trình gỡ bá» hạt nhân, nếu bạn không sẵn sàng sá»­a " ++"chữa hệ thống sau khi gỡ bá»." ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "Required firmware files may be missing" ++msgstr "Có thể thiếu má»™t số tập tin phần vững cần thiết" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"This system is currently running Linux ${runningversion} and you are " ++"installing Linux ${version}. In the new version some of the drivers used on " ++"this system may require additional firmware files:" ++msgstr "" ++"Hệ thống này hiện thá»i chạy Linux ${runningversion} còn bạn Ä‘ang cài đặt " ++"Linux ${version}. Trong phiên bản má»›i, má»™t số trình Ä‘iá»u khiển dùng trên hệ " ++"thống này có thể yêu cầu tập tin phần vững bổ sung:" ++ ++#. Type: note ++#. Description ++#: ../templates/temp.image.plain/templates:4001 ++msgid "" ++"Most firmware files are not included in the system because they do not " ++"conform to the Debian Free Software Guidelines. You may need to reconfigure " ++"the package manager to include the contrib and non-free sections of the " ++"package archive before you can install these firmware files." ++msgstr "" ++"Phần lá»›n các tập tin phần vững không phải có sẵn trong hệ thống do không làm " ++"cho hợp vá»›i Nguyên tắc Chỉ đạo Phần má»m Tá»± do Debian. Có thể là bạn cần phải " ++"cấu hình lại trình quản lý gói phần má»m để bao gồm phần đóng góp (contrib) " ++"và phần khác tá»± do (non-free) cá»§a kho lưu gói trước khi có khả năng cài đặt " ++"tập tin phần vững như vậy." ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "Boot loader configuration must be updated" ++msgstr "Cần phải cập nhật cấu hình cá»§a bá»™ nạp khởi động" ++ ++#. Type: error ++#. Description ++#: ../templates/temp.image.plain/templates:5001 ++msgid "" ++"Kernel packages no longer update a default boot loader. You should remove " ++"'do_bootloader = yes' from /etc/kernel-img.conf." ++msgstr "Gói hạt nhân không còn cập nhật lại bá»™ nạp khởi động mặc định. Bạn nên gỡ bá» chuá»—i « do_bootloader = yes » (làm bá»™ nạp khởi động = có) khá»i tập tin cấu hình « /etc/kernel-img.conf »." +diff --git a/debian/rules b/debian/rules +new file mode 100755 +index 0000000..3f23cd9 +--- /dev/null ++++ b/debian/rules +@@ -0,0 +1,96 @@ ++#!/usr/bin/make -f ++ ++#jtoppins: disable debian-installer udeb generation for now ++export DEBIAN_KERNEL_DISABLE_INSTALLER=1 ++ ++SHELL := sh -e ++DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH) ++SOURCE := $(shell dpkg-parsechangelog | sed -ne 's,^Source: *\(.*\)$$,\1,p') ++VERSION := $(shell dpkg-parsechangelog | sed -ne 's,^Version: *\(.*\)$$,\1,p') ++VERSION_UPSTREAM := $(shell echo "$(VERSION)" | sed -e 's,-[^-]*$$,,') ++VERSION_BINNMU := $(shell echo "$(VERSION)" | sed -ne 's,.*+b\(.*\)$$,\1,p') ++ ++include debian/rules.defs ++ ++stamp = [ -d $(dir $@) ] || mkdir $(dir $@); touch $@ ++ ++ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) ++ DEBIAN_KERNEL_JOBS := $(subst parallel=,,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) ++endif ++ifdef DEBIAN_KERNEL_JOBS ++ MAKEFLAGS += -j$(DEBIAN_KERNEL_JOBS) ++endif ++ ++.NOTPARALLEL: ++ ++source: debian/control $(STAMPS_DIR)/source-base ++$(STAMPS_DIR)/source-base: ++ dh_testdir ++ $(MAKE) -f debian/rules.gen source ++ @$(stamp) ++ ++setup: debian/control $(STAMPS_DIR)/setup-base ++$(STAMPS_DIR)/setup-base: $(STAMPS_DIR)/source-base ++ dh_testdir ++ $(MAKE) -f debian/rules.gen setup_$(DEB_HOST_ARCH) ++ @$(stamp) ++ ++build: build-arch build-indep ++ ++build-arch: debian/control $(STAMPS_DIR)/build-arch-base ++$(STAMPS_DIR)/build-arch-base: $(STAMPS_DIR)/setup-base ++ dh_testdir ++ $(MAKE) -f debian/rules.gen build-arch_$(DEB_HOST_ARCH) ++ @$(stamp) ++ ++build-indep: debian/control $(STAMPS_DIR)/build-indep-base ++$(STAMPS_DIR)/build-indep-base: $(STAMPS_DIR)/setup-base ++ dh_testdir ++ $(MAKE) -f debian/rules.gen build-indep ++ @$(stamp) ++ ++maintainerclean: ++ rm -f debian/config.defines.dump debian/control debian/control.md5sum debian/rules.gen ++ ++clean: debian/control ++ dh_testdir ++ rm -rf $(BUILD_DIR) $(STAMPS_DIR) debian/lib/python/debian_linux/*.pyc debian/linux-headers-* debian/linux-image-* debian/linux-support-* debian/linux-source-* debian/linux-doc-* debian/linux-manual-* debian/xen-linux-system-* debian/*-modules-*-di* ++ dh_clean ++ ++binary-indep: $(STAMPS_DIR)/build-indep-base ++ dh_testdir ++ $(MAKE) -f debian/rules.gen binary-indep ++ ++binary-arch: $(STAMPS_DIR)/build-arch-base ++ dh_testdir ++ $(MAKE) -f debian/rules.gen binary-arch_$(DEB_HOST_ARCH) ++ ++binary: binary-indep binary-arch ++ ++CONTROL_FILES = debian/changelog $(wildcard debian/templates/*.in) ++CONTROL_FILES += debian/config/defines $(wildcard debian/config/*/defines) $(wildcard debian/config/*/*/defines) ++CONTROL_FILES += $(wildcard debian/installer/*/kernel-versions) $(wildcard debian/installer/*/package-list) debian/installer/package-list ++debian/control debian/rules.gen: debian/bin/gencontrol.py $(CONTROL_FILES) ++ifeq ($(wildcard debian/control.md5sum),) ++ $(MAKE) -f debian/rules debian/control-real ++else ifeq ($(VERSION_BINNMU),) ++ md5sum --check debian/control.md5sum --status || \ ++ $(MAKE) -f debian/rules debian/control-real ++else ++ grep -v debian/changelog debian/control.md5sum | md5sum --check - --status || \ ++ $(MAKE) -f debian/rules debian/control-real ++endif ++ ++debian/control-real: debian/bin/gencontrol.py $(CONTROL_FILES) ++ chmod +x $< ++ $< ++ md5sum $^ > debian/control.md5sum ++ @echo ++ @echo This target is made to fail intentionally, to make sure ++ @echo that it is NEVER run during the automated build. Please ++ @echo ignore the following error, the debian/control file has ++ @echo been generated SUCCESSFULLY. ++ @echo ++ exit 1 ++ ++.PHONY: clean build setup binary-indep binary-arch binary +diff --git a/debian/rules.defs b/debian/rules.defs +new file mode 100644 +index 0000000..06b3f3e +--- /dev/null ++++ b/debian/rules.defs +@@ -0,0 +1,4 @@ ++BUILD_DIR = debian/build ++STAMPS_DIR = debian/stamps ++TEMPLATES_DIR = debian/templates ++ +diff --git a/debian/rules.real b/debian/rules.real +new file mode 100644 +index 0000000..778cf2d +--- /dev/null ++++ b/debian/rules.real +@@ -0,0 +1,524 @@ ++# ++# This Makefile executes the unpack/build/binary targets for a single ++# subarch, which is passed in the subarch variable. Empty subarch ++# variable means that we are building for an arch without the subarch. ++# Additionally, variables version, abiname and ltver are ++# expected to be available (need to be exported from the parent process). ++# ++SHELL := bash -e ++DEB_HOST_ARCH := $(shell dpkg-architecture -a'$(ARCH)' -qDEB_HOST_ARCH) ++DEB_HOST_GNU_TYPE := $(shell dpkg-architecture -a'$(ARCH)' -qDEB_HOST_GNU_TYPE) ++DEB_HOST_MULTIARCH:= $(shell dpkg-architecture -a'$(ARCH)' -qDEB_HOST_MULTIARCH) ++DEB_BUILD_ARCH := $(shell dpkg-architecture -a'$(ARCH)' -qDEB_BUILD_ARCH) ++MAINTAINER := $(shell sed -ne 's,^Maintainer: .[^<]*<\([^>]*\)>,\1,p' debian/control) ++DISTRIBUTION := $(shell dpkg-parsechangelog | sed -ne 's,^Distribution: ,,p') ++ ++DISTRIBUTOR := $(shell lsb_release -is 2>/dev/null) ++ifeq ($(DISTRIBUTOR),) ++DISTRIBUTOR := Debian ++endif ++ ++export PYTHONPATH = $(CURDIR)/debian/lib/python ++export DH_OPTIONS ++export DEB_HOST_ARCH DEB_HOST_GNU_TYPE DEB_BUILD_ARCH ++ ++ifneq (,$(filter experimental UNRELEASED,$(DISTRIBUTION))) ++ export KW_CHECK_NONFATAL = y ++endif ++ ++# Set Multi-Arch fields only when built in a suite that supports it ++ifneq (,$(DEB_HOST_MULTIARCH)) ++DEFINE_MULTIARCH = -Vlinux:Multi-Arch=$(1) ++else ++DEFINE_MULTIARCH = -Vlinux:Multi-Arch= ++endif ++ ++include debian/rules.defs ++ ++stamp = [ -d $(dir $@) ] || mkdir $(dir $@); touch $@ ++ ++setup_env := env -u ABINAME -u ABINAME_PART -u ARCH -u FEATURESET -u FLAVOUR -u VERSION -u LOCALVERSION ++setup_env += DISTRIBUTION_OFFICIAL_BUILD=1 DISTRIBUTOR="$(DISTRIBUTOR)" DISTRIBUTION_VERSION="$(SOURCEVERSION)" KBUILD_BUILD_TIMESTAMP="$(DISTRIBUTOR) $(SOURCEVERSION)" KBUILD_BUILD_USER="$(word 1,$(subst @, ,$(MAINTAINER)))" KBUILD_BUILD_HOST="$(word 2,$(subst @, ,$(MAINTAINER)))" ++ ++MAKE_CLEAN = $(setup_env) $(MAKE) ++MAKE_SELF := $(MAKE) -f debian/rules.real $(MAKEOVERRIDES) ++MAKEOVERRIDES = ++ ++# ++# Targets ++# ++binary-arch-arch: install-headers_$(ARCH) ++binary-arch-arch: install-libc-dev_$(ARCH) ++binary-arch-featureset: install-headers_$(ARCH)_$(FEATURESET) ++binary-arch-flavour: install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE) ++ifeq ($(DEBUG),True) ++ binary-arch-flavour: install-image-dbg_$(ARCH)_$(FEATURESET)_$(FLAVOUR) ++endif ++ifeq ($(MODULES),True) ++ binary-arch-flavour: install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR) ++endif ++ ++binary-indep: install-doc ++binary-indep: install-manual ++binary-indep: install-source ++binary-indep: install-support ++ ++build-arch: $(STAMPS_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE) ++build-indep: $(STAMPS_DIR)/build-doc ++ ++setup-flavour: $(STAMPS_DIR)/setup_$(ARCH)_$(FEATURESET)_$(FLAVOUR) ++ ++source-featureset: $(STAMPS_DIR)/source_$(FEATURESET) ++ ++$(BUILD_DIR)/config.$(ARCH)_$(FEATURESET)_$(FLAVOUR): $(KCONFIG) ++ python debian/bin/kconfig.py '$@' $(KCONFIG) $(KCONFIG_OPTIONS) ++ ++define copy_source ++mkdir -p '$(1)' ++cp -al $(filter-out debian .pc .svk .svn .git, $(wildcard * .[^.]*)) '$(1)' ++endef ++ ++$(BUILD_DIR)/linux-source-$(UPSTREAMVERSION).tar.bz2: DIR = $(BUILD_DIR)/linux-source-$(UPSTREAMVERSION) ++$(BUILD_DIR)/linux-source-$(UPSTREAMVERSION).tar.bz2: $(STAMPS_DIR)/source ++ rm -rf '$@' '$(DIR)' ++ $(call copy_source,$(DIR)) ++ chmod -R u+rw,go=rX '$(DIR)' ++ cd '$(BUILD_DIR)'; tar -cjf 'linux-source-$(UPSTREAMVERSION).tar.bz2' 'linux-source-$(UPSTREAMVERSION)' ++ rm -rf '$(DIR)' ++ ++$(BUILD_DIR)/linux-patch-$(UPSTREAMVERSION)-%.patch.bz2: $(STAMPS_DIR)/source_none $(STAMPS_DIR)/source_% ++ set -o pipefail; \ ++ (cd '$(BUILD_DIR)'; \ ++ set +e; \ ++ diff -urN -p -x debian -x .pc -x .svk -x .svn -x .git source_none source_$*; \ ++ test $$? -eq 1) | \ ++ filterdiff --remove-timestamps --strip=1 --addoldprefix=a/ --addnewprefix=b/ | \ ++ bzip2 -c >$@ || \ ++ (rm -f $@; exit 1) ++ ++define patch_cmd ++cd '$(DIR)' && QUILT_PATCHES='$(CURDIR)/debian/patches' QUILT_SERIES=series-$(1) QUILT_PC=.pc quilt push --quiltrc - -a -q --fuzz=0 ++endef ++ ++$(STAMPS_DIR)/source: ++ #test -d .pc ++ #set +e; QUILT_PC=.pc quilt unapplied --quiltrc - >/dev/null && echo 'Patch series not fully applied'; test $$? -eq 1 ++ @$(stamp) ++ ++$(STAMPS_DIR)/source_%: SOURCE_DIR=$(BUILD_DIR)/source ++$(STAMPS_DIR)/source_%: DIR=$(BUILD_DIR)/source_$* ++$(STAMPS_DIR)/source_%: $(STAMPS_DIR)/source ++ mkdir -p '$(BUILD_DIR)' ++ rm -rf '$(DIR)' ++ $(call copy_source,$(DIR)) ++ $(call patch_cmd,$*) ++ @$(stamp) ++.PRECIOUS: $(STAMPS_DIR)/source_% ++ ++$(STAMPS_DIR)/source_none: DIR=$(BUILD_DIR)/source_none ++$(STAMPS_DIR)/source_none: $(STAMPS_DIR)/source ++ mkdir -p '$(BUILD_DIR)' ++ rm -f '$(DIR)' ++ ln -s '$(CURDIR)' '$(DIR)' ++ @$(stamp) ++ ++$(STAMPS_DIR)/setup_$(ARCH)_$(FEATURESET)_$(FLAVOUR): CONFIG=$(BUILD_DIR)/config.$(ARCH)_$(FEATURESET)_$(FLAVOUR) ++$(STAMPS_DIR)/setup_$(ARCH)_$(FEATURESET)_$(FLAVOUR): SOURCE_DIR=$(BUILD_DIR)/source_$(FEATURESET) ++$(STAMPS_DIR)/setup_$(ARCH)_$(FEATURESET)_$(FLAVOUR): DIR=$(BUILD_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR) ++$(STAMPS_DIR)/setup_$(ARCH)_$(FEATURESET)_$(FLAVOUR): $(STAMPS_DIR)/source_$(FEATURESET) $(BUILD_DIR)/config.$(ARCH)_$(FEATURESET)_$(FLAVOUR) ++ rm -rf '$(DIR)' ++ mkdir '$(DIR)' ++ cp '$(CONFIG)' '$(DIR)/.config' ++ echo 'override ARCH = $(KERNEL_ARCH)' >> '$(DIR)/.kernelvariables' ++ echo 'override KERNELRELEASE = $(ABINAME)$(LOCALVERSION_IMAGE)' >> '$(DIR)/.kernelvariables' ++ echo 'CCACHE = ccache' >> '$(DIR)/.kernelvariables' ++ echo 'CC = $$(if $$(DEBIAN_KERNEL_USE_CCACHE),$$(CCACHE)) $$(CROSS_COMPILE)$(COMPILER)' >> '$(DIR)/.kernelvariables' ++# TODO: Should we set CROSS_COMPILE always? ++ifdef OVERRIDE_HOST_TYPE ++ echo 'override CROSS_COMPILE = $(OVERRIDE_HOST_TYPE)-' >> '$(DIR)/.kernelvariables' ++else ++ echo 'ifneq ($$(DEB_BUILD_ARCH),$$(DEB_HOST_ARCH))' >> '$(DIR)/.kernelvariables' ++ echo 'override CROSS_COMPILE = $$(DEB_HOST_GNU_TYPE)-' >> '$(DIR)/.kernelvariables' ++ echo 'endif' >> '$(DIR)/.kernelvariables' ++endif ++ifdef CFLAGS_KERNEL ++ echo 'CFLAGS_KERNEL += $(CFLAGS_KERNEL)' >> '$(DIR)/.kernelvariables' ++ echo 'CFLAGS_MODULE += $(CFLAGS_KERNEL)' >> '$(DIR)/.kernelvariables' ++endif ++ +$(MAKE_CLEAN) -C '$(SOURCE_DIR)' O='$(CURDIR)/$(DIR)' V=1 listnewconfig ++ +yes "" | $(MAKE_CLEAN) -C '$(SOURCE_DIR)' O='$(CURDIR)/$(DIR)' oldconfig >/dev/null ++ +$(MAKE_CLEAN) -C '$(SOURCE_DIR)' O='$(CURDIR)/$(DIR)' prepare ++ @$(stamp) ++ ++$(STAMPS_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE): DIR=$(BUILD_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR) ++$(STAMPS_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE): $(STAMPS_DIR)/setup_$(ARCH)_$(FEATURESET)_$(FLAVOUR) ++ ++$(STAMPS_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain-s390-tape: BUILD_TARGET = image ++$(STAMPS_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain-s390x-tape: BUILD_TARGET = image ++ ++$(STAMPS_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain \ ++$(STAMPS_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain-s390-tape \ ++$(STAMPS_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain-s390x-tape: ++ +$(MAKE_CLEAN) -C '$(DIR)' $(BUILD_TARGET) ++ python debian/bin/buildcheck.py $(DIR) $(ARCH) $(FEATURESET) $(FLAVOUR) ++ @$(stamp) ++ ++$(STAMPS_DIR)/build-doc: DIR=$(BUILD_DIR)/build-doc ++$(STAMPS_DIR)/build-doc: $(STAMPS_DIR)/source ++ rm -rf $(DIR) ++ mkdir -p $(DIR) ++ +$(MAKE_CLEAN) O='$(CURDIR)/$(DIR)' xmldocs ++ +$(MAKE_CLEAN) O='$(CURDIR)/$(DIR)' htmldocs mandocs ++ @$(stamp) ++ ++install-base: ++ dh_installchangelogs ++ dh_installdocs ++ dh_strip ++ dh_compress ++ dh_fixperms ++ dh_installdeb ++ dh_gencontrol -- $(GENCONTROL_ARGS) ++ dh_md5sums ++ dh_builddeb -- -Zxz $(BUILDDEB_ARGS) ++ ++install-dummy: ++ dh_testdir ++ dh_testroot ++ dh_prep ++ +$(MAKE_SELF) install-base ++ ++install-doc: PACKAGE_NAME = linux-doc-$(VERSION) ++install-doc: DIR = $(BUILD_DIR)/build-doc ++install-doc: PACKAGE_DIR = debian/$(PACKAGE_NAME) ++install-doc: OUT_DIR = $(PACKAGE_DIR)/usr/share/doc/$(PACKAGE_NAME) ++install-doc: DH_OPTIONS = -p$(PACKAGE_NAME) ++install-doc: $(STAMPS_DIR)/build-doc ++ dh_prep ++ mkdir -p $(OUT_DIR) ++ cp -a CREDITS MAINTAINERS README REPORTING-BUGS Documentation $(OUT_DIR) ++ rm -rf $(OUT_DIR)/Documentation/DocBook ++ set -o pipefail; \ ++ cd $(DIR)/Documentation/DocBook; \ ++ find * -name '*.html' -print \ ++ | \ ++ cpio -pd --preserve-modification-time '$(CURDIR)/$(OUT_DIR)/html' ++ gzip -9qfr $(OUT_DIR)/Documentation ++ +$(MAKE_SELF) install-base GENCONTROL_ARGS='$(call DEFINE_MULTIARCH,foreign)' ++ ++install-manual: PACKAGE_NAME = linux-manual-$(VERSION) ++install-manual: DIR=$(BUILD_DIR)/build-doc ++install-manual: DH_OPTIONS = -p$(PACKAGE_NAME) ++install-manual: $(STAMPS_DIR)/build-doc ++ dh_prep ++ set -o pipefail; \ ++ find $(DIR)/Documentation/DocBook/man/ -name '*.9' | xargs dh_installman ++ +$(MAKE_SELF) install-base GENCONTROL_ARGS='$(call DEFINE_MULTIARCH,foreign)' ++ ++install-headers_$(ARCH): PACKAGE_NAMES = linux-headers-$(ABINAME)-all linux-headers-$(ABINAME)-all-$(ARCH) ++install-headers_$(ARCH): DH_OPTIONS = $(foreach p, $(PACKAGE_NAMES), -p$(p)) ++install-headers_$(ARCH): ++ dh_testdir ++ dh_testroot ++ +$(MAKE_SELF) install-base GENCONTROL_ARGS='-Vkernel:Arch=$(ARCH)' ++ ++install-headers_$(ARCH)_$(FEATURESET): PACKAGE_NAME = linux-headers-$(ABINAME)-common$(LOCALVERSION_HEADERS) ++install-headers_$(ARCH)_$(FEATURESET): PACKAGE_NAME_KBUILD = linux-kbuild-$(VERSION) ++install-headers_$(ARCH)_$(FEATURESET): DH_OPTIONS = -p$(PACKAGE_NAME) ++install-headers_$(ARCH)_$(FEATURESET): BASE_DIR = /usr/src/$(PACKAGE_NAME) ++install-headers_$(ARCH)_$(FEATURESET): SOURCE_DIR = $(BUILD_DIR)/source_$(FEATURESET) ++install-headers_$(ARCH)_$(FEATURESET): DIR = debian/$(PACKAGE_NAME)/$(BASE_DIR) ++install-headers_$(ARCH)_$(FEATURESET): $(STAMPS_DIR)/source_$(FEATURESET) ++ dh_testdir ++ dh_testroot ++ dh_prep ++ ++ set -o pipefail; \ ++ cd $(SOURCE_DIR); \ ++ ( \ ++ echo Makefile; \ ++ find arch/$(KERNEL_ARCH) -maxdepth 1 -name 'Makefile*' -print; \ ++ find arch/$(KERNEL_ARCH) \( -name 'module.lds' -o -name 'Kbuild.platforms' -o -name 'Platform' \) -print; \ ++ find $$(find arch/$(KERNEL_ARCH) \( -name include -o -name scripts \) -type d -print) -print; \ ++ find include -name 'asm*' -prune -o -print; \ ++ find include/asm-generic -print; \ ++ ) \ ++ | \ ++ cpio -pd --preserve-modification-time '$(CURDIR)/$(DIR)' ++ ++ dh_link /usr/lib/$(PACKAGE_NAME_KBUILD)/scripts $(BASE_DIR)/scripts ++ ++ +$(MAKE_SELF) install-base ++ ++install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR): REAL_VERSION = $(ABINAME)$(LOCALVERSION) ++install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR): PACKAGE_NAME = linux-headers-$(REAL_VERSION) ++install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR): PACKAGE_NAME_COMMON = linux-headers-$(ABINAME)-common$(LOCALVERSION_HEADERS) ++install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR): PACKAGE_NAME_KBUILD = linux-kbuild-$(VERSION) ++install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR): DH_OPTIONS = -p$(PACKAGE_NAME) ++install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR): BASE_DIR = /usr/src/$(PACKAGE_NAME) ++install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR): BASE_DIR_COMMON = /usr/src/$(PACKAGE_NAME_COMMON) ++install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR): SOURCE_DIR = $(BUILD_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR) ++install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR): REF_DIR = $(BUILD_DIR)/source_$(FEATURESET) ++install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR): PACKAGE_DIR = debian/$(PACKAGE_NAME) ++install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR): DIR = $(PACKAGE_DIR)/$(BASE_DIR) ++install-headers_$(ARCH)_$(FEATURESET)_$(FLAVOUR): $(STAMPS_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE) ++ dh_testdir ++ dh_testroot ++ dh_prep ++ ++ mkdir -p $(DIR)/arch/$(KERNEL_ARCH)/kernel ++ cp -a $(SOURCE_DIR)/{.config,.kernel*,Module.symvers,include} $(DIR) ++ cp -a $(SOURCE_DIR)/arch/$(KERNEL_ARCH)/include $(DIR)/arch/$(KERNEL_ARCH) ++ cp -a $(SOURCE_DIR)/arch/$(KERNEL_ARCH)/kernel/asm-offsets.s $(DIR)/arch/$(KERNEL_ARCH)/kernel ++ ++ifneq ($(filter powerpc ppc64,$(ARCH)),) ++ if [ -f $(SOURCE_DIR)/arch/$(KERNEL_ARCH)/lib/crtsavres.o ]; then \ ++ mkdir $(DIR)/arch/$(KERNEL_ARCH)/lib; \ ++ cp -a $(SOURCE_DIR)/arch/$(KERNEL_ARCH)/lib/crtsavres.o $(DIR)/arch/$(KERNEL_ARCH)/lib; \ ++ fi ++endif ++ ++ @echo 'VERSION = 2' > $(DIR)/Makefile ++ @echo 'PATCHLEVEL = 6' >> $(DIR)/Makefile ++ ++ @echo 'MAKEARGS := -C $(BASE_DIR_COMMON) O=$(BASE_DIR)' >> $(DIR)/Makefile ++ @echo 'MAKEFLAGS += --no-print-directory' >> $(DIR)/Makefile ++ ++ @echo '.PHONY: all $$(MAKECMDGOALS)' >> $(DIR)/Makefile ++ @echo 'cmd := $$(filter-out all Makefile,$$(MAKECMDGOALS))' >> $(DIR)/Makefile ++ @echo 'all:' >> $(DIR)/Makefile ++ @echo ' @$$(MAKE) $$(MAKEARGS) $$(cmd)' >> $(DIR)/Makefile ++ @echo 'Makefile:;' >> $(DIR)/Makefile ++ @echo '$$(cmd) %/: all' >> $(DIR)/Makefile ++ @echo ' @:' >> $(DIR)/Makefile ++ ++ dh_link /usr/lib/$(PACKAGE_NAME_KBUILD)/scripts $(BASE_DIR)/scripts ++ ++ mkdir -p $(PACKAGE_DIR)/lib/modules/$(REAL_VERSION) ++ ln -s /usr/src/$(PACKAGE_NAME) $(PACKAGE_DIR)/lib/modules/$(REAL_VERSION)/build ++ ln -s /usr/src/$(PACKAGE_NAME_COMMON) $(PACKAGE_DIR)/lib/modules/$(REAL_VERSION)/source ++ ++ install -d $(PACKAGE_DIR)/DEBIAN ++ sed -e 's/=V/$(REAL_VERSION)/g' \ ++ debian/templates/temp.headers.plain/postinst \ ++ > $(PACKAGE_DIR)/DEBIAN/postinst ++ chmod 755 $(PACKAGE_DIR)/DEBIAN/postinst ++ ++ +$(MAKE_SELF) install-base ++ ++install-libc-dev_$(ARCH): PACKAGE_NAME = linux-libc-dev ++install-libc-dev_$(ARCH): DH_OPTIONS = -p$(PACKAGE_NAME) ++install-libc-dev_$(ARCH): DIR = $(BUILD_DIR)/build-libc-dev ++install-libc-dev_$(ARCH): OUT_DIR = debian/$(PACKAGE_NAME)/usr ++install-libc-dev_$(ARCH): ++ dh_testdir ++ dh_testroot ++ dh_prep ++ rm -rf '$(DIR)' ++ mkdir -p $(DIR) ++ +$(MAKE_CLEAN) O='$(CURDIR)/$(DIR)' headers_check ARCH=$(KERNEL_ARCH) ++ +$(MAKE_CLEAN) O='$(CURDIR)/$(DIR)' headers_install ARCH=$(KERNEL_ARCH) INSTALL_HDR_PATH='$(CURDIR)'/$(OUT_DIR) ++ ++ rm -rf $(OUT_DIR)/include/drm $(OUT_DIR)/include/scsi ++ find $(OUT_DIR)/include \( -name .install -o -name ..install.cmd \) -execdir rm {} + ++ ++ifneq (,$(DEB_HOST_MULTIARCH)) ++ # Move include/asm to arch-specific directory ++ mkdir -p $(OUT_DIR)/include/$(DEB_HOST_MULTIARCH) ++ mv $(OUT_DIR)/include/asm $(OUT_DIR)/include/$(DEB_HOST_MULTIARCH)/ ++endif ++ ++ +$(MAKE_SELF) install-base GENCONTROL_ARGS='$(call DEFINE_MULTIARCH,same)' ++ ++install-support: PACKAGE_NAME = linux-support-$(ABINAME) ++install-support: DH_OPTIONS = -p$(PACKAGE_NAME) ++install-support: PACKAGE_DIR = debian/$(PACKAGE_NAME) ++install-support: PACKAGE_ROOT = /usr/share/$(PACKAGE_NAME) ++install-support: ++ dh_testdir ++ dh_testroot ++ dh_prep ++ dh_installdirs $(PACKAGE_ROOT)/lib/python/debian_linux $(PACKAGE_ROOT)/modules ++ cp debian/config.defines.dump $(PACKAGE_DIR)$(PACKAGE_ROOT) ++ cp debian/lib/python/debian_linux/*.py $(PACKAGE_DIR)$(PACKAGE_ROOT)/lib/python/debian_linux ++ dh_python2 ++ dh_link $(PACKAGE_ROOT) /usr/src/$(PACKAGE_NAME) ++ +$(MAKE_SELF) install-base GENCONTROL_ARGS='$(call DEFINE_MULTIARCH,foreign)' ++ ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE): REAL_VERSION = $(ABINAME)$(LOCALVERSION) ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE): PACKAGE_NAME = linux-image-$(REAL_VERSION) ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE): PACKAGE_DIR = debian/$(PACKAGE_NAME) ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE): INSTALL_DIR = $(PACKAGE_DIR)/boot ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE): DIR = $(BUILD_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR) ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE): DH_OPTIONS = -p$(PACKAGE_NAME) ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE): $(STAMPS_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE) ++ ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain: ++ dh_testdir ++ dh_testroot ++ dh_prep ++ dh_installdirs 'boot' ++ +$(MAKE_SELF) \ ++ install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain_image \ ++ DIR='$(DIR)' PACKAGE_DIR='$(PACKAGE_DIR)' INSTALL_DIR='$(INSTALL_DIR)' REAL_VERSION='$(REAL_VERSION)' ++ifeq ($(MODULES),True) ++ chmod a+x $(CURDIR)/debian/bin/no-depmod ++ +$(MAKE_CLEAN) -C $(DIR) modules_install DEPMOD='$(CURDIR)/debian/bin/no-depmod' INSTALL_MOD_PATH='$(CURDIR)'/$(PACKAGE_DIR) INSTALL_MOD_STRIP=1 ++ifeq ($(DEBUG),True) ++ set -o pipefail; \ ++ find $(PACKAGE_DIR) -name '*.ko' | sed 's|$(PACKAGE_DIR)/lib/modules/$(REAL_VERSION)/kernel/||' | while read module ; do \ ++ objcopy --add-gnu-debuglink=$(DIR)/$$module $(PACKAGE_DIR)/lib/modules/$(REAL_VERSION)/kernel/$$module || exit; \ ++ done ++endif ++ cp $(DIR)/.config $(PACKAGE_DIR)/boot/config-$(REAL_VERSION) ++ cp $(DIR)/System.map $(PACKAGE_DIR)/boot/System.map-$(REAL_VERSION) ++ rm -f $(PACKAGE_DIR)/lib/modules/$(REAL_VERSION)/build ++ rm -f $(PACKAGE_DIR)/lib/modules/$(REAL_VERSION)/source ++ rm $(PACKAGE_DIR)/lib/firmware -rf ++endif ++ +$(MAKE_SELF) \ ++ install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain_templates \ ++ PACKAGE_NAME='$(PACKAGE_NAME)' PACKAGE_DIR='$(PACKAGE_DIR)' REAL_VERSION='$(REAL_VERSION)' ++ +$(MAKE_SELF) \ ++ install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain_bug \ ++ PACKAGE_DIR='$(PACKAGE_DIR)' PACKAGE_NAME='$(PACKAGE_NAME)' REAL_VERSION='$(REAL_VERSION)' ++ +$(MAKE_SELF) install-base ++ ++install-image_sparc_$(FEATURESET)_$(FLAVOUR)_plain_image \ ++install-image_sparc64_$(FEATURESET)_$(FLAVOUR)_plain_image \ ++install-image_sh4_$(FEATURESET)_$(FLAVOUR)_plain_image: ++ install -m644 '$(DIR)/arch/$(KERNEL_ARCH)/boot/zImage' $(INSTALL_DIR)/vmlinuz-$(REAL_VERSION) ++ ++ifneq ($(filter armel armhf,$(ARCH)),) ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain_image: DTB_INSTALL_DIR = /usr/lib/linux-image-$(REAL_VERSION) ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain_image: ++ install -m644 '$(DIR)/arch/$(KERNEL_ARCH)/boot/zImage' $(INSTALL_DIR)/vmlinuz-$(REAL_VERSION) ++ +$(MAKE_CLEAN) -C $(DIR) dtbs ++ shopt -s nullglob ; for i in $(DIR)/arch/arm/boot/*.dtb ; do \ ++ install -D -m644 $$i '$(PACKAGE_DIR)'/'$(DTB_INSTALL_DIR)'/$$(basename $$i) ; \ ++ done ++endif ++ ++install-image_amd64_$(FEATURESET)_$(FLAVOUR)_plain_image \ ++install-image_i386_$(FEATURESET)_$(FLAVOUR)_plain_image: ++ install -m644 '$(DIR)/arch/$(KERNEL_ARCH)/boot/bzImage' $(INSTALL_DIR)/vmlinuz-$(REAL_VERSION) ++ ++install-image_alpha_$(FEATURESET)_$(FLAVOUR)_plain_image: ++ install -m644 '$(DIR)/arch/$(KERNEL_ARCH)/boot/vmlinux.gz' $(INSTALL_DIR)/vmlinuz-$(REAL_VERSION) ++ ++install-image_ia64_$(FEATURESET)_$(FLAVOUR)_plain_image \ ++install-image_m68k_$(FEATURESET)_$(FLAVOUR)_plain_image: ++ install -m644 '$(DIR)/vmlinux.gz' $(INSTALL_DIR)/vmlinuz-$(REAL_VERSION) ++ ++install-image_hppa_$(FEATURESET)_$(FLAVOUR)_plain_image \ ++install-image_mips_$(FEATURESET)_$(FLAVOUR)_plain_image \ ++install-image_mipsel_$(FEATURESET)_$(FLAVOUR)_plain_image: ++ install -m644 '$(DIR)/vmlinux' $(INSTALL_DIR)/vmlinux-$(REAL_VERSION) ++ ++ifneq ($(filter powerpc ppc64,$(ARCH)),) ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain_image: WRAPPER_INSTALL_DIR = '$(CURDIR)'/$(PACKAGE_DIR)/usr/lib/linux-image-$(REAL_VERSION) ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain_image: ++ install -m644 '$(DIR)/vmlinux' $(INSTALL_DIR)/vmlinux-$(REAL_VERSION) ++ +$(MAKE_CLEAN) -C '$(DIR)' bootwrapper_install \ ++ WRAPPER_OBJDIR='$(WRAPPER_INSTALL_DIR)' \ ++ WRAPPER_DTSDIR='$(WRAPPER_INSTALL_DIR)'/dts \ ++ WRAPPER_BINDIR='$(WRAPPER_INSTALL_DIR)' ++endif ++ ++ifneq ($(filter s390 s390x,$(ARCH)),) ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain_image: ++ install -m644 '$(DIR)/arch/s390/boot/image' $(INSTALL_DIR)/vmlinuz-$(REAL_VERSION) ++endif ++ ++ifneq ($(INITRAMFS),False) ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain_templates: ARG_INITRD = YES ++endif ++ ++ARG_KIMAGE = vmlinuz ++install-image_hppa_$(FEATURESET)_$(FLAVOUR)_plain_templates \ ++install-image_mips_$(FEATURESET)_$(FLAVOUR)_plain_templates \ ++install-image_mipsel_$(FEATURESET)_$(FLAVOUR)_plain_templates \ ++install-image_powerpc_$(FEATURESET)_$(FLAVOUR)_plain_templates \ ++install-image_ppc64_$(FEATURESET)_$(FLAVOUR)_plain_templates: ARG_KIMAGE = vmlinux ++ ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain_templates: ++ for i in $(wildcard debian/templates/temp.image.plain/*); do \ ++ sed \ ++ -e 's@=B@$(KERNEL_ARCH)@g' \ ++ -e 's/=I/$(ARG_INITRD)/g' \ ++ -e 's/=K/$(ARG_KIMAGE)/g' \ ++ -e 's/=V/$(REAL_VERSION)/g' \ ++ $$i > debian/$(PACKAGE_NAME).$$(basename $$i) || exit; \ ++ done ++ mkdir -p debian/$(PACKAGE_NAME).po ++ for i in $(wildcard debian/po/*.po); do \ ++ sed \ ++ -e 's/=V/$(REAL_VERSION)/g' \ ++ $$i > debian/$(PACKAGE_NAME).po/$$(basename $$i) || exit; \ ++ done ++ mkdir -p debian/$(PACKAGE_NAME)/DEBIAN ++ po2debconf --podir debian/$(PACKAGE_NAME).po \ ++ -o debian/$(PACKAGE_NAME)/DEBIAN/templates \ ++ debian/$(PACKAGE_NAME).templates ++ ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain_bug: ++ dh_installdirs usr/share/bug/$(PACKAGE_NAME) ++ dh_install debian/templates/image.plain.bug/* usr/share/bug/$(PACKAGE_NAME) ++ chmod 755 $(PACKAGE_DIR)/usr/share/bug/$(PACKAGE_NAME)/script ++ echo "RELEASE='$(REAL_VERSION)'" > $(PACKAGE_DIR)/usr/share/bug/$(PACKAGE_NAME)/info ++ ++install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain-s390-tape: ++ dh_testdir ++ dh_testroot ++ dh_prep ++ dh_installdirs 'boot' ++ install -m644 '$(DIR)/arch/s390/boot/image' $(PACKAGE_DIR)/boot/vmlinuz-$(REAL_VERSION) ++ +$(MAKE_SELF) install-base ++ ++install-image-dbg_$(ARCH)_$(FEATURESET)_$(FLAVOUR): REAL_VERSION = $(ABINAME)$(LOCALVERSION) ++install-image-dbg_$(ARCH)_$(FEATURESET)_$(FLAVOUR): PACKAGE_NAME = linux-image-$(REAL_VERSION)-dbg ++install-image-dbg_$(ARCH)_$(FEATURESET)_$(FLAVOUR): PACKAGE_DIR = debian/$(PACKAGE_NAME) ++install-image-dbg_$(ARCH)_$(FEATURESET)_$(FLAVOUR): DEBUG_DIR = $(PACKAGE_DIR)/usr/lib/debug ++install-image-dbg_$(ARCH)_$(FEATURESET)_$(FLAVOUR): DIR = $(BUILD_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR) ++install-image-dbg_$(ARCH)_$(FEATURESET)_$(FLAVOUR): DH_OPTIONS = -p$(PACKAGE_NAME) ++install-image-dbg_$(ARCH)_$(FEATURESET)_$(FLAVOUR): $(STAMPS_DIR)/build_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_$(TYPE) ++ dh_testdir ++ dh_testroot ++ dh_prep ++ dh_installdirs usr/lib/debug usr/lib/debug/boot usr/share/lintian/overrides/ ++ sed -e 's/=V/$(REAL_VERSION)/g' \ ++ debian/templates/image-dbg.lintian-override.in \ ++ > $(PACKAGE_DIR)/usr/share/lintian/overrides/$(PACKAGE_NAME) ++ install -m644 $(DIR)/vmlinux $(DEBUG_DIR)/boot/vmlinux-$(REAL_VERSION) ++ifeq ($(MODULES),True) ++ +$(MAKE_CLEAN) -C $(DIR) modules_install INSTALL_MOD_PATH='$(CURDIR)'/$(DEBUG_DIR) ++ find $(DEBUG_DIR)/lib/modules/$(REAL_VERSION)/ -mindepth 1 -maxdepth 1 \! -name kernel -exec rm {} \+ ++ rm $(DEBUG_DIR)/lib/firmware -rf ++endif ++# Add symlinks to vmlinux from the locations expected by kdump-tools, ++# systemtap and others ++ ln -s boot/vmlinux-$(REAL_VERSION) $(DEBUG_DIR)/ ++ mkdir -p $(DEBUG_DIR)/lib/modules/$(REAL_VERSION) ++ ln -s ../../../boot/vmlinux-$(REAL_VERSION) $(DEBUG_DIR)/lib/modules/$(REAL_VERSION)/vmlinux ++ +$(MAKE_SELF) install-base ++ ++install-udeb_$(ARCH): export KW_DEFCONFIG_DIR=debian/installer ++install-udeb_$(ARCH): export KW_CONFIG_DIR=debian/installer/$(ARCH) ++install-udeb_$(ARCH): DH_OPTIONS=$(PACKAGE_NAMES:%=-p%) ++install-udeb_$(ARCH): ++ dh_testdir ++ dh_prep ++ kernel-wedge install-files $(ABINAME) ++ kernel-wedge check $(PACKAGE_NAMES) ++ dh_fixperms ++ dh_gencontrol ++ dh_builddeb ++ ++install-source: DH_OPTIONS = -plinux-source-$(VERSION) ++install-source: $(BUILD_DIR)/linux-source-$(UPSTREAMVERSION).tar.bz2 $(foreach FEATURESET,$(filter-out none,$(ALL_FEATURESETS)),$(BUILD_DIR)/linux-patch-$(UPSTREAMVERSION)-$(FEATURESET).patch.bz2) ++ dh_testdir ++ dh_testroot ++ dh_install '$^' /usr/src ++ +$(MAKE_SELF) install-base GENCONTROL_ARGS='$(call DEFINE_MULTIARCH,foreign)' ++ ++# vim: filetype=make +diff --git a/debian/source/format b/debian/source/format +new file mode 100644 +index 0000000..c3d9f24 +--- /dev/null ++++ b/debian/source/format +@@ -0,0 +1,2 @@ ++3.0 (quilt) ++ +diff --git a/debian/source/options b/debian/source/options +new file mode 100644 +index 0000000..b7bc1f2 +--- /dev/null ++++ b/debian/source/options +@@ -0,0 +1 @@ ++compression = "xz" +diff --git a/debian/templates/control.headers.arch.in b/debian/templates/control.headers.arch.in +new file mode 100644 +index 0000000..d209d96 +--- /dev/null ++++ b/debian/templates/control.headers.arch.in +@@ -0,0 +1,14 @@ ++Package: linux-headers-@abiname@-all ++Depends: linux-headers-@abiname@-all-${kernel:Arch} (= ${binary:Version}), ${misc:Depends} ++Description: All header files for Linux @version@ (meta-package) ++ This package depends against all architecture-specific kernel header files ++ for Linux kernel version @upstreamversion@, generally used for building out-of-tree ++ kernel modules. ++ ++Package: linux-headers-@abiname@-all-@arch@ ++Depends: ${misc:Depends} ++Description: All header files for Linux @version@ (meta-package) ++ This package depends against all architecture-specific kernel header files ++ for Linux kernel version @upstreamversion@, generally used for building out-of-tree ++ kernel modules. ++ +diff --git a/debian/templates/control.headers.featureset.in b/debian/templates/control.headers.featureset.in +new file mode 100644 +index 0000000..d3f9dfd +--- /dev/null ++++ b/debian/templates/control.headers.featureset.in +@@ -0,0 +1,8 @@ ++Package: linux-headers-@abiname@-common@localversion_headers@ ++Depends: ${misc:Depends} ++Description: Common header files for Linux @abiname@@localversion_headers@ ++ This package provides the architecture-specific common kernel header files ++ for Linux kernel version @abiname@@localversion_headers@, generally used for building out-of-tree ++ kernel modules. To obtain a complete set of headers you also need to install ++ the linux-headers-@abiname@-(flavour) package, matching the ++ flavour of the kernel you intend the build for. +diff --git a/debian/templates/control.headers.in b/debian/templates/control.headers.in +new file mode 100644 +index 0000000..1062709 +--- /dev/null ++++ b/debian/templates/control.headers.in +@@ -0,0 +1,10 @@ ++Package: linux-headers-@abiname@@localversion@ ++Depends: linux-headers-@abiname@-common@localversion_headers@ (= ${binary:Version}), linux-kbuild-@version@, ${misc:Depends} ++Provides: linux-headers ++Description: Header files for Linux @abiname@@localversion@ ++ This package provides the architecture-specific kernel header files ++ for Linux kernel @abiname@@localversion@, generally ++ used for building out-of-tree kernel modules. These files are going to be ++ installed into /usr/src/linux-headers-@abiname@@localversion@, and can ++ be used for building modules that load into the kernel provided by the ++ linux-image-@abiname@@localversion@ package. +diff --git a/debian/templates/control.image-dbg.in b/debian/templates/control.image-dbg.in +new file mode 100644 +index 0000000..7e15424 +--- /dev/null ++++ b/debian/templates/control.image-dbg.in +@@ -0,0 +1,7 @@ ++Package: linux-image-@abiname@@localversion@-dbg ++Depends: linux-image-@abiname@@localversion@, ${misc:Depends} ++Section: debug ++Priority: extra ++Description: Debugging symbols for Linux @abiname@@localversion@ ++ This package provides the detached debugging symbols for the Linux kernel ++ and modules in linux-image-@abiname@@localversion@. +diff --git a/debian/templates/control.image.type-plain.in b/debian/templates/control.image.type-plain.in +new file mode 100644 +index 0000000..dbe808e +--- /dev/null ++++ b/debian/templates/control.image.type-plain.in +@@ -0,0 +1,9 @@ ++Package: linux-image-@abiname@@localversion@ ++Provides: linux-image, linux-modules-@abiname@@localversion@ ++Pre-Depends: debconf | debconf-2.0 ++Depends: kmod | module-init-tools, linux-base (>= 3~), ${misc:Depends} ++Recommends: firmware-linux-free (>= 3~) ++Suggests: linux-doc-@version@, debian-kernel-handbook ++Breaks: at (<< 3.1.12-1+squeeze1) ++Description: Linux @upstreamversion@ for @class@ ++ The Linux kernel @upstreamversion@ and modules for use on @longclass@. +diff --git a/debian/templates/control.image.type-standalone.in b/debian/templates/control.image.type-standalone.in +new file mode 100644 +index 0000000..1c99d6e +--- /dev/null ++++ b/debian/templates/control.image.type-standalone.in +@@ -0,0 +1,6 @@ ++Package: linux-image-@abiname@@localversion@ ++Provides: linux-image ++Suggests: linux-doc-@version@ ++Depends: ${misc:Depends} ++Description: Linux @upstreamversion@ for @class@ ++ The Linux kernel @upstreamversion@ for use on @longclass@. +diff --git a/debian/templates/control.libc-dev.in b/debian/templates/control.libc-dev.in +new file mode 100644 +index 0000000..8e0b7d7 +--- /dev/null ++++ b/debian/templates/control.libc-dev.in +@@ -0,0 +1,10 @@ ++Package: linux-libc-dev ++Section: devel ++Depends: ${misc:Depends} ++Provides: linux-kernel-headers ++Replaces: linux-kernel-headers ++Conflicts: linux-kernel-headers ++Multi-Arch: ${linux:Multi-Arch} ++Description: Linux support headers for userspace development ++ This package provides userspaces headers from the Linux kernel. These headers ++ are used by the installed headers for GNU libc and other system libraries. +diff --git a/debian/templates/control.main.in b/debian/templates/control.main.in +new file mode 100644 +index 0000000..26139cc +--- /dev/null ++++ b/debian/templates/control.main.in +@@ -0,0 +1,56 @@ ++Package: linux-source-@version@ ++Architecture: all ++Section: kernel ++Provides: linux-source ++Depends: binutils, bzip2, ${misc:Depends} ++Recommends: libc6-dev | libc-dev, gcc, make ++Suggests: libncurses-dev | ncurses-dev, libqt4-dev, pkg-config ++Multi-Arch: ${linux:Multi-Arch} ++Description: Linux kernel source for version @version@ with Debian patches ++ This package provides source code for the Linux kernel version @version@. ++ This source closely tracks official Linux kernel releases. Debian's ++ modifications to that source consist of security fixes, bug fixes, and ++ features that have already been (or are believed to be) accepted by the ++ upstream maintainers. ++ ++Package: linux-doc-@version@ ++Architecture: all ++Depends: ${misc:Depends} ++Section: doc ++Multi-Arch: ${linux:Multi-Arch} ++Description: Linux kernel specific documentation for version @version@ ++ This package provides the various README files and HTML documentation for ++ the Linux kernel version @version@. Plenty of information, including the ++ descriptions of various kernel subsystems, filesystems, driver-specific ++ notes and the like. Consult the file ++ /usr/share/doc/linux-doc-@version@/Documentation/00-INDEX ++ for the detailed description of the contents. ++ ++Package: linux-manual-@version@ ++Architecture: all ++Depends: ${misc:Depends} ++Section: doc ++Provides: linux-manual ++Conflicts: linux-manual ++Replaces: linux-manual ++Multi-Arch: ${linux:Multi-Arch} ++Description: Linux kernel API manual pages for version @version@ ++ This package provides the Kernel Hacker's Guide in the form of ++ manual pages, describing the kernel API functions. They ++ are installed into section 9 of the manual. ++ . ++ As the files containing manual pages for different kernel versions ++ are installed in the same location, only one linux-manual package ++ may be installed at a time. The linux-doc package containing the ++ documentation in other formats is free from such restriction. ++ ++Package: linux-support-@abiname@ ++Architecture: all ++Section: devel ++Depends: ${python:Depends}, ${misc:Depends} ++Multi-Arch: ${linux:Multi-Arch} ++Description: Support files for Linux @upstreamversion@ ++ This package provides support files for the Linux kernel build, ++ e.g. scripts to handle ABI information and for generation of ++ build system meta data. ++ +diff --git a/debian/templates/control.source.in b/debian/templates/control.source.in +new file mode 100644 +index 0000000..1c0e6e5 +--- /dev/null ++++ b/debian/templates/control.source.in +@@ -0,0 +1,9 @@ ++Section: kernel ++Priority: optional ++Maintainer: Cumulus Kernel Team ++Uploaders: Andy Gospodarek , Roopa Prabhu , Jonathan Toppins ++Standards-Version: 3.9.2 ++Build-Depends: debhelper (>> 7), cpio, kmod | module-init-tools, python (>= 2.7), lzma [armel], kernel-wedge (>= 2.84), quilt, patchutils ++Build-Depends-Indep: bzip2, xmlto ++Vcs-Git: ++Vcs-Browser: +diff --git a/debian/templates/image-dbg.lintian-override.in b/debian/templates/image-dbg.lintian-override.in +new file mode 100644 +index 0000000..b0773e2 +--- /dev/null ++++ b/debian/templates/image-dbg.lintian-override.in +@@ -0,0 +1,2 @@ ++# Kernel dbg packages contain a full image with debug data ++linux-image-=V-dbg: dbg-package-missing-depends +diff --git a/debian/templates/image.plain.bug/control b/debian/templates/image.plain.bug/control +new file mode 100644 +index 0000000..5468d73 +--- /dev/null ++++ b/debian/templates/image.plain.bug/control +@@ -0,0 +1,2 @@ ++Submit-As: src:linux ++Package-Status: firmware-atheros firmware-bnx2 firmware-bnx2x firmware-brcm80211 firmware-intelwimax firmware-ipw2x00 firmware-ivtv firmware-iwlwifi firmware-libertas firmware-linux firmware-linux-nonfree firmware-myricom firmware-netxen firmware-qlogic firmware-ralink firmware-realtek xen-hypervisor +diff --git a/debian/templates/image.plain.bug/include-0version b/debian/templates/image.plain.bug/include-0version +new file mode 100644 +index 0000000..b5b32bf +--- /dev/null ++++ b/debian/templates/image.plain.bug/include-0version +@@ -0,0 +1,9 @@ ++add_0version() { ++ echo '** Version:' >&3 ++ cat /proc/version >&3 ++ echo >&3 ++} ++ ++ask_0version() { ++ true ++} +diff --git a/debian/templates/image.plain.bug/include-1cmdline b/debian/templates/image.plain.bug/include-1cmdline +new file mode 100644 +index 0000000..3fcc940 +--- /dev/null ++++ b/debian/templates/image.plain.bug/include-1cmdline +@@ -0,0 +1,9 @@ ++add_1cmdline() { ++ echo '** Command line:' >&3 ++ cat /proc/cmdline >&3 ++ echo >&3 ++} ++ ++ask_1cmdline() { ++ true ++} +diff --git a/debian/templates/image.plain.bug/include-1tainted b/debian/templates/image.plain.bug/include-1tainted +new file mode 100644 +index 0000000..5a64409 +--- /dev/null ++++ b/debian/templates/image.plain.bug/include-1tainted +@@ -0,0 +1,49 @@ ++TAINT_PROPRIETARY_MODULE=0 ++TAINT_FORCED_MODULE=1 ++TAINT_UNSAFE_SMP=2 ++TAINT_FORCED_RMMOD=3 ++TAINT_MACHINE_CHECK=4 ++TAINT_BAD_PAGE=5 ++TAINT_USER=6 ++TAINT_DIE=7 ++TAINT_OVERRIDDEN_ACPI_TABLE=8 ++TAINT_WARN=9 ++TAINT_CRAP=10 ++TAINT_FIRMWARE_WORKAROUND=11 ++TAINT_OOT_MODULE=12 ++ ++_check() { ++ if [ $(($tainted & 1<<$1)) -ne 0 ]; then ++ result_short="$result_short$2" ++ result_long="$result_long * $3\n" ++ fi ++} ++ ++add_1tainted() { ++ tainted=$(cat /proc/sys/kernel/tainted) ++ if [ "$tainted" -gt 0 ]; then ++ local result_short result_long ++ _check $TAINT_PROPRIETARY_MODULE 'P' 'Proprietary module has been loaded.' ++ _check $TAINT_FORCED_MODULE 'F' 'Module has been forcibly loaded.' ++ _check $TAINT_UNSAFE_SMP 'S' 'SMP with CPUs not designed for SMP.' ++ _check $TAINT_FORCED_RMMOD 'R' 'User forced a module unload.' ++ _check $TAINT_MACHINE_CHECK 'M' 'System experienced a machine check exception.' ++ _check $TAINT_BAD_PAGE 'B' 'System has hit bad_page.' ++ _check $TAINT_USER 'U' 'Userspace-defined naughtiness.' ++ _check $TAINT_DIE 'D' 'Kernel has oopsed before.' ++ _check $TAINT_OVERRIDDEN_ACPI_TABLE 'A' 'ACPI table overridden.' ++ _check $TAINT_WARN 'W' 'Taint on warning.' ++ _check $TAINT_CRAP 'C' 'Module from drivers/staging has been loaded.' ++ _check $TAINT_FIRMWARE_WORKAROUND 'I' 'Working around severe firmware bug.' ++ _check $TAINT_OOT_MODULE 'O' 'Out-of-tree module has been loaded.' ++ echo "** Tainted: $result_short ($tainted)" >&3 ++ printf "$result_long" >&3 ++ else ++ echo '** Not tainted' >&3 ++ fi ++ echo >&3 ++} ++ ++ask_1tainted() { ++ true ++} +diff --git a/debian/templates/image.plain.bug/include-dmesg b/debian/templates/image.plain.bug/include-dmesg +new file mode 100644 +index 0000000..a7f4f41 +--- /dev/null ++++ b/debian/templates/image.plain.bug/include-dmesg +@@ -0,0 +1,12 @@ ++add_dmesg() { ++ echo '** Kernel log:' >&3 ++ dmesg | tail -n 100 >&3 ++ echo >&3 ++} ++ ++ask_dmesg() { ++ # Remind the user to attach the kernel log. This should also trigger ++ # a reminder in some MUAs if the user tries to send without it. ++ echo '** Kernel log: boot messages should be attached' >&3 ++ echo >&3 ++} +diff --git a/debian/templates/image.plain.bug/include-model b/debian/templates/image.plain.bug/include-model +new file mode 100644 +index 0000000..40f8021 +--- /dev/null ++++ b/debian/templates/image.plain.bug/include-model +@@ -0,0 +1,55 @@ ++grep_model() { ++ case "$(uname -m)" in ++ alpha) ++ egrep '^(system (type|variation|revision)|platform string)\b' /proc/cpuinfo ++ ;; ++ arm*) ++ egrep '^(Processor|Hardware|Revision)\b' /proc/cpuinfo ++ ;; ++ i386|ia64|x86_64) ++ local found= ++ for name in {sys,product,chassis,bios,board}_{vendor,name,version}; do ++ if [ -f /sys/class/dmi/id/$name ]; then ++ echo -n "$name: " ++ cat /sys/class/dmi/id/$name ++ found=y ++ fi ++ done ++ test -n "$found" ++ ;; ++ mips|mips64) ++ egrep '^(system type|cpu model)\b' /proc/cpuinfo ++ ;; ++ parisc|parisc64) ++ egrep '^(model|[hs]version)\b' /proc/cpuinfo ++ ;; ++ ppc|ppc64) ++ egrep -i '^(board|machine|model|motherboard|platform|revision|vendor)\b' /proc/cpuinfo ++ ;; ++ s390|s390x) ++ egrep '^processor\b' /proc/cpuinfo ++ ;; ++ sparc|sparc64) ++ egrep '^(cpu|fpu|pmu|prom|type)\b' /proc/cpuinfo ++ ;; ++ sh4|sh4a) ++ egrep '^(machine|cpu)\b' /proc/cpuinfo ++ ;; ++ *) ++ false ++ ;; ++ esac ++} ++ ++add_model() { ++ local found= ++ echo '** Model information' >&3 ++ grep_model >&3 2>/dev/null || echo "not available" >&3 ++ echo >&3 ++} ++ ++ask_model() { ++ # This is still valid as long as the bug is being reported on the same ++ # system. ++ test $same_system = nop || add_model ++} +diff --git a/debian/templates/image.plain.bug/include-modules b/debian/templates/image.plain.bug/include-modules +new file mode 100644 +index 0000000..22271c9 +--- /dev/null ++++ b/debian/templates/image.plain.bug/include-modules +@@ -0,0 +1,13 @@ ++add_modules() { ++ echo '** Loaded modules:' >&3 ++ # List modules along with any taint flags. ++ # We should be able to tell cut to use an empty output delimiter, but ++ # currently (coreutils 8.13-3) this results in null bytes in the output. ++ cut -d' ' -f1,7 /proc/modules | sed 's/ //' >&3 ++ echo >&3 ++} ++ ++ask_modules() { ++ true ++} ++ +diff --git a/debian/templates/image.plain.bug/include-network b/debian/templates/image.plain.bug/include-network +new file mode 100644 +index 0000000..bd12def +--- /dev/null ++++ b/debian/templates/image.plain.bug/include-network +@@ -0,0 +1,39 @@ ++_add_etc_network_interfaces() { ++ echo '** Network interface configuration:' >&3 ++ # Hide passwords/keys ++ awk '$1 ~ /key|pass|^wpa-(anonymous|identity|phase|pin|private|psk)/ { gsub(".", "*", $2); } ++ $1 == "ethtool-wol" { gsub(".", "*", $3); } ++ !/^[[:space:]]*\#/ { print; } ++ ' &3 ++ echo >&3 ++} ++ ++add_network() { ++ yesno "Include network configuration and status from this computer? " nop ++ test $REPLY = yep || return 0 ++ ++ _add_etc_network_interfaces ++ echo '** Network status:' >&3 ++ if command -v ip >/dev/null; then ++ echo '*** IP interfaces and addresses:' >&3 ++ ip address show >&3 ++ echo >&3 ++ fi ++ echo '*** Device statistics:' >&3 ++ cat /proc/net/dev >&3 ++ echo >&3 ++ if command -v netstat >/dev/null; then ++ echo '*** Protocol statistics:' >&3 ++ netstat -s >&3 || true ++ echo >&3 ++ fi ++ echo >&3 ++} ++ ++ask_network() { ++ test $same_system = yep || return 0 ++ yesno "Include network configuration from this computer? " nop ++ test $REPLY = yep || return 0 ++ ++ _add_etc_network_interfaces ++} +diff --git a/debian/templates/image.plain.bug/include-pci b/debian/templates/image.plain.bug/include-pci +new file mode 100644 +index 0000000..8e6528e +--- /dev/null ++++ b/debian/templates/image.plain.bug/include-pci +@@ -0,0 +1,12 @@ ++add_pci() { ++ echo '** PCI devices:' >&3 ++ lspci -nnvv >&3 2>/dev/null || echo 'not available' >&3 ++ echo >&3 ++} ++ ++ask_pci() { ++ # This information shouldn't vary much between kernel versions, so ++ # include it anyway. ++ test $same_system = nop || add_pci ++} ++ +diff --git a/debian/templates/image.plain.bug/include-usb b/debian/templates/image.plain.bug/include-usb +new file mode 100644 +index 0000000..e8eb67e +--- /dev/null ++++ b/debian/templates/image.plain.bug/include-usb +@@ -0,0 +1,11 @@ ++add_usb() { ++ echo '** USB devices:' >&3 ++ lsusb >&3 2>/dev/null || echo 'not available' >&3 ++ echo >&3 ++} ++ ++ask_usb() { ++ # This information shouldn't vary much between kernel versions, so ++ # include it anyway. ++ test $same_system = nop || add_usb ++} +diff --git a/debian/templates/image.plain.bug/presubj b/debian/templates/image.plain.bug/presubj +new file mode 100644 +index 0000000..59b891a +--- /dev/null ++++ b/debian/templates/image.plain.bug/presubj +@@ -0,0 +1,8 @@ ++Please ensure that you are currently running the kernel version that you ++are reporting on. This will allow your bug report to include useful ++diagnostic information about the running kernel. ++ ++If you are reporting that the kernel fails to boot, please use a digital ++camera, serial console or netconsole to record the boot messages and ++attach these to your report. You can use the kernel parameter ++'boot_delay=1000' to slow down the boot messages. +diff --git a/debian/templates/image.plain.bug/script b/debian/templates/image.plain.bug/script +new file mode 100644 +index 0000000..9374b2f +--- /dev/null ++++ b/debian/templates/image.plain.bug/script +@@ -0,0 +1,26 @@ ++#!/bin/bash ++set -e ++ ++PATH=/sbin:/bin:/usr/sbin:/usr/bin ++ ++dir="$(dirname $0)" ++ ++. "$dir"/info ++ ++for file in "$dir"/include-*; do ++ name="$(echo $file | sed -e 's,^.*/include-,,')" ++ hooks+=($name) ++ . "$file" ++done ++ ++if [ "$RELEASE" == "$(uname -r)" ]; then ++ for hook in ${hooks[@]}; do ++ add_$hook ++ done ++else ++ yesno "Does the bug you are reporting affect this computer? " yep ++ same_system=$REPLY ++ for hook in ${hooks[@]}; do ++ ask_$hook ++ done ++fi +diff --git a/debian/templates/temp.headers.plain/postinst b/debian/templates/temp.headers.plain/postinst +new file mode 100644 +index 0000000..8c214bc +--- /dev/null ++++ b/debian/templates/temp.headers.plain/postinst +@@ -0,0 +1,26 @@ ++#!/usr/bin/perl ++# Author: Michael Gilbert ++# Origin: Stripped down version of the linux-headers postinst from Ubuntu's ++# 2.6.32-14-generic kernel, which was itself derived from a ++# Debian linux-image postinst script. ++ ++$|=1; ++my $version = "=V"; ++ ++if (-d "/etc/kernel/header_postinst.d") { ++ print STDERR "Examining /etc/kernel/header_postinst.d.\n"; ++ system ("run-parts --verbose --exit-on-error --arg=$version " . ++ "/etc/kernel/header_postinst.d") && ++ die "Failed to process /etc/kernel/header_postinst.d"; ++} ++ ++if (-d "/etc/kernel/header_postinst.d/$version") { ++ print STDERR "Examining /etc/kernel/header_postinst.d/$version.\n"; ++ system ("run-parts --verbose --exit-on-error --arg=$version " . ++ "/etc/kernel/header_postinst.d/$version") && ++ die "Failed to process /etc/kernel/header_postinst.d/$version"; ++} ++ ++exit 0; ++ ++__END__ +diff --git a/debian/templates/temp.image.plain/postinst b/debian/templates/temp.image.plain/postinst +new file mode 100755 +index 0000000..55cd64a +--- /dev/null ++++ b/debian/templates/temp.image.plain/postinst +@@ -0,0 +1,712 @@ ++#! /usr/bin/perl ++# ++use strict; ++use warnings; ++use Cwd 'abs_path'; ++use Debconf::Client::ConfModule qw(:all); ++use POSIX (); ++version('2.0'); ++my $capb = capb('backup', 'escape'); ++ ++$|=1; ++ ++# Predefined values: ++my $version = "=V"; ++my $link_in_boot = ""; ++my $no_symlink = ""; ++my $do_symlink = "Yes"; # target machine defined ++my $kimage = "=K"; ++my $initrd = "=I"; # initrd kernel ++my $mkimage = ""; # command to generate the initrd image ++my $use_hard_links = ''; # hardlinks do not work across fs boundaries ++my $postinst_hook = ''; #Normally we do not ++my $minimal_swap = ''; # Do not swap symlinks ++my $ignore_depmod_err = ''; # normally we do not ++my $kernel_arch = "=B"; ++my $ramdisk = ''; ++my $package_name = "linux-image-$version"; ++ ++#known variables ++my $image_dest = "/"; ++my $realimageloc = "/boot/"; ++my $have_conffile = ""; ++ ++my $modules_base = '/lib/modules'; ++my $CONF_LOC = '/etc/kernel-img.conf'; ++ ++# Ignore all invocations except when called on to configure. ++exit 0 unless $ARGV[0] =~ /configure/; ++ ++my $DEBUG = 0; ++ ++# Do some preliminary sanity checks here to ensure we actually have an ++# valid image dir ++chdir('/') or die "could not chdir to /:$!\n"; ++die "Internal Error: ($realimageloc) is not a directory!\n" ++ unless -d $realimageloc; ++ ++if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { ++ if (open(CONF, "$CONF_LOC")) { ++ while () { ++ chomp; ++ s/\#.*$//g; ++ next if /^\s*$/; ++ ++ $do_symlink = "" if /do_symlinks\s*=\s*(no|false|0)\s*$/i; ++ $no_symlink = "" if /no_symlinks\s*=\s*(no|false|0)\s*$/i; ++ $link_in_boot = "" if /link_in_boot\s*=\s*(no|false|0)\s*$/i; ++ $use_hard_links = '' if /use_hard_links\s*=\s*(no|false|0)\s*$/i; ++ $minimal_swap = '' if /minimal_swap\s*=\s*(no|false|0)\s*$/i; ++ $ignore_depmod_err = '' if /ignore_depmod_err\s*=\s*(no|false|0)\s*$/i; ++ ++ $do_symlink = "Yes" if /do_symlinks\s*=\s*(yes|true|1)\s*$/i; ++ $no_symlink = "Yes" if /no_symlinks\s*=\s*(yes|true|1)\s*$/i; ++ $link_in_boot = "Yes" if /link_in_boot\s*=\s*(yes|true|1)\s*$/i; ++ $use_hard_links = "Yes" if /use_hard_links\s*=\s*(yes|true|1)\s*$/i; ++ $minimal_swap = 'Yes' if /minimal_swap\s*=\s*(yes|true|1)\s*$/i; ++ $ignore_depmod_err = 'Yes' if /ignore_depmod_err\s*=\s*(yes|true|1)\s*$/i; ++ ++ $image_dest = "$1" if /image_dest\s*=\s*(\S+)/i; ++ $postinst_hook = "$1" if /postinst_hook\s*=\s*(\S+)/i; ++ $mkimage = "$1" if /mkimage\s*=\s*(.+)$/i; ++ $ramdisk = "$1" if /ramdisk\s*=\s*(.+)$/i; ++ } ++ close CONF; ++ $have_conffile = "Yes"; ++ } ++} ++ ++ ++if ($link_in_boot) { ++ $image_dest = $realimageloc; ++} ++ ++# Tack on at least one trainling / ++$image_dest = "$image_dest/"; ++$image_dest =~ s|^/*|/|o; ++$image_dest =~ s|/+$|/|o; ++ ++if (! -d "$image_dest") { ++ die "Expected Image Destination dir ($image_dest) to be a valid directory!\n"; ++} ++ ++# sanity ++if ($do_symlink && $no_symlink) { ++ warn "Both do_symlinks and no_symlinks options enabled; disabling no_symlinks\n"; ++ $no_symlink = 0; ++} ++ ++# most of our work is done in $image_dest (nominally /) ++chdir("$image_dest") or die "could not chdir to $image_dest:$!\n"; ++ ++$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch; ++ ++ ++die "Internal Error: Could not find image (" . $realimageloc ++ . "$kimage-$version)\n" unless -e $realimageloc ++ . "$kimage-$version"; ++ ++ ++###################################################################### ++###################################################################### ++########### Test whether a relative symlinkwould be OK ####### ++###################################################################### ++###################################################################### ++sub test_relative { ++ my %params = @_; ++ my $cwd; ++ ++ die "Internal Error: Missing Required paramater 'Old Dir' " ++ unless $params{'Old Dir'}; ++ die "Internal Error: Missing Required paramater New Dir' " ++ unless $params{'New Dir'}; ++ ++ ++ die "Internal Error: No such dir $params{'Old Dir'} " ++ unless -d $params{'Old Dir'}; ++ die "Internal Error: No such dir $params{'New Dir'} " ++ unless -d $params{'New Dir'}; ++ ++ warn "Test relative: testing $params{'Old Dir'} -> $params{'New Dir'}" ++ if $DEBUG; ++ chomp($cwd = `pwd`); ++ chdir ($params{'New Dir'}) or die "Could not chdir to $params{'New Dir'}:$!"; ++ my $ok = 0; ++ $params{'Old Dir'} =~ s|^/*||o; ++ if (-d $params{'Old Dir'} ) { ++ if (defined $params{'Test File'}) { ++ if (-e $params{'Old Dir'} . $params{'Test File'}) { ++ $ok = 1; ++ } ++ } else { ++ $ok = 1; # well, backward compatibility ++ } ++ } ++ chdir ($cwd) or die "Could not chdir to $params{'New Dir'}:$!"; ++ return $ok; ++} ++ ++ ++sub spath { ++ my %params = @_; ++ ++ die "Missing Required paramater 'Old'" unless $params{'Old'}; ++ die "Missing Required paramater 'New'" unless $params{'New'}; ++ ++ my @olddir = split '/', `readlink -q -m $params{'Old'}`; ++ my @newdir = split '/', `readlink -q -m $params{'New'}`; ++ my @outdir = @olddir; ++ ++ my $out = ''; ++ my $i; ++ for ($i = 0; $i <= $#olddir && $i <= $#newdir; $i++) { ++ $out++ if ($olddir[$i] ne $newdir[$i]); ++ shift @outdir unless $out; ++ unshift @outdir, ".." if $out; ++ } ++ if ($#newdir > $#olddir) { ++ for ($i=0; $i < $#newdir; $i++) { ++ unshift @outdir, ".."; ++ } ++ } ++ return join ('/', @outdir); ++} ++ ++# This routine is invoked if there is a symbolic link in place ++# in $image_dest/$kimage -- so a symlink exists in the destination. ++# What we are trying to determine is if we need to move the symbolic link over ++# to the the .old location ++sub move_p { ++ my $kimage = $_[0]; # Name of the symbolic link ++ my $image_dest = $_[1]; # The directory the links goes into ++ my $image_name = $_[2]; ++ my $src_dir = $_[3]; ++ my $force_move = 0; ++ warn "Move?: kimage=$kimage, image_dest=$image_dest, \n" . ++ "\timage_name=$image_name, src_dir=$src_dir" if $DEBUG; ++ ++ if ($no_symlink) { ++ # we do not want links, yet we have a symbolic link here! ++ warn "found a symbolic link in " . $image_dest . "$kimage \n" . ++ "even though no_symlink is defined\n" if $no_symlink; ++ # make sure we change this state of affairs ++ $force_move = 1; ++ return $force_move; ++ } ++ ++ warn "DEBUG: OK. We found symlink, and we should have a symlink here.\n" ++ if $DEBUG; ++ my $vmlinuz_target = readlink "$kimage"; ++ my $real_target = ''; ++ my $target = `readlink -q -m "${realimageloc}${kimage}-$version"`; ++ $real_target = abs_path($vmlinuz_target) if defined($vmlinuz_target); ++ ++ if (!defined($vmlinuz_target) || ! -f "$real_target") { ++ # what, a dangling symlink? ++ warn "The link " . $image_dest . "$kimage is a dangling link" . ++ "to $real_target\n"; ++ $force_move = 1; ++ return $force_move; ++ } ++ ++ ++ warn "DEBUG: The link $kimage points to ($vmlinuz_target)\n" if $DEBUG; ++ warn "DEBUG: ($vmlinuz_target) is really ($real_target)\n" if $DEBUG; ++ my $cwd; ++ chomp ($cwd=`pwd`); ++ if ($vmlinuz_target !~ m|^/|o) { ++ $vmlinuz_target = $cwd . "/" . $vmlinuz_target; ++ $vmlinuz_target =~ s|/+|/|o; ++ } ++ $vmlinuz_target = `readlink -q -m $vmlinuz_target`; ++ ++ if ("$vmlinuz_target" ne "$target") { ++ warn "DEBUG: We need to handle this.\n" if $DEBUG; ++ if ($minimal_swap) { ++ warn "DEBUG: Minimal swap.\n" if $DEBUG; ++ if (-l "$kimage.old") { ++ warn "DEBUG: There is an old link at $kimage.old\n" if $DEBUG; ++ my $old_target = readlink "$kimage.old"; ++ my $real_old_target = ''; ++ $real_old_target=abs_path($old_target) if defined ($old_target); ++ ++ if ($real_old_target && -f "$real_old_target") { ++ if ($old_target !~ m|^/|o) { ++ $old_target = $cwd . "/" . $old_target; ++ $old_target =~ s|/+|/|o; ++ } ++ $old_target = `readlink -q -m $old_target`; ++ if ("$old_target" ne "$target") { ++ $force_move = 1; ++ warn "DEBUG: Old link ($old_target) does not point to us ($target)\n" ++ if $DEBUG; ++ } ++ else { # The .old points to the current ++ warn "$kimage.old --> $target -- doing nothing"; ++ $force_move = 0; ++ } ++ } ++ else { ++ warn "DEBUG: Well, the old link does not exist -- so we move\n" ++ if $DEBUG; ++ $force_move = 1; ++ } ++ } ++ else { ++ warn "DEBUG: No .old link -- OK to move\n" ++ if $DEBUG; ++ $force_move = 1; ++ } ++ } ++ else { ++ warn "DEBUG: ok, minimal swap is no-- so we move.\n" ++ if $DEBUG; ++ $force_move = 1; ++ } ++ } ++ else { # already have proper link ++ warn "$kimage($vmlinuz_target) points to $target ($real_target) -- doing nothing"; ++ $force_move = 0; ++ } ++ return $force_move; ++} ++ ++ ++# This routine moves the symbolic link around (/vmlinuz -> /vmlinuz.old) ++# It pays attention to whether we should the fact whether we should be using ++# hard links or not. ++sub really_move_link { ++ my $kimage = $_[0]; # Name of the symbolic link ++ my $image_dest = $_[1]; # The directory the links goes into ++ my $image_name = $_[2]; ++ my $src_dir = $_[3]; ++ warn "really_move_link: kimage=$kimage, image_dest=$image_dest\n" . ++ "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG; ++ ++ # don't clobber $kimage.old quite yet ++ rename("$kimage", "$kimage.$$") || ++ die "failed to move " . $image_dest . "$kimage:$!"; ++ my $Old = $src_dir; ++ my $cwd; ++ ++ chomp($cwd=`pwd`); ++ if (test_relative ('Old Dir' => $Old, 'New Dir' => $cwd, ++ 'Test File' => "$image_name")) { ++ $Old =~ s|^/*||o; ++ } ++ # Special case is they are in the same dir ++ my $rel_path = spath('Old' => "$Old", 'New' => "$cwd" ); ++ $Old ="" if $rel_path =~ m/^\s*$/o; ++ ++ if ($use_hard_links =~ m/YES/i) { ++ if (! link("${Old}${image_name}", "$kimage")) { ++ rename("$kimage.$$", "$kimage"); ++ die("Failed to link ${Old}${image_name} to " . ++ "${image_dest}${kimage}.\n"); ++ } ++ } ++ else { ++ if (! symlink("${Old}${image_name}", "$kimage")) { ++ rename("$kimage.$$", "$kimage"); ++ die("Failed to symbolic-link ${Old}${image_name} to " . ++ "${image_dest}${kimage}.\n"); ++ } ++ } ++ ++ # Ok, now we may clobber the previous .old file ++ if (-l "$kimage.old" || ! -e "$kimage.old" ) { ++ rename("$kimage.$$", "$kimage.old"); ++ } ++ else { ++ warn "$kimage.old is not a symlink, not clobbering\n"; ++ warn "rm $kimage.$$"; ++ } ++} ++ ++# This routine handles a request to do symlinks, but there is no ++# symlink file already there. Either we are supposed to use copy, or we are ++# installing on a pristine system, or the user does not want symbolic links at ++# all. We use a configuration file to tell the last two cases apart, creating ++# a config file if needed. ++sub handle_missing_link { ++ my $kimage = $_[0]; # Name of the symbolic link ++ my $image_dest = $_[1]; # The directory the links goes into ++ my $image_name = $_[2]; ++ my $src_dir = $_[3]; ++ warn "handle_missing_link: kimage=$kimage, image_dest=$image_dest\n" . ++ "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG; ++ ++ if ($no_symlink) { ++ my $ret = system("cp -a --backup=t " . $realimageloc . ++ "$image_name " . " $kimage"); ++ if ($ret) { ++ die("Failed to copy " . $realimageloc . "$image_name to " ++ . $image_dest . "$kimage .\n"); ++ } ++ } ++ ++ if (! $no_symlink && $do_symlink =~ /Yes/i) { ++ my $Old = $realimageloc; ++ my $New = $image_dest; ++ my $Name = "$image_name"; ++ my $Link_Dest = "$kimage"; ++ ++ if (test_relative ('Old Dir' => $Old, ++ 'New Dir' => $New, ++ 'Test File' => $Name)) { ++ $Old =~ s|^/*||o; ++ } ++ # Special case is they are in the same dir ++ my $rel_path = spath('Old' => "$Old", 'New' => "$New" ); ++ $Old ="" if $rel_path =~ m/^\s*$/o; ++ ++ symlink($Old . "$Name", "$Link_Dest") || ++ die("Failed to symbolic-link ${Old}$Name to $Link_Dest.\n"); ++ ++ } ++} ++ ++# This routine handles the rest of the cases, where the user has requested ++# non-traditional handling, like using cp or hard links. ++sub handle_non_symlinks { ++ my $kimage = $_[0]; # Name of the symbolic link ++ my $image_dest = $_[1]; # The directory the links goes into ++ my $image_name = $_[2]; ++ my $src_dir = $_[3]; ++ warn "handle_non_link: kimage=$kimage, image_dest=$image_dest\n" . ++ "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG; ++ ++ # Save the current image. We do this in all four cases ++ rename("$kimage", "$kimage.$$") || ++ die "failed to move " . $image_dest . "$kimage:$!"; ++ ++ ##,#### ++ # case One ++ #`#### ++ if ($no_symlink) { ++ # Maybe /$image_dest is on a dos system? ++ my $ret = system("cp -a --backup=t " . $realimageloc ++ . "$image_name " . "$kimage"); ++ if ($ret) { ++ if (-e "$kimage.$$") { ++ rename("$kimage.$$", "$kimage"); ++ } ++ die("Failed to copy " . $realimageloc . "$image_name to " ++ . $image_dest . "$kimage .\n"); ++ } ++ } ++ ##,#### ++ # case Two ++ #`#### ++ elsif ($use_hard_links =~ m/YES/i ) { ++ # Ok then. this ought to be a hard link, and hence fair game ++ # don't clobber $kimage.old quite yet ++ my $Old = $realimageloc; ++ my $cwd; ++ chomp($cwd=`pwd`); ++ if (test_relative ('Old Dir' => $Old, 'New Dir' => $cwd, ++ 'Test File' => "$image_name")) { ++ $Old =~ s|^/*||o; ++ } ++ # Special case is they are in the same dir ++ my $rel_path = spath('Old' => "$Old", 'New' => "$cwd" ); ++ $Old ="" if $rel_path =~ m/^\s*$/o; ++ ++ if (! link($Old . "$image_name", "$kimage")) { ++ rename("$kimage.$$", "$kimage"); ++ die("Failed to hard link " . $realimageloc . "$image_name to " ++ . $image_dest . "$kimage .\n"); ++ } ++ } ++ ##,#### ++ # case Three ++ #`#### ++ else { ++ # We just use cp ++ my $ret = system("cp -a --backup=t " . $realimageloc ++ . "$image_name " . "$kimage"); ++ if ($ret) { ++ if (-e "$kimage.$$") { ++ rename("$kimage.$$", "$kimage"); ++ } ++ die("Failed to copy " . $realimageloc . "$image_name to " ++ . $image_dest . "$kimage .\n"); ++ } ++ } ++ # Ok, now we may clobber the previous .old file ++ rename("$kimage.$$", "$kimage.old") if -e "$kimage.$$"; ++} ++ ++# This routine is responsible for setting up the symbolic links ++# So, the actual kernel image lives in ++# $realimageloc/$image_name (/boot/vmlinuz-2.6.12). ++# This routine creates symbolic links in $image_dest/$kimage (/vmlinuz) ++sub image_magic { ++ my $kimage = $_[0]; # Name of the symbolic link ++ my $image_dest = $_[1]; # The directory the links goes into ++ my $image_name = "$kimage-$version"; ++ my $src_dir = $realimageloc; ++ warn "image_magic: kimage=$kimage, image_dest=$image_dest\n" . ++ "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG; ++ ++ if (-l "$kimage") { # There is a symbolic link ++ warn "DEBUG: There is a symlink for $kimage\n" if $DEBUG; ++ my $force_move = move_p($kimage, $image_dest, $image_name, $src_dir); ++ ++ if ($force_move) { ++ really_move_link($kimage, $image_dest, $image_name, $src_dir); ++ } ++ } ++ elsif (! -e "$kimage") { ++ # Hmm. Pristine system? How can that be? Installing from scratch? ++ # Or maybe the user does not want a symbolic link here. ++ # Possibly they do not want a link here. (we should be in / ++ # here[$image_dest, really] ++ handle_missing_link($kimage, $image_dest, $image_name, $src_dir); ++ } ++ elsif (-e "$kimage" ) { ++ # OK, $kimage exists -- but is not a link ++ handle_non_symlinks($kimage, $image_dest, $image_name, $src_dir); ++ } ++} ++ ++###################################################################### ++###################################################################### ++###################################################################### ++###################################################################### ++ ++sub do_modules { ++ print STDERR "Running depmod.\n"; ++ my $ret = system("depmod -a -F $realimageloc/System.map-$version $version"); ++ my $exit_value = $? >> 8; ++ my $signal_num = $? & 127; ++ my $dumped_core = $? & 128; ++ if ($ret) { ++ my $seen; ++ my $answer; ++ my $question; ++ $question = "${package_name}/postinst/depmod-error-initrd-$version"; ++ ++ ($ret,$seen) = fset ("$question", 'seen', 'false'); ++ die "Error setting debconf flags in $question: $seen" if $ret; ++ ++ $ret = subst("$question", 'modules_base', "$modules_base"); ++ die "Error setting debconf substitutions in $question: $seen" if $ret; ++ ++ $ret = subst("$question", 'SIGNAL', ", and got a signal $signal_num"); ++ die "Error setting debconf substitutions in $question: $seen" if $ret; ++ ++ if ($dumped_core) { ++ $ret = subst("$question", 'CORE', ", and dumped core"); ++ die "Error setting debconf substitutions in $question: $seen" if $ret; ++ } ++ else { ++ $ret = subst("$question", 'CORE', " "); ++ die "Error setting debconf substitutions in $question: $seen" if $ret; ++ } ++ ++ ($ret,$seen) = input('medium', "$question"); ++ if ($ret && $ret != 30 ) { ++ die "Error setting debconf question $question: $seen"; ++ } ++ ++ ($ret,$seen) = go (); ++ if ($ret && $ret != 30 ) { ++ die "Error asking debconf question $question: $seen"; ++ } ++ ++ ($ret,$answer) = get("$question"); ++ die "Error retreiving answer for $question: $answer" if $ret; ++ ++ if (! $ignore_depmod_err) { ++ if ($answer =~ /^(y|t)/i) { ++ exit(1); ++ } ++ else { ++ print STDERR "Ok, continuing as directed\n"; ++ } ++ } ++ } ++ ++ # If we are installing (not upgrading) a package for a newer ++ # upstream version than that of the running kernel, check whether ++ # the user might be missing necessary firmware, perhaps because ++ # it has now been removed from the kernel. ++ # ++ # We base this check on the modules used in the running kernel and ++ # the corresponding (by name) modules in the new kernel. This is ++ # not entirely accurate because: ++ # 1. A device may now be handled by a module with a different name, ++ # leading us to miss the dependency ++ # 2. A device may be handled by a module that needs firmware only ++ # for some other device, leading us to claim a dependency wrongly ++ ++ if (!defined($ARGV[1]) || $ARGV[1] eq '') { ++ sub version_code { ++ my $version = shift; ++ $version =~ s/^2\.(\d+)\.(\d+).*/2*65536 + $1*256 + $2/e ++ or $version =~ s/^(\d+)\.(\d+).*/$1*65536 + $2*256/e ++ or $version = 0; ++ return $version; ++ } ++ (undef, undef, my $running_version) = POSIX::uname(); ++ ++ if (version_code($version) > version_code($running_version)) { ++ my $missing = ''; ++ my %module_paths; ++ open(DEP, "<$modules_base/$version/modules.dep") or return; ++ while () { ++ if (m|(.*/([^/]*)\.ko):|) { ++ my ($path, $module) = ($1, $2); ++ $module =~ s/-/_/g; ++ $module_paths{$module} = $path; ++ } ++ } ++ close(DEP); ++ open(MODULES, ') { ++ s/ .*//s; ++ my $module = $_; ++ my $module_path = $module_paths{$module}; ++ if (defined($module_path)) { ++ my $first = 1; ++ if ($module_path !~ m|^/|) { ++ $module_path = "$modules_base/$version/$module_path"; ++ } ++ open(MODINFO, "modinfo -F firmware '$module_path' |"); ++ while () { ++ chomp; ++ my $firmware = $_; ++ unless (-e "/lib/firmware/$firmware" || ++ -e "/lib/firmware/$version/$firmware") { ++ if ($first) { ++ $missing .= "\\n" if $missing ne ''; ++ $missing .= "$module: "; ++ $first = 0; ++ } else { ++ $missing .= ', '; ++ } ++ $missing .= $firmware; ++ } ++ } ++ close(MODINFO); ++ } ++ } ++ close(MODULES); ++ ++ if ($missing ne '') { ++ my ($ret, $seen); ++ my $text = "${package_name}/postinst/missing-firmware-${version}"; ++ ++ ($ret, $seen) = subst($text, 'runningversion', $running_version); ++ die "Error setting debconf substitutions in $text: $seen" if $ret; ++ ++ ($ret, $seen) = subst($text, 'version', $version); ++ die "Error setting debconf substitutions in $text: $seen" if $ret; ++ ++ ($ret, $seen) = subst($text, 'missing', $missing); ++ die "Error setting debconf substitutions in $text: $seen" if $ret; ++ ++ ($ret, $seen) = input('high', $text); ++ if ($ret && $ret != 30) { ++ die "Error setting debconf question $text: $seen"; ++ } ++ ++ ($ret, $seen) = go(); ++ if ($ret && $ret != 30) { ++ die "Error asking debconf question $text: $seen"; ++ } ++ } ++ } ++ } ++} ++ ++# We may not have any modules installed ++if (-d "$modules_base/$version") { ++ &do_modules(); ++} ++ ++ ++# Warn if we are ignoring the old ramdisk setting ++if ($ramdisk =~ /\S/) { ++ my ($question, $ret, $seen); ++ $question = "${package_name}/postinst/ignoring-ramdisk"; ++ ($ret,$seen) = input('high', "$question"); ++ die "Error setting debconf question $question: $seen" if $ret && $ret != 30; ++ ($ret,$seen) = go(); ++ die "Error asking debconf question $question: $seen" if $ret && $ret != 30; ++} ++ ++# Only change the symlinks if we are not being upgraded ++if (! defined $ARGV[1] || ! $ARGV[1] || $ARGV[1] =~ m//o) { ++ image_magic($kimage, $image_dest); ++ if ($initrd) { ++ image_magic("initrd.img", $image_dest); ++ } ++} ++else { ++ if (! -e "$kimage") { ++ handle_missing_link($kimage, $image_dest, "$kimage-$version", ++ $realimageloc); ++ } ++ if ($initrd && ! -e "initrd.img") { ++ handle_missing_link("initrd.img", $image_dest, "initrd.img-$version", ++ $realimageloc); ++ } ++} ++ ++# set the env var stem ++$ENV{'STEM'} = "linux"; ++sub run_hook { ++ my $type = shift; ++ my $script = shift; ++ ++ print STDERR "Running $script.\n"; ++ system ("$script $version $realimageloc$kimage-$version") && ++ print STDERR "User $type hook script [$script] "; ++ if ($?) { ++ if ($? == -1) { ++ print STDERR "failed to execute: $!\n"; ++ } ++ elsif ($? & 127) { ++ printf STDERR "died with signal %d, %s coredump\n", ++ ($? & 127), ($? & 128) ? 'with' : 'without'; ++ } ++ else { ++ printf STDERR "exited with value %d\n", $? >> 8; ++ } ++ exit $? >> 8; ++ } ++} ++ ++my $options; ++for (@ARGV) { ++ s,','\\'',g; ++ $options .= " '$_'"; ++} ++$ENV{'DEB_MAINT_PARAMS'}="$options"; ++ ++## Run user hook script here, if any ++if ($postinst_hook) { ++ &run_hook("postinst", $postinst_hook); ++} ++ ++if (-d "/etc/kernel/postinst.d") { ++ print STDERR "Examining /etc/kernel/postinst.d.\n"; ++ system ("run-parts --verbose --exit-on-error --arg=$version " . ++ "--arg=$realimageloc$kimage-$version " . ++ "/etc/kernel/postinst.d") && ++ die "Failed to process /etc/kernel/postinst.d"; ++} ++ ++if (-d "/etc/kernel/postinst.d/$version") { ++ print STDERR "Examining /etc/kernel/postinst.d/$version.\n"; ++ system ("run-parts --verbose --exit-on-error --arg=$version " . ++ "--arg=$realimageloc$kimage-$version " . ++ "/etc/kernel/postinst.d/$version") && ++ die "Failed to process /etc/kernel/postinst.d/$version"; ++} ++ ++exit 0; ++ ++__END__ +diff --git a/debian/templates/temp.image.plain/postrm b/debian/templates/temp.image.plain/postrm +new file mode 100755 +index 0000000..4ef4651 +--- /dev/null ++++ b/debian/templates/temp.image.plain/postrm +@@ -0,0 +1,272 @@ ++#! /usr/bin/perl ++# ++use strict; ++use warnings; ++use Cwd 'abs_path'; ++ ++# Debconf may not be around here. ++my $have_debconf = 0; ++my $capb; ++ ++eval {require Debconf::Client::ConfModule;}; ++if ( ! $@ ) ++{ ++ $have_debconf++; ++ import Debconf::Client::ConfModule ':all'; ++ version('2.0'); ++ $capb=capb("backup"); ++} ++ ++$|=1; ++# Predefined values: ++my $version = "=V"; ++my $link_in_boot = ""; ++my $kimage = "=K"; ++my $initrd = "=I"; # initrd kernel ++my $postrm_hook = ''; #Normally we do not ++my $kernel_arch = "=B"; ++my $ramdisk = "=MK"; # List of tools to create initial ram fs. ++my $package_name = "linux-image-$version"; ++ ++#known variables ++my $image_dest = "/"; ++my $realimageloc = "/boot/"; ++my $CONF_LOC = '/etc/kernel-img.conf'; ++ ++chdir('/') or die "could not chdir to /:$!\n"; ++ ++ ++if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { ++ if (open(CONF, "$CONF_LOC")) { ++ while () { ++ chomp; ++ s/\#.*$//g; ++ next if /^\s*$/; ++ ++ $link_in_boot = "" if /link_in_boot\s*=\s*(no|false|0)\s*$/i; ++ ++ $link_in_boot = "Yes" if /link_in_boot\s*=\s*(yes|true|1)\s*$/i; ++ ++ $image_dest = "$1" if /image_dest\s*=\s*(\S+)/i; ++ $postrm_hook = "$1" if /postrm_hook\s*=\s*(\S+)/i; ++ } ++ close CONF; ++ } ++} ++ ++if ($link_in_boot) { ++ $image_dest = $realimageloc; ++} ++ ++$image_dest = "$image_dest/"; ++$image_dest =~ s|/+$|/|o; ++ ++# The destdir may be gone by now. ++if (-d "$image_dest") { ++ chdir("$image_dest") or die "could not chdir to $image_dest:$!\n"; ++} ++ ++$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch; ++ ++ ++###################################################################### ++###################################################################### ++############ ++###################################################################### ++###################################################################### ++sub remove_sym_link { ++ my $bad_image = $_[0]; ++ ++ warn "Removing symbolic link $bad_image \n"; ++ warn "You may need to re-run your boot loader\n"; ++ # Remove the dangling link ++ unlink "$bad_image"; ++} ++ ++###################################################################### ++###################################################################### ++############ ++###################################################################### ++###################################################################### ++sub CanonicalizePath { ++ my $path = join '/', @_; ++ my @work = split '/', $path; ++ my @out; ++ my $is_absolute; ++ ++ if (@work && $work[0] eq "") { $is_absolute = 1; shift @work; } ++ ++ while (@work) { ++ my $seg = shift @work; ++ if ($seg eq "." || $seg eq "") { ++ } elsif ($seg eq "..") { ++ if (@out && $out[-1] ne "..") { ++ pop @out; ++ } else { ++ # Leading "..", or "../..", etc. ++ push @out, $seg; ++ } ++ } else { ++ push @out, $seg; ++ } ++ } ++ ++ unshift @out, "" if $is_absolute; ++ return join('/', @out); ++} ++ ++###################################################################### ++###################################################################### ++############ ++###################################################################### ++###################################################################### ++# This removes dangling symlinks. What do we do about hard links? Surely a ++# something with the nane $image_dest . "$kimage" ought not to be left behind? ++sub image_magic { ++ my $kimage = $_[0]; ++ my $image_dest = $_[1]; ++ ++ if (-l "$kimage") { ++ # There is a symbolic link ++ my $force_move = 0; ++ my $vmlinuz_target = readlink "$kimage"; ++ my $real_target = ''; ++ $real_target = abs_path($vmlinuz_target) if defined ($vmlinuz_target); ++ if (!defined($vmlinuz_target) || ! -f "$real_target") { ++ # what, a dangling symlink? ++ warn "The link " . $image_dest . "$kimage is a damaged link\n"; ++ # Remove the dangling link ++ &remove_sym_link("$kimage"); ++ } ++ else { ++ my $canonical_target = CanonicalizePath("$vmlinuz_target"); ++ if (! -e $canonical_target) { ++ warn "The link " . $image_dest . "$kimage is a dangling link\n"; ++ &remove_sym_link("$kimage"); ++ } ++ } ++ } ++} ++ ++# set the env var stem ++$ENV{'STEM'} = "linux"; ++ ++sub exec_script { ++ my $type = shift; ++ my $script = shift; ++ print STDERR "Running $type hook script $script.\n"; ++ system ("$script $version $realimageloc$kimage-$version") && ++ print STDERR "User $type hook script [$script] "; ++ if ($?) { ++ if ($? == -1) { ++ print STDERR "failed to execute: $!\n"; ++ } ++ elsif ($? & 127) { ++ printf STDERR "died with signal %d, %s coredump\n", ++ ($? & 127), ($? & 128) ? 'with' : 'without'; ++ } ++ else { ++ printf STDERR "exited with value %d\n", $? >> 8; ++ } ++ } ++} ++sub run_hook { ++ my $type = shift; ++ my $script = shift; ++ if ($script =~ m,^/,) { ++ # Full path provided for the hook script ++ if (-x "$script") { ++ &exec_script($type,$script); ++ } ++ else { ++ warn "The provided $type hook script [$script] could not be run.\n"; ++ } ++ } ++ else { ++ # Look for it in a safe path ++ for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { ++ if (-x "$path/$script") { ++ &exec_script($type, "$path/$script"); ++ return 0; ++ } ++ } ++ # No luck ++ print STDERR "Could not find $type hook script [$script].\n"; ++ warn "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; ++ } ++} ++ ++my $options; ++for (@ARGV) { ++ s,','\\'',g; ++ $options .= " '$_'"; ++} ++$ENV{'DEB_MAINT_PARAMS'}="$options"; ++ ++## Run user hook script here, if any ++if ($postrm_hook) { ++ &run_hook("postrm", $postrm_hook); ++} ++if (-d "/etc/kernel/postrm.d") { ++ warn "Examining /etc/kernel/postrm.d .\n"; ++ system ("run-parts --verbose --exit-on-error --arg=$version " . ++ "--arg=$realimageloc$kimage-$version " . ++ "/etc/kernel/postrm.d") && ++ die "Failed to process /etc/kernel/postrm.d"; ++} ++if (-d "/etc/kernel/postrm.d/$version") { ++ warn "Examining /etc/kernel/postrm.d/$version .\n"; ++ system ("run-parts --verbose --exit-on-error --arg=$version " . ++ "--arg=$realimageloc$kimage-$version " . ++ "/etc/kernel/postrm.d/$version") && ++ die "Failed to process /etc/kernel/postrm.d/$version"; ++} ++ ++# purge initramfs and related ++if ($ARGV[0] !~ /upgrade/) { ++ if (-f $realimageloc . "initrd.img-$version") { ++ unlink $realimageloc . "initrd.img-$version"; ++ } ++ if (-f $realimageloc . "initrd.img-$version.bak") { ++ unlink $realimageloc . "initrd.img-$version.bak"; ++ } ++ if (-f "/var/lib/initramfs-tools/$version") { ++ unlink "/var/lib/initramfs-tools/$version"; ++ } ++ # check and remove damaged and dangling symlinks ++ image_magic($kimage, $image_dest); ++ image_magic($kimage . ".old", $image_dest); ++ image_magic("initrd.img", $image_dest) if $initrd; ++ image_magic("initrd.img.old", $image_dest) if $initrd; ++} ++ ++ ++# Ignore all invocations except when called on to purge. ++exit 0 unless $ARGV[0] =~ /purge/; ++ ++my $ret = purge(); ++ ++my @files_to_remove = qw{ ++ modules.dep modules.isapnpmap modules.pcimap ++ modules.usbmap modules.parportmap ++ modules.generic_string modules.ieee1394map ++ modules.ieee1394map modules.pnpbiosmap ++ modules.alias modules.ccwmap modules.inputmap ++ modules.symbols modules.ofmap ++ modules.seriomap modules.*.bin ++ modules.softdep modules.devname ++ }; ++ ++foreach my $extra_file (@files_to_remove) { ++ for (glob("/lib/modules/$version/$extra_file")) { ++ unlink; ++ } ++} ++ ++if (-d "/lib/modules/$version" ) { ++ system ("rmdir", "/lib/modules/$version"); ++} ++ ++exit 0; ++ ++__END__ +diff --git a/debian/templates/temp.image.plain/preinst b/debian/templates/temp.image.plain/preinst +new file mode 100755 +index 0000000..8bf10e7 +--- /dev/null ++++ b/debian/templates/temp.image.plain/preinst +@@ -0,0 +1,124 @@ ++#! /usr/bin/perl ++# ++use strict; ++use warnings; ++ ++use Debconf::Client::ConfModule qw(:all); ++version('2.0'); ++my $capb=capb("backup"); ++ ++$|=1; ++ ++# Predefined values: ++my $version = "=V"; ++my $kimage = "=K"; ++my $preinst_hook = ''; #Normally we do not ++my $kernel_arch = "=B"; ++my $package_name = "linux-image-$version"; ++ ++#known variables ++my $realimageloc = "/boot/"; ++my $CONF_LOC = '/etc/kernel-img.conf'; ++ ++my $modules_base = '/lib/modules'; ++ ++die "Pre inst Internal error. Aborting." unless $version; ++ ++exit 0 if $ARGV[0] =~ /abort-upgrade/; ++exit 1 unless $ARGV[0] =~ /(install|upgrade)/; ++ ++if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { ++ if (open(CONF, "$CONF_LOC")) { ++ while () { ++ chomp; ++ s/\#.*$//g; ++ next if /^\s*$/; ++ ++ $preinst_hook = "$1" if /preinst_hook\s*=\s*(\S+)/i; ++ } ++ close CONF; ++ } ++} ++ ++$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch; ++ ++ ++# set the env var stem ++$ENV{'STEM'} = "linux"; ++ ++sub exec_script { ++ my $type = shift; ++ my $script = shift; ++ print STDERR "Running $type hook script $script.\n"; ++ system ("$script $version $realimageloc$kimage-$version") && ++ print STDERR "User $type hook script [$script] "; ++ if ($?) { ++ if ($? == -1) { ++ print STDERR "failed to execute: $!\n"; ++ } ++ elsif ($? & 127) { ++ printf STDERR "died with signal %d, %s coredump\n", ++ ($? & 127), ($? & 128) ? 'with' : 'without'; ++ } ++ else { ++ printf STDERR "exited with value %d\n", $? >> 8; ++ } ++ exit $? >> 8; ++ } ++} ++sub run_hook { ++ my $type = shift; ++ my $script = shift; ++ if ($script =~ m,^/,) { ++ # Full path provided for the hook script ++ if (-x "$script") { ++ &exec_script($type,$script); ++ } ++ else { ++ die "The provided $type hook script [$script] could not be run.\n"; ++ } ++ } ++ else { ++ # Look for it in a safe path ++ for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { ++ if (-x "$path/$script") { ++ &exec_script($type, "$path/$script"); ++ return 0; ++ } ++ } ++ # No luck ++ print STDERR "Could not find $type hook script [$script].\n"; ++ die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; ++ } ++} ++ ++ ++my $options; ++for (@ARGV) { ++ s,','\\'',g; ++ $options .= " '$_'"; ++} ++$ENV{'DEB_MAINT_PARAMS'}="$options"; ++ ++## Run user hook script here, if any ++if (-x "$preinst_hook") { ++ &run_hook("preinst", $preinst_hook); ++} ++if (-d "/etc/kernel/preinst.d") { ++ print STDERR "Examining /etc/kernel/preinst.d/\n"; ++ system ("run-parts --verbose --exit-on-error --arg=$version" . ++ " --arg=$realimageloc$kimage-$version" . ++ " /etc/kernel/preinst.d") && ++ die "Failed to process /etc/kernel/preinst.d"; ++} ++if (-d "/etc/kernel/preinst.d/$version") { ++ print STDERR "Examining /etc/kernel/preinst.d/$version.\n"; ++ system ("run-parts --verbose --exit-on-error --arg=$version" . ++ " --arg=$realimageloc$kimage-$version" . ++ " /etc/kernel/preinst.d/$version") && ++ die "Failed to process /etc/kernel/preinst.d/$version"; ++} ++ ++exit 0; ++ ++__END__ +diff --git a/debian/templates/temp.image.plain/prerm b/debian/templates/temp.image.plain/prerm +new file mode 100755 +index 0000000..3c43b9f +--- /dev/null ++++ b/debian/templates/temp.image.plain/prerm +@@ -0,0 +1,163 @@ ++#! /usr/bin/perl ++# ++use strict; ++use warnings; ++use Debconf::Client::ConfModule qw(:all); ++version('2.0'); ++my $capb=capb("backup"); ++ ++$|=1; ++# Predefined values: ++my $version = "=V"; ++my $kimage = "=K"; ++my $prerm_hook = ''; #Normally we do not ++my $kernel_arch = "=B"; ++my $package_name = "linux-image-$version"; ++ ++#known variables ++my $realimageloc = "/boot/"; ++my $CONF_LOC = '/etc/kernel-img.conf'; ++ ++# Variables used ++my $image=''; ++my $ret=0; ++my $seen=''; ++my $answer=''; ++my $running = ''; ++my $WouldInvalidate = 0; ++ ++# Ignore all invocations uxcept when called on to remove ++exit 0 unless ($ARGV[0] && $ARGV[0] =~ /remove/) ; ++ ++if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { ++ if (open(CONF, "$CONF_LOC")) { ++ while () { ++ chomp; ++ s/\#.*$//g; ++ next if /^\s*$/; ++ ++ $prerm_hook = "$1" if /prerm_hook\s*=\s*(\S+)/i; ++ } ++ close CONF; ++ } ++} ++ ++ ++$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch; ++ ++#check to see if we are trying to remove a running kernel ++# if so we abort right now. ++chop($running=`uname -r`); ++if ($running eq $version) { ++ my $question = "${package_name}/prerm/removing-running-kernel-$version"; ++ ++ ($ret,$seen) = fset ("$question", 'seen', 'false'); ++ die "Error setting debconf flags in $question: $seen" if $ret; ++ ++ $ret = subst("$question", 'running', "$running"); ++ die "Error setting debconf substitutions in $question: $seen" if $ret; ++ ++ ($ret,$seen) = input('critical', "$question"); ++ if ($ret && $ret != 30 ) { ++ die "Error setting debconf question $question: $seen"; ++ } ++ ++ ($ret,$seen) = go (); ++ if ($ret && $ret != 30 ) { ++ die "Error asking debconf question $question: $seen"; ++ } ++ ++ ($ret,$answer) = get("$question"); ++ die "Error retreiving answer for $question: $answer" if $ret; ++ ++ if ($answer =~ /^(y|t)/i) { ++ print STDERR "Aborting removal of running kernel image.\n"; ++ exit 1; #Operation not permitted ++ } ++ else { ++ print STDERR "Ok, proceeding with removing running kernel image.\n"; ++ } ++} ++ ++#Now, they have an alternate kernel which they are currently running ++ ++chdir("/") or die "could not chdir to /:$!\n"; ++ ++ ++# set the env var stem ++$ENV{'STEM'} = "linux"; ++ ++sub exec_script { ++ my $type = shift; ++ my $script = shift; ++ print STDERR "Running $type hook script $script.\n"; ++ system ("$script $version $realimageloc$kimage-$version") && ++ print STDERR "User $type hook script [$script] "; ++ if ($?) { ++ if ($? == -1) { ++ print STDERR "failed to execute: $!\n"; ++ } ++ elsif ($? & 127) { ++ printf STDERR "died with signal %d, %s coredump\n", ++ ($? & 127), ($? & 128) ? 'with' : 'without'; ++ } ++ else { ++ printf STDERR "exited with value %d\n", $? >> 8; ++ } ++ exit $? >> 8; ++ } ++} ++sub run_hook { ++ my $type = shift; ++ my $script = shift; ++ if ($script =~ m,^/,) { ++ # Full path provided for the hook script ++ if (-x "$script") { ++ &exec_script($type,$script); ++ } ++ else { ++ die "The provided $type hook script [$script] could not be run.\n"; ++ } ++ } ++ else { ++ # Look for it in a safe path ++ for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { ++ if (-x "$path/$script") { ++ &exec_script($type, "$path/$script"); ++ return 0; ++ } ++ } ++ # No luck ++ print STDERR "Could not find $type hook script [$script].\n"; ++ die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; ++ } ++} ++ ++ ++my $options; ++for (@ARGV) { ++ s,','\\'',g; ++ $options .= " '$_'"; ++} ++$ENV{'DEB_MAINT_PARAMS'}="$options"; ++ ++## Run user hook script here, if any ++if (-x "$prerm_hook") { ++ &run_hook("prerm", $prerm_hook); ++} ++if (-d "/etc/kernel/prerm.d") { ++ print STDERR "Examining /etc/kernel/prerm.d.\n"; ++ system ("run-parts --verbose --exit-on-error --arg=$version " . ++ "--arg=$realimageloc$kimage-$version /etc/kernel/prerm.d") && ++ die "Failed to process /etc/kernel/prerm.d"; ++} ++if (-d "/etc/kernel/prerm.d/$version") { ++ print STDERR "Examining /etc/kernel/prerm.d/$version.\n"; ++ system ("run-parts --verbose --exit-on-error --arg=$version" . ++ " --arg=$realimageloc$kimage-$version " . ++ "/etc/kernel/prerm.d/$version") && ++ die "Failed to process /etc/kernel/prerm.d/$version"; ++} ++ ++exit 0; ++__END__ +diff --git a/debian/templates/temp.image.plain/templates b/debian/templates/temp.image.plain/templates +new file mode 100644 +index 0000000..a9005bf +--- /dev/null ++++ b/debian/templates/temp.image.plain/templates +@@ -0,0 +1,63 @@ ++# These templates have mostly been reviewed by the debian-l10n-english ++# team ++# ++# If modifications/additions/rewording are needed, please ask ++# debian-l10n-english@lists.debian.org for advice. ++# ++# Even minor modifications require translation updates and such ++# changes should be coordinated with translators and reviewers. ++ ++Template: linux-image-=V/postinst/depmod-error-initrd-=V ++Type: boolean ++Default: false ++_Description: Abort installation after depmod error? ++ The 'depmod' command exited with the exit code ${exit_value} ++ (${SIGNAL}${CORE}). ++ . ++ Since this image uses initrd, the ${modules_base}/=V/modules.dep file ++ will not be deleted, even though it may be invalid. ++ . ++ You should abort the installation and fix the ++ errors in depmod, or regenerate the initrd image with a known good ++ modules.dep file. If you don't abort the installation, there is ++ a danger that the system will fail to boot. ++ ++Template: linux-image-=V/prerm/removing-running-kernel-=V ++Type: boolean ++Default: true ++_Description: Abort kernel removal? ++ You are running a kernel (version ${running}) and attempting to remove ++ the same version. ++ . ++ This can make the system unbootable as it will remove ++ /boot/vmlinuz-${running} and all modules under the directory ++ /lib/modules/${running}. This can only be fixed with a copy of the ++ kernel image and the corresponding modules. ++ . ++ It is highly recommended to abort the kernel removal unless you are ++ prepared to fix the system after removal. ++ ++Template: linux-image-=V/postinst/missing-firmware-=V ++Type: note ++#flag:translate!:3 ++_Description: Required firmware files may be missing ++ This system is currently running Linux ${runningversion} and you are ++ installing Linux ${version}. In the new version some of the drivers ++ used on this system may require additional firmware files: ++ . ++ ${missing} ++ . ++ Most firmware files are not included in the system because they do ++ not conform to the Debian Free Software Guidelines. You may need to ++ reconfigure the package manager to include the contrib and non-free ++ sections of the package archive before you can install these ++ firmware files. ++ ++# This has not yet been reviewed ++Template: linux-image-=V/postinst/ignoring-ramdisk ++Type: error ++_Description: Ramdisk configuration must be updated ++ Kernel packages will no longer run a specific ramdisk creator. The ++ ramdisk creator package must install a script in ++ /etc/kernel/postinst.d, and you should remove the line beginning ++ 'ramdisk =' from /etc/kernel-img.conf. +diff --git a/drivers/Kconfig b/drivers/Kconfig +index b5e6f24..b67a808 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -136,4 +136,8 @@ source "drivers/hv/Kconfig" + + source "drivers/devfreq/Kconfig" + ++source "drivers/net/dpa/NetCommSw/Kconfig" ++ ++source "drivers/bcmdrivers/Kconfig" ++ + endmenu +diff --git a/drivers/Makefile b/drivers/Makefile +index 1b31421..9352f86 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -132,3 +132,4 @@ obj-$(CONFIG_VIRT_DRIVERS) += virt/ + obj-$(CONFIG_HYPERV) += hv/ + + obj-$(CONFIG_PM_DEVFREQ) += devfreq/ ++obj-y += bcmdrivers/ +diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c +index 7f9eba9..0eefa12 100644 +--- a/drivers/acpi/pci_irq.c ++++ b/drivers/acpi/pci_irq.c +@@ -487,10 +487,10 @@ int acpi_pci_irq_enable(struct pci_dev *dev) + else + link_desc[0] = '\0'; + +- dev_info(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n", +- pin_name(pin), link_desc, gsi, +- (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", +- (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); ++ dev_dbg(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n", ++ pin_name(pin), link_desc, gsi, ++ (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", ++ (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); + + return 0; + } +@@ -524,6 +524,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev) + * (e.g. PCI_UNDEFINED_IRQ). + */ + +- dev_info(&dev->dev, "PCI INT %c disabled\n", pin_name(pin)); ++ dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin)); + acpi_unregister_gsi(gsi); + } +diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c +index ac28db3..31bbf15 100644 +--- a/drivers/acpi/processor_driver.c ++++ b/drivers/acpi/processor_driver.c +@@ -447,7 +447,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) + { + struct acpi_processor *pr = NULL; + int result = 0; +- struct sys_device *sysdev; ++ struct device *dev; + + pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); + if (!pr) +@@ -492,14 +492,15 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) + + per_cpu(processors, pr->id) = pr; + +- sysdev = get_cpu_sysdev(pr->id); +- if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) { ++ dev = get_cpu_device(pr->id); ++ if (sysfs_create_link(&device->dev.kobj, &dev->kobj, "sysdev")) { + result = -EFAULT; + goto err_free_cpumask; + } + + #ifdef CONFIG_CPU_FREQ + acpi_processor_ppc_has_changed(pr, 0); ++ acpi_processor_load_module(pr); + #endif + acpi_processor_get_throttling_info(pr); + acpi_processor_get_limit_info(pr); +diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c +index 85b3237..0af48a8 100644 +--- a/drivers/acpi/processor_perflib.c ++++ b/drivers/acpi/processor_perflib.c +@@ -240,6 +240,28 @@ void acpi_processor_ppc_exit(void) + acpi_processor_ppc_status &= ~PPC_REGISTERED; + } + ++/* ++ * Do a quick check if the systems looks like it should use ACPI ++ * cpufreq. We look at a _PCT method being available, but don't ++ * do a whole lot of sanity checks. ++ */ ++void acpi_processor_load_module(struct acpi_processor *pr) ++{ ++ static int requested; ++ acpi_status status = 0; ++ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; ++ ++ if (!arch_has_acpi_pdc() || requested) ++ return; ++ status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer); ++ if (!ACPI_FAILURE(status)) { ++ printk(KERN_INFO PREFIX "Requesting acpi_cpufreq\n"); ++ request_module_nowait("acpi_cpufreq"); ++ requested = 1; ++ } ++ kfree(buffer.pointer); ++} ++ + static int acpi_processor_get_performance_control(struct acpi_processor *pr) + { + int result = 0; +diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c +index 4da7d9d..641b545 100644 +--- a/drivers/acpi/processor_thermal.c ++++ b/drivers/acpi/processor_thermal.c +@@ -30,7 +30,6 @@ + #include + #include + #include +-#include + + #include + +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index e2958aa..371670f 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -357,6 +357,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { + /* JMicron 360/1/3/5/6, match class to avoid IDE function */ + { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, ++ /* JMicron 362B and 362C have an AHCI function with IDE class code */ ++ { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, ++ { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, + + /* ATI */ + { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ +diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c +index b1e8e11..3716945 100644 +--- a/drivers/ata/ata_piix.c ++++ b/drivers/ata/ata_piix.c +@@ -1608,6 +1608,58 @@ static bool piix_broken_system_poweroff(struct pci_dev *pdev) + return false; + } + ++static int prefer_ms_hyperv = 1; ++module_param(prefer_ms_hyperv, int, 0); ++ ++static void piix_ignore_devices_quirk(struct ata_host *host) ++{ ++#if IS_ENABLED(CONFIG_HYPERV_STORAGE) ++ static const struct dmi_system_id ignore_hyperv[] = { ++ { ++ /* On Hyper-V hypervisors the disks are exposed on ++ * both the emulated SATA controller and on the ++ * paravirtualised drivers. The CD/DVD devices ++ * are only exposed on the emulated controller. ++ * Request we ignore ATA devices on this host. ++ */ ++ .ident = "Hyper-V Virtual Machine", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, ++ "Microsoft Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), ++ }, ++ }, ++ { } /* terminate list */ ++ }; ++ static const struct dmi_system_id allow_virtual_pc[] = { ++ { ++ /* In MS Virtual PC guests the DMI ident is nearly ++ * identical to a Hyper-V guest. One difference is the ++ * product version which is used here to identify ++ * a Virtual PC guest. This entry allows ata_piix to ++ * drive the emulated hardware. ++ */ ++ .ident = "MS Virtual PC 2007", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, ++ "Microsoft Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"), ++ }, ++ }, ++ { } /* terminate list */ ++ }; ++ const struct dmi_system_id *ignore = dmi_first_match(ignore_hyperv); ++ const struct dmi_system_id *allow = dmi_first_match(allow_virtual_pc); ++ ++ if (ignore && !allow && prefer_ms_hyperv) { ++ host->flags |= ATA_HOST_IGNORE_ATA; ++ dev_info(host->dev, "%s detected, ATA device ignore set\n", ++ ignore->ident); ++ } ++#endif ++} ++ + /** + * piix_init_one - Register PIIX ATA PCI device with kernel services + * @pdev: PCI device to register +@@ -1723,6 +1775,9 @@ static int __devinit piix_init_one(struct pci_dev *pdev, + } + host->flags |= ATA_HOST_PARALLEL_SCAN; + ++ /* Allow hosts to specify device types to ignore when scanning. */ ++ piix_ignore_devices_quirk(host); ++ + pci_set_master(pdev); + return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht); + } +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index 4e9beff..e0f7692 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -171,6 +171,17 @@ static bool ata_sstatus_online(u32 sstatus) + return (sstatus & 0xf) == 0x3; + } + ++static unsigned int ata_host_get_n_tags(const struct ata_host *host) ++{ ++ return (host->flags & ATA_HOST_N_TAGS_MASK) >> ATA_HOST_N_TAGS_SHIFT; ++} ++ ++static void ata_host_set_n_tags(struct ata_host *host, unsigned int n_tags) ++{ ++ host->flags = ((host->flags & ~ATA_HOST_N_TAGS_MASK) | ++ (n_tags << ATA_HOST_N_TAGS_SHIFT)); ++} ++ + /** + * ata_link_next - link iteration helper + * @link: the previous link, NULL to start +@@ -1978,6 +1989,12 @@ retry: + if (class == ATA_DEV_ATA) { + if (!ata_id_is_ata(id) && !ata_id_is_cfa(id)) + goto err_out; ++ if (ap->host->flags & ATA_HOST_IGNORE_ATA && ++ ata_id_is_ata(id)) { ++ ata_dev_dbg(dev, ++ "host indicates ignore ATA devices, ignored\n"); ++ return -ENOENT; ++ } + } else { + if (ata_id_is_ata(id)) + goto err_out; +@@ -4727,7 +4744,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) + static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) + { + struct ata_queued_cmd *qc = NULL; +- unsigned int max_queue = ap->host->n_tags; ++ unsigned int max_queue = ata_host_get_n_tags(ap->host); + unsigned int i, tag; + + /* no command while frozen */ +@@ -5931,7 +5948,7 @@ void ata_host_init(struct ata_host *host, struct device *dev, + { + spin_lock_init(&host->lock); + mutex_init(&host->eh_mutex); +- host->n_tags = ATA_MAX_QUEUE - 1; ++ ata_host_set_n_tags(host, ATA_MAX_QUEUE - 1); + host->dev = dev; + host->flags = flags; + host->ops = ops; +@@ -6012,7 +6029,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) + { + int i, rc; + +- host->n_tags = clamp(sht->can_queue, 1, ATA_MAX_QUEUE - 1); ++ ata_host_set_n_tags(host, clamp(sht->can_queue, 1, ATA_MAX_QUEUE - 1)); + + /* host must have been started */ + if (!(host->flags & ATA_HOST_STARTED)) { +@@ -6634,21 +6651,8 @@ u32 ata_wait_register(struct ata_port *ap, void __iomem *reg, u32 mask, u32 val, + */ + bool sata_lpm_ignore_phy_events(struct ata_link *link) + { +- unsigned long lpm_timeout = link->last_lpm_change + +- msecs_to_jiffies(ATA_TMOUT_SPURIOUS_PHY); +- + /* if LPM is enabled, PHYRDY doesn't mean anything */ +- if (link->lpm_policy > ATA_LPM_MAX_POWER) +- return true; +- +- /* ignore the first PHY event after the LPM policy changed +- * as it is might be spurious +- */ +- if ((link->flags & ATA_LFLAG_CHANGED) && +- time_before(jiffies, lpm_timeout)) +- return true; +- +- return false; ++ return !!(link->lpm_policy > ATA_LPM_MAX_POWER); + } + EXPORT_SYMBOL_GPL(sata_lpm_ignore_phy_events); + +diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c +index f54b0775..7d1a478 100644 +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -3423,9 +3423,6 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, + } + } + +- link->last_lpm_change = jiffies; +- link->flags |= ATA_LFLAG_CHANGED; +- + return 0; + + fail: +diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c +index 22edc92..c90b590 100644 +--- a/drivers/ata/libata-sff.c ++++ b/drivers/ata/libata-sff.c +@@ -561,12 +561,27 @@ unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf, + struct ata_port *ap = dev->link->ap; + void __iomem *data_addr = ap->ioaddr.data_addr; + unsigned int words = buflen >> 1; ++ unsigned int word; + + /* Transfer multiple of 2 bytes */ +- if (rw == READ) ++ if (rw == READ) { + ioread16_rep(data_addr, buf, words); +- else ++ } else { ++ for (word = 0; word < words; word++) { ++ unsigned char tmp; ++ tmp = buf[word * 2]; ++ buf[word * 2] = buf[word * 2 + 1]; ++ buf[word * 2 + 1] = tmp; ++ } + iowrite16_rep(data_addr, buf, words); ++ } ++ ++ for (word = 0; word < words; word++) { ++ unsigned char tmp; ++ tmp = buf[word * 2]; ++ buf[word * 2] = buf[word * 2 + 1]; ++ buf[word * 2 + 1] = tmp; ++ } + + /* Transfer trailing byte, if any. */ + if (unlikely(buflen & 0x01)) { +@@ -581,9 +596,9 @@ unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf, + */ + if (rw == READ) { + ioread16_rep(data_addr, pad, 1); +- *buf = pad[0]; ++ *buf = pad[1]; + } else { +- pad[0] = *buf; ++ pad[1] = *buf; + iowrite16_rep(data_addr, pad, 1); + } + words++; +diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c +index 2a472c5..7128350 100644 +--- a/drivers/ata/pata_of_platform.c ++++ b/drivers/ata/pata_of_platform.c +@@ -23,9 +23,11 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev) + struct resource io_res; + struct resource ctl_res; + struct resource irq_res; +- unsigned int reg_shift = 0; ++ unsigned int port_width = 1; ++ bool port_bswap = 0; + int pio_mode = 0; + int pio_mask; ++ const u32 *reg_shift_prop, *port_width_prop; + const u32 *prop; + + ret = of_address_to_resource(dn, 0, &io_res); +@@ -57,26 +59,31 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev) + else + irq_res.flags = 0; + +- prop = of_get_property(dn, "reg-shift", NULL); +- if (prop) +- reg_shift = be32_to_cpup(prop); ++ reg_shift_prop = of_get_property(dn, "reg-shift", NULL); ++ port_width_prop = of_get_property(dn, "port-width", NULL); ++ if (reg_shift_prop && port_width_prop) { ++ dev_err(&ofdev->dev, "invalid configuration, reg-shift and port-width " ++ "are mutually exclusive\n"); ++ return -EINVAL; ++ } ++ ++ if (reg_shift_prop) { ++ unsigned int reg_shift = be32_to_cpup(reg_shift_prop); ++ port_width = (reg_shift ? (reg_shift << 1) : 1); ++ } else if (port_width_prop) { ++ port_width = be32_to_cpup(port_width_prop); ++ } + +- prop = of_get_property(dn, "pio-mode", NULL); ++ prop = of_get_property(dn, "port-bswap", NULL); + if (prop) { +- pio_mode = be32_to_cpup(prop); +- if (pio_mode > 6) { +- dev_err(&ofdev->dev, "invalid pio-mode\n"); +- return -EINVAL; +- } +- } else { +- dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n"); ++ port_bswap = (be32_to_cpup(prop) != 0); + } + + pio_mask = 1 << pio_mode; + pio_mask |= (1 << pio_mode) - 1; + + return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res, +- reg_shift, pio_mask); ++ port_width, port_bswap, pio_mask); + } + + static int __devexit pata_of_platform_remove(struct platform_device *ofdev) +diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c +index 2067308..e493501 100644 +--- a/drivers/ata/pata_platform.c ++++ b/drivers/ata/pata_platform.c +@@ -55,20 +55,83 @@ static struct ata_port_operations pata_platform_port_ops = { + .set_mode = pata_platform_set_mode, + }; + ++static void bswap_buf16(unsigned char *buf, unsigned int words) ++{ ++ u16 *wbuf = (u16 *)buf; ++ unsigned int word; ++ ++ for (word = 0; word < words; word++) { ++ *wbuf = (*wbuf << 8) | ((*wbuf >> 8) & 0xff); ++ wbuf++; ++ } ++} ++ ++static unsigned int pata_platform_data_xfer_bswap(struct ata_device *dev, unsigned char *buf, ++ unsigned int buflen, int rw) ++{ ++ struct ata_port *ap = dev->link->ap; ++ void __iomem *data_addr = ap->ioaddr.data_addr; ++ unsigned int words = buflen >> 1; ++ ++ if (ap->pflags & ATA_PFLAG_PIO32) { ++ dev_err(&dev->tdev, "32-bit PIO with port-bswap not impelemented\n"); ++ return 0; ++ } ++ ++ /* Transfer multiple of 2 bytes */ ++ if (rw == READ) { ++ ioread16_rep(data_addr, buf, words); ++ } else { ++ bswap_buf16(buf, words); ++ iowrite16_rep(data_addr, buf, words); ++ } ++ ++ bswap_buf16(buf, words); ++ ++ /* Transfer trailing byte, if any. */ ++ if (unlikely(buflen & 0x01)) { ++ unsigned char pad[2] = { }; ++ ++ /* Point buf to the tail of buffer */ ++ buf += buflen - 1; ++ ++ if (rw == READ) { ++ ioread16_rep(data_addr, pad, 1); ++ *buf = pad[1]; ++ } else { ++ pad[1] = *buf; ++ iowrite16_rep(data_addr, pad, 1); ++ } ++ words++; ++ } ++ ++ return words << 1; ++} ++ + static void pata_platform_setup_port(struct ata_ioports *ioaddr, +- unsigned int shift) ++ unsigned int port_width, ++ bool port_bswap) + { ++ unsigned int port_shift = port_width >> 1; ++ unsigned int data_offset = 0; ++ unsigned int ctl_offset = 0; ++ ++ if (port_bswap) { ++ data_offset = (port_width - 2); ++ ctl_offset = (port_width - 1); ++ } ++ + /* Fixup the port shift for platforms that need it */ +- ioaddr->data_addr = ioaddr->cmd_addr + (ATA_REG_DATA << shift); +- ioaddr->error_addr = ioaddr->cmd_addr + (ATA_REG_ERR << shift); +- ioaddr->feature_addr = ioaddr->cmd_addr + (ATA_REG_FEATURE << shift); +- ioaddr->nsect_addr = ioaddr->cmd_addr + (ATA_REG_NSECT << shift); +- ioaddr->lbal_addr = ioaddr->cmd_addr + (ATA_REG_LBAL << shift); +- ioaddr->lbam_addr = ioaddr->cmd_addr + (ATA_REG_LBAM << shift); +- ioaddr->lbah_addr = ioaddr->cmd_addr + (ATA_REG_LBAH << shift); +- ioaddr->device_addr = ioaddr->cmd_addr + (ATA_REG_DEVICE << shift); +- ioaddr->status_addr = ioaddr->cmd_addr + (ATA_REG_STATUS << shift); +- ioaddr->command_addr = ioaddr->cmd_addr + (ATA_REG_CMD << shift); ++ ioaddr->data_addr = ioaddr->cmd_addr + (ATA_REG_DATA << port_shift) + data_offset; ++ ioaddr->error_addr = ioaddr->cmd_addr + (ATA_REG_ERR << port_shift) + ctl_offset; ++ ioaddr->feature_addr = ioaddr->cmd_addr + (ATA_REG_FEATURE << port_shift) + ctl_offset; ++ ioaddr->nsect_addr = ioaddr->cmd_addr + (ATA_REG_NSECT << port_shift) + ctl_offset; ++ ioaddr->lbal_addr = ioaddr->cmd_addr + (ATA_REG_LBAL << port_shift) + ctl_offset; ++ ioaddr->lbam_addr = ioaddr->cmd_addr + (ATA_REG_LBAM << port_shift) + ctl_offset; ++ ioaddr->lbah_addr = ioaddr->cmd_addr + (ATA_REG_LBAH << port_shift) + ctl_offset; ++ ioaddr->device_addr = ioaddr->cmd_addr + (ATA_REG_DEVICE << port_shift) + ctl_offset; ++ ioaddr->status_addr = ioaddr->cmd_addr + (ATA_REG_STATUS << port_shift) + ctl_offset; ++ ioaddr->command_addr = ioaddr->cmd_addr + (ATA_REG_CMD << port_shift) + ctl_offset; + } + + /** +@@ -102,7 +165,8 @@ int __devinit __pata_platform_probe(struct device *dev, + struct resource *io_res, + struct resource *ctl_res, + struct resource *irq_res, +- unsigned int ioport_shift, ++ unsigned int port_width, ++ bool port_bswap, + int __pio_mask) + { + struct ata_host *host; +@@ -166,7 +230,12 @@ int __devinit __pata_platform_probe(struct device *dev, + + ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr; + +- pata_platform_setup_port(&ap->ioaddr, ioport_shift); ++ pata_platform_setup_port(&ap->ioaddr, port_width, port_bswap); ++ if (port_bswap) { ++ pata_platform_port_ops.sff_data_xfer = pata_platform_data_xfer_bswap; ++ } ++ dev_info(dev, "port width: %u byte swap %s\n", ++ port_width, port_bswap ? "enabled" : "disabled"); + + ata_port_desc(ap, "%s cmd 0x%llx ctl 0x%llx", mmio ? "mmio" : "ioport", + (unsigned long long)io_res->start, +@@ -238,7 +307,8 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) + irq_res->flags = pp_info ? pp_info->irq_flags : 0; + + return __pata_platform_probe(&pdev->dev, io_res, ctl_res, irq_res, +- pp_info ? pp_info->ioport_shift : 0, ++ pp_info ? pp_info->port_width : 1, ++ pp_info ? pp_info->port_bswap : false, + pio_mask); + } + +diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c +index 89b30f3..bfe7195 100644 +--- a/drivers/atm/ambassador.c ++++ b/drivers/atm/ambassador.c +@@ -1926,10 +1926,8 @@ static int __devinit ucode_init (loader_block * lb, amb_dev * dev) { + int res; + + res = request_ihex_firmware(&fw, "atmsar11.fw", &dev->pci_dev->dev); +- if (res) { +- PRINTK (KERN_ERR, "Cannot load microcode data"); ++ if (res) + return res; +- } + + /* First record contains just the start address */ + rec = (const struct ihex_binrec *)fw->data; +diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c +index 361f5ae..490cd80 100644 +--- a/drivers/atm/fore200e.c ++++ b/drivers/atm/fore200e.c +@@ -2519,10 +2519,9 @@ fore200e_load_and_start_fw(struct fore200e* fore200e) + return err; + + sprintf(buf, "%s%s", fore200e->bus->proc_name, FW_EXT); +- if ((err = request_firmware(&firmware, buf, device)) < 0) { +- printk(FORE200E "problem loading firmware image %s\n", fore200e->bus->model_name); ++ err = request_firmware(&firmware, buf, device); ++ if (err) + return err; +- } + + fw_data = (__le32 *) firmware->data; + fw_size = firmware->size / sizeof(u32); +diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig +index 21cf46f..4ebc5d3 100644 +--- a/drivers/base/Kconfig ++++ b/drivers/base/Kconfig +@@ -172,6 +172,10 @@ config SYS_HYPERVISOR + bool + default n + ++config GENERIC_CPU_DEVICES ++ bool ++ default n ++ + source "drivers/base/regmap/Kconfig" + + endmenu +diff --git a/drivers/base/Makefile b/drivers/base/Makefile +index 99a375a..1334d89 100644 +--- a/drivers/base/Makefile ++++ b/drivers/base/Makefile +@@ -3,7 +3,8 @@ + obj-y := core.o sys.o bus.o dd.o syscore.o \ + driver.o class.o platform.o \ + cpu.o firmware.o init.o map.o devres.o \ +- attribute_container.o transport_class.o ++ attribute_container.o transport_class.o \ ++ topology.o + obj-$(CONFIG_DEVTMPFS) += devtmpfs.o + obj-y += power/ + obj-$(CONFIG_HAS_DMA) += dma-mapping.o +@@ -12,7 +13,6 @@ obj-$(CONFIG_ISA) += isa.o + obj-$(CONFIG_FW_LOADER) += firmware_class.o + obj-$(CONFIG_NUMA) += node.o + obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o +-obj-$(CONFIG_SMP) += topology.o + ifeq ($(CONFIG_SYSFS),y) + obj-$(CONFIG_MODULES) += module.o + endif +diff --git a/drivers/base/base.h b/drivers/base/base.h +index 21c1b96..b858dfd 100644 +--- a/drivers/base/base.h ++++ b/drivers/base/base.h +@@ -4,7 +4,9 @@ + * struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure. + * + * @subsys - the struct kset that defines this subsystem +- * @devices_kset - the list of devices associated ++ * @devices_kset - the subsystem's 'devices' directory ++ * @interfaces - list of subsystem interfaces associated ++ * @mutex - protect the devices, and interfaces lists. + * + * @drivers_kset - the list of drivers associated + * @klist_devices - the klist to iterate over the @devices_kset +@@ -14,10 +16,8 @@ + * @bus - pointer back to the struct bus_type that this structure is associated + * with. + * +- * @class_interfaces - list of class_interfaces associated + * @glue_dirs - "glue" directory to put in-between the parent device to + * avoid namespace conflicts +- * @class_mutex - mutex to protect the children, devices, and interfaces lists. + * @class - pointer back to the struct class that this structure is associated + * with. + * +@@ -28,6 +28,8 @@ + struct subsys_private { + struct kset subsys; + struct kset *devices_kset; ++ struct list_head interfaces; ++ struct mutex mutex; + + struct kset *drivers_kset; + struct klist klist_devices; +@@ -36,9 +38,7 @@ struct subsys_private { + unsigned int drivers_autoprobe:1; + struct bus_type *bus; + +- struct list_head class_interfaces; + struct kset glue_dirs; +- struct mutex class_mutex; + struct class *class; + }; + #define to_subsys_private(obj) container_of(obj, struct subsys_private, subsys.kobj) +@@ -94,8 +94,7 @@ extern int hypervisor_init(void); + static inline int hypervisor_init(void) { return 0; } + #endif + extern int platform_bus_init(void); +-extern int system_bus_init(void); +-extern int cpu_dev_init(void); ++extern void cpu_dev_init(void); + + extern int bus_add_device(struct device *dev); + extern void bus_probe_device(struct device *dev); +@@ -116,6 +115,7 @@ extern char *make_class_name(const char *name, struct kobject *kobj); + + extern int devres_release_all(struct device *dev); + ++/* /sys/devices directory */ + extern struct kset *devices_kset; + + #if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS) +diff --git a/drivers/base/bus.c b/drivers/base/bus.c +index b802cfc..cd8337b 100644 +--- a/drivers/base/bus.c ++++ b/drivers/base/bus.c +@@ -16,9 +16,14 @@ + #include + #include + #include ++#include + #include "base.h" + #include "power/power.h" + ++/* /sys/devices/system */ ++/* FIXME: make static after drivers/base/sys.c is deleted */ ++struct kset *system_kset; ++ + #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) + + /* +@@ -362,6 +367,47 @@ struct device *bus_find_device_by_name(struct bus_type *bus, + } + EXPORT_SYMBOL_GPL(bus_find_device_by_name); + ++/** ++ * subsys_find_device_by_id - find a device with a specific enumeration number ++ * @subsys: subsystem ++ * @id: index 'id' in struct device ++ * @hint: device to check first ++ * ++ * Check the hint's next object and if it is a match return it directly, ++ * otherwise, fall back to a full list search. Either way a reference for ++ * the returned object is taken. ++ */ ++struct device *subsys_find_device_by_id(struct bus_type *subsys, unsigned int id, ++ struct device *hint) ++{ ++ struct klist_iter i; ++ struct device *dev; ++ ++ if (!subsys) ++ return NULL; ++ ++ if (hint) { ++ klist_iter_init_node(&subsys->p->klist_devices, &i, &hint->p->knode_bus); ++ dev = next_device(&i); ++ if (dev && dev->id == id && get_device(dev)) { ++ klist_iter_exit(&i); ++ return dev; ++ } ++ klist_iter_exit(&i); ++ } ++ ++ klist_iter_init_node(&subsys->p->klist_devices, &i, NULL); ++ while ((dev = next_device(&i))) { ++ if (dev->id == id && get_device(dev)) { ++ klist_iter_exit(&i); ++ return dev; ++ } ++ } ++ klist_iter_exit(&i); ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(subsys_find_device_by_id); ++ + static struct device_driver *next_driver(struct klist_iter *i) + { + struct klist_node *n = klist_next(i); +@@ -489,38 +535,59 @@ out_put: + void bus_probe_device(struct device *dev) + { + struct bus_type *bus = dev->bus; ++ struct subsys_interface *sif; + int ret; + +- if (bus && bus->p->drivers_autoprobe) { ++ if (!bus) ++ return; ++ ++ if (bus->p->drivers_autoprobe) { + ret = device_attach(dev); + WARN_ON(ret < 0); + } ++ ++ mutex_lock(&bus->p->mutex); ++ list_for_each_entry(sif, &bus->p->interfaces, node) ++ if (sif->add_dev) ++ sif->add_dev(dev, sif); ++ mutex_unlock(&bus->p->mutex); + } + + /** + * bus_remove_device - remove device from bus + * @dev: device to be removed + * +- * - Remove symlink from bus's directory. ++ * - Remove device from all interfaces. ++ * - Remove symlink from bus' directory. + * - Delete device from bus's list. + * - Detach from its driver. + * - Drop reference taken in bus_add_device(). + */ + void bus_remove_device(struct device *dev) + { +- if (dev->bus) { +- sysfs_remove_link(&dev->kobj, "subsystem"); +- sysfs_remove_link(&dev->bus->p->devices_kset->kobj, +- dev_name(dev)); +- device_remove_attrs(dev->bus, dev); +- if (klist_node_attached(&dev->p->knode_bus)) +- klist_del(&dev->p->knode_bus); +- +- pr_debug("bus: '%s': remove device %s\n", +- dev->bus->name, dev_name(dev)); +- device_release_driver(dev); +- bus_put(dev->bus); +- } ++ struct bus_type *bus = dev->bus; ++ struct subsys_interface *sif; ++ ++ if (!bus) ++ return; ++ ++ mutex_lock(&bus->p->mutex); ++ list_for_each_entry(sif, &bus->p->interfaces, node) ++ if (sif->remove_dev) ++ sif->remove_dev(dev, sif); ++ mutex_unlock(&bus->p->mutex); ++ ++ sysfs_remove_link(&dev->kobj, "subsystem"); ++ sysfs_remove_link(&dev->bus->p->devices_kset->kobj, ++ dev_name(dev)); ++ device_remove_attrs(dev->bus, dev); ++ if (klist_node_attached(&dev->p->knode_bus)) ++ klist_del(&dev->p->knode_bus); ++ ++ pr_debug("bus: '%s': remove device %s\n", ++ dev->bus->name, dev_name(dev)); ++ device_release_driver(dev); ++ bus_put(dev->bus); + } + + static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv) +@@ -849,14 +916,14 @@ static ssize_t bus_uevent_store(struct bus_type *bus, + static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); + + /** +- * bus_register - register a bus with the system. ++ * __bus_register - register a driver-core subsystem + * @bus: bus. + * + * Once we have that, we registered the bus with the kobject + * infrastructure, then register the children subsystems it has: +- * the devices and drivers that belong to the bus. ++ * the devices and drivers that belong to the subsystem. + */ +-int bus_register(struct bus_type *bus) ++int __bus_register(struct bus_type *bus, struct lock_class_key *key) + { + int retval; + struct subsys_private *priv; +@@ -900,6 +967,8 @@ int bus_register(struct bus_type *bus) + goto bus_drivers_fail; + } + ++ INIT_LIST_HEAD(&priv->interfaces); ++ __mutex_init(&priv->mutex, "subsys mutex", key); + klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); + klist_init(&priv->klist_drivers, NULL, NULL); + +@@ -929,7 +998,7 @@ out: + bus->p = NULL; + return retval; + } +-EXPORT_SYMBOL_GPL(bus_register); ++EXPORT_SYMBOL_GPL(__bus_register); + + /** + * bus_unregister - remove a bus from the system +@@ -941,6 +1010,8 @@ EXPORT_SYMBOL_GPL(bus_register); + void bus_unregister(struct bus_type *bus) + { + pr_debug("bus: '%s': unregistering\n", bus->name); ++ if (bus->dev_root) ++ device_unregister(bus->dev_root); + bus_remove_attrs(bus); + remove_probe_files(bus); + kset_unregister(bus->p->drivers_kset); +@@ -1030,10 +1101,194 @@ void bus_sort_breadthfirst(struct bus_type *bus, + } + EXPORT_SYMBOL_GPL(bus_sort_breadthfirst); + ++/** ++ * subsys_dev_iter_init - initialize subsys device iterator ++ * @iter: subsys iterator to initialize ++ * @subsys: the subsys we wanna iterate over ++ * @start: the device to start iterating from, if any ++ * @type: device_type of the devices to iterate over, NULL for all ++ * ++ * Initialize subsys iterator @iter such that it iterates over devices ++ * of @subsys. If @start is set, the list iteration will start there, ++ * otherwise if it is NULL, the iteration starts at the beginning of ++ * the list. ++ */ ++void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct bus_type *subsys, ++ struct device *start, const struct device_type *type) ++{ ++ struct klist_node *start_knode = NULL; ++ ++ if (start) ++ start_knode = &start->p->knode_bus; ++ klist_iter_init_node(&subsys->p->klist_devices, &iter->ki, start_knode); ++ iter->type = type; ++} ++EXPORT_SYMBOL_GPL(subsys_dev_iter_init); ++ ++/** ++ * subsys_dev_iter_next - iterate to the next device ++ * @iter: subsys iterator to proceed ++ * ++ * Proceed @iter to the next device and return it. Returns NULL if ++ * iteration is complete. ++ * ++ * The returned device is referenced and won't be released till ++ * iterator is proceed to the next device or exited. The caller is ++ * free to do whatever it wants to do with the device including ++ * calling back into subsys code. ++ */ ++struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter) ++{ ++ struct klist_node *knode; ++ struct device *dev; ++ ++ for (;;) { ++ knode = klist_next(&iter->ki); ++ if (!knode) ++ return NULL; ++ dev = container_of(knode, struct device_private, knode_bus)->device; ++ if (!iter->type || iter->type == dev->type) ++ return dev; ++ } ++} ++EXPORT_SYMBOL_GPL(subsys_dev_iter_next); ++ ++/** ++ * subsys_dev_iter_exit - finish iteration ++ * @iter: subsys iterator to finish ++ * ++ * Finish an iteration. Always call this function after iteration is ++ * complete whether the iteration ran till the end or not. ++ */ ++void subsys_dev_iter_exit(struct subsys_dev_iter *iter) ++{ ++ klist_iter_exit(&iter->ki); ++} ++EXPORT_SYMBOL_GPL(subsys_dev_iter_exit); ++ ++int subsys_interface_register(struct subsys_interface *sif) ++{ ++ struct bus_type *subsys; ++ struct subsys_dev_iter iter; ++ struct device *dev; ++ ++ if (!sif || !sif->subsys) ++ return -ENODEV; ++ ++ subsys = bus_get(sif->subsys); ++ if (!subsys) ++ return -EINVAL; ++ ++ mutex_lock(&subsys->p->mutex); ++ list_add_tail(&sif->node, &subsys->p->interfaces); ++ if (sif->add_dev) { ++ subsys_dev_iter_init(&iter, subsys, NULL, NULL); ++ while ((dev = subsys_dev_iter_next(&iter))) ++ sif->add_dev(dev, sif); ++ subsys_dev_iter_exit(&iter); ++ } ++ mutex_unlock(&subsys->p->mutex); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(subsys_interface_register); ++ ++void subsys_interface_unregister(struct subsys_interface *sif) ++{ ++ struct bus_type *subsys = sif->subsys; ++ struct subsys_dev_iter iter; ++ struct device *dev; ++ ++ if (!sif) ++ return; ++ ++ mutex_lock(&subsys->p->mutex); ++ list_del_init(&sif->node); ++ if (sif->remove_dev) { ++ subsys_dev_iter_init(&iter, subsys, NULL, NULL); ++ while ((dev = subsys_dev_iter_next(&iter))) ++ sif->remove_dev(dev, sif); ++ subsys_dev_iter_exit(&iter); ++ } ++ mutex_unlock(&subsys->p->mutex); ++ ++ bus_put(subsys); ++} ++EXPORT_SYMBOL_GPL(subsys_interface_unregister); ++ ++static void system_root_device_release(struct device *dev) ++{ ++ kfree(dev); ++} ++/** ++ * subsys_system_register - register a subsystem at /sys/devices/system/ ++ * @subsys - system subsystem ++ * @groups - default attributes for the root device ++ * ++ * All 'system' subsystems have a /sys/devices/system/ root device ++ * with the name of the subsystem. The root device can carry subsystem- ++ * wide attributes. All registered devices are below this single root ++ * device and are named after the subsystem with a simple enumeration ++ * number appended. The registered devices are not explicitely named; ++ * only 'id' in the device needs to be set. ++ * ++ * Do not use this interface for anything new, it exists for compatibility ++ * with bad ideas only. New subsystems should use plain subsystems; and ++ * add the subsystem-wide attributes should be added to the subsystem ++ * directory itself and not some create fake root-device placed in ++ * /sys/devices/system/. ++ */ ++int subsys_system_register(struct bus_type *subsys, ++ const struct attribute_group **groups) ++{ ++ struct device *dev; ++ int err; ++ ++ err = bus_register(subsys); ++ if (err < 0) ++ return err; ++ ++ dev = kzalloc(sizeof(struct device), GFP_KERNEL); ++ if (!dev) { ++ err = -ENOMEM; ++ goto err_dev; ++ } ++ ++ err = dev_set_name(dev, "%s", subsys->name); ++ if (err < 0) ++ goto err_name; ++ ++ dev->kobj.parent = &system_kset->kobj; ++ dev->groups = groups; ++ dev->release = system_root_device_release; ++ ++ err = device_register(dev); ++ if (err < 0) ++ goto err_dev_reg; ++ ++ subsys->dev_root = dev; ++ return 0; ++ ++err_dev_reg: ++ put_device(dev); ++ dev = NULL; ++err_name: ++ kfree(dev); ++err_dev: ++ bus_unregister(subsys); ++ return err; ++} ++EXPORT_SYMBOL_GPL(subsys_system_register); ++ + int __init buses_init(void) + { + bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); + if (!bus_kset) + return -ENOMEM; ++ ++ system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj); ++ if (!system_kset) ++ return -ENOMEM; ++ + return 0; + } +diff --git a/drivers/base/class.c b/drivers/base/class.c +index b80d91c..03243d4 100644 +--- a/drivers/base/class.c ++++ b/drivers/base/class.c +@@ -184,9 +184,9 @@ int __class_register(struct class *cls, struct lock_class_key *key) + if (!cp) + return -ENOMEM; + klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put); +- INIT_LIST_HEAD(&cp->class_interfaces); ++ INIT_LIST_HEAD(&cp->interfaces); + kset_init(&cp->glue_dirs); +- __mutex_init(&cp->class_mutex, "struct class mutex", key); ++ __mutex_init(&cp->mutex, "subsys mutex", key); + error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name); + if (error) { + kfree(cp); +@@ -460,15 +460,15 @@ int class_interface_register(struct class_interface *class_intf) + if (!parent) + return -EINVAL; + +- mutex_lock(&parent->p->class_mutex); +- list_add_tail(&class_intf->node, &parent->p->class_interfaces); ++ mutex_lock(&parent->p->mutex); ++ list_add_tail(&class_intf->node, &parent->p->interfaces); + if (class_intf->add_dev) { + class_dev_iter_init(&iter, parent, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) + class_intf->add_dev(dev, class_intf); + class_dev_iter_exit(&iter); + } +- mutex_unlock(&parent->p->class_mutex); ++ mutex_unlock(&parent->p->mutex); + + return 0; + } +@@ -482,7 +482,7 @@ void class_interface_unregister(struct class_interface *class_intf) + if (!parent) + return; + +- mutex_lock(&parent->p->class_mutex); ++ mutex_lock(&parent->p->mutex); + list_del_init(&class_intf->node); + if (class_intf->remove_dev) { + class_dev_iter_init(&iter, parent, NULL, NULL); +@@ -490,7 +490,7 @@ void class_interface_unregister(struct class_interface *class_intf) + class_intf->remove_dev(dev, class_intf); + class_dev_iter_exit(&iter); + } +- mutex_unlock(&parent->p->class_mutex); ++ mutex_unlock(&parent->p->mutex); + + class_put(parent); + } +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 81e0e87..72a7fa8 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -118,6 +118,56 @@ static const struct sysfs_ops dev_sysfs_ops = { + .store = dev_attr_store, + }; + ++#define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr) ++ ++ssize_t device_store_ulong(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct dev_ext_attribute *ea = to_ext_attr(attr); ++ char *end; ++ unsigned long new = simple_strtoul(buf, &end, 0); ++ if (end == buf) ++ return -EINVAL; ++ *(unsigned long *)(ea->var) = new; ++ /* Always return full write size even if we didn't consume all */ ++ return size; ++} ++EXPORT_SYMBOL_GPL(device_store_ulong); ++ ++ssize_t device_show_ulong(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct dev_ext_attribute *ea = to_ext_attr(attr); ++ return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var)); ++} ++EXPORT_SYMBOL_GPL(device_show_ulong); ++ ++ssize_t device_store_int(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct dev_ext_attribute *ea = to_ext_attr(attr); ++ char *end; ++ long new = simple_strtol(buf, &end, 0); ++ if (end == buf || new > INT_MAX || new < INT_MIN) ++ return -EINVAL; ++ *(int *)(ea->var) = new; ++ /* Always return full write size even if we didn't consume all */ ++ return size; ++} ++EXPORT_SYMBOL_GPL(device_store_int); ++ ++ssize_t device_show_int(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct dev_ext_attribute *ea = to_ext_attr(attr); ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var)); ++} ++EXPORT_SYMBOL_GPL(device_show_int); + + /** + * device_release - free device structure. +@@ -464,7 +514,7 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr, + static struct device_attribute devt_attr = + __ATTR(dev, S_IRUGO, show_dev, NULL); + +-/* kset to create /sys/devices/ */ ++/* /sys/devices/ */ + struct kset *devices_kset; + + /** +@@ -711,6 +761,10 @@ static struct kobject *get_device_parent(struct device *dev, + return k; + } + ++ /* subsystems can specify a default root directory for their devices */ ++ if (!parent && dev->bus && dev->bus->dev_root) ++ return &dev->bus->dev_root->kobj; ++ + if (parent) + return &parent->kobj; + return NULL; +@@ -731,14 +785,6 @@ static void cleanup_device_parent(struct device *dev) + cleanup_glue_dir(dev, dev->kobj.parent); + } + +-static void setup_parent(struct device *dev, struct device *parent) +-{ +- struct kobject *kobj; +- kobj = get_device_parent(dev, parent); +- if (kobj) +- dev->kobj.parent = kobj; +-} +- + static int device_add_class_symlinks(struct device *dev) + { + int error; +@@ -891,6 +937,7 @@ int device_private_init(struct device *dev) + int device_add(struct device *dev) + { + struct device *parent = NULL; ++ struct kobject *kobj; + struct class_interface *class_intf; + int error = -EINVAL; + +@@ -914,6 +961,10 @@ int device_add(struct device *dev) + dev->init_name = NULL; + } + ++ /* subsystems can specify simple device enumeration */ ++ if (!dev_name(dev) && dev->bus && dev->bus->dev_name) ++ dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id); ++ + if (!dev_name(dev)) { + error = -EINVAL; + goto name_error; +@@ -922,7 +973,9 @@ int device_add(struct device *dev) + pr_debug("device: '%s': %s\n", dev_name(dev), __func__); + + parent = get_device(dev->parent); +- setup_parent(dev, parent); ++ kobj = get_device_parent(dev, parent); ++ if (kobj) ++ dev->kobj.parent = kobj; + + /* use parent numa_node */ + if (parent) +@@ -982,17 +1035,17 @@ int device_add(struct device *dev) + &parent->p->klist_children); + + if (dev->class) { +- mutex_lock(&dev->class->p->class_mutex); ++ mutex_lock(&dev->class->p->mutex); + /* tie the class to the device */ + klist_add_tail(&dev->knode_class, + &dev->class->p->klist_devices); + + /* notify any interfaces that the device is here */ + list_for_each_entry(class_intf, +- &dev->class->p->class_interfaces, node) ++ &dev->class->p->interfaces, node) + if (class_intf->add_dev) + class_intf->add_dev(dev, class_intf); +- mutex_unlock(&dev->class->p->class_mutex); ++ mutex_unlock(&dev->class->p->mutex); + } + done: + put_device(dev); +@@ -1107,15 +1160,15 @@ void device_del(struct device *dev) + if (dev->class) { + device_remove_class_symlinks(dev); + +- mutex_lock(&dev->class->p->class_mutex); ++ mutex_lock(&dev->class->p->mutex); + /* notify any interfaces that the device is now gone */ + list_for_each_entry(class_intf, +- &dev->class->p->class_interfaces, node) ++ &dev->class->p->interfaces, node) + if (class_intf->remove_dev) + class_intf->remove_dev(dev, class_intf); + /* remove the device from the class list */ + klist_del(&dev->knode_class); +- mutex_unlock(&dev->class->p->class_mutex); ++ mutex_unlock(&dev->class->p->mutex); + } + device_remove_file(dev, &uevent_attr); + device_remove_attrs(dev); +diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c +index 251acea..a3409a1 100644 +--- a/drivers/base/cpu.c ++++ b/drivers/base/cpu.c +@@ -1,8 +1,8 @@ + /* +- * drivers/base/cpu.c - basic CPU class support ++ * CPU subsystem support + */ + +-#include ++#include + #include + #include + #include +@@ -11,43 +11,45 @@ + #include + #include + #include ++#include ++#include + + #include "base.h" + +-static struct sysdev_class_attribute *cpu_sysdev_class_attrs[]; +- +-struct sysdev_class cpu_sysdev_class = { ++struct bus_type cpu_subsys = { + .name = "cpu", +- .attrs = cpu_sysdev_class_attrs, ++ .dev_name = "cpu", + }; +-EXPORT_SYMBOL(cpu_sysdev_class); ++EXPORT_SYMBOL_GPL(cpu_subsys); + +-static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices); ++static DEFINE_PER_CPU(struct device *, cpu_sys_devices); + + #ifdef CONFIG_HOTPLUG_CPU +-static ssize_t show_online(struct sys_device *dev, struct sysdev_attribute *attr, ++static ssize_t show_online(struct device *dev, ++ struct device_attribute *attr, + char *buf) + { +- struct cpu *cpu = container_of(dev, struct cpu, sysdev); ++ struct cpu *cpu = container_of(dev, struct cpu, dev); + +- return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id)); ++ return sprintf(buf, "%u\n", !!cpu_online(cpu->dev.id)); + } + +-static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribute *attr, +- const char *buf, size_t count) ++static ssize_t __ref store_online(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) + { +- struct cpu *cpu = container_of(dev, struct cpu, sysdev); ++ struct cpu *cpu = container_of(dev, struct cpu, dev); + ssize_t ret; + + cpu_hotplug_driver_lock(); + switch (buf[0]) { + case '0': +- ret = cpu_down(cpu->sysdev.id); ++ ret = cpu_down(cpu->dev.id); + if (!ret) + kobject_uevent(&dev->kobj, KOBJ_OFFLINE); + break; + case '1': +- ret = cpu_up(cpu->sysdev.id); ++ ret = cpu_up(cpu->dev.id); + if (!ret) + kobject_uevent(&dev->kobj, KOBJ_ONLINE); + break; +@@ -60,44 +62,44 @@ static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribut + ret = count; + return ret; + } +-static SYSDEV_ATTR(online, 0644, show_online, store_online); ++static DEVICE_ATTR(online, 0644, show_online, store_online); + + static void __cpuinit register_cpu_control(struct cpu *cpu) + { +- sysdev_create_file(&cpu->sysdev, &attr_online); ++ device_create_file(&cpu->dev, &dev_attr_online); + } + void unregister_cpu(struct cpu *cpu) + { +- int logical_cpu = cpu->sysdev.id; ++ int logical_cpu = cpu->dev.id; + + unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu)); + +- sysdev_remove_file(&cpu->sysdev, &attr_online); ++ device_remove_file(&cpu->dev, &dev_attr_online); + +- sysdev_unregister(&cpu->sysdev); ++ device_unregister(&cpu->dev); + per_cpu(cpu_sys_devices, logical_cpu) = NULL; + return; + } + + #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE +-static ssize_t cpu_probe_store(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t cpu_probe_store(struct device *dev, ++ struct device_attribute *attr, + const char *buf, + size_t count) + { + return arch_cpu_probe(buf, count); + } + +-static ssize_t cpu_release_store(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t cpu_release_store(struct device *dev, ++ struct device_attribute *attr, + const char *buf, + size_t count) + { + return arch_cpu_release(buf, count); + } + +-static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); +-static SYSDEV_CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store); ++static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); ++static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store); + #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ + + #else /* ... !CONFIG_HOTPLUG_CPU */ +@@ -109,15 +111,15 @@ static inline void register_cpu_control(struct cpu *cpu) + #ifdef CONFIG_KEXEC + #include + +-static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr, ++static ssize_t show_crash_notes(struct device *dev, struct device_attribute *attr, + char *buf) + { +- struct cpu *cpu = container_of(dev, struct cpu, sysdev); ++ struct cpu *cpu = container_of(dev, struct cpu, dev); + ssize_t rc; + unsigned long long addr; + int cpunum; + +- cpunum = cpu->sysdev.id; ++ cpunum = cpu->dev.id; + + /* + * Might be reading other cpu's data based on which cpu read thread +@@ -129,7 +131,7 @@ static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute + rc = sprintf(buf, "%Lx\n", addr); + return rc; + } +-static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); ++static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL); + #endif + + /* +@@ -137,12 +139,12 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); + */ + + struct cpu_attr { +- struct sysdev_class_attribute attr; ++ struct device_attribute attr; + const struct cpumask *const * const map; + }; + +-static ssize_t show_cpus_attr(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t show_cpus_attr(struct device *dev, ++ struct device_attribute *attr, + char *buf) + { + struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr); +@@ -153,10 +155,10 @@ static ssize_t show_cpus_attr(struct sysdev_class *class, + return n; + } + +-#define _CPU_ATTR(name, map) \ +- { _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map } ++#define _CPU_ATTR(name, map) \ ++ { __ATTR(name, 0444, show_cpus_attr, NULL), map } + +-/* Keep in sync with cpu_sysdev_class_attrs */ ++/* Keep in sync with cpu_subsys_attrs */ + static struct cpu_attr cpu_attrs[] = { + _CPU_ATTR(online, &cpu_online_mask), + _CPU_ATTR(possible, &cpu_possible_mask), +@@ -166,19 +168,19 @@ static struct cpu_attr cpu_attrs[] = { + /* + * Print values for NR_CPUS and offlined cpus + */ +-static ssize_t print_cpus_kernel_max(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, char *buf) ++static ssize_t print_cpus_kernel_max(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1); + return n; + } +-static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL); ++static DEVICE_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL); + + /* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */ + unsigned int total_cpus; + +-static ssize_t print_cpus_offline(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, char *buf) ++static ssize_t print_cpus_offline(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + int n = 0, len = PAGE_SIZE-2; + cpumask_var_t offline; +@@ -205,7 +207,26 @@ static ssize_t print_cpus_offline(struct sysdev_class *class, + n += snprintf(&buf[n], len - n, "\n"); + return n; + } +-static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL); ++static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL); ++ ++static void cpu_device_release(struct device *dev) ++{ ++ /* ++ * This is an empty function to prevent the driver core from spitting a ++ * warning at us. Yes, I know this is directly opposite of what the ++ * documentation for the driver core and kobjects say, and the author ++ * of this code has already been publically ridiculed for doing ++ * something as foolish as this. However, at this point in time, it is ++ * the only way to handle the issue of statically allocated cpu ++ * devices. The different architectures will have their cpu device ++ * code reworked to properly handle this in the near future, so this ++ * function will then be changed to correctly free up the memory held ++ * by the cpu device. ++ * ++ * Never copy this way of doing things, or you too will be made fun of ++ * on the linux-kerenl list, you have been warned. ++ */ ++} + + /* + * register_cpu - Setup a sysfs device for a CPU. +@@ -218,57 +239,92 @@ static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL); + int __cpuinit register_cpu(struct cpu *cpu, int num) + { + int error; +- cpu->node_id = cpu_to_node(num); +- cpu->sysdev.id = num; +- cpu->sysdev.cls = &cpu_sysdev_class; +- +- error = sysdev_register(&cpu->sysdev); + ++ cpu->node_id = cpu_to_node(num); ++ memset(&cpu->dev, 0x00, sizeof(struct device)); ++ cpu->dev.id = num; ++ cpu->dev.bus = &cpu_subsys; ++ cpu->dev.release = cpu_device_release; ++#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE ++ cpu->dev.bus->uevent = arch_cpu_uevent; ++#endif ++ error = device_register(&cpu->dev); + if (!error && cpu->hotpluggable) + register_cpu_control(cpu); + if (!error) +- per_cpu(cpu_sys_devices, num) = &cpu->sysdev; ++ per_cpu(cpu_sys_devices, num) = &cpu->dev; + if (!error) + register_cpu_under_node(num, cpu_to_node(num)); + + #ifdef CONFIG_KEXEC + if (!error) +- error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes); ++ error = device_create_file(&cpu->dev, &dev_attr_crash_notes); + #endif + return error; + } + +-struct sys_device *get_cpu_sysdev(unsigned cpu) ++struct device *get_cpu_device(unsigned cpu) + { + if (cpu < nr_cpu_ids && cpu_possible(cpu)) + return per_cpu(cpu_sys_devices, cpu); + else + return NULL; + } +-EXPORT_SYMBOL_GPL(get_cpu_sysdev); +- +-int __init cpu_dev_init(void) +-{ +- int err; ++EXPORT_SYMBOL_GPL(get_cpu_device); + +- err = sysdev_class_register(&cpu_sysdev_class); +-#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) +- if (!err) +- err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class); ++#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE ++static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL); + #endif + +- return err; +-} +- +-static struct sysdev_class_attribute *cpu_sysdev_class_attrs[] = { ++static struct attribute *cpu_root_attrs[] = { + #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE +- &attr_probe, +- &attr_release, ++ &dev_attr_probe.attr, ++ &dev_attr_release.attr, ++#endif ++ &cpu_attrs[0].attr.attr, ++ &cpu_attrs[1].attr.attr, ++ &cpu_attrs[2].attr.attr, ++ &dev_attr_kernel_max.attr, ++ &dev_attr_offline.attr, ++#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE ++ &dev_attr_modalias.attr, + #endif +- &cpu_attrs[0].attr, +- &cpu_attrs[1].attr, +- &cpu_attrs[2].attr, +- &attr_kernel_max, +- &attr_offline, + NULL + }; ++ ++static struct attribute_group cpu_root_attr_group = { ++ .attrs = cpu_root_attrs, ++}; ++ ++static const struct attribute_group *cpu_root_attr_groups[] = { ++ &cpu_root_attr_group, ++ NULL, ++}; ++ ++#ifdef CONFIG_GENERIC_CPU_DEVICES ++static DEFINE_PER_CPU(struct cpu, cpu_devices); ++#endif ++ ++static void __init cpu_dev_register_generic(void) ++{ ++#ifdef CONFIG_GENERIC_CPU_DEVICES ++ int i; ++ ++ for_each_possible_cpu(i) { ++ if (register_cpu(&per_cpu(cpu_devices, i), i)) ++ panic("Failed to register CPU device"); ++ } ++#endif ++} ++ ++void __init cpu_dev_init(void) ++{ ++ if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups)) ++ panic("Failed to register CPU subsystem"); ++ ++ cpu_dev_register_generic(); ++ ++#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) ++ sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root); ++#endif ++} +diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c +index 763b356..2168f2f 100644 +--- a/drivers/base/firmware_class.c ++++ b/drivers/base/firmware_class.c +@@ -251,7 +251,8 @@ static ssize_t firmware_loading_store(struct device *dev, + fw_priv->nr_pages, + 0, PAGE_KERNEL_RO); + if (!fw_priv->fw->data) { +- dev_err(dev, "%s: vmap() failed\n", __func__); ++ dev_err(dev->parent, "%s: vmap() failed\n", ++ __func__); + goto err; + } + /* Pages are now owned by 'struct firmware' */ +@@ -266,9 +267,14 @@ static ssize_t firmware_loading_store(struct device *dev, + } + /* fallthrough */ + default: +- dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading); +- /* fallthrough */ ++ dev_err(dev->parent, "%s: unexpected value (%d)\n", ++ __func__, loading); ++ goto err; + case -1: ++ dev_err(dev->parent, ++ "firmware: agent aborted loading %s (not found?)\n", ++ fw_priv->fw_id); ++ /* fallthrough */ + err: + fw_load_abort(fw_priv); + break; +@@ -431,6 +437,9 @@ static void firmware_class_timeout(u_long data) + { + struct firmware_priv *fw_priv = (struct firmware_priv *) data; + ++ dev_err(fw_priv->dev.parent, ++ "firmware: agent did not handle request for %s\n", ++ fw_priv->fw_id); + fw_load_abort(fw_priv); + } + +@@ -533,7 +542,8 @@ static int _request_firmware(const struct firmware **firmware_p, + } + + if (fw_get_builtin_firmware(firmware, name)) { +- dev_dbg(device, "firmware: using built-in firmware %s\n", name); ++ dev_info(device, "firmware: using built-in firmware %s\n", ++ name); + return 0; + } + +@@ -567,8 +577,15 @@ static int _request_firmware(const struct firmware **firmware_p, + del_timer_sync(&fw_priv->timeout); + + mutex_lock(&fw_lock); +- if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) ++ if (test_bit(FW_STATUS_ABORT, &fw_priv->status)) { ++ /* failure has already been logged */ + retval = -ENOENT; ++ } else if (!fw_priv->fw->size) { ++ dev_err(device, ++ "firmware: agent loaded no data for %s (not found?)\n", ++ name); ++ retval = -ENOENT; ++ } + fw_priv->fw = NULL; + mutex_unlock(&fw_lock); + +@@ -578,6 +595,9 @@ out: + if (retval) { + release_firmware(firmware); + *firmware_p = NULL; ++ } else { ++ dev_info(device, "firmware: agent loaded %s into memory\n", ++ name); + } + + return retval; +diff --git a/drivers/base/init.c b/drivers/base/init.c +index c8a934e..c16f0b8 100644 +--- a/drivers/base/init.c ++++ b/drivers/base/init.c +@@ -31,7 +31,6 @@ void __init driver_init(void) + * core core pieces. + */ + platform_bus_init(); +- system_bus_init(); + cpu_dev_init(); + memory_dev_init(); + } +diff --git a/drivers/base/node.c b/drivers/base/node.c +index 5693ece..90cf357 100644 +--- a/drivers/base/node.c ++++ b/drivers/base/node.c +@@ -317,12 +317,12 @@ struct node node_devices[MAX_NUMNODES]; + int register_cpu_under_node(unsigned int cpu, unsigned int nid) + { + int ret; +- struct sys_device *obj; ++ struct device *obj; + + if (!node_online(nid)) + return 0; + +- obj = get_cpu_sysdev(cpu); ++ obj = get_cpu_device(cpu); + if (!obj) + return 0; + +@@ -339,12 +339,12 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid) + + int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) + { +- struct sys_device *obj; ++ struct device *obj; + + if (!node_online(nid)) + return 0; + +- obj = get_cpu_sysdev(cpu); ++ obj = get_cpu_device(cpu); + if (!obj) + return 0; + +diff --git a/drivers/base/sys.c b/drivers/base/sys.c +index 9dff77b..409f5ce 100644 +--- a/drivers/base/sys.c ++++ b/drivers/base/sys.c +@@ -126,7 +126,7 @@ void sysdev_class_remove_file(struct sysdev_class *c, + } + EXPORT_SYMBOL_GPL(sysdev_class_remove_file); + +-static struct kset *system_kset; ++extern struct kset *system_kset; + + int sysdev_class_register(struct sysdev_class *cls) + { +@@ -331,14 +331,6 @@ void sysdev_unregister(struct sys_device *sysdev) + EXPORT_SYMBOL_GPL(sysdev_register); + EXPORT_SYMBOL_GPL(sysdev_unregister); + +-int __init system_bus_init(void) +-{ +- system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj); +- if (!system_kset) +- return -ENOMEM; +- return 0; +-} +- + #define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr) + + ssize_t sysdev_store_ulong(struct sys_device *sysdev, +diff --git a/drivers/base/topology.c b/drivers/base/topology.c +index f6f37a0..ae989c5 100644 +--- a/drivers/base/topology.c ++++ b/drivers/base/topology.c +@@ -23,7 +23,6 @@ + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +-#include + #include + #include + #include +@@ -32,14 +31,14 @@ + #include + + #define define_one_ro_named(_name, _func) \ +-static SYSDEV_ATTR(_name, 0444, _func, NULL) ++ static DEVICE_ATTR(_name, 0444, _func, NULL) + + #define define_one_ro(_name) \ +-static SYSDEV_ATTR(_name, 0444, show_##_name, NULL) ++ static DEVICE_ATTR(_name, 0444, show_##_name, NULL) + + #define define_id_show_func(name) \ +-static ssize_t show_##name(struct sys_device *dev, \ +- struct sysdev_attribute *attr, char *buf) \ ++static ssize_t show_##name(struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ + { \ + unsigned int cpu = dev->id; \ + return sprintf(buf, "%d\n", topology_##name(cpu)); \ +@@ -65,16 +64,16 @@ static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf) + + #ifdef arch_provides_topology_pointers + #define define_siblings_show_map(name) \ +-static ssize_t show_##name(struct sys_device *dev, \ +- struct sysdev_attribute *attr, char *buf) \ ++static ssize_t show_##name(struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ + { \ + unsigned int cpu = dev->id; \ + return show_cpumap(0, topology_##name(cpu), buf); \ + } + + #define define_siblings_show_list(name) \ +-static ssize_t show_##name##_list(struct sys_device *dev, \ +- struct sysdev_attribute *attr, \ ++static ssize_t show_##name##_list(struct device *dev, \ ++ struct device_attribute *attr, \ + char *buf) \ + { \ + unsigned int cpu = dev->id; \ +@@ -83,15 +82,15 @@ static ssize_t show_##name##_list(struct sys_device *dev, \ + + #else + #define define_siblings_show_map(name) \ +-static ssize_t show_##name(struct sys_device *dev, \ +- struct sysdev_attribute *attr, char *buf) \ ++static ssize_t show_##name(struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ + { \ + return show_cpumap(0, topology_##name(dev->id), buf); \ + } + + #define define_siblings_show_list(name) \ +-static ssize_t show_##name##_list(struct sys_device *dev, \ +- struct sysdev_attribute *attr, \ ++static ssize_t show_##name##_list(struct device *dev, \ ++ struct device_attribute *attr, \ + char *buf) \ + { \ + return show_cpumap(1, topology_##name(dev->id), buf); \ +@@ -124,16 +123,16 @@ define_one_ro_named(book_siblings_list, show_book_cpumask_list); + #endif + + static struct attribute *default_attrs[] = { +- &attr_physical_package_id.attr, +- &attr_core_id.attr, +- &attr_thread_siblings.attr, +- &attr_thread_siblings_list.attr, +- &attr_core_siblings.attr, +- &attr_core_siblings_list.attr, ++ &dev_attr_physical_package_id.attr, ++ &dev_attr_core_id.attr, ++ &dev_attr_thread_siblings.attr, ++ &dev_attr_thread_siblings_list.attr, ++ &dev_attr_core_siblings.attr, ++ &dev_attr_core_siblings_list.attr, + #ifdef CONFIG_SCHED_BOOK +- &attr_book_id.attr, +- &attr_book_siblings.attr, +- &attr_book_siblings_list.attr, ++ &dev_attr_book_id.attr, ++ &dev_attr_book_siblings.attr, ++ &dev_attr_book_siblings_list.attr, + #endif + NULL + }; +@@ -146,16 +145,16 @@ static struct attribute_group topology_attr_group = { + /* Add/Remove cpu_topology interface for CPU device */ + static int __cpuinit topology_add_dev(unsigned int cpu) + { +- struct sys_device *sys_dev = get_cpu_sysdev(cpu); ++ struct device *dev = get_cpu_device(cpu); + +- return sysfs_create_group(&sys_dev->kobj, &topology_attr_group); ++ return sysfs_create_group(&dev->kobj, &topology_attr_group); + } + + static void __cpuinit topology_remove_dev(unsigned int cpu) + { +- struct sys_device *sys_dev = get_cpu_sysdev(cpu); ++ struct device *dev = get_cpu_device(cpu); + +- sysfs_remove_group(&sys_dev->kobj, &topology_attr_group); ++ sysfs_remove_group(&dev->kobj, &topology_attr_group); + } + + static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, +diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c +index 48e06be..8128330 100644 +--- a/drivers/bcma/host_pci.c ++++ b/drivers/bcma/host_pci.c +@@ -263,11 +263,13 @@ static int bcma_host_pci_resume(struct pci_dev *dev) + #endif /* CONFIG_PM */ + + static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { ++#if !IS_ENABLED(CONFIG_BRCMSMAC) + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, +- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, ++#endif ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, + { 0, }, + }; + MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); +diff --git a/drivers/bcmdrivers/Kconfig b/drivers/bcmdrivers/Kconfig +new file mode 100755 +index 0000000..f0466c2 +--- /dev/null ++++ b/drivers/bcmdrivers/Kconfig +@@ -0,0 +1,84 @@ ++menu "Broadcom iProc Drivers" ++ depends on ARCH_IPROC ++ ++source "drivers/bcmdrivers/timer/Kconfig" ++source "drivers/bcmdrivers/mdio/Kconfig" ++source "drivers/bcmdrivers/dma/Kconfig" ++source "drivers/bcmdrivers/gpio/Kconfig" ++source "drivers/bcmdrivers/qspi/Kconfig" ++source "drivers/bcmdrivers/nand/Kconfig" ++source "drivers/bcmdrivers/pwm/Kconfig" ++source "drivers/bcmdrivers/wdt/Kconfig" ++source "drivers/bcmdrivers/usb2h/Kconfig" ++source "drivers/bcmdrivers/gmac/et/Kconfig" ++source "drivers/bcmdrivers/gmac/hnd/Kconfig" ++source "drivers/bcmdrivers/smbus/Kconfig" ++source "drivers/bcmdrivers/pmu/Kconfig" ++ ++config BCM_IPROC_CA9_PREFETCH ++ tristate "CortexA9 cache auto-prefetching support" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable iProc CortexA9 L1/L2 cache auto-prefetching support ++ ++ If unsure, say N. ++ ++config BCM_BARRIER_PERFORMANCE ++ bool "Linux memory barrier performance improvement" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable linux memory barrier performance improvements ++ ++ If unsure, say N. ++ ++config BCM_MEM_OPTIMIZATION ++ bool "ARM Memory library optimization" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable ARM memory library optimization ++ ++ If unsure, say N. ++ ++config BROADCOM_CUSTOM_SENDFILE ++ bool "Custom Sendfile optimization" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable Broadcom Custom Sendfile optimization ++ ++ If unsure, say N. ++ ++config BCM_CUSTOM_RECVFILE ++ bool "Custom Receivefile optimization" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable Broadcom Custom Receivefile optimization ++ ++ If unsure, say N. ++ ++config BCM_CUSTOM_RECVFILE_MAX_PERF ++# Enabling BCM_CUSTOM_RECVFILE_MAX_PERF gives maximum write performance ++# at the risk of filesystem errors (due to skipping cache invalidation ++# on writes) and exposure to A0 hardware errata for lazy interrupts. ++ bool "Custom Receivefile Max Performance optimization" ++ depends on ARCH_IPROC && BCM_CUSTOM_RECVFILE ++ default n ++ help ++ Enable Broadcom Custom Receivefile Maximum Performance optimization ++ ++ If unsure, say N. ++ ++config BCM_GRO_ENABLE ++ bool "Broadcom GRO Enable" ++ depends on ARCH_IPROC && (ET_NAPI_POLL || ET_NAPI2_POLL) ++ default n ++ help ++ Enable Broadcom Generic Receive Offload ++ ++ If unsure, say N. ++ ++endmenu +diff --git a/drivers/bcmdrivers/Makefile b/drivers/bcmdrivers/Makefile +new file mode 100755 +index 0000000..6a8ba6f +--- /dev/null ++++ b/drivers/bcmdrivers/Makefile +@@ -0,0 +1,21 @@ ++# File: bcmdrivers/Makefile ++# ++# Makefile for the Linux kernel modules. ++# ++ ++# The following must have config defined for each driver ++ ++obj-y += timer/ ++obj-y += mdio/ ++obj-y += dma/ ++obj-y += qspi/ ++obj-$(CONFIG_IPROC_MTD_NAND) += nand/ ++obj-y += pwm/ ++obj-y += gpio/ ++obj-y += wdt/ ++obj-y += usb2h/ ++obj-$(CONFIG_ET) += gmac/et/ ++obj-y += gmac/hnd/ ++obj-y += smbus/ ++ ++obj-y += pmu/ +diff --git a/drivers/bcmdrivers/dma/.gitignore b/drivers/bcmdrivers/dma/.gitignore +new file mode 100644 +index 0000000..d741861 +--- /dev/null ++++ b/drivers/bcmdrivers/dma/.gitignore +@@ -0,0 +1,4 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/dma/Kconfig b/drivers/bcmdrivers/dma/Kconfig +new file mode 100644 +index 0000000..652fbb4 +--- /dev/null ++++ b/drivers/bcmdrivers/dma/Kconfig +@@ -0,0 +1,15 @@ ++config IPROC_DMA ++ tristate "DMA support" ++ depends on ARCH_IPROC ++ select DMADEVICES ++ select DMADEVICES_DEBUG ++ select DMADEVICES_VDEBUG ++ select DMA_ENGINE ++ select PL330 ++ select DMAC_PL330 ++ select DMATEST ++ default n ++ help ++ DMA support for pl330 ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/dma/Makefile b/drivers/bcmdrivers/dma/Makefile +new file mode 100644 +index 0000000..0b6a480 +--- /dev/null ++++ b/drivers/bcmdrivers/dma/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_DMA) += iproc_dma.o ++iproc_dma-objs := dma.o +diff --git a/drivers/bcmdrivers/dma/dma-pl330.h b/drivers/bcmdrivers/dma/dma-pl330.h +new file mode 100644 +index 0000000..bf45e7b +--- /dev/null ++++ b/drivers/bcmdrivers/dma/dma-pl330.h +@@ -0,0 +1,103 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_DMA_H ++#define __PLAT_DMA_H ++ ++#include ++ ++#define MAX_CHAN_NAME_LENGTH 32 ++ ++/* DMA direction control */ ++enum dma_direction { ++ DMA_DIRECTION_MEM_TO_MEM = 0, ++ DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_DMAC = 1, ++ DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_PERI = 2, ++ DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_DMAC = 3, ++ DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_PERI = 4, ++ DMA_DIRECTION_DEV_TO_DEV = 5 /* Invalid, unsupported */ ++}; ++#define DMA_DIRECTION_MASK 0x7 ++ ++/* Channel configurations definition */ ++#define DMA_CFG_SRC_ADDR_FIXED (0x0 << 0) ++#define DMA_CFG_SRC_ADDR_INCREMENT (0x1 << 0) ++#define DMA_CFG_DST_ADDR_FIXED (0x0 << 14) ++#define DMA_CFG_DST_ADDR_INCREMENT (0x1 << 14) ++ ++#define DMA_CFG_BURST_SIZE_MASK (0x7 << 1) ++#define DMA_CFG_BURST_SIZE_1 (0x0 << 1) ++#define DMA_CFG_BURST_SIZE_2 (0x1 << 1) ++#define DMA_CFG_BURST_SIZE_4 (0x2 << 1) ++#define DMA_CFG_BURST_SIZE_8 (0x3 << 1) ++#define DMA_CFG_BURST_SIZE_16 (0x4 << 1) ++#define DMA_CFG_BURST_SIZE_32 (0x5 << 1) ++#define DMA_CFG_BURST_SIZE_64 (0x6 << 1) ++#define DMA_CFG_BURST_SIZE_128 (0x7 << 1) ++ ++#define DMA_CFG_BURST_LENGTH_MASK (0xF << 4) ++#define DMA_CFG_BURST_LENGTH_1 (0x0 << 4) ++#define DMA_CFG_BURST_LENGTH_2 (0x1 << 4) ++#define DMA_CFG_BURST_LENGTH_3 (0x2 << 4) ++#define DMA_CFG_BURST_LENGTH_4 (0x3 << 4) ++#define DMA_CFG_BURST_LENGTH_5 (0x4 << 4) ++#define DMA_CFG_BURST_LENGTH_6 (0x5 << 4) ++#define DMA_CFG_BURST_LENGTH_7 (0x6 << 4) ++#define DMA_CFG_BURST_LENGTH_8 (0x7 << 4) ++#define DMA_CFG_BURST_LENGTH_9 (0x8 << 4) ++#define DMA_CFG_BURST_LENGTH_10 (0x9 << 4) ++#define DMA_CFG_BURST_LENGTH_11 (0xA << 4) ++#define DMA_CFG_BURST_LENGTH_12 (0xB << 4) ++#define DMA_CFG_BURST_LENGTH_13 (0xC << 4) ++#define DMA_CFG_BURST_LENGTH_14 (0xD << 4) ++#define DMA_CFG_BURST_LENGTH_15 (0xE << 4) ++#define DMA_CFG_BURST_LENGTH_16 (0xF << 4) ++ ++#define DMA_CFG_BURST_LEN(x) (((x - 1) & 0xF) << 4) ++ ++/* src and dest burst size and burst length are assumed to be same */ ++ ++enum pl330_xfer_status { ++ DMA_PL330_XFER_OK, ++ DMA_PL330_XFER_ERR, ++ DMA_PL330_XFER_ABORT, ++}; ++ ++struct dma_transfer_list { ++ dma_addr_t srcaddr; /* src address */ ++ dma_addr_t dstaddr; /* dst address */ ++ unsigned int xfer_size; /* In bytes */ ++ struct list_head next; /* Next item */ ++}; ++ ++typedef void (*pl330_xfer_callback_t) (void *private_data, ++ enum pl330_xfer_status status); ++ ++int dma_request_chan(unsigned int *chan, const char *name); ++int dma_free_chan(unsigned int chan); ++int dma_map_peripheral(unsigned int chan, const char *peri_name); ++int dma_unmap_peripheral(unsigned int chan); ++int dma_setup_transfer(unsigned int chan, dma_addr_t s, dma_addr_t d, ++ unsigned int xfer_size, int ctrl, int cfg); ++int dma_setup_transfer_list(unsigned int chan, struct list_head *head, ++ int ctrl, int cfg); ++int dma_start_transfer(unsigned int chan); ++int dma_stop_transfer(unsigned int chan); ++int dma_shutdown_all_chan(void); ++int dma_register_callback(unsigned int chan, ++ pl330_xfer_callback_t cb, void *pri); ++int dma_free_callback(unsigned int chan); ++ ++#endif /* __PLAT_DMA_H */ +diff --git a/drivers/bcmdrivers/dma/dma.c b/drivers/bcmdrivers/dma/dma.c +new file mode 100755 +index 0000000..2ff23da +--- /dev/null ++++ b/drivers/bcmdrivers/dma/dma.c +@@ -0,0 +1,886 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "pl330-pdata.h" ++#include "dma-pl330.h" ++ ++#define IPROC_IDM_DMAC_RESET_CONTROL (0x18114800) ++#define IPROC_IDM_DMAC_RESET_CONTROL_VA HW_IO_PHYS_TO_VIRT(IPROC_IDM_DMAC_RESET_CONTROL) ++ ++/** ++ * struct pl330_chan_desc - Peripheral channel descriptor. ++ */ ++struct pl330_chan_desc { ++ int id; /* channel ID for the client */ ++ struct list_head node; /* Link to next channel desc */ ++ bool is_peri_mapped; /*Is peripheral mapped?, false if mem to mem */ ++ char *name[MAX_CHAN_NAME_LENGTH]; /* Name of the peripheral */ ++ int event_id; /* ID of event/Interrupt line to notify */ ++ u8 peri_req_id; /* mapped peripheral request interface(PRI) ID */ ++ void *pl330_chan_id; /* PL330 channel id alloted */ ++ unsigned int options; /* DMA options */ ++ struct pl330_reqcfg rqcfg; /* DMA req configurations */ ++ pl330_xfer_callback_t xfer_callback; /* DMA callback function */ ++ void *client_cookie; /* client data for callback fn */ ++ bool in_use; /* is DMA channel busy */ ++ bool is_setup; /* Is 'pl330_req' having valid transfer setup */ ++ struct pl330_req req; /* A DMA request item */ ++}; ++ ++/** ++ * struct pl330_dmac_desc - PL330 DMAC Descriptor. ++ */ ++struct pl330_dmac_desc { ++ struct pl330_info *pi; /* PL330 DMAC info */ ++ int irq_start; /* First PL330 Irq mapped */ ++ int irq_end; /* Last Irq number mapped */ ++ struct list_head chan_list; /* List of channel descriptors */ ++ int chan_count; /* channel descriptors count */ ++}; ++ ++/* PL330 DMAC Descriptor structure */ ++static struct pl330_dmac_desc *dmac = NULL; /* Allocate on platform device probe */ ++/* global resources lock */ ++static DEFINE_SPINLOCK(lock); ++ ++/* always call this function with global spinlock held */ ++static struct pl330_chan_desc *chan_id_to_cdesc(int id) ++{ ++ struct pl330_chan_desc *cdesc; ++ ++ list_for_each_entry(cdesc, &dmac->chan_list, node) ++ if (cdesc->id == id) ++ return cdesc; ++ ++ return NULL; ++} ++ ++static void _cleanup_req(struct pl330_req *rq) ++{ ++ struct pl330_xfer *x, *nxt; ++ ++ if (!rq) ++ return; ++ ++ rq->rqtype = DEVTODEV; /* Invalid type */ ++ ++ if (rq->cfg) { ++ kfree(rq->cfg); ++ rq->cfg = NULL; ++ } ++ ++ if (!rq->x) ++ return; ++ ++ /* Free all the xfer items */ ++ x = rq->x; ++ do { ++ nxt = x->next; ++ kfree(x); ++ x = nxt; ++ } while (x); ++ rq->x = NULL; ++ ++ return; ++} ++ ++static void _free_cdesc(struct pl330_chan_desc *cdesc) ++{ ++ /* Deallocate all mapped peripherals */ ++ if (cdesc->is_peri_mapped) { ++ cdesc->is_peri_mapped = false; ++ } ++ ++ /* Release PL330 channel thread */ ++ pl330_release_channel(cdesc->pl330_chan_id); ++ ++ list_del(&cdesc->node); ++ dmac->chan_count--; ++ kfree(cdesc); ++} ++ ++static void pl330_req_callback(void *token, enum pl330_op_err err) ++{ ++ struct pl330_req *r = token; ++ enum pl330_xfer_status stat; ++ struct pl330_chan_desc *c = ++ container_of(r, struct pl330_chan_desc, req); ++ ++ printk("\n----> %s ()\n", __func__); ++ if (c && c->xfer_callback) { ++ switch (err) { ++ case PL330_ERR_NONE: ++ stat = DMA_PL330_XFER_OK; ++ break; ++ case PL330_ERR_ABORT: ++ stat = DMA_PL330_XFER_ABORT; ++ break; ++ case PL330_ERR_FAIL: ++ stat = DMA_PL330_XFER_ERR; ++ break; ++ default: ++ stat = DMA_PL330_XFER_OK; ++ break; ++ } ++ /* call client callback function */ ++ c->xfer_callback(c->client_cookie, stat); ++ } ++} ++ ++int dma_request_chan(unsigned int *chan, const char *name) ++{ ++ int ch, err = -1; ++ //enum dma_peri peri; ++ u8 pri_id; ++ void *pl330_chan_id = NULL; ++ struct pl330_chan_desc *cdesc = NULL; ++ unsigned long flags; ++ bool is_peri = false; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ /* channel request for a 'named' peripheral, NULL if memory<->memory DMA */ ++ /* no peripheral mapping in IPROC */ ++ ++ /* Allocate PL330 DMA channel thread first */ ++ pl330_chan_id = pl330_request_channel(dmac->pi); ++ if (!pl330_chan_id) { ++ dev_info(dmac->pi->dev, ++ "Failed to allocate PL330 channel thread!!!\n"); ++ goto err_1; ++ } ++ ++ ++ if (dmac->chan_count >= 8) ++ { ++ dev_info(dmac->pi->dev, "MAX DMAC channel exceeded\n"); ++ goto err_2; ++ } ++ ++ /* No peripheral mapping in IPROC */ ++ ++ spin_unlock_irqrestore(&lock, flags); ++ ++ /* Channel allocation is done, create a 'channel descriptor' for the client */ ++ cdesc = (struct pl330_chan_desc *)kzalloc(sizeof(*cdesc), GFP_KERNEL); ++ ++ spin_lock_irqsave(&lock, flags); ++ if (!cdesc) { ++ err = -ENOMEM; ++ goto err_4; ++ } ++ ++ /* Populate the cdesc and return channel id to client */ ++ cdesc->id = dmac->chan_count; ++ cdesc->xfer_callback = NULL; ++ cdesc->client_cookie = NULL; ++ cdesc->is_peri_mapped = is_peri; ++ cdesc->event_id = 0; /* always use INTR/EVT line 0 */ ++ cdesc->peri_req_id = pri_id; ++ cdesc->pl330_chan_id = pl330_chan_id; ++ cdesc->in_use = false; ++ cdesc->req.rqtype = DEVTODEV; /* set invalid type */ ++ if (name) ++ strlcpy(cdesc->name, name, MAX_CHAN_NAME_LENGTH); ++ ++ /* Attach cdesc to DMAC channel list */ ++ list_add_tail(&cdesc->node, &dmac->chan_list); ++ dmac->chan_count++; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ /* Give the channel ID to client */ ++ *chan = cdesc->id; ++ return 0; ++ ++ err_4: ++ err_3: ++ err_2: ++ pl330_release_channel(pl330_chan_id); ++ err_1: ++ err_ret: ++ spin_unlock_irqrestore(&lock, flags); ++ return err; ++} ++ ++int dma_free_chan(unsigned int chan) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *cdesc; ++ ++ spin_lock_irqsave(&lock, flags); ++ cdesc = chan_id_to_cdesc(chan); ++ if (!cdesc || cdesc->in_use) /* can free id channel is active */ ++ goto err; ++ ++ _cleanup_req(&cdesc->req); ++ ++ _free_cdesc(cdesc); ++ ++ spin_unlock_irqrestore(&lock, flags); ++ ++ return 0; ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_map_peripheral(unsigned int chan, const char *peri_name) ++{ ++ struct pl330_chan_desc *c = NULL; ++ unsigned long flags; ++ //enum dma_peri peri; ++ u8 pri_id; ++ ++ if (!peri_name) ++ return -1; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err_ret; ++ ++ /* If a peripheral is already mapped, return failure */ ++ if (c->is_peri_mapped) { ++ dev_info(dmac->pi->dev, ++ "Already peripheral mapped, need to unmap first!!!\n"); ++ goto err_ret; ++ } ++ ++ /* no peripheral mapping in IPROC */ ++ ++ /* no peripheral mapping in IPROC */ ++ ++ c->peri_req_id = pri_id; ++ c->is_peri_mapped = true; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err_ret: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_unmap_peripheral(unsigned int chan) ++{ ++ struct pl330_chan_desc *c = NULL; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err_ret; ++ ++ /* If a peripheral is already mapped or channel in use, return failure */ ++ if (!c->is_peri_mapped || c->in_use) { ++ dev_info(dmac->pi->dev, "Peripheral is not mapped\n"); ++ goto err_ret; ++ } ++ ++ c->is_peri_mapped = false; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err_ret: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_setup_transfer(unsigned int chan, ++ dma_addr_t src_addr, ++ dma_addr_t dst_addr, ++ unsigned int xfer_size, int control, int cfg) ++{ ++ unsigned long flags; ++ enum pl330_reqtype rqtype; ++ struct pl330_reqcfg *config; ++ struct pl330_xfer *xfer; ++ struct pl330_chan_desc *c; ++ int err = -1; ++ ++ if (!xfer_size) ++ goto err1; ++ ++ /* DMA transfer direction */ ++ switch (control & DMA_DIRECTION_MASK) { ++ /* Peripheral transfers with DMAC flow control are ++ * treated as Mem to Mem transfers at PL330 microcode level. ++ */ ++ case DMA_DIRECTION_MEM_TO_MEM: ++ case DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_DMAC: ++ case DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_DMAC: ++ rqtype = MEMTOMEM; ++ break; ++ case DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_PERI: ++ rqtype = MEMTODEV; ++ break; ++ case DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_PERI: ++ rqtype = DEVTOMEM; ++ break; ++ case DMA_DIRECTION_DEV_TO_DEV: ++ default: ++ rqtype = DEVTODEV; /*Unsupported */ ++ break; ++ }; ++ ++ if (rqtype == DEVTODEV) ++ goto err1; ++ ++ /* Burst size max is 64 bit(AXI), not supporting >64 bit burst size */ ++ if ((cfg & DMA_CFG_BURST_SIZE_MASK) > DMA_CFG_BURST_SIZE_8) ++ goto err1; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) { ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ } ++ ++ if (c->in_use || c->is_setup) { ++ dev_info(dmac->pi->dev, ++ "Cant setup transfer, already setup/running\n"); ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ }; ++ ++ if ((rqtype != DMA_DIRECTION_MEM_TO_MEM) && (!c->is_peri_mapped)) { ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ } ++ ++ c->is_setup = true; /* Mark it now, for setup */ ++ ++ spin_unlock_irqrestore(&lock, flags); ++ ++ /* Allocate */ ++ config = (struct pl330_reqcfg *)kzalloc(sizeof(*config), GFP_KERNEL); ++ if (!config) { ++ err = -ENOMEM; ++ goto err1; ++ } ++ ++ xfer = (struct pl330_xfer *)kzalloc(sizeof(*xfer), GFP_KERNEL); ++ if (!xfer) { ++ err = -ENOMEM; ++ goto err2; ++ } ++ ++ /* configuration options */ ++ config->src_inc = (cfg & DMA_CFG_SRC_ADDR_INCREMENT) ? 1 : 0; ++ config->dst_inc = (cfg & DMA_CFG_DST_ADDR_INCREMENT) ? 1 : 0; ++ /* Burst size */ ++ config->brst_size = (cfg & DMA_CFG_BURST_SIZE_MASK) >> 1; ++ /* Burst Length */ ++ config->brst_len = (((cfg & DMA_CFG_BURST_LENGTH_MASK) >> 4) + 1); ++ ++ /* default settings: Noncacheable, nonbufferable, no swapping */ ++ config->scctl = SCCTRL0; ++ config->dcctl = DCCTRL0; ++ config->swap = SWAP_NO; ++ ++ /* TrustZone security AXPROT[2:0} = 000 */ ++ config->insnaccess = false; /* tied LOW */ ++ config->nonsecure = true; /* DMAC boots in Non Secure Mode */ ++ config->privileged = false; ++ ++ xfer->src_addr = src_addr; ++ xfer->dst_addr = dst_addr; ++ xfer->bytes = xfer_size; ++ xfer->next = NULL; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ /* Attach the request */ ++ c->req.rqtype = rqtype; ++ ++ if (rqtype != MEMTOMEM) ++ c->req.peri = c->peri_req_id; ++ ++ /* callback function */ ++ c->req.xfer_cb = pl330_req_callback; ++ c->req.token = &c->req; /* callback data */ ++ /* attach configuration */ ++ c->req.cfg = config; ++ /* attach xfer item */ ++ c->req.x = xfer; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err2: ++ kfree(config); ++ err1: ++ return err; ++} ++ ++int dma_setup_transfer_list(unsigned int chan, struct list_head *head, ++ int control, int cfg) ++{ ++ unsigned long flags; ++ enum pl330_reqtype rqtype; ++ struct pl330_reqcfg *config; ++ struct pl330_xfer *xfer_front, *nxt, *priv; ++ struct pl330_chan_desc *c; ++ struct dma_transfer_list *lli; ++ int err = -1; ++ ++ if (!head) ++ return -1; ++ ++ /* DMA transfer direction */ ++ switch (control & DMA_DIRECTION_MASK) { ++ /* Peripheral transfers with DMAC flow control are ++ * treated as Mem to Mem transfers at PL330 microcode level. ++ */ ++ case DMA_DIRECTION_MEM_TO_MEM: ++ case DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_DMAC: ++ case DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_DMAC: ++ rqtype = MEMTOMEM; ++ break; ++ case DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_PERI: ++ rqtype = MEMTODEV; ++ break; ++ case DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_PERI: ++ rqtype = DEVTOMEM; ++ break; ++ case DMA_DIRECTION_DEV_TO_DEV: ++ default: ++ rqtype = DEVTODEV; /*Unsupported */ ++ break; ++ }; ++ ++ if (rqtype == DEVTODEV) ++ goto err1; ++ ++ /* Burst size max is 64 bit(AXI), not supporting > 64 bit burst size */ ++ if ((cfg & DMA_CFG_BURST_SIZE_MASK) > DMA_CFG_BURST_SIZE_8) ++ goto err1; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) { ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ } ++ ++ if (c->in_use || c->is_setup) { ++ dev_info(dmac->pi->dev, ++ "Cant setup transfer, already setup/running\n"); ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ }; ++ ++ if ((rqtype != DMA_DIRECTION_MEM_TO_MEM) && (!c->is_peri_mapped)) { ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ } ++ ++ c->is_setup = true; /* Mark it now, for setup */ ++ ++ spin_unlock_irqrestore(&lock, flags); ++ ++ /* Allocate config strcuture */ ++ config = (struct pl330_reqcfg *)kzalloc(sizeof(*config), GFP_KERNEL); ++ if (!config) { ++ err = -ENOMEM; ++ goto err1; ++ } ++ ++ /* configuration options */ ++ config->src_inc = (cfg & DMA_CFG_SRC_ADDR_INCREMENT) ? 1 : 0; ++ config->dst_inc = (cfg & DMA_CFG_DST_ADDR_INCREMENT) ? 1 : 0; ++ /* Burst size */ ++ config->brst_size = (cfg & DMA_CFG_BURST_SIZE_MASK) >> 1; ++ /* Burst Length */ ++ config->brst_len = (((cfg & DMA_CFG_BURST_LENGTH_MASK) >> 4) + 1); ++ ++ /* default settings: Noncacheable, nonbufferable, no swapping */ ++ config->scctl = SCCTRL0; ++ config->dcctl = DCCTRL0; ++ config->swap = SWAP_NO; ++ ++ /* TrustZone security AXPROT[2:0} = 000 */ ++ config->insnaccess = false; /* tied LOW */ ++ config->nonsecure = true; /* DMAC boots in non Secure Mode */ ++ config->privileged = false; /* AXPROT[2:0] = 000 */ ++ ++ /* Generate xfer list based on linked list passed */ ++ xfer_front = NULL; ++ list_for_each_entry(lli, head, next) { ++ ++ if (!lli->xfer_size) ++ continue; ++ ++ nxt = (struct pl330_xfer *)kzalloc(sizeof(*nxt), GFP_KERNEL); ++ if (!nxt) { ++ err = -ENOMEM; ++ goto err2; ++ } ++ nxt->src_addr = lli->srcaddr; ++ nxt->dst_addr = lli->dstaddr; ++ nxt->bytes = lli->xfer_size; ++ nxt->next = NULL; ++ ++ if (!xfer_front) { ++ xfer_front = nxt; /* First Item */ ++ priv = nxt; ++ } else { ++ priv->next = nxt; /* Add to the tail */ ++ priv = nxt; ++ } ++ } ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ /* Attach the request */ ++ c->req.rqtype = rqtype; ++ ++ if (rqtype != MEMTOMEM) ++ c->req.peri = c->peri_req_id; ++ ++ /* callback function */ ++ c->req.xfer_cb = pl330_req_callback; ++ c->req.token = &c->req; /* callback data */ ++ /* attach configuration */ ++ c->req.cfg = config; ++ /* attach xfer item list */ ++ c->req.x = xfer_front; ++ c->is_setup = true; /* Mark the xfer item as valid */ ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err2: ++ /* Free all allocated xfer items */ ++ if (xfer_front) { ++ nxt = xfer_front; ++ while (nxt->next) { ++ priv = nxt; ++ nxt = nxt->next; ++ kfree(priv); ++ } ++ } ++ kfree(config); ++ err1: ++ return err; ++} ++ ++int dma_start_transfer(unsigned int chan) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *c; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ ++ if (!c || !c->is_setup || c->in_use) ++ goto err; ++ ++ /* Acquire DMUX semaphore while microcode loading ++ * This call always success because protect(unprotect) happen ++ * atomically within global spinlock. ++ */ ++ if (pl330_submit_req(c->pl330_chan_id, &c->req) != 0) ++ goto err2; ++ ++ /* Start DMA channel thread */ ++ if (pl330_chan_ctrl(c->pl330_chan_id, PL330_OP_START) != 0) { ++ goto err2; ++ } ++ ++ c->in_use = true; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ return 0; ++ err2: ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_stop_transfer(unsigned int chan) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *c; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err; ++ ++ pl330_chan_ctrl(c->pl330_chan_id, PL330_OP_FLUSH); ++ ++ /* Free the completed transfer req */ ++ c->in_use = false; ++ c->is_setup = false; ++ /* free memory allocated for this request */ ++ _cleanup_req(&c->req); ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_register_callback(unsigned int chan, ++ pl330_xfer_callback_t callback, void *private_data) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *c; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err; ++ ++ c->xfer_callback = callback; ++ c->client_cookie = private_data; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_free_callback(unsigned int chan) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *c; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err; ++ ++ c->xfer_callback = NULL; ++ c->client_cookie = NULL; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++ ++} ++ ++static irqreturn_t pl330_irq_handler(int irq, void *data) ++{ ++ printk("\n-----> %s(): irq = %d\n", __func__, irq); ++ if (pl330_update(data)) ++ return IRQ_HANDLED; ++ else ++ return IRQ_NONE; ++} ++ ++static int pl330_probe(struct platform_device *pdev) ++{ ++ struct pl330_dmac_desc *pd; ++ struct iproc_pl330_data *pl330_pdata; ++ struct pl330_info *pl330_info; ++ int ret, i, irq_start, irq; ++ ++ printk("\niproc-dmac-pl330: Probe ()\n"); ++ ++ pl330_pdata = pdev->dev.platform_data; ++ ++ /* Only One Pl330 device is supported, ++ * since PL330 is closely bound to DMUX logic ++ */ ++ if (dmac) { ++ dev_err(&pdev->dev, "Multiple devices are not supported!!!\n"); ++ ret = -ENODEV; ++ goto probe_err1; ++ } ++ ++ /* Platform data is required */ ++ if (!pl330_pdata) { ++ dev_err(&pdev->dev, "platform data missing!\n"); ++ ret = -ENODEV; ++ goto probe_err1; ++ } ++ ++ pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL); ++ if (!pl330_info) { ++ ret = -ENOMEM; ++ goto probe_err1; ++ } ++ ++ pl330_info->pl330_data = NULL; ++ pl330_info->client_data = NULL; ++ pl330_info->dev = &pdev->dev; ++ ++ /* For NS DMAC is in non-secure mode */ ++ pl330_info->base = (void __iomem *)pl330_pdata->dmac_ns_base; ++ /* pl330_info->base = (void __iomem *)pl330_pdata->dmac_s_base; */ ++ ++ /* Get the first IRQ line */ ++ irq_start = pl330_pdata->irq_base; ++ irq = irq_start; ++ ++ for (i = 0; i < pl330_pdata->irq_line_count; i++) { ++ irq = irq_start + i; ++ ret = request_irq(irq, pl330_irq_handler, 0, ++ dev_name(&pdev->dev), pl330_info); ++ if (ret) { ++ irq--; ++ goto probe_err2; ++ } ++ } ++ ++ ret = pl330_add(pl330_info); ++ if (ret) ++ goto probe_err3; ++ ++ /* Allocate DMAC descriptor */ ++ pd = kmalloc(sizeof(*pd), GFP_KERNEL); ++ if (!pd) { ++ ret = -ENOMEM; ++ goto probe_err4; ++ } ++ ++ /* Hook the info */ ++ pd->pi = pl330_info; ++ pd->irq_start = irq_start; ++ pd->irq_end = irq; ++ /* init channel desc list, channels are added during dma_request_chan() */ ++ pd->chan_list.next = pd->chan_list.prev = &pd->chan_list; ++ pd->chan_count = 0; ++ ++ /* Assign the DMAC descriptor */ ++ dmac = pd; ++ ++ printk(KERN_INFO ++ "Loaded driver for PL330 DMAC-%d %s\n", pdev->id, pdev->name); ++ printk(KERN_INFO ++ "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n", ++ pl330_info->pcfg.data_buf_dep, ++ pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan, ++ pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events); ++ ++ return 0; ++ ++ probe_err4: ++ pl330_del(pl330_info); ++ probe_err3: ++ probe_err2: ++ while (irq >= irq_start) { ++ free_irq(irq, pl330_info); ++ irq--; ++ } ++ ++ kfree(pl330_info); ++ probe_err1: ++ return ret; ++} ++ ++static int pl330_remove(struct platform_device *pdev) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *cdesc; ++ int irq; ++ ++ spin_lock_irqsave(&lock, flags); ++ /* Free all channel descriptors first */ ++ list_for_each_entry(cdesc, &dmac->chan_list, node) { ++ /* free requests */ ++ _cleanup_req(&cdesc->req); ++ /* Free channel desc */ ++ _free_cdesc(cdesc); ++ } ++ ++ /* Free interrupt resource */ ++ for (irq = dmac->irq_start; irq <= dmac->irq_end; irq++) ++ free_irq(irq, dmac->pi); ++ ++ pl330_del(dmac->pi); ++ /* free PL330 info handle */ ++ kfree(dmac->pi); ++ /* Free dmac descriptor */ ++ kfree(dmac); ++ dmac = NULL; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ return 0; ++} ++ ++static struct platform_driver pl330_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "iproc-dmac-pl330", ++ }, ++ .probe = pl330_probe, ++ .remove = pl330_remove, ++}; ++ ++static int __init pl330_init(void) ++{ ++ int dmac_reset_state; ++ ++ dmac_reset_state = readl_relaxed(IPROC_IDM_DMAC_RESET_CONTROL_VA); ++ printk("Initial dmac_reset_state is: %08x\n", dmac_reset_state); ++ if ((dmac_reset_state & 1) == 1) ++ { ++ writel_relaxed(0x0, IPROC_IDM_DMAC_RESET_CONTROL_VA); ++ dmac_reset_state = readl_relaxed(IPROC_IDM_DMAC_RESET_CONTROL_VA); ++ printk("dmac_reset_state is set and now it is: %08x\n", dmac_reset_state); ++ } ++ return platform_driver_register(&pl330_driver); ++} ++ ++module_init(pl330_init); ++ ++static void __exit pl330_exit(void) ++{ ++ platform_driver_unregister(&pl330_driver); ++ return; ++} ++ ++module_exit(pl330_exit); ++ ++EXPORT_SYMBOL(dma_request_chan); ++EXPORT_SYMBOL(dma_free_chan); ++EXPORT_SYMBOL(dma_map_peripheral); ++EXPORT_SYMBOL(dma_unmap_peripheral); ++EXPORT_SYMBOL(dma_setup_transfer); ++EXPORT_SYMBOL(dma_setup_transfer_list); ++EXPORT_SYMBOL(dma_start_transfer); ++EXPORT_SYMBOL(dma_stop_transfer); ++EXPORT_SYMBOL(dma_register_callback); ++EXPORT_SYMBOL(dma_free_callback); +diff --git a/drivers/bcmdrivers/dma/dma_drv.h b/drivers/bcmdrivers/dma/dma_drv.h +new file mode 100644 +index 0000000..ca5a6b5 +--- /dev/null ++++ b/drivers/bcmdrivers/dma/dma_drv.h +@@ -0,0 +1,602 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/** ++* ++* @file dma_drv.h ++* ++* @brief DMA device driver defines and prototypes. ++* ++****************************************************************************/ ++/** ++* ++* @defgroup DMAGroup Direct Memory Access ++* @ingroup CSLGroup ++* @brief This group defines the APIs for DMA driver ++ ++Click here to navigate back to the Chip Support Library Overview page: \ref CSLOverview. \n ++*****************************************************************************/ ++#ifndef _DMA_DRV_H_ ++#define _DMA_DRV_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @addtogroup DMAGroup ++ * @{ ++ */ ++ ++/** ++* ++* DMA driver status definition ++* ++*****************************************************************************/ ++#define DMADRV_STATUS_t DMADRV_STATUS ++typedef enum ++{ ++ DMADRV_STATUS_CLOSED, ++ DMADRV_STATUS_OPEN, ++ DMADRV_STATUS_OK, ++ DMADRV_STATUS_FAIL ++}DMADRV_STATUS_t; ++ ++/** ++* ++* DMA driver callback status definition ++* ++*****************************************************************************/ ++#define DMADRV_CALLBACK_STATUS_t DMADRV_CALLBACK_STATUS ++typedef enum ++{ ++ DMADRV_CALLBACK_OK = 0, ++ DMADRV_CALLBACK_FAIL ++} DMADRV_CALLBACK_STATUS_t; ++ ++/** ++* ++* DMA driver channel descriptor definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 src; ++ UInt32 dest; ++ UInt32 next; ++ UInt32 control; ++ UInt32 size; ++ UInt32 owner; ++} Dma_Chan_Desc; ++ ++/** ++* ++* DMA driver data buffer feature definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 srcAddr; ++ UInt32 destAddr; ++ UInt32 length; ++ UInt32 bRepeat; ++ UInt32 interrupt; ++} Dma_Buffer; ++ ++/** ++* ++* DMA driver data buffer definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ Dma_Buffer buffers[1]; ++} Dma_Buffer_List; ++ ++/** ++* ++* DMA driver data buffer list definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 numBuffer; ++ Dma_Buffer_List *pBufList; ++} Dma_Data; ++ ++ ++/** ++* ++* DMA data transfer width definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_DATA_SIZE_8BIT = 0x00, ++ DMA_DATA_SIZE_16BIT = 0x01, ++ DMA_DATA_SIZE_32BIT = 0x02 ++} DMA_DWIDTH; ++ ++/** ++* ++* DMA data transfer type definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_FCTRL_MEM_TO_MEM = 0, ++ DMA_FCTRL_MEM_TO_PERI = 1, ++ DMA_FCTRL_PERI_TO_MEM = 2, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI = 3, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI_CTRL_DESTPERI = 4, ++ DMA_FCTRL_MEM_TO_PERI_CTRL_PERI = 5, ++ DMA_FCTRL_PERI_TO_MEM_CTRL_PERI = 6, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI_CTRL_SRCPERI = 7 ++} DMA_CHAN_TYPE; ++ ++/** ++* ++* DMA burst length definition ++* ++*****************************************************************************/ ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++typedef enum { ++ DMA_BURST_LEN_1 = 0x00, ///< ++ DMA_BURST_LEN_2 = 0x01, ///< ++ DMA_BURST_LEN_3 = 0x02, ///< ++ DMA_BURST_LEN_4 = 0x03, ///< ++ DMA_BURST_LEN_5 = 0x04, ///< ++ DMA_BURST_LEN_6 = 0x05, ///< ++ DMA_BURST_LEN_7 = 0x06, ///< ++ DMA_BURST_LEN_8 = 0x07, ///< ++ DMA_BURST_LEN_9 = 0x08, ///< ++ DMA_BURST_LEN_10 = 0x09, ///< ++ DMA_BURST_LEN_11 = 0x0A, ///< ++ DMA_BURST_LEN_12 = 0x0B, ///< ++ DMA_BURST_LEN_13 = 0x0C, ///< ++ DMA_BURST_LEN_14 = 0x0D, ///< ++ DMA_BURST_LEN_15 = 0x0E, ///< ++ DMA_BURST_LEN_16 = 0x0F ///< ++} DMADRV_BLENGTH; ++ ++typedef enum ++{ ++ DMA_BURST_SIZE_1 = 0x00, ++ DMA_BURST_SIZE_2 = 0x01, ++ DMA_BURST_SIZE_4 = 0x02, ++ DMA_BURST_SIZE_8 = 0x03, ++ DMA_BURST_SIZE_16 = 0x04, ++ DMA_BURST_SIZE_32 = 0x05, ++ DMA_BURST_SIZE_64 = 0x06, ++ DMA_BURST_SIZE_128 = 0x07 ++} DMA_BSIZE; ++ ++#else ++/** ++* ++* DMA burst size definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_BURST_SIZE_1 = 0x00, ++ DMA_BURST_SIZE_4 = 0x01, ++ DMA_BURST_SIZE_8 = 0x02, ++ DMA_BURST_SIZE_16 = 0x03, ++ DMA_BURST_SIZE_32 = 0x04, ++ DMA_BURST_SIZE_64 = 0x05, ++ DMA_BURST_SIZE_128 = 0x06, ++ DMA_BURST_SIZE_256 = 0x07 ++} DMA_BSIZE; ++#endif ++ ++/** ++* ++* DMA alignment definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_ALIGNMENT_8 = 8, ++ DMA_ALIGNMENT_16 = 16, ++ DMA_ALIGNMENT_32 = 32 ++} DMA_ALIGN; ++ ++/** ++* ++* DMA data transfer incremnet definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_INC_MODE_NONE = 0, ++ DMA_INC_MODE_SRC, ++ DMA_INC_MODE_DST, ++ DMA_INC_MODE_BOTH, ++} DMA_INC_MODE; ++ ++/** ++* ++* DMA driver client type definition ++* ++*****************************************************************************/ ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++typedef enum { ++ DMA_CLIENT_EP_INVALID = 0xff, ++ DMA_CLIENT_EP_UARTB_A = 8, ++ DMA_CLIENT_EP_UARTB_B = 9, ++ DMA_CLIENT_EP_UARTB2_A = 10, ++ DMA_CLIENT_EP_UARTB2_B = 11, ++ DMA_CLIENT_EP_UARTB3_A = 12, ++ DMA_CLIENT_EP_UARTB3_B = 13, ++ DMA_CLIENT_EP_SSP_0A_RX0 = 16, ++ DMA_CLIENT_EP_SSP_0B_TX0 = 17, ++ DMA_CLIENT_EP_SSP_0C_RX1 = 18, ++ DMA_CLIENT_EP_SSP_0D_TX1 = 19, ++ DMA_CLIENT_EP_SSP_1A_RX0 = 20, ++ DMA_CLIENT_EP_SSP_1B_TX0 = 21, ++ DMA_CLIENT_EP_SSP_1C_RX1 = 22, ++ DMA_CLIENT_EP_SSP_1D_TX1 = 23, ++ DMA_CLIENT_EP_HSIA = 32, ++ DMA_CLIENT_EP_HSIB = 33, ++ DMA_CLIENT_EP_HSIC = 34, ++ DMA_CLIENT_EP_HSID = 35, ++ DMA_CLIENT_EP_EANC = 40, ++ DMA_CLIENT_EP_STEREO = 41, ++ DMA_CLIENT_EP_NVIN = 42, ++ DMA_CLIENT_EP_VIN = 43, ++ DMA_CLIENT_EP_VIBRA = 44, ++ DMA_CLIENT_EP_IHF_0 = 45, ++ DMA_CLIENT_EP_VOUT = 46, ++ DMA_CLIENT_EP_SLIMA = 47, ++ DMA_CLIENT_EP_SLIMB = 48, ++ DMA_CLIENT_EP_SLIMC = 49, ++ DMA_CLIENT_EP_SLIMD = 50, ++ DMA_CLIENT_EP_SIM_A = 51, ++ DMA_CLIENT_EP_SIM_B = 52, ++ DMA_CLIENT_EP_SIM2_A = 53, ++ DMA_CLIENT_EP_SIM2_B = 54, ++ DMA_CLIENT_EP_IHF_1 = 55, ++#if defined(_RHEA_) ++ DMA_CLIENT_EP_SSP_3A_RX0 = 56, ++ DMA_CLIENT_EP_SSP_3B_TX0 = 57, ++ DMA_CLIENT_EP_SSP_3C_RX1 = 58, ++ DMA_CLIENT_EP_SSP_3D_TX1 = 59, ++#else ++ DMA_CLIENT_EP_SSP_2A_RX0 = 56, ++ DMA_CLIENT_EP_SSP_2B_TX0 = 57, ++ DMA_CLIENT_EP_SSP_2C_RX1 = 58, ++ DMA_CLIENT_EP_SSP_2D_TX1 = 59, ++#endif ++ DMA_CLIENT_EP_SPUM_SecureA = 65, ++ DMA_CLIENT_EP_SPUM_SecureB = 66, ++ DMA_CLIENT_EP_SPUM_OpenA = 67, ++ DMA_CLIENT_EP_SPUM_OpenB = 68, ++ DMA_CLIENT_MEMORY = 69, ++#if defined(_RHEA_) ++ DMA_CLIENT_EP_SSP_4A_RX0 = 76, ++ DMA_CLIENT_EP_SSP_4B_TX0 = 77, ++ DMA_CLIENT_EP_SSP_4C_RX1 = 78, ++ DMA_CLIENT_EP_SSP_4D_TX1 = 79, ++#endif ++ DMA_CLIENT_TOTAL ++} DMA_CLIENT; ++#else ++typedef enum ++{ ++ DMA_CLIENT_BULK_CRYPT_OUT = 0, ++ DMA_CLIENT_CAM = 1, ++ DMA_CLIENT_I2S_TX = 2, ++ DMA_CLIENT_I2S_RX = 3, ++ DMA_CLIENT_SIM_RX = 4, ++ DMA_CLIENT_SIM_TX = 4, ++ DMA_CLIENT_CRC = 5, ++ DMA_CLIENT_SPI_RX = 6, ++ DMA_CLIENT_SPI_TX = 7, ++ DMA_CLIENT_UARTA_RX = 8, ++ DMA_CLIENT_UARTA_TX = 9, ++ DMA_CLIENT_UARTB_RX = 10, ++ DMA_CLIENT_UARTB_TX = 11, ++ DMA_CLIENT_DES_IN = 12, ++ DMA_CLIENT_DES_OUT = 13, ++ DMA_CLIENT_USB_RX = 14, ++ DMA_CLIENT_USB_TX = 15, ++ DMA_CLIENT_UARTC_RX = 16, ++ DMA_CLIENT_UARTC_TX = 17, ++ DMA_CLIENT_BULK_CRYPT_IN = 18, ++ DMA_CLIENT_LCD = 19, ++ DMA_CLIENT_MSPRO = 20, ++ DMA_CLIENT_DSI_CM = 21, ++ DMA_CLIENT_DSI_VM = 22, ++ DMA_CLIENT_TVENC1 = 23, ++ DMA_CLIENT_TVENC2 = 24, ++#if defined(_ATHENA_) ++ DMA_CLIENT_AUDIO_IN_FIFO = 25, ++ DMA_CLIENT_AUDIO_OUT_FIFO = 26, ++ DMA_CLIENT_POLYRING_OUT_FIFO = 27, ++ DMA_CLIENT_AUDIO_WB_MIXERTAP = 28, ++ DMA_CLIENT_MEMORY = 29, ++#else ++ DMA_CLIENT_MEMORY = 25, ++#endif ++ DMA_CLIENT_TOTAL ++} DMA_CLIENT; ++#endif ++ ++/** ++* ++* DMA driver channel definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_CHANNEL_INVALID = 0xFF, ++ DMA_CHANNEL_0 = 0, ++ DMA_CHANNEL_1 = 1, ++ DMA_CHANNEL_2 = 2, ++ DMA_CHANNEL_3 = 3, ++#if !defined(_SAMOA_) ++ DMA_CHANNEL_4 = 4, ++ DMA_CHANNEL_5 = 5, ++ DMA_CHANNEL_6 = 6, ++ DMA_CHANNEL_7 = 7, ++#if defined(_ATHENA_) ++ DMA_CHANNEL_8 = 8, //used for DMA_CLIENT_AUDIO_OUT_FIFO ++ DMA_CHANNEL_9 = 9, //used for DMA_CLIENT_POLYRING_OUT_FIFO ++ DMA_CHANNEL_10 = 10, //used for DMA_CLIENT_AUDIO_WB_MIXERTAP ++ DMA_CHANNEL_11 = 11, //used for DMA_CLIENT_AUDIO_IN_FIFO ++#endif ++#endif ++ TOTAL_DMA_CHANNELS ++} DMA_CHANNEL; ++ ++/** ++* ++* DMA driver callback function definition ++* ++*****************************************************************************/ ++#define DMADRV_CALLBACK_t DmaDrv_Callback ++typedef void (*DMADRV_CALLBACK_t)(DMADRV_CALLBACK_STATUS_t Err); ++ ++/** ++* ++* DMA driver channel info structure definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ DMA_CLIENT srcID; ++ DMA_CLIENT dstID; ++ DMA_CHAN_TYPE type; ++ DMA_ALIGN alignment; ++ DMA_BSIZE srcBstSize; ++ DMA_BSIZE dstBstSize; ++ DMA_DWIDTH srcDataWidth; ++ DMA_DWIDTH dstDataWidth; ++ UInt32 priority; ++ UInt32 chanNumber; ++ UInt32 dmaCfgReg; ++ UInt32 incMode; ++ DmaDrv_Callback xferCompleteCb; ++ UInt32 prot; ++ UInt32 dstMaster; ++ UInt32 srcMaster; ++ UInt32 dstIncrement; ++ UInt32 srcIncrement; ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++ DMADRV_BLENGTH srcBstLength; ++ DMADRV_BLENGTH dstBstLength; ++#endif ++ Boolean freeChan; ++ Boolean bCircular; ++} Dma_Chan_Info, *pChanInfo; ++ ++/** ++* ++* DMA driver LLI structure definition ++* ++*****************************************************************************/ ++typedef void *DMADRV_LLI_T; ++ ++/** ++* ++* This function initialize dma driver ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Init(void); ++ ++/** ++* ++* This function deinitialize dma driver ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_DeInit(void); ++ ++/** ++* ++* This function allocates dma channel ++* ++* @param srcID (in) source identification ++* @param dstID (in) destination identification ++* @param chanID (in) buffer to store channel number ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Obtain_Channel( ++ DMA_CLIENT srcID, ++ DMA_CLIENT dstID, ++ DMA_CHANNEL *chanID ++); ++ ++/** ++* ++* This function release dma channel ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Release_Channel(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function configure dma channel ++* ++* @param chanID (in) channel number ++* @param pChanInfo (in) pointer to dma channe info structure ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Config_Channel( ++ DMA_CHANNEL chanID, ++ Dma_Chan_Info *pChanInfo ++); ++ ++/** ++* ++* This function bind data buffer for the DMA channel ++* ++* @param chanID (in) channel to bind data ++* @param pData (in) pointer to dma channel data buffer ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Bind_Data(DMA_CHANNEL chanID, Dma_Data *pData); ++ ++/** ++* ++* This function start dma channel transfer ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Start_Transfer(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function bind data buffer for the DMA channel ++* ++* @param chanID (in) channel to bind data ++* @param pData (in) pointer to dma channel data buffer ++* @param pLLI (in) buffer to store returned LLI table ++* identification info ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Bind_Data_Ex( ++ DMA_CHANNEL chanID, ++ Dma_Data *pData, ++ DMADRV_LLI_T *pLLI ++); ++ ++/** ++* ++* This function start dma channel transfer ++* ++* @param chanID (in) channel identification ++* @param pLLI (in) one of the LLI tables needs to be used for DMA ++* transfer ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Start_Transfer_Ex( ++ DMA_CHANNEL chanID, ++ DMADRV_LLI_T pLLI ++); ++ ++/** ++* ++* This function stop dma channel trnasfer ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Stop_Transfer(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function stop dma channel trnasfer and lose all data in FIFO ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Force_Shutdown_Channel(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function register hisr for client usage ++* ++* @param client (in) client identification ++* @param hisr (in) registered hisr ++* ++* @return void ++* ++*****************************************************************************/ ++void DMADRV_Register_HISR(DMA_CLIENT client, void *hisr); ++ ++/** ++* ++* This function unregister hisr from client usage ++* ++* @param client (in) client identification ++* ++* @return void ++* ++*****************************************************************************/ ++void DMADRV_UnRegister_HISR(DMA_CLIENT client); ++ ++/** ++* ++* This function get hisr for client usage ++* ++* @param client (in) client identification ++* ++* @return hisr (out) return registered client's hisr ++* ++*****************************************************************************/ ++void *DMADRV_Get_HISR(DMA_CLIENT client); ++ ++/** ++* ++* This function get DMA driver version number ++* ++* @return driver version number ++* ++*****************************************************************************/ ++UInt32 DMADRV_Get_Version(void); ++ ++/** @} */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DMA_DRV_H_ */ +diff --git a/drivers/bcmdrivers/dma/pl330-pdata.h b/drivers/bcmdrivers/dma/pl330-pdata.h +new file mode 100644 +index 0000000..21c74c8 +--- /dev/null ++++ b/drivers/bcmdrivers/dma/pl330-pdata.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __DMA_PL330_PDATA_H ++#define __DMA_PL330_PDATA_H ++ ++/* ++ * The platforms just need to provide this info to the KONA DMA API ++ */ ++struct iproc_pl330_data { ++ /* Non Secure DMAC virtual base address */ ++ unsigned int dmac_ns_base; ++ /* Secure DMAC virtual base address */ ++ unsigned int dmac_s_base; ++ /* # of PL330 dmac channels 'configurable' */ ++ unsigned int num_pl330_chans; ++ /* DMAC irq number, connected to GIC */ ++ int irq_base; ++ /* # of PL330 Interrupts/events 'configurable' */ ++ unsigned int irq_line_count; ++ //int dmac_abort_irq; ++}; ++ ++#endif /* __DMA_PL330_PDATA_H */ +diff --git a/drivers/bcmdrivers/gmac/et/.gitignore b/drivers/bcmdrivers/gmac/et/.gitignore +new file mode 100644 +index 0000000..752a208 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/et/.gitignore +@@ -0,0 +1,6 @@ ++/.built-in.o.cmd ++/.et.o.cmd ++/built-in.o ++/et.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/gmac/et/Kconfig b/drivers/bcmdrivers/gmac/et/Kconfig +new file mode 100644 +index 0000000..53f6462 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/et/Kconfig +@@ -0,0 +1,14 @@ ++config IPROC_GMAC ++ tristate "GMAC support " ++ select NETDEVICES ++ select PCI ++ select HND ++ select ET ++ select ET_47XX ++ select ET_ALL_PASSIVE_ON ++ depends on ARCH_IPROC ++ default n ++ help ++ Add GMAC support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/gmac/et/Makefile b/drivers/bcmdrivers/gmac/et/Makefile +new file mode 100755 +index 0000000..4f603a0 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/et/Makefile +@@ -0,0 +1,97 @@ ++# ++# Makefile for the Broadcom et driver ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# ++# $Id: Makefile,v 1.5 2010-12-07 04:47:36 $ ++# ++ ++ ++ETSRCDIR := ../src/et ++ ++et-objs := $(ETSRCDIR)/sys/et_linux.o $(ETSRCDIR)/sys/etc.o ++ ++## from linux dir ########## ++export SRCBASE_et := $(src)/$(ETSRCDIR)/sys/../../ ++KBUILD_CFLAGS += -I$(SRCBASE_et)/include ++KBUILD_AFLAGS += -I$(SRCBASE_et)/include ++KBUILD_CFLAGS += -DBCMDRIVER -Dlinux ++ ++KBUILD_CFLAGS += -DCFG_NORTHSTAR -DCFG_SIM ++ ++######## ######################### ++ ++#EXTRA_CFLAGS += -DGMAC3 ++ ++EXTRA_CFLAGS += -DGMAC_RATE_LIMITING ++ ++ifeq ($(CONFIG_BCM_IPROC_GMAC_SG),y) ++EXTRA_CFLAGS += -DBCMDMASGLISTOSL ++endif ++ ++ifeq ($(CONFIG_ET_47XX),y) ++et-objs += $(ETSRCDIR)/sys/etcgmac.o ++EXTRA_CFLAGS += -DCFG_GMAC -DBCMDMA64 -DBCMDMA32 -DBCMDBG_ERR ++ifeq ($(CONFIG_ROOT_NFS),y) ++else ++ifeq ($(CONFIG_MACH_NS),y) ++EXTRA_CFLAGS += -DETROBO ++endif ++endif ++ifeq ($(CONFIG_MACH_NSP),y) ++EXTRA_CFLAGS += -DETROBO ++endif ++endif ++ ++obj-$(CONFIG_ET) := et.o ++ ++EXTRA_CFLAGS += -DDMA -Wno-error ++ifeq ($(CONFIG_ET_ALL_PASSIVE_ON),y) ++#EXTRA_CFLAGS += -DET_ALL_PASSIVE_ON -DET_ALL_PASSIVE ++# Forcing the use of CONFIG_ET_ALL_PASSIVE_RUNTIME ++EXTRA_CFLAGS += -DET_ALL_PASSIVE ++else ++ifeq ($(CONFIG_ET_ALL_PASSIVE_RUNTIME),y) ++EXTRA_CFLAGS += -DET_ALL_PASSIVE ++endif ++endif ++ ++ifeq ($(CONFIG_ET_NAPI_POLL),y) ++EXTRA_CFLAGS += -DNAPI_POLL ++else ++ifeq ($(CONFIG_ET_NAPI2_POLL),y) ++EXTRA_CFLAGS += -DNAPI2_POLL ++endif ++endif ++ ++# Disable PKTC for now, it is required the CTF enabled ++#EXTRA_CFLAGS += -DPKTC ++ ++# Search for sources under src/et/sys or objects under src/et/linux ++EXTRA_CFLAGS += -I$(src)/$(ETSRCDIR)/sys ++ ++ifneq ($(KERNELRELEASE),) ++# kbuild part of makefile ++else ++# Normal makefile ++KERNELDIR := ../../kernel/linux ++all: ++ $(MAKE) -C $(KERNELDIR) M=`pwd` ++ ++clean: ++ $(MAKE) -C $(KERNELDIR) M=`pwd` clean ++endif ++ ++clean-files += $(ETSRCDIR)/sys/*.o $(ETSRCDIR)/sys/.*.o.cmd +diff --git a/drivers/bcmdrivers/gmac/hnd/.gitignore b/drivers/bcmdrivers/gmac/hnd/.gitignore +new file mode 100644 +index 0000000..e015903 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/.gitignore +@@ -0,0 +1,6 @@ ++/.built-in.o.cmd ++/.hnd.o.cmd ++/built-in.o ++/hnd.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/gmac/hnd/Kconfig b/drivers/bcmdrivers/gmac/hnd/Kconfig +new file mode 100755 +index 0000000..e57b937 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/Kconfig +@@ -0,0 +1,197 @@ ++# ++# Broadcom Home Networking Division (HND) driver configuration ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# ++# $Id: Kconfig,v 1.6 2010-07-05 07:01:45 $ ++# ++ ++menu "Broadcom HND network devices" ++# Kenlo depends on PCI ++config HND ++ bool "Broadcom HND network device support" ++config ET ++ tristate "10/100 Ethernet support" ++ depends on HND ++config ET_47XX ++ bool "BCM47xx support" ++ depends on ET ++choice ++ prompt "ET ALL PASSIVE mode" ++ depends on ET ++ optional ++config ET_ALL_PASSIVE_ON ++ bool "ET ALL PASSIVE on" ++config ET_ALL_PASSIVE_RUNTIME ++ bool "ET ALL PASSIVE with runtime setting" ++endchoice ++config ET_NAPI2_POLL ++ bool "BCM GMAC NAPI2_POLL" ++ default n ++ depends on !ET_ALL_PASSIVE_ON && !ET_ALL_PASSIVE_RUNTIME ++config BCM_CTF ++ tristate "BCMCTF support" ++ depends on HND ++config BCM_CTF2 ++ tristate "BCMCTF2 support (NETFILTER and NF_DEFRAG_IPV4 required)" ++ depends on HND ++ default n ++ help ++ Add BCM_CTF2 support for performance enhancements with WLAN integration in LDK ++config BCM_IPROC_GMAC_ACP ++ tristate "BCM GMAC_ACP support" ++ depends on HND ++ default n ++ help ++ Add GMAC_ACP support to improve performance without ++ cache flushing/invalidate. The uboot's bootargs must ++ include "mem=240M" to limit whole Kernel memory inside ++ ACP region which is 256MB from 0x80000000; since kernel ++ starts from 0x81000000, total mem is 240MB only ++ If unsure, say N. ++config BCM_IPROC_GMAC_PREFETCH ++ tristate "BCM GMAC prefetching support" ++ depends on HND ++ default n ++ help ++ If unsure, say N. ++config BCM_IPROC_GMAC_TXONCPU1 ++ tristate "BCM GMAC TX-ON-CPU1 support" ++ depends on HND && SMP && (ET_ALL_PASSIVE_ON || ET_ALL_PASSIVE_RUNTIME) ++ default n ++ help ++ Run "Passive Mode" Tx workthread on CPU1 for ++ multi-cores utilizing; ++ If unsure, say N. ++config BCM_IPROC_GMAC_SKB_RECYCLING ++ tristate "BCM GMAC SKB-RECYCLING support" ++ depends on HND ++ default n ++ help ++ Recycle Tx/Rx skb_buff for high-speed IP forwarding tasks; ++ it is still an experimental feature now. ++ If unsure, say N. ++config BCM_IPROC_GMAC_LOCK_OPT ++ tristate "BCM GMAC LOCK OPTIMIZATION support" ++ depends on HND ++ default n ++ help ++ Minimize locks during Tx/Rx tasks; ++ it is tested under "Passive Mode" (workthread) only. ++ If unsure, say N. ++config BCM_IPROC_GMAC_RWREG_OPT ++ tristate "BCM GMAC R/W_REG OPTIMIZATION support" ++ depends on HND ++ default n ++ help ++ Remove unnecessary "DSB" intructions of R/W_REG Macro. ++ If unsure, say N. ++config BCM_IPROC_GMAC_SG ++ bool "BCM GMAC Scatter Gather support" ++ default n ++ depends on HND ++config WL_EMULATOR ++ bool "WL emulation using Gigabit ethernet" ++ depends on HND ++config BCM57XX ++ tristate "BCM57xx support is ON" ++ depends on WL_EMULATOR ++config WL ++ tristate "Wireless feature variant is set to AP" ++ depends on WL_EMULATOR ++ select WL_USE_AP ++config BCM57XX ++ tristate "BCM57xx Gigabit Ethernet support" ++ depends on HND && !WL_EMULATOR ++config WL ++ tristate "BCM43xx 802.11 Wireless support" ++ depends on HND && !WL_EMULATOR ++config WAPI ++ bool "Wireless Authentication Privacy Infrastructure (WAPI) support" ++ depends on HND && !WL_EMULATOR && WL ++ select MTD_BCMCONF_PARTS ++choice ++ prompt "Wireless feature variant" ++ depends on HND && !WL_EMULATOR && WL ++config WL_USE_AP ++ bool "Config file for basic AP variant" ++config WL_USE_AP_SDSTD ++ bool "Config file for basic AP sdstd variant" ++config WL_USE_STA ++ bool "Config file for basic STA variant" ++config WL_USE_APSTA ++ bool "Config file for basic APSTA variant" ++config WL_USE_AP_ONCHIP_G ++ bool "Config file for AP 1chipG variant" ++config WL_USE_STA_ONCHIP_G ++ bool "Config file for STA 1chipG variant" ++config WL_USE_APSTA_ONCHIP_G ++ bool "Config file for APSTA 1chipG variant" ++endchoice ++config WL_USBAP ++ bool "USB/HSIC Wireless Access Point support" ++config WL_AP ++ string "Config file for basic AP variant" ++ default "wlconfig_lx_router_ap" ++config WL_AP_SDSTD ++ string "Config file for basic AP sdstd variant" ++ default "wlconfig_lx_router_ap_sdstd" ++config WL_STA ++ string "Config file for basic STA variant" ++ default "wlconfig_lx_router_sta" ++config WL_APSTA ++ string "Config file for basic APSTA variant" ++ default "wlconfig_lx_router_apsta" ++config WL_AP_ONCHIP_G ++ string "Config file for AP 1chipG variant" ++ default "wlconfig_lx_router_ap_1chipG" ++config WL_STA_ONCHIP_G ++ string "Config file for STA 1chipG variant" ++ default "wlconfig_lx_router_sta_1chipG" ++config WL_HIGH ++ string "Config file for high/bmac split variant" ++ default "wlconfig_lx_router_high" ++ ++choice ++ prompt "WL ALL PASSIVE mode" ++ depends on WL ++ ++config WL_ALL_PASSIVE_ON ++ bool "WL ALL PASSIVE on" ++config WL_ALL_PASSIVE_RUNTIME ++ bool "WL ALL PASSIVE with runtime setting" ++endchoice ++config DPSTA ++ tristate "Broadcom dualband wireless proxy repeater support" ++ depends on WL ++config EMF ++ tristate "Efficient Multicast Forwarding & IGMP Snooping Layers" ++ depends on NETFILTER ++config PLC ++ bool "Broadcom PLC network failover support" ++ depends on ET && WL ++config IPROC_SDK_MGT_PORT_HANDOFF ++ bool "GMAC SDK Management port handoff" ++ default y ++ depends on HND ++config IPROC_2STAGE_RX ++ bool "GMAC 2 stage packet RX" ++ default n ++ depends on HND ++config SERDES_ASYMMETRIC_MODE ++ bool "GMAC SDK Serdes Asymmetric Mode" ++ default n ++ depends on HND && (MACH_KT2 || MACH_HX4) ++endmenu +diff --git a/drivers/bcmdrivers/gmac/hnd/Makefile b/drivers/bcmdrivers/gmac/hnd/Makefile +new file mode 100755 +index 0000000..83c02e2 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/Makefile +@@ -0,0 +1,175 @@ ++# ++# Makefile for Broadcom Home Networking Division (HND) shared driver code ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# ++# $Id: Makefile,v 1.5 2008-05-02 22:49:54 $ ++# ++ ++SHARED := ../src/shared ++ ++include $(src)/$(SHARED)/wl_config ++ ++## from linux dir ########## ++export SRCBASE_hnd := $(src)/$(SHARED)/../ ++KBUILD_CFLAGS += -I$(SRCBASE_hnd)/include ++KBUILD_AFLAGS += -I$(SRCBASE_hnd)/include ++KBUILD_CFLAGS += -DBCMDRIVER -Dlinux ++ ++KBUILD_CFLAGS += -DCFG_NORTHSTAR -DCFG_SIM ++ ++################################# ++ ++EXTRA_CFLAGS += $(WLFLAGS) -DBCM5354 -DLINUX_HYBRID_POSTPROCESSING_REMOVAL -DBCMDBG_ERR ++ ++ifeq ($(CONFIG_BCM_IPROC_GMAC_SG),y) ++EXTRA_CFLAGS += -DBCMDMASGLISTOSL ++endif ++ ++### for bcm5301x_otp.h ++EXTRA_CFLAGS += -I$(src)/../../otp/ ++ ++ ++#HND_OBJS += $(src)/$(SHARED)/hndfwd.o ++#hnd-objs += $(SHARED)/hndfwd.o ++#EXTRA_CFLAGS += -DGMAC3 ++ ++ifneq ($(CONFIG_BCM947XX),y) ++HND_OBJS += $(src)/$(SHARED)/nvramstubs.o ++hnd-objs += $(SHARED)/nvramstubs.o ++endif ++ ++ifeq ($(CONFIG_MACH_HX4),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_serdes.o ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o ++hnd-objs += $(SHARED)/bcmiproc_phy5461s.o ++endif ++ifeq ($(CONFIG_MACH_DNI_3448P),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_serdes.o ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o ++hnd-objs += $(SHARED)/bcmiproc_phy5461s.o ++endif ++ifeq ($(CONFIG_MACH_ACCTON_AS4610_54),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_serdes.o ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o ++hnd-objs += $(SHARED)/bcmiproc_phy5461s.o ++endif ++ifeq ($(CONFIG_MACH_KT2),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_serdes.o ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o ++hnd-objs += $(SHARED)/bcmiproc_phy5461s.o ++endif ++ ++ifeq ($(CONFIG_MACH_HR2),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5221.o ++hnd-objs += $(SHARED)/bcmiproc_phy5221.o ++endif ++ ++ifeq ($(CONFIG_MACH_NSP),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_robo_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_robo_serdes.o ++endif ++ ++ifeq ($(CONFIG_ET_47XX),y) ++HND_OBJS += $(src)/$(SHARED)/bcmrobo.o ++hnd-objs += $(SHARED)/bcmrobo.o ++endif ++ ++#ifdef HNDDMA ++ifeq ($(HNDDMA),1) ++HND_OBJS += $(src)/$(SHARED)/hnddma.o ++hnd-objs += $(SHARED)/hnddma.o ++endif ++#endif ++ ++#ifdef BCMUTILS ++ifeq ($(BCMUTILS),1) ++HND_OBJS += $(src)/$(SHARED)/bcmutils.o ++hnd-objs += $(SHARED)/bcmutils.o ++endif ++#endif ++ ++#ifdef SIUTILS ++ifeq ($(SIUTILS),1) ++HND_OBJS += $(src)/$(SHARED)/siutils.o ++hnd-objs += $(SHARED)/siutils.o ++HND_OBJS += $(src)/$(SHARED)/aiutils.o ++hnd-objs += $(SHARED)/aiutils.o ++ifeq ($(CONFIG_MACH_HX4),y) ++HND_OBJS += $(src)/$(SHARED)/hx4_erom.o ++hnd-objs += $(SHARED)/hx4_erom.o ++endif ++ifeq ($(CONFIG_MACH_DNI_3448P),y) ++HND_OBJS += $(src)/$(SHARED)/hx4_erom.o ++hnd-objs += $(SHARED)/hx4_erom.o ++endif ++ifeq ($(CONFIG_MACH_ACCTON_AS4610_54),y) ++HND_OBJS += $(src)/$(SHARED)/hx4_erom.o ++hnd-objs += $(SHARED)/hx4_erom.o ++endif ++ifeq ($(CONFIG_MACH_HR2),y) ++HND_OBJS += $(src)/$(SHARED)/hr2_erom.o ++hnd-objs += $(SHARED)/hr2_erom.o ++endif ++ifeq ($(CONFIG_MACH_NSP),y) ++HND_OBJS += $(src)/$(SHARED)/nsp_erom.o ++hnd-objs += $(SHARED)/nsp_erom.o ++endif ++ifeq ($(CONFIG_MACH_KT2),y) ++HND_OBJS += $(src)/$(SHARED)/kt2_erom.o ++hnd-objs += $(SHARED)/kt2_erom.o ++endif ++endif ++#endif /* SIUTILS */ ++ ++#ifdef BCMSROM ++ifeq ($(BCMSROM),1) ++HND_OBJS += $(src)/$(SHARED)/bcmsrom.o ++hnd-objs += $(SHARED)/bcmsrom.o ++HND_OBJS += $(src)/$(SHARED)/bcmotp.o ++hnd-objs += $(SHARED)/bcmotp.o ++endif ++#endif ++ ++#ifdef BCMOTP ++ifeq ($(BCMOTP),1) ++ifneq ($(BCMSROM),1) ++HND_OBJS += $(src)/$(SHARED)/bcmotp.o ++hnd-objs += $(SHARED)/bcmotp.o ++endif ++EXTRA_CFLAGS += -DBCMNVRAMR ++endif ++#endif ++ ++#ifdef OSLLX ++# linux osl ++ifeq ($(OSLLX),1) ++HND_OBJS += $(src)/$(SHARED)/linux_osl.o ++hnd-objs += $(SHARED)/linux_osl.o ++endif ++#endif ++ ++# BCMDMA32 ++ifeq ($(BCMDMA32),1) ++EXTRA_CFLAGS += -DBCMDMA32 ++endif ++ ++obj-$(CONFIG_HND) := hnd.o ++ ++hnd-objs += shared_ksyms.o +diff --git a/drivers/bcmdrivers/gmac/hnd/shared_ksyms.c b/drivers/bcmdrivers/gmac/hnd/shared_ksyms.c +new file mode 100755 +index 0000000..a615f54 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/shared_ksyms.c +@@ -0,0 +1,62 @@ ++#include ++#include ++#include ++#include ++#include ++EXPORT_SYMBOL(bcm_atoi); ++EXPORT_SYMBOL(bcm_binit); ++EXPORT_SYMBOL(bcm_bprintf); ++EXPORT_SYMBOL(bcm_ether_atoe); ++EXPORT_SYMBOL(bcm_ether_ntoa); ++EXPORT_SYMBOL(bcm_robo_attach); ++EXPORT_SYMBOL(bcm_robo_config_vlan); ++EXPORT_SYMBOL(bcm_robo_detach); ++EXPORT_SYMBOL(bcm_robo_enable_device); ++EXPORT_SYMBOL(bcm_robo_enable_switch); ++EXPORT_SYMBOL(bcm_strtoul); ++EXPORT_SYMBOL(getgpiopin); ++EXPORT_SYMBOL(getintvar); ++EXPORT_SYMBOL(getvar); ++EXPORT_SYMBOL(nvram_env_gmac_name); ++EXPORT_SYMBOL(nvram_get); ++#ifdef CTFPOOL ++EXPORT_SYMBOL(osl_ctfpool_add); ++EXPORT_SYMBOL(osl_ctfpool_cleanup); ++EXPORT_SYMBOL(osl_ctfpool_init); ++EXPORT_SYMBOL(osl_ctfpool_replenish); ++EXPORT_SYMBOL(osl_ctfpool_stats); ++#endif ++EXPORT_SYMBOL(osl_delay); ++EXPORT_SYMBOL(osl_detach); ++EXPORT_SYMBOL(osl_dma_map); ++EXPORT_SYMBOL(osl_malloc); ++EXPORT_SYMBOL(osl_malloced); ++EXPORT_SYMBOL(osl_mfree); ++EXPORT_SYMBOL(osl_pkt_frmnative); ++EXPORT_SYMBOL(osl_pkt_tonative); ++EXPORT_SYMBOL(osl_pktfree); ++EXPORT_SYMBOL(pktsetprio); ++EXPORT_SYMBOL(robo_bprintf_mib); ++EXPORT_SYMBOL(robo_dump_mib); ++EXPORT_SYMBOL(robo_dump_regs); ++EXPORT_SYMBOL(robo_is_port_cfg); ++EXPORT_SYMBOL(robo_power_save_mode_get); ++EXPORT_SYMBOL(robo_power_save_mode_set); ++EXPORT_SYMBOL(robo_power_save_mode_update); ++EXPORT_SYMBOL(robo_power_save_toggle); ++EXPORT_SYMBOL(robo_reset_mib); ++EXPORT_SYMBOL(robo_watchdog); ++EXPORT_SYMBOL(si_core_cflags); ++EXPORT_SYMBOL(si_core_disable); ++EXPORT_SYMBOL(si_core_reset); ++EXPORT_SYMBOL(si_core_sflags); ++EXPORT_SYMBOL(si_coreid); ++EXPORT_SYMBOL(si_coreidx); ++EXPORT_SYMBOL(si_corerev); ++EXPORT_SYMBOL(si_coreunit); ++EXPORT_SYMBOL(si_detach); ++EXPORT_SYMBOL(si_gpioout); ++EXPORT_SYMBOL(si_gpioouten); ++EXPORT_SYMBOL(si_iscoreup); ++EXPORT_SYMBOL(si_kattach); ++EXPORT_SYMBOL(si_setcoreidx); +diff --git a/drivers/bcmdrivers/gmac/hnd/shared_ksyms.sh b/drivers/bcmdrivers/gmac/hnd/shared_ksyms.sh +new file mode 100755 +index 0000000..8b537a3 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/shared_ksyms.sh +@@ -0,0 +1,30 @@ ++#!/bin/sh ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# ++# $Id: shared_ksyms.sh,v 1.2 2008-12-05 20:10:41 $ ++# ++ ++cat < ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++#include ++#endif ++EOF ++ ++for file in $* ; do ++ ${NM} $file | sed -ne 's/[0-9A-Fa-f]* [BDRT] \([^ ]*\)/extern void \1; EXPORT_SYMBOL(\1);/p' ++done +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/.gitignore b/drivers/bcmdrivers/gmac/src/et/sys/.gitignore +new file mode 100644 +index 0000000..25794d4 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/.gitignore +@@ -0,0 +1,6 @@ ++/.et_linux.o.cmd ++/.etc.o.cmd ++/.etcgmac.o.cmd ++/et_linux.o ++/etc.o ++/etcgmac.o +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_cfg.h b/drivers/bcmdrivers/gmac/src/et/sys/et_cfg.h +new file mode 100755 +index 0000000..38ded3d +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_cfg.h +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * BCM ET driver config options ++ * ++ * $Id: et_cfg.h,v 1.1.4.1 2010-08-05 19:17:00 $ ++ */ ++ ++#if defined(__NetBSD__) || defined(__FreeBSD__) ++#include ++#include ++#endif /* defined(__NetBSD__) || defined(__FreeBSD__) */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_dbg.h b/drivers/bcmdrivers/gmac/src/et/sys/et_dbg.h +new file mode 100755 +index 0000000..7d209a1 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_dbg.h +@@ -0,0 +1,59 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Minimal debug/trace/assert driver definitions for ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Device Driver. ++ * ++ * $Id: et_dbg.h 286404 2011-09-27 19:29:08Z $ ++ */ ++ ++#ifndef _et_dbg_ ++#define _et_dbg_ ++ ++#ifdef BCMDBG ++struct ether_header; ++extern void etc_prhdr(char *msg, struct ether_header *eh, uint len, int unit); ++extern void etc_prhex(char *msg, uchar *buf, uint nbytes, int unit); ++/* ++ * et_msg_level is a bitvector: ++ * 0 errors ++ * 1 function-level tracing ++ * 2 one-line frame tx/rx summary ++ * 3 complex frame tx/rx in hex ++ */ ++#define ET_ERROR(args) if (!(et_msg_level & 1)) ; else printf args ++#define ET_TRACE(args) if (!(et_msg_level & 2)) ; else printf args ++#define ET_PRHDR(msg, eh, len, unit) if (!(et_msg_level & 4)) ; else etc_prhdr(msg, eh, len, unit) ++#define ET_PRPKT(msg, buf, len, unit) if (!(et_msg_level & 8)) ; else etc_prhex(msg, buf, len, unit) ++#else /* BCMDBG */ ++#define ET_ERROR(args) ++#define ET_TRACE(args) ++#define ET_PRHDR(msg, eh, len, unit) ++#define ET_PRPKT(msg, buf, len, unit) ++#endif /* BCMDBG */ ++ ++extern uint32 et_msg_level; ++ ++#define ET_LOG(fmt, a1, a2) ++ ++/* include port-specific tunables */ ++#if defined(linux) ++#include ++#else ++#error ++#endif ++ ++#endif /* _et_dbg_ */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_export.h b/drivers/bcmdrivers/gmac/src/et/sys/et_export.h +new file mode 100755 +index 0000000..e06bf27 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_export.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Required functions exported by the port-specific (os-dependent) driver ++ * to common (os-independent) driver code. ++ * ++ * $Id: et_export.h 322208 2012-03-20 01:53:23Z $ ++ */ ++ ++#ifndef _et_export_h_ ++#define _et_export_h_ ++ ++/* misc callbacks */ ++extern void et_init(void *et, uint options); ++extern void et_reset(void *et); ++extern void et_link_up(void *et); ++extern void et_link_down(void *et); ++extern bool et_is_link_up(void *et); ++extern int et_up(void *et); ++extern int et_down(void *et, int reset); ++extern void et_dump(void *et, struct bcmstrbuf *b); ++extern void et_intrson(void *et); ++ ++/* for BCM5222 dual-phy shared mdio contortion */ ++extern void *et_phyfind(void *et, uint coreunit); ++extern uint16 et_phyrd(void *et, uint phyaddr, uint reg); ++extern void et_phywr(void *et, uint reg, uint phyaddr, uint16 val); ++#ifdef HNDCTF ++extern void et_dump_ctf(void *et, struct bcmstrbuf *b); ++#endif ++#endif /* _et_export_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_linux.c b/drivers/bcmdrivers/gmac/src/et/sys/et_linux.c +new file mode 100755 +index 0000000..e510812 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_linux.c +@@ -0,0 +1,3896 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux device driver for ++ * Broadcom BCM47XX 10/100/1000 Mbps Ethernet Controller ++ * ++ * $Id: et_linux.c 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++#include ++#define __UNDEF_NO_VERSION__ ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef SIOCETHTOOL ++#include ++#endif /* SIOCETHTOOL */ ++#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 ++#ifdef HNDCTF ++#include ++#endif /* HNDCTF */ ++#ifdef GMAC3 ++#include /* GMAC3 */ ++#endif /* GMAC3 */ ++ ++/* to be cleaned and fixed */ ++/* to be cleaned Makefile */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "plat/shm.h" ++ ++#if defined(CONFIG_IPROC_FA2) ++#include "../../../fa2/fa2_defs.h" ++#include "../../../fa2/fa2_if.h" ++#endif /* CONFIG_IPROC_FA2 */ ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++#include ++ ++#define SKB_PREFETCH_LEN (128) ++ ++/* 30 rxhdr + 34 mac & ip */ ++#define SKB_DATA_PREFETCH_LEN (96) ++ ++#endif ++ ++#define MIN_PACKET_SIZE 70 /* for gmac2 (&GMAC3?) */ ++ /* if packet is less than 64 bytes, it will not tx */ ++ /* if packet is less than 66 bytes, CRC is not generated) */ ++ /* this length is after brm tag is stripped off */ ++#define NS_MAX_GMAC_CORES 4 ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) ++#define HAVE_NET_DEVICE_OPS 1 ++#define HAVE_NETDEV_PRIV 1 ++#endif ++ ++int gmac_pdev_loaded[NS_MAX_GMAC_CORES]; ++ ++/* Global SB handle */ ++si_t *bcm947xx_sih = NULL; ++spinlock_t bcm947xx_sih_lock; ++EXPORT_SYMBOL(bcm947xx_sih); ++EXPORT_SYMBOL(bcm947xx_sih_lock); ++ ++/* Convenience */ ++#define sih bcm947xx_sih ++#define sih_lock bcm947xx_sih_lock ++ ++#ifdef ET_ALL_PASSIVE_ON ++/* When ET_ALL_PASSIVE_ON, ET_ALL_PASSIVE must be true */ ++#define ET_ALL_PASSIVE_ENAB(et) 1 ++#else ++#ifdef ET_ALL_PASSIVE ++#define ET_ALL_PASSIVE_ENAB(et) (!(et)->all_dispatch_mode) ++#else /* ET_ALL_PASSIVE */ ++#define ET_ALL_PASSIVE_ENAB(et) 0 ++#endif /* ET_ALL_PASSIVE */ ++#endif /* ET_ALL_PASSIVE_ON */ ++ ++//#define BRCM_TAG true ++//#define PRINT_PKT true ++//#define PRINT_PKT_SUM true ++ ++#ifdef ET_ALL_PASSIVE ++#define ET_LIMIT_TXQ ++#endif ++ ++#ifdef PKTC ++#ifndef HNDCTF ++#error "Packet chaining feature can't work w/o CTF" ++#endif ++#define PKTC_ENAB(et) ((et)->etc->pktc) ++ ++#ifdef GMAC3 ++#define PKT_CHAINABLE(et, p, evh, prio, h_sa, h_da, h_prio) \ ++ (!eacmp((h_da), ((struct ethervlan_header *)(evh))->ether_dhost) && \ ++ !eacmp((h_sa), ((struct ethervlan_header *)(evh))->ether_shost) && \ ++ ((h_prio) == (prio)) && !RXH_FLAGS((et)->etc, PKTDATA((et)->osh, (p))) && \ ++ ((((struct ether_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IP)) || \ ++ (((struct ether_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IPV6)))) ++#else /* !GMAC3 */ ++#define PKT_CHAINABLE(et, p, evh, prio, h_sa, h_da, h_prio) \ ++ (!ETHER_ISNULLDEST(((struct ethervlan_header *)(evh))->ether_dhost) && \ ++ !eacmp((h_da), ((struct ethervlan_header *)(evh))->ether_dhost) && \ ++ !eacmp((h_sa), ((struct ethervlan_header *)(evh))->ether_shost) && \ ++ (et)->brc_hot && CTF_HOTBRC_CMP((et)->brc_hot, (evh), (void *)(et)->dev) && \ ++ ((h_prio) == (prio)) && !RXH_FLAGS((et)->etc, PKTDATA((et)->osh, (p))) && \ ++ (((struct ethervlan_header *)(evh))->vlan_type == HTON16(ETHER_TYPE_8021Q)) && \ ++ ((((struct ethervlan_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IP)) || \ ++ (((struct ethervlan_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IPV6)))) ++#endif /* !GMAC3 */ ++ ++#define PKTCMC 2 ++struct pktc_data { ++ void *chead; /* chain head */ ++ void *ctail; /* chain tail */ ++ uint8 *h_da; /* pointer to da of chain head */ ++ uint8 *h_sa; /* pointer to sa of chain head */ ++ uint8 h_prio; /* prio of chain head */ ++}; ++typedef struct pktc_data pktc_data_t; ++#else /* PKTC */ ++#define PKTC_ENAB(et) 0 ++#define PKT_CHAINABLE(et, p, evh, h_sa, h_da, h_prio) 0 ++#endif /* PKTC */ ++ ++static char bcm5301x_gmac0_string[] = "bcmiproc-gmac0"; ++static char bcm5301x_gmac1_string[] = "bcmiproc-gmac1"; ++static char bcm5301x_gmac2_string[] = "bcmiproc-gmac2"; ++static char bcm5301x_gmac3_string[] = "bcmiproc-gmac3"; ++ ++#ifdef GMAC_RATE_LIMITING ++static int et_rx_rate_limit = 0; ++extern void etc_check_rate_limiting(etc_info_t *etc, void *pch); ++#endif /* GMAC_RATE_LIMITING */ ++extern int nvram_env_gmac_name(int gmac, char *name); ++ ++#if defined(CONFIG_IPROC_FA) ++extern int fc_receive(struct sk_buff *skb_p); ++extern int fc_transmit(struct sk_buff *skb_p); ++#else ++#define fc_receive(arg) {} ++#define fc_transmit(arg) {} ++#endif /* defined(CONFIG_IPROC_FA) */ ++ ++#if defined(CONFIG_IPROC_FA2) ++extern int fa2_receive(struct sk_buff *skb_p); ++extern int fa2_transmit(struct sk_buff *skb_p, struct fa2_pkt_info *pkt_info); ++extern int fa2_get_packet_info(struct sk_buff *skb, struct fa2_pkt_info *info); ++extern int fa2_modify_header(struct sk_buff *skb); ++ ++#else ++#define fa2_receive(arg) {} ++#define fa2_transmit(arg) {} ++#endif /* defined(CONFIG_IPROC_FA2) */ ++ ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++extern int gmac_has_mdio_access(void); ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++/* In 2.6.20 kernels work functions get passed a pointer to the ++ * struct work, so things will continue to work as long as the work ++ * structure is the first component of the task structure. ++ */ ++typedef struct et_task { ++ struct work_struct work; ++ void *context; ++} et_task_t; ++ ++typedef struct et_info { ++ etc_info_t *etc; /* pointer to common os-independent data */ ++ struct net_device *dev; /* backpoint to device */ ++ struct pci_dev *pdev; /* backpoint to pci_dev */ ++ void *osh; /* pointer to os handle */ ++#ifdef GMAC3 ++ struct fwder *fwdh; /* pointer to my upstream forwarder handle */ ++#endif /* GMAC3 */ ++#ifdef HNDCTF ++ ctf_t *cih; /* ctf instance handle */ ++ ctf_brc_hot_t *brc_hot; /* hot bridge cache entry */ ++#endif ++ struct semaphore sem; /* use semaphore to allow sleep */ ++ spinlock_t lock; /* per-device perimeter lock */ ++ spinlock_t txq_lock; /* lock for txq protection */ ++ spinlock_t tx_lock; /* lock for tx protection */ ++ spinlock_t isr_lock; /* lock for irq reentrancy protection */ ++ struct sk_buff_head txq[NUMTXQ]; /* send queue */ ++ void *regsva; /* opaque chip registers virtual address */ ++ struct timer_list timer; /* one second watchdog timer */ ++ bool set; /* indicate the timer is set or not */ ++ struct net_device_stats stats; /* stat counter reporting structure */ ++ int events; /* bit channel between isr and dpc */ ++ struct et_info *next; /* pointer to next et_info_t in chain */ ++#ifdef NAPI2_POLL ++ struct napi_struct napi_poll; ++#endif /* NAPI2_POLL */ ++#ifndef NAPI_POLL ++ struct tasklet_struct tasklet; /* dpc tasklet */ ++#endif /* NAPI_POLL */ ++#ifdef ET_ALL_PASSIVE ++ et_task_t dpc_task; /* work queue for rx dpc */ ++ et_task_t txq_task; /* work queue for tx frames */ ++ bool all_dispatch_mode; /* dispatch mode: tasklets or passive */ ++#endif /* ET_ALL_PASSIVE */ ++ bool resched; /* dpc was rescheduled */ ++#ifdef CONFIG_IPROC_2STAGE_RX ++ bool rxinisr; ++#endif /* CONFIG_IPROC_2STAGE_RX */ ++} et_info_t; ++ ++static int et_found = 0; ++static et_info_t *et_list = NULL; ++ ++/* defines */ ++#define DATAHIWAT 1000 /* data msg txq hiwat mark */ ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 37) ++#define init_MUTEX(x) sema_init(x,1) ++#endif ++ ++ ++#ifndef HAVE_NETDEV_PRIV ++#define HAVE_NETDEV_PRIV ++#define netdev_priv(dev) ((dev)->priv) ++#define ET_INFO(dev) (et_info_t *)((dev)->priv) ++#else ++#define ET_INFO(dev) netdev_priv(dev) ++#endif /* HAVE_NETDEV_PRIV */ ++ ++ ++#define ET_LOCK(et) \ ++do { \ ++ if (ET_ALL_PASSIVE_ENAB(et)) \ ++ down(&(et)->sem); \ ++ else \ ++ spin_lock_bh(&(et)->lock); \ ++} while (0) ++ ++#define ET_UNLOCK(et) \ ++do { \ ++ if (ET_ALL_PASSIVE_ENAB(et)) \ ++ up(&(et)->sem); \ ++ else \ ++ spin_unlock_bh(&(et)->lock); \ ++} while (0) ++ ++#define ET_TXQ_LOCK(et) spin_lock_bh(&(et)->txq_lock) ++#define ET_TXQ_UNLOCK(et) spin_unlock_bh(&(et)->txq_lock) ++ ++#define ET_TX_LOCK(et) spin_lock_bh(&(et)->tx_lock) ++#define ET_TX_UNLOCK(et) spin_unlock_bh(&(et)->tx_lock) ++ ++#define INT_LOCK(et, flags) spin_lock_irqsave(&(et)->isr_lock, flags) ++#define INT_UNLOCK(et, flags) spin_unlock_irqrestore(&(et)->isr_lock, flags) ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5) ++#error Linux version must be newer than 2.4.5 ++#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5) */ ++ ++/* linux 2.4 doesn't have in_atomic */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) ++#define in_atomic() 0 ++#endif ++ ++/* prototypes called by etc.c */ ++void et_init(et_info_t *et, uint options); ++void et_reset(et_info_t *et); ++void et_link_up(et_info_t *et); ++void et_link_down(et_info_t *et); ++bool et_is_link_down(et_info_t *et); ++void et_up(et_info_t *et); ++void et_down(et_info_t *et, int reset); ++void et_dump(et_info_t *et, struct bcmstrbuf *b); ++#ifdef HNDCTF ++void et_dump_ctf(et_info_t *et, struct bcmstrbuf *b); ++#endif ++ ++/* local prototypes */ ++static void et_free(et_info_t *et); ++static int et_open(struct net_device *dev); ++static int et_close(struct net_device *dev); ++static int et_start(struct sk_buff *skb, struct net_device *dev); ++static void et_sendnext(et_info_t *et); ++static struct net_device_stats *et_get_stats(struct net_device *dev); ++static int et_set_mac_address(struct net_device *dev, void *addr); ++static void et_set_multicast_list(struct net_device *dev); ++static void _et_watchdog(struct net_device *data); ++static void et_watchdog(ulong data); ++#ifdef ET_ALL_PASSIVE ++static void et_watchdog_task(et_task_t *task); ++#endif /* ET_ALL_PASSIVE */ ++static int et_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) ++static irqreturn_t et_isr(int irq, void *dev_id); ++#else ++static irqreturn_t et_isr(int irq, void *dev_id, struct pt_regs *ptregs); ++#endif ++#ifdef NAPI2_POLL ++static int et_poll(struct napi_struct *napi, int budget); ++#elif defined(NAPI_POLL) ++static int et_poll(struct net_device *dev, int *budget); ++#else /* ! NAPI_POLL */ ++static void et_dpc(ulong data); ++#endif /* NAPI_POLL */ ++#ifdef ET_ALL_PASSIVE ++static void et_dpc_work(struct et_task *task); ++static void et_txq_work(struct et_task *task); ++static int et_schedule_task(et_info_t *et, void (*fn)(struct et_task *task), void *context); ++#endif /* ET_ALL_PASSIVE */ ++static void et_sendup(et_info_t *et, struct sk_buff *skb); ++static void et_dumpet(et_info_t *et, struct bcmstrbuf *b); ++ ++static int et_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd); ++static int et_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd); ++static void et_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++static const struct ethtool_ops et_ethtool_ops = ++{ ++ .get_settings = et_get_settings, ++ .set_settings = et_set_settings, ++ .get_drvinfo = et_get_driver_info, ++}; ++#endif ++ ++static int bcm5301x_gmac_probe(struct platform_device*); ++static int __exit bcm5301x_gmac_remove(struct platform_device*); ++static int __init bcm5301x_gmac_init_module(void); ++static void __exit bcm5301x_gmac_cleanup_module(void); ++#ifdef CONFIG_PM ++static int bcm5301x_gmac_drv_suspend(struct platform_device *pdev, pm_message_t state); ++static int bcm5301x_gmac_drv_resume(struct platform_device *pdev); ++#endif ++static void bcm5301x_gmac_release (struct device *dev); ++#if 0 //dgb /* Functions related to PROC file system support */ ++static int get_debug_level(char *page, char **start, off_t off, int count, int *eof, void *data); ++static int set_debug_level(struct file *file, const char *buffer, unsigned long count, void *data); ++#define MIN_DEBUG_LEVEL 0 ++#define MAX_DEBUG_LEVEL 3 ++static int cur_dbg_lvl = MIN_DEBUG_LEVEL; ++ ++#endif ++static int eth_mac_proc_create(struct net_device *dev ); ++static void eth_mac_proc_remove(void); ++#if (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD)) ++static et_info_t *et_get_eth3_info(void); ++#endif ++static int et_rxevent(osl_t *osh, et_info_t *et, struct chops *chops, void *ch, int quota); ++ ++#define DISABLE_FA_BYPASS 0 ++#define ENABLE_FA_BYPASS 1 ++static unsigned int gBypass = DISABLE_FA_BYPASS; ++ ++#ifdef HAVE_NET_DEVICE_OPS ++static const struct net_device_ops et_netdev_ops = { ++ .ndo_open = et_open, ++ .ndo_stop = et_close, ++ .ndo_start_xmit = et_start, ++ .ndo_get_stats = et_get_stats, ++ .ndo_set_mac_address = et_set_mac_address, ++ .ndo_set_rx_mode = et_set_multicast_list, ++ .ndo_do_ioctl = et_ioctl, ++}; ++#endif /*HAVE_NET_DEVICE_OPS*/ ++ ++static struct resource bcm5301x_gmac0_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IPROC_GMAC0_INT, ++ }, ++ [1] = { ++ .flags = IORESOURCE_MEM, ++ .start = IPROC_GMAC0_REG_BASE, ++ .end = IPROC_GMAC0_REG_BASE+0xbff, ++ }, ++}; ++static struct resource bcm5301x_gmac1_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IPROC_GMAC1_INT, ++ }, ++ [1] = { ++ .flags = IORESOURCE_MEM, ++ .start = IPROC_GMAC1_REG_BASE, ++ .end = IPROC_GMAC1_REG_BASE+0xbff, ++ }, ++}; ++static struct resource bcm5301x_gmac2_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IPROC_GMAC2_INT, ++ }, ++ [1] = { ++ .flags = IORESOURCE_MEM, ++ .start = IPROC_GMAC2_REG_BASE, ++ .end = IPROC_GMAC2_REG_BASE+0xbff, ++ }, ++}; ++static struct resource bcm5301x_gmac3_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IPROC_GMAC3_INT, ++ }, ++ [1] = { ++ .flags = IORESOURCE_MEM, ++ .start = IPROC_GMAC3_REG_BASE, ++ .end = IPROC_GMAC3_REG_BASE+0xbff, ++ }, ++}; ++ ++#if defined(BCMDBG) ++static uint32 msglevel = 0xdeadbeef; ++module_param(msglevel, uint, 0644); ++#endif /* defined(BCMDBG) */ ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++static bool brcm_tag=true; ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ ++#ifdef ET_ALL_PASSIVE ++/* passive mode: 1: enable, 0: disable */ ++static int passivemode = 0; ++module_param(passivemode, int, 0); ++#endif /* ET_ALL_PASSIVE */ ++#ifdef ET_LIMIT_TXQ ++#define ET_TXQ_THRESH 0 ++static int et_txq_thresh = ET_TXQ_THRESH; ++module_param(et_txq_thresh, int, 0); ++#endif /* ET_LIMIT_TXQ */ ++ ++#ifdef HNDCTF ++//int32 ctf_init(void); ++void ctf_exit(void); ++ ++static void ++et_ctf_detach(ctf_t *ci, void *arg) ++{ ++ et_info_t *et = (et_info_t *)arg; ++ ++ et->cih = NULL; ++ ++#ifdef CTFPOOL ++ /* free the buffers in fast pool */ ++ osl_ctfpool_cleanup(et->osh); ++#endif /* CTFPOOL */ ++ ++ return; ++} ++#endif /* HNDCTF */ ++ ++static bool ++et_ctf_active(et_info_t *et) ++{ ++ bool retval=false; ++#if defined(CONFIG_IPROC_FA) ++ if (brcm_tag == true) { ++ if (et->etc->unit == 2) { ++ retval = true; ++ } ++ } ++#elif defined(CONFIG_MACH_NSP) ++ if (et->etc->unit == 2 || et->etc->unit == 3) { ++ retval = true; ++ } ++#endif /* defined(CONFIG_IPROC_FA) */ ++ ++ return retval; ++} ++ ++static bool ++et_ctf_pipeline_loopback(et_info_t *et) ++{ ++ if (et->etc->unit == 3) { ++ return true; ++ } else { ++ return false; ++ } ++} ++ ++static int ++et_bcmtag_len(et_info_t *et) ++{ ++ if (et_ctf_pipeline_loopback(et)) ++ return 8; ++ if (et_ctf_active(et)) ++ return 4; ++ return 0; ++} ++ ++void *et_get_hndl(uint unit) ++{ ++ et_info_t *listptr; ++ void *roboptr; ++ ++ roboptr = NULL; ++ ++ for (listptr = et_list; listptr; listptr = listptr->next) { ++ if (listptr->etc->unit == unit) { ++ roboptr = listptr->etc->robo; ++ break; ++ } ++ } ++ ++ return roboptr; ++} ++ ++static void ++et_free(et_info_t *et) ++{ ++ et_info_t **prev; ++ osl_t *osh; ++ ++ if (et == NULL) ++ return; ++ ++ ET_TRACE(("et: et_free\n")); ++ ++ if (et->dev && et->dev->irq) ++ free_irq(et->dev->irq, et); ++ ++#ifdef NAPI2_POLL ++ napi_disable(&et->napi_poll); ++ netif_napi_del(&et->napi_poll); ++#endif /* NAPI2_POLL */ ++ ++#ifdef HNDCTF ++ if (et->cih) ++ ctf_dev_unregister(et->cih, et->dev); ++#endif /* HNDCTF */ ++ ++ if (et->dev) { ++ unregister_netdev(et->dev); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ free_netdev(et->dev); ++#else ++ MFREE(et->osh, et->dev, sizeof(struct net_device)); ++#endif ++ et->dev = NULL; ++ } ++ ++#ifdef CTFPOOL ++ /* free the buffers in fast pool */ ++ osl_ctfpool_cleanup(et->osh); ++#endif /* CTFPOOL */ ++ ++#ifdef HNDCTF ++ /* free ctf resources */ ++ if (et->cih) ++ ctf_detach(et->cih); ++#endif /* HNDCTF */ ++ ++ /* free common resources */ ++ if (et->etc) { ++ etc_detach(et->etc); ++ et->etc = NULL; ++ } ++ ++ /* ++ * unregister_netdev() calls get_stats() which may read chip registers ++ * so we cannot unmap the chip registers until after calling unregister_netdev() . ++ */ ++ if (et->regsva) { ++ iounmap((void *)et->regsva); ++ et->regsva = NULL; ++ } ++ ++ /* remove us from the global linked list */ ++ for (prev = &et_list; *prev; prev = &(*prev)->next) ++ if (*prev == et) { ++ *prev = et->next; ++ break; ++ } ++ ++ osh = et->osh; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++ free_netdev(et->dev); ++ et->dev = NULL; ++#else ++ MFREE(et->osh, et, sizeof(et_info_t)); ++#endif ++ ++ if (MALLOCED(osh)) { ++ ET_ERROR(("Memory leak of bytes %d\n", MALLOCED(osh))); ++ } ++ ASSERT(MALLOCED(osh) == 0); ++ ++ osl_detach(osh); ++} ++ ++static int ++et_open(struct net_device *dev) ++{ ++ et_info_t *et; ++ ++ et = ET_INFO(dev); ++ ++ ET_TRACE(("et%d: et_open\n", et->etc->unit)); ++ ++ et->etc->promisc = (dev->flags & IFF_PROMISC)? TRUE: FALSE; ++ et->etc->allmulti = (dev->flags & IFF_ALLMULTI)? TRUE: et->etc->promisc; ++#ifdef GMAC_RATE_LIMITING ++ et->etc->rl_enabled = et_rx_rate_limit; ++#endif /* GMAC_RATE_LIMITING */ ++ ++ ET_LOCK(et); ++ et_up(et); ++ ET_UNLOCK(et); ++ ++ OLD_MOD_INC_USE_COUNT; ++ ++ return (0); ++} ++ ++static int ++et_close(struct net_device *dev) ++{ ++ et_info_t *et; ++ ++ et = ET_INFO(dev); ++ ++ ET_TRACE(("et%d: et_close\n", et->etc->unit)); ++ ++ et->etc->promisc = FALSE; ++ et->etc->allmulti = FALSE; ++ ++ ET_LOCK(et); ++ et_down(et, 1); ++ ET_UNLOCK(et); ++ ++ OLD_MOD_DEC_USE_COUNT; ++ ++ return (0); ++} ++ ++#if defined(BCMDMASGLISTOSL) ++/* ++ * Driver level checksum offload. This is being done so that we can advertise ++ * checksum offload support to Linux. ++ */ ++static void BCMFASTPATH_HOST ++et_cso(et_info_t *et, struct sk_buff *skb) ++{ ++ struct ethervlan_header *evh; ++ uint8 *th = skb_transport_header(skb); ++ uint16 thoff, eth_type, *check; ++ uint8 prot; ++ ++ ASSERT(!PKTISCTF(et->osh, skb)); ++ ++ evh = (struct ethervlan_header *)PKTDATA(et->osh, skb); ++ eth_type = ((evh->vlan_type == HTON16(ETHER_TYPE_8021Q)) ? ++ evh->ether_type : evh->vlan_type); ++ ++ /* tcp/udp checksum calculation */ ++ thoff = (th - skb->data); ++ if (eth_type == HTON16(ETHER_TYPE_IP)) { ++ struct iphdr *ih = ip_hdr(skb); ++ prot = ih->protocol; ++ ASSERT((prot == IP_PROT_TCP) || (prot == IP_PROT_UDP)); ++ check = (uint16 *)(th + ((prot == IP_PROT_UDP) ? ++ offsetof(struct udphdr, check) : offsetof(struct tcphdr, check))); ++ *check = 0; ++ skb->csum = skb_checksum(skb, thoff, skb->len - thoff, 0); ++ *check = csum_tcpudp_magic(ih->saddr, ih->daddr, ++ skb->len - thoff, prot, skb->csum); ++ } else if (eth_type == HTON16(ETHER_TYPE_IPV6)) { ++ struct ipv6hdr *ih = ipv6_hdr(skb); ++ prot = IPV6_PROT(ih); ++ ASSERT((prot == IP_PROT_TCP) || (prot == IP_PROT_UDP)); ++ check = (uint16 *)(th + ((prot == IP_PROT_UDP) ? ++ offsetof(struct udphdr, check) : offsetof(struct tcphdr, check))); ++ *check = 0; ++ skb->csum = skb_checksum(skb, thoff, skb->len - thoff, 0); ++ *check = csum_ipv6_magic(&ih->saddr, &ih->daddr, ++ skb->len - thoff, prot, skb->csum); ++ } else { ++ return; ++ } ++ ++ if ((*check == 0) && (prot == IP_PROT_UDP)) ++ *check = CSUM_MANGLED_0; ++} ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++#ifdef ET_ALL_PASSIVE ++/* Schedule a completion handler to run at safe time */ ++static int ++et_schedule_task(et_info_t *et, void (*fn)(struct et_task *task), void *context) ++{ ++ et_task_t *task; ++ ++ ET_TRACE(("et%d: et_schedule_task\n", et->etc->unit)); ++ ++ if (!(task = MALLOC(et->osh, sizeof(et_task_t)))) { ++ ET_ERROR(("et%d: et_schedule_task: out of memory, malloced %d bytes\n", ++ et->etc->unit, MALLOCED(et->osh))); ++ return -ENOMEM; ++ } ++ ++ MY_INIT_WORK(&task->work, (work_func_t)fn); ++ task->context = context; ++ ++ if (!schedule_work(&task->work)) { ++ ET_ERROR(("et%d: schedule_work() failed\n", et->etc->unit)); ++ MFREE(et->osh, task, sizeof(et_task_t)); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++static void BCMFASTPATH ++et_txq_work(struct et_task *task) ++{ ++ et_info_t *et = (et_info_t *)task->context; ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_LOCK(et); ++#endif /* !CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ et_sendnext(et); ++#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_UNLOCK(et); ++#endif /* !CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ return; ++} ++#endif /* ET_ALL_PASSIVE */ ++ ++#ifdef GMAC3 ++/* et_start counterpart (test performance of using a queue) */ ++static int BCMFASTPATH ++et_forward(struct sk_buff *skb, struct net_device *dev, int cnt) ++{ ++ et_info_t *et; ++ etc_info_t *etc; ++ void *p, *n; ++#ifdef PRINT_PKT ++ int i; ++#endif /* PRINT_PKT */ ++ ++ et = ET_INFO(dev); ++ etc = et->etc; ++ ++ /* BUZZZ_DPL1(ET_FORWARD, 3, etc->unit, (uint32)skb, cnt); */ ++ ET_TRACE(("et%d: et_forward\n", etc->unit)); ++ ET_LOG("et%d: et_forward", etc->unit, 0); ++ ++ ET_PRHDR("tx", (struct ether_header *)skb->data, skb->len, etc->unit); ++ ET_PRPKT("txpkt", skb->data, skb->len, etc->unit); ++ ++ //p = PKTFRMFORWARD(etc->osh, skb, cnt); ++ p = PKTFRMNATIVE(etc->osh, skb); ++ ASSERT(p != NULL); ++ ++ ET_TRACE(("%s: sdu %p chained %d chain sz %d next %p\n", ++ __FUNCTION__, p, PKTISCHAINED(p), PKTCCNT(p), PKTCLINK(p))); ++#ifdef PRINT_PKT ++ printk("et%d: %s len(0x%x) fwdpkt:", etc->unit, __FUNCTION__, skb->len); ++ for (i=0; ilen; i++) { ++ if ( (i % 16) == 0 ) ++ printk("\n"); ++ printk("%02x ", skb->data[i]); ++ } ++ printk("\n"); ++#endif /* PRINT_PKT */ ++ ++ /* ---------------------------------------- */ ++ /* ---------------------------------------- */ ++ ++ FOREACH_CHAINED_PKT(p, n) { ++ ++ PKTCLRCHAINED(et->osh, p); ++ if (n == NULL) ++ PKTCSETFLAG(p, 1); ++ (*etc->chops->tx)(etc->ch, p); ++ ++ etc->txframe++; ++ etc->txbyte += PKTLEN(et->osh, p); ++ } ++ /* BUZZZ_DPL2(ET_FORWARD_RTN, 0); */ ++ ++ return FWDER_SUCCESS; ++} ++#endif /* GMAC3 */ ++ ++ ++#if defined(BCMDMASGLISTOSL) ++/* ++ * Convert a non leaner packet to a linear packet ++ */ ++static int BCMFASTPATH ++et_convert2linear_skb(struct sk_buff *skb, et_info_t *et) ++{ ++ int copy_len, z; ++ unsigned char my_buff[100]; ++ unsigned char *to_buffer; ++ ++ if (skb_is_nonlinear(skb)) { ++ ++ copy_len = skb->data_len; ++ skb_header_pointer(skb, skb_headlen(skb), ++ skb->data_len, (void*)my_buff); ++ ++ /* Trim packet to only header, should make linear */ ++ if (__pskb_trim(skb, skb_headlen(skb))) { ++ ET_ERROR(("et%d: __pskb_trim() error\n", et->etc->unit)); ++ return -1; ++ } ++ ++ if (skb_is_nonlinear(skb)) { ++ ET_ERROR(("et%d: skb_is_nonlinear() error\n", et->etc->unit)); ++ return -1; ++ } else { ++ to_buffer = skb_put(skb, copy_len); ++ ++ for (z=0; z < copy_len; z++) { ++ to_buffer[z] = my_buff[z]; ++ } ++ } ++ } ++ return 0; ++} ++ ++ ++/* ++ * Calculate checksum ++ */ ++static int BCMFASTPATH ++et_linear_skb_cksum(struct sk_buff *skb, et_info_t *et, int brcmtag) ++{ ++ int ret; ++ void *usr_data; ++ int ip_hdr_len, ip_tot_len, tcp_hdr_len, udp_hdr_len, usr_data_len; ++ struct iphdr *iph = NULL; ++ int save_len; ++ int offset; ++ int brcm_tag_len, hdr_len, vlan_tag_len; ++ struct ethervlan_header *evh; ++ ++ brcm_tag_len=0; ++ if (brcmtag) { ++ brcm_tag_len = et_bcmtag_len(et); ++ } ++ evh = (struct ethervlan_header *)(skb->data+brcm_tag_len); ++ ++ iph = (struct iphdr *)skb->network_header; ++ ip_hdr_len = ip_hdr(skb)->ihl << 2; ++ ip_tot_len = ntohs(ip_hdr(skb)->tot_len); ++ tcp_hdr_len = tcp_hdr(skb)->doff << 2; ++ udp_hdr_len = 8; ++ vlan_tag_len = 0; ++ if (evh->vlan_type == HTON16(ETHER_TYPE_8021Q)) { ++ /* add in vlan tags */ ++ vlan_tag_len = 4; ++ } ++ ++ /* Generate IPv4 checksum */ ++ ret = skb_checksum_help(skb); ++ ++ // printk(" ip done: skb len=%d ip_checksum=%x ret=%x (csum=%x tcp_checksum=%x)\n", ++ // skb->len, iph->check, ret, skb->csum, tcp_hdr(skb)->check); ++ ++ /* mark checksum mode */ ++ /* - clear partial checksum */ ++ skb->ip_summed = CHECKSUM_NONE; ++ skb->csum = 0; ++ ++ hdr_len=0; ++ /* build csum for user data */ ++ if (iph->protocol == IPPROTO_TCP) { ++ usr_data = skb->network_header + ip_hdr_len + tcp_hdr_len; ++ usr_data_len = ip_tot_len - ip_hdr_len - tcp_hdr_len; ++ hdr_len = 20; ++ } else { ++ usr_data = skb->network_header + ip_hdr_len + udp_hdr_len; ++ usr_data_len = ip_tot_len - ip_hdr_len - udp_hdr_len; ++ hdr_len = 8; ++ } ++ ++ /* offset = 12-mac, 2-etype, 20-ip, x-bcm, (20-tcp or 8-udp), [4-vlan] */ ++ offset = 34 + brcm_tag_len + hdr_len + vlan_tag_len; ++ if (usr_data != ((skb->data)+offset)) { ++ printk("et%d: FIXME usr_data not expected %p vs %p\n", ++ et->etc->unit, skb->data+offset, usr_data); ++ } ++ ++ skb->csum = csum_partial(usr_data, usr_data_len, 0); ++ // printk(" csum prep: skb_data at %x=%x, skb_csum=%x \n", ++ // (skb->data + 58), *(skb->data + 58), skb->csum); ++ ++ /* save skb length */ ++ save_len = skb->len; ++ ++ /* adjust skb->len to inlcude TCP header and user data */ ++ /* - use ip_hdr.tot_len - ip_hdr_len */ ++ skb->len = ip_tot_len - ip_hdr_len; ++ ++ /* offset = 12-mac, 2-etype, 20-ip, x-bcm, [4-vlan] */ ++ offset = 34 + brcm_tag_len + vlan_tag_len; ++ if (skb->len != save_len-offset) { ++ printk("et%d: FIXME sdk_len not expected %d vs %d\n", ++ et->etc->unit, skb->len, save_len-offset); ++ } ++ ++ // printk(" tcp prep: socket=%x inet=%x \n", skb->sk, inet_sk(skb->sk)); ++ ++ if (iph->protocol == IPPROTO_TCP) { ++ /* Generate TCP checksum */ ++ tcp_hdr(skb)->check = 0; ++ tcp_v4_send_check(skb->sk, skb); ++ } else { ++ /* udp checksum optional */ ++ udp_hdr(skb)->check = 0; ++ } ++ ++ /* restore skb length */ ++ skb->len = save_len; ++ ++ // printk(" tcp done: checksum=%x\n", tcp_hdr(skb)->check); ++ ++ return 0; ++} ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++ ++/* ++ * Yeah, queueing the packets on a tx queue instead of throwing them ++ * directly into the descriptor ring in the case of dma is kinda lame, ++ * but this results in a unified transmit path for both dma and pio ++ * and localizes/simplifies the netif_*_queue semantics, too. ++ */ ++static int BCMFASTPATH ++et_start(struct sk_buff *skb, struct net_device *dev) ++{ ++ et_info_t *et; ++ uint32 q = 0; ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ int less68 = 0; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++#if (defined(CONFIG_IPROC_FA2_NAPT_BYPASS) || defined(BCMDMASGLISTOSL)) ++ struct iphdr *iph = NULL; ++#endif /* (defined(CONFIG_IPROC_FA2_NAPT_BYPASS) || defined(BCMDMASGLISTOSL)) */ ++#ifdef ET_LIMIT_TXQ ++ int qlen; ++#endif /* ET_LIMIT_TXQ */ ++ ++ et = ET_INFO(dev); ++ ++#if defined(BCMDMASGLISTOSL) ++ { ++ bool sw_cksum=true; ++ ++ if (!PKTSUMNEEDED(skb)) ++ sw_cksum=false; ++ ++ #if (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD)) ++ if (et->etc->unit == 2) ++ sw_cksum=false; ++ #endif /* (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD)) */ ++ ++ #if !defined(CONFIG_IPROC_FA2_CS_OFFLOAD) ++ /* can only update checksum once. */ ++ /* if checksum is updated later, don't do it here */ ++ iph = (struct iphdr *)skb->network_header; ++ if (((skb->len+et_bcmtag_len(et)) < MIN_PACKET_SIZE) && ++ ((iph->protocol == IPPROTO_TCP) || (iph->protocol == IPPROTO_UDP))) { ++ sw_cksum=false; ++ } ++ #endif /* !defined(CONFIG_IPROC_FA2_CS_OFFLOAD) */ ++ ++ if (sw_cksum) { ++ et_cso(et, skb); ++ } ++ } ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++ if (skb_is_nonlinear(skb)) ++ et->etc->txsgpkt++; ++ ++ if (skb->len > et->etc->txmaxlen) { ++ et->etc->txmaxlen = skb->len; ++ } ++ ++#if defined(CONFIG_MACH_NS) ++ if (ET_GMAC(et->etc) && (et->etc->qos)) ++ q = etc_up2tc(PKTPRIO(skb)); ++#endif /* defined(CONFIG_MACH_NS) */ ++ ++ ET_TRACE(("et%d: et_start: len %d\n", et->etc->unit, skb->len)); ++ ET_LOG("et%d: et_start: len %d", et->etc->unit, skb->len); ++ ++ et->etc->txfrm++; ++#ifdef ET_LIMIT_TXQ ++#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_TXQ_LOCK(et); ++#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ qlen = skb_queue_len(&et->txq[q]); ++#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_TXQ_UNLOCK(et); ++#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ if (qlen > et->etc->txqlen) ++ et->etc->txqlen = qlen; ++ if (et_txq_thresh && (qlen >= et_txq_thresh)) { ++ //PKTCFREE(et->osh, skb, TRUE); ++ //return 0; ++ et->etc->txfrmdropped++; ++ /* schedule work */ ++#ifdef ET_ALL_PASSIVE ++ if (ET_ALL_PASSIVE_ENAB(et)) { ++#ifdef CONFIG_BCM_IPROC_GMAC_TXONCPU1 ++ schedule_work_on(1, &et->txq_task.work); ++#else ++ schedule_work(&et->txq_task.work); ++#endif ++ } ++#endif /* ET_ALL_PASSIVE */ ++ return NETDEV_TX_BUSY; ++ } ++#endif /* ET_LIMIT_TXQ */ ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2) || defined(CONFIG_MACH_NSP)) ++ ++ if (et_ctf_pipeline_loopback(et)) { ++ int bcm_hdr_size = 8; /* type 3 */ ++ ++ /* add brcm tag; tag is locate at offset 0-3 */ ++ ET_TRACE(("et%d %s: headroom(0x%x)\n", et->etc->unit, __FUNCTION__, skb_headroom(skb))); ++ ET_TRACE(("et%d: NOT enough headroom for BRCM tag.\n", et->etc->unit)); ++ if (skb_headroom(skb) < bcm_hdr_size) { ++ struct sk_buff *sk_tmp = skb; ++ skb = skb_realloc_headroom(sk_tmp, bcm_hdr_size); ++ PKTCFREE(et->osh, sk_tmp, TRUE); ++ if (!skb) { ++ ET_ERROR(("et%d: Failed to realloc headroom for BRCM tag; NOT transmitting frame.\n", et->etc->unit)); ++ return 0; ++ } ++ } ++ ++ ET_TRACE(("Adding BRCM TAG\n")); ++ __skb_push(skb, bcm_hdr_size); ++ ++ /* insert egress hdr type 3*/ ++ skb->data[0] = 0x60; /* opcode b011 */ ++ skb->data[1] = 0x00; ++ skb->data[2] = 0x00; ++ skb->data[3] = 0x00; ++ skb->data[4] = 0x00; ++ skb->data[5] = 0x00; ++ skb->data[6] = 0x00; ++ skb->data[7] = 0x28; /* fwd to AXI1, proc by SPU */ ++ ++ if (skb->len < MIN_PACKET_SIZE) { ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ less68 = 1; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ ET_TRACE(("forcing skb->len (%d) to %d\n", skb->len, MIN_PACKET_SIZE)); ++ skb->len = MIN_PACKET_SIZE; ++ } ++ __pskb_trim(skb, skb->len); ++ ++ } else if (et_ctf_active(et)) { ++ int bcm_hdr_size = 4; ++ ++#if defined(CONFIG_IPROC_FA2_CS_OFFLOAD) ++ bcm_hdr_size = 8; ++#endif ++ /* add brcm tag; tag is located at offset 0-3 */ ++ ET_TRACE(("et%d %s: headroom(0x%x)\n", et->etc->unit, __FUNCTION__, skb_headroom(skb))); ++ if (skb_headroom(skb) < bcm_hdr_size) { ++ struct sk_buff *sk_tmp = skb; ++ ++ ET_TRACE(("et%d: NOT enough headroom for BRCM tag.\n", et->etc->unit)); ++ skb = skb_realloc_headroom(sk_tmp, bcm_hdr_size); ++ PKTCFREE(et->osh, sk_tmp, TRUE); ++ if (!skb) { ++ ET_ERROR(("et%d: Failed to realloc headroom for BRCM tag; NOT transmitting frame.\n", et->etc->unit)); ++ return 0; ++ } ++ } ++ ++ ET_TRACE(("Adding BRCM TAG\n")); ++ __skb_push(skb, 4); ++ ++ /* insert ingress hdr type 0*/ ++ skb->data[0] = 0x00; ++ skb->data[1] = 0x00; ++ skb->data[2] = 0x00; ++ skb->data[3] = 0x00; ++ ++#if (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD) && \ ++ defined(CONFIG_IPROC_FA2_CS_OFFLOAD_SMALL_PKT_WA)) ++ if (skb->len < MIN_PACKET_SIZE) { ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ less68 = 1; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) { ++ int ret; ++ ret = skb_checksum_help(skb); ++ if (ret) { ++ ET_ERROR(("et%d: skb_checksum_help() returned error %d\n", et->etc->unit, ret)); ++ } ++ } ++ } ++#endif ++ ++#if defined(BCMDMASGLISTOSL) ++ iph = (struct iphdr *)skb->network_header; ++ if ((skb->len < MIN_PACKET_SIZE) && ++ ((iph->protocol == IPPROTO_TCP) || (iph->protocol == IPPROTO_UDP))) { ++ /* convert nonlinear SKB to linear */ ++ et_convert2linear_skb(skb, et); ++ if (skb->sk) { ++ /* if socket - calculate checksum */ ++ et_linear_skb_cksum(skb, et, 1); ++ } ++ } ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++ if (skb->len < MIN_PACKET_SIZE) { ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ less68 = 1; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ ET_TRACE(("forcing skb->len (%d) to %d\n", skb->len, MIN_PACKET_SIZE)); ++ skb->len = MIN_PACKET_SIZE; ++ } ++ __pskb_trim(skb, skb->len); ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ iph = (struct iphdr *)skb->network_header; ++ if (!less68 &&((iph->protocol == IPPROTO_TCP) || (iph->protocol == IPPROTO_UDP))) { ++ fa2_modify_header(skb); ++ /* Send pkt to AXI1 */ ++ et = et_get_eth3_info(); ++ if (!et->etc->up) { ++ ET_ERROR(("et%d: eth3 not up, exit.\n", et->etc->unit)); ++ return 0; ++ } ++ } ++ goto send_packet; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ ++#if defined(CONFIG_IPROC_FA) ++ if(!gBypass) { ++ fc_transmit(skb); ++ } ++#endif /* defined(CONFIG_IPROC_FA) */ ++#if defined(CONFIG_IPROC_FA2) ++ if(!gBypass) { ++#if defined(CONFIG_IPROC_FA2_CS_OFFLOAD) ++ struct fa2_pkt_info pkt_info; ++ extern spinlock_t fa2_lock; ++ uint8_t p_op; ++ ++ //memset((void *)&pkt_info, 0x0, sizeof(pkt_info)); ++ /* Initialize pkt_info */ ++ pkt_info.mac = pkt_info.ipv4_or_ipv6 = pkt_info.tcp_or_udp = NULL; ++ ++ pkt_info.vlan_tag = pkt_info.vlan_tag_next = pkt_info.et_type = ++ pkt_info.eth_snapllc = pkt_info.need_hdr_bytes = ++ pkt_info.hdr_words[0] = pkt_info.hdr_words[1] = 0; ++ ++ pkt_info.proto = FA2_PROTO_NOT_SUPPORTED; ++ pkt_info.pkt_type = FA2_INVALID_PKT; ++ ++ spin_lock(&fa2_lock); ++ fa2_get_packet_info(skb, &pkt_info); ++ spin_unlock(&fa2_lock); ++ ++ /* Check if this packet can be processed by FA+ pipeline. ++ * If not, let the eth driver handle it. ++ * If yes, do fa+ processing ++ */ ++ if (pkt_info.proto != FA2_PROTO_NOT_SUPPORTED) { ++ if (pkt_info.pkt_type != FA2_FWD_PKT) { ++ ++ p_op = pkt_info.hdr_words[1] & FA2_BCMHDR_OP_3_PROC_OP; ++ ++ /* Check for proc_ops 0, 1, 2 and 5 */ ++ if ((p_op <= 0x2) || (p_op == 0x5)) { ++ ++ fa2_transmit(skb, &pkt_info); ++ } ++ } else { ++ fa2_transmit(skb, &pkt_info); ++ } ++#if defined(CONFIG_IPROC_FA2_CS_OFFLOAD_SMALL_PKT_WA) ++ if (pkt_info.pkt_type == FA2_LOCAL_SMALL_TX_PKT) { ++ fa2_transmit(skb, &pkt_info); ++ } ++#endif ++ } ++ ++ /* If the packet is a L4 packet, and it is _not_ a forwarded packet, ++ * then add bcm hdr 0x3 bytes ++ */ ++ if ((pkt_info.proto != FA2_PROTO_NOT_SUPPORTED) && ++ (pkt_info.pkt_type == FA2_LOCAL_TX_PKT)) { ++ ++ /* Add Broadcom header bytes (8 bytes). Note 4 bytes were ++ * 'push'ed earlier ++ */ ++ __skb_push(skb, 4); ++ *((uint32_t *)skb->data) = htonl(pkt_info.hdr_words[0]); ++ *((uint32_t *)skb->data + 1) = htonl(pkt_info.hdr_words[1]); ++ __pskb_trim(skb, skb->len); ++ ++ /* Send pkt to AXI1 */ ++ et = et_get_eth3_info(); ++ if (!et->etc->up) { ++ ET_ERROR(("et%d: eth3 not up, exit.\n", et->etc->unit)); ++ return 0; ++ } ++ } ++ ++ ++#else ++ fa2_transmit(skb, NULL); ++#endif ++ } ++#endif /* defined(CONFIG_IPROC_FA2) */ ++ } ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2) || defined(CONFIG_MACH_NSP)) */ ++ ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++send_packet: ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ ++ /* put it on the tx queue and call sendnext */ ++ ET_TXQ_LOCK(et); ++ __skb_queue_tail(&et->txq[q], skb); ++ et->etc->txq_state |= (1 << q); ++ ET_TXQ_UNLOCK(et); ++ ++ if (!ET_ALL_PASSIVE_ENAB(et)) { ++ ET_LOCK(et); ++ et_sendnext(et); ++ ET_UNLOCK(et); ++ } ++#ifdef ET_ALL_PASSIVE ++ else ++#ifdef CONFIG_BCM_IPROC_GMAC_TXONCPU1 ++ schedule_work_on(1, &et->txq_task.work); ++#else ++ schedule_work(&et->txq_task.work); ++#endif ++ ++#endif /* ET_ALL_PASSIVE */ ++ ++ ET_LOG("et%d: et_start ret\n", et->etc->unit, 0); ++ ++ return (0); ++} ++ ++static void BCMFASTPATH ++et_sendnext(et_info_t *et) ++{ ++ etc_info_t *etc; ++ struct sk_buff *skb; ++ void *p, *n; ++ uint32 priq = TX_Q0; ++#ifdef DMA ++ uint32 txavail; ++#endif ++#ifdef PRINT_PKT_SUM ++ int tagoff=12; ++#endif /* PRINT_PKT_SUM */ ++ ++#ifdef PRINT_PKT ++ int i; ++#endif /* PRINT_PKT */ ++ ++ etc = et->etc; ++ ++ ET_TRACE(("et%d: et_sendnext\n", etc->unit)); ++ ET_LOG("et%d: et_sendnext", etc->unit, 0); ++ ++ /* dequeue packets from highest priority queue and send */ ++ while (1) { ++ ET_TXQ_LOCK(et); ++ ++ if (etc->txq_state == 0) ++ break; ++ ++ priq = etc_priq(etc->txq_state); ++ ++ ET_TRACE(("et%d: txq_state %x priq %d txavail %d\n", ++ etc->unit, etc->txq_state, priq, ++ *(uint *)etc->txavail[priq])); ++ ++ if ((skb = skb_peek(&et->txq[priq])) == NULL) { ++ etc->txq_state &= ~(1 << priq); ++ ET_TXQ_UNLOCK(et); ++ continue; ++ } ++ ++#ifdef DMA ++ /* current highest priority dma queue is full */ ++ txavail = *(uint *)(etc->txavail[priq]); ++ if ((PKTISCHAINED(skb) && (txavail < PKTCCNT(skb))) || (txavail == 0)) ++#else /* DMA */ ++ if (etc->pioactive != NULL) ++#endif /* DMA */ ++ { ++ etc->txdmafull++; ++ break; ++ } ++ ++ skb = __skb_dequeue(&et->txq[priq]); ++ ++ ET_TXQ_UNLOCK(et); ++ ET_PRHDR("tx", (struct ether_header *)skb->data, skb->len, etc->unit); ++ ET_PRPKT("txpkt", skb->data, skb->len, etc->unit); ++ ++#ifdef PRINT_PKT_SUM ++ tagoff = 16; ++ printf("et%d: txpkt len(0x%x) tag:0x%02x%02x%02x%02x\n", etc->unit, skb->len, ++ skb->data[tagoff], skb->data[tagoff+1], skb->data[tagoff+2], skb->data[tagoff+3]); ++#endif /* PRINT_PKT_SUM */ ++#ifdef PRINT_PKT ++ printk("et%d: %s len(0x%x) txpkt:", etc->unit, __FUNCTION__, skb->len); ++ for (i=0; ilen; i++) { ++ if ( (i % 16) == 0 ) ++ printk("\n"); ++ printk("%02x ", skb->data[i]); ++ } ++ printk("\n"); ++#endif /* PRINT_PKT */ ++ /* convert the packet. */ ++ p = PKTFRMNATIVE(etc->osh, skb); ++ ASSERT(p != NULL); ++ ++ ET_TRACE(("%s: sdu %p chained %d chain sz %d next %p\n", ++ __FUNCTION__, p, PKTISCHAINED(p), PKTCCNT(p), PKTCLINK(p))); ++ ++ ET_TX_LOCK(et); ++ FOREACH_CHAINED_PKT(p, n) { ++ /* replicate vlan header contents from curr frame */ ++ if (n != NULL) { ++ uint8 *n_evh; ++ n_evh = PKTPUSH(et->osh, n, VLAN_TAG_LEN); ++ *(struct ethervlan_header *)n_evh = ++ *(struct ethervlan_header *)PKTDATA(et->osh, p); ++ } ++ (*etc->chops->tx)(etc->ch, p); ++#ifdef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_LOCK(et); ++#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ etc->txframe++; ++ etc->txbyte += PKTLEN(et->osh, p); ++#ifdef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_UNLOCK(et); ++#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ } ++ ET_TX_UNLOCK(et); ++ } ++ ++ /* no flow control when qos is enabled */ ++ if (!et->etc->qos) { ++ /* stop the queue whenever txq fills */ ++ if ((skb_queue_len(&et->txq[TX_Q0]) > DATAHIWAT) && !netif_queue_stopped(et->dev)) { ++ et->etc->txqstop++; ++ netif_stop_queue(et->dev); ++ } ++ else if (netif_queue_stopped(et->dev) && ++ (skb_queue_len(&et->txq[TX_Q0]) < (DATAHIWAT/2))) { ++ netif_wake_queue(et->dev); ++ } ++ } else { ++ /* drop the frame if corresponding prec txq len exceeds hiwat ++ * when qos is enabled. ++ */ ++ if ((priq != TC_NONE) && (skb_queue_len(&et->txq[priq]) > DATAHIWAT)) { ++ skb = __skb_dequeue(&et->txq[priq]); ++ PKTCFREE(et->osh, skb, TRUE); ++ ET_ERROR(("et%d: %s: txqlen %d\n", et->etc->unit, ++ __FUNCTION__, skb_queue_len(&et->txq[priq]))); ++ } ++ } ++ ++ ET_TXQ_UNLOCK(et); ++} ++ ++void ++et_init(et_info_t *et, uint options) ++{ ++ ET_TRACE(("et%d: et_init\n", et->etc->unit)); ++ ET_LOG("et%d: et_init", et->etc->unit, 0); ++ ++ etc_init(et->etc, options); ++} ++ ++ ++void ++et_reset(et_info_t *et) ++{ ++ ET_TRACE(("et%d: et_reset\n", et->etc->unit)); ++ ++ etc_reset(et->etc); ++ ++ /* zap any pending dpc interrupt bits */ ++ et->events = 0; ++ ++ /* dpc will not be rescheduled */ ++ et->resched = 0; ++} ++ ++void ++et_up(et_info_t *et) ++{ ++ etc_info_t *etc; ++ ++ etc = et->etc; ++ ++ if (etc->up) ++ return; ++ ++ ET_TRACE(("et%d: et_up\n", etc->unit)); ++ ++ etc_up(etc); ++ ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (et->set) { ++ /* This will happen if running watchdog to monitor mdio bus */ ++ /* and port not up */ ++ del_timer(&et->timer); ++ et->set = FALSE; ++ } ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++ /* schedule one second watchdog timer */ ++ et->timer.expires = jiffies + HZ; ++ mod_timer(&et->timer, et->timer.expires); ++ et->set=TRUE; ++ ++ netif_start_queue(et->dev); ++ ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) { ++ et->etc->pktc = TRUE; ++ ++ /* ++ * Attach my transmit handler to UPSTREAM fwder instance on core=unit ++ * wl# MAC -> wl_sendup -> et_forward -> et::GMAC# ++ * and get the DNSTREAM direction transmit handler for use in sendup. ++ * et_sendup/chain -> et->fwdh->start_xmit=wl_start -> wl# MAC ++ */ ++ et->fwdh = fwder_attach(et_forward, et->dev, et->etc->unit, FWD_UPSTREAM); ++ /* fwder_dump_all(); */ ++ } ++#endif /* GMAC3 */ ++} ++ ++void ++et_down(et_info_t *et, int reset) ++{ ++ etc_info_t *etc; ++ struct sk_buff *skb; ++ int32 i; ++ bool stoptmr = TRUE; ++ ++ etc = et->etc; ++ ++ ET_TRACE(("et%d: et_down\n", etc->unit)); ++ ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) { ++ et->fwdh = fwder_dettach(et->fwdh); ++ /* fwder_dump_all(); */ ++ } ++#endif /* GMAC3 */ ++ ++ netif_down(et->dev); ++ netif_stop_queue(et->dev); ++ ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (gmac_has_mdio_access()) { ++ /* we have mdio bus don't stop timer so we can continue to monitor */ ++ stoptmr = FALSE; ++ } ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++ if ( stoptmr ) { ++ /* stop watchdog timer */ ++ del_timer(&et->timer); ++ et->set = FALSE; ++ } ++ ++#ifdef GMAC_RATE_LIMITING ++ /* stop ratelimiting timer */ ++ del_timer(&et->etc->rl_timer); ++ et->etc->rl_set = FALSE; ++#endif /* GMAC_RATE_LIMITING */ ++ ++ etc_down(etc, reset); ++ ++ /* flush the txq(s) */ ++ for (i = 0; i < NUMTXQ; i++) ++ while ((skb = skb_dequeue(&et->txq[i]))) ++ PKTFREE(etc->osh, skb, TRUE); ++ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ /* kill dpc */ ++ ET_UNLOCK(et); ++ tasklet_kill(&et->tasklet); ++ ET_LOCK(et); ++#endif /* NAPI_POLL */ ++} ++ ++/* ++ * These are interrupt on/off entry points. Disable interrupts ++ * during interrupt state transition. ++ */ ++void ++et_intrson(et_info_t *et) ++{ ++ unsigned long flags; ++ INT_LOCK(et, flags); ++ (*et->etc->chops->intrson)(et->etc->ch); ++ INT_UNLOCK(et, flags); ++} ++ ++static void ++_et_watchdog(struct net_device *dev) ++{ ++ et_info_t *et; ++ ++ et = ET_INFO(dev); ++ ++ ET_LOCK(et); ++ ++ etc_watchdog(et->etc); ++ ++ if (et->set) { ++ /* reschedule one second watchdog timer */ ++ et->timer.expires = jiffies + HZ; ++ mod_timer(&et->timer, et->timer.expires); ++ } ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ /* this in case port when up then down before we released mdio */ ++ else if (gmac_has_mdio_access()) { ++ /* interface not up but we have mdio bus */ ++ /* reschedule one second watchdog timer */ ++ et->timer.expires = jiffies + HZ; ++ mod_timer(&et->timer, et->timer.expires); ++ et->set = TRUE; ++ } ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++#ifdef CTFPOOL ++ /* allocate and add a new skb to the pkt pool */ ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ if (CTF_ENAB(et->cih)) ++#endif /* !CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++ osl_ctfpool_replenish(et->osh, CTFPOOL_REFILL_THRESH); ++#endif /* CTFPOOL */ ++ ET_UNLOCK(et); ++} ++ ++#ifdef ET_ALL_PASSIVE ++static void ++et_watchdog_task(et_task_t *task) ++{ ++ et_info_t *et = ET_INFO((struct net_device *)task->context); ++ ++ _et_watchdog((struct net_device *)task->context); ++ MFREE(et->osh, task, sizeof(et_task_t)); ++} ++#endif /* ET_ALL_PASSIVE */ ++ ++static void ++et_watchdog(ulong data) ++{ ++ struct net_device *dev = (struct net_device *)data; ++#ifdef ET_ALL_PASSIVE ++ et_info_t *et = ET_INFO(dev); ++#endif /* ET_ALL_PASSIVE */ ++ ++ if (!ET_ALL_PASSIVE_ENAB(et)) ++ _et_watchdog(dev); ++#ifdef ET_ALL_PASSIVE ++ else ++ et_schedule_task(et, et_watchdog_task, dev); ++#endif /* ET_ALL_PASSIVE */ ++} ++ ++/* Rate limiting */ ++#ifdef GMAC_RATE_LIMITING ++static void et_release_congestion(ulong data) ++{ ++ struct net_device *dev = (struct net_device *)data; ++ et_info_t *et = ET_INFO(dev); ++ ++ if (!et) { ++ return; ++ } ++ if (et->etc->rl_stopping_broadcasts) { ++ //printf("et%d: %s: releasing broadcast packet congestion; dropped: 0x%x\n", et->etc->unit, __FUNCTION__, et->etc->rl_dropped_bc_packets); ++ et->etc->rl_stopping_broadcasts = 0; ++ /* clear the number of dropped broadcast packets */ ++ et->etc->rl_dropped_bc_packets = 0; ++ } ++ if (et->etc->rl_stopping_all_packets) { ++ //printf("et%d: %s: releasing all packet congestion; dropped: 0x%x\n", et->etc->unit, __FUNCTION__, et->etc->rl_dropped_all_packets); ++ et->etc->rl_stopping_all_packets = 0; ++ et->etc->rl_dropped_all_packets = 0; ++ } ++} ++#endif /* GMAC_RATE_LIMITING */ ++ ++ ++ ++static int ++et_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ++{ ++ et_info_t *et = ET_INFO(dev); ++ ++ ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | ++ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | ++ SUPPORTED_Autoneg | SUPPORTED_TP); ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ ecmd->supported |= SUPPORTED_1000baseT_Full | SUPPORTED_Pause; ++#endif ++#if defined(CONFIG_MACH_HR2) ++ ecmd->supported |= SUPPORTED_Pause; ++#endif ++ ++ ecmd->advertising = ADVERTISED_TP; ++ ecmd->advertising |= (et->etc->advertise & ADV_10HALF) ? ++ ADVERTISED_10baseT_Half : 0; ++ ecmd->advertising |= (et->etc->advertise & ADV_10FULL) ? ++ ADVERTISED_10baseT_Full : 0; ++ ecmd->advertising |= (et->etc->advertise & ADV_100HALF) ? ++ ADVERTISED_100baseT_Half : 0; ++ ecmd->advertising |= (et->etc->advertise & ADV_100FULL) ? ++ ADVERTISED_100baseT_Full : 0; ++ ecmd->advertising |= (et->etc->advertise2 & ADV_1000FULL) ? ++ ADVERTISED_1000baseT_Full : 0; ++ ecmd->advertising |= (et->etc->advertise2 & ADV_1000HALF) ? ++ ADVERTISED_1000baseT_Half : 0; ++ ecmd->advertising |= (et->etc->forcespeed == ET_AUTO) ? ++ ADVERTISED_Autoneg : 0; ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ ecmd->advertising |= ADVERTISED_Pause; ++#endif ++ if (et->etc->linkstate) { ++ ecmd->speed = (et->etc->speed == 1000) ? SPEED_1000 : ++ ((et->etc->speed == 100) ? SPEED_100 : SPEED_10); ++ ecmd->duplex = (et->etc->duplex == 1) ? DUPLEX_FULL : DUPLEX_HALF; ++ } else { ++ ecmd->speed = 0; ++ ecmd->duplex = 0; ++ } ++ ecmd->port = PORT_TP; ++ ecmd->phy_address = et->etc->phyaddr; ++ ecmd->transceiver = XCVR_INTERNAL; ++ ecmd->autoneg = (et->etc->forcespeed == ET_AUTO) ? AUTONEG_ENABLE : AUTONEG_DISABLE; ++ ecmd->maxtxpkt = 0; ++ ecmd->maxrxpkt = 0; ++ ++ return 0; ++} ++ ++static int ++et_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ++{ ++ int speed[2]; ++ ++ et_info_t *et = ET_INFO(dev); ++ ++ if (!capable(CAP_NET_ADMIN)) ++ return (-EPERM); ++ ++ if (ecmd->autoneg == AUTONEG_ENABLE) { ++ speed[0] = ET_AUTO; ++ speed[1] = ecmd->advertising; ++ } else if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF) ++ speed[0] = ET_10HALF; ++ else if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL) ++ speed[0] = ET_10FULL; ++ else if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_HALF) ++ speed[0] = ET_100HALF; ++ else if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL) ++ speed[0] = ET_100FULL; ++ else if (ecmd->speed == SPEED_1000 && ecmd->duplex == DUPLEX_FULL) ++ speed[0] = ET_1000FULL; ++ else ++ return (-EINVAL); ++ ++ return etc_ioctl(et->etc, ETCSPEED, speed); ++} ++ ++static void ++et_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info) ++{ ++ et_info_t *et = ET_INFO(dev); ++ bzero(info, sizeof(struct ethtool_drvinfo)); ++ info->cmd = ETHTOOL_GDRVINFO; ++ sprintf(info->driver, "et%d", et->etc->unit); ++ strncpy(info->version, EPI_VERSION_STR, sizeof(info->version)); ++ info->version[(sizeof(info->version))-1] = '\0'; ++} ++ ++#ifdef SIOCETHTOOL ++static int ++et_ethtool(et_info_t *et, struct ethtool_cmd *ecmd) ++{ ++ int ret = 0; ++ ++ ET_LOCK(et); ++ ++ switch (ecmd->cmd) { ++ case ETHTOOL_GSET: ++ ret = et_get_settings(et->dev, ecmd); ++ break; ++ case ETHTOOL_SSET: ++ ret = et_set_settings(et->dev, ecmd); ++ break; ++ case ETHTOOL_GDRVINFO: ++ et_get_driver_info(et->dev, (struct ethtool_drvinfo *)ecmd); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ ET_UNLOCK(et); ++ ++ return (ret); ++} ++#endif /* SIOCETHTOOL */ ++ ++static int ++et_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ et_info_t *et; ++ int error; ++ char *buf; ++ int size, ethtoolcmd; ++ bool get = 0, set; ++ et_var_t *var = NULL; ++ void *buffer = NULL; ++ ++ et = ET_INFO(dev); ++ ++ ET_TRACE(("et%d: et_ioctl: cmd 0x%x\n", et->etc->unit, cmd)); ++ ++ switch (cmd) { ++#ifdef SIOCETHTOOL ++ case SIOCETHTOOL: ++ if (copy_from_user(ðtoolcmd, ifr->ifr_data, sizeof(uint32))) ++ return (-EFAULT); ++ ++ if (ethtoolcmd == ETHTOOL_GDRVINFO) ++ size = sizeof(struct ethtool_drvinfo); ++ else ++ size = sizeof(struct ethtool_cmd); ++ get = TRUE; set = TRUE; ++ break; ++#endif /* SIOCETHTOOL */ ++ case SIOCGETCDUMP: ++ size = IOCBUFSZ; ++ get = TRUE; set = FALSE; ++ break; ++ case SIOCGETCPHYRD: ++ case SIOCGETCPHYRD2: ++ case SIOCGETCROBORD: ++ size = sizeof(int) * 2; ++ get = TRUE; set = TRUE; ++ break; ++ case SIOCSETCSPEED: ++ case SIOCSETCPHYWR: ++ case SIOCSETCPHYWR2: ++ case SIOCSETCROBOWR: ++ size = sizeof(int) * 2; ++ get = FALSE; set = TRUE; ++ break; ++ case SIOCSETGETVAR: ++ size = sizeof(et_var_t); ++ set = TRUE; ++ break; ++ default: ++ size = sizeof(int); ++ get = FALSE; set = TRUE; ++ break; ++ } ++ ++ if ((buf = MALLOC(et->osh, size)) == NULL) { ++ ET_ERROR(("et: et_ioctl: out of memory, malloced %d bytes\n", MALLOCED(et->osh))); ++ return (-ENOMEM); ++ } ++ ++ if (set && copy_from_user(buf, ifr->ifr_data, size)) { ++ MFREE(et->osh, buf, size); ++ return (-EFAULT); ++ } ++ ++ if (cmd == SIOCSETGETVAR) { ++ var = (et_var_t *)buf; ++ if (var->buf) { ++ if (!var->set) ++ get = TRUE; ++ ++ if (!(buffer = (void *) MALLOC(et->osh, var->len))) { ++ ET_ERROR(("et: et_ioctl: out of memory, malloced %d bytes\n", ++ MALLOCED(et->osh))); ++ MFREE(et->osh, buf, size); ++ return (-ENOMEM); ++ } ++ ++ if (copy_from_user(buffer, var->buf, var->len)) { ++ MFREE(et->osh, buffer, var->len); ++ MFREE(et->osh, buf, size); ++ return (-EFAULT); ++ } ++ } ++ } ++ ++ switch (cmd) { ++#ifdef SIOCETHTOOL ++ case SIOCETHTOOL: ++ error = et_ethtool(et, (struct ethtool_cmd *)buf); ++ break; ++#endif /* SIOCETHTOOL */ ++ case SIOCSETGETVAR: ++ ET_LOCK(et); ++ error = etc_iovar(et->etc, var->cmd, var->set, buffer); ++ ET_UNLOCK(et); ++ if (!error && get) ++ error = copy_to_user(var->buf, buffer, var->len); ++ ++ if (buffer) ++ MFREE(et->osh, buffer, var->len); ++ break; ++ default: ++ ET_LOCK(et); ++ error = etc_ioctl(et->etc, cmd - SIOCSETCUP, buf) ? -EINVAL : 0; ++ ET_UNLOCK(et); ++ break; ++ } ++ ++ if (!error && get) ++ error = copy_to_user(ifr->ifr_data, buf, size); ++ ++ MFREE(et->osh, buf, size); ++ ++ return (error); ++} ++ ++static struct net_device_stats * ++et_get_stats(struct net_device *dev) ++{ ++ et_info_t *et; ++ etc_info_t *etc; ++ struct net_device_stats *stats; ++ int locked = 0; ++ ++ et = ET_INFO(dev); ++ ++ ET_TRACE(("et%d: et_get_stats\n", et->etc->unit)); ++ ++ if (!in_atomic()) { ++ locked = 1; ++ ET_LOCK(et); ++ } ++ ++ etc = et->etc; ++ stats = &et->stats; ++ bzero(stats, sizeof(struct net_device_stats)); ++ ++ /* refresh stats */ ++ if (et->etc->up) ++ (*etc->chops->statsupd)(etc->ch); ++ ++ /* SWAG */ ++ stats->rx_packets = etc->rxframe; ++ stats->tx_packets = etc->txframe; ++ stats->rx_bytes = etc->rxbyte; ++ stats->tx_bytes = etc->txbyte; ++ stats->rx_errors = etc->rxerror; ++ stats->tx_errors = etc->txerror; ++ ++ if (ET_GMAC(etc)) { ++ gmacmib_t *mib; ++ ++ mib = etc->mib; ++ stats->collisions = mib->tx_total_cols; ++ stats->rx_length_errors = (mib->rx_oversize_pkts + mib->rx_undersize); ++ stats->rx_crc_errors = mib->rx_crc_errs; ++ stats->rx_frame_errors = mib->rx_align_errs; ++ stats->rx_missed_errors = mib->rx_missed_pkts; ++ } else { ++ bcmenetmib_t *mib; ++ ++ mib = etc->mib; ++ stats->collisions = mib->tx_total_cols; ++ stats->rx_length_errors = (mib->rx_oversize_pkts + mib->rx_undersize); ++ stats->rx_crc_errors = mib->rx_crc_errs; ++ stats->rx_frame_errors = mib->rx_align_errs; ++ stats->rx_missed_errors = mib->rx_missed_pkts; ++ ++ } ++ ++ stats->rx_fifo_errors = etc->rxoflo; ++ stats->rx_over_errors = etc->rxoflo; ++ stats->tx_fifo_errors = etc->txuflo; ++ ++ //etc_robomib(etc); ++ ++ if (locked) ++ ET_UNLOCK(et); ++ ++ return (stats); ++} ++ ++static int ++et_set_mac_address(struct net_device *dev, void *addr) ++{ ++ et_info_t *et; ++ struct sockaddr *sa = (struct sockaddr *) addr; ++ ++ et = ET_INFO(dev); ++ ET_TRACE(("et%d: et_set_mac_address\n", et->etc->unit)); ++ ++ if (et->etc->up) ++ return -EBUSY; ++ ++ bcopy(sa->sa_data, dev->dev_addr, ETHER_ADDR_LEN); ++ bcopy(dev->dev_addr, &et->etc->cur_etheraddr, ETHER_ADDR_LEN); ++ ++ return 0; ++} ++ ++static void ++et_set_multicast_list(struct net_device *dev) ++{ ++ et_info_t *et; ++ etc_info_t *etc; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ++ struct dev_mc_list *mclist; ++#else ++ struct netdev_hw_addr *ha ; ++#endif ++ int i; ++ int locked = 0; ++ ++ et = ET_INFO(dev); ++ etc = et->etc; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ++ mclist = NULL ; /* fend off warnings */ ++#else ++ ha = NULL ; ++#endif ++ ++ ET_TRACE(("et%d: et_set_multicast_list\n", etc->unit)); ++ ++ if (!in_atomic()) { ++ locked = 1; ++ ET_LOCK(et); ++ } ++ ++ if (etc->up) { ++ etc->promisc = (dev->flags & IFF_PROMISC)? TRUE: FALSE; ++ etc->allmulti = (dev->flags & IFF_ALLMULTI)? TRUE: etc->promisc; ++ ++ /* copy the list of multicasts into our private table */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ++ for (i = 0, mclist = dev->mc_list; mclist && (i < dev->mc_count); ++ i++, mclist = mclist->next) { ++ if (i >= MAXMULTILIST) { ++ etc->allmulti = TRUE; ++ i = 0; ++ break; ++ } ++ etc->multicast[i] = *((struct ether_addr *)mclist->dmi_addr); ++ } ++#else /* >= 2.6.36 */ ++ i = 0; ++ netdev_for_each_mc_addr(ha, dev) { ++ i ++; ++ if (i >= MAXMULTILIST) { ++ etc->allmulti = TRUE; ++ i = 0; ++ break; ++ } ++ etc->multicast[i] = *((struct ether_addr *)ha->addr); ++ } /* for each ha */ ++#endif /* LINUX_VERSION_CODE */ ++ etc->nmulticast = i; ++ ++ /* LR: partial re-init, DMA is already initialized */ ++ et_init(et, ET_INIT_INTRON); ++ } ++ ++ if (locked) ++ ET_UNLOCK(et); ++} ++ ++#ifdef CONFIG_BCM_GRO_ENABLE ++void et_flush(void *dev_id) ++{ ++ et_info_t *et; ++ struct chops *chops; ++ void *ch; ++ osl_t *osh; ++ ++ et = (et_info_t *)dev_id; ++ chops = et->etc->chops; ++ ch = et->etc->ch; ++ osh = et->etc->osh; ++ ++ /* guard against shared interrupts */ ++ if (!et->etc->up) { ++ ET_TRACE(("et%d: et_isr: not up\n", et->etc->unit)); ++ return; ++ } ++ if (!et->napi_poll.gro_list) { ++ return; ++ } ++ /* disable interrupts */ ++ (*chops->intrsoff)(ch); ++ ++ et->resched = TRUE; ++ ++ napi_gro_flush(&et->napi_poll); ++ ++ /* enable interrupts now */ ++ (*chops->intrson)(ch); ++} ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) ++static irqreturn_t BCMFASTPATH ++et_isr(int irq, void *dev_id) ++#else ++static irqreturn_t BCMFASTPATH ++et_isr(int irq, void *dev_id, struct pt_regs *ptregs) ++#endif ++{ ++ et_info_t *et; ++ struct chops *chops; ++ void *ch; ++ uint events = 0; ++ osl_t *osh; ++ ++ et = (et_info_t *)dev_id; ++ chops = et->etc->chops; ++ ch = et->etc->ch; ++ osh = et->etc->osh; ++ ++ /* guard against shared interrupts */ ++ if (!et->etc->up) { ++ ET_TRACE(("et%d: et_isr: not up\n", et->etc->unit)); ++ goto done; ++ } ++ ++ /* get interrupt condition bits */ ++ events = (*chops->getintrevents)(ch, TRUE); ++ ++ /* not for us */ ++ if (!(events & INTR_NEW)) ++ goto done; ++ ++ ET_TRACE(("et%d: et_isr: events 0x%x\n", et->etc->unit, events)); ++ ET_LOG("et%d: et_isr: events 0x%x", et->etc->unit, events); ++ ++#ifdef CONFIG_IPROC_2STAGE_RX ++ if (events & INTR_RX) { ++ et->rxinisr = true; ++ /* process a few RX interrupts */ ++ et_rxevent(osh, et, chops, ch, 1); ++ ++ et->rxinisr = false; ++ /* get interrupt condition bits */ ++ events = (*chops->getintrevents)(ch, TRUE); ++ et->resched = FALSE; ++ ++ /* not for us */ ++ if (!(events & INTR_NEW)) ++ goto done; ++ } ++#endif /* CONFIG_IPROC_2STAGE_RX */ ++ ++ /* disable interrupts */ ++ (*chops->intrsoff)(ch); ++ ++ /* save intstatus bits */ ++ ASSERT(et->events == 0); ++ et->events = events; ++ ++ ASSERT(et->resched == FALSE); ++ ++#ifdef NAPI2_POLL ++ ++ napi_schedule(&et->napi_poll); ++ ++#elif defined(NAPI_POLL) ++ /* allow the device to be added to the cpu polling list if we are up */ ++ if (netif_rx_schedule_prep(et->dev)) { ++ /* tell the network core that we have packets to send up */ ++ __netif_rx_schedule(et->dev); ++ } else { ++ ET_ERROR(("et%d: et_isr: intr while in poll!\n", ++ et->etc->unit)); ++ (*chops->intrson)(ch); ++ } ++#else /* ! NAPI_POLL && ! NAPI2_POLL */ ++ /* schedule dpc */ ++#ifdef ET_ALL_PASSIVE ++ if (ET_ALL_PASSIVE_ENAB(et)) { ++ schedule_work(&et->dpc_task.work); ++ } else ++#endif /* ET_ALL_PASSIVE */ ++ tasklet_schedule(&et->tasklet); ++#endif /* NAPI_POLL */ ++ ++done: ++ ET_LOG("et%d: et_isr ret", et->etc->unit, 0); ++ ++ return IRQ_RETVAL(events & INTR_NEW); ++} ++ ++#ifdef GMAC3 ++static struct net_device * BCMFASTPATH ++et_find_dev(struct sk_buff *skb) { ++ ++ /* ----------------------------------------------- */ ++ /* ----------------------------------------------- */ ++ ++ return NULL; ++} ++#endif /* GMAC3 */ ++ ++#ifdef PKTC ++static void BCMFASTPATH ++et_sendup_chain(et_info_t *et, void *h) ++{ ++ struct sk_buff *skb; ++ uint sz = PKTCCNT(h); ++ ++ ASSERT(h != NULL); ++ ASSERT((sz > 0) && (sz <= PKTCBND)); ++ ET_TRACE(("et%d: %s: sending up packet chain of sz %d\n", ++ et->etc->unit, __FUNCTION__, sz)); ++ et->etc->chained += sz; ++ et->etc->currchainsz = sz; ++ et->etc->maxchainsz = MAX(et->etc->maxchainsz, sz); ++ ++#ifdef GMAC3 ++ /* Forward chain directly to wl transmit */ ++ if (DEV_FWDER(et->etc)) { ++ struct net_device * dev; ++ ++ //skb = PKTTOFORWARD(et->etc->osh, h, sz); ++ skb = PKTTONATIVE(et->etc->osh, h); ++ skb->dev = et->dev; ++ ++ dev = et_find_dev(skb); ++ ++ if (fwder_transmit(skb, dev, et->fwdh, sz) == FWDER_FAILURE) { ++ PKTCFREE(et->etc->osh, skb, FALSE); ++ } ++ } ++ else ++ ASSERT(DEV_NTKIF(et->etc)); ++#else /* !GMAC3 */ ++ ++ skb = PKTTONATIVE(et->etc->osh, h); ++ skb->dev = et->dev; ++ ++ /* send up the packet chain */ ++ ctf_forward(et->cih, h, et->dev); ++#endif /* !GMAC3 */ ++ ++} ++#endif /* PKTC */ ++ ++static inline int ++et_rxevent(osl_t *osh, et_info_t *et, struct chops *chops, void *ch, int quota) ++{ ++ uint processed = 0; ++ void *p, *h = NULL, *t = NULL; ++ struct sk_buff *skb; ++#ifdef PKTC ++ pktc_data_t cd[PKTCMC] = {{0}}; ++ uint8 *evh, prio; ++ int32 i = 0, cidx = 0; ++#ifdef GMAC3 ++ bool chaining = DEV_FWDER(et->etc); ++#else /* !GMAC3 */ ++ bool chaining = PKTC_ENAB(et); ++#endif /* !GMAC3 */ ++#endif ++ ++#ifdef GMAC_RATE_LIMITING ++ /* rate limiting */ ++ if ( et->etc->rl_enabled ) ++ etc_check_rate_limiting(et->etc, ch); ++#endif /* GMAC_RATE_LIMITING */ ++ ++ /* read the buffers first */ ++ while ((p = (*chops->rx)(ch))) { ++#ifdef PKTC ++ ASSERT(PKTCLINK(p) == NULL); ++ evh = PKTDATA(et->osh, p) + HWRXOFF; ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) ++ prio = IP_TOS46(evh + ETHER_HDR_LEN) >> IPV4_TOS_PREC_SHIFT; ++ else ++#endif /* GMAC3 */ ++ prio = IP_TOS46(evh + ETHERVLAN_HDR_LEN) >> IPV4_TOS_PREC_SHIFT; ++ if (cd[0].h_da == NULL) { ++ cd[0].h_da = evh; cd[0].h_sa = evh + ETHER_ADDR_LEN; ++ cd[0].h_prio = prio; ++ } ++ ++ /* if current frame doesn't match cached src/dest/prio or has err flags ++ * set then stop chaining. ++ */ ++ if (chaining) { ++ for (i = 0; i <= cidx; i++) { ++ if (PKT_CHAINABLE(et, p, evh, prio, cd[i].h_sa, ++ cd[i].h_da, cd[i].h_prio)) ++ break; ++ else if ((i + 1 < PKTCMC) && (cd[i + 1].h_da == NULL)) { ++ cidx++; ++ cd[cidx].h_da = evh; ++ cd[cidx].h_sa = evh + ETHER_ADDR_LEN; ++ cd[cidx].h_prio = prio; ++ } ++ } ++ chaining = (i < PKTCMC); ++ } ++ ++ if (chaining) { ++ PKTCENQTAIL(cd[i].chead, cd[i].ctail, p); ++ /* strip off rxhdr */ ++ PKTPULL(et->osh, p, HWRXOFF); ++ ++ et->etc->rxframe++; ++ et->etc->rxbyte += PKTLEN(et->osh, p); ++ ++ /* strip off crc32 */ ++ PKTSETLEN(et->osh, p, PKTLEN(et->osh, p) - ETHER_CRC_LEN); ++ ++#ifndef GMAC3 ++ /* update header for non-first frames */ ++ if (cd[i].chead != p) ++ CTF_HOTBRC_L2HDR_PREP(et->osh, et->brc_hot, prio, ++ PKTDATA(et->osh, p), p); ++#endif /* !GMAC3 */ ++ ++ PKTCINCRCNT(cd[i].chead); ++ PKTSETCHAINED(et->osh, p); ++ PKTCADDLEN(cd[i].chead, PKTLEN(et->osh, p)); ++ } else ++ PKTCENQTAIL(h, t, p); ++#else /* PKTC */ ++ PKTSETLINK(p, NULL); ++ if (t == NULL) ++ h = t = p; ++ else { ++ PKTSETLINK(t, p); ++ t = p; ++ } ++#endif /* PKTC */ ++ ++ /* we reached quota already */ ++ if (++processed >= quota) { ++ /* reschedule et_dpc()/et_poll() */ ++ et->resched = TRUE; ++ et->etc->rxquota++; ++ break; ++ } ++ } ++ ++ /* prefetch the headers */ ++ if (h != NULL) ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(PKTDATA(osh, h), SKB_DATA_PREFETCH_LEN); ++#else ++ ETPREFHDRS(PKTDATA(osh, h), PREFSZ); ++#endif ++ ++ /* post more rx bufs */ ++ (*chops->rxfill)(ch); ++ ++#ifdef PKTC ++ /* send up the chain(s) at one fell swoop */ ++ ASSERT(cidx < PKTCMC); ++ for (i = 0; i <= cidx; i++) { ++ if (cd[i].chead != NULL) { ++#ifdef GMAC3 ++ PKTSETPRIO(cd[i].chead, cd[i].h_prio); ++#endif ++ et_sendup_chain(et, cd[i].chead); ++ } ++ } ++#endif ++ ++ while ((p = h) != NULL) { ++#ifdef PKTC ++ h = PKTCLINK(h); ++ PKTSETCLINK(p, NULL); ++#else ++ h = PKTLINK(h); ++ PKTSETLINK(p, NULL); ++#endif ++ /* prefetch the headers */ ++ if (h != NULL) ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(PKTDATA(osh, h), SKB_DATA_PREFETCH_LEN); ++#else ++ ETPREFHDRS(PKTDATA(osh, h), PREFSZ); ++#endif ++ ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) { ++ uint8 *evh1; ++ //skb = PKTTOFORWARD(osh, p, 1); ++ skb = PKTTONATIVE(osh, p); ++ evh1 = skb->data + HWRXOFF; ++ skb->priority = IPV4_TOS(evh1 + ETHER_HDR_LEN) >> IPV4_TOS_PREC_SHIFT; ++ } else ++#endif ++ skb = PKTTONATIVE(osh, p); ++ et->etc->unchained++; ++ et_sendup(et, skb); ++ } ++ ++ return (processed); ++} ++ ++#if defined(NAPI2_POLL) ++static int BCMFASTPATH ++et_poll(struct napi_struct *napi, int budget) ++{ ++ int quota = budget; ++ struct net_device *dev = napi->dev; ++ et_info_t *et = ET_INFO(dev); ++ ++#elif defined(NAPI_POLL) ++static int BCMFASTPATH ++et_poll(struct net_device *dev, int *budget) ++{ ++ int quota = min(RXBND, *budget); ++ et_info_t *et = ET_INFO(dev); ++#else /* NAPI_POLL */ ++static void BCMFASTPATH ++et_dpc(ulong data) ++{ ++ et_info_t *et = (et_info_t *)data; ++ #ifndef GMAC3 ++ int quota = PKTC_ENAB(et) ? et->etc->pktcbnd : RXBND; ++ #else /* GMAC3 */ ++ int quota = PKTC_ENAB(et) ? et->etc->pktcbnd : RXBND; ++ #endif /* GMAC3 */ ++#endif /* NAPI_POLL */ ++ struct chops *chops; ++ void *ch; ++ osl_t *osh; ++ uint nrx = 0; ++ ++ chops = et->etc->chops; ++ ch = et->etc->ch; ++ osh = et->etc->osh; ++ ++ ET_TRACE(("et%d: et_dpc: events 0x%x\n", et->etc->unit, et->events)); ++ ET_LOG("et%d: et_dpc: events 0x%x", et->etc->unit, et->events); ++ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ ET_LOCK(et); ++#endif /* ! NAPIx_POLL */ ++ ++ if (!et->etc->up) ++ goto done; ++ ++ /* get interrupt condition bits again when dpc was rescheduled */ ++ if (et->resched) { ++ et->events = (*chops->getintrevents)(ch, FALSE); ++ et->resched = FALSE; ++ } ++ ++ if (et->events & INTR_RX) ++ nrx = et_rxevent(osh, et, chops, ch, quota); ++ ++ if (et->events & INTR_TX) { ++ (*chops->txreclaim)(ch, FALSE); ++ } ++ ++ (*chops->rxfill)(ch); ++ ++ /* handle error conditions, if reset required leave interrupts off! */ ++ if (et->events & INTR_ERROR) { ++ if ((*chops->errors)(ch)) { ++ printk("%s error, calling et_init() for et%d\n", __FUNCTION__, et->etc->unit); ++ et_init(et, ET_INIT_INTROFF); ++ } ++ else ++ if (nrx < quota) ++ nrx += et_rxevent(osh, et, chops, ch, quota); ++ } ++ ++ /* run the tx queue */ ++ if (et->etc->txq_state != 0) { ++ if (!ET_ALL_PASSIVE_ENAB(et)) { ++ et_sendnext(et); ++ } ++#ifdef ET_ALL_PASSIVE ++ else ++ #ifdef CONFIG_BCM_IPROC_GMAC_TXONCPU1 ++ schedule_work_on(1, &et->txq_task.work); ++ #else ++ schedule_work(&et->txq_task.work); ++ #endif ++ ++#endif /* ET_ALL_PASSIVE */ ++ } ++ ++ /* clear this before re-enabling interrupts */ ++ et->events = 0; ++ ++ /* something may bring the driver down */ ++ if (!et->etc->up) { ++ et->resched = FALSE; ++ goto done; ++ } ++ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ #ifdef ET_ALL_PASSIVE ++ if (et->resched) { ++ if (!ET_ALL_PASSIVE_ENAB(et)) ++ tasklet_schedule(&et->tasklet); ++ else ++ schedule_work(&et->dpc_task.work); ++ } ++ else ++ (*chops->intrson)(ch); ++ #else /* ET_ALL_PASSIVE */ ++ /* there may be frames left, reschedule et_dpc() */ ++ if (et->resched) ++ tasklet_schedule(&et->tasklet); ++ /* re-enable interrupts */ ++ else ++ (*chops->intrson)(ch); ++ #endif /* ET_ALL_PASSIVE */ ++#endif /* ! NAPIx_POLL */ ++ ++done: ++ ET_LOG("et%d: et_dpc ret", et->etc->unit, 0); ++ ++#if defined(NAPI_POLL) || defined(NAPI2_POLL) ++ #ifdef NAPI_POLL ++ /* update number of frames processed */ ++ *budget -= nrx; ++ dev->quota -= nrx; ++ ++ ET_TRACE(("et%d: et_poll: quota %d budget %d\n", ++ et->etc->unit, dev->quota, *budget)); ++ #else ++ ET_TRACE(("et%d: et_poll: budget %d\n", ++ et->etc->unit, budget)); ++ #endif ++ ++ /* we got packets but no quota */ ++ if (et->resched) ++ /* indicate that we are not done, don't enable ++ * interrupts yet. linux network core will call ++ * us again. ++ */ ++ return (1); ++ ++ #ifdef NAPI2_POLL ++ napi_complete(napi); ++ #else /* NAPI_POLL */ ++ netif_rx_complete(dev); ++ #endif ++ ++ /* enable interrupts now */ ++ (*chops->intrson)(ch); ++ ++ /* indicate that we are done */ ++ return (0); ++#else /* NAPI_POLL */ ++ ET_UNLOCK(et); ++ return; ++#endif /* NAPI_POLL */ ++} ++ ++#ifdef ET_ALL_PASSIVE ++static void BCMFASTPATH ++et_dpc_work(struct et_task *task) ++{ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ et_info_t *et = (et_info_t *)task->context; ++ et_dpc((unsigned long)et); ++#else ++ BUG_ON(1); ++#endif ++ return; ++} ++#endif /* ET_ALL_PASSIVE */ ++ ++static void ++et_error(et_info_t *et, struct sk_buff *skb, void *rxh) ++{ ++ uchar eabuf[32]; ++ struct ether_header *eh; ++ ++ eh = (struct ether_header *)skb->data; ++ bcm_ether_ntoa((struct ether_addr *)eh->ether_shost, eabuf); ++ ++ if (RXH_OVERSIZE(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: over size packet from %s\n", et->etc->unit, eabuf)); ++ } ++ if (RXH_CRC(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: crc error from %s\n", et->etc->unit, eabuf)); ++ } ++ if (RXH_OVF(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: fifo overflow\n", et->etc->unit)); ++ } ++ if (RXH_NO(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: crc error (odd nibbles) from %s\n", ++ et->etc->unit, eabuf)); ++ } ++ if (RXH_RXER(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: symbol error from %s\n", et->etc->unit, eabuf)); ++ } ++} ++ ++static inline int32 ++et_ctf_forward(et_info_t *et, struct sk_buff *skb) ++{ ++#ifdef HNDCTF ++ /* use slow path if ctf is disabled */ ++ if (!CTF_ENAB(et->cih)) ++ return (BCME_ERROR); ++ ++ /* try cut thru first */ ++ if (ctf_forward(et->cih, skb, skb->dev) != BCME_ERROR) ++ return (BCME_OK); ++ ++ /* clear skipct flag before sending up */ ++ PKTCLRSKIPCT(et->osh, skb); ++#endif /* HNDCTF */ ++ ++#ifdef CTFPOOL ++ /* allocate and add a new skb to the pkt pool */ ++ if (PKTISFAST(et->osh, skb)) ++ osl_ctfpool_add(et->osh); ++ ++ /* clear fast buf flag before sending up */ ++ PKTCLRFAST(et->osh, skb); ++ ++ /* re-init the hijacked field */ ++ CTFPOOLPTR(et->osh, skb) = NULL; ++#endif /* CTFPOOL */ ++ ++ /* map the unmapped buffer memory before sending up */ ++ PKTCTFMAP(et->osh, skb); ++ ++ return (BCME_ERROR); ++} ++ ++void BCMFASTPATH ++et_sendup(et_info_t *et, struct sk_buff *skb) ++{ ++ etc_info_t *etc; ++ void *rxh; ++ uint16 flags; ++#ifdef PRINT_PKT ++ int i; ++#endif /* PRINT_PKT */ ++#if defined(CONFIG_IPROC_FA2) ++ uint32 rcv_sts_word; ++#endif ++ ++ etc = et->etc; ++ ++ /* packet buffer starts with rxhdr */ ++ rxh = skb->data; ++ ++#if defined(CONFIG_IPROC_FA2) ++ rcv_sts_word = LTOH32(*((uint32 *)skb->data)); ++#endif ++ /* strip off rxhdr */ ++ __skb_pull(skb, HWRXOFF); ++ ++ ET_TRACE(("et%d: et_sendup: %d bytes\n", et->etc->unit, skb->len)); ++ ET_LOG("et%d: et_sendup: len %d", et->etc->unit, skb->len); ++ ++ etc->rxframe++; ++ etc->rxbyte += skb->len; ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2) || defined(CONFIG_MACH_NSP)) ++ if (et_ctf_active(et)) { ++#if defined(CONFIG_IPROC_FA) ++ if(!gBypass) { ++ if (fc_receive(skb) == -1) ++ goto err; ++ } ++#endif /* defined(CONFIG_IPROC_FA) */ ++ ++#if defined(CONFIG_IPROC_FA2) ++ if(!gBypass) { ++ ++ /* If pipeline did not indicate error, proceed with rx processing */ ++ if (!(RXH_CTFERROR(etc, rxh))) { ++ if (fa2_receive(skb) == FA2_PKT_DONE) { ++ goto drop_pkt; ++ } ++ } else { ++ /* ++ printk(KERN_DEBUG "\n=== rxstsword is 0x%08X\n", ++ rcv_sts_word); ++ */ ++ } ++ } ++#endif /* defined(CONFIG_IPROC_FA2) */ ++ ++ /* remove brcm tag */ ++ ET_TRACE(("Removing BRCM TAG\n")); ++ /* size depends on egress tag opcode */ ++ switch ((skb->data[0] & 0xe0) >> 5) { ++ case 0: ++ case 1: ++ case 2: ++ skb_pull(skb, 4); ++ break; ++ case 3: ++ skb_pull(skb, 8); ++ break; ++ } ++ } ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2) || defined(CONFIG_MACH_NSP)) */ ++ ++ /* eh should now be aligned 2-mod-4 */ ++ ASSERT(((ulong)skb->data & 3) == 2); ++ ++ /* strip off crc32 */ ++ __skb_trim(skb, skb->len - ETHER_CRC_LEN); ++ ++ ET_PRHDR("rx", (struct ether_header *)skb->data, skb->len, etc->unit); ++ ET_PRPKT("rxpkt", skb->data, skb->len, etc->unit); ++#ifdef PRINT_PKT_SUM ++ printk("et%d: rxpkt len(0x%x) tag:0x%02x%02x%02x%02x\n", etc->unit, skb->len, ++ skb->data[12], skb->data[13], skb->data[14], skb->data[15]); ++#endif /* PRINT_PKT_SUM */ ++#ifdef PRINT_PKT ++ printk("et%d: %s len(0x%x) rxpkt:", etc->unit, __FUNCTION__, skb->len); ++ for (i=0; ilen; i++) { ++ if ( (i % 16) == 0 ) ++ printk("\n"); ++ printk("%02x ", skb->data[i]); ++ } ++ printk("\n"); ++#endif /* PRINT_PKT */ ++ ++ /* get the error flags */ ++ flags = RXH_FLAGS(etc, rxh); ++ ++ /* check for reported frame errors */ ++ if (flags) ++ goto err; ++ ++ skb->dev = et->dev; ++ ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) { ++ struct net_device * dev = et_find_dev(skb); ++ ++ if (fwder_transmit(skb, dev, et->fwdh, 1) == FWDER_FAILURE) { ++ PKTFRMNATIVE(etc->osh, skb); ++ PKTFREE(etc->osh, skb, FALSE); ++ } ++ return; ++ } ++#endif /* !GMAC3 */ ++ ++#ifdef HNDCTF ++ /* try cut thru' before sending up */ ++ if (et_ctf_forward(et, skb) != BCME_ERROR) ++ return; ++#endif /* HNDCTF */ ++ ++ ASSERT(!PKTISCHAINED(skb)); ++ ++ /* extract priority from payload and store it out-of-band ++ * in skb->priority ++ */ ++ if (et->etc->qos) ++ pktsetprio(skb, TRUE); ++ ++ skb->protocol = eth_type_trans(skb, et->dev); ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++#ifndef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ { ++ struct sk_buff *next = skb->next; ++ while (1) { ++ if (next != NULL) { ++ ++ prefetch_range(next, SKB_PREFETCH_LEN); ++ next = next->next; ++ } else { ++ break; ++ } ++ } ++ } ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++#endif ++ ++ /* send it up */ ++#if defined(NAPI_POLL) || defined(NAPI2_POLL) ++#ifdef CONFIG_IPROC_2STAGE_RX ++ if (!et->rxinisr) ++ netif_receive_skb(skb); ++ else ++ netif_rx(skb); ++#else /* CONFIG_IPROC_2STAGE_RX */ ++ if (et->dev->features & NETIF_F_GRO) { ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { ++ skb = vlan_untag(skb); ++ if (unlikely(!skb)) { ++ goto err; ++ } ++ } ++ napi_gro_receive(&et->napi_poll, skb); ++ } else { ++ netif_receive_skb(skb); ++ } ++#endif /* CONFIG_IPROC_2STAGE_RX */ ++ ++#else /* NAPI_POLL */ ++ netif_rx(skb); ++#endif /* NAPI_POLL */ ++ ++ ET_LOG("et%d: et_sendup ret", et->etc->unit, 0); ++ ++ return; ++ ++err: ++ et_error(et, skb, rxh); ++ ++#if defined(CONFIG_IPROC_FA2) ++drop_pkt: ++#endif /* defined(CONFIG_IPROC_FA2) */ ++ PKTFRMNATIVE(etc->osh, skb); ++ PKTFREE(etc->osh, skb, FALSE); ++ ++ return; ++} ++ ++#ifdef HNDCTF ++void ++et_dump_ctf(et_info_t *et, struct bcmstrbuf *b) ++{ ++ ctf_dump(et->cih, b); ++} ++#endif ++ ++void ++et_dump(et_info_t *et, struct bcmstrbuf *b) ++{ ++ bcm_bprintf(b, "et%d: %s %s version %s\n", et->etc->unit, ++ __DATE__, __TIME__, EPI_VERSION_STR); ++ ++#ifdef HNDCTF ++#if defined(BCMDBG) ++ ctf_dump(et->cih, b); ++#endif ++#endif /* HNDCTF */ ++ ++ et_dumpet(et, b); ++ etc_dump(et->etc, b); ++ ++ bcm_bprintf(b, "txdfrm(%d); txdfrmropped(%d); txqlen(%d); txqstop(%d); txdmafull(%d) txmaxlen(%d) txsgpkt(%d)\n", ++ et->etc->txfrm, et->etc->txfrmdropped, et->etc->txqlen, et->etc->txqstop, et->etc->txdmafull, ++ et->etc->txmaxlen, et->etc->txsgpkt); ++ et->etc->txfrm=0; ++ et->etc->txfrmdropped=0; ++ et->etc->txqlen=0; ++ et->etc->txqstop=0; ++ et->etc->txdmafull=0; ++ et->etc->txmaxlen=0; ++ et->etc->txsgpkt=0; ++ ++ bcm_bprintf(b, "rxquota(%d); rxdmastopped(%d)\n", ++ et->etc->rxquota, et->etc->rxdmastopped); ++ et->etc->rxquota=0; ++ et->etc->rxdmastopped=0; ++#ifdef GMAC_RATE_LIMITING ++ bcm_bprintf(b, "rxd_dropped_packets(%d)\n", ++ et->etc->rl_dropped_packets); ++ et->etc->rl_dropped_packets=0; ++#endif /* GMAC_RATE_LIMITING */ ++ ++} ++ ++static void ++et_dumpet(et_info_t *et, struct bcmstrbuf *b) ++{ ++ bcm_bprintf(b, "et %p dev %p name %s tbusy %d txq[0].qlen %d malloced %d\n", ++ et, et->dev, et->dev->name, (uint)netif_queue_stopped(et->dev), et->txq[0].qlen, ++ MALLOCED(et->osh)); ++} ++ ++void ++et_link_up(et_info_t *et) ++{ ++ ET_ERROR(("et%d: link up (%d%s)\n", ++ et->etc->unit, et->etc->speed, (et->etc->duplex? "FD" : "HD"))); ++ printf("et%d Link Up: %d%s\n", et->etc->unit, et->etc->speed, et->etc->duplex?"FD":"HD"); ++ netif_carrier_on(et->dev); ++} ++ ++void ++et_link_down(et_info_t *et) ++{ ++ ET_ERROR(("et%d: link down\n", et->etc->unit)); ++ printf("et%d Link Down\n", et->etc->unit); ++ netif_carrier_off(et->dev); ++} ++ ++bool ++et_is_link_up(et_info_t *et) ++{ ++ return netif_carrier_ok(et->dev); ++} ++ ++int ++et_enable_device( uint idx ) ++{ ++ ulong flags; ++ uint coreidx, coreid; ++ int rc = -1; ++ ++ spin_lock_irqsave(&sih_lock, flags); ++ ++ si_setcore(sih, GMAC_CORE_ID, idx); ++ coreidx = si_coreidx(sih); ++ coreid = si_coreid(sih); ++ ++ //printk("%s coreidx(0x%x) coreid(0x%x)\n", __FUNCTION__, coreidx, coreid); ++ /* 2G_ENABLED: Enable IDM 250MHz for 2G mode */ ++/* #if 1 */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ si_core_reset(sih, 0x44, 0); ++#else ++ si_core_reset(sih, 0, 0); ++#endif ++ ++ /* Initialize USBHC core OK */ ++ rc = 0; ++ ++ si_setcoreidx(sih, coreidx); ++ spin_unlock_irqrestore(&sih_lock, flags); ++ ++ return rc; ++} ++ ++ ++/********************************************************************** ++ * bcm5301x_gmac_probe(device) ++ * ++ * The Platform Driver Probe function. ++ * ++ * Input parameters: ++ * device: The Device Context ++ * ++ * Return value: ++ * 0: Driver Probe is Succesful ++ * not 0: ERROR ++ **********************************************************************/ ++static int bcm5301x_gmac_probe(struct platform_device* pldev) ++{ ++ struct net_device *dev = NULL; ++ void __iomem *macbase = NULL; ++ struct resource *memres = NULL; ++ struct resource *irqres = NULL; ++ osl_t *osh = NULL; ++ et_info_t *et = NULL; ++ int unit = et_found; ++ int err = 0; ++ char name[128]; ++ int i; ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++ char *var; ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ ++ printk("%s enter name:%s; id:0x%x; unit:%d\n", __FUNCTION__, pldev->name, pldev->id, unit); ++ ++ /*Validation of platform device structure*/ ++ if (!pldev) { ++ ET_ERROR(("WRONG INPUT\nplatfrom_device ppointer should not be NULL.\n")); ++ return -EINVAL; ++ } ++ ++ et_found++; ++ ++ /* pre-qualify et unit, that can save the effort to do et_detach */ ++ ++ nvram_env_gmac_name(unit, name); ++ if (getvar(NULL, name) == NULL) { ++ printk("et%d: %s not found, ignore it\n", unit, name); ++ return -ENODEV; ++ } ++ ++ osh = osl_attach(pldev, PCI_BUS, FALSE); ++ ASSERT(osh); ++ ++ /* Get global SB handle */ ++ sih = si_kattach(SI_OSH); ++ ++ /* reset core */ ++ et_enable_device(unit); ++ ++ ET_TRACE(("%s call alloc_etherdev\n", __FUNCTION__)); ++ if ((dev = alloc_etherdev(sizeof( et_info_t ))) == NULL) { ++ ET_ERROR(("%s: alloc_etherdev() failed\n", __FUNCTION__)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++ et = ET_INFO(dev); ++ bzero(et, sizeof(et_info_t)); /* Is this needed in 2.6.36 ? -LR */ ++ et->dev = dev; ++ et->osh = osh; ++ ++ ET_TRACE(("%s get resources\n", __FUNCTION__)); ++ memres = iproc_platform_get_resource(pldev, IORESOURCE_MEM, 0); ++ if (NULL == memres) { ++ ET_ERROR(("ERROR: Could not get Platform Resource MAC Register Memory Resurce\n")); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++ if (!request_mem_region(memres->start, (memres->end - memres->start + 1), pldev->name)) { ++ ET_ERROR(("ERROR: Could not request mem region. In file %s, LN:%d\n", ++ __FILE__, __LINE__)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ irqres = iproc_platform_get_resource(pldev, IORESOURCE_IRQ, 0); ++ if (NULL == irqres) { ++ ET_ERROR(("ERROR: Could not get Platform Resource GMAC Register IRQ Resource\n")); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++ dev->base_addr = memres->start; ++ dev->irq = irqres->start; ++ ++ printk("et%d: base_addr (0x%x) irq (%d)\n", unit, (uint32)dev->base_addr, dev->irq); ++ ++// if ((et->regsva = ioremap_nocache(dev->base_addr, PCI_BAR0_WINSZ)) == NULL) { ++ if ((et->regsva = ioremap_nocache(dev->base_addr, 0xc00)) == NULL) { ++ ET_ERROR(("et%d: ioremap() failed\n", unit)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ET_TRACE(("%s base_addr: 0x%x; regsva:0x%x\n", __FUNCTION__, (uint32)dev->base_addr, (uint32)et->regsva)); ++ ++ pldev->id = dev->base_addr; ++ dev_set_drvdata(&(pldev->dev), dev); ++ SET_NETDEV_DEV(dev, (&pldev->dev)); ++ ++ init_MUTEX(&et->sem); ++ spin_lock_init(&et->lock); ++ spin_lock_init(&et->txq_lock); ++ spin_lock_init(&et->tx_lock); ++ spin_lock_init(&et->isr_lock); ++ ++ for (i = 0; i < NUMTXQ; i++) ++ skb_queue_head_init(&et->txq[i]); ++ ++ /* common load-time initialization */ ++ et->etc = etc_attach((void *)et, VENDOR_BROADCOM, BCMIPROC_CHIP_ID, unit, osh, et->regsva); ++ if (et->etc == NULL) { ++ ET_ERROR(("et%d: etc_attach() failed\n", unit)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++#ifdef GMAC3 ++ et->fwdh = (fwder_t *)NULL; /* attached/dettached on et up/dn */ ++ /* The ethernet network interface uses "eth0". Use fwd0, fwd1 instead */ ++ if (DEV_FWDER(et->etc)) ++ strncpy(dev->name, DEV_FWDER_NAME, 3); ++ ++#endif /* GMAC3 */ ++ ++#ifdef HNDCTF ++ et->cih = ctf_attach(osh, dev->name, &et_msg_level, et_ctf_detach, et); ++ ++ if(et->cih) ++ { ++ printk("%s: et->cih not NULL \n", __FUNCTION__); ++ } ++ else ++ { ++ printk("%s: et->cih is NULL \n", __FUNCTION__); ++ } ++ printk("%s: CTF_ENAB(ci) = %d \n", __FUNCTION__, (CTF_ENAB(et->cih) ? 1 : 0)); ++ if (ctf_dev_register(et->cih, dev, FALSE) != BCME_OK) { ++ ET_ERROR(("et%d: ctf_dev_register() failed\n", unit)); ++ goto Exit; ++ } ++#endif /* HNDCTF */ ++ ++#ifdef CTFPOOL ++ /* create ctf packet pool with specified number of buffers */ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++if ((osl_ctfpool_init(unit, osh, CTFPOOLSZ, RXBUFSZ+BCMEXTRAHDROOM) < 0)) { ++ ET_ERROR(("et%d: chipattach: ctfpool alloc/init failed\n", unit)); ++ goto Exit; ++ } else { ++ printk("\net%d: chipattach: ctfpool alloc/init successful\n", unit); ++ } ++#else ++ if (CTF_ENAB(et->cih)) { ++ uint32 poolsz; ++ /* use large ctf poolsz for platforms with more memory */ ++ poolsz = ((num_physpages >= 32767) ? CTFPOOLSZ * 2 : ++ ((num_physpages >= 8192) ? CTFPOOLSZ : 0)); ++ if ((poolsz > 0) && ++ (osl_ctfpool_init(osh, poolsz, RXBUFSZ+BCMEXTRAHDROOM) < 0)) { ++ ET_ERROR(("et%d: chipattach: ctfpool alloc/init failed\n", unit)); ++ goto Exit; ++ } else { ++ printk("\net%d: chipattach: ctfpool alloc/init successful\n", unit); ++ } ++ } ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++#endif /* CTFPOOL */ ++ ++ bcopy(&et->etc->cur_etheraddr, dev->dev_addr, ETHER_ADDR_LEN); ++ ++ /* init 1 second watchdog timer */ ++ init_timer(&et->timer); ++ et->timer.data = (ulong)dev; ++ et->timer.function = et_watchdog; ++ ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ /* schedule one second watchdog timer */ ++ et->timer.expires = jiffies + HZ; ++ mod_timer(&et->timer, et->timer.expires); ++ et->set = TRUE; ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++#ifdef GMAC_RATE_LIMITING ++ /* init 1 second watchdog timer */ ++ init_timer(&et->etc->rl_timer); ++ et->etc->rl_timer.data = (ulong)dev; ++ et->etc->rl_timer.function = et_release_congestion; ++#endif /* GMAC_RATE_LIMITING */ ++ ++#ifdef NAPI2_POLL ++ netif_napi_add(dev, & et->napi_poll, et_poll, 64); ++ napi_enable(&et->napi_poll); ++#endif /* NAPI2_POLL */ ++ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ /* setup the bottom half handler */ ++ tasklet_init(&et->tasklet, et_dpc, (ulong)et); ++#endif /* NAPI_POLL */ ++ ++#ifdef ET_ALL_PASSIVE ++ if (ET_ALL_PASSIVE_ENAB(et)) { ++ MY_INIT_WORK(&et->dpc_task.work, (work_func_t)et_dpc_work); ++ et->dpc_task.context = et; ++ MY_INIT_WORK(&et->txq_task.work, (work_func_t)et_txq_work); ++ et->txq_task.context = et; ++ } ++ if (et_ctf_pipeline_loopback(et)) { ++ et->all_dispatch_mode = FALSE; ++ } else { ++ et->all_dispatch_mode = (passivemode == 0) ? TRUE : FALSE; ++ } ++#endif /* ET_ALL_PASSIVE */ ++ ++ ET_TRACE(("%s request irq\n", __FUNCTION__)); ++ /* register our interrupt handler */ ++ if (request_irq(dev->irq, et_isr, IRQF_SHARED, dev->name, et)) { ++ ET_ERROR(("%s: request_irq(%d) failed\n", __FUNCTION__, dev->irq)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++ /* add us to the global linked list */ ++ et->next = et_list; ++ et_list = et; ++ ++#ifndef HAVE_NET_DEVICE_OPS ++ /* lastly, enable our entry points */ ++ dev->open = et_open; ++ dev->stop = et_close; ++ dev->hard_start_xmit = et_start; ++ dev->get_stats = et_get_stats; ++ dev->set_mac_address = et_set_mac_address; ++ dev->set_multicast_list = et_set_multicast_list; ++ dev->do_ioctl = et_ioctl; ++#ifdef NAPI_POLL ++ dev->poll = et_poll; ++ dev->weight = (ET_GMAC(et->etc) ? 64 : 32); ++#endif /* NAPI_POLL */ ++#else /* HAVE_NET_DEVICE_OPS */ ++ /* Linux 2.6.36 and up. - LR */ ++ dev->netdev_ops = &et_netdev_ops ; ++#ifdef NAPI_POLL ++ dev->poll = et_poll; ++ dev->weight = (ET_GMAC(et->etc) ? 64 : 32); ++#endif /* NAPI_POLL */ ++ ++#endif /* !HAVE_NET_DEVICE_OPS */ ++ ++#if (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD)) ++ if (et->etc->unit == 2) { ++ dev->features = (NETIF_F_IP_CSUM); ++ //dev->features = (NETIF_F_IP_CSUM | NETIF_F_SG); ++ //dev->hw_features = dev->features; ++ dev->vlan_features = (NETIF_F_IP_CSUM); ++ printk("\n Enabling checksum offload ...\n"); ++ } ++#endif /* CONFIG_IPROC_FA2 && CONFIG_IPROC_FA2_CS_OFFLOAD */ ++ ++#if defined(BCMDMASGLISTOSL) ++#ifdef CONFIG_BCM_GRO_ENABLE ++ dev->features = (NETIF_F_GRO | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); ++ dev->vlan_features = (NETIF_F_GRO | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); ++ printk("et%d: Enable Checksum-SG-GRO\n", unit); ++#else ++ dev->features = (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); ++ dev->vlan_features = (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); ++ printk("et%d: Enable Checksum-SG\n", unit); ++#endif ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++ dev->ethtool_ops = &et_ethtool_ops; ++#endif ++ ++ /* Assign netdev name consistently, even if GMAC0 or 1 is disabled */ ++ { ++ unsigned char devname[8] = {0}; ++ snprintf(devname, 8, "eth%d", unit); ++ dev_alloc_name(dev, devname); ++ } ++ ++ ET_TRACE(("%s register netdev\n", __FUNCTION__)); ++ if (register_netdev(dev)) { ++ ET_ERROR(("%s register_netdev() failed\n", __FUNCTION__)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ET_LOCK(et); ++ et->etc->linkstate = FALSE; ++ et_link_down(et); ++ ET_UNLOCK(et); ++ ++ /* print hello string */ ++ (*et->etc->chops->longname)(et->etc->ch, name, sizeof(name)); ++ printk("%s: %s %s\n", dev->name, name, EPI_VERSION_STR); ++ ++ eth_mac_proc_create(dev); ++ ++#ifdef HNDCTF ++ if (ctf_enable(et->cih, dev, TRUE, &et->brc_hot) != BCME_OK) { ++ ET_ERROR(("et%d: ctf_enable() failed\n", unit)); ++ goto Exit; ++ } ++#endif ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++ /* check if brcm tag is turned off */ ++ var = getvar(NULL, "brcmtag"); ++ if (var) { ++ int tag = bcm_strtoul(var, NULL, 0); ++ if (tag==0) { ++ ET_ERROR(("BRCM TAG disabled\n")); ++ brcm_tag = false; ++ } ++ } ++ printk("BRCM TAG %sabled\n", brcm_tag?"en":"dis"); ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ printk("et_ctf_active %sabled\n", et_ctf_active(et)?"en":"dis"); ++ ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ ++ return 0; ++ ++Exit: ++ if (macbase) { ++ iounmap(macbase); ++ macbase=NULL; ++ } ++ if (memres) { ++ release_mem_region(memres->start, (memres->end - memres->start + 1)); ++ memres=NULL; ++ } ++ if (dev) { ++ free_netdev(dev); ++ dev = NULL; ++ } ++ if (osh) { ++ osl_detach(osh); ++ osh=NULL; ++ } ++ if (et) { ++ etc_detach(et->etc); ++ et->dev = NULL; ++ et->osh = NULL; ++ et_free(et); ++ et=NULL; ++ } ++ return err; ++} ++ ++ ++/********************************************************************** ++ * bcm5301x_gmac_remove(device) ++ * ++ * The Removal of Platform Device, and un-initialize the previously ++ * added MAC, and it's MEM Regions and Resources. ++ * ++ * Input parameters: ++ * device: The Device Context ++ * ++ * Return value: ++ * 0: Driver Entry is Succesfull ++ **********************************************************************/ ++static int __exit bcm5301x_gmac_remove(struct platform_device *pldev) ++{ ++ struct net_device *dev = platform_get_drvdata(pldev); ++ int retVal = 0; ++ et_info_t *et = NULL; ++ struct resource *memres = NULL; ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ++#ifdef CONFIG_PM ++ bcm5301x_gmac_drv_suspend(pldev, PMSG_SUSPEND); ++#endif ++ ++ et = ET_INFO(dev); ++ ++ iounmap(et->regsva); ++ unregister_netdev(dev); ++ ++ memres = iproc_platform_get_resource(pldev, IORESOURCE_MEM, 0); ++ if (memres) { ++ release_mem_region(memres->start, (memres->end - memres->start + 1)); ++ } else { ++ ET_ERROR(("ERROR: Could not get Platform Resource GMAC Register Memory Resource\n")); ++ retVal = -ENOMEM; ++ } ++ ++ free_netdev(dev); ++ ++ et->dev = NULL; ++ et_free(et); ++ ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ ++ return retVal; ++} ++ ++#ifdef CONFIG_PM ++static int bcm5301x_gmac_drv_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ int ret; ++ char *filename = "/usr/sbin/ifdown"; ++ char *argv[] = {filename, "eth0", NULL}; ++ char *envp[] = {"HOME=/", ++ "TERM=linux", ++ "PATH=/sbin:/usr/sbin:/bin:/usr/bin", ++ NULL}; ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ret = kernel_execve(filename, (const char * const*) argv, (const char * const*) envp); ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ ++ return 0; ++} ++ ++static int bcm5301x_gmac_drv_resume(struct platform_device *pdev) ++{ ++ int ret; ++ char *filename = "/usr/sbin/ifup"; ++ char *argv[] = {filename, "eth0", NULL}; ++ char *envp[] = {"HOME=/", ++ "TERM=linux", ++ "PATH=/sbin:/usr/sbin:/bin:/usr/bin", ++ NULL}; ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ret = kernel_execve(filename, (const char * const*) argv, (const char * const*) envp); ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ ++ return 0; ++} ++#else ++#define bcm5301x_gmac_drv_suspend NULL ++#define bcm5301x_gmac_drv_resume NULL ++#endif ++ ++/********************************************************************** ++ * GMAC0 driver: ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. ++**********************************************************************/ ++static struct platform_driver bcm5301x_gmac0_driver = ++{ ++ .probe = bcm5301x_gmac_probe, ++ .remove = __exit_p(bcm5301x_gmac_remove), ++ .suspend = bcm5301x_gmac_drv_suspend, ++ .resume = bcm5301x_gmac_drv_resume, ++ .driver = ++ { ++ .name = bcm5301x_gmac0_string, ++ }, ++}; ++ ++/********************************************************************** ++ * GMAC0 device: ++ * This structure defines the methods to be called by a platform device ++ * during the lifecycle of a device ++**********************************************************************/ ++static u64 gmac0_dmamask = DMA_BIT_MASK(32); ++static struct platform_device bcm5301x_gmac0_pdev = { ++ .name = bcm5301x_gmac0_string, ++ .id = 0, ++ .dev = { ++ .release = bcm5301x_gmac_release, ++ .init_name = bcm5301x_gmac0_string, ++ .dma_mask = &gmac0_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm5301x_gmac0_resources, ++ .num_resources = ARRAY_SIZE(bcm5301x_gmac0_resources), ++}; ++ ++/********************************************************************** ++ * GMAC1 driver: ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. ++**********************************************************************/ ++static struct platform_driver bcm5301x_gmac1_driver = ++{ ++ .probe = bcm5301x_gmac_probe, ++ .remove = __exit_p(bcm5301x_gmac_remove), ++ .suspend = bcm5301x_gmac_drv_suspend, ++ .resume = bcm5301x_gmac_drv_resume, ++ .driver = ++ { ++ .name = bcm5301x_gmac1_string, ++ }, ++}; ++ ++/********************************************************************** ++ * GMAC1 device: ++ * This structure defines the methods to be called by a platform device ++ * during the lifecycle of a device ++**********************************************************************/ ++static u64 gmac1_dmamask = DMA_BIT_MASK(32); ++static struct platform_device bcm5301x_gmac1_pdev = { ++ .name = bcm5301x_gmac1_string, ++ .id = 0, ++ .dev = { ++ .release = bcm5301x_gmac_release, ++ .init_name = bcm5301x_gmac1_string, ++ .dma_mask = &gmac1_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm5301x_gmac1_resources, ++ .num_resources = ARRAY_SIZE(bcm5301x_gmac1_resources), ++}; ++ ++/********************************************************************** ++ * GMAC2 driver: ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. ++**********************************************************************/ ++static struct platform_driver bcm5301x_gmac2_driver = ++{ ++ .probe = bcm5301x_gmac_probe, ++ .remove = __exit_p(bcm5301x_gmac_remove), ++ .suspend = bcm5301x_gmac_drv_suspend, ++ .resume = bcm5301x_gmac_drv_resume, ++ .driver = ++ { ++ .name = bcm5301x_gmac2_string, ++ }, ++}; ++ ++/********************************************************************** ++ * GMAC2 device: ++ * This structure defines the methods to be called by a platform device ++ * during the lifecycle of a device ++**********************************************************************/ ++static u64 gmac2_dmamask = DMA_BIT_MASK(32); ++static struct platform_device bcm5301x_gmac2_pdev = { ++ .name = bcm5301x_gmac2_string, ++ .id = 0, ++ .dev = { ++ .release = bcm5301x_gmac_release, ++ .init_name = bcm5301x_gmac2_string, ++ .dma_mask = &gmac2_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm5301x_gmac2_resources, ++ .num_resources = ARRAY_SIZE(bcm5301x_gmac2_resources), ++}; ++ ++/********************************************************************** ++ * GMAC3 driver: ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. ++**********************************************************************/ ++static struct platform_driver bcm5301x_gmac3_driver = ++{ ++ .probe = bcm5301x_gmac_probe, ++ .remove = __exit_p(bcm5301x_gmac_remove), ++ .suspend = bcm5301x_gmac_drv_suspend, ++ .resume = bcm5301x_gmac_drv_resume, ++ .driver = ++ { ++ .name = bcm5301x_gmac3_string, ++ }, ++}; ++ ++/********************************************************************** ++ * GMAC3 device: ++ * This structure defines the methods to be called by a platform device ++ * during the lifecycle of a device ++**********************************************************************/ ++static u64 gmac3_dmamask = DMA_BIT_MASK(32); ++static struct platform_device bcm5301x_gmac3_pdev = { ++ .name = bcm5301x_gmac3_string, ++ .id = 0, ++ .dev = { ++ .release = bcm5301x_gmac_release, ++ .init_name = bcm5301x_gmac3_string, ++ .dma_mask = &gmac3_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm5301x_gmac3_resources, ++ .num_resources = ARRAY_SIZE(bcm5301x_gmac3_resources), ++}; ++ ++/********************************************************************** ++ * This function calls the device structure. ++ * Input Parameter: ++ * dev - pointer to the struct device ++ **********************************************************************/ ++ ++static void bcm5301x_gmac_release (struct device *dev) {} ++ ++/********************************************************************** ++ * bcm5301x_gmac_init_module(VOID) ++ * ++ * The Driver Entry Function ++ * ++ * Input parameters: ++ * None ++ * ++ * Return value: ++ * 0: Driver Entry is Succesful ++ * not 0: ERROR ++ **********************************************************************/ ++static int __init ++bcm5301x_gmac_init_module(void) ++{ ++ int err = -1; ++ int deverr = -1; ++ int idx; ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ ++ spin_lock_init(&sih_lock); ++ ++#if defined(BCMDBG) ++ if (msglevel != 0xdeadbeef) ++ et_msg_level = msglevel; ++ else { ++ char *var = getvar(NULL, "et_msglevel"); ++ if (var) ++ et_msg_level = bcm_strtoul(var, NULL, 0); ++ } ++ ++ printk("%s: msglevel set to 0x%x\n", __FUNCTION__, et_msg_level); ++#endif /* defined(BCMDBG) */ ++ ++#ifdef ET_ALL_PASSIVE ++ { ++ char *var = getvar(NULL, "et_dispatch_mode"); ++ if (var) ++ passivemode = bcm_strtoul(var, NULL, 0); ++ printk("%s: passivemode set to 0x%x\n", __FUNCTION__, passivemode); ++ } ++#endif /* ET_ALL_PASSIVE */ ++#ifdef NAPI_POLL ++ printk("%s: NAPI_POLL mode\n", __FUNCTION__); ++#endif /* NAPI_POLL */ ++#ifdef NAPI2_POLL ++ printk("%s: NAPI2_POLL mode\n", __FUNCTION__); ++#endif /* NAPI2_POLL */ ++ ++#ifdef ET_LIMIT_TXQ ++ { ++ char *var = getvar(NULL, "et_txq_thresh"); ++ if (var) ++ et_txq_thresh = bcm_strtoul(var, NULL, 0); ++ printk("%s: et_txq_thresh set to 0x%x\n", __FUNCTION__, et_txq_thresh); ++ } ++#endif /* ET_LIMIT_TXQ */ ++#ifdef GMAC_RATE_LIMITING ++ { ++ char *var = getvar(NULL, "et_rx_rate_limit"); ++ if (var) ++ et_rx_rate_limit = bcm_strtoul(var, NULL, 0); ++ printk("%s: et_rx_rate_limit set to 0x%x\n", __FUNCTION__, et_rx_rate_limit); ++ } ++#endif /* GMAC_RATE_LIMITING */ ++ ++#ifdef GMAC3 ++ fwder_init(); ++ /* fwder_dump_all(); */ ++#endif /* GMAC3 */ ++ ++ /* keep track of which ones loaded */ ++ for (idx=0; idx1) { ++ /* load GMAC1 driver */ ++ err = iproc_platform_driver_register(&bcm5301x_gmac1_driver); ++ if (!err) { ++ /* load GMAC1 device */ ++ err = iproc_platform_device_register(&bcm5301x_gmac1_pdev); ++ if (err) { ++ iproc_platform_driver_unregister(&bcm5301x_gmac1_driver); ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } else { ++ gmac_pdev_loaded[1] = true; ++ deverr = 0; ++ } ++ } else { ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } ++ } ++ ++ if (IPROC_NUM_GMACS>2) { ++ /* load GMAC2 driver */ ++ err = iproc_platform_driver_register(&bcm5301x_gmac2_driver); ++ if (!err) { ++ /* load GMAC2 device */ ++ err = iproc_platform_device_register(&bcm5301x_gmac2_pdev); ++ if (err) { ++ iproc_platform_driver_unregister(&bcm5301x_gmac2_driver); ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } else { ++ gmac_pdev_loaded[2] = true; ++ deverr = 0; ++ } ++ } else { ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } ++ } ++ ++ if (IPROC_NUM_GMACS>3) { ++ /* load GMAC3 driver */ ++ err = iproc_platform_driver_register(&bcm5301x_gmac3_driver); ++ if (!err) { ++ /* load GMAC3 device */ ++ err = iproc_platform_device_register(&bcm5301x_gmac3_pdev); ++ if (err) { ++ iproc_platform_driver_unregister(&bcm5301x_gmac3_driver); ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } else { ++ gmac_pdev_loaded[3] = true; ++ deverr = 0; ++ } ++ } else { ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } ++ } ++ ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ return deverr; ++} ++ ++/********************************************************************** ++ * bcm5301x_gmac_cleanup_module(VOID) ++ * ++ * The Driver Exit Function ++ * ++ * Input parameters: ++ * None ++ * ++ * Return value: ++ * Nothing ++ **********************************************************************/ ++static void __exit ++bcm5301x_gmac_cleanup_module(void) ++{ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ++ if ( gmac_pdev_loaded[0] ) { ++ /* unregister device */ ++ iproc_platform_device_unregister(&bcm5301x_gmac0_pdev); ++ /* Unregister the driver*/ ++ iproc_platform_driver_unregister(&bcm5301x_gmac0_driver); ++ } ++ ++ if (IPROC_NUM_GMACS>1) { ++ if ( gmac_pdev_loaded[1] ) { ++ /* unregister device */ ++ iproc_platform_device_unregister(&bcm5301x_gmac1_pdev); ++ /* Unregister the driver*/ ++ iproc_platform_driver_unregister(&bcm5301x_gmac1_driver); ++ } ++ } ++ ++ if (IPROC_NUM_GMACS>2) { ++ if ( gmac_pdev_loaded[2] ) { ++ /* unregister device */ ++ iproc_platform_device_unregister(&bcm5301x_gmac2_pdev); ++ /* Unregister the driver*/ ++ iproc_platform_driver_unregister(&bcm5301x_gmac2_driver); ++ } ++ } ++ ++ if (IPROC_NUM_GMACS>3) { ++ if ( gmac_pdev_loaded[3] ) { ++ /* unregister device */ ++ iproc_platform_device_unregister(&bcm5301x_gmac3_pdev); ++ /* Unregister the driver*/ ++ iproc_platform_driver_unregister(&bcm5301x_gmac3_driver); ++ } ++ } ++ ++ //clean up the proc directory ++ eth_mac_proc_remove(); ++ ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ return; ++} ++ ++static int get_fa_bypass(char *page, char **start, off_t off, int count, int *eof, void *data) ++{ ++ unsigned int len=0; ++ len += sprintf(page+len, "\n\n## Current FA Bypass setting = 0x%x, %s ##\n\n",gBypass, gBypass?"enabled":"disabled"); ++ *eof = 1; ++ return len; ++} ++ ++static int set_fa_bypass(struct file *file, const char *buffer, unsigned long count, void *data) ++{ ++ unsigned int len=1; ++ unsigned char debug_buffer[2]; ++ int bypass =0; ++ ++ //printk("count %x ## \n\n",(unsigned int) count); ++ if (count != 2) ++ { ++ ET_ERROR(("Please pass (one:1) digit FA bypass value only, 0=disable FA bypass, 1 = enable FA bypass\n")); ++ return -EINVAL; ++ } ++ ++ // Last buffer byte will be LF or CR only ++ if(copy_from_user(&debug_buffer[0], buffer, len)) ++ { ++ ET_ERROR(("Problem in copying invalid user buffer\n")); ++ return -EFAULT; ++ } ++ ++ debug_buffer[len]='\0'; // Only one byte value is available now ++ if ( sscanf(debug_buffer,"%d",&bypass) != 1) ++ { ++ ET_ERROR(("\n##Invalid value :%s: is passed ##\n",debug_buffer)); ++ return -EINVAL; ++ } ++ if (!((bypass >=DISABLE_FA_BYPASS) && (bypass <= ENABLE_FA_BYPASS))) ++ { ++ ET_ERROR(("\n##Passed value :%d: is not in valid range %d-%d \n",bypass,DISABLE_FA_BYPASS,ENABLE_FA_BYPASS)); ++ return -EINVAL; ++ } ++ ET_TRACE(("\n##set_fa_bypass(): Previous: 0x%x %s ##\n", gBypass, gBypass?"enabled":"disabled")); ++ gBypass = bypass; ++ ET_TRACE(("\n##set_fa_bypass(): New: 0x%x %s ##\n", gBypass, gBypass?"enabled":"disabled")); ++ return count; ++} ++ ++ ++static char* bcm5301x_eth_proc_root="bcm5301x_eth"; ++static struct proc_dir_entry *bcm5301x_eth_root_dir ; // BCM5892 eth proc root directory ++ ++static int eth_mac_proc_create(struct net_device *dev ) ++{ ++ struct proc_dir_entry *dent, *ent; ++ et_info_t *et; ++ etc_info_t *etc; ++ char fname[32]; ++ ++ et = ET_INFO(dev); ++ if (et != NULL) { ++ etc = et->etc; ++ } ++ ++ if ((et == NULL) || (etc == NULL)) { ++ printk("%s: error: Unit probably not initialized by probe function." ++ " et=0x%pm etc=0x%p\n", __FUNCTION__, et, etc); ++ return -1; ++ } ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ++ snprintf(fname, 32, "%s%u", bcm5301x_eth_proc_root, etc->unit); ++ ++ dent = proc_mkdir(fname,bcm5301x_eth_root_dir); ++ if (dent) { ++ /* unit 2 has FA connectivity, create bypass path only for unit 2 */ ++ if (etc->unit == 2) { ++ printk("\nCreating fa bypass proc entry\n"); ++ ++ ent = create_proc_entry("fa_bypass", S_IFREG|S_IRUGO, dent); ++ if (ent) { ++ ent->read_proc = get_fa_bypass; ++ ent->write_proc = set_fa_bypass; ++ } ++ else { ++ printk("Error creating proc_entry, returning\n"); ++ return -1; ++ } ++ } ++ } ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ return 0; ++} ++ ++static void eth_mac_proc_remove(void) ++{ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ remove_proc_entry(bcm5301x_eth_proc_root,NULL); ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++} ++ ++ ++#if defined(CONFIG_IPROC_FA2) ++int et_fa2_spu_tx(struct sk_buff *skb) ++{ ++ struct net_device *dev = platform_get_drvdata(&bcm5301x_gmac3_pdev); ++ return et_start(skb, dev); ++} ++ ++#if defined(CONFIG_IPROC_FA2_CS_OFFLOAD) ++static et_info_t *et_get_eth3_info() ++{ ++ et_info_t *et; ++ struct net_device *d = platform_get_drvdata(&bcm5301x_gmac3_pdev); ++ ++ et = ET_INFO(d); ++ ++ if (et == NULL) { ++ printk(KERN_INFO "\net for dev3 is NULL, using dev2\n"); ++ // NOTEet = ET_INFO(dev); ++ ++ } ++ ++ return(et); ++} ++#endif /* CONFIG_IPROC_FA2_CS_OFFLOAD */ ++#endif /* CONFIG_IPROC_FA2 */ ++ ++ ++module_init(bcm5301x_gmac_init_module); ++module_exit(bcm5301x_gmac_cleanup_module); ++ ++MODULE_DESCRIPTION("Broadcom Northstar Ethernet Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_linux.h b/drivers/bcmdrivers/gmac/src/et/sys/et_linux.h +new file mode 100755 +index 0000000..68b4de8 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_linux.h +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux device driver tunables for ++ * Broadcom BCM47XX 10/100Mbps Ethernet Device Driver ++ * ++ * $Id: et_linux.h 320789 2012-03-13 04:01:27Z $ ++ */ ++ ++#ifndef _et_linux_h_ ++#define _et_linux_h_ ++ ++/* tunables */ ++#define NTXD 512 /* # tx dma ring descriptors (must be ^2) */ ++#define NRXD 512 /* # rx dma ring descriptors (must be ^2) */ ++#if defined(CONFIG_RAM_SIZE) && (CONFIG_RAM_SIZE <= 16) ++#define NRXBUFPOST 256 /* try to keep this # rbufs posted to the chip */ ++#else ++#define NRXBUFPOST 420 /* try to keep this # rbufs posted to the chip */ ++#endif ++#ifdef CONFIG_JUMBO_FRAME ++#define BCM_ETHER_MAX_LEN 2500 ++#else ++#define BCM_ETHER_MAX_LEN 1518 //ETHER_MAX_LEN (1518) ++#endif /* CONFIG_JUMBO_FRAME */ ++#define RXBUFSZ (BCM_ETHER_MAX_LEN + HWRXOFF + BCMEXTRAHDROOM) /* receive buffer size */ ++ ++#ifndef RXBND ++#define RXBND 64 //32 /* max # rx frames to process in dpc */ ++#endif ++ ++#if defined(ILSIM) || defined(__arch_um__) ++#undef NTXD ++#define NTXD 16 ++#undef NRXD ++#define NRXD 16 ++#undef NRXBUFPOST ++#define NRXBUFPOST 2 ++#endif ++ ++#define PKTCBND 48 ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define CTFPOOLSZ (2048) ++#else ++#define CTFPOOLSZ 768 ++#endif ++ ++#define PREFSZ 96 ++#ifndef PKTC ++#define ETPREFHDRS(h, sz) OSL_PREF_RANGE_ST((h), (sz)) ++#else ++#define ETPREFHDRS(h, sz) ++#endif ++ ++#endif /* _et_linux_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/etc.c b/drivers/bcmdrivers/gmac/src/et/sys/etc.c +new file mode 100755 +index 0000000..a356421 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/etc.c +@@ -0,0 +1,899 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Common [OS-independent] portion of ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Device Driver. ++ * ++ * $Id: etc.c 323634 2012-03-26 10:26:11Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef ETROBO ++#ifndef _siutils_h_ ++typedef const struct si_pub si_t; ++#endif ++#include ++#endif /* ETROBO */ ++ ++uint32 et_msg_level = ++#ifdef BCMDBG ++ 1; ++#else ++ 0; ++#endif /* BCMDBG */ ++ ++uint8 ethup=0; ++uint8 ethupmask=0; ++etc_info_t *ethupetcptr[IPROC_NUM_GMACS]; ++ ++/* local prototypes */ ++static void etc_loopback(etc_info_t *etc, int on); ++static void etc_dumpetc(etc_info_t *etc, struct bcmstrbuf *b); ++int etc_gmac_speed(int gmac); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++extern void gmac_set_amac_mdio(int en); ++extern int gmac_has_mdio_access(void); ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++void gmac_serdes_asym_mode(etc_info_t *etcptrs[]); ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++ ++ ++/* 802.1d priority to traffic class mapping. queues correspond one-to-one ++ * with traffic classes. ++ */ ++uint32 up2tc[NUMPRIO] = { ++ TC_BE, /* 0 BE TC_BE Best Effort */ ++ TC_BK, /* 1 BK TC_BK Background */ ++ TC_BK, /* 2 -- TC_BK Background */ ++ TC_BE, /* 3 EE TC_BE Best Effort */ ++ TC_CL, /* 4 CL TC_CL Controlled Load */ ++ TC_CL, /* 5 VI TC_CL Controlled Load */ ++ TC_VO, /* 6 VO TC_VO Voice */ ++ TC_VO /* 7 NC TC_VO Voice */ ++}; ++ ++uint32 priq_selector[] = { ++ [0x0] = TC_NONE, [0x1] = TC_BK, [0x2] = TC_BE, [0x3] = TC_BE, ++ [0x4] = TC_CL, [0x5] = TC_CL, [0x6] = TC_CL, [0x7] = TC_CL, ++ [0x8] = TC_VO, [0x9] = TC_VO, [0xa] = TC_VO, [0xb] = TC_VO, ++ [0xc] = TC_VO, [0xd] = TC_VO, [0xe] = TC_VO, [0xf] = TC_VO ++}; ++ ++/* find the chip opsvec for this chip */ ++struct chops* ++etc_chipmatch(uint vendor, uint device) ++{ ++#ifdef CFG_GMAC ++ { ++ extern struct chops bcmgmac_et_chops; ++ ++ if (bcmgmac_et_chops.id(vendor, device)) ++ return (&bcmgmac_et_chops); ++ } ++#endif /* CFG_GMAC */ ++ return (NULL); ++} ++ ++void* ++etc_attach(void *et, uint vendor, uint device, uint unit, void *osh, void *regsva) ++{ ++ etc_info_t *etc; ++ char *var; ++ ++ ET_TRACE(("et%d: etc_attach: vendor 0x%x device 0x%x\n", unit, vendor, device)); ++ ++ /* some code depends on packed structures */ ++ ASSERT(sizeof(struct ether_addr) == ETHER_ADDR_LEN); ++ ASSERT(sizeof(struct ether_header) == ETHER_HDR_LEN); ++ ++ /* allocate etc_info_t state structure */ ++ if ((etc = (etc_info_t*) MALLOC(osh, sizeof(etc_info_t))) == NULL) { ++ ET_ERROR(("et%d: etc_attach: out of memory, malloced %d bytes\n", unit, ++ MALLOCED(osh))); ++ return (NULL); ++ } ++ bzero((char*)etc, sizeof(etc_info_t)); ++ ++ etc->et = et; ++ etc->unit = unit; ++ etc->osh = osh; ++ etc->vendorid = (uint16) vendor; ++ etc->deviceid = (uint16) device; ++ etc->forcespeed = etc_gmac_speed(unit); ++ etc->linkstate = FALSE; ++ etc->mdio_init_time = 5; /* number of seconds to wait before release mdio bus */ ++ var = getvar(NULL, "eth_init_time"); ++ if (var) ++ etc->mdio_init_time = bcm_strtoul(var, NULL, 0); ++ printk("%s() mdio_init_time = %d\n", __FUNCTION__, etc->mdio_init_time); ++ ethupmask |= 1<unit; ++ ethupetcptr[unit] = etc; ++ ++#ifdef PKTC ++ /* initialize default pktc values */ ++ etc->pktcbnd = MAX(PKTCBND, RXBND); ++#endif ++ ++ /* set chip opsvec */ ++ etc->chops = etc_chipmatch(vendor, device); ++ ASSERT(etc->chops); ++ ++ /* chip attach */ ++ if ((etc->ch = (*etc->chops->attach)(etc, osh, regsva)) == NULL) { ++ ET_ERROR(("et%d: chipattach error\n", unit)); ++ goto fail; ++ } ++ ++ return ((void*)etc); ++ ++fail: ++ etc_detach(etc); ++ return (NULL); ++} ++ ++void ++etc_detach(etc_info_t *etc) ++{ ++ if (etc == NULL) ++ return; ++ ++ /* free chip private state */ ++ if (etc->ch) { ++ (*etc->chops->detach)(etc->ch); ++ etc->chops = etc->ch = NULL; ++ } ++ ++ MFREE(etc->osh, etc, sizeof(etc_info_t)); ++} ++ ++void ++etc_reset(etc_info_t *etc) ++{ ++ ET_TRACE(("et%d: etc_reset\n", etc->unit)); ++ ++ etc->reset++; ++ ++ /* reset the chip */ ++ (*etc->chops->reset)(etc->ch); ++ ++ /* free any posted tx packets */ ++ (*etc->chops->txreclaim)(etc->ch, TRUE); ++ ++#ifdef DMA ++ /* free any posted rx packets */ ++ (*etc->chops->rxreclaim)(etc->ch); ++#endif /* DMA */ ++} ++ ++void ++etc_init(etc_info_t *etc, uint options) ++{ ++ ET_TRACE(("et%d: etc_init\n", etc->unit)); ++ ++ ASSERT(etc->pioactive == NULL); ++ ASSERT(!ETHER_ISNULLADDR(&etc->cur_etheraddr)); ++ ASSERT(!ETHER_ISMULTI(&etc->cur_etheraddr)); ++ ++ /* init the chip */ ++ (*etc->chops->init)(etc->ch, options); ++ /* init the PM change mode and linkstate */ ++ etc->pm_modechange = FALSE; ++} ++ ++/* mark interface up */ ++void ++etc_up(etc_info_t *etc) ++{ ++ etc->up = TRUE; ++ ++ /* enable the port phy */ ++ (*etc->chops->phyenable)(etc->ch, etc->unit, etc->phyaddr, 1); ++ ++ et_init(etc->et, ET_INIT_FULL | ET_INIT_INTRON); ++} ++ ++/* mark interface down */ ++uint ++etc_down(etc_info_t *etc, int reset) ++{ ++ uint callback; ++ ++ callback = 0; ++ ++ ET_FLAG_DOWN(etc); ++ ++ /* disable the port phy */ ++ (*etc->chops->phyenable)(etc->ch, etc->unit, etc->phyaddr, 0); ++ ++ if (reset) ++ et_reset(etc->et); ++ ++ /* suppress link state changes during power management mode changes */ ++ if (etc->linkstate) { ++ etc->linkstate = FALSE; ++ if (!etc->pm_modechange) ++ et_link_down(etc->et); ++ } ++ ++ return (callback); ++} ++ ++/* common iovar handler. return 0=ok, -1=error */ ++int ++etc_iovar(etc_info_t *etc, uint cmd, uint set, void *arg) ++{ ++ int error; ++ uint *vecarg; ++#if defined(ETROBO) && !defined(_CFE_) ++ int i; ++ robo_info_t *robo = etc->robo; ++#endif /* ETROBO && _CFE_ */ ++ ++ error = 0; ++ vecarg = (uint *)arg; ++ ET_TRACE(("et%d: etc_iovar: cmd 0x%x\n", etc->unit, cmd)); ++ ++ switch (cmd) { ++#if defined(ETROBO) && !defined(_CFE_) ++ case IOV_ET_POWER_SAVE_MODE: ++ if (set) ++ error = robo_power_save_mode_set(robo, vecarg[1], vecarg[0]); ++ else { ++ /* get power save mode of all the phys */ ++ if (vecarg[0] == MAX_NO_PHYS) { ++ for (i = 0; i < MAX_NO_PHYS; i++) ++ vecarg[i] = robo_power_save_mode_get(robo, i); ++ break; ++ } ++ ++ /* get power save mode of the phy */ ++ error = robo_power_save_mode_get(robo, vecarg[0]); ++ if (error != -1) { ++ vecarg[1] = error; ++ error = 0; ++ } ++ } ++ break; ++ ++ case IOV_ET_ROBO_DEVID: ++ error = -1; ++ ++ if (robo != NULL) { ++ *vecarg = robo->devid; ++ error = 0; ++ } ++ break; ++#endif /* ETROBO && !_CFE_ */ ++#ifdef BCMDBG ++ case IOV_ET_CLEAR_DUMP: ++ if (set) { ++ uint size = ((char *)(&etc->rxbadlen) - (char *)(&etc->txframe)); ++ ++ bzero((char *)&etc->txframe, size + sizeof(etc->rxbadlen)); ++ (*etc->chops->dumpmib)(etc->ch, NULL, TRUE); ++ error = 0; ++ } ++ break; ++#endif /* BCMDBG */ ++ case IOV_PKTC: ++ if (set) ++ etc->pktc = *vecarg; ++ else ++ *vecarg = (uint)etc->pktc; ++ break; ++ ++ case IOV_PKTCBND: ++ if (set) ++ etc->pktcbnd = MAX(*vecarg, 32); ++ else ++ *vecarg = etc->pktcbnd; ++ break; ++ ++ case IOV_COUNTERS: ++ { ++ struct bcmstrbuf b; ++ bcm_binit(&b, (char*)arg, IOCBUFSZ); ++ etc_dumpetc(etc, &b); ++ } ++ break; ++ ++#ifdef HNDCTF ++ case IOV_DUMP_CTF: ++ { ++ struct bcmstrbuf b; ++ bcm_binit(&b, (char*)arg, IOCBUFSZ); ++ et_dump_ctf(etc->et, &b); ++ } ++ break; ++#endif /* HNDCTF */ ++ ++ default: ++ error = -1; ++ } ++ ++ return (error); ++} ++ ++/* common ioctl handler. return: 0=ok, -1=error */ ++int ++etc_ioctl(etc_info_t *etc, int cmd, void *arg) ++{ ++ int error; ++ int val; ++ int *vec = (int*)arg; ++ ++ error = 0; ++ ++ val = arg ? *(int*)arg : 0; ++ ++ ET_TRACE(("et%d: etc_ioctl: cmd 0x%x\n", etc->unit, cmd)); ++ ++ switch (cmd) { ++ case ETCUP: ++ et_up(etc->et); ++ break; ++ ++ case ETCDOWN: ++ et_down(etc->et, TRUE); ++ break; ++ ++ case ETCLOOP: ++ etc_loopback(etc, val); ++ break; ++ ++ case ETCDUMP: ++ if (et_msg_level & 0x10000) ++ bcmdumplog((char *)arg, IOCBUFSZ); ++ else ++ { ++ struct bcmstrbuf b; ++ bcm_binit(&b, (char*)arg, IOCBUFSZ); ++ et_dump(etc->et, &b); ++ } ++ break; ++ ++ case ETCSETMSGLEVEL: ++ et_msg_level = val; ++ break; ++ ++ case ETCPROMISC: ++ etc_promisc(etc, val); ++ break; ++ ++ case ETCQOS: ++ etc_qos(etc, val); ++ break; ++ ++ case ETCSPEED: ++ if (vec) { ++ if (vec[0] == ET_1000FULL) { ++ etc->speed = 1000; ++ etc->duplex = 1; ++ } else if (vec[0] == ET_1000HALF) { ++ etc->speed = 1000; ++ etc->duplex = 0; ++ } else if (vec[0] == ET_100FULL) { ++ etc->speed = 100; ++ etc->duplex = 1; ++ } else if (vec[0] == ET_100HALF) { ++ etc->speed = 100; ++ etc->duplex = 0; ++ } else if (vec[0] == ET_10FULL) { ++ etc->speed = 10; ++ etc->duplex = 1; ++ } else if (vec[0] == ET_10HALF) { ++ etc->speed = 10; ++ etc->duplex = 0; ++ } else if (vec[0] == ET_AUTO) ++ ; ++ else ++ goto err; ++ ++ etc->forcespeed = vec[0]; ++ ++ /* explicitly reset the phy */ ++ (*etc->chops->phyreset)(etc->ch, etc->phyaddr); ++ ++ /* request restart autonegotiation if we're reverting to adv mode */ ++ etc->advertise = etc->advertise2 = 0; ++ if (etc->forcespeed == ET_AUTO) { ++ if (vec[1] & ADVERTISED_10baseT_Half) ++ etc->advertise |= ADV_10HALF; ++ if (vec[1] & ADVERTISED_10baseT_Full) ++ etc->advertise |= ADV_10FULL; ++ if (vec[1] & ADVERTISED_100baseT_Half) ++ etc->advertise |= ADV_100HALF; ++ if (vec[1] & ADVERTISED_100baseT_Full) ++ etc->advertise |= ADV_100FULL; ++ if (vec[1] & ADVERTISED_1000baseT_Full) ++ etc->advertise2 |= ADV_1000FULL; ++ etc->needautoneg = TRUE; ++ } else { ++ etc->needautoneg = FALSE; ++ } ++ et_init(etc->et, ET_INIT_INTRON); ++ } ++ break; ++ ++ case ETCPHYRD: ++ if (vec) { ++ vec[1] = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, vec[0]); ++ ET_TRACE(("etc_ioctl: ETCPHYRD of reg 0x%x => 0x%x\n", vec[0], vec[1])); ++ } ++ break; ++ ++ case ETCPHYRD2: ++ if (vec) { ++ uint phyaddr, reg; ++ phyaddr = vec[0] >> 16; ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ if (phyaddr < MAXEPHY) { ++#else ++ if (1) { ++#endif ++ reg = vec[0] & 0xffff; ++ vec[1] = (*etc->chops->phyrd)(etc->ch, phyaddr, reg); ++ ET_TRACE(("etc_ioctl: ETCPHYRD2 of phy 0x%x, reg 0x%x => 0x%x\n", ++ phyaddr, reg, vec[1])); ++ } ++ } ++ break; ++ ++ case ETCPHYWR: ++ if (vec) { ++ ET_TRACE(("etc_ioctl: ETCPHYWR to reg 0x%x <= 0x%x\n", vec[0], vec[1])); ++ (*etc->chops->phywr)(etc->ch, etc->phyaddr, vec[0], (uint16)vec[1]); ++ } ++ break; ++ ++ case ETCPHYWR2: ++ if (vec) { ++ uint phyaddr, reg; ++ phyaddr = vec[0] >> 16; ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ if (phyaddr < MAXEPHY) { ++#else ++ if (1) { ++#endif ++ reg = vec[0] & 0xffff; ++ (*etc->chops->phywr)(etc->ch, phyaddr, reg, (uint16)vec[1]); ++ ET_TRACE(("etc_ioctl: ETCPHYWR2 to phy 0x%x, reg 0x%x <= 0x%x\n", ++ phyaddr, reg, vec[1])); ++ } ++ } ++ break; ++ ++#ifdef ETROBO ++ case ETCROBORD: ++ if (etc->robo && vec) { ++ uint page, reg; ++ uint16 val; ++ robo_info_t *robo = (robo_info_t *)etc->robo; ++ ++ page = vec[0] >> 16; ++ reg = vec[0] & 0xffff; ++ val = -1; ++ robo->ops->read_reg(etc->robo, page, reg, &val, 2); ++ vec[1] = val; ++ ET_TRACE(("etc_ioctl: ETCROBORD of page 0x%x, reg 0x%x => 0x%x\n", ++ page, reg, val)); ++ } ++ break; ++ ++ case ETCROBOWR: ++ if (etc->robo && vec) { ++ uint page, reg; ++ uint16 val; ++ robo_info_t *robo = (robo_info_t *)etc->robo; ++ ++ page = vec[0] >> 16; ++ reg = vec[0] & 0xffff; ++ val = vec[1]; ++ robo->ops->write_reg(etc->robo, page, vec[0], &val, 2); ++ ET_TRACE(("etc_ioctl: ETCROBOWR to page 0x%x, reg 0x%x <= 0x%x\n", ++ page, reg, val)); ++ } ++ break; ++#endif /* ETROBO */ ++ ++ ++ default: ++ err: ++ error = -1; ++ } ++ ++ return (error); ++} ++ ++/* called once per second */ ++void ++etc_watchdog(etc_info_t *etc) ++{ ++ uint16 status; ++ uint16 lpa; ++#if defined(ETROBO) ++ robo_info_t *robo = (robo_info_t *)etc->robo; ++#endif ++#if defined(ETROBO) && !defined(_CFE_) ++ static uint32 sleep_timer = PWRSAVE_SLEEP_TIME, wake_timer; ++#endif /* ETROBO && !_CFE_ */ ++ uint16 phyaddrflag=0; ++ ++ etc->now++; ++ ++#if defined(ETROBO) ++ /* BCM53125 EEE IOP WAR for some other vendor's wrong EEE implementation. */ ++ if (robo) ++ robo_watchdog(robo); ++#endif ++ ++#if defined(ETROBO) && !defined(_CFE_) ++ /* Every PWRSAVE_WAKE_TIME sec the phys that are in manual mode ++ * is taken out of that mode and link status is checked after ++ * PWRSAVE_SLEEP_TIME sec to see if any of the links is up ++ * to take that port is taken out of the manual power save mode ++ */ ++ if (robo) { ++ if (ROBO_IS_PWRSAVE_MANUAL(robo)) { ++ if (etc->now == sleep_timer) { ++ robo_power_save_toggle(robo, FALSE); ++ wake_timer = sleep_timer + PWRSAVE_WAKE_TIME; ++ } else if (etc->now == wake_timer) { ++ robo_power_save_toggle(robo, TRUE); ++ sleep_timer = wake_timer + PWRSAVE_SLEEP_TIME; ++ } ++ } ++ ++ /* Apply the auto configuration from the nvram variable in the beginning */ ++ if ((etc->now == PWRSAVE_WAKE_TIME) && ROBO_IS_PWRSAVE_AUTO(robo)) { ++ robo_power_save_mode_update(robo); ++ } ++ } ++#endif /* ETROBO && !_CFE_ */ ++ ++ /* no local phy registers */ ++ if (etc->phyaddr == EPHY_NOREG) { ++ etc->linkstate = TRUE; ++ etc->duplex = 1; ++ /* keep emac txcontrol duplex bit consistent with current phy duplex */ ++ (*etc->chops->duplexupd)(etc->ch); ++ return; ++ } ++ ++ if (etc->up && etc->linkstate) { ++ if (!(ethup & 1<unit)) ++ printf("et%d Interface up\n", etc->unit); ++ ethup |= 1<unit; ++ } ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++ if ( !gmac_has_mdio_access()) { ++ /* we can't monitor link so force link up */ ++ /* if GMAC does not have access to MDIO then exit */ ++ if (!etc->linkstate) { ++ etc->linkstate = TRUE; ++ etc->duplex = 1; ++ etc->speed = 1000; ++ } ++ /* keep emac txcontrol duplex bit consistent with current phy duplex */ ++ (*etc->chops->duplexupd)(etc->ch); ++ if (!et_is_link_up(etc->et)) { ++ printf("%s can't access PHY, forcing link up\n", __FUNCTION__); ++ et_link_up(etc->et); ++ } ++ return; ++ } ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ /* access external phy */ ++ phyaddrflag = 0; ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++ ++ status = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 1); ++ /* check for bad mdio read */ ++ if (status == 0xffff) { ++ ET_ERROR(("et%d: etc_watchdog: bad mdio read: phyaddr %d mdcport %d\n", ++ etc->unit, etc->phyaddr, etc->mdcport)); ++ return; ++ } ++ ++ if (etc->forcespeed == ET_AUTO) { ++ uint16 adv, adv2 = 0, status2 = 0, estatus; ++ ++ adv = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 4); ++ lpa = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 5); ++ ++ /* read extended status register. if we are 1000BASE-T ++ * capable then get our advertised capabilities and the ++ * link partner capabilities from 1000BASE-T control and ++ * status registers. ++ */ ++ estatus = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 15); ++ if ((estatus != 0xffff) && (estatus & EST_1000TFULL)) { ++ /* read 1000BASE-T control and status registers */ ++ adv2 = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 9); ++ status2 = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 10); ++ } ++ ++ /* update current speed and duplex */ ++ if ((adv2 & ADV_1000FULL) && (status2 & LPA_1000FULL)) { ++ etc->speed = 1000; ++ etc->duplex = 1; ++ } else if ((adv2 & ADV_1000HALF) && (status2 & LPA_1000HALF)) { ++ etc->speed = 1000; ++ etc->duplex = 0; ++ } else if ((adv & ADV_100FULL) && (lpa & LPA_100FULL)) { ++ etc->speed = 100; ++ etc->duplex = 1; ++ } else if ((adv & ADV_100HALF) && (lpa & LPA_100HALF)) { ++ etc->speed = 100; ++ etc->duplex = 0; ++ } else if ((adv & ADV_10FULL) && (lpa & LPA_10FULL)) { ++ etc->speed = 10; ++ etc->duplex = 1; ++ } else { ++ etc->speed = 10; ++ etc->duplex = 0; ++ } ++ } ++ ++ /* monitor link state */ ++ if (!etc->linkstate && (status & STAT_LINK)) { ++ etc->linkstate = TRUE; ++ if (etc->pm_modechange) ++ etc->pm_modechange = FALSE; ++ else { ++ et_link_up(etc->et); ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++ (*etc->chops->forcespddpx)(etc->ch); ++#endif /* (!defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ } ++ } else if (etc->linkstate && !(status & STAT_LINK)) { ++ etc->linkstate = FALSE; ++ if (!etc->pm_modechange) ++ et_link_down(etc->et); ++ } ++ ++ /* keep emac txcontrol duplex bit consistent with current phy duplex */ ++ (*etc->chops->duplexupd)(etc->ch); ++ ++ /* check for remote fault error */ ++ if (status & STAT_REMFAULT) { ++ ET_ERROR(("et%d: remote fault\n", etc->unit)); ++ } ++ ++ /* check for jabber error */ ++ if (status & STAT_JAB) { ++ ET_ERROR(("et%d: jabber\n", etc->unit)); ++ } ++ ++ /* ++ * Read chip mib counters occationally before the 16bit ones can wrap. ++ * We don't use the high-rate mib counters. ++ */ ++ if ((etc->now % 30) == 0) ++ (*etc->chops->statsupd)(etc->ch); ++} ++ ++static void ++etc_loopback(etc_info_t *etc, int on) ++{ ++ ET_TRACE(("et%d: etc_loopback: %d\n", etc->unit, on)); ++ ++ etc->loopbk = (bool) on; ++ et_init(etc->et, ET_INIT_INTRON); ++} ++ ++void ++etc_promisc(etc_info_t *etc, uint on) ++{ ++ ET_TRACE(("et%d: etc_promisc: %d\n", etc->unit, on)); ++ ++ etc->promisc = (bool) on; ++ et_init(etc->et, ET_INIT_INTRON); ++} ++ ++void ++etc_qos(etc_info_t *etc, uint on) ++{ ++ ET_TRACE(("et%d: etc_qos: %d\n", etc->unit, on)); ++ ++ etc->qos = (bool) on; ++ et_init(etc->et, ET_INIT_INTRON); ++} ++ ++void ++etc_dump(etc_info_t *etc, struct bcmstrbuf *b) ++{ ++ etc_dumpetc(etc, b); ++ (*etc->chops->dump)(etc->ch, b); ++} ++ ++static void ++etc_dumpetc(etc_info_t *etc, struct bcmstrbuf *b) ++{ ++ char perm[32], cur[32]; ++ uint i; ++ ++ bcm_bprintf(b, "etc 0x%x et 0x%x unit %d msglevel %d speed/duplex %d%s\n", ++ (ulong)etc, (ulong)etc->et, etc->unit, et_msg_level, ++ etc->speed, (etc->duplex ? "full": "half")); ++ bcm_bprintf(b, "up %d promisc %d loopbk %d forcespeed %d advertise 0x%x " ++ "advertise2 0x%x needautoneg %d\n", ++ etc->up, etc->promisc, etc->loopbk, etc->forcespeed, ++ etc->advertise, etc->advertise2, etc->needautoneg); ++ bcm_bprintf(b, "piomode %d pioactive 0x%x nmulticast %d allmulti %d qos %d\n", ++ etc->piomode, (ulong)etc->pioactive, etc->nmulticast, etc->allmulti, etc->qos); ++ bcm_bprintf(b, "vendor 0x%x device 0x%x rev %d coreunit %d phyaddr %d mdcport %d\n", ++ etc->vendorid, etc->deviceid, etc->chiprev, ++ etc->coreunit, etc->phyaddr, etc->mdcport); ++ ++ bcm_bprintf(b, "perm_etheraddr %s cur_etheraddr %s\n", ++ bcm_ether_ntoa(&etc->perm_etheraddr, perm), ++ bcm_ether_ntoa(&etc->cur_etheraddr, cur)); ++ ++ if (etc->nmulticast) { ++ bcm_bprintf(b, "multicast: "); ++ for (i = 0; i < etc->nmulticast; i++) ++ bcm_bprintf(b, "%s ", bcm_ether_ntoa(&etc->multicast[i], cur)); ++ bcm_bprintf(b, "\n"); ++ } ++ ++ bcm_bprintf(b, "linkstate %d\n", etc->linkstate); ++ bcm_bprintf(b, "\n"); ++ ++ /* refresh stat counters */ ++ (*etc->chops->statsupd)(etc->ch); ++ ++ /* summary stat counter line */ ++ /* use sw frame and byte counters -- hw mib counters wrap too quickly */ ++ bcm_bprintf(b, "txframe %d txbyte %d txerror %d rxframe %d rxbyte %d rxerror %d\n", ++ etc->txframe, etc->txbyte, etc->txerror, ++ etc->rxframe, etc->rxbyte, etc->rxerror); ++ ++ /* transmit & receive stat counters */ ++ /* hardware mib pkt and octet counters wrap too quickly to be useful */ ++ (*etc->chops->dumpmib)(etc->ch, b, FALSE); ++ ++ bcm_bprintf(b, "txnobuf %d reset %d dmade %d dmada %d dmape %d\n", ++ etc->txnobuf, etc->reset, etc->dmade, etc->dmada, etc->dmape); ++ ++ /* hardware mib pkt and octet counters wrap too quickly to be useful */ ++ bcm_bprintf(b, "rxnobuf %d rxdmauflo %d rxoflo %d rxbadlen %d " ++ "rxgiants %d rxoflodiscards %d\n", ++ etc->rxnobuf, etc->rxdmauflo, etc->rxoflo, etc->rxbadlen, ++ etc->rxgiants, etc->rxoflodiscards); ++ ++ bcm_bprintf(b, "chained %d chainedsz1 %d unchained %d maxchainsz %d currchainsz %d\n", ++ etc->chained, etc->chainedsz1, etc->unchained, etc->maxchainsz, ++ etc->currchainsz); ++ ++ bcm_bprintf(b, "\n"); ++} ++ ++uint ++etc_totlen(etc_info_t *etc, void *p) ++{ ++ uint total; ++ ++ total = 0; ++ for (; p; p = PKTNEXT(etc->osh, p)) ++ total += PKTLEN(etc->osh, p); ++ return (total); ++} ++ ++#ifdef BCMDBG ++void ++etc_prhdr(char *msg, struct ether_header *eh, uint len, int unit) ++{ ++ char da[32], sa[32]; ++ ++ if (msg && (msg[0] != '\0')) ++ printf("et%d: %s: ", unit, msg); ++ else ++ printf("et%d: ", unit); ++ ++ printf("dst %s src %s type 0x%04X len %d\n", ++ bcm_ether_ntoa((struct ether_addr *)eh->ether_dhost, da), ++ bcm_ether_ntoa((struct ether_addr *)eh->ether_shost, sa), ++ ntoh16(eh->ether_type), ++ len); ++} ++void ++etc_prhex(char *msg, uchar *buf, uint nbytes, int unit) ++{ ++ if (msg && (msg[0] != '\0')) ++ printf("et%d: %s:\n", unit, msg); ++ else ++ printf("et%d:\n", unit); ++ ++ prhex(NULL, buf, nbytes); ++} ++#endif /* BCMDBG */ ++ ++ ++#ifdef ETROBO ++extern void robo_dump_mib(robo_info_t *robo); ++extern void robo_reset_mib(robo_info_t *robo); ++#endif ++extern void etc_chip_mib(etc_info_t *etc); ++void ++etc_robomib(etc_info_t *etc) ++{ ++#ifdef ETROBO ++ if (etc->robo) { ++ robo_dump_mib(etc->robo); ++ robo_reset_mib(etc->robo); ++ } ++#endif ++ ++ etc_chip_mib(etc); ++} ++ ++int ++etc_gmac_speed(int gmac) ++{ ++ char name[16], *speed; ++ sprintf(name, "et%dspeed", gmac); ++ ++ speed = nvram_get(name); ++ if (speed == NULL) { ++ printf("%s default GMAC%d speed: auto\n", __FUNCTION__, gmac); ++ return ET_AUTO; ++ } ++ ++ if (!strcmp(speed, "2500")) { ++ printf("%s specifing GMAC%d speed: 2500\n", __FUNCTION__, gmac); ++ return ET_2500FULL; ++ } ++ else if (!strcmp(speed, "1000")) { ++ printf("%s specifing GMAC%d speed: 1000\n", __FUNCTION__, gmac); ++ return ET_1000FULL; ++ } ++ else if (!strcmp(speed, "100")) { ++ printf("%s specifing GMAC%d speed: 100\n", __FUNCTION__, gmac); ++ return ET_100FULL; ++ } ++ else if (!strcmp(speed, "10")) { ++ printf("%s specifing GMAC%d speed: 10\n", __FUNCTION__, gmac); ++ return ET_10FULL; ++ } ++ ++ printf("%s default GMAC%d speed: auto\n", __FUNCTION__, gmac); ++ return ET_AUTO; ++} +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/etc.h b/drivers/bcmdrivers/gmac/src/et/sys/etc.h +new file mode 100755 +index 0000000..c31ce8a +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/etc.h +@@ -0,0 +1,317 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Common [OS-independent] header file for ++ * Broadcom BCM47XX 10/100Mbps Ethernet Device Driver ++ * ++ * $Id: etc.h 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++#ifndef _etc_h_ ++#define _etc_h_ ++ ++#include ++ ++#define MAXMULTILIST 32 ++ ++#ifndef ch_t ++#define ch_t void ++#endif ++ ++#if defined(CONFIG_MACH_NS) ++#define NUMTXQ 4 ++#else ++#define NUMTXQ 1 ++#endif /* defined(CONFIG_MACH_NS) */ ++ ++ ++#define TXREC_THR 8 ++ ++#if defined(__ECOS) ++#define IOCBUFSZ 4096 ++#elif defined(__linux__) ++#define IOCBUFSZ 16384 ++#else ++#define IOCBUFSZ 4096 ++#endif ++ ++struct etc_info; /* forward declaration */ ++struct bcmstrbuf; /* forward declaration */ ++ ++/* each chip type supports a set of chip-type-specific ops */ ++struct chops { ++ bool (*id)(uint vendor, uint device); /* return true if match */ ++ void *(*attach)(struct etc_info *etc, void *dev, void *regs); ++ void (*detach)(ch_t *ch); /* free chip private state */ ++ void (*reset)(ch_t *ch); /* chip reset */ ++ void (*init)(ch_t *ch, uint options); /* chip init */ ++ bool (*tx)(ch_t *ch, void *p); /* transmit frame */ ++ void *(*rx)(ch_t *ch); /* receive frame */ ++ void (*rxfill)(ch_t *ch); /* post dma rx buffers */ ++ int (*getintrevents)(ch_t *ch, bool in_isr); /* return intr events */ ++ bool (*errors)(ch_t *ch); /* handle chip errors */ ++ void (*intrson)(ch_t *ch); /* enable chip interrupts */ ++ void (*intrsoff)(ch_t *ch); /* disable chip interrupts */ ++ void (*txreclaim)(ch_t *ch, bool all); /* reclaim transmit resources */ ++ void (*rxreclaim)(ch_t *ch); /* reclaim receive resources */ ++ void (*statsupd)(ch_t *ch); /* update sw stat counters */ ++ void (*dumpmib)(ch_t *ch, struct bcmstrbuf *, bool clear); /* get sw mib counters */ ++ void (*enablepme)(ch_t *ch); /* enable PME */ ++ void (*disablepme)(ch_t *ch); /* disable PME */ ++ void (*phyreset)(ch_t *ch, uint phyaddr); /* reset phy */ ++ uint16 (*phyrd)(ch_t *ch, uint phyaddr, uint reg); /* read phy register */ ++ void (*phywr)(ch_t *ch, uint phyaddr, uint reg, uint16 val); /* write phy register */ ++ void (*dump)(ch_t *ch, struct bcmstrbuf *b); /* debugging output */ ++ void (*longname)(ch_t *ch, char *buf, uint bufsize); /* return descriptive name */ ++ void (*duplexupd)(ch_t *ch); /* keep mac duplex consistent */ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++ void (*forcespddpx)(ch_t *ch); /* force the speed and duplex */ ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ void (*phyenable)(ch_t *ch, uint eth_num, uint phyaddr, int enable); /* enable phy */ ++}; ++ ++/* ++ * "Common" os-independent software state structure. ++ */ ++typedef struct etc_info { ++#ifdef GMAC3 ++ bool gmac_fwd; /* gmac forwarding */ ++#endif /* GMAC3 */ ++ void *et; /* pointer to os-specific private state */ ++ uint unit; /* device instance number */ ++ void *osh; /* pointer to os handler */ ++ bool pktc; /* packet chaining enabled or not */ ++ int pktcbnd; /* max # of packets to chain */ ++ void *mib; /* pointer to s/w maintained mib counters */ ++ bool up; /* interface up and running */ ++ bool promisc; /* promiscuous destination address */ ++ bool qos; /* QoS priority determination on rx */ ++ bool loopbk; /* loopback override mode */ ++ ++ int forcespeed; /* disable autonegotiation and force speed/duplex */ ++ uint advertise; /* control speed/duplex advertised caps */ ++ uint advertise2; /* control gige speed/duplex advertised caps */ ++ bool needautoneg; /* request restart autonegotiation */ ++ int speed; /* current speed: 10, 100 */ ++ int duplex; /* current duplex: 0=half, 1=full */ ++ ++ bool piomode; /* enable programmed io (!dma) */ ++ void *pioactive; /* points to pio packet being transmitted */ ++ volatile uint *txavail[NUMTXQ]; /* dma: # tx descriptors available */ ++ ++ uint16 vendorid; /* pci function vendor id */ ++ uint16 deviceid; /* pci function device id */ ++ uint chip; /* chip number */ ++ uint chiprev; /* chip revision */ ++ uint coreid; /* core id */ ++ uint corerev; /* core revision */ ++ ++ bool nicmode; /* is this core using its own pci i/f */ ++ ++ struct chops *chops; /* pointer to chip-specific opsvec */ ++ void *ch; /* pointer to chip-specific state */ ++ void *robo; /* optional robo private data */ ++ ++ uint txq_state; /* tx queues state bits */ ++ uint coreunit; /* sb chips: chip enet instance # */ ++ uint phyaddr; /* sb chips: mdio 5-bit phy address */ ++ uint mdcport; /* sb chips: which mii to use (enet core #) to access phy */ ++ ++ struct ether_addr cur_etheraddr; /* our local ethernet address */ ++ struct ether_addr perm_etheraddr; /* original sprom local ethernet address */ ++ ++ struct ether_addr multicast[MAXMULTILIST]; ++ uint nmulticast; ++ bool allmulti; /* enable all multicasts */ ++ ++ bool linkstate; /* link integrity state */ ++ bool pm_modechange; /* true if mode change is to due pm */ ++ ++ uint32 now; /* elapsed seconds */ ++ ++ uint32 boardflags; /* board flags */ ++ uint32 txrec_thresh; /* # of tx frames after which reclaim is done */ ++ ++ uint32 mdio_init_time; /* # of seconds to wait before release mdio bus */ ++ ++#ifdef GMAC_RATE_LIMITING ++ /* rate limiting */ ++ bool rl_enabled; /* enable rate limiting logic */ ++ struct timer_list rl_timer; /* one second ratelimiting timer */ ++ bool rl_set; /* indicate the timer is set or not */ ++ uint32 rl_stopping_all_packets; ++ uint32 rl_stopping_broadcasts; ++ uint32 rl_dropped_all_packets; ++ uint32 rl_dropped_bc_packets; ++ uint32 rl_dropped_packets; ++ uint32 rl_prior_jiffies; ++#endif /* GMAC_RATE_LIMITING */ ++ ++ /* sw-maintained stat counters */ ++ uint32 txframes[NUMTXQ]; /* transmitted frames on each tx fifo */ ++ uint32 txframe; /* transmitted frames */ ++ uint32 txbyte; /* transmitted bytes */ ++ uint32 rxframe; /* received frames */ ++ uint32 rxbyte; /* received bytes */ ++ uint32 txerror; /* total tx errors */ ++ uint32 txnobuf; /* tx out-of-buffer errors */ ++ uint32 rxerror; /* total rx errors */ ++ uint32 rxgiants; /* total rx giant frames */ ++ uint32 rxnobuf; /* rx out-of-buffer errors */ ++ uint32 reset; /* reset count */ ++ uint32 dmade; /* pci descriptor errors */ ++ uint32 dmada; /* pci data errors */ ++ uint32 dmape; /* descriptor protocol error */ ++ uint32 rxdmauflo; /* receive descriptor underflow */ ++ uint32 rxoflo; /* receive fifo overflow */ ++ uint32 txuflo; /* transmit fifo underflow */ ++ uint32 rxoflodiscards; /* frames discarded during rx fifo overflow */ ++ uint32 rxbadlen; /* 802.3 len field != read length */ ++ uint32 chained; /* number of frames chained */ ++ uint32 chainedsz1; /* number of chain size 1 frames */ ++ uint32 unchained; /* number of frames not chained */ ++ uint32 maxchainsz; /* max chain size so far */ ++ uint32 currchainsz; /* current chain size */ ++ /* my counters */ ++ uint32 txfrm; /* tx frames */ ++ uint32 txfrmdropped; /* tx dropped frames */ ++ uint32 txqlen; ++ uint32 txqstop; ++ uint32 txdmafull; ++ uint32 txmaxlen; ++ uint32 txsgpkt; ++ uint32 rxquota; ++ uint32 rxdmastopped; ++} etc_info_t; ++ ++/* interrupt event bitvec */ ++#define INTR_TX 0x1 ++#define INTR_RX 0x2 ++#define INTR_ERROR 0x4 ++#define INTR_TO 0x8 ++#define INTR_NEW 0x10 ++ ++/* forcespeed values */ ++#define ET_AUTO -1 ++#define ET_10HALF 0 ++#define ET_10FULL 1 ++#define ET_100HALF 2 ++#define ET_100FULL 3 ++#define ET_1000HALF 4 ++#define ET_1000FULL 5 ++#define ET_2500FULL 6 /* 2.5Gigabit */ ++ ++/* init options */ ++#define ET_INIT_FULL 0x1 ++#define ET_INIT_INTRON 0x2 ++ ++/* Specific init options for et_init */ ++#define ET_INIT_DEF_OPTIONS (ET_INIT_FULL | ET_INIT_INTRON) ++#define ET_INIT_INTROFF (ET_INIT_FULL) ++#define ET_INIT_PARTIAL (0) ++ ++/* macro to safely clear the UP flag */ ++#define ET_FLAG_DOWN(x) (*(x)->chops->intrsoff)((x)->ch); \ ++ (x)->up = FALSE; ++ ++/* ++ * Least-common denominator rxbuf start-of-data offset: ++ * Must be >= size of largest rxhdr ++ * Must be 2-mod-4 aligned so IP is 0-mod-4 ++ */ ++#define HWRXOFF 30 ++ ++#define TC_BK 0 /* background traffic class */ ++#define TC_BE 1 /* best effort traffic class */ ++#define TC_CL 2 /* controlled load traffic class */ ++#define TC_VO 3 /* voice traffic class */ ++#define TC_NONE -1 /* traffic class none */ ++ ++#define RX_Q0 0 /* receive DMA queue */ ++#define NUMRXQ 1 /* gmac has one rx queue */ ++ ++#define TX_Q0 TC_BK /* DMA txq 0 */ ++#define TX_Q1 TC_BE /* DMA txq 1 */ ++#define TX_Q2 TC_CL /* DMA txq 2 */ ++#define TX_Q3 TC_VO /* DMA txq 3 */ ++ ++static inline uint32 ++etc_up2tc(uint32 up) ++{ ++ extern uint32 up2tc[]; ++ ++ return (up2tc[up]); ++} ++ ++static inline uint32 ++etc_priq(uint32 txq_state) ++{ ++ extern uint32 priq_selector[]; ++ ++ return (priq_selector[txq_state]); ++} ++ ++/* rx header flags bits */ ++#define RXH_FLAGS(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ ((((bcmgmacrxh_t *)(rxh))->flags) & htol16(GRXF_CRC | GRXF_OVF | GRXF_OVERSIZE)) : \ ++ ((((bcmenetrxh_t *)(rxh))->flags) & htol16(RXF_NO | RXF_RXER | RXF_CRC | RXF_OV))) ++ ++#define RXH_OVERSIZE(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_OVERSIZE) : FALSE) ++ ++#define RXH_PT(etc, rxh) (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_PT_MASK) ++ ++#define RXH_CRC(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_CRC) : \ ++ (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_CRC)) ++ ++#define RXH_OVF(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_OVF) : \ ++ (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_OV)) ++ ++#define RXH_RXER(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ FALSE : (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_RXER)) ++ ++#define RXH_NO(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ FALSE : (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_NO)) ++ ++/* Used for fa+ error determination */ ++#define RXH_CTFERROR(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & (GRXF_CTFERR | GRXF_CRC | GRXF_OVF)) : FALSE) ++ ++#ifdef CFG_GMAC ++#define ET_GMAC(etc) ((etc)->coreid == GMAC_CORE_ID) ++#else ++#define ET_GMAC(etc) (0) ++#endif /* CFG_GMAC */ ++ ++/* exported prototypes */ ++extern struct chops *etc_chipmatch(uint vendor, uint device); ++extern void *etc_attach(void *et, uint vendor, uint device, uint unit, void *dev, void *regsva); ++extern void etc_detach(etc_info_t *etc); ++extern void etc_reset(etc_info_t *etc); ++extern void etc_init(etc_info_t *etc, uint options); ++extern void etc_up(etc_info_t *etc); ++extern uint etc_down(etc_info_t *etc, int reset); ++extern int etc_ioctl(etc_info_t *etc, int cmd, void *arg); ++extern int etc_iovar(etc_info_t *etc, uint cmd, uint set, void *arg); ++extern void etc_promisc(etc_info_t *etc, uint on); ++extern void etc_qos(etc_info_t *etc, uint on); ++extern void etc_dump(etc_info_t *etc, struct bcmstrbuf *b); ++extern void etc_watchdog(etc_info_t *etc); ++extern uint etc_totlen(etc_info_t *etc, void *p); ++extern void etc_robomib(etc_info_t *etc); ++ ++#endif /* _etc_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.c b/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.c +new file mode 100755 +index 0000000..eff478e +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.c +@@ -0,0 +1,2567 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Gigabit Ethernet MAC (Unimac) core. ++ * This file implements the chip-specific routines for the GMAC core. ++ * ++ * $Id: etcgmac.c 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* for et_phyxx() routines */ ++#include ++#include ++#include ++#include ++ ++#ifdef ETROBO ++#include ++#endif /* ETROBO */ ++#ifdef GMAC3 ++#include /* GMAC3 */ ++#endif /* GMAC3 */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#include "mach/socregs_ing_open.h" ++#endif ++#if defined(CONFIG_MACH_KT2) ++#include "mach/socregs_ing_open.h" ++#endif ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#include "bcmiproc_serdes.h" ++#include "bcmiproc_phy5461s.h" ++#endif ++#if defined(CONFIG_MACH_HR2) ++#include "bcmiproc_phy5221.h" ++#endif ++#if defined(CONFIG_MACH_NSP) ++#include ++#include "bcmiproc_robo_serdes.h" ++#endif ++ ++struct bcmgmac; /* forward declaration */ ++#define ch_t struct bcmgmac ++#include ++ ++extern int nvram_env_gmac_name(int gmac, char *name); ++ ++#ifdef ETROBO ++extern void robo_reset_mib(robo_info_t *robo); ++extern void robo_dump_mib(robo_info_t *robo); ++#endif ++ ++/* private chip state */ ++struct bcmgmac { ++ void *et; /* pointer to et private state */ ++ etc_info_t *etc; /* pointer to etc public state */ ++ ++ gmac_commonregs_t *regscomm; /* pointer to GMAC COMMON registers */ ++ gmacregs_t *regs; /* pointer to chip registers */ ++ osl_t *osh; /* os handle */ ++ ++ void *etphy; /* pointer to et for shared mdc/mdio contortion */ ++ ++ uint32 intstatus; /* saved interrupt condition bits */ ++ uint32 intmask; /* current software interrupt mask */ ++ uint32 def_intmask; /* default interrupt mask */ ++ ++ hnddma_t *di[NUMTXQ]; /* dma engine software state */ ++ ++ bool mibgood; /* true once mib registers have been cleared */ ++ gmacmib_t mib; /* mib statistic counters */ ++ si_t *sih; /* si utils handle */ ++ ++ char *vars; /* sprom name=value */ ++ uint vars_size; ++ ++ void *adm; /* optional admtek private data */ ++ mcfilter_t mf; /* multicast filter */ ++}; ++ ++/* local prototypes */ ++static bool chipid(uint vendor, uint device); ++static void *chipattach(etc_info_t *etc, void *osh, void *regsva); ++static void chipdetach(ch_t *ch); ++static void chipreset(ch_t *ch); ++static void chipinit(ch_t *ch, uint options); ++static bool chiptx(ch_t *ch, void *p); ++static void *chiprx(ch_t *ch); ++static void chiprxfill(ch_t *ch); ++static int chipgetintrevents(ch_t *ch, bool in_isr); ++static bool chiperrors(ch_t *ch); ++static void chipintrson(ch_t *ch); ++static void chipintrsoff(ch_t *ch); ++static void chiptxreclaim(ch_t *ch, bool all); ++static void chiprxreclaim(ch_t *ch); ++static void chipstatsupd(ch_t *ch); ++static void chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear); ++static void chipenablepme(ch_t *ch); ++static void chipdisablepme(ch_t *ch); ++static void chipphyreset(ch_t *ch, uint phyaddr); ++static uint16 chipphyrd(ch_t *ch, uint phyaddr, uint reg); ++static void chipphywr(ch_t *ch, uint phyaddr, uint reg, uint16 v); ++static void chipdump(ch_t *ch, struct bcmstrbuf *b); ++static void chiplongname(ch_t *ch, char *buf, uint bufsize); ++static void chipduplexupd(ch_t *ch); ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++static void chipforcespddpx(ch_t *ch); ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++static void chipphyinit(ch_t *ch, uint phyaddr); ++static void chipphyor(ch_t *ch, uint phyaddr, uint reg, uint16 v); ++static void chipphyforce(ch_t *ch, uint phyaddr); ++static void chipphyadvertise(ch_t *ch, uint phyaddr); ++static void chipphyenable(ch_t *ch, uint eth_num, uint phyaddr, int enable); ++static void chipdumpregs(ch_t *ch, gmacregs_t *regs, struct bcmstrbuf *b); ++static void gmac_mf_cleanup(ch_t *ch); ++static int gmac_speed(ch_t *ch, uint32 speed); ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++static void gmac_serdes_init(ch_t *ch); ++#endif ++static void gmac_miiconfig(ch_t *ch); ++ ++struct chops bcmgmac_et_chops = { ++ chipid, ++ chipattach, ++ chipdetach, ++ chipreset, ++ chipinit, ++ chiptx, ++ chiprx, ++ chiprxfill, ++ chipgetintrevents, ++ chiperrors, ++ chipintrson, ++ chipintrsoff, ++ chiptxreclaim, ++ chiprxreclaim, ++ chipstatsupd, ++ chipdumpmib, ++ chipenablepme, ++ chipdisablepme, ++ chipphyreset, ++ chipphyrd, ++ chipphywr, ++ chipdump, ++ chiplongname, ++ chipduplexupd, ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++ chipforcespddpx, ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ chipphyenable ++}; ++ ++static uint devices[] = { ++ BCM47XX_GMAC_ID, ++ BCM4716_CHIP_ID, ++ BCM4748_CHIP_ID, ++ BCM53010_CHIP_ID, ++ BCM56150_CHIP_ID, ++ BCM56340_CHIP_ID, ++ BCM53020_CHIP_ID, ++ BCM56450_CHIP_ID, ++ 0x0000 ++}; ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++static void *wrapaddr = 0; ++void gmac_set_amac_mdio(int en) ++{ ++ u32 tmp; ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ u32 mdio_sel= IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL; ++ u32 ctrl_sel= IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL; ++#else ++ u32 mdio_sel= IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_MDIO_SEL; ++ u32 ctrl_sel= IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_CTRL_SEL; ++#endif ++ u32 iproc_mdio_sel= IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL; ++ ++ if (en) { ++ /* Get register base address */ ++ wrapaddr = ioremap(IPROC_WRAP_MISC_CONTROL, 0x10); ++ //printf("%s IPROC_WRAP_MISC_CONTROL(0x%x) remaps to 0x%x\n", __FUNCTION__, IPROC_WRAP_MISC_CONTROL, (u32)wrapaddr); ++ } ++ ++ tmp = ioread32(wrapaddr); ++ //printf("%s read (0x%x) from IPROC_WRAP_MISC_CONTROL(0x%x)\n", __FUNCTION__, tmp, (u32)wrapaddr); ++ if (en) { ++ /* set bits IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL, ++ IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL & ++ IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL ++ so AMAC can access the Serdes and Phy */ ++ tmp |= ((1 << mdio_sel) | (1 << ctrl_sel) | (1 << iproc_mdio_sel)); ++ } else { ++ /* clear bits IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL & ++ IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL ++ so CMIC can access the Serdes and Phy */ ++ tmp &= ~((1 << mdio_sel) | (1 << iproc_mdio_sel)); ++ } ++ //printf("%s write 0x%x to IPROC_WRAP_MISC_CONTROL(0x%x)\n", __FUNCTION__, tmp, (u32)wrapaddr); ++ iowrite32(tmp, wrapaddr); ++ ++ if (!en) { ++ /* unmap register base address */ ++ //printf("%s unmap(0x%x)\n", __FUNCTION__, (u32)wrapaddr); ++ iounmap(wrapaddr); ++ wrapaddr=0; ++ } ++} ++ ++ ++int gmac_has_mdio_access(void) ++{ ++ u32 tmp; ++ u32 regmsk = (1 << IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ regmsk |= ((1 << IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL) | ++ (1 << IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL)); ++#else ++ regmsk |= ((1 << IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_MDIO_SEL) | ++ (1 << IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_CTRL_SEL)); ++#endif ++ ++ if (wrapaddr==0) { ++ /* if no wrapaddr then no access */ ++ return 0; ++ } ++ ++ tmp = ioread32(wrapaddr); ++ tmp &= ~regmsk; ++ if (tmp == regmsk) { ++ return 0; ++ } ++ ++ return 1; ++} ++#endif ++ ++/* This api will determine if this unit specified is the last interface. */ ++bool gmac_last_interface(int unit) ++{ ++ char name[128]; ++ int idx; ++ ++ /* if interface 2 or greater then must be last */ ++ if (unit>=2) ++ return true; ++ ++ /* Look to see if there is a next interface specified */ ++ for (idx=unit+1; idx<=2; idx++) { ++ nvram_env_gmac_name(idx, name); ++ if (getvar(NULL, name) != NULL) { ++ /* there is a next interface */ ++ return false; ++ } ++ } ++ /* no other interfaces */ ++ return true; ++} ++ ++ ++static bool ++chipid(uint vendor, uint device) ++{ ++ int i; ++ ++ if (vendor != VENDOR_BROADCOM) { ++ ET_ERROR(("%s ERROR: NOT a BROADCOM Vendor ID (0x%x)\n", __FUNCTION__, vendor)); ++ return (FALSE); ++ } ++ ++ for (i = 0; devices[i]; i++) { ++ if (device == devices[i]) ++ return (TRUE); ++ } ++ ++ ET_ERROR(("%s ERROR: UNKNOWN Device ID (0x%x)\n", __FUNCTION__, device)); ++ printk("%s ERROR: UNKNOWN Device ID (0x%x)\n", __FUNCTION__, device); ++ return (FALSE); ++} ++ ++static void * ++chipattach(etc_info_t *etc, void *osh, void *regsva) ++{ ++ ch_t *ch; ++ gmacregs_t *regs; ++ uint i; ++ char name[16]; ++ char *var; ++ uint boardflags, boardtype; ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ uint reset; ++#endif ++#ifdef ETROBO ++ char *pet; ++ int initsw=0; ++#endif ++ ++ ET_TRACE(("et%d: chipattach: regsva 0x%lx\n", etc->unit, (ulong)regsva)); ++ ++ if ((ch = (ch_t *)MALLOC(osh, sizeof(ch_t))) == NULL) { ++ ET_ERROR(("et%d: chipattach: out of memory, malloced %d bytes\n", etc->unit, ++ MALLOCED(osh))); ++ return (NULL); ++ } ++ bzero((char *)ch, sizeof(ch_t)); ++ ++ ch->etc = etc; ++ ch->et = etc->et; ++ ch->osh = osh; ++ ++ /* store the pointer to the sw mib */ ++ etc->mib = (void *)&ch->mib; ++ ++ /* get si handle */ ++ if ((ch->sih = si_attach(etc->deviceid, ch->osh, regsva, PCI_BUS, NULL, &ch->vars, ++ &ch->vars_size)) == NULL) { ++ ET_ERROR(("et%d: chipattach: si_attach error\n", etc->unit)); ++ goto fail; ++ } ++ ++ if ((etc->corerev = si_corerev(ch->sih)) == GMAC_4706B0_CORE_REV && ++ (ch->regscomm = (gmac_commonregs_t *)si_setcore(ch->sih, ++ GMAC_COMMON_4706_CORE_ID, 0)) == NULL) { ++ ET_ERROR(("et%d: chipattach: Could not setcore to GMAC common\n", etc->unit)); ++ goto fail; ++ } ++ ++ if ((regs = (gmacregs_t *)si_setcore(ch->sih, GMAC_CORE_ID, etc->unit)) == NULL) { ++ ET_ERROR(("et%d: chipattach: Could not setcore to GMAC\n", etc->unit)); ++ goto fail; ++ } ++ ++ ch->regs = regs; ++ etc->chip = ch->sih->chip; ++ etc->chiprev = ch->sih->chiprev; ++ etc->coreid = si_coreid(ch->sih); ++ etc->nicmode = !(ch->sih->bustype == SI_BUS); ++ etc->coreunit = si_coreunit(ch->sih); ++#ifdef GMAC3 ++ etc->gmac_fwd = FALSE; /* GMAC3 */ ++#endif /* GMAC3 */ ++ etc->boardflags = getintvar(ch->vars, "boardflags"); ++ ++ boardflags = etc->boardflags; ++ boardtype = ch->sih->boardtype; ++ ++#ifdef PKTC ++ etc->pktc = (getintvar(ch->vars, "pktc_disable") == 0); ++#endif ++ ++ /* get our local ether addr */ ++ nvram_env_gmac_name(etc->coreunit, name); ++ var = getvar(ch->vars, name); ++ if (var == NULL) { ++ ET_ERROR(("et%d: chipattach: getvar(%s) not found\n", etc->unit, name)); ++ goto fail; ++ } ++ bcm_ether_atoe(var, &etc->perm_etheraddr); ++ ++#ifdef GMAC3 ++ /* ++ * Select GMAC mode of operation: ++ * If a valid MAC address is present, it operates as an Ethernet Network ++ * interface, otherwise it operates as a forwarding GMAC interface. ++ */ ++ //if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) ++ if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) { ++ etc->gmac_fwd = TRUE; ++ printk("%s GMAC forward enabled\n", __FUNCTION__); ++ } ++#else /* !GMAC3 */ ++ if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) { ++ ET_ERROR(("et%d: chipattach: invalid format: %s=%s\n", etc->unit, name, var)); ++ goto fail; ++ } ++#endif /* !GMAC3 */ ++ ++ bcopy((char *)&etc->perm_etheraddr, (char *)&etc->cur_etheraddr, ETHER_ADDR_LEN); ++ ++ ++ /* ++ * Too much can go wrong in scanning MDC/MDIO playing "whos my phy?" . ++ * Instead, explicitly require the environment var "etphyaddr=". ++ */ ++ ++ /* get our phyaddr value */ ++ sprintf(name, "et%dphyaddr", etc->coreunit); ++ var = getvar(NULL, name); ++ if (var == NULL) { ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ etc->phyaddr = EPHY_NOREG; ++#else ++ etc->phyaddr = etc->unit+1; ++#endif ++ ET_ERROR(("et%d: chipattach: getvar(%s) not found set to %d\n", etc->unit, name, etc->phyaddr)); ++ } else { ++ etc->phyaddr = bcm_atoi(var) & EPHY_MASK; ++ } ++ printf("et%d: chipattach: phyaddr(0x%x)\n", etc->unit, etc->phyaddr); ++ ++ /* nvram says no phy is present */ ++ if (etc->phyaddr == EPHY_NONE) { ++ ET_ERROR(("et%d: chipattach: phy not present\n", etc->unit)); ++ goto fail; ++ } ++ ++ /* reset the gmac core */ ++ chipreset(ch); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (wrapaddr == 0) { ++ /* flip switch so AMAC can access serdes */ ++ gmac_set_amac_mdio(1); ++ } ++ ++ if (etc->unit == 0) { ++ void *amacidmaddr; ++ uint32 tmp; ++ ++ /* Get register base address */ ++ amacidmaddr = ioremap(AMAC_IDM0_IO_CONTROL_DIRECT, 0x10); ++ tmp = ioread32(amacidmaddr); ++ ++ //printf("%s read AMAC_IDM0_IO_CONTROL_DIRECT: 0x%x\n", __FUNCTION__, tmp); ++ tmp &= ~(1<unit == 1) { ++ void *amacidmaddr; ++ uint32 tmp; ++ ++ /* Get register base address */ ++ amacidmaddr = ioremap(AMAC_IDM1_IO_CONTROL_DIRECT, 0x10); ++ tmp = ioread32(amacidmaddr); ++ ++ //printf("%s read AMAC_IDM1_IO_CONTROL_DIRECT: 0x%x\n", __FUNCTION__, tmp); ++ tmp &= ~(1<=1000) { ++ printf("%s ERROR: PLL failed to lock\n", __FUNCTION__); ++ } ++ /* CRU_LCPLL2_CONTROL0 post_resetb=1 */ ++ tmp = ioread32(lcplladdr); ++ tmp |= (1<coreunit); ++ ++ /* allocate dma resources for txqs */ ++ /* TX: TC_BK, RX: RX_Q0 */ ++ ch->di[0] = dma_attach(osh, name, ch->sih, ++ DMAREG(ch, DMA_TX, TX_Q0), ++ DMAREG(ch, DMA_RX, RX_Q0), ++ NTXD, NRXD, RXBUFSZ, -1, NRXBUFPOST, HWRXOFF, ++ &et_msg_level); ++ ++#if defined(CONFIG_MACH_NS) ++ /* TX: TC_BE, RX: UNUSED */ ++ ch->di[1] = dma_attach(osh, name, ch->sih, ++ DMAREG(ch, DMA_TX, TX_Q1), ++ NULL /* rxq unused */, ++ NTXD, 0, 0, -1, 0, 0, &et_msg_level); ++ ++ /* TX: TC_CL, RX: UNUSED */ ++ ch->di[2] = dma_attach(osh, name, ch->sih, ++ DMAREG(ch, DMA_TX, TX_Q2), ++ NULL /* rxq unused */, ++ NTXD, 0, 0, -1, 0, 0, &et_msg_level); ++ ++ /* TX: TC_VO, RX: UNUSED */ ++ ch->di[3] = dma_attach(osh, name, ch->sih, ++ DMAREG(ch, DMA_TX, TX_Q3), ++ NULL /* rxq unused */, ++ NTXD, 0, 0, -1, 0, 0, &et_msg_level); ++#endif /* defined(CONFIG_MACH_NS) */ ++ ++ for (i = 0; i < NUMTXQ; i++) ++ if (ch->di[i] == NULL) { ++ ET_ERROR(("et%d: chipattach: dma_attach failed\n", etc->unit)); ++ goto fail; ++ } ++ ++ for (i = 0; i < NUMTXQ; i++) ++ if (ch->di[i] != NULL) ++ etc->txavail[i] = (uint *)&ch->di[i]->txavail; ++ ++ /* set default sofware intmask */ ++ sprintf(name, "et%d_no_txint", etc->coreunit); ++ if (getintvar(ch->vars, name)) { ++ /* if no_txint variable is non-zero we disable tx interrupts. ++ * we do the tx buffer reclaim once every few frames. ++ */ ++ ch->def_intmask = (DEF_INTMASK & ~(I_XI0 | I_XI1 | I_XI2 | I_XI3)); ++ etc->txrec_thresh = (((NTXD >> 2) > TXREC_THR) ? TXREC_THR - 1 : 1); ++ } else ++ ch->def_intmask = DEF_INTMASK; ++ ++ ch->intmask = ch->def_intmask; ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ /* reset the external phy */ ++ if ((reset = getgpiopin(ch->vars, "ephy_reset", GPIO_PIN_NOTDEFINED)) != ++ GPIO_PIN_NOTDEFINED) { ++ reset = 1 << reset; ++ ++ /* Keep RESET low for 2 us */ ++ si_gpioout(ch->sih, reset, 0, GPIO_DRV_PRIORITY); ++ si_gpioouten(ch->sih, reset, reset, GPIO_DRV_PRIORITY); ++ OSL_DELAY(2); ++ ++ /* Keep RESET high for at least 2 us */ ++ si_gpioout(ch->sih, reset, reset, GPIO_DRV_PRIORITY); ++ OSL_DELAY(2); ++ ++ /* if external phy is present enable auto-negotation and ++ * advertise full capabilities as default config. ++ */ ++ ASSERT(etc->phyaddr != EPHY_NOREG); ++ etc->needautoneg = TRUE; ++ etc->advertise = (ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); ++ etc->advertise2 = ADV_1000FULL; ++ } ++#endif ++ ++ /* reset phy: reset it once now */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (ch->etc->unit == 0) { ++ serdes_reset_core(ch->etc->unit, etc->phyaddr); ++ } ++#endif ++ ++ chipphyreset(ch, etc->phyaddr); ++ ++#ifdef ETROBO ++ /* ++ * Broadcom Robo ethernet switch. ++ */ ++ pet = getvar(NULL, "swgmacet"); ++ sprintf(name, "et%d", etc->coreunit); ++ if (pet) { ++ if (bcmp(pet, name, strlen(pet)) == 0) ++ initsw = 1; ++ } ++ ++ if ((boardflags & BFL_ENETROBO) && initsw) { ++ ET_TRACE(("et%d: chipattach: Calling robo attach\n", etc->unit)); ++ printk("et%d: chipattach: Calling robo attach\n", etc->unit); ++ ++ /* Attach to the switch */ ++ if (!(etc->robo = bcm_robo_attach(ch->sih, ch, ch->vars, ++ (miird_f)bcmgmac_et_chops.phyrd, ++ (miiwr_f)bcmgmac_et_chops.phywr))) { ++ ET_ERROR(("et%d: chipattach: robo_attach failed\n", etc->unit)); ++ goto fail; ++ } ++ if (etc->switch_mode) { ++ printf("et%d: %s: bringing up robo switch\n", ch->etc->unit, __FUNCTION__); ++ /* Enable the switch and set it to a known good state */ ++ if (bcm_robo_enable_device(etc->robo)) { ++ ET_ERROR(("et%d: chipattach: robo_enable_device failed\n", etc->unit)); ++ goto fail; ++ } ++ /* Configure the switch to do VLAN */ ++ if ((boardflags & BFL_ENETVLAN) && ++ bcm_robo_config_vlan(etc->robo, etc->perm_etheraddr.octet)) { ++ ET_ERROR(("et%d: chipattach: robo_config_vlan failed\n", etc->unit)); ++ goto fail; ++ } ++ /* Enable switching/forwarding */ ++ if (bcm_robo_enable_switch(etc->robo)) { ++ ET_ERROR(("et%d: chipattach: robo_enable_switch failed\n", etc->unit)); ++ goto fail; ++ } ++ robo_reset_mib(etc->robo); ++ } ++ } ++#endif /* ETROBO */ ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (gmac_last_interface(etc->unit)) { ++ /* must init all serdes lanes, init port 49 (phy 3) */ ++ serdes_init(etc->unit, 3); ++ serdes_start_pll(etc->unit, 1); ++ } ++ ++ if (etc->forcespeed == ET_AUTO) { ++ etc->needautoneg = TRUE; ++ etc->advertise = (ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); ++ etc->advertise2 = ADV_1000FULL; ++ } ++#endif ++#if defined(CONFIG_MACH_HR2) ++ if (etc->forcespeed == ET_AUTO) { ++ etc->needautoneg = TRUE; ++ etc->advertise = (ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); ++ } ++#endif ++ return ((void *) ch); ++ ++fail: ++ chipdetach(ch); ++ return (NULL); ++} ++ ++static void ++chipdetach(ch_t *ch) ++{ ++ int32 i; ++ ++ ET_TRACE(("et%d: chipdetach\n", ch->etc->unit)); ++ ++ if (ch == NULL) ++ return; ++ ++#ifdef ETROBO ++ /* free robo state */ ++ if (ch->etc->robo) ++ bcm_robo_detach(ch->etc->robo); ++#endif /* ETROBO */ ++ ++ /* free dma state */ ++ for (i = 0; i < NUMTXQ; i++) ++ if (ch->di[i] != NULL) { ++ dma_detach(ch->di[i]); ++ ch->di[i] = NULL; ++ } ++ ++ /* put the core back into reset */ ++ if (ch->sih) ++ si_core_disable(ch->sih, 0); ++ ++ if (ch->etc) ++ if (ch->etc->mib) ++ ch->etc->mib = NULL; ++ ++ /* free si handle */ ++ if (ch->sih) { ++ si_detach(ch->sih); ++ ch->sih = NULL; ++ } ++ ++ /* free vars */ ++ if (ch->vars) ++ MFREE(ch->osh, ch->vars, ch->vars_size); ++ ++ /* free chip private state */ ++ MFREE(ch->osh, ch, sizeof(ch_t)); ++} ++ ++static void ++chiplongname(ch_t *ch, char *buf, uint bufsize) ++{ ++ char *s; ++ ++ switch (ch->etc->deviceid) { ++ case BCM53010_CHIP_ID: ++ s = "Broadcom BCM5301x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ case BCM53020_CHIP_ID: ++ s = "Broadcom BCM5302x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ case BCM56150_CHIP_ID: ++ s = "Broadcom BCM5615x 10/100 Mbps Ethernet Controller"; ++ break; ++ case BCM56340_CHIP_ID: ++ s = "Broadcom BCM5634x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ case BCM56450_CHIP_ID: ++ s = "Broadcom BCM5645x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ case BCM47XX_GMAC_ID: ++ case BCM4716_CHIP_ID: ++ case BCM4748_CHIP_ID: ++ default: ++ s = "Broadcom BCM5301x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ } ++ ++ strncpy(buf, s, bufsize); ++ buf[bufsize - 1] = '\0'; ++} ++ ++#ifdef ETROBO ++extern void robo_bprintf_mib(robo_info_t *robo, struct bcmstrbuf *b); ++#endif ++ ++static void ++chipdump(ch_t *ch, struct bcmstrbuf *b) ++{ ++ /* int32 i; */ ++ ++ bcm_bprintf(b, "regs 0x%lx etphy 0x%lx ch->intstatus 0x%x intmask 0x%x\n", ++ (ulong)ch->regs, (ulong)ch->etphy, ch->intstatus, ch->intmask); ++ bcm_bprintf(b, "\n"); ++ ++ ++ /* registers */ ++ chipdumpregs(ch, ch->regs, b); ++ bcm_bprintf(b, "\n"); ++ ++ /* switch registers */ ++#ifdef ETROBO ++ if (ch->etc->robo) { ++ robo_dump_regs(ch->etc->robo, b); ++ robo_bprintf_mib(ch->etc->robo, b); ++ } ++ ++#endif /* ETROBO */ ++} ++ ++ ++#define PRREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, ®s->name)) ++#define PRMIBREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, ®s->mib.name)) ++ ++static void ++chipdumpregs(ch_t *ch, gmacregs_t *regs, struct bcmstrbuf *b) ++{ ++ uint phyaddr; ++ ++ phyaddr = ch->etc->phyaddr; ++ ++ PRREG(devcontrol); PRREG(devstatus); ++ bcm_bprintf(b, "\n"); ++ PRREG(biststatus); ++ bcm_bprintf(b, "\n"); ++ PRREG(intstatus); PRREG(intmask); PRREG(gptimer); ++ bcm_bprintf(b, "\n"); ++ PRREG(intrecvlazy); ++ bcm_bprintf(b, "\n"); ++ PRREG(flowctlthresh); PRREG(wrrthresh); PRREG(gmac_idle_cnt_thresh); ++ bcm_bprintf(b, "\n"); ++ if (ch->etc->corerev != GMAC_4706B0_CORE_REV) { ++ PRREG(phyaccess); PRREG(phycontrol); ++ bcm_bprintf(b, "\n"); ++ } ++ PRREG(txqctl); PRREG(rxqctl); ++ bcm_bprintf(b, "\n"); ++ PRREG(gpioselect); PRREG(gpio_output_en); ++ bcm_bprintf(b, "\n"); ++ PRREG(clk_ctl_st); PRREG(pwrctl); ++ bcm_bprintf(b, "\n"); ++ ++ /* unimac registers */ ++ PRREG(hdbkpctl); ++ bcm_bprintf(b, "\n"); ++ PRREG(cmdcfg); ++ bcm_bprintf(b, "\n"); ++ PRREG(macaddrhigh); PRREG(macaddrlow); ++ bcm_bprintf(b, "\n"); ++ PRREG(rxmaxlength); PRREG(pausequanta); PRREG(macmode); ++ bcm_bprintf(b, "\n"); ++ PRREG(outertag); PRREG(innertag); PRREG(txipg); PRREG(pausectl); ++ bcm_bprintf(b, "\n"); ++ PRREG(txflush); PRREG(rxstatus); PRREG(txstatus); ++ bcm_bprintf(b, "\n"); ++ ++ /* mib registers */ ++ PRMIBREG(tx_good_octets); PRMIBREG(tx_good_pkts); PRMIBREG(tx_octets); PRMIBREG(tx_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(tx_broadcast_pkts); PRMIBREG(tx_multicast_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(tx_jabber_pkts); PRMIBREG(tx_oversize_pkts); PRMIBREG(tx_fragment_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(tx_underruns); PRMIBREG(tx_total_cols); PRMIBREG(tx_single_cols); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(tx_multiple_cols); PRMIBREG(tx_excessive_cols); PRMIBREG(tx_late_cols); ++ bcm_bprintf(b, "\n"); ++ if (ch->etc->corerev != GMAC_4706B0_CORE_REV) { ++ PRMIBREG(tx_defered); PRMIBREG(tx_carrier_lost); PRMIBREG(tx_pause_pkts); ++ bcm_bprintf(b, "\n"); ++ } ++ ++ PRMIBREG(rx_good_octets); PRMIBREG(rx_good_pkts); PRMIBREG(rx_octets); PRMIBREG(rx_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(rx_broadcast_pkts); PRMIBREG(rx_multicast_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(rx_jabber_pkts); ++ if (ch->etc->corerev != GMAC_4706B0_CORE_REV) { ++ PRMIBREG(rx_oversize_pkts); PRMIBREG(rx_fragment_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(rx_missed_pkts); PRMIBREG(rx_crc_align_errs); PRMIBREG(rx_undersize); ++ } ++ bcm_bprintf(b, "\n"); ++ if (ch->etc->corerev != GMAC_4706B0_CORE_REV) { ++ PRMIBREG(rx_crc_errs); PRMIBREG(rx_align_errs); PRMIBREG(rx_symbol_errs); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(rx_pause_pkts); PRMIBREG(rx_nonpause_pkts); ++ bcm_bprintf(b, "\n"); ++ } ++ if (phyaddr != EPHY_NOREG) { ++ /* print a few interesting phy registers */ ++ bcm_bprintf(b, "phy0 0x%x phy1 0x%x phy2 0x%x phy3 0x%x\n", ++ chipphyrd(ch, phyaddr, 0), ++ chipphyrd(ch, phyaddr, 1), ++ chipphyrd(ch, phyaddr, 2), ++ chipphyrd(ch, phyaddr, 3)); ++ bcm_bprintf(b, "phy4 0x%x phy5 0x%x phy24 0x%x phy25 0x%x\n", ++ chipphyrd(ch, phyaddr, 4), ++ chipphyrd(ch, phyaddr, 5), ++ chipphyrd(ch, phyaddr, 24), ++ chipphyrd(ch, phyaddr, 25)); ++ } ++ ++} ++ ++static void ++gmac_clearmib(ch_t *ch) ++{ ++ volatile uint32 *ptr; ++ ++ if (ch->etc->corerev == GMAC_4706B0_CORE_REV) ++ return; ++ ++ /* enable clear on read */ ++ OR_REG(ch->osh, &ch->regs->devcontrol, DC_MROR); ++ ++ for (ptr = &ch->regs->mib.tx_good_octets; ptr <= &ch->regs->mib.rx_uni_pkts; ptr++) { ++ (void)R_REG(ch->osh, ptr); ++ if (ptr == &ch->regs->mib.tx_q3_octets_high) ++ ptr++; ++ } ++ ++ return; ++} ++ ++static void ++gmac_init_reset(ch_t *ch) ++{ ++ OR_REG(ch->osh, &ch->regs->cmdcfg, CC_SR); ++ OSL_DELAY(GMAC_RESET_DELAY); ++} ++ ++static void ++gmac_clear_reset(ch_t *ch) ++{ ++ AND_REG(ch->osh, &ch->regs->cmdcfg, ~CC_SR); ++ OSL_DELAY(GMAC_RESET_DELAY); ++} ++ ++static void ++gmac_reset(ch_t *ch) ++{ ++ uint32 ocmdcfg, cmdcfg; ++ ++ /* put the mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* initialize default config */ ++ ocmdcfg = cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ cmdcfg &= ~(CC_TE | CC_RE | CC_RPI | CC_TAI | CC_HD | CC_ML | ++ CC_CFE | CC_RL | CC_RED | CC_PE | CC_TPI | CC_PAD_EN | CC_PF); ++ cmdcfg |= (CC_PROM | CC_NLC | CC_CFE); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ cmdcfg |= (CC_AE | CC_OT | CC_OR); ++#endif ++ ++ /*2G_ENABLED: Enable Unimac at 2G mode */ ++/* #if 1 */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ cmdcfg |= 0xc; ++#endif ++ ++ if (cmdcfg != ocmdcfg) ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++static void ++gmac_promisc(ch_t *ch, bool mode) ++{ ++ uint32 cmdcfg; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put the mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* enable or disable promiscuous mode */ ++ if (mode) ++ cmdcfg |= CC_PROM; ++ else ++ cmdcfg &= ~CC_PROM; ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++static int ++gmac_speed(ch_t *ch, uint32 speed) ++{ ++ uint32 cmdcfg; ++ uint32 hd_ena = 0; ++ ++ switch (speed) { ++ case ET_10HALF: ++ hd_ena = CC_HD; ++ /* FALLTHRU */ ++ ++ case ET_10FULL: ++ speed = 0; ++ break; ++ ++ case ET_100HALF: ++ hd_ena = CC_HD; ++ /* FALLTHRU */ ++ ++ case ET_100FULL: ++ speed = 1; ++ break; ++ ++ case ET_1000FULL: ++ speed = 2; ++ break; ++ ++ case ET_1000HALF: ++ ET_ERROR(("et%d: gmac_speed: supports 1000 mbps full duplex only\n", ++ ch->etc->unit)); ++ return (FAILURE); ++ ++ case ET_2500FULL: ++ speed = 3; ++ break; ++ ++ default: ++ ET_ERROR(("et%d: gmac_speed: speed %d not supported\n", ++ ch->etc->unit, speed)); ++ return (FAILURE); ++ } ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* set the speed */ ++ cmdcfg &= ~(CC_ES_MASK | CC_HD); ++ cmdcfg |= ((speed << CC_ES_SHIFT) | hd_ena); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ cmdcfg |= CC_AE; ++#endif ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++ ++ return (SUCCESS); ++} ++ ++static void ++gmac_macloopback(ch_t *ch, bool on) ++{ ++ uint32 ocmdcfg, cmdcfg; ++ ++ ocmdcfg = cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* set/clear the mac loopback mode */ ++ if (on) ++ cmdcfg |= CC_ML; ++ else ++ cmdcfg &= ~CC_ML; ++ ++ if (cmdcfg != ocmdcfg) ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++static int ++gmac_loopback(ch_t *ch, uint32 mode) ++{ ++ switch (mode) { ++ case LOOPBACK_MODE_DMA: ++ /* to enable loopback for any channel set the loopback ++ * enable bit in xmt0control register. ++ */ ++ dma_fifoloopbackenable(ch->di[TX_Q0]); ++ break; ++ ++ case LOOPBACK_MODE_MAC: ++ gmac_macloopback(ch, TRUE); ++ break; ++ ++ case LOOPBACK_MODE_NONE: ++ gmac_macloopback(ch, FALSE); ++ break; ++ ++ default: ++ ET_ERROR(("et%d: gmac_loopaback: Unknown loopback mode %d\n", ++ ch->etc->unit, mode)); ++ return (FAILURE); ++ } ++ ++ return (SUCCESS); ++} ++ ++static void ++gmac_enable(ch_t *ch) ++{ ++ uint32 cmdcfg; ++ gmacregs_t *regs; ++ ++ regs = ch->regs; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ cmdcfg |= CC_SR; ++ ++ /* first deassert rx_ena and tx_ena while in reset */ ++ cmdcfg &= ~(CC_RE | CC_TE); ++ W_REG(ch->osh, ®s->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++ ++ /* enable the mac transmit and receive paths now */ ++ OSL_DELAY(2); ++ cmdcfg &= ~CC_SR; ++ cmdcfg |= (CC_RE | CC_TE); ++ ++ /*2G_ENABLED: Enable Unimac at 2G mode */ ++/* #if 1 */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ cmdcfg |= 0xc; ++#endif ++ ++ /* assert rx_ena and tx_ena when out of reset to enable the mac */ ++ W_REG(ch->osh, ®s->cmdcfg, cmdcfg); ++ ++ /* request ht clock */ ++ OR_REG(ch->osh, ®s->clk_ctl_st, CS_FH); ++ ++ return; ++} ++ ++static void ++gmac_txflowcontrol(ch_t *ch, bool on) ++{ ++ uint32 cmdcfg; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put the mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* to enable tx flow control clear the rx pause ignore bit */ ++ if (on) ++ cmdcfg &= ~CC_RPI; ++ else ++ cmdcfg |= CC_RPI; ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++static void ++gmac_serdes_init(ch_t *ch) ++{ ++ uint32_t sdctl, sdstat0, sdstat1; ++ gmacregs_t *regs; ++ ++ regs = ch->regs; ++ ++ ET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdstat0 = R_REG(ch->osh, &ch->regs->serdes_status0); ++ sdstat1 = R_REG(ch->osh, &ch->regs->serdes_status1); ++ //printf("et%d: %s read sdstat0(0x%x); sdstat1(0x%x)\n", ch->etc->unit, __FUNCTION__, sdstat0, sdstat1); ++ ++ /* ++ * Bring up both digital and analog clocks ++ * ++ * NOTE: Many MAC registers are not accessible until the PLL is locked. ++ * An S-Channel timeout will occur before that. ++ */ ++ ++ sdctl = 0; ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ sdctl |= (SC_TX1G_FIFO_RST_VAL|SC_FORCE_SPD_STRAP_VAL|SC_REFSEL_VAL|SC_REF_TERM_SEL_MASK); ++#else ++ sdctl |= (SC_TX1G_FIFO_RST_VAL|SC_FORCE_SPD_STRAP_VAL|SC_REF_TERM_SEL_MASK); ++#endif /* (defined(CONFIG_MACH_HX4) */ ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ udelay(1000); ++ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl |= (SC_IDDQ_MASK|SC_PWR_DOWN_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl &= ~(SC_IDDQ_MASK|SC_PWR_DOWN_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ /* Bring hardware out of reset */ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl |= (SC_RSTB_HW_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ /* Bring MDIOREGS out of reset */ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl |= (SC_RSTB_MDIOREGS_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ udelay(1000); ++ ++ /* Bring PLL out of reset */ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl |= (SC_RSTB_PLL_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ udelay(1000); ++ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdstat0 = R_REG(ch->osh, &ch->regs->serdes_status0); ++ sdstat1 = R_REG(ch->osh, &ch->regs->serdes_status1); ++ //printf("et%d: %s read sdstat0(0x%x); sdstat1(0x%x)\n", ch->etc->unit, __FUNCTION__, sdstat0, sdstat1); ++ ++ return; ++} ++#endif ++ ++static void ++gmac_miiconfig(ch_t *ch) ++{ ++ /* BCM53010 GMAC DevStatus register has different definition of "Interface Mode" ++ * Bit 12:8 "interface_mode" This field is programmed through IDM control bits [6:2] ++ * ++ * Bit 0 : SOURCE_SYNC_MODE_EN - If set, Rx line clock input will be used by Unimac for ++ * sampling data.If this is reset, PLL reference clock (Clock 250 or Clk 125 based ++ * on CLK_250_SEL) will be used as receive side line clock. ++ * Bit 1 : DEST_SYNC_MODE_EN - If this is reset, PLL reference clock input (Clock 250 or ++ * Clk 125 based on CLK_250_SEL) will be used as transmit line clock. ++ * If this is set, TX line clock input (from external switch/PHY) is used as ++ * transmit line clock. ++ * Bit 2 : TX_CLK_OUT_INVERT_EN - If set, this will invert the TX clock out of AMAC. ++ * Bit 3 : DIRECT_GMII_MODE - If direct gmii is set to 0, then only 25 MHz clock needs to ++ * be fed at 25MHz reference clock input, for both 10/100 Mbps speeds. ++ * Unimac will internally divide the clock to 2.5 MHz for 10 Mbps speed ++ * Bit 4 : CLK_250_SEL - When set, this selects 250Mhz reference clock input and hence ++ * Unimac line rate will be 2G. ++ * If reset, this selects 125MHz reference clock input. ++ */ ++ if (IS_IPROC_CHIP_ID(CHIPID(ch->sih->chip))) { ++ if (ch->etc->forcespeed == ET_AUTO) ++#if defined(CONFIG_MACH_HR2) ++ gmac_speed(ch, ET_100FULL); ++#elif (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ /*2G_ENABLED: Enable Unimac at 2G mode */ ++ gmac_speed(ch, ET_2500FULL); ++#else ++ gmac_speed(ch, ET_1000FULL); ++#endif ++ else ++ gmac_speed(ch, ch->etc->forcespeed); ++ } ++} ++ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++void ++gmac_serdes_asym_mode(etc_info_t *etcptrs[]) ++{ ++ etc_info_t *etc; ++ ++ etc = etcptrs[0]; ++ ++ /* initialize serdes */ ++ gmac_serdes_init(etc->ch); ++ serdes_reset_core(etc->unit, etc->phyaddr); ++ ++ /* initialize lane 0 */ ++ //printk("et%d %s() phyaddr=%d, speed=%d, dpx=%d\n", etc->unit, __FUNCTION__, etc->phyaddr, etc->speed, etc->duplex); ++ serdes_set_asym_mode(etc->unit, etc->phyaddr); ++ serdes_init(etc->unit, etc->phyaddr); ++ serdes_speeddpx_set(etc->unit, etc->phyaddr, etc->speed, etc->duplex); ++ /* initialize lane 1 */ ++ etc = etcptrs[1]; ++ if (etc->linkstate) { ++ //printk("et%d %s() phyaddr=%d, speed=%d, dpx=%d\n", etc->unit, __FUNCTION__, etc->phyaddr, etc->speed, etc->duplex); ++ serdes_set_asym_mode(etc->unit, etc->phyaddr); ++ serdes_init(etc->unit, etc->phyaddr); ++ serdes_speeddpx_set(etc->unit, etc->phyaddr, etc->speed, etc->duplex); ++ } ++ ++ /* must init all serdes lanes, init port 49 (phy 3) */ ++ serdes_init(etc->unit, 3); ++ ++ /* start PLL */ ++ serdes_start_pll(etc->unit, 1); ++} ++#endif /* (!defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++ ++static void ++chipreset(ch_t *ch) ++{ ++ gmacregs_t *regs; ++ uint32 i, sflags, flagbits = 0; ++ ++ ET_TRACE(("et%d: chipreset\n", ch->etc->unit)); ++ ++ regs = ch->regs; ++ ++ if (!si_iscoreup(ch->sih)) { ++ /* power on reset: reset the enet core */ ++ goto chipinreset; ++ } ++ ++ /* Northstar, reset other three GMAC cores if needed */ ++ if (IS_IPROC_CHIP_ID(CHIPID(ch->sih->chip))) { ++ int ns_gmac; ++ for (ns_gmac = 0; ns_gmac < IPROC_NUM_GMACS; ns_gmac++) { ++ /* As northstar requirement, we have to reset all GAMCs before accessing them. ++ * et_probe() call pci_enable_device() for etx and do si_core_reset for GAMCx only. ++ * then the other three GAMC didn't reset. ++ * We do it here. ++ */ ++ si_setcore(ch->sih, GMAC_CORE_ID, ns_gmac); ++ if (!si_iscoreup(ch->sih)) { ++ ET_TRACE(("et%d: reset NorthStar GMAC[%d] core\n", ch->etc->unit, ns_gmac)); ++ si_core_reset(ch->sih, flagbits, 0); ++ } ++ } ++ si_setcore(ch->sih, GMAC_CORE_ID, 0); ++ } ++ ++ /* update software counters before resetting the chip */ ++ if (ch->mibgood) ++ chipstatsupd(ch); ++ ++ /* reset the tx dma engines */ ++ for (i = 0; i < NUMTXQ; i++) { ++ if (ch->di[i]) { ++ ET_TRACE(("et%d: resetting tx dma%d\n", ch->etc->unit, i)); ++ dma_txreset(ch->di[i]); ++ } ++ } ++ ++ /* set gmac into loopback mode to ensure no rx traffic */ ++ gmac_loopback(ch, LOOPBACK_MODE_MAC); ++ OSL_DELAY(1); ++ ++ /* reset the rx dma engine */ ++ if (ch->di[RX_Q0]) { ++ ET_TRACE(("et%d: resetting rx dma\n", ch->etc->unit)); ++ dma_rxreset(ch->di[RX_Q0]); ++ } ++ ++ /* clear the multicast filter table */ ++ gmac_mf_cleanup(ch); ++ ++chipinreset: ++ sflags = si_core_sflags(ch->sih, 0, 0); ++ if (sflags & SISF_SW_ATTACHED) { ++ ET_TRACE(("et%d: internal switch attached\n", ch->etc->unit)); ++ flagbits = SICF_SWCLKE; ++ if (!ch->etc->robo) { ++ ET_TRACE(("et%d: reseting switch\n", ch->etc->unit)); ++ flagbits |= SICF_SWRST; ++ } ++ } ++ ++ /* reset all GMAC cores */ ++ if (IS_IPROC_CHIP_ID(CHIPID(ch->sih->chip))) { ++ int ns_gmac; ++ for (ns_gmac = 0; ns_gmac < IPROC_NUM_GMACS; ns_gmac++) { ++ /* As northstar requirement, we have to reset all GAMCs before accessing them. ++ * et_probe() call pci_enable_device() for etx and do si_core_reset for GAMCx only. ++ * then the other three GAMC didn't reset. ++ * We do it here. ++ */ ++ si_setcore(ch->sih, GMAC_CORE_ID, ns_gmac); ++ if (!si_iscoreup(ch->sih)) { ++ ET_TRACE(("et%d: reset NorthStar GMAC[%d] core\n", ch->etc->unit, ns_gmac)); ++ si_core_reset(ch->sih, flagbits, 0); ++ } ++ } ++ si_setcore(ch->sih, GMAC_CORE_ID, 0); ++ } ++ ++ if ((sflags & SISF_SW_ATTACHED) && (!ch->etc->robo)) { ++ ET_TRACE(("et%d: taking switch out of reset\n", ch->etc->unit)); ++ si_core_cflags(ch->sih, SICF_SWRST, 0); ++ } ++ ++ /* reset gmac */ ++ gmac_reset(ch); ++ ++ /* clear mib */ ++ gmac_clearmib(ch); ++ ch->mibgood = TRUE; ++ ++ /* set mdc_transition_en */ ++ OR_REG(ch->osh, ®s->phycontrol, PC_MTE); ++ ++ /* Read the devstatus to figure out the configuration mode of ++ * the interface. Set the speed to 100 if the switch interface ++ * is mii/rmii. ++ */ ++ gmac_miiconfig(ch); ++ ++// /* gmac doesn't have internal phy */ ++// chipphyinit(ch, ch->etc->phyaddr); ++ ++ /* clear persistent sw intstatus */ ++ ch->intstatus = 0; ++} ++ ++/* ++ * Lookup a multicast address in the filter hash table. ++ */ ++static int ++gmac_mf_lkup(ch_t *ch, struct ether_addr *mcaddr) ++{ ++ mflist_t *ptr; ++ ++ /* find the multicast address */ ++ for (ptr = ch->mf.bucket[GMAC_MCADDR_HASH(mcaddr)]; ptr != NULL; ptr = ptr->next) { ++ if (!ETHER_MCADDR_CMP(&ptr->mc_addr, mcaddr)) ++ return (SUCCESS); ++ } ++ ++ return (FAILURE); ++} ++ ++/* ++ * Add a multicast address to the filter hash table. ++ */ ++static int ++gmac_mf_add(ch_t *ch, struct ether_addr *mcaddr) ++{ ++ uint32 hash; ++ mflist_t *entry; ++#ifdef BCMDBG ++ char mac[ETHER_ADDR_STR_LEN]; ++#endif /* BCMDBG */ ++ ++ /* add multicast addresses only */ ++ if (!ETHER_ISMULTI(mcaddr)) { ++ ET_ERROR(("et%d: adding invalid multicast address %s\n", ++ ch->etc->unit, bcm_ether_ntoa(mcaddr, mac))); ++ return (FAILURE); ++ } ++ ++ /* discard duplicate add requests */ ++ if (gmac_mf_lkup(ch, mcaddr) == SUCCESS) { ++ ET_ERROR(("et%d: adding duplicate mcast filter entry\n", ch->etc->unit)); ++ return (FAILURE); ++ } ++ ++ /* allocate memory for list entry */ ++ entry = MALLOC(ch->osh, sizeof(mflist_t)); ++ if (entry == NULL) { ++ ET_ERROR(("et%d: out of memory allocating mcast filter entry\n", ch->etc->unit)); ++ return (FAILURE); ++ } ++ ++ /* add the entry to the hash bucket */ ++ ether_copy(mcaddr, &entry->mc_addr); ++ hash = GMAC_MCADDR_HASH(mcaddr); ++ entry->next = ch->mf.bucket[hash]; ++ ch->mf.bucket[hash] = entry; ++ ++ return (SUCCESS); ++} ++ ++/* ++ * Cleanup the multicast filter hash table. ++ */ ++static void ++gmac_mf_cleanup(ch_t *ch) ++{ ++ mflist_t *ptr, *tmp; ++ int32 i; ++ ++ for (i = 0; i < GMAC_HASHT_SIZE; i++) { ++ ptr = ch->mf.bucket[i]; ++ while (ptr) { ++ tmp = ptr; ++ ptr = ptr->next; ++ MFREE(ch->osh, tmp, sizeof(mflist_t)); ++ } ++ ch->mf.bucket[i] = NULL; ++ } ++} ++ ++/* ++ * Initialize all the chip registers. If dma mode, init tx and rx dma engines ++ * but leave the devcontrol tx and rx (fifos) disabled. ++ */ ++static void ++chipinit(ch_t *ch, uint options) ++{ ++ etc_info_t *etc; ++ gmacregs_t *regs; ++ uint idx; ++ uint i; ++#ifdef CONFIG_BCM_CUSTOM_RECVFILE_MAX_PERF ++ uint bp_clk; ++ uint32_t fpi = 8; ++#endif ++ ++ regs = ch->regs; ++ etc = ch->etc; ++ idx = 0; ++ ++ ET_TRACE(("et%d: chipinit\n", etc->unit)); ++ ++#ifdef CONFIG_BCM_CUSTOM_RECVFILE_MAX_PERF ++ /* enable rx lazy interrupt. set frame count and timeout */ ++ bp_clk = si_clock(ch->sih) / 1000000; ++ W_REG(ch->osh, ®s->intrecvlazy, (fpi << IRL_FC_SHIFT) | (48 * bp_clk)); ++#else ++ /* enable one rx interrupt per received frame */ ++ W_REG(ch->osh, ®s->intrecvlazy, (1 << IRL_FC_SHIFT)); ++#endif ++ ++ /* enable 802.3x tx flow control (honor received PAUSE frames) */ ++ gmac_txflowcontrol(ch, TRUE); ++ ++ /* enable/disable promiscuous mode */ ++ gmac_promisc(ch, etc->promisc); ++ ++ /* set our local address */ ++ W_REG(ch->osh, ®s->macaddrhigh, ++ hton32(*(uint32 *)&etc->cur_etheraddr.octet[0])); ++ W_REG(ch->osh, ®s->macaddrlow, ++ hton16(*(uint16 *)&etc->cur_etheraddr.octet[4])); ++ ++ if (!etc->promisc) { ++ /* gmac doesn't have a cam, hence do the multicast address filtering ++ * in the software ++ */ ++ /* allmulti or a list of discrete multicast addresses */ ++ if (!etc->allmulti && etc->nmulticast) ++ for (i = 0; i < etc->nmulticast; i++) ++ (void)gmac_mf_add(ch, &etc->multicast[i]); ++ } ++ ++ /* optionally enable mac-level loopback */ ++ if (etc->loopbk) ++ gmac_loopback(ch, LOOPBACK_MODE_MAC); ++ else ++ gmac_loopback(ch, LOOPBACK_MODE_NONE); ++ ++ /* set max frame lengths - account for possible vlan tag */ ++ W_REG(ch->osh, ®s->rxmaxlength, BCM_ETHER_MAX_LEN); ++ ++ /* ++ * Optionally, disable phy autonegotiation and force our speed/duplex ++ * or constrain our advertised capabilities. ++ */ ++ if (etc->forcespeed != ET_AUTO) { ++ gmac_speed(ch, etc->forcespeed); ++ chipphyforce(ch, etc->phyaddr); ++ } else if (etc->advertise && etc->needautoneg) ++ chipphyadvertise(ch, etc->phyaddr); ++ ++ /* enable the overflow continue feature and disable parity */ ++ dma_ctrlflags(ch->di[0], DMA_CTRL_ROC | DMA_CTRL_PEN /* mask */, ++ DMA_CTRL_ROC /* value */); ++ ++ if (options & ET_INIT_FULL) { ++ /* initialize the tx and rx dma channels */ ++ for (i = 0; i < NUMTXQ; i++) ++ dma_txinit(ch->di[i]); ++ dma_rxinit(ch->di[RX_Q0]); ++ ++ /* post dma receive buffers */ ++ dma_rxfill(ch->di[RX_Q0]); ++ ++ /* lastly, enable interrupts */ ++ if (options & ET_INIT_INTRON) ++ et_intrson(etc->et); ++ } ++ else ++ dma_rxenable(ch->di[RX_Q0]); ++ ++ /* turn on the emac */ ++ gmac_enable(ch); ++} ++ ++/* dma transmit */ ++static bool BCMFASTPATH ++chiptx(ch_t *ch, void *p0) ++{ ++ int error, len; ++ uint32 q = TX_Q0; ++ ++ ET_TRACE(("et%d: chiptx\n", ch->etc->unit)); ++ ET_LOG("et%d: chiptx", ch->etc->unit, 0); ++ ++ len = PKTLEN(ch->osh, p0); ++ ++ /* check tx max length */ ++ if (len > BCM_ETHER_MAX_LEN) { ++ ET_ERROR(("et%d: chiptx: max frame length exceeded\n", ++ ch->etc->unit)); ++ PKTFREE(ch->osh, p0, TRUE); ++ return FALSE; ++ } ++ ++ if ((len < GMAC_MIN_FRAMESIZE) && (ch->etc->corerev == 0)) ++ PKTSETLEN(ch->osh, p0, GMAC_MIN_FRAMESIZE); ++ ++#if defined(CONFIG_MACH_NS) ++ /* queue the packet based on its priority */ ++#ifdef GMAC3 ++ //q = (ch->etc->txQId++) % NUMTXQ; ++ //q = ch->etc->unit; ++ if (DEV_FWDER(ch->etc)) { ++ q = TX_Q0; ++ } else { ++ if (ch->etc->qos) ++ q = etc_up2tc(PKTPRIO(p0)); ++ else ++ q = TX_Q0; ++ } ++#else /* !GMAC3 */ ++ if (ch->etc->qos) ++ q = etc_up2tc(PKTPRIO(p0)); ++#endif /* !GMAC3 */ ++#endif /* defined(CONFIG_MACH_NS) */ ++ ++ ASSERT(q < NUMTXQ); ++ ++ /* if tx completion intr is disabled then do the reclaim ++ * once every few frames transmitted. ++ */ ++ if ((ch->etc->txframes[q] & ch->etc->txrec_thresh) == 1) ++ dma_txreclaim(ch->di[q], HNDDMA_RANGE_TRANSMITTED); ++ ++ error = dma_txfast(ch->di[q], p0, TRUE); ++ ++ if (error) { ++ ET_ERROR(("et%d: chiptx: out of txds\n", ch->etc->unit)); ++ ch->etc->txnobuf++; ++ return FALSE; ++ } ++ ++ ch->etc->txframes[q]++; ++ ++ if ((len < GMAC_MIN_FRAMESIZE) && (ch->etc->corerev == 0)) { ++ if (skb_is_nonlinear((struct sk_buff*)p0)) ++ printk("Modified nonlinear skb (et_ctf_pipeline_loopback) - not calling skb_trim\n"); ++ else ++ /* set back the orig length */ ++ PKTSETLEN(ch->osh, p0, len); ++ } ++ ++ return TRUE; ++} ++ ++/* reclaim completed transmit descriptors and packets */ ++static void BCMFASTPATH ++chiptxreclaim(ch_t *ch, bool forceall) ++{ ++ int32 i; ++ ++ ET_TRACE(("et%d: chiptxreclaim\n", ch->etc->unit)); ++ ++ for (i = 0; i < NUMTXQ; i++) { ++ dma_txreclaim(ch->di[i], forceall ? HNDDMA_RANGE_ALL : HNDDMA_RANGE_TRANSMITTED); ++ ch->intstatus &= ~(I_XI0 << i); ++ } ++} ++ ++/* dma receive: returns a pointer to the next frame received, or NULL if there are no more */ ++static void * BCMFASTPATH ++chiprx(ch_t *ch) ++{ ++ void *p; ++ struct ether_addr *da; ++ ++ ET_TRACE(("et%d: chiprx\n", ch->etc->unit)); ++ ET_LOG("et%d: chiprx", ch->etc->unit, 0); ++ ++ if (dma_rxstopped(ch->di[RX_Q0])) { ++ ch->etc->rxdmastopped++; ++ } ++ ++ /* gmac doesn't have a cam to do address filtering. so we implement ++ * the multicast address filtering here. ++ */ ++ while ((p = dma_rx(ch->di[RX_Q0])) != NULL) { ++ /* check for overflow error packet */ ++ if (RXH_FLAGS(ch->etc, PKTDATA(ch->osh, p)) & GRXF_OVF) { ++ PKTFREE(ch->osh, p, FALSE); ++ ch->etc->rxoflodiscards++; ++ continue; ++ } ++ ++#ifdef GMAC_RATE_LIMITING ++ /* rate limiting */ ++ //printf("et%d: chiprx RXH_PT(0x%x)\n", ch->etc->unit, RXH_PT(ch->etc, PKTDATA(ch->osh, p))); ++ if (ch->etc->rl_stopping_broadcasts) { ++ /* check if broadcast packet */ ++ if (RXH_PT(ch->etc, PKTDATA(ch->osh, p)) == 2) { ++ /* broadcast packet */ ++ PKTFREE(ch->osh, p, FALSE); ++ ch->etc->rl_dropped_bc_packets++; ++ ch->etc->rl_dropped_packets++; ++ continue; ++ } ++ } else if (ch->etc->rl_stopping_all_packets) { ++ PKTFREE(ch->osh, p, FALSE); ++ ch->etc->rl_dropped_all_packets++; ++ ch->etc->rl_dropped_packets++; ++ continue; ++ } ++#endif /* GMAC_RATE_LIMITING */ ++ ++ if (ch->etc->allmulti) { ++ return (p); ++ } ++ else { ++ /* skip the rx header */ ++ PKTPULL(ch->osh, p, HWRXOFF); ++ ++ /* do filtering only for multicast packets when allmulti is false */ ++ da = (struct ether_addr *)PKTDATA(ch->osh, p); ++ if (!ETHER_ISMULTI(da) || ++ (gmac_mf_lkup(ch, da) == SUCCESS) || ETHER_ISBCAST(da)) { ++ PKTPUSH(ch->osh, p, HWRXOFF); ++ return (p); ++ } ++ PKTFREE(ch->osh, p, FALSE); ++ } ++ } ++ ++ ch->intstatus &= ~I_RI; ++ ++ /* post more rx buffers since we consumed a few */ ++ dma_rxfill(ch->di[RX_Q0]); ++ ++ return (NULL); ++} ++ ++/* reclaim completed dma receive descriptors and packets */ ++static void ++chiprxreclaim(ch_t *ch) ++{ ++ ET_TRACE(("et%d: chiprxreclaim\n", ch->etc->unit)); ++ dma_rxreclaim(ch->di[RX_Q0]); ++ ch->intstatus &= ~I_RI; ++} ++ ++/* allocate and post dma receive buffers */ ++static void BCMFASTPATH ++chiprxfill(ch_t *ch) ++{ ++ ET_TRACE(("et%d: chiprxfill\n", ch->etc->unit)); ++ ET_LOG("et%d: chiprxfill", ch->etc->unit, 0); ++ dma_rxfill(ch->di[RX_Q0]); ++} ++ ++ ++/* get current and pending interrupt events */ ++static int BCMFASTPATH ++chipgetintrevents(ch_t *ch, bool in_isr) ++{ ++ uint32 intstatus; ++ int events; ++ ++ events = 0; ++ ++ /* read the interrupt status register */ ++ intstatus = R_REG(ch->osh, &ch->regs->intstatus); ++ ++ /* defer unsolicited interrupts */ ++ intstatus &= (in_isr ? ch->intmask : ch->def_intmask); ++ ++ if (intstatus != 0) ++ events = INTR_NEW; ++ ++ /* or new bits into persistent intstatus */ ++ intstatus = (ch->intstatus |= intstatus); ++ ++ /* return if no events */ ++ if (intstatus == 0) ++ return (0); ++ ++ /*check_errs(ch);*/ ++ ++ /* convert chip-specific intstatus bits into generic intr event bits */ ++ if (intstatus & I_RI) ++ events |= INTR_RX; ++ if (intstatus & (I_XI0 | I_XI1 | I_XI2 | I_XI3)) ++ events |= INTR_TX; ++ if (intstatus & I_ERRORS) ++ events |= INTR_ERROR; ++ ++ return (events); ++} ++ ++/* enable chip interrupts */ ++static void BCMFASTPATH ++chipintrson(ch_t *ch) ++{ ++ ch->intmask = ch->def_intmask; ++ W_REG(ch->osh, &ch->regs->intmask, ch->intmask); ++} ++ ++/* disable chip interrupts */ ++static void BCMFASTPATH ++chipintrsoff(ch_t *ch) ++{ ++ /* disable further interrupts from gmac */ ++ W_REG(ch->osh, &ch->regs->intmask, 0); ++ (void) R_REG(ch->osh, &ch->regs->intmask); /* sync readback */ ++ ch->intmask = 0; ++ ++ /* clear the interrupt conditions */ ++ W_REG(ch->osh, &ch->regs->intstatus, ch->intstatus); ++} ++ ++/* return true of caller should re-initialize, otherwise false */ ++static bool BCMFASTPATH ++chiperrors(ch_t *ch) ++{ ++ uint32 intstatus; ++ etc_info_t *etc; ++ ++ etc = ch->etc; ++ ++ intstatus = ch->intstatus; ++ ch->intstatus &= ~(I_ERRORS); ++ ++ ET_TRACE(("et%d: chiperrors: intstatus 0x%x\n", etc->unit, intstatus)); ++ ++ if (intstatus & I_PDEE) { ++ ET_ERROR(("et%d: descriptor error\n", etc->unit)); ++ etc->dmade++; ++ } ++ ++ if (intstatus & I_PDE) { ++ ET_ERROR(("et%d: data error\n", etc->unit)); ++ etc->dmada++; ++ } ++ ++ if (intstatus & I_DE) { ++ ET_ERROR(("et%d: descriptor protocol error\n", etc->unit)); ++ etc->dmape++; ++ } ++ ++ if (intstatus & I_RDU) { ++ ET_ERROR(("et%d: receive descriptor underflow\n", etc->unit)); ++ etc->rxdmauflo++; ++ } ++ ++ if (intstatus & I_RFO) { ++ ET_TRACE(("et%d: receive fifo overflow\n", etc->unit)); ++ etc->rxoflo++; ++ } ++ ++ if (intstatus & I_XFU) { ++ ET_ERROR(("et%d: transmit fifo underflow\n", etc->unit)); ++ etc->txuflo++; ++ } ++ ++ /* if overflows or decriptors underflow, don't report it ++ * as an error and provoque a reset ++ */ ++ if (intstatus & ~(I_RDU | I_RFO) & I_ERRORS) ++ return (TRUE); ++ ++ return (FALSE); ++} ++ ++static void ++chipstatsupd(ch_t *ch) ++{ ++ etc_info_t *etc; ++ gmacregs_t *regs; ++ volatile uint32 *s; ++ uint32 *d; ++ ++ etc = ch->etc; ++ regs = ch->regs; ++ ++ /* read the mib counters and update the driver maintained software ++ * counters. ++ */ ++ if (etc->corerev != GMAC_4706B0_CORE_REV) { ++ OR_REG(ch->osh, ®s->devcontrol, DC_MROR); ++ for (s = ®s->mib.tx_good_octets, d = &ch->mib.tx_good_octets; ++ s <= ®s->mib.rx_uni_pkts; s++, d++) { ++ *d += R_REG(ch->osh, s); ++ if (s == &ch->regs->mib.tx_q3_octets_high) { ++ s++; ++ d++; ++ } ++ } ++ } ++ ++ ++ /* ++ * Aggregate transmit and receive errors that probably resulted ++ * in the loss of a frame are computed on the fly. ++ * ++ * We seem to get lots of tx_carrier_lost errors when flipping ++ * speed modes so don't count these as tx errors. ++ * ++ * Arbitrarily lump the non-specific dma errors as tx errors. ++ */ ++ etc->txerror = ch->mib.tx_jabber_pkts + ch->mib.tx_oversize_pkts ++ + ch->mib.tx_underruns + ch->mib.tx_excessive_cols ++ + ch->mib.tx_late_cols + etc->txnobuf + etc->dmade ++ + etc->dmada + etc->dmape + etc->txuflo; ++ etc->rxerror = ch->mib.rx_jabber_pkts + ch->mib.rx_oversize_pkts ++ + ch->mib.rx_missed_pkts + ch->mib.rx_crc_align_errs ++ + ch->mib.rx_undersize + ch->mib.rx_crc_errs ++ + ch->mib.rx_align_errs + ch->mib.rx_symbol_errs ++ + etc->rxnobuf + etc->rxdmauflo + etc->rxoflo + etc->rxbadlen; ++ etc->rxgiants = (ch->di[RX_Q0])->rxgiants; ++} ++ ++static void ++chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear) ++{ ++ gmacmib_t *m; ++ ++ m = &ch->mib; ++ ++ if (clear) { ++ bzero((char *)m, sizeof(gmacmib_t)); ++ return; ++ } ++ ++ bcm_bprintf(b, "tx_broadcast_pkts %d tx_multicast_pkts %d tx_jabber_pkts %d " ++ "tx_oversize_pkts %d\n", ++ m->tx_broadcast_pkts, m->tx_multicast_pkts, ++ m->tx_jabber_pkts, ++ m->tx_oversize_pkts); ++ bcm_bprintf(b, "tx_fragment_pkts %d tx_underruns %d\n", ++ m->tx_fragment_pkts, m->tx_underruns); ++ bcm_bprintf(b, "tx_total_cols %d tx_single_cols %d tx_multiple_cols %d " ++ "tx_excessive_cols %d\n", ++ m->tx_total_cols, m->tx_single_cols, m->tx_multiple_cols, ++ m->tx_excessive_cols); ++ bcm_bprintf(b, "tx_late_cols %d tx_defered %d tx_carrier_lost %d tx_pause_pkts %d\n", ++ m->tx_late_cols, m->tx_defered, m->tx_carrier_lost, ++ m->tx_pause_pkts); ++ ++ /* receive stat counters */ ++ /* hardware mib pkt and octet counters wrap too quickly to be useful */ ++ bcm_bprintf(b, "rx_broadcast_pkts %d rx_multicast_pkts %d rx_jabber_pkts %d " ++ "rx_oversize_pkts %d\n", ++ m->rx_broadcast_pkts, m->rx_multicast_pkts, ++ m->rx_jabber_pkts, m->rx_oversize_pkts); ++ bcm_bprintf(b, "rx_fragment_pkts %d rx_missed_pkts %d rx_crc_align_errs %d " ++ "rx_undersize %d\n", ++ m->rx_fragment_pkts, m->rx_missed_pkts, ++ m->rx_crc_align_errs, m->rx_undersize); ++ bcm_bprintf(b, "rx_crc_errs %d rx_align_errs %d rx_symbol_errs %d\n", ++ m->rx_crc_errs, m->rx_align_errs, m->rx_symbol_errs); ++ bcm_bprintf(b, "rx_pause_pkts %d rx_nonpause_pkts %d\n", ++ m->rx_pause_pkts, m->rx_nonpause_pkts); ++} ++ ++void ++etc_chip_mib(etc_info_t *etc) ++{ ++ uint32 *d; ++ ch_t *ch = (ch_t*)etc->ch; ++ ++ chipstatsupd(ch); ++ printk("et%d: txframe:0x%x, txbyte:0x%x txerror:0x%x\n", ch->etc->unit, ++ ch->etc->txframe, ch->etc->txbyte, ch->etc->txerror); ++ printk("et%d: rxframe:0x%x, rxbyte:0x%x rxerror:0x%x\n", ch->etc->unit, ++ ch->etc->rxframe, ch->etc->rxbyte, ch->etc->rxerror); ++ printk("et%d: RXDMA: ctrl(0x%x), ptr(0x%x), addrl(0x%x), addrh(0x%x) st0(0x%x), st1(0x%x)\n", ++ ch->etc->unit, ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.control), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.ptr), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.addrlow), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.addrhigh), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.status0), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.status1)); ++ ++ /* clear counters */ ++ for (d = &ch->mib.tx_good_octets; d <= &ch->mib.rx_uni_pkts; d++) { ++ *d = 0; ++ if (d == &ch->mib.tx_q3_octets_high) { ++ d++; ++ } ++ } ++} ++ ++static void ++chipenablepme(ch_t *ch) ++{ ++ return; ++} ++ ++static void ++chipdisablepme(ch_t *ch) ++{ ++ return; ++} ++ ++static void ++chipduplexupd(ch_t *ch) ++{ ++ uint32 cmdcfg; ++ int32 duplex, speed; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* check if duplex mode changed */ ++ if (ch->etc->duplex && (cmdcfg & CC_HD)) ++ duplex = 0; ++ else if (!ch->etc->duplex && ((cmdcfg & CC_HD) == 0)) ++ duplex = CC_HD; ++ else ++ duplex = -1; ++ ++ /* check if the speed changed */ ++ speed = ((cmdcfg & CC_ES_MASK) >> CC_ES_SHIFT); ++ if ((ch->etc->speed == 1000) && (speed != 2)) ++ speed = 2; ++ else if ((ch->etc->speed == 100) && (speed != 1)) ++ speed = 1; ++ else if ((ch->etc->speed == 10) && (speed != 0)) ++ speed = 0; ++ else ++ speed = -1; ++ ++ /* no duplex or speed change required */ ++ if ((speed == -1) && (duplex == -1)) { ++ return; ++ } ++ ++ /* update the speed */ ++ if (speed != -1) { ++ cmdcfg &= ~CC_ES_MASK; ++ cmdcfg |= (speed << CC_ES_SHIFT); ++ } ++ ++ /* update the duplex mode */ ++ if (duplex != -1) { ++ cmdcfg &= ~CC_HD; ++ cmdcfg |= duplex; ++ } ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ cmdcfg |= CC_AE; ++#endif ++ ++ ET_TRACE(("chipduplexupd: updating speed & duplex %x\n", cmdcfg)); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++static void ++chipforcespddpx(ch_t *ch) ++{ ++ uint32 cmdcfg; ++ int32 duplex=0, speed; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* set duplex */ ++ if (!ch->etc->duplex) ++ duplex = CC_HD; ++ ++ /* set speed */ ++ if (ch->etc->speed == 10) ++ speed = 0; ++ else if (ch->etc->speed == 100) ++ speed = 1; ++ else ++ speed = 2; ++ ++ /* update the speed */ ++ cmdcfg &= ~CC_ES_MASK; ++ cmdcfg |= (speed << CC_ES_SHIFT); ++ ++ /* update the duplex mode */ ++ cmdcfg &= ~CC_HD; ++ cmdcfg |= duplex; ++ ++ ET_TRACE(("chipforcespddpx: forcing speed & duplex %x\n", cmdcfg)); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++ ++ if (ch->etc->up) { ++ serdes_speeddpx_set(ch->etc->unit, ch->etc->phyaddr, ch->etc->speed, ch->etc->duplex); ++ } ++} ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++ ++static uint16 ++chipphyrd(ch_t *ch, uint phyaddr, uint reg) ++{ ++ uint32 tmp = 0xffffffff; ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ gmacregs_t *regs; ++ uint32 *phycontrol_addr, *phyaccess_addr; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ASSERT(reg < MAXPHYREG); ++ ++ regs = ch->regs; ++ ++ phycontrol_addr = (uint32 *)®s->phycontrol; ++ phyaccess_addr = (uint32 *)®s->phyaccess; ++ ++ /* issue the read */ ++ tmp = R_REG(ch->osh, phycontrol_addr); ++ tmp &= ~0x1f; ++ tmp |= phyaddr; ++ W_REG(ch->osh, phycontrol_addr, tmp); ++ W_REG(ch->osh, phyaccess_addr, ++ (PA_START | (phyaddr << PA_ADDR_SHIFT) | (reg << PA_REG_SHIFT))); ++ ++ /* wait for it to complete */ ++ SPINWAIT((R_REG(ch->osh, phyaccess_addr) & PA_START), 1000); ++ tmp = R_REG(ch->osh, phyaccess_addr); ++ if (tmp & PA_START) { ++ ET_ERROR(("et%d: chipphyrd: did not complete\n", ch->etc->unit)); ++ tmp = 0xffff; ++ } ++#endif /* (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ uint32 addr, int_bus, bank, flags; ++ uint16 tmp16; ++ ++ addr = phyaddr&0xf; ++ int_bus = phyaddr&0xf0; ++ bank = (phyaddr&0x1f00)>>8; ++ flags = (phyaddr&0x10000)?SOC_PHY_REG_1000X:0; ++ ++ if (int_bus) { ++ /* internal serdes */ ++ tmp = serdes_rd_reg(ch->etc->unit, addr, reg); ++ } else { ++ /* external phy */ ++ phy5461_rd_reg(ch->etc->unit, addr, flags, bank, reg, &tmp16); ++ tmp = tmp16; ++ } ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#if defined(CONFIG_MACH_HR2) ++ uint32 addr, bank; ++ uint16 tmp16; ++ ++ addr = phyaddr&0xf; ++ bank = (phyaddr&0x1f00)>>8; ++ ++ phy5221_rd_reg(ch->etc->unit, addr, bank, reg, &tmp16); ++ tmp = tmp16; ++#endif /* defined(CONFIG_MACH_HR2) */ ++ ++ return (tmp & PA_DATA_MASK); ++} ++ ++static void ++chipphywr(ch_t *ch, uint phyaddr, uint reg, uint16 v) ++{ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ uint32 tmp; ++ gmacregs_t *regs; ++ uint32 *phycontrol_addr, *phyaccess_addr; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ASSERT(reg < MAXPHYREG); ++ ++ regs = ch->regs; ++ ++ phycontrol_addr = (uint32 *)®s->phycontrol; ++ phyaccess_addr = (uint32 *)®s->phyaccess; ++ ++ /* clear mdioint bit of intstatus first */ ++ tmp = R_REG(ch->osh, phycontrol_addr); ++ tmp &= ~0x1f; ++ tmp |= phyaddr; ++ W_REG(ch->osh, phycontrol_addr, tmp); ++ W_REG(ch->osh, ®s->intstatus, I_MDIO); ++ ASSERT((R_REG(ch->osh, ®s->intstatus) & I_MDIO) == 0); ++ ++ /* issue the write */ ++ W_REG(ch->osh, phyaccess_addr, ++ (PA_START | PA_WRITE | (phyaddr << PA_ADDR_SHIFT) | (reg << PA_REG_SHIFT) | v)); ++ ++ /* wait for it to complete */ ++ SPINWAIT((R_REG(ch->osh, phyaccess_addr) & PA_START), 1000); ++ if (R_REG(ch->osh, phyaccess_addr) & PA_START) { ++ ET_ERROR(("et%d: chipphywr: did not complete\n", ch->etc->unit)); ++ } ++#endif /* (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ uint32 addr, int_bus, bank, flags; ++ ++ addr = phyaddr&0xf; ++ int_bus = phyaddr&0xf0; ++ bank = (phyaddr&0x1f00)>>8; ++ flags = (phyaddr&0x10000)?SOC_PHY_REG_1000X:0; ++ ++ if (int_bus) { ++ /* internal serdes */ ++ serdes_wr_reg(ch->etc->unit, addr, reg, v); ++ } else { ++ /* external phy */ ++ phy5461_wr_reg(ch->etc->unit, addr, flags, bank, reg, &v); ++ } ++#endif ++#if defined(CONFIG_MACH_HR2) ++ uint32 addr, bank; ++ ++ addr = phyaddr&0xf; ++ bank = (phyaddr&0x1f00)>>8; ++ ++ phy5221_wr_reg(ch->etc->unit, addr, bank, reg, &v); ++ ++#endif /* defined(CONFIG_MACH_HR2) */ ++} ++ ++static void ++chipphyor(ch_t *ch, uint phyaddr, uint reg, uint16 v) ++{ ++ uint16 tmp; ++ ++ tmp = chipphyrd(ch, phyaddr, reg); ++ tmp |= v; ++ chipphywr(ch, phyaddr, reg, tmp); ++} ++ ++static void ++chipphyreset(ch_t *ch, uint phyaddr) ++{ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ ET_TRACE(("et%d: chipphyreset: phyaddr %d\n", ch->etc->unit, phyaddr)); ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ chipphywr(ch, phyaddr, 0, CTL_RESET); ++ OSL_DELAY(100); ++ if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) { ++ ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit)); ++ } ++#endif /* (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ chipphywr(ch, phyaddr, 0, CTL_RESET); ++ OSL_DELAY(100); ++ if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) { ++ ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit)); ++ } ++ serdes_reset(ch->etc->unit, phyaddr); ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#if defined(CONFIG_MACH_HR2) ++ chipphywr(ch, phyaddr, 0, CTL_RESET); ++ OSL_DELAY(100); ++ if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) { ++ ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit)); ++ } ++#endif /* defined(CONFIG_MACH_HR2) */ ++ ++ chipphyinit(ch, phyaddr); ++} ++ ++static void ++chipphyinit(ch_t *ch, uint phyaddr) ++{ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ ET_TRACE(("et%d: chipphyinit: phyaddr %d\n", ch->etc->unit, phyaddr)); ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ phy5461_init(ch->etc->unit, phyaddr); ++ serdes_init(ch->etc->unit, phyaddr); ++ if (gmac_last_interface(ch->etc->unit)) { ++ /* must init all serdes lanes, init port 49 (phy 3) */ ++ serdes_init(ch->etc->unit, 3); ++ serdes_start_pll(ch->etc->unit, 1); ++ } ++#elif defined(CONFIG_MACH_HR2) ++ phy5221_init(ch->etc->unit, phyaddr); ++#endif ++ ++} ++ ++static void ++chipphyforce(ch_t *ch, uint phyaddr) ++{ ++ etc_info_t *etc; ++ uint16 ctl; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ etc = ch->etc; ++ ++ if (etc->forcespeed == ET_AUTO) ++ return; ++ ++ ET_TRACE(("et%d: chipphyforce: phyaddr %d speed %d\n", ++ ch->etc->unit, phyaddr, etc->forcespeed)); ++ ++ ctl = chipphyrd(ch, phyaddr, 0); ++ ctl &= ~(CTL_SPEED | CTL_SPEED_MSB | CTL_ANENAB | CTL_DUPLEX); ++ ++ switch (etc->forcespeed) { ++ case ET_10HALF: ++ break; ++ ++ case ET_10FULL: ++ ctl |= CTL_DUPLEX; ++ break; ++ ++ case ET_100HALF: ++ ctl |= CTL_SPEED_100; ++ break; ++ ++ case ET_100FULL: ++ ctl |= (CTL_SPEED_100 | CTL_DUPLEX); ++ break; ++ ++ case ET_1000FULL: ++ ctl |= (CTL_SPEED_1000 | CTL_DUPLEX); ++ break; ++ } ++ ++ chipphywr(ch, phyaddr, 0, ctl); ++} ++ ++/* set selected capability bits in autonegotiation advertisement */ ++static void ++chipphyadvertise(ch_t *ch, uint phyaddr) ++{ ++ etc_info_t *etc; ++ uint16 adv, adv2; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ etc = ch->etc; ++ ++ if ((etc->forcespeed != ET_AUTO) || !etc->needautoneg) ++ return; ++ ++ ASSERT(etc->advertise); ++ ++ ET_TRACE(("et%d: chipphyadvertise: phyaddr %d advertise %x\n", ++ ch->etc->unit, phyaddr, etc->advertise)); ++ ++ /* reset our advertised capabilitity bits */ ++ adv = chipphyrd(ch, phyaddr, 4); ++ adv &= ~(ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); ++ adv |= etc->advertise; ++ adv |= ADV_PAUSE; ++ chipphywr(ch, phyaddr, 4, adv); ++ ++ adv2 = chipphyrd(ch, phyaddr, 9); ++ adv2 &= ~(ADV_1000FULL | ADV_1000HALF); ++ adv2 |= etc->advertise2; ++ chipphywr(ch, phyaddr, 9, adv2); ++ ++ ET_TRACE(("et%d: chipphyadvertise: phyaddr %d adv %x adv2 %x phyad0 %x\n", ++ ch->etc->unit, phyaddr, adv, adv2, chipphyrd(ch, phyaddr, 0))); ++ ++ /* restart autonegotiation */ ++ chipphyor(ch, phyaddr, 0, CTL_RESTART); ++ etc->needautoneg = FALSE; ++} ++ ++static void ++chipphyenable(ch_t *ch, uint eth_num, uint phyaddr, int enable) ++{ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ phy5461_enable_set(eth_num, phyaddr, enable); ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#if defined(CONFIG_MACH_HR2) ++ phy5221_enable_set(eth_num, phyaddr, enable); ++#endif /* defined(CONFIG_MACH_HR2) */ ++} ++ ++#ifdef GMAC_RATE_LIMITING ++void ++etc_check_rate_limiting(etc_info_t *etc, void *pch) ++{ ++ ch_t *ch = (ch_t*)pch; ++ uint32 timediff, bc_pkt_count, all_pkt_count; ++ ++ timediff = ((long)jiffies - (long)(etc->rl_prior_jiffies)); ++ if ((timediff>>5) != 0) { ++ /* 32 or more jiffies have gone by; see if we're seeing too ++ many packets */ ++ if ((timediff>>5) == 1) { ++ /* 32-63 jiffies elapsed */ ++ bc_pkt_count = R_REG(ch->osh, &ch->regs->mib.rx_broadcast_pkts); ++ all_pkt_count = R_REG(ch->osh, &ch->regs->mib.rx_good_pkts); ++ /* account for the dropped broadcast packets */ ++ all_pkt_count -= etc->rl_dropped_bc_packets; ++ ++ if (((bc_pkt_count>>10) != 0) && !(etc->rl_stopping_broadcasts)) { ++ /* 1K or more broadcast packets have arrived in 32-63 jiffies; try to throttle back the incoming packets */ ++ etc->rl_stopping_broadcasts = 1; ++ printf("et%d: %s: stopping broadcasts bc_pkt_count(0x%x)\n", ++ etc->unit, __FUNCTION__, bc_pkt_count); ++ if (!timer_pending(&etc->rl_timer)) { ++ etc->rl_timer.expires = jiffies + HZ; ++ add_timer(&etc->rl_timer); ++ etc->rl_set=TRUE; ++ } ++ } ++ } ++ etc->rl_prior_jiffies = jiffies; ++ } ++} ++#endif /* GMAC_RATE_LIMITING */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.h b/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.h +new file mode 100755 +index 0000000..395de4b +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.h +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Gigabit Ethernet MAC defines. ++ * ++ * $Id: etcgmac.h 267700 2011-06-19 15:41:07Z $ ++ */ ++#ifndef _etcgmac_h_ ++#define _etcgmac_h_ ++ ++/* chip interrupt bit error summary */ ++#define I_ERRORS (I_PDEE | I_PDE | I_DE | I_RDU | I_RFO | I_XFU) ++#define DEF_INTMASK (I_XI0 | I_XI1 | I_XI2 | I_XI3 | I_RI | I_ERRORS) ++ ++#define GMAC_RESET_DELAY 2 ++ ++#define GMAC_MIN_FRAMESIZE 17 /* gmac can only send frames of ++ * size above 17 octetes. ++ */ ++ ++#define LOOPBACK_MODE_DMA 0 /* loopback the packet at the DMA engine */ ++#define LOOPBACK_MODE_MAC 1 /* loopback the packet at MAC */ ++#define LOOPBACK_MODE_NONE 2 /* no Loopback */ ++ ++#define DMAREG(ch, dir, qnum) ((dir == DMA_TX) ? \ ++ (void *)(uintptr)&(ch->regs->dmaregs[qnum].dmaxmt) : \ ++ (void *)(uintptr)&(ch->regs->dmaregs[qnum].dmarcv)) ++ ++/* ++ * Add multicast address to the list. Multicast address are maintained as ++ * hash table with chaining. ++ */ ++typedef struct mclist { ++ struct ether_addr mc_addr; /* multicast address to allow */ ++ struct mclist *next; /* next entry */ ++} mflist_t; ++ ++#define GMAC_HASHT_SIZE 16 /* hash table size */ ++#define GMAC_MCADDR_HASH(m) ((((uint8 *)(m))[3] + ((uint8 *)(m))[4] + \ ++ ((uint8 *)(m))[5]) & (GMAC_HASHT_SIZE - 1)) ++ ++#define ETHER_MCADDR_CMP(x, y) ((((uint16 *)(x))[0] ^ ((uint16 *)(y))[0]) | \ ++ (((uint16 *)(x))[1] ^ ((uint16 *)(y))[1]) | \ ++ (((uint16 *)(x))[2] ^ ((uint16 *)(y))[2])) ++ ++#define SUCCESS 0 ++#define FAILURE -1 ++ ++typedef struct mcfilter { ++ /* hash table for multicast filtering */ ++ mflist_t *bucket[GMAC_HASHT_SIZE]; ++} mcfilter_t; ++ ++extern uint32 find_priq(uint32 pri_map); ++ ++#endif /* _etcgmac_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/Makefile b/drivers/bcmdrivers/gmac/src/include/Makefile +new file mode 100755 +index 0000000..42b3b68 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/Makefile +@@ -0,0 +1,53 @@ ++#!/bin/bash ++# ++# This script serves following purpose: ++# ++# 1. It generates native version information by querying ++# automerger maintained database to see where src/include ++# came from ++# 2. For select components, as listed in compvers.sh ++# it generates component version files ++# ++# Copyright 2005, Broadcom, Inc. ++# ++# $Id: Makefile 241686 2011-02-19 00:22:45Z $ ++# ++ ++SRCBASE := .. ++ ++TARGETS := epivers.h ++ ++ifdef VERBOSE ++export VERBOSE ++endif ++ ++all release: epivers compvers ++ ++# Generate epivers.h for native branch version ++epivers: ++ bash epivers.sh ++ ++# Generate epivers.h for native branch version ++compvers: ++ @if [ -s "compvers.sh" ]; then \ ++ echo "Generating component versions, if any"; \ ++ bash compvers.sh; \ ++ else \ ++ echo "Skipping component version generation"; \ ++ fi ++ ++# Generate epivers.h for native branch version ++clean_compvers: ++ @if [ -s "compvers.sh" ]; then \ ++ echo "bash compvers.sh clean"; \ ++ bash compvers.sh clean; \ ++ else \ ++ echo "Skipping component version clean"; \ ++ fi ++ ++clean: ++ rm -f $(TARGETS) *.prev ++ ++clean_all: clean clean_compvers ++ ++.PHONY: all release clean epivers compvers clean_compvers +diff --git a/drivers/bcmdrivers/gmac/src/include/aidmp.h b/drivers/bcmdrivers/gmac/src/include/aidmp.h +new file mode 100755 +index 0000000..a8fe0bc +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/aidmp.h +@@ -0,0 +1,383 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom AMBA Interconnect definitions. ++ * ++ * $Id: aidmp.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _AIDMP_H ++#define _AIDMP_H ++ ++/* Manufacturer Ids */ ++#define MFGID_ARM 0x43b ++#define MFGID_BRCM 0x4bf ++#define MFGID_MIPS 0x4a7 ++ ++/* Component Classes */ ++#define CC_SIM 0 ++#define CC_EROM 1 ++#define CC_CORESIGHT 9 ++#define CC_VERIF 0xb ++#define CC_OPTIMO 0xd ++#define CC_GEN 0xe ++#define CC_PRIMECELL 0xf ++ ++/* Enumeration ROM registers */ ++#define ER_EROMENTRY 0x000 ++#define ER_REMAPCONTROL 0xe00 ++#define ER_REMAPSELECT 0xe04 ++#define ER_MASTERSELECT 0xe10 ++#define ER_ITCR 0xf00 ++#define ER_ITIP 0xf04 ++ ++/* Erom entries */ ++#define ER_TAG 0xe ++#define ER_TAG1 0x6 ++#define ER_VALID 1 ++#define ER_CI 0 ++#define ER_MP 2 ++#define ER_ADD 4 ++#define ER_END 0xe ++#define ER_BAD 0xffffffff ++ ++/* EROM CompIdentA */ ++#define CIA_MFG_MASK 0xfff00000 ++#define CIA_MFG_SHIFT 20 ++#define CIA_CID_MASK 0x000fff00 ++#define CIA_CID_SHIFT 8 ++#define CIA_CCL_MASK 0x000000f0 ++#define CIA_CCL_SHIFT 4 ++ ++/* EROM CompIdentB */ ++#define CIB_REV_MASK 0xff000000 ++#define CIB_REV_SHIFT 24 ++#define CIB_NSW_MASK 0x00f80000 ++#define CIB_NSW_SHIFT 19 ++#define CIB_NMW_MASK 0x0007c000 ++#define CIB_NMW_SHIFT 14 ++#define CIB_NSP_MASK 0x00003e00 ++#define CIB_NSP_SHIFT 9 ++#define CIB_NMP_MASK 0x000001f0 ++#define CIB_NMP_SHIFT 4 ++ ++/* EROM MasterPortDesc */ ++#define MPD_MUI_MASK 0x0000ff00 ++#define MPD_MUI_SHIFT 8 ++#define MPD_MP_MASK 0x000000f0 ++#define MPD_MP_SHIFT 4 ++ ++/* EROM AddrDesc */ ++#define AD_ADDR_MASK 0xfffff000 ++#define AD_SP_MASK 0x00000f00 ++#define AD_SP_SHIFT 8 ++#define AD_ST_MASK 0x000000c0 ++#define AD_ST_SHIFT 6 ++#define AD_ST_SLAVE 0x00000000 ++#define AD_ST_BRIDGE 0x00000040 ++#define AD_ST_SWRAP 0x00000080 ++#define AD_ST_MWRAP 0x000000c0 ++#define AD_SZ_MASK 0x00000030 ++#define AD_SZ_SHIFT 4 ++#define AD_SZ_4K 0x00000000 ++#define AD_SZ_8K 0x00000010 ++#define AD_SZ_16K 0x00000020 ++#define AD_SZ_SZD 0x00000030 ++#define AD_AG32 0x00000008 ++#define AD_ADDR_ALIGN 0x00000fff ++#define AD_SZ_BASE 0x00001000 /* 4KB */ ++ ++/* EROM SizeDesc */ ++#define SD_SZ_MASK 0xfffff000 ++#define SD_SG32 0x00000008 ++#define SD_SZ_ALIGN 0x00000fff ++ ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++typedef volatile struct _aidmp { ++ uint32 oobselina30; /* 0x000 */ ++ uint32 oobselina74; /* 0x004 */ ++ uint32 PAD[6]; ++ uint32 oobselinb30; /* 0x020 */ ++ uint32 oobselinb74; /* 0x024 */ ++ uint32 PAD[6]; ++ uint32 oobselinc30; /* 0x040 */ ++ uint32 oobselinc74; /* 0x044 */ ++ uint32 PAD[6]; ++ uint32 oobselind30; /* 0x060 */ ++ uint32 oobselind74; /* 0x064 */ ++ uint32 PAD[38]; ++ uint32 oobselouta30; /* 0x100 */ ++ uint32 oobselouta74; /* 0x104 */ ++ uint32 PAD[6]; ++ uint32 oobseloutb30; /* 0x120 */ ++ uint32 oobseloutb74; /* 0x124 */ ++ uint32 PAD[6]; ++ uint32 oobseloutc30; /* 0x140 */ ++ uint32 oobseloutc74; /* 0x144 */ ++ uint32 PAD[6]; ++ uint32 oobseloutd30; /* 0x160 */ ++ uint32 oobseloutd74; /* 0x164 */ ++ uint32 PAD[38]; ++ uint32 oobsynca; /* 0x200 */ ++ uint32 oobseloutaen; /* 0x204 */ ++ uint32 PAD[6]; ++ uint32 oobsyncb; /* 0x220 */ ++ uint32 oobseloutben; /* 0x224 */ ++ uint32 PAD[6]; ++ uint32 oobsyncc; /* 0x240 */ ++ uint32 oobseloutcen; /* 0x244 */ ++ uint32 PAD[6]; ++ uint32 oobsyncd; /* 0x260 */ ++ uint32 oobseloutden; /* 0x264 */ ++ uint32 PAD[38]; ++ uint32 oobaextwidth; /* 0x300 */ ++ uint32 oobainwidth; /* 0x304 */ ++ uint32 oobaoutwidth; /* 0x308 */ ++ uint32 PAD[5]; ++ uint32 oobbextwidth; /* 0x320 */ ++ uint32 oobbinwidth; /* 0x324 */ ++ uint32 oobboutwidth; /* 0x328 */ ++ uint32 PAD[5]; ++ uint32 oobcextwidth; /* 0x340 */ ++ uint32 oobcinwidth; /* 0x344 */ ++ uint32 oobcoutwidth; /* 0x348 */ ++ uint32 PAD[5]; ++ uint32 oobdextwidth; /* 0x360 */ ++ uint32 oobdinwidth; /* 0x364 */ ++ uint32 oobdoutwidth; /* 0x368 */ ++ uint32 PAD[37]; ++ uint32 ioctrlset; /* 0x400 */ ++ uint32 ioctrlclear; /* 0x404 */ ++ uint32 ioctrl; /* 0x408 */ ++ uint32 PAD[61]; ++ uint32 iostatus; /* 0x500 */ ++ uint32 PAD[127]; ++ uint32 ioctrlwidth; /* 0x700 */ ++ uint32 iostatuswidth; /* 0x704 */ ++ uint32 PAD[62]; ++ uint32 resetctrl; /* 0x800 */ ++ uint32 resetstatus; /* 0x804 */ ++ uint32 resetreadid; /* 0x808 */ ++ uint32 resetwriteid; /* 0x80c */ ++ uint32 PAD[60]; ++ uint32 errlogctrl; /* 0x900 */ ++ uint32 errlogdone; /* 0x904 */ ++ uint32 errlogstatus; /* 0x908 */ ++ uint32 errlogaddrlo; /* 0x90c */ ++ uint32 errlogaddrhi; /* 0x910 */ ++ uint32 errlogid; /* 0x914 */ ++ uint32 errloguser; /* 0x918 */ ++ uint32 errlogflags; /* 0x91c */ ++ uint32 PAD[56]; ++ uint32 intstatus; /* 0xa00 */ ++ uint32 PAD[255]; ++ uint32 config; /* 0xe00 */ ++ uint32 PAD[63]; ++ uint32 itcr; /* 0xf00 */ ++ uint32 PAD[3]; ++ uint32 itipooba; /* 0xf10 */ ++ uint32 itipoobb; /* 0xf14 */ ++ uint32 itipoobc; /* 0xf18 */ ++ uint32 itipoobd; /* 0xf1c */ ++ uint32 PAD[4]; ++ uint32 itipoobaout; /* 0xf30 */ ++ uint32 itipoobbout; /* 0xf34 */ ++ uint32 itipoobcout; /* 0xf38 */ ++ uint32 itipoobdout; /* 0xf3c */ ++ uint32 PAD[4]; ++ uint32 itopooba; /* 0xf50 */ ++ uint32 itopoobb; /* 0xf54 */ ++ uint32 itopoobc; /* 0xf58 */ ++ uint32 itopoobd; /* 0xf5c */ ++ uint32 PAD[4]; ++ uint32 itopoobain; /* 0xf70 */ ++ uint32 itopoobbin; /* 0xf74 */ ++ uint32 itopoobcin; /* 0xf78 */ ++ uint32 itopoobdin; /* 0xf7c */ ++ uint32 PAD[4]; ++ uint32 itopreset; /* 0xf90 */ ++ uint32 PAD[15]; ++ uint32 peripherialid4; /* 0xfd0 */ ++ uint32 peripherialid5; /* 0xfd4 */ ++ uint32 peripherialid6; /* 0xfd8 */ ++ uint32 peripherialid7; /* 0xfdc */ ++ uint32 peripherialid0; /* 0xfe0 */ ++ uint32 peripherialid1; /* 0xfe4 */ ++ uint32 peripherialid2; /* 0xfe8 */ ++ uint32 peripherialid3; /* 0xfec */ ++ uint32 componentid0; /* 0xff0 */ ++ uint32 componentid1; /* 0xff4 */ ++ uint32 componentid2; /* 0xff8 */ ++ uint32 componentid3; /* 0xffc */ ++} aidmp_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* Out-of-band Router registers */ ++#define OOB_BUSCONFIG 0x020 ++#define OOB_STATUSA 0x100 ++#define OOB_STATUSB 0x104 ++#define OOB_STATUSC 0x108 ++#define OOB_STATUSD 0x10c ++#define OOB_ENABLEA0 0x200 ++#define OOB_ENABLEA1 0x204 ++#define OOB_ENABLEA2 0x208 ++#define OOB_ENABLEA3 0x20c ++#define OOB_ENABLEB0 0x280 ++#define OOB_ENABLEB1 0x284 ++#define OOB_ENABLEB2 0x288 ++#define OOB_ENABLEB3 0x28c ++#define OOB_ENABLEC0 0x300 ++#define OOB_ENABLEC1 0x304 ++#define OOB_ENABLEC2 0x308 ++#define OOB_ENABLEC3 0x30c ++#define OOB_ENABLED0 0x380 ++#define OOB_ENABLED1 0x384 ++#define OOB_ENABLED2 0x388 ++#define OOB_ENABLED3 0x38c ++#define OOB_ITCR 0xf00 ++#define OOB_ITIPOOBA 0xf10 ++#define OOB_ITIPOOBB 0xf14 ++#define OOB_ITIPOOBC 0xf18 ++#define OOB_ITIPOOBD 0xf1c ++#define OOB_ITOPOOBA 0xf30 ++#define OOB_ITOPOOBB 0xf34 ++#define OOB_ITOPOOBC 0xf38 ++#define OOB_ITOPOOBD 0xf3c ++ ++/* DMP wrapper registers */ ++#define AI_OOBSELINA30 0x000 ++#define AI_OOBSELINA74 0x004 ++#define AI_OOBSELINB30 0x020 ++#define AI_OOBSELINB74 0x024 ++#define AI_OOBSELINC30 0x040 ++#define AI_OOBSELINC74 0x044 ++#define AI_OOBSELIND30 0x060 ++#define AI_OOBSELIND74 0x064 ++#define AI_OOBSELOUTA30 0x100 ++#define AI_OOBSELOUTA74 0x104 ++#define AI_OOBSELOUTB30 0x120 ++#define AI_OOBSELOUTB74 0x124 ++#define AI_OOBSELOUTC30 0x140 ++#define AI_OOBSELOUTC74 0x144 ++#define AI_OOBSELOUTD30 0x160 ++#define AI_OOBSELOUTD74 0x164 ++#define AI_OOBSYNCA 0x200 ++#define AI_OOBSELOUTAEN 0x204 ++#define AI_OOBSYNCB 0x220 ++#define AI_OOBSELOUTBEN 0x224 ++#define AI_OOBSYNCC 0x240 ++#define AI_OOBSELOUTCEN 0x244 ++#define AI_OOBSYNCD 0x260 ++#define AI_OOBSELOUTDEN 0x264 ++#define AI_OOBAEXTWIDTH 0x300 ++#define AI_OOBAINWIDTH 0x304 ++#define AI_OOBAOUTWIDTH 0x308 ++#define AI_OOBBEXTWIDTH 0x320 ++#define AI_OOBBINWIDTH 0x324 ++#define AI_OOBBOUTWIDTH 0x328 ++#define AI_OOBCEXTWIDTH 0x340 ++#define AI_OOBCINWIDTH 0x344 ++#define AI_OOBCOUTWIDTH 0x348 ++#define AI_OOBDEXTWIDTH 0x360 ++#define AI_OOBDINWIDTH 0x364 ++#define AI_OOBDOUTWIDTH 0x368 ++ ++#if defined(IL_BIGENDIAN) && defined(BCMHND74K) ++/* Selective swapped defines for those registers we need in ++ * big-endian code. ++ */ ++#define AI_IOCTRLSET 0x404 ++#define AI_IOCTRLCLEAR 0x400 ++#define AI_IOCTRL 0x40c ++#define AI_IOSTATUS 0x504 ++#define AI_RESETCTRL 0x804 ++#define AI_RESETSTATUS 0x800 ++ ++#else /* !IL_BIGENDIAN || !BCMHND74K */ ++ ++#define AI_IOCTRLSET 0x400 ++#define AI_IOCTRLCLEAR 0x404 ++#define AI_IOCTRL 0x408 ++#define AI_IOSTATUS 0x500 ++#define AI_RESETCTRL 0x800 ++#define AI_RESETSTATUS 0x804 ++ ++#endif /* IL_BIGENDIAN && BCMHND74K */ ++ ++#define AI_IOCTRLWIDTH 0x700 ++#define AI_IOSTATUSWIDTH 0x704 ++ ++#define AI_RESETREADID 0x808 ++#define AI_RESETWRITEID 0x80c ++#define AI_ERRLOGCTRL 0xa00 ++#define AI_ERRLOGDONE 0xa04 ++#define AI_ERRLOGSTATUS 0xa08 ++#define AI_ERRLOGADDRLO 0xa0c ++#define AI_ERRLOGADDRHI 0xa10 ++#define AI_ERRLOGID 0xa14 ++#define AI_ERRLOGUSER 0xa18 ++#define AI_ERRLOGFLAGS 0xa1c ++#define AI_INTSTATUS 0xa00 ++#define AI_CONFIG 0xe00 ++#define AI_ITCR 0xf00 ++#define AI_ITIPOOBA 0xf10 ++#define AI_ITIPOOBB 0xf14 ++#define AI_ITIPOOBC 0xf18 ++#define AI_ITIPOOBD 0xf1c ++#define AI_ITIPOOBAOUT 0xf30 ++#define AI_ITIPOOBBOUT 0xf34 ++#define AI_ITIPOOBCOUT 0xf38 ++#define AI_ITIPOOBDOUT 0xf3c ++#define AI_ITOPOOBA 0xf50 ++#define AI_ITOPOOBB 0xf54 ++#define AI_ITOPOOBC 0xf58 ++#define AI_ITOPOOBD 0xf5c ++#define AI_ITOPOOBAIN 0xf70 ++#define AI_ITOPOOBBIN 0xf74 ++#define AI_ITOPOOBCIN 0xf78 ++#define AI_ITOPOOBDIN 0xf7c ++#define AI_ITOPRESET 0xf90 ++#define AI_PERIPHERIALID4 0xfd0 ++#define AI_PERIPHERIALID5 0xfd4 ++#define AI_PERIPHERIALID6 0xfd8 ++#define AI_PERIPHERIALID7 0xfdc ++#define AI_PERIPHERIALID0 0xfe0 ++#define AI_PERIPHERIALID1 0xfe4 ++#define AI_PERIPHERIALID2 0xfe8 ++#define AI_PERIPHERIALID3 0xfec ++#define AI_COMPONENTID0 0xff0 ++#define AI_COMPONENTID1 0xff4 ++#define AI_COMPONENTID2 0xff8 ++#define AI_COMPONENTID3 0xffc ++ ++/* resetctrl */ ++#define AIRC_RESET 1 ++ ++/* config */ ++#define AICFG_OOB 0x00000020 ++#define AICFG_IOS 0x00000010 ++#define AICFG_IOC 0x00000008 ++#define AICFG_TO 0x00000004 ++#define AICFG_ERRL 0x00000002 ++#define AICFG_RST 0x00000001 ++ ++/* bit defines for AI_OOBSELOUTB74 reg */ ++#define OOB_SEL_OUTEN_B_5 15 ++#define OOB_SEL_OUTEN_B_6 23 ++ ++#endif /* _AIDMP_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/arminc.h b/drivers/bcmdrivers/gmac/src/include/arminc.h +new file mode 100755 +index 0000000..a0f2401 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/arminc.h +@@ -0,0 +1,317 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND Run Time Environment for standalone ARM programs. ++ * ++ * $Id: arminc.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _ARMINC_H ++#define _ARMINC_H ++ ++ ++/* ARM defines */ ++ ++#ifdef _LANGUAGE_ASSEMBLY ++ ++/* ++ * LEAF - declare leaf routine ++ */ ++#define LEAF(function) \ ++ .section .text.function, "ax"; \ ++ .global function; \ ++ .func function; \ ++function: ++ ++#define THUMBLEAF(function) \ ++ .section .text.function, "ax"; \ ++ .global function; \ ++ .func function; \ ++ .thumb; \ ++ .thumb_func; \ ++function: ++ ++/* ++ * END - mark end of function ++ */ ++#define END(function) \ ++ .ltorg; \ ++ .endfunc; \ ++ .size function, . - function ++ ++#define DW(var, val) \ ++ .global var; \ ++ .type var, %object; \ ++ .size var, 4; \ ++ .align 2; \ ++var: .word val ++ ++ ++#define _ULCAST_ ++ ++#else ++ ++/* ++ * The following macros are especially useful for __asm__ ++ * inline assembler. ++ */ ++#ifndef __STR ++#define __STR(x) #x ++#endif ++#ifndef STR ++#define STR(x) __STR(x) ++#endif ++ ++#define _ULCAST_ (unsigned long) ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++ ++#if defined(__ARM_ARCH_7M__) /* Cortex-M3 */ ++ ++/* Data Watchpoint and Trigger */ ++#define CM3_DWT_CTRL 0xe0001000 ++#define CM3_DWT_CYCCNT 0xe0001004 ++#define CM3_DWT_CPICNT 0xe0001008 ++#define CM3_DWT_EXCCNT 0xe000100c ++#define CM3_DWT_SLEEPCNT 0xe0001010 ++#define CM3_DWT_LSUCNT 0xe0001014 ++#define CM3_DWT_FOLDCNT 0xe0001018 ++#define CM3_DWT_COMP0 0xe0001020 ++#define CM3_DWT_MASK0 0xe0001024 ++#define CM3_DWT_FUNCTION0 0xe0001028 ++#define CM3_DWT_COMP1 0xe0001030 ++#define CM3_DWT_MASK1 0xe0001034 ++#define CM3_DWT_FUNCTION1 0xe0001038 ++#define CM3_DWT_COMP2 0xe0001040 ++#define CM3_DWT_MASK2 0xe0001044 ++#define CM3_DWT_FUNCTION2 0xe0001048 ++#define CM3_DWT_COMP3 0xe0001050 ++#define CM3_DWT_MASK3 0xe0001054 ++#define CM3_DWT_FUNCTION3 0xe0001058 ++ ++#define CM3_DWT_FUNCTION_DISAB 0 ++#define CM3_DWT_FUNCTION_WP_PCMATCH 4 ++#define CM3_DWT_FUNCTION_WP_READ 5 ++#define CM3_DWT_FUNCTION_WP_WRITE 6 ++#define CM3_DWT_FUNCTION_WP_RDWR 7 ++ ++#define CM3_NVIC_IC_TYPE 0xe000e004 /* Interrupt Control Type Reg */ ++#define CM3_NVIC_TICK_CSR 0xe000e010 /* SysTick Control and Status Reg */ ++#define CM3_NVIC_TICK_CSR_COUNTFLAG 0x10000 ++#define CM3_NVIC_TICK_CSR_CLKSOURCE 0x4 /* Set for core clock, 0 for ext ref */ ++#define CM3_NVIC_TICK_CSR_TICKINT 0x2 /* Set for intr on count going 1 => 0 */ ++#define CM3_NVIC_TICK_CSR_ENABLE 0x1 ++#define CM3_NVIC_TICK_RLDVAL 0xe000e014 /* SysTick Reload Value Reg */ ++#define CM3_NVIC_TICK_CURVAL 0xe000e018 /* SysTick Current Value Reg */ ++#define CM3_NVIC_TICK_CALVAL 0xe000e01c /* SysTick Calibration Value Reg */ ++ ++/* Interrupt enable/disable register */ ++#define CM3_NVIC_IRQ_SET_EN0 0xe000e100 /* Irq 0 to 31 Set Enable Reg */ ++#define CM3_NVIC_IRQ_SET_EN(n) (0xe000e100 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_CLR_EN0 0xe000e180 /* Irq 0 to 31 Clear Enable Reg [...] */ ++#define CM3_NVIC_IRQ_CLR_EN(n) (0xe000e180 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_SET_PND0 0xe000e200 /* Irq 0 to 31 Set Pending Reg [...] */ ++#define CM3_NVIC_IRQ_SET_PND(n) (0xe000e200 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_CLR_PND0 0xe000e280 /* Irq 0 to 31 Clear Pending Reg [...] */ ++#define CM3_NVIC_IRQ_CLR_PND(n) (0xe000e280 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_ACT_BIT0 0xe000e300 /* Irq 0 to 31 Active Bit Reg [...] */ ++#define CM3_NVIC_IRQ_ACT_BIT(n) (0xe000e300 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_PRIO0 0xe000e400 /* Irq 0 to 31 Priority Reg [...] */ ++#define CM3_NVIC_IRQ_PRIO(n) (0xe000e400 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++/* CPU control */ ++#define CM3_CPUID 0xe000ed00 ++#define CM3_INTCTLSTATE 0xe000ed04 ++#define CM3_VTOFF 0xe000ed08 /* Vector Table Offset */ ++#define CM3_SYSCTRL 0xe000ed10 ++#define CM3_CFGCTRL 0xe000ed14 ++#define CM3_CFGCTRL_UNALIGN_TRP 0x8 ++#define CM3_CFGCTRL_DIV_0_TRP 0x10 ++#define CM3_CFGCTRL_STKALIGN 0x200 ++ ++#define CM3_PFR0 0xe000ed40 ++#define CM3_PFR1 0xe000ed44 ++#define CM3_DFR0 0xe000ed48 ++#define CM3_AFR0 0xe000ed4c ++#define CM3_MMFR0 0xe000ed50 ++#define CM3_MMFR1 0xe000ed54 ++#define CM3_MMFR2 0xe000ed58 ++#define CM3_MMFR3 0xe000ed5c ++#define CM3_ISAR0 0xe000ed60 ++#define CM3_ISAR1 0xe000ed64 ++#define CM3_ISAR2 0xe000ed68 ++#define CM3_ISAR3 0xe000ed6c ++#define CM3_ISAR4 0xe000ed70 ++#define CM3_ISAR5 0xe000ed74 ++ ++#define CM3_MPUTYPE 0xe000ed90 ++#define CM3_MPUCTRL 0xe000ed94 ++#define CM3_REGNUM 0xe000ed98 ++#define CM3_REGBAR 0xe000ed9c ++#define CM3_REGASZ 0xe000eda0 ++#define CM3_AL1BAR 0xe000eda4 ++#define CM3_AL1ASZ 0xe000eda8 ++#define CM3_AL2BAR 0xe000edac ++#define CM3_AL2ASZ 0xe000edb0 ++#define CM3_AL3BAR 0xe000edb4 ++#define CM3_AL3ASZ 0xe000edb8 ++ ++#define CM3_DBG_HCSR 0xe000edf0 /* Debug Halting Control and Status Reg */ ++#define CM3_DBG_CRSR 0xe000edf4 /* Debug Core Register Selector Reg */ ++#define CM3_DBG_CRDR 0xe000edf8 /* Debug Core Register Data Reg */ ++#define CM3_DBG_EMCR 0xe000edfc /* Debug Exception and Monitor Control Reg */ ++#define CM3_DBG_EMCR_TRCENA (1U << 24) ++#define CM3_DBG_EMCR_MON_EN (1U << 16) ++ ++/* Trap types */ ++#define TR_RST 1 /* Reset */ ++#define TR_NMI 2 /* NMI */ ++#define TR_FAULT 3 /* Hard Fault */ ++#define TR_MM 4 /* Memory Management */ ++#define TR_BUS 5 /* Bus Fault */ ++#define TR_USAGE 6 /* Usage Fault */ ++#define TR_SVC 11 /* SVCall */ ++#define TR_DMON 12 /* Debug Monitor */ ++#define TR_PENDSV 14 /* PendSV */ ++#define TR_SYSTICK 15 /* SysTick */ ++#define TR_ISR 16 /* External Interrupts start here */ ++ ++#define TR_BAD 256 /* Bad trap: Not used by CM3 */ ++ ++/* Offsets of automatically saved registers from sp upon trap */ ++#define CM3_TROFF_R0 0 ++#define CM3_TROFF_R1 4 ++#define CM3_TROFF_R2 8 ++#define CM3_TROFF_R3 12 ++#define CM3_TROFF_R12 16 ++#define CM3_TROFF_LR 20 ++#define CM3_TROFF_PC 24 ++#define CM3_TROFF_xPSR 28 ++ ++#elif defined(__ARM_ARCH_7A__) /* Cortex-A9 */ ++/* Fields in cpsr */ ++#define PS_USR 0x00000010 /* Mode: User */ ++#define PS_FIQ 0x00000011 /* Mode: FIQ */ ++#define PS_IRQ 0x00000012 /* Mode: IRQ */ ++#define PS_SVC 0x00000013 /* Mode: Supervisor */ ++#define PS_ABT 0x00000017 /* Mode: Abort */ ++#define PS_UND 0x0000001b /* Mode: Undefined */ ++#define PS_SYS 0x0000001f /* Mode: System */ ++#define PS_MM 0x0000001f /* Mode bits mask */ ++#define PS_T 0x00000020 /* Thumb mode */ ++#define PS_F 0x00000040 /* FIQ disable */ ++#define PS_I 0x00000080 /* IRQ disable */ ++#define PS_A 0x00000100 /* Imprecise abort */ ++#define PS_E 0x00000200 /* Endianess */ ++#define PS_IT72 0x0000fc00 /* IT[7:2] */ ++#define PS_GE 0x000f0000 /* IT[7:2] */ ++#define PS_J 0x01000000 /* Java state */ ++#define PS_IT10 0x06000000 /* IT[1:0] */ ++#define PS_Q 0x08000000 /* Sticky overflow */ ++#define PS_V 0x10000000 /* Overflow cc */ ++#define PS_C 0x20000000 /* Carry cc */ ++#define PS_Z 0x40000000 /* Zero cc */ ++#define PS_N 0x80000000 /* Negative cc */ ++ ++/* Trap types */ ++#define TR_RST 0 /* Reset trap */ ++#define TR_UND 1 /* Indefined instruction trap */ ++#define TR_SWI 2 /* Software intrrupt */ ++#define TR_IAB 3 /* Instruction fetch abort */ ++#define TR_DAB 4 /* Data access abort */ ++#define TR_BAD 5 /* Bad trap: Not used by ARM */ ++#define TR_IRQ 6 /* Interrupt */ ++#define TR_FIQ 7 /* Fast interrupt */ ++ ++/* ++ * Memory segments (32bit kernel mode addresses) ++ */ ++#define PHYSADDR_MASK 0xffffffff ++ ++/* ++ * Map an address to a certain kernel segment ++ */ ++#undef PHYSADDR ++#define PHYSADDR(a) (_ULCAST_(a) & PHYSADDR_MASK) ++#else /* !__ARM_ARCH_7M__ */ ++ ++/* Fields in cpsr */ ++#define PS_USR 0x00000010 /* Mode: User */ ++#define PS_FIQ 0x00000011 /* Mode: FIQ */ ++#define PS_IRQ 0x00000012 /* Mode: IRQ */ ++#define PS_SVC 0x00000013 /* Mode: Supervisor */ ++#define PS_ABT 0x00000017 /* Mode: Abort */ ++#define PS_UND 0x0000001b /* Mode: Undefined */ ++#define PS_SYS 0x0000001f /* Mode: System */ ++#define PS_MM 0x0000001f /* Mode bits mask */ ++#define PS_T 0x00000020 /* Thumb mode */ ++#define PS_F 0x00000040 /* FIQ disable */ ++#define PS_I 0x00000080 /* IRQ disable */ ++#define PS_A 0x00000100 /* Imprecise abort */ ++#define PS_E 0x00000200 /* Endianess */ ++#define PS_IT72 0x0000fc00 /* IT[7:2] */ ++#define PS_GE 0x000f0000 /* IT[7:2] */ ++#define PS_J 0x01000000 /* Java state */ ++#define PS_IT10 0x06000000 /* IT[1:0] */ ++#define PS_Q 0x08000000 /* Sticky overflow */ ++#define PS_V 0x10000000 /* Overflow cc */ ++#define PS_C 0x20000000 /* Carry cc */ ++#define PS_Z 0x40000000 /* Zero cc */ ++#define PS_N 0x80000000 /* Negative cc */ ++ ++/* Trap types */ ++#define TR_RST 0 /* Reset trap */ ++#define TR_UND 1 /* Indefined instruction trap */ ++#define TR_SWI 2 /* Software intrrupt */ ++#define TR_IAB 3 /* Instruction fetch abort */ ++#define TR_DAB 4 /* Data access abort */ ++#define TR_BAD 5 /* Bad trap: Not used by ARM */ ++#define TR_IRQ 6 /* Interrupt */ ++#define TR_FIQ 7 /* Fast interrupt */ ++ ++#ifdef BCMDBG_ARMRST ++#define TR_ARMRST 0xF /* Debug facility to trap Arm reset */ ++#endif ++ ++/* used to fill an overlay region with nop's */ ++#define NOP_UINT32 0x46c046c0 ++ ++ ++#define mrc(cp, a, b, n) \ ++({ \ ++ int __res; \ ++ __asm__ __volatile__("\tmrc\tp"STR(cp)", 0, %0, c"STR(a)", c"STR(b)", "STR(n) \ ++ :"=r" (__res)); \ ++ __res; \ ++}) ++ ++ ++#endif /* !__ARM_ARCH_7M__ */ ++ ++/* Pieces of a CPU Id */ ++#define CID_IMPL 0xff000000 /* Implementor: 0x41 for ARM Ltd. */ ++#define CID_VARIANT 0x00f00000 ++#define CID_ARCH 0x000f0000 ++#define CID_PART 0x0000fff0 ++#define CID_REV 0x0000000f ++#define CID_MASK (CID_IMPL | CID_ARCH | CID_PART) ++ ++#endif /* _ARMINC_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcm_cfg.h b/drivers/bcmdrivers/gmac/src/include/bcm_cfg.h +new file mode 100755 +index 0000000..8219b8b +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcm_cfg.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * BCM common config options ++ * ++ * $Id: bcm_cfg.h 294399 2011-11-07 03:31:22Z $ ++ */ ++ ++#ifndef _bcm_cfg_h_ ++#define _bcm_cfg_h_ ++#if defined(__NetBSD__) || defined(__FreeBSD__) ++#if defined(_KERNEL) ++#include ++#endif /* defined(_KERNEL) */ ++#endif /* defined(__NetBSD__) || defined(__FreeBSD__) */ ++#endif /* _bcm_cfg_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcm_mpool_pub.h b/drivers/bcmdrivers/gmac/src/include/bcm_mpool_pub.h +new file mode 100755 +index 0000000..7a1f01d +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcm_mpool_pub.h +@@ -0,0 +1,355 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Memory pools library, Public interface ++ * ++ * API Overview ++ * ++ * This package provides a memory allocation subsystem based on pools of ++ * homogenous objects. ++ * ++ * Instrumentation is available for reporting memory utilization both ++ * on a per-data-structure basis and system wide. ++ * ++ * There are two main types defined in this API. ++ * ++ * pool manager: A singleton object that acts as a factory for ++ * pool allocators. It also is used for global ++ * instrumentation, such as reporting all blocks ++ * in use across all data structures. The pool manager ++ * creates and provides individual memory pools ++ * upon request to application code. ++ * ++ * memory pool: An object for allocating homogenous memory blocks. ++ * ++ * Global identifiers in this module use the following prefixes: ++ * bcm_mpm_* Memory pool manager ++ * bcm_mp_* Memory pool ++ * ++ * There are two main types of memory pools: ++ * ++ * prealloc: The contiguous memory block of objects can either be supplied ++ * by the client or malloc'ed by the memory manager. The objects are ++ * allocated out of a block of memory and freed back to the block. ++ * ++ * heap: The memory pool allocator uses the heap (malloc/free) for memory. ++ * In this case, the pool allocator is just providing statistics ++ * and instrumentation on top of the heap, without modifying the heap ++ * allocation implementation. ++ * ++ * $Id$ ++ */ ++ ++#ifndef _BCM_MPOOL_PUB_H ++#define _BCM_MPOOL_PUB_H 1 ++ ++#include /* needed for uint16 */ ++ ++ ++/* ++************************************************************************** ++* ++* Type definitions, handles ++* ++************************************************************************** ++*/ ++ ++/* Forward declaration of OSL handle. */ ++struct osl_info; ++ ++/* Forward declaration of string buffer. */ ++struct bcmstrbuf; ++ ++/* ++ * Opaque type definition for the pool manager handle. This object is used for global ++ * memory pool operations such as obtaining a new pool, deleting a pool, iterating and ++ * instrumentation/debugging. ++ */ ++struct bcm_mpm_mgr; ++typedef struct bcm_mpm_mgr *bcm_mpm_mgr_h; ++ ++/* ++ * Opaque type definition for an instance of a pool. This handle is used for allocating ++ * and freeing memory through the pool, as well as management/instrumentation on this ++ * specific pool. ++ */ ++struct bcm_mp_pool; ++typedef struct bcm_mp_pool *bcm_mp_pool_h; ++ ++ ++/* ++ * To make instrumentation more readable, every memory ++ * pool must have a readable name. Pool names are up to ++ * 8 bytes including '\0' termination. (7 printable characters.) ++ */ ++#define BCM_MP_NAMELEN 8 ++ ++ ++/* ++ * Type definition for pool statistics. ++ */ ++typedef struct bcm_mp_stats { ++ char name[BCM_MP_NAMELEN]; /* Name of this pool. */ ++ unsigned int objsz; /* Object size allocated in this pool */ ++ uint16 nobj; /* Total number of objects in this pool */ ++ uint16 num_alloc; /* Number of objects currently allocated */ ++ uint16 high_water; /* Max number of allocated objects. */ ++ uint16 failed_alloc; /* Failed allocations. */ ++} bcm_mp_stats_t; ++ ++ ++/* ++************************************************************************** ++* ++* API Routines on the pool manager. ++* ++************************************************************************** ++*/ ++ ++/* ++ * bcm_mpm_init() - initialize the whole memory pool system. ++ * ++ * Parameters: ++ * osh: INPUT Operating system handle. Needed for heap memory allocation. ++ * max_pools: INPUT Maximum number of mempools supported. ++ * mgr: OUTPUT The handle is written with the new pools manager object/handle. ++ * ++ * Returns: ++ * BCME_OK Object initialized successfully. May be used. ++ * BCME_NOMEM Initialization failed due to no memory. Object must not be used. ++ */ ++int bcm_mpm_init(struct osl_info *osh, int max_pools, bcm_mpm_mgr_h *mgrp); ++ ++ ++/* ++ * bcm_mpm_deinit() - de-initialize the whole memory pool system. ++ * ++ * Parameters: ++ * mgr: INPUT Pointer to pool manager handle. ++ * ++ * Returns: ++ * BCME_OK Memory pool manager successfully de-initialized. ++ * other Indicated error occured during de-initialization. ++ */ ++int bcm_mpm_deinit(bcm_mpm_mgr_h *mgrp); ++ ++/* ++ * bcm_mpm_create_prealloc_pool() - Create a new pool for fixed size objects. The ++ * pool uses a contiguous block of pre-alloced ++ * memory. The memory block may either be provided ++ * by the client or dynamically allocated by the ++ * pool manager. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pool manager ++ * obj_sz: INPUT Size of objects that will be allocated by the new pool ++ * Must be >= sizeof(void *). ++ * nobj: INPUT Maximum number of concurrently existing objects to support ++ * memstart INPUT Pointer to the memory to use, or NULL to malloc() ++ * memsize INPUT Number of bytes referenced from memstart (for error checking). ++ * Must be 0 if 'memstart' is NULL. ++ * poolname INPUT For instrumentation, the name of the pool ++ * newp: OUTPUT The handle for the new pool, if creation is successful ++ * ++ * Returns: ++ * BCME_OK Pool created ok. ++ * other Pool not created due to indicated error. newpoolp set to NULL. ++ * ++ * ++ */ ++int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr, ++ unsigned int obj_sz, ++ int nobj, ++ void *memstart, ++ unsigned int memsize, ++ char poolname[BCM_MP_NAMELEN], ++ bcm_mp_pool_h *newp); ++ ++ ++/* ++ * bcm_mpm_delete_prealloc_pool() - Delete a memory pool. This should only be called after ++ * all memory objects have been freed back to the pool. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * pool: INPUT The handle of the pool to delete ++ * ++ * Returns: ++ * BCME_OK Pool deleted ok. ++ * other Pool not deleted due to indicated error. ++ * ++ */ ++int bcm_mpm_delete_prealloc_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); ++ ++/* ++ * bcm_mpm_create_heap_pool() - Create a new pool for fixed size objects. The memory ++ * pool allocator uses the heap (malloc/free) for memory. ++ * In this case, the pool allocator is just providing ++ * statistics and instrumentation on top of the heap, ++ * without modifying the heap allocation implementation. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pool manager ++ * obj_sz: INPUT Size of objects that will be allocated by the new pool ++ * poolname INPUT For instrumentation, the name of the pool ++ * newp: OUTPUT The handle for the new pool, if creation is successful ++ * ++ * Returns: ++ * BCME_OK Pool created ok. ++ * other Pool not created due to indicated error. newpoolp set to NULL. ++ * ++ * ++ */ ++int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz, ++ char poolname[BCM_MP_NAMELEN], ++ bcm_mp_pool_h *newp); ++ ++ ++/* ++ * bcm_mpm_delete_heap_pool() - Delete a memory pool. This should only be called after ++ * all memory objects have been freed back to the pool. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * pool: INPUT The handle of the pool to delete ++ * ++ * Returns: ++ * BCME_OK Pool deleted ok. ++ * other Pool not deleted due to indicated error. ++ * ++ */ ++int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); ++ ++ ++/* ++ * bcm_mpm_stats() - Return stats for all pools ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * stats: OUTPUT Array of pool statistics. ++ * nentries: MOD Max elements in 'stats' array on INPUT. Actual number ++ * of array elements copied to 'stats' on OUTPUT. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error getting stats. ++ * ++ */ ++int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries); ++ ++ ++/* ++ * bcm_mpm_dump() - Display statistics on all pools ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * b: OUTPUT Output buffer. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during dump. ++ * ++ */ ++int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b); ++ ++ ++/* ++ * bcm_mpm_get_obj_size() - The size of memory objects may need to be padded to ++ * compensate for alignment requirements of the objects. ++ * This function provides the padded object size. If clients ++ * pre-allocate a memory slab for a memory pool, the ++ * padded object size should be used by the client to allocate ++ * the memory slab (in order to provide sufficent space for ++ * the maximum number of objects). ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager. ++ * obj_sz: INPUT Input object size. ++ * padded_obj_sz: OUTPUT Padded object size. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * BCME_BADARG Bad arguments. ++ * ++ */ ++int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *padded_obj_sz); ++ ++ ++/* ++*************************************************************************** ++* ++* API Routines on a specific pool. ++* ++*************************************************************************** ++*/ ++ ++ ++/* ++ * bcm_mp_alloc() - Allocate a memory pool object. ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool. ++ * ++ * Returns: ++ * A pointer to the new object. NULL on error. ++ * ++ */ ++void* bcm_mp_alloc(bcm_mp_pool_h pool); ++ ++/* ++ * bcm_mp_free() - Free a memory pool object. ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool. ++ * objp: INPUT A pointer to the object to free. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during free. ++ * ++ */ ++int bcm_mp_free(bcm_mp_pool_h pool, void *objp); ++ ++/* ++ * bcm_mp_stats() - Return stats for this pool ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool ++ * stats: OUTPUT Pool statistics ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error getting statistics. ++ * ++ */ ++int bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats); ++ ++ ++/* ++ * bcm_mp_dump() - Dump a pool ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool ++ * b OUTPUT Output buffer ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during dump. ++ * ++ */ ++int bcm_mp_dump(bcm_mp_pool_h pool, struct bcmstrbuf *b); ++ ++ ++#endif /* _BCM_MPOOL_PUB_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmcdc.h b/drivers/bcmdrivers/gmac/src/include/bcmcdc.h +new file mode 100755 +index 0000000..2b99cf1 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmcdc.h +@@ -0,0 +1,122 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * CDC network driver ioctl/indication encoding ++ * Broadcom 802.11abg Networking Device Driver ++ * ++ * Definitions subject to change without notice. ++ * ++ * $Id: bcmcdc.h 291086 2011-10-21 01:17:24Z $ ++ */ ++#ifndef _bcmcdc_h_ ++#define _bcmcdc_h_ ++#include ++ ++typedef struct cdc_ioctl { ++ uint32 cmd; /* ioctl command value */ ++ uint32 len; /* lower 16: output buflen; upper 16: input buflen (excludes header) */ ++ uint32 flags; /* flag defns given below */ ++ uint32 status; /* status code returned from the device */ ++} cdc_ioctl_t; ++ ++/* Max valid buffer size that can be sent to the dongle */ ++#define CDC_MAX_MSG_SIZE ETHER_MAX_LEN ++ ++/* len field is divided into input and output buffer lengths */ ++#define CDCL_IOC_OUTLEN_MASK 0x0000FFFF /* maximum or expected response length, */ ++ /* excluding IOCTL header */ ++#define CDCL_IOC_OUTLEN_SHIFT 0 ++#define CDCL_IOC_INLEN_MASK 0xFFFF0000 /* input buffer length, excluding IOCTL header */ ++#define CDCL_IOC_INLEN_SHIFT 16 ++ ++/* CDC flag definitions */ ++#define CDCF_IOC_ERROR 0x01 /* 0=success, 1=ioctl cmd failed */ ++#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */ ++#define CDCF_IOC_OVL_IDX_MASK 0x3c /* overlay region index mask */ ++#define CDCF_IOC_OVL_RSV 0x40 /* 1=reserve this overlay region */ ++#define CDCF_IOC_OVL 0x80 /* 1=this ioctl corresponds to an overlay */ ++#define CDCF_IOC_ACTION_MASK 0xfe /* SET/GET, OVL_IDX, OVL_RSV, OVL mask */ ++#define CDCF_IOC_ACTION_SHIFT 1 /* SET/GET, OVL_IDX, OVL_RSV, OVL shift */ ++#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */ ++#define CDCF_IOC_IF_SHIFT 12 ++#define CDCF_IOC_ID_MASK 0xFFFF0000 /* used to uniquely id an ioctl req/resp pairing */ ++#define CDCF_IOC_ID_SHIFT 16 /* # of bits of shift for ID Mask */ ++ ++#define CDC_IOC_IF_IDX(flags) (((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT) ++#define CDC_IOC_ID(flags) (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT) ++ ++#define CDC_GET_IF_IDX(hdr) \ ++ ((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)) ++#define CDC_SET_IF_IDX(hdr, idx) \ ++ ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | ((idx) << CDCF_IOC_IF_SHIFT))) ++ ++/* ++ * BDC header ++ * ++ * The BDC header is used on data packets to convey priority across USB. ++ */ ++ ++#define BDC_HEADER_LEN 4 ++ ++#define BDC_PROTO_VER_1 1 /* Old Protocol version */ ++#define BDC_PROTO_VER 2 /* Protocol version */ ++ ++#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ ++#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ ++ ++#define BDC_FLAG__UNUSED 0x03 /* Unassigned */ ++#define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good RX checksums */ ++#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ ++ ++#define BDC_PRIORITY_MASK 0x7 ++ ++#define BDC_FLAG2_FC_FLAG 0x10 /* flag to indicate if pkt contains */ ++ /* FLOW CONTROL info only */ ++#define BDC_PRIORITY_FC_SHIFT 4 /* flow control info shift */ ++ ++#define BDC_FLAG2_IF_MASK 0x0f /* APSTA: interface on which the packet was received */ ++#define BDC_FLAG2_IF_SHIFT 0 ++#define BDC_FLAG2_PAD_MASK 0xf0 ++#define BDC_FLAG_PAD_MASK 0x03 ++#define BDC_FLAG2_PAD_SHIFT 2 ++#define BDC_FLAG_PAD_SHIFT 0 ++#define BDC_FLAG2_PAD_IDX 0x3c ++#define BDC_FLAG_PAD_IDX 0x03 ++#define BDC_GET_PAD_LEN(hdr) \ ++ ((int)(((((hdr)->flags2) & BDC_FLAG2_PAD_MASK) >> BDC_FLAG2_PAD_SHIFT) | \ ++ ((((hdr)->flags) & BDC_FLAG_PAD_MASK) >> BDC_FLAG_PAD_SHIFT))) ++#define BDC_SET_PAD_LEN(hdr, idx) \ ++ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_PAD_MASK) | \ ++ (((idx) & BDC_FLAG2_PAD_IDX) << BDC_FLAG2_PAD_SHIFT))); \ ++ ((hdr)->flags = (((hdr)->flags & ~BDC_FLAG_PAD_MASK) | \ ++ (((idx) & BDC_FLAG_PAD_IDX) << BDC_FLAG_PAD_SHIFT))) ++ ++#define BDC_GET_IF_IDX(hdr) \ ++ ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) ++#define BDC_SET_IF_IDX(hdr, idx) \ ++ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | ((idx) << BDC_FLAG2_IF_SHIFT))) ++ ++struct bdc_header { ++ uint8 flags; /* Flags */ ++ uint8 priority; /* 802.1d Priority 0:2 bits, 4:7 USB flow control info */ ++ uint8 flags2; ++ uint8 dataOffset; /* Offset from end of BDC header to packet data, in ++ * 4-byte words. Leaves room for optional headers. ++ */ ++}; ++ ++#define BDC_PROTO_VER_1 1 /* Old Protocol version */ ++ ++#endif /* _bcmcdc_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmdefs.h b/drivers/bcmdrivers/gmac/src/include/bcmdefs.h +new file mode 100755 +index 0000000..e2b9b0e +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmdefs.h +@@ -0,0 +1,336 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc system wide definitions ++ * ++ * $Id: bcmdefs.h 316696 2012-02-23 03:29:35Z $ ++ */ ++ ++#ifndef _bcmdefs_h_ ++#define _bcmdefs_h_ ++ ++/* ++ * One doesn't need to include this file explicitly, gets included automatically if ++ * typedefs.h is included. ++ */ ++ ++/* Use BCM_REFERENCE to suppress warnings about intentionally-unused function ++ * arguments or local variables. ++ */ ++#define BCM_REFERENCE(data) ((void)(data)) ++ ++/* Compile-time assert can be used in place of ASSERT if the expression evaluates ++ * to a constant at compile time. ++ */ ++#define STATIC_ASSERT(expr) { \ ++ /* Make sure the expression is constant. */ \ ++ typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e; \ ++ /* Make sure the expression is true. */ \ ++ typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1]; \ ++} ++ ++/* Reclaiming text and data : ++ * The following macros specify special linker sections that can be reclaimed ++ * after a system is considered 'up'. ++ * BCMATTACHFN is also used for detach functions (it's not worth having a BCMDETACHFN, ++ * as in most cases, the attach function calls the detach function to clean up on error). ++ */ ++#ifdef DONGLEBUILD ++ ++extern bool bcmreclaimed; ++extern bool attach_part_reclaimed; ++ ++#define BCMATTACHDATA(_data) __attribute__ ((__section__ (".dataini2." #_data))) _data ++#define BCMATTACHFN(_fn) __attribute__ ((__section__ (".textini2." #_fn), noinline)) _fn ++ ++#ifndef PREATTACH_NORECLAIM ++#define BCMPREATTACHDATA(_data) __attribute__ ((__section__ (".dataini3." #_data))) _data ++#define BCMPREATTACHFN(_fn) __attribute__ ((__section__ (".textini3." #_fn), noinline)) _fn ++#else ++#define BCMPREATTACHDATA(_data) __attribute__ ((__section__ (".dataini2." #_data))) _data ++#define BCMPREATTACHFN(_fn) __attribute__ ((__section__ (".textini2." #_fn), noinline)) _fn ++#endif ++ ++#if defined(BCMRECLAIM) ++#define BCMINITDATA(_data) __attribute__ ((__section__ (".dataini1." #_data))) _data ++#define BCMINITFN(_fn) __attribute__ ((__section__ (".textini1." #_fn), noinline)) _fn ++#define CONST ++#else ++#define BCMINITDATA(_data) _data ++#define BCMINITFN(_fn) _fn ++#define CONST const ++#endif ++ ++/* Non-manufacture or internal attach function/dat */ ++#if !defined(WLTEST) ++#define BCMNMIATTACHFN(_fn) BCMATTACHFN(_fn) ++#define BCMNMIATTACHDATA(_data) BCMATTACHDATA(_data) ++#else ++#define BCMNMIATTACHFN(_fn) _fn ++#define BCMNMIATTACHDATA(_data) _data ++#endif ++ ++#define BCMUNINITFN(_fn) _fn ++ ++#define BCMFASTPATH ++#else /* DONGLEBUILD */ ++ ++#define bcmreclaimed 0 ++#define BCMATTACHDATA(_data) _data ++#define BCMATTACHFN(_fn) _fn ++#define BCMPREATTACHDATA(_data) _data ++#define BCMPREATTACHFN(_fn) _fn ++#define BCMINITDATA(_data) _data ++#define BCMINITFN(_fn) _fn ++#define BCMUNINITFN(_fn) _fn ++#define BCMNMIATTACHFN(_fn) _fn ++#define BCMNMIATTACHDATA(_data) _data ++#define CONST const ++#if defined(__ARM_ARCH_7A__) ++#define BCM47XX_CA9 ++#else ++#undef BCM47XX_CA9 ++#endif ++#ifndef BCMFASTPATH ++#if defined(mips) || defined(BCM47XX_CA9) ++#define BCMFASTPATH __attribute__ ((__section__ (".text.fastpath"))) ++#define BCMFASTPATH_HOST __attribute__ ((__section__ (".text.fastpath_host"))) ++#else ++#define BCMFASTPATH ++#define BCMFASTPATH_HOST ++#endif ++#endif /* BCMFASTPATH */ ++ ++#endif /* DONGLEBUILD */ ++ ++#if defined(BCMROMBUILD) ++typedef struct { ++ uint16 esiz; ++ uint16 cnt; ++ void *addr; ++} bcmromdat_patch_t; ++#endif ++ ++/* Put some library data/code into ROM to reduce RAM requirements */ ++#if defined(BCMROMBUILD) && !defined(BCMROMSYMGEN_BUILD) && !defined(BCMJMPTBL_TCAM) ++#include ++#define STATIC static ++#else /* !BCMROMBUILD */ ++#define BCMROMDATA(_data) _data ++#define BCMROMDAT_NAME(_data) _data ++#define BCMROMFN(_fn) _fn ++#define BCMROMFN_NAME(_fn) _fn ++#define STATIC static ++#define BCMROMDAT_ARYSIZ(data) ARRAYSIZE(data) ++#define BCMROMDAT_SIZEOF(data) sizeof(data) ++#define BCMROMDAT_APATCH(data) ++#define BCMROMDAT_SPATCH(data) ++#endif /* !BCMROMBUILD */ ++ ++/* Bus types */ ++#define SI_BUS 0 /* SOC Interconnect */ ++#define PCI_BUS 1 /* PCI target */ ++#define PCMCIA_BUS 2 /* PCMCIA target */ ++#define SDIO_BUS 3 /* SDIO target */ ++#define JTAG_BUS 4 /* JTAG */ ++#define USB_BUS 5 /* USB (does not support R/W REG) */ ++#define SPI_BUS 6 /* gSPI target */ ++#define RPC_BUS 7 /* RPC target */ ++ ++/* Allows size optimization for single-bus image */ ++#ifdef BCMBUSTYPE ++#define BUSTYPE(bus) (BCMBUSTYPE) ++#else ++#define BUSTYPE(bus) (bus) ++#endif ++ ++/* Allows size optimization for single-backplane image */ ++#ifdef BCMCHIPTYPE ++#define CHIPTYPE(bus) (BCMCHIPTYPE) ++#else ++#define CHIPTYPE(bus) (bus) ++#endif ++ ++ ++/* Allows size optimization for SPROM support */ ++#if defined(BCMSPROMBUS) ++#define SPROMBUS (BCMSPROMBUS) ++#elif defined(SI_PCMCIA_SROM) ++#define SPROMBUS (PCMCIA_BUS) ++#else ++#define SPROMBUS (PCI_BUS) ++#endif ++ ++/* Allows size optimization for single-chip image */ ++#ifdef BCMCHIPID ++#define CHIPID(chip) (BCMCHIPID) ++#else ++#define CHIPID(chip) (chip) ++#endif ++ ++#ifdef BCMCHIPREV ++#define CHIPREV(rev) (BCMCHIPREV) ++#else ++#define CHIPREV(rev) (rev) ++#endif ++ ++/* Defines for DMA Address Width - Shared between OSL and HNDDMA */ ++#define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */ ++#define DMADDR_MASK_30 0xc0000000 /* Address mask for 30-bits */ ++#define DMADDR_MASK_0 0xffffffff /* Address mask for 0-bits (hi-part) */ ++ ++#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */ ++#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */ ++#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */ ++#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */ ++ ++#ifdef BCMDMA64OSL ++typedef struct { ++ uint32 loaddr; ++ uint32 hiaddr; ++} dma64addr_t; ++ ++typedef dma64addr_t dmaaddr_t; ++#define PHYSADDRHI(_pa) ((_pa).hiaddr) ++#define PHYSADDRHISET(_pa, _val) \ ++ do { \ ++ (_pa).hiaddr = (_val); \ ++ } while (0) ++#define PHYSADDRLO(_pa) ((_pa).loaddr) ++#define PHYSADDRLOSET(_pa, _val) \ ++ do { \ ++ (_pa).loaddr = (_val); \ ++ } while (0) ++ ++#else ++typedef unsigned long dmaaddr_t; ++#define PHYSADDRHI(_pa) (0) ++#define PHYSADDRHISET(_pa, _val) ++#define PHYSADDRLO(_pa) ((_pa)) ++#define PHYSADDRLOSET(_pa, _val) \ ++ do { \ ++ (_pa) = (_val); \ ++ } while (0) ++#endif /* BCMDMA64OSL */ ++ ++/* One physical DMA segment */ ++typedef struct { ++ dmaaddr_t addr; ++ uint32 length; ++} hnddma_seg_t; ++ ++#if defined(MACOSX) ++/* In MacOS, the OS API may return large number of segments. Setting this number lower ++ * will result in failure of dma map ++ */ ++#define MAX_DMA_SEGS 8 ++#elif defined(__NetBSD__) ++/* In NetBSD we also want more segments because the lower level mbuf mapping api might ++ * allocate a large number of segments ++ */ ++#define MAX_DMA_SEGS 16 ++#else ++#define MAX_DMA_SEGS 4 ++#endif ++ ++ ++typedef struct { ++ void *oshdmah; /* Opaque handle for OSL to store its information */ ++ uint origsize; /* Size of the virtual packet */ ++ uint nsegs; ++ hnddma_seg_t segs[MAX_DMA_SEGS]; ++} hnddma_seg_map_t; ++ ++ ++/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF). ++ * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL. ++ * There is a compile time check in wlc.c which ensure that this value is at least as big ++ * as TXOFF. This value is used in dma_rxfill (hnddma.c). ++ */ ++ ++#if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY) ++/* add 40 bytes to allow for extra RPC header and info */ ++#define BCMEXTRAHDROOM 260 ++#else /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ ++#ifdef CTFMAP ++#define BCMEXTRAHDROOM 208 ++#else /* CTFMAP */ ++#define BCMEXTRAHDROOM 204 ++#endif /* CTFMAP */ ++#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ ++ ++/* Packet alignment for most efficient SDIO (can change based on platform) */ ++#ifndef SDALIGN ++#define SDALIGN 32 ++#endif ++ ++/* Headroom required for dongle-to-host communication. Packets allocated ++ * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should ++ * leave this much room in front for low-level message headers which may ++ * be needed to get across the dongle bus to the host. (These messages ++ * don't go over the network, so room for the full WL header above would ++ * be a waste.). ++*/ ++#define BCMDONGLEHDRSZ 12 ++#define BCMDONGLEPADSZ 16 ++ ++#define BCMDONGLEOVERHEAD (BCMDONGLEHDRSZ + BCMDONGLEPADSZ) ++ ++#ifdef BCMDBG ++ ++#ifndef BCMDBG_ERR ++#define BCMDBG_ERR ++#endif /* BCMDBG_ERR */ ++ ++#define BCMDBG_ASSERT ++ ++#endif /* BCMDBG */ ++ ++ ++/* Macros for doing definition and get/set of bitfields ++ * Usage example, e.g. a three-bit field (bits 4-6): ++ * #define _M BITFIELD_MASK(3) ++ * #define _S 4 ++ * ... ++ * regval = R_REG(osh, ®s->regfoo); ++ * field = GFIELD(regval, ); ++ * regval = SFIELD(regval, , 1); ++ * W_REG(osh, ®s->regfoo, regval); ++ */ ++#define BITFIELD_MASK(width) \ ++ (((unsigned)1 << (width)) - 1) ++#define GFIELD(val, field) \ ++ (((val) >> field ## _S) & field ## _M) ++#define SFIELD(val, field, bits) \ ++ (((val) & (~(field ## _M << field ## _S))) | \ ++ ((unsigned)(bits) << field ## _S)) ++ ++/* define BCMSMALL to remove misc features for memory-constrained environments */ ++#ifdef BCMSMALL ++#undef BCMSPACE ++#define bcmspace FALSE /* if (bcmspace) code is discarded */ ++#else ++#define BCMSPACE ++#define bcmspace TRUE /* if (bcmspace) code is retained */ ++#endif ++ ++/* Max. nvram variable table size */ ++#define MAXSZ_NVRAM_VARS 4096 ++ ++#ifdef EFI ++#define __attribute__(x) /* CSTYLED */ ++#endif ++ ++#endif /* _bcmdefs_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmdevs.h b/drivers/bcmdrivers/gmac/src/include/bcmdevs.h +new file mode 100755 +index 0000000..39918b9 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmdevs.h +@@ -0,0 +1,862 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom device-specific manifest constants. ++ * ++ * $Id: bcmdevs.h 328955 2012-04-23 09:06:12Z $ ++ */ ++ ++#ifndef _BCMDEVS_H ++#define _BCMDEVS_H ++ ++/* PCI vendor IDs */ ++#define VENDOR_EPIGRAM 0xfeda ++#define VENDOR_BROADCOM 0x14e4 ++#define VENDOR_3COM 0x10b7 ++#define VENDOR_NETGEAR 0x1385 ++#define VENDOR_DIAMOND 0x1092 ++#define VENDOR_INTEL 0x8086 ++#define VENDOR_DELL 0x1028 ++#define VENDOR_HP 0x103c ++#define VENDOR_HP_COMPAQ 0x0e11 ++#define VENDOR_APPLE 0x106b ++#define VENDOR_SI_IMAGE 0x1095 /* Silicon Image, used by Arasan SDIO Host */ ++#define VENDOR_BUFFALO 0x1154 /* Buffalo vendor id */ ++#define VENDOR_TI 0x104c /* Texas Instruments */ ++#define VENDOR_RICOH 0x1180 /* Ricoh */ ++#define VENDOR_JMICRON 0x197b ++ ++ ++/* PCMCIA vendor IDs */ ++#define VENDOR_BROADCOM_PCMCIA 0x02d0 ++ ++/* SDIO vendor IDs */ ++#define VENDOR_BROADCOM_SDIO 0x00BF ++ ++/* DONGLE VID/PIDs */ ++#define BCM_DNGL_VID 0x0a5c ++#define BCM_DNGL_BL_PID_4328 0xbd12 ++#define BCM_DNGL_BL_PID_4322 0xbd13 ++#define BCM_DNGL_BL_PID_4319 0xbd16 ++#define BCM_DNGL_BL_PID_43236 0xbd17 ++#define BCM_DNGL_BL_PID_4332 0xbd18 ++#define BCM_DNGL_BL_PID_4330 0xbd19 ++#define BCM_DNGL_BL_PID_4334 0xbd1a ++#define BCM_DNGL_BL_PID_43239 0xbd1b ++#define BCM_DNGL_BL_PID_4324 0xbd1c ++#define BCM_DNGL_BL_PID_4360 0xbd1d ++#define BCM_DNGL_BL_PID_4335 0xbd20 ++ ++#define BCM_DNGL_BDC_PID 0x0bdc ++#define BCM_DNGL_JTAG_PID 0x4a44 ++ ++/* HW USB BLOCK [CPULESS USB] PIDs */ ++#define BCM_HWUSB_PID_43239 43239 ++ ++/* PCI Device IDs */ ++#define BCM4210_DEVICE_ID 0x1072 /* never used */ ++#define BCM4230_DEVICE_ID 0x1086 /* never used */ ++#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */ ++#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */ ++#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */ ++#define BCM4211_DEVICE_ID 0x4211 ++#define BCM4231_DEVICE_ID 0x4231 ++#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */ ++#define BCM4311_D11G_ID 0x4311 /* 4311 802.11b/g id */ ++#define BCM4311_D11DUAL_ID 0x4312 /* 4311 802.11a/b/g id */ ++#define BCM4311_D11A_ID 0x4313 /* 4311 802.11a id */ ++#define BCM4328_D11DUAL_ID 0x4314 /* 4328/4312 802.11a/g id */ ++#define BCM4328_D11G_ID 0x4315 /* 4328/4312 802.11g id */ ++#define BCM4328_D11A_ID 0x4316 /* 4328/4312 802.11a id */ ++#define BCM4318_D11G_ID 0x4318 /* 4318 802.11b/g id */ ++#define BCM4318_D11DUAL_ID 0x4319 /* 4318 802.11a/b/g id */ ++#define BCM4318_D11A_ID 0x431a /* 4318 802.11a id */ ++#define BCM4325_D11DUAL_ID 0x431b /* 4325 802.11a/g id */ ++#define BCM4325_D11G_ID 0x431c /* 4325 802.11g id */ ++#define BCM4325_D11A_ID 0x431d /* 4325 802.11a id */ ++#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */ ++#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */ ++#define BCM4306_UART_ID 0x4322 /* 4306 uart */ ++#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */ ++#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */ ++#define BCM4306_D11G_ID2 0x4325 /* BCM4306_D11G_ID; INF w/loose binding war */ ++#define BCM4321_D11N_ID 0x4328 /* 4321 802.11n dualband id */ ++#define BCM4321_D11N2G_ID 0x4329 /* 4321 802.11n 2.4Ghz band id */ ++#define BCM4321_D11N5G_ID 0x432a /* 4321 802.11n 5Ghz band id */ ++#define BCM4322_D11N_ID 0x432b /* 4322 802.11n dualband device */ ++#define BCM4322_D11N2G_ID 0x432c /* 4322 802.11n 2.4GHz device */ ++#define BCM4322_D11N5G_ID 0x432d /* 4322 802.11n 5GHz device */ ++#define BCM4329_D11N_ID 0x432e /* 4329 802.11n dualband device */ ++#define BCM4329_D11N2G_ID 0x432f /* 4329 802.11n 2.4G device */ ++#define BCM4329_D11N5G_ID 0x4330 /* 4329 802.11n 5G device */ ++#define BCM4315_D11DUAL_ID 0x4334 /* 4315 802.11a/g id */ ++#define BCM4315_D11G_ID 0x4335 /* 4315 802.11g id */ ++#define BCM4315_D11A_ID 0x4336 /* 4315 802.11a id */ ++#define BCM4319_D11N_ID 0x4337 /* 4319 802.11n dualband device */ ++#define BCM4319_D11N2G_ID 0x4338 /* 4319 802.11n 2.4G device */ ++#define BCM4319_D11N5G_ID 0x4339 /* 4319 802.11n 5G device */ ++#define BCM43231_D11N2G_ID 0x4340 /* 43231 802.11n 2.4GHz device */ ++#define BCM43221_D11N2G_ID 0x4341 /* 43221 802.11n 2.4GHz device */ ++#define BCM43222_D11N_ID 0x4350 /* 43222 802.11n dualband device */ ++#define BCM43222_D11N2G_ID 0x4351 /* 43222 802.11n 2.4GHz device */ ++#define BCM43222_D11N5G_ID 0x4352 /* 43222 802.11n 5GHz device */ ++#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ ++#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db device */ ++#define BCM43226_D11N_ID 0x4354 /* 43226 802.11n dualband device */ ++#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ ++#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ ++#define BCM43236_D11N5G_ID 0x4348 /* 43236 802.11n 5GHz device */ ++#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ ++#define BCM43421_D11N_ID 0xA99D /* 43421 802.11n dualband device */ ++#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ ++#define BCM4330_D11N_ID 0x4360 /* 4330 802.11n dualband device */ ++#define BCM4330_D11N2G_ID 0x4361 /* 4330 802.11n 2.4G device */ ++#define BCM4330_D11N5G_ID 0x4362 /* 4330 802.11n 5G device */ ++#define BCM4336_D11N_ID 0x4343 /* 4336 802.11n 2.4GHz device */ ++#define BCM6362_D11N_ID 0x435f /* 6362 802.11n dualband device */ ++#define BCM4331_D11N_ID 0x4331 /* 4331 802.11n dualband id */ ++#define BCM4331_D11N2G_ID 0x4332 /* 4331 802.11n 2.4Ghz band id */ ++#define BCM4331_D11N5G_ID 0x4333 /* 4331 802.11n 5Ghz band id */ ++#define BCM43237_D11N_ID 0x4355 /* 43237 802.11n dualband device */ ++#define BCM43237_D11N5G_ID 0x4356 /* 43237 802.11n 5GHz device */ ++#define BCM43227_D11N2G_ID 0x4358 /* 43228 802.11n 2.4GHz device */ ++#define BCM43228_D11N_ID 0x4359 /* 43228 802.11n DualBand device */ ++#define BCM43228_D11N5G_ID 0x435a /* 43228 802.11n 5GHz device */ ++#define BCM43362_D11N_ID 0x4363 /* 43362 802.11n 2.4GHz device */ ++#define BCM43239_D11N_ID 0x4370 /* 43239 802.11n dualband device */ ++#define BCM4324_D11N_ID 0x4374 /* 4324 802.11n dualband device */ ++#define BCM43217_D11N2G_ID 0x43a9 /* 43217 802.11n 2.4GHz device */ ++#define BCM43131_D11N2G_ID 0x43aa /* 43131 802.11n 2.4GHz device */ ++#define BCM4314_D11N2G_ID 0x4364 /* 4314 802.11n 2.4G device */ ++#define BCM43142_D11N2G_ID 0x4365 /* 43142 802.11n 2.4G device */ ++#define BCM4334_D11N_ID 0x4380 /* 4334 802.11n dualband device */ ++#define BCM4334_D11N2G_ID 0x4381 /* 4334 802.11n 2.4G device */ ++#define BCM4334_D11N5G_ID 0x4382 /* 4334 802.11n 5G device */ ++#define BCM4360_D11AC_ID 0x43a0 ++#define BCM4360_D11AC2G_ID 0x43a1 ++#define BCM4360_D11AC5G_ID 0x43a2 ++#define BCM4335_D11AC_ID 0x43ae ++#define BCM4335_D11AC2G_ID 0x43af ++#define BCM4335_D11AC5G_ID 0x43b0 ++#define BCM4352_D11AC_ID 0x43b1 /* 4352 802.11ac dualband device */ ++#define BCM4352_D11AC2G_ID 0x43b2 /* 4352 802.11ac 2.4G device */ ++#define BCM4352_D11AC5G_ID 0x43b3 /* 4352 802.11ac 5G device */ ++ ++/* PCI Subsystem ID */ ++#define BCM943228HMB_SSID_VEN1 0x0607 ++#define BCM94313HMGBL_SSID_VEN1 0x0608 ++#define BCM94313HMG_SSID_VEN1 0x0609 ++ ++ ++#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */ ++#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */ ++#define FPGA_JTAGM_ID 0x43f0 /* FPGA jtagm device id */ ++#define BCM_JTAGM_ID 0x43f1 /* BCM jtagm device id */ ++#define SDIOH_FPGA_ID 0x43f2 /* sdio host fpga */ ++#define BCM_SDIOH_ID 0x43f3 /* BCM sdio host id */ ++#define SDIOD_FPGA_ID 0x43f4 /* sdio device fpga */ ++#define SPIH_FPGA_ID 0x43f5 /* PCI SPI Host Controller FPGA */ ++#define BCM_SPIH_ID 0x43f6 /* Synopsis SPI Host Controller */ ++#define MIMO_FPGA_ID 0x43f8 /* FPGA mimo minimacphy device id */ ++#define BCM_JTAGM2_ID 0x43f9 /* BCM alternate jtagm device id */ ++#define SDHCI_FPGA_ID 0x43fa /* Standard SDIO Host Controller FPGA */ ++#define BCM4402_ENET_ID 0x4402 /* 4402 enet */ ++#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */ ++#define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */ ++#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */ ++#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */ ++#define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */ ++#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */ ++#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */ ++#define BCM47XX_AUDIO_ID 0x4711 /* 47xx audio codec */ ++#define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */ ++#define BCM47XX_ENET_ID 0x4713 /* 47xx enet */ ++#define BCM47XX_EXT_ID 0x4714 /* 47xx external i/f */ ++#define BCM47XX_GMAC_ID 0x4715 /* 47xx Unimac based GbE */ ++#define BCM47XX_USBH_ID 0x4716 /* 47xx usb host */ ++#define BCM47XX_USBD_ID 0x4717 /* 47xx usb device */ ++#define BCM47XX_IPSEC_ID 0x4718 /* 47xx ipsec */ ++#define BCM47XX_ROBO_ID 0x4719 /* 47xx/53xx roboswitch core */ ++#define BCM47XX_USB20H_ID 0x471a /* 47xx usb 2.0 host */ ++#define BCM47XX_USB20D_ID 0x471b /* 47xx usb 2.0 device */ ++#define BCM47XX_ATA100_ID 0x471d /* 47xx parallel ATA */ ++#define BCM47XX_SATAXOR_ID 0x471e /* 47xx serial ATA & XOR DMA */ ++#define BCM47XX_GIGETH_ID 0x471f /* 47xx GbE (5700) */ ++#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */ ++#define BCM4716_DEVICE_ID 0x4722 /* 4716 base devid */ ++#define BCM47XX_SMBUS_EMU_ID 0x47fe /* 47xx emulated SMBus device */ ++#define BCM47XX_XOR_EMU_ID 0x47ff /* 47xx emulated XOR engine */ ++#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */ ++#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */ ++#define JINVANI_SDIOH_ID 0x4743 /* Jinvani SDIO Gold Host */ ++#define BCM27XX_SDIOH_ID 0x2702 /* BCM27xx Standard SDIO Host */ ++#define PCIXX21_FLASHMEDIA_ID 0x803b /* TI PCI xx21 Standard Host Controller */ ++#define PCIXX21_SDIOH_ID 0x803c /* TI PCI xx21 Standard Host Controller */ ++#define R5C822_SDIOH_ID 0x0822 /* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host */ ++#define JMICRON_SDIOH_ID 0x2381 /* JMicron Standard SDIO Host Controller */ ++ ++/* Chip IDs */ ++#define BCM4306_CHIP_ID 0x4306 /* 4306 chipcommon chipid */ ++#define BCM4311_CHIP_ID 0x4311 /* 4311 PCIe 802.11a/b/g */ ++#define BCM43111_CHIP_ID 43111 /* 43111 chipcommon chipid (OTP chipid) */ ++#define BCM43112_CHIP_ID 43112 /* 43112 chipcommon chipid (OTP chipid) */ ++#define BCM4312_CHIP_ID 0x4312 /* 4312 chipcommon chipid */ ++#define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */ ++#define BCM43131_CHIP_ID 43131 /* 43131 chip id (OTP chipid) */ ++#define BCM4315_CHIP_ID 0x4315 /* 4315 chip id */ ++#define BCM4318_CHIP_ID 0x4318 /* 4318 chipcommon chipid */ ++#define BCM4319_CHIP_ID 0x4319 /* 4319 chip id */ ++#define BCM4320_CHIP_ID 0x4320 /* 4320 chipcommon chipid */ ++#define BCM4321_CHIP_ID 0x4321 /* 4321 chipcommon chipid */ ++#define BCM43217_CHIP_ID 43217 /* 43217 chip id (OTP chipid) */ ++#define BCM4322_CHIP_ID 0x4322 /* 4322 chipcommon chipid */ ++#define BCM43221_CHIP_ID 43221 /* 43221 chipcommon chipid (OTP chipid) */ ++#define BCM43222_CHIP_ID 43222 /* 43222 chipcommon chipid */ ++#define BCM43224_CHIP_ID 43224 /* 43224 chipcommon chipid */ ++#define BCM43225_CHIP_ID 43225 /* 43225 chipcommon chipid */ ++#define BCM43227_CHIP_ID 43227 /* 43227 chipcommon chipid */ ++#define BCM43228_CHIP_ID 43228 /* 43228 chipcommon chipid */ ++#define BCM43226_CHIP_ID 43226 /* 43226 chipcommon chipid */ ++#define BCM43231_CHIP_ID 43231 /* 43231 chipcommon chipid (OTP chipid) */ ++#define BCM43234_CHIP_ID 43234 /* 43234 chipcommon chipid */ ++#define BCM43235_CHIP_ID 43235 /* 43235 chipcommon chipid */ ++#define BCM43236_CHIP_ID 43236 /* 43236 chipcommon chipid */ ++#define BCM43237_CHIP_ID 43237 /* 43237 chipcommon chipid */ ++#define BCM43238_CHIP_ID 43238 /* 43238 chipcommon chipid */ ++#define BCM43239_CHIP_ID 43239 /* 43239 chipcommon chipid */ ++#define BCM43420_CHIP_ID 43420 /* 43222 chipcommon chipid (OTP, RBBU) */ ++#define BCM43421_CHIP_ID 43421 /* 43224 chipcommon chipid (OTP, RBBU) */ ++#define BCM43428_CHIP_ID 43428 /* 43228 chipcommon chipid (OTP, RBBU) */ ++#define BCM43431_CHIP_ID 43431 /* 4331 chipcommon chipid (OTP, RBBU) */ ++#define BCM43460_CHIP_ID 43460 /* 4360 chipcommon chipid (OTP, RBBU) */ ++#define BCM4325_CHIP_ID 0x4325 /* 4325 chip id */ ++#define BCM4328_CHIP_ID 0x4328 /* 4328 chip id */ ++#define BCM4329_CHIP_ID 0x4329 /* 4329 chipcommon chipid */ ++#define BCM4331_CHIP_ID 0x4331 /* 4331 chipcommon chipid */ ++#define BCM4336_CHIP_ID 0x4336 /* 4336 chipcommon chipid */ ++#define BCM43362_CHIP_ID 43362 /* 43362 chipcommon chipid */ ++#define BCM4330_CHIP_ID 0x4330 /* 4330 chipcommon chipid */ ++#define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */ ++#define BCM4314_CHIP_ID 0x4314 /* 4314 chipcommon chipid */ ++#define BCM43142_CHIP_ID 43142 /* 43142 chipcommon chipid */ ++#define BCM4324_CHIP_ID 0x4324 /* 4324 chipcommon chipid */ ++#define BCM43242_CHIP_ID 43242 /* 43242 chipcommon chipid */ ++#define BCM4334_CHIP_ID 0x4334 /* 4334 chipcommon chipid */ ++#define BCM4335_CHIP_ID 0x4335 ++#define BCM4360_CHIP_ID 0x4360 ++#define BCM43526_CHIP_ID 0xAA06 ++#define BCM4352_CHIP_ID 0x4352 ++ ++#define BCM4342_CHIP_ID 4342 /* 4342 chipcommon chipid (OTP, RBBU) */ ++#define BCM4402_CHIP_ID 0x4402 /* 4402 chipid */ ++#define BCM4704_CHIP_ID 0x4704 /* 4704 chipcommon chipid */ ++#define BCM4706_CHIP_ID 0x5300 /* 4706 chipcommon chipid */ ++#define BCM4710_CHIP_ID 0x4710 /* 4710 chipid */ ++#define BCM4712_CHIP_ID 0x4712 /* 4712 chipcommon chipid */ ++#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ ++#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */ ++#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ ++#define BCM4749_CHIP_ID 0x4749 /* 5357 chipcommon chipid (OTP, RBBU) */ ++#define BCM4785_CHIP_ID 0x4785 /* 4785 chipcommon chipid */ ++#define BCM5350_CHIP_ID 0x5350 /* 5350 chipcommon chipid */ ++#define BCM5352_CHIP_ID 0x5352 /* 5352 chipcommon chipid */ ++#define BCM5354_CHIP_ID 0x5354 /* 5354 chipcommon chipid */ ++#define BCM5365_CHIP_ID 0x5365 /* 5365 chipcommon chipid */ ++#define BCM5356_CHIP_ID 0x5356 /* 5356 chipcommon chipid */ ++#define BCM5357_CHIP_ID 0x5357 /* 5357 chipcommon chipid */ ++#define BCM53572_CHIP_ID 53572 /* 53572 chipcommon chipid */ ++#define BCM53010_CHIP_ID 53010 /* NS chipcommon chipid */ ++#define BCM56150_CHIP_ID 56150 /* HR2 chipcommon chipid */ ++#define BCM56340_CHIP_ID 56340 /* HX4 chipcommon chipid */ ++#define BCM53020_CHIP_ID 53020 /* NSP chipcommon chipid */ ++#define BCM56450_CHIP_ID 56450 /* KT2 chipcommon chipid */ ++ ++#if defined(CONFIG_MACH_NS) ++#define BCMIPROC_CHIP_ID BCM53010_CHIP_ID ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define BCMIPROC_CHIP_ID BCM56340_CHIP_ID ++#elif defined(CONFIG_MACH_HR2) ++#define BCMIPROC_CHIP_ID BCM56150_CHIP_ID ++#elif defined(CONFIG_MACH_NSP) ++#define BCMIPROC_CHIP_ID BCM53020_CHIP_ID ++#elif defined(CONFIG_MACH_KT2) ++#define BCMIPROC_CHIP_ID BCM56450_CHIP_ID ++#endif ++ ++#define IS_BCM5301X_CHIP_ID(id) (1) ++#define IS_IPROC_CHIP_ID(id) (((id) >= 53010 && (id) <= 53019) || \ ++ ((id) >= 56150 && (id) <= 56159) || \ ++ ((id) >= 56340 && (id) <= 56349) || \ ++ ((id) >= 53020 && (id) <= 53029) || \ ++ ((id) >= 56450 && (id) <= 56459)) ++ ++/* Package IDs */ ++#define BCM4303_PKG_ID 2 /* 4303 package id */ ++#define BCM4309_PKG_ID 1 /* 4309 package id */ ++#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */ ++#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */ ++#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */ ++#define BCM4328USBD11G_PKG_ID 2 /* 4328 802.11g USB package id */ ++#define BCM4328USBDUAL_PKG_ID 3 /* 4328 802.11a/g USB package id */ ++#define BCM4328SDIOD11G_PKG_ID 4 /* 4328 802.11g SDIO package id */ ++#define BCM4328SDIODUAL_PKG_ID 5 /* 4328 802.11a/g SDIO package id */ ++#define BCM4329_289PIN_PKG_ID 0 /* 4329 289-pin package id */ ++#define BCM4329_182PIN_PKG_ID 1 /* 4329N 182-pin package id */ ++#define BCM5354E_PKG_ID 1 /* 5354E package id */ ++#define BCM4716_PKG_ID 8 /* 4716 package id */ ++#define BCM4717_PKG_ID 9 /* 4717 package id */ ++#define BCM4718_PKG_ID 10 /* 4718 package id */ ++#define BCM5356_PKG_NONMODE 1 /* 5356 package without nmode suppport */ ++#define BCM5358U_PKG_ID 8 /* 5358U package id */ ++#define BCM5358_PKG_ID 9 /* 5358 package id */ ++#define BCM47186_PKG_ID 10 /* 47186 package id */ ++#define BCM5357_PKG_ID 11 /* 5357 package id */ ++#define BCM5356U_PKG_ID 12 /* 5356U package id */ ++#define BCM53572_PKG_ID 8 /* 53572 package id */ ++#define BCM5357C0_PKG_ID 8 /* 5357c0 package id (the same as 53572) */ ++#define BCM47188_PKG_ID 9 /* 47188 package id */ ++#define BCM5358C0_PKG_ID 0xa /* 5358c0 package id */ ++#define BCM5356C0_PKG_ID 0xb /* 5356c0 package id */ ++#define BCM4331TT_PKG_ID 8 /* 4331 12x12 package id */ ++#define BCM4331TN_PKG_ID 9 /* 4331 12x9 package id */ ++#define BCM4331TNA0_PKG_ID 0xb /* 4331 12x9 package id */ ++#define BCM4706L_PKG_ID 1 /* 4706L package id */ ++ ++#define HDLSIM5350_PKG_ID 1 /* HDL simulator package id for a 5350 */ ++#define HDLSIM_PKG_ID 14 /* HDL simulator package id */ ++#define HWSIM_PKG_ID 15 /* Hardware simulator package id */ ++#define BCM43224_FAB_CSM 0x8 /* the chip is manufactured by CSM */ ++#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */ ++#define BCM4336_WLBGA_PKG_ID 0x8 ++#define BCM4330_WLBGA_PKG_ID 0x0 ++#define BCM4314PCIE_ARM_PKG_ID (8 | 0) /* 4314 QFN PCI package id, bit 3 tie high */ ++#define BCM4314SDIO_PKG_ID (8 | 1) /* 4314 QFN SDIO package id */ ++#define BCM4314PCIE_PKG_ID (8 | 2) /* 4314 QFN PCI (ARM-less) package id */ ++#define BCM4314SDIO_ARM_PKG_ID (8 | 3) /* 4314 QFN SDIO (ARM-less) package id */ ++#define BCM4314SDIO_FPBGA_PKG_ID (8 | 4) /* 4314 FpBGA SDIO package id */ ++#define BCM4314DEV_PKG_ID (8 | 6) /* 4314 Developement package id */ ++ ++#define BCM4707_PKG_ID 1 /* 4707 package id */ ++#define BCM4708_PKG_ID 2 /* 4708 package id */ ++#define BCM4709_PKG_ID 0 /* 4709 package id */ ++ ++#define PCIXX21_FLASHMEDIA0_ID 0x8033 /* TI PCI xx21 Standard Host Controller */ ++#define PCIXX21_SDIOH0_ID 0x8034 /* TI PCI xx21 Standard Host Controller */ ++ ++#define BCM4335_WLCSP_PKG_ID (0x0) /* WLCSP Module/Mobile SDIO/HSIC. */ ++#define BCM4335_FCBGA_PKG_ID (0x1) /* FCBGA PC/Embeded/Media PCIE/SDIO */ ++#define BCM4335_WLBGA_PKG_ID (0x2) /* WLBGA COB/Mobile SDIO/HSIC. */ ++#define BCM4335_FCBGAD_PKG_ID (0x3) /* FCBGA Debug Debug/Dev All if's. */ ++#define BCM4335_PKG_MASK (0x3) ++ ++/* boardflags */ ++#define BFL_BTC2WIRE 0x00000001 /* old 2wire Bluetooth coexistence, OBSOLETE */ ++#define BFL_BTCOEX 0x00000001 /* Board supports BTCOEX */ ++#define BFL_PACTRL 0x00000002 /* Board has gpio 9 controlling the PA */ ++#define BFL_AIRLINEMODE 0x00000004 /* Board implements gpio 13 radio disable indication, UNUSED */ ++#define BFL_ADCDIV 0x00000008 /* Board has the rssi ADC divider */ ++#define BFL_ENETROBO 0x00000010 /* Board has robo switch or core */ ++#define BFL_NOPLLDOWN 0x00000020 /* Not ok to power down the chip pll and oscillator */ ++#define BFL_CCKHIPWR 0x00000040 /* Can do high-power CCK transmission */ ++#define BFL_ENETADM 0x00000080 /* Board has ADMtek switch */ ++#define BFL_ENETVLAN 0x00000100 /* Board has VLAN capability */ ++#define BFL_UNUSED 0x00000200 ++#define BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ ++#define BFL_FEM 0x00000800 /* Board supports the Front End Module */ ++#define BFL_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */ ++#define BFL_HGPA 0x00002000 /* Board has a high gain PA */ ++#define BFL_BTC2WIRE_ALTGPIO 0x00004000 /* Board's BTC 2wire is in the alternate gpios */ ++#define BFL_ALTIQ 0x00008000 /* Alternate I/Q settings */ ++#define BFL_NOPA 0x00010000 /* Board has no PA */ ++#define BFL_RSSIINV 0x00020000 /* Board's RSSI uses positive slope(not TSSI) */ ++#define BFL_PAREF 0x00040000 /* Board uses the PARef LDO */ ++#define BFL_3TSWITCH 0x00080000 /* Board uses a triple throw switch shared with BT */ ++#define BFL_PHASESHIFT 0x00100000 /* Board can support phase shifter */ ++#define BFL_BUCKBOOST 0x00200000 /* Power topology uses BUCKBOOST */ ++#define BFL_FEM_BT 0x00400000 /* Board has FEM and switch to share antenna w/ BT */ ++#define BFL_NOCBUCK 0x00800000 /* Power topology doesn't use CBUCK */ ++#define BFL_CCKFAVOREVM 0x01000000 /* Favor CCK EVM over spectral mask */ ++#define BFL_PALDO 0x02000000 /* Power topology uses PALDO */ ++#define BFL_LNLDO2_2P5 0x04000000 /* Select 2.5V as LNLDO2 output voltage */ ++#define BFL_FASTPWR 0x08000000 ++#define BFL_UCPWRCTL_MININDX 0x08000000 /* Enforce min power index to avoid FEM damage */ ++#define BFL_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */ ++#define BFL_TRSW_1by2 0x20000000 /* Board has 2 TRSW's in 1by2 designs */ ++#define BFL_LO_TRSW_R_5GHz 0x40000000 /* In 5G do not throw TRSW to T for clipLO gain */ ++#define BFL_ELNA_GAINDEF 0x80000000 /* Backoff InitGain based on elna_2g/5g field ++ * when this flag is set ++ */ ++#define BFL_EXTLNA_TX 0x20000000 /* Temp boardflag to indicate to */ ++ ++/* boardflags2 */ ++#define BFL2_RXBB_INT_REG_DIS 0x00000001 /* Board has an external rxbb regulator */ ++#define BFL2_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */ ++#define BFL2_TXPWRCTRL_EN 0x00000004 /* Board permits enabling TX Power Control */ ++#define BFL2_2X4_DIV 0x00000008 /* Board supports the 2X4 diversity switch */ ++#define BFL2_5G_PWRGAIN 0x00000010 /* Board supports 5G band power gain */ ++#define BFL2_PCIEWAR_OVR 0x00000020 /* Board overrides ASPM and Clkreq settings */ ++#define BFL2_CAESERS_BRD 0x00000040 /* Board is Caesers brd (unused by sw) */ ++#define BFL2_BTC3WIRE 0x00000080 /* Board support legacy 3 wire or 4 wire */ ++#define BFL2_BTCLEGACY 0x00000080 /* Board support legacy 3/4 wire, to replace ++ * BFL2_BTC3WIRE ++ */ ++#define BFL2_SKWRKFEM_BRD 0x00000100 /* 4321mcm93 board uses Skyworks FEM */ ++#define BFL2_SPUR_WAR 0x00000200 /* Board has a WAR for clock-harmonic spurs */ ++#define BFL2_GPLL_WAR 0x00000400 /* Flag to narrow G-band PLL loop b/w */ ++#define BFL2_TRISTATE_LED 0x00000800 /* Tri-state the LED */ ++#define BFL2_SINGLEANT_CCK 0x00001000 /* Tx CCK pkts on Ant 0 only */ ++#define BFL2_2G_SPUR_WAR 0x00002000 /* WAR to reduce and avoid clock-harmonic spurs in 2G */ ++#define BFL2_BPHY_ALL_TXCORES 0x00004000 /* Transmit bphy frames using all tx cores */ ++#define BFL2_FCC_BANDEDGE_WAR 0x00008000 /* Activates WAR to improve FCC bandedge performance */ ++#define BFL2_GPLL_WAR2 0x00010000 /* Flag to widen G-band PLL loop b/w */ ++#define BFL2_IPALVLSHIFT_3P3 0x00020000 ++#define BFL2_INTERNDET_TXIQCAL 0x00040000 /* Use internal envelope detector for TX IQCAL */ ++#define BFL2_XTALBUFOUTEN 0x00080000 /* Keep the buffered Xtal output from radio on */ ++ /* Most drivers will turn it off without this flag */ ++ /* to save power. */ ++ ++#define BFL2_ANAPACTRL_2G 0x00100000 /* 2G ext PAs are controlled by analog PA ctrl lines */ ++#define BFL2_ANAPACTRL_5G 0x00200000 /* 5G ext PAs are controlled by analog PA ctrl lines */ ++#define BFL2_ELNACTRL_TRSW_2G 0x00400000 /* AZW4329: 2G gmode_elna_gain controls TR Switch */ ++#define BFL2_BT_SHARE_ANT0 0x00800000 /* share core0 antenna with BT */ ++#define BFL2_TEMPSENSE_HIGHER 0x01000000 /* The tempsense threshold can sustain higher value ++ * than programmed. The exact delta is decided by ++ * driver per chip/boardtype. This can be used ++ * when tempsense qualification happens after shipment ++ */ ++#define BFL2_BTC3WIREONLY 0x02000000 /* standard 3 wire btc only. 4 wire not supported */ ++#define BFL2_PWR_NOMINAL 0x04000000 /* 0: power reduction on, 1: no power reduction */ ++#define BFL2_EXTLNA_PWRSAVE 0x08000000 /* boardflag to enable ucode to apply power save */ ++ /* ucode control of eLNA during Tx */ ++#define BFL2_4313_RADIOREG 0x10000000 ++ /* board rework */ ++#define BFL2_SDR_EN 0x20000000 /* SDR enabled or disabled */ ++ ++/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ ++#define BOARD_GPIO_BTC3W_IN 0x850 /* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */ ++#define BOARD_GPIO_BTC3W_OUT 0x020 /* bit 5 is TX_CONF */ ++#define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistence Input */ ++#define BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistence Out */ ++#define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistence Input */ ++#define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistence Out */ ++#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */ ++#define BOARD_GPIO_12 0x1000 /* gpio 12 */ ++#define BOARD_GPIO_13 0x2000 /* gpio 13 */ ++#define BOARD_GPIO_BTC4_IN 0x0800 /* gpio 11, coex4, in */ ++#define BOARD_GPIO_BTC4_BT 0x2000 /* gpio 12, coex4, bt active */ ++#define BOARD_GPIO_BTC4_STAT 0x4000 /* gpio 14, coex4, status */ ++#define BOARD_GPIO_BTC4_WLAN 0x8000 /* gpio 15, coex4, wlan active */ ++#define BOARD_GPIO_1_WLAN_PWR 0x02 /* throttle WLAN power on X21 board */ ++#define BOARD_GPIO_3_WLAN_PWR 0x08 /* throttle WLAN power on X28 board */ ++#define BOARD_GPIO_4_WLAN_PWR 0x10 /* throttle WLAN power on X19 board */ ++ ++#define GPIO_BTC4W_OUT_4312 0x010 /* bit 4 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_43224 0x020 /* bit 5 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_43224_SHARED 0x0e0 /* bit 5 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_43225 0x0e0 /* bit 5 BT_IODISABLE, bit 6 SW_BT, bit 7 SW_WL */ ++#define GPIO_BTC4W_OUT_43421 0x020 /* bit 5 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_4313 0x060 /* bit 5 SW_BT, bit 6 SW_WL */ ++#define GPIO_BTC4W_OUT_4331_SHARED 0x010 /* GPIO 4 */ ++ ++#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ ++#define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ ++#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal power-up */ ++#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL power-down */ ++ ++/* power control defines */ ++#define PLL_DELAY 150 /* us pll on delay */ ++#define FREF_DELAY 200 /* us fref change delay */ ++#define MIN_SLOW_CLK 32 /* us Slow clock period */ ++#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* Reference Board Types */ ++#define BU4710_BOARD 0x0400 ++#define VSIM4710_BOARD 0x0401 ++#define QT4710_BOARD 0x0402 ++ ++#define BU4309_BOARD 0x040a ++#define BCM94309CB_BOARD 0x040b ++#define BCM94309MP_BOARD 0x040c ++#define BCM4309AP_BOARD 0x040d ++ ++#define BCM94302MP_BOARD 0x040e ++ ++#define BU4306_BOARD 0x0416 ++#define BCM94306CB_BOARD 0x0417 ++#define BCM94306MP_BOARD 0x0418 ++ ++#define BCM94710D_BOARD 0x041a ++#define BCM94710R1_BOARD 0x041b ++#define BCM94710R4_BOARD 0x041c ++#define BCM94710AP_BOARD 0x041d ++ ++#define BU2050_BOARD 0x041f ++ ++#define BCM94306P50_BOARD 0x0420 ++ ++#define BCM94309G_BOARD 0x0421 ++ ++#define BU4704_BOARD 0x0423 ++#define BU4702_BOARD 0x0424 ++ ++#define BCM94306PC_BOARD 0x0425 /* pcmcia 3.3v 4306 card */ ++ ++#define MPSG4306_BOARD 0x0427 ++ ++#define BCM94702MN_BOARD 0x0428 ++ ++/* BCM4702 1U CompactPCI Board */ ++#define BCM94702CPCI_BOARD 0x0429 ++ ++/* BCM4702 with BCM95380 VLAN Router */ ++#define BCM95380RR_BOARD 0x042a ++ ++/* cb4306 with SiGe PA */ ++#define BCM94306CBSG_BOARD 0x042b ++ ++/* cb4306 with SiGe PA */ ++#define PCSG94306_BOARD 0x042d ++ ++/* bu4704 with sdram */ ++#define BU4704SD_BOARD 0x042e ++ ++/* Dual 11a/11g Router */ ++#define BCM94704AGR_BOARD 0x042f ++ ++/* 11a-only minipci */ ++#define BCM94308MP_BOARD 0x0430 ++ ++/* 4306/gprs combo */ ++#define BCM94306GPRS_BOARD 0x0432 ++ ++/* BCM5365/BCM4704 FPGA Bringup Board */ ++#define BU5365_FPGA_BOARD 0x0433 ++ ++#define BU4712_BOARD 0x0444 ++#define BU4712SD_BOARD 0x045d ++#define BU4712L_BOARD 0x045f ++ ++/* BCM4712 boards */ ++#define BCM94712AP_BOARD 0x0445 ++#define BCM94712P_BOARD 0x0446 ++ ++/* BCM4318 boards */ ++#define BU4318_BOARD 0x0447 ++#define CB4318_BOARD 0x0448 ++#define MPG4318_BOARD 0x0449 ++#define MP4318_BOARD 0x044a ++#define SD4318_BOARD 0x044b ++ ++/* BCM4313 boards */ ++#define BCM94313BU_BOARD 0x050f ++#define BCM94313HM_BOARD 0x0510 ++#define BCM94313EPA_BOARD 0x0511 ++#define BCM94313HMG_BOARD 0x051C ++ ++/* BCM63XX boards */ ++#define BCM96338_BOARD 0x6338 ++#define BCM96348_BOARD 0x6348 ++#define BCM96358_BOARD 0x6358 ++#define BCM96368_BOARD 0x6368 ++ ++/* Another mp4306 with SiGe */ ++#define BCM94306P_BOARD 0x044c ++ ++/* mp4303 */ ++#define BCM94303MP_BOARD 0x044e ++ ++/* mpsgh4306 */ ++#define BCM94306MPSGH_BOARD 0x044f ++ ++/* BRCM 4306 w/ Front End Modules */ ++#define BCM94306MPM 0x0450 ++#define BCM94306MPL 0x0453 ++ ++/* 4712agr */ ++#define BCM94712AGR_BOARD 0x0451 ++ ++/* pcmcia 4303 */ ++#define PC4303_BOARD 0x0454 ++ ++/* 5350K */ ++#define BCM95350K_BOARD 0x0455 ++ ++/* 5350R */ ++#define BCM95350R_BOARD 0x0456 ++ ++/* 4306mplna */ ++#define BCM94306MPLNA_BOARD 0x0457 ++ ++/* 4320 boards */ ++#define BU4320_BOARD 0x0458 ++#define BU4320S_BOARD 0x0459 ++#define BCM94320PH_BOARD 0x045a ++ ++/* 4306mph */ ++#define BCM94306MPH_BOARD 0x045b ++ ++/* 4306pciv */ ++#define BCM94306PCIV_BOARD 0x045c ++ ++#define BU4712SD_BOARD 0x045d ++ ++#define BCM94320PFLSH_BOARD 0x045e ++ ++#define BU4712L_BOARD 0x045f ++#define BCM94712LGR_BOARD 0x0460 ++#define BCM94320R_BOARD 0x0461 ++ ++#define BU5352_BOARD 0x0462 ++ ++#define BCM94318MPGH_BOARD 0x0463 ++ ++#define BU4311_BOARD 0x0464 ++#define BCM94311MC_BOARD 0x0465 ++#define BCM94311MCAG_BOARD 0x0466 ++ ++#define BCM95352GR_BOARD 0x0467 ++ ++/* bcm95351agr */ ++#define BCM95351AGR_BOARD 0x0470 ++ ++/* bcm94704mpcb */ ++#define BCM94704MPCB_BOARD 0x0472 ++ ++/* 4785 boards */ ++#define BU4785_BOARD 0x0478 ++ ++/* 4321 boards */ ++#define BU4321_BOARD 0x046b ++#define BU4321E_BOARD 0x047c ++#define MP4321_BOARD 0x046c ++#define CB2_4321_BOARD 0x046d ++#define CB2_4321_AG_BOARD 0x0066 ++#define MC4321_BOARD 0x046e ++ ++/* 4328 boards */ ++#define BU4328_BOARD 0x0481 ++#define BCM4328SDG_BOARD 0x0482 ++#define BCM4328SDAG_BOARD 0x0483 ++#define BCM4328UG_BOARD 0x0484 ++#define BCM4328UAG_BOARD 0x0485 ++#define BCM4328PC_BOARD 0x0486 ++#define BCM4328CF_BOARD 0x0487 ++ ++/* 4325 boards */ ++#define BCM94325DEVBU_BOARD 0x0490 ++#define BCM94325BGABU_BOARD 0x0491 ++ ++#define BCM94325SDGWB_BOARD 0x0492 ++ ++#define BCM94325SDGMDL_BOARD 0x04aa ++#define BCM94325SDGMDL2_BOARD 0x04c6 ++#define BCM94325SDGMDL3_BOARD 0x04c9 ++ ++#define BCM94325SDABGWBA_BOARD 0x04e1 ++ ++/* 4322 boards */ ++#define BCM94322MC_SSID 0x04a4 ++#define BCM94322USB_SSID 0x04a8 /* dualband */ ++#define BCM94322HM_SSID 0x04b0 ++#define BCM94322USB2D_SSID 0x04bf /* single band discrete front end */ ++ ++/* 4312 boards */ ++#define BCM4312MCGSG_BOARD 0x04b5 ++ ++/* 4315 boards */ ++#define BCM94315DEVBU_SSID 0x04c2 ++#define BCM94315USBGP_SSID 0x04c7 ++#define BCM94315BGABU_SSID 0x04ca ++#define BCM94315USBGP41_SSID 0x04cb ++ ++/* 4319 boards */ ++#define BCM94319DEVBU_SSID 0X04e5 ++#define BCM94319USB_SSID 0X04e6 ++#define BCM94319SD_SSID 0X04e7 ++ ++/* 4716 boards */ ++#define BCM94716NR2_SSID 0x04cd ++ ++/* 4319 boards */ ++#define BCM94319DEVBU_SSID 0X04e5 ++#define BCM94319USBNP4L_SSID 0X04e6 ++#define BCM94319WLUSBN4L_SSID 0X04e7 ++#define BCM94319SDG_SSID 0X04ea ++#define BCM94319LCUSBSDN4L_SSID 0X04eb ++#define BCM94319USBB_SSID 0x04ee ++#define BCM94319LCSDN4L_SSID 0X0507 ++#define BCM94319LSUSBN4L_SSID 0X0508 ++#define BCM94319SDNA4L_SSID 0X0517 ++#define BCM94319SDELNA4L_SSID 0X0518 ++#define BCM94319SDELNA6L_SSID 0X0539 ++#define BCM94319ARCADYAN_SSID 0X0546 ++#define BCM94319WINDSOR_SSID 0x0561 ++#define BCM94319MLAP_SSID 0x0562 ++#define BCM94319SDNA_SSID 0x058b ++#define BCM94319BHEMU3_SSID 0x0563 ++#define BCM94319SDHMB_SSID 0x058c ++#define BCM94319SDBREF_SSID 0x05a1 ++#define BCM94319USBSDB_SSID 0x05a2 ++ ++ ++/* 4329 boards */ ++#define BCM94329AGB_SSID 0X04b9 ++#define BCM94329TDKMDL1_SSID 0X04ba ++#define BCM94329TDKMDL11_SSID 0X04fc ++#define BCM94329OLYMPICN18_SSID 0X04fd ++#define BCM94329OLYMPICN90_SSID 0X04fe ++#define BCM94329OLYMPICN90U_SSID 0X050c ++#define BCM94329OLYMPICN90M_SSID 0X050b ++#define BCM94329AGBF_SSID 0X04ff ++#define BCM94329OLYMPICX17_SSID 0X0504 ++#define BCM94329OLYMPICX17M_SSID 0X050a ++#define BCM94329OLYMPICX17U_SSID 0X0509 ++#define BCM94329OLYMPICUNO_SSID 0X0564 ++#define BCM94329MOTOROLA_SSID 0X0565 ++#define BCM94329OLYMPICLOCO_SSID 0X0568 ++/* 4336 SDIO board types */ ++#define BCM94336SD_WLBGABU_SSID 0x0511 ++#define BCM94336SD_WLBGAREF_SSID 0x0519 ++#define BCM94336SDGP_SSID 0x0538 ++#define BCM94336SDG_SSID 0x0519 ++#define BCM94336SDGN_SSID 0x0538 ++#define BCM94336SDGFC_SSID 0x056B ++ ++/* 4330 SDIO board types */ ++#define BCM94330SDG_SSID 0x0528 ++#define BCM94330SD_FCBGABU_SSID 0x052e ++#define BCM94330SD_WLBGABU_SSID 0x052f ++#define BCM94330SD_FCBGA_SSID 0x0530 ++#define BCM94330FCSDAGB_SSID 0x0532 ++#define BCM94330OLYMPICAMG_SSID 0x0549 ++#define BCM94330OLYMPICAMGEPA_SSID 0x054F ++#define BCM94330OLYMPICUNO3_SSID 0x0551 ++#define BCM94330WLSDAGB_SSID 0x0547 ++#define BCM94330CSPSDAGBB_SSID 0x054A ++ ++/* 43224 boards */ ++#define BCM943224X21 0x056e ++#define BCM943224X21_FCC 0x00d1 ++#define BCM943224X21B 0x00e9 ++#define BCM943224M93 0x008b ++#define BCM943224M93A 0x0090 ++#define BCM943224X16 0x0093 ++#define BCM94322X9 0x008d ++#define BCM94322M35e 0x008e ++ ++/* 43228 Boards */ ++#define BCM943228BU8_SSID 0x0540 ++#define BCM943228BU9_SSID 0x0541 ++#define BCM943228BU_SSID 0x0542 ++#define BCM943227HM4L_SSID 0x0543 ++#define BCM943227HMB_SSID 0x0544 ++#define BCM943228HM4L_SSID 0x0545 ++#define BCM943228SD_SSID 0x0573 ++ ++/* 43239 Boards */ ++#define BCM943239MOD_SSID 0x05ac ++#define BCM943239REF_SSID 0x05aa ++ ++/* 4331 boards */ ++#define BCM94331X19 0x00D6 /* X19B */ ++#define BCM94331X28 0x00E4 /* X28 */ ++#define BCM94331X28B 0x010E /* X28B */ ++#define BCM94331PCIEBT3Ax_SSID BCM94331X28 ++#define BCM94331X12_2G_SSID 0x00EC /* X12 2G */ ++#define BCM94331X12_5G_SSID 0x00ED /* X12 5G */ ++#define BCM94331X29B 0x00EF /* X29B */ ++#define BCM94331CSAX_SSID BCM94331X29B ++#define BCM94331X19C 0x00F5 /* X19C */ ++#define BCM94331X33 0x00F4 /* X33 */ ++#define BCM94331BU_SSID 0x0523 ++#define BCM94331S9BU_SSID 0x0524 ++#define BCM94331MC_SSID 0x0525 ++#define BCM94331MCI_SSID 0x0526 ++#define BCM94331PCIEBT4_SSID 0x0527 ++#define BCM94331HM_SSID 0x0574 ++#define BCM94331PCIEDUAL_SSID 0x059B ++#define BCM94331MCH5_SSID 0x05A9 ++#define BCM94331CS_SSID 0x05C6 ++#define BCM94331CD_SSID 0x05DA ++ ++/* 4314 Boards */ ++#define BCM94314BU_SSID 0x05b1 ++ ++/* 53572 Boards */ ++#define BCM953572BU_SSID 0x058D ++#define BCM953572NR2_SSID 0x058E ++#define BCM947188NR2_SSID 0x058F ++#define BCM953572SDRNR2_SSID 0x0590 ++ ++/* 43236 boards */ ++#define BCM943236OLYMPICSULLEY_SSID 0x594 ++#define BCM943236PREPROTOBLU2O3_SSID 0x5b9 ++#define BCM943236USBELNA_SSID 0x5f8 ++ ++/* 4314 Boards */ ++#define BCM94314BUSDIO_SSID 0x05c8 ++#define BCM94314BGABU_SSID 0x05c9 ++#define BCM94314HMEPA_SSID 0x05ca ++#define BCM94314HMEPABK_SSID 0x05cb ++#define BCM94314SUHMEPA_SSID 0x05cc ++#define BCM94314SUHM_SSID 0x05cd ++#define BCM94314HM_SSID 0x05d1 ++ ++/* 4334 Boards */ ++#define BCM94334FCAGBI_SSID 0x05df ++#define BCM94334WLAGBI_SSID 0x05dd ++ ++/* 43217 Boards */ ++#define BCM943217BU_SSID 0x05d5 ++#define BCM943217HM2L_SSID 0x05d6 ++#define BCM943217HMITR2L_SSID 0x05d7 ++ ++/* 43142 Boards */ ++#define BCM943142HM_SSID 0x05e0 ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* # of GPIO pins */ ++#define GPIO_NUMPINS 32 ++ ++/* These values are used by dhd host driver. */ ++#define RDL_RAM_BASE_4319 0x60000000 ++#define RDL_RAM_BASE_4329 0x60000000 ++#define RDL_RAM_SIZE_4319 0x48000 ++#define RDL_RAM_SIZE_4329 0x48000 ++#define RDL_RAM_SIZE_43236 0x70000 ++#define RDL_RAM_BASE_43236 0x60000000 ++#define RDL_RAM_SIZE_4328 0x60000 ++#define RDL_RAM_BASE_4328 0x80000000 ++#define RDL_RAM_SIZE_4322 0x60000 ++#define RDL_RAM_BASE_4322 0x60000000 ++#define RDL_RAM_SIZE_4360 0xE0000 ++#define RDL_RAM_BASE_4360 0x60000000 ++ ++/* generic defs for nvram "muxenab" bits ++* Note: these differ for 4335a0. refer bcmchipc.h for specific mux options. ++*/ ++#define MUXENAB_UART 0x00000001 ++#define MUXENAB_GPIO 0x00000002 ++#define MUXENAB_ERCX 0x00000004 ++#define MUXENAB_JTAG 0x00000008 ++#define MUXENAB_HOST_WAKE 0x00000010 ++ ++/* Boot flags */ ++#define FLASH_KERNEL_NFLASH 0x00000001 ++#define FLASH_BOOT_NFLASH 0x00000002 ++ ++#endif /* _BCMDEVS_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmendian.h b/drivers/bcmdrivers/gmac/src/include/bcmendian.h +new file mode 100755 +index 0000000..6e810d3 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmendian.h +@@ -0,0 +1,324 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Byte order utilities ++ * ++ * $Id: bcmendian.h 241182 2011-02-17 21:50:03Z $ ++ * ++ * This file by default provides proper behavior on little-endian architectures. ++ * On big-endian architectures, IL_BIGENDIAN should be defined. ++ */ ++ ++#ifndef _BCMENDIAN_H_ ++#define _BCMENDIAN_H_ ++ ++#include ++ ++/* Reverse the bytes in a 16-bit value */ ++#define BCMSWAP16(val) \ ++ ((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \ ++ (((uint16)(val) & (uint16)0xff00U) >> 8))) ++ ++/* Reverse the bytes in a 32-bit value */ ++#define BCMSWAP32(val) \ ++ ((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \ ++ (((uint32)(val) & (uint32)0x0000ff00U) << 8) | \ ++ (((uint32)(val) & (uint32)0x00ff0000U) >> 8) | \ ++ (((uint32)(val) & (uint32)0xff000000U) >> 24))) ++ ++/* Reverse the two 16-bit halves of a 32-bit value */ ++#define BCMSWAP32BY16(val) \ ++ ((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \ ++ (((uint32)(val) & (uint32)0xffff0000U) >> 16))) ++ ++/* Byte swapping macros ++ * Host <=> Network (Big Endian) for 16- and 32-bit values ++ * Host <=> Little-Endian for 16- and 32-bit values ++ */ ++#ifndef hton16 ++#ifndef IL_BIGENDIAN ++#define HTON16(i) BCMSWAP16(i) ++#define hton16(i) bcmswap16(i) ++#define HTON32(i) BCMSWAP32(i) ++#define hton32(i) bcmswap32(i) ++#define NTOH16(i) BCMSWAP16(i) ++#define ntoh16(i) bcmswap16(i) ++#define NTOH32(i) BCMSWAP32(i) ++#define ntoh32(i) bcmswap32(i) ++#define LTOH16(i) (i) ++#define ltoh16(i) (i) ++#define LTOH32(i) (i) ++#define ltoh32(i) (i) ++#define HTOL16(i) (i) ++#define htol16(i) (i) ++#define HTOL32(i) (i) ++#define htol32(i) (i) ++#else /* IL_BIGENDIAN */ ++#define HTON16(i) (i) ++#define hton16(i) (i) ++#define HTON32(i) (i) ++#define hton32(i) (i) ++#define NTOH16(i) (i) ++#define ntoh16(i) (i) ++#define NTOH32(i) (i) ++#define ntoh32(i) (i) ++#define LTOH16(i) BCMSWAP16(i) ++#define ltoh16(i) bcmswap16(i) ++#define LTOH32(i) BCMSWAP32(i) ++#define ltoh32(i) bcmswap32(i) ++#define HTOL16(i) BCMSWAP16(i) ++#define htol16(i) bcmswap16(i) ++#define HTOL32(i) BCMSWAP32(i) ++#define htol32(i) bcmswap32(i) ++#endif /* IL_BIGENDIAN */ ++#endif /* hton16 */ ++ ++#ifndef IL_BIGENDIAN ++#define ltoh16_buf(buf, i) ++#define htol16_buf(buf, i) ++#else ++#define ltoh16_buf(buf, i) bcmswap16_buf((uint16 *)(buf), (i)) ++#define htol16_buf(buf, i) bcmswap16_buf((uint16 *)(buf), (i)) ++#endif /* IL_BIGENDIAN */ ++ ++/* Unaligned loads and stores in host byte order */ ++#ifndef IL_BIGENDIAN ++#define load32_ua(a) ltoh32_ua(a) ++#define store32_ua(a, v) htol32_ua_store(v, a) ++#define load16_ua(a) ltoh16_ua(a) ++#define store16_ua(a, v) htol16_ua_store(v, a) ++#else ++#define load32_ua(a) ntoh32_ua(a) ++#define store32_ua(a, v) hton32_ua_store(v, a) ++#define load16_ua(a) ntoh16_ua(a) ++#define store16_ua(a, v) hton16_ua_store(v, a) ++#endif /* IL_BIGENDIAN */ ++ ++#define _LTOH16_UA(cp) ((cp)[0] | ((cp)[1] << 8)) ++#define _LTOH32_UA(cp) ((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24)) ++#define _NTOH16_UA(cp) (((cp)[0] << 8) | (cp)[1]) ++#define _NTOH32_UA(cp) (((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3]) ++ ++#define ltoh_ua(ptr) \ ++ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ ++ sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \ ++ sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr)) : \ ++ *(uint8 *)0) ++ ++#define ntoh_ua(ptr) \ ++ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ ++ sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr)) : \ ++ sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr)) : \ ++ *(uint8 *)0) ++ ++#ifdef __GNUC__ ++ ++/* GNU macro versions avoid referencing the argument multiple times, while also ++ * avoiding the -fno-inline used in ROM builds. ++ */ ++ ++#define bcmswap16(val) ({ \ ++ uint16 _val = (val); \ ++ BCMSWAP16(_val); \ ++}) ++ ++#define bcmswap32(val) ({ \ ++ uint32 _val = (val); \ ++ BCMSWAP32(_val); \ ++}) ++ ++#define bcmswap32by16(val) ({ \ ++ uint32 _val = (val); \ ++ BCMSWAP32BY16(_val); \ ++}) ++ ++#define bcmswap16_buf(buf, len) ({ \ ++ uint16 *_buf = (uint16 *)(buf); \ ++ uint _wds = (len) / 2; \ ++ while (_wds--) { \ ++ *_buf = bcmswap16(*_buf); \ ++ _buf++; \ ++ } \ ++}) ++ ++#define htol16_ua_store(val, bytes) ({ \ ++ uint16 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val & 0xff; \ ++ _bytes[1] = _val >> 8; \ ++}) ++ ++#define htol32_ua_store(val, bytes) ({ \ ++ uint32 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val & 0xff; \ ++ _bytes[1] = (_val >> 8) & 0xff; \ ++ _bytes[2] = (_val >> 16) & 0xff; \ ++ _bytes[3] = _val >> 24; \ ++}) ++ ++#define hton16_ua_store(val, bytes) ({ \ ++ uint16 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val >> 8; \ ++ _bytes[1] = _val & 0xff; \ ++}) ++ ++#define hton32_ua_store(val, bytes) ({ \ ++ uint32 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val >> 24; \ ++ _bytes[1] = (_val >> 16) & 0xff; \ ++ _bytes[2] = (_val >> 8) & 0xff; \ ++ _bytes[3] = _val & 0xff; \ ++}) ++ ++#define ltoh16_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _LTOH16_UA(_bytes); \ ++}) ++ ++#define ltoh32_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _LTOH32_UA(_bytes); \ ++}) ++ ++#define ntoh16_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _NTOH16_UA(_bytes); \ ++}) ++ ++#define ntoh32_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _NTOH32_UA(_bytes); \ ++}) ++ ++#else /* !__GNUC__ */ ++ ++/* Inline versions avoid referencing the argument multiple times */ ++static INLINE uint16 ++bcmswap16(uint16 val) ++{ ++ return BCMSWAP16(val); ++} ++ ++static INLINE uint32 ++bcmswap32(uint32 val) ++{ ++ return BCMSWAP32(val); ++} ++ ++static INLINE uint32 ++bcmswap32by16(uint32 val) ++{ ++ return BCMSWAP32BY16(val); ++} ++ ++/* Reverse pairs of bytes in a buffer (not for high-performance use) */ ++/* buf - start of buffer of shorts to swap */ ++/* len - byte length of buffer */ ++static INLINE void ++bcmswap16_buf(uint16 *buf, uint len) ++{ ++ len = len / 2; ++ ++ while (len--) { ++ *buf = bcmswap16(*buf); ++ buf++; ++ } ++} ++ ++/* ++ * Store 16-bit value to unaligned little-endian byte array. ++ */ ++static INLINE void ++htol16_ua_store(uint16 val, uint8 *bytes) ++{ ++ bytes[0] = val & 0xff; ++ bytes[1] = val >> 8; ++} ++ ++/* ++ * Store 32-bit value to unaligned little-endian byte array. ++ */ ++static INLINE void ++htol32_ua_store(uint32 val, uint8 *bytes) ++{ ++ bytes[0] = val & 0xff; ++ bytes[1] = (val >> 8) & 0xff; ++ bytes[2] = (val >> 16) & 0xff; ++ bytes[3] = val >> 24; ++} ++ ++/* ++ * Store 16-bit value to unaligned network-(big-)endian byte array. ++ */ ++static INLINE void ++hton16_ua_store(uint16 val, uint8 *bytes) ++{ ++ bytes[0] = val >> 8; ++ bytes[1] = val & 0xff; ++} ++ ++/* ++ * Store 32-bit value to unaligned network-(big-)endian byte array. ++ */ ++static INLINE void ++hton32_ua_store(uint32 val, uint8 *bytes) ++{ ++ bytes[0] = val >> 24; ++ bytes[1] = (val >> 16) & 0xff; ++ bytes[2] = (val >> 8) & 0xff; ++ bytes[3] = val & 0xff; ++} ++ ++/* ++ * Load 16-bit value from unaligned little-endian byte array. ++ */ ++static INLINE uint16 ++ltoh16_ua(const void *bytes) ++{ ++ return _LTOH16_UA((const uint8 *)bytes); ++} ++ ++/* ++ * Load 32-bit value from unaligned little-endian byte array. ++ */ ++static INLINE uint32 ++ltoh32_ua(const void *bytes) ++{ ++ return _LTOH32_UA((const uint8 *)bytes); ++} ++ ++/* ++ * Load 16-bit value from unaligned big-(network-)endian byte array. ++ */ ++static INLINE uint16 ++ntoh16_ua(const void *bytes) ++{ ++ return _NTOH16_UA((const uint8 *)bytes); ++} ++ ++/* ++ * Load 32-bit value from unaligned big-(network-)endian byte array. ++ */ ++static INLINE uint32 ++ntoh32_ua(const void *bytes) ++{ ++ return _NTOH32_UA((const uint8 *)bytes); ++} ++ ++#endif /* !__GNUC__ */ ++#endif /* !_BCMENDIAN_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmenetmib.h b/drivers/bcmdrivers/gmac/src/include/bcmenetmib.h +new file mode 100755 +index 0000000..6f733fc +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmenetmib.h +@@ -0,0 +1,88 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Hardware-specific MIB definition for ++ * Broadcom Home Networking Division ++ * BCM44XX and BCM47XX 10/100 Mbps Ethernet cores. ++ * ++ * $Id: bcmenetmib.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmenetmib_h_ ++#define _bcmenetmib_h_ ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* ++ * EMAC MIB Registers ++ */ ++typedef volatile struct { ++ uint32 tx_good_octets; ++ uint32 tx_good_pkts; ++ uint32 tx_octets; ++ uint32 tx_pkts; ++ uint32 tx_broadcast_pkts; ++ uint32 tx_multicast_pkts; ++ uint32 tx_len_64; ++ uint32 tx_len_65_to_127; ++ uint32 tx_len_128_to_255; ++ uint32 tx_len_256_to_511; ++ uint32 tx_len_512_to_1023; ++ uint32 tx_len_1024_to_max; ++ uint32 tx_jabber_pkts; ++ uint32 tx_oversize_pkts; ++ uint32 tx_fragment_pkts; ++ uint32 tx_underruns; ++ uint32 tx_total_cols; ++ uint32 tx_single_cols; ++ uint32 tx_multiple_cols; ++ uint32 tx_excessive_cols; ++ uint32 tx_late_cols; ++ uint32 tx_defered; ++ uint32 tx_carrier_lost; ++ uint32 tx_pause_pkts; ++ uint32 PAD[8]; ++ ++ uint32 rx_good_octets; ++ uint32 rx_good_pkts; ++ uint32 rx_octets; ++ uint32 rx_pkts; ++ uint32 rx_broadcast_pkts; ++ uint32 rx_multicast_pkts; ++ uint32 rx_len_64; ++ uint32 rx_len_65_to_127; ++ uint32 rx_len_128_to_255; ++ uint32 rx_len_256_to_511; ++ uint32 rx_len_512_to_1023; ++ uint32 rx_len_1024_to_max; ++ uint32 rx_jabber_pkts; ++ uint32 rx_oversize_pkts; ++ uint32 rx_fragment_pkts; ++ uint32 rx_missed_pkts; ++ uint32 rx_crc_align_errs; ++ uint32 rx_undersize; ++ uint32 rx_crc_errs; ++ uint32 rx_align_errs; ++ uint32 rx_symbol_errs; ++ uint32 rx_pause_pkts; ++ uint32 rx_nonpause_pkts; ++} bcmenetmib_t; ++ ++#endif /* _bcmenetmib_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmenetphy.h b/drivers/bcmdrivers/gmac/src/include/bcmenetphy.h +new file mode 100755 +index 0000000..19c9c86 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmenetphy.h +@@ -0,0 +1,87 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc Broadcom BCM47XX MDC/MDIO enet phy definitions. ++ * ++ * $Id: bcmenetphy.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmenetphy_h_ ++#define _bcmenetphy_h_ ++ ++/* phy address */ ++#define MAXEPHY 32 /* mdio phy addresses are 5bit quantities */ ++#define EPHY_MASK 0x1f /* phy mask */ ++#define EPHY_NONE 31 /* nvram: no phy present at all */ ++#define EPHY_NOREG 30 /* nvram: no local phy regs */ ++ ++#define MAXPHYREG 32 /* max 32 registers per phy */ ++ ++/* just a few phy registers */ ++#define CTL_RESET (1 << 15) /* reset */ ++#define CTL_LOOP (1 << 14) /* loopback */ ++#define CTL_SPEED (1 << 13) /* speed selection lsb 0=10, 1=100 */ ++#define CTL_ANENAB (1 << 12) /* autonegotiation enable */ ++#define CTL_RESTART (1 << 9) /* restart autonegotiation */ ++#define CTL_DUPLEX (1 << 8) /* duplex mode 0=half, 1=full */ ++#define CTL_SPEED_MSB (1 << 6) /* speed selection msb */ ++ ++#define CTL_SPEED_10 ((0 << 6) | (0 << 13)) /* speed selection CTL.6=0, CTL.13=0 */ ++#define CTL_SPEED_100 ((0 << 6) | (1 << 13)) /* speed selection CTL.6=0, CTL.13=1 */ ++#define CTL_SPEED_1000 ((1 << 6) | (0 << 13)) /* speed selection CTL.6=1, CTL.13=0 */ ++ ++#define ADV_10FULL (1 << 6) /* autonegotiate advertise 10full */ ++#define ADV_10HALF (1 << 5) /* autonegotiate advertise 10half */ ++#define ADV_100FULL (1 << 8) /* autonegotiate advertise 100full */ ++#define ADV_100HALF (1 << 7) /* autonegotiate advertise 100half */ ++#define ADV_PAUSE (1 << 10) /* autonegotiate advertise pause */ ++ ++/* link partner ability register */ ++#define LPA_SLCT 0x001f /* same as advertise selector */ ++#define LPA_10HALF 0x0020 /* can do 10mbps half-duplex */ ++#define LPA_10FULL 0x0040 /* can do 10mbps full-duplex */ ++#define LPA_100HALF 0x0080 /* can do 100mbps half-duplex */ ++#define LPA_100FULL 0x0100 /* can do 100mbps full-duplex */ ++#define LPA_100BASE4 0x0200 /* can do 100mbps 4k packets */ ++#define LPA_RESV 0x1c00 /* unused */ ++#define LPA_RFAULT 0x2000 /* link partner faulted */ ++#define LPA_LPACK 0x4000 /* link partner acked us */ ++#define LPA_NPAGE 0x8000 /* next page bit */ ++ ++#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL) ++#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4) ++ ++/* 1000BASE-T control register */ ++#define ADV_1000HALF 0x0100 /* advertise 1000BASE-T half duplex */ ++#define ADV_1000FULL 0x0200 /* advertise 1000BASE-T full duplex */ ++ ++/* 1000BASE-T status register */ ++#define LPA_1000HALF 0x0400 /* link partner 1000BASE-T half duplex */ ++#define LPA_1000FULL 0x0800 /* link partner 1000BASE-T full duplex */ ++ ++/* 1000BASE-T extended status register */ ++#define EST_1000THALF 0x1000 /* 1000BASE-T half duplex capable */ ++#define EST_1000TFULL 0x2000 /* 1000BASE-T full duplex capable */ ++#define EST_1000XHALF 0x4000 /* 1000BASE-X half duplex capable */ ++#define EST_1000XFULL 0x8000 /* 1000BASE-X full duplex capable */ ++ ++#define STAT_REMFAULT (1 << 4) /* remote fault */ ++#define STAT_LINK (1 << 2) /* link status */ ++#define STAT_JAB (1 << 1) /* jabber detected */ ++#define AUX_FORCED (1 << 2) /* forced 10/100 */ ++#define AUX_SPEED (1 << 1) /* speed 0=10mbps 1=100mbps */ ++#define AUX_DUPLEX (1 << 0) /* duplex 0=half 1=full */ ++ ++#endif /* _bcmenetphy_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmenetrxh.h b/drivers/bcmdrivers/gmac/src/include/bcmenetrxh.h +new file mode 100755 +index 0000000..b82e0fe +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmenetrxh.h +@@ -0,0 +1,50 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Hardware-specific Receive Data Header for the ++ * Broadcom Home Networking Division ++ * BCM44XX and BCM47XX 10/100 Mbps Ethernet cores. ++ * ++ * $Id: bcmenetrxh.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmenetrxh_h_ ++#define _bcmenetrxh_h_ ++ ++/* ++ * The Ethernet MAC core returns an 8-byte Receive Frame Data Header ++ * with every frame consisting of ++ * 16bits of frame length, followed by ++ * 16bits of EMAC rx descriptor info, followed by 32bits of undefined. ++ */ ++typedef volatile struct { ++ uint16 len; ++ uint16 flags; ++ uint16 pad[12]; ++} bcmenetrxh_t; ++ ++#define RXHDR_LEN 28 /* Header length */ ++ ++#define RXF_L ((uint16)1 << 11) /* last buffer in a frame */ ++#define RXF_MISS ((uint16)1 << 7) /* received due to promisc mode */ ++#define RXF_BRDCAST ((uint16)1 << 6) /* dest is broadcast address */ ++#define RXF_MULT ((uint16)1 << 5) /* dest is multicast address */ ++#define RXF_LG ((uint16)1 << 4) /* frame length > rxmaxlength */ ++#define RXF_NO ((uint16)1 << 3) /* odd number of nibbles */ ++#define RXF_RXER ((uint16)1 << 2) /* receive symbol error */ ++#define RXF_CRC ((uint16)1 << 1) /* crc error */ ++#define RXF_OV ((uint16)1 << 0) /* fifo overflow */ ++ ++#endif /* _bcmenetrxh_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmgmacmib.h b/drivers/bcmdrivers/gmac/src/include/bcmgmacmib.h +new file mode 100755 +index 0000000..6f0cf09 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmgmacmib.h +@@ -0,0 +1,117 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Hardware-specific MIB definition for ++ * Broadcom Home Networking Division ++ * GbE Unimac core ++ * ++ * $Id: bcmgmacmib.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmgmacmib_h_ ++#define _bcmgmacmib_h_ ++ ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* GMAC MIB structure */ ++ ++typedef struct _gmacmib { ++ uint32 tx_good_octets; /* 0x300 */ ++ uint32 tx_good_octets_high; /* 0x304 */ ++ uint32 tx_good_pkts; /* 0x308 */ ++ uint32 tx_octets; /* 0x30c */ ++ uint32 tx_octets_high; /* 0x310 */ ++ uint32 tx_pkts; /* 0x314 */ ++ uint32 tx_broadcast_pkts; /* 0x318 */ ++ uint32 tx_multicast_pkts; /* 0x31c */ ++ uint32 tx_len_64; /* 0x320 */ ++ uint32 tx_len_65_to_127; /* 0x324 */ ++ uint32 tx_len_128_to_255; /* 0x328 */ ++ uint32 tx_len_256_to_511; /* 0x32c */ ++ uint32 tx_len_512_to_1023; /* 0x330 */ ++ uint32 tx_len_1024_to_1522; /* 0x334 */ ++ uint32 tx_len_1523_to_2047; /* 0x338 */ ++ uint32 tx_len_2048_to_4095; /* 0x33c */ ++ uint32 tx_len_4095_to_8191; /* 0x340 */ ++ uint32 tx_len_8192_to_max; /* 0x344 */ ++ uint32 tx_jabber_pkts; /* 0x348 */ ++ uint32 tx_oversize_pkts; /* 0x34c */ ++ uint32 tx_fragment_pkts; /* 0x350 */ ++ uint32 tx_underruns; /* 0x354 */ ++ uint32 tx_total_cols; /* 0x358 */ ++ uint32 tx_single_cols; /* 0x35c */ ++ uint32 tx_multiple_cols; /* 0x360 */ ++ uint32 tx_excessive_cols; /* 0x364 */ ++ uint32 tx_late_cols; /* 0x368 */ ++ uint32 tx_defered; /* 0x36c */ ++ uint32 tx_carrier_lost; /* 0x370 */ ++ uint32 tx_pause_pkts; /* 0x374 */ ++ uint32 tx_uni_pkts; /* 0x378 */ ++ uint32 tx_q0_pkts; /* 0x37c */ ++ uint32 tx_q0_octets; /* 0x380 */ ++ uint32 tx_q0_octets_high; /* 0x384 */ ++ uint32 tx_q1_pkts; /* 0x388 */ ++ uint32 tx_q1_octets; /* 0x38c */ ++ uint32 tx_q1_octets_high; /* 0x390 */ ++ uint32 tx_q2_pkts; /* 0x394 */ ++ uint32 tx_q2_octets; /* 0x398 */ ++ uint32 tx_q2_octets_high; /* 0x39c */ ++ uint32 tx_q3_pkts; /* 0x3a0 */ ++ uint32 tx_q3_octets; /* 0x3a4 */ ++ uint32 tx_q3_octets_high; /* 0x3a8 */ ++ uint32 PAD; ++ uint32 rx_good_octets; /* 0x3b0 */ ++ uint32 rx_good_octets_high; /* 0x3b4 */ ++ uint32 rx_good_pkts; /* 0x3b8 */ ++ uint32 rx_octets; /* 0x3bc */ ++ uint32 rx_octets_high; /* 0x3c0 */ ++ uint32 rx_pkts; /* 0x3c4 */ ++ uint32 rx_broadcast_pkts; /* 0x3c8 */ ++ uint32 rx_multicast_pkts; /* 0x3cc */ ++ uint32 rx_len_64; /* 0x3d0 */ ++ uint32 rx_len_65_to_127; /* 0x3d4 */ ++ uint32 rx_len_128_to_255; /* 0x3d8 */ ++ uint32 rx_len_256_to_511; /* 0x3dc */ ++ uint32 rx_len_512_to_1023; /* 0x3e0 */ ++ uint32 rx_len_1024_to_1522; /* 0x3e4 */ ++ uint32 rx_len_1523_to_2047; /* 0x3e8 */ ++ uint32 rx_len_2048_to_4095; /* 0x3ec */ ++ uint32 rx_len_4095_to_8191; /* 0x3f0 */ ++ uint32 rx_len_8192_to_max; /* 0x3f4 */ ++ uint32 rx_jabber_pkts; /* 0x3f8 */ ++ uint32 rx_oversize_pkts; /* 0x3fc */ ++ uint32 rx_fragment_pkts; /* 0x400 */ ++ uint32 rx_missed_pkts; /* 0x404 */ ++ uint32 rx_crc_align_errs; /* 0x408 */ ++ uint32 rx_undersize; /* 0x40c */ ++ uint32 rx_crc_errs; /* 0x410 */ ++ uint32 rx_align_errs; /* 0x414 */ ++ uint32 rx_symbol_errs; /* 0x418 */ ++ uint32 rx_pause_pkts; /* 0x41c */ ++ uint32 rx_nonpause_pkts; /* 0x420 */ ++ uint32 rx_sachanges; /* 0x424 */ ++ uint32 rx_uni_pkts; /* 0x428 */ ++} gmacmib_t; ++ ++#define GM_MIB_BASE 0x300 ++#define GM_MIB_LIMIT 0x800 ++ ++#endif /* _bcmgmacmib_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmgmacrxh.h b/drivers/bcmdrivers/gmac/src/include/bcmgmacrxh.h +new file mode 100755 +index 0000000..c3d58e9 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmgmacrxh.h +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Hardware-specific Receive Data Header for the ++ * Broadcom Home Networking Division ++ * BCM47XX GbE cores. ++ * ++ * $Id: bcmgmacrxh.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmgmacrxh_h_ ++#define _bcmgmacrxh_h_ ++ ++/* ++ * The Ethernet GMAC core returns an 8-byte Receive Frame Data Header ++ * with every frame consisting of ++ * 16 bits of frame length, followed by ++ * 16 bits of GMAC rx descriptor info, followed by 32bits of undefined. ++ */ ++typedef volatile struct { ++ uint16 len; ++ uint16 flags; ++ uint16 pad[12]; ++} bcmgmacrxh_t; ++ ++#define RXHDR_LEN 28 /* Header length */ ++ ++#define GRXF_DT_MASK ((uint16)0xf) /* data type */ ++#define GRXF_DT_SHIFT 12 ++#define GRXF_DC_MASK ((uint16)0xf) /* (num descr to xfer the frame) - 1 */ ++#define GRXF_DC_SHIFT 8 ++#define GRXF_OVF ((uint16)1 << 7) /* overflow error occured */ ++#define GRXF_CTFERR ((uint16)1 << 6) /* overflow error occured */ ++#define GRXF_OVERSIZE ((uint16)1 << 4) /* frame size > rxmaxlength */ ++#define GRXF_CRC ((uint16)1 << 3) /* crc error */ ++#define GRXF_VLAN ((uint16)1 << 2) /* vlan tag detected */ ++#define GRXF_PT_MASK ((uint16)3) /* packet type 0 - Unicast, ++ * 1 - Multicast, 2 - Broadcast ++ */ ++ ++#endif /* _bcmgmacrxh_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy.h +new file mode 100755 +index 0000000..3698729 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy.h +@@ -0,0 +1,267 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++#ifndef _bcm_iproc_phy_h_ ++#define _bcm_iproc_phy_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++/* ++ * Defines: SOC_E_XXX ++ * Purpose: SOC API error codes ++ * Notes: ++ * An error code may be converted to a string by passing ++ * the code to soc_errmsg(). ++ */ ++ ++typedef enum { ++ SOC_E_NONE = 0, ++ SOC_E_INTERNAL = -1, ++ SOC_E_MEMORY = -2, ++ SOC_E_UNIT = -3, ++ SOC_E_PARAM = -4, ++ SOC_E_EMPTY = -5, ++ SOC_E_FULL = -6, ++ SOC_E_NOT_FOUND = -7, ++ SOC_E_EXISTS = -8, ++ SOC_E_TIMEOUT = -9, ++ SOC_E_BUSY = -10, ++ SOC_E_FAIL = -11, ++ SOC_E_DISABLED = -12, ++ SOC_E_BADID = -13, ++ SOC_E_RESOURCE = -14, ++ SOC_E_CONFIG = -15, ++ SOC_E_UNAVAIL = -16, ++ SOC_E_INIT = -17, ++ SOC_E_PORT = -18, ++ ++ SOC_E_LIMIT = -19 /* Must come last */ ++} soc_error_t; ++ ++#define SOC_SUCCESS(rv) ((rv) >= 0) ++#define SOC_FAILURE(rv) ((rv) < 0) ++ ++typedef enum _soc_port_if_e { ++ SOC_PORT_IF_NOCXN, /* No physical connection */ ++ SOC_PORT_IF_NULL, /* Pass-through connection without PHY */ ++ SOC_PORT_IF_MII, ++ SOC_PORT_IF_GMII, ++ SOC_PORT_IF_SGMII, ++ SOC_PORT_IF_TBI, ++ SOC_PORT_IF_XGMII, ++ SOC_PORT_IF_RGMII, ++ SOC_PORT_IF_RvMII, ++ SOC_PORT_IF_SFI, ++ SOC_PORT_IF_XFI, ++ SOC_PORT_IF_KR, ++ SOC_PORT_IF_KR4, ++ SOC_PORT_IF_CR, ++ SOC_PORT_IF_CR4, ++ SOC_PORT_IF_XLAUI, ++ SOC_PORT_IF_SR, ++ SOC_PORT_IF_RXAUI, ++ SOC_PORT_IF_XAUI, ++ SOC_PORT_IF_SPAUI, ++ SOC_PORT_IF_QSGMII, ++ SOC_PORT_IF_ILKN, ++ SOC_PORT_IF_RCY, ++ SOC_PORT_IF_FAT_PIPE, ++ SOC_PORT_IF_CGMII, ++ SOC_PORT_IF_CAUI, ++ SOC_PORT_IF_LR, ++ SOC_PORT_IF_LR4, ++ SOC_PORT_IF_SR4, ++ SOC_PORT_IF_KX, ++ SOC_PORT_IF_CPU, ++ SOC_PORT_IF_OLP, ++ SOC_PORT_IF_OAMP, ++ SOC_PORT_IF_ERP, ++ SOC_PORT_IF_COUNT /* last, please */ ++} _soc_port_if_t; ++typedef _soc_port_if_t soc_port_if_t; ++ ++ ++/* 1000BASE-T/100BASE-TX/10BASE-T MII Control Register (Addr 00h) */ ++#define PHY_MII_CTRLr_FLAGS 0x00 ++#define PHY_MII_CTRLr_BANK 0x0000 ++#define PHY_MII_CTRLr_ADDR 0x00 ++/* 1000BASE-T/100BASE-TX/10BASE-T MII Status Register (ADDR 01h) */ ++#define PHY_MII_STATr_FLAGS 0x00 ++#define PHY_MII_STATr_BANK 0x0000 ++#define PHY_MII_STATr_ADDR 0x01 ++/* 1000BASE-T/100BASE-TX/10BASE-T PHY Identifier Register (ADDR 02h) */ ++#define PHY_MII_PHY_ID0r_FLAGS _SOC_PHY_REG_DIRECT ++#define PHY_MII_PHY_ID0r_BANK 0x0000 ++#define PHY_MII_PHY_ID0r_ADDR 0x02 ++/* 1000BASE-T/100BASE-TX/10BASE-T PHY Identifier Register (ADDR 03h) */ ++#define PHY_MII_PHY_ID1r_FLAGS _SOC_PHY_REG_DIRECT ++#define PHY_MII_PHY_ID1r_BANK 0x0000 ++#define PHY_MII_PHY_ID1r_ADDR 0x03 ++/* 1000BASE-T/100BASE-TX/10BASE-T Auto-neg Advertisment Register (ADDR 04h) */ ++#define PHY_MII_ANAr_FLAGS 0x00 ++#define PHY_MII_ANAr_BANK 0x0000 ++#define PHY_MII_ANAr_ADDR 0x04 ++/* 1000BASE-T/100BASE-TX/10BASE-T Auto-neg Link Partner Ability (ADDR 05h) */ ++#define PHY_MII_ANPr_FLAGS 0x00 ++#define PHY_MII_ANPr_BANK 0x0000 ++#define PHY_MII_ANPr_ADDR 0x05 ++/* 1000BASE-T Control Register (ADDR 09h) */ ++#define PHY_MII_GB_CTRLr_FLAGS 0x00 ++#define PHY_MII_GB_CTRLr_BANK 0x0000 ++#define PHY_MII_GB_CTRLr_ADDR 0x09 ++/* 1000BASE-T Status Register (ADDR 0ah) */ ++#define PHY_MII_GB_STATr_FLAGS 0x00 ++#define PHY_MII_GB_STATr_BANK 0x0000 ++#define PHY_MII_GB_STATr_ADDR 0x0a ++/* 1000BASE-T/100BASE-TX/10BASE-T IEEE Extended Status Register (ADDR 0fh) */ ++#define PHY_MII_ESRr_FLAGS 0x00 ++#define PHY_MII_ESRr_BANK 0x0000 ++#define PHY_MII_ESRr_ADDR 0x0f ++/* 1000BASE-T/100BASE-TX/10BASE-T PHY Extended Control Register (ADDR 10h) */ ++#define PHY_MII_ECRr_FLAGS 0x00 ++#define PHY_MII_ECRr_BANK 0x0000 ++#define PHY_MII_ECRr_ADDR 0x10 ++/* 1000BASE-T/100BASE-TX/10BASE-T Auxiliary Control Reg (ADDR 18h Shadow 000)*/ ++#define PHY_MII_AUX_CTRLr_FLAGS 0x00 ++#define PHY_MII_AUX_CTRLr_BANK 0x0000 ++#define PHY_MII_AUX_CTRLr_ADDR 0x18 ++/* 1000BASE-T/100BASE-TX/10BASE-T Power/MII Control Reg (ADDR 18h Shadow 010)*/ ++#define PHY_MII_POWER_CTRLr_FLAGS 0x00 ++#define PHY_MII_POWER_CTRLr_BANK 0x0002 ++#define PHY_MII_POWER_CTRLr_ADDR 0x18 ++/* Auxiliary 1000BASE-X Control Reg (ADDR 1ch shadow 11011) */ ++#define PHY_AUX_1000X_CTRLr_FLAGS 0x00 ++#define PHY_AUX_1000X_CTRLr_BANK 0x001B ++#define PHY_AUX_1000X_CTRLr_ADDRS 0x1c ++/* Mode Control Reg (ADDR 1ch shadow 11111) */ ++#define PHY_MODE_CTRLr_FLAGS 0x00 ++#define PHY_MODE_CTRLr_BANK 0x001F ++#define PHY_MODE_CTRLr_ADDR 0x1c ++ ++/* ++ * Primary SerDes Registers ++ */ ++/* 1000BASE-X MII Control Register (Addr 00h) */ ++#define PHY_1000X_MII_CTRLr_FLAGS SOC_PHY_REG_1000X ++#define PHY_1000X_MII_CTRLr_BANK 0x0000 ++#define PHY_1000X_MII_CTRLr_ADDR 0x00 ++ ++ ++/* MII Control Register: bit definitions */ ++#define MII_CTRL_FS_2500 (1 << 5) /* Force speed to 2500 Mbps */ ++#define MII_CTRL_SS_MSB (1 << 6) /* Speed select, MSb */ ++#define MII_CTRL_CST (1 << 7) /* Collision Signal test */ ++#define MII_CTRL_FD (1 << 8) /* Full Duplex */ ++#define MII_CTRL_RAN (1 << 9) /* Restart Autonegotiation */ ++#define MII_CTRL_IP (1 << 10) /* Isolate Phy */ ++#define MII_CTRL_PD (1 << 11) /* Power Down */ ++#define MII_CTRL_AE (1 << 12) /* Autonegotiation enable */ ++#define MII_CTRL_SS_LSB (1 << 13) /* Speed select, LSb */ ++#define MII_CTRL_LE (1 << 14) /* Loopback enable */ ++#define MII_CTRL_RESET (1 << 15) /* PHY reset */ ++ ++#define MII_CTRL_SS(_x) ((_x) & (MII_CTRL_SS_LSB|MII_CTRL_SS_MSB)) ++#define MII_CTRL_SS_10 0 ++#define MII_CTRL_SS_100 (MII_CTRL_SS_LSB) ++#define MII_CTRL_SS_1000 (MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_INVALID (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_MASK (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++ ++/* ++ * MII Status Register: See 802.3, 1998 pg 544 ++ */ ++#define MII_STAT_EXT (1 << 0) /* Extended Registers */ ++#define MII_STAT_JBBR (1 << 1) /* Jabber Detected */ ++#define MII_STAT_LA (1 << 2) /* Link Active */ ++#define MII_STAT_AN_CAP (1 << 3) /* Autoneg capable */ ++#define MII_STAT_RF (1 << 4) /* Remote Fault */ ++#define MII_STAT_AN_DONE (1 << 5) /* Autoneg complete */ ++#define MII_STAT_MF_PS (1 << 6) /* Preamble suppression */ ++#define MII_STAT_ES (1 << 8) /* Extended status (R15) */ ++#define MII_STAT_HD_100_T2 (1 << 9) /* Half duplex 100Mb/s supported */ ++#define MII_STAT_FD_100_T2 (1 << 10)/* Full duplex 100Mb/s supported */ ++#define MII_STAT_HD_10 (1 << 11)/* Half duplex 100Mb/s supported */ ++#define MII_STAT_FD_10 (1 << 12)/* Full duplex 100Mb/s supported */ ++#define MII_STAT_HD_100 (1 << 13)/* Half duplex 100Mb/s supported */ ++#define MII_STAT_FD_100 (1 << 14)/* Full duplex 100Mb/s supported */ ++#define MII_STAT_100_T4 (1 << 15)/* Full duplex 100Mb/s supported */ ++ ++/* ++ * MII Link Advertisment ++ */ ++#define MII_ANA_ASF (1 << 0)/* Advertise Selector Field */ ++#define MII_ANA_HD_10 (1 << 5)/* Half duplex 10Mb/s supported */ ++#define MII_ANA_FD_10 (1 << 6)/* Full duplex 10Mb/s supported */ ++#define MII_ANA_HD_100 (1 << 7)/* Half duplex 100Mb/s supported */ ++#define MII_ANA_FD_100 (1 << 8)/* Full duplex 100Mb/s supported */ ++#define MII_ANA_T4 (1 << 9)/* T4 */ ++#define MII_ANA_PAUSE (1 << 10)/* Pause supported */ ++#define MII_ANA_ASYM_PAUSE (1 << 11)/* Asymmetric pause supported */ ++#define MII_ANA_RF (1 << 13)/* Remote fault */ ++#define MII_ANA_NP (1 << 15)/* Next Page */ ++ ++#define MII_ANA_ASF_802_3 (1) /* 802.3 PHY */ ++ ++/* ++ * 1000Base-T Control Register ++ */ ++#define MII_GB_CTRL_MS_MAN (1 << 12) /* Manual Master/Slave mode */ ++#define MII_GB_CTRL_MS (1 << 11) /* Master/Slave negotiation mode */ ++#define MII_GB_CTRL_PT (1 << 10) /* Port type */ ++#define MII_GB_CTRL_ADV_1000FD (1 << 9) /* Advertise 1000Base-T FD */ ++#define MII_GB_CTRL_ADV_1000HD (1 << 8) /* Advertise 1000Base-T HD */ ++ ++/* ++ * 1000Base-T Status Register ++ */ ++#define MII_GB_STAT_MS_FAULT (1 << 15) /* Master/Slave Fault */ ++#define MII_GB_STAT_MS (1 << 14) /* Master/Slave, 1 == Master */ ++#define MII_GB_STAT_LRS (1 << 13) /* Local receiver status */ ++#define MII_GB_STAT_RRS (1 << 12) /* Remote receiver status */ ++#define MII_GB_STAT_LP_1000FD (1 << 11) /* Link partner 1000FD capable */ ++#define MII_GB_STAT_LP_1000HD (1 << 10) /* Link partner 1000HD capable */ ++#define MII_GB_STAT_IDE (0xff << 0) /* Idle error count */ ++ ++/* ++ * IEEE Extended Status Register ++ */ ++#define MII_ESR_1000_X_FD (1 << 15) /* 1000Base-T FD capable */ ++#define MII_ESR_1000_X_HD (1 << 14) /* 1000Base-T HD capable */ ++#define MII_ESR_1000_T_FD (1 << 13) /* 1000Base-T FD capable */ ++#define MII_ESR_1000_T_HD (1 << 12) /* 1000Base-T FD capable */ ++ ++/* MII Extended Control Register (BROADCOM) */ ++#define MII_ECR_FE (1 << 0) /* FIFO Elasticity */ ++#define MII_ECR_TLLM (1 << 1) /* Three link LED mode */ ++#define MII_ECR_ET_IPG (1 << 2) /* Extended XMIT IPG mode */ ++#define MII_ECR_FLED_OFF (1 << 3) /* Force LED off */ ++#define MII_ECR_FLED_ON (1 << 4) /* Force LED on */ ++#define MII_ECR_ELT (1 << 5) /* Enable LED traffic */ ++#define MII_ECR_RS (1 << 6) /* Reset Scrambler */ ++#define MII_ECR_BRSA (1 << 7) /* Bypass Receive Sym. align */ ++#define MII_ECR_BMLT3 (1 << 8) /* Bypass MLT3 Encoder/Decoder */ ++#define MII_ECR_BSD (1 << 9) /* Bypass Scramble/Descramble */ ++#define MII_ECR_B4B5B (1 << 10) /* Bypass 4B/5B Encode/Decode */ ++#define MII_ECR_FI (1 << 11) /* Force Interrupt */ ++#define MII_ECR_ID (1 << 12) /* Interrupt Disable */ ++#define MII_ECR_TD (1 << 13) /* XMIT Disable */ ++#define MII_ECR_DAMC (1 << 14) /* DIsable Auto-MDI Crossover */ ++#define MII_ECR_10B (1 << 15) /* 1 == 10B, 0 == GMII */ ++ ++#endif /* _bcm_iproc_phy_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5221.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5221.h +new file mode 100755 +index 0000000..523c8e1 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5221.h +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++#ifndef _bcm_iproc_phy5221_h_ ++#define _bcm_iproc_phy5221_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++ ++#define PHY_AUX_MULTIPLE_PHYr_BANK 0x0000 ++#define PHY_AUX_MULTIPLE_PHYr_ADDR 0x1e ++ ++#define PHY522X_SUPER_ISOLATE_MODE (1<<3) ++ ++/* ---- External Function Prototypes ------------------------------------- */ ++ ++extern int phy5221_wr_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data); ++extern int phy5221_rd_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data); ++extern int phy5221_mod_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 data, uint16 mask); ++extern int phy5221_init(uint eth_num, uint phyaddr); ++extern int phy5221_link_get(uint eth_num, uint phyaddr, int *link); ++extern int phy5221_enable_set(uint eth_num, uint phyaddr, int enable); ++extern int phy5221_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex); ++ ++#endif /* _bcm_iproc_phy5221_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5461s.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5461s.h +new file mode 100755 +index 0000000..a366dd8 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5461s.h +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++#ifndef _bcm_iproc_phy5461s_h_ ++#define _bcm_iproc_phy5461s_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++ ++/* Indirect PHY register address flags */ ++#define SOC_PHY_REG_RESERVE_ACCESS 0x20000000 ++#define SOC_PHY_REG_1000X 0x40000000 ++#define SOC_PHY_REG_INDIRECT 0x80000000 ++#define _SOC_PHY_REG_DIRECT ((SOC_PHY_REG_1000X << 1) | (SOC_PHY_REG_1000X >> 1)) ++ ++/* ---- External Function Prototypes ------------------------------------- */ ++ ++extern int phy5461_wr_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data); ++extern int phy5461_rd_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data); ++extern int phy5461_mod_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 data, uint16 mask); ++extern int phy5461_init(uint eth_num, uint phyaddr); ++extern int phy5461_link_get(uint eth_num, uint phyaddr, int *link); ++extern int phy5461_enable_set(uint eth_num, uint phyaddr, int enable); ++extern int phy5461_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex); ++ ++#endif /* _bcm_iproc_phy5461s_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_robo_serdes.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_robo_serdes.h +new file mode 100755 +index 0000000..d8e0a39 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_robo_serdes.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the serdes ++ * ++ */ ++ ++#ifndef _bcm_iproc_robo_serdes_h_ ++#define _bcm_iproc_robo_serdes_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include "bcmrobo.h" ++ ++#define PHY_REG_BLK_ADDR 0x001f /* GLOBAL BLOCK ADDRESS REGISTER */ ++ ++/* ++ * MII Link Advertisment (Clause 37) ++ */ ++#define MII_ANA_C37_NP (1 << 15) /* Next Page */ ++#define MII_ANA_C37_RF_OK (0 << 12) /* No error, link OK */ ++#define MII_ANA_C37_RF_LINK_FAIL (1 << 12) /* Offline */ ++#define MII_ANA_C37_RF_OFFLINE (2 << 12) /* Link failure */ ++#define MII_ANA_C37_RF_AN_ERR (3 << 12) /* Auto-Negotiation Error */ ++#define MII_ANA_C37_PAUSE (1 << 7) /* Symmetric Pause */ ++#define MII_ANA_C37_ASYM_PAUSE (1 << 8) /* Asymmetric Pause */ ++#define MII_ANA_C37_HD (1 << 6) /* Half duplex */ ++#define MII_ANA_C37_FD (1 << 5) /* Full duplex */ ++ ++/* MII Control Register: bit definitions */ ++ ++#define MII_CTRL_FS_2500 (1 << 5) /* Force speed to 2500 Mbps */ ++#define MII_CTRL_SS_MSB (1 << 6) /* Speed select, MSb */ ++#define MII_CTRL_CST (1 << 7) /* Collision Signal test */ ++#define MII_CTRL_FD (1 << 8) /* Full Duplex */ ++#define MII_CTRL_RAN (1 << 9) /* Restart Autonegotiation */ ++#define MII_CTRL_IP (1 << 10) /* Isolate Phy */ ++#define MII_CTRL_PD (1 << 11) /* Power Down */ ++#define MII_CTRL_AE (1 << 12) /* Autonegotiation enable */ ++#define MII_CTRL_SS_LSB (1 << 13) /* Speed select, LSb */ ++#define MII_CTRL_LE (1 << 14) /* Loopback enable */ ++#define MII_CTRL_RESET (1 << 15) /* PHY reset */ ++ ++#define MII_CTRL_SS(_x) ((_x) & (MII_CTRL_SS_LSB|MII_CTRL_SS_MSB)) ++#define MII_CTRL_SS_10 0 ++#define MII_CTRL_SS_100 (MII_CTRL_SS_LSB) ++#define MII_CTRL_SS_1000 (MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_INVALID (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_MASK (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++ ++#define GPIO_SFP0_TXDIS 26 ++#define GPIO_SFP1_TXDIS 27 ++ ++/* ---- External Function Prototypes ------------------------------------- */ ++ ++extern uint16 robo_serdes_get_id(robo_info_t *robo, uint page, uint off); ++extern void robo_serdes_reset(robo_info_t *robo, uint page); ++extern int robo_serdes_reset_core(robo_info_t *robo, uint page); ++extern int robo_serdes_start_pll(robo_info_t *robo, uint page); ++extern int robo_serdes_init(robo_info_t *robo, uint page); ++extern int robo_serdes_enable_set(robo_info_t *robo, uint page, int enable); ++extern int robo_serdes_speed_set(robo_info_t *robo, uint page, int speed); ++extern int robo_serdes_speed_get(robo_info_t *robo, uint page, int *speed); ++ ++#endif /* _bcm_iproc_serdes_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes.h +new file mode 100755 +index 0000000..f9abc47 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the serdes ++ * ++ */ ++ ++#ifndef _bcm_iproc_serdes_h_ ++#define _bcm_iproc_serdes_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++ ++#define PHY_REG_BLK_ADDR 0x001f /* GLOBAL BLOCK ADDRESS REGISTER */ ++ ++/* ++ * MII Link Advertisment (Clause 37) ++ */ ++#define MII_ANA_C37_NP (1 << 15) /* Next Page */ ++#define MII_ANA_C37_RF_OK (0 << 12) /* No error, link OK */ ++#define MII_ANA_C37_RF_LINK_FAIL (1 << 12) /* Offline */ ++#define MII_ANA_C37_RF_OFFLINE (2 << 12) /* Link failure */ ++#define MII_ANA_C37_RF_AN_ERR (3 << 12) /* Auto-Negotiation Error */ ++#define MII_ANA_C37_PAUSE (1 << 7) /* Symmetric Pause */ ++#define MII_ANA_C37_ASYM_PAUSE (1 << 8) /* Asymmetric Pause */ ++#define MII_ANA_C37_HD (1 << 6) /* Half duplex */ ++#define MII_ANA_C37_FD (1 << 5) /* Full duplex */ ++ ++/* MII Control Register: bit definitions */ ++ ++#define MII_CTRL_FS_2500 (1 << 5) /* Force speed to 2500 Mbps */ ++#define MII_CTRL_SS_MSB (1 << 6) /* Speed select, MSb */ ++#define MII_CTRL_CST (1 << 7) /* Collision Signal test */ ++#define MII_CTRL_FD (1 << 8) /* Full Duplex */ ++#define MII_CTRL_RAN (1 << 9) /* Restart Autonegotiation */ ++#define MII_CTRL_IP (1 << 10) /* Isolate Phy */ ++#define MII_CTRL_PD (1 << 11) /* Power Down */ ++#define MII_CTRL_AE (1 << 12) /* Autonegotiation enable */ ++#define MII_CTRL_SS_LSB (1 << 13) /* Speed select, LSb */ ++#define MII_CTRL_LE (1 << 14) /* Loopback enable */ ++#define MII_CTRL_RESET (1 << 15) /* PHY reset */ ++ ++#define MII_CTRL_SS(_x) ((_x) & (MII_CTRL_SS_LSB|MII_CTRL_SS_MSB)) ++#define MII_CTRL_SS_10 0 ++#define MII_CTRL_SS_100 (MII_CTRL_SS_LSB) ++#define MII_CTRL_SS_1000 (MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_INVALID (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_MASK (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++ ++/* ---- External Function Prototypes ------------------------------------- */ ++ ++extern void serdes_set_blk(uint eth_num, uint phyaddr, uint blk); ++extern void serdes_wr_reg(uint eth_num, uint phyaddr, uint reg, uint data); ++extern uint16 serdes_rd_reg(uint eth_num, uint phyaddr, uint reg); ++extern uint16 serdes_get_id(uint eth_num, uint phyaddr, uint off); ++extern void serdes_reset(uint eth_num, uint phyaddr); ++extern int serdes_reset_core(uint eth_num, uint phyaddr); ++extern int serdes_start_pll(uint eth_num, uint phyaddr); ++extern int serdes_init(uint eth_num, uint phyaddr); ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++extern int serdes_speeddpx_set(uint eth_num, uint phyaddr, int speed, int fulldpx); ++extern int serdes_set_asym_mode(uint eth_num, uint phyaddr); ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++#endif /* _bcm_iproc_serdes_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes_def.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes_def.h +new file mode 100755 +index 0000000..5bd5abd +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes_def.h +@@ -0,0 +1,306 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These are serdes defines ++ * ++ */ ++ ++#ifndef _PHY_XGXS16G_H_ ++#define _PHY_XGXS16G_H_ ++ ++/* macros */ ++ ++/* Macros ONLY used after initialization */ ++#define XGXS16G_2p5G_ID(id2) ((id2 & 0xff) == 0xf) ++ ++ ++/****************************************************************************/ ++/***** Starting below is auto-generated register macros from RDB files *****/ ++/****************************************************************************/ ++ ++/**************************************************************************** ++ * Core Enums. ++ ***************************************************************************/ ++ ++#define XGXS16G_IEEE0BLK_IEEECONTROL0r 0x00000000 ++#define XGXS16G_XGXSBLK0_XGXSCONTROLr 0x00008000 ++#define XGXS16G_XGXSBLK0_XGXSSTATUSr 0x00008001 ++#define XGXS16G_XGXSBLK0_MMDSELECTr 0x0000800d ++#define XGXS16G_XGXSBLK0_MISCCONTROL1r 0x0000800e ++#define XGXS16G_XGXSBLK1_LANECTRL0r 0x00008015 ++#define XGXS16G_XGXSBLK1_LANECTRL1r 0x00008016 ++#define XGXS16G_XGXSBLK1_LANECTRL3r 0x00008018 ++#define XGXS16G_TX0_TX_ACONTROL0r 0x00008061 ++#define XGXS16G_RX0_RX_CONTROLr 0x000080b1 ++#define XGXS16G_AN73_PDET_PARDET10GCONTROLr 0x00008131 ++#define XGXS16G_XGXSBLK7_EEECONTROLr 0x00008150 ++#define XGXS16G_TX_LN_SWAP1r 0x00008169 ++#define XGXS16G_SERDESDIGITAL_CONTROL1000X1r 0x00008300 ++#define XGXS16G_SERDESDIGITAL_CONTROL1000X2r 0x00008301 ++#define XGXS16G_SERDESDIGITAL_CONTROL1000X3r 0x00008302 ++#define XGXS16G_SERDESDIGITAL_STATUS1000X1r 0x00008304 ++#define XGXS16G_SERDESDIGITAL_MISC1r 0x00008308 ++#define XGXS16G_SERDESID_SERDESID0r 0x00008310 ++#define XGXS16G_SERDESID_SERDESID1r 0x00008311 ++#define XGXS16G_SERDESID_SERDESID2r 0x00008312 ++#define XGXS16G_SERDESID_SERDESID3r 0x00008313 ++#define XGXS16G_REMOTEPHY_MISC3r 0x0000833c ++#define XGXS16G_REMOTEPHY_MISC5r 0x0000833e ++#define XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr 0x00008350 ++#define XGXS16G_BAM_NEXTPAGE_UD_FIELDr 0x00008357 ++#define XGXS16G_COMBO_IEEE0_MIICNTLr 0x0000ffe0 ++#define XGXS16G_COMBO_IEEE0_AUTONEGADVr 0x0000ffe4 ++ ++ ++/**************************************************************************** ++ * XGXS16G_IEEE_ieee0Blk ++ ***************************************************************************/ ++/**************************************************************************** ++ * ieee0Blk :: ieeeControl0 ++ ***************************************************************************/ ++/* ieee0Blk :: ieeeControl0 :: rst_hw [15:15] */ ++#define IEEE0BLK_IEEECONTROL0_RST_HW_MASK 0x8000 ++#define IEEE0BLK_IEEECONTROL0_RST_HW_ALIGN 0 ++#define IEEE0BLK_IEEECONTROL0_RST_HW_BITS 1 ++#define IEEE0BLK_IEEECONTROL0_RST_HW_SHIFT 15 ++ ++/* ieee0Blk :: ieeeControl0 :: gloopback [14:14] */ ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK 0x4000 ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_ALIGN 0 ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_BITS 1 ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_SHIFT 14 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_XgxsBlk0 ++ ***************************************************************************/ ++/**************************************************************************** ++ * XgxsBlk0 :: xgxsControl ++ ***************************************************************************/ ++/* XgxsBlk0 :: xgxsControl :: start_sequencer [13:13] */ ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK 0x2000 ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_SHIFT 13 ++ ++/* XgxsBlk0 :: xgxsControl :: mode_10g [11:08] */ ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_MASK 0x0f00 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_BITS 4 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT 8 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS 0 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noCC 1 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane 6 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noLss 8 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noLss_noCC 9 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_protBypass 10 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_protBypass_noDsk 11 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_ComboCoreMode 12 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_ClocksOff 15 ++ ++/* XgxsBlk0 :: xgxsControl :: hstl [05:05] */ ++#define XGXSBLK0_XGXSCONTROL_HSTL_MASK 0x0020 ++#define XGXSBLK0_XGXSCONTROL_HSTL_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_HSTL_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_HSTL_SHIFT 5 ++ ++/* XgxsBlk0 :: xgxsControl :: cdet_en [03:03] */ ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_MASK 0x0008 ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_SHIFT 3 ++ ++/* XgxsBlk0 :: xgxsControl :: eden [02:02] */ ++#define XGXSBLK0_XGXSCONTROL_EDEN_MASK 0x0004 ++#define XGXSBLK0_XGXSCONTROL_EDEN_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_EDEN_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_EDEN_SHIFT 2 ++ ++/* XgxsBlk0 :: xgxsControl :: afrst_en [01:01] */ ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK 0x0002 ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_SHIFT 1 ++ ++/* XgxsBlk0 :: xgxsControl :: txcko_div [00:00] */ ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK 0x0001 ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * XgxsBlk0 :: xgxsStatus ++ ***************************************************************************/ ++/* XgxsBlk0 :: xgxsStatus :: txpll_lock [11:11] */ ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK 0x0800 ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_ALIGN 0 ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_BITS 1 ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_SHIFT 11 ++ ++ ++/**************************************************************************** ++ * XgxsBlk0 :: miscControl1 ++ ***************************************************************************/ ++/* XgxsBlk0 :: miscControl1 :: PCS_dev_en_override [10:10] */ ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_MASK 0x0400 ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_SHIFT 10 ++ ++/* XgxsBlk0 :: miscControl1 :: PMD_dev_en_override [09:09] */ ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_MASK 0x0200 ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_SHIFT 9 ++ ++/* XgxsBlk0 :: miscControl1 :: ieee_blksel_autodet [01:01] */ ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK 0x0002 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_SHIFT 1 ++ ++/* XgxsBlk0 :: miscControl1 :: ieee_blksel_val [00:00] */ ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK 0x0001 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_XgxsBlk1 ++ ***************************************************************************/ ++/**************************************************************************** ++ * XgxsBlk1 :: laneCtrl0 ++ ***************************************************************************/ ++/* XgxsBlk1 :: laneCtrl0 :: cl36_pcs_en_rx [07:04] */ ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK 0x00f0 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_ALIGN 0 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_BITS 4 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_SHIFT 4 ++ ++/* XgxsBlk1 :: laneCtrl0 :: cl36_pcs_en_tx [03:00] */ ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK 0x000f ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_ALIGN 0 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_BITS 4 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_TX0 ++ ***************************************************************************/ ++/**************************************************************************** ++ * TX0 :: Tx_AControl0 ++ ***************************************************************************/ ++/* TX0 :: Tx_AControl0 :: txpol_flip [05:05] */ ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_MASK 0x0020 ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_ALIGN 0 ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_BITS 1 ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_SHIFT 5 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_dsc_2_0 ++ ***************************************************************************/ ++/**************************************************************************** ++ * dsc_2_0 :: dsc_ctrl0 ++ ***************************************************************************/ ++/* dsc_2_0 :: dsc_ctrl0 :: rxSeqStart [15:15] */ ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK 0x8000 ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_ALIGN 0 ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_BITS 1 ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_SHIFT 15 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_SerdesDigital ++ ***************************************************************************/ ++/**************************************************************************** ++ * SerdesDigital :: Control1000X1 ++ ***************************************************************************/ ++/* SerdesDigital :: Control1000X1 :: crc_checker_disable [07:07] */ ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK 0x0080 ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_SHIFT 7 ++ ++/* SerdesDigital :: Control1000X1 :: disable_pll_pwrdwn [06:06] */ ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK 0x0040 ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_SHIFT 6 ++ ++/* SerdesDigital :: Control1000X1 :: fiber_mode_1000X [00:00] */ ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK 0x0001 ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_SHIFT 0 ++ ++/**************************************************************************** ++ * SerdesDigital :: Control1000X3 ++ ***************************************************************************/ ++/* SerdesDigital :: Control1000X3 :: fifo_elasicity_tx_rx [02:01] */ ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK 0x0006 ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_BITS 2 ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_SHIFT 1 ++ ++/* SerdesDigital :: Control1000X3 :: tx_fifo_rst [00:00] */ ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK 0x0001 ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_SHIFT 0 ++ ++/**************************************************************************** ++ * SerdesDigital :: Status1000X1 ++ ***************************************************************************/ ++/* SerdesDigital :: Status1000X1 :: speed_status [04:03] */ ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_MASK 0x0018 ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_ALIGN 0 ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_BITS 2 ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT 3 ++ ++/**************************************************************************** ++ * SerdesDigital :: Misc1 ++ ***************************************************************************/ ++/* SerdesDigital :: Misc1 :: force_speed_sel [04:04] */ ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK 0x0010 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_ALIGN 0 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_BITS 1 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_SHIFT 4 ++ ++/* SerdesDigital :: Misc1 :: force_speed [03:00] */ ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_MASK 0x000f ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_ALIGN 0 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_BITS 4 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * CL73_UserB0 :: CL73_BAMCtrl1 ++ ***************************************************************************/ ++/* CL73_UserB0 :: CL73_BAMCtrl1 :: CL73_bamEn [15:15] */ ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK 0x8000 ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_ALIGN 0 ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_BITS 1 ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_SHIFT 15 ++ ++ ++/**************************************************************************** ++ * Datatype Definitions. ++ ***************************************************************************/ ++#endif /* _PHY_XGXS16G_H_ */ ++ ++/* End of File */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmnvram.h b/drivers/bcmdrivers/gmac/src/include/bcmnvram.h +new file mode 100755 +index 0000000..a9c63d8 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmnvram.h +@@ -0,0 +1,295 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * NVRAM variable manipulation ++ * ++ * $Id: bcmnvram.h 325984 2012-04-05 08:51:37Z $ ++ */ ++ ++#ifndef _bcmnvram_h_ ++#define _bcmnvram_h_ ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++#include ++#include ++#include ++ ++struct nvram_header { ++ uint32 magic; ++ uint32 len; ++ uint32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ ++ uint32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ ++ uint32 config_ncdl; /* ncdl values for memc */ ++}; ++ ++struct nvram_otphdr { ++ struct nvram_header nvh; ++ uint16 flags_swmacm_gpio_phya; /* otp flags, switch/gmac mode, gpio, phyaddr */ ++ struct ether_addr mac; ++ uint32 clkfreq; ++}; ++ ++struct nvram_tuple { ++ char *name; ++ char *value; ++ struct nvram_tuple *next; ++}; ++ ++/* ++ * Get default value for an NVRAM variable ++ */ ++extern char *nvram_default_get(const char *name); ++ ++/* ++ * Initialize NVRAM access. May be unnecessary or undefined on certain ++ * platforms. ++ */ ++extern int nvram_init(void *sih); ++ ++/* ++ * Append a chunk of nvram variables to the global list ++ */ ++extern int nvram_append(void *si, char *vars, uint varsz); ++ ++extern void nvram_get_global_vars(char **varlst, uint *varsz); ++ ++ ++/* ++ * Check for reset button press for restoring factory defaults. ++ */ ++extern int nvram_reset(void *sih); ++ ++/* ++ * Disable NVRAM access. May be unnecessary or undefined on certain ++ * platforms. ++ */ ++extern void nvram_exit(void *sih); ++ ++/* ++ * Get the value of an NVRAM variable. The pointer returned may be ++ * invalid after a set. ++ * @param name name of variable to get ++ * @return value of variable or NULL if undefined ++ */ ++extern char * nvram_get(const char *name); ++ ++/* ++ * Read the reset GPIO value from the nvram and set the GPIO ++ * as input ++ */ ++extern int BCMINITFN(nvram_resetgpio_init)(void *sih); ++ ++/* ++ * Get the value of an NVRAM variable. ++ * @param name name of variable to get ++ * @return value of variable or NUL if undefined ++ */ ++static INLINE char * ++nvram_safe_get(const char *name) ++{ ++ char *p = nvram_get(name); ++ return p ? p : ""; ++} ++ ++/* ++ * Match an NVRAM variable. ++ * @param name name of variable to match ++ * @param match value to compare against value of variable ++ * @return TRUE if variable is defined and its value is string equal ++ * to match or FALSE otherwise ++ */ ++static INLINE int ++nvram_match(char *name, char *match) ++{ ++ const char *value = nvram_get(name); ++ return (value && !strcmp(value, match)); ++} ++ ++/* ++ * Inversely match an NVRAM variable. ++ * @param name name of variable to match ++ * @param match value to compare against value of variable ++ * @return TRUE if variable is defined and its value is not string ++ * equal to invmatch or FALSE otherwise ++ */ ++static INLINE int ++nvram_invmatch(char *name, char *invmatch) ++{ ++ const char *value = nvram_get(name); ++ return (value && strcmp(value, invmatch)); ++} ++ ++/* ++ * Set the value of an NVRAM variable. The name and value strings are ++ * copied into private storage. Pointers to previously set values ++ * may become invalid. The new value may be immediately ++ * retrieved but will not be permanently stored until a commit. ++ * @param name name of variable to set ++ * @param value value of variable ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_set(const char *name, const char *value); ++ ++/* ++ * Unset an NVRAM variable. Pointers to previously set values ++ * remain valid until a set. ++ * @param name name of variable to unset ++ * @return 0 on success and errno on failure ++ * NOTE: use nvram_commit to commit this change to flash. ++ */ ++extern int nvram_unset(const char *name); ++ ++/* ++ * NVRAM is based of FLASH or OTP. ++ * @return From FLASH: TRUE ++ * From OTP: FALSE ++ */ ++extern bool nvram_inotp(void); ++ ++/* ++ * Commit NVRAM header to OTP. All pointers to values ++ * may be invalid after a commit. ++ * NVRAM values are undefined after a commit. ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_otpcommit(void *sih); ++ ++/* ++ * Commit NVRAM variables to permanent storage. All pointers to values ++ * may be invalid after a commit. ++ * NVRAM values are undefined after a commit. ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_commit(void); ++ ++/* ++ * Get all NVRAM variables (format name=value\0 ... \0\0). ++ * @param buf buffer to store variables ++ * @param count size of buffer in bytes ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_getall(char *nvram_buf, int count); ++ ++/* ++ * returns the crc value of the nvram ++ * @param nvh nvram header pointer ++ */ ++uint8 nvram_calc_crc(struct nvram_header * nvh); ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* The NVRAM version number stored as an NVRAM variable */ ++#define NVRAM_SOFTWARE_VERSION "1" ++ ++#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ ++#define NVRAM_CLEAR_MAGIC 0x0 ++#define NVRAM_INVALID_MAGIC 0xFFFFFFFF ++#define NVRAM_VERSION 1 ++#define NVRAM_HEADER_SIZE 20 ++#define NVRAM_SPACE 0x8000 ++#define ENVRAM_SPACE 0x1000 ++ ++#define NVRAM_MAX_VALUE_LEN 255 ++#define NVRAM_MAX_PARAM_LEN 64 ++ ++#define NVRAM_CRC_START_POSITION 9 /* magic, len, crc8 to be skipped */ ++#define NVRAM_CRC_VER_MASK 0xffffff00 /* for crc_ver_init */ ++ ++/* Incase of nvram header(in OTP), we save 16bit after nvram header ++ * o 0:0 Switch Present ++ * o 1:4 Switch and gmac mode ++ * o 5:10 robo reset GPIO pin number ++ * o 11:15 phyaddr ++ */ ++#define OTPNVRAM_SWITCH_PRESENT 0x1 ++ ++#define OTPNVRAM_FLAGS_MASK 0x1 ++#define OTPNVRAM_SMACMODE_MASK 0x1e ++#define OTPNVRAM_GPIO_MASK 0x7e0 ++#define OTPNVRAM_PHYADDR_MASK 0xf800 ++ ++#define OTPNVRAM_SMACMODE_SHIFT 1 ++#define OTPNVRAM_GPIO_SHIFT 5 ++#define OTPNVRAM_PHYADDR_SHIFT 11 ++ ++/* clkfreq is saved in following format in OTP nvram data ++ * 9:0 pci clock ++ * 20:10 si clock ++ * 31:21 mips clock ++ */ ++ ++#define NVRAM_PCI_CLKMASK 0x3ff ++#define NVRAM_SI_CLKMASK 0x1ffc00 ++#define NVRAM_SI_CLKSHIFT 10 ++#define NVRAM_CPUCLK_SHIFT 21 ++ ++/* Offsets to embedded nvram area */ ++#define NVRAM_START_COMPRESSED 0x400 ++#define NVRAM_START 0x1000 ++ ++#define BCM_JUMBO_NVRAM_DELIMIT '\n' ++#define BCM_JUMBO_START "Broadcom Jumbo Nvram file" ++ ++#if !defined(BCMHIGHSDIO) && defined(BCMTRXV2) ++extern char *_vars; ++extern uint _varsz; ++#endif ++ ++#if (defined(FAILSAFE_UPGRADE) || defined(CONFIG_FAILSAFE_UPGRADE) || \ ++ defined(__CONFIG_FAILSAFE_UPGRADE_SUPPORT__)) ++#define IMAGE_SIZE "image_size" ++#define BOOTPARTITION "bootpartition" ++#define IMAGE_BOOT BOOTPARTITION ++#define PARTIALBOOTS "partialboots" ++#define MAXPARTIALBOOTS "maxpartialboots" ++#define IMAGE_1ST_FLASH_TRX "flash0.trx" ++#define IMAGE_1ST_FLASH_OS "flash0.os" ++#define IMAGE_2ND_FLASH_TRX "flash0.trx2" ++#define IMAGE_2ND_FLASH_OS "flash0.os2" ++#define IMAGE_FIRST_OFFSET "image_first_offset" ++#define IMAGE_SECOND_OFFSET "image_second_offset" ++#define LINUX_FIRST "linux" ++#define LINUX_SECOND "linux2" ++#endif ++ ++#if (defined(DUAL_IMAGE) || defined(CONFIG_DUAL_IMAGE) || \ ++ defined(__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__)) ++/* Shared by all: CFE, Linux Kernel, and Ap */ ++#define IMAGE_BOOT "image_boot" ++#define BOOTPARTITION IMAGE_BOOT ++/* CFE variables */ ++#define IMAGE_1ST_FLASH_TRX "flash0.trx" ++#define IMAGE_1ST_FLASH_OS "flash0.os" ++#define IMAGE_2ND_FLASH_TRX "flash0.trx2" ++#define IMAGE_2ND_FLASH_OS "flash0.os2" ++#define IMAGE_SIZE "image_size" ++ ++/* CFE and Linux Kernel shared variables */ ++#define IMAGE_FIRST_OFFSET "image_first_offset" ++#define IMAGE_SECOND_OFFSET "image_second_offset" ++ ++/* Linux application variables */ ++#define LINUX_FIRST "linux" ++#define LINUX_SECOND "linux2" ++#define POLICY_TOGGLE "toggle" ++#define LINUX_PART_TO_FLASH "linux_to_flash" ++#define LINUX_FLASH_POLICY "linux_flash_policy" ++ ++#endif /* defined(DUAL_IMAGE||CONFIG_DUAL_IMAGE)||__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__ */ ++ ++int nvram_env_gmac_name(int gmac, char *name); ++ ++#endif /* _bcmnvram_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmotp.h b/drivers/bcmdrivers/gmac/src/include/bcmotp.h +new file mode 100755 +index 0000000..d1ec475 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmotp.h +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * OTP support. ++ * ++ * $Id: bcmotp.h 321779 2012-03-16 19:39:00Z $ ++ */ ++ ++#ifndef _bcmotp_h_ ++#define _bcmotp_h_ ++ ++/* OTP regions */ ++#define OTP_HW_RGN 1 ++#define OTP_SW_RGN 2 ++#define OTP_CI_RGN 4 ++#define OTP_FUSE_RGN 8 ++#define OTP_ALL_RGN 0xf /* From h/w region to end of OTP including checksum */ ++ ++/* OTP Size */ ++#define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */ ++ ++/* Fixed size subregions sizes in words */ ++#define OTPGU_CI_SZ 2 ++ ++/* OTP usage */ ++#define OTP4325_FM_DISABLED_OFFSET 188 ++ ++#ifdef BCMNVRAMW ++/* Global RDE index for chips not having an OTP PMU resource. */ ++#define OTP_GLOBAL_RDE_IDX 0xFF ++#endif ++ ++/* Exported functions */ ++extern int otp_status(void *oh); ++extern int otp_size(void *oh); ++extern uint16 otp_read_bit(void *oh, uint offset); ++extern void* otp_init(si_t *sih); ++extern int otp_read_region(si_t *sih, int region, uint16 *data, uint *wlen); ++extern int otp_read_word(si_t *sih, uint wn, uint16 *data); ++extern int otp_nvread(void *oh, char *data, uint *len); ++#ifdef BCMNVRAMW ++extern int otp_write_region(si_t *sih, int region, uint16 *data, uint wlen); ++extern int otp_write_word(si_t *sih, uint wn, uint16 data); ++extern int otp_cis_append_region(si_t *sih, int region, char *vars, int count); ++extern int otp_lock(si_t *sih); ++extern int otp_nvwrite(void *oh, uint16 *data, uint wlen); ++#endif /* BCMNVRAMW */ ++ ++#if defined(WLTEST) ++extern int otp_dump(void *oh, int arg, char *buf, uint size); ++extern int otp_dumpstats(void *oh, int arg, char *buf, uint size); ++#endif ++ ++#if defined(BCMNVRAMW) ++#define otp_write_rde(oh, rde, bit, val) ipxotp_write_rde(oh, rde, bit, val) ++extern int ipxotp_write_rde(void *oh, int rde, uint bit, uint val); ++extern int otp_write_bits(void *oh, uint offset, int bits, uint8* data); ++ ++#ifdef OTP_DEBUG ++extern int otp_verify1x(void *oh, uint off, uint fuse); ++extern int otp_read1x(void *oh, uint off, uint fuse); ++extern int otp_repair_bit(void *oh, uint off, uint val); ++extern int otp_write_ones(void *oh, uint off, uint bits); ++extern int otp_write_ones_old(void *oh, uint off, uint bits); ++#endif ++ ++#endif ++ ++#endif /* _bcmotp_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmparams.h b/drivers/bcmdrivers/gmac/src/include/bcmparams.h +new file mode 100755 +index 0000000..da6eb4c +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmparams.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc system wide parameters. ++ * ++ * $Id: bcmparams.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmparams_h_ ++#define _bcmparams_h_ ++ ++#define VLAN_MAXVID 15 /* Max. VLAN ID supported/allowed */ ++ ++#define VLAN_NUMPRIS 8 /* # of prio, start from 0 */ ++ ++#define DEV_NUMIFS 16 /* Max. # of devices/interfaces supported */ ++ ++#define WL_MAXBSSCFG 16 /* maximum number of BSS Configs we can configure */ ++ ++#endif +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmperf.h b/drivers/bcmdrivers/gmac/src/include/bcmperf.h +new file mode 100755 +index 0000000..2ec4079 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmperf.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Performance counters software interface. ++ * ++ * $Id: bcmperf.h 241182 2011-02-17 21:50:03Z $ ++ */ ++/* essai */ ++#ifndef _BCMPERF_H_ ++#define _BCMPERF_H_ ++/* get cache hits and misses */ ++#if defined(BCMMIPS) && defined(BCMPERFSTATS) ++#include ++#define BCMPERF_ENABLE_INSTRCOUNT() hndmips_perf_instrcount_enable() ++#define BCMPERF_ENABLE_ICACHE_MISS() hndmips_perf_icache_miss_enable() ++#define BCMPERF_ENABLE_ICACHE_HIT() hndmips_perf_icache_hit_enable() ++#define BCMPERF_GETICACHE_MISS(x) ((x) = hndmips_perf_read_cache_miss()) ++#define BCMPERF_GETICACHE_HIT(x) ((x) = hndmips_perf_read_cache_hit()) ++#define BCMPERF_GETINSTRCOUNT(x) ((x) = hndmips_perf_read_instrcount()) ++#else ++#define BCMPERF_ENABLE_INSTRCOUNT() ++#define BCMPERF_ENABLE_ICACHE_MISS() ++#define BCMPERF_ENABLE_ICACHE_HIT() ++#define BCMPERF_GETICACHE_MISS(x) ((x) = 0) ++#define BCMPERF_GETICACHE_HIT(x) ((x) = 0) ++#define BCMPERF_GETINSTRCOUNT(x) ((x) = 0) ++#endif /* defined(mips) */ ++#endif /* _BCMPERF_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmrobo.h b/drivers/bcmdrivers/gmac/src/include/bcmrobo.h +new file mode 100755 +index 0000000..38f5a9f +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmrobo.h +@@ -0,0 +1,203 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * RoboSwitch setup functions ++ * ++ * $Id: bcmrobo.h 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++#ifndef _bcm_robo_h_ ++#define _bcm_robo_h_ ++ ++/* ++ * MODELID: ++ * 0x53010: BCM53010, Select Low SKU device if SKU ID[1:0] = 01. ++ * 0x53011: BCM53011, Select Middle SKU device if SKU ID[1:0] = 10. ++ * 0x53012: BCM53012, Select High SKU device if SKU ID[1:0] = 00. ++ * Note: The SKU ID[1:0] is loaded from OTP configuration data. ++ */ ++#define DEVID53010 0x53010 /* 53010 */ ++#define DEVID53011 0x53011 /* 53011 */ ++#define DEVID53012 0x53012 /* 53012 */ ++#define DEVID53013 0x53013 /* 53013 */ ++#define DEVID53014 0x53014 /* 53014 */ ++#define DEVID53015 0x53015 /* 53015 */ ++#define DEVID53016 0x53016 /* 53016 */ ++#define DEVID53017 0x53017 /* 53017 */ ++#define DEVID53018 0x53018 /* 53018 */ ++#define DEVID53019 0x53019 /* 53019 */ ++#define DEVID53022 0x53022 /* 53022 */ ++#define DEVID53025 0x53025 /* 53025 */ ++ ++#define ROBO_IS_BCM5301X(id) (1) ++#define ROBO_IS_VEGA(id) ((id) >= DEVID53014 && (id) <= DEVID53017) ++ ++#define OTP_SKU_ID_53014 0x2 ++#define OTP_SKU_ID_53015 0x3 ++#define OTP_SKU_ID_53016 0x4 ++ ++/* Power save duty cycle times */ ++#define MAX_NO_PHYS 5 ++#define PWRSAVE_SLEEP_TIME 12 ++#define PWRSAVE_WAKE_TIME 3 ++ ++/* Power save modes for the switch */ ++#define ROBO_PWRSAVE_NORMAL 0 ++#define ROBO_PWRSAVE_AUTO 1 ++#define ROBO_PWRSAVE_MANUAL 2 ++#define ROBO_PWRSAVE_AUTO_MANUAL 3 ++ ++#define ROBO_IS_PWRSAVE_MANUAL(r) ((r)->pwrsave_mode_manual) ++#define ROBO_IS_PWRSAVE_AUTO(r) ((r)->pwrsave_mode_auto) ++ ++/* NorthStar SRAB interface */ ++/* Access switch registers through SRAB (Switch Register Access Bridge) */ ++#define REG_VERSION_ID 0x40 ++#define REG_CTRL_PORT0_GMIIPO 0x58 /* 53012: GMII Port0 Override register */ ++#define REG_CTRL_PORT1_GMIIPO 0x59 /* 53012: GMII Port1 Override register */ ++#define REG_CTRL_PORT2_GMIIPO 0x5a /* 53012: GMII Port2 Override register */ ++#define REG_CTRL_PORT3_GMIIPO 0x5b /* 53012: GMII Port3 Override register */ ++#define REG_CTRL_PORT4_GMIIPO 0x5c /* 53012: GMII Port4 Override register */ ++#define REG_CTRL_PORT5_GMIIPO 0x5d /* 53012: GMII Port5 Override register */ ++#define REG_CTRL_PORT7_GMIIPO 0x5f /* 53012: GMII Port7 Override register */ ++ ++/* Command and status register of the SRAB */ ++#define CFG_F_sra_rst_MASK (1 << 2) ++#define CFG_F_sra_write_MASK (1 << 1) ++#define CFG_F_sra_gordyn_MASK (1 << 0) ++#define CFG_F_sra_page_R 24 ++#define CFG_F_sra_offset_R 16 ++ ++/* Switch interface controls */ ++#define CFG_F_sw_init_done_MASK (1 << 6) ++#define CFG_F_rcareq_MASK (1 << 3) ++#define CFG_F_rcagnt_MASK (1 << 4) ++ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++#define PAGE_P5_SGMII 0x16 ++#define PAGE_P4_SGMII 0x17 ++ ++/* SGMII REGISTERS */ ++#define REG_SGMII_BLK_ADDR 0x3e ++#define REG_IEEECTRL0 0x0000 ++#define REG_TX_ACTL0 0x8061 ++#define REG_TX_DRIVER 0x8065 ++#define REG_RX_CONTROL 0x80f1 ++#define REG_RX_ANLOGBIAS0L 0x80fc ++#define REG_SERDES_CTL1000X1 0x8300 ++#define REG_SERDES_CTL1000X2 0x8301 ++#define REG_SERDES_CTL1000X3 0x8302 ++#define REG_SERDES_STAT1000X1 0x8304 ++#define REG_COMBO_IEEE0_MIICTL 0xffe0 ++#define REG_COMBO_IEEE0_ANADV 0xffe4 ++#define REG_COMBO_IEEE0_ANLP 0xffe5 ++ ++#define PORTCFG_5 5 ++#define PORTCFG_4 4 ++#define PORTCFG "port%dcfg" ++#define PORTCFG_RGMII "rgmii" ++#define PORTCFG_SGMII "sgmii" ++#define PORTCFG_GPHY "gphy" ++ ++typedef volatile struct { ++ uint32 PAD[11]; ++ uint32 cmdstat; /* 0x2c, command and status register of the SRAB */ ++ uint32 wd_h; /* 0x30, high order word of write data to switch registe */ ++ uint32 wd_l; /* 0x34, low order word of write data to switch registe */ ++ uint32 rd_h; /* 0x38, high order word of read data from switch register */ ++ uint32 rd_l; /* 0x3c, low order word of read data from switch register */ ++ uint32 ctrls; /* 0x40, switch interface controls */ ++ uint32 intr; /* 0x44, the register captures interrupt pulses from the switch */ ++} srabregs_t; ++ ++/* Forward declaration */ ++typedef struct robo_info_s robo_info_t; ++ ++/* Device access/config oprands */ ++typedef struct { ++ /* low level routines */ ++ void (*enable_mgmtif)(robo_info_t *robo); /* enable mgmt i/f, optional */ ++ void (*disable_mgmtif)(robo_info_t *robo); /* disable mgmt i/f, optional */ ++ int (*write_reg)(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len); ++ int (*read_reg)(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len); ++ /* description */ ++ char *desc; ++} dev_ops_t; ++ ++ ++typedef uint16 (*miird_f)(void *h, int add, int off); ++typedef void (*miiwr_f)(void *h, int add, int off, uint16 val); ++ ++/* Private state per RoboSwitch */ ++struct robo_info_s { ++ si_t *sih; /* SiliconBackplane handle */ ++ char *vars; /* nvram variables handle */ ++ void *h; /* dev handle */ ++ uint16 devid; /* Device id for the switch */ ++ uint32 devid32; /* Device id for the switch (32bits) */ ++ uint32 corerev; /* Core rev of internal switch */ ++ ++ dev_ops_t *ops; /* device ops */ ++ uint8 page; /* current page */ ++ ++ /* SPI */ ++ uint32 ss, sck, mosi, miso; /* GPIO mapping */ ++ ++ /* MII */ ++ miird_f miird; ++ miiwr_f miiwr; ++ ++ /* SRAB */ ++ srabregs_t *srabregs; ++ ++ uint16 prev_status; /* link status of switch ports */ ++ uint32 pwrsave_mode_manual; /* bitmap of ports in manual power save */ ++ uint32 pwrsave_mode_auto; /* bitmap of ports in auto power save mode */ ++ uint8 pwrsave_phys; /* Phys that can be put into power save mode */ ++ uint8 pwrsave_mode_phys[MAX_NO_PHYS]; /* Power save mode on the switch */ ++}; ++ ++extern int srab_sgmii_rreg(robo_info_t *robo, uint8 page, uint16 reg, uint16 *val); ++extern int srab_sgmii_wreg(robo_info_t *robo, uint8 page, uint16 reg, uint16 *val); ++ ++/* Power Save mode related functions */ ++extern int32 robo_power_save_mode_get(robo_info_t *robo, int32 phy); ++extern int32 robo_power_save_mode_set(robo_info_t *robo, int32 mode, int32 phy); ++extern void robo_power_save_mode_update(robo_info_t *robo); ++extern int robo_power_save_mode(robo_info_t *robo, int mode, int phy); ++extern int robo_power_save_toggle(robo_info_t *robo, int normal); ++ ++extern robo_info_t *bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr); ++extern void bcm_robo_detach(robo_info_t *robo); ++extern int bcm_robo_enable_device(robo_info_t *robo); ++extern int bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr); ++extern int bcm_robo_enable_switch(robo_info_t *robo); ++extern int robo_is_port5_cpu(void); ++extern int robo_is_port_cfg(int port, char *cfg); ++ ++extern void robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b); ++ ++extern void robo_watchdog(robo_info_t *robo); ++ ++void robo_reset_mib(robo_info_t *robo); ++void robo_dump_mib(robo_info_t *robo); ++void robo_bprintf_mib(robo_info_t *robo, struct bcmstrbuf *b); ++ ++#endif /* _bcm_robo_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsdh.h b/drivers/bcmdrivers/gmac/src/include/bcmsdh.h +new file mode 100755 +index 0000000..2767f73 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsdh.h +@@ -0,0 +1,226 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * SDIO host client driver interface of Broadcom HNBU ++ * export functions to client drivers ++ * abstract OS and BUS specific details of SDIO ++ * ++ * $Id: bcmsdh.h 299859 2011-12-01 03:53:27Z $ ++ */ ++ ++/** ++ * @file bcmsdh.h ++ */ ++ ++#ifndef _bcmsdh_h_ ++#define _bcmsdh_h_ ++ ++#define BCMSDH_ERROR_VAL 0x0001 /* Error */ ++#define BCMSDH_INFO_VAL 0x0002 /* Info */ ++extern const uint bcmsdh_msglevel; ++ ++#ifdef BCMDBG ++#define BCMSDH_ERROR(x) do { if (bcmsdh_msglevel & BCMSDH_ERROR_VAL) printf x; } while (0) ++#define BCMSDH_INFO(x) do { if (bcmsdh_msglevel & BCMSDH_INFO_VAL) printf x; } while (0) ++#else /* BCMDBG */ ++#define BCMSDH_ERROR(x) ++#define BCMSDH_INFO(x) ++#endif /* BCMDBG */ ++ ++ ++/* forward declarations */ ++typedef struct bcmsdh_info bcmsdh_info_t; ++typedef void (*bcmsdh_cb_fn_t)(void *); ++ ++/* Attach and build an interface to the underlying SD host driver. ++ * - Allocates resources (structs, arrays, mem, OS handles, etc) needed by bcmsdh. ++ * - Returns the bcmsdh handle and virtual address base for register access. ++ * The returned handle should be used in all subsequent calls, but the bcmsh ++ * implementation may maintain a single "default" handle (e.g. the first or ++ * most recent one) to enable single-instance implementations to pass NULL. ++ */ ++extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq); ++ ++/* Detach - freeup resources allocated in attach */ ++extern int bcmsdh_detach(osl_t *osh, void *sdh); ++ ++/* Query if SD device interrupts are enabled */ ++extern bool bcmsdh_intr_query(void *sdh); ++ ++/* Enable/disable SD interrupt */ ++extern int bcmsdh_intr_enable(void *sdh); ++extern int bcmsdh_intr_disable(void *sdh); ++ ++/* Register/deregister device interrupt handler. */ ++extern int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh); ++extern int bcmsdh_intr_dereg(void *sdh); ++ ++#if defined(DHD_DEBUG) || defined(BCMDBG) ++/* Query pending interrupt status from the host controller */ ++extern bool bcmsdh_intr_pending(void *sdh); ++#endif ++ ++/* Register a callback to be called if and when bcmsdh detects ++ * device removal. No-op in the case of non-removable/hardwired devices. ++ */ ++extern int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh); ++ ++/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface). ++ * fn: function number ++ * addr: unmodified SDIO-space address ++ * data: data byte to write ++ * err: pointer to error code (or NULL) ++ */ ++extern uint8 bcmsdh_cfg_read(void *sdh, uint func, uint32 addr, int *err); ++extern void bcmsdh_cfg_write(void *sdh, uint func, uint32 addr, uint8 data, int *err); ++ ++/* Read/Write 4bytes from/to cfg space */ ++extern uint32 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, uint32 addr, int *err); ++extern void bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *err); ++ ++/* Read CIS content for specified function. ++ * fn: function whose CIS is being requested (0 is common CIS) ++ * cis: pointer to memory location to place results ++ * length: number of bytes to read ++ * Internally, this routine uses the values from the cis base regs (0x9-0xB) ++ * to form an SDIO-space address to read the data from. ++ */ ++extern int bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length); ++ ++/* Synchronous access to device (client) core registers via CMD53 to F1. ++ * addr: backplane address (i.e. >= regsva from attach) ++ * size: register width in bytes (2 or 4) ++ * data: data for register write ++ */ ++extern uint32 bcmsdh_reg_read(void *sdh, uint32 addr, uint size); ++extern uint32 bcmsdh_reg_write(void *sdh, uint32 addr, uint size, uint32 data); ++ ++/* set sb address window */ ++extern int bcmsdhsdio_set_sbaddr_window(void *sdh, uint32 address, bool force_set); ++ ++/* Indicate if last reg read/write failed */ ++extern bool bcmsdh_regfail(void *sdh); ++ ++/* Buffer transfer to/from device (client) core via cmd53. ++ * fn: function number ++ * addr: backplane address (i.e. >= regsva from attach) ++ * flags: backplane width, address increment, sync/async ++ * buf: pointer to memory data buffer ++ * nbytes: number of bytes to transfer to/from buf ++ * pkt: pointer to packet associated with buf (if any) ++ * complete: callback function for command completion (async only) ++ * handle: handle for completion callback (first arg in callback) ++ * Returns 0 or error code. ++ * NOTE: Async operation is not currently supported. ++ */ ++typedef void (*bcmsdh_cmplt_fn_t)(void *handle, int status, bool sync_waiting); ++extern int bcmsdh_send_buf(void *sdh, uint32 addr, uint fn, uint flags, ++ uint8 *buf, uint nbytes, void *pkt, ++ bcmsdh_cmplt_fn_t complete_fn, void *handle); ++extern int bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags, ++ uint8 *buf, uint nbytes, void *pkt, ++ bcmsdh_cmplt_fn_t complete_fn, void *handle); ++ ++/* Flags bits */ ++#define SDIO_REQ_4BYTE 0x1 /* Four-byte target (backplane) width (vs. two-byte) */ ++#define SDIO_REQ_FIXED 0x2 /* Fixed address (FIFO) (vs. incrementing address) */ ++#define SDIO_REQ_ASYNC 0x4 /* Async request (vs. sync request) */ ++#define SDIO_BYTE_MODE 0x8 /* Byte mode request(non-block mode) */ ++ ++/* Pending (non-error) return code */ ++#define BCME_PENDING 1 ++ ++/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only). ++ * rw: read or write (0/1) ++ * addr: direct SDIO address ++ * buf: pointer to memory data buffer ++ * nbytes: number of bytes to transfer to/from buf ++ * Returns 0 or error code. ++ */ ++extern int bcmsdh_rwdata(void *sdh, uint rw, uint32 addr, uint8 *buf, uint nbytes); ++ ++/* Issue an abort to the specified function */ ++extern int bcmsdh_abort(void *sdh, uint fn); ++ ++/* Start SDIO Host Controller communication */ ++extern int bcmsdh_start(void *sdh, int stage); ++ ++/* Stop SDIO Host Controller communication */ ++extern int bcmsdh_stop(void *sdh); ++ ++/* Wait system lock free */ ++extern int bcmsdh_waitlockfree(void *sdh); ++ ++/* Returns the "Device ID" of target device on the SDIO bus. */ ++extern int bcmsdh_query_device(void *sdh); ++ ++/* Returns the number of IO functions reported by the device */ ++extern uint bcmsdh_query_iofnum(void *sdh); ++ ++/* Miscellaneous knob tweaker. */ ++extern int bcmsdh_iovar_op(void *sdh, const char *name, ++ void *params, int plen, void *arg, int len, bool set); ++ ++/* Reset and reinitialize the device */ ++extern int bcmsdh_reset(bcmsdh_info_t *sdh); ++ ++/* helper functions */ ++ ++extern void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh); ++ ++/* callback functions */ ++typedef struct { ++ /* attach to device */ ++ void *(*attach)(uint16 vend_id, uint16 dev_id, uint16 bus, uint16 slot, ++ uint16 func, uint bustype, void * regsva, osl_t * osh, ++ void * param); ++ /* detach from device */ ++ void (*detach)(void *ch); ++} bcmsdh_driver_t; ++ ++/* platform specific/high level functions */ ++extern int bcmsdh_register(bcmsdh_driver_t *driver); ++extern void bcmsdh_unregister(void); ++extern bool bcmsdh_chipmatch(uint16 vendor, uint16 device); ++extern void bcmsdh_device_remove(void * sdh); ++ ++#if defined(OOB_INTR_ONLY) ++extern int bcmsdh_register_oob_intr(void * dhdp); ++extern void bcmsdh_unregister_oob_intr(void); ++extern void bcmsdh_oob_intr_set(bool enable); ++#endif /* defined(OOB_INTR_ONLY) */ ++ ++/* Function to pass device-status bits to DHD. */ ++extern uint32 bcmsdh_get_dstatus(void *sdh); ++ ++/* Function to return current window addr */ ++extern uint32 bcmsdh_cur_sbwad(void *sdh); ++ ++/* Function to pass chipid and rev to lower layers for controlling pr's */ ++extern void bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev); ++ ++#ifdef BCMSPI ++extern void bcmsdh_dwordmode(void *sdh, bool set); ++#endif /* BCMSPI */ ++ ++extern int bcmsdh_sleep(void *sdh, bool enab); ++ ++/* GPIO support */ ++extern int bcmsdh_gpio_init(void *sd); ++extern bool bcmsdh_gpioin(void *sd, uint32 gpio); ++extern int bcmsdh_gpioouten(void *sd, uint32 gpio); ++extern int bcmsdh_gpioout(void *sd, uint32 gpio, bool enab); ++ ++#endif /* _bcmsdh_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsdpcm.h b/drivers/bcmdrivers/gmac/src/include/bcmsdpcm.h +new file mode 100755 +index 0000000..c1a320c +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsdpcm.h +@@ -0,0 +1,268 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom SDIO/PCMCIA ++ * Software-specific definitions shared between device and host side ++ * ++ * $Id: bcmsdpcm.h 314495 2012-02-12 07:56:39Z $ ++ */ ++ ++#ifndef _bcmsdpcm_h_ ++#define _bcmsdpcm_h_ ++ ++/* ++ * Software allocation of To SB Mailbox resources ++ */ ++ ++/* intstatus bits */ ++#define I_SMB_NAK I_SMB_SW0 /* To SB Mailbox Frame NAK */ ++#define I_SMB_INT_ACK I_SMB_SW1 /* To SB Mailbox Host Interrupt ACK */ ++#define I_SMB_USE_OOB I_SMB_SW2 /* To SB Mailbox Use OOB Wakeup */ ++#define I_SMB_DEV_INT I_SMB_SW3 /* To SB Mailbox Miscellaneous Interrupt */ ++ ++#define I_TOSBMAIL (I_SMB_NAK | I_SMB_INT_ACK | I_SMB_USE_OOB | I_SMB_DEV_INT) ++ ++/* tosbmailbox bits corresponding to intstatus bits */ ++#define SMB_NAK (1 << 0) /* To SB Mailbox Frame NAK */ ++#define SMB_INT_ACK (1 << 1) /* To SB Mailbox Host Interrupt ACK */ ++#define SMB_USE_OOB (1 << 2) /* To SB Mailbox Use OOB Wakeup */ ++#define SMB_DEV_INT (1 << 3) /* To SB Mailbox Miscellaneous Interrupt */ ++#define SMB_MASK 0x0000000f /* To SB Mailbox Mask */ ++ ++/* tosbmailboxdata */ ++#define SMB_DATA_VERSION_MASK 0x00ff0000 /* host protocol version (sent with F2 enable) */ ++#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version (sent with F2 enable) */ ++ ++/* ++ * Software allocation of To Host Mailbox resources ++ */ ++ ++/* intstatus bits */ ++#define I_HMB_FC_STATE I_HMB_SW0 /* To Host Mailbox Flow Control State */ ++#define I_HMB_FC_CHANGE I_HMB_SW1 /* To Host Mailbox Flow Control State Changed */ ++#define I_HMB_FRAME_IND I_HMB_SW2 /* To Host Mailbox Frame Indication */ ++#define I_HMB_HOST_INT I_HMB_SW3 /* To Host Mailbox Miscellaneous Interrupt */ ++ ++#define I_TOHOSTMAIL (I_HMB_FC_CHANGE | I_HMB_FRAME_IND | I_HMB_HOST_INT) ++ ++/* tohostmailbox bits corresponding to intstatus bits */ ++#define HMB_FC_ON (1 << 0) /* To Host Mailbox Flow Control State */ ++#define HMB_FC_CHANGE (1 << 1) /* To Host Mailbox Flow Control State Changed */ ++#define HMB_FRAME_IND (1 << 2) /* To Host Mailbox Frame Indication */ ++#define HMB_HOST_INT (1 << 3) /* To Host Mailbox Miscellaneous Interrupt */ ++#define HMB_MASK 0x0000000f /* To Host Mailbox Mask */ ++ ++/* tohostmailboxdata */ ++#define HMB_DATA_NAKHANDLED 0x01 /* we're ready to retransmit NAK'd frame to host */ ++#define HMB_DATA_DEVREADY 0x02 /* we're ready to to talk to host after enable */ ++#define HMB_DATA_FC 0x04 /* per prio flowcontrol update flag to host */ ++#define HMB_DATA_FWREADY 0x08 /* firmware is ready for protocol activity */ ++#define HMB_DATA_FWHALT 0x10 /* firmware has halted operation */ ++ ++#define HMB_DATA_FCDATA_MASK 0xff000000 /* per prio flowcontrol data */ ++#define HMB_DATA_FCDATA_SHIFT 24 /* per prio flowcontrol data */ ++ ++#define HMB_DATA_VERSION_MASK 0x00ff0000 /* device protocol version (with devready) */ ++#define HMB_DATA_VERSION_SHIFT 16 /* device protocol version (with devready) */ ++ ++/* ++ * Software-defined protocol header ++ */ ++ ++/* Current protocol version */ ++#define SDPCM_PROT_VERSION 4 ++ ++/* SW frame header */ ++#define SDPCM_SEQUENCE_MASK 0x000000ff /* Sequence Number Mask */ ++#define SDPCM_PACKET_SEQUENCE(p) (((uint8 *)p)[0] & 0xff) /* p starts w/SW Header */ ++ ++#define SDPCM_CHANNEL_MASK 0x00000f00 /* Channel Number Mask */ ++#define SDPCM_CHANNEL_SHIFT 8 /* Channel Number Shift */ ++#define SDPCM_PACKET_CHANNEL(p) (((uint8 *)p)[1] & 0x0f) /* p starts w/SW Header */ ++ ++#define SDPCM_FLAGS_MASK 0x0000f000 /* Mask of flag bits */ ++#define SDPCM_FLAGS_SHIFT 12 /* Flag bits shift */ ++#define SDPCM_PACKET_FLAGS(p) ((((uint8 *)p)[1] & 0xf0) >> 4) /* p starts w/SW Header */ ++ ++/* Next Read Len: lookahead length of next frame, in 16-byte units (rounded up) */ ++#define SDPCM_NEXTLEN_MASK 0x00ff0000 /* Next Read Len Mask */ ++#define SDPCM_NEXTLEN_SHIFT 16 /* Next Read Len Shift */ ++#define SDPCM_NEXTLEN_VALUE(p) ((((uint8 *)p)[2] & 0xff) << 4) /* p starts w/SW Header */ ++#define SDPCM_NEXTLEN_OFFSET 2 ++ ++/* Data Offset from SOF (HW Tag, SW Tag, Pad) */ ++#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */ ++#define SDPCM_DOFFSET_VALUE(p) (((uint8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) ++#define SDPCM_DOFFSET_MASK 0xff000000 ++#define SDPCM_DOFFSET_SHIFT 24 ++ ++#define SDPCM_FCMASK_OFFSET 4 /* Flow control */ ++#define SDPCM_FCMASK_VALUE(p) (((uint8 *)p)[SDPCM_FCMASK_OFFSET ] & 0xff) ++#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */ ++#define SDPCM_WINDOW_VALUE(p) (((uint8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff) ++#define SDPCM_VERSION_OFFSET 6 /* Version # */ ++#define SDPCM_VERSION_VALUE(p) (((uint8 *)p)[SDPCM_VERSION_OFFSET] & 0xff) ++#define SDPCM_UNUSED_OFFSET 7 /* Spare */ ++#define SDPCM_UNUSED_VALUE(p) (((uint8 *)p)[SDPCM_UNUSED_OFFSET] & 0xff) ++ ++#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */ ++ ++/* logical channel numbers */ ++#define SDPCM_CONTROL_CHANNEL 0 /* Control Request/Response Channel Id */ ++#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */ ++#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */ ++#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets (superframes) */ ++#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */ ++#define SDPCM_MAX_CHANNEL 15 ++ ++#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for eight-bit frame seq number */ ++ ++#define SDPCM_FLAG_RESVD0 0x01 ++#define SDPCM_FLAG_RESVD1 0x02 ++#define SDPCM_FLAG_GSPI_TXENAB 0x04 ++#define SDPCM_FLAG_GLOMDESC 0x08 /* Superframe descriptor mask */ ++ ++/* For GLOM_CHANNEL frames, use a flag to indicate descriptor frame */ ++#define SDPCM_GLOMDESC_FLAG (SDPCM_FLAG_GLOMDESC << SDPCM_FLAGS_SHIFT) ++ ++#define SDPCM_GLOMDESC(p) (((uint8 *)p)[1] & 0x80) ++ ++/* For TEST_CHANNEL packets, define another 4-byte header */ ++#define SDPCM_TEST_HDRLEN 4 /* Generally: Cmd(1), Ext(1), Len(2); ++ * Semantics of Ext byte depend on command. ++ * Len is current or requested frame length, not ++ * including test header; sent little-endian. ++ */ ++#define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext is a pattern id. */ ++#define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext is a pattern id. */ ++#define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext is a pattern id. */ ++#define SDPCM_TEST_BURST 0x04 /* Receiver to send a burst. Ext is a frame count */ ++#define SDPCM_TEST_SEND 0x05 /* Receiver sets send mode. Ext is boolean on/off */ ++ ++/* Handy macro for filling in datagen packets with a pattern */ ++#define SDPCM_TEST_FILL(byteno, id) ((uint8)(id + byteno)) ++ ++/* ++ * Software counters (first part matches hardware counters) ++ */ ++ ++typedef volatile struct { ++ uint32 cmd52rd; /* Cmd52RdCount, SDIO: cmd52 reads */ ++ uint32 cmd52wr; /* Cmd52WrCount, SDIO: cmd52 writes */ ++ uint32 cmd53rd; /* Cmd53RdCount, SDIO: cmd53 reads */ ++ uint32 cmd53wr; /* Cmd53WrCount, SDIO: cmd53 writes */ ++ uint32 abort; /* AbortCount, SDIO: aborts */ ++ uint32 datacrcerror; /* DataCrcErrorCount, SDIO: frames w/CRC error */ ++ uint32 rdoutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Rd Frm out of sync */ ++ uint32 wroutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Wr Frm out of sync */ ++ uint32 writebusy; /* WriteBusyCount, SDIO: device asserted "busy" */ ++ uint32 readwait; /* ReadWaitCount, SDIO: no data ready for a read cmd */ ++ uint32 readterm; /* ReadTermCount, SDIO: read frame termination cmds */ ++ uint32 writeterm; /* WriteTermCount, SDIO: write frames termination cmds */ ++ uint32 rxdescuflo; /* receive descriptor underflows */ ++ uint32 rxfifooflo; /* receive fifo overflows */ ++ uint32 txfifouflo; /* transmit fifo underflows */ ++ uint32 runt; /* runt (too short) frames recv'd from bus */ ++ uint32 badlen; /* frame's rxh len does not match its hw tag len */ ++ uint32 badcksum; /* frame's hw tag chksum doesn't agree with len value */ ++ uint32 seqbreak; /* break in sequence # space from one rx frame to the next */ ++ uint32 rxfcrc; /* frame rx header indicates crc error */ ++ uint32 rxfwoos; /* frame rx header indicates write out of sync */ ++ uint32 rxfwft; /* frame rx header indicates write frame termination */ ++ uint32 rxfabort; /* frame rx header indicates frame aborted */ ++ uint32 woosint; /* write out of sync interrupt */ ++ uint32 roosint; /* read out of sync interrupt */ ++ uint32 rftermint; /* read frame terminate interrupt */ ++ uint32 wftermint; /* write frame terminate interrupt */ ++} sdpcmd_cnt_t; ++ ++/* ++ * Register Access Macros ++ */ ++ ++#define SDIODREV_IS(var, val) ((var) == (val)) ++#define SDIODREV_GE(var, val) ((var) >= (val)) ++#define SDIODREV_GT(var, val) ((var) > (val)) ++#define SDIODREV_LT(var, val) ((var) < (val)) ++#define SDIODREV_LE(var, val) ((var) <= (val)) ++ ++#define SDIODDMAREG32(h, dir, chnl) \ ++ ((dir) == DMA_TX ? \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].xmt) : \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].rcv)) ++ ++#define SDIODDMAREG64(h, dir, chnl) \ ++ ((dir) == DMA_TX ? \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].xmt) : \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].rcv)) ++ ++#define SDIODDMAREG(h, dir, chnl) \ ++ (SDIODREV_LT((h)->corerev, 1) ? \ ++ SDIODDMAREG32((h), (dir), (chnl)) : \ ++ SDIODDMAREG64((h), (dir), (chnl))) ++ ++#define PCMDDMAREG(h, dir, chnl) \ ++ ((dir) == DMA_TX ? \ ++ (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.xmt) : \ ++ (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.rcv)) ++ ++#define SDPCMDMAREG(h, dir, chnl, coreid) \ ++ ((coreid) == SDIOD_CORE_ID ? \ ++ SDIODDMAREG(h, dir, chnl) : \ ++ PCMDDMAREG(h, dir, chnl)) ++ ++#define SDIODFIFOREG(h, corerev) \ ++ (SDIODREV_LT((corerev), 1) ? \ ++ ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod32.dmafifo)) : \ ++ ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod64.dmafifo))) ++ ++#define PCMDFIFOREG(h) \ ++ ((dma32diag_t *)(uintptr)&((h)->regs->dma.pcm32.dmafifo)) ++ ++#define SDPCMFIFOREG(h, coreid, corerev) \ ++ ((coreid) == SDIOD_CORE_ID ? \ ++ SDIODFIFOREG(h, corerev) : \ ++ PCMDFIFOREG(h)) ++ ++/* ++ * Shared structure between dongle and the host. ++ * The structure contains pointers to trap or assert information. ++ */ ++#define SDPCM_SHARED_VERSION 0x0001 ++#define SDPCM_SHARED_VERSION_MASK 0x00FF ++#define SDPCM_SHARED_ASSERT_BUILT 0x0100 ++#define SDPCM_SHARED_ASSERT 0x0200 ++#define SDPCM_SHARED_TRAP 0x0400 ++#define SDPCM_SHARED_IN_BRPT 0x0800 ++#define SDPCM_SHARED_SET_BRPT 0x1000 ++#define SDPCM_SHARED_PENDING_BRPT 0x2000 ++ ++typedef struct { ++ uint32 flags; ++ uint32 trap_addr; ++ uint32 assert_exp_addr; ++ uint32 assert_file_addr; ++ uint32 assert_line; ++ uint32 console_addr; /* Address of hndrte_cons_t */ ++ uint32 msgtrace_addr; ++ uint32 fwid; ++} sdpcm_shared_t; ++ ++extern sdpcm_shared_t sdpcm_shared; ++ ++/* Function can be used to notify host of FW halt */ ++extern void sdpcmd_fwhalt(void); ++ ++#endif /* _bcmsdpcm_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsrom.h b/drivers/bcmdrivers/gmac/src/include/bcmsrom.h +new file mode 100755 +index 0000000..0e6c210 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsrom.h +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc useful routines to access NIC local SROM/OTP . ++ * ++ * $Id: bcmsrom.h 280889 2011-08-31 18:39:27Z $ ++ */ ++ ++#ifndef _bcmsrom_h_ ++#define _bcmsrom_h_ ++ ++#include ++ ++/* Prototypes */ ++extern int srom_var_init(si_t *sih, uint bus, void *curmap, osl_t *osh, ++ char **vars, uint *count); ++extern void srom_var_deinit(si_t *sih); ++ ++extern int srom_read(si_t *sih, uint bus, void *curmap, osl_t *osh, ++ uint byteoff, uint nbytes, uint16 *buf, ++ bool check_crc); ++ ++extern int srom_write(si_t *sih, uint bus, void *curmap, osl_t *osh, ++ uint byteoff, uint nbytes, uint16 *buf); ++ ++extern int srom_otp_cisrwvar(si_t *sih, osl_t *osh, char *vars, int *count); ++#if defined(WLTEST) || defined(BCMDBG) ++extern int srom_otp_write_region_crc(si_t *sih, uint nbytes, uint16* buf16, bool write); ++#endif ++ ++/* parse standard PCMCIA cis, normally used by SB/PCMCIA/SDIO/SPI/OTP ++ * and extract from it into name=value pairs ++ */ ++extern int srom_probe_boardtype(uint8 *pcis[], uint ciscnt); ++extern int srom_parsecis(osl_t *osh, uint8 **pcis, uint ciscnt, ++ char **vars, uint *count); ++ ++#if defined(BCMUSBDEV) ++/* Return sprom size in 16-bit words */ ++extern uint srom_size(si_t *sih, osl_t *osh); ++#endif ++ ++#endif /* _bcmsrom_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsrom_fmt.h b/drivers/bcmdrivers/gmac/src/include/bcmsrom_fmt.h +new file mode 100755 +index 0000000..9f90ed8 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsrom_fmt.h +@@ -0,0 +1,549 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * SROM format definition. ++ * ++ * $Id: bcmsrom_fmt.h 322525 2012-03-21 01:28:39Z $ ++ */ ++ ++#ifndef _bcmsrom_fmt_h_ ++#define _bcmsrom_fmt_h_ ++ ++#define SROM_MAXREV 11 /* max revisiton supported by driver */ ++ ++/* Maximum srom: 6 Kilobits == 768 bytes */ ++#define SROM_MAX 768 ++#define SROM_MAXW 384 ++#define VARS_MAX 4096 ++ ++/* PCI fields */ ++#define PCI_F0DEVID 48 ++ ++ ++#define SROM_WORDS 64 ++ ++#define SROM3_SWRGN_OFF 28 /* s/w region offset in words */ ++ ++#define SROM_SSID 2 ++ ++#define SROM_WL1LHMAXP 29 ++ ++#define SROM_WL1LPAB0 30 ++#define SROM_WL1LPAB1 31 ++#define SROM_WL1LPAB2 32 ++ ++#define SROM_WL1HPAB0 33 ++#define SROM_WL1HPAB1 34 ++#define SROM_WL1HPAB2 35 ++ ++#define SROM_MACHI_IL0 36 ++#define SROM_MACMID_IL0 37 ++#define SROM_MACLO_IL0 38 ++#define SROM_MACHI_ET0 39 ++#define SROM_MACMID_ET0 40 ++#define SROM_MACLO_ET0 41 ++#define SROM_MACHI_ET1 42 ++#define SROM_MACMID_ET1 43 ++#define SROM_MACLO_ET1 44 ++#define SROM3_MACHI 37 ++#define SROM3_MACMID 38 ++#define SROM3_MACLO 39 ++ ++#define SROM_BXARSSI2G 40 ++#define SROM_BXARSSI5G 41 ++ ++#define SROM_TRI52G 42 ++#define SROM_TRI5GHL 43 ++ ++#define SROM_RXPO52G 45 ++ ++#define SROM2_ENETPHY 45 ++ ++#define SROM_AABREV 46 ++/* Fields in AABREV */ ++#define SROM_BR_MASK 0x00ff ++#define SROM_CC_MASK 0x0f00 ++#define SROM_CC_SHIFT 8 ++#define SROM_AA0_MASK 0x3000 ++#define SROM_AA0_SHIFT 12 ++#define SROM_AA1_MASK 0xc000 ++#define SROM_AA1_SHIFT 14 ++ ++#define SROM_WL0PAB0 47 ++#define SROM_WL0PAB1 48 ++#define SROM_WL0PAB2 49 ++ ++#define SROM_LEDBH10 50 ++#define SROM_LEDBH32 51 ++ ++#define SROM_WL10MAXP 52 ++ ++#define SROM_WL1PAB0 53 ++#define SROM_WL1PAB1 54 ++#define SROM_WL1PAB2 55 ++ ++#define SROM_ITT 56 ++ ++#define SROM_BFL 57 ++#define SROM_BFL2 28 ++#define SROM3_BFL2 61 ++ ++#define SROM_AG10 58 ++ ++#define SROM_CCODE 59 ++ ++#define SROM_OPO 60 ++ ++#define SROM3_LEDDC 62 ++ ++#define SROM_CRCREV 63 ++ ++/* SROM Rev 4: Reallocate the software part of the srom to accomodate ++ * MIMO features. It assumes up to two PCIE functions and 440 bytes ++ * of useable srom i.e. the useable storage in chips with OTP that ++ * implements hardware redundancy. ++ */ ++ ++#define SROM4_WORDS 220 ++ ++#define SROM4_SIGN 32 ++#define SROM4_SIGNATURE 0x5372 ++ ++#define SROM4_BREV 33 ++ ++#define SROM4_BFL0 34 ++#define SROM4_BFL1 35 ++#define SROM4_BFL2 36 ++#define SROM4_BFL3 37 ++#define SROM5_BFL0 37 ++#define SROM5_BFL1 38 ++#define SROM5_BFL2 39 ++#define SROM5_BFL3 40 ++ ++#define SROM4_MACHI 38 ++#define SROM4_MACMID 39 ++#define SROM4_MACLO 40 ++#define SROM5_MACHI 41 ++#define SROM5_MACMID 42 ++#define SROM5_MACLO 43 ++ ++#define SROM4_CCODE 41 ++#define SROM4_REGREV 42 ++#define SROM5_CCODE 34 ++#define SROM5_REGREV 35 ++ ++#define SROM4_LEDBH10 43 ++#define SROM4_LEDBH32 44 ++#define SROM5_LEDBH10 59 ++#define SROM5_LEDBH32 60 ++ ++#define SROM4_LEDDC 45 ++#define SROM5_LEDDC 45 ++ ++#define SROM4_AA 46 ++#define SROM4_AA2G_MASK 0x00ff ++#define SROM4_AA2G_SHIFT 0 ++#define SROM4_AA5G_MASK 0xff00 ++#define SROM4_AA5G_SHIFT 8 ++ ++#define SROM4_AG10 47 ++#define SROM4_AG32 48 ++ ++#define SROM4_TXPID2G 49 ++#define SROM4_TXPID5G 51 ++#define SROM4_TXPID5GL 53 ++#define SROM4_TXPID5GH 55 ++ ++#define SROM4_TXRXC 61 ++#define SROM4_TXCHAIN_MASK 0x000f ++#define SROM4_TXCHAIN_SHIFT 0 ++#define SROM4_RXCHAIN_MASK 0x00f0 ++#define SROM4_RXCHAIN_SHIFT 4 ++#define SROM4_SWITCH_MASK 0xff00 ++#define SROM4_SWITCH_SHIFT 8 ++ ++ ++/* Per-path fields */ ++#define MAX_PATH_SROM 4 ++#define SROM4_PATH0 64 ++#define SROM4_PATH1 87 ++#define SROM4_PATH2 110 ++#define SROM4_PATH3 133 ++ ++#define SROM4_2G_ITT_MAXP 0 ++#define SROM4_2G_PA 1 ++#define SROM4_5G_ITT_MAXP 5 ++#define SROM4_5GLH_MAXP 6 ++#define SROM4_5G_PA 7 ++#define SROM4_5GL_PA 11 ++#define SROM4_5GH_PA 15 ++ ++/* Fields in the ITT_MAXP and 5GLH_MAXP words */ ++#define B2G_MAXP_MASK 0xff ++#define B2G_ITT_SHIFT 8 ++#define B5G_MAXP_MASK 0xff ++#define B5G_ITT_SHIFT 8 ++#define B5GH_MAXP_MASK 0xff ++#define B5GL_MAXP_SHIFT 8 ++ ++/* All the miriad power offsets */ ++#define SROM4_2G_CCKPO 156 ++#define SROM4_2G_OFDMPO 157 ++#define SROM4_5G_OFDMPO 159 ++#define SROM4_5GL_OFDMPO 161 ++#define SROM4_5GH_OFDMPO 163 ++#define SROM4_2G_MCSPO 165 ++#define SROM4_5G_MCSPO 173 ++#define SROM4_5GL_MCSPO 181 ++#define SROM4_5GH_MCSPO 189 ++#define SROM4_CDDPO 197 ++#define SROM4_STBCPO 198 ++#define SROM4_BW40PO 199 ++#define SROM4_BWDUPPO 200 ++ ++#define SROM4_CRCREV 219 ++ ++ ++/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6. ++ * This is acombined srom for both MIMO and SISO boards, usable in ++ * the .130 4Kilobit OTP with hardware redundancy. ++ */ ++ ++#define SROM8_SIGN 64 ++ ++#define SROM8_BREV 65 ++ ++#define SROM8_BFL0 66 ++#define SROM8_BFL1 67 ++#define SROM8_BFL2 68 ++#define SROM8_BFL3 69 ++ ++#define SROM8_MACHI 70 ++#define SROM8_MACMID 71 ++#define SROM8_MACLO 72 ++ ++#define SROM8_CCODE 73 ++#define SROM8_REGREV 74 ++ ++#define SROM8_LEDBH10 75 ++#define SROM8_LEDBH32 76 ++ ++#define SROM8_LEDDC 77 ++ ++#define SROM8_AA 78 ++ ++#define SROM8_AG10 79 ++#define SROM8_AG32 80 ++ ++#define SROM8_TXRXC 81 ++ ++#define SROM8_BXARSSI2G 82 ++#define SROM8_BXARSSI5G 83 ++#define SROM8_TRI52G 84 ++#define SROM8_TRI5GHL 85 ++#define SROM8_RXPO52G 86 ++ ++#define SROM8_FEM2G 87 ++#define SROM8_FEM5G 88 ++#define SROM8_FEM_ANTSWLUT_MASK 0xf800 ++#define SROM8_FEM_ANTSWLUT_SHIFT 11 ++#define SROM8_FEM_TR_ISO_MASK 0x0700 ++#define SROM8_FEM_TR_ISO_SHIFT 8 ++#define SROM8_FEM_PDET_RANGE_MASK 0x00f8 ++#define SROM8_FEM_PDET_RANGE_SHIFT 3 ++#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006 ++#define SROM8_FEM_EXTPA_GAIN_SHIFT 1 ++#define SROM8_FEM_TSSIPOS_MASK 0x0001 ++#define SROM8_FEM_TSSIPOS_SHIFT 0 ++ ++#define SROM8_THERMAL 89 ++ ++/* Temp sense related entries */ ++#define SROM8_MPWR_RAWTS 90 ++#define SROM8_TS_SLP_OPT_CORRX 91 ++/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */ ++#define SROM8_FOC_HWIQ_IQSWP 92 ++ ++#define SROM8_EXTLNAGAIN 93 ++ ++/* Temperature delta for PHY calibration */ ++#define SROM8_PHYCAL_TEMPDELTA 94 ++ ++/* Measured power 1 & 2, 0-13 bits at offset 95, MSB 2 bits are unused for now. */ ++#define SROM8_MPWR_1_AND_2 95 ++ ++ ++/* Per-path offsets & fields */ ++#define SROM8_PATH0 96 ++#define SROM8_PATH1 112 ++#define SROM8_PATH2 128 ++#define SROM8_PATH3 144 ++ ++#define SROM8_2G_ITT_MAXP 0 ++#define SROM8_2G_PA 1 ++#define SROM8_5G_ITT_MAXP 4 ++#define SROM8_5GLH_MAXP 5 ++#define SROM8_5G_PA 6 ++#define SROM8_5GL_PA 9 ++#define SROM8_5GH_PA 12 ++ ++/* All the miriad power offsets */ ++#define SROM8_2G_CCKPO 160 ++ ++#define SROM8_2G_OFDMPO 161 ++#define SROM8_5G_OFDMPO 163 ++#define SROM8_5GL_OFDMPO 165 ++#define SROM8_5GH_OFDMPO 167 ++ ++#define SROM8_2G_MCSPO 169 ++#define SROM8_5G_MCSPO 177 ++#define SROM8_5GL_MCSPO 185 ++#define SROM8_5GH_MCSPO 193 ++ ++#define SROM8_CDDPO 201 ++#define SROM8_STBCPO 202 ++#define SROM8_BW40PO 203 ++#define SROM8_BWDUPPO 204 ++ ++/* SISO PA parameters are in the path0 spaces */ ++#define SROM8_SISO 96 ++ ++/* Legacy names for SISO PA paramters */ ++#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP) ++#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA) ++#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1) ++#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2) ++#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP) ++#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP) ++#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA) ++#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1) ++#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2) ++#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA) ++#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1) ++#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2) ++#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA) ++#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1) ++#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2) ++ ++#define SROM8_CRCREV 219 ++ ++/* SROM REV 9 */ ++#define SROM9_2GPO_CCKBW20 160 ++#define SROM9_2GPO_CCKBW20UL 161 ++#define SROM9_2GPO_LOFDMBW20 162 ++#define SROM9_2GPO_LOFDMBW20UL 164 ++ ++#define SROM9_5GLPO_LOFDMBW20 166 ++#define SROM9_5GLPO_LOFDMBW20UL 168 ++#define SROM9_5GMPO_LOFDMBW20 170 ++#define SROM9_5GMPO_LOFDMBW20UL 172 ++#define SROM9_5GHPO_LOFDMBW20 174 ++#define SROM9_5GHPO_LOFDMBW20UL 176 ++ ++#define SROM9_2GPO_MCSBW20 178 ++#define SROM9_2GPO_MCSBW20UL 180 ++#define SROM9_2GPO_MCSBW40 182 ++ ++#define SROM9_5GLPO_MCSBW20 184 ++#define SROM9_5GLPO_MCSBW20UL 186 ++#define SROM9_5GLPO_MCSBW40 188 ++#define SROM9_5GMPO_MCSBW20 190 ++#define SROM9_5GMPO_MCSBW20UL 192 ++#define SROM9_5GMPO_MCSBW40 194 ++#define SROM9_5GHPO_MCSBW20 196 ++#define SROM9_5GHPO_MCSBW20UL 198 ++#define SROM9_5GHPO_MCSBW40 200 ++ ++#define SROM9_PO_MCS32 202 ++#define SROM9_PO_LOFDM40DUP 203 ++#define SROM8_RXGAINERR_2G 205 ++#define SROM8_RXGAINERR_5GL 206 ++#define SROM8_RXGAINERR_5GM 207 ++#define SROM8_RXGAINERR_5GH 208 ++#define SROM8_RXGAINERR_5GU 209 ++#define SROM8_SUBBAND_PPR 210 ++#define SROM8_PCIEINGRESS_WAR 211 ++#define SROM9_SAR 212 ++ ++#define SROM8_NOISELVL_2G 213 ++#define SROM8_NOISELVL_5GL 214 ++#define SROM8_NOISELVL_5GM 215 ++#define SROM8_NOISELVL_5GH 216 ++#define SROM8_NOISELVL_5GU 217 ++ ++#define SROM9_REV_CRC 219 ++ ++#define SROM10_CCKPWROFFSET 218 ++#define SROM10_SIGN 219 ++#define SROM10_SWCTRLMAP_2G 220 ++#define SROM10_CRCREV 229 ++ ++#define SROM10_WORDS 230 ++#define SROM10_SIGNATURE SROM4_SIGNATURE ++ ++ ++/* SROM REV 11 */ ++#define SROM11_BREV 65 ++ ++#define SROM11_BFL0 66 ++#define SROM11_BFL1 67 ++#define SROM11_BFL2 68 ++#define SROM11_BFL3 69 ++#define SROM11_BFL4 70 ++#define SROM11_BFL5 71 ++ ++#define SROM11_MACHI 72 ++#define SROM11_MACMID 73 ++#define SROM11_MACLO 74 ++ ++#define SROM11_CCODE 75 ++#define SROM11_REGREV 76 ++ ++#define SROM11_LEDBH10 77 ++#define SROM11_LEDBH32 78 ++ ++#define SROM11_LEDDC 79 ++ ++#define SROM11_AA 80 ++ ++#define SROM11_AGBG10 81 ++#define SROM11_AGBG2A0 82 ++#define SROM11_AGA21 83 ++ ++#define SROM11_TXRXC 84 ++ ++#define SROM11_FEM_CFG1 85 ++#define SROM11_FEM_CFG2 86 ++ ++#define SROM11_THERMAL 87 ++#define SROM11_MPWR_RAWTS 88 ++#define SROM11_TS_SLP_OPT_CORRX 89 ++#define SROM11_PHYCAL_TEMPDELTA 92 ++#define SROM11_MPWR_1_AND_2 93 ++ ++#define SROM11_PDOFF_40M_A0 101 ++#define SROM11_PDOFF_40M_A1 102 ++#define SROM11_PDOFF_40M_A2 103 ++#define SROM11_PDOFF_80M_A0 104 ++#define SROM11_PDOFF_80M_A1 105 ++#define SROM11_PDOFF_80M_A2 106 ++ ++#define SROM11_SUBBAND5GVER 107 ++ ++/* Per-path fields and offset */ ++#define MAX_PATH_SROM_11 3 ++#define SROM11_PATH0 108 ++#define SROM11_PATH1 128 ++#define SROM11_PATH2 148 ++ ++#define SROM11_2G_MAXP 0 ++#define SROM11_2G_PA 1 ++#define SROM11_RXGAINS1 4 ++#define SROM11_RXGAINS 5 ++#define SROM11_5GB1B0_MAXP 6 ++#define SROM11_5GB3B2_MAXP 7 ++#define SROM11_5GB0_PA 8 ++#define SROM11_5GB1_PA 11 ++#define SROM11_5GB2_PA 14 ++#define SROM11_5GB3_PA 17 ++ ++/* Power per rate */ ++#define SROM11_CCKBW202GPO 168 ++#define SROM11_CCKBW20UL2GPO 169 ++#define SROM11_MCSBW202GPO 170 ++#define SROM11_MCSBW202GPO_1 171 ++#define SROM11_MCSBW402GPO 172 ++#define SROM11_MCSBW402GPO_1 173 ++#define SROM11_DOT11AGOFDMHRBW202GPO 174 ++#define SROM11_OFDMLRBW202GPO 175 ++ ++#define SROM11_MCSBW205GLPO 176 ++#define SROM11_MCSBW205GLPO_1 177 ++#define SROM11_MCSBW405GLPO 178 ++#define SROM11_MCSBW405GLPO_1 179 ++#define SROM11_MCSBW805GLPO 180 ++#define SROM11_MCSBW805GLPO_1 181 ++#define SROM11_MCSBW1605GLPO 182 ++#define SROM11_MCSBW1605GLPO_1 183 ++#define SROM11_MCSBW205GMPO 184 ++#define SROM11_MCSBW205GMPO_1 185 ++#define SROM11_MCSBW405GMPO 186 ++#define SROM11_MCSBW405GMPO_1 187 ++#define SROM11_MCSBW805GMPO 188 ++#define SROM11_MCSBW805GMPO_1 189 ++#define SROM11_MCSBW1605GMPO 190 ++#define SROM11_MCSBW1605GMPO_1 191 ++#define SROM11_MCSBW205GHPO 192 ++#define SROM11_MCSBW205GHPO_1 193 ++#define SROM11_MCSBW405GHPO 194 ++#define SROM11_MCSBW405GHPO_1 195 ++#define SROM11_MCSBW805GHPO 196 ++#define SROM11_MCSBW805GHPO_1 197 ++#define SROM11_MCSBW1605GHPO 198 ++#define SROM11_MCSBW1605GHPO_1 199 ++ ++#define SROM11_MCSLR5GLPO 200 ++#define SROM11_MCSLR5GMPO 201 ++#define SROM11_MCSLR5GHPO 202 ++ ++#define SROM11_SB20IN40HRPO 203 ++#define SROM11_SB20IN80AND160HR5GLPO 204 ++#define SROM11_SB40AND80HR5GLPO 205 ++#define SROM11_SB20IN80AND160HR5GMPO 206 ++#define SROM11_SB40AND80HR5GMPO 207 ++#define SROM11_SB20IN80AND160HR5GHPO 208 ++#define SROM11_SB40AND80HR5GHPO 209 ++#define SROM11_SB20IN40LRPO 210 ++#define SROM11_SB20IN80AND160LR5GLPO 211 ++#define SROM11_SB40AND80LR5GLPO 212 ++#define SROM11_SB20IN80AND160LR5GMPO 213 ++#define SROM11_SB40AND80LR5GMPO 214 ++#define SROM11_SB20IN80AND160LR5GHPO 215 ++#define SROM11_SB40AND80LR5GHPO 216 ++ ++#define SROM11_DOT11AGDUPHRPO 217 ++#define SROM11_DOT11AGDUPLRPO 218 ++ ++/* MISC */ ++#define SROM11_PCIEINGRESS_WAR 220 ++#define SROM11_SAR 221 ++ ++#define SROM11_NOISELVL_2G 222 ++#define SROM11_NOISELVL_5GL 223 ++#define SROM11_NOISELVL_5GM 224 ++#define SROM11_NOISELVL_5GH 225 ++#define SROM11_NOISELVL_5GU 226 ++ ++#define SROM11_RXGAINERR_2G 227 ++#define SROM11_RXGAINERR_5GL 228 ++#define SROM11_RXGAINERR_5GM 229 ++#define SROM11_RXGAINERR_5GH 230 ++#define SROM11_RXGAINERR_5GU 231 ++ ++#define SROM11_SIGN 64 ++#define SROM11_CRCREV 233 ++ ++#define SROM11_WORDS 234 ++#define SROM11_SIGNATURE 0x0634 ++ ++typedef struct { ++ uint8 tssipos; /* TSSI positive slope, 1: positive, 0: negative */ ++ uint8 extpagain; /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */ ++ uint8 pdetrange; /* support 32 combinations of different Pdet dynamic ranges */ ++ uint8 triso; /* TR switch isolation */ ++ uint8 antswctrllut; /* antswctrl lookup table configuration: 32 possible choices */ ++} srom_fem_t; ++ ++#endif /* _bcmsrom_fmt_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsrom_tbl.h b/drivers/bcmdrivers/gmac/src/include/bcmsrom_tbl.h +new file mode 100755 +index 0000000..2190d7e +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsrom_tbl.h +@@ -0,0 +1,878 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Table that encodes the srom formats for PCI/PCIe NICs. ++ * ++ * $Id: bcmsrom_tbl.h 324896 2012-03-30 19:35:36Z $ ++ */ ++ ++#ifndef _bcmsrom_tbl_h_ ++#define _bcmsrom_tbl_h_ ++ ++#include "sbpcmcia.h" ++#include "wlioctl.h" ++ ++typedef struct { ++ const char *name; ++ uint32 revmask; ++ uint32 flags; ++ uint16 off; ++ uint16 mask; ++} sromvar_t; ++ ++#define SRFL_MORE 1 /* value continues as described by the next entry */ ++#define SRFL_NOFFS 2 /* value bits can't be all one's */ ++#define SRFL_PRHEX 4 /* value is in hexdecimal format */ ++#define SRFL_PRSIGN 8 /* value is in signed decimal format */ ++#define SRFL_CCODE 0x10 /* value is in country code format */ ++#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ ++#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ ++#define SRFL_NOVAR 0x80 /* do not generate a nvram param, entry is for mfgc */ ++#define SRFL_ARRAY 0x100 /* value is in an array. All elements EXCEPT FOR THE LAST ++ * ONE in the array should have this flag set. ++ */ ++ ++ ++/* Assumptions: ++ * - Ethernet address spans across 3 consective words ++ * ++ * Table rules: ++ * - Add multiple entries next to each other if a value spans across multiple words ++ * (even multiple fields in the same word) with each entry except the last having ++ * it's SRFL_MORE bit set. ++ * - Ethernet address entry does not follow above rule and must not have SRFL_MORE ++ * bit set. Its SRFL_ETHADDR bit implies it takes multiple words. ++ * - The last entry's name field must be NULL to indicate the end of the table. Other ++ * entries must have non-NULL name. ++ */ ++ ++static const sromvar_t pci_sromvars[] = { ++ {"devid", 0xffffff00, SRFL_PRHEX|SRFL_NOVAR, PCI_F0DEVID, 0xffff}, ++ {"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK}, ++ {"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff}, ++ {"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, ++ {"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff}, ++ {"boardflags", 0x00000004, SRFL_PRHEX|SRFL_MORE, SROM_BFL, 0xffff}, ++ {"", 0, 0, SROM_BFL2, 0xffff}, ++ {"boardflags", 0x00000008, SRFL_PRHEX|SRFL_MORE, SROM_BFL, 0xffff}, ++ {"", 0, 0, SROM3_BFL2, 0xffff}, ++ {"boardflags", 0x00000010, SRFL_PRHEX|SRFL_MORE, SROM4_BFL0, 0xffff}, ++ {"", 0, 0, SROM4_BFL1, 0xffff}, ++ {"boardflags", 0x000000e0, SRFL_PRHEX|SRFL_MORE, SROM5_BFL0, 0xffff}, ++ {"", 0, 0, SROM5_BFL1, 0xffff}, ++ {"boardflags", 0xffffff00, SRFL_PRHEX|SRFL_MORE, SROM8_BFL0, 0xffff}, ++ {"", 0, 0, SROM8_BFL1, 0xffff}, ++ {"boardflags2", 0x00000010, SRFL_PRHEX|SRFL_MORE, SROM4_BFL2, 0xffff}, ++ {"", 0, 0, SROM4_BFL3, 0xffff}, ++ {"boardflags2", 0x000000e0, SRFL_PRHEX|SRFL_MORE, SROM5_BFL2, 0xffff}, ++ {"", 0, 0, SROM5_BFL3, 0xffff}, ++ {"boardflags2", 0xffffff00, SRFL_PRHEX|SRFL_MORE, SROM8_BFL2, 0xffff}, ++ {"", 0, 0, SROM8_BFL3, 0xffff}, ++ {"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, ++ ++ {"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff}, ++ {"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff}, ++ {"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff}, ++ {"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff}, ++ {"boardnum", 0x00000700, 0, SROM8_MACLO, 0xffff}, ++ {"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK}, ++ {"regrev", 0x00000008, 0, SROM_OPO, 0xff00}, ++ {"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff}, ++ {"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff}, ++ {"regrev", 0x00000700, 0, SROM8_REGREV, 0x00ff}, ++ {"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff}, ++ {"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00}, ++ {"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff}, ++ {"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00}, ++ {"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff}, ++ {"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00}, ++ {"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff}, ++ {"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00}, ++ {"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff}, ++ {"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00}, ++ {"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff}, ++ {"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00}, ++ {"ledbh0", 0x00000700, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff}, ++ {"ledbh1", 0x00000700, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, ++ {"ledbh2", 0x00000700, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff}, ++ {"ledbh3", 0x00000700, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, ++ {"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff}, ++ {"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff}, ++ {"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff}, ++ {"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff}, ++ {"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff}, ++ {"pa0b0", 0x00000700, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, ++ {"pa0b1", 0x00000700, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, ++ {"pa0b2", 0x00000700, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, ++ {"pa0itssit", 0x00000700, 0, SROM8_W0_ITTMAXP, 0xff00}, ++ {"pa0maxpwr", 0x00000700, 0, SROM8_W0_ITTMAXP, 0x00ff}, ++ {"opo", 0x0000000c, 0, SROM_OPO, 0x00ff}, ++ {"opo", 0x00000700, 0, SROM8_2G_OFDMPO, 0x00ff}, ++ {"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK}, ++ {"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff}, ++ {"aa2g", 0x00000700, 0, SROM8_AA, 0x00ff}, ++ {"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK}, ++ {"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00}, ++ {"aa5g", 0x00000700, 0, SROM8_AA, 0xff00}, ++ {"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff}, ++ {"ag1", 0x0000000e, 0, SROM_AG10, 0xff00}, ++ {"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff}, ++ {"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00}, ++ {"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff}, ++ {"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00}, ++ {"ag0", 0x00000700, 0, SROM8_AG10, 0x00ff}, ++ {"ag1", 0x00000700, 0, SROM8_AG10, 0xff00}, ++ {"ag2", 0x00000700, 0, SROM8_AG32, 0x00ff}, ++ {"ag3", 0x00000700, 0, SROM8_AG32, 0xff00}, ++ {"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff}, ++ {"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff}, ++ {"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff}, ++ {"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff}, ++ {"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff}, ++ {"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff}, ++ {"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff}, ++ {"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff}, ++ {"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff}, ++ {"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00}, ++ {"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00}, ++ {"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00}, ++ {"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff}, ++ {"pa1b0", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, ++ {"pa1b1", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, ++ {"pa1b2", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, ++ {"pa1lob0", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff}, ++ {"pa1lob1", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff}, ++ {"pa1lob2", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff}, ++ {"pa1hib0", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff}, ++ {"pa1hib1", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff}, ++ {"pa1hib2", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff}, ++ {"pa1itssit", 0x00000700, 0, SROM8_W1_ITTMAXP, 0xff00}, ++ {"pa1maxpwr", 0x00000700, 0, SROM8_W1_ITTMAXP, 0x00ff}, ++ {"pa1lomaxpwr", 0x00000700, 0, SROM8_W1_MAXP_LCHC, 0xff00}, ++ {"pa1himaxpwr", 0x00000700, 0, SROM8_W1_MAXP_LCHC, 0x00ff}, ++ {"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800}, ++ {"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700}, ++ {"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0}, ++ {"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f}, ++ {"bxa2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x1800}, ++ {"rssisav2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x0700}, ++ {"rssismc2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x00f0}, ++ {"rssismf2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x000f}, ++ {"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800}, ++ {"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700}, ++ {"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0}, ++ {"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f}, ++ {"bxa5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x1800}, ++ {"rssisav5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x0700}, ++ {"rssismc5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x00f0}, ++ {"rssismf5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x000f}, ++ {"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff}, ++ {"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00}, ++ {"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff}, ++ {"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00}, ++ {"tri2g", 0x00000700, 0, SROM8_TRI52G, 0x00ff}, ++ {"tri5g", 0x00000700, 0, SROM8_TRI52G, 0xff00}, ++ {"tri5gl", 0x00000700, 0, SROM8_TRI5GHL, 0x00ff}, ++ {"tri5gh", 0x00000700, 0, SROM8_TRI5GHL, 0xff00}, ++ {"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff}, ++ {"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00}, ++ {"rxpo2g", 0x00000700, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff}, ++ {"rxpo5g", 0x00000700, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, ++ {"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK}, ++ {"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK}, ++ {"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK}, ++ {"txchain", 0x00000700, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK}, ++ {"rxchain", 0x00000700, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK}, ++ {"antswitch", 0x00000700, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK}, ++ {"tssipos2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK}, ++ {"extpagain2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK}, ++ {"pdetrange2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK}, ++ {"triso2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK}, ++ {"antswctl2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK}, ++ {"tssipos5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK}, ++ {"extpagain5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK}, ++ {"pdetrange5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK}, ++ {"triso5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK}, ++ {"antswctl5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK}, ++ {"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff}, ++ {"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00}, ++ {"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff}, ++ {"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00}, ++ {"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff}, ++ {"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00}, ++ {"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff}, ++ {"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00}, ++ {"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff}, ++ {"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00}, ++ {"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff}, ++ {"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00}, ++ {"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff}, ++ {"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00}, ++ {"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff}, ++ {"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00}, ++ ++ {"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff}, ++ {"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff}, ++ {"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff}, ++ {"ccode", 0x00000700, SRFL_CCODE, SROM8_CCODE, 0xffff}, ++ {"macaddr", 0x00000700, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, ++ {"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff}, ++ {"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff}, ++ {"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff}, ++ {"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff}, ++ {"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff}, ++ {"leddc", 0x00000700, SRFL_NOFFS|SRFL_LEDDC, SROM8_LEDDC, 0xffff}, ++ {"leddc", 0x000000e0, SRFL_NOFFS|SRFL_LEDDC, SROM5_LEDDC, 0xffff}, ++ {"leddc", 0x00000010, SRFL_NOFFS|SRFL_LEDDC, SROM4_LEDDC, 0xffff}, ++ {"leddc", 0x00000008, SRFL_NOFFS|SRFL_LEDDC, SROM3_LEDDC, 0xffff}, ++ ++ {"tempthresh", 0x00000700, 0, SROM8_THERMAL, 0xff00}, ++ {"tempoffset", 0x00000700, 0, SROM8_THERMAL, 0x00ff}, ++ {"rawtempsense", 0x00000700, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff}, ++ {"measpower", 0x00000700, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00}, ++ {"tempsense_slope", 0x00000700, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x00ff}, ++ {"tempcorrx", 0x00000700, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00}, ++ {"tempsense_option", 0x00000700, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x0300}, ++ {"freqoffset_corr", 0x00000700, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x000f}, ++ {"iqcal_swp_dis", 0x00000700, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010}, ++ {"hw_iqcal_en", 0x00000700, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020}, ++ {"elna2g", 0x00000700, 0, SROM8_EXTLNAGAIN, 0x00ff}, ++ {"elna5g", 0x00000700, 0, SROM8_EXTLNAGAIN, 0xff00}, ++ {"phycal_tempdelta", 0x00000700, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff}, ++ {"temps_period", 0x00000700, 0, SROM8_PHYCAL_TEMPDELTA, 0x0f00}, ++ {"temps_hysteresis", 0x00000700, 0, SROM8_PHYCAL_TEMPDELTA, 0xf000}, ++ {"measpower1", 0x00000700, SRFL_PRHEX, SROM8_MPWR_1_AND_2, 0x007f}, ++ {"measpower2", 0x00000700, SRFL_PRHEX, SROM8_MPWR_1_AND_2, 0x3f80}, ++ ++ {"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff}, ++ {"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff}, ++ {"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM4_2G_OFDMPO + 1, 0xffff}, ++ {"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM4_5G_OFDMPO + 1, 0xffff}, ++ {"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff}, ++ {"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff}, ++ {"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM8_2G_OFDMPO + 1, 0xffff}, ++ {"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM8_5G_OFDMPO + 1, 0xffff}, ++ {"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff}, ++ {"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff}, ++ {"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff}, ++ {"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff}, ++ {"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff}, ++ {"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff}, ++ {"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff}, ++ {"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff}, ++ {"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff}, ++ {"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff}, ++ {"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff}, ++ {"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff}, ++ {"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff}, ++ {"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff}, ++ {"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff}, ++ {"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff}, ++ {"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff}, ++ {"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff}, ++ {"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff}, ++ {"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff}, ++ {"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff}, ++ {"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff}, ++ {"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff}, ++ {"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff}, ++ {"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff}, ++ {"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff}, ++ {"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff}, ++ {"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff}, ++ {"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff}, ++ {"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff}, ++ {"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff}, ++ {"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff}, ++ {"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff}, ++ {"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff}, ++ {"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff}, ++ {"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff}, ++ {"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff}, ++ {"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff}, ++ {"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff}, ++ {"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff}, ++ {"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff}, ++ {"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff}, ++ {"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff}, ++ {"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff}, ++ {"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff}, ++ {"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff}, ++ {"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff}, ++ {"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff}, ++ {"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff}, ++ {"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff}, ++ {"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff}, ++ {"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff}, ++ {"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff}, ++ {"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff}, ++ {"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff}, ++ {"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff}, ++ {"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff}, ++ {"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff}, ++ {"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff}, ++ {"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff}, ++ {"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff}, ++ {"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff}, ++ {"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff}, ++ {"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff}, ++ {"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff}, ++ {"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff}, ++ {"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff}, ++ {"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff}, ++ {"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff}, ++ {"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff}, ++ {"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff}, ++ {"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff}, ++ {"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff}, ++ {"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff}, ++ ++ /* power per rate from sromrev 9 */ ++ {"cckbw202gpo", 0x00000600, 0, SROM9_2GPO_CCKBW20, 0xffff}, ++ {"cckbw20ul2gpo", 0x00000600, 0, SROM9_2GPO_CCKBW20UL, 0xffff}, ++ {"legofdmbw202gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_LOFDMBW20, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff}, ++ {"legofdmbw20ul2gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_LOFDMBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff}, ++ {"legofdmbw205glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_LOFDMBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff}, ++ {"legofdmbw20ul5glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff}, ++ {"legofdmbw205gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_LOFDMBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff}, ++ {"legofdmbw20ul5gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff}, ++ {"legofdmbw205ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_LOFDMBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff}, ++ {"legofdmbw20ul5ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff}, ++ {"mcsbw202gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff}, ++ {"mcsbw20ul2gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff}, ++ {"mcsbw402gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff}, ++ {"mcsbw205glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff}, ++ {"mcsbw20ul5glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_MCSBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff}, ++ {"mcsbw405glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff}, ++ {"mcsbw205gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff}, ++ {"mcsbw20ul5gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_MCSBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff}, ++ {"mcsbw405gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff}, ++ {"mcsbw205ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff}, ++ {"mcsbw20ul5ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_MCSBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff}, ++ {"mcsbw405ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff}, ++ {"mcs32po", 0x00000600, 0, SROM9_PO_MCS32, 0xffff}, ++ {"legofdm40duppo", 0x00000600, 0, SROM9_PO_LOFDM40DUP, 0xffff}, ++ {"pcieingress_war", 0x00000700, 0, SROM8_PCIEINGRESS_WAR, 0xf}, ++ {"rxgainerr2ga0", 0x00000700, 0, SROM8_RXGAINERR_2G, 0x003f}, ++ {"rxgainerr2ga1", 0x00000700, 0, SROM8_RXGAINERR_2G, 0x07c0}, ++ {"rxgainerr2ga2", 0x00000700, 0, SROM8_RXGAINERR_2G, 0xf800}, ++ {"rxgainerr5gla0", 0x00000700, 0, SROM8_RXGAINERR_5GL, 0x003f}, ++ {"rxgainerr5gla1", 0x00000700, 0, SROM8_RXGAINERR_5GL, 0x07c0}, ++ {"rxgainerr5gla2", 0x00000700, 0, SROM8_RXGAINERR_5GL, 0xf800}, ++ {"rxgainerr5gma0", 0x00000700, 0, SROM8_RXGAINERR_5GM, 0x003f}, ++ {"rxgainerr5gma1", 0x00000700, 0, SROM8_RXGAINERR_5GM, 0x07c0}, ++ {"rxgainerr5gma2", 0x00000700, 0, SROM8_RXGAINERR_5GM, 0xf800}, ++ {"rxgainerr5gha0", 0x00000700, 0, SROM8_RXGAINERR_5GH, 0x003f}, ++ {"rxgainerr5gha1", 0x00000700, 0, SROM8_RXGAINERR_5GH, 0x07c0}, ++ {"rxgainerr5gha2", 0x00000700, 0, SROM8_RXGAINERR_5GH, 0xf800}, ++ {"rxgainerr5gua0", 0x00000700, 0, SROM8_RXGAINERR_5GU, 0x003f}, ++ {"rxgainerr5gua1", 0x00000700, 0, SROM8_RXGAINERR_5GU, 0x07c0}, ++ {"rxgainerr5gua2", 0x00000700, 0, SROM8_RXGAINERR_5GU, 0xf800}, ++ {"sar2g", 0x00000600, 0, SROM9_SAR, 0x00ff}, ++ {"sar5g", 0x00000600, 0, SROM9_SAR, 0xff00}, ++ {"noiselvl2ga0", 0x00000700, 0, SROM8_NOISELVL_2G, 0x001f}, ++ {"noiselvl2ga1", 0x00000700, 0, SROM8_NOISELVL_2G, 0x03e0}, ++ {"noiselvl2ga2", 0x00000700, 0, SROM8_NOISELVL_2G, 0x7c00}, ++ {"noiselvl5gla0", 0x00000700, 0, SROM8_NOISELVL_5GL, 0x001f}, ++ {"noiselvl5gla1", 0x00000700, 0, SROM8_NOISELVL_5GL, 0x03e0}, ++ {"noiselvl5gla2", 0x00000700, 0, SROM8_NOISELVL_5GL, 0x7c00}, ++ {"noiselvl5gma0", 0x00000700, 0, SROM8_NOISELVL_5GM, 0x001f}, ++ {"noiselvl5gma1", 0x00000700, 0, SROM8_NOISELVL_5GM, 0x03e0}, ++ {"noiselvl5gma2", 0x00000700, 0, SROM8_NOISELVL_5GM, 0x7c00}, ++ {"noiselvl5gha0", 0x00000700, 0, SROM8_NOISELVL_5GH, 0x001f}, ++ {"noiselvl5gha1", 0x00000700, 0, SROM8_NOISELVL_5GH, 0x03e0}, ++ {"noiselvl5gha2", 0x00000700, 0, SROM8_NOISELVL_5GH, 0x7c00}, ++ {"noiselvl5gua0", 0x00000700, 0, SROM8_NOISELVL_5GU, 0x001f}, ++ {"noiselvl5gua1", 0x00000700, 0, SROM8_NOISELVL_5GU, 0x03e0}, ++ {"noiselvl5gua2", 0x00000700, 0, SROM8_NOISELVL_5GU, 0x7c00}, ++ {"subband5gver", 0x00000700, 0, SROM8_SUBBAND_PPR, 0x7}, ++ ++ {"cckPwrOffset", 0x00000400, 0, SROM10_CCKPWROFFSET, 0xffff}, ++ /* swctrlmap_2g array, note that the last element doesn't have SRFL_ARRAY flag set */ ++ {"swctrlmap_2g", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G, 0xffff}, ++ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 1, 0xffff}, ++ {"", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 2, 0xffff}, ++ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 3, 0xffff}, ++ {"", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 4, 0xffff}, ++ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 5, 0xffff}, ++ {"", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 6, 0xffff}, ++ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 7, 0xffff}, ++ {"", 0x00000400, SRFL_PRHEX, SROM10_SWCTRLMAP_2G + 8, 0xffff}, ++ ++ /* sromrev 11 */ ++ {"boardflags3", 0xfffff800, SRFL_PRHEX|SRFL_MORE, SROM11_BFL3, 0xffff}, ++ {"", 0, 0, SROM11_BFL3, 0xffff}, ++ {"boardnum", 0xfffff800, 0, SROM11_MACLO, 0xffff}, ++ {"macaddr", 0xfffff800, SRFL_ETHADDR, SROM11_MACHI, 0xffff}, ++ {"ccode", 0xfffff800, SRFL_CCODE, SROM11_CCODE, 0xffff}, ++ {"regrev", 0xfffff800, 0, SROM11_REGREV, 0x00ff}, ++ {"ledbh0", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH10, 0x00ff}, ++ {"ledbh1", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH10, 0xff00}, ++ {"ledbh2", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH32, 0x00ff}, ++ {"ledbh3", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH32, 0xff00}, ++ {"leddc", 0xfffff800, SRFL_NOFFS|SRFL_LEDDC, SROM11_LEDDC, 0xffff}, ++ {"aa2g", 0xfffff800, 0, SROM11_AA, 0x00ff}, ++ {"aa5g", 0xfffff800, 0, SROM11_AA, 0xff00}, ++ {"agbg0", 0xfffff800, 0, SROM11_AGBG10, 0x00ff}, ++ {"agbg1", 0xfffff800, 0, SROM11_AGBG10, 0xff00}, ++ {"agbg2", 0xfffff800, 0, SROM11_AGBG2A0, 0x00ff}, ++ {"aga0", 0xfffff800, 0, SROM11_AGBG2A0, 0xff00}, ++ {"aga1", 0xfffff800, 0, SROM11_AGA21, 0x00ff}, ++ {"aga2", 0xfffff800, 0, SROM11_AGA21, 0xff00}, ++ {"txchain", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_TXCHAIN_MASK}, ++ {"rxchain", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_RXCHAIN_MASK}, ++ {"antswitch", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_SWITCH_MASK}, ++ ++ {"tssiposslope2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x0001}, ++ {"epagain2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x000e}, ++ {"pdgain2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x01f0}, ++ {"tworangetssi2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x0200}, ++ {"papdcap2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x0400}, ++ {"femctrl", 0xfffff800, 0, SROM11_FEM_CFG1, 0xf800}, ++ ++ {"tssiposslope5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x0001}, ++ {"epagain5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x000e}, ++ {"pdgain5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x01f0}, ++ {"tworangetssi5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x0200}, ++ {"papdcap5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x0400}, ++ {"gainctrlsph", 0xfffff800, 0, SROM11_FEM_CFG2, 0xf800}, ++ ++ {"tempthresh", 0xfffff800, 0, SROM11_THERMAL, 0xff00}, ++ {"tempoffset", 0xfffff800, 0, SROM11_THERMAL, 0x00ff}, ++ {"rawtempsense", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_RAWTS, 0x01ff}, ++ {"measpower", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_RAWTS, 0xfe00}, ++ {"tempsense_slope", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0x00ff}, ++ {"tempcorrx", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0xfc00}, ++ {"tempsense_option", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0x0300}, ++ {"phycal_tempdelta", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0x00ff}, ++ {"temps_period", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0x0f00}, ++ {"temps_hysteresis", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0xf000}, ++ {"measpower1", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_1_AND_2, 0x007f}, ++ {"measpower2", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_1_AND_2, 0x3f80}, ++ {"pdoffset40ma0", 0xfffff800, 0, SROM11_PDOFF_40M_A0, 0xffff}, ++ {"pdoffset40ma1", 0xfffff800, 0, SROM11_PDOFF_40M_A1, 0xffff}, ++ {"pdoffset40ma2", 0xfffff800, 0, SROM11_PDOFF_40M_A2, 0xffff}, ++ {"pdoffset80ma0", 0xfffff800, 0, SROM11_PDOFF_80M_A0, 0xffff}, ++ {"pdoffset80ma1", 0xfffff800, 0, SROM11_PDOFF_80M_A1, 0xffff}, ++ {"pdoffset80ma2", 0xfffff800, 0, SROM11_PDOFF_80M_A2, 0xffff}, ++ ++ {"subband5gver", 0xfffff800, SRFL_PRHEX, SROM11_SUBBAND5GVER, 0xffff}, ++ ++ /* power per rate */ ++ {"cckbw202gpo", 0xfffff800, 0, SROM11_CCKBW202GPO, 0xffff}, ++ {"cckbw20ul2gpo", 0xfffff800, 0, SROM11_CCKBW20UL2GPO, 0xffff}, ++ {"mcsbw202gpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW202GPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW202GPO_1, 0xffff}, ++ {"mcsbw402gpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW402GPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW402GPO_1, 0xffff}, ++ {"dot11agofdmhrbw202gpo", 0xfffff800, 0, SROM11_DOT11AGOFDMHRBW202GPO, 0xffff}, ++ {"ofdmlrbw202gpo", 0xfffff800, 0, SROM11_OFDMLRBW202GPO, 0xffff}, ++ {"mcsbw205glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GLPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW205GLPO_1, 0xffff}, ++ {"mcsbw405glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GLPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW405GLPO_1, 0xffff}, ++ {"mcsbw805glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GLPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW805GLPO_1, 0xffff}, ++ {"mcsbw1605glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW1605GLPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW1605GLPO_1, 0xffff}, ++ {"mcsbw205gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GMPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW205GMPO_1, 0xffff}, ++ {"mcsbw405gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GMPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW405GMPO_1, 0xffff}, ++ {"mcsbw805gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GMPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW805GMPO_1, 0xffff}, ++ {"mcsbw1605gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW1605GMPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW1605GMPO_1, 0xffff}, ++ {"mcsbw205ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GHPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW205GHPO_1, 0xffff}, ++ {"mcsbw405ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GHPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW405GHPO_1, 0xffff}, ++ {"mcsbw805ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GHPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW805GHPO_1, 0xffff}, ++ {"mcsbw1605ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW1605GHPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW1605GHPO_1, 0xffff}, ++ {"mcslr5glpo", 0xfffff800, 0, SROM11_MCSLR5GLPO, 0xffff}, ++ {"mcslr5gmpo", 0xfffff800, 0, SROM11_MCSLR5GMPO, 0xffff}, ++ {"mcslr5ghpo", 0xfffff800, 0, SROM11_MCSLR5GHPO, 0xffff}, ++ {"sb20in40hrrpo", 0xfffff800, 0, SROM11_SB20IN40HRPO, 0xffff}, ++ {"sb20in80and160hr5glpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GLPO, 0xffff}, ++ {"sb40and80hr5glpo", 0xfffff800, 0, SROM11_SB40AND80HR5GLPO, 0xffff}, ++ {"sb20in80and160hr5gmpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GMPO, 0xffff}, ++ {"sb40and80hr5gmpo", 0xfffff800, 0, SROM11_SB40AND80HR5GMPO, 0xffff}, ++ {"sb20in80and160hr5ghpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GHPO, 0xffff}, ++ {"sb40and80hr5ghpo", 0xfffff800, 0, SROM11_SB40AND80HR5GHPO, 0xffff}, ++ {"sb20in40lrpo", 0xfffff800, 0, SROM11_SB20IN40LRPO, 0xffff}, ++ {"sb20in80and160lr5glpo", 0xfffff800, 0, SROM11_SB20IN80AND160LR5GLPO, 0xffff}, ++ {"sb40and80lr5glpo", 0xfffff800, 0, SROM11_SB40AND80LR5GLPO, 0xffff}, ++ {"sb20in80and160lr5gmpo", 0xfffff800, 0, SROM11_SB20IN80AND160LR5GMPO, 0xffff}, ++ {"sb40and80lr5gmpo", 0xfffff800, 0, SROM11_SB40AND80LR5GMPO, 0xffff}, ++ {"sb20in80and160lr5ghpo", 0xfffff800, 0, SROM11_SB20IN80AND160LR5GHPO, 0xffff}, ++ {"sb40and80lr5ghpo", 0xfffff800, 0, SROM11_SB40AND80LR5GHPO, 0xffff}, ++ {"dot11agduphrpo", 0xfffff800, 0, SROM11_DOT11AGDUPHRPO, 0xffff}, ++ {"dot11agduplrpo", 0xfffff800, 0, SROM11_DOT11AGDUPLRPO, 0xffff}, ++ ++ /* Misc */ ++ {"pcieingress_war", 0xfffff800, 0, SROM11_PCIEINGRESS_WAR, 0xf}, ++ {"sar2g", 0xfffff800, 0, SROM11_SAR, 0x00ff}, ++ {"sar5g", 0xfffff800, 0, SROM11_SAR, 0xff00}, ++ {"noiselvl2ga0", 0xfffff800, 0, SROM11_NOISELVL_2G, 0x001f}, ++ {"noiselvl2ga1", 0xfffff800, 0, SROM11_NOISELVL_2G, 0x03e0}, ++ {"noiselvl2ga2", 0xfffff800, 0, SROM11_NOISELVL_2G, 0x7c00}, ++ {"noiselvl5gla0", 0xfffff800, 0, SROM11_NOISELVL_5GL, 0x001f}, ++ {"noiselvl5gla1", 0xfffff800, 0, SROM11_NOISELVL_5GL, 0x03e0}, ++ {"noiselvl5gla2", 0xfffff800, 0, SROM11_NOISELVL_5GL, 0x7c00}, ++ {"noiselvl5gma0", 0xfffff800, 0, SROM11_NOISELVL_5GM, 0x001f}, ++ {"noiselvl5gma1", 0xfffff800, 0, SROM11_NOISELVL_5GM, 0x03e0}, ++ {"noiselvl5gma2", 0xfffff800, 0, SROM11_NOISELVL_5GM, 0x7c00}, ++ {"noiselvl5gha0", 0xfffff800, 0, SROM11_NOISELVL_5GH, 0x001f}, ++ {"noiselvl5gha1", 0xfffff800, 0, SROM11_NOISELVL_5GH, 0x03e0}, ++ {"noiselvl5gha2", 0xfffff800, 0, SROM11_NOISELVL_5GH, 0x7c00}, ++ {"noiselvl5gua0", 0xfffff800, 0, SROM11_NOISELVL_5GU, 0x001f}, ++ {"noiselvl5gua1", 0xfffff800, 0, SROM11_NOISELVL_5GU, 0x03e0}, ++ {"noiselvl5gua2", 0xfffff800, 0, SROM11_NOISELVL_5GU, 0x7c00}, ++ {"rxgainerr2g", 0xfffff800, SRFL_PRHEX, SROM11_RXGAINERR_2G, 0xffff}, ++ {"rxgainerr5g", 0xfffff800, SRFL_PRHEX|SRFL_ARRAY, SROM11_RXGAINERR_5GL, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX|SRFL_ARRAY, SROM11_RXGAINERR_5GM, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX|SRFL_ARRAY, SROM11_RXGAINERR_5GH, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX, SROM11_RXGAINERR_5GU, 0xffff}, ++ {NULL, 0, 0, 0, 0} ++}; ++ ++static const sromvar_t perpath_pci_sromvars[] = { ++ {"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff}, ++ {"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00}, ++ {"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00}, ++ {"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff}, ++ {"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff}, ++ {"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff}, ++ {"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff}, ++ {"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff}, ++ {"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff}, ++ {"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00}, ++ {"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff}, ++ {"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff}, ++ {"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff}, ++ {"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff}, ++ {"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff}, ++ {"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, 0xffff}, ++ {"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, 0xffff}, ++ {"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, 0xffff}, ++ {"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff}, ++ {"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, 0xffff}, ++ {"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, 0xffff}, ++ {"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, 0xffff}, ++ {"maxp2ga", 0x00000700, 0, SROM8_2G_ITT_MAXP, 0x00ff}, ++ {"itt2ga", 0x00000700, 0, SROM8_2G_ITT_MAXP, 0xff00}, ++ {"itt5ga", 0x00000700, 0, SROM8_5G_ITT_MAXP, 0xff00}, ++ {"pa2gw0a", 0x00000700, SRFL_PRHEX, SROM8_2G_PA, 0xffff}, ++ {"pa2gw1a", 0x00000700, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff}, ++ {"pa2gw2a", 0x00000700, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff}, ++ {"maxp5ga", 0x00000700, 0, SROM8_5G_ITT_MAXP, 0x00ff}, ++ {"maxp5gha", 0x00000700, 0, SROM8_5GLH_MAXP, 0x00ff}, ++ {"maxp5gla", 0x00000700, 0, SROM8_5GLH_MAXP, 0xff00}, ++ {"pa5gw0a", 0x00000700, SRFL_PRHEX, SROM8_5G_PA, 0xffff}, ++ {"pa5gw1a", 0x00000700, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff}, ++ {"pa5gw2a", 0x00000700, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff}, ++ {"pa5glw0a", 0x00000700, SRFL_PRHEX, SROM8_5GL_PA, 0xffff}, ++ {"pa5glw1a", 0x00000700, SRFL_PRHEX, SROM8_5GL_PA + 1, 0xffff}, ++ {"pa5glw2a", 0x00000700, SRFL_PRHEX, SROM8_5GL_PA + 2, 0xffff}, ++ {"pa5ghw0a", 0x00000700, SRFL_PRHEX, SROM8_5GH_PA, 0xffff}, ++ {"pa5ghw1a", 0x00000700, SRFL_PRHEX, SROM8_5GH_PA + 1, 0xffff}, ++ {"pa5ghw2a", 0x00000700, SRFL_PRHEX, SROM8_5GH_PA + 2, 0xffff}, ++ ++ /* sromrev 11 */ ++ {"maxp2ga", 0xfffff800, 0, SROM11_2G_MAXP, 0x00ff}, ++ {"pa2ga", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX, SROM11_2G_PA + 2, 0xffff}, ++ {"rxgains5gmelnagaina", 0xfffff800, 0, SROM11_RXGAINS1, 0x0007}, ++ {"rxgains5gmtrisoa", 0xfffff800, 0, SROM11_RXGAINS1, 0x0078}, ++ {"rxgains5gmtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS1, 0x0080}, ++ {"rxgains5ghelnagaina", 0xfffff800, 0, SROM11_RXGAINS1, 0x0700}, ++ {"rxgains5ghtrisoa", 0xfffff800, 0, SROM11_RXGAINS1, 0x7800}, ++ {"rxgains5ghtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS1, 0x8000}, ++ {"rxgains2gelnagaina", 0xfffff800, 0, SROM11_RXGAINS, 0x0007}, ++ {"rxgains2gtrisoa", 0xfffff800, 0, SROM11_RXGAINS, 0x0078}, ++ {"rxgains2gtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS, 0x0080}, ++ {"rxgains5gelnagaina", 0xfffff800, 0, SROM11_RXGAINS, 0x0700}, ++ {"rxgains5gtrisoa", 0xfffff800, 0, SROM11_RXGAINS, 0x7800}, ++ {"rxgains5gtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS, 0x8000}, ++ {"maxp5ga", 0xfffff800, SRFL_ARRAY, SROM11_5GB1B0_MAXP, 0x00ff}, ++ {"", 0xfffff800, SRFL_ARRAY, SROM11_5GB1B0_MAXP, 0xff00}, ++ {"", 0xfffff800, SRFL_ARRAY, SROM11_5GB3B2_MAXP, 0x00ff}, ++ {"", 0xfffff800, 0, SROM11_5GB3B2_MAXP, 0xff00}, ++ {"pa5ga", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 2, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 2, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 2, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX, SROM11_5GB3_PA + 2, 0xffff}, ++ ++ {NULL, 0, 0, 0, 0} ++}; ++ ++#if !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) ++#define PHY_TYPE_HT 7 /* HT-Phy value */ ++#define PHY_TYPE_N 4 /* N-Phy value */ ++#define PHY_TYPE_LP 5 /* LP-Phy value */ ++#endif /* !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) */ ++#if !defined(PHY_TYPE_AC) ++#define PHY_TYPE_AC 11 /* AC-Phy value */ ++#endif /* !defined(PHY_TYPE_AC) */ ++#if !defined(PHY_TYPE_NULL) ++#define PHY_TYPE_NULL 0xf /* Invalid Phy value */ ++#endif /* !defined(PHY_TYPE_NULL) */ ++ ++typedef struct { ++ uint16 phy_type; ++ uint16 bandrange; ++ uint16 chain; ++ const char *vars; ++} pavars_t; ++ ++static const pavars_t pavars[] = { ++ /* HTPHY */ ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G, 2, "pa2gw0a2 pa2gw1a2 pa2gw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GL, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GL, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GL, 2, "pa5glw0a2 pa5glw1a2 pa5glw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GM, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GM, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GM, 2, "pa5gw0a2 pa5gw1a2 pa5gw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"}, ++ /* HTPHY PPR_SUBBAND */ ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 0, "pa5gllw0a0 pa5gllw1a0 pa5gllw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 1, "pa5gllw0a1 pa5gllw1a1 pa5gllw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 2, "pa5gllw0a2 pa5gllw1a2 pa5gllw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 0, "pa5glhw0a0 pa5glhw1a0 pa5glhw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 1, "pa5glhw0a1 pa5glhw1a1 pa5glhw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 2, "pa5glhw0a2 pa5glhw1a2 pa5glhw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_5BAND, 0, "pa5gmlw0a0 pa5gmlw1a0 pa5gmlw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_5BAND, 1, "pa5gmlw0a1 pa5gmlw1a1 pa5gmlw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_5BAND, 2, "pa5gmlw0a2 pa5gmlw1a2 pa5gmlw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 0, "pa5gmhw0a0 pa5gmhw1a0 pa5gmhw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 1, "pa5gmhw0a1 pa5gmhw1a1 pa5gmhw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 2, "pa5gmhw0a2 pa5gmhw1a2 pa5gmhw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_5BAND, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_5BAND, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_5BAND, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"}, ++ /* NPHY */ ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, ++ /* LPPHY */ ++ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_2G, 0, "pa0b0 pa0b1 pa0b2"}, ++ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GL, 0, "pa1lob0 pa1lob1 pa1lob2"}, ++ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GM, 0, "pa1b0 pa1b1 pa1b2"}, ++ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GH, 0, "pa1hib0 pa1hib1 pa1hib2"}, ++ /* ACPHY */ ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 0, "pa2ga0"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 1, "pa2ga1"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 2, "pa2ga2"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 0, "pa5ga0"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 1, "pa5ga1"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 2, "pa5ga2"}, ++ {PHY_TYPE_NULL, 0, 0, ""} ++}; ++ ++typedef struct { ++ uint16 phy_type; ++ uint16 bandrange; ++ const char *vars; ++} povars_t; ++ ++static const povars_t povars[] = { ++ /* NPHY */ ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, "mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 " ++ "mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, "mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 " ++ "mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, "mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 " ++ "mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, "mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 " ++ "mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"}, ++ {PHY_TYPE_NULL, 0, ""} ++}; ++ ++typedef struct { ++ uint8 tag; /* Broadcom subtag name */ ++ uint32 revmask; /* Supported cis_sromrev */ ++ uint8 len; /* Length field of the tuple, note that it includes the ++ * subtag name (1 byte): 1 + tuple content length ++ */ ++ const char *params; ++} cis_tuple_t; ++ ++#define OTP_RAW (0xff - 1) /* Reserved tuple number for wrvar Raw input */ ++#define OTP_VERS_1 (0xff - 2) /* CISTPL_VERS_1 */ ++#define OTP_MANFID (0xff - 3) /* CISTPL_MANFID */ ++#define OTP_RAW1 (0xff - 4) /* Like RAW, but comes first */ ++ ++static const cis_tuple_t cis_hnbuvars[] = { ++ {OTP_RAW1, 0xffffffff, 0, ""}, /* special case */ ++ {OTP_VERS_1, 0xffffffff, 0, "smanf sproductname"}, /* special case (non BRCM tuple) */ ++ {OTP_MANFID, 0xffffffff, 4, "2manfid 2prodid"}, /* special case (non BRCM tuple) */ ++ /* Unified OTP: tupple to embed USB manfid inside SDIO CIS */ ++ {HNBU_UMANFID, 0xffffffff, 8, "8usbmanfid"}, ++ {HNBU_SROMREV, 0xffffffff, 2, "1sromrev"}, ++ /* NOTE: subdevid is also written to boardtype. ++ * Need to write HNBU_BOARDTYPE to change it if it is different. ++ */ ++ {HNBU_CHIPID, 0xffffffff, 11, "2vendid 2devid 2chiprev 2subvendid 2subdevid"}, ++ {HNBU_BOARDREV, 0xffffffff, 3, "2boardrev"}, ++ {HNBU_PAPARMS, 0xffffffff, 10, "2pa0b0 2pa0b1 2pa0b2 1pa0itssit 1pa0maxpwr 1opo"}, ++ {HNBU_AA, 0xffffffff, 3, "1aa2g 1aa5g"}, ++ {HNBU_AA, 0xffffffff, 3, "1aa0 1aa1"}, /* backward compatibility */ ++ {HNBU_AG, 0xffffffff, 5, "1ag0 1ag1 1ag2 1ag3"}, ++ {HNBU_BOARDFLAGS, 0xffffffff, 13, "4boardflags 4boardflags2 4boardflags3"}, ++ {HNBU_LEDS, 0xffffffff, 5, "1ledbh0 1ledbh1 1ledbh2 1ledbh3"}, ++ {HNBU_CCODE, 0xffffffff, 4, "2ccode 1cctl"}, ++ {HNBU_CCKPO, 0xffffffff, 3, "2cckpo"}, ++ {HNBU_OFDMPO, 0xffffffff, 5, "4ofdmpo"}, ++ {HNBU_PAPARMS5G, 0xffffffff, 23, "2pa1b0 2pa1b1 2pa1b2 2pa1lob0 2pa1lob1 2pa1lob2 " ++ "2pa1hib0 2pa1hib1 2pa1hib2 1pa1itssit " ++ "1pa1maxpwr 1pa1lomaxpwr 1pa1himaxpwr"}, ++ {HNBU_RDLID, 0xffffffff, 3, "2rdlid"}, ++ {HNBU_RSSISMBXA2G, 0xffffffff, 3, "0rssismf2g 0rssismc2g " ++ "0rssisav2g 0bxa2g"}, /* special case */ ++ {HNBU_RSSISMBXA5G, 0xffffffff, 3, "0rssismf5g 0rssismc5g " ++ "0rssisav5g 0bxa5g"}, /* special case */ ++ {HNBU_XTALFREQ, 0xffffffff, 5, "4xtalfreq"}, ++ {HNBU_TRI2G, 0xffffffff, 2, "1tri2g"}, ++ {HNBU_TRI5G, 0xffffffff, 4, "1tri5gl 1tri5g 1tri5gh"}, ++ {HNBU_RXPO2G, 0xffffffff, 2, "1rxpo2g"}, ++ {HNBU_RXPO5G, 0xffffffff, 2, "1rxpo5g"}, ++ {HNBU_BOARDNUM, 0xffffffff, 3, "2boardnum"}, ++ {HNBU_MACADDR, 0xffffffff, 7, "6macaddr"}, /* special case */ ++ {HNBU_RDLSN, 0xffffffff, 3, "2rdlsn"}, ++ {HNBU_BOARDTYPE, 0xffffffff, 3, "2boardtype"}, ++ {HNBU_LEDDC, 0xffffffff, 3, "2leddc"}, ++ {HNBU_RDLRNDIS, 0xffffffff, 2, "1rdlndis"}, ++ {HNBU_CHAINSWITCH, 0xffffffff, 5, "1txchain 1rxchain 2antswitch"}, ++ {HNBU_REGREV, 0xffffffff, 2, "1regrev"}, ++ {HNBU_FEM, 0x000007fe, 5, "0antswctl2g 0triso2g 0pdetrange2g 0extpagain2g " ++ "0tssipos2g 0antswctl5g 0triso5g 0pdetrange5g 0extpagain5g 0tssipos5g"}, /* special case */ ++ {HNBU_PAPARMS_C0, 0x000007fe, 31, "1maxp2ga0 1itt2ga0 2pa2gw0a0 2pa2gw1a0 " ++ "2pa2gw2a0 1maxp5ga0 1itt5ga0 1maxp5gha0 1maxp5gla0 2pa5gw0a0 2pa5gw1a0 2pa5gw2a0 " ++ "2pa5glw0a0 2pa5glw1a0 2pa5glw2a0 2pa5ghw0a0 2pa5ghw1a0 2pa5ghw2a0"}, ++ {HNBU_PAPARMS_C1, 0x000007fe, 31, "1maxp2ga1 1itt2ga1 2pa2gw0a1 2pa2gw1a1 " ++ "2pa2gw2a1 1maxp5ga1 1itt5ga1 1maxp5gha1 1maxp5gla1 2pa5gw0a1 2pa5gw1a1 2pa5gw2a1 " ++ "2pa5glw0a1 2pa5glw1a1 2pa5glw2a1 2pa5ghw0a1 2pa5ghw1a1 2pa5ghw2a1"}, ++ {HNBU_PO_CCKOFDM, 0xffffffff, 19, "2cck2gpo 4ofdm2gpo 4ofdm5gpo 4ofdm5glpo " ++ "4ofdm5ghpo"}, ++ {HNBU_PO_MCS2G, 0xffffffff, 17, "2mcs2gpo0 2mcs2gpo1 2mcs2gpo2 2mcs2gpo3 " ++ "2mcs2gpo4 2mcs2gpo5 2mcs2gpo6 2mcs2gpo7"}, ++ {HNBU_PO_MCS5GM, 0xffffffff, 17, "2mcs5gpo0 2mcs5gpo1 2mcs5gpo2 2mcs5gpo3 " ++ "2mcs5gpo4 2mcs5gpo5 2mcs5gpo6 2mcs5gpo7"}, ++ {HNBU_PO_MCS5GLH, 0xffffffff, 33, "2mcs5glpo0 2mcs5glpo1 2mcs5glpo2 2mcs5glpo3 " ++ "2mcs5glpo4 2mcs5glpo5 2mcs5glpo6 2mcs5glpo7 " ++ "2mcs5ghpo0 2mcs5ghpo1 2mcs5ghpo2 2mcs5ghpo3 " ++ "2mcs5ghpo4 2mcs5ghpo5 2mcs5ghpo6 2mcs5ghpo7"}, ++ {HNBU_CCKFILTTYPE, 0xffffffff, 2, "1cckdigfilttype"}, ++ {HNBU_PO_CDD, 0xffffffff, 3, "2cddpo"}, ++ {HNBU_PO_STBC, 0xffffffff, 3, "2stbcpo"}, ++ {HNBU_PO_40M, 0xffffffff, 3, "2bw40po"}, ++ {HNBU_PO_40MDUP, 0xffffffff, 3, "2bwduppo"}, ++ {HNBU_RDLRWU, 0xffffffff, 2, "1rdlrwu"}, ++ {HNBU_WPS, 0xffffffff, 3, "1wpsgpio 1wpsled"}, ++ {HNBU_USBFS, 0xffffffff, 2, "1usbfs"}, ++ {HNBU_ELNA2G, 0xffffffff, 2, "1elna2g"}, ++ {HNBU_ELNA5G, 0xffffffff, 2, "1elna5g"}, ++ {HNBU_CUSTOM1, 0xffffffff, 5, "4customvar1"}, ++ {OTP_RAW, 0xffffffff, 0, ""}, /* special case */ ++ {HNBU_OFDMPO5G, 0xffffffff, 13, "4ofdm5gpo 4ofdm5glpo 4ofdm5ghpo"}, ++ {HNBU_USBEPNUM, 0xffffffff, 3, "2usbepnum"}, ++ {HNBU_CCKBW202GPO, 0xffffffff, 5, "2cckbw202gpo 2cckbw20ul2gpo"}, ++ {HNBU_LEGOFDMBW202GPO, 0xffffffff, 9, "4legofdmbw202gpo 4legofdmbw20ul2gp"}, ++ {HNBU_LEGOFDMBW205GPO, 0xffffffff, 25, "4legofdmbw205glpo 4legofdmbw20ul5glpo " ++ "4legofdmbw205gmpo 4legofdmbw20ul5gmpo 4legofdmbw205ghpo 4legofdmbw20ul5ghpo"}, ++ {HNBU_MCS2GPO, 0xffffffff, 13, "4mcsbw202gpo 4mcsbw20ul2gpo 4mcsbw402gpo"}, ++ {HNBU_MCS5GLPO, 0xffffffff, 13, "4mcsbw205glpo 4mcsbw20ul5glpo 4mcsbw405glpo"}, ++ {HNBU_MCS5GMPO, 0xffffffff, 13, "4mcsbw205gmpo 4mcsbw20ul5gmpo 4mcsbw405gmpo"}, ++ {HNBU_MCS5GHPO, 0xffffffff, 13, "4mcsbw205ghpo 4mcsbw20ul5ghpo 4mcsbw405ghpo"}, ++ {HNBU_MCS32PO, 0xffffffff, 3, "2mcs32po"}, ++ {HNBU_LEG40DUPPO, 0xffffffff, 3, "2legofdm40duppo"}, ++ {HNBU_TEMPTHRESH, 0xffffffff, 6, "1tempthresh 1periodhyst 1tempoffset 1tempcoropt " ++ "1phycal_tempdelta"}, ++ {HNBU_FEM_CFG, 0xfffff800, 5, "2fem_cfg1 2fem_cfg2"}, ++ {HNBU_ACPA_C0, 0xfffff800, 41, "2subband5gver 2maxp2ga0 2*3pa2ga0 2rxgainsa0 " ++ "1*4maxp5ga0 2*12pa5ga0"}, ++ {HNBU_ACPA_C1, 0xfffff800, 39, "2maxp2ga1 2*3pa2ga1 2rxgainsa1 1*4maxp5ga1 " ++ "2*12pa5ga1"}, ++ {HNBU_ACPA_C2, 0xfffff800, 39, "2maxp2ga2 2*3pa2ga2 2rxgainsa2 1*4maxp5ga2 " ++ "2*12pa5ga2"}, ++ {HNBU_MEAS_PWR, 0xfffff800, 5, "1measpower 1measpower1 1measpower2 2rawtempsense"}, ++ {HNBU_PDOFF, 0xfffff800, 13, "2pdoffset40ma0 2pdoffset40ma1 2pdoffset40ma2 " ++ "2pdoffset80ma0 2pdoffset80ma1 2pdoffset80ma2"}, ++ {HNBU_ACPPR_2GPO, 0xfffff800, 5, "2dot11agofdmhrbw202gpo 2ofdmlrbw202gpo"}, ++ {HNBU_ACPPR_5GPO, 0xfffff800, 31, "4mcsbw805glpo 4mcsbw1605glpo 4mcsbw805gmpo " ++ "4mcsbw1605gmpo 4mcsbw805ghpo 4mcsbw1605ghpo 2mcslr5rlpo 2mcslr5gmpo 2mcslr5ghpo"}, ++ {HNBU_ACPPR_SBPO, 0xfffff800, 33, "2sb20in40hrrpo 2sb20in80and160hr5glpo " ++ "2sb40and80hr5glpo 2sb20in80and160hr5gmpo 2sb40and80hr5gmpo 2sb20in80and160hr5ghpo " ++ "2sb40and80hr5ghpo 2sb20in40lrpo 2sb20in80and160lr5glpo 2sb40and80lr5glpo " ++ "2sb20in80and160lr5gmpo 2sb40and80lr5gmpo 2sb20in80and160lr5ghpo 2sb40and80lr5ghpo " ++ "2dot11agduphrpo 2dot11agduplrpo"}, ++ {HNBU_NOISELVL, 0xfffff800, 11, "2noiselvl2g 2noiselvl5gl 2noiselvl5gm " ++ "2noiselvl5gh 2noiselvl5gu"}, ++ {HNBU_RXGAIN_ERR, 0xfffff800, 11, "2rxgainerr2g 2*4rxgainerr5g"}, ++ {HNBU_AGBGA, 0xfffff800, 7, "1agbg0 1agbg1 1agbg2 1aga0 1aga1 1aga2"}, ++ {HNBU_UUID, 0xffffffff, 17, "16uuid"}, ++ {0xFF, 0xffffffff, 0, ""} ++}; ++ ++#endif /* _bcmsrom_tbl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmstdlib.h b/drivers/bcmdrivers/gmac/src/include/bcmstdlib.h +new file mode 100755 +index 0000000..de1686f +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmstdlib.h +@@ -0,0 +1,128 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * prototypes for functions defined in bcmstdlib.c ++ * ++ * $Id: bcmstdlib.h 289936 2011-10-14 21:06:33Z $: ++ */ ++ ++/* ++ * bcmstdlib.h file should be used only to construct an OSL or alone without any OSL ++ * It should not be used with any orbitarary OSL's as there could be a conflict ++ * with some of the routines defined here. ++*/ ++ ++#ifndef _BCMSTDLIB_H ++#define _BCMSTDLIB_H ++ ++#include ++#include ++#include ++ ++#ifndef INT_MAX ++#define INT_MAX 2147483647 /* from limits.h */ ++#endif ++ ++ ++/* For backwards compatibility, define "BWL_NO_INTERNAL_STDLIB_SUPPORT" to ++ * exclude support for the BRCM stdlib APIs. This should be cleaned-up such ++ * that platforms that require the BRCM stdlib API should simply define ++ * "BWL_INTERNAL_STDLIB_SUPPORT". This would eliminate the need for the ++ * following #ifndef check. ++ */ ++#ifndef BWL_NO_INTERNAL_STDLIB_SUPPORT ++#define BWL_INTERNAL_STDLIB_SUPPORT ++#endif ++ ++#ifdef BWL_INTERNAL_STDLIB_SUPPORT ++/* This should be cleaned-up such that platforms that require the BRCM stdlib ++ * API should simply define "BWL_INTERNAL_STDLIB_SUPPORT". This would eliminate ++ * the need for the following #ifdef check. ++ */ ++#if !defined(_WIN32) && !defined(_CFE_) && !defined(EFI) ++ ++typedef int FILE; ++#define stdout ((FILE *)1) ++#define stderr ((FILE *)2) ++ ++/* i/o functions */ ++extern int fputc(int c, FILE *stream); ++extern void putc(int c); ++/* extern int putc(int c, FILE *stream); */ ++#define putchar(c) putc(c) ++extern int fputs(const char *s, FILE *stream); ++extern int puts(const char *s); ++extern int getc(void); ++extern bool keypressed(void); ++ ++/* bcopy, bcmp, and bzero */ ++#define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++#define bzero(b, len) memset((b), '\0', (len)) ++ ++extern unsigned long rand(void); ++ ++#define atoi(s) ((int)(strtoul((s), NULL, 10))) ++ ++#endif ++ ++#if !defined(_WIN32) || defined(EFI) ++/* string functions */ ++#define PRINTF_BUFLEN 512 ++extern int printf(const char *fmt, ...) ++ __attribute__ ((format (__printf__, 1, 2))); ++extern int BCMROMFN(sprintf)(char *buf, const char *fmt, ...) ++ __attribute__ ((format (__printf__, 2, 3))); ++ ++extern int BCMROMFN(strcmp)(const char *s1, const char *s2); ++extern size_t BCMROMFN(strlen)(const char *s); ++extern char *BCMROMFN(strcpy)(char *dest, const char *src); ++extern char *BCMROMFN(strstr)(const char *s, const char *find); ++extern char *BCMROMFN(strncpy)(char *dest, const char *src, size_t n); ++extern char *BCMROMFN(strcat)(char *d, const char *s); ++ ++extern int BCMROMFN(strncmp)(const char *s1, const char *s2, size_t n); ++extern char *BCMROMFN(strchr)(const char *str, int c); ++extern char *BCMROMFN(strrchr)(const char *str, int c); ++extern size_t BCMROMFN(strspn)(const char *s1, const char *s2); ++extern size_t BCMROMFN(strcspn)(const char *s1, const char *s2); ++extern unsigned long BCMROMFN(strtoul)(const char *cp, char **endp, int base); ++#define strtol(nptr, endptr, base) ((long)strtoul((nptr), (endptr), (base))) ++ ++extern void *BCMROMFN(memmove)(void *dest, const void *src, size_t n); ++extern void *BCMROMFN(memchr)(const void *s, int c, size_t n); ++ ++extern int BCMROMFN(vsprintf)(char *buf, const char *fmt, va_list ap); ++/* mem functions */ ++/* For EFI, using EFIDriverLib versions */ ++/* Cannot use memmem in ROM because of character array initialization wiht "" in gcc */ ++extern void *memset(void *dest, int c, size_t n); ++/* Cannot use memcpy in ROM because of structure assignmnets in gcc */ ++extern void *memcpy(void *dest, const void *src, size_t n); ++extern int BCMROMFN(memcmp)(const void *s1, const void *s2, size_t n); ++ ++#endif /* !_WIN32 || EFI */ ++#endif /* BWL_INTERNAL_STDLIB_SUPPORT */ ++ ++#if !defined(_WIN32) || defined(EFI) ++extern int BCMROMFN(snprintf)(char *str, size_t n, char const *fmt, ...) ++ __attribute__ ((format (__printf__, 3, 4))); ++#else ++extern int BCMROMFN(snprintf)(char *str, size_t n, char const *fmt, ...); ++#endif ++ ++extern int BCMROMFN(vsnprintf)(char *buf, size_t size, const char *fmt, va_list ap); ++ ++#endif /* _BCMSTDLIB_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmutils.h b/drivers/bcmdrivers/gmac/src/include/bcmutils.h +new file mode 100755 +index 0000000..ac00a91 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmutils.h +@@ -0,0 +1,864 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc useful os-independent macros and functions. ++ * ++ * $Id: bcmutils.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _bcmutils_h_ ++#define _bcmutils_h_ ++ ++#if defined(UNDER_CE) ++#include ++#else ++#define bcm_strcpy_s(dst, noOfElements, src) strcpy((dst), (src)) ++#define bcm_strncpy_s(dst, noOfElements, src, count) strncpy((dst), (src), (count)) ++#define bcm_strcat_s(dst, noOfElements, src) strcat((dst), (src)) ++#endif ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef PKTQ_LOG ++#include ++#endif ++ ++/* ctype replacement */ ++#define _BCM_U 0x01 /* upper */ ++#define _BCM_L 0x02 /* lower */ ++#define _BCM_D 0x04 /* digit */ ++#define _BCM_C 0x08 /* cntrl */ ++#define _BCM_P 0x10 /* punct */ ++#define _BCM_S 0x20 /* white space (space/lf/tab) */ ++#define _BCM_X 0x40 /* hex digit */ ++#define _BCM_SP 0x80 /* hard space (0x20) */ ++ ++#if defined(BCMROMBUILD) ++extern const unsigned char BCMROMDATA(bcm_ctype)[]; ++#else ++extern const unsigned char bcm_ctype[]; ++#endif ++#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)]) ++ ++#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0) ++#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0) ++#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0) ++#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0) ++#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0) ++#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0) ++#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0) ++#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0) ++#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0) ++#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0) ++#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0) ++#define bcm_tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) ++#define bcm_toupper(c) (bcm_islower((c)) ? ((c) + 'A' - 'a') : (c)) ++ ++/* Buffer structure for collecting string-formatted data ++* using bcm_bprintf() API. ++* Use bcm_binit() to initialize before use ++*/ ++ ++struct bcmstrbuf { ++ char *buf; /* pointer to current position in origbuf */ ++ unsigned int size; /* current (residual) size in bytes */ ++ char *origbuf; /* unmodified pointer to orignal buffer */ ++ unsigned int origsize; /* unmodified orignal buffer size in bytes */ ++}; ++ ++/* ** driver-only section ** */ ++#ifdef BCMDRIVER ++#ifdef EFI ++/* forward declare structyre type */ ++struct spktq; ++#endif ++#include ++ ++#define GPIO_PIN_NOTDEFINED 0x20 /* Pin not defined */ ++ ++/* ++ * Spin at most 'us' microseconds while 'exp' is true. ++ * Caller should explicitly test 'exp' when this completes ++ * and take appropriate error action if 'exp' is still true. ++ */ ++#define SPINWAIT(exp, us) { \ ++ uint countdown = (us) + 9; \ ++ while ((exp) && (countdown >= 10)) {\ ++ OSL_DELAY(10); \ ++ countdown -= 10; \ ++ } \ ++} ++ ++/* osl multi-precedence packet queue */ ++#ifndef PKTQ_LEN_DEFAULT ++#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ ++#endif ++#ifndef PKTQ_MAX_PREC ++#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ ++#endif ++ ++typedef struct pktq_prec { ++ void *head; /* first packet to dequeue */ ++ void *tail; /* last packet to dequeue */ ++ uint16 len; /* number of queued packets */ ++ uint16 max; /* maximum number of queued packets */ ++} pktq_prec_t; ++ ++#ifdef PKTQ_LOG ++typedef struct { ++ uint32 requested; /* packets requested to be stored */ ++ uint32 stored; /* packets stored */ ++ uint32 saved; /* packets saved, ++ because a lowest priority queue has given away one packet ++ */ ++ uint32 selfsaved; /* packets saved, ++ because an older packet from the same queue has been dropped ++ */ ++ uint32 full_dropped; /* packets dropped, ++ because pktq is full with higher precedence packets ++ */ ++ uint32 dropped; /* packets dropped because pktq per that precedence is full */ ++ uint32 sacrificed; /* packets dropped, ++ in order to save one from a queue of a highest priority ++ */ ++ uint32 busy; /* packets droped because of hardware/transmission error */ ++ uint32 retry; /* packets re-sent because they were not received */ ++ uint32 ps_retry; /* packets retried again prior to moving power save mode */ ++ uint32 retry_drop; /* packets finally dropped after retry limit */ ++ uint32 max_avail; /* the high-water mark of the queue capacity for packets - ++ goes to zero as queue fills ++ */ ++ uint32 max_used; /* the high-water mark of the queue utilisation for packets - ++ increases with use ('inverse' of max_avail) ++ */ ++ uint32 queue_capacity; /* the maximum capacity of the queue */ ++} pktq_counters_t; ++#endif /* PKTQ_LOG */ ++ ++ ++#define PKTQ_COMMON \ ++ uint16 num_prec; /* number of precedences in use */ \ ++ uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ \ ++ uint16 max; /* total max packets */ \ ++ uint16 len; /* total number of packets */ ++ ++/* multi-priority pkt queue */ ++struct pktq { ++ PKTQ_COMMON ++ /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ ++ struct pktq_prec q[PKTQ_MAX_PREC]; ++#ifdef PKTQ_LOG ++ pktq_counters_t _prec_cnt[PKTQ_MAX_PREC]; /* Counters per queue */ ++#endif ++}; ++ ++/* simple, non-priority pkt queue */ ++struct spktq { ++ PKTQ_COMMON ++ /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ ++ struct pktq_prec q[1]; ++}; ++ ++#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) ++ ++/* fn(pkt, arg). return true if pkt belongs to if */ ++typedef bool (*ifpkt_cb_t)(void*, int); ++ ++#ifdef BCMPKTPOOL ++#define POOL_ENAB(pool) ((pool) && (pool)->inited) ++#if defined(BCM4329C0) ++#define SHARED_POOL (pktpool_shared_ptr) ++#else ++#define SHARED_POOL (pktpool_shared) ++#endif /* BCM4329C0 */ ++#else /* BCMPKTPOOL */ ++#define POOL_ENAB(bus) 0 ++#define SHARED_POOL ((struct pktpool *)NULL) ++#endif /* BCMPKTPOOL */ ++ ++#ifndef PKTPOOL_LEN_MAX ++#define PKTPOOL_LEN_MAX 40 ++#endif /* PKTPOOL_LEN_MAX */ ++#define PKTPOOL_CB_MAX 3 ++ ++struct pktpool; ++typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg); ++typedef struct { ++ pktpool_cb_t cb; ++ void *arg; ++} pktpool_cbinfo_t; ++ ++#ifdef BCMDBG_POOL ++/* pkt pool debug states */ ++#define POOL_IDLE 0 ++#define POOL_RXFILL 1 ++#define POOL_RXDH 2 ++#define POOL_RXD11 3 ++#define POOL_TXDH 4 ++#define POOL_TXD11 5 ++#define POOL_AMPDU 6 ++#define POOL_TXENQ 7 ++ ++typedef struct { ++ void *p; ++ uint32 cycles; ++ uint32 dur; ++} pktpool_dbg_t; ++ ++typedef struct { ++ uint8 txdh; /* tx to host */ ++ uint8 txd11; /* tx to d11 */ ++ uint8 enq; /* waiting in q */ ++ uint8 rxdh; /* rx from host */ ++ uint8 rxd11; /* rx from d11 */ ++ uint8 rxfill; /* dma_rxfill */ ++ uint8 idle; /* avail in pool */ ++} pktpool_stats_t; ++#endif /* BCMDBG_POOL */ ++ ++typedef struct pktpool { ++ bool inited; ++ uint16 r; ++ uint16 w; ++ uint16 len; ++ uint16 maxlen; ++ uint16 plen; ++ bool istx; ++ bool empty; ++ uint8 cbtoggle; ++ uint8 cbcnt; ++ uint8 ecbcnt; ++ bool emptycb_disable; ++ pktpool_cbinfo_t *availcb_excl; ++ pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX]; ++ pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX]; ++ void *q[PKTPOOL_LEN_MAX + 1]; ++ ++#ifdef BCMDBG_POOL ++ uint8 dbg_cbcnt; ++ pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX]; ++ uint16 dbg_qlen; ++ pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1]; ++#endif ++} pktpool_t; ++ ++#if defined(BCM4329C0) ++extern pktpool_t *pktpool_shared_ptr; ++#else ++extern pktpool_t *pktpool_shared; ++#endif /* BCM4329C0 */ ++ ++extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx); ++extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp); ++extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal); ++extern void* pktpool_get(pktpool_t *pktp); ++extern void pktpool_free(pktpool_t *pktp, void *p); ++extern int pktpool_add(pktpool_t *pktp, void *p); ++extern uint16 pktpool_avail(pktpool_t *pktp); ++extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp); ++extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb); ++extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); ++extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); ++extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen); ++extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen); ++extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable); ++extern bool pktpool_emptycb_disabled(pktpool_t *pktp); ++ ++#define POOLPTR(pp) ((pktpool_t *)(pp)) ++#define pktpool_len(pp) (POOLPTR(pp)->len - 1) ++#define pktpool_plen(pp) (POOLPTR(pp)->plen) ++#define pktpool_maxlen(pp) (POOLPTR(pp)->maxlen) ++ ++#ifdef BCMDBG_POOL ++extern int pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); ++extern int pktpool_start_trigger(pktpool_t *pktp, void *p); ++extern int pktpool_dbg_dump(pktpool_t *pktp); ++extern int pktpool_dbg_notify(pktpool_t *pktp); ++extern int pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats); ++#endif /* BCMDBG_POOL */ ++ ++/* forward definition of ether_addr structure used by some function prototypes */ ++ ++struct ether_addr; ++ ++extern int ether_isbcast(const void *ea); ++extern int ether_isnulladdr(const void *ea); ++ ++/* operations on a specific precedence in packet queue */ ++ ++#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) ++#define pktq_pmax(pq, prec) ((pq)->q[prec].max) ++#define pktq_plen(pq, prec) ((pq)->q[prec].len) ++#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len) ++#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max) ++#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0) ++ ++#define pktq_ppeek(pq, prec) ((pq)->q[prec].head) ++#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) ++ ++extern void *pktq_penq(struct pktq *pq, int prec, void *p); ++extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); ++extern void *pktq_pdeq(struct pktq *pq, int prec); ++extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p); ++extern void *pktq_pdeq_tail(struct pktq *pq, int prec); ++/* Empty the queue at particular precedence level */ ++extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ++ ifpkt_cb_t fn, int arg); ++/* Remove a specified packet from its queue */ ++extern bool pktq_pdel(struct pktq *pq, void *p, int prec); ++ ++/* operations on a set of precedences in packet queue */ ++ ++extern int pktq_mlen(struct pktq *pq, uint prec_bmp); ++extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); ++extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out); ++ ++/* operations on packet queue as a whole */ ++ ++#define pktq_len(pq) ((int)(pq)->len) ++#define pktq_max(pq) ((int)(pq)->max) ++#define pktq_avail(pq) ((int)((pq)->max - (pq)->len)) ++#define pktq_full(pq) ((pq)->len >= (pq)->max) ++#define pktq_empty(pq) ((pq)->len == 0) ++ ++/* operations for single precedence queues */ ++#define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p)) ++#define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p)) ++#define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0) ++#define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0) ++#define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len) ++ ++extern void pktq_init(struct pktq *pq, int num_prec, int max_len); ++extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len); ++ ++/* prec_out may be NULL if caller is not interested in return value */ ++extern void *pktq_deq(struct pktq *pq, int *prec_out); ++extern void *pktq_deq_tail(struct pktq *pq, int *prec_out); ++extern void *pktq_peek(struct pktq *pq, int *prec_out); ++extern void *pktq_peek_tail(struct pktq *pq, int *prec_out); ++extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg); ++ ++/* externs */ ++/* packet */ ++extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf); ++extern uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf); ++extern uint pkttotlen(osl_t *osh, void *p); ++extern void *pktlast(osl_t *osh, void *p); ++extern uint pktsegcnt(osl_t *osh, void *p); ++extern uint pktsegcnt_war(osl_t *osh, void *p); ++extern uint8 *pktdataoffset(osl_t *osh, void *p, uint offset); ++extern void *pktoffset(osl_t *osh, void *p, uint offset); ++ ++/* Get priority from a packet and pass it back in scb (or equiv) */ ++#define PKTPRIO_VDSCP 0x100 /* DSCP prio found after VLAN tag */ ++#define PKTPRIO_VLAN 0x200 /* VLAN prio found */ ++#define PKTPRIO_UPD 0x400 /* DSCP used to update VLAN prio */ ++#define PKTPRIO_DSCP 0x800 /* DSCP prio found */ ++ ++extern uint pktsetprio(void *pkt, bool update_vtag); ++ ++/* string */ ++extern int BCMROMFN(bcm_atoi)(const char *s); ++extern ulong BCMROMFN(bcm_strtoul)(const char *cp, char **endp, uint base); ++extern char *BCMROMFN(bcmstrstr)(const char *haystack, const char *needle); ++extern char *BCMROMFN(bcmstrcat)(char *dest, const char *src); ++extern char *BCMROMFN(bcmstrncat)(char *dest, const char *src, uint size); ++extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen); ++char* bcmstrtok(char **string, const char *delimiters, char *tokdelim); ++int bcmstricmp(const char *s1, const char *s2); ++int bcmstrnicmp(const char* s1, const char* s2, int cnt); ++ ++ ++/* ethernet address */ ++extern char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf); ++extern int BCMROMFN(bcm_ether_atoe)(const char *p, struct ether_addr *ea); ++ ++/* ip address */ ++struct ipv4_addr; ++extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf); ++ ++/* delay */ ++extern void bcm_mdelay(uint ms); ++/* variable access */ ++#if defined(DONGLEBUILD) && !defined(WLTEST) ++#ifdef BCMDBG ++#define NVRAM_RECLAIM_CHECK(name) \ ++ if (attach_part_reclaimed == TRUE) { \ ++ printf("%s: NVRAM already reclaimed, %s\n", __FUNCTION__, (name)); \ ++ *(char*) 0 = 0; /* TRAP */ \ ++ return NULL; \ ++ } ++#else /* BCMDBG */ ++#define NVRAM_RECLAIM_CHECK(name) \ ++ if (attach_part_reclaimed == TRUE) { \ ++ *(char*) 0 = 0; /* TRAP */ \ ++ return NULL; \ ++ } ++#endif /* BCMDBG */ ++#else /* DONGLEBUILD && !WLTEST && !BCMINTERNAL && !BCMDBG_DUMP */ ++#define NVRAM_RECLAIM_CHECK(name) ++#endif ++ ++extern char *getvar(char *vars, const char *name); ++extern int getintvar(char *vars, const char *name); ++extern int getintvararray(char *vars, const char *name, int index); ++extern int getintvararraysize(char *vars, const char *name); ++extern uint getgpiopin(char *vars, char *pin_name, uint def_pin); ++extern int getwanport(void); ++extern int getbrcmtag(void); ++#ifdef BCMDBG ++extern void prpkt(const char *msg, osl_t *osh, void *p0); ++#endif /* BCMDBG */ ++#ifdef BCMPERFSTATS ++extern void bcm_perf_enable(void); ++extern void bcmstats(char *fmt); ++extern void bcmlog(char *fmt, uint a1, uint a2); ++extern void bcmdumplog(char *buf, int size); ++extern int bcmdumplogent(char *buf, uint idx); ++#else ++#define bcm_perf_enable() ++#define bcmstats(fmt) ++#define bcmlog(fmt, a1, a2) ++#define bcmdumplog(buf, size) *buf = '\0' ++#define bcmdumplogent(buf, idx) -1 ++#endif /* BCMPERFSTATS */ ++ ++#if defined(BCMTSTAMPEDLOGS) ++#define TSF_TICKS_PER_MS 1024 ++/* Store a TSF timestamp and a log line in the log buffer */ ++extern void bcmtslog(uint32 tstamp, char *fmt, uint a1, uint a2); ++/* Print out the log buffer with timestamps */ ++extern void bcmprinttslogs(void); ++/* Print out a microsecond timestamp as "sec.ms.us " */ ++extern void bcmprinttstamp(uint32 us); ++/* Dump to buffer a microsecond timestamp as "sec.ms.us " */ ++extern void bcmdumptslog(char *buf, int size); ++#else ++#define bcmtslog(tstamp, fmt, a1, a2) ++#define bcmprinttslogs() ++#define bcmprinttstamp(us) ++#define bcmdumptslog(buf, size) ++#endif /* BCMTSTAMPEDLOGS */ ++ ++extern char *bcm_nvram_vars(uint *length); ++extern int bcm_nvram_cache(void *sih); ++ ++/* Support for sharing code across in-driver iovar implementations. ++ * The intent is that a driver use this structure to map iovar names ++ * to its (private) iovar identifiers, and the lookup function to ++ * find the entry. Macros are provided to map ids and get/set actions ++ * into a single number space for a switch statement. ++ */ ++ ++/* iovar structure */ ++typedef struct bcm_iovar { ++ const char *name; /* name for lookup and display */ ++ uint16 varid; /* id for switch */ ++ uint16 flags; /* driver-specific flag bits */ ++ uint16 type; /* base type of argument */ ++ uint16 minlen; /* min length for buffer vars */ ++} bcm_iovar_t; ++ ++/* varid definitions are per-driver, may use these get/set bits */ ++ ++/* IOVar action bits for id mapping */ ++#define IOV_GET 0 /* Get an iovar */ ++#define IOV_SET 1 /* Set an iovar */ ++ ++/* Varid to actionid mapping */ ++#define IOV_GVAL(id) ((id) * 2) ++#define IOV_SVAL(id) ((id) * 2 + IOV_SET) ++#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET) ++#define IOV_ID(actionid) (actionid >> 1) ++ ++/* flags are per-driver based on driver attributes */ ++ ++extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name); ++extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set); ++#if defined(WLTINYDUMP) || defined(BCMDBG) || defined(WLMSG_INFORM) || \ ++ defined(WLMSG_ASSOC) || defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) ++extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len); ++#endif /* WLTINYDUMP || BCMDBG || WLMSG_INFORM || WLMSG_ASSOC || WLMSG_PRPKT */ ++#endif /* BCMDRIVER */ ++ ++/* Base type definitions */ ++#define IOVT_VOID 0 /* no value (implictly set only) */ ++#define IOVT_BOOL 1 /* any value ok (zero/nonzero) */ ++#define IOVT_INT8 2 /* integer values are range-checked */ ++#define IOVT_UINT8 3 /* unsigned int 8 bits */ ++#define IOVT_INT16 4 /* int 16 bits */ ++#define IOVT_UINT16 5 /* unsigned int 16 bits */ ++#define IOVT_INT32 6 /* int 32 bits */ ++#define IOVT_UINT32 7 /* unsigned int 32 bits */ ++#define IOVT_BUFFER 8 /* buffer is size-checked as per minlen */ ++#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER) ++ ++/* Initializer for IOV type strings */ ++#define BCM_IOV_TYPE_INIT { \ ++ "void", \ ++ "bool", \ ++ "int8", \ ++ "uint8", \ ++ "int16", \ ++ "uint16", \ ++ "int32", \ ++ "uint32", \ ++ "buffer", \ ++ "" } ++ ++#define BCM_IOVT_IS_INT(type) (\ ++ (type == IOVT_BOOL) || \ ++ (type == IOVT_INT8) || \ ++ (type == IOVT_UINT8) || \ ++ (type == IOVT_INT16) || \ ++ (type == IOVT_UINT16) || \ ++ (type == IOVT_INT32) || \ ++ (type == IOVT_UINT32)) ++ ++/* ** driver/apps-shared section ** */ ++ ++#define BCME_STRLEN 64 /* Max string length for BCM errors */ ++#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) ++ ++ ++/* ++ * error codes could be added but the defined ones shouldn't be changed/deleted ++ * these error codes are exposed to the user code ++ * when ever a new error code is added to this list ++ * please update errorstring table with the related error string and ++ * update osl files with os specific errorcode map ++*/ ++ ++#define BCME_OK 0 /* Success */ ++#define BCME_ERROR -1 /* Error generic */ ++#define BCME_BADARG -2 /* Bad Argument */ ++#define BCME_BADOPTION -3 /* Bad option */ ++#define BCME_NOTUP -4 /* Not up */ ++#define BCME_NOTDOWN -5 /* Not down */ ++#define BCME_NOTAP -6 /* Not AP */ ++#define BCME_NOTSTA -7 /* Not STA */ ++#define BCME_BADKEYIDX -8 /* BAD Key Index */ ++#define BCME_RADIOOFF -9 /* Radio Off */ ++#define BCME_NOTBANDLOCKED -10 /* Not band locked */ ++#define BCME_NOCLK -11 /* No Clock */ ++#define BCME_BADRATESET -12 /* BAD Rate valueset */ ++#define BCME_BADBAND -13 /* BAD Band */ ++#define BCME_BUFTOOSHORT -14 /* Buffer too short */ ++#define BCME_BUFTOOLONG -15 /* Buffer too long */ ++#define BCME_BUSY -16 /* Busy */ ++#define BCME_NOTASSOCIATED -17 /* Not Associated */ ++#define BCME_BADSSIDLEN -18 /* Bad SSID len */ ++#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */ ++#define BCME_BADCHAN -20 /* Bad Channel */ ++#define BCME_BADADDR -21 /* Bad Address */ ++#define BCME_NORESOURCE -22 /* Not Enough Resources */ ++#define BCME_UNSUPPORTED -23 /* Unsupported */ ++#define BCME_BADLEN -24 /* Bad length */ ++#define BCME_NOTREADY -25 /* Not Ready */ ++#define BCME_EPERM -26 /* Not Permitted */ ++#define BCME_NOMEM -27 /* No Memory */ ++#define BCME_ASSOCIATED -28 /* Associated */ ++#define BCME_RANGE -29 /* Not In Range */ ++#define BCME_NOTFOUND -30 /* Not Found */ ++#define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */ ++#define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */ ++#define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */ ++#define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */ ++#define BCME_SDIO_ERROR -35 /* SDIO Bus Error */ ++#define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */ ++#define BCME_VERSION -37 /* Incorrect version */ ++#define BCME_TXFAIL -38 /* TX failure */ ++#define BCME_RXFAIL -39 /* RX failure */ ++#define BCME_NODEVICE -40 /* Device not present */ ++#define BCME_NMODE_DISABLED -41 /* NMODE disabled */ ++#define BCME_NONRESIDENT -42 /* access to nonresident overlay */ ++#define BCME_LAST BCME_NONRESIDENT ++ ++/* These are collection of BCME Error strings */ ++#define BCMERRSTRINGTABLE { \ ++ "OK", \ ++ "Undefined error", \ ++ "Bad Argument", \ ++ "Bad Option", \ ++ "Not up", \ ++ "Not down", \ ++ "Not AP", \ ++ "Not STA", \ ++ "Bad Key Index", \ ++ "Radio Off", \ ++ "Not band locked", \ ++ "No clock", \ ++ "Bad Rate valueset", \ ++ "Bad Band", \ ++ "Buffer too short", \ ++ "Buffer too long", \ ++ "Busy", \ ++ "Not Associated", \ ++ "Bad SSID len", \ ++ "Out of Range Channel", \ ++ "Bad Channel", \ ++ "Bad Address", \ ++ "Not Enough Resources", \ ++ "Unsupported", \ ++ "Bad length", \ ++ "Not Ready", \ ++ "Not Permitted", \ ++ "No Memory", \ ++ "Associated", \ ++ "Not In Range", \ ++ "Not Found", \ ++ "WME Not Enabled", \ ++ "TSPEC Not Found", \ ++ "ACM Not Supported", \ ++ "Not WME Association", \ ++ "SDIO Bus Error", \ ++ "Dongle Not Accessible", \ ++ "Incorrect version", \ ++ "TX Failure", \ ++ "RX Failure", \ ++ "Device Not Present", \ ++ "NMODE Disabled", \ ++ "Nonresident overlay access", \ ++} ++ ++#ifndef ABS ++#define ABS(a) (((a) < 0) ? -(a) : (a)) ++#endif /* ABS */ ++ ++#ifndef MIN ++#define MIN(a, b) (((a) < (b)) ? (a) : (b)) ++#endif /* MIN */ ++ ++#ifndef MAX ++#define MAX(a, b) (((a) > (b)) ? (a) : (b)) ++#endif /* MAX */ ++ ++#define CEIL(x, y) (((x) + ((y) - 1)) / (y)) ++#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) ++#define ISALIGNED(a, x) (((uintptr)(a) & ((x) - 1)) == 0) ++#define ALIGN_ADDR(addr, boundary) (void *)(((uintptr)(addr) + (boundary) - 1) \ ++ & ~((boundary) - 1)) ++#define ALIGN_SIZE(size, boundary) (((size) + (boundary) - 1) \ ++ & ~((boundary) - 1)) ++#define ISPOWEROF2(x) ((((x) - 1) & (x)) == 0) ++#define VALID_MASK(mask) !((mask) & ((mask) + 1)) ++ ++#ifndef OFFSETOF ++#ifdef __ARMCC_VERSION ++/* ++ * The ARM RVCT compiler complains when using OFFSETOF where a constant ++ * expression is expected, such as an initializer for a static object. ++ * offsetof from the runtime library doesn't have that problem. ++ */ ++#include ++#define OFFSETOF(type, member) offsetof(type, member) ++#else ++#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) ++#endif /* __ARMCC_VERSION */ ++#endif /* OFFSETOF */ ++ ++#ifndef ARRAYSIZE ++#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0])) ++#endif ++ ++/* Reference a function; used to prevent a static function from being optimized out */ ++extern void *_bcmutils_dummy_fn; ++#define REFERENCE_FUNCTION(f) (_bcmutils_dummy_fn = (void *)(f)) ++ ++/* bit map related macros */ ++#ifndef setbit ++#ifndef NBBY /* the BSD family defines NBBY */ ++#define NBBY 8 /* 8 bits per byte */ ++#endif /* #ifndef NBBY */ ++#define setbit(a, i) (((uint8 *)a)[(i) / NBBY] |= 1 << ((i) % NBBY)) ++#define clrbit(a, i) (((uint8 *)a)[(i) / NBBY] &= ~(1 << ((i) % NBBY))) ++#define isset(a, i) (((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) ++#define isclr(a, i) ((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0) ++#endif /* setbit */ ++ ++#define NBITS(type) (sizeof(type) * 8) ++#define NBITVAL(nbits) (1 << (nbits)) ++#define MAXBITVAL(nbits) ((1 << (nbits)) - 1) ++#define NBITMASK(nbits) MAXBITVAL(nbits) ++#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) ++ ++/* basic mux operation - can be optimized on several architectures */ ++#define MUX(pred, true, false) ((pred) ? (true) : (false)) ++ ++/* modulo inc/dec - assumes x E [0, bound - 1] */ ++#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1) ++#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) ++ ++/* modulo inc/dec, bound = 2^k */ ++#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) ++#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) ++ ++/* modulo add/sub - assumes x, y E [0, bound - 1] */ ++#define MODADD(x, y, bound) \ ++ MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y)) ++#define MODSUB(x, y, bound) \ ++ MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y)) ++ ++/* module add/sub, bound = 2^k */ ++#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) ++#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) ++ ++/* crc defines */ ++#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */ ++#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */ ++#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ ++#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ ++#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */ ++#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */ ++ ++/* use for direct output of MAC address in printf etc */ ++#define MACF "%02x:%02x:%02x:%02x:%02x:%02x" ++#define ETHERP_TO_MACF(ea) ((struct ether_addr *) (ea))->octet[0], \ ++ ((struct ether_addr *) (ea))->octet[1], \ ++ ((struct ether_addr *) (ea))->octet[2], \ ++ ((struct ether_addr *) (ea))->octet[3], \ ++ ((struct ether_addr *) (ea))->octet[4], \ ++ ((struct ether_addr *) (ea))->octet[5] ++ ++#define ETHER_TO_MACF(ea) (ea).octet[0], \ ++ (ea).octet[1], \ ++ (ea).octet[2], \ ++ (ea).octet[3], \ ++ (ea).octet[4], \ ++ (ea).octet[5] ++ ++/* bcm_format_flags() bit description structure */ ++typedef struct bcm_bit_desc { ++ uint32 bit; ++ const char* name; ++} bcm_bit_desc_t; ++ ++/* tag_ID/length/value_buffer tuple */ ++typedef struct bcm_tlv { ++ uint8 id; ++ uint8 len; ++ uint8 data[1]; ++} bcm_tlv_t; ++ ++/* Check that bcm_tlv_t fits into the given buflen */ ++#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len)) ++ ++/* buffer length for ethernet address from bcm_ether_ntoa() */ ++#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */ ++ ++/* crypto utility function */ ++/* 128-bit xor: *dst = *src1 xor *src2. dst1, src1 and src2 may have any alignment */ ++static INLINE void ++xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst) ++{ ++ if ( ++#ifdef __i386__ ++ 1 || ++#endif ++ (((uintptr)src1 | (uintptr)src2 | (uintptr)dst) & 3) == 0) { ++ /* ARM CM3 rel time: 1229 (727 if alignment check could be omitted) */ ++ /* x86 supports unaligned. This version runs 6x-9x faster on x86. */ ++ ((uint32 *)dst)[0] = ((const uint32 *)src1)[0] ^ ((const uint32 *)src2)[0]; ++ ((uint32 *)dst)[1] = ((const uint32 *)src1)[1] ^ ((const uint32 *)src2)[1]; ++ ((uint32 *)dst)[2] = ((const uint32 *)src1)[2] ^ ((const uint32 *)src2)[2]; ++ ((uint32 *)dst)[3] = ((const uint32 *)src1)[3] ^ ((const uint32 *)src2)[3]; ++ } else { ++ /* ARM CM3 rel time: 4668 (4191 if alignment check could be omitted) */ ++ int k; ++ for (k = 0; k < 16; k++) ++ dst[k] = src1[k] ^ src2[k]; ++ } ++} ++ ++/* externs */ ++/* crc */ ++extern uint8 BCMROMFN(hndcrc8)(uint8 *p, uint nbytes, uint8 crc); ++extern uint16 BCMROMFN(hndcrc16)(uint8 *p, uint nbytes, uint16 crc); ++extern uint32 BCMROMFN(hndcrc32)(uint8 *p, uint nbytes, uint32 crc); ++ ++/* format/print */ ++#if defined(BCMDBG) || defined(DHD_DEBUG) || defined(BCMDBG_ERR) || \ ++ defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) ++extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len); ++#endif ++ ++#if defined(BCMDBG) || defined(DHD_DEBUG) || defined(BCMDBG_ERR) || \ ++ defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \ ++ defined(WLMEDIA_PEAKRATE) ++extern int bcm_format_hex(char *str, const void *bytes, int len); ++#endif ++ ++#ifdef BCMDBG ++extern void deadbeef(void *p, size_t len); ++#endif ++extern const char *bcm_crypto_algo_name(uint algo); ++extern char *bcm_chipname(uint chipid, char *buf, uint len); ++extern char *bcm_brev_str(uint32 brev, char *buf); ++extern void printbig(char *buf); ++extern void prhex(const char *msg, uchar *buf, uint len); ++ ++/* IE parsing */ ++extern bcm_tlv_t *BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen); ++extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key); ++extern bcm_tlv_t *BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key); ++ ++/* bcmerror */ ++extern const char *bcmerrorstr(int bcmerror); ++extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key); ++ ++/* multi-bool data type: set of bools, mbool is true if any is set */ ++typedef uint32 mbool; ++#define mboolset(mb, bit) ((mb) |= (bit)) /* set one bool */ ++#define mboolclr(mb, bit) ((mb) &= ~(bit)) /* clear one bool */ ++#define mboolisset(mb, bit) (((mb) & (bit)) != 0) /* TRUE if one bool is set */ ++#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) ++ ++/* generic datastruct to help dump routines */ ++struct fielddesc { ++ const char *nameandfmt; ++ uint32 offset; ++ uint32 len; ++}; ++ ++extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size); ++extern void bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len); ++ ++extern void bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount); ++extern int bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes); ++extern void bcm_print_bytes(const char *name, const uchar *cdata, int len); ++ ++typedef uint32 (*bcmutl_rdreg_rtn)(void *arg0, uint arg1, uint32 offset); ++extern uint bcmdumpfields(bcmutl_rdreg_rtn func_ptr, void *arg0, uint arg1, struct fielddesc *str, ++ char *buf, uint32 bufsize); ++extern uint BCMROMFN(bcm_bitcount)(uint8 *bitmap, uint bytelength); ++ ++extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...); ++ ++/* power conversion */ ++extern uint16 BCMROMFN(bcm_qdbm_to_mw)(uint8 qdbm); ++extern uint8 BCMROMFN(bcm_mw_to_qdbm)(uint16 mw); ++ ++extern int32 exthdr_validate(char *ptr, uint size); ++extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); ++ ++unsigned int process_nvram_vars(char *varbuf, unsigned int len); ++ ++#ifdef __cplusplus ++ } ++#endif ++ ++#endif /* _bcmutils_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmwifi.h b/drivers/bcmdrivers/gmac/src/include/bcmwifi.h +new file mode 100755 +index 0000000..1470332 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmwifi.h +@@ -0,0 +1,456 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc utility routines for WL and Apps ++ * This header file housing the define and function prototype use by ++ * both the wl driver, tools & Apps. ++ * ++ * $Id: bcmwifi.h 293848 2011-11-03 12:31:04Z $ ++ */ ++ ++#ifndef _bcmwifi_h_ ++#define _bcmwifi_h_ ++ ++ ++/* A chanspec holds the channel number, band, bandwidth and control sideband */ ++typedef uint16 chanspec_t; ++ ++/* channel defines */ ++#define CH_UPPER_SB 0x01 ++#define CH_LOWER_SB 0x02 ++#define CH_EWA_VALID 0x04 ++#define CH_80MHZ_APART 16 ++#define CH_40MHZ_APART 8 ++#define CH_20MHZ_APART 4 ++#define CH_10MHZ_APART 2 ++#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ ++#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ ++#define MAXCHANNEL 224 /* max # supported channels. The max channel no is 216, ++ * this is that + 1 rounded up to a multiple of NBBY (8). ++ * DO NOT MAKE it > 255: channels are uint8's all over ++ */ ++#define CHSPEC_CTLOVLP(sp1, sp2, sep) ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < (sep) ++ ++#ifndef D11AC_IOTYPES ++ ++#define WL_CHANSPEC_CHAN_MASK 0x00ff ++#define WL_CHANSPEC_CHAN_SHIFT 0 ++ ++#define WL_CHANSPEC_CTL_SB_MASK 0x0300 ++#define WL_CHANSPEC_CTL_SB_SHIFT 8 ++#define WL_CHANSPEC_CTL_SB_LOWER 0x0100 ++#define WL_CHANSPEC_CTL_SB_UPPER 0x0200 ++#define WL_CHANSPEC_CTL_SB_NONE 0x0300 ++ ++#define WL_CHANSPEC_BW_MASK 0x0C00 ++#define WL_CHANSPEC_BW_SHIFT 10 ++#define WL_CHANSPEC_BW_10 0x0400 ++#define WL_CHANSPEC_BW_20 0x0800 ++#define WL_CHANSPEC_BW_40 0x0C00 ++ ++#define WL_CHANSPEC_BAND_MASK 0xf000 ++#define WL_CHANSPEC_BAND_SHIFT 12 ++#define WL_CHANSPEC_BAND_5G 0x1000 ++#define WL_CHANSPEC_BAND_2G 0x2000 ++#define INVCHANSPEC 255 ++ ++/* channel defines */ ++#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0) ++#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ ++ ((channel) + CH_10MHZ_APART) : 0) ++#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) ++#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ ++ WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ ++ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) ++#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ ++ ((channel) + CH_20MHZ_APART) : 0) ++#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) ++#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) ++ ++/* chanspec stores radio channel & flags to indicate control channel location, i.e. upper/lower */ ++#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) ++#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) ++ ++#ifdef WL11N_20MHZONLY ++ ++#define CHSPEC_IS10(chspec) 0 ++#define CHSPEC_IS20(chspec) 1 ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) 0 ++#endif ++ ++#else /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) ++#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) ++#endif ++ ++#endif /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) ++#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) ++#define CHSPEC_SB_NONE(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) ++#define CHSPEC_SB_UPPER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) ++#define CHSPEC_SB_LOWER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) ++#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \ ++ (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ ++ (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK)))) ++#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) ++ ++#define CHANSPEC_STR_LEN 8 ++ ++#else /* D11AC_IOTYPES */ ++ ++#define WL_CHANSPEC_CHAN_MASK 0x00ff ++#define WL_CHANSPEC_CHAN_SHIFT 0 ++#define WL_CHANSPEC_CHAN1_MASK 0x000f ++#define WL_CHANSPEC_CHAN1_SHIFT 0 ++#define WL_CHANSPEC_CHAN2_MASK 0x00f0 ++#define WL_CHANSPEC_CHAN2_SHIFT 4 ++ ++#define WL_CHANSPEC_CTL_SB_MASK 0x0700 ++#define WL_CHANSPEC_CTL_SB_SHIFT 8 ++#define WL_CHANSPEC_CTL_SB_LLL 0x0000 ++#define WL_CHANSPEC_CTL_SB_LLU 0x0100 ++#define WL_CHANSPEC_CTL_SB_LUL 0x0200 ++#define WL_CHANSPEC_CTL_SB_LUU 0x0300 ++#define WL_CHANSPEC_CTL_SB_ULL 0x0400 ++#define WL_CHANSPEC_CTL_SB_ULU 0x0500 ++#define WL_CHANSPEC_CTL_SB_UUL 0x0600 ++#define WL_CHANSPEC_CTL_SB_UUU 0x0700 ++#define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL ++#define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU ++#define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL ++#define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU ++#define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL ++#define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU ++#define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL ++#define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU ++ ++#define WL_CHANSPEC_BW_MASK 0x3800 ++#define WL_CHANSPEC_BW_SHIFT 11 ++#define WL_CHANSPEC_BW_5 0x0000 ++#define WL_CHANSPEC_BW_10 0x0800 ++#define WL_CHANSPEC_BW_20 0x1000 ++#define WL_CHANSPEC_BW_40 0x1800 ++#define WL_CHANSPEC_BW_80 0x2000 ++#define WL_CHANSPEC_BW_160 0x2800 ++#define WL_CHANSPEC_BW_8080 0x3000 ++ ++#define WL_CHANSPEC_BAND_MASK 0xc000 ++#define WL_CHANSPEC_BAND_SHIFT 14 ++#define WL_CHANSPEC_BAND_2G 0x0000 ++#define WL_CHANSPEC_BAND_3G 0x4000 ++#define WL_CHANSPEC_BAND_4G 0x8000 ++#define WL_CHANSPEC_BAND_5G 0xc000 ++#define INVCHANSPEC 255 ++ ++/* channel defines */ ++#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \ ++ ((channel) - CH_10MHZ_APART) : 0) ++#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ ++ ((channel) + CH_10MHZ_APART) : 0) ++#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) ++#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ ++ (((channel) <= CH_MAX_2G_CHANNEL) ? \ ++ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) ++#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ ++ ((channel) + CH_20MHZ_APART) : 0) ++#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++#define CH80MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_80 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++#define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_160 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++ ++/* simple MACROs to get different fields of chanspec */ ++#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) ++#define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK) ++#define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK) ++#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) ++#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) ++#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) ++ ++#ifdef WL11N_20MHZONLY ++ ++#define CHSPEC_IS10(chspec) 0 ++#define CHSPEC_IS20(chspec) 1 ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) 0 ++#endif ++#ifndef CHSPEC_IS80 ++#define CHSPEC_IS160(chspec) 0 ++#endif ++#ifndef CHSPEC_IS160 ++#define CHSPEC_IS160(chspec) 0 ++#endif ++#ifndef CHSPEC_IS8080 ++#define CHSPEC_IS8080(chspec) 0 ++#endif ++ ++#else /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) ++#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) ++#endif ++#ifndef CHSPEC_IS80 ++#define CHSPEC_IS80(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80) ++#endif ++#ifndef CHSPEC_IS160 ++#define CHSPEC_IS160(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160) ++#endif ++#ifndef CHSPEC_IS8080 ++#define CHSPEC_IS8080(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080) ++#endif ++ ++#endif /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) ++#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) ++#define CHSPEC_SB_UPPER(chspec) \ ++ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) ++#define CHSPEC_SB_LOWER(chspec) \ ++ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) ++#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) ++ ++/** ++ * Number of chars needed for wf_chspec_ntoa() destination character buffer. ++ */ ++#define CHANSPEC_STR_LEN 20 ++ ++ ++/* Legacy Chanspec defines ++ * These are the defines for the previous format of the chanspec_t ++ */ ++#define WL_LCHANSPEC_CHAN_MASK 0x00ff ++#define WL_LCHANSPEC_CHAN_SHIFT 0 ++ ++#define WL_LCHANSPEC_CTL_SB_MASK 0x0300 ++#define WL_LCHANSPEC_CTL_SB_SHIFT 8 ++#define WL_LCHANSPEC_CTL_SB_LOWER 0x0100 ++#define WL_LCHANSPEC_CTL_SB_UPPER 0x0200 ++#define WL_LCHANSPEC_CTL_SB_NONE 0x0300 ++ ++#define WL_LCHANSPEC_BW_MASK 0x0C00 ++#define WL_LCHANSPEC_BW_SHIFT 10 ++#define WL_LCHANSPEC_BW_10 0x0400 ++#define WL_LCHANSPEC_BW_20 0x0800 ++#define WL_LCHANSPEC_BW_40 0x0C00 ++ ++#define WL_LCHANSPEC_BAND_MASK 0xf000 ++#define WL_LCHANSPEC_BAND_SHIFT 12 ++#define WL_LCHANSPEC_BAND_5G 0x1000 ++#define WL_LCHANSPEC_BAND_2G 0x2000 ++ ++#define LCHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK)) ++#define LCHSPEC_BAND(chspec) ((chspec) & WL_LCHANSPEC_BAND_MASK) ++#define LCHSPEC_CTL_SB(chspec) ((chspec) & WL_LCHANSPEC_CTL_SB_MASK) ++#define LCHSPEC_BW(chspec) ((chspec) & WL_LCHANSPEC_BW_MASK) ++#define LCHSPEC_IS10(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10) ++#define LCHSPEC_IS20(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20) ++#define LCHSPEC_IS40(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40) ++#define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G) ++#define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G) ++ ++#define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band))) ++ ++#endif /* D11AC_IOTYPES */ ++ ++/* ++ * WF_CHAN_FACTOR_* constants are used to calculate channel frequency ++ * given a channel number. ++ * chan_freq = chan_factor * 500Mhz + chan_number * 5 ++ */ ++ ++/** ++ * Channel Factor for the starting frequence of 2.4 GHz channels. ++ * The value corresponds to 2407 MHz. ++ */ ++#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */ ++ ++/** ++ * Channel Factor for the starting frequence of 5 GHz channels. ++ * The value corresponds to 5000 MHz. ++ */ ++#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */ ++ ++/** ++ * Channel Factor for the starting frequence of 4.9 GHz channels. ++ * The value corresponds to 4000 MHz. ++ */ ++#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ ++ ++/* defined rate in 500kbps */ ++#define WLC_MAXRATE 108 /* in 500kbps units */ ++#define WLC_RATE_1M 2 /* in 500kbps units */ ++#define WLC_RATE_2M 4 /* in 500kbps units */ ++#define WLC_RATE_5M5 11 /* in 500kbps units */ ++#define WLC_RATE_11M 22 /* in 500kbps units */ ++#define WLC_RATE_6M 12 /* in 500kbps units */ ++#define WLC_RATE_9M 18 /* in 500kbps units */ ++#define WLC_RATE_12M 24 /* in 500kbps units */ ++#define WLC_RATE_18M 36 /* in 500kbps units */ ++#define WLC_RATE_24M 48 /* in 500kbps units */ ++#define WLC_RATE_36M 72 /* in 500kbps units */ ++#define WLC_RATE_48M 96 /* in 500kbps units */ ++#define WLC_RATE_54M 108 /* in 500kbps units */ ++ ++#define WLC_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */ ++ ++/** ++ * Convert chanspec to ascii string ++ * ++ * @param chspec chanspec format ++ * @param buf ascii string of chanspec ++ * ++ * @return pointer to buf with room for at least CHANSPEC_STR_LEN bytes ++ * ++ * @see CHANSPEC_STR_LEN ++ */ ++extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf); ++ ++/** ++ * Convert ascii string to chanspec ++ * ++ * @param a pointer to input string ++ * ++ * @return >= 0 if successful or 0 otherwise ++ */ ++extern chanspec_t wf_chspec_aton(const char *a); ++ ++/** ++ * Verify the chanspec fields are valid. ++ * ++ * Verify the chanspec is using a legal set field values, i.e. that the chanspec ++ * specified a band, bw, ctl_sb and channel and that the combination could be ++ * legal given some set of circumstances. ++ * ++ * @param chanspec input chanspec to verify ++ * ++ * @return TRUE if the chanspec is malformed, FALSE if it looks good. ++ */ ++extern bool wf_chspec_malformed(chanspec_t chanspec); ++ ++/** ++ * Verify the chanspec specifies a valid channel according to 802.11. ++ * ++ * @param chanspec input chanspec to verify ++ * ++ * @return TRUE if the chanspec is a valid 802.11 channel ++ */ ++extern bool wf_chspec_valid(chanspec_t chanspec); ++ ++/** ++ * Return the primary (control) channel. ++ * ++ * This function returns the channel number of the primary 20MHz channel. For ++ * 20MHz channels this is just the channel number. For 40MHz or wider channels ++ * it is the primary 20MHz channel specified by the chanspec. ++ * ++ * @param chspec input chanspec ++ * ++ * @return Returns the channel number of the primary 20MHz channel ++ */ ++extern uint8 wf_chspec_ctlchan(chanspec_t chspec); ++ ++/** ++ * Return the primary (control) chanspec. ++ * ++ * This function returns the chanspec of the primary 20MHz channel. For 20MHz ++ * channels this is just the chanspec. For 40MHz or wider channels it is the ++ * chanspec of the primary 20MHZ channel specified by the chanspec. ++ * ++ * @param chspec input chanspec ++ * ++ * @return Returns the chanspec of the primary 20MHz channel ++ */ ++extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec); ++ ++/** ++ * Return a channel number corresponding to a frequency. ++ * ++ * Return the channel number for a given frequency and base frequency. ++ * The returned channel number is relative to the given base frequency. ++ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for ++ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz. ++ * ++ * Frequency is specified in MHz. ++ * The base frequency is specified as (start_factor * 500 kHz). ++ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for ++ * 2.4 GHz and 5 GHz bands. ++ * ++ * The returned channel will be in the range [1, 14] in the 2.4 GHz band ++ * and [0, 200] otherwise. ++ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the ++ * frequency is not a 2.4 GHz channel, or if the frequency is not and even ++ * multiple of 5 MHz from the base frequency to the base plus 1 GHz. ++ * ++ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 ++ * ++ * @param freq frequency in MHz ++ * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz ++ * ++ * @return Returns a channel number ++ * ++ * @see WF_CHAN_FACTOR_2_4_G ++ * @see WF_CHAN_FACTOR_5_G ++ */ ++extern int wf_mhz2channel(uint freq, uint start_factor); ++ ++/** ++ * Return the center frequency in MHz of the given channel and base frequency. ++ * ++ * Return the center frequency in MHz of the given channel and base frequency. ++ * The channel number is interpreted relative to the given base frequency. ++ * ++ * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise. ++ * The base frequency is specified as (start_factor * 500 kHz). ++ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for ++ * 2.4 GHz and 5 GHz bands. ++ * The channel range of [1, 14] is only checked for a start_factor of ++ * WF_CHAN_FACTOR_2_4_G (4814). ++ * Odd start_factors produce channels on .5 MHz boundaries, in which case ++ * the answer is rounded down to an integral MHz. ++ * -1 is returned for an out of range channel. ++ * ++ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 ++ * ++ * @param channel input channel number ++ * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz ++ * ++ * @return Returns a frequency in MHz ++ * ++ * @see WF_CHAN_FACTOR_2_4_G ++ * @see WF_CHAN_FACTOR_5_G ++ */ ++extern int wf_channel2mhz(uint channel, uint start_factor); ++ ++#endif /* _bcmwifi_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/compvers.sh b/drivers/bcmdrivers/gmac/src/include/compvers.sh +new file mode 100755 +index 0000000..3f6fd6a +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/compvers.sh +@@ -0,0 +1,122 @@ ++#!/bin/bash ++# ++# Given a list of components, generate _version.h ++# from version.h.in in 's directory ++# ++# Copyright 2005, Broadcom, Inc. ++# ++# $Id: compvers.sh 281527 2011-09-02 17:12:53Z $ ++# ++ ++# Optional argument ++ACTION=$1 ++[ -n "$VERBOSE" ] && export VERBOSE ++ ++SRCBASE=.. ++ ++# List of components ++# TODO: In the long term component versioning model, following list ++# TODO: or table of components will come from a central file ++COMPONENTS=( \ ++ upnp \ ++ phy \ ++ router \ ++ wps \ ++) ++ ++# Component dirs. Need one entry for each of above COMPONENTS ++COMPONENT_DIR_upnp=${SRCBASE}/router/libupnp/include ++COMPONENT_DIR_phy=${SRCBASE}/wl/phy ++COMPONENT_DIR_router=${SRCBASE}/router/shared ++COMPONENT_DIR_wps=${SRCBASE}/wps/common/include ++ ++# For a given component, query automerger for a different ++# path than COMPONENT_DIR_. ++# Force router component to be pointing to local branch or tag. ++COMPONENT_QUERY_router=src_force_local_component ++ ++ ++ ++# ===== DO NOT CHANGE ANYTHING BELOW THIS LINE ===== ++ ++NULL=/dev/null ++MKCOMPVER=${SRCBASE}/tools/release/mkversion.sh ++MERGERLOG=${SRCBASE}/../merger_sources.log ++ ++# TODO: Post svn transition, network paths will be taken away ++GETCOMPVER=getcompver.py ++GETCOMPVER_NET=/projects/hnd_software/gallery/src/tools/build/$GETCOMPVER ++GETCOMPVER_NET_WIN=Z:${GETCOMPVER_NET} ++ ++# ++# If there is a local copy GETCOMPVER use it ahead of network copy ++# ++if [ -s "$GETCOMPVER" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER" ++elif [ -s "${SRCBASE}/../src/tools/build/$GETCOMPVER" ]; then ++ GETCOMPVER_PATH="${SRCBASE}/../src/tools/build/$GETCOMPVER" ++elif [ -s "$GETCOMPVER_NET" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER_NET" ++elif [ -s "$GETCOMPVER_NET_WIN" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER_NET_WIN" ++fi ++ ++# ++# If $GETCOMPVER isn't found, fetch it from SVN ++# (this is very rare) ++# ++if [ ! -s "$GETCOMPVER_PATH" ]; then ++ svn export -q \ ++ ^/proj/trunk/src/tools/build/${GETCOMPVER} \ ++ ${GETCOMPVER} 2> $NULL ++ GETCOMPVER_PATH=$GETCOMPVER ++fi ++ ++# ++# Now walk through each specified component to generate its ++# component_version.h file from version.h.in template ++# ++for component in ${COMPONENTS[*]} ++do ++ # Get relative path of component from current dir ++ tmp="COMPONENT_DIR_$component" ++ eval rel_path=\$$tmp ++ ++ # Get query path for component ++ tmp="COMPONENT_QUERY_$component" ++ eval query_path=\$$tmp ++ ++ if [ ! -d "$rel_path" ]; then ++ continue ++ fi ++ ++ if [ "$query_path" != "" ]; then ++ abs_path=$(echo $query_path | sed -e "s%\.\.%src%g") ++ else ++ abs_path=$(echo $rel_path | sed -e "s%\.\.%src%g") ++ fi ++ ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: python $GETCOMPVER_PATH $MERGERLOG $abs_path" ++ ++ tag=$(python $GETCOMPVER_PATH $MERGERLOG $abs_path 2> $NULL | sed -e 's/[[:space:]]*//g') ++ ++ template=$rel_path/version.h.in ++ verfile=$rel_path/${component}_version.h ++ ++ if [ "$ACTION" == "clean" ]; then ++ rm -fv $verfile ++ continue ++ fi ++ ++ # MKCOMPVER always has defaults if tag isn't set correctly ++ if [ ! -f "$verfile" -o "$FORCE" != "" ]; then ++ echo "" ++ echo ">>> Generate $abs_path/${component}_version.h from $tag" ++ ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: bash $MKCOMPVER $template $verfile $tag" ++ ++ bash $MKCOMPVER $template $verfile $tag ++ fi ++done +diff --git a/drivers/bcmdrivers/gmac/src/include/ctf/ctf_cfg.h b/drivers/bcmdrivers/gmac/src/include/ctf/ctf_cfg.h +new file mode 100755 +index 0000000..a44e08b +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/ctf/ctf_cfg.h +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: $ ++ */ ++ ++#ifndef _CTF_CFG_H_ ++#define _CTF_CFG_H_ ++ ++#define NETLINK_CTF 20 ++ ++#define SUCCESS 0 ++#define FAILURE -1 ++ ++#define CTFCFG_MAX_SIZE sizeof(ctf_cfg_request_t) ++#define CTFCFG_MAX_ARG_SIZE 1024 ++ ++#define CTFCFG_CMD_SUSPEND 1 ++#define CTFCFG_CMD_RESUME 2 ++#define CTFCFG_CMD_TUPLE_VALID 3 ++#define CTFCFG_CMD_DEFAULT_FWD_GET 4 ++#define CTFCFG_CMD_DEFAULT_FWD_SET 5 ++ ++#define CTFCFG_STATUS_SUCCESS 1 ++#define CTFCFG_STATUS_FAILURE 2 ++#define CTFCFG_STATUS_TUPLE_INVALID 3 ++#define CTFCFG_STATUS_FLOW_ALREADY_SUSPENDED 4 ++#define CTFCFG_STATUS_FLOW_NOT_SUSPENDED 5 ++#define CTFCFG_STATUS_DEFAULT_FWD_INVALID 6 ++#define CTFCFG_STATUS_PROTOCOL_NOT_SUPPORTED 7 ++ ++typedef union ++{ ++ struct in_addr ip_v4; ++ struct in6_addr ip_v6; ++} ip_address_t; ++ ++typedef struct ++{ ++ int family; ++ ++ ip_address_t src_addr; ++ ip_address_t dst_addr; ++ ++ uint16_t src_port; ++ uint16_t dst_port; ++ ++ uint8_t protocol; ++} ctf_tuple_t; ++ ++typedef enum { ++ CTF_FWD_FASTPATH, ++ CTF_FWD_HOST, /* i.e. send to network stack */ ++} ctf_fwd_t; ++ ++typedef struct ctf_cfg_request ++{ ++ uint32_t command_id; ++ uint32_t status; /* Command status */ ++ uint32_t size; /* Size of the argument */ ++ uint8_t arg[CTFCFG_MAX_ARG_SIZE]; ++} ctf_cfg_request_t; ++ ++#endif /* _CTF_CFG_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/ctf/hndctf.h b/drivers/bcmdrivers/gmac/src/include/ctf/hndctf.h +new file mode 100755 +index 0000000..e4385dd +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/ctf/hndctf.h +@@ -0,0 +1,299 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: hndctf.h 418247 2013-08-14 11:16:42Z $ ++ */ ++ ++#ifndef _HNDCTF_H_ ++#define _HNDCTF_H_ ++ ++#include ++#include ++#include ++#include ++/* ++ * Define to enable couting VLAN tx and rx packets and bytes. This could be ++ * disabled if the functionality has impact on performance. ++ */ ++#define CTFVLSTATS ++ ++#define CTF_ENAB(ci) (((ci) != NULL) && (ci)->_ctf) ++ ++#define CTF_ACTION_TAG (1 << 0) ++#define CTF_ACTION_UNTAG (1 << 1) ++#define CTF_ACTION_SNAT (1 << 2) ++#define CTF_ACTION_DNAT (1 << 3) ++#define CTF_ACTION_SUSPEND (1 << 4) ++#define CTF_ACTION_TOS (1 << 5) ++#define CTF_ACTION_MARK (1 << 6) ++#define CTF_ACTION_BYTECNT (1 << 7) ++#define CTF_ACTION_PPPOE_ADD (1 << 8) ++#define CTF_ACTION_PPPOE_DEL (1 << 9) ++ ++#define CTF_SUSPEND_TCP (1 << 0) ++#define CTF_SUSPEND_UDP (1 << 1) ++ ++#define ctf_attach(osh, n, m, c, a) \ ++ (ctf_attach_fn ? ctf_attach_fn(osh, n, m, c, a) : NULL) ++#define ctf_forward(ci, p, d) (ci)->fn.forward(ci, p, d) ++#define ctf_isenabled(ci, d) (CTF_ENAB(ci) ? (ci)->fn.isenabled(ci, d) : FALSE) ++#define ctf_isbridge(ci, d) (CTF_ENAB(ci) ? (ci)->fn.isbridge(ci, d) : FALSE) ++#define ctf_enable(ci, d, e, b) (CTF_ENAB(ci) ? (ci)->fn.enable(ci, d, e, b) : BCME_OK) ++#define ctf_brc_add(ci, b) (CTF_ENAB(ci) ? (ci)->fn.brc_add(ci, b) : BCME_OK) ++#define ctf_brc_delete(ci, e) (CTF_ENAB(ci) ? (ci)->fn.brc_delete(ci, e) : BCME_OK) ++#define ctf_brc_update(ci, b) (CTF_ENAB(ci) ? (ci)->fn.brc_update(ci, b) : BCME_OK) ++#define ctf_brc_lkup(ci, e) (CTF_ENAB(ci) ? (ci)->fn.brc_lkup(ci, e) : NULL) ++#define ctf_brc_release(ci, b) do { if (CTF_ENAB(ci)) (ci)->fn.brc_release(ci, b); } while (0) ++#define ctf_ipc_add(ci, i, v6) (CTF_ENAB(ci) ? (ci)->fn.ipc_add(ci, i, v6) : BCME_OK) ++#define ctf_ipc_delete(ci, i, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_delete(ci, i, v6) : BCME_OK) ++#define ctf_ipc_count_get(ci, i) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_count_get(ci, i) : BCME_OK) ++#define ctf_ipc_delete_multi(ci, i, im, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_delete_multi(ci, i, im, v6) : BCME_OK) ++#define ctf_ipc_delete_range(ci, s, e, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_delete_range(ci, s, e, v6) : BCME_OK) ++#define ctf_ipc_action(ci, s, e, am, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_action(ci, s, e, am, v6) : BCME_OK) ++#define ctf_ipc_lkup(ci, i, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_lkup(ci, i, v6) : NULL) ++#ifdef CTF_IPV6 ++#define ctf_ipc_lkup_l4proto(ci, iph, l4p) (CTF_ENAB(ci) && (ci)->fn.ipc_lkup_l4proto? \ ++ (ci)->fn.ipc_lkup_l4proto((uint8 *)iph, l4p) : NULL) ++#else ++#define ctf_ipc_lkup_l4proto(ci, iph, l4p) (NULL) ++#endif /* CTF_IPV6 */ ++#define ctf_ipc_release(ci, i) do { if (CTF_ENAB(ci)) (ci)->fn.ipc_release(ci, i); } while (0) ++#define ctf_dev_register(ci, d, b) \ ++ (CTF_ENAB(ci) ? (ci)->fn.dev_register(ci, d, b) : BCME_OK) ++#define ctf_dev_vlan_add(ci, d, vid, vd) \ ++ (CTF_ENAB(ci) ? (ci)->fn.dev_vlan_add(ci, d, vid, vd) : BCME_OK) ++#define ctf_dev_vlan_delete(ci, d, vid) \ ++ (CTF_ENAB(ci) ? (ci)->fn.dev_vlan_delete(ci, d, vid) : BCME_OK) ++#define ctf_detach(ci) if (CTF_ENAB(ci)) (ci)->fn.detach(ci) ++#define ctf_dump(ci, b) if (CTF_ENAB(ci)) (ci)->fn.dump(ci, b) ++#define ctf_cfg_req_process(ci, c) if (CTF_ENAB(ci)) (ci)->fn.cfg_req_process(ci, c) ++#define ctf_dev_unregister(ci, d) if (CTF_ENAB(ci)) (ci)->fn.dev_unregister(ci, d) ++#ifdef BCMFA ++#define ctf_fa_register(ci, d, i) if (CTF_ENAB(ci)) (ci)->fn.fa_register(ci, d, i) ++#define ctf_live(ci, i, v6) (CTF_ENAB(ci) ? (ci)->fn.live(ci, i, v6) : FALSE) ++#endif /* BCMFA */ ++ ++#define CTFCNTINCR(s) ((s)++) ++#define CTFCNTADD(s, c) ((s) += (c)) ++ ++#define PPPOE_ETYPE_OFFSET 12 ++#define PPPOE_VER_OFFSET 14 ++#define PPPOE_SESID_OFFSET 16 ++#define PPPOE_LEN_OFFSET 18 ++ ++#define PPPOE_HLEN 20 ++#define PPPOE_PPP_HLEN 8 ++ ++#define PPPOE_PROT_PPP 0x0021 ++#define PPPOE_PROT_PPP_IP6 0x0057 ++ ++ ++typedef struct ctf_pub ctf_t; ++typedef struct ctf_brc ctf_brc_t; ++typedef struct ctf_ipc ctf_ipc_t; ++typedef struct ctf_conn_tuple ctf_conn_tuple_t; ++typedef struct ctf_brc_hot ctf_brc_hot_t; ++ ++typedef void (*ctf_detach_cb_t)(ctf_t *ci, void *arg); ++typedef ctf_t * (*ctf_attach_t)(osl_t *osh, uint8 *name, uint32 *msg_level, ++ ctf_detach_cb_t cb, void *arg); ++typedef void (*ctf_detach_t)(ctf_t *ci); ++typedef int32 (*ctf_forward_t)(ctf_t *ci, void *p, void *rxifp); ++typedef bool (*ctf_isenabled_t)(ctf_t *ci, void *dev); ++typedef bool (*ctf_isbridge_t)(ctf_t *ci, void *dev); ++typedef int32 (*ctf_brc_add_t)(ctf_t *ci, ctf_brc_t *brc); ++typedef int32 (*ctf_brc_delete_t)(ctf_t *ci, uint8 *ea); ++typedef int32 (*ctf_brc_update_t)(ctf_t *ci, ctf_brc_t *brc); ++typedef ctf_brc_t * (*ctf_brc_lkup_t)(ctf_t *ci, uint8 *da); ++typedef void (*ctf_brc_release_t)(ctf_t *ci, ctf_brc_t *brc); ++typedef int32 (*ctf_ipc_add_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); ++typedef int32 (*ctf_ipc_delete_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); ++typedef int32 (*ctf_ipc_count_get_t)(ctf_t *ci); ++typedef int32 (*ctf_ipc_delete_multi_t)(ctf_t *ci, ctf_ipc_t *ipc, ++ ctf_ipc_t *ipcm, bool v6); ++typedef int32 (*ctf_ipc_delete_range_t)(ctf_t *ci, ctf_ipc_t *start, ++ ctf_ipc_t *end, bool v6); ++typedef int32 (*ctf_ipc_action_t)(ctf_t *ci, ctf_ipc_t *start, ++ ctf_ipc_t *end, uint32 action_mask, bool v6); ++typedef ctf_ipc_t * (*ctf_ipc_lkup_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); ++typedef uint8 * (*ctf_ipc_lkup_l4proto_t)(uint8 *iph, uint8 *proto_num); ++typedef void (*ctf_ipc_release_t)(ctf_t *ci, ctf_ipc_t *ipc); ++typedef int32 (*ctf_enable_t)(ctf_t *ci, void *dev, bool enable, ctf_brc_hot_t **brc_hot); ++typedef int32 (*ctf_dev_register_t)(ctf_t *ci, void *dev, bool br); ++typedef void (*ctf_dev_unregister_t)(ctf_t *ci, void *dev); ++typedef int32 (*ctf_dev_vlan_add_t)(ctf_t *ci, void *dev, uint16 vid, void *vldev); ++typedef int32 (*ctf_dev_vlan_delete_t)(ctf_t *ci, void *dev, uint16 vid); ++typedef void (*ctf_dump_t)(ctf_t *ci, struct bcmstrbuf *b); ++typedef void (*ctf_cfg_req_process_t)(ctf_t *ci, void *arg); ++#ifdef BCMFA ++typedef int (*ctf_fa_cb_t)(void *dev, ctf_ipc_t *ipc, bool v6, int cmd); ++ ++typedef int32 (*ctf_fa_register_t)(ctf_t *ci, ctf_fa_cb_t facb, void *fa); ++typedef void (*ctf_live_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); ++#endif /* BCMFA */ ++ ++struct ctf_brc_hot { ++ struct ether_addr ea; /* Dest address */ ++ ctf_brc_t *brcp; /* BRC entry corresp to dest mac */ ++}; ++ ++typedef struct ctf_fn { ++ ctf_detach_t detach; ++ ctf_forward_t forward; ++ ctf_isenabled_t isenabled; ++ ctf_isbridge_t isbridge; ++ ctf_brc_add_t brc_add; ++ ctf_brc_delete_t brc_delete; ++ ctf_brc_update_t brc_update; ++ ctf_brc_lkup_t brc_lkup; ++ ctf_brc_release_t brc_release; ++ ctf_ipc_add_t ipc_add; ++ ctf_ipc_delete_t ipc_delete; ++ ctf_ipc_count_get_t ipc_count_get; ++ ctf_ipc_delete_multi_t ipc_delete_multi; ++ ctf_ipc_delete_range_t ipc_delete_range; ++ ctf_ipc_action_t ipc_action; ++ ctf_ipc_lkup_t ipc_lkup; ++ ctf_ipc_lkup_l4proto_t ipc_lkup_l4proto; ++ ctf_ipc_release_t ipc_release; ++ ctf_enable_t enable; ++ ctf_dev_register_t dev_register; ++ ctf_dev_unregister_t dev_unregister; ++ ctf_detach_cb_t detach_cb; ++ void *detach_cb_arg; ++ ctf_dev_vlan_add_t dev_vlan_add; ++ ctf_dev_vlan_delete_t dev_vlan_delete; ++ ctf_dump_t dump; ++ ctf_cfg_req_process_t cfg_req_process; ++#ifdef BCMFA ++ ctf_fa_register_t fa_register; ++ ctf_live_t live; ++#endif /* BCMFA */ ++} ctf_fn_t; ++ ++struct ctf_pub { ++ bool _ctf; /* Global CTF enable/disable */ ++ ctf_fn_t fn; /* Exported functions */ ++ void *nl_sk; /* Netlink socket */ ++ uint32 ipc_suspend; /* Global IPC suspend flags */ ++}; ++ ++struct ctf_mark; /* Connection Mark */ ++ ++struct ctf_brc { ++ struct ctf_brc *next; /* Pointer to brc entry */ ++ struct ether_addr dhost; /* MAC addr of host */ ++ uint16 vid; /* VLAN id to use on txif */ ++ void *txifp; /* Interface connected to host */ ++ uint32 action; /* Tag or untag the frames */ ++ uint32 live; /* Counter used to expire the entry */ ++ uint32 hits; /* Num frames matching brc entry */ ++ uint64 *bytecnt_ptr; /* Pointer to the byte counter */ ++}; ++ ++#ifdef CTF_IPV6 ++#define IPADDR_U32_SZ (IPV6_ADDR_LEN / sizeof(uint32)) ++#else ++#define IPADDR_U32_SZ 1 ++#endif ++ ++struct ctf_conn_tuple { ++ uint32 sip[IPADDR_U32_SZ], dip[IPADDR_U32_SZ]; ++ uint16 sp, dp; ++ uint8 proto; ++}; ++ ++typedef struct ctf_nat { ++ uint32 ip; ++ uint16 port; ++} ctf_nat_t; ++ ++#ifdef BCMFA ++#define CTF_FA_PEND_ADD_ENTRY 0x1 ++#define CTF_FA_ADD_ISPEND(ipc) ((ipc)->flags & CTF_FA_PEND_ADD_ENTRY) ++#define CTF_FA_SET_ADD_PEND(ipc) ((ipc)->flags |= CTF_FA_PEND_ADD_ENTRY) ++#define CTF_FA_CLR_ADD_PEND(ipc) ((ipc)->flags &= ~(CTF_FA_PEND_ADD_ENTRY)) ++#endif /* BCMFA */ ++ ++struct ctf_ipc { ++ struct ctf_ipc *next; /* Pointer to ipc entry */ ++ ctf_conn_tuple_t tuple; /* Tuple to uniquely id the flow */ ++ uint16 vid; /* VLAN id to use on txif */ ++ struct ether_addr dhost; /* Destination MAC address */ ++ struct ether_addr shost; /* Source MAC address */ ++ void *txif; /* Target interface to send */ ++ uint32 action; /* NAT and/or VLAN actions */ ++ ctf_brc_t *brcp; /* BRC entry corresp to source mac */ ++ uint32 live; /* Counter used to expire the entry */ ++ struct ctf_nat nat; /* Manip data for SNAT, DNAT */ ++ struct ether_addr sa; /* MAC address of sender */ ++ uint8 tos; /* IPv4 tos or IPv6 traff class excl ECN */ ++ uint16 pppoe_sid; /* PPPOE session to use */ ++ void *ppp_ifp; /* PPP interface handle */ ++ uint32 hits; /* Num frames matching ipc entry */ ++ uint64 *bytecnt_ptr; /* Pointer to the byte counter */ ++ struct ctf_mark mark; /* Mark value to use for the connection */ ++#ifdef BCMFA ++ void *rxif; /* Receive interface */ ++ void *pkt; /* Received packet */ ++ uint8 flags; /* Flags for multiple purpose */ ++#endif /* BCMFA */ ++}; ++ ++extern ctf_t *ctf_kattach(osl_t *osh, uint8 *name); ++extern void ctf_kdetach(ctf_t *kci); ++extern ctf_attach_t ctf_attach_fn; ++extern ctf_t *_ctf_attach(osl_t *osh, uint8 *name, uint32 *msg_level, ++ ctf_detach_cb_t cb, void *arg); ++extern ctf_t *kcih; ++ ++/* Hot bridge cache lkup */ ++#define MAXBRCHOT 4 ++#define MAXBRCHOTIF 4 ++#define CTF_BRC_HOT_HASH(da) ((((uint8 *)da)[4] ^ ((uint8 *)da)[5]) & (MAXBRCHOT - 1)) ++#define CTF_HOTBRC_CMP(hbrc, da, rxifp) \ ++({ \ ++ ctf_brc_hot_t *bh = (hbrc) + CTF_BRC_HOT_HASH(da); \ ++ ((eacmp((bh)->ea.octet, (da)) == 0) && (bh->brcp->txifp != (rxifp))); \ ++}) ++ ++/* Header prep for packets matching hot bridge cache entry */ ++#define CTF_HOTBRC_L2HDR_PREP(osh, hbrc, prio, data, p) \ ++do { \ ++ uint8 *l2h; \ ++ ctf_brc_hot_t *bh = (hbrc) + CTF_BRC_HOT_HASH(data); \ ++ ASSERT(*(uint16 *)((data) + VLAN_TPID_OFFSET) == HTON16(ETHER_TYPE_8021Q)); \ ++ if (bh->brcp->action & CTF_ACTION_UNTAG) { \ ++ /* Remove vlan header */ \ ++ l2h = PKTPULL((osh), (p), VLAN_TAG_LEN); \ ++ ether_rcopy(l2h - VLAN_TAG_LEN + ETHER_ADDR_LEN, \ ++ l2h + ETHER_ADDR_LEN); \ ++ ether_rcopy(l2h - VLAN_TAG_LEN, l2h); \ ++ } else { \ ++ /* Update vlan header */ \ ++ l2h = (data); \ ++ *(uint16 *)(l2h + VLAN_TCI_OFFSET) = \ ++ HTON16((prio) << VLAN_PRI_SHIFT | bh->brcp->vid); \ ++ } \ ++} while (0) ++ ++ ++#endif /* _HNDCTF_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/epivers.h b/drivers/bcmdrivers/gmac/src/include/epivers.h +new file mode 100644 +index 0000000..6b067dd +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/epivers.h +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $ ++*/ ++ ++#ifndef _epivers_h_ ++#define _epivers_h_ ++ ++#define EPI_MAJOR_VERSION 6 ++ ++#define EPI_MINOR_VERSION 30 ++ ++#define EPI_RC_NUMBER 40 ++ ++#define EPI_INCREMENTAL_NUMBER 0 ++ ++#define EPI_BUILD_NUMBER 2 ++ ++#define EPI_VERSION 6, 30, 40, 0 ++ ++#define EPI_VERSION_NUM 0x061e2800 ++ ++#define EPI_VERSION_DEV 6.30.40 ++ ++/* Driver Version String, ASCII, 32 chars max */ ++#ifdef WLTEST ++#define EPI_VERSION_STR "6.30.40 (TOB) (r WLTEST)" ++#else ++#define EPI_VERSION_STR "6.30.40 (TOB) (r)" ++#endif ++ ++#endif /* _epivers_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/epivers.h.in b/drivers/bcmdrivers/gmac/src/include/epivers.h.in +new file mode 100755 +index 0000000..790f8d4 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/epivers.h.in +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $ ++ * ++*/ ++ ++#ifndef _epivers_h_ ++#define _epivers_h_ ++ ++#define EPI_MAJOR_VERSION @EPI_MAJOR_VERSION@ ++ ++#define EPI_MINOR_VERSION @EPI_MINOR_VERSION@ ++ ++#define EPI_RC_NUMBER @EPI_RC_NUMBER@ ++ ++#define EPI_INCREMENTAL_NUMBER @EPI_INCREMENTAL_NUMBER@ ++ ++#define EPI_BUILD_NUMBER @EPI_BUILD_NUMBER@ ++ ++#define EPI_VERSION @EPI_VERSION@ ++ ++#define EPI_VERSION_NUM @EPI_VERSION_NUM@ ++ ++#define EPI_VERSION_DEV @EPI_VERSION_DEV@ ++ ++/* Driver Version String, ASCII, 32 chars max */ ++#ifdef WLTEST ++#define EPI_VERSION_STR "@EPI_VERSION_STR@@EPI_VERSION_TYPE@ (@VC_VERSION_NUM@ WLTEST)" ++#else ++#define EPI_VERSION_STR "@EPI_VERSION_STR@@EPI_VERSION_TYPE@ (@VC_VERSION_NUM@)" ++#endif ++ ++#endif /* _epivers_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/epivers.sh b/drivers/bcmdrivers/gmac/src/include/epivers.sh +new file mode 100755 +index 0000000..4424501 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/epivers.sh +@@ -0,0 +1,295 @@ ++#! /bin/bash ++# ++# Create the epivers.h file from epivers.h.in ++# ++# Epivers.h generation mechanism supports svn based checkouts ++# ++# $Id: epivers.sh 299409 2011-11-30 00:52:43Z $ ++# ++# GetCompVer.py return value and action needed ++# i. trunk => use current date as version string ++# ii. local => use SVNURL expanded by HeadURL keyword ++# iii. => use it as as is ++# (some components can override and say give me native ver) ++# iv. empty => ++# a) If TAG is specified use it ++# a) If no TAG is specified use date ++# ++ ++# If the version header file already exists, increment its build number. ++# Otherwise, create a new file. ++if [ -f epivers.h ]; then ++ ++ # If REUSE_VERSION is set, epivers iteration is not incremented ++ # This can be used precommit and continuous integration projects ++ if [ -n "$REUSE_VERSION" ]; then ++ echo "Previous epivers.h exists. Skipping version increment" ++ exit 0 ++ fi ++ ++ build=`grep EPI_BUILD_NUMBER epivers.h | sed -e "s,.*BUILD_NUMBER[ ]*,,"` ++ build=`expr ${build} + 1` ++ echo build=${build} ++ sed -e "s,.*_BUILD_NUMBER.*,#define EPI_BUILD_NUMBER ${build}," \ ++ < epivers.h > epivers.h.new ++ mv epivers.h epivers.h.prev ++ mv epivers.h.new epivers.h ++ exit 0 ++ ++else # epivers.h doesn't exist ++ ++ NULL="/dev/null" ++ svncmd="svn --non-interactive" ++ ++ # Check for the in file, if not there we're in the wrong directory ++ if [ ! -f epivers.h.in ]; then ++ echo "ERROR: No epivers.h.in found" ++ exit 1 ++ fi ++ ++ # Following SVNURL should be expanded on checkout ++ SVNURL='$HeadURL: http://svn.sj.broadcom.com/svn/wlansvn/users/kenlo/northstar/AARDVARK_TWIG_6_30_40/src/include/epivers.sh $' ++ ++ # If SVNURL isn't expanded, extract it from svn info ++ if echo "$SVNURL" | grep -vq '$.*HeadURL.*epivers.sh.*$'; then ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: SVN URL wasn't expanded. Getting it from svn info" ++ SVNURL=$($svncmd info epivers.sh 2> $NULL | egrep "^URL:") ++ fi ++ ++ if echo "${TAG}" | grep -q "_BRANCH_\|_TWIG_"; then ++ branchtag=$TAG ++ else ++ branchtag="" ++ fi ++ ++ # If this is a tagged build, use the tag to supply the numbers ++ # Tag should be in the form ++ # _REL__ ++ # or ++ # _REL___RC ++ # or ++ # _REL___RC_ ++ ++ SRCBASE=.. ++ MERGERLOG=${SRCBASE}/../merger_sources.log ++ GETCOMPVER=getcompver.py ++ GETCOMPVER_NET=/projects/hnd_software/gallery/src/tools/build/$GETCOMPVER ++ GETCOMPVER_NET_WIN=Z:${GETCOMPVER_NET} ++ ++ # ++ # If there is a local copy GETCOMPVER use it ahead of network copy ++ # ++ if [ -s "$GETCOMPVER" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER" ++ elif [ -s "${SRCBASE}/../src/tools/build/$GETCOMPVER" ]; then ++ GETCOMPVER_PATH="${SRCBASE}/../src/tools/build/$GETCOMPVER" ++ elif [ -s "$GETCOMPVER_NET" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER_NET" ++ elif [ -s "$GETCOMPVER_NET_WIN" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER_NET_WIN" ++ fi ++ ++ # ++ # If $GETCOMPVER isn't found, fetch it from SVN ++ # (this should be very rare) ++ # ++ if [ ! -s "$GETCOMPVER_PATH" ]; then ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: Fetching $GETCOMPVER from trunk" ++ ++ $svncmd export -q \ ++ ^/proj/trunk/src/tools/build/${GETCOMPVER} \ ++ ${GETCOMPVER} 2> $NULL ++ ++ GETCOMPVER_PATH=$GETCOMPVER ++ fi ++ ++ # Now get tag for src/include from automerger log ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: python $GETCOMPVER_PATH $MERGERLOG src/include" ++ ++ COMPTAG=$(python $GETCOMPVER_PATH $MERGERLOG src/include 2> $NULL | sed -e 's/[[:space:]]*//g') ++ ++ echo "DBG: Component Tag String Derived = $COMPTAG" ++ ++ # Process COMPTAG values ++ # Rule: ++ # If trunk is returned, use date as component tag ++ # If LOCAL_COMPONENT is returned, use SVN URL to get native tag ++ # If component is returned or empty, assign it to SVNTAG ++ # GetCompVer.py return value and action needed ++ # i. trunk => use current date as version string ++ # ii. local => use SVNURL expanded by HeadURL keyword ++ # iii. => use it as as is ++ # iv. empty => ++ # a) If TAG is specified use it ++ # a) If no TAG is specified use SVNURL from HeadURL ++ ++ SVNURL_VER=false ++ ++ if [ "$COMPTAG" == "" ]; then ++ SVNURL_VER=true ++ elif [ "$COMPTAG" == "LOCAL_COMPONENT" ]; then ++ SVNURL_VER=true ++ elif [ "$COMPTAG" == "trunk" ]; then ++ SVNTAG=$(date '+TRUNKCOMP_REL_%Y_%m_%d') ++ else ++ SVNTAG=$COMPTAG ++ fi ++ ++ # Given SVNURL path conventions or naming conventions, derive SVNTAG ++ # TO-DO: SVNTAG derivation logic can move to a central common API ++ # TO-DO: ${SRCBASE}/tools/build/svnurl2tag.sh ++ if [ "$SVNURL_VER" == "true" ]; then ++ case "${SVNURL}" in ++ */branches/*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%.*/branches/\(.*\)/src.*%\1%g' | xargs printf "%s") ++ ;; ++ *_BRANCH_*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%/%\n%g' | egrep _BRANCH_ | xargs printf "%s") ++ ;; ++ *_TWIG_*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%/%\n%g' | egrep _TWIG_ | xargs printf "%s") ++ ;; ++ */tags/*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%.*/tags/.*/\(.*\)/src.*%\1%g' | xargs printf "%s") ++ ;; ++ *_REL_*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%/%\n%g' | egrep _REL_ | xargs printf "%s") ++ ;; ++ */trunk/*) ++ SVNTAG=$(date '+TRUNKURL_REL_%Y_%m_%d') ++ ;; ++ *) ++ SVNTAG=$(date '+OTHER_REL_%Y_%m_%d') ++ ;; ++ esac ++ echo "DBG: Native Tag String Derived from URL: $SVNTAG" ++ else ++ echo "DBG: Native Tag String Derived: $SVNTAG" ++ fi ++ ++ TAG=${SVNTAG} ++ ++ # Normalize the branch name portion to "D11" in case it has underscores in it ++ branch_name=`expr match "$TAG" '\(.*\)_\(BRANCH\|TWIG\|REL\)_.*'` ++ TAG=`echo $TAG | sed -e "s%^$branch_name%D11%"` ++ ++ # Split the tag into an array on underbar or whitespace boundaries. ++ IFS="_ " tag=(${TAG}) ++ unset IFS ++ ++ tagged=1 ++ if [ ${#tag[*]} -eq 0 ]; then ++ tag=(`date '+TOT REL %Y %m %d 0 %y'`); ++ # reconstruct a TAG from the date ++ TAG=${tag[0]}_${tag[1]}_${tag[2]}_${tag[3]}_${tag[4]}_${tag[5]} ++ tagged=0 ++ fi ++ ++ # Allow environment variable to override values. ++ # Missing values default to 0 ++ # ++ maj=${EPI_MAJOR_VERSION:-${tag[2]:-0}} ++ min=${EPI_MINOR_VERSION:-${tag[3]:-0}} ++ rcnum=${EPI_RC_NUMBER:-${tag[4]:-0}} ++ ++ # If increment field is 0, set it to date suffix if on TOB ++ if [ -n "$branchtag" ]; then ++ [ "${tag[5]:-0}" -eq 0 ] && echo "Using date suffix for incr" ++ today=`date '+%Y%m%d'` ++ incremental=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-${today:-0}}} ++ else ++ incremental=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-0}} ++ fi ++ origincr=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-0}} ++ build=${EPI_BUILD_NUMBER:-0} ++ ++ # Strip 'RC' from front of rcnum if present ++ rcnum=${rcnum/#RC/} ++ ++ # strip leading zero off the number (otherwise they look like octal) ++ maj=${maj/#0/} ++ min=${min/#0/} ++ rcnum=${rcnum/#0/} ++ incremental=${incremental/#0/} ++ origincr=${origincr/#0/} ++ build=${build/#0/} ++ ++ # some numbers may now be null. replace with with zero. ++ maj=${maj:-0} ++ min=${min:-0} ++ ++ rcnum=${rcnum:-0} ++ incremental=${incremental:-0} ++ origincr=${origincr:-0} ++ build=${build:-0} ++ ++ if [ ${tagged} -eq 1 ]; then ++ # vernum is 32chars max ++ vernum=`printf "0x%02x%02x%02x%02x" ${maj} ${min} ${rcnum} ${origincr}` ++ else ++ vernum=`printf "0x00%02x%02x%02x" ${tag[7]} ${min} ${rcnum}` ++ fi ++ ++ # make sure the size of vernum is under 32 bits. ++ # Otherwise, truncate. The string will keep full information. ++ vernum=${vernum:0:10} ++ ++ # build the string directly from the tag, irrespective of its length ++ # remove the name , the tag type, then replace all _ by . ++ tag_ver_str=${TAG/${tag[0]}_} ++ tag_ver_str=${tag_ver_str/${tag[1]}_} ++ tag_ver_str=${tag_ver_str//_/.} ++ ++ # record tag type ++ tagtype= ++ ++ if [ "${tag[1]}" = "BRANCH" -o "${tag[1]}" = "TWIG" ]; then ++ tagtype=" (TOB)" ++ echo "tag type: $tagtype" ++ fi ++ ++ echo "Effective version string: $tag_ver_str" ++ ++ if [ "$(uname -s)" == "Darwin" ]; then ++ # Mac does not like 2-digit numbers so convert the number to single ++ # digit. 5.100 becomes 5.1 ++ if [ $min -gt 99 ]; then ++ minmac=`expr $min / 100` ++ else ++ minmac=$min ++ fi ++ epi_ver_dev="${maj}.${minmac}.0" ++ else ++ epi_ver_dev="${maj}.${min}.${rcnum}" ++ fi ++ ++ # Finally get version control revision number of (if any) ++ vc_version_num=$($svncmd info ${SRCBASE} 2> $NULL | awk -F': ' '/^Revision: /{printf "%s", $2}') ++ ++ # OK, go do it ++ echo "maj=${maj}, min=${min}, rc=${rcnum}, inc=${incremental}, build=${build}" ++ ++ sed \ ++ -e "s;@EPI_MAJOR_VERSION@;${maj};" \ ++ -e "s;@EPI_MINOR_VERSION@;${min};" \ ++ -e "s;@EPI_RC_NUMBER@;${rcnum};" \ ++ -e "s;@EPI_INCREMENTAL_NUMBER@;${incremental};" \ ++ -e "s;@EPI_BUILD_NUMBER@;${build};" \ ++ -e "s;@EPI_VERSION@;${maj}, ${min}, ${rcnum}, ${incremental};" \ ++ -e "s;@EPI_VERSION_STR@;${tag_ver_str};" \ ++ -e "s;@EPI_VERSION_TYPE@;${tagtype};" \ ++ -e "s;@VERSION_TYPE@;${tagtype};" \ ++ -e "s;@EPI_VERSION_NUM@;${vernum};" \ ++ -e "s;@EPI_VERSION_DEV@;${epi_ver_dev};" \ ++ -e "s;@VC_VERSION_NUM@;r${vc_version_num};" \ ++ < epivers.h.in > epivers.h ++ ++ # In shared workspaces across different platforms, ensure that ++ # windows generated file is made platform neutral without CRLF ++ if uname -s | egrep -i -q "cygwin"; then ++ dos2unix epivers.h > $NULL 2>&1 ++ fi ++fi # epivers.h +diff --git a/drivers/bcmdrivers/gmac/src/include/etioctl.h b/drivers/bcmdrivers/gmac/src/include/etioctl.h +new file mode 100755 +index 0000000..2fbddf9 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/etioctl.h +@@ -0,0 +1,158 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * BCM44XX Ethernet Windows device driver custom OID definitions. ++ * ++ * $Id: etioctl.h 322208 2012-03-20 01:53:23Z $ ++ */ ++ ++#ifndef _etioctl_h_ ++#define _etioctl_h_ ++ ++/* ++ * Minor kludge alert: ++ * Duplicate a few definitions that irelay requires from epiioctl.h here ++ * so caller doesn't have to include this file and epiioctl.h . ++ * If this grows any more, it would be time to move these irelay-specific ++ * definitions out of the epiioctl.h and into a separate driver common file. ++ */ ++#ifndef EPICTRL_COOKIE ++#define EPICTRL_COOKIE 0xABADCEDE ++#endif ++ ++/* common ioctl definitions */ ++#define ETCUP 0 ++#define ETCDOWN 1 ++#define ETCLOOP 2 ++#define ETCDUMP 3 ++#define ETCSETMSGLEVEL 4 ++#define ETCPROMISC 5 ++#define ETCVAR 6 ++#define ETCSPEED 7 ++#define ETCPHYRD 9 ++#define ETCPHYWR 10 ++#define ETCQOS 11 ++#define ETCPHYRD2 12 ++#define ETCPHYWR2 13 ++#define ETCROBORD 14 ++#define ETCROBOWR 15 ++ ++/* ++ * A set of iovars defined for ET set/get ++ */ ++#define IOV_ET_POWER_SAVE_MODE 1 ++#define IOV_ET_CLEAR_DUMP 2 ++#define IOV_ET_ROBO_DEVID 3 ++#define IOV_PKTC 4 ++#define IOV_PKTCBND 5 ++#define IOV_COUNTERS 6 ++#define IOV_DUMP_CTF 7 ++ ++#if defined(linux) || defined(__ECOS) ++#define SIOCSETCUP (SIOCDEVPRIVATE + ETCUP) ++#define SIOCSETCDOWN (SIOCDEVPRIVATE + ETCDOWN) ++#define SIOCSETCLOOP (SIOCDEVPRIVATE + ETCLOOP) ++#define SIOCGETCDUMP (SIOCDEVPRIVATE + ETCDUMP) ++#define SIOCSETCSETMSGLEVEL (SIOCDEVPRIVATE + ETCSETMSGLEVEL) ++#define SIOCSETCPROMISC (SIOCDEVPRIVATE + ETCPROMISC) ++#define SIOCSETGETVAR (SIOCDEVPRIVATE + ETCVAR) ++#define SIOCSETCSPEED (SIOCDEVPRIVATE + ETCSPEED) ++#define SIOCTXGEN (SIOCDEVPRIVATE + 8) ++#define SIOCGETCPHYRD (SIOCDEVPRIVATE + ETCPHYRD) ++#define SIOCSETCPHYWR (SIOCDEVPRIVATE + ETCPHYWR) ++#define SIOCSETCQOS (SIOCDEVPRIVATE + ETCQOS) ++#define SIOCGETCPHYRD2 (SIOCDEVPRIVATE + ETCPHYRD2) ++#define SIOCSETCPHYWR2 (SIOCDEVPRIVATE + ETCPHYWR2) ++#define SIOCGETCROBORD (SIOCDEVPRIVATE + ETCROBORD) ++#define SIOCSETCROBOWR (SIOCDEVPRIVATE + ETCROBOWR) ++ ++/* structure to send a generic var set/get */ ++typedef struct et_var_s { ++ uint cmd; ++ uint set; ++ void *buf; ++ uint len; ++} et_var_t; ++ ++/* arg to SIOCTXGEN */ ++struct txg { ++ uint32 num; /* number of frames to send */ ++ uint32 delay; /* delay in microseconds between sending each */ ++ uint32 size; /* size of ether frame to send */ ++ uchar buf[1514]; /* starting ether frame data */ ++}; ++#endif /* linux */ ++ ++ ++#if defined(__NetBSD__) ++#define SIOCSETCUP _IOW('e', 0, struct ifreq) ++#define SIOCSETCDOWN _IOW('e', 1, struct ifreq) ++#define SIOCSETCLOOP _IOW('e', 2, struct ifreq) ++#define SIOCGETCDUMP _IOWR('e', 3, struct ifreq) ++#define SIOCSETCSETMSGLEVEL _IOW('e', 4, struct ifreq) ++#define SIOCSETCPROMISC _IOW('e', 5, struct ifreq) ++#define SIOCSETCTXDOWN _IOW('e', 6, struct ifreq) /* obsolete */ ++#define SIOCSETCSPEED _IOW('e', 7, struct ifreq) ++#define SIOCTXGEN _IOW('e', 8, struct ifreq) ++#define SIOCGETCPHYRD _IOWR('e', 9, struct ifreq) ++#define SIOCSETCPHYWR _IOW('e', 10, struct ifreq) ++#define SIOCSETCQOS _IOW('e', 11, struct ifreq) ++#define SIOCGETCPHYRD2 _IOWR('e', 12, struct ifreq) ++#define SIOCSETCPHYWR2 _IOW('e', 13, struct ifreq) ++#define SIOCGETCROBORD _IOWR('e', 14, struct ifreq) ++#define SIOCSETCROBOWR _IOW('e', 15, struct ifreq) ++ ++/* arg to SIOCTXGEN */ ++struct txg { ++ uint32 num; /* number of frames to send */ ++ uint32 delay; /* delay in microseconds between sending each */ ++ uint32 size; /* size of ether frame to send */ ++ uchar buf[1514]; /* starting ether frame data */ ++}; ++#endif /* __NetBSD__ */ ++ ++/* ++ * custom OID support ++ * ++ * 0xFF - implementation specific OID ++ * 0xE4 - first byte of Broadcom PCI vendor ID ++ * 0x14 - second byte of Broadcom PCI vendor ID ++ * 0xXX - the custom OID number ++ */ ++#define ET_OID_BASE 0xFFE41400 /* OID Base for ET */ ++ ++#define OID_ET_UP (ET_OID_BASE + ETCUP) ++#define OID_ET_DOWN (ET_OID_BASE + ETCDOWN) ++#define OID_ET_LOOP (ET_OID_BASE + ETCLOOP) ++#define OID_ET_DUMP (ET_OID_BASE + ETCDUMP) ++#define OID_ET_SETMSGLEVEL (ET_OID_BASE + ETCSETMSGLEVEL) ++#define OID_ET_PROMISC (ET_OID_BASE + ETCPROMISC) ++#define OID_ET_TXDOWN (ET_OID_BASE + 6) ++#define OID_ET_SPEED (ET_OID_BASE + ETCSPEED) ++#define OID_ET_GETINSTANCE (ET_OID_BASE + 8) ++#define OID_ET_SETCALLBACK (ET_OID_BASE + 9) ++#define OID_ET_UNSETCALLBACK (ET_OID_BASE + 10) ++ ++#define IS_ET_OID(oid) (((oid) & 0xFFFFFF00) == 0xFFE41400) ++ ++#define ET_ISQUERYOID(oid) ((oid == OID_ET_DUMP) || (oid == OID_ET_GETINSTANCE)) ++ ++/* OID_ET_SETCALLBACK data type */ ++typedef struct et_cb { ++ void (*fn)(void *, int); /* Callback function */ ++ void *context; /* Passed to callback function */ ++} et_cb_t; ++ ++#endif /* _etioctl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/gmac_common.h b/drivers/bcmdrivers/gmac/src/include/gmac_common.h +new file mode 100755 +index 0000000..145e587 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/gmac_common.h +@@ -0,0 +1,560 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * gmacdefs - Broadcom gmac (Unimac) specific definitions ++ * ++ * $Id: gmac_common.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _gmac_common_core_h_ ++#define _gmac_common_core_h_ ++ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD XSTR(__LINE__) ++#endif ++ ++typedef volatile struct _gmac_commonregs { ++ uint32 stag0; ++ uint32 stag1; ++ uint32 stag2; ++ uint32 stag3; ++ uint32 PAD[4]; ++ uint32 parsercontrol; ++ uint32 mib_max_len; ++ uint32 PAD[54]; ++ uint32 phyaccess; ++ uint32 phycontrol; ++ uint32 PAD[2]; ++ uint32 gmac0_rgmii_cntl; ++ uint32 PAD[59]; ++ uint32 cfp_access; ++ uint32 PAD[3]; ++ uint32 cfp_tcam_data0; ++ uint32 cfp_tcam_data1; ++ uint32 cfp_tcam_data2; ++ uint32 cfp_tcam_data3; ++ uint32 cfp_tcam_data4; ++ uint32 cfp_tcam_data5; ++ uint32 cfp_tcam_data6; ++ uint32 cfp_tcam_data7; ++ uint32 cfp_tcam_mask0; ++ uint32 cfp_tcam_mask1; ++ uint32 cfp_tcam_mask2; ++ uint32 cfp_tcam_mask3; ++ uint32 cfp_tcam_mask4; ++ uint32 cfp_tcam_mask5; ++ uint32 cfp_tcam_mask6; ++ uint32 cfp_tcam_mask7; ++ uint32 cfp_action_data; ++ uint32 PAD[19]; ++ uint32 tcam_bist_cntl; ++ uint32 tcam_bist_status; ++ uint32 tcam_cmp_status; ++ uint32 tcam_disable; ++ uint32 PAD[16]; ++ uint32 tcam_test_cntl; ++ uint32 PAD[3]; ++ uint32 udf_0_a3_a0; ++ uint32 udf_0_a7_a4; ++ uint32 udf_0_a8; ++ uint32 PAD[1]; ++ uint32 udf_1_a3_a0; ++ uint32 udf_1_a7_a4; ++ uint32 udf_1_a8; ++ uint32 PAD[1]; ++ uint32 udf_2_a3_a0; ++ uint32 udf_2_a7_a4; ++ uint32 udf_2_a8; ++ uint32 PAD[1]; ++ uint32 udf_0_b3_b0; ++ uint32 udf_0_b7_b4; ++ uint32 udf_0_b8; ++ uint32 PAD[1]; ++ uint32 udf_1_b3_b0; ++ uint32 udf_1_b7_b4; ++ uint32 udf_1_b8; ++ uint32 PAD[1]; ++ uint32 udf_2_b3_b0; ++ uint32 udf_2_b7_b4; ++ uint32 udf_2_b8; ++ uint32 PAD[1]; ++ uint32 udf_0_c3_c0; ++ uint32 udf_0_c7_c4; ++ uint32 udf_0_c8; ++ uint32 PAD[1]; ++ uint32 udf_1_c3_c0; ++ uint32 udf_1_c7_c4; ++ uint32 udf_1_c8; ++ uint32 PAD[1]; ++ uint32 udf_2_c3_c0; ++ uint32 udf_2_c7_c4; ++ uint32 udf_2_c8; ++ uint32 PAD[1]; ++ uint32 udf_0_d3_d0; ++ uint32 udf_0_d7_d4; ++ uint32 udf_0_d11_d8; ++} gmac_commonregs_t; ++ ++/* stag0 offset0x0 */ ++#define STAG0_TPID_SHIFT 0 ++#define STAG0_TPID_MASK 0xffff ++ ++/* stag1 offset0x4 */ ++#define STAG1_TPID_SHIFT 0 ++#define STAG1_TPID_MASK 0xffff ++ ++/* stag2 offset0x8 */ ++#define STAG2_TPID_SHIFT 0 ++#define STAG2_TPID_MASK 0xffff ++ ++/* stag3 offset0xc */ ++#define STAG3_TPID_SHIFT 0 ++#define STAG3_TPID_MASK 0xffff ++ ++/* parsercontrol offset0x20 */ ++#define PARSERCONTROL_MAX_PARSER_LEN_TH_SHIFT 0 ++#define PARSERCONTROL_MAX_PARSER_LEN_TH_MASK 0x3fff ++ ++/* mib_max_len offset0x24 */ ++#define MIB_MAX_LEN_MIB_MAX_LEN_SHIFT 0 ++#define MIB_MAX_LEN_MIB_MAX_LEN_MASK 0x3fff ++ ++/* phyaccess offset0x100 */ ++#define PHYACCESS_TRIGGER_SHIFT 30 ++#define PHYACCESS_TRIGGER_MASK 0x40000000 ++#define PHYACCESS_WR_CMD_SHIFT 29 ++#define PHYACCESS_WR_CMD_MASK 0x20000000 ++#define PHYACCESS_CPU_REG_ADDR_SHIFT 24 ++#define PHYACCESS_CPU_REG_ADDR_MASK 0x1f000000 ++#define PHYACCESS_CPU_PHY_ADDR_SHIFT 16 ++#define PHYACCESS_CPU_PHY_ADDR_MASK 0x1f0000 ++#define PHYACCESS_ACC_DATA_SHIFT 0 ++#define PHYACCESS_ACC_DATA_MASK 0xffff ++ ++/* phycontrol offset0x104 */ ++#define PHYCONTROL_SD_ACCESS_EN_SHIFT 25 ++#define PHYCONTROL_SD_ACCESS_EN_MASK 0x2000000 ++#define PHYCONTROL_NWAY_AUTO_POLLING_EN_SHIFT 24 ++#define PHYCONTROL_NWAY_AUTO_POLLING_EN_MASK 0x1000000 ++#define PHYCONTROL_MDC_TRANSITION_EN_SHIFT 23 ++#define PHYCONTROL_MDC_TRANSITION_EN_MASK 0x800000 ++#define PHYCONTROL_MDC_CYCLE_TH_SHIFT 16 ++#define PHYCONTROL_MDC_CYCLE_TH_MASK 0x7f0000 ++#define PHYCONTROL_EXT_PHY_ADDR_SHIFT 0 ++#define PHYCONTROL_EXT_PHY_ADDR_MASK 0x1f ++ ++/* gmac0_rgmii_cntl offset0x110 */ ++#define GMAC0_RGMII_CNTL_TIMING_SEL_SHIFT 0 ++#define GMAC0_RGMII_CNTL_TIMING_SEL_MASK 0x1 ++#define GMAC0_RGMII_CNTL_RGMII_DLL_RXC_BYPASS_SHIFT 1 ++#define GMAC0_RGMII_CNTL_RGMII_DLL_RXC_BYPASS_MASK 0x2 ++#define GMAC0_RGMII_CNTL_BYPASS_2NS_DEL_SHIFT 2 ++#define GMAC0_RGMII_CNTL_BYPASS_2NS_DEL_MASK 0x4 ++#define GMAC0_RGMII_CNTL_DEL_STRB_SHIFT 3 ++#define GMAC0_RGMII_CNTL_DEL_STRB_MASK 0x8 ++#define GMAC0_RGMII_CNTL_DEL_VALUE_SHIFT 4 ++#define GMAC0_RGMII_CNTL_DEL_VALUE_MASK 0x70 ++#define GMAC0_RGMII_CNTL_DEL_ADDR_SHIFT 7 ++#define GMAC0_RGMII_CNTL_DEL_ADDR_MASK 0x780 ++ ++/* cfp_access offset0x200 */ ++#define CFP_ACCESS_OP_START_DONE_SHIFT 0 ++#define CFP_ACCESS_OP_START_DONE_MASK 0x1 ++#define CFP_ACCESS_OP_SEL_SHIFT 1 ++#define CFP_ACCESS_OP_SEL_MASK 0xe ++#define CFP_ACCESS_CFP_RAM_CLEAR_SHIFT 4 ++#define CFP_ACCESS_CFP_RAM_CLEAR_MASK 0x10 ++#define CFP_ACCESS_RESERVED1_SHIFT 5 ++#define CFP_ACCESS_RESERVED1_MASK 0x3e0 ++#define CFP_ACCESS_RAM_SEL_SHIFT 10 ++#define CFP_ACCESS_RAM_SEL_MASK 0x7c00 ++#define CFP_ACCESS_TCAM_RESET_SHIFT 15 ++#define CFP_ACCESS_TCAM_RESET_MASK 0x8000 ++#define CFP_ACCESS_XCESS_ADDR_SHIFT 16 ++#define CFP_ACCESS_XCESS_ADDR_MASK 0x1ff0000 ++#define CFP_ACCESS_RESERVED0_SHIFT 25 ++#define CFP_ACCESS_RESERVED0_MASK 0xe000000 ++#define CFP_ACCESS_RD_STATUS_SHIFT 28 ++#define CFP_ACCESS_RD_STATUS_MASK 0xf0000000 ++ ++/* cfp_tcam_data0 offset0x210 */ ++#define CFP_TCAM_DATA0_DATA_SHIFT 0 ++#define CFP_TCAM_DATA0_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data1 offset0x214 */ ++#define CFP_TCAM_DATA1_DATA_SHIFT 0 ++#define CFP_TCAM_DATA1_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data2 offset0x218 */ ++#define CFP_TCAM_DATA2_DATA_SHIFT 0 ++#define CFP_TCAM_DATA2_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data3 offset0x21c */ ++#define CFP_TCAM_DATA3_DATA_SHIFT 0 ++#define CFP_TCAM_DATA3_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data4 offset0x220 */ ++#define CFP_TCAM_DATA4_DATA_SHIFT 0 ++#define CFP_TCAM_DATA4_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data5 offset0x224 */ ++#define CFP_TCAM_DATA5_DATA_SHIFT 0 ++#define CFP_TCAM_DATA5_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data6 offset0x228 */ ++#define CFP_TCAM_DATA6_DATA_SHIFT 0 ++#define CFP_TCAM_DATA6_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data7 offset0x22c */ ++#define CFP_TCAM_DATA7_DATA_SHIFT 0 ++#define CFP_TCAM_DATA7_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask0 offset0x230 */ ++#define CFP_TCAM_MASK0_DATA_SHIFT 0 ++#define CFP_TCAM_MASK0_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask1 offset0x234 */ ++#define CFP_TCAM_MASK1_DATA_SHIFT 0 ++#define CFP_TCAM_MASK1_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask2 offset0x238 */ ++#define CFP_TCAM_MASK2_DATA_SHIFT 0 ++#define CFP_TCAM_MASK2_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask3 offset0x23c */ ++#define CFP_TCAM_MASK3_DATA_SHIFT 0 ++#define CFP_TCAM_MASK3_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask4 offset0x240 */ ++#define CFP_TCAM_MASK4_DATA_SHIFT 0 ++#define CFP_TCAM_MASK4_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask5 offset0x244 */ ++#define CFP_TCAM_MASK5_DATA_SHIFT 0 ++#define CFP_TCAM_MASK5_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask6 offset0x248 */ ++#define CFP_TCAM_MASK6_DATA_SHIFT 0 ++#define CFP_TCAM_MASK6_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask7 offset0x24c */ ++#define CFP_TCAM_MASK7_DATA_SHIFT 0 ++#define CFP_TCAM_MASK7_DATA_MASK 0xffffffff ++ ++/* cfp_action_data offset0x250 */ ++#define CFP_ACTION_DATA_CHAINID_SHIFT 0 ++#define CFP_ACTION_DATA_CHAINID_MASK 0xff ++#define CFP_ACTION_DATA_CHANNELID_SHIFT 8 ++#define CFP_ACTION_DATA_CHANNELID_MASK 0xf00 ++#define CFP_ACTION_DATA_DROP_SHIFT 12 ++#define CFP_ACTION_DATA_DROP_MASK 0x1000 ++#define CFP_ACTION_DATA_RESERVED_SHIFT 13 ++#define CFP_ACTION_DATA_RESERVED_MASK 0xffffe000 ++ ++/* tcam_bist_cntl offset0x2a0 */ ++#define TCAM_BIST_CNTL_TCAM_BIST_EN_SHIFT 0 ++#define TCAM_BIST_CNTL_TCAM_BIST_EN_MASK 0x1 ++#define TCAM_BIST_CNTL_TCAM_BIST_TCAM_SEL_SHIFT 1 ++#define TCAM_BIST_CNTL_TCAM_BIST_TCAM_SEL_MASK 0x6 ++#define TCAM_BIST_CNTL_RESERVED1_SHIFT 3 ++#define TCAM_BIST_CNTL_RESERVED1_MASK 0x8 ++#define TCAM_BIST_CNTL_TCAM_BIST_STATUS_SEL_SHIFT 4 ++#define TCAM_BIST_CNTL_TCAM_BIST_STATUS_SEL_MASK 0xf0 ++#define TCAM_BIST_CNTL_TCAM_BIST_SKIP_ERR_CNT_SHIFT 8 ++#define TCAM_BIST_CNTL_TCAM_BIST_SKIP_ERR_CNT_MASK 0xff00 ++#define TCAM_BIST_CNTL_TCAM_TEST_COMPARE_SHIFT 16 ++#define TCAM_BIST_CNTL_TCAM_TEST_COMPARE_MASK 0x10000 ++#define TCAM_BIST_CNTL_RESERVED_SHIFT 17 ++#define TCAM_BIST_CNTL_RESERVED_MASK 0x7ffe0000 ++#define TCAM_BIST_CNTL_TCAM_BIST_DONE_SHIFT 31 ++#define TCAM_BIST_CNTL_TCAM_BIST_DONE_MASK 0x80000000 ++ ++/* tcam_bist_status offset0x2a4 */ ++#define TCAM_BIST_STATUS_TCAM_BIST_STATUS_SHIFT 0 ++#define TCAM_BIST_STATUS_TCAM_BIST_STATUS_MASK 0xffff ++#define TCAM_BIST_STATUS_RESERVED_SHIFT 16 ++#define TCAM_BIST_STATUS_RESERVED_MASK 0xffff0000 ++ ++/* tcam_cmp_status offset0x2a8 */ ++#define TCAM_CMP_STATUS_TCAM_HIT_ADDR_SHIFT 0 ++#define TCAM_CMP_STATUS_TCAM_HIT_ADDR_MASK 0x1ff ++#define TCAM_CMP_STATUS_RESERVED2_SHIFT 9 ++#define TCAM_CMP_STATUS_RESERVED2_MASK 0x7e00 ++#define TCAM_CMP_STATUS_TCAM_HIT_SHIFT 15 ++#define TCAM_CMP_STATUS_TCAM_HIT_MASK 0x8000 ++#define TCAM_CMP_STATUS_RESERVED1_SHIFT 16 ++#define TCAM_CMP_STATUS_RESERVED1_MASK 0xffff0000 ++ ++/* tcam_disable offset0x2ac */ ++#define TCAM_DISABLE_TCAM_DISABLE_SHIFT 0 ++#define TCAM_DISABLE_TCAM_DISABLE_MASK 0xf ++#define TCAM_DISABLE_RESERVED_SHIFT 4 ++#define TCAM_DISABLE_RESERVED_MASK 0xfffffff0 ++ ++/* tcam_test_cntl offset0x2f0 */ ++#define TCAM_TEST_CNTL_TCAM_TEST_CNTL_SHIFT 0 ++#define TCAM_TEST_CNTL_TCAM_TEST_CNTL_MASK 0x7ff ++#define TCAM_TEST_CNTL_RESERVED_SHIFT 11 ++#define TCAM_TEST_CNTL_RESERVED_MASK 0xfffff800 ++ ++/* udf_0_a3_a0 offset0x300 */ ++#define UDF_0_A3_A0_CFG_UDF_0_A0_SHIFT 0 ++#define UDF_0_A3_A0_CFG_UDF_0_A0_MASK 0xff ++#define UDF_0_A3_A0_CFG_UDF_0_A1_SHIFT 8 ++#define UDF_0_A3_A0_CFG_UDF_0_A1_MASK 0xff00 ++#define UDF_0_A3_A0_CFG_UDF_0_A2_SHIFT 16 ++#define UDF_0_A3_A0_CFG_UDF_0_A2_MASK 0xff0000 ++#define UDF_0_A3_A0_CFG_UDF_0_A3_SHIFT 24 ++#define UDF_0_A3_A0_CFG_UDF_0_A3_MASK 0xff000000 ++ ++/* udf_0_a7_a4 offset0x304 */ ++#define UDF_0_A7_A4_CFG_UDF_0_A4_SHIFT 0 ++#define UDF_0_A7_A4_CFG_UDF_0_A4_MASK 0xff ++#define UDF_0_A7_A4_CFG_UDF_0_A5_SHIFT 8 ++#define UDF_0_A7_A4_CFG_UDF_0_A5_MASK 0xff00 ++#define UDF_0_A7_A4_CFG_UDF_0_A6_SHIFT 16 ++#define UDF_0_A7_A4_CFG_UDF_0_A6_MASK 0xff0000 ++#define UDF_0_A7_A4_CFG_UDF_0_A7_SHIFT 24 ++#define UDF_0_A7_A4_CFG_UDF_0_A7_MASK 0xff000000 ++ ++/* udf_0_a8 offset0x308 */ ++#define UDF_0_A8_CFG_UDF_0_A8_SHIFT 0 ++#define UDF_0_A8_CFG_UDF_0_A8_MASK 0xff ++ ++/* udf_1_a3_a0 offset0x310 */ ++#define UDF_1_A3_A0_CFG_UDF_1_A0_SHIFT 0 ++#define UDF_1_A3_A0_CFG_UDF_1_A0_MASK 0xff ++#define UDF_1_A3_A0_CFG_UDF_1_A1_SHIFT 8 ++#define UDF_1_A3_A0_CFG_UDF_1_A1_MASK 0xff00 ++#define UDF_1_A3_A0_CFG_UDF_1_A2_SHIFT 16 ++#define UDF_1_A3_A0_CFG_UDF_1_A2_MASK 0xff0000 ++#define UDF_1_A3_A0_CFG_UDF_1_A3_SHIFT 24 ++#define UDF_1_A3_A0_CFG_UDF_1_A3_MASK 0xff000000 ++ ++/* udf_1_a7_a4 offset0x314 */ ++#define UDF_1_A7_A4_CFG_UDF_1_A4_SHIFT 0 ++#define UDF_1_A7_A4_CFG_UDF_1_A4_MASK 0xff ++#define UDF_1_A7_A4_CFG_UDF_1_A5_SHIFT 8 ++#define UDF_1_A7_A4_CFG_UDF_1_A5_MASK 0xff00 ++#define UDF_1_A7_A4_CFG_UDF_1_A6_SHIFT 16 ++#define UDF_1_A7_A4_CFG_UDF_1_A6_MASK 0xff0000 ++#define UDF_1_A7_A4_CFG_UDF_1_A7_SHIFT 24 ++#define UDF_1_A7_A4_CFG_UDF_1_A7_MASK 0xff000000 ++ ++/* udf_1_a8 offset0x318 */ ++#define UDF_1_A8_CFG_UDF_1_A8_SHIFT 0 ++#define UDF_1_A8_CFG_UDF_1_A8_MASK 0xff ++ ++/* udf_2_a3_a0 offset0x320 */ ++#define UDF_2_A3_A0_CFG_UDF_2_A0_SHIFT 0 ++#define UDF_2_A3_A0_CFG_UDF_2_A0_MASK 0xff ++#define UDF_2_A3_A0_CFG_UDF_2_A1_SHIFT 8 ++#define UDF_2_A3_A0_CFG_UDF_2_A1_MASK 0xff00 ++#define UDF_2_A3_A0_CFG_UDF_2_A2_SHIFT 16 ++#define UDF_2_A3_A0_CFG_UDF_2_A2_MASK 0xff0000 ++#define UDF_2_A3_A0_CFG_UDF_2_A3_SHIFT 24 ++#define UDF_2_A3_A0_CFG_UDF_2_A3_MASK 0xff000000 ++ ++/* udf_2_a7_a4 offset0x324 */ ++#define UDF_2_A7_A4_CFG_UDF_2_A4_SHIFT 0 ++#define UDF_2_A7_A4_CFG_UDF_2_A4_MASK 0xff ++#define UDF_2_A7_A4_CFG_UDF_2_A5_SHIFT 8 ++#define UDF_2_A7_A4_CFG_UDF_2_A5_MASK 0xff00 ++#define UDF_2_A7_A4_CFG_UDF_2_A6_SHIFT 16 ++#define UDF_2_A7_A4_CFG_UDF_2_A6_MASK 0xff0000 ++#define UDF_2_A7_A4_CFG_UDF_2_A7_SHIFT 24 ++#define UDF_2_A7_A4_CFG_UDF_2_A7_MASK 0xff000000 ++ ++/* udf_2_a8 offset0x328 */ ++#define UDF_2_A8_CFG_UDF_2_A8_SHIFT 0 ++#define UDF_2_A8_CFG_UDF_2_A8_MASK 0xff ++ ++/* udf_0_b3_b0 offset0x330 */ ++#define UDF_0_B3_B0_CFG_UDF_0_B0_SHIFT 0 ++#define UDF_0_B3_B0_CFG_UDF_0_B0_MASK 0xff ++#define UDF_0_B3_B0_CFG_UDF_0_B1_SHIFT 8 ++#define UDF_0_B3_B0_CFG_UDF_0_B1_MASK 0xff00 ++#define UDF_0_B3_B0_CFG_UDF_0_B2_SHIFT 16 ++#define UDF_0_B3_B0_CFG_UDF_0_B2_MASK 0xff0000 ++#define UDF_0_B3_B0_CFG_UDF_0_B3_SHIFT 24 ++#define UDF_0_B3_B0_CFG_UDF_0_B3_MASK 0xff000000 ++ ++/* udf_0_b7_b4 offset0x334 */ ++#define UDF_0_B7_B4_CFG_UDF_0_B4_SHIFT 0 ++#define UDF_0_B7_B4_CFG_UDF_0_B4_MASK 0xff ++#define UDF_0_B7_B4_CFG_UDF_0_B5_SHIFT 8 ++#define UDF_0_B7_B4_CFG_UDF_0_B5_MASK 0xff00 ++#define UDF_0_B7_B4_CFG_UDF_0_B6_SHIFT 16 ++#define UDF_0_B7_B4_CFG_UDF_0_B6_MASK 0xff0000 ++#define UDF_0_B7_B4_CFG_UDF_0_B7_SHIFT 24 ++#define UDF_0_B7_B4_CFG_UDF_0_B7_MASK 0xff000000 ++ ++/* udf_0_b8 offset0x338 */ ++#define UDF_0_B8_CFG_UDF_0_B8_SHIFT 0 ++#define UDF_0_B8_CFG_UDF_0_B8_MASK 0xff ++ ++/* udf_1_b3_b0 offset0x340 */ ++#define UDF_1_B3_B0_CFG_UDF_1_B0_SHIFT 0 ++#define UDF_1_B3_B0_CFG_UDF_1_B0_MASK 0xff ++#define UDF_1_B3_B0_CFG_UDF_1_B1_SHIFT 8 ++#define UDF_1_B3_B0_CFG_UDF_1_B1_MASK 0xff00 ++#define UDF_1_B3_B0_CFG_UDF_1_B2_SHIFT 16 ++#define UDF_1_B3_B0_CFG_UDF_1_B2_MASK 0xff0000 ++#define UDF_1_B3_B0_CFG_UDF_1_B3_SHIFT 24 ++#define UDF_1_B3_B0_CFG_UDF_1_B3_MASK 0xff000000 ++ ++/* udf_1_b7_b4 offset0x344 */ ++#define UDF_1_B7_B4_CFG_UDF_1_B4_SHIFT 0 ++#define UDF_1_B7_B4_CFG_UDF_1_B4_MASK 0xff ++#define UDF_1_B7_B4_CFG_UDF_1_B5_SHIFT 8 ++#define UDF_1_B7_B4_CFG_UDF_1_B5_MASK 0xff00 ++#define UDF_1_B7_B4_CFG_UDF_1_B6_SHIFT 16 ++#define UDF_1_B7_B4_CFG_UDF_1_B6_MASK 0xff0000 ++#define UDF_1_B7_B4_CFG_UDF_1_B7_SHIFT 24 ++#define UDF_1_B7_B4_CFG_UDF_1_B7_MASK 0xff000000 ++ ++/* udf_1_b8 offset0x348 */ ++#define UDF_1_B8_CFG_UDF_1_B8_SHIFT 0 ++#define UDF_1_B8_CFG_UDF_1_B8_MASK 0xff ++ ++/* udf_2_b3_b0 offset0x350 */ ++#define UDF_2_B3_B0_CFG_UDF_2_B0_SHIFT 0 ++#define UDF_2_B3_B0_CFG_UDF_2_B0_MASK 0xff ++#define UDF_2_B3_B0_CFG_UDF_2_B1_SHIFT 8 ++#define UDF_2_B3_B0_CFG_UDF_2_B1_MASK 0xff00 ++#define UDF_2_B3_B0_CFG_UDF_2_B2_SHIFT 16 ++#define UDF_2_B3_B0_CFG_UDF_2_B2_MASK 0xff0000 ++#define UDF_2_B3_B0_CFG_UDF_2_B3_SHIFT 24 ++#define UDF_2_B3_B0_CFG_UDF_2_B3_MASK 0xff000000 ++ ++/* udf_2_b7_b4 offset0x354 */ ++#define UDF_2_B7_B4_CFG_UDF_2_B4_SHIFT 0 ++#define UDF_2_B7_B4_CFG_UDF_2_B4_MASK 0xff ++#define UDF_2_B7_B4_CFG_UDF_2_B5_SHIFT 8 ++#define UDF_2_B7_B4_CFG_UDF_2_B5_MASK 0xff00 ++#define UDF_2_B7_B4_CFG_UDF_2_B6_SHIFT 16 ++#define UDF_2_B7_B4_CFG_UDF_2_B6_MASK 0xff0000 ++#define UDF_2_B7_B4_CFG_UDF_2_B7_SHIFT 24 ++#define UDF_2_B7_B4_CFG_UDF_2_B7_MASK 0xff000000 ++ ++/* udf_2_b8 offset0x358 */ ++#define UDF_2_B8_CFG_UDF_2_B8_SHIFT 0 ++#define UDF_2_B8_CFG_UDF_2_B8_MASK 0xff ++ ++/* udf_0_c3_c0 offset0x360 */ ++#define UDF_0_C3_C0_CFG_UDF_0_C0_SHIFT 0 ++#define UDF_0_C3_C0_CFG_UDF_0_C0_MASK 0xff ++#define UDF_0_C3_C0_CFG_UDF_0_C1_SHIFT 8 ++#define UDF_0_C3_C0_CFG_UDF_0_C1_MASK 0xff00 ++#define UDF_0_C3_C0_CFG_UDF_0_C2_SHIFT 16 ++#define UDF_0_C3_C0_CFG_UDF_0_C2_MASK 0xff0000 ++#define UDF_0_C3_C0_CFG_UDF_0_C3_SHIFT 24 ++#define UDF_0_C3_C0_CFG_UDF_0_C3_MASK 0xff000000 ++ ++/* udf_0_c7_c4 offset0x364 */ ++#define UDF_0_C7_C4_CFG_UDF_0_C4_SHIFT 0 ++#define UDF_0_C7_C4_CFG_UDF_0_C4_MASK 0xff ++#define UDF_0_C7_C4_CFG_UDF_0_C5_SHIFT 8 ++#define UDF_0_C7_C4_CFG_UDF_0_C5_MASK 0xff00 ++#define UDF_0_C7_C4_CFG_UDF_0_C6_SHIFT 16 ++#define UDF_0_C7_C4_CFG_UDF_0_C6_MASK 0xff0000 ++#define UDF_0_C7_C4_CFG_UDF_0_C7_SHIFT 24 ++#define UDF_0_C7_C4_CFG_UDF_0_C7_MASK 0xff000000 ++ ++/* udf_0_c8 offset0x368 */ ++#define UDF_0_C8_CFG_UDF_0_C8_SHIFT 0 ++#define UDF_0_C8_CFG_UDF_0_C8_MASK 0xff ++ ++/* udf_1_c3_c0 offset0x370 */ ++#define UDF_1_C3_C0_CFG_UDF_1_C0_SHIFT 0 ++#define UDF_1_C3_C0_CFG_UDF_1_C0_MASK 0xff ++#define UDF_1_C3_C0_CFG_UDF_1_C1_SHIFT 8 ++#define UDF_1_C3_C0_CFG_UDF_1_C1_MASK 0xff00 ++#define UDF_1_C3_C0_CFG_UDF_1_C2_SHIFT 16 ++#define UDF_1_C3_C0_CFG_UDF_1_C2_MASK 0xff0000 ++#define UDF_1_C3_C0_CFG_UDF_1_C3_SHIFT 24 ++#define UDF_1_C3_C0_CFG_UDF_1_C3_MASK 0xff000000 ++ ++/* udf_1_c7_c4 offset0x374 */ ++#define UDF_1_C7_C4_CFG_UDF_1_C4_SHIFT 0 ++#define UDF_1_C7_C4_CFG_UDF_1_C4_MASK 0xff ++#define UDF_1_C7_C4_CFG_UDF_1_C5_SHIFT 8 ++#define UDF_1_C7_C4_CFG_UDF_1_C5_MASK 0xff00 ++#define UDF_1_C7_C4_CFG_UDF_1_C6_SHIFT 16 ++#define UDF_1_C7_C4_CFG_UDF_1_C6_MASK 0xff0000 ++#define UDF_1_C7_C4_CFG_UDF_1_C7_SHIFT 24 ++#define UDF_1_C7_C4_CFG_UDF_1_C7_MASK 0xff000000 ++ ++/* udf_1_c8 offset0x378 */ ++#define UDF_1_C8_CFG_UDF_1_C8_SHIFT 0 ++#define UDF_1_C8_CFG_UDF_1_C8_MASK 0xff ++ ++/* udf_2_c3_c0 offset0x380 */ ++#define UDF_2_C3_C0_CFG_UDF_2_C0_SHIFT 0 ++#define UDF_2_C3_C0_CFG_UDF_2_C0_MASK 0xff ++#define UDF_2_C3_C0_CFG_UDF_2_C1_SHIFT 8 ++#define UDF_2_C3_C0_CFG_UDF_2_C1_MASK 0xff00 ++#define UDF_2_C3_C0_CFG_UDF_2_C2_SHIFT 16 ++#define UDF_2_C3_C0_CFG_UDF_2_C2_MASK 0xff0000 ++#define UDF_2_C3_C0_CFG_UDF_2_C3_SHIFT 24 ++#define UDF_2_C3_C0_CFG_UDF_2_C3_MASK 0xff000000 ++ ++/* udf_2_c7_c4 offset0x384 */ ++#define UDF_2_C7_C4_CFG_UDF_2_C4_SHIFT 0 ++#define UDF_2_C7_C4_CFG_UDF_2_C4_MASK 0xff ++#define UDF_2_C7_C4_CFG_UDF_2_C5_SHIFT 8 ++#define UDF_2_C7_C4_CFG_UDF_2_C5_MASK 0xff00 ++#define UDF_2_C7_C4_CFG_UDF_2_C6_SHIFT 16 ++#define UDF_2_C7_C4_CFG_UDF_2_C6_MASK 0xff0000 ++#define UDF_2_C7_C4_CFG_UDF_2_C7_SHIFT 24 ++#define UDF_2_C7_C4_CFG_UDF_2_C7_MASK 0xff000000 ++ ++/* udf_2_c8 offset0x388 */ ++#define UDF_2_C8_CFG_UDF_2_C8_SHIFT 0 ++#define UDF_2_C8_CFG_UDF_2_C8_MASK 0xff ++ ++/* udf_0_d3_d0 offset0x390 */ ++#define UDF_0_D3_D0_CFG_UDF_0_D0_SHIFT 0 ++#define UDF_0_D3_D0_CFG_UDF_0_D0_MASK 0xff ++#define UDF_0_D3_D0_CFG_UDF_0_D1_SHIFT 8 ++#define UDF_0_D3_D0_CFG_UDF_0_D1_MASK 0xff00 ++#define UDF_0_D3_D0_CFG_UDF_0_D2_SHIFT 16 ++#define UDF_0_D3_D0_CFG_UDF_0_D2_MASK 0xff0000 ++#define UDF_0_D3_D0_CFG_UDF_0_D3_SHIFT 24 ++#define UDF_0_D3_D0_CFG_UDF_0_D3_MASK 0xff000000 ++ ++/* udf_0_d7_d4 offset0x394 */ ++#define UDF_0_D7_D4_CFG_UDF_0_D4_SHIFT 0 ++#define UDF_0_D7_D4_CFG_UDF_0_D4_MASK 0xff ++#define UDF_0_D7_D4_CFG_UDF_0_D5_SHIFT 8 ++#define UDF_0_D7_D4_CFG_UDF_0_D5_MASK 0xff00 ++#define UDF_0_D7_D4_CFG_UDF_0_D6_SHIFT 16 ++#define UDF_0_D7_D4_CFG_UDF_0_D6_MASK 0xff0000 ++#define UDF_0_D7_D4_CFG_UDF_0_D7_SHIFT 24 ++#define UDF_0_D7_D4_CFG_UDF_0_D7_MASK 0xff000000 ++ ++/* udf_0_d11_d8 offset0x398 */ ++#define UDF_0_D11_D8_CFG_UDF_0_D8_SHIFT 0 ++#define UDF_0_D11_D8_CFG_UDF_0_D8_MASK 0xff ++#define UDF_0_D11_D8_CFG_UDF_0_D9_SHIFT 8 ++#define UDF_0_D11_D8_CFG_UDF_0_D9_MASK 0xff00 ++#define UDF_0_D11_D8_CFG_UDF_0_D10_SHIFT 16 ++#define UDF_0_D11_D8_CFG_UDF_0_D10_MASK 0xff0000 ++#define UDF_0_D11_D8_CFG_UDF_0_D11_SHIFT 24 ++#define UDF_0_D11_D8_CFG_UDF_0_D11_MASK 0xff000000 ++ ++#endif /* _gmac_common_core_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/gmac_core.h b/drivers/bcmdrivers/gmac/src/include/gmac_core.h +new file mode 100755 +index 0000000..090c327 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/gmac_core.h +@@ -0,0 +1,302 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * gmacdefs - Broadcom gmac (Unimac) specific definitions ++ * ++ * $Id: gmac_core.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _gmac_core_h_ ++#define _gmac_core_h_ ++ ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* We have 4 DMA TX channels */ ++#define GMAC_NUM_DMA_TX 4 ++ ++typedef volatile struct { ++ dma64regs_t dmaxmt; /* dma tx */ ++ uint32 PAD[2]; ++ dma64regs_t dmarcv; /* dma rx */ ++ uint32 PAD[2]; ++} dma64_t; ++ ++/* ++ * Host Interface Registers ++ */ ++typedef volatile struct _gmacregs { ++ uint32 devcontrol; /* 0x000 */ ++ uint32 devstatus; /* 0x004 */ ++ uint32 PAD; ++ uint32 biststatus; /* 0x00c */ ++ uint32 PAD[4]; ++ uint32 intstatus; /* 0x020 */ ++ uint32 intmask; /* 0x024 */ ++ uint32 gptimer; /* 0x028 */ ++ uint32 PAD[53]; ++ uint32 intrecvlazy; /* 0x100 */ ++ uint32 flowctlthresh; /* 0x104 */ ++ uint32 wrrthresh; /* 0x108 */ ++ uint32 gmac_idle_cnt_thresh; /* 0x10c */ ++ uint32 PAD[28]; ++ uint32 phyaccess; /* 0x180 */ ++ uint32 PAD; ++ uint32 phycontrol; /* 0x188 */ ++ uint32 txqctl; /* 0x18c */ ++ uint32 rxqctl; /* 0x190 */ ++ uint32 gpioselect; /* 0x194 */ ++ uint32 gpio_output_en; /* 0x198 */ ++ uint32 PAD; /* 0x19c */ ++ uint32 txq_rxq_mem_ctl; /* 0x1a0 */ ++ uint32 memory_ecc_status; /* 0x1a4 */ ++ uint32 serdes_ctl; /* 0x1a8 */ ++ uint32 serdes_status0; /* 0x1ac */ ++ uint32 serdes_status1; /* 0x1b0 */ ++ uint32 PAD[11]; /* 0x1b4-1dc */ ++ uint32 clk_ctl_st; /* 0x1e0 */ ++ uint32 hw_war; /* 0x1e4 */ ++ uint32 pwrctl; /* 0x1e8 */ ++ uint32 PAD[5]; ++ ++ dma64_t dmaregs[GMAC_NUM_DMA_TX]; ++ ++ /* GAMC MIB counters */ ++ gmacmib_t mib; ++ uint32 PAD[245]; ++ ++ uint32 unimacversion; /* 0x800 */ ++ uint32 hdbkpctl; /* 0x804 */ ++ uint32 cmdcfg; /* 0x808 */ ++ uint32 macaddrhigh; /* 0x80c */ ++ uint32 macaddrlow; /* 0x810 */ ++ uint32 rxmaxlength; /* 0x814 */ ++ uint32 pausequanta; /* 0x818 */ ++ uint32 PAD[10]; ++ uint32 macmode; /* 0x844 */ ++ uint32 outertag; /* 0x848 */ ++ uint32 innertag; /* 0x84c */ ++ uint32 PAD[3]; ++ uint32 txipg; /* 0x85c */ ++ uint32 PAD[180]; ++ uint32 pausectl; /* 0xb30 */ ++ uint32 txflush; /* 0xb34 */ ++ uint32 rxstatus; /* 0xb38 */ ++ uint32 txstatus; /* 0xb3c */ ++} gmacregs_t; ++ ++#define GM_MIB_BASE 0x300 ++#define GM_MIB_LIMIT 0x800 ++ ++/* ++ * register-specific flag definitions ++ */ ++ ++/* device control */ ++#define DC_TSM 0x00000002 ++#define DC_CFCO 0x00000004 ++#define DC_RLSS 0x00000008 ++#define DC_MROR 0x00000010 ++#define DC_FCM_MASK 0x00000060 ++#define DC_FCM_SHIFT 5 ++#define DC_NAE 0x00000080 ++#define DC_TF 0x00000100 ++#define DC_RDS_MASK 0x00030000 ++#define DC_RDS_SHIFT 16 ++#define DC_TDS_MASK 0x000c0000 ++#define DC_TDS_SHIFT 18 ++ ++/* device status */ ++#define DS_RBF 0x00000001 ++#define DS_RDF 0x00000002 ++#define DS_RIF 0x00000004 ++#define DS_TBF 0x00000008 ++#define DS_TDF 0x00000010 ++#define DS_TIF 0x00000020 ++#define DS_PO 0x00000040 ++#define DS_MM_MASK 0x00000300 ++#define DS_MM_SHIFT 8 ++ ++/* bist status */ ++#define BS_MTF 0x00000001 ++#define BS_MRF 0x00000002 ++#define BS_TDB 0x00000004 ++#define BS_TIB 0x00000008 ++#define BS_TBF 0x00000010 ++#define BS_RDB 0x00000020 ++#define BS_RIB 0x00000040 ++#define BS_RBF 0x00000080 ++#define BS_URTF 0x00000100 ++#define BS_UTF 0x00000200 ++#define BS_URF 0x00000400 ++ ++/* interrupt status and mask registers */ ++#define I_MRO 0x00000001 ++#define I_MTO 0x00000002 ++#define I_TFD 0x00000004 ++#define I_LS 0x00000008 ++#define I_MDIO 0x00000010 ++#define I_MR 0x00000020 ++#define I_MT 0x00000040 ++#define I_TO 0x00000080 ++#define I_PDEE 0x00000400 ++#define I_PDE 0x00000800 ++#define I_DE 0x00001000 ++#define I_RDU 0x00002000 ++#define I_RFO 0x00004000 ++#define I_XFU 0x00008000 ++#define I_RI 0x00010000 ++#define I_XI0 0x01000000 ++#define I_XI1 0x02000000 ++#define I_XI2 0x04000000 ++#define I_XI3 0x08000000 ++#define I_INTMASK 0x0f01fcff ++#define I_ERRMASK 0x0000fc00 ++ ++/* interrupt receive lazy */ ++#define IRL_TO_MASK 0x00ffffff ++#define IRL_FC_MASK 0xff000000 ++#define IRL_FC_SHIFT 24 ++ ++/* flow control thresholds */ ++#define FCT_TT_MASK 0x00000fff ++#define FCT_RT_MASK 0x0fff0000 ++#define FCT_RT_SHIFT 16 ++ ++/* txq aribter wrr thresholds */ ++#define WRRT_Q0T_MASK 0x000000ff ++#define WRRT_Q1T_MASK 0x0000ff00 ++#define WRRT_Q1T_SHIFT 8 ++#define WRRT_Q2T_MASK 0x00ff0000 ++#define WRRT_Q2T_SHIFT 16 ++#define WRRT_Q3T_MASK 0xff000000 ++#define WRRT_Q3T_SHIFT 24 ++ ++/* phy access */ ++#define PA_DATA_MASK 0x0000ffff ++#define PA_ADDR_MASK 0x001f0000 ++#define PA_ADDR_SHIFT 16 ++#define PA_REG_MASK 0x1f000000 ++#define PA_REG_SHIFT 24 ++#define PA_WRITE 0x20000000 ++#define PA_START 0x40000000 ++ ++/* phy control */ ++#define PC_EPA_MASK 0x0000001f ++#define PC_MCT_MASK 0x007f0000 ++#define PC_MCT_SHIFT 16 ++#define PC_MTE 0x00800000 ++ ++/* rxq control */ ++#define RC_DBT_MASK 0x00000fff ++#define RC_DBT_SHIFT 0 ++#define RC_PTE 0x00001000 ++#define RC_MDP_MASK 0x3f000000 ++#define RC_MDP_SHIFT 24 ++ ++#define RC_MAC_DATA_PERIOD 9 ++ ++/* txq control */ ++#define TC_DBT_MASK 0x00000fff ++#define TC_DBT_SHIFT 0 ++ ++/* gpio select */ ++#define GS_GSC_MASK 0x0000000f ++#define GS_GSC_SHIFT 0 ++ ++/* gpio output enable */ ++#define GS_GOE_MASK 0x0000ffff ++#define GS_GOE_SHIFT 0 ++ ++/* gpio output enable */ ++#define SC_TX1G_FIFO_RST_MASK 0x00f00000 ++#define SC_TX1G_FIFO_RST_VAL 0x00f00000 ++#define SC_FORCE_SPD_STRAP_MASK 0x00060000 ++#define SC_FORCE_SPD_STRAP_VAL 0x00040000 ++#define SC_REF_TERM_SEL_MASK 0x00001000 ++#define SC_REFSEL_MASK 0x00000c00 ++#define SC_REFSEL_VAL 0x00000400 ++#define SC_REFDIV_MASK 0x00000300 ++#define SC_REFDIV_VAL 0x00000000 ++#define SC_LCREF_EN_MASK 0x00000040 ++#define SC_RSTB_PLL_MASK 0x00000010 ++#define SC_RSTB_MDIOREGS_MASK 0x00000008 ++#define SC_RSTB_HW_MASK 0x00000004 ++#define SC_IDDQ_MASK 0x00000002 ++#define SC_PWR_DOWN_MASK 0x00000001 ++ ++/* clk control status */ ++#define CS_FA 0x00000001 ++#define CS_FH 0x00000002 ++#define CS_FI 0x00000004 ++#define CS_AQ 0x00000008 ++#define CS_HQ 0x00000010 ++#define CS_FC 0x00000020 ++#define CS_ER 0x00000100 ++#define CS_AA 0x00010000 ++#define CS_HA 0x00020000 ++#define CS_BA 0x00040000 ++#define CS_BH 0x00080000 ++#define CS_ES 0x01000000 ++ ++/* command config */ ++#define CC_TE 0x00000001 ++#define CC_RE 0x00000002 ++#define CC_ES_MASK 0x0000000c ++#define CC_ES_SHIFT 2 ++#define CC_PROM 0x00000010 ++#define CC_PAD_EN 0x00000020 ++#define CC_CF 0x00000040 ++#define CC_PF 0x00000080 ++#define CC_RPI 0x00000100 ++#define CC_TAI 0x00000200 ++#define CC_HD 0x00000400 ++#define CC_HD_SHIFT 10 ++#define CC_SR 0x00002000 ++#define CC_ML 0x00008000 ++#define CC_OT 0x00020000 ++#define CC_OR 0x00040000 ++#define CC_AE 0x00400000 ++#define CC_CFE 0x00800000 ++#define CC_NLC 0x01000000 ++#define CC_RL 0x02000000 ++#define CC_RED 0x04000000 ++#define CC_PE 0x08000000 ++#define CC_TPI 0x10000000 ++#define CC_AT 0x20000000 ++ ++/* mac addr high */ ++#define MH_HI_MASK 0xffff ++#define MH_HI_SHIFT 16 ++#define MH_MID_MASK 0xffff ++#define MH_MID_SHIFT 0 ++ ++/* mac addr low */ ++#define ML_LO_MASK 0xffff ++#define ML_LO_SHIFT 0 ++ ++/* Core specific control flags */ ++#define SICF_SWCLKE 0x0004 ++#define SICF_SWRST 0x0008 ++ ++/* Core specific status flags */ ++#define SISF_SW_ATTACHED 0x0800 ++ ++#endif /* _gmac_core_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndarm.h b/drivers/bcmdrivers/gmac/src/include/hndarm.h +new file mode 100755 +index 0000000..c105b958 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndarm.h +@@ -0,0 +1,96 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND SiliconBackplane ARM core software interface. ++ * ++ * $Id: hndarm.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _hndarm_h_ ++#define _hndarm_h_ ++ ++#include ++ ++extern void *hndarm_armr; ++extern uint32 hndarm_rev; ++ ++ ++extern void si_arm_init(si_t *sih); ++ ++#ifdef __ARM_ARCH_7A__ ++extern uint32 si_memc_get_ncdl(si_t *sih); ++#endif ++ ++extern void enable_arm_ints(uint32 which); ++extern void disable_arm_ints(uint32 which); ++ ++extern uint32 get_arm_cyclecount(void); ++extern void set_arm_cyclecount(uint32 ticks); ++ ++#ifdef __ARM_ARCH_7R__ ++extern uint32 get_arm_perfcount_enable(void); ++extern void set_arm_perfcount_enable(uint32 which); ++extern uint32 set_arm_perfcount_disable(void); ++ ++extern uint32 get_arm_perfcount_sel(void); ++extern void set_arm_perfcount_sel(uint32 which); ++ ++extern uint32 get_arm_perfcount_event(void); ++extern void set_arm_perfcount_event(uint32 which); ++ ++extern uint32 get_arm_perfcount(void); ++extern void set_arm_perfcount(uint32 which); ++ ++extern void enable_arm_cyclecount(void); ++extern void disable_arm_cyclecount(void); ++#endif /* __ARM_ARCH_7R__ */ ++ ++extern uint32 get_arm_inttimer(void); ++extern void set_arm_inttimer(uint32 ticks); ++ ++extern uint32 get_arm_intmask(void); ++extern void set_arm_intmask(uint32 ticks); ++ ++extern uint32 get_arm_intstatus(void); ++extern void set_arm_intstatus(uint32 ticks); ++ ++extern uint32 get_arm_firqmask(void); ++extern void set_arm_firqmask(uint32 ticks); ++ ++extern uint32 get_arm_firqstatus(void); ++extern void set_arm_firqstatus(uint32 ticks); ++ ++extern void arm_wfi(si_t *sih); ++extern void arm_jumpto(void *addr); ++ ++extern void traptest(void); ++ ++#ifdef BCMOVLHW ++#define BCMOVLHW_ENAB(sih) TRUE ++ ++extern int si_arm_ovl_remap(si_t *sih, void *virt, void *phys, uint size); ++extern int si_arm_ovl_reset(si_t *sih); ++extern bool si_arm_ovl_vaildaddr(si_t *sih, void *virt); ++extern bool si_arm_ovl_isenab(si_t *sih); ++extern bool si_arm_ovl_int(si_t *sih, uint32 pc); ++#else ++#define BCMOVLHW_ENAB(sih) FALSE ++ ++#define si_arm_ovl_remap(a, b, c, d) do {} while (0) ++#define si_arm_ovl_reset(a) do {} while (0) ++#define si_arm_ovl_int(a, b) FALSE ++#endif ++ ++#endif /* _hndarm_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndchipc.h b/drivers/bcmdrivers/gmac/src/include/hndchipc.h +new file mode 100755 +index 0000000..878276f +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndchipc.h +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND SiliconBackplane chipcommon support. ++ * ++ * $Id: hndchipc.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _hndchipc_h_ ++#define _hndchipc_h_ ++ ++typedef void (*si_serial_init_fn)(void *regs, uint irq, uint baud_base, uint reg_shift); ++ ++extern void si_serial_init(si_t *sih, si_serial_init_fn add); ++ ++extern void *hnd_jtagm_init(si_t *sih, uint clkd, bool exttap); ++extern void hnd_jtagm_disable(si_t *sih, void *h); ++extern uint32 jtag_scan(si_t *sih, void *h, uint irsz, uint32 ir0, uint32 ir1, ++ uint drsz, uint32 dr0, uint32 *dr1, bool rti); ++ ++typedef void (*cc_isr_fn)(void* cbdata, uint32 ccintst); ++ ++extern bool si_cc_register_isr(si_t *sih, cc_isr_fn isr, uint32 ccintmask, void *cbdata); ++extern void si_cc_isr(si_t *sih, chipcregs_t *regs); ++ ++#endif /* _hndchipc_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndcpu.h b/drivers/bcmdrivers/gmac/src/include/hndcpu.h +new file mode 100755 +index 0000000..8a4ee4c +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndcpu.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND SiliconBackplane MIPS/ARM cores software interface. ++ * ++ * $Id: hndcpu.h 258983 2011-05-11 09:59:25Z $ ++ */ ++ ++#ifndef _hndcpu_h_ ++#define _hndcpu_h_ ++ ++#if defined(mips) ++#include ++#elif defined(__arm__) || defined(__thumb__) || defined(__thumb2__) ++#include ++#endif ++ ++extern uint si_irq(si_t *sih); ++extern uint32 si_cpu_clock(si_t *sih); ++extern uint32 si_mem_clock(si_t *sih); ++extern void hnd_cpu_wait(si_t *sih); ++extern void hnd_cpu_jumpto(void *addr); ++extern void hnd_cpu_reset(si_t *sih); ++extern void hnd_cpu_deadman_timer(si_t *sih, uint32 val); ++extern void si_router_coma(si_t *sih, int reset, int delay); ++extern void si_dmc_phyctl(si_t *sih, uint32 phyctl_val); ++ ++#endif /* _hndcpu_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hnddma.h b/drivers/bcmdrivers/gmac/src/include/hnddma.h +new file mode 100755 +index 0000000..64f0349 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hnddma.h +@@ -0,0 +1,317 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Generic Broadcom Home Networking Division (HND) DMA engine SW interface ++ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * ++ * $Id: hnddma.h 321146 2012-03-14 08:27:23Z $ ++ */ ++ ++#ifndef _hnddma_h_ ++#define _hnddma_h_ ++ ++#ifndef _hnddma_pub_ ++#define _hnddma_pub_ ++typedef const struct hnddma_pub hnddma_t; ++#endif /* _hnddma_pub_ */ ++ ++/* range param for dma_getnexttxp() and dma_txreclaim */ ++typedef enum txd_range { ++ HNDDMA_RANGE_ALL = 1, ++ HNDDMA_RANGE_TRANSMITTED, ++ HNDDMA_RANGE_TRANSFERED ++} txd_range_t; ++ ++/* dma parameters id */ ++enum dma_param_id { ++ HNDDMA_PID_TX_MULTI_OUTSTD_RD = 0, ++ HNDDMA_PID_TX_PREFETCH_CTL, ++ HNDDMA_PID_TX_PREFETCH_THRESH, ++ HNDDMA_PID_TX_BURSTLEN, ++ ++ HNDDMA_PID_RX_PREFETCH_CTL = 0x100, ++ HNDDMA_PID_RX_PREFETCH_THRESH, ++ HNDDMA_PID_RX_BURSTLEN ++}; ++ ++/* dma function type */ ++typedef void (*di_detach_t)(hnddma_t *dmah); ++typedef bool (*di_txreset_t)(hnddma_t *dmah); ++typedef bool (*di_rxreset_t)(hnddma_t *dmah); ++typedef bool (*di_rxidle_t)(hnddma_t *dmah); ++typedef void (*di_txinit_t)(hnddma_t *dmah); ++typedef bool (*di_txenabled_t)(hnddma_t *dmah); ++typedef void (*di_rxinit_t)(hnddma_t *dmah); ++typedef void (*di_txsuspend_t)(hnddma_t *dmah); ++typedef void (*di_txresume_t)(hnddma_t *dmah); ++typedef bool (*di_txsuspended_t)(hnddma_t *dmah); ++typedef bool (*di_txsuspendedidle_t)(hnddma_t *dmah); ++#ifdef WL_MULTIQUEUE ++typedef void (*di_txflush_t)(hnddma_t *dmah); ++typedef void (*di_txflush_clear_t)(hnddma_t *dmah); ++#endif /* WL_MULTIQUEUE */ ++typedef int (*di_txfast_t)(hnddma_t *dmah, void *p, bool commit); ++typedef int (*di_txunframed_t)(hnddma_t *dmah, void *p, uint len, bool commit); ++typedef int (*di_rxunframed_t)(hnddma_t *dmah, void *p, uint len, bool commit); ++typedef void* (*di_getpos_t)(hnddma_t *di, bool direction); ++typedef void (*di_fifoloopbackenable_t)(hnddma_t *dmah); ++typedef bool (*di_txstopped_t)(hnddma_t *dmah); ++typedef bool (*di_rxstopped_t)(hnddma_t *dmah); ++typedef bool (*di_rxenable_t)(hnddma_t *dmah); ++typedef bool (*di_rxenabled_t)(hnddma_t *dmah); ++typedef void* (*di_rx_t)(hnddma_t *dmah); ++typedef bool (*di_rxfill_t)(hnddma_t *dmah); ++typedef void (*di_txreclaim_t)(hnddma_t *dmah, txd_range_t range); ++typedef void (*di_rxreclaim_t)(hnddma_t *dmah); ++typedef uintptr (*di_getvar_t)(hnddma_t *dmah, const char *name); ++typedef void* (*di_getnexttxp_t)(hnddma_t *dmah, txd_range_t range); ++typedef void* (*di_getnextrxp_t)(hnddma_t *dmah, bool forceall); ++typedef void* (*di_peeknexttxp_t)(hnddma_t *dmah); ++typedef void* (*di_peekntxp_t)(hnddma_t *dmah, int *len, void *txps[], txd_range_t range); ++typedef void* (*di_peeknextrxp_t)(hnddma_t *dmah); ++typedef void (*di_rxparam_get_t)(hnddma_t *dmah, uint16 *rxoffset, uint16 *rxbufsize); ++typedef void (*di_txblock_t)(hnddma_t *dmah); ++typedef void (*di_txunblock_t)(hnddma_t *dmah); ++typedef uint (*di_txactive_t)(hnddma_t *dmah); ++typedef void (*di_txrotate_t)(hnddma_t *dmah); ++typedef void (*di_counterreset_t)(hnddma_t *dmah); ++typedef uint (*di_ctrlflags_t)(hnddma_t *dmah, uint mask, uint flags); ++typedef char* (*di_dump_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); ++typedef char* (*di_dumptx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); ++typedef char* (*di_dumprx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); ++typedef uint (*di_rxactive_t)(hnddma_t *dmah); ++typedef uint (*di_txpending_t)(hnddma_t *dmah); ++typedef uint (*di_txcommitted_t)(hnddma_t *dmah); ++typedef int (*di_pktpool_set_t)(hnddma_t *dmah, pktpool_t *pool); ++typedef bool (*di_rxtxerror_t)(hnddma_t *dmah, bool istx); ++typedef void (*di_burstlen_set_t)(hnddma_t *dmah, uint8 rxburstlen, uint8 txburstlen); ++typedef uint (*di_avoidancecnt_t)(hnddma_t *dmah); ++typedef void (*di_param_set_t)(hnddma_t *dmah, uint16 paramid, uint16 paramval); ++typedef bool (*dma_glom_enable_t) (hnddma_t *dmah, uint32 val); ++typedef uint (*dma_active_rxbuf_t) (hnddma_t *dmah); ++/* dma opsvec */ ++typedef struct di_fcn_s { ++ di_detach_t detach; ++ di_txinit_t txinit; ++ di_txreset_t txreset; ++ di_txenabled_t txenabled; ++ di_txsuspend_t txsuspend; ++ di_txresume_t txresume; ++ di_txsuspended_t txsuspended; ++ di_txsuspendedidle_t txsuspendedidle; ++#ifdef WL_MULTIQUEUE ++ di_txflush_t txflush; ++ di_txflush_clear_t txflush_clear; ++#endif /* WL_MULTIQUEUE */ ++ di_txfast_t txfast; ++ di_txunframed_t txunframed; ++ di_getpos_t getpos; ++ di_txstopped_t txstopped; ++ di_txreclaim_t txreclaim; ++ di_getnexttxp_t getnexttxp; ++ di_peeknexttxp_t peeknexttxp; ++ di_peekntxp_t peekntxp; ++ di_txblock_t txblock; ++ di_txunblock_t txunblock; ++ di_txactive_t txactive; ++ di_txrotate_t txrotate; ++ ++ di_rxinit_t rxinit; ++ di_rxreset_t rxreset; ++ di_rxidle_t rxidle; ++ di_rxstopped_t rxstopped; ++ di_rxenable_t rxenable; ++ di_rxenabled_t rxenabled; ++ di_rx_t rx; ++ di_rxfill_t rxfill; ++ di_rxreclaim_t rxreclaim; ++ di_getnextrxp_t getnextrxp; ++ di_peeknextrxp_t peeknextrxp; ++ di_rxparam_get_t rxparam_get; ++ ++ di_fifoloopbackenable_t fifoloopbackenable; ++ di_getvar_t d_getvar; ++ di_counterreset_t counterreset; ++ di_ctrlflags_t ctrlflags; ++ di_dump_t dump; ++ di_dumptx_t dumptx; ++ di_dumprx_t dumprx; ++ di_rxactive_t rxactive; ++ di_txpending_t txpending; ++ di_txcommitted_t txcommitted; ++ di_pktpool_set_t pktpool_set; ++ di_rxtxerror_t rxtxerror; ++ di_burstlen_set_t burstlen_set; ++ di_avoidancecnt_t avoidancecnt; ++ di_param_set_t param_set; ++ dma_glom_enable_t glom_enab; ++ di_rxunframed_t rxunframed; ++ dma_active_rxbuf_t dma_activerxbuf; ++ uint endnum; ++} di_fcn_t; ++ ++/* ++ * Exported data structure (read-only) ++ */ ++/* export structure */ ++struct hnddma_pub { ++ const di_fcn_t *di_fn; /* DMA function pointers */ ++ uint txavail; /* # free tx descriptors */ ++ uint dmactrlflags; /* dma control flags */ ++ ++ /* rx error counters */ ++ uint rxgiants; /* rx giant frames */ ++ uint rxnobuf; /* rx out of dma descriptors */ ++ /* tx error counters */ ++ uint txnobuf; /* tx out of dma descriptors */ ++ uint txnodesc; /* tx out of dma descriptors running count */ ++}; ++ ++ ++extern hnddma_t * dma_attach(osl_t *osh, const char *name, si_t *sih, ++ volatile void *dmaregstx, volatile void *dmaregsrx, ++ uint ntxd, uint nrxd, uint rxbufsize, int rxextheadroom, uint nrxpost, ++ uint rxoffset, uint *msg_level); ++#ifdef BCMDMA32 ++ ++#define dma_detach(di) ((di)->di_fn->detach(di)) ++#define dma_txreset(di) ((di)->di_fn->txreset(di)) ++#define dma_rxreset(di) ((di)->di_fn->rxreset(di)) ++#define dma_rxidle(di) ((di)->di_fn->rxidle(di)) ++#define dma_txinit(di) ((di)->di_fn->txinit(di)) ++#define dma_txenabled(di) ((di)->di_fn->txenabled(di)) ++#define dma_rxinit(di) ((di)->di_fn->rxinit(di)) ++#define dma_txsuspend(di) ((di)->di_fn->txsuspend(di)) ++#define dma_txresume(di) ((di)->di_fn->txresume(di)) ++#define dma_txsuspended(di) ((di)->di_fn->txsuspended(di)) ++#define dma_txsuspendedidle(di) ((di)->di_fn->txsuspendedidle(di)) ++#ifdef WL_MULTIQUEUE ++#define dma_txflush(di) ((di)->di_fn->txflush(di)) ++#define dma_txflush_clear(di) ((di)->di_fn->txflush_clear(di)) ++#endif /* WL_MULTIQUEUE */ ++#define dma_txfast(di, p, commit) ((di)->di_fn->txfast(di, p, commit)) ++#define dma_fifoloopbackenable(di) ((di)->di_fn->fifoloopbackenable(di)) ++#define dma_txstopped(di) ((di)->di_fn->txstopped(di)) ++#define dma_rxstopped(di) ((di)->di_fn->rxstopped(di)) ++#define dma_rxenable(di) ((di)->di_fn->rxenable(di)) ++#define dma_rxenabled(di) ((di)->di_fn->rxenabled(di)) ++#define dma_rx(di) ((di)->di_fn->rx(di)) ++#define dma_rxfill(di) ((di)->di_fn->rxfill(di)) ++#define dma_txreclaim(di, range) ((di)->di_fn->txreclaim(di, range)) ++#define dma_rxreclaim(di) ((di)->di_fn->rxreclaim(di)) ++#define dma_getvar(di, name) ((di)->di_fn->d_getvar(di, name)) ++#define dma_getnexttxp(di, range) ((di)->di_fn->getnexttxp(di, range)) ++#define dma_getnextrxp(di, forceall) ((di)->di_fn->getnextrxp(di, forceall)) ++#define dma_peeknexttxp(di) ((di)->di_fn->peeknexttxp(di)) ++#define dma_peekntxp(di, l, t, r) ((di)->di_fn->peekntxp(di, l, t, r)) ++#define dma_peeknextrxp(di) ((di)->di_fn->peeknextrxp(di)) ++#define dma_rxparam_get(di, off, bufs) ((di)->di_fn->rxparam_get(di, off, bufs)) ++ ++#define dma_txblock(di) ((di)->di_fn->txblock(di)) ++#define dma_txunblock(di) ((di)->di_fn->txunblock(di)) ++#define dma_txactive(di) ((di)->di_fn->txactive(di)) ++#define dma_rxactive(di) ((di)->di_fn->rxactive(di)) ++#define dma_txrotate(di) ((di)->di_fn->txrotate(di)) ++#define dma_counterreset(di) ((di)->di_fn->counterreset(di)) ++#define dma_ctrlflags(di, mask, flags) ((di)->di_fn->ctrlflags((di), (mask), (flags))) ++#define dma_txpending(di) ((di)->di_fn->txpending(di)) ++#define dma_txcommitted(di) ((di)->di_fn->txcommitted(di)) ++#define dma_pktpool_set(di, pool) ((di)->di_fn->pktpool_set((di), (pool))) ++#if defined(BCMDBG) ++#define dma_dump(di, buf, dumpring) ((di)->di_fn->dump(di, buf, dumpring)) ++#define dma_dumptx(di, buf, dumpring) ((di)->di_fn->dumptx(di, buf, dumpring)) ++#define dma_dumprx(di, buf, dumpring) ((di)->di_fn->dumprx(di, buf, dumpring)) ++#endif ++#define dma_rxtxerror(di, istx) ((di)->di_fn->rxtxerror(di, istx)) ++#define dma_burstlen_set(di, rxlen, txlen) ((di)->di_fn->burstlen_set(di, rxlen, txlen)) ++#define dma_avoidance_cnt(di) ((di)->di_fn->avoidancecnt(di)) ++#define dma_param_set(di, paramid, paramval) ((di)->di_fn->param_set(di, paramid, paramval)) ++#define dma_activerxbuf(di) ((di)->di_fn->dma_activerxbuf(di)) ++ ++#else /* BCMDMA32 */ ++extern const di_fcn_t dma64proc; ++ ++#define dma_detach(di) (dma64proc.detach(di)) ++#define dma_txreset(di) (dma64proc.txreset(di)) ++#define dma_rxreset(di) (dma64proc.rxreset(di)) ++#define dma_rxidle(di) (dma64proc.rxidle(di)) ++#define dma_txinit(di) (dma64proc.txinit(di)) ++#define dma_txenabled(di) (dma64proc.txenabled(di)) ++#define dma_rxinit(di) (dma64proc.rxinit(di)) ++#define dma_txsuspend(di) (dma64proc.txsuspend(di)) ++#define dma_txresume(di) (dma64proc.txresume(di)) ++#define dma_txsuspended(di) (dma64proc.txsuspended(di)) ++#define dma_txsuspendedidle(di) (dma64proc.txsuspendedidle(di)) ++#ifdef WL_MULTIQUEUE ++#define dma_txflush(di) (dma64proc.txflush(di)) ++#define dma_txflush_clear(di) (dma64proc.txflush_clear(di)) ++#endif /* WL_MULTIQUEUE */ ++#define dma_txfast(di, p, commit) (dma64proc.txfast(di, p, commit)) ++#define dma_txunframed(di, p, l, commit)(dma64proc.txunframed(di, p, l, commit)) ++#define dma_getpos(di, dir) (dma64proc.getpos(di, dir)) ++#define dma_fifoloopbackenable(di) (dma64proc.fifoloopbackenable(di)) ++#define dma_txstopped(di) (dma64proc.txstopped(di)) ++#define dma_rxstopped(di) (dma64proc.rxstopped(di)) ++#define dma_rxenable(di) (dma64proc.rxenable(di)) ++#define dma_rxenabled(di) (dma64proc.rxenabled(di)) ++#define dma_rx(di) (dma64proc.rx(di)) ++#define dma_rxfill(di) (dma64proc.rxfill(di)) ++#define dma_txreclaim(di, range) (dma64proc.txreclaim(di, range)) ++#define dma_rxreclaim(di) (dma64proc.rxreclaim(di)) ++#define dma_getvar(di, name) (dma64proc.d_getvar(di, name)) ++#define dma_getnexttxp(di, range) (dma64proc.getnexttxp(di, range)) ++#define dma_getnextrxp(di, forceall) (dma64proc.getnextrxp(di, forceall)) ++#define dma_peeknexttxp(di) (dma64proc.peeknexttxp(di)) ++#define dma_peekntxp(di, l, t, r) (dma64proc.peekntxp(di, l, t, r)) ++#define dma_peeknextrxp(di) (dma64proc.peeknextrxp(di)) ++#define dma_rxparam_get(di, off, bufs) (dma64proc.rxparam_get(di, off, bufs)) ++ ++#define dma_txblock(di) (dma64proc.txblock(di)) ++#define dma_txunblock(di) (dma64proc.txunblock(di)) ++#define dma_txactive(di) (dma64proc.txactive(di)) ++#define dma_rxactive(di) (dma64proc.rxactive(di)) ++#define dma_txrotate(di) (dma64proc.txrotate(di)) ++#define dma_counterreset(di) (dma64proc.counterreset(di)) ++#define dma_ctrlflags(di, mask, flags) (dma64proc.ctrlflags((di), (mask), (flags))) ++#define dma_txpending(di) (dma64proc.txpending(di)) ++#define dma_txcommitted(di) (dma64proc.txcommitted(di)) ++#define dma_pktpool_set(di, pool) (dma64proc.pktpool_set((di), (pool))) ++#define dma_rxunframed(di, p, l, commit)(dma64proc.rxunframed(di, p, l, commit)) ++#if defined(BCMDBG) ++#define dma_dump(di, buf, dumpring) (dma64proc.dump(di, buf, dumpring)) ++#define dma_dumptx(di, buf, dumpring) (dma64proc.dumptx(di, buf, dumpring)) ++#define dma_dumprx(di, buf, dumpring) (dma64proc.dumprx(di, buf, dumpring)) ++#endif ++#define dma_rxtxerror(di, istx) (dma64proc.rxtxerror(di, istx)) ++#define dma_burstlen_set(di, rxlen, txlen) (dma64proc.burstlen_set(di, rxlen, txlen)) ++#define dma_avoidance_cnt(di) (dma64proc.avoidancecnt(di)) ++#define dma_param_set(di, paramid, paramval) (dma64proc.param_set(di, paramid, paramval)) ++ ++#define dma_glom_enable(di, val) (dma64proc.glom_enab(di, val)) ++#define dma_activerxbuf(di) (dma64proc.dma_activerxbuf(di)) ++ ++#endif /* BCMDMA32 */ ++ ++/* return addresswidth allowed ++ * This needs to be done after SB attach but before dma attach. ++ * SB attach provides ability to probe backplane and dma core capabilities ++ * This info is needed by DMA_ALLOC_CONSISTENT in dma attach ++ */ ++extern uint dma_addrwidth(si_t *sih, void *dmaregs); ++ ++/* pio helpers */ ++extern void dma_txpioloopback(osl_t *osh, dma32regs_t *); ++ ++#endif /* _hnddma_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndfwd.h b/drivers/bcmdrivers/gmac/src/include/hndfwd.h +new file mode 100755 +index 0000000..1502804 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndfwd.h +@@ -0,0 +1,136 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND GMAC Forwarder ++ * When multiple ports from a switch to a dual core host processor are available ++ * each Wl MAC instance (wl0 and wl1) may be tied to each core. A forwarding ++ * driver would recieve/transmit packets from/to switch on behalf of the Wl ++ * driver per core, essentially translating each core of the host processor to ++ * be a WL MAC that is becomes just another "W"-LAN port on the switch. ++ * ++ * hndfwd.h provides the API for the Fwder network device driver and wl driver ++ * to register their respective transmit handlers as a per cpu object. ++ * ++ * HND Fwder in SMP assumes "dual" core: ++ * Core1: wl0=11ac ++ * Core0: wl1=11n + eth0 ++ * HND Fwder in Uniprocessor mode would use 2 units. ++ * ++ * $Id$ ++ */ ++ ++#ifndef _hndfwd_h_ ++#define _hndfwd_h_ ++ ++#if defined(GMAC3) ++ ++/* ++ * Multiple GMAC to Host SMP Model: The ethernet driver operates as a ++ * FWD: Forwarder to MAC Interface such as wl0, wl1 ++ * NTK: Ethernet Network Interface binding to network stack (via CTF) ++ */ ++#define DEV_FWDER_NAME "fwd" ++#define DEV_NTKIF(etc) ((etc)->gmac_fwd == FALSE) ++#define DEV_FWDER(etc) ((etc)->gmac_fwd == TRUE) ++ ++#if defined(CONFIG_SMP) ++#define _FWDER_LOCK(fwder) spin_lock_bh(&(fwder)->lock) ++#define _FWDER_UNLOCK(fwder) spin_unlock_bh(&(fwder)->lock) ++#else /* !CONFIG_SMP */ ++#define _FWDER_LOCK(fwder) local_bh_disable() ++#define _FWDER_UNLOCK(fwder) local_bh_enable() ++#endif /* !CONFIG_SMP */ ++ ++#define FWDER_FAILURE 1 ++#define FWDER_SUCCESS 0 ++ ++#define FWDER_DEBUG ++#define FWDER_MAX_UNITS 2 ++ ++/* hard start xmit handler of a network device driver */ ++typedef int (* fwder_start_t)(struct sk_buff * buff, struct net_device * dev, ++ int cnt); ++ ++typedef enum fwder_dir { ++ FWD_UPSTREAM, /* WL##(RX) -> GMAC(TX) Start Xmit Handler */ ++ FWD_DNSTREAM, /* GMAC(RX) -> Wl##(TX) Start Xmit Handler */ ++ FWD_MAX_DIRS ++} fwder_dir_t; ++ ++typedef struct fwder { ++ struct net_device * dev; ++ fwder_start_t forward; ++ int unit; ++ unsigned int error; ++#if defined(CONFIG_SMP) ++ spinlock_t lock; ++#endif /* CONFIG_SMP */ ++} fwder_t; ++ ++#if defined(CONFIG_SMP) ++DECLARE_PER_CPU(struct fwder, fwd_upstream); /* Per Core GMAC Transmit */ ++DECLARE_PER_CPU(struct fwder, fwd_dnstream); /* Per Core Wl## Transmit */ ++#else /* !CONFIG_SMP */ ++extern struct fwder fwd_upstream[FWDER_MAX_UNITS]; ++extern struct fwder fwd_dnstream[FWDER_MAX_UNITS]; ++#endif /* !CONFIG_SMP */ ++ ++extern int fwder_init(void); /* Invoked in eth0 module_init */ ++ ++/* Register a transmit handler and return the reverse dir handler */ ++extern struct fwder * fwder_attach(fwder_start_t forward, ++ const struct net_device * dev, const int unit, const enum fwder_dir dir); ++ ++/* Deregister a transmit handler */ ++extern struct fwder * fwder_dettach(struct fwder * fwder_p); ++ ++extern void fwder_dump(const struct fwder * fwder_p); ++extern void fwder_dump_all(void); ++ ++static inline int ++fwder_transmit(struct sk_buff * skb, struct net_device * dev, ++ struct fwder * fwder_p, int cnt) ++{ ++ int ret; ++ ++ ASSERT(fwder_p != (struct fwder*)NULL); ++ ++ _FWDER_LOCK(fwder_p); /* ++LOCK */ ++ ++ if (dev == (struct net_device *)NULL) { ++ skb->dev = (struct net_device *)fwder_p->dev; ++ } ++ ++ ret = fwder_p->forward(skb, skb->dev, cnt); ++ ++#if defined(FWDER_DEBUG) ++ if (ret == FWDER_FAILURE) ++ fwder_p->error++; ++#endif ++ ++ _FWDER_UNLOCK(fwder_p); /* --LOCK */ ++ ++ return ret; ++} ++ ++#else /* !GMAC3 */ ++ ++#define DEV_FWDER_NAME "eth" ++#define DEV_NTKIF(etc) 1 ++#define DEV_FWDER(etc) 0 ++ ++#endif /* !GMAC3 */ ++ ++#endif /* _hndfwd_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndsoc.h b/drivers/bcmdrivers/gmac/src/include/hndsoc.h +new file mode 100755 +index 0000000..ae3d3c3 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndsoc.h +@@ -0,0 +1,269 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom HND chip & on-chip-interconnect-related definitions. ++ * ++ * $Id: hndsoc.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _HNDSOC_H ++#define _HNDSOC_H ++ ++/* Include the soci specific files */ ++#include ++#include ++ ++/* ++ * SOC Interconnect Address Map. ++ * All regions may not exist on all chips. ++ */ ++#define SI_SDRAM_BASE 0x00000000 /* Physical SDRAM */ ++#define SI_PCI_MEM 0x08000000 /* Host Mode sb2pcitranslation0 (64 MB) */ ++#define SI_PCI_MEM_SZ (64 * 1024 * 1024) ++#define SI_PCI_CFG 0x0c000000 /* Host Mode sb2pcitranslation1 (64 MB) */ ++#define SI_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ ++#define SI_SDRAM_R2 0x80000000 /* Region 2 for sdram (512 MB) */ ++ ++#ifdef SI_ENUM_BASE_VARIABLE ++#define SI_ENUM_BASE (sii->pub.si_enum_base) ++#else ++#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ ++#endif /* SI_ENUM_BASE_VARIABLE */ ++ ++#define SI_WRAP_BASE 0x18100000 /* Wrapper space base */ ++#define SI_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */ ++#define SI_MAXCORES 20 /* Max cores (this is arbitrary, for software ++ * convenience and could be changed if we ++ * make any larger chips ++ */ ++ ++#define SI_FASTRAM 0x19000000 /* On-chip RAM on chips that also have DDR */ ++#define SI_FASTRAM_SWAPPED 0x19800000 ++ ++#define SI_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */ ++#define SI_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */ ++#define SI_ARMCM3_ROM 0x1e000000 /* ARM Cortex-M3 ROM */ ++#define SI_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */ ++#define SI_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */ ++ ++#define SI_NS_NANDFLASH 0x1c000000 /* NorthStar NAND flash base */ ++#define SI_NS_NORFLASH 0x1e000000 /* NorthStar NOR flash base */ ++#define SI_NS_NORFLASH_SZ 0x02000000 /* Size of NorthStar NOR flash region */ ++#define SI_NS_ROM 0xfffd0000 /* NorthStar ROM */ ++ ++#define SI_ARM7S_ROM 0x20000000 /* ARM7TDMI-S ROM */ ++#define SI_ARMCR4_ROM 0x000f0000 /* ARM Cortex-R4 ROM */ ++#define SI_ARMCM3_SRAM2 0x60000000 /* ARM Cortex-M3 SRAM Region 2 */ ++#define SI_ARM7S_SRAM2 0x80000000 /* ARM7TDMI-S SRAM Region 2 */ ++#define SI_ARM_FLASH1 0xffff0000 /* ARM Flash Region 1 */ ++#define SI_ARM_FLASH1_SZ 0x00010000 /* ARM Size of Flash Region 1 */ ++ ++#define SI_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */ ++#define SI_PCI_DMA2 0x80000000 /* Client Mode sb2pcitranslation2 (1 GB) */ ++#define SI_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */ ++#define SI_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), low 32 bits ++ */ ++#define SI_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), high 32 bits ++ */ ++#define SI_NS_CUR 0x1800B000 /* NorthStar CUR base */ ++ ++#if defined(CONFIG_MACH_NS) ++#define SI_NS_CHIPCB_SRAB 0x18007000 /* NorthStar Chip Common B SRAB base */ ++#else ++#define SI_NS_CHIPCB_SRAB 0x18036000 /* NorthStar+ Chip Common B SRAB base */ ++#endif ++ ++/* core codes */ ++#define NODEV_CORE_ID 0x700 /* Invalid coreid */ ++#define CC_CORE_ID 0x800 /* chipcommon core */ ++#define ILINE20_CORE_ID 0x801 /* iline20 core */ ++#define SRAM_CORE_ID 0x802 /* sram core */ ++#define SDRAM_CORE_ID 0x803 /* sdram core */ ++#define PCI_CORE_ID 0x804 /* pci core */ ++#define MIPS_CORE_ID 0x805 /* mips core */ ++#define ENET_CORE_ID 0x806 /* enet mac core */ ++#define CODEC_CORE_ID 0x807 /* v90 codec core */ ++#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ ++#define ADSL_CORE_ID 0x809 /* ADSL core */ ++#define ILINE100_CORE_ID 0x80a /* iline100 core */ ++#define IPSEC_CORE_ID 0x80b /* ipsec core */ ++#define UTOPIA_CORE_ID 0x80c /* utopia core */ ++#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ ++#define SOCRAM_CORE_ID 0x80e /* internal memory core */ ++#define MEMC_CORE_ID 0x80f /* memc sdram core */ ++#define OFDM_CORE_ID 0x810 /* OFDM phy core */ ++#define EXTIF_CORE_ID 0x811 /* external interface core */ ++#define D11_CORE_ID 0x812 /* 802.11 MAC core */ ++#define APHY_CORE_ID 0x813 /* 802.11a phy core */ ++#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ ++#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ ++#define MIPS33_CORE_ID 0x816 /* mips3302 core */ ++#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ ++#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ ++#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ ++#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ ++#define SDIOH_CORE_ID 0x81b /* sdio host core */ ++#define ROBO_CORE_ID 0x81c /* roboswitch core */ ++#define ATA100_CORE_ID 0x81d /* parallel ATA core */ ++#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ ++#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ ++#define PCIE_CORE_ID 0x820 /* pci express core */ ++#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ ++#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ ++#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ ++#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ ++#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ ++#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ ++#define PMU_CORE_ID 0x827 /* PMU core */ ++#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ ++#define SDIOD_CORE_ID 0x829 /* SDIO device core */ ++#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ ++#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ ++#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ ++#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ ++#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ ++#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ ++#define SC_CORE_ID 0x831 /* shared common core */ ++#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ ++#define SPIH_CORE_ID 0x833 /* SPI host core */ ++#define I2S_CORE_ID 0x834 /* I2S core */ ++#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ ++#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ ++ ++#define ACPHY_CORE_ID 0x83b /* Dot11 ACPHY */ ++#define PCIE2_CORE_ID 0x83c /* pci express Gen2 core */ ++#define USB30D_CORE_ID 0x83d /* usb 3.0 device core */ ++#define ARMCR4_CORE_ID 0x83e /* ARM CR4 CPU */ ++#define APB_BRIDGE_CORE_ID 0x135 /* APB bridge core ID */ ++#define AXI_CORE_ID 0x301 /* AXI/GPV core ID */ ++#define EROM_CORE_ID 0x366 /* EROM core ID */ ++#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ ++#define DEF_AI_COMP 0xfff /* Default component, in ai chips it maps all ++ * unused address ranges ++ */ ++ ++#define CC_4706_CORE_ID 0x500 /* chipcommon core */ ++#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++#define SOCRAM_4706_CORE_ID 0x50e /* internal memory core */ ++#define NS_SOCRAM_CORE_ID SOCRAM_4706_CORE_ID ++#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++#define NS_IHOST_CORE_ID ARMCA9_CORE_ID /* ARM Cortex A9 core (ihost) */ ++#define GMAC_COMMON_4706_CORE_ID 0x5dc /* Gigabit MAC core */ ++#define GMAC_4706_CORE_ID 0x52d /* Gigabit MAC core */ ++#define AMEMC_CORE_ID 0x52e /* DDR1/2 memory controller core */ ++#define ALTA_CORE_ID 0x534 /* I2S core */ ++#define DDR23_PHY_CORE_ID 0x5dd ++ ++#define SI_PCI1_MEM 0x40000000 /* Host Mode sb2pcitranslation0 (64 MB) */ ++#define SI_PCI1_CFG 0x44000000 /* Host Mode sb2pcitranslation1 (64 MB) */ ++#define SI_PCIE1_DMA_H32 0xc0000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), high 32 bits ++ */ ++#define CC_4706B0_CORE_REV 0x8000001f /* chipcommon core */ ++#define SOCRAM_4706B0_CORE_REV 0x80000005 /* internal memory core */ ++#define GMAC_4706B0_CORE_REV 0x80000000 /* Gigabit MAC core */ ++ ++/* There are TWO constants on all HND chips: SI_ENUM_BASE above, ++ * and chipcommon being the first core: ++ */ ++#define SI_CC_IDX 0 ++ ++/* SOC Interconnect types (aka chip types) */ ++#define SOCI_SB 0 ++#define SOCI_AI 1 ++#define SOCI_UBUS 2 ++#define SOCI_NS 3 ++ ++/* Common core control flags */ ++#define SICF_BIST_EN 0x8000 ++#define SICF_PME_EN 0x4000 ++#define SICF_CORE_BITS 0x3ffc ++#define SICF_FGC 0x0002 ++#define SICF_CLOCK_EN 0x0001 ++ ++/* Common core status flags */ ++#define SISF_BIST_DONE 0x8000 ++#define SISF_BIST_ERROR 0x4000 ++#define SISF_GATED_CLK 0x2000 ++#define SISF_DMA64 0x1000 ++#define SISF_CORE_BITS 0x0fff ++ ++/* Norstar core status flags */ ++#define SISF_NS_BOOTDEV_MASK 0x0003 /* ROM core */ ++#define SISF_NS_BOOTDEV_NOR 0x0000 /* ROM core */ ++#define SISF_NS_BOOTDEV_NAND 0x0001 /* ROM core */ ++#define SISF_NS_BOOTDEV_ROM 0x0002 /* ROM core */ ++#define SISF_NS_BOOTDEV_OFFLOAD 0x0003 /* ROM core */ ++#define SISF_NS_SKUVEC_MASK 0x000c /* ROM core */ ++ ++/* A register that is common to all cores to ++ * communicate w/PMU regarding clock control. ++ */ ++#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */ ++ ++/* clk_ctl_st register */ ++#define CCS_FORCEALP 0x00000001 /* force ALP request */ ++#define CCS_FORCEHT 0x00000002 /* force HT request */ ++#define CCS_FORCEILP 0x00000004 /* force ILP request */ ++#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */ ++#define CCS_HTAREQ 0x00000010 /* HT Avail Request */ ++#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */ ++#define CCS_HQCLKREQ 0x00000040 /* HQ Clock Required */ ++#define CCS_USBCLKREQ 0x00000100 /* USB Clock Req */ ++#define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */ ++#define CCS_ERSRC_REQ_SHIFT 8 ++#define CCS_ALPAVAIL 0x00010000 /* ALP is available */ ++#define CCS_HTAVAIL 0x00020000 /* HT is available */ ++#define CCS_BP_ON_APL 0x00040000 /* RO: Backplane is running on ALP clock */ ++#define CCS_BP_ON_HT 0x00080000 /* RO: Backplane is running on HT clock */ ++#define CCS_ERSRC_STS_MASK 0x07000000 /* external resource status */ ++#define CCS_ERSRC_STS_SHIFT 24 ++ ++#define CCS0_HTAVAIL 0x00010000 /* HT avail in chipc and pcmcia on 4328a0 */ ++#define CCS0_ALPAVAIL 0x00020000 /* ALP avail in chipc and pcmcia on 4328a0 */ ++ ++/* Not really related to SOC Interconnect, but a couple of software ++ * conventions for the use the flash space: ++ */ ++ ++/* Minumum amount of flash we support */ ++#define FLASH_MIN 0x00020000 /* Minimum flash size */ ++ ++/* A boot/binary may have an embedded block that describes its size */ ++#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */ ++#define BISZ_MAGIC 0x4249535a /* Marked with this value: 'BISZ' */ ++#define BISZ_MAGIC_IDX 0 /* Word 0: magic */ ++#define BISZ_TXTST_IDX 1 /* 1: text start */ ++#define BISZ_TXTEND_IDX 2 /* 2: text end */ ++#define BISZ_DATAST_IDX 3 /* 3: data start */ ++#define BISZ_DATAEND_IDX 4 /* 4: data end */ ++#define BISZ_BSSST_IDX 5 /* 5: bss start */ ++#define BISZ_BSSEND_IDX 6 /* 6: bss end */ ++#define BISZ_SIZE 7 /* descriptor size in 32-bit integers */ ++ ++#endif /* _HNDSOC_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndtcam.h b/drivers/bcmdrivers/gmac/src/include/hndtcam.h +new file mode 100755 +index 0000000..da7acf8 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndtcam.h +@@ -0,0 +1,95 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND SOCRAM TCAM software interface. ++ * ++ * $Id: hndtcam.h 317281 2012-02-27 11:23:27Z $ ++ */ ++#ifndef _hndtcam_h_ ++#define _hndtcam_h_ ++ ++/* ++ * 0 - 1 ++ * 1 - 2 Consecutive locations are patched ++ * 2 - 4 Consecutive locations are patched ++ * 3 - 8 Consecutive locations are patched ++ * 4 - 16 Consecutive locations are patched ++ * Define default to patch 2 locations ++ */ ++ ++#ifdef PATCHCOUNT ++#define SRPC_PATCHCOUNT PATCHCOUNT ++#else ++#define PATCHCOUNT 0 ++#define SRPC_PATCHCOUNT PATCHCOUNT ++#endif ++ ++#if defined(__ARM_ARCH_7R__) ++#ifndef PATCHCOUNT ++#define PATCHCOUNT 1 ++#endif ++#define ARMCR4_TCAMPATCHCOUNT PATCHCOUNT ++#define ARMCR4_TCAMADDR_MASK (~((1 << (ARMCR4_TCAMPATCHCOUNT + 2))-1)) ++#define ARMCR4_PATCHNLOC (1 << ARMCR4_TCAMPATCHCOUNT) ++#endif /* defined(__ARM_ARCH_7R__) */ ++ ++/* N Consecutive location to patch */ ++#define SRPC_PATCHNLOC (1 << (SRPC_PATCHCOUNT)) ++ ++#define PATCHHDR(_p) __attribute__ ((__section__ (".patchhdr."#_p))) _p ++#define PATCHENTRY(_p) __attribute__ ((__section__ (".patchentry."#_p))) _p ++ ++#if defined(__ARM_ARCH_7R__) ++typedef struct { ++ uint32 data[ARMCR4_PATCHNLOC]; ++} patch_entry_t; ++#else ++typedef struct { ++ uint32 data[SRPC_PATCHNLOC]; ++} patch_entry_t; ++#endif ++ ++typedef struct { ++ void *addr; /* patch address */ ++ uint32 len; /* bytes to patch in entry */ ++ patch_entry_t *entry; /* patch entry data */ ++} patch_hdr_t; ++ ++/* patch values and address structure */ ++typedef struct patchaddrvalue { ++ uint32 addr; ++ uint32 value; ++} patchaddrvalue_t; ++ ++extern void *socram_regs; ++extern uint32 socram_rev; ++ ++extern void *arm_regs; ++ ++extern void hnd_patch_init(void *srp); ++extern void hnd_tcam_write(void *srp, uint16 idx, uint32 data); ++extern void hnd_tcam_read(void *srp, uint16 idx, uint32 *content); ++void * hnd_tcam_init(void *srp, int no_addrs); ++extern void hnd_tcam_disablepatch(void *srp); ++extern void hnd_tcam_enablepatch(void *srp); ++#ifdef CONFIG_XIP ++extern void hnd_tcam_bootloader_load(void *srp, char *pvars); ++#else ++extern void hnd_tcam_load(void *srp, const patchaddrvalue_t *patchtbl); ++#endif /* CONFIG_XIP */ ++extern void BCMATTACHFN(hnd_tcam_load_default)(void); ++extern void hnd_tcam_reclaim(void); ++ ++#endif /* _hndtcam_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/linux_osl.h b/drivers/bcmdrivers/gmac/src/include/linux_osl.h +new file mode 100755 +index 0000000..e49878b +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/linux_osl.h +@@ -0,0 +1,979 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux OS Independent Layer ++ * ++ * $Id: linux_osl.h 329351 2012-04-25 01:48:39Z $ ++ */ ++ ++#ifndef _linux_osl_h_ ++#define _linux_osl_h_ ++ ++#include ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ ++/* Reuse some of existing code of CTFPOOL */ ++#ifndef CTFPOOL ++#define CTFPOOL ++#endif ++ ++/* #define SKB_RECYCLING_DEBUG */ ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++ ++/* Linux Kernel: File Operations: start */ ++extern void * osl_os_open_image(char * filename); ++extern int osl_os_get_image_block(char * buf, int len, void * image); ++extern void osl_os_close_image(void * image); ++extern int osl_os_image_size(void *image); ++/* Linux Kernel: File Operations: end */ ++ ++#ifdef BCMDRIVER ++ ++/* OSL initialization */ ++extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag); ++extern void osl_detach(osl_t *osh); ++ ++/* Global ASSERT type */ ++extern uint32 g_assert_type; ++ ++/* ASSERT */ ++ #ifdef __GNUC__ ++ #define GCC_VERSION \ ++ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) ++ #if GCC_VERSION > 30100 ++ #define ASSERT(exp) do {} while (0) ++ #else ++ /* ASSERT could cause segmentation fault on GCC3.1, use empty instead */ ++ #define ASSERT(exp) ++ #endif /* GCC_VERSION > 30100 */ ++ #endif /* __GNUC__ */ ++ ++/* microsecond delay */ ++#define OSL_DELAY(usec) osl_delay(usec) ++extern void osl_delay(uint usec); ++ ++#define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) \ ++ osl_pcmcia_read_attr((osh), (offset), (buf), (size)) ++#define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) \ ++ osl_pcmcia_write_attr((osh), (offset), (buf), (size)) ++extern void osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size); ++extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size); ++ ++/* PCI configuration space access macros */ ++#define OSL_PCI_READ_CONFIG(osh, offset, size) \ ++ osl_pci_read_config((osh), (offset), (size)) ++#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \ ++ osl_pci_write_config((osh), (offset), (size), (val)) ++extern uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size); ++extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val); ++ ++/* PCI device bus # and slot # */ ++#define OSL_PCI_BUS(osh) osl_pci_bus(osh) ++#define OSL_PCI_SLOT(osh) osl_pci_slot(osh) ++extern uint osl_pci_bus(osl_t *osh); ++extern uint osl_pci_slot(osl_t *osh); ++extern struct pci_dev *osl_pci_device(osl_t *osh); ++ ++/* Pkttag flag should be part of public information */ ++typedef struct { ++ bool pkttag; ++ bool mmbus; /* Bus supports memory-mapped register accesses */ ++ pktfree_cb_fn_t tx_fn; /* Callback function for PKTFREE */ ++ void *tx_ctx; /* Context to the callback function */ ++#ifdef OSLREGOPS ++ osl_rreg_fn_t rreg_fn; /* Read Register function */ ++ osl_wreg_fn_t wreg_fn; /* Write Register function */ ++ void *reg_ctx; /* Context to the reg callback functions */ ++#else ++ void *unused[3]; ++#endif ++} osl_pubinfo_t; ++ ++#define PKTFREESETCB(osh, _tx_fn, _tx_ctx) \ ++ do { \ ++ ((osl_pubinfo_t*)osh)->tx_fn = _tx_fn; \ ++ ((osl_pubinfo_t*)osh)->tx_ctx = _tx_ctx; \ ++ } while (0) ++ ++#ifdef OSLREGOPS ++#define REGOPSSET(osh, rreg, wreg, ctx) \ ++ do { \ ++ ((osl_pubinfo_t*)osh)->rreg_fn = rreg; \ ++ ((osl_pubinfo_t*)osh)->wreg_fn = wreg; \ ++ ((osl_pubinfo_t*)osh)->reg_ctx = ctx; \ ++ } while (0) ++#endif /* OSLREGOPS */ ++ ++/* host/bus architecture-specific byte swap */ ++// #define BUS_SWAP32(v) (v) /* JIRA:LINUXDEV-16 */ ++#ifdef IL_BIGENDIAN ++#define BUS_SWAP32(v) bcmswap32(v) ++#else ++#define BUS_SWAP32(v) (v) ++#endif /* IL_BIGENDIAN */ ++ ++ #define MALLOC(osh, size) osl_malloc((osh), (size)) ++ #define MFREE(osh, addr, size) osl_mfree((osh), (addr), (size)) ++ #define MALLOCED(osh) osl_malloced((osh)) ++ extern void *osl_malloc(osl_t *osh, uint size); ++ extern void osl_mfree(osl_t *osh, void *addr, uint size); ++ extern uint osl_malloced(osl_t *osh); ++ ++#define NATIVE_MALLOC(osh, size) kmalloc(size, GFP_ATOMIC) ++#define NATIVE_MFREE(osh, addr, size) kfree(addr) ++#ifdef USBAP ++#include ++#define VMALLOC(osh, size) vmalloc(size) ++#define VFREE(osh, addr, size) vfree(addr) ++#endif /* USBAP */ ++ ++#define MALLOC_FAILED(osh) osl_malloc_failed((osh)) ++extern uint osl_malloc_failed(osl_t *osh); ++ ++/* allocate/free shared (dma-able) consistent memory */ ++#define DMA_CONSISTENT_ALIGN osl_dma_consistent_align() ++#define DMA_ALLOC_CONSISTENT(osh, size, align, tot, pap, dmah) \ ++ osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap)) ++#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \ ++ osl_dma_free_consistent((osh), (void*)(va), (size), (pa)) ++extern uint osl_dma_consistent_align(void); ++extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align, uint *tot, ulong *pap); ++extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa); ++ ++/* map/unmap direction */ ++#define DMA_TX 1 /* TX direction for DMA */ ++#define DMA_RX 2 /* RX direction for DMA */ ++ ++/* map/unmap shared (dma-able) memory */ ++#define DMA_UNMAP(osh, pa, size, direction, p, dmah) \ ++ osl_dma_unmap((osh), (pa), (size), (direction)) ++extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah); ++extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); ++ ++/* API for DMA addressing capability */ ++#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0) ++ ++/* register access macros */ ++ ++ #define SELECT_BUS_WRITE(osh, mmap_op, bus_op) mmap_op ++ #define SELECT_BUS_READ(osh, mmap_op, bus_op) mmap_op ++ ++#define OSL_ERROR(bcmerror) osl_error(bcmerror) ++extern int osl_error(int bcmerror); ++ ++/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */ ++#define PKTBUFSZ 2048 /* largest reasonable packet buffer, driver uses for ethernet MTU */ ++ ++/* ++ * BINOSL selects the slightly slower function-call-based binary compatible osl. ++ * Macros expand to calls to functions defined in linux_osl.c . ++ */ ++#ifndef BINOSL ++#include /* use current 2.4.x calling conventions */ ++#include /* for vsn/printf's */ ++#include /* for mem*, str* */ ++ ++#define OSL_SYSUPTIME() ((uint32)jiffies * (1000 / HZ)) ++#define printf(fmt, args...) printk(fmt , ## args) ++#include /* for vsn/printf's */ ++#include /* for mem*, str* */ ++/* bcopy's: Linux kernel doesn't provide these (anymore) */ ++#define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++#define bzero(b, len) memset((b), '\0', (len)) ++ ++ ++/* register access macros */ ++#if defined(OSLREGOPS) ++#define R_REG(osh, r) (\ ++ sizeof(*(r)) == sizeof(uint8) ? osl_readb((osh), (volatile uint8*)(r)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? osl_readw((osh), (volatile uint16*)(r)) : \ ++ osl_readl((osh), (volatile uint32*)(r)) \ ++) ++#define W_REG(osh, r, v) do { \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): osl_writeb((osh), (volatile uint8*)(r), (uint8)(v)); break; \ ++ case sizeof(uint16): osl_writew((osh), (volatile uint16*)(r), (uint16)(v)); break; \ ++ case sizeof(uint32): osl_writel((osh), (volatile uint32*)(r), (uint32)(v)); break; \ ++ } \ ++} while (0) ++ ++extern uint8 osl_readb(osl_t *osh, volatile uint8 *r); ++extern uint16 osl_readw(osl_t *osh, volatile uint16 *r); ++extern uint32 osl_readl(osl_t *osh, volatile uint32 *r); ++extern void osl_writeb(osl_t *osh, volatile uint8 *r, uint8 v); ++extern void osl_writew(osl_t *osh, volatile uint16 *r, uint16 v); ++extern void osl_writel(osl_t *osh, volatile uint32 *r, uint32 v); ++#else /* OSLREGOPS */ ++ ++#ifndef IL_BIGENDIAN ++#ifndef __mips__ ++#define R_REG(osh, r) (\ ++ SELECT_BUS_READ(osh, \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ BCM_REFERENCE(osh); \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): __osl_v = \ ++ readb((volatile uint8*)(r)); break; \ ++ case sizeof(uint16): __osl_v = \ ++ readw((volatile uint16*)(r)); break; \ ++ case sizeof(uint32): __osl_v = \ ++ readl((volatile uint32*)(r)); break; \ ++ } \ ++ __osl_v; \ ++ }), \ ++ OSL_READ_REG(osh, r)) \ ++) ++#else /* __mips__ */ ++#define R_REG(osh, r) (\ ++ SELECT_BUS_READ(osh, \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ BCM_REFERENCE(osh); \ ++ __asm__ __volatile__("sync"); \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): __osl_v = \ ++ readb((volatile uint8*)(r)); break; \ ++ case sizeof(uint16): __osl_v = \ ++ readw((volatile uint16*)(r)); break; \ ++ case sizeof(uint32): __osl_v = \ ++ readl((volatile uint32*)(r)); break; \ ++ } \ ++ __asm__ __volatile__("sync"); \ ++ __osl_v; \ ++ }), \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ __asm__ __volatile__("sync"); \ ++ __osl_v = OSL_READ_REG(osh, r); \ ++ __asm__ __volatile__("sync"); \ ++ __osl_v; \ ++ })) \ ++) ++#endif /* __mips__ */ ++ ++#define W_REG(osh, r, v) do { \ ++ BCM_REFERENCE(osh); \ ++ SELECT_BUS_WRITE(osh, \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \ ++ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \ ++ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \ ++ }, \ ++ (OSL_WRITE_REG(osh, r, v))); \ ++ } while (0) ++#else /* IL_BIGENDIAN */ ++#define R_REG(osh, r) (\ ++ SELECT_BUS_READ(osh, \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ BCM_REFERENCE(osh); \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): __osl_v = \ ++ readb((volatile uint8*)((uintptr)(r)^3)); break; \ ++ case sizeof(uint16): __osl_v = \ ++ readw((volatile uint16*)((uintptr)(r)^2)); break; \ ++ case sizeof(uint32): __osl_v = \ ++ readl((volatile uint32*)(r)); break; \ ++ } \ ++ __osl_v; \ ++ }), \ ++ OSL_READ_REG(osh, r)) \ ++) ++#define W_REG(osh, r, v) do { \ ++ BCM_REFERENCE(osh); \ ++ SELECT_BUS_WRITE(osh, \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): writeb((uint8)(v), \ ++ (volatile uint8*)((uintptr)(r)^3)); break; \ ++ case sizeof(uint16): writew((uint16)(v), \ ++ (volatile uint16*)((uintptr)(r)^2)); break; \ ++ case sizeof(uint32): writel((uint32)(v), \ ++ (volatile uint32*)(r)); break; \ ++ }, \ ++ (OSL_WRITE_REG(osh, r, v))); \ ++ } while (0) ++#endif /* IL_BIGENDIAN */ ++#endif /* OSLREGOPS */ ++ ++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) ++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) ++ ++/* bcopy, bcmp, and bzero functions */ ++#define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++#define bzero(b, len) memset((b), '\0', (len)) ++ ++/* uncached/cached virtual address */ ++#ifdef __mips__ ++#include ++#define OSL_UNCACHED(va) ((void *)KSEG1ADDR((va))) ++#define OSL_CACHED(va) ((void *)KSEG0ADDR((va))) ++#else ++#define OSL_UNCACHED(va) ((void *)va) ++#define OSL_CACHED(va) ((void *)va) ++ ++/* ARM NorthStar */ ++#define OSL_CACHE_FLUSH(va, len) ++ ++#endif /* mips */ ++ ++#ifdef __mips__ ++#define OSL_PREF_RANGE_LD(va, sz) prefetch_range_PREF_LOAD_RETAINED(va, sz) ++#define OSL_PREF_RANGE_ST(va, sz) prefetch_range_PREF_STORE_RETAINED(va, sz) ++#else /* __mips__ */ ++#define OSL_PREF_RANGE_LD(va, sz) ++#define OSL_PREF_RANGE_ST(va, sz) ++#endif /* __mips__ */ ++ ++/* get processor cycle count */ ++#if defined(mips) ++#define OSL_GETCYCLES(x) ((x) = read_c0_count() * 2) ++#elif defined(__i386__) ++#define OSL_GETCYCLES(x) rdtscl((x)) ++#else ++#define OSL_GETCYCLES(x) ((x) = 0) ++#endif /* defined(mips) */ ++ ++/* dereference an address that may cause a bus exception */ ++#ifdef mips ++#if defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 17)) ++#define BUSPROBE(val, addr) panic("get_dbe() will not fixup a bus exception when compiled into"\ ++ " a module") ++#else ++#define BUSPROBE(val, addr) get_dbe((val), (addr)) ++#include ++#endif /* defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 17)) */ ++#else ++#define BUSPROBE(val, addr) ({ (val) = R_REG(NULL, (addr)); 0; }) ++#endif /* mips */ ++ ++/* map/unmap physical to virtual I/O */ ++#if !defined(CONFIG_MMC_MSM7X00A) ++#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size)) ++#else ++#define REG_MAP(pa, size) (void *)(0) ++#endif /* !defined(CONFIG_MMC_MSM7X00A */ ++#define REG_UNMAP(va) iounmap((va)) ++ ++/* shared (dma-able) memory access macros */ ++#define R_SM(r) *(r) ++#define W_SM(r, v) (*(r) = (v)) ++#define BZERO_SM(r, len) memset((r), '\0', (len)) ++ ++/* Because the non BINOSL implemenation of the PKT OSL routines are macros (for ++ * performance reasons), we need the Linux headers. ++ */ ++#include /* use current 2.4.x calling conventions */ ++ ++/* packet primitives */ ++#define PKTGET(osh, len, send) osl_pktget((osh), (len)) ++#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) ++#define PKTLIST_DUMP(osh, buf) ++#define PKTDBG_TRACE(osh, pkt, bit) ++#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) ++#ifdef DHD_USE_STATIC_BUF ++#define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len)) ++#define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send)) ++#endif /* DHD_USE_STATIC_BUF */ ++#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) ++#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) ++#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) ++#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail)) ++#define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next) ++#define PKTSETNEXT(osh, skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)) ++#define PKTSETLEN(osh, skb, len) __pskb_trim((struct sk_buff*)(skb), (len)) ++#define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes)) ++#define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes)) ++#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) ++#define PKTSETPOOL(osh, skb, x, y) do {} while (0) ++#define PKTPOOL(osh, skb) FALSE ++#define PKTSHRINK(osh, m) (m) ++ ++#ifdef CTFPOOL ++#define CTFPOOL_REFILL_THRESH 3 ++typedef struct ctfpool { ++ void *head; ++ spinlock_t lock; ++ uint max_obj; ++ uint curr_obj; ++ uint obj_size; ++ uint refills; ++ uint fast_allocs; ++ uint fast_frees; ++ uint slow_allocs; ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ int unit; ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++} ctfpool_t; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) && defined CONFIG_BCM_CTF2 ++#define FASTBUF (1 << 0) ++#define CTFBUF (1 << 1) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) &= (~CTFBUF)) ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) & CTFBUF) ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->pktc_flags) ++#else ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define FASTBUF (0xFFF00000) ++#else ++#define FASTBUF (1 << 4) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++#define CTFBUF (1 << 5) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~CTFBUF)) ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->ctfpool_tag) == FASTBUF) ++#else ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & FASTBUF) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & CTFBUF) ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->ctfpool_tag) ++#else ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++#endif /* 2.6.36 */ ++ ++#else ++#define FASTBUF (1 << 0) ++#define CTFBUF (1 << 1) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) &= (~CTFBUF)) ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) & CTFBUF) ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->__unused) ++#endif /* 2.6.22 */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->ctfpool) ++#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->ctfpool)->head) ++#else ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->ctfpool) ++#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->ctfpool)->head) ++#else ++#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->sk) ++#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->sk)->head) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++#endif ++ ++extern void *osl_ctfpool_add(osl_t *osh); ++extern void osl_ctfpool_replenish(osl_t *osh, uint thresh); ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++extern int32 osl_ctfpool_init(int unit, osl_t *osh, uint numobj, uint size); ++#else ++extern int32 osl_ctfpool_init(osl_t *osh, uint numobj, uint size); ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++extern void osl_ctfpool_cleanup(osl_t *osh); ++extern void osl_ctfpool_stats(osl_t *osh, void *b); ++#else ++#define FASTBUF (1 << 16) ++#define CTFBUF (1 << 17) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~CTFBUF)) ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & CTFBUF) ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len) ++#endif /* CTFPOOL */ ++ ++#ifdef CTFMAP ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#define CTFMAPPTR(osh, skb) (((struct sk_buff*)(skb))->sp) ++#else /* 2.6.14 */ ++#define CTFMAPPTR(osh, skb) (((struct sk_buff*)(skb))->list) ++#endif /* 2.6.14 */ ++ ++#define PKTCTFMAP(osh, p) \ ++do { \ ++ if (PKTISCTF(osh, p)) { \ ++ int32 sz; \ ++ sz = (uint32)(((struct sk_buff *)p)->end) - \ ++ (uint32)CTFMAPPTR(osh, p); \ ++ /* map the remaining unmapped area */ \ ++ if (sz > 0) { \ ++ _DMA_MAP(osh, (void *)CTFMAPPTR(osh, p), \ ++ sz, DMA_RX, p, NULL); \ ++ } \ ++ /* clear ctf buf flag */ \ ++ PKTCLRCTF(osh, p); \ ++ CTFMAPPTR(osh, p) = NULL; \ ++ } \ ++} while (0) ++#endif /* CTFMAP */ ++ ++#ifdef HNDCTF ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++#define SKIPCT (1 << 2) ++#define CHAINED (1 << 3) ++#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags |= SKIPCT) ++#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags &= (~SKIPCT)) ++#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags & SKIPCT) ++#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->pktc_flags |= CHAINED) ++#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->pktc_flags &= (~CHAINED)) ++#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->pktc_flags & CHAINED) ++#else ++#define SKIPCT (1 << 18) ++#define CHAINED (1 << 19) ++#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len |= SKIPCT) ++#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~SKIPCT)) ++#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len & SKIPCT) ++#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->mac_len |= CHAINED) ++#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~CHAINED)) ++#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->mac_len & CHAINED) ++#endif /* 2.6.36 */ ++#else /* 2.6.22 */ ++#define SKIPCT (1 << 2) ++#define CHAINED (1 << 3) ++#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused |= SKIPCT) ++#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~SKIPCT)) ++#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused & SKIPCT) ++#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->__unused |= CHAINED) ++#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~CHAINED)) ++#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->__unused & CHAINED) ++#endif /* 2.6.22 */ ++typedef struct ctf_mark { ++ uint32 value; ++} ctf_mark_t; ++#define CTF_MARK(m) (m.value) ++#else /* HNDCTF */ ++#define PKTSETSKIPCT(osh, skb) ++#define PKTCLRSKIPCT(osh, skb) ++#define PKTSKIPCT(osh, skb) ++#define PKTCLRCHAINED(osh, skb) ++#define PKTSETCHAINED(osh, skb) ++#define CTF_MARK(m) 0 ++#endif /* HNDCTF */ ++ ++#ifdef BCMFA ++#ifdef BCMFA_HW_HASH ++#define PKTSETFAHIDX(skb, idx) (((struct sk_buff*)(skb))->napt_idx = idx) ++#else ++#define PKTSETFAHIDX(skb, idx) ++#endif /* BCMFA_SW_HASH */ ++#define PKTGETFAHIDX(skb) (((struct sk_buff*)(skb))->napt_idx) ++#define PKTSETFADEV(skb, imp) (((struct sk_buff*)(skb))->dev = imp) ++#define PKTSETRXDEV(skb) (((struct sk_buff*)(skb))->rxdev = ((struct sk_buff*)(skb))->dev) ++ ++#define AUX_TCP_FIN_RST (1 << 0) ++#define AUX_FREED (1 << 1) ++#define PKTSETFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_TCP_FIN_RST) ++#define PKTCLRFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_TCP_FIN_RST)) ++#define PKTISFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_TCP_FIN_RST) ++#define PKTSETFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_FREED) ++#define PKTCLRFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_FREED)) ++#define PKTISFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_FREED) ++#define PKTISFABRIDGED(skb) PKTISFAAUX(skb) ++#else ++#define PKTISFAAUX(skb) (FALSE) ++#define PKTISFABRIDGED(skb) (FALSE) ++#define PKTISFAFREED(skb) (FALSE) ++ ++#define PKTCLRFAAUX(skb) ++#define PKTSETFAFREED(skb) ++#define PKTCLRFAFREED(skb) ++#endif /* BCMFA */ ++ ++extern void osl_pktfree(osl_t *osh, void *skb, bool send); ++extern void *osl_pktget_static(osl_t *osh, uint len); ++extern void osl_pktfree_static(osl_t *osh, void *skb, bool send); ++ ++extern void *osl_pkt_frmnative(osl_t *osh, void *skb); ++extern void *osl_pktget(osl_t *osh, uint len); ++extern void *osl_pktdup(osl_t *osh, void *skb); ++extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); ++#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), (struct sk_buff*)(skb)) ++#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_t *)(osh), (pkt)) ++ ++#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev) ++#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x)) ++#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority) ++#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x)) ++#define PKTSUMNEEDED(skb) (((struct sk_buff*)(skb))->ip_summed == CHECKSUM_HW) ++#define PKTSETSUMGOOD(skb, x) (((struct sk_buff*)(skb))->ip_summed = \ ++ ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE)) ++/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because skb->ip_summed is overloaded */ ++#define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned) ++ ++#ifdef CONFIG_NF_CONNTRACK_MARK ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#define PKTMARK(p) (((struct sk_buff *)(p))->mark) ++#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->mark = (m) ++#else /* !2.6.0 */ ++#define PKTMARK(p) (((struct sk_buff *)(p))->nfmark) ++#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->nfmark = (m) ++#endif /* 2.6.0 */ ++#else /* CONFIG_NF_CONNTRACK_MARK */ ++#define PKTMARK(p) 0 ++#define PKTSETMARK(p, m) ++#endif /* CONFIG_NF_CONNTRACK_MARK */ ++ ++#else /* BINOSL */ ++ ++/* Where to get the declarations for mem, str, printf, bcopy's? Two basic approaches. ++ * ++ * First, use the Linux header files and the C standard library replacmenent versions ++ * built-in to the kernel. Use this approach when compiling non hybrid code or compling ++ * the OS port files. The second approach is to use our own defines/prototypes and ++ * functions we have provided in the Linux OSL, i.e. linux_osl.c. Use this approach when ++ * compiling the files that make up the hybrid binary. We are ensuring we ++ * don't directly link to the kernel replacement routines from the hybrid binary. ++ * ++ * NOTE: The issue we are trying to avoid is any questioning of whether the ++ * hybrid binary is derived from Linux. The wireless common code (wlc) is designed ++ * to be OS independent through the use of the OSL API and thus the hybrid binary doesn't ++ * derive from the Linux kernel at all. But since we defined our OSL API to include ++ * a small collection of standard C library routines and these routines are provided in ++ * the kernel we want to avoid even the appearance of deriving at all even though clearly ++ * usage of a C standard library API doesn't represent a derivation from Linux. Lastly ++ * note at the time of this checkin 4 references to memcpy/memset could not be eliminated ++ * from the binary because they are created internally by GCC as part of things like ++ * structure assignment. I don't think the compiler should be doing this but there is ++ * no options to disable it on Intel architectures (there is for MIPS so somebody must ++ * agree with me). I may be able to even remove these references eventually with ++ * a GNU binutil such as objcopy via a symbol rename (i.e. memcpy to osl_memcpy). ++ */ ++#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) ++ #define printf(fmt, args...) printk(fmt , ## args) ++ #include /* for vsn/printf's */ ++ #include /* for mem*, str* */ ++ /* bcopy's: Linux kernel doesn't provide these (anymore) */ ++ #define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++ #define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++ #define bzero(b, len) memset((b), '\0', (len)) ++ ++ /* These are provided only because when compiling linux_osl.c there ++ * must be an explicit prototype (separate from the definition) because ++ * we are compiling with GCC option -Wstrict-prototypes. Conversely ++ * these could be placed directly in linux_osl.c. ++ */ ++ extern int osl_printf(const char *format, ...); ++ extern int osl_sprintf(char *buf, const char *format, ...); ++ extern int osl_snprintf(char *buf, size_t n, const char *format, ...); ++ extern int osl_vsprintf(char *buf, const char *format, va_list ap); ++ extern int osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap); ++ extern int osl_strcmp(const char *s1, const char *s2); ++ extern int osl_strncmp(const char *s1, const char *s2, uint n); ++ extern int osl_strlen(const char *s); ++ extern char* osl_strcpy(char *d, const char *s); ++ extern char* osl_strncpy(char *d, const char *s, uint n); ++ extern char* osl_strchr(const char *s, int c); ++ extern char* osl_strrchr(const char *s, int c); ++ extern void *osl_memset(void *d, int c, size_t n); ++ extern void *osl_memcpy(void *d, const void *s, size_t n); ++ extern void *osl_memmove(void *d, const void *s, size_t n); ++ extern int osl_memcmp(const void *s1, const void *s2, size_t n); ++#else ++ ++ /* In the below defines we undefine the macro first in case it is ++ * defined. This shouldn't happen because we are not using Linux ++ * header files but because our Linux 2.4 make includes modversions.h ++ * through a GCC -include compile option, they get defined to point ++ * at the appropriate versioned symbol name. Note this doesn't ++ * happen with our Linux 2.6 makes. ++ */ ++ ++ /* *printf functions */ ++ #include /* va_list needed for v*printf */ ++ #include /* size_t needed for *nprintf */ ++ #undef printf ++ #undef sprintf ++ #undef snprintf ++ #undef vsprintf ++ #undef vsnprintf ++ #define printf(fmt, args...) osl_printf((fmt) , ## args) ++ #define sprintf(buf, fmt, args...) osl_sprintf((buf), (fmt) , ## args) ++ #define snprintf(buf, n, fmt, args...) osl_snprintf((buf), (n), (fmt) , ## args) ++ #define vsprintf(buf, fmt, ap) osl_vsprintf((buf), (fmt), (ap)) ++ #define vsnprintf(buf, n, fmt, ap) osl_vsnprintf((buf), (n), (fmt), (ap)) ++ extern int osl_printf(const char *format, ...); ++ extern int osl_sprintf(char *buf, const char *format, ...); ++ extern int osl_snprintf(char *buf, size_t n, const char *format, ...); ++ extern int osl_vsprintf(char *buf, const char *format, va_list ap); ++ extern int osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap); ++ ++ /* str* functions */ ++ #undef strcmp ++ #undef strncmp ++ #undef strlen ++ #undef strcpy ++ #undef strncpy ++ #undef strchr ++ #undef strrchr ++ #define strcmp(s1, s2) osl_strcmp((s1), (s2)) ++ #define strncmp(s1, s2, n) osl_strncmp((s1), (s2), (n)) ++ #define strlen(s) osl_strlen((s)) ++ #define strcpy(d, s) osl_strcpy((d), (s)) ++ #define strncpy(d, s, n) osl_strncpy((d), (s), (n)) ++ #define strchr(s, c) osl_strchr((s), (c)) ++ #define strrchr(s, c) osl_strrchr((s), (c)) ++ extern int osl_strcmp(const char *s1, const char *s2); ++ extern int osl_strncmp(const char *s1, const char *s2, uint n); ++ extern int osl_strlen(const char *s); ++ extern char* osl_strcpy(char *d, const char *s); ++ extern char* osl_strncpy(char *d, const char *s, uint n); ++ extern char* osl_strchr(const char *s, int c); ++ extern char* osl_strrchr(const char *s, int c); ++ ++ /* mem* functions */ ++ #undef memset ++ #undef memcpy ++ #undef memcmp ++ #define memset(d, c, n) osl_memset((d), (c), (n)) ++ #define memcpy(d, s, n) osl_memcpy((d), (s), (n)) ++ #define memmove(d, s, n) osl_memmove((d), (s), (n)) ++ #define memcmp(s1, s2, n) osl_memcmp((s1), (s2), (n)) ++ extern void *osl_memset(void *d, int c, size_t n); ++ extern void *osl_memcpy(void *d, const void *s, size_t n); ++ extern void *osl_memmove(void *d, const void *s, size_t n); ++ extern int osl_memcmp(const void *s1, const void *s2, size_t n); ++ ++ /* bcopy, bcmp, and bzero functions */ ++ #undef bcopy ++ #undef bcmp ++ #undef bzero ++ #define bcopy(src, dst, len) osl_memcpy((dst), (src), (len)) ++ #define bcmp(b1, b2, len) osl_memcmp((b1), (b2), (len)) ++ #define bzero(b, len) osl_memset((b), '\0', (len)) ++#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ ++ ++/* register access macros */ ++#define R_REG(osh, r) (\ ++ sizeof(*(r)) == sizeof(uint8) ? osl_readb((volatile uint8*)(r)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? osl_readw((volatile uint16*)(r)) : \ ++ osl_readl((volatile uint32*)(r)) \ ++) ++#define W_REG(osh, r, v) do { \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): osl_writeb((uint8)(v), (volatile uint8*)(r)); break; \ ++ case sizeof(uint16): osl_writew((uint16)(v), (volatile uint16*)(r)); break; \ ++ case sizeof(uint32): osl_writel((uint32)(v), (volatile uint32*)(r)); break; \ ++ } \ ++} while (0) ++ ++/* else added by johnvb to make sdio and jtag work with BINOSL, at least compile ... UNTESTED */ ++ ++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) ++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) ++extern uint8 osl_readb(volatile uint8 *r); ++extern uint16 osl_readw(volatile uint16 *r); ++extern uint32 osl_readl(volatile uint32 *r); ++extern void osl_writeb(uint8 v, volatile uint8 *r); ++extern void osl_writew(uint16 v, volatile uint16 *r); ++extern void osl_writel(uint32 v, volatile uint32 *r); ++ ++/* system up time in ms */ ++#define OSL_SYSUPTIME() osl_sysuptime() ++extern uint32 osl_sysuptime(void); ++ ++/* uncached/cached virtual address */ ++#define OSL_UNCACHED(va) osl_uncached((va)) ++extern void *osl_uncached(void *va); ++#define OSL_CACHED(va) osl_cached((va)) ++extern void *osl_cached(void *va); ++ ++#define OSL_PREF_RANGE_LD(va, sz) ++#define OSL_PREF_RANGE_ST(va, sz) ++ ++/* get processor cycle count */ ++#define OSL_GETCYCLES(x) ((x) = osl_getcycles()) ++extern uint osl_getcycles(void); ++ ++/* dereference an address that may target abort */ ++#define BUSPROBE(val, addr) osl_busprobe(&(val), (addr)) ++extern int osl_busprobe(uint32 *val, uint32 addr); ++ ++/* map/unmap physical to virtual */ ++#define REG_MAP(pa, size) osl_reg_map((pa), (size)) ++#define REG_UNMAP(va) osl_reg_unmap((va)) ++extern void *osl_reg_map(uint32 pa, uint size); ++extern void osl_reg_unmap(void *va); ++ ++/* shared (dma-able) memory access macros */ ++#define R_SM(r) *(r) ++#define W_SM(r, v) (*(r) = (v)) ++#define BZERO_SM(r, len) bzero((r), (len)) ++ ++/* packet primitives */ ++#define PKTGET(osh, len, send) osl_pktget((osh), (len)) ++#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) ++#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative((osh), (skb)) ++#define PKTLIST_DUMP(osh, buf) ++#define PKTDBG_TRACE(osh, pkt, bit) ++#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) ++#define PKTDATA(osh, skb) osl_pktdata((osh), (skb)) ++#define PKTLEN(osh, skb) osl_pktlen((osh), (skb)) ++#define PKTHEADROOM(osh, skb) osl_pktheadroom((osh), (skb)) ++#define PKTTAILROOM(osh, skb) osl_pkttailroom((osh), (skb)) ++#define PKTNEXT(osh, skb) osl_pktnext((osh), (skb)) ++#define PKTSETNEXT(osh, skb, x) osl_pktsetnext((skb), (x)) ++#define PKTSETLEN(osh, skb, len) osl_pktsetlen((osh), (skb), (len)) ++#define PKTPUSH(osh, skb, bytes) osl_pktpush((osh), (skb), (bytes)) ++#define PKTPULL(osh, skb, bytes) osl_pktpull((osh), (skb), (bytes)) ++#define PKTTAG(skb) osl_pkttag((skb)) ++#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osh), (pkt)) ++#define PKTLINK(skb) osl_pktlink((skb)) ++#define PKTSETLINK(skb, x) osl_pktsetlink((skb), (x)) ++#define PKTPRIO(skb) osl_pktprio((skb)) ++#define PKTSETPRIO(skb, x) osl_pktsetprio((skb), (x)) ++#define PKTSHARED(skb) osl_pktshared((skb)) ++#define PKTSETPOOL(osh, skb, x, y) do {} while (0) ++#define PKTPOOL(osh, skb) FALSE ++ ++extern void *osl_pktget(osl_t *osh, uint len); ++extern void *osl_pktdup(osl_t *osh, void *skb); ++extern void *osl_pkt_frmnative(osl_t *osh, void *skb); ++extern void osl_pktfree(osl_t *osh, void *skb, bool send); ++extern uchar *osl_pktdata(osl_t *osh, void *skb); ++extern uint osl_pktlen(osl_t *osh, void *skb); ++extern uint osl_pktheadroom(osl_t *osh, void *skb); ++extern uint osl_pkttailroom(osl_t *osh, void *skb); ++extern void *osl_pktnext(osl_t *osh, void *skb); ++extern void osl_pktsetnext(void *skb, void *x); ++extern void osl_pktsetlen(osl_t *osh, void *skb, uint len); ++extern uchar *osl_pktpush(osl_t *osh, void *skb, int bytes); ++extern uchar *osl_pktpull(osl_t *osh, void *skb, int bytes); ++extern void *osl_pkttag(void *skb); ++extern void *osl_pktlink(void *skb); ++extern void osl_pktsetlink(void *skb, void *x); ++extern uint osl_pktprio(void *skb); ++extern void osl_pktsetprio(void *skb, uint x); ++extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); ++extern bool osl_pktshared(void *skb); ++ ++ ++#endif /* BINOSL */ ++ ++#define PKTALLOCED(osh) osl_pktalloced(osh) ++extern uint osl_pktalloced(osl_t *osh); ++ ++#ifdef CTFMAP ++#include ++#define CTFMAPSZ 320 ++#define DMA_MAP(osh, va, size, direction, p, dmah) \ ++({ \ ++ typeof(size) sz = (size); \ ++ if (PKTISCTF((osh), (p))) { \ ++ sz = CTFMAPSZ; \ ++ CTFMAPPTR((osh), (p)) = (void *)(((uint8 *)(va)) + CTFMAPSZ); \ ++ } \ ++ osl_dma_map((osh), (va), sz, (direction), (p), (dmah)); \ ++}) ++#define _DMA_MAP(osh, va, size, direction, p, dmah) \ ++ osl_dma_map((osh), (va), (size), (direction), (p), (dmah)) ++#else /* CTFMAP */ ++#define DMA_MAP(osh, va, size, direction, p, dmah) \ ++ osl_dma_map((osh), (va), (size), (direction), (p), (dmah)) ++#endif /* CTFMAP */ ++ ++#ifdef PKTC ++/* Use 8 bytes of skb tstamp field to store below info */ ++struct chain_node { ++ struct sk_buff *link; ++ unsigned int flags:3, pkts:9, bytes:20; ++}; ++ ++#define CHAIN_NODE(skb) ((struct chain_node*)(((struct sk_buff*)skb)->pktc_cb)) ++ ++#define PKTCSETATTR(s, f, p, b) ({CHAIN_NODE(s)->flags = (f); CHAIN_NODE(s)->pkts = (p); \ ++ CHAIN_NODE(s)->bytes = (b);}) ++#define PKTCCLRATTR(s) ({CHAIN_NODE(s)->flags = CHAIN_NODE(s)->pkts = \ ++ CHAIN_NODE(s)->bytes = 0;}) ++#define PKTCGETATTR(s) (CHAIN_NODE(s)->flags << 29 | CHAIN_NODE(s)->pkts << 20 | \ ++ CHAIN_NODE(s)->bytes) ++#define PKTCCNT(skb) (CHAIN_NODE(skb)->pkts) ++#define PKTCLEN(skb) (CHAIN_NODE(skb)->bytes) ++#define PKTCGETFLAGS(skb) (CHAIN_NODE(skb)->flags) ++#define PKTCSETFLAGS(skb, f) (CHAIN_NODE(skb)->flags = (f)) ++#define PKTCCLRFLAGS(skb) (CHAIN_NODE(skb)->flags = 0) ++#define PKTCFLAGS(skb) (CHAIN_NODE(skb)->flags) ++#define PKTCSETCNT(skb, c) (CHAIN_NODE(skb)->pkts = (c)) ++#define PKTCINCRCNT(skb) (CHAIN_NODE(skb)->pkts++) ++#define PKTCADDCNT(skb, c) (CHAIN_NODE(skb)->pkts += (c)) ++#define PKTCSETLEN(skb, l) (CHAIN_NODE(skb)->bytes = (l)) ++#define PKTCADDLEN(skb, l) (CHAIN_NODE(skb)->bytes += (l)) ++#define PKTCSETFLAG(skb, fb) (CHAIN_NODE(skb)->flags |= (fb)) ++#define PKTCCLRFLAG(skb, fb) (CHAIN_NODE(skb)->flags &= ~(fb)) ++#define PKTCLINK(skb) (CHAIN_NODE(skb)->link) ++#define PKTSETCLINK(skb, x) (CHAIN_NODE(skb)->link = (struct sk_buff*)(x)) ++#define FOREACH_CHAINED_PKT(skb, nskb) \ ++ for (; (skb) != NULL; (skb) = (nskb)) \ ++ if ((nskb) = (PKTISCHAINED(skb) ? PKTCLINK(skb) : NULL), \ ++ PKTSETCLINK((skb), NULL), 1) ++#define PKTCFREE(osh, skb, send) \ ++do { \ ++ void *nskb; \ ++ ASSERT((skb) != NULL); \ ++ FOREACH_CHAINED_PKT((skb), nskb) { \ ++ PKTCLRCHAINED((osh), (skb)); \ ++ PKTCCLRFLAGS((skb)); \ ++ PKTFREE((osh), (skb), (send)); \ ++ } \ ++} while (0) ++#define PKTCENQTAIL(h, t, p) \ ++do { \ ++ if ((t) == NULL) { \ ++ (h) = (t) = (p); \ ++ } else { \ ++ PKTSETCLINK((t), (p)); \ ++ (t) = (p); \ ++ } \ ++} while (0) ++#endif /* PKTC */ ++ ++#else /* ! BCMDRIVER */ ++ ++ ++/* ASSERT */ ++ #define ASSERT(exp) do {} while (0) ++ ++/* MALLOC and MFREE */ ++#define MALLOC(o, l) malloc(l) ++#define MFREE(o, p, l) free(p) ++#include ++ ++/* str* and mem* functions */ ++#include ++ ++/* *printf functions */ ++#include ++ ++/* bcopy, bcmp, and bzero */ ++extern void bcopy(const void *src, void *dst, size_t len); ++extern int bcmp(const void *b1, const void *b2, size_t len); ++extern void bzero(void *b, size_t len); ++#endif /* ! BCMDRIVER */ ++ ++#endif /* _linux_osl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/linuxver.h b/drivers/bcmdrivers/gmac/src/include/linuxver.h +new file mode 100755 +index 0000000..6150c05 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/linuxver.h +@@ -0,0 +1,662 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux-specific abstractions to gain some independence from linux kernel versions. ++ * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences. ++ * ++ * $Id: linuxver.h 312774 2012-02-03 22:20:14Z $ ++ */ ++ ++#ifndef _linuxver_h_ ++#define _linuxver_h_ ++ ++#include ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++#include ++#else ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) ++#include ++#else ++#include ++#endif ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ ++#include ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)) ++/* __NO_VERSION__ must be defined for all linkables except one in 2.2 */ ++#ifdef __UNDEF_NO_VERSION__ ++#undef __NO_VERSION__ ++#else ++#define __NO_VERSION__ ++#endif ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) ++#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i") ++#define module_param_string(_name_, _string_, _size_, _perm_) \ ++ MODULE_PARM(_string_, "c" __MODULE_STRING(_size_)) ++#endif ++ ++/* linux/malloc.h is deprecated, use linux/slab.h instead. */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9)) ++#include ++#else ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#include ++#else ++#include ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) ++#undef IP_TOS ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) */ ++#include ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41)) ++#include ++#else ++#include ++#ifndef work_struct ++#define work_struct tq_struct ++#endif ++#ifndef INIT_WORK ++#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data)) ++#endif ++#ifndef schedule_work ++#define schedule_work(_work) schedule_task((_work)) ++#endif ++#ifndef flush_scheduled_work ++#define flush_scheduled_work() flush_scheduled_tasks() ++#endif ++#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) ++#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func) ++#else ++#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func, _work) ++typedef void (*work_func_t)(void *work); ++#endif /* >= 2.6.20 */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++/* Some distributions have their own 2.6.x compatibility layers */ ++#ifndef IRQ_NONE ++typedef void irqreturn_t; ++#define IRQ_NONE ++#define IRQ_HANDLED ++#define IRQ_RETVAL(x) ++#endif ++#else ++typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs); ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) ++#define IRQF_SHARED SA_SHIRQ ++#endif /* < 2.6.18 */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17) ++#ifdef CONFIG_NET_RADIO ++#define CONFIG_WIRELESS_EXT ++#endif ++#endif /* < 2.6.17 */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) ++#define MOD_INC_USE_COUNT ++#define MOD_DEC_USE_COUNT ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) ++#include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) ++#include ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) ++#include ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#include ++#endif ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) */ ++ ++#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) ++#include ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ++#include ++#include ++#endif ++#include ++#include ++#include ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 69)) ++/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which ++ * does this, but it's not in 2.4 so we do our own for now. ++ */ ++static inline void ++cs_error(client_handle_t handle, int func, int ret) ++{ ++ error_info_t err = { func, ret }; ++ CardServices(ReportError, handle, &err); ++} ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 16)) ++ ++typedef struct pcmcia_device dev_link_t; ++ ++#endif ++ ++#endif /* CONFIG_PCMCIA */ ++ ++#ifndef __exit ++#define __exit ++#endif ++#ifndef __devexit ++#define __devexit ++#endif ++#ifndef __devinit ++#define __devinit __init ++#endif ++#ifndef __devinitdata ++#define __devinitdata ++#endif ++#ifndef __devexit_p ++#define __devexit_p(x) x ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)) ++ ++#define pci_get_drvdata(dev) (dev)->sysdata ++#define pci_set_drvdata(dev, value) (dev)->sysdata = (value) ++ ++/* ++ * New-style (2.4.x) PCI/hot-pluggable PCI/CardBus registration ++ */ ++ ++struct pci_device_id { ++ unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ ++ unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ ++ unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ ++ unsigned long driver_data; /* Data private to the driver */ ++}; ++ ++struct pci_driver { ++ struct list_head node; ++ char *name; ++ const struct pci_device_id *id_table; /* NULL if wants all devices */ ++ int (*probe)(struct pci_dev *dev, ++ const struct pci_device_id *id); /* New device inserted */ ++ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug ++ * capable driver) ++ */ ++ void (*suspend)(struct pci_dev *dev); /* Device suspended */ ++ void (*resume)(struct pci_dev *dev); /* Device woken up */ ++}; ++ ++#define MODULE_DEVICE_TABLE(type, name) ++#define PCI_ANY_ID (~0) ++ ++/* compatpci.c */ ++#define pci_module_init pci_register_driver ++extern int pci_register_driver(struct pci_driver *drv); ++extern void pci_unregister_driver(struct pci_driver *drv); ++ ++#endif /* PCI registration */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)) ++#define pci_module_init pci_register_driver ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)) ++#ifdef MODULE ++#define module_init(x) int init_module(void) { return x(); } ++#define module_exit(x) void cleanup_module(void) { x(); } ++#else ++#define module_init(x) __initcall(x); ++#define module_exit(x) __exitcall(x); ++#endif ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) ++#define WL_USE_NETDEV_OPS ++#else ++#undef WL_USE_NETDEV_OPS ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) && defined(CONFIG_RFKILL) ++#define WL_CONFIG_RFKILL ++#else ++#undef WL_CONFIG_RFKILL ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48)) ++#define list_for_each(pos, head) \ ++ for (pos = (head)->next; pos != (head); pos = pos->next) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13)) ++#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)]) ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44)) ++#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23)) ++#define pci_enable_device(dev) do { } while (0) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14)) ++#define net_device device ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42)) ++ ++/* ++ * DMA mapping ++ * ++ * See linux/Documentation/DMA-mapping.txt ++ */ ++ ++#ifndef PCI_DMA_TODEVICE ++#define PCI_DMA_TODEVICE 1 ++#define PCI_DMA_FROMDEVICE 2 ++#endif ++ ++typedef u32 dma_addr_t; ++ ++/* Pure 2^n version of get_order */ ++static inline int get_order(unsigned long size) ++{ ++ int order; ++ ++ size = (size-1) >> (PAGE_SHIFT-1); ++ order = -1; ++ do { ++ size >>= 1; ++ order++; ++ } while (size); ++ return order; ++} ++ ++static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, ++ dma_addr_t *dma_handle) ++{ ++ void *ret; ++ int gfp = GFP_ATOMIC | GFP_DMA; ++ ++ ret = (void *)__get_free_pages(gfp, get_order(size)); ++ ++ if (ret != NULL) { ++ memset(ret, 0, size); ++ *dma_handle = virt_to_bus(ret); ++ } ++ return ret; ++} ++static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, ++ void *vaddr, dma_addr_t dma_handle) ++{ ++ free_pages((unsigned long)vaddr, get_order(size)); ++} ++#ifdef ILSIM ++extern uint pci_map_single(void *dev, void *va, uint size, int direction); ++extern void pci_unmap_single(void *dev, uint pa, uint size, int direction); ++#else ++#define pci_map_single(cookie, address, size, dir) virt_to_bus(address) ++#define pci_unmap_single(cookie, address, size, dir) ++#endif ++ ++#endif /* DMA mapping */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43)) ++ ++#define dev_kfree_skb_any(a) dev_kfree_skb(a) ++#define netif_down(dev) do { (dev)->start = 0; } while (0) ++ ++/* pcmcia-cs provides its own netdevice compatibility layer */ ++#ifndef _COMPAT_NETDEVICE_H ++ ++/* ++ * SoftNet ++ * ++ * For pre-softnet kernels we need to tell the upper layer not to ++ * re-enter start_xmit() while we are in there. However softnet ++ * guarantees not to enter while we are in there so there is no need ++ * to do the netif_stop_queue() dance unless the transmit queue really ++ * gets stuck. This should also improve performance according to tests ++ * done by Aman Singla. ++ */ ++ ++#define dev_kfree_skb_irq(a) dev_kfree_skb(a) ++#define netif_wake_queue(dev) \ ++ do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while (0) ++#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy) ++ ++static inline void netif_start_queue(struct net_device *dev) ++{ ++ dev->tbusy = 0; ++ dev->interrupt = 0; ++ dev->start = 1; ++} ++ ++#define netif_queue_stopped(dev) (dev)->tbusy ++#define netif_running(dev) (dev)->start ++ ++#endif /* _COMPAT_NETDEVICE_H */ ++ ++#define netif_device_attach(dev) netif_start_queue(dev) ++#define netif_device_detach(dev) netif_stop_queue(dev) ++ ++/* 2.4.x renamed bottom halves to tasklets */ ++#define tasklet_struct tq_struct ++static inline void tasklet_schedule(struct tasklet_struct *tasklet) ++{ ++ queue_task(tasklet, &tq_immediate); ++ mark_bh(IMMEDIATE_BH); ++} ++ ++static inline void tasklet_init(struct tasklet_struct *tasklet, ++ void (*func)(unsigned long), ++ unsigned long data) ++{ ++ tasklet->next = NULL; ++ tasklet->sync = 0; ++ tasklet->routine = (void (*)(void *))func; ++ tasklet->data = (void *)data; ++} ++#define tasklet_kill(tasklet) { do {} while (0); } ++ ++/* 2.4.x introduced del_timer_sync() */ ++#define del_timer_sync(timer) del_timer(timer) ++ ++#else ++ ++#define netif_down(dev) ++ ++#endif /* SoftNet */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3)) ++ ++/* ++ * Emit code to initialise a tq_struct's routine and data pointers ++ */ ++#define PREPARE_TQUEUE(_tq, _routine, _data) \ ++ do { \ ++ (_tq)->routine = _routine; \ ++ (_tq)->data = _data; \ ++ } while (0) ++ ++/* ++ * Emit code to initialise all of a tq_struct ++ */ ++#define INIT_TQUEUE(_tq, _routine, _data) \ ++ do { \ ++ INIT_LIST_HEAD(&(_tq)->list); \ ++ (_tq)->sync = 0; \ ++ PREPARE_TQUEUE((_tq), (_routine), (_data)); \ ++ } while (0) ++ ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3) */ ++ ++/* Power management related macro & routines */ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 9) ++#define PCI_SAVE_STATE(a, b) pci_save_state(a) ++#define PCI_RESTORE_STATE(a, b) pci_restore_state(a) ++#else ++#define PCI_SAVE_STATE(a, b) pci_save_state(a, b) ++#define PCI_RESTORE_STATE(a, b) pci_restore_state(a, b) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6)) ++static inline int ++pci_save_state(struct pci_dev *dev, u32 *buffer) ++{ ++ int i; ++ if (buffer) { ++ for (i = 0; i < 16; i++) ++ pci_read_config_dword(dev, i * 4, &buffer[i]); ++ } ++ return 0; ++} ++ ++static inline int ++pci_restore_state(struct pci_dev *dev, u32 *buffer) ++{ ++ int i; ++ ++ if (buffer) { ++ for (i = 0; i < 16; i++) ++ pci_write_config_dword(dev, i * 4, buffer[i]); ++ } ++ /* ++ * otherwise, write the context information we know from bootup. ++ * This works around a problem where warm-booting from Windows ++ * combined with a D3(hot)->D0 transition causes PCI config ++ * header data to be forgotten. ++ */ ++ else { ++ for (i = 0; i < 6; i ++) ++ pci_write_config_dword(dev, ++ PCI_BASE_ADDRESS_0 + (i * 4), ++ pci_resource_start(dev, i)); ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); ++ } ++ return 0; ++} ++#endif /* PCI power management */ ++ ++/* Old cp0 access macros deprecated in 2.4.19 */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19)) ++#define read_c0_count() read_32bit_cp0_register(CP0_COUNT) ++#endif ++ ++/* Module refcount handled internally in 2.6.x */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) ++#ifndef SET_MODULE_OWNER ++#define SET_MODULE_OWNER(dev) do {} while (0) ++#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT ++#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT ++#else ++#define OLD_MOD_INC_USE_COUNT do {} while (0) ++#define OLD_MOD_DEC_USE_COUNT do {} while (0) ++#endif ++#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */ ++#ifndef SET_MODULE_OWNER ++#define SET_MODULE_OWNER(dev) do {} while (0) ++#endif ++#ifndef MOD_INC_USE_COUNT ++#define MOD_INC_USE_COUNT do {} while (0) ++#endif ++#ifndef MOD_DEC_USE_COUNT ++#define MOD_DEC_USE_COUNT do {} while (0) ++#endif ++#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT ++#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */ ++ ++#ifndef SET_NETDEV_DEV ++#define SET_NETDEV_DEV(net, pdev) do {} while (0) ++#endif ++ ++#ifndef HAVE_FREE_NETDEV ++#define free_netdev(dev) kfree(dev) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++/* struct packet_type redefined in 2.6.x */ ++#define af_packet_priv data ++#endif ++ ++/* suspend args */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) ++#define DRV_SUSPEND_STATE_TYPE pm_message_t ++#else ++#define DRV_SUSPEND_STATE_TYPE uint32 ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) ++#define CHECKSUM_HW CHECKSUM_PARTIAL ++#endif ++ ++typedef struct { ++ void *parent; /* some external entity that the thread supposed to work for */ ++ struct task_struct *p_task; ++ long thr_pid; ++ int prio; /* priority */ ++ struct semaphore sema; ++ int terminated; ++ struct completion completed; ++} tsk_ctl_t; ++ ++ ++/* requires tsk_ctl_t tsk argument, the caller's priv data is passed in owner ptr */ ++/* note this macro assumes there may be only one context waiting on thread's completion */ ++#ifdef DHD_DEBUG ++#define DBG_THR(x) printk x ++#else ++#define DBG_THR(x) ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x) ++#else ++#define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x) ++#endif ++ ++ ++#define PROC_START(thread_func, owner, tsk_ctl, flags) \ ++{ \ ++ sema_init(&((tsk_ctl)->sema), 0); \ ++ init_completion(&((tsk_ctl)->completed)); \ ++ (tsk_ctl)->parent = owner; \ ++ (tsk_ctl)->terminated = FALSE; \ ++ (tsk_ctl)->thr_pid = kernel_thread(thread_func, tsk_ctl, flags); \ ++ if ((tsk_ctl)->thr_pid > 0) \ ++ wait_for_completion(&((tsk_ctl)->completed)); \ ++ DBG_THR(("%s thr:%lx started\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ ++} ++ ++#define PROC_STOP(tsk_ctl) \ ++{ \ ++ (tsk_ctl)->terminated = TRUE; \ ++ smp_wmb(); \ ++ up(&((tsk_ctl)->sema)); \ ++ wait_for_completion(&((tsk_ctl)->completed)); \ ++ DBG_THR(("%s thr:%lx terminated OK\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ ++ (tsk_ctl)->thr_pid = -1; \ ++} ++ ++/* ----------------------- */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) ++#define KILL_PROC(nr, sig) \ ++{ \ ++struct task_struct *tsk; \ ++struct pid *pid; \ ++pid = find_get_pid((pid_t)nr); \ ++tsk = pid_task(pid, PIDTYPE_PID); \ ++if (tsk) send_sig(sig, tsk, 1); \ ++} ++#else ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \ ++ KERNEL_VERSION(2, 6, 30)) ++#define KILL_PROC(pid, sig) \ ++{ \ ++ struct task_struct *tsk; \ ++ tsk = find_task_by_vpid(pid); \ ++ if (tsk) send_sig(sig, tsk, 1); \ ++} ++#else ++#define KILL_PROC(pid, sig) \ ++{ \ ++ kill_proc(pid, sig, 1); \ ++} ++#endif ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#include ++#include ++#else ++#include ++ ++#define __wait_event_interruptible_timeout(wq, condition, ret) \ ++do { \ ++ wait_queue_t __wait; \ ++ init_waitqueue_entry(&__wait, current); \ ++ \ ++ add_wait_queue(&wq, &__wait); \ ++ for (;;) { \ ++ set_current_state(TASK_INTERRUPTIBLE); \ ++ if (condition) \ ++ break; \ ++ if (!signal_pending(current)) { \ ++ ret = schedule_timeout(ret); \ ++ if (!ret) \ ++ break; \ ++ continue; \ ++ } \ ++ ret = -ERESTARTSYS; \ ++ break; \ ++ } \ ++ current->state = TASK_RUNNING; \ ++ remove_wait_queue(&wq, &__wait); \ ++} while (0) ++ ++#define wait_event_interruptible_timeout(wq, condition, timeout) \ ++({ \ ++ long __ret = timeout; \ ++ if (!(condition)) \ ++ __wait_event_interruptible_timeout(wq, condition, __ret); \ ++ __ret; \ ++}) ++ ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */ ++ ++/* ++For < 2.6.24, wl creates its own netdev but doesn't ++align the priv area like the genuine alloc_netdev(). ++Since netdev_priv() always gives us the aligned address, it will ++not match our unaligned address for < 2.6.24 ++*/ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) ++#define DEV_PRIV(dev) (dev->priv) ++#else ++#define DEV_PRIV(dev) netdev_priv(dev) ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) ++#define WL_ISR(i, d, p) wl_isr((i), (d)) ++#else ++#define WL_ISR(i, d, p) wl_isr((i), (d), (p)) ++#endif /* < 2.6.20 */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++#define netdev_priv(dev) dev->priv ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ ++ ++#endif /* _linuxver_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/osl.h b/drivers/bcmdrivers/gmac/src/include/osl.h +new file mode 100755 +index 0000000..6b961d9 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/osl.h +@@ -0,0 +1,145 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * OS Abstraction Layer ++ * ++ * $Id: osl.h 321101 2012-03-14 02:53:01Z $ ++ */ ++ ++#ifndef _osl_h_ ++#define _osl_h_ ++ ++/* osl handle type forward declaration */ ++typedef struct osl_info osl_t; ++typedef struct osl_dmainfo osldma_t; ++ ++#define OSL_PKTTAG_SZ 32 /* Size of PktTag */ ++ ++/* Drivers use PKTFREESETCB to register a callback function when a packet is freed by OSL */ ++typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status); ++ ++/* Drivers use REGOPSSET() to register register read/write funcitons */ ++typedef unsigned int (*osl_rreg_fn_t)(void *ctx, volatile void *reg, unsigned int size); ++typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, unsigned int size); ++ ++#ifdef __mips__ ++#define PREF_LOAD 0 ++#define PREF_STORE 1 ++#define PREF_LOAD_STREAMED 4 ++#define PREF_STORE_STREAMED 5 ++#define PREF_LOAD_RETAINED 6 ++#define PREF_STORE_RETAINED 7 ++#define PREF_WBACK_INV 25 ++#define PREF_PREPARE4STORE 30 ++ ++ ++#define MAKE_PREFETCH_FN(hint) \ ++static inline void prefetch_##hint(const void *addr) \ ++{ \ ++ __asm__ __volatile__(\ ++ " .set mips4 \n" \ ++ " pref %0, (%1) \n" \ ++ " .set mips0 \n" \ ++ : \ ++ : "i" (hint), "r" (addr)); \ ++} ++ ++#define MAKE_PREFETCH_RANGE_FN(hint) \ ++static inline void prefetch_range_##hint(const void *addr, int len) \ ++{ \ ++ int size = len; \ ++ while (size > 0) { \ ++ prefetch_##hint(addr); \ ++ size -= 32; \ ++ } \ ++} ++ ++MAKE_PREFETCH_FN(PREF_LOAD) ++MAKE_PREFETCH_RANGE_FN(PREF_LOAD) ++MAKE_PREFETCH_FN(PREF_STORE) ++MAKE_PREFETCH_RANGE_FN(PREF_STORE) ++MAKE_PREFETCH_FN(PREF_LOAD_STREAMED) ++MAKE_PREFETCH_RANGE_FN(PREF_LOAD_STREAMED) ++MAKE_PREFETCH_FN(PREF_STORE_STREAMED) ++MAKE_PREFETCH_RANGE_FN(PREF_STORE_STREAMED) ++MAKE_PREFETCH_FN(PREF_LOAD_RETAINED) ++MAKE_PREFETCH_RANGE_FN(PREF_LOAD_RETAINED) ++MAKE_PREFETCH_FN(PREF_STORE_RETAINED) ++MAKE_PREFETCH_RANGE_FN(PREF_STORE_RETAINED) ++#endif /* __mips__ */ ++ ++#if defined(linux) ++#include ++#else ++#error "Unsupported OSL requested" ++#endif ++ ++#ifndef PKTDBG_TRACE ++#define PKTDBG_TRACE(osh, pkt, bit) ++#endif ++ ++#ifndef PKTCTFMAP ++#define PKTCTFMAP(osh, p) ++#endif /* PKTCTFMAP */ ++ ++/* -------------------------------------------------------------------------- ++** Register manipulation macros. ++*/ ++ ++#define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val))) ++ ++#ifndef AND_REG ++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) ++#endif /* !AND_REG */ ++ ++#ifndef OR_REG ++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) ++#endif /* !OR_REG */ ++ ++#if !defined(OSL_SYSUPTIME) ++#define OSL_SYSUPTIME() (0) ++#define OSL_SYSUPTIME_SUPPORT FALSE ++#else ++#define OSL_SYSUPTIME_SUPPORT TRUE ++#endif /* OSL_SYSUPTIME */ ++ ++#if !defined(linux) || !defined(PKTC) ++#define PKTCGETATTR(s) (0) ++#define PKTCSETATTR(skb, f, p, b) ++#define PKTCCLRATTR(skb) ++#define PKTCCNT(skb) (1) ++#define PKTCLEN(skb) PKTLEN(NULL, skb) ++#define PKTCGETFLAGS(skb) (0) ++#define PKTCSETFLAGS(skb, f) ++#define PKTCCLRFLAGS(skb) ++#define PKTCFLAGS(skb) (0) ++#define PKTCSETCNT(skb, c) ++#define PKTCINCRCNT(skb) ++#define PKTCADDCNT(skb, c) ++#define PKTCSETLEN(skb, l) ++#define PKTCADDLEN(skb, l) ++#define PKTCSETFLAG(skb, fb) ++#define PKTCCLRFLAG(skb, fb) ++#define PKTCLINK(skb) NULL ++#define PKTSETCLINK(skb, x) ++#undef PKTISCHAINED ++#define PKTISCHAINED(skb) FALSE ++#define FOREACH_CHAINED_PKT(skb, nskb) \ ++ for ((nskb) = NULL; (skb) != NULL; (skb) = (nskb)) ++#define PKTCFREE PKTFREE ++#endif ++ ++ ++#endif /* _osl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/packed_section_end.h b/drivers/bcmdrivers/gmac/src/include/packed_section_end.h +new file mode 100755 +index 0000000..44c83f8 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/packed_section_end.h +@@ -0,0 +1,71 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Declare directives for structure packing. No padding will be provided ++ * between the members of packed structures, and therefore, there is no ++ * guarantee that structure members will be aligned. ++ * ++ * Declaring packed structures is compiler specific. In order to handle all ++ * cases, packed structures should be delared as: ++ * ++ * #include ++ * ++ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t { ++ * some_struct_members; ++ * } BWL_POST_PACKED_STRUCT foobar_t; ++ * ++ * #include ++ * ++ * ++ * $Id: packed_section_end.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++ ++/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h ++ * and undefined in packed_section_end.h. If it is NOT defined at this ++ * point, then there is a missing include of packed_section_start.h. ++ */ ++#ifdef BWL_PACKED_SECTION ++ #undef BWL_PACKED_SECTION ++#else ++ #error "BWL_PACKED_SECTION is NOT defined!" ++#endif ++ ++ ++#if defined(_MSC_VER) ++ /* Disable compiler warning about pragma pack changing alignment. */ ++ #pragma warning(disable:4103) ++ ++ /* The Microsoft compiler uses pragmas for structure packing. Other ++ * compilers use structure attribute modifiers. Refer to ++ * BWL_PRE_PACKED_STRUCT and BWL_POST_PACKED_STRUCT defined in ++ * typedefs.h ++ */ ++ #if defined(BWL_DEFAULT_PACKING) ++ /* require default structure packing */ ++ #pragma pack(pop) ++ #undef BWL_DEFAULT_PACKING ++ #else /* BWL_PACKED_SECTION */ ++ #pragma pack() ++ #endif /* BWL_PACKED_SECTION */ ++#endif /* _MSC_VER */ ++ ++ ++/* Compiler-specific directives for structure packing are declared in ++ * packed_section_start.h. This marks the end of the structure packing section, ++ * so, undef them here. ++ */ ++#undef BWL_PRE_PACKED_STRUCT ++#undef BWL_POST_PACKED_STRUCT +diff --git a/drivers/bcmdrivers/gmac/src/include/packed_section_start.h b/drivers/bcmdrivers/gmac/src/include/packed_section_start.h +new file mode 100755 +index 0000000..1899125 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/packed_section_start.h +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Declare directives for structure packing. No padding will be provided ++ * between the members of packed structures, and therefore, there is no ++ * guarantee that structure members will be aligned. ++ * ++ * Declaring packed structures is compiler specific. In order to handle all ++ * cases, packed structures should be delared as: ++ * ++ * #include ++ * ++ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t { ++ * some_struct_members; ++ * } BWL_POST_PACKED_STRUCT foobar_t; ++ * ++ * #include ++ * ++ * ++ * $Id: packed_section_start.h 286783 2011-09-29 06:18:57Z $ ++ */ ++ ++ ++/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h ++ * and undefined in packed_section_end.h. If it is already defined at this ++ * point, then there is a missing include of packed_section_end.h. ++ */ ++#ifdef BWL_PACKED_SECTION ++ #error "BWL_PACKED_SECTION is already defined!" ++#else ++ #define BWL_PACKED_SECTION ++#endif ++ ++ ++#if defined(_MSC_VER) ++ /* Disable compiler warning about pragma pack changing alignment. */ ++ #pragma warning(disable:4103) ++ ++ /* The Microsoft compiler uses pragmas for structure packing. Other ++ * compilers use structure attribute modifiers. Refer to ++ * BWL_PRE_PACKED_STRUCT and BWL_POST_PACKED_STRUCT defined below. ++ */ ++ #if defined(BWL_DEFAULT_PACKING) ++ /* Default structure packing */ ++ #pragma pack(push, 8) ++ #else /* BWL_PACKED_SECTION */ ++ #pragma pack(1) ++ #endif /* BWL_PACKED_SECTION */ ++#endif /* _MSC_VER */ ++ ++ ++/* Declare compiler-specific directives for structure packing. */ ++#if defined(_MSC_VER) ++ #define BWL_PRE_PACKED_STRUCT ++ #define BWL_POST_PACKED_STRUCT ++#elif defined(__GNUC__) || defined(__lint) ++ #define BWL_PRE_PACKED_STRUCT ++ #define BWL_POST_PACKED_STRUCT __attribute__ ((packed)) ++#elif defined(__CC_ARM) ++ #define BWL_PRE_PACKED_STRUCT __packed ++ #define BWL_POST_PACKED_STRUCT ++#else ++ #error "Unknown compiler!" ++#endif +diff --git a/drivers/bcmdrivers/gmac/src/include/pcicfg.h b/drivers/bcmdrivers/gmac/src/include/pcicfg.h +new file mode 100755 +index 0000000..fa01982 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/pcicfg.h +@@ -0,0 +1,569 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * pcicfg.h: PCI configuration constants and structures. ++ * ++ * $Id: pcicfg.h 316716 2012-02-23 04:39:13Z $ ++ */ ++ ++#ifndef _h_pcicfg_ ++#define _h_pcicfg_ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* The following inside ifndef's so we don't collide with NTDDK.H */ ++#ifndef PCI_MAX_BUS ++#define PCI_MAX_BUS 0x100 ++#endif ++#ifndef PCI_MAX_DEVICES ++#define PCI_MAX_DEVICES 0x20 ++#endif ++#ifndef PCI_MAX_FUNCTION ++#define PCI_MAX_FUNCTION 0x8 ++#endif ++ ++#ifndef PCI_INVALID_VENDORID ++#define PCI_INVALID_VENDORID 0xffff ++#endif ++#ifndef PCI_INVALID_DEVICEID ++#define PCI_INVALID_DEVICEID 0xffff ++#endif ++ ++ ++/* Convert between bus-slot-function-register and config addresses */ ++ ++#define PCICFG_BUS_SHIFT 16 /* Bus shift */ ++#define PCICFG_SLOT_SHIFT 11 /* Slot shift */ ++#define PCICFG_FUN_SHIFT 8 /* Function shift */ ++#define PCICFG_OFF_SHIFT 0 /* Register shift */ ++ ++#define PCICFG_BUS_MASK 0xff /* Bus mask */ ++#define PCICFG_SLOT_MASK 0x1f /* Slot mask */ ++#define PCICFG_FUN_MASK 7 /* Function mask */ ++#define PCICFG_OFF_MASK 0xff /* Bus mask */ ++ ++#define PCI_CONFIG_ADDR(b, s, f, o) \ ++ ((((b) & PCICFG_BUS_MASK) << PCICFG_BUS_SHIFT) \ ++ | (((s) & PCICFG_SLOT_MASK) << PCICFG_SLOT_SHIFT) \ ++ | (((f) & PCICFG_FUN_MASK) << PCICFG_FUN_SHIFT) \ ++ | (((o) & PCICFG_OFF_MASK) << PCICFG_OFF_SHIFT)) ++ ++#define PCI_CONFIG_BUS(a) (((a) >> PCICFG_BUS_SHIFT) & PCICFG_BUS_MASK) ++#define PCI_CONFIG_SLOT(a) (((a) >> PCICFG_SLOT_SHIFT) & PCICFG_SLOT_MASK) ++#define PCI_CONFIG_FUN(a) (((a) >> PCICFG_FUN_SHIFT) & PCICFG_FUN_MASK) ++#define PCI_CONFIG_OFF(a) (((a) >> PCICFG_OFF_SHIFT) & PCICFG_OFF_MASK) ++ ++/* PCIE Config space accessing MACROS */ ++ ++#define PCIECFG_BUS_SHIFT 24 /* Bus shift */ ++#define PCIECFG_SLOT_SHIFT 19 /* Slot/Device shift */ ++#define PCIECFG_FUN_SHIFT 16 /* Function shift */ ++#define PCIECFG_OFF_SHIFT 0 /* Register shift */ ++ ++#define PCIECFG_BUS_MASK 0xff /* Bus mask */ ++#define PCIECFG_SLOT_MASK 0x1f /* Slot/Device mask */ ++#define PCIECFG_FUN_MASK 7 /* Function mask */ ++#define PCIECFG_OFF_MASK 0xfff /* Register mask */ ++ ++#define PCIE_CONFIG_ADDR(b, s, f, o) \ ++ ((((b) & PCIECFG_BUS_MASK) << PCIECFG_BUS_SHIFT) \ ++ | (((s) & PCIECFG_SLOT_MASK) << PCIECFG_SLOT_SHIFT) \ ++ | (((f) & PCIECFG_FUN_MASK) << PCIECFG_FUN_SHIFT) \ ++ | (((o) & PCIECFG_OFF_MASK) << PCIECFG_OFF_SHIFT)) ++ ++#define PCIE_CONFIG_BUS(a) (((a) >> PCIECFG_BUS_SHIFT) & PCIECFG_BUS_MASK) ++#define PCIE_CONFIG_SLOT(a) (((a) >> PCIECFG_SLOT_SHIFT) & PCIECFG_SLOT_MASK) ++#define PCIE_CONFIG_FUN(a) (((a) >> PCIECFG_FUN_SHIFT) & PCIECFG_FUN_MASK) ++#define PCIE_CONFIG_OFF(a) (((a) >> PCIECFG_OFF_SHIFT) & PCIECFG_OFF_MASK) ++ ++/* The actual config space */ ++ ++#define PCI_BAR_MAX 6 ++ ++#define PCI_ROM_BAR 8 ++ ++#define PCR_RSVDA_MAX 2 ++ ++/* Bits in PCI bars' flags */ ++ ++#define PCIBAR_FLAGS 0xf ++#define PCIBAR_IO 0x1 ++#define PCIBAR_MEM1M 0x2 ++#define PCIBAR_MEM64 0x4 ++#define PCIBAR_PREFETCH 0x8 ++#define PCIBAR_MEM32_MASK 0xFFFFFF80 ++ ++/* pci config status reg has a bit to indicate that capability ptr is present */ ++ ++#define PCI_CAPPTR_PRESENT 0x0010 ++ ++typedef struct _pci_config_regs { ++ uint16 vendor; ++ uint16 device; ++ uint16 command; ++ uint16 status; ++ uint8 rev_id; ++ uint8 prog_if; ++ uint8 sub_class; ++ uint8 base_class; ++ uint8 cache_line_size; ++ uint8 latency_timer; ++ uint8 header_type; ++ uint8 bist; ++ uint32 base[PCI_BAR_MAX]; ++ uint32 cardbus_cis; ++ uint16 subsys_vendor; ++ uint16 subsys_id; ++ uint32 baserom; ++ uint32 rsvd_a[PCR_RSVDA_MAX]; ++ uint8 int_line; ++ uint8 int_pin; ++ uint8 min_gnt; ++ uint8 max_lat; ++ uint8 dev_dep[192]; ++} pci_config_regs; ++ ++#define SZPCR (sizeof (pci_config_regs)) ++#define MINSZPCR 64 /* offsetof (dev_dep[0] */ ++ ++#endif /* !LINUX_POSTMOGRIFY_REMOVAL */ ++/* A structure for the config registers is nice, but in most ++ * systems the config space is not memory mapped, so we need ++ * field offsetts. :-( ++ */ ++#define PCI_CFG_VID 0 ++#define PCI_CFG_DID 2 ++#define PCI_CFG_CMD 4 ++#define PCI_CFG_STAT 6 ++#define PCI_CFG_REV 8 ++#define PCI_CFG_PROGIF 9 ++#define PCI_CFG_SUBCL 0xa ++#define PCI_CFG_BASECL 0xb ++#define PCI_CFG_CLSZ 0xc ++#define PCI_CFG_LATTIM 0xd ++#define PCI_CFG_HDR 0xe ++#define PCI_CFG_BIST 0xf ++#define PCI_CFG_BAR0 0x10 ++#define PCI_CFG_BAR1 0x14 ++#define PCI_CFG_BAR2 0x18 ++#define PCI_CFG_BAR3 0x1c ++#define PCI_CFG_BAR4 0x20 ++#define PCI_CFG_BAR5 0x24 ++#define PCI_CFG_CIS 0x28 ++#define PCI_CFG_SVID 0x2c ++#define PCI_CFG_SSID 0x2e ++#define PCI_CFG_ROMBAR 0x30 ++#define PCI_CFG_CAPPTR 0x34 ++#define PCI_CFG_INT 0x3c ++#define PCI_CFG_PIN 0x3d ++#define PCI_CFG_MINGNT 0x3e ++#define PCI_CFG_MAXLAT 0x3f ++#define PCI_CFG_DEVCTRL 0xd8 ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++ ++#ifdef __NetBSD__ ++#undef PCI_CLASS_DISPLAY ++#undef PCI_CLASS_MEMORY ++#undef PCI_CLASS_BRIDGE ++#undef PCI_CLASS_INPUT ++#undef PCI_CLASS_DOCK ++#endif /* __NetBSD__ */ ++ ++#ifdef EFI ++#undef PCI_CLASS_BRIDGE ++#undef PCI_CLASS_OLD ++#undef PCI_CLASS_DISPLAY ++#undef PCI_CLASS_SERIAL ++#undef PCI_CLASS_SATELLITE ++#endif /* EFI */ ++ ++/* Classes and subclasses */ ++ ++typedef enum { ++ PCI_CLASS_OLD = 0, ++ PCI_CLASS_DASDI, ++ PCI_CLASS_NET, ++ PCI_CLASS_DISPLAY, ++ PCI_CLASS_MMEDIA, ++ PCI_CLASS_MEMORY, ++ PCI_CLASS_BRIDGE, ++ PCI_CLASS_COMM, ++ PCI_CLASS_BASE, ++ PCI_CLASS_INPUT, ++ PCI_CLASS_DOCK, ++ PCI_CLASS_CPU, ++ PCI_CLASS_SERIAL, ++ PCI_CLASS_INTELLIGENT = 0xe, ++ PCI_CLASS_SATELLITE, ++ PCI_CLASS_CRYPT, ++ PCI_CLASS_DSP, ++ PCI_CLASS_XOR = 0xfe ++} pci_classes; ++ ++typedef enum { ++ PCI_DASDI_SCSI, ++ PCI_DASDI_IDE, ++ PCI_DASDI_FLOPPY, ++ PCI_DASDI_IPI, ++ PCI_DASDI_RAID, ++ PCI_DASDI_OTHER = 0x80 ++} pci_dasdi_subclasses; ++ ++typedef enum { ++ PCI_NET_ETHER, ++ PCI_NET_TOKEN, ++ PCI_NET_FDDI, ++ PCI_NET_ATM, ++ PCI_NET_OTHER = 0x80 ++} pci_net_subclasses; ++ ++typedef enum { ++ PCI_DISPLAY_VGA, ++ PCI_DISPLAY_XGA, ++ PCI_DISPLAY_3D, ++ PCI_DISPLAY_OTHER = 0x80 ++} pci_display_subclasses; ++ ++typedef enum { ++ PCI_MMEDIA_VIDEO, ++ PCI_MMEDIA_AUDIO, ++ PCI_MMEDIA_PHONE, ++ PCI_MEDIA_OTHER = 0x80 ++} pci_mmedia_subclasses; ++ ++typedef enum { ++ PCI_MEMORY_RAM, ++ PCI_MEMORY_FLASH, ++ PCI_MEMORY_OTHER = 0x80 ++} pci_memory_subclasses; ++ ++typedef enum { ++ PCI_BRIDGE_HOST, ++ PCI_BRIDGE_ISA, ++ PCI_BRIDGE_EISA, ++ PCI_BRIDGE_MC, ++ PCI_BRIDGE_PCI, ++ PCI_BRIDGE_PCMCIA, ++ PCI_BRIDGE_NUBUS, ++ PCI_BRIDGE_CARDBUS, ++ PCI_BRIDGE_RACEWAY, ++ PCI_BRIDGE_OTHER = 0x80 ++} pci_bridge_subclasses; ++ ++typedef enum { ++ PCI_COMM_UART, ++ PCI_COMM_PARALLEL, ++ PCI_COMM_MULTIUART, ++ PCI_COMM_MODEM, ++ PCI_COMM_OTHER = 0x80 ++} pci_comm_subclasses; ++ ++typedef enum { ++ PCI_BASE_PIC, ++ PCI_BASE_DMA, ++ PCI_BASE_TIMER, ++ PCI_BASE_RTC, ++ PCI_BASE_PCI_HOTPLUG, ++ PCI_BASE_OTHER = 0x80 ++} pci_base_subclasses; ++ ++typedef enum { ++ PCI_INPUT_KBD, ++ PCI_INPUT_PEN, ++ PCI_INPUT_MOUSE, ++ PCI_INPUT_SCANNER, ++ PCI_INPUT_GAMEPORT, ++ PCI_INPUT_OTHER = 0x80 ++} pci_input_subclasses; ++ ++typedef enum { ++ PCI_DOCK_GENERIC, ++ PCI_DOCK_OTHER = 0x80 ++} pci_dock_subclasses; ++ ++typedef enum { ++ PCI_CPU_386, ++ PCI_CPU_486, ++ PCI_CPU_PENTIUM, ++ PCI_CPU_ALPHA = 0x10, ++ PCI_CPU_POWERPC = 0x20, ++ PCI_CPU_MIPS = 0x30, ++ PCI_CPU_COPROC = 0x40, ++ PCI_CPU_OTHER = 0x80 ++} pci_cpu_subclasses; ++ ++typedef enum { ++ PCI_SERIAL_IEEE1394, ++ PCI_SERIAL_ACCESS, ++ PCI_SERIAL_SSA, ++ PCI_SERIAL_USB, ++ PCI_SERIAL_FIBER, ++ PCI_SERIAL_SMBUS, ++ PCI_SERIAL_OTHER = 0x80 ++} pci_serial_subclasses; ++ ++typedef enum { ++ PCI_INTELLIGENT_I2O ++} pci_intelligent_subclasses; ++ ++typedef enum { ++ PCI_SATELLITE_TV, ++ PCI_SATELLITE_AUDIO, ++ PCI_SATELLITE_VOICE, ++ PCI_SATELLITE_DATA, ++ PCI_SATELLITE_OTHER = 0x80 ++} pci_satellite_subclasses; ++ ++typedef enum { ++ PCI_CRYPT_NETWORK, ++ PCI_CRYPT_ENTERTAINMENT, ++ PCI_CRYPT_OTHER = 0x80 ++} pci_crypt_subclasses; ++ ++typedef enum { ++ PCI_DSP_DPIO, ++ PCI_DSP_OTHER = 0x80 ++} pci_dsp_subclasses; ++ ++typedef enum { ++ PCI_XOR_QDMA, ++ PCI_XOR_OTHER = 0x80 ++} pci_xor_subclasses; ++ ++/* Header types */ ++#define PCI_HEADER_MULTI 0x80 ++#define PCI_HEADER_MASK 0x7f ++typedef enum { ++ PCI_HEADER_NORMAL, ++ PCI_HEADER_BRIDGE, ++ PCI_HEADER_CARDBUS ++} pci_header_types; ++ ++ ++/* Overlay for a PCI-to-PCI bridge */ ++ ++#define PPB_RSVDA_MAX 2 ++#define PPB_RSVDD_MAX 8 ++ ++typedef struct _ppb_config_regs { ++ uint16 vendor; ++ uint16 device; ++ uint16 command; ++ uint16 status; ++ uint8 rev_id; ++ uint8 prog_if; ++ uint8 sub_class; ++ uint8 base_class; ++ uint8 cache_line_size; ++ uint8 latency_timer; ++ uint8 header_type; ++ uint8 bist; ++ uint32 rsvd_a[PPB_RSVDA_MAX]; ++ uint8 prim_bus; ++ uint8 sec_bus; ++ uint8 sub_bus; ++ uint8 sec_lat; ++ uint8 io_base; ++ uint8 io_lim; ++ uint16 sec_status; ++ uint16 mem_base; ++ uint16 mem_lim; ++ uint16 pf_mem_base; ++ uint16 pf_mem_lim; ++ uint32 pf_mem_base_hi; ++ uint32 pf_mem_lim_hi; ++ uint16 io_base_hi; ++ uint16 io_lim_hi; ++ uint16 subsys_vendor; ++ uint16 subsys_id; ++ uint32 rsvd_b; ++ uint8 rsvd_c; ++ uint8 int_pin; ++ uint16 bridge_ctrl; ++ uint8 chip_ctrl; ++ uint8 diag_ctrl; ++ uint16 arb_ctrl; ++ uint32 rsvd_d[PPB_RSVDD_MAX]; ++ uint8 dev_dep[192]; ++} ppb_config_regs; ++ ++ ++/* PCI CAPABILITY DEFINES */ ++#define PCI_CAP_POWERMGMTCAP_ID 0x01 ++#define PCI_CAP_MSICAP_ID 0x05 ++#define PCI_CAP_VENDSPEC_ID 0x09 ++#define PCI_CAP_PCIECAP_ID 0x10 ++ ++/* Data structure to define the Message Signalled Interrupt facility ++ * Valid for PCI and PCIE configurations ++ */ ++typedef struct _pciconfig_cap_msi { ++ uint8 capID; ++ uint8 nextptr; ++ uint16 msgctrl; ++ uint32 msgaddr; ++} pciconfig_cap_msi; ++ ++/* Data structure to define the Power managment facility ++ * Valid for PCI and PCIE configurations ++ */ ++typedef struct _pciconfig_cap_pwrmgmt { ++ uint8 capID; ++ uint8 nextptr; ++ uint16 pme_cap; ++ uint16 pme_sts_ctrl; ++ uint8 pme_bridge_ext; ++ uint8 data; ++} pciconfig_cap_pwrmgmt; ++ ++#define PME_CAP_PM_STATES (0x1f << 27) /* Bits 31:27 states that can generate PME */ ++#define PME_CSR_OFFSET 0x4 /* 4-bytes offset */ ++#define PME_CSR_PME_EN (1 << 8) /* Bit 8 Enable generating of PME */ ++#define PME_CSR_PME_STAT (1 << 15) /* Bit 15 PME got asserted */ ++ ++/* Data structure to define the PCIE capability */ ++typedef struct _pciconfig_cap_pcie { ++ uint8 capID; ++ uint8 nextptr; ++ uint16 pcie_cap; ++ uint32 dev_cap; ++ uint16 dev_ctrl; ++ uint16 dev_status; ++ uint32 link_cap; ++ uint16 link_ctrl; ++ uint16 link_status; ++ uint32 slot_cap; ++ uint16 slot_ctrl; ++ uint16 slot_status; ++ uint16 root_ctrl; ++ uint16 root_cap; ++ uint32 root_status; ++} pciconfig_cap_pcie; ++ ++/* PCIE Enhanced CAPABILITY DEFINES */ ++#define PCIE_EXTCFG_OFFSET 0x100 ++#define PCIE_ADVERRREP_CAPID 0x0001 ++#define PCIE_VC_CAPID 0x0002 ++#define PCIE_DEVSNUM_CAPID 0x0003 ++#define PCIE_PWRBUDGET_CAPID 0x0004 ++ ++/* PCIE Extended configuration */ ++#define PCIE_ADV_CORR_ERR_MASK 0x114 ++#define CORR_ERR_RE (1 << 0) /* Receiver */ ++#define CORR_ERR_BT (1 << 6) /* Bad TLP */ ++#define CORR_ERR_BD (1 << 7) /* Bad DLLP */ ++#define CORR_ERR_RR (1 << 8) /* REPLAY_NUM rollover */ ++#define CORR_ERR_RT (1 << 12) /* Reply timer timeout */ ++#define ALL_CORR_ERRORS (CORR_ERR_RE | CORR_ERR_BT | CORR_ERR_BD | \ ++ CORR_ERR_RR | CORR_ERR_RT) ++ ++/* PCIE Root Control Register bits (Host mode only) */ ++#define PCIE_RC_CORR_SERR_EN 0x0001 ++#define PCIE_RC_NONFATAL_SERR_EN 0x0002 ++#define PCIE_RC_FATAL_SERR_EN 0x0004 ++#define PCIE_RC_PME_INT_EN 0x0008 ++#define PCIE_RC_CRS_EN 0x0010 ++ ++/* PCIE Root Capability Register bits (Host mode only) */ ++#define PCIE_RC_CRS_VISIBILITY 0x0001 ++ ++/* Header to define the PCIE specific capabilities in the extended config space */ ++typedef struct _pcie_enhanced_caphdr { ++ uint16 capID; ++ uint16 cap_ver : 4; ++ uint16 next_ptr : 12; ++} pcie_enhanced_caphdr; ++ ++ ++/* Everything below is BRCM HND proprietary */ ++ ++ ++/* Brcm PCI configuration registers */ ++#define cap_list rsvd_a[0] ++#define bar0_window dev_dep[0x80 - 0x40] ++#define bar1_window dev_dep[0x84 - 0x40] ++#define sprom_control dev_dep[0x88 - 0x40] ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++#define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */ ++#define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */ ++#define PCI_SPROM_CONTROL 0x88 /* sprom property control */ ++#define PCI_BAR1_CONTROL 0x8c /* BAR1 region burst control */ ++#define PCI_INT_STATUS 0x90 /* PCI and other cores interrupts */ ++#define PCI_INT_MASK 0x94 /* mask of PCI and other cores interrupts */ ++#define PCI_TO_SB_MB 0x98 /* signal backplane interrupts */ ++#define PCI_BACKPLANE_ADDR 0xa0 /* address an arbitrary location on the system backplane */ ++#define PCI_BACKPLANE_DATA 0xa4 /* data at the location specified by above address */ ++#define PCI_CLK_CTL_ST 0xa8 /* pci config space clock control/status (>=rev14) */ ++#define PCI_BAR0_WIN2 0xac /* backplane addres space accessed by second 4KB of BAR0 */ ++#define PCI_GPIO_IN 0xb0 /* pci config space gpio input (>=rev3) */ ++#define PCI_GPIO_OUT 0xb4 /* pci config space gpio output (>=rev3) */ ++#define PCI_GPIO_OUTEN 0xb8 /* pci config space gpio output enable (>=rev3) */ ++ ++#define PCI_BAR0_SHADOW_OFFSET (2 * 1024) /* bar0 + 2K accesses sprom shadow (in pci core) */ ++#define PCI_BAR0_SPROM_OFFSET (4 * 1024) /* bar0 + 4K accesses external sprom */ ++#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) /* bar0 + 6K accesses pci core registers */ ++#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) /* pci core SB registers are at the end of the ++ * 8KB window, so their address is the "regular" ++ * address plus 4K ++ */ ++/* ++ * PCIE GEN2 changed some of the above locations for ++ * Bar0WrapperBase, SecondaryBAR0Window and SecondaryBAR0WrapperBase ++ * BAR0 maps 32K of register space ++*/ ++#define PCIE2_BAR0_WIN2 0x70 /* backplane addres space accessed by second 4KB of BAR0 */ ++#define PCIE2_BAR0_CORE2_WIN 0x74 /* backplane addres space accessed by second 4KB of BAR0 */ ++#define PCIE2_BAR0_CORE2_WIN2 0x78 /* backplane addres space accessed by second 4KB of BAR0 */ ++ ++#define PCI_BAR0_WINSZ (16 * 1024) /* bar0 window size Match with corerev 13 */ ++/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */ ++#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) /* bar0 + 8K accesses pci/pcie core registers */ ++#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) /* bar0 + 12K accesses chipc core registers */ ++#define PCI_16KBB0_WINSZ (16 * 1024) /* bar0 window size */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* On AI chips we have a second window to map DMP regs are mapped: */ ++#define PCI_16KB0_WIN2_OFFSET (4 * 1024) /* bar0 + 4K is "Window 2" */ ++ ++/* PCI_INT_STATUS */ ++#define PCI_SBIM_STATUS_SERR 0x4 /* backplane SBErr interrupt status */ ++ ++/* PCI_INT_MASK */ ++#define PCI_SBIM_SHIFT 8 /* backplane core interrupt mask bits offset */ ++#define PCI_SBIM_MASK 0xff00 /* backplane core interrupt mask */ ++#define PCI_SBIM_MASK_SERR 0x4 /* backplane SBErr interrupt mask */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* PCI_SPROM_CONTROL */ ++#define SPROM_SZ_MSK 0x02 /* SPROM Size Mask */ ++#define SPROM_LOCKED 0x08 /* SPROM Locked */ ++#define SPROM_BLANK 0x04 /* indicating a blank SPROM */ ++#define SPROM_WRITEEN 0x10 /* SPROM write enable */ ++#define SPROM_BOOTROM_WE 0x20 /* external bootrom write enable */ ++#define SPROM_BACKPLANE_EN 0x40 /* Enable indirect backplane access */ ++#define SPROM_OTPIN_USE 0x80 /* device OTP In use */ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* Bits in PCI command and status regs */ ++#define PCI_CMD_IO 0x00000001 /* I/O enable */ ++#define PCI_CMD_MEMORY 0x00000002 /* Memory enable */ ++#define PCI_CMD_MASTER 0x00000004 /* Master enable */ ++#define PCI_CMD_SPECIAL 0x00000008 /* Special cycles enable */ ++#define PCI_CMD_INVALIDATE 0x00000010 /* Invalidate? */ ++#define PCI_CMD_VGA_PAL 0x00000040 /* VGA Palate */ ++#define PCI_STAT_TA 0x08000000 /* target abort status */ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define PCI_CONFIG_SPACE_SIZE 256 ++#endif /* _h_pcicfg_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/802.11.h b/drivers/bcmdrivers/gmac/src/include/proto/802.11.h +new file mode 100755 +index 0000000..db026bf +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/802.11.h +@@ -0,0 +1,2356 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental types and constants relating to 802.11 ++ * ++ * $Id: 802.11.h 308961 2012-01-18 03:01:00Z $ ++ */ ++ ++#ifndef _802_11_H_ ++#define _802_11_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++#ifndef _NET_ETHERNET_H_ ++#include ++#endif ++ ++#include ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++#define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */ ++ ++/* Generic 802.11 frame constants */ ++#define DOT11_A3_HDR_LEN 24 /* d11 header length with A3 */ ++#define DOT11_A4_HDR_LEN 30 /* d11 header length with A4 */ ++#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN /* MAC header length */ ++#define DOT11_FCS_LEN 4 /* d11 FCS length */ ++#define DOT11_ICV_LEN 4 /* d11 ICV length */ ++#define DOT11_ICV_AES_LEN 8 /* d11 ICV/AES length */ ++#define DOT11_QOS_LEN 2 /* d11 QoS length */ ++#define DOT11_HTC_LEN 4 /* d11 HT Control field length */ ++ ++#define DOT11_KEY_INDEX_SHIFT 6 /* d11 key index shift */ ++#define DOT11_IV_LEN 4 /* d11 IV length */ ++#define DOT11_IV_TKIP_LEN 8 /* d11 IV TKIP length */ ++#define DOT11_IV_AES_OCB_LEN 4 /* d11 IV/AES/OCB length */ ++#define DOT11_IV_AES_CCM_LEN 8 /* d11 IV/AES/CCM length */ ++#define DOT11_IV_MAX_LEN 8 /* maximum iv len for any encryption */ ++ ++/* Includes MIC */ ++#define DOT11_MAX_MPDU_BODY_LEN 2304 /* max MPDU body length */ ++/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */ ++#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \ ++ DOT11_QOS_LEN + \ ++ DOT11_IV_AES_CCM_LEN + \ ++ DOT11_MAX_MPDU_BODY_LEN + \ ++ DOT11_ICV_LEN + \ ++ DOT11_FCS_LEN) /* d11 max MPDU length */ ++ ++#define DOT11_MAX_SSID_LEN 32 /* d11 max ssid length */ ++ ++/* dot11RTSThreshold */ ++#define DOT11_DEFAULT_RTS_LEN 2347 /* d11 default RTS length */ ++#define DOT11_MAX_RTS_LEN 2347 /* d11 max RTS length */ ++ ++/* dot11FragmentationThreshold */ ++#define DOT11_MIN_FRAG_LEN 256 /* d11 min fragmentation length */ ++#define DOT11_MAX_FRAG_LEN 2346 /* Max frag is also limited by aMPDUMaxLength ++ * of the attached PHY ++ */ ++#define DOT11_DEFAULT_FRAG_LEN 2346 /* d11 default fragmentation length */ ++ ++/* dot11BeaconPeriod */ ++#define DOT11_MIN_BEACON_PERIOD 1 /* d11 min beacon period */ ++#define DOT11_MAX_BEACON_PERIOD 0xFFFF /* d11 max beacon period */ ++ ++/* dot11DTIMPeriod */ ++#define DOT11_MIN_DTIM_PERIOD 1 /* d11 min DTIM period */ ++#define DOT11_MAX_DTIM_PERIOD 0xFF /* d11 max DTIM period */ ++ ++/* 802.2 LLC/SNAP header used by 802.11 per 802.1H */ ++#define DOT11_LLC_SNAP_HDR_LEN 8 /* d11 LLC/SNAP header length */ ++#define DOT11_OUI_LEN 3 /* d11 OUI length */ ++BWL_PRE_PACKED_STRUCT struct dot11_llc_snap_header { ++ uint8 dsap; /* always 0xAA */ ++ uint8 ssap; /* always 0xAA */ ++ uint8 ctl; /* always 0x03 */ ++ uint8 oui[DOT11_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00 ++ * Bridge-Tunnel: 0x00 0x00 0xF8 ++ */ ++ uint16 type; /* ethertype */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* RFC1042 header used by 802.11 per 802.1H */ ++#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN) /* RCF1042 header length */ ++ ++/* Generic 802.11 MAC header */ ++/* ++ * N.B.: This struct reflects the full 4 address 802.11 MAC header. ++ * The fields are defined such that the shorter 1, 2, and 3 ++ * address headers just use the first k fields. ++ */ ++BWL_PRE_PACKED_STRUCT struct dot11_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr a1; /* address 1 */ ++ struct ether_addr a2; /* address 2 */ ++ struct ether_addr a3; /* address 3 */ ++ uint16 seq; /* sequence control */ ++ struct ether_addr a4; /* address 4 */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* Control frames */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rts_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_RTS_LEN 16 /* d11 RTS frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_cts_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CTS_LEN 10 /* d11 CTS frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ack_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACK_LEN 10 /* d11 ACK frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ps_poll_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* AID */ ++ struct ether_addr bssid; /* receiver address, STA in AP */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_PS_POLL_LEN 16 /* d11 PS poll frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_cf_end_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr bssid; /* transmitter address, STA in AP */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CS_END_LEN 16 /* d11 CF-END frame length */ ++ ++/* RWL wifi protocol: The Vendor Specific Action frame is defined for vendor-specific signaling ++* category+OUI+vendor specific content ( this can be variable) ++*/ ++BWL_PRE_PACKED_STRUCT struct dot11_action_wifi_vendor_specific { ++ uint8 category; ++ uint8 OUI[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 data[1040]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_action_wifi_vendor_specific dot11_action_wifi_vendor_specific_t; ++ ++/* generic vender specific action frame with variable length */ ++BWL_PRE_PACKED_STRUCT struct dot11_action_vs_frmhdr { ++ uint8 category; ++ uint8 OUI[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_action_vs_frmhdr dot11_action_vs_frmhdr_t; ++#define DOT11_ACTION_VS_HDR_LEN 6 ++ ++#define BCM_ACTION_OUI_BYTE0 0x00 ++#define BCM_ACTION_OUI_BYTE1 0x90 ++#define BCM_ACTION_OUI_BYTE2 0x4c ++ ++/* BA/BAR Control parameters */ ++#define DOT11_BA_CTL_POLICY_NORMAL 0x0000 /* normal ack */ ++#define DOT11_BA_CTL_POLICY_NOACK 0x0001 /* no ack */ ++#define DOT11_BA_CTL_POLICY_MASK 0x0001 /* ack policy mask */ ++ ++#define DOT11_BA_CTL_MTID 0x0002 /* multi tid BA */ ++#define DOT11_BA_CTL_COMPRESSED 0x0004 /* compressed bitmap */ ++ ++#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0 /* num msdu in bitmap mask */ ++#define DOT11_BA_CTL_NUMMSDU_SHIFT 6 /* num msdu in bitmap shift */ ++ ++#define DOT11_BA_CTL_TID_MASK 0xF000 /* tid mask */ ++#define DOT11_BA_CTL_TID_SHIFT 12 /* tid shift */ ++ ++/* control frame header (BA/BAR) */ ++BWL_PRE_PACKED_STRUCT struct dot11_ctl_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CTL_HDR_LEN 16 /* control frame hdr len */ ++ ++/* BAR frame payload */ ++BWL_PRE_PACKED_STRUCT struct dot11_bar { ++ uint16 bar_control; /* BAR Control */ ++ uint16 seqnum; /* Starting Sequence control */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BAR_LEN 4 /* BAR frame payload length */ ++ ++#define DOT11_BA_BITMAP_LEN 128 /* bitmap length */ ++#define DOT11_BA_CMP_BITMAP_LEN 8 /* compressed bitmap length */ ++/* BA frame payload */ ++BWL_PRE_PACKED_STRUCT struct dot11_ba { ++ uint16 ba_control; /* BA Control */ ++ uint16 seqnum; /* Starting Sequence control */ ++ uint8 bitmap[DOT11_BA_BITMAP_LEN]; /* Block Ack Bitmap */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BA_LEN 4 /* BA frame payload len (wo bitmap) */ ++ ++/* Management frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_management_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr da; /* receiver address */ ++ struct ether_addr sa; /* transmitter address */ ++ struct ether_addr bssid; /* BSS ID */ ++ uint16 seq; /* sequence control */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_MGMT_HDR_LEN 24 /* d11 management header length */ ++ ++/* Management frame payloads */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_bcn_prb { ++ uint32 timestamp[2]; ++ uint16 beacon_interval; ++ uint16 capability; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BCN_PRB_LEN 12 /* 802.11 beacon/probe frame fixed length */ ++#define DOT11_BCN_PRB_FIXED_LEN 12 /* 802.11 beacon/probe frame fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_auth { ++ uint16 alg; /* algorithm */ ++ uint16 seq; /* sequence control */ ++ uint16 status; /* status code */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_AUTH_FIXED_LEN 6 /* length of auth frame without challenge IE */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_assoc_req { ++ uint16 capability; /* capability information */ ++ uint16 listen; /* listen interval */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ASSOC_REQ_FIXED_LEN 4 /* length of assoc frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_reassoc_req { ++ uint16 capability; /* capability information */ ++ uint16 listen; /* listen interval */ ++ struct ether_addr ap; /* Current AP address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_REASSOC_REQ_FIXED_LEN 10 /* length of assoc frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_assoc_resp { ++ uint16 capability; /* capability information */ ++ uint16 status; /* status code */ ++ uint16 aid; /* association ID */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ASSOC_RESP_FIXED_LEN 6 /* length of assoc resp frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_measure { ++ uint8 category; ++ uint8 action; ++ uint8 token; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACTION_MEASURE_LEN 3 /* d11 action measurement header length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ht_ch_width { ++ uint8 category; ++ uint8 action; ++ uint8 ch_width; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ht_mimops { ++ uint8 category; ++ uint8 action; ++ uint8 control; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_sa_query { ++ uint8 category; ++ uint8 action; ++ uint16 id; ++} BWL_POST_PACKED_STRUCT; ++ ++#define SM_PWRSAVE_ENABLE 1 ++#define SM_PWRSAVE_MODE 2 ++ ++/* ************* 802.11h related definitions. ************* */ ++BWL_PRE_PACKED_STRUCT struct dot11_power_cnst { ++ uint8 id; ++ uint8 len; ++ uint8 power; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_power_cnst dot11_power_cnst_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_power_cap { ++ uint8 min; ++ uint8 max; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_power_cap dot11_power_cap_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_tpc_rep { ++ uint8 id; ++ uint8 len; ++ uint8 tx_pwr; ++ uint8 margin; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_tpc_rep dot11_tpc_rep_t; ++#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_supp_channels { ++ uint8 id; ++ uint8 len; ++ uint8 first_channel; ++ uint8 num_channels; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_supp_channels dot11_supp_channels_t; ++ ++/* Extension Channel Offset IE: 802.11n-D1.0 spec. added sideband ++ * offset for 40MHz operation. The possible 3 values are: ++ * 1 = above control channel ++ * 3 = below control channel ++ * 0 = no extension channel ++ */ ++BWL_PRE_PACKED_STRUCT struct dot11_extch { ++ uint8 id; /* IE ID, 62, DOT11_MNG_EXT_CHANNEL_OFFSET */ ++ uint8 len; /* IE length */ ++ uint8 extch; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extch dot11_extch_ie_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_brcm_extch { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type inidicates what follows */ ++ uint8 extch; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t; ++ ++#define BRCM_EXTCH_IE_LEN 5 ++#define BRCM_EXTCH_IE_TYPE 53 /* 802.11n ID not yet assigned */ ++#define DOT11_EXTCH_IE_LEN 1 ++#define DOT11_EXT_CH_MASK 0x03 /* extension channel mask */ ++#define DOT11_EXT_CH_UPPER 0x01 /* ext. ch. on upper sb */ ++#define DOT11_EXT_CH_LOWER 0x03 /* ext. ch. on lower sb */ ++#define DOT11_EXT_CH_NONE 0x00 /* no extension ch. */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr { ++ uint8 category; ++ uint8 action; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACTION_FRMHDR_LEN 2 ++ ++/* CSA IE data structure */ ++BWL_PRE_PACKED_STRUCT struct dot11_channel_switch { ++ uint8 id; /* id DOT11_MNG_CHANNEL_SWITCH_ID */ ++ uint8 len; /* length of IE */ ++ uint8 mode; /* mode 0 or 1 */ ++ uint8 channel; /* channel switch to */ ++ uint8 count; /* number of beacons before switching */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_channel_switch dot11_chan_switch_ie_t; ++ ++#define DOT11_SWITCH_IE_LEN 3 /* length of IE data, not including 2 byte header */ ++/* CSA mode - 802.11h-2003 $7.3.2.20 */ ++#define DOT11_CSA_MODE_ADVISORY 0 /* no DOT11_CSA_MODE_NO_TX restriction imposed */ ++#define DOT11_CSA_MODE_NO_TX 1 /* no transmission upon receiving CSA frame. */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel { ++ uint8 category; ++ uint8 action; ++ dot11_chan_switch_ie_t chan_switch_ie; /* for switch IE */ ++ dot11_brcm_extch_ie_t extch_ie; /* extension channel offset */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_csa_body { ++ uint8 mode; /* mode 0 or 1 */ ++ uint8 reg; /* regulatory class */ ++ uint8 channel; /* channel switch to */ ++ uint8 count; /* number of beacons before switching */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* 11n Extended Channel Switch IE data structure */ ++BWL_PRE_PACKED_STRUCT struct dot11_ext_csa { ++ uint8 id; /* id DOT11_MNG_EXT_CHANNEL_SWITCH_ID */ ++ uint8 len; /* length of IE */ ++ struct dot11_csa_body b; /* body of the ie */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ext_csa dot11_ext_csa_ie_t; ++#define DOT11_EXT_CSA_IE_LEN 4 /* length of extended channel switch IE body */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ext_csa { ++ uint8 category; ++ uint8 action; ++ dot11_ext_csa_ie_t chan_switch_ie; /* for switch IE */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa { ++ uint8 category; ++ uint8 action; ++ struct dot11_csa_body b; /* body of the ie */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_coex { ++ uint8 id; ++ uint8 len; ++ uint8 info; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_coex dot11_obss_coex_t; ++#define DOT11_OBSS_COEXINFO_LEN 1 /* length of OBSS Coexistence INFO IE */ ++ ++#define DOT11_OBSS_COEX_INFO_REQ 0x01 ++#define DOT11_OBSS_COEX_40MHZ_INTOLERANT 0x02 ++#define DOT11_OBSS_COEX_20MHZ_WIDTH_REQ 0x04 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_chanlist { ++ uint8 id; ++ uint8 len; ++ uint8 regclass; ++ uint8 chanlist[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_chanlist dot11_obss_chanlist_t; ++#define DOT11_OBSS_CHANLIST_FIXED_LEN 1 /* fixed length of regclass */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie { ++ uint8 id; ++ uint8 len; ++ uint8 cap[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extcap_ie dot11_extcap_ie_t; ++ ++#define DOT11_EXTCAP_LEN_MAX 7 ++#define DOT11_EXTCAP_LEN_COEX 1 ++#define DOT11_EXTCAP_LEN_BT 3 ++#define DOT11_EXTCAP_LEN_IW 4 ++#define DOT11_EXTCAP_LEN_SI 6 ++ ++#define DOT11_EXTCAP_LEN_TDLS 5 ++BWL_PRE_PACKED_STRUCT struct dot11_extcap { ++ uint8 extcap[DOT11_EXTCAP_LEN_TDLS]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extcap dot11_extcap_t; ++ ++/* TDLS Capabilities */ ++#define TDLS_CAP_TDLS 37 /* TDLS support */ ++#define TDLS_CAP_PU_BUFFER_STA 28 /* TDLS Peer U-APSD buffer STA support */ ++#define TDLS_CAP_PEER_PSM 20 /* TDLS Peer PSM support */ ++#define TDLS_CAP_CH_SW 30 /* TDLS Channel switch */ ++#define TDLS_CAP_PROH 38 /* TDLS prohibited */ ++#define TDLS_CAP_CH_SW_PROH 39 /* TDLS Channel switch prohibited */ ++ ++#define TDLS_CAP_MAX_BIT 39 /* TDLS max bit defined in ext cap */ ++ ++/* 802.11h/802.11k Measurement Request/Report IEs */ ++/* Measurement Type field */ ++#define DOT11_MEASURE_TYPE_BASIC 0 /* d11 measurement basic type */ ++#define DOT11_MEASURE_TYPE_CCA 1 /* d11 measurement CCA type */ ++#define DOT11_MEASURE_TYPE_RPI 2 /* d11 measurement RPI type */ ++#define DOT11_MEASURE_TYPE_CHLOAD 3 /* d11 measurement Channel Load type */ ++#define DOT11_MEASURE_TYPE_NOISE 4 /* d11 measurement Noise Histogram type */ ++#define DOT11_MEASURE_TYPE_BEACON 5 /* d11 measurement Beacon type */ ++#define DOT11_MEASURE_TYPE_FRAME 6 /* d11 measurement Frame type */ ++#define DOT11_MEASURE_TYPE_STATS 7 /* d11 measurement STA Statistics type */ ++#define DOT11_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */ ++#define DOT11_MEASURE_TYPE_TXSTREAM 9 /* d11 measurement TX Stream type */ ++#define DOT11_MEASURE_TYPE_PAUSE 255 /* d11 measurement pause type */ ++ ++/* Measurement Request Modes */ ++#define DOT11_MEASURE_MODE_PARALLEL (1<<0) /* d11 measurement parallel */ ++#define DOT11_MEASURE_MODE_ENABLE (1<<1) /* d11 measurement enable */ ++#define DOT11_MEASURE_MODE_REQUEST (1<<2) /* d11 measurement request */ ++#define DOT11_MEASURE_MODE_REPORT (1<<3) /* d11 measurement report */ ++#define DOT11_MEASURE_MODE_DUR (1<<4) /* d11 measurement dur mandatory */ ++/* Measurement Report Modes */ ++#define DOT11_MEASURE_MODE_LATE (1<<0) /* d11 measurement late */ ++#define DOT11_MEASURE_MODE_INCAPABLE (1<<1) /* d11 measurement incapable */ ++#define DOT11_MEASURE_MODE_REFUSED (1<<2) /* d11 measurement refuse */ ++/* Basic Measurement Map bits */ ++#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0)) /* d11 measurement basic map BSS */ ++#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1)) /* d11 measurement map OFDM */ ++#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2)) /* d11 measurement map unknown */ ++#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3)) /* d11 measurement map radar */ ++#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4)) /* d11 measurement map unmeasuremnt */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_req { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_req dot11_meas_req_t; ++#define DOT11_MNG_IE_MREQ_LEN 14 /* d11 measurement request IE length */ ++/* length of Measure Request IE data not including variable len */ ++#define DOT11_MNG_IE_MREQ_FIXED_LEN 3 /* d11 measurement request IE fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_rep { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ BWL_PRE_PACKED_STRUCT union ++ { ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++ uint8 map; ++ } BWL_POST_PACKED_STRUCT basic; ++ uint8 data[1]; ++ } BWL_POST_PACKED_STRUCT rep; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_rep dot11_meas_rep_t; ++ ++/* length of Measure Report IE data not including variable len */ ++#define DOT11_MNG_IE_MREP_FIXED_LEN 3 /* d11 measurement response IE fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_rep_basic { ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++ uint8 map; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t; ++#define DOT11_MEASURE_BASIC_REP_LEN 12 /* d11 measurement basic report length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_quiet { ++ uint8 id; ++ uint8 len; ++ uint8 count; /* TBTTs until beacon interval in quiet starts */ ++ uint8 period; /* Beacon intervals between periodic quiet periods ? */ ++ uint16 duration; /* Length of quiet period, in TU's */ ++ uint16 offset; /* TU's offset from TBTT in Count field */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_quiet dot11_quiet_t; ++ ++BWL_PRE_PACKED_STRUCT struct chan_map_tuple { ++ uint8 channel; ++ uint8 map; ++} BWL_POST_PACKED_STRUCT; ++typedef struct chan_map_tuple chan_map_tuple_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ibss_dfs { ++ uint8 id; ++ uint8 len; ++ uint8 eaddr[ETHER_ADDR_LEN]; ++ uint8 interval; ++ chan_map_tuple_t map[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ibss_dfs dot11_ibss_dfs_t; ++ ++/* WME Elements */ ++#define WME_OUI "\x00\x50\xf2" /* WME OUI */ ++#define WME_OUI_LEN 3 ++#define WME_OUI_TYPE 2 /* WME type */ ++#define WME_TYPE 2 /* WME type, deprecated */ ++#define WME_SUBTYPE_IE 0 /* Information Element */ ++#define WME_SUBTYPE_PARAM_IE 1 /* Parameter Element */ ++#define WME_SUBTYPE_TSPEC 2 /* Traffic Specification */ ++#define WME_VER 1 /* WME version */ ++ ++/* WME Access Category Indices (ACIs) */ ++#define AC_BE 0 /* Best Effort */ ++#define AC_BK 1 /* Background */ ++#define AC_VI 2 /* Video */ ++#define AC_VO 3 /* Voice */ ++#define AC_COUNT 4 /* number of ACs */ ++ ++typedef uint8 ac_bitmap_t; /* AC bitmap of (1 << AC_xx) */ ++ ++#define AC_BITMAP_NONE 0x0 /* No ACs */ ++#define AC_BITMAP_ALL 0xf /* All ACs */ ++#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0) ++#define AC_BITMAP_SET(ab, ac) (((ab) |= (1 << (ac)))) ++#define AC_BITMAP_RESET(ab, ac) (((ab) &= ~(1 << (ac)))) ++ ++/* WME Information Element (IE) */ ++BWL_PRE_PACKED_STRUCT struct wme_ie { ++ uint8 oui[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 version; ++ uint8 qosinfo; ++} BWL_POST_PACKED_STRUCT; ++typedef struct wme_ie wme_ie_t; ++#define WME_IE_LEN 7 /* WME IE length */ ++ ++BWL_PRE_PACKED_STRUCT struct edcf_acparam { ++ uint8 ACI; ++ uint8 ECW; ++ uint16 TXOP; /* stored in network order (ls octet first) */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct edcf_acparam edcf_acparam_t; ++ ++/* WME Parameter Element (PE) */ ++BWL_PRE_PACKED_STRUCT struct wme_param_ie { ++ uint8 oui[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 version; ++ uint8 qosinfo; ++ uint8 rsvd; ++ edcf_acparam_t acparam[AC_COUNT]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct wme_param_ie wme_param_ie_t; ++#define WME_PARAM_IE_LEN 24 /* WME Parameter IE length */ ++ ++/* QoS Info field for IE as sent from AP */ ++#define WME_QI_AP_APSD_MASK 0x80 /* U-APSD Supported mask */ ++#define WME_QI_AP_APSD_SHIFT 7 /* U-APSD Supported shift */ ++#define WME_QI_AP_COUNT_MASK 0x0f /* Parameter set count mask */ ++#define WME_QI_AP_COUNT_SHIFT 0 /* Parameter set count shift */ ++ ++/* QoS Info field for IE as sent from STA */ ++#define WME_QI_STA_MAXSPLEN_MASK 0x60 /* Max Service Period Length mask */ ++#define WME_QI_STA_MAXSPLEN_SHIFT 5 /* Max Service Period Length shift */ ++#define WME_QI_STA_APSD_ALL_MASK 0xf /* APSD all AC bits mask */ ++#define WME_QI_STA_APSD_ALL_SHIFT 0 /* APSD all AC bits shift */ ++#define WME_QI_STA_APSD_BE_MASK 0x8 /* APSD AC_BE mask */ ++#define WME_QI_STA_APSD_BE_SHIFT 3 /* APSD AC_BE shift */ ++#define WME_QI_STA_APSD_BK_MASK 0x4 /* APSD AC_BK mask */ ++#define WME_QI_STA_APSD_BK_SHIFT 2 /* APSD AC_BK shift */ ++#define WME_QI_STA_APSD_VI_MASK 0x2 /* APSD AC_VI mask */ ++#define WME_QI_STA_APSD_VI_SHIFT 1 /* APSD AC_VI shift */ ++#define WME_QI_STA_APSD_VO_MASK 0x1 /* APSD AC_VO mask */ ++#define WME_QI_STA_APSD_VO_SHIFT 0 /* APSD AC_VO shift */ ++ ++/* ACI */ ++#define EDCF_AIFSN_MIN 1 /* AIFSN minimum value */ ++#define EDCF_AIFSN_MAX 15 /* AIFSN maximum value */ ++#define EDCF_AIFSN_MASK 0x0f /* AIFSN mask */ ++#define EDCF_ACM_MASK 0x10 /* ACM mask */ ++#define EDCF_ACI_MASK 0x60 /* ACI mask */ ++#define EDCF_ACI_SHIFT 5 /* ACI shift */ ++#define EDCF_AIFSN_SHIFT 12 /* 4 MSB(0xFFF) in ifs_ctl for AC idx */ ++ ++/* ECW */ ++#define EDCF_ECW_MIN 0 /* cwmin/cwmax exponent minimum value */ ++#define EDCF_ECW_MAX 15 /* cwmin/cwmax exponent maximum value */ ++#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1) ++#define EDCF_ECWMIN_MASK 0x0f /* cwmin exponent form mask */ ++#define EDCF_ECWMAX_MASK 0xf0 /* cwmax exponent form mask */ ++#define EDCF_ECWMAX_SHIFT 4 /* cwmax exponent form shift */ ++ ++/* TXOP */ ++#define EDCF_TXOP_MIN 0 /* TXOP minimum value */ ++#define EDCF_TXOP_MAX 65535 /* TXOP maximum value */ ++#define EDCF_TXOP2USEC(txop) ((txop) << 5) ++ ++/* Default BE ACI value for non-WME connection STA */ ++#define NON_EDCF_AC_BE_ACI_STA 0x02 ++ ++/* Default EDCF parameters that AP advertises for STA to use; WMM draft Table 12 */ ++#define EDCF_AC_BE_ACI_STA 0x03 /* STA ACI value for best effort AC */ ++#define EDCF_AC_BE_ECW_STA 0xA4 /* STA ECW value for best effort AC */ ++#define EDCF_AC_BE_TXOP_STA 0x0000 /* STA TXOP value for best effort AC */ ++#define EDCF_AC_BK_ACI_STA 0x27 /* STA ACI value for background AC */ ++#define EDCF_AC_BK_ECW_STA 0xA4 /* STA ECW value for background AC */ ++#define EDCF_AC_BK_TXOP_STA 0x0000 /* STA TXOP value for background AC */ ++#define EDCF_AC_VI_ACI_STA 0x42 /* STA ACI value for video AC */ ++#define EDCF_AC_VI_ECW_STA 0x43 /* STA ECW value for video AC */ ++#define EDCF_AC_VI_TXOP_STA 0x005e /* STA TXOP value for video AC */ ++#define EDCF_AC_VO_ACI_STA 0x62 /* STA ACI value for audio AC */ ++#define EDCF_AC_VO_ECW_STA 0x32 /* STA ECW value for audio AC */ ++#define EDCF_AC_VO_TXOP_STA 0x002f /* STA TXOP value for audio AC */ ++ ++/* Default EDCF parameters that AP uses; WMM draft Table 14 */ ++#define EDCF_AC_BE_ACI_AP 0x03 /* AP ACI value for best effort AC */ ++#define EDCF_AC_BE_ECW_AP 0x64 /* AP ECW value for best effort AC */ ++#define EDCF_AC_BE_TXOP_AP 0x0000 /* AP TXOP value for best effort AC */ ++#define EDCF_AC_BK_ACI_AP 0x27 /* AP ACI value for background AC */ ++#define EDCF_AC_BK_ECW_AP 0xA4 /* AP ECW value for background AC */ ++#define EDCF_AC_BK_TXOP_AP 0x0000 /* AP TXOP value for background AC */ ++#define EDCF_AC_VI_ACI_AP 0x41 /* AP ACI value for video AC */ ++#define EDCF_AC_VI_ECW_AP 0x43 /* AP ECW value for video AC */ ++#define EDCF_AC_VI_TXOP_AP 0x005e /* AP TXOP value for video AC */ ++#define EDCF_AC_VO_ACI_AP 0x61 /* AP ACI value for audio AC */ ++#define EDCF_AC_VO_ECW_AP 0x32 /* AP ECW value for audio AC */ ++#define EDCF_AC_VO_TXOP_AP 0x002f /* AP TXOP value for audio AC */ ++ ++/* EDCA Parameter IE */ ++BWL_PRE_PACKED_STRUCT struct edca_param_ie { ++ uint8 qosinfo; ++ uint8 rsvd; ++ edcf_acparam_t acparam[AC_COUNT]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct edca_param_ie edca_param_ie_t; ++#define EDCA_PARAM_IE_LEN 18 /* EDCA Parameter IE length */ ++ ++/* QoS Capability IE */ ++BWL_PRE_PACKED_STRUCT struct qos_cap_ie { ++ uint8 qosinfo; ++} BWL_POST_PACKED_STRUCT; ++typedef struct qos_cap_ie qos_cap_ie_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_qbss_load_ie { ++ uint8 id; /* 11, DOT11_MNG_QBSS_LOAD_ID */ ++ uint8 length; ++ uint16 station_count; /* total number of STAs associated */ ++ uint8 channel_utilization; /* % of time, normalized to 255, QAP sensed medium busy */ ++ uint16 aac; /* available admission capacity */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t; ++#define BSS_LOAD_IE_SIZE 7 /* BSS load IE size */ ++ ++/* nom_msdu_size */ ++#define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */ ++#define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */ ++ ++/* surplus_bandwidth */ ++/* Represented as 3 bits of integer, binary point, 13 bits fraction */ ++#define INTEGER_SHIFT 13 /* integer shift */ ++#define FRACTION_MASK 0x1FFF /* fraction mask */ ++ ++/* Management Notification Frame */ ++BWL_PRE_PACKED_STRUCT struct dot11_management_notification { ++ uint8 category; /* DOT11_ACTION_NOTIFICATION */ ++ uint8 action; ++ uint8 token; ++ uint8 status; ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_MGMT_NOTIFICATION_LEN 4 /* Fixed length */ ++ ++/* Timeout Interval IE */ ++BWL_PRE_PACKED_STRUCT struct ti_ie { ++ uint8 ti_type; ++ uint32 ti_val; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ti_ie ti_ie_t; ++#define TI_TYPE_REASSOC_DEADLINE 1 ++#define TI_TYPE_KEY_LIFETIME 2 ++ ++/* WME Action Codes */ ++#define WME_ADDTS_REQUEST 0 /* WME ADDTS request */ ++#define WME_ADDTS_RESPONSE 1 /* WME ADDTS response */ ++#define WME_DELTS_REQUEST 2 /* WME DELTS request */ ++ ++/* WME Setup Response Status Codes */ ++#define WME_ADMISSION_ACCEPTED 0 /* WME admission accepted */ ++#define WME_INVALID_PARAMETERS 1 /* WME invalide parameters */ ++#define WME_ADMISSION_REFUSED 3 /* WME admission refused */ ++ ++/* Macro to take a pointer to a beacon or probe response ++ * body and return the char* pointer to the SSID info element ++ */ ++#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN) ++ ++/* Authentication frame payload constants */ ++#define DOT11_OPEN_SYSTEM 0 /* d11 open authentication */ ++#define DOT11_SHARED_KEY 1 /* d11 shared authentication */ ++#define DOT11_FAST_BSS 2 /* d11 fast bss authentication */ ++#define DOT11_CHALLENGE_LEN 128 /* d11 challenge text length */ ++ ++/* Frame control macros */ ++#define FC_PVER_MASK 0x3 /* PVER mask */ ++#define FC_PVER_SHIFT 0 /* PVER shift */ ++#define FC_TYPE_MASK 0xC /* type mask */ ++#define FC_TYPE_SHIFT 2 /* type shift */ ++#define FC_SUBTYPE_MASK 0xF0 /* subtype mask */ ++#define FC_SUBTYPE_SHIFT 4 /* subtype shift */ ++#define FC_TODS 0x100 /* to DS */ ++#define FC_TODS_SHIFT 8 /* to DS shift */ ++#define FC_FROMDS 0x200 /* from DS */ ++#define FC_FROMDS_SHIFT 9 /* from DS shift */ ++#define FC_MOREFRAG 0x400 /* more frag. */ ++#define FC_MOREFRAG_SHIFT 10 /* more frag. shift */ ++#define FC_RETRY 0x800 /* retry */ ++#define FC_RETRY_SHIFT 11 /* retry shift */ ++#define FC_PM 0x1000 /* PM */ ++#define FC_PM_SHIFT 12 /* PM shift */ ++#define FC_MOREDATA 0x2000 /* more data */ ++#define FC_MOREDATA_SHIFT 13 /* more data shift */ ++#define FC_WEP 0x4000 /* WEP */ ++#define FC_WEP_SHIFT 14 /* WEP shift */ ++#define FC_ORDER 0x8000 /* order */ ++#define FC_ORDER_SHIFT 15 /* order shift */ ++ ++/* sequence control macros */ ++#define SEQNUM_SHIFT 4 /* seq. number shift */ ++#define SEQNUM_MAX 0x1000 /* max seqnum + 1 */ ++#define FRAGNUM_MASK 0xF /* frag. number mask */ ++ ++/* Frame Control type/subtype defs */ ++ ++/* FC Types */ ++#define FC_TYPE_MNG 0 /* management type */ ++#define FC_TYPE_CTL 1 /* control type */ ++#define FC_TYPE_DATA 2 /* data type */ ++ ++/* Management Subtypes */ ++#define FC_SUBTYPE_ASSOC_REQ 0 /* assoc. request */ ++#define FC_SUBTYPE_ASSOC_RESP 1 /* assoc. response */ ++#define FC_SUBTYPE_REASSOC_REQ 2 /* reassoc. request */ ++#define FC_SUBTYPE_REASSOC_RESP 3 /* reassoc. response */ ++#define FC_SUBTYPE_PROBE_REQ 4 /* probe request */ ++#define FC_SUBTYPE_PROBE_RESP 5 /* probe response */ ++#define FC_SUBTYPE_BEACON 8 /* beacon */ ++#define FC_SUBTYPE_ATIM 9 /* ATIM */ ++#define FC_SUBTYPE_DISASSOC 10 /* disassoc. */ ++#define FC_SUBTYPE_AUTH 11 /* authentication */ ++#define FC_SUBTYPE_DEAUTH 12 /* de-authentication */ ++#define FC_SUBTYPE_ACTION 13 /* action */ ++#define FC_SUBTYPE_ACTION_NOACK 14 /* action no-ack */ ++ ++/* Control Subtypes */ ++#define FC_SUBTYPE_CTL_WRAPPER 7 /* Control Wrapper */ ++#define FC_SUBTYPE_BLOCKACK_REQ 8 /* Block Ack Req */ ++#define FC_SUBTYPE_BLOCKACK 9 /* Block Ack */ ++#define FC_SUBTYPE_PS_POLL 10 /* PS poll */ ++#define FC_SUBTYPE_RTS 11 /* RTS */ ++#define FC_SUBTYPE_CTS 12 /* CTS */ ++#define FC_SUBTYPE_ACK 13 /* ACK */ ++#define FC_SUBTYPE_CF_END 14 /* CF-END */ ++#define FC_SUBTYPE_CF_END_ACK 15 /* CF-END ACK */ ++ ++/* Data Subtypes */ ++#define FC_SUBTYPE_DATA 0 /* Data */ ++#define FC_SUBTYPE_DATA_CF_ACK 1 /* Data + CF-ACK */ ++#define FC_SUBTYPE_DATA_CF_POLL 2 /* Data + CF-Poll */ ++#define FC_SUBTYPE_DATA_CF_ACK_POLL 3 /* Data + CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_NULL 4 /* Null */ ++#define FC_SUBTYPE_CF_ACK 5 /* CF-Ack */ ++#define FC_SUBTYPE_CF_POLL 6 /* CF-Poll */ ++#define FC_SUBTYPE_CF_ACK_POLL 7 /* CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_QOS_DATA 8 /* QoS Data */ ++#define FC_SUBTYPE_QOS_DATA_CF_ACK 9 /* QoS Data + CF-Ack */ ++#define FC_SUBTYPE_QOS_DATA_CF_POLL 10 /* QoS Data + CF-Poll */ ++#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11 /* QoS Data + CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_QOS_NULL 12 /* QoS Null */ ++#define FC_SUBTYPE_QOS_CF_POLL 14 /* QoS CF-Poll */ ++#define FC_SUBTYPE_QOS_CF_ACK_POLL 15 /* QoS CF-Ack + CF-Poll */ ++ ++/* Data Subtype Groups */ ++#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0) ++#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0) ++#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0) ++#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0) ++ ++/* Type/Subtype Combos */ ++#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK) /* FC kind mask */ ++ ++#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT)) /* FC kind */ ++ ++#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT) /* Subtype from FC */ ++#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT) /* Type from FC */ ++ ++#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ) /* assoc. request */ ++#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP) /* assoc. response */ ++#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ) /* reassoc. request */ ++#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP) /* reassoc. response */ ++#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ) /* probe request */ ++#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP) /* probe response */ ++#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON) /* beacon */ ++#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC) /* disassoc */ ++#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH) /* authentication */ ++#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH) /* deauthentication */ ++#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) /* action */ ++#define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK) /* action no-ack */ ++ ++#define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER) /* Control Wrapper */ ++#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ) /* Block Ack Req */ ++#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK) /* Block Ack */ ++#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL) /* PS poll */ ++#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS) /* RTS */ ++#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS) /* CTS */ ++#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK) /* ACK */ ++#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END) /* CF-END */ ++#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK) /* CF-END ACK */ ++ ++#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA) /* data */ ++#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL) /* null data */ ++#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK) /* data CF ACK */ ++#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA) /* QoS data */ ++#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL) /* QoS null */ ++ ++/* QoS Control Field */ ++ ++/* 802.1D Priority */ ++#define QOS_PRIO_SHIFT 0 /* QoS priority shift */ ++#define QOS_PRIO_MASK 0x0007 /* QoS priority mask */ ++#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT) /* QoS priority */ ++ ++/* Traffic Identifier */ ++#define QOS_TID_SHIFT 0 /* QoS TID shift */ ++#define QOS_TID_MASK 0x000f /* QoS TID mask */ ++#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT) /* QoS TID */ ++ ++/* End of Service Period (U-APSD) */ ++#define QOS_EOSP_SHIFT 4 /* QoS End of Service Period shift */ ++#define QOS_EOSP_MASK 0x0010 /* QoS End of Service Period mask */ ++#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT) /* Qos EOSP */ ++ ++/* Ack Policy */ ++#define QOS_ACK_NORMAL_ACK 0 /* Normal Ack */ ++#define QOS_ACK_NO_ACK 1 /* No Ack (eg mcast) */ ++#define QOS_ACK_NO_EXP_ACK 2 /* No Explicit Ack */ ++#define QOS_ACK_BLOCK_ACK 3 /* Block Ack */ ++#define QOS_ACK_SHIFT 5 /* QoS ACK shift */ ++#define QOS_ACK_MASK 0x0060 /* QoS ACK mask */ ++#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT) /* QoS ACK */ ++ ++/* A-MSDU flag */ ++#define QOS_AMSDU_SHIFT 7 /* AMSDU shift */ ++#define QOS_AMSDU_MASK 0x0080 /* AMSDU mask */ ++ ++/* Management Frames */ ++ ++/* Management Frame Constants */ ++ ++/* Fixed fields */ ++#define DOT11_MNG_AUTH_ALGO_LEN 2 /* d11 management auth. algo. length */ ++#define DOT11_MNG_AUTH_SEQ_LEN 2 /* d11 management auth. seq. length */ ++#define DOT11_MNG_BEACON_INT_LEN 2 /* d11 management beacon interval length */ ++#define DOT11_MNG_CAP_LEN 2 /* d11 management cap. length */ ++#define DOT11_MNG_AP_ADDR_LEN 6 /* d11 management AP address length */ ++#define DOT11_MNG_LISTEN_INT_LEN 2 /* d11 management listen interval length */ ++#define DOT11_MNG_REASON_LEN 2 /* d11 management reason length */ ++#define DOT11_MNG_AID_LEN 2 /* d11 management AID length */ ++#define DOT11_MNG_STATUS_LEN 2 /* d11 management status length */ ++#define DOT11_MNG_TIMESTAMP_LEN 8 /* d11 management timestamp length */ ++ ++/* DUR/ID field in assoc resp is 0xc000 | AID */ ++#define DOT11_AID_MASK 0x3fff /* d11 AID mask */ ++ ++/* Reason Codes */ ++#define DOT11_RC_RESERVED 0 /* d11 RC reserved */ ++#define DOT11_RC_UNSPECIFIED 1 /* Unspecified reason */ ++#define DOT11_RC_AUTH_INVAL 2 /* Previous authentication no longer valid */ ++#define DOT11_RC_DEAUTH_LEAVING 3 /* Deauthenticated because sending station ++ * is leaving (or has left) IBSS or ESS ++ */ ++#define DOT11_RC_INACTIVITY 4 /* Disassociated due to inactivity */ ++#define DOT11_RC_BUSY 5 /* Disassociated because AP is unable to handle ++ * all currently associated stations ++ */ ++#define DOT11_RC_INVAL_CLASS_2 6 /* Class 2 frame received from ++ * nonauthenticated station ++ */ ++#define DOT11_RC_INVAL_CLASS_3 7 /* Class 3 frame received from ++ * nonassociated station ++ */ ++#define DOT11_RC_DISASSOC_LEAVING 8 /* Disassociated because sending station is ++ * leaving (or has left) BSS ++ */ ++#define DOT11_RC_NOT_AUTH 9 /* Station requesting (re)association is not ++ * authenticated with responding station ++ */ ++#define DOT11_RC_BAD_PC 10 /* Unacceptable power capability element */ ++#define DOT11_RC_BAD_CHANNELS 11 /* Unacceptable supported channels element */ ++/* 12 is unused */ ++ ++/* 32-39 are QSTA specific reasons added in 11e */ ++#define DOT11_RC_UNSPECIFIED_QOS 32 /* unspecified QoS-related reason */ ++#define DOT11_RC_INSUFFCIENT_BW 33 /* QAP lacks sufficient bandwidth */ ++#define DOT11_RC_EXCESSIVE_FRAMES 34 /* excessive number of frames need ack */ ++#define DOT11_RC_TX_OUTSIDE_TXOP 35 /* transmitting outside the limits of txop */ ++#define DOT11_RC_LEAVING_QBSS 36 /* QSTA is leaving the QBSS (or restting) */ ++#define DOT11_RC_BAD_MECHANISM 37 /* does not want to use the mechanism */ ++#define DOT11_RC_SETUP_NEEDED 38 /* mechanism needs a setup */ ++#define DOT11_RC_TIMEOUT 39 /* timeout */ ++ ++#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */ ++ ++#define DOT11_RC_TDLS_PEER_UNREACH 25 ++#define DOT11_RC_TDLS_DOWN_UNSPECIFIED 26 ++ ++/* Status Codes */ ++#define DOT11_SC_SUCCESS 0 /* Successful */ ++#define DOT11_SC_FAILURE 1 /* Unspecified failure */ ++#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2 /* TDLS wakeup schedule rejected but alternative */ ++ /* schedule provided */ ++#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3 /* TDLS wakeup schedule rejected */ ++#define DOT11_SC_TDLS_SEC_DISABLED 5 /* TDLS Security disabled */ ++#define DOT11_SC_LIFETIME_REJ 6 /* Unacceptable lifetime */ ++#define DOT11_SC_NOT_SAME_BSS 7 /* Not in same BSS */ ++#define DOT11_SC_CAP_MISMATCH 10 /* Cannot support all requested ++ * capabilities in the Capability ++ * Information field ++ */ ++#define DOT11_SC_REASSOC_FAIL 11 /* Reassociation denied due to inability ++ * to confirm that association exists ++ */ ++#define DOT11_SC_ASSOC_FAIL 12 /* Association denied due to reason ++ * outside the scope of this standard ++ */ ++#define DOT11_SC_AUTH_MISMATCH 13 /* Responding station does not support ++ * the specified authentication ++ * algorithm ++ */ ++#define DOT11_SC_AUTH_SEQ 14 /* Received an Authentication frame ++ * with authentication transaction ++ * sequence number out of expected ++ * sequence ++ */ ++#define DOT11_SC_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of ++ * challenge failure ++ */ ++#define DOT11_SC_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout ++ * waiting for next frame in sequence ++ */ ++#define DOT11_SC_ASSOC_BUSY_FAIL 17 /* Association denied because AP is ++ * unable to handle additional ++ * associated stations ++ */ ++#define DOT11_SC_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting ++ * station not supporting all of the ++ * data rates in the BSSBasicRateSet ++ * parameter ++ */ ++#define DOT11_SC_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting ++ * station not supporting the Short ++ * Preamble option ++ */ ++#define DOT11_SC_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting ++ * station not supporting the PBCC ++ * Modulation option ++ */ ++#define DOT11_SC_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting ++ * station not supporting the Channel ++ * Agility option ++ */ ++#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum ++ * Management capability is required. ++ */ ++#define DOT11_SC_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info ++ * in the Power Cap element is ++ * unacceptable. ++ */ ++#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info ++ * in the Supported Channel element is ++ * unacceptable ++ */ ++#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting ++ * station not supporting the Short Slot ++ * Time option ++ */ ++#define DOT11_SC_ASSOC_ERPBCC_REQUIRED 26 /* Association denied due to requesting ++ * station not supporting the ER-PBCC ++ * Modulation option ++ */ ++#define DOT11_SC_ASSOC_DSSOFDM_REQUIRED 27 /* Association denied due to requesting ++ * station not supporting the DSS-OFDM ++ * option ++ */ ++#define DOT11_SC_ASSOC_R0KH_UNREACHABLE 28 /* Association denied due to AP ++ * being unable to reach the R0 Key Holder ++ */ ++#define DOT11_SC_ASSOC_TRY_LATER 30 /* Association denied temporarily, try again later ++ */ ++#define DOT11_SC_ASSOC_MFP_VIOLATION 31 /* Association denied due to Robust Management ++ * frame policy violation ++ */ ++ ++#define DOT11_SC_DECLINED 37 /* request declined */ ++#define DOT11_SC_INVALID_PARAMS 38 /* One or more params have invalid values */ ++#define DOT11_SC_INVALID_PAIRWISE_CIPHER 42 /* invalid pairwise cipher */ ++#define DOT11_SC_INVALID_AKMP 43 /* Association denied due to invalid AKMP */ ++#define DOT11_SC_INVALID_RSNIE_CAP 45 /* invalid RSN IE capabilities */ ++#define DOT11_SC_DLS_NOT_ALLOWED 48 /* DLS is not allowed in the BSS by policy */ ++#define DOT11_SC_INVALID_PMKID 53 /* Association denied due to invalid PMKID */ ++#define DOT11_SC_INVALID_MDID 54 /* Association denied due to invalid MDID */ ++#define DOT11_SC_INVALID_FTIE 55 /* Association denied due to invalid FTIE */ ++ ++#define DOT11_SC_UNEXP_MSG 70 /* Unexpected message */ ++#define DOT11_SC_INVALID_SNONCE 71 /* Invalid SNonce */ ++#define DOT11_SC_INVALID_RSNIE 72 /* Invalid contents of RSNIE */ ++ ++/* Info Elts, length of INFORMATION portion of Info Elts */ ++#define DOT11_MNG_DS_PARAM_LEN 1 /* d11 management DS parameter length */ ++#define DOT11_MNG_IBSS_PARAM_LEN 2 /* d11 management IBSS parameter length */ ++ ++/* TIM Info element has 3 bytes fixed info in INFORMATION field, ++ * followed by 1 to 251 bytes of Partial Virtual Bitmap ++ */ ++#define DOT11_MNG_TIM_FIXED_LEN 3 /* d11 management TIM fixed length */ ++#define DOT11_MNG_TIM_DTIM_COUNT 0 /* d11 management DTIM count */ ++#define DOT11_MNG_TIM_DTIM_PERIOD 1 /* d11 management DTIM period */ ++#define DOT11_MNG_TIM_BITMAP_CTL 2 /* d11 management TIM BITMAP control */ ++#define DOT11_MNG_TIM_PVB 3 /* d11 management TIM PVB */ ++ ++/* TLV defines */ ++#define TLV_TAG_OFF 0 /* tag offset */ ++#define TLV_LEN_OFF 1 /* length offset */ ++#define TLV_HDR_LEN 2 /* header length */ ++#define TLV_BODY_OFF 2 /* body offset */ ++ ++/* Management Frame Information Element IDs */ ++#define DOT11_MNG_SSID_ID 0 /* d11 management SSID id */ ++#define DOT11_MNG_RATES_ID 1 /* d11 management rates id */ ++#define DOT11_MNG_FH_PARMS_ID 2 /* d11 management FH parameter id */ ++#define DOT11_MNG_DS_PARMS_ID 3 /* d11 management DS parameter id */ ++#define DOT11_MNG_CF_PARMS_ID 4 /* d11 management CF parameter id */ ++#define DOT11_MNG_TIM_ID 5 /* d11 management TIM id */ ++#define DOT11_MNG_IBSS_PARMS_ID 6 /* d11 management IBSS parameter id */ ++#define DOT11_MNG_COUNTRY_ID 7 /* d11 management country id */ ++#define DOT11_MNG_HOPPING_PARMS_ID 8 /* d11 management hopping parameter id */ ++#define DOT11_MNG_HOPPING_TABLE_ID 9 /* d11 management hopping table id */ ++#define DOT11_MNG_REQUEST_ID 10 /* d11 management request id */ ++#define DOT11_MNG_QBSS_LOAD_ID 11 /* d11 management QBSS Load id */ ++#define DOT11_MNG_EDCA_PARAM_ID 12 /* 11E EDCA Parameter id */ ++#define DOT11_MNG_CHALLENGE_ID 16 /* d11 management chanllenge id */ ++#define DOT11_MNG_PWR_CONSTRAINT_ID 32 /* 11H PowerConstraint */ ++#define DOT11_MNG_PWR_CAP_ID 33 /* 11H PowerCapability */ ++#define DOT11_MNG_TPC_REQUEST_ID 34 /* 11H TPC Request */ ++#define DOT11_MNG_TPC_REPORT_ID 35 /* 11H TPC Report */ ++#define DOT11_MNG_SUPP_CHANNELS_ID 36 /* 11H Supported Channels */ ++#define DOT11_MNG_CHANNEL_SWITCH_ID 37 /* 11H ChannelSwitch Announcement */ ++#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */ ++#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementReport */ ++#define DOT11_MNG_QUIET_ID 40 /* 11H Quiet */ ++#define DOT11_MNG_IBSS_DFS_ID 41 /* 11H IBSS_DFS */ ++#define DOT11_MNG_ERP_ID 42 /* d11 management ERP id */ ++#define DOT11_MNG_TS_DELAY_ID 43 /* d11 management TS Delay id */ ++#define DOT11_MNG_HT_CAP 45 /* d11 mgmt HT cap id */ ++#define DOT11_MNG_QOS_CAP_ID 46 /* 11E QoS Capability id */ ++#define DOT11_MNG_NONERP_ID 47 /* d11 management NON-ERP id */ ++#define DOT11_MNG_RSN_ID 48 /* d11 management RSN id */ ++#define DOT11_MNG_EXT_RATES_ID 50 /* d11 management ext. rates id */ ++#define DOT11_MNG_AP_CHREP_ID 51 /* 11k AP Channel report id */ ++#define DOT11_MNG_NBR_REP_ID 52 /* 11k Neighbor report id */ ++#define DOT11_MNG_MDIE_ID 54 /* 11r Mobility domain id */ ++#define DOT11_MNG_FTIE_ID 55 /* 11r Fast Bss Transition id */ ++#define DOT11_MNG_FT_TI_ID 56 /* 11r Timeout Interval id */ ++#define DOT11_MNG_REGCLASS_ID 59 /* d11 management regulatory class id */ ++#define DOT11_MNG_EXT_CSA_ID 60 /* d11 Extended CSA */ ++#define DOT11_MNG_HT_ADD 61 /* d11 mgmt additional HT info */ ++#define DOT11_MNG_EXT_CHANNEL_OFFSET 62 /* d11 mgmt ext channel offset */ ++#define DOT11_MNG_WAPI_ID 68 /* d11 management WAPI id */ ++#define DOT11_MNG_TIME_ADVERTISE_ID 69 /* 11p time advertisement */ ++#define DOT11_MNG_RRM_CAP_ID 70 /* 11k radio measurement capability */ ++#define DOT11_MNG_HT_BSS_COEXINFO_ID 72 /* d11 mgmt OBSS Coexistence INFO */ ++#define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73 /* d11 mgmt OBSS Intolerant Channel list */ ++#define DOT11_MNG_HT_OBSS_ID 74 /* d11 mgmt OBSS HT info */ ++#define DOT11_MNG_CHANNEL_USAGE 97 /* 11v channel usage */ ++#define DOT11_MNG_TIME_ZONE_ID 98 /* 11v time zone */ ++#define DOT11_MNG_LINK_IDENTIFIER_ID 101 /* 11z TDLS Link Identifier IE */ ++#define DOT11_MNG_WAKEUP_SCHEDULE_ID 102 /* 11z TDLS Wakeup Schedule IE */ ++#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID 104 /* 11z TDLS Channel Switch Timing IE */ ++#define DOT11_MNG_PTI_CONTROL_ID 105 /* 11z TDLS PTI Control IE */ ++#define DOT11_MNG_PU_BUFFER_STATUS_ID 106 /* 11z TDLS PU Buffer Status IE */ ++#define DOT11_MNG_INTERWORKING_ID 107 /* 11u interworking */ ++#define DOT11_MNG_ADVERTISEMENT_ID 108 /* 11u advertisement protocol */ ++#define DOT11_MNG_EXP_BW_REQ_ID 109 /* 11u expedited bandwith request */ ++#define DOT11_MNG_QOS_MAP_ID 110 /* 11u QoS map set */ ++#define DOT11_MNG_ROAM_CONSORT_ID 111 /* 11u roaming consortium */ ++#define DOT11_MNG_EMERGCY_ALERT_ID 112 /* 11u emergency alert identifier */ ++#define DOT11_MNG_EXT_CAP_ID 127 /* d11 mgmt ext capability */ ++#define DOT11_MNG_VHT_CAP_ID 191 /* d11 mgmt VHT cap id */ ++#define DOT11_MNG_VHT_OPERATION_ID 192 /* d11 mgmt VHT op id */ ++ ++#define DOT11_MNG_WPA_ID 221 /* d11 management WPA id */ ++#define DOT11_MNG_PROPR_ID 221 /* d11 management proprietary id */ ++/* should start using this one instead of above two */ ++#define DOT11_MNG_VS_ID 221 /* d11 management Vendor Specific IE */ ++ ++/* Rate element Basic flag and rate mask */ ++#define DOT11_RATE_BASIC 0x80 /* flag for a Basic Rate */ ++#define DOT11_RATE_MASK 0x7F /* mask for numeric part of rate */ ++ ++/* ERP info element bit values */ ++#define DOT11_MNG_ERP_LEN 1 /* ERP is currently 1 byte long */ ++#define DOT11_MNG_NONERP_PRESENT 0x01 /* NonERP (802.11b) STAs are present ++ *in the BSS ++ */ ++#define DOT11_MNG_USE_PROTECTION 0x02 /* Use protection mechanisms for ++ *ERP-OFDM frames ++ */ ++#define DOT11_MNG_BARKER_PREAMBLE 0x04 /* Short Preambles: 0 == allowed, ++ * 1 == not allowed ++ */ ++/* TS Delay element offset & size */ ++#define DOT11_MGN_TS_DELAY_LEN 4 /* length of TS DELAY IE */ ++#define TS_DELAY_FIELD_SIZE 4 /* TS DELAY field size */ ++ ++/* Capability Information Field */ ++#define DOT11_CAP_ESS 0x0001 /* d11 cap. ESS */ ++#define DOT11_CAP_IBSS 0x0002 /* d11 cap. IBSS */ ++#define DOT11_CAP_POLLABLE 0x0004 /* d11 cap. pollable */ ++#define DOT11_CAP_POLL_RQ 0x0008 /* d11 cap. poll request */ ++#define DOT11_CAP_PRIVACY 0x0010 /* d11 cap. privacy */ ++#define DOT11_CAP_SHORT 0x0020 /* d11 cap. short */ ++#define DOT11_CAP_PBCC 0x0040 /* d11 cap. PBCC */ ++#define DOT11_CAP_AGILITY 0x0080 /* d11 cap. agility */ ++#define DOT11_CAP_SPECTRUM 0x0100 /* d11 cap. spectrum */ ++#define DOT11_CAP_SHORTSLOT 0x0400 /* d11 cap. shortslot */ ++#define DOT11_CAP_RRM 0x1000 /* d11 cap. 11k radio measurement */ ++#define DOT11_CAP_CCK_OFDM 0x2000 /* d11 cap. CCK/OFDM */ ++ ++/* Extended capabilities IE bitfields */ ++/* 20/40 BSS Coexistence Management support bit position */ ++#define DOT11_EXT_CAP_OBSS_COEX_MGMT 0 ++/* scheduled PSMP support bit position */ ++#define DOT11_EXT_CAP_SPSMP 6 ++/* BSS Transition Management support bit position */ ++#define DOT11_EXT_CAP_BSS_TRANSITION_MGMT 19 ++/* Interworking support bit position */ ++#define DOT11_EXT_CAP_IW 31 ++/* service Interval granularity bit position and mask */ ++#define DOT11_EXT_CAP_SI 41 ++#define DOT11_EXT_CAP_SI_MASK 0x0E ++ ++/* ++ * Action Frame Constants ++ */ ++#define DOT11_ACTION_HDR_LEN 2 /* action frame category + action field */ ++#define DOT11_ACTION_CAT_OFF 0 /* category offset */ ++#define DOT11_ACTION_ACT_OFF 1 /* action offset */ ++ ++/* Action Category field (sec 7.3.1.11) */ ++#define DOT11_ACTION_CAT_ERR_MASK 0x80 /* category error mask */ ++#define DOT11_ACTION_CAT_MASK 0x7F /* category mask */ ++#define DOT11_ACTION_CAT_SPECT_MNG 0 /* category spectrum management */ ++#define DOT11_ACTION_CAT_QOS 1 /* category QoS */ ++#define DOT11_ACTION_CAT_DLS 2 /* category DLS */ ++#define DOT11_ACTION_CAT_BLOCKACK 3 /* category block ack */ ++#define DOT11_ACTION_CAT_PUBLIC 4 /* category public */ ++#define DOT11_ACTION_CAT_RRM 5 /* category radio measurements */ ++#define DOT11_ACTION_CAT_FBT 6 /* category fast bss transition */ ++#define DOT11_ACTION_CAT_HT 7 /* category for HT */ ++#define DOT11_ACTION_CAT_SA_QUERY 8 /* security association query */ ++#define DOT11_ACTION_CAT_PDPA 9 /* protected dual of public action */ ++#define DOT11_ACTION_CAT_BSSMGMT 10 /* category for BSS transition management */ ++#define DOT11_ACTION_NOTIFICATION 17 ++#define DOT11_ACTION_CAT_VSP 126 /* protected vendor specific */ ++#define DOT11_ACTION_CAT_VS 127 /* category Vendor Specific */ ++ ++/* Spectrum Management Action IDs (sec 7.4.1) */ ++#define DOT11_SM_ACTION_M_REQ 0 /* d11 action measurement request */ ++#define DOT11_SM_ACTION_M_REP 1 /* d11 action measurement response */ ++#define DOT11_SM_ACTION_TPC_REQ 2 /* d11 action TPC request */ ++#define DOT11_SM_ACTION_TPC_REP 3 /* d11 action TPC response */ ++#define DOT11_SM_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */ ++#define DOT11_SM_ACTION_EXT_CSA 5 /* d11 extened CSA for 11n */ ++ ++/* HT action ids */ ++#define DOT11_ACTION_ID_HT_CH_WIDTH 0 /* notify channel width action id */ ++#define DOT11_ACTION_ID_HT_MIMO_PS 1 /* mimo ps action id */ ++ ++/* Public action ids */ ++#define DOT11_PUB_ACTION_BSS_COEX_MNG 0 /* 20/40 Coexistence Management action id */ ++#define DOT11_PUB_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */ ++ ++/* Block Ack action types */ ++#define DOT11_BA_ACTION_ADDBA_REQ 0 /* ADDBA Req action frame type */ ++#define DOT11_BA_ACTION_ADDBA_RESP 1 /* ADDBA Resp action frame type */ ++#define DOT11_BA_ACTION_DELBA 2 /* DELBA action frame type */ ++ ++/* ADDBA action parameters */ ++#define DOT11_ADDBA_PARAM_AMSDU_SUP 0x0001 /* AMSDU supported under BA */ ++#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002 /* policy mask(ack vs delayed) */ ++#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1 /* policy shift */ ++#define DOT11_ADDBA_PARAM_TID_MASK 0x003c /* tid mask */ ++#define DOT11_ADDBA_PARAM_TID_SHIFT 2 /* tid shift */ ++#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0 /* buffer size mask */ ++#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6 /* buffer size shift */ ++ ++#define DOT11_ADDBA_POLICY_DELAYED 0 /* delayed BA policy */ ++#define DOT11_ADDBA_POLICY_IMMEDIATE 1 /* immediate BA policy */ ++ ++/* Fast Transition action types */ ++#define DOT11_FT_ACTION_FT_RESERVED 0 ++#define DOT11_FT_ACTION_FT_REQ 1 /* FBT request - for over-the-DS FBT */ ++#define DOT11_FT_ACTION_FT_RES 2 /* FBT response - for over-the-DS FBT */ ++#define DOT11_FT_ACTION_FT_CON 3 /* FBT confirm - for OTDS with RRP */ ++#define DOT11_FT_ACTION_FT_ACK 4 /* FBT ack */ ++ ++/* DLS action types */ ++#define DOT11_DLS_ACTION_REQ 0 /* DLS Request */ ++#define DOT11_DLS_ACTION_RESP 1 /* DLS Response */ ++#define DOT11_DLS_ACTION_TD 2 /* DLS Teardown */ ++ ++/* Wireless Network Management (WNM) action types */ ++#define DOT11_WNM_ACTION_EVENT_REQ 0 ++#define DOT11_WNM_ACTION_EVENT_REP 1 ++#define DOT11_WNM_ACTION_DIAG_REQ 2 ++#define DOT11_WNM_ACTION_DIAG_REP 3 ++#define DOT11_WNM_ACTION_LOC_CFG_REQ 4 ++#define DOT11_WNM_ACTION_LOC_RFG_RESP 5 ++#define DOT11_WNM_ACTION_BSS_TRANS_QURY 6 ++#define DOT11_WNM_ACTION_BSS_TRANS_REQ 7 ++#define DOT11_WNM_ACTION_BSS_TRANS_RESP 8 ++#define DOT11_WNM_ACTION_FMS_REQ 9 ++#define DOT11_WNM_ACTION_FMS_RESP 10 ++#define DOT11_WNM_ACTION_COL_INTRFRNCE_REQ 11 ++#define DOT11_WNM_ACTION_COL_INTRFRNCE_REP 12 ++#define DOT11_WNM_ACTION_TFS_REQ 13 ++#define DOT11_WNM_ACTION_TFS_RESP 14 ++#define DOT11_WNM_ACTION_TFS_NOTIFY 15 ++#define DOT11_WNM_ACTION_WNM_SLEEP_REQ 16 ++#define DOT11_WNM_ACTION_WNM_SLEEP_RESP 17 ++#define DOT11_WNM_ACTION_TIM_BCAST_REQ 18 ++#define DOT11_WNM_ACTION_TIM_BCAST_RESP 19 ++#define DOT11_WNM_ACTION_QOS_TRFC_CAP_UPD 20 ++#define DOT11_WNM_ACTION_CHAN_USAGE_REQ 21 ++#define DOT11_WNM_ACTION_CHAN_USAGE_RESP 22 ++#define DOT11_WNM_ACTION_DMS_REQ 23 ++#define DOT11_WNM_ACTION_DMS_RESP 24 ++#define DOT11_WNM_ACTION_TMNG_MEASUR_REQ 25 ++#define DOT11_WNM_ACTION_NOTFCTN_REQ 26 ++#define DOT11_WNM_ACTION_NOTFCTN_RES 27 ++ ++#define DOT11_MNG_COUNTRY_ID_LEN 3 ++ ++/* DLS Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_dls_req { ++ uint8 category; /* category of action frame (2) */ ++ uint8 action; /* DLS action: req (0) */ ++ struct ether_addr da; /* destination address */ ++ struct ether_addr sa; /* source address */ ++ uint16 cap; /* capability */ ++ uint16 timeout; /* timeout value */ ++ uint8 data[1]; /* IE:support rate, extend support rate, HT cap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_dls_req dot11_dls_req_t; ++#define DOT11_DLS_REQ_LEN 18 /* Fixed length */ ++ ++/* DLS response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_dls_resp { ++ uint8 category; /* category of action frame (2) */ ++ uint8 action; /* DLS action: req (0) */ ++ uint16 status; /* status code field */ ++ struct ether_addr da; /* destination address */ ++ struct ether_addr sa; /* source address */ ++ uint8 data[1]; /* optional: capability, rate ... */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_dls_resp dot11_dls_resp_t; ++#define DOT11_DLS_RESP_LEN 16 /* Fixed length */ ++ ++ ++/* BSS Management Transition Query frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_query { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_query (6) */ ++ uint8 token; /* dialog token */ ++ uint8 reason; /* transition query reason */ ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_query dot11_bss_trans_query_t; ++#define DOT11_BSS_TRANS_QUERY_LEN 4 /* Fixed length */ ++ ++/* BSS Management Transition Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_req { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_req (7) */ ++ uint8 token; /* dialog token */ ++ uint8 reqmode; /* transition request mode */ ++ uint16 disassoc_tmr; /* disassociation timer */ ++ uint8 validity_intrvl; /* validity interval */ ++ uint8 data[1]; /* optional: BSS term duration, ... */ ++ /* ...session info URL, list */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_req dot11_bss_trans_req_t; ++#define DOT11_BSS_TRANS_REQ_LEN 7 /* Fixed length */ ++ ++#define DOT11_BSS_TERM_DUR_LEN 12 /* Fixed length if present */ ++ ++ ++/* BSS Mgmt Transition Request Mode Field - 802.11v */ ++#define DOT11_BSS_TRNS_REQMODE_PREF_LIST_INCL 0x01 ++#define DOT11_BSS_TRNS_REQMODE_ABRIDGED 0x02 ++#define DOT11_BSS_TRNS_REQMODE_DISASSOC_IMMINENT 0x04 ++#define DOT11_BSS_TRNS_REQMODE_BSS_TERM_INCL 0x08 ++#define DOT11_BSS_TRNS_REQMODE_ESS_DISASSOC_IMNT 0x10 ++ ++ ++/* BSS Management transition response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_res { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_res (8) */ ++ uint8 token; /* dialog token */ ++ uint8 status; /* transition status */ ++ uint8 term_delay; /* validity interval */ ++ uint8 data[1]; /* optional: BSS term duration, ... */ ++ /* ...session info URL, list */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_res dot11_bss_trans_res_t; ++#define DOT11_BSS_TRANS_RES_LEN 5 /* Fixed length */ ++ ++/* BSS Mgmt Transition Response Status Field */ ++#define DOT11_BSS_TRNS_RES_STATUS_ACCEPT 0 ++#define DOT11_BSS_TRNS_RES_STATUS_REJECT 1 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_BCN 2 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_CAP 3 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_UNDESIRED 4 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_DELAY_REQ 5 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_BSS_LIST_PROVIDED 6 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_NO_SUITABLE_BSS 7 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_LEAVING_ESS 8 ++ ++ ++/* Neighbor Report BSSID Information Field */ ++#define DOT11_NBR_RPRT_BSSID_INFO_REACHABILTY 0x0003 ++#define DOT11_NBR_RPRT_BSSID_INFO_SEC 0x0004 ++#define DOT11_NBR_RPRT_BSSID_INFO_KEY_SCOPE 0x0008 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP 0x03f0 ++ ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_SPEC_MGMT 0x0010 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_QOS 0x0020 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_APSD 0x0040 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_RDIO_MSMT 0x0080 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_DEL_BA 0x0100 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_IMM_BA 0x0200 ++ ++/* Neighbor Report Subelements */ ++#define DOT11_NBR_RPRT_SUBELEM_BSS_CANDDT_PREF_ID 3 ++ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_addba_req { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba req */ ++ uint8 token; /* identifier */ ++ uint16 addba_param_set; /* parameter set */ ++ uint16 timeout; /* timeout in seconds */ ++ uint16 start_seqnum; /* starting sequence number */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_addba_req dot11_addba_req_t; ++#define DOT11_ADDBA_REQ_LEN 9 /* length of addba req frame */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_addba_resp { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba resp */ ++ uint8 token; /* identifier */ ++ uint16 status; /* status of add request */ ++ uint16 addba_param_set; /* negotiated parameter set */ ++ uint16 timeout; /* negotiated timeout in seconds */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_addba_resp dot11_addba_resp_t; ++#define DOT11_ADDBA_RESP_LEN 9 /* length of addba resp frame */ ++ ++/* DELBA action parameters */ ++#define DOT11_DELBA_PARAM_INIT_MASK 0x0800 /* initiator mask */ ++#define DOT11_DELBA_PARAM_INIT_SHIFT 11 /* initiator shift */ ++#define DOT11_DELBA_PARAM_TID_MASK 0xf000 /* tid mask */ ++#define DOT11_DELBA_PARAM_TID_SHIFT 12 /* tid shift */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_delba { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba req */ ++ uint16 delba_param_set; /* paarmeter set */ ++ uint16 reason; /* reason for dellba */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_delba dot11_delba_t; ++#define DOT11_DELBA_LEN 6 /* length of delba frame */ ++ ++/* SA Query action field value */ ++#define SA_QUERY_REQUEST 0 ++#define SA_QUERY_RESPONSE 1 ++ ++/* ************* 802.11r related definitions. ************* */ ++ ++/* Over-the-DS Fast Transition Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_req { ++ uint8 category; /* category of action frame (6) */ ++ uint8 action; /* action: ft req */ ++ uint8 sta_addr[ETHER_ADDR_LEN]; ++ uint8 tgt_ap_addr[ETHER_ADDR_LEN]; ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_req dot11_ft_req_t; ++#define DOT11_FT_REQ_FIXED_LEN 14 ++ ++/* Over-the-DS Fast Transition Response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_res { ++ uint8 category; /* category of action frame (6) */ ++ uint8 action; /* action: ft resp */ ++ uint8 sta_addr[ETHER_ADDR_LEN]; ++ uint8 tgt_ap_addr[ETHER_ADDR_LEN]; ++ uint16 status; /* status code */ ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_res dot11_ft_res_t; ++#define DOT11_FT_RES_FIXED_LEN 16 ++ ++ ++/* ************* 802.11k related definitions. ************* */ ++ ++/* Radio measurements enabled capability ie */ ++ ++#define DOT11_RRM_CAP_LEN 5 /* length of rrm cap bitmap */ ++BWL_PRE_PACKED_STRUCT struct dot11_rrm_cap_ie { ++ uint8 cap[DOT11_RRM_CAP_LEN]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rrm_cap_ie dot11_rrm_cap_ie_t; ++ ++/* Bitmap definitions for cap ie */ ++#define DOT11_RRM_CAP_LINK 0 ++#define DOT11_RRM_CAP_NEIGHBOR_REPORT 1 ++#define DOT11_RRM_CAP_PARALLEL 2 ++#define DOT11_RRM_CAP_REPEATED 3 ++#define DOT11_RRM_CAP_BCN_PASSIVE 4 ++#define DOT11_RRM_CAP_BCN_ACTIVE 5 ++#define DOT11_RRM_CAP_BCN_TABLE 6 ++#define DOT11_RRM_CAP_BCN_REP_COND 7 ++#define DOT11_RRM_CAP_AP_CHANREP 16 ++ ++ ++/* Operating Class (formerly "Regulatory Class") definitions */ ++#define DOT11_OP_CLASS_NONE 255 ++ ++ ++/* Radio Measurements action ids */ ++#define DOT11_RM_ACTION_RM_REQ 0 /* Radio measurement request */ ++#define DOT11_RM_ACTION_RM_REP 1 /* Radio measurement report */ ++#define DOT11_RM_ACTION_LM_REQ 2 /* Link measurement request */ ++#define DOT11_RM_ACTION_LM_REP 3 /* Link measurement report */ ++#define DOT11_RM_ACTION_NR_REQ 4 /* Neighbor report request */ ++#define DOT11_RM_ACTION_NR_REP 5 /* Neighbor report response */ ++ ++/* Generic radio measurement action frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_rm_action { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rm_action dot11_rm_action_t; ++#define DOT11_RM_ACTION_LEN 3 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmreq { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint16 reps; /* no. of repetitions */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmreq dot11_rmreq_t; ++#define DOT11_RMREQ_LEN 5 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rm_ie { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rm_ie dot11_rm_ie_t; ++#define DOT11_RM_IE_LEN 5 ++ ++/* Definitions for "mode" bits in rm req */ ++#define DOT11_RMREQ_MODE_PARALLEL 1 ++#define DOT11_RMREQ_MODE_ENABLE 2 ++#define DOT11_RMREQ_MODE_REQUEST 4 ++#define DOT11_RMREQ_MODE_REPORT 8 ++#define DOT11_RMREQ_MODE_DURMAND 0x10 /* Duration Mandatory */ ++ ++/* Definitions for "mode" bits in rm rep */ ++#define DOT11_RMREP_MODE_LATE 1 ++#define DOT11_RMREP_MODE_INCAPABLE 2 ++#define DOT11_RMREP_MODE_REFUSED 4 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmreq_bcn { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ uint8 reg; ++ uint8 channel; ++ uint16 interval; ++ uint16 duration; ++ uint8 bcn_mode; ++ struct ether_addr bssid; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmreq_bcn dot11_rmreq_bcn_t; ++#define DOT11_RMREQ_BCN_LEN 18 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmrep_bcn { ++ uint8 reg; ++ uint8 channel; ++ uint32 starttime[2]; ++ uint16 duration; ++ uint8 frame_info; ++ uint8 rcpi; ++ uint8 rsni; ++ struct ether_addr bssid; ++ uint8 antenna_id; ++ uint32 parent_tsf; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t; ++#define DOT11_RMREP_BCN_LEN 26 ++ ++/* Beacon request measurement mode */ ++#define DOT11_RMREQ_BCN_PASSIVE 0 ++#define DOT11_RMREQ_BCN_ACTIVE 1 ++#define DOT11_RMREQ_BCN_TABLE 2 ++ ++/* Sub-element IDs for Beacon Request */ ++#define DOT11_RMREQ_BCN_SSID_ID 0 ++#define DOT11_RMREQ_BCN_REPINFO_ID 1 ++#define DOT11_RMREQ_BCN_REPDET_ID 2 ++#define DOT11_RMREQ_BCN_REQUEST_ID 10 ++#define DOT11_RMREQ_BCN_APCHREP_ID 51 ++ ++/* Reporting Detail element definition */ ++#define DOT11_RMREQ_BCN_REPDET_FIXED 0 /* Fixed length fields only */ ++#define DOT11_RMREQ_BCN_REPDET_REQUEST 1 /* + requested information elems */ ++#define DOT11_RMREQ_BCN_REPDET_ALL 2 /* All fields */ ++ ++/* Sub-element IDs for Beacon Report */ ++#define DOT11_RMREP_BCN_FRM_BODY 1 ++ ++/* Neighbor measurement report */ ++BWL_PRE_PACKED_STRUCT struct dot11_rmrep_nbr { ++ struct ether_addr bssid; ++ uint32 bssid_info; ++ uint8 reg; ++ uint8 channel; ++ uint8 phytype; ++ uchar sub_elements[1]; /* Variable size data */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmrep_nbr dot11_rmrep_nbr_t; ++#define DOT11_RMREP_NBR_LEN 13 ++ ++/* MLME Enumerations */ ++#define DOT11_BSSTYPE_INFRASTRUCTURE 0 /* d11 infrastructure */ ++#define DOT11_BSSTYPE_INDEPENDENT 1 /* d11 independent */ ++#define DOT11_BSSTYPE_ANY 2 /* d11 any BSS type */ ++#define DOT11_SCANTYPE_ACTIVE 0 /* d11 scan active */ ++#define DOT11_SCANTYPE_PASSIVE 1 /* d11 scan passive */ ++ ++/* Link Measurement */ ++BWL_PRE_PACKED_STRUCT struct dot11_lmreq { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint8 txpwr; /* Transmit Power Used */ ++ uint8 maxtxpwr; /* Max Transmit Power */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_lmreq dot11_lmreq_t; ++#define DOT11_LMREQ_LEN 5 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_lmrep { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ dot11_tpc_rep_t tpc; /* TPC element */ ++ uint8 rxant; /* Receive Antenna ID */ ++ uint8 txant; /* Transmit Antenna ID */ ++ uint8 rcpi; /* RCPI */ ++ uint8 rsni; /* RSNI */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_lmrep dot11_lmrep_t; ++#define DOT11_LMREP_LEN 11 ++ ++/* 802.11 BRCM "Compromise" Pre N constants */ ++#define PREN_PREAMBLE 24 /* green field preamble time */ ++#define PREN_MM_EXT 12 /* extra mixed mode preamble time */ ++#define PREN_PREAMBLE_EXT 4 /* extra preamble (multiply by unique_streams-1) */ ++ ++/* 802.11N PHY constants */ ++#define RIFS_11N_TIME 2 /* NPHY RIFS time */ ++ ++/* 802.11 HT PLCP format 802.11n-2009, sec 20.3.9.4.3 ++ * HT-SIG is composed of two 24 bit parts, HT-SIG1 and HT-SIG2 ++ */ ++/* HT-SIG1 */ ++#define HT_SIG1_MCS_MASK 0x00007F ++#define HT_SIG1_CBW 0x000080 ++#define HT_SIG1_HT_LENGTH 0xFFFF00 ++ ++/* HT-SIG2 */ ++#define HT_SIG2_SMOOTHING 0x000001 ++#define HT_SIG2_NOT_SOUNDING 0x000002 ++#define HT_SIG2_RESERVED 0x000004 ++#define HT_SIG2_AGGREGATION 0x000008 ++#define HT_SIG2_STBC_MASK 0x000030 ++#define HT_SIG2_STBC_SHIFT 4 ++#define HT_SIG2_FEC_CODING 0x000040 ++#define HT_SIG2_SHORT_GI 0x000080 ++#define HT_SIG2_ESS_MASK 0x000300 ++#define HT_SIG2_ESS_SHIFT 8 ++#define HT_SIG2_CRC 0x03FC00 ++#define HT_SIG2_TAIL 0x1C0000 ++ ++/* 802.11 A PHY constants */ ++#define APHY_SLOT_TIME 9 /* APHY slot time */ ++#define APHY_SIFS_TIME 16 /* APHY SIFS time */ ++#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) /* APHY DIFS time */ ++#define APHY_PREAMBLE_TIME 16 /* APHY preamble time */ ++#define APHY_SIGNAL_TIME 4 /* APHY signal time */ ++#define APHY_SYMBOL_TIME 4 /* APHY symbol time */ ++#define APHY_SERVICE_NBITS 16 /* APHY service nbits */ ++#define APHY_TAIL_NBITS 6 /* APHY tail nbits */ ++#define APHY_CWMIN 15 /* APHY cwmin */ ++ ++/* 802.11 B PHY constants */ ++#define BPHY_SLOT_TIME 20 /* BPHY slot time */ ++#define BPHY_SIFS_TIME 10 /* BPHY SIFS time */ ++#define BPHY_DIFS_TIME 50 /* BPHY DIFS time */ ++#define BPHY_PLCP_TIME 192 /* BPHY PLCP time */ ++#define BPHY_PLCP_SHORT_TIME 96 /* BPHY PLCP short time */ ++#define BPHY_CWMIN 31 /* BPHY cwmin */ ++ ++/* 802.11 G constants */ ++#define DOT11_OFDM_SIGNAL_EXTENSION 6 /* d11 OFDM signal extension */ ++ ++#define PHY_CWMAX 1023 /* PHY cwmax */ ++ ++#define DOT11_MAXNUMFRAGS 16 /* max # fragments per MSDU */ ++ ++/* 802.11 AC (VHT) constants */ ++ ++typedef int vht_group_id_t; ++ ++/* for VHT-A1 */ ++/* SIG-A1 reserved bits */ ++#define VHT_SIGA1_CONST_MASK 0x800004 ++ ++#define VHT_SIGA1_20MHZ_VAL 0x000000 ++#define VHT_SIGA1_40MHZ_VAL 0x000001 ++#define VHT_SIGA1_80MHZ_VAL 0x000002 ++#define VHT_SIGA1_160MHZ_VAL 0x000003 ++ ++#define VHT_SIGA1_STBC 0x000008 ++ ++#define VHT_SIGA1_GID_MAX_GID 0x3f ++#define VHT_SIGA1_GID_SHIFT 4 ++#define VHT_SIGA1_GID_TO_AP 0x00 ++#define VHT_SIGA1_GID_NOT_TO_AP 0x3f ++ ++#define VHT_SIGA1_NSTS_SHIFT 10 ++#define VHT_SIGA1_NSTS_SHIFT_MASK_USER0 0x001C00 ++ ++#define VHT_SIGA1_PARTIAL_AID_SHIFT 13 ++ ++/* for VHT-A2 */ ++#define VHT_SIGA2_GI_NONE 0x000000 ++#define VHT_SIGA2_GI_SHORT 0x000001 ++#define VHT_SIGA2_GI_W_MOD10 0x000002 ++#define VHT_SIGA2_CODING_LDPC 0x000004 ++#define VHT_SIGA2_BEAMFORM_ENABLE 0x000100 ++#define VHT_SIGA2_MCS_SHIFT 4 ++ ++#define VHT_SIGA2_B9_RESERVED 0x000200 ++#define VHT_SIGA2_TAIL_MASK 0xfc0000 ++#define VHT_SIGA2_TAIL_VALUE 0x000000 ++ ++#define VHT_SIGA2_SVC_BITS 16 ++#define VHT_SIGA2_TAIL_BITS 6 ++ ++ ++/* dot11Counters Table - 802.11 spec., Annex D */ ++typedef struct d11cnt { ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++} d11cnt_t; ++ ++/* OUI for BRCM proprietary IE */ ++#define BRCM_PROP_OUI "\x00\x90\x4C" /* Broadcom proprietary OUI */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* The following BRCM_PROP_OUI types are currently in use (defined in ++ * relevant subsections). Each of them will be in a separate proprietary(221) IE ++ * #define SES_VNDR_IE_TYPE 1 (defined in src/ses/shared/ses.h) ++ * #define DPT_IE_TYPE 2 ++ * #define HT_CAP_IE_TYPE 51 ++ * #define HT_ADD_IE_TYPE 52 ++ * #define BRCM_EXTCH_IE_TYPE 53 ++ */ ++ ++/* Following is the generic structure for brcm_prop_ie (uses BRCM_PROP_OUI). ++ * DPT uses this format with type set to DPT_IE_TYPE ++ */ ++BWL_PRE_PACKED_STRUCT struct brcm_prop_ie_s { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type of this IE */ ++ uint16 cap; /* DPT capabilities */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct brcm_prop_ie_s brcm_prop_ie_t; ++ ++#define BRCM_PROP_IE_LEN 6 /* len of fixed part of brcm_prop ie */ ++ ++#define DPT_IE_TYPE 2 ++#define WET_TUNNEL_IE_TYPE 3 ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* BRCM OUI: Used in the proprietary(221) IE in all broadcom devices */ ++#define BRCM_OUI "\x00\x10\x18" /* Broadcom OUI */ ++ ++/* BRCM info element */ ++BWL_PRE_PACKED_STRUCT struct brcm_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_OUI */ ++ uint8 ver; /* type/ver of this IE */ ++ uint8 assoc; /* # of assoc STAs */ ++ uint8 flags; /* misc flags */ ++ uint8 flags1; /* misc flags */ ++ uint16 amsdu_mtu_pref; /* preferred A-MSDU MTU */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct brcm_ie brcm_ie_t; ++#define BRCM_IE_LEN 11 /* BRCM IE length */ ++#define BRCM_IE_VER 2 /* BRCM IE version */ ++#define BRCM_IE_LEGACY_AES_VER 1 /* BRCM IE legacy AES version */ ++ ++/* brcm_ie flags */ ++#define BRF_LZWDS 0x4 /* lazy wds enabled */ ++#define BRF_BLOCKACK 0x8 /* BlockACK capable */ ++ ++/* brcm_ie flags1 */ ++#define BRF1_AMSDU 0x1 /* A-MSDU capable */ ++#define BRF1_WMEPS 0x4 /* AP is capable of handling WME + PS w/o APSD */ ++#define BRF1_PSOFIX 0x8 /* AP has fixed PS mode out-of-order packets */ ++#define BRF1_RX_LARGE_AGG 0x10 /* device can rx large aggregates */ ++#define BRF1_RFAWARE_DCS 0x20 /* RFAWARE dynamic channel selection (DCS) */ ++#define BRF1_SOFTAP 0x40 /* Configure as Broadcom SOFTAP */ ++ ++/* Vendor IE structure */ ++BWL_PRE_PACKED_STRUCT struct vndr_ie { ++ uchar id; ++ uchar len; ++ uchar oui [3]; ++ uchar data [1]; /* Variable size data */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct vndr_ie vndr_ie_t; ++ ++#define VNDR_IE_HDR_LEN 2 /* id + len field */ ++#define VNDR_IE_MIN_LEN 3 /* size of the oui field */ ++#define VNDR_IE_MAX_LEN 256 /* verdor IE max length */ ++ ++/* ************* HT definitions. ************* */ ++#define MCSSET_LEN 16 /* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */ ++#define MAX_MCS_NUM (128) /* max mcs number = 128 */ ++ ++BWL_PRE_PACKED_STRUCT struct ht_cap_ie { ++ uint16 cap; ++ uint8 params; ++ uint8 supp_mcs[MCSSET_LEN]; ++ uint16 ext_htcap; ++ uint32 txbf_cap; ++ uint8 as_cap; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_cap_ie ht_cap_ie_t; ++ ++/* CAP IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ ++/* the capability IE is primarily used to convey this nodes abilities */ ++BWL_PRE_PACKED_STRUCT struct ht_prop_cap_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type inidicates what follows */ ++ ht_cap_ie_t cap_ie; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_prop_cap_ie ht_prop_cap_ie_t; ++ ++#define HT_PROP_IE_OVERHEAD 4 /* overhead bytes for prop oui ie */ ++#define HT_CAP_IE_LEN 26 /* HT capability len (based on .11n d2.0) */ ++#define HT_CAP_IE_TYPE 51 ++ ++#define HT_CAP_LDPC_CODING 0x0001 /* Support for rx of LDPC coded pkts */ ++#define HT_CAP_40MHZ 0x0002 /* FALSE:20Mhz, TRUE:20/40MHZ supported */ ++#define HT_CAP_MIMO_PS_MASK 0x000C /* Mimo PS mask */ ++#define HT_CAP_MIMO_PS_SHIFT 0x0002 /* Mimo PS shift */ ++#define HT_CAP_MIMO_PS_OFF 0x0003 /* Mimo PS, no restriction */ ++#define HT_CAP_MIMO_PS_RTS 0x0001 /* Mimo PS, send RTS/CTS around MIMO frames */ ++#define HT_CAP_MIMO_PS_ON 0x0000 /* Mimo PS, MIMO disallowed */ ++#define HT_CAP_GF 0x0010 /* Greenfield preamble support */ ++#define HT_CAP_SHORT_GI_20 0x0020 /* 20MHZ short guard interval support */ ++#define HT_CAP_SHORT_GI_40 0x0040 /* 40Mhz short guard interval support */ ++#define HT_CAP_TX_STBC 0x0080 /* Tx STBC support */ ++#define HT_CAP_RX_STBC_MASK 0x0300 /* Rx STBC mask */ ++#define HT_CAP_RX_STBC_SHIFT 8 /* Rx STBC shift */ ++#define HT_CAP_DELAYED_BA 0x0400 /* delayed BA support */ ++#define HT_CAP_MAX_AMSDU 0x0800 /* Max AMSDU size in bytes , 0=3839, 1=7935 */ ++ ++#define HT_CAP_DSSS_CCK 0x1000 /* DSSS/CCK supported by the BSS */ ++#define HT_CAP_PSMP 0x2000 /* Power Save Multi Poll support */ ++#define HT_CAP_40MHZ_INTOLERANT 0x4000 /* 40MHz Intolerant */ ++#define HT_CAP_LSIG_TXOP 0x8000 /* L-SIG TXOP protection support */ ++ ++#define HT_CAP_RX_STBC_NO 0x0 /* no rx STBC support */ ++#define HT_CAP_RX_STBC_ONE_STREAM 0x1 /* rx STBC support of 1 spatial stream */ ++#define HT_CAP_RX_STBC_TWO_STREAM 0x2 /* rx STBC support of 1-2 spatial streams */ ++#define HT_CAP_RX_STBC_THREE_STREAM 0x3 /* rx STBC support of 1-3 spatial streams */ ++ ++#define VHT_MAX_MPDU 11454 /* max mpdu size for now (bytes) */ ++#define VHT_MPDU_MSDU_DELTA 56 /* Difference in spec - vht mpdu, amsdu len */ ++/* Max AMSDU len - per spec */ ++#define VHT_MAX_AMSDU (VHT_MAX_MPDU - VHT_MPDU_MSDU_DELTA) ++ ++#define HT_MAX_AMSDU 7935 /* max amsdu size (bytes) per the HT spec */ ++#define HT_MIN_AMSDU 3835 /* min amsdu size (bytes) per the HT spec */ ++ ++#define HT_PARAMS_RX_FACTOR_MASK 0x03 /* ampdu rcv factor mask */ ++#define HT_PARAMS_DENSITY_MASK 0x1C /* ampdu density mask */ ++#define HT_PARAMS_DENSITY_SHIFT 2 /* ampdu density shift */ ++ ++/* HT/AMPDU specific define */ ++#define AMPDU_MAX_MPDU_DENSITY 7 /* max mpdu density; in 1/8 usec units */ ++#define AMPDU_RX_FACTOR_8K 0 /* max rcv ampdu len (8kb) */ ++#define AMPDU_RX_FACTOR_16K 1 /* max rcv ampdu len (16kb) */ ++#define AMPDU_RX_FACTOR_32K 2 /* max rcv ampdu len (32kb) */ ++#define AMPDU_RX_FACTOR_64K 3 /* max rcv ampdu len (64kb) */ ++#define AMPDU_RX_FACTOR_BASE 8*1024 /* ampdu factor base for rx len */ ++ ++#define AMPDU_DELIMITER_LEN 4 /* length of ampdu delimiter */ ++#define AMPDU_DELIMITER_LEN_MAX 63 /* max length of ampdu delimiter(enforced in HW) */ ++ ++#define HT_CAP_EXT_PCO 0x0001 ++#define HT_CAP_EXT_PCO_TTIME_MASK 0x0006 ++#define HT_CAP_EXT_PCO_TTIME_SHIFT 1 ++#define HT_CAP_EXT_MCS_FEEDBACK_MASK 0x0300 ++#define HT_CAP_EXT_MCS_FEEDBACK_SHIFT 8 ++#define HT_CAP_EXT_HTC 0x0400 ++#define HT_CAP_EXT_RD_RESP 0x0800 ++ ++BWL_PRE_PACKED_STRUCT struct ht_add_ie { ++ uint8 ctl_ch; /* control channel number */ ++ uint8 byte1; /* ext ch,rec. ch. width, RIFS support */ ++ uint16 opmode; /* operation mode */ ++ uint16 misc_bits; /* misc bits */ ++ uint8 basic_mcs[MCSSET_LEN]; /* required MCS set */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_add_ie ht_add_ie_t; ++ ++/* ADD IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ ++/* the additional IE is primarily used to convey the current BSS configuration */ ++BWL_PRE_PACKED_STRUCT struct ht_prop_add_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* indicates what follows */ ++ ht_add_ie_t add_ie; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_prop_add_ie ht_prop_add_ie_t; ++ ++#define HT_ADD_IE_LEN 22 ++#define HT_ADD_IE_TYPE 52 ++ ++/* byte1 defn's */ ++#define HT_BW_ANY 0x04 /* set, STA can use 20 or 40MHz */ ++#define HT_RIFS_PERMITTED 0x08 /* RIFS allowed */ ++ ++/* opmode defn's */ ++#define HT_OPMODE_MASK 0x0003 /* protection mode mask */ ++#define HT_OPMODE_SHIFT 0 /* protection mode shift */ ++#define HT_OPMODE_PURE 0x0000 /* protection mode PURE */ ++#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ ++#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ ++#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ ++#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */ ++#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ ++#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ ++ ++/* misc_bites defn's */ ++#define HT_BASIC_STBC_MCS 0x007f /* basic STBC MCS */ ++#define HT_DUAL_STBC_PROT 0x0080 /* Dual STBC Protection */ ++#define HT_SECOND_BCN 0x0100 /* Secondary beacon support */ ++#define HT_LSIG_TXOP 0x0200 /* L-SIG TXOP Protection full support */ ++#define HT_PCO_ACTIVE 0x0400 /* PCO active */ ++#define HT_PCO_PHASE 0x0800 /* PCO phase */ ++#define HT_DUALCTS_PROTECTION 0x0080 /* DUAL CTS protection needed */ ++ ++/* Tx Burst Limits */ ++#define DOT11N_2G_TXBURST_LIMIT 6160 /* 2G band Tx burst limit per 802.11n Draft 1.10 (usec) */ ++#define DOT11N_5G_TXBURST_LIMIT 3080 /* 5G band Tx burst limit per 802.11n Draft 1.10 (usec) */ ++ ++/* Macros for opmode */ ++#define GET_HT_OPMODE(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ >> HT_OPMODE_SHIFT) ++#define HT_MIXEDMODE_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_MIXED) /* mixed mode present */ ++#define HT_HT20_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_HT20IN40) /* 20MHz HT present */ ++#define HT_OPTIONAL_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_OPTIONAL) /* Optional protection present */ ++#define HT_USE_PROTECTION(add_ie) (HT_HT20_PRESENT((add_ie)) || \ ++ HT_MIXEDMODE_PRESENT((add_ie))) /* use protection */ ++#define HT_NONGF_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_NONGF) \ ++ == HT_OPMODE_NONGF) /* non-GF present */ ++#define DOT11N_TXBURST_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \ ++ == DOT11N_TXBURST) /* Tx Burst present */ ++#define DOT11N_OBSS_NONHT_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \ ++ == DOT11N_OBSS_NONHT) /* OBSS Non-HT present */ ++ ++BWL_PRE_PACKED_STRUCT struct obss_params { ++ uint16 passive_dwell; ++ uint16 active_dwell; ++ uint16 bss_widthscan_interval; ++ uint16 passive_total; ++ uint16 active_total; ++ uint16 chanwidth_transition_dly; ++ uint16 activity_threshold; ++} BWL_POST_PACKED_STRUCT; ++typedef struct obss_params obss_params_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_ie { ++ uint8 id; ++ uint8 len; ++ obss_params_t obss_params; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_ie dot11_obss_ie_t; ++#define DOT11_OBSS_SCAN_IE_LEN sizeof(obss_params_t) /* HT OBSS len (based on 802.11n d3.0) */ ++ ++/* HT control field */ ++#define HT_CTRL_LA_TRQ 0x00000002 /* sounding request */ ++#define HT_CTRL_LA_MAI 0x0000003C /* MCS request or antenna selection indication */ ++#define HT_CTRL_LA_MAI_SHIFT 2 ++#define HT_CTRL_LA_MAI_MRQ 0x00000004 /* MCS request */ ++#define HT_CTRL_LA_MAI_MSI 0x00000038 /* MCS request sequence identifier */ ++#define HT_CTRL_LA_MFSI 0x000001C0 /* MFB sequence identifier */ ++#define HT_CTRL_LA_MFSI_SHIFT 6 ++#define HT_CTRL_LA_MFB_ASELC 0x0000FE00 /* MCS feedback, antenna selection command/data */ ++#define HT_CTRL_LA_MFB_ASELC_SH 9 ++#define HT_CTRL_LA_ASELC_CMD 0x00000C00 /* ASEL command */ ++#define HT_CTRL_LA_ASELC_DATA 0x0000F000 /* ASEL data */ ++#define HT_CTRL_CAL_POS 0x00030000 /* Calibration position */ ++#define HT_CTRL_CAL_SEQ 0x000C0000 /* Calibration sequence */ ++#define HT_CTRL_CSI_STEERING 0x00C00000 /* CSI/Steering */ ++#define HT_CTRL_CSI_STEER_SHIFT 22 ++#define HT_CTRL_CSI_STEER_NFB 0 /* no fedback required */ ++#define HT_CTRL_CSI_STEER_CSI 1 /* CSI, H matrix */ ++#define HT_CTRL_CSI_STEER_NCOM 2 /* non-compressed beamforming */ ++#define HT_CTRL_CSI_STEER_COM 3 /* compressed beamforming */ ++#define HT_CTRL_NDP_ANNOUNCE 0x01000000 /* NDP announcement */ ++#define HT_CTRL_AC_CONSTRAINT 0x40000000 /* AC Constraint */ ++#define HT_CTRL_RDG_MOREPPDU 0x80000000 /* RDG/More PPDU */ ++ ++#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ ++#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ ++#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ ++#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */ ++#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ ++#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ ++ ++/* ************* VHT definitions. ************* */ ++ ++BWL_PRE_PACKED_STRUCT struct vht_cap_ie { ++ uint32 vht_cap_info; ++ /* supported MCS set - 64 bit field */ ++ uint16 rx_mcs_map; ++ uint16 rx_max_rate; ++ uint16 tx_mcs_map; ++ uint16 tx_max_rate; ++} BWL_POST_PACKED_STRUCT; ++typedef struct vht_cap_ie vht_cap_ie_t; ++/* 4B cap_info + 8B supp_mcs */ ++#define VHT_CAP_IE_LEN 12 ++/* 32bit - cap info */ ++#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK 0x00000003 ++#define VHT_CAP_INFO_SUPP_CHAN_WIDTH_MASK 0x0000000c ++#define VHT_CAP_INFO_LDPC 0x00000010 ++#define VHT_CAP_INFO_SGI_80MHZ 0x00000020 ++#define VHT_CAP_INFO_SGI_160MHZ 0x00000040 ++#define VHT_CAP_INFO_TX_STBC 0x00000080 ++#define VHT_CAP_INFO_RX_STBC 0x00000700 ++ ++#define VHT_CAP_INFO_RX_STBC_MASK 0x00000700 ++#define VHT_CAP_INFO_RX_STBC_SHIFT 8 ++#define VHT_CAP_INFO_SU_BEAMFMR 0x00000800 ++#define VHT_CAP_INFO_SU_BEAMFMEE 0x00001000 ++#define VHT_CAP_INFO_NUM_BMFMR_ANT_MASK 0x0000e000 ++#define VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT 13 ++ ++#define VHT_CAP_INFO_NUM_SOUNDING_DIM_MASK 0x00070000 ++#define VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT 16 ++#define VHT_CAP_INFO_MU_BEAMFMR 0x00080000 ++#define VHT_CAP_INFO_MU_BEAMFMEE 0x00100000 ++#define VHT_CAP_INFO_TXOPPS 0x00200000 ++#define VHT_CAP_INFO_HTCVHT 0x00400000 ++#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_MASK 0x03800000 ++#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT 23 ++ ++#define VHT_CAP_INFO_LINK_ADAPT_CAP_MASK 0x0c000000 ++#define VHT_CAP_INFO_LINK_ADAPT_CAP_SHIFT 26 ++ ++/* 64-bit Supp MCS. */ ++#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK 0x1fff ++#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT 0 ++ ++#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_MASK 0x1fff ++#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_SHIFT 0 ++ ++#define VHT_CAP_MCS_MAP_0_7 0 ++#define VHT_CAP_MCS_MAP_0_8 1 ++#define VHT_CAP_MCS_MAP_0_9 2 ++#define VHT_CAP_MCS_MAP_NONE 3 ++ ++#define VHT_CAP_MCS_MAP_NSS_MAX 8 ++ ++/* VHT Capabilities Supported Channel Width */ ++typedef enum vht_cap_chan_width { ++ VHT_CAP_CHAN_WIDTH_20_40 = 0x00, ++ VHT_CAP_CHAN_WIDTH_80 = 0x04, ++ VHT_CAP_CHAN_WIDTH_160 = 0x08 ++} vht_cap_chan_width_t; ++ ++/* VHT Capabilities Supported max MPDU LEN */ ++typedef enum vht_cap_max_mpdu_len { ++ VHT_CAP_MPDU_MAX_4K = 0x00, ++ VHT_CAP_MPDU_MAX_8K = 0x01, ++ VHT_CAP_MPDU_MAX_11K = 0x02 ++} vht_cap_max_mpdu_len_t; ++ ++/* VHT Operation Element */ ++BWL_PRE_PACKED_STRUCT struct vht_op_ie { ++ uint8 chan_width; ++ uint8 chan1; ++ uint8 chan2; ++ uint16 supp_mcs; /* same def as above in vht cap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct vht_op_ie vht_op_ie_t; ++/* 3B VHT Op info + 2B Basic MCS */ ++#define VHT_OP_IE_LEN 5 ++ ++typedef enum vht_op_chan_width { ++ VHT_OP_CHAN_WIDTH_20_40 = 0, ++ VHT_OP_CHAN_WIDTH_80 = 1, ++ VHT_OP_CHAN_WIDTH_160 = 2, ++ VHT_OP_CHAN_WIDTH_80_80 = 3 ++} vht_op_chan_width_t; ++ ++/* Def for rx & tx basic mcs maps - ea ss num has 2 bits of info */ ++#define VHT_MCS_MAP_GET_SS_IDX(nss) (((nss)-1)*2) ++#define VHT_MCS_MAP_GET_MCS_PER_SS(nss, mcsMap) \ ++ (((mcsMap) >> VHT_MCS_MAP_GET_SS_IDX(nss)) & 0x3) ++#define VHT_MCS_MAP_SET_MCS_PER_SS(nss, numMcs, mcsMap) \ ++ ((mcsMap) |= (((numMcs) & 0x3) << VHT_MCS_MAP_GET_SS_IDX(nss))) ++ ++/* ************* WPA definitions. ************* */ ++#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ ++#define WPA_OUI_LEN 3 /* WPA OUI length */ ++#define WPA_OUI_TYPE 1 ++#define WPA_VERSION 1 /* WPA version */ ++#define WPA2_OUI "\x00\x0F\xAC" /* WPA2 OUI */ ++#define WPA2_OUI_LEN 3 /* WPA2 OUI length */ ++#define WPA2_VERSION 1 /* WPA2 version */ ++#define WPA2_VERSION_LEN 2 /* WAP2 version length */ ++ ++/* ************* WPS definitions. ************* */ ++#define WPS_OUI "\x00\x50\xF2" /* WPS OUI */ ++#define WPS_OUI_LEN 3 /* WPS OUI length */ ++#define WPS_OUI_TYPE 4 ++ ++/* ************* WFA definitions. ************* */ ++#if defined(MACOSX) ++#define MAC_OUI "\x00\x17\xF2" /* MACOSX OUI */ ++#define MAC_OUI_TYPE_P2P 5 ++#endif /* MACOSX */ ++ ++#if defined(MACOSX) && !defined(WLP2P_NEW_WFA_OUI) ++#define WFA_OUI WPS_OUI /* WFA OUI */ ++#else ++#ifdef P2P_IE_OVRD ++#define WFA_OUI MAC_OUI ++#else ++#define WFA_OUI "\x50\x6F\x9A" /* WFA OUI */ ++#endif /* P2P_IE_OVRD */ ++#endif /* MACOSX && !WLP2P_NEW_WFA_OUI */ ++#define WFA_OUI_LEN 3 /* WFA OUI length */ ++#ifdef P2P_IE_OVRD ++#define WFA_OUI_TYPE_P2P MAC_OUI_TYPE_P2P ++#else ++#define WFA_OUI_TYPE_P2P 9 ++#endif ++ ++#define WFA_OUI_TYPE_TPC 8 ++ ++/* RSN authenticated key managment suite */ ++#define RSN_AKM_NONE 0 /* None (IBSS) */ ++#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */ ++#define RSN_AKM_PSK 2 /* Pre-shared Key */ ++#define RSN_AKM_FBT_1X 3 /* Fast Bss transition using 802.1X */ ++#define RSN_AKM_FBT_PSK 4 /* Fast Bss transition using Pre-shared Key */ ++#define RSN_AKM_MFP_1X 5 /* SHA256 key derivation, using 802.1X */ ++#define RSN_AKM_MFP_PSK 6 /* SHA256 key derivation, using Pre-shared Key */ ++#define RSN_AKM_TPK 7 /* TPK(TDLS Peer Key) handshake */ ++ ++/* Key related defines */ ++#define DOT11_MAX_DEFAULT_KEYS 4 /* number of default keys */ ++#define DOT11_MAX_KEY_SIZE 32 /* max size of any key */ ++#define DOT11_MAX_IV_SIZE 16 /* max size of any IV */ ++#define DOT11_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */ ++#define DOT11_WPA_KEY_RSC_LEN 8 /* WPA RSC key len */ ++ ++#define WEP1_KEY_SIZE 5 /* max size of any WEP key */ ++#define WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */ ++#define WEP128_KEY_SIZE 13 /* max size of any WEP key */ ++#define WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */ ++#define TKIP_MIC_SIZE 8 /* size of TKIP MIC */ ++#define TKIP_EOM_SIZE 7 /* max size of TKIP EOM */ ++#define TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */ ++#define TKIP_KEY_SIZE 32 /* size of any TKIP key */ ++#define TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */ ++#define TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */ ++#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX /* offset to Supplicant MIC RX key */ ++#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX /* offset to Supplicant MIC TX key */ ++#define AES_KEY_SIZE 16 /* size of AES key */ ++#define AES_MIC_SIZE 8 /* size of AES MIC */ ++#define BIP_KEY_SIZE 16 /* size of BIP key */ ++ ++/* WCN */ ++#define WCN_OUI "\x00\x50\xf2" /* WCN OUI */ ++#define WCN_TYPE 4 /* WCN type */ ++ ++ ++/* 802.11r protocol definitions */ ++ ++/* Mobility Domain IE */ ++BWL_PRE_PACKED_STRUCT struct dot11_mdid_ie { ++ uint8 id; ++ uint8 len; ++ uint16 mdid; /* Mobility Domain Id */ ++ uint8 cap; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_mdid_ie dot11_mdid_ie_t; ++ ++#define FBT_MDID_CAP_OVERDS 0x01 /* Fast Bss transition over the DS support */ ++#define FBT_MDID_CAP_RRP 0x02 /* Resource request protocol support */ ++ ++/* Fast Bss Transition IE */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_ie { ++ uint8 id; ++ uint8 len; ++ uint16 mic_control; /* Mic Control */ ++ uint8 mic[16]; ++ uint8 anonce[32]; ++ uint8 snonce[32]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_ie dot11_ft_ie_t; ++ ++#define TIE_TYPE_RESERVED 0 ++#define TIE_TYPE_REASSOC_DEADLINE 1 ++#define TIE_TYPE_KEY_LIEFTIME 2 ++#define TIE_TYPE_ASSOC_COMEBACK 3 ++BWL_PRE_PACKED_STRUCT struct dot11_timeout_ie { ++ uint8 id; ++ uint8 len; ++ uint8 type; /* timeout interval type */ ++ uint32 value; /* timeout interval value */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_timeout_ie dot11_timeout_ie_t; ++ ++/* GTK ie */ ++BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie { ++ uint8 id; ++ uint8 len; ++ uint16 key_info; ++ uint8 key_len; ++ uint8 rsc[8]; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_gtk_ie dot11_gtk_ie_t; ++ ++#define BSSID_INVALID "\x00\x00\x00\x00\x00\x00" ++#define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF" ++ ++ ++/* ************* WMM Parameter definitions. ************* */ ++#define WMM_OUI "\x00\x50\xF2" /* WNN OUI */ ++#define WMM_OUI_LEN 3 /* WMM OUI length */ ++#define WMM_OUI_TYPE 2 /* WMM OUT type */ ++#define WMM_VERSION 1 ++#define WMM_VERSION_LEN 1 ++ ++/* WMM OUI subtype */ ++#define WMM_OUI_SUBTYPE_PARAMETER 1 ++#define WMM_PARAMETER_IE_LEN 24 ++ ++/* Link Identifier Element */ ++BWL_PRE_PACKED_STRUCT struct link_id_ie { ++ uint8 id; ++ uint8 len; ++ struct ether_addr bssid; ++ struct ether_addr tdls_init_mac; ++ struct ether_addr tdls_resp_mac; ++} BWL_POST_PACKED_STRUCT; ++typedef struct link_id_ie link_id_ie_t; ++#define TDLS_LINK_ID_IE_LEN 18 ++ ++/* Link Wakeup Schedule Element */ ++BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie { ++ uint8 id; ++ uint8 len; ++ uint32 offset; /* in ms between TSF0 and start of 1st Awake Window */ ++ uint32 interval; /* in ms bwtween the start of 2 Awake Windows */ ++ uint32 awake_win_slots; /* in backof slots, duration of Awake Window */ ++ uint32 max_wake_win; /* in ms, max duration of Awake Window */ ++ uint16 idle_cnt; /* number of consecutive Awake Windows */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wakeup_sch_ie wakeup_sch_ie_t; ++#define TDLS_WAKEUP_SCH_IE_LEN 18 ++ ++/* Channel Switch Timing Element */ ++BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie { ++ uint8 id; ++ uint8 len; ++ uint16 switch_time; /* in ms, time to switch channels */ ++ uint16 switch_timeout; /* in ms */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct channel_switch_timing_ie channel_switch_timing_ie_t; ++#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN 4 ++ ++/* PTI Control Element */ ++BWL_PRE_PACKED_STRUCT struct pti_control_ie { ++ uint8 id; ++ uint8 len; ++ uint8 tid; ++ uint16 seq_control; ++} BWL_POST_PACKED_STRUCT; ++typedef struct pti_control_ie pti_control_ie_t; ++#define TDLS_PTI_CONTROL_IE_LEN 3 ++ ++/* PU Buffer Status Element */ ++BWL_PRE_PACKED_STRUCT struct pu_buffer_status_ie { ++ uint8 id; ++ uint8 len; ++ uint8 status; ++} BWL_POST_PACKED_STRUCT; ++typedef struct pu_buffer_status_ie pu_buffer_status_ie_t; ++#define TDLS_PU_BUFFER_STATUS_IE_LEN 1 ++#define TDLS_PU_BUFFER_STATUS_AC_BK 1 ++#define TDLS_PU_BUFFER_STATUS_AC_BE 2 ++#define TDLS_PU_BUFFER_STATUS_AC_VI 4 ++#define TDLS_PU_BUFFER_STATUS_AC_VO 8 ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _802_11_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/802.1d.h b/drivers/bcmdrivers/gmac/src/include/proto/802.1d.h +new file mode 100755 +index 0000000..3749214 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/802.1d.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental types and constants relating to 802.1D ++ * ++ * $Id: 802.1d.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _802_1_D_ ++#define _802_1_D_ ++ ++/* 802.1D priority defines */ ++#define PRIO_8021D_NONE 2 /* None = - */ ++#define PRIO_8021D_BK 1 /* BK - Background */ ++#define PRIO_8021D_BE 0 /* BE - Best-effort */ ++#define PRIO_8021D_EE 3 /* EE - Excellent-effort */ ++#define PRIO_8021D_CL 4 /* CL - Controlled Load */ ++#define PRIO_8021D_VI 5 /* Vi - Video */ ++#define PRIO_8021D_VO 6 /* Vo - Voice */ ++#define PRIO_8021D_NC 7 /* NC - Network Control */ ++#define MAXPRIO 7 /* 0-7 */ ++#define NUMPRIO (MAXPRIO + 1) ++ ++#define ALLPRIO -1 /* All prioirty */ ++ ++/* Converts prio to precedence since the numerical value of ++ * PRIO_8021D_BE and PRIO_8021D_NONE are swapped. ++ */ ++#define PRIO2PREC(prio) \ ++ (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio)) ++ ++#endif /* _802_1_D__ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/BOM b/drivers/bcmdrivers/gmac/src/include/proto/BOM +new file mode 100755 +index 0000000..98c6e5d +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/BOM +@@ -0,0 +1,4 @@ ++# Created by mkbom ++# $Id: BOM,v 9.0 1998-07-30 23:19:02 $ ++ ++File 1.46 vip.h +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/Makefile b/drivers/bcmdrivers/gmac/src/include/proto/Makefile +new file mode 100755 +index 0000000..533b7c4 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/Makefile +@@ -0,0 +1,9 @@ ++# ++# include/proto/Makefile ++# ++# Copyright 2006, Broadcom, Inc. ++# ++# $Id: Makefile 241182 2011-02-17 21:50:03Z $ ++# ++ ++# build etags +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/bcmeth.h b/drivers/bcmdrivers/gmac/src/include/proto/bcmeth.h +new file mode 100755 +index 0000000..f3aede9 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/bcmeth.h +@@ -0,0 +1,106 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Ethernettype protocol definitions ++ * ++ * $Id: bcmeth.h 294352 2011-11-06 19:23:00Z $ ++ */ ++ ++/* ++ * Broadcom Ethernet protocol defines ++ */ ++ ++#ifndef _BCMETH_H_ ++#define _BCMETH_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++/* ETHER_TYPE_BRCM is defined in ethernet.h */ ++ ++/* ++ * Following the 2byte BRCM ether_type is a 16bit BRCM subtype field ++ * in one of two formats: (only subtypes 32768-65535 are in use now) ++ * ++ * subtypes 0-32767: ++ * 8 bit subtype (0-127) ++ * 8 bit length in bytes (0-255) ++ * ++ * subtypes 32768-65535: ++ * 16 bit big-endian subtype ++ * 16 bit big-endian length in bytes (0-65535) ++ * ++ * length is the number of additional bytes beyond the 4 or 6 byte header ++ * ++ * Reserved values: ++ * 0 reserved ++ * 5-15 reserved for iLine protocol assignments ++ * 17-126 reserved, assignable ++ * 127 reserved ++ * 32768 reserved ++ * 32769-65534 reserved, assignable ++ * 65535 reserved ++ */ ++ ++/* ++ * While adding the subtypes and their specific processing code make sure ++ * bcmeth_bcm_hdr_t is the first data structure in the user specific data structure definition ++ */ ++ ++#define BCMILCP_SUBTYPE_RATE 1 ++#define BCMILCP_SUBTYPE_LINK 2 ++#define BCMILCP_SUBTYPE_CSA 3 ++#define BCMILCP_SUBTYPE_LARQ 4 ++#define BCMILCP_SUBTYPE_VENDOR 5 ++#define BCMILCP_SUBTYPE_FLH 17 ++ ++#define BCMILCP_SUBTYPE_VENDOR_LONG 32769 ++#define BCMILCP_SUBTYPE_CERT 32770 ++#define BCMILCP_SUBTYPE_SES 32771 ++ ++ ++#define BCMILCP_BCM_SUBTYPE_RESERVED 0 ++#define BCMILCP_BCM_SUBTYPE_EVENT 1 ++#define BCMILCP_BCM_SUBTYPE_SES 2 ++/* ++ * The EAPOL type is not used anymore. Instead EAPOL messages are now embedded ++ * within BCMILCP_BCM_SUBTYPE_EVENT type messages ++ */ ++/* #define BCMILCP_BCM_SUBTYPE_EAPOL 3 */ ++#define BCMILCP_BCM_SUBTYPE_DPT 4 ++ ++#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8 ++#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0 ++ ++/* These fields are stored in network order */ ++typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr ++{ ++ uint16 subtype; /* Vendor specific..32769 */ ++ uint16 length; ++ uint8 version; /* Version is 0 */ ++ uint8 oui[3]; /* Broadcom OUI */ ++ /* user specific Data */ ++ uint16 usr_subtype; ++} BWL_POST_PACKED_STRUCT bcmeth_hdr_t; ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _BCMETH_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/bcmevent.h b/drivers/bcmdrivers/gmac/src/include/proto/bcmevent.h +new file mode 100755 +index 0000000..57776ae +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/bcmevent.h +@@ -0,0 +1,313 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Event protocol definitions ++ * ++ * Dependencies: proto/bcmeth.h ++ * ++ * $Id: bcmevent.h 315348 2012-02-16 07:32:51Z $ ++ * ++ */ ++ ++/* ++ * Broadcom Ethernet Events protocol defines ++ * ++ */ ++ ++#ifndef _BCMEVENT_H_ ++#define _BCMEVENT_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#define BCM_EVENT_MSG_VERSION 2 /* wl_event_msg_t struct version */ ++#define BCM_MSG_IFNAME_MAX 16 /* max length of interface name */ ++ ++/* flags */ ++#define WLC_EVENT_MSG_LINK 0x01 /* link is up */ ++#define WLC_EVENT_MSG_FLUSHTXQ 0x02 /* flush tx queue on MIC error */ ++#define WLC_EVENT_MSG_GROUP 0x04 /* group MIC error */ ++#define WLC_EVENT_MSG_UNKBSS 0x08 /* unknown source bsscfg */ ++#define WLC_EVENT_MSG_UNKIF 0x10 /* unknown source OS i/f */ ++ ++/* these fields are stored in network order */ ++ ++/* version 1 */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint16 version; ++ uint16 flags; /* see flags below */ ++ uint32 event_type; /* Message (see below) */ ++ uint32 status; /* Status code (see below) */ ++ uint32 reason; /* Reason code (if applicable) */ ++ uint32 auth_type; /* WLC_E_AUTH */ ++ uint32 datalen; /* data buf */ ++ struct ether_addr addr; /* Station address (if applicable) */ ++ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ ++} BWL_POST_PACKED_STRUCT wl_event_msg_v1_t; ++ ++/* the current version */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint16 version; ++ uint16 flags; /* see flags below */ ++ uint32 event_type; /* Message (see below) */ ++ uint32 status; /* Status code (see below) */ ++ uint32 reason; /* Reason code (if applicable) */ ++ uint32 auth_type; /* WLC_E_AUTH */ ++ uint32 datalen; /* data buf */ ++ struct ether_addr addr; /* Station address (if applicable) */ ++ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ ++ uint8 ifidx; /* destination OS i/f index */ ++ uint8 bsscfgidx; /* source bsscfg index */ ++} BWL_POST_PACKED_STRUCT wl_event_msg_t; ++ ++/* used by driver msgs */ ++typedef BWL_PRE_PACKED_STRUCT struct bcm_event { ++ struct ether_header eth; ++ bcmeth_hdr_t bcm_hdr; ++ wl_event_msg_t event; ++ /* data portion follows */ ++} BWL_POST_PACKED_STRUCT bcm_event_t; ++ ++#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header)) ++ ++/* Event messages */ ++#define WLC_E_SET_SSID 0 /* indicates status of set SSID */ ++#define WLC_E_JOIN 1 /* differentiates join IBSS from found (WLC_E_START) IBSS */ ++#define WLC_E_START 2 /* STA founded an IBSS or AP started a BSS */ ++#define WLC_E_AUTH 3 /* 802.11 AUTH request */ ++#define WLC_E_AUTH_IND 4 /* 802.11 AUTH indication */ ++#define WLC_E_DEAUTH 5 /* 802.11 DEAUTH request */ ++#define WLC_E_DEAUTH_IND 6 /* 802.11 DEAUTH indication */ ++#define WLC_E_ASSOC 7 /* 802.11 ASSOC request */ ++#define WLC_E_ASSOC_IND 8 /* 802.11 ASSOC indication */ ++#define WLC_E_REASSOC 9 /* 802.11 REASSOC request */ ++#define WLC_E_REASSOC_IND 10 /* 802.11 REASSOC indication */ ++#define WLC_E_DISASSOC 11 /* 802.11 DISASSOC request */ ++#define WLC_E_DISASSOC_IND 12 /* 802.11 DISASSOC indication */ ++#define WLC_E_QUIET_START 13 /* 802.11h Quiet period started */ ++#define WLC_E_QUIET_END 14 /* 802.11h Quiet period ended */ ++#define WLC_E_BEACON_RX 15 /* BEACONS received/lost indication */ ++#define WLC_E_LINK 16 /* generic link indication */ ++#define WLC_E_MIC_ERROR 17 /* TKIP MIC error occurred */ ++#define WLC_E_NDIS_LINK 18 /* NDIS style link indication */ ++#define WLC_E_ROAM 19 /* roam attempt occurred: indicate status & reason */ ++#define WLC_E_TXFAIL 20 /* change in dot11FailedCount (txfail) */ ++#define WLC_E_PMKID_CACHE 21 /* WPA2 pmkid cache indication */ ++#define WLC_E_RETROGRADE_TSF 22 /* current AP's TSF value went backward */ ++#define WLC_E_PRUNE 23 /* AP was pruned from join list for reason */ ++#define WLC_E_AUTOAUTH 24 /* report AutoAuth table entry match for join attempt */ ++#define WLC_E_EAPOL_MSG 25 /* Event encapsulating an EAPOL message */ ++#define WLC_E_SCAN_COMPLETE 26 /* Scan results are ready or scan was aborted */ ++#define WLC_E_ADDTS_IND 27 /* indicate to host addts fail/success */ ++#define WLC_E_DELTS_IND 28 /* indicate to host delts fail/success */ ++#define WLC_E_BCNSENT_IND 29 /* indicate to host of beacon transmit */ ++#define WLC_E_BCNRX_MSG 30 /* Send the received beacon up to the host */ ++#define WLC_E_BCNLOST_MSG 31 /* indicate to host loss of beacon */ ++#define WLC_E_ROAM_PREP 32 /* before attempting to roam */ ++#define WLC_E_PFN_NET_FOUND 33 /* PFN network found event */ ++#define WLC_E_PFN_NET_LOST 34 /* PFN network lost event */ ++#define WLC_E_RESET_COMPLETE 35 ++#define WLC_E_JOIN_START 36 ++#define WLC_E_ROAM_START 37 ++#define WLC_E_ASSOC_START 38 ++#define WLC_E_IBSS_ASSOC 39 ++#define WLC_E_RADIO 40 ++#define WLC_E_PSM_WATCHDOG 41 /* PSM microcode watchdog fired */ ++#define WLC_E_PROBREQ_MSG 44 /* probe request received */ ++#define WLC_E_SCAN_CONFIRM_IND 45 ++#define WLC_E_PSK_SUP 46 /* WPA Handshake fail */ ++#define WLC_E_COUNTRY_CODE_CHANGED 47 ++#define WLC_E_EXCEEDED_MEDIUM_TIME 48 /* WMMAC excedded medium time */ ++#define WLC_E_ICV_ERROR 49 /* WEP ICV error occurred */ ++#define WLC_E_UNICAST_DECODE_ERROR 50 /* Unsupported unicast encrypted frame */ ++#define WLC_E_MULTICAST_DECODE_ERROR 51 /* Unsupported multicast encrypted frame */ ++#define WLC_E_TRACE 52 ++#define WLC_E_IF 54 /* I/F change (for dongle host notification) */ ++#define WLC_E_P2P_DISC_LISTEN_COMPLETE 55 /* listen state expires */ ++#define WLC_E_RSSI 56 /* indicate RSSI change based on configured levels */ ++#define WLC_E_PFN_SCAN_COMPLETE 57 /* PFN completed scan of network list */ ++#define WLC_E_EXTLOG_MSG 58 ++#define WLC_E_ACTION_FRAME 59 /* Action frame Rx */ ++#define WLC_E_ACTION_FRAME_COMPLETE 60 /* Action frame Tx complete */ ++#define WLC_E_PRE_ASSOC_IND 61 /* assoc request received */ ++#define WLC_E_PRE_REASSOC_IND 62 /* re-assoc request received */ ++#define WLC_E_CHANNEL_ADOPTED 63 ++#define WLC_E_AP_STARTED 64 /* AP started */ ++#define WLC_E_DFS_AP_STOP 65 /* AP stopped due to DFS */ ++#define WLC_E_DFS_AP_RESUME 66 /* AP resumed due to DFS */ ++#define WLC_E_WAI_STA_EVENT 67 /* WAI stations event */ ++#define WLC_E_WAI_MSG 68 /* event encapsulating an WAI message */ ++#define WLC_E_ESCAN_RESULT 69 /* escan result event */ ++#define WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70 /* action frame off channel complete */ ++#define WLC_E_PROBRESP_MSG 71 /* probe response received */ ++#define WLC_E_P2P_PROBREQ_MSG 72 /* P2P Probe request received */ ++#define WLC_E_DCS_REQUEST 73 ++ ++#define WLC_E_FIFO_CREDIT_MAP 74 /* credits for D11 FIFOs. [AC0,AC1,AC2,AC3,BC_MC,ATIM] */ ++ ++#define WLC_E_ACTION_FRAME_RX 75 /* Received action frame event WITH ++ * wl_event_rx_frame_data_t header ++ */ ++#define WLC_E_WAKE_EVENT 76 /* Wake Event timer fired, used for wake WLAN test mode */ ++#define WLC_E_RM_COMPLETE 77 /* Radio measurement complete */ ++#define WLC_E_HTSFSYNC 78 /* Synchronize TSF with the host */ ++#define WLC_E_OVERLAY_REQ 79 /* request an overlay IOCTL/iovar from the host */ ++#define WLC_E_CSA_COMPLETE_IND 80 /* 802.11 CHANNEL SWITCH ACTION completed */ ++#define WLC_E_EXCESS_PM_WAKE_EVENT 81 /* excess PM Wake Event to inform host */ ++#define WLC_E_PFN_SCAN_NONE 82 /* no PFN networks around */ ++#define WLC_E_PFN_SCAN_ALLGONE 83 /* last found PFN network gets lost */ ++#define WLC_E_GTK_PLUMBED 84 ++#define WLC_E_ASSOC_IND_NDIS 85 /* 802.11 ASSOC indication for NDIS only */ ++#define WLC_E_REASSOC_IND_NDIS 86 /* 802.11 REASSOC indication for NDIS only */ ++#define WLC_E_ASSOC_REQ_IE 87 ++#define WLC_E_ASSOC_RESP_IE 88 ++ ++#define WLC_E_LAST 89 /* highest val + 1 for range checking */ ++ ++/* Table of event name strings for UIs and debugging dumps */ ++typedef struct { ++ uint event; ++ const char *name; ++} bcmevent_name_t; ++ ++extern const bcmevent_name_t bcmevent_names[]; ++extern const int bcmevent_names_size; ++ ++/* Event status codes */ ++#define WLC_E_STATUS_SUCCESS 0 /* operation was successful */ ++#define WLC_E_STATUS_FAIL 1 /* operation failed */ ++#define WLC_E_STATUS_TIMEOUT 2 /* operation timed out */ ++#define WLC_E_STATUS_NO_NETWORKS 3 /* failed due to no matching network found */ ++#define WLC_E_STATUS_ABORT 4 /* operation was aborted */ ++#define WLC_E_STATUS_NO_ACK 5 /* protocol failure: packet not ack'd */ ++#define WLC_E_STATUS_UNSOLICITED 6 /* AUTH or ASSOC packet was unsolicited */ ++#define WLC_E_STATUS_ATTEMPT 7 /* attempt to assoc to an auto auth configuration */ ++#define WLC_E_STATUS_PARTIAL 8 /* scan results are incomplete */ ++#define WLC_E_STATUS_NEWSCAN 9 /* scan aborted by another scan */ ++#define WLC_E_STATUS_NEWASSOC 10 /* scan aborted due to assoc in progress */ ++#define WLC_E_STATUS_11HQUIET 11 /* 802.11h quiet period started */ ++#define WLC_E_STATUS_SUPPRESS 12 /* user disabled scanning (WLC_SET_SCANSUPPRESS) */ ++#define WLC_E_STATUS_NOCHANS 13 /* no allowable channels to scan */ ++#define WLC_E_STATUS_CS_ABORT 15 /* abort channel select */ ++#define WLC_E_STATUS_ERROR 16 /* request failed due to error */ ++ ++/* roam reason codes */ ++#define WLC_E_REASON_INITIAL_ASSOC 0 /* initial assoc */ ++#define WLC_E_REASON_LOW_RSSI 1 /* roamed due to low RSSI */ ++#define WLC_E_REASON_DEAUTH 2 /* roamed due to DEAUTH indication */ ++#define WLC_E_REASON_DISASSOC 3 /* roamed due to DISASSOC indication */ ++#define WLC_E_REASON_BCNS_LOST 4 /* roamed due to lost beacons */ ++#define WLC_E_REASON_MINTXRATE 9 /* roamed because at mintxrate for too long */ ++#define WLC_E_REASON_TXFAIL 10 /* We can hear AP, but AP can't hear us */ ++ ++/* Roam codes used primarily by CCX */ ++#define WLC_E_REASON_FAST_ROAM_FAILED 5 /* roamed due to fast roam failure */ ++#define WLC_E_REASON_DIRECTED_ROAM 6 /* roamed due to request by AP */ ++#define WLC_E_REASON_TSPEC_REJECTED 7 /* roamed due to TSPEC rejection */ ++#define WLC_E_REASON_BETTER_AP 8 /* roamed due to finding better AP */ ++ ++#define WLC_E_REASON_REQUESTED_ROAM 11 /* roamed due to BSS Mgmt Transition request by AP */ ++ ++/* prune reason codes */ ++#define WLC_E_PRUNE_ENCR_MISMATCH 1 /* encryption mismatch */ ++#define WLC_E_PRUNE_BCAST_BSSID 2 /* AP uses a broadcast BSSID */ ++#define WLC_E_PRUNE_MAC_DENY 3 /* STA's MAC addr is in AP's MAC deny list */ ++#define WLC_E_PRUNE_MAC_NA 4 /* STA's MAC addr is not in AP's MAC allow list */ ++#define WLC_E_PRUNE_REG_PASSV 5 /* AP not allowed due to regulatory restriction */ ++#define WLC_E_PRUNE_SPCT_MGMT 6 /* AP does not support STA locale spectrum mgmt */ ++#define WLC_E_PRUNE_RADAR 7 /* AP is on a radar channel of STA locale */ ++#define WLC_E_RSN_MISMATCH 8 /* STA does not support AP's RSN */ ++#define WLC_E_PRUNE_NO_COMMON_RATES 9 /* No rates in common with AP */ ++#define WLC_E_PRUNE_BASIC_RATES 10 /* STA does not support all basic rates of BSS */ ++#define WLC_E_PRUNE_CIPHER_NA 12 /* BSS's cipher not supported */ ++#define WLC_E_PRUNE_KNOWN_STA 13 /* AP is already known to us as a STA */ ++#define WLC_E_PRUNE_WDS_PEER 15 /* AP is already known to us as a WDS peer */ ++#define WLC_E_PRUNE_QBSS_LOAD 16 /* QBSS LOAD - AAC is too low */ ++#define WLC_E_PRUNE_HOME_AP 17 /* prune home AP */ ++ ++/* WPA failure reason codes carried in the WLC_E_PSK_SUP event */ ++#define WLC_E_SUP_OTHER 0 /* Other reason */ ++#define WLC_E_SUP_DECRYPT_KEY_DATA 1 /* Decryption of key data failed */ ++#define WLC_E_SUP_BAD_UCAST_WEP128 2 /* Illegal use of ucast WEP128 */ ++#define WLC_E_SUP_BAD_UCAST_WEP40 3 /* Illegal use of ucast WEP40 */ ++#define WLC_E_SUP_UNSUP_KEY_LEN 4 /* Unsupported key length */ ++#define WLC_E_SUP_PW_KEY_CIPHER 5 /* Unicast cipher mismatch in pairwise key */ ++#define WLC_E_SUP_MSG3_TOO_MANY_IE 6 /* WPA IE contains > 1 RSN IE in key msg 3 */ ++#define WLC_E_SUP_MSG3_IE_MISMATCH 7 /* WPA IE mismatch in key message 3 */ ++#define WLC_E_SUP_NO_INSTALL_FLAG 8 /* INSTALL flag unset in 4-way msg */ ++#define WLC_E_SUP_MSG3_NO_GTK 9 /* encapsulated GTK missing from msg 3 */ ++#define WLC_E_SUP_GRP_KEY_CIPHER 10 /* Multicast cipher mismatch in group key */ ++#define WLC_E_SUP_GRP_MSG1_NO_GTK 11 /* encapsulated GTK missing from group msg 1 */ ++#define WLC_E_SUP_GTK_DECRYPT_FAIL 12 /* GTK decrypt failure */ ++#define WLC_E_SUP_SEND_FAIL 13 /* message send failure */ ++#define WLC_E_SUP_DEAUTH 14 /* received FC_DEAUTH */ ++#define WLC_E_SUP_WPA_PSK_TMO 15 /* WPA PSK 4-way handshake timeout */ ++ ++/* Event data for events that include frames received over the air */ ++/* WLC_E_PROBRESP_MSG ++ * WLC_E_P2P_PROBREQ_MSG ++ * WLC_E_ACTION_FRAME_RX ++ */ ++typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data { ++ uint16 version; ++ uint16 channel; /* Matches chanspec_t format from bcmwifi_channels.h */ ++ int32 rssi; ++ uint32 mactime; ++ uint32 rate; ++} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_t; ++ ++#define BCM_RX_FRAME_DATA_VERSION 1 ++ ++/* WLC_E_IF event data */ ++typedef struct wl_event_data_if { ++ uint8 ifidx; /* RTE virtual device index (for dongle) */ ++ uint8 opcode; /* see I/F opcode */ ++ uint8 reserved; ++ uint8 bssidx; /* bsscfg index */ ++ uint8 role; /* see I/F role */ ++} wl_event_data_if_t; ++ ++/* opcode in WLC_E_IF event */ ++#define WLC_E_IF_ADD 1 /* bsscfg add */ ++#define WLC_E_IF_DEL 2 /* bsscfg delete */ ++#define WLC_E_IF_CHANGE 3 /* bsscfg role change */ ++ ++/* I/F role code in WLC_E_IF event */ ++#define WLC_E_IF_ROLE_STA 0 /* Infra STA */ ++#define WLC_E_IF_ROLE_AP 1 /* Access Point */ ++#define WLC_E_IF_ROLE_WDS 2 /* WDS link */ ++#define WLC_E_IF_ROLE_P2P_GO 3 /* P2P Group Owner */ ++#define WLC_E_IF_ROLE_P2P_CLIENT 4 /* P2P Client */ ++ ++/* Reason codes for LINK */ ++#define WLC_E_LINK_BCN_LOSS 1 /* Link down because of beacon loss */ ++#define WLC_E_LINK_DISASSOC 2 /* Link down because of disassoc */ ++#define WLC_E_LINK_ASSOC_REC 3 /* Link down because assoc recreate failed */ ++#define WLC_E_LINK_BSSCFG_DIS 4 /* Link down due to bsscfg down */ ++ ++/* reason codes for WLC_E_OVERLAY_REQ event */ ++#define WLC_E_OVL_DOWNLOAD 0 /* overlay download request */ ++#define WLC_E_OVL_UPDATE_IND 1 /* device indication of host overlay update */ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _BCMEVENT_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/bcmip.h b/drivers/bcmdrivers/gmac/src/include/proto/bcmip.h +new file mode 100755 +index 0000000..4f01aee +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/bcmip.h +@@ -0,0 +1,205 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental constants relating to IP Protocol ++ * ++ * $Id: bcmip.h 324300 2012-03-28 20:29:37Z $ ++ */ ++ ++#ifndef _bcmip_h_ ++#define _bcmip_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* IPV4 and IPV6 common */ ++#define IP_VER_OFFSET 0x0 /* offset to version field */ ++#define IP_VER_MASK 0xf0 /* version mask */ ++#define IP_VER_SHIFT 4 /* version shift */ ++#define IP_VER_4 4 /* version number for IPV4 */ ++#define IP_VER_6 6 /* version number for IPV6 */ ++ ++#define IP_VER(ip_body) \ ++ ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT) ++ ++#define IP_PROT_ICMP 0x1 /* ICMP protocol */ ++#define IP_PROT_IGMP 0x2 /* IGMP protocol */ ++#define IP_PROT_TCP 0x6 /* TCP protocol */ ++#define IP_PROT_UDP 0x11 /* UDP protocol type */ ++#define IP_PROT_ICMP6 0x3a /* ICMPv6 protocol type */ ++ ++/* IPV4 field offsets */ ++#define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */ ++#define IPV4_TOS_OFFSET 1 /* type of service offset */ ++#define IPV4_PKTLEN_OFFSET 2 /* packet length offset */ ++#define IPV4_PKTFLAG_OFFSET 6 /* more-frag,dont-frag flag offset */ ++#define IPV4_PROT_OFFSET 9 /* protocol type offset */ ++#define IPV4_CHKSUM_OFFSET 10 /* IP header checksum offset */ ++#define IPV4_SRC_IP_OFFSET 12 /* src IP addr offset */ ++#define IPV4_DEST_IP_OFFSET 16 /* dest IP addr offset */ ++#define IPV4_OPTIONS_OFFSET 20 /* IP options offset */ ++#define IPV4_MIN_HEADER_LEN 20 /* Minimum size for an IP header (no options) */ ++ ++/* IPV4 field decodes */ ++#define IPV4_VER_MASK 0xf0 /* IPV4 version mask */ ++#define IPV4_VER_SHIFT 4 /* IPV4 version shift */ ++ ++#define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */ ++#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK)) ++ ++#define IPV4_ADDR_LEN 4 /* IPV4 address length */ ++ ++#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \ ++ ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0) ++ ++#define IPV4_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \ ++ ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff) ++ ++#define IPV4_TOS_DSCP_MASK 0xfc /* DiffServ codepoint mask */ ++#define IPV4_TOS_DSCP_SHIFT 2 /* DiffServ codepoint shift */ ++ ++#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET]) ++ ++#define IPV4_TOS_PREC_MASK 0xe0 /* Historical precedence mask */ ++#define IPV4_TOS_PREC_SHIFT 5 /* Historical precedence shift */ ++ ++#define IPV4_TOS_LOWDELAY 0x10 /* Lowest delay requested */ ++#define IPV4_TOS_THROUGHPUT 0x8 /* Best throughput requested */ ++#define IPV4_TOS_RELIABILITY 0x4 /* Most reliable delivery requested */ ++ ++#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET]) ++ ++#define IPV4_FRAG_RESV 0x8000 /* Reserved */ ++#define IPV4_FRAG_DONT 0x4000 /* Don't fragment */ ++#define IPV4_FRAG_MORE 0x2000 /* More fragments */ ++#define IPV4_FRAG_OFFSET_MASK 0x1fff /* Fragment offset */ ++ ++#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */ ++ ++/* IPV4 packet formats */ ++BWL_PRE_PACKED_STRUCT struct ipv4_addr { ++ uint8 addr[IPV4_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct ipv4_hdr { ++ uint8 version_ihl; /* Version and Internet Header Length */ ++ uint8 tos; /* Type Of Service */ ++ uint16 tot_len; /* Number of bytes in packet (max 65535) */ ++ uint16 id; ++ uint16 frag; /* 3 flag bits and fragment offset */ ++ uint8 ttl; /* Time To Live */ ++ uint8 prot; /* Protocol */ ++ uint16 hdr_chksum; /* IP header checksum */ ++ uint8 src_ip[IPV4_ADDR_LEN]; /* Source IP Address */ ++ uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* IPV6 field offsets */ ++#define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */ ++#define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */ ++#define IPV6_HOP_LIMIT_OFFSET 7 /* hop limit offset */ ++#define IPV6_SRC_IP_OFFSET 8 /* src IP addr offset */ ++#define IPV6_DEST_IP_OFFSET 24 /* dst IP addr offset */ ++ ++/* IPV6 field decodes */ ++#define IPV6_TRAFFIC_CLASS(ipv6_body) \ ++ (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \ ++ ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4)) ++ ++#define IPV6_FLOW_LABEL(ipv6_body) \ ++ (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \ ++ (((uint8 *)(ipv6_body))[2] << 8) | \ ++ (((uint8 *)(ipv6_body))[3])) ++ ++#define IPV6_PAYLOAD_LEN(ipv6_body) \ ++ ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \ ++ ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1]) ++ ++#define IPV6_NEXT_HDR(ipv6_body) \ ++ (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET]) ++ ++#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body) ++ ++#define IPV6_ADDR_LEN 16 /* IPV6 address length */ ++ ++/* IPV4 TOS or IPV6 Traffic Classifier or 0 */ ++#define IP_TOS46(ip_body) \ ++ (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \ ++ IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0) ++ ++/* IPV6 extension headers (options) */ ++#define IPV6_EXTHDR_HOP 0 ++#define IPV6_EXTHDR_ROUTING 43 ++#define IPV6_EXTHDR_FRAGMENT 44 ++#define IPV6_EXTHDR_AUTH 51 ++#define IPV6_EXTHDR_NONE 59 ++#define IPV6_EXTHDR_DEST 60 ++ ++#define IPV6_EXTHDR(prot) (((prot) == IPV6_EXTHDR_HOP) || \ ++ ((prot) == IPV6_EXTHDR_ROUTING) || \ ++ ((prot) == IPV6_EXTHDR_FRAGMENT) || \ ++ ((prot) == IPV6_EXTHDR_AUTH) || \ ++ ((prot) == IPV6_EXTHDR_NONE) || \ ++ ((prot) == IPV6_EXTHDR_DEST)) ++ ++#define IPV6_MIN_HLEN 40 ++ ++#define IPV6_EXTHDR_LEN(eh) ((((struct ipv6_exthdr *)(eh))->hdrlen + 1) << 3) ++ ++BWL_PRE_PACKED_STRUCT struct ipv6_exthdr { ++ uint8 nexthdr; ++ uint8 hdrlen; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct ipv6_exthdr_frag { ++ uint8 nexthdr; ++ uint8 rsvd; ++ uint16 frag_off; ++ uint32 ident; ++} BWL_POST_PACKED_STRUCT; ++ ++static INLINE int32 ++ipv6_exthdr_len(uint8 *h, uint8 *proto) ++{ ++ uint16 len = 0, hlen; ++ struct ipv6_exthdr *eh = (struct ipv6_exthdr *)h; ++ ++ while (IPV6_EXTHDR(eh->nexthdr)) { ++ if (eh->nexthdr == IPV6_EXTHDR_NONE) ++ return -1; ++ else if (eh->nexthdr == IPV6_EXTHDR_FRAGMENT) ++ hlen = 8; ++ else if (eh->nexthdr == IPV6_EXTHDR_AUTH) ++ hlen = (eh->hdrlen + 2) << 2; ++ else ++ hlen = IPV6_EXTHDR_LEN(eh); ++ ++ len += hlen; ++ eh = (struct ipv6_exthdr *)(h + len); ++ } ++ ++ *proto = eh->nexthdr; ++ return len; ++} ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _bcmip_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/bcmipv6.h b/drivers/bcmdrivers/gmac/src/include/proto/bcmipv6.h +new file mode 100755 +index 0000000..c72eb31 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/bcmipv6.h +@@ -0,0 +1,101 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental constants relating to Neighbor Discovery Protocol ++ * ++ * $Id: bcmipv6.h 305568 2011-12-29 20:21:17Z $ ++ */ ++ ++#ifndef _bcmipv6_h_ ++#define _bcmipv6_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#define ICMPV6_HEADER_TYPE 0x3A ++#define ICMPV6_PKT_TYPE_NS 135 ++#define ICMPV6_PKT_TYPE_NA 136 ++ ++#define ICMPV6_ND_OPT_TYPE_TARGET_MAC 2 ++#define ICMPV6_ND_OPT_TYPE_SRC_MAC 1 ++ ++#define IPV6_VERSION 6 ++#define IPV6_HOP_LIMIT 255 ++ ++#define IPV6_ADDR_NULL(a) ((a[0] | a[1] | a[2] | a[3] | a[4] | \ ++ a[5] | a[6] | a[7] | a[8] | a[9] | \ ++ a[10] | a[11] | a[12] | a[13] | \ ++ a[14] | a[15]) == 0) ++ ++/* IPV6 address */ ++BWL_PRE_PACKED_STRUCT struct ipv6_addr { ++ uint8 addr[16]; ++} BWL_POST_PACKED_STRUCT; ++ ++#ifndef IL_BIGENDIAN ++ ++/* ICMPV6 Header */ ++BWL_PRE_PACKED_STRUCT struct icmp6_hdr { ++ uint8 icmp6_type; ++ uint8 icmp6_code; ++ uint16 icmp6_cksum; ++ BWL_PRE_PACKED_STRUCT union { ++ uint32 reserved; ++ BWL_PRE_PACKED_STRUCT struct nd_advt { ++ uint32 reserved1:5, ++ override:1, ++ solicited:1, ++ router:1, ++ reserved2:24; ++ } BWL_POST_PACKED_STRUCT nd_advt; ++ } BWL_POST_PACKED_STRUCT opt; ++} BWL_POST_PACKED_STRUCT; ++ ++/* Ipv6 Header Format */ ++BWL_PRE_PACKED_STRUCT struct ipv6_hdr { ++ uint8 priority:4, ++ version:4; ++ uint8 flow_lbl[3]; ++ uint16 payload_len; ++ uint8 nexthdr; ++ uint8 hop_limit; ++ struct ipv6_addr saddr; ++ struct ipv6_addr daddr; ++} BWL_POST_PACKED_STRUCT; ++ ++/* Neighbor Advertisement/Solicitation Packet Structure */ ++BWL_PRE_PACKED_STRUCT struct nd_msg { ++ struct icmp6_hdr icmph; ++ struct ipv6_addr target; ++} BWL_POST_PACKED_STRUCT; ++ ++ ++/* Neighibor Solicitation/Advertisement Optional Structure */ ++BWL_PRE_PACKED_STRUCT struct nd_msg_opt { ++ uint8 type; ++ uint8 len; ++ uint8 mac_addr[ETHER_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++ ++#endif /* IL_BIGENDIAN */ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* !defined(_bcmipv6_h_) */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/ethernet.h b/drivers/bcmdrivers/gmac/src/include/proto/ethernet.h +new file mode 100755 +index 0000000..85d664c +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/ethernet.h +@@ -0,0 +1,202 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet. ++ * ++ * $Id: ethernet.h 316696 2012-02-23 03:29:35Z $ ++ */ ++ ++#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */ ++#define _NET_ETHERNET_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include "typedefs.h" ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* ++ * The number of bytes in an ethernet (MAC) address. ++ */ ++#define ETHER_ADDR_LEN 6 ++ ++/* ++ * The number of bytes in the type field. ++ */ ++#define ETHER_TYPE_LEN 2 ++ ++/* ++ * The number of bytes in the trailing CRC field. ++ */ ++#define ETHER_CRC_LEN 4 ++ ++/* ++ * The length of the combined header. ++ */ ++#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) ++ ++/* ++ * The minimum packet length. ++ */ ++#define ETHER_MIN_LEN 64 ++ ++/* ++ * The minimum packet user data length. ++ */ ++#define ETHER_MIN_DATA 46 ++ ++/* ++ * The maximum packet length. ++ */ ++#define ETHER_MAX_LEN 1518 ++ ++/* ++ * The maximum packet user data length. ++ */ ++#define ETHER_MAX_DATA 1500 ++ ++/* ether types */ ++#define ETHER_TYPE_MIN 0x0600 /* Anything less than MIN is a length */ ++#define ETHER_TYPE_IP 0x0800 /* IP */ ++#define ETHER_TYPE_ARP 0x0806 /* ARP */ ++#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */ ++#define ETHER_TYPE_IPV6 0x86dd /* IPv6 */ ++#define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */ ++#define ETHER_TYPE_802_1X 0x888e /* 802.1x */ ++#define ETHER_TYPE_802_1X_PREAUTH 0x88c7 /* 802.1x preauthentication */ ++#define ETHER_TYPE_WAI 0x88b4 /* WAI */ ++#define ETHER_TYPE_89_0D 0x890d /* 89-0d frame for TDLS */ ++ ++#define ETHER_TYPE_PPP_SES 0x8864 /* PPPoE Session */ ++ ++/* Broadcom subtype follows ethertype; First 2 bytes are reserved; Next 2 are subtype; */ ++#define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4 byte subtype */ ++ ++/* ether header */ ++#define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN) /* dest address offset */ ++#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN) /* src address offset */ ++#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN) /* ether type offset */ ++ ++/* ++ * A macro to validate a length with ++ */ ++#define ETHER_IS_VALID_LEN(foo) \ ++ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) ++ ++#define ETHER_FILL_MCAST_ADDR_FROM_IP(ea, mgrp_ip) { \ ++ ((uint8 *)ea)[0] = 0x01; \ ++ ((uint8 *)ea)[1] = 0x00; \ ++ ((uint8 *)ea)[2] = 0x5e; \ ++ ((uint8 *)ea)[3] = ((mgrp_ip) >> 16) & 0x7f; \ ++ ((uint8 *)ea)[4] = ((mgrp_ip) >> 8) & 0xff; \ ++ ((uint8 *)ea)[5] = ((mgrp_ip) >> 0) & 0xff; \ ++} ++ ++#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */ ++/* ++ * Structure of a 10Mb/s Ethernet header. ++ */ ++BWL_PRE_PACKED_STRUCT struct ether_header { ++ uint8 ether_dhost[ETHER_ADDR_LEN]; ++ uint8 ether_shost[ETHER_ADDR_LEN]; ++ uint16 ether_type; ++} BWL_POST_PACKED_STRUCT; ++ ++/* ++ * Structure of a 48-bit Ethernet address. ++ */ ++BWL_PRE_PACKED_STRUCT struct ether_addr { ++ uint8 octet[ETHER_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++#endif /* !__INCif_etherh Quick and ugly hack for VxWorks */ ++ ++/* ++ * Takes a pointer, set, test, clear, toggle locally admininistered ++ * address bit in the 48-bit Ethernet address. ++ */ ++#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2)) ++#define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2) ++#define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xfd)) ++#define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2)) ++ ++/* Takes a pointer, marks unicast address bit in the MAC address */ ++#define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1)) ++ ++/* ++ * Takes a pointer, returns true if a 48-bit multicast address ++ * (including broadcast, since it is all ones) ++ */ ++#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1) ++ ++/* Copy an ethernet address in reverse order */ ++#define ether_rcopy(s, d) \ ++do { \ ++ ((uint16 *)(d))[2] = ((uint16 *)(s))[2]; \ ++ ((uint16 *)(d))[1] = ((uint16 *)(s))[1]; \ ++ ((uint16 *)(d))[0] = ((uint16 *)(s))[0]; \ ++} while (0) ++ ++/* compare two ethernet addresses - assumes the pointers can be referenced as shorts */ ++#define eacmp(a, b) ((((uint16 *)(a))[0] ^ ((uint16 *)(b))[0]) | \ ++ (((uint16 *)(a))[1] ^ ((uint16 *)(b))[1]) | \ ++ (((uint16 *)(a))[2] ^ ((uint16 *)(b))[2])) ++ ++#define ether_cmp(a, b) eacmp(a, b) ++ ++/* copy an ethernet address - assumes the pointers can be referenced as shorts */ ++#define eacopy(s, d) \ ++do { \ ++ ((uint16 *)(d))[0] = ((const uint16 *)(s))[0]; \ ++ ((uint16 *)(d))[1] = ((const uint16 *)(s))[1]; \ ++ ((uint16 *)(d))[2] = ((const uint16 *)(s))[2]; \ ++} while (0) ++ ++#define ether_copy(s, d) eacopy(s, d) ++ ++ ++static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}}; ++static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}}; ++ ++#define ETHER_ISBCAST(ea) ((((const uint8 *)(ea))[0] & \ ++ ((const uint8 *)(ea))[1] & \ ++ ((const uint8 *)(ea))[2] & \ ++ ((const uint8 *)(ea))[3] & \ ++ ((const uint8 *)(ea))[4] & \ ++ ((const uint8 *)(ea))[5]) == 0xff) ++#define ETHER_ISNULLADDR(ea) ((((const uint8 *)(ea))[0] | \ ++ ((const uint8 *)(ea))[1] | \ ++ ((const uint8 *)(ea))[2] | \ ++ ((const uint8 *)(ea))[3] | \ ++ ((const uint8 *)(ea))[4] | \ ++ ((const uint8 *)(ea))[5]) == 0) ++ ++#define ETHER_ISNULLDEST(da) ((((const uint16 *)(da))[0] | \ ++ ((const uint16 *)(da))[1] | \ ++ ((const uint16 *)(da))[2]) == 0) ++ ++ ++#define ETHER_MOVE_HDR(d, s) \ ++do { \ ++ struct ether_header t; \ ++ t = *(struct ether_header *)(s); \ ++ *(struct ether_header *)(d) = t; \ ++} while (0) ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _NET_ETHERNET_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/vlan.h b/drivers/bcmdrivers/gmac/src/include/proto/vlan.h +new file mode 100755 +index 0000000..5393070 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/vlan.h +@@ -0,0 +1,67 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * 802.1Q VLAN protocol definitions ++ * ++ * $Id: vlan.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _vlan_h_ ++#define _vlan_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#ifndef VLAN_VID_MASK ++#define VLAN_VID_MASK 0xfff /* low 12 bits are vlan id */ ++#endif ++#define VLAN_CFI_SHIFT 12 /* canonical format indicator bit */ ++#define VLAN_PRI_SHIFT 13 /* user priority */ ++ ++#define VLAN_PRI_MASK 7 /* 3 bits of priority */ ++ ++#define VLAN_TCI_OFFSET 14 /* offset of tag ctrl info field */ ++ ++#define VLAN_TAG_LEN 4 ++#define VLAN_TAG_OFFSET (2 * ETHER_ADDR_LEN) /* offset in Ethernet II packet only */ ++ ++#define VLAN_TPID 0x8100 /* VLAN ethertype/Tag Protocol ID */ ++ ++struct ethervlan_header { ++ uint8 ether_dhost[ETHER_ADDR_LEN]; ++ uint8 ether_shost[ETHER_ADDR_LEN]; ++ uint16 vlan_type; /* 0x8100 */ ++ uint16 vlan_tag; /* priority, cfi and vid */ ++ uint16 ether_type; ++}; ++ ++#define ETHERVLAN_HDR_LEN (ETHER_HDR_LEN + VLAN_TAG_LEN) ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#define ETHERVLAN_MOVE_HDR(d, s) \ ++do { \ ++ struct ethervlan_header t; \ ++ t = *(struct ethervlan_header *)(s); \ ++ *(struct ethervlan_header *)(d) = t; \ ++} while (0) ++ ++#endif /* _vlan_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/wpa.h b/drivers/bcmdrivers/gmac/src/include/proto/wpa.h +new file mode 100755 +index 0000000..98b09a2 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/wpa.h +@@ -0,0 +1,169 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental types and constants relating to WPA ++ * ++ * $Id: wpa.h 261155 2011-05-23 23:51:32Z $ ++ */ ++ ++#ifndef _proto_wpa_h_ ++#define _proto_wpa_h_ ++ ++#include ++#include ++ ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++/* Reason Codes */ ++ ++/* 13 through 23 taken from IEEE Std 802.11i-2004 */ ++#define DOT11_RC_INVALID_WPA_IE 13 /* Invalid info. element */ ++#define DOT11_RC_MIC_FAILURE 14 /* Michael failure */ ++#define DOT11_RC_4WH_TIMEOUT 15 /* 4-way handshake timeout */ ++#define DOT11_RC_GTK_UPDATE_TIMEOUT 16 /* Group key update timeout */ ++#define DOT11_RC_WPA_IE_MISMATCH 17 /* WPA IE in 4-way handshake differs from ++ * (re-)assoc. request/probe response ++ */ ++#define DOT11_RC_INVALID_MC_CIPHER 18 /* Invalid multicast cipher */ ++#define DOT11_RC_INVALID_UC_CIPHER 19 /* Invalid unicast cipher */ ++#define DOT11_RC_INVALID_AKMP 20 /* Invalid authenticated key management protocol */ ++#define DOT11_RC_BAD_WPA_VERSION 21 /* Unsupported WPA version */ ++#define DOT11_RC_INVALID_WPA_CAP 22 /* Invalid WPA IE capabilities */ ++#define DOT11_RC_8021X_AUTH_FAIL 23 /* 802.1X authentication failure */ ++ ++#define WPA2_PMKID_LEN 16 ++ ++/* WPA IE fixed portion */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint8 tag; /* TAG */ ++ uint8 length; /* TAG length */ ++ uint8 oui[3]; /* IE OUI */ ++ uint8 oui_type; /* OUI type */ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT version; /* IE version */ ++} BWL_POST_PACKED_STRUCT wpa_ie_fixed_t; ++#define WPA_IE_OUITYPE_LEN 4 ++#define WPA_IE_FIXED_LEN 8 ++#define WPA_IE_TAG_FIXED_LEN 6 ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 tag; /* TAG */ ++ uint8 length; /* TAG length */ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT version; /* IE version */ ++} BWL_POST_PACKED_STRUCT wpa_rsn_ie_fixed_t; ++#define WPA_RSN_IE_FIXED_LEN 4 ++#define WPA_RSN_IE_TAG_FIXED_LEN 2 ++typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN]; ++ ++/* WPA suite/multicast suite */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint8 oui[3]; ++ uint8 type; ++} BWL_POST_PACKED_STRUCT wpa_suite_t, wpa_suite_mcast_t; ++#define WPA_SUITE_LEN 4 ++ ++/* WPA unicast suite list/key management suite list */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT count; ++ wpa_suite_t list[1]; ++} BWL_POST_PACKED_STRUCT wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t; ++#define WPA_IE_SUITE_COUNT_LEN 2 ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT count; ++ wpa_pmkid_t list[1]; ++} BWL_POST_PACKED_STRUCT wpa_pmkid_list_t; ++ ++/* WPA cipher suites */ ++#define WPA_CIPHER_NONE 0 /* None */ ++#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */ ++#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */ ++#define WPA_CIPHER_AES_OCB 3 /* AES (OCB) */ ++#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */ ++#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */ ++#define WPA_CIPHER_BIP 6 /* WEP (104-bit) */ ++#define WPA_CIPHER_TPK 7 /* Group addressed traffic not allowed */ ++ ++ ++#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \ ++ (cipher) == WPA_CIPHER_WEP_40 || \ ++ (cipher) == WPA_CIPHER_WEP_104 || \ ++ (cipher) == WPA_CIPHER_TKIP || \ ++ (cipher) == WPA_CIPHER_AES_OCB || \ ++ (cipher) == WPA_CIPHER_AES_CCM || \ ++ (cipher) == WPA_CIPHER_TPK) ++ ++ ++/* WPA TKIP countermeasures parameters */ ++#define WPA_TKIP_CM_DETECT 60 /* multiple MIC failure window (seconds) */ ++#define WPA_TKIP_CM_BLOCK 60 /* countermeasures active window (seconds) */ ++ ++/* RSN IE defines */ ++#define RSN_CAP_LEN 2 /* Length of RSN capabilities field (2 octets) */ ++ ++/* RSN Capabilities defined in 802.11i */ ++#define RSN_CAP_PREAUTH 0x0001 ++#define RSN_CAP_NOPAIRWISE 0x0002 ++#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C ++#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT 2 ++#define RSN_CAP_GTK_REPLAY_CNTR_MASK 0x0030 ++#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT 4 ++#define RSN_CAP_1_REPLAY_CNTR 0 ++#define RSN_CAP_2_REPLAY_CNTRS 1 ++#define RSN_CAP_4_REPLAY_CNTRS 2 ++#define RSN_CAP_16_REPLAY_CNTRS 3 ++#ifdef MFP ++#define RSN_CAP_MFPR 0x0040 ++#define RSN_CAP_MFPC 0x0080 ++#endif ++ ++/* WPA capabilities defined in 802.11i */ ++#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS ++#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS ++#define WPA_CAP_REPLAY_CNTR_SHIFT RSN_CAP_PTK_REPLAY_CNTR_SHIFT ++#define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK ++ ++/* WPA capabilities defined in 802.11zD9.0 */ ++#define WPA_CAP_PEER_KEY_ENABLE (0x1 << 1) /* bit 9 */ ++ ++/* WPA Specific defines */ ++#define WPA_CAP_LEN RSN_CAP_LEN /* Length of RSN capabilities in RSN IE (2 octets) */ ++#define WPA_PMKID_CNT_LEN 2 /* Length of RSN PMKID count (2 octests) */ ++ ++#define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH ++ ++#define WPA2_PMKID_COUNT_LEN 2 ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _proto_wpa_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbchipc.h b/drivers/bcmdrivers/gmac/src/include/sbchipc.h +new file mode 100755 +index 0000000..a03df39 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbchipc.h +@@ -0,0 +1,2517 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * SiliconBackplane Chipcommon core hardware definitions. ++ * ++ * The chipcommon core provides chip identification, SB control, ++ * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer, ++ * GPIO interface, extbus, and support for serial and parallel flashes. ++ * ++ * $Id: sbchipc.h 328955 2012-04-23 09:06:12Z $ ++ */ ++ ++#ifndef _SBCHIPC_H ++#define _SBCHIPC_H ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++typedef struct eci_prerev35 { ++ uint32 eci_output; ++ uint32 eci_control; ++ uint32 eci_inputlo; ++ uint32 eci_inputmi; ++ uint32 eci_inputhi; ++ uint32 eci_inputintpolaritylo; ++ uint32 eci_inputintpolaritymi; ++ uint32 eci_inputintpolarityhi; ++ uint32 eci_intmasklo; ++ uint32 eci_intmaskmi; ++ uint32 eci_intmaskhi; ++ uint32 eci_eventlo; ++ uint32 eci_eventmi; ++ uint32 eci_eventhi; ++ uint32 eci_eventmasklo; ++ uint32 eci_eventmaskmi; ++ uint32 eci_eventmaskhi; ++ uint32 PAD[3]; ++} eci_prerev35_t; ++ ++typedef struct eci_rev35 { ++ uint32 eci_outputlo; ++ uint32 eci_outputhi; ++ uint32 eci_controllo; ++ uint32 eci_controlhi; ++ uint32 eci_inputlo; ++ uint32 eci_inputhi; ++ uint32 eci_inputintpolaritylo; ++ uint32 eci_inputintpolarityhi; ++ uint32 eci_intmasklo; ++ uint32 eci_intmaskhi; ++ uint32 eci_eventlo; ++ uint32 eci_eventhi; ++ uint32 eci_eventmasklo; ++ uint32 eci_eventmaskhi; ++ uint32 eci_auxtx; ++ uint32 eci_auxrx; ++ uint32 eci_datatag; ++ uint32 eci_uartescvalue; ++ uint32 eci_autobaudctr; ++ uint32 eci_uartfifolevel; ++} eci_rev35_t; ++ ++typedef struct flash_config { ++ uint32 PAD[19]; ++ /* Flash struct configuration registers (0x18c) for BCM4706 (corerev = 31) */ ++ uint32 flashstrconfig; ++} flash_config_t; ++ ++typedef volatile struct { ++ uint32 chipid; /* 0x0 */ ++ uint32 capabilities; ++ uint32 corecontrol; /* corerev >= 1 */ ++ uint32 bist; ++ ++ /* OTP */ ++ uint32 otpstatus; /* 0x10, corerev >= 10 */ ++ uint32 otpcontrol; ++ uint32 otpprog; ++ uint32 otplayout; /* corerev >= 23 */ ++ ++ /* Interrupt control */ ++ uint32 intstatus; /* 0x20 */ ++ uint32 intmask; ++ ++ /* Chip specific regs */ ++ uint32 chipcontrol; /* 0x28, rev >= 11 */ ++ uint32 chipstatus; /* 0x2c, rev >= 11 */ ++ ++ /* Jtag Master */ ++ uint32 jtagcmd; /* 0x30, rev >= 10 */ ++ uint32 jtagir; ++ uint32 jtagdr; ++ uint32 jtagctrl; ++ ++ /* serial flash interface registers */ ++ uint32 flashcontrol; /* 0x40 */ ++ uint32 flashaddress; ++ uint32 flashdata; ++ uint32 otplayoutextension; /* rev >= 35 */ ++ ++ /* Silicon backplane configuration broadcast control */ ++ uint32 broadcastaddress; /* 0x50 */ ++ uint32 broadcastdata; ++ ++ /* gpio - cleared only by power-on-reset */ ++ uint32 gpiopullup; /* 0x58, corerev >= 20 */ ++ uint32 gpiopulldown; /* 0x5c, corerev >= 20 */ ++ uint32 gpioin; /* 0x60 */ ++ uint32 gpioout; /* 0x64 */ ++ uint32 gpioouten; /* 0x68 */ ++ uint32 gpiocontrol; /* 0x6C */ ++ uint32 gpiointpolarity; /* 0x70 */ ++ uint32 gpiointmask; /* 0x74 */ ++ ++ /* GPIO events corerev >= 11 */ ++ uint32 gpioevent; ++ uint32 gpioeventintmask; ++ ++ /* Watchdog timer */ ++ uint32 watchdog; /* 0x80 */ ++ ++ /* GPIO events corerev >= 11 */ ++ uint32 gpioeventintpolarity; ++ ++ /* GPIO based LED powersave registers corerev >= 16 */ ++ uint32 gpiotimerval; /* 0x88 */ ++ uint32 gpiotimeroutmask; ++ ++ /* clock control */ ++ uint32 clockcontrol_n; /* 0x90 */ ++ uint32 clockcontrol_sb; /* aka m0 */ ++ uint32 clockcontrol_pci; /* aka m1 */ ++ uint32 clockcontrol_m2; /* mii/uart/mipsref */ ++ uint32 clockcontrol_m3; /* cpu */ ++ uint32 clkdiv; /* corerev >= 3 */ ++ uint32 gpiodebugsel; /* corerev >= 28 */ ++ uint32 capabilities_ext; /* 0xac */ ++ ++ /* pll delay registers (corerev >= 4) */ ++ uint32 pll_on_delay; /* 0xb0 */ ++ uint32 fref_sel_delay; ++ uint32 slow_clk_ctl; /* 5 < corerev < 10 */ ++ uint32 PAD; ++ ++ /* Instaclock registers (corerev >= 10) */ ++ uint32 system_clk_ctl; /* 0xc0 */ ++ uint32 clkstatestretch; ++ uint32 PAD[2]; ++ ++ /* Indirect backplane access (corerev >= 22) */ ++ uint32 bp_addrlow; /* 0xd0 */ ++ uint32 bp_addrhigh; ++ uint32 bp_data; ++ uint32 PAD; ++ uint32 bp_indaccess; ++ /* SPI registers, corerev >= 37 */ ++ uint32 gsioctrl; ++ uint32 gsioaddress; ++ uint32 gsiodata; ++ ++ /* More clock dividers (corerev >= 32) */ ++ uint32 clkdiv2; ++ /* FAB ID (corerev >= 40) */ ++ uint32 otpcontrol1; ++ uint32 fabid; /* 0xf8 */ ++ ++ /* In AI chips, pointer to erom */ ++ uint32 eromptr; /* 0xfc */ ++ ++ /* ExtBus control registers (corerev >= 3) */ ++ uint32 pcmcia_config; /* 0x100 */ ++ uint32 pcmcia_memwait; ++ uint32 pcmcia_attrwait; ++ uint32 pcmcia_iowait; ++ uint32 ide_config; ++ uint32 ide_memwait; ++ uint32 ide_attrwait; ++ uint32 ide_iowait; ++ uint32 prog_config; ++ uint32 prog_waitcount; ++ uint32 flash_config; ++ uint32 flash_waitcount; ++ uint32 SECI_config; /* 0x130 SECI configuration */ ++ uint32 SECI_status; ++ uint32 SECI_statusmask; ++ uint32 SECI_rxnibchanged; ++ ++ union { /* 0x140 */ ++ /* Enhanced Coexistence Interface (ECI) registers (corerev >= 21) */ ++ struct eci_prerev35 lt35; ++ struct eci_rev35 ge35; ++ /* Other interfaces */ ++ struct flash_config flashconf; ++ uint32 PAD[20]; ++ } eci; ++ ++ /* SROM interface (corerev >= 32) */ ++ uint32 sromcontrol; /* 0x190 */ ++ uint32 sromaddress; ++ uint32 sromdata; ++ uint32 PAD[1]; /* 0x19C */ ++ /* NAND flash registers for BCM4706 (corerev = 31) */ ++ uint32 nflashctrl; /* 0x1a0 */ ++ uint32 nflashconf; ++ uint32 nflashcoladdr; ++ uint32 nflashrowaddr; ++ uint32 nflashdata; ++ uint32 nflashwaitcnt0; /* 0x1b4 */ ++ uint32 PAD[2]; ++ ++ uint32 seci_uart_data; /* 0x1C0 */ ++ uint32 seci_uart_bauddiv; ++ uint32 seci_uart_fcr; ++ uint32 seci_uart_lcr; ++ uint32 seci_uart_mcr; ++ uint32 seci_uart_lsr; ++ uint32 seci_uart_msr; ++ uint32 seci_uart_baudadj; ++ /* Clock control and hardware workarounds (corerev >= 20) */ ++ uint32 clk_ctl_st; /* 0x1e0 */ ++ uint32 hw_war; ++ uint32 PAD[70]; ++ ++ /* UARTs */ ++ uint8 uart0data; /* 0x300 */ ++ uint8 uart0imr; ++ uint8 uart0fcr; ++ uint8 uart0lcr; ++ uint8 uart0mcr; ++ uint8 uart0lsr; ++ uint8 uart0msr; ++ uint8 uart0scratch; ++ uint8 PAD[248]; /* corerev >= 1 */ ++ ++ uint8 uart1data; /* 0x400 */ ++ uint8 uart1imr; ++ uint8 uart1fcr; ++ uint8 uart1lcr; ++ uint8 uart1mcr; ++ uint8 uart1lsr; ++ uint8 uart1msr; ++ uint8 uart1scratch; ++ uint32 PAD[126]; ++ ++ /* PMU registers (corerev >= 20) */ ++ /* Note: all timers driven by ILP clock are updated asynchronously to HT/ALP. ++ * The CPU must read them twice, compare, and retry if different. ++ */ ++ uint32 pmucontrol; /* 0x600 */ ++ uint32 pmucapabilities; ++ uint32 pmustatus; ++ uint32 res_state; ++ uint32 res_pending; ++ uint32 pmutimer; ++ uint32 min_res_mask; ++ uint32 max_res_mask; ++ uint32 res_table_sel; ++ uint32 res_dep_mask; ++ uint32 res_updn_timer; ++ uint32 res_timer; ++ uint32 clkstretch; ++ uint32 pmuwatchdog; ++ uint32 gpiosel; /* 0x638, rev >= 1 */ ++ uint32 gpioenable; /* 0x63c, rev >= 1 */ ++ uint32 res_req_timer_sel; ++ uint32 res_req_timer; ++ uint32 res_req_mask; ++ uint32 PAD; ++ uint32 chipcontrol_addr; /* 0x650 */ ++ uint32 chipcontrol_data; /* 0x654 */ ++ uint32 regcontrol_addr; ++ uint32 regcontrol_data; ++ uint32 pllcontrol_addr; ++ uint32 pllcontrol_data; ++ uint32 pmustrapopt; /* 0x668, corerev >= 28 */ ++ uint32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ ++ uint32 PAD[100]; ++ uint16 sromotp[512]; /* 0x800 */ ++#ifdef NFLASH_SUPPORT ++ /* Nand flash MLC controller registers (corerev >= 38) */ ++ uint32 nand_revision; /* 0xC00 */ ++ uint32 nand_cmd_start; ++ uint32 nand_cmd_addr_x; ++ uint32 nand_cmd_addr; ++ uint32 nand_cmd_end_addr; ++ uint32 nand_cs_nand_select; ++ uint32 nand_cs_nand_xor; ++ uint32 PAD; ++ uint32 nand_spare_rd0; ++ uint32 nand_spare_rd4; ++ uint32 nand_spare_rd8; ++ uint32 nand_spare_rd12; ++ uint32 nand_spare_wr0; ++ uint32 nand_spare_wr4; ++ uint32 nand_spare_wr8; ++ uint32 nand_spare_wr12; ++ uint32 nand_acc_control; ++ uint32 PAD; ++ uint32 nand_config; ++ uint32 PAD; ++ uint32 nand_timing_1; ++ uint32 nand_timing_2; ++ uint32 nand_semaphore; ++ uint32 PAD; ++ uint32 nand_devid; ++ uint32 nand_devid_x; ++ uint32 nand_block_lock_status; ++ uint32 nand_intfc_status; ++ uint32 nand_ecc_corr_addr_x; ++ uint32 nand_ecc_corr_addr; ++ uint32 nand_ecc_unc_addr_x; ++ uint32 nand_ecc_unc_addr; ++ uint32 nand_read_error_count; ++ uint32 nand_corr_stat_threshold; ++ uint32 PAD[2]; ++ uint32 nand_read_addr_x; ++ uint32 nand_read_addr; ++ uint32 nand_page_program_addr_x; ++ uint32 nand_page_program_addr; ++ uint32 nand_copy_back_addr_x; ++ uint32 nand_copy_back_addr; ++ uint32 nand_block_erase_addr_x; ++ uint32 nand_block_erase_addr; ++ uint32 nand_inv_read_addr_x; ++ uint32 nand_inv_read_addr; ++ uint32 PAD[2]; ++ uint32 nand_blk_wr_protect; ++ uint32 PAD[3]; ++ uint32 nand_acc_control_cs1; ++ uint32 nand_config_cs1; ++ uint32 nand_timing_1_cs1; ++ uint32 nand_timing_2_cs1; ++ uint32 PAD[20]; ++ uint32 nand_spare_rd16; ++ uint32 nand_spare_rd20; ++ uint32 nand_spare_rd24; ++ uint32 nand_spare_rd28; ++ uint32 nand_cache_addr; ++ uint32 nand_cache_data; ++ uint32 nand_ctrl_config; ++ uint32 nand_ctrl_status; ++#endif /* NFLASH_SUPPORT */ ++ uint32 gci_corecaps0; /* GCI starting at 0xC00 */ ++ uint32 gci_corecaps1; ++ uint32 gci_corecaps2; ++ uint32 gci_corectrl; ++ uint32 gci_corestat; /* 0xC10 */ ++ uint32 PAD[11]; ++ uint32 gci_indirect_addr; /* 0xC40 */ ++ uint32 PAD[111]; ++ uint32 gci_chipctrl; /* 0xE00 */ ++} chipcregs_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++#if defined(IL_BIGENDIAN) && defined(BCMHND74K) ++/* Selective swapped defines for those registers we need in ++ * big-endian code. ++ */ ++#define CC_CHIPID 4 ++#define CC_CAPABILITIES 0 ++#define CC_CHIPST 0x28 ++#define CC_EROMPTR 0xf8 ++ ++#else /* !IL_BIGENDIAN || !BCMHND74K */ ++ ++#define CC_CHIPID 0 ++#define CC_CAPABILITIES 4 ++#define CC_CHIPST 0x2c ++#define CC_EROMPTR 0xfc ++ ++#endif /* IL_BIGENDIAN && BCMHND74K */ ++ ++#define CC_OTPST 0x10 ++#define CC_JTAGCMD 0x30 ++#define CC_JTAGIR 0x34 ++#define CC_JTAGDR 0x38 ++#define CC_JTAGCTRL 0x3c ++#define CC_GPIOPU 0x58 ++#define CC_GPIOPD 0x5c ++#define CC_GPIOIN 0x60 ++#define CC_GPIOOUT 0x64 ++#define CC_GPIOOUTEN 0x68 ++#define CC_GPIOCTRL 0x6c ++#define CC_GPIOPOL 0x70 ++#define CC_GPIOINTM 0x74 ++#define CC_WATCHDOG 0x80 ++#define CC_CLKC_N 0x90 ++#define CC_CLKC_M0 0x94 ++#define CC_CLKC_M1 0x98 ++#define CC_CLKC_M2 0x9c ++#define CC_CLKC_M3 0xa0 ++#define CC_CLKDIV 0xa4 ++#define CC_SYS_CLK_CTL 0xc0 ++#define CC_CLK_CTL_ST SI_CLK_CTL_ST ++#define PMU_CTL 0x600 ++#define PMU_CAP 0x604 ++#define PMU_ST 0x608 ++#define PMU_RES_STATE 0x60c ++#define PMU_TIMER 0x614 ++#define PMU_MIN_RES_MASK 0x618 ++#define PMU_MAX_RES_MASK 0x61c ++#define CC_CHIPCTL_ADDR 0x650 ++#define CC_CHIPCTL_DATA 0x654 ++#define PMU_REG_CONTROL_ADDR 0x658 ++#define PMU_REG_CONTROL_DATA 0x65C ++#define PMU_PLL_CONTROL_ADDR 0x660 ++#define PMU_PLL_CONTROL_DATA 0x664 ++#define CC_SROM_CTRL 0x190 ++#define CC_SROM_OTP 0x800 /* SROM/OTP address space */ ++#define CC_GCI_INDIRECT_ADDR_REG 0xC40 ++#define CC_GCI_CHIP_CTRL_REG 0xE00 ++#define CC_GCI_CC_OFFSET_2 2 ++#define CC_GCI_CC_OFFSET_5 5 ++ ++#ifdef NFLASH_SUPPORT ++/* NAND flash support */ ++#define CC_NAND_REVISION 0xC00 ++#define CC_NAND_CMD_START 0xC04 ++#define CC_NAND_CMD_ADDR 0xC0C ++#define CC_NAND_SPARE_RD_0 0xC20 ++#define CC_NAND_SPARE_RD_4 0xC24 ++#define CC_NAND_SPARE_RD_8 0xC28 ++#define CC_NAND_SPARE_RD_C 0xC2C ++#define CC_NAND_CONFIG 0xC48 ++#define CC_NAND_DEVID 0xC60 ++#define CC_NAND_DEVID_EXT 0xC64 ++#define CC_NAND_INTFC_STATUS 0xC6C ++#endif /* NFLASH_SUPPORT */ ++ ++/* chipid */ ++#define CID_ID_MASK 0x0000ffff /* Chip Id mask */ ++#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */ ++#define CID_REV_SHIFT 16 /* Chip Revision shift */ ++#define CID_PKG_MASK 0x00f00000 /* Package Option mask */ ++#define CID_PKG_SHIFT 20 /* Package Option shift */ ++#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */ ++#define CID_CC_SHIFT 24 ++#define CID_TYPE_MASK 0xf0000000 /* Chip Type */ ++#define CID_TYPE_SHIFT 28 ++ ++/* capabilities */ ++#define CC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */ ++#define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ ++#define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */ ++#define CC_CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */ ++#define CC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */ ++#define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ ++#define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ ++#define CC_CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */ ++#define CC_CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */ ++#define CC_CAP_FLASH_MASK 0x00000700 /* Type of flash */ ++#define CC_CAP_PLL_MASK 0x00038000 /* Type of PLL */ ++#define CC_CAP_PWR_CTL 0x00040000 /* Power control */ ++#define CC_CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */ ++#define CC_CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */ ++#define CC_CAP_OTPSIZE_BASE 5 /* OTP Size base */ ++#define CC_CAP_JTAGP 0x00400000 /* JTAG Master Present */ ++#define CC_CAP_ROM 0x00800000 /* Internal boot rom active */ ++#define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */ ++#define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */ ++#define CC_CAP_ECI 0x20000000 /* ECI Present, rev >= 21 */ ++#define CC_CAP_SROM 0x40000000 /* Srom Present, rev >= 32 */ ++#define CC_CAP_NFLASH 0x80000000 /* Nand flash present, rev >= 35 */ ++ ++#define CC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */ ++#define CC_CAP2_GSIO 0x00000002 /* GSIO (spi/i2c) present, rev >= 37 */ ++ ++/* capabilities extension */ ++#define CC_CAP_EXT_SECI_PRESENT 0x00000001 /* SECI present */ ++ ++/* PLL type */ ++#define PLL_NONE 0x00000000 ++#define PLL_TYPE1 0x00010000 /* 48MHz base, 3 dividers */ ++#define PLL_TYPE2 0x00020000 /* 48MHz, 4 dividers */ ++#define PLL_TYPE3 0x00030000 /* 25MHz, 2 dividers */ ++#define PLL_TYPE4 0x00008000 /* 48MHz, 4 dividers */ ++#define PLL_TYPE5 0x00018000 /* 25MHz, 4 dividers */ ++#define PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */ ++#define PLL_TYPE7 0x00038000 /* 25MHz, 4 dividers */ ++ ++/* ILP clock */ ++#define ILP_CLOCK 32000 ++ ++/* ALP clock on pre-PMU chips */ ++#define ALP_CLOCK 20000000 ++ ++#define NS_ALP_CLOCK 125000000 ++#define NS_SLOW_ALP_CLOCK 100000000 ++#define NS_CPU_CLOCK 1000000000 ++#define NS_SLOW_CPU_CLOCK 800000000 ++#define NS_SI_CLOCK 250000000 ++#define NS_SLOW_SI_CLOCK 200000000 ++#define NS_FAST_MEM_CLOCK 800000000 ++#define NS_MEM_CLOCK 533000000 ++#define NS_SLOW_MEM_CLOCK 400000000 ++ ++/* HT clock */ ++#define HT_CLOCK 80000000 ++ ++/* corecontrol */ ++#define CC_UARTCLKO 0x00000001 /* Drive UART with internal clock */ ++#define CC_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ ++#define CC_ASYNCGPIO 0x00000004 /* 1=generate GPIO interrupt without backplane clock */ ++#define CC_UARTCLKEN 0x00000008 /* enable UART Clock (corerev > = 21 */ ++ ++/* 4321 chipcontrol */ ++#define CHIPCTRL_4321A0_DEFAULT 0x3a4 ++#define CHIPCTRL_4321A1_DEFAULT 0x0a4 ++#define CHIPCTRL_4321_PLL_DOWN 0x800000 /* serdes PLL down override */ ++ ++/* Fields in the otpstatus register in rev >= 21 */ ++#define OTPS_OL_MASK 0x000000ff ++#define OTPS_OL_MFG 0x00000001 /* manuf row is locked */ ++#define OTPS_OL_OR1 0x00000002 /* otp redundancy row 1 is locked */ ++#define OTPS_OL_OR2 0x00000004 /* otp redundancy row 2 is locked */ ++#define OTPS_OL_GU 0x00000008 /* general use region is locked */ ++#define OTPS_GUP_MASK 0x00000f00 ++#define OTPS_GUP_SHIFT 8 ++#define OTPS_GUP_HW 0x00000100 /* h/w subregion is programmed */ ++#define OTPS_GUP_SW 0x00000200 /* s/w subregion is programmed */ ++#define OTPS_GUP_CI 0x00000400 /* chipid/pkgopt subregion is programmed */ ++#define OTPS_GUP_FUSE 0x00000800 /* fuse subregion is programmed */ ++#define OTPS_READY 0x00001000 ++#define OTPS_RV(x) (1 << (16 + (x))) /* redundancy entry valid */ ++#define OTPS_RV_MASK 0x0fff0000 ++#define OTPS_PROGOK 0x40000000 ++ ++/* Fields in the otpcontrol register in rev >= 21 */ ++#define OTPC_PROGSEL 0x00000001 ++#define OTPC_PCOUNT_MASK 0x0000000e ++#define OTPC_PCOUNT_SHIFT 1 ++#define OTPC_VSEL_MASK 0x000000f0 ++#define OTPC_VSEL_SHIFT 4 ++#define OTPC_TMM_MASK 0x00000700 ++#define OTPC_TMM_SHIFT 8 ++#define OTPC_ODM 0x00000800 ++#define OTPC_PROGEN 0x80000000 ++ ++/* Fields in the 40nm otpcontrol register in rev >= 40 */ ++#define OTPC_40NM_PROGSEL_SHIFT 0 ++#define OTPC_40NM_PCOUNT_SHIFT 1 ++#define OTPC_40NM_PCOUNT_WR 0xA ++#define OTPC_40NM_PCOUNT_V1X 0xB ++#define OTPC_40NM_REGCSEL_SHIFT 5 ++#define OTPC_40NM_REGCSEL_DEF 0x4 ++#define OTPC_40NM_PROGIN_SHIFT 8 ++#define OTPC_40NM_R2X_SHIFT 10 ++#define OTPC_40NM_ODM_SHIFT 11 ++#define OTPC_40NM_DF_SHIFT 15 ++#define OTPC_40NM_VSEL_SHIFT 16 ++#define OTPC_40NM_VSEL_WR 0xA ++#define OTPC_40NM_VSEL_V1X 0xA ++#define OTPC_40NM_VSEL_R1X 0x5 ++#define OTPC_40NM_COFAIL_SHIFT 30 ++ ++#define OTPC1_CPCSEL_SHIFT 0 ++#define OTPC1_CPCSEL_DEF 6 ++#define OTPC1_TM_SHIFT 8 ++#define OTPC1_TM_WR 0x84 ++#define OTPC1_TM_V1X 0x84 ++#define OTPC1_TM_R1X 0x4 ++ ++/* Fields in otpprog in rev >= 21 and HND OTP */ ++#define OTPP_COL_MASK 0x000000ff ++#define OTPP_COL_SHIFT 0 ++#define OTPP_ROW_MASK 0x0000ff00 ++#define OTPP_ROW_SHIFT 8 ++#define OTPP_OC_MASK 0x0f000000 ++#define OTPP_OC_SHIFT 24 ++#define OTPP_READERR 0x10000000 ++#define OTPP_VALUE_MASK 0x20000000 ++#define OTPP_VALUE_SHIFT 29 ++#define OTPP_START_BUSY 0x80000000 ++#define OTPP_READ 0x40000000 /* HND OTP */ ++ ++/* Fields in otplayout register */ ++#define OTPL_HWRGN_OFF_MASK 0x00000FFF ++#define OTPL_HWRGN_OFF_SHIFT 0 ++#define OTPL_WRAP_REVID_MASK 0x00F80000 ++#define OTPL_WRAP_REVID_SHIFT 19 ++#define OTPL_WRAP_TYPE_MASK 0x00070000 ++#define OTPL_WRAP_TYPE_SHIFT 16 ++#define OTPL_WRAP_TYPE_65NM 0 ++#define OTPL_WRAP_TYPE_40NM 1 ++ ++/* otplayout reg corerev >= 36 */ ++#define OTP_CISFORMAT_NEW 0x80000000 ++ ++/* Opcodes for OTPP_OC field */ ++#define OTPPOC_READ 0 ++#define OTPPOC_BIT_PROG 1 ++#define OTPPOC_VERIFY 3 ++#define OTPPOC_INIT 4 ++#define OTPPOC_SET 5 ++#define OTPPOC_RESET 6 ++#define OTPPOC_OCST 7 ++#define OTPPOC_ROW_LOCK 8 ++#define OTPPOC_PRESCN_TEST 9 ++ ++/* Opcodes for OTPP_OC field (40NM) */ ++#define OTPPOC_READ_40NM 0 ++#define OTPPOC_PROG_ENABLE_40NM 1 ++#define OTPPOC_PROG_DISABLE_40NM 2 ++#define OTPPOC_VERIFY_40NM 3 ++#define OTPPOC_WORD_VERIFY_1_40NM 4 ++#define OTPPOC_ROW_LOCK_40NM 5 ++#define OTPPOC_STBY_40NM 6 ++#define OTPPOC_WAKEUP_40NM 7 ++#define OTPPOC_WORD_VERIFY_0_40NM 8 ++#define OTPPOC_PRESCN_TEST_40NM 9 ++#define OTPPOC_BIT_PROG_40NM 10 ++#define OTPPOC_WORDPROG_40NM 11 ++#define OTPPOC_BURNIN_40NM 12 ++#define OTPPOC_AUTORELOAD_40NM 13 ++#define OTPPOC_OVST_READ_40NM 14 ++#define OTPPOC_OVST_PROG_40NM 15 ++ ++/* Fields in otplayoutextension */ ++#define OTPLAYOUTEXT_FUSE_MASK 0x3FF ++ ++ ++/* Jtagm characteristics that appeared at a given corerev */ ++#define JTAGM_CREV_OLD 10 /* Old command set, 16bit max IR */ ++#define JTAGM_CREV_IRP 22 /* Able to do pause-ir */ ++#define JTAGM_CREV_RTI 28 /* Able to do return-to-idle */ ++ ++/* jtagcmd */ ++#define JCMD_START 0x80000000 ++#define JCMD_BUSY 0x80000000 ++#define JCMD_STATE_MASK 0x60000000 ++#define JCMD_STATE_TLR 0x00000000 /* Test-logic-reset */ ++#define JCMD_STATE_PIR 0x20000000 /* Pause IR */ ++#define JCMD_STATE_PDR 0x40000000 /* Pause DR */ ++#define JCMD_STATE_RTI 0x60000000 /* Run-test-idle */ ++#define JCMD0_ACC_MASK 0x0000f000 ++#define JCMD0_ACC_IRDR 0x00000000 ++#define JCMD0_ACC_DR 0x00001000 ++#define JCMD0_ACC_IR 0x00002000 ++#define JCMD0_ACC_RESET 0x00003000 ++#define JCMD0_ACC_IRPDR 0x00004000 ++#define JCMD0_ACC_PDR 0x00005000 ++#define JCMD0_IRW_MASK 0x00000f00 ++#define JCMD_ACC_MASK 0x000f0000 /* Changes for corerev 11 */ ++#define JCMD_ACC_IRDR 0x00000000 ++#define JCMD_ACC_DR 0x00010000 ++#define JCMD_ACC_IR 0x00020000 ++#define JCMD_ACC_RESET 0x00030000 ++#define JCMD_ACC_IRPDR 0x00040000 ++#define JCMD_ACC_PDR 0x00050000 ++#define JCMD_ACC_PIR 0x00060000 ++#define JCMD_ACC_IRDR_I 0x00070000 /* rev 28: return to run-test-idle */ ++#define JCMD_ACC_DR_I 0x00080000 /* rev 28: return to run-test-idle */ ++#define JCMD_IRW_MASK 0x00001f00 ++#define JCMD_IRW_SHIFT 8 ++#define JCMD_DRW_MASK 0x0000003f ++ ++/* jtagctrl */ ++#define JCTRL_FORCE_CLK 4 /* Force clock */ ++#define JCTRL_EXT_EN 2 /* Enable external targets */ ++#define JCTRL_EN 1 /* Enable Jtag master */ ++ ++/* Fields in clkdiv */ ++#define CLKD_SFLASH 0x0f000000 ++#define CLKD_SFLASH_SHIFT 24 ++#define CLKD_OTP 0x000f0000 ++#define CLKD_OTP_SHIFT 16 ++#define CLKD_JTAG 0x00000f00 ++#define CLKD_JTAG_SHIFT 8 ++#define CLKD_UART 0x000000ff ++ ++#define CLKD2_SROM 0x00000003 ++ ++/* intstatus/intmask */ ++#define CI_GPIO 0x00000001 /* gpio intr */ ++#define CI_EI 0x00000002 /* extif intr (corerev >= 3) */ ++#define CI_TEMP 0x00000004 /* temp. ctrl intr (corerev >= 15) */ ++#define CI_SIRQ 0x00000008 /* serial IRQ intr (corerev >= 15) */ ++#define CI_ECI 0x00000010 /* eci intr (corerev >= 21) */ ++#define CI_PMU 0x00000020 /* pmu intr (corerev >= 21) */ ++#define CI_UART 0x00000040 /* uart intr (corerev >= 21) */ ++#define CI_WDRESET 0x80000000 /* watchdog reset occurred */ ++ ++/* slow_clk_ctl */ ++#define SCC_SS_MASK 0x00000007 /* slow clock source mask */ ++#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */ ++#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */ ++#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */ ++#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ ++#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled, ++ * 0: LPO is enabled ++ */ ++#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, ++ * 0: power logic control ++ */ ++#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors ++ * PLL clock disable requests from core ++ */ ++#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't ++ * disable crystal when appropriate ++ */ ++#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */ ++#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */ ++#define SCC_CD_SHIFT 16 ++ ++/* system_clk_ctl */ ++#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */ ++#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */ ++#define SYCC_FP 0x00000004 /* ForcePLLOn */ ++#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */ ++#define SYCC_HR 0x00000010 /* Force HT */ ++#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ ++#define SYCC_CD_SHIFT 16 ++ ++/* Indirect backplane access */ ++#define BPIA_BYTEEN 0x0000000f ++#define BPIA_SZ1 0x00000001 ++#define BPIA_SZ2 0x00000003 ++#define BPIA_SZ4 0x00000007 ++#define BPIA_SZ8 0x0000000f ++#define BPIA_WRITE 0x00000100 ++#define BPIA_START 0x00000200 ++#define BPIA_BUSY 0x00000200 ++#define BPIA_ERROR 0x00000400 ++ ++/* pcmcia/prog/flash_config */ ++#define CF_EN 0x00000001 /* enable */ ++#define CF_EM_MASK 0x0000000e /* mode */ ++#define CF_EM_SHIFT 1 ++#define CF_EM_FLASH 0 /* flash/asynchronous mode */ ++#define CF_EM_SYNC 2 /* synchronous mode */ ++#define CF_EM_PCMCIA 4 /* pcmcia mode */ ++#define CF_DS 0x00000010 /* destsize: 0=8bit, 1=16bit */ ++#define CF_BS 0x00000020 /* byteswap */ ++#define CF_CD_MASK 0x000000c0 /* clock divider */ ++#define CF_CD_SHIFT 6 ++#define CF_CD_DIV2 0x00000000 /* backplane/2 */ ++#define CF_CD_DIV3 0x00000040 /* backplane/3 */ ++#define CF_CD_DIV4 0x00000080 /* backplane/4 */ ++#define CF_CE 0x00000100 /* clock enable */ ++#define CF_SB 0x00000200 /* size/bytestrobe (synch only) */ ++ ++/* pcmcia_memwait */ ++#define PM_W0_MASK 0x0000003f /* waitcount0 */ ++#define PM_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PM_W1_SHIFT 8 ++#define PM_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PM_W2_SHIFT 16 ++#define PM_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PM_W3_SHIFT 24 ++ ++/* pcmcia_attrwait */ ++#define PA_W0_MASK 0x0000003f /* waitcount0 */ ++#define PA_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PA_W1_SHIFT 8 ++#define PA_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PA_W2_SHIFT 16 ++#define PA_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PA_W3_SHIFT 24 ++ ++/* pcmcia_iowait */ ++#define PI_W0_MASK 0x0000003f /* waitcount0 */ ++#define PI_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PI_W1_SHIFT 8 ++#define PI_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PI_W2_SHIFT 16 ++#define PI_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PI_W3_SHIFT 24 ++ ++/* prog_waitcount */ ++#define PW_W0_MASK 0x0000001f /* waitcount0 */ ++#define PW_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PW_W1_SHIFT 8 ++#define PW_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PW_W2_SHIFT 16 ++#define PW_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PW_W3_SHIFT 24 ++ ++#define PW_W0 0x0000000c ++#define PW_W1 0x00000a00 ++#define PW_W2 0x00020000 ++#define PW_W3 0x01000000 ++ ++/* flash_waitcount */ ++#define FW_W0_MASK 0x0000003f /* waitcount0 */ ++#define FW_W1_MASK 0x00001f00 /* waitcount1 */ ++#define FW_W1_SHIFT 8 ++#define FW_W2_MASK 0x001f0000 /* waitcount2 */ ++#define FW_W2_SHIFT 16 ++#define FW_W3_MASK 0x1f000000 /* waitcount3 */ ++#define FW_W3_SHIFT 24 ++ ++/* When Srom support present, fields in sromcontrol */ ++#define SRC_START 0x80000000 ++#define SRC_BUSY 0x80000000 ++#define SRC_OPCODE 0x60000000 ++#define SRC_OP_READ 0x00000000 ++#define SRC_OP_WRITE 0x20000000 ++#define SRC_OP_WRDIS 0x40000000 ++#define SRC_OP_WREN 0x60000000 ++#define SRC_OTPSEL 0x00000010 ++#define SRC_LOCK 0x00000008 ++#define SRC_SIZE_MASK 0x00000006 ++#define SRC_SIZE_1K 0x00000000 ++#define SRC_SIZE_4K 0x00000002 ++#define SRC_SIZE_16K 0x00000004 ++#define SRC_SIZE_SHIFT 1 ++#define SRC_PRESENT 0x00000001 ++ ++/* Fields in pmucontrol */ ++#define PCTL_ILP_DIV_MASK 0xffff0000 ++#define PCTL_ILP_DIV_SHIFT 16 ++#define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */ ++#define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */ ++#define PCTL_HT_REQ_EN 0x00000100 ++#define PCTL_ALP_REQ_EN 0x00000080 ++#define PCTL_XTALFREQ_MASK 0x0000007c ++#define PCTL_XTALFREQ_SHIFT 2 ++#define PCTL_ILP_DIV_EN 0x00000002 ++#define PCTL_LPO_SEL 0x00000001 ++ ++/* Fields in clkstretch */ ++#define CSTRETCH_HT 0xffff0000 ++#define CSTRETCH_ALP 0x0000ffff ++ ++/* gpiotimerval */ ++#define GPIO_ONTIME_SHIFT 16 ++ ++/* clockcontrol_n */ ++#define CN_N1_MASK 0x3f /* n1 control */ ++#define CN_N2_MASK 0x3f00 /* n2 control */ ++#define CN_N2_SHIFT 8 ++#define CN_PLLC_MASK 0xf0000 /* pll control */ ++#define CN_PLLC_SHIFT 16 ++ ++/* clockcontrol_sb/pci/uart */ ++#define CC_M1_MASK 0x3f /* m1 control */ ++#define CC_M2_MASK 0x3f00 /* m2 control */ ++#define CC_M2_SHIFT 8 ++#define CC_M3_MASK 0x3f0000 /* m3 control */ ++#define CC_M3_SHIFT 16 ++#define CC_MC_MASK 0x1f000000 /* mux control */ ++#define CC_MC_SHIFT 24 ++ ++/* N3M Clock control magic field values */ ++#define CC_F6_2 0x02 /* A factor of 2 in */ ++#define CC_F6_3 0x03 /* 6-bit fields like */ ++#define CC_F6_4 0x05 /* N1, M1 or M3 */ ++#define CC_F6_5 0x09 ++#define CC_F6_6 0x11 ++#define CC_F6_7 0x21 ++ ++#define CC_F5_BIAS 5 /* 5-bit fields get this added */ ++ ++#define CC_MC_BYPASS 0x08 ++#define CC_MC_M1 0x04 ++#define CC_MC_M1M2 0x02 ++#define CC_MC_M1M2M3 0x01 ++#define CC_MC_M1M3 0x11 ++ ++/* Type 2 Clock control magic field values */ ++#define CC_T2_BIAS 2 /* n1, n2, m1 & m3 bias */ ++#define CC_T2M2_BIAS 3 /* m2 bias */ ++ ++#define CC_T2MC_M1BYP 1 ++#define CC_T2MC_M2BYP 2 ++#define CC_T2MC_M3BYP 4 ++ ++/* Type 6 Clock control magic field values */ ++#define CC_T6_MMASK 1 /* bits of interest in m */ ++#define CC_T6_M0 120000000 /* sb clock for m = 0 */ ++#define CC_T6_M1 100000000 /* sb clock for m = 1 */ ++#define SB2MIPS_T6(sb) (2 * (sb)) ++ ++/* Common clock base */ ++#define CC_CLOCK_BASE1 24000000 /* Half the clock freq */ ++#define CC_CLOCK_BASE2 12500000 /* Alternate crystal on some PLLs */ ++ ++/* Clock control values for 200MHz in 5350 */ ++#define CLKC_5350_N 0x0311 ++#define CLKC_5350_M 0x04020009 ++ ++/* Flash types in the chipcommon capabilities register */ ++#define FLASH_NONE 0x000 /* No flash */ ++#define SFLASH_ST 0x100 /* ST serial flash */ ++#define SFLASH_AT 0x200 /* Atmel serial flash */ ++#define NFLASH 0x300 ++#define PFLASH 0x700 /* Parallel flash */ ++#define QSPIFLASH_ST 0x800 ++#define QSPIFLASH_AT 0x900 ++ ++/* Bits in the ExtBus config registers */ ++#define CC_CFG_EN 0x0001 /* Enable */ ++#define CC_CFG_EM_MASK 0x000e /* Extif Mode */ ++#define CC_CFG_EM_ASYNC 0x0000 /* Async/Parallel flash */ ++#define CC_CFG_EM_SYNC 0x0002 /* Synchronous */ ++#define CC_CFG_EM_PCMCIA 0x0004 /* PCMCIA */ ++#define CC_CFG_EM_IDE 0x0006 /* IDE */ ++#define CC_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ ++#define CC_CFG_CD_MASK 0x00e0 /* Sync: Clock divisor, rev >= 20 */ ++#define CC_CFG_CE 0x0100 /* Sync: Clock enable, rev >= 20 */ ++#define CC_CFG_SB 0x0200 /* Sync: Size/Bytestrobe, rev >= 20 */ ++#define CC_CFG_IS 0x0400 /* Extif Sync Clk Select, rev >= 20 */ ++ ++/* ExtBus address space */ ++#define CC_EB_BASE 0x1a000000 /* Chipc ExtBus base address */ ++#define CC_EB_PCMCIA_MEM 0x1a000000 /* PCMCIA 0 memory base address */ ++#define CC_EB_PCMCIA_IO 0x1a200000 /* PCMCIA 0 I/O base address */ ++#define CC_EB_PCMCIA_CFG 0x1a400000 /* PCMCIA 0 config base address */ ++#define CC_EB_IDE 0x1a800000 /* IDE memory base */ ++#define CC_EB_PCMCIA1_MEM 0x1a800000 /* PCMCIA 1 memory base address */ ++#define CC_EB_PCMCIA1_IO 0x1aa00000 /* PCMCIA 1 I/O base address */ ++#define CC_EB_PCMCIA1_CFG 0x1ac00000 /* PCMCIA 1 config base address */ ++#define CC_EB_PROGIF 0x1b000000 /* ProgIF Async/Sync base address */ ++ ++ ++/* Start/busy bit in flashcontrol */ ++#define SFLASH_OPCODE 0x000000ff ++#define SFLASH_ACTION 0x00000700 ++#define SFLASH_CS_ACTIVE 0x00001000 /* Chip Select Active, rev >= 20 */ ++#define SFLASH_START 0x80000000 ++#define SFLASH_BUSY SFLASH_START ++ ++/* flashcontrol action codes */ ++#define SFLASH_ACT_OPONLY 0x0000 /* Issue opcode only */ ++#define SFLASH_ACT_OP1D 0x0100 /* opcode + 1 data byte */ ++#define SFLASH_ACT_OP3A 0x0200 /* opcode + 3 addr bytes */ ++#define SFLASH_ACT_OP3A1D 0x0300 /* opcode + 3 addr & 1 data bytes */ ++#define SFLASH_ACT_OP3A4D 0x0400 /* opcode + 3 addr & 4 data bytes */ ++#define SFLASH_ACT_OP3A4X4D 0x0500 /* opcode + 3 addr, 4 don't care & 4 data bytes */ ++#define SFLASH_ACT_OP3A1X4D 0x0700 /* opcode + 3 addr, 1 don't care & 4 data bytes */ ++ ++/* flashcontrol action+opcodes for ST flashes */ ++#define SFLASH_ST_WREN 0x0006 /* Write Enable */ ++#define SFLASH_ST_WRDIS 0x0004 /* Write Disable */ ++#define SFLASH_ST_RDSR 0x0105 /* Read Status Register */ ++#define SFLASH_ST_WRSR 0x0101 /* Write Status Register */ ++#define SFLASH_ST_READ 0x0303 /* Read Data Bytes */ ++#define SFLASH_ST_PP 0x0302 /* Page Program */ ++#define SFLASH_ST_SE 0x02d8 /* Sector Erase */ ++#define SFLASH_ST_BE 0x00c7 /* Bulk Erase */ ++#define SFLASH_ST_DP 0x00b9 /* Deep Power-down */ ++#define SFLASH_ST_RES 0x03ab /* Read Electronic Signature */ ++#define SFLASH_ST_CSA 0x1000 /* Keep chip select asserted */ ++#define SFLASH_ST_SSE 0x0220 /* Sub-sector Erase */ ++ ++#define SFLASH_MXIC_RDID 0x0390 /* Read Manufacture ID */ ++#define SFLASH_MXIC_MFID 0xc2 /* MXIC Manufacture ID */ ++ ++/* Status register bits for ST flashes */ ++#define SFLASH_ST_WIP 0x01 /* Write In Progress */ ++#define SFLASH_ST_WEL 0x02 /* Write Enable Latch */ ++#define SFLASH_ST_BP_MASK 0x1c /* Block Protect */ ++#define SFLASH_ST_BP_SHIFT 2 ++#define SFLASH_ST_SRWD 0x80 /* Status Register Write Disable */ ++ ++/* flashcontrol action+opcodes for Atmel flashes */ ++#define SFLASH_AT_READ 0x07e8 ++#define SFLASH_AT_PAGE_READ 0x07d2 ++#define SFLASH_AT_BUF1_READ ++#define SFLASH_AT_BUF2_READ ++#define SFLASH_AT_STATUS 0x01d7 ++#define SFLASH_AT_BUF1_WRITE 0x0384 ++#define SFLASH_AT_BUF2_WRITE 0x0387 ++#define SFLASH_AT_BUF1_ERASE_PROGRAM 0x0283 ++#define SFLASH_AT_BUF2_ERASE_PROGRAM 0x0286 ++#define SFLASH_AT_BUF1_PROGRAM 0x0288 ++#define SFLASH_AT_BUF2_PROGRAM 0x0289 ++#define SFLASH_AT_PAGE_ERASE 0x0281 ++#define SFLASH_AT_BLOCK_ERASE 0x0250 ++#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382 ++#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385 ++#define SFLASH_AT_BUF1_LOAD 0x0253 ++#define SFLASH_AT_BUF2_LOAD 0x0255 ++#define SFLASH_AT_BUF1_COMPARE 0x0260 ++#define SFLASH_AT_BUF2_COMPARE 0x0261 ++#define SFLASH_AT_BUF1_REPROGRAM 0x0258 ++#define SFLASH_AT_BUF2_REPROGRAM 0x0259 ++ ++/* Status register bits for Atmel flashes */ ++#define SFLASH_AT_READY 0x80 ++#define SFLASH_AT_MISMATCH 0x40 ++#define SFLASH_AT_ID_MASK 0x38 ++#define SFLASH_AT_ID_SHIFT 3 ++ ++/* SPI register bits, corerev >= 37 */ ++#define GSIO_START 0x80000000 ++#define GSIO_BUSY GSIO_START ++ ++/* ++ * These are the UART port assignments, expressed as offsets from the base ++ * register. These assignments should hold for any serial port based on ++ * a 8250, 16450, or 16550(A). ++ */ ++ ++#define UART_RX 0 /* In: Receive buffer (DLAB=0) */ ++#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ ++#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ ++#define UART_IER 1 /* In/Out: Interrupt Enable Register (DLAB=0) */ ++#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */ ++#define UART_IIR 2 /* In: Interrupt Identity Register */ ++#define UART_FCR 2 /* Out: FIFO Control Register */ ++#define UART_LCR 3 /* Out: Line Control Register */ ++#define UART_MCR 4 /* Out: Modem Control Register */ ++#define UART_LSR 5 /* In: Line Status Register */ ++#define UART_MSR 6 /* In: Modem Status Register */ ++#define UART_SCR 7 /* I/O: Scratch Register */ ++#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ ++#define UART_LCR_WLEN8 0x03 /* Word length: 8 bits */ ++#define UART_MCR_OUT2 0x08 /* MCR GPIO out 2 */ ++#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ ++#define UART_LSR_RX_FIFO 0x80 /* Receive FIFO error */ ++#define UART_LSR_TDHR 0x40 /* Data-hold-register empty */ ++#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ ++#define UART_LSR_BREAK 0x10 /* Break interrupt */ ++#define UART_LSR_FRAMING 0x08 /* Framing error */ ++#define UART_LSR_PARITY 0x04 /* Parity error */ ++#define UART_LSR_OVERRUN 0x02 /* Overrun error */ ++#define UART_LSR_RXRDY 0x01 /* Receiver ready */ ++#define UART_FCR_FIFO_ENABLE 1 /* FIFO control register bit controlling FIFO enable/disable */ ++ ++/* Interrupt Identity Register (IIR) bits */ ++#define UART_IIR_FIFO_MASK 0xc0 /* IIR FIFO disable/enabled mask */ ++#define UART_IIR_INT_MASK 0xf /* IIR interrupt ID source */ ++#define UART_IIR_MDM_CHG 0x0 /* Modem status changed */ ++#define UART_IIR_NOINT 0x1 /* No interrupt pending */ ++#define UART_IIR_THRE 0x2 /* THR empty */ ++#define UART_IIR_RCVD_DATA 0x4 /* Received data available */ ++#define UART_IIR_RCVR_STATUS 0x6 /* Receiver status */ ++#define UART_IIR_CHAR_TIME 0xc /* Character time */ ++ ++/* Interrupt Enable Register (IER) bits */ ++#define UART_IER_EDSSI 8 /* enable modem status interrupt */ ++#define UART_IER_ELSI 4 /* enable receiver line status interrupt */ ++#define UART_IER_ETBEI 2 /* enable transmitter holding register empty interrupt */ ++#define UART_IER_ERBFI 1 /* enable data available interrupt */ ++ ++/* pmustatus */ ++#define PST_EXTLPOAVAIL 0x0100 ++#define PST_WDRESET 0x0080 ++#define PST_INTPEND 0x0040 ++#define PST_SBCLKST 0x0030 ++#define PST_SBCLKST_ILP 0x0010 ++#define PST_SBCLKST_ALP 0x0020 ++#define PST_SBCLKST_HT 0x0030 ++#define PST_ALPAVAIL 0x0008 ++#define PST_HTAVAIL 0x0004 ++#define PST_RESINIT 0x0003 ++ ++/* pmucapabilities */ ++#define PCAP_REV_MASK 0x000000ff ++#define PCAP_RC_MASK 0x00001f00 ++#define PCAP_RC_SHIFT 8 ++#define PCAP_TC_MASK 0x0001e000 ++#define PCAP_TC_SHIFT 13 ++#define PCAP_PC_MASK 0x001e0000 ++#define PCAP_PC_SHIFT 17 ++#define PCAP_VC_MASK 0x01e00000 ++#define PCAP_VC_SHIFT 21 ++#define PCAP_CC_MASK 0x1e000000 ++#define PCAP_CC_SHIFT 25 ++#define PCAP5_PC_MASK 0x003e0000 /* PMU corerev >= 5 */ ++#define PCAP5_PC_SHIFT 17 ++#define PCAP5_VC_MASK 0x07c00000 ++#define PCAP5_VC_SHIFT 22 ++#define PCAP5_CC_MASK 0xf8000000 ++#define PCAP5_CC_SHIFT 27 ++ ++/* PMU Resource Request Timer registers */ ++/* This is based on PmuRev0 */ ++#define PRRT_TIME_MASK 0x03ff ++#define PRRT_INTEN 0x0400 ++#define PRRT_REQ_ACTIVE 0x0800 ++#define PRRT_ALP_REQ 0x1000 ++#define PRRT_HT_REQ 0x2000 ++#define PRRT_HQ_REQ 0x4000 ++ ++/* PMU resource bit position */ ++#define PMURES_BIT(bit) (1 << (bit)) ++ ++/* PMU resource number limit */ ++#define PMURES_MAX_RESNUM 30 ++ ++/* PMU chip control0 register */ ++#define PMU_CHIPCTL0 0 ++ ++/* clock req types */ ++#define PMU_CC1_CLKREQ_TYPE_SHIFT 19 ++#define PMU_CC1_CLKREQ_TYPE_MASK (1 << PMU_CC1_CLKREQ_TYPE_SHIFT) ++ ++#define CLKREQ_TYPE_CONFIG_OPENDRAIN 0 ++#define CLKREQ_TYPE_CONFIG_PUSHPULL 1 ++ ++/* PMU chip control1 register */ ++#define PMU_CHIPCTL1 1 ++#define PMU_CC1_RXC_DLL_BYPASS 0x00010000 ++ ++#define PMU_CC1_IF_TYPE_MASK 0x00000030 ++#define PMU_CC1_IF_TYPE_RMII 0x00000000 ++#define PMU_CC1_IF_TYPE_MII 0x00000010 ++#define PMU_CC1_IF_TYPE_RGMII 0x00000020 ++ ++#define PMU_CC1_SW_TYPE_MASK 0x000000c0 ++#define PMU_CC1_SW_TYPE_EPHY 0x00000000 ++#define PMU_CC1_SW_TYPE_EPHYMII 0x00000040 ++#define PMU_CC1_SW_TYPE_EPHYRMII 0x00000080 ++#define PMU_CC1_SW_TYPE_RGMII 0x000000c0 ++ ++/* PMU chip control2 register */ ++#define PMU_CHIPCTL2 2 ++ ++/* PMU chip control3 register */ ++#define PMU_CHIPCTL3 3 ++ ++#define PMU_CC3_ENABLE_SDIO_WAKEUP_SHIFT 19 ++#define PMU_CC3_ENABLE_RF_SHIFT 22 ++#define PMU_CC3_RF_DISABLE_IVALUE_SHIFT 23 ++ ++ ++/* PMU corerev and chip specific PLL controls. ++ * PMU_PLL_XX where is PMU corerev and is an arbitrary number ++ * to differentiate different PLLs controlled by the same PMU rev. ++ */ ++/* pllcontrol registers */ ++/* PDIV, div_phy, div_arm, div_adc, dith_sel, ioff, kpd_scale, lsb_sel, mash_sel, lf_c & lf_r */ ++#define PMU0_PLL0_PLLCTL0 0 ++#define PMU0_PLL0_PC0_PDIV_MASK 1 ++#define PMU0_PLL0_PC0_PDIV_FREQ 25000 ++#define PMU0_PLL0_PC0_DIV_ARM_MASK 0x00000038 ++#define PMU0_PLL0_PC0_DIV_ARM_SHIFT 3 ++#define PMU0_PLL0_PC0_DIV_ARM_BASE 8 ++ ++/* PC0_DIV_ARM for PLLOUT_ARM */ ++#define PMU0_PLL0_PC0_DIV_ARM_110MHZ 0 ++#define PMU0_PLL0_PC0_DIV_ARM_97_7MHZ 1 ++#define PMU0_PLL0_PC0_DIV_ARM_88MHZ 2 ++#define PMU0_PLL0_PC0_DIV_ARM_80MHZ 3 /* Default */ ++#define PMU0_PLL0_PC0_DIV_ARM_73_3MHZ 4 ++#define PMU0_PLL0_PC0_DIV_ARM_67_7MHZ 5 ++#define PMU0_PLL0_PC0_DIV_ARM_62_9MHZ 6 ++#define PMU0_PLL0_PC0_DIV_ARM_58_6MHZ 7 ++ ++/* Wildcard base, stop_mod, en_lf_tp, en_cal & lf_r2 */ ++#define PMU0_PLL0_PLLCTL1 1 ++#define PMU0_PLL0_PC1_WILD_INT_MASK 0xf0000000 ++#define PMU0_PLL0_PC1_WILD_INT_SHIFT 28 ++#define PMU0_PLL0_PC1_WILD_FRAC_MASK 0x0fffff00 ++#define PMU0_PLL0_PC1_WILD_FRAC_SHIFT 8 ++#define PMU0_PLL0_PC1_STOP_MOD 0x00000040 ++ ++/* Wildcard base, vco_calvar, vco_swc, vco_var_selref, vso_ical & vco_sel_avdd */ ++#define PMU0_PLL0_PLLCTL2 2 ++#define PMU0_PLL0_PC2_WILD_INT_MASK 0xf ++#define PMU0_PLL0_PC2_WILD_INT_SHIFT 4 ++ ++/* pllcontrol registers */ ++/* ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, p1div, p2div, _bypass_sdmod */ ++#define PMU1_PLL0_PLLCTL0 0 ++#define PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000 ++#define PMU1_PLL0_PC0_P1DIV_SHIFT 20 ++#define PMU1_PLL0_PC0_P2DIV_MASK 0x0f000000 ++#define PMU1_PLL0_PC0_P2DIV_SHIFT 24 ++ ++/* mdiv */ ++#define PMU1_PLL0_PLLCTL1 1 ++#define PMU1_PLL0_PC1_M1DIV_MASK 0x000000ff ++#define PMU1_PLL0_PC1_M1DIV_SHIFT 0 ++#define PMU1_PLL0_PC1_M2DIV_MASK 0x0000ff00 ++#define PMU1_PLL0_PC1_M2DIV_SHIFT 8 ++#define PMU1_PLL0_PC1_M3DIV_MASK 0x00ff0000 ++#define PMU1_PLL0_PC1_M3DIV_SHIFT 16 ++#define PMU1_PLL0_PC1_M4DIV_MASK 0xff000000 ++#define PMU1_PLL0_PC1_M4DIV_SHIFT 24 ++#define PMU1_PLL0_PC1_M4DIV_BY_9 9 ++#define PMU1_PLL0_PC1_M4DIV_BY_18 0x12 ++#define PMU1_PLL0_PC1_M4DIV_BY_36 0x24 ++ ++#define DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8 ++#define DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) ++#define DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) ++ ++/* mdiv, ndiv_dither_mfb, ndiv_mode, ndiv_int */ ++#define PMU1_PLL0_PLLCTL2 2 ++#define PMU1_PLL0_PC2_M5DIV_MASK 0x000000ff ++#define PMU1_PLL0_PC2_M5DIV_SHIFT 0 ++#define PMU1_PLL0_PC2_M5DIV_BY_12 0xc ++#define PMU1_PLL0_PC2_M5DIV_BY_18 0x12 ++#define PMU1_PLL0_PC2_M5DIV_BY_36 0x24 ++#define PMU1_PLL0_PC2_M6DIV_MASK 0x0000ff00 ++#define PMU1_PLL0_PC2_M6DIV_SHIFT 8 ++#define PMU1_PLL0_PC2_M6DIV_BY_18 0x12 ++#define PMU1_PLL0_PC2_M6DIV_BY_36 0x24 ++#define PMU1_PLL0_PC2_NDIV_MODE_MASK 0x000e0000 ++#define PMU1_PLL0_PC2_NDIV_MODE_SHIFT 17 ++#define PMU1_PLL0_PC2_NDIV_MODE_MASH 1 ++#define PMU1_PLL0_PC2_NDIV_MODE_MFB 2 /* recommended for 4319 */ ++#define PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000 ++#define PMU1_PLL0_PC2_NDIV_INT_SHIFT 20 ++ ++/* ndiv_frac */ ++#define PMU1_PLL0_PLLCTL3 3 ++#define PMU1_PLL0_PC3_NDIV_FRAC_MASK 0x00ffffff ++#define PMU1_PLL0_PC3_NDIV_FRAC_SHIFT 0 ++ ++/* pll_ctrl */ ++#define PMU1_PLL0_PLLCTL4 4 ++ ++/* pll_ctrl, vco_rng, clkdrive_ch */ ++#define PMU1_PLL0_PLLCTL5 5 ++#define PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00 ++#define PMU1_PLL0_PC5_CLK_DRV_SHIFT 8 ++ ++/* PMU rev 2 control words */ ++#define PMU2_PHY_PLL_PLLCTL 4 ++#define PMU2_SI_PLL_PLLCTL 10 ++ ++/* PMU rev 2 */ ++/* pllcontrol registers */ ++/* ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, p1div, p2div, _bypass_sdmod */ ++#define PMU2_PLL_PLLCTL0 0 ++#define PMU2_PLL_PC0_P1DIV_MASK 0x00f00000 ++#define PMU2_PLL_PC0_P1DIV_SHIFT 20 ++#define PMU2_PLL_PC0_P2DIV_MASK 0x0f000000 ++#define PMU2_PLL_PC0_P2DIV_SHIFT 24 ++ ++/* mdiv */ ++#define PMU2_PLL_PLLCTL1 1 ++#define PMU2_PLL_PC1_M1DIV_MASK 0x000000ff ++#define PMU2_PLL_PC1_M1DIV_SHIFT 0 ++#define PMU2_PLL_PC1_M2DIV_MASK 0x0000ff00 ++#define PMU2_PLL_PC1_M2DIV_SHIFT 8 ++#define PMU2_PLL_PC1_M3DIV_MASK 0x00ff0000 ++#define PMU2_PLL_PC1_M3DIV_SHIFT 16 ++#define PMU2_PLL_PC1_M4DIV_MASK 0xff000000 ++#define PMU2_PLL_PC1_M4DIV_SHIFT 24 ++ ++/* mdiv, ndiv_dither_mfb, ndiv_mode, ndiv_int */ ++#define PMU2_PLL_PLLCTL2 2 ++#define PMU2_PLL_PC2_M5DIV_MASK 0x000000ff ++#define PMU2_PLL_PC2_M5DIV_SHIFT 0 ++#define PMU2_PLL_PC2_M6DIV_MASK 0x0000ff00 ++#define PMU2_PLL_PC2_M6DIV_SHIFT 8 ++#define PMU2_PLL_PC2_NDIV_MODE_MASK 0x000e0000 ++#define PMU2_PLL_PC2_NDIV_MODE_SHIFT 17 ++#define PMU2_PLL_PC2_NDIV_INT_MASK 0x1ff00000 ++#define PMU2_PLL_PC2_NDIV_INT_SHIFT 20 ++ ++/* ndiv_frac */ ++#define PMU2_PLL_PLLCTL3 3 ++#define PMU2_PLL_PC3_NDIV_FRAC_MASK 0x00ffffff ++#define PMU2_PLL_PC3_NDIV_FRAC_SHIFT 0 ++ ++/* pll_ctrl */ ++#define PMU2_PLL_PLLCTL4 4 ++ ++/* pll_ctrl, vco_rng, clkdrive_ch */ ++#define PMU2_PLL_PLLCTL5 5 ++#define PMU2_PLL_PC5_CLKDRIVE_CH1_MASK 0x00000f00 ++#define PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT 8 ++#define PMU2_PLL_PC5_CLKDRIVE_CH2_MASK 0x0000f000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT 12 ++#define PMU2_PLL_PC5_CLKDRIVE_CH3_MASK 0x000f0000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT 16 ++#define PMU2_PLL_PC5_CLKDRIVE_CH4_MASK 0x00f00000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT 20 ++#define PMU2_PLL_PC5_CLKDRIVE_CH5_MASK 0x0f000000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH5_SHIFT 24 ++#define PMU2_PLL_PC5_CLKDRIVE_CH6_MASK 0xf0000000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH6_SHIFT 28 ++ ++/* PMU rev 5 (& 6) */ ++#define PMU5_PLL_P1P2_OFF 0 ++#define PMU5_PLL_P1_MASK 0x0f000000 ++#define PMU5_PLL_P1_SHIFT 24 ++#define PMU5_PLL_P2_MASK 0x00f00000 ++#define PMU5_PLL_P2_SHIFT 20 ++#define PMU5_PLL_M14_OFF 1 ++#define PMU5_PLL_MDIV_MASK 0x000000ff ++#define PMU5_PLL_MDIV_WIDTH 8 ++#define PMU5_PLL_NM5_OFF 2 ++#define PMU5_PLL_NDIV_MASK 0xfff00000 ++#define PMU5_PLL_NDIV_SHIFT 20 ++#define PMU5_PLL_NDIV_MODE_MASK 0x000e0000 ++#define PMU5_PLL_NDIV_MODE_SHIFT 17 ++#define PMU5_PLL_FMAB_OFF 3 ++#define PMU5_PLL_MRAT_MASK 0xf0000000 ++#define PMU5_PLL_MRAT_SHIFT 28 ++#define PMU5_PLL_ABRAT_MASK 0x08000000 ++#define PMU5_PLL_ABRAT_SHIFT 27 ++#define PMU5_PLL_FDIV_MASK 0x07ffffff ++#define PMU5_PLL_PLLCTL_OFF 4 ++#define PMU5_PLL_PCHI_OFF 5 ++#define PMU5_PLL_PCHI_MASK 0x0000003f ++ ++/* pmu XtalFreqRatio */ ++#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF ++#define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000 ++#define PMU_XTALFREQ_REG_MEASURE_SHIFT 31 ++ ++/* Divider allocation in 4716/47162/5356/5357 */ ++#define PMU5_MAINPLL_CPU 1 ++#define PMU5_MAINPLL_MEM 2 ++#define PMU5_MAINPLL_SI 3 ++ ++/* 4706 PMU */ ++#define PMU4706_MAINPLL_PLL0 0 ++#define PMU6_4706_PROCPLL_OFF 4 /* The CPU PLL */ ++#define PMU6_4706_PROC_P2DIV_MASK 0x000f0000 ++#define PMU6_4706_PROC_P2DIV_SHIFT 16 ++#define PMU6_4706_PROC_P1DIV_MASK 0x0000f000 ++#define PMU6_4706_PROC_P1DIV_SHIFT 12 ++#define PMU6_4706_PROC_NDIV_INT_MASK 0x00000ff8 ++#define PMU6_4706_PROC_NDIV_INT_SHIFT 3 ++#define PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007 ++#define PMU6_4706_PROC_NDIV_MODE_SHIFT 0 ++ ++#define PMU7_PLL_PLLCTL7 7 ++#define PMU7_PLL_CTL7_M4DIV_MASK 0xff000000 ++#define PMU7_PLL_CTL7_M4DIV_SHIFT 24 ++#define PMU7_PLL_CTL7_M4DIV_BY_6 6 ++#define PMU7_PLL_CTL7_M4DIV_BY_12 0xc ++#define PMU7_PLL_CTL7_M4DIV_BY_24 0x18 ++#define PMU7_PLL_PLLCTL8 8 ++#define PMU7_PLL_CTL8_M5DIV_MASK 0x000000ff ++#define PMU7_PLL_CTL8_M5DIV_SHIFT 0 ++#define PMU7_PLL_CTL8_M5DIV_BY_8 8 ++#define PMU7_PLL_CTL8_M5DIV_BY_12 0xc ++#define PMU7_PLL_CTL8_M5DIV_BY_24 0x18 ++#define PMU7_PLL_CTL8_M6DIV_MASK 0x0000ff00 ++#define PMU7_PLL_CTL8_M6DIV_SHIFT 8 ++#define PMU7_PLL_CTL8_M6DIV_BY_12 0xc ++#define PMU7_PLL_CTL8_M6DIV_BY_24 0x18 ++#define PMU7_PLL_PLLCTL11 11 ++#define PMU7_PLL_PLLCTL11_MASK 0xffffff00 ++#define PMU7_PLL_PLLCTL11_VAL 0x22222200 ++ ++/* PMU rev 15 */ ++#define PMU15_PLL_PLLCTL0 0 ++#define PMU15_PLL_PC0_CLKSEL_MASK 0x00000003 ++#define PMU15_PLL_PC0_CLKSEL_SHIFT 0 ++#define PMU15_PLL_PC0_FREQTGT_MASK 0x003FFFFC ++#define PMU15_PLL_PC0_FREQTGT_SHIFT 2 ++#define PMU15_PLL_PC0_PRESCALE_MASK 0x00C00000 ++#define PMU15_PLL_PC0_PRESCALE_SHIFT 22 ++#define PMU15_PLL_PC0_KPCTRL_MASK 0x07000000 ++#define PMU15_PLL_PC0_KPCTRL_SHIFT 24 ++#define PMU15_PLL_PC0_FCNTCTRL_MASK 0x38000000 ++#define PMU15_PLL_PC0_FCNTCTRL_SHIFT 27 ++#define PMU15_PLL_PC0_FDCMODE_MASK 0x40000000 ++#define PMU15_PLL_PC0_FDCMODE_SHIFT 30 ++#define PMU15_PLL_PC0_CTRLBIAS_MASK 0x80000000 ++#define PMU15_PLL_PC0_CTRLBIAS_SHIFT 31 ++ ++#define PMU15_PLL_PLLCTL1 1 ++#define PMU15_PLL_PC1_BIAS_CTLM_MASK 0x00000060 ++#define PMU15_PLL_PC1_BIAS_CTLM_SHIFT 5 ++#define PMU15_PLL_PC1_BIAS_CTLM_RST_MASK 0x00000040 ++#define PMU15_PLL_PC1_BIAS_CTLM_RST_SHIFT 6 ++#define PMU15_PLL_PC1_BIAS_SS_DIVR_MASK 0x0001FF80 ++#define PMU15_PLL_PC1_BIAS_SS_DIVR_SHIFT 7 ++#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_MASK 0x03FE0000 ++#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_SHIFT 17 ++#define PMU15_PLL_PC1_BIAS_INTG_BW_MASK 0x0C000000 ++#define PMU15_PLL_PC1_BIAS_INTG_BW_SHIFT 26 ++#define PMU15_PLL_PC1_BIAS_INTG_BYP_MASK 0x10000000 ++#define PMU15_PLL_PC1_BIAS_INTG_BYP_SHIFT 28 ++#define PMU15_PLL_PC1_OPENLP_EN_MASK 0x40000000 ++#define PMU15_PLL_PC1_OPENLP_EN_SHIFT 30 ++ ++#define PMU15_PLL_PLLCTL2 2 ++#define PMU15_PLL_PC2_CTEN_MASK 0x00000001 ++#define PMU15_PLL_PC2_CTEN_SHIFT 0 ++ ++#define PMU15_PLL_PLLCTL3 3 ++#define PMU15_PLL_PC3_DITHER_EN_MASK 0x00000001 ++#define PMU15_PLL_PC3_DITHER_EN_SHIFT 0 ++#define PMU15_PLL_PC3_DCOCTLSP_MASK 0xFE000000 ++#define PMU15_PLL_PC3_DCOCTLSP_SHIFT 25 ++#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_MASK 0x01 ++#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_SHIFT 0 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_MASK 0x02 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_SHIFT 1 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_MASK 0x04 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_SHIFT 2 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_MASK 0x18 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_SHIFT 3 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_MASK 0x60 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_SHIFT 5 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV1 0 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV2 1 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV3 2 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV5 3 ++ ++#define PMU15_PLL_PLLCTL4 4 ++#define PMU15_PLL_PC4_FLLCLK1_DIV_MASK 0x00000007 ++#define PMU15_PLL_PC4_FLLCLK1_DIV_SHIFT 0 ++#define PMU15_PLL_PC4_FLLCLK2_DIV_MASK 0x00000038 ++#define PMU15_PLL_PC4_FLLCLK2_DIV_SHIFT 3 ++#define PMU15_PLL_PC4_FLLCLK3_DIV_MASK 0x000001C0 ++#define PMU15_PLL_PC4_FLLCLK3_DIV_SHIFT 6 ++#define PMU15_PLL_PC4_DBGMODE_MASK 0x00000E00 ++#define PMU15_PLL_PC4_DBGMODE_SHIFT 9 ++#define PMU15_PLL_PC4_FLL480_CTLSP_LK_MASK 0x00001000 ++#define PMU15_PLL_PC4_FLL480_CTLSP_LK_SHIFT 12 ++#define PMU15_PLL_PC4_FLL480_CTLSP_MASK 0x000FE000 ++#define PMU15_PLL_PC4_FLL480_CTLSP_SHIFT 13 ++#define PMU15_PLL_PC4_DINPOL_MASK 0x00100000 ++#define PMU15_PLL_PC4_DINPOL_SHIFT 20 ++#define PMU15_PLL_PC4_CLKOUT_PD_MASK 0x00200000 ++#define PMU15_PLL_PC4_CLKOUT_PD_SHIFT 21 ++#define PMU15_PLL_PC4_CLKDIV2_PD_MASK 0x00400000 ++#define PMU15_PLL_PC4_CLKDIV2_PD_SHIFT 22 ++#define PMU15_PLL_PC4_CLKDIV4_PD_MASK 0x00800000 ++#define PMU15_PLL_PC4_CLKDIV4_PD_SHIFT 23 ++#define PMU15_PLL_PC4_CLKDIV8_PD_MASK 0x01000000 ++#define PMU15_PLL_PC4_CLKDIV8_PD_SHIFT 24 ++#define PMU15_PLL_PC4_CLKDIV16_PD_MASK 0x02000000 ++#define PMU15_PLL_PC4_CLKDIV16_PD_SHIFT 25 ++#define PMU15_PLL_PC4_TEST_EN_MASK 0x04000000 ++#define PMU15_PLL_PC4_TEST_EN_SHIFT 26 ++ ++#define PMU15_PLL_PLLCTL5 5 ++#define PMU15_PLL_PC5_FREQTGT_MASK 0x000FFFFF ++#define PMU15_PLL_PC5_FREQTGT_SHIFT 0 ++#define PMU15_PLL_PC5_DCOCTLSP_MASK 0x07F00000 ++#define PMU15_PLL_PC5_DCOCTLSP_SHIFT 20 ++#define PMU15_PLL_PC5_PRESCALE_MASK 0x18000000 ++#define PMU15_PLL_PC5_PRESCALE_SHIFT 27 ++ ++#define PMU15_PLL_PLLCTL6 6 ++#define PMU15_PLL_PC6_FREQTGT_MASK 0x000FFFFF ++#define PMU15_PLL_PC6_FREQTGT_SHIFT 0 ++#define PMU15_PLL_PC6_DCOCTLSP_MASK 0x07F00000 ++#define PMU15_PLL_PC6_DCOCTLSP_SHIFT 20 ++#define PMU15_PLL_PC6_PRESCALE_MASK 0x18000000 ++#define PMU15_PLL_PC6_PRESCALE_SHIFT 27 ++ ++#define PMU15_FREQTGT_480_DEFAULT 0x19AB1 ++#define PMU15_FREQTGT_492_DEFAULT 0x1A4F5 ++#define PMU15_ARM_96MHZ 96000000 /* 96 Mhz */ ++#define PMU15_ARM_98MHZ 98400000 /* 98.4 Mhz */ ++#define PMU15_ARM_97MHZ 97000000 /* 97 Mhz */ ++ ++ ++#define PMU17_PLLCTL2_NDIVTYPE_MASK 0x00000070 ++#define PMU17_PLLCTL2_NDIVTYPE_SHIFT 4 ++ ++#define PMU17_PLLCTL2_NDIV_MODE_INT 0 ++#define PMU17_PLLCTL2_NDIV_MODE_INT1B8 1 ++#define PMU17_PLLCTL2_NDIV_MODE_MASH111 2 ++#define PMU17_PLLCTL2_NDIV_MODE_MASH111B8 3 ++ ++#define PMU17_PLLCTL0_BBPLL_PWRDWN 0 ++#define PMU17_PLLCTL0_BBPLL_DRST 3 ++#define PMU17_PLLCTL0_BBPLL_DISBL_CLK 8 ++ ++/* PLL usage in 4716/47162 */ ++#define PMU4716_MAINPLL_PLL0 12 ++ ++/* PLL usage in 5356/5357 */ ++#define PMU5356_MAINPLL_PLL0 0 ++#define PMU5357_MAINPLL_PLL0 0 ++ ++/* 4716/47162 resources */ ++#define RES4716_PROC_PLL_ON 0x00000040 ++#define RES4716_PROC_HT_AVAIL 0x00000080 ++ ++/* 4716/4717/4718 Chip specific ChipControl register bits */ ++#define CCTRL_471X_I2S_PINS_ENABLE 0x0080 /* I2S pins off by default, shared w/ pflash */ ++ ++/* 5357 Chip specific ChipControl register bits */ ++/* 2nd - 32-bit reg */ ++#define CCTRL_5357_I2S_PINS_ENABLE 0x00040000 /* I2S pins enable */ ++#define CCTRL_5357_I2CSPI_PINS_ENABLE 0x00080000 /* I2C/SPI pins enable */ ++ ++/* 5354 resources */ ++#define RES5354_EXT_SWITCHER_PWM 0 /* 0x00001 */ ++#define RES5354_BB_SWITCHER_PWM 1 /* 0x00002 */ ++#define RES5354_BB_SWITCHER_BURST 2 /* 0x00004 */ ++#define RES5354_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */ ++#define RES5354_ILP_REQUEST 4 /* 0x00010 */ ++#define RES5354_RADIO_SWITCHER_PWM 5 /* 0x00020 */ ++#define RES5354_RADIO_SWITCHER_BURST 6 /* 0x00040 */ ++#define RES5354_ROM_SWITCH 7 /* 0x00080 */ ++#define RES5354_PA_REF_LDO 8 /* 0x00100 */ ++#define RES5354_RADIO_LDO 9 /* 0x00200 */ ++#define RES5354_AFE_LDO 10 /* 0x00400 */ ++#define RES5354_PLL_LDO 11 /* 0x00800 */ ++#define RES5354_BG_FILTBYP 12 /* 0x01000 */ ++#define RES5354_TX_FILTBYP 13 /* 0x02000 */ ++#define RES5354_RX_FILTBYP 14 /* 0x04000 */ ++#define RES5354_XTAL_PU 15 /* 0x08000 */ ++#define RES5354_XTAL_EN 16 /* 0x10000 */ ++#define RES5354_BB_PLL_FILTBYP 17 /* 0x20000 */ ++#define RES5354_RF_PLL_FILTBYP 18 /* 0x40000 */ ++#define RES5354_BB_PLL_PU 19 /* 0x80000 */ ++ ++/* 5357 Chip specific ChipControl register bits */ ++#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */ ++#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */ ++#define CCTRL5357_NFLASH (1<<16) /* Nandflash in ChipControl 1, bit 16 */ ++ ++/* 4328 resources */ ++#define RES4328_EXT_SWITCHER_PWM 0 /* 0x00001 */ ++#define RES4328_BB_SWITCHER_PWM 1 /* 0x00002 */ ++#define RES4328_BB_SWITCHER_BURST 2 /* 0x00004 */ ++#define RES4328_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */ ++#define RES4328_ILP_REQUEST 4 /* 0x00010 */ ++#define RES4328_RADIO_SWITCHER_PWM 5 /* 0x00020 */ ++#define RES4328_RADIO_SWITCHER_BURST 6 /* 0x00040 */ ++#define RES4328_ROM_SWITCH 7 /* 0x00080 */ ++#define RES4328_PA_REF_LDO 8 /* 0x00100 */ ++#define RES4328_RADIO_LDO 9 /* 0x00200 */ ++#define RES4328_AFE_LDO 10 /* 0x00400 */ ++#define RES4328_PLL_LDO 11 /* 0x00800 */ ++#define RES4328_BG_FILTBYP 12 /* 0x01000 */ ++#define RES4328_TX_FILTBYP 13 /* 0x02000 */ ++#define RES4328_RX_FILTBYP 14 /* 0x04000 */ ++#define RES4328_XTAL_PU 15 /* 0x08000 */ ++#define RES4328_XTAL_EN 16 /* 0x10000 */ ++#define RES4328_BB_PLL_FILTBYP 17 /* 0x20000 */ ++#define RES4328_RF_PLL_FILTBYP 18 /* 0x40000 */ ++#define RES4328_BB_PLL_PU 19 /* 0x80000 */ ++ ++/* 4325 A0/A1 resources */ ++#define RES4325_BUCK_BOOST_BURST 0 /* 0x00000001 */ ++#define RES4325_CBUCK_BURST 1 /* 0x00000002 */ ++#define RES4325_CBUCK_PWM 2 /* 0x00000004 */ ++#define RES4325_CLDO_CBUCK_BURST 3 /* 0x00000008 */ ++#define RES4325_CLDO_CBUCK_PWM 4 /* 0x00000010 */ ++#define RES4325_BUCK_BOOST_PWM 5 /* 0x00000020 */ ++#define RES4325_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4325_ABUCK_BURST 7 /* 0x00000080 */ ++#define RES4325_ABUCK_PWM 8 /* 0x00000100 */ ++#define RES4325_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4325_OTP_PU 10 /* 0x00000400 */ ++#define RES4325_LNLDO3_PU 11 /* 0x00000800 */ ++#define RES4325_LNLDO4_PU 12 /* 0x00001000 */ ++#define RES4325_XTAL_PU 13 /* 0x00002000 */ ++#define RES4325_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4325_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4325_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4325_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4325_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4325_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4325_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4325_HT_AVAIL 21 /* 0x00200000 */ ++ ++/* 4325 B0/C0 resources */ ++#define RES4325B0_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4325B0_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4325B0_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4325B0_CLDO_PU 4 /* 0x00000010 */ ++ ++/* 4325 C1 resources */ ++#define RES4325C1_LNLDO2_PU 12 /* 0x00001000 */ ++ ++/* 4325 chip-specific ChipStatus register bits */ ++#define CST4325_SPROM_OTP_SEL_MASK 0x00000003 ++#define CST4325_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4325_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ ++#define CST4325_OTP_SEL 2 /* OTP is powered up, no SPROM */ ++#define CST4325_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ ++#define CST4325_SDIO_USB_MODE_MASK 0x00000004 ++#define CST4325_SDIO_USB_MODE_SHIFT 2 ++#define CST4325_RCAL_VALID_MASK 0x00000008 ++#define CST4325_RCAL_VALID_SHIFT 3 ++#define CST4325_RCAL_VALUE_MASK 0x000001f0 ++#define CST4325_RCAL_VALUE_SHIFT 4 ++#define CST4325_PMUTOP_2B_MASK 0x00000200 /* 1 for 2b, 0 for to 2a */ ++#define CST4325_PMUTOP_2B_SHIFT 9 ++ ++#define RES4329_RESERVED0 0 /* 0x00000001 */ ++#define RES4329_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4329_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4329_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4329_CLDO_PU 4 /* 0x00000010 */ ++#define RES4329_PALDO_PU 5 /* 0x00000020 */ ++#define RES4329_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4329_RESERVED7 7 /* 0x00000080 */ ++#define RES4329_RESERVED8 8 /* 0x00000100 */ ++#define RES4329_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4329_OTP_PU 10 /* 0x00000400 */ ++#define RES4329_RESERVED11 11 /* 0x00000800 */ ++#define RES4329_LNLDO2_PU 12 /* 0x00001000 */ ++#define RES4329_XTAL_PU 13 /* 0x00002000 */ ++#define RES4329_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4329_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4329_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4329_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4329_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4329_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4329_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4329_HT_AVAIL 21 /* 0x00200000 */ ++ ++#define CST4329_SPROM_OTP_SEL_MASK 0x00000003 ++#define CST4329_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4329_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ ++#define CST4329_OTP_SEL 2 /* OTP is powered up, no SPROM */ ++#define CST4329_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ ++#define CST4329_SPI_SDIO_MODE_MASK 0x00000004 ++#define CST4329_SPI_SDIO_MODE_SHIFT 2 ++ ++/* 4312 chip-specific ChipStatus register bits */ ++#define CST4312_SPROM_OTP_SEL_MASK 0x00000003 ++#define CST4312_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4312_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ ++#define CST4312_OTP_SEL 2 /* OTP is powered up, no SPROM */ ++#define CST4312_OTP_BAD 3 /* OTP is broken, SPROM is present */ ++ ++/* 4312 resources (all PMU chips with little memory constraint) */ ++#define RES4312_SWITCHER_BURST 0 /* 0x00000001 */ ++#define RES4312_SWITCHER_PWM 1 /* 0x00000002 */ ++#define RES4312_PA_REF_LDO 2 /* 0x00000004 */ ++#define RES4312_CORE_LDO_BURST 3 /* 0x00000008 */ ++#define RES4312_CORE_LDO_PWM 4 /* 0x00000010 */ ++#define RES4312_RADIO_LDO 5 /* 0x00000020 */ ++#define RES4312_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4312_BG_FILTBYP 7 /* 0x00000080 */ ++#define RES4312_TX_FILTBYP 8 /* 0x00000100 */ ++#define RES4312_RX_FILTBYP 9 /* 0x00000200 */ ++#define RES4312_XTAL_PU 10 /* 0x00000400 */ ++#define RES4312_ALP_AVAIL 11 /* 0x00000800 */ ++#define RES4312_BB_PLL_FILTBYP 12 /* 0x00001000 */ ++#define RES4312_RF_PLL_FILTBYP 13 /* 0x00002000 */ ++#define RES4312_HT_AVAIL 14 /* 0x00004000 */ ++ ++/* 4322 resources */ ++#define RES4322_RF_LDO 0 ++#define RES4322_ILP_REQUEST 1 ++#define RES4322_XTAL_PU 2 ++#define RES4322_ALP_AVAIL 3 ++#define RES4322_SI_PLL_ON 4 ++#define RES4322_HT_SI_AVAIL 5 ++#define RES4322_PHY_PLL_ON 6 ++#define RES4322_HT_PHY_AVAIL 7 ++#define RES4322_OTP_PU 8 ++ ++/* 4322 chip-specific ChipStatus register bits */ ++#define CST4322_XTAL_FREQ_20_40MHZ 0x00000020 ++#define CST4322_SPROM_OTP_SEL_MASK 0x000000c0 ++#define CST4322_SPROM_OTP_SEL_SHIFT 6 ++#define CST4322_NO_SPROM_OTP 0 /* no OTP, no SPROM */ ++#define CST4322_SPROM_PRESENT 1 /* SPROM is present */ ++#define CST4322_OTP_PRESENT 2 /* OTP is present */ ++#define CST4322_PCI_OR_USB 0x00000100 ++#define CST4322_BOOT_MASK 0x00000600 ++#define CST4322_BOOT_SHIFT 9 ++#define CST4322_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST4322_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST4322_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST4322_BOOT_FROM_INVALID 3 ++#define CST4322_ILP_DIV_EN 0x00000800 ++#define CST4322_FLASH_TYPE_MASK 0x00001000 ++#define CST4322_FLASH_TYPE_SHIFT 12 ++#define CST4322_FLASH_TYPE_SHIFT_ST 0 /* ST serial FLASH */ ++#define CST4322_FLASH_TYPE_SHIFT_ATMEL 1 /* ATMEL flash */ ++#define CST4322_ARM_TAP_SEL 0x00002000 ++#define CST4322_RES_INIT_MODE_MASK 0x0000c000 ++#define CST4322_RES_INIT_MODE_SHIFT 14 ++#define CST4322_RES_INIT_MODE_ILPAVAIL 0 /* resinitmode: ILP available */ ++#define CST4322_RES_INIT_MODE_ILPREQ 1 /* resinitmode: ILP request */ ++#define CST4322_RES_INIT_MODE_ALPAVAIL 2 /* resinitmode: ALP available */ ++#define CST4322_RES_INIT_MODE_HTAVAIL 3 /* resinitmode: HT available */ ++#define CST4322_PCIPLLCLK_GATING 0x00010000 ++#define CST4322_CLK_SWITCH_PCI_TO_ALP 0x00020000 ++#define CST4322_PCI_CARDBUS_MODE 0x00040000 ++ ++/* 43224 chip-specific ChipControl register bits */ ++#define CCTRL43224_GPIO_TOGGLE 0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */ ++#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */ ++#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */ ++ ++/* 43236 resources */ ++#define RES43236_REGULATOR 0 ++#define RES43236_ILP_REQUEST 1 ++#define RES43236_XTAL_PU 2 ++#define RES43236_ALP_AVAIL 3 ++#define RES43236_SI_PLL_ON 4 ++#define RES43236_HT_SI_AVAIL 5 ++ ++/* 43236 chip-specific ChipControl register bits */ ++#define CCTRL43236_BT_COEXIST (1<<0) /* 0 disable */ ++#define CCTRL43236_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ ++#define CCTRL43236_EXT_LNA (1<<2) /* 0 disable */ ++#define CCTRL43236_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */ ++#define CCTRL43236_GSIO (1<<4) /* 0 disable */ ++ ++/* 43236 Chip specific ChipStatus register bits */ ++#define CST43236_SFLASH_MASK 0x00000040 ++#define CST43236_OTP_SEL_MASK 0x00000080 ++#define CST43236_OTP_SEL_SHIFT 7 ++#define CST43236_HSIC_MASK 0x00000100 /* USB/HSIC */ ++#define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */ ++#define CST43236_BOOT_MASK 0x00001800 ++#define CST43236_BOOT_SHIFT 11 ++#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST43236_BOOT_FROM_INVALID 3 ++ ++/* 43237 resources */ ++#define RES43237_REGULATOR 0 ++#define RES43237_ILP_REQUEST 1 ++#define RES43237_XTAL_PU 2 ++#define RES43237_ALP_AVAIL 3 ++#define RES43237_SI_PLL_ON 4 ++#define RES43237_HT_SI_AVAIL 5 ++ ++/* 43237 chip-specific ChipControl register bits */ ++#define CCTRL43237_BT_COEXIST (1<<0) /* 0 disable */ ++#define CCTRL43237_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ ++#define CCTRL43237_EXT_LNA (1<<2) /* 0 disable */ ++#define CCTRL43237_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */ ++#define CCTRL43237_GSIO (1<<4) /* 0 disable */ ++ ++/* 43237 Chip specific ChipStatus register bits */ ++#define CST43237_SFLASH_MASK 0x00000040 ++#define CST43237_OTP_SEL_MASK 0x00000080 ++#define CST43237_OTP_SEL_SHIFT 7 ++#define CST43237_HSIC_MASK 0x00000100 /* USB/HSIC */ ++#define CST43237_BP_CLK 0x00000200 /* 120/96Mbps */ ++#define CST43237_BOOT_MASK 0x00001800 ++#define CST43237_BOOT_SHIFT 11 ++#define CST43237_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST43237_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST43237_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST43237_BOOT_FROM_INVALID 3 ++ ++/* 43239 resources */ ++#define RES43239_OTP_PU 9 ++#define RES43239_MACPHY_CLKAVAIL 23 ++#define RES43239_HT_AVAIL 24 ++ ++/* 43239 Chip specific ChipStatus register bits */ ++#define CST43239_SPROM_MASK 0x00000002 ++#define CST43239_SFLASH_MASK 0x00000004 ++#define CST43239_RES_INIT_MODE_SHIFT 7 ++#define CST43239_RES_INIT_MODE_MASK 0x000001f0 ++#define CST43239_CHIPMODE_SDIOD(cs) ((cs) & (1 << 15)) /* SDIO || gSPI */ ++#define CST43239_CHIPMODE_USB20D(cs) (~(cs) & (1 << 15)) /* USB || USBDA */ ++#define CST43239_CHIPMODE_SDIO(cs) (((cs) & (1 << 0)) == 0) /* SDIO */ ++#define CST43239_CHIPMODE_GSPI(cs) (((cs) & (1 << 0)) == (1 << 0)) /* gSPI */ ++ ++/* 4324 resources */ ++#define RES4324_OTP_PU 10 ++#define RES4324_HT_AVAIL 29 ++#define RES4324_MACPHY_CLKAVAIL 30 ++ ++/* 4324 Chip specific ChipStatus register bits */ ++#define CST4324_SPROM_MASK 0x00000080 ++#define CST4324_SFLASH_MASK 0x00400000 ++#define CST4324_RES_INIT_MODE_SHIFT 10 ++#define CST4324_RES_INIT_MODE_MASK 0x00000c00 ++#define CST4324_CHIPMODE_MASK 0x7 ++#define CST4324_CHIPMODE_SDIOD(cs) ((~(cs)) & (1 << 2)) /* SDIO || gSPI */ ++#define CST4324_CHIPMODE_USB20D(cs) (((cs) & CST4324_CHIPMODE_MASK) == 0x6) /* USB || USBDA */ ++ ++/* 4331 resources */ ++#define RES4331_REGULATOR 0 ++#define RES4331_ILP_REQUEST 1 ++#define RES4331_XTAL_PU 2 ++#define RES4331_ALP_AVAIL 3 ++#define RES4331_SI_PLL_ON 4 ++#define RES4331_HT_SI_AVAIL 5 ++ ++/* 4331 chip-specific ChipControl register bits */ ++#define CCTRL4331_BT_COEXIST (1<<0) /* 0 disable */ ++#define CCTRL4331_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ ++#define CCTRL4331_EXT_LNA_G (1<<2) /* 0 disable */ ++#define CCTRL4331_SPROM_GPIO13_15 (1<<3) /* sprom/gpio13-15 mux */ ++#define CCTRL4331_EXTPA_EN (1<<4) /* 0 ext pa disable, 1 ext pa enabled */ ++#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) /* set drive out GPIO_CLK on sprom_cs pin */ ++#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) /* use sprom_cs pin as PCIE mdio interface */ ++#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) /* aband extpa will be at gpio2/5 and sprom_dout */ ++#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) /* override core control on pipe_AuxClkEnable */ ++#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /* override core control on pipe_AuxPowerDown */ ++#define CCTRL4331_PCIE_AUXCLKEN (1<<10) /* pcie_auxclkenable */ ++#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /* pcie_pipe_pllpowerdown */ ++#define CCTRL4331_EXTPA_EN2 (1<<12) /* 0 ext pa disable, 1 ext pa enabled */ ++#define CCTRL4331_EXT_LNA_A (1<<13) /* 0 disable */ ++#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */ ++#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */ ++#define CCTRL4331_EXTPA_ANA_EN (1<<24) /* 0 ext pa disable, 1 ext pa enabled */ ++ ++/* 4331 Chip specific ChipStatus register bits */ ++#define CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */ ++#define CST4331_SPROM_OTP_SEL_MASK 0x00000006 ++#define CST4331_SPROM_OTP_SEL_SHIFT 1 ++#define CST4331_SPROM_PRESENT 0x00000002 ++#define CST4331_OTP_PRESENT 0x00000004 ++#define CST4331_LDO_RF 0x00000008 ++#define CST4331_LDO_PAR 0x00000010 ++ ++/* 4315 resource */ ++#define RES4315_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4315_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4315_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4315_CLDO_PU 4 /* 0x00000010 */ ++#define RES4315_PALDO_PU 5 /* 0x00000020 */ ++#define RES4315_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4315_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4315_OTP_PU 10 /* 0x00000400 */ ++#define RES4315_LNLDO2_PU 12 /* 0x00001000 */ ++#define RES4315_XTAL_PU 13 /* 0x00002000 */ ++#define RES4315_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4315_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4315_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4315_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4315_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4315_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4315_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4315_HT_AVAIL 21 /* 0x00200000 */ ++ ++/* 4315 chip-specific ChipStatus register bits */ ++#define CST4315_SPROM_OTP_SEL_MASK 0x00000003 /* gpio [7:6], SDIO CIS selection */ ++#define CST4315_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */ ++#define CST4315_SPROM_SEL 0x00000001 /* use SPROM, OTP is powered up */ ++#define CST4315_OTP_SEL 0x00000002 /* use OTP, OTP is powered up */ ++#define CST4315_OTP_PWRDN 0x00000003 /* use SPROM, OTP is powered down */ ++#define CST4315_SDIO_MODE 0x00000004 /* gpio [8], sdio/usb mode */ ++#define CST4315_RCAL_VALID 0x00000008 ++#define CST4315_RCAL_VALUE_MASK 0x000001f0 ++#define CST4315_RCAL_VALUE_SHIFT 4 ++#define CST4315_PALDO_EXTPNP 0x00000200 /* PALDO is configured with external PNP */ ++#define CST4315_CBUCK_MODE_MASK 0x00000c00 ++#define CST4315_CBUCK_MODE_BURST 0x00000400 ++#define CST4315_CBUCK_MODE_LPBURST 0x00000c00 ++ ++/* 4319 resources */ ++#define RES4319_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4319_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4319_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4319_CLDO_PU 4 /* 0x00000010 */ ++#define RES4319_PALDO_PU 5 /* 0x00000020 */ ++#define RES4319_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4319_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4319_OTP_PU 10 /* 0x00000400 */ ++#define RES4319_LNLDO2_PU 12 /* 0x00001000 */ ++#define RES4319_XTAL_PU 13 /* 0x00002000 */ ++#define RES4319_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4319_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4319_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4319_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4319_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4319_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4319_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4319_HT_AVAIL 21 /* 0x00200000 */ ++ ++/* 4319 chip-specific ChipStatus register bits */ ++#define CST4319_SPI_CPULESSUSB 0x00000001 ++#define CST4319_SPI_CLK_POL 0x00000002 ++#define CST4319_SPI_CLK_PH 0x00000008 ++#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 /* gpio [7:6], SDIO CIS selection */ ++#define CST4319_SPROM_OTP_SEL_SHIFT 6 ++#define CST4319_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */ ++#define CST4319_SPROM_SEL 0x00000040 /* use SPROM, OTP is powered up */ ++#define CST4319_OTP_SEL 0x00000080 /* use OTP, OTP is powered up */ ++#define CST4319_OTP_PWRDN 0x000000c0 /* use SPROM, OTP is powered down */ ++#define CST4319_SDIO_USB_MODE 0x00000100 /* gpio [8], sdio/usb mode */ ++#define CST4319_REMAP_SEL_MASK 0x00000600 ++#define CST4319_ILPDIV_EN 0x00000800 ++#define CST4319_XTAL_PD_POL 0x00001000 ++#define CST4319_LPO_SEL 0x00002000 ++#define CST4319_RES_INIT_MODE 0x0000c000 ++#define CST4319_PALDO_EXTPNP 0x00010000 /* PALDO is configured with external PNP */ ++#define CST4319_CBUCK_MODE_MASK 0x00060000 ++#define CST4319_CBUCK_MODE_BURST 0x00020000 ++#define CST4319_CBUCK_MODE_LPBURST 0x00060000 ++#define CST4319_RCAL_VALID 0x01000000 ++#define CST4319_RCAL_VALUE_MASK 0x3e000000 ++#define CST4319_RCAL_VALUE_SHIFT 25 ++ ++#define PMU1_PLL0_CHIPCTL0 0 ++#define PMU1_PLL0_CHIPCTL1 1 ++#define PMU1_PLL0_CHIPCTL2 2 ++#define CCTL_4319USB_XTAL_SEL_MASK 0x00180000 ++#define CCTL_4319USB_XTAL_SEL_SHIFT 19 ++#define CCTL_4319USB_48MHZ_PLL_SEL 1 ++#define CCTL_4319USB_24MHZ_PLL_SEL 2 ++ ++/* PMU resources for 4336 */ ++#define RES4336_CBUCK_LPOM 0 ++#define RES4336_CBUCK_BURST 1 ++#define RES4336_CBUCK_LP_PWM 2 ++#define RES4336_CBUCK_PWM 3 ++#define RES4336_CLDO_PU 4 ++#define RES4336_DIS_INT_RESET_PD 5 ++#define RES4336_ILP_REQUEST 6 ++#define RES4336_LNLDO_PU 7 ++#define RES4336_LDO3P3_PU 8 ++#define RES4336_OTP_PU 9 ++#define RES4336_XTAL_PU 10 ++#define RES4336_ALP_AVAIL 11 ++#define RES4336_RADIO_PU 12 ++#define RES4336_BG_PU 13 ++#define RES4336_VREG1p4_PU_PU 14 ++#define RES4336_AFE_PWRSW_PU 15 ++#define RES4336_RX_PWRSW_PU 16 ++#define RES4336_TX_PWRSW_PU 17 ++#define RES4336_BB_PWRSW_PU 18 ++#define RES4336_SYNTH_PWRSW_PU 19 ++#define RES4336_MISC_PWRSW_PU 20 ++#define RES4336_LOGEN_PWRSW_PU 21 ++#define RES4336_BBPLL_PWRSW_PU 22 ++#define RES4336_MACPHY_CLKAVAIL 23 ++#define RES4336_HT_AVAIL 24 ++#define RES4336_RSVD 25 ++ ++/* 4336 chip-specific ChipStatus register bits */ ++#define CST4336_SPI_MODE_MASK 0x00000001 ++#define CST4336_SPROM_PRESENT 0x00000002 ++#define CST4336_OTP_PRESENT 0x00000004 ++#define CST4336_ARMREMAP_0 0x00000008 ++#define CST4336_ILPDIV_EN_MASK 0x00000010 ++#define CST4336_ILPDIV_EN_SHIFT 4 ++#define CST4336_XTAL_PD_POL_MASK 0x00000020 ++#define CST4336_XTAL_PD_POL_SHIFT 5 ++#define CST4336_LPO_SEL_MASK 0x00000040 ++#define CST4336_LPO_SEL_SHIFT 6 ++#define CST4336_RES_INIT_MODE_MASK 0x00000180 ++#define CST4336_RES_INIT_MODE_SHIFT 7 ++#define CST4336_CBUCK_MODE_MASK 0x00000600 ++#define CST4336_CBUCK_MODE_SHIFT 9 ++ ++/* 4336 Chip specific PMU ChipControl register bits */ ++#define PCTL_4336_SERIAL_ENAB (1 << 24) ++ ++/* 4330 resources */ ++#define RES4330_CBUCK_LPOM 0 ++#define RES4330_CBUCK_BURST 1 ++#define RES4330_CBUCK_LP_PWM 2 ++#define RES4330_CBUCK_PWM 3 ++#define RES4330_CLDO_PU 4 ++#define RES4330_DIS_INT_RESET_PD 5 ++#define RES4330_ILP_REQUEST 6 ++#define RES4330_LNLDO_PU 7 ++#define RES4330_LDO3P3_PU 8 ++#define RES4330_OTP_PU 9 ++#define RES4330_XTAL_PU 10 ++#define RES4330_ALP_AVAIL 11 ++#define RES4330_RADIO_PU 12 ++#define RES4330_BG_PU 13 ++#define RES4330_VREG1p4_PU_PU 14 ++#define RES4330_AFE_PWRSW_PU 15 ++#define RES4330_RX_PWRSW_PU 16 ++#define RES4330_TX_PWRSW_PU 17 ++#define RES4330_BB_PWRSW_PU 18 ++#define RES4330_SYNTH_PWRSW_PU 19 ++#define RES4330_MISC_PWRSW_PU 20 ++#define RES4330_LOGEN_PWRSW_PU 21 ++#define RES4330_BBPLL_PWRSW_PU 22 ++#define RES4330_MACPHY_CLKAVAIL 23 ++#define RES4330_HT_AVAIL 24 ++#define RES4330_5gRX_PWRSW_PU 25 ++#define RES4330_5gTX_PWRSW_PU 26 ++#define RES4330_5g_LOGEN_PWRSW_PU 27 ++ ++/* 4330 chip-specific ChipStatus register bits */ ++#define CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /* SDIO || gSPI */ ++#define CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /* USB || USBDA */ ++#define CST4330_CHIPMODE_SDIO(cs) (((cs) & 0x4) == 0) /* SDIO */ ++#define CST4330_CHIPMODE_GSPI(cs) (((cs) & 0x6) == 4) /* gSPI */ ++#define CST4330_CHIPMODE_USB(cs) (((cs) & 0x7) == 6) /* USB packet-oriented */ ++#define CST4330_CHIPMODE_USBDA(cs) (((cs) & 0x7) == 7) /* USB Direct Access */ ++#define CST4330_OTP_PRESENT 0x00000010 ++#define CST4330_LPO_AUTODET_EN 0x00000020 ++#define CST4330_ARMREMAP_0 0x00000040 ++#define CST4330_SPROM_PRESENT 0x00000080 /* takes priority over OTP if both set */ ++#define CST4330_ILPDIV_EN 0x00000100 ++#define CST4330_LPO_SEL 0x00000200 ++#define CST4330_RES_INIT_MODE_SHIFT 10 ++#define CST4330_RES_INIT_MODE_MASK 0x00000c00 ++#define CST4330_CBUCK_MODE_SHIFT 12 ++#define CST4330_CBUCK_MODE_MASK 0x00003000 ++#define CST4330_CBUCK_POWER_OK 0x00004000 ++#define CST4330_BB_PLL_LOCKED 0x00008000 ++#define SOCDEVRAM_BP_ADDR 0x1E000000 ++#define SOCDEVRAM_ARM_ADDR 0x00800000 ++ ++/* 4330 Chip specific PMU ChipControl register bits */ ++#define PCTL_4330_SERIAL_ENAB (1 << 24) ++ ++/* 4330 Chip specific ChipControl register bits */ ++#define CCTRL_4330_GPIO_SEL 0x00000001 /* 1=select GPIOs to be muxed out */ ++#define CCTRL_4330_ERCX_SEL 0x00000002 /* 1=select ERCX BT coex to be muxed out */ ++#define CCTRL_4330_SDIO_HOST_WAKE 0x00000004 /* SDIO: 1=configure GPIO0 for host wake */ ++#define CCTRL_4330_JTAG_DISABLE 0x00000008 /* 1=disable JTAG interface on mux'd pins */ ++ ++/* 4334 resources */ ++#define RES4334_LPLDO_PU 0 ++#define RES4334_RESET_PULLDN_DIS 1 ++#define RES4334_PMU_BG_PU 2 ++#define RES4334_HSIC_LDO_PU 3 ++#define RES4334_CBUCK_LPOM_PU 4 ++#define RES4334_CBUCK_PFM_PU 5 ++#define RES4334_CLDO_PU 6 ++#define RES4334_LPLDO2_LVM 7 ++#define RES4334_LNLDO_PU 8 ++#define RES4334_LDO3P3_PU 9 ++#define RES4334_OTP_PU 10 ++#define RES4334_XTAL_PU 11 ++#define RES4334_WL_PWRSW_PU 12 ++#define RES4334_LQ_AVAIL 13 ++#define RES4334_LOGIC_RET 14 ++#define RES4334_MEM_SLEEP 15 ++#define RES4334_MACPHY_RET 16 ++#define RES4334_WL_CORE_READY 17 ++#define RES4334_ILP_REQ 18 ++#define RES4334_ALP_AVAIL 19 ++#define RES4334_MISC_PWRSW_PU 20 ++#define RES4334_SYNTH_PWRSW_PU 21 ++#define RES4334_RX_PWRSW_PU 22 ++#define RES4334_RADIO_PU 23 ++#define RES4334_WL_PMU_PU 24 ++#define RES4334_VCO_LDO_PU 25 ++#define RES4334_AFE_LDO_PU 26 ++#define RES4334_RX_LDO_PU 27 ++#define RES4334_TX_LDO_PU 28 ++#define RES4334_HT_AVAIL 29 ++#define RES4334_MACPHY_CLK_AVAIL 30 ++ ++/* 4334 chip-specific ChipStatus register bits */ ++#define CST4334_CHIPMODE_MASK 7 ++#define CST4334_SDIO_MODE 0x00000000 ++#define CST4334_SPI_MODE 0x00000004 ++#define CST4334_HSIC_MODE 0x00000006 ++#define CST4334_BLUSB_MODE 0x00000007 ++#define CST4334_CHIPMODE_HSIC(cs) (((cs) & CST4334_CHIPMODE_MASK) == CST4334_HSIC_MODE) ++#define CST4334_OTP_PRESENT 0x00000010 ++#define CST4334_LPO_AUTODET_EN 0x00000020 ++#define CST4334_ARMREMAP_0 0x00000040 ++#define CST4334_SPROM_PRESENT 0x00000080 ++#define CST4334_ILPDIV_EN_MASK 0x00000100 ++#define CST4334_ILPDIV_EN_SHIFT 8 ++#define CST4334_LPO_SEL_MASK 0x00000200 ++#define CST4334_LPO_SEL_SHIFT 9 ++#define CST4334_RES_INIT_MODE_MASK 0x00000C00 ++#define CST4334_RES_INIT_MODE_SHIFT 10 ++ ++/* 4334 Chip specific PMU ChipControl register bits */ ++#define PCTL_4334_GPIO3_ENAB (1 << 3) ++ ++/* 4334 Chip control */ ++#define CCTRL4334_HSIC_LDO_PU (1 << 23) ++ ++/* 4324 Chip specific ChipControl1 register bits */ ++#define CCTRL1_4324_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ ++#define CCTRL1_4324_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ ++ ++ ++/* 4313 resources */ ++#define RES4313_BB_PU_RSRC 0 ++#define RES4313_ILP_REQ_RSRC 1 ++#define RES4313_XTAL_PU_RSRC 2 ++#define RES4313_ALP_AVAIL_RSRC 3 ++#define RES4313_RADIO_PU_RSRC 4 ++#define RES4313_BG_PU_RSRC 5 ++#define RES4313_VREG1P4_PU_RSRC 6 ++#define RES4313_AFE_PWRSW_RSRC 7 ++#define RES4313_RX_PWRSW_RSRC 8 ++#define RES4313_TX_PWRSW_RSRC 9 ++#define RES4313_BB_PWRSW_RSRC 10 ++#define RES4313_SYNTH_PWRSW_RSRC 11 ++#define RES4313_MISC_PWRSW_RSRC 12 ++#define RES4313_BB_PLL_PWRSW_RSRC 13 ++#define RES4313_HT_AVAIL_RSRC 14 ++#define RES4313_MACPHY_CLK_AVAIL_RSRC 15 ++ ++/* 4313 chip-specific ChipStatus register bits */ ++#define CST4313_SPROM_PRESENT 1 ++#define CST4313_OTP_PRESENT 2 ++#define CST4313_SPROM_OTP_SEL_MASK 0x00000002 ++#define CST4313_SPROM_OTP_SEL_SHIFT 0 ++ ++/* 4313 Chip specific ChipControl register bits */ ++#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */ ++ ++/* PMU respources for 4314 */ ++#define RES4314_LPLDO_PU 0 ++#define RES4314_PMU_SLEEP_DIS 1 ++#define RES4314_PMU_BG_PU 2 ++#define RES4314_CBUCK_LPOM_PU 3 ++#define RES4314_CBUCK_PFM_PU 4 ++#define RES4314_CLDO_PU 5 ++#define RES4314_LPLDO2_LVM 6 ++#define RES4314_WL_PMU_PU 7 ++#define RES4314_LNLDO_PU 8 ++#define RES4314_LDO3P3_PU 9 ++#define RES4314_OTP_PU 10 ++#define RES4314_XTAL_PU 11 ++#define RES4314_WL_PWRSW_PU 12 ++#define RES4314_LQ_AVAIL 13 ++#define RES4314_LOGIC_RET 14 ++#define RES4314_MEM_SLEEP 15 ++#define RES4314_MACPHY_RET 16 ++#define RES4314_WL_CORE_READY 17 ++#define RES4314_ILP_REQ 18 ++#define RES4314_ALP_AVAIL 19 ++#define RES4314_MISC_PWRSW_PU 20 ++#define RES4314_SYNTH_PWRSW_PU 21 ++#define RES4314_RX_PWRSW_PU 22 ++#define RES4314_RADIO_PU 23 ++#define RES4314_VCO_LDO_PU 24 ++#define RES4314_AFE_LDO_PU 25 ++#define RES4314_RX_LDO_PU 26 ++#define RES4314_TX_LDO_PU 27 ++#define RES4314_HT_AVAIL 28 ++#define RES4314_MACPHY_CLK_AVAIL 29 ++ ++/* 4314 chip-specific ChipStatus register bits */ ++#define CST4314_OTP_ENABLED 0x00200000 ++ ++/* 43228 resources */ ++#define RES43228_NOT_USED 0 ++#define RES43228_ILP_REQUEST 1 ++#define RES43228_XTAL_PU 2 ++#define RES43228_ALP_AVAIL 3 ++#define RES43228_PLL_EN 4 ++#define RES43228_HT_PHY_AVAIL 5 ++ ++/* 43228 chipstatus reg bits */ ++#define CST43228_ILP_DIV_EN 0x1 ++#define CST43228_OTP_PRESENT 0x2 ++#define CST43228_SERDES_REFCLK_PADSEL 0x4 ++#define CST43228_SDIO_MODE 0x8 ++#define CST43228_SDIO_OTP_PRESENT 0x10 ++#define CST43228_SDIO_RESET 0x20 ++ ++/* 4706 chipstatus reg bits */ ++#define CST4706_PKG_OPTION (1<<0) /* 0: full-featured package 1: low-cost package */ ++#define CST4706_SFLASH_PRESENT (1<<1) /* 0: parallel, 1: serial flash is present */ ++#define CST4706_SFLASH_TYPE (1<<2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */ ++#define CST4706_MIPS_BENDIAN (1<<3) /* 0: little, 1: big endian */ ++#define CST4706_PCIE1_DISABLE (1<<5) /* PCIE1 enable strap pin */ ++ ++/* 4706 flashstrconfig reg bits */ ++#define FLSTRCF4706_MASK 0x000000ff ++#define FLSTRCF4706_SF1 0x00000001 /* 2nd serial flash present */ ++#define FLSTRCF4706_PF1 0x00000002 /* 2nd parallel flash present */ ++#define FLSTRCF4706_SF1_TYPE 0x00000004 /* 2nd serial flash type : 0 : ST, 1 : Atmel */ ++#define FLSTRCF4706_NF1 0x00000008 /* 2nd NAND flash present */ ++#define FLSTRCF4706_1ST_MADDR_SEG_MASK 0x000000f0 /* Valid value mask */ ++#define FLSTRCF4706_1ST_MADDR_SEG_4MB 0x00000010 /* 4MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_8MB 0x00000020 /* 8MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_16MB 0x00000030 /* 16MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_32MB 0x00000040 /* 32MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_64MB 0x00000050 /* 64MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_128MB 0x00000060 /* 128MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_256MB 0x00000070 /* 256MB */ ++ ++/* 4360 Chip specific ChipControl register bits */ ++#define CCTRL4360_SECI_MODE (1 << 2) ++#define CCTRL4360_BTSWCTRL_MODE (1 << 3) ++#define CCTRL4360_EXTRA_FEMCTRL_MODE (1 << 8) ++#define CCTRL4360_BT_LGCY_MODE (1 << 9) ++#define CCTRL4360_CORE2FEMCTRL4_ON (1 << 21) ++ ++/* 4360 PMU resources and chip status bits */ ++#define RES4360_REGULATOR 0 ++#define RES4360_ILP_AVAIL 1 ++#define RES4360_ILP_REQ 2 ++#define RES4360_XTAL_PU 3 ++#define RES4360_ALP_AVAIL 4 ++#define RES4360_BBPLLPWRSW_PU 5 ++#define RES4360_HT_AVAIL 6 ++#define RES4360_OTP_PU 7 ++#define RES4360_USBLDO_PU 8 ++#define RES4360_USBPLL_PWRSW_PU 9 ++#define RES4360_LQ_AVAIL 10 ++ ++#define CST4360_XTAL_40MZ 0x00000001 ++#define CST4360_SFLASH 0x00000002 ++#define CST4360_SPROM_PRESENT 0x00000004 ++#define CST4360_SFLASH_TYPE 0x00000004 ++#define CST4360_OTP_ENABLED 0x00000008 ++#define CST4360_REMAP_ROM 0x00000010 ++#define CST4360_RSRC_INIT_MODE_MASK 0x00000060 ++#define CST4360_RSRC_INIT_MODE_SHIFT 5 ++#define CST4360_ILP_DIVEN 0x00000080 ++#define CST4360_MODE_USB 0x00000100 ++#define CST4360_SPROM_SIZE_MASK 0x00000600 ++#define CST4360_SPROM_SIZE_SHIFT 9 ++#define CST4360_BBPLL_LOCK 0x00000800 ++#define CST4360_AVBBPLL_LOCK 0x00001000 ++#define CST4360_USBBBPLL_LOCK 0x00002000 ++ ++#define CCTL_4360_UART_SEL 2 ++ ++/* 4335 resources */ ++#define RES4335_LPLDO_PO 0 ++#define RES4335_PMU_BG_PU 1 ++#define RES4335_PMU_SLEEP 2 ++#define RES4335_RSVD_3 3 ++#define RES4335_CBUCK_LPOM_PU 4 ++#define RES4335_CBUCK_PFM_PU 5 ++#define RES4335_RSVD_6 6 ++#define RES4335_RSVD_7 7 ++#define RES4335_LNLDO_PU 8 ++#define RES4335_XTALLDO_PU 9 ++#define RES4335_LDO3P3_PU 10 ++#define RES4335_OTP_PU 11 ++#define RES4335_XTAL_PU 12 ++#define RES4335_SR_CLK_START 13 ++#define RES4335_LQ_AVAIL 14 ++#define RES4335_LQ_START 15 ++#define RES4335_RSVD_16 16 ++#define RES4335_WL_CORE_RDY 17 ++#define RES4335_ILP_REQ 18 ++#define RES4335_ALP_AVAIL 19 ++#define RES4335_MINI_PMU 20 ++#define RES4335_RADIO_PU 21 ++#define RES4335_SR_CLK_STABLE 22 ++#define RES4335_SR_SAVE_RESTORE 23 ++#define RES4335_SR_PHY_PWRSW 24 ++#define RES4335_SR_VDDM_PWRSW 25 ++#define RES4335_SR_SUBCORE_PWRSW 26 ++#define RES4335_SR_SLEEP 27 ++#define RES4335_HT_START 28 ++#define RES4335_HT_AVAIL 29 ++#define RES4335_MACPHY_CLKAVAIL 30 ++ ++/* 4335 Chip specific ChipStatus register bits */ ++#define CST4335_SPROM_MASK 0x00000020 ++#define CST4335_SFLASH_MASK 0x00000040 ++#define CST4335_RES_INIT_MODE_SHIFT 7 ++#define CST4335_RES_INIT_MODE_MASK 0x00000180 ++#define CST4335_CHIPMODE_MASK 0xF ++#define CST4335_CHIPMODE_SDIOD(cs) (((cs) & (1 << 0)) != 0) /* SDIO */ ++#define CST4335_CHIPMODE_GSPI(cs) (((cs) & (1 << 1)) != 0) /* gSPI */ ++#define CST4335_CHIPMODE_USB20D(cs) (((cs) & (1 << 2)) != 0) /* USB || USBDA */ ++#define CST4335_CHIPMODE_PCIE(cs) (((cs) & (1 << 3)) != 0) /* PCIE */ ++ ++/* 4335 Chip specific ChipControl1 register bits */ ++#define CCTRL1_4335_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ ++#define CCTRL1_4335_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ ++ ++ ++#define CR4_RAM_BASE (0x180000) ++#define PATCHTBL_SIZE (0x800) ++ ++ ++/* 4335 resources--END */ ++ ++/* GCI chipcontrol register indices */ ++#define CC_GCI_CHIPCTRL_00 (0) ++#define CC_GCI_CHIPCTRL_01 (1) ++#define CC_GCI_CHIPCTRL_02 (2) ++#define CC_GCI_CHIPCTRL_03 (3) ++#define CC_GCI_CHIPCTRL_04 (4) ++#define CC_GCI_CHIPCTRL_05 (5) ++#define CC_GCI_CHIPCTRL_06 (6) ++#define CC_GCI_CHIPCTRL_07 (7) ++#define CC_GCI_CHIPCTRL_08 (8) ++ ++#define CC_GCI_NUMCHIPCTRLREGS(cap1) ((cap1 & 0xF00) >> 8) ++ ++/* 4335 pins ++* note: only the values set as default/used are added here. ++*/ ++#define CC4335_PIN_GPIO_00 (0) ++#define CC4335_PIN_GPIO_01 (1) ++#define CC4335_PIN_GPIO_02 (2) ++#define CC4335_PIN_GPIO_03 (3) ++#define CC4335_PIN_GPIO_04 (4) ++#define CC4335_PIN_GPIO_05 (5) ++#define CC4335_PIN_GPIO_06 (6) ++#define CC4335_PIN_GPIO_07 (7) ++#define CC4335_PIN_GPIO_08 (8) ++#define CC4335_PIN_GPIO_09 (9) ++#define CC4335_PIN_GPIO_10 (10) ++#define CC4335_PIN_GPIO_11 (11) ++#define CC4335_PIN_GPIO_12 (12) ++#define CC4335_PIN_GPIO_13 (13) ++#define CC4335_PIN_GPIO_14 (14) ++#define CC4335_PIN_GPIO_15 (15) ++#define CC4335_PIN_SDIO_CLK (16) ++#define CC4335_PIN_SDIO_CMD (17) ++#define CC4335_PIN_SDIO_DATA0 (18) ++#define CC4335_PIN_SDIO_DATA1 (19) ++#define CC4335_PIN_SDIO_DATA2 (20) ++#define CC4335_PIN_SDIO_DATA3 (21) ++#define CC4335_PIN_RF_SW_CTRL_0 (22) ++#define CC4335_PIN_RF_SW_CTRL_1 (23) ++#define CC4335_PIN_RF_SW_CTRL_2 (24) ++#define CC4335_PIN_RF_SW_CTRL_3 (25) ++#define CC4335_PIN_RF_SW_CTRL_4 (26) ++#define CC4335_PIN_RF_SW_CTRL_5 (27) ++#define CC4335_PIN_RF_SW_CTRL_6 (28) ++#define CC4335_PIN_RF_SW_CTRL_7 (29) ++#define CC4335_PIN_RF_SW_CTRL_8 (30) ++#define CC4335_PIN_RF_SW_CTRL_9 (31) ++ ++/* 4335 GCI function sel values ++*/ ++#define CC4335_FNSEL_HWDEF (0) ++#define CC4335_FNSEL_SAMEASPIN (1) ++#define CC4335_FNSEL_GPIO0 (2) ++#define CC4335_FNSEL_GPIO1 (3) ++#define CC4335_FNSEL_GCI0 (4) ++#define CC4335_FNSEL_GCI1 (5) ++#define CC4335_FNSEL_UART (6) ++#define CC4335_FNSEL_SFLASH (7) ++#define CC4335_FNSEL_SPROM (8) ++#define CC4335_FNSEL_MISC0 (9) ++#define CC4335_FNSEL_MISC1 (10) ++#define CC4335_FNSEL_MISC2 (11) ++#define CC4335_FNSEL_IND (12) ++#define CC4335_FNSEL_PDN (13) ++#define CC4335_FNSEL_PUP (14) ++#define CC4335_FNSEL_TRI (15) ++ ++/* find the 4 bit mask given the bit position */ ++#define GCIMASK(pos) (((uint32)0xF) << pos) ++ ++/* get the value which can be used to directly OR with chipcontrol reg */ ++#define GCIPOSVAL(val, pos) ((((uint32)val) << pos) & GCIMASK(pos)) ++ ++/* 4335 MUX options. each nibble belongs to a setting. Non-zero value specifies a logic ++* for now only UART for bootloader. ++*/ ++#define MUXENAB4335_UART_MASK (0x0000000f) ++ ++ ++/* defines to detect active host interface in use */ ++#define CHIP_HOSTIF_USB(sih) (si_chip_hostif(sih) & CST4360_MODE_USB) ++ ++/* ++* Maximum delay for the PMU state transition in us. ++* This is an upper bound intended for spinwaits etc. ++*/ ++#define PMU_MAX_TRANSITION_DLY 20000 ++ ++/* PMU resource up transition time in ILP cycles */ ++#define PMURES_UP_TRANSITION 2 ++ ++/* ++* Information from BT to WLAN over eci_inputlo, eci_inputmi & ++* eci_inputhi register. Rev >=21 ++*/ ++/* Fields in eci_inputlo register - [0:31] */ ++#define ECI_INLO_TASKTYPE_MASK 0x0000000f /* [3:0] - 4 bits */ ++#define ECI_INLO_TASKTYPE_SHIFT 0 ++#define ECI_INLO_PKTDUR_MASK 0x000000f0 /* [7:4] - 4 bits */ ++#define ECI_INLO_PKTDUR_SHIFT 4 ++#define ECI_INLO_ROLE_MASK 0x00000100 /* [8] - 1 bits */ ++#define ECI_INLO_ROLE_SHIFT 8 ++#define ECI_INLO_MLP_MASK 0x00000e00 /* [11:9] - 3 bits */ ++#define ECI_INLO_MLP_SHIFT 9 ++#define ECI_INLO_TXPWR_MASK 0x000ff000 /* [19:12] - 8 bits */ ++#define ECI_INLO_TXPWR_SHIFT 12 ++#define ECI_INLO_RSSI_MASK 0x0ff00000 /* [27:20] - 8 bits */ ++#define ECI_INLO_RSSI_SHIFT 20 ++#define ECI_INLO_VAD_MASK 0x10000000 /* [28] - 1 bits */ ++#define ECI_INLO_VAD_SHIFT 28 ++ ++/* ++* Register eci_inputlo bitfield values. ++* - BT packet type information bits [7:0] ++*/ ++/* [3:0] - Task (link) type */ ++#define BT_ACL 0x00 ++#define BT_SCO 0x01 ++#define BT_eSCO 0x02 ++#define BT_A2DP 0x03 ++#define BT_SNIFF 0x04 ++#define BT_PAGE_SCAN 0x05 ++#define BT_INQUIRY_SCAN 0x06 ++#define BT_PAGE 0x07 ++#define BT_INQUIRY 0x08 ++#define BT_MSS 0x09 ++#define BT_PARK 0x0a ++#define BT_RSSISCAN 0x0b ++#define BT_MD_ACL 0x0c ++#define BT_MD_eSCO 0x0d ++#define BT_SCAN_WITH_SCO_LINK 0x0e ++#define BT_SCAN_WITHOUT_SCO_LINK 0x0f ++/* [7:4] = packet duration code */ ++/* [8] - Master / Slave */ ++#define BT_MASTER 0 ++#define BT_SLAVE 1 ++/* [11:9] - multi-level priority */ ++#define BT_LOWEST_PRIO 0x0 ++#define BT_HIGHEST_PRIO 0x3 ++/* [19:12] - BT transmit power */ ++/* [27:20] - BT RSSI */ ++/* [28] - VAD silence */ ++/* [31:29] - Undefined */ ++/* Register eci_inputmi values - [32:63] - none defined */ ++/* [63:32] - Undefined */ ++ ++/* Information from WLAN to BT over eci_output register. */ ++/* Fields in eci_output register - [0:31] */ ++#define ECI48_OUT_MASKMAGIC_HIWORD 0x55550000 ++#define ECI_OUT_CHANNEL_MASK(ccrev) ((ccrev) < 35 ? 0xf : (ECI48_OUT_MASKMAGIC_HIWORD | 0xf000)) ++#define ECI_OUT_CHANNEL_SHIFT(ccrev) ((ccrev) < 35 ? 0 : 12) ++#define ECI_OUT_BW_MASK(ccrev) ((ccrev) < 35 ? 0x70 : (ECI48_OUT_MASKMAGIC_HIWORD | 0xe00)) ++#define ECI_OUT_BW_SHIFT(ccrev) ((ccrev) < 35 ? 4 : 9) ++#define ECI_OUT_ANTENNA_MASK(ccrev) ((ccrev) < 35 ? 0x80 : (ECI48_OUT_MASKMAGIC_HIWORD | 0x100)) ++#define ECI_OUT_ANTENNA_SHIFT(ccrev) ((ccrev) < 35 ? 7 : 8) ++#define ECI_OUT_SIMUL_TXRX_MASK(ccrev) \ ++ ((ccrev) < 35 ? 0x10000 : (ECI48_OUT_MASKMAGIC_HIWORD | 0x80)) ++#define ECI_OUT_SIMUL_TXRX_SHIFT(ccrev) ((ccrev) < 35 ? 16 : 7) ++#define ECI_OUT_FM_DISABLE_MASK(ccrev) \ ++ ((ccrev) < 35 ? 0x40000 : (ECI48_OUT_MASKMAGIC_HIWORD | 0x40)) ++#define ECI_OUT_FM_DISABLE_SHIFT(ccrev) ((ccrev) < 35 ? 18 : 6) ++ ++/* Indicate control of ECI bits between s/w and dot11mac. ++ * 0 => FW control, 1=> MAC/ucode control ++ ++ * Current assignment (ccrev >= 35): ++ * 0 - TxConf (ucode) ++ * 38 - FM disable (wl) ++ * 39 - Allow sim rx (ucode) ++ * 40 - Num antennas (wl) ++ * 43:41 - WLAN channel exclusion BW (wl) ++ * 47:44 - WLAN channel (wl) ++ * ++ * (ccrev < 35) ++ * 15:0 - wl ++ * 16 - ++ * 18 - FM disable ++ * 30 - wl interrupt ++ * 31 - ucode interrupt ++ * others - unassigned (presumed to be with dot11mac/ucode) ++ */ ++#define ECI_MACCTRL_BITS 0xbffb0000 ++#define ECI_MACCTRLLO_BITS 0x1 ++#define ECI_MACCTRLHI_BITS 0xFF ++ ++ ++/* SECI configuration */ ++#define SECI_MODE_UART 0x0 ++#define SECI_MODE_SECI 0x1 ++#define SECI_MODE_LEGACY_3WIRE_BT 0x2 ++#define SECI_MODE_LEGACY_3WIRE_WLAN 0x3 ++#define SECI_MODE_HALF_SECI 0x4 ++ ++#define SECI_RESET (1 << 0) ++#define SECI_RESET_BAR_UART (1 << 1) ++#define SECI_ENAB_SECI_ECI (1 << 2) ++#define SECI_ENAB_SECIOUT_DIS (1 << 3) ++#define SECI_MODE_MASK 0x7 ++#define SECI_MODE_SHIFT 4 /* (bits 5, 6, 7) */ ++#define SECI_UPD_SECI (1 << 7) ++ ++#define SECI_SIGNOFF_0 0xDB ++#define SECI_SIGNOFF_1 0 ++ ++/* seci clk_ctl_st bits */ ++#define CLKCTL_STS_SECI_CLK_REQ (1 << 8) ++#define CLKCTL_STS_SECI_CLK_AVAIL (1 << 24) ++ ++#define SECI_UART_MSR_CTS_STATE (1 << 0) ++#define SECI_UART_MSR_RTS_STATE (1 << 1) ++#define SECI_UART_SECI_IN_STATE (1 << 2) ++#define SECI_UART_SECI_IN2_STATE (1 << 3) ++ ++/* SECI UART LCR/MCR register bits */ ++#define SECI_UART_LCR_STOP_BITS (1 << 0) /* 0 - 1bit, 1 - 2bits */ ++#define SECI_UART_LCR_PARITY_EN (1 << 1) ++#define SECI_UART_LCR_PARITY (1 << 2) /* 0 - odd, 1 - even */ ++#define SECI_UART_LCR_RX_EN (1 << 3) ++#define SECI_UART_LCR_LBRK_CTRL (1 << 4) /* 1 => SECI_OUT held low */ ++#define SECI_UART_LCR_TXO_EN (1 << 5) ++#define SECI_UART_LCR_RTSO_EN (1 << 6) ++#define SECI_UART_LCR_SLIPMODE_EN (1 << 7) ++#define SECI_UART_LCR_RXCRC_CHK (1 << 8) ++#define SECI_UART_LCR_TXCRC_INV (1 << 9) ++#define SECI_UART_LCR_TXCRC_LSBF (1 << 10) ++#define SECI_UART_LCR_TXCRC_EN (1 << 11) ++ ++#define SECI_UART_MCR_TX_EN (1 << 0) ++#define SECI_UART_MCR_PRTS (1 << 1) ++#define SECI_UART_MCR_SWFLCTRL_EN (1 << 2) ++#define SECI_UART_MCR_HIGHRATE_EN (1 << 3) ++#define SECI_UART_MCR_LOOPBK_EN (1 << 4) ++#define SECI_UART_MCR_AUTO_RTS (1 << 5) ++#define SECI_UART_MCR_AUTO_TX_DIS (1 << 6) ++#define SECI_UART_MCR_BAUD_ADJ_EN (1 << 7) ++#define SECI_UART_MCR_XONOFF_RPT (1 << 9) ++ ++/* WLAN channel numbers - used from wifi.h */ ++ ++/* WLAN BW */ ++#define ECI_BW_20 0x0 ++#define ECI_BW_25 0x1 ++#define ECI_BW_30 0x2 ++#define ECI_BW_35 0x3 ++#define ECI_BW_40 0x4 ++#define ECI_BW_45 0x5 ++#define ECI_BW_50 0x6 ++#define ECI_BW_ALL 0x7 ++ ++/* WLAN - number of antenna */ ++#define WLAN_NUM_ANT1 TXANT_0 ++#define WLAN_NUM_ANT2 TXANT_1 ++ ++#endif /* _SBCHIPC_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbconfig.h b/drivers/bcmdrivers/gmac/src/include/sbconfig.h +new file mode 100755 +index 0000000..cd13ce6 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbconfig.h +@@ -0,0 +1,276 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom SiliconBackplane hardware register definitions. ++ * ++ * $Id: sbconfig.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _SBCONFIG_H ++#define _SBCONFIG_H ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif ++ ++/* enumeration in SB is based on the premise that cores are contiguos in the ++ * enumeration space. ++ */ ++#define SB_BUS_SIZE 0x10000 /* Each bus gets 64Kbytes for cores */ ++#define SB_BUS_BASE(b) (SI_ENUM_BASE + (b) * SB_BUS_SIZE) ++#define SB_BUS_MAXCORES (SB_BUS_SIZE / SI_CORE_SIZE) /* Max cores per bus */ ++ ++/* ++ * Sonics Configuration Space Registers. ++ */ ++#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */ ++#define SBCONFIGSIZE 256 /* sizeof (sbconfig_t) */ ++ ++#define SBIPSFLAG 0x08 ++#define SBTPSFLAG 0x18 ++#define SBTMERRLOGA 0x48 /* sonics >= 2.3 */ ++#define SBTMERRLOG 0x50 /* sonics >= 2.3 */ ++#define SBADMATCH3 0x60 ++#define SBADMATCH2 0x68 ++#define SBADMATCH1 0x70 ++#define SBIMSTATE 0x90 ++#define SBINTVEC 0x94 ++#define SBTMSTATELOW 0x98 ++#define SBTMSTATEHIGH 0x9c ++#define SBBWA0 0xa0 ++#define SBIMCONFIGLOW 0xa8 ++#define SBIMCONFIGHIGH 0xac ++#define SBADMATCH0 0xb0 ++#define SBTMCONFIGLOW 0xb8 ++#define SBTMCONFIGHIGH 0xbc ++#define SBBCONFIG 0xc0 ++#define SBBSTATE 0xc8 ++#define SBACTCNFG 0xd8 ++#define SBFLAGST 0xe8 ++#define SBIDLOW 0xf8 ++#define SBIDHIGH 0xfc ++ ++/* All the previous registers are above SBCONFIGOFF, but with Sonics 2.3, we have ++ * a few registers *below* that line. I think it would be very confusing to try ++ * and change the value of SBCONFIGOFF, so I'm definig them as absolute offsets here, ++ */ ++ ++#define SBIMERRLOGA 0xea8 ++#define SBIMERRLOG 0xeb0 ++#define SBTMPORTCONNID0 0xed8 ++#define SBTMPORTLOCK0 0xef8 ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++typedef volatile struct _sbconfig { ++ uint32 PAD[2]; ++ uint32 sbipsflag; /* initiator port ocp slave flag */ ++ uint32 PAD[3]; ++ uint32 sbtpsflag; /* target port ocp slave flag */ ++ uint32 PAD[11]; ++ uint32 sbtmerrloga; /* (sonics >= 2.3) */ ++ uint32 PAD; ++ uint32 sbtmerrlog; /* (sonics >= 2.3) */ ++ uint32 PAD[3]; ++ uint32 sbadmatch3; /* address match3 */ ++ uint32 PAD; ++ uint32 sbadmatch2; /* address match2 */ ++ uint32 PAD; ++ uint32 sbadmatch1; /* address match1 */ ++ uint32 PAD[7]; ++ uint32 sbimstate; /* initiator agent state */ ++ uint32 sbintvec; /* interrupt mask */ ++ uint32 sbtmstatelow; /* target state */ ++ uint32 sbtmstatehigh; /* target state */ ++ uint32 sbbwa0; /* bandwidth allocation table0 */ ++ uint32 PAD; ++ uint32 sbimconfiglow; /* initiator configuration */ ++ uint32 sbimconfighigh; /* initiator configuration */ ++ uint32 sbadmatch0; /* address match0 */ ++ uint32 PAD; ++ uint32 sbtmconfiglow; /* target configuration */ ++ uint32 sbtmconfighigh; /* target configuration */ ++ uint32 sbbconfig; /* broadcast configuration */ ++ uint32 PAD; ++ uint32 sbbstate; /* broadcast state */ ++ uint32 PAD[3]; ++ uint32 sbactcnfg; /* activate configuration */ ++ uint32 PAD[3]; ++ uint32 sbflagst; /* current sbflags */ ++ uint32 PAD[3]; ++ uint32 sbidlow; /* identification */ ++ uint32 sbidhigh; /* identification */ ++} sbconfig_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* sbipsflag */ ++#define SBIPS_INT1_MASK 0x3f /* which sbflags get routed to mips interrupt 1 */ ++#define SBIPS_INT1_SHIFT 0 ++#define SBIPS_INT2_MASK 0x3f00 /* which sbflags get routed to mips interrupt 2 */ ++#define SBIPS_INT2_SHIFT 8 ++#define SBIPS_INT3_MASK 0x3f0000 /* which sbflags get routed to mips interrupt 3 */ ++#define SBIPS_INT3_SHIFT 16 ++#define SBIPS_INT4_MASK 0x3f000000 /* which sbflags get routed to mips interrupt 4 */ ++#define SBIPS_INT4_SHIFT 24 ++ ++/* sbtpsflag */ ++#define SBTPS_NUM0_MASK 0x3f /* interrupt sbFlag # generated by this core */ ++#define SBTPS_F0EN0 0x40 /* interrupt is always sent on the backplane */ ++ ++/* sbtmerrlog */ ++#define SBTMEL_CM 0x00000007 /* command */ ++#define SBTMEL_CI 0x0000ff00 /* connection id */ ++#define SBTMEL_EC 0x0f000000 /* error code */ ++#define SBTMEL_ME 0x80000000 /* multiple error */ ++ ++/* sbimstate */ ++#define SBIM_PC 0xf /* pipecount */ ++#define SBIM_AP_MASK 0x30 /* arbitration policy */ ++#define SBIM_AP_BOTH 0x00 /* use both timeslaces and token */ ++#define SBIM_AP_TS 0x10 /* use timesliaces only */ ++#define SBIM_AP_TK 0x20 /* use token only */ ++#define SBIM_AP_RSV 0x30 /* reserved */ ++#define SBIM_IBE 0x20000 /* inbanderror */ ++#define SBIM_TO 0x40000 /* timeout */ ++#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */ ++#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */ ++ ++/* sbtmstatelow */ ++#define SBTML_RESET 0x0001 /* reset */ ++#define SBTML_REJ_MASK 0x0006 /* reject field */ ++#define SBTML_REJ 0x0002 /* reject */ ++#define SBTML_TMPREJ 0x0004 /* temporary reject, for error recovery */ ++ ++#define SBTML_SICF_SHIFT 16 /* Shift to locate the SI control flags in sbtml */ ++ ++/* sbtmstatehigh */ ++#define SBTMH_SERR 0x0001 /* serror */ ++#define SBTMH_INT 0x0002 /* interrupt */ ++#define SBTMH_BUSY 0x0004 /* busy */ ++#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */ ++ ++#define SBTMH_SISF_SHIFT 16 /* Shift to locate the SI status flags in sbtmh */ ++ ++/* sbbwa0 */ ++#define SBBWA_TAB0_MASK 0xffff /* lookup table 0 */ ++#define SBBWA_TAB1_MASK 0xffff /* lookup table 1 */ ++#define SBBWA_TAB1_SHIFT 16 ++ ++/* sbimconfiglow */ ++#define SBIMCL_STO_MASK 0x7 /* service timeout */ ++#define SBIMCL_RTO_MASK 0x70 /* request timeout */ ++#define SBIMCL_RTO_SHIFT 4 ++#define SBIMCL_CID_MASK 0xff0000 /* connection id */ ++#define SBIMCL_CID_SHIFT 16 ++ ++/* sbimconfighigh */ ++#define SBIMCH_IEM_MASK 0xc /* inband error mode */ ++#define SBIMCH_TEM_MASK 0x30 /* timeout error mode */ ++#define SBIMCH_TEM_SHIFT 4 ++#define SBIMCH_BEM_MASK 0xc0 /* bus error mode */ ++#define SBIMCH_BEM_SHIFT 6 ++ ++/* sbadmatch0 */ ++#define SBAM_TYPE_MASK 0x3 /* address type */ ++#define SBAM_AD64 0x4 /* reserved */ ++#define SBAM_ADINT0_MASK 0xf8 /* type0 size */ ++#define SBAM_ADINT0_SHIFT 3 ++#define SBAM_ADINT1_MASK 0x1f8 /* type1 size */ ++#define SBAM_ADINT1_SHIFT 3 ++#define SBAM_ADINT2_MASK 0x1f8 /* type2 size */ ++#define SBAM_ADINT2_SHIFT 3 ++#define SBAM_ADEN 0x400 /* enable */ ++#define SBAM_ADNEG 0x800 /* negative decode */ ++#define SBAM_BASE0_MASK 0xffffff00 /* type0 base address */ ++#define SBAM_BASE0_SHIFT 8 ++#define SBAM_BASE1_MASK 0xfffff000 /* type1 base address for the core */ ++#define SBAM_BASE1_SHIFT 12 ++#define SBAM_BASE2_MASK 0xffff0000 /* type2 base address for the core */ ++#define SBAM_BASE2_SHIFT 16 ++ ++/* sbtmconfiglow */ ++#define SBTMCL_CD_MASK 0xff /* clock divide */ ++#define SBTMCL_CO_MASK 0xf800 /* clock offset */ ++#define SBTMCL_CO_SHIFT 11 ++#define SBTMCL_IF_MASK 0xfc0000 /* interrupt flags */ ++#define SBTMCL_IF_SHIFT 18 ++#define SBTMCL_IM_MASK 0x3000000 /* interrupt mode */ ++#define SBTMCL_IM_SHIFT 24 ++ ++/* sbtmconfighigh */ ++#define SBTMCH_BM_MASK 0x3 /* busy mode */ ++#define SBTMCH_RM_MASK 0x3 /* retry mode */ ++#define SBTMCH_RM_SHIFT 2 ++#define SBTMCH_SM_MASK 0x30 /* stop mode */ ++#define SBTMCH_SM_SHIFT 4 ++#define SBTMCH_EM_MASK 0x300 /* sb error mode */ ++#define SBTMCH_EM_SHIFT 8 ++#define SBTMCH_IM_MASK 0xc00 /* int mode */ ++#define SBTMCH_IM_SHIFT 10 ++ ++/* sbbconfig */ ++#define SBBC_LAT_MASK 0x3 /* sb latency */ ++#define SBBC_MAX0_MASK 0xf0000 /* maxccntr0 */ ++#define SBBC_MAX0_SHIFT 16 ++#define SBBC_MAX1_MASK 0xf00000 /* maxccntr1 */ ++#define SBBC_MAX1_SHIFT 20 ++ ++/* sbbstate */ ++#define SBBS_SRD 0x1 /* st reg disable */ ++#define SBBS_HRD 0x2 /* hold reg disable */ ++ ++/* sbidlow */ ++#define SBIDL_CS_MASK 0x3 /* config space */ ++#define SBIDL_AR_MASK 0x38 /* # address ranges supported */ ++#define SBIDL_AR_SHIFT 3 ++#define SBIDL_SYNCH 0x40 /* sync */ ++#define SBIDL_INIT 0x80 /* initiator */ ++#define SBIDL_MINLAT_MASK 0xf00 /* minimum backplane latency */ ++#define SBIDL_MINLAT_SHIFT 8 ++#define SBIDL_MAXLAT 0xf000 /* maximum backplane latency */ ++#define SBIDL_MAXLAT_SHIFT 12 ++#define SBIDL_FIRST 0x10000 /* this initiator is first */ ++#define SBIDL_CW_MASK 0xc0000 /* cycle counter width */ ++#define SBIDL_CW_SHIFT 18 ++#define SBIDL_TP_MASK 0xf00000 /* target ports */ ++#define SBIDL_TP_SHIFT 20 ++#define SBIDL_IP_MASK 0xf000000 /* initiator ports */ ++#define SBIDL_IP_SHIFT 24 ++#define SBIDL_RV_MASK 0xf0000000 /* sonics backplane revision code */ ++#define SBIDL_RV_SHIFT 28 ++#define SBIDL_RV_2_2 0x00000000 /* version 2.2 or earlier */ ++#define SBIDL_RV_2_3 0x10000000 /* version 2.3 */ ++ ++/* sbidhigh */ ++#define SBIDH_RC_MASK 0x000f /* revision code */ ++#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */ ++#define SBIDH_RCE_SHIFT 8 ++#define SBCOREREV(sbidh) \ ++ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK)) ++#define SBIDH_CC_MASK 0x8ff0 /* core code */ ++#define SBIDH_CC_SHIFT 4 ++#define SBIDH_VC_MASK 0xffff0000 /* vendor code */ ++#define SBIDH_VC_SHIFT 16 ++ ++#define SB_COMMIT 0xfd8 /* update buffered registers value */ ++ ++/* vendor codes */ ++#define SB_VEND_BCM 0x4243 /* Broadcom's SB vendor code */ ++ ++#endif /* _SBCONFIG_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbhndarm.h b/drivers/bcmdrivers/gmac/src/include/sbhndarm.h +new file mode 100755 +index 0000000..f925da3 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbhndarm.h +@@ -0,0 +1,293 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom SiliconBackplane ARM definitions ++ * ++ * $Id: sbhndarm.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _sbhndarm_h_ ++#define _sbhndarm_h_ ++ ++#include ++#include ++ ++/* register offsets */ ++#define ARM7_CORECTL 0 ++ ++/* bits in corecontrol */ ++#define ACC_FORCED_RST 0x1 ++#define ACC_SERRINT 0x2 ++#define ACC_NOTSLEEPINGCLKREQ_SHIFT 24 ++ ++/* arm resetlog */ ++#define SBRESETLOG 0x1 ++#define SERRORLOG 0x2 ++ ++/* arm core-specific control flags */ ++#define SICF_REMAP_MSK 0x001c ++#define SICF_REMAP_NONE 0 ++#define SICF_REMAP_ROM 0x0004 ++#define SIFC_REMAP_FLASH 0x0008 ++ ++/* misc core-specific defines */ ++#if defined(__ARM_ARCH_4T__) ++/* arm7tdmi-s */ ++/* backplane related stuff */ ++#define ARM_CORE_ID ARM7S_CORE_ID /* arm coreid */ ++#define SI_ARM_ROM SI_ARM7S_ROM /* ROM backplane/system address */ ++#define SI_ARM_SRAM2 SI_ARM7S_SRAM2 /* RAM backplane address when remap is 1 or 2 */ ++#elif defined(__ARM_ARCH_7M__) ++/* cortex-m3 */ ++/* backplane related stuff */ ++#define ARM_CORE_ID ARMCM3_CORE_ID /* arm coreid */ ++#define SI_ARM_ROM SI_ARMCM3_ROM /* ROM backplane/system address */ ++#define SI_ARM_SRAM2 SI_ARMCM3_SRAM2 /* RAM backplane address when remap is 1 or 2 */ ++/* core registers offsets */ ++#define ARMCM3_CYCLECNT 0x90 /* Cortex-M3 core registers offsets */ ++#define ARMCM3_INTTIMER 0x94 ++#define ARMCM3_INTMASK 0x98 ++#define ARMCM3_INTSTATUS 0x9c ++/* interrupt/exception */ ++#define ARMCM3_NUMINTS 16 /* # of external interrupts */ ++#define ARMCM3_INTALL ((1 << ARMCM3_NUMINTS) - 1) /* Interrupt mask */ ++#define ARMCM3_FAULTMASK 0x40000000 /* Master fault enable/disable */ ++#define ARMCM3_PRIMASK 0x80000000 /* Master interrupt enable/disable */ ++#define ARMCM3_SHARED_INT 0 /* Interrupt shared by multiple cores */ ++#define ARMCM3_INT(i) (1 << (i)) /* Individual interrupt enable/disable */ ++/* compatible with arm7tdmi-s */ ++#define PS_I ARMCM3_PRIMASK ++#define PS_F ARMCM3_FAULTMASK ++/* intmask/intstatus bits */ ++#define ARMCM3_INTMASK_TIMER 0x1 ++#define ARMCM3_INTMASK_SYSRESET 0x4 ++#define ARMCM3_INTMASK_LOCKUP 0x8 ++ ++/* ++ * Overlay Support in Rev 5 ++ */ ++#define ARMCM3_OVL_VALID_SHIFT 0 ++#define ARMCM3_OVL_VALID 1 ++#define ARMCM3_OVL_SZ_SHIFT 1 ++#define ARMCM3_OVL_SZ_MASK 0x0000000e ++#define ARMCM3_OVL_SZ_512B 0 /* 512B */ ++#define ARMCM3_OVL_SZ_1KB 1 /* 1KB */ ++#define ARMCM3_OVL_SZ_2KB 2 /* 2KB */ ++#define ARMCM3_OVL_SZ_4KB 3 /* 4KB */ ++#define ARMCM3_OVL_SZ_8KB 4 /* 8KB */ ++#define ARMCM3_OVL_SZ_16KB 5 /* 16KB */ ++#define ARMCM3_OVL_SZ_32KB 6 /* 32KB */ ++#define ARMCM3_OVL_SZ_64KB 7 /* 64KB */ ++#define ARMCM3_OVL_ADDR_SHIFT 9 ++#define ARMCM3_OVL_ADDR_MASK 0x003FFE00 ++#define ARMCM3_OVL_MAX 16 ++ ++#elif defined(__ARM_ARCH_7R__) ++/* cortex-r4 */ ++/* backplane related stuff */ ++#define ARM_CORE_ID ARMCR4_CORE_ID /* arm coreid */ ++#define SI_ARM_ROM SI_ARMCR4_ROM /* ROM backplane/system address */ ++#define SI_ARM_SRAM2 0x0 /* In the cr4 the RAM is just not available ++ * when remap is 1 ++ */ ++ ++/* core registers offsets */ ++#define ARMCR4_CORECTL 0 ++#define ARMCR4_CORECAP 4 ++#define ARMCR4_COREST 8 ++ ++#define ARMCR4_FIQRSTATUS 0x10 ++#define ARMCR4_FIQMASK 0x14 ++#define ARMCR4_IRQMASK 0x18 ++ ++#define ARMCR4_INTSTATUS 0x20 ++#define ARMCR4_INTMASK 0x24 ++#define ARMCR4_CYCLECNT 0x28 ++#define ARMCR4_INTTIMER 0x2c ++ ++#define ARMCR4_GPIOSEL 0x30 ++#define ARMCR4_GPIOEN 0x34 ++ ++#define ARMCR4_BANKIDX 0x40 ++#define ARMCR4_BANKINFO 0x44 ++#define ARMCR4_BANKSTBY 0x48 ++#define ARMCR4_BANKPDA 0x4c ++ ++#define ARMCR4_TCAMPATCHCTRL 0x68 ++#define ARMCR4_TCAMPATCHTBLBASEADDR 0x6C ++#define ARMCR4_TCAMCMDREG 0x70 ++#define ARMCR4_TCAMDATAREG 0x74 ++#define ARMCR4_TCAMBANKXMASKREG 0x78 ++ ++#define ARMCR4_ROMNB_MASK 0xf00 ++#define ARMCR4_ROMNB_SHIFT 8 ++#define ARMCR4_TCBBNB_MASK 0xf0 ++#define ARMCR4_TCBBNB_SHIFT 4 ++#define ARMCR4_TCBANB_MASK 0xf ++#define ARMCR4_TCBANB_SHIFT 0 ++ ++#define ARMCR4_MT_MASK 0x300 ++#define ARMCR4_MT_SHIFT 8 ++#define ARMCR4_MT_ROM 0x100 ++#define ARMCR4_MT_RAM 0 ++ ++#define ARMCR4_BSZ_MASK 0x3f ++#define ARMCR4_BSZ_MULT 8192 ++ ++#define ARMCR4_TCAM_ENABLE (1 << 31) ++#define ARMCR4_TCAM_CLKENAB (1 << 30) ++#define ARMCR4_TCAM_PATCHCNT_MASK 0xf ++ ++#define ARMCR4_TCAM_CMD_DONE (1 << 31) ++#define ARMCR4_TCAM_MATCH (1 << 24) ++#define ARMCR4_TCAM_OPCODE_MASK (3 << 16) ++#define ARMCR4_TCAM_OPCODE_SHIFT 16 ++#define ARMCR4_TCAM_ADDR_MASK 0xffff ++#define ARMCR4_TCAM_NONE (0 << ARMCR4_TCAM_OPCODE_SHIFT) ++#define ARMCR4_TCAM_READ (1 << ARMCR4_TCAM_OPCODE_SHIFT) ++#define ARMCR4_TCAM_WRITE (2 << ARMCR4_TCAM_OPCODE_SHIFT) ++#define ARMCR4_TCAM_COMPARE (3 << ARMCR4_TCAM_OPCODE_SHIFT) ++#define ARMCR4_TCAM_CMD_DONE_DLY 1000 ++ ++#define ARMCR4_DATA_MASK (~0x7) ++#define ARMCR4_DATA_VALID (1 << 0) ++ ++ ++/* arm core-specific conrol flags */ ++#define SICF_CPUHALT 0x0020 ++#define SICF_UPDATEFW 0x0040 ++ ++/* arm core-specific status flags */ ++#define SISF_SDRENABLE 0x0001 ++#define SISF_TCMPROT 0x0002 ++ ++#define CHIP_SDRENABLE(sih) (sih->boardflags2 & BFL2_SDR_EN) ++#define CHIP_TCMPROTENAB(sih) (si_arm_sflags(sih) & SISF_TCMPROT) ++ ++#elif defined(__ARM_ARCH_7A__) ++/* backplane related stuff */ ++#define ARM_CORE_ID ARMCA9_CORE_ID /* arm coreid */ ++ ++#else /* !__ARM_ARCH_4T__ && !__ARM_ARCH_7M__ && !__ARM_ARCH_7R__ */ ++#error Unrecognized ARM Architecture ++#endif /* !__ARM_ARCH_4T__ && !__ARM_ARCH_7M__ && !__ARM_ARCH_7R__ */ ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++#if defined(__ARM_ARCH_4T__) ++/* arm7tdmi-s */ ++typedef volatile struct { ++ uint32 corecontrol; /* 0 */ ++ uint32 sleepcontrol; /* 4 */ ++ uint32 PAD; ++ uint32 biststatus; /* 0xc */ ++ uint32 firqstatus; /* 0x10 */ ++ uint32 fiqmask; /* 0x14 */ ++ uint32 irqmask; /* 0x18 */ ++ uint32 PAD; ++ uint32 resetlog; /* 0x20 */ ++ uint32 gpioselect; /* 0x24 */ ++ uint32 gpioenable; /* 0x28 */ ++ uint32 PAD; ++ uint32 bpaddrlo; /* 0x30 */ ++ uint32 bpaddrhi; /* 0x34 */ ++ uint32 bpdata; /* 0x38 */ ++ uint32 bpindaccess; /* 0x3c */ ++ uint32 PAD[104]; ++ uint32 clk_ctl_st; /* 0x1e0 */ ++ uint32 hw_war; /* 0x1e4 */ ++} armregs_t; ++#define ARMREG(regs, reg) (&((armregs_t *)regs)->reg) ++#endif /* __ARM_ARCH_4T__ */ ++ ++#if defined(__ARM_ARCH_7M__) ++/* cortex-m3 */ ++typedef volatile struct { ++ uint32 corecontrol; /* 0x0 */ ++ uint32 corestatus; /* 0x4 */ ++ uint32 PAD[1]; ++ uint32 biststatus; /* 0xc */ ++ uint32 nmiisrst; /* 0x10 */ ++ uint32 nmimask; /* 0x14 */ ++ uint32 isrmask; /* 0x18 */ ++ uint32 PAD[1]; ++ uint32 resetlog; /* 0x20 */ ++ uint32 gpioselect; /* 0x24 */ ++ uint32 gpioenable; /* 0x28 */ ++ uint32 PAD[1]; ++ uint32 bpaddrlo; /* 0x30 */ ++ uint32 bpaddrhi; /* 0x34 */ ++ uint32 bpdata; /* 0x38 */ ++ uint32 bpindaccess; /* 0x3c */ ++ uint32 ovlidx; /* 0x40 */ ++ uint32 ovlmatch; /* 0x44 */ ++ uint32 ovladdr; /* 0x48 */ ++ uint32 PAD[13]; ++ uint32 bwalloc; /* 0x80 */ ++ uint32 PAD[3]; ++ uint32 cyclecnt; /* 0x90 */ ++ uint32 inttimer; /* 0x94 */ ++ uint32 intmask; /* 0x98 */ ++ uint32 intstatus; /* 0x9c */ ++ uint32 PAD[80]; ++ uint32 clk_ctl_st; /* 0x1e0 */ ++} cm3regs_t; ++#define ARMREG(regs, reg) (&((cm3regs_t *)regs)->reg) ++#endif /* __ARM_ARCH_7M__ */ ++ ++#if defined(__ARM_ARCH_7R__) ++/* cortex-R4 */ ++typedef volatile struct { ++ uint32 corecontrol; /* 0x0 */ ++ uint32 corecapabilities; /* 0x4 */ ++ uint32 corestatus; /* 0x8 */ ++ uint32 biststatus; /* 0xc */ ++ uint32 nmiisrst; /* 0x10 */ ++ uint32 nmimask; /* 0x14 */ ++ uint32 isrmask; /* 0x18 */ ++ uint32 PAD[1]; ++ uint32 intstatus; /* 0x20 */ ++ uint32 intmask; /* 0x24 */ ++ uint32 cyclecnt; /* 0x28 */ ++ uint32 inttimer; /* 0x2c */ ++ uint32 gpioselect; /* 0x30 */ ++ uint32 gpioenable; /* 0x34 */ ++ uint32 PAD[2]; ++ uint32 bankidx; /* 0x40 */ ++ uint32 bankinfo; /* 0x44 */ ++ uint32 bankstbyctl; /* 0x48 */ ++ uint32 bankpda; /* 0x4c */ ++ uint32 PAD[6]; ++ uint32 tcampatchctrl; /* 0x68 */ ++ uint32 tcampatchtblbaseaddr; /* 0x6c */ ++ uint32 tcamcmdreg; /* 0x70 */ ++ uint32 tcamdatareg; /* 0x74 */ ++ uint32 tcambankxmaskreg; /* 0x78 */ ++ uint32 PAD[89]; ++ uint32 clk_ctl_st; /* 0x1e0 */ ++} cr4regs_t; ++#define ARMREG(regs, reg) (&((cr4regs_t *)regs)->reg) ++#endif /* __ARM_ARCH_7R__ */ ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++#endif /* _sbhndarm_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbhnddma.h b/drivers/bcmdrivers/gmac/src/include/sbhnddma.h +new file mode 100755 +index 0000000..3003687 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbhnddma.h +@@ -0,0 +1,403 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface ++ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * ++ * $Id: sbhnddma.h 321146 2012-03-14 08:27:23Z $ ++ */ ++ ++#ifndef _sbhnddma_h_ ++#define _sbhnddma_h_ ++ ++/* DMA structure: ++ * support two DMA engines: 32 bits address or 64 bit addressing ++ * basic DMA register set is per channel(transmit or receive) ++ * a pair of channels is defined for convenience ++ */ ++ ++ ++/* 32 bits addressing */ ++ ++/* dma registers per channel(xmt or rcv) */ ++typedef volatile struct { ++ uint32 control; /* enable, et al */ ++ uint32 addr; /* descriptor ring base address (4K aligned) */ ++ uint32 ptr; /* last descriptor posted to chip */ ++ uint32 status; /* current active descriptor, et al */ ++} dma32regs_t; ++ ++typedef volatile struct { ++ dma32regs_t xmt; /* dma tx channel */ ++ dma32regs_t rcv; /* dma rx channel */ ++} dma32regp_t; ++ ++typedef volatile struct { /* diag access */ ++ uint32 fifoaddr; /* diag address */ ++ uint32 fifodatalow; /* low 32bits of data */ ++ uint32 fifodatahigh; /* high 32bits of data */ ++ uint32 pad; /* reserved */ ++} dma32diag_t; ++ ++/* ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. ++ */ ++typedef volatile struct { ++ uint32 ctrl; /* misc control bits & bufcount */ ++ uint32 addr; /* data buffer address */ ++} dma32dd_t; ++ ++/* ++ * Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page. ++ */ ++#define D32RINGALIGN_BITS 12 ++#define D32MAXRINGSZ (1 << D32RINGALIGN_BITS) ++#define D32RINGALIGN (1 << D32RINGALIGN_BITS) ++ ++#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t)) ++ ++/* transmit channel control */ ++#define XC_XE ((uint32)1 << 0) /* transmit enable */ ++#define XC_SE ((uint32)1 << 1) /* transmit suspend request */ ++#define XC_LE ((uint32)1 << 2) /* loopback enable */ ++#define XC_FL ((uint32)1 << 4) /* flush request */ ++#define XC_MR_MASK 0x000000C0 /* Multiple outstanding reads */ ++#define XC_MR_SHIFT 6 ++#define XC_PD ((uint32)1 << 11) /* parity check disable */ ++#define XC_AE ((uint32)3 << 16) /* address extension bits */ ++#define XC_AE_SHIFT 16 ++#define XC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define XC_BL_SHIFT 18 ++#define XC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define XC_PC_SHIFT 21 ++#define XC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define XC_PT_SHIFT 24 ++ ++/* Multiple outstanding reads */ ++#define DMA_MR_1 0 ++#define DMA_MR_2 1 ++/* 2, 3: reserved */ ++ ++/* DMA Burst Length in bytes */ ++#define DMA_BL_16 0 ++#define DMA_BL_32 1 ++#define DMA_BL_64 2 ++#define DMA_BL_128 3 ++#define DMA_BL_256 4 ++#define DMA_BL_512 5 ++#define DMA_BL_1024 6 ++ ++/* Prefetch control */ ++#define DMA_PC_0 0 ++#define DMA_PC_4 1 ++#define DMA_PC_8 2 ++#define DMA_PC_16 3 ++/* others: reserved */ ++ ++/* Prefetch threshold */ ++#define DMA_PT_1 0 ++#define DMA_PT_2 1 ++#define DMA_PT_4 2 ++#define DMA_PT_8 3 ++ ++/* transmit descriptor table pointer */ ++#define XP_LD_MASK 0xfff /* last valid descriptor */ ++ ++/* transmit channel status */ ++#define XS_CD_MASK 0x0fff /* current descriptor pointer */ ++#define XS_XS_MASK 0xf000 /* transmit state */ ++#define XS_XS_SHIFT 12 ++#define XS_XS_DISABLED 0x0000 /* disabled */ ++#define XS_XS_ACTIVE 0x1000 /* active */ ++#define XS_XS_IDLE 0x2000 /* idle wait */ ++#define XS_XS_STOPPED 0x3000 /* stopped */ ++#define XS_XS_SUSP 0x4000 /* suspend pending */ ++#define XS_XE_MASK 0xf0000 /* transmit errors */ ++#define XS_XE_SHIFT 16 ++#define XS_XE_NOERR 0x00000 /* no error */ ++#define XS_XE_DPE 0x10000 /* descriptor protocol error */ ++#define XS_XE_DFU 0x20000 /* data fifo underrun */ ++#define XS_XE_BEBR 0x30000 /* bus error on buffer read */ ++#define XS_XE_BEDA 0x40000 /* bus error on descriptor access */ ++#define XS_AD_MASK 0xfff00000 /* active descriptor */ ++#define XS_AD_SHIFT 20 ++ ++/* receive channel control */ ++#define RC_RE ((uint32)1 << 0) /* receive enable */ ++#define RC_RO_MASK 0xfe /* receive frame offset */ ++#define RC_RO_SHIFT 1 ++#define RC_FM ((uint32)1 << 8) /* direct fifo receive (pio) mode */ ++#define RC_SH ((uint32)1 << 9) /* separate rx header descriptor enable */ ++#define RC_OC ((uint32)1 << 10) /* overflow continue */ ++#define RC_PD ((uint32)1 << 11) /* parity check disable */ ++#define RC_AE ((uint32)3 << 16) /* address extension bits */ ++#define RC_AE_SHIFT 16 ++#define RC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define RC_BL_SHIFT 18 ++#define RC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define RC_PC_SHIFT 21 ++#define RC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define RC_PT_SHIFT 24 ++ ++/* receive descriptor table pointer */ ++#define RP_LD_MASK 0xfff /* last valid descriptor */ ++ ++/* receive channel status */ ++#define RS_CD_MASK 0x0fff /* current descriptor pointer */ ++#define RS_RS_MASK 0xf000 /* receive state */ ++#define RS_RS_SHIFT 12 ++#define RS_RS_DISABLED 0x0000 /* disabled */ ++#define RS_RS_ACTIVE 0x1000 /* active */ ++#define RS_RS_IDLE 0x2000 /* idle wait */ ++#define RS_RS_STOPPED 0x3000 /* reserved */ ++#define RS_RE_MASK 0xf0000 /* receive errors */ ++#define RS_RE_SHIFT 16 ++#define RS_RE_NOERR 0x00000 /* no error */ ++#define RS_RE_DPE 0x10000 /* descriptor protocol error */ ++#define RS_RE_DFO 0x20000 /* data fifo overflow */ ++#define RS_RE_BEBW 0x30000 /* bus error on buffer write */ ++#define RS_RE_BEDA 0x40000 /* bus error on descriptor access */ ++#define RS_AD_MASK 0xfff00000 /* active descriptor */ ++#define RS_AD_SHIFT 20 ++ ++/* fifoaddr */ ++#define FA_OFF_MASK 0xffff /* offset */ ++#define FA_SEL_MASK 0xf0000 /* select */ ++#define FA_SEL_SHIFT 16 ++#define FA_SEL_XDD 0x00000 /* transmit dma data */ ++#define FA_SEL_XDP 0x10000 /* transmit dma pointers */ ++#define FA_SEL_RDD 0x40000 /* receive dma data */ ++#define FA_SEL_RDP 0x50000 /* receive dma pointers */ ++#define FA_SEL_XFD 0x80000 /* transmit fifo data */ ++#define FA_SEL_XFP 0x90000 /* transmit fifo pointers */ ++#define FA_SEL_RFD 0xc0000 /* receive fifo data */ ++#define FA_SEL_RFP 0xd0000 /* receive fifo pointers */ ++#define FA_SEL_RSD 0xe0000 /* receive frame status data */ ++#define FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ ++/* descriptor control flags */ ++#define CTRL_BC_MASK 0x00001fff /* buffer byte count, real data len must <= 4KB */ ++#define CTRL_AE ((uint32)3 << 16) /* address extension bits */ ++#define CTRL_AE_SHIFT 16 ++#define CTRL_PARITY ((uint32)3 << 18) /* parity bit */ ++#define CTRL_EOT ((uint32)1 << 28) /* end of descriptor table */ ++#define CTRL_IOC ((uint32)1 << 29) /* interrupt on completion */ ++#define CTRL_EOF ((uint32)1 << 30) /* end of frame */ ++#define CTRL_SOF ((uint32)1 << 31) /* start of frame */ ++ ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define CTRL_CORE_MASK 0x0ff00000 ++ ++/* 64 bits addressing */ ++ ++/* dma registers per channel(xmt or rcv) */ ++typedef volatile struct { ++ uint32 control; /* enable, et al */ ++ uint32 ptr; /* last descriptor posted to chip */ ++ uint32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */ ++ uint32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */ ++ uint32 status0; /* current descriptor, xmt state */ ++ uint32 status1; /* active descriptor, xmt error */ ++} dma64regs_t; ++ ++typedef volatile struct { ++ dma64regs_t tx; /* dma64 tx channel */ ++ dma64regs_t rx; /* dma64 rx channel */ ++} dma64regp_t; ++ ++typedef volatile struct { /* diag access */ ++ uint32 fifoaddr; /* diag address */ ++ uint32 fifodatalow; /* low 32bits of data */ ++ uint32 fifodatahigh; /* high 32bits of data */ ++ uint32 pad; /* reserved */ ++} dma64diag_t; ++ ++/* ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. ++ */ ++typedef volatile struct { ++ uint32 ctrl1; /* misc control bits */ ++ uint32 ctrl2; /* buffer count and address extension */ ++ uint32 addrlow; /* memory address of the date buffer, bits 31:0 */ ++ uint32 addrhigh; /* memory address of the date buffer, bits 63:32 */ ++} dma64dd_t; ++ ++/* ++ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss. ++ */ ++#define D64RINGALIGN_BITS 13 ++#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) ++#define D64RINGBOUNDARY (1 << D64RINGALIGN_BITS) ++ ++#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) ++ ++/* for cores with large descriptor ring support, descriptor ring size can be up to 4096 */ ++#define D64MAXDD_LARGE ((1 << 16) / sizeof (dma64dd_t)) ++ ++/* for cores with large descriptor ring support (4k descriptors), descriptor ring cannot cross ++ * 64K boundary ++ */ ++#define D64RINGBOUNDARY_LARGE (1 << 16) ++ ++/* ++ * Default DMA Burstlen values for USBRev >= 12 and SDIORev >= 11. ++ * When this field contains the value N, the burst length is 2**(N + 4) bytes. ++ */ ++#define D64_DEF_USBBURSTLEN 2 ++#define D64_DEF_SDIOBURSTLEN 1 ++ ++ ++#ifndef D64_USBBURSTLEN ++#define D64_USBBURSTLEN DMA_BL_64 ++#endif ++#ifndef D64_SDIOBURSTLEN ++#define D64_SDIOBURSTLEN DMA_BL_32 ++#endif ++ ++/* transmit channel control */ ++#define D64_XC_XE 0x00000001 /* transmit enable */ ++#define D64_XC_SE 0x00000002 /* transmit suspend request */ ++#define D64_XC_LE 0x00000004 /* loopback enable */ ++#define D64_XC_FL 0x00000010 /* flush request */ ++#define D64_XC_MR_MASK 0x000000C0 /* Multiple outstanding reads */ ++#define D64_XC_MR_SHIFT 6 ++#define D64_XC_PD 0x00000800 /* parity check disable */ ++#define D64_XC_AE 0x00030000 /* address extension bits */ ++#define D64_XC_AE_SHIFT 16 ++#define D64_XC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define D64_XC_BL_SHIFT 18 ++#define D64_XC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define D64_XC_PC_SHIFT 21 ++#define D64_XC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define D64_XC_PT_SHIFT 24 ++ ++/* transmit descriptor table pointer */ ++#define D64_XP_LD_MASK 0x00001fff /* last valid descriptor */ ++ ++/* transmit channel status */ ++#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ ++#define D64_XS0_XS_SHIFT 28 ++#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ ++#define D64_XS0_XS_ACTIVE 0x10000000 /* active */ ++#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */ ++#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ ++#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ ++ ++#define D64_XS1_AD_MASK 0x00001fff /* active descriptor */ ++#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ ++#define D64_XS1_XE_SHIFT 28 ++#define D64_XS1_XE_NOERR 0x00000000 /* no error */ ++#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */ ++#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */ ++#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */ ++#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_XS1_XE_COREE 0x50000000 /* core error */ ++ ++/* receive channel control */ ++#define D64_RC_RE 0x00000001 /* receive enable */ ++#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */ ++#define D64_RC_RO_SHIFT 1 ++#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */ ++#define D64_RC_SH 0x00000200 /* separate rx header descriptor enable */ ++#define D64_RC_OC 0x00000400 /* overflow continue */ ++#define D64_RC_PD 0x00000800 /* parity check disable */ ++#define D64_RC_GE 0x00004000 /* Glom enable */ ++#define D64_RC_AE 0x00030000 /* address extension bits */ ++#define D64_RC_AE_SHIFT 16 ++#define D64_RC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define D64_RC_BL_SHIFT 18 ++#define D64_RC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define D64_RC_PC_SHIFT 21 ++#define D64_RC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define D64_RC_PT_SHIFT 24 ++ ++/* flags for dma controller */ ++#define DMA_CTRL_PEN (1 << 0) /* partity enable */ ++#define DMA_CTRL_ROC (1 << 1) /* rx overflow continue */ ++#define DMA_CTRL_RXMULTI (1 << 2) /* allow rx scatter to multiple descriptors */ ++#define DMA_CTRL_UNFRAMED (1 << 3) /* Unframed Rx/Tx data */ ++#define DMA_CTRL_USB_BOUNDRY4KB_WAR (1 << 4) ++#define DMA_CTRL_DMA_AVOIDANCE_WAR (1 << 5) /* DMA avoidance WAR for 4331 */ ++#define DMA_CTRL_RXSINGLE (1 << 6) /* always single buffer */ ++ ++/* receive descriptor table pointer */ ++#define D64_RP_LD_MASK 0x00001fff /* last valid descriptor */ ++ ++/* receive channel status */ ++#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_RS0_RS_MASK 0xf0000000 /* receive state */ ++#define D64_RS0_RS_SHIFT 28 ++#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ ++#define D64_RS0_RS_ACTIVE 0x10000000 /* active */ ++#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */ ++#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */ ++#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */ ++ ++#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */ ++#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */ ++#define D64_RS1_RE_SHIFT 28 ++#define D64_RS1_RE_NOERR 0x00000000 /* no error */ ++#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */ ++#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */ ++#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */ ++#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_RS1_RE_COREE 0x50000000 /* core error */ ++ ++/* fifoaddr */ ++#define D64_FA_OFF_MASK 0xffff /* offset */ ++#define D64_FA_SEL_MASK 0xf0000 /* select */ ++#define D64_FA_SEL_SHIFT 16 ++#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */ ++#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */ ++#define D64_FA_SEL_RDD 0x40000 /* receive dma data */ ++#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */ ++#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */ ++#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */ ++#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */ ++#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */ ++#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */ ++#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ ++/* descriptor control flags 1 */ ++#define D64_CTRL_COREFLAGS 0x0ff00000 /* core specific flags */ ++#define D64_CTRL1_EOT ((uint32)1 << 28) /* end of descriptor table */ ++#define D64_CTRL1_IOC ((uint32)1 << 29) /* interrupt on completion */ ++#define D64_CTRL1_EOF ((uint32)1 << 30) /* end of frame */ ++#define D64_CTRL1_SOF ((uint32)1 << 31) /* start of frame */ ++ ++/* descriptor control flags 2 */ ++#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count. real data len must <= 16KB */ ++#define D64_CTRL2_AE 0x00030000 /* address extension bits */ ++#define D64_CTRL2_AE_SHIFT 16 ++#define D64_CTRL2_PARITY 0x00040000 /* parity bit */ ++ ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define D64_CTRL_CORE_MASK 0x0ff00000 ++ ++#define D64_RX_FRM_STS_LEN 0x0000ffff /* frame length mask */ ++#define D64_RX_FRM_STS_OVFL 0x00800000 /* RxOverFlow */ ++#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1, d11corerev >= 22 */ ++#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */ ++ ++/* receive frame status */ ++typedef volatile struct { ++ uint16 len; ++ uint16 flags; ++} dma_rxh_t; ++ ++#endif /* _sbhnddma_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbsocram.h b/drivers/bcmdrivers/gmac/src/include/sbsocram.h +new file mode 100755 +index 0000000..1afd2e3 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbsocram.h +@@ -0,0 +1,193 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * BCM47XX Sonics SiliconBackplane embedded ram core ++ * ++ * $Id: sbsocram.h 271781 2011-07-13 20:00:06Z $ ++ */ ++ ++#ifndef _SBSOCRAM_H ++#define _SBSOCRAM_H ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* Memcsocram core registers */ ++typedef volatile struct sbsocramregs { ++ uint32 coreinfo; ++ uint32 bwalloc; ++ uint32 extracoreinfo; ++ uint32 biststat; ++ uint32 bankidx; ++ uint32 standbyctrl; ++ ++ uint32 errlogstatus; /* rev 6 */ ++ uint32 errlogaddr; /* rev 6 */ ++ /* used for patching rev 3 & 5 */ ++ uint32 cambankidx; ++ uint32 cambankstandbyctrl; ++ uint32 cambankpatchctrl; ++ uint32 cambankpatchtblbaseaddr; ++ uint32 cambankcmdreg; ++ uint32 cambankdatareg; ++ uint32 cambankmaskreg; ++ uint32 PAD[1]; ++ uint32 bankinfo; /* corev 8 */ ++ uint32 PAD[15]; ++ uint32 extmemconfig; ++ uint32 extmemparitycsr; ++ uint32 extmemparityerrdata; ++ uint32 extmemparityerrcnt; ++ uint32 extmemwrctrlandsize; ++ uint32 PAD[84]; ++ uint32 workaround; ++ uint32 pwrctl; /* corerev >= 2 */ ++ uint32 PAD[133]; ++ uint32 sr_control; /* corerev >= 15 */ ++ uint32 sr_status; /* corerev >= 15 */ ++ uint32 sr_address; /* corerev >= 15 */ ++ uint32 sr_data; /* corerev >= 15 */ ++} sbsocramregs_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* Register offsets */ ++#define SR_COREINFO 0x00 ++#define SR_BWALLOC 0x04 ++#define SR_BISTSTAT 0x0c ++#define SR_BANKINDEX 0x10 ++#define SR_BANKSTBYCTL 0x14 ++#define SR_PWRCTL 0x1e8 ++ ++/* Coreinfo register */ ++#define SRCI_PT_MASK 0x00070000 /* corerev >= 6; port type[18:16] */ ++#define SRCI_PT_SHIFT 16 ++/* port types : SRCI_PT__ */ ++#define SRCI_PT_OCP_OCP 0 ++#define SRCI_PT_AXI_OCP 1 ++#define SRCI_PT_ARM7AHB_OCP 2 ++#define SRCI_PT_CM3AHB_OCP 3 ++#define SRCI_PT_AXI_AXI 4 ++#define SRCI_PT_AHB_AXI 5 ++/* corerev >= 3 */ ++#define SRCI_LSS_MASK 0x00f00000 ++#define SRCI_LSS_SHIFT 20 ++#define SRCI_LRS_MASK 0x0f000000 ++#define SRCI_LRS_SHIFT 24 ++ ++/* In corerev 0, the memory size is 2 to the power of the ++ * base plus 16 plus to the contents of the memsize field plus 1. ++ */ ++#define SRCI_MS0_MASK 0xf ++#define SR_MS0_BASE 16 ++ ++/* ++ * In corerev 1 the bank size is 2 ^ the bank size field plus 14, ++ * the memory size is number of banks times bank size. ++ * The same applies to rom size. ++ */ ++#define SRCI_ROMNB_MASK 0xf000 ++#define SRCI_ROMNB_SHIFT 12 ++#define SRCI_ROMBSZ_MASK 0xf00 ++#define SRCI_ROMBSZ_SHIFT 8 ++#define SRCI_SRNB_MASK 0xf0 ++#define SRCI_SRNB_SHIFT 4 ++#define SRCI_SRBSZ_MASK 0xf ++#define SRCI_SRBSZ_SHIFT 0 ++ ++#define SR_BSZ_BASE 14 ++ ++/* Standby control register */ ++#define SRSC_SBYOVR_MASK 0x80000000 ++#define SRSC_SBYOVR_SHIFT 31 ++#define SRSC_SBYOVRVAL_MASK 0x60000000 ++#define SRSC_SBYOVRVAL_SHIFT 29 ++#define SRSC_SBYEN_MASK 0x01000000 /* rev >= 3 */ ++#define SRSC_SBYEN_SHIFT 24 ++ ++/* Power control register */ ++#define SRPC_PMU_STBYDIS_MASK 0x00000010 /* rev >= 3 */ ++#define SRPC_PMU_STBYDIS_SHIFT 4 ++#define SRPC_STBYOVRVAL_MASK 0x00000008 ++#define SRPC_STBYOVRVAL_SHIFT 3 ++#define SRPC_STBYOVR_MASK 0x00000007 ++#define SRPC_STBYOVR_SHIFT 0 ++ ++/* Extra core capability register */ ++#define SRECC_NUM_BANKS_MASK 0x000000F0 ++#define SRECC_NUM_BANKS_SHIFT 4 ++#define SRECC_BANKSIZE_MASK 0x0000000F ++#define SRECC_BANKSIZE_SHIFT 0 ++ ++#define SRECC_BANKSIZE(value) (1 << (value)) ++ ++/* CAM bank patch control */ ++#define SRCBPC_PATCHENABLE 0x80000000 ++ ++#define SRP_ADDRESS 0x0001FFFC ++#define SRP_VALID 0x8000 ++ ++/* CAM bank command reg */ ++#define SRCMD_WRITE 0x00020000 ++#define SRCMD_READ 0x00010000 ++#define SRCMD_DONE 0x80000000 ++ ++#define SRCMD_DONE_DLY 1000 ++ ++/* bankidx and bankinfo reg defines corerev >= 8 */ ++#define SOCRAM_BANKINFO_SZMASK 0x7f ++#define SOCRAM_BANKIDX_ROM_MASK 0x100 ++ ++#define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8 ++/* socram bankinfo memtype */ ++#define SOCRAM_MEMTYPE_RAM 0 ++#define SOCRAM_MEMTYPE_R0M 1 ++#define SOCRAM_MEMTYPE_DEVRAM 2 ++ ++#define SOCRAM_BANKINFO_REG 0x40 ++#define SOCRAM_BANKIDX_REG 0x10 ++#define SOCRAM_BANKINFO_STDBY_MASK 0x400 ++#define SOCRAM_BANKINFO_STDBY_TIMER 0x800 ++ ++/* bankinfo rev >= 10 */ ++#define SOCRAM_BANKINFO_DEVRAMSEL_SHIFT 13 ++#define SOCRAM_BANKINFO_DEVRAMSEL_MASK 0x2000 ++#define SOCRAM_BANKINFO_DEVRAMPRO_SHIFT 14 ++#define SOCRAM_BANKINFO_DEVRAMPRO_MASK 0x4000 ++#define SOCRAM_BANKINFO_SLPSUPP_SHIFT 15 ++#define SOCRAM_BANKINFO_SLPSUPP_MASK 0x8000 ++#define SOCRAM_BANKINFO_RETNTRAM_SHIFT 16 ++#define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000 ++#define SOCRAM_BANKINFO_PDASZ_SHIFT 17 ++#define SOCRAM_BANKINFO_PDASZ_MASK 0x003E0000 ++#define SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT 24 ++#define SOCRAM_BANKINFO_DEVRAMREMAP_MASK 0x01000000 ++ ++/* extracoreinfo register */ ++#define SOCRAM_DEVRAMBANK_MASK 0xF000 ++#define SOCRAM_DEVRAMBANK_SHIFT 12 ++ ++/* bank info to calculate bank size */ ++#define SOCRAM_BANKINFO_SZBASE 8192 ++#define SOCRAM_BANKSIZE_SHIFT 13 /* SOCRAM_BANKINFO_SZBASE */ ++ ++ ++#endif /* _SBSOCRAM_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/siutils.h b/drivers/bcmdrivers/gmac/src/include/siutils.h +new file mode 100755 +index 0000000..5e4ce7d +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/siutils.h +@@ -0,0 +1,256 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc utility routines for accessing the SOC Interconnects ++ * of Broadcom HNBU chips. ++ * ++ * $Id: siutils.h 323456 2012-03-24 07:17:39Z $ ++ */ ++ ++#ifndef _siutils_h_ ++#define _siutils_h_ ++ ++#if defined(WLC_HIGH) && !defined(WLC_LOW) ++#include "bcm_rpc.h" ++#endif ++/* ++ * Data structure to export all chip specific common variables ++ * public (read-only) portion of siutils handle returned by si_attach()/si_kattach() ++ */ ++struct si_pub { ++ uint socitype; /* SOCI_SB, SOCI_AI */ ++ ++ uint bustype; /* SI_BUS, PCI_BUS */ ++ uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */ ++ uint buscorerev; /* buscore rev */ ++ uint buscoreidx; /* buscore index */ ++ int ccrev; /* chip common core rev */ ++ uint32 cccaps; /* chip common capabilities */ ++ uint32 cccaps_ext; /* chip common capabilities extension */ ++ int pmurev; /* pmu core rev */ ++ uint32 pmucaps; /* pmu capabilities */ ++ uint boardtype; /* board type */ ++ uint boardrev; /* board rev */ ++ uint boardvendor; /* board vendor */ ++ uint boardflags; /* board flags */ ++ uint boardflags2; /* board flags2 */ ++ uint chip; /* chip number */ ++ uint chiprev; /* chip revision */ ++ uint chippkg; /* chip package option */ ++ uint32 chipst; /* chip status */ ++ bool issim; /* chip is in simulation or emulation */ ++ uint socirev; /* SOC interconnect rev */ ++ bool pci_pr32414; ++ ++#if defined(WLC_HIGH) && !defined(WLC_LOW) ++ rpc_info_t *rpc; ++#endif ++#ifdef SI_ENUM_BASE_VARIABLE ++ uint32 si_enum_base; ++#endif /* SI_ENUM_BASE_VARIABLE */ ++}; ++ ++/* for HIGH_ONLY driver, the si_t must be writable to allow states sync from BMAC to HIGH driver ++ * for monolithic driver, it is readonly to prevent accident change ++ */ ++#if defined(WLC_HIGH) && !defined(WLC_LOW) ++typedef struct si_pub si_t; ++#else ++typedef const struct si_pub si_t; ++#endif ++ ++#ifdef ATE_BUILD ++typedef struct _ate_params { ++ void* wl; ++ uint8 gpio_input; ++ uint8 gpio_output; ++ bool cmd_proceed; ++ uint16 cmd_idx; ++ bool ate_cmd_done; ++} ate_params_t; ++#endif /* ATE_BUILD */ ++ ++/* ++ * Many of the routines below take an 'sih' handle as their first arg. ++ * Allocate this by calling si_attach(). Free it by calling si_detach(). ++ * At any one time, the sih is logically focused on one particular si core ++ * (the "current core"). ++ * Use si_setcore() or si_setcoreidx() to change the association to another core. ++ */ ++#define SI_OSH NULL /* Use for si_kattach when no osh is available */ ++ ++#define BADIDX (SI_MAXCORES + 1) ++ ++/* clkctl xtal what flags */ ++#define XTAL 0x1 /* primary crystal oscillator (2050) */ ++#define PLL 0x2 /* main chip pll */ ++ ++/* clkctl clk mode */ ++#define CLK_FAST 0 /* force fast (pll) clock */ ++#define CLK_DYNAMIC 2 /* enable dynamic clock control */ ++ ++/* GPIO usage priorities */ ++#define GPIO_DRV_PRIORITY 0 /* Driver */ ++#define GPIO_APP_PRIORITY 1 /* Application */ ++#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO reservation */ ++ ++/* GPIO pull up/down */ ++#define GPIO_PULLUP 0 ++#define GPIO_PULLDN 1 ++ ++/* GPIO event regtype */ ++#define GPIO_REGEVT 0 /* GPIO register event */ ++#define GPIO_REGEVT_INTMSK 1 /* GPIO register event int mask */ ++#define GPIO_REGEVT_INTPOL 2 /* GPIO register event int polarity */ ++ ++/* device path */ ++#define SI_DEVPATH_BUFSZ 16 /* min buffer size in bytes */ ++ ++/* SI routine enumeration: to be used by update function with multiple hooks */ ++#define SI_DOATTACH 1 ++#define SI_PCIDOWN 2 ++#define SI_PCIUP 3 ++ ++#if defined(BCMQT) ++#define ISSIM_ENAB(sih) ((sih)->issim) ++#else ++#define ISSIM_ENAB(sih) 0 ++#endif ++ ++/* PMU clock/power control */ ++#if defined(BCMPMUCTL) ++#define PMUCTL_ENAB(sih) (BCMPMUCTL) ++#else ++#define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU) ++#endif ++ ++/* chipcommon clock/power control (exclusive with PMU's) */ ++#if defined(BCMPMUCTL) && BCMPMUCTL ++#define CCCTL_ENAB(sih) (0) ++#define CCPLL_ENAB(sih) (0) ++#else ++#define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL) ++#define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK) ++#endif ++ ++typedef void (*gpio_handler_t)(uint32 stat, void *arg); ++/* External BT Coex enable mask */ ++#define CC_BTCOEX_EN_MASK 0x01 ++/* External PA enable mask */ ++#define GPIO_CTRL_EPA_EN_MASK 0x40 ++/* WL/BT control enable mask */ ++#define GPIO_CTRL_5_6_EN_MASK 0x60 ++#define GPIO_CTRL_7_6_EN_MASK 0xC0 ++#define GPIO_OUT_7_EN_MASK 0x80 ++ ++ ++ ++ ++/* === exported functions === */ ++extern si_t *si_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, ++ void *sdh, char **vars, uint *varsz); ++extern si_t *si_kattach(osl_t *osh); ++extern void si_detach(si_t *sih); ++ ++extern uint si_corelist(si_t *sih, uint coreid[]); ++extern uint si_coreid(si_t *sih); ++extern uint si_flag(si_t *sih); ++extern uint si_intflag(si_t *sih); ++extern uint si_coreidx(si_t *sih); ++extern uint si_coreunit(si_t *sih); ++extern uint si_corevendor(si_t *sih); ++extern uint si_corerev(si_t *sih); ++extern void *si_osh(si_t *sih); ++extern void si_setosh(si_t *sih, osl_t *osh); ++extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); ++extern void *si_coreregs(si_t *sih); ++extern uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val); ++extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val); ++extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); ++extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val); ++#ifdef WLC_HIGH_ONLY ++extern bool wlc_bmac_iscoreup(si_t *sih); ++#define si_iscoreup(sih) wlc_bmac_iscoreup(sih) ++#else ++extern bool si_iscoreup(si_t *sih); ++#endif /* __CONFIG_USBAP__ */ ++extern uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit); ++extern void *si_setcoreidx(si_t *sih, uint coreidx); ++extern void *si_setcore(si_t *sih, uint coreid, uint coreunit); ++extern void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val); ++extern void si_restore_core(si_t *sih, uint coreid, uint intr_val); ++extern int si_numaddrspaces(si_t *sih); ++extern uint32 si_addrspace(si_t *sih, uint asidx); ++extern uint32 si_addrspacesize(si_t *sih, uint asidx); ++extern void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); ++extern int si_corebist(si_t *sih); ++extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits); ++extern void si_core_disable(si_t *sih, uint32 bits); ++extern uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m); ++extern uint32 si_clock(si_t *sih); ++extern uint32 si_alp_clock(si_t *sih); ++extern void si_setint(si_t *sih, int siflag); ++extern bool si_backplane64(si_t *sih); ++extern void si_clkctl_init(si_t *sih); ++extern bool si_clkctl_cc(si_t *sih, uint mode); ++extern int si_clkctl_xtal(si_t *sih, uint what, bool on); ++ ++extern uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority); ++extern uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority); ++ ++/* Wake-on-wireless-LAN (WOWL) */ ++extern bool si_pci_pmecap(si_t *sih); ++struct osl_info; ++extern bool si_pci_fastpmecap(struct osl_info *osh); ++ ++/* SPROM availability */ ++#ifdef SI_SPROM_PROBE ++extern void si_sprom_init(si_t *sih); ++#endif /* SI_SPROM_PROBE */ ++ ++/* Fab-id information */ ++#define DEFAULT_FAB 0x0 /* Original/first fab used for this chip */ ++#define CSM_FAB7 0x1 /* CSM Fab7 chip */ ++#define TSMC_FAB12 0x2 /* TSMC Fab12/Fab14 chip */ ++#define SMIC_FAB4 0x3 /* SMIC Fab4 chip */ ++ ++/* ++ * Build device path. Path size must be >= SI_DEVPATH_BUFSZ. ++ * The returned path is NULL terminated and has trailing '/'. ++ * Return 0 on success, nonzero otherwise. ++ */ ++extern int si_devpath(si_t *sih, char *path, int size); ++/* Read variable with prepending the devpath to the name */ ++extern int si_getdevpathintvar(si_t *sih, const char *name); ++extern char *si_coded_devpathvar(si_t *sih, char *varname, int var_len, const char *name); ++ ++ ++extern void si_war42780_clkreq(si_t *sih, bool clkreq); ++extern void si_pcie_extendL1timer(si_t *sih, bool extend); ++ ++/* === debug routines === */ ++ ++#ifdef BCMDBG ++extern void si_view(si_t *sih, bool verbose); ++extern void si_viewall(si_t *sih, bool verbose); ++#endif ++ ++#if defined(BCMDBG) ++struct bcmstrbuf; ++extern void si_dumpregs(si_t *sih, struct bcmstrbuf *b); ++#endif ++ ++ ++#endif /* _siutils_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/trxhdr.h b/drivers/bcmdrivers/gmac/src/include/trxhdr.h +new file mode 100755 +index 0000000..4926311 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/trxhdr.h +@@ -0,0 +1,86 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * TRX image file header format. ++ * ++ * $Id: trxhdr.h 314841 2012-02-14 18:28:33Z $ ++ */ ++ ++#ifndef _TRX_HDR_H ++#define _TRX_HDR_H ++ ++#include ++ ++#define TRX_MAGIC 0x30524448 /* "HDR0" */ ++#define TRX_MAX_LEN 0x3B0000 /* Max length */ ++#define TRX_NO_HEADER 1 /* Do not write TRX header */ ++#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ ++#define TRX_EMBED_UCODE 0x8 /* Trx contains embedded ucode image */ ++#define TRX_ROMSIM_IMAGE 0x10 /* Trx contains ROM simulation image */ ++#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed rtecdc.bin image */ ++#define TRX_BOOTLOADER 0x40 /* the image is a bootloader */ ++ ++#define TRX_V1 1 ++#define TRX_V1_MAX_OFFSETS 3 /* V1: Max number of individual files */ ++ ++#ifndef BCMTRXV2 ++#define TRX_VERSION TRX_V1 /* Version 1 */ ++#define TRX_MAX_OFFSET TRX_V1_MAX_OFFSETS ++#endif ++ ++/* BMAC Host driver/application like bcmdl need to support both Ver 1 as well as ++ * Ver 2 of trx header. To make it generic, trx_header is structure is modified ++ * as below where size of "offsets" field will vary as per the TRX version. ++ * Currently, BMAC host driver and bcmdl are modified to support TRXV2 as well. ++ * To make sure, other applications like "dhdl" which are yet to be enhanced to support ++ * TRXV2 are not broken, new macro and structure defintion take effect only when BCMTRXV2 ++ * is defined. ++ */ ++struct trx_header { ++ uint32 magic; /* "HDR0" */ ++ uint32 len; /* Length of file including header */ ++ uint32 crc32; /* 32-bit CRC from flag_version to end of file */ ++ uint32 flag_version; /* 0:15 flags, 16:31 version */ ++#ifndef BCMTRXV2 ++ uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ ++#else ++ uint32 offsets[1]; /* Offsets of partitions from start of header */ ++#endif ++}; ++ ++#ifdef BCMTRXV2 ++#define TRX_VERSION TRX_V2 /* Version 2 */ ++#define TRX_MAX_OFFSET TRX_V2_MAX_OFFSETS ++ ++#define TRX_V2 2 ++/* V2: Max number of individual files ++ * To support SDR signature + Config data region ++ */ ++#define TRX_V2_MAX_OFFSETS 5 ++#define SIZEOF_TRXHDR_V1 (sizeof(struct trx_header)+(TRX_V1_MAX_OFFSETS-1)*sizeof(uint32)) ++#define SIZEOF_TRXHDR_V2 (sizeof(struct trx_header)+(TRX_V2_MAX_OFFSETS-1)*sizeof(uint32)) ++#define TRX_VER(trx) (trx->flag_version>>16) ++#define ISTRX_V1(trx) (TRX_VER(trx) == TRX_V1) ++#define ISTRX_V2(trx) (TRX_VER(trx) == TRX_V2) ++/* For V2, return size of V2 size: others, return V1 size */ ++#define SIZEOF_TRX(trx) (ISTRX_V2(trx) ? SIZEOF_TRXHDR_V2: SIZEOF_TRXHDR_V1) ++#else ++#define SIZEOF_TRX(trx) (sizeof(struct trx_header)) ++#endif /* BCMTRXV2 */ ++ ++/* Compatibility */ ++typedef struct trx_header TRXHDR, *PTRXHDR; ++ ++#endif /* _TRX_HDR_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/typedefs.h b/drivers/bcmdrivers/gmac/src/include/typedefs.h +new file mode 100644 +index 0000000..5caa36a +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/typedefs.h +@@ -0,0 +1,452 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: typedefs.h 286783 2011-09-29 06:18:57Z $ ++ */ ++ ++#ifndef _TYPEDEFS_H_ ++#define _TYPEDEFS_H_ ++ ++#ifdef SITE_TYPEDEFS ++ ++/* ++ * Define SITE_TYPEDEFS in the compile to include a site-specific ++ * typedef file "site_typedefs.h". ++ * ++ * If SITE_TYPEDEFS is not defined, then the code section below makes ++ * inferences about the compile environment based on defined symbols and ++ * possibly compiler pragmas. ++ * ++ * Following these two sections is the Default Typedefs section. ++ * This section is only processed if USE_TYPEDEF_DEFAULTS is ++ * defined. This section has a default set of typedefs and a few ++ * preprocessor symbols (TRUE, FALSE, NULL, ...). ++ */ ++ ++#include "site_typedefs.h" ++ ++#else ++ ++/* ++ * Infer the compile environment based on preprocessor symbols and pragmas. ++ * Override type definitions as needed, and include configuration-dependent ++ * header files to define types. ++ */ ++ ++#ifdef __cplusplus ++ ++#define TYPEDEF_BOOL ++#ifndef FALSE ++#define FALSE false ++#endif ++#ifndef TRUE ++#define TRUE true ++#endif ++ ++#else /* ! __cplusplus */ ++ ++#if defined(_WIN32) ++ ++#define TYPEDEF_BOOL ++typedef unsigned char bool; /* consistent w/BOOL */ ++ ++#endif /* _WIN32 */ ++ ++#endif /* ! __cplusplus */ ++ ++#if defined(_WIN64) && !defined(EFI) ++/* use the Windows ULONG_PTR type when compiling for 64 bit */ ++#include ++#define TYPEDEF_UINTPTR ++typedef ULONG_PTR uintptr; ++#elif defined(__x86_64__) ++#define TYPEDEF_UINTPTR ++typedef unsigned long long int uintptr; ++#endif ++ ++ ++#if defined(_MINOSL_) ++#define _NEED_SIZE_T_ ++#endif ++ ++#if defined(EFI) && !defined(_WIN64) ++#define _NEED_SIZE_T_ ++#endif ++ ++#if defined(TARGETOS_nucleus) ++/* for 'size_t' type */ ++#include ++ ++/* float_t types conflict with the same typedefs from the standard ANSI-C ++** math.h header file. Don't re-typedef them here. ++*/ ++#define TYPEDEF_FLOAT_T ++#endif /* TARGETOS_nucleus */ ++ ++#if defined(_NEED_SIZE_T_) ++typedef long unsigned int size_t; ++#endif ++ ++#ifdef _MSC_VER /* Microsoft C */ ++#define TYPEDEF_INT64 ++#define TYPEDEF_UINT64 ++typedef signed __int64 int64; ++typedef unsigned __int64 uint64; ++#endif ++ ++#if defined(MACOSX) ++#define TYPEDEF_BOOL ++#endif ++ ++#if defined(__NetBSD__) ++#define TYPEDEF_BOOL ++#ifndef _KERNEL ++#include ++#endif ++#define TYPEDEF_UINT ++#define TYPEDEF_USHORT ++#define TYPEDEF_ULONG ++#endif /* defined(__NetBSD__) */ ++ ++#if defined(__sparc__) ++#define TYPEDEF_ULONG ++#endif ++ ++ ++#ifdef linux ++/* ++ * If this is either a Linux hybrid build or the per-port code of a hybrid build ++ * then use the Linux header files to get some of the typedefs. Otherwise, define ++ * them entirely in this file. We can't always define the types because we get ++ * a duplicate typedef error; there is no way to "undefine" a typedef. ++ * We know when it's per-port code because each file defines LINUX_PORT at the top. ++ */ ++#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) ++#define TYPEDEF_UINT ++#ifndef TARGETENV_android ++#define TYPEDEF_USHORT ++#define TYPEDEF_ULONG ++#endif /* TARGETENV_android */ ++#ifdef __KERNEL__ ++#include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)) ++#define TYPEDEF_BOOL ++#endif /* >= 2.6.19 */ ++/* special detection for 2.6.18-128.7.1.0.1.el5 */ ++#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18)) ++#include ++#ifdef noinline_for_stack ++#define TYPEDEF_BOOL ++#endif ++#endif /* == 2.6.18 */ ++#endif /* __KERNEL__ */ ++#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ ++#endif /* linux */ ++ ++#if defined(__ECOS) ++#define TYPEDEF_UCHAR ++#define TYPEDEF_UINT ++#define TYPEDEF_USHORT ++#define TYPEDEF_ULONG ++#define TYPEDEF_BOOL ++#endif ++ ++#if !defined(linux) && !defined(_WIN32) && !defined(_CFE_) && !defined(_MINOSL_) && \ ++ !defined(__DJGPP__) && !defined(__ECOS) && !defined(__BOB__) && \ ++ !defined(TARGETOS_nucleus) && !defined(EFI) && !defined(__FreeBSD__) ++#define TYPEDEF_UINT ++#define TYPEDEF_USHORT ++#endif ++ ++ ++/* Do not support the (u)int64 types with strict ansi for GNU C */ ++#if defined(__GNUC__) && defined(__STRICT_ANSI__) ++#define TYPEDEF_INT64 ++#define TYPEDEF_UINT64 ++#endif ++ ++/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode ++ * for signed or unsigned ++ */ ++#if defined(__ICL) ++ ++#define TYPEDEF_INT64 ++ ++#if defined(__STDC__) ++#define TYPEDEF_UINT64 ++#endif ++ ++#endif /* __ICL */ ++ ++#if !defined(_WIN32) && !defined(_CFE_) && !defined(_MINOSL_) && !defined(__DJGPP__) && \ ++ !defined(__BOB__) && !defined(TARGETOS_nucleus) && !defined(EFI) ++ ++/* pick up ushort & uint from standard types.h */ ++#if defined(linux) && defined(__KERNEL__) ++ ++/* See note above */ ++#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) ++#ifdef USER_MODE ++#include ++#else ++#include /* sys/types.h and linux/types.h are oil and water */ ++#endif /* USER_MODE */ ++#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ ++ ++#else ++ ++#if defined(__ECOS) ++#include ++#include ++#include ++#endif ++ ++#include ++ ++#endif /* linux && __KERNEL__ */ ++ ++#endif ++ ++#if defined(CONFIG_MACH_NSP) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) /* JIRA:LINUXDEV- */ ++#ifdef CONFIG_CPU_BIG_ENDIAN ++#define IL_BIGENDIAN ++#endif /* CONFIG_CPU_BIG_ENDIAN */ ++#else ++ ++#ifdef IL_BIGENDIAN ++#error "IL_BIGENDIAN was defined for a little-endian compile" ++#endif ++ ++#endif ++ ++#if defined(MACOSX) ++ ++#ifdef __BIG_ENDIAN__ ++#define IL_BIGENDIAN ++#else ++#ifdef IL_BIGENDIAN ++#error "IL_BIGENDIAN was defined for a little-endian compile" ++#endif ++#endif /* __BIG_ENDIAN__ */ ++ ++#if !defined(__cplusplus) ++ ++#if defined(__i386__) ++typedef unsigned char bool; ++#else ++typedef unsigned int bool; ++#endif ++#define TYPE_BOOL 1 ++enum { ++ false = 0, ++ true = 1 ++}; ++ ++#if defined(KERNEL) ++#include ++#endif /* KERNEL */ ++ ++#endif /* __cplusplus */ ++ ++#endif /* MACOSX */ ++ ++ ++/* use the default typedefs in the next section of this file */ ++#define USE_TYPEDEF_DEFAULTS ++ ++#endif /* SITE_TYPEDEFS */ ++ ++ ++/* ++ * Default Typedefs ++ */ ++ ++#ifdef USE_TYPEDEF_DEFAULTS ++#undef USE_TYPEDEF_DEFAULTS ++ ++#ifndef TYPEDEF_BOOL ++typedef /* @abstract@ */ unsigned char bool; ++#endif ++ ++/* define uchar, ushort, uint, ulong */ ++ ++#ifndef TYPEDEF_UCHAR ++typedef unsigned char uchar; ++#endif ++ ++#ifndef TYPEDEF_USHORT ++typedef unsigned short ushort; ++#endif ++ ++#ifndef TYPEDEF_UINT ++typedef unsigned int uint; ++#endif ++ ++#ifndef TYPEDEF_ULONG ++typedef unsigned long ulong; ++#endif ++ ++/* define [u]int8/16/32/64, uintptr */ ++ ++#ifndef TYPEDEF_UINT8 ++typedef unsigned char uint8; ++#endif ++ ++#ifndef TYPEDEF_UINT16 ++typedef unsigned short uint16; ++#endif ++ ++#ifndef TYPEDEF_UINT32 ++typedef unsigned int uint32; ++#endif ++ ++#ifndef TYPEDEF_UINT64 ++typedef unsigned long long uint64; ++#endif ++ ++#ifndef TYPEDEF_UINTPTR ++typedef unsigned int uintptr; ++#endif ++ ++#ifndef TYPEDEF_INT8 ++typedef signed char int8; ++#endif ++ ++#ifndef TYPEDEF_INT16 ++typedef signed short int16; ++#endif ++ ++#ifndef TYPEDEF_INT32 ++typedef signed int int32; ++#endif ++ ++#ifndef TYPEDEF_INT64 ++typedef signed long long int64; ++#endif ++ ++/* define float32/64, float_t */ ++ ++#ifndef TYPEDEF_FLOAT32 ++typedef float float32; ++#endif ++ ++#ifndef TYPEDEF_FLOAT64 ++typedef double float64; ++#endif ++ ++/* ++ * abstracted floating point type allows for compile time selection of ++ * single or double precision arithmetic. Compiling with -DFLOAT32 ++ * selects single precision; the default is double precision. ++ */ ++ ++#ifndef TYPEDEF_FLOAT_T ++ ++#if defined(FLOAT32) ++typedef float32 float_t; ++#else /* default to double precision floating point */ ++typedef float64 float_t; ++#endif ++ ++#endif /* TYPEDEF_FLOAT_T */ ++ ++/* define macro values */ ++ ++#ifndef FALSE ++#define FALSE 0 ++#endif ++ ++#ifndef TRUE ++#define TRUE 1 /* TRUE */ ++#endif ++ ++#ifndef NULL ++#define NULL 0 ++#endif ++ ++#ifndef OFF ++#define OFF 0 ++#endif ++ ++#ifndef ON ++#define ON 1 /* ON = 1 */ ++#endif ++ ++#define AUTO (-1) /* Auto = -1 */ ++ ++/* define PTRSZ, INLINE */ ++ ++#ifndef PTRSZ ++#define PTRSZ sizeof(char*) ++#endif ++ ++ ++/* Detect compiler type. */ ++#ifdef _MSC_VER ++ #define BWL_COMPILER_MICROSOFT ++#elif defined(__GNUC__) || defined(__lint) ++ #define BWL_COMPILER_GNU ++#elif defined(__CC_ARM) && __CC_ARM ++ #define BWL_COMPILER_ARMCC ++#else ++ #error "Unknown compiler!" ++#endif /* _MSC_VER */ ++ ++ ++#ifndef INLINE ++ #if defined(BWL_COMPILER_MICROSOFT) ++ #define INLINE __inline ++ #elif defined(BWL_COMPILER_GNU) ++ #define INLINE __inline__ ++ #elif defined(BWL_COMPILER_ARMCC) ++ #define INLINE __inline ++ #else ++ #define INLINE ++ #endif /* _MSC_VER */ ++#endif /* INLINE */ ++ ++#undef TYPEDEF_BOOL ++#undef TYPEDEF_UCHAR ++#undef TYPEDEF_USHORT ++#undef TYPEDEF_UINT ++#undef TYPEDEF_ULONG ++#undef TYPEDEF_UINT8 ++#undef TYPEDEF_UINT16 ++#undef TYPEDEF_UINT32 ++#undef TYPEDEF_UINT64 ++#undef TYPEDEF_UINTPTR ++#undef TYPEDEF_INT8 ++#undef TYPEDEF_INT16 ++#undef TYPEDEF_INT32 ++#undef TYPEDEF_INT64 ++#undef TYPEDEF_FLOAT32 ++#undef TYPEDEF_FLOAT64 ++#undef TYPEDEF_FLOAT_T ++ ++#endif /* USE_TYPEDEF_DEFAULTS */ ++ ++/* Suppress unused parameter warning */ ++#define UNUSED_PARAMETER(x) (void)(x) ++ ++/* Avoid warning for discarded const or volatile qualifier in special cases (-Wcast-qual) */ ++#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr)) ++ ++/* ++ * Including the bcmdefs.h here, to make sure everyone including typedefs.h ++ * gets this automatically ++*/ ++#include ++#endif /* _TYPEDEFS_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/wlioctl.h b/drivers/bcmdrivers/gmac/src/include/wlioctl.h +new file mode 100755 +index 0000000..3aef8ca +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/wlioctl.h +@@ -0,0 +1,4883 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Custom OID/ioctl definitions for ++ * Broadcom 802.11abg Networking Device Driver ++ * ++ * Definitions subject to change without notice. ++ * ++ * $Id: wlioctl.h 324203 2012-03-28 09:55:17Z $ ++ */ ++ ++#ifndef _wlioctl_h_ ++#define _wlioctl_h_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#ifdef __NetBSD__ ++/* NetBSD 2.0 does not have SIOCDEVPRIVATE. */ ++#define SIOCDEVPRIVATE _IOWR('i', 139, struct ifreq) ++#endif ++ ++#ifndef INTF_NAME_SIZ ++#define INTF_NAME_SIZ 16 ++#endif ++ ++/* Used to send ioctls over the transport pipe */ ++typedef struct remote_ioctl { ++ cdc_ioctl_t msg; ++ uint data_len; ++#ifndef OLYMPIC_RWL ++ char intf_name[INTF_NAME_SIZ]; ++#endif ++} rem_ioctl_t; ++#define REMOTE_SIZE sizeof(rem_ioctl_t) ++#ifdef EFI ++#define BCMWL_IOCTL_GUID \ ++ {0xB4910A35, 0x88C5, 0x4328, { 0x90, 0x08, 0x9F, 0xB2, 0x00, 0x00, 0x0, 0x0 } } ++#endif /* EFI */ ++ ++#define ACTION_FRAME_SIZE 1800 ++ ++typedef struct wl_action_frame { ++ struct ether_addr da; ++ uint16 len; ++ uint32 packetId; ++ uint8 data[ACTION_FRAME_SIZE]; ++} wl_action_frame_t; ++ ++#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame) ++ ++typedef struct ssid_info ++{ ++ uint8 ssid_len; /* the length of SSID */ ++ uint8 ssid[32]; /* SSID string */ ++} ssid_info_t; ++ ++typedef struct wl_af_params { ++ uint32 channel; ++ int32 dwell_time; ++ struct ether_addr BSSID; ++ wl_action_frame_t action_frame; ++} wl_af_params_t; ++ ++#define WL_WIFI_AF_PARAMS_SIZE sizeof(struct wl_af_params) ++ ++#define MFP_TEST_FLAG_NORMAL 0 ++#define MFP_TEST_FLAG_ANY_KEY 1 ++typedef struct wl_sa_query { ++ uint32 flag; ++ uint8 action; ++ uint16 id; ++ struct ether_addr da; ++} wl_sa_query_t; ++ ++ ++/* require default structure packing */ ++#define BWL_DEFAULT_PACKING ++#include ++ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* Legacy structure to help keep backward compatible wl tool and tray app */ ++ ++#define LEGACY_WL_BSS_INFO_VERSION 107 /* older version of wl_bss_info struct */ ++ ++typedef struct wl_bss_info_107 { ++ uint32 version; /* version field */ ++ uint32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ struct ether_addr BSSID; ++ uint16 beacon_period; /* units are Kusec */ ++ uint16 capability; /* Capability information */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct { ++ uint count; /* # rates in this set */ ++ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ uint8 channel; /* Channel no. */ ++ uint16 atim_window; /* units are Kusec */ ++ uint8 dtim_period; /* DTIM period */ ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ int8 phy_noise; /* noise (in dBm) */ ++ uint32 ie_length; /* byte length of Information Elements */ ++ /* variable length Information Elements */ ++} wl_bss_info_107_t; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* ++ * Per-BSS information structure. ++ */ ++ ++#define LEGACY2_WL_BSS_INFO_VERSION 108 /* old version of wl_bss_info struct */ ++ ++/* BSS info structure ++ * Applications MUST CHECK ie_offset field and length field to access IEs and ++ * next bss_info structure in a vector (in wl_scan_results_t) ++ */ ++typedef struct wl_bss_info_108 { ++ uint32 version; /* version field */ ++ uint32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ struct ether_addr BSSID; ++ uint16 beacon_period; /* units are Kusec */ ++ uint16 capability; /* Capability information */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct { ++ uint count; /* # rates in this set */ ++ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ chanspec_t chanspec; /* chanspec for bss */ ++ uint16 atim_window; /* units are Kusec */ ++ uint8 dtim_period; /* DTIM period */ ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ int8 phy_noise; /* noise (in dBm) */ ++ ++ uint8 n_cap; /* BSS is 802.11N Capable */ ++ uint32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */ ++ uint8 ctl_ch; /* 802.11N BSS control channel number */ ++ uint32 reserved32[1]; /* Reserved for expansion of BSS properties */ ++ uint8 flags; /* flags */ ++ uint8 reserved[3]; /* Reserved for expansion of BSS properties */ ++ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ ++ ++ uint16 ie_offset; /* offset at which IEs start, from beginning */ ++ uint32 ie_length; /* byte length of Information Elements */ ++ /* Add new fields here */ ++ /* variable length Information Elements */ ++} wl_bss_info_108_t; ++ ++#define WL_BSS_INFO_VERSION 109 /* current version of wl_bss_info struct */ ++ ++/* BSS info structure ++ * Applications MUST CHECK ie_offset field and length field to access IEs and ++ * next bss_info structure in a vector (in wl_scan_results_t) ++ */ ++typedef struct wl_bss_info { ++ uint32 version; /* version field */ ++ uint32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ struct ether_addr BSSID; ++ uint16 beacon_period; /* units are Kusec */ ++ uint16 capability; /* Capability information */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct { ++ uint count; /* # rates in this set */ ++ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ chanspec_t chanspec; /* chanspec for bss */ ++ uint16 atim_window; /* units are Kusec */ ++ uint8 dtim_period; /* DTIM period */ ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ int8 phy_noise; /* noise (in dBm) */ ++ ++ uint8 n_cap; /* BSS is 802.11N Capable */ ++ uint32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */ ++ uint8 ctl_ch; /* 802.11N BSS control channel number */ ++ uint16 vht_rxmcsmap; /* VHT rx mcs map */ ++ uint16 vht_txmcsmap; /* VHT tx mcs map */ ++ uint8 flags; /* flags */ ++ uint8 vht_cap; /* BSS is vht capable */ ++ uint8 reserved[2]; /* Reserved for expansion of BSS properties */ ++ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ ++ ++ uint16 ie_offset; /* offset at which IEs start, from beginning */ ++ uint32 ie_length; /* byte length of Information Elements */ ++ int16 SNR; /* average SNR of during frame reception */ ++ /* Add new fields here */ ++ /* variable length Information Elements */ ++} wl_bss_info_t; ++ ++typedef struct wl_bsscfg { ++ uint32 wsec; ++ uint32 WPA_auth; ++ uint32 wsec_index; ++ uint32 associated; ++ uint32 BSS; ++ uint32 phytest_on; ++ struct ether_addr prev_BSSID; ++ struct ether_addr BSSID; ++} wl_bsscfg_t; ++ ++typedef struct wl_bss_config { ++ uint32 atim_window; ++ uint32 beacon_period; ++ uint32 chanspec; ++} wl_bss_config_t; ++ ++#define DLOAD_HANDLER_VER 1 /* Downloader version */ ++#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */ ++#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */ ++ ++#define DL_CRC_NOT_INUSE 0x0001 ++ ++/* generic download types & flags */ ++enum { ++ DL_TYPE_UCODE = 1, ++ DL_TYPE_CLM = 2 ++}; ++ ++/* ucode type values */ ++enum { ++ UCODE_FW, ++ INIT_VALS, ++ BS_INIT_VALS ++}; ++ ++struct wl_dload_data { ++ uint16 flag; ++ uint16 dload_type; ++ uint32 len; ++ uint32 crc; ++ uint8 data[1]; ++}; ++typedef struct wl_dload_data wl_dload_data_t; ++ ++struct wl_ucode_info { ++ uint32 ucode_type; ++ uint32 num_chunks; ++ uint32 chunk_len; ++ uint32 chunk_num; ++ uint8 data_chunk[1]; ++}; ++typedef struct wl_ucode_info wl_ucode_info_t; ++ ++struct wl_clm_dload_info { ++ uint32 ds_id; ++ uint32 clm_total_len; ++ uint32 num_chunks; ++ uint32 chunk_len; ++ uint32 chunk_offset; ++ uint8 data_chunk[1]; ++}; ++typedef struct wl_clm_dload_info wl_clm_dload_info_t; ++ ++typedef struct wlc_ssid { ++ uint32 SSID_len; ++ uchar SSID[32]; ++} wlc_ssid_t; ++ ++#define MAX_PREFERRED_AP_NUM 5 ++typedef struct wlc_fastssidinfo { ++ uint32 SSID_channel[MAX_PREFERRED_AP_NUM]; ++ wlc_ssid_t SSID_info[MAX_PREFERRED_AP_NUM]; ++} wlc_fastssidinfo_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct wnm_url { ++ uint8 len; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT wnm_url_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++typedef struct chan_scandata { ++ uint8 txpower; ++ uint8 pad; ++ chanspec_t channel; /* Channel num, bw, ctrl_sb and band */ ++ uint32 channel_mintime; ++ uint32 channel_maxtime; ++} chan_scandata_t; ++ ++typedef enum wl_scan_type { ++ EXTDSCAN_FOREGROUND_SCAN, ++ EXTDSCAN_BACKGROUND_SCAN, ++ EXTDSCAN_FORCEDBACKGROUND_SCAN ++} wl_scan_type_t; ++ ++#define WLC_EXTDSCAN_MAX_SSID 5 ++ ++#define WL_BSS_FLAGS_FROM_BEACON 0x01 /* bss_info derived from beacon */ ++#define WL_BSS_FLAGS_FROM_CACHE 0x02 /* bss_info collected from cache */ ++#define WL_BSS_FLAGS_RSSI_ONCHANNEL 0x04 /* rssi info was received on channel (vs offchannel) */ ++ ++typedef struct wl_extdscan_params { ++ int8 nprobes; /* 0, passive, otherwise active */ ++ int8 split_scan; /* split scan */ ++ int8 band; /* band */ ++ int8 pad; ++ wlc_ssid_t ssid[WLC_EXTDSCAN_MAX_SSID]; /* ssid list */ ++ uint32 tx_rate; /* in 500ksec units */ ++ wl_scan_type_t scan_type; /* enum */ ++ int32 channel_num; ++ chan_scandata_t channel_list[1]; /* list of chandata structs */ ++} wl_extdscan_params_t; ++ ++#define WL_EXTDSCAN_PARAMS_FIXED_SIZE (sizeof(wl_extdscan_params_t) - sizeof(chan_scandata_t)) ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define WL_BSSTYPE_INFRA 1 ++#define WL_BSSTYPE_INDEP 0 ++#define WL_BSSTYPE_ANY 2 ++ ++/* Bitmask for scan_type */ ++#define WL_SCANFLAGS_PASSIVE 0x01 /* force passive scan */ ++#define WL_SCANFLAGS_RESERVED 0x02 /* Reserved */ ++#define WL_SCANFLAGS_PROHIBITED 0x04 /* allow scanning prohibited channels */ ++ ++#define WL_SCAN_PARAMS_SSID_MAX 10 ++ ++typedef struct wl_scan_params { ++ wlc_ssid_t ssid; /* default: {0, ""} */ ++ struct ether_addr bssid; /* default: bcast */ ++ int8 bss_type; /* default: any, ++ * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT ++ */ ++ uint8 scan_type; /* flags, 0 use default */ ++ int32 nprobes; /* -1 use default, number of probes per channel */ ++ int32 active_time; /* -1 use default, dwell time per channel for ++ * active scanning ++ */ ++ int32 passive_time; /* -1 use default, dwell time per channel ++ * for passive scanning ++ */ ++ int32 home_time; /* -1 use default, dwell time for the home channel ++ * between channel scans ++ */ ++ int32 channel_num; /* count of channels and ssids that follow ++ * ++ * low half is count of channels in channel_list, 0 ++ * means default (use all available channels) ++ * ++ * high half is entries in wlc_ssid_t array that ++ * follows channel_list, aligned for int32 (4 bytes) ++ * meaning an odd channel count implies a 2-byte pad ++ * between end of channel_list and first ssid ++ * ++ * if ssid count is zero, single ssid in the fixed ++ * parameter portion is assumed, otherwise ssid in ++ * the fixed portion is ignored ++ */ ++ uint16 channel_list[1]; /* list of chanspecs */ ++} wl_scan_params_t; ++ ++/* size of wl_scan_params not including variable length array */ ++#define WL_SCAN_PARAMS_FIXED_SIZE 64 ++ ++/* masks for channel and ssid count */ ++#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff ++#define WL_SCAN_PARAMS_NSSID_SHIFT 16 ++ ++#define WL_SCAN_ACTION_START 1 ++#define WL_SCAN_ACTION_CONTINUE 2 ++#define WL_SCAN_ACTION_ABORT 3 ++ ++#define ISCAN_REQ_VERSION 1 ++ ++/* incremental scan struct */ ++typedef struct wl_iscan_params { ++ uint32 version; ++ uint16 action; ++ uint16 scan_duration; ++ wl_scan_params_t params; ++} wl_iscan_params_t; ++ ++/* 3 fields + size of wl_scan_params, not including variable length array */ ++#define WL_ISCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_iscan_params_t, params) + sizeof(wlc_ssid_t)) ++ ++typedef struct wl_scan_results { ++ uint32 buflen; ++ uint32 version; ++ uint32 count; ++ wl_bss_info_t bss_info[1]; ++} wl_scan_results_t; ++ ++/* size of wl_scan_results not including variable length array */ ++#define WL_SCAN_RESULTS_FIXED_SIZE (sizeof(wl_scan_results_t) - sizeof(wl_bss_info_t)) ++ ++/* wl_iscan_results status values */ ++#define WL_SCAN_RESULTS_SUCCESS 0 ++#define WL_SCAN_RESULTS_PARTIAL 1 ++#define WL_SCAN_RESULTS_PENDING 2 ++#define WL_SCAN_RESULTS_ABORTED 3 ++#define WL_SCAN_RESULTS_NO_MEM 4 ++ ++/* Used in EXT_STA */ ++#define DNGL_RXCTXT_SIZE 45 ++ ++#if defined(SIMPLE_ISCAN) ++#define ISCAN_RETRY_CNT 5 ++#define ISCAN_STATE_IDLE 0 ++#define ISCAN_STATE_SCANING 1 ++#define ISCAN_STATE_PENDING 2 ++ ++/* the buf lengh can be WLC_IOCTL_MAXLEN (8K) to reduce iteration */ ++#define WLC_IW_ISCAN_MAXLEN 2048 ++typedef struct iscan_buf { ++ struct iscan_buf * next; ++ char iscan_buf[WLC_IW_ISCAN_MAXLEN]; ++} iscan_buf_t; ++#endif /* SIMPLE_ISCAN */ ++ ++#define ESCAN_REQ_VERSION 1 ++ ++typedef struct wl_escan_params { ++ uint32 version; ++ uint16 action; ++ uint16 sync_id; ++ wl_scan_params_t params; ++} wl_escan_params_t; ++ ++#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t)) ++ ++typedef struct wl_escan_result { ++ uint32 buflen; ++ uint32 version; ++ uint16 sync_id; ++ uint16 bss_count; ++ wl_bss_info_t bss_info[1]; ++} wl_escan_result_t; ++ ++#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t)) ++ ++/* incremental scan results struct */ ++typedef struct wl_iscan_results { ++ uint32 status; ++ wl_scan_results_t results; ++} wl_iscan_results_t; ++ ++/* size of wl_iscan_results not including variable length array */ ++#define WL_ISCAN_RESULTS_FIXED_SIZE \ ++ (WL_SCAN_RESULTS_FIXED_SIZE + OFFSETOF(wl_iscan_results_t, results)) ++ ++typedef struct wl_probe_params { ++ wlc_ssid_t ssid; ++ struct ether_addr bssid; ++ struct ether_addr mac; ++} wl_probe_params_t; ++ ++#define WL_MAXRATES_IN_SET 16 /* max # of rates in a rateset */ ++typedef struct wl_rateset { ++ uint32 count; /* # rates in this set */ ++ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ ++} wl_rateset_t; ++ ++typedef struct wl_rateset_args { ++ uint32 count; /* # rates in this set */ ++ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ ++ uint8 mcs[MCSSET_LEN]; /* supported mcs index bit map */ ++} wl_rateset_args_t; ++ ++/* uint32 list */ ++typedef struct wl_uint32_list { ++ /* in - # of elements, out - # of entries */ ++ uint32 count; ++ /* variable length uint32 list */ ++ uint32 element[1]; ++} wl_uint32_list_t; ++ ++/* used for association with a specific BSSID and chanspec list */ ++typedef struct wl_assoc_params { ++ struct ether_addr bssid; /* 00:00:00:00:00:00: broadcast scan */ ++ int32 chanspec_num; /* 0: all available channels, ++ * otherwise count of chanspecs in chanspec_list ++ */ ++ chanspec_t chanspec_list[1]; /* list of chanspecs */ ++} wl_assoc_params_t; ++#define WL_ASSOC_PARAMS_FIXED_SIZE OFFSETOF(wl_assoc_params_t, chanspec_list) ++ ++/* used for reassociation/roam to a specific BSSID and channel */ ++typedef wl_assoc_params_t wl_reassoc_params_t; ++#define WL_REASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE ++ ++/* used for association to a specific BSSID and channel */ ++typedef wl_assoc_params_t wl_join_assoc_params_t; ++#define WL_JOIN_ASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE ++ ++/* used for join with or without a specific bssid and channel list */ ++typedef struct wl_join_params { ++ wlc_ssid_t ssid; ++ wl_assoc_params_t params; /* optional field, but it must include the fixed portion ++ * of the wl_assoc_params_t struct when it does present. ++ */ ++} wl_join_params_t; ++#define WL_JOIN_PARAMS_FIXED_SIZE (OFFSETOF(wl_join_params_t, params) + \ ++ WL_ASSOC_PARAMS_FIXED_SIZE) ++/* scan params for extended join */ ++typedef struct wl_join_scan_params { ++ uint8 scan_type; /* 0 use default, active or passive scan */ ++ int32 nprobes; /* -1 use default, number of probes per channel */ ++ int32 active_time; /* -1 use default, dwell time per channel for ++ * active scanning ++ */ ++ int32 passive_time; /* -1 use default, dwell time per channel ++ * for passive scanning ++ */ ++ int32 home_time; /* -1 use default, dwell time for the home channel ++ * between channel scans ++ */ ++} wl_join_scan_params_t; ++ ++/* extended join params */ ++typedef struct wl_extjoin_params { ++ wlc_ssid_t ssid; /* {0, ""}: wildcard scan */ ++ wl_join_scan_params_t scan; ++ wl_join_assoc_params_t assoc; /* optional field, but it must include the fixed portion ++ * of the wl_join_assoc_params_t struct when it does ++ * present. ++ */ ++} wl_extjoin_params_t; ++#define WL_EXTJOIN_PARAMS_FIXED_SIZE (OFFSETOF(wl_extjoin_params_t, assoc) + \ ++ WL_JOIN_ASSOC_PARAMS_FIXED_SIZE) ++ ++/* All builds use the new 11ac ratespec/chanspec */ ++#undef D11AC_IOTYPES ++#define D11AC_IOTYPES ++ ++#ifndef D11AC_IOTYPES ++ ++/* defines used by the nrate iovar */ ++#define NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ ++#define NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ ++#define NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */ ++#define NRATE_STF_SHIFT 8 /* stf mode shift */ ++#define NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */ ++#define NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */ ++#define NRATE_SGI_MASK 0x00800000 /* sgi mode */ ++#define NRATE_SGI_SHIFT 23 /* sgi mode */ ++#define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ ++#define NRATE_LDPC_SHIFT 22 /* ldpc shift */ ++ ++#define NRATE_STF_SISO 0 /* stf mode SISO */ ++#define NRATE_STF_CDD 1 /* stf mode CDD */ ++#define NRATE_STF_STBC 2 /* stf mode STBC */ ++#define NRATE_STF_SDM 3 /* stf mode SDM */ ++ ++#else /* D11AC_IOTYPES */ ++ ++/* WL_RSPEC defines for rate information */ ++#define WL_RSPEC_RATE_MASK 0x000000FF /* rate or HT MCS value */ ++#define WL_RSPEC_VHT_MCS_MASK 0x0000000F /* VHT MCS value */ ++#define WL_RSPEC_VHT_NSS_MASK 0x000000F0 /* VHT Nss value */ ++#define WL_RSPEC_VHT_NSS_SHIFT 4 /* VHT Nss value shift */ ++#define WL_RSPEC_TXEXP_MASK 0x00000300 ++#define WL_RSPEC_TXEXP_SHIFT 8 ++#define WL_RSPEC_BW_MASK 0x00070000 /* bandwidth mask */ ++#define WL_RSPEC_BW_SHIFT 16 /* bandwidth shift */ ++#define WL_RSPEC_STBC 0x00100000 /* STBC encoding, Nsts = 2 x Nss */ ++#define WL_RSPEC_LDPC 0x00400000 /* bit indicates adv coding in use */ ++#define WL_RSPEC_SGI 0x00800000 /* Short GI mode */ ++#define WL_RSPEC_ENCODING_MASK 0x03000000 /* Encoding of Rate/MCS field */ ++#define WL_RSPEC_OVERRIDE_RATE 0x40000000 /* bit indicate to override mcs only */ ++#define WL_RSPEC_OVERRIDE_MODE 0x80000000 /* bit indicates override both rate & mode */ ++ ++/* WL_RSPEC_ENCODING field defs */ ++#define WL_RSPEC_ENCODE_RATE 0x00000000 /* Legacy rate is stored in RSPEC_RATE_MASK */ ++#define WL_RSPEC_ENCODE_HT 0x01000000 /* HT MCS is stored in RSPEC_RATE_MASK */ ++#define WL_RSPEC_ENCODE_VHT 0x02000000 /* VHT MCS and Nss is stored in RSPEC_RATE_MASK */ ++ ++/* WL_RSPEC_BW field defs */ ++#define WL_RSPEC_BW_UNSPECIFIED 0 ++#define WL_RSPEC_BW_20MHZ 0x00010000 ++#define WL_RSPEC_BW_40MHZ 0x00020000 ++#define WL_RSPEC_BW_80MHZ 0x00030000 ++#define WL_RSPEC_BW_160MHZ 0x00040000 ++ ++/* Legacy defines for the nrate iovar */ ++#define OLD_NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ ++#define OLD_NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ ++#define OLD_NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */ ++#define OLD_NRATE_STF_SHIFT 8 /* stf mode shift */ ++#define OLD_NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */ ++#define OLD_NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */ ++#define OLD_NRATE_SGI 0x00800000 /* sgi mode */ ++#define OLD_NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ ++ ++#define OLD_NRATE_STF_SISO 0 /* stf mode SISO */ ++#define OLD_NRATE_STF_CDD 1 /* stf mode CDD */ ++#define OLD_NRATE_STF_STBC 2 /* stf mode STBC */ ++#define OLD_NRATE_STF_SDM 3 /* stf mode SDM */ ++ ++#endif /* D11AC_IOTYPES */ ++ ++#define ANTENNA_NUM_1 1 /* total number of antennas to be used */ ++#define ANTENNA_NUM_2 2 ++#define ANTENNA_NUM_3 3 ++#define ANTENNA_NUM_4 4 ++ ++#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */ ++#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */ ++#define ANT_SELCFG_MAX 4 /* max number of antenna configurations */ ++#define ANT_SELCFG_TX_UNICAST 0 /* unicast tx antenna configuration */ ++#define ANT_SELCFG_RX_UNICAST 1 /* unicast rx antenna configuration */ ++#define ANT_SELCFG_TX_DEF 2 /* default tx antenna configuration */ ++#define ANT_SELCFG_RX_DEF 3 /* default rx antenna configuration */ ++ ++#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */ ++ ++typedef struct { ++ uint8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */ ++ uint8 num_antcfg; /* number of available antenna configurations */ ++} wlc_antselcfg_t; ++ ++#define HIGHEST_SINGLE_STREAM_MCS 7 /* MCS values greater than this enable multiple streams */ ++ ++#define MAX_CCA_CHANNELS 38 /* Max number of 20 Mhz wide channels */ ++#define MAX_CCA_SECS 60 /* CCA keeps this many seconds history */ ++ ++#define IBSS_MED 15 /* Mediom in-bss congestion percentage */ ++#define IBSS_HI 25 /* Hi in-bss congestion percentage */ ++#define OBSS_MED 12 ++#define OBSS_HI 25 ++#define INTERFER_MED 5 ++#define INTERFER_HI 10 ++ ++#define CCA_FLAG_2G_ONLY 0x01 /* Return a channel from 2.4 Ghz band */ ++#define CCA_FLAG_5G_ONLY 0x02 /* Return a channel from 2.4 Ghz band */ ++#define CCA_FLAG_IGNORE_DURATION 0x04 /* Ignore dwell time for each channel */ ++#define CCA_FLAGS_PREFER_1_6_11 0x10 ++#define CCA_FLAG_IGNORE_INTERFER 0x20 /* do not exlude channel based on interfer level */ ++ ++#define CCA_ERRNO_BAND 1 /* After filtering for band pref, no choices left */ ++#define CCA_ERRNO_DURATION 2 /* After filtering for duration, no choices left */ ++#define CCA_ERRNO_PREF_CHAN 3 /* After filtering for chan pref, no choices left */ ++#define CCA_ERRNO_INTERFER 4 /* After filtering for interference, no choices left */ ++#define CCA_ERRNO_TOO_FEW 5 /* Only 1 channel was input */ ++ ++typedef struct { ++ uint32 duration; /* millisecs spent sampling this channel */ ++ uint32 congest_ibss; /* millisecs in our bss (presumably this traffic will */ ++ /* move if cur bss moves channels) */ ++ uint32 congest_obss; /* traffic not in our bss */ ++ uint32 interference; /* millisecs detecting a non 802.11 interferer. */ ++ uint32 timestamp; /* second timestamp */ ++} cca_congest_t; ++ ++typedef struct { ++ chanspec_t chanspec; /* Which channel? */ ++ uint8 num_secs; /* How many secs worth of data */ ++ cca_congest_t secs[1]; /* Data */ ++} cca_congest_channel_req_t; ++ ++/* interference source detection and identification mode */ ++#define ITFR_MODE_DISABLE 0 /* disable feature */ ++#define ITFR_MODE_MANUAL_ENABLE 1 /* enable manual detection */ ++#define ITFR_MODE_AUTO_ENABLE 2 /* enable auto detection */ ++ ++/* interference sources */ ++enum interference_source { ++ ITFR_NONE = 0, /* interference */ ++ ITFR_PHONE, /* wireless phone */ ++ ITFR_VIDEO_CAMERA, /* wireless video camera */ ++ ITFR_MICROWAVE_OVEN, /* microwave oven */ ++ ITFR_BABY_MONITOR, /* wireless baby monitor */ ++ ITFR_BLUETOOTH, /* bluetooth */ ++ ITFR_VIDEO_CAMERA_OR_BABY_MONITOR, /* wireless camera or baby monitor */ ++ ITFR_BLUETOOTH_OR_BABY_MONITOR, /* bluetooth or baby monitor */ ++ ITFR_VIDEO_CAMERA_OR_PHONE, /* video camera or phone */ ++ ITFR_UNIDENTIFIED /* interference from unidentified source */ ++}; ++ ++/* structure for interference source report */ ++typedef struct { ++ uint32 flags; /* flags. bit definitions below */ ++ uint32 source; /* last detected interference source */ ++ uint32 timestamp; /* second timestamp on interferenced flag change */ ++} interference_source_rep_t; ++ ++/* bit definitions for flags in interference source report */ ++#define ITFR_INTERFERENCED 1 /* interference detected */ ++#define ITFR_HOME_CHANNEL 2 /* home channel has interference */ ++#define ITFR_NOISY_ENVIRONMENT 4 /* noisy environemnt so feature stopped */ ++ ++#define WLC_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */ ++ ++typedef struct wl_country { ++ char country_abbrev[WLC_CNTRY_BUF_SZ]; /* nul-terminated country code used in ++ * the Country IE ++ */ ++ int32 rev; /* revision specifier for ccode ++ * on set, -1 indicates unspecified. ++ * on get, rev >= 0 ++ */ ++ char ccode[WLC_CNTRY_BUF_SZ]; /* nul-terminated built-in country code. ++ * variable length, but fixed size in ++ * struct allows simple allocation for ++ * expected country strings <= 3 chars. ++ */ ++} wl_country_t; ++ ++typedef struct wl_channels_in_country { ++ uint32 buflen; ++ uint32 band; ++ char country_abbrev[WLC_CNTRY_BUF_SZ]; ++ uint32 count; ++ uint32 channel[1]; ++} wl_channels_in_country_t; ++ ++typedef struct wl_country_list { ++ uint32 buflen; ++ uint32 band_set; ++ uint32 band; ++ uint32 count; ++ char country_abbrev[1]; ++} wl_country_list_t; ++ ++#define WL_NUM_RPI_BINS 8 ++#define WL_RM_TYPE_BASIC 1 ++#define WL_RM_TYPE_CCA 2 ++#define WL_RM_TYPE_RPI 3 ++ ++#define WL_RM_FLAG_PARALLEL (1<<0) ++ ++#define WL_RM_FLAG_LATE (1<<1) ++#define WL_RM_FLAG_INCAPABLE (1<<2) ++#define WL_RM_FLAG_REFUSED (1<<3) ++ ++typedef struct wl_rm_req_elt { ++ int8 type; ++ int8 flags; ++ chanspec_t chanspec; ++ uint32 token; /* token for this measurement */ ++ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */ ++ uint32 tsf_l; /* TSF low 32-bits */ ++ uint32 dur; /* TUs */ ++} wl_rm_req_elt_t; ++ ++typedef struct wl_rm_req { ++ uint32 token; /* overall measurement set token */ ++ uint32 count; /* number of measurement requests */ ++ void *cb; /* completion callback function: may be NULL */ ++ void *cb_arg; /* arg to completion callback function */ ++ wl_rm_req_elt_t req[1]; /* variable length block of requests */ ++} wl_rm_req_t; ++#define WL_RM_REQ_FIXED_LEN OFFSETOF(wl_rm_req_t, req) ++ ++typedef struct wl_rm_rep_elt { ++ int8 type; ++ int8 flags; ++ chanspec_t chanspec; ++ uint32 token; /* token for this measurement */ ++ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */ ++ uint32 tsf_l; /* TSF low 32-bits */ ++ uint32 dur; /* TUs */ ++ uint32 len; /* byte length of data block */ ++ uint8 data[1]; /* variable length data block */ ++} wl_rm_rep_elt_t; ++#define WL_RM_REP_ELT_FIXED_LEN 24 /* length excluding data block */ ++ ++#define WL_RPI_REP_BIN_NUM 8 ++typedef struct wl_rm_rpi_rep { ++ uint8 rpi[WL_RPI_REP_BIN_NUM]; ++ int8 rpi_max[WL_RPI_REP_BIN_NUM]; ++} wl_rm_rpi_rep_t; ++ ++typedef struct wl_rm_rep { ++ uint32 token; /* overall measurement set token */ ++ uint32 len; /* length of measurement report block */ ++ wl_rm_rep_elt_t rep[1]; /* variable length block of reports */ ++} wl_rm_rep_t; ++#define WL_RM_REP_FIXED_LEN 8 ++ ++ ++#if defined(BCMSUP_PSK) ++typedef enum sup_auth_status { ++ /* Basic supplicant authentication states */ ++ WLC_SUP_DISCONNECTED = 0, ++ WLC_SUP_CONNECTING, ++ WLC_SUP_IDREQUIRED, ++ WLC_SUP_AUTHENTICATING, ++ WLC_SUP_AUTHENTICATED, ++ WLC_SUP_KEYXCHANGE, ++ WLC_SUP_KEYED, ++ WLC_SUP_TIMEOUT, ++ WLC_SUP_LAST_BASIC_STATE, ++ ++ /* Extended supplicant authentication states */ ++ /* Waiting to receive handshake msg M1 */ ++ WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED, ++ /* Preparing to send handshake msg M2 */ ++ WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE, ++ /* Waiting to receive handshake msg M3 */ ++ WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE, ++ WLC_SUP_KEYXCHANGE_PREP_M4, /* Preparing to send handshake msg M4 */ ++ WLC_SUP_KEYXCHANGE_WAIT_G1, /* Waiting to receive handshake msg G1 */ ++ WLC_SUP_KEYXCHANGE_PREP_G2 /* Preparing to send handshake msg G2 */ ++} sup_auth_status_t; ++#endif ++ ++/* Enumerate crypto algorithms */ ++#define CRYPTO_ALGO_OFF 0 ++#define CRYPTO_ALGO_WEP1 1 ++#define CRYPTO_ALGO_TKIP 2 ++#define CRYPTO_ALGO_WEP128 3 ++#define CRYPTO_ALGO_AES_CCM 4 ++#define CRYPTO_ALGO_AES_OCB_MSDU 5 ++#define CRYPTO_ALGO_AES_OCB_MPDU 6 ++#define CRYPTO_ALGO_NALG 7 ++#define CRYPTO_ALGO_PMK 12 /* for 802.1x supp to set PMK before 4-way */ ++ ++#define WSEC_GEN_MIC_ERROR 0x0001 ++#define WSEC_GEN_REPLAY 0x0002 ++#define WSEC_GEN_ICV_ERROR 0x0004 ++#define WSEC_GEN_MFP_ACT_ERROR 0x0008 ++#define WSEC_GEN_MFP_DISASSOC_ERROR 0x0010 ++#define WSEC_GEN_MFP_DEAUTH_ERROR 0x0020 ++ ++#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */ ++#define WL_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */ ++#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */ ++#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */ ++#define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */ ++ ++typedef struct wl_wsec_key { ++ uint32 index; /* key index */ ++ uint32 len; /* key length */ ++ uint8 data[DOT11_MAX_KEY_SIZE]; /* key data */ ++ uint32 pad_1[18]; ++ uint32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ ++ uint32 flags; /* misc flags */ ++ uint32 pad_2[2]; ++ int pad_3; ++ int iv_initialized; /* has IV been initialized already? */ ++ int pad_4; ++ /* Rx IV */ ++ struct { ++ uint32 hi; /* upper 32 bits of IV */ ++ uint16 lo; /* lower 16 bits of IV */ ++ } rxiv; ++ uint32 pad_5[2]; ++ struct ether_addr ea; /* per station */ ++} wl_wsec_key_t; ++ ++#define WSEC_MIN_PSK_LEN 8 ++#define WSEC_MAX_PSK_LEN 64 ++ ++/* Flag for key material needing passhash'ing */ ++#define WSEC_PASSPHRASE (1<<0) ++ ++/* receptacle for WLC_SET_WSEC_PMK parameter */ ++typedef struct { ++ ushort key_len; /* octets in key material */ ++ ushort flags; /* key handling qualification */ ++ uint8 key[WSEC_MAX_PSK_LEN]; /* PMK material */ ++} wsec_pmk_t; ++ ++/* wireless security bitvec */ ++#define WEP_ENABLED 0x0001 ++#define TKIP_ENABLED 0x0002 ++#define AES_ENABLED 0x0004 ++#define WSEC_SWFLAG 0x0008 ++#define SES_OW_ENABLED 0x0040 /* to go into transition mode without setting wep */ ++ ++/* wsec macros for operating on the above definitions */ ++#define WSEC_WEP_ENABLED(wsec) ((wsec) & WEP_ENABLED) ++#define WSEC_TKIP_ENABLED(wsec) ((wsec) & TKIP_ENABLED) ++#define WSEC_AES_ENABLED(wsec) ((wsec) & AES_ENABLED) ++ ++#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) ++#define WSEC_SES_OW_ENABLED(wsec) ((wsec) & SES_OW_ENABLED) ++ ++#ifdef MFP ++#define MFP_CAPABLE 0x0200 ++#define MFP_REQUIRED 0x0400 ++#define MFP_SHA256 0x0800 /* a special configuration for STA for WIFI test tool */ ++#endif /* MFP */ ++ ++/* WPA authentication mode bitvec */ ++#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ ++#define WPA_AUTH_NONE 0x0001 /* none (IBSS) */ ++#define WPA_AUTH_UNSPECIFIED 0x0002 /* over 802.1x */ ++#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */ ++/* #define WPA_AUTH_8021X 0x0020 */ /* 802.1x, reserved */ ++#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */ ++#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ ++#define BRCM_AUTH_PSK 0x0100 /* BRCM specific PSK */ ++#define BRCM_AUTH_DPT 0x0200 /* DPT PSK without group keys */ ++#define WPA2_AUTH_MFP 0x1000 /* MFP (11w) in contrast to CCX */ ++#define WPA2_AUTH_TPK 0x2000 /* TDLS Peer Key */ ++#define WPA2_AUTH_FT 0x4000 /* Fast Transition. */ ++#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ ++ ++/* pmkid */ ++#define MAXPMKID 16 ++ ++typedef struct _pmkid { ++ struct ether_addr BSSID; ++ uint8 PMKID[WPA2_PMKID_LEN]; ++} pmkid_t; ++ ++typedef struct _pmkid_list { ++ uint32 npmkid; ++ pmkid_t pmkid[1]; ++} pmkid_list_t; ++ ++typedef struct _pmkid_cand { ++ struct ether_addr BSSID; ++ uint8 preauth; ++} pmkid_cand_t; ++ ++typedef struct _pmkid_cand_list { ++ uint32 npmkid_cand; ++ pmkid_cand_t pmkid_cand[1]; ++} pmkid_cand_list_t; ++ ++typedef struct wl_assoc_info { ++ uint32 req_len; ++ uint32 resp_len; ++ uint32 flags; ++ struct dot11_assoc_req req; ++ struct ether_addr reassoc_bssid; /* used in reassoc's */ ++ struct dot11_assoc_resp resp; ++} wl_assoc_info_t; ++ ++/* flags */ ++#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++typedef struct wl_led_info { ++ uint32 index; /* led index */ ++ uint32 behavior; ++ uint8 activehi; ++} wl_led_info_t; ++ ++ ++/* srom read/write struct passed through ioctl */ ++typedef struct { ++ uint byteoff; /* byte offset */ ++ uint nbytes; /* number of bytes */ ++ uint16 buf[1]; ++} srom_rw_t; ++ ++/* similar cis (srom or otp) struct [iovar: may not be aligned] */ ++typedef struct { ++ uint32 source; /* cis source */ ++ uint32 byteoff; /* byte offset */ ++ uint32 nbytes; /* number of bytes */ ++ /* data follows here */ ++} cis_rw_t; ++ ++#define WLC_CIS_DEFAULT 0 /* built-in default */ ++#define WLC_CIS_SROM 1 /* source is sprom */ ++#define WLC_CIS_OTP 2 /* source is otp */ ++ ++/* R_REG and W_REG struct passed through ioctl */ ++typedef struct { ++ uint32 byteoff; /* byte offset of the field in d11regs_t */ ++ uint32 val; /* read/write value of the field */ ++ uint32 size; /* sizeof the field */ ++ uint band; /* band (optional) */ ++} rw_reg_t; ++ ++/* Structure used by GET/SET_ATTEN ioctls - it controls power in b/g-band */ ++/* PCL - Power Control Loop */ ++/* current gain setting is replaced by user input */ ++#define WL_ATTEN_APP_INPUT_PCL_OFF 0 /* turn off PCL, apply supplied input */ ++#define WL_ATTEN_PCL_ON 1 /* turn on PCL */ ++/* current gain setting is maintained */ ++#define WL_ATTEN_PCL_OFF 2 /* turn off PCL. */ ++ ++typedef struct { ++ uint16 auto_ctrl; /* WL_ATTEN_XX */ ++ uint16 bb; /* Baseband attenuation */ ++ uint16 radio; /* Radio attenuation */ ++ uint16 txctl1; /* Radio TX_CTL1 value */ ++} atten_t; ++ ++/* Per-AC retry parameters */ ++struct wme_tx_params_s { ++ uint8 short_retry; ++ uint8 short_fallback; ++ uint8 long_retry; ++ uint8 long_fallback; ++ uint16 max_rate; /* In units of 512 Kbps */ ++}; ++ ++typedef struct wme_tx_params_s wme_tx_params_t; ++ ++#define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT) ++ ++/* defines used by poweridx iovar - it controls power in a-band */ ++/* current gain setting is maintained */ ++#define WL_PWRIDX_PCL_OFF -2 /* turn off PCL. */ ++#define WL_PWRIDX_PCL_ON -1 /* turn on PCL */ ++#define WL_PWRIDX_LOWER_LIMIT -2 /* lower limit */ ++#define WL_PWRIDX_UPPER_LIMIT 63 /* upper limit */ ++/* value >= 0 causes ++ * - input to be set to that value ++ * - PCL to be off ++ */ ++ ++/* Used to get specific link/ac parameters */ ++typedef struct { ++ int ac; ++ uint8 val; ++ struct ether_addr ea; ++} link_val_t; ++ ++#define BCM_MAC_STATUS_INDICATION (0x40010200L) ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++typedef struct { ++ uint16 ver; /* version of this struct */ ++ uint16 len; /* length in bytes of this structure */ ++ uint16 cap; /* sta's advertised capabilities */ ++ uint32 flags; /* flags defined below */ ++ uint32 idle; /* time since data pkt rx'd from sta */ ++ struct ether_addr ea; /* Station address */ ++ wl_rateset_t rateset; /* rateset in use */ ++ uint32 in; /* seconds elapsed since associated */ ++ uint32 listen_interval_inms; /* Min Listen interval in ms for this STA */ ++ uint32 tx_pkts; /* # of packets transmitted */ ++ uint32 tx_failures; /* # of packets failed */ ++ uint32 rx_ucast_pkts; /* # of unicast packets received */ ++ uint32 rx_mcast_pkts; /* # of multicast packets received */ ++ uint32 tx_rate; /* Rate of last successful tx frame */ ++ uint32 rx_rate; /* Rate of last successful rx frame */ ++ uint32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ ++ uint32 rx_decrypt_failures; /* # of packet decrypted unsuccessfully */ ++} sta_info_t; ++ ++#define WL_OLD_STAINFO_SIZE OFFSETOF(sta_info_t, tx_pkts) ++ ++#define WL_STA_VER 3 ++ ++/* Flags for sta_info_t indicating properties of STA */ ++#define WL_STA_BRCM 0x1 /* Running a Broadcom driver */ ++#define WL_STA_WME 0x2 /* WMM association */ ++#define WL_STA_UNUSED 0x4 ++#define WL_STA_AUTHE 0x8 /* Authenticated */ ++#define WL_STA_ASSOC 0x10 /* Associated */ ++#define WL_STA_AUTHO 0x20 /* Authorized */ ++#define WL_STA_WDS 0x40 /* Wireless Distribution System */ ++#define WL_STA_WDS_LINKUP 0x80 /* WDS traffic/probes flowing properly */ ++#define WL_STA_PS 0x100 /* STA is in power save mode from AP's viewpoint */ ++#define WL_STA_APSD_BE 0x200 /* APSD delv/trigger for AC_BE is default enabled */ ++#define WL_STA_APSD_BK 0x400 /* APSD delv/trigger for AC_BK is default enabled */ ++#define WL_STA_APSD_VI 0x800 /* APSD delv/trigger for AC_VI is default enabled */ ++#define WL_STA_APSD_VO 0x1000 /* APSD delv/trigger for AC_VO is default enabled */ ++#define WL_STA_N_CAP 0x2000 /* STA 802.11n capable */ ++#define WL_STA_SCBSTATS 0x4000 /* Per STA debug stats */ ++ ++#define WL_WDS_LINKUP WL_STA_WDS_LINKUP /* deprecated */ ++ ++/* Values for TX Filter override mode */ ++#define WLC_TXFILTER_OVERRIDE_DISABLED 0 ++#define WLC_TXFILTER_OVERRIDE_ENABLED 1 ++ ++/* Used to get specific STA parameters */ ++typedef struct { ++ uint32 val; ++ struct ether_addr ea; ++} scb_val_t; ++ ++/* Used by iovar versions of some ioctls, i.e. WLC_SCB_AUTHORIZE et al */ ++typedef struct { ++ uint32 code; ++ scb_val_t ioctl_args; ++} authops_t; ++ ++/* channel encoding */ ++typedef struct channel_info { ++ int hw_channel; ++ int target_channel; ++ int scan_channel; ++} channel_info_t; ++ ++/* For ioctls that take a list of MAC addresses */ ++struct maclist { ++ uint count; /* number of MAC addresses */ ++ struct ether_addr ea[1]; /* variable length array of MAC addresses */ ++}; ++ ++/* get pkt count struct passed through ioctl */ ++typedef struct get_pktcnt { ++ uint rx_good_pkt; ++ uint rx_bad_pkt; ++ uint tx_good_pkt; ++ uint tx_bad_pkt; ++ uint rx_ocast_good_pkt; /* unicast packets destined for others */ ++} get_pktcnt_t; ++ ++/* NINTENDO2 */ ++#define LQ_IDX_MIN 0 ++#define LQ_IDX_MAX 1 ++#define LQ_IDX_AVG 2 ++#define LQ_IDX_SUM 2 ++#define LQ_IDX_LAST 3 ++#define LQ_STOP_MONITOR 0 ++#define LQ_START_MONITOR 1 ++ ++/* Get averages RSSI, Rx PHY rate and SNR values */ ++typedef struct { ++ int rssi[LQ_IDX_LAST]; /* Array to keep min, max, avg rssi */ ++ int snr[LQ_IDX_LAST]; /* Array to keep min, max, avg snr */ ++ int isvalid; /* Flag indicating whether above data is valid */ ++} wl_lq_t; /* Link Quality */ ++ ++typedef enum wl_wakeup_reason_type { ++ LCD_ON = 1, ++ LCD_OFF, ++ DRC1_WAKE, ++ DRC2_WAKE, ++ REASON_LAST ++} wl_wr_type_t; ++ ++typedef struct { ++/* Unique filter id */ ++ uint32 id; ++ ++/* stores the reason for the last wake up */ ++ uint8 reason; ++} wl_wr_t; ++ ++/* Get MAC specific rate histogram command */ ++typedef struct { ++ struct ether_addr ea; /* MAC Address */ ++ uint8 ac_cat; /* Access Category */ ++ uint8 num_pkts; /* Number of packet entries to be averaged */ ++} wl_mac_ratehisto_cmd_t; /* MAC Specific Rate Histogram command */ ++ ++/* Get MAC rate histogram response */ ++typedef struct { ++ uint32 rate[WLC_MAXRATE + 1]; /* Rates */ ++ uint32 mcs[WL_RATESET_SZ_HT_MCS * WL_TX_CHAINS_MAX]; /* MCS counts */ ++ uint32 vht[WL_RATESET_SZ_VHT_MCS][WL_TX_CHAINS_MAX]; /* VHT counts */ ++ uint32 tsf_timer[2][2]; /* Start and End time for 8bytes value */ ++} wl_mac_ratehisto_res_t; /* MAC Specific Rate Histogram Response */ ++ ++/* Values for TX Filter override mode */ ++#define WLC_TXFILTER_OVERRIDE_DISABLED 0 ++#define WLC_TXFILTER_OVERRIDE_ENABLED 1 ++ ++#define WL_IOCTL_ACTION_GET 0x0 ++#define WL_IOCTL_ACTION_SET 0x1 ++#define WL_IOCTL_ACTION_OVL_IDX_MASK 0x1e ++#define WL_IOCTL_ACTION_OVL_RSV 0x20 ++#define WL_IOCTL_ACTION_OVL 0x40 ++#define WL_IOCTL_ACTION_MASK 0x7e ++#define WL_IOCTL_ACTION_OVL_SHIFT 1 ++ ++/* Linux network driver ioctl encoding */ ++typedef struct wl_ioctl { ++ uint cmd; /* common ioctl definition */ ++ void *buf; /* pointer to user buffer */ ++ uint len; /* length of user buffer */ ++ uint8 set; /* 1=set IOCTL; 0=query IOCTL */ ++ uint used; /* bytes read or written (optional) */ ++ uint needed; /* bytes needed (optional) */ ++} wl_ioctl_t; ++ ++/* reference to wl_ioctl_t struct used by usermode driver */ ++#define ioctl_subtype set /* subtype param */ ++#define ioctl_pid used /* pid param */ ++#define ioctl_status needed /* status param */ ++ ++/* ++ * Structure for passing hardware and software ++ * revision info up from the driver. ++ */ ++typedef struct wlc_rev_info { ++ uint vendorid; /* PCI vendor id */ ++ uint deviceid; /* device id of chip */ ++ uint radiorev; /* radio revision */ ++ uint chiprev; /* chip revision */ ++ uint corerev; /* core revision */ ++ uint boardid; /* board identifier (usu. PCI sub-device id) */ ++ uint boardvendor; /* board vendor (usu. PCI sub-vendor id) */ ++ uint boardrev; /* board revision */ ++ uint driverrev; /* driver version */ ++ uint ucoderev; /* microcode version */ ++ uint bus; /* bus type */ ++ uint chipnum; /* chip number */ ++ uint phytype; /* phy type */ ++ uint phyrev; /* phy revision */ ++ uint anarev; /* anacore rev */ ++ uint chippkg; /* chip package info */ ++} wlc_rev_info_t; ++ ++#define WL_REV_INFO_LEGACY_LENGTH 48 ++ ++#define WL_BRAND_MAX 10 ++typedef struct wl_instance_info { ++ uint instance; ++ char brand[WL_BRAND_MAX]; ++} wl_instance_info_t; ++ ++/* structure to change size of tx fifo */ ++typedef struct wl_txfifo_sz { ++ uint16 magic; ++ uint16 fifo; ++ uint16 size; ++} wl_txfifo_sz_t; ++/* magic pattern used for mismatch driver and wl */ ++#define WL_TXFIFO_SZ_MAGIC 0xa5a5 ++ ++/* Transfer info about an IOVar from the driver */ ++/* Max supported IOV name size in bytes, + 1 for nul termination */ ++#define WLC_IOV_NAME_LEN 30 ++typedef struct wlc_iov_trx_s { ++ uint8 module; ++ uint8 type; ++ char name[WLC_IOV_NAME_LEN]; ++} wlc_iov_trx_t; ++ ++/* check this magic number */ ++#define WLC_IOCTL_MAGIC 0x14e46c77 ++ ++/* bump this number if you change the ioctl interface */ ++#ifdef D11AC_IOTYPES ++#define WLC_IOCTL_VERSION 2 ++#define WLC_IOCTL_VERSION_LEGACY_IOTYPES 1 ++#else ++#define WLC_IOCTL_VERSION 1 ++#endif /* D11AC_IOTYPES */ ++ ++#define WLC_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */ ++#define WLC_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */ ++#define WLC_IOCTL_MEDLEN 1536 /* "med" length ioctl buffer required */ ++#ifdef WLC_HIGH_ONLY ++#define WLC_SAMPLECOLLECT_MAXLEN 1024 /* limit sample size for bmac */ ++#else ++#if defined(LCNCONF) || defined(LCN40CONF) ++#define WLC_SAMPLECOLLECT_MAXLEN 8192 /* Max Sample Collect buffer */ ++#else ++#define WLC_SAMPLECOLLECT_MAXLEN 10240 /* Max Sample Collect buffer for two cores */ ++#endif ++#endif /* WLC_HIGH_ONLY */ ++ ++/* common ioctl definitions */ ++#define WLC_GET_MAGIC 0 ++#define WLC_GET_VERSION 1 ++#define WLC_UP 2 ++#define WLC_DOWN 3 ++#define WLC_GET_LOOP 4 ++#define WLC_SET_LOOP 5 ++#define WLC_DUMP 6 ++#define WLC_GET_MSGLEVEL 7 ++#define WLC_SET_MSGLEVEL 8 ++#define WLC_GET_PROMISC 9 ++#define WLC_SET_PROMISC 10 ++/* #define WLC_OVERLAY_IOCTL 11 */ /* not supported */ ++#define WLC_GET_RATE 12 ++#define WLC_GET_MAX_RATE 13 ++#define WLC_GET_INSTANCE 14 ++/* #define WLC_GET_FRAG 15 */ /* no longer supported */ ++/* #define WLC_SET_FRAG 16 */ /* no longer supported */ ++/* #define WLC_GET_RTS 17 */ /* no longer supported */ ++/* #define WLC_SET_RTS 18 */ /* no longer supported */ ++#define WLC_GET_INFRA 19 ++#define WLC_SET_INFRA 20 ++#define WLC_GET_AUTH 21 ++#define WLC_SET_AUTH 22 ++#define WLC_GET_BSSID 23 ++#define WLC_SET_BSSID 24 ++#define WLC_GET_SSID 25 ++#define WLC_SET_SSID 26 ++#define WLC_RESTART 27 ++#define WLC_TERMINATED 28 ++/* #define WLC_DUMP_SCB 28 */ /* no longer supported */ ++#define WLC_GET_CHANNEL 29 ++#define WLC_SET_CHANNEL 30 ++#define WLC_GET_SRL 31 ++#define WLC_SET_SRL 32 ++#define WLC_GET_LRL 33 ++#define WLC_SET_LRL 34 ++#define WLC_GET_PLCPHDR 35 ++#define WLC_SET_PLCPHDR 36 ++#define WLC_GET_RADIO 37 ++#define WLC_SET_RADIO 38 ++#define WLC_GET_PHYTYPE 39 ++#define WLC_DUMP_RATE 40 ++#define WLC_SET_RATE_PARAMS 41 ++#define WLC_GET_FIXRATE 42 ++#define WLC_SET_FIXRATE 43 ++/* #define WLC_GET_WEP 42 */ /* no longer supported */ ++/* #define WLC_SET_WEP 43 */ /* no longer supported */ ++#define WLC_GET_KEY 44 ++#define WLC_SET_KEY 45 ++#define WLC_GET_REGULATORY 46 ++#define WLC_SET_REGULATORY 47 ++#define WLC_GET_PASSIVE_SCAN 48 ++#define WLC_SET_PASSIVE_SCAN 49 ++#define WLC_SCAN 50 ++#define WLC_SCAN_RESULTS 51 ++#define WLC_DISASSOC 52 ++#define WLC_REASSOC 53 ++#define WLC_GET_ROAM_TRIGGER 54 ++#define WLC_SET_ROAM_TRIGGER 55 ++#define WLC_GET_ROAM_DELTA 56 ++#define WLC_SET_ROAM_DELTA 57 ++#define WLC_GET_ROAM_SCAN_PERIOD 58 ++#define WLC_SET_ROAM_SCAN_PERIOD 59 ++#define WLC_EVM 60 /* diag */ ++#define WLC_GET_TXANT 61 ++#define WLC_SET_TXANT 62 ++#define WLC_GET_ANTDIV 63 ++#define WLC_SET_ANTDIV 64 ++/* #define WLC_GET_TXPWR 65 */ /* no longer supported */ ++/* #define WLC_SET_TXPWR 66 */ /* no longer supported */ ++#define WLC_GET_CLOSED 67 ++#define WLC_SET_CLOSED 68 ++#define WLC_GET_MACLIST 69 ++#define WLC_SET_MACLIST 70 ++#define WLC_GET_RATESET 71 ++#define WLC_SET_RATESET 72 ++/* #define WLC_GET_LOCALE 73 */ /* no longer supported */ ++#define WLC_LONGTRAIN 74 ++#define WLC_GET_BCNPRD 75 ++#define WLC_SET_BCNPRD 76 ++#define WLC_GET_DTIMPRD 77 ++#define WLC_SET_DTIMPRD 78 ++#define WLC_GET_SROM 79 ++#define WLC_SET_SROM 80 ++#define WLC_GET_WEP_RESTRICT 81 ++#define WLC_SET_WEP_RESTRICT 82 ++#define WLC_GET_COUNTRY 83 ++#define WLC_SET_COUNTRY 84 ++#define WLC_GET_PM 85 ++#define WLC_SET_PM 86 ++#define WLC_GET_WAKE 87 ++#define WLC_SET_WAKE 88 ++/* #define WLC_GET_D11CNTS 89 */ /* -> "counters" iovar */ ++#define WLC_GET_FORCELINK 90 /* ndis only */ ++#define WLC_SET_FORCELINK 91 /* ndis only */ ++#define WLC_FREQ_ACCURACY 92 /* diag */ ++#define WLC_CARRIER_SUPPRESS 93 /* diag */ ++#define WLC_GET_PHYREG 94 ++#define WLC_SET_PHYREG 95 ++#define WLC_GET_RADIOREG 96 ++#define WLC_SET_RADIOREG 97 ++#define WLC_GET_REVINFO 98 ++#define WLC_GET_UCANTDIV 99 ++#define WLC_SET_UCANTDIV 100 ++#define WLC_R_REG 101 ++#define WLC_W_REG 102 ++/* #define WLC_DIAG_LOOPBACK 103 old tray diag */ ++/* #define WLC_RESET_D11CNTS 104 */ /* -> "reset_d11cnts" iovar */ ++#define WLC_GET_MACMODE 105 ++#define WLC_SET_MACMODE 106 ++#define WLC_GET_MONITOR 107 ++#define WLC_SET_MONITOR 108 ++#define WLC_GET_GMODE 109 ++#define WLC_SET_GMODE 110 ++#define WLC_GET_LEGACY_ERP 111 ++#define WLC_SET_LEGACY_ERP 112 ++#define WLC_GET_RX_ANT 113 ++#define WLC_GET_CURR_RATESET 114 /* current rateset */ ++#define WLC_GET_SCANSUPPRESS 115 ++#define WLC_SET_SCANSUPPRESS 116 ++#define WLC_GET_AP 117 ++#define WLC_SET_AP 118 ++#define WLC_GET_EAP_RESTRICT 119 ++#define WLC_SET_EAP_RESTRICT 120 ++#define WLC_SCB_AUTHORIZE 121 ++#define WLC_SCB_DEAUTHORIZE 122 ++#define WLC_GET_WDSLIST 123 ++#define WLC_SET_WDSLIST 124 ++#define WLC_GET_ATIM 125 ++#define WLC_SET_ATIM 126 ++#define WLC_GET_RSSI 127 ++#define WLC_GET_PHYANTDIV 128 ++#define WLC_SET_PHYANTDIV 129 ++#define WLC_AP_RX_ONLY 130 ++#define WLC_GET_TX_PATH_PWR 131 ++#define WLC_SET_TX_PATH_PWR 132 ++#define WLC_GET_WSEC 133 ++#define WLC_SET_WSEC 134 ++#define WLC_GET_PHY_NOISE 135 ++#define WLC_GET_BSS_INFO 136 ++#define WLC_GET_PKTCNTS 137 ++#define WLC_GET_LAZYWDS 138 ++#define WLC_SET_LAZYWDS 139 ++#define WLC_GET_BANDLIST 140 ++#define WLC_GET_BAND 141 ++#define WLC_SET_BAND 142 ++#define WLC_SCB_DEAUTHENTICATE 143 ++#define WLC_GET_SHORTSLOT 144 ++#define WLC_GET_SHORTSLOT_OVERRIDE 145 ++#define WLC_SET_SHORTSLOT_OVERRIDE 146 ++#define WLC_GET_SHORTSLOT_RESTRICT 147 ++#define WLC_SET_SHORTSLOT_RESTRICT 148 ++#define WLC_GET_GMODE_PROTECTION 149 ++#define WLC_GET_GMODE_PROTECTION_OVERRIDE 150 ++#define WLC_SET_GMODE_PROTECTION_OVERRIDE 151 ++#define WLC_UPGRADE 152 ++/* #define WLC_GET_MRATE 153 */ /* no longer supported */ ++/* #define WLC_SET_MRATE 154 */ /* no longer supported */ ++#define WLC_GET_IGNORE_BCNS 155 ++#define WLC_SET_IGNORE_BCNS 156 ++#define WLC_GET_SCB_TIMEOUT 157 ++#define WLC_SET_SCB_TIMEOUT 158 ++#define WLC_GET_ASSOCLIST 159 ++#define WLC_GET_CLK 160 ++#define WLC_SET_CLK 161 ++#define WLC_GET_UP 162 ++#define WLC_OUT 163 ++#define WLC_GET_WPA_AUTH 164 ++#define WLC_SET_WPA_AUTH 165 ++#define WLC_GET_UCFLAGS 166 ++#define WLC_SET_UCFLAGS 167 ++#define WLC_GET_PWRIDX 168 ++#define WLC_SET_PWRIDX 169 ++#define WLC_GET_TSSI 170 ++#define WLC_GET_SUP_RATESET_OVERRIDE 171 ++#define WLC_SET_SUP_RATESET_OVERRIDE 172 ++/* #define WLC_SET_FAST_TIMER 173 */ /* no longer supported */ ++/* #define WLC_GET_FAST_TIMER 174 */ /* no longer supported */ ++/* #define WLC_SET_SLOW_TIMER 175 */ /* no longer supported */ ++/* #define WLC_GET_SLOW_TIMER 176 */ /* no longer supported */ ++/* #define WLC_DUMP_PHYREGS 177 */ /* no longer supported */ ++#define WLC_GET_PROTECTION_CONTROL 178 ++#define WLC_SET_PROTECTION_CONTROL 179 ++#define WLC_GET_PHYLIST 180 ++#define WLC_ENCRYPT_STRENGTH 181 /* ndis only */ ++#define WLC_DECRYPT_STATUS 182 /* ndis only */ ++#define WLC_GET_KEY_SEQ 183 ++#define WLC_GET_SCAN_CHANNEL_TIME 184 ++#define WLC_SET_SCAN_CHANNEL_TIME 185 ++#define WLC_GET_SCAN_UNASSOC_TIME 186 ++#define WLC_SET_SCAN_UNASSOC_TIME 187 ++#define WLC_GET_SCAN_HOME_TIME 188 ++#define WLC_SET_SCAN_HOME_TIME 189 ++#define WLC_GET_SCAN_NPROBES 190 ++#define WLC_SET_SCAN_NPROBES 191 ++#define WLC_GET_PRB_RESP_TIMEOUT 192 ++#define WLC_SET_PRB_RESP_TIMEOUT 193 ++#define WLC_GET_ATTEN 194 ++#define WLC_SET_ATTEN 195 ++#define WLC_GET_SHMEM 196 /* diag */ ++#define WLC_SET_SHMEM 197 /* diag */ ++/* #define WLC_GET_GMODE_PROTECTION_CTS 198 */ /* no longer supported */ ++/* #define WLC_SET_GMODE_PROTECTION_CTS 199 */ /* no longer supported */ ++#define WLC_SET_WSEC_TEST 200 ++#define WLC_SCB_DEAUTHENTICATE_FOR_REASON 201 ++#define WLC_TKIP_COUNTERMEASURES 202 ++#define WLC_GET_PIOMODE 203 ++#define WLC_SET_PIOMODE 204 ++#define WLC_SET_ASSOC_PREFER 205 ++#define WLC_GET_ASSOC_PREFER 206 ++#define WLC_SET_ROAM_PREFER 207 ++#define WLC_GET_ROAM_PREFER 208 ++#define WLC_SET_LED 209 ++#define WLC_GET_LED 210 ++#define WLC_GET_INTERFERENCE_MODE 211 ++#define WLC_SET_INTERFERENCE_MODE 212 ++#define WLC_GET_CHANNEL_QA 213 ++#define WLC_START_CHANNEL_QA 214 ++#define WLC_GET_CHANNEL_SEL 215 ++#define WLC_START_CHANNEL_SEL 216 ++#define WLC_GET_VALID_CHANNELS 217 ++#define WLC_GET_FAKEFRAG 218 ++#define WLC_SET_FAKEFRAG 219 ++#define WLC_GET_PWROUT_PERCENTAGE 220 ++#define WLC_SET_PWROUT_PERCENTAGE 221 ++#define WLC_SET_BAD_FRAME_PREEMPT 222 ++#define WLC_GET_BAD_FRAME_PREEMPT 223 ++#define WLC_SET_LEAP_LIST 224 ++#define WLC_GET_LEAP_LIST 225 ++#define WLC_GET_CWMIN 226 ++#define WLC_SET_CWMIN 227 ++#define WLC_GET_CWMAX 228 ++#define WLC_SET_CWMAX 229 ++#define WLC_GET_WET 230 ++#define WLC_SET_WET 231 ++#define WLC_GET_PUB 232 ++/* #define WLC_SET_GLACIAL_TIMER 233 */ /* no longer supported */ ++/* #define WLC_GET_GLACIAL_TIMER 234 */ /* no longer supported */ ++#define WLC_GET_KEY_PRIMARY 235 ++#define WLC_SET_KEY_PRIMARY 236 ++/* #define WLC_DUMP_RADIOREGS 237 */ /* no longer supported */ ++#define WLC_GET_ACI_ARGS 238 ++#define WLC_SET_ACI_ARGS 239 ++#define WLC_UNSET_CALLBACK 240 ++#define WLC_SET_CALLBACK 241 ++#define WLC_GET_RADAR 242 ++#define WLC_SET_RADAR 243 ++#define WLC_SET_SPECT_MANAGMENT 244 ++#define WLC_GET_SPECT_MANAGMENT 245 ++#define WLC_WDS_GET_REMOTE_HWADDR 246 /* handled in wl_linux.c/wl_vx.c */ ++#define WLC_WDS_GET_WPA_SUP 247 ++#define WLC_SET_CS_SCAN_TIMER 248 ++#define WLC_GET_CS_SCAN_TIMER 249 ++#define WLC_MEASURE_REQUEST 250 ++#define WLC_INIT 251 ++#define WLC_SEND_QUIET 252 ++#define WLC_KEEPALIVE 253 ++#define WLC_SEND_PWR_CONSTRAINT 254 ++#define WLC_UPGRADE_STATUS 255 ++#define WLC_CURRENT_PWR 256 ++#define WLC_GET_SCAN_PASSIVE_TIME 257 ++#define WLC_SET_SCAN_PASSIVE_TIME 258 ++#define WLC_LEGACY_LINK_BEHAVIOR 259 ++#define WLC_GET_CHANNELS_IN_COUNTRY 260 ++#define WLC_GET_COUNTRY_LIST 261 ++#define WLC_GET_VAR 262 /* get value of named variable */ ++#define WLC_SET_VAR 263 /* set named variable to value */ ++#define WLC_NVRAM_GET 264 /* deprecated */ ++#define WLC_NVRAM_SET 265 ++#define WLC_NVRAM_DUMP 266 ++#define WLC_REBOOT 267 ++#define WLC_SET_WSEC_PMK 268 ++#define WLC_GET_AUTH_MODE 269 ++#define WLC_SET_AUTH_MODE 270 ++#define WLC_GET_WAKEENTRY 271 ++#define WLC_SET_WAKEENTRY 272 ++#define WLC_NDCONFIG_ITEM 273 /* currently handled in wl_oid.c */ ++#define WLC_NVOTPW 274 ++#define WLC_OTPW 275 ++#define WLC_IOV_BLOCK_GET 276 ++#define WLC_IOV_MODULES_GET 277 ++#define WLC_SOFT_RESET 278 ++#define WLC_GET_ALLOW_MODE 279 ++#define WLC_SET_ALLOW_MODE 280 ++#define WLC_GET_DESIRED_BSSID 281 ++#define WLC_SET_DESIRED_BSSID 282 ++#define WLC_DISASSOC_MYAP 283 ++#define WLC_GET_NBANDS 284 /* for Dongle EXT_STA support */ ++#define WLC_GET_BANDSTATES 285 /* for Dongle EXT_STA support */ ++#define WLC_GET_WLC_BSS_INFO 286 /* for Dongle EXT_STA support */ ++#define WLC_GET_ASSOC_INFO 287 /* for Dongle EXT_STA support */ ++#define WLC_GET_OID_PHY 288 /* for Dongle EXT_STA support */ ++#define WLC_SET_OID_PHY 289 /* for Dongle EXT_STA support */ ++#define WLC_SET_ASSOC_TIME 290 /* for Dongle EXT_STA support */ ++#define WLC_GET_DESIRED_SSID 291 /* for Dongle EXT_STA support */ ++#define WLC_GET_CHANSPEC 292 /* for Dongle EXT_STA support */ ++#define WLC_GET_ASSOC_STATE 293 /* for Dongle EXT_STA support */ ++#define WLC_SET_PHY_STATE 294 /* for Dongle EXT_STA support */ ++#define WLC_GET_SCAN_PENDING 295 /* for Dongle EXT_STA support */ ++#define WLC_GET_SCANREQ_PENDING 296 /* for Dongle EXT_STA support */ ++#define WLC_GET_PREV_ROAM_REASON 297 /* for Dongle EXT_STA support */ ++#define WLC_SET_PREV_ROAM_REASON 298 /* for Dongle EXT_STA support */ ++#define WLC_GET_BANDSTATES_PI 299 /* for Dongle EXT_STA support */ ++#define WLC_GET_PHY_STATE 300 /* for Dongle EXT_STA support */ ++#define WLC_GET_BSS_WPA_RSN 301 /* for Dongle EXT_STA support */ ++#define WLC_GET_BSS_WPA2_RSN 302 /* for Dongle EXT_STA support */ ++#define WLC_GET_BSS_BCN_TS 303 /* for Dongle EXT_STA support */ ++#define WLC_GET_INT_DISASSOC 304 /* for Dongle EXT_STA support */ ++#define WLC_SET_NUM_PEERS 305 /* for Dongle EXT_STA support */ ++#define WLC_GET_NUM_BSS 306 /* for Dongle EXT_STA support */ ++#define WLC_PHY_SAMPLE_COLLECT 307 /* phy sample collect mode */ ++/* #define WLC_UM_PRIV 308 */ /* Deprecated: usermode driver */ ++#define WLC_GET_CMD 309 ++/* #define WLC_LAST 310 */ /* Never used - can be reused */ ++#define WLC_SET_INTERFERENCE_OVERRIDE_MODE 311 /* set inter mode override */ ++#define WLC_GET_INTERFERENCE_OVERRIDE_MODE 312 /* get inter mode override */ ++/* #define WLC_GET_WAI_RESTRICT 313 */ /* for WAPI, deprecated use iovar instead */ ++/* #define WLC_SET_WAI_RESTRICT 314 */ /* for WAPI, deprecated use iovar instead */ ++/* #define WLC_SET_WAI_REKEY 315 */ /* for WAPI, deprecated use iovar instead */ ++#define WLC_SET_NAT_CONFIG 316 /* for configuring NAT filter driver */ ++#define WLC_GET_NAT_STATE 317 ++#define WLC_LAST 318 ++ ++#ifndef EPICTRL_COOKIE ++#define EPICTRL_COOKIE 0xABADCEDE ++#endif ++ ++/* vx wlc ioctl's offset */ ++#define CMN_IOCTL_OFF 0x180 ++ ++/* ++ * custom OID support ++ * ++ * 0xFF - implementation specific OID ++ * 0xE4 - first byte of Broadcom PCI vendor ID ++ * 0x14 - second byte of Broadcom PCI vendor ID ++ * 0xXX - the custom OID number ++ */ ++ ++/* begin 0x1f values beyond the start of the ET driver range. */ ++#define WL_OID_BASE 0xFFE41420 ++ ++/* NDIS overrides */ ++#define OID_WL_GETINSTANCE (WL_OID_BASE + WLC_GET_INSTANCE) ++#define OID_WL_GET_FORCELINK (WL_OID_BASE + WLC_GET_FORCELINK) ++#define OID_WL_SET_FORCELINK (WL_OID_BASE + WLC_SET_FORCELINK) ++#define OID_WL_ENCRYPT_STRENGTH (WL_OID_BASE + WLC_ENCRYPT_STRENGTH) ++#define OID_WL_DECRYPT_STATUS (WL_OID_BASE + WLC_DECRYPT_STATUS) ++#define OID_LEGACY_LINK_BEHAVIOR (WL_OID_BASE + WLC_LEGACY_LINK_BEHAVIOR) ++#define OID_WL_NDCONFIG_ITEM (WL_OID_BASE + WLC_NDCONFIG_ITEM) ++ ++/* EXT_STA Dongle suuport */ ++#define OID_STA_CHANSPEC (WL_OID_BASE + WLC_GET_CHANSPEC) ++#define OID_STA_NBANDS (WL_OID_BASE + WLC_GET_NBANDS) ++#define OID_STA_GET_PHY (WL_OID_BASE + WLC_GET_OID_PHY) ++#define OID_STA_SET_PHY (WL_OID_BASE + WLC_SET_OID_PHY) ++#define OID_STA_ASSOC_TIME (WL_OID_BASE + WLC_SET_ASSOC_TIME) ++#define OID_STA_DESIRED_SSID (WL_OID_BASE + WLC_GET_DESIRED_SSID) ++#define OID_STA_SET_PHY_STATE (WL_OID_BASE + WLC_SET_PHY_STATE) ++#define OID_STA_SCAN_PENDING (WL_OID_BASE + WLC_GET_SCAN_PENDING) ++#define OID_STA_SCANREQ_PENDING (WL_OID_BASE + WLC_GET_SCANREQ_PENDING) ++#define OID_STA_GET_ROAM_REASON (WL_OID_BASE + WLC_GET_PREV_ROAM_REASON) ++#define OID_STA_SET_ROAM_REASON (WL_OID_BASE + WLC_SET_PREV_ROAM_REASON) ++#define OID_STA_GET_PHY_STATE (WL_OID_BASE + WLC_GET_PHY_STATE) ++#define OID_STA_INT_DISASSOC (WL_OID_BASE + WLC_GET_INT_DISASSOC) ++#define OID_STA_SET_NUM_PEERS (WL_OID_BASE + WLC_SET_NUM_PEERS) ++#define OID_STA_GET_NUM_BSS (WL_OID_BASE + WLC_GET_NUM_BSS) ++ ++/* NAT filter driver support */ ++#define OID_NAT_SET_CONFIG (WL_OID_BASE + WLC_SET_NAT_CONFIG) ++#define OID_NAT_GET_STATE (WL_OID_BASE + WLC_GET_NAT_STATE) ++ ++#define WL_DECRYPT_STATUS_SUCCESS 1 ++#define WL_DECRYPT_STATUS_FAILURE 2 ++#define WL_DECRYPT_STATUS_UNKNOWN 3 ++ ++/* allows user-mode app to poll the status of USB image upgrade */ ++#define WLC_UPGRADE_SUCCESS 0 ++#define WLC_UPGRADE_PENDING 1 ++ ++#ifdef CONFIG_USBRNDIS_RETAIL ++/* struct passed in for WLC_NDCONFIG_ITEM */ ++typedef struct { ++ char *name; ++ void *param; ++} ndconfig_item_t; ++#endif ++ ++ ++/* WLC_GET_AUTH, WLC_SET_AUTH values */ ++#define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */ ++#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ ++#define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */ ++ ++/* Bit masks for radio disabled status - returned by WL_GET_RADIO */ ++#define WL_RADIO_SW_DISABLE (1<<0) ++#define WL_RADIO_HW_DISABLE (1<<1) ++#define WL_RADIO_MPC_DISABLE (1<<2) ++#define WL_RADIO_COUNTRY_DISABLE (1<<3) /* some countries don't support any channel */ ++ ++#define WL_SPURAVOID_OFF 0 ++#define WL_SPURAVOID_ON1 1 ++#define WL_SPURAVOID_ON2 2 ++ ++/* Override bit for WLC_SET_TXPWR. if set, ignore other level limits */ ++#define WL_TXPWR_OVERRIDE (1U<<31) ++#define WL_TXPWR_NEG (1U<<30) ++ ++#define WL_PHY_PAVARS_LEN 32 /* Phy type, Band range, chain, a1[0], b0[0], b1[0] ... */ ++ ++#define WL_PHY_PAVARS2_NUM 3 /* a1, b0, b1 */ ++#define WL_PHY_PAVAR_VER 1 /* pavars version */ ++typedef struct wl_pavars2 { ++ uint16 ver; /* version of this struct */ ++ uint16 len; /* len of this structure */ ++ uint16 inuse; /* driver return 1 for a1,b0,b1 in current band range */ ++ uint16 phy_type; /* phy type */ ++ uint16 bandrange; ++ uint16 chain; ++ uint16 inpa[WL_PHY_PAVARS2_NUM]; /* phy pavars for one band range */ ++} wl_pavars2_t; ++ ++typedef struct wl_po { ++ uint16 phy_type; /* Phy type */ ++ uint16 band; ++ uint16 cckpo; ++ uint32 ofdmpo; ++ uint16 mcspo[8]; ++} wl_po_t; ++ ++/* a large TX Power as an init value to factor out of MIN() calculations, ++ * keep low enough to fit in an int8, units are .25 dBm ++ */ ++#define WLC_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */ ++ ++/* "diag" iovar argument and error code */ ++#define WL_DIAG_INTERRUPT 1 /* d11 loopback interrupt test */ ++#define WL_DIAG_LOOPBACK 2 /* d11 loopback data test */ ++#define WL_DIAG_MEMORY 3 /* d11 memory test */ ++#define WL_DIAG_LED 4 /* LED test */ ++#define WL_DIAG_REG 5 /* d11/phy register test */ ++#define WL_DIAG_SROM 6 /* srom read/crc test */ ++#define WL_DIAG_DMA 7 /* DMA test */ ++#define WL_DIAG_LOOPBACK_EXT 8 /* enhenced d11 loopback data test */ ++ ++#define WL_DIAGERR_SUCCESS 0 ++#define WL_DIAGERR_FAIL_TO_RUN 1 /* unable to run requested diag */ ++#define WL_DIAGERR_NOT_SUPPORTED 2 /* diag requested is not supported */ ++#define WL_DIAGERR_INTERRUPT_FAIL 3 /* loopback interrupt test failed */ ++#define WL_DIAGERR_LOOPBACK_FAIL 4 /* loopback data test failed */ ++#define WL_DIAGERR_SROM_FAIL 5 /* srom read failed */ ++#define WL_DIAGERR_SROM_BADCRC 6 /* srom crc failed */ ++#define WL_DIAGERR_REG_FAIL 7 /* d11/phy register test failed */ ++#define WL_DIAGERR_MEMORY_FAIL 8 /* d11 memory test failed */ ++#define WL_DIAGERR_NOMEM 9 /* diag test failed due to no memory */ ++#define WL_DIAGERR_DMA_FAIL 10 /* DMA test failed */ ++ ++#define WL_DIAGERR_MEMORY_TIMEOUT 11 /* d11 memory test didn't finish in time */ ++#define WL_DIAGERR_MEMORY_BADPATTERN 12 /* d11 memory test result in bad pattern */ ++ ++/* band types */ ++#define WLC_BAND_AUTO 0 /* auto-select */ ++#define WLC_BAND_5G 1 /* 5 Ghz */ ++#define WLC_BAND_2G 2 /* 2.4 Ghz */ ++#define WLC_BAND_ALL 3 /* all bands */ ++ ++/* band range returned by band_range iovar */ ++#define WL_CHAN_FREQ_RANGE_2G 0 ++#define WL_CHAN_FREQ_RANGE_5GL 1 ++#define WL_CHAN_FREQ_RANGE_5GM 2 ++#define WL_CHAN_FREQ_RANGE_5GH 3 ++ ++#define WL_CHAN_FREQ_RANGE_5GLL_5BAND 4 ++#define WL_CHAN_FREQ_RANGE_5GLH_5BAND 5 ++#define WL_CHAN_FREQ_RANGE_5GML_5BAND 6 ++#define WL_CHAN_FREQ_RANGE_5GMH_5BAND 7 ++#define WL_CHAN_FREQ_RANGE_5GH_5BAND 8 ++ ++#define WL_CHAN_FREQ_RANGE_5G_BAND0 1 ++#define WL_CHAN_FREQ_RANGE_5G_BAND1 2 ++#define WL_CHAN_FREQ_RANGE_5G_BAND2 3 ++#define WL_CHAN_FREQ_RANGE_5G_BAND3 4 ++ ++#define WL_CHAN_FREQ_RANGE_5G_4BAND 5 ++ ++/* phy types (returned by WLC_GET_PHYTPE) */ ++#define WLC_PHY_TYPE_A 0 ++#define WLC_PHY_TYPE_B 1 ++#define WLC_PHY_TYPE_G 2 ++#define WLC_PHY_TYPE_N 4 ++#define WLC_PHY_TYPE_LP 5 ++#define WLC_PHY_TYPE_SSN 6 ++#define WLC_PHY_TYPE_HT 7 ++#define WLC_PHY_TYPE_LCN 8 ++#define WLC_PHY_TYPE_LCN40 10 ++#define WLC_PHY_TYPE_AC 11 ++#define WLC_PHY_TYPE_NULL 0xf ++ ++/* MAC list modes */ ++#define WLC_MACMODE_DISABLED 0 /* MAC list disabled */ ++#define WLC_MACMODE_DENY 1 /* Deny specified (i.e. allow unspecified) */ ++#define WLC_MACMODE_ALLOW 2 /* Allow specified (i.e. deny unspecified) */ ++ ++/* ++ * 54g modes (basic bits may still be overridden) ++ * ++ * GMODE_LEGACY_B Rateset: 1b, 2b, 5.5, 11 ++ * Preamble: Long ++ * Shortslot: Off ++ * GMODE_AUTO Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 ++ * Extended Rateset: 6, 9, 12, 48 ++ * Preamble: Long ++ * Shortslot: Auto ++ * GMODE_ONLY Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54 ++ * Extended Rateset: 6b, 9, 12b, 48 ++ * Preamble: Short required ++ * Shortslot: Auto ++ * GMODE_B_DEFERRED Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 ++ * Extended Rateset: 6, 9, 12, 48 ++ * Preamble: Long ++ * Shortslot: On ++ * GMODE_PERFORMANCE Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54 ++ * Preamble: Short required ++ * Shortslot: On and required ++ * GMODE_LRS Rateset: 1b, 2b, 5.5b, 11b ++ * Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54 ++ * Preamble: Long ++ * Shortslot: Auto ++ */ ++#define GMODE_LEGACY_B 0 ++#define GMODE_AUTO 1 ++#define GMODE_ONLY 2 ++#define GMODE_B_DEFERRED 3 ++#define GMODE_PERFORMANCE 4 ++#define GMODE_LRS 5 ++#define GMODE_MAX 6 ++ ++/* values for PLCPHdr_override */ ++#define WLC_PLCP_AUTO -1 ++#define WLC_PLCP_SHORT 0 ++#define WLC_PLCP_LONG 1 ++ ++/* values for g_protection_override and n_protection_override */ ++#define WLC_PROTECTION_AUTO -1 ++#define WLC_PROTECTION_OFF 0 ++#define WLC_PROTECTION_ON 1 ++#define WLC_PROTECTION_MMHDR_ONLY 2 ++#define WLC_PROTECTION_CTS_ONLY 3 ++ ++/* values for g_protection_control and n_protection_control */ ++#define WLC_PROTECTION_CTL_OFF 0 ++#define WLC_PROTECTION_CTL_LOCAL 1 ++#define WLC_PROTECTION_CTL_OVERLAP 2 ++ ++/* values for n_protection */ ++#define WLC_N_PROTECTION_OFF 0 ++#define WLC_N_PROTECTION_OPTIONAL 1 ++#define WLC_N_PROTECTION_20IN40 2 ++#define WLC_N_PROTECTION_MIXEDMODE 3 ++ ++/* values for n_preamble_type */ ++#define WLC_N_PREAMBLE_MIXEDMODE 0 ++#define WLC_N_PREAMBLE_GF 1 ++#define WLC_N_PREAMBLE_GF_BRCM 2 ++ ++/* values for band specific 40MHz capabilities (deprecated) */ ++#define WLC_N_BW_20ALL 0 ++#define WLC_N_BW_40ALL 1 ++#define WLC_N_BW_20IN2G_40IN5G 2 ++ ++#define WLC_BW_20MHZ_BIT (1<<0) ++#define WLC_BW_40MHZ_BIT (1<<1) ++#define WLC_BW_80MHZ_BIT (1<<2) ++ ++/* Bandwidth capabilities */ ++#define WLC_BW_CAP_20MHZ (WLC_BW_20MHZ_BIT) ++#define WLC_BW_CAP_40MHZ (WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT) ++#define WLC_BW_CAP_80MHZ (WLC_BW_80MHZ_BIT|WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT) ++#define WLC_BW_CAP_UNRESTRICTED 0xFF ++ ++#define WL_BW_CAP_20MHZ(bw_cap) (((bw_cap) & WLC_BW_20MHZ_BIT) ? TRUE : FALSE) ++#define WL_BW_CAP_40MHZ(bw_cap) (((bw_cap) & WLC_BW_40MHZ_BIT) ? TRUE : FALSE) ++#define WL_BW_CAP_80MHZ(bw_cap) (((bw_cap) & WLC_BW_80MHZ_BIT) ? TRUE : FALSE) ++ ++/* values to force tx/rx chain */ ++#define WLC_N_TXRX_CHAIN0 0 ++#define WLC_N_TXRX_CHAIN1 1 ++ ++/* bitflags for SGI support (sgi_rx iovar) */ ++#define WLC_N_SGI_20 0x01 ++#define WLC_N_SGI_40 0x02 ++ ++/* when sgi_tx==WLC_SGI_ALL, bypass rate selection, enable sgi for all mcs */ ++#define WLC_SGI_ALL 0x02 ++ ++/* Values for PM */ ++#define PM_OFF 0 ++#define PM_MAX 1 ++#define PM_FAST 2 ++#define PM_FORCE_OFF 3 /* use this bit to force PM off even bt is active */ ++ ++#define LISTEN_INTERVAL 10 ++/* interference mitigation options */ ++#define INTERFERE_OVRRIDE_OFF -1 /* interference override off */ ++#define INTERFERE_NONE 0 /* off */ ++#define NON_WLAN 1 /* foreign/non 802.11 interference, no auto detect */ ++#define WLAN_MANUAL 2 /* ACI: no auto detection */ ++#define WLAN_AUTO 3 /* ACI: auto detect */ ++#define WLAN_AUTO_W_NOISE 4 /* ACI: auto - detect and non 802.11 interference */ ++#define AUTO_ACTIVE (1 << 7) /* Auto is currently active */ ++ ++typedef struct wl_aci_args { ++ int enter_aci_thresh; /* Trigger level to start detecting ACI */ ++ int exit_aci_thresh; /* Trigger level to exit ACI mode */ ++ int usec_spin; /* microsecs to delay between rssi samples */ ++ int glitch_delay; /* interval between ACI scans when glitch count is consistently high */ ++ uint16 nphy_adcpwr_enter_thresh; /* ADC power to enter ACI mitigation mode */ ++ uint16 nphy_adcpwr_exit_thresh; /* ADC power to exit ACI mitigation mode */ ++ uint16 nphy_repeat_ctr; /* Number of tries per channel to compute power */ ++ uint16 nphy_num_samples; /* Number of samples to compute power on one channel */ ++ uint16 nphy_undetect_window_sz; /* num of undetects to exit ACI Mitigation mode */ ++ uint16 nphy_b_energy_lo_aci; /* low ACI power energy threshold for bphy */ ++ uint16 nphy_b_energy_md_aci; /* mid ACI power energy threshold for bphy */ ++ uint16 nphy_b_energy_hi_aci; /* high ACI power energy threshold for bphy */ ++ uint16 nphy_noise_noassoc_glitch_th_up; /* wl interference 4 */ ++ uint16 nphy_noise_noassoc_glitch_th_dn; ++ uint16 nphy_noise_assoc_glitch_th_up; ++ uint16 nphy_noise_assoc_glitch_th_dn; ++ uint16 nphy_noise_assoc_aci_glitch_th_up; ++ uint16 nphy_noise_assoc_aci_glitch_th_dn; ++ uint16 nphy_noise_assoc_enter_th; ++ uint16 nphy_noise_noassoc_enter_th; ++ uint16 nphy_noise_assoc_rx_glitch_badplcp_enter_th; ++ uint16 nphy_noise_noassoc_crsidx_incr; ++ uint16 nphy_noise_assoc_crsidx_incr; ++ uint16 nphy_noise_crsidx_decr; ++} wl_aci_args_t; ++ ++#define TRIGGER_NOW 0 ++#define TRIGGER_CRS 0x01 ++#define TRIGGER_CRSDEASSERT 0x02 ++#define TRIGGER_GOODFCS 0x04 ++#define TRIGGER_BADFCS 0x08 ++#define TRIGGER_BADPLCP 0x10 ++#define TRIGGER_CRSGLITCH 0x20 ++#define WL_ACI_ARGS_LEGACY_LENGTH 16 /* bytes of pre NPHY aci args */ ++#define WL_SAMPLECOLLECT_T_VERSION 2 /* version of wl_samplecollect_args_t struct */ ++typedef struct wl_samplecollect_args { ++ /* version 0 fields */ ++ uint8 coll_us; ++ int cores; ++ /* add'l version 1 fields */ ++ uint16 version; /* see definition of WL_SAMPLECOLLECT_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ int8 trigger; ++ uint16 timeout; ++ uint16 mode; ++ uint32 pre_dur; ++ uint32 post_dur; ++ uint8 gpio_sel; ++ bool downsamp; ++ bool be_deaf; ++ bool agc; /* loop from init gain and going down */ ++ bool filter; /* override high pass corners to lowest */ ++ /* add'l version 2 fields */ ++ uint8 trigger_state; ++ uint8 module_sel1; ++ uint8 module_sel2; ++ uint16 nsamps; ++} wl_samplecollect_args_t; ++ ++#define WL_SAMPLEDATA_HEADER_TYPE 1 ++#define WL_SAMPLEDATA_HEADER_SIZE 80 /* sample collect header size (bytes) */ ++#define WL_SAMPLEDATA_TYPE 2 ++#define WL_SAMPLEDATA_SEQ 0xff /* sequence # */ ++#define WL_SAMPLEDATA_MORE_DATA 0x100 /* more data mask */ ++#define WL_SAMPLEDATA_T_VERSION 1 /* version of wl_samplecollect_args_t struct */ ++/* version for unpacked sample data, int16 {(I,Q),Core(0..N)} */ ++#define WL_SAMPLEDATA_T_VERSION_SPEC_AN 2 ++ ++typedef struct wl_sampledata { ++ uint16 version; /* structure version */ ++ uint16 size; /* size of structure */ ++ uint16 tag; /* Header/Data */ ++ uint16 length; /* data length */ ++ uint32 flag; /* bit def */ ++} wl_sampledata_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* wl_radar_args_t */ ++typedef struct { ++ int npulses; /* required number of pulses at n * t_int */ ++ int ncontig; /* required number of pulses at t_int */ ++ int min_pw; /* minimum pulse width (20 MHz clocks) */ ++ int max_pw; /* maximum pulse width (20 MHz clocks) */ ++ uint16 thresh0; /* Radar detection, thresh 0 */ ++ uint16 thresh1; /* Radar detection, thresh 1 */ ++ uint16 blank; /* Radar detection, blank control */ ++ uint16 fmdemodcfg; /* Radar detection, fmdemod config */ ++ int npulses_lp; /* Radar detection, minimum long pulses */ ++ int min_pw_lp; /* Minimum pulsewidth for long pulses */ ++ int max_pw_lp; /* Maximum pulsewidth for long pulses */ ++ int min_fm_lp; /* Minimum fm for long pulses */ ++ int max_span_lp; /* Maximum deltat for long pulses */ ++ int min_deltat; /* Minimum spacing between pulses */ ++ int max_deltat; /* Maximum spacing between pulses */ ++ uint16 autocorr; /* Radar detection, autocorr on or off */ ++ uint16 st_level_time; /* Radar detection, start_timing level */ ++ uint16 t2_min; /* minimum clocks needed to remain in state 2 */ ++ uint32 version; /* version */ ++ uint32 fra_pulse_err; /* sample error margin for detecting French radar pulsed */ ++ int npulses_fra; /* Radar detection, minimum French pulses set */ ++ int npulses_stg2; /* Radar detection, minimum staggered-2 pulses set */ ++ int npulses_stg3; /* Radar detection, minimum staggered-3 pulses set */ ++ uint16 percal_mask; /* defines which period cal is masked from radar detection */ ++ int quant; /* quantization resolution to pulse positions */ ++ uint32 min_burst_intv_lp; /* minimum burst to burst interval for bin3 radar */ ++ uint32 max_burst_intv_lp; /* maximum burst to burst interval for bin3 radar */ ++ int nskip_rst_lp; /* number of skipped pulses before resetting lp buffer */ ++ int max_pw_tol; /* maximum tollerance allowed in detected pulse width for radar detection */ ++ uint16 feature_mask; /* 16-bit mask to specify enabled features */ ++} wl_radar_args_t; ++ ++#define WL_RADAR_ARGS_VERSION 2 ++ ++typedef struct { ++ uint32 version; /* version */ ++ uint16 thresh0_20_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 20MHz */ ++ uint16 thresh1_20_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 20MHz */ ++ uint16 thresh0_40_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 40MHz */ ++ uint16 thresh1_40_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 40MHz */ ++ uint16 thresh0_80_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 80MHz */ ++ uint16 thresh1_80_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 80MHz */ ++ uint16 thresh0_160_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 160MHz */ ++ uint16 thresh1_160_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 160MHz */ ++ uint16 thresh0_20_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 20MHz */ ++ uint16 thresh1_20_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 20MHz */ ++ uint16 thresh0_40_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 40MHz */ ++ uint16 thresh1_40_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 40MHz */ ++ uint16 thresh0_80_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 80MHz */ ++ uint16 thresh1_80_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 80MHz */ ++ uint16 thresh0_160_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 160MHz */ ++ uint16 thresh1_160_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 160MHz */ ++} wl_radar_thr_t; ++ ++#define WL_RADAR_THR_VERSION 2 ++#define WL_THRESHOLD_LO_BAND 70 /* range from 5250MHz - 5350MHz */ ++ ++/* radar iovar SET defines */ ++#define WL_RADAR_DETECTOR_OFF 0 /* radar detector off */ ++#define WL_RADAR_DETECTOR_ON 1 /* radar detector on */ ++#define WL_RADAR_SIMULATED 2 /* force radar detector to declare ++ * detection once ++ */ ++#define WL_RSSI_ANT_VERSION 1 /* current version of wl_rssi_ant_t */ ++#define WL_ANT_RX_MAX 2 /* max 2 receive antennas */ ++#define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */ ++#define WL_ANT_IDX_1 0 /* antenna index 1 */ ++#define WL_ANT_IDX_2 1 /* antenna index 2 */ ++ ++#ifndef WL_RSSI_ANT_MAX ++#define WL_RSSI_ANT_MAX 4 /* max possible rx antennas */ ++#elif WL_RSSI_ANT_MAX != 4 ++#error "WL_RSSI_ANT_MAX does not match" ++#endif ++ ++/* RSSI per antenna */ ++typedef struct { ++ uint32 version; /* version field */ ++ uint32 count; /* number of valid antenna rssi */ ++ int8 rssi_ant[WL_RSSI_ANT_MAX]; /* rssi per antenna */ ++} wl_rssi_ant_t; ++ ++/* dfs_status iovar-related defines */ ++ ++/* cac - channel availability check, ++ * ism - in-service monitoring ++ * csa - channel switching announcement ++ */ ++ ++/* cac state values */ ++#define WL_DFS_CACSTATE_IDLE 0 /* state for operating in non-radar channel */ ++#define WL_DFS_CACSTATE_PREISM_CAC 1 /* CAC in progress */ ++#define WL_DFS_CACSTATE_ISM 2 /* ISM in progress */ ++#define WL_DFS_CACSTATE_CSA 3 /* csa */ ++#define WL_DFS_CACSTATE_POSTISM_CAC 4 /* ISM CAC */ ++#define WL_DFS_CACSTATE_PREISM_OOC 5 /* PREISM OOC */ ++#define WL_DFS_CACSTATE_POSTISM_OOC 6 /* POSTISM OOC */ ++#define WL_DFS_CACSTATES 7 /* this many states exist */ ++ ++/* data structure used in 'dfs_status' wl interface, which is used to query dfs status */ ++typedef struct { ++ uint state; /* noted by WL_DFS_CACSTATE_XX. */ ++ uint duration; /* time spent in ms in state. */ ++ /* as dfs enters ISM state, it removes the operational channel from quiet channel ++ * list and notes the channel in channel_cleared. set to 0 if no channel is cleared ++ */ ++ chanspec_t chanspec_cleared; ++ /* chanspec cleared used to be a uint, add another to uint16 to maintain size */ ++ uint16 pad; ++} wl_dfs_status_t; ++ ++#define NUM_PWRCTRL_RATES 12 ++ ++typedef struct { ++ uint8 txpwr_band_max[NUM_PWRCTRL_RATES]; /* User set target */ ++ uint8 txpwr_limit[NUM_PWRCTRL_RATES]; /* reg and local power limit */ ++ uint8 txpwr_local_max; /* local max according to the AP */ ++ uint8 txpwr_local_constraint; /* local constraint according to the AP */ ++ uint8 txpwr_chan_reg_max; /* Regulatory max for this channel */ ++ uint8 txpwr_target[2][NUM_PWRCTRL_RATES]; /* Latest target for 2.4 and 5 Ghz */ ++ uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ ++ uint8 txpwr_opo[NUM_PWRCTRL_RATES]; /* On G phy, OFDM power offset */ ++ uint8 txpwr_bphy_cck_max[NUM_PWRCTRL_RATES]; /* Max CCK power for this band (SROM) */ ++ uint8 txpwr_bphy_ofdm_max; /* Max OFDM power for this band (SROM) */ ++ uint8 txpwr_aphy_max[NUM_PWRCTRL_RATES]; /* Max power for A band (SROM) */ ++ int8 txpwr_antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ ++} tx_power_legacy_t; ++ ++#define WL_TX_POWER_RATES_LEGACY 45 ++#define WL_TX_POWER_MCS20_FIRST 12 ++#define WL_TX_POWER_MCS20_NUM 16 ++#define WL_TX_POWER_MCS40_FIRST 28 ++#define WL_TX_POWER_MCS40_NUM 17 ++ ++typedef struct { ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 local_max; /* local max according to the AP */ ++ uint8 local_constraint; /* local constraint according to the AP */ ++ int8 antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 rf_cores; /* count of RF Cores being reported */ ++ uint8 est_Pout[4]; /* Latest tx power out estimate per RF ++ * chain without adjustment ++ */ ++ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ uint8 user_limit[WL_TX_POWER_RATES_LEGACY]; /* User limit */ ++ uint8 reg_limit[WL_TX_POWER_RATES_LEGACY]; /* Regulatory power limit */ ++ uint8 board_limit[WL_TX_POWER_RATES_LEGACY]; /* Max power board can support (SROM) */ ++ uint8 target[WL_TX_POWER_RATES_LEGACY]; /* Latest target power */ ++} tx_power_legacy2_t; ++ ++/* TX Power index defines */ ++#define WL_NUM_RATES_CCK 4 /* 1, 2, 5.5, 11 Mbps */ ++#define WL_NUM_RATES_OFDM 8 /* 6, 9, 12, 18, 24, 36, 48, 54 Mbps SISO/CDD */ ++#define WL_NUM_RATES_MCS_1STREAM 8 /* MCS 0-7 1-stream rates - SISO/CDD/STBC/MCS */ ++#define WL_NUM_RATES_EXTRA_VHT 2 /* Additional VHT 11AC rates */ ++#define WL_NUM_RATES_VHT 10 ++#define WL_NUM_RATES_MCS32 1 ++ ++#define WLC_NUM_RATES_CCK WL_NUM_RATES_CCK ++#define WLC_NUM_RATES_OFDM WL_NUM_RATES_OFDM ++#define WLC_NUM_RATES_MCS_1_STREAM WL_NUM_RATES_MCS_1STREAM ++#define WLC_NUM_RATES_MCS_2_STREAM WL_NUM_RATES_MCS_1STREAM ++#define WLC_NUM_RATES_MCS32 WL_NUM_RATES_MCS32 ++#define WL_TX_POWER_CCK_NUM WL_NUM_RATES_CCK ++#define WL_TX_POWER_OFDM_NUM WL_NUM_RATES_OFDM ++#define WL_TX_POWER_MCS_1_STREAM_NUM WL_NUM_RATES_MCS_1STREAM ++#define WL_TX_POWER_MCS_2_STREAM_NUM WL_NUM_RATES_MCS_1STREAM ++#define WL_TX_POWER_MCS_32_NUM WL_NUM_RATES_MCS32 ++ ++#define WL_NUM_2x2_ELEMENTS 4 ++#define WL_NUM_3x3_ELEMENTS 6 ++ ++typedef struct txppr { ++ /* start of 20MHz tx power limits */ ++ uint8 b20_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 40MHz tx power limits */ ++ uint8 b40_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b40_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b40_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 20in40MHz tx power limits */ ++ uint8 b20in40_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20in40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20in40_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20in40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20in40_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* 20 in 40 MHz Legacy OFDM CDD */ ++ uint8 b20in40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20in40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20in40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20in40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20in40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20in40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20in40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20in40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20in40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20in40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20in40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 80MHz tx power limits */ ++ uint8 b80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 20in80MHz tx power limits */ ++ uint8 b20in80_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20in80_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20in80_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 40in80MHz tx power limits */ ++ uint8 b40in80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b40in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b40in80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b40in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b40in80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* MHz Legacy OFDM CDD */ ++ uint8 b40in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b40in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b40in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b40in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b40in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b40in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b40in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b40in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b40in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b40in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b40in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ uint8 mcs32; /* C_CHECK - THIS NEEDS TO BE REMOVED THROUGHOUT THE CODE */ ++} txppr_t; ++ ++/* 20MHz */ ++#define WL_TX_POWER_CCK_FIRST OFFSETOF(txppr_t, b20_1x1dsss) ++#define WL_TX_POWER_OFDM20_FIRST OFFSETOF(txppr_t, b20_1x1ofdm) ++#define WL_TX_POWER_MCS20_SISO_FIRST OFFSETOF(txppr_t, b20_1x1mcs0) ++#define WL_TX_POWER_20_S1x1_FIRST OFFSETOF(txppr_t, b20_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20_1x2dsss) ++#define WL_TX_POWER_OFDM20_CDD_FIRST OFFSETOF(txppr_t, b20_1x2cdd_ofdm) ++#define WL_TX_POWER_MCS20_CDD_FIRST OFFSETOF(txppr_t, b20_1x2cdd_mcs0) ++#define WL_TX_POWER_20_S1x2_FIRST OFFSETOF(txppr_t, b20_1x2cdd_mcs0) ++#define WL_TX_POWER_MCS20_STBC_FIRST OFFSETOF(txppr_t, b20_2x2stbc_mcs0) ++#define WL_TX_POWER_MCS20_SDM_FIRST OFFSETOF(txppr_t, b20_2x2sdm_mcs8) ++#define WL_TX_POWER_20_S2x2_FIRST OFFSETOF(txppr_t, b20_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3dsss) ++#define WL_TX_POWER_OFDM20_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3cdd_ofdm) ++#define WL_TX_POWER_20_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3cdd_mcs0) ++#define WL_TX_POWER_20_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20_2x3stbc_mcs0) ++#define WL_TX_POWER_20_S2x3_FIRST OFFSETOF(txppr_t, b20_2x3sdm_mcs8) ++#define WL_TX_POWER_20_S3x3_FIRST OFFSETOF(txppr_t, b20_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_20_S1X1_VHT OFFSETOF(txppr_t, b20_1x1vht) ++#define WL_TX_POWER_20_S1X2_CDD_VHT OFFSETOF(txppr_t, b20_1x2cdd_vht) ++#define WL_TX_POWER_20_S2X2_STBC_VHT OFFSETOF(txppr_t, b20_2x2stbc_vht) ++#define WL_TX_POWER_20_S2X2_VHT OFFSETOF(txppr_t, b20_2x2sdm_vht) ++#define WL_TX_POWER_20_S1X3_CDD_VHT OFFSETOF(txppr_t, b20_1x3cdd_vht) ++#define WL_TX_POWER_20_S2X3_STBC_VHT OFFSETOF(txppr_t, b20_2x3stbc_vht) ++#define WL_TX_POWER_20_S2X3_VHT OFFSETOF(txppr_t, b20_2x3sdm_vht) ++#define WL_TX_POWER_20_S3X3_VHT OFFSETOF(txppr_t, b20_3x3sdm_vht) ++ ++/* 40MHz */ ++#define WL_TX_POWER_40_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b40_dummy1x1dsss) ++#define WL_TX_POWER_OFDM40_FIRST OFFSETOF(txppr_t, b40_1x1ofdm) ++#define WL_TX_POWER_MCS40_SISO_FIRST OFFSETOF(txppr_t, b40_1x1mcs0) ++#define WL_TX_POWER_40_S1x1_FIRST OFFSETOF(txppr_t, b40_1x1mcs0) ++ ++#define WL_TX_POWER_40_DUMMY_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b40_dummy1x2dsss) ++#define WL_TX_POWER_OFDM40_CDD_FIRST OFFSETOF(txppr_t, b40_1x2cdd_ofdm) ++#define WL_TX_POWER_MCS40_CDD_FIRST OFFSETOF(txppr_t, b40_1x2cdd_mcs0) ++#define WL_TX_POWER_40_S1x2_FIRST OFFSETOF(txppr_t, b40_1x2cdd_mcs0) ++#define WL_TX_POWER_MCS40_STBC_FIRST OFFSETOF(txppr_t, b40_2x2stbc_mcs0) ++#define WL_TX_POWER_MCS40_SDM_FIRST OFFSETOF(txppr_t, b40_2x2sdm_mcs8) ++#define WL_TX_POWER_40_S2x2_FIRST OFFSETOF(txppr_t, b40_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_40_DUMMY_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40_dummy1x3dsss) ++#define WL_TX_POWER_OFDM40_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40_1x3cdd_ofdm) ++#define WL_TX_POWER_40_S1x3_FIRST OFFSETOF(txppr_t, b40_1x3cdd_mcs0) ++#define WL_TX_POWER_40_STBC_S2x3_FIRST OFFSETOF(txppr_t, b40_2x3stbc_mcs0) ++#define WL_TX_POWER_40_S2x3_FIRST OFFSETOF(txppr_t, b40_2x3sdm_mcs8) ++#define WL_TX_POWER_40_S3x3_FIRST OFFSETOF(txppr_t, b40_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_40_S1X1_VHT OFFSETOF(txppr_t, b40_1x1vht) ++#define WL_TX_POWER_40_S1X2_CDD_VHT OFFSETOF(txppr_t, b40_1x2cdd_vht) ++#define WL_TX_POWER_40_S2X2_STBC_VHT OFFSETOF(txppr_t, b40_2x2stbc_vht) ++#define WL_TX_POWER_40_S2X2_VHT OFFSETOF(txppr_t, b40_2x2sdm_vht) ++#define WL_TX_POWER_40_S1X3_CDD_VHT OFFSETOF(txppr_t, b40_1x3cdd_vht) ++#define WL_TX_POWER_40_S2X3_STBC_VHT OFFSETOF(txppr_t, b40_2x3stbc_vht) ++#define WL_TX_POWER_40_S2X3_VHT OFFSETOF(txppr_t, b40_2x3sdm_vht) ++#define WL_TX_POWER_40_S3X3_VHT OFFSETOF(txppr_t, b40_3x3sdm_vht) ++ ++/* 20 in 40MHz */ ++#define WL_TX_POWER_20UL_CCK_FIRST OFFSETOF(txppr_t, b20in40_1x1dsss) ++#define WL_TX_POWER_20UL_OFDM_FIRST OFFSETOF(txppr_t, b20in40_1x1ofdm) ++#define WL_TX_POWER_20UL_S1x1_FIRST OFFSETOF(txppr_t, b20in40_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_20U_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20in40_1x2dsss) ++#define WL_TX_POWER_20UL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b20in40_1x2cdd_ofdm) ++#define WL_TX_POWER_20UL_S1x2_FIRST OFFSETOF(txppr_t, b20in40_1x2cdd_mcs0) ++#define WL_TX_POWER_20UL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b20in40_2x2stbc_mcs0) ++#define WL_TX_POWER_20UL_S2x2_FIRST OFFSETOF(txppr_t, b20in40_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_20U_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3dsss) ++#define WL_TX_POWER_20UL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3cdd_ofdm) ++#define WL_TX_POWER_20UL_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3cdd_mcs0) ++#define WL_TX_POWER_20UL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20in40_2x3stbc_mcs0) ++#define WL_TX_POWER_20UL_S2x3_FIRST OFFSETOF(txppr_t, b20in40_2x3sdm_mcs8) ++#define WL_TX_POWER_20UL_S3x3_FIRST OFFSETOF(txppr_t, b20in40_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_20UL_S1X1_VHT OFFSETOF(txppr_t, b20in40_1x1vht) ++#define WL_TX_POWER_20UL_S1X2_CDD_VHT OFFSETOF(txppr_t, b20in40_1x2cdd_vht) ++#define WL_TX_POWER_20UL_S2X2_STBC_VHT OFFSETOF(txppr_t, b20in40_2x2stbc_vht) ++#define WL_TX_POWER_20UL_S2X2_VHT OFFSETOF(txppr_t, b20in40_2x2sdm_vht) ++#define WL_TX_POWER_20UL_S1X3_CDD_VHT OFFSETOF(txppr_t, b20in40_1x3cdd_vht) ++#define WL_TX_POWER_20UL_S2X3_STBC_VHT OFFSETOF(txppr_t, b20in40_2x3stbc_vht) ++#define WL_TX_POWER_20UL_S2X3_VHT OFFSETOF(txppr_t, b20in40_2x3sdm_vht) ++#define WL_TX_POWER_20UL_S3X3_VHT OFFSETOF(txppr_t, b20in40_3x3sdm_vht) ++ ++/* 80MHz */ ++#define WL_TX_POWER_80_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b80_dummy1x1dsss) ++#define WL_TX_POWER_OFDM80_FIRST OFFSETOF(txppr_t, b80_1x1ofdm) ++#define WL_TX_POWER_MCS80_SISO_FIRST OFFSETOF(txppr_t, b80_1x1mcs0) ++#define WL_TX_POWER_80_S1x1_FIRST OFFSETOF(txppr_t, b80_1x1mcs0) ++ ++#define WL_TX_POWER_80_DUMMY_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b80_dummy1x2dsss) ++#define WL_TX_POWER_OFDM80_CDD_FIRST OFFSETOF(txppr_t, b80_1x2cdd_ofdm) ++#define WL_TX_POWER_MCS80_CDD_FIRST OFFSETOF(txppr_t, b80_1x2cdd_mcs0) ++#define WL_TX_POWER_80_S1x2_FIRST OFFSETOF(txppr_t, b80_1x2cdd_mcs0) ++#define WL_TX_POWER_MCS80_STBC_FIRST OFFSETOF(txppr_t, b80_2x2stbc_mcs0) ++#define WL_TX_POWER_MCS80_SDM_FIRST OFFSETOF(txppr_t, b80_2x2sdm_mcs8) ++#define WL_TX_POWER_80_S2x2_FIRST OFFSETOF(txppr_t, b80_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_80_DUMMY_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b80_dummy1x3dsss) ++#define WL_TX_POWER_OFDM80_CDD_S1x3_FIRST OFFSETOF(txppr_t, b80_1x3cdd_ofdm) ++#define WL_TX_POWER_80_S1x3_FIRST OFFSETOF(txppr_t, b80_1x3cdd_mcs0) ++#define WL_TX_POWER_80_STBC_S2x3_FIRST OFFSETOF(txppr_t, b80_2x3stbc_mcs0) ++#define WL_TX_POWER_80_S2x3_FIRST OFFSETOF(txppr_t, b80_2x3sdm_mcs8) ++#define WL_TX_POWER_80_S3x3_FIRST OFFSETOF(txppr_t, b80_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_80_S1X1_VHT OFFSETOF(txppr_t, b80_1x1vht) ++#define WL_TX_POWER_80_S1X2_CDD_VHT OFFSETOF(txppr_t, b80_1x2cdd_vht) ++#define WL_TX_POWER_80_S2X2_STBC_VHT OFFSETOF(txppr_t, b80_2x2stbc_vht) ++#define WL_TX_POWER_80_S2X2_VHT OFFSETOF(txppr_t, b80_2x2sdm_vht) ++#define WL_TX_POWER_80_S1X3_CDD_VHT OFFSETOF(txppr_t, b80_1x3cdd_vht) ++#define WL_TX_POWER_80_S2X3_STBC_VHT OFFSETOF(txppr_t, b80_2x3stbc_vht) ++#define WL_TX_POWER_80_S2X3_VHT OFFSETOF(txppr_t, b80_2x3sdm_vht) ++#define WL_TX_POWER_80_S3X3_VHT OFFSETOF(txppr_t, b80_3x3sdm_vht) ++ ++/* 20 in 80MHz */ ++#define WL_TX_POWER_20UUL_CCK_FIRST OFFSETOF(txppr_t, b20in80_1x1dsss) ++#define WL_TX_POWER_20UUL_OFDM_FIRST OFFSETOF(txppr_t, b20in80_1x1ofdm) ++#define WL_TX_POWER_20UUL_S1x1_FIRST OFFSETOF(txppr_t, b20in80_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_20UU_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20in80_1x2dsss) ++#define WL_TX_POWER_20UUL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b20in80_1x2cdd_ofdm) ++#define WL_TX_POWER_20UUL_S1x2_FIRST OFFSETOF(txppr_t, b20in80_1x2cdd_mcs0) ++#define WL_TX_POWER_20UUL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b20in80_2x2stbc_mcs0) ++#define WL_TX_POWER_20UUL_S2x2_FIRST OFFSETOF(txppr_t, b20in80_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_20UU_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3dsss) ++#define WL_TX_POWER_20UUL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3cdd_ofdm) ++#define WL_TX_POWER_20UUL_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3cdd_mcs0) ++#define WL_TX_POWER_20UUL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20in80_2x3stbc_mcs0) ++#define WL_TX_POWER_20UUL_S2x3_FIRST OFFSETOF(txppr_t, b20in80_2x3sdm_mcs8) ++#define WL_TX_POWER_20UUL_S3x3_FIRST OFFSETOF(txppr_t, b20in80_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_20UUL_S1X1_VHT OFFSETOF(txppr_t, b20in80_1x1vht) ++#define WL_TX_POWER_20UUL_S1X2_CDD_VHT OFFSETOF(txppr_t, b20in80_1x2cdd_vht) ++#define WL_TX_POWER_20UUL_S2X2_STBC_VHT OFFSETOF(txppr_t, b20in80_2x2stbc_vht) ++#define WL_TX_POWER_20UUL_S2X2_VHT OFFSETOF(txppr_t, b20in80_2x2sdm_vht) ++#define WL_TX_POWER_20UUL_S1X3_CDD_VHT OFFSETOF(txppr_t, b20in80_1x3cdd_vht) ++#define WL_TX_POWER_20UUL_S2X3_STBC_VHT OFFSETOF(txppr_t, b20in80_2x3stbc_vht) ++#define WL_TX_POWER_20UUL_S2X3_VHT OFFSETOF(txppr_t, b20in80_2x3sdm_vht) ++#define WL_TX_POWER_20UUL_S3X3_VHT OFFSETOF(txppr_t, b20in80_3x3sdm_vht) ++ ++/* 40 in 80MHz */ ++#define WL_TX_POWER_40UUL_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b40in80_dummy1x1dsss) ++#define WL_TX_POWER_40UUL_OFDM_FIRST OFFSETOF(txppr_t, b40in80_1x1ofdm) ++#define WL_TX_POWER_40UUL_S1x1_FIRST OFFSETOF(txppr_t, b40in80_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_40UU_DUMMY_CDD_S1x2_FIRST OFFSETOF(txppr_t, b40in80_dummy1x2dsss) ++#define WL_TX_POWER_40UUL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b40in80_1x2cdd_ofdm) ++#define WL_TX_POWER_40UUL_S1x2_FIRST OFFSETOF(txppr_t, b40in80_1x2cdd_mcs0) ++#define WL_TX_POWER_40UUL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b40in80_2x2stbc_mcs0) ++#define WL_TX_POWER_40UUL_S2x2_FIRST OFFSETOF(txppr_t, b40in80_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_40UU_DUMMY_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40in80_dummy1x3dsss) ++#define WL_TX_POWER_40UUL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40in80_1x3cdd_ofdm) ++#define WL_TX_POWER_40UUL_S1x3_FIRST OFFSETOF(txppr_t, b40in80_1x3cdd_mcs0) ++#define WL_TX_POWER_40UUL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b40in80_2x3stbc_mcs0) ++#define WL_TX_POWER_40UUL_S2x3_FIRST OFFSETOF(txppr_t, b40in80_2x3sdm_mcs8) ++#define WL_TX_POWER_40UUL_S3x3_FIRST OFFSETOF(txppr_t, b40in80_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_40UUL_S1X1_VHT OFFSETOF(txppr_t, b40in80_1x1vht) ++#define WL_TX_POWER_40UUL_S1X2_CDD_VHT OFFSETOF(txppr_t, b40in80_1x2cdd_vht) ++#define WL_TX_POWER_40UUL_S2X2_STBC_VHT OFFSETOF(txppr_t, b40in80_2x2stbc_vht) ++#define WL_TX_POWER_40UUL_S2X2_VHT OFFSETOF(txppr_t, b40in80_2x2sdm_vht) ++#define WL_TX_POWER_40UUL_S1X3_CDD_VHT OFFSETOF(txppr_t, b40in80_1x3cdd_vht) ++#define WL_TX_POWER_40UUL_S2X3_STBC_VHT OFFSETOF(txppr_t, b40in80_2x3stbc_vht) ++#define WL_TX_POWER_40UUL_S2X3_VHT OFFSETOF(txppr_t, b40in80_2x3sdm_vht) ++#define WL_TX_POWER_40UUL_S3X3_VHT OFFSETOF(txppr_t, b40in80_3x3sdm_vht) ++ ++#define WL_TX_POWER_MCS_32 OFFSETOF(txppr_t, mcs32) /* C_CHECK remove later */ ++ ++#define WL_TX_POWER_RATES sizeof(struct txppr) ++ ++/* sslpnphy specifics */ ++#define WL_TX_POWER_MCS20_SISO_FIRST_SSN WL_TX_POWER_MCS20_SISO_FIRST ++#define WL_TX_POWER_MCS40_SISO_FIRST_SSN WL_TX_POWER_MCS40_SISO_FIRST ++ ++typedef struct { ++ uint16 ver; /* version of this struct */ ++ uint16 len; /* length in bytes of this structure */ ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 ppr[WL_TX_POWER_RATES]; /* Latest target power */ ++} wl_txppr_t; ++ ++#define WL_TXPPR_VERSION 0 ++#define WL_TXPPR_LENGTH (sizeof(wl_txppr_t)) ++#define TX_POWER_T_VERSION 43 ++ ++/* Defines used with channel_bandwidth for curpower */ ++#define WL_BW_20MHZ 0 ++#define WL_BW_40MHZ 1 ++#define WL_BW_80MHZ 2 ++ ++/* tx_power_t.flags bits */ ++#ifdef PPR_API ++#define WL_TX_POWER2_F_ENABLED 1 ++#define WL_TX_POWER2_F_HW 2 ++#define WL_TX_POWER2_F_MIMO 4 ++#define WL_TX_POWER2_F_SISO 8 ++#define WL_TX_POWER2_F_HT 0x10 ++#else ++#define WL_TX_POWER_F_ENABLED 1 ++#define WL_TX_POWER_F_HW 2 ++#define WL_TX_POWER_F_MIMO 4 ++#define WL_TX_POWER_F_SISO 8 ++#define WL_TX_POWER_F_HT 0x10 ++#endif ++ ++typedef struct { ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 local_max; /* local max according to the AP */ ++ uint8 local_constraint; /* local constraint according to the AP */ ++ int8 antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 rf_cores; /* count of RF Cores being reported */ ++ uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ ++ uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain w/o adjustment */ ++ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ uint8 tx_power_max[4]; /* Maximum target power among all rates */ ++ uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ ++ uint8 user_limit[WL_TX_POWER_RATES]; /* User limit */ ++ int8 board_limit[WL_TX_POWER_RATES]; /* Max power board can support (SROM) */ ++ int8 target[WL_TX_POWER_RATES]; /* Latest target power */ ++ int8 clm_limits[WL_NUMRATES]; /* regulatory limits - 20, 40 or 80MHz */ ++ int8 clm_limits_subchan1[WL_NUMRATES]; /* regulatory limits - 20in40 or 40in80 */ ++ int8 clm_limits_subchan2[WL_NUMRATES]; /* regulatory limits - 20in80MHz */ ++ int8 sar; /* SAR limit for display by wl executable */ ++ int8 channel_bandwidth; /* 20, 40 or 80 MHz bandwidth? */ ++ uint8 version; /* Version of the data format wlu <--> driver */ ++ uint8 display_core; /* Displayed curpower core */ ++#ifdef PPR_API ++} tx_power_new_t; ++#else ++} tx_power_t; ++#endif ++ ++typedef struct tx_inst_power { ++ uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ ++ uint8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ ++} tx_inst_power_t; ++ ++ ++typedef struct { ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 local_max; /* local max according to the AP */ ++ uint8 local_constraint; /* local constraint according to the AP */ ++ int8 antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 rf_cores; /* count of RF Cores being reported */ ++ uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ ++ uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain ++ * without adjustment ++ */ ++ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ uint8 tx_power_max[4]; /* Maximum target power among all rates */ ++ uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ ++ txppr_t user_limit; /* User limit */ ++ txppr_t reg_limit; /* Regulatory power limit */ ++ txppr_t board_limit; /* Max power board can support (SROM) */ ++ txppr_t target; /* Latest target power */ ++} wl_txpwr_t; ++ ++#define WL_NUM_TXCHAIN_MAX 4 ++typedef struct wl_txchain_pwr_offsets { ++ int8 offset[WL_NUM_TXCHAIN_MAX]; /* quarter dBm signed offset for each chain */ ++} wl_txchain_pwr_offsets_t; ++ ++/* 802.11h measurement types */ ++#define WLC_MEASURE_TPC 1 ++#define WLC_MEASURE_CHANNEL_BASIC 2 ++#define WLC_MEASURE_CHANNEL_CCA 3 ++#define WLC_MEASURE_CHANNEL_RPI 4 ++ ++/* regulatory enforcement levels */ ++#define SPECT_MNGMT_OFF 0 /* both 11h and 11d disabled */ ++#define SPECT_MNGMT_LOOSE_11H 1 /* allow non-11h APs in scan lists */ ++#define SPECT_MNGMT_STRICT_11H 2 /* prune out non-11h APs from scan list */ ++#define SPECT_MNGMT_STRICT_11D 3 /* switch to 802.11D mode */ ++/* SPECT_MNGMT_LOOSE_11H_D - same as SPECT_MNGMT_LOOSE with the exception that Country IE ++ * adoption is done regardless of capability spectrum_management ++ */ ++#define SPECT_MNGMT_LOOSE_11H_D 4 /* operation defined above */ ++ ++#define WL_CHAN_VALID_HW (1 << 0) /* valid with current HW */ ++#define WL_CHAN_VALID_SW (1 << 1) /* valid with current country setting */ ++#define WL_CHAN_BAND_5G (1 << 2) /* 5GHz-band channel */ ++#define WL_CHAN_RADAR (1 << 3) /* radar sensitive channel */ ++#define WL_CHAN_INACTIVE (1 << 4) /* temporarily inactive due to radar */ ++#define WL_CHAN_PASSIVE (1 << 5) /* channel is in passive mode */ ++#define WL_CHAN_RESTRICTED (1 << 6) /* restricted use channel */ ++ ++/* BTC mode used by "btc_mode" iovar */ ++#define WL_BTC_DISABLE 0 /* disable BT coexistence */ ++#define WL_BTC_FULLTDM 1 /* full TDM COEX */ ++#define WL_BTC_ENABLE 1 /* full TDM COEX to maintain backward compatiblity */ ++#define WL_BTC_PREMPT 2 /* full TDM COEX with preemption */ ++#define WL_BTC_LITE 3 /* light weight coex for large isolation platform */ ++#define WL_BTC_PARALLEL 4 /* BT and WLAN run in parallel with separate antenna */ ++#define WL_BTC_HYBRID 5 /* hybrid coex, only ack is allowed to transmit in BT slot */ ++#define WL_BTC_DEFAULT 8 /* set the default mode for the device */ ++#define WL_INF_BTC_DISABLE 0 ++#define WL_INF_BTC_ENABLE 1 ++#define WL_INF_BTC_AUTO 3 ++ ++/* BTC wire used by "btc_wire" iovar */ ++#define WL_BTC_DEFWIRE 0 /* use default wire setting */ ++#define WL_BTC_2WIRE 2 /* use 2-wire BTC */ ++#define WL_BTC_3WIRE 3 /* use 3-wire BTC */ ++#define WL_BTC_4WIRE 4 /* use 4-wire BTC */ ++ ++/* BTC flags: BTC configuration that can be set by host */ ++#define WL_BTC_FLAG_PREMPT (1 << 0) ++#define WL_BTC_FLAG_BT_DEF (1 << 1) ++#define WL_BTC_FLAG_ACTIVE_PROT (1 << 2) ++#define WL_BTC_FLAG_SIM_RSP (1 << 3) ++#define WL_BTC_FLAG_PS_PROTECT (1 << 4) ++#define WL_BTC_FLAG_SIM_TX_LP (1 << 5) ++#define WL_BTC_FLAG_ECI (1 << 6) ++#define WL_BTC_FLAG_LIGHT (1 << 7) ++#define WL_BTC_FLAG_PARALLEL (1 << 8) ++#endif /* !defined(LINUX_POSTMOGRIFY_REMOVAL) */ ++ ++/* Message levels */ ++#define WL_ERROR_VAL 0x00000001 ++#define WL_TRACE_VAL 0x00000002 ++#define WL_PRHDRS_VAL 0x00000004 ++#define WL_PRPKT_VAL 0x00000008 ++#define WL_INFORM_VAL 0x00000010 ++#define WL_TMP_VAL 0x00000020 ++#define WL_OID_VAL 0x00000040 ++#define WL_RATE_VAL 0x00000080 ++#define WL_ASSOC_VAL 0x00000100 ++#define WL_PRUSR_VAL 0x00000200 ++#define WL_PS_VAL 0x00000400 ++#define WL_TXPWR_VAL 0x00000800 /* retired in TOT on 6/10/2009 */ ++#define WL_PORT_VAL 0x00001000 ++#define WL_DUAL_VAL 0x00002000 ++#define WL_WSEC_VAL 0x00004000 ++#define WL_WSEC_DUMP_VAL 0x00008000 ++#define WL_LOG_VAL 0x00010000 ++#define WL_NRSSI_VAL 0x00020000 /* retired in TOT on 6/10/2009 */ ++#define WL_LOFT_VAL 0x00040000 /* retired in TOT on 6/10/2009 */ ++#define WL_REGULATORY_VAL 0x00080000 ++#define WL_PHYCAL_VAL 0x00100000 /* retired in TOT on 6/10/2009 */ ++#define WL_RADAR_VAL 0x00200000 /* retired in TOT on 6/10/2009 */ ++#define WL_MPC_VAL 0x00400000 ++#define WL_APSTA_VAL 0x00800000 ++#define WL_DFS_VAL 0x01000000 ++#define WL_BA_VAL 0x02000000 /* retired in TOT on 6/14/2010 */ ++#define WL_ACI_VAL 0x04000000 ++#define WL_MBSS_VAL 0x04000000 ++#define WL_CAC_VAL 0x08000000 ++#define WL_AMSDU_VAL 0x10000000 ++#define WL_AMPDU_VAL 0x20000000 ++#define WL_FFPLD_VAL 0x40000000 ++ ++/* wl_msg_level is full. For new bits take the next one and AND with ++ * wl_msg_level2 in wl_dbg.h ++ */ ++#define WL_DPT_VAL 0x00000001 ++#define WL_SCAN_VAL 0x00000002 ++#define WL_WOWL_VAL 0x00000004 ++#define WL_COEX_VAL 0x00000008 ++#define WL_RTDC_VAL 0x00000010 ++#define WL_PROTO_VAL 0x00000020 ++#define WL_BTA_VAL 0x00000040 ++#define WL_CHANINT_VAL 0x00000080 ++#define WL_THERMAL_VAL 0x00000100 /* retired in TOT on 6/10/2009 */ ++#define WL_P2P_VAL 0x00000200 ++#define WL_ITFR_VAL 0x00000400 ++#define WL_MCHAN_VAL 0x00000800 ++#define WL_TDLS_VAL 0x00001000 ++#define WL_MCNX_VAL 0x00002000 ++#define WL_PROT_VAL 0x00004000 ++#define WL_PSTA_VAL 0x00008000 ++#define WL_TSO_VAL 0x00010000 ++/* use top-bit for WL_TIME_STAMP_VAL because this is a modifier ++ * rather than a message-type of its own ++ */ ++#define WL_TIMESTAMP_VAL 0x80000000 ++ ++/* max # of leds supported by GPIO (gpio pin# == led index#) */ ++#define WL_LED_NUMGPIO 32 /* gpio 0-31 */ ++ ++/* led per-pin behaviors */ ++#define WL_LED_OFF 0 /* always off */ ++#define WL_LED_ON 1 /* always on */ ++#define WL_LED_ACTIVITY 2 /* activity */ ++#define WL_LED_RADIO 3 /* radio enabled */ ++#define WL_LED_ARADIO 4 /* 5 Ghz radio enabled */ ++#define WL_LED_BRADIO 5 /* 2.4Ghz radio enabled */ ++#define WL_LED_BGMODE 6 /* on if gmode, off if bmode */ ++#define WL_LED_WI1 7 ++#define WL_LED_WI2 8 ++#define WL_LED_WI3 9 ++#define WL_LED_ASSOC 10 /* associated state indicator */ ++#define WL_LED_INACTIVE 11 /* null behavior (clears default behavior) */ ++#define WL_LED_ASSOCACT 12 /* on when associated; blink fast for activity */ ++#define WL_LED_WI4 13 ++#define WL_LED_WI5 14 ++#define WL_LED_BLINKSLOW 15 /* blink slow */ ++#define WL_LED_BLINKMED 16 /* blink med */ ++#define WL_LED_BLINKFAST 17 /* blink fast */ ++#define WL_LED_BLINKCUSTOM 18 /* blink custom */ ++#define WL_LED_BLINKPERIODIC 19 /* blink periodic (custom 1000ms / off 400ms) */ ++#define WL_LED_ASSOC_WITH_SEC 20 /* when connected with security */ ++ /* keep on for 300 sec */ ++#define WL_LED_START_OFF 21 /* off upon boot, could be turned on later */ ++#define WL_LED_NUMBEHAVIOR 22 ++ ++/* led behavior numeric value format */ ++#define WL_LED_BEH_MASK 0x7f /* behavior mask */ ++#define WL_LED_AL_MASK 0x80 /* activelow (polarity) bit */ ++ ++/* maximum channels returned by the get valid channels iovar */ ++#define WL_NUMCHANNELS 64 ++ ++/* max number of chanspecs (used by the iovar to calc. buf space) */ ++#define WL_NUMCHANSPECS 110 ++ ++/* WDS link local endpoint WPA role */ ++#define WL_WDS_WPA_ROLE_AUTH 0 /* authenticator */ ++#define WL_WDS_WPA_ROLE_SUP 1 /* supplicant */ ++#define WL_WDS_WPA_ROLE_AUTO 255 /* auto, based on mac addr value */ ++ ++/* number of bytes needed to define a 128-bit mask for MAC event reporting */ ++#define WL_EVENTING_MASK_LEN 16 ++ ++/* ++ * Join preference iovar value is an array of tuples. Each tuple has a one-byte type, ++ * a one-byte length, and a variable length value. RSSI type tuple must be present ++ * in the array. ++ * ++ * Types are defined in "join preference types" section. ++ * ++ * Length is the value size in octets. It is reserved for WL_JOIN_PREF_WPA type tuple ++ * and must be set to zero. ++ * ++ * Values are defined below. ++ * ++ * 1. RSSI - 2 octets ++ * offset 0: reserved ++ * offset 1: reserved ++ * ++ * 2. WPA - 2 + 12 * n octets (n is # tuples defined below) ++ * offset 0: reserved ++ * offset 1: # of tuples ++ * offset 2: tuple 1 ++ * offset 14: tuple 2 ++ * ... ++ * offset 2 + 12 * (n - 1) octets: tuple n ++ * ++ * struct wpa_cfg_tuple { ++ * uint8 akm[DOT11_OUI_LEN+1]; akm suite ++ * uint8 ucipher[DOT11_OUI_LEN+1]; unicast cipher suite ++ * uint8 mcipher[DOT11_OUI_LEN+1]; multicast cipher suite ++ * }; ++ * ++ * multicast cipher suite can be specified as a specific cipher suite or WL_WPA_ACP_MCS_ANY. ++ * ++ * 3. BAND - 2 octets ++ * offset 0: reserved ++ * offset 1: see "band preference" and "band types" ++ * ++ * 4. BAND RSSI - 2 octets ++ * offset 0: band types ++ * offset 1: +ve RSSI boost balue in dB ++ */ ++ ++/* join preference types */ ++#define WL_JOIN_PREF_RSSI 1 /* by RSSI */ ++#define WL_JOIN_PREF_WPA 2 /* by akm and ciphers */ ++#define WL_JOIN_PREF_BAND 3 /* by 802.11 band */ ++#define WL_JOIN_PREF_RSSI_DELTA 4 /* by 802.11 band only if RSSI delta condition matches */ ++#define WL_JOIN_PREF_TRANS_PREF 5 /* defined by requesting AP */ ++ ++/* band preference */ ++#define WLJP_BAND_ASSOC_PREF 255 /* use what WLC_SET_ASSOC_PREFER ioctl specifies */ ++ ++/* any multicast cipher suite */ ++#define WL_WPA_ACP_MCS_ANY "\x00\x00\x00\x00" ++ ++struct tsinfo_arg { ++ uint8 octets[3]; ++}; ++ ++#define NFIFO 6 /* # tx/rx fifopairs */ ++ ++#define WL_CNT_T_VERSION 8 /* current version of wl_cnt_t struct */ ++ ++typedef struct { ++ uint16 version; /* see definition of WL_CNT_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txframe; /* tx data frames */ ++ uint32 txbyte; /* tx data bytes */ ++ uint32 txretrans; /* tx mac retransmits */ ++ uint32 txerror; /* tx data errors (derived: sum of others) */ ++ uint32 txctl; /* tx management frames */ ++ uint32 txprshort; /* tx short preamble frames */ ++ uint32 txserr; /* tx status errors */ ++ uint32 txnobuf; /* tx out of buffers errors */ ++ uint32 txnoassoc; /* tx discard because we're not associated */ ++ uint32 txrunt; /* tx runt frames */ ++ uint32 txchit; /* tx header cache hit (fastpath) */ ++ uint32 txcmiss; /* tx header cache miss (slowpath) */ ++ ++ /* transmit chip error counters */ ++ uint32 txuflo; /* tx fifo underflows */ ++ uint32 txphyerr; /* tx phy errors (indicated in tx status) */ ++ uint32 txphycrs; ++ ++ /* receive stat counters */ ++ uint32 rxframe; /* rx data frames */ ++ uint32 rxbyte; /* rx data bytes */ ++ uint32 rxerror; /* rx data errors (derived: sum of others) */ ++ uint32 rxctl; /* rx management frames */ ++ uint32 rxnobuf; /* rx out of buffers errors */ ++ uint32 rxnondata; /* rx non data frames in the data channel errors */ ++ uint32 rxbadds; /* rx bad DS errors */ ++ uint32 rxbadcm; /* rx bad control or management frames */ ++ uint32 rxfragerr; /* rx fragmentation errors */ ++ uint32 rxrunt; /* rx runt frames */ ++ uint32 rxgiant; /* rx giant frames */ ++ uint32 rxnoscb; /* rx no scb error */ ++ uint32 rxbadproto; /* rx invalid frames */ ++ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */ ++ uint32 rxbadda; /* rx frames tossed for invalid da */ ++ uint32 rxfilter; /* rx frames filtered out */ ++ ++ /* receive chip error counters */ ++ uint32 rxoflo; /* rx fifo overflow errors */ ++ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ ++ ++ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ ++ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ ++ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ ++ ++ /* misc counters */ ++ uint32 dmade; /* tx/rx dma descriptor errors */ ++ uint32 dmada; /* tx/rx dma data errors */ ++ uint32 dmape; /* tx/rx dma descriptor protocol errors */ ++ uint32 reset; /* reset count */ ++ uint32 tbtt; /* cnts the TBTT int's */ ++ uint32 txdmawar; ++ uint32 pkt_callback_reg_fail; /* callbacks register failure */ ++ ++ /* MAC counters: 32-bit version of d11.h's macstat_t */ ++ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, ++ * Control Management (includes retransmissions) ++ */ ++ uint32 txrtsfrm; /* number of RTS sent out by the MAC */ ++ uint32 txctsfrm; /* number of CTS sent out by the MAC */ ++ uint32 txackfrm; /* number of ACK frames sent out */ ++ uint32 txdnlfrm; /* Not used */ ++ uint32 txbcnfrm; /* beacons transmitted */ ++ uint32 txfunfl[8]; /* per-fifo tx underflows */ ++ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS ++ * or BCN) ++ */ ++ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for ++ * driver enqueued frames ++ */ ++ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ ++ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ ++ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not ++ * data/control/management ++ */ ++ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ ++ uint32 rxbadplcp; /* parity check of the PLCP header failed */ ++ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ ++ uint32 rxstrt; /* Number of received frames with a good PLCP ++ * (i.e. passing parity check) ++ */ ++ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ ++ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ ++ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ ++ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ ++ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ ++ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */ ++ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ ++ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ ++ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ ++ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */ ++ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */ ++ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ ++ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ ++ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC ++ * (unlikely to see these) ++ */ ++ uint32 rxbeaconmbss; /* beacons received from member of BSS */ ++ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from ++ * other BSS (WDS FRAME) ++ */ ++ uint32 rxbeaconobss; /* beacons received from other BSS */ ++ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames ++ * expecting a response ++ */ ++ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ ++ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */ ++ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ ++ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ ++ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ ++ uint32 pmqovfl; /* Number of PMQ overflows */ ++ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into ++ * the PRQ fifo ++ */ ++ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ ++ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did ++ * not get ACK ++ */ ++ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */ ++ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ ++ * fifo because a probe response could not be sent out within ++ * the time limit defined in M_PRS_MAXTIME ++ */ ++ uint32 rxnack; /* obsolete */ ++ uint32 frmscons; /* obsolete */ ++ uint32 txnack; /* obsolete */ ++ uint32 txglitch_nack; /* obsolete */ ++ uint32 txburst; /* obsolete */ ++ ++ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay; /* TKIPReplays */ ++ uint32 ccmpfmterr; /* CCMPFormatErrors */ ++ uint32 ccmpreplay; /* CCMPReplays */ ++ uint32 ccmpundec; /* CCMPDecryptErrors */ ++ uint32 fourwayfail; /* FourWayHandshakeFailures */ ++ uint32 wepundec; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess; /* DecryptSuccessCount */ ++ uint32 tkipicverr; /* TKIPICVErrorCount */ ++ uint32 wepexcluded; /* dot11WEPExcludedCount */ ++ ++ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */ ++ uint32 psmwds; /* Count PSM watchdogs */ ++ uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ ++ ++ /* MBSS counters, AP only */ ++ uint32 prq_entries_handled; /* PRQ entries read in */ ++ uint32 prq_undirected_entries; /* which were bcast bss & ssid */ ++ uint32 prq_bad_entries; /* which could not be translated to info */ ++ uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */ ++ uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */ ++ uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ ++ uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */ ++ ++ /* per-rate receive stat counters */ ++ uint32 rx1mbps; /* packets rx at 1Mbps */ ++ uint32 rx2mbps; /* packets rx at 2Mbps */ ++ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ ++ uint32 rx6mbps; /* packets rx at 6Mbps */ ++ uint32 rx9mbps; /* packets rx at 9Mbps */ ++ uint32 rx11mbps; /* packets rx at 11Mbps */ ++ uint32 rx12mbps; /* packets rx at 12Mbps */ ++ uint32 rx18mbps; /* packets rx at 18Mbps */ ++ uint32 rx24mbps; /* packets rx at 24Mbps */ ++ uint32 rx36mbps; /* packets rx at 36Mbps */ ++ uint32 rx48mbps; /* packets rx at 48Mbps */ ++ uint32 rx54mbps; /* packets rx at 54Mbps */ ++ uint32 rx108mbps; /* packets rx at 108mbps */ ++ uint32 rx162mbps; /* packets rx at 162mbps */ ++ uint32 rx216mbps; /* packets rx at 216 mbps */ ++ uint32 rx270mbps; /* packets rx at 270 mbps */ ++ uint32 rx324mbps; /* packets rx at 324 mbps */ ++ uint32 rx378mbps; /* packets rx at 378 mbps */ ++ uint32 rx432mbps; /* packets rx at 432 mbps */ ++ uint32 rx486mbps; /* packets rx at 486 mbps */ ++ uint32 rx540mbps; /* packets rx at 540 mbps */ ++ ++ /* pkteng rx frame stats */ ++ uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */ ++ uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */ ++ ++ uint32 rfdisable; /* count of radio disables */ ++ uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */ ++ ++ uint32 txexptime; /* Tx frames suppressed due to timer expiration */ ++ ++ uint32 txmpdu_sgi; /* count for sgi transmit */ ++ uint32 rxmpdu_sgi; /* count for sgi received */ ++ uint32 txmpdu_stbc; /* count for stbc transmit */ ++ uint32 rxmpdu_stbc; /* count for stbc received */ ++ ++ uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay_mcst; /* TKIPReplays */ ++ uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */ ++ uint32 ccmpreplay_mcst; /* CCMPReplays */ ++ uint32 ccmpundec_mcst; /* CCMPDecryptErrors */ ++ uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */ ++ uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess_mcst; /* DecryptSuccessCount */ ++ uint32 tkipicverr_mcst; /* TKIPICVErrorCount */ ++ uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */ ++ ++ uint32 dma_hang; /* count for dma hang */ ++ uint32 reinit; /* count for reinit */ ++ ++ uint32 pstatxucast; /* count of ucast frames xmitted on all psta assoc */ ++ uint32 pstatxnoassoc; /* count of txnoassoc frames xmitted on all psta assoc */ ++ uint32 pstarxucast; /* count of ucast frames received on all psta assoc */ ++ uint32 pstarxbcmc; /* count of bcmc frames received on all psta */ ++ uint32 pstatxbcmc; /* count of bcmc frames transmitted on all psta */ ++ ++ uint32 cso_passthrough; /* hw cso required but passthrough */ ++ uint32 cso_normal; /* hw cso hdr for normal process */ ++ uint32 chained; /* number of frames chained */ ++ uint32 chainedsz1; /* number of chain size 1 frames */ ++ uint32 unchained; /* number of frames not chained */ ++ uint32 maxchainsz; /* max chain size so far */ ++ uint32 currchainsz; /* current chain size */ ++} wl_cnt_t; ++ ++typedef struct { ++ uint16 version; /* see definition of WL_CNT_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txframe; /* tx data frames */ ++ uint32 txbyte; /* tx data bytes */ ++ uint32 txretrans; /* tx mac retransmits */ ++ uint32 txerror; /* tx data errors (derived: sum of others) */ ++ uint32 txctl; /* tx management frames */ ++ uint32 txprshort; /* tx short preamble frames */ ++ uint32 txserr; /* tx status errors */ ++ uint32 txnobuf; /* tx out of buffers errors */ ++ uint32 txnoassoc; /* tx discard because we're not associated */ ++ uint32 txrunt; /* tx runt frames */ ++ uint32 txchit; /* tx header cache hit (fastpath) */ ++ uint32 txcmiss; /* tx header cache miss (slowpath) */ ++ ++ /* transmit chip error counters */ ++ uint32 txuflo; /* tx fifo underflows */ ++ uint32 txphyerr; /* tx phy errors (indicated in tx status) */ ++ uint32 txphycrs; ++ ++ /* receive stat counters */ ++ uint32 rxframe; /* rx data frames */ ++ uint32 rxbyte; /* rx data bytes */ ++ uint32 rxerror; /* rx data errors (derived: sum of others) */ ++ uint32 rxctl; /* rx management frames */ ++ uint32 rxnobuf; /* rx out of buffers errors */ ++ uint32 rxnondata; /* rx non data frames in the data channel errors */ ++ uint32 rxbadds; /* rx bad DS errors */ ++ uint32 rxbadcm; /* rx bad control or management frames */ ++ uint32 rxfragerr; /* rx fragmentation errors */ ++ uint32 rxrunt; /* rx runt frames */ ++ uint32 rxgiant; /* rx giant frames */ ++ uint32 rxnoscb; /* rx no scb error */ ++ uint32 rxbadproto; /* rx invalid frames */ ++ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */ ++ uint32 rxbadda; /* rx frames tossed for invalid da */ ++ uint32 rxfilter; /* rx frames filtered out */ ++ ++ /* receive chip error counters */ ++ uint32 rxoflo; /* rx fifo overflow errors */ ++ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ ++ ++ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ ++ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ ++ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ ++ ++ /* misc counters */ ++ uint32 dmade; /* tx/rx dma descriptor errors */ ++ uint32 dmada; /* tx/rx dma data errors */ ++ uint32 dmape; /* tx/rx dma descriptor protocol errors */ ++ uint32 reset; /* reset count */ ++ uint32 tbtt; /* cnts the TBTT int's */ ++ uint32 txdmawar; ++ uint32 pkt_callback_reg_fail; /* callbacks register failure */ ++ ++ /* MAC counters: 32-bit version of d11.h's macstat_t */ ++ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, ++ * Control Management (includes retransmissions) ++ */ ++ uint32 txrtsfrm; /* number of RTS sent out by the MAC */ ++ uint32 txctsfrm; /* number of CTS sent out by the MAC */ ++ uint32 txackfrm; /* number of ACK frames sent out */ ++ uint32 txdnlfrm; /* Not used */ ++ uint32 txbcnfrm; /* beacons transmitted */ ++ uint32 txfunfl[8]; /* per-fifo tx underflows */ ++ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS ++ * or BCN) ++ */ ++ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for ++ * driver enqueued frames ++ */ ++ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ ++ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ ++ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not ++ * data/control/management ++ */ ++ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ ++ uint32 rxbadplcp; /* parity check of the PLCP header failed */ ++ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ ++ uint32 rxstrt; /* Number of received frames with a good PLCP ++ * (i.e. passing parity check) ++ */ ++ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ ++ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ ++ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ ++ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ ++ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ ++ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */ ++ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ ++ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ ++ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ ++ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */ ++ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */ ++ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ ++ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ ++ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC ++ * (unlikely to see these) ++ */ ++ uint32 rxbeaconmbss; /* beacons received from member of BSS */ ++ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from ++ * other BSS (WDS FRAME) ++ */ ++ uint32 rxbeaconobss; /* beacons received from other BSS */ ++ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames ++ * expecting a response ++ */ ++ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ ++ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */ ++ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ ++ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ ++ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ ++ uint32 pmqovfl; /* Number of PMQ overflows */ ++ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into ++ * the PRQ fifo ++ */ ++ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ ++ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did ++ * not get ACK ++ */ ++ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */ ++ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ ++ * fifo because a probe response could not be sent out within ++ * the time limit defined in M_PRS_MAXTIME ++ */ ++ uint32 rxnack; ++ uint32 frmscons; ++ uint32 txnack; ++ uint32 txglitch_nack; /* obsolete */ ++ uint32 txburst; /* obsolete */ ++ ++ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay; /* TKIPReplays */ ++ uint32 ccmpfmterr; /* CCMPFormatErrors */ ++ uint32 ccmpreplay; /* CCMPReplays */ ++ uint32 ccmpundec; /* CCMPDecryptErrors */ ++ uint32 fourwayfail; /* FourWayHandshakeFailures */ ++ uint32 wepundec; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess; /* DecryptSuccessCount */ ++ uint32 tkipicverr; /* TKIPICVErrorCount */ ++ uint32 wepexcluded; /* dot11WEPExcludedCount */ ++ ++ uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay_mcst; /* TKIPReplays */ ++ uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */ ++ uint32 ccmpreplay_mcst; /* CCMPReplays */ ++ uint32 ccmpundec_mcst; /* CCMPDecryptErrors */ ++ uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */ ++ uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess_mcst; /* DecryptSuccessCount */ ++ uint32 tkipicverr_mcst; /* TKIPICVErrorCount */ ++ uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */ ++ ++ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */ ++ uint32 txexptime; /* Tx frames suppressed due to timer expiration */ ++ uint32 psmwds; /* Count PSM watchdogs */ ++ uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ ++ ++ /* MBSS counters, AP only */ ++ uint32 prq_entries_handled; /* PRQ entries read in */ ++ uint32 prq_undirected_entries; /* which were bcast bss & ssid */ ++ uint32 prq_bad_entries; /* which could not be translated to info */ ++ uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */ ++ uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */ ++ uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ ++ uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */ ++ ++ /* per-rate receive stat counters */ ++ uint32 rx1mbps; /* packets rx at 1Mbps */ ++ uint32 rx2mbps; /* packets rx at 2Mbps */ ++ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ ++ uint32 rx6mbps; /* packets rx at 6Mbps */ ++ uint32 rx9mbps; /* packets rx at 9Mbps */ ++ uint32 rx11mbps; /* packets rx at 11Mbps */ ++ uint32 rx12mbps; /* packets rx at 12Mbps */ ++ uint32 rx18mbps; /* packets rx at 18Mbps */ ++ uint32 rx24mbps; /* packets rx at 24Mbps */ ++ uint32 rx36mbps; /* packets rx at 36Mbps */ ++ uint32 rx48mbps; /* packets rx at 48Mbps */ ++ uint32 rx54mbps; /* packets rx at 54Mbps */ ++ uint32 rx108mbps; /* packets rx at 108mbps */ ++ uint32 rx162mbps; /* packets rx at 162mbps */ ++ uint32 rx216mbps; /* packets rx at 216 mbps */ ++ uint32 rx270mbps; /* packets rx at 270 mbps */ ++ uint32 rx324mbps; /* packets rx at 324 mbps */ ++ uint32 rx378mbps; /* packets rx at 378 mbps */ ++ uint32 rx432mbps; /* packets rx at 432 mbps */ ++ uint32 rx486mbps; /* packets rx at 486 mbps */ ++ uint32 rx540mbps; /* packets rx at 540 mbps */ ++ ++ /* pkteng rx frame stats */ ++ uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */ ++ uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */ ++ ++ uint32 rfdisable; /* count of radio disables */ ++ uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */ ++ ++ uint32 txmpdu_sgi; /* count for sgi transmit */ ++ uint32 rxmpdu_sgi; /* count for sgi received */ ++ uint32 txmpdu_stbc; /* count for stbc transmit */ ++ uint32 rxmpdu_stbc; /* count for stbc received */ ++} wl_cnt_ver_six_t; ++ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#define WL_DELTA_STATS_T_VERSION 1 /* current version of wl_delta_stats_t struct */ ++ ++typedef struct { ++ uint16 version; /* see definition of WL_DELTA_STATS_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txframe; /* tx data frames */ ++ uint32 txbyte; /* tx data bytes */ ++ uint32 txretrans; /* tx mac retransmits */ ++ uint32 txfail; /* tx failures */ ++ ++ /* receive stat counters */ ++ uint32 rxframe; /* rx data frames */ ++ uint32 rxbyte; /* rx data bytes */ ++ ++ /* per-rate receive stat counters */ ++ uint32 rx1mbps; /* packets rx at 1Mbps */ ++ uint32 rx2mbps; /* packets rx at 2Mbps */ ++ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ ++ uint32 rx6mbps; /* packets rx at 6Mbps */ ++ uint32 rx9mbps; /* packets rx at 9Mbps */ ++ uint32 rx11mbps; /* packets rx at 11Mbps */ ++ uint32 rx12mbps; /* packets rx at 12Mbps */ ++ uint32 rx18mbps; /* packets rx at 18Mbps */ ++ uint32 rx24mbps; /* packets rx at 24Mbps */ ++ uint32 rx36mbps; /* packets rx at 36Mbps */ ++ uint32 rx48mbps; /* packets rx at 48Mbps */ ++ uint32 rx54mbps; /* packets rx at 54Mbps */ ++ uint32 rx108mbps; /* packets rx at 108mbps */ ++ uint32 rx162mbps; /* packets rx at 162mbps */ ++ uint32 rx216mbps; /* packets rx at 216 mbps */ ++ uint32 rx270mbps; /* packets rx at 270 mbps */ ++ uint32 rx324mbps; /* packets rx at 324 mbps */ ++ uint32 rx378mbps; /* packets rx at 378 mbps */ ++ uint32 rx432mbps; /* packets rx at 432 mbps */ ++ uint32 rx486mbps; /* packets rx at 486 mbps */ ++ uint32 rx540mbps; /* packets rx at 540 mbps */ ++} wl_delta_stats_t; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define WL_WME_CNT_VERSION 1 /* current version of wl_wme_cnt_t */ ++ ++typedef struct { ++ uint32 packets; ++ uint32 bytes; ++} wl_traffic_stats_t; ++ ++typedef struct { ++ uint16 version; /* see definition of WL_WME_CNT_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ wl_traffic_stats_t tx[AC_COUNT]; /* Packets transmitted */ ++ wl_traffic_stats_t tx_failed[AC_COUNT]; /* Packets dropped or failed to transmit */ ++ wl_traffic_stats_t rx[AC_COUNT]; /* Packets received */ ++ wl_traffic_stats_t rx_failed[AC_COUNT]; /* Packets failed to receive */ ++ ++ wl_traffic_stats_t forward[AC_COUNT]; /* Packets forwarded by AP */ ++ ++ wl_traffic_stats_t tx_expired[AC_COUNT]; /* packets dropped due to lifetime expiry */ ++ ++} wl_wme_cnt_t; ++ ++struct wl_msglevel2 { ++ uint32 low; ++ uint32 high; ++}; ++ ++typedef struct wl_mkeep_alive_pkt { ++ uint16 version; /* Version for mkeep_alive */ ++ uint16 length; /* length of fixed parameters in the structure */ ++ uint32 period_msec; ++ uint16 len_bytes; ++ uint8 keep_alive_id; /* 0 - 3 for N = 4 */ ++ uint8 data[1]; ++} wl_mkeep_alive_pkt_t; ++ ++#define WL_MKEEP_ALIVE_VERSION 1 ++#define WL_MKEEP_ALIVE_FIXED_LEN OFFSETOF(wl_mkeep_alive_pkt_t, data) ++#define WL_MKEEP_ALIVE_PRECISION 500 ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#ifdef WLBA ++ ++#define WLC_BA_CNT_VERSION 1 /* current version of wlc_ba_cnt_t */ ++ ++/* block ack related stats */ ++typedef struct wlc_ba_cnt { ++ uint16 version; /* WLC_BA_CNT_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txpdu; /* pdus sent */ ++ uint32 txsdu; /* sdus sent */ ++ uint32 txfc; /* tx side flow controlled packets */ ++ uint32 txfci; /* tx side flow control initiated */ ++ uint32 txretrans; /* retransmitted pdus */ ++ uint32 txbatimer; /* ba resend due to timer */ ++ uint32 txdrop; /* dropped packets */ ++ uint32 txaddbareq; /* addba req sent */ ++ uint32 txaddbaresp; /* addba resp sent */ ++ uint32 txdelba; /* delba sent */ ++ uint32 txba; /* ba sent */ ++ uint32 txbar; /* bar sent */ ++ uint32 txpad[4]; /* future */ ++ ++ /* receive side counters */ ++ uint32 rxpdu; /* pdus recd */ ++ uint32 rxqed; /* pdus buffered before sending up */ ++ uint32 rxdup; /* duplicate pdus */ ++ uint32 rxnobuf; /* pdus discarded due to no buf */ ++ uint32 rxaddbareq; /* addba req recd */ ++ uint32 rxaddbaresp; /* addba resp recd */ ++ uint32 rxdelba; /* delba recd */ ++ uint32 rxba; /* ba recd */ ++ uint32 rxbar; /* bar recd */ ++ uint32 rxinvba; /* invalid ba recd */ ++ uint32 rxbaholes; /* ba recd with holes */ ++ uint32 rxunexp; /* unexpected packets */ ++ uint32 rxpad[4]; /* future */ ++} wlc_ba_cnt_t; ++#endif /* WLBA */ ++ ++/* structure for per-tid ampdu control */ ++struct ampdu_tid_control { ++ uint8 tid; /* tid */ ++ uint8 enable; /* enable/disable */ ++}; ++ ++/* structure for identifying ea/tid for sending addba/delba */ ++struct ampdu_ea_tid { ++ struct ether_addr ea; /* Station address */ ++ uint8 tid; /* tid */ ++}; ++/* structure for identifying retry/tid for retry_limit_tid/rr_retry_limit_tid */ ++struct ampdu_retry_tid { ++ uint8 tid; /* tid */ ++ uint8 retry; /* retry value */ ++}; ++ ++/* Different discovery modes for dpt */ ++#define DPT_DISCOVERY_MANUAL 0x01 /* manual discovery mode */ ++#define DPT_DISCOVERY_AUTO 0x02 /* auto discovery mode */ ++#define DPT_DISCOVERY_SCAN 0x04 /* scan-based discovery mode */ ++ ++/* different path selection values */ ++#define DPT_PATHSEL_AUTO 0 /* auto mode for path selection */ ++#define DPT_PATHSEL_DIRECT 1 /* always use direct DPT path */ ++#define DPT_PATHSEL_APPATH 2 /* always use AP path */ ++ ++/* different ops for deny list */ ++#define DPT_DENY_LIST_ADD 1 /* add to dpt deny list */ ++#define DPT_DENY_LIST_REMOVE 2 /* remove from dpt deny list */ ++ ++/* different ops for manual end point */ ++#define DPT_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ ++#define DPT_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ ++#define DPT_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ ++ ++/* structure for dpt iovars */ ++typedef struct dpt_iovar { ++ struct ether_addr ea; /* Station address */ ++ uint8 mode; /* mode: depends on iovar */ ++ uint32 pad; /* future */ ++} dpt_iovar_t; ++ ++/* flags to indicate DPT status */ ++#define DPT_STATUS_ACTIVE 0x01 /* link active (though may be suspended) */ ++#define DPT_STATUS_AES 0x02 /* link secured through AES encryption */ ++#define DPT_STATUS_FAILED 0x04 /* DPT link failed */ ++ ++#define DPT_FNAME_LEN 48 /* Max length of friendly name */ ++ ++typedef struct dpt_status { ++ uint8 status; /* flags to indicate status */ ++ uint8 fnlen; /* length of friendly name */ ++ uchar name[DPT_FNAME_LEN]; /* friendly name */ ++ uint32 rssi; /* RSSI of the link */ ++ sta_info_t sta; /* sta info */ ++} dpt_status_t; ++ ++/* structure for dpt list */ ++typedef struct dpt_list { ++ uint32 num; /* number of entries in struct */ ++ dpt_status_t status[1]; /* per station info */ ++} dpt_list_t; ++ ++/* structure for dpt friendly name */ ++typedef struct dpt_fname { ++ uint8 len; /* length of friendly name */ ++ uchar name[DPT_FNAME_LEN]; /* friendly name */ ++} dpt_fname_t; ++ ++#define BDD_FNAME_LEN 32 /* Max length of friendly name */ ++typedef struct bdd_fname { ++ uint8 len; /* length of friendly name */ ++ uchar name[BDD_FNAME_LEN]; /* friendly name */ ++} bdd_fname_t; ++ ++/* structure for addts arguments */ ++/* For ioctls that take a list of TSPEC */ ++struct tslist { ++ int count; /* number of tspecs */ ++ struct tsinfo_arg tsinfo[1]; /* variable length array of tsinfo */ ++}; ++ ++#ifdef WLTDLS ++/* different ops for manual end point */ ++#define TDLS_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ ++#define TDLS_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ ++#define TDLS_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ ++#define TDLS_MANUAL_EP_PM 4 /* put dpt endpoint in PM mode */ ++#define TDLS_MANUAL_EP_WAKE 5 /* wake up dpt endpoint from PM */ ++#define TDLS_MANUAL_EP_DISCOVERY 6 /* discover if endpoint is TDLS capable */ ++#define TDLS_MANUAL_EP_CHSW 7 /* channel switch */ ++ ++/* structure for tdls iovars */ ++typedef struct tdls_iovar { ++ struct ether_addr ea; /* Station address */ ++ uint8 mode; /* mode: depends on iovar */ ++ chanspec_t chanspec; ++ uint32 pad; /* future */ ++} tdls_iovar_t; ++#endif /* WLTDLS */ ++ ++/* structure for addts/delts arguments */ ++typedef struct tspec_arg { ++ uint16 version; /* see definition of TSPEC_ARG_VERSION */ ++ uint16 length; /* length of entire structure */ ++ uint flag; /* bit field */ ++ /* TSPEC Arguments */ ++ struct tsinfo_arg tsinfo; /* TS Info bit field */ ++ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ ++ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ ++ uint min_srv_interval; /* Minimum Service Interval (us) */ ++ uint max_srv_interval; /* Maximum Service Interval (us) */ ++ uint inactivity_interval; /* Inactivity Interval (us) */ ++ uint suspension_interval; /* Suspension Interval (us) */ ++ uint srv_start_time; /* Service Start Time (us) */ ++ uint min_data_rate; /* Minimum Data Rate (bps) */ ++ uint mean_data_rate; /* Mean Data Rate (bps) */ ++ uint peak_data_rate; /* Peak Data Rate (bps) */ ++ uint max_burst_size; /* Maximum Burst Size (bytes) */ ++ uint delay_bound; /* Delay Bound (us) */ ++ uint min_phy_rate; /* Minimum PHY Rate (bps) */ ++ uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0 to 8.0) */ ++ uint16 medium_time; /* Medium Time (32 us/s periods) */ ++ uint8 dialog_token; /* dialog token */ ++} tspec_arg_t; ++ ++/* tspec arg for desired station */ ++typedef struct tspec_per_sta_arg { ++ struct ether_addr ea; ++ struct tspec_arg ts; ++} tspec_per_sta_arg_t; ++ ++/* structure for max bandwidth for each access category */ ++typedef struct wme_max_bandwidth { ++ uint32 ac[AC_COUNT]; /* max bandwidth for each access category */ ++} wme_max_bandwidth_t; ++ ++#define WL_WME_MBW_PARAMS_IO_BYTES (sizeof(wme_max_bandwidth_t)) ++ ++/* current version of wl_tspec_arg_t struct */ ++#define TSPEC_ARG_VERSION 2 /* current version of wl_tspec_arg_t struct */ ++#define TSPEC_ARG_LENGTH 55 /* argument length from tsinfo to medium_time */ ++#define TSPEC_DEFAULT_DIALOG_TOKEN 42 /* default dialog token */ ++#define TSPEC_DEFAULT_SBW_FACTOR 0x3000 /* default surplus bw */ ++ ++ ++#define WL_WOWL_KEEPALIVE_MAX_PACKET_SIZE 80 ++#define WLC_WOWL_MAX_KEEPALIVE 2 ++ ++/* define for flag */ ++#define TSPEC_PENDING 0 /* TSPEC pending */ ++#define TSPEC_ACCEPTED 1 /* TSPEC accepted */ ++#define TSPEC_REJECTED 2 /* TSPEC rejected */ ++#define TSPEC_UNKNOWN 3 /* TSPEC unknown */ ++#define TSPEC_STATUS_MASK 7 /* TSPEC status mask */ ++ ++ ++/* Software feature flag defines used by wlfeatureflag */ ++#ifdef WLAFTERBURNER ++#define WL_SWFL_ABBFL 0x0001 /* Allow Afterburner on systems w/o hardware BFL */ ++#define WL_SWFL_ABENCORE 0x0002 /* Allow AB on non-4318E chips */ ++#endif /* WLAFTERBURNER */ ++#define WL_SWFL_NOHWRADIO 0x0004 ++#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */ ++#define WL_SWFL_WLBSSSORT 0x0010 /* Per-port supports sorting of BSS */ ++ ++#define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */ ++ ++/* Packet lifetime configuration per ac */ ++typedef struct wl_lifetime { ++ uint32 ac; /* access class */ ++ uint32 lifetime; /* Packet lifetime value in ms */ ++} wl_lifetime_t; ++ ++/* Channel Switch Announcement param */ ++typedef struct wl_chan_switch { ++ uint8 mode; /* value 0 or 1 */ ++ uint8 count; /* count # of beacons before switching */ ++ chanspec_t chspec; /* chanspec */ ++ uint8 reg; /* regulatory class */ ++} wl_chan_switch_t; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* Roaming trigger definitions for WLC_SET_ROAM_TRIGGER. ++ * ++ * (-100 < value < 0) value is used directly as a roaming trigger in dBm ++ * (0 <= value) value specifies a logical roaming trigger level from ++ * the list below ++ * ++ * WLC_GET_ROAM_TRIGGER always returns roaming trigger value in dBm, never ++ * the logical roam trigger value. ++ */ ++#define WLC_ROAM_TRIGGER_DEFAULT 0 /* default roaming trigger */ ++#define WLC_ROAM_TRIGGER_BANDWIDTH 1 /* optimize for bandwidth roaming trigger */ ++#define WLC_ROAM_TRIGGER_DISTANCE 2 /* optimize for distance roaming trigger */ ++#define WLC_ROAM_TRIGGER_AUTO 3 /* auto-detect environment */ ++#define WLC_ROAM_TRIGGER_MAX_VALUE 3 /* max. valid value */ ++ ++#define WLC_ROAM_NEVER_ROAM_TRIGGER (-100) /* Avoid Roaming by setting a large value */ ++ ++/* Preferred Network Offload (PNO, formerly PFN) defines */ ++#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ ++ ++enum { ++ PFN_LIST_ORDER, ++ PFN_RSSI ++}; ++ ++enum { ++ DISABLE, ++ ENABLE ++}; ++ ++enum { ++ OFF_ADAPT, ++ SMART_ADAPT, ++ STRICT_ADAPT, ++ SLOW_ADAPT ++}; ++ ++#define SORT_CRITERIA_BIT 0 ++#define AUTO_NET_SWITCH_BIT 1 ++#define ENABLE_BKGRD_SCAN_BIT 2 ++#define IMMEDIATE_SCAN_BIT 3 ++#define AUTO_CONNECT_BIT 4 ++#define ENABLE_BD_SCAN_BIT 5 ++#define ENABLE_ADAPTSCAN_BIT 6 ++#define IMMEDIATE_EVENT_BIT 8 ++ ++#define SORT_CRITERIA_MASK 0x0001 ++#define AUTO_NET_SWITCH_MASK 0x0002 ++#define ENABLE_BKGRD_SCAN_MASK 0x0004 ++#define IMMEDIATE_SCAN_MASK 0x0008 ++#define AUTO_CONNECT_MASK 0x0010 ++ ++#define ENABLE_BD_SCAN_MASK 0x0020 ++#define ENABLE_ADAPTSCAN_MASK 0x00c0 ++#define IMMEDIATE_EVENT_MASK 0x0100 ++ ++#define PFN_VERSION 2 ++#define PFN_SCANRESULT_VERSION 1 ++#define MAX_PFN_LIST_COUNT 16 ++ ++#define PFN_COMPLETE 1 ++#define PFN_INCOMPLETE 0 ++ ++#define DEFAULT_BESTN 2 ++#define DEFAULT_MSCAN 0 ++#define DEFAULT_REPEAT 10 ++#define DEFAULT_EXP 2 ++ ++/* PFN network info structure */ ++typedef struct wl_pfn_subnet_info { ++ struct ether_addr BSSID; ++ uint8 channel; /* channel number only */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++} wl_pfn_subnet_info_t; ++ ++typedef struct wl_pfn_net_info { ++ wl_pfn_subnet_info_t pfnsubnet; ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ uint16 timestamp; /* age in seconds */ ++} wl_pfn_net_info_t; ++ ++typedef struct wl_pfn_scanresults { ++ uint32 version; ++ uint32 status; ++ uint32 count; ++ wl_pfn_net_info_t netinfo[1]; ++} wl_pfn_scanresults_t; ++ ++/* PFN data structure */ ++typedef struct wl_pfn_param { ++ int32 version; /* PNO parameters version */ ++ int32 scan_freq; /* Scan frequency */ ++ int32 lost_network_timeout; /* Timeout in sec. to declare ++ * discovered network as lost ++ */ ++ int16 flags; /* Bit field to control features ++ * of PFN such as sort criteria auto ++ * enable switch and background scan ++ */ ++ int16 rssi_margin; /* Margin to avoid jitter for choosing a ++ * PFN based on RSSI sort criteria ++ */ ++ uint8 bestn; /* number of best networks in each scan */ ++ uint8 mscan; /* number of scans recorded */ ++ uint8 repeat; /* Minimum number of scan intervals ++ *before scan frequency changes in adaptive scan ++ */ ++ uint8 exp; /* Exponent of 2 for maximum scan interval */ ++#if !defined(WLC_PATCH) || !defined(BCM43362A2) ++ int32 slow_freq; /* slow scan period */ ++#endif /* !WLC_PATCH || !BCM43362A2 */ ++} wl_pfn_param_t; ++ ++typedef struct wl_pfn { ++ wlc_ssid_t ssid; /* ssid name and its length */ ++ int32 bss_type; /* IBSS or infrastructure */ ++ int32 infra; /* BSS Vs IBSS */ ++ int32 auth; /* Open Vs Closed */ ++ int32 wpa_auth; /* WPA type */ ++ int32 wsec; /* wsec value */ ++} wl_pfn_t; ++#define WL_PFN_HIDDEN_BIT 2 ++#define PNO_SCAN_MAX_FW 508*1000 /* max time scan time in msec */ ++#define PNO_SCAN_MAX_FW_SEC PNO_SCAN_MAX_FW/1000 /* max time scan time in SEC */ ++#define PNO_SCAN_MIN_FW_SEC 10 /* min time scan time in SEC */ ++#define WL_PFN_HIDDEN_MASK 0x4 ++ ++/* TCP Checksum Offload defines */ ++#define TOE_TX_CSUM_OL 0x00000001 ++#define TOE_RX_CSUM_OL 0x00000002 ++ ++/* TCP Checksum Offload error injection for testing */ ++#define TOE_ERRTEST_TX_CSUM 0x00000001 ++#define TOE_ERRTEST_RX_CSUM 0x00000002 ++#define TOE_ERRTEST_RX_CSUM2 0x00000004 ++ ++struct toe_ol_stats_t { ++ /* Num of tx packets that don't need to be checksummed */ ++ uint32 tx_summed; ++ ++ /* Num of tx packets where checksum is filled by offload engine */ ++ uint32 tx_iph_fill; ++ uint32 tx_tcp_fill; ++ uint32 tx_udp_fill; ++ uint32 tx_icmp_fill; ++ ++ /* Num of rx packets where toe finds out if checksum is good or bad */ ++ uint32 rx_iph_good; ++ uint32 rx_iph_bad; ++ uint32 rx_tcp_good; ++ uint32 rx_tcp_bad; ++ uint32 rx_udp_good; ++ uint32 rx_udp_bad; ++ uint32 rx_icmp_good; ++ uint32 rx_icmp_bad; ++ ++ /* Num of tx packets in which csum error is injected */ ++ uint32 tx_tcp_errinj; ++ uint32 tx_udp_errinj; ++ uint32 tx_icmp_errinj; ++ ++ /* Num of rx packets in which csum error is injected */ ++ uint32 rx_tcp_errinj; ++ uint32 rx_udp_errinj; ++ uint32 rx_icmp_errinj; ++}; ++ ++/* ARP Offload feature flags for arp_ol iovar */ ++#define ARP_OL_AGENT 0x00000001 ++#define ARP_OL_SNOOP 0x00000002 ++#define ARP_OL_HOST_AUTO_REPLY 0x00000004 ++#define ARP_OL_PEER_AUTO_REPLY 0x00000008 ++ ++/* ARP Offload error injection */ ++#define ARP_ERRTEST_REPLY_PEER 0x1 ++#define ARP_ERRTEST_REPLY_HOST 0x2 ++ ++#define ARP_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ ++#define ND_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ ++ ++/* Arp offload statistic counts */ ++struct arp_ol_stats_t { ++ uint32 host_ip_entries; /* Host IP table addresses (more than one if multihomed) */ ++ uint32 host_ip_overflow; /* Host IP table additions skipped due to overflow */ ++ ++ uint32 arp_table_entries; /* ARP table entries */ ++ uint32 arp_table_overflow; /* ARP table additions skipped due to overflow */ ++ ++ uint32 host_request; /* ARP requests from host */ ++ uint32 host_reply; /* ARP replies from host */ ++ uint32 host_service; /* ARP requests from host serviced by ARP Agent */ ++ ++ uint32 peer_request; /* ARP requests received from network */ ++ uint32 peer_request_drop; /* ARP requests from network that were dropped */ ++ uint32 peer_reply; /* ARP replies received from network */ ++ uint32 peer_reply_drop; /* ARP replies from network that were dropped */ ++ uint32 peer_service; /* ARP request from host serviced by ARP Agent */ ++}; ++ ++/* NS offload statistic counts */ ++struct nd_ol_stats_t { ++ uint32 host_ip_entries; /* Host IP table addresses (more than one if multihomed) */ ++ uint32 host_ip_overflow; /* Host IP table additions skipped due to overflow */ ++ uint32 peer_request; /* NS requests received from network */ ++ uint32 peer_request_drop; /* NS requests from network that were dropped */ ++ uint32 peer_reply_drop; /* NA replies from network that were dropped */ ++ uint32 peer_service; /* NS request from host serviced by firmware */ ++}; ++ ++/* ++ * Keep-alive packet offloading. ++ */ ++ ++/* NAT keep-alive packets format: specifies the re-transmission period, the packet ++ * length, and packet contents. ++ */ ++typedef struct wl_keep_alive_pkt { ++ uint32 period_msec; /* Retransmission period (0 to disable packet re-transmits) */ ++ uint16 len_bytes; /* Size of packet to transmit (0 to disable packet re-transmits) */ ++ uint8 data[1]; /* Variable length packet to transmit. Contents should include ++ * entire ethernet packet (enet header, IP header, UDP header, ++ * and UDP payload) in network byte order. ++ */ ++} wl_keep_alive_pkt_t; ++ ++#define WL_KEEP_ALIVE_FIXED_LEN OFFSETOF(wl_keep_alive_pkt_t, data) ++ ++/* ++ * Dongle pattern matching filter. ++ */ ++ ++/* Packet filter types. Currently, only pattern matching is supported. */ ++typedef enum wl_pkt_filter_type { ++ WL_PKT_FILTER_TYPE_PATTERN_MATCH /* Pattern matching filter */ ++} wl_pkt_filter_type_t; ++ ++#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t ++ ++/* Pattern matching filter. Specifies an offset within received packets to ++ * start matching, the pattern to match, the size of the pattern, and a bitmask ++ * that indicates which bits within the pattern should be matched. ++ */ ++typedef struct wl_pkt_filter_pattern { ++ uint32 offset; /* Offset within received packet to start pattern matching. ++ * Offset '0' is the first byte of the ethernet header. ++ */ ++ uint32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */ ++ uint8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts ++ * at offset 0. Pattern immediately follows mask. ++ */ ++} wl_pkt_filter_pattern_t; ++ ++/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ ++typedef struct wl_pkt_filter { ++ uint32 id; /* Unique filter id, specified by app. */ ++ uint32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ ++ uint32 negate_match; /* Negate the result of filter matches */ ++ union { /* Filter definitions */ ++ wl_pkt_filter_pattern_t pattern; /* Pattern matching filter */ ++ } u; ++} wl_pkt_filter_t; ++ ++#define WL_PKT_FILTER_FIXED_LEN OFFSETOF(wl_pkt_filter_t, u) ++#define WL_PKT_FILTER_PATTERN_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_t, mask_and_pattern) ++ ++/* IOVAR "pkt_filter_enable" parameter. */ ++typedef struct wl_pkt_filter_enable { ++ uint32 id; /* Unique filter id */ ++ uint32 enable; /* Enable/disable bool */ ++} wl_pkt_filter_enable_t; ++ ++/* IOVAR "pkt_filter_list" parameter. Used to retrieve a list of installed filters. */ ++typedef struct wl_pkt_filter_list { ++ uint32 num; /* Number of installed packet filters */ ++ wl_pkt_filter_t filter[1]; /* Variable array of packet filters. */ ++} wl_pkt_filter_list_t; ++ ++#define WL_PKT_FILTER_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_list_t, filter) ++ ++/* IOVAR "pkt_filter_stats" parameter. Used to retrieve debug statistics. */ ++typedef struct wl_pkt_filter_stats { ++ uint32 num_pkts_matched; /* # filter matches for specified filter id */ ++ uint32 num_pkts_forwarded; /* # packets fwded from dongle to host for all filters */ ++ uint32 num_pkts_discarded; /* # packets discarded by dongle for all filters */ ++} wl_pkt_filter_stats_t; ++ ++/* Sequential Commands ioctl */ ++typedef struct wl_seq_cmd_ioctl { ++ uint32 cmd; /* common ioctl definition */ ++ uint32 len; /* length of user buffer */ ++} wl_seq_cmd_ioctl_t; ++ ++#define WL_SEQ_CMD_ALIGN_BYTES 4 ++ ++/* These are the set of get IOCTLs that should be allowed when using ++ * IOCTL sequence commands. These are issued implicitly by wl.exe each time ++ * it is invoked. We never want to buffer these, or else wl.exe will stop working. ++ */ ++#define WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd) \ ++ (((cmd) == WLC_GET_MAGIC) || \ ++ ((cmd) == WLC_GET_VERSION) || \ ++ ((cmd) == WLC_GET_AP) || \ ++ ((cmd) == WLC_GET_INSTANCE)) ++ ++/* ++ * Packet engine interface ++ */ ++ ++#define WL_PKTENG_PER_TX_START 0x01 ++#define WL_PKTENG_PER_TX_STOP 0x02 ++#define WL_PKTENG_PER_RX_START 0x04 ++#define WL_PKTENG_PER_RX_WITH_ACK_START 0x05 ++#define WL_PKTENG_PER_TX_WITH_ACK_START 0x06 ++#define WL_PKTENG_PER_RX_STOP 0x08 ++#define WL_PKTENG_PER_MASK 0xff ++ ++#define WL_PKTENG_SYNCHRONOUS 0x100 /* synchronous flag */ ++ ++typedef struct wl_pkteng { ++ uint32 flags; ++ uint32 delay; /* Inter-packet delay */ ++ uint32 nframes; /* Number of frames */ ++ uint32 length; /* Packet length */ ++ uint8 seqno; /* Enable/disable sequence no. */ ++ struct ether_addr dest; /* Destination address */ ++ struct ether_addr src; /* Source address */ ++} wl_pkteng_t; ++ ++#define NUM_80211b_RATES 4 ++#define NUM_80211ag_RATES 8 ++#define NUM_80211n_RATES 32 ++#define NUM_80211_RATES (NUM_80211b_RATES+NUM_80211ag_RATES+NUM_80211n_RATES) ++typedef struct wl_pkteng_stats { ++ uint32 lostfrmcnt; /* RX PER test: no of frames lost (skip seqno) */ ++ int32 rssi; /* RSSI */ ++ int32 snr; /* signal to noise ratio */ ++ uint16 rxpktcnt[NUM_80211_RATES+1]; ++} wl_pkteng_stats_t; ++ ++typedef struct wl_sslpnphy_papd_debug_data { ++ uint8 psat_pwr; ++ uint8 psat_indx; ++ uint8 final_idx; ++ uint8 start_idx; ++ int32 min_phase; ++ int32 voltage; ++ int8 temperature; ++} wl_sslpnphy_papd_debug_data_t; ++typedef struct wl_sslpnphy_debug_data { ++ int16 papdcompRe [64]; ++ int16 papdcompIm [64]; ++} wl_sslpnphy_debug_data_t; ++typedef struct wl_sslpnphy_spbdump_data { ++ uint16 tbl_length; ++ int16 spbreal[256]; ++ int16 spbimg[256]; ++} wl_sslpnphy_spbdump_data_t; ++typedef struct wl_sslpnphy_percal_debug_data { ++ uint cur_idx; ++ uint tx_drift; ++ uint8 prev_cal_idx; ++ uint percal_ctr; ++ int nxt_cal_idx; ++ uint force_1idxcal; ++ uint onedxacl_req; ++ int32 last_cal_volt; ++ int8 last_cal_temp; ++ uint vbat_ripple; ++ uint exit_route; ++ int32 volt_winner; ++} wl_sslpnphy_percal_debug_data_t; ++ ++#define WL_WOWL_MAGIC (1 << 0) /* Wakeup on Magic packet */ ++#define WL_WOWL_NET (1 << 1) /* Wakeup on Netpattern */ ++#define WL_WOWL_DIS (1 << 2) /* Wakeup on loss-of-link due to Disassoc/Deauth */ ++#define WL_WOWL_RETR (1 << 3) /* Wakeup on retrograde TSF */ ++#define WL_WOWL_BCN (1 << 4) /* Wakeup on loss of beacon */ ++#define WL_WOWL_TST (1 << 5) /* Wakeup after test */ ++#define WL_WOWL_M1 (1 << 6) /* Wakeup after PTK refresh */ ++#define WL_WOWL_EAPID (1 << 7) /* Wakeup after receipt of EAP-Identity Req */ ++#define WL_WOWL_PME_GPIO (1 << 8) /* Wakeind via PME(0) or GPIO(1) */ ++#define WL_WOWL_NEEDTKIP1 (1 << 9) /* need tkip phase 1 key to be updated by the driver */ ++#define WL_WOWL_GTK_FAILURE (1 << 10) /* enable wakeup if GTK fails */ ++#define WL_WOWL_EXTMAGPAT (1 << 11) /* support extended magic packets */ ++#define WL_WOWL_ARPOFFLOAD (1 << 12) /* support ARP/NS/keepalive offloading */ ++#define WL_WOWL_WPA2 (1 << 13) /* read protocol version for EAPOL frames */ ++#define WL_WOWL_KEYROT (1 << 14) /* If the bit is set, use key rotaton */ ++#define WL_WOWL_BCAST (1 << 15) /* If the bit is set, frm received was bcast frame */ ++ ++#define MAGIC_PKT_MINLEN 102 /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */ ++ ++#define WOWL_PATTEN_TYPE_ARP (1 << 0) /* ARP offload Pattern */ ++#define WOWL_PATTEN_TYPE_NA (1 << 1) /* NA offload Pattern */ ++ ++typedef struct { ++ uint32 masksize; /* Size of the mask in #of bytes */ ++ uint32 offset; /* Offset to start looking for the packet in # of bytes */ ++ uint32 patternoffset; /* Offset of start of pattern in the structure */ ++ uint32 patternsize; /* Size of the pattern itself in #of bytes */ ++ uint32 id; /* id */ ++ uint32 reasonsize; /* Size of the wakeup reason code */ ++ uint32 flags; /* Flags to tell the pattern type and other properties */ ++ /* Mask follows the structure above */ ++ /* Pattern follows the mask is at 'patternoffset' from the start */ ++} wl_wowl_pattern_t; ++ ++typedef struct { ++ uint count; ++ wl_wowl_pattern_t pattern[1]; ++} wl_wowl_pattern_list_t; ++ ++typedef struct { ++ uint8 pci_wakeind; /* Whether PCI PMECSR PMEStatus bit was set */ ++ uint16 ucode_wakeind; /* What wakeup-event indication was set by ucode */ ++} wl_wowl_wakeind_t; ++ ++ ++/* per AC rate control related data structure */ ++typedef struct wl_txrate_class { ++ uint8 init_rate; ++ uint8 min_rate; ++ uint8 max_rate; ++} wl_txrate_class_t; ++ ++ ++#if defined(DSLCPE_DELAY) ++#define WL_DELAYMODE_DEFER 0 /* defer by scheduler's choice, make this driver default */ ++#define WL_DELAYMODE_FORCE 1 /* force, this is driver default */ ++#define WL_DELAYMODE_AUTO 2 /* defer if no sta associated, force if sta associated */ ++#endif ++ ++/* Overlap BSS Scan parameters default, minimum, maximum */ ++#define WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT 20 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_DWELL_MIN 5 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_DWELL_MAX 1000 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT 10 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_DWELL_MIN 10 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_DWELL_MAX 1000 /* unit TU */ ++#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT 300 /* unit Sec */ ++#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN 10 /* unit Sec */ ++#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX 900 /* unit Sec */ ++#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT 5 ++#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN 5 ++#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX 100 ++#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT 200 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN 200 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX 10000 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT 20 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN 20 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX 10000 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT 25 /* unit percent */ ++#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN 0 /* unit percent */ ++#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX 100 /* unit percent */ ++ ++/* structure for Overlap BSS scan arguments */ ++typedef struct wl_obss_scan_arg { ++ int16 passive_dwell; ++ int16 active_dwell; ++ int16 bss_widthscan_interval; ++ int16 passive_total; ++ int16 active_total; ++ int16 chanwidth_transition_delay; ++ int16 activity_threshold; ++} wl_obss_scan_arg_t; ++ ++#define WL_OBSS_SCAN_PARAM_LEN sizeof(wl_obss_scan_arg_t) ++#define WL_MIN_NUM_OBSS_SCAN_ARG 7 /* minimum number of arguments required for OBSS Scan */ ++ ++#define WL_COEX_INFO_MASK 0x07 ++#define WL_COEX_INFO_REQ 0x01 ++#define WL_COEX_40MHZ_INTOLERANT 0x02 ++#define WL_COEX_WIDTH20 0x04 ++ ++#define WLC_RSSI_INVALID 0 /* invalid RSSI value */ ++ ++#define MAX_RSSI_LEVELS 8 ++ ++/* RSSI event notification configuration. */ ++typedef struct wl_rssi_event { ++ uint32 rate_limit_msec; /* # of events posted to application will be limited to ++ * one per specified period (0 to disable rate limit). ++ */ ++ uint8 num_rssi_levels; /* Number of entries in rssi_levels[] below */ ++ int8 rssi_levels[MAX_RSSI_LEVELS]; /* Variable number of RSSI levels. An event ++ * will be posted each time the RSSI of received ++ * beacons/packets crosses a level. ++ */ ++} wl_rssi_event_t; ++ ++typedef struct wl_action_obss_coex_req { ++ uint8 info; ++ uint8 num; ++ uint8 ch_list[1]; ++} wl_action_obss_coex_req_t; ++ ++ ++/* IOVar parameter block for small MAC address array with type indicator */ ++#define WL_IOV_MAC_PARAM_LEN 4 ++ ++#define WL_IOV_PKTQ_LOG_PRECS 16 ++ ++typedef struct { ++ uint32 num_addrs; ++ char addr_type[WL_IOV_MAC_PARAM_LEN]; ++ struct ether_addr ea[WL_IOV_MAC_PARAM_LEN]; ++} wl_iov_mac_params_t; ++ ++ ++/* Parameter block for PKTQ_LOG statistics */ ++typedef struct { ++ uint32 requested; /* packets requested to be stored */ ++ uint32 stored; /* packets stored */ ++ uint32 saved; /* packets saved, ++ because a lowest priority queue has given away one packet ++ */ ++ uint32 selfsaved; /* packets saved, ++ because an older packet from the same queue has been dropped ++ */ ++ uint32 full_dropped; /* packets dropped, ++ because pktq is full with higher precedence packets ++ */ ++ uint32 dropped; /* packets dropped because pktq per that precedence is full */ ++ uint32 sacrificed; /* packets dropped, ++ in order to save one from a queue of a highest priority ++ */ ++ uint32 busy; /* packets droped because of hardware/transmission error */ ++ uint32 retry; /* packets re-sent because they were not received */ ++ uint32 ps_retry; /* packets retried again prior to moving power save mode */ ++ uint32 retry_drop; /* packets finally dropped after retry limit */ ++ uint32 max_avail; /* the high-water mark of the queue capacity for packets - ++ goes to zero as queue fills ++ */ ++ uint32 max_used; /* the high-water mark of the queue utilisation for packets - ++ increases with use ('inverse' of max_avail) ++ */ ++ uint32 queue_capacity; /* the maximum capacity of the queue */ ++} pktq_log_counters_v01_t; ++ ++#define sacrified sacrificed ++ ++typedef struct { ++ uint8 num_prec[WL_IOV_MAC_PARAM_LEN]; ++ pktq_log_counters_v01_t counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS]; ++ char headings[1]; ++} pktq_log_format_v01_t; ++ ++ ++typedef struct { ++ uint32 version; ++ wl_iov_mac_params_t params; ++ union { ++ pktq_log_format_v01_t v01; ++ } pktq_log; ++} wl_iov_pktq_log_t; ++ ++ ++/* **** EXTLOG **** */ ++#define EXTLOG_CUR_VER 0x0100 ++ ++#define MAX_ARGSTR_LEN 18 /* At least big enough for storing ETHER_ADDR_STR_LEN */ ++ ++/* log modules (bitmap) */ ++#define LOG_MODULE_COMMON 0x0001 ++#define LOG_MODULE_ASSOC 0x0002 ++#define LOG_MODULE_EVENT 0x0004 ++#define LOG_MODULE_MAX 3 /* Update when adding module */ ++ ++/* log levels */ ++#define WL_LOG_LEVEL_DISABLE 0 ++#define WL_LOG_LEVEL_ERR 1 ++#define WL_LOG_LEVEL_WARN 2 ++#define WL_LOG_LEVEL_INFO 3 ++#define WL_LOG_LEVEL_MAX WL_LOG_LEVEL_INFO /* Update when adding level */ ++ ++/* flag */ ++#define LOG_FLAG_EVENT 1 ++ ++/* log arg_type */ ++#define LOG_ARGTYPE_NULL 0 ++#define LOG_ARGTYPE_STR 1 /* %s */ ++#define LOG_ARGTYPE_INT 2 /* %d */ ++#define LOG_ARGTYPE_INT_STR 3 /* %d...%s */ ++#define LOG_ARGTYPE_STR_INT 4 /* %s...%d */ ++ ++typedef struct wlc_extlog_cfg { ++ int max_number; ++ uint16 module; /* bitmap */ ++ uint8 level; ++ uint8 flag; ++ uint16 version; ++} wlc_extlog_cfg_t; ++ ++typedef struct log_record { ++ uint32 time; ++ uint16 module; ++ uint16 id; ++ uint8 level; ++ uint8 sub_unit; ++ uint8 seq_num; ++ int32 arg; ++ char str[MAX_ARGSTR_LEN]; ++} log_record_t; ++ ++typedef struct wlc_extlog_req { ++ uint32 from_last; ++ uint32 num; ++} wlc_extlog_req_t; ++ ++typedef struct wlc_extlog_results { ++ uint16 version; ++ uint16 record_len; ++ uint32 num; ++ log_record_t logs[1]; ++} wlc_extlog_results_t; ++ ++typedef struct log_idstr { ++ uint16 id; ++ uint16 flag; ++ uint8 arg_type; ++ const char *fmt_str; ++} log_idstr_t; ++ ++#define FMTSTRF_USER 1 ++ ++/* flat ID definitions ++ * New definitions HAVE TO BE ADDED at the end of the table. Otherwise, it will ++ * affect backward compatibility with pre-existing apps ++ */ ++typedef enum { ++ FMTSTR_DRIVER_UP_ID = 0, ++ FMTSTR_DRIVER_DOWN_ID = 1, ++ FMTSTR_SUSPEND_MAC_FAIL_ID = 2, ++ FMTSTR_NO_PROGRESS_ID = 3, ++ FMTSTR_RFDISABLE_ID = 4, ++ FMTSTR_REG_PRINT_ID = 5, ++ FMTSTR_EXPTIME_ID = 6, ++ FMTSTR_JOIN_START_ID = 7, ++ FMTSTR_JOIN_COMPLETE_ID = 8, ++ FMTSTR_NO_NETWORKS_ID = 9, ++ FMTSTR_SECURITY_MISMATCH_ID = 10, ++ FMTSTR_RATE_MISMATCH_ID = 11, ++ FMTSTR_AP_PRUNED_ID = 12, ++ FMTSTR_KEY_INSERTED_ID = 13, ++ FMTSTR_DEAUTH_ID = 14, ++ FMTSTR_DISASSOC_ID = 15, ++ FMTSTR_LINK_UP_ID = 16, ++ FMTSTR_LINK_DOWN_ID = 17, ++ FMTSTR_RADIO_HW_OFF_ID = 18, ++ FMTSTR_RADIO_HW_ON_ID = 19, ++ FMTSTR_EVENT_DESC_ID = 20, ++ FMTSTR_PNP_SET_POWER_ID = 21, ++ FMTSTR_RADIO_SW_OFF_ID = 22, ++ FMTSTR_RADIO_SW_ON_ID = 23, ++ FMTSTR_PWD_MISMATCH_ID = 24, ++ FMTSTR_FATAL_ERROR_ID = 25, ++ FMTSTR_AUTH_FAIL_ID = 26, ++ FMTSTR_ASSOC_FAIL_ID = 27, ++ FMTSTR_IBSS_FAIL_ID = 28, ++ FMTSTR_EXTAP_FAIL_ID = 29, ++ FMTSTR_MAX_ID ++} log_fmtstr_id_t; ++ ++#ifdef DONGLEOVERLAYS ++typedef struct { ++ uint32 flags_idx; /* lower 8 bits: overlay index; upper 24 bits: flags */ ++ uint32 offset; /* offset into overlay region to write code */ ++ uint32 len; /* overlay code len */ ++ /* overlay code follows this struct */ ++} wl_ioctl_overlay_t; ++ ++#define OVERLAY_IDX_MASK 0x000000ff ++#define OVERLAY_IDX_SHIFT 0 ++#define OVERLAY_FLAGS_MASK 0xffffff00 ++#define OVERLAY_FLAGS_SHIFT 8 ++/* overlay written to device memory immediately after loading the base image */ ++#define OVERLAY_FLAG_POSTLOAD 0x100 ++/* defer overlay download until the device responds w/WLC_E_OVL_DOWNLOAD event */ ++#define OVERLAY_FLAG_DEFER_DL 0x200 ++/* overlay downloaded prior to the host going to sleep */ ++#define OVERLAY_FLAG_PRESLEEP 0x400 ++ ++#define OVERLAY_DOWNLOAD_CHUNKSIZE 1024 ++#endif /* DONGLEOVERLAYS */ ++ ++/* no default structure packing */ ++#include ++ ++/* require strict packing */ ++#include ++/* Structures and constants used for "vndr_ie" IOVar interface */ ++#define VNDR_IE_CMD_LEN 4 /* length of the set command string: ++ * "add", "del" (+ NUL) ++ */ ++ ++/* 802.11 Mgmt Packet flags */ ++#define VNDR_IE_BEACON_FLAG 0x1 ++#define VNDR_IE_PRBRSP_FLAG 0x2 ++#define VNDR_IE_ASSOCRSP_FLAG 0x4 ++#define VNDR_IE_AUTHRSP_FLAG 0x8 ++#define VNDR_IE_PRBREQ_FLAG 0x10 ++#define VNDR_IE_ASSOCREQ_FLAG 0x20 ++#define VNDR_IE_IWAPID_FLAG 0x40 /* vendor IE in IW advertisement protocol ID field */ ++#define VNDR_IE_CUSTOM_FLAG 0x100 /* allow custom IE id */ ++ ++#define VNDR_IE_INFO_HDR_LEN (sizeof(uint32)) ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ ++ vndr_ie_t vndr_ie_data; /* vendor IE data */ ++} BWL_POST_PACKED_STRUCT vndr_ie_info_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ int iecount; /* number of entries in the vndr_ie_list[] array */ ++ vndr_ie_info_t vndr_ie_list[1]; /* variable size list of vndr_ie_info_t structs */ ++} BWL_POST_PACKED_STRUCT vndr_ie_buf_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ char cmd[VNDR_IE_CMD_LEN]; /* vndr_ie IOVar set command : "add", "del" + NUL */ ++ vndr_ie_buf_t vndr_ie_buffer; /* buffer containing Vendor IE list information */ ++} BWL_POST_PACKED_STRUCT vndr_ie_setbuf_t; ++ ++/* tag_ID/length/value_buffer tuple */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 id; ++ uint8 len; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT tlv_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ ++ tlv_t ie_data; /* IE data */ ++} BWL_POST_PACKED_STRUCT ie_info_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ int iecount; /* number of entries in the ie_list[] array */ ++ ie_info_t ie_list[1]; /* variable size list of ie_info_t structs */ ++} BWL_POST_PACKED_STRUCT ie_buf_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ char cmd[VNDR_IE_CMD_LEN]; /* ie IOVar set command : "add" + NUL */ ++ ie_buf_t ie_buffer; /* buffer containing IE list information */ ++} BWL_POST_PACKED_STRUCT ie_setbuf_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ ++ uint8 id; /* IE type */ ++} BWL_POST_PACKED_STRUCT ie_getbuf_t; ++ ++/* structures used to define format of wps ie data from probe requests */ ++/* passed up to applications via iovar "prbreq_wpsie" */ ++typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_hdr { ++ struct ether_addr staAddr; ++ uint16 ieLen; ++} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_hdr_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_data { ++ sta_prbreq_wps_ie_hdr_t hdr; ++ uint8 ieData[1]; ++} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_data_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_list { ++ uint32 totLen; ++ uint8 ieDataList[1]; ++} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_list_t; ++ ++ ++#ifdef WLMEDIA_TXFAILEVENT ++typedef BWL_PRE_PACKED_STRUCT struct { ++ char dest[ETHER_ADDR_LEN]; /* destination MAC */ ++ uint8 prio; /* Packet Priority */ ++ uint8 flags; /* Flags */ ++ uint32 tsf_l; /* TSF timer low */ ++ uint32 tsf_h; /* TSF timer high */ ++ uint16 rates; /* Main Rates */ ++ uint16 txstatus; /* TX Status */ ++} BWL_POST_PACKED_STRUCT txfailinfo_t; ++#endif /* WLMEDIA_TXFAILEVENT */ ++ ++/* no strict structure packing */ ++#include ++ ++/* Global ASSERT Logging */ ++#define ASSERTLOG_CUR_VER 0x0100 ++#define MAX_ASSRTSTR_LEN 64 ++ ++typedef struct assert_record { ++ uint32 time; ++ uint8 seq_num; ++ char str[MAX_ASSRTSTR_LEN]; ++} assert_record_t; ++ ++typedef struct assertlog_results { ++ uint16 version; ++ uint16 record_len; ++ uint32 num; ++ assert_record_t logs[1]; ++} assertlog_results_t; ++ ++#define LOGRRC_FIX_LEN 8 ++#define IOBUF_ALLOWED_NUM_OF_LOGREC(type, len) ((len - LOGRRC_FIX_LEN)/sizeof(type)) ++ ++ ++/* channel interference measurement (chanim) related defines */ ++ ++/* chanim mode */ ++#define CHANIM_DISABLE 0 /* disabled */ ++#define CHANIM_DETECT 1 /* detection only */ ++#define CHANIM_EXT 2 /* external state machine */ ++#define CHANIM_ACT 3 /* full internal state machine, detect + act */ ++#define CHANIM_MODE_MAX 4 ++ ++/* define for apcs reason code */ ++#define APCS_INIT 0 ++#define APCS_IOCTL 1 ++#define APCS_CHANIM 2 ++#define APCS_CSTIMER 3 ++#define APCS_BTA 4 ++ ++/* number of ACS record entries */ ++#define CHANIM_ACS_RECORD 10 ++ ++/* CHANIM */ ++#define CCASTATS_TXDUR 0 ++#define CCASTATS_INBSS 1 ++#define CCASTATS_OBSS 2 ++#define CCASTATS_NOCTG 3 ++#define CCASTATS_NOPKT 4 ++#define CCASTATS_DOZE 5 ++#define CCASTATS_TXOP 6 ++#define CCASTATS_GDTXDUR 7 ++#define CCASTATS_BDTXDUR 8 ++#define CCASTATS_MAX 9 ++ ++/* chanim acs record */ ++typedef struct { ++ bool valid; ++ uint8 trigger; ++ chanspec_t selected_chspc; ++ int8 bgnoise; ++ uint32 glitch_cnt; ++ uint8 ccastats; ++ uint timestamp; ++} chanim_acs_record_t; ++ ++typedef struct { ++ chanim_acs_record_t acs_record[CHANIM_ACS_RECORD]; ++ uint8 count; ++ uint timestamp; ++} wl_acs_record_t; ++ ++typedef struct chanim_stats { ++ uint32 glitchcnt; /* normalized as per second count */ ++ uint32 badplcp; /* normalized as per second count */ ++ uint8 ccastats[CCASTATS_MAX]; /* normalized as 0-255 */ ++ int8 bgnoise; /* background noise level (in dBm) */ ++ chanspec_t chanspec; ++ uint32 timestamp; ++} chanim_stats_t; ++ ++#define WL_CHANIM_STATS_VERSION 1 ++#define WL_CHANIM_COUNT_ALL 0xff ++#define WL_CHANIM_COUNT_ONE 0x1 ++ ++typedef struct { ++ uint32 buflen; ++ uint32 version; ++ uint32 count; ++ chanim_stats_t stats[1]; ++} wl_chanim_stats_t; ++ ++#define WL_CHANIM_STATS_FIXED_LEN OFFSETOF(wl_chanim_stats_t, stats) ++ ++/* Noise measurement metrics. */ ++#define NOISE_MEASURE_KNOISE 0x1 ++ ++/* scb probe parameter */ ++typedef struct { ++ uint32 scb_timeout; ++ uint32 scb_activity_time; ++ uint32 scb_max_probe; ++} wl_scb_probe_t; ++ ++/* ap tpc modes */ ++#define AP_TPC_OFF 0 ++#define AP_TPC_BSS_PWR 1 /* BSS power control */ ++#define AP_TPC_AP_PWR 2 /* AP power control */ ++#define AP_TPC_AP_BSS_PWR 3 /* Both AP and BSS power control */ ++#define AP_TPC_MAX_LINK_MARGIN 127 ++ ++/* structure/defines for selective mgmt frame (smf) stats support */ ++ ++#define SMFS_VERSION 1 ++/* selected mgmt frame (smf) stats element */ ++typedef struct wl_smfs_elem { ++ uint32 count; ++ uint16 code; /* SC or RC code */ ++} wl_smfs_elem_t; ++ ++typedef struct wl_smf_stats { ++ uint32 version; ++ uint16 length; /* reserved for future usage */ ++ uint8 type; ++ uint8 codetype; ++ uint32 ignored_cnt; ++ uint32 malformed_cnt; ++ uint32 count_total; /* count included the interested group */ ++ wl_smfs_elem_t elem[1]; ++} wl_smf_stats_t; ++ ++#define WL_SMFSTATS_FIXED_LEN OFFSETOF(wl_smf_stats_t, elem); ++ ++enum { ++ SMFS_CODETYPE_SC, ++ SMFS_CODETYPE_RC ++}; ++ ++/* reuse two number in the sc/rc space */ ++#define SMFS_CODE_MALFORMED 0xFFFE ++#define SMFS_CODE_IGNORED 0xFFFD ++ ++typedef enum smfs_type { ++ SMFS_TYPE_AUTH, ++ SMFS_TYPE_ASSOC, ++ SMFS_TYPE_REASSOC, ++ SMFS_TYPE_DISASSOC_TX, ++ SMFS_TYPE_DISASSOC_RX, ++ SMFS_TYPE_DEAUTH_TX, ++ SMFS_TYPE_DEAUTH_RX, ++ SMFS_TYPE_MAX ++} smfs_type_t; ++ ++#ifdef PHYMON ++ ++#define PHYMON_VERSION 1 ++ ++typedef struct wl_phycal_core_state { ++ /* Tx IQ/LO calibration coeffs */ ++ int16 tx_iqlocal_a; ++ int16 tx_iqlocal_b; ++ int8 tx_iqlocal_ci; ++ int8 tx_iqlocal_cq; ++ int8 tx_iqlocal_di; ++ int8 tx_iqlocal_dq; ++ int8 tx_iqlocal_ei; ++ int8 tx_iqlocal_eq; ++ int8 tx_iqlocal_fi; ++ int8 tx_iqlocal_fq; ++ ++ /* Rx IQ calibration coeffs */ ++ int16 rx_iqcal_a; ++ int16 rx_iqcal_b; ++ ++ uint8 tx_iqlocal_pwridx; /* Tx Power Index for Tx IQ/LO calibration */ ++ uint32 papd_epsilon_table[64]; /* PAPD epsilon table */ ++ int16 papd_epsilon_offset; /* PAPD epsilon offset */ ++ uint8 curr_tx_pwrindex; /* Tx power index */ ++ int8 idle_tssi; /* Idle TSSI */ ++ int8 est_tx_pwr; /* Estimated Tx Power (dB) */ ++ int8 est_rx_pwr; /* Estimated Rx Power (dB) from RSSI */ ++ uint16 rx_gaininfo; /* Rx gain applied on last Rx pkt */ ++ uint16 init_gaincode; /* initgain required for ACI */ ++ int8 estirr_tx; ++ int8 estirr_rx; ++ ++} wl_phycal_core_state_t; ++ ++typedef struct wl_phycal_state { ++ int version; ++ int8 num_phy_cores; /* number of cores */ ++ int8 curr_temperature; /* on-chip temperature sensor reading */ ++ chanspec_t chspec; /* channspec for this state */ ++ bool aci_state; /* ACI state: ON/OFF */ ++ uint16 crsminpower; /* crsminpower required for ACI */ ++ uint16 crsminpowerl; /* crsminpowerl required for ACI */ ++ uint16 crsminpoweru; /* crsminpoweru required for ACI */ ++ wl_phycal_core_state_t phycal_core[1]; ++} wl_phycal_state_t; ++ ++#define WL_PHYCAL_STAT_FIXED_LEN OFFSETOF(wl_phycal_state_t, phycal_core) ++#endif /* PHYMON */ ++ ++/* discovery state */ ++typedef struct wl_p2p_disc_st { ++ uint8 state; /* see state */ ++ chanspec_t chspec; /* valid in listen state */ ++ uint16 dwell; /* valid in listen state, in ms */ ++} wl_p2p_disc_st_t; ++ ++/* state */ ++#define WL_P2P_DISC_ST_SCAN 0 ++#define WL_P2P_DISC_ST_LISTEN 1 ++#define WL_P2P_DISC_ST_SEARCH 2 ++ ++/* scan request */ ++typedef struct wl_p2p_scan { ++ uint8 type; /* 'S' for WLC_SCAN, 'E' for "escan" */ ++ uint8 reserved[3]; ++ /* scan or escan parms... */ ++} wl_p2p_scan_t; ++ ++/* i/f request */ ++typedef struct wl_p2p_if { ++ struct ether_addr addr; ++ uint8 type; /* see i/f type */ ++ chanspec_t chspec; /* for p2p_ifadd GO */ ++} wl_p2p_if_t; ++ ++/* i/f type */ ++#define WL_P2P_IF_CLIENT 0 ++#define WL_P2P_IF_GO 1 ++#define WL_P2P_IF_DYNBCN_GO 2 ++#define WL_P2P_IF_DEV 3 ++ ++/* i/f query */ ++typedef struct wl_p2p_ifq { ++ uint bsscfgidx; ++ char ifname[BCM_MSG_IFNAME_MAX]; ++} wl_p2p_ifq_t; ++ ++/* OppPS & CTWindow */ ++typedef struct wl_p2p_ops { ++ uint8 ops; /* 0: disable 1: enable */ ++ uint8 ctw; /* >= 10 */ ++} wl_p2p_ops_t; ++ ++/* absence and presence request */ ++typedef struct wl_p2p_sched_desc { ++ uint32 start; ++ uint32 interval; ++ uint32 duration; ++ uint32 count; /* see count */ ++} wl_p2p_sched_desc_t; ++ ++/* count */ ++#define WL_P2P_SCHED_RSVD 0 ++#define WL_P2P_SCHED_REPEAT 255 /* anything > 255 will be treated as 255 */ ++ ++typedef struct wl_p2p_sched { ++ uint8 type; /* see schedule type */ ++ uint8 action; /* see schedule action */ ++ uint8 option; /* see schedule option */ ++ wl_p2p_sched_desc_t desc[1]; ++} wl_p2p_sched_t; ++#define WL_P2P_SCHED_FIXED_LEN 3 ++ ++/* schedule type */ ++#define WL_P2P_SCHED_TYPE_ABS 0 /* Scheduled Absence */ ++#define WL_P2P_SCHED_TYPE_REQ_ABS 1 /* Requested Absence */ ++ ++/* schedule action during absence periods (for WL_P2P_SCHED_ABS type) */ ++#define WL_P2P_SCHED_ACTION_NONE 0 /* no action */ ++#define WL_P2P_SCHED_ACTION_DOZE 1 /* doze */ ++/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */ ++#define WL_P2P_SCHED_ACTION_GOOFF 2 /* turn off GO beacon/prbrsp functions */ ++/* schedule option - WL_P2P_SCHED_TYPE_XXX */ ++#define WL_P2P_SCHED_ACTION_RESET 255 /* reset */ ++ ++/* schedule option - WL_P2P_SCHED_TYPE_ABS */ ++#define WL_P2P_SCHED_OPTION_NORMAL 0 /* normal start/interval/duration/count */ ++#define WL_P2P_SCHED_OPTION_BCNPCT 1 /* percentage of beacon interval */ ++/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */ ++#define WL_P2P_SCHED_OPTION_TSFOFS 2 /* normal start/internal/duration/count with ++ * start being an offset of the 'current' TSF ++ */ ++ ++/* feature flags */ ++#define WL_P2P_FEAT_GO_CSA (1 << 0) /* GO moves with the STA using CSA method */ ++#define WL_P2P_FEAT_GO_NOLEGACY (1 << 1) /* GO does not probe respond to non-p2p probe ++ * requests ++ */ ++#define WL_P2P_FEAT_RESTRICT_DEV_RESP (1 << 2) /* Restrict p2p dev interface from responding */ ++ ++/* RFAWARE def */ ++#define BCM_ACTION_RFAWARE 0x77 ++#define BCM_ACTION_RFAWARE_DCS 0x01 ++ ++/* DCS reason code define */ ++#define BCM_DCS_IOVAR 0x1 ++#define BCM_DCS_UNKNOWN 0xFF ++ ++typedef struct wl_bcmdcs_data { ++ uint reason; ++ chanspec_t chspec; ++} wl_bcmdcs_data_t; ++ ++/* n-mode support capability */ ++/* 2x2 includes both 1x1 & 2x2 devices ++ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and ++ * control it independently ++ */ ++#define WL_11N_2x2 1 ++#define WL_11N_3x3 3 ++#define WL_11N_4x4 4 ++ ++/* define 11n feature disable flags */ ++#define WLFEATURE_DISABLE_11N 0x00000001 ++#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002 ++#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004 ++#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008 ++#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010 ++#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020 ++#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040 ++#define WLFEATURE_DISABLE_11N_GF 0x00000080 ++ ++/* Proxy STA modes */ ++#define PSTA_MODE_DISABLED 0 ++#define PSTA_MODE_PROXY 1 ++#define PSTA_MODE_REPEATER 2 ++ ++ ++/* NAT configuration */ ++typedef struct { ++ uint32 ipaddr; /* interface ip address */ ++ uint32 ipaddr_mask; /* interface ip address mask */ ++ uint32 ipaddr_gateway; /* gateway ip address */ ++ uint8 mac_gateway[6]; /* gateway mac address */ ++ uint32 ipaddr_dns; /* DNS server ip address, valid only for public if */ ++ uint8 mac_dns[6]; /* DNS server mac address, valid only for public if */ ++ uint8 GUID[38]; /* interface GUID */ ++} nat_if_info_t; ++ ++typedef struct { ++ uint op; /* operation code */ ++ bool pub_if; /* set for public if, clear for private if */ ++ nat_if_info_t if_info; /* interface info */ ++} nat_cfg_t; ++ ++/* op code in nat_cfg */ ++#define NAT_OP_ENABLE 1 /* enable NAT on given interface */ ++#define NAT_OP_DISABLE 2 /* disable NAT on given interface */ ++#define NAT_OP_DISABLE_ALL 3 /* disable NAT on all interfaces */ ++ ++/* NAT state */ ++#define NAT_STATE_ENABLED 1 /* NAT is enabled */ ++#define NAT_STATE_DISABLED 2 /* NAT is disabled */ ++ ++typedef struct { ++ int state; /* NAT state returned */ ++} nat_state_t; ++ ++#ifdef PROP_TXSTATUS ++/* Bit definitions for tlv iovar */ ++/* ++ * enable RSSI signals: ++ * WLFC_CTL_TYPE_RSSI ++ */ ++#define WLFC_FLAGS_RSSI_SIGNALS 1 ++ ++/* enable (if/mac_open, if/mac_close,, mac_add, mac_del) signals: ++ * ++ * WLFC_CTL_TYPE_MAC_OPEN ++ * WLFC_CTL_TYPE_MAC_CLOSE ++ * ++ * WLFC_CTL_TYPE_INTERFACE_OPEN ++ * WLFC_CTL_TYPE_INTERFACE_CLOSE ++ * ++ * WLFC_CTL_TYPE_MACDESC_ADD ++ * WLFC_CTL_TYPE_MACDESC_DEL ++ * ++ */ ++#define WLFC_FLAGS_XONXOFF_SIGNALS 2 ++ ++/* enable (status, fifo_credit, mac_credit) signals ++ * WLFC_CTL_TYPE_MAC_REQUEST_CREDIT ++ * WLFC_CTL_TYPE_TXSTATUS ++ * WLFC_CTL_TYPE_FIFO_CREDITBACK ++ */ ++#define WLFC_FLAGS_CREDIT_STATUS_SIGNALS 4 ++ ++#define WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE 8 ++#define WLFC_FLAGS_PSQ_GENERATIONFSM_ENABLE 16 ++#define WLFC_FLAGS_PSQ_ZERO_BUFFER_ENABLE 32 ++#endif /* PROP_TXSTATUS */ ++ ++#define BTA_STATE_LOG_SZ 64 ++ ++/* BTAMP Statemachine states */ ++enum { ++ HCIReset = 1, ++ HCIReadLocalAMPInfo, ++ HCIReadLocalAMPASSOC, ++ HCIWriteRemoteAMPASSOC, ++ HCICreatePhysicalLink, ++ HCIAcceptPhysicalLinkRequest, ++ HCIDisconnectPhysicalLink, ++ HCICreateLogicalLink, ++ HCIAcceptLogicalLink, ++ HCIDisconnectLogicalLink, ++ HCILogicalLinkCancel, ++ HCIAmpStateChange, ++ HCIWriteLogicalLinkAcceptTimeout ++}; ++ ++typedef struct flush_txfifo { ++ uint32 txfifobmp; ++ uint32 hwtxfifoflush; ++ struct ether_addr ea; ++} flush_txfifo_t; ++ ++#define CHANNEL_5G_LOW_START 36 /* 5G low (36..48) CDD enable/disable bit mask */ ++#define CHANNEL_5G_MID_START 52 /* 5G mid (52..64) CDD enable/disable bit mask */ ++#define CHANNEL_5G_HIGH_START 100 /* 5G high (100..140) CDD enable/disable bit mask */ ++#define CHANNEL_5G_UPPER_START 149 /* 5G upper (149..161) CDD enable/disable bit mask */ ++ ++enum { ++ SPATIAL_MODE_2G_IDX = 0, ++ SPATIAL_MODE_5G_LOW_IDX, ++ SPATIAL_MODE_5G_MID_IDX, ++ SPATIAL_MODE_5G_HIGH_IDX, ++ SPATIAL_MODE_5G_UPPER_IDX, ++ SPATIAL_MODE_MAX_IDX ++}; ++ ++/* IOVAR "mempool" parameter. Used to retrieve a list of memory pool statistics. */ ++typedef struct wl_mempool_stats { ++ int num; /* Number of memory pools */ ++ bcm_mp_stats_t s[1]; /* Variable array of memory pool stats. */ ++} wl_mempool_stats_t; ++ ++/* Network Offload Engine */ ++#define NWOE_OL_ENABLE 0x00000001 ++ ++typedef struct { ++ uint32 ipaddr; ++ uint32 ipaddr_netmask; ++ uint32 ipaddr_gateway; ++} nwoe_ifconfig_t; ++ ++/* ++ * Traffic management structures/defines. ++ */ ++ ++/* Traffic management bandwidth parameters */ ++#define TRF_MGMT_MAX_PRIORITIES 3 ++ ++#define TRF_MGMT_FLAG_ADD_DSCP 0x0001 /* Add DSCP to IP TOS field */ ++#define TRF_MGMT_FLAG_DISABLE_SHAPING 0x0002 /* Only support traffic clasification */ ++ ++ ++/* Traffic management priority classes */ ++typedef enum trf_mgmt_priority_class { ++ trf_mgmt_priority_low = 0, /* Maps to 802.1p BK */ ++ trf_mgmt_priority_medium = 1, /* Maps to 802.1p BE */ ++ trf_mgmt_priority_high = 2, /* Maps to 802.1p VI */ ++ trf_mgmt_priority_invalid = (trf_mgmt_priority_high + 1) ++} trf_mgmt_priority_class_t; ++ ++/* Traffic management configuration parameters */ ++typedef struct trf_mgmt_config { ++ uint32 trf_mgmt_enabled; /* 0 - disabled, 1 - enabled */ ++ uint32 flags; /* See TRF_MGMT_FLAG_xxx defines */ ++ uint32 host_ip_addr; ++ uint32 host_subnet_mask; ++ uint32 downlink_bandwidth; /* In units of kbps */ ++ uint32 uplink_bandwidth; /* In units of kbps */ ++ uint32 min_tx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; ++ uint32 min_rx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; ++} trf_mgmt_config_t; ++ ++/* Traffic management filter */ ++typedef struct trf_mgmt_filter { ++ uint32 dst_ip_addr; /* His IP address */ ++ uint16 dst_port; /* His L4 port */ ++ uint16 src_port; /* My L4 port */ ++ uint16 prot; /* L4 protocol (only TCP or UDP protocols) */ ++ uint16 flags; /* TBD. For now, this must be zero. */ ++ trf_mgmt_priority_class_t priority; /* 802.1p priority for filtered packets */ ++} trf_mgmt_filter_t; ++ ++/* Traffic management filter list (variable length) */ ++typedef struct trf_mgmt_filter_list { ++ uint32 num_filters; ++ trf_mgmt_filter_t filter[1]; ++} trf_mgmt_filter_list_t; ++ ++/* Traffic management shaping info */ ++typedef struct trf_mgmt_shaping_info { ++ uint32 max_bps; /* Max bytes consumed or produced per second */ ++ uint32 max_bytes_per_sampling_period; /* Max bytes consumed or produced per sample */ ++ uint32 shaping_delay_threshold; /* Theshold for starting traffic delays */ ++ uint32 num_bytes_produced_per_sec; /* Bytes produced over the sampling period */ ++ uint32 num_bytes_consumed_per_sec; /* Bytes consumed over the sampling period */ ++} trf_mgmt_shaping_info_t; ++ ++/* Traffic management shaping info array */ ++typedef struct trf_mgmt_shaping_info_array { ++ trf_mgmt_shaping_info_t tx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES]; ++ trf_mgmt_shaping_info_t rx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES]; ++} trf_mgmt_shaping_info_array_t; ++ ++ ++/* Traffic management statistical counters */ ++typedef struct trf_mgmt_stats { ++ uint32 num_processed_packets; /* Number of packets processed */ ++ uint32 num_processed_bytes; /* Number of bytes processed */ ++ uint32 num_queued_packets; /* Number of packets in queue */ ++ uint32 num_queued_bytes; /* Number of bytes in queue */ ++ uint32 num_discarded_packets; /* Number of packets discarded from queue */ ++} trf_mgmt_stats_t; ++ ++/* Traffic management statisics array */ ++typedef struct trf_mgmt_stats_array { ++ trf_mgmt_stats_t tx_queue_stats[TRF_MGMT_MAX_PRIORITIES]; ++ trf_mgmt_stats_t rx_queue_stats[TRF_MGMT_MAX_PRIORITIES]; ++} trf_mgmt_stats_array_t; ++ ++#endif /* _wlioctl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/aiutils.c b/drivers/bcmdrivers/gmac/src/shared/aiutils.c +new file mode 100755 +index 0000000..eed6a11 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/aiutils.c +@@ -0,0 +1,1263 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc utility routines for accessing chip-specific features ++ * of the SiliconBackplane-based Broadcom chips. ++ * ++ * $Id: aiutils.c 327582 2012-04-14 05:02:37Z $ ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "siutils_priv.h" ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#include "hx4_erom.h" ++#elif defined(CONFIG_MACH_HR2) ++#include "hr2_erom.h" ++#elif defined(CONFIG_MACH_NSP) ++#include "nsp_erom.h" ++#elif defined(CONFIG_MACH_KT2) ++#include "kt2_erom.h" ++#endif ++ ++#include ++ ++#define BCM47162_DMP() ((CHIPID(sih->chip) == BCM47162_CHIP_ID) && \ ++ (CHIPREV(sih->chiprev) == 0) && \ ++ (sii->coreid[sii->curidx] == MIPS74K_CORE_ID)) ++ ++#define BCM5357_DMP() (((CHIPID(sih->chip) == BCM5357_CHIP_ID) || \ ++ (CHIPID(sih->chip) == BCM4749_CHIP_ID)) && \ ++ (sih->chippkg == BCM5357_PKG_ID) && \ ++ (sii->coreid[sii->curidx] == USB20H_CORE_ID)) ++ ++/* EROM parsing */ ++ ++static uint32 ++get_erom_ent(si_t *sih, uint32 **eromptr, uint32 mask, uint32 match) ++{ ++ uint32 ent; ++ uint inv = 0, nom = 0; ++ ++ while (TRUE) { ++#if defined(CONFIG_MACH_NS) ++ ent = R_REG(si_osh(sih), *eromptr); ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ ent = **eromptr; ++#elif defined(CONFIG_MACH_HR2) ++ ent = **eromptr; ++#elif defined(CONFIG_MACH_NSP) ++ ent = **eromptr; ++#elif defined(CONFIG_MACH_KT2) ++ ent = **eromptr; ++#endif ++ ++ (*eromptr)++; ++ ++ if (mask == 0) ++ break; ++ ++ if ((ent & ER_VALID) == 0) { ++ inv++; ++ continue; ++ } ++ ++ if (ent == (ER_END | ER_VALID)) ++ break; ++ ++ if ((ent & mask) == match) ++ break; ++ ++ nom++; ++ } ++ ++ SI_VMSG(("%s: Returning ent 0x%08x\n", __FUNCTION__, ent)); ++ if (inv + nom) { ++ SI_VMSG((" after %d invalid and %d non-matching entries\n", inv, nom)); ++ } ++ return ent; ++} ++ ++static uint32 ++get_asd(si_t *sih, uint32 **eromptr, uint sp, uint ad, uint st, uint32 *addrl, uint32 *addrh, ++ uint32 *sizel, uint32 *sizeh) ++{ ++ uint32 asd, sz, szd; ++ ++ asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID); ++ if (((asd & ER_TAG1) != ER_ADD) || ++ (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) || ++ ((asd & AD_ST_MASK) != st)) { ++ /* This is not what we want, "push" it back */ ++ (*eromptr)--; ++ return 0; ++ } ++ *addrl = asd & AD_ADDR_MASK; ++ if (asd & AD_AG32) ++ *addrh = get_erom_ent(sih, eromptr, 0, 0); ++ else ++ *addrh = 0; ++ *sizeh = 0; ++ sz = asd & AD_SZ_MASK; ++ if (sz == AD_SZ_SZD) { ++ szd = get_erom_ent(sih, eromptr, 0, 0); ++ *sizel = szd & SD_SZ_MASK; ++ if (szd & SD_SG32) ++ *sizeh = get_erom_ent(sih, eromptr, 0, 0); ++ } else ++ *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT); ++ ++ SI_VMSG((" SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n", ++ sp, ad, st, *sizeh, *sizel, *addrh, *addrl)); ++ ++ return asd; ++} ++ ++static void ++ai_hwfixup(si_info_t *sii) ++{ ++#ifdef _CFE_ ++ /* Fixup the interrupts in 4716 for i2s core so that ai_flag ++ * works without having to look at the core sinking the ++ * interrupt. We should have done this as the hardware default. ++ * ++ * Future chips should allocate interrupt lines in order (meaning ++ * no line should be skipped), without regard for core index. ++ */ ++ if (BUSTYPE(sii->pub.bustype) == SI_BUS && ++ ((CHIPID(sii->pub.chip) == BCM4716_CHIP_ID) || ++ (CHIPID(sii->pub.chip) == BCM4748_CHIP_ID))) { ++ aidmp_t *i2s, *pcie, *cpu; ++ ++ ASSERT(sii->coreid[3] == MIPS74K_CORE_ID); ++ cpu = REG_MAP(sii->wrapba[3], SI_CORE_SIZE); ++ ASSERT(sii->coreid[5] == PCIE_CORE_ID); ++ pcie = REG_MAP(sii->wrapba[5], SI_CORE_SIZE); ++ ASSERT(sii->coreid[8] == I2S_CORE_ID); ++ i2s = REG_MAP(sii->wrapba[8], SI_CORE_SIZE); ++ if ((R_REG(sii->osh, &cpu->oobselina74) != 0x08060504) || ++ (R_REG(sii->osh, &pcie->oobselina74) != 0x08060504) || ++ (R_REG(sii->osh, &i2s->oobselouta30) != 0x88)) { ++ SI_VMSG(("Unexpected oob values, not fixing i2s interrupt\n")); ++ } else { ++ /* Move i2s interrupt to oob line 7 instead of 8 */ ++ W_REG(sii->osh, &cpu->oobselina74, 0x07060504); ++ W_REG(sii->osh, &pcie->oobselina74, 0x07060504); ++ W_REG(sii->osh, &i2s->oobselouta30, 0x87); ++ SI_VMSG(("Changed i2s interrupt to use oob line 7 instead of 8\n")); ++ } ++ } ++#endif /* _CFE_ */ ++} ++ ++struct _corerev_entry { ++ uint corerev; ++ uint corerev_alias; ++}; ++static struct _corerev_entry bcm4706_corerev_cc[] = { ++ { 0x1f, CC_4706B0_CORE_REV }, ++ { 0, 0 } ++}; ++static struct _corerev_entry bcm4706_corerev_socsram[] = { ++ { 0x05, SOCRAM_4706B0_CORE_REV }, ++ { 0, 0 } ++}; ++static struct _corerev_entry bcm4706_corerev_gmac[] = { ++ { 0x00, GMAC_4706B0_CORE_REV }, ++ { 0, 0 } ++}; ++ ++struct _coreid_entry { ++ uint coreid; ++ uint coreid_alias; ++}; ++static struct _coreid_entry bcm4706_coreid_table[] = { ++ { CC_4706_CORE_ID, CC_CORE_ID }, ++ { SOCRAM_4706_CORE_ID, SOCRAM_CORE_ID }, ++ { GMAC_4706_CORE_ID, GMAC_CORE_ID }, ++ { 0, 0 } ++}; ++ ++static uint ++remap_coreid(si_t *sih, uint coreid) ++{ ++ struct _coreid_entry *coreid_table = NULL; ++ ++ if (CHIPID(sih->chip) == BCM4706_CHIP_ID) ++ coreid_table = &bcm4706_coreid_table[0]; ++ ++ if (coreid_table != NULL) { ++ uint i; ++ ++ for (i = 0; coreid_table[i].coreid; i++) { ++ if (coreid_table[i].coreid == coreid) ++ return coreid_table[i].coreid_alias; ++ } ++ } ++ ++ return coreid; ++} ++ ++static uint ++remap_corerev(si_t *sih, uint corerev) ++{ ++ if (CHIPID(sih->chip) == BCM4706_CHIP_ID) { ++ si_info_t *sii = SI_INFO(sih); ++ uint i, coreid = sii->coreid[sii->curidx]; ++ struct _corerev_entry *corerev_table = NULL; ++ ++ if (coreid == CC_CORE_ID) ++ corerev_table = bcm4706_corerev_cc; ++ else if (coreid == GMAC_CORE_ID) ++ corerev_table = bcm4706_corerev_gmac; ++ else if (coreid == SOCRAM_CORE_ID) ++ corerev_table = bcm4706_corerev_socsram; ++ if (corerev_table != NULL) { ++ for (i = 0; corerev_table[i].corerev_alias; i++) ++ if (corerev_table[i].corerev == corerev) ++ return corerev_table[i].corerev_alias; ++ } ++ } ++ ++ return corerev; ++} ++ ++/* parse the enumeration rom to identify all cores */ ++void ++BCMATTACHFN(ai_scan)(si_t *sih, void *regs, uint devid) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ chipcregs_t *cc = (chipcregs_t *)regs; ++ uint32 erombase, *eromptr, *eromlim; ++ ++ erombase = R_REG(sii->osh, &cc->eromptr); ++ ++ switch (BUSTYPE(sih->bustype)) { ++ case SI_BUS: ++#if defined(CONFIG_MACH_NS) ++ eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE); ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ eromptr = hx4_erom; ++#elif defined(CONFIG_MACH_HR2) ++ eromptr = hr2_erom; ++#elif defined(CONFIG_MACH_NSP) ++ eromptr = nsp_erom; ++#elif defined(CONFIG_MACH_KT2) ++ eromptr = kt2_erom; ++#endif ++ break; ++ ++ case PCI_BUS: ++ /* Set wrappers address */ ++ sii->curwrap = (void *)((uintptr)regs + SI_CORE_SIZE); ++ ++ /* Now point the window at the erom */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, erombase); ++ eromptr = regs; ++ break; ++ ++ ++ case PCMCIA_BUS: ++ default: ++ SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n", sih->bustype)); ++ ASSERT(0); ++ return; ++ } ++ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32)); ++ ++ SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n", ++ regs, erombase, eromptr, eromlim)); ++ while (eromptr < eromlim) { ++ uint32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp; ++ uint32 mpd, asd, addrl, addrh, sizel, sizeh; ++ uint i, j, idx; ++ bool br; ++ ++ br = FALSE; ++ ++ /* Grok a component */ ++ cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI); ++ if (cia == (ER_END | ER_VALID)) { ++ SI_VMSG(("Found END of erom after %d cores\n", sii->numcores)); ++ ai_hwfixup(sii); ++ return; ++ } ++ ++ cib = get_erom_ent(sih, &eromptr, 0, 0); ++ ++ if ((cib & ER_TAG) != ER_CI) { ++ SI_ERROR(("CIA not followed by CIB\n")); ++ goto error; ++ } ++ ++ cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT; ++ mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; ++ crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; ++ nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT; ++ nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT; ++ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; ++ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; ++ ++#ifdef BCMDBG_SI ++ SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, " ++ "nsw = %d, nmp = %d & nsp = %d\n", ++ mfg, cid, crev, eromptr - 1, nmw, nsw, nmp, nsp)); ++#else ++ BCM_REFERENCE(crev); ++#endif ++ ++ if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0)) ++ continue; ++ if ((nmw + nsw == 0)) { ++ /* A component which is not a core */ ++ if (cid == OOB_ROUTER_CORE_ID) { ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, ++ &addrl, &addrh, &sizel, &sizeh); ++ if (asd != 0) { ++ sii->oob_router = addrl; ++ } ++ } ++ if (cid != GMAC_COMMON_4706_CORE_ID) ++ continue; ++ } ++ ++ idx = sii->numcores; ++ ++ sii->cia[idx] = cia; ++ sii->cib[idx] = cib; ++ sii->coreid[idx] = remap_coreid(sih, cid); ++ ++ for (i = 0; i < nmp; i++) { ++ mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); ++ if ((mpd & ER_TAG) != ER_MP) { ++ SI_ERROR(("Not enough MP entries for component 0x%x\n", cid)); ++ goto error; ++ } ++ SI_VMSG((" Master port %d, mp: %d id: %d\n", i, ++ (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT, ++ (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT)); ++ } ++ ++ /* First Slave Address Descriptor should be port 0: ++ * the main register space for the core ++ */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); ++ if (asd == 0) { ++ do { ++ /* Try again to see if it is a bridge */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd != 0) ++ br = TRUE; ++ else { ++ if (br == TRUE) { ++ break; ++ } ++ else if ((addrh != 0) || (sizeh != 0) || ++ (sizel != SI_CORE_SIZE)) { ++ SI_ERROR(("addrh = 0x%x\t sizeh = 0x%x\t size1 =" ++ "0x%x\n", addrh, sizeh, sizel)); ++ SI_ERROR(("First Slave ASD for" ++ "core 0x%04x malformed " ++ "(0x%08x)\n", cid, asd)); ++ goto error; ++ } ++ } ++ } while (1); ++ } ++ sii->coresba[idx] = addrl; ++ sii->coresba_size[idx] = sizel; ++ /* Get any more ASDs in port 0 */ ++ j = 1; ++ do { ++ asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) { ++ sii->coresba2[idx] = addrl; ++ sii->coresba2_size[idx] = sizel; ++ } ++ j++; ++ } while (asd != 0); ++ ++ /* Go through the ASDs for other slave ports */ ++ for (i = 1; i < nsp; i++) { ++ j = 0; ++ do { ++ asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ ++ if (asd == 0) ++ break; ++ j++; ++ } while (1); ++ if (j == 0) { ++ SI_ERROR((" SP %d has no address descriptors\n", i)); ++ goto error; ++ } ++ } ++ ++ /* Now get master wrappers */ ++ for (i = 0; i < nmw; i++) { ++ asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) { ++ SI_ERROR(("Missing descriptor for MW %d\n", i)); ++ goto error; ++ } ++ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { ++ SI_ERROR(("Master wrapper %d is not 4KB\n", i)); ++ goto error; ++ } ++ if (i == 0) ++ sii->wrapba[idx] = addrl; ++ } ++ ++ /* And finally slave wrappers */ ++ for (i = 0; i < nsw; i++) { ++ uint fwp = (nsp == 1) ? 0 : 1; ++ asd = get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) { ++ SI_ERROR(("Missing descriptor for SW %d\n", i)); ++ goto error; ++ } ++ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { ++ SI_ERROR(("Slave wrapper %d is not 4KB\n", i)); ++ goto error; ++ } ++ if ((nmw == 0) && (i == 0)) ++ sii->wrapba[idx] = addrl; ++ } ++ ++ if (CHIPID(sih->chip) == BCM4706_CHIP_ID) { ++ /* Check if it's a low cost package */ ++ i = (R_REG(sii->osh, &cc->chipid) & CID_PKG_MASK) >> CID_PKG_SHIFT; ++ if (i == BCM4706L_PKG_ID) { ++ /* bcm4706L: only one GMAC */ ++ if (cid == GMAC_4706_CORE_ID) { ++ for (j = 0; j < sii->numcores; j++) { ++ if (sii->coreid[j] == GMAC_CORE_ID) ++ break; ++ } ++ if (j != sii->numcores) { ++ /* Found one GMAC already, ignore this one */ ++ continue; ++ } ++ } ++ } ++ } ++ ++ /* Don't record bridges */ ++ if (br) ++ continue; ++ ++ /* Done with core */ ++ sii->numcores++; ++ } ++ ++ SI_ERROR(("Reached end of erom without finding END")); ++ ++error: ++ sii->numcores = 0; ++ return; ++} ++ ++/* This function changes the logical "focus" to the indicated core. ++ * Return the current core's virtual address. ++ */ ++void * ++ai_setcoreidx(si_t *sih, uint coreidx) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ uint32 addr, wrap; ++ void *regs; ++ ++ if (coreidx >= MIN(sii->numcores, SI_MAXCORES)) ++ return (NULL); ++ ++ addr = sii->coresba[coreidx]; ++ wrap = sii->wrapba[coreidx]; ++ ++ /* ++ * If the user has provided an interrupt mask enabled function, ++ * then assert interrupts are disabled before switching the core. ++ */ ++ ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg)); ++ ++ switch (BUSTYPE(sih->bustype)) { ++ case SI_BUS: ++ /* map new one */ ++ if (!sii->regs[coreidx]) { ++ sii->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->regs[coreidx])); ++ } ++ sii->curmap = regs = sii->regs[coreidx]; ++ if (!sii->wrappers[coreidx]) { ++ sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->wrappers[coreidx])); ++ } ++ sii->curwrap = sii->wrappers[coreidx]; ++ break; ++ ++ case PCI_BUS: ++ /* point bar0 window */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, addr); ++ regs = sii->curmap; ++ /* point bar0 2nd 4KB window to the primary wrapper */ ++ if (PCIE_GEN2(sii)) ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_WIN2, 4, wrap); ++ else ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, wrap); ++ break; ++ ++ ++ case PCMCIA_BUS: ++ default: ++ ASSERT(0); ++ regs = NULL; ++ break; ++ } ++ ++ sii->curmap = regs; ++ sii->curidx = coreidx; ++ ++ return regs; ++} ++ ++void ++ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ chipcregs_t *cc = NULL; ++ uint32 erombase, *eromptr, *eromlim; ++ uint i, j, cidx; ++ uint32 cia, cib, nmp, nsp; ++ uint32 asd, addrl, addrh, sizel, sizeh; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ if (sii->coreid[i] == CC_CORE_ID) { ++ cc = (chipcregs_t *)sii->regs[i]; ++ break; ++ } ++ } ++ if (cc == NULL) ++ goto error; ++ ++ erombase = R_REG(sii->osh, &cc->eromptr); ++ eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE); ++ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32)); ++ ++ cidx = sii->curidx; ++ cia = sii->cia[cidx]; ++ cib = sii->cib[cidx]; ++ ++ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; ++ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; ++ ++ /* scan for cores */ ++ while (eromptr < eromlim) { ++ if ((get_erom_ent(sih, &eromptr, ER_TAG, ER_CI) == cia) && ++ (get_erom_ent(sih, &eromptr, 0, 0) == cib)) { ++ break; ++ } ++ } ++ ++ /* skip master ports */ ++ for (i = 0; i < nmp; i++) ++ get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); ++ ++ /* Skip ASDs in port 0 */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); ++ if (asd == 0) { ++ /* Try again to see if it is a bridge */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh, ++ &sizel, &sizeh); ++ } ++ ++ j = 1; ++ do { ++ asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ j++; ++ } while (asd != 0); ++ ++ /* Go through the ASDs for other slave ports */ ++ for (i = 1; i < nsp; i++) { ++ j = 0; ++ do { ++ asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) ++ break; ++ ++ if (!asidx--) { ++ *addr = addrl; ++ *size = sizel; ++ return; ++ } ++ j++; ++ } while (1); ++ ++ if (j == 0) { ++ SI_ERROR((" SP %d has no address descriptors\n", i)); ++ break; ++ } ++ } ++ ++error: ++ *size = 0; ++ return; ++} ++ ++/* Return the number of address spaces in current core */ ++int ++ai_numaddrspaces(si_t *sih) ++{ ++ return 2; ++} ++ ++/* Return the address of the nth address space in the current core */ ++uint32 ++ai_addrspace(si_t *sih, uint asidx) ++{ ++ si_info_t *sii; ++ uint cidx; ++ ++ sii = SI_INFO(sih); ++ cidx = sii->curidx; ++ ++ if (asidx == 0) ++ return sii->coresba[cidx]; ++ else if (asidx == 1) ++ return sii->coresba2[cidx]; ++ else { ++ SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", ++ __FUNCTION__, asidx)); ++ return 0; ++ } ++} ++ ++/* Return the size of the nth address space in the current core */ ++uint32 ++ai_addrspacesize(si_t *sih, uint asidx) ++{ ++ si_info_t *sii; ++ uint cidx; ++ ++ sii = SI_INFO(sih); ++ cidx = sii->curidx; ++ ++ if (asidx == 0) ++ return sii->coresba_size[cidx]; ++ else if (asidx == 1) ++ return sii->coresba2_size[cidx]; ++ else { ++ SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", ++ __FUNCTION__, asidx)); ++ return 0; ++ } ++} ++ ++uint ++ai_flag(si_t *sih) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ ++ sii = SI_INFO(sih); ++ if (BCM47162_DMP()) { ++ SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__)); ++ return sii->curidx; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__)); ++ return sii->curidx; ++ } ++ ai = sii->curwrap; ++//printf("ai=%p, oobselouta30=0x%x\n", ai, R_REG(sii->osh, &ai->oobselouta30)); ++ return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f); ++} ++ ++void ++ai_setint(si_t *sih, int siflag) ++{ ++} ++ ++uint ++ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ uint32 *map = (uint32 *) sii->curwrap; ++ ++ if (mask || val) { ++ uint32 w = R_REG(sii->osh, map+(offset/4)); ++ w &= ~mask; ++ w |= val; ++ W_REG(sii->osh, map+(offset/4), val); ++ } ++ ++ return (R_REG(sii->osh, map+(offset/4))); ++} ++ ++uint ++ai_corevendor(si_t *sih) ++{ ++ si_info_t *sii; ++ uint32 cia; ++ ++ sii = SI_INFO(sih); ++ cia = sii->cia[sii->curidx]; ++ return ((cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT); ++} ++ ++uint ++ai_corerev(si_t *sih) ++{ ++ si_info_t *sii; ++ uint32 cib; ++ ++ sii = SI_INFO(sih); ++ cib = sii->cib[sii->curidx]; ++ return remap_corerev(sih, (cib & CIB_REV_MASK) >> CIB_REV_SHIFT); ++} ++ ++bool ++ai_iscoreup(si_t *sih) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ ++ sii = SI_INFO(sih); ++ ai = sii->curwrap; ++ ++ return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == SICF_CLOCK_EN) && ++ ((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0)); ++} ++ ++/* ++ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation, ++ * switch back to the original core, and return the new value. ++ * ++ * When using the silicon backplane, no fiddling with interrupts or core switches is needed. ++ * ++ * Also, when using pci/pcie, we can optimize away the core switching for pci registers ++ * and (on newer pci cores) chipcommon registers. ++ */ ++uint ++ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) ++{ ++ uint origidx = 0; ++ uint32 *r = NULL; ++ uint w; ++ uint intr_val = 0; ++ bool fast = FALSE; ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ ASSERT(GOODIDX(coreidx)); ++ ASSERT(regoff < SI_CORE_SIZE); ++ ASSERT((val & ~mask) == 0); ++ ++ if (coreidx >= SI_MAXCORES) ++ return 0; ++ ++ if (BUSTYPE(sih->bustype) == SI_BUS) { ++ /* If internal bus, we can always get at everything */ ++ fast = TRUE; ++ /* map if does not exist */ ++ if (!sii->regs[coreidx]) { ++ sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx], ++ SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->regs[coreidx])); ++ } ++ r = (uint32 *)((uchar *)sii->regs[coreidx] + regoff); ++ } else if (BUSTYPE(sih->bustype) == PCI_BUS) { ++ /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ ++ ++ if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { ++ /* Chipc registers are mapped at 12KB */ ++ ++ fast = TRUE; ++ r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); ++ } else if (sii->pub.buscoreidx == coreidx) { ++ /* pci registers are at either in the last 2KB of an 8KB window ++ * or, in pcie and pci rev 13 at 8KB ++ */ ++ fast = TRUE; ++ if (SI_FAST(sii)) ++ r = (uint32 *)((char *)sii->curmap + ++ PCI_16KB0_PCIREGS_OFFSET + regoff); ++ else ++ r = (uint32 *)((char *)sii->curmap + ++ ((regoff >= SBCONFIGOFF) ? ++ PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + ++ regoff); ++ } ++ } ++ ++ if (!fast) { ++ INTR_OFF(sii, intr_val); ++ ++ /* save current core index */ ++ origidx = si_coreidx(&sii->pub); ++ ++ /* switch core */ ++ r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff); ++ } ++ ASSERT(r != NULL); ++ ++ /* mask and set */ ++ if (mask || val) { ++ w = (R_REG(sii->osh, r) & ~mask) | val; ++ W_REG(sii->osh, r, w); ++ } ++ ++ /* readback */ ++ w = R_REG(sii->osh, r); ++ ++ if (!fast) { ++ /* restore core index */ ++ if (origidx != coreidx) ++ ai_setcoreidx(&sii->pub, origidx); ++ ++ INTR_RESTORE(sii, intr_val); ++ } ++ ++ return (w); ++} ++ ++void ++ai_core_disable(si_t *sih, uint32 bits) ++{ ++ si_info_t *sii; ++ volatile uint32 dummy; ++ uint32 status; ++ aidmp_t *ai; ++ ++ sii = SI_INFO(sih); ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ /* if core is already in reset, just return */ ++ if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) ++ return; ++ ++ /* ensure there are no pending backplane operations */ ++ SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 300); ++ ++ /* if pending backplane ops still, try waiting longer */ ++ if (status != 0) { ++ /* 300usecs was sufficient to allow backplane ops to clear for big hammer */ ++ /* during driver load we may need more time */ ++ SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 10000); ++ /* if still pending ops, continue on and try disable anyway */ ++ /* this is in big hammer path, so don't call wl_reinit in this case... */ ++#ifdef BCMDBG ++ if (status != 0) { ++ printf("%s: WARN: resetstatus=%0x on core disable\n", __FUNCTION__, status); ++ } ++#endif ++ } ++ ++ W_REG(sii->osh, &ai->ioctrl, bits); ++ dummy = R_REG(sii->osh, &ai->ioctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(10); ++ ++ W_REG(sii->osh, &ai->resetctrl, AIRC_RESET); ++ dummy = R_REG(sii->osh, &ai->resetctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++} ++ ++/* reset and re-enable a core ++ * inputs: ++ * bits - core specific bits that are set during and after reset sequence ++ * resetbits - core specific bits that are set only during reset sequence ++ */ ++void ++ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ volatile uint32 dummy; ++ ++ sii = SI_INFO(sih); ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ bits = resetbits = R_REG(sii->osh, &ai->ioctrl) & 0xFFFFFFFC; ++#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++ ++ /* ++ * Must do the disable sequence first to work for arbitrary current core state. ++ */ ++ ai_core_disable(sih, (bits | resetbits)); ++ ++ /* ++ * Now do the initialization sequence. ++ */ ++ W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN)); ++ dummy = R_REG(sii->osh, &ai->ioctrl); ++ BCM_REFERENCE(dummy); ++ ++ W_REG(sii->osh, &ai->resetctrl, 0); ++ dummy = R_REG(sii->osh, &ai->resetctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++ ++ W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN)); ++ dummy = R_REG(sii->osh, &ai->ioctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++} ++ ++void ++ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ ++ if (BCM47162_DMP()) { ++ SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0", ++ __FUNCTION__)); ++ return; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n", ++ __FUNCTION__)); ++ return; ++ } ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ ASSERT((val & ~mask) == 0); ++ ++ if (mask || val) { ++ w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); ++ W_REG(sii->osh, &ai->ioctrl, w); ++ } ++} ++ ++uint32 ++ai_core_cflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ if (BCM47162_DMP()) { ++ SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0", ++ __FUNCTION__)); ++ return 0; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n", ++ __FUNCTION__)); ++ return 0; ++ } ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ ASSERT((val & ~mask) == 0); ++ ++ if (mask || val) { ++ w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); ++ W_REG(sii->osh, &ai->ioctrl, w); ++ } ++ ++ return R_REG(sii->osh, &ai->ioctrl); ++} ++ ++uint32 ++ai_core_sflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ if (BCM47162_DMP()) { ++ SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0", ++ __FUNCTION__)); ++ return 0; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("%s: Accessing USB20H DMP register (iostatus) on 5357\n", ++ __FUNCTION__)); ++ return 0; ++ } ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ ASSERT((val & ~mask) == 0); ++ ASSERT((mask & ~SISF_CORE_BITS) == 0); ++ ++ if (mask || val) { ++ w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val); ++ W_REG(sii->osh, &ai->iostatus, w); ++ } ++ ++ return R_REG(sii->osh, &ai->iostatus); ++} ++ ++#if defined(BCMDBG) ++/* print interesting aidmp registers */ ++void ++ai_dumpregs(si_t *sih, struct bcmstrbuf *b) ++{ ++ si_info_t *sii; ++ osl_t *osh; ++ aidmp_t *ai; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ osh = sii->osh; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ si_setcoreidx(&sii->pub, i); ++ ai = sii->curwrap; ++ ++ bcm_bprintf(b, "core 0x%x: \n", sii->coreid[i]); ++ if (BCM47162_DMP()) { ++ bcm_bprintf(b, "Skipping mips74k in 47162a0\n"); ++ continue; ++ } ++ if (BCM5357_DMP()) { ++ bcm_bprintf(b, "Skipping usb20h in 5357\n"); ++ continue; ++ } ++ ++ bcm_bprintf(b, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x" ++ "ioctrlwidth 0x%x iostatuswidth 0x%x\n" ++ "resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x resetwriteid 0x%x\n" ++ "errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x" ++ "errlogaddrlo 0x%x errlogaddrhi 0x%x\n" ++ "errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n" ++ "intstatus 0x%x config 0x%x itcr 0x%x\n", ++ R_REG(osh, &ai->ioctrlset), ++ R_REG(osh, &ai->ioctrlclear), ++ R_REG(osh, &ai->ioctrl), ++ R_REG(osh, &ai->iostatus), ++ R_REG(osh, &ai->ioctrlwidth), ++ R_REG(osh, &ai->iostatuswidth), ++ R_REG(osh, &ai->resetctrl), ++ R_REG(osh, &ai->resetstatus), ++ R_REG(osh, &ai->resetreadid), ++ R_REG(osh, &ai->resetwriteid), ++ R_REG(osh, &ai->errlogctrl), ++ R_REG(osh, &ai->errlogdone), ++ R_REG(osh, &ai->errlogstatus), ++ R_REG(osh, &ai->errlogaddrlo), ++ R_REG(osh, &ai->errlogaddrhi), ++ R_REG(osh, &ai->errlogid), ++ R_REG(osh, &ai->errloguser), ++ R_REG(osh, &ai->errlogflags), ++ R_REG(osh, &ai->intstatus), ++ R_REG(osh, &ai->config), ++ R_REG(osh, &ai->itcr)); ++ if ((sih->chip == BCM4331_CHIP_ID) && (sii->coreid[i] == PCIE_CORE_ID)) { ++ /* point bar0 2nd 4KB window */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, 0x18103000); ++ bcm_bprintf(b, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x" ++ "ioctrlwidth 0x%x iostatuswidth 0x%x\n" ++ "resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x" ++ " resetwriteid 0x%x\n" ++ "errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x" ++ "errlogaddrlo 0x%x errlogaddrhi 0x%x\n" ++ "errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n" ++ "intstatus 0x%x config 0x%x itcr 0x%x\n", ++ R_REG(osh, &ai->ioctrlset), ++ R_REG(osh, &ai->ioctrlclear), ++ R_REG(osh, &ai->ioctrl), ++ R_REG(osh, &ai->iostatus), ++ R_REG(osh, &ai->ioctrlwidth), ++ R_REG(osh, &ai->iostatuswidth), ++ R_REG(osh, &ai->resetctrl), ++ R_REG(osh, &ai->resetstatus), ++ R_REG(osh, &ai->resetreadid), ++ R_REG(osh, &ai->resetwriteid), ++ R_REG(osh, &ai->errlogctrl), ++ R_REG(osh, &ai->errlogdone), ++ R_REG(osh, &ai->errlogstatus), ++ R_REG(osh, &ai->errlogaddrlo), ++ R_REG(osh, &ai->errlogaddrhi), ++ R_REG(osh, &ai->errlogid), ++ R_REG(osh, &ai->errloguser), ++ R_REG(osh, &ai->errlogflags), ++ R_REG(osh, &ai->intstatus), ++ R_REG(osh, &ai->config), ++ R_REG(osh, &ai->itcr)); ++ /* bar0 2nd 4KB window will be fixed in the next setcore */ ++ } ++ } ++} ++#endif ++ ++#ifdef BCMDBG ++static void ++_ai_view(osl_t *osh, aidmp_t *ai, uint32 cid, uint32 addr, bool verbose) ++{ ++ uint32 config; ++ ++ config = R_REG(osh, &ai->config); ++ SI_ERROR(("\nCore ID: 0x%x, addr 0x%x, config 0x%x\n", cid, addr, config)); ++ ++ if (config & AICFG_RST) ++ SI_ERROR(("resetctrl 0x%x, resetstatus 0x%x, resetreadid 0x%x, resetwriteid 0x%x\n", ++ R_REG(osh, &ai->resetctrl), R_REG(osh, &ai->resetstatus), ++ R_REG(osh, &ai->resetreadid), R_REG(osh, &ai->resetwriteid))); ++ ++ if (config & AICFG_IOC) ++ SI_ERROR(("ioctrl 0x%x, width %d\n", R_REG(osh, &ai->ioctrl), ++ R_REG(osh, &ai->ioctrlwidth))); ++ ++ if (config & AICFG_IOS) ++ SI_ERROR(("iostatus 0x%x, width %d\n", R_REG(osh, &ai->iostatus), ++ R_REG(osh, &ai->iostatuswidth))); ++ ++ if (config & AICFG_ERRL) { ++ SI_ERROR(("errlogctrl 0x%x, errlogdone 0x%x, errlogstatus 0x%x, intstatus 0x%x\n", ++ R_REG(osh, &ai->errlogctrl), R_REG(osh, &ai->errlogdone), ++ R_REG(osh, &ai->errlogstatus), R_REG(osh, &ai->intstatus))); ++ SI_ERROR(("errlogid 0x%x, errloguser 0x%x, errlogflags 0x%x, errlogaddr " ++ "0x%x/0x%x\n", ++ R_REG(osh, &ai->errlogid), R_REG(osh, &ai->errloguser), ++ R_REG(osh, &ai->errlogflags), R_REG(osh, &ai->errlogaddrhi), ++ R_REG(osh, &ai->errlogaddrlo))); ++ } ++ ++ if (verbose && (config & AICFG_OOB)) { ++ SI_ERROR(("oobselina30 0x%x, oobselina74 0x%x\n", ++ R_REG(osh, &ai->oobselina30), R_REG(osh, &ai->oobselina74))); ++ SI_ERROR(("oobselinb30 0x%x, oobselinb74 0x%x\n", ++ R_REG(osh, &ai->oobselinb30), R_REG(osh, &ai->oobselinb74))); ++ SI_ERROR(("oobselinc30 0x%x, oobselinc74 0x%x\n", ++ R_REG(osh, &ai->oobselinc30), R_REG(osh, &ai->oobselinc74))); ++ SI_ERROR(("oobselind30 0x%x, oobselind74 0x%x\n", ++ R_REG(osh, &ai->oobselind30), R_REG(osh, &ai->oobselind74))); ++ SI_ERROR(("oobselouta30 0x%x, oobselouta74 0x%x\n", ++ R_REG(osh, &ai->oobselouta30), R_REG(osh, &ai->oobselouta74))); ++ SI_ERROR(("oobseloutb30 0x%x, oobseloutb74 0x%x\n", ++ R_REG(osh, &ai->oobseloutb30), R_REG(osh, &ai->oobseloutb74))); ++ SI_ERROR(("oobseloutc30 0x%x, oobseloutc74 0x%x\n", ++ R_REG(osh, &ai->oobseloutc30), R_REG(osh, &ai->oobseloutc74))); ++ SI_ERROR(("oobseloutd30 0x%x, oobseloutd74 0x%x\n", ++ R_REG(osh, &ai->oobseloutd30), R_REG(osh, &ai->oobseloutd74))); ++ SI_ERROR(("oobsynca 0x%x, oobseloutaen 0x%x\n", ++ R_REG(osh, &ai->oobsynca), R_REG(osh, &ai->oobseloutaen))); ++ SI_ERROR(("oobsyncb 0x%x, oobseloutben 0x%x\n", ++ R_REG(osh, &ai->oobsyncb), R_REG(osh, &ai->oobseloutben))); ++ SI_ERROR(("oobsyncc 0x%x, oobseloutcen 0x%x\n", ++ R_REG(osh, &ai->oobsyncc), R_REG(osh, &ai->oobseloutcen))); ++ SI_ERROR(("oobsyncd 0x%x, oobseloutden 0x%x\n", ++ R_REG(osh, &ai->oobsyncd), R_REG(osh, &ai->oobseloutden))); ++ SI_ERROR(("oobaextwidth 0x%x, oobainwidth 0x%x, oobaoutwidth 0x%x\n", ++ R_REG(osh, &ai->oobaextwidth), R_REG(osh, &ai->oobainwidth), ++ R_REG(osh, &ai->oobaoutwidth))); ++ SI_ERROR(("oobbextwidth 0x%x, oobbinwidth 0x%x, oobboutwidth 0x%x\n", ++ R_REG(osh, &ai->oobbextwidth), R_REG(osh, &ai->oobbinwidth), ++ R_REG(osh, &ai->oobboutwidth))); ++ SI_ERROR(("oobcextwidth 0x%x, oobcinwidth 0x%x, oobcoutwidth 0x%x\n", ++ R_REG(osh, &ai->oobcextwidth), R_REG(osh, &ai->oobcinwidth), ++ R_REG(osh, &ai->oobcoutwidth))); ++ SI_ERROR(("oobdextwidth 0x%x, oobdinwidth 0x%x, oobdoutwidth 0x%x\n", ++ R_REG(osh, &ai->oobdextwidth), R_REG(osh, &ai->oobdinwidth), ++ R_REG(osh, &ai->oobdoutwidth))); ++ } ++} ++ ++void ++ai_view(si_t *sih, bool verbose) ++{ ++ si_info_t *sii; ++ osl_t *osh; ++ aidmp_t *ai; ++ uint32 cid, addr; ++ ++ sii = SI_INFO(sih); ++ ai = sii->curwrap; ++ osh = sii->osh; ++ if (BCM47162_DMP()) { ++ SI_ERROR(("Cannot access mips74k DMP in 47162a0\n")); ++ return; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("Cannot access usb20h DMP in 5357\n")); ++ return; ++ } ++ cid = sii->coreid[sii->curidx]; ++ addr = sii->wrapba[sii->curidx]; ++ _ai_view(osh, ai, cid, addr, verbose); ++} ++ ++void ++ai_viewall(si_t *sih, bool verbose) ++{ ++ si_info_t *sii; ++ osl_t *osh; ++ aidmp_t *ai; ++ uint32 cid, addr; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ osh = sii->osh; ++ for (i = 0; i < sii->numcores; i++) { ++ si_setcoreidx(sih, i); ++ if (BCM47162_DMP()) { ++ SI_ERROR(("Skipping mips74k DMP in 47162a0\n")); ++ continue; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("Skipping usb20h DMP in 5357\n")); ++ continue; ++ } ++ ai = sii->curwrap; ++ cid = sii->coreid[sii->curidx]; ++ addr = sii->wrapba[sii->curidx]; ++ _ai_view(osh, ai, cid, addr, verbose); ++ if ((sih->chip == BCM4331_CHIP_ID) && (sii->coreid[i] == PCIE_CORE_ID)) { ++ /* point bar0 2nd 4KB window */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, 0x18103000); ++ _ai_view(osh, ai, cid, 0x18103000, verbose); ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, 0x18104000); ++ _ai_view(osh, ai, 0x135, 0x18104000, verbose); ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, 0x18105000); ++ _ai_view(osh, ai, 0x135, 0x18105000, verbose); ++ /* bar0 2nd 4KB window will be fixed in the next setcore */ ++ } ++ } ++} ++#endif /* BCMDBG */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5221.c b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5221.c +new file mode 100755 +index 0000000..58e66fc +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5221.c +@@ -0,0 +1,509 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include ++#include "../../../mdio/iproc_mdio.h" ++#include "bcmiproc_phy.h" ++#include "bcmiproc_phy5221.h" ++ ++/* ---- External Variable Declarations ----------------------------------- */ ++/* ---- External Function Prototypes ------------------------------------- */ ++/* ---- Public Variables ------------------------------------------------- */ ++/* ---- Private Constants and Types -------------------------------------- */ ++/* ---- Private Variables ------------------------------------------------ */ ++ ++/* debug/trace */ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) printf args ++#elif defined(BCMDBG_ERR) ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) ++#else ++#define NET_ERROR(args) ++#define NET_TRACE(args) ++#endif /* BCMDBG */ ++#define NET_REG_TRACE(args) ++ ++ ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++ ++ ++/* ==== Public Functions ================================================= */ ++ ++int ++phy5221_wr_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data) ++{ ++ uint16 wr_data=*data; ++ uint16 test_reg; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to write phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, wr_data)); ++ //printf("%s going to write phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg_bank, reg_addr, wr_data); ++ ++ if (reg_bank) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1f, &test_reg); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, (test_reg | 0x0080)); ++ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, test_reg); ++ } else { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ } ++ return SOC_E_NONE; ++} ++ ++ ++int ++phy5221_rd_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data) ++{ ++ uint16 test_reg; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to read phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr)); ++ ++ if (reg_bank) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1f, &test_reg); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, (test_reg | 0x0080)); ++ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); ++ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, test_reg); ++ } else { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); ++ } ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, *data)); ++ //printf("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg_bank, reg_addr, *data); ++ return SOC_E_NONE; ++} ++ ++ ++int ++phy5221_mod_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 data, uint16 mask) ++{ ++ uint16 test_reg; ++ uint16 org_data, rd_data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to modify phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x) mask(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, data, mask)); ++ ++ if (reg_bank) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1f, &test_reg); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, (test_reg | 0x0080)); ++ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ org_data = rd_data; ++ rd_data &= ~(mask); ++ rd_data |= data; ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, test_reg); ++ } else { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ org_data = rd_data; ++ rd_data &= ~(mask); ++ rd_data |= data; ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ } ++ //printf("%s modified(0x%x to 0x%x) at phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", ++ // __FUNCTION__, org_data, rd_data, phyaddr, reg_bank, reg_addr); ++ ++ return SOC_E_NONE; ++} ++ ++ ++void ++phy5221_fe_reset(uint eth_num, uint phyaddr) ++{ ++ uint16 ctrl; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* set reset flag */ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ ctrl |= MII_CTRL_RESET; ++ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ ++ SPINWAIT( (!phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl) ++ && (ctrl & MII_CTRL_RESET)), 100000); ++ /* check if out of reset */ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ if (ctrl & MII_CTRL_RESET) { ++ /* timeout */ ++ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); ++ } else { ++ NET_ERROR(("et%d: %s reset complete\n", eth_num, __FUNCTION__)); ++ } ++ ++ return; ++} ++ ++ ++/* ++ * Function: ++ * phy5221_fe_init ++ * Purpose: ++ * Initialize the PHY (MII mode) to a known good state. ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * Returns: ++ * SOC_E_XXX ++ ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++int ++phy5221_fe_init(uint eth_num, uint phyaddr) ++{ ++ uint16 mii_ana, mii_ctrl; ++ ++ /* Reset PHY */ ++ phy5221_fe_reset(eth_num, phyaddr); ++ ++ mii_ana = MII_ANA_HD_10 | MII_ANA_FD_10 | MII_ANA_HD_100 | ++ MII_ANA_FD_100 | MII_ANA_ASF_802_3; ++ mii_ctrl = MII_CTRL_FD | MII_CTRL_SS_100 | MII_CTRL_AE | MII_CTRL_RAN; ++ ++ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ ++ return SOC_E_NONE; ++} ++ ++ ++ ++ ++/* ++ * Function: ++ * phy5221_init ++ * Purpose: ++ * Initialize xgxs6 phys ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * Returns: ++ * 0 ++ */ ++int ++phy5221_init(uint eth_num, uint phyaddr) ++{ ++ uint16 phyid0, phyid1; ++ uint16 tmp = 0; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID0r_BANK, PHY_MII_PHY_ID0r_ADDR, &phyid0); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID1r_BANK, PHY_MII_PHY_ID1r_ADDR, &phyid1); ++ ++ //printf("%s phyaddr(0x%x) Phy ChipID: 0x%04x:0x%04x\n", __FUNCTION__, phyaddr, phyid1, phyid0); ++ ++ phy5221_fe_init(eth_num, phyaddr); ++ ++ phy5221_rd_reg(eth_num, phyaddr, 0, 0x16, &tmp); ++ tmp = 2; ++ phy5221_wr_reg(eth_num, phyaddr, 0, 0x16, &tmp); ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * phy5221_link_get ++ * Purpose: ++ * Determine the current link up/down status ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * link - (OUT) Boolean, true indicates link established. ++ * Returns: ++ * SOC_E_XXX ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++int ++phy5221_link_get(uint eth_num, uint phyaddr, int *link) ++{ ++ uint16 mii_ctrl, mii_stat; ++ uint32 wait; ++ ++ *link = FALSE; /* Default */ ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ /* the first read of status register will not show link up, second read will show link up */ ++ if (!(mii_stat & MII_STAT_LA) ) { ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ } ++ ++ if (!(mii_stat & MII_STAT_LA) || (mii_stat == 0xffff)) { ++ /* mii_stat == 0xffff check is to handle removable PHY daughter cards */ ++ return SOC_E_NONE; ++ } ++ ++ /* Link appears to be up; we are done if autoneg is off. */ ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ ++ if (!(mii_ctrl & MII_CTRL_AE)) { ++ *link = TRUE; ++ return SOC_E_NONE; ++ } ++ ++ /* ++ * If link appears to be up but autonegotiation is still in ++ * progress, wait for it to complete. For BCM5228, autoneg can ++ * still be busy up to about 200 usec after link is indicated. Also ++ * continue to check link state in case it goes back down. ++ * wait 500ms (500000us/10us = 50000 ) ++ */ ++ for (wait=0; wait<50000; wait++) { ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ if (!(mii_stat & MII_STAT_LA)) { ++ /* link is down */ ++ return SOC_E_NONE; ++ } ++ ++ if (mii_stat & MII_STAT_AN_DONE) { ++ /* AutoNegotiation done */ ++ break; ++ } ++ ++ OSL_DELAY(10); ++ } ++ if (wait>=50000) { ++ /* timeout */ ++ return SOC_E_BUSY; ++ } ++ ++ /* Return link state at end of polling */ ++ *link = ((mii_stat & MII_STAT_LA) != 0); ++ ++ return SOC_E_NONE; ++} ++ ++ ++/* ++ * Function: ++ * phy5221_enable_set ++ * Purpose: ++ * Enable/Disable phy ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * enable - on/off state to set ++ * Returns: ++ * 0 ++ */ ++int ++phy5221_enable_set(uint eth_num, uint phyaddr, int enable) ++{ ++ uint16 data; /* New value to write to PHY register */ ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ data = enable ? 0 : MII_ECR_TD; /* Transmitt enable/disable */ ++ phy5221_mod_reg(eth_num, phyaddr, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, data, MII_ECR_TD); ++ ++ data = enable ? 0 : PHY522X_SUPER_ISOLATE_MODE; ++ /* Device needs to be put in super-isolate mode in order to disable ++ * the link in 10BaseT mode ++ */ ++ phy5221_mod_reg(eth_num, phyaddr, PHY_AUX_MULTIPLE_PHYr_BANK, PHY_AUX_MULTIPLE_PHYr_ADDR, ++ data, PHY522X_SUPER_ISOLATE_MODE); ++ ++ return SOC_E_NONE; ++} ++ ++ ++ ++ ++/* ++ * Function: ++ * phy5221_auto_negotiate_gcd (greatest common denominator). ++ * Purpose: ++ * Determine the current greatest common denominator between ++ * two ends of a link ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * speed - (OUT) greatest common speed. ++ * duplex - (OUT) greatest common duplex. ++ * link - (OUT) Boolean, true indicates link established. ++ * Returns: ++ * SOC_E_XXX ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++static int ++phy5221_auto_negotiate_gcd(uint eth_num, uint phyaddr, int *speed, int *duplex) ++{ ++ int t_speed, t_duplex; ++ uint16 mii_ana, mii_anp, mii_stat; ++ uint16 mii_gb_stat, mii_esr, mii_gb_ctrl; ++ ++ mii_gb_stat = 0; /* Start off 0 */ ++ mii_gb_ctrl = 0; /* Start off 0 */ ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ANPr_BANK, PHY_MII_ANPr_ADDR, &mii_anp); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ if (mii_stat & MII_STAT_ES) { /* Supports extended status */ ++ /* ++ * If the PHY supports extended status, check if it is 1000MB ++ * capable. If it is, check the 1000Base status register to see ++ * if 1000MB negotiated. ++ */ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ESRr_BANK, PHY_MII_ESRr_ADDR, &mii_esr); ++ ++ if (mii_esr & (MII_ESR_1000_X_FD | MII_ESR_1000_X_HD | ++ MII_ESR_1000_T_FD | MII_ESR_1000_T_HD)) { ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_GB_STATr_BANK, PHY_MII_GB_STATr_ADDR, &mii_gb_stat); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); ++ } ++ } ++ ++ /* ++ * At this point, if we did not see Gig status, one of mii_gb_stat or ++ * mii_gb_ctrl will be 0. This will cause the first 2 cases below to ++ * fail and fall into the default 10/100 cases. ++ */ ++ ++ mii_ana &= mii_anp; ++ ++ if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) && ++ (mii_gb_stat & MII_GB_STAT_LP_1000FD)) { ++ t_speed = 1000; ++ t_duplex = 1; ++ } else if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) && ++ (mii_gb_stat & MII_GB_STAT_LP_1000HD)) { ++ t_speed = 1000; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_FD_100) { /* [a] */ ++ t_speed = 100; ++ t_duplex = 1; ++ } else if (mii_ana & MII_ANA_T4) { /* [b] */ ++ t_speed = 100; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_HD_100) { /* [c] */ ++ t_speed = 100; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_FD_10) { /* [d] */ ++ t_speed = 10; ++ t_duplex = 1 ; ++ } else if (mii_ana & MII_ANA_HD_10) { /* [e] */ ++ t_speed = 10; ++ t_duplex = 0; ++ } else { ++ return(SOC_E_FAIL); ++ } ++ ++ if (speed) *speed = t_speed; ++ if (duplex) *duplex = t_duplex; ++ ++ return(SOC_E_NONE); ++} ++ ++ ++/* ++ * Function: ++ * phy5221_speed_get ++ * Purpose: ++ * Get PHY speed ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * speed - current link speed in Mbps ++ * Returns: ++ * 0 ++ */ ++int ++phy5221_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex) ++{ ++ int rv; ++ uint16 mii_ctrl, mii_stat; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ *speed = 0; ++ *duplex = 0; ++ if (mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ ++ if (!(mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ ++ rv = SOC_E_NONE; ++ } else { ++ rv = phy5221_auto_negotiate_gcd(eth_num, phyaddr, speed, duplex); ++ } ++ } else { /* Auto-negotiation disabled */ ++ /* ++ * Simply pick up the values we force in CTRL register. ++ */ ++ if (mii_ctrl & MII_CTRL_FD) ++ *duplex = 1; ++ ++ switch(MII_CTRL_SS(mii_ctrl)) { ++ case MII_CTRL_SS_10: ++ *speed = 10; ++ break; ++ case MII_CTRL_SS_100: ++ *speed = 100; ++ break; ++ case MII_CTRL_SS_1000: ++ *speed = 1000; ++ break; ++ default: /* Just pass error back */ ++ return(SOC_E_UNAVAIL); ++ } ++ rv = SOC_E_NONE; ++ } ++ ++ return(rv); ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5461s.c b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5461s.c +new file mode 100755 +index 0000000..6b2391d +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5461s.c +@@ -0,0 +1,734 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include ++#include "../../../mdio/iproc_mdio.h" ++#include "bcmiproc_phy.h" ++#include "bcmiproc_phy5461s.h" ++ ++/* ---- External Variable Declarations ----------------------------------- */ ++/* ---- External Function Prototypes ------------------------------------- */ ++/* ---- Public Variables ------------------------------------------------- */ ++/* ---- Private Constants and Types -------------------------------------- */ ++/* ---- Private Variables ------------------------------------------------ */ ++ ++/* debug/trace */ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) printf args ++#elif defined(BCMDBG_ERR) ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) ++#else ++#define NET_ERROR(args) ++#define NET_TRACE(args) ++#endif /* BCMDBG */ ++#define NET_REG_TRACE(args) ++ ++ ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++ ++ ++/* ==== Public Functions ================================================= */ ++ ++int ++phy5461_wr_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data) ++{ ++ int rv = SOC_E_NONE; ++ uint16 wr_data=*data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to write phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, wr_data)); ++ //printf("%s phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, wr_data); ++ ++ if (flags & SOC_PHY_REG_1000X) { ++ if (reg_addr <= 0x000f) { ++ uint16 blk_sel; ++ ++ /* Map 1000X page */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, 0x7c00); ++ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1c, &blk_sel); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, blk_sel | 0x8001); ++ ++ /* write 1000X IEEE register */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ ++ /* Restore IEEE mapping */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, (blk_sel & 0xfffe) | 0x8000); ++ } else if (flags & _SOC_PHY_REG_DIRECT) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ } else { ++ switch(reg_addr) { ++ /* Map shadow registers */ ++ case 0x18: ++ if (reg_bank <= 0x0007) { ++ if (reg_bank == 0x0007) { ++ wr_data |= 0x8000; ++ } ++ wr_data = (wr_data & ~(0x0007)) | reg_bank; ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ case 0x1C: ++ if (reg_bank <= 0x001F) { ++ wr_data = 0x8000 | (reg_bank << 10) | (wr_data & 0x03FF); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ default: ++ if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { ++ /* Must not write to reserved registers */ ++ if (reg_addr > 0x001e) { ++ rv = SOC_E_PARAM; ++ } ++ } ++ break; ++ } ++ if (SOC_SUCCESS(rv)) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ } ++ } ++ if (SOC_FAILURE(rv)) { ++ NET_ERROR(("%s ERROR phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) rv(%d)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rv)); ++ } ++ return rv; ++} ++ ++ ++int ++phy5461_rd_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data) ++{ ++ int rv = SOC_E_NONE; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to read phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr)); ++ if (flags & SOC_PHY_REG_1000X) { ++ if (reg_addr <= 0x000f) { ++ uint16 blk_sel; ++ ++ /* Map 1000X page */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, 0x7c00); ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1c, &blk_sel); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, blk_sel | 0x8001); ++ ++ /* Read 1000X IEEE register */ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, *data)); ++ ++ /* Restore IEEE mapping */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, (blk_sel & 0xfffe) | 0x8000); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ } else { ++ switch(reg_addr) { ++ /* Map shadow registers */ ++ case 0x18: ++ if (reg_bank <= 0x0007) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 12) | 0x7); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ case 0x1C: ++ if (reg_bank <= 0x001F) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 10)); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ default: ++ if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { ++ /* Must not read from reserved registers */ ++ if (reg_addr > 0x001e) { ++ rv = SOC_E_PARAM; ++ } ++ } ++ break; ++ } ++ if (SOC_SUCCESS(rv)) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, *data)); ++ } ++ } ++ if (SOC_FAILURE(rv)) { ++ NET_ERROR(("%s ERROR phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) rv(%d)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rv)); ++ } else { ++ //printf("%s phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg_bank, reg_addr, *data); ++ } ++ ++ return rv; ++} ++ ++ ++int ++phy5461_mod_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 data, uint16 mask) ++{ ++ int rv = SOC_E_NONE; ++ uint16 org_data, rd_data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to modify phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x) mask(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, data, mask)); ++ ++ if (flags & SOC_PHY_REG_1000X) { ++ if (reg_addr <= 0x000f) { ++ uint16 blk_sel; ++ ++ /* Map 1000X page */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, 0x7c00); ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1c, &blk_sel); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, blk_sel | 0x8001); ++ ++ /* Modify 1000X IEEE register */ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ org_data = rd_data; ++ rd_data &= ~(mask); ++ rd_data |= data; ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ ++ /* Restore IEEE mapping */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, (blk_sel & 0xfffe) | 0x8000); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ } else { ++ switch(reg_addr) { ++ /* Map shadow registers */ ++ case 0x18: ++ if (reg_bank <= 0x0007) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 12) | 0x7); ++ ++ if (reg_bank == 0x0007) { ++ data |= 0x8000; ++ mask |= 0x8000; ++ } ++ mask &= ~(0x0007); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ case 0x1C: ++ if (reg_bank <= 0x001F) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 10)); ++ data |= 0x8000; ++ mask |= 0x8000; ++ mask &= ~(0x1F << 10); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ default: ++ if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { ++ /* Must not write to reserved registers */ ++ if (reg_addr > 0x001e) { ++ rv = SOC_E_PARAM; ++ } ++ } ++ break; ++ } ++ if (SOC_SUCCESS(rv)) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ org_data = rd_data; ++ rd_data &= ~(mask); ++ rd_data |= data; ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ } ++ } ++ ++ if (SOC_FAILURE(rv)) { ++ NET_ERROR(("%s ERROR phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) rv(%d)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rv)); ++ } else { ++ //printf("%s modified(0x%x to 0x%x at phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", ++ // __FUNCTION__, org_data, rd_data, phyaddr, reg_bank, reg_addr); ++ } ++ ++ return rv; ++} ++ ++ ++void ++phy5461_ge_reset(uint eth_num, uint phyaddr) ++{ ++ uint16 ctrl; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* set reset flag */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ ctrl |= MII_CTRL_RESET; ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ ++ SPINWAIT( (!phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl) ++ && (ctrl & MII_CTRL_RESET)), 100000); ++ /* check if out of reset */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ if (ctrl & MII_CTRL_RESET) { ++ /* timeout */ ++ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); ++ } else { ++ NET_TRACE(("et%d: %s reset complete\n", eth_num, __FUNCTION__)); ++ } ++} ++ ++ ++/* ++ * Function: ++ * phy5461_ge_interface_set ++ * Purpose: ++ * Set the current operating mode of the PHY. ++ * (Pertaining to the MAC/PHY interface, not the line interface). ++ * For example: TBI or MII/GMII. ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * pif - one of SOC_PORT_IF_* ++ * Returns: ++ * SOC_E_XXX ++ */ ++int ++phy5461_ge_interface_set(uint eth_num, uint phyaddr, soc_port_if_t pif) ++{ ++ uint16 mii_ecr; ++ int mii; /* MII if true, TBI otherwise */ ++ ++ switch (pif) { ++ case SOC_PORT_IF_MII: ++ case SOC_PORT_IF_GMII: ++ case SOC_PORT_IF_SGMII: ++ mii = TRUE; ++ break; ++ case SOC_PORT_IF_NOCXN: ++ return (SOC_E_NONE); ++ case SOC_PORT_IF_TBI: ++ mii = FALSE; ++ break; ++ default: ++ return SOC_E_UNAVAIL; ++ } ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ECRr_FLAGS, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, &mii_ecr); ++ ++ if (mii) { ++ mii_ecr &= ~MII_ECR_10B; ++ } else { ++ mii_ecr |= MII_ECR_10B; ++ } ++ ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_ECRr_FLAGS, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, &mii_ecr); ++ ++ return(SOC_E_NONE); ++} ++ ++ ++/* ++ * Function: ++ * phy5461_ge_init ++ * Purpose: ++ * Initialize the PHY (MII mode) to a known good state. ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * Returns: ++ * SOC_E_XXX ++ ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++int ++phy5461_ge_init(uint eth_num, uint phyaddr) ++{ ++ uint16 mii_ctrl, mii_gb_ctrl; ++ uint16 mii_ana; ++ soc_port_if_t pif; ++ ++ /* Reset PHY */ ++ phy5461_ge_reset(eth_num, phyaddr); ++ ++ /* set advertized bits */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ mii_ana |= MII_ANA_FD_100 | MII_ANA_FD_10; ++ mii_ana |= MII_ANA_HD_100 | MII_ANA_HD_10; ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ ++ mii_ctrl = MII_CTRL_FD | MII_CTRL_SS_1000 | MII_CTRL_AE | MII_CTRL_RAN; ++ mii_gb_ctrl = MII_GB_CTRL_ADV_1000FD | MII_GB_CTRL_PT; ++ ++ pif = SOC_PORT_IF_GMII; ++ ++ phy5461_ge_interface_set(eth_num, phyaddr, pif); ++ ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_FLAGS, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ ++ return(SOC_E_NONE); ++} ++ ++ ++ ++ ++void ++phy5461_reset_setup(uint eth_num, uint phyaddr) ++{ ++ uint16 tmp; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ phy5461_ge_init(eth_num, phyaddr); ++ ++ /* copper regs */ ++ /* remove power down */ ++ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, 0, MII_CTRL_PD); ++ /* Disable super-isolate */ ++ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_POWER_CTRLr_FLAGS, PHY_MII_POWER_CTRLr_BANK, PHY_MII_POWER_CTRLr_ADDR, 0, 1U<<5); ++ /* Enable extended packet length */ ++ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_AUX_CTRLr_FLAGS, PHY_MII_AUX_CTRLr_BANK, PHY_MII_AUX_CTRLr_ADDR, 0x4000, 0x4000); ++ ++ /* Configure interface to MAC */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_1000X_MII_CTRLr_FLAGS, PHY_1000X_MII_CTRLr_BANK, PHY_1000X_MII_CTRLr_ADDR, &tmp); ++ /* phy5461_ge_init has reset the phy, powering down the unstrapped interface */ ++ /* make sure enabled interfaces are powered up */ ++ /* SGMII (passthrough fiber) or GMII fiber regs */ ++ tmp &= ~MII_CTRL_PD; /* remove power down */ ++ /* ++ * Enable SGMII autonegotiation on the switch side so that the ++ * link status changes are reflected in the switch. ++ * On Bradley devices, LAG failover feature depends on the SerDes ++ * link staus to activate failover recovery. ++ */ ++ tmp |= MII_CTRL_AE; ++ phy5461_wr_reg(eth_num, phyaddr, PHY_1000X_MII_CTRLr_FLAGS, PHY_1000X_MII_CTRLr_BANK, PHY_1000X_MII_CTRLr_ADDR, &tmp); ++ ++ return; ++} ++ ++ ++/* ++ * Function: ++ * phy5461_init ++ * Purpose: ++ * Initialize xgxs6 phys ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * Returns: ++ * 0 ++ */ ++int ++phy5461_init(uint eth_num, uint phyaddr) ++{ ++ uint16 phyid0, phyid1; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID0r_FLAGS, PHY_MII_PHY_ID0r_BANK, PHY_MII_PHY_ID0r_ADDR, &phyid0); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID1r_FLAGS, PHY_MII_PHY_ID1r_BANK, PHY_MII_PHY_ID1r_ADDR, &phyid1); ++ ++ printf("%s Phy ChipID: 0x%04x:0x%04x\n", __FUNCTION__, phyid1, phyid0); ++ ++ phy5461_reset_setup(eth_num, phyaddr); ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * phy5461_link_get ++ * Purpose: ++ * Determine the current link up/down status ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * link - (OUT) Boolean, true indicates link established. ++ * Returns: ++ * SOC_E_XXX ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++int ++phy5461_link_get(uint eth_num, uint phyaddr, int *link) ++{ ++ uint16 mii_ctrl, mii_stat; ++ uint32 wait; ++ ++ *link = FALSE; /* Default */ ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ /* the first read of status register will not show link up, second read will show link up */ ++ if (!(mii_stat & MII_STAT_LA) ) { ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ } ++ ++ if (!(mii_stat & MII_STAT_LA) || (mii_stat == 0xffff)) { ++ /* mii_stat == 0xffff check is to handle removable PHY daughter cards */ ++ return SOC_E_NONE; ++ } ++ ++ /* Link appears to be up; we are done if autoneg is off. */ ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ ++ if (!(mii_ctrl & MII_CTRL_AE)) { ++ *link = TRUE; ++ return SOC_E_NONE; ++ } ++ ++ /* ++ * If link appears to be up but autonegotiation is still in ++ * progress, wait for it to complete. For BCM5228, autoneg can ++ * still be busy up to about 200 usec after link is indicated. Also ++ * continue to check link state in case it goes back down. ++ */ ++ for (wait=0; wait<50000; wait++) { ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ if (!(mii_stat & MII_STAT_LA)) { ++ /* link is down */ ++ return SOC_E_NONE; ++ } ++ ++ if (mii_stat & MII_STAT_AN_DONE) { ++ /* AutoNegotiation done */ ++ break; ++ } ++ ++ OSL_DELAY(10); ++ } ++ if (wait>=50000) { ++ /* timeout */ ++ return SOC_E_BUSY; ++ } ++ ++ /* Return link state at end of polling */ ++ *link = ((mii_stat & MII_STAT_LA) != 0); ++ ++ return SOC_E_NONE; ++} ++ ++ ++/* ++ * Function: ++ * phy5461_enable_set ++ * Purpose: ++ * Enable/Disable phy ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * enable - on/off state to set ++ * Returns: ++ * 0 ++ */ ++int ++phy5461_enable_set(uint eth_num, uint phyaddr, int enable) ++{ ++ uint16 power_down; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ power_down = (enable) ? 0 : MII_CTRL_PD; ++ ++ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, power_down, MII_CTRL_PD); ++ ++ return SOC_E_NONE; ++} ++ ++ ++ ++ ++/* ++ * Function: ++ * phy5461_auto_negotiate_gcd (greatest common denominator). ++ * Purpose: ++ * Determine the current greatest common denominator between ++ * two ends of a link ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * speed - (OUT) greatest common speed. ++ * duplex - (OUT) greatest common duplex. ++ * link - (OUT) Boolean, true indicates link established. ++ * Returns: ++ * SOC_E_XXX ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++static int ++phy5461_auto_negotiate_gcd(uint eth_num, uint phyaddr, int *speed, int *duplex) ++{ ++ int t_speed, t_duplex; ++ uint16 mii_ana, mii_anp, mii_stat; ++ uint16 mii_gb_stat, mii_esr, mii_gb_ctrl; ++ ++ mii_gb_stat = 0; /* Start off 0 */ ++ mii_gb_ctrl = 0; /* Start off 0 */ ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANPr_FLAGS, PHY_MII_ANPr_BANK, PHY_MII_ANPr_ADDR, &mii_anp); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ if (mii_stat & MII_STAT_ES) { /* Supports extended status */ ++ /* ++ * If the PHY supports extended status, check if it is 1000MB ++ * capable. If it is, check the 1000Base status register to see ++ * if 1000MB negotiated. ++ */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ESRr_FLAGS, PHY_MII_ESRr_BANK, PHY_MII_ESRr_ADDR, &mii_esr); ++ ++ if (mii_esr & (MII_ESR_1000_X_FD | MII_ESR_1000_X_HD | ++ MII_ESR_1000_T_FD | MII_ESR_1000_T_HD)) { ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_GB_STATr_FLAGS, PHY_MII_GB_STATr_BANK, PHY_MII_GB_STATr_ADDR, &mii_gb_stat); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_FLAGS, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); ++ } ++ } ++ ++ /* ++ * At this point, if we did not see Gig status, one of mii_gb_stat or ++ * mii_gb_ctrl will be 0. This will cause the first 2 cases below to ++ * fail and fall into the default 10/100 cases. ++ */ ++ ++ mii_ana &= mii_anp; ++ ++ if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) && ++ (mii_gb_stat & MII_GB_STAT_LP_1000FD)) { ++ t_speed = 1000; ++ t_duplex = 1; ++ } else if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) && ++ (mii_gb_stat & MII_GB_STAT_LP_1000HD)) { ++ t_speed = 1000; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_FD_100) { /* [a] */ ++ t_speed = 100; ++ t_duplex = 1; ++ } else if (mii_ana & MII_ANA_T4) { /* [b] */ ++ t_speed = 100; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_HD_100) { /* [c] */ ++ t_speed = 100; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_FD_10) { /* [d] */ ++ t_speed = 10; ++ t_duplex = 1 ; ++ } else if (mii_ana & MII_ANA_HD_10) { /* [e] */ ++ t_speed = 10; ++ t_duplex = 0; ++ } else { ++ return(SOC_E_FAIL); ++ } ++ ++ if (speed) *speed = t_speed; ++ if (duplex) *duplex = t_duplex; ++ ++ return(SOC_E_NONE); ++} ++ ++ ++/* ++ * Function: ++ * phy5461_speed_get ++ * Purpose: ++ * Get PHY speed ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * speed - current link speed in Mbps ++ * Returns: ++ * 0 ++ */ ++int ++phy5461_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex) ++{ ++ int rv; ++ uint16 mii_ctrl, mii_stat; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ *speed = 0; ++ *duplex = 0; ++ if (mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ ++ if (!(mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ ++ rv = SOC_E_NONE; ++ } else { ++ rv = phy5461_auto_negotiate_gcd(eth_num, phyaddr, speed, duplex); ++ } ++ } else { /* Auto-negotiation disabled */ ++ /* ++ * Simply pick up the values we force in CTRL register. ++ */ ++ if (mii_ctrl & MII_CTRL_FD) ++ *duplex = 1; ++ ++ switch(MII_CTRL_SS(mii_ctrl)) { ++ case MII_CTRL_SS_10: ++ *speed = 10; ++ break; ++ case MII_CTRL_SS_100: ++ *speed = 100; ++ break; ++ case MII_CTRL_SS_1000: ++ *speed = 1000; ++ break; ++ default: /* Just pass error back */ ++ return(SOC_E_UNAVAIL); ++ } ++ rv = SOC_E_NONE; ++ } ++ ++ return(rv); ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmiproc_robo_serdes.c b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_robo_serdes.c +new file mode 100755 +index 0000000..add347f +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_robo_serdes.c +@@ -0,0 +1,428 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the serdes ++ * ++ */ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include ++#include ++#include ++#include "bcmiproc_robo_serdes.h" ++#include "bcmiproc_serdes_def.h" ++ ++/* ---- External Variable Declarations ----------------------------------- */ ++/* ---- External Function Prototypes ------------------------------------- */ ++/* ---- Public Variables ------------------------------------------------- */ ++/* ---- Private Constants and Types -------------------------------------- */ ++/* ---- Private Variables ------------------------------------------------ */ ++ ++/* debug/trace */ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) printf args ++#elif defined(BCMDBG_ERR) ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) ++#else ++#define NET_ERROR(args) ++#define NET_TRACE(args) ++#endif /* BCMDBG */ ++#define NET_REG_TRACE(args) ++ ++ ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++ ++/* ==== Public Functions ================================================= */ ++ ++uint16 ++robo_serdes_get_id(robo_info_t *robo, uint page, uint off) ++{ ++ uint16 data; ++ ++ /* read the id high */ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESID_SERDESID0r+off, &data); ++ return data; ++} ++ ++ ++void ++robo_serdes_reset(robo_info_t *robo, uint page) ++{ ++ uint16 ctrl; ++ ++ /* set reset flag */ ++ srab_sgmii_rreg(robo, page, XGXS16G_IEEE0BLK_IEEECONTROL0r, &ctrl); ++ ctrl |= IEEE0BLK_IEEECONTROL0_RST_HW_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_IEEE0BLK_IEEECONTROL0r, &ctrl); ++ udelay(100); ++ /* check if out of reset */ ++ srab_sgmii_rreg(robo, page, XGXS16G_IEEE0BLK_IEEECONTROL0r, &ctrl); ++ if (ctrl & IEEE0BLK_IEEECONTROL0_RST_HW_MASK) { ++ NET_ERROR(("%s page (0x%x) reset not complete\n", __FUNCTION__, page)); ++ } ++} ++ ++ ++int ++robo_serdes_reset_core(robo_info_t *robo, uint page) ++{ ++ uint16 data16; ++ uint16 serdes_id2; ++ ++ /* get serdes id */ ++ serdes_id2 = robo_serdes_get_id(robo, page, 2); ++ printf("%s page(0x%x) id2(0x%x)\n", __FUNCTION__, page, serdes_id2); ++ ++ /* unlock lane */ ++ srab_sgmii_rreg(robo, page, 0x833c, &data16); ++ data16 &= ~(0x0040); ++ srab_sgmii_wreg(robo, page, 0x833c, &data16); ++ ++ if ( page == PAGE_P5_SGMII ) { ++ /* Reset the core */ ++ /* Stop PLL Sequencer and configure the core into correct mode */ ++ data16 = (XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane << ++ XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT) | ++ XGXSBLK0_XGXSCONTROL_HSTL_MASK | ++ XGXSBLK0_XGXSCONTROL_CDET_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_EDEN_MASK | ++ XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_XGXSBLK0_XGXSCONTROLr, &data16); ++ ++ /* Disable IEEE block select auto-detect. ++ * The driver will select desired block as necessary. ++ * By default, the driver keeps the XAUI block in ++ * IEEE address space. ++ */ ++ srab_sgmii_rreg(robo, page, XGXS16G_XGXSBLK0_MISCCONTROL1r, &data16); ++ if (XGXS16G_2p5G_ID(serdes_id2)) { ++ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++ } else { ++ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++ data16 |= XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK; ++ } ++ srab_sgmii_wreg(robo, page, XGXS16G_XGXSBLK0_MISCCONTROL1r, &data16); ++ ++ } ++ return 0; ++} ++ ++ ++int ++robo_serdes_start_pll(robo_info_t *robo, uint page) ++{ ++ uint16 data16; ++ ++ if ( page == PAGE_P5_SGMII ) { ++ uint32 count=250; ++ /* Start PLL Sequencer and wait for PLL to lock */ ++ srab_sgmii_rreg(robo, page, XGXS16G_XGXSBLK0_XGXSCONTROLr, &data16); ++ data16 |= XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_XGXSBLK0_XGXSCONTROLr, &data16); ++ ++ /* wait for PLL to lock */ ++ while (count!=0) { ++ srab_sgmii_rreg(robo, page, XGXS16G_XGXSBLK0_XGXSSTATUSr, &data16); ++ if ( data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK ) { ++ break; ++ } ++ /* wait 1 usec then dec counter */ ++ udelay(10); ++ count--; ++ } ++ if (count == 0) { ++ NET_ERROR(("%s TXPLL did not lock\n", __FUNCTION__)); ++ } ++ } ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * robo_serdes_init ++ * Purpose: ++ * Initialize xgxs6 phys ++ * Parameters: ++ * robo - robo handle ++ * page - port page ++ * Returns: ++ * 0 ++ */ ++int ++robo_serdes_init(robo_info_t *robo, uint page) ++{ ++ uint16 data16; ++ uint16 serdes_id0, serdes_id1, serdes_id2; ++ uint locpage=page; ++ ++ if ( page == PAGE_P4_SGMII ) { ++ printf("%s access page4 via page5 lane1\n", __FUNCTION__); ++ locpage = PAGE_P5_SGMII; ++ // try to access p4 registers via lane1 ++ data16 = 1; ++ srab_sgmii_wreg(robo, locpage, 0xffde, &data16); ++ } ++ ++ /* get serdes id */ ++ serdes_id0 = robo_serdes_get_id(robo, locpage, 0); ++ serdes_id1 = robo_serdes_get_id(robo, locpage, 1); ++ serdes_id2 = robo_serdes_get_id(robo, locpage, 2); ++ printf("%s page(0x%x) id0(0x%x) id1(0x%x) id2(0x%x)\n", __FUNCTION__, locpage, serdes_id0, serdes_id1, serdes_id2); ++ ++ /* get more ids */ ++ srab_sgmii_rreg(robo, locpage, 2, &serdes_id0); ++ srab_sgmii_rreg(robo, locpage, 3, &serdes_id1); ++ //printf("%s locpage(0x%x) SERDES PhyID_MS(0x%x) PhyID_LS(0x%x)\n", __FUNCTION__, locpage, serdes_id0, serdes_id1); ++ ++ /* unlock lane */ ++ srab_sgmii_rreg(robo, locpage, 0x833c, &data16); ++ data16 &= ~(0x0040); ++ srab_sgmii_wreg(robo, locpage, 0x833c, &data16); ++ ++ /* Must Enable TX polarity flip */ ++ srab_sgmii_rreg(robo, locpage, XGXS16G_TX0_TX_ACONTROL0r, &data16); ++ data16 |= TX0_TX_ACONTROL0_TXPOL_FLIP_MASK; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_TX0_TX_ACONTROL0r, &data16); ++ ++ /* disable CL73 BAM */ ++ srab_sgmii_rreg(robo, locpage, 0x8372, &data16); ++ data16 &= ~(CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK); ++ srab_sgmii_wreg(robo, locpage, 0x8372, &data16); ++ ++ /* Set Local Advertising Configuration */ ++ data16 = MII_ANA_C37_FD | MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_COMBO_IEEE0_AUTONEGADVr, &data16); ++ ++ /* Disable BAM in Independent Lane mode. Over1G AN not supported */ ++ data16 = 0; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, &data16); ++ srab_sgmii_wreg(robo, locpage, XGXS16G_BAM_NEXTPAGE_UD_FIELDr, &data16); ++ ++ data16 = SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK | ++ SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK | ++ SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK; ++ ++// data16 |= SERDESDIGITAL_CONTROL1000X1_REMOTE_LOOPBACK_MASK; ++ /* ++ * Put the Serdes in SGMII mode ++ * bit0 = 0; in SGMII mode ++ */ ++ srab_sgmii_wreg(robo, locpage, XGXS16G_SERDESDIGITAL_CONTROL1000X1r, &data16); ++ ++ /* set autoneg */ ++ data16 = MII_CTRL_AE | MII_CTRL_RAN; ++// data16 = MII_CTRL_SS_MSB | MII_CTRL_FD; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_COMBO_IEEE0_MIICNTLr, &data16); ++ ++ /* Disable 10G parallel detect */ ++ data16 = 0; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_AN73_PDET_PARDET10GCONTROLr, &data16); ++ ++ /* Disable BAM mode and Teton mode */ ++ srab_sgmii_wreg(robo, locpage, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, &data16); ++ ++ /* Enable lanes */ ++ srab_sgmii_rreg(robo, locpage, XGXS16G_XGXSBLK1_LANECTRL0r, &data16); ++ data16 |= XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK | ++ XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_XGXSBLK1_LANECTRL0r, &data16); ++ ++ /* set elasticity fifo size to 13.5k to support 12k jumbo pkt size*/ ++ srab_sgmii_rreg(robo, locpage, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ data16 &= SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK; ++ data16 |= (1 << 2); ++ srab_sgmii_wreg(robo, locpage, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ ++ /* Enabble LPI passthru' for native mode EEE */ ++ srab_sgmii_rreg(robo, locpage, XGXS16G_REMOTEPHY_MISC5r, &data16); ++ data16 |= 0xc000; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_REMOTEPHY_MISC5r, &data16); ++ srab_sgmii_rreg(robo, locpage, XGXS16G_XGXSBLK7_EEECONTROLr, &data16); ++ data16 |= 0x0007; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_XGXSBLK7_EEECONTROLr, &data16); ++ ++ if ( page == PAGE_P4_SGMII ) { ++ printf("%s set back to lane0\n", __FUNCTION__); ++ // set back to lane 0 ++ data16 = 0; ++ srab_sgmii_wreg(robo, locpage, 0xffde, &data16); ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * robo_serdes_enable_set ++ * Purpose: ++ * Enable/Disable phy ++ * Parameters: ++ * robo - robo handle ++ * page - port page ++ * enable - on/off state to set ++ * Returns: ++ * 0 ++ */ ++int ++robo_serdes_enable_set(robo_info_t *robo, uint page, int enable) ++{ ++ uint16 data16, mask16; ++ ++ srab_sgmii_rreg(robo, page, XGXS16G_XGXSBLK1_LANECTRL3r, &data16); ++ if (page == PAGE_P5_SGMII) ++ /* lane 0 */ ++ mask16 = 1; /* rx lane */ ++ else ++ /* lane 1 */ ++ mask16 = 2; /* rx lane */ ++ mask16 |= (mask16 << 4); /* add tx lane */ ++ mask16 |= 0x800; ++ if (enable) { ++ data16 &= ~(mask16); ++ } else { ++ data16 &= ~(mask16); ++ data16 |= mask16; ++ } ++ srab_sgmii_wreg(robo, page, XGXS16G_XGXSBLK1_LANECTRL3r, &data16); ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * robo_serdes_speed_set ++ * Purpose: ++ * Set PHY speed ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * speed - link speed in Mbps ++ * Returns: ++ * 0 ++ */ ++int ++robo_serdes_speed_set(robo_info_t *robo, uint page, int speed) ++{ ++ uint16 speed_val, mask; ++ uint16 data16; ++ uint16 speed_mii; ++ ++ if (speed > 1000) { ++ return -1; ++ } ++ ++ speed_val = 0; ++ speed_mii = 0; ++ mask = SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK | ++ SERDESDIGITAL_MISC1_FORCE_SPEED_MASK; ++ ++ switch (speed) { ++ case 0: ++ /* Do not change speed */ ++ return 0; ++ case 10: ++ speed_mii = MII_CTRL_SS_10; ++ break; ++ case 100: ++ speed_mii = MII_CTRL_SS_100; ++ break; ++ case 1000: ++ speed_mii = MII_CTRL_SS_1000; ++ break; ++ default: ++ return -1; ++ } ++ ++ /* Hold rxSeqStart */ ++ srab_sgmii_rreg(robo, page, XGXS16G_RX0_RX_CONTROLr, &data16); ++ data16 |= DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_RX0_RX_CONTROLr, &data16); ++ ++ /* hold TX FIFO in reset */ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ data16 |= SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESDIGITAL_MISC1r, &data16); ++ data16 &= ~(mask); ++ data16 |= speed_val; ++ srab_sgmii_wreg(robo, page, XGXS16G_SERDESDIGITAL_MISC1r, &data16); ++ ++ srab_sgmii_rreg(robo, page, XGXS16G_COMBO_IEEE0_MIICNTLr, &data16); ++ data16 &= ~(MII_CTRL_SS_LSB | MII_CTRL_SS_MSB); ++ data16 |= speed_mii; ++ srab_sgmii_wreg(robo, page, XGXS16G_COMBO_IEEE0_MIICNTLr, &data16); ++ ++ /* release rxSeqStart */ ++ srab_sgmii_rreg(robo, page, XGXS16G_RX0_RX_CONTROLr, &data16); ++ data16 &= ~(DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK); ++ srab_sgmii_wreg(robo, page, XGXS16G_RX0_RX_CONTROLr, &data16); ++ ++ /* release TX FIFO reset */ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ data16 &= ~(SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK); ++ srab_sgmii_wreg(robo, page, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * robo_serdes_speed_get ++ * Purpose: ++ * Get PHY speed ++ * Parameters: ++ * robo - robo handle ++ * page - port page ++ * speed - current link speed in Mbps ++ * Returns: ++ * 0 ++ */ ++int ++robo_serdes_speed_get(robo_info_t *robo, uint page, int *speed) ++{ ++ uint16 data16; ++ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESDIGITAL_STATUS1000X1r, &data16); ++ ++ data16 &= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_MASK; ++ data16 >>= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT; ++ ++ if (data16 == 3) { ++ *speed= 2500; ++ } else if (data16 == 2) { ++ *speed= 1000; ++ } else if (data16 == 1) { ++ *speed= 100; ++ } else { ++ *speed= 10; ++ } ++ ++ return 0; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmiproc_serdes.c b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_serdes.c +new file mode 100755 +index 0000000..0dda6c6 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_serdes.c +@@ -0,0 +1,481 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the serdes ++ * ++ */ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include ++#include "bcmiproc_serdes.h" ++#include "bcmiproc_serdes_def.h" ++#include "../../../mdio/iproc_mdio.h" ++ ++/* ---- External Variable Declarations ----------------------------------- */ ++/* ---- External Function Prototypes ------------------------------------- */ ++/* ---- Public Variables ------------------------------------------------- */ ++/* ---- Private Constants and Types -------------------------------------- */ ++/* ---- Private Variables ------------------------------------------------ */ ++ ++/* debug/trace */ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) printf args ++#elif defined(BCMDBG_ERR) ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) ++#else ++#define NET_ERROR(args) ++#define NET_TRACE(args) ++#endif /* BCMDBG */ ++#define NET_REG_TRACE(args) ++ ++ ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++ ++/* ==== Public Functions ================================================= */ ++ ++void ++serdes_set_blk(uint eth_num, uint phyaddr, uint blk) ++{ ++ uint16 blkaddr; ++ uint16 destblk = (uint16)blk; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s phyaddr(0x%x) blk(0x%x)\n", ++ __FUNCTION__, phyaddr, blk)); ++ ++ /* check if need to update blk addr */ ++ ccb_mii_read(MII_DEV_LOCAL, phyaddr, PHY_REG_BLK_ADDR, &blkaddr); ++ if (blkaddr!=destblk) { ++ /* write block address */ ++ ccb_mii_write(MII_DEV_LOCAL, phyaddr, PHY_REG_BLK_ADDR, destblk); ++ } ++} ++ ++ ++void ++serdes_wr_reg(uint eth_num, uint phyaddr, uint reg, uint data) ++{ ++ uint blk = reg&0x7ff0; ++ uint off = reg&0x000f; ++ uint16 tmpdata=(uint16)data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ if (reg&0x8000) ++ off|=0x10; ++ ++ /* set block address */ ++ serdes_set_blk(eth_num, phyaddr, blk); ++ ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg, tmpdata)); ++ //printf("%s wrt phyaddr(0x%x) reg(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg, tmpdata); ++ /* write register */ ++ ccb_mii_write(MII_DEV_LOCAL, phyaddr, off, tmpdata); ++} ++ ++ ++uint16 ++serdes_rd_reg(uint eth_num, uint phyaddr, uint reg) ++{ ++ uint blk = reg&0x7ff0; ++ uint off = reg&0x000f; ++ uint16 data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ if (reg&0x8000) ++ off|=0x10; ++ ++ /* set block address */ ++ serdes_set_blk(eth_num, phyaddr, blk); ++ ++ /* read register */ ++ ccb_mii_read(MII_DEV_LOCAL, phyaddr, off, &data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg, data)); ++ //printf("%s rd phyaddr(0x%x) reg(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg, data); ++ ++ return data; ++} ++ ++ ++uint16 ++serdes_get_id(uint eth_num, uint phyaddr, uint off) ++{ ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return 0; ++ ++ /* read the id high */ ++ return serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESID_SERDESID0r+off); ++} ++ ++ ++void ++serdes_reset(uint eth_num, uint phyaddr) ++{ ++ uint ctrl; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* set reset flag */ ++ ctrl = serdes_rd_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r); ++ ctrl |= IEEE0BLK_IEEECONTROL0_RST_HW_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r, ctrl); ++ udelay(100); ++ /* check if out of reset */ ++ if (serdes_rd_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r) & IEEE0BLK_IEEECONTROL0_RST_HW_MASK) { ++ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); ++ } ++} ++ ++ ++int ++serdes_reset_core(uint eth_num, uint phyaddr) ++{ ++ uint16 data16; ++ uint16 serdes_id2; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* get serdes id */ ++ serdes_id2 = serdes_get_id(eth_num, phyaddr, 2); ++ printf("et%d %s pbyaddr(0x%x) id2(0x%x)\n", eth_num, __FUNCTION__, phyaddr, serdes_id2); ++ ++ /* unlock lane */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, 0x833c); ++ data16 &= ~(0x0040); ++ serdes_wr_reg(eth_num, phyaddr, 0x833c, data16); ++ ++ if ( phyaddr == 1 ) { ++ /* Reset the core */ ++ /* Stop PLL Sequencer and configure the core into correct mode */ ++ data16 = (XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane << ++ XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT) | ++ XGXSBLK0_XGXSCONTROL_HSTL_MASK | ++ XGXSBLK0_XGXSCONTROL_CDET_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_EDEN_MASK | ++ XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); ++ ++ /* Disable IEEE block select auto-detect. ++ * The driver will select desired block as necessary. ++ * By default, the driver keeps the XAUI block in ++ * IEEE address space. ++ */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_MISCCONTROL1r); ++ if (XGXS16G_2p5G_ID(serdes_id2)) { ++ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++ } else { ++ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++#if !defined(CONFIG_MACH_KT2) ++ data16 |= XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK; ++#endif /* (!defined(CONFIG_MACH_KT2)) */ ++ } ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_MISCCONTROL1r, data16); ++ ++ /* disable in-band MDIO. PHY-443 */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, 0x8111); ++ /* rx_inBandMdio_rst */ ++ data16 |= 1 << 3; ++ serdes_wr_reg(eth_num, phyaddr, 0x8111, data16); ++ } ++ return 0; ++} ++ ++ ++int ++serdes_start_pll(uint eth_num, uint phyaddr) ++{ ++ uint16 data16; ++ ++ if ( phyaddr == 1 ) { ++ uint32 count=250; ++ /* Start PLL Sequencer and wait for PLL to lock */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr); ++ data16 |= XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); ++ ++ /* wait for PLL to lock */ ++ while (count!=0) { ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSSTATUSr); ++ if ( data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK ) { ++ break; ++ } ++ /* wait 1 usec then dec counter */ ++ udelay(10); ++ count--; ++ } ++ if (count == 0) { ++ NET_ERROR(("%s TXPLL did not lock\n", __FUNCTION__)); ++ } ++ } ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * serdes_init ++ * Purpose: ++ * Initialize xgxs6 phys ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * Returns: ++ * 0 ++ */ ++int ++serdes_init(uint eth_num, uint phyaddr) ++{ ++ uint16 data16; ++ uint16 serdes_id0, serdes_id1, serdes_id2; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* get serdes id */ ++ serdes_id0 = serdes_get_id(eth_num, phyaddr, 0); ++ serdes_id1 = serdes_get_id(eth_num, phyaddr, 1); ++ serdes_id2 = serdes_get_id(eth_num, phyaddr, 2); ++ printf("%s pbyaddr(0x%x) id0(0x%x) id1(0x%x) id2(0x%x)\n", __FUNCTION__, phyaddr, serdes_id0, serdes_id1, serdes_id2); ++ ++ /* get more ids */ ++ serdes_id0 = serdes_rd_reg(eth_num, phyaddr, 2); ++ serdes_id1 = serdes_rd_reg(eth_num, phyaddr, 3); ++ //printf("%s pbyaddr(0x%x) SERDES PhyID_MS(0x%x) PhyID_LS(0x%x)\n", __FUNCTION__, phyaddr, serdes_id0, serdes_id1); ++ ++ /* unlock lane */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, 0x833c); ++ data16 &= ~(0x0040); ++ serdes_wr_reg(eth_num, phyaddr, 0x833c, data16); ++ ++ /* disable CL73 BAM */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, 0x8372); ++ data16 &= ~(CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK); ++ serdes_wr_reg(eth_num, phyaddr, 0x8372, data16); ++ ++ /* Set Local Advertising Configuration */ ++ data16 = MII_ANA_C37_FD | MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_AUTONEGADVr, data16); ++ ++ /* Disable BAM in Independent Lane mode. Over1G AN not supported */ ++ data16 = 0; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, data16); ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_UD_FIELDr, data16); ++ ++ data16 = SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK | ++ SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK; ++ /* ++ * Put the Serdes in SGMII mode ++ * bit0 = 0; in SGMII mode ++ */ ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X1r, data16); ++ ++ /* set autoneg */ ++ data16 = MII_CTRL_AE | MII_CTRL_RAN; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr, data16); ++ ++ /* Disable 10G parallel detect */ ++ data16 = 0; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_AN73_PDET_PARDET10GCONTROLr, data16); ++ ++ /* Disable BAM mode and Teton mode */ ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, data16); ++ ++ /* Enable lanes */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL0r); ++ data16 |= XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK | ++ XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL0r, data16); ++ ++ /* set elasticity fifo size to 13.5k to support 12k jumbo pkt size*/ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); ++ data16 &= SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK; ++ data16 |= (1 << 2); ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); ++ ++ /* Enabble LPI passthru' for native mode EEE */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_REMOTEPHY_MISC5r); ++ data16 |= 0xc000; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_REMOTEPHY_MISC5r, data16); ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK7_EEECONTROLr); ++ data16 |= 0x0007; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK7_EEECONTROLr, data16); ++ ++ return 0; ++} ++ ++ ++ ++ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++/* ++ * Function: ++ * serdes_speeddpx_set ++ * Purpose: ++ * Set serdes speed dpx ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * speed - link speed in Mbps ++ * fulldpx - link dpx ++ * Returns: ++ * 0 ++ */ ++int ++serdes_speeddpx_set(uint eth_num, uint phyaddr, int speed, int fulldpx) ++{ ++ uint16 speed_val, mask; ++ uint16 data16; ++ uint16 speed_mii; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ if (speed > 1000) { ++ return -1; ++ } ++ ++ speed_val = 0; ++ speed_mii = 0; ++ mask = SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK | ++ SERDESDIGITAL_MISC1_FORCE_SPEED_MASK; ++ ++ switch (speed) { ++ case 0: ++ /* Do not change speed */ ++ return 0; ++ case 10: ++ speed_mii = MII_CTRL_SS_10; ++ break; ++ case 100: ++ speed_mii = MII_CTRL_SS_100; ++ break; ++ case 1000: ++ speed_mii = MII_CTRL_SS_1000; ++ break; ++ default: ++ return -1; ++ } ++ ++ if (fulldpx) ++ speed_mii |= MII_CTRL_FD; ++ ++ /* Hold rxSeqStart */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr); ++ data16 |= DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr, data16); ++ ++ /* hold TX FIFO in reset */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); ++ data16 |= SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); ++ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r); ++ data16 &= ~(mask); ++ data16 |= speed_val; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r, data16); ++ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr); ++ data16 &= ~(MII_CTRL_AE | MII_CTRL_RAN | MII_CTRL_SS_LSB | MII_CTRL_SS_MSB | MII_CTRL_FD); ++ data16 |= speed_mii; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr, data16); ++ ++ /* release rxSeqStart */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr); ++ data16 &= ~(DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK); ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr, data16); ++ ++ /* release TX FIFO reset */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); ++ data16 &= ~(SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK); ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); ++ ++ return 0; ++} ++ ++int ++serdes_set_asym_mode(uint eth_num, uint phyaddr) ++{ ++ uint16 data16; ++ uint32 txclkctrlreg[] = {0x0000, 0x8065, 0x8075, 0x8085}; ++ uint32 rxclkctrlreg[] = {0x0000, 0x80bc, 0x80cc, 0x80dc}; ++ uint32 spd[] = {0x0000, 0x7120, 0x7120, 0x7110}; ++ uint32 clkctrlmsk[] = {0x0000, 0x0040, 0x0040, 0x0040}; ++ uint32 clkctrlval[] = {0x0000, 0x0040, 0x0040, 0x0000}; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ printk("et%d: %s: setting serdes asymmetrice mode\n", eth_num, __FUNCTION__); ++ ++ /* set speed */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r); ++ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_SERDESDIGITAL_MISC1r); ++ data16 &= 0x0f00; ++ data16 |= spd[phyaddr]; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r, data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_SERDESDIGITAL_MISC1r); ++ ++ /* Enable asymmetric mode */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_TX_LN_SWAP1r); ++ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_TX_LN_SWAP1r); ++ data16 |= 0x0100; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_TX_LN_SWAP1r, data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_TX_LN_SWAP1r); ++ ++ /* set tx clock control bit */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, txclkctrlreg[phyaddr]); ++ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, txclkctrlreg[phyaddr]); ++ data16 &= ~(clkctrlmsk[phyaddr]); ++ data16 |= clkctrlval[phyaddr]; ++ serdes_wr_reg(eth_num, phyaddr, txclkctrlreg[phyaddr], data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, txclkctrlreg[phyaddr]); ++ ++ /* set rx clock control bit */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, rxclkctrlreg[phyaddr]); ++ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, rxclkctrlreg[phyaddr]); ++ data16 &= ~(clkctrlmsk[phyaddr]); ++ data16 |= clkctrlval[phyaddr]; ++ serdes_wr_reg(eth_num, phyaddr, rxclkctrlreg[phyaddr], data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, rxclkctrlreg[phyaddr]); ++ ++ data16 = 0xffff; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL1r, data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_XGXSBLK1_LANECTRL1r); ++ ++ return 0; ++} ++ ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmotp.c b/drivers/bcmdrivers/gmac/src/shared/bcmotp.c +new file mode 100755 +index 0000000..a6c41d4 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmotp.c +@@ -0,0 +1,3791 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * OTP support. ++ * ++ * $Id: bcmotp.c 322632 2012-03-21 05:17:48Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * There are two different OTP controllers so far: ++ * 1. new IPX OTP controller: chipc 21, >=23 ++ * 2. older HND OTP controller: chipc 12, 17, 22 ++ * ++ * Define BCMHNDOTP to include support for the HND OTP controller. ++ * Define BCMIPXOTP to include support for the IPX OTP controller. ++ * ++ * NOTE 1: More than one may be defined ++ * NOTE 2: If none are defined, the default is to include them all. ++ */ ++ ++#if !defined(BCMHNDOTP) && !defined(BCMIPXOTP) ++#define BCMHNDOTP 1 ++#define BCMIPXOTP 1 ++#endif ++ ++#define OTPTYPE_HND(ccrev) ((ccrev) < 21 || (ccrev) == 22) ++#define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23) ++ ++#define OTP_ERR_VAL 0x0001 ++#define OTP_MSG_VAL 0x0002 ++#define OTP_DBG_VAL 0x0004 ++uint32 otp_msg_level = OTP_ERR_VAL; ++ ++#if defined(BCMDBG) || defined(BCMDBG_ERR) ++#define OTP_ERR(args) do {if (otp_msg_level & OTP_ERR_VAL) printf args;} while (0) ++#else ++#define OTP_ERR(args) ++#endif ++ ++#ifdef BCMDBG ++#define OTP_MSG(args) do {if (otp_msg_level & OTP_MSG_VAL) printf args;} while (0) ++#define OTP_DBG(args) do {if (otp_msg_level & OTP_DBG_VAL) printf args;} while (0) ++#else ++#define OTP_MSG(args) ++#define OTP_DBG(args) ++#endif ++ ++#define OTPP_TRIES 10000000 /* # of tries for OTPP */ ++#define OTP_FUSES_PER_BIT 2 ++#define OTP_WRITE_RETRY 16 ++ ++#ifdef BCMIPXOTP ++#define MAXNUMRDES 9 /* Maximum OTP redundancy entries */ ++#endif ++ ++/* OTP common function type */ ++typedef int (*otp_status_t)(void *oh); ++typedef int (*otp_size_t)(void *oh); ++typedef void* (*otp_init_t)(si_t *sih); ++typedef uint16 (*otp_read_bit_t)(void *oh, chipcregs_t *cc, uint off); ++typedef int (*otp_read_region_t)(si_t *sih, int region, uint16 *data, uint *wlen); ++typedef int (*otp_nvread_t)(void *oh, char *data, uint *len); ++typedef int (*otp_write_region_t)(void *oh, int region, uint16 *data, uint wlen); ++typedef int (*otp_cis_append_region_t)(si_t *sih, int region, char *vars, int count); ++typedef int (*otp_lock_t)(si_t *sih); ++typedef int (*otp_nvwrite_t)(void *oh, uint16 *data, uint wlen); ++typedef int (*otp_dump_t)(void *oh, int arg, char *buf, uint size); ++typedef int (*otp_write_word_t)(void *oh, uint wn, uint16 data); ++typedef int (*otp_read_word_t)(void *oh, uint wn, uint16 *data); ++typedef int (*otp_write_bits_t)(void *oh, int bn, int bits, uint8* data); ++ ++/* OTP function struct */ ++typedef struct otp_fn_s { ++ otp_size_t size; ++ otp_read_bit_t read_bit; ++ otp_dump_t dump; ++ otp_status_t status; ++ ++ otp_init_t init; ++ otp_read_region_t read_region; ++ otp_nvread_t nvread; ++ otp_write_region_t write_region; ++ otp_cis_append_region_t cis_append_region; ++ otp_lock_t lock; ++ otp_nvwrite_t nvwrite; ++ otp_write_word_t write_word; ++ otp_read_word_t read_word; ++ ++#if defined(BCMNVRAMW) ++ otp_write_bits_t write_bits; ++#endif ++} otp_fn_t; ++ ++typedef struct { ++ uint ccrev; /* chipc revision */ ++ otp_fn_t *fn; /* OTP functions */ ++ si_t *sih; /* Saved sb handle */ ++ osl_t *osh; ++ ++#ifdef BCMIPXOTP ++ /* IPX OTP section */ ++ uint16 wsize; /* Size of otp in words */ ++ uint16 rows; /* Geometry */ ++ uint16 cols; /* Geometry */ ++ uint32 status; /* Flag bits (lock/prog/rv). ++ * (Reflected only when OTP is power cycled) ++ */ ++ uint16 hwbase; /* hardware subregion offset */ ++ uint16 hwlim; /* hardware subregion boundary */ ++ uint16 swbase; /* software subregion offset */ ++ uint16 swlim; /* software subregion boundary */ ++ uint16 fbase; /* fuse subregion offset */ ++ uint16 flim; /* fuse subregion boundary */ ++ int otpgu_base; /* offset to General Use Region */ ++ uint16 fusebits; /* num of fusebits */ ++ bool buotp; /* Uinified OTP flag */ ++ uint usbmanfid_offset; /* Offset of the usb manfid inside the sdio CIS */ ++ struct { ++ uint8 width; /* entry width in bits */ ++ uint8 val_shift; /* value bit offset in the entry */ ++ uint8 offsets; /* # entries */ ++ uint8 stat_shift; /* valid bit in otpstatus */ ++ uint16 offset[MAXNUMRDES]; /* entry offset in OTP */ ++ } rde_cb; /* OTP redundancy control blocks */ ++ uint16 rde_idx; ++#endif /* BCMIPXOTP */ ++ ++#ifdef BCMHNDOTP ++ /* HND OTP section */ ++ uint size; /* Size of otp in bytes */ ++ uint hwprot; /* Hardware protection bits */ ++ uint signvalid; /* Signature valid bits */ ++ int boundary; /* hw/sw boundary */ ++#endif /* BCMHNDOTP */ ++} otpinfo_t; ++ ++static otpinfo_t otpinfo; ++ ++/* ++ * ROM accessor to avoid struct in shdat ++ */ ++static otpinfo_t * ++get_otpinfo(void) ++{ ++ return (otpinfo_t *)&otpinfo; ++} ++ ++/* ++ * IPX OTP Code ++ * ++ * Exported functions: ++ * ipxotp_status() ++ * ipxotp_size() ++ * ipxotp_init() ++ * ipxotp_read_bit() ++ * ipxotp_read_region() ++ * ipxotp_read_word() ++ * ipxotp_nvread() ++ * ipxotp_write_region() ++ * ipxotp_write_word() ++ * ipxotp_cis_append_region() ++ * ipxotp_lock() ++ * ipxotp_nvwrite() ++ * ipxotp_dump() ++ * ++ * IPX internal functions: ++ * ipxotp_otpr() ++ * _ipxotp_init() ++ * ipxotp_write_bit() ++ * ipxotp_otpwb16() ++ * ipxotp_check_otp_pmu_res() ++ * ipxotp_write_rde() ++ * ipxotp_fix_word16() ++ * ipxotp_check_word16() ++ * ipxotp_max_rgnsz() ++ * ipxotp_otprb16() ++ * ipxotp_uotp_usbmanfid_offset() ++ * ++ */ ++ ++#ifdef BCMIPXOTP ++ ++#define OTPWSIZE 16 /* word size */ ++#define HWSW_RGN(rgn) (((rgn) == OTP_HW_RGN) ? "h/w" : "s/w") ++ ++/* OTP layout */ ++/* CC revs 21, 24 and 27 OTP General Use Region word offset */ ++#define REVA4_OTPGU_BASE 12 ++ ++/* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */ ++#define REVB8_OTPGU_BASE 20 ++ ++/* CC rev 36 OTP General Use Region word offset */ ++#define REV36_OTPGU_BASE 12 ++ ++/* Subregion word offsets in General Use region */ ++#define OTPGU_HSB_OFF 0 ++#define OTPGU_SFB_OFF 1 ++#define OTPGU_CI_OFF 2 ++#define OTPGU_P_OFF 3 ++#define OTPGU_SROM_OFF 4 ++ ++/* Flag bit offsets in General Use region */ ++#define OTPGU_NEWCISFORMAT_OFF 59 ++#define OTPGU_HWP_OFF 60 ++#define OTPGU_SWP_OFF 61 ++#define OTPGU_CIP_OFF 62 ++#define OTPGU_FUSEP_OFF 63 ++#define OTPGU_CIP_MSK 0x4000 ++#define OTPGU_P_MSK 0xf000 ++#define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16) ++ ++/* LOCK but offset */ ++#define OTP_LOCK_ROW1_LOC_OFF 63 /* 1st ROW lock bit */ ++#define OTP_LOCK_ROW2_LOC_OFF 127 /* 2nd ROW lock bit */ ++#define OTP_LOCK_RD_LOC_OFF 128 /* Redundnancy Region lock bit */ ++#define OTP_LOCK_GU_LOC_OFF 129 /* General User Region lock bit */ ++ ++ ++/* OTP Size */ ++#define OTP_SZ_FU_324 ((ROUNDUP(324,8))/8) /* 324 bits */ ++#define OTP_SZ_FU_288 (288/8) /* 288 bits */ ++#define OTP_SZ_FU_216 (216/8) /* 216 bits */ ++#define OTP_SZ_FU_72 (72/8) /* 72 bits */ ++#define OTP_SZ_CHECKSUM (16/8) /* 16 bits */ ++#define OTP4315_SWREG_SZ 178 /* 178 bytes */ ++#define OTP_SZ_FU_144 (144/8) /* 144 bits */ ++#define OTP_SZ_FU_180 ((ROUNDUP(180,8))/8) /* 180 bits */ ++ ++/* OTP BT shared region (pre-allocated) */ ++#define OTP_BT_BASE_4330 (1760/OTPWSIZE) ++#define OTP_BT_END_4330 (1888/OTPWSIZE) ++#define OTP_BT_BASE_4324 (2384/OTPWSIZE) ++#define OTP_BT_END_4324 (2640/OTPWSIZE) ++#define OTP_BT_BASE_4334 (2512/OTPWSIZE) ++#define OTP_BT_END_4334 (2768/OTPWSIZE) ++#define OTP_BT_BASE_4314 (4192/OTPWSIZE) ++#define OTP_BT_END_4314 (4960/OTPWSIZE) ++#define OTP_BT_BASE_4335 (4528/OTPWSIZE) ++#define OTP_BT_END_4335 (5552/OTPWSIZE) ++ ++/* OTP unification */ ++#if defined(USBSDIOUNIFIEDOTP) ++/* USB MANIFID tuple offset in the SDIO CIS in (16-bit) words */ ++#define USB_MANIFID_OFFSET_4319 42 ++#endif /* USBSDIOUNIFIEDOTP */ ++ ++#if defined(BCMNVRAMW) ++/* Local */ ++static int ipxotp_check_otp_pmu_res(chipcregs_t *cc); ++static int ipxotp_write_bit(otpinfo_t *oi, chipcregs_t *cc, uint off); ++static int ipxotp40n_read2x(void *oh, chipcregs_t *cc, uint off); ++static int ipxotp_write_rde_nopc(void *oh, chipcregs_t *cc, int rde, uint bit, uint val); ++#endif ++ ++static int ++ipxotp_status(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return (int)(oi->status); ++} ++ ++/* Return size in bytes */ ++static int ++ipxotp_size(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return (int)oi->wsize * 2; ++} ++ ++static uint16 ++ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ ++ ASSERT(wn < oi->wsize); ++ ASSERT(cc != NULL); ++ ++ return R_REG(oi->osh, &cc->sromotp[wn]); ++} ++ ++static uint16 ++ipxotp_read_bit_common(void *oh, chipcregs_t *cc, uint off) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint k, row, col; ++ uint32 otpp, st; ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ row = off / oi->cols; ++ col = off % oi->cols; ++ ++ otpp = OTPP_START_BUSY | ++ ((((otpwt == OTPL_WRAP_TYPE_40NM)? OTPPOC_READ_40NM : ++ OTPPOC_READ) << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x", ++ __FUNCTION__, off, row, col, otpp)); ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return 0xffff; ++ } ++ if (st & OTPP_READERR) { ++ OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__, off)); ++ return 0xffff; ++ } ++ st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT; ++ ++ OTP_DBG((" => %d\n", st)); ++ return (int)st; ++} ++ ++static uint16 ++ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ W_REG(oi->osh, &cc->otpcontrol, 0); ++ W_REG(oi->osh, &cc->otpcontrol1, 0); ++ ++ return ipxotp_read_bit_common(oh, cc, off); ++} ++ ++/* ++ * OTP BT region size ++ */ ++static void ++ipxotp_bt_region_get(otpinfo_t *oi, uint16 *start, uint16 *end) ++{ ++ *start = *end = 0; ++ switch (CHIPID(oi->sih->chip)) { ++ case BCM4330_CHIP_ID: ++ *start = OTP_BT_BASE_4330; ++ *end = OTP_BT_END_4330; ++ break; ++ case BCM4324_CHIP_ID: ++ *start = OTP_BT_BASE_4324; ++ *end = OTP_BT_END_4324; ++ break; ++ case BCM4334_CHIP_ID: ++ *start = OTP_BT_BASE_4334; ++ *end = OTP_BT_END_4334; ++ break; ++ case BCM4314_CHIP_ID: ++ case BCM43142_CHIP_ID: ++ *start = OTP_BT_BASE_4314; ++ *end = OTP_BT_END_4314; ++ break; ++ case BCM4335_CHIP_ID: ++ *start = OTP_BT_BASE_4335; ++ *end = OTP_BT_END_4335; ++ break; ++ } ++} ++ ++/* Calculate max HW/SW region byte size by substracting fuse region and checksum size, ++ * osizew is oi->wsize (OTP size - GU size) in words ++ */ ++static int ++ipxotp_max_rgnsz(otpinfo_t *oi) ++{ ++ int osizew = oi->wsize; ++ int ret = 0; ++ uint16 checksum; ++ uint idx; ++ chipcregs_t *cc; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ checksum = OTP_SZ_CHECKSUM; ++ ++ /* for new chips, fusebit is available from cc register */ ++ if (oi->sih->ccrev >= 35) { ++ oi->fusebits = R_REG(oi->osh, &cc->otplayoutextension) & OTPLAYOUTEXT_FUSE_MASK; ++ oi->fusebits = ROUNDUP(oi->fusebits, 8); ++ oi->fusebits >>= 3; /* bytes */ ++ } ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ switch (CHIPID(oi->sih->chip)) { ++ case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: ++ case BCM43239_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_288; ++ break; ++ case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID: ++ case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43421_CHIP_ID: ++ case BCM43226_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_72; ++ break; ++ case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID: ++ case BCM43237_CHIP_ID: ++ case BCM43234_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_324; ++ break; ++ case BCM4325_CHIP_ID: ++ case BCM5356_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_216; ++ break; ++ case BCM4336_CHIP_ID: ++ case BCM43362_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_144; ++ break; ++ case BCM4313_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_72; ++ break; ++ case BCM4330_CHIP_ID: ++ case BCM4334_CHIP_ID: ++ case BCM4314_CHIP_ID: ++ case BCM43142_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_144; ++ break; ++ case BCM4319_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_180; ++ break; ++ case BCM4331_CHIP_ID: ++ case BCM43431_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_72; ++ break; ++ case BCM43131_CHIP_ID: ++ case BCM43217_CHIP_ID: ++ case BCM43227_CHIP_ID: ++ case BCM43228_CHIP_ID: ++ case BCM43428_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_72; ++ break; ++ default: ++ if (oi->fusebits == 0) ++ ASSERT(0); /* Don't konw about this chip */ ++ } ++ ++ ret = osizew*2 - oi->fusebits - checksum; ++ ++ if (CHIPID(oi->sih->chip) == BCM4315_CHIP_ID) { ++ ret = OTP4315_SWREG_SZ; ++ } ++ ++ OTP_MSG(("max region size %d bytes\n", ret)); ++ return ret; ++} ++ ++/* ++ * OTP sizes for 65nm and 130nm ++ */ ++static int ++ipxotp_otpsize_set_65nm(otpinfo_t *oi, uint otpsz) ++{ ++ /* Check for otp size */ ++ switch (otpsz) { ++ case 1: /* 32x64 */ ++ oi->rows = 32; ++ oi->cols = 64; ++ oi->wsize = 128; ++ break; ++ case 2: /* 64x64 */ ++ oi->rows = 64; ++ oi->cols = 64; ++ oi->wsize = 256; ++ break; ++ case 5: /* 96x64 */ ++ oi->rows = 96; ++ oi->cols = 64; ++ oi->wsize = 384; ++ break; ++ case 7: /* 16x64 */ /* 1024 bits */ ++ oi->rows = 16; ++ oi->cols = 64; ++ oi->wsize = 64; ++ break; ++ default: ++ /* Don't know the geometry */ ++ OTP_ERR(("%s: unknown OTP geometry\n", __FUNCTION__)); ++ } ++ ++ return 0; ++} ++ ++/* ++ * OTP sizes for 40nm ++ */ ++static int ++ipxotp_otpsize_set_40nm(otpinfo_t *oi, uint otpsz) ++{ ++ /* Check for otp size */ ++ switch (otpsz) { ++ case 1: /* 64x32: 2048 bits */ ++ oi->rows = 64; ++ oi->cols = 32; ++ break; ++ case 2: /* 96x32: 3072 bits */ ++ oi->rows = 96; ++ oi->cols = 32; ++ break; ++ case 3: /* 128x32: 4096 bits */ ++ oi->rows = 128; ++ oi->cols = 32; ++ break; ++ case 4: /* 160x32: 5120 bits */ ++ oi->rows = 160; ++ oi->cols = 32; ++ break; ++ case 5: /* 192x32: 6144 bits */ ++ oi->rows = 192; ++ oi->cols = 32; ++ break; ++ case 7: /* 256x32: 8192 bits */ ++ oi->rows = 256; ++ oi->cols = 32; ++ break; ++ default: ++ /* Don't know the geometry */ ++ OTP_ERR(("%s: unknown OTP geometry\n", __FUNCTION__)); ++ } ++ ++ oi->wsize = (oi->cols * oi->rows)/OTPWSIZE; ++ return 0; ++} ++ ++/* OTP unification */ ++#if defined(USBSDIOUNIFIEDOTP) && defined(BCMNVRAMW) ++static void ++ipxotp_uotp_usbmanfid_offset(otpinfo_t *oi) ++{ ++ OTP_DBG(("%s: chip=0x%x\n", __FUNCTION__, CHIPID(oi->sih->chip))); ++ switch (CHIPID(oi->sih->chip)) { ++ /* Add cases for supporting chips */ ++ case BCM4319_CHIP_ID: ++ oi->usbmanfid_offset = USB_MANIFID_OFFSET_4319; ++ oi->buotp = TRUE; ++ break; ++ default: ++ OTP_ERR(("chip=0x%x does not support Unified OTP.\n", ++ CHIPID(oi->sih->chip))); ++ break; ++ } ++} ++#endif /* USBSDIOUNIFIEDOTP && BCMNVRAMW */ ++ ++static void ++BCMNMIATTACHFN(_ipxotp_init)(otpinfo_t *oi, chipcregs_t *cc) ++{ ++ uint k; ++ uint32 otpp, st; ++ uint16 btsz, btbase = 0, btend = 0; ++ uint otpwt; ++ ++ /* record word offset of General Use Region for various chipcommon revs */ ++ if (oi->sih->ccrev >= 40) { ++ /* FIX: Available in rev >= 23; Verify before applying to others */ ++ oi->otpgu_base = (R_REG(oi->osh, &cc->otplayout) & OTPL_HWRGN_OFF_MASK) ++ >> OTPL_HWRGN_OFF_SHIFT; ++ ASSERT((oi->otpgu_base - (OTPGU_SROM_OFF * OTPWSIZE)) > 0); ++ oi->otpgu_base >>= 4; /* words */ ++ oi->otpgu_base -= OTPGU_SROM_OFF; ++ } else if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24 || oi->sih->ccrev == 27) { ++ oi->otpgu_base = REVA4_OTPGU_BASE; ++ } else if ((oi->sih->ccrev == 36) || (oi->sih->ccrev == 39)) { ++ /* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */ ++ if (oi->wsize >= 128) ++ oi->otpgu_base = REVB8_OTPGU_BASE; ++ else ++ oi->otpgu_base = REV36_OTPGU_BASE; ++ } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) { ++ oi->otpgu_base = REVB8_OTPGU_BASE; ++ } else { ++ OTP_ERR(("%s: chipc rev %d not supported\n", __FUNCTION__, oi->sih->ccrev)); ++ } ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt != OTPL_WRAP_TYPE_40NM) { ++ /* First issue an init command so the status is up to date */ ++ otpp = OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK); ++ ++ OTP_DBG(("%s: otpp = 0x%x", __FUNCTION__, otpp)); ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return; ++ } ++ } ++ ++ /* Read OTP lock bits and subregion programmed indication bits */ ++ oi->status = R_REG(oi->osh, &cc->otpstatus); ++ ++ if ((CHIPID(oi->sih->chip) == BCM43222_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43111_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43112_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43224_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43225_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43421_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43226_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43236_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43235_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43234_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43238_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43237_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43239_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM4324_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM4335_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43526_CHIP_ID) || ++ 0) { ++ uint32 p_bits; ++ p_bits = (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) & OTPGU_P_MSK) ++ >> OTPGU_P_SHIFT; ++ oi->status |= (p_bits << OTPS_GUP_SHIFT); ++ } ++ OTP_DBG(("%s: status 0x%x\n", __FUNCTION__, oi->status)); ++ ++ /* OTP unification */ ++ oi->buotp = FALSE; /* Initialize it to false, until its explicitely set true. */ ++ oi->usbmanfid_offset = 0; ++#if defined(USBSDIOUNIFIEDOTP) && defined(BCMNVRAMW) ++ ipxotp_uotp_usbmanfid_offset(oi); ++#endif /* USBSDIOUNIFIEDOTP && BCMNVRAMW */ ++ if ((oi->status & (OTPS_GUP_HW | OTPS_GUP_SW)) == (OTPS_GUP_HW | OTPS_GUP_SW)) { ++ switch (CHIPID(oi->sih->chip)) { ++ /* Add cases for supporting chips */ ++ case BCM4319_CHIP_ID: ++ oi->buotp = TRUE; ++ break; ++ default: ++ OTP_ERR(("chip=0x%x does not support Unified OTP.\n", ++ CHIPID(oi->sih->chip))); ++ break; ++ } ++ } ++ ++ /* ++ * h/w region base and fuse region limit are fixed to the top and ++ * the bottom of the general use region. Everything else can be flexible. ++ */ ++ oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF; ++ oi->hwlim = oi->wsize; ++ oi->flim = oi->wsize; ++ ++ ipxotp_bt_region_get(oi, &btbase, &btend); ++ btsz = btend - btbase; ++ if (btsz > 0) { ++ /* default to not exceed BT base */ ++ oi->hwlim = btbase; ++ ++ /* With BT shared region, swlim and fbase are fixed */ ++ oi->swlim = btbase; ++ oi->fbase = btend; ++ } ++ ++ /* Update hwlim and swbase */ ++ if (oi->status & OTPS_GUP_HW) { ++ OTP_DBG(("%s: hw region programmed\n", __FUNCTION__)); ++ oi->hwlim = ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16; ++ oi->swbase = oi->hwlim; ++ } else ++ oi->swbase = oi->hwbase; ++ ++ /* Update swlim and fbase only if no BT region */ ++ if (btsz == 0) { ++ /* subtract fuse and checksum from beginning */ ++ oi->swlim = ipxotp_max_rgnsz(oi) / 2; ++ ++ if (oi->status & OTPS_GUP_SW) { ++ OTP_DBG(("%s: sw region programmed\n", __FUNCTION__)); ++ oi->swlim = ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16; ++ oi->fbase = oi->swlim; ++ } ++ else ++ oi->fbase = oi->swbase; ++ } ++ ++ OTP_DBG(("%s: OTP limits---\n" ++ "hwbase %d/%d hwlim %d/%d\n" ++ "swbase %d/%d swlim %d/%d\n" ++ "fbase %d/%d flim %d/%d\n", __FUNCTION__, ++ oi->hwbase, oi->hwbase * 16, oi->hwlim, oi->hwlim * 16, ++ oi->swbase, oi->swbase * 16, oi->swlim, oi->swlim * 16, ++ oi->fbase, oi->fbase * 16, oi->flim, oi->flim * 16)); ++} ++ ++static void * ++BCMNMIATTACHFN(ipxotp_init)(si_t *sih) ++{ ++ uint idx, otpsz, otpwt; ++ chipcregs_t *cc; ++ otpinfo_t *oi = NULL; ++ ++ OTP_MSG(("%s: Use IPX OTP controller\n", __FUNCTION__)); ++ ++ /* Make sure we're running IPX OTP */ ++ ASSERT(OTPTYPE_IPX(sih->ccrev)); ++ if (!OTPTYPE_IPX(sih->ccrev)) ++ return NULL; ++ ++ /* Make sure OTP is not disabled */ ++ if (si_is_otp_disabled(sih)) { ++ OTP_MSG(("%s: OTP is disabled\n", __FUNCTION__)); ++#if !defined(WLTEST) ++ return NULL; ++#endif ++ } ++ ++ /* Make sure OTP is powered up */ ++ if (!si_is_otp_powered(sih)) { ++ OTP_ERR(("%s: OTP is powered down\n", __FUNCTION__)); ++ return NULL; ++ } ++ ++ /* Retrieve OTP region info */ ++ idx = si_coreidx(sih); ++ cc = si_setcoreidx(sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ otpsz = (sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT; ++ if (otpsz == 0) { ++ OTP_ERR(("%s: No OTP\n", __FUNCTION__)); ++ goto exit; ++ } ++ ++ oi = get_otpinfo(); ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt == OTPL_WRAP_TYPE_40NM) { ++ ipxotp_otpsize_set_40nm(oi, otpsz); ++ } else if (otpwt == OTPL_WRAP_TYPE_65NM) { ++ ipxotp_otpsize_set_65nm(oi, otpsz); ++ } else { ++ OTP_ERR(("%s: Unknown wrap type: %d\n", __FUNCTION__, otpwt)); ++ ASSERT(0); ++ } ++ ++ OTP_MSG(("%s: rows %u cols %u wsize %u\n", __FUNCTION__, oi->rows, oi->cols, oi->wsize)); ++ ++#ifdef BCMNVRAMW ++ /* Initialize OTP redundancy control blocks */ ++ if (sih->ccrev >= 40) { ++ uint16 offset[] = {269, 286, 303, 333, 350, 367, 397, 414, 431}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 17; ++ oi->rde_cb.val_shift = 13; ++ oi->rde_cb.stat_shift = 16; ++ } else if (sih->ccrev == 36) { ++ uint16 offset[] = {141, 158, 175}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 15; ++ oi->rde_cb.val_shift = 13; ++ oi->rde_cb.stat_shift = 16; ++ } else if (sih->ccrev == 21 || sih->ccrev == 24) { ++ uint16 offset[] = {64, 79, 94, 109, 128, 143, 158, 173}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 15; ++ oi->rde_cb.val_shift = 11; ++ oi->rde_cb.stat_shift = 16; ++ } ++ else if (sih->ccrev == 27) { ++ uint16 offset[] = {128, 143, 158, 173}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 15; ++ oi->rde_cb.val_shift = 11; ++ oi->rde_cb.stat_shift = 20; ++ } ++ else { ++ uint16 offset[] = {141, 158, 175, 205, 222, 239, 269, 286, 303}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 17; ++ oi->rde_cb.val_shift = 13; ++ oi->rde_cb.stat_shift = 16; ++ } ++ ASSERT(oi->rde_cb.offsets <= MAXNUMRDES); ++ /* Initialize global rde index */ ++ oi->rde_idx = 0; ++#endif /* BCMNVRAMW */ ++ ++ _ipxotp_init(oi, cc); ++ ++exit: ++ si_setcoreidx(sih, idx); ++ ++ return (void *)oi; ++} ++ ++static int ++ipxotp_read_region(void *oh, int region, uint16 *data, uint *wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ uint base, i, sz; ++ ++ /* Validate region selection */ ++ switch (region) { ++ case OTP_HW_RGN: ++ /* OTP unification: For unified OTP sz=flim-hwbase */ ++ if (oi->buotp) ++ sz = (uint)oi->flim - oi->hwbase; ++ else ++ sz = (uint)oi->hwlim - oi->hwbase; ++ if (!(oi->status & OTPS_GUP_HW)) { ++ OTP_ERR(("%s: h/w region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small, should be at least %u\n", ++ __FUNCTION__, oi->hwlim - oi->hwbase)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->hwbase; ++ break; ++ case OTP_SW_RGN: ++ /* OTP unification: For unified OTP sz=flim-swbase */ ++ if (oi->buotp) ++ sz = ((uint)oi->flim - oi->swbase); ++ else ++ sz = ((uint)oi->swlim - oi->swbase); ++ if (!(oi->status & OTPS_GUP_SW)) { ++ OTP_ERR(("%s: s/w region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small should be at least %u\n", ++ __FUNCTION__, oi->swlim - oi->swbase)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->swbase; ++ break; ++ case OTP_CI_RGN: ++ sz = OTPGU_CI_SZ; ++ if (!(oi->status & OTPS_GUP_CI)) { ++ OTP_ERR(("%s: chipid region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small, should be at least %u\n", ++ __FUNCTION__, OTPGU_CI_SZ)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->otpgu_base + OTPGU_CI_OFF; ++ break; ++ case OTP_FUSE_RGN: ++ sz = (uint)oi->flim - oi->fbase; ++ if (!(oi->status & OTPS_GUP_FUSE)) { ++ OTP_ERR(("%s: fuse region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small, should be at least %u\n", ++ __FUNCTION__, oi->flim - oi->fbase)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->fbase; ++ break; ++ case OTP_ALL_RGN: ++ sz = ((uint)oi->flim - oi->hwbase); ++ if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) { ++ OTP_ERR(("%s: h/w & s/w region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small, should be at least %u\n", ++ __FUNCTION__, oi->hwlim - oi->hwbase)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->hwbase; ++ break; ++ default: ++ OTP_ERR(("%s: reading region %d is not supported\n", __FUNCTION__, region)); ++ return BCME_BADARG; ++ } ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Read the data */ ++ for (i = 0; i < sz; i ++) ++ data[i] = ipxotp_otpr(oh, cc, base + i); ++ ++ si_setcoreidx(oi->sih, idx); ++ *wlen = sz; ++ return 0; ++} ++ ++static int ++ipxotp_read_word(void *oh, uint wn, uint16 *data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Read the data */ ++ *data = ipxotp_otpr(oh, cc, wn); ++ ++ si_setcoreidx(oi->sih, idx); ++ return 0; ++} ++ ++static int ++ipxotp_nvread(void *oh, char *data, uint *len) ++{ ++ return BCME_UNSUPPORTED; ++} ++ ++#ifdef BCMNVRAMW ++static int ++ipxotp_writable(otpinfo_t *oi, chipcregs_t *cc) ++{ ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt == OTPL_WRAP_TYPE_40NM) { ++ uint i, k, row, col; ++ uint32 otpp, st; ++ uint cols[4] = {15, 4, 8, 13}; ++ ++ row = 0; ++ for (i = 0; i < 4; i++) { ++ col = cols[i]; ++ ++ otpp = OTPP_START_BUSY | ++ ((OTPPOC_PROG_ENABLE_40NM << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: row = %d, col = %d, otpp = 0x%x\n", ++ __FUNCTION__, row, col, otpp)); ++ ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && ++ (k < OTPP_TRIES); k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", ++ __FUNCTION__, st, k)); ++ return -1; ++ } ++ } ++ ++ /* wait till OTP Program mode is unlocked */ ++ for (k = 0; ++ (!((st = R_REG(oi->osh, &cc->otpstatus)) & OTPS_PROGOK)) && ++ (k < OTPP_TRIES); k ++) ++ ; ++ OTP_MSG(("\n%s: OTP Program status: %x\n", __FUNCTION__, st)); ++ ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: OTP Program mode is still locked, OTP is unwritable\n", ++ __FUNCTION__)); ++ return -1; ++ } ++ } ++ ++ OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN); ++ return 0; ++} ++ ++static int ++ipxotp_unwritable(otpinfo_t *oi, chipcregs_t *cc) ++{ ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt == OTPL_WRAP_TYPE_40NM) { ++ uint k, row, col; ++ uint32 otpp, st; ++ ++ row = 0; ++ col = 0; ++ ++ otpp = OTPP_START_BUSY | ++ ((OTPPOC_PROG_DISABLE_40NM << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: row = %d, col = %d, otpp = 0x%x\n", ++ __FUNCTION__, row, col, otpp)); ++ ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return -1; ++ } ++ ++ /* wait till OTP Program mode is unlocked */ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpstatus)) & OTPS_PROGOK) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ OTP_MSG(("\n%s: OTP Program status: %x\n", __FUNCTION__, st)); ++ ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: OTP Program mode is still unlocked, OTP is writable\n", ++ __FUNCTION__)); ++ return -1; ++ } ++ } ++ ++ AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN); ++ return 0; ++} ++ ++static int ++ipxotp_write_bit_common(otpinfo_t *oi, chipcregs_t *cc, uint off) ++{ ++ uint k, row, col; ++ uint32 otpp, st; ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ row = off / oi->cols; ++ col = off % oi->cols; ++ ++ otpp = OTPP_START_BUSY | ++ ((1 << OTPP_VALUE_SHIFT) & OTPP_VALUE_MASK) | ++ ((((otpwt == OTPL_WRAP_TYPE_40NM)? OTPPOC_BIT_PROG_40NM : ++ OTPPOC_BIT_PROG) << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x\n", ++ __FUNCTION__, off, row, col, otpp)); ++ ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++ipxotp40n_read2x(void *oh, chipcregs_t *cc, uint off) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ ++ W_REG(oi->osh, &cc->otpcontrol, ++ (OTPC_40NM_PCOUNT_V1X << OTPC_40NM_PCOUNT_SHIFT) | ++ (OTPC_40NM_REGCSEL_DEF << OTPC_40NM_REGCSEL_SHIFT) | ++ (1 << OTPC_40NM_PROGIN_SHIFT) | ++ (1 << OTPC_40NM_R2X_SHIFT) | ++ (1 << OTPC_40NM_ODM_SHIFT) | ++ (1 << OTPC_40NM_DF_SHIFT) | ++ (OTPC_40NM_VSEL_R1X << OTPC_40NM_VSEL_SHIFT) | ++ (1 << OTPC_40NM_COFAIL_SHIFT)); ++ ++ W_REG(oi->osh, &cc->otpcontrol1, ++ (OTPC1_CPCSEL_DEF << OTPC1_CPCSEL_SHIFT) | ++ (OTPC1_TM_R1X << OTPC1_TM_SHIFT)); ++ ++ return ipxotp_read_bit_common(oh, cc, off); ++} ++ ++static int ++ipxotp40n_read1x(void *oh, chipcregs_t *cc, uint off, uint fuse) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ ++ W_REG(oi->osh, &cc->otpcontrol, ++ (fuse << OTPC_40NM_PROGSEL_SHIFT) | ++ (OTPC_40NM_PCOUNT_V1X << OTPC_40NM_PCOUNT_SHIFT) | ++ (OTPC_40NM_REGCSEL_DEF << OTPC_40NM_REGCSEL_SHIFT) | ++ (1 << OTPC_40NM_PROGIN_SHIFT) | ++ (0 << OTPC_40NM_R2X_SHIFT) | ++ (1 << OTPC_40NM_ODM_SHIFT) | ++ (1 << OTPC_40NM_DF_SHIFT) | ++ (OTPC_40NM_VSEL_R1X << OTPC_40NM_VSEL_SHIFT) | ++ (1 << OTPC_40NM_COFAIL_SHIFT)); ++ W_REG(oi->osh, &cc->otpcontrol1, ++ (OTPC1_CPCSEL_DEF << OTPC1_CPCSEL_SHIFT) | ++ (OTPC1_TM_R1X << OTPC1_TM_SHIFT)); ++ ++ return ipxotp_read_bit_common(oh, cc, off); ++} ++ ++static int ++ipxotp40n_verify1x(void *oh, chipcregs_t *cc, uint off, uint fuse) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ ++ W_REG(oi->osh, &cc->otpcontrol, ++ (fuse << OTPC_40NM_PROGSEL_SHIFT) | ++ (OTPC_40NM_PCOUNT_V1X << OTPC_40NM_PCOUNT_SHIFT) | ++ (OTPC_40NM_REGCSEL_DEF << OTPC_40NM_REGCSEL_SHIFT) | ++ (1 << OTPC_40NM_PROGIN_SHIFT) | ++ (0 << OTPC_40NM_R2X_SHIFT) | ++ (1 << OTPC_40NM_ODM_SHIFT) | ++ (1 << OTPC_40NM_DF_SHIFT) | ++ (OTPC_40NM_VSEL_V1X << OTPC_40NM_VSEL_SHIFT) | ++ (1 << OTPC_40NM_COFAIL_SHIFT)); ++ W_REG(oi->osh, &cc->otpcontrol1, ++ (OTPC1_CPCSEL_DEF << OTPC1_CPCSEL_SHIFT) | ++ (OTPC1_TM_V1X << OTPC1_TM_SHIFT)); ++ ++ return ipxotp_read_bit_common(oh, cc, off); ++} ++ ++static int ++ipxotp40n_write_fuse(otpinfo_t *oi, chipcregs_t *cc, uint off, uint fuse) ++{ ++ W_REG(oi->osh, &cc->otpcontrol, ++ (fuse << OTPC_40NM_PROGSEL_SHIFT) | ++ (OTPC_40NM_PCOUNT_WR << OTPC_40NM_PCOUNT_SHIFT) | ++ (OTPC_40NM_REGCSEL_DEF << OTPC_40NM_REGCSEL_SHIFT) | ++ (1 << OTPC_40NM_PROGIN_SHIFT) | ++ (0 << OTPC_40NM_R2X_SHIFT) | ++ (1 << OTPC_40NM_ODM_SHIFT) | ++ (0 << OTPC_40NM_DF_SHIFT) | ++ (OTPC_40NM_VSEL_WR << OTPC_40NM_VSEL_SHIFT) | ++ (1 << OTPC_40NM_COFAIL_SHIFT) | ++ OTPC_PROGEN); ++ ++ W_REG(oi->osh, &cc->otpcontrol1, ++ (OTPC1_CPCSEL_DEF << OTPC1_CPCSEL_SHIFT) | ++ (OTPC1_TM_WR << OTPC1_TM_SHIFT)); ++ ++ return ipxotp_write_bit_common(oi, cc, off); ++} ++ ++static int ++ipxotp40n_write_bit(otpinfo_t *oi, chipcregs_t *cc, uint off) ++{ ++ uint32 oc_orig, oc1_orig; ++ uint8 i, j, err = 0; ++ int verr0, verr1, rerr0, rerr1, retry, val; ++ ++ oc_orig = R_REG(oi->osh, &cc->otpcontrol); ++ oc1_orig = R_REG(oi->osh, &cc->otpcontrol1); ++ ++ for (i = 0; i < OTP_FUSES_PER_BIT; i++) { ++ retry = 0; ++ for (j = 0; j < OTP_WRITE_RETRY; j++) { ++ /* program fuse */ ++ ipxotp40n_write_fuse(oi, cc, off, i); ++ ++ /* verify fuse */ ++ val = ipxotp40n_verify1x(oi, cc, off, i); ++ if (val == 1) ++ break; ++ ++ retry++; ++ } ++ ++ if ((val != 1) && (j == OTP_WRITE_RETRY)) { ++ OTP_ERR(("ERROR: New write failed max attempts fuse:%d @ off:%d\n", ++ i, off)); ++ } else if (retry > 0) ++ OTP_MSG(("Verify1x multi retries:%d fuse:%d @ off:%d\n", ++ retry, i, off)); ++ } ++ ++ /* Post screen */ ++ verr0 = (ipxotp40n_verify1x(oi, cc, off, 0) == 1) ? TRUE : FALSE; ++ verr1 = (ipxotp40n_verify1x(oi, cc, off, 1) == 1) ? TRUE : FALSE; ++ rerr0 = (ipxotp40n_read1x(oi, cc, off, 0) == 1) ? TRUE : FALSE; ++ rerr1 = (ipxotp40n_read1x(oi, cc, off, 1) == 1) ? TRUE : FALSE; ++ ++ if (verr0 && verr1) { ++ OTP_MSG(("V0:%d and V1:%d ok off:%d\n", verr0, verr1, off)); ++ } else if (verr0 && rerr1) { ++ OTP_MSG(("V0:%d and R1:%d ok off:%d\n", verr0, rerr1, off)); ++ } else if (rerr0 && verr1) { ++ OTP_MSG(("R0:%d and V1:%d ok off:%d\n", rerr0, verr1, off)); ++ } else { ++ OTP_ERR(("Bit failed post screen v0:%d v1:%d r0:%d r1:%d off:%d\n", ++ verr0, verr1, rerr0, rerr1, off)); ++ err = -1; ++ } ++ ++ W_REG(oi->osh, &cc->otpcontrol, oc_orig); ++ W_REG(oi->osh, &cc->otpcontrol1, oc1_orig); ++ ++ return err; ++} ++ ++#ifdef OTP_DEBUG ++int ++otp_read1x(void *oh, uint off, uint fuse) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ chipcregs_t *cc; ++ uint idx, otpwt; ++ int val = 0; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ if ((otpwt != OTPL_WRAP_TYPE_40NM) || (oi->sih->ccrev < 40)) ++ goto exit; ++ ++ val = ipxotp40n_read1x(oi, cc, off, fuse); ++ ++exit: ++ si_setcoreidx(oi->sih, idx); ++ return val; ++} ++ ++int ++otp_verify1x(void *oh, uint off, uint fuse) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int err = 0; ++ chipcregs_t *cc; ++ uint idx, otpwt; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ if ((otpwt != OTPL_WRAP_TYPE_40NM) || (oi->sih->ccrev < 40)) ++ goto exit; ++ ++ err = ipxotp40n_verify1x(oi, cc, off, fuse); ++ if (err != 1) ++ OTP_ERR(("v1x failed fuse:%d @ off:%d\n", fuse, off)); ++exit: ++ si_setcoreidx(oi->sih, idx); ++ return err; ++} ++ ++/* ++ * Repair is to fix damaged bits; not intended to fix programming errors ++ * This is limited and for 4334 only nine repair entries available ++ */ ++int ++otp_repair_bit(void *oh, uint off, uint val) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return ipxotp_write_rde(oi, -1, off, val); ++} ++ ++int ++otp_write_ones_old(void *oh, uint off, uint bits) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ uint32 i; ++ ++ if (off < 0 || off + bits > oi->rows * oi->cols) ++ return BCME_RANGE; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ W_REG(oi->osh, &cc->otpcontrol, 0); ++ W_REG(oi->osh, &cc->otpcontrol1, 0); ++ ++ ipxotp_writable(oi, cc); ++ for (i = 0; i < bits; i++) { ++ ipxotp_write_bit_common(oi, cc, off++); ++ } ++ ipxotp_unwritable(oi, cc); ++ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ return BCME_OK; ++} ++ ++int ++otp_write_ones(void *oh, uint off, uint bits) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ uint32 i; ++ int err; ++ ++ if (off < 0 || off + bits > oi->rows * oi->cols) ++ return BCME_RANGE; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ ipxotp_writable(oi, cc); ++ for (i = 0; i < bits; i++) { ++ err = ipxotp_write_bit(oi, cc, off); ++ if (err != 0) { ++ OTP_ERR(("%s: write bit failed: %d\n", __FUNCTION__, off)); ++ ++ err = ipxotp_write_rde_nopc(oi, cc, ++ ipxotp_check_otp_pmu_res(cc), off, 1); ++ if (err != 0) ++ OTP_ERR(("%s: repair bit failed: %d\n", __FUNCTION__, off)); ++ else ++ OTP_ERR(("%s: repair bit ok: %d\n", __FUNCTION__, off)); ++ } ++ ++ off++; ++ } ++ ipxotp_unwritable(oi, cc); ++ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ return BCME_OK; ++} ++ ++#endif /* OTP_DEBUG */ ++ ++static int ++ipxotp_write_bit(otpinfo_t *oi, chipcregs_t *cc, uint off) ++{ ++ uint otpwt; ++ int status = 0; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt == OTPL_WRAP_TYPE_40NM) { ++ /* Can damage fuse in 40nm so safeguard against reprogramming */ ++ if (ipxotp40n_read2x(oi, cc, off) != 1) { ++ status = ipxotp40n_write_bit(oi, cc, off); ++ } else { ++ OTP_MSG(("Bit already programmed: %d\n", off)); ++ } ++ } else { ++ W_REG(oi->osh, &cc->otpcontrol, 0); ++ W_REG(oi->osh, &cc->otpcontrol1, 0); ++ ++ status = ipxotp_write_bit_common(oi, cc, off); ++ } ++ ++ return status; ++} ++ ++static int ++ipxotp_write_bits(void *oh, int bn, int bits, uint8* data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ int i, j; ++ uint8 temp; ++ int err; ++ ++ if (bn < 0 || bn + bits > oi->rows * oi->cols) ++ return BCME_RANGE; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ ipxotp_writable(oi, cc); ++ for (i = 0; i < bits; ) { ++ temp = *data++; ++ for (j = 0; j < 8; j++, i++) { ++ if (i >= bits) ++ break; ++ if (temp & 0x01) ++ { ++ if (ipxotp_write_bit(oi, cc, (uint)(i + bn)) != 0) { ++ OTP_ERR(("%s: write bit failed: %d\n", ++ __FUNCTION__, i + bn)); ++ ++ err = ipxotp_write_rde_nopc(oi, cc, ++ ipxotp_check_otp_pmu_res(cc), i + bn, 1); ++ if (err != 0) { ++ OTP_ERR(("%s: repair bit failed: %d\n", ++ __FUNCTION__, i + bn)); ++ AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN); ++ return -1; ++ } else ++ OTP_ERR(("%s: repair bit ok: %d\n", ++ __FUNCTION__, i + bn)); ++ } ++ } ++ temp >>= 1; ++ } ++ } ++ ipxotp_unwritable(oi, cc); ++ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ return BCME_OK; ++} ++ ++ ++static int ++ipxotp_write_lock_bit(otpinfo_t *oi, chipcregs_t *cc, uint off) ++{ ++ uint k, row, col; ++ uint32 otpp, st; ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ row = off / oi->cols; ++ col = off % oi->cols; ++ ++ otpp = OTPP_START_BUSY | ++ ((((otpwt == OTPL_WRAP_TYPE_40NM)? OTPPOC_ROW_LOCK_40NM : ++ OTPPOC_ROW_LOCK) << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x\n", ++ __FUNCTION__, off, row, col, otpp)); ++ ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++ipxotp_otpwb16(otpinfo_t *oi, chipcregs_t *cc, int wn, uint16 data) ++{ ++ uint base, i; ++ int rc = 0; ++ ++ base = wn * 16; ++ for (i = 0; i < 16; i++) { ++ if (data & (1 << i)) { ++ rc = ipxotp_write_bit(oi, cc, base + i); ++ if (rc != 0) { ++ OTP_ERR(("%s: write bit failed:%d\n", __FUNCTION__, base + i)); ++ ++ rc = ipxotp_write_rde_nopc(oi, cc, ++ ipxotp_check_otp_pmu_res(cc), base + i, 1); ++ if (rc != 0) { ++ OTP_ERR(("%s: repair bit failed:%d\n", ++ __FUNCTION__, base + i)); ++ break; ++ } else ++ OTP_ERR(("%s: repair bit ok:%d\n", __FUNCTION__, base + i)); ++ } ++ } ++ } ++ ++ return rc; ++} ++ ++/* Write OTP redundancy entry: ++ * rde - redundancy entry index (-ve for "next") ++ * bit - bit offset ++ * val - bit value ++ */ ++ ++/* Check if for a particular chip OTP PMU resource is available */ ++static int ++ipxotp_check_otp_pmu_res(chipcregs_t *cc) ++{ ++ switch (cc->chipid & 0x0000ffff) { ++ case BCM43131_CHIP_ID: ++ case BCM43217_CHIP_ID: ++ case BCM43227_CHIP_ID: ++ case BCM43228_CHIP_ID: ++ /* OTP PMU resource not available, hence use global rde index */ ++ return OTP_GLOBAL_RDE_IDX; ++ default: ++ /* OTP PMU resource available, hence calculate rde index */ ++ return -1; ++ } ++ return -1; ++} ++ ++/* Assumes already writable and bypasses power-cycling */ ++static int ++ipxotp_write_rde_nopc(void *oh, chipcregs_t *cc, int rde, uint bit, uint val) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint i, temp; ++ int err = BCME_OK; ++ ++#ifdef BCMDBG ++ if ((rde >= (int)oi->rde_cb.offsets) || (bit >= (uint)(oi->rows * oi->cols)) || (val > 1)) ++ return BCME_RANGE; ++#endif ++ ++ if (rde < 0) { ++ for (rde = 0; rde < oi->rde_cb.offsets - 1; rde++) { ++ if ((oi->status & (1 << (oi->rde_cb.stat_shift + rde))) == 0) ++ break; ++ } ++ OTP_ERR(("%s: Auto rde index %d\n", __FUNCTION__, rde)); ++ } ++ else if (rde == OTP_GLOBAL_RDE_IDX) { ++ /* Chips which do not have a OTP PMU res, OTP can't be pwr cycled from the drv. */ ++ /* Hence we need to have a count of the global rde, and populate accordingly. */ ++ ++ /* Find the next available rde location */ ++ while (oi->status & (1 << (oi->rde_cb.stat_shift + oi->rde_idx))) { ++ OTP_MSG(("%s: rde %d already in use, status 0x%08x\n", __FUNCTION__, ++ rde, oi->status)); ++ oi->rde_idx++; ++ } ++ rde = oi->rde_idx++; ++ ++ if (rde >= MAXNUMRDES) { ++ OTP_MSG(("%s: No rde location available to fix.\n", __FUNCTION__)); ++ return BCME_ERROR; ++ } ++ } ++ ++ if (oi->status & (1 << (oi->rde_cb.stat_shift + rde))) { ++ OTP_ERR(("%s: rde %d already in use, status 0x%08x\n", __FUNCTION__, ++ rde, oi->status)); ++ return BCME_ERROR; ++ } ++ ++ temp = ~(~0 << oi->rde_cb.width) & ++ ((~0 << (oi->rde_cb.val_shift + 1)) | (val << oi->rde_cb.val_shift) | bit); ++ ++ OTP_MSG(("%s: rde %d bit %d val %d bmp 0x%08x\n", __FUNCTION__, rde, bit, val, temp)); ++ ++ for (i = 0; i < oi->rde_cb.width; i ++) { ++ if (!(temp & (1 << i))) ++ continue; ++ if (ipxotp_write_bit(oi, cc, oi->rde_cb.offset[rde] + i) != 0) ++ err = BCME_ERROR; ++ } ++ ++ /* no power-cyclying to just set status */ ++ oi->status |= (1 << (oi->rde_cb.stat_shift + rde)); ++ ++ return err; ++} ++ ++int ++ipxotp_write_rde(void *oh, int rde, uint bit, uint val) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ int err; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Enable Write */ ++ ipxotp_writable(oi, cc); ++ ++ err = ipxotp_write_rde_nopc(oh, cc, rde, bit, val); ++ ++ /* Disable Write */ ++ ipxotp_unwritable(oi, cc); ++ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ return err; ++} ++ ++/* Set up redundancy entries for the specified bits */ ++static int ++ipxotp_fix_word16(void *oh, uint wn, uint16 mask, uint16 val, chipcregs_t *cc) ++{ ++ otpinfo_t *oi; ++ uint bit; ++ int rc = 0; ++ ++ oi = (otpinfo_t *)oh; ++ ++ ASSERT(oi != NULL); ++ ASSERT(wn < oi->wsize); ++ ++ for (bit = wn * 16; mask; bit++, mask >>= 1, val >>= 1) { ++ if (mask & 1) { ++ if ((rc = ipxotp_write_rde(oi, ipxotp_check_otp_pmu_res(cc), bit, val & 1))) ++ break; ++ } ++ } ++ ++ return rc; ++} ++ ++static int ++ipxotp_check_word16(void *oh, chipcregs_t *cc, uint wn, uint16 val) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint16 word = ipxotp_otpr(oi, cc, wn); ++ int rc = 0; ++ ++ if ((word ^= val)) { ++ OTP_MSG(("%s: word %d is 0x%04x, wanted 0x%04x, fixing...\n", ++ __FUNCTION__, wn, (word ^ val), val)); ++ ++ if ((rc = ipxotp_fix_word16(oi, wn, word, val, cc))) { ++ OTP_ERR(("FAILED, ipxotp_fix_word16 returns %d\n", rc)); ++ /* Fatal error, unfixable. MFGC will have to fail. Board ++ * needs to be discarded!! ++ */ ++ return BCME_NORESOURCE; ++ } ++ } ++ ++ return BCME_OK; ++} ++ ++/* expects the caller to disable interrupts before calling this routine */ ++static int ++ipxotp_write_region(void *oh, int region, uint16 *data, uint wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ uint base, i; ++ int otpgu_bit_base; ++ bool rewrite = FALSE; ++ int rc = 0; ++#if defined(DONGLEBUILD) ++ uint16 *origdata = NULL; ++#endif /* DONGLEBUILD */ ++ ++ otpgu_bit_base = oi->otpgu_base * 16; ++ ++ /* Validate region selection */ ++ switch (region) { ++ case OTP_HW_RGN: ++ if (wlen > (uint)(oi->hwlim - oi->hwbase)) { ++ OTP_ERR(("%s: wlen %u exceeds OTP h/w region limit %u\n", ++ __FUNCTION__, wlen, oi->hwlim - oi->hwbase)); ++ return BCME_BUFTOOLONG; ++ } ++ rewrite = !!(oi->status & OTPS_GUP_HW); ++ base = oi->hwbase; ++ break; ++ case OTP_SW_RGN: ++ if (wlen > (uint)(oi->swlim - oi->swbase)) { ++ OTP_ERR(("%s: wlen %u exceeds OTP s/w region limit %u\n", ++ __FUNCTION__, wlen, oi->swlim - oi->swbase)); ++ return BCME_BUFTOOLONG; ++ } ++ rewrite = !!(oi->status & OTPS_GUP_SW); ++ base = oi->swbase; ++ break; ++ case OTP_CI_RGN: ++ if (oi->status & OTPS_GUP_CI) { ++ OTP_ERR(("%s: chipid region has been programmed\n", __FUNCTION__)); ++ return BCME_ERROR; ++ } ++ if (wlen > OTPGU_CI_SZ) { ++ OTP_ERR(("%s: wlen %u exceeds OTP ci region limit %u\n", ++ __FUNCTION__, wlen, OTPGU_CI_SZ)); ++ return BCME_BUFTOOLONG; ++ } ++ if ((wlen == OTPGU_CI_SZ) && (data[OTPGU_CI_SZ - 1] & OTPGU_P_MSK) != 0) { ++ OTP_ERR(("%s: subregion programmed bits not zero\n", __FUNCTION__)); ++ return BCME_BADARG; ++ } ++ base = oi->otpgu_base + OTPGU_CI_OFF; ++ break; ++ case OTP_FUSE_RGN: ++ if (oi->status & OTPS_GUP_FUSE) { ++ OTP_ERR(("%s: fuse region has been programmed\n", __FUNCTION__)); ++ return BCME_ERROR; ++ } ++ if (wlen > (uint)(oi->flim - oi->fbase)) { ++ OTP_ERR(("%s: wlen %u exceeds OTP ci region limit %u\n", ++ __FUNCTION__, wlen, oi->flim - oi->fbase)); ++ return BCME_BUFTOOLONG; ++ } ++ base = oi->flim - wlen; ++ break; ++ default: ++ OTP_ERR(("%s: writing region %d is not supported\n", __FUNCTION__, region)); ++ return BCME_ERROR; ++ } ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++#if defined(DONGLEBUILD) ++ /* Check for conflict; Since some bits might be programmed at ATE time, we need to ++ * avoid redundancy by clearing already written bits, but copy original for verification. ++ */ ++ if ((origdata = (uint16*)MALLOC(oi->osh, wlen * 2)) == NULL) { ++ rc = BCME_NOMEM; ++ goto exit; ++ } ++ for (i = 0; i < wlen; i++) { ++ origdata[i] = data[i]; ++ data[i] = ipxotp_otpr(oi, cc, base + i); ++ if (data[i] & ~origdata[i]) { ++ OTP_ERR(("%s: %s region: word %d incompatible (0x%04x->0x%04x)\n", ++ __FUNCTION__, HWSW_RGN(region), i, data[i], origdata[i])); ++ rc = BCME_BADARG; ++ goto exit; ++ } ++ data[i] ^= origdata[i]; ++ } ++#endif /* DONGLEBUILD */ ++ ++ OTP_MSG(("%s: writing new bits in %s region\n", __FUNCTION__, HWSW_RGN(region))); ++ ++ /* Enable Write */ ++ ipxotp_writable(oi, cc); ++ ++ /* Write the data */ ++ for (i = 0; i < wlen; i++) { ++ rc = ipxotp_otpwb16(oi, cc, base + i, data[i]); ++ if (rc != 0) { ++ OTP_ERR(("%s: otpwb16 failed: %d 0x%x\n", __FUNCTION__, base + i, data[i])); ++ ipxotp_unwritable(oi, cc); ++ goto exit; ++ } ++ } ++ ++ /* One time set region flag: Update boundary/flag in memory and in OTP */ ++ if (!rewrite) { ++ switch (region) { ++ case OTP_HW_RGN: ++ /* OTP unification */ ++ if (oi->buotp) { ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, ++ ((base + oi->usbmanfid_offset) * 16)); ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_SWP_OFF); ++ } else ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, ++ (base + i) * 16); ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_HWP_OFF); ++ if (CHIPID(oi->sih->chip) == BCM4336_CHIP_ID || ++ CHIPID(oi->sih->chip) == BCM43362_CHIP_ID || ++ CHIPID(oi->sih->chip) == BCM4324_CHIP_ID) ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_NEWCISFORMAT_OFF); ++ break; ++ case OTP_SW_RGN: ++ /* Write HW region limit as well */ ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, base * 16); ++ /* write max swlim(covert to bits) to the sw/fuse boundary */ ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF, oi->swlim * 16); ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_SWP_OFF); ++ break; ++ case OTP_CI_RGN: ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_CIP_OFF); ++ /* Also set the OTPGU_CIP_MSK bit in the input so verification ++ * doesn't fail ++ */ ++ if (wlen >= OTPGU_CI_SZ) ++ data[OTPGU_CI_SZ - 1] |= OTPGU_CIP_MSK; ++ break; ++ case OTP_FUSE_RGN: ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF, base * 16); ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_FUSEP_OFF); ++ break; ++ } ++ } ++ ++ /* Disable Write */ ++ ipxotp_unwritable(oi, cc); ++ ++ /* Sync region info by retrieving them again (use PMU bit to power cycle OTP) */ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ ++ /* Check and fix for region size and region programmed bits */ ++ if (!rewrite) { ++ uint16 boundary_off = 0, boundary_val = 0; ++ uint16 programmed_off = 0; ++ uint16 bit = 0; ++ ++ switch (region) { ++ case OTP_HW_RGN: ++ boundary_off = OTPGU_HSB_OFF; ++ /* OTP unification */ ++ if (oi->buotp) { ++ boundary_val = ((base + oi->usbmanfid_offset) * 16); ++ } else ++ boundary_val = (base + i) * 16; ++ programmed_off = OTPGU_HWP_OFF; ++ break; ++ case OTP_SW_RGN: ++ /* Also write 0 to HW region boundary */ ++ if ((rc = ipxotp_check_word16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, ++ base * 16))) ++ goto exit; ++ boundary_off = OTPGU_SFB_OFF; ++ boundary_val = oi->swlim * 16; ++ programmed_off = OTPGU_SWP_OFF; ++ break; ++ case OTP_CI_RGN: ++ /* No CI region boundary */ ++ programmed_off = OTPGU_CIP_OFF; ++ break; ++ case OTP_FUSE_RGN: ++ boundary_off = OTPGU_SFB_OFF; ++ boundary_val = base * 16; ++ programmed_off = OTPGU_FUSEP_OFF; ++ break; ++ } ++ ++ /* Do the actual checking and return BCME_NORESOURCE if we cannot fix */ ++ if ((region != OTP_CI_RGN) && ++ (rc = ipxotp_check_word16(oi, cc, oi->otpgu_base + boundary_off, ++ boundary_val))) { ++ goto exit; ++ } ++ ++ if ((bit = ipxotp_read_bit(oh, cc, otpgu_bit_base + programmed_off)) == 0xffff) { ++ OTP_ERR(("\n%s: FAILED bit %d reads %d\n", __FUNCTION__, otpgu_bit_base + ++ programmed_off, bit)); ++ goto exit; ++ } else if (bit == 0) { /* error detected, fix it */ ++ OTP_ERR(("\n%s: FAILED bit %d reads %d, fixing\n", __FUNCTION__, ++ otpgu_bit_base + programmed_off, bit)); ++ if ((rc = ipxotp_write_rde(oi, ipxotp_check_otp_pmu_res(cc), ++ otpgu_bit_base + programmed_off, 1))) { ++ OTP_ERR(("\n%s: cannot fix, ipxotp_write_rde returns %d\n", ++ __FUNCTION__, rc)); ++ goto exit; ++ } ++ } ++ } ++ ++ /* Update status, apply WAR */ ++ _ipxotp_init(oi, cc); ++ ++#if defined(DONGLEBUILD) ++ /* Recover original data... */ ++ if (origdata) ++ bcopy(origdata, data, wlen * 2); ++#endif /* DONGLEBUILD */ ++ ++ /* ...Check again so we can verify and fix where possible */ ++ for (i = 0; i < wlen; i++) { ++ if ((rc = ipxotp_check_word16(oi, cc, base + i, data[i]))) ++ goto exit; ++ } ++ ++exit: ++#if defined(DONGLEBUILD) ++ if (origdata) ++ MFREE(oi->osh, origdata, wlen * 2); ++#endif /* DONGLEBUILD */ ++ si_setcoreidx(oi->sih, idx); ++ return rc; ++} ++ ++static int ++ipxotp_write_word(void *oh, uint wn, uint16 data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int rc = 0; ++ uint16 origdata; ++ uint idx; ++ chipcregs_t *cc; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Check for conflict */ ++ origdata = data; ++ data = ipxotp_otpr(oi, cc, wn); ++ if (data & ~origdata) { ++ OTP_ERR(("%s: word %d incompatible (0x%04x->0x%04x)\n", ++ __FUNCTION__, wn, data, origdata)); ++ rc = BCME_BADARG; ++ goto exit; ++ } ++ data ^= origdata; ++ ++ /* Enable Write */ ++ ipxotp_writable(oi, cc); ++ ++ rc = ipxotp_otpwb16(oi, cc, wn, data); ++ ++ /* Disable Write */ ++ ipxotp_unwritable(oi, cc); ++ ++ data = origdata; ++ if ((rc = ipxotp_check_word16(oi, cc, wn, data))) ++ goto exit; ++exit: ++ si_setcoreidx(oi->sih, idx); ++ return rc; ++} ++ ++static int ++ipxotp_cis_append_region(si_t *sih, int region, char *vars, int count) ++{ ++ uint8 *cis; ++ osl_t *osh; ++ uint sz = OTP_SZ_MAX/2; /* size in words */ ++ int rc = 0; ++ bool newchip = FALSE; ++ uint overwrite = 0; ++ ++ ASSERT(region == OTP_HW_RGN || region == OTP_SW_RGN); ++ ++ osh = si_osh(sih); ++ if ((cis = MALLOC(osh, OTP_SZ_MAX)) == NULL) { ++ return BCME_ERROR; ++ } ++ ++ bzero(cis, OTP_SZ_MAX); ++ ++ rc = otp_read_region(sih, region, (uint16 *)cis, &sz); ++ newchip = (rc == BCME_NOTFOUND) ? TRUE : FALSE; ++ if ((rc != 0) && (rc != BCME_NOTFOUND)) { ++ return BCME_ERROR; ++ } ++ rc = 0; ++ ++ /* zero count for read, non-zero count for write */ ++ if (count) { ++ int i = 0, newlen = 0; ++ ++ if (newchip) { ++ int termw_len = 0; /* length of termination word */ ++ ++ /* convert halfwords to bytes offset */ ++ newlen = sz * 2; ++ ++ if ((CHIPID(sih->chip) == BCM4322_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43231_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4315_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4319_CHIP_ID)) { ++ /* bootloader WAR, refer to above twiki link */ ++ cis[newlen-1] = 0x00; ++ cis[newlen-2] = 0xff; ++ cis[newlen-3] = 0x00; ++ cis[newlen-4] = 0xff; ++ cis[newlen-5] = 0xff; ++ cis[newlen-6] = 0x1; ++ cis[newlen-7] = 0x2; ++ termw_len = 7; ++ } else { ++ cis[newlen-1] = 0xff; ++ cis[newlen-2] = 0xff; ++ termw_len = 2; ++ } ++ ++ if (count >= newlen - termw_len) { ++ OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", newlen, count)); ++ rc = BCME_BUFTOOLONG; ++ } ++ } else { ++ int end = 0; ++ if (region == OTP_SW_RGN) { ++ /* Walk through the leading zeros (could be 0 or 8 bytes for now) */ ++ for (i = 0; i < (int)sz*2; i++) ++ if (cis[i] != 0) ++ break; ++ } else { ++ /* move pass the hardware header */ ++ if (sih->ccrev >= 36) { ++ uint32 otp_layout; ++ otp_layout = si_corereg(sih, SI_CC_IDX, ++ OFFSETOF(chipcregs_t, otplayout), 0, 0); ++ if (otp_layout & OTP_CISFORMAT_NEW) { ++ i += 4; /* new sdio header format, 2 half words */ ++ } else { ++ i += 8; /* old sdio header format */ ++ } ++ } else { ++ return BCME_ERROR; /* old chip, not suppported */ ++ } ++ } ++ ++ /* Find the place to append */ ++ for (; i < (int)sz*2; i++) { ++ int j; ++ if (cis[i] == 0) ++ break; ++ /* If the tuple exist, check if it can be overwritten */ ++ if (cis[i + 2] == vars[2]) { ++ if (cis[i+1] == vars[1]) { ++ /* found, check if it is compiatable for fix */ ++ for (j = 0; j < cis[i+1] + 2; j++) { ++ if ((cis[i+j] ^ vars[j]) & cis[i+j]) { ++ break; ++ } ++ } ++ if (j == cis[i+1] + 2) { ++ overwrite = i; ++ } ++ } ++ } ++ i += ((int)cis[i+1] + 1); ++ } ++ for (end = i; end < (int)sz*2; end++) { ++ if (cis[end] != 0) ++ break; ++ } ++ if (overwrite) ++ i = overwrite; ++ ++ newlen = i + count; ++ if (newlen & 1) /* make it even-sized buffer */ ++ newlen++; ++ ++ if (newlen >= (end - 1)) { ++ OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", end-i, count)); ++ rc = BCME_BUFTOOLONG; ++ } ++ } ++ ++ /* copy the buffer */ ++ memcpy(&cis[i], vars, count); ++#ifdef BCMNVRAMW ++ /* Write the buffer back */ ++ if (!rc) ++ rc = otp_write_region(sih, region, (uint16*)cis, newlen/2); ++ ++ /* Print the buffer */ ++ OTP_MSG(("Buffer of size %d bytes to write:\n", newlen)); ++ for (i = 0; i < newlen; i++) { ++ OTP_DBG(("%02x ", cis[i] & 0xff)); ++ if ((i % 16) == 15) { ++ OTP_DBG(("\n")); ++ } ++ } ++ OTP_MSG(("\n")); ++#endif /* BCMNVRAMW */ ++ } ++ if (cis) ++ MFREE(osh, cis, OTP_SZ_MAX); ++ ++ return (rc); ++} ++ ++/* No need to lock for IPXOTP */ ++static int ++ipxotp_lock(void *oh) ++{ ++ uint idx; ++ chipcregs_t *cc; ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int err = 0, rc = 0; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Enable Write */ ++ ipxotp_writable(oi, cc); ++ ++ err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_ROW1_LOC_OFF); ++ if (err) { ++ OTP_ERR(("fail to lock ROW1\n")); ++ rc = -1; ++ } ++ err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_ROW2_LOC_OFF); ++ if (err) { ++ OTP_ERR(("fail to lock ROW2\n")); ++ rc = -2; ++ } ++ err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_RD_LOC_OFF); ++ if (err) { ++ OTP_ERR(("fail to lock RD\n")); ++ rc = -3; ++ } ++ err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_GU_LOC_OFF); ++ if (err) { ++ OTP_ERR(("fail to lock GU\n")); ++ rc = -4; ++ } ++ ++ /* Disable Write */ ++ ipxotp_unwritable(oi, cc); ++ ++ /* Sync region info by retrieving them again (use PMU bit to power cycle OTP) */ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ ++ /* Update status, apply WAR */ ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return rc; ++} ++ ++static int ++ipxotp_nvwrite(void *oh, uint16 *data, uint wlen) ++{ ++ return -1; ++} ++#endif /* BCMNVRAMW */ ++ ++#if defined(WLTEST) && !defined(BCMROMBUILD) ++static uint16 ++ipxotp_otprb16(void *oh, chipcregs_t *cc, uint wn) ++{ ++ uint base, i; ++ uint16 val; ++ uint16 bit; ++ ++ base = wn * 16; ++ ++ val = 0; ++ for (i = 0; i < 16; i++) { ++ if ((bit = ipxotp_read_bit(oh, cc, base + i)) == 0xffff) ++ break; ++ val = val | (bit << i); ++ } ++ if (i < 16) ++ val = 0xffff; ++ ++ return val; ++} ++ ++static int ++ipxotp_dump(void *oh, int arg, char *buf, uint size) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ chipcregs_t *cc; ++ uint idx, i, count; ++ uint16 val; ++ struct bcmstrbuf b; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ count = ipxotp_size(oh); ++ ++ bcm_binit(&b, buf, size); ++ for (i = 0; i < count / 2; i++) { ++ if (!(i % 4)) ++ bcm_bprintf(&b, "\n0x%04x:", 2 * i); ++ if (arg == 0) ++ val = ipxotp_otpr(oh, cc, i); ++ else ++ val = ipxotp_otprb16(oi, cc, i); ++ bcm_bprintf(&b, " 0x%04x", val); ++ } ++ bcm_bprintf(&b, "\n"); ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return ((int)(b.buf - b.origbuf)); ++} ++#endif ++ ++static otp_fn_t ipxotp_fn = { ++ (otp_size_t)ipxotp_size, ++ (otp_read_bit_t)ipxotp_read_bit, ++ (otp_dump_t)NULL, /* Assigned in otp_init */ ++ (otp_status_t)ipxotp_status, ++ ++ (otp_init_t)ipxotp_init, ++ (otp_read_region_t)ipxotp_read_region, ++ (otp_nvread_t)ipxotp_nvread, ++#ifdef BCMNVRAMW ++ (otp_write_region_t)ipxotp_write_region, ++ (otp_cis_append_region_t)ipxotp_cis_append_region, ++ (otp_lock_t)ipxotp_lock, ++ (otp_nvwrite_t)ipxotp_nvwrite, ++ (otp_write_word_t)ipxotp_write_word, ++#else /* BCMNVRAMW */ ++ (otp_write_region_t)NULL, ++ (otp_cis_append_region_t)NULL, ++ (otp_lock_t)NULL, ++ (otp_nvwrite_t)NULL, ++ (otp_write_word_t)NULL, ++#endif /* BCMNVRAMW */ ++ (otp_read_word_t)ipxotp_read_word, ++#if defined(BCMNVRAMW) ++ (otp_write_bits_t)ipxotp_write_bits ++#endif ++}; ++ ++#endif /* BCMIPXOTP */ ++ ++ ++/* ++ * HND OTP Code ++ * ++ * Exported functions: ++ * hndotp_status() ++ * hndotp_size() ++ * hndotp_init() ++ * hndotp_read_bit() ++ * hndotp_read_region() ++ * hndotp_read_word() ++ * hndotp_nvread() ++ * hndotp_write_region() ++ * hndotp_cis_append_region() ++ * hndotp_lock() ++ * hndotp_nvwrite() ++ * hndotp_dump() ++ * ++ * HND internal functions: ++ * hndotp_otpr() ++ * hndotp_otproff() ++ * hndotp_write_bit() ++ * hndotp_write_word() ++ * hndotp_valid_rce() ++ * hndotp_write_rce() ++ * hndotp_write_row() ++ * hndotp_otprb16() ++ * ++ */ ++ ++#ifdef BCMHNDOTP ++ ++/* Fields in otpstatus */ ++#define OTPS_PROGFAIL 0x80000000 ++#define OTPS_PROTECT 0x00000007 ++#define OTPS_HW_PROTECT 0x00000001 ++#define OTPS_SW_PROTECT 0x00000002 ++#define OTPS_CID_PROTECT 0x00000004 ++#define OTPS_RCEV_MSK 0x00003f00 ++#define OTPS_RCEV_SHIFT 8 ++ ++/* Fields in the otpcontrol register */ ++#define OTPC_RECWAIT 0xff000000 ++#define OTPC_PROGWAIT 0x00ffff00 ++#define OTPC_PRW_SHIFT 8 ++#define OTPC_MAXFAIL 0x00000038 ++#define OTPC_VSEL 0x00000006 ++#define OTPC_SELVL 0x00000001 ++ ++/* OTP regions (Word offsets from otp size) */ ++#define OTP_SWLIM_OFF (-4) ++#define OTP_CIDBASE_OFF 0 ++#define OTP_CIDLIM_OFF 4 ++ ++/* Predefined OTP words (Word offset from otp size) */ ++#define OTP_BOUNDARY_OFF (-4) ++#define OTP_HWSIGN_OFF (-3) ++#define OTP_SWSIGN_OFF (-2) ++#define OTP_CIDSIGN_OFF (-1) ++#define OTP_CID_OFF 0 ++#define OTP_PKG_OFF 1 ++#define OTP_FID_OFF 2 ++#define OTP_RSV_OFF 3 ++#define OTP_LIM_OFF 4 ++#define OTP_RD_OFF 4 /* Redundancy row starts here */ ++#define OTP_RC0_OFF 28 /* Redundancy control word 1 */ ++#define OTP_RC1_OFF 32 /* Redundancy control word 2 */ ++#define OTP_RC_LIM_OFF 36 /* Redundancy control word end */ ++ ++#define OTP_HW_REGION OTPS_HW_PROTECT ++#define OTP_SW_REGION OTPS_SW_PROTECT ++#define OTP_CID_REGION OTPS_CID_PROTECT ++ ++#if OTP_HW_REGION != OTP_HW_RGN ++#error "incompatible OTP_HW_RGN" ++#endif ++#if OTP_SW_REGION != OTP_SW_RGN ++#error "incompatible OTP_SW_RGN" ++#endif ++#if OTP_CID_REGION != OTP_CI_RGN ++#error "incompatible OTP_CI_RGN" ++#endif ++ ++/* Redundancy entry definitions */ ++#define OTP_RCE_ROW_SZ 6 ++#define OTP_RCE_SIGN_MASK 0x7fff ++#define OTP_RCE_ROW_MASK 0x3f ++#define OTP_RCE_BITS 21 ++#define OTP_RCE_SIGN_SZ 15 ++#define OTP_RCE_BIT0 1 ++ ++#define OTP_WPR 4 ++#define OTP_SIGNATURE 0x578a ++#define OTP_MAGIC 0x4e56 ++ ++static int ++hndotp_status(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return ((int)(oi->hwprot | oi->signvalid)); ++} ++ ++static int ++hndotp_size(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return ((int)(oi->size)); ++} ++ ++static uint16 ++hndotp_otpr(void *oh, chipcregs_t *cc, uint wn) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ osl_t *osh; ++ volatile uint16 *ptr; ++ ++ ASSERT(wn < ((oi->size / 2) + OTP_RC_LIM_OFF)); ++ ASSERT(cc != NULL); ++ ++ osh = si_osh(oi->sih); ++ ++ ptr = (volatile uint16 *)((volatile char *)cc + CC_SROM_OTP); ++ return (R_REG(osh, &ptr[wn])); ++} ++ ++static uint16 ++hndotp_otproff(void *oh, chipcregs_t *cc, int woff) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ osl_t *osh; ++ volatile uint16 *ptr; ++ ++ ASSERT(woff >= (-((int)oi->size / 2))); ++ ASSERT(woff < OTP_LIM_OFF); ++ ASSERT(cc != NULL); ++ ++ osh = si_osh(oi->sih); ++ ++ ptr = (volatile uint16 *)((volatile char *)cc + CC_SROM_OTP); ++ ++ return (R_REG(osh, &ptr[(oi->size / 2) + woff])); ++} ++ ++static uint16 ++hndotp_read_bit(void *oh, chipcregs_t *cc, uint idx) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint k, row, col; ++ uint32 otpp, st; ++ osl_t *osh; ++ ++ osh = si_osh(oi->sih); ++ row = idx / 65; ++ col = idx % 65; ++ ++ otpp = OTPP_START_BUSY | OTPP_READ | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ (col & OTPP_COL_MASK); ++ ++ OTP_DBG(("%s: idx = %d, row = %d, col = %d, otpp = 0x%x", __FUNCTION__, ++ idx, row, col, otpp)); ++ ++ W_REG(osh, &cc->otpprog, otpp); ++ st = R_REG(osh, &cc->otpprog); ++ for (k = 0; ((st & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES); k++) ++ st = R_REG(osh, &cc->otpprog); ++ ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return 0xffff; ++ } ++ if (st & OTPP_READERR) { ++ OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__, idx)); ++ return 0xffff; ++ } ++ st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT; ++ OTP_DBG((" => %d\n", st)); ++ return (uint16)st; ++} ++ ++static void * ++BCMNMIATTACHFN(hndotp_init)(si_t *sih) ++{ ++ uint idx; ++ chipcregs_t *cc; ++ otpinfo_t *oi; ++ uint32 cap = 0, clkdiv, otpdiv = 0; ++ void *ret = NULL; ++ osl_t *osh; ++ ++ OTP_MSG(("%s: Use HND OTP controller\n", __FUNCTION__)); ++ ++ oi = get_otpinfo(); ++ ++ idx = si_coreidx(sih); ++ osh = si_osh(oi->sih); ++ ++ /* Check for otp */ ++ if ((cc = si_setcoreidx(sih, SI_CC_IDX)) != NULL) { ++ cap = R_REG(osh, &cc->capabilities); ++ if ((cap & CC_CAP_OTPSIZE) == 0) { ++ /* Nothing there */ ++ goto out; ++ } ++ ++ /* As of right now, support only 4320a2, 4311a1 and 4312 */ ++ ASSERT((oi->ccrev == 12) || (oi->ccrev == 17) || (oi->ccrev == 22)); ++ if (!((oi->ccrev == 12) || (oi->ccrev == 17) || (oi->ccrev == 22))) ++ return NULL; ++ ++ /* Read the OTP byte size. chipcommon rev >= 18 has RCE so the size is ++ * 8 row (64 bytes) smaller ++ */ ++ oi->size = 1 << (((cap & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) ++ + CC_CAP_OTPSIZE_BASE); ++ if (oi->ccrev >= 18) { ++ oi->size -= ((OTP_RC0_OFF - OTP_BOUNDARY_OFF) * 2); ++ } else { ++ OTP_ERR(("Negative otp size, shouldn't happen for programmed chip.")); ++ oi->size = 0; ++ } ++ ++ oi->hwprot = (int)(R_REG(osh, &cc->otpstatus) & OTPS_PROTECT); ++ oi->boundary = -1; ++ ++ /* Check the region signature */ ++ if (hndotp_otproff(oi, cc, OTP_HWSIGN_OFF) == OTP_SIGNATURE) { ++ oi->signvalid |= OTP_HW_REGION; ++ oi->boundary = hndotp_otproff(oi, cc, OTP_BOUNDARY_OFF); ++ } ++ ++ if (hndotp_otproff(oi, cc, OTP_SWSIGN_OFF) == OTP_SIGNATURE) ++ oi->signvalid |= OTP_SW_REGION; ++ ++ if (hndotp_otproff(oi, cc, OTP_CIDSIGN_OFF) == OTP_SIGNATURE) ++ oi->signvalid |= OTP_CID_REGION; ++ ++ /* Set OTP clkdiv for stability */ ++ if (oi->ccrev == 22) ++ otpdiv = 12; ++ ++ if (otpdiv) { ++ clkdiv = R_REG(osh, &cc->clkdiv); ++ clkdiv = (clkdiv & ~CLKD_OTP) | (otpdiv << CLKD_OTP_SHIFT); ++ W_REG(osh, &cc->clkdiv, clkdiv); ++ OTP_MSG(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv)); ++ } ++ OSL_DELAY(10); ++ ++ ret = (void *)oi; ++ } ++ ++ OTP_MSG(("%s: ccrev %d\tsize %d bytes\thwprot %x\tsignvalid %x\tboundary %x\n", ++ __FUNCTION__, oi->ccrev, oi->size, oi->hwprot, oi->signvalid, ++ oi->boundary)); ++ ++out: /* All done */ ++ si_setcoreidx(sih, idx); ++ ++ return ret; ++} ++ ++static int ++hndotp_read_region(void *oh, int region, uint16 *data, uint *wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 idx, st; ++ chipcregs_t *cc; ++ int i; ++ ++ /* Only support HW region (no active chips use HND OTP SW region) */ ++ ASSERT(region == OTP_HW_REGION); ++ ++ OTP_MSG(("%s: region %x wlen %d\n", __FUNCTION__, region, *wlen)); ++ ++ /* Region empty? */ ++ st = oi->hwprot | oi-> signvalid; ++ if ((st & region) == 0) ++ return BCME_NOTFOUND; ++ ++ *wlen = ((int)*wlen < oi->boundary/2) ? *wlen : (uint)oi->boundary/2; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ for (i = 0; i < (int)*wlen; i++) ++ data[i] = hndotp_otpr(oh, cc, i); ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return 0; ++} ++ ++static int ++hndotp_read_word(void *oh, uint wn, uint16 *data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 idx; ++ chipcregs_t *cc; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ *data = hndotp_otpr(oh, cc, wn); ++ ++ si_setcoreidx(oi->sih, idx); ++ return 0; ++} ++ ++static int ++hndotp_nvread(void *oh, char *data, uint *len) ++{ ++ int rc = 0; ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 base, bound, lim = 0, st; ++ int i, chunk, gchunks, tsz = 0; ++ uint32 idx; ++ chipcregs_t *cc; ++ uint offset; ++ uint16 *rawotp = NULL; ++ ++ /* save the orig core */ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ st = hndotp_status(oh); ++ if (!(st & (OTP_HW_REGION | OTP_SW_REGION))) { ++ OTP_ERR(("OTP not programmed\n")); ++ rc = -1; ++ goto out; ++ } ++ ++ /* Read the whole otp so we can easily manipulate it */ ++ lim = hndotp_size(oh); ++ if (lim == 0) { ++ OTP_ERR(("OTP size is 0\n")); ++ rc = -1; ++ goto out; ++ } ++ if ((rawotp = MALLOC(si_osh(oi->sih), lim)) == NULL) { ++ OTP_ERR(("Out of memory for rawotp\n")); ++ rc = -2; ++ goto out; ++ } ++ for (i = 0; i < (int)(lim / 2); i++) ++ rawotp[i] = hndotp_otpr(oh, cc, i); ++ ++ if ((st & OTP_HW_REGION) == 0) { ++ OTP_ERR(("otp: hw region not written (0x%x)\n", st)); ++ ++ /* This could be a programming failure in the first ++ * chunk followed by one or more good chunks ++ */ ++ for (i = 0; i < (int)(lim / 2); i++) ++ if (rawotp[i] == OTP_MAGIC) ++ break; ++ ++ if (i < (int)(lim / 2)) { ++ base = i; ++ bound = (i * 2) + rawotp[i + 1]; ++ OTP_MSG(("otp: trying chunk at 0x%x-0x%x\n", i * 2, bound)); ++ } else { ++ OTP_MSG(("otp: unprogrammed\n")); ++ rc = -3; ++ goto out; ++ } ++ } else { ++ bound = rawotp[(lim / 2) + OTP_BOUNDARY_OFF]; ++ ++ /* There are two cases: 1) The whole otp is used as nvram ++ * and 2) There is a hardware header followed by nvram. ++ */ ++ if (rawotp[0] == OTP_MAGIC) { ++ base = 0; ++ if (bound != rawotp[1]) ++ OTP_MSG(("otp: Bound 0x%x != chunk0 len 0x%x\n", bound, ++ rawotp[1])); ++ } else ++ base = bound; ++ } ++ ++ /* Find and copy the data */ ++ ++ chunk = 0; ++ gchunks = 0; ++ i = base / 2; ++ offset = 0; ++ while ((i < (int)(lim / 2)) && (rawotp[i] == OTP_MAGIC)) { ++ int dsz, rsz = rawotp[i + 1]; ++ ++ if (((i * 2) + rsz) >= (int)lim) { ++ OTP_MSG((" bad chunk size, chunk %d, base 0x%x, size 0x%x\n", ++ chunk, i * 2, rsz)); ++ /* Bad length, try to find another chunk anyway */ ++ rsz = 6; ++ } ++ if (hndcrc16((uint8 *)&rawotp[i], rsz, ++ CRC16_INIT_VALUE) == CRC16_GOOD_VALUE) { ++ /* Good crc, copy the vars */ ++ OTP_MSG((" good chunk %d, base 0x%x, size 0x%x\n", ++ chunk, i * 2, rsz)); ++ gchunks++; ++ dsz = rsz - 6; ++ tsz += dsz; ++ if (offset + dsz >= *len) { ++ OTP_MSG(("Out of memory for otp\n")); ++ goto out; ++ } ++ bcopy((char *)&rawotp[i + 2], &data[offset], dsz); ++ offset += dsz; ++ /* Remove extra null characters at the end */ ++ while (offset > 1 && ++ data[offset - 1] == 0 && data[offset - 2] == 0) ++ offset --; ++ i += rsz / 2; ++ } else { ++ /* bad length or crc didn't check, try to find the next set */ ++ OTP_MSG((" chunk %d @ 0x%x size 0x%x: bad crc, ", ++ chunk, i * 2, rsz)); ++ if (rawotp[i + (rsz / 2)] == OTP_MAGIC) { ++ /* Assume length is good */ ++ i += rsz / 2; ++ } else { ++ while (++i < (int)(lim / 2)) ++ if (rawotp[i] == OTP_MAGIC) ++ break; ++ } ++ if (i < (int)(lim / 2)) ++ OTP_MSG(("trying next base 0x%x\n", i * 2)); ++ else ++ OTP_MSG(("no more chunks\n")); ++ } ++ chunk++; ++ } ++ ++ OTP_MSG((" otp size = %d, boundary = 0x%x, nv base = 0x%x\n", lim, bound, base)); ++ if (tsz != 0) { ++ OTP_MSG((" Found %d bytes in %d good chunks out of %d\n", tsz, gchunks, chunk)); ++ } else { ++ OTP_MSG((" No good chunks found out of %d\n", chunk)); ++ } ++ ++ *len = offset; ++ ++out: ++ if (rawotp) ++ MFREE(si_osh(oi->sih), rawotp, lim); ++ si_setcoreidx(oi->sih, idx); ++ ++ return rc; ++} ++ ++#ifdef BCMNVRAMW ++#if defined(BCMDBG) || defined(WLTEST) ++static uint st_n, st_s, st_hwm, pp_hwm; ++#ifdef OTP_FORCEFAIL ++static uint forcefail_bitcount = 0; ++#endif /* OTP_FORCEFAIL */ ++#endif /* BCMDBG || WLTEST */ ++ ++static int ++hndotp_write_bit(void *oh, chipcregs_t *cc, int bn, bool bit, int no_retry) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint row, col, j, k; ++ uint32 pwait, init_pwait, otpc, otpp, pst, st; ++ osl_t *osh; ++ ++ osh = si_osh(oi->sih); ++ ASSERT((bit >> 1) == 0); ++ ++#ifdef OTP_FORCEFAIL ++ OTP_MSG(("%s: [0x%x] = 0x%x\n", __FUNCTION__, wn * 2, data)); ++#endif ++ ++ /* This is bit-at-a-time writing, future cores may do word-at-a-time */ ++ if (oi->ccrev == 12) { ++ otpc = 0x20000001; ++ init_pwait = 0x00000200; ++ } else if (oi->ccrev == 22) { ++ otpc = 0x20000001; ++ init_pwait = 0x00000400; ++ } else { ++ otpc = 0x20000001; ++ init_pwait = 0x00004000; ++ } ++ ++ pwait = init_pwait; ++ row = bn / 65; ++ col = bn % 65; ++ otpp = OTPP_START_BUSY | ++ ((bit << OTPP_VALUE_SHIFT) & OTPP_VALUE_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ (col & OTPP_COL_MASK); ++ j = 0; ++ while (1) { ++ j++; ++ if (j > 1) { ++ OTP_DBG(("row %d, col %d, val %d, otpc 0x%x, otpp 0x%x\n", ++ row, col, bit, (otpc | pwait), otpp)); ++ } ++ W_REG(osh, &cc->otpcontrol, otpc | pwait); ++ W_REG(osh, &cc->otpprog, otpp); ++ pst = R_REG(osh, &cc->otpprog); ++ for (k = 0; ((pst & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES); k++) ++ pst = R_REG(osh, &cc->otpprog); ++#if defined(BCMDBG) || defined(WLTEST) ++ if (k > pp_hwm) ++ pp_hwm = k; ++#endif /* BCMDBG || WLTEST */ ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("BUSY stuck: pst=0x%x, count=%d\n", pst, k)); ++ st = OTPS_PROGFAIL; ++ break; ++ } ++ st = R_REG(osh, &cc->otpstatus); ++ if (((st & OTPS_PROGFAIL) == 0) || (pwait == OTPC_PROGWAIT) || (no_retry)) { ++ break; ++ } else { ++ if ((oi->ccrev == 12) || (oi->ccrev == 22)) ++ pwait = (pwait << 3) & OTPC_PROGWAIT; ++ else ++ pwait = (pwait << 1) & OTPC_PROGWAIT; ++ if (pwait == 0) ++ pwait = OTPC_PROGWAIT; ++ } ++ } ++#if defined(BCMDBG) || defined(WLTEST) ++ st_n++; ++ st_s += j; ++ if (j > st_hwm) ++ st_hwm = j; ++#ifdef OTP_FORCEFAIL ++ if (forcefail_bitcount++ == OTP_FORCEFAIL * 16) { ++ OTP_DBG(("Forcing PROGFAIL on bit %d (FORCEFAIL = %d/0x%x)\n", ++ forcefail_bitcount, OTP_FORCEFAIL, OTP_FORCEFAIL)); ++ st = OTPS_PROGFAIL; ++ } ++#endif ++#endif /* BCMDBG || WLTEST */ ++ if (st & OTPS_PROGFAIL) { ++ OTP_ERR(("After %d tries: otpc = 0x%x, otpp = 0x%x/0x%x, otps = 0x%x\n", ++ j, otpc | pwait, otpp, pst, st)); ++ OTP_ERR(("otp prog failed. bit=%d, ppret=%d, ret=%d\n", bit, k, j)); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ++hndotp_write_bits(void *oh, int bn, int bits, uint8* data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ int i, j; ++ uint8 temp; ++ ++ if (bn < 0 || bn + bits >= oi->rows * oi->cols) ++ return BCME_RANGE; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ for (i = 0; i < bits; ) { ++ temp = *data++; ++ for (j = 0; j < 8; j++, i++) { ++ if (i >= bits) ++ break; ++ if (hndotp_write_bit(oh, cc, i + bn, (temp & 0x01), 0) != 0) { ++ return -1; ++ } ++ temp >>= 1; ++ } ++ } ++ ++ si_setcoreidx(oi->sih, idx); ++ return BCME_OK; ++} ++ ++static int ++hndotp_write_word(void *oh, chipcregs_t *cc, int wn, uint16 data) ++{ ++ uint base, i; ++ int err = 0; ++ ++ OTP_MSG(("%s: wn %d data %x\n", __FUNCTION__, wn, data)); ++ ++ /* There is one test bit for each row */ ++ base = (wn * 16) + (wn / 4); ++ ++ for (i = 0; i < 16; i++) { ++ err += hndotp_write_bit(oh, cc, base + i, data & 1, 0); ++ data >>= 1; ++ /* abort write after first error to avoid stress the charge-pump */ ++ if (err) { ++ OTP_DBG(("%s: wn %d fail on bit %d\n", __FUNCTION__, wn, i)); ++ break; ++ } ++ } ++ ++ return err; ++} ++ ++static int ++hndotp_valid_rce(void *oh, chipcregs_t *cc, int i) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ osl_t *osh; ++ uint32 hwv, fw, rce, e, sign, row, st; ++ ++ ASSERT(oi->ccrev >= 18); ++ ++ /* HW valid bit */ ++ osh = si_osh(oi->sih); ++ st = R_REG(osh, &cc->otpstatus); ++ hwv = (st & OTPS_RCEV_MSK) & (1 << (OTPS_RCEV_SHIFT + i)); ++ BCM_REFERENCE(hwv); ++ ++ if (i < 3) { ++ e = i; ++ fw = hndotp_size(oh)/2 + OTP_RC0_OFF + e; ++ } else { ++ e = i - 3; ++ fw = hndotp_size(oh)/2 + OTP_RC1_OFF + e; ++ } ++ ++ rce = hndotp_otpr(oh, cc, fw+1) << 16 | hndotp_otpr(oh, cc, fw); ++ rce >>= ((e * OTP_RCE_BITS) + OTP_RCE_BIT0 - (e * 16)); ++ row = rce & OTP_RCE_ROW_MASK; ++ sign = (rce >> OTP_RCE_ROW_SZ) & OTP_RCE_SIGN_MASK; ++ ++ OTP_MSG(("rce %d sign %x row %d hwv %x\n", i, sign, row, hwv)); ++ ++ return (sign == OTP_SIGNATURE) ? row : -1; ++} ++ ++static int ++hndotp_write_rce(void *oh, chipcregs_t *cc, int r, uint16* data) ++{ ++ int i, rce = -1; ++ uint32 sign; ++ ++ ASSERT(((otpinfo_t *)oh)->ccrev >= 18); ++ ASSERT(r >= 0 && r < hndotp_size(oh)/(2*OTP_WPR)); ++ ASSERT(data); ++ ++ for (rce = OTP_RCE_ROW_SZ -1; rce >= 0; rce--) { ++ int e, rt, rcr, bit, err = 0; ++ ++ int rr = hndotp_valid_rce(oh, cc, rce); ++ /* redundancy row in use already */ ++ if (rr != -1) { ++ if (rr == r) { ++ OTP_MSG(("%s: row %d already replaced by RCE %d", ++ __FUNCTION__, r, rce)); ++ return 0; ++ } ++ ++ continue; /* If row used, go for the next row */ ++ } ++ ++ /* ++ * previously used bad rce entry maybe treaed as valid rce and used again, abort on ++ * first bit error to avoid stress the charge pump ++ */ ++ ++ /* Write the data to the redundant row */ ++ for (i = 0; i < OTP_WPR; i++) { ++ err += hndotp_write_word(oh, cc, hndotp_size(oh)/2+OTP_RD_OFF+rce*4+i, ++ data[i]); ++ if (err) { ++ OTP_MSG(("fail to write redundant row %d\n", rce)); ++ break; ++ } ++ } ++ ++ /* Now write the redundant row index */ ++ if (rce < 3) { ++ e = rce; ++ rcr = hndotp_size(oh)/2 + OTP_RC0_OFF; ++ } else { ++ e = rce - 3; ++ rcr = hndotp_size(oh)/2 + OTP_RC1_OFF; ++ } ++ ++ /* Write row numer bit-by-bit */ ++ bit = (rcr * 16 + rcr / 4) + e * OTP_RCE_BITS + OTP_RCE_BIT0; ++ rt = r; ++ for (i = 0; i < OTP_RCE_ROW_SZ; i++) { ++ /* If any timeout happened, invalidate the subsequent bits with 0 */ ++ if (hndotp_write_bit(oh, cc, bit, (rt & (err ? 0 : 1)), err)) { ++ OTP_MSG(("%s: timeout fixing row %d with RCE %d - at row" ++ " number bit %x\n", __FUNCTION__, r, rce, i)); ++ err++; ++ } ++ rt >>= 1; ++ bit ++; ++ } ++ ++ /* Write the RCE signature bit-by-bit */ ++ sign = OTP_SIGNATURE; ++ for (i = 0; i < OTP_RCE_SIGN_SZ; i++) { ++ /* If any timeout happened, invalidate the subsequent bits with 0 */ ++ if (hndotp_write_bit(oh, cc, bit, (sign & (err ? 0 : 1)), err)) { ++ OTP_MSG(("%s: timeout fixing row %d with RCE %d - at row" ++ " number bit %x\n", __FUNCTION__, r, rce, i)); ++ err++; ++ } ++ sign >>= 1; ++ bit ++; ++ } ++ ++ if (err) { ++ OTP_ERR(("%s: row %d not fixed by RCE %d due to %d timeouts. try next" ++ " RCE\n", __FUNCTION__, r, rce, err)); ++ continue; ++ } else { ++ OTP_MSG(("%s: Fixed row %d by RCE %d\n", __FUNCTION__, r, rce)); ++ return BCME_OK; ++ } ++ } ++ ++ OTP_ERR(("All RCE's are in use. Failed fixing OTP.\n")); ++ /* Fatal error, unfixable. MFGC will have to fail. Board needs to be discarded!! */ ++ return BCME_NORESOURCE; ++} ++ ++/* Write a row and fix it with RCE if any error detected */ ++static int ++hndotp_write_row(void *oh, chipcregs_t *cc, int wn, uint16* data, bool rewrite) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int err = 0, i; ++ ++ ASSERT(wn % OTP_WPR == 0); ++ ++ /* Write the data */ ++ for (i = 0; i < OTP_WPR; i++) { ++ if (rewrite && (data[i] == hndotp_otpr(oh, cc, wn+i))) ++ continue; ++ ++ err += hndotp_write_word(oh, cc, wn + i, data[i]); ++ } ++ ++ /* Fix this row if any error */ ++ if (err && (oi->ccrev >= 18)) { ++ OTP_DBG(("%s: %d write errors in row %d. Fixing...\n", __FUNCTION__, err, wn/4)); ++ if ((err = hndotp_write_rce(oh, cc, wn / OTP_WPR, data))) ++ OTP_MSG(("%s: failed to fix row %d\n", __FUNCTION__, wn/4)); ++ } ++ ++ return err; ++} ++ ++/* expects the caller to disable interrupts before calling this routine */ ++static int ++hndotp_write_region(void *oh, int region, uint16 *data, uint wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 st; ++ uint wn, base = 0, lim; ++ int ret = BCME_OK; ++ uint idx; ++ chipcregs_t *cc; ++ bool rewrite = FALSE; ++ uint32 save_clk; ++ ++ ASSERT(wlen % OTP_WPR == 0); ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Check valid region */ ++ if ((region != OTP_HW_REGION) && ++ (region != OTP_SW_REGION) && ++ (region != OTP_CID_REGION)) { ++ ret = BCME_BADARG; ++ goto out; ++ } ++ ++ /* Region already written? */ ++ st = oi->hwprot | oi-> signvalid; ++ if ((st & region) != 0) ++ rewrite = TRUE; ++ ++ /* HW and CID have to be written before SW */ ++ if ((((st & (OTP_HW_REGION | OTP_CID_REGION)) == 0) && ++ (st & OTP_SW_REGION) != 0)) { ++ OTP_ERR(("%s: HW/CID region should be programmed first\n", __FUNCTION__)); ++ ret = BCME_BADARG; ++ goto out; ++ } ++ ++ /* Bounds for the region */ ++ lim = (oi->size / 2) + OTP_SWLIM_OFF; ++ if (region == OTP_HW_REGION) { ++ base = 0; ++ } else if (region == OTP_SW_REGION) { ++ base = oi->boundary / 2; ++ } else if (region == OTP_CID_REGION) { ++ base = (oi->size / 2) + OTP_CID_OFF; ++ lim = (oi->size / 2) + OTP_LIM_OFF; ++ } ++ ++ if (wlen > (lim - base)) { ++ ret = BCME_BUFTOOLONG; ++ goto out; ++ } ++ lim = base + wlen; ++ ++#if defined(BCMDBG) || defined(WLTEST) ++ st_n = st_s = st_hwm = pp_hwm = 0; ++#endif /* BCMDBG || WLTEST */ ++ ++ /* force ALP for progrramming stability */ ++ save_clk = R_REG(oi->osh, &cc->clk_ctl_st); ++ OR_REG(oi->osh, &cc->clk_ctl_st, CCS_FORCEALP); ++ OSL_DELAY(10); ++ ++ /* Write the data row by row */ ++ for (wn = base; wn < lim; wn += OTP_WPR, data += OTP_WPR) { ++ if ((ret = hndotp_write_row(oh, cc, wn, data, rewrite)) != 0) { ++ if (ret == BCME_NORESOURCE) { ++ OTP_ERR(("%s: Abort at word %x\n", __FUNCTION__, wn)); ++ break; ++ } ++ } ++ } ++ ++ /* Don't need to update signature & boundary if rewrite */ ++ if (rewrite) ++ goto out_rclk; ++ ++ /* Done with the data, write the signature & boundary if needed */ ++ if (region == OTP_HW_REGION) { ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_BOUNDARY_OFF, lim * 2) != 0) { ++ ret = BCME_NORESOURCE; ++ goto out_rclk; ++ } ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_HWSIGN_OFF, ++ OTP_SIGNATURE) != 0) { ++ ret = BCME_NORESOURCE; ++ goto out_rclk; ++ } ++ oi->boundary = lim * 2; ++ oi->signvalid |= OTP_HW_REGION; ++ } else if (region == OTP_SW_REGION) { ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_SWSIGN_OFF, ++ OTP_SIGNATURE) != 0) { ++ ret = BCME_NORESOURCE; ++ goto out_rclk; ++ } ++ oi->signvalid |= OTP_SW_REGION; ++ } else if (region == OTP_CID_REGION) { ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_CIDSIGN_OFF, ++ OTP_SIGNATURE) != 0) { ++ ret = BCME_NORESOURCE; ++ goto out_rclk; ++ } ++ oi->signvalid |= OTP_CID_REGION; ++ } ++ ++out_rclk: ++ /* Restore clock */ ++ W_REG(oi->osh, &cc->clk_ctl_st, save_clk); ++ ++out: ++#if defined(BCMDBG) || defined(WLTEST) ++ OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n", ++ st_n, st_s, st_n, st_n?(st_s / st_n):0, st_hwm, pp_hwm)); ++#endif ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return ret; ++} ++ ++/* For HND OTP, there's no space for appending after filling in SROM image */ ++static int ++hndotp_cis_append_region(si_t *sih, int region, char *vars, int count) ++{ ++ return otp_write_region(sih, region, (uint16*)vars, count/2); ++} ++ ++/* ++ * Fill all unwritten RCE signature with 0 and return the number of them. ++ * HNDOTP needs lock due to the randomness of unprogrammed content. ++ */ ++static int ++hndotp_lock(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int i, j, e, rcr, bit, ret = 0; ++ uint32 st, idx; ++ chipcregs_t *cc; ++ ++ ASSERT(oi->ccrev >= 18); ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Region already written? */ ++ st = oi->hwprot | oi-> signvalid; ++ if ((st & (OTP_HW_REGION | OTP_SW_REGION)) == 0) { ++ si_setcoreidx(oi->sih, idx); ++ return BCME_NOTREADY; /* Don't lock unprogrammed OTP */ ++ } ++ ++ /* Find the highest valid RCE */ ++ for (i = 0; i < OTP_RCE_ROW_SZ -1; i++) { ++ if ((hndotp_valid_rce(oh, cc, i) != -1)) ++ break; ++ } ++ i--; /* Start invalidating from the next RCE */ ++ ++ for (; i >= 0; i--) { ++ if ((hndotp_valid_rce(oh, cc, i) == -1)) { ++ ++ ret++; /* This is a unprogrammed row */ ++ ++ /* Invalidate the row with 0 */ ++ if (i < 3) { ++ e = i; ++ rcr = hndotp_size(oh)/2 + OTP_RC0_OFF; ++ } else { ++ e = i - 3; ++ rcr = hndotp_size(oh)/2 + OTP_RC1_OFF; ++ } ++ ++ /* Fill row numer and signature with 0 bit-by-bit */ ++ bit = (rcr * 16 + rcr / 4) + e * OTP_RCE_BITS + OTP_RCE_BIT0; ++ for (j = 0; j < (OTP_RCE_ROW_SZ + OTP_RCE_SIGN_SZ); j++) { ++ hndotp_write_bit(oh, cc, bit, 0, 1); ++ bit ++; ++ } ++ ++ OTP_MSG(("locking rce %d\n", i)); ++ } ++ } ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return ret; ++} ++ ++/* expects the caller to disable interrupts before calling this routine */ ++static int ++hndotp_nvwrite(void *oh, uint16 *data, uint wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 st; ++ uint16 crc, clen, *p, hdr[2]; ++ uint wn, base = 0, lim; ++ int err, gerr = 0; ++ uint idx; ++ chipcregs_t *cc; ++ ++ /* otp already written? */ ++ st = oi->hwprot | oi-> signvalid; ++ if ((st & (OTP_HW_REGION | OTP_SW_REGION)) == (OTP_HW_REGION | OTP_SW_REGION)) ++ return BCME_EPERM; ++ ++ /* save the orig core */ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Bounds for the region */ ++ lim = (oi->size / 2) + OTP_SWLIM_OFF; ++ base = 0; ++ ++ /* Look for possible chunks from the end down */ ++ wn = lim; ++ while (wn > 0) { ++ wn--; ++ if (hndotp_otpr(oh, cc, wn) == OTP_MAGIC) { ++ base = wn + (hndotp_otpr(oh, cc, wn + 1) / 2); ++ break; ++ } ++ } ++ if (base == 0) { ++ OTP_MSG(("Unprogrammed otp\n")); ++ } else { ++ OTP_MSG(("Found some chunks, skipping to 0x%x\n", base * 2)); ++ } ++ if ((wlen + 3) > (lim - base)) { ++ err = BCME_NORESOURCE; ++ goto out; ++ } ++ ++#if defined(BCMDBG) || defined(WLTEST) ++ st_n = st_s = st_hwm = pp_hwm = 0; ++#endif /* BCMDBG || WLTEST */ ++ ++ /* Prepare the header and crc */ ++ hdr[0] = OTP_MAGIC; ++ hdr[1] = (wlen + 3) * 2; ++ crc = hndcrc16((uint8 *)hdr, sizeof(hdr), CRC16_INIT_VALUE); ++ crc = hndcrc16((uint8 *)data, wlen * 2, crc); ++ crc = ~crc; ++ ++ do { ++ p = data; ++ wn = base + 2; ++ lim = base + wlen + 2; ++ ++ OTP_MSG(("writing chunk, 0x%x bytes @ 0x%x-0x%x\n", wlen * 2, ++ base * 2, (lim + 1) * 2)); ++ ++ /* Write the header */ ++ err = hndotp_write_word(oh, cc, base, hdr[0]); ++ ++ /* Write the data */ ++ while (wn < lim) { ++ err += hndotp_write_word(oh, cc, wn++, *p++); ++ ++ /* If there has been an error, close this chunk */ ++ if (err != 0) { ++ OTP_MSG(("closing early @ 0x%x\n", wn * 2)); ++ break; ++ } ++ } ++ ++ /* If we wrote the whole chunk, write the crc */ ++ if (wn == lim) { ++ OTP_MSG((" whole chunk written, crc = 0x%x\n", crc)); ++ err += hndotp_write_word(oh, cc, wn++, crc); ++ clen = hdr[1]; ++ } else { ++ /* If there was an error adjust the count to point to ++ * the word after the error so we can start the next ++ * chunk there. ++ */ ++ clen = (wn - base) * 2; ++ OTP_MSG((" partial chunk written, chunk len = 0x%x\n", clen)); ++ } ++ /* And now write the chunk length */ ++ err += hndotp_write_word(oh, cc, base + 1, clen); ++ ++ if (base == 0) { ++ /* Write the signature and boundary if this is the HW region, ++ * but don't report failure if either of these 2 writes fail. ++ */ ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_BOUNDARY_OFF, ++ wn * 2) == 0) ++ gerr += hndotp_write_word(oh, cc, (oi->size / 2) + OTP_HWSIGN_OFF, ++ OTP_SIGNATURE); ++ else ++ gerr++; ++ oi->boundary = wn * 2; ++ oi->signvalid |= OTP_HW_REGION; ++ } ++ ++ if (err != 0) { ++ gerr += err; ++ /* Errors, do it all over again if there is space left */ ++ if ((wlen + 3) <= ((oi->size / 2) + OTP_SWLIM_OFF - wn)) { ++ base = wn; ++ lim = base + wlen + 2; ++ OTP_ERR(("Programming errors, retry @ 0x%x\n", wn * 2)); ++ } else { ++ OTP_ERR(("Programming errors, no space left ( 0x%x)\n", wn * 2)); ++ break; ++ } ++ } ++ } while (err != 0); ++ ++ OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n", ++ st_n, st_s, st_n, st_s / st_n, st_hwm, pp_hwm)); ++ ++ if (gerr != 0) ++ OTP_MSG(("programming %s after %d errors\n", (err == 0) ? "succedded" : "failed", ++ gerr)); ++out: ++ /* done */ ++ si_setcoreidx(oi->sih, idx); ++ ++ if (err) ++ return BCME_ERROR; ++ else ++ return 0; ++} ++#endif /* BCMNVRAMW */ ++ ++#if defined(WLTEST) && !defined(BCMROMBUILD) ++static uint16 ++hndotp_otprb16(void *oh, chipcregs_t *cc, uint wn) ++{ ++ uint base, i; ++ uint16 val, bit; ++ ++ base = (wn * 16) + (wn / 4); ++ val = 0; ++ for (i = 0; i < 16; i++) { ++ if ((bit = hndotp_read_bit(oh, cc, base + i)) == 0xffff) ++ break; ++ val = val | (bit << i); ++ } ++ if (i < 16) ++ val = 0xaaaa; ++ return val; ++} ++ ++static int ++hndotp_dump(void *oh, int arg, char *buf, uint size) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ chipcregs_t *cc; ++ uint idx, i, count, lil; ++ uint16 val; ++ struct bcmstrbuf b; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ if (arg >= 16) ++ arg -= 16; ++ ++ if (arg == 2) { ++ count = 66 * 4; ++ lil = 3; ++ } else { ++ count = (oi->size / 2) + OTP_RC_LIM_OFF; ++ lil = 7; ++ } ++ ++ OTP_MSG(("%s: arg %d, size %d, words %d\n", __FUNCTION__, arg, size, count)); ++ bcm_binit(&b, buf, size); ++ for (i = 0; i < count; i++) { ++ if ((i & lil) == 0) ++ bcm_bprintf(&b, "0x%04x:", 2 * i); ++ ++ if (arg == 0) ++ val = hndotp_otpr(oh, cc, i); ++ else ++ val = hndotp_otprb16(oi, cc, i); ++ bcm_bprintf(&b, " 0x%04x", val); ++ if ((i & lil) == lil) { ++ if (arg == 2) { ++ bcm_bprintf(&b, " %d\n", ++ hndotp_read_bit(oh, cc, ((i / 4) * 65) + 64) & 1); ++ } else { ++ bcm_bprintf(&b, "\n"); ++ } ++ } ++ } ++ if ((i & lil) != lil) ++ bcm_bprintf(&b, "\n"); ++ ++ OTP_MSG(("%s: returning %d, left %d, wn %d\n", ++ __FUNCTION__, (int)(b.buf - b.origbuf), b.size, i)); ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return ((int)(b.buf - b.origbuf)); ++} ++#endif ++ ++static otp_fn_t hndotp_fn = { ++ (otp_size_t)hndotp_size, ++ (otp_read_bit_t)hndotp_read_bit, ++ (otp_dump_t)NULL, /* Assigned in otp_init */ ++ (otp_status_t)hndotp_status, ++ ++ (otp_init_t)hndotp_init, ++ (otp_read_region_t)hndotp_read_region, ++ (otp_nvread_t)hndotp_nvread, ++#ifdef BCMNVRAMW ++ (otp_write_region_t)hndotp_write_region, ++ (otp_cis_append_region_t)hndotp_cis_append_region, ++ (otp_lock_t)hndotp_lock, ++ (otp_nvwrite_t)hndotp_nvwrite, ++ (otp_write_word_t)NULL, ++#else /* BCMNVRAMW */ ++ (otp_write_region_t)NULL, ++ (otp_cis_append_region_t)NULL, ++ (otp_lock_t)NULL, ++ (otp_nvwrite_t)NULL, ++ (otp_write_word_t)NULL, ++#endif /* BCMNVRAMW */ ++ (otp_read_word_t)hndotp_read_word, ++#if defined(BCMNVRAMW) ++ (otp_write_bits_t)hndotp_write_bits ++#endif ++}; ++ ++#endif /* BCMHNDOTP */ ++ ++/* ++ * Common Code: Compiled for IPX / HND / AUTO ++ * otp_status() ++ * otp_size() ++ * otp_read_bit() ++ * otp_init() ++ * otp_read_region() ++ * otp_read_word() ++ * otp_nvread() ++ * otp_write_region() ++ * otp_write_word() ++ * otp_cis_append_region() ++ * otp_lock() ++ * otp_nvwrite() ++ * otp_dump() ++ */ ++ ++int ++otp_status(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return oi->fn->status(oh); ++} ++ ++int ++otp_size(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return oi->fn->size(oh); ++} ++ ++uint16 ++otp_read_bit(void *oh, uint offset) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx = si_coreidx(oi->sih); ++ chipcregs_t *cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ uint16 readBit = (uint16)oi->fn->read_bit(oh, cc, offset); ++ si_setcoreidx(oi->sih, idx); ++ return readBit; ++} ++ ++#if defined(BCMNVRAMW) ++int ++otp_write_bits(void *oh, uint offset, int bits, uint8* data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return oi->fn->write_bits(oh, offset, bits, data); ++} ++#endif ++ ++void * ++BCMNMIATTACHFN(otp_init)(si_t *sih) ++{ ++ otpinfo_t *oi; ++ void *ret = NULL; ++ bool wasup = FALSE; ++ ++ oi = get_otpinfo(); ++ bzero(oi, sizeof(otpinfo_t)); ++ ++ oi->ccrev = sih->ccrev; ++ ++#ifdef BCMIPXOTP ++ if (OTPTYPE_IPX(oi->ccrev)) { ++#if defined(WLTEST) && !defined(BCMROMBUILD) ++ /* Dump function is excluded from ROM */ ++ ipxotp_fn.dump = ipxotp_dump; ++#endif ++ oi->fn = &ipxotp_fn; ++ } ++#endif /* BCMIPXOTP */ ++ ++#ifdef BCMHNDOTP ++ if (OTPTYPE_HND(oi->ccrev)) { ++#if defined(WLTEST) && !defined(BCMROMBUILD) ++ /* Dump function is excluded from ROM */ ++ hndotp_fn.dump = hndotp_dump; ++#endif ++ oi->fn = &hndotp_fn; ++ } ++#endif /* BCMHNDOTP */ ++ ++ if (oi->fn == NULL) { ++ OTP_ERR(("otp_init: unsupported OTP type\n")); ++ return NULL; ++ } ++ ++ oi->sih = sih; ++ oi->osh = si_osh(oi->sih); ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ ret = (oi->fn->init)(sih); ++ ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return ret; ++} ++ ++int ++BCMNMIATTACHFN(otp_read_region)(si_t *sih, int region, uint16 *data, uint *wlen) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int err = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ err = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ err = BCME_ERROR; ++ goto out; ++ } ++ ++ err = (((otpinfo_t*)oh)->fn->read_region)(oh, region, data, wlen); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return err; ++} ++ ++int ++otp_read_word(si_t *sih, uint wn, uint16 *data) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int err = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ err = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ err = BCME_ERROR; ++ goto out; ++ } ++ ++ if (((otpinfo_t*)oh)->fn->read_word == NULL) { ++ err = BCME_UNSUPPORTED; ++ goto out; ++ } ++ err = (((otpinfo_t*)oh)->fn->read_word)(oh, wn, data); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return err; ++} ++ ++int ++otp_nvread(void *oh, char *data, uint *len) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return oi->fn->nvread(oh, data, len); ++} ++ ++#ifdef BCMNVRAMW ++int ++BCMNMIATTACHFN(otp_write_region)(si_t *sih, int region, uint16 *data, uint wlen) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int err = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ err = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ err = BCME_ERROR; ++ goto out; ++ } ++ ++ err = (((otpinfo_t*)oh)->fn->write_region)(oh, region, data, wlen); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return err; ++} ++ ++int ++otp_write_word(si_t *sih, uint wn, uint16 data) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int err = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ err = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ err = BCME_ERROR; ++ goto out; ++ } ++ ++ if (((otpinfo_t*)oh)->fn->write_word == NULL) { ++ err = BCME_UNSUPPORTED; ++ goto out; ++ } ++ err = (((otpinfo_t*)oh)->fn->write_word)(oh, wn, data); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return err; ++} ++ ++int ++otp_cis_append_region(si_t *sih, int region, char *vars, int count) ++{ ++ void *oh = otp_init(sih); ++ ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ return -1; ++ } ++ return (((otpinfo_t*)oh)->fn->cis_append_region)(sih, region, vars, count); ++} ++ ++int ++otp_lock(si_t *sih) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int ret = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ ret = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ ret = BCME_ERROR; ++ goto out; ++ } ++ ++ ret = (((otpinfo_t*)oh)->fn->lock)(oh); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return ret; ++} ++ ++int ++otp_nvwrite(void *oh, uint16 *data, uint wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return oi->fn->nvwrite(oh, data, wlen); ++} ++#endif /* BCMNVRAMW */ ++ ++#if defined(WLTEST) ++int ++otp_dump(void *oh, int arg, char *buf, uint size) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ if (oi->fn->dump == NULL) ++ return BCME_UNSUPPORTED; ++ else ++ return oi->fn->dump(oh, arg, buf, size); ++} ++ ++int ++otp_dumpstats(void *oh, int arg, char *buf, uint size) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ struct bcmstrbuf b; ++ ++ bcm_binit(&b, buf, size); ++ ++ bcm_bprintf(&b, "\nOTP, ccrev 0x%04x\n", oi->ccrev); ++#if defined(BCMIPXOTP) ++ bcm_bprintf(&b, "wsize %d rows %d cols %d\n", oi->wsize, oi->rows, oi->cols); ++ bcm_bprintf(&b, "hwbase %d hwlim %d swbase %d swlim %d fusebits %d\n", ++ oi->hwbase, oi->hwlim, oi->swbase, oi->swlim, oi->fbase, oi->flim, oi->fusebits); ++ bcm_bprintf(&b, "otpgu_base %d status %d\n", oi->otpgu_base, oi->status); ++#endif ++#if defined(BCMHNDOTP) ++ bcm_bprintf(&b, "OLD OTP, size %d hwprot 0x%x signvalid 0x%x boundary %d\n", ++ oi->size, oi->hwprot, oi->signvalid, oi->boundary); ++#endif ++ bcm_bprintf(&b, "\n"); ++ ++ return 200; /* real buf length, pick one to cover above print */ ++} ++ ++#endif +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmrobo.c b/drivers/bcmdrivers/gmac/src/shared/bcmrobo.c +new file mode 100755 +index 0000000..df74e4b +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmrobo.c +@@ -0,0 +1,1548 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom 53xx RoboSwitch device driver. ++ * ++ * $Id: bcmrobo.c 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(CONFIG_IPROC_OTP) ++#include "bcm5301x_otp.h" ++#endif /* defined(CONFIG_IPROC_OTP) */ ++ ++#ifdef BCMDBG ++#define ET_ERROR(args) printf args ++#else /* BCMDBG */ ++#define ET_ERROR(args) ++#endif /* BCMDBG */ ++#define ET_MSG(args) ++ ++#define VARG(var, len) (((len) == 1) ? *((uint8 *)(var)) : \ ++ ((len) == 2) ? *((uint16 *)(var)) : \ ++ *((uint32 *)(var))) ++ ++//#define BRCM_TAG true ++ ++/* Page numbers */ ++#define PAGE_CTRL 0x00 /* Control page */ ++#define PAGE_STATUS 0x01 /* Status page */ ++#define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */ ++#define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */ ++#define PAGE_GPHYP0 0x10 /* Port0 internal GPHY registers page */ ++#define PAGE_VLAN 0x34 /* VLAN page */ ++ ++/* Control page registers */ ++#define REG_CTRL_PORT0 0x00 /* Port 0 traffic control register */ ++#define REG_CTRL_PORT1 0x01 /* Port 1 traffic control register */ ++#define REG_CTRL_PORT2 0x02 /* Port 2 traffic control register */ ++#define REG_CTRL_PORT3 0x03 /* Port 3 traffic control register */ ++#define REG_CTRL_PORT4 0x04 /* Port 4 traffic control register */ ++#define REG_CTRL_PORT5 0x05 /* Port 5 traffic control register */ ++#define REG_CTRL_PORT6 0x06 /* Port 6 traffic control register */ ++#define REG_CTRL_PORT7 0x07 /* Port 7 traffic control register */ ++#define REG_CTRL_IMP 0x08 /* IMP port traffic control register */ ++#define REG_CTRL_MODE 0x0B /* Switch Mode register */ ++#define REG_CTRL_MIIPO 0x0E /* 5325: MII Port Override register */ ++#define REG_CTRL_PWRDOWN 0x0F /* 5325: Power Down Mode register */ ++#define REG_CTRL_PPORT 0x24 /* Protected port register */ ++#define REG_CTRL_PHY_PWR 0x4a /* phy power down register */ ++#define REG_CTRL_SRST 0x79 /* Software reset control register */ ++ ++/* Status Page Registers */ ++#define REG_STATUS_LINK 0x00 /* Link Status Summary */ ++#define REG_STATUS_REV 0x50 /* Revision Register */ ++ ++#define REG_MGMT_CFG 0x00 /* Global Management Configuration */ ++#define REG_BRCM_HDR 0x03 /* BRCM Header Control */ ++#define REG_DEVICE_ID 0x30 /* 539x Device id: */ ++ ++/* VLAN page registers */ ++#define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */ ++#define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */ ++#define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */ ++#define REG_VLAN_CTRL5 0x06 /* VLAN Control 5 register */ ++#define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */ ++#define REG_VLAN_WRITE 0x08 /* VLAN Write register */ ++#define REG_VLAN_READ 0x0C /* VLAN Read register */ ++#define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */ ++#define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */ ++#define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */ ++#define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */ ++#define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */ ++#define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */ ++#define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */ ++#define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */ ++#define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */ ++#define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */ ++ ++/* Port0 internal GPHY registers page */ ++#define PAGE_GPHYP0_DSP_COEF 0x2a /* dsp coefficient */ ++#define PAGE_GPHYP0_DSP_COEF_ADDR 0x2e /* dsp coefficient address */ ++ ++#define VLAN_NUMVLANS 16 /* # of VLANs */ ++ ++ ++/* ARL/VLAN Table Access page registers */ ++#define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */ ++#define REG_VTBL_MINDX 0x02 /* MAC Address Index */ ++#define REG_VTBL_VINDX 0x08 /* VID Table Index */ ++#define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */ ++#define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */ ++#define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */ ++#define REG_VTBL_SCTRL 0x20 /* ARL Search Control */ ++#define REG_VTBL_SADDR 0x22 /* ARL Search Address */ ++#define REG_VTBL_SRES 0x24 /* ARL Search Result */ ++#define REG_VTBL_SREXT 0x2c /* ARL Search Result */ ++#define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */ ++#define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */ ++#define REG_VTBL_PREG 0xFF /* Page Register */ ++#define REG_VTBL_ACCESS 0x60 /* VLAN table access register */ ++#define REG_VTBL_INDX 0x61 /* VLAN table address index register */ ++#define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */ ++#define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */ ++#define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */ ++#define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */ ++ ++#define SRAB_MAX_RETRY 1000 ++ ++#if defined(CONFIG_IPROC_OTP) ++void * (*bcm5301x_otp_init_fptr )(void) = NULL; ++int (*bcm5301x_otp_read_dword_fptr)(void *oh, uint wn, u32 *data) = NULL; ++int (*bcm5301x_otp_exit_fptr)(void) = NULL; ++#endif /* defined(CONFIG_IPROC_OTP) */ ++ ++static int ++srab_request_grant(robo_info_t *robo) ++{ ++ int i, ret = 0; ++ uint32 val32; ++ ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); ++ val32 |= CFG_F_rcareq_MASK; ++ W_REG(si_osh(robo->sih), &robo->srabregs->ctrls, val32); ++ ++ /* Wait for command complete */ ++ for (i = SRAB_MAX_RETRY * 10; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); ++ if ((val32 & CFG_F_rcagnt_MASK)) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_request_grant: timeout")); ++ ret = -1; ++ } ++ ++ return ret; ++} ++ ++static void ++srab_release_grant(robo_info_t *robo) ++{ ++ uint32 val32; ++ ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); ++ val32 &= ~CFG_F_rcareq_MASK; ++ W_REG(si_osh(robo->sih), &robo->srabregs->ctrls, val32); ++} ++ ++static int ++srab_interface_reset(robo_info_t *robo) ++{ ++ int i, ret = 0; ++ uint32 val32; ++ ++ /* Wait for switch initialization complete */ ++ for (i = SRAB_MAX_RETRY * 10; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); ++ if ((val32 & CFG_F_sw_init_done_MASK)) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_interface_reset: timeout sw_init_done")); ++ ret = -1; ++ } ++ ++ /* Set the SRAU reset bit */ ++ W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, CFG_F_sra_rst_MASK); ++ ++ /* Wait for it to auto-clear */ ++ for (i = SRAB_MAX_RETRY * 10; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat); ++ if ((val32 & CFG_F_sra_rst_MASK) == 0) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_interface_reset: timeout sra_rst")); ++ ret |= -2; ++ } ++ ++ return ret; ++} ++ ++static int ++srab_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) ++{ ++ uint16 val16; ++ uint32 val32; ++ uint32 val_h = 0, val_l = 0; ++ int i, ret = 0; ++ uint8 *ptr = (uint8 *)val; ++ ++ /* validate value length and buffer address */ ++ ASSERT(len == 1 || len == 6 || len == 8 || ++ ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3))); ++ ++ ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg, ++ VARG(val, len), len)); ++ ++ srab_request_grant(robo); ++ ++ /* Load the value to write */ ++ switch (len) { ++ case 8: ++ val16 = ptr[7]; ++ val16 = ((val16 << 8) | ptr[6]); ++ val_h = val16 << 16; ++ /* FALLTHRU */ ++ ++ case 6: ++ val16 = ptr[5]; ++ val16 = ((val16 << 8) | ptr[4]); ++ val_h |= val16; ++ ++ val16 = ptr[3]; ++ val16 = ((val16 << 8) | ptr[2]); ++ val_l = val16 << 16; ++ val16 = ptr[1]; ++ val16 = ((val16 << 8) | ptr[0]); ++ val_l |= val16; ++ break; ++ ++ case 4: ++ val_l = *(uint32 *)val; ++ break; ++ ++ case 2: ++ val_l = *(uint16 *)val; ++ break; ++ ++ case 1: ++ val_l = *(uint8 *)val; ++ break; ++ } ++ W_REG(si_osh(robo->sih), &robo->srabregs->wd_h, val_h); ++ W_REG(si_osh(robo->sih), &robo->srabregs->wd_l, val_l); ++ ++ /* We don't need this variable */ ++ if (robo->page != page) ++ robo->page = page; ++ ++ /* Issue the write command */ ++ val32 = ((page << CFG_F_sra_page_R) ++ | (reg << CFG_F_sra_offset_R) ++ | CFG_F_sra_gordyn_MASK ++ | CFG_F_sra_write_MASK); ++ W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, val32); ++ ++ /* Wait for command complete */ ++ for (i = SRAB_MAX_RETRY; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat); ++ if ((val32 & CFG_F_sra_gordyn_MASK) == 0) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_wreg: timeout")); ++ srab_interface_reset(robo); ++ ret = -1; ++ } ++ ++ srab_release_grant(robo); ++ ++ return ret; ++} ++ ++static int ++srab_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) ++{ ++ uint32 val32; ++ uint32 val_h = 0, val_l = 0; ++ int i, ret = 0; ++ uint8 *ptr = (uint8 *)val; ++ ++ /* validate value length and buffer address */ ++ ASSERT(len == 1 || len == 6 || len == 8 || ++ ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3))); ++ ++ srab_request_grant(robo); ++ ++ /* We don't need this variable */ ++ if (robo->page != page) ++ robo->page = page; ++ ++ /* Assemble read command */ ++ srab_request_grant(robo); ++ ++ val32 = ((page << CFG_F_sra_page_R) ++ | (reg << CFG_F_sra_offset_R) ++ | CFG_F_sra_gordyn_MASK); ++ W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, val32); ++ ++ /* is operation finished? */ ++ for (i = SRAB_MAX_RETRY; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat); ++ if ((val32 & CFG_F_sra_gordyn_MASK) == 0) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_read: timeout")); ++ srab_interface_reset(robo); ++ ret = -1; ++ goto err; ++ } ++ ++ /* Didn't time out, read and return the value */ ++ val_h = R_REG(si_osh(robo->sih), &robo->srabregs->rd_h); ++ val_l = R_REG(si_osh(robo->sih), &robo->srabregs->rd_l); ++ ++ switch (len) { ++ case 8: ++ ptr[7] = (val_h >> 24); ++ ptr[6] = ((val_h >> 16) & 0xff); ++ /* FALLTHRU */ ++ ++ case 6: ++ ptr[5] = ((val_h >> 8) & 0xff); ++ ptr[4] = (val_h & 0xff); ++ ptr[3] = (val_l >> 24); ++ ptr[2] = ((val_l >> 16) & 0xff); ++ ptr[1] = ((val_l >> 8) & 0xff); ++ ptr[0] = (val_l & 0xff); ++ break; ++ ++ case 4: ++ *(uint32 *)val = val_l; ++ break; ++ ++ case 2: ++ *(uint16 *)val = (uint16)(val_l & 0xffff); ++ break; ++ ++ case 1: ++ *(uint8 *)val = (uint8)(val_l & 0xff); ++ break; ++ } ++ ++ ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg, ++ VARG(val, len), len)); ++ ++err: ++ srab_release_grant(robo); ++ ++ return ret; ++} ++ ++/* SRAB interface functions */ ++static dev_ops_t srab = { ++ NULL, ++ NULL, ++ srab_wreg, ++ srab_rreg, ++ "SRAB" ++}; ++ ++#if defined(CONFIG_MACH_NSP) ++void ++srab_sgmii_set_blk(robo_info_t *robo, uint page, uint blk) ++{ ++ uint16 blkaddr; ++ uint16 destblk = (uint16)blk; ++ ++ /* printf("%s page(0x%x) blk(0x%x)\n", __FUNCTION__, page, blk); */ ++ /* check if need to update blk addr */ ++ robo->ops->read_reg(robo, page, REG_SGMII_BLK_ADDR, &blkaddr, sizeof(blkaddr)); ++ if (blkaddr!=destblk) { ++ /* write block address */ ++ robo->ops->write_reg(robo, page, REG_SGMII_BLK_ADDR, &destblk, sizeof(destblk)); ++ } ++} ++ ++int ++srab_sgmii_rreg(robo_info_t *robo, uint8 page, uint16 reg, uint16 *val) ++{ ++ uint blk = reg&0xfff0; ++ uint8 off = reg&0x000f; ++ uint16 data; ++ ++ if (reg&0x8000) ++ off|=0x10; ++ ++ /* spi offset is only even (multiple of 2) */ ++ off = off*2; ++ ++ /* check block addr */ ++ srab_sgmii_set_blk(robo, page, blk); ++ ++ /* read offset register */ ++ robo->ops->read_reg(robo, page, off, &data, sizeof(data)); ++ //printf("%s page(0x%x) blk(0x%x) offset(0x%x) value(0x%x)\n", __FUNCTION__, page, blk, off, data); ++ *val = data; ++ ++ return 0; ++} ++ ++int ++srab_sgmii_wreg(robo_info_t *robo, uint8 page, uint16 reg, uint16 *val) ++{ ++ uint blk = reg&0xfff0; ++ uint8 off = reg&0x000f; ++ uint16 data=*val; ++ ++ if (reg&0x8000) ++ off|=0x10; ++ ++ /* spi offset is only even (multiple of 2) */ ++ off = off*2; ++ ++ /* check block addr */ ++ srab_sgmii_set_blk(robo, page, blk); ++ ++ /* write offset register */ ++ robo->ops->write_reg(robo, page, off, &data, sizeof(data)); ++ //printf("%s page(0x%x) blk(0x%x) offset(0x%x) value(0x%x)\n", __FUNCTION__, page, blk, off, data); ++ ++ return 0; ++} ++#endif /* defined(CONFIG_MACH_NSP) */ ++ ++/* High level switch configuration functions. */ ++ ++/* Get access to the RoboSwitch */ ++robo_info_t * ++bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr) ++{ ++ robo_info_t *robo; ++ uint32 reset, idx; ++#ifndef _CFE_ ++// const char *et1port, *et1phyaddr; ++ int mdcport = 0, phyaddr = 0; ++#endif /* _CFE_ */ ++ int lan_portenable = 0; ++ ++ /* Allocate and init private state */ ++ if (!(robo = MALLOC(si_osh(sih), sizeof(robo_info_t)))) { ++ ET_ERROR(("robo_attach: out of memory, malloced %d bytes", ++ MALLOCED(si_osh(sih)))); ++ return NULL; ++ } ++ bzero(robo, sizeof(robo_info_t)); ++ ++ robo->h = h; ++ robo->sih = sih; ++ robo->vars = vars; ++ robo->miird = miird; ++ robo->miiwr = miiwr; ++ robo->page = -1; ++ ++ if (IS_BCM5301X_CHIP_ID(sih->chip)) { ++ robo->miird = NULL; ++ robo->miiwr = NULL; ++ robo->srabregs = (srabregs_t *)REG_MAP(SI_NS_CHIPCB_SRAB, SI_CORE_SIZE); ++ } ++ ++ /* Enable center tap voltage for LAN ports using gpio23. Usefull in case when ++ * romboot CFE loads linux over WAN port and Linux enables LAN ports later ++ */ ++ if ((lan_portenable = getgpiopin(robo->vars, "lanports_enable", GPIO_PIN_NOTDEFINED)) != ++ GPIO_PIN_NOTDEFINED) { ++ lan_portenable = 1 << lan_portenable; ++ si_gpioouten(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY); ++ si_gpioout(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY); ++ bcm_mdelay(5); ++ } ++ ++ /* Trigger external reset by nvram variable existance */ ++ if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) != ++ GPIO_PIN_NOTDEFINED) { ++ /* ++ * Reset sequence: RESET low(50ms)->high(20ms) ++ * ++ * We have to perform a full sequence for we don't know how long ++ * it has been from power on till now. ++ */ ++ ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset)); ++ reset = 1 << reset; ++ ++ /* Keep RESET low for 50 ms */ ++ si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY); ++ si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY); ++ bcm_mdelay(50); ++ ++ /* Keep RESET high for at least 20 ms */ ++ si_gpioout(sih, reset, reset, GPIO_DRV_PRIORITY); ++ bcm_mdelay(20); ++ } else { ++ /* In case we need it */ ++ idx = si_coreidx(sih); ++ ++ if (si_setcore(sih, ROBO_CORE_ID, 0)) { ++ /* If we have an internal robo core, reset it using si_core_reset */ ++ ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__)); ++ si_core_reset(sih, 0, 0); ++ robo->corerev = si_corerev(sih); ++ } ++ else if (IS_BCM5301X_CHIP_ID(sih->chip)) { ++ srab_interface_reset(robo); ++ srab_rreg(robo, PAGE_MMR, REG_VERSION_ID, &robo->corerev, 1); ++ } ++ else { ++ ET_ERROR(("%s: unknown switch\n", __FUNCTION__)); ++ } ++ si_setcoreidx(sih, idx); ++ ET_MSG(("%s: Internal robo rev %d\n", __FUNCTION__, robo->corerev)); ++ } ++ ++ if (IS_BCM5301X_CHIP_ID(sih->chip)) { ++ int rc; ++ ++ rc = srab_rreg(robo, PAGE_MMR, REG_DEVICE_ID, &robo->devid32, sizeof(uint32)); ++ ++ ET_MSG(("%s: devid read %ssuccesfully via srab: 0x%x\n", ++ __FUNCTION__, rc ? "un" : "", robo->devid32)); ++ ++ robo->ops = &srab; ++ if ((rc != 0) || (robo->devid32 == 0)) { ++ ET_ERROR(("%s: error reading devid\n", __FUNCTION__)); ++ MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t)); ++ return NULL; ++ } ++ ET_MSG(("%s: devid32: 0x%x\n", __FUNCTION__, robo->devid32)); ++ printf("%s: devid32: 0x%x\n", __FUNCTION__, robo->devid32); ++ } ++ ++#ifndef _CFE_ ++ if (!robo->ops) { ++ ET_ERROR(("%s: unknown switch", __FUNCTION__)); ++ goto error; ++ } ++#endif /* _CFE_ */ ++ ++ /* sanity check */ ++ ASSERT(robo->ops); ++ ASSERT(robo->ops->write_reg); ++ ASSERT(robo->ops->read_reg); ++ ASSERT(ROBO_IS_BCM5301X(robo->devid32)); ++ ++#ifndef _CFE_ ++ /* nvram variable switch_mode controls the power save mode on the switch ++ * set the default value in the beginning ++ */ ++ robo->pwrsave_mode_manual = getintvar(robo->vars, "switch_mode_manual"); ++ robo->pwrsave_mode_auto = getintvar(robo->vars, "switch_mode_auto"); ++ ++ /* Determining what all phys need to be included in ++ * power save operation ++ */ ++ //et1port = getvar(vars, "et1mdcport"); ++ //if (et1port) ++ // mdcport = bcm_atoi(et1port); ++ ++ //et1phyaddr = getvar(vars, "et1phyaddr"); ++ //if (et1phyaddr) ++ // phyaddr = bcm_atoi(et1phyaddr); ++ ++ if ((mdcport == 0) && (phyaddr == 4)) ++ /* For 5325F switch we need to do only phys 0-3 */ ++ robo->pwrsave_phys = 0xf; ++ else ++ /* By default all 5 phys are put into power save if there is no link */ ++ robo->pwrsave_phys = 0x1f; ++#endif /* _CFE_ */ ++ ++ return robo; ++ ++#ifndef _CFE_ ++error: ++ bcm_robo_detach(robo); ++ return NULL; ++#endif /* _CFE_ */ ++} ++ ++/* Release access to the RoboSwitch */ ++void ++bcm_robo_detach(robo_info_t *robo) ++{ ++ if (robo->srabregs) ++ REG_UNMAP(robo->srabregs); ++ ++ MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t)); ++} ++ ++/* Enable the device and set it to a known good state */ ++int ++bcm_robo_enable_device(robo_info_t *robo) ++{ ++ int ret = 0; ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++ ++ return ret; ++} ++ ++/* Port flags */ ++#define FLAG_TAGGED 't' /* output tagged (external ports only) */ ++#define FLAG_UNTAG 'u' /* input & output untagged (CPU port only, for OS (linux, ...) */ ++#define FLAG_LAN '*' /* input & output untagged (CPU port only, for CFE */ ++ ++/* port descriptor */ ++typedef struct { ++ uint32 untag; /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */ ++ uint32 member; /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */ ++ uint8 ptagr; /* port tag register address (Page 0x34 Address 0x10-0x1F) */ ++ uint8 cpu; /* is this cpu port? */ ++} pdesc_t; ++ ++pdesc_t pdesc97[] = { ++ /* 5395/5397/5398/53115S is 0 ~ 7. port 8 is IMP port. */ ++ /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0}, ++ /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0}, ++ /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0}, ++ /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0}, ++ /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0}, ++#ifdef GMAC3 ++ /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0}, ++ /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0}, ++ /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0}, ++#else /* !GMAC3 */ ++ /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 1}, ++ /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 1}, ++ /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 1}, ++#endif /* !GMAC3 */ ++ /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1}, ++}; ++ ++/* Configure the VLANs */ ++int ++bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr) ++{ ++ uint8 val8; ++ uint16 val16; ++ uint32 val32; ++ pdesc_t *pdesc; ++ int pdescsz; ++ uint16 vid; ++ uint8 arl_entry[8] = { 0 }; ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ /* setup global vlan configuration */ ++ /* VLAN Control 0 Register (Page 0x34, Address 0) */ ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); ++ val8 |= ((1 << 7) | /* enable 802.1Q VLAN */ ++ (3 << 5)); /* individual VLAN learning mode */ ++ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); ++ /* VLAN Control 1 Register (Page 0x34, Address 1) */ ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); ++ val8 |= ((1 << 2) | /* enable RSV multicast V Fwdmap */ ++ (1 << 3)); /* enable RSV multicast V Untagmap */ ++ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); ++ ++ arl_entry[0] = mac_addr[5]; ++ arl_entry[1] = mac_addr[4]; ++ arl_entry[2] = mac_addr[3]; ++ arl_entry[3] = mac_addr[2]; ++ arl_entry[4] = mac_addr[1]; ++ arl_entry[5] = mac_addr[0]; ++ ++ /* Initialize the MAC Addr Index Register */ ++ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, ++ arl_entry, ETHER_ADDR_LEN); ++ ++ pdesc = pdesc97; ++ pdescsz = sizeof(pdesc97) / sizeof(pdesc_t); ++ ++ /* check if p5 is not CPU port */ ++ if (!robo_is_port5_cpu()) { ++ pdesc[5].cpu = 0; ++ } ++ ++ /* setup each vlan. max. 16 vlans. */ ++ /* force vlan id to be equal to vlan number */ ++ for (vid = 0; vid < VLAN_NUMVLANS; vid ++) { ++ char vlanports[] = "vlanXXXXports"; ++ char port[] = "XXXX", *next; ++ const char *ports, *cur; ++ uint32 untag = 0; ++ uint32 member = 0; ++ int pid, len; ++ int cpuport=0; ++ ++ /* no members if VLAN id is out of limitation */ ++ if (vid > VLAN_MAXVID) ++ goto vlan_setup; ++ ++ /* get vlan member ports from nvram */ ++ sprintf(vlanports, "vlan%dports", vid); ++ ports = getvar(robo->vars, vlanports); ++ ++ ET_MSG(("%s: getvar(%s) port %s \n", ++ __FUNCTION__, vlanports, ports)); ++ /* vid == 0 is invalid?? */ ++ if (vid == 0) { ++ if (ports) ++ ET_ERROR(("VID 0 is set in nvram, Ignoring\n")); ++ continue; ++ } ++ ++ /* disable this vlan if not defined */ ++ if (!ports) ++ goto vlan_setup; ++ ++ /* ++ * setup each port in the vlan. cpu port needs special handing ++ * (with or without output tagging) to support linux/pmon/cfe. ++ */ ++ for (cur = ports; cur; cur = next) { ++ /* tokenize the port list */ ++ while (*cur == ' ') ++ cur ++; ++ next = bcmstrstr(cur, " "); ++ len = next ? next - cur : strlen(cur); ++ if (!len) ++ break; ++ if (len > sizeof(port) - 1) ++ len = sizeof(port) - 1; ++ strncpy(port, cur, len); ++ port[len] = 0; ++ ++ /* make sure port # is within the range */ ++ pid = bcm_atoi(port); ++ if (pid >= pdescsz) { ++ ET_ERROR(("robo_config_vlan: port %d in vlan%dports is out " ++ "of range[0-%d]\n", pid, vid, pdescsz)); ++ continue; ++ } ++ if (pid == 6) { ++ ET_ERROR(("robo_config_vlan: port %d in vlan%dports is not valid\n", pid, vid)); ++ continue; ++ } ++ ++ /* build VLAN registers values */ ++#ifndef _CFE_ ++ if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) || ++ (pdesc[pid].cpu && strchr(port, FLAG_UNTAG))) ++#endif ++ untag |= pdesc[pid].untag; ++ ++ member |= pdesc[pid].member; ++ ++ /* set port tag - applies to untagged ingress frames */ ++ /* Default Port Tag Register (Page 0x34, Address 0x10-0x1D) */ ++#ifdef _CFE_ ++#define FL FLAG_LAN ++#else ++#define FL FLAG_UNTAG ++#endif /* _CFE_ */ ++ if (!pdesc[pid].cpu || strchr(port, FL)) { ++ val16 = ((0 << 13) | /* priority - always 0 */ ++ vid); /* vlan id */ ++ robo->ops->write_reg(robo, PAGE_VLAN, pdesc[pid].ptagr, ++ &val16, sizeof(val16)); ++ } ++ if (pdesc[pid].cpu) ++ cpuport=pid; ++ } ++ ++ /* Add static ARL entries */ ++ /* Set the VLAN Id in VLAN ID Index Register */ ++ val8 = vid; ++ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, ++ &val8, sizeof(val8)); ++ ++ /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0 ++ * Register. ++ */ ++ arl_entry[6] = vid; ++ arl_entry[7] = 0x0; ++ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, ++ arl_entry, sizeof(arl_entry)); ++ ++ /* Set the Static bit , Valid bit and Port ID fields in ++ * ARL Table Data Entry 0 Register ++ */ ++ //val16 = 0xc100; //0xc020; ++ val32 = 0x08000 + (1<ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0, ++ &val32, sizeof(val32)); ++ ++ /* Clear the ARL_R/W bit and set the START/DONE bit in ++ * the ARL Read/Write Control Register. ++ */ ++ val8 = 0x80; ++ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, ++ &val8, sizeof(val8)); ++ /* Wait for write to complete */ ++ SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, ++ &val8, sizeof(val8)), ((val8 & 0x80) != 0)), ++ 100 /* usec */); ++ ++vlan_setup: ++ /* setup VLAN ID and VLAN memberships */ ++ ++ val32 = (untag | /* untag enable */ ++ member); /* vlan members */ ++ { ++ uint8 vtble, vtbli, vtbla; ++ ++ vtble = REG_VTBL_ENTRY_5395; ++ vtbli = REG_VTBL_INDX_5395; ++ vtbla = REG_VTBL_ACCESS_5395; ++ ++ /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32, ++ sizeof(val32)); ++ /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */ ++ val16 = vid; /* vlan id */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16, ++ sizeof(val16)); ++ ++ /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */ ++ val8 = ((1 << 7) | /* start command */ ++ 0); /* write */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8, ++ sizeof(val8)); ++ } ++ } ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++ ++ return 0; ++} ++ ++/* Enable switching/forwarding */ ++int ++bcm_robo_enable_switch(robo_info_t *robo) ++{ ++ int i, max_port_ind, ret = 0; ++ uint8 val8; ++ uint16 val16; ++ bool bcm_tag_on=false; ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++ char *var; ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ uint32_t val32; ++#if defined(CONFIG_IPROC_OTP) ++ void *oh; ++#endif /* defined(CONFIG_IPROC_OTP) */ ++ uint32_t skuid=0; ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++ /* check if brcm tag is turned off */ ++ bcm_tag_on=true; ++ var = getvar(NULL, "brcmtag"); ++ if (var) { ++ int tag = bcm_strtoul(var, NULL, 0); ++ if (tag==0) { ++ ET_ERROR(("BRCM TAG disabled\n")); ++ /* if brcm tag == 0 tag disabled */ ++ bcm_tag_on = false; ++ } ++ } ++#elif defined(CONFIG_MACH_NSP) ++ bcm_tag_on=true; ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ /* Switch Mode register (Page 0, Address 0x0B) */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ ++ /* Bit 1 enables switching/forwarding */ ++ if (!(val8 & (1 << 1))) { ++ /* Set unmanaged mode */ ++ val8 &= (~(1 << 0)); ++ ++ /* Enable forwarding */ ++ val8 |= (1 << 1); ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ ++ /* Read back */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ if (!(val8 & (1 << 1))) { ++ ET_ERROR(("robo_enable_switch: enabling forwarding failed\n")); ++ ret = -1; ++ } ++ ++ /* No spanning tree for unmanaged mode */ ++ val8 = 0; ++ if (ROBO_IS_BCM5301X(robo->devid32)) ++ max_port_ind = REG_CTRL_PORT7; ++ else ++ max_port_ind = REG_CTRL_PORT4; ++ ++ for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) { ++ if (ROBO_IS_BCM5301X(robo->devid32) && i == REG_CTRL_PORT6) ++ continue; ++ robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8)); ++ } ++ ++ /* No spanning tree on IMP port too */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8)); ++ } ++ else { ++ /* Set managed mode */ ++ val8 |= 1; ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ } ++ ++ if (ROBO_IS_BCM5301X(robo->devid32)) { ++ /* ++ * Port N GMII Port States Override Register (Page 0x00 , address Offset: 0x0e , 0x58-0x5d and 0x5f ) ++ * SPEED/ DUPLEX_MODE/ LINK_STS ++ */ ++ ++ /* check if p5 is CPU port */ ++ if (robo_is_port5_cpu()) { ++ /* Over ride GMAC0 Port5 status to make it link by default */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT5_GMIIPO, &val8, sizeof(val8)); ++ /* 2G_ENABLED: */ ++ val8 |= 0xf1; /* Make Link pass and override it. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT5_GMIIPO, &val8, sizeof(val8)); ++ } ++ ++ /* Over ride GMAC1 Port7 status to make it link by default */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT7_GMIIPO, &val8, sizeof(val8)); ++ /* 2G_ENABLED: */ ++ val8 |= 0xf1; /* Make Link pass and override it. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT7_GMIIPO, &val8, sizeof(val8)); ++ ++ /* Over ride GMAC2 IMP(Port8) status to make it link by default */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8)); ++ /* 2G_ENABLED: ++ * Page :0x00 ++ * ( Offset: 0xe ) IMP Port States Override Register ++ * [6]: GMII SPEED UP 2G ++ */ ++ val8 |= 0xf1; /* Make Link pass and override it. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8)); ++ ++ /* GMAC2 IMP(Port8) config BRCM tag */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_MMR, REG_BRCM_HDR, &val8, sizeof(val8)); ++ if (bcm_tag_on) ++ val8 |= 0x01; ++ else ++ val8 &= 0xfe; ++ robo->ops->write_reg(robo, PAGE_MMR, REG_BRCM_HDR, &val8, sizeof(val8)); ++ ++ /* GMAC2 IMP(Port8) Enable receive all packets */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8)); ++ val8 |= 0x1c; ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8)); ++ ++ /* GMAC2 IMP(Port8) IMP port Enable */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++ val8 |= 0x80; ++ robo->ops->write_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++ } ++ ++ if (bcm_tag_on) { ++ /* GMAC2 IMP(Port8) enable ignore crc check */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8)); ++ val8 |= 0x01; ++ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8)); ++ } ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++ ++ /* make sure external ports are not in protected mode (Page 0, Address 0x24) */ ++ val16 = 0; ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PPORT, &val16, sizeof(val16)); ++ ++ ++#if defined(CONFIG_IPROC_OTP) ++ /* check if need to turn off unused ports */ ++ /* Check for Vega chip - get OTP skuid */ ++ bcm5301x_otp_init_fptr = symbol_get(bcm5301x_otp_init); ++ bcm5301x_otp_read_dword_fptr = symbol_get(bcm5301x_otp_read_dword); ++ bcm5301x_otp_exit_fptr = symbol_get(bcm5301x_otp_exit); ++ ++ ++ if ( (bcm5301x_otp_init_fptr != NULL) ++ && ( bcm5301x_otp_read_dword_fptr != NULL) ++ && (bcm5301x_otp_exit_fptr != NULL)) { ++ ++ oh = (*bcm5301x_otp_init_fptr)(); ++ (*bcm5301x_otp_read_dword_fptr)(oh, 0x0f, &skuid); ++ (*bcm5301x_otp_exit_fptr)(); ++ } ++ printf("%s OTP: offset 0x0f = 0x%x\n", __FUNCTION__, skuid); ++#else /* defined(CONFIG_IPROC_OTP) */ ++ printf("%s IPROC OTP is not configured, can not determine skuid\n", __FUNCTION__); ++#endif /* defined(CONFIG_IPROC_OTP) */ ++ ++ if (IS_BCM5301X_CHIP_ID(sih->chip)) { ++ printf("%s Northstar Family chip\n", __FUNCTION__); ++ if ( (robo->devid32==DEVID53010 && skuid==OTP_SKU_ID_53014) ++ || (robo->devid32==DEVID53011 && skuid==OTP_SKU_ID_53015) ++ || (robo->devid32==DEVID53012 && skuid==OTP_SKU_ID_53016) ) { ++ /* check for VEGA */ ++ printf("%s Vega chip\n", __FUNCTION__); ++ /* only have ports 0-1, power down phy of ports 2-4 */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ val32 |= 0x1c; /* power down ports 2-4. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ } ++ else if ( robo->devid32 == DEVID53025 ) { ++ /* for nsp, skuid is actually gphy_ext_pwrdown[4-0] bits, ++ mask off other bits */ ++ skuid &= 0x1f; ++ printf("%s Checking powered down port (0x%x)\n", __FUNCTION__, skuid); ++ if (skuid == 0x1c) { ++ printf("%s Powering down ports 2-4\n", __FUNCTION__); ++ /* only have ports 0-1, power down phy of ports 2-4 */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ val32 |= 0x1c; /* power down ports 2-4. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ } else if ((skuid == 0x07) || (skuid == 0x06)) { ++ printf("%s Powering down ports 0-2\n", __FUNCTION__); ++ /* only have ports 3-4, power down phy of ports 1-2 */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ val32 |= 0x6; /* power down ports 1-2. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ /* power down port 0 */ ++ val32 = 0xfff; ++ robo->ops->write_reg(robo, PAGE_GPHYP0, PAGE_GPHYP0_DSP_COEF_ADDR, &val32, sizeof(val32)); ++ val32 = 0x7fff; ++ robo->ops->write_reg(robo, PAGE_GPHYP0, PAGE_GPHYP0_DSP_COEF, &val32, sizeof(val32)); ++ } ++ } ++ } ++ ++#if defined(CONFIG_MACH_NSP) ++ if ( robo_is_port_cfg(PORTCFG_5, PORTCFG_SGMII) ++ || robo_is_port_cfg(PORTCFG_4, PORTCFG_SGMII) ) { ++ /* either port5 or port4 SGMII enabled */ ++ /* enable serdes */ ++ robo_serdes_reset_core(robo, PAGE_P5_SGMII); ++ if (robo_is_port_cfg(PORTCFG_5, PORTCFG_SGMII)) { ++ /* enable port5 sgmii */ ++ robo_serdes_init(robo, PAGE_P5_SGMII); ++ } ++ if (robo_is_port_cfg(PORTCFG_4, PORTCFG_SGMII)) { ++ /* enable port4 sgmii */ ++ robo_serdes_init(robo, PAGE_P4_SGMII); ++ } ++ /* start serdes pll */ ++ robo_serdes_start_pll(robo, PAGE_P5_SGMII); ++ } ++#endif /* defined(CONFIG_MACH_NSP) */ ++ ++ return ret; ++} ++ ++void ++robo_reset_mib(robo_info_t *robo) ++{ ++ uint8 val8; ++ ++ robo->ops->read_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++ /* set clear mib bit */ ++ val8 |= 0x01; ++ robo->ops->write_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++ /* clear clear mib bit */ ++ val8 &= 0xfe; ++ robo->ops->write_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++} ++ ++void ++robo_dump_mib(robo_info_t *robo) ++{ ++ uint32 tx32, rx32; ++ int port; ++ ++ for (port=0x20; port<=0x28; port++) { ++ if (port==0x26) ++ continue; ++ robo->ops->read_reg(robo, port, 0x00, &tx32, sizeof(tx32)); ++ robo->ops->read_reg(robo, port, 0x50, &rx32, sizeof(rx32)); ++ printf("port%d: TX Octets: 0x%x; RX Octets: 0x%x\n", port-0x20, tx32, rx32); ++ } ++} ++ ++void ++robo_bprintf_mib(robo_info_t *robo, struct bcmstrbuf *b) ++{ ++ uint32 tx32, txdrp32, txbcst32, txmcst32, txcol32, ucst32, txpause32; ++ uint32 rx32, rxusz32, rxosz32, rxale32, rxfcs32, rxdrp32, rxsachg32, rxfrag32, rxsym32, irec32, orec32, rxdis32; ++ int port; ++ ++ for (port=0x20; port<=0x28; port++) { ++ if (port==0x26) ++ continue; ++ robo->ops->read_reg(robo, port, 0x00, &tx32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x08, &txdrp32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x10, &txbcst32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x14, &txmcst32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x18, &ucst32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x1c, &txcol32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x38, &txpause32, sizeof(uint32)); ++ bcm_bprintf(b, "port%d TX: Octs(%x); Drp(%x) Bcst(%x) Mcst(%x) Ucst(%x) Col(%x) Pause(%x)\n", ++ port-0x20, tx32, txdrp32, txbcst32, txmcst32, ucst32, txcol32, txpause32); ++ robo->ops->read_reg(robo, port, 0x50, &rx32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x58, &rxusz32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x78, &rxosz32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x80, &rxale32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x84, &rxfcs32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x90, &rxdrp32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x94, &ucst32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xa0, &rxsachg32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xa4, &rxfrag32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xac, &rxsym32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xb0, &irec32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xb4, &orec32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xc0, &rxdis32, sizeof(uint32)); ++ bcm_bprintf(b, "port%d RX: Octs(%x); USz(%x) OSz(%x) AlgnEr(%x) FcsEr(%x) Drp(%x) Ucst(%x); SacCh(%x); Frag(%x) SymEr(%x) IRngEr(%x) ORngEr(%x) Dis(%x)\n", ++ port-0x20, rx32, rxusz32, rxosz32, rxale32, rxfcs32, rxdrp32, ++ ucst32, rxsachg32, rxfrag32, rxsym32, irec32, orec32, rxdis32); ++ } ++ robo_reset_mib(robo); ++} ++ ++ ++void ++robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b) ++{ ++ uint8 val8; ++ uint16 val16; ++ uint32 val32; ++ pdesc_t *pdesc; ++ int pdescsz; ++ int i; ++ ++ bcm_bprintf(b, "%s:\n", robo->ops->desc); ++ if (robo->miird == NULL && !strcmp(robo->ops->desc, "SPI (GPIO)")) ++ bcm_bprintf(b, "SPI gpio pins: ss %d sck %d mosi %d miso %d\n", ++ robo->ss, robo->sck, robo->mosi, robo->miso); ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ /* Dump registers interested */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ bcm_bprintf(b, "(0x00,0x0B)Switch mode regsiter: 0x%02x\n", val8); ++ ++ pdesc = pdesc97; ++ pdescsz = sizeof(pdesc97) / sizeof(pdesc_t); ++ ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); ++ bcm_bprintf(b, "(0x34,0x00)VLAN control 0 register: 0x%02x\n", val8); ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); ++ bcm_bprintf(b, "(0x34,0x01)VLAN control 1 register: 0x%02x\n", val8); ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8)); ++ { ++ uint8 vtble, vtbli, vtbla; ++ ++ vtble = REG_VTBL_ENTRY_5395; ++ vtbli = REG_VTBL_INDX_5395; ++ vtbla = REG_VTBL_ACCESS_5395; ++ ++ for (i = 0; i <= VLAN_MAXVID; i++) { ++ /* VLAN Table Address Index Register (Page 0x05, Address 0x61-0x62/0x81-0x82) */ ++ val16 = i; /* vlan id */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16, ++ sizeof(val16)); ++ /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */ ++ val8 = ((1 << 7) | /* start command */ ++ 1); /* read */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8, ++ sizeof(val8)); ++ /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */ ++ robo->ops->read_reg(robo, PAGE_VTBL, vtble, &val32, ++ sizeof(val32)); ++ bcm_bprintf(b, "VLAN %d untag bits: 0x%02x member bits: 0x%02x\n", ++ i, (val32 & 0x3fe00) >> 9, (val32 & 0x1ff)); ++ } ++ } ++ for (i = 0; i < pdescsz; i++) { ++ robo->ops->read_reg(robo, PAGE_VLAN, pdesc[i].ptagr, &val16, sizeof(val16)); ++ bcm_bprintf(b, "(0x34,0x%02x)Port %d Tag: 0x%04x\n", pdesc[i].ptagr, i, val16); ++ } ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++} ++ ++#ifndef _CFE_ ++/* ++ * Update the power save configuration for ports that changed link status. ++ */ ++void ++robo_power_save_mode_update(robo_info_t *robo) ++{ ++ uint phy; ++ ++ for (phy = 0; phy < MAX_NO_PHYS; phy++) { ++ if (robo->pwrsave_mode_auto & (1 << phy)) { ++ ET_MSG(("%s: set port %d to auto mode\n", ++ __FUNCTION__, phy)); ++ robo_power_save_mode(robo, ROBO_PWRSAVE_AUTO, phy); ++ } ++ } ++ ++ return; ++} ++ ++static int32 ++robo_power_save_mode_clear_auto(robo_info_t *robo, int32 phy) ++{ ++ return -1; ++} ++ ++static int32 ++robo_power_save_mode_clear_manual(robo_info_t *robo, int32 phy) ++{ ++ return -1; ++ ++} ++ ++/* ++ * Function which periodically checks the power save mode on the switch ++ */ ++int32 ++robo_power_save_toggle(robo_info_t *robo, int32 normal) ++{ ++ int32 phy; ++ uint16 link_status; ++ ++ ++ /* read the link status of all ports */ ++ robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK, ++ &link_status, sizeof(uint16)); ++ link_status &= 0x1f; ++ ++ /* Take the phys out of the manual mode first so that link status ++ * can be checked. Once out of that mode check the link status ++ * and if any of the link is up do not put that phy into ++ * manual power save mode ++ */ ++ for (phy = 0; phy < MAX_NO_PHYS; phy++) { ++ /* When auto+manual modes are enabled we toggle between ++ * manual and auto modes. When only manual mode is enabled ++ * we toggle between manual and normal modes. When only ++ * auto mode is enabled there is no need to do anything ++ * here since auto mode is one time config. ++ */ ++ if ((robo->pwrsave_phys & (1 << phy)) && ++ (robo->pwrsave_mode_manual & (1 << phy))) { ++ if (!normal) { ++ /* Take the port out of the manual mode */ ++ robo_power_save_mode_clear_manual(robo, phy); ++ } else { ++ /* If the link is down put it back to manual else ++ * remain in the current state ++ */ ++ if (!(link_status & (1 << phy))) { ++ ET_MSG(("%s: link down, set port %d to man mode\n", ++ __FUNCTION__, phy)); ++ robo_power_save_mode(robo, ROBO_PWRSAVE_MANUAL, phy); ++ } ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * Switch the ports to normal mode. ++ */ ++static int32 ++robo_power_save_mode_normal(robo_info_t *robo, int32 phy) ++{ ++ int32 error = 0; ++ ++ /* If the phy in the power save mode come out of it */ ++ switch (robo->pwrsave_mode_phys[phy]) { ++ case ROBO_PWRSAVE_AUTO_MANUAL: ++ case ROBO_PWRSAVE_AUTO: ++ error = robo_power_save_mode_clear_auto(robo, phy); ++ if ((error == -1) || ++ (robo->pwrsave_mode_phys[phy] == ROBO_PWRSAVE_AUTO)) ++ break; ++ ++ case ROBO_PWRSAVE_MANUAL: ++ error = robo_power_save_mode_clear_manual(robo, phy); ++ break; ++ ++ default: ++ break; ++ } ++ ++ return error; ++} ++ ++/* ++ * Switch all the inactive ports to auto power down mode. ++ */ ++static int32 ++robo_power_save_mode_auto(robo_info_t *robo, int32 phy) ++{ ++ return -1; ++} ++ ++/* ++ * Switch all the inactive ports to manual power down mode. ++ */ ++static int32 ++robo_power_save_mode_manual(robo_info_t *robo, int32 phy) ++{ ++ uint16 val16; ++ ++ /* For both 5325 and 53115 the link status register is the same */ ++ robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK, ++ &val16, sizeof(val16)); ++ if (val16 & (0x1 << phy)) ++ return 0; ++ ++ return -1; ++} ++ ++/* ++ * Set power save modes on the robo switch ++ */ ++int32 ++robo_power_save_mode(robo_info_t *robo, int32 mode, int32 phy) ++{ ++ int32 error = -1; ++ ++ if (phy > MAX_NO_PHYS) { ++ ET_ERROR(("Passed parameter phy is out of range\n")); ++ return -1; ++ } ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ switch (mode) { ++ case ROBO_PWRSAVE_NORMAL: ++ /* If the phy in the power save mode come out of it */ ++ error = robo_power_save_mode_normal(robo, phy); ++ break; ++ ++ case ROBO_PWRSAVE_AUTO_MANUAL: ++ /* If the switch supports auto and manual power down ++ * enable both of them ++ */ ++ case ROBO_PWRSAVE_AUTO: ++ error = robo_power_save_mode_auto(robo, phy); ++ if ((error == -1) || (mode == ROBO_PWRSAVE_AUTO)) ++ break; ++ ++ case ROBO_PWRSAVE_MANUAL: ++ error = robo_power_save_mode_manual(robo, phy); ++ break; ++ ++ default: ++ break; ++ } ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++ ++ return error; ++} ++ ++/* ++ * Get the current power save mode of the switch ports. ++ */ ++int32 ++robo_power_save_mode_get(robo_info_t *robo, int32 phy) ++{ ++ ASSERT(robo); ++ ++ if (phy >= MAX_NO_PHYS) ++ return -1; ++ ++ return robo->pwrsave_mode_phys[phy]; ++} ++ ++/* ++ * Configure the power save mode for the switch ports. ++ */ ++int32 ++robo_power_save_mode_set(robo_info_t *robo, int32 mode, int32 phy) ++{ ++ int32 error; ++ ++ ASSERT(robo); ++ ++ if (phy >= MAX_NO_PHYS) ++ return -1; ++ ++ error = robo_power_save_mode(robo, mode, phy); ++ ++ if (error) ++ return error; ++ ++ if (mode == ROBO_PWRSAVE_NORMAL) { ++ robo->pwrsave_mode_manual &= ~(1 << phy); ++ robo->pwrsave_mode_auto &= ~(1 << phy); ++ } else if (mode == ROBO_PWRSAVE_AUTO) { ++ robo->pwrsave_mode_auto |= (1 << phy); ++ robo->pwrsave_mode_manual &= ~(1 << phy); ++ robo_power_save_mode_clear_manual(robo, phy); ++ } else if (mode == ROBO_PWRSAVE_MANUAL) { ++ robo->pwrsave_mode_manual |= (1 << phy); ++ robo->pwrsave_mode_auto &= ~(1 << phy); ++ robo_power_save_mode_clear_auto(robo, phy); ++ } else { ++ robo->pwrsave_mode_auto |= (1 << phy); ++ robo->pwrsave_mode_manual |= (1 << phy); ++ } ++ ++ return 0; ++} ++#endif /* _CFE_ */ ++ ++void ++robo_watchdog(robo_info_t *robo) ++{ ++ return; ++} ++ ++int ++robo_write_reg(void *rih, unsigned char page, unsigned char reg, void *val, int len) ++{ ++ robo_info_t *robo = (robo_info_t*)rih; ++ return robo->ops->write_reg(robo, (uint8)page, (uint8)reg, val, len); ++} ++ ++ ++int ++robo_read_reg(void *rih, unsigned char page, unsigned char reg, void *val, int len) ++{ ++ robo_info_t *robo = (robo_info_t*)rih; ++ return robo->ops->read_reg(robo, (uint8)page, (uint8)reg, val, len); ++} ++ ++ ++int ++robo_is_port5_cpu(void) ++{ ++ char name[16]; ++ char *var; ++ ++ /* get port5 config */ ++ sprintf(name, PORTCFG, PORTCFG_5); ++ var = getvar(NULL, name); ++ ++ /* check if not CPU port */ ++ if (var == NULL) { ++ /* if no port 5 config then CPU port */ ++ return 1; ++ } ++ /* now check if valid CONFIGURATION */ ++ if (strcmp(var, PORTCFG_RGMII)==0) { ++ printf("%s port5 is configured as RGMII port\n", __FUNCTION__); ++ return 0; ++ } ++ if (strcmp(var, PORTCFG_SGMII)==0) { ++ printf("%s port5 is configured as SGMII port\n", __FUNCTION__); ++ return 0; ++ } ++ if (strcmp(var, PORTCFG_GPHY)==0) { ++ printf("%s port5 is configured as GPHY port\n", __FUNCTION__); ++ return 0; ++ } ++ ++ printf("%s port5 has UNKNOWN configuration: %s\n", __FUNCTION__, var); ++ /* must be CPU port */ ++ return 1; ++} ++ ++ ++int ++robo_is_port_cfg(int port, char *cfg) ++{ ++ char name[16]; ++ char *var; ++ ++ /* get port5 config */ ++ sprintf(name, PORTCFG, port); ++ var = getvar(NULL, name); ++ if (var == NULL) { ++ /* if no port config then normal port config */ ++ return 0; ++ } ++ ++ if (strcmp(var, cfg)==0) { ++ /* the port is the configuration we are looing for */ ++ return 1; ++ } ++ ++ /* not config we are looking for */ ++ return 0; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmsrom.c b/drivers/bcmdrivers/gmac/src/shared/bcmsrom.c +new file mode 100755 +index 0000000..be26681 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmsrom.c +@@ -0,0 +1,5109 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Routines to access SPROM and to parse SROM/CIS variables. ++ * ++ * $Id: bcmsrom.c 323253 2012-03-23 17:21:10Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#if defined(__FreeBSD__) || defined(__NetBSD__) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef BCMSPI ++#include ++#endif ++ ++#include ++#include ++ ++#if defined(BCMUSBDEV) ++#include ++#include ++#include ++#endif ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++#include ++#endif ++#include /* for sprom content groking */ ++ ++ ++#if defined(BCMDBG_ERR) || defined(WLTEST) ++#define BS_ERROR(args) printf args ++#else ++#define BS_ERROR(args) ++#endif ++ ++#define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \ ++ (((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \ ++ ((uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \ ++ ((uint8 *)curmap + PCI_BAR0_SPROM_OFFSET)) ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */ ++#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */ ++#endif ++ ++typedef struct varbuf { ++ char *base; /* pointer to buffer base */ ++ char *buf; /* pointer to current position */ ++ unsigned int size; /* current (residual) size in bytes */ ++} varbuf_t; ++extern char *_vars; ++extern uint _varsz; ++ ++#define SROM_CIS_SINGLE 1 ++ ++ ++static int initvars_srom_si(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *count); ++static void _initvars_srom_pci(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b); ++static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count); ++static int initvars_cis_pcmcia(si_t *sih, osl_t *osh, char **vars, uint *count); ++#if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED) ++static int initvars_flash_si(si_t *sih, char **vars, uint *count); ++#endif ++#ifdef BCMSPI ++static int initvars_cis_spi(osl_t *osh, char **vars, uint *count); ++#endif /* BCMSPI */ ++static int sprom_cmd_pcmcia(osl_t *osh, uint8 cmd); ++static int sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data); ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++static int sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data); ++#endif ++static int sprom_read_pci(osl_t *osh, si_t *sih, uint16 *sprom, uint wordoff, uint16 *buf, ++ uint nwords, bool check_crc); ++#if defined(BCMNVRAMW) || defined(BCMNVRAMR) ++static int otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz); ++#endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */ ++static uint16 srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, uint32 cmd, uint wordoff, ++ uint16 data); ++ ++static int initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count); ++static int initvars_flash(si_t *sih, osl_t *osh, char **vp, uint len); ++ ++#if defined(BCMUSBDEV) ++static int get_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs, ++ uint boff, uint16 *srom, uint bsz, bool check_crc); ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++static int set_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs, ++ uint boff, uint16 *srom, uint bsz); ++#endif ++#endif ++ ++#if defined(BCMUSBDEV) ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++/* default to bcm94323 P200, other boards should have OTP programmed */ ++static char BCMATTACHDATA(defaultsromvars_4322usb)[] = ++ "vendid=0x14e4\0" ++ "subvendid=0x0a5c\0" ++ "subdevid=0xbdc\0" ++ "macaddr=00:90:4c:d3:04:73\0" ++ "sromrev=8\0" ++ "devid=0x432b\0" ++ "boardrev=0x1200\0" ++ "boardflags=0xa00\0" ++ "boardflags2=0x602\0" ++ "boardtype=0x04a8\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x0\0" ++ "pdetrange2g=0x0\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x2\0" ++ "tssipos5g=0x1\0" ++ "extpagain5g=0x0\0" ++ "pdetrange5g=0x0\0" ++ "triso5g=0x3\0" ++ "antswctl5g=0x2\0" ++ "maxp2ga0=0x48\0" ++ "itt2ga0=0x20\0" ++ "pa2gw0a0=0xFEA8\0" ++ "pa2gw1a0=0x16CD\0" ++ "pa2gw2a0=0xFAA5\0" ++ "maxp5ga0=0x40\0" ++ "itt5ga0=0x3e\0" ++ "maxp5gha0=0x3c\0" ++ "maxp5gla0=0x40\0" ++ "pa5gw0a0=0xFEB2\0" ++ "pa5gw1a0=0x1471\0" ++ "pa5gw2a0=0xFB1F\0" ++ "pa5glw0a0=0xFEA2\0" ++ "pa5glw1a0=0x149A\0" ++ "pa5glw2a0=0xFAFC\0" ++ "pa5ghw0a0=0xFEC6\0" ++ "pa5ghw1a0=0x13DD\0" ++ "pa5ghw2a0=0xFB48\0" ++ "maxp2ga1=0x48\0" ++ "itt2ga1=0x20\0" ++ "pa2gw0a1=0xFEA3\0" ++ "pa2gw1a1=0x1687\0" ++ "pa2gw2a1=0xFAAA\0" ++ "maxp5ga1=0x40\0" ++ "itt5ga1=0x3e\0" ++ "maxp5gha1=0x3c\0" ++ "maxp5gla1=0x40\0" ++ "pa5gw0a1=0xFEBC\0" ++ "pa5gw1a1=0x14F9\0" ++ "pa5gw2a1=0xFB05\0" ++ "pa5glw0a1=0xFEBE\0" ++ "pa5glw1a1=0x1478\0" ++ "pa5glw2a1=0xFB1A\0" ++ "pa5ghw0a1=0xFEE1\0" ++ "pa5ghw1a1=0x14FD\0" ++ "pa5ghw2a1=0xFB38\0" ++ "cctl=0\0" ++ "ccode=US\0" ++ "regrev=0x0\0" ++ "ledbh0=0xff\0" ++ "ledbh1=0x2\0" ++ "ledbh2=0x3\0" ++ "ledbh3=0xff\0" ++ "leddc=0xa0a0\0" ++ "aa2g=0x3\0" ++ "aa5g=0x3\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0xff\0" ++ "ag3=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_43234usb)[] = ++ "vendid=0x14e4\0" ++ "subvendid=0x0a5c\0" ++ "subdevid=0xbdc\0" ++ "macaddr=00:90:4c:03:21:23\0" ++ "cctl=0\0" ++ "ccode=US\0" ++ "regrev=0x0\0" ++ "ledbh0=0x82\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0x0\0" ++ "aa2g=0x2\0" ++ "aa5g=0x2\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0x2\0" ++ "ag3=0xff\0" ++ "txchain=0x2\0" ++ "rxchain=0x2\0" ++ "antswitch=0\0" ++ "sromrev=8\0" ++ "devid=0x4346\0" ++ "boardrev=0x1403\0" ++ "boardflags=0x200\0" ++ "boardflags2=0x2000\0" ++ "boardtype=0x0521\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x2\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "tssipos5g=0x1\0" ++ "extpagain5g=0x2\0" ++ "pdetrange5g=0x2\0" ++ "triso5g=0x3\0" ++ "antswctl5g=0x0\0" ++ "ofdm2gpo=0x0\0" ++ "ofdm5gpo=0x0\0" ++ "ofdm5glpo=0x0\0" ++ "ofdm5ghpo=0x0\0" ++ "mcs2gpo0=0x0\0" ++ "mcs2gpo1=0x0\0" ++ "mcs2gpo2=0x0\0" ++ "mcs2gpo3=0x0\0" ++ "mcs2gpo4=0x4444\0" ++ "mcs2gpo5=0x4444\0" ++ "mcs2gpo6=0x4444\0" ++ "mcs2gpo7=0x4444\0" ++ "mcs5gpo4=0x2222\0" ++ "mcs5gpo5=0x2222\0" ++ "mcs5gpo6=0x2222\0" ++ "mcs5gpo7=0x2222\0" ++ "mcs5glpo4=0x2222\0" ++ "mcs5glpo5=0x2222\0" ++ "mcs5glpo6=0x2222\0" ++ "mcs5glpo7=0x2222\0" ++ "mcs5ghpo4=0x2222\0" ++ "mcs5ghpo5=0x2222\0" ++ "mcs5ghpo6=0x2222\0" ++ "mcs5ghpo7=0x2222\0" ++ "maxp2ga0=0x42\0" ++ "itt2ga0=0x20\0" ++ "itt5ga0=0x3e\0" ++ "pa2gw0a0=0xFF21\0" ++ "pa2gw1a0=0x13B7\0" ++ "pa2gw2a0=0xFB44\0" ++ "maxp5ga0=0x3E\0" ++ "maxp5gha0=0x3a\0" ++ "maxp5gla0=0x3c\0" ++ "pa5gw0a0=0xFEB2\0" ++ "pa5gw1a0=0x1570\0" ++ "pa5gw2a0=0xFAD6\0" ++ "pa5glw0a0=0xFE64\0" ++ "pa5glw1a0=0x13F7\0" ++ "pa5glw2a0=0xFAF6\0" ++ "pa5ghw0a0=0xFEAB\0" ++ "pa5ghw1a0=0x15BB\0" ++ "pa5ghw2a0=0xFAC6\0" ++ "maxp2ga1=0x42\0" ++ "itt2ga1=0x20\0" ++ "itt5ga1=0x3e\0" ++ "pa2gw0a1=0xFF17\0" ++ "pa2gw1a1=0x13C4\0" ++ "pa2gw2a1=0xFB3C\0" ++ "maxp5ga1=0x3E\0" ++ "maxp5gha1=0x3a\0" ++ "maxp5gla1=0x3c\0" ++ "pa5gw0a1=0xFE6F\0" ++ "pa5gw1a1=0x13CC\0" ++ "pa5gw2a1=0xFAF8\0" ++ "pa5glw0a1=0xFE87\0" ++ "pa5glw1a1=0x14BE\0" ++ "pa5glw2a1=0xFAD6\0" ++ "pa5ghw0a1=0xFE68\0" ++ "pa5ghw1a1=0x13E9\0" ++ "pa5ghw2a1=0xFAF6\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_43235usb)[] = ++ "vendid=0x14e4\0" ++ "subvendid=0x0a5c\0" ++ "subdevid=0xbdc\0" ++ "macaddr=00:90:4c:05:30:01\0" ++ "ccode=US\0" ++ "regrev=0x0\0" ++ "ledbh0=0x82\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0x0\0" ++ "aa2g=0x3\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0xff\0" ++ "ag3=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0\0" ++ "sromrev=8\0" ++ "devid=0x4347\0" ++ "boardrev=0x1113\0" ++ "boardflags=0x200\0" ++ "boardflags2=0x0\0" ++ "boardtype=0x0571\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x2\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "antswctl5g=0x0\0" ++ "ofdm2gpo=0x0\0" ++ "mcs2gpo0=0x0\0" ++ "mcs2gpo1=0x0\0" ++ "mcs2gpo2=0x0\0" ++ "mcs2gpo3=0x0\0" ++ "mcs2gpo4=0x2222\0" ++ "mcs2gpo5=0x2222\0" ++ "mcs2gpo6=0x2222\0" ++ "mcs2gpo7=0x4444\0" ++ "maxp2ga0=0x42\0" ++ "itt2ga0=0x20\0" ++ "pa2gw0a0=0xFF00\0" ++ "pa2gw1a0=0x143C\0" ++ "pa2gw2a0=0xFB27\0" ++ "maxp2ga1=0x42\0" ++ "itt2ga1=0x20\0" ++ "pa2gw0a1=0xFF22\0" ++ "pa2gw1a1=0x142E\0" ++ "pa2gw2a1=0xFB45\0" ++ "tempthresh=120\0" ++ "temps_period=5\0" ++ "temp_hysteresis=5\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_43236usb)[] = ++ "vendid=0x14e4\0" ++ "subvendid=0x0a5c\0" ++ "subdevid=0xbdc\0" ++ "macaddr=00:90:4c:03:21:23\0" ++ "cctl=0\0" ++ "ccode=US\0" ++ "regrev=0x0\0" ++ "ledbh0=0x82\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0x0\0" ++ "aa2g=0x3\0" ++ "aa5g=0x3\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0x2\0" ++ "ag3=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0\0" ++ "sromrev=8\0" ++ "devid=0x4346\0" ++ "boardrev=0x1532\0" ++ "boardflags=0x200\0" ++ "boardflags2=0x2000\0" ++ "boardtype=0x0521\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x2\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "tssipos5g=0x1\0" ++ "extpagain5g=0x2\0" ++ "pdetrange5g=0x2\0" ++ "triso5g=0x3\0" ++ "antswctl5g=0x0\0" ++ "ofdm2gpo=0x33333333\0" ++ "ofdm5gpo=0x0\0" ++ "ofdm5glpo=0x0\0" ++ "ofdm5ghpo=0x0\0" ++ "mcs2gpo0=0x3333\0" ++ "mcs2gpo1=0x3333\0" ++ "mcs2gpo2=0x3333\0" ++ "mcs2gpo3=0x3333\0" ++ "mcs2gpo4=0x5555\0" ++ "mcs2gpo5=0x5555\0" ++ "mcs2gpo6=0x5555\0" ++ "mcs2gpo7=0x5555\0" ++ "mcs5gpo4=0x2222\0" ++ "mcs5gpo5=0x2222\0" ++ "mcs5gpo6=0x2222\0" ++ "mcs5gpo7=0x2222\0" ++ "mcs5glpo4=0x2222\0" ++ "mcs5glpo5=0x2222\0" ++ "mcs5glpo6=0x2222\0" ++ "mcs5glpo7=0x2222\0" ++ "mcs5ghpo4=0x2222\0" ++ "mcs5ghpo5=0x2222\0" ++ "mcs5ghpo6=0x2222\0" ++ "mcs5ghpo7=0x2222\0" ++ "maxp2ga0=0x48\0" ++ "itt2ga0=0x20\0" ++ "itt5ga0=0x3e\0" ++ "pa2gw0a0=0xFFD8\0" ++ "pa2gw1a0=0x171C\0" ++ "pa2gw2a0=0xFB14\0" ++ "maxp5ga0=0x3e\0" ++ "maxp5gha0=0x3a\0" ++ "maxp5gla0=0x3c\0" ++ "pa5gw0a0=0xFE88\0" ++ "pa5gw1a0=0x141C\0" ++ "pa5gw2a0=0xFB17\0" ++ "pa5glw0a0=0xFE8C\0" ++ "pa5glw1a0=0x1493\0" ++ "pa5glw2a0=0xFAFC\0" ++ "pa5ghw0a0=0xFE86\0" ++ "pa5ghw1a0=0x13CC\0" ++ "pa5ghw2a0=0xFB20\0" ++ "maxp2ga1=0x48\0" ++ "itt2ga1=0x20\0" ++ "itt5ga1=0x3e\0" ++ "pa2gw0a1=0x0020\0" ++ "pa2gw1a1=0x1791\0" ++ "pa2gw2a1=0xFB5F\0" ++ "maxp5ga1=0x3e\0" ++ "maxp5gha1=0x3a\0" ++ "maxp5gla1=0x3c\0" ++ "pa5gw0a1=0xFE7E\0" ++ "pa5gw1a1=0x1399\0" ++ "pa5gw2a1=0xFB27\0" ++ "pa5glw0a1=0xFE82\0" ++ "pa5glw1a1=0x13F3\0" ++ "pa5glw2a1=0xFB14\0" ++ "pa5ghw0a1=0xFE96\0" ++ "pa5ghw1a1=0x13BF\0" ++ "pa5ghw2a1=0xFB30\0" ++ "tempthresh=120\0" ++ "temps_period=5\0" ++ "temp_hysteresis=5\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_4319usb)[] = ++ "sromrev=3\0" ++ "vendid=0x14e4\0" ++ "devid=0x4338\0" ++ "boardtype=0x4e7\0" ++ "boardrev=0x1508\0" ++ "boardflags=0x200\0" ++ "xtalfreq=30000\0" ++ "aa2g=3\0" ++ "aa5g=0\0" ++ "ag0=255\0" ++ "opo=0\0" ++ "pa0b0=5756\0" ++ "pa0b1=64121\0" ++ "pa0b2=65153\0" ++ "pa0itssit=62\0" ++ "pa0maxpwr=76\0" ++ "rssismf2g=0xa\0" ++ "rssismc2g=0xb\0" ++ "rssisav2g=0x3\0" ++ "bxa2g=0\0" ++ "tri2g=78\0" ++ "cckdigfilttype=6\0" ++ "rxpo2g=2\0" ++ "cckpo=0\0" ++ "ofdmpo=0x44441111\0" ++ "mcs2gpo0=0xaaaa\0" ++ "mcs2gpo1=0xaaaa\0" ++ "boardnum=1\0" ++ "macaddr=00:90:4c:16:${maclo}\0" ++ "otpimagesize=182\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_4360usb)[] = ++ "sromrev=11\0" ++ "boardtype=0x623\0" ++ "venid=0x14e4\0" ++ "boardvendor=0x14e4\0" ++ "devid=0x43a0\0" ++ "boardrev=0x1101\0" ++ "boardflags=0x10001000\0" ++ "boardflags2=0x0\0" ++ "boardflags3=0x0\0" ++ "macaddr=00:90:4c:0e:60:01\0" ++ "ccode=0\0" ++ "regrev=0\0" ++ "aa2g=0x3\0" ++ "aa5g=0x3\0" ++ "agbg0=0x2\0" ++ "agbg1=0x2\0" ++ "agbg2=0xff\0" ++ "aga0=0x2\0" ++ "aga1=0x2\0" ++ "aga2=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0\0" ++ "tssiposslope2g=1\0" ++ "epagain2g=0\0" ++ "pdgain2g=2\0" ++ "tworangetssi2g=0\0" ++ "papdcap2g=0\0" ++ "femctrl=1\0" ++ "tssiposslope5g=1\0" ++ "epagain5g=0\0" ++ "pdgain5g=2\0" ++ "tworangetssi5g=0\0" ++ "papdcap5g=0\0" ++ "gainctrlsph=0\0" ++ "tempthresh=0xff\0" ++ "tempoffset=0xff\0" ++ "rawtempsense=0x1ff\0" ++ "measpower=0x7f\0" ++ "tempsense_slope=0xff\0" ++ "tempcorrx=0x3f\0" ++ "tempsense_option=0x3\0" ++ "phycal_tempdelta=255\0" ++ "temps_period=15\0" ++ "temps_hysteresis=15\0" ++ "measpower1=0x7f\0" ++ "subband5gver=0x4\0" ++ "pcieingress_war=15\0" ++ "sar2g=18\0" ++ "sar5g=15\0" ++ "noiselvl2ga0=31\0" ++ "noiselvl2ga1=31\0" ++ "noiselvl2ga2=31\0" ++ "noiselvl5gla0=31\0" ++ "noiselvl5gla1=31\0" ++ "noiselvl5gla2=31\0" ++ "noiselvl5gma0=31\0" ++ "noiselvl5gma1=31\0" ++ "noiselvl5gma2=31\0" ++ "noiselvl5gha0=31\0" ++ "noiselvl5gha1=31\0" ++ "noiselvl5gha2=31\0" ++ "noiselvl5gua0=31\0" ++ "noiselvl5gua1=31\0" ++ "noiselvl5gua2=31\0" ++ "rxgainerr2g=0xffff\0" ++ "rxgainerr5g=0xffff,0xffff,0xffff,0xffff\0" ++ "maxp2ga0=76\0" ++ "pa2ga0=0xfe72,0x14c0,0xfac7\0" ++ "rxgains2gelnagaina0=4\0" ++ "rxgains2gtrisoa0=10\0" ++ "rxgains2gtrelnabypa0=1\0" ++ "rxgains5gelnagaina0=4\0" ++ "rxgains5gtrisoa0=11\0" ++ "rxgains5gtrelnabypa0=1\0" ++ "maxp5ga0=72,72,76,76\0" ++"pa5ga0=0xfe75,0x14b5,0xfad4,0xfe97,0x121a,0xfb6e,0xfe7f,0x149d,0xfad0,0xfe7c,0x1431,0xfae6\0" ++ "maxp2ga1=76\0" ++ "pa2ga1=0xfe80,0x1472,0xfabc\0" ++ "rxgains2gelnagaina1=4\0" ++ "rxgains2gtrisoa1=10\0" ++ "rxgains2gtrelnabypa1=1\0" ++ "rxgains5gelnagaina1=4\0" ++ "rxgains5gtrisoa1=11\0" ++ "rxgains5gtrelnabypa1=1\0" ++ "maxp5ga1=72,72,76,76\0" ++"pa5ga1=0xfe72,0x155e,0xfa96,0xfea1,0x125d,0xfb55,0xfe77,0x1596,0xfa8e,0xfe78,0x15e1,0xfa7a\0" ++ "END\0"; ++ ++#endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */ ++#endif /* BCMUSBDEV */ ++ ++ ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++/* Also used by wl_readconfigdata for vars download */ ++char BCMATTACHDATA(mfgsromvars)[VARS_MAX]; ++int BCMATTACHDATA(defvarslen) = 0; ++#endif ++ ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++static char BCMATTACHDATA(defaultsromvars_4331)[] = ++ "sromrev=9\0" ++ "boardrev=0x1104\0" ++ "boardflags=0x200\0" ++ "boardflags2=0x0\0" ++ "boardtype=0x524\0" ++ "boardvendor=0x14e4\0" ++ "boardnum=0x2064\0" ++ "macaddr=00:90:4c:1a:20:64\0" ++ "ccode=0x0\0" ++ "regrev=0x0\0" ++ "ledbh0=0xff\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0xffff\0" ++ "opo=0x0\0" ++ "aa2g=0x7\0" ++ "aa5g=0x7\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0x2\0" ++ "ag3=0xff\0" ++ "pa0b0=0xfe7f\0" ++ "pa0b1=0x15d9\0" ++ "pa0b2=0xfac6\0" ++ "pa0itssit=0x20\0" ++ "pa0maxpwr=0x48\0" ++ "pa1b0=0xfe89\0" ++ "pa1b1=0x14b1\0" ++ "pa1b2=0xfada\0" ++ "pa1lob0=0xffff\0" ++ "pa1lob1=0xffff\0" ++ "pa1lob2=0xffff\0" ++ "pa1hib0=0xfe8f\0" ++ "pa1hib1=0x13df\0" ++ "pa1hib2=0xfafa\0" ++ "pa1itssit=0x3e\0" ++ "pa1maxpwr=0x3c\0" ++ "pa1lomaxpwr=0x3c\0" ++ "pa1himaxpwr=0x3c\0" ++ "bxa2g=0x3\0" ++ "rssisav2g=0x7\0" ++ "rssismc2g=0xf\0" ++ "rssismf2g=0xf\0" ++ "bxa5g=0x3\0" ++ "rssisav5g=0x7\0" ++ "rssismc5g=0xf\0" ++ "rssismf5g=0xf\0" ++ "tri2g=0xff\0" ++ "tri5g=0xff\0" ++ "tri5gl=0xff\0" ++ "tri5gh=0xff\0" ++ "rxpo2g=0xff\0" ++ "rxpo5g=0xff\0" ++ "txchain=0x7\0" ++ "rxchain=0x7\0" ++ "antswitch=0x0\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x4\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "tssipos5g=0x1\0" ++ "elna2g=0xff\0" ++ "extpagain5g=0x2\0" ++ "pdetrange5g=0x4\0" ++ "triso5g=0x3\0" ++ "antswctl5g=0x0\0" ++ "elna5g=0xff\0" ++ "cckbw202gpo=0x0\0" ++ "cckbw20ul2gpo=0x0\0" ++ "legofdmbw202gpo=0x0\0" ++ "legofdmbw20ul2gpo=0x0\0" ++ "legofdmbw205glpo=0x0\0" ++ "legofdmbw20ul5glpo=0x0\0" ++ "legofdmbw205gmpo=0x0\0" ++ "legofdmbw20ul5gmpo=0x0\0" ++ "legofdmbw205ghpo=0x0\0" ++ "legofdmbw20ul5ghpo=0x0\0" ++ "mcsbw202gpo=0x0\0" ++ "mcsbw20ul2gpo=0x0\0" ++ "mcsbw402gpo=0x0\0" ++ "mcsbw205glpo=0x0\0" ++ "mcsbw20ul5glpo=0x0\0" ++ "mcsbw405glpo=0x0\0" ++ "mcsbw205gmpo=0x0\0" ++ "mcsbw20ul5gmpo=0x0\0" ++ "mcsbw405gmpo=0x0\0" ++ "mcsbw205ghpo=0x0\0" ++ "mcsbw20ul5ghpo=0x0\0" ++ "mcsbw405ghpo=0x0\0" ++ "mcs32po=0x0\0" ++ "legofdm40duppo=0x0\0" ++ "maxp2ga0=0x48\0" ++ "itt2ga0=0x20\0" ++ "itt5ga0=0x3e\0" ++ "pa2gw0a0=0xfe7f\0" ++ "pa2gw1a0=0x15d9\0" ++ "pa2gw2a0=0xfac6\0" ++ "maxp5ga0=0x3c\0" ++ "maxp5gha0=0x3c\0" ++ "maxp5gla0=0x3c\0" ++ "pa5gw0a0=0xfe89\0" ++ "pa5gw1a0=0x14b1\0" ++ "pa5gw2a0=0xfada\0" ++ "pa5glw0a0=0xffff\0" ++ "pa5glw1a0=0xffff\0" ++ "pa5glw2a0=0xffff\0" ++ "pa5ghw0a0=0xfe8f\0" ++ "pa5ghw1a0=0x13df\0" ++ "pa5ghw2a0=0xfafa\0" ++ "maxp2ga1=0x48\0" ++ "itt2ga1=0x20\0" ++ "itt5ga1=0x3e\0" ++ "pa2gw0a1=0xfe54\0" ++ "pa2gw1a1=0x1563\0" ++ "pa2gw2a1=0xfa7f\0" ++ "maxp5ga1=0x3c\0" ++ "maxp5gha1=0x3c\0" ++ "maxp5gla1=0x3c\0" ++ "pa5gw0a1=0xfe53\0" ++ "pa5gw1a1=0x14fe\0" ++ "pa5gw2a1=0xfa94\0" ++ "pa5glw0a1=0xffff\0" ++ "pa5glw1a1=0xffff\0" ++ "pa5glw2a1=0xffff\0" ++ "pa5ghw0a1=0xfe6e\0" ++ "pa5ghw1a1=0x1457\0" ++ "pa5ghw2a1=0xfab9\0" ++ "END\0"; ++#endif ++ ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++static char BCMATTACHDATA(defaultsromvars_wltest)[] = ++ "macaddr=00:90:4c:f8:00:01\0" ++ "et0macaddr=00:11:22:33:44:52\0" ++ "et0phyaddr=30\0" ++ "et0mdcport=0\0" ++ "gpio2=robo_reset\0" ++ "boardvendor=0x14e4\0" ++ "boardflags=0x210\0" ++ "boardflags2=0\0" ++ "boardtype=0x04c3\0" ++ "boardrev=0x1100\0" ++ "sromrev=8\0" ++ "devid=0x432c\0" ++ "ccode=0\0" ++ "regrev=0\0" ++ "ledbh0=255\0" ++ "ledbh1=255\0" ++ "ledbh2=255\0" ++ "ledbh3=255\0" ++ "leddc=0xffff\0" ++ "aa2g=3\0" ++ "ag0=2\0" ++ "ag1=2\0" ++ "aa5g=3\0" ++ "aa0=2\0" ++ "aa1=2\0" ++ "txchain=3\0" ++ "rxchain=3\0" ++ "antswitch=0\0" ++ "itt2ga0=0x20\0" ++ "maxp2ga0=0x48\0" ++ "pa2gw0a0=0xfe9e\0" ++ "pa2gw1a0=0x15d5\0" ++ "pa2gw2a0=0xfae9\0" ++ "itt2ga1=0x20\0" ++ "maxp2ga1=0x48\0" ++ "pa2gw0a1=0xfeb3\0" ++ "pa2gw1a1=0x15c9\0" ++ "pa2gw2a1=0xfaf7\0" ++ "tssipos2g=1\0" ++ "extpagain2g=0\0" ++ "pdetrange2g=0\0" ++ "triso2g=3\0" ++ "antswctl2g=0\0" ++ "tssipos5g=1\0" ++ "extpagain5g=0\0" ++ "pdetrange5g=0\0" ++ "triso5g=3\0" ++ "antswctl5g=0\0" ++ "cck2gpo=0\0" ++ "ofdm2gpo=0\0" ++ "mcs2gpo0=0\0" ++ "mcs2gpo1=0\0" ++ "mcs2gpo2=0\0" ++ "mcs2gpo3=0\0" ++ "mcs2gpo4=0\0" ++ "mcs2gpo5=0\0" ++ "mcs2gpo6=0\0" ++ "mcs2gpo7=0\0" ++ "cddpo=0\0" ++ "stbcpo=0\0" ++ "bw40po=4\0" ++ "bwduppo=0\0" ++ "END\0"; ++#endif ++ ++static bool srvars_inited = FALSE; /* Use OTP/SROM as global variables */ ++ ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) || (defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND)) ++/* It must end with pattern of "END" */ ++static uint ++BCMATTACHFN(srom_vars_len)(char *vars) ++{ ++ uint pos = 0; ++ uint len; ++ char *s; ++ ++ for (s = vars; s && *s;) { ++ ++ if (strcmp(s, "END") == 0) ++ break; ++ ++ len = strlen(s); ++ s += strlen(s) + 1; ++ pos += len + 1; ++ /* BS_ERROR(("len %d vars[pos] %s\n", pos, s)); */ ++ if (pos > 4000) { ++ return 0; ++ } ++ } ++ ++ return pos + 4; /* include the "END\0" */ ++} ++#endif ++ ++/* Initialization of varbuf structure */ ++static void ++BCMATTACHFN(varbuf_init)(varbuf_t *b, char *buf, uint size) ++{ ++ b->size = size; ++ b->base = b->buf = buf; ++} ++ ++/* append a null terminated var=value string */ ++static int ++BCMATTACHFN(varbuf_append)(varbuf_t *b, const char *fmt, ...) ++{ ++ va_list ap; ++ int r; ++ size_t len; ++ char *s; ++ ++ if (b->size < 2) ++ return 0; ++ ++ va_start(ap, fmt); ++ r = vsnprintf(b->buf, b->size, fmt, ap); ++ va_end(ap); ++ ++ /* C99 snprintf behavior returns r >= size on overflow, ++ * others return -1 on overflow. ++ * All return -1 on format error. ++ * We need to leave room for 2 null terminations, one for the current var ++ * string, and one for final null of the var table. So check that the ++ * strlen written, r, leaves room for 2 chars. ++ */ ++ if ((r == -1) || (r > (int)(b->size - 2))) { ++ b->size = 0; ++ return 0; ++ } ++ ++ /* Remove any earlier occurrence of the same variable */ ++ if ((s = strchr(b->buf, '=')) != NULL) { ++ len = (size_t)(s - b->buf); ++ for (s = b->base; s < b->buf;) { ++ if ((bcmp(s, b->buf, len) == 0) && s[len] == '=') { ++ len = strlen(s) + 1; ++ memmove(s, (s + len), ((b->buf + r + 1) - (s + len))); ++ b->buf -= len; ++ b->size += (unsigned int)len; ++ break; ++ } ++ ++ while (*s++) ++ ; ++ } ++ } ++ ++ /* skip over this string's null termination */ ++ r++; ++ b->size -= r; ++ b->buf += r; ++ ++ return r; ++} ++ ++/* ++ * Initialize local vars from the right source for this platform. ++ * Return 0 on success, nonzero on error. ++ */ ++int ++BCMATTACHFN(srom_var_init)(si_t *sih, uint bustype, void *curmap, osl_t *osh, ++ char **vars, uint *count) ++{ ++ ASSERT(bustype == BUSTYPE(bustype)); ++ if (vars == NULL || count == NULL) ++ return (0); ++ ++ *vars = NULL; ++ *count = 0; ++ ++ switch (BUSTYPE(bustype)) { ++ case SI_BUS: ++ case JTAG_BUS: ++ return initvars_srom_si(sih, osh, curmap, vars, count); ++ ++ case PCI_BUS: ++ ASSERT(curmap != NULL); ++ if (curmap == NULL) ++ return (-1); ++ ++ return initvars_srom_pci(sih, curmap, vars, count); ++ ++ case PCMCIA_BUS: ++ return initvars_cis_pcmcia(sih, osh, vars, count); ++ ++ ++#ifdef BCMSPI ++ case SPI_BUS: ++ return initvars_cis_spi(osh, vars, count); ++#endif /* BCMSPI */ ++ ++ default: ++ ASSERT(0); ++ } ++ return (-1); ++} ++ ++/* support only 16-bit word read from srom */ ++int ++srom_read(si_t *sih, uint bustype, void *curmap, osl_t *osh, ++ uint byteoff, uint nbytes, uint16 *buf, bool check_crc) ++{ ++ uint i, off, nw; ++ ++ ASSERT(bustype == BUSTYPE(bustype)); ++ ++ /* check input - 16-bit access only */ ++ if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > SROM_MAX) ++ return 1; ++ ++ off = byteoff / 2; ++ nw = nbytes / 2; ++ ++ if (BUSTYPE(bustype) == PCI_BUS) { ++ if (!curmap) ++ return 1; ++ ++ if (si_is_sprom_available(sih)) { ++ uint16 *srom; ++ ++ srom = (uint16 *)SROM_OFFSET(sih); ++ if (srom == NULL) ++ return 1; ++ ++ if (sprom_read_pci(osh, sih, srom, off, buf, nw, check_crc)) ++ return 1; ++ } ++#if defined(BCMNVRAMW) || defined(BCMNVRAMR) ++ else { ++ if (otp_read_pci(osh, sih, buf, SROM_MAX)) ++ return 1; ++ } ++#endif ++ } else if (BUSTYPE(bustype) == PCMCIA_BUS) { ++ for (i = 0; i < nw; i++) { ++ if (sprom_read_pcmcia(osh, (uint16)(off + i), (uint16 *)(buf + i))) ++ return 1; ++ } ++#ifdef BCMSPI ++ } else if (BUSTYPE(bustype) == SPI_BUS) { ++ if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, (uint8 *)buf, byteoff + nbytes) != 0) ++ return 1; ++#endif /* BCMSPI */ ++ } else if (BUSTYPE(bustype) == SI_BUS) { ++#if defined(BCMUSBDEV) ++ if (SPROMBUS == PCMCIA_BUS) { ++ uint origidx; ++ void *regs; ++ int rc; ++ bool wasup; ++ ++ /* Don't bother if we can't talk to SPROM */ ++ if (!si_is_sprom_available(sih)) ++ return 1; ++ ++ origidx = si_coreidx(sih); ++ regs = si_setcore(sih, PCMCIA_CORE_ID, 0); ++ if (!regs) ++ regs = si_setcore(sih, SDIOD_CORE_ID, 0); ++ ASSERT(regs != NULL); ++ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ rc = get_si_pcmcia_srom(sih, osh, regs, byteoff, buf, nbytes, check_crc); ++ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ ++ si_setcoreidx(sih, origidx); ++ return rc; ++ } ++#endif ++ ++ return 1; ++ } else { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++/* support only 16-bit word write into srom */ ++int ++srom_write(si_t *sih, uint bustype, void *curmap, osl_t *osh, ++ uint byteoff, uint nbytes, uint16 *buf) ++{ ++ uint i, nw, crc_range; ++ uint16 *old, *new; ++ uint8 crc; ++ volatile uint32 val32; ++ int rc = 1; ++ ++ ASSERT(bustype == BUSTYPE(bustype)); ++ ++ old = MALLOC(osh, SROM_MAXW * sizeof(uint16)); ++ new = MALLOC(osh, SROM_MAXW * sizeof(uint16)); ++ ++ if (old == NULL || new == NULL) ++ goto done; ++ ++ /* check input - 16-bit access only. use byteoff 0x55aa to indicate ++ * srclear ++ */ ++ if ((byteoff != 0x55aa) && ((byteoff & 1) || (nbytes & 1))) ++ goto done; ++ ++ if ((byteoff != 0x55aa) && ((byteoff + nbytes) > SROM_MAX)) ++ goto done; ++ ++ if (BUSTYPE(bustype) == PCMCIA_BUS) { ++ crc_range = SROM_MAX; ++ } ++#if defined(BCMUSBDEV) ++ else { ++ crc_range = srom_size(sih, osh); ++ } ++#else ++ else { ++ crc_range = (SROM8_SIGN + 1) * 2; /* must big enough for SROM8 */ ++ } ++#endif ++ ++ nw = crc_range / 2; ++ /* read first small number words from srom, then adjust the length, read all */ ++ if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) ++ goto done; ++ ++ BS_ERROR(("%s: old[SROM4_SIGN] 0x%x, old[SROM8_SIGN] 0x%x\n", ++ __FUNCTION__, old[SROM4_SIGN], old[SROM8_SIGN])); ++ /* Deal with blank srom */ ++ if (old[0] == 0xffff) { ++ /* see if the input buffer is valid SROM image or not */ ++ if (buf[SROM11_SIGN] == SROM11_SIGNATURE) { ++ BS_ERROR(("%s: buf[SROM11_SIGN] 0x%x\n", ++ __FUNCTION__, buf[SROM11_SIGN])); ++ ++ /* block invalid buffer size */ ++ if (nbytes < SROM11_WORDS * 2) { ++ rc = BCME_BUFTOOSHORT; ++ goto done; ++ } else if (nbytes > SROM11_WORDS * 2) { ++ rc = BCME_BUFTOOLONG; ++ goto done; ++ } ++ ++ nw = SROM11_WORDS; ++ } else if ((buf[SROM4_SIGN] == SROM4_SIGNATURE) || ++ (buf[SROM8_SIGN] == SROM4_SIGNATURE)) { ++ BS_ERROR(("%s: buf[SROM4_SIGN] 0x%x, buf[SROM8_SIGN] 0x%x\n", ++ __FUNCTION__, buf[SROM4_SIGN], buf[SROM8_SIGN])); ++ ++ /* block invalid buffer size */ ++ if (nbytes < SROM4_WORDS * 2) { ++ rc = BCME_BUFTOOSHORT; ++ goto done; ++ } else if (nbytes > SROM4_WORDS * 2) { ++ rc = BCME_BUFTOOLONG; ++ goto done; ++ } ++ ++ nw = SROM4_WORDS; ++ } else if (nbytes == SROM_WORDS * 2){ /* the other possible SROM format */ ++ BS_ERROR(("%s: Not SROM4 or SROM8.\n", __FUNCTION__)); ++ ++ nw = SROM_WORDS; ++ } else { ++ BS_ERROR(("%s: Invalid input file signature\n", __FUNCTION__)); ++ rc = BCME_BADARG; ++ goto done; ++ } ++ crc_range = nw * 2; ++ if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) ++ goto done; ++ } else if (old[SROM11_SIGN] == SROM11_SIGNATURE) { ++ nw = SROM11_WORDS; ++ crc_range = nw * 2; ++ if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) ++ goto done; ++ } else if ((old[SROM4_SIGN] == SROM4_SIGNATURE) || ++ (old[SROM8_SIGN] == SROM4_SIGNATURE)) { ++ nw = SROM4_WORDS; ++ crc_range = nw * 2; ++ if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) ++ goto done; ++ } else { ++ /* Assert that we have already read enough for sromrev 2 */ ++ ASSERT(crc_range >= SROM_WORDS * 2); ++ nw = SROM_WORDS; ++ crc_range = nw * 2; ++ } ++ ++ if (byteoff == 0x55aa) { ++ /* Erase request */ ++ crc_range = 0; ++ memset((void *)new, 0xff, nw * 2); ++ } else { ++ /* Copy old contents */ ++ bcopy((void *)old, (void *)new, nw * 2); ++ /* make changes */ ++ bcopy((void *)buf, (void *)&new[byteoff / 2], nbytes); ++ } ++ ++ if (crc_range) { ++ /* calculate crc */ ++ htol16_buf(new, crc_range); ++ crc = ~hndcrc8((uint8 *)new, crc_range - 1, CRC8_INIT_VALUE); ++ ltoh16_buf(new, crc_range); ++ new[nw - 1] = (crc << 8) | (new[nw - 1] & 0xff); ++ } ++ ++ if (BUSTYPE(bustype) == PCI_BUS) { ++ uint16 *srom = NULL; ++ void *ccregs = NULL; ++ uint32 ccval = 0; ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ /* save current control setting */ ++ ccval = si_chipcontrl_read(sih); ++ } ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID)) { ++ /* Disable Ext PA lines to allow reading from SROM */ ++ si_chipcontrl_epa4331(sih, FALSE); ++ } else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ si_chipcontrl_srom4360(sih, TRUE); ++ } ++ ++ /* enable writes to the SPROM */ ++ if (sih->ccrev > 31) { ++ ccregs = (void *)((uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET); ++ srom = (uint16 *)((uint8 *)ccregs + CC_SROM_OTP); ++ (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WREN, 0, 0); ++ } else { ++ srom = (uint16 *)((uint8 *)curmap + PCI_BAR0_SPROM_OFFSET); ++ val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32)); ++ val32 |= SPROM_WRITEEN; ++ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32); ++ } ++ bcm_mdelay(WRITE_ENABLE_DELAY); ++ /* write srom */ ++ for (i = 0; i < nw; i++) { ++ if (old[i] != new[i]) { ++ if (sih->ccrev > 31) { ++ if ((sih->cccaps & CC_CAP_SROM) == 0) { ++ /* No srom support in this chip */ ++ BS_ERROR(("srom_write, invalid srom, skip\n")); ++ } else ++ (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRITE, ++ i, new[i]); ++ } else { ++ W_REG(osh, &srom[i], new[i]); ++ } ++ bcm_mdelay(WRITE_WORD_DELAY); ++ } ++ } ++ /* disable writes to the SPROM */ ++ if (sih->ccrev > 31) { ++ (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRDIS, 0, 0); ++ } else { ++ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 & ++ ~SPROM_WRITEEN); ++ } ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ /* Restore config after reading SROM */ ++ si_chipcontrl_restore(sih, ccval); ++ } ++ ++ } else if (BUSTYPE(bustype) == PCMCIA_BUS) { ++ /* enable writes to the SPROM */ ++ if (sprom_cmd_pcmcia(osh, SROM_WEN)) ++ goto done; ++ bcm_mdelay(WRITE_ENABLE_DELAY); ++ /* write srom */ ++ for (i = 0; i < nw; i++) { ++ if (old[i] != new[i]) { ++ sprom_write_pcmcia(osh, (uint16)(i), new[i]); ++ bcm_mdelay(WRITE_WORD_DELAY); ++ } ++ } ++ /* disable writes to the SPROM */ ++ if (sprom_cmd_pcmcia(osh, SROM_WDS)) ++ goto done; ++ } else if (BUSTYPE(bustype) == SI_BUS) { ++#if defined(BCMUSBDEV) ++ if (SPROMBUS == PCMCIA_BUS) { ++ uint origidx; ++ void *regs; ++ bool wasup; ++ ++ origidx = si_coreidx(sih); ++ regs = si_setcore(sih, PCMCIA_CORE_ID, 0); ++ if (!regs) ++ regs = si_setcore(sih, SDIOD_CORE_ID, 0); ++ ASSERT(regs != NULL); ++ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ rc = set_si_pcmcia_srom(sih, osh, regs, byteoff, buf, nbytes); ++ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ ++ si_setcoreidx(sih, origidx); ++ goto done; ++ } ++#endif ++ goto done; ++ } else { ++ goto done; ++ } ++ ++ bcm_mdelay(WRITE_ENABLE_DELAY); ++ rc = 0; ++ ++done: ++ if (old != NULL) ++ MFREE(osh, old, SROM_MAXW * sizeof(uint16)); ++ if (new != NULL) ++ MFREE(osh, new, SROM_MAXW * sizeof(uint16)); ++ ++ return rc; ++} ++#endif ++ ++#if defined(BCMUSBDEV) ++#define SI_PCMCIA_READ(osh, regs, fcr) \ ++ R_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2) ++#define SI_PCMCIA_WRITE(osh, regs, fcr, v) \ ++ W_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2, v) ++ ++/* set PCMCIA srom command register */ ++static int ++srom_cmd_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint8 cmd) ++{ ++ uint8 status = 0; ++ uint wait_cnt = 0; ++ ++ /* write srom command register */ ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_CS, cmd); ++ ++ /* wait status */ ++ while (++wait_cnt < 1000000) { ++ status = SI_PCMCIA_READ(osh, pcmregs, SROM_CS); ++ if (status & SROM_DONE) ++ return 0; ++ OSL_DELAY(1); ++ } ++ ++ BS_ERROR(("sr_cmd: Give up after %d tries, stat = 0x%x\n", wait_cnt, status)); ++ return 1; ++} ++ ++/* read a word from the PCMCIA srom over SI */ ++static int ++srom_read_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint16 addr, uint16 *data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; ++ ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ ++ /* set address */ ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRH, addr_h); ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRL, addr_l); ++ ++ /* do read */ ++ if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_READ)) ++ return 1; ++ ++ /* read data */ ++ data_h = SI_PCMCIA_READ(osh, pcmregs, SROM_DATAH); ++ data_l = SI_PCMCIA_READ(osh, pcmregs, SROM_DATAL); ++ *data = ((uint16)data_h << 8) | data_l; ++ ++ return 0; ++} ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++/* write a word to the PCMCIA srom over SI */ ++static int ++srom_write_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint16 addr, uint16 data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; ++ int rc; ++ ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ ++ /* set address */ ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRH, addr_h); ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRL, addr_l); ++ ++ data_l = (uint8)(data & 0xff); ++ data_h = (uint8)((data >> 8) & 0xff); ++ ++ /* write data */ ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_DATAH, data_h); ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_DATAL, data_l); ++ ++ /* do write */ ++ rc = srom_cmd_si_pcmcia(osh, pcmregs, SROM_WRITE); ++ OSL_DELAY(20000); ++ return rc; ++} ++#endif ++ ++/* ++ * Read the srom for the pcmcia-srom over si case. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++get_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs, ++ uint boff, uint16 *srom, uint bsz, bool check_crc) ++{ ++ uint i, nw, woff, wsz; ++ int err = 0; ++ ++ /* read must be at word boundary */ ++ ASSERT((boff & 1) == 0 && (bsz & 1) == 0); ++ ++ /* read sprom size and validate the parms */ ++ if ((nw = srom_size(sih, osh)) == 0) { ++ BS_ERROR(("get_si_pcmcia_srom: sprom size unknown\n")); ++ err = -1; ++ goto out; ++ } ++ if (boff + bsz > 2 * nw) { ++ BS_ERROR(("get_si_pcmcia_srom: sprom size exceeded\n")); ++ err = -2; ++ goto out; ++ } ++ ++ /* read in sprom contents */ ++ for (woff = boff / 2, wsz = bsz / 2, i = 0; ++ woff < nw && i < wsz; woff ++, i ++) { ++ if (srom_read_si_pcmcia(osh, pcmregs, (uint16)woff, &srom[i])) { ++ BS_ERROR(("get_si_pcmcia_srom: sprom read failed\n")); ++ err = -3; ++ goto out; ++ } ++ } ++ ++ if (check_crc) { ++ if (srom[0] == 0xffff) { ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ BS_ERROR(("%s: srom[0] == 0xffff, assuming unprogrammed srom\n", ++ __FUNCTION__)); ++ err = -4; ++ goto out; ++ } ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(srom, nw * 2); ++ if (hndcrc8((uint8 *)srom, nw * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) { ++ BS_ERROR(("%s: bad crc\n", __FUNCTION__)); ++ err = -5; ++ } ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(srom, nw * 2); ++ } ++ ++out: ++ return err; ++} ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++/* ++ * Write the srom for the pcmcia-srom over si case. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++set_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs, ++ uint boff, uint16 *srom, uint bsz) ++{ ++ uint i, nw, woff, wsz; ++ uint16 word; ++ uint8 crc; ++ int err = 0; ++ ++ /* write must be at word boundary */ ++ ASSERT((boff & 1) == 0 && (bsz & 1) == 0); ++ ++ /* read sprom size and validate the parms */ ++ if ((nw = srom_size(sih, osh)) == 0) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom size unknown\n")); ++ err = -1; ++ goto out; ++ } ++ if (boff + bsz > 2 * nw) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom size exceeded\n")); ++ err = -2; ++ goto out; ++ } ++ ++ /* enable write */ ++ if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_WEN)) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom wen failed\n")); ++ err = -3; ++ goto out; ++ } ++ ++ /* write buffer to sprom */ ++ for (woff = boff / 2, wsz = bsz / 2, i = 0; ++ woff < nw && i < wsz; woff ++, i ++) { ++ if (srom_write_si_pcmcia(osh, pcmregs, (uint16)woff, srom[i])) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom write failed\n")); ++ err = -4; ++ goto out; ++ } ++ } ++ ++ /* fix crc */ ++ crc = CRC8_INIT_VALUE; ++ for (woff = 0; woff < nw; woff ++) { ++ if (srom_read_si_pcmcia(osh, pcmregs, (uint16)woff, &word)) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom fix crc read failed\n")); ++ err = -5; ++ goto out; ++ } ++ word = htol16(word); ++ crc = hndcrc8((uint8 *)&word, woff != nw - 1 ? 2 : 1, crc); ++ } ++ word = (~crc << 8) + (ltoh16(word) & 0xff); ++ if (srom_write_si_pcmcia(osh, pcmregs, (uint16)(woff - 1), word)) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom fix crc write failed\n")); ++ err = -6; ++ goto out; ++ } ++ ++ /* disable write */ ++ if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_WDS)) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom wds failed\n")); ++ err = -7; ++ goto out; ++ } ++ ++out: ++ return err; ++} ++#endif ++#endif ++ ++static const char BCMATTACHDATA(vstr_manf)[] = "manf=%s"; ++static const char BCMATTACHDATA(vstr_productname)[] = "productname=%s"; ++static const char BCMATTACHDATA(vstr_manfid)[] = "manfid=0x%x"; ++static const char BCMATTACHDATA(vstr_prodid)[] = "prodid=0x%x"; ++static const char BCMATTACHDATA(vstr_regwindowsz)[] = "regwindowsz=%d"; ++static const char BCMATTACHDATA(vstr_sromrev)[] = "sromrev=%d"; ++static const char BCMATTACHDATA(vstr_chiprev)[] = "chiprev=%d"; ++static const char BCMATTACHDATA(vstr_subvendid)[] = "subvendid=0x%x"; ++static const char BCMATTACHDATA(vstr_subdevid)[] = "subdevid=0x%x"; ++static const char BCMATTACHDATA(vstr_boardrev)[] = "boardrev=0x%x"; ++static const char BCMATTACHDATA(vstr_aa2g)[] = "aa2g=0x%x"; ++static const char BCMATTACHDATA(vstr_aa5g)[] = "aa5g=0x%x"; ++static const char BCMATTACHDATA(vstr_ag)[] = "ag%d=0x%x"; ++static const char BCMATTACHDATA(vstr_cc)[] = "cc=%d"; ++static const char BCMATTACHDATA(vstr_opo)[] = "opo=%d"; ++static const char BCMATTACHDATA(vstr_pa0b)[][9] = { "pa0b0=%d", "pa0b1=%d", "pa0b2=%d" }; ++static const char BCMATTACHDATA(vstr_pa0itssit)[] = "pa0itssit=%d"; ++static const char BCMATTACHDATA(vstr_pa0maxpwr)[] = "pa0maxpwr=%d"; ++static const char BCMATTACHDATA(vstr_pa1b)[][9] = { "pa1b0=%d", "pa1b1=%d", "pa1b2=%d" }; ++static const char BCMATTACHDATA(vstr_pa1lob)[][11] = ++ { "pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d" }; ++static const char BCMATTACHDATA(vstr_pa1hib)[][11] = ++ { "pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d" }; ++static const char BCMATTACHDATA(vstr_pa1itssit)[] = "pa1itssit=%d"; ++static const char BCMATTACHDATA(vstr_pa1maxpwr)[] = "pa1maxpwr=%d"; ++static const char BCMATTACHDATA(vstr_pa1lomaxpwr)[] = "pa1lomaxpwr=%d"; ++static const char BCMATTACHDATA(vstr_pa1himaxpwr)[] = "pa1himaxpwr=%d"; ++static const char BCMATTACHDATA(vstr_oem)[] = "oem=%02x%02x%02x%02x%02x%02x%02x%02x"; ++static const char BCMATTACHDATA(vstr_boardflags)[] = "boardflags=0x%x"; ++static const char BCMATTACHDATA(vstr_boardflags2)[] = "boardflags2=0x%x"; ++static const char BCMATTACHDATA(vstr_boardflags3)[] = "boardflags3=0x%x"; ++static const char BCMATTACHDATA(vstr_ledbh)[] = "ledbh%d=0x%x"; ++static const char BCMATTACHDATA(vstr_noccode)[] = "ccode=0x0"; ++static const char BCMATTACHDATA(vstr_ccode)[] = "ccode=%c%c"; ++static const char BCMATTACHDATA(vstr_cctl)[] = "cctl=0x%x"; ++static const char BCMATTACHDATA(vstr_cckpo)[] = "cckpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdmpo)[] = "ofdmpo=0x%x"; ++static const char BCMATTACHDATA(vstr_rdlid)[] = "rdlid=0x%x"; ++static const char BCMATTACHDATA(vstr_rdlrndis)[] = "rdlrndis=%d"; ++static const char BCMATTACHDATA(vstr_rdlrwu)[] = "rdlrwu=%d"; ++static const char BCMATTACHDATA(vstr_usbfs)[] = "usbfs=%d"; ++static const char BCMATTACHDATA(vstr_wpsgpio)[] = "wpsgpio=%d"; ++static const char BCMATTACHDATA(vstr_wpsled)[] = "wpsled=%d"; ++static const char BCMATTACHDATA(vstr_rdlsn)[] = "rdlsn=%d"; ++static const char BCMATTACHDATA(vstr_rssismf2g)[] = "rssismf2g=%d"; ++static const char BCMATTACHDATA(vstr_rssismc2g)[] = "rssismc2g=%d"; ++static const char BCMATTACHDATA(vstr_rssisav2g)[] = "rssisav2g=%d"; ++static const char BCMATTACHDATA(vstr_bxa2g)[] = "bxa2g=%d"; ++static const char BCMATTACHDATA(vstr_rssismf5g)[] = "rssismf5g=%d"; ++static const char BCMATTACHDATA(vstr_rssismc5g)[] = "rssismc5g=%d"; ++static const char BCMATTACHDATA(vstr_rssisav5g)[] = "rssisav5g=%d"; ++static const char BCMATTACHDATA(vstr_bxa5g)[] = "bxa5g=%d"; ++static const char BCMATTACHDATA(vstr_tri2g)[] = "tri2g=%d"; ++static const char BCMATTACHDATA(vstr_tri5gl)[] = "tri5gl=%d"; ++static const char BCMATTACHDATA(vstr_tri5g)[] = "tri5g=%d"; ++static const char BCMATTACHDATA(vstr_tri5gh)[] = "tri5gh=%d"; ++static const char BCMATTACHDATA(vstr_rxpo2g)[] = "rxpo2g=%d"; ++static const char BCMATTACHDATA(vstr_rxpo5g)[] = "rxpo5g=%d"; ++static const char BCMATTACHDATA(vstr_boardtype)[] = "boardtype=0x%x"; ++static const char BCMATTACHDATA(vstr_leddc)[] = "leddc=0x%04x"; ++static const char BCMATTACHDATA(vstr_vendid)[] = "vendid=0x%x"; ++static const char BCMATTACHDATA(vstr_devid)[] = "devid=0x%x"; ++static const char BCMATTACHDATA(vstr_xtalfreq)[] = "xtalfreq=%d"; ++static const char BCMATTACHDATA(vstr_txchain)[] = "txchain=0x%x"; ++static const char BCMATTACHDATA(vstr_rxchain)[] = "rxchain=0x%x"; ++static const char BCMNMIATTACHDATA(vstr_elna2g)[] = "elna2g=0x%x"; ++static const char BCMNMIATTACHDATA(vstr_elna5g)[] = "elna5g=0x%x"; ++static const char BCMATTACHDATA(vstr_antswitch)[] = "antswitch=0x%x"; ++static const char BCMATTACHDATA(vstr_regrev)[] = "regrev=0x%x"; ++static const char BCMATTACHDATA(vstr_antswctl2g)[] = "antswctl2g=0x%x"; ++static const char BCMATTACHDATA(vstr_triso2g)[] = "triso2g=0x%x"; ++static const char BCMATTACHDATA(vstr_pdetrange2g)[] = "pdetrange2g=0x%x"; ++static const char BCMATTACHDATA(vstr_extpagain2g)[] = "extpagain2g=0x%x"; ++static const char BCMATTACHDATA(vstr_tssipos2g)[] = "tssipos2g=0x%x"; ++static const char BCMATTACHDATA(vstr_antswctl5g)[] = "antswctl5g=0x%x"; ++static const char BCMATTACHDATA(vstr_triso5g)[] = "triso5g=0x%x"; ++static const char BCMATTACHDATA(vstr_pdetrange5g)[] = "pdetrange5g=0x%x"; ++static const char BCMATTACHDATA(vstr_extpagain5g)[] = "extpagain5g=0x%x"; ++static const char BCMATTACHDATA(vstr_tssipos5g)[] = "tssipos5g=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp2ga)[] = "maxp2ga%d=0x%x"; ++static const char BCMATTACHDATA(vstr_itt2ga0)[] = "itt2ga0=0x%x"; ++static const char BCMATTACHDATA(vstr_pa)[] = "pa%dgw%da%d=0x%x"; ++static const char BCMATTACHDATA(vstr_pahl)[] = "pa%dg%cw%da%d=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5ga0)[] = "maxp5ga0=0x%x"; ++static const char BCMATTACHDATA(vstr_itt5ga0)[] = "itt5ga0=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5gha0)[] = "maxp5gha0=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5gla0)[] = "maxp5gla0=0x%x"; ++static const char BCMATTACHDATA(vstr_itt2ga1)[] = "itt2ga1=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5ga1)[] = "maxp5ga1=0x%x"; ++static const char BCMATTACHDATA(vstr_itt5ga1)[] = "itt5ga1=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5gha1)[] = "maxp5gha1=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5gla1)[] = "maxp5gla1=0x%x"; ++static const char BCMATTACHDATA(vstr_cck2gpo)[] = "cck2gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdm2gpo)[] = "ofdm2gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdm5gpo)[] = "ofdm5gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdm5glpo)[] = "ofdm5glpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdm5ghpo)[] = "ofdm5ghpo=0x%x"; ++static const char BCMATTACHDATA(vstr_cddpo)[] = "cddpo=0x%x"; ++static const char BCMATTACHDATA(vstr_stbcpo)[] = "stbcpo=0x%x"; ++static const char BCMATTACHDATA(vstr_bw40po)[] = "bw40po=0x%x"; ++static const char BCMATTACHDATA(vstr_bwduppo)[] = "bwduppo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcspo)[] = "mcs%dgpo%d=0x%x"; ++static const char BCMATTACHDATA(vstr_mcspohl)[] = "mcs%dg%cpo%d=0x%x"; ++static const char BCMATTACHDATA(vstr_custom)[] = "customvar%d=0x%x"; ++static const char BCMATTACHDATA(vstr_cckdigfilttype)[] = "cckdigfilttype=%d"; ++static const char BCMATTACHDATA(vstr_usbflags)[] = "usbflags=0x%x"; ++#ifdef BCM_BOOTLOADER ++static const char BCMATTACHDATA(vstr_mdio)[] = "mdio%d=0x%%x"; ++static const char BCMATTACHDATA(vstr_mdioex)[] = "mdioex%d=0x%%x"; ++static const char BCMATTACHDATA(vstr_brmin)[] = "brmin=0x%x"; ++static const char BCMATTACHDATA(vstr_brmax)[] = "brmax=0x%x"; ++static const char BCMATTACHDATA(vstr_pllreg)[] = "pll%d=0x%x"; ++static const char BCMATTACHDATA(vstr_ccreg)[] = "chipc%d=0x%x"; ++static const char BCMATTACHDATA(vstr_regctrl)[] = "reg%d=0x%x"; ++static const char BCMATTACHDATA(vstr_time)[] = "r%dt=0x%x"; ++static const char BCMATTACHDATA(vstr_depreg)[] = "r%dd=0x%x"; ++static const char BCMATTACHDATA(vstr_usbpredly)[] = "usbpredly=0x%x"; ++static const char BCMATTACHDATA(vstr_usbpostdly)[] = "usbpostdly=0x%x"; ++static const char BCMATTACHDATA(vstr_usbrdy)[] = "usbrdy=0x%x"; ++static const char BCMATTACHDATA(vstr_hsicphyctrl1)[] = "hsicphyctrl1=0x%x"; ++static const char BCMATTACHDATA(vstr_hsicphyctrl2)[] = "hsicphyctrl2=0x%x"; ++static const char BCMATTACHDATA(vstr_usbdevctrl)[] = "usbdevctrl=0x%x"; ++static const char BCMATTACHDATA(vstr_bldr_reset_timeout)[] = "bldr_to=0x%x"; ++static const char BCMATTACHDATA(vstr_muxenab)[] = "muxenab=0x%x"; ++#endif /* BCM_BOOTLOADER */ ++static const char BCMATTACHDATA(vstr_boardnum)[] = "boardnum=%d"; ++static const char BCMATTACHDATA(vstr_macaddr)[] = "macaddr=%s"; ++static const char BCMATTACHDATA(vstr_usbepnum)[] = "usbepnum=0x%x"; ++ ++/* Power per rate for SROM V9 */ ++static const char BCMATTACHDATA(vstr_cckbw202gpo)[][19] = ++ { "cckbw202gpo=0x%x", "cckbw20ul2gpo=0x%x" }; ++static const char BCMATTACHDATA(vstr_legofdmbw202gpo)[][22] = ++ { "legofdmbw202gpo=0x%x", "legofdmbw20ul2gpo=0x%x" }; ++static const char BCMATTACHDATA(vstr_legofdmbw205gpo)[][24] = ++ { "legofdmbw205glpo=0x%x", "legofdmbw20ul5glpo=0x%x", ++ "legofdmbw205gmpo=0x%x", "legofdmbw20ul5gmpo=0x%x", ++ "legofdmbw205ghpo=0x%x", "legofdmbw20ul5ghpo=0x%x" }; ++ ++static const char BCMATTACHDATA(vstr_mcs2gpo)[][19] = ++{ "mcsbw202gpo=0x%x", "mcsbw20ul2gpo=0x%x", "mcsbw402gpo=0x%x"}; ++ ++static const char BCMATTACHDATA(vstr_mcs5glpo)[][20] = ++ { "mcsbw205glpo=0x%x", "mcsbw20ul5glpo=0x%x", "mcsbw405glpo=0x%x"}; ++ ++static const char BCMATTACHDATA(vstr_mcs5gmpo)[][20] = ++ { "mcsbw205gmpo=0x%x", "mcsbw20ul5gmpo=0x%x", "mcsbw405gmpo=0x%x"}; ++ ++static const char BCMATTACHDATA(vstr_mcs5ghpo)[][20] = ++ { "mcsbw205ghpo=0x%x", "mcsbw20ul5ghpo=0x%x", "mcsbw405ghpo=0x%x"}; ++ ++static const char BCMATTACHDATA(vstr_mcs32po)[] = "mcs32po=0x%x"; ++static const char BCMATTACHDATA(vstr_legofdm40duppo)[] = "legofdm40duppo=0x%x"; ++ ++/* SROM V11 */ ++static const char BCMATTACHDATA(vstr_tempthresh)[] = "tempthresh=%d"; /* HNBU_TEMPTHRESH */ ++static const char BCMATTACHDATA(vstr_temps_period)[] = "temps_period=%d"; ++static const char BCMATTACHDATA(vstr_temp_hysteresis)[] = "temp_hysteresis=%d"; ++static const char BCMATTACHDATA(vstr_tempoffset)[] = "tempoffset=%d"; ++static const char BCMATTACHDATA(vstr_temp_corrx)[] = "tempcorrx=%d"; ++static const char BCMATTACHDATA(vstr_tempsense_option)[] = "tempsense_option=%d"; ++static const char BCMATTACHDATA(vstr_phycal_tempdelta)[] = "phycal_tempdelta=%d"; ++static const char BCMATTACHDATA(vstr_tssiposslopeg)[] = "tssiposslope%dg=%d"; /* HNBU_FEM_CFG */ ++static const char BCMATTACHDATA(vstr_epagaing)[] = "epagain%dg=%d"; ++static const char BCMATTACHDATA(vstr_pdgaing)[] = "pdgain%dg=%d"; ++static const char BCMATTACHDATA(vstr_tworangetssi)[] = "tworangetssi%dg=%d"; ++static const char BCMATTACHDATA(vstr_papdcap)[] = "papdcap%dg=%d"; ++static const char BCMATTACHDATA(vstr_femctrl)[] = "femctrl=%d"; ++static const char BCMATTACHDATA(vstr_gainctrlsph)[] = "gainctrlsph=%d"; ++static const char BCMATTACHDATA(vstr_subband5gver)[] = "subband5gver=%d"; /* HNBU_ACPA_CX */ ++static const char BCMATTACHDATA(vstr_pa2ga)[] = "pa2ga%d=0x%x,0x%x,0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5ga)[] = "maxp5ga%d=0x%x,0x%x,0x%x,0x%x"; ++static const char BCMATTACHDATA(vstr_pa5ga)[] = "pa5ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x," ++ "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x"; ++static const char BCMATTACHDATA(vstr_rxgainsgelnagaina)[] = "rxgains%dgelnagaina=%d"; ++static const char BCMATTACHDATA(vstr_rxgainsgtrisoa)[] = "rxgains%dgtrisoa%d=%d"; ++static const char BCMATTACHDATA(vstr_rxgainsgtrelnabypa)[] = "rxgains%dgtrelnabypa%d=%d"; ++static const char BCMATTACHDATA(vstr_measpower)[] = "measpower%d=0x%x"; /* HNBU_MEAS_PWR */ ++static const char BCMATTACHDATA(vstr_measpowerX)[] = "measpower%d=0x%x"; ++static const char BCMATTACHDATA(vstr_rawtempsense)[] = "rawtempsense=0x%x"; ++/* HNBU_ACPPR_2GPO */ ++static const char BCMATTACHDATA(vstr_dot11agofdmhrbw202gpo)[] = "dot11agofdmhrbw202gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdmlrbw202gpo)[] = "ofdmlrbw202gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw805glpo)[] = "mcsbw805glpo=0x%x"; /* HNBU_ACPPR_5GPO */ ++static const char BCMATTACHDATA(vstr_mcsbw1605glpo)[] = "mcsbw1605glpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw805gmpo)[] = "mcsbw805gmpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw1605gmpo)[] = "mcsbw1605gmpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw805ghpo)[] = "mcsbw805ghpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw1605ghpo)[] = "mcsbw1605ghpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcslr5rlpo)[] = "mcslr5rlpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcslr5gmpo)[] = "mcslr5gmpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcslr5ghpo)[] = "mcslr5ghpo=0x%x"; ++static const char BCMATTACHDATA(vstr_sb20in40rrpo)[] = "sb20in40%crrpo=0x%x"; /* HNBU_ACPPR_SBPO */ ++static const char BCMATTACHDATA(vstr_sb20in80and160r5gpo)[] = "sb20in80and160%cr5g%cpo=0x%x"; ++static const char BCMATTACHDATA(vstr_sb40and80r5gpo)[] = "sb40and80%cr5g%cpo=0x%x"; ++static const char BCMATTACHDATA(vstr_dot11agduprpo)[] = "dot11agdup%crpo=0x%x"; ++static const char BCMATTACHDATA(vstr_noiselvl2ga)[] = "noiselvl2ga%d=%d"; /* HNBU_NOISELVL */ ++static const char BCMATTACHDATA(vstr_noiselvl5ga)[] = "noiselvl5g%ca%d=%d"; ++static const char BCMATTACHDATA(vstr_rxgainerr2g)[] = "rxgainerr2g=0x%x"; /* HNBU_RXGAIN_ERR */ ++static const char BCMATTACHDATA(vstr_rxgainerr5g)[] = "rxgainerr5g=0x%x,0x%x,0x%x,0x%x"; ++static const char BCMATTACHDATA(vstr_agbg)[] = "agbg%d=0x%x"; /* HNBU_AGBGA */ ++static const char BCMATTACHDATA(vstr_aga)[] = "aga%d=0x%x"; ++ ++static const char BCMATTACHDATA(vstr_uuid)[] = "uuid=%s"; ++ ++static const char BCMATTACHDATA(vstr_end)[] = "END\0"; ++ ++uint8 patch_pair = 0; ++ ++/* For dongle HW, accept partial calibration parameters */ ++#if defined(BCMUSBDEV) ++#define BCMDONGLECASE(n) case n: ++#else ++#define BCMDONGLECASE(n) ++#endif ++ ++#ifdef BCM_BOOTLOADER ++/* The format of the PMUREGS OTP Tuple -> ++ * 1 byte -> Lower 5 bits has the address of the register ++ * Higher 3 bits has the mode of the register like ++ * PLL, ChipCtrl, RegCtrl, UpDwn or Dependency mask ++ * 4 bytes -> Value of the register to be updated. ++ */ ++#define PMUREGS_MODE_MASK 0xE0 ++#define PMUREGS_MODE_SHIFT 5 ++#define PMUREGS_ADDR_MASK 0x1F ++#define PMUREGS_TPL_SIZE 5 ++ ++enum { ++ PMU_PLLREG_MODE, ++ PMU_CCREG_MODE, ++ PMU_VOLTREG_MODE, ++ PMU_RES_TIME_MODE, ++ PMU_RESDEPEND_MODE ++}; ++ ++#define USBREGS_TPL_SIZE 5 ++enum { ++ USB_DEV_CTRL_REG, ++ HSIC_PHY_CTRL1_REG, ++ HSIC_PHY_CTRL2_REG ++}; ++ ++#define USBRDY_DLY_TYPE 0x8000 /* Bit indicating if the byte is pre or post delay value */ ++#define USBRDY_DLY_MASK 0x7FFF /* Bits indicating the amount of delay */ ++#define USBRDY_MAXOTP_SIZE 5 /* Max size of the OTP parameter */ ++ ++#endif /* BCM_BOOTLOADER */ ++ ++#ifdef BCM_BMAC_VARS_APPEND ++int ++BCMATTACHFN(srom_probe_boardtype)(uint8 *pcis[], uint ciscnt) ++{ ++ int i; ++ uint cisnum; ++ uint8 *cis, tup, tlen; ++ ++ for (cisnum = 0; cisnum < ciscnt; cisnum++) { ++ cis = *pcis++; ++ i = 0; ++ do { ++ tup = cis[i++]; ++ if (tup == CISTPL_NULL || tup == CISTPL_END) ++ tlen = 0; ++ else ++ tlen = cis[i++]; ++ ++ if ((i + tlen) >= CIS_SIZE) ++ break; ++ ++ if ((tup == CISTPL_BRCM_HNBU) && (cis[i] == HNBU_BOARDTYPE)) { ++ return (int)((cis[i + 2] << 8) + cis[i + 1]); ++ } ++ ++ i += tlen; ++ ++ } while (tup != CISTPL_END); ++ } ++ ++ return 0; ++} ++#endif /* BCM_BMAC_VARS_APPEND */ ++ ++int ++BCMATTACHFN(srom_parsecis)(osl_t *osh, uint8 *pcis[], uint ciscnt, char **vars, uint *count) ++{ ++ char eabuf[32]; ++ char *base; ++ varbuf_t b; ++ uint8 *cis, tup, tlen, sromrev = 1; ++ int i, j; ++#ifndef BCM_BOOTLOADER ++ bool ag_init = FALSE; ++#endif ++ uint32 w32; ++ uint funcid; ++ uint cisnum; ++ int32 boardnum; ++ int err; ++ bool standard_cis; ++ ++ ASSERT(vars != NULL); ++ ASSERT(count != NULL); ++ ++ boardnum = -1; ++ ++ base = MALLOC(osh, MAXSZ_NVRAM_VARS); ++ ASSERT(base != NULL); ++ if (!base) ++ return -2; ++ ++ varbuf_init(&b, base, MAXSZ_NVRAM_VARS); ++ bzero(base, MAXSZ_NVRAM_VARS); ++#ifdef BCM_BMAC_VARS_APPEND ++ /* 43236 use defaultsromvars_43236usb as the base, ++ * then append and update it with the content from OTP. ++ * Only revision/board specfic content or updates used to override ++ * the driver default will be stored in OTP ++ */ ++ *count -= (strlen(vstr_end) + 1 + 1); /* back off the termnating END\0\0 from fakenvram */ ++ bcopy(*vars, base, *count); ++ b.buf += *count; ++#endif /* BCM_BMAC_VARS_APPEND */ ++ eabuf[0] = '\0'; ++ for (cisnum = 0; cisnum < ciscnt; cisnum++) { ++ cis = *pcis++; ++ i = 0; ++ funcid = 0; ++ standard_cis = TRUE; ++ do { ++ if (standard_cis) { ++ tup = cis[i++]; ++ if (tup == CISTPL_NULL || tup == CISTPL_END) ++ tlen = 0; ++ else ++ tlen = cis[i++]; ++ } else { ++ if (cis[i] == CISTPL_NULL || cis[i] == CISTPL_END) { ++ tlen = 0; ++ tup = cis[i]; ++ } else { ++ tlen = cis[i]; ++ tup = CISTPL_BRCM_HNBU; ++ } ++ ++i; ++ } ++ if ((i + tlen) >= CIS_SIZE) ++ break; ++ ++ switch (tup) { ++ case CISTPL_VERS_1: ++ /* assume the strings are good if the version field checks out */ ++ if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) { ++ varbuf_append(&b, vstr_manf, &cis[i + 2]); ++ varbuf_append(&b, vstr_productname, ++ &cis[i + 3 + strlen((char *)&cis[i + 2])]); ++ break; ++ } ++ ++ case CISTPL_MANFID: ++ varbuf_append(&b, vstr_manfid, (cis[i + 1] << 8) + cis[i]); ++ varbuf_append(&b, vstr_prodid, (cis[i + 3] << 8) + cis[i + 2]); ++ break; ++ ++ case CISTPL_FUNCID: ++ funcid = cis[i]; ++ break; ++ ++ case CISTPL_FUNCE: ++ switch (funcid) { ++ case CISTPL_FID_SDIO: ++ funcid = 0; ++ break; ++ default: ++ /* set macaddr if HNBU_MACADDR not seen yet */ ++ if (eabuf[0] == '\0' && cis[i] == LAN_NID && ++ !(ETHER_ISNULLADDR(&cis[i + 2])) && ++ !(ETHER_ISMULTI(&cis[i + 2]))) { ++ ASSERT(cis[i + 1] == ETHER_ADDR_LEN); ++ bcm_ether_ntoa((struct ether_addr *)&cis[i + 2], ++ eabuf); ++ ++ /* set boardnum if HNBU_BOARDNUM not seen yet */ ++ if (boardnum == -1) ++ boardnum = (cis[i + 6] << 8) + cis[i + 7]; ++ } ++ break; ++ } ++ break; ++ ++ case CISTPL_CFTABLE: ++ varbuf_append(&b, vstr_regwindowsz, (cis[i + 7] << 8) | cis[i + 6]); ++ break; ++ ++ case CISTPL_BRCM_HNBU: ++ switch (cis[i]) { ++ case HNBU_SROMREV: ++ sromrev = cis[i + 1]; ++ varbuf_append(&b, vstr_sromrev, sromrev); ++ break; ++ ++ case HNBU_XTALFREQ: ++ varbuf_append(&b, vstr_xtalfreq, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++ ++ case HNBU_CHIPID: ++ varbuf_append(&b, vstr_vendid, (cis[i + 2] << 8) + ++ cis[i + 1]); ++ varbuf_append(&b, vstr_devid, (cis[i + 4] << 8) + ++ cis[i + 3]); ++ if (tlen >= 7) { ++ varbuf_append(&b, vstr_chiprev, ++ (cis[i + 6] << 8) + cis[i + 5]); ++ } ++ if (tlen >= 9) { ++ varbuf_append(&b, vstr_subvendid, ++ (cis[i + 8] << 8) + cis[i + 7]); ++ } ++ if (tlen >= 11) { ++ varbuf_append(&b, vstr_subdevid, ++ (cis[i + 10] << 8) + cis[i + 9]); ++ /* subdevid doubles for boardtype */ ++ varbuf_append(&b, vstr_boardtype, ++ (cis[i + 10] << 8) + cis[i + 9]); ++ } ++ break; ++ ++ case HNBU_BOARDNUM: ++ boardnum = (cis[i + 2] << 8) + cis[i + 1]; ++ break; ++ ++ case HNBU_PATCH: ++ { ++ char vstr_paddr[16]; ++ char vstr_pdata[16]; ++ ++ /* retrieve the patch pairs ++ * from tlen/6; where 6 is ++ * sizeof(patch addr(2)) + ++ * sizeof(patch data(4)). ++ */ ++ patch_pair = tlen/6; ++ ++ for (j = 0; j < patch_pair; j++) { ++ snprintf(vstr_paddr, sizeof(vstr_paddr), ++ "pa%d=0x%%x", j); ++ snprintf(vstr_pdata, sizeof(vstr_pdata), ++ "pd%d=0x%%x", j); ++ ++ varbuf_append(&b, vstr_paddr, ++ (cis[i + (j*6) + 2] << 8) | ++ cis[i + (j*6) + 1]); ++ ++ varbuf_append(&b, vstr_pdata, ++ (cis[i + (j*6) + 6] << 24) | ++ (cis[i + (j*6) + 5] << 16) | ++ (cis[i + (j*6) + 4] << 8) | ++ cis[i + (j*6) + 3]); ++ } ++ } ++ break; ++ ++ case HNBU_BOARDREV: ++ if (tlen == 2) ++ varbuf_append(&b, vstr_boardrev, cis[i + 1]); ++ else ++ varbuf_append(&b, vstr_boardrev, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_BOARDFLAGS: ++ w32 = (cis[i + 2] << 8) + cis[i + 1]; ++ if (tlen >= 5) ++ w32 |= ((cis[i + 4] << 24) + (cis[i + 3] << 16)); ++ varbuf_append(&b, vstr_boardflags, w32); ++ ++ if (tlen >= 7) { ++ w32 = (cis[i + 6] << 8) + cis[i + 5]; ++ if (tlen >= 9) ++ w32 |= ((cis[i + 8] << 24) + ++ (cis[i + 7] << 16)); ++ varbuf_append(&b, vstr_boardflags2, w32); ++ } ++ if (tlen >= 11) { ++ w32 = (cis[i + 10] << 8) + cis[i + 9]; ++ if (tlen >= 13) ++ w32 |= ((cis[i + 12] << 24) + ++ (cis[i + 11] << 16)); ++ varbuf_append(&b, vstr_boardflags3, w32); ++ } ++ break; ++ ++ case HNBU_USBFS: ++ varbuf_append(&b, vstr_usbfs, cis[i + 1]); ++ break; ++ ++ case HNBU_BOARDTYPE: ++ varbuf_append(&b, vstr_boardtype, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_HNBUCIS: ++ /* ++ * what follows is a nonstandard HNBU CIS ++ * that lacks CISTPL_BRCM_HNBU tags ++ * ++ * skip 0xff (end of standard CIS) ++ * after this tuple ++ */ ++ tlen++; ++ standard_cis = FALSE; ++ break; ++ ++ case HNBU_USBEPNUM: ++ varbuf_append(&b, vstr_usbepnum, ++ (cis[i + 2] << 8) | cis[i + 1]); ++ break; ++ ++ case HNBU_PATCH_AUTOINC: { ++ char vstr_paddr[16]; ++ char vstr_pdata[16]; ++ uint32 addr_inc; ++ uint8 pcnt; ++ ++ addr_inc = (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ (cis[i + 1]); ++ ++ pcnt = (tlen - 5)/4; ++ for (j = 0; j < pcnt; j++) { ++ snprintf(vstr_paddr, sizeof(vstr_paddr), ++ "pa%d=0x%%x", j + patch_pair); ++ snprintf(vstr_pdata, sizeof(vstr_pdata), ++ "pd%d=0x%%x", j + patch_pair); ++ ++ varbuf_append(&b, vstr_paddr, addr_inc); ++ varbuf_append(&b, vstr_pdata, ++ (cis[i + (j*4) + 8] << 24) | ++ (cis[i + (j*4) + 7] << 16) | ++ (cis[i + (j*4) + 6] << 8) | ++ cis[i + (j*4) + 5]); ++ addr_inc += 4; ++ } ++ patch_pair += pcnt; ++ } ++ break; ++ case HNBU_PATCH2: ++ { ++ char vstr_paddr[16]; ++ char vstr_pdata[16]; ++ ++ /* retrieve the patch pairs ++ * from tlen/8; where 8 is ++ * sizeof(patch addr(4)) + ++ * sizeof(patch data(4)). ++ */ ++ patch_pair = tlen/8; ++ ++ for (j = 0; j < patch_pair; j++) { ++ snprintf(vstr_paddr, sizeof(vstr_paddr), ++ "pa%d=0x%%x", j); ++ snprintf(vstr_pdata, sizeof(vstr_pdata), ++ "pd%d=0x%%x", j); ++ ++ varbuf_append(&b, vstr_paddr, ++ (cis[i + (j*8) + 4] << 24) | ++ (cis[i + (j*8) + 3] << 16) | ++ (cis[i + (j*8) + 2] << 8) | ++ cis[i + (j*8) + 1]); ++ ++ varbuf_append(&b, vstr_pdata, ++ (cis[i + (j*8) + 8] << 24) | ++ (cis[i + (j*8) + 7] << 16) | ++ (cis[i + (j*8) + 6] << 8) | ++ cis[i + (j*8) + 5]); ++ } ++ } ++ break; ++ case HNBU_USBFLAGS: ++ varbuf_append(&b, vstr_usbflags, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++#ifdef BCM_BOOTLOADER ++ case HNBU_MDIOEX_REGLIST: ++ case HNBU_MDIO_REGLIST: { ++ /* Format: addr (8 bits) | val (16 bits) */ ++ const uint8 msize = 3; ++ char mdiostr[24]; ++ const char *mdiodesc; ++ uint8 *st; ++ ++ mdiodesc = (cis[i] == HNBU_MDIO_REGLIST) ? ++ vstr_mdio : vstr_mdioex; ++ ++ ASSERT(((tlen - 1) % msize) == 0); ++ ++ st = &cis[i + 1]; /* start of reg list */ ++ for (j = 0; j < (tlen - 1); j += msize, st += msize) { ++ snprintf(mdiostr, sizeof(mdiostr), ++ mdiodesc, st[0]); ++ varbuf_append(&b, mdiostr, (st[2] << 8) | st[1]); ++ } ++ } ++ break; ++ case HNBU_BRMIN: ++ varbuf_append(&b, vstr_brmin, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++ ++ case HNBU_BRMAX: ++ varbuf_append(&b, vstr_brmax, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++#endif /* BCM_BOOTLOADER */ ++ ++ case HNBU_RDLID: ++ varbuf_append(&b, vstr_rdlid, ++ (cis[i + 2] << 8) | cis[i + 1]); ++ break; ++ ++ case HNBU_GCI_CCR: ++ { ++ /* format: ++ * |0x80 | <== brcm ++ * |len| <== variable, multiple of 5 ++ * |tup| <== tupletype ++ * |ccreg_ix0|<== ix of ccreg [1byte] ++ * |ccreg_val0|<= corr value [4bytes] ++ * --- ++ * Multiple registers are possible. for eg: we ++ * can specify reg_ix3val3 and reg_ix5val5, etc ++ */ ++ char vstr_gci_ccreg_entry[16]; ++ int num_entries = 0; ++ ++ /* retrieve the index-value pairs ++ * from tlen/5; where 5 is ++ * sizeof(ccreg_ix(1)) + ++ * sizeof(ccreg_val(4)). ++ */ ++ num_entries = tlen/5; ++ ++ for (j = 0; j < num_entries; j++) { ++ snprintf(vstr_gci_ccreg_entry, ++ sizeof(vstr_gci_ccreg_entry), ++ "gcr%d=0x%%x", cis[i + (j*5) + 1]); ++ ++ varbuf_append(&b, vstr_gci_ccreg_entry, ++ (cis[i + (j*5) + 5] << 24) | ++ (cis[i + (j*5) + 4] << 16) | ++ (cis[i + (j*5) + 3] << 8) | ++ cis[i + (j*5) + 2]); ++ } ++ } ++ break; ++ ++#ifdef BCM_BOOTLOADER ++ case HNBU_RDLRNDIS: ++ varbuf_append(&b, vstr_rdlrndis, cis[i + 1]); ++ break; ++ ++ case HNBU_RDLRWU: ++ varbuf_append(&b, vstr_rdlrwu, cis[i + 1]); ++ break; ++ ++ case HNBU_RDLSN: ++ if (tlen >= 5) ++ varbuf_append(&b, vstr_rdlsn, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ else ++ varbuf_append(&b, vstr_rdlsn, ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++ ++ case HNBU_PMUREGS: ++ { ++ uint8 offset = 1, mode_addr, mode, addr; ++ const char *fmt; ++ ++ do { ++ mode_addr = cis[i+offset]; ++ ++ mode = (mode_addr & PMUREGS_MODE_MASK) ++ >> PMUREGS_MODE_SHIFT; ++ addr = mode_addr & PMUREGS_ADDR_MASK; ++ ++ switch (mode) { ++ case PMU_PLLREG_MODE: ++ fmt = vstr_pllreg; ++ break; ++ case PMU_CCREG_MODE: ++ fmt = vstr_ccreg; ++ break; ++ case PMU_VOLTREG_MODE: ++ fmt = vstr_regctrl; ++ break; ++ case PMU_RES_TIME_MODE: ++ fmt = vstr_time; ++ break; ++ case PMU_RESDEPEND_MODE: ++ fmt = vstr_depreg; ++ break; ++ default: ++ fmt = NULL; ++ break; ++ } ++ ++ if (fmt != NULL) { ++ varbuf_append(&b, fmt, addr, ++ (cis[i + offset + 4] << 24) | ++ (cis[i + offset + 3] << 16) | ++ (cis[i + offset + 2] << 8) | ++ cis[i + offset + 1]); ++ } ++ ++ offset += PMUREGS_TPL_SIZE; ++ } while (offset < tlen); ++ } ++ break; ++ ++ case HNBU_USBREGS: ++ { ++ uint8 offset = 1, usb_reg; ++ const char *fmt; ++ ++ do { ++ usb_reg = cis[i+offset]; ++ ++ switch (usb_reg) { ++ case USB_DEV_CTRL_REG: ++ fmt = vstr_usbdevctrl; ++ break; ++ case HSIC_PHY_CTRL1_REG: ++ fmt = vstr_hsicphyctrl1; ++ break; ++ case HSIC_PHY_CTRL2_REG: ++ fmt = vstr_hsicphyctrl2; ++ break; ++ default: ++ fmt = NULL; ++ break; ++ } ++ ++ if (fmt != NULL) { ++ varbuf_append(&b, fmt, ++ (cis[i + offset + 4] << 24) | ++ (cis[i + offset + 3] << 16) | ++ (cis[i + offset + 2] << 8) | ++ cis[i + offset + 1]); ++ } ++ ++ offset += USBREGS_TPL_SIZE; ++ } while (offset < tlen); ++ } ++ break; ++ ++ case HNBU_USBRDY: ++ /* The first byte of this tuple indicate if the host ++ * needs to be informed about the readiness of ++ * the HSIC/USB for enumeration on which GPIO should ++ * the device assert this event. ++ */ ++ varbuf_append(&b, vstr_usbrdy, cis[i + 1]); ++ ++ /* The following fields in this OTP are optional. ++ * The remaining bytes will indicate the delay required ++ * before and/or after the ch_init(). The delay is defined ++ * using 16-bits of this the MSB(bit15 of 15:0) will be ++ * used indicate if the parameter is for Pre or Post delay. ++ */ ++ for (j = 2; j < USBRDY_MAXOTP_SIZE && j < tlen; ++ j += 2) { ++ uint16 usb_delay; ++ ++ usb_delay = cis[i + j] | (cis[i + j + 1] << 8); ++ ++ /* The bit-15 of the delay field will indicate the ++ * type of delay (pre or post). ++ */ ++ if (usb_delay & USBRDY_DLY_TYPE) { ++ varbuf_append(&b, vstr_usbpostdly, ++ (usb_delay & USBRDY_DLY_MASK)); ++ } else { ++ varbuf_append(&b, vstr_usbpredly, ++ (usb_delay & USBRDY_DLY_MASK)); ++ } ++ } ++ break; ++ ++ case HNBU_BLDR_TIMEOUT: ++ /* The Delay after USBConnect for timeout till dongle ++ * receives get_descriptor request. ++ */ ++ varbuf_append(&b, vstr_bldr_reset_timeout, ++ (cis[i + 1] | (cis[i + 2] << 8))); ++ break; ++ case HNBU_MUXENAB: ++ varbuf_append(&b, vstr_muxenab, cis[i + 1]); ++ break; ++#else ++ case HNBU_AA: ++ varbuf_append(&b, vstr_aa2g, cis[i + 1]); ++ if (tlen >= 3) ++ varbuf_append(&b, vstr_aa5g, cis[i + 2]); ++ break; ++ ++ case HNBU_AG: ++ varbuf_append(&b, vstr_ag, 0, cis[i + 1]); ++ if (tlen >= 3) ++ varbuf_append(&b, vstr_ag, 1, cis[i + 2]); ++ if (tlen >= 4) ++ varbuf_append(&b, vstr_ag, 2, cis[i + 3]); ++ if (tlen >= 5) ++ varbuf_append(&b, vstr_ag, 3, cis[i + 4]); ++ ag_init = TRUE; ++ break; ++ ++ case HNBU_ANT5G: ++ varbuf_append(&b, vstr_aa5g, cis[i + 1]); ++ varbuf_append(&b, vstr_ag, 1, cis[i + 2]); ++ break; ++ ++ case HNBU_CC: ++ ASSERT(sromrev == 1); ++ varbuf_append(&b, vstr_cc, cis[i + 1]); ++ break; ++ ++ case HNBU_PAPARMS: ++ switch (tlen) { ++ case 2: ++ ASSERT(sromrev == 1); ++ varbuf_append(&b, vstr_pa0maxpwr, cis[i + 1]); ++ break; ++ case 10: ++ ASSERT(sromrev >= 2); ++ varbuf_append(&b, vstr_opo, cis[i + 9]); ++ /* FALLTHROUGH */ ++ case 9: ++ varbuf_append(&b, vstr_pa0maxpwr, cis[i + 8]); ++ /* FALLTHROUGH */ ++ BCMDONGLECASE(8) ++ varbuf_append(&b, vstr_pa0itssit, cis[i + 7]); ++ /* FALLTHROUGH */ ++ BCMDONGLECASE(7) ++ for (j = 0; j < 3; j++) { ++ varbuf_append(&b, vstr_pa0b[j], ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ } ++ break; ++ default: ++ ASSERT((tlen == 2) || (tlen == 9) || (tlen == 10)); ++ break; ++ } ++ break; ++ ++ case HNBU_PAPARMS5G: ++ ASSERT((sromrev == 2) || (sromrev == 3)); ++ switch (tlen) { ++ case 23: ++ varbuf_append(&b, vstr_pa1himaxpwr, cis[i + 22]); ++ varbuf_append(&b, vstr_pa1lomaxpwr, cis[i + 21]); ++ varbuf_append(&b, vstr_pa1maxpwr, cis[i + 20]); ++ /* FALLTHROUGH */ ++ case 20: ++ varbuf_append(&b, vstr_pa1itssit, cis[i + 19]); ++ /* FALLTHROUGH */ ++ case 19: ++ for (j = 0; j < 3; j++) { ++ varbuf_append(&b, vstr_pa1b[j], ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ } ++ for (j = 3; j < 6; j++) { ++ varbuf_append(&b, vstr_pa1lob[j - 3], ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ } ++ for (j = 6; j < 9; j++) { ++ varbuf_append(&b, vstr_pa1hib[j - 6], ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ } ++ break; ++ default: ++ ASSERT((tlen == 19) || ++ (tlen == 20) || (tlen == 23)); ++ break; ++ } ++ break; ++ ++ case HNBU_OEM: ++ ASSERT(sromrev == 1); ++ varbuf_append(&b, vstr_oem, ++ cis[i + 1], cis[i + 2], ++ cis[i + 3], cis[i + 4], ++ cis[i + 5], cis[i + 6], ++ cis[i + 7], cis[i + 8]); ++ break; ++ ++ case HNBU_LEDS: ++ for (j = 1; j <= 4; j++) { ++ if (cis[i + j] != 0xff) { ++ varbuf_append(&b, vstr_ledbh, j-1, ++ cis[i + j]); ++ } ++ } ++ break; ++ ++ case HNBU_CCODE: ++ ASSERT(sromrev > 1); ++ if ((cis[i + 1] == 0) || (cis[i + 2] == 0)) ++ varbuf_append(&b, vstr_noccode); ++ else ++ varbuf_append(&b, vstr_ccode, ++ cis[i + 1], cis[i + 2]); ++ varbuf_append(&b, vstr_cctl, cis[i + 3]); ++ break; ++ ++ case HNBU_CCKPO: ++ ASSERT(sromrev > 2); ++ varbuf_append(&b, vstr_cckpo, ++ (cis[i + 2] << 8) | cis[i + 1]); ++ break; ++ ++ case HNBU_OFDMPO: ++ ASSERT(sromrev > 2); ++ varbuf_append(&b, vstr_ofdmpo, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++ ++ case HNBU_WPS: ++ varbuf_append(&b, vstr_wpsgpio, cis[i + 1]); ++ if (tlen >= 3) ++ varbuf_append(&b, vstr_wpsled, cis[i + 2]); ++ break; ++ ++ case HNBU_RSSISMBXA2G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_rssismf2g, cis[i + 1] & 0xf); ++ varbuf_append(&b, vstr_rssismc2g, (cis[i + 1] >> 4) & 0xf); ++ varbuf_append(&b, vstr_rssisav2g, cis[i + 2] & 0x7); ++ varbuf_append(&b, vstr_bxa2g, (cis[i + 2] >> 3) & 0x3); ++ break; ++ ++ case HNBU_RSSISMBXA5G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_rssismf5g, cis[i + 1] & 0xf); ++ varbuf_append(&b, vstr_rssismc5g, (cis[i + 1] >> 4) & 0xf); ++ varbuf_append(&b, vstr_rssisav5g, cis[i + 2] & 0x7); ++ varbuf_append(&b, vstr_bxa5g, (cis[i + 2] >> 3) & 0x3); ++ break; ++ ++ case HNBU_TRI2G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_tri2g, cis[i + 1]); ++ break; ++ ++ case HNBU_TRI5G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_tri5gl, cis[i + 1]); ++ varbuf_append(&b, vstr_tri5g, cis[i + 2]); ++ varbuf_append(&b, vstr_tri5gh, cis[i + 3]); ++ break; ++ ++ case HNBU_RXPO2G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_rxpo2g, cis[i + 1]); ++ break; ++ ++ case HNBU_RXPO5G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_rxpo5g, cis[i + 1]); ++ break; ++ ++ case HNBU_MACADDR: ++ if (!(ETHER_ISNULLADDR(&cis[i+1])) && ++ !(ETHER_ISMULTI(&cis[i+1]))) { ++ bcm_ether_ntoa((struct ether_addr *)&cis[i + 1], ++ eabuf); ++ ++ /* set boardnum if HNBU_BOARDNUM not seen yet */ ++ if (boardnum == -1) ++ boardnum = (cis[i + 5] << 8) + cis[i + 6]; ++ } ++ break; ++ ++ case HNBU_LEDDC: ++ /* CIS leddc only has 16bits, convert it to 32bits */ ++ w32 = ((cis[i + 2] << 24) | /* oncount */ ++ (cis[i + 1] << 8)); /* offcount */ ++ varbuf_append(&b, vstr_leddc, w32); ++ break; ++ ++ case HNBU_CHAINSWITCH: ++ varbuf_append(&b, vstr_txchain, cis[i + 1]); ++ varbuf_append(&b, vstr_rxchain, cis[i + 2]); ++ varbuf_append(&b, vstr_antswitch, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ break; ++ ++ case HNBU_ELNA2G: ++ varbuf_append(&b, vstr_elna2g, cis[i + 1]); ++ break; ++ ++ case HNBU_ELNA5G: ++ varbuf_append(&b, vstr_elna5g, cis[i + 1]); ++ break; ++ ++ case HNBU_REGREV: ++ varbuf_append(&b, vstr_regrev, cis[i + 1]); ++ break; ++ ++ case HNBU_FEM: { ++ uint16 fem = (cis[i + 2] << 8) + cis[i + 1]; ++ varbuf_append(&b, vstr_antswctl2g, (fem & ++ SROM8_FEM_ANTSWLUT_MASK) >> ++ SROM8_FEM_ANTSWLUT_SHIFT); ++ varbuf_append(&b, vstr_triso2g, (fem & ++ SROM8_FEM_TR_ISO_MASK) >> ++ SROM8_FEM_TR_ISO_SHIFT); ++ varbuf_append(&b, vstr_pdetrange2g, (fem & ++ SROM8_FEM_PDET_RANGE_MASK) >> ++ SROM8_FEM_PDET_RANGE_SHIFT); ++ varbuf_append(&b, vstr_extpagain2g, (fem & ++ SROM8_FEM_EXTPA_GAIN_MASK) >> ++ SROM8_FEM_EXTPA_GAIN_SHIFT); ++ varbuf_append(&b, vstr_tssipos2g, (fem & ++ SROM8_FEM_TSSIPOS_MASK) >> ++ SROM8_FEM_TSSIPOS_SHIFT); ++ if (tlen < 5) break; ++ ++ fem = (cis[i + 4] << 8) + cis[i + 3]; ++ varbuf_append(&b, vstr_antswctl5g, (fem & ++ SROM8_FEM_ANTSWLUT_MASK) >> ++ SROM8_FEM_ANTSWLUT_SHIFT); ++ varbuf_append(&b, vstr_triso5g, (fem & ++ SROM8_FEM_TR_ISO_MASK) >> ++ SROM8_FEM_TR_ISO_SHIFT); ++ varbuf_append(&b, vstr_pdetrange5g, (fem & ++ SROM8_FEM_PDET_RANGE_MASK) >> ++ SROM8_FEM_PDET_RANGE_SHIFT); ++ varbuf_append(&b, vstr_extpagain5g, (fem & ++ SROM8_FEM_EXTPA_GAIN_MASK) >> ++ SROM8_FEM_EXTPA_GAIN_SHIFT); ++ varbuf_append(&b, vstr_tssipos5g, (fem & ++ SROM8_FEM_TSSIPOS_MASK) >> ++ SROM8_FEM_TSSIPOS_SHIFT); ++ break; ++ } ++ ++ case HNBU_PAPARMS_C0: ++ varbuf_append(&b, vstr_maxp2ga, 0, cis[i + 1]); ++ varbuf_append(&b, vstr_itt2ga0, cis[i + 2]); ++ varbuf_append(&b, vstr_pa, 2, 0, 0, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ varbuf_append(&b, vstr_pa, 2, 1, 0, ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_pa, 2, 2, 0, ++ (cis[i + 8] << 8) + cis[i + 7]); ++ if (tlen < 31) break; ++ ++ varbuf_append(&b, vstr_maxp5ga0, cis[i + 9]); ++ varbuf_append(&b, vstr_itt5ga0, cis[i + 10]); ++ varbuf_append(&b, vstr_maxp5gha0, cis[i + 11]); ++ varbuf_append(&b, vstr_maxp5gla0, cis[i + 12]); ++ varbuf_append(&b, vstr_pa, 5, 0, 0, ++ (cis[i + 14] << 8) + cis[i + 13]); ++ varbuf_append(&b, vstr_pa, 5, 1, 0, ++ (cis[i + 16] << 8) + cis[i + 15]); ++ varbuf_append(&b, vstr_pa, 5, 2, 0, ++ (cis[i + 18] << 8) + cis[i + 17]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 0, 0, ++ (cis[i + 20] << 8) + cis[i + 19]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 1, 0, ++ (cis[i + 22] << 8) + cis[i + 21]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 2, 0, ++ (cis[i + 24] << 8) + cis[i + 23]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 0, 0, ++ (cis[i + 26] << 8) + cis[i + 25]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 1, 0, ++ (cis[i + 28] << 8) + cis[i + 27]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 2, 0, ++ (cis[i + 30] << 8) + cis[i + 29]); ++ break; ++ ++ case HNBU_PAPARMS_C1: ++ varbuf_append(&b, vstr_maxp2ga, 1, cis[i + 1]); ++ varbuf_append(&b, vstr_itt2ga1, cis[i + 2]); ++ varbuf_append(&b, vstr_pa, 2, 0, 1, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ varbuf_append(&b, vstr_pa, 2, 1, 1, ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_pa, 2, 2, 1, ++ (cis[i + 8] << 8) + cis[i + 7]); ++ if (tlen < 31) break; ++ ++ varbuf_append(&b, vstr_maxp5ga1, cis[i + 9]); ++ varbuf_append(&b, vstr_itt5ga1, cis[i + 10]); ++ varbuf_append(&b, vstr_maxp5gha1, cis[i + 11]); ++ varbuf_append(&b, vstr_maxp5gla1, cis[i + 12]); ++ varbuf_append(&b, vstr_pa, 5, 0, 1, ++ (cis[i + 14] << 8) + cis[i + 13]); ++ varbuf_append(&b, vstr_pa, 5, 1, 1, ++ (cis[i + 16] << 8) + cis[i + 15]); ++ varbuf_append(&b, vstr_pa, 5, 2, 1, ++ (cis[i + 18] << 8) + cis[i + 17]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 0, 1, ++ (cis[i + 20] << 8) + cis[i + 19]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 1, 1, ++ (cis[i + 22] << 8) + cis[i + 21]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 2, 1, ++ (cis[i + 24] << 8) + cis[i + 23]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 0, 1, ++ (cis[i + 26] << 8) + cis[i + 25]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 1, 1, ++ (cis[i + 28] << 8) + cis[i + 27]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 2, 1, ++ (cis[i + 30] << 8) + cis[i + 29]); ++ break; ++ ++ case HNBU_PO_CCKOFDM: ++ varbuf_append(&b, vstr_cck2gpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_ofdm2gpo, ++ (cis[i + 6] << 24) + (cis[i + 5] << 16) + ++ (cis[i + 4] << 8) + cis[i + 3]); ++ if (tlen < 19) break; ++ ++ varbuf_append(&b, vstr_ofdm5gpo, ++ (cis[i + 10] << 24) + (cis[i + 9] << 16) + ++ (cis[i + 8] << 8) + cis[i + 7]); ++ varbuf_append(&b, vstr_ofdm5glpo, ++ (cis[i + 14] << 24) + (cis[i + 13] << 16) + ++ (cis[i + 12] << 8) + cis[i + 11]); ++ varbuf_append(&b, vstr_ofdm5ghpo, ++ (cis[i + 18] << 24) + (cis[i + 17] << 16) + ++ (cis[i + 16] << 8) + cis[i + 15]); ++ break; ++ ++ case HNBU_PO_MCS2G: ++ for (j = 0; j <= (tlen/2); j++) { ++ varbuf_append(&b, vstr_mcspo, 2, j, ++ (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]); ++ } ++ break; ++ ++ case HNBU_PO_MCS5GM: ++ for (j = 0; j <= (tlen/2); j++) { ++ varbuf_append(&b, vstr_mcspo, 5, j, ++ (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]); ++ } ++ break; ++ ++ case HNBU_PO_MCS5GLH: ++ for (j = 0; j <= (tlen/4); j++) { ++ varbuf_append(&b, vstr_mcspohl, 5, 'l', j, ++ (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]); ++ } ++ ++ for (j = 0; j <= (tlen/4); j++) { ++ varbuf_append(&b, vstr_mcspohl, 5, 'h', j, ++ (cis[i + ((tlen/2)+2) + 2*j] << 8) + ++ cis[i + ((tlen/2)+1) + 2*j]); ++ } ++ ++ break; ++ ++ case HNBU_PO_CDD: ++ varbuf_append(&b, vstr_cddpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_PO_STBC: ++ varbuf_append(&b, vstr_stbcpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_PO_40M: ++ varbuf_append(&b, vstr_bw40po, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_PO_40MDUP: ++ varbuf_append(&b, vstr_bwduppo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_OFDMPO5G: ++ varbuf_append(&b, vstr_ofdm5gpo, ++ (cis[i + 4] << 24) + (cis[i + 3] << 16) + ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_ofdm5glpo, ++ (cis[i + 8] << 24) + (cis[i + 7] << 16) + ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_ofdm5ghpo, ++ (cis[i + 12] << 24) + (cis[i + 11] << 16) + ++ (cis[i + 10] << 8) + cis[i + 9]); ++ break; ++ /* Power per rate for SROM V9 */ ++ case HNBU_CCKBW202GPO: ++ varbuf_append(&b, vstr_cckbw202gpo[0], ++ ((cis[i + 2] << 8) + cis[i + 1])); ++ if (tlen > 4) ++ varbuf_append(&b, vstr_cckbw202gpo[1], ++ ((cis[i + 4] << 8) + cis[i + 3])); ++ break; ++ ++ case HNBU_LEGOFDMBW202GPO: ++ varbuf_append(&b, vstr_legofdmbw202gpo[0], ++ ((cis[i + 4] << 24) + (cis[i + 3] << 16) + ++ (cis[i + 2] << 8) + cis[i + 1])); ++ if (tlen > 6) { ++ varbuf_append(&b, vstr_legofdmbw202gpo[1], ++ ((cis[i + 8] << 24) + (cis[i + 7] << 16) + ++ (cis[i + 6] << 8) + cis[i + 5])); ++ } ++ break; ++ ++ case HNBU_LEGOFDMBW205GPO: ++ for (j = 0; j < 6; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_legofdmbw205gpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS2GPO: ++ for (j = 0; j < 3; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_mcs2gpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS5GLPO: ++ for (j = 0; j < 3; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_mcs5glpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS5GMPO: ++ for (j = 0; j < 3; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_mcs5gmpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS5GHPO: ++ for (j = 0; j < 3; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_mcs5ghpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS32PO: ++ varbuf_append(&b, vstr_mcs32po, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_LEG40DUPPO: ++ varbuf_append(&b, vstr_legofdm40duppo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_CUSTOM1: ++ varbuf_append(&b, vstr_custom, 1, ((cis[i + 4] << 24) + ++ (cis[i + 3] << 16) + (cis[i + 2] << 8) + ++ cis[i + 1])); ++ break; ++ ++#if defined(BCMCCISSR3) ++ case HNBU_SROM3SWRGN: ++ if (tlen >= 73) { ++ uint16 srom[35]; ++ uint8 srev = cis[i + 1 + 70]; ++ ASSERT(srev == 3); ++ /* make tuple value 16-bit aligned and parse it */ ++ bcopy(&cis[i + 1], srom, sizeof(srom)); ++ _initvars_srom_pci(srev, srom, SROM3_SWRGN_OFF, &b); ++ /* 2.4G antenna gain is included in SROM */ ++ ag_init = TRUE; ++ /* Ethernet MAC address is included in SROM */ ++ eabuf[0] = 0; ++ boardnum = -1; ++ } ++ /* create extra variables */ ++ if (tlen >= 75) ++ varbuf_append(&b, vstr_vendid, ++ (cis[i + 1 + 73] << 8) + ++ cis[i + 1 + 72]); ++ if (tlen >= 77) ++ varbuf_append(&b, vstr_devid, ++ (cis[i + 1 + 75] << 8) + ++ cis[i + 1 + 74]); ++ if (tlen >= 79) ++ varbuf_append(&b, vstr_xtalfreq, ++ (cis[i + 1 + 77] << 8) + ++ cis[i + 1 + 76]); ++ break; ++#endif ++ ++ case HNBU_CCKFILTTYPE: ++ varbuf_append(&b, vstr_cckdigfilttype, ++ (cis[i + 1])); ++ break; ++ ++ case HNBU_TEMPTHRESH: ++ varbuf_append(&b, vstr_tempthresh, ++ (cis[i + 1])); ++ /* period in msb nibble */ ++ varbuf_append(&b, vstr_temps_period, ++ (cis[i + 2] >> 4)); ++ /* hysterisis in lsb nibble */ ++ varbuf_append(&b, vstr_temp_hysteresis, ++ (cis[i + 2] & 0xF)); ++ if (tlen >= 4) ++ varbuf_append(&b, vstr_tempoffset, ++ (cis[i + 3])); ++ if (tlen >= 5) { ++ varbuf_append(&b, vstr_temp_corrx, ++ (cis[i + 4] >> 2)); ++ varbuf_append(&b, vstr_tempsense_option, ++ (cis[i + 4] & 0x3)); ++ } ++ if (tlen >= 6) ++ varbuf_append(&b, vstr_phycal_tempdelta, ++ (cis[i + 5])); ++ break; ++ ++ case HNBU_FEM_CFG: ++ /* fem_cfg1 */ ++ varbuf_append(&b, vstr_tssiposslopeg, 2, ++ (cis[i + 1] & 0x1)); ++ varbuf_append(&b, vstr_epagaing, 2, ++ (cis[i + 1] & 0xe) >> 1); ++ varbuf_append(&b, vstr_pdgaing, 2, ++ ((cis[i + 2] & 0x1) << 8) + ++ ((cis[i + 1] & 0xf0) >> 4)); ++ varbuf_append(&b, vstr_tworangetssi, 2, ++ (cis[i + 2] & 0x2) >> 1); ++ varbuf_append(&b, vstr_papdcap, 2, ++ (cis[i + 2] & 0x4) >> 2); ++ varbuf_append(&b, vstr_femctrl, ++ (cis[i + 2] & 0xf8) >> 3); ++ /* fem_cfg2 */ ++ varbuf_append(&b, vstr_tssiposslopeg, 5, ++ (cis[i + 3] & 0x1)); ++ varbuf_append(&b, vstr_epagaing, 5, ++ (cis[i + 3] & 0xe) >> 1); ++ varbuf_append(&b, vstr_pdgaing, 5, ++ ((cis[i + 4] & 0x1) << 8) + ++ ((cis[i + 3] & 0xf0) >> 4)); ++ varbuf_append(&b, vstr_tworangetssi, 2, ++ (cis[i + 4] & 0x2) >> 1); ++ varbuf_append(&b, vstr_papdcap, 5, ++ (cis[i + 4] & 0x4) >> 2); ++ varbuf_append(&b, vstr_gainctrlsph, ++ (cis[i + 4] & 0xf8) >> 3); ++ break; ++ ++ case HNBU_ACPA_C0: ++ { ++ const int a = 0; ++ ++ varbuf_append(&b, vstr_subband5gver, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_maxp2ga, a, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ /* pa2g */ ++ varbuf_append(&b, vstr_pa2ga, 2, a, ++ (cis[i + 6] << 8) + cis[i + 5], ++ (cis[i + 8] << 8) + cis[i + 7], ++ (cis[i + 10] << 8) + cis[i + 9]); ++ /* rxgains */ ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a, ++ cis[i + 11] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a, ++ (cis[i + 11] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a, ++ (cis[i + 11] & 0x80) >> 7); ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a, ++ cis[i + 12] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a, ++ (cis[i + 12] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a, ++ (cis[i + 12] & 0x80) >> 7); ++ /* maxp5g */ ++ varbuf_append(&b, vstr_maxp5ga, a, ++ cis[i + 13], ++ cis[i + 14], ++ cis[i + 15], ++ cis[i + 16]); ++ /* pa5g */ ++ varbuf_append(&b, vstr_pa5ga, a, ++ (cis[i + 18] << 8) + cis[i + 17], ++ (cis[i + 20] << 8) + cis[i + 19], ++ (cis[i + 22] << 8) + cis[i + 21], ++ (cis[i + 24] << 8) + cis[i + 23], ++ (cis[i + 26] << 8) + cis[i + 25], ++ (cis[i + 28] << 8) + cis[i + 27], ++ (cis[i + 30] << 8) + cis[i + 29], ++ (cis[i + 32] << 8) + cis[i + 31], ++ (cis[i + 34] << 8) + cis[i + 33], ++ (cis[i + 36] << 8) + cis[i + 35], ++ (cis[i + 38] << 8) + cis[i + 37], ++ (cis[i + 40] << 8) + cis[i + 39]); ++ break; ++ } ++ ++ case HNBU_ACPA_C1: ++ { ++ const int a = 1; ++ ++ varbuf_append(&b, vstr_maxp2ga, a, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ /* pa2g */ ++ varbuf_append(&b, vstr_pa2ga, 2, a, ++ (cis[i + 4] << 8) + cis[i + 3], ++ (cis[i + 6] << 8) + cis[i + 5], ++ (cis[i + 8] << 8) + cis[i + 7]); ++ /* rxgains */ ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a, ++ cis[i + 9] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a, ++ (cis[i + 9] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a, ++ (cis[i + 9] & 0x80) >> 7); ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a, ++ cis[i + 10] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a, ++ (cis[i + 10] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a, ++ (cis[i + 10] & 0x80) >> 7); ++ /* maxp5g */ ++ varbuf_append(&b, vstr_maxp5ga, a, ++ cis[i + 11], ++ cis[i + 12], ++ cis[i + 13], ++ cis[i + 14]); ++ /* pa5g */ ++ varbuf_append(&b, vstr_pa5ga, a, ++ (cis[i + 16] << 8) + cis[i + 15], ++ (cis[i + 18] << 8) + cis[i + 17], ++ (cis[i + 20] << 8) + cis[i + 19], ++ (cis[i + 22] << 8) + cis[i + 21], ++ (cis[i + 24] << 8) + cis[i + 23], ++ (cis[i + 26] << 8) + cis[i + 25], ++ (cis[i + 28] << 8) + cis[i + 27], ++ (cis[i + 30] << 8) + cis[i + 29], ++ (cis[i + 32] << 8) + cis[i + 31], ++ (cis[i + 34] << 8) + cis[i + 33], ++ (cis[i + 36] << 8) + cis[i + 35], ++ (cis[i + 38] << 8) + cis[i + 37]); ++ break; ++ } ++ ++ case HNBU_ACPA_C2: ++ { ++ const int a = 2; ++ ++ varbuf_append(&b, vstr_maxp2ga, a, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ /* pa2g */ ++ varbuf_append(&b, vstr_pa2ga, 2, a, ++ (cis[i + 4] << 8) + cis[i + 3], ++ (cis[i + 6] << 8) + cis[i + 5], ++ (cis[i + 8] << 8) + cis[i + 7]); ++ /* rxgains */ ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a, ++ cis[i + 9] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a, ++ (cis[i + 9] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a, ++ (cis[i + 9] & 0x80) >> 7); ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a, ++ cis[i + 10] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a, ++ (cis[i + 10] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a, ++ (cis[i + 10] & 0x80) >> 7); ++ /* maxp5g */ ++ varbuf_append(&b, vstr_maxp5ga, a, ++ cis[i + 11], ++ cis[i + 12], ++ cis[i + 13], ++ cis[i + 14]); ++ /* pa5g */ ++ varbuf_append(&b, vstr_pa5ga, a, ++ (cis[i + 16] << 8) + cis[i + 15], ++ (cis[i + 18] << 8) + cis[i + 17], ++ (cis[i + 20] << 8) + cis[i + 19], ++ (cis[i + 22] << 8) + cis[i + 21], ++ (cis[i + 24] << 8) + cis[i + 23], ++ (cis[i + 26] << 8) + cis[i + 25], ++ (cis[i + 28] << 8) + cis[i + 27], ++ (cis[i + 30] << 8) + cis[i + 29], ++ (cis[i + 32] << 8) + cis[i + 31], ++ (cis[i + 34] << 8) + cis[i + 33], ++ (cis[i + 36] << 8) + cis[i + 35], ++ (cis[i + 38] << 8) + cis[i + 37]); ++ break; ++ } ++ ++ case HNBU_MEAS_PWR: ++ varbuf_append(&b, vstr_measpower, cis[i + 1]); ++ varbuf_append(&b, vstr_measpowerX, 1, (cis[i + 2])); ++ varbuf_append(&b, vstr_measpowerX, 2, (cis[i + 3])); ++ varbuf_append(&b, vstr_rawtempsense, ++ ((cis[i + 5] & 0x1) << 8) + cis[i + 4]); ++ break; ++ ++ case HNBU_ACPPR_2GPO: ++ varbuf_append(&b, vstr_dot11agofdmhrbw202gpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_ofdmlrbw202gpo, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ break; ++ ++ case HNBU_ACPPR_5GPO: ++ varbuf_append(&b, vstr_mcsbw805glpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_mcsbw1605glpo, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ varbuf_append(&b, vstr_mcsbw805gmpo, ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_mcsbw1605gmpo, ++ (cis[i + 8] << 8) + cis[i + 7]); ++ varbuf_append(&b, vstr_mcsbw805ghpo, ++ (cis[i + 10] << 8) + cis[i + 9]); ++ varbuf_append(&b, vstr_mcsbw1605ghpo, ++ (cis[i + 12] << 8) + cis[i + 11]); ++ varbuf_append(&b, vstr_mcslr5rlpo, ++ (cis[i + 14] << 8) + cis[i + 13]); ++ varbuf_append(&b, vstr_mcslr5gmpo, ++ (cis[i + 16] << 8) + cis[i + 15]); ++ varbuf_append(&b, vstr_mcslr5ghpo, ++ (cis[i + 18] << 8) + cis[i + 17]); ++ break; ++ ++ case HNBU_ACPPR_SBPO: ++ varbuf_append(&b, vstr_sb20in40rrpo, 'h', ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'l', ++ (cis[i + 4] << 8) + cis[i + 3]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'l', ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'm', ++ (cis[i + 8] << 8) + cis[i + 7]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'm', ++ (cis[i + 10] << 8) + cis[i + 9]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'h', ++ (cis[i + 12] << 8) + cis[i + 11]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'h', ++ (cis[i + 14] << 8) + cis[i + 13]); ++ varbuf_append(&b, vstr_sb20in40rrpo, 'l', ++ (cis[i + 16] << 8) + cis[i + 15]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'l', ++ (cis[i + 18] << 8) + cis[i + 17]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'l', ++ (cis[i + 20] << 8) + cis[i + 19]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'm', ++ (cis[i + 22] << 8) + cis[i + 21]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'm', ++ (cis[i + 24] << 8) + cis[i + 23]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'h', ++ (cis[i + 26] << 8) + cis[i + 25]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'h', ++ (cis[i + 28] << 8) + cis[i + 27]); ++ varbuf_append(&b, vstr_dot11agduprpo, 'h', ++ (cis[i + 30] << 8) + cis[i + 24]); ++ varbuf_append(&b, vstr_dot11agduprpo, 'l', ++ (cis[i + 32] << 8) + cis[i + 26]); ++ break; ++ ++ case HNBU_NOISELVL: ++ /* noiselvl2g */ ++ varbuf_append(&b, vstr_noiselvl2ga, 0, ++ (cis[i + 1] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl2ga, 1, ++ ((cis[i + 2] & 0x3) << 4) + ++ ((cis[i + 1] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl2ga, 2, ++ (cis[i + 2] & 0x7c) >> 2); ++ /* noiselvl5gl */ ++ varbuf_append(&b, vstr_noiselvl5ga, 'l', 0, ++ (cis[i + 3] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'l', 1, ++ ((cis[i + 4] & 0x3) << 4) + ++ ((cis[i + 3] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'l', 2, ++ (cis[i + 4] & 0x7c) >> 2); ++ /* noiselvl5gm */ ++ varbuf_append(&b, vstr_noiselvl5ga, 'm', 0, ++ (cis[i + 5] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'm', 1, ++ ((cis[i + 6] & 0x3) << 4) + ++ ((cis[i + 5] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'm', 2, ++ (cis[i + 6] & 0x7c) >> 2); ++ /* noiselvl5gh */ ++ varbuf_append(&b, vstr_noiselvl5ga, 'h', 0, ++ (cis[i + 7] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'h', 1, ++ ((cis[i + 8] & 0x3) << 4) + ++ ((cis[i + 7] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'h', 2, ++ (cis[i + 8] & 0x7c) >> 2); ++ /* noiselvl5gu */ ++ varbuf_append(&b, vstr_noiselvl5ga, 'u', 0, ++ (cis[i + 9] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'u', 1, ++ ((cis[i + 10] & 0x3) << 4) + ++ ((cis[i + 9] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'u', 2, ++ (cis[i + 10] & 0x7c) >> 2); ++ break; ++ ++ case HNBU_RXGAIN_ERR: ++ varbuf_append(&b, vstr_rxgainerr2g, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_rxgainerr5g, ++ (cis[i + 4] << 8) + cis[i + 3], ++ (cis[i + 6] << 8) + cis[i + 5], ++ (cis[i + 8] << 8) + cis[i + 7], ++ (cis[i + 10] << 8) + cis[i + 9]); ++ break; ++ ++ case HNBU_AGBGA: ++ varbuf_append(&b, vstr_agbg, 0, cis[i + 1]); ++ varbuf_append(&b, vstr_agbg, 1, cis[i + 2]); ++ varbuf_append(&b, vstr_agbg, 2, cis[i + 3]); ++ varbuf_append(&b, vstr_aga, 3, cis[i + 4]); ++ varbuf_append(&b, vstr_aga, 4, cis[i + 5]); ++ varbuf_append(&b, vstr_aga, 5, cis[i + 6]); ++ break; ++ ++ case HNBU_UUID: ++ { ++ /* uuid format 12345678-1234-5678-1234-567812345678 */ ++ ++ char uuidstr[37]; /* 32 ids, 4 '-', 1 Null */ ++ ++ snprintf(uuidstr, sizeof(uuidstr), ++ "%02X%02X%02X%02X-%02X%02X-%02X%02X-" ++ "%02X%02X-%02X%02X%02X%02X%02X%02X", ++ cis[i + 1], cis[i + 2], cis[i + 3], cis[i + 4], ++ cis[i + 5], cis[i + 6], cis[i + 7], cis[i + 8], ++ cis[i + 9], cis[i + 10], cis[i + 11], cis[i + 12], ++ cis[i + 13], cis[i + 14], cis[i + 15], cis[i + 16]); ++ ++ varbuf_append(&b, vstr_uuid, uuidstr); ++ break; ++ ++ } ++#endif /* !BCM_BOOTLOADER */ ++ } ++ ++ break; ++ } ++ i += tlen; ++ } while (tup != CISTPL_END); ++ } ++ ++ if (boardnum != -1) { ++ varbuf_append(&b, vstr_boardnum, boardnum); ++ } ++ ++ if (eabuf[0]) { ++ varbuf_append(&b, vstr_macaddr, eabuf); ++ } ++ ++#ifndef BCM_BOOTLOADER ++ /* if there is no antenna gain field, set default */ ++ if (getvar(NULL, "ag0") == NULL && ag_init == FALSE) { ++ varbuf_append(&b, vstr_ag, 0, 0xff); ++ } ++#endif ++ ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++ varbuf_append(&b, vstr_end, NULL); ++#endif /* BCMUSBDEV_BMAC */ ++ ++ /* final nullbyte terminator */ ++ ASSERT(b.size >= 1); ++ *b.buf++ = '\0'; ++ ++ ASSERT(b.buf - base <= MAXSZ_NVRAM_VARS); ++ err = initvars_table(osh, base, b.buf, vars, count); ++ ++ MFREE(osh, base, MAXSZ_NVRAM_VARS); ++ return err; ++} ++ ++/* set PCMCIA sprom command register */ ++static int ++sprom_cmd_pcmcia(osl_t *osh, uint8 cmd) ++{ ++ uint8 status = 0; ++ uint wait_cnt = 1000; ++ ++ /* write sprom command register */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_CS, &cmd, 1); ++ ++ /* wait status */ ++ while (wait_cnt--) { ++ OSL_PCMCIA_READ_ATTR(osh, SROM_CS, &status, 1); ++ if (status & SROM_DONE) ++ return 0; ++ } ++ ++ return 1; ++} ++ ++/* read a word from the PCMCIA srom */ ++static int ++sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; ++ ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ ++ /* set address */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1); ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1); ++ ++ /* do read */ ++ if (sprom_cmd_pcmcia(osh, SROM_READ)) ++ return 1; ++ ++ /* read data */ ++ data_h = data_l = 0; ++ OSL_PCMCIA_READ_ATTR(osh, SROM_DATAH, &data_h, 1); ++ OSL_PCMCIA_READ_ATTR(osh, SROM_DATAL, &data_l, 1); ++ ++ *data = (data_h << 8) | data_l; ++ return 0; ++} ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++/* write a word to the PCMCIA srom */ ++static int ++sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; ++ ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ data_l = (uint8)(data & 0xff); ++ data_h = (uint8)((data >> 8) & 0xff); ++ ++ /* set address */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1); ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1); ++ ++ /* write data */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAH, &data_h, 1); ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAL, &data_l, 1); ++ ++ /* do write */ ++ return sprom_cmd_pcmcia(osh, SROM_WRITE); ++} ++#endif ++ ++/* In chips with chipcommon rev 32 and later, the srom is in chipcommon, ++ * not in the bus cores. ++ */ ++static uint16 ++srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, uint32 cmd, uint wordoff, uint16 data) ++{ ++ chipcregs_t *cc = (chipcregs_t *)ccregs; ++ uint wait_cnt = 1000; ++ ++ if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) { ++ W_REG(osh, &cc->sromaddress, wordoff * 2); ++ if (cmd == SRC_OP_WRITE) ++ W_REG(osh, &cc->sromdata, data); ++ } ++ ++ W_REG(osh, &cc->sromcontrol, SRC_START | cmd); ++ ++ while (wait_cnt--) { ++ if ((R_REG(osh, &cc->sromcontrol) & SRC_BUSY) == 0) ++ break; ++ } ++ ++ if (!wait_cnt) { ++ BS_ERROR(("%s: Command 0x%x timed out\n", __FUNCTION__, cmd)); ++ return 0xffff; ++ } ++ if (cmd == SRC_OP_READ) ++ return (uint16)R_REG(osh, &cc->sromdata); ++ else ++ return 0xffff; ++} ++ ++/* ++ * Read in and validate sprom. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++sprom_read_pci(osl_t *osh, si_t *sih, uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, ++ bool check_crc) ++{ ++ int err = 0; ++ uint i; ++ void *ccregs = NULL; ++ uint32 ccval = 0; ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ /* save current control setting */ ++ ccval = si_chipcontrl_read(sih); ++ } ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID)) { ++ /* Disable Ext PA lines to allow reading from SROM */ ++ si_chipcontrl_epa4331(sih, FALSE); ++ } else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ si_chipcontrl_srom4360(sih, TRUE); ++ } ++ ++ /* read the sprom */ ++ for (i = 0; i < nwords; i++) { ++ ++ if (sih->ccrev > 31 && ISSIM_ENAB(sih)) { ++ /* use indirect since direct is too slow on QT */ ++ if ((sih->cccaps & CC_CAP_SROM) == 0) { ++ err = 1; ++ goto error; ++ } ++ ++ ccregs = (void *)((uint8 *)sprom - CC_SROM_OTP); ++ buf[i] = srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ, wordoff + i, 0); ++ ++ } else { ++ if (ISSIM_ENAB(sih)) ++ buf[i] = R_REG(osh, &sprom[wordoff + i]); ++ ++ buf[i] = R_REG(osh, &sprom[wordoff + i]); ++ } ++ ++ } ++ ++ /* bypass crc checking for simulation to allow srom hack */ ++ if (ISSIM_ENAB(sih)) { ++ goto error; ++ } ++ ++ if (check_crc) { ++ ++ if (buf[0] == 0xffff) { ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__, buf[0])); ++ err = 1; ++ goto error; ++ } ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(buf, nwords * 2); ++ if (hndcrc8((uint8 *)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) { ++ /* DBG only pci always read srom4 first, then srom8/9 */ ++ /* BS_ERROR(("%s: bad crc\n", __FUNCTION__)); */ ++ err = 1; ++ } ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf, nwords * 2); ++ } ++ ++error: ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ ++ /* Restore config after reading SROM */ ++ si_chipcontrl_restore(sih, ccval); ++ } ++ ++ return err; ++} ++ ++#if defined(BCMNVRAMW) || defined(BCMNVRAMR) ++static int ++otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz) ++{ ++ uint8 *otp; ++ uint sz = OTP_SZ_MAX/2; /* size in words */ ++ int err = 0; ++ ++ ASSERT(bufsz <= OTP_SZ_MAX); ++ ++ if ((otp = MALLOC(osh, OTP_SZ_MAX)) == NULL) { ++ return BCME_ERROR; ++ } ++ ++ bzero(otp, OTP_SZ_MAX); ++ ++ err = otp_read_region(sih, OTP_HW_RGN, (uint16 *)otp, &sz); ++ ++ if (err) { ++ MFREE(osh, otp, OTP_SZ_MAX); ++ return err; ++ } ++ ++ bcopy(otp, buf, bufsz); ++ ++ MFREE(osh, otp, OTP_SZ_MAX); ++ ++ /* Check CRC */ ++ if (buf[0] == 0xffff) { ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__, buf[0])); ++ return 1; ++ } ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(buf, bufsz); ++ if (hndcrc8((uint8 *)buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE && ++ hndcrc8((uint8 *)buf, SROM10_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) { ++ BS_ERROR(("%s: bad crc\n", __FUNCTION__)); ++ err = 1; ++ } ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf, bufsz); ++ ++ return err; ++} ++#endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */ ++ ++#if defined(WLTEST) || defined(BCMDBG) ++int ++srom_otp_write_region_crc(si_t *sih, uint nbytes, uint16* buf16, bool write) ++{ ++ int err = 0, crc = 0; ++ uint8 *buf8; ++ ++ /* Check nbytes is not odd or too big */ ++ if ((nbytes & 1) || (nbytes > SROM_MAX)) ++ return 1; ++ ++ /* block invalid buffer size */ ++ if (nbytes < SROM4_WORDS * 2) ++ return BCME_BUFTOOSHORT; ++ else if (nbytes > SROM10_WORDS * 2) ++ return BCME_BUFTOOLONG; ++ ++ /* Verify signatures */ ++ if (!((buf16[SROM4_SIGN] == SROM4_SIGNATURE) || ++ (buf16[SROM8_SIGN] == SROM4_SIGNATURE) || ++ (buf16[SROM10_SIGN] == SROM4_SIGNATURE))) { ++ BS_ERROR(("%s: wrong signature SROM4_SIGN %x SROM8_SIGN %x SROM10_SIGN %x\n", ++ __FUNCTION__, buf16[SROM4_SIGN], buf16[SROM8_SIGN], buf16[SROM10_SIGN])); ++ return BCME_ERROR; ++ } ++ ++ /* Check CRC */ ++ if (buf16[0] == 0xffff) { ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ BS_ERROR(("%s: invalid buf16[0] = 0x%x\n", __FUNCTION__, buf16[0])); ++ goto out; ++ } ++ ++ buf8 = (uint8*)buf16; ++ /* fixup the endianness and then calculate crc */ ++ htol16_buf(buf8, nbytes); ++ crc = ~hndcrc8(buf8, nbytes - 1, CRC8_INIT_VALUE); ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf8, nbytes); ++ if (nbytes == SROM10_WORDS * 2) ++ buf16[SROM10_CRCREV] = (crc << 8) | (buf16[SROM10_CRCREV] & 0xff); ++ else ++ buf16[SROM4_CRCREV] = (crc << 8) | (buf16[SROM4_CRCREV] & 0xff); ++ ++#ifdef BCMNVRAMW ++ /* Write the CRC back */ ++ if (write) ++ err = otp_write_region(sih, OTP_HW_RGN, buf16, nbytes/2); ++#endif /* BCMNVRAMW */ ++ ++out: ++ return write ? err : crc; ++} ++#endif ++ ++/* ++* Create variable table from memory. ++* Return 0 on success, nonzero on error. ++*/ ++static int ++BCMATTACHFN(initvars_table)(osl_t *osh, char *start, char *end, char **vars, uint *count) ++{ ++ int c = (int)(end - start); ++ ++ /* do it only when there is more than just the null string */ ++ if (c > 1) { ++ char *vp = MALLOC(osh, c); ++ ASSERT(vp != NULL); ++ if (!vp) ++ return BCME_NOMEM; ++ bcopy(start, vp, c); ++ *vars = vp; ++ *count = c; ++ } ++ else { ++ *vars = NULL; ++ *count = 0; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Find variables with from flash. 'base' points to the beginning ++ * of the table upon enter and to the end of the table upon exit when success. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_flash)(si_t *sih, osl_t *osh, char **base, uint len) ++{ ++ char *vp = *base; ++ char *flash; ++ int err; ++ char *s; ++ uint l, dl, copy_len; ++ char devpath[SI_DEVPATH_BUFSZ]; ++ char coded_name[SI_DEVPATH_BUFSZ] = {0}; ++ int path_len, coded_len, devid_len; ++ ++ /* allocate memory and read in flash */ ++ if (!(flash = MALLOC(osh, NVRAM_SPACE))) ++ return BCME_NOMEM; ++ if ((err = nvram_getall(flash, NVRAM_SPACE))) ++ goto exit; ++ ++ /* create legacy devpath prefix */ ++ si_devpath(sih, devpath, sizeof(devpath)); ++ path_len = strlen(devpath); ++ ++ /* create coded devpath prefix */ ++ si_coded_devpathvar(sih, coded_name, sizeof(coded_name), "devid"); ++ ++ /* coded_name now is 'xx:devid, eat ending 'devid' */ ++ /* to be 'xx:' */ ++ devid_len = strlen("devid"); ++ coded_len = strlen(coded_name); ++ if (coded_len > devid_len) { ++ coded_name[coded_len - devid_len] = '\0'; ++ coded_len -= devid_len; ++ } ++ else ++ coded_len = 0; ++ ++ /* grab vars with the prefix or previx in name */ ++ for (s = flash; s && *s; s += l + 1) { ++ l = strlen(s); ++ ++ /* skip non-matching variable */ ++ if (strncmp(s, devpath, path_len) == 0) ++ dl = path_len; ++ else if (coded_len && strncmp(s, coded_name, coded_len) == 0) ++ dl = coded_len; ++ else ++ continue; ++ ++ /* is there enough room to copy? */ ++ copy_len = l - dl + 1; ++ if (len < copy_len) { ++ err = BCME_BUFTOOSHORT; ++ goto exit; ++ } ++ ++ /* no prefix, just the name=value */ ++ strncpy(vp, &s[dl], copy_len); ++ vp += copy_len; ++ len -= copy_len; ++ } ++ ++ /* add null string as terminator */ ++ if (len < 1) { ++ err = BCME_BUFTOOSHORT; ++ goto exit; ++ } ++ *vp++ = '\0'; ++ ++ *base = vp; ++ ++exit: MFREE(osh, flash, NVRAM_SPACE); ++ return err; ++} ++ ++#if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED) ++/* ++ * Initialize nonvolatile variable table from flash. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_flash_si)(si_t *sih, char **vars, uint *count) ++{ ++ osl_t *osh = si_osh(sih); ++ char *vp, *base; ++ int err; ++ ++ ASSERT(vars != NULL); ++ ASSERT(count != NULL); ++ ++ base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS); ++ ASSERT(vp != NULL); ++ if (!vp) ++ return BCME_NOMEM; ++ ++ if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS)) == 0) ++ err = initvars_table(osh, base, vp, vars, count); ++ ++ MFREE(osh, base, MAXSZ_NVRAM_VARS); ++ ++ return err; ++} ++#endif ++ ++/* Parse SROM and create name=value pairs. 'srom' points to ++ * the SROM word array. 'off' specifies the offset of the ++ * first word 'srom' points to, which should be either 0 or ++ * SROM3_SWRG_OFF (full SROM or software region). ++ */ ++ ++static uint ++mask_shift(uint16 mask) ++{ ++ uint i; ++ for (i = 0; i < (sizeof(mask) << 3); i ++) { ++ if (mask & (1 << i)) ++ return i; ++ } ++ ASSERT(mask); ++ return 0; ++} ++ ++static uint ++mask_width(uint16 mask) ++{ ++ int i; ++ for (i = (sizeof(mask) << 3) - 1; i >= 0; i --) { ++ if (mask & (1 << i)) ++ return (uint)(i - mask_shift(mask) + 1); ++ } ++ ASSERT(mask); ++ return 0; ++} ++ ++#ifdef BCMASSERT_SUPPORT ++static bool ++mask_valid(uint16 mask) ++{ ++ uint shift = mask_shift(mask); ++ uint width = mask_width(mask); ++ return mask == ((~0 << shift) & ~(~0 << (shift + width))); ++} ++#endif ++ ++static void ++BCMATTACHFN(_initvars_srom_pci)(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b) ++{ ++ uint16 w; ++ uint32 val; ++ const sromvar_t *srv; ++ uint width; ++ uint flags; ++ uint32 sr = (1 << sromrev); ++ bool in_array = FALSE; ++ static char array_temp[256]; ++ uint array_curr = 0; ++ const char* array_name = NULL; ++ ++ varbuf_append(b, "sromrev=%d", sromrev); ++ ++ for (srv = pci_sromvars; srv->name != NULL; srv ++) { ++ const char *name; ++ static bool in_array = FALSE; ++ static char array_temp[256]; ++ static uint array_curr = 0; ++ static const char* array_name = NULL; ++ ++ if ((srv->revmask & sr) == 0) ++ continue; ++ ++ if (srv->off < off) ++ continue; ++ ++ flags = srv->flags; ++ name = srv->name; ++ ++ /* This entry is for mfgc only. Don't generate param for it, */ ++ if (flags & SRFL_NOVAR) ++ continue; ++ ++ if (flags & SRFL_ETHADDR) { ++ char eabuf[ETHER_ADDR_STR_LEN]; ++ struct ether_addr ea; ++ ++ ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff; ++ ea.octet[1] = srom[srv->off - off] & 0xff; ++ ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff; ++ ea.octet[3] = srom[srv->off + 1 - off] & 0xff; ++ ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff; ++ ea.octet[5] = srom[srv->off + 2 - off] & 0xff; ++ bcm_ether_ntoa(&ea, eabuf); ++ ++ varbuf_append(b, "%s=%s", name, eabuf); ++ } ++ else { ++ ASSERT(mask_valid(srv->mask)); ++ ASSERT(mask_width(srv->mask)); ++ ++ /* Start of an array */ ++ if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array) { ++ array_curr = 0; ++ array_name = (const char*)srv->name; ++ memset((void*)array_temp, 0, sizeof(array_temp)); ++ in_array = TRUE; ++ } ++ ++ w = srom[srv->off - off]; ++ val = (w & srv->mask) >> mask_shift(srv->mask); ++ width = mask_width(srv->mask); ++ ++ while (srv->flags & SRFL_MORE) { ++ srv ++; ++ ASSERT(srv->name != NULL); ++ ++ if (srv->off == 0 || srv->off < off) ++ continue; ++ ++ ASSERT(mask_valid(srv->mask)); ++ ASSERT(mask_width(srv->mask)); ++ ++ w = srom[srv->off - off]; ++ val += ((w & srv->mask) >> mask_shift(srv->mask)) << width; ++ width += mask_width(srv->mask); ++ } ++ ++ if ((flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1)) ++ continue; ++ ++ /* Array support starts in sromrev 10. Skip arrays for sromrev <= 9 */ ++ if (sromrev <= 9 && srv->flags & SRFL_ARRAY) { ++ while (srv->flags & SRFL_ARRAY) ++ srv ++; ++ srv ++; ++ } ++ ++ if (in_array) { ++ int ret; ++ ++ if (flags & SRFL_PRHEX) { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "0x%x,", val); ++ } else if ((flags & SRFL_PRSIGN) && ++ (val & (1 << (width - 1)))) { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "%d,", ++ (int)(val | (~0 << width))); ++ } else { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "%u,", val); ++ } ++ ++ if (ret > 0) { ++ array_curr += ret; ++ } else { ++ BS_ERROR(("%s: array %s parsing error. buffer too short.\n", ++ __FUNCTION__, array_name)); ++ ASSERT(0); ++ ++ /* buffer too small, skip this param */ ++ while (srv->flags & SRFL_ARRAY) ++ srv ++; ++ srv ++; ++ in_array = FALSE; ++ continue; ++ } ++ ++ if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */ ++ /* Remove the last ',' */ ++ array_temp[array_curr-1] = '\0'; ++ in_array = FALSE; ++ varbuf_append(b, "%s=%s", array_name, array_temp); ++ } ++ } else if (flags & SRFL_CCODE) { ++ if (val == 0) ++ varbuf_append(b, "ccode="); ++ else ++ varbuf_append(b, "ccode=%c%c", (val >> 8), (val & 0xff)); ++ } ++ /* LED Powersave duty cycle has to be scaled: ++ *(oncount >> 24) (offcount >> 8) ++ */ ++ else if (flags & SRFL_LEDDC) { ++ uint32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */ ++ (((val & 0xff)) << 8); /* offcount */ ++ varbuf_append(b, "leddc=%d", w32); ++ } ++ else if (flags & SRFL_PRHEX) ++ varbuf_append(b, "%s=0x%x", name, val); ++ else if ((flags & SRFL_PRSIGN) && (val & (1 << (width - 1)))) ++ varbuf_append(b, "%s=%d", name, (int)(val | (~0 << width))); ++ else ++ varbuf_append(b, "%s=%u", name, val); ++ } ++ } ++ ++ if (sromrev >= 4) { ++ /* Do per-path variables */ ++ uint p, pb, psz, path_num; ++ ++ if (sromrev >= 11) { ++ pb = SROM11_PATH0; ++ psz = SROM11_PATH1 - SROM11_PATH0; ++ path_num = MAX_PATH_SROM_11; ++ } else if (sromrev >= 8) { ++ pb = SROM8_PATH0; ++ psz = SROM8_PATH1 - SROM8_PATH0; ++ path_num = MAX_PATH_SROM; ++ } else { ++ pb = SROM4_PATH0; ++ psz = SROM4_PATH1 - SROM4_PATH0; ++ path_num = MAX_PATH_SROM; ++ } ++ ++ for (p = 0; p < path_num; p++) { ++ for (srv = perpath_pci_sromvars; srv->name != NULL; srv ++) { ++ if ((srv->revmask & sr) == 0) ++ continue; ++ ++ if (pb + srv->off < off) ++ continue; ++ ++ /* This entry is for mfgc only. Don't generate param for it, */ ++ if (srv->flags & SRFL_NOVAR) ++ continue; ++ ++ /* Start of an array */ ++ if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array) { ++ array_curr = 0; ++ array_name = (const char*)srv->name; ++ memset((void*)array_temp, 0, sizeof(array_temp)); ++ in_array = TRUE; ++ } ++ ++ w = srom[pb + srv->off - off]; ++ ++ ASSERT(mask_valid(srv->mask)); ++ val = (w & srv->mask) >> mask_shift(srv->mask); ++ width = mask_width(srv->mask); ++ ++ flags = srv->flags; ++ ++ /* Cheating: no per-path var is more than 1 word */ ++ ++ if ((srv->flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1)) ++ continue; ++ ++ if (in_array) { ++ int ret; ++ ++ if (flags & SRFL_PRHEX) { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "0x%x,", val); ++ } else if ((flags & SRFL_PRSIGN) && ++ (val & (1 << (width - 1)))) { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "%d,", ++ (int)(val | (~0 << width))); ++ } else { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "%u,", val); ++ } ++ ++ if (ret > 0) { ++ array_curr += ret; ++ } else { ++ BS_ERROR( ++ ("%s: array %s parsing error. buffer too short.\n", ++ __FUNCTION__, array_name)); ++ ASSERT(0); ++ ++ /* buffer too small, skip this param */ ++ while (srv->flags & SRFL_ARRAY) ++ srv ++; ++ srv ++; ++ in_array = FALSE; ++ continue; ++ } ++ ++ if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */ ++ /* Remove the last ',' */ ++ array_temp[array_curr-1] = '\0'; ++ in_array = FALSE; ++ varbuf_append(b, "%s%d=%s", ++ array_name, p, array_temp); ++ } ++ } else if (srv->flags & SRFL_PRHEX) ++ varbuf_append(b, "%s%d=0x%x", srv->name, p, val); ++ else ++ varbuf_append(b, "%s%d=%d", srv->name, p, val); ++ } ++ pb += psz; ++ } ++ } ++} ++ ++/* ++ * Initialize nonvolatile variable table from sprom. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_srom_pci)(si_t *sih, void *curmap, char **vars, uint *count) ++{ ++ uint16 *srom, *sromwindow; ++ uint8 sromrev = 0; ++ uint32 sr; ++ varbuf_t b; ++ char *vp, *base = NULL; ++ osl_t *osh = si_osh(sih); ++ bool flash = FALSE; ++ int err = 0; ++ ++ /* ++ * Apply CRC over SROM content regardless SROM is present or not, ++ * and use variable sromrev's existance in flash to decide ++ * if we should return an error when CRC fails or read SROM variables ++ * from flash. ++ */ ++ srom = MALLOC(osh, SROM_MAX); ++ ASSERT(srom != NULL); ++ if (!srom) ++ return -2; ++ ++ sromwindow = (uint16 *)SROM_OFFSET(sih); ++ if (si_is_sprom_available(sih)) { ++ err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM11_WORDS, TRUE); ++ ++ if (err == 0) { ++ if (srom[SROM11_SIGN] == SROM11_SIGNATURE) /* srom 11 */ ++ sromrev = srom[SROM11_CRCREV] & 0xff; ++ } else { ++ err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM4_WORDS, TRUE); ++ ++ if (err == 0) { ++ if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || /* srom 4 */ ++ (srom[SROM8_SIGN] == SROM4_SIGNATURE) ) { /* srom 8, 9 */ ++ sromrev = srom[SROM4_CRCREV] & 0xff; ++ } ++ } else { ++ err = sprom_read_pci(osh, sih, sromwindow, 0, ++ srom, SROM_WORDS, TRUE); ++ ++ if (err == 0) { ++ /* srom is good and is rev < 4 */ ++ /* top word of sprom contains version and crc8 */ ++ sromrev = srom[SROM_CRCREV] & 0xff; ++ /* bcm4401 sroms misprogrammed */ ++ if (sromrev == 0x10) ++ sromrev = 1; ++ } ++ } ++ } ++ } ++ ++#if defined(BCMNVRAMW) || defined(BCMNVRAMR) ++ /* Use OTP if SPROM not available */ ++ else if ((err = otp_read_pci(osh, sih, srom, SROM_MAX)) == 0) { ++ /* OTP only contain SROM rev8/rev9/rev10/Rev11 for now */ ++ if (srom[SROM11_SIGN] == SROM11_SIGNATURE) ++ sromrev = srom[SROM11_CRCREV] & 0xff; ++ else if (srom[SROM10_SIGN] == SROM10_SIGNATURE) ++ sromrev = srom[SROM10_CRCREV] & 0xff; ++ else ++ sromrev = srom[SROM4_CRCREV] & 0xff; ++ } ++#endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */ ++ else { ++ err = 1; ++ BS_ERROR(("Neither SPROM nor OTP has valid image\n")); ++ } ++ ++ BS_ERROR(("srom rev:%d\n", sromrev)); ++ ++ ++ /* We want internal/wltest driver to come up with default sromvars so we can ++ * program a blank SPROM/OTP. ++ */ ++ if (err) { ++ char *value; ++ uint32 val; ++ val = 0; ++ BCM_REFERENCE(val); ++ ++ if ((value = si_getdevpathvar(sih, "sromrev"))) { ++ sromrev = (uint8)bcm_strtoul(value, NULL, 0); ++ flash = TRUE; ++ goto varscont; ++ } ++ ++ BS_ERROR(("%s, SROM CRC Error\n", __FUNCTION__)); ++ ++#ifndef DONGLEBUILD ++ if ((value = si_getnvramflvar(sih, "sromrev"))) { ++ err = 0; ++ goto errout; ++ } ++#endif ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++ val = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32)); ++ if ((si_is_sprom_available(sih) && srom[0] == 0xffff) || ++ (val & SPROM_OTPIN_USE)) { ++ vp = base = mfgsromvars; ++ ++ if (defvarslen == 0) { ++ BS_ERROR(("No nvm file, use generic default (for programming" ++ " SPROM/OTP only)\n")); ++ ++ if (((sih->chip == BCM4331_CHIP_ID) || ++ (sih->chip == BCM43431_CHIP_ID)) && ++ (sih->chiprev < 3)) { ++ ++ defvarslen = srom_vars_len(defaultsromvars_4331); ++ bcopy(defaultsromvars_4331, vp, defvarslen); ++ ++ } else { ++ /* For 4311 A1 there is no signature to indicate that OTP is ++ * programmed, so can't really verify the OTP is ++ * unprogrammed or a bad OTP. ++ */ ++ if (sih->chip == BCM4311_CHIP_ID) { ++ const char *devid = "devid=0x4311"; ++ const size_t devid_strlen = strlen(devid); ++ BS_ERROR(("setting the devid to be 4311\n")); ++ bcopy(devid, vp, devid_strlen + 1); ++ vp += devid_strlen + 1; ++ } ++ defvarslen = srom_vars_len(defaultsromvars_wltest); ++ bcopy(defaultsromvars_wltest, vp, defvarslen); ++ } ++ } else { ++ BS_ERROR(("Use nvm file as default\n")); ++ } ++ ++ vp += defvarslen; ++ /* add final null terminator */ ++ *vp++ = '\0'; ++ ++ BS_ERROR(("Used %d bytes of defaultsromvars\n", defvarslen)); ++ goto varsdone; ++ ++ } else if ((((sih->chip == BCM4331_CHIP_ID) || ++ (sih->chip == BCM43431_CHIP_ID)) && ++ (sih->chiprev < 3)) || (sih->chip == BCM4360_CHIP_ID) || ++ (sih->chip == BCM43460_CHIP_ID) || ++ (sih->chip == BCM4352_CHIP_ID)) { ++ base = vp = mfgsromvars; ++ ++ if ((sih->chip == BCM4360_CHIP_ID) || ++ (sih->chip == BCM43460_CHIP_ID) || ++ (sih->chip == BCM4352_CHIP_ID)) ++ BS_ERROR(("4360 BOOT w/o SPROM or OTP\n")); ++ else ++ BS_ERROR(("4331 BOOT w/o SPROM or OTP\n")); ++ ++ defvarslen = srom_vars_len(defaultsromvars_4331); ++ bcopy(defaultsromvars_4331, vp, defvarslen); ++ vp += defvarslen; ++ *vp++ = '\0'; ++ goto varsdone; ++ } else ++#endif ++ { ++ err = -1; ++ goto errout; ++ } ++ } ++ ++varscont: ++ /* Bitmask for the sromrev */ ++ sr = 1 << sromrev; ++ ++ /* srom version check: Current valid versions: 1-5, 8-11, SROM_MAXREV */ ++ if ((sr & 0xf3e) == 0) { ++ BS_ERROR(("Invalid SROM rev %d\n", sromrev)); ++ err = -2; ++ goto errout; ++ } ++ ++ ASSERT(vars != NULL); ++ ASSERT(count != NULL); ++ ++ base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS); ++ ASSERT(vp != NULL); ++ if (!vp) { ++ err = -2; ++ goto errout; ++ } ++ ++ /* read variables from flash */ ++ if (flash) { ++ if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS))) ++ goto errout; ++ goto varsdone; ++ } ++ ++ varbuf_init(&b, base, MAXSZ_NVRAM_VARS); ++ ++ /* parse SROM into name=value pairs. */ ++ _initvars_srom_pci(sromrev, srom, 0, &b); ++ ++ ++ /* final nullbyte terminator */ ++ ASSERT(b.size >= 1); ++ vp = b.buf; ++ *vp++ = '\0'; ++ ++ ASSERT((vp - base) <= MAXSZ_NVRAM_VARS); ++ ++varsdone: ++ err = initvars_table(osh, base, vp, vars, count); ++ ++errout: ++/* BCMHOSTVARS are enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++ if (base && (base != mfgsromvars)) ++#else ++ if (base) ++#endif ++ MFREE(osh, base, MAXSZ_NVRAM_VARS); ++ ++ MFREE(osh, srom, SROM_MAX); ++ return err; ++} ++ ++/* ++ * Read the cis and call parsecis to initialize the vars. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_cis_pcmcia)(si_t *sih, osl_t *osh, char **vars, uint *count) ++{ ++ uint8 *cis = NULL; ++ int rc; ++ uint data_sz; ++ ++ data_sz = (sih->buscorerev == 1) ? SROM_MAX : CIS_SIZE; ++ ++ if ((cis = MALLOC(osh, data_sz)) == NULL) ++ return (-2); ++ ++ if (sih->buscorerev == 1) { ++ if (srom_read(sih, PCMCIA_BUS, (void *)NULL, osh, 0, data_sz, (uint16 *)cis, ++ TRUE)) { ++ MFREE(osh, cis, data_sz); ++ return (-1); ++ } ++ /* fix up endianess for 16-bit data vs 8-bit parsing */ ++ htol16_buf((uint16 *)cis, data_sz); ++ } else ++ OSL_PCMCIA_READ_ATTR(osh, 0, cis, data_sz); ++ ++ rc = srom_parsecis(osh, &cis, SROM_CIS_SINGLE, vars, count); ++ ++ MFREE(osh, cis, data_sz); ++ ++ return (rc); ++} ++ ++ ++#ifdef BCMSPI ++/* ++ * Read the SPI cis and call parsecis to initialize the vars. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_cis_spi)(osl_t *osh, char **vars, uint *count) ++{ ++ uint8 *cis; ++ int rc; ++ ++#if defined(NDIS) && !defined(UNDER_CE) ++ uint8 cisd[SBSDIO_CIS_SIZE_LIMIT]; ++ cis = (uint8*)cisd; ++#else ++ if ((cis = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT)) == NULL) { ++ return -1; ++ } ++#endif /* defined(NDIS) && (!defined(UNDER_CE)) */ ++ ++ bzero(cis, SBSDIO_CIS_SIZE_LIMIT); ++ ++ if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, cis, SBSDIO_CIS_SIZE_LIMIT) != 0) { ++#if defined(NDIS) && !defined(UNDER_CE) ++ /* nothing to do */ ++#else ++ MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT); ++#endif /* defined(NDIS) && (!defined(UNDER_CE)) */ ++ return -2; ++ } ++ ++ rc = srom_parsecis(osh, &cis, SDIO_FUNC_1, vars, count); ++ ++#if defined(NDIS) && !defined(UNDER_CE) ++ /* nothing to do here */ ++#else ++ MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT); ++#endif ++ ++ return (rc); ++} ++#endif /* BCMSPI */ ++ ++#if defined(BCMUSBDEV) ++/* Return sprom size in 16-bit words */ ++uint ++srom_size(si_t *sih, osl_t *osh) ++{ ++ uint size = 0; ++ if (SPROMBUS == PCMCIA_BUS) { ++ uint32 origidx; ++ sdpcmd_regs_t *pcmregs; ++ bool wasup; ++ ++ origidx = si_coreidx(sih); ++ pcmregs = si_setcore(sih, PCMCIA_CORE_ID, 0); ++ if (!pcmregs) ++ pcmregs = si_setcore(sih, SDIOD_CORE_ID, 0); ++ ASSERT(pcmregs); ++ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ /* not worry about earlier core revs */ ++ /* valid for only pcmcia core */ ++ if (si_coreid(sih) == PCMCIA_CORE_ID) ++ if (si_corerev(sih) < 8) ++ goto done; ++ ++ ++ switch (SI_PCMCIA_READ(osh, pcmregs, SROM_INFO) & SRI_SZ_MASK) { ++ case 1: ++ size = 256; /* SROM_INFO == 1 means 4kbit */ ++ break; ++ case 2: ++ size = 1024; /* SROM_INFO == 2 means 16kbit */ ++ break; ++ default: ++ break; ++ } ++ ++ done: ++ if (!wasup) ++ si_core_disable(sih, 0); ++ ++ si_setcoreidx(sih, origidx); ++ } ++ return size; ++} ++#endif ++ ++/* ++ * initvars are different for BCMUSBDEV and BCMSDIODEV. This is OK when supporting both at ++ * the same time, but only because all of the code is in attach functions and not in ROM. ++ */ ++ ++#if defined(BCMUSBDEV_ENABLED) ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++/* ++ * Read the USB cis and call parsecis to initialize the vars. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_cis_usbdriver)(si_t *sih, osl_t *osh, char **vars, uint *count) ++{ ++ uint8 *cis; ++ uint sz = OTP_SZ_MAX/2; /* size in words */ ++ int rc = BCME_OK; ++ ++ if ((cis = MALLOC(osh, OTP_SZ_MAX)) == NULL) { ++ return -1; ++ } ++ ++ bzero(cis, OTP_SZ_MAX); ++ ++ if (otp_read_region(sih, OTP_SW_RGN, (uint16 *)cis, &sz)) { ++ BS_ERROR(("%s: OTP read SW region failure.\n*", __FUNCTION__)); ++ rc = -2; ++ } else { ++ BS_ERROR(("%s: OTP programmed. use OTP for srom vars\n*", __FUNCTION__)); ++ rc = srom_parsecis(osh, &cis, SROM_CIS_SINGLE, vars, count); ++ } ++ ++ MFREE(osh, cis, OTP_SZ_MAX); ++ ++ return (rc); ++} ++ ++/* For driver(not bootloader), if nvram is not downloadable or missing, use default */ ++static int ++BCMATTACHFN(initvars_srom_si_usbdriver)(si_t *sih, osl_t *osh, char **vars, uint *varsz) ++{ ++ uint len; ++ char *base; ++ char *fakevars; ++ int rc = -1; ++ ++ base = fakevars = NULL; ++ len = 0; ++ switch (CHIPID(sih->chip)) { ++ case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: ++ fakevars = defaultsromvars_4322usb; ++ break; ++ case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID: ++ case BCM43234_CHIP_ID: ++ /* check against real chipid instead of compile time flag */ ++ if (sih->chip == BCM43234_CHIP_ID) { ++ fakevars = defaultsromvars_43234usb; ++ } else if (sih->chip == BCM43235_CHIP_ID) { ++ fakevars = defaultsromvars_43235usb; ++ } else ++ fakevars = defaultsromvars_43236usb; ++ break; ++ ++ case BCM4319_CHIP_ID: ++ fakevars = defaultsromvars_4319usb; ++ break; ++ case BCM4360_CHIP_ID: ++ case BCM43460_CHIP_ID: ++ case BCM43526_CHIP_ID: ++ fakevars = defaultsromvars_4360usb; ++ break; ++ default: ++ ASSERT(0); ++ return rc; ++ } ++ ++#ifndef BCM_BMAC_VARS_APPEND ++ if (BCME_OK == initvars_cis_usbdriver(sih, osh, vars, varsz)) { ++ /* Make OTP/SROM variables global */ ++ if (srvars_inited == FALSE) ++ nvram_append((void *)sih, *vars, *varsz); ++ return BCME_OK; ++ } ++#endif /* BCM_BMAC_VARS_APPEND */ ++ ++ /* NO OTP, if nvram downloaded, use it */ ++ if ((_varsz != 0) && (_vars != NULL)) { ++ len = _varsz + (strlen(vstr_end)); ++ base = MALLOC(osh, len + 2); /* plus 2 terminating \0 */ ++ if (base == NULL) { ++ BS_ERROR(("initvars_srom_si: MALLOC failed.\n")); ++ return BCME_ERROR; ++ } ++ bzero(base, len + 2); ++ ++ /* make a copy of the _vars, _vars is at the top of the memory, cannot append ++ * END\0\0 to it. copy the download vars to base, back of the terminating \0, ++ * then append END\0\0 ++ */ ++ bcopy((void *)_vars, base, _varsz); ++ /* backoff all the terminating \0s except the one the for the last string */ ++ len = _varsz; ++ while (!base[len - 1]) ++ len--; ++ len++; /* \0 for the last string */ ++ /* append END\0\0 to the end */ ++ bcopy((void *)vstr_end, (base + len), strlen(vstr_end)); ++ len += (strlen(vstr_end) + 2); ++ *vars = base; ++ *varsz = len; ++ ++ BS_ERROR(("%s USB nvram downloaded %d bytes\n", __FUNCTION__, _varsz)); ++ } else { ++ /* Fall back to fake srom vars if OTP not programmed */ ++ len = srom_vars_len(fakevars); ++ base = MALLOC(osh, (len + 1)); ++ if (base == NULL) { ++ BS_ERROR(("initvars_srom_si: MALLOC failed.\n")); ++ return BCME_ERROR; ++ } ++ bzero(base, (len + 1)); ++ bcopy(fakevars, base, len); ++ *(base + len) = '\0'; /* add final nullbyte terminator */ ++ *vars = base; ++ *varsz = len + 1; ++ BS_ERROR(("initvars_srom_usbdriver: faked nvram %d bytes\n", len)); ++ } ++ ++#ifdef BCM_BMAC_VARS_APPEND ++ if (BCME_OK == initvars_cis_usbdriver(sih, osh, vars, varsz)) { ++ if (base) ++ MFREE(osh, base, (len + 1)); ++ } ++#endif /* BCM_BMAC_VARS_APPEND */ ++ /* Make OTP/SROM variables global */ ++ if (srvars_inited == FALSE) { ++ nvram_append((void *)sih, *vars, *varsz); ++ srvars_inited = TRUE; ++ } ++ return BCME_OK; ++ ++} ++#endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */ ++ ++#ifdef BCM_DONGLEVARS ++static int ++BCMATTACHFN(initvars_srom_si_bl)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ int sel = 0; /* where to read srom/cis: 0 - none, 1 - otp, 2 - sprom */ ++ uint sz = 0; /* srom size in bytes */ ++ void *oh = NULL; ++ int rc = BCME_OK; ++ ++ if ((oh = otp_init(sih)) != NULL && (otp_status(oh) & OTPS_GUP_SW)) { ++ /* Access OTP if it is present, powered on, and programmed */ ++ sz = otp_size(oh); ++ sel = 1; ++ } else if ((sz = srom_size(sih, osh)) != 0) { ++ /* Access the SPROM if it is present */ ++ sz <<= 1; ++ sel = 2; ++ } ++ ++ /* Read CIS in OTP/SPROM */ ++ if (sel != 0) { ++ uint16 *srom; ++ uint8 *body = NULL; ++ uint otpsz = sz; ++ ++ ASSERT(sz); ++ ++ /* Allocate memory */ ++ if ((srom = (uint16 *)MALLOC(osh, sz)) == NULL) ++ return BCME_NOMEM; ++ ++ /* Read CIS */ ++ switch (sel) { ++ case 1: ++ rc = otp_read_region(sih, OTP_SW_RGN, srom, &otpsz); ++ sz = otpsz; ++ body = (uint8 *)srom; ++ break; ++ case 2: ++ rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, srom, TRUE); ++ /* sprom has 8 byte h/w header */ ++ body = (uint8 *)srom + SBSDIO_SPROM_CIS_OFFSET; ++ break; ++ default: ++ /* impossible to come here */ ++ ASSERT(0); ++ break; ++ } ++ ++ /* Parse CIS */ ++ if (rc == BCME_OK) { ++ /* each word is in host endian */ ++ htol16_buf((uint8 *)srom, sz); ++ ASSERT(body); ++ rc = srom_parsecis(osh, &body, SROM_CIS_SINGLE, vars, varsz); ++ } ++ ++ MFREE(osh, srom, sz); /* Clean up */ ++ ++ /* Make SROM variables global */ ++ if (rc == BCME_OK) ++ nvram_append((void *)sih, *vars, *varsz); ++ } ++ ++ return BCME_OK; ++} ++#endif /* #ifdef BCM_DONGLEVARS */ ++ ++static int ++BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ ++ /* Bail out if we've dealt with OTP/SPROM before! */ ++ if (srvars_inited) ++ goto exit; ++ ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++ /* read OTP or use faked var array */ ++ switch (CHIPID(sih->chip)) { ++ case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: ++ case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID: ++ case BCM43234_CHIP_ID: ++ case BCM4319_CHIP_ID: ++ case BCM4360_CHIP_ID: ++ case BCM43460_CHIP_ID: ++ case BCM4352_CHIP_ID: ++ if (BCME_OK != initvars_srom_si_usbdriver(sih, osh, vars, varsz)) ++ goto exit; ++ return BCME_OK; ++ default: ++ UNUSED_PARAMETER(defaultsromvars_4322usb); ++ UNUSED_PARAMETER(defaultsromvars_43234usb); ++ UNUSED_PARAMETER(defaultsromvars_43235usb); ++ UNUSED_PARAMETER(defaultsromvars_43236usb); ++ UNUSED_PARAMETER(defaultsromvars_4319usb); ++ } ++#endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */ ++ ++#ifdef BCM_DONGLEVARS /* this flag should be defined for usb bootloader, to read OTP \ ++ or SROM */ ++ if (BCME_OK != initvars_srom_si_bl(sih, osh, curmap, vars, varsz)) ++ return BCME_ERROR; ++#endif ++ ++ /* update static local var to skip for next call */ ++ srvars_inited = TRUE; ++ ++exit: ++ /* Tell the caller there is no individual SROM variables */ ++ *vars = NULL; ++ *varsz = 0; ++ ++ /* return OK so the driver will load & use defaults if bad srom/otp */ ++ return BCME_OK; ++} ++ ++#elif defined(BCMSDIODEV_ENABLED) ++ ++#ifdef BCM_DONGLEVARS ++static uint8 BCMATTACHDATA(defcis4325)[] = { 0x20, 0x4, 0xd0, 0x2, 0x25, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4315)[] = { 0x20, 0x4, 0xd0, 0x2, 0x15, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4329)[] = { 0x20, 0x4, 0xd0, 0x2, 0x29, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4319)[] = { 0x20, 0x4, 0xd0, 0x2, 0x19, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4336)[] = { 0x20, 0x4, 0xd0, 0x2, 0x36, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4330)[] = { 0x20, 0x4, 0xd0, 0x2, 0x30, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis43237)[] = { 0x20, 0x4, 0xd0, 0x2, 0xe5, 0xa8, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4324)[] = { 0x20, 0x4, 0xd0, 0x2, 0x24, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4335)[] = { 0x20, 0x4, 0xd0, 0x2, 0x24, 0x43, 0xff, 0xff }; ++ ++#ifdef BCM_BMAC_VARS_APPEND ++ ++static char BCMATTACHDATA(defaultsromvars_4319sdio)[] = ++ "sromrev=3\0" ++ "vendid=0x14e4\0" ++ "devid=0x4338\0" ++ "boardtype=0x05a1\0" ++ "boardrev=0x1102\0" ++ "boardflags=0x400201\0" ++ "boardflags2=0x80\0" ++ "xtalfreq=26000\0" ++ "aa2g=3\0" ++ "aa5g=0\0" ++ "ag0=0\0" ++ "opo=0\0" ++ "pa0b0=0x1675\0" ++ "pa0b1=0xfa74\0" ++ "pa0b2=0xfea1\0" ++ "pa0itssit=62\0" ++ "pa0maxpwr=78\0" ++ "rssismf2g=0xa\0" ++ "rssismc2g=0xb\0" ++ "rssisav2g=0x3\0" ++ "bxa2g=0\0" ++ "cckdigfilttype=6\0" ++ "rxpo2g=2\0" ++ "cckpo=0\0" ++ "ofdmpo=0x55553333\0" ++ "mcs2gpo0=0x9999\0" ++ "mcs2gpo1=0x9999\0" ++ "mcs2gpo2=0x0000\0" ++ "mcs2gpo3=0x0000\0" ++ "mcs2gpo4=0x9999\0" ++ "mcs2gpo5=0x9999\0" ++ "macaddr=00:90:4c:06:c0:19\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_4319sdio_hmb)[] = ++ "sromrev=3\0" ++ "vendid=0x14e4\0" ++ "devid=0x4338\0" ++ "boardtype=0x058c\0" ++ "boardrev=0x1102\0" ++ "boardflags=0x400201\0" ++ "boardflags2=0x80\0" ++ "xtalfreq=26000\0" ++ "aa2g=3\0" ++ "aa5g=0\0" ++ "ag0=0\0" ++ "opo=0\0" ++ "pa0b0=0x1675\0" ++ "pa0b1=0xfa74\0" ++ "pa0b2=0xfea1\0" ++ "pa0itssit=62\0" ++ "pa0maxpwr=78\0" ++ "rssismf2g=0xa \0" ++ "rssismc2g=0xb \0" ++ "rssisav2g=0x3 \0" ++ "bxa2g=0\0" ++ "cckdigfilttype=6\0" ++ "rxpo2g=2\0" ++ "cckpo=0\0" ++ "ofdmpo=0x55553333\0" ++ "mcs2gpo0=0x9999\0" ++ "mcs2gpo1=0x9999\0" ++ "mcs2gpo2=0x0000\0" ++ "mcs2gpo3=0x0000\0" ++ "mcs2gpo4=0x9999\0" ++ "mcs2gpo5=0x9999\0" ++ "macaddr=00:90:4c:06:c0:19\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_4319sdio_usbsd)[] = ++ "sromrev=3\0" ++ "vendid=0x14e4\0" ++ "devid=0x4338\0" ++ "boardtype=0x05a2\0" ++ "boardrev=0x1100\0" ++ "boardflags=0x400201\0" ++ "boardflags2=0x80\0" ++ "xtalfreq=30000\0" ++ "aa2g=3\0" ++ "aa5g=0\0" ++ "ag0=0\0" ++ "opo=0\0" ++ "pa0b0=0x1675\0" ++ "pa0b1=0xfa74\0" ++ "pa0b2=0xfea1\0" ++ "pa0itssit=62\0" ++ "pa0maxpwr=78\0" ++ "rssismf2g=0xa \0" ++ "rssismc2g=0xb \0" ++ "rssisav2g=0x3 \0" ++ "bxa2g=0\0" ++ "cckdigfilttype=6\0" ++ "rxpo2g=2\0" ++ "cckpo=0\0" ++ "ofdmpo=0x55553333\0" ++ "mcs2gpo0=0x9999\0" ++ "mcs2gpo1=0x9999\0" ++ "mcs2gpo2=0x0000\0" ++ "mcs2gpo3=0x0000\0" ++ "mcs2gpo4=0x9999\0" ++ "mcs2gpo5=0x9999\0" ++ "macaddr=00:90:4c:08:90:00\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_43237)[] = ++ "vendid=0x14e4\0" ++ "devid=0x4355\0" ++ "boardtype=0x0583\0" ++ "boardrev=0x1103\0" ++ "boardnum=0x1\0" ++ "boardflags=0x200\0" ++ "boardflags2=0\0" ++ "sromrev=8\0" ++ "macaddr=00:90:4c:51:a8:e4\0" ++ "ccode=0\0" ++ "regrev=0\0" ++ "ledbh0=0xff\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0xffff\0" ++ "opo=0x0\0" ++ "aa2g=0x3\0" ++ "aa5g=0x3\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0xff\0" ++ "ag3=0xff\0" ++ "pa0b0=0xfed1\0" ++ "pa0b1=0x15fd\0" ++ "pa0b2=0xfac2\0" ++ "pa0itssit=0x20\0" ++ "pa0maxpwr=0x4c\0" ++ "pa1b0=0xfecd\0" ++ "pa1b1=0x1497\0" ++ "pa1b2=0xfae3\0" ++ "pa1lob0=0xfe87\0" ++ "pa1lob1=0x1637\0" ++ "pa1lob2=0xfa8e\0" ++ "pa1hib0=0xfedc\0" ++ "pa1hib1=0x144b\0" ++ "pa1hib2=0xfb01\0" ++ "pa1itssit=0x3e\0" ++ "pa1maxpwr=0x40\0" ++ "pa1lomaxpwr=0x3a\0" ++ "pa1himaxpwr=0x3c\0" ++ "bxa2g=0x3\0" ++ "rssisav2g=0x7\0" ++ "rssismc2g=0xf\0" ++ "rssismf2g=0xf\0" ++ "bxa5g=0x3\0" ++ "rssisav5g=0x7\0" ++ "rssismc5g=0xf\0" ++ "rssismf5g=0xf\0" ++ "tri2g=0xff\0" ++ "tri5g=0xff\0" ++ "tri5gl=0xff\0" ++ "tri5gh=0xff\0" ++ "rxpo2g=0xff\0" ++ "rxpo5g=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0x0\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x2\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "tssipos5g=0x1\0" ++ "extpagain5g=0x2\0" ++ "pdetrange5g=0x2\0" ++ "triso5g=0x3\0" ++ "cck2gpo=0x0\0" ++ "ofdm2gpo=0x0\0" ++ "ofdm5gpo=0x0\0" ++ "ofdm5glpo=0x0\0" ++ "ofdm5ghpo=0x0\0" ++ "mcs2gpo0=0x0\0" ++ "mcs2gpo1=0x0\0" ++ "mcs2gpo2=0x0\0" ++ "mcs2gpo3=0x0\0" ++ "mcs2gpo4=0x0\0" ++ "mcs2gpo5=0x0\0" ++ "mcs2gpo6=0x0\0" ++ "mcs2gpo7=0x0\0" ++ "mcs5gpo0=0x0\0" ++ "mcs5gpo1=0x0\0" ++ "mcs5gpo2=0x0\0" ++ "mcs5gpo3=0x0\0" ++ "mcs5gpo4=0x0\0" ++ "mcs5gpo5=0x0\0" ++ "mcs5gpo6=0x0\0" ++ "mcs5gpo7=0x0\0" ++ "mcs5glpo0=0x0\0" ++ "mcs5glpo1=0x0\0" ++ "mcs5glpo2=0x0\0" ++ "mcs5glpo3=0x0\0" ++ "mcs5glpo4=0x0\0" ++ "mcs5glpo5=0x0\0" ++ "mcs5glpo6=0x0\0" ++ "mcs5glpo7=0x0\0" ++ "mcs5ghpo0=0x0\0" ++ "mcs5ghpo1=0x0\0" ++ "mcs5ghpo2=0x0\0" ++ "mcs5ghpo3=0x0\0" ++ "mcs5ghpo4=0x0\0" ++ "mcs5ghpo5=0x0\0" ++ "mcs5ghpo6=0x0\0" ++ "mcs5ghpo7=0x0\0" ++ "cddpo=0x0\0" ++ "stbcpo=0x0\0" ++ "bw40po=0x0\0" ++ "bwduppo=0x0\0" ++ "maxp2ga0=0x4c\0" ++ "pa2gw0a0=0xfed1\0" ++ "pa2gw1a0=0x15fd\0" ++ "pa2gw2a0=0xfac2\0" ++ "maxp5ga0=0x3c\0" ++ "maxp5gha0=0x3c\0" ++ "maxp5gla0=0x3c\0" ++ "pa5gw0a0=0xfeb0\0" ++ "pa5gw1a0=0x1491\0" ++ "pa5gw2a0=0xfaf8\0" ++ "pa5glw0a0=0xfeaa\0" ++ "pa5glw1a0=0x14b9\0" ++ "pa5glw2a0=0xfaf0\0" ++ "pa5ghw0a0=0xfec5\0" ++ "pa5ghw1a0=0x1439\0" ++ "pa5ghw2a0=0xfb18\0" ++ "maxp2ga1=0x4c\0" ++ "itt2ga0=0x20\0" ++ "itt5ga0=0x3e\0" ++ "itt2ga1=0x20\0" ++ "itt5ga1=0x3e\0" ++ "pa2gw0a1=0xfed2\0" ++ "pa2gw1a1=0x15d9\0" ++ "pa2gw2a1=0xfac6\0" ++ "maxp5ga1=0x3a\0" ++ "maxp5gha1=0x3a\0" ++ "maxp5gla1=0x3a\0" ++ "pa5gw0a1=0xfebe\0" ++ "pa5gw1a1=0x1306\0" ++ "pa5gw2a1=0xfb63\0" ++ "pa5glw0a1=0xfece\0" ++ "pa5glw1a1=0x1361\0" ++ "pa5glw2a1=0xfb5f\0" ++ "pa5ghw0a1=0xfe9e\0" ++ "pa5ghw1a1=0x12ca\0" ++ "pa5ghw2a1=0xfb41\0" ++ "END\0"; ++ ++static int ++srom_load_nvram(si_t *sih, osl_t *osh, uint8 *pcis[], uint ciscnt, char **vars, uint *varsz) ++{ ++ uint len = 0, base_len; ++ char *base; ++ char *fakevars; ++ ++ base = fakevars = NULL; ++ switch (CHIPID(sih->chip)) { ++ case BCM4319_CHIP_ID: ++ printf("load driver default for chip %x\n", CHIPID(sih->chip)); ++ fakevars = defaultsromvars_4319sdio; ++ if (si_cis_source(sih) == CIS_OTP) { ++ switch (srom_probe_boardtype(pcis, ciscnt)) { ++ case BCM94319SDHMB_SSID: ++ fakevars = defaultsromvars_4319sdio_hmb; ++ break; ++ case BCM94319USBSDB_SSID: ++ fakevars = defaultsromvars_4319sdio_usbsd; ++ break; ++ default: ++ fakevars = defaultsromvars_4319sdio; ++ break; ++ } ++ } ++ break; ++ case BCM43237_CHIP_ID: ++ printf("load driver default for chip %x\n", CHIPID(sih->chip)); ++ fakevars = defaultsromvars_43237; ++ break; ++ default: ++ printf("unknown chip %x\n", CHIPID(sih->chip)); ++ return BCME_ERROR; /* fakevars == NULL for switch default */ ++ } ++ ++ ++ /* NO OTP, if nvram downloaded, use it */ ++ if ((_varsz != 0) && (_vars != NULL)) { ++ len = _varsz + (strlen(vstr_end)); ++ base_len = len + 2; /* plus 2 terminating \0 */ ++ base = MALLOC(osh, base_len); ++ if (base == NULL) { ++ BS_ERROR(("initvars_srom_si: MALLOC failed.\n")); ++ return BCME_ERROR; ++ } ++ bzero(base, base_len); ++ ++ /* make a copy of the _vars, _vars is at the top of the memory, cannot append ++ * END\0\0 to it. copy the download vars to base, back of the terminating \0, ++ * then append END\0\0 ++ */ ++ bcopy((void *)_vars, base, _varsz); ++ /* backoff all the terminating \0s except the one the for the last string */ ++ len = _varsz; ++ while (!base[len - 1]) ++ len--; ++ len++; /* \0 for the last string */ ++ /* append END\0\0 to the end */ ++ bcopy((void *)vstr_end, (base + len), strlen(vstr_end)); ++ len += (strlen(vstr_end) + 2); ++ *vars = base; ++ *varsz = len; ++ ++ BS_ERROR(("%s nvram downloaded %d bytes\n", __FUNCTION__, _varsz)); ++ } else { ++ /* Fall back to fake srom vars if OTP not programmed */ ++ len = srom_vars_len(fakevars); ++ base = MALLOC(osh, (len + 1)); ++ base_len = len + 1; ++ if (base == NULL) { ++ BS_ERROR(("initvars_srom_si: MALLOC failed.\n")); ++ return BCME_ERROR; ++ } ++ bzero(base, base_len); ++ bcopy(fakevars, base, len); ++ *(base + len) = '\0'; /* add final nullbyte terminator */ ++ *vars = base; ++ *varsz = len + 1; ++ BS_ERROR(("srom_load_driver)default: faked nvram %d bytes\n", len)); ++ } ++ /* Parse the CIS */ ++ if ((srom_parsecis(osh, pcis, ciscnt, vars, varsz)) == BCME_OK) ++ nvram_append((void *)sih, *vars, *varsz); ++ MFREE(osh, base, base_len); ++ return BCME_OK; ++} ++ ++#endif /* BCM_BMAC_VARS_APPEND */ ++ ++static int ++BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ int cis_src; ++ uint msz = 0; ++ uint sz = 0; ++ void *oh = NULL; ++ int rc = BCME_OK; ++ bool new_cisformat = FALSE; ++ ++ uint16 *cisbuf = NULL; ++ ++ /* # sdiod fns + common + extra */ ++ uint8 *cis[SBSDIO_NUM_FUNCTION + 2] = { 0 }; ++ ++ uint ciss = 0; ++ uint8 *defcis; ++ uint hdrsz; ++ ++ /* Bail out if we've dealt with OTP/SPROM before! */ ++ if (srvars_inited) ++ goto exit; ++ ++ /* Initialize default and cis format count */ ++ switch (CHIPID(sih->chip)) { ++ case BCM4325_CHIP_ID: ciss = 3; defcis = defcis4325; hdrsz = 8; break; ++ case BCM4315_CHIP_ID: ciss = 3; defcis = defcis4315; hdrsz = 8; break; ++ case BCM4329_CHIP_ID: ciss = 4; defcis = defcis4329; hdrsz = 12; break; ++ case BCM4319_CHIP_ID: ciss = 3; defcis = defcis4319; hdrsz = 12; break; ++ case BCM4336_CHIP_ID: ciss = 1; defcis = defcis4336; hdrsz = 4; break; ++ case BCM43362_CHIP_ID: ciss = 1; defcis = defcis4336; hdrsz = 4; break; ++ case BCM4330_CHIP_ID: ciss = 1; defcis = defcis4330; hdrsz = 4; break; ++ case BCM43237_CHIP_ID: ciss = 1; defcis = defcis43237; hdrsz = 4; break; ++ case BCM4324_CHIP_ID: ciss = 1; defcis = defcis4324; hdrsz = 4; break; ++ case BCM4314_CHIP_ID: ciss = 1; defcis = defcis4330; hdrsz = 4; break; ++ case BCM4334_CHIP_ID: ciss = 1; defcis = defcis4330; hdrsz = 4; break; ++ case BCM4335_CHIP_ID: ciss = 1; defcis = defcis4335; hdrsz = 4; break; ++ default: ++ BS_ERROR(("%s: Unknown chip 0x%04x\n", __FUNCTION__, sih->chip)); ++ return BCME_ERROR; ++ } ++ if (sih->ccrev >= 36) { ++ uint32 otplayout; ++ otplayout = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, otplayout), 0, 0); ++ if (otplayout & OTP_CISFORMAT_NEW) { ++ ciss = 1; ++ hdrsz = 2; ++ new_cisformat = TRUE; ++ } ++ else { ++ ciss = 3; ++ hdrsz = 12; ++ } ++ } ++ ++ cis_src = si_cis_source(sih); ++ switch (cis_src) { ++ case CIS_SROM: ++ sz = srom_size(sih, osh) << 1; ++ break; ++ case CIS_OTP: ++ if (((oh = otp_init(sih)) != NULL) && (otp_status(oh) & OTPS_GUP_HW)) ++ sz = otp_size(oh); ++ break; ++ } ++ ++ if (sz != 0) { ++ if ((cisbuf = (uint16*)MALLOC(osh, sz)) == NULL) ++ return BCME_NOMEM; ++ msz = sz; ++ ++ switch (cis_src) { ++ case CIS_SROM: ++ rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, cisbuf, FALSE); ++ break; ++ case CIS_OTP: ++ sz >>= 1; ++ rc = otp_read_region(sih, OTP_HW_RGN, cisbuf, &sz); ++ sz <<= 1; ++ break; ++ } ++ ++ ASSERT(sz > hdrsz); ++ if (rc == BCME_OK) { ++ if ((cisbuf[0] == 0xffff) || (cisbuf[0] == 0)) { ++ MFREE(osh, cisbuf, msz); ++ cisbuf = NULL; ++ } else if (new_cisformat) { ++ cis[0] = (uint8*)(cisbuf + hdrsz); ++ } else { ++ cis[0] = (uint8*)cisbuf + hdrsz; ++ cis[1] = (uint8*)cisbuf + hdrsz + ++ (cisbuf[1] >> 8) + ((cisbuf[2] & 0x00ff) << 8) - ++ SBSDIO_CIS_BASE_COMMON; ++ cis[2] = (uint8*)cisbuf + hdrsz + ++ cisbuf[3] - SBSDIO_CIS_BASE_COMMON; ++ cis[3] = (uint8*)cisbuf + hdrsz + ++ cisbuf[4] - SBSDIO_CIS_BASE_COMMON; ++ ASSERT((cis[1] >= cis[0]) && (cis[1] < (uint8*)cisbuf + sz)); ++ ASSERT((cis[2] >= cis[0]) && (cis[2] < (uint8*)cisbuf + sz)); ++ ASSERT(((cis[3] >= cis[0]) && (cis[3] < (uint8*)cisbuf + sz)) || ++ (ciss <= 3)); ++ } ++ } ++ } ++ ++ /* Use default if strapped to, or strapped source empty */ ++ if (cisbuf == NULL) { ++ ciss = 1; ++ cis[0] = defcis; ++ } ++ ++#ifdef BCM_BMAC_VARS_APPEND ++ srom_load_nvram(sih, osh, cis, ciss, vars, varsz); ++#else ++ /* Parse the CIS */ ++ if (rc == BCME_OK) { ++ if ((rc = srom_parsecis(osh, cis, ciss, vars, varsz)) == BCME_OK) ++ nvram_append((void *)sih, *vars, *varsz); ++ } ++#endif /* BCM_BMAC_VARS_APPEND */ ++ /* Clean up */ ++ if (cisbuf != NULL) ++ MFREE(osh, cisbuf, msz); ++ ++ srvars_inited = TRUE; ++exit: ++ /* Tell the caller there is no individual SROM variables */ ++ *vars = NULL; ++ *varsz = 0; ++ ++ /* return OK so the driver will load & use defaults if bad srom/otp */ ++ return BCME_OK; ++} ++#else /* BCM_DONGLEVARS */ ++static int ++BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ *vars = NULL; ++ *varsz = 0; ++ return BCME_OK; ++} ++#endif /* BCM_DONGLEVARS */ ++ ++#else /* !BCMUSBDEV && !BCMSDIODEV */ ++ ++static int ++BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ /* Search flash nvram section for srom variables */ ++ return initvars_flash_si(sih, vars, varsz); ++} ++#endif ++ ++void ++srom_var_deinit(si_t *sih) ++{ ++ srvars_inited = FALSE; ++} ++ ++extern void _make_gcc_happy_about_unused_variabe_(void); ++void ++_make_gcc_happy_about_unused_variabe_(void) ++{ ++#if defined(BCMUSBDEV) ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++ UNUSED_PARAMETER(defaultsromvars_4322usb); ++ UNUSED_PARAMETER(defaultsromvars_43234usb); ++ UNUSED_PARAMETER(defaultsromvars_43235usb); ++ UNUSED_PARAMETER(defaultsromvars_43236usb); ++ UNUSED_PARAMETER(defaultsromvars_4319usb); ++#endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */ ++#endif /* BCMUSBDEV */ ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmutils.c b/drivers/bcmdrivers/gmac/src/shared/bcmutils.c +new file mode 100755 +index 0000000..9f45f68 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmutils.c +@@ -0,0 +1,3253 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Driver O/S-independent utility routines ++ * ++ * $Id: bcmutils.c 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#include ++#include ++#include ++#if defined(__FreeBSD__) || defined(__NetBSD__) ++#include ++#else ++#include ++#endif ++#ifdef BCMDRIVER ++ ++#include ++#include ++#include ++#include ++ ++#else /* !BCMDRIVER */ ++ ++#include ++#include ++#include ++ ++#if defined(BCMEXTSUP) ++#include ++#endif ++ ++ ++#endif /* !BCMDRIVER */ ++ ++#if defined(_WIN32) || defined(NDIS) || defined(__vxworks) || defined(_CFE_) ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef BCMPERFSTATS ++#include ++#endif ++#include ++void *_bcmutils_dummy_fn = NULL; ++ ++#ifdef BCMDRIVER ++ ++#ifdef WLC_LOW ++/* nvram vars cache */ ++static char *nvram_vars = NULL; ++static int vars_len = -1; ++#endif /* WLC_LOW */ ++ ++int ++pktpool_init(osl_t *osh, pktpool_t *pktp, int *pplen, int plen, bool istx) ++{ ++ int i, err = BCME_OK; ++ void *p; ++ int pktplen; ++ ++ ASSERT(pktp != NULL); ++ ASSERT(osh != NULL); ++ ASSERT(pplen != NULL); ++ ++ pktplen = *pplen; ++ ++ bzero(pktp, sizeof(pktpool_t)); ++ pktp->inited = TRUE; ++ pktp->istx = istx ? TRUE : FALSE; ++ pktp->plen = (uint16)plen; ++ *pplen = 0; ++ ++ pktp->maxlen = PKTPOOL_LEN_MAX; ++ if (pktplen > pktp->maxlen) ++ pktplen = pktp->maxlen; ++ ++ for (i = 0; i < pktplen; i++) { ++ p = PKTGET(osh, plen, pktp->istx); ++ if (p == NULL) { ++ /* Not able to allocate all requested pkts ++ * so just return what was actually allocated ++ * We can add to the pool later ++ */ ++ if (pktp->w == 0) ++ err = BCME_NOMEM; ++ ++ goto exit; ++ } ++ ++ PKTSETPOOL(osh, p, TRUE, pktp); ++ pktp->q[i] = p; ++ pktp->w++; ++ pktp->len++; ++#ifdef BCMDBG_POOL ++ pktp->dbg_q[pktp->dbg_qlen++].p = p; ++#endif ++ } ++ ++exit: ++ *pplen = pktp->w; ++ pktp->len++; /* Add one for end */ ++ return err; ++} ++ ++int ++pktpool_deinit(osl_t *osh, pktpool_t *pktp) ++{ ++ int i; ++ int cnt; ++ ++ ASSERT(osh != NULL); ++ ASSERT(pktp != NULL); ++ ++ cnt = pktp->len; ++ for (i = 0; i < cnt; i++) { ++ if (pktp->q[i] != NULL) { ++ PKTSETPOOL(osh, pktp->q[i], FALSE, NULL); ++ PKTFREE(osh, pktp->q[i], pktp->istx); ++ pktp->q[i] = NULL; ++ pktp->len--; ++ } ++#ifdef BCMDBG_POOL ++ if (pktp->dbg_q[i].p != NULL) ++ pktp->dbg_q[i].p = NULL; ++#endif ++ } ++ pktp->inited = FALSE; ++ ++ /* Are there still pending pkts? */ ++ ASSERT(pktpool_len(pktp) == 0); ++ ++ return 0; ++} ++ ++int ++pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal) ++{ ++ void *p; ++ int err = 0; ++ int len, psize, maxlen; ++ ++ ASSERT(pktpool_plen(pktp) != 0); ++ ++ maxlen = pktpool_maxlen(pktp); ++ psize = minimal ? (maxlen >> 2) : maxlen; ++ len = pktpool_len(pktp); ++ for (; len < psize; len++) { ++ p = PKTGET(osh, pktpool_plen(pktp), FALSE); ++ if (p == NULL) { ++ err = BCME_NOMEM; ++ break; ++ } ++ ++ if (pktpool_add(pktp, p) != BCME_OK) { ++ PKTFREE(osh, p, FALSE); ++ err = BCME_ERROR; ++ break; ++ } ++ } ++ ++ return err; ++} ++ ++uint16 ++pktpool_avail(pktpool_t *pktp) ++{ ++ if (pktp->w == pktp->r) ++ return 0; ++ ++ return (pktp->w > pktp->r) ? (pktp->w - pktp->r) : ((pktp->len) - (pktp->r - pktp->w)); ++} ++ ++static void * ++pktpool_deq(pktpool_t *pktp) ++{ ++ void *p; ++ ++ if (pktp->r == pktp->w) ++ return NULL; ++ ++ p = pktp->q[pktp->r]; ++ ASSERT(p != NULL); ++ ++ pktp->q[pktp->r++] = NULL; ++ pktp->r %= (pktp->len); ++ ++ return p; ++} ++ ++static void ++pktpool_enq(pktpool_t *pktp, void *p) ++{ ++ uint16 next; ++ ++ ASSERT(p != NULL); ++ ++ next = (pktp->w + 1) % (pktp->len); ++ if (next == pktp->r) { ++ /* Should not happen; otherwise pkt leak */ ++ ASSERT(0); ++ return; ++ } ++ ++ ASSERT(pktp->q[pktp->w] == NULL); ++ ++ pktp->q[pktp->w] = p; ++ pktp->w = next; ++} ++ ++int ++pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) ++{ ++ int i; ++ ++ ASSERT(cb != NULL); ++ ++ i = pktp->cbcnt; ++ if (i == PKTPOOL_CB_MAX) ++ return BCME_ERROR; ++ ++ ASSERT(pktp->cbs[i].cb == NULL); ++ pktp->cbs[i].cb = cb; ++ pktp->cbs[i].arg = arg; ++ pktp->cbcnt++; ++ ++ return 0; ++} ++ ++int ++pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) ++{ ++ int i; ++ ++ ASSERT(cb != NULL); ++ ++ i = pktp->ecbcnt; ++ if (i == PKTPOOL_CB_MAX) ++ return BCME_ERROR; ++ ++ ASSERT(pktp->ecbs[i].cb == NULL); ++ pktp->ecbs[i].cb = cb; ++ pktp->ecbs[i].arg = arg; ++ pktp->ecbcnt++; ++ ++ return 0; ++} ++ ++static int ++pktpool_empty_notify(pktpool_t *pktp) ++{ ++ int i; ++ ++ pktp->empty = TRUE; ++ for (i = 0; i < pktp->ecbcnt; i++) { ++ ASSERT(pktp->ecbs[i].cb != NULL); ++ pktp->ecbs[i].cb(pktp, pktp->ecbs[i].arg); ++ } ++ pktp->empty = FALSE; ++ ++ return 0; ++} ++ ++#ifdef BCMDBG_POOL ++int ++pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) ++{ ++ int i; ++ ++ ASSERT(cb); ++ ++ i = pktp->dbg_cbcnt; ++ if (i == PKTPOOL_CB_MAX) ++ return BCME_ERROR; ++ ++ ASSERT(pktp->dbg_cbs[i].cb == NULL); ++ pktp->dbg_cbs[i].cb = cb; ++ pktp->dbg_cbs[i].arg = arg; ++ pktp->dbg_cbcnt++; ++ ++ return 0; ++} ++ ++int pktpool_dbg_notify(pktpool_t *pktp); ++ ++int ++pktpool_dbg_notify(pktpool_t *pktp) ++{ ++ int i; ++ ++ for (i = 0; i < pktp->dbg_cbcnt; i++) { ++ ASSERT(pktp->dbg_cbs[i].cb); ++ pktp->dbg_cbs[i].cb(pktp, pktp->dbg_cbs[i].arg); ++ } ++ ++ return 0; ++} ++ ++int ++pktpool_dbg_dump(pktpool_t *pktp) ++{ ++ int i; ++ ++ printf("pool len=%d maxlen=%d\n", pktp->dbg_qlen, pktp->maxlen); ++ for (i = 0; i < pktp->dbg_qlen; i++) { ++ ASSERT(pktp->dbg_q[i].p); ++ printf("%d, p: 0x%x dur:%lu us state:%d\n", i, ++ pktp->dbg_q[i].p, pktp->dbg_q[i].dur/100, PKTPOOLSTATE(pktp->dbg_q[i].p)); ++ } ++ ++ return 0; ++} ++ ++int ++pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats) ++{ ++ int i; ++ int state; ++ ++ bzero(stats, sizeof(pktpool_stats_t)); ++ for (i = 0; i < pktp->dbg_qlen; i++) { ++ ASSERT(pktp->dbg_q[i].p != NULL); ++ ++ state = PKTPOOLSTATE(pktp->dbg_q[i].p); ++ switch (state) { ++ case POOL_TXENQ: ++ stats->enq++; break; ++ case POOL_TXDH: ++ stats->txdh++; break; ++ case POOL_TXD11: ++ stats->txd11++; break; ++ case POOL_RXDH: ++ stats->rxdh++; break; ++ case POOL_RXD11: ++ stats->rxd11++; break; ++ case POOL_RXFILL: ++ stats->rxfill++; break; ++ case POOL_IDLE: ++ stats->idle++; break; ++ } ++ } ++ ++ return 0; ++} ++ ++int ++pktpool_start_trigger(pktpool_t *pktp, void *p) ++{ ++ uint32 cycles, i; ++ ++ if (!PKTPOOL(NULL, p)) ++ return 0; ++ ++ OSL_GETCYCLES(cycles); ++ ++ for (i = 0; i < pktp->dbg_qlen; i++) { ++ ASSERT(pktp->dbg_q[i].p != NULL); ++ ++ if (pktp->dbg_q[i].p == p) { ++ pktp->dbg_q[i].cycles = cycles; ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++int pktpool_stop_trigger(pktpool_t *pktp, void *p); ++int ++pktpool_stop_trigger(pktpool_t *pktp, void *p) ++{ ++ uint32 cycles, i; ++ ++ if (!PKTPOOL(NULL, p)) ++ return 0; ++ ++ OSL_GETCYCLES(cycles); ++ ++ for (i = 0; i < pktp->dbg_qlen; i++) { ++ ASSERT(pktp->dbg_q[i].p != NULL); ++ ++ if (pktp->dbg_q[i].p == p) { ++ if (pktp->dbg_q[i].cycles == 0) ++ break; ++ ++ if (cycles >= pktp->dbg_q[i].cycles) ++ pktp->dbg_q[i].dur = cycles - pktp->dbg_q[i].cycles; ++ else ++ pktp->dbg_q[i].dur = ++ (((uint32)-1) - pktp->dbg_q[i].cycles) + cycles + 1; ++ ++ pktp->dbg_q[i].cycles = 0; ++ break; ++ } ++ } ++ ++ return 0; ++} ++#endif /* BCMDBG_POOL */ ++ ++int ++pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp) ++{ ++ ASSERT(pktp); ++ pktp->availcb_excl = NULL; ++ return 0; ++} ++ ++int ++pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb) ++{ ++ int i; ++ ++ ASSERT(pktp); ++ ASSERT(pktp->availcb_excl == NULL); ++ for (i = 0; i < pktp->cbcnt; i++) { ++ if (cb == pktp->cbs[i].cb) { ++ pktp->availcb_excl = &pktp->cbs[i]; ++ break; ++ } ++ } ++ ++ if (pktp->availcb_excl == NULL) ++ return BCME_ERROR; ++ else ++ return 0; ++} ++ ++static int ++pktpool_avail_notify(pktpool_t *pktp) ++{ ++ int i, k, idx; ++ int avail; ++ ++ ASSERT(pktp); ++ if (pktp->availcb_excl != NULL) { ++ pktp->availcb_excl->cb(pktp, pktp->availcb_excl->arg); ++ return 0; ++ } ++ ++ k = pktp->cbcnt - 1; ++ for (i = 0; i < pktp->cbcnt; i++) { ++ avail = pktpool_avail(pktp); ++ ++ if (avail) { ++ if (pktp->cbtoggle) ++ idx = i; ++ else ++ idx = k--; ++ ++ ASSERT(pktp->cbs[idx].cb != NULL); ++ pktp->cbs[idx].cb(pktp, pktp->cbs[idx].arg); ++ } ++ } ++ ++ /* Alternate between filling from head or tail ++ */ ++ pktp->cbtoggle ^= 1; ++ ++ return 0; ++} ++ ++void * ++pktpool_get(pktpool_t *pktp) ++{ ++ void *p; ++ ++ p = pktpool_deq(pktp); ++ ++ if (p == NULL) { ++ /* Notify and try to reclaim tx pkts */ ++ if (pktp->ecbcnt) ++ pktpool_empty_notify(pktp); ++ ++ p = pktpool_deq(pktp); ++ } ++ ++ return p; ++} ++ ++void ++pktpool_free(pktpool_t *pktp, void *p) ++{ ++ ASSERT(p != NULL); ++ ++#ifdef BCMDBG_POOL ++ /* pktpool_stop_trigger(pktp, p); */ ++#endif ++ ++ pktpool_enq(pktp, p); ++ ++ if (pktp->emptycb_disable) ++ return; ++ ++ if (pktp->cbcnt) { ++ if (pktp->empty == FALSE) ++ pktpool_avail_notify(pktp); ++ } ++} ++ ++int ++pktpool_add(pktpool_t *pktp, void *p) ++{ ++ ASSERT(p != NULL); ++ ++ if (pktpool_len(pktp) == pktp->maxlen) ++ return BCME_RANGE; ++ ++ ASSERT(pktpool_plen(pktp) == PKTLEN(NULL, p)); /* pkts in pool have same length */ ++ PKTSETPOOL(NULL, p, TRUE, pktp); ++ ++ pktp->len++; ++ if (pktp->r > pktp->w) { ++ /* Add to tail */ ++ ASSERT(pktp->q[pktp->len - 1] == NULL); ++ pktp->q[pktp->len - 1] = p; ++ } else ++ pktpool_enq(pktp, p); ++ ++#ifdef BCMDBG_POOL ++ pktp->dbg_q[pktp->dbg_qlen++].p = p; ++#endif ++ ++ return 0; ++} ++ ++int ++pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen) ++{ ++ if (maxlen > PKTPOOL_LEN_MAX) ++ maxlen = PKTPOOL_LEN_MAX; ++ ++ /* if pool is already beyond maxlen, then just cap it ++ * since we currently do not reduce the pool len ++ * already allocated ++ */ ++ pktp->maxlen = (pktpool_len(pktp) > maxlen) ? pktpool_len(pktp) : maxlen; ++ ++ return pktp->maxlen; ++} ++ ++void ++pktpool_emptycb_disable(pktpool_t *pktp, bool disable) ++{ ++ ASSERT(pktp); ++ ++ pktp->emptycb_disable = disable; ++} ++ ++bool ++pktpool_emptycb_disabled(pktpool_t *pktp) ++{ ++ ASSERT(pktp); ++ return pktp->emptycb_disable; ++} ++ ++/* copy a pkt buffer chain into a buffer */ ++uint ++pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) ++{ ++ uint n, ret = 0; ++ ++ if (len < 0) ++ len = 4096; /* "infinite" */ ++ ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = PKTNEXT(osh, p)) { ++ if (offset < (uint)PKTLEN(osh, p)) ++ break; ++ offset -= PKTLEN(osh, p); ++ } ++ ++ if (!p) ++ return 0; ++ ++ /* copy the data */ ++ for (; p && len; p = PKTNEXT(osh, p)) { ++ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); ++ bcopy(PKTDATA(osh, p) + offset, buf, n); ++ buf += n; ++ len -= n; ++ ret += n; ++ offset = 0; ++ } ++ ++ return ret; ++} ++ ++/* copy a buffer into a pkt buffer chain */ ++uint ++pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf) ++{ ++ uint n, ret = 0; ++ ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = PKTNEXT(osh, p)) { ++ if (offset < (uint)PKTLEN(osh, p)) ++ break; ++ offset -= PKTLEN(osh, p); ++ } ++ ++ if (!p) ++ return 0; ++ ++ /* copy the data */ ++ for (; p && len; p = PKTNEXT(osh, p)) { ++ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); ++ bcopy(buf, PKTDATA(osh, p) + offset, n); ++ buf += n; ++ len -= n; ++ ret += n; ++ offset = 0; ++ } ++ ++ return ret; ++} ++ ++#ifdef NOTYET ++/* copy data from one pkt buffer (chain) to another */ ++uint ++pkt2pktcopy(osl_t *osh, void *p1, uint offs1, void *p2, uint offs2, int maxlen) ++{ ++ uint8 *dp1, *dp2; ++ uint len1, len2, copylen, totallen; ++ ++ for (; p1 && offs; p1 = PKTNEXT(osh, p1)) { ++ if (offs1 < (uint)PKTLEN(osh, p1)) ++ break; ++ offs1 -= PKTLEN(osh, p1); ++ } ++ for (; p2 && offs; p2 = PKTNEXT(osh, p2)) { ++ if (offs2 < (uint)PKTLEN(osh, p2)) ++ break; ++ offs2 -= PKTLEN(osh, p2); ++ } ++ ++ /* Heck w/it, only need the above for now */ ++} ++#endif /* NOTYET */ ++ ++ ++/* return total length of buffer chain */ ++uint BCMFASTPATH ++pkttotlen(osl_t *osh, void *p) ++{ ++ uint total; ++ int len; ++ ++ total = 0; ++ for (; p; p = PKTNEXT(osh, p)) { ++ len = PKTLEN(osh, p); ++#ifdef MACOSX ++ if (len < 0) { ++ /* Bad packet length, just drop and exit */ ++ printf("wl: pkttotlen bad (%p,%d)\n", p, len); ++ break; ++ } ++#endif /* MACOSX */ ++ total += len; ++ } ++ ++ return (total); ++} ++ ++/* return the last buffer of chained pkt */ ++void * ++pktlast(osl_t *osh, void *p) ++{ ++ for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p)) ++ ; ++ ++ return (p); ++} ++ ++/* count segments of a chained packet */ ++uint BCMFASTPATH ++pktsegcnt(osl_t *osh, void *p) ++{ ++ uint cnt; ++ ++ for (cnt = 0; p; p = PKTNEXT(osh, p)) ++ cnt++; ++ ++ return cnt; ++} ++ ++ ++/* count segments of a chained packet */ ++uint BCMFASTPATH ++pktsegcnt_war(osl_t *osh, void *p) ++{ ++ uint cnt; ++ uint8 *pktdata; ++ uint len, remain, align64; ++ ++ for (cnt = 0; p; p = PKTNEXT(osh, p)) { ++ cnt++; ++ len = PKTLEN(osh, p); ++ if (len > 128) { ++ pktdata = (uint8 *)PKTDATA(osh, p); /* starting address of data */ ++ /* Check for page boundary straddle (2048B) */ ++ if (((uintptr)pktdata & ~0x7ff) != ((uintptr)(pktdata+len) & ~0x7ff)) ++ cnt++; ++ ++ align64 = (uint)((uintptr)pktdata & 0x3f); /* aligned to 64B */ ++ align64 = (64 - align64) & 0x3f; ++ len -= align64; /* bytes from aligned 64B to end */ ++ /* if aligned to 128B, check for MOD 128 between 1 to 4B */ ++ remain = len % 128; ++ if (remain > 0 && remain <= 4) ++ cnt++; /* add extra seg */ ++ } ++ } ++ ++ return cnt; ++} ++ ++uint8 * BCMFASTPATH ++pktdataoffset(osl_t *osh, void *p, uint offset) ++{ ++ uint total = pkttotlen(osh, p); ++ uint pkt_off = 0, len = 0; ++ uint8 *pdata = (uint8 *) PKTDATA(osh, p); ++ ++ if (offset > total) ++ return NULL; ++ ++ for (; p; p = PKTNEXT(osh, p)) { ++ pdata = (uint8 *) PKTDATA(osh, p); ++ pkt_off = offset - len; ++ len += PKTLEN(osh, p); ++ if (len > offset) ++ break; ++ } ++ return (uint8*) (pdata+pkt_off); ++} ++ ++ ++/* given a offset in pdata, find the pkt seg hdr */ ++void * ++pktoffset(osl_t *osh, void *p, uint offset) ++{ ++ uint total = pkttotlen(osh, p); ++ uint len = 0; ++ ++ if (offset > total) ++ return NULL; ++ ++ for (; p; p = PKTNEXT(osh, p)) { ++ len += PKTLEN(osh, p); ++ if (len > offset) ++ break; ++ } ++ return p; ++} ++ ++/* ++ * osl multiple-precedence packet queue ++ * hi_prec is always >= the number of the highest non-empty precedence ++ */ ++void * BCMFASTPATH ++pktq_penq(struct pktq *pq, int prec, void *p) ++{ ++ struct pktq_prec *q; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ++ ++ ASSERT(!pktq_full(pq)); ++ ASSERT(!pktq_pfull(pq, prec)); ++ ++ q = &pq->q[prec]; ++ ++ if (q->head) ++ PKTSETLINK(q->tail, p); ++ else ++ q->head = p; ++ ++ q->tail = p; ++ q->len++; ++ ++ pq->len++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (uint8)prec; ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_penq_head(struct pktq *pq, int prec, void *p) ++{ ++ struct pktq_prec *q; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ++ ++ ASSERT(!pktq_full(pq)); ++ ASSERT(!pktq_pfull(pq, prec)); ++ ++ q = &pq->q[prec]; ++ ++ if (q->head == NULL) ++ q->tail = p; ++ ++ PKTSETLINK(p, q->head); ++ q->head = p; ++ q->len++; ++ ++ pq->len++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (uint8)prec; ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_pdeq(struct pktq *pq, int prec) ++{ ++ struct pktq_prec *q; ++ void *p; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p) ++{ ++ struct pktq_prec *q; ++ void *p; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if (prev_p == NULL) ++ return NULL; ++ ++ if ((p = PKTLINK(prev_p)) == NULL) ++ return NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ PKTSETLINK(prev_p, PKTLINK(p)); ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_pdeq_tail(struct pktq *pq, int prec) ++{ ++ struct pktq_prec *q; ++ void *p, *prev; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ for (prev = NULL; p != q->tail; p = PKTLINK(p)) ++ prev = p; ++ ++ if (prev) ++ PKTSETLINK(prev, NULL); ++ else ++ q->head = NULL; ++ ++ q->tail = prev; ++ q->len--; ++ ++ pq->len--; ++ ++ return p; ++} ++ ++void ++pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ifpkt_cb_t fn, int arg) ++{ ++ struct pktq_prec *q; ++ void *p, *prev = NULL; ++ ++ q = &pq->q[prec]; ++ p = q->head; ++ while (p) { ++ if (fn == NULL || (*fn)(p, arg)) { ++ bool head = (p == q->head); ++ if (head) ++ q->head = PKTLINK(p); ++ else ++ PKTSETLINK(prev, PKTLINK(p)); ++ PKTSETLINK(p, NULL); ++ PKTFREE(osh, p, dir); ++ q->len--; ++ pq->len--; ++ p = (head ? q->head : PKTLINK(prev)); ++ } else { ++ prev = p; ++ p = PKTLINK(p); ++ } ++ } ++ ++ if (q->head == NULL) { ++ ASSERT(q->len == 0); ++ q->tail = NULL; ++ } ++} ++ ++bool BCMFASTPATH ++pktq_pdel(struct pktq *pq, void *pktbuf, int prec) ++{ ++ struct pktq_prec *q; ++ void *p; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ if (!pktbuf) ++ return FALSE; ++ ++ q = &pq->q[prec]; ++ ++ if (q->head == pktbuf) { ++ if ((q->head = PKTLINK(pktbuf)) == NULL) ++ q->tail = NULL; ++ } else { ++ for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p)) ++ ; ++ if (p == NULL) ++ return FALSE; ++ ++ PKTSETLINK(p, PKTLINK(pktbuf)); ++ if (q->tail == pktbuf) ++ q->tail = p; ++ } ++ ++ q->len--; ++ pq->len--; ++ PKTSETLINK(pktbuf, NULL); ++ return TRUE; ++} ++ ++void ++pktq_init(struct pktq *pq, int num_prec, int max_len) ++{ ++ int prec; ++ ++ ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC); ++ ++ /* pq is variable size; only zero out what's requested */ ++ bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec)); ++ ++ pq->num_prec = (uint16)num_prec; ++ ++ pq->max = (uint16)max_len; ++ ++ for (prec = 0; prec < num_prec; prec++) ++ pq->q[prec].max = pq->max; ++} ++ ++void ++pktq_set_max_plen(struct pktq *pq, int prec, int max_len) ++{ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ if (prec < pq->num_prec) ++ pq->q[prec].max = (uint16)max_len; ++} ++ ++void * BCMFASTPATH ++pktq_deq(struct pktq *pq, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_deq_tail(struct pktq *pq, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p, *prev; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ for (prev = NULL; p != q->tail; p = PKTLINK(p)) ++ prev = p; ++ ++ if (prev) ++ PKTSETLINK(prev, NULL); ++ else ++ q->head = NULL; ++ ++ q->tail = prev; ++ q->len--; ++ ++ pq->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * ++pktq_peek(struct pktq *pq, int *prec_out) ++{ ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return (pq->q[prec].head); ++} ++ ++void * ++pktq_peek_tail(struct pktq *pq, int *prec_out) ++{ ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return (pq->q[prec].tail); ++} ++ ++void ++pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg) ++{ ++ int prec; ++ ++ /* Optimize flush, if pktq len = 0, just return. ++ * pktq len of 0 means pktq's prec q's are all empty. ++ */ ++ if (pq->len == 0) { ++ return; ++ } ++ ++ for (prec = 0; prec < pq->num_prec; prec++) ++ pktq_pflush(osh, pq, prec, dir, fn, arg); ++ if (fn == NULL) ++ ASSERT(pq->len == 0); ++} ++ ++/* Return sum of lengths of a specific set of precedences */ ++int ++pktq_mlen(struct pktq *pq, uint prec_bmp) ++{ ++ int prec, len; ++ ++ len = 0; ++ ++ for (prec = 0; prec <= pq->hi_prec; prec++) ++ if (prec_bmp & (1 << prec)) ++ len += pq->q[prec].len; ++ ++ return len; ++} ++ ++/* Priority peek from a specific set of precedences */ ++void * BCMFASTPATH ++pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; ++ ++ if (pq->len == 0) ++ { ++ return NULL; ++ } ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) ++ if (prec-- == 0) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return p; ++} ++/* Priority dequeue from a specific set of precedences */ ++void * BCMFASTPATH ++pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0)) ++ if (prec-- == 0) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ pq->len--; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++#endif /* BCMDRIVER */ ++ ++#if defined(BCMROMBUILD) ++const unsigned char BCMROMDATA(bcm_ctype)[] = { ++#else ++const unsigned char bcm_ctype[] = { ++#endif ++ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ ++ _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C, ++ _BCM_C, /* 8-15 */ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */ ++ _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */ ++ _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */ ++ _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */ ++ _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */ ++ _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, ++ _BCM_U|_BCM_X, _BCM_U, /* 64-71 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */ ++ _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, ++ _BCM_L|_BCM_X, _BCM_L, /* 96-103 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */ ++ _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */ ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */ ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */ ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U, ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */ ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */ ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L, ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */ ++}; ++ ++ulong ++BCMROMFN(bcm_strtoul)(const char *cp, char **endp, uint base) ++{ ++ ulong result, last_result = 0, value; ++ bool minus; ++ ++ minus = FALSE; ++ ++ while (bcm_isspace(*cp)) ++ cp++; ++ ++ if (cp[0] == '+') ++ cp++; ++ else if (cp[0] == '-') { ++ minus = TRUE; ++ cp++; ++ } ++ ++ if (base == 0) { ++ if (cp[0] == '0') { ++ if ((cp[1] == 'x') || (cp[1] == 'X')) { ++ base = 16; ++ cp = &cp[2]; ++ } else { ++ base = 8; ++ cp = &cp[1]; ++ } ++ } else ++ base = 10; ++ } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { ++ cp = &cp[2]; ++ } ++ ++ result = 0; ++ ++ while (bcm_isxdigit(*cp) && ++ (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) { ++ result = result*base + value; ++ /* Detected overflow */ ++ if (result < last_result && !minus) ++ return (ulong)-1; ++ last_result = result; ++ cp++; ++ } ++ ++ if (minus) ++ result = (ulong)(-(long)result); ++ ++ if (endp) ++ *endp = DISCARD_QUAL(cp, char); ++ ++ return (result); ++} ++ ++int ++BCMROMFN(bcm_atoi)(const char *s) ++{ ++ return (int)bcm_strtoul(s, NULL, 10); ++} ++ ++/* return pointer to location of substring 'needle' in 'haystack' */ ++char * ++BCMROMFN(bcmstrstr)(const char *haystack, const char *needle) ++{ ++ int len, nlen; ++ int i; ++ ++ if ((haystack == NULL) || (needle == NULL)) ++ return DISCARD_QUAL(haystack, char); ++ ++ nlen = strlen(needle); ++ len = strlen(haystack) - nlen + 1; ++ ++ for (i = 0; i < len; i++) ++ if (memcmp(needle, &haystack[i], nlen) == 0) ++ return DISCARD_QUAL(&haystack[i], char); ++ return (NULL); ++} ++ ++char * ++BCMROMFN(bcmstrcat)(char *dest, const char *src) ++{ ++ char *p; ++ ++ p = dest + strlen(dest); ++ ++ while ((*p++ = *src++) != '\0') ++ ; ++ ++ return (dest); ++} ++ ++char * ++BCMROMFN(bcmstrncat)(char *dest, const char *src, uint size) ++{ ++ char *endp; ++ char *p; ++ ++ p = dest + strlen(dest); ++ endp = p + size; ++ ++ while (p != endp && (*p++ = *src++) != '\0') ++ ; ++ ++ return (dest); ++} ++ ++ ++/**************************************************************************** ++* Function: bcmstrtok ++* ++* Purpose: ++* Tokenizes a string. This function is conceptually similiar to ANSI C strtok(), ++* but allows strToken() to be used by different strings or callers at the same ++* time. Each call modifies '*string' by substituting a NULL character for the ++* first delimiter that is encountered, and updates 'string' to point to the char ++* after the delimiter. Leading delimiters are skipped. ++* ++* Parameters: ++* string (mod) Ptr to string ptr, updated by token. ++* delimiters (in) Set of delimiter characters. ++* tokdelim (out) Character that delimits the returned token. (May ++* be set to NULL if token delimiter is not required). ++* ++* Returns: Pointer to the next token found. NULL when no more tokens are found. ++***************************************************************************** ++*/ ++char * ++bcmstrtok(char **string, const char *delimiters, char *tokdelim) ++{ ++ unsigned char *str; ++ unsigned long map[8]; ++ int count; ++ char *nextoken; ++ ++ if (tokdelim != NULL) { ++ /* Prime the token delimiter */ ++ *tokdelim = '\0'; ++ } ++ ++ /* Clear control map */ ++ for (count = 0; count < 8; count++) { ++ map[count] = 0; ++ } ++ ++ /* Set bits in delimiter table */ ++ do { ++ map[*delimiters >> 5] |= (1 << (*delimiters & 31)); ++ } ++ while (*delimiters++); ++ ++ str = (unsigned char*)*string; ++ ++ /* Find beginning of token (skip over leading delimiters). Note that ++ * there is no token iff this loop sets str to point to the terminal ++ * null (*str == '\0') ++ */ ++ while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) { ++ str++; ++ } ++ ++ nextoken = (char*)str; ++ ++ /* Find the end of the token. If it is not the end of the string, ++ * put a null there. ++ */ ++ for (; *str; str++) { ++ if (map[*str >> 5] & (1 << (*str & 31))) { ++ if (tokdelim != NULL) { ++ *tokdelim = *str; ++ } ++ ++ *str++ = '\0'; ++ break; ++ } ++ } ++ ++ *string = (char*)str; ++ ++ /* Determine if a token has been found. */ ++ if (nextoken == (char *) str) { ++ return NULL; ++ } ++ else { ++ return nextoken; ++ } ++} ++ ++ ++#define xToLower(C) \ ++ ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C) ++ ++ ++/**************************************************************************** ++* Function: bcmstricmp ++* ++* Purpose: Compare to strings case insensitively. ++* ++* Parameters: s1 (in) First string to compare. ++* s2 (in) Second string to compare. ++* ++* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if ++* t1 > t2, when ignoring case sensitivity. ++***************************************************************************** ++*/ ++int ++bcmstricmp(const char *s1, const char *s2) ++{ ++ char dc, sc; ++ ++ while (*s2 && *s1) { ++ dc = xToLower(*s1); ++ sc = xToLower(*s2); ++ if (dc < sc) return -1; ++ if (dc > sc) return 1; ++ s1++; ++ s2++; ++ } ++ ++ if (*s1 && !*s2) return 1; ++ if (!*s1 && *s2) return -1; ++ return 0; ++} ++ ++ ++/**************************************************************************** ++* Function: bcmstrnicmp ++* ++* Purpose: Compare to strings case insensitively, upto a max of 'cnt' ++* characters. ++* ++* Parameters: s1 (in) First string to compare. ++* s2 (in) Second string to compare. ++* cnt (in) Max characters to compare. ++* ++* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if ++* t1 > t2, when ignoring case sensitivity. ++***************************************************************************** ++*/ ++int ++bcmstrnicmp(const char* s1, const char* s2, int cnt) ++{ ++ char dc, sc; ++ ++ while (*s2 && *s1 && cnt) { ++ dc = xToLower(*s1); ++ sc = xToLower(*s2); ++ if (dc < sc) return -1; ++ if (dc > sc) return 1; ++ s1++; ++ s2++; ++ cnt--; ++ } ++ ++ if (!cnt) return 0; ++ if (*s1 && !*s2) return 1; ++ if (!*s1 && *s2) return -1; ++ return 0; ++} ++ ++/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ ++int ++BCMROMFN(bcm_ether_atoe)(const char *p, struct ether_addr *ea) ++{ ++ int i = 0; ++ char *ep; ++ ++ for (;;) { ++ ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16); ++ p = ep; ++ if (!*p++ || i == 6) ++ break; ++ } ++ ++ return (i == 6); ++} ++ ++ ++#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) ++/* registry routine buffer preparation utility functions: ++ * parameter order is like strncpy, but returns count ++ * of bytes copied. Minimum bytes copied is null char(1)/wchar(2) ++ */ ++ulong ++wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen) ++{ ++ ulong copyct = 1; ++ ushort i; ++ ++ if (abuflen == 0) ++ return 0; ++ ++ /* wbuflen is in bytes */ ++ wbuflen /= sizeof(ushort); ++ ++ for (i = 0; i < wbuflen; ++i) { ++ if (--abuflen == 0) ++ break; ++ *abuf++ = (char) *wbuf++; ++ ++copyct; ++ } ++ *abuf = '\0'; ++ ++ return copyct; ++} ++#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */ ++ ++char * ++bcm_ether_ntoa(const struct ether_addr *ea, char *buf) ++{ ++ static const char hex[] = ++ { ++ '0', '1', '2', '3', '4', '5', '6', '7', ++ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' ++ }; ++ const uint8 *octet = ea->octet; ++ char *p = buf; ++ int i; ++ ++ for (i = 0; i < 6; i++, octet++) { ++ *p++ = hex[(*octet >> 4) & 0xf]; ++ *p++ = hex[*octet & 0xf]; ++ *p++ = ':'; ++ } ++ ++ *(p-1) = '\0'; ++ ++ return (buf); ++} ++ ++char * ++bcm_ip_ntoa(struct ipv4_addr *ia, char *buf) ++{ ++ snprintf(buf, 16, "%d.%d.%d.%d", ++ ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]); ++ return (buf); ++} ++ ++#ifdef BCMDRIVER ++ ++void ++bcm_mdelay(uint ms) ++{ ++ uint i; ++ ++ for (i = 0; i < ms; i++) { ++ OSL_DELAY(1000); ++ } ++} ++ ++/* ++ * Search the name=value vars for a specific one and return its value. ++ * Returns NULL if not found. ++ */ ++char * ++getvar(char *vars, const char *name) ++{ ++#ifdef _MINOSL_ ++ return NULL; ++#else ++ char *s; ++ int len; ++ ++ if (!name) ++ return NULL; ++ ++ len = strlen(name); ++ if (len == 0) ++ return NULL; ++ ++ /* first look in vars[] */ ++ for (s = vars; s && *s;) { ++ if ((bcmp(s, name, len) == 0) && (s[len] == '=') && (strlen(s)==len)) ++ return (&s[len+1]); ++ ++ while (*s++) ++ ; ++ } ++ ++ /* then query nvram */ ++ return (nvram_get(name)); ++#endif /* defined(_MINOSL_) */ ++} ++ ++/* ++ * Search the vars for a specific one and return its value as ++ * an integer. Returns 0 if not found. ++ */ ++int ++getintvar(char *vars, const char *name) ++{ ++#ifdef _MINOSL_ ++ return 0; ++#else ++ char *val; ++ ++ if ((val = getvar(vars, name)) == NULL) ++ return (0); ++ ++ return (bcm_strtoul(val, NULL, 0)); ++#endif /* _MINOSL_ */ ++} ++ ++int ++getintvararray(char *vars, const char *name, int index) ++{ ++#ifdef _MINOSL_ ++ return 0; ++#else ++ char *buf, *endp; ++ int i = 0; ++ int val = 0; ++ ++ if ((buf = getvar(vars, name)) == NULL) { ++ return (0); ++ } ++ ++ /* table values are always separated by "," or " " */ ++ while (*buf != '\0') { ++ val = bcm_strtoul(buf, &endp, 0); ++ if (i == index) { ++ return val; ++ } ++ buf = endp; ++ /* delimiter is ',' */ ++ if (*buf == ',') ++ buf++; ++ i++; ++ } ++ return 0; ++#endif /* _MINOSL_ */ ++} ++ ++int ++getintvararraysize(char *vars, const char *name) ++{ ++#ifdef _MINOSL_ ++ return 0; ++#else ++ char *buf, *endp; ++ int count = 0; ++ int val = 0; ++ ++ if ((buf = getvar(vars, name)) == NULL) { ++ return (0); ++ } ++ ++ /* table values are always separated by "," or " " */ ++ while (*buf != '\0') { ++ val = bcm_strtoul(buf, &endp, 0); ++ buf = endp; ++ /* delimiter is ',' */ ++ if (*buf == ',') ++ buf++; ++ count++; ++ } ++ BCM_REFERENCE(val); ++ return count; ++#endif /* _MINOSL_ */ ++} ++ ++/* Search for token in comma separated token-string */ ++static int ++findmatch(const char *string, const char *name) ++{ ++ uint len; ++ char *c; ++ ++ len = strlen(name); ++ while ((c = strchr(string, ',')) != NULL) { ++ if (len == (uint)(c - string) && !strncmp(string, name, len)) ++ return 1; ++ string = c + 1; ++ } ++ ++ return (!strcmp(string, name)); ++} ++ ++/* Return gpio pin number assigned to the named pin ++ * ++ * Variable should be in format: ++ * ++ * gpio=pin_name,pin_name ++ * ++ * This format allows multiple features to share the gpio with mutual ++ * understanding. ++ * ++ * 'def_pin' is returned if a specific gpio is not defined for the requested functionality ++ * and if def_pin is not used by others. ++ */ ++uint ++getgpiopin(char *vars, char *pin_name, uint def_pin) ++{ ++ char name[] = "gpioXXXX"; ++ char *val; ++ uint pin; ++ ++ /* Go thru all possibilities till a match in pin name */ ++ for (pin = 0; pin < GPIO_NUMPINS; pin ++) { ++ snprintf(name, sizeof(name), "gpio%d", pin); ++ val = getvar(vars, name); ++ if (val && findmatch(val, pin_name)) ++ return pin; ++ } ++ ++ if (def_pin != GPIO_PIN_NOTDEFINED) { ++ /* make sure the default pin is not used by someone else */ ++ snprintf(name, sizeof(name), "gpio%d", def_pin); ++ if (getvar(vars, name)) { ++ def_pin = GPIO_PIN_NOTDEFINED; ++ } ++ } ++ return def_pin; ++} ++ ++ ++/* Return the WAN port number ++ * ++ * 0 is returned if no wanport is configured. ++ */ ++int ++getwanport(void) ++{ ++ char name[] = "wanport"; ++ int retval; ++ ++ retval = getintvar(NULL, name); ++ return retval; ++} ++ ++ ++/* Return the brcmtag variable ++ * ++ * 0 is returned if no wanport is configured. ++ */ ++int ++getbrcmtag(void) ++{ ++ char name[] = "brcmtag"; ++ int retval; ++ ++ retval = getintvar(NULL, name); ++ return retval; ++} ++ ++ ++#if defined(BCMPERFSTATS) || defined(BCMTSTAMPEDLOGS) ++ ++#define LOGSIZE 256 /* should be power of 2 to avoid div below */ ++static struct { ++ uint cycles; ++ char *fmt; ++ uint a1; ++ uint a2; ++} logtab[LOGSIZE]; ++ ++/* last entry logged */ ++static uint logi = 0; ++/* next entry to read */ ++static uint readi = 0; ++#endif /* defined(BCMPERFSTATS) || defined(BCMTSTAMPEDLOGS) */ ++ ++#ifdef BCMPERFSTATS ++void ++bcm_perf_enable() ++{ ++ BCMPERF_ENABLE_INSTRCOUNT(); ++ BCMPERF_ENABLE_ICACHE_MISS(); ++ BCMPERF_ENABLE_ICACHE_HIT(); ++} ++ ++/* WARNING: This routine uses OSL_GETCYCLES(), which can give unexpected results on ++ * modern speed stepping CPUs. Use bcmtslog() instead in combination with TSF counter. ++ */ ++void ++bcmlog(char *fmt, uint a1, uint a2) ++{ ++ static uint last = 0; ++ uint cycles, i; ++ OSL_GETCYCLES(cycles); ++ ++ i = logi; ++ ++ logtab[i].cycles = cycles - last; ++ logtab[i].fmt = fmt; ++ logtab[i].a1 = a1; ++ logtab[i].a2 = a2; ++ ++ logi = (i + 1) % LOGSIZE; ++ last = cycles; ++} ++ ++ ++void ++bcmstats(char *fmt) ++{ ++ static uint last = 0; ++ static uint32 ic_miss = 0; ++ static uint32 instr_count = 0; ++ uint32 ic_miss_cur; ++ uint32 instr_count_cur; ++ uint cycles, i; ++ ++ OSL_GETCYCLES(cycles); ++ BCMPERF_GETICACHE_MISS(ic_miss_cur); ++ BCMPERF_GETINSTRCOUNT(instr_count_cur); ++ ++ i = logi; ++ ++ logtab[i].cycles = cycles - last; ++ logtab[i].a1 = ic_miss_cur - ic_miss; ++ logtab[i].a2 = instr_count_cur - instr_count; ++ logtab[i].fmt = fmt; ++ ++ logi = (i + 1) % LOGSIZE; ++ ++ last = cycles; ++ instr_count = instr_count_cur; ++ ic_miss = ic_miss_cur; ++} ++ ++ ++void ++bcmdumplog(char *buf, int size) ++{ ++ char *limit; ++ int j = 0; ++ int num; ++ ++ limit = buf + size - 80; ++ *buf = '\0'; ++ ++ num = logi - readi; ++ ++ if (num < 0) ++ num += LOGSIZE; ++ ++ /* print in chronological order */ ++ ++ for (j = 0; j < num && (buf < limit); readi = (readi + 1) % LOGSIZE, j++) { ++ if (logtab[readi].fmt == NULL) ++ continue; ++ buf += snprintf(buf, (limit - buf), "%d\t", logtab[readi].cycles); ++ buf += snprintf(buf, (limit - buf), logtab[readi].fmt, logtab[readi].a1, ++ logtab[readi].a2); ++ buf += snprintf(buf, (limit - buf), "\n"); ++ } ++ ++} ++ ++ ++/* ++ * Dump one log entry at a time. ++ * Return index of next entry or -1 when no more . ++ */ ++int ++bcmdumplogent(char *buf, uint i) ++{ ++ bool hit; ++ ++ /* ++ * If buf is NULL, return the starting index, ++ * interpreting i as the indicator of last 'i' entries to dump. ++ */ ++ if (buf == NULL) { ++ i = ((i > 0) && (i < (LOGSIZE - 1))) ? i : (LOGSIZE - 1); ++ return ((logi - i) % LOGSIZE); ++ } ++ ++ *buf = '\0'; ++ ++ ASSERT(i < LOGSIZE); ++ ++ if (i == logi) ++ return (-1); ++ ++ hit = FALSE; ++ for (; (i != logi) && !hit; i = (i + 1) % LOGSIZE) { ++ if (logtab[i].fmt == NULL) ++ continue; ++ buf += sprintf(buf, "%d: %d\t", i, logtab[i].cycles); ++ buf += sprintf(buf, logtab[i].fmt, logtab[i].a1, logtab[i].a2); ++ buf += sprintf(buf, "\n"); ++ hit = TRUE; ++ } ++ ++ return (i); ++} ++ ++#endif /* BCMPERFSTATS */ ++ ++#if defined(BCMTSTAMPEDLOGS) ++/* Store a TSF timestamp and a log line in the log buffer */ ++void ++bcmtslog(uint32 tstamp, char *fmt, uint a1, uint a2) ++{ ++ uint i = logi; ++ bool use_delta = FALSE; ++ static uint32 last = 0; /* used only when use_delta is true */ ++ ++ logtab[i].cycles = tstamp; ++ if (use_delta) ++ logtab[i].cycles -= last; ++ ++ logtab[i].fmt = fmt; ++ logtab[i].a1 = a1; ++ logtab[i].a2 = a2; ++ ++ if (use_delta) ++ last = tstamp; ++ logi = (i + 1) % LOGSIZE; ++} ++ ++/* Print out a microsecond timestamp as "sec.ms.us " */ ++void ++bcmprinttstamp(uint32 ticks) ++{ ++ uint us, ms, sec; ++ ++ us = (ticks % TSF_TICKS_PER_MS) * 1000 / TSF_TICKS_PER_MS; ++ ms = ticks / TSF_TICKS_PER_MS; ++ sec = ms / 1000; ++ ms -= sec * 1000; ++ printf("%04u.%03u.%03u ", sec, ms, us); ++} ++ ++/* Print out the log buffer with timestamps */ ++void ++bcmprinttslogs(void) ++{ ++ int j = 0; ++ int num; ++ ++ num = logi - readi; ++ if (num < 0) ++ num += LOGSIZE; ++ ++ /* Format and print the log entries directly in chronological order */ ++ for (j = 0; j < num; readi = (readi + 1) % LOGSIZE, j++) { ++ if (logtab[readi].fmt == NULL) ++ continue; ++ bcmprinttstamp(logtab[readi].cycles); ++ printf(logtab[readi].fmt, logtab[readi].a1, logtab[readi].a2); ++ printf("\n"); ++ } ++} ++ ++void ++bcmdumptslog(char *buf, int size) ++{ ++ char *limit; ++ int j = 0; ++ int num; ++ uint us, ms, sec; ++ ++ limit = buf + size - 80; ++ *buf = '\0'; ++ ++ num = logi - readi; ++ ++ if (num < 0) ++ num += LOGSIZE; ++ ++ /* print in chronological order */ ++ for (j = 0; j < num && (buf < limit); readi = (readi + 1) % LOGSIZE, j++) { ++ if (logtab[readi].fmt == NULL) ++ continue; ++ us = (logtab[readi].cycles % TSF_TICKS_PER_MS) * 1000 / TSF_TICKS_PER_MS; ++ ms = logtab[readi].cycles / TSF_TICKS_PER_MS; ++ sec = ms / 1000; ++ ms -= sec * 1000; ++ ++ buf += snprintf(buf, (limit - buf), "%04u.%03u.%03u ", sec, ms, us); ++ /* buf += snprintf(buf, (limit - buf), "%d\t", logtab[readi].cycles); */ ++ buf += snprintf(buf, (limit - buf), logtab[readi].fmt, logtab[readi].a1, ++ logtab[readi].a2); ++ buf += snprintf(buf, (limit - buf), "\n"); ++ } ++} ++ ++#endif /* BCMTSTAMPEDLOGS */ ++ ++#if defined(BCMDBG) || defined(DHD_DEBUG) ++/* pretty hex print a pkt buffer chain */ ++void ++prpkt(const char *msg, osl_t *osh, void *p0) ++{ ++ void *p; ++ ++ if (msg && (msg[0] != '\0')) ++ printf("%s:\n", msg); ++ ++ for (p = p0; p; p = PKTNEXT(osh, p)) ++ prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p)); ++} ++#endif /* BCMDBG || DHD_DEBUG */ ++ ++/* Takes an Ethernet frame and sets out-of-bound PKTPRIO. ++ * Also updates the inplace vlan tag if requested. ++ * For debugging, it returns an indication of what it did. ++ */ ++uint BCMFASTPATH ++pktsetprio(void *pkt, bool update_vtag) ++{ ++ struct ether_header *eh; ++ struct ethervlan_header *evh; ++ uint8 *pktdata; ++ int priority = 0; ++ int rc = 0; ++ ++ pktdata = (uint8 *)PKTDATA(NULL, pkt); ++ ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16))); ++ ++ eh = (struct ether_header *) pktdata; ++ ++ if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) { ++ uint16 vlan_tag; ++ int vlan_prio, dscp_prio = 0; ++ ++ evh = (struct ethervlan_header *)eh; ++ ++ vlan_tag = ntoh16(evh->vlan_tag); ++ vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; ++ ++ if (evh->ether_type == hton16(ETHER_TYPE_IP)) { ++ uint8 *ip_body = pktdata + sizeof(struct ethervlan_header); ++ uint8 tos_tc = IP_TOS46(ip_body); ++ dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); ++ } ++ ++ /* DSCP priority gets precedence over 802.1P (vlan tag) */ ++ if (dscp_prio != 0) { ++ priority = dscp_prio; ++ rc |= PKTPRIO_VDSCP; ++ } else { ++ priority = vlan_prio; ++ rc |= PKTPRIO_VLAN; ++ } ++ /* ++ * If the DSCP priority is not the same as the VLAN priority, ++ * then overwrite the priority field in the vlan tag, with the ++ * DSCP priority value. This is required for Linux APs because ++ * the VLAN driver on Linux, overwrites the skb->priority field ++ * with the priority value in the vlan tag ++ */ ++ if (update_vtag && (priority != vlan_prio)) { ++ vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); ++ vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT; ++ evh->vlan_tag = hton16(vlan_tag); ++ rc |= PKTPRIO_UPD; ++ } ++ } else if (eh->ether_type == hton16(ETHER_TYPE_IP)) { ++ uint8 *ip_body = pktdata + sizeof(struct ether_header); ++ uint8 tos_tc = IP_TOS46(ip_body); ++ priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); ++ rc |= PKTPRIO_DSCP; ++ } ++ ++ ASSERT(priority >= 0 && priority <= MAXPRIO); ++ PKTSETPRIO(pkt, priority); ++ return (rc | priority); ++} ++ ++#ifndef BCM_BOOTLOADER ++ ++static char bcm_undeferrstr[32]; ++static const char *const bcmerrorstrtable[] = BCMERRSTRINGTABLE; ++ ++/* Convert the error codes into related error strings */ ++const char * ++bcmerrorstr(int bcmerror) ++{ ++ /* check if someone added a bcmerror code but forgot to add errorstring */ ++ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1)); ++ ++ if (bcmerror > 0 || bcmerror < BCME_LAST) { ++ snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror); ++ return bcm_undeferrstr; ++ } ++ ++ ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN); ++ ++ return bcmerrorstrtable[-bcmerror]; ++} ++ ++#endif /* !BCM_BOOTLOADER */ ++ ++#ifdef WLC_LOW ++static void ++BCMINITFN(bcm_nvram_refresh)(char *flash) ++{ ++ int i; ++ int ret = 0; ++ ++ ASSERT(flash != NULL); ++ ++ /* default "empty" vars cache */ ++ bzero(flash, 2); ++ ++ if ((ret = nvram_getall(flash, NVRAM_SPACE))) ++ return; ++ ++ /* determine nvram length */ ++ for (i = 0; i < NVRAM_SPACE; i++) { ++ if (flash[i] == '\0' && flash[i+1] == '\0') ++ break; ++ } ++ ++ if (i > 1) ++ vars_len = i + 2; ++ else ++ vars_len = 0; ++} ++ ++char * ++bcm_nvram_vars(uint *length) ++{ ++#ifndef BCMNVRAMR ++ /* cache may be stale if nvram is read/write */ ++ if (nvram_vars) { ++ ASSERT(!bcmreclaimed); ++ bcm_nvram_refresh(nvram_vars); ++ } ++#endif ++ if (length) ++ *length = vars_len; ++ return nvram_vars; ++} ++ ++/* copy nvram vars into locally-allocated multi-string array */ ++int ++BCMINITFN(bcm_nvram_cache)(void *sih) ++{ ++ int ret = 0; ++ void *osh; ++ char *flash = NULL; ++ ++ if (vars_len >= 0) { ++#ifndef BCMNVRAMR ++ bcm_nvram_refresh(nvram_vars); ++#endif ++ return 0; ++ } ++ ++ osh = si_osh((si_t *)sih); ++ ++ /* allocate memory and read in flash */ ++ if (!(flash = MALLOC(osh, NVRAM_SPACE))) { ++ ret = BCME_NOMEM; ++ goto exit; ++ } ++ ++ bcm_nvram_refresh(flash); ++ ++#ifdef BCMNVRAMR ++ if (vars_len > 3) { ++ /* copy into a properly-sized buffer */ ++ if (!(nvram_vars = MALLOC(osh, vars_len))) { ++ ret = BCME_NOMEM; ++ } else ++ bcopy(flash, nvram_vars, vars_len); ++ } ++ MFREE(osh, flash, NVRAM_SPACE); ++#else ++ /* cache must be full size of nvram if read/write */ ++ nvram_vars = flash; ++#endif /* BCMNVRAMR */ ++ ++exit: ++ return ret; ++} ++#endif /* WLC_LOW */ ++ ++ ++int32 ++exthdr_validate(char *ptr, uint size) ++{ ++ char *exthdr, *trx_offset; ++ uint hdrsz; ++ int trxof = 0; ++ ++ if ((exthdr = nvram_get("ext_imghdr"))) { ++ char s[] = "XXX"; ++ uint i, j; ++ ++ hdrsz = strlen(exthdr); ++ ++ if (hdrsz > size) { ++ printf("Exthdr_size(%d) > Image_size(%d)\n", hdrsz, size); ++ trxof = -1; ++ goto done; ++ } ++ ++ if (hdrsz == 0) ++ goto match; ++ ++ for (i = 0, j = 0; i < (hdrsz >> 1); i++) { ++ sprintf(s, "%02x", (ptr[i] & 0xff)); ++ if ((exthdr[j++] != s[0]) || (exthdr[j++] != s[1])) { ++ printf("Header mismatch\n"); ++ goto done; ++ } ++ } ++ } ++ ++match: ++ if ((trx_offset = nvram_get("trx_offset"))) ++ trxof = bcm_strtoul(trx_offset, NULL, 0); ++ ++done: ++ return trxof; ++} ++ ++/* iovar table lookup */ ++const bcm_iovar_t* ++bcm_iovar_lookup(const bcm_iovar_t *table, const char *name) ++{ ++ const bcm_iovar_t *vi; ++ const char *lookup_name; ++ ++ /* skip any ':' delimited option prefixes */ ++ lookup_name = strrchr(name, ':'); ++ if (lookup_name != NULL) ++ lookup_name++; ++ else ++ lookup_name = name; ++ ++ ASSERT(table != NULL); ++ ++ for (vi = table; vi->name; vi++) { ++ if (!strcmp(vi->name, lookup_name)) ++ return vi; ++ } ++ /* ran to end of table */ ++ ++ return NULL; /* var name not found */ ++} ++ ++int ++bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set) ++{ ++ int bcmerror = 0; ++ ++ /* length check on io buf */ ++ switch (vi->type) { ++ case IOVT_BOOL: ++ case IOVT_INT8: ++ case IOVT_INT16: ++ case IOVT_INT32: ++ case IOVT_UINT8: ++ case IOVT_UINT16: ++ case IOVT_UINT32: ++ /* all integers are int32 sized args at the ioctl interface */ ++ if (len < (int)sizeof(int)) { ++ bcmerror = BCME_BUFTOOSHORT; ++ } ++ break; ++ ++ case IOVT_BUFFER: ++ /* buffer must meet minimum length requirement */ ++ if (len < vi->minlen) { ++ bcmerror = BCME_BUFTOOSHORT; ++ } ++ break; ++ ++ case IOVT_VOID: ++ if (!set) { ++ /* Cannot return nil... */ ++ bcmerror = BCME_UNSUPPORTED; ++ } else if (len) { ++ /* Set is an action w/o parameters */ ++ bcmerror = BCME_BUFTOOLONG; ++ } ++ break; ++ ++ default: ++ /* unknown type for length check in iovar info */ ++ ASSERT(0); ++ bcmerror = BCME_UNSUPPORTED; ++ } ++ ++ return bcmerror; ++} ++ ++#endif /* BCMDRIVER */ ++ ++ ++/******************************************************************************* ++ * crc8 ++ * ++ * Computes a crc8 over the input data using the polynomial: ++ * ++ * x^8 + x^7 +x^6 + x^4 + x^2 + 1 ++ * ++ * The caller provides the initial value (either CRC8_INIT_VALUE ++ * or the previous returned value) to allow for processing of ++ * discontiguous blocks of data. When generating the CRC the ++ * caller is responsible for complementing the final return value ++ * and inserting it into the byte stream. When checking, a final ++ * return value of CRC8_GOOD_VALUE indicates a valid CRC. ++ * ++ * Reference: Dallas Semiconductor Application Note 27 ++ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", ++ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., ++ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt ++ * ++ * **************************************************************************** ++ */ ++ ++static const uint8 crc8_table[256] = { ++ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, ++ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, ++ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, ++ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, ++ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, ++ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, ++ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, ++ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, ++ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, ++ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, ++ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, ++ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, ++ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, ++ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, ++ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, ++ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, ++ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, ++ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, ++ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, ++ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, ++ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, ++ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, ++ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, ++ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, ++ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, ++ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, ++ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, ++ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, ++ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, ++ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, ++ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, ++ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F ++}; ++ ++#define CRC_INNER_LOOP(n, c, x) \ ++ (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] ++ ++uint8 ++BCMROMFN(hndcrc8)( ++ uint8 *pdata, /* pointer to array of data to process */ ++ uint nbytes, /* number of input data bytes to process */ ++ uint8 crc /* either CRC8_INIT_VALUE or previous return value */ ++) ++{ ++ /* hard code the crc loop instead of using CRC_INNER_LOOP macro ++ * to avoid the undefined and unnecessary (uint8 >> 8) operation. ++ */ ++ while (nbytes-- > 0) ++ crc = crc8_table[(crc ^ *pdata++) & 0xff]; ++ ++ return crc; ++} ++ ++/******************************************************************************* ++ * crc16 ++ * ++ * Computes a crc16 over the input data using the polynomial: ++ * ++ * x^16 + x^12 +x^5 + 1 ++ * ++ * The caller provides the initial value (either CRC16_INIT_VALUE ++ * or the previous returned value) to allow for processing of ++ * discontiguous blocks of data. When generating the CRC the ++ * caller is responsible for complementing the final return value ++ * and inserting it into the byte stream. When checking, a final ++ * return value of CRC16_GOOD_VALUE indicates a valid CRC. ++ * ++ * Reference: Dallas Semiconductor Application Note 27 ++ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", ++ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., ++ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt ++ * ++ * **************************************************************************** ++ */ ++ ++static const uint16 crc16_table[256] = { ++ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, ++ 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, ++ 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, ++ 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, ++ 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, ++ 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, ++ 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, ++ 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, ++ 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, ++ 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, ++ 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, ++ 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, ++ 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, ++ 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, ++ 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, ++ 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, ++ 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, ++ 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, ++ 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, ++ 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, ++ 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, ++ 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, ++ 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, ++ 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, ++ 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, ++ 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, ++ 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, ++ 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, ++ 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, ++ 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, ++ 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, ++ 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 ++}; ++ ++uint16 ++BCMROMFN(hndcrc16)( ++ uint8 *pdata, /* pointer to array of data to process */ ++ uint nbytes, /* number of input data bytes to process */ ++ uint16 crc /* either CRC16_INIT_VALUE or previous return value */ ++) ++{ ++ while (nbytes-- > 0) ++ CRC_INNER_LOOP(16, crc, *pdata++); ++ return crc; ++} ++ ++static const uint32 crc32_table[256] = { ++ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, ++ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, ++ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, ++ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, ++ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, ++ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, ++ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, ++ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, ++ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, ++ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, ++ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, ++ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, ++ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, ++ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, ++ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, ++ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, ++ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, ++ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, ++ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, ++ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, ++ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, ++ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, ++ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, ++ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, ++ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, ++ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, ++ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, ++ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, ++ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, ++ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, ++ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, ++ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, ++ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, ++ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, ++ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, ++ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, ++ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, ++ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, ++ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, ++ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, ++ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, ++ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, ++ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, ++ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, ++ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, ++ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, ++ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, ++ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, ++ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, ++ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, ++ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, ++ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, ++ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, ++ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, ++ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, ++ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, ++ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, ++ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, ++ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, ++ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, ++ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, ++ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, ++ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, ++ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D ++}; ++ ++/* ++ * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if ++ * accumulating over multiple pieces. ++ */ ++uint32 ++BCMROMFN(hndcrc32)(uint8 *pdata, uint nbytes, uint32 crc) ++{ ++ uint8 *pend; ++#ifdef __mips__ ++ uint8 tmp[4]; ++ ulong *tptr = (ulong *)tmp; ++ ++ if (nbytes > 3) { ++ /* in case the beginning of the buffer isn't aligned */ ++ pend = (uint8 *)((uint)(pdata + 3) & ~0x3); ++ nbytes -= (pend - pdata); ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); ++ } ++ ++ if (nbytes > 3) { ++ /* handle bulk of data as 32-bit words */ ++ pend = pdata + (nbytes & ~0x3); ++ while (pdata < pend) { ++ *tptr = *(ulong *)pdata; ++ pdata += sizeof(ulong *); ++ CRC_INNER_LOOP(32, crc, tmp[0]); ++ CRC_INNER_LOOP(32, crc, tmp[1]); ++ CRC_INNER_LOOP(32, crc, tmp[2]); ++ CRC_INNER_LOOP(32, crc, tmp[3]); ++ } ++ } ++ ++ /* 1-3 bytes at end of buffer */ ++ pend = pdata + (nbytes & 0x03); ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); ++#else ++ pend = pdata + nbytes; ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); ++#endif /* __mips__ */ ++ ++ return crc; ++} ++ ++#ifdef notdef ++#define CLEN 1499 /* CRC Length */ ++#define CBUFSIZ (CLEN+4) ++#define CNBUFS 5 /* # of bufs */ ++ ++void ++testcrc32(void) ++{ ++ uint j, k, l; ++ uint8 *buf; ++ uint len[CNBUFS]; ++ uint32 crcr; ++ uint32 crc32tv[CNBUFS] = ++ {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110}; ++ ++ ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL); ++ ++ /* step through all possible alignments */ ++ for (l = 0; l <= 4; l++) { ++ for (j = 0; j < CNBUFS; j++) { ++ len[j] = CLEN; ++ for (k = 0; k < len[j]; k++) ++ *(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff; ++ } ++ ++ for (j = 0; j < CNBUFS; j++) { ++ crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE); ++ ASSERT(crcr == crc32tv[j]); ++ } ++ } ++ ++ MFREE(buf, CBUFSIZ*CNBUFS); ++ return; ++} ++#endif /* notdef */ ++ ++/* ++ * Advance from the current 1-byte tag/1-byte length/variable-length value ++ * triple, to the next, returning a pointer to the next. ++ * If the current or next TLV is invalid (does not fit in given buffer length), ++ * NULL is returned. ++ * *buflen is not modified if the TLV elt parameter is invalid, or is decremented ++ * by the TLV parameter's length if it is valid. ++ */ ++bcm_tlv_t * ++BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen) ++{ ++ int len; ++ ++ /* validate current elt */ ++ if (!bcm_valid_tlv(elt, *buflen)) ++ return NULL; ++ ++ /* advance to next elt */ ++ len = elt->len; ++ elt = (bcm_tlv_t*)(elt->data + len); ++ *buflen -= (TLV_HDR_LEN + len); ++ ++ /* validate next elt */ ++ if (!bcm_valid_tlv(elt, *buflen)) ++ return NULL; ++ ++ return elt; ++} ++ ++/* ++ * Traverse a string of 1-byte tag/1-byte length/variable-length value ++ * triples, returning a pointer to the substring whose first element ++ * matches tag ++ */ ++bcm_tlv_t * ++BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key) ++{ ++ bcm_tlv_t *elt; ++ int totlen; ++ ++ elt = (bcm_tlv_t*)buf; ++ totlen = buflen; ++ ++ /* find tagged parameter */ ++ while (totlen >= TLV_HDR_LEN) { ++ int len = elt->len; ++ ++ /* validate remaining totlen */ ++ if ((elt->id == key) && ++ (totlen >= (len + TLV_HDR_LEN))) ++ return (elt); ++ ++ elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); ++ totlen -= (len + TLV_HDR_LEN); ++ } ++ ++ return NULL; ++} ++ ++/* ++ * Traverse a string of 1-byte tag/1-byte length/variable-length value ++ * triples, returning a pointer to the substring whose first element ++ * matches tag. Stop parsing when we see an element whose ID is greater ++ * than the target key. ++ */ ++bcm_tlv_t * ++BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key) ++{ ++ bcm_tlv_t *elt; ++ int totlen; ++ ++ elt = (bcm_tlv_t*)buf; ++ totlen = buflen; ++ ++ /* find tagged parameter */ ++ while (totlen >= TLV_HDR_LEN) { ++ uint id = elt->id; ++ int len = elt->len; ++ ++ /* Punt if we start seeing IDs > than target key */ ++ if (id > key) ++ return (NULL); ++ ++ /* validate remaining totlen */ ++ if ((id == key) && ++ (totlen >= (len + TLV_HDR_LEN))) ++ return (elt); ++ ++ elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); ++ totlen -= (len + TLV_HDR_LEN); ++ } ++ return NULL; ++} ++ ++#if defined(BCMDBG) || defined(BCMDBG_ERR) || defined(WLMSG_PRHDRS) || \ ++ defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || defined(DHD_DEBUG) ++int ++bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len) ++{ ++ int i; ++ char* p = buf; ++ char hexstr[16]; ++ int slen = 0, nlen = 0; ++ uint32 bit; ++ const char* name; ++ ++ if (len < 2 || !buf) ++ return 0; ++ ++ buf[0] = '\0'; ++ ++ for (i = 0; flags != 0; i++) { ++ bit = bd[i].bit; ++ name = bd[i].name; ++ if (bit == 0 && flags != 0) { ++ /* print any unnamed bits */ ++ snprintf(hexstr, 16, "0x%X", flags); ++ name = hexstr; ++ flags = 0; /* exit loop */ ++ } else if ((flags & bit) == 0) ++ continue; ++ flags &= ~bit; ++ nlen = strlen(name); ++ slen += nlen; ++ /* count btwn flag space */ ++ if (flags != 0) ++ slen += 1; ++ /* need NULL char as well */ ++ if (len <= slen) ++ break; ++ /* copy NULL char but don't count it */ ++ strncpy(p, name, nlen + 1); ++ p += nlen; ++ /* copy btwn flag space and NULL char */ ++ if (flags != 0) ++ p += snprintf(p, 2, " "); ++ } ++ ++ /* indicate the str was too short */ ++ if (flags != 0) { ++ if (len < 2) ++ p -= 2 - len; /* overwrite last char */ ++ p += snprintf(p, 2, ">"); ++ } ++ ++ return (int)(p - buf); ++} ++ ++/* print bytes formatted as hex to a string. return the resulting string length */ ++int ++bcm_format_hex(char *str, const void *bytes, int len) ++{ ++ int i; ++ char *p = str; ++ const uint8 *src = (const uint8*)bytes; ++ ++ for (i = 0; i < len; i++) { ++ p += snprintf(p, 3, "%02X", *src); ++ src++; ++ } ++ return (int)(p - str); ++} ++#endif ++ ++/* pretty hex print a contiguous buffer */ ++void ++prhex(const char *msg, uchar *buf, uint nbytes) ++{ ++ char line[128], *p; ++ int len = sizeof(line); ++ int nchar; ++ uint i; ++ ++ if (msg && (msg[0] != '\0')) ++ printf("%s:\n", msg); ++ ++ p = line; ++ for (i = 0; i < nbytes; i++) { ++ if (i % 16 == 0) { ++ nchar = snprintf(p, len, " %04d: ", i); /* line prefix */ ++ p += nchar; ++ len -= nchar; ++ } ++ if (len > 0) { ++ nchar = snprintf(p, len, "%02x ", buf[i]); ++ p += nchar; ++ len -= nchar; ++ } ++ ++ if (i % 16 == 15) { ++ printf("%s\n", line); /* flush line */ ++ p = line; ++ len = sizeof(line); ++ } ++ } ++ ++ /* flush last partial line */ ++ if (p != line) ++ printf("%s\n", line); ++} ++ ++static const char *crypto_algo_names[] = { ++ "NONE", ++ "WEP1", ++ "TKIP", ++ "WEP128", ++ "AES_CCM", ++ "AES_OCB_MSDU", ++ "AES_OCB_MPDU", ++ "NALG" ++ "UNDEF", ++ "UNDEF", ++ "UNDEF", ++ "UNDEF" ++}; ++ ++const char * ++bcm_crypto_algo_name(uint algo) ++{ ++ return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR"; ++} ++ ++#ifdef BCMDBG ++void ++deadbeef(void *p, size_t len) ++{ ++ static uint8 meat[] = { 0xde, 0xad, 0xbe, 0xef }; ++ ++ while (len-- > 0) { ++ *(uint8*)p = meat[((uintptr)p) & 3]; ++ p = (uint8*)p + 1; ++ } ++} ++#endif /* BCMDBG */ ++ ++char * ++bcm_chipname(uint chipid, char *buf, uint len) ++{ ++ const char *fmt; ++ ++ fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x"; ++ snprintf(buf, len, fmt, chipid); ++ return buf; ++} ++ ++/* Produce a human-readable string for boardrev */ ++char * ++bcm_brev_str(uint32 brev, char *buf) ++{ ++ if (brev < 0x100) ++ snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf); ++ else ++ snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff); ++ ++ return (buf); ++} ++ ++#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */ ++ ++/* dump large strings to console */ ++void ++printbig(char *buf) ++{ ++ uint len, max_len; ++ char c; ++ ++ len = strlen(buf); ++ ++ max_len = BUFSIZE_TODUMP_ATONCE; ++ ++ while (len > max_len) { ++ c = buf[max_len]; ++ buf[max_len] = '\0'; ++ printf("%s", buf); ++ buf[max_len] = c; ++ ++ buf += max_len; ++ len -= max_len; ++ } ++ /* print the remaining string */ ++ printf("%s\n", buf); ++ return; ++} ++ ++/* routine to dump fields in a fileddesc structure */ ++uint ++bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array, ++ char *buf, uint32 bufsize) ++{ ++ uint filled_len; ++ int len; ++ struct fielddesc *cur_ptr; ++ ++ filled_len = 0; ++ cur_ptr = fielddesc_array; ++ ++ while (bufsize > 1) { ++ if (cur_ptr->nameandfmt == NULL) ++ break; ++ len = snprintf(buf, bufsize, cur_ptr->nameandfmt, ++ read_rtn(arg0, arg1, cur_ptr->offset)); ++ /* check for snprintf overflow or error */ ++ if (len < 0 || (uint32)len >= bufsize) ++ len = bufsize - 1; ++ buf += len; ++ bufsize -= len; ++ filled_len += len; ++ cur_ptr++; ++ } ++ return filled_len; ++} ++ ++uint ++bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) ++{ ++ uint len; ++ ++ len = strlen(name) + 1; ++ ++ if ((len + datalen) > buflen) ++ return 0; ++ ++ strncpy(buf, name, buflen); ++ ++ /* append data onto the end of the name string */ ++ memcpy(&buf[len], data, datalen); ++ len += datalen; ++ ++ return len; ++} ++ ++/* Quarter dBm units to mW ++ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 ++ * Table is offset so the last entry is largest mW value that fits in ++ * a uint16. ++ */ ++ ++#define QDBM_OFFSET 153 /* Offset for first entry */ ++#define QDBM_TABLE_LEN 40 /* Table size */ ++ ++/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. ++ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 ++ */ ++#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ ++ ++/* Largest mW value that will round down to the last table entry, ++ * QDBM_OFFSET + QDBM_TABLE_LEN-1. ++ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. ++ */ ++#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ ++ ++static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { ++/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ ++/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, ++/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, ++/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, ++/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, ++/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 ++}; ++ ++uint16 ++BCMROMFN(bcm_qdbm_to_mw)(uint8 qdbm) ++{ ++ uint factor = 1; ++ int idx = qdbm - QDBM_OFFSET; ++ ++ if (idx >= QDBM_TABLE_LEN) { ++ /* clamp to max uint16 mW value */ ++ return 0xFFFF; ++ } ++ ++ /* scale the qdBm index up to the range of the table 0-40 ++ * where an offset of 40 qdBm equals a factor of 10 mW. ++ */ ++ while (idx < 0) { ++ idx += 40; ++ factor *= 10; ++ } ++ ++ /* return the mW value scaled down to the correct factor of 10, ++ * adding in factor/2 to get proper rounding. ++ */ ++ return ((nqdBm_to_mW_map[idx] + factor/2) / factor); ++} ++ ++uint8 ++BCMROMFN(bcm_mw_to_qdbm)(uint16 mw) ++{ ++ uint8 qdbm; ++ int offset; ++ uint mw_uint = mw; ++ uint boundary; ++ ++ /* handle boundary case */ ++ if (mw_uint <= 1) ++ return 0; ++ ++ offset = QDBM_OFFSET; ++ ++ /* move mw into the range of the table */ ++ while (mw_uint < QDBM_TABLE_LOW_BOUND) { ++ mw_uint *= 10; ++ offset -= 40; ++ } ++ ++ for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) { ++ boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] - ++ nqdBm_to_mW_map[qdbm])/2; ++ if (mw_uint < boundary) break; ++ } ++ ++ qdbm += (uint8)offset; ++ ++ return (qdbm); ++} ++ ++ ++uint ++BCMROMFN(bcm_bitcount)(uint8 *bitmap, uint length) ++{ ++ uint bitcount = 0, i; ++ uint8 tmp; ++ for (i = 0; i < length; i++) { ++ tmp = bitmap[i]; ++ while (tmp) { ++ bitcount++; ++ tmp &= (tmp - 1); ++ } ++ } ++ return bitcount; ++} ++ ++#ifdef BCMDRIVER ++ ++/* Initialization of bcmstrbuf structure */ ++void ++bcm_binit(struct bcmstrbuf *b, char *buf, uint size) ++{ ++ b->origsize = b->size = size; ++ b->origbuf = b->buf = buf; ++} ++ ++/* Buffer sprintf wrapper to guard against buffer overflow */ ++int ++bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...) ++{ ++ va_list ap; ++ int r; ++ ++ va_start(ap, fmt); ++ ++ r = vsnprintf(b->buf, b->size, fmt, ap); ++ ++ /* Non Ansi C99 compliant returns -1, ++ * Ansi compliant return r >= b->size, ++ * bcmstdlib returns 0, handle all ++ */ ++ /* r == 0 is also the case when strlen(fmt) is zero. ++ * typically the case when "" is passed as argument. ++ */ ++ if ((r == -1) || (r >= (int)b->size)) { ++ b->size = 0; ++ } else { ++ b->size -= r; ++ b->buf += r; ++ } ++ ++ va_end(ap); ++ ++ return r; ++} ++ ++void ++bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len) ++{ ++ int i; ++ ++ if (msg != NULL && msg[0] != '\0') ++ bcm_bprintf(b, "%s", msg); ++ for (i = 0; i < len; i ++) ++ bcm_bprintf(b, "%02X", buf[i]); ++ if (newline) ++ bcm_bprintf(b, "\n"); ++} ++ ++void ++bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount) ++{ ++ int i; ++ ++ for (i = 0; i < num_bytes; i++) { ++ num[i] += amount; ++ if (num[i] >= amount) ++ break; ++ amount = 1; ++ } ++} ++ ++int ++bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes) ++{ ++ int i; ++ ++ for (i = nbytes - 1; i >= 0; i--) { ++ if (arg1[i] != arg2[i]) ++ return (arg1[i] - arg2[i]); ++ } ++ return 0; ++} ++ ++void ++bcm_print_bytes(const char *name, const uchar *data, int len) ++{ ++ int i; ++ int per_line = 0; ++ ++ printf("%s: %d \n", name ? name : "", len); ++ for (i = 0; i < len; i++) { ++ printf("%02x ", *data++); ++ per_line++; ++ if (per_line == 16) { ++ per_line = 0; ++ printf("\n"); ++ } ++ } ++ printf("\n"); ++} ++#if defined(WLTINYDUMP) || defined(BCMDBG) || defined(WLMSG_INFORM) || \ ++ defined(WLMSG_ASSOC) || defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) ++#define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1) ++ ++int ++bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len) ++{ ++ uint i, c; ++ char *p = buf; ++ char *endp = buf + SSID_FMT_BUF_LEN; ++ ++ if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN; ++ ++ for (i = 0; i < ssid_len; i++) { ++ c = (uint)ssid[i]; ++ if (c == '\\') { ++ *p++ = '\\'; ++ *p++ = '\\'; ++ } else if (bcm_isprint((uchar)c)) { ++ *p++ = (char)c; ++ } else { ++ p += snprintf(p, (endp - p), "\\x%02X", c); ++ } ++ } ++ *p = '\0'; ++ ASSERT(p < endp); ++ ++ return (int)(p - buf); ++} ++#endif /* WLTINYDUMP || BCMDBG || WLMSG_INFORM || WLMSG_ASSOC || WLMSG_PRPKT */ ++ ++#endif /* BCMDRIVER */ ++ ++/* ++ * ProcessVars:Takes a buffer of "=\n" lines read from a file and ending in a NUL. ++ * also accepts nvram files which are already in the format of =\0\=\0 ++ * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs. ++ * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs. ++*/ ++ ++unsigned int ++process_nvram_vars(char *varbuf, unsigned int len) ++{ ++ char *dp; ++ bool findNewline; ++ int column; ++ unsigned int buf_len, n; ++ unsigned int pad = 0; ++ ++ dp = varbuf; ++ ++ findNewline = FALSE; ++ column = 0; ++ ++ for (n = 0; n < len; n++) { ++ if (varbuf[n] == '\r') ++ continue; ++ if (findNewline && varbuf[n] != '\n') ++ continue; ++ findNewline = FALSE; ++ if (varbuf[n] == '#') { ++ findNewline = TRUE; ++ continue; ++ } ++ if (varbuf[n] == '\n') { ++ if (column == 0) ++ continue; ++ *dp++ = 0; ++ column = 0; ++ continue; ++ } ++ *dp++ = varbuf[n]; ++ column++; ++ } ++ buf_len = (unsigned int)(dp - varbuf); ++ if (buf_len % 4) { ++ pad = 4 - buf_len % 4; ++ if (pad && (buf_len + pad <= len)) { ++ buf_len += pad; ++ } ++ } ++ ++ while (dp < varbuf + n) ++ *dp++ = 0; ++ ++ return buf_len; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/hnddma.c b/drivers/bcmdrivers/gmac/src/shared/hnddma.c +new file mode 100755 +index 0000000..2463d1f +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hnddma.c +@@ -0,0 +1,3569 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Generic Broadcom Home Networking Division (HND) DMA module. ++ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * ++ * $Id: hnddma.c 328477 2012-04-19 10:57:54Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++#include ++#endif ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_RWREG_OPT ++#ifdef R_REG ++#undef R_REG ++#define R_REG(osh, r) (\ ++ sizeof(*(r)) == sizeof(uint8) ? (*(volatile unsigned char __force *)(r)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? (*(volatile unsigned short __force *)(r)) : \ ++ (*(volatile unsigned int __force *)(r)) \ ++) ++#endif /* R_REG */ ++ ++#ifdef W_REG ++#undef W_REG ++#define W_REG(osh, r, v) (\ ++ sizeof(*(r)) == sizeof(uint8) ? (*(volatile unsigned char __force *)(r) = (v)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? (*(volatile unsigned short __force *)(r) = (v)) : \ ++ (*(volatile unsigned int __force *)(r) = (v)) \ ++) ++#endif /* W_REG */ ++#endif /* CONFIG_BCM_IPROC_GMAC_RWREG_OPT */ ++ ++/* debug/trace */ ++#ifdef BCMDBG ++#define DMA_ERROR(args) if (!(*di->msg_level & 1)); else printf args ++#define DMA_TRACE(args) if (!(*di->msg_level & 2)); else printf args ++#elif defined(BCMDBG_ERR) ++#define DMA_ERROR(args) if (!(*di->msg_level & 1)); else printf args ++#define DMA_TRACE(args) ++#else ++#define DMA_ERROR(args) ++#define DMA_TRACE(args) ++#endif /* BCMDBG */ ++ ++#define DMA_NONE(args) ++ ++ ++#define d32txregs dregs.d32_u.txregs_32 ++#define d32rxregs dregs.d32_u.rxregs_32 ++#define txd32 dregs.d32_u.txd_32 ++#define rxd32 dregs.d32_u.rxd_32 ++ ++#define d64txregs dregs.d64_u.txregs_64 ++#define d64rxregs dregs.d64_u.rxregs_64 ++#define txd64 dregs.d64_u.txd_64 ++#define rxd64 dregs.d64_u.rxd_64 ++ ++#define DBG(x...) printk(KERN_ERR x) ++ ++/* default dma message level (if input msg_level pointer is null in dma_attach()) */ ++static uint dma_msg_level = ++#ifdef BCMDBG_ERR ++ 1; ++#else ++ 0; ++#endif /* BCMDBG_ERR */ ++ ++#define MAXNAMEL 8 /* 8 char names */ ++ ++#define DI_INFO(dmah) ((dma_info_t *)dmah) ++ ++/* dma engine software state */ ++typedef struct dma_info { ++ struct hnddma_pub hnddma; /* exported structure, don't use hnddma_t, ++ * which could be const ++ */ ++ uint *msg_level; /* message level pointer */ ++ char name[MAXNAMEL]; /* callers name for diag msgs */ ++ ++ void *osh; /* os handle */ ++ si_t *sih; /* sb handle */ ++ ++ bool dma64; /* this dma engine is operating in 64-bit mode */ ++ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ ++ ++ union { ++ struct { ++ dma32regs_t *txregs_32; /* 32-bit dma tx engine registers */ ++ dma32regs_t *rxregs_32; /* 32-bit dma rx engine registers */ ++ dma32dd_t *txd_32; /* pointer to dma32 tx descriptor ring */ ++ dma32dd_t *rxd_32; /* pointer to dma32 rx descriptor ring */ ++ } d32_u; ++ struct { ++ dma64regs_t *txregs_64; /* 64-bit dma tx engine registers */ ++ dma64regs_t *rxregs_64; /* 64-bit dma rx engine registers */ ++ dma64dd_t *txd_64; /* pointer to dma64 tx descriptor ring */ ++ dma64dd_t *rxd_64; /* pointer to dma64 rx descriptor ring */ ++ } d64_u; ++ } dregs; ++ ++ uint16 dmadesc_align; /* alignment requirement for dma descriptors */ ++ ++ uint16 ntxd; /* # tx descriptors tunable */ ++ uint16 txin; /* index of next descriptor to reclaim */ ++ uint16 txout; /* index of next descriptor to post */ ++ void **txp; /* pointer to parallel array of pointers to packets */ ++ osldma_t *tx_dmah; /* DMA TX descriptor ring handle */ ++ hnddma_seg_map_t *txp_dmah; /* DMA MAP meta-data handle */ ++ dmaaddr_t txdpa; /* Aligned physical address of descriptor ring */ ++ dmaaddr_t txdpaorig; /* Original physical address of descriptor ring */ ++ uint16 txdalign; /* #bytes added to alloc'd mem to align txd */ ++ uint32 txdalloc; /* #bytes allocated for the ring */ ++ uint32 xmtptrbase; /* When using unaligned descriptors, the ptr register ++ * is not just an index, it needs all 13 bits to be ++ * an offset from the addr register. ++ */ ++ ++ uint16 nrxd; /* # rx descriptors tunable */ ++ uint16 rxin; /* index of next descriptor to reclaim */ ++ uint16 rxout; /* index of next descriptor to post */ ++ void **rxp; /* pointer to parallel array of pointers to packets */ ++ osldma_t *rx_dmah; /* DMA RX descriptor ring handle */ ++ hnddma_seg_map_t *rxp_dmah; /* DMA MAP meta-data handle */ ++ dmaaddr_t rxdpa; /* Aligned physical address of descriptor ring */ ++ dmaaddr_t rxdpaorig; /* Original physical address of descriptor ring */ ++ uint16 rxdalign; /* #bytes added to alloc'd mem to align rxd */ ++ uint32 rxdalloc; /* #bytes allocated for the ring */ ++ uint32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */ ++ ++ /* tunables */ ++ uint16 rxbufsize; /* rx buffer size in bytes, ++ * not including the extra headroom ++ */ ++ uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper stack ++ * e.g. some rx pkt buffers will be bridged to tx side ++ * without byte copying. The extra headroom needs to be ++ * large enough to fit txheader needs. ++ * Some dongle driver may not need it. ++ */ ++ uint nrxpost; /* # rx buffers to keep posted */ ++ uint rxoffset; /* rxcontrol offset */ ++ uint ddoffsetlow; /* add to get dma address of descriptor ring, low 32 bits */ ++ uint ddoffsethigh; /* high 32 bits */ ++ uint dataoffsetlow; /* add to get dma address of data buffer, low 32 bits */ ++ uint dataoffsethigh; /* high 32 bits */ ++ bool aligndesc_4k; /* descriptor base need to be aligned or not */ ++ uint8 rxburstlen; /* burstlen field for rx (for cores supporting burstlen) */ ++ uint8 txburstlen; /* burstlen field for tx (for cores supporting burstlen) */ ++ uint8 txmultioutstdrd; /* tx multiple outstanding reads */ ++ uint8 txprefetchctl; /* prefetch control for tx */ ++ uint8 txprefetchthresh; /* prefetch threshold for tx */ ++ uint8 rxprefetchctl; /* prefetch control for rx */ ++ uint8 rxprefetchthresh; /* prefetch threshold for rx */ ++ pktpool_t *pktpool; /* pktpool */ ++ uint dma_avoidance_cnt; ++ ++ uint32 d64_xs0_cd_mask; /* tx current descriptor pointer mask */ ++ uint32 d64_xs1_ad_mask; /* tx active descriptor mask */ ++ uint32 d64_rs0_cd_mask; /* rx current descriptor pointer mask */ ++ uint16 rs0cd; /* cached value of rcvstatus0 currdescr */ ++ uint16 xs0cd; /* cached value of xmtstatus0 currdescr */ ++ uint16 xs0cd_snapshot; /* snapshot of xmtstatus0 currdescr */ ++ spinlock_t des_lock; ++} dma_info_t; ++ ++/* ++ * If BCMDMA32 is defined, hnddma will support both 32-bit and 64-bit DMA engines. ++ * Otherwise it will support only 64-bit. ++ * ++ * DMA32_ENAB indicates whether hnddma is compiled with support for 32-bit DMA engines. ++ * DMA64_ENAB indicates whether hnddma is compiled with support for 64-bit DMA engines. ++ * ++ * DMA64_MODE indicates whether the current DMA engine is running as 64-bit. ++ */ ++#ifdef BCMDMA32 ++#define DMA32_ENAB(di) 1 ++#define DMA64_ENAB(di) 1 ++#define DMA64_MODE(di) ((di)->dma64) ++#else /* !BCMDMA32 */ ++#define DMA32_ENAB(di) 0 ++#define DMA64_ENAB(di) 1 ++#define DMA64_MODE(di) 1 ++#endif /* !BCMDMA32 */ ++ ++/* DMA Scatter-gather list is supported. Note this is limited to TX direction only */ ++#ifdef BCMDMASGLISTOSL ++#define DMASGLIST_ENAB TRUE ++#else ++#define DMASGLIST_ENAB FALSE ++#endif /* BCMDMASGLISTOSL */ ++ ++/* descriptor bumping macros */ ++#define XXD(x, n) ((x) & ((n) - 1)) /* faster than %, but n must be power of 2 */ ++#define TXD(x) XXD((x), di->ntxd) ++#define RXD(x) XXD((x), di->nrxd) ++#define NEXTTXD(i) TXD((i) + 1) ++#define PREVTXD(i) TXD((i) - 1) ++#define NEXTRXD(i) RXD((i) + 1) ++#define PREVRXD(i) RXD((i) - 1) ++ ++#define NTXDACTIVE(h, t) TXD((t) - (h)) ++#define NRXDACTIVE(h, t) RXD((t) - (h)) ++ ++/* macros to convert between byte offsets and indexes */ ++#define B2I(bytes, type) ((uint16)((bytes) / sizeof(type))) ++#define I2B(index, type) ((index) * sizeof(type)) ++ ++#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ ++#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */ ++ ++#define PCI64ADDR_HIGH 0x80000000 /* address[63] */ ++#define PCI64ADDR_HIGH_SHIFT 31 /* address[63] */ ++ ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++#define SKB_PREFETCH_LEN (128) ++#endif ++ ++/* Common prototypes */ ++static bool _dma_isaddrext(dma_info_t *di); ++static bool _dma_descriptor_align(dma_info_t *di); ++static bool _dma_alloc(dma_info_t *di, uint direction); ++static void _dma_detach(dma_info_t *di); ++static void _dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa); ++static void _dma_rxinit(dma_info_t *di); ++static void *_dma_rx(dma_info_t *di); ++static bool _dma_rxfill(dma_info_t *di); ++static void _dma_rxreclaim(dma_info_t *di); ++static void _dma_rxenable(dma_info_t *di); ++static void *_dma_getnextrxp(dma_info_t *di, bool forceall); ++static void _dma_rx_param_get(dma_info_t *di, uint16 *rxoffset, uint16 *rxbufsize); ++ ++static void _dma_txblock(dma_info_t *di); ++static void _dma_txunblock(dma_info_t *di); ++static uint _dma_txactive(dma_info_t *di); ++static uint _dma_rxactive(dma_info_t *di); ++static uint _dma_activerxbuf(dma_info_t *di); ++static uint _dma_txpending(dma_info_t *di); ++static uint _dma_txcommitted(dma_info_t *di); ++ ++static void *_dma_peeknexttxp(dma_info_t *di); ++static int _dma_peekntxp(dma_info_t *di, int *len, void *txps[], txd_range_t range); ++static void *_dma_peeknextrxp(dma_info_t *di); ++static uintptr _dma_getvar(dma_info_t *di, const char *name); ++static void _dma_counterreset(dma_info_t *di); ++static void _dma_fifoloopbackenable(dma_info_t *di); ++static uint _dma_ctrlflags(dma_info_t *di, uint mask, uint flags); ++static uint8 dma_align_sizetobits(uint size); ++static void *dma_ringalloc(osl_t *osh, uint32 boundary, uint size, uint16 *alignbits, uint* alloced, ++ dmaaddr_t *descpa, osldma_t **dmah); ++static int _dma_pktpool_set(dma_info_t *di, pktpool_t *pool); ++static bool _dma_rxtx_error(dma_info_t *di, bool istx); ++static void _dma_burstlen_set(dma_info_t *di, uint8 rxburstlen, uint8 txburstlen); ++static uint _dma_avoidancecnt(dma_info_t *di); ++static void _dma_param_set(dma_info_t *di, uint16 paramid, uint16 paramval); ++static bool _dma_glom_enable(dma_info_t *di, uint32 val); ++ ++ ++/* Prototypes for 32-bit routines */ ++static bool dma32_alloc(dma_info_t *di, uint direction); ++static bool dma32_txreset(dma_info_t *di); ++static bool dma32_rxreset(dma_info_t *di); ++static bool dma32_txsuspendedidle(dma_info_t *di); ++static int dma32_txfast(dma_info_t *di, void *p0, bool commit); ++static void *dma32_getnexttxp(dma_info_t *di, txd_range_t range); ++static void *dma32_getnextrxp(dma_info_t *di, bool forceall); ++static void dma32_txrotate(dma_info_t *di); ++static bool dma32_rxidle(dma_info_t *di); ++static void dma32_txinit(dma_info_t *di); ++static bool dma32_txenabled(dma_info_t *di); ++static void dma32_txsuspend(dma_info_t *di); ++static void dma32_txresume(dma_info_t *di); ++static bool dma32_txsuspended(dma_info_t *di); ++#ifdef WL_MULTIQUEUE ++static void dma32_txflush(dma_info_t *di); ++static void dma32_txflush_clear(dma_info_t *di); ++#endif /* WL_MULTIQUEUE */ ++static void dma32_txreclaim(dma_info_t *di, txd_range_t range); ++static bool dma32_txstopped(dma_info_t *di); ++static bool dma32_rxstopped(dma_info_t *di); ++static bool dma32_rxenabled(dma_info_t *di); ++#if defined(BCMDBG) ++static void dma32_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma32dd_t *ring, uint start, ++ uint end, uint max_num); ++static void dma32_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++static void dma32_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++static void dma32_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++#endif ++ ++static bool _dma32_addrext(osl_t *osh, dma32regs_t *dma32regs); ++ ++/* Prototypes for 64-bit routines */ ++static bool dma64_alloc(dma_info_t *di, uint direction); ++static bool dma64_txreset(dma_info_t *di); ++static bool dma64_rxreset(dma_info_t *di); ++static bool dma64_txsuspendedidle(dma_info_t *di); ++static int dma64_txfast(dma_info_t *di, void *p0, bool commit); ++static int dma64_txunframed(dma_info_t *di, void *p0, uint len, bool commit); ++static void *dma64_getpos(dma_info_t *di, bool direction); ++static void *dma64_getnexttxp(dma_info_t *di, txd_range_t range); ++static void *dma64_getnextrxp(dma_info_t *di, bool forceall); ++static void dma64_txrotate(dma_info_t *di); ++ ++static bool dma64_rxidle(dma_info_t *di); ++static void dma64_txinit(dma_info_t *di); ++static bool dma64_txenabled(dma_info_t *di); ++static void dma64_txsuspend(dma_info_t *di); ++static void dma64_txresume(dma_info_t *di); ++static bool dma64_txsuspended(dma_info_t *di); ++#ifdef WL_MULTIQUEUE ++static void dma64_txflush(dma_info_t *di); ++static void dma64_txflush_clear(dma_info_t *di); ++#endif /* WL_MULTIQUEUE */ ++static void dma64_txreclaim(dma_info_t *di, txd_range_t range); ++static bool dma64_txstopped(dma_info_t *di); ++static bool dma64_rxstopped(dma_info_t *di); ++static bool dma64_rxenabled(dma_info_t *di); ++static bool _dma64_addrext(osl_t *osh, dma64regs_t *dma64regs); ++static int dma64_rxunframed(dma_info_t *di, void *p0, uint len, bool commit); ++ ++STATIC INLINE uint32 parity32(uint32 data); ++ ++#if defined(BCMDBG) ++static void dma64_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma64dd_t *ring, uint start, ++ uint end, uint max_num); ++static void dma64_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++static void dma64_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++static void dma64_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++#endif ++ ++ ++const di_fcn_t dma64proc = { ++ (di_detach_t)_dma_detach, ++ (di_txinit_t)dma64_txinit, ++ (di_txreset_t)dma64_txreset, ++ (di_txenabled_t)dma64_txenabled, ++ (di_txsuspend_t)dma64_txsuspend, ++ (di_txresume_t)dma64_txresume, ++ (di_txsuspended_t)dma64_txsuspended, ++ (di_txsuspendedidle_t)dma64_txsuspendedidle, ++#ifdef WL_MULTIQUEUE ++ (di_txflush_t)dma64_txflush, ++ (di_txflush_clear_t)dma64_txflush_clear, ++#endif /* WL_MULTIQUEUE */ ++ (di_txfast_t)dma64_txfast, ++ (di_txunframed_t)dma64_txunframed, ++ (di_getpos_t)dma64_getpos, ++ (di_txstopped_t)dma64_txstopped, ++ (di_txreclaim_t)dma64_txreclaim, ++ (di_getnexttxp_t)dma64_getnexttxp, ++ (di_peeknexttxp_t)_dma_peeknexttxp, ++ (di_peekntxp_t)_dma_peekntxp, ++ (di_txblock_t)_dma_txblock, ++ (di_txunblock_t)_dma_txunblock, ++ (di_txactive_t)_dma_txactive, ++ (di_txrotate_t)dma64_txrotate, ++ ++ (di_rxinit_t)_dma_rxinit, ++ (di_rxreset_t)dma64_rxreset, ++ (di_rxidle_t)dma64_rxidle, ++ (di_rxstopped_t)dma64_rxstopped, ++ (di_rxenable_t)_dma_rxenable, ++ (di_rxenabled_t)dma64_rxenabled, ++ (di_rx_t)_dma_rx, ++ (di_rxfill_t)_dma_rxfill, ++ (di_rxreclaim_t)_dma_rxreclaim, ++ (di_getnextrxp_t)_dma_getnextrxp, ++ (di_peeknextrxp_t)_dma_peeknextrxp, ++ (di_rxparam_get_t)_dma_rx_param_get, ++ ++ (di_fifoloopbackenable_t)_dma_fifoloopbackenable, ++ (di_getvar_t)_dma_getvar, ++ (di_counterreset_t)_dma_counterreset, ++ (di_ctrlflags_t)_dma_ctrlflags, ++ ++#if defined(BCMDBG) ++ (di_dump_t)dma64_dump, ++ (di_dumptx_t)dma64_dumptx, ++ (di_dumprx_t)dma64_dumprx, ++#else ++ NULL, ++ NULL, ++ NULL, ++#endif ++ (di_rxactive_t)_dma_rxactive, ++ (di_txpending_t)_dma_txpending, ++ (di_txcommitted_t)_dma_txcommitted, ++ (di_pktpool_set_t)_dma_pktpool_set, ++ (di_rxtxerror_t)_dma_rxtx_error, ++ (di_burstlen_set_t)_dma_burstlen_set, ++ (di_avoidancecnt_t)_dma_avoidancecnt, ++ (di_param_set_t)_dma_param_set, ++ (dma_glom_enable_t)_dma_glom_enable, ++ (di_rxunframed_t)dma64_rxunframed, ++ (dma_active_rxbuf_t)_dma_activerxbuf, ++ 40 ++}; ++ ++static const di_fcn_t dma32proc = { ++ (di_detach_t)_dma_detach, ++ (di_txinit_t)dma32_txinit, ++ (di_txreset_t)dma32_txreset, ++ (di_txenabled_t)dma32_txenabled, ++ (di_txsuspend_t)dma32_txsuspend, ++ (di_txresume_t)dma32_txresume, ++ (di_txsuspended_t)dma32_txsuspended, ++ (di_txsuspendedidle_t)dma32_txsuspendedidle, ++#ifdef WL_MULTIQUEUE ++ (di_txflush_t)dma32_txflush, ++ (di_txflush_clear_t)dma32_txflush_clear, ++#endif /* WL_MULTIQUEUE */ ++ (di_txfast_t)dma32_txfast, ++ NULL, ++ NULL, ++ (di_txstopped_t)dma32_txstopped, ++ (di_txreclaim_t)dma32_txreclaim, ++ (di_getnexttxp_t)dma32_getnexttxp, ++ (di_peeknexttxp_t)_dma_peeknexttxp, ++ (di_peekntxp_t)_dma_peekntxp, ++ (di_txblock_t)_dma_txblock, ++ (di_txunblock_t)_dma_txunblock, ++ (di_txactive_t)_dma_txactive, ++ (di_txrotate_t)dma32_txrotate, ++ ++ (di_rxinit_t)_dma_rxinit, ++ (di_rxreset_t)dma32_rxreset, ++ (di_rxidle_t)dma32_rxidle, ++ (di_rxstopped_t)dma32_rxstopped, ++ (di_rxenable_t)_dma_rxenable, ++ (di_rxenabled_t)dma32_rxenabled, ++ (di_rx_t)_dma_rx, ++ (di_rxfill_t)_dma_rxfill, ++ (di_rxreclaim_t)_dma_rxreclaim, ++ (di_getnextrxp_t)_dma_getnextrxp, ++ (di_peeknextrxp_t)_dma_peeknextrxp, ++ (di_rxparam_get_t)_dma_rx_param_get, ++ ++ (di_fifoloopbackenable_t)_dma_fifoloopbackenable, ++ (di_getvar_t)_dma_getvar, ++ (di_counterreset_t)_dma_counterreset, ++ (di_ctrlflags_t)_dma_ctrlflags, ++ ++#if defined(BCMDBG) ++ (di_dump_t)dma32_dump, ++ (di_dumptx_t)dma32_dumptx, ++ (di_dumprx_t)dma32_dumprx, ++#else ++ NULL, ++ NULL, ++ NULL, ++#endif ++ (di_rxactive_t)_dma_rxactive, ++ (di_txpending_t)_dma_txpending, ++ (di_txcommitted_t)_dma_txcommitted, ++ (di_pktpool_set_t)_dma_pktpool_set, ++ (di_rxtxerror_t)_dma_rxtx_error, ++ (di_burstlen_set_t)_dma_burstlen_set, ++ (di_avoidancecnt_t)_dma_avoidancecnt, ++ (di_param_set_t)_dma_param_set, ++ NULL, ++ NULL, ++ NULL, ++ 40 ++}; ++ ++EXPORT_SYMBOL(dma_attach); ++EXPORT_SYMBOL(dma64proc); ++ ++hnddma_t * ++dma_attach(osl_t *osh, const char *name, si_t *sih, ++ volatile void *dmaregstx, volatile void *dmaregsrx, ++ uint ntxd, uint nrxd, uint rxbufsize, int rxextheadroom, uint nrxpost, uint rxoffset, ++ uint *msg_level) ++{ ++ dma_info_t *di; ++ uint size; ++ uint32 mask; ++ ++ /* allocate private info structure */ ++ if ((di = MALLOC(osh, sizeof (dma_info_t))) == NULL) { ++#ifdef BCMDBG ++ DMA_ERROR(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh))); ++#endif ++ return (NULL); ++ } ++ ++ bzero(di, sizeof(dma_info_t)); ++ ++ di->msg_level = msg_level ? msg_level : &dma_msg_level; ++ spin_lock_init(&di->des_lock); ++ ++ /* old chips w/o sb is no longer supported */ ++ ASSERT(sih != NULL); ++ ++ if (DMA64_ENAB(di)) ++ di->dma64 = ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64); ++ else ++ di->dma64 = 0; ++ ++ /* check arguments */ ++ ASSERT(ISPOWEROF2(ntxd)); ++ ASSERT(ISPOWEROF2(nrxd)); ++ ++ if (nrxd == 0) ++ ASSERT(dmaregsrx == NULL); ++ if (ntxd == 0) ++ ASSERT(dmaregstx == NULL); ++ ++ /* init dma reg pointer */ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ di->d64txregs = (dma64regs_t *)dmaregstx; ++ di->d64rxregs = (dma64regs_t *)dmaregsrx; ++ di->hnddma.di_fn = (const di_fcn_t *)&dma64proc; ++ } else if (DMA32_ENAB(di)) { ++ ASSERT(ntxd <= D32MAXDD); ++ ASSERT(nrxd <= D32MAXDD); ++ di->d32txregs = (dma32regs_t *)dmaregstx; ++ di->d32rxregs = (dma32regs_t *)dmaregsrx; ++ di->hnddma.di_fn = (const di_fcn_t *)&dma32proc; ++ } else { ++ DMA_ERROR(("%s: driver doesn't support 32-bit DMA\n", __FUNCTION__)); ++ ASSERT(0); ++ goto fail; ++ } ++ ++ /* Default flags (which can be changed by the driver calling dma_ctrlflags ++ * before enable): For backwards compatibility both Rx Overflow Continue ++ * and Parity are DISABLED. ++ * supports it. ++ */ ++ di->hnddma.di_fn->ctrlflags(&di->hnddma, DMA_CTRL_ROC | DMA_CTRL_PEN, 0); ++ ++ DMA_TRACE(("%s: %s: %s osh %p flags 0x%x ntxd %d nrxd %d rxbufsize %d " ++ "rxextheadroom %d nrxpost %d rxoffset %d dmaregstx %p dmaregsrx %p\n", ++ name, __FUNCTION__, (DMA64_MODE(di) ? "DMA64" : "DMA32"), ++ osh, di->hnddma.dmactrlflags, ntxd, nrxd, ++ rxbufsize, rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx)); ++ ++ /* make a private copy of our callers name */ ++ strncpy(di->name, name, MAXNAMEL); ++ di->name[MAXNAMEL-1] = '\0'; ++ ++ di->osh = osh; ++ di->sih = sih; ++ ++ /* save tunables */ ++ di->ntxd = (uint16)ntxd; ++ di->nrxd = (uint16)nrxd; ++ ++ /* the actual dma size doesn't include the extra headroom */ ++ di->rxextrahdrroom = (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom; ++ if (rxbufsize > BCMEXTRAHDROOM) ++ di->rxbufsize = (uint16)(rxbufsize - di->rxextrahdrroom); ++ else ++ di->rxbufsize = (uint16)rxbufsize; ++ ++ di->nrxpost = (uint16)nrxpost; ++ di->rxoffset = (uint8)rxoffset; ++ ++ /* Get the default values (POR) of the burstlen. This can be overridden by the modules ++ * if this has to be different. Otherwise this value will be used to program the control ++ * register after the reset or during the init. ++ */ ++ if (dmaregsrx) { ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ /* detect the dma descriptor address mask, ++ * should be 0x1fff before 4360B0, 0xffff start from 4360B0 ++ */ ++ W_REG(di->osh, &di->d64rxregs->addrlow, 0xffffffff); ++ mask = R_REG(di->osh, &di->d64rxregs->addrlow); ++ ++ if (mask & 0xfff) ++ mask = R_REG(di->osh, &di->d64rxregs->ptr) | 0xf; ++ else ++ mask = 0x1fff; ++ ++ DMA_TRACE(("%s: dma_rx_mask: %08x\n", di->name, mask)); ++ di->d64_rs0_cd_mask = mask; ++ ++ if (mask == 0x1fff) ++ ASSERT(nrxd <= D64MAXDD); ++ else ++ ASSERT(nrxd <= D64MAXDD_LARGE); ++ ++ di->rxburstlen = (R_REG(di->osh, ++ &di->d64rxregs->control) & D64_RC_BL_MASK) >> D64_RC_BL_SHIFT; ++ di->rxprefetchctl = (R_REG(di->osh, ++ &di->d64rxregs->control) & D64_RC_PC_MASK) >> D64_RC_PC_SHIFT; ++ di->rxprefetchthresh = (R_REG(di->osh, ++ &di->d64rxregs->control) & D64_RC_PT_MASK) >> D64_RC_PT_SHIFT; ++ } else if (DMA32_ENAB(di)) { ++ di->rxburstlen = (R_REG(di->osh, ++ &di->d32rxregs->control) & RC_BL_MASK) >> RC_BL_SHIFT; ++ di->rxprefetchctl = (R_REG(di->osh, ++ &di->d32rxregs->control) & RC_PC_MASK) >> RC_PC_SHIFT; ++ di->rxprefetchthresh = (R_REG(di->osh, ++ &di->d32rxregs->control) & RC_PT_MASK) >> RC_PT_SHIFT; ++ } ++ } ++ if (dmaregstx) { ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ ++ /* detect the dma descriptor address mask, ++ * should be 0x1fff before 4360B0, 0xffff start from 4360B0 ++ */ ++ W_REG(di->osh, &di->d64txregs->addrlow, 0xffffffff); ++ mask = R_REG(di->osh, &di->d64txregs->addrlow); ++ ++ if (mask & 0xfff) ++ mask = R_REG(di->osh, &di->d64txregs->ptr) | 0xf; ++ else ++ mask = 0x1fff; ++ ++ DMA_TRACE(("%s: dma_tx_mask: %08x\n", di->name, mask)); ++ di->d64_xs0_cd_mask = mask; ++ di->d64_xs1_ad_mask = mask; ++ ++ if (mask == 0x1fff) ++ ASSERT(ntxd <= D64MAXDD); ++ else ++ ASSERT(ntxd <= D64MAXDD_LARGE); ++ ++ di->txburstlen = (R_REG(di->osh, ++ &di->d64txregs->control) & D64_XC_BL_MASK) >> D64_XC_BL_SHIFT; ++ di->txmultioutstdrd = (R_REG(di->osh, ++ &di->d64txregs->control) & D64_XC_MR_MASK) >> D64_XC_MR_SHIFT; ++ di->txprefetchctl = (R_REG(di->osh, ++ &di->d64txregs->control) & D64_XC_PC_MASK) >> D64_XC_PC_SHIFT; ++ di->txprefetchthresh = (R_REG(di->osh, ++ &di->d64txregs->control) & D64_XC_PT_MASK) >> D64_XC_PT_SHIFT; ++ } else if (DMA32_ENAB(di)) { ++ di->txburstlen = (R_REG(di->osh, ++ &di->d32txregs->control) & XC_BL_MASK) >> XC_BL_SHIFT; ++ di->txmultioutstdrd = (R_REG(di->osh, ++ &di->d32txregs->control) & XC_MR_MASK) >> XC_MR_SHIFT; ++ di->txprefetchctl = (R_REG(di->osh, ++ &di->d32txregs->control) & XC_PC_MASK) >> XC_PC_SHIFT; ++ di->txprefetchthresh = (R_REG(di->osh, ++ &di->d32txregs->control) & XC_PT_MASK) >> XC_PT_SHIFT; ++ } ++ } ++ ++ /* force burstlen to 3 */ ++ di->rxburstlen = 3; ++ di->txburstlen = 3; ++ /* ++ * figure out the DMA physical address offset for dd and data ++ * Other bus: use zero ++ */ ++ di->ddoffsetlow = 0; ++ di->dataoffsetlow = 0; ++ ++#if defined(__mips__) && defined(IL_BIGENDIAN) ++ di->dataoffsetlow = di->dataoffsetlow + SI_SDRAM_SWAPPED; ++#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */ ++ ++ /* set addr ext fields */ ++ di->addrext = _dma_isaddrext(di); ++ ++ /* does the descriptors need to be aligned and if yes, on 4K/8K or not */ ++ di->aligndesc_4k = _dma_descriptor_align(di); ++ if (di->aligndesc_4k) { ++ if (DMA64_MODE(di)) { ++ di->dmadesc_align = D64RINGALIGN_BITS; ++ if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) { ++ /* for smaller dd table, HW relax the alignment requirement */ ++ di->dmadesc_align = D64RINGALIGN_BITS - 1; ++ } ++ } else ++ di->dmadesc_align = D32RINGALIGN_BITS; ++ } else { ++ /* The start address of descriptor table should be algined to cache line size, ++ * or other structure may share a cache line with it, which can lead to memory ++ * overlapping due to cache write-back operation. In the case of MIPS 74k, the ++ * cache line size is 32 bytes. ++ */ ++#ifdef __mips__ ++ di->dmadesc_align = 5; /* 32 byte alignment */ ++#else ++ di->dmadesc_align = 4; /* 16 byte alignment */ ++#endif ++ } ++ ++ DMA_NONE(("DMA descriptor align_needed %d, align %d\n", ++ di->aligndesc_4k, di->dmadesc_align)); ++ ++ /* allocate tx packet pointer vector */ ++ if (ntxd) { ++ size = ntxd * sizeof(void *); ++ if ((di->txp = MALLOC(osh, size)) == NULL) { ++ DMA_ERROR(("%s: %s: out of tx memory, malloced %d bytes\n", ++ di->name, __FUNCTION__, MALLOCED(osh))); ++ goto fail; ++ } ++ bzero(di->txp, size); ++ } ++ ++ /* allocate rx packet pointer vector */ ++ if (nrxd) { ++ size = nrxd * sizeof(void *); ++ if ((di->rxp = MALLOC(osh, size)) == NULL) { ++ DMA_ERROR(("%s: %s: out of rx memory, malloced %d bytes\n", ++ di->name, __FUNCTION__, MALLOCED(osh))); ++ goto fail; ++ } ++ bzero(di->rxp, size); ++ } ++ ++ /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ ++ if (ntxd) { ++ if (!_dma_alloc(di, DMA_TX)) ++ goto fail; ++ } ++ ++ /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ ++ if (nrxd) { ++ if (!_dma_alloc(di, DMA_RX)) ++ goto fail; ++ } ++ ++ if ((di->ddoffsetlow != 0) && !di->addrext) { ++ if (PHYSADDRLO(di->txdpa) > SI_PCI_DMA_SZ) { ++ DMA_ERROR(("%s: %s: txdpa 0x%x: addrext not supported\n", ++ di->name, __FUNCTION__, (uint32)PHYSADDRLO(di->txdpa))); ++ goto fail; ++ } ++ if (PHYSADDRLO(di->rxdpa) > SI_PCI_DMA_SZ) { ++ DMA_ERROR(("%s: %s: rxdpa 0x%x: addrext not supported\n", ++ di->name, __FUNCTION__, (uint32)PHYSADDRLO(di->rxdpa))); ++ goto fail; ++ } ++ } ++ ++ DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh " ++ "0x%x addrext %d\n", di->ddoffsetlow, di->ddoffsethigh, di->dataoffsetlow, ++ di->dataoffsethigh, di->addrext)); ++ ++ /* allocate DMA mapping vectors */ ++ if (DMASGLIST_ENAB) { ++ if (ntxd) { ++ size = ntxd * sizeof(hnddma_seg_map_t); ++ if ((di->txp_dmah = (hnddma_seg_map_t *)MALLOC(osh, size)) == NULL) ++ goto fail; ++ bzero(di->txp_dmah, size); ++ } ++ ++ if (nrxd) { ++ size = nrxd * sizeof(hnddma_seg_map_t); ++ if ((di->rxp_dmah = (hnddma_seg_map_t *)MALLOC(osh, size)) == NULL) ++ goto fail; ++ bzero(di->rxp_dmah, size); ++ } ++ } ++ ++ return ((hnddma_t *)di); ++ ++fail: ++ _dma_detach(di); ++ return (NULL); ++} ++ ++/* init the tx or rx descriptor */ ++static INLINE void ++dma32_dd_upd(dma_info_t *di, dma32dd_t *ddring, dmaaddr_t pa, uint outidx, uint32 *flags, ++ uint32 bufcount) ++{ ++ /* dma32 uses 32-bit control to fit both flags and bufcounter */ ++ *flags = *flags | (bufcount & CTRL_BC_MASK); ++ ++ if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++ W_SM(&ddring[outidx].addr, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags)); ++ } else { ++ /* address extension */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ++ ++ *flags |= (ae << CTRL_AE_SHIFT); ++ W_SM(&ddring[outidx].addr, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags)); ++ } ++} ++ ++/* Check for odd number of 1's */ ++STATIC INLINE uint32 parity32(uint32 data) ++{ ++ data ^= data >> 16; ++ data ^= data >> 8; ++ data ^= data >> 4; ++ data ^= data >> 2; ++ data ^= data >> 1; ++ ++ return (data & 1); ++} ++ ++#define DMA64_DD_PARITY(dd) parity32((dd)->addrlow ^ (dd)->addrhigh ^ (dd)->ctrl1 ^ (dd)->ctrl2) ++ ++static INLINE void ++dma64_dd_upd(dma_info_t *di, dma64dd_t *ddring, dmaaddr_t pa, uint outidx, uint32 *flags, ++ uint32 bufcount) ++{ ++ uint32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; ++ ++ /* PCI bus with big(>1G) physical address, use address extension */ ++#if defined(__mips__) && defined(IL_BIGENDIAN) ++ if ((di->dataoffsetlow == SI_SDRAM_SWAPPED) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++#else ++ if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */ ++ ASSERT((PHYSADDRHI(pa) & PCI64ADDR_HIGH) == 0); ++ ++ W_SM(&ddring[outidx].addrlow, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].addrhigh, BUS_SWAP32(PHYSADDRHI(pa) + di->dataoffsethigh)); ++ W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); ++ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); ++ } else { ++ /* address extension for 32-bit PCI */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ++ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ++ ASSERT(PHYSADDRHI(pa) == 0); ++ ++ ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE; ++ W_SM(&ddring[outidx].addrlow, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].addrhigh, BUS_SWAP32(0 + di->dataoffsethigh)); ++ W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); ++ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); ++ } ++ if (di->hnddma.dmactrlflags & DMA_CTRL_PEN) { ++ if (DMA64_DD_PARITY(&ddring[outidx])) { ++ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2 | D64_CTRL2_PARITY)); ++ } ++ } ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++/* Test */ ++#if defined(__arm__) ++ if (IS_IPROC_CHIP_ID(CHIPID(di->sih->chip))) ++ OSL_CACHE_FLUSH((uint)OSL_CACHED(&ddring[outidx]), sizeof(dma64dd_t)); ++#endif ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++static bool ++_dma32_addrext(osl_t *osh, dma32regs_t *dma32regs) ++{ ++ uint32 w; ++ ++ OR_REG(osh, &dma32regs->control, XC_AE); ++ w = R_REG(osh, &dma32regs->control); ++ AND_REG(osh, &dma32regs->control, ~XC_AE); ++ return ((w & XC_AE) == XC_AE); ++} ++ ++static bool ++_dma_alloc(dma_info_t *di, uint direction) ++{ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ return dma64_alloc(di, direction); ++ } else if (DMA32_ENAB(di)) { ++ return dma32_alloc(di, direction); ++ } else ++ ASSERT(0); ++} ++ ++/* !! may be called with core in reset */ ++static void ++_dma_detach(dma_info_t *di) ++{ ++ ++ DMA_TRACE(("%s: dma_detach\n", di->name)); ++ ++ /* shouldn't be here if descriptors are unreclaimed */ ++ ASSERT(di->txin == di->txout); ++ ASSERT(di->rxin == di->rxout); ++ ++ /* free dma descriptor rings */ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ if (di->txd64) ++ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->txd64 - di->txdalign), ++ di->txdalloc, (di->txdpaorig), &di->tx_dmah); ++ if (di->rxd64) ++ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->rxd64 - di->rxdalign), ++ di->rxdalloc, (di->rxdpaorig), &di->rx_dmah); ++ } else if (DMA32_ENAB(di)) { ++ if (di->txd32) ++ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->txd32 - di->txdalign), ++ di->txdalloc, (di->txdpaorig), &di->tx_dmah); ++ if (di->rxd32) ++ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->rxd32 - di->rxdalign), ++ di->rxdalloc, (di->rxdpaorig), &di->rx_dmah); ++ } else ++ ASSERT(0); ++ ++ /* free packet pointer vectors */ ++ if (di->txp) ++ MFREE(di->osh, (void *)di->txp, (di->ntxd * sizeof(void *))); ++ if (di->rxp) ++ MFREE(di->osh, (void *)di->rxp, (di->nrxd * sizeof(void *))); ++ ++ /* free tx packet DMA handles */ ++ if (di->txp_dmah) ++ MFREE(di->osh, (void *)di->txp_dmah, di->ntxd * sizeof(hnddma_seg_map_t)); ++ ++ /* free rx packet DMA handles */ ++ if (di->rxp_dmah) ++ MFREE(di->osh, (void *)di->rxp_dmah, di->nrxd * sizeof(hnddma_seg_map_t)); ++ ++ /* free our private info structure */ ++ MFREE(di->osh, (void *)di, sizeof(dma_info_t)); ++ ++} ++ ++static bool ++_dma_descriptor_align(dma_info_t *di) ++{ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ uint32 addrl; ++ ++ /* Check to see if the descriptors need to be aligned on 4K/8K or not */ ++ if (di->d64txregs != NULL) { ++ W_REG(di->osh, &di->d64txregs->addrlow, 0xff0); ++ addrl = R_REG(di->osh, &di->d64txregs->addrlow); ++ if (addrl != 0) ++ return FALSE; ++ } else if (di->d64rxregs != NULL) { ++ W_REG(di->osh, &di->d64rxregs->addrlow, 0xff0); ++ addrl = R_REG(di->osh, &di->d64rxregs->addrlow); ++ if (addrl != 0) ++ return FALSE; ++ } ++ } ++ return TRUE; ++} ++ ++/* return TRUE if this dma engine supports DmaExtendedAddrChanges, otherwise FALSE */ ++static bool ++_dma_isaddrext(dma_info_t *di) ++{ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ /* DMA64 supports full 32- or 64-bit operation. AE is always valid */ ++ ++ /* not all tx or rx channel are available */ ++ if (di->d64txregs != NULL) { ++ if (!_dma64_addrext(di->osh, di->d64txregs)) { ++ DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have AE set\n", ++ di->name)); ++ ASSERT(0); ++ } ++ return TRUE; ++ } else if (di->d64rxregs != NULL) { ++ if (!_dma64_addrext(di->osh, di->d64rxregs)) { ++ DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have AE set\n", ++ di->name)); ++ ASSERT(0); ++ } ++ return TRUE; ++ } ++ return FALSE; ++ } else if (DMA32_ENAB(di)) { ++ if (di->d32txregs) ++ return (_dma32_addrext(di->osh, di->d32txregs)); ++ else if (di->d32rxregs) ++ return (_dma32_addrext(di->osh, di->d32rxregs)); ++ } else ++ ASSERT(0); ++ ++ return FALSE; ++} ++ ++/* initialize descriptor table base address */ ++static void ++_dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa) ++{ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ if (!di->aligndesc_4k) { ++ if (direction == DMA_TX) ++ di->xmtptrbase = PHYSADDRLO(pa); ++ else ++ di->rcvptrbase = PHYSADDRLO(pa); ++ } ++ ++ if ((di->ddoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++ if (direction == DMA_TX) { ++ W_REG(di->osh, &di->d64txregs->addrlow, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ W_REG(di->osh, &di->d64txregs->addrhigh, (PHYSADDRHI(pa) + ++ di->ddoffsethigh)); ++ } else { ++ W_REG(di->osh, &di->d64rxregs->addrlow, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ W_REG(di->osh, &di->d64rxregs->addrhigh, (PHYSADDRHI(pa) + ++ di->ddoffsethigh)); ++ } ++ } else { ++ /* DMA64 32bits address extension */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ASSERT(PHYSADDRHI(pa) == 0); ++ ++ /* shift the high bit(s) from pa to ae */ ++ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ++ ++ if (direction == DMA_TX) { ++ W_REG(di->osh, &di->d64txregs->addrlow, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ W_REG(di->osh, &di->d64txregs->addrhigh, di->ddoffsethigh); ++ SET_REG(di->osh, &di->d64txregs->control, D64_XC_AE, ++ (ae << D64_XC_AE_SHIFT)); ++ } else { ++ W_REG(di->osh, &di->d64rxregs->addrlow, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ W_REG(di->osh, &di->d64rxregs->addrhigh, di->ddoffsethigh); ++ SET_REG(di->osh, &di->d64rxregs->control, D64_RC_AE, ++ (ae << D64_RC_AE_SHIFT)); ++ } ++ } ++ ++ } else if (DMA32_ENAB(di)) { ++ ASSERT(PHYSADDRHI(pa) == 0); ++ if ((di->ddoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++ if (direction == DMA_TX) ++ W_REG(di->osh, &di->d32txregs->addr, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ else ++ W_REG(di->osh, &di->d32rxregs->addr, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ } else { ++ /* dma32 address extension */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ++ /* shift the high bit(s) from pa to ae */ ++ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ++ ++ if (direction == DMA_TX) { ++ W_REG(di->osh, &di->d32txregs->addr, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ SET_REG(di->osh, &di->d32txregs->control, XC_AE, ae <osh, &di->d32rxregs->addr, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ SET_REG(di->osh, &di->d32rxregs->control, RC_AE, ae <name)); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) ++ OR_REG(di->osh, &di->d64txregs->control, D64_XC_LE); ++ else if (DMA32_ENAB(di)) ++ OR_REG(di->osh, &di->d32txregs->control, XC_LE); ++ else ++ ASSERT(0); ++} ++ ++static void ++_dma_rxinit(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxinit\n", di->name)); ++ ++ if (di->nrxd == 0) { ++ return; ++ } ++ ++ /* During the reset procedure, the active rxd may not be zero if pktpool is ++ * enabled, we need to reclaim active rxd to avoid rxd being leaked. ++ */ ++ if ((POOL_ENAB(di->pktpool)) && (NRXDACTIVE(di->rxin, di->rxout))) { ++ _dma_rxreclaim(di); ++ } ++ ++ ASSERT(di->rxin == di->rxout); ++ di->rxin = di->rxout = di->rs0cd = 0; ++ ++ /* clear rx descriptor ring */ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ BZERO_SM((void *)(uintptr)di->rxd64, (di->nrxd * sizeof(dma64dd_t))); ++ ++ /* DMA engine with out alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (!di->aligndesc_4k) { ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++ } ++ ++ _dma_rxenable(di); ++ ++ if (di->aligndesc_4k) { ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++ } ++ } else if (DMA32_ENAB(di)) { ++ BZERO_SM((void *)(uintptr)di->rxd32, (di->nrxd * sizeof(dma32dd_t))); ++ _dma_rxenable(di); ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++ } else ++ ASSERT(0); ++} ++ ++static void ++_dma_rxenable(dma_info_t *di) ++{ ++ uint dmactrlflags = di->hnddma.dmactrlflags; ++ ++ DMA_TRACE(("%s: dma_rxenable\n", di->name)); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ uint32 control = (R_REG(di->osh, &di->d64rxregs->control) & D64_RC_AE) | D64_RC_RE; ++ ++ if ((dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= D64_RC_PD; ++ ++ if (dmactrlflags & DMA_CTRL_ROC) ++ control |= D64_RC_OC; ++ ++ /* These bits 20:18 (burstLen) of control register can be written but will take ++ * effect only if these bits are valid. So this will not affect previous versions ++ * of the DMA. They will continue to have those bits set to 0. ++ */ ++ control &= ~D64_RC_BL_MASK; ++ control |= (di->rxburstlen << D64_RC_BL_SHIFT); ++ ++ control &= ~D64_RC_PC_MASK; ++ control |= (di->rxprefetchctl << D64_RC_PC_SHIFT); ++ ++ control &= ~D64_RC_PT_MASK; ++ control |= (di->rxprefetchthresh << D64_RC_PT_SHIFT); ++ ++ W_REG(di->osh, &di->d64rxregs->control, ++ ((di->rxoffset << D64_RC_RO_SHIFT) | control)); ++ } else if (DMA32_ENAB(di)) { ++ uint32 control = (R_REG(di->osh, &di->d32rxregs->control) & RC_AE) | RC_RE; ++ ++ if ((dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= RC_PD; ++ ++ if (dmactrlflags & DMA_CTRL_ROC) ++ control |= RC_OC; ++ ++ /* These bits 20:18 (burstLen) of control register can be written but will take ++ * effect only if these bits are valid. So this will not affect previous versions ++ * of the DMA. They will continue to have those bits set to 0. ++ */ ++ control &= ~RC_BL_MASK; ++ control |= (di->rxburstlen << RC_BL_SHIFT); ++ ++ control &= ~RC_PC_MASK; ++ control |= (di->rxprefetchctl << RC_PC_SHIFT); ++ ++ control &= ~RC_PT_MASK; ++ control |= (di->rxprefetchthresh << RC_PT_SHIFT); ++ ++ W_REG(di->osh, &di->d32rxregs->control, ++ ((di->rxoffset << RC_RO_SHIFT) | control)); ++ } else ++ ASSERT(0); ++} ++ ++static void ++_dma_rx_param_get(dma_info_t *di, uint16 *rxoffset, uint16 *rxbufsize) ++{ ++ /* the normal values fit into 16 bits */ ++ *rxoffset = (uint16)di->rxoffset; ++ *rxbufsize = (uint16)di->rxbufsize; ++} ++ ++/* !! rx entry routine ++ * returns a pointer to the next frame received, or NULL if there are no more ++ * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is supported ++ * with pkts chain ++ * otherwise, it's treated as giant pkt and will be tossed. ++ * The DMA scattering starts with normal DMA header, followed by first buffer data. ++ * After it reaches the max size of buffer, the data continues in next DMA descriptor ++ * buffer WITHOUT DMA header ++ */ ++static void * BCMFASTPATH ++_dma_rx(dma_info_t *di) ++{ ++ void *p, *head, *tail; ++ uint len; ++ uint pkt_len; ++ int resid = 0; ++#ifdef BCM4335 ++ dma64regs_t *dregs = di->d64rxregs; ++#endif ++ ++next_frame: ++ head = _dma_getnextrxp(di, FALSE); ++ if (head == NULL) ++ return (NULL); ++ ++ len = ltoh16(*(uint16 *)(PKTDATA(di->osh, head))); ++ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); ++ ++ /* set actual length */ ++ pkt_len = MIN((di->rxoffset + len), di->rxbufsize); ++ PKTSETLEN(di->osh, head, pkt_len); ++ resid = len - (di->rxbufsize - di->rxoffset); ++ ++ /* check for single or multi-buffer rx */ ++ if (resid <= 0) { ++ /* Single frame, all good */ ++ } else if (di->hnddma.dmactrlflags & DMA_CTRL_RXSINGLE) { ++ DMA_TRACE(("%s: dma_rx: corrupted length (%d)\n", di->name, len)); ++ PKTFREE(di->osh, head, FALSE); ++ di->hnddma.rxgiants++; ++ goto next_frame; ++ } else { ++ /* multi-buffer rx */ ++#ifdef BCMDBG ++ p = NULL; /* get rid of compiler warning */ ++#endif /* BCMDBG */ ++ tail = head; ++ while ((resid > 0) && (p = _dma_getnextrxp(di, FALSE))) { ++ PKTSETNEXT(di->osh, tail, p); ++ pkt_len = MIN(resid, (int)di->rxbufsize); ++ PKTSETLEN(di->osh, p, pkt_len); ++ ++ tail = p; ++ resid -= di->rxbufsize; ++ } ++ ++#ifdef BCMDBG ++ if (resid > 0) { ++ uint16 cur; ++ ASSERT(p == NULL); ++ cur = (DMA64_ENAB(di) && DMA64_MODE(di)) ? ++ B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t) : ++ B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, ++ dma32dd_t); ++ DMA_ERROR(("_dma_rx, rxin %d rxout %d, hw_curr %d\n", ++ di->rxin, di->rxout, cur)); ++ } ++#endif /* BCMDBG */ ++ ++ if ((di->hnddma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) { ++ DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", di->name, len)); ++ PKTFREE(di->osh, head, FALSE); ++ di->hnddma.rxgiants++; ++ goto next_frame; ++ } ++ } ++ ++ return (head); ++} ++ ++/* post receive buffers ++ * return FALSE is refill failed completely and ring is empty ++ * this will stall the rx dma and user might want to call rxfill again asap ++ * This unlikely happens on memory-rich NIC, but often on memory-constrained dongle ++ */ ++static bool BCMFASTPATH ++_dma_rxfill(dma_info_t *di) ++{ ++ void *p; ++ uint16 rxin, rxout; ++ uint32 flags = 0; ++ uint n; ++ uint i; ++ dmaaddr_t pa; ++ uint extra_offset = 0, extra_pad; ++ bool ring_empty; ++ uint alignment_req = (di->hnddma.dmactrlflags & DMA_CTRL_USB_BOUNDRY4KB_WAR) ? ++ 16 : 1; /* MUST BE POWER of 2 */ ++ ++ ring_empty = FALSE; ++ ++ /* ++ * Determine how many receive buffers we're lacking ++ * from the full complement, allocate, initialize, ++ * and post them, then update the chip rx lastdscr. ++ */ ++ ++ rxin = di->rxin; ++ rxout = di->rxout; ++ ++ n = di->nrxpost - NRXDACTIVE(rxin, rxout); ++ ++ if (di->rxbufsize > BCMEXTRAHDROOM) ++ extra_offset = di->rxextrahdrroom; ++ ++ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); ++ ++ for (i = 0; i < n; i++) { ++ /* the di->rxbufsize doesn't include the extra headroom, we need to add it to the ++ size to be allocated ++ */ ++ if (POOL_ENAB(di->pktpool)) { ++ ASSERT(di->pktpool); ++ p = pktpool_get(di->pktpool); ++#ifdef BCMDBG_POOL ++ if (p) ++ PKTPOOLSETSTATE(p, POOL_RXFILL); ++#endif /* BCMDBG_POOL */ ++ } ++ else { ++ p = PKTGET(di->osh, (di->rxbufsize + extra_offset + alignment_req - 1), ++ FALSE); ++ } ++ if (p == NULL) { ++ DMA_TRACE(("%s: dma_rxfill: out of rxbufs\n", di->name)); ++ if (i == 0) { ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ if (dma64_rxidle(di)) { ++ DMA_TRACE(("%s: rxfill64: ring is empty !\n", ++ di->name)); ++ ring_empty = TRUE; ++ } ++ } else if (DMA32_ENAB(di)) { ++ if (dma32_rxidle(di)) { ++ DMA_TRACE(("%s: rxfill32: ring is empty !\n", ++ di->name)); ++ ring_empty = TRUE; ++ } ++ } else ++ ASSERT(0); ++ } ++ di->hnddma.rxnobuf++; ++ break; ++ } ++ /* reserve an extra headroom, if applicable */ ++ if (di->hnddma.dmactrlflags & DMA_CTRL_USB_BOUNDRY4KB_WAR) { ++ extra_pad = ((alignment_req - (uint)(((unsigned long)PKTDATA(di->osh, p) - ++ (unsigned long)(uchar *)0))) & (alignment_req - 1)); ++ } else ++ extra_pad = 0; ++ ++ if (extra_offset + extra_pad) ++ PKTPULL(di->osh, p, extra_offset + extra_pad); ++ ++#ifdef CTFMAP ++ /* mark as ctf buffer for fast mapping */ ++ if (CTF_ENAB(kcih)) { ++ ASSERT((((uint32)PKTDATA(di->osh, p)) & 31) == 0); ++ PKTSETCTF(di->osh, p); ++ } ++#endif /* CTFMAP */ ++ ++ /* Do a cached write instead of uncached write since DMA_MAP ++ * will flush the cache. ++ */ ++ *(uint16 *)(PKTDATA(di->osh, p)) = 0; ++ ++ if (DMASGLIST_ENAB) ++ bzero(&di->rxp_dmah[rxout], sizeof(hnddma_seg_map_t)); ++ ++#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) ++ pa = virt_to_phys(PKTDATA(di->osh, p)); ++#else ++ pa = DMA_MAP(di->osh, PKTDATA(di->osh, p), ++ di->rxbufsize, DMA_RX, p, ++ &di->rxp_dmah[rxout]); ++#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ ++ ++ ASSERT(ISALIGNED(PHYSADDRLO(pa), 4)); ++ ++ /* save the free packet pointer */ ++ ASSERT(di->rxp[rxout] == NULL); ++ di->rxp[rxout] = p; ++ ++ /* reset flags for each descriptor */ ++ flags = 0; ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ if (rxout == (di->nrxd - 1)) ++ flags = D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->rxd64, pa, rxout, &flags, di->rxbufsize); ++ } else if (DMA32_ENAB(di)) { ++ if (rxout == (di->nrxd - 1)) ++ flags = CTRL_EOT; ++ ++ ASSERT(PHYSADDRHI(pa) == 0); ++ dma32_dd_upd(di, di->rxd32, pa, rxout, &flags, di->rxbufsize); ++ } else ++ ASSERT(0); ++ rxout = NEXTRXD(rxout); ++ } ++ ++ di->rxout = rxout; ++ ++ /* update the chip lastdscr pointer */ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ W_REG(di->osh, &di->d64rxregs->ptr, di->rcvptrbase + I2B(rxout, dma64dd_t)); ++ } else if (DMA32_ENAB(di)) { ++ W_REG(di->osh, &di->d32rxregs->ptr, I2B(rxout, dma32dd_t)); ++ } else ++ ASSERT(0); ++ ++ return ring_empty; ++} ++ ++/* like getnexttxp but no reclaim */ ++static void * ++_dma_peeknexttxp(dma_info_t *di) ++{ ++ uint16 end, i; ++ ++ if (di->ntxd == 0) ++ return (NULL); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ end = (uint16)B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); ++ di->xs0cd = end; ++ } else if (DMA32_ENAB(di)) { ++ end = (uint16)B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++ di->xs0cd = end; ++ } else ++ ASSERT(0); ++ ++ for (i = di->txin; i != end; i = NEXTTXD(i)) ++ if (di->txp[i]) ++ return (di->txp[i]); ++ ++ return (NULL); ++} ++ ++int ++_dma_peekntxp(dma_info_t *di, int *len, void *txps[], txd_range_t range) ++{ ++ uint16 start, end, i; ++ uint act; ++ void *txp = NULL; ++ int k, len_max; ++ ++ DMA_TRACE(("%s: dma_peekntxp\n", di->name)); ++ ++ ASSERT(len); ++ ASSERT(txps); ++ ASSERT(di); ++ if (di->ntxd == 0) { ++ *len = 0; ++ return BCME_ERROR; ++ } ++ ++ len_max = *len; ++ *len = 0; ++ ++ start = di->txin; ++ ++ if (range == HNDDMA_RANGE_ALL) ++ end = di->txout; ++ else { ++ if (DMA64_ENAB(di)) { ++ end = B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); ++ ++ act = (uint)(R_REG(di->osh, &di->d64txregs->status1) & D64_XS1_AD_MASK); ++ act = (act - di->xmtptrbase) & D64_XS0_CD_MASK; ++ act = (uint)B2I(act, dma64dd_t); ++ } else { ++ end = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++ ++ act = (uint)((R_REG(di->osh, &di->d32txregs->status) & XS_AD_MASK) >> ++ XS_AD_SHIFT); ++ act = (uint)B2I(act, dma32dd_t); ++ } ++ ++ di->xs0cd = end; ++ if (end != act) ++ end = PREVTXD(act); ++ } ++ ++ if ((start == 0) && (end > di->txout)) ++ return BCME_ERROR; ++ ++ k = 0; ++ for (i = start; i != end; i = NEXTTXD(i)) { ++ txp = di->txp[i]; ++ if (txp != NULL) { ++ if (k < len_max) ++ txps[k++] = txp; ++ else ++ break; ++ } ++ } ++ *len = k; ++ ++ return BCME_OK; ++} ++ ++/* like getnextrxp but not take off the ring */ ++static void * ++_dma_peeknextrxp(dma_info_t *di) ++{ ++ uint16 end, i; ++ ++ if (di->nrxd == 0) ++ return (NULL); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ end = (uint16)B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ di->rs0cd = end; ++ } else if (DMA32_ENAB(di)) { ++ end = (uint16)B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, dma32dd_t); ++ di->rs0cd = end; ++ } else ++ ASSERT(0); ++ ++ for (i = di->rxin; i != end; i = NEXTRXD(i)) ++ if (di->rxp[i]) ++ return (di->rxp[i]); ++ ++ return (NULL); ++} ++ ++static void ++_dma_rxreclaim(dma_info_t *di) ++{ ++ void *p; ++ bool origcb = TRUE; ++ ++#ifndef EFI ++ /* "unused local" warning suppression for OSLs that ++ * define PKTFREE() without using the di->osh arg ++ */ ++ di = di; ++#endif /* EFI */ ++ ++ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); ++ ++ if (POOL_ENAB(di->pktpool) && ++ ((origcb = pktpool_emptycb_disabled(di->pktpool)) == FALSE)) ++ pktpool_emptycb_disable(di->pktpool, TRUE); ++ ++ while ((p = _dma_getnextrxp(di, TRUE))) ++ PKTFREE(di->osh, p, FALSE); ++ ++ if (origcb == FALSE) ++ pktpool_emptycb_disable(di->pktpool, FALSE); ++} ++ ++static void * BCMFASTPATH ++_dma_getnextrxp(dma_info_t *di, bool forceall) ++{ ++ if (di->nrxd == 0) ++ return (NULL); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ return dma64_getnextrxp(di, forceall); ++ } else if (DMA32_ENAB(di)) { ++ return dma32_getnextrxp(di, forceall); ++ } else ++ ASSERT(0); ++} ++ ++static void ++_dma_txblock(dma_info_t *di) ++{ ++ di->hnddma.txavail = 0; ++} ++ ++static void ++_dma_txunblock(dma_info_t *di) ++{ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++} ++ ++static uint ++_dma_txactive(dma_info_t *di) ++{ ++ return NTXDACTIVE(di->txin, di->txout); ++} ++ ++static uint ++_dma_txpending(dma_info_t *di) ++{ ++ uint16 curr; ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ curr = B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); ++ di->xs0cd = curr; ++ } else if (DMA32_ENAB(di)) { ++ curr = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++ di->xs0cd = curr; ++ } else ++ ASSERT(0); ++ ++ return NTXDACTIVE(curr, di->txout); ++} ++ ++static uint ++_dma_txcommitted(dma_info_t *di) ++{ ++ uint16 ptr; ++ uint txin = di->txin; ++ ++ if (txin == di->txout) ++ return 0; ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ ptr = B2I(R_REG(di->osh, &di->d64txregs->ptr), dma64dd_t); ++ } else if (DMA32_ENAB(di)) { ++ ptr = B2I(R_REG(di->osh, &di->d32txregs->ptr), dma32dd_t); ++ } else ++ ASSERT(0); ++ ++ return NTXDACTIVE(di->txin, ptr); ++} ++ ++static uint ++_dma_rxactive(dma_info_t *di) ++{ ++ return NRXDACTIVE(di->rxin, di->rxout); ++} ++ ++static uint ++_dma_activerxbuf(dma_info_t *di) ++{ ++ uint16 curr, ptr; ++ curr = B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ ptr = B2I(((R_REG(di->osh, &di->d64rxregs->ptr) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ return NRXDACTIVE(curr, ptr); ++} ++ ++ ++static void ++_dma_counterreset(dma_info_t *di) ++{ ++ /* reset all software counter */ ++ di->hnddma.rxgiants = 0; ++ di->hnddma.rxnobuf = 0; ++ di->hnddma.txnobuf = 0; ++} ++ ++static uint ++_dma_ctrlflags(dma_info_t *di, uint mask, uint flags) ++{ ++ uint dmactrlflags; ++ ++ if (!di) { ++ DMA_ERROR(("_dma_ctrlflags: NULL dma handle\n")); ++ return (0); ++ } ++ ++ dmactrlflags = di->hnddma.dmactrlflags; ++ ASSERT((flags & ~mask) == 0); ++ ++ dmactrlflags &= ~mask; ++ dmactrlflags |= flags; ++ ++ /* If trying to enable parity, check if parity is actually supported */ ++ if (dmactrlflags & DMA_CTRL_PEN) { ++ uint32 control; ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ control = R_REG(di->osh, &di->d64txregs->control); ++ W_REG(di->osh, &di->d64txregs->control, control | D64_XC_PD); ++ if (R_REG(di->osh, &di->d64txregs->control) & D64_XC_PD) { ++ /* We *can* disable it so it is supported, ++ * restore control register ++ */ ++ W_REG(di->osh, &di->d64txregs->control, control); ++ } else { ++ /* Not supported, don't allow it to be enabled */ ++ dmactrlflags &= ~DMA_CTRL_PEN; ++ } ++ } else if (DMA32_ENAB(di)) { ++ control = R_REG(di->osh, &di->d32txregs->control); ++ W_REG(di->osh, &di->d32txregs->control, control | XC_PD); ++ if (R_REG(di->osh, &di->d32txregs->control) & XC_PD) { ++ W_REG(di->osh, &di->d32txregs->control, control); ++ } else { ++ /* Not supported, don't allow it to be enabled */ ++ dmactrlflags &= ~DMA_CTRL_PEN; ++ } ++ } else ++ ASSERT(0); ++ } ++ ++ di->hnddma.dmactrlflags = dmactrlflags; ++ ++ return (dmactrlflags); ++} ++ ++/* get the address of the var in order to change later */ ++static uintptr ++_dma_getvar(dma_info_t *di, const char *name) ++{ ++ if (!strcmp(name, "&txavail")) ++ return ((uintptr) &(di->hnddma.txavail)); ++ else { ++ ASSERT(0); ++ } ++ return (0); ++} ++ ++static uint ++_dma_avoidancecnt(dma_info_t *di) ++{ ++ return (di->dma_avoidance_cnt); ++} ++ ++void ++dma_txpioloopback(osl_t *osh, dma32regs_t *regs) ++{ ++ OR_REG(osh, ®s->control, XC_LE); ++} ++ ++static ++uint8 dma_align_sizetobits(uint size) ++{ ++ uint8 bitpos = 0; ++ ASSERT(size); ++ ASSERT(!(size & (size-1))); ++ while (size >>= 1) { ++ bitpos ++; ++ } ++ return (bitpos); ++} ++ ++/* This function ensures that the DMA descriptor ring will not get allocated ++ * across Page boundary. If the allocation is done across the page boundary ++ * at the first time, then it is freed and the allocation is done at ++ * descriptor ring size aligned location. This will ensure that the ring will ++ * not cross page boundary ++ */ ++static void * ++dma_ringalloc(osl_t *osh, uint32 boundary, uint size, uint16 *alignbits, uint* alloced, ++ dmaaddr_t *descpa, osldma_t **dmah) ++{ ++ void * va; ++ uint32 desc_strtaddr; ++ uint32 alignbytes = 1 << *alignbits; ++ ++ if ((va = DMA_ALLOC_CONSISTENT(osh, size, *alignbits, alloced, descpa, dmah)) == NULL) ++ return NULL; ++ ++ /* printk("%s va(0x%x)\n", __FUNCTION__, va); */ ++ desc_strtaddr = (uint32)ROUNDUP((uint)PHYSADDRLO(*descpa), alignbytes); ++ if (((desc_strtaddr + size - 1) & boundary) != ++ (desc_strtaddr & boundary)) { ++ *alignbits = dma_align_sizetobits(size); ++ DMA_FREE_CONSISTENT(osh, va, ++ size, *descpa, dmah); ++ va = DMA_ALLOC_CONSISTENT(osh, size, *alignbits, alloced, descpa, dmah); ++ } ++ return va; ++} ++ ++#if defined(BCMDBG) ++static void ++dma32_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma32dd_t *ring, uint start, uint end, ++ uint max_num) ++{ ++ uint i; ++ ++ for (i = start; i != end; i = XXD((i + 1), max_num)) { ++ /* in the format of high->low 8 bytes */ ++ bcm_bprintf(b, "ring index %d: 0x%x %x\n", ++ i, R_SM(&ring[i].addr), R_SM(&ring[i].ctrl)); ++ } ++} ++ ++static void ++dma32_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ if (di->ntxd == 0) ++ return; ++ ++ bcm_bprintf(b, "DMA32: txd32 %p txdpa 0x%lx txp %p txin %d txout %d " ++ "txavail %d txnodesc %d\n", di->txd32, PHYSADDRLO(di->txdpa), di->txp, di->txin, ++ di->txout, di->hnddma.txavail, di->hnddma.txnodesc); ++ ++ bcm_bprintf(b, "xmtcontrol 0x%x xmtaddr 0x%x xmtptr 0x%x xmtstatus 0x%x\n", ++ R_REG(di->osh, &di->d32txregs->control), ++ R_REG(di->osh, &di->d32txregs->addr), ++ R_REG(di->osh, &di->d32txregs->ptr), ++ R_REG(di->osh, &di->d32txregs->status)); ++ ++ if (dumpring && di->txd32) ++ dma32_dumpring(di, b, di->txd32, di->txin, di->txout, di->ntxd); ++} ++ ++static void ++dma32_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ if (di->nrxd == 0) ++ return; ++ ++ bcm_bprintf(b, "DMA32: rxd32 %p rxdpa 0x%lx rxp %p rxin %d rxout %d\n", ++ di->rxd32, PHYSADDRLO(di->rxdpa), di->rxp, di->rxin, di->rxout); ++ ++ bcm_bprintf(b, "rcvcontrol 0x%x rcvaddr 0x%x rcvptr 0x%x rcvstatus 0x%x\n", ++ R_REG(di->osh, &di->d32rxregs->control), ++ R_REG(di->osh, &di->d32rxregs->addr), ++ R_REG(di->osh, &di->d32rxregs->ptr), ++ R_REG(di->osh, &di->d32rxregs->status)); ++ if (di->rxd32 && dumpring) ++ dma32_dumpring(di, b, di->rxd32, di->rxin, di->rxout, di->nrxd); ++} ++ ++static void ++dma32_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ dma32_dumptx(di, b, dumpring); ++ dma32_dumprx(di, b, dumpring); ++} ++ ++static void ++dma64_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma64dd_t *ring, uint start, uint end, ++ uint max_num) ++{ ++ uint i; ++ ++ for (i = start; i != end; i = XXD((i + 1), max_num)) { ++ /* in the format of high->low 16 bytes */ ++ bcm_bprintf(b, "ring index %d: 0x%x %x %x %x\n", ++ i, R_SM(&ring[i].addrhigh), R_SM(&ring[i].addrlow), ++ R_SM(&ring[i].ctrl2), R_SM(&ring[i].ctrl1)); ++ } ++} ++ ++static void ++dma64_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ if (di->ntxd == 0) ++ return; ++ ++ bcm_bprintf(b, "DMA64: txd64 %p txdpa 0x%lx txdpahi 0x%lx txp %p txin %d txout %d " ++ "txavail %d txnodesc %d\n", di->txd64, PHYSADDRLO(di->txdpa), ++ PHYSADDRHI(di->txdpaorig), di->txp, di->txin, di->txout, di->hnddma.txavail, ++ di->hnddma.txnodesc); ++ ++ bcm_bprintf(b, "xmtcontrol 0x%x xmtaddrlow 0x%x xmtaddrhigh 0x%x " ++ "xmtptr 0x%x xmtstatus0 0x%x xmtstatus1 0x%x\n", ++ R_REG(di->osh, &di->d64txregs->control), ++ R_REG(di->osh, &di->d64txregs->addrlow), ++ R_REG(di->osh, &di->d64txregs->addrhigh), ++ R_REG(di->osh, &di->d64txregs->ptr), ++ R_REG(di->osh, &di->d64txregs->status0), ++ R_REG(di->osh, &di->d64txregs->status1)); ++ ++ bcm_bprintf(b, "DMA64: DMA avoidance applied %d\n", di->dma_avoidance_cnt); ++ ++ if (dumpring && di->txd64) { ++ dma64_dumpring(di, b, di->txd64, di->txin, di->txout, di->ntxd); ++ } ++} ++ ++static void ++dma64_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ if (di->nrxd == 0) ++ return; ++ ++ bcm_bprintf(b, "DMA64: rxd64 %p rxdpa 0x%lx rxdpahi 0x%lx rxp %p rxin %d rxout %d\n", ++ di->rxd64, PHYSADDRLO(di->rxdpa), PHYSADDRHI(di->rxdpaorig), di->rxp, ++ di->rxin, di->rxout); ++ ++ bcm_bprintf(b, "rcvcontrol 0x%x rcvaddrlow 0x%x rcvaddrhigh 0x%x rcvptr " ++ "0x%x rcvstatus0 0x%x rcvstatus1 0x%x\n", ++ R_REG(di->osh, &di->d64rxregs->control), ++ R_REG(di->osh, &di->d64rxregs->addrlow), ++ R_REG(di->osh, &di->d64rxregs->addrhigh), ++ R_REG(di->osh, &di->d64rxregs->ptr), ++ R_REG(di->osh, &di->d64rxregs->status0), ++ R_REG(di->osh, &di->d64rxregs->status1)); ++ if (di->rxd64 && dumpring) { ++ dma64_dumpring(di, b, di->rxd64, di->rxin, di->rxout, di->nrxd); ++ } ++} ++ ++static void ++dma64_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ dma64_dumptx(di, b, dumpring); ++ dma64_dumprx(di, b, dumpring); ++} ++ ++#endif ++ ++ ++/* 32-bit DMA functions */ ++ ++static void ++dma32_txinit(dma_info_t *di) ++{ ++ uint32 control = XC_XE; ++ ++ DMA_TRACE(("%s: dma_txinit\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ di->txin = di->txout = di->xs0cd = 0; ++ di->hnddma.txavail = di->ntxd - 1; ++ ++ /* clear tx descriptor ring */ ++ BZERO_SM(DISCARD_QUAL(di->txd32, void), (di->ntxd * sizeof(dma32dd_t))); ++ ++ /* These bits 20:18 (burstLen) of control register can be written but will take ++ * effect only if these bits are valid. So this will not affect previous versions ++ * of the DMA. They will continue to have those bits set to 0. ++ */ ++ control |= (di->txburstlen << XC_BL_SHIFT); ++ control |= (di->txmultioutstdrd << XC_MR_SHIFT); ++ control |= (di->txprefetchctl << XC_PC_SHIFT); ++ control |= (di->txprefetchthresh << XC_PT_SHIFT); ++ ++ if ((di->hnddma.dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= XC_PD; ++ W_REG(di->osh, &di->d32txregs->control, control); ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++} ++ ++static bool ++dma32_txenabled(dma_info_t *di) ++{ ++ uint32 xc; ++ ++ /* If the chip is dead, it is not enabled :-) */ ++ xc = R_REG(di->osh, &di->d32txregs->control); ++ return ((xc != 0xffffffff) && (xc & XC_XE)); ++} ++ ++static void ++dma32_txsuspend(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(di->osh, &di->d32txregs->control, XC_SE); ++} ++ ++static void ++dma32_txresume(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txresume\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ AND_REG(di->osh, &di->d32txregs->control, ~XC_SE); ++} ++ ++static bool ++dma32_txsuspended(dma_info_t *di) ++{ ++ return (di->ntxd == 0) || ((R_REG(di->osh, &di->d32txregs->control) & XC_SE) == XC_SE); ++} ++ ++#ifdef WL_MULTIQUEUE ++static void ++dma32_txflush(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txflush\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(di->osh, &di->d32txregs->control, XC_SE | XC_FL); ++} ++ ++static void ++dma32_txflush_clear(dma_info_t *di) ++{ ++ uint32 status; ++ ++ DMA_TRACE(("%s: dma_txflush_clear\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK)) ++ != XS_XS_DISABLED) && ++ (status != XS_XS_IDLE) && ++ (status != XS_XS_STOPPED), ++ (10000)); ++ AND_REG(di->osh, &di->d32txregs->control, ~XC_FL); ++} ++#endif /* WL_MULTIQUEUE */ ++ ++static void ++dma32_txreclaim(dma_info_t *di, txd_range_t range) ++{ ++ void *p; ++ ++ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, ++ (range == HNDDMA_RANGE_ALL) ? "all" : ++ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); ++ ++ if (di->txin == di->txout) ++ return; ++ ++ while ((p = dma32_getnexttxp(di, range))) ++ PKTFREE(di->osh, p, TRUE); ++} ++ ++static bool ++dma32_txstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_STOPPED); ++} ++ ++static bool ++dma32_rxstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d32rxregs->status) & RS_RS_MASK) == RS_RS_STOPPED); ++} ++ ++static bool ++dma32_alloc(dma_info_t *di, uint direction) ++{ ++ uint size; ++ uint ddlen; ++ void *va; ++ uint alloced; ++ uint16 align; ++ uint16 align_bits; ++ ++ ddlen = sizeof(dma32dd_t); ++ ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ ++ alloced = 0; ++ align_bits = di->dmadesc_align; ++ align = (1 << align_bits); ++ ++ if (direction == DMA_TX) { ++ if ((va = dma_ringalloc(di->osh, D32RINGALIGN, size, &align_bits, &alloced, ++ &di->txdpaorig, &di->tx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ ++ PHYSADDRHISET(di->txdpa, 0); ++ ASSERT(PHYSADDRHI(di->txdpaorig) == 0); ++ di->txd32 = (dma32dd_t *)ROUNDUP((uintptr)va, align); ++ di->txdalign = (uint)((int8 *)(uintptr)di->txd32 - (int8 *)va); ++ ++ PHYSADDRLOSET(di->txdpa, PHYSADDRLO(di->txdpaorig) + di->txdalign); ++ /* Make sure that alignment didn't overflow */ ++ ASSERT(PHYSADDRLO(di->txdpa) >= PHYSADDRLO(di->txdpaorig)); ++ ++ di->txdalloc = alloced; ++ ASSERT(ISALIGNED(di->txd32, align)); ++ } else { ++ if ((va = dma_ringalloc(di->osh, D32RINGALIGN, size, &align_bits, &alloced, ++ &di->rxdpaorig, &di->rx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ ++ PHYSADDRHISET(di->rxdpa, 0); ++ ASSERT(PHYSADDRHI(di->rxdpaorig) == 0); ++ di->rxd32 = (dma32dd_t *)ROUNDUP((uintptr)va, align); ++ di->rxdalign = (uint)((int8 *)(uintptr)di->rxd32 - (int8 *)va); ++ ++ PHYSADDRLOSET(di->rxdpa, PHYSADDRLO(di->rxdpaorig) + di->rxdalign); ++ /* Make sure that alignment didn't overflow */ ++ ASSERT(PHYSADDRLO(di->rxdpa) >= PHYSADDRLO(di->rxdpaorig)); ++ di->rxdalloc = alloced; ++ ASSERT(ISALIGNED(di->rxd32, align)); ++ } ++ ++ return TRUE; ++} ++ ++static bool ++dma32_txreset(dma_info_t *di) ++{ ++ uint32 status; ++ ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ /* suspend tx DMA first */ ++ W_REG(di->osh, &di->d32txregs->control, XC_SE); ++ SPINWAIT(((status = (R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK)) ++ != XS_XS_DISABLED) && ++ (status != XS_XS_IDLE) && ++ (status != XS_XS_STOPPED), ++ (10000)); ++ ++ W_REG(di->osh, &di->d32txregs->control, 0); ++ SPINWAIT(((status = (R_REG(di->osh, ++ &di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED), ++ 10000); ++ ++ /* We should be disabled at this point */ ++ if (status != XS_XS_DISABLED) { ++ DMA_ERROR(("%s: status != D64_XS0_XS_DISABLED 0x%x\n", __FUNCTION__, status)); ++ ASSERT(status == XS_XS_DISABLED); ++ OSL_DELAY(300); ++ } ++ ++ return (status == XS_XS_DISABLED); ++} ++ ++static bool ++dma32_rxidle(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxidle\n", di->name)); ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ return ((R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK) == ++ R_REG(di->osh, &di->d32rxregs->ptr)); ++} ++ ++static bool ++dma32_rxreset(dma_info_t *di) ++{ ++ uint32 status; ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ W_REG(di->osh, &di->d32rxregs->control, 0); ++ SPINWAIT(((status = (R_REG(di->osh, ++ &di->d32rxregs->status) & RS_RS_MASK)) != RS_RS_DISABLED), ++ 10000); ++ ++ return (status == RS_RS_DISABLED); ++} ++ ++static bool ++dma32_rxenabled(dma_info_t *di) ++{ ++ uint32 rc; ++ ++ rc = R_REG(di->osh, &di->d32rxregs->control); ++ return ((rc != 0xffffffff) && (rc & RC_RE)); ++} ++ ++static bool ++dma32_txsuspendedidle(dma_info_t *di) ++{ ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ if (!(R_REG(di->osh, &di->d32txregs->control) & XC_SE)) ++ return 0; ++ ++ if ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE) ++ return 0; ++ ++ OSL_DELAY(2); ++ return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_IDLE); ++} ++ ++/* !! tx entry routine ++ * supports full 32bit dma engine buffer addressing so ++ * dma buffers can cross 4 Kbyte page boundaries. ++ * ++ * WARNING: call must check the return value for error. ++ * the error(toss frames) could be fatal and cause many subsequent hard to debug problems ++ */ ++static int ++dma32_txfast(dma_info_t *di, void *p0, bool commit) ++{ ++ void *p, *next; ++ uchar *data; ++ uint len; ++ uint16 txout; ++ uint32 flags = 0; ++ dmaaddr_t pa; ++ ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ ++ txout = di->txout; ++ ++ /* ++ * Walk the chain of packet buffers ++ * allocating and initializing transmit descriptor entries. ++ */ ++ for (p = p0; p; p = next) { ++ uint nsegs, j; ++ hnddma_seg_map_t *map; ++ ++ data = PKTDATA(di->osh, p); ++ len = PKTLEN(di->osh, p); ++#ifdef BCM_DMAPAD ++ len += PKTDMAPAD(di->osh, p); ++#endif ++ next = PKTNEXT(di->osh, p); ++ ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; ++ ++ if (len == 0) ++ continue; ++ ++ if (DMASGLIST_ENAB) ++ bzero(&di->txp_dmah[txout], sizeof(hnddma_seg_map_t)); ++ ++ /* get physical address of buffer start */ ++ pa = DMA_MAP(di->osh, data, len, DMA_TX, p, &di->txp_dmah[txout]); ++ ++ if (DMASGLIST_ENAB) { ++ map = &di->txp_dmah[txout]; ++ ++ /* See if all the segments can be accounted for */ ++ if (map->nsegs > (uint)(di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1)) ++ goto outoftxd; ++ ++ nsegs = map->nsegs; ++ } else ++ nsegs = 1; ++ ++ for (j = 1; j <= nsegs; j++) { ++ flags = 0; ++ if (p == p0 && j == 1) ++ flags |= CTRL_SOF; ++ ++ /* With a DMA segment list, Descriptor table is filled ++ * using the segment list instead of looping over ++ * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when ++ * end of segment list is reached. ++ */ ++ if ((!DMASGLIST_ENAB && next == NULL) || ++ (DMASGLIST_ENAB && j == nsegs)) ++ flags |= (CTRL_IOC | CTRL_EOF); ++ if (txout == (di->ntxd - 1)) ++ flags |= CTRL_EOT; ++ ++ if (DMASGLIST_ENAB) { ++ len = map->segs[j - 1].length; ++ pa = map->segs[j - 1].addr; ++ } ++ ASSERT(PHYSADDRHI(pa) == 0); ++ ++ dma32_dd_upd(di, di->txd32, pa, txout, &flags, len); ++ ASSERT(di->txp[txout] == NULL); ++ ++ txout = NEXTTXD(txout); ++ } ++ ++ /* See above. No need to loop over individual buffers */ ++ if (DMASGLIST_ENAB) ++ break; ++ } ++ ++ /* if last txd eof not set, fix it */ ++ if (!(flags & CTRL_EOF)) ++ W_SM(&di->txd32[PREVTXD(txout)].ctrl, BUS_SWAP32(flags | CTRL_IOC | CTRL_EOF)); ++ ++ /* save the packet */ ++ di->txp[PREVTXD(txout)] = p0; ++ ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* kick the chip */ ++ if (commit) ++ W_REG(di->osh, &di->d32txregs->ptr, I2B(txout, dma32dd_t)); ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (0); ++ ++outoftxd: ++ DMA_ERROR(("%s: dma_txfast: out of txds\n", di->name)); ++ PKTFREE(di->osh, p0, TRUE); ++ di->hnddma.txavail = 0; ++ di->hnddma.txnobuf++; ++ di->hnddma.txnodesc++; ++ return (-1); ++} ++ ++/* ++ * Reclaim next completed txd (txds if using chained buffers) in the range ++ * specified and return associated packet. ++ * If range is HNDDMA_RANGE_TRANSMITTED, reclaim descriptors that have be ++ * transmitted as noted by the hardware "CurrDescr" pointer. ++ * If range is HNDDMA_RANGE_TRANSFERED, reclaim descriptors that have be ++ * transfered by the DMA as noted by the hardware "ActiveDescr" pointer. ++ * If range is HNDDMA_RANGE_ALL, reclaim all txd(s) posted to the ring and ++ * return associated packet regardless of the value of hardware pointers. ++ */ ++static void * ++dma32_getnexttxp(dma_info_t *di, txd_range_t range) ++{ ++ uint16 start, end, i; ++ uint16 active_desc; ++ void *txp; ++ ++ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, ++ (range == HNDDMA_RANGE_ALL) ? "all" : ++ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); ++ ++ if (di->ntxd == 0) ++ return (NULL); ++ ++ txp = NULL; ++ ++ start = di->txin; ++ if (range == HNDDMA_RANGE_ALL) ++ end = di->txout; ++ else { ++ dma32regs_t *dregs = di->d32txregs; ++ ++ if (di->txin == di->xs0cd) { ++ end = (uint16)B2I(R_REG(di->osh, &dregs->status) & XS_CD_MASK, dma32dd_t); ++ di->xs0cd = end; ++ } else ++ end = di->xs0cd; ++ ++ if (range == HNDDMA_RANGE_TRANSFERED) { ++ active_desc = (uint16)((R_REG(di->osh, &dregs->status) & XS_AD_MASK) >> ++ XS_AD_SHIFT); ++ active_desc = (uint16)B2I(active_desc, dma32dd_t); ++ if (end != active_desc) ++ end = PREVTXD(active_desc); ++ } ++ } ++ ++ if ((start == 0) && (end > di->txout)) ++ goto bogus; ++ ++ for (i = start; i != end && !txp; i = NEXTTXD(i)) { ++ dmaaddr_t pa; ++ hnddma_seg_map_t *map = NULL; ++ uint size, j, nsegs; ++ ++ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->txd32[i].addr)) - di->dataoffsetlow)); ++ PHYSADDRHISET(pa, 0); ++ ++ if (DMASGLIST_ENAB) { ++ map = &di->txp_dmah[i]; ++ size = map->origsize; ++ nsegs = map->nsegs; ++ } else { ++ size = (BUS_SWAP32(R_SM(&di->txd32[i].ctrl)) & CTRL_BC_MASK); ++ nsegs = 1; ++ } ++ ++ for (j = nsegs; j > 0; j--) { ++ W_SM(&di->txd32[i].addr, 0xdeadbeef); ++ ++ txp = di->txp[i]; ++ di->txp[i] = NULL; ++ if (j > 1) ++ i = NEXTTXD(i); ++ } ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ DMA_UNMAP(di->osh, pa, size, DMA_TX, txp, map); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++ } ++ ++ di->txin = i; ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (txp); ++ ++bogus: ++ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", ++ start, end, di->txout, forceall)); ++ return (NULL); ++} ++ ++static void * ++dma32_getnextrxp(dma_info_t *di, bool forceall) ++{ ++ uint16 i, curr; ++ void *rxp; ++ dmaaddr_t pa; ++ /* if forcing, dma engine must be disabled */ ++ ASSERT(!forceall || !dma32_rxenabled(di)); ++ ++ i = di->rxin; ++ ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return (NULL); ++ ++ if (di->rxin == di->rs0cd) { ++ curr = (uint16)B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, dma32dd_t); ++ di->rs0cd = curr; ++ } else ++ curr = di->rs0cd; ++ ++ /* ignore curr if forceall */ ++ if (!forceall && (i == curr)) ++ return (NULL); ++ ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ ASSERT(rxp); ++ di->rxp[i] = NULL; ++ ++ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->rxd32[i].addr)) - di->dataoffsetlow)); ++ PHYSADDRHISET(pa, 0); ++ ++ /* clear this packet from the descriptor ring */ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ DMA_UNMAP(di->osh, pa, ++ di->rxbufsize, DMA_RX, rxp, &di->rxp_dmah[i]); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++ ++ W_SM(&di->rxd32[i].addr, 0xdeadbeef); ++ ++ di->rxin = NEXTRXD(i); ++ ++ return (rxp); ++} ++ ++/* ++ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). ++ */ ++static void ++dma32_txrotate(dma_info_t *di) ++{ ++ uint16 ad; ++ uint nactive; ++ uint rot; ++ uint16 old, new; ++ uint32 w; ++ uint16 first, last; ++ ++ ASSERT(dma32_txsuspendedidle(di)); ++ ++ nactive = _dma_txactive(di); ++ ad = B2I(((R_REG(di->osh, &di->d32txregs->status) & XS_AD_MASK) >> XS_AD_SHIFT), dma32dd_t); ++ rot = TXD(ad - di->txin); ++ ++ ASSERT(rot < di->ntxd); ++ ++ /* full-ring case is a lot harder - don't worry about this */ ++ if (rot >= (di->ntxd - nactive)) { ++ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); ++ return; ++ } ++ ++ first = di->txin; ++ last = PREVTXD(di->txout); ++ ++ /* move entries starting at last and moving backwards to first */ ++ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { ++ new = TXD(old + rot); ++ ++ /* ++ * Move the tx dma descriptor. ++ * EOT is set only in the last entry in the ring. ++ */ ++ w = BUS_SWAP32(R_SM(&di->txd32[old].ctrl)) & ~CTRL_EOT; ++ if (new == (di->ntxd - 1)) ++ w |= CTRL_EOT; ++ W_SM(&di->txd32[new].ctrl, BUS_SWAP32(w)); ++ W_SM(&di->txd32[new].addr, R_SM(&di->txd32[old].addr)); ++ ++ /* zap the old tx dma descriptor address field */ ++ W_SM(&di->txd32[old].addr, BUS_SWAP32(0xdeadbeef)); ++ ++ /* move the corresponding txp[] entry */ ++ ASSERT(di->txp[new] == NULL); ++ di->txp[new] = di->txp[old]; ++ ++ /* Move the segment map as well */ ++ if (DMASGLIST_ENAB) { ++ bcopy(&di->txp_dmah[old], &di->txp_dmah[new], sizeof(hnddma_seg_map_t)); ++ bzero(&di->txp_dmah[old], sizeof(hnddma_seg_map_t)); ++ } ++ ++ di->txp[old] = NULL; ++ } ++ ++ /* update txin and txout */ ++ di->txin = ad; ++ di->txout = TXD(di->txout + rot); ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ /* kick the chip */ ++ W_REG(di->osh, &di->d32txregs->ptr, I2B(di->txout, dma32dd_t)); ++} ++ ++/* 64-bit DMA functions */ ++ ++static void ++dma64_txinit(dma_info_t *di) ++{ ++ uint32 control; ++ ++ DMA_TRACE(("%s: dma_txinit\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ di->txin = di->txout = di->xs0cd = di->xs0cd_snapshot = 0; ++ di->hnddma.txavail = di->ntxd - 1; ++ ++ /* clear tx descriptor ring */ ++ BZERO_SM((void *)(uintptr)di->txd64, (di->ntxd * sizeof(dma64dd_t))); ++ ++ /* These bits 20:18 (burstLen) of control register can be written but will take ++ * effect only if these bits are valid. So this will not affect previous versions ++ * of the DMA. They will continue to have those bits set to 0. ++ */ ++ control = R_REG(di->osh, &di->d64txregs->control); ++ control = (control & ~D64_XC_BL_MASK) | (di->txburstlen << D64_XC_BL_SHIFT); ++ control = (control & ~D64_XC_MR_MASK) | (di->txmultioutstdrd << D64_XC_MR_SHIFT); ++ control = (control & ~D64_XC_PC_MASK) | (di->txprefetchctl << D64_XC_PC_SHIFT); ++ control = (control & ~D64_XC_PT_MASK) | (di->txprefetchthresh << D64_XC_PT_SHIFT); ++ W_REG(di->osh, &di->d64txregs->control, control); ++ ++ control = D64_XC_XE; ++ /* DMA engine with out alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (!di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++ ++ if ((di->hnddma.dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= D64_XC_PD; ++ OR_REG(di->osh, &di->d64txregs->control, control); ++ ++ /* DMA engine with alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++} ++ ++static bool ++dma64_txenabled(dma_info_t *di) ++{ ++ uint32 xc; ++ ++ /* If the chip is dead, it is not enabled :-) */ ++ xc = R_REG(di->osh, &di->d64txregs->control); ++ return ((xc != 0xffffffff) && (xc & D64_XC_XE)); ++} ++ ++static void ++dma64_txsuspend(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(di->osh, &di->d64txregs->control, D64_XC_SE); ++} ++ ++static void ++dma64_txresume(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txresume\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ AND_REG(di->osh, &di->d64txregs->control, ~D64_XC_SE); ++} ++ ++static bool ++dma64_txsuspended(dma_info_t *di) ++{ ++ return (di->ntxd == 0) || ++ ((R_REG(di->osh, &di->d64txregs->control) & D64_XC_SE) == D64_XC_SE); ++} ++ ++#ifdef WL_MULTIQUEUE ++static void ++dma64_txflush(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txflush\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(di->osh, &di->d64txregs->control, D64_XC_SE | D64_XC_FL); ++} ++ ++static void ++dma64_txflush_clear(dma_info_t *di) ++{ ++ uint32 status; ++ ++ DMA_TRACE(("%s: dma_txflush_clear\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != ++ D64_XS0_XS_DISABLED) && ++ (status != D64_XS0_XS_IDLE) && ++ (status != D64_XS0_XS_STOPPED), ++ 10000); ++ AND_REG(di->osh, &di->d64txregs->control, ~D64_XC_FL); ++} ++#endif /* WL_MULTIQUEUE */ ++ ++static void BCMFASTPATH ++dma64_txreclaim(dma_info_t *di, txd_range_t range) ++{ ++ void *p; ++ ++ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, ++ (range == HNDDMA_RANGE_ALL) ? "all" : ++ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); ++ ++ if (di->txin == di->txout) ++ return; ++ ++ while ((p = dma64_getnexttxp(di, range))) { ++ /* For unframed data, we don't have any packets to free */ ++ if (!(di->hnddma.dmactrlflags & DMA_CTRL_UNFRAMED)) ++ PKTFREE(di->osh, p, TRUE); ++ } ++} ++ ++static bool ++dma64_txstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_STOPPED); ++} ++ ++static bool ++dma64_rxstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK) == D64_RS0_RS_STOPPED); ++} ++ ++static bool ++dma64_alloc(dma_info_t *di, uint direction) ++{ ++ uint32 size; ++ uint ddlen; ++ void *va; ++ uint alloced = 0; ++ uint32 align; ++ uint16 align_bits; ++ ++ ddlen = sizeof(dma64dd_t); ++ ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ align_bits = di->dmadesc_align; ++ align = (1 << align_bits); ++ ++ if (direction == DMA_TX) { ++ if ((va = dma_ringalloc(di->osh, ++ (di->d64_xs0_cd_mask == 0x1fff) ? D64RINGBOUNDARY : D64RINGBOUNDARY_LARGE, ++ size, &align_bits, &alloced, ++ &di->txdpaorig, &di->tx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ align = (1 << align_bits); ++ ++ /* adjust the pa by rounding up to the alignment */ ++ PHYSADDRLOSET(di->txdpa, ROUNDUP(PHYSADDRLO(di->txdpaorig), align)); ++ PHYSADDRHISET(di->txdpa, PHYSADDRHI(di->txdpaorig)); ++ ++ /* Make sure that alignment didn't overflow */ ++ ASSERT(PHYSADDRLO(di->txdpa) >= PHYSADDRLO(di->txdpaorig)); ++ ++ /* find the alignment offset that was used */ ++ di->txdalign = (uint)(PHYSADDRLO(di->txdpa) - PHYSADDRLO(di->txdpaorig)); ++ ++ /* adjust the va by the same offset */ ++ di->txd64 = (dma64dd_t *)((uintptr)va + di->txdalign); ++ ++ /* printk("%s di->txd64(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->txd64), PHYSADDRLO(di->txd64)); */ ++ /* printk("%s di->txdpa(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->txdpa), PHYSADDRLO(di->txdpa)); */ ++ di->txdalloc = alloced; ++ ASSERT(ISALIGNED(PHYSADDRLO(di->txdpa), align)); ++ } else { ++ if ((va = dma_ringalloc(di->osh, ++ (di->d64_rs0_cd_mask == 0x1fff) ? D64RINGBOUNDARY : D64RINGBOUNDARY_LARGE, ++ size, &align_bits, &alloced, ++ &di->rxdpaorig, &di->rx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ align = (1 << align_bits); ++ ++ /* adjust the pa by rounding up to the alignment */ ++ PHYSADDRLOSET(di->rxdpa, ROUNDUP(PHYSADDRLO(di->rxdpaorig), align)); ++ PHYSADDRHISET(di->rxdpa, PHYSADDRHI(di->rxdpaorig)); ++ ++ /* Make sure that alignment didn't overflow */ ++ ASSERT(PHYSADDRLO(di->rxdpa) >= PHYSADDRLO(di->rxdpaorig)); ++ ++ /* find the alignment offset that was used */ ++ di->rxdalign = (uint)(PHYSADDRLO(di->rxdpa) - PHYSADDRLO(di->rxdpaorig)); ++ ++ /* adjust the va by the same offset */ ++ di->rxd64 = (dma64dd_t *)((uintptr)va + di->rxdalign); ++ ++ /* printk("%s di->rxd64(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->rxd64), PHYSADDRLO(di->rxd64)); */ ++ /* printk("%s di->rxdpa(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->rxdpa), PHYSADDRLO(di->rxdpa)); */ ++ di->rxdalloc = alloced; ++ ASSERT(ISALIGNED(PHYSADDRLO(di->rxdpa), align)); ++ } ++ ++ return TRUE; ++} ++ ++static bool ++dma64_txreset(dma_info_t *di) ++{ ++ uint32 status; ++ ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ /* suspend tx DMA first */ ++ W_REG(di->osh, &di->d64txregs->control, D64_XC_SE); ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != ++ D64_XS0_XS_DISABLED) && ++ (status != D64_XS0_XS_IDLE) && ++ (status != D64_XS0_XS_STOPPED), ++ 10000); ++ ++ W_REG(di->osh, &di->d64txregs->control, 0); ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != ++ D64_XS0_XS_DISABLED), ++ 10000); ++ ++ /* We should be disabled at this point */ ++ if (status != D64_XS0_XS_DISABLED) { ++ DMA_ERROR(("%s: status != D64_XS0_XS_DISABLED 0x%x\n", __FUNCTION__, status)); ++ ASSERT(status == D64_XS0_XS_DISABLED); ++ OSL_DELAY(300); ++ } ++ ++ return (status == D64_XS0_XS_DISABLED); ++} ++ ++static bool ++dma64_rxidle(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxidle\n", di->name)); ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ return ((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) == ++ (R_REG(di->osh, &di->d64rxregs->ptr) & D64_RS0_CD_MASK)); ++} ++ ++static bool ++dma64_rxreset(dma_info_t *di) ++{ ++ uint32 status; ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ W_REG(di->osh, &di->d64rxregs->control, 0); ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK)) != ++ D64_RS0_RS_DISABLED), 10000); ++ ++ return (status == D64_RS0_RS_DISABLED); ++} ++ ++static bool ++dma64_rxenabled(dma_info_t *di) ++{ ++ uint32 rc; ++ ++ rc = R_REG(di->osh, &di->d64rxregs->control); ++ return ((rc != 0xffffffff) && (rc & D64_RC_RE)); ++} ++ ++static bool ++dma64_txsuspendedidle(dma_info_t *di) ++{ ++ ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ if (!(R_REG(di->osh, &di->d64txregs->control) & D64_XC_SE)) ++ return 0; ++ ++ if ((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_IDLE) ++ return 1; ++ ++ return 0; ++} ++ ++/* Useful when sending unframed data. This allows us to get a progress report from the DMA. ++ * We return a pointer to the beginning of the data buffer of the current descriptor. ++ * If DMA is idle, we return NULL. ++ */ ++static void* ++dma64_getpos(dma_info_t *di, bool direction) ++{ ++ void *va; ++ bool idle; ++ uint16 cur_idx; ++ ++ if (direction == DMA_TX) { ++ cur_idx = B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); ++ idle = !NTXDACTIVE(di->txin, di->txout); ++ va = di->txp[cur_idx]; ++ } else { ++ cur_idx = B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ idle = !NRXDACTIVE(di->rxin, di->rxout); ++ va = di->rxp[cur_idx]; ++ } ++ ++ /* If DMA is IDLE, return NULL */ ++ if (idle) { ++ DMA_TRACE(("%s: DMA idle, return NULL\n", __FUNCTION__)); ++ va = NULL; ++ } ++ ++ return va; ++} ++ ++/* TX of unframed data ++ * ++ * Adds a DMA ring descriptor for the data pointed to by "buf". ++ * This is for DMA of a buffer of data and is unlike other hnddma TX functions ++ * that take a pointer to a "packet" ++ * Each call to this is results in a single descriptor being added for "len" bytes of ++ * data starting at "buf", it doesn't handle chained buffers. ++ */ ++static int ++dma64_txunframed(dma_info_t *di, void *buf, uint len, bool commit) ++{ ++ uint16 txout; ++ uint32 flags = 0; ++ dmaaddr_t pa; /* phys addr */ ++ ++ txout = di->txout; ++ ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; ++ ++ if (len == 0) ++ return 0; ++ ++#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) ++ pa = virt_to_phys(buf); ++#else ++ pa = DMA_MAP(di->osh, buf, len, DMA_TX, NULL, &di->txp_dmah[txout]); ++#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ ++ ++ flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF); ++ ++ if (txout == (di->ntxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); ++ ASSERT(di->txp[txout] == NULL); ++ ++ /* save the buffer pointer - used by dma_getpos */ ++ di->txp[txout] = buf; ++ ++ txout = NEXTTXD(txout); ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* kick the chip */ ++ if (commit) { ++ W_REG(di->osh, &di->d64txregs->ptr, di->xmtptrbase + I2B(txout, dma64dd_t)); ++ } ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (0); ++ ++outoftxd: ++ DMA_ERROR(("%s: %s: out of txds !!!\n", di->name, __FUNCTION__)); ++ di->hnddma.txavail = 0; ++ di->hnddma.txnobuf++; ++ return (-1); ++} ++ ++/* RX of unframed data ++ * ++ * Adds a DMA ring descriptor for the data pointed to by "buf". ++ * This is for DMA of a buffer of data and is unlike other hnddma TX functions ++ * that take a pointer to a "packet" ++ * Each call to this is results in a single descriptor being added for "len" bytes of ++ * data starting at "buf", it doesn't handle chained buffers. ++ */ ++static int ++dma64_rxunframed(dma_info_t *di, void *buf, uint len, bool commit) ++{ ++ uint16 rxout; ++ uint32 flags = 0; ++ dmaaddr_t pa; /* phys addr */ ++ ++ rxout = di->rxout; ++ ++ /* return nonzero if out of rx descriptors */ ++ if (NEXTRXD(rxout) == di->rxin) ++ goto outofrxd; ++ ++ if (len == 0) ++ return 0; ++ ++#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) ++ pa = virt_to_phys(buf); ++#else ++ pa = DMA_MAP(di->osh, buf, len, DMA_RX, NULL, &di->rxp_dmah[rxout]); ++#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ ++ ++ flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF); ++ ++ if (rxout == (di->nrxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->rxd64, pa, rxout, &flags, len); ++ ASSERT(di->rxp[rxout] == NULL); ++ ++ /* save the buffer pointer - used by dma_getpos */ ++ di->rxp[rxout] = buf; ++ ++ rxout = NEXTRXD(rxout); ++ /* bump the tx descriptor index */ ++ di->rxout = rxout; ++ ++ /* kick the chip */ ++ if (commit) { ++ W_REG(di->osh, &di->d64rxregs->ptr, di->rcvptrbase + I2B(rxout, dma64dd_t)); ++ //DBG("%s (Control Reg)W_REG: 0x%x Value: 0x%x\n", __FUNCTION__, &di->d64rxregs->ptr, di->rcvptrbase + I2B(rxout, dma64dd_t)); ++ } ++ ++ /* tx flow control */ ++ //di->hnddma.rxavail = di->nrxd - NRXDACTIVE(di->rxin, di->rxout) - 1; ++ ++ return (0); ++ ++outofrxd: ++ DMA_ERROR(("%s: %s: out of rxds !!!\n", di->name, __FUNCTION__)); ++ //di->hnddma.rxavail = 0; ++ di->hnddma.rxnobuf++; ++ return (-1); ++} ++ ++/* !! tx entry routine ++ * WARNING: call must check the return value for error. ++ * the error(toss frames) could be fatal and cause many subsequent hard to debug problems ++ */ ++static int BCMFASTPATH ++dma64_txfast(dma_info_t *di, void *p0, bool commit) ++{ ++ void *p, *next; ++ uchar *data; ++ uint len; ++ uint16 txout; ++ uint32 flags = 0; ++ dmaaddr_t pa; ++ bool war; ++ ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ ++ txout = di->txout; ++ war = (di->hnddma.dmactrlflags & DMA_CTRL_DMA_AVOIDANCE_WAR) ? TRUE : FALSE; ++ ++ /* ++ * Walk the chain of packet buffers ++ * allocating and initializing transmit descriptor entries. ++ */ ++ for (p = p0; p; p = next) { ++ uint nsegs, j, segsadd; ++ hnddma_seg_map_t *map = NULL; ++ ++ data = PKTDATA(di->osh, p); ++ len = PKTLEN(di->osh, p); ++#ifdef BCM_DMAPAD ++ len += PKTDMAPAD(di->osh, p); ++#endif /* BCM_DMAPAD */ ++ next = PKTNEXT(di->osh, p); ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(next, SKB_PREFETCH_LEN); ++#endif ++ ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; ++ ++ if (len == 0) ++ continue; ++ ++ /* get physical address of buffer start */ ++ if (DMASGLIST_ENAB) ++ bzero(&di->txp_dmah[txout], sizeof(hnddma_seg_map_t)); ++ ++#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) ++ pa = virt_to_phys(data); ++#else ++ pa = DMA_MAP(di->osh, data, len, DMA_TX, p, &di->txp_dmah[txout]); ++#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ ++ ++ ++ if (DMASGLIST_ENAB) { ++ map = &di->txp_dmah[txout]; ++ ++ /* See if all the segments can be accounted for */ ++ if (map->nsegs > (uint)(di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1)) ++ goto outoftxd; ++ ++ nsegs = map->nsegs; ++ } else ++ nsegs = 1; ++ ++ segsadd = 0; ++ for (j = 1; j <= nsegs; j++) { ++ flags = 0; ++ if (p == p0 && j == 1) ++ flags |= D64_CTRL1_SOF; ++ ++ /* With a DMA segment list, Descriptor table is filled ++ * using the segment list instead of looping over ++ * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when ++ * end of segment list is reached. ++ */ ++ if ((!DMASGLIST_ENAB && next == NULL) || ++ (DMASGLIST_ENAB && j == nsegs)) ++ flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF); ++ if (txout == (di->ntxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ ++ if (DMASGLIST_ENAB) { ++ len = map->segs[j - 1].length; ++ pa = map->segs[j - 1].addr; ++ if (len > 128 && war) { ++ uint remain, new_len, align64; ++ /* check for 64B aligned of pa */ ++ align64 = (uint)(PHYSADDRLO(pa) & 0x3f); ++ align64 = (64 - align64) & 0x3f; ++ new_len = len - align64; ++ remain = new_len % 128; ++ if (remain > 0 && remain <= 4) { ++ uint32 buf_addr_lo; ++ uint32 tmp_flags = ++ flags & (~(D64_CTRL1_EOF | D64_CTRL1_IOC)); ++ flags &= ~(D64_CTRL1_SOF | D64_CTRL1_EOT); ++ remain += 64; ++ dma64_dd_upd(di, di->txd64, pa, txout, ++ &tmp_flags, len-remain); ++ ASSERT(di->txp[txout] == NULL); ++ txout = NEXTTXD(txout); ++ /* return nonzero if out of tx descriptors */ ++ if (txout == di->txin) { ++ DMA_ERROR(("%s: dma_txfast: Out-of-DMA" ++ " descriptors (txin %d txout %d" ++ " nsegs %d)\n", __FUNCTION__, ++ di->txin, di->txout, nsegs)); ++ goto outoftxd; ++ } ++ if (txout == (di->ntxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ buf_addr_lo = PHYSADDRLO(pa); ++ PHYSADDRLOSET(pa, (PHYSADDRLO(pa) + (len-remain))); ++ if (PHYSADDRLO(pa) < buf_addr_lo) { ++ PHYSADDRHISET(pa, (PHYSADDRHI(pa) + 1)); ++ } ++ len = remain; ++ segsadd++; ++ di->dma_avoidance_cnt++; ++ } ++ } ++ } ++ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); ++ ASSERT(di->txp[txout] == NULL); ++ ++ txout = NEXTTXD(txout); ++ /* return nonzero if out of tx descriptors */ ++ if (txout == di->txin) { ++ DMA_ERROR(("%s: dma_txfast: Out-of-DMA descriptors" ++ " (txin %d txout %d nsegs %d)\n", __FUNCTION__, ++ di->txin, di->txout, nsegs)); ++ goto outoftxd; ++ } ++ } ++ if (segsadd && DMASGLIST_ENAB) ++ map->nsegs += segsadd; ++ ++ /* See above. No need to loop over individual buffers */ ++ if (DMASGLIST_ENAB) ++ break; ++ } ++ ++ /* if last txd eof not set, fix it */ ++ if (!(flags & D64_CTRL1_EOF)) { ++ W_SM(&di->txd64[PREVTXD(txout)].ctrl1, ++ BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF)); ++ } ++ ++ /* save the packet */ ++ di->txp[PREVTXD(txout)] = p0; ++ ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* Spin lock to prevent TX discriptor protocol errors when using SG lists */ ++ spin_lock(&di->des_lock); ++ spin_unlock(&di->des_lock); ++ ++ /* kick the chip */ ++ if (commit) ++ W_REG(di->osh, &di->d64txregs->ptr, di->xmtptrbase + I2B(txout, dma64dd_t)); ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (0); ++ ++outoftxd: ++ DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name)); ++ PKTFREE(di->osh, p0, TRUE); ++ di->hnddma.txavail = 0; ++ di->hnddma.txnobuf++; ++ return (-1); ++} ++ ++/* ++ * Reclaim next completed txd (txds if using chained buffers) in the range ++ * specified and return associated packet. ++ * If range is HNDDMA_RANGE_TRANSMITTED, reclaim descriptors that have be ++ * transmitted as noted by the hardware "CurrDescr" pointer. ++ * If range is HNDDMA_RANGE_TRANSFERED, reclaim descriptors that have be ++ * transfered by the DMA as noted by the hardware "ActiveDescr" pointer. ++ * If range is HNDDMA_RANGE_ALL, reclaim all txd(s) posted to the ring and ++ * return associated packet regardless of the value of hardware pointers. ++ */ ++static void * BCMFASTPATH ++dma64_getnexttxp(dma_info_t *di, txd_range_t range) ++{ ++ uint16 start, end, i; ++ uint16 active_desc; ++ void *txp; ++ ++ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, ++ (range == HNDDMA_RANGE_ALL) ? "all" : ++ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); ++ ++ if (di->ntxd == 0) ++ return (NULL); ++ ++ txp = NULL; ++ ++ start = di->txin; ++ if (range == HNDDMA_RANGE_ALL) ++ end = di->txout; ++ else { ++ dma64regs_t *dregs = di->d64txregs; ++ ++ if (di->txin == di->xs0cd) { ++ end = (uint16)(B2I(((R_REG(di->osh, &dregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t)); ++ di->xs0cd = end; ++ } else ++ end = di->xs0cd; ++ ++ if (range == HNDDMA_RANGE_TRANSFERED) { ++ active_desc = (uint16)(R_REG(di->osh, &dregs->status1) & D64_XS1_AD_MASK); ++ active_desc = (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK; ++ active_desc = B2I(active_desc, dma64dd_t); ++ if (end != active_desc) ++ end = PREVTXD(active_desc); ++ } ++ } ++ ++ if ((start == 0) && (end > di->txout)) ++ goto bogus; ++ ++ for (i = start; i != end && !txp; i = NEXTTXD(i)) { ++ dmaaddr_t pa; ++ hnddma_seg_map_t *map = NULL; ++ uint size, j, nsegs; ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(di->txp[NEXTTXD(i)], SKB_PREFETCH_LEN); ++#endif ++ ++ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->txd64[i].addrlow)) - di->dataoffsetlow)); ++ PHYSADDRHISET(pa, (BUS_SWAP32(R_SM(&di->txd64[i].addrhigh)) - di->dataoffsethigh)); ++ ++ if (DMASGLIST_ENAB) { ++ map = &di->txp_dmah[i]; ++ size = map->origsize; ++ nsegs = map->nsegs; ++ if (nsegs > (uint)NTXDACTIVE(i, end)) { ++ di->xs0cd = i; ++ break; ++ } ++ } else { ++ size = (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) & D64_CTRL2_BC_MASK); ++ nsegs = 1; ++ } ++ ++ for (j = nsegs; j > 0; j--) { ++ W_SM(&di->txd64[i].addrlow, 0xdeadbeef); ++ W_SM(&di->txd64[i].addrhigh, 0xdeadbeef); ++ ++ txp = di->txp[i]; ++ di->txp[i] = NULL; ++ if (j > 1) ++ i = NEXTTXD(i); ++ } ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ DMA_UNMAP(di->osh, pa, size, DMA_TX, txp, map); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++ } ++ ++ di->txin = i; ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (txp); ++ ++bogus: ++ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", ++ start, end, di->txout, forceall)); ++ return (NULL); ++} ++ ++static void * BCMFASTPATH ++dma64_getnextrxp(dma_info_t *di, bool forceall) ++{ ++ uint16 i, curr; ++ void *rxp; ++ dmaaddr_t pa; ++ ++ /* if forcing, dma engine must be disabled */ ++ ASSERT(!forceall || !dma64_rxenabled(di)); ++ ++ i = di->rxin; ++ ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return (NULL); ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(di->rxp[NEXTRXD(i)], SKB_PREFETCH_LEN); ++#endif ++ ++ if (di->rxin == di->rs0cd) { ++ curr = (uint16)B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ di->rs0cd = curr; ++ } else ++ curr = di->rs0cd; ++ ++ /* ignore curr if forceall */ ++ if (!forceall && (i == curr)) ++ return (NULL); ++ ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ ASSERT(rxp); ++ di->rxp[i] = NULL; ++ ++ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->rxd64[i].addrlow)) - di->dataoffsetlow)); ++ PHYSADDRHISET(pa, (BUS_SWAP32(R_SM(&di->rxd64[i].addrhigh)) - di->dataoffsethigh)); ++ ++ /* clear this packet from the descriptor ring */ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ DMA_UNMAP(di->osh, pa, ++ di->rxbufsize, DMA_RX, rxp, &di->rxp_dmah[i]); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++ ++ W_SM(&di->rxd64[i].addrlow, 0xdeadbeef); ++ W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef); ++ ++ di->rxin = NEXTRXD(i); ++ ++ return (rxp); ++} ++ ++static bool ++_dma64_addrext(osl_t *osh, dma64regs_t *dma64regs) ++{ ++ uint32 w; ++ OR_REG(osh, &dma64regs->control, D64_XC_AE); ++ w = R_REG(osh, &dma64regs->control); ++ AND_REG(osh, &dma64regs->control, ~D64_XC_AE); ++ return ((w & D64_XC_AE) == D64_XC_AE); ++} ++ ++/* ++ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). ++ */ ++static void ++dma64_txrotate(dma_info_t *di) ++{ ++ uint16 ad; ++ uint nactive; ++ uint rot; ++ uint16 old, new; ++ uint32 w; ++ uint16 first, last; ++ ++ ASSERT(dma64_txsuspendedidle(di)); ++ ++ nactive = _dma_txactive(di); ++ ad = B2I((((R_REG(di->osh, &di->d64txregs->status1) & D64_XS1_AD_MASK) ++ - di->xmtptrbase) & D64_XS1_AD_MASK), dma64dd_t); ++ rot = TXD(ad - di->txin); ++ ++ ASSERT(rot < di->ntxd); ++ ++ /* full-ring case is a lot harder - don't worry about this */ ++ if (rot >= (di->ntxd - nactive)) { ++ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); ++ return; ++ } ++ ++ first = di->txin; ++ last = PREVTXD(di->txout); ++ ++ /* move entries starting at last and moving backwards to first */ ++ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { ++ new = TXD(old + rot); ++ ++ /* ++ * Move the tx dma descriptor. ++ * EOT is set only in the last entry in the ring. ++ */ ++ w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl1)) & ~D64_CTRL1_EOT; ++ if (new == (di->ntxd - 1)) ++ w |= D64_CTRL1_EOT; ++ W_SM(&di->txd64[new].ctrl1, BUS_SWAP32(w)); ++ ++ w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl2)); ++ W_SM(&di->txd64[new].ctrl2, BUS_SWAP32(w)); ++ ++ W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow)); ++ W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh)); ++ ++ /* zap the old tx dma descriptor address field */ ++ W_SM(&di->txd64[old].addrlow, BUS_SWAP32(0xdeadbeef)); ++ W_SM(&di->txd64[old].addrhigh, BUS_SWAP32(0xdeadbeef)); ++ ++ /* move the corresponding txp[] entry */ ++ ASSERT(di->txp[new] == NULL); ++ di->txp[new] = di->txp[old]; ++ ++ /* Move the map */ ++ if (DMASGLIST_ENAB) { ++ bcopy(&di->txp_dmah[old], &di->txp_dmah[new], sizeof(hnddma_seg_map_t)); ++ bzero(&di->txp_dmah[old], sizeof(hnddma_seg_map_t)); ++ } ++ ++ di->txp[old] = NULL; ++ } ++ ++ /* update txin and txout */ ++ di->txin = ad; ++ di->txout = TXD(di->txout + rot); ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ /* kick the chip */ ++ W_REG(di->osh, &di->d64txregs->ptr, di->xmtptrbase + I2B(di->txout, dma64dd_t)); ++} ++ ++uint ++BCMATTACHFN(dma_addrwidth)(si_t *sih, void *dmaregs) ++{ ++ dma32regs_t *dma32regs; ++ osl_t *osh; ++ ++ osh = si_osh(sih); ++ ++ /* Perform 64-bit checks only if we want to advertise 64-bit (> 32bit) capability) */ ++ /* DMA engine is 64-bit capable */ ++ if ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64) { ++ /* backplane are 64-bit capable */ ++ if (si_backplane64(sih)) ++ /* If bus is System Backplane or PCIE then we can access 64-bits */ ++ if ((BUSTYPE(sih->bustype) == SI_BUS) || ++ ((BUSTYPE(sih->bustype) == PCI_BUS) && ++ ((sih->buscoretype == PCIE_CORE_ID) || ++ (sih->buscoretype == PCIE2_CORE_ID)))) ++ return (DMADDRWIDTH_64); ++ ++ /* DMA64 is always 32-bit capable, AE is always TRUE */ ++ ASSERT(_dma64_addrext(osh, (dma64regs_t *)dmaregs)); ++ ++ return (DMADDRWIDTH_32); ++ } ++ ++ /* Start checking for 32-bit / 30-bit addressing */ ++ dma32regs = (dma32regs_t *)dmaregs; ++ ++ /* For System Backplane, PCIE bus or addrext feature, 32-bits ok */ ++ if ((BUSTYPE(sih->bustype) == SI_BUS) || ++ ((BUSTYPE(sih->bustype) == PCI_BUS) && ++ ((sih->buscoretype == PCIE_CORE_ID) || ++ (sih->buscoretype == PCIE2_CORE_ID))) || ++ (_dma32_addrext(osh, dma32regs))) ++ return (DMADDRWIDTH_32); ++ ++ /* Fallthru */ ++ return (DMADDRWIDTH_30); ++} ++ ++static int ++_dma_pktpool_set(dma_info_t *di, pktpool_t *pool) ++{ ++ ASSERT(di); ++ ASSERT(di->pktpool == NULL); ++ di->pktpool = pool; ++ return 0; ++} ++ ++static bool ++_dma_rxtx_error(dma_info_t *di, bool istx) ++{ ++ uint32 status1 = 0; ++ uint16 curr; ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ ++ if (istx) { ++ ++ status1 = R_REG(di->osh, &di->d64txregs->status1); ++ ++ if ((status1 & D64_XS1_XE_MASK) != D64_XS1_XE_NOERR) ++ return TRUE; ++ else if (si_coreid(di->sih) == GMAC_CORE_ID && si_corerev(di->sih) >= 4) { ++ curr = (uint16)(B2I(((R_REG(di->osh, &di->d64txregs->status0) & ++ D64_XS0_CD_MASK) - di->xmtptrbase) & ++ D64_XS0_CD_MASK, dma64dd_t)); ++ ++ if (NTXDACTIVE(di->txin, di->txout) != 0 && ++ curr == di->xs0cd_snapshot) { ++ ++ /* suspicious */ ++ return TRUE; ++ } ++ di->xs0cd_snapshot = di->xs0cd = curr; ++ ++ return FALSE; ++ } ++ else ++ return FALSE; ++ } ++ else { ++ ++ status1 = R_REG(di->osh, &di->d64rxregs->status1); ++ ++ if ((status1 & D64_RS1_RE_MASK) != D64_RS1_RE_NOERR) ++ return TRUE; ++ else ++ return FALSE; ++ } ++ ++ } else if (DMA32_ENAB(di)) { ++ return FALSE; ++ ++ } else { ++ ASSERT(0); ++ return FALSE; ++ } ++ ++} ++ ++void ++_dma_burstlen_set(dma_info_t *di, uint8 rxburstlen, uint8 txburstlen) ++{ ++ di->rxburstlen = rxburstlen; ++ di->txburstlen = txburstlen; ++} ++ ++void ++_dma_param_set(dma_info_t *di, uint16 paramid, uint16 paramval) ++{ ++ switch (paramid) { ++ case HNDDMA_PID_TX_MULTI_OUTSTD_RD: ++ di->txmultioutstdrd = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_TX_PREFETCH_CTL: ++ di->txprefetchctl = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_TX_PREFETCH_THRESH: ++ di->txprefetchthresh = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_TX_BURSTLEN: ++ di->txburstlen = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_RX_PREFETCH_CTL: ++ di->rxprefetchctl = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_RX_PREFETCH_THRESH: ++ di->rxprefetchthresh = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_RX_BURSTLEN: ++ di->rxburstlen = (uint8)paramval; ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static bool ++_dma_glom_enable(dma_info_t *di, uint32 val) ++{ ++ dma64regs_t *dregs = di->d64rxregs; ++ bool ret = TRUE; ++ if (val) { ++ OR_REG(di->osh, &dregs->control, D64_RC_GE); ++ if (!(R_REG(di->osh, &dregs->control) & D64_RC_GE)) ++ ret = FALSE; ++ } else { ++ AND_REG(di->osh, &dregs->control, ~D64_RC_GE); ++ } ++ return ret; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/hndfwd.c b/drivers/bcmdrivers/gmac/src/shared/hndfwd.c +new file mode 100755 +index 0000000..5dddaf6 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hndfwd.c +@@ -0,0 +1,225 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND GMAC Forwarder ++ * ++ * $Id$ ++ */ ++ ++#if defined(GMAC3) ++ ++#include ++#include ++#include ++ ++#if defined(CONFIG_SMP) ++#define _FWDER_GET(fwder_instance, unit) &per_cpu(fwder_instance, unit) ++#else /* !CONFIG_SMP */ ++#define _FWDER_GET(fwder_instance, unit) &fwder_instance[unit] ++#endif /* !CONFIG_SMP */ ++ ++ ++static int /* default dummy xmit handler when tx device is down */ ++_fwder_default(struct sk_buff * skb, struct net_device * dev, int cnt) ++{ ++ return FWDER_FAILURE; ++} ++ ++#if defined(CONFIG_SMP) ++DEFINE_PER_CPU(struct fwder, fwd_upstream) = { ++ .lock = __SPIN_LOCK_UNLOCKED(.lock), /* static init */ ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .error = 0U ++}; ++ ++DEFINE_PER_CPU(struct fwder, fwd_dnstream) = { ++ .lock = __SPIN_LOCK_UNLOCKED(.lock), ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .error = 0U ++}; ++#else /* !CONFIG_SMP */ ++struct fwder fwd_upstream[FWDER_MAX_UNITS] = { ++ { ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .unit = 0, ++ .error = 0U ++ }, ++ { ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .unit = 1, ++ .error = 0U ++ } ++}; ++struct fwder fwd_dnstream[FWDER_MAX_UNITS] = { ++ { ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .unit = 0, ++ .error = 0U ++ }, ++ { ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .unit = 1, ++ .error = 0U ++ } ++}; ++#endif /* !CONFIG_SMP */ ++ ++static inline ++struct fwder * _get_other(struct fwder * fwder_p) ++{ ++ struct fwder * other_p; ++ ++ other_p = _FWDER_GET(fwd_upstream, fwder_p->unit); ++ if (other_p == fwder_p) ++ return _FWDER_GET(fwd_dnstream, fwder_p->unit); ++ else ++ return other_p; ++} ++ ++int /* Initialization of fwder in et_module_init */ ++fwder_init(void) ++{ ++ int dir; ++ fwder_t * fwder_p; ++ int unit; ++ ++#if defined(CONFIG_SMP) ++ for_each_online_cpu(unit) ++#else /* !CONFIG_SMP */ ++ for (unit = 0; unit < FWDER_MAX_UNITS; unit++) ++#endif /* !CONFIG_SMP */ ++ { ++ for (dir = (int)FWD_UPSTREAM; dir < (int)FWD_MAX_DIRS; dir++) { ++ if (dir == (int)FWD_UPSTREAM) ++ fwder_p = _FWDER_GET(fwd_upstream, unit); ++ else ++ fwder_p = _FWDER_GET(fwd_dnstream, unit); ++ fwder_p->dev = (struct net_device *)fwder_p; ++ fwder_p->forward = (fwder_start_t)_fwder_default; ++ fwder_p->unit = unit; ++ fwder_p->error = 0U; ++ } ++ ++ } /* for_each_online_cpu / for unit = 0 .. FWDER_MAX_UNITS */ ++ ++printk("===FWD: fwder_init\n"); // DELETE ME ++ return 0; ++} ++ ++struct fwder * /* Driver registers its xx_start_xmit() handler on netdev open */ ++fwder_attach(fwder_start_t forward, const struct net_device * dev, ++ const int unit, const enum fwder_dir dir) ++{ ++ fwder_t * fwder_p; ++ fwder_t * other_p; /* reverse direction forwarder */ ++ ++ printk("fwder_attach forward<%p> dev<%p> unit<%d> dir<%d>\n", ++ forward, dev, unit, dir); ++ ++ ASSERT((dir < (int)FWD_MAX_DIRS) && (dev != (struct net_device *)NULL) ++ && (forward != (fwder_start_t)NULL)); ++ ++#if defined(CONFIG_SMP) ++ ASSERT(unit < NR_CPUS); ++#else /* !CONFIG_SMP */ ++ ASSERT(unit < FWDER_MAX_UNITS); ++#endif /* !CONFIG_SMP */ ++ ++ if (dir == (int)FWD_UPSTREAM) { ++ fwder_p = _FWDER_GET(fwd_upstream, unit); ++ other_p = _FWDER_GET(fwd_dnstream, unit); ++ } else { ++ fwder_p = _FWDER_GET(fwd_dnstream, unit); ++ other_p = _FWDER_GET(fwd_upstream, unit); ++ } ++ ++ _FWDER_LOCK(fwder_p); /* ++LOCK */ ++ ++ fwder_p->dev = (struct net_device *)dev; ++ fwder_p->forward = forward; ++ ++ _FWDER_UNLOCK(fwder_p); /* ++LOCK */ ++ ++printk("===FWD: ATTACH<%d,%d>: <%p> unit<%d> dir<%d> dev<%p> xmit<%p>\n", unit, (int)dir, fwder_p, fwder_p->unit, dir, fwder_p->dev, fwder_p->forward); // DELETE ME ++printk("===FWD: RETURN<%d,%d>: <%p> unit<%d> dir<%d> dev<%p> xmit<%p>\n", unit, (int)dir, other_p, other_p->unit, dir^1, other_p->dev, other_p->forward); // DELETE ME ++ ++ return other_p; ++} ++ ++struct fwder * /* A driver deregisters itself on netdev close */ ++fwder_dettach(struct fwder * fwder_p) ++{ ++ ++ if (fwder_p == (fwder_t *)NULL) ++ return (fwder_t *)NULL; ++ ++ printk("fwder_dettach <%p>\n", fwder_p); ++ ++ fwder_p = _get_other(fwder_p); ++ ++ _FWDER_LOCK(fwder_p); /* ++LOCK */ ++ ++ fwder_p->dev = (struct net_device *)NULL; ++ fwder_p->forward = (fwder_start_t)_fwder_default; ++ ++ _FWDER_UNLOCK(fwder_p); /* ++LOCK */ ++ ++ return (fwder_t *)NULL; ++} ++ ++void ++fwder_dump(const struct fwder * fwder_p) ++{ ++ if (fwder_p == (fwder_t *)NULL) ++ return; ++ ++ printk("FWD<%p>: dev<%p> forward<%p> unit<%d> error<%u>\n", ++ fwder_p, fwder_p->dev, fwder_p->forward, ++ fwder_p->unit, fwder_p->error); ++} ++ ++void ++fwder_dump_all(void) ++{ ++ int unit; ++ struct fwder * fwder_p; ++ ++ printk("FWDER DUMP ALL default<%p>\n", _fwder_default); ++#if defined(CONFIG_SMP) ++ for_each_online_cpu(unit) ++#else /* !CONFIG_SMP */ ++ for (unit = 0; unit < FWDER_MAX_UNITS; unit++) ++#endif /* !CONFIG_SMP */ ++ { ++ fwder_p = _FWDER_GET(fwd_upstream, unit); ++ printk("FWD[UP]<%p> CPU<%d>: dev<%p> forward<%p> unit<%d> error<%u>\n", ++ fwder_p, unit, fwder_p->dev, fwder_p->forward, ++ fwder_p->unit, fwder_p->error); ++ ++ fwder_p = _FWDER_GET(fwd_dnstream, unit); ++ printk("FWD[DN]<%p> CPU<%d>: dev<%p> forward<%p> unit<%d> error<%u>\n", ++ fwder_p, unit, fwder_p->dev, fwder_p->forward, ++ fwder_p->unit, fwder_p->error); ++ ++ } /* for_each_online_cpu / for unit = 0 .. FWDER_MAX_UNITS */ ++} ++ ++#endif /* GMAC3 */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/hr2_erom.c b/drivers/bcmdrivers/gmac/src/shared/hr2_erom.c +new file mode 100755 +index 0000000..4c93c3a +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hr2_erom.c +@@ -0,0 +1,64 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++#include ++ ++uint32 hr2_erom[] = { ++ //#define CC_CORE_ID 0x800 /* chipcommon core */ ++ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, ++ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, ++ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, ++ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, ++ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, ++ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, ++ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, ++ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, ++ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, ++ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, ++ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, ++ //#define I2S_CORE_ID 0x834 /* I2S core */ ++ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, ++ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, ++ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, ++ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, ++ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, ++ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, ++ //#define EROM_CORE_ID 0x366 /* EROM core ID */ ++ 0x43b36601, 0x00000201, 0x18130005, ++ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, ++ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, ++ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, ++ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, ++ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, ++ 0x18134285, 0x18135385, 0x18136485, ++ 0x0000000f ++}; +diff --git a/drivers/bcmdrivers/gmac/src/shared/hr2_erom.h b/drivers/bcmdrivers/gmac/src/shared/hr2_erom.h +new file mode 100755 +index 0000000..f7354c6 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hr2_erom.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++ ++#ifndef _hr2_erom_h_ ++#define _hr2_erom_h_ ++ ++extern uint32 hr2_erom[]; ++ ++#endif //_hr2_erom_h_ +diff --git a/drivers/bcmdrivers/gmac/src/shared/hx4_erom.c b/drivers/bcmdrivers/gmac/src/shared/hx4_erom.c +new file mode 100755 +index 0000000..0f83e7f +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hx4_erom.c +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++#include ++ ++uint32 hx4_erom[] = { ++ //#define CC_CORE_ID 0x800 /* chipcommon core */ ++ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, ++ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, ++ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, ++ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, ++ 0x4bf82d01, 0x04004211, 0x00000203, 0x18023005, 0x181110c5, ++ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, ++ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, ++ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, ++ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, ++ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, ++ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, ++ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, ++ //#define I2S_CORE_ID 0x834 /* I2S core */ ++ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, ++ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, ++ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, ++ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, ++ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, ++ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, ++ //#define EROM_CORE_ID 0x366 /* EROM core ID */ ++ 0x43b36601, 0x00000201, 0x18130005, ++ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, ++ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, ++ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, ++ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, ++ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, ++ 0x18134285, 0x18135385, 0x18136485, ++ 0x0000000f ++}; +diff --git a/drivers/bcmdrivers/gmac/src/shared/hx4_erom.h b/drivers/bcmdrivers/gmac/src/shared/hx4_erom.h +new file mode 100755 +index 0000000..4170fb4 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hx4_erom.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++ ++#ifndef _hx4_erom_h_ ++#define _hx4_erom_h_ ++ ++extern uint32 hx4_erom[]; ++ ++#endif //_hx4_erom_h_ +diff --git a/drivers/bcmdrivers/gmac/src/shared/kt2_erom.c b/drivers/bcmdrivers/gmac/src/shared/kt2_erom.c +new file mode 100755 +index 0000000..ddd9494 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/kt2_erom.c +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++#include ++ ++uint32 kt2_erom[] = { ++ //#define CC_CORE_ID 0x800 /* chipcommon core */ ++ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, ++ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, ++ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, ++ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, ++ 0x4bf82d01, 0x04004211, 0x00000203, 0x18023005, 0x181110c5, ++ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, ++ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, ++ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, ++ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, ++ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, ++ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, ++ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, ++ //#define I2S_CORE_ID 0x834 /* I2S core */ ++ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, ++ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, ++ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, ++ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, ++ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, ++ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, ++ //#define EROM_CORE_ID 0x366 /* EROM core ID */ ++ 0x43b36601, 0x00000201, 0x18130005, ++ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, ++ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, ++ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, ++ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, ++ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, ++ 0x18134285, 0x18135385, 0x18136485, ++ 0x0000000f ++}; +diff --git a/drivers/bcmdrivers/gmac/src/shared/kt2_erom.h b/drivers/bcmdrivers/gmac/src/shared/kt2_erom.h +new file mode 100755 +index 0000000..b2b6095 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/kt2_erom.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++ ++#ifndef _kt2_erom_h_ ++#define _kt2_erom_h_ ++ ++extern uint32 kt2_erom[]; ++ ++#endif //_kt2_erom_h_ +diff --git a/drivers/bcmdrivers/gmac/src/shared/linux_osl.c b/drivers/bcmdrivers/gmac/src/shared/linux_osl.c +new file mode 100755 +index 0000000..aa06749 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/linux_osl.c +@@ -0,0 +1,1713 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux OS Independent Layer ++ * ++ * $Id: linux_osl.c 322208 2012-03-20 01:53:23Z $ ++ */ ++ ++#define LINUX_PORT ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef mips ++#include ++#endif /* mips */ ++#include ++ ++ ++ ++#include ++#include ++ ++#define PCI_CFG_RETRY 10 ++ ++#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognize osh */ ++#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */ ++ ++#ifdef DHD_USE_STATIC_BUF ++#define STATIC_BUF_MAX_NUM 16 ++#define STATIC_BUF_SIZE (PAGE_SIZE*2) ++#define STATIC_BUF_TOTAL_LEN (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) ++ ++typedef struct bcm_static_buf { ++ struct semaphore static_sem; ++ unsigned char *buf_ptr; ++ unsigned char buf_use[STATIC_BUF_MAX_NUM]; ++} bcm_static_buf_t; ++ ++static bcm_static_buf_t *bcm_static_buf = 0; ++ ++#define STATIC_PKT_MAX_NUM 8 ++ ++typedef struct bcm_static_pkt { ++ struct sk_buff *skb_4k[STATIC_PKT_MAX_NUM]; ++ struct sk_buff *skb_8k[STATIC_PKT_MAX_NUM]; ++ struct semaphore osl_pkt_sem; ++ unsigned char pkt_use[STATIC_PKT_MAX_NUM * 2]; ++} bcm_static_pkt_t; ++ ++static bcm_static_pkt_t *bcm_static_skb = 0; ++#endif /* DHD_USE_STATIC_BUF */ ++ ++typedef struct bcm_mem_link { ++ struct bcm_mem_link *prev; ++ struct bcm_mem_link *next; ++ uint size; ++ int line; ++ void *osh; ++ char file[BCM_MEM_FILENAME_LEN]; ++} bcm_mem_link_t; ++ ++struct osl_info { ++ osl_pubinfo_t pub; ++#ifdef CTFPOOL ++ ctfpool_t *ctfpool; ++#endif /* CTFPOOL */ ++ uint magic; ++ void *pdev; ++ atomic_t malloced; ++ atomic_t pktalloced; /* Number of allocated packet buffers */ ++ uint failed; ++ uint bustype; ++ bcm_mem_link_t *dbgmem_list; ++#if defined(DSLCPE_DELAY) ++ shared_osl_t *oshsh; /* osh shared */ ++#endif ++ spinlock_t dbgmem_lock; ++ spinlock_t pktalloc_lock; ++}; ++ ++#define OSL_PKTTAG_CLEAR(p) \ ++do { \ ++ struct sk_buff *s = (struct sk_buff *)(p); \ ++ ASSERT(OSL_PKTTAG_SZ == 32); \ ++ *(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \ ++ *(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \ ++ *(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \ ++ *(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \ ++} while (0) ++ ++/* PCMCIA attribute space access macros */ ++#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) ++struct pcmcia_dev { ++ dev_link_t link; /* PCMCIA device pointer */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ++ dev_node_t node; /* PCMCIA node structure */ ++#endif ++ void *base; /* Mapped attribute memory window */ ++ size_t size; /* Size of window */ ++ void *drv; /* Driver data */ ++}; ++#endif /* defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) */ ++ ++/* Global ASSERT type flag */ ++uint32 g_assert_type = FALSE; ++ ++static int16 linuxbcmerrormap[] = ++{ 0, /* 0 */ ++ -EINVAL, /* BCME_ERROR */ ++ -EINVAL, /* BCME_BADARG */ ++ -EINVAL, /* BCME_BADOPTION */ ++ -EINVAL, /* BCME_NOTUP */ ++ -EINVAL, /* BCME_NOTDOWN */ ++ -EINVAL, /* BCME_NOTAP */ ++ -EINVAL, /* BCME_NOTSTA */ ++ -EINVAL, /* BCME_BADKEYIDX */ ++ -EINVAL, /* BCME_RADIOOFF */ ++ -EINVAL, /* BCME_NOTBANDLOCKED */ ++ -EINVAL, /* BCME_NOCLK */ ++ -EINVAL, /* BCME_BADRATESET */ ++ -EINVAL, /* BCME_BADBAND */ ++ -E2BIG, /* BCME_BUFTOOSHORT */ ++ -E2BIG, /* BCME_BUFTOOLONG */ ++ -EBUSY, /* BCME_BUSY */ ++ -EINVAL, /* BCME_NOTASSOCIATED */ ++ -EINVAL, /* BCME_BADSSIDLEN */ ++ -EINVAL, /* BCME_OUTOFRANGECHAN */ ++ -EINVAL, /* BCME_BADCHAN */ ++ -EFAULT, /* BCME_BADADDR */ ++ -ENOMEM, /* BCME_NORESOURCE */ ++ -EOPNOTSUPP, /* BCME_UNSUPPORTED */ ++ -EMSGSIZE, /* BCME_BADLENGTH */ ++ -EINVAL, /* BCME_NOTREADY */ ++ -EPERM, /* BCME_EPERM */ ++ -ENOMEM, /* BCME_NOMEM */ ++ -EINVAL, /* BCME_ASSOCIATED */ ++ -ERANGE, /* BCME_RANGE */ ++ -EINVAL, /* BCME_NOTFOUND */ ++ -EINVAL, /* BCME_WME_NOT_ENABLED */ ++ -EINVAL, /* BCME_TSPEC_NOTFOUND */ ++ -EINVAL, /* BCME_ACM_NOTSUPPORTED */ ++ -EINVAL, /* BCME_NOT_WME_ASSOCIATION */ ++ -EIO, /* BCME_SDIO_ERROR */ ++ -ENODEV, /* BCME_DONGLE_DOWN */ ++ -EINVAL, /* BCME_VERSION */ ++ -EIO, /* BCME_TXFAIL */ ++ -EIO, /* BCME_RXFAIL */ ++ -ENODEV, /* BCME_NODEVICE */ ++ -EINVAL, /* BCME_NMODE_DISABLED */ ++ -ENODATA, /* BCME_NONRESIDENT */ ++ ++/* When an new error code is added to bcmutils.h, add os ++ * specific error translation here as well ++ */ ++/* check if BCME_LAST changed since the last time this function was updated */ ++#if BCME_LAST != -42 ++#error "You need to add a OS error translation in the linuxbcmerrormap \ ++ for new error code defined in bcmutils.h" ++#endif ++}; ++ ++/* translate bcmerrors into linux errors */ ++int ++osl_error(int bcmerror) ++{ ++ if (bcmerror > 0) ++ bcmerror = 0; ++ else if (bcmerror < BCME_LAST) ++ bcmerror = BCME_ERROR; ++ ++ /* Array bounds covered by ASSERT in osl_attach */ ++ return linuxbcmerrormap[-bcmerror]; ++} ++ ++extern uint8* dhd_os_prealloc(void *osh, int section, int size); ++ ++EXPORT_SYMBOL(osl_attach); ++osl_t * ++osl_attach(void *pdev, uint bustype, bool pkttag) ++{ ++ osl_t *osh; ++ ++ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); ++ ASSERT(osh); ++ ++ bzero(osh, sizeof(osl_t)); ++ ++ /* Check that error map has the right number of entries in it */ ++ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1)); ++ ++ osh->magic = OS_HANDLE_MAGIC; ++ atomic_set(&osh->malloced, 0); ++ osh->failed = 0; ++ osh->dbgmem_list = NULL; ++ spin_lock_init(&(osh->dbgmem_lock)); ++ osh->pdev = pdev; ++ osh->pub.pkttag = pkttag; ++ osh->bustype = bustype; ++ ++ switch (bustype) { ++ case PCI_BUS: ++ case SI_BUS: ++ case PCMCIA_BUS: ++ osh->pub.mmbus = TRUE; ++ break; ++ case JTAG_BUS: ++ case SDIO_BUS: ++ case USB_BUS: ++ case SPI_BUS: ++ case RPC_BUS: ++ osh->pub.mmbus = FALSE; ++ break; ++ default: ++ ASSERT(FALSE); ++ break; ++ } ++ ++#if defined(DHD_USE_STATIC_BUF) ++ if (!bcm_static_buf) { ++ if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(osh, 3, STATIC_BUF_SIZE+ ++ STATIC_BUF_TOTAL_LEN))) { ++ printk("can not alloc static buf!\n"); ++ } ++ else ++ printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); ++ ++ ++ sema_init(&bcm_static_buf->static_sem, 1); ++ ++ bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE; ++ } ++ ++ if (!bcm_static_skb) { ++ int i; ++ void *skb_buff_ptr = 0; ++ bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); ++ skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); ++ ++ bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)*16); ++ for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++) ++ bcm_static_skb->pkt_use[i] = 0; ++ ++ sema_init(&bcm_static_skb->osl_pkt_sem, 1); ++ } ++#endif /* DHD_USE_STATIC_BUF */ ++ ++ spin_lock_init(&(osh->pktalloc_lock)); ++ ++#ifdef BCMDBG ++ if (pkttag) { ++ struct sk_buff *skb; ++ ASSERT(OSL_PKTTAG_SZ <= sizeof(skb->cb)); ++ } ++#endif ++ return osh; ++} ++ ++void ++osl_detach(osl_t *osh) ++{ ++ if (osh == NULL) ++ return; ++ ++#ifdef DHD_USE_STATIC_BUF ++ if (bcm_static_buf) { ++ bcm_static_buf = 0; ++ } ++ if (bcm_static_skb) { ++ bcm_static_skb = 0; ++ } ++#endif ++ ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ kfree(osh); ++} ++ ++static struct sk_buff *osl_alloc_skb(unsigned int len) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) ++ gfp_t flags = GFP_ATOMIC; ++ ++ return __dev_alloc_skb(len, flags); ++#else ++ return dev_alloc_skb(len); ++#endif ++} ++ ++#ifdef CTFPOOL ++ ++#ifdef CTFPOOL_SPINLOCK ++#define CTFPOOL_LOCK(ctfpool, flags) spin_lock_irqsave(&(ctfpool)->lock, flags) ++#define CTFPOOL_UNLOCK(ctfpool, flags) spin_unlock_irqrestore(&(ctfpool)->lock, flags) ++#else ++#define CTFPOOL_LOCK(ctfpool, flags) spin_lock_bh(&(ctfpool)->lock) ++#define CTFPOOL_UNLOCK(ctfpool, flags) spin_unlock_bh(&(ctfpool)->lock) ++#endif /* CTFPOOL_SPINLOCK */ ++/* ++ * Allocate and add an object to packet pool. ++ */ ++void * ++osl_ctfpool_add(osl_t *osh) ++{ ++ struct sk_buff *skb; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return NULL; ++ ++ CTFPOOL_LOCK(osh->ctfpool, flags); ++ ASSERT(osh->ctfpool->curr_obj <= osh->ctfpool->max_obj); ++ ++ /* No need to allocate more objects */ ++ if (osh->ctfpool->curr_obj == osh->ctfpool->max_obj) { ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ return NULL; ++ } ++ ++ /* Allocate a new skb and add it to the ctfpool */ ++ skb = osl_alloc_skb(osh->ctfpool->obj_size); ++ if (skb == NULL) { ++ printk("%s: skb alloc of len %d failed\n", __FUNCTION__, ++ osh->ctfpool->obj_size); ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ return NULL; ++ } ++ ++ /* Add to ctfpool */ ++ skb->next = (struct sk_buff *)osh->ctfpool->head; ++ osh->ctfpool->head = skb; ++ osh->ctfpool->fast_frees++; ++ osh->ctfpool->curr_obj++; ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#ifdef SKB_RECYCLING_DEBUG ++ if ((osh->ctfpool->unit == 2)) { ++ static int count = 0; ++ printk("<%d>allocated skb=%p\n", count, skb); ++ count++; ++ } ++#endif /* SKB_RECYCLING_DEBUG */ ++ /* Fot reset during release to pool */ ++ skb->reset_size = skb->truesize; ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++ /* Hijack a skb member to store ptr to ctfpool */ ++ CTFPOOLPTR(osh, skb) = (void *)osh->ctfpool; ++ ++ /* Use bit flag to indicate skb from fast ctfpool */ ++ PKTFAST(osh, skb) = FASTBUF; ++ ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ ++ return skb; ++} ++ ++/* ++ * Add new objects to the pool. ++ */ ++void ++osl_ctfpool_replenish(osl_t *osh, uint thresh) ++{ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return; ++ ++ /* Do nothing if no refills are required */ ++ while ((osh->ctfpool->refills > 0) && (thresh--)) { ++ osl_ctfpool_add(osh); ++ osh->ctfpool->refills--; ++ } ++} ++ ++/* ++ * Initialize the packet pool with specified number of objects. ++ */ ++int32 ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++osl_ctfpool_init(int unit, osl_t *osh, uint numobj, uint size) ++#else ++osl_ctfpool_init(osl_t *osh, uint numobj, uint size) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++{ ++ osh->ctfpool = kmalloc(sizeof(ctfpool_t), GFP_ATOMIC); ++ ASSERT(osh->ctfpool); ++ bzero(osh->ctfpool, sizeof(ctfpool_t)); ++ ++ osh->ctfpool->max_obj = numobj; ++ osh->ctfpool->obj_size = size; ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ osh->ctfpool->unit = unit; ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ spin_lock_init(&osh->ctfpool->lock); ++ ++ while (numobj--) { ++ if (!osl_ctfpool_add(osh)) ++ return -1; ++ osh->ctfpool->fast_frees--; ++ } ++ ++#ifdef SKB_RECYCLING_DEBUG ++ printk("ctfpool = %p\n", osh->ctfpool); ++#endif /* SKB_RECYCLING_DEBUG */ ++ return 0; ++} ++ ++/* ++ * Cleanup the packet pool objects. ++ */ ++void ++osl_ctfpool_cleanup(osl_t *osh) ++{ ++ struct sk_buff *skb, *nskb; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return; ++ ++ CTFPOOL_LOCK(osh->ctfpool, flags); ++ ++ skb = osh->ctfpool->head; ++ ++ while (skb != NULL) { ++ nskb = skb->next; ++ dev_kfree_skb(skb); ++ skb = nskb; ++ osh->ctfpool->curr_obj--; ++ } ++ ++ ASSERT(osh->ctfpool->curr_obj == 0); ++ osh->ctfpool->head = NULL; ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ ++ kfree(osh->ctfpool); ++ osh->ctfpool = NULL; ++} ++ ++void ++osl_ctfpool_stats(osl_t *osh, void *b) ++{ ++ struct bcmstrbuf *bb; ++ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return; ++ ++#ifdef DHD_USE_STATIC_BUF ++ if (bcm_static_buf) { ++ bcm_static_buf = 0; ++ } ++ if (bcm_static_skb) { ++ bcm_static_skb = 0; ++ } ++#endif /* DHD_USE_STATIC_BUF */ ++ ++ bb = b; ++ ++ ASSERT((osh != NULL) && (bb != NULL)); ++ ++ bcm_bprintf(bb, "max_obj %d obj_size %d curr_obj %d refills %d\n", ++ osh->ctfpool->max_obj, osh->ctfpool->obj_size, ++ osh->ctfpool->curr_obj, osh->ctfpool->refills); ++ bcm_bprintf(bb, "fast_allocs %d fast_frees %d slow_allocs %d\n", ++ osh->ctfpool->fast_allocs, osh->ctfpool->fast_frees, ++ osh->ctfpool->slow_allocs); ++} ++ ++static inline struct sk_buff * ++osl_pktfastget(osl_t *osh, uint len) ++{ ++ struct sk_buff *skb; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++ /* Try to do fast allocate. Return null if ctfpool is not in use ++ * or if there are no items in the ctfpool. ++ */ ++ if (osh->ctfpool == NULL) ++ return NULL; ++ ++ CTFPOOL_LOCK(osh->ctfpool, flags); ++ if (osh->ctfpool->head == NULL) { ++ ASSERT(osh->ctfpool->curr_obj == 0); ++ osh->ctfpool->slow_allocs++; ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++#ifdef SKB_RECYCLING_DEBUG ++ WARN_ON_ONCE(1); ++#endif /* SKB_RECYCLING_DEBUG */ ++ return NULL; ++ } ++ ++ ASSERT(len <= osh->ctfpool->obj_size); ++ if (len > osh->ctfpool->obj_size) { ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ return NULL; ++ } ++ ++ /* Get an object from ctfpool */ ++ skb = (struct sk_buff *)osh->ctfpool->head; ++ osh->ctfpool->head = (void *)skb->next; ++ ++#ifdef SKB_RECYCLING_DEBUG ++ { ++ if (skb->next == NULL) { ++ printk("Get a skb whose next is empty: osh->ctfpool=%p, \ ++ skb=%p, skb->next=%p, osh->ctfpool->head=%p\n", ++ osh->ctfpool, skb, skb->next, osh->ctfpool->head); ++ } ++ } ++#endif /* SKB_RECYCLING_DEBUG */ ++ ++ ++ osh->ctfpool->fast_allocs++; ++ osh->ctfpool->curr_obj--; ++ ASSERT(CTFPOOLHEAD(osh, skb) == (struct sock *)osh->ctfpool->head); ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ ++ /* Init skb struct */ ++ skb->next = skb->prev = NULL; ++ skb->data = skb->head + 16; ++ skb->tail = skb->head + 16; ++ ++ skb->len = 0; ++ skb->cloned = 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) ++ skb->list = NULL; ++#endif ++ atomic_set(&skb->users, 1); ++ ++ PKTSETCLINK(skb, NULL); ++ PKTCCLRATTR(skb); ++#ifdef HNDCTF ++ PKTFAST(osh, skb) &= ~(CTFBUF | SKIPCT | CHAINED); ++#endif ++ return skb; ++} ++#endif /* CTFPOOL */ ++/* Convert a driver packet to native(OS) packet ++ * In the process, packettag is zeroed out before sending up ++ * IP code depends on skb->cb to be setup correctly with various options ++ * In our case, that means it should be 0 ++ */ ++struct sk_buff * BCMFASTPATH ++osl_pkt_tonative(osl_t *osh, void *pkt) ++{ ++ struct sk_buff *nskb; ++ ++ if (osh->pub.pkttag) ++ OSL_PKTTAG_CLEAR(pkt); ++ ++ /* Decrement the packet counter */ ++ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { ++ atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); ++ } ++ return (struct sk_buff *)pkt; ++} ++ ++/* Convert a native(OS) packet to driver packet. ++ * In the process, native packet is destroyed, there is no copying ++ * Also, a packettag is zeroed out ++ */ ++void * BCMFASTPATH ++osl_pkt_frmnative(osl_t *osh, void *pkt) ++{ ++ struct sk_buff *nskb; ++ ++ if (osh->pub.pkttag) ++ OSL_PKTTAG_CLEAR(pkt); ++ ++ /* Increment the packet counter */ ++ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { ++ atomic_add(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); ++ } ++ return (void *)pkt; ++} ++ ++/* Return a new packet. zero out pkttag */ ++void * BCMFASTPATH ++osl_pktget(osl_t *osh, uint len) ++{ ++ struct sk_buff *skb; ++ ++#ifdef CTFPOOL ++ /* Allocate from local pool */ ++ skb = osl_pktfastget(osh, len); ++ ++#ifdef SKB_RECYCLING_DEBUG ++ if (skb == NULL) { ++ printk("<%s> osl_pktfastget fail! ctfpool=%p, ctfpool->head=%p, \ ++ ctfpool->curr_obj=%u, ctfpool->fast_allocs=%u, \ ++ ctfpool->fast_frees=%u, ctfpool->slow_allocs=%u\n", ++ __FUNCTION__, osh->ctfpool, osh->ctfpool->head, ++ osh->ctfpool->curr_obj, osh->ctfpool->fast_allocs, ++ osh->ctfpool->fast_frees, osh->ctfpool->slow_allocs); ++ } ++#endif /* SKB_RECYCLING_DEBUG */ ++ ++ if ((skb != NULL) || ((skb = osl_alloc_skb(len)) != NULL)) { ++#else /* CTFPOOL */ ++ if ((skb = osl_alloc_skb(len))) { ++#endif /* CTFPOOL */ ++ skb_put(skb, len); ++ skb->priority = 0; ++ ++ atomic_inc(&osh->pktalloced); ++ } ++ ++ PKTSETCLINK(skb, NULL); ++ ++ return ((void*) skb); ++} ++ ++#ifdef CTFPOOL ++static inline void ++osl_pktfastfree(osl_t *osh, struct sk_buff *skb) ++{ ++ ctfpool_t *ctfpool; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ ++ if (skb->destructor) { ++ WARN_ON(in_irq()); ++ skb->destructor(skb); ++ } ++ ++ skb->data_len = 0; ++ skb->truesize = skb->reset_size; ++ ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR) ++ skb->tstamp.tv.sec = 0; /*ING*/ ++#else ++ skb->tstamp.tv64 = 0; ++#endif ++#else ++ skb->stamp.tv_sec = 0; ++#endif ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++ /* We only need to init the fields that we change */ ++ skb->dev = NULL; ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ++ skb->dst = NULL; ++#endif ++#endif /* !CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ OSL_PKTTAG_CLEAR(skb); ++ skb->ip_summed = 0; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++ skb_orphan(skb); ++#else ++ skb->destructor = NULL; ++#endif ++ ++ ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); ++ ASSERT(ctfpool != NULL); ++ ++ /* Add object to the ctfpool */ ++ CTFPOOL_LOCK(ctfpool, flags); ++ skb->next = (struct sk_buff *)ctfpool->head; ++ ctfpool->head = (void *)skb; ++ ++ ctfpool->fast_frees++; ++ ctfpool->curr_obj++; ++ ++ ASSERT(ctfpool->curr_obj <= ctfpool->max_obj); ++ CTFPOOL_UNLOCK(ctfpool, flags); ++} ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++bool pktfastfree_wrapper(struct sk_buff *skb) ++{ ++ int rval = FALSE; ++ ++ if (PKTISFAST(NULL, skb)) { ++ osl_pktfastfree(NULL, skb); ++ rval = TRUE; ++ } ++ ++ return rval; ++} ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++#endif /* CTFPOOL */ ++ ++/* Free the driver packet. Free the tag if present */ ++void BCMFASTPATH ++osl_pktfree(osl_t *osh, void *p, bool send) ++{ ++ struct sk_buff *skb, *nskb; ++ ++ skb = (struct sk_buff*) p; ++ ++ if (send && osh->pub.tx_fn) ++ osh->pub.tx_fn(osh->pub.tx_ctx, p, 0); ++ ++ PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE); ++ ++ /* perversion: we use skb->next to chain multi-skb packets */ ++ while (skb) { ++ nskb = skb->next; ++ skb->next = NULL; ++ ++ ++#ifdef CTFMAP ++ /* Clear the map ptr before freeing */ ++ PKTCLRCTF(osh, skb); ++ CTFMAPPTR(osh, skb) = NULL; ++#endif /* CTFMAP */ ++ ++#ifdef CTFPOOL ++ if ((PKTISFAST(osh, skb)) && (atomic_read(&skb->users) == 1)) ++ osl_pktfastfree(osh, skb); ++ else { ++#else /* CTFPOOL */ ++ { ++#endif /* CTFPOOL */ ++ ++ if (skb->destructor) ++ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if ++ * destructor exists ++ */ ++ dev_kfree_skb_any(skb); ++ else ++ /* can free immediately (even in_irq()) if destructor ++ * does not exist ++ */ ++ dev_kfree_skb(skb); ++ } ++ atomic_dec(&osh->pktalloced); ++ skb = nskb; ++ } ++} ++ ++#ifdef DHD_USE_STATIC_BUF ++void* ++osl_pktget_static(osl_t *osh, uint len) ++{ ++ int i = 0; ++ struct sk_buff *skb; ++ ++ if (len > (PAGE_SIZE*2)) { ++ printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); ++ return osl_pktget(osh, len); ++ } ++ ++ down(&bcm_static_skb->osl_pkt_sem); ++ ++ if (len <= PAGE_SIZE) { ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (bcm_static_skb->pkt_use[i] == 0) ++ break; ++ } ++ ++ if (i != STATIC_PKT_MAX_NUM) { ++ bcm_static_skb->pkt_use[i] = 1; ++ up(&bcm_static_skb->osl_pkt_sem); ++ skb = bcm_static_skb->skb_4k[i]; ++ skb->tail = skb->data + len; ++ skb->len = len; ++ return skb; ++ } ++ } ++ ++ ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] == 0) ++ break; ++ } ++ ++ if (i != STATIC_PKT_MAX_NUM) { ++ bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] = 1; ++ up(&bcm_static_skb->osl_pkt_sem); ++ skb = bcm_static_skb->skb_8k[i]; ++ skb->tail = skb->data + len; ++ skb->len = len; ++ return skb; ++ } ++ ++ up(&bcm_static_skb->osl_pkt_sem); ++ printk("%s: all static pkt in use!\n", __FUNCTION__); ++ return osl_pktget(osh, len); ++} ++ ++void ++osl_pktfree_static(osl_t *osh, void *p, bool send) ++{ ++ int i; ++ ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (p == bcm_static_skb->skb_4k[i]) { ++ down(&bcm_static_skb->osl_pkt_sem); ++ bcm_static_skb->pkt_use[i] = 0; ++ up(&bcm_static_skb->osl_pkt_sem); ++ return; ++ } ++ } ++ ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (p == bcm_static_skb->skb_8k[i]) { ++ down(&bcm_static_skb->osl_pkt_sem); ++ bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0; ++ up(&bcm_static_skb->osl_pkt_sem); ++ return; ++ } ++ } ++ ++ return osl_pktfree(osh, p, send); ++} ++#endif /* DHD_USE_STATIC_BUF */ ++ ++uint32 ++osl_pci_read_config(osl_t *osh, uint offset, uint size) ++{ ++ uint val = 0; ++ uint retry = PCI_CFG_RETRY; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ /* only 4byte access supported */ ++ ASSERT(size == 4); ++ ++ do { ++ pci_read_config_dword(osh->pdev, offset, &val); ++ if (val != 0xffffffff) ++ break; ++ } while (retry--); ++ ++#ifdef BCMDBG ++ if (retry < PCI_CFG_RETRY) ++ printk("PCI CONFIG READ access to %d required %d retries\n", offset, ++ (PCI_CFG_RETRY - retry)); ++#endif /* BCMDBG */ ++ ++ return (val); ++} ++ ++void ++osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) ++{ ++ uint retry = PCI_CFG_RETRY; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ /* only 4byte access supported */ ++ ASSERT(size == 4); ++ ++ do { ++ pci_write_config_dword(osh->pdev, offset, val); ++ if (offset != PCI_BAR0_WIN) ++ break; ++ if (osl_pci_read_config(osh, offset, size) == val) ++ break; ++ } while (retry--); ++ ++#ifdef BCMDBG ++ if (retry < PCI_CFG_RETRY) ++ printk("PCI CONFIG WRITE access to %d required %d retries\n", offset, ++ (PCI_CFG_RETRY - retry)); ++#endif /* BCMDBG */ ++} ++ ++/* return bus # for the pci device pointed by osh->pdev */ ++uint ++osl_pci_bus(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return ((struct pci_dev *)osh->pdev)->bus->number; ++} ++ ++/* return slot # for the pci device pointed by osh->pdev */ ++uint ++osl_pci_slot(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); ++} ++ ++/* return the pci device pointed by osh->pdev */ ++struct pci_dev * ++osl_pci_device(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return osh->pdev; ++} ++ ++static void ++osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write) ++{ ++} ++ ++void ++osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size) ++{ ++ osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE); ++} ++ ++void ++osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size) ++{ ++ osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE); ++} ++ ++void * ++osl_malloc(osl_t *osh, uint size) ++{ ++ void *addr; ++ ++ /* only ASSERT if osh is defined */ ++ if (osh) ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ ++#ifdef DHD_USE_STATIC_BUF ++ if (bcm_static_buf) ++ { ++ int i = 0; ++ if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE)) ++ { ++ down(&bcm_static_buf->static_sem); ++ ++ for (i = 0; i < STATIC_BUF_MAX_NUM; i++) ++ { ++ if (bcm_static_buf->buf_use[i] == 0) ++ break; ++ } ++ ++ if (i == STATIC_BUF_MAX_NUM) ++ { ++ up(&bcm_static_buf->static_sem); ++ printk("all static buff in use!\n"); ++ goto original; ++ } ++ ++ bcm_static_buf->buf_use[i] = 1; ++ up(&bcm_static_buf->static_sem); ++ ++ bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size); ++ if (osh) ++ atomic_add(size, &osh->malloced); ++ ++ return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i)); ++ } ++ } ++original: ++#endif /* DHD_USE_STATIC_BUF */ ++ ++ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { ++ if (osh) ++ osh->failed++; ++ return (NULL); ++ } ++ if (osh) ++ atomic_add(size, &osh->malloced); ++ ++ return (addr); ++} ++ ++void ++osl_mfree(osl_t *osh, void *addr, uint size) ++{ ++#ifdef DHD_USE_STATIC_BUF ++ if (bcm_static_buf) ++ { ++ if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr ++ <= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN))) ++ { ++ int buf_idx = 0; ++ ++ buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE; ++ ++ down(&bcm_static_buf->static_sem); ++ bcm_static_buf->buf_use[buf_idx] = 0; ++ up(&bcm_static_buf->static_sem); ++ ++ if (osh) { ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ atomic_sub(size, &osh->malloced); ++ } ++ return; ++ } ++ } ++#endif /* DHD_USE_STATIC_BUF */ ++ if (osh) { ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ atomic_sub(size, &osh->malloced); ++ } ++ kfree(addr); ++} ++ ++uint ++osl_malloced(osl_t *osh) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ return (atomic_read(&osh->malloced)); ++} ++ ++uint ++osl_malloc_failed(osl_t *osh) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ return (osh->failed); ++} ++ ++ ++uint ++osl_dma_consistent_align(void) ++{ ++ return (PAGE_SIZE); ++} ++ ++void* ++osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, ulong *pap) ++{ ++#ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ void *va; ++ uint16 align = (1 << align_bits); ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align)) ++ size += align; ++ *alloced = size; ++ ++ va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO); ++ if (va) ++ *pap = (ulong)__virt_to_phys((ulong)va); ++ return va; ++ ++#else ++ void *ret; ++// int gfp = GFP_KERNEL; //GFP_ATOMIC | GFP_DMA; ++ /* platform device reference */ ++ struct platform_device *pdev; ++ ++ uint16 align = (1 << align_bits); ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align)) ++ size += align; ++ *alloced = size; ++ ++// ret = (void *)__get_free_pages(gfp, get_order(size)); ++// if (ret != NULL) { ++// memset(ret, 0, size); ++// *pap = virt_to_phys(ret); ++// } ++ pdev = (struct platform_device *)osh->pdev; ++ ret = dma_alloc_coherent(&pdev->dev, size, (dma_addr_t*)pap, GFP_KERNEL); ++ return ret; ++ ++#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++void ++osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) ++{ ++#ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ kfree(va); ++#else ++ /* platform device reference */ ++ struct platform_device *pdev; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++// free_pages((unsigned long)va, get_order(size)); ++ pdev = (struct platform_device *)osh->pdev; ++ dma_free_coherent(&pdev->dev, size, va, (dma_addr_t)pa); ++#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++uint BCMFASTPATH ++osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah) ++{ ++ int dir; ++ /* platform device reference */ ++ struct platform_device *pdev; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ pdev = (struct platform_device *)osh->pdev; ++ dir = (direction == DMA_TX)? DMA_TO_DEVICE: DMA_FROM_DEVICE; ++ ++#if defined(BCMDMASGLISTOSL) ++ if (dmah != NULL) { ++ int32 nsegs, i, totsegs = 0, totlen = 0; ++ struct scatterlist *sg, _sg[MAX_DMA_SEGS * 2]; ++ struct sk_buff *skb; ++ for (skb = (struct sk_buff *)p; skb != NULL; skb = PKTNEXT(osh, skb)) { ++ sg = &_sg[totsegs]; ++ if (skb_is_nonlinear(skb)) { ++ nsegs = skb_to_sgvec(skb, sg, 0, PKTLEN(osh, skb)); ++ ASSERT((nsegs > 0) && (totsegs + nsegs <= MAX_DMA_SEGS)); ++ #ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ dma_map_sg(&pdev->dev, sg, nsegs, dir); ++ #endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++ } else { ++ nsegs = 1; ++ ASSERT(totsegs + nsegs <= MAX_DMA_SEGS); ++ sg->page_link = 0; ++ sg_set_buf(sg, PKTDATA(osh, skb), PKTLEN(osh, skb)); ++ #ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ dma_map_single(&pdev->dev, PKTDATA(osh, skb), PKTLEN(osh, skb), dir); ++ #endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++ } ++ totsegs += nsegs; ++ totlen += PKTLEN(osh, skb); ++ } ++ dmah->nsegs = totsegs; ++ dmah->origsize = totlen; ++ for (i = 0, sg = _sg; i < totsegs; i++, sg++) { ++ dmah->segs[i].addr = sg_phys(sg); ++ dmah->segs[i].length = sg->length; ++ } ++ #ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ return virt_to_phys(va); ++ #else ++ return dmah->segs[0].addr; ++ #endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++ } ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ return virt_to_phys(va); ++#else ++ return dma_map_single(&pdev->dev, va, size, dir); ++#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++void BCMFASTPATH ++osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction) ++{ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ int dir; ++ /* platform device reference */ ++ struct platform_device *pdev; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ pdev = (struct platform_device *)osh->pdev; ++ dir = (direction == DMA_TX)? DMA_TO_DEVICE: DMA_FROM_DEVICE; ++ dma_unmap_single(&pdev->dev, (uint32)pa, size, dir); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++ ++void ++osl_delay(uint usec) ++{ ++ uint d; ++ ++ while (usec > 0) { ++ d = MIN(usec, 1000); ++ udelay(d); ++ usec -= d; ++ } ++} ++ ++#if defined(DSLCPE_DELAY) ++ ++void ++osl_oshsh_init(osl_t *osh, shared_osl_t* oshsh) ++{ ++ extern unsigned long loops_per_jiffy; ++ osh->oshsh = oshsh; ++ osh->oshsh->MIPS = loops_per_jiffy / (500000/HZ); ++} ++ ++int ++in_long_delay(osl_t *osh) ++{ ++ return osh->oshsh->long_delay; ++} ++ ++void ++osl_long_delay(osl_t *osh, uint usec, bool yield) ++{ ++ uint d; ++ bool yielded = TRUE; ++ int usec_to_delay = usec; ++ unsigned long tick1, tick2, tick_diff = 0; ++ ++ /* delay at least requested usec */ ++ while (usec_to_delay > 0) { ++ if (!yield || !yielded) { ++ d = MIN(usec_to_delay, 10); ++ udelay(d); ++ usec_to_delay -= d; ++ } ++ if (usec_to_delay > 0) { ++ osh->oshsh->long_delay++; ++ OSL_GETCYCLES(tick1); ++ spin_unlock_bh(osh->oshsh->lock); ++ if (usec_to_delay > 0 && !in_irq() && !in_softirq() && !in_interrupt()) { ++ schedule(); ++ yielded = TRUE; ++ } else { ++ yielded = FALSE; ++ } ++ spin_lock_bh(osh->oshsh->lock); ++ OSL_GETCYCLES(tick2); ++ ++ if (yielded) { ++ tick_diff = TICKDIFF(tick2, tick1); ++ tick_diff = (tick_diff * 2)/(osh->oshsh->MIPS); ++ if (tick_diff) { ++ usec_to_delay -= tick_diff; ++ } else ++ yielded = 0; ++ } ++ osh->oshsh->long_delay--; ++ ASSERT(osh->oshsh->long_delay >= 0); ++ } ++ } ++} ++#endif /* DSLCPE_DELAY */ ++ ++/* Clone a packet. ++ * The pkttag contents are NOT cloned. ++ */ ++void * ++osl_pktdup(osl_t *osh, void *skb) ++{ ++ void * p; ++ ++ /* clear the CTFBUF flag if set and map the rest of the buffer ++ * before cloning. ++ */ ++ PKTCTFMAP(osh, skb); ++ ++ if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL) ++ return NULL; ++ ++#ifdef CTFPOOL ++ if (PKTISFAST(osh, skb)) { ++ ctfpool_t *ctfpool; ++ ++ /* if the buffer allocated from ctfpool is cloned then ++ * we can't be sure when it will be freed. since there ++ * is a chance that we will be losing a buffer ++ * from our pool, we increment the refill count for the ++ * object to be alloced later. ++ */ ++ ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); ++ ASSERT(ctfpool != NULL); ++ PKTCLRFAST(osh, p); ++ PKTCLRFAST(osh, skb); ++ ctfpool->refills++; ++ } ++#endif /* CTFPOOL */ ++ ++ /* skb_clone copies skb->cb.. we don't want that */ ++ if (osh->pub.pkttag) ++ OSL_PKTTAG_CLEAR(p); ++ ++ /* Increment the packet counter */ ++ atomic_inc(&osh->pktalloced); ++ return (p); ++} ++ ++ ++/* ++ * OSLREGOPS specifies the use of osl_XXX routines to be used for register access ++ */ ++#ifdef OSLREGOPS ++uint8 ++osl_readb(osl_t *osh, volatile uint8 *r) ++{ ++ osl_rreg_fn_t rreg = ((osl_pubinfo_t*)osh)->rreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ return (uint8)((rreg)(ctx, (void*)r, sizeof(uint8))); ++} ++ ++ ++uint16 ++osl_readw(osl_t *osh, volatile uint16 *r) ++{ ++ osl_rreg_fn_t rreg = ((osl_pubinfo_t*)osh)->rreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ return (uint16)((rreg)(ctx, (void*)r, sizeof(uint16))); ++} ++ ++uint32 ++osl_readl(osl_t *osh, volatile uint32 *r) ++{ ++ osl_rreg_fn_t rreg = ((osl_pubinfo_t*)osh)->rreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ return (uint32)((rreg)(ctx, (void*)r, sizeof(uint32))); ++} ++ ++void ++osl_writeb(osl_t *osh, volatile uint8 *r, uint8 v) ++{ ++ osl_wreg_fn_t wreg = ((osl_pubinfo_t*)osh)->wreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ ((wreg)(ctx, (void*)r, v, sizeof(uint8))); ++} ++ ++ ++void ++osl_writew(osl_t *osh, volatile uint16 *r, uint16 v) ++{ ++ osl_wreg_fn_t wreg = ((osl_pubinfo_t*)osh)->wreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ ((wreg)(ctx, (void*)r, v, sizeof(uint16))); ++} ++ ++void ++osl_writel(osl_t *osh, volatile uint32 *r, uint32 v) ++{ ++ osl_wreg_fn_t wreg = ((osl_pubinfo_t*)osh)->wreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ ((wreg)(ctx, (void*)r, v, sizeof(uint32))); ++} ++#endif /* OSLREGOPS */ ++ ++/* ++ * BINOSL selects the slightly slower function-call-based binary compatible osl. ++ */ ++#ifdef BINOSL ++ ++uint32 ++osl_sysuptime(void) ++{ ++ return ((uint32)jiffies * (1000 / HZ)); ++} ++ ++int ++osl_printf(const char *format, ...) ++{ ++ va_list args; ++ static char printbuf[1024]; ++ int len; ++ ++ /* sprintf into a local buffer because there *is* no "vprintk()".. */ ++ va_start(args, format); ++ len = vsnprintf(printbuf, 1024, format, args); ++ va_end(args); ++ ++ if (len > sizeof(printbuf)) { ++ printk("osl_printf: buffer overrun\n"); ++ return (0); ++ } ++ ++ return (printk("%s", printbuf)); ++} ++ ++int ++osl_sprintf(char *buf, const char *format, ...) ++{ ++ va_list args; ++ int rc; ++ ++ va_start(args, format); ++ rc = vsprintf(buf, format, args); ++ va_end(args); ++ return (rc); ++} ++ ++int ++osl_snprintf(char *buf, size_t n, const char *format, ...) ++{ ++ va_list args; ++ int rc; ++ ++ va_start(args, format); ++ rc = vsnprintf(buf, n, format, args); ++ va_end(args); ++ return (rc); ++} ++ ++int ++osl_vsprintf(char *buf, const char *format, va_list ap) ++{ ++ return (vsprintf(buf, format, ap)); ++} ++ ++int ++osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap) ++{ ++ return (vsnprintf(buf, n, format, ap)); ++} ++ ++int ++osl_strcmp(const char *s1, const char *s2) ++{ ++ return (strcmp(s1, s2)); ++} ++ ++int ++osl_strncmp(const char *s1, const char *s2, uint n) ++{ ++ return (strncmp(s1, s2, n)); ++} ++ ++int ++osl_strlen(const char *s) ++{ ++ return (strlen(s)); ++} ++ ++char* ++osl_strcpy(char *d, const char *s) ++{ ++ return (strcpy(d, s)); ++} ++ ++char* ++osl_strncpy(char *d, const char *s, uint n) ++{ ++ return (strncpy(d, s, n)); ++} ++ ++char* ++osl_strchr(const char *s, int c) ++{ ++ return (strchr(s, c)); ++} ++ ++char* ++osl_strrchr(const char *s, int c) ++{ ++ return (strrchr(s, c)); ++} ++ ++void* ++osl_memset(void *d, int c, size_t n) ++{ ++ return memset(d, c, n); ++} ++ ++void* ++osl_memcpy(void *d, const void *s, size_t n) ++{ ++ return memcpy(d, s, n); ++} ++ ++void* ++osl_memmove(void *d, const void *s, size_t n) ++{ ++ return memmove(d, s, n); ++} ++ ++int ++osl_memcmp(const void *s1, const void *s2, size_t n) ++{ ++ return memcmp(s1, s2, n); ++} ++ ++uint32 ++osl_readl(volatile uint32 *r) ++{ ++ return (readl(r)); ++} ++ ++uint16 ++osl_readw(volatile uint16 *r) ++{ ++ return (readw(r)); ++} ++ ++uint8 ++osl_readb(volatile uint8 *r) ++{ ++ return (readb(r)); ++} ++ ++void ++osl_writel(uint32 v, volatile uint32 *r) ++{ ++ writel(v, r); ++} ++ ++void ++osl_writew(uint16 v, volatile uint16 *r) ++{ ++ writew(v, r); ++} ++ ++void ++osl_writeb(uint8 v, volatile uint8 *r) ++{ ++ writeb(v, r); ++} ++ ++void * ++osl_uncached(void *va) ++{ ++#ifdef mips ++ return ((void*)KSEG1ADDR(va)); ++#else ++ return ((void*)va); ++#endif /* mips */ ++} ++ ++void * ++osl_cached(void *va) ++{ ++#ifdef mips ++ return ((void*)KSEG0ADDR(va)); ++#else ++ return ((void*)va); ++#endif /* mips */ ++} ++ ++uint ++osl_getcycles(void) ++{ ++ uint cycles; ++ ++#if defined(mips) ++ cycles = read_c0_count() * 2; ++#elif defined(__i386__) ++ rdtscl(cycles); ++#else ++ cycles = 0; ++#endif /* defined(mips) */ ++ return cycles; ++} ++ ++void * ++osl_reg_map(uint32 pa, uint size) ++{ ++ return (ioremap_nocache((unsigned long)pa, (unsigned long)size)); ++} ++ ++void ++osl_reg_unmap(void *va) ++{ ++ iounmap(va); ++} ++ ++int ++osl_busprobe(uint32 *val, uint32 addr) ++{ ++#ifdef mips ++ return get_dbe(*val, (uint32 *)addr); ++#else ++ *val = readl((uint32 *)(uintptr)addr); ++ return 0; ++#endif /* mips */ ++} ++ ++bool ++osl_pktshared(void *skb) ++{ ++ return (((struct sk_buff*)skb)->cloned); ++} ++ ++uchar* ++osl_pktdata(osl_t *osh, void *skb) ++{ ++ return (((struct sk_buff*)skb)->data); ++} ++ ++uint ++osl_pktlen(osl_t *osh, void *skb) ++{ ++ return (((struct sk_buff*)skb)->len); ++} ++ ++uint ++osl_pktheadroom(osl_t *osh, void *skb) ++{ ++ return (uint) skb_headroom((struct sk_buff *) skb); ++} ++ ++uint ++osl_pkttailroom(osl_t *osh, void *skb) ++{ ++ return (uint) skb_tailroom((struct sk_buff *) skb); ++} ++ ++void* ++osl_pktnext(osl_t *osh, void *skb) ++{ ++ return (((struct sk_buff*)skb)->next); ++} ++ ++void ++osl_pktsetnext(void *skb, void *x) ++{ ++ ((struct sk_buff*)skb)->next = (struct sk_buff*)x; ++} ++ ++void ++osl_pktsetlen(osl_t *osh, void *skb, uint len) ++{ ++ __pskb_trim((struct sk_buff*)skb, len); ++} ++ ++uchar* ++osl_pktpush(osl_t *osh, void *skb, int bytes) ++{ ++ return (skb_push((struct sk_buff*)skb, bytes)); ++} ++ ++uchar* ++osl_pktpull(osl_t *osh, void *skb, int bytes) ++{ ++ return (skb_pull((struct sk_buff*)skb, bytes)); ++} ++ ++void* ++osl_pkttag(void *skb) ++{ ++ return ((void*)(((struct sk_buff*)skb)->cb)); ++} ++ ++void* ++osl_pktlink(void *skb) ++{ ++ return (((struct sk_buff*)skb)->prev); ++} ++ ++void ++osl_pktsetlink(void *skb, void *x) ++{ ++ ((struct sk_buff*)skb)->prev = (struct sk_buff*)x; ++} ++ ++uint ++osl_pktprio(void *skb) ++{ ++ return (((struct sk_buff*)skb)->priority); ++} ++ ++void ++osl_pktsetprio(void *skb, uint x) ++{ ++ ((struct sk_buff*)skb)->priority = x; ++} ++#endif /* BINOSL */ ++ ++uint ++osl_pktalloced(osl_t *osh) ++{ ++ return (atomic_read(&osh->pktalloced)); ++} ++ ++/* Linux Kernel: File Operations: start */ ++void * ++osl_os_open_image(char *filename) ++{ ++ struct file *fp; ++ ++ fp = filp_open(filename, O_RDONLY, 0); ++ /* ++ * 2.6.11 (FC4) supports filp_open() but later revs don't? ++ * Alternative: ++ * fp = open_namei(AT_FDCWD, filename, O_RD, 0); ++ * ??? ++ */ ++ if (IS_ERR(fp)) ++ fp = NULL; ++ ++ return fp; ++} ++ ++int ++osl_os_get_image_block(char *buf, int len, void *image) ++{ ++ struct file *fp = (struct file *)image; ++ int rdlen; ++ ++ if (!image) ++ return 0; ++ ++ rdlen = kernel_read(fp, fp->f_pos, buf, len); ++ if (rdlen > 0) ++ fp->f_pos += rdlen; ++ ++ return rdlen; ++} ++ ++void ++osl_os_close_image(void *image) ++{ ++ if (image) ++ filp_close((struct file *)image, NULL); ++} ++/* Linux Kernel: File Operations: end */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/nsp_erom.c b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.c +new file mode 100755 +index 0000000..9ad67a0 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.c +@@ -0,0 +1,67 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Northstar+ sudo EROM ++ * ++ */ ++#include ++ ++uint32 nsp_erom[] = { ++ //#define CC_CORE_ID 0x800 /* chipcommon core */ ++ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, ++ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, ++ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, ++ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, ++ 0x4bf82d01, 0x04004211, 0x00000203, 0x18023005, 0x181110c5, ++ 0x4bf82d01, 0x04004211, 0x00000303, 0x18024005, 0x181120c5, ++ 0x4bf82d01, 0x04004211, 0x00000403, 0x18025005, 0x181130c5, ++ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, ++ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, ++ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, ++ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, ++ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, ++ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, ++ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, ++ //#define I2S_CORE_ID 0x834 /* I2S core */ ++ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, ++ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, ++ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, ++ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, ++ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, ++ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, ++ //#define EROM_CORE_ID 0x366 /* EROM core ID */ ++ 0x43b36601, 0x00000201, 0x18130005, ++ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, ++ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, ++ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, ++ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, ++ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, ++ 0x18134285, 0x18135385, 0x18136485, ++ 0x0000000f ++}; +diff --git a/drivers/bcmdrivers/gmac/src/shared/nsp_erom.h b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.h +new file mode 100755 +index 0000000..98cf29e +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++ ++#ifndef _nsp_erom_h_ ++#define _snp_erom_h_ ++ ++extern uint32 nsp_erom[]; ++ ++#endif //_nsp_erom_h_ +diff --git a/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c b/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c +new file mode 100755 +index 0000000..d5b400d +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c +@@ -0,0 +1,365 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Stubs for NVRAM functions for platforms without flash ++ * ++ * $Id: nvramstubs.c 325991 2012-04-05 10:16:42Z $ ++ */ ++ ++#include ++#include ++#include ++#undef strcmp ++#define strcmp(s1,s2) 0 /* always match */ ++#include ++#include ++#include ++ ++int brcm_get_hx4_model(void); ++ ++int ++nvram_init(void *sih) ++{ ++ return 0; ++} ++ ++int ++nvram_append(void *sb, char *vars, uint varsz) ++{ ++ return 0; ++} ++ ++void ++nvram_exit(void *sih) ++{ ++} ++ ++/* fake nvram tuples */ ++typedef struct { ++ char *name; ++ char *value; ++} nvram_t; ++ ++static nvram_t fake_nvram[] = { ++ {"boardtype", "0x058d"}, ++ {"boardnum", "0x010"}, ++ {"boardrev", "0x1100"}, ++ {"boardflags", "0x710"}, ++ {"boardflags2", "0"}, ++ {"sromrev", "8"}, ++ {"clkfreq", "133,133,133"}, ++ {"xtalfreq", "125000"}, ++ {"et_txq_thresh", "1024"}, ++ {"et_rx_rate_limit","1"}, ++ {"sdram_config", "0x103"}, ++ {"swgmacet", "et2"}, ++ {"brcmtag", "1"}, ++ //{"ethaddr", "00:90:4c:06:a5:72"}, ++#ifdef FOUR_PORT_CONFIG ++ {"vlan1hwname", "et2"}, ++ {"vlan1ports", "0 1 2 8*"}, ++ {"vlan2hwname", "et2"}, ++ {"vlan2ports", "3 8*"}, ++ {"wanport", "3"}, ++#else ++#if (defined(CONFIG_ROOT_NFS) && defined(CONFIG_MACH_NSP)) ++ ++ {"vlan1hwname", "et2"}, ++ {"vlan1ports", "0 1 2 3 8u"}, ++ {"wanport", "4"}, ++#else ++ {"vlan1hwname", "et2"}, ++ {"vlan1ports", "0 1 2 3 8*"}, ++ {"vlan2hwname", "et2"}, ++ {"vlan2ports", "4 8*"}, ++ {"wanport", "4"}, ++#endif //(defined(CONFIG_ROOT_NFS) && defined(CONFIG_MACH_NSP)) ++#endif ++ {"landevs", "vlan1"}, ++ {"wandevs", "et0"}, ++ {"lan_ipaddr", "192.168.1.1"}, ++ {"lan_netmask", "255.255.255.0"}, ++ {"boot_wait", "on"}, ++ {"wait_time", "3"}, ++ {"watchdog", "0"}, ++ {"et_msglevel", "0xFFFFFFFF"} ++}; ++ ++#define fake_nvram_size sizeof(fake_nvram)/sizeof(fake_nvram[0]) ++ ++#ifndef FAKE_NVRAM ++ ++#define CONFIG_SPI_BASE 0x1e000000 ++#define CONFIG_NAND_BASE 0x1c000000 ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++#define CONFIG_ENV_OFFSET 0xa0000 /* 30000-b0000 - use last 10000 for env */ ++#else ++#define CONFIG_ENV_OFFSET 0xc0000 /* 30000-b0000 - use last 10000 for env */ ++#endif ++#define CONFIG_ENV_SIZE 0x20000 /* 128K */ ++#define CONFIG_ENV_MAX_ENTRIES 512 ++ ++#define UBOOT_ENV_ADDR CONFIG_SPI_BASE+CONFIG_ENV_OFFSET ++#define UBOOT_ENV_SIZE CONFIG_ENV_SIZE ++#define UBOOT_ENV_MAX_NUM CONFIG_ENV_MAX_ENTRIES ++ ++static uint8 u_boot_env[UBOOT_ENV_SIZE]; ++static bool u_boot_env_loaded=false; ++static nvram_t env_list[UBOOT_ENV_MAX_NUM]; ++static int uboot_vars_start = UBOOT_ENV_ADDR; ++static int uboot_nvram_max = UBOOT_ENV_SIZE; ++ ++/* pass envaddr= in bootargs */ ++static int __init envaddr_setup(char *str) ++{ ++ int ret =0; ++ unsigned long ul=0; ++ ++ //printk("NVRAM: %s\n", str); ++ ++ ret = strict_strtoul(str, 16, &ul); ++ ++ if (!ret) { ++ uboot_vars_start = ul; ++ printk("NVRAM: assign 0x%08x\n", uboot_vars_start); ++ } ++ ++ return !ret; ++} ++__setup("envaddr=", envaddr_setup); ++ ++enum { ++ HX4_NONE = 0, ++ HX4_DNI_3448P, ++ HX4_ACCTON_AS4610_54 ++}; ++ ++static void ++setup_uboot_vars(void) { ++ int modelnum; ++ int env_offset; ++ ++ modelnum = brcm_get_hx4_model(); ++ if (modelnum == HX4_DNI_3448P) { ++ env_offset = 0x00100000; ++ uboot_vars_start = CONFIG_NAND_BASE + env_offset; ++ } else if (modelnum == HX4_ACCTON_AS4610_54) { ++ env_offset = 0x000f0000; ++ uboot_vars_start = CONFIG_SPI_BASE + env_offset; ++ } ++} ++ ++/* ++APIs for access into uboot env vars ++*/ ++ ++int ++nvram_env_init(void) ++{ ++ volatile void *envbuf; ++ char *dp, *sp, *name, *value, *dp_end; ++ char sep = '\0'; ++ int idx=0; ++ ++ setup_uboot_vars(); ++ ++ printk("NVRAM: map 0x%08x\n", uboot_vars_start); ++ ++ /* map uboot env */ ++ if ((envbuf = (uint8*)ioremap(uboot_vars_start, UBOOT_ENV_SIZE)) == NULL) { ++ printk("%s: ioremap() failed\n", __FUNCTION__); ++ return -ENOMEM; ++ } ++ ++ /* copy memory into buffer */ ++ memcpy((void*)u_boot_env, (void *) envbuf, uboot_nvram_max); ++ ++ /* clear fake entry set */ ++ memset(env_list, 0, sizeof(env_list)); ++ ++ /* load uboot fake nvram buffer */ ++ /* point to first data */ ++ dp = (char*)u_boot_env; ++ /* point to data buffer */ ++ dp += 4; ++ dp_end = (char*)((uint32)u_boot_env+UBOOT_ENV_SIZE); ++ ++ /* point to first data */ ++ do { ++ ++ /* skip leading white space */ ++ while ((*dp == ' ') || (*dp == '\t')) ++ ++dp; ++ ++ /* skip comment lines */ ++ if (*dp == '#') { ++ while (*dp && (*dp != sep)) ++ ++dp; ++ ++dp; ++ continue; ++ } ++ ++ /* parse name */ ++ for (name = dp; *dp != '=' && *dp && *dp != sep; ++dp) ++ ; ++ ++ *dp++ = '\0'; /* terminate name */ ++ ++ /* parse value; deal with escapes */ ++ for (value = sp = dp; *dp && (*dp != sep); ++dp) { ++ if ((*dp == '\\') && *(dp + 1)) ++ ++dp; ++ *sp++ = *dp; ++ } ++ *sp++ = '\0'; /* terminate value */ ++ ++dp; ++ ++ /* enter into hash table */ ++ env_list[idx].name = name; ++ env_list[idx].value = value; ++ //printk("entry%d %s=%s\n", idx, name, value); ++ idx++; ++ ++ /* check if table is full */ ++ if (idx >= UBOOT_ENV_MAX_NUM ) { ++ printk("%s: WARNING - UBoot environment table is full\n", __FUNCTION__); ++ break; ++ } ++ ++ /* check if end of table */ ++ } while ((dp < dp_end) && *dp); /* size check needed for text */ ++ ++ u_boot_env_loaded = true; ++ ++ /* unmap uboot env */ ++ iounmap(envbuf); ++ ++ return 0; ++} ++#endif ++ ++int ++nvram_env_gmac_name(int gmac, char *name) ++{ ++ int ret=0; ++ switch (gmac) ++ { ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ case 0: ++ case 1: ++ sprintf(name, "eth%daddr", gmac+1); ++ break; ++ case 2: ++ strcpy(name, "ethaddr"); ++ break; ++ case 3: ++ sprintf(name, "eth%daddr", gmac); ++ break; ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ case 0: ++ strcpy(name, "ethaddr"); ++ break; ++ case 1: ++ sprintf(name, "eth1addr"); ++ break; ++#elif defined(CONFIG_MACH_HR2) ++ case 0: ++ strcpy(name, "ethaddr"); ++ break; ++#endif ++ default: ++ strcpy(name, "unknown"); ++ ret = -1; ++ break; ++ } ++ return ret; ++ ++} ++ ++char * ++nvram_get(const char *name) ++{ ++ int i, len; ++ nvram_t *tuple; ++ int num_entries; ++ ++ if (!name) ++ return (char *) 0; ++ ++ len = strlen(name); ++ if (len == 0) ++ return (char *) 0; ++ ++#ifndef FAKE_NVRAM ++ tuple = &env_list[0]; ++ num_entries = sizeof(env_list)/sizeof(nvram_t); ++ ++ if (!u_boot_env_loaded) ++ nvram_env_init(); ++ ++ /* first check the uboot NVRAM variables */ ++ for (i = 0; i < num_entries; i++) { ++ ++ if (tuple->name && (bcmp(tuple->name, name, len) == 0) && (strlen(tuple->name)==len)) { ++ /*printf("%s (NVRAM) %s: %s\n", __FUNCTION__, name, tuple->value);*/ ++ return tuple->value; ++ } ++ tuple++; ++ } ++#endif ++ ++ /* if cant find then check fake table above */ ++ tuple = &fake_nvram[0]; ++ num_entries = fake_nvram_size; ++ for (i = 0; i < num_entries; i++) { ++ ++ if (tuple->name && (bcmp(tuple->name, name, len) == 0) && (strlen(tuple->name)==len)) { ++ /*printf("%s (STUBS) %s: %s\n", __FUNCTION__, name, tuple->value);*/ ++ return tuple->value; ++ } ++ tuple++; ++ } ++ ++ return (char *) 0; ++} ++ ++int ++nvram_set(const char *name, const char *value) ++{ ++ return 0; ++} ++ ++int ++nvram_unset(const char *name) ++{ ++ return 0; ++} ++ ++int ++nvram_commit(void) ++{ ++ return 0; ++} ++ ++int ++nvram_getall(char *buf, int count) ++{ ++ /* add null string as terminator */ ++ if (count < 1) ++ return BCME_BUFTOOSHORT; ++ *buf = '\0'; ++ return 0; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/siutils.c b/drivers/bcmdrivers/gmac/src/shared/siutils.c +new file mode 100755 +index 0000000..23f84ac +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/siutils.c +@@ -0,0 +1,1536 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc utility routines for accessing chip-specific features ++ * of the SiliconBackplane-based Broadcom chips. ++ * ++ * $Id: siutils.c 328955 2012-04-23 09:06:12Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if !defined(BCM_BOOTLOADER) && defined(SAVERESTORE) ++#include ++#endif /* !defined(BCM_BOOTLOADER) && defined(SAVERESTORE) */ ++ ++#include "siutils_priv.h" ++ ++/* local prototypes */ ++static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz); ++static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh); ++static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, ++ uint *origidx, void *regs); ++ ++static void si_nvram_process(si_info_t *sii, char *pvars); ++/* dev path concatenation util */ ++static char *si_devpathvar(si_t *sih, char *var, int len, const char *name); ++static bool _si_clkctl_cc(si_info_t *sii, uint mode); ++ ++ ++/* global variable to indicate reservation/release of gpio's */ ++static uint32 si_gpioreservation = 0; ++ ++/* global flag to prevent shared resources from being initialized multiple times in si_attach() */ ++ ++EXPORT_SYMBOL(si_attach); ++EXPORT_SYMBOL(si_setcore); ++ ++/* ++ * Allocate a si handle. ++ * devid - pci device id (used to determine chip#) ++ * osh - opaque OS handle ++ * regs - virtual address of initial core registers ++ * bustype - pci/pcmcia/sb/sdio/etc ++ * vars - pointer to a pointer area for "environment" variables ++ * varsz - pointer to int to return the size of the vars ++ */ ++si_t * ++BCMATTACHFN(si_attach)(uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz) ++{ ++ si_info_t *sii; ++ si_t *sih; ++ ++ /* alloc si_info_t */ ++ if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) { ++ SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); ++ return (NULL); ++ } ++ ++ if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { ++ MFREE(osh, sii, sizeof(si_info_t)); ++ SI_ERROR(("%s si_doattach() failed\n", __FUNCTION__)); ++ return (NULL); ++ } ++ sii->vars = vars ? *vars : NULL; ++ sii->varsz = varsz ? *varsz : 0; ++ ++ sih = (si_t*)sii; ++ printk("%s socitype(0x%x) chip(0x%x) chiprev(0x%x) chippkg(0x%x)\n", ++ __FUNCTION__, sih->socitype, sih->chip, sih->chiprev, sih->chippkg); ++ ++ return (si_t *)sii; ++} ++ ++/* global kernel resource */ ++static si_info_t ksii; ++ ++static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */ ++ ++/* generic kernel variant of si_attach() */ ++si_t * ++BCMATTACHFN(si_kattach)(osl_t *osh) ++{ ++ static bool ksii_attached = FALSE; ++ ++ if (!ksii_attached) { ++ void *regs; ++#ifndef SI_ENUM_BASE_VARIABLE ++ regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); ++#endif ++ ++ if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, ++ SI_BUS, NULL, ++ osh != SI_OSH ? &ksii.vars : NULL, ++ osh != SI_OSH ? &ksii.varsz : NULL) == NULL) { ++ SI_ERROR(("si_kattach: si_doattach failed\n")); ++ REG_UNMAP(regs); ++ return NULL; ++ } ++ REG_UNMAP(regs); ++ ++ /* save ticks normalized to ms for si_watchdog_ms() */ ++ if (PMUCTL_ENAB(&ksii.pub)) { ++ /* based on 32KHz ILP clock */ ++ wd_msticks = 32; ++ } else { ++ if (ksii.pub.ccrev < 18) ++ wd_msticks = si_clock(&ksii.pub) / 1000; ++ else ++ wd_msticks = si_alp_clock(&ksii.pub) / 1000; ++ } ++ ++ ksii_attached = TRUE; ++ SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n", ++ ksii.pub.ccrev, wd_msticks)); ++ } ++ ++ return &ksii.pub; ++} ++ ++static bool ++BCMATTACHFN(si_buscore_prep)(si_info_t *sii, uint bustype, uint devid, void *sdh) ++{ ++ return TRUE; ++} ++ ++static bool ++BCMATTACHFN(si_buscore_setup)(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, ++ uint *origidx, void *regs) ++{ ++ bool pci, pcie; ++ uint i; ++ uint pciidx, pcieidx, pcirev, pcierev; ++ ++ cc = si_setcoreidx(&sii->pub, SI_CC_IDX); ++ ASSERT((uintptr)cc); ++ ++ /* get chipcommon rev */ ++ sii->pub.ccrev = (int)si_corerev(&sii->pub); ++ ++ /* get chipcommon chipstatus */ ++ if (sii->pub.ccrev >= 11) ++ sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); ++ ++ /* get chipcommon capabilites */ ++ sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); ++ /* get chipcommon extended capabilities */ ++ ++ if (sii->pub.ccrev >= 35) ++ sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext); ++ ++ /* get pmu rev and caps */ ++ if (sii->pub.cccaps & CC_CAP_PMU) { ++ sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); ++ sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; ++ } ++ ++ SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", ++ sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, ++ sii->pub.pmucaps)); ++ ++ /* figure out bus/orignal core idx */ ++ sii->pub.buscoretype = NODEV_CORE_ID; ++ sii->pub.buscorerev = (uint)NOREV; ++ sii->pub.buscoreidx = BADIDX; ++ ++ pci = pcie = FALSE; ++ pcirev = pcierev = (uint)NOREV; ++ pciidx = pcieidx = BADIDX; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ uint cid, crev; ++ ++ si_setcoreidx(&sii->pub, i); ++ cid = si_coreid(&sii->pub); ++ crev = si_corerev(&sii->pub); ++ ++ /* Display cores found */ ++ SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", ++ i, cid, crev, sii->coresba[i], sii->regs[i])); ++ ++ /* find the core idx before entering this func. */ ++ if ((savewin && (savewin == sii->coresba[i])) || ++ (regs == sii->regs[i])) ++ *origidx = i; ++ } ++ ++ SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, ++ sii->pub.buscorerev)); ++ ++ /* return to the original core */ ++ si_setcoreidx(&sii->pub, *origidx); ++ ++ return TRUE; ++} ++ ++static void ++BCMATTACHFN(si_nvram_process)(si_info_t *sii, char *pvars) ++{ ++ /* get boardtype and boardrev */ ++ switch (BUSTYPE(sii->pub.bustype)) { ++ case SI_BUS: ++ sii->pub.boardvendor = VENDOR_BROADCOM; ++ if (pvars == NULL || ((sii->pub.boardtype = getintvar(pvars, "prodid")) == 0)) ++ if ((sii->pub.boardtype = getintvar(NULL, "boardtype")) == 0) ++ sii->pub.boardtype = 0xffff; ++ break; ++ } ++ ++ if (sii->pub.boardtype == 0) { ++ SI_ERROR(("si_doattach: unknown board type\n")); ++ ASSERT(sii->pub.boardtype); ++ } ++ ++ sii->pub.boardrev = getintvar(pvars, "boardrev"); ++ sii->pub.boardflags = getintvar(pvars, "boardflags"); ++} ++ ++ ++static si_info_t * ++BCMATTACHFN(si_doattach)(si_info_t *sii, uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz) ++{ ++ struct si_pub *sih = &sii->pub; ++ uint32 w, savewin; ++ chipcregs_t *cc; ++ char *pvars = NULL; ++ uint origidx; ++ ASSERT(GOODREGS(regs)); ++ ++ bzero((uchar*)sii, sizeof(si_info_t)); ++ ++ savewin = 0; ++ ++ sih->buscoreidx = BADIDX; ++ ++ sii->curmap = regs; ++ sii->sdh = sdh; ++ sii->osh = osh; ++ ++#ifdef SI_ENUM_BASE_VARIABLE ++ si_enum_base_init(sih, bustype); ++#endif /* SI_ENUM_BASE_VARIABLE */ ++ ++ /* check to see if we are a si core mimic'ing a pci core */ ++ if ((bustype == PCI_BUS)) { ++ SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI " ++ "devid:0x%x\n", __FUNCTION__, devid)); ++ bustype = SI_BUS; ++ } ++ ++ /* find Chipcommon address */ ++ cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); ++ ++ sih->bustype = bustype; ++ if (bustype != BUSTYPE(bustype)) { ++ SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", ++ bustype, BUSTYPE(bustype))); ++ return NULL; ++ } ++ ++ /* bus/core/clk setup for register access */ ++ if (!si_buscore_prep(sii, bustype, devid, sdh)) { ++ SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype)); ++ return NULL; ++ } ++ ++ /* ChipID recognition. ++ * We assume we can read chipid at offset 0 from the regs arg. ++ * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), ++ * some way of recognizing them needs to be added here. ++ */ ++ if (!cc) { ++ SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__)); ++ return NULL; ++ } ++ w = R_REG(osh, &cc->chipid); ++ printk("%s chipid: 0x%x\n", __FUNCTION__, w); ++ sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; ++ /* Might as wll fill in chip id rev & pkg */ ++ sih->chip = w & CID_ID_MASK; ++ sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; ++ sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; ++ /* printk("%s chip: 0x%x; chiprev: 0x%x; chippkg: 0x%x\n", __FUNCTION__, sih->chip, sih->chiprev, sih->chippkg); */ ++ ++ sih->issim = IS_SIM(sih->chippkg); ++ ++ /* scan for cores */ ++ if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { ++ SI_MSG(("Found chip type SB (0x%08x)\n", w)); ++ sb_scan(&sii->pub, regs, devid); ++ } else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) || (CHIPTYPE(sii->pub.socitype) == SOCI_NS)) { ++ if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) ++ SI_MSG(("Found chip type AI (0x%08x)\n", w)); ++ else ++ SI_MSG(("Found chip type NS (0x%08x)\n", w)); ++ /* pass chipc address instead of original core base */ ++ ai_scan(&sii->pub, (void *)(uintptr)cc, devid); ++ } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) { ++ SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip)); ++ /* pass chipc address instead of original core base */ ++ ub_scan(&sii->pub, (void *)(uintptr)cc, devid); ++ } else { ++ SI_ERROR(("Found chip of unknown type (0x%08x)\n", w)); ++ return NULL; ++ } ++ /* no cores found, bail out */ ++ if (sii->numcores == 0) { ++ SI_ERROR(("si_doattach: could not find any cores\n")); ++ return NULL; ++ } ++ /* bus/core/clk setup */ ++ origidx = SI_CC_IDX; ++ if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { ++ SI_ERROR(("si_doattach: si_buscore_setup failed\n")); ++ goto exit; ++ } ++ ++#ifdef SI_SPROM_PROBE ++ si_sprom_init(sih); ++#endif /* SI_SPROM_PROBE */ ++ ++#if !defined(BCMHIGHSDIO) ++ /* Init nvram from flash if it exists */ ++ nvram_init((void *)&(sii->pub)); ++ ++ pvars = vars ? *vars : NULL; ++ ++ si_nvram_process(sii, pvars); ++ ++ /* === NVRAM, clock is ready === */ ++#else ++ pvars = NULL; ++ BCM_REFERENCE(pvars); ++#endif ++ ++ ++ /* bootloader should retain default pulls */ ++#ifndef BCM_BOOTLOADER ++ if (sii->pub.ccrev >= 20) { ++ uint32 gpiopullup = 0, gpiopulldown = 0; ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ASSERT(cc != NULL); ++ ++ /* 4314/43142 has pin muxing, don't clear gpio bits */ ++ if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43142_CHIP_ID)) { ++ gpiopullup |= 0x402e0; ++ gpiopulldown |= 0x20500; ++ } ++ ++ W_REG(osh, &cc->gpiopullup, gpiopullup); ++ W_REG(osh, &cc->gpiopulldown, gpiopulldown); ++ si_setcoreidx(sih, origidx); ++ } ++#endif /* !BCM_BOOTLOADER */ ++ ++ ++ /* setup the GPIO based LED powersave register */ ++ if (sii->pub.ccrev >= 16) { ++ if ((w = getintvar(pvars, "leddc")) == 0) ++ w = DEFAULT_GPIOTIMERVAL; ++ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w); ++ } ++ ++ if (PCI_FORCEHT(sii)) { ++ SI_MSG(("si_doattach: force HT\n")); ++ sih->pci_pr32414 = TRUE; ++ si_clkctl_init(sih); ++ _si_clkctl_cc(sii, CLK_FAST); ++ } ++ ++#if !defined(_CFE_) || defined(CFG_WL) ++ /* enable GPIO interrupts when clocks are off */ ++ if (sii->pub.ccrev >= 21) { ++ uint32 corecontrol; ++ corecontrol = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol), ++ 0, 0); ++ corecontrol |= CC_ASYNCGPIO; ++ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol), ++ corecontrol, corecontrol); ++ } ++ ++#endif /* !_CFE_ || CFG_WL */ ++ ++#if defined(SAVERESTORE) ++ sr_save_restore_init(sih); ++#endif ++ ++ ++ return (sii); ++ ++exit: ++ ++ return NULL; ++} ++ ++/* may be called with core in reset */ ++void ++BCMATTACHFN(si_detach)(si_t *sih) ++{ ++ si_info_t *sii; ++ uint idx; ++ ++#if defined(STA) ++ struct si_pub *si_local = NULL; ++ bcopy(&sih, &si_local, sizeof(si_t*)); ++#endif ++ ++ sii = SI_INFO(sih); ++ ++ if (sii == NULL) ++ return; ++ ++ if (BUSTYPE(sih->bustype) == SI_BUS) ++ for (idx = 0; idx < SI_MAXCORES; idx++) ++ if (sii->regs[idx]) { ++ REG_UNMAP(sii->regs[idx]); ++ sii->regs[idx] = NULL; ++ } ++ ++#if defined(STA) ++#if !defined(BCMHIGHSDIO) ++ srom_var_deinit((void *)si_local); ++#endif ++ nvram_exit((void *)si_local); /* free up nvram buffers */ ++#endif ++ ++#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) ++ if (sii != &ksii) ++#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */ ++ MFREE(sii->osh, sii, sizeof(si_info_t)); ++} ++ ++void * ++si_osh(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ return sii->osh; ++} ++ ++void ++si_setosh(si_t *sih, osl_t *osh) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ if (sii->osh != NULL) { ++ SI_ERROR(("osh is already set....\n")); ++ ASSERT(!sii->osh); ++ } ++ sii->osh = osh; ++} ++ ++uint ++si_intflag(si_t *sih) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_intflag(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return R_REG(sii->osh, ((uint32 *)(uintptr) ++ (sii->oob_router + OOB_STATUSA))); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++uint ++si_flag(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_flag(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_flag(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_flag(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_setint(si_t *sih, int siflag) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_setint(sih, siflag); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_setint(sih, siflag); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_setint(sih, siflag); ++ else ++ ASSERT(0); ++} ++ ++uint ++si_coreid(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ return sii->coreid[sii->curidx]; ++} ++ ++uint ++si_coreidx(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ return sii->curidx; ++} ++ ++/* return the core-type instantiation # of the current core */ ++uint ++si_coreunit(si_t *sih) ++{ ++ si_info_t *sii; ++ uint idx; ++ uint coreid; ++ uint coreunit; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ coreunit = 0; ++ ++ idx = sii->curidx; ++ ++ ASSERT(GOODREGS(sii->curmap)); ++ coreid = si_coreid(sih); ++ ++ /* count the cores of our type */ ++ for (i = 0; i < idx; i++) ++ if (sii->coreid[i] == coreid) ++ coreunit++; ++ ++ return (coreunit); ++} ++ ++uint ++si_corevendor(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_corevendor(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_corevendor(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_corevendor(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++bool ++si_backplane64(si_t *sih) ++{ ++ return ((sih->cccaps & CC_CAP_BKPLN64) != 0); ++} ++ ++uint ++si_corerev(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_corerev(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_corerev(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_corerev(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++/* return index of coreid or BADIDX if not found */ ++uint ++si_findcoreidx(si_t *sih, uint coreid, uint coreunit) ++{ ++ si_info_t *sii; ++ uint found; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ ++ found = 0; ++ ++ for (i = 0; i < sii->numcores; i++) ++ if (sii->coreid[i] == coreid) { ++ if (found == coreunit) ++ return (i); ++ found++; ++ } ++ ++ return (BADIDX); ++} ++ ++/* return list of found cores */ ++uint ++si_corelist(si_t *sih, uint coreid[]) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint))); ++ return (sii->numcores); ++} ++ ++/* return current register mapping */ ++void * ++si_coreregs(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ASSERT(GOODREGS(sii->curmap)); ++ ++ return (sii->curmap); ++} ++ ++/* ++ * This function changes logical "focus" to the indicated core; ++ * must be called with interrupts off. ++ * Moreover, callers should keep interrupts off during switching out of and back to d11 core ++ */ ++void * ++si_setcore(si_t *sih, uint coreid, uint coreunit) ++{ ++ uint idx; ++ ++ idx = si_findcoreidx(sih, coreid, coreunit); ++ if (!GOODIDX(idx)) ++ return (NULL); ++ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_setcoreidx(sih, idx); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_setcoreidx(sih, idx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_setcoreidx(sih, idx); ++ else { ++ ASSERT(0); ++ return NULL; ++ } ++} ++ ++void * ++si_setcoreidx(si_t *sih, uint coreidx) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_setcoreidx(sih, coreidx); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_setcoreidx(sih, coreidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_setcoreidx(sih, coreidx); ++ else { ++ ASSERT(0); ++ return NULL; ++ } ++} ++ ++/* Turn off interrupt as required by sb_setcore, before switch core */ ++void * ++si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val) ++{ ++ void *cc; ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ if (SI_FAST(sii)) { ++ /* Overloading the origidx variable to remember the coreid, ++ * this works because the core ids cannot be confused with ++ * core indices. ++ */ ++ *origidx = coreid; ++ if (coreid == CC_CORE_ID) ++ return (void *)CCREGS_FAST(sii); ++ else if (coreid == sih->buscoretype) ++ return (void *)PCIEREGS(sii); ++ } ++ INTR_OFF(sii, *intr_val); ++ *origidx = sii->curidx; ++ cc = si_setcore(sih, coreid, 0); ++ ASSERT(cc != NULL); ++ ++ return cc; ++} ++ ++/* restore coreidx and restore interrupt */ ++void ++si_restore_core(si_t *sih, uint coreid, uint intr_val) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) ++ return; ++ ++ si_setcoreidx(sih, coreid); ++ INTR_RESTORE(sii, intr_val); ++} ++ ++int ++si_numaddrspaces(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_numaddrspaces(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_numaddrspaces(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_numaddrspaces(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++uint32 ++si_addrspace(si_t *sih, uint asidx) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_addrspace(sih, asidx); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_addrspace(sih, asidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_addrspace(sih, asidx); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++uint32 ++si_addrspacesize(si_t *sih, uint asidx) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_addrspacesize(sih, asidx); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_addrspacesize(sih, asidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_addrspacesize(sih, asidx); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) ++{ ++ /* Only supported for SOCI_AI */ ++ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_coreaddrspaceX(sih, asidx, addr, size); ++ else ++ *size = 0; ++} ++ ++uint32 ++si_core_cflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_core_cflags(sih, mask, val); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_core_cflags(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_core_cflags(sih, mask, val); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_core_cflags_wo(sih, mask, val); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_core_cflags_wo(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_core_cflags_wo(sih, mask, val); ++ else ++ ASSERT(0); ++} ++ ++uint32 ++si_core_sflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_core_sflags(sih, mask, val); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_core_sflags(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_core_sflags(sih, mask, val); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++bool ++si_iscoreup(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_iscoreup(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_iscoreup(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_iscoreup(sih); ++ else { ++ ASSERT(0); ++ return FALSE; ++ } ++} ++ ++uint ++si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val) ++{ ++ /* only for AI back plane chips */ ++ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return (ai_wrap_reg(sih, offset, mask, val)); ++ return 0; ++} ++ ++uint ++si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_corereg(sih, coreidx, regoff, mask, val); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_corereg(sih, coreidx, regoff, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_corereg(sih, coreidx, regoff, mask, val); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_core_disable(si_t *sih, uint32 bits) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_core_disable(sih, bits); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_core_disable(sih, bits); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_core_disable(sih, bits); ++} ++ ++void ++si_core_reset(si_t *sih, uint32 bits, uint32 resetbits) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_core_reset(sih, bits, resetbits); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_core_reset(sih, bits, resetbits); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_core_reset(sih, bits, resetbits); ++} ++ ++/* Run bist on current core. Caller needs to take care of core-specific bist hazards */ ++int ++si_corebist(si_t *sih) ++{ ++ uint32 cflags; ++ int result = 0; ++ ++ /* Read core control flags */ ++ cflags = si_core_cflags(sih, 0, 0); ++ ++ /* Set bist & fgc */ ++ si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC)); ++ ++ /* Wait for bist done */ ++ SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000); ++ ++ if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR) ++ result = BCME_ERROR; ++ ++ /* Reset core control flags */ ++ si_core_cflags(sih, 0xffff, cflags); ++ ++ return result; ++} ++ ++static uint32 ++BCMINITFN(factor6)(uint32 x) ++{ ++ switch (x) { ++ case CC_F6_2: return 2; ++ case CC_F6_3: return 3; ++ case CC_F6_4: return 4; ++ case CC_F6_5: return 5; ++ case CC_F6_6: return 6; ++ case CC_F6_7: return 7; ++ default: return 0; ++ } ++} ++ ++/* calculate the speed the SI would run at given a set of clockcontrol values */ ++uint32 ++BCMINITFN(si_clock_rate)(uint32 pll_type, uint32 n, uint32 m) ++{ ++ uint32 n1, n2, clock, m1, m2, m3, mc; ++ ++ n1 = n & CN_N1_MASK; ++ n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; ++ ++ if (pll_type == PLL_TYPE6) { ++ if (m & CC_T6_MMASK) ++ return CC_T6_M1; ++ else ++ return CC_T6_M0; ++ } else if ((pll_type == PLL_TYPE1) || ++ (pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE4) || ++ (pll_type == PLL_TYPE7)) { ++ n1 = factor6(n1); ++ n2 += CC_F5_BIAS; ++ } else if (pll_type == PLL_TYPE2) { ++ n1 += CC_T2_BIAS; ++ n2 += CC_T2_BIAS; ++ ASSERT((n1 >= 2) && (n1 <= 7)); ++ ASSERT((n2 >= 5) && (n2 <= 23)); ++ } else if (pll_type == PLL_TYPE5) { ++ return (100000000); ++ } else ++ ASSERT(0); ++ /* PLL types 3 and 7 use BASE2 (25Mhz) */ ++ if ((pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE7)) { ++ clock = CC_CLOCK_BASE2 * n1 * n2; ++ } else ++ clock = CC_CLOCK_BASE1 * n1 * n2; ++ ++ if (clock == 0) ++ return 0; ++ ++ m1 = m & CC_M1_MASK; ++ m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; ++ m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; ++ mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; ++ ++ if ((pll_type == PLL_TYPE1) || ++ (pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE4) || ++ (pll_type == PLL_TYPE7)) { ++ m1 = factor6(m1); ++ if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) ++ m2 += CC_F5_BIAS; ++ else ++ m2 = factor6(m2); ++ m3 = factor6(m3); ++ ++ switch (mc) { ++ case CC_MC_BYPASS: return (clock); ++ case CC_MC_M1: return (clock / m1); ++ case CC_MC_M1M2: return (clock / (m1 * m2)); ++ case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); ++ case CC_MC_M1M3: return (clock / (m1 * m3)); ++ default: return (0); ++ } ++ } else { ++ ASSERT(pll_type == PLL_TYPE2); ++ ++ m1 += CC_T2_BIAS; ++ m2 += CC_T2M2_BIAS; ++ m3 += CC_T2_BIAS; ++ ASSERT((m1 >= 2) && (m1 <= 7)); ++ ASSERT((m2 >= 3) && (m2 <= 10)); ++ ASSERT((m3 >= 2) && (m3 <= 7)); ++ ++ if ((mc & CC_T2MC_M1BYP) == 0) ++ clock /= m1; ++ if ((mc & CC_T2MC_M2BYP) == 0) ++ clock /= m2; ++ if ((mc & CC_T2MC_M3BYP) == 0) ++ clock /= m3; ++ ++ return (clock); ++ } ++} ++ ++uint32 ++BCMINITFN(si_clock)(si_t *sih) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint32 n, m; ++ uint idx; ++ uint32 pll_type, rate; ++ uint intr_val = 0; ++ ++ if (IS_IPROC_CHIP_ID(CHIPID(sih->chip))) { ++ if (sih->chippkg == BCM4709_PKG_ID) { ++ return NS_SI_CLOCK; ++ } else ++ return NS_SLOW_SI_CLOCK; ++ } ++ ++ sii = SI_INFO(sih); ++ INTR_OFF(sii, intr_val); ++ ++ idx = sii->curidx; ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ASSERT(cc != NULL); ++ ++ n = R_REG(sii->osh, &cc->clockcontrol_n); ++ pll_type = sih->cccaps & CC_CAP_PLL_MASK; ++ if (pll_type == PLL_TYPE6) ++ m = R_REG(sii->osh, &cc->clockcontrol_m3); ++ else if (pll_type == PLL_TYPE3) ++ m = R_REG(sii->osh, &cc->clockcontrol_m2); ++ else ++ m = R_REG(sii->osh, &cc->clockcontrol_sb); ++ ++ /* calculate rate */ ++ rate = si_clock_rate(pll_type, n, m); ++ ++ if (pll_type == PLL_TYPE3) ++ rate = rate / 2; ++ ++ /* switch back to previous core */ ++ si_setcoreidx(sih, idx); ++ ++ INTR_RESTORE(sii, intr_val); ++ ++ return rate; ++} ++ ++uint32 ++BCMINITFN(si_alp_clock)(si_t *sih) ++{ ++ if (IS_IPROC_CHIP_ID(CHIPID(sih->chip))) { ++ if (sih->chippkg == BCM4709_PKG_ID) ++ return NS_ALP_CLOCK; ++ else ++ return NS_SLOW_ALP_CLOCK; ++ } ++ ++ return NS_ALP_CLOCK; ++} ++ ++ ++#if defined(BCMDBG) ++/* print interesting sbconfig registers */ ++void ++si_dumpregs(si_t *sih, struct bcmstrbuf *b) ++{ ++ si_info_t *sii; ++ uint origidx, intr_val = 0; ++ ++ sii = SI_INFO(sih); ++ origidx = sii->curidx; ++ ++ INTR_OFF(sii, intr_val); ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_dumpregs(sih, b); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_dumpregs(sih, b); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_dumpregs(sih, b); ++ else ++ ASSERT(0); ++ ++ si_setcoreidx(sih, origidx); ++ INTR_RESTORE(sii, intr_val); ++} ++#endif ++ ++#ifdef BCMDBG ++void ++si_view(si_t *sih, bool verbose) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_view(sih, verbose); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_view(sih, verbose); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_view(sih, verbose); ++ else ++ ASSERT(0); ++} ++ ++void ++si_viewall(si_t *sih, bool verbose) ++{ ++ si_info_t *sii; ++ uint curidx, i; ++ uint intr_val = 0; ++ ++ sii = SI_INFO(sih); ++ curidx = sii->curidx; ++ ++ INTR_OFF(sii, intr_val); ++ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_viewall(sih, verbose); ++ else { ++ SI_ERROR(("si_viewall: num_cores %d\n", sii->numcores)); ++ for (i = 0; i < sii->numcores; i++) { ++ si_setcoreidx(sih, i); ++ si_view(sih, verbose); ++ } ++ } ++ si_setcoreidx(sih, curidx); ++ INTR_RESTORE(sii, intr_val); ++} ++#endif /* BCMDBG */ ++ ++/* return the slow clock source - LPO, XTAL, or PCI */ ++static uint ++si_slowclk_src(si_info_t *sii) ++{ ++ chipcregs_t *cc; ++ ++ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); ++ ++ if (sii->pub.ccrev < 6) { ++ return (SCC_SS_XTAL); ++ } else if (sii->pub.ccrev < 10) { ++ cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx); ++ return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); ++ } else /* Insta-clock */ ++ return (SCC_SS_XTAL); ++} ++ ++/* return the ILP (slowclock) min or max frequency */ ++static uint ++si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc) ++{ ++ uint32 slowclk; ++ uint div; ++ ++ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); ++ ++ /* shouldn't be here unless we've established the chip has dynamic clk control */ ++ ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL); ++ ++ slowclk = si_slowclk_src(sii); ++ if (sii->pub.ccrev < 6) { ++ if (slowclk == SCC_SS_PCI) ++ return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64)); ++ else ++ return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32)); ++ } else if (sii->pub.ccrev < 10) { ++ div = 4 * ++ (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); ++ if (slowclk == SCC_SS_LPO) ++ return (max_freq ? LPOMAXFREQ : LPOMINFREQ); ++ else if (slowclk == SCC_SS_XTAL) ++ return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div)); ++ else if (slowclk == SCC_SS_PCI) ++ return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div)); ++ else ++ ASSERT(0); ++ } else { ++ /* Chipc rev 10 is InstaClock */ ++ div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT; ++ div = 4 * (div + 1); ++ return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div)); ++ } ++ return (0); ++} ++ ++static void ++BCMINITFN(si_clkctl_setdelay)(si_info_t *sii, void *chipcregs) ++{ ++ chipcregs_t *cc = (chipcregs_t *)chipcregs; ++ uint slowmaxfreq, pll_delay, slowclk; ++ uint pll_on_delay, fref_sel_delay; ++ ++ pll_delay = PLL_DELAY; ++ ++ /* If the slow clock is not sourced by the xtal then add the xtal_on_delay ++ * since the xtal will also be powered down by dynamic clk control logic. ++ */ ++ ++ slowclk = si_slowclk_src(sii); ++ if (slowclk != SCC_SS_XTAL) ++ pll_delay += XTAL_ON_DELAY; ++ ++ /* Starting with 4318 it is ILP that is used for the delays */ ++ slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc); ++ ++ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; ++ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; ++ ++ W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay); ++ W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay); ++} ++ ++/* initialize power control delay registers */ ++void ++BCMINITFN(si_clkctl_init)(si_t *sih) ++{ ++ si_info_t *sii; ++ uint origidx = 0; ++ chipcregs_t *cc; ++ bool fast; ++ ++ if (!CCCTL_ENAB(sih)) ++ return; ++ ++ sii = SI_INFO(sih); ++ fast = SI_FAST(sii); ++ if (!fast) { ++ origidx = sii->curidx; ++ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) ++ return; ++ } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL) ++ return; ++ ASSERT(cc != NULL); ++ ++ /* set all Instaclk chip ILP to 1 MHz */ ++ if (sih->ccrev >= 10) ++ SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK, ++ (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); ++ ++ si_clkctl_setdelay(sii, (void *)(uintptr)cc); ++ ++ if (!fast) ++ si_setcoreidx(sih, origidx); ++} ++ ++/* turn primary xtal and/or pll off/on */ ++int ++si_clkctl_xtal(si_t *sih, uint what, bool on) ++{ ++ switch (BUSTYPE(sih->bustype)) { ++ ++ default: ++ return (-1); ++ } ++ ++} ++ ++/* ++ * clock control policy function throught chipcommon ++ * ++ * set dynamic clk control mode (forceslow, forcefast, dynamic) ++ * returns true if we are forcing fast clock ++ * this is a wrapper over the next internal function ++ * to allow flexible policy settings for outside caller ++ */ ++bool ++si_clkctl_cc(si_t *sih, uint mode) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ /* chipcommon cores prior to rev6 don't support dynamic clock control */ ++ if (sih->ccrev < 6) ++ return FALSE; ++ ++ if (PCI_FORCEHT(sii)) ++ return (mode == CLK_FAST); ++ ++ return _si_clkctl_cc(sii, mode); ++} ++ ++/* clk control mechanism through chipcommon, no policy checking */ ++static bool ++_si_clkctl_cc(si_info_t *sii, uint mode) ++{ ++ uint origidx = 0; ++ chipcregs_t *cc; ++ uint32 scc; ++ uint intr_val = 0; ++ bool fast = SI_FAST(sii); ++ ++ /* chipcommon cores prior to rev6 don't support dynamic clock control */ ++ if (sii->pub.ccrev < 6) ++ return (FALSE); ++ ++ /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */ ++ ASSERT(sii->pub.ccrev != 10); ++ ++ if (!fast) { ++ INTR_OFF(sii, intr_val); ++ origidx = sii->curidx; ++ ++ if ((BUSTYPE(sii->pub.bustype) == SI_BUS) && ++ si_setcore(&sii->pub, MIPS33_CORE_ID, 0) && ++ (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10)) ++ goto done; ++ ++ cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0); ++ } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL) ++ goto done; ++ ASSERT(cc != NULL); ++ ++ if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20)) ++ goto done; ++ ++ switch (mode) { ++ case CLK_FAST: /* FORCEHT, fast (pll) clock */ ++ if (sii->pub.ccrev < 10) { ++ /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */ ++ si_clkctl_xtal(&sii->pub, XTAL, ON); ++ SET_REG(sii->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP); ++ } else if (sii->pub.ccrev < 20) { ++ OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR); ++ } else { ++ OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT); ++ } ++ ++ /* wait for the PLL */ ++ if (PMUCTL_ENAB(&sii->pub)) { ++ uint32 htavail = CCS_HTAVAIL; ++ if (CHIPID(sii->pub.chip) == BCM4328_CHIP_ID) ++ htavail = CCS0_HTAVAIL; ++ SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail) == 0), ++ PMU_MAX_TRANSITION_DLY); ++ ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail); ++ } else { ++ OSL_DELAY(PLL_DELAY); ++ } ++ break; ++ ++ case CLK_DYNAMIC: /* enable dynamic clock control */ ++ if (sii->pub.ccrev < 10) { ++ scc = R_REG(sii->osh, &cc->slow_clk_ctl); ++ scc &= ~(SCC_FS | SCC_IP | SCC_XC); ++ if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) ++ scc |= SCC_XC; ++ W_REG(sii->osh, &cc->slow_clk_ctl, scc); ++ ++ /* for dynamic control, we have to release our xtal_pu "force on" */ ++ if (scc & SCC_XC) ++ si_clkctl_xtal(&sii->pub, XTAL, OFF); ++ } else if (sii->pub.ccrev < 20) { ++ /* Instaclock */ ++ AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR); ++ } else { ++ AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT); ++ } ++ break; ++ ++ default: ++ ASSERT(0); ++ } ++ ++done: ++ if (!fast) { ++ si_setcoreidx(&sii->pub, origidx); ++ INTR_RESTORE(sii, intr_val); ++ } ++ return (mode == CLK_FAST); ++} ++ ++/* Build device path. Support SI, PCI, and JTAG for now. */ ++int ++BCMNMIATTACHFN(si_devpath)(si_t *sih, char *path, int size) ++{ ++ int slen; ++ ++ ASSERT(path != NULL); ++ ASSERT(size >= SI_DEVPATH_BUFSZ); ++ ++ if (!path || size <= 0) ++ return -1; ++ ++ switch (BUSTYPE(sih->bustype)) { ++ case SI_BUS: ++ slen = snprintf(path, (size_t)size, "sb/%u/", si_coreidx(sih)); ++ break; ++ default: ++ slen = -1; ++ ASSERT(0); ++ break; ++ } ++ ++ if (slen < 0 || slen >= size) { ++ path[0] = '\0'; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++char * ++BCMATTACHFN(si_coded_devpathvar)(si_t *sih, char *varname, int var_len, const char *name) ++{ ++ char pathname[SI_DEVPATH_BUFSZ + 32]; ++ char devpath[SI_DEVPATH_BUFSZ + 32]; ++ char *p; ++ int idx; ++ int len; ++ ++ /* try to get compact devpath if it exist */ ++ if (si_devpath(sih, devpath, SI_DEVPATH_BUFSZ) == 0) { ++ len = strlen(devpath); ++ devpath[len - 1] = '\0'; ++ for (idx = 0; idx < SI_MAXCORES; idx++) { ++ snprintf(pathname, SI_DEVPATH_BUFSZ, "devpath%d", idx); ++ if ((p = getvar(NULL, pathname)) == NULL) ++ continue; ++ ++ if (strncmp(p, devpath, len) == 0) { ++ snprintf(varname, var_len, "%d:%s", idx, name); ++ return varname; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++/* Get a variable, but only if it has a devpath prefix */ ++int ++BCMATTACHFN(si_getdevpathintvar)(si_t *sih, const char *name) ++{ ++#if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS) ++ return (getintvar(NULL, name)); ++#else ++ char varname[SI_DEVPATH_BUFSZ + 32]; ++ int val; ++ ++ si_devpathvar(sih, varname, sizeof(varname), name); ++ ++ if ((val = getintvar(NULL, varname)) != 0) ++ return val; ++ ++ /* try to get compact devpath if it exist */ ++ if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL) ++ return 0; ++ ++ return (getintvar(NULL, varname)); ++#endif /* BCMBUSTYPE && BCMBUSTYPE == SI_BUS */ ++} ++ ++/* Concatenate the dev path with a varname into the given 'var' buffer ++ * and return the 'var' pointer. ++ * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned. ++ * On overflow, the first char will be set to '\0'. ++ */ ++static char * ++BCMATTACHFN(si_devpathvar)(si_t *sih, char *var, int len, const char *name) ++{ ++ uint path_len; ++ ++ if (!var || len <= 0) ++ return var; ++ ++ if (si_devpath(sih, var, len) == 0) { ++ path_len = strlen(var); ++ ++ if (strlen(name) + 1 > (uint)(len - path_len)) ++ var[0] = '\0'; ++ else ++ strncpy(var + path_len, name, len - path_len - 1); ++ } ++ ++ return var; ++} ++ ++ ++#if defined(BCMDBG) ++#endif ++ ++ ++/* mask&set gpio output enable bits */ ++uint32 ++si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority) ++{ ++ uint regoff; ++ ++ regoff = 0; ++ ++ /* gpios could be shared on router platforms ++ * ignore reservation if it's high priority (e.g., test apps) ++ */ ++ if ((priority != GPIO_HI_PRIORITY) && ++ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { ++ mask = priority ? (si_gpioreservation & mask) : ++ ((si_gpioreservation | mask) & ~(si_gpioreservation)); ++ val &= mask; ++ } ++ ++ regoff = OFFSETOF(chipcregs_t, gpioouten); ++ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); ++} ++ ++/* mask&set gpio output bits */ ++uint32 ++si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority) ++{ ++ uint regoff; ++ ++ regoff = 0; ++ ++ /* gpios could be shared on router platforms ++ * ignore reservation if it's high priority (e.g., test apps) ++ */ ++ if ((priority != GPIO_HI_PRIORITY) && ++ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { ++ mask = priority ? (si_gpioreservation & mask) : ++ ((si_gpioreservation | mask) & ~(si_gpioreservation)); ++ val &= mask; ++ } ++ ++ regoff = OFFSETOF(chipcregs_t, gpioout); ++ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/siutils_priv.h b/drivers/bcmdrivers/gmac/src/shared/siutils_priv.h +new file mode 100755 +index 0000000..56650d1 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/siutils_priv.h +@@ -0,0 +1,259 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Include file private to the SOC Interconnect support files. ++ * ++ * $Id: siutils_priv.h 302333 2011-12-11 01:47:49Z $ ++ */ ++ ++#ifndef _siutils_priv_h_ ++#define _siutils_priv_h_ ++ ++#ifdef BCMDBG_ERR ++#define SI_ERROR(args) printf args ++#else ++#define SI_ERROR(args) ++#endif /* BCMDBG_ERR */ ++ ++#ifdef BCMDBG ++#define SI_MSG(args) printf args ++#else ++#define SI_MSG(args) ++#endif /* BCMDBG */ ++ ++#ifdef BCMDBG_SI ++#define SI_VMSG(args) printf args ++#else ++#define SI_VMSG(args) ++#endif ++ ++#define IS_SIM(chippkg) ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) ++ ++ ++typedef uint32 (*si_intrsoff_t)(void *intr_arg); ++typedef void (*si_intrsrestore_t)(void *intr_arg, uint32 arg); ++typedef bool (*si_intrsenabled_t)(void *intr_arg); ++ ++typedef struct gpioh_item { ++ void *arg; ++ bool level; ++ gpio_handler_t handler; ++ uint32 event; ++ struct gpioh_item *next; ++} gpioh_item_t; ++ ++/* misc si info needed by some of the routines */ ++typedef struct si_info { ++ struct si_pub pub; /* back plane public state (must be first field) */ ++ ++ void *osh; /* osl os handle */ ++ void *sdh; /* bcmsdh handle */ ++ ++ uint dev_coreid; /* the core provides driver functions */ ++ void *intr_arg; /* interrupt callback function arg */ ++ si_intrsoff_t intrsoff_fn; /* turns chip interrupts off */ ++ si_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */ ++ si_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */ ++ ++ void *pch; /* PCI/E core handle */ ++ ++ gpioh_item_t *gpioh_head; /* GPIO event handlers list */ ++ ++ bool memseg; /* flag to toggle MEM_SEG register */ ++ ++ char *vars; ++ uint varsz; ++ ++ void *curmap; /* current regs va */ ++ void *regs[SI_MAXCORES]; /* other regs va */ ++ ++ uint curidx; /* current core index */ ++ uint numcores; /* # discovered cores */ ++ uint coreid[SI_MAXCORES]; /* id of each core */ ++ uint32 coresba[SI_MAXCORES]; /* backplane address of each core */ ++ void *regs2[SI_MAXCORES]; /* va of each core second register set (usbh20) */ ++ uint32 coresba2[SI_MAXCORES]; /* address of each core second register set (usbh20) */ ++ uint32 coresba_size[SI_MAXCORES]; /* backplane address space size */ ++ uint32 coresba2_size[SI_MAXCORES]; /* second address space size */ ++ ++ void *curwrap; /* current wrapper va */ ++ void *wrappers[SI_MAXCORES]; /* other cores wrapper va */ ++ uint32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */ ++ ++ uint32 cia[SI_MAXCORES]; /* erom cia entry for each core */ ++ uint32 cib[SI_MAXCORES]; /* erom cia entry for each core */ ++ uint32 oob_router; /* oob router registers for axi */ ++} si_info_t; ++ ++#define SI_INFO(sih) (si_info_t *)(uintptr)sih ++ ++#define GOODCOREADDR(x, b) (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ ++ ISALIGNED((x), SI_CORE_SIZE)) ++#define GOODREGS(regs) ((regs) != NULL && ISALIGNED((uintptr)(regs), SI_CORE_SIZE)) ++#define BADCOREADDR 0 ++#define GOODIDX(idx) (((uint)idx) < SI_MAXCORES) ++#define NOREV -1 /* Invalid rev */ ++ ++#define PCI(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ ++ ((si)->pub.buscoretype == PCI_CORE_ID)) ++ ++#define PCIE_GEN1(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ ++ ((si)->pub.buscoretype == PCIE_CORE_ID)) ++ ++#define PCIE_GEN2(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ ++ ((si)->pub.buscoretype == PCIE2_CORE_ID)) ++ ++#define PCIE(si) (PCIE_GEN1(si) || PCIE_GEN2(si)) ++ ++#define PCMCIA(si) ((BUSTYPE((si)->pub.bustype) == PCMCIA_BUS) && ((si)->memseg == TRUE)) ++ ++/* Newer chips can access PCI/PCIE and CC core without requiring to change ++ * PCI BAR0 WIN ++ */ ++#define SI_FAST(si) (PCIE(si) || (PCI(si) && ((si)->pub.buscorerev >= 13))) ++ ++#define PCIEREGS(si) (((char *)((si)->curmap) + PCI_16KB0_PCIREGS_OFFSET)) ++#define CCREGS_FAST(si) (((char *)((si)->curmap) + PCI_16KB0_CCREGS_OFFSET)) ++ ++/* ++ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/ ++ * after core switching to avoid invalid register accesss inside ISR. ++ */ ++#define INTR_OFF(si, intr_val) \ ++ if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ ++ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); } ++#define INTR_RESTORE(si, intr_val) \ ++ if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ ++ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); } ++ ++/* dynamic clock control defines */ ++#define LPOMINFREQ 25000 /* low power oscillator min */ ++#define LPOMAXFREQ 43000 /* low power oscillator max */ ++#define XTALMINFREQ 19800000 /* 20 MHz - 1% */ ++#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */ ++#define PCIMINFREQ 25000000 /* 25 MHz */ ++#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */ ++ ++#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ ++#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ ++ ++#define PCI_FORCEHT(si) \ ++ (((PCIE_GEN1(si)) && (si->pub.chip == BCM4311_CHIP_ID) && ((si->pub.chiprev <= 1))) || \ ++ ((PCI(si) || PCIE_GEN1(si)) && (si->pub.chip == BCM4321_CHIP_ID)) || \ ++ (PCIE_GEN1(si) && (si->pub.chip == BCM4716_CHIP_ID)) || \ ++ (PCIE_GEN1(si) && (si->pub.chip == BCM4748_CHIP_ID))) ++ ++/* GPIO Based LED powersave defines */ ++#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ ++#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ ++ ++#ifndef DEFAULT_GPIOTIMERVAL ++#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) ++#endif ++ ++#define sb_scan(a, b, c) do {} while (0) ++#define sb_coreid(a) (0) ++#define sb_intflag(a) (0) ++#define sb_flag(a) (0) ++#define sb_setint(a, b) do {} while (0) ++#define sb_corevendor(a) (0) ++#define sb_corerev(a) (0) ++#define sb_corereg(a, b, c, d, e) (0) ++#define sb_iscoreup(a) (false) ++#define sb_setcoreidx(a, b) (0) ++#define sb_core_cflags(a, b, c) (0) ++#define sb_core_cflags_wo(a, b, c) do {} while (0) ++#define sb_core_sflags(a, b, c) (0) ++#define sb_commit(a) do {} while (0) ++#define sb_base(a) (0) ++#define sb_size(a) (0) ++#define sb_core_reset(a, b, c) do {} while (0) ++#define sb_core_disable(a, b) do {} while (0) ++#define sb_addrspace(a, b) (0) ++#define sb_addrspacesize(a, b) (0) ++#define sb_numaddrspaces(a) (0) ++#define sb_set_initiator_to(a, b, c) (0) ++#define sb_taclear(a, b) (false) ++#define sb_view(a, b) do {} while (0) ++#define sb_viewall(a, b) do {} while (0) ++#define sb_dump(a, b) do {} while (0) ++#define sb_dumpregs(a, b) do {} while (0) ++ ++/* Wake-on-wireless-LAN (WOWL) */ ++extern bool sb_pci_pmecap(si_t *sih); ++struct osl_info; ++extern bool sb_pci_fastpmecap(struct osl_info *osh); ++extern bool sb_pci_pmeclr(si_t *sih); ++extern void sb_pci_pmeen(si_t *sih); ++extern uint sb_pcie_readreg(void *sih, uint addrtype, uint offset); ++ ++/* AMBA Interconnect exported externs */ ++extern si_t *ai_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, ++ void *sdh, char **vars, uint *varsz); ++extern si_t *ai_kattach(osl_t *osh); ++extern void ai_scan(si_t *sih, void *regs, uint devid); ++ ++extern uint ai_flag(si_t *sih); ++extern void ai_setint(si_t *sih, int siflag); ++extern uint ai_coreidx(si_t *sih); ++extern uint ai_corevendor(si_t *sih); ++extern uint ai_corerev(si_t *sih); ++extern bool ai_iscoreup(si_t *sih); ++extern void *ai_setcoreidx(si_t *sih, uint coreidx); ++extern uint32 ai_core_cflags(si_t *sih, uint32 mask, uint32 val); ++extern void ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); ++extern uint32 ai_core_sflags(si_t *sih, uint32 mask, uint32 val); ++extern uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); ++extern void ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits); ++extern void ai_core_disable(si_t *sih, uint32 bits); ++extern int ai_numaddrspaces(si_t *sih); ++extern uint32 ai_addrspace(si_t *sih, uint asidx); ++extern uint32 ai_addrspacesize(si_t *sih, uint asidx); ++extern void ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); ++extern uint ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val); ++ ++#ifdef BCMDBG ++extern void ai_view(si_t *sih, bool verbose); ++extern void ai_viewall(si_t *sih, bool verbose); ++#endif ++#if defined(BCMDBG) ++extern void ai_dumpregs(si_t *sih, struct bcmstrbuf *b); ++#endif ++ ++#ifdef SI_ENUM_BASE_VARIABLE ++extern void si_enum_base_init(si_t *sih, uint bustype); ++#endif /* SI_ENUM_BASE_VARIABLE */ ++ ++#define ub_scan(a, b, c) do {} while (0) ++#define ub_flag(a) (0) ++#define ub_setint(a, b) do {} while (0) ++#define ub_coreidx(a) (0) ++#define ub_corevendor(a) (0) ++#define ub_corerev(a) (0) ++#define ub_iscoreup(a) (0) ++#define ub_setcoreidx(a, b) (0) ++#define ub_core_cflags(a, b, c) (0) ++#define ub_core_cflags_wo(a, b, c) do {} while (0) ++#define ub_core_sflags(a, b, c) (0) ++#define ub_corereg(a, b, c, d, e) (0) ++#define ub_core_reset(a, b, c) do {} while (0) ++#define ub_core_disable(a, b) do {} while (0) ++#define ub_numaddrspaces(a) (0) ++#define ub_addrspace(a, b) (0) ++#define ub_addrspacesize(a, b) (0) ++#define ub_view(a, b) do {} while (0) ++#define ub_dumpregs(a, b) do {} while (0) ++ ++#endif /* _siutils_priv_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/wl_config b/drivers/bcmdrivers/gmac/src/shared/wl_config +new file mode 100755 +index 0000000..aded587 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/wl_config +@@ -0,0 +1,26 @@ ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# wl driver config shared hnd files ++# ++ ++HNDDMA=1 ++BCMUTILS=1 ++SIUTILS=1 ++#BCMSROM=1 ++#BCMOTP=1 ++BCMDMA32=1 ++ ++# OSL shared ++OSLLX=1 +diff --git a/drivers/bcmdrivers/gpio/.gitignore b/drivers/bcmdrivers/gpio/.gitignore +new file mode 100644 +index 0000000..9463d48 +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/.gitignore +@@ -0,0 +1,12 @@ ++/.built-in.o.cmd ++/.gpio_cfg.o.cmd ++/.gpio.o.cmd ++/.gpiolib.o.cmd ++/.iproc_gpio.o.cmd ++/built-in.o ++/gpio_cfg.o ++/gpio.o ++/gpiolib.o ++/iproc_gpio.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/gpio/Kconfig b/drivers/bcmdrivers/gpio/Kconfig +new file mode 100644 +index 0000000..0bcd76f +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/Kconfig +@@ -0,0 +1,11 @@ ++config IPROC_GPIO ++ tristate "GPIO support" ++ select GENERIC_GPIO ++ select ARCH_REQUIRE_GPIOLIB ++ select GPIOLIB ++ depends on ARCH_IPROC ++ default y ++ help ++ Add GPIO support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/gpio/Makefile b/drivers/bcmdrivers/gpio/Makefile +new file mode 100644 +index 0000000..edbecf6 +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_GPIO) += iproc_gpio.o ++iproc_gpio-objs := gpio.o gpio_cfg.o gpiolib.o +diff --git a/drivers/bcmdrivers/gpio/gpio.c b/drivers/bcmdrivers/gpio/gpio.c +new file mode 100644 +index 0000000..cd41cf6 +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpio.c +@@ -0,0 +1,744 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++ ++#include "gpio.h" ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) ++#define irq_get_chip_data get_irq_chip_data ++#define irq_set_chip_data set_irq_chip_data ++#define irq_set_chip set_irq_chip ++#define irq_set_handler set_irq_handler ++#define status_use_accessors status ++#endif ++ ++ ++static struct iproc_gpio_chip *iproc_gpio_dev[MAX_NS_GPIO] = {}; ++static int dev = 0; ++ ++static unsigned int _iproc_gpio_readl(struct iproc_gpio_chip *chip, int reg) ++{ ++ return readl(chip->ioaddr + reg); ++} ++ ++static void _iproc_gpio_writel(struct iproc_gpio_chip *chip, unsigned int val, int reg) ++{ ++ writel(val, chip->ioaddr + reg); ++} ++ ++ ++/* ++@ pin : the actual pin number of the gpiochip ++*/ ++static int iproc_gpio_to_irq(struct iproc_gpio_chip *chip, unsigned int pin) { ++ return (chip->irq_base + pin - chip->pin_offset); ++} ++ ++/* ++returns the actual pin number of the gpiochip ++*/ ++static int iproc_irq_to_gpio(struct iproc_gpio_chip *chip, unsigned int irq) { ++ return (irq - chip->irq_base + chip->pin_offset); ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++static void iproc_gpio_irq_ack(unsigned int irq) ++{ ++#else ++static void iproc_gpio_irq_ack(struct irq_data *d) ++{ ++ unsigned int irq = d->irq; ++#endif ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->ack) ++ irqcfg->ack(irq); ++ ++ } ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++static void iproc_gpio_irq_unmask(unsigned int irq) ++{ ++#else ++static void iproc_gpio_irq_unmask(struct irq_data *d) ++{ ++ unsigned int irq = d->irq; ++#endif ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->unmask) ++ irqcfg->unmask(irq); ++ } ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++static void iproc_gpio_irq_mask(unsigned int irq) ++{ ++#else ++static void iproc_gpio_irq_mask(struct irq_data *d) ++{ ++ unsigned int irq = d->irq; ++#endif ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->mask) ++ irqcfg->mask(irq); ++ } ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++static int iproc_gpio_irq_set_type(unsigned int irq, unsigned int type) ++{ ++#else ++static int iproc_gpio_irq_set_type(struct irq_data *d, unsigned int type) ++{ ++ unsigned int irq = d->irq; ++#endif ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->set_type) ++ return irqcfg->set_type(irq, type); ++ } ++ return -EINVAL; ++} ++ ++#if defined(IPROC_GPIO_CCA) ++static irqreturn_t ++iproc_gpio_irq_handler_cca(int irq, void *dev) ++ ++{ ++ unsigned int val, irq_type; ++ unsigned int int_mask, int_pol, in; ++ unsigned int event_mask, event, event_pol, tmp = 0; ++ int iter, g_irq, max_pin; ++ struct iproc_gpio_chip *ourchip = dev; ++ ++ ++ val = readl(ourchip->intr_ioaddr + IPROC_CCA_INT_STS); ++ ++ if (val & IPROC_CCA_INT_F_GPIOINT) { ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ int_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL); ++ in = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_DIN); ++ event_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT_MASK); ++ event = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT); ++ event_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EDGE); ++ ++ max_pin = ourchip->pin_offset + ourchip->chip.ngpio; ++ for (iter = ourchip->pin_offset; iter < max_pin; iter ++) { ++ g_irq = iproc_gpio_to_irq(ourchip, iter); ++ irq_type = irq_desc[g_irq].status_use_accessors & IRQ_TYPE_SENSE_MASK; ++ switch(irq_type) { ++ case IRQ_TYPE_EDGE_RISING: ++ tmp = event_mask; ++ tmp &= event; ++ tmp &= ~event_pol; ++ if (tmp & (1 << iter)) { ++ generic_handle_irq(g_irq); ++ } ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ tmp = event_mask; ++ tmp &= event; ++ tmp &= event_pol; ++ if (tmp & (1 << iter)) { ++ generic_handle_irq(g_irq); ++ } ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ tmp = in ^ int_pol; ++ tmp &= int_mask; ++ tmp &= int_pol; ++ if (tmp & (1 << iter)) { ++ generic_handle_irq(g_irq); ++ } ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ tmp = in ^ int_pol; ++ tmp &= int_mask; ++ tmp &= ~int_pol; ++ if (tmp & (1 << iter)) { ++ generic_handle_irq(g_irq); ++ } ++ break; ++ default: ++ break; ++ } ++ } ++ }else { ++ return IRQ_NONE; ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void iproc_gpio_irq_ack_cca(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if (ourchip->id == IPROC_GPIO_CCA_ID) { ++ unsigned int event_status, irq_type; ++ ++ event_status = 0; ++ irq_type = irq_desc[irq].status_use_accessors & IRQ_TYPE_SENSE_MASK; ++ if (irq_type & IRQ_TYPE_EDGE_BOTH) ++ { ++ event_status |= (1 << pin); ++ _iproc_gpio_writel(ourchip, event_status, ++ IPROC_GPIO_CCA_INT_EVENT); ++ } ++ ++ } ++} ++ ++static void iproc_gpio_irq_unmask_cca(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ unsigned int int_mask, irq_type; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ irq_type = irq_desc[irq].status_use_accessors & IRQ_TYPE_SENSE_MASK; ++ ++ if (ourchip->id == IPROC_GPIO_CCA_ID) { ++ unsigned int event_mask; ++ ++ event_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT_MASK); ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ ++ if (irq_type & IRQ_TYPE_EDGE_BOTH) { ++ event_mask |= 1 << pin; ++ _iproc_gpio_writel(ourchip, event_mask, ++ IPROC_GPIO_CCA_INT_EVENT_MASK); ++ } else { ++ int_mask |= 1 << pin; ++ _iproc_gpio_writel(ourchip, int_mask, ++ IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ } ++ } ++ ++} ++ ++static void iproc_gpio_irq_mask_cca(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ unsigned int irq_type, int_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ irq_type = irq_desc[irq].status_use_accessors & IRQ_TYPE_SENSE_MASK; ++ ++ if (ourchip->id == IPROC_GPIO_CCA_ID) { ++ unsigned int event_mask; ++ ++ event_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT_MASK); ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ ++ if (irq_type & IRQ_TYPE_EDGE_BOTH) { ++ event_mask &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, event_mask, ++ IPROC_GPIO_CCA_INT_EVENT_MASK); ++ } else { ++ int_mask &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_mask, ++ IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ } ++ } ++} ++ ++static int iproc_gpio_irq_set_type_cca(unsigned int irq, unsigned int type) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if (ourchip->id == IPROC_GPIO_CCA_ID) { ++ unsigned int event_pol, int_pol; ++ ++ switch (type & IRQ_TYPE_SENSE_MASK) { ++ case IRQ_TYPE_EDGE_RISING: ++ event_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EDGE); ++ event_pol &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, event_pol, IPROC_GPIO_CCA_INT_EDGE); ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ event_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EDGE); ++ event_pol |= (1 << pin); ++ _iproc_gpio_writel(ourchip, event_pol, IPROC_GPIO_CCA_INT_EDGE); ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ int_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL); ++ int_pol &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_pol, IPROC_GPIO_CCA_INT_LEVEL); ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ int_pol = _iproc_gpio_readl(ourchip,IPROC_GPIO_CCA_INT_LEVEL); ++ int_pol |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_pol, IPROC_GPIO_CCA_INT_LEVEL); ++ break; ++ default: ++ printk(KERN_ERR "unsupport irq type !\n"); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++struct iproc_gpio_irqcfg cca_gpio_irqcfg = { ++ .flags = IRQF_NO_SUSPEND|IRQF_SHARED, ++ .handler = iproc_gpio_irq_handler_cca, ++ .ack = iproc_gpio_irq_ack_cca, ++ .mask = iproc_gpio_irq_mask_cca, ++ .unmask = iproc_gpio_irq_unmask_cca, ++ .set_type = iproc_gpio_irq_set_type_cca, ++}; ++#endif /* IPROC_GPIO_CCA */ ++ ++#if defined(IPROC_GPIO_CCB) || defined(IPROC_GPIO_CCG) ++static irqreturn_t ++iproc_gpio_irq_handler_ccb(int irq, void *dev) ++{ ++ struct iproc_gpio_chip *ourchip = dev; ++ int iter, max_pin; ++ unsigned int val; ++ ++ val = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_MSTAT); ++ if(!val){ ++ return IRQ_NONE; ++ } ++ ++ max_pin = ourchip->pin_offset + ourchip->chip.ngpio; ++ for (iter = ourchip->pin_offset; iter < max_pin; iter ++) { ++ if (val & (1 << iter)) { ++ generic_handle_irq(iproc_gpio_to_irq(ourchip, iter)); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void iproc_gpio_irq_ack_ccb(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if ((ourchip->id == IPROC_GPIO_CCB_ID) || ++ (ourchip->id == IPROC_GPIO_CCG_ID)) { ++ unsigned int int_clear = 0; ++ ++ int_clear |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_clear, IPROC_GPIO_CCB_INT_CLR); ++ ++ } ++} ++ ++static void iproc_gpio_irq_unmask_ccb(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ unsigned int int_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if ((ourchip->id == IPROC_GPIO_CCB_ID) || ++ (ourchip->id == IPROC_GPIO_CCG_ID)) { ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_MASK); ++ int_mask |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_mask, IPROC_GPIO_CCB_INT_MASK); ++ } ++ ++} ++ ++static void iproc_gpio_irq_mask_ccb(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ unsigned int int_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if ((ourchip->id == IPROC_GPIO_CCB_ID) || ++ (ourchip->id == IPROC_GPIO_CCG_ID)) { ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_MASK); ++ int_mask &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_mask,IPROC_GPIO_CCB_INT_MASK); ++ } ++} ++ ++static int iproc_gpio_irq_set_type_ccb(unsigned int irq, unsigned int type) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if ((ourchip->id == IPROC_GPIO_CCB_ID) || ++ (ourchip->id == IPROC_GPIO_CCG_ID)) { ++ unsigned int int_type, int_de, int_edge; ++ int_type = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_TYPE); ++ int_edge = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_EDGE); ++ switch (type) { ++ case IRQ_TYPE_EDGE_BOTH: ++ int_type &= ~(1 << pin); ++ int_de = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_DE); ++ int_de |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_de, IPROC_GPIO_CCB_INT_DE); ++ break; ++ case IRQ_TYPE_EDGE_RISING: ++ int_type &= ~(1 << pin); ++ int_edge |= (1 << pin); ++ ++ int_de = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_DE); ++ int_de &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_de, IPROC_GPIO_CCB_INT_DE); ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ int_type &= ~(1 << pin); ++ int_edge &= ~(1 << pin); ++ ++ int_de = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_DE); ++ int_de &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_de, IPROC_GPIO_CCB_INT_DE); ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ int_type |= (1 << pin); ++ int_edge |= (1 << pin); ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ int_type |= (1 << pin); ++ int_edge &= ~(1 << pin); ++ break; ++ default: ++ printk(KERN_ERR "unsupport irq type !\n"); ++ return -EINVAL; ++ } ++ _iproc_gpio_writel(ourchip, int_type, IPROC_GPIO_CCB_INT_TYPE); ++ _iproc_gpio_writel(ourchip, int_edge, IPROC_GPIO_CCB_INT_EDGE); ++ } ++ ++ return 0; ++} ++ ++struct iproc_gpio_irqcfg ccb_gpio_irqcfg = { ++ .flags = IRQF_NO_SUSPEND, ++ .handler = iproc_gpio_irq_handler_ccb, ++ .ack = iproc_gpio_irq_ack_ccb, ++ .mask = iproc_gpio_irq_mask_ccb, ++ .unmask = iproc_gpio_irq_unmask_ccb, ++ .set_type = iproc_gpio_irq_set_type_ccb, ++}; ++#endif /* IPROC_GPIO_CCB || IPROC_GPIO_CCG*/ ++ ++ ++static struct irq_chip iproc_gpio_irq_chip = { ++ .name = "IPROC-GPIO", ++#if 0 ++//#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++ .ack = (void *) iproc_gpio_irq_ack, ++ .mask = (void *) iproc_gpio_irq_mask, ++ .unmask = (void *) iproc_gpio_irq_unmask, ++ .set_type = (void *) iproc_gpio_irq_set_type, ++//#else ++#endif ++ .irq_ack = (void *) iproc_gpio_irq_ack, ++ .irq_mask = (void *) iproc_gpio_irq_mask, ++ .irq_unmask = (void *) iproc_gpio_irq_unmask, ++ .irq_set_type = (void *) iproc_gpio_irq_set_type, ++//#endif ++}; ++ ++struct iproc_gpio_chip *iproc_gpios[IPROC_GPIO_END]; ++ ++static __init void iproc_gpiolib_track(struct iproc_gpio_chip *chip) ++{ ++ unsigned int gpn; ++ int i; ++ ++ gpn = chip->chip.base; ++ for (i = 0; i < chip->chip.ngpio; i++, gpn++) { ++ BUG_ON(gpn >= ARRAY_SIZE(iproc_gpios)); ++ iproc_gpios[gpn] = chip; ++ } ++} ++ ++static int iproc_gpiolib_input(struct gpio_chip *chip, unsigned gpio) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ unsigned int val; ++ unsigned int pin_offset = gpio + ourchip->pin_offset; ++ unsigned int nBitMask = 1 << pin_offset; ++ ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN); ++ val &= ~nBitMask; ++ _iproc_gpio_writel(ourchip, val, REGOFFSET_GPIO_EN); ++ ++ iproc_gpio_unlock(ourchip, flags); ++ return 0; ++} ++ ++static int iproc_gpiolib_output(struct gpio_chip *chip, ++ unsigned gpio, int value) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ unsigned long val; ++ unsigned int pin_offset = gpio + ourchip->pin_offset; ++ unsigned int nBitMask = 1 << pin_offset; ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN); ++ val |= nBitMask; ++ _iproc_gpio_writel(ourchip, val, REGOFFSET_GPIO_EN); ++ ++ iproc_gpio_unlock(ourchip, flags); ++ return 0; ++} ++ ++static void iproc_gpiolib_set(struct gpio_chip *chip, ++ unsigned gpio, int value) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ unsigned long val; ++ unsigned int pin_offset = gpio + ourchip->pin_offset; ++ unsigned int nBitMask = 1 << pin_offset; ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ ++ /* determine the GPIO pin direction ++ */ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN); ++ val &= nBitMask; ++ ++ /* this function only applies to output pin ++ */ ++ if (!val) ++ return; ++ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DOUT); ++ ++ if ( value == 0 ){ ++ /* Set the pin to zero */ ++ val &= ~nBitMask; ++ }else{ ++ /* Set the pin to 1 */ ++ val |= nBitMask; ++ } ++ _iproc_gpio_writel(ourchip, val, REGOFFSET_GPIO_DOUT); ++ ++ iproc_gpio_unlock(ourchip, flags); ++ ++} ++ ++ ++static int iproc_gpiolib_get(struct gpio_chip *chip, unsigned gpio) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ unsigned int val, offset; ++ unsigned int pin_offset = gpio + ourchip->pin_offset; ++ unsigned int nBitMask = 1 << pin_offset; ++ ++ iproc_gpio_lock(ourchip, flags); ++ /* determine the GPIO pin direction ++ */ ++ offset = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN); ++ offset &= nBitMask; ++ ++ if (offset){ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DOUT); ++ } else { ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DIN); ++ } ++ val >>= pin_offset; ++ val &= 1; ++ iproc_gpio_unlock(ourchip, flags); ++ ++ return val; ++} ++ ++/* ++@offset : the gpio pin index number from gpiolib view (minus gpio base only) ++*/ ++static int iproc_gpiolib_to_irq(struct gpio_chip *chip, ++ unsigned offset) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ return iproc_gpio_to_irq(ourchip, offset + ourchip->pin_offset); ++} ++void __init iproc_gpiolib_add(struct iproc_gpio_chip *chip) ++{ ++ struct resource *res; ++ struct gpio_chip *gc = &chip->chip; ++ int ret, i; ++ ++ BUG_ON(!gc->label); ++ BUG_ON(!gc->ngpio); ++ ++ spin_lock_init(&chip->lock); ++ ++ if (!gc->direction_input) ++ gc->direction_input = iproc_gpiolib_input; ++ if (!gc->direction_output) ++ gc->direction_output = iproc_gpiolib_output; ++ if (!gc->set) ++ gc->set = iproc_gpiolib_set; ++ if (!gc->get) ++ gc->get = iproc_gpiolib_get; ++ if (!gc->to_irq) ++ gc->to_irq = iproc_gpiolib_to_irq; ++ ++ /* gpiochip_add() prints own failure message on error. */ ++ ret = gpiochip_add(gc); ++ if (ret >= 0) ++ iproc_gpiolib_track(chip); ++ ++ printk(KERN_INFO "iproc gpiochip add %s\n", gc->label); ++ /* io remap */ ++ res = chip->resource; ++ ++ chip->ioaddr = ioremap_nocache(res->start, (res->end - res->start) + 1); ++ printk(KERN_INFO "%s:ioaddr %p \n", gc->label, chip->ioaddr); ++ chip->intr_ioaddr = NULL; ++ chip->dmu_ioaddr = NULL; ++ if(res->child){ ++ for (i=0; i< 2; i++){ ++ if (!strcmp("intr", res->child[i].name)){ ++ chip->intr_ioaddr = ++ ioremap_nocache(res->child[i].start, ++ (res->child[i].end - res->child[i].start) + 1); ++ } ++ if (!strcmp("dmu", res->child[i].name)){ ++ chip->dmu_ioaddr = ++ ioremap_nocache(res->child[i].start, ++ (res->child[i].end - res->child[i].start) + 1); ++ } ++ } ++ printk(KERN_INFO "%s:intr_ioaddr %p dmu_ioaddr %p\n", ++ gc->label, chip->intr_ioaddr,chip->dmu_ioaddr); ++ } ++ ++ ++ if (chip->irq_base) { ++ for (i = chip->irq_base; i < (chip->irq_base + gc->ngpio); i++) { ++ irq_set_chip(i, &iproc_gpio_irq_chip); ++ irq_set_chip_data(i,chip); ++ irq_set_handler(i, handle_level_irq); ++ set_irq_flags(i, IRQF_VALID); ++ ++ } ++#if defined(IPROC_GPIO_CCA) ++ if (chip->id == IPROC_GPIO_CCA_ID ){ ++ unsigned int val; ++ /* enable the GPIO in CCA interrupt mask */ ++ val = readl(chip->intr_ioaddr + IPROC_CCA_INT_MASK); ++ val |= IPROC_CCA_INT_F_GPIOINT; ++ writel(val, chip->intr_ioaddr + IPROC_CCA_INT_MASK); ++ } ++#endif ++ if (chip->irqcfg) { ++ struct iproc_gpio_irqcfg *irqcfg = chip->irqcfg; ++ if (irqcfg->handler) { ++ ret = request_irq(chip->irq, irqcfg->handler, irqcfg->flags, ++ gc->label, chip); ++ if (ret) ++ printk(KERN_ERR "Unable to request IRQ%d: %d\n", ++ chip->irq, ret); ++ } ++ else ++ printk(KERN_ERR "%s is added without isr!\n", chip->chip.label); ++ } ++ } ++ iproc_gpio_dev[dev] = chip; ++ dev++; ++} ++ ++static int __init gpio_init(void) ++{ ++ iproc_gpiolib_init(); ++ ++ return 0; ++} ++static void __exit gpio_exit(void) ++{ ++ int i=0; ++ ++ for (i = 0 ; i < MAX_NS_GPIO; i++) { ++ if(iproc_gpio_dev[i]){ ++ if(iproc_gpio_dev[i]->ioaddr){ ++ iounmap(iproc_gpio_dev[i]->ioaddr); ++ } ++ if(iproc_gpio_dev[i]->intr_ioaddr){ ++#if defined(IPROC_GPIO_CCA) ++ if (iproc_gpio_dev[i]->id == IPROC_GPIO_CCA_ID ){ ++ unsigned int val; ++ val = readl(iproc_gpio_dev[i]->intr_ioaddr + IPROC_CCA_INT_MASK); ++ val &= ~(IPROC_CCA_INT_F_GPIOINT); ++ writel(val, iproc_gpio_dev[i]->intr_ioaddr + IPROC_CCA_INT_MASK); ++ } ++#endif ++ iounmap(iproc_gpio_dev[i]->intr_ioaddr); ++ } ++ if(iproc_gpio_dev[i]->dmu_ioaddr){ ++ iounmap(iproc_gpio_dev[i]->dmu_ioaddr); ++ } ++ if(iproc_gpio_dev[i]->irq_base) { ++ free_irq(iproc_gpio_dev[i]->irq,iproc_gpio_dev[i]); ++ } ++ ++ gpiochip_remove(&iproc_gpio_dev[i]->chip); ++ iproc_gpio_dev[i] = NULL; ++ } ++ } ++} ++ ++MODULE_DESCRIPTION("IPROC GPIO driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(gpio_init); ++module_exit(gpio_exit); +diff --git a/drivers/bcmdrivers/gpio/gpio.h b/drivers/bcmdrivers/gpio/gpio.h +new file mode 100644 +index 0000000..bfc44f7 +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpio.h +@@ -0,0 +1,101 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __IPROC_PLAT_GPIO_H ++#define __IPROC_PLAT_GPIO_H ++ ++#include ++ ++#if defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_GPIO_CCG ++#else ++#define IPROC_GPIO_CCA ++#define IPROC_GPIO_CCB ++#endif ++ ++#define IPROC_GPIO_REG_SIZE (0x50) ++ ++ ++ ++ ++ ++#define REGOFFSET_GPIO_DIN 0x000 /* GPIO Data in register */ ++#define REGOFFSET_GPIO_DOUT 0x004 /* GPIO Data out register */ ++#define REGOFFSET_GPIO_EN 0x008 /* GPIO driver enable register */ ++ ++ ++#define IPROC_GPIO_CCA_ID (0) ++#define IPROC_GPIO_CCB_ID (1) ++#define IPROC_GPIO_CCG_ID (2) ++ ++#define IPROC_GPIO_CCA_IRQ_BASE (IPROC_IRQ_GPIO_0) ++#define IPROC_GPIO_CCB_IRQ_BASE (IPROC_IRQ_GPIO_0 + 32) ++#define IPROC_GPIO_CCG_IRQ_BASE (IPROC_IRQ_GPIO_0) ++ ++ ++ ++ ++#define IPROC_CCA_INT_F_GPIOINT (1) ++ ++struct iproc_gpio_irqcfg { ++ unsigned long flags; ++ irqreturn_t (*handler)(int irq, void *dev); ++ void (*ack)(unsigned int irq); ++ void (*unmask)(unsigned int irq); ++ void (*mask)(unsigned int irq); ++ int (*set_type)(unsigned int irq, unsigned int type); ++}; ++ ++struct iproc_gpio_chip { ++ int id; ++ struct gpio_chip chip; ++ struct iproc_gpio_cfg *config; ++ void __iomem *ioaddr; ++ void __iomem *intr_ioaddr; ++ void __iomem *dmu_ioaddr; ++ spinlock_t lock; ++ int irq_base; ++ struct resource * resource; ++ int irq; ++ struct iproc_gpio_irqcfg *irqcfg; ++ int pin_offset; ++}; ++ ++ ++static inline struct iproc_gpio_chip *to_iproc_gpio(struct gpio_chip *gpc) ++{ ++ return container_of(gpc, struct iproc_gpio_chip, chip); ++} ++ ++#define IPROC_GPIO_END (32 + 4) ++ ++extern struct iproc_gpio_chip *iproc_gpios[IPROC_GPIO_END]; ++ ++static inline struct iproc_gpio_chip *iproc_gpiolib_getchip(unsigned int chip) ++{ ++ return (chip < IPROC_GPIO_END) ? iproc_gpios[chip] : NULL; ++} ++ ++/* locking wrappers to deal with multiple access to the same gpio bank */ ++#define iproc_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl) ++#define iproc_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl) ++ ++extern void iproc_gpiolib_add(struct iproc_gpio_chip *chip); ++extern int iproc_gpiolib_init(void); ++ ++#define MAX_NS_GPIO 2 ++ ++#endif +diff --git a/drivers/bcmdrivers/gpio/gpio_cfg.c b/drivers/bcmdrivers/gpio/gpio_cfg.c +new file mode 100644 +index 0000000..2bd1a74 +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpio_cfg.c +@@ -0,0 +1,402 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "gpio.h" ++#include "gpio_cfg.h" ++ ++#if defined(IPROC_GPIO_CCA) ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++int iproc_gpio_set_config_cca(struct iproc_gpio_chip *chip, ++ unsigned int off, unsigned int cfg) ++{ ++ unsigned long aux_sel; ++ unsigned int aux_sel_reg; ++ unsigned int base, pin; ++ ++ base = 0; ++ pin = 0; ++ if (chip->id == IPROC_GPIO_CCA_ID) { ++ aux_sel_reg = IPROC_GPIO_CCA_CTRL0; ++ base = (unsigned int)chip->dmu_ioaddr; ++ if(off <= 17){ ++ pin = 1 << off; ++ } else if (off >= 21){ ++ pin = 1 << (off - 3); ++ } else { ++ if (cfg == IPROC_GPIO_AUX_FUN) ++ return -EINVAL; ++ else ++ return 0; ++ } ++ } ++ aux_sel = readl_relaxed(base + aux_sel_reg); ++ ++ switch (cfg) { ++ case IPROC_GPIO_GENERAL: ++ aux_sel |= pin; ++ break; ++ case IPROC_GPIO_AUX_FUN: ++ aux_sel &= ~(pin); ++ break; ++ default: ++ return -EINVAL; ++ } ++ writel_relaxed(aux_sel, base + aux_sel_reg); ++ ++ return 0; ++} ++ ++ ++unsigned iproc_gpio_get_config_cca(struct iproc_gpio_chip *chip, ++ unsigned int off) ++{ ++ unsigned long aux_sel; ++ unsigned int aux_sel_reg; ++ unsigned int base, pin; ++ ++ base = 0; ++ pin = 0; ++ if (chip->id == IPROC_GPIO_CCA_ID) { ++ ++ aux_sel_reg = IPROC_GPIO_CCA_CTRL0; ++ base = (unsigned int)chip->dmu_ioaddr; ++ if(off <= 17){ ++ pin = 1 << off; ++ } else if (off >= 21){ ++ pin = 1 << (off - 3); ++ } else { ++ return IPROC_GPIO_GENERAL; ++ } ++ } ++ ++ aux_sel = readl_relaxed(base + aux_sel_reg); ++ ++ if (aux_sel & pin) { ++ return IPROC_GPIO_GENERAL; ++ } else { ++ return IPROC_GPIO_AUX_FUN; ++ } ++} ++ ++ ++int iproc_gpio_setpull_updown_cca(struct iproc_gpio_chip *chip, ++ unsigned int off, iproc_gpio_pull_t pull) ++{ ++ unsigned int base; ++ base = 0; ++ ++ if (chip->id == IPROC_GPIO_CCA_ID) { ++ unsigned long pull_up, pull_down; ++ ++ base = (unsigned int)chip->dmu_ioaddr; ++ ++ pull_up = readl_relaxed(base + IPROC_GPIO_CCA_PULL_UP); ++ pull_down = readl_relaxed(base + IPROC_GPIO_CCA_PULL_DOWN); ++ ++ switch (pull) { ++ case IPROC_GPIO_PULL_UP: ++ pull_up |= (1 << off); ++ pull_down &= ~(1 << off); ++ break; ++ case IPROC_GPIO_PULL_DOWN: ++ pull_up &= ~(1 << off); ++ pull_down |= (1 << off); ++ break; ++ case IPROC_GPIO_PULL_NONE: ++ pull_up &= ~(1 << off); ++ pull_down &= ~(1 << off); ++ break; ++ default: ++ return -EINVAL; ++ } ++ writel_relaxed(pull_up, base + IPROC_GPIO_CCA_PULL_UP); ++ writel_relaxed(pull_down, base + IPROC_GPIO_CCA_PULL_DOWN); ++ } ++ ++ return 0; ++} ++ ++ ++iproc_gpio_pull_t iproc_gpio_getpull_updown_cca(struct iproc_gpio_chip *chip, ++ unsigned int off) ++{ ++ ++ unsigned int base; ++ base = 0; ++ ++ if (chip->id == IPROC_GPIO_CCA_ID) { ++ unsigned long pull_up, pull_down; ++ ++ base = (unsigned int)chip->dmu_ioaddr; ++ ++ pull_up = readl_relaxed(base + IPROC_GPIO_CCA_PULL_UP); ++ pull_down = readl_relaxed(base + IPROC_GPIO_CCA_PULL_DOWN); ++ pull_up &= 1 << off; ++ pull_down &= 1 << off; ++ ++ if (pull_up ^ pull_down) { ++ if (pull_up) { ++ return IPROC_GPIO_PULL_UP; ++ } else { ++ return IPROC_GPIO_PULL_DOWN; ++ } ++ } else if(!pull_up) { ++ return IPROC_GPIO_PULL_NONE; ++ } ++ } ++ ++ return IPROC_GPIO_PULL_NONE; ++} ++struct iproc_gpio_cfg cca_gpio_cfg = { ++ .get_pull = iproc_gpio_getpull_updown_cca, ++ .set_pull = iproc_gpio_setpull_updown_cca, ++ .get_config = iproc_gpio_get_config_cca, ++ .set_config = iproc_gpio_set_config_cca, ++}; ++#endif ++#endif /* IPROC_GPIO_CCA */ ++ ++#if defined(IPROC_GPIO_CCB) || defined(IPROC_GPIO_CCG) ++int iproc_gpio_set_config_ccb(struct iproc_gpio_chip *chip, ++ unsigned int off, unsigned int cfg) ++{ ++ unsigned long aux_sel; ++ unsigned int aux_sel_reg; ++ unsigned int base, pin; ++ ++ base = 0; ++ pin = 0; ++ ++ if ((chip->id == IPROC_GPIO_CCB_ID) || (chip->id == IPROC_GPIO_CCG_ID)) { ++ aux_sel_reg = IPROC_GPIO_CCB_AUX_SEL; ++ base = (unsigned int)chip->ioaddr; ++ pin = 1 << off; ++ } ++ aux_sel = readl_relaxed(base + aux_sel_reg); ++ ++ switch (cfg) { ++ case IPROC_GPIO_GENERAL: ++ aux_sel &= ~(pin); ++ break; ++ case IPROC_GPIO_AUX_FUN: ++ aux_sel |= (pin); ++ break; ++ default: ++ return -EINVAL; ++ } ++ writel_relaxed(aux_sel, base + aux_sel_reg); ++ ++ return 0; ++} ++ ++ ++unsigned iproc_gpio_get_config_ccb(struct iproc_gpio_chip *chip, ++ unsigned int off) ++{ ++ unsigned long aux_sel; ++ unsigned int aux_sel_reg; ++ unsigned int base, pin; ++ ++ base = 0; ++ pin = 0; ++ ++ if ((chip->id == IPROC_GPIO_CCB_ID) || (chip->id == IPROC_GPIO_CCG_ID)) { ++ aux_sel_reg = IPROC_GPIO_CCB_AUX_SEL; ++ base = (unsigned int)chip->ioaddr; ++ pin = 1 << off; ++ } ++ ++ aux_sel = readl_relaxed(base + aux_sel_reg); ++ ++ if (aux_sel & pin) { ++ return IPROC_GPIO_AUX_FUN; ++ } else { ++ return IPROC_GPIO_GENERAL; ++ } ++} ++ ++ ++int iproc_gpio_setpull_updown_ccb(struct iproc_gpio_chip *chip, ++ unsigned int off, iproc_gpio_pull_t pull) ++{ ++ unsigned int base; ++ base = 0; ++ ++ if ((chip->id == IPROC_GPIO_CCB_ID) || (chip->id == IPROC_GPIO_CCG_ID)) { ++ unsigned long pad_res, res_en; ++ ++ base = (unsigned int)chip->ioaddr; ++ ++ pad_res = readl_relaxed(base + IPROC_GPIO_CCB_PAD_RES); ++ res_en = readl_relaxed(base + IPROC_GPIO_CCB_RES_EN); ++ switch (pull) { ++ case IPROC_GPIO_PULL_UP: ++ pad_res |= (1 << off); ++ res_en |= (1 << off); ++ break; ++ case IPROC_GPIO_PULL_DOWN: ++ pad_res &= ~(1 << off); ++ res_en |= (1 << off); ++ break; ++ case IPROC_GPIO_PULL_NONE: ++ res_en &= ~(1 << off); ++ break; ++ default: ++ return -EINVAL; ++ } ++ writel_relaxed(pad_res, base + IPROC_GPIO_CCB_PAD_RES); ++ writel_relaxed(res_en, base + IPROC_GPIO_CCB_RES_EN); ++ } ++ return 0; ++} ++ ++ ++iproc_gpio_pull_t iproc_gpio_getpull_updown_ccb(struct iproc_gpio_chip *chip, ++ unsigned int off) ++{ ++ ++ unsigned int base; ++ base = 0; ++ ++ if ((chip->id == IPROC_GPIO_CCB_ID) || (chip->id == IPROC_GPIO_CCG_ID)) { ++ unsigned long pad_res, res_en; ++ ++ base = (unsigned int)chip->ioaddr; ++ ++ pad_res = readl_relaxed(base + IPROC_GPIO_CCB_PAD_RES); ++ res_en = readl_relaxed(base + IPROC_GPIO_CCB_RES_EN); ++ pad_res &= 1 << off; ++ res_en &= 1 << off; ++ ++ if (res_en) { ++ if (pad_res) { ++ return IPROC_GPIO_PULL_UP; ++ } else { ++ return IPROC_GPIO_PULL_DOWN; ++ } ++ } else { ++ return IPROC_GPIO_PULL_NONE; ++ } ++ } ++ return IPROC_GPIO_PULL_NONE; ++} ++ ++struct iproc_gpio_cfg ccb_gpio_cfg = { ++ .get_pull = iproc_gpio_getpull_updown_ccb, ++ .set_pull = iproc_gpio_setpull_updown_ccb, ++ .get_config = iproc_gpio_get_config_ccb, ++ .set_config = iproc_gpio_set_config_ccb, ++}; ++#endif /* IPROC_GPIO_CCB || IPROC_GPIO_CCG */ ++ ++iproc_gpio_pull_t iproc_gpio_getpull(unsigned int pin) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpiolib_getchip(pin); ++ unsigned long flags; ++ int offset, ret = -EINVAL; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ offset = pin - chip->chip.base; ++ offset += chip->pin_offset; ++ ++ iproc_gpio_lock(chip, flags); ++ if (chip->config){ ++ ret = (chip->config->get_pull)(chip, offset); ++ } ++ iproc_gpio_unlock(chip, flags); ++ ++ return ret; ++ ++} ++EXPORT_SYMBOL(iproc_gpio_getpull); ++ ++ ++int iproc_gpio_setpull(unsigned int pin, iproc_gpio_pull_t pull) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpiolib_getchip(pin); ++ unsigned long flags; ++ int offset, ret = -EINVAL; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ offset = pin - chip->chip.base; ++ offset += chip->pin_offset; ++ ++ iproc_gpio_lock(chip, flags); ++ if (chip->config){ ++ ret = (chip->config->set_pull)(chip, offset, pull); ++ } ++ iproc_gpio_unlock(chip, flags); ++ ++ return ret; ++ ++} ++EXPORT_SYMBOL(iproc_gpio_setpull); ++ ++unsigned iproc_gpio_getcfg(unsigned int pin) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpiolib_getchip(pin); ++ unsigned long flags; ++ int offset; ++ unsigned ret = 0; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ offset = pin - chip->chip.base; ++ offset += chip->pin_offset; ++ iproc_gpio_lock(chip, flags); ++ if (chip->config){ ++ ret = (chip->config->get_config)(chip, offset); ++ } ++ iproc_gpio_unlock(chip, flags); ++ ++ return ret; ++} ++ ++EXPORT_SYMBOL(iproc_gpio_getcfg); ++ ++int iproc_gpio_cfgpin(unsigned int pin, unsigned int config) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpiolib_getchip(pin); ++ unsigned long flags; ++ int offset; ++ int ret = 0; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ offset = pin - chip->chip.base; ++ offset += chip->pin_offset; ++ iproc_gpio_lock(chip, flags); ++ if (chip->config){ ++ (chip->config->set_config)(chip, offset, config); ++ } ++ iproc_gpio_unlock(chip, flags); ++ ++ return ret; ++ ++ ++} ++EXPORT_SYMBOL(iproc_gpio_cfgpin); +diff --git a/drivers/bcmdrivers/gpio/gpio_cfg.h b/drivers/bcmdrivers/gpio/gpio_cfg.h +new file mode 100644 +index 0000000..126a7fb +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpio_cfg.h +@@ -0,0 +1,107 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __PLAT_GPIO_CFG_H ++#define __PLAT_GPIO_CFG_H ++ ++typedef unsigned int __bitwise__ iproc_gpio_pull_t; ++typedef unsigned int __bitwise__ iproc_gpio_drvstr_t; ++ ++struct iproc_gpio_chip; ++ ++struct iproc_gpio_cfg { ++ iproc_gpio_pull_t (*get_pull)(struct iproc_gpio_chip *chip, unsigned int offs); ++ int (*set_pull)(struct iproc_gpio_chip *chip, unsigned int offs, ++ iproc_gpio_pull_t pull); ++ unsigned (*get_config)(struct iproc_gpio_chip *chip, unsigned int offs); ++ int (*set_config)(struct iproc_gpio_chip *chip, unsigned int offs, ++ unsigned int config); ++}; ++ ++ ++/** ++ * iproc_gpio_cfgpin() - Change the GPIO function of a pin. ++ * @pin pin The pin number to configure. ++ * @to to The configuration (IPROC_GPIO_GENERAL/ IPROC_GPIO_AUX_FUN) for the pin's function. ++ * ++ */ ++ ++extern int iproc_gpio_cfgpin(unsigned int pin, unsigned int to); ++ ++ ++/** ++ * iproc_gpio_getcfg - Read the current function for a GPIO pin ++ * @pin: The pin to read the configuration value for. ++ * ++ * Read the configuration state of the given @pin, returning a value that ++ * could be passed back to iproc_gpio_cfgpin(). ++ * ++ * ++ */ ++extern unsigned iproc_gpio_getcfg(unsigned int pin); ++ ++#define IPROC_GPIO_GENERAL 0 ++#define IPROC_GPIO_AUX_FUN 1 ++ ++ ++/* Define values for the pull-{up,down} available for each gpio pin. ++ * ++ * These values control the state of the weak pull-{up,down} resistors. ++ */ ++#define IPROC_GPIO_PULL_NONE ((__force iproc_gpio_pull_t)0x00) ++#define IPROC_GPIO_PULL_DOWN ((__force iproc_gpio_pull_t)0x01) ++#define IPROC_GPIO_PULL_UP ((__force iproc_gpio_pull_t)0x02) ++ ++ ++ ++ ++/** ++ * iproc_gpio_setpull() - set the state of a gpio pin pull resistor ++ * @pin: The pin number to configure the pull resistor. ++ * @pull: The configuration for the pull resistor. ++ * ++ * This function sets the state of the pull-{up,down} resistor for the ++ * specified pin. It will return 0 if successfull, or a negative error ++ * code if the pin cannot support the requested pull setting. ++ * ++ * @pull is one of IPROC_GPIO_PULL_NONE, IPROC_GPIO_PULL_DOWN or IPROC_GPIO_PULL_UP. ++*/ ++extern int iproc_gpio_setpull(unsigned int pin, iproc_gpio_pull_t pull); ++ ++ ++/** ++ * iproc_gpio_getpull() - get the pull resistor state of a gpio pin ++ * @pin: The pin number to get the settings for ++ * ++ * Read the pull resistor value for the specified pin. ++*/ ++extern iproc_gpio_pull_t iproc_gpio_getpull(unsigned int pin); ++ ++/* internal gpio functions */ ++extern int iproc_gpio_setpull_updown(struct iproc_gpio_chip *chip, ++ unsigned int off, iproc_gpio_pull_t pull); ++ ++extern iproc_gpio_pull_t iproc_gpio_getpull_updown(struct iproc_gpio_chip *chip, ++ unsigned int off); ++ ++extern int iproc_gpio_set_config(struct iproc_gpio_chip *chip, ++ unsigned int off, unsigned int cfg); ++ ++unsigned iproc_gpio_get_config(struct iproc_gpio_chip *chip, ++ unsigned int off); ++ ++#endif +diff --git a/drivers/bcmdrivers/gpio/gpiolib.c b/drivers/bcmdrivers/gpio/gpiolib.c +new file mode 100644 +index 0000000..6348974 +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpiolib.c +@@ -0,0 +1,259 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "gpio.h" ++#include "gpio_cfg.h" ++ ++ ++#if defined(IPROC_GPIO_CCA) ++ ++extern struct iproc_gpio_irqcfg cca_gpio_irqcfg; ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ ++extern struct iproc_gpio_cfg cca_gpio_cfg; ++ ++#endif /*CONFIG_MACH_NS || CONFIG_MACH_NSP */ ++ ++static struct resource iproc_gpio_cca_config_resource[] = { ++ [0] = { ++ .start = IPROC_CCA_BASE, ++ .end = IPROC_CCA_BASE + IPROC_GPIO_REG_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ .name = "intr", ++ }, ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ [1] = { ++ .start = IPROC_DMU_BASE, ++ .end = IPROC_DMU_BASE + 0x200 - 1, ++ .flags = IORESOURCE_MEM, ++ .name = "dmu", ++ }, ++#else ++ [1] = {.name = "",}, ++#endif ++}; ++ ++#endif /* IPROC_GPIO_CCA */ ++ ++ ++#if defined(IPROC_GPIO_CCB) || defined(IPROC_GPIO_CCG) ++ ++extern struct iproc_gpio_irqcfg ccb_gpio_irqcfg; ++extern struct iproc_gpio_cfg ccb_gpio_cfg; ++ ++#endif /* IPROC_GPIO_CCB || IPROC_GPIO_CCG */ ++ ++ ++#if defined(IPROC_GPIO_CCG) ++static struct resource iproc_gpio_resources[] = { ++ [0] = { ++ .start = IPROC_GPIO_CCG_BASE, ++ .end = IPROC_GPIO_CCG_BASE + IPROC_GPIO_REG_SIZE -1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++#else ++static struct resource iproc_gpio_resources[] = { ++ [0] = { ++ .start = IPROC_GPIO_CCA_BASE, ++ .end = IPROC_GPIO_CCA_BASE + IPROC_GPIO_REG_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ .child = iproc_gpio_cca_config_resource, ++ }, ++ [1] = { ++ .start = IPROC_GPIO_CCB_BASE, ++ .end = IPROC_GPIO_CCB_BASE + IPROC_GPIO_REG_SIZE -1, ++ .flags = IORESOURCE_MEM, ++ } ++}; ++#endif ++ ++#if defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP) ++ ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCA_ID, ++ .config = &cca_gpio_cfg, ++ .chip = { ++ .base = 0, ++ .label = "GPIOA", ++ .ngpio = 24, ++ }, ++ .irq_base = IPROC_GPIO_CCA_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCA_INT, ++ .irqcfg = &cca_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++}; ++/* CONFIG_MACH_NS */ ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++/* ++ * Chip level GPIO 0-3 from CMICD, ++ * GPIO 4-11 from ChipcommonA gpio pin 0 - 7 ++ * Hence the base is 4 and the number is 8. ++ */ ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCA_ID, ++ .chip = { ++ .base = 4, ++ .label = "GPIOA", ++ .ngpio = 8, ++ }, ++ .irq_base = IPROC_GPIO_CCA_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCA_INT, ++ .irqcfg = &cca_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++}; ++#elif defined(CONFIG_MACH_HR2) ++/* ++ * Chip level GPIO 0-3 from CMICD, ++ * GPIO 4-15 are from ChipcommonA gpio pin 0 - 11 ++ * where GPIO 8-15 are shared with MII or LED depends on strap pin ++ * Hence the base is 4 and the number is 12. ++ */ ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCA_ID, ++ .chip = { ++ .base = 4, ++ .label = "GPIOA", ++ .ngpio = 12, ++ }, ++ .irq_base = IPROC_GPIO_CCA_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCA_INT, ++ .irqcfg = &cca_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++}; ++#elif defined(CONFIG_MACH_GH) ++/* ++* Chip level GPIO 0-3 from CMICD, ++* GPIO 4-15 are from ChipcommonG gpio pin 4 - 15 ++*/ ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCG_ID, ++ .config = &ccb_gpio_cfg, ++ .chip = { ++ .base = 4, ++ .label = "GPIOG", ++ .ngpio = 12, ++ }, ++ .irq_base = IPROC_GPIO_CCG_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCG_INT, ++ .irqcfg = &ccb_gpio_irqcfg, ++ .pin_offset = 4, ++ }, ++}; ++#else ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCA_ID, ++ .chip = { ++ .base = 0, ++ .label = "GPIOA", ++ .ngpio = 32, ++ }, ++ .irq_base = IPROC_GPIO_CCA_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCA_INT, ++ .irqcfg = &cca_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++ [1] = { ++ .id = IPROC_GPIO_CCB_ID, ++ .chip = { ++ .base = -EINVAL, ++ .label = "GPIOB", ++ .ngpio = 4, ++ }, ++ .irq_base = IPROC_GPIO_CCB_IRQ_BASE, ++ .resource = &iproc_gpio_resources[1], ++ .irq = IPROC_GPIO_CCB_INT, ++ .irqcfg = &ccb_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++}; ++#endif ++ ++int iproc_gpiolib_init(void) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpios_config; ++ int gpn; ++ int temp_base; ++ ++#if defined(CONFIG_MACH_NS) ++ /* bcm53012 support 24 gpios; bcm53010/53011 support 16 gpios */ ++ if ((__REG32(IPROC_IDM_REGISTER_VA + 0xd500) & 0xc) != 0x0) { ++ iproc_gpios_config[0].chip.ngpio = 16; ++ } ++#endif ++#if defined(CONFIG_MACH_NSP) ++ /* bcm53025 support 32 gpios; bcm53022/53023 support 24 gpios */ ++ reg32_write((volatile uint32_t *)(IPROC_PCIE_AXIB0_REG_VA + PAXB_0_CONFIG_IND_ADDR_BASE), 0); ++ ++/* ++ the mechanism to get the chip number does not work, always reads 22K. ++ OTP must be programmed and then need to look at OTP ++ for now assume 25K chip ++ ++ if ((__REG32(IPROC_PCIE_AXIB0_REG_VA + PAXB_0_CONFIG_IND_DATA_BASE) ++ & 0xffff0000) == 0x80250000) { ++*/ ++ if (1) { ++ iproc_gpios_config[0].chip.ngpio = 32; ++ } ++#endif ++ ++ ++ temp_base = 0; ++ for (gpn = 0; gpn < ARRAY_SIZE(iproc_gpios_config); gpn++, chip++) { ++ if (gpn >= MAX_NS_GPIO){ ++ printk("Unavailabe to add gpiolib\n"); ++ return -EINVAL; ++ } ++ ++ if (chip->chip.base == -EINVAL) { ++ chip->chip.base = temp_base; ++ } ++ ++ iproc_gpiolib_add(chip); ++ temp_base = chip->chip.base + chip->chip.ngpio; ++ } ++ ++ return 0; ++} +diff --git a/drivers/bcmdrivers/include/Readme.txt b/drivers/bcmdrivers/include/Readme.txt +new file mode 100644 +index 0000000..41eb87c +--- /dev/null ++++ b/drivers/bcmdrivers/include/Readme.txt +@@ -0,0 +1 @@ ++Only shared api's or exported api's common files +diff --git a/drivers/bcmdrivers/mdio/.gitignore b/drivers/bcmdrivers/mdio/.gitignore +new file mode 100644 +index 0000000..c1e8a25 +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/.iproc_mdio.o.cmd ++/.iproc_mii.o.cmd ++/built-in.o ++/iproc_mdio.o ++/iproc_mii.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/mdio/Kconfig b/drivers/bcmdrivers/mdio/Kconfig +new file mode 100644 +index 0000000..3d54c81 +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/Kconfig +@@ -0,0 +1,8 @@ ++config IPROC_MDIO ++ tristate "MDIO support" ++ depends on ARCH_IPROC ++ default n ++ help ++ MDIO support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/mdio/Makefile b/drivers/bcmdrivers/mdio/Makefile +new file mode 100644 +index 0000000..03746c7 +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_MDIO) += iproc_mii.o ++iproc_mii-objs := iproc_mdio.o +diff --git a/drivers/bcmdrivers/mdio/iproc_mdio.c b/drivers/bcmdrivers/mdio/iproc_mdio.c +new file mode 100755 +index 0000000..5ecb92e +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/iproc_mdio.c +@@ -0,0 +1,585 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++ ++#include "iproc_mdio.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "iproc_mdio_dev.h" ++ ++static void * baseAddr; ++ ++#define R_REG(reg) ioread32(baseAddr + (reg&0x0fff)) ++#define W_REG(reg, val) iowrite32(val, baseAddr + (reg&0x0fff)) ++ ++#define MII_ERR_VAL 0x0001 ++#define MII_MSG_VAL 0x0002 ++#define MII_DBG_VAL 0x0004 ++//static u32 mii_msg_level = MII_ERR_VAL; ++ ++#if defined(BCMDBG) || defined(BCMDBG_ERR) ++#define MII_ERR(args) do {if (mii_msg_level & MII_ERR_VAL) printk args;} while (0) ++#else ++#define MII_ERR(args) ++#endif ++ ++#ifdef BCMDBG ++#define MII_MSG(args) do {if (mii_msg_level & MII_MSG_VAL) printk args;} while (0) ++#define MII_DBG(args) do {if (mii_msg_level & MII_DBG_VAL) printk args;} while (0) ++#else ++#define MII_MSG(args) ++#define MII_DBG(args) ++#endif ++ ++#define MII_EN_CHK \ ++ {\ ++ if (!baseAddr) { \ ++ return MII_ERR_INIT; \ ++ } \ ++ if (!(R_REG(MII_MGMT) & 0x7f)) { \ ++ return MII_ERR_INTERNAL; \ ++ } \ ++ } ++ ++#define MII_TRIES 100000 ++#define MII_POLL_USEC 20 ++ ++struct mdio_device_data { ++ mdio_info_t *mdio; ++ int init; ++}; ++ ++static struct mdio_device_data mdio_devices={0}; ++ ++#define DRIVER_VERSION "0.01" ++#define DRIVER_NAME "iproc mdio" ++ ++static int mdio_major; ++static struct cdev mdio_cdev; ++ ++#define MDIO_IOC_OP_EXTERNAL_READ 0 ++#define MDIO_IOC_OP_EXTERNAL_WRITE 1 ++#define MDIO_IOC_OP_LOCAL_READ 2 ++#define MDIO_IOC_OP_LOCAL_WRITE 3 ++ ++/* Function : ccb_mii_read ++ * - Read operation. ++ * Return : ++ * Note : ++ */ ++int ++ccb_mii_read(int dev_type, int phy_addr, int reg_off, uint16_t *data) ++{ ++ int i; ++ uint32_t ctrl = 0; ++ unsigned long flags; ++ mdio_info_t *mdio = NULL; ++ ++ MII_EN_CHK; ++ ++ mdio = mdio_devices.mdio; ++ ++ spin_lock_irqsave(&mdio->lock, flags); ++ ++ ctrl = R_REG(MII_MGMT); ++ if (dev_type == MII_DEV_LOCAL) { ++ ctrl &= ~MII_MGMT_EXP_MASK; ++ } else { ++ ctrl |= MII_MGMT_EXP_MASK; ++ } ++ W_REG(MII_MGMT, ctrl); ++ MII_DBG(("MII READ: write(0x%x)=0x%x\n",MII_MGMT, ctrl)); ++ ++ for (i = 0; i < MII_TRIES; i++) { ++ ctrl = R_REG(MII_MGMT); ++ if (!(ctrl & MII_MGMT_BSY_MASK)) { ++ break; ++ } ++ udelay(MII_POLL_USEC); ++ } ++ if (i >= MII_TRIES) { ++ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ return -1; ++ } ++ ++ ctrl = ((1 << MII_CMD_DATA_SB_SHIFT) & MII_CMD_DATA_SB_MASK) | ++ ((2 << MII_CMD_DATA_OP_SHIFT) & MII_CMD_DATA_OP_MASK) | ++ ((phy_addr << MII_CMD_DATA_PA_SHIFT) & MII_CMD_DATA_PA_MASK) | ++ ((reg_off << MII_CMD_DATA_RA_SHIFT) & MII_CMD_DATA_RA_MASK) | ++ ((2 << MII_CMD_DATA_TA_SHIFT) & MII_CMD_DATA_TA_MASK); ++ W_REG(MII_CMD_DATA, ctrl); ++ MII_DBG(("MII READ: write(0x%x)=0x%x\n",MII_CMD_DATA, ctrl)); ++ ++ ++ for (i = 0; i < MII_TRIES; i++) { ++ ctrl = R_REG(MII_MGMT); ++ if (!(ctrl & MII_MGMT_BSY_MASK)) { ++ break; ++ } ++ udelay(MII_POLL_USEC); ++ } ++ if (i >= MII_TRIES) { ++ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ return -1; ++ } ++ ++ ctrl = R_REG(MII_CMD_DATA); ++ ++ MII_DBG(("MDIO READ: addr=%x off=%x value=%x\n", phy_addr, reg_off, ctrl)); ++ ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ ++ *data = (ctrl & 0xffff); ++ return 0; ++} ++ ++/* Function : ccb_mii_write ++ * - Write operation. ++ * Return : ++ * Note : ++ */ ++int ++ccb_mii_write(int dev_type, int phy_addr, int reg_off, uint16_t data) ++{ ++ int i; ++ uint32_t ctrl = 0; ++ unsigned long flags; ++ mdio_info_t *mdio = NULL; ++ ++ MII_DBG(("MDIO WRITE: addr=%x off=%x\n", phy_addr, reg_off)); ++ ++ MII_EN_CHK; ++ ++ mdio = mdio_devices.mdio; ++ ++ spin_lock_irqsave(&mdio->lock, flags); ++ ++ ctrl = R_REG(MII_MGMT); ++ if (dev_type == MII_DEV_LOCAL) { ++ ctrl &= ~MII_MGMT_EXP_MASK; ++ } else { ++ ctrl |= MII_MGMT_EXP_MASK; ++ } ++ W_REG(MII_MGMT, ctrl); ++ MII_DBG(("MII WRITE: write(0x%x)=0x%x\n",MII_MGMT, ctrl)); ++ ++ for (i = 0; i < MII_TRIES; i++) { ++ ctrl = R_REG(MII_MGMT); ++ if (!(ctrl & MII_MGMT_BSY_MASK)) { ++ break; ++ } ++ udelay(MII_POLL_USEC); ++ } ++ if (i >= MII_TRIES) { ++ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ return -1; ++ } ++ ++ ctrl = ((1 << MII_CMD_DATA_SB_SHIFT) & MII_CMD_DATA_SB_MASK) | ++ ((1 << MII_CMD_DATA_OP_SHIFT) & MII_CMD_DATA_OP_MASK) | ++ ((phy_addr << MII_CMD_DATA_PA_SHIFT) & MII_CMD_DATA_PA_MASK) | ++ ((reg_off << MII_CMD_DATA_RA_SHIFT) & MII_CMD_DATA_RA_MASK) | ++ ((2 << MII_CMD_DATA_TA_SHIFT) & MII_CMD_DATA_TA_MASK) | ++ ((data << MII_CMD_DATA_DATA_SHIFT) & MII_CMD_DATA_DATA_MASK); ++ W_REG(MII_CMD_DATA, ctrl); ++ MII_DBG(("MII WRITE: write(0x%x)=0x%x\n",MII_CMD_DATA, ctrl)); ++ ++ ++ for (i = 0; i < MII_TRIES; i++) { ++ ctrl = R_REG(MII_MGMT); ++ if (!(ctrl & MII_MGMT_BSY_MASK)) { ++ break; ++ } ++ udelay(MII_POLL_USEC); ++ } ++ if (i >= MII_TRIES) { ++ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ return -1; ++ } ++ ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ ++ return MII_ERR_NONE; ++} ++ ++/* Function : ccb_mii_freq_set ++ * - Set MII management interface frequency. ++ * Return : ++ * Note : ++ * ++ */ ++int ++ccb_mii_freq_set(int speed_khz) ++{ ++ int rv = MII_ERR_NONE; ++ uint32_t divider = 0; ++ uint32_t mgmt = 0; ++ ++ MII_DBG(("MDIO FREQ SET: %d KHz\n", speed_khz)); ++ ++ /* host clock 66MHz device value the MDCDIV field */ ++ /* resultant MDIO clock should not exceed 2.5MHz */ ++ ++ if (speed_khz > 2560) { ++ MII_ERR(("\n%s: Maximum MDIO frequency is 2.5MHz\n", __FUNCTION__)); ++ return MII_ERR_PARAM; ++ } ++ ++ divider = 67584 / speed_khz; ++ divider = (divider & MII_MGMT_MDCDIV_MASK); ++ if (divider > 0x7f) { ++ /* make sure the minimum configurable frequency */ ++ divider = 0x7f; ++ } ++ mgmt = R_REG(MII_MGMT); ++ mgmt &= ~MII_MGMT_MDCDIV_MASK; ++ mgmt |= divider; ++ ++ W_REG(MII_MGMT, mgmt); ++ MII_DBG(("MII FREQ(%d KHz): write(0x%x)=0x%x\n",speed_khz, MII_MGMT, mgmt)); ++ ++ return rv; ++} ++ ++static void __maybe_unused ++_dump_devs(void) ++{ ++// int r; ++// int addr, off; ++ int addr; ++ int phyid1, phyid2; ++ int cnt = 0; ++ int found = 0; ++ ++ for (addr = 0; addr <= 0x1f; addr++) { ++ ccb_mii_read(MII_DEV_LOCAL, addr, 2, (uint16_t *)&phyid1); ++ ccb_mii_read(MII_DEV_LOCAL, addr, 3, (uint16_t *)&phyid2); ++ found = 0; ++ if (phyid1 == 0xffff) { ++ continue; ++ } ++ ++ if ((phyid1) && (phyid2)) { ++ cnt ++; ++ found = 1; ++ } ++ if (cnt == 1) { ++ printk("Found LOCAL device(s) on MDC/MDIO interface:\n"); ++ } ++ if (found) { ++ printk("PHY address=%2d, IDs = 0x%4x 0x%4x\n", addr, phyid1, phyid2); ++ } ++ } ++ ++ cnt = 0; ++ found = 0; ++ for (addr = 0; addr <= 0x1f; addr++) { ++ ccb_mii_read(MII_DEV_EXT, addr, 2, (uint16_t *)&phyid1); ++ ccb_mii_read(MII_DEV_EXT, addr, 3, (uint16_t *)&phyid2); ++ found = 0; ++ if (phyid1 == 0xffff) { ++ continue; ++ } ++ ++ if ((phyid1) && (phyid2)) { ++ cnt ++; ++ found = 1; ++ } ++ if (cnt == 1) { ++ printk("Found EXTERNAL device(s) on MDC/MDIO interface:\n"); ++ } ++ if (found) { ++ printk("PHY address=%2d, IDs = 0x%4x 0x%4x\n", addr, phyid1, phyid2); ++ } ++ } ++} ++ ++static int ++mdio_open(struct inode *inode, struct file *filp) ++{ ++ filp->private_data = mdio_devices.mdio; ++ return 0; ++} ++ ++static int ++mdio_release(struct inode *inode, struct file *filp) ++{ ++ ++ return 0; ++} ++ ++static int mdio_message(mdio_info_t *mdio, ++ struct mdio_ioc_transfer *u_xfers, unsigned n_xfers, int op) ++{ ++ ++ uint8_t pa, ra; ++ uint16_t regval; ++ ++ pa = u_xfers->pa; ++ ra = u_xfers->ra; ++ ++ MII_DBG(("mdio_message: op = %d\n", op)); ++ ++ if(op == MDIO_IOC_OP_LOCAL_READ) { ++ ccb_mii_read(MII_DEV_LOCAL, pa, ra, ®val); ++ u_xfers->rx_buf = regval; ++ } ++ ++ if(op == MDIO_IOC_OP_LOCAL_WRITE) { ++ ccb_mii_write(MII_DEV_LOCAL, pa, ra, u_xfers->tx_buf); ++ } ++ ++ if(op == MDIO_IOC_OP_EXTERNAL_READ) { ++ ccb_mii_read(MII_DEV_EXT, pa, ra, ®val); ++ u_xfers->rx_buf = regval; ++ } ++ ++ if(op == MDIO_IOC_OP_EXTERNAL_WRITE) { ++ ccb_mii_write(MII_DEV_EXT, pa, ra, u_xfers->tx_buf); ++ } ++ return 0; ++} ++ ++static long ++mdio_ioctl(struct file *filp, ++ unsigned int cmd, unsigned long arg) ++{ ++ int err = 0; ++ int retval = 0; ++ int ioc_op = 0; ++ uint32_t tmp; ++ unsigned n_ioc; ++ struct mdio_ioc_transfer *ioc, *uf; ++ mdio_info_t *mdio; ++ ++ MII_DBG(("mdio_ioctl: cmd = %d\n", cmd)); ++ ++ /* Check type and command number */ ++ if (_IOC_TYPE(cmd) != MDIO_IOC_MAGIC){ ++ return -ENOTTY; ++ } ++ ++ /* Check access direction once here; don't repeat below. ++ * IOC_DIR is from the user perspective, while access_ok is ++ * from the kernel perspective; so they look reversed. ++ */ ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ err = !access_ok(VERIFY_WRITE, ++ (void __user *)arg, _IOC_SIZE(cmd)); ++ if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE) ++ err = !access_ok(VERIFY_READ, ++ (void __user *)arg, _IOC_SIZE(cmd)); ++ if (err) ++ return -EFAULT; ++ ++ mdio = (mdio_info_t *)filp->private_data; ++ ++ switch (cmd) { ++ ++ case MDIO_IOC_EXTERNAL_R_REG: ++ ioc_op = MDIO_IOC_OP_EXTERNAL_READ; ++ break; ++ case MDIO_IOC_EXTERNAL_W_REG: ++ ioc_op = MDIO_IOC_OP_EXTERNAL_WRITE; ++ break; ++ case MDIO_IOC_LOCAL_R_REG: ++ ioc_op = MDIO_IOC_OP_LOCAL_READ; ++ break; ++ case MDIO_IOC_LOCAL_W_REG: ++ ioc_op = MDIO_IOC_OP_LOCAL_WRITE; ++ break; ++ } ++ ++ tmp = _IOC_SIZE(cmd); ++ if ((tmp % sizeof(struct mdio_ioc_transfer)) != 0) { ++ retval = -EINVAL; ++ return retval; ++ } ++ n_ioc = tmp / sizeof(struct mdio_ioc_transfer); ++ if (n_ioc == 0) ++ return 0; ++ ++ /* copy into scratch area */ ++ ioc = kmalloc(tmp, GFP_KERNEL); ++ if (!ioc) { ++ retval = -ENOMEM; ++ return retval; ++ } ++ if (__copy_from_user(ioc, (void __user *)arg, tmp)) { ++ kfree(ioc); ++ retval = -EFAULT; ++ return retval; ++ } ++ /* translate to mdio_message, execute */ ++ retval = mdio_message(mdio, ioc, n_ioc, ioc_op); ++ ++ if ((ioc_op == MDIO_IOC_OP_EXTERNAL_READ) || (ioc_op == MDIO_IOC_OP_LOCAL_READ)) { ++ ++ uf = (struct mdio_ioc_transfer *)arg; ++ if (__copy_to_user((u8 __user *)&uf->rx_buf, (uint8_t *)&ioc->rx_buf, 2)) { ++ kfree(ioc); ++ retval = -EFAULT; ++ return retval; ++ } ++ } ++ kfree(ioc); ++ ++ return 0; ++} ++ ++static const struct file_operations mdio_fops = { ++ .open = mdio_open, ++ .release = mdio_release, ++ .unlocked_ioctl = mdio_ioctl, ++ .owner = THIS_MODULE, ++}; ++ ++static int _mdio_handler_init(mdio_info_t **mdio) ++{ ++ *mdio = kmalloc(sizeof(mdio_info_t), GFP_KERNEL); ++ if (*mdio == NULL) { ++ MII_ERR(("mdio_init: out of memory\n")); ++ return -ENOMEM; ++ } ++ memset(*mdio, 0, sizeof(mdio_info_t)); ++ ++ /* Initialize lock */ ++ spin_lock_init(&(*mdio)->lock); ++ ++ ++ mdio_devices.mdio = *mdio; ++ mdio_devices.init = 1; ++ ++ return 0; ++} ++ ++/* Function : ccb_mii_init ++ * - Init Northstar CCB MII management interface. ++ * Return : ++ * Note : ++ * ++ */ ++int ++ccb_mii_init(void) ++{ ++ int ret = -ENODEV; ++ dev_t mdio_dev; ++ mdio_info_t *mdio=NULL; ++ ++ _mdio_handler_init(&mdio); ++ ++ /* Get register base address */ ++ baseAddr = ioremap(IPROC_CCB_MDIO_REG_BASE, 0x1000); ++ MII_DBG(("MDIO INIT: baseAddr %x\n",baseAddr)); ++ ++ /* Set preamble */ ++ W_REG(MII_MGMT, MII_MGMT_PRE_MASK); ++ /* Set the MII default clock 1MHz */ ++ ccb_mii_freq_set(1024); ++ ++// _dump_devs(); ++ ++ if(mdio_devices.init != 1) { ++ return -ENOMEM; ++ } ++ mdio = mdio_devices.mdio; ++ ++ if (mdio_major) { ++ mdio_dev = MKDEV(mdio_major, 0); ++ ret = register_chrdev_region(mdio_dev, ++ 1, "mdio"); ++ } else { ++ ret = alloc_chrdev_region(&mdio_dev, 0, ++ 1, "mdio"); ++ mdio_major = MAJOR(mdio_dev); ++ } ++ ++ if (ret) { ++ goto error; ++ } ++ cdev_init(&mdio_cdev, &mdio_fops); ++ ret = cdev_add(&mdio_cdev, mdio_dev, 1); ++ if (ret) { ++ printk(KERN_ERR "Fail to add mdio char dev!\n"); ++ goto error_region; ++ } ++ ++ return 0; ++ ++error_region: ++ unregister_chrdev_region(mdio_dev, 1); ++error: ++ kfree(mdio); ++ return ret; ++} ++ ++void ++ccb_mii_exit(void) ++{ ++ mdio_info_t *mdio=NULL; ++ ++ /* Get register base address */ ++ if (baseAddr) { ++ iounmap(baseAddr); ++ baseAddr = NULL; ++ } ++ ++ mdio = mdio_devices.mdio; ++ kfree(mdio); ++ ++ mdio_devices.mdio = NULL; ++ mdio_devices.init = 0; ++ unregister_chrdev_region(MKDEV(mdio_major, 0), 1); ++ ++} ++ ++module_init(ccb_mii_init); ++module_exit(ccb_mii_exit); ++ ++EXPORT_SYMBOL(ccb_mii_init); ++EXPORT_SYMBOL(ccb_mii_freq_set); ++EXPORT_SYMBOL(ccb_mii_read); ++EXPORT_SYMBOL(ccb_mii_write); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_DESCRIPTION("BCM5301X MDIO Device Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/mdio/iproc_mdio.h b/drivers/bcmdrivers/mdio/iproc_mdio.h +new file mode 100755 +index 0000000..2356ce6 +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/iproc_mdio.h +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef _bcm5301x_ccb_mii_h_ ++#define _bcm5301x_ccb_mii_h_ ++ ++#include ++ ++typedef struct _mdio_info_s { ++ void *h; /* dev handle */ ++ spinlock_t lock; ++} mdio_info_t; ++ ++/* reutrn value for MII driver */ ++#define MII_ERR_NONE 0 ++#define MII_ERR_TIMEOUT -1 ++#define MII_ERR_INTERNAL -2 ++#define MII_ERR_PARAM -3 ++#define MII_ERR_UNAVAIL -4 ++#define MII_ERR_UNKNOW -5 ++#define MII_ERR_INIT -6 ++ ++/* device type */ ++#define MII_DEV_LOCAL 0 ++#define MII_DEV_EXT 1 ++ ++/* MII register definition */ ++#define MII_MGMT 0x18003000 ++#define MII_MGMT_BASE 0x000 ++#define MII_MGMT_DATAMASK 0x000007ff ++#define MII_CMD_DATA 0x18003004 ++#define MII_CMD_DATA_BASE 0x004 ++#define MII_CMD_DATA_DATAMASK 0xffffffff ++ ++/* fields in MII_MGMT */ ++#define MII_MGMT_BYP_MASK 0x00000400 ++#define MII_MGMT_BYP_SHIFT 10 ++#define MII_MGMT_EXP_MASK 0x00000200 ++#define MII_MGMT_EXP_SHIFT 9 ++#define MII_MGMT_BSY_MASK 0x00000100 ++#define MII_MGMT_BSY_SHIFT 8 ++#define MII_MGMT_PRE_MASK 0x00000080 ++#define MII_MGMT_PRE_SHIFT 7 ++#define MII_MGMT_MDCDIV_MASK 0x0000007f ++#define MII_MGMT_MDCDIV_SHIFT 0 ++/* fields in MII_CMD_DATA */ ++#define MII_CMD_DATA_SB_MASK 0xc0000000 ++#define MII_CMD_DATA_SB_SHIFT 30 ++#define MII_CMD_DATA_OP_MASK 0x30000000 ++#define MII_CMD_DATA_OP_SHIFT 28 ++#define MII_CMD_DATA_PA_MASK 0x0f800000 ++#define MII_CMD_DATA_PA_SHIFT 23 ++#define MII_CMD_DATA_RA_MASK 0x007c0000 ++#define MII_CMD_DATA_RA_SHIFT 18 ++#define MII_CMD_DATA_TA_MASK 0x00030000 ++#define MII_CMD_DATA_TA_SHIFT 16 ++#define MII_CMD_DATA_DATA_MASK 0x0000ffff ++#define MII_CMD_DATA_DATA_SHIFT 0 ++ ++ ++/* external functions for SPI driver */ ++extern int ccb_mii_read(int dev_type, int phy_addr, int reg_off, uint16_t *data); ++extern int ccb_mii_write(int dev_type, int phy_addr, int reg_off, uint16_t data); ++ ++extern int ccb_mii_freq_set(int speed_khz); ++extern int ccb_mii_init(void); ++ ++#endif /* _bcm5301x_ccb_mii_h_ */ +diff --git a/drivers/bcmdrivers/mdio/iproc_mdio_dev.h b/drivers/bcmdrivers/mdio/iproc_mdio_dev.h +new file mode 100755 +index 0000000..fcf080a +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/iproc_mdio_dev.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef _IPROC_MDIO_DEV_H ++#define _IPROC_MDIO_DEV_H ++ ++/* IOCTL commands */ ++ ++#define MDIO_IOC_MAGIC 'm' ++ ++struct mdio_ioc_transfer { ++ uint8_t pa; /* phy address */ ++ uint8_t ra; /* register address */ ++ uint16_t tx_buf; ++ uint16_t rx_buf; ++}; ++ ++#define MDIO_MSGSIZE(N) \ ++ ((((N)*(sizeof (struct mdio_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \ ++ ? ((N)*(sizeof (struct mdio_ioc_transfer))) : 0) ++ ++#define MDIO_IOC_MESSAGE(N) _IOW(MDIO_IOC_MAGIC, 0, char[MDIO_MSGSIZE(N)]) ++ ++#define MDIO_IOC_EXTERNAL_R_REG _IOWR(MDIO_IOC_MAGIC, 0, char[MDIO_MSGSIZE(1)]) ++#define MDIO_IOC_EXTERNAL_W_REG _IOW(MDIO_IOC_MAGIC, 1, char[MDIO_MSGSIZE(1)]) ++#define MDIO_IOC_LOCAL_R_REG _IOWR(MDIO_IOC_MAGIC, 2, char[MDIO_MSGSIZE(1)]) ++#define MDIO_IOC_LOCAL_W_REG _IOW(MDIO_IOC_MAGIC, 3, char[MDIO_MSGSIZE(1)]) ++ ++ ++#endif +diff --git a/drivers/bcmdrivers/nand/.gitignore b/drivers/bcmdrivers/nand/.gitignore +new file mode 100644 +index 0000000..26ea8be +--- /dev/null ++++ b/drivers/bcmdrivers/nand/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order ++/.iproc_mtd_nand.o.cmd ++/.nand_iproc.o.cmd ++/iproc_mtd_nand.o ++/nand_iproc.o +diff --git a/drivers/bcmdrivers/nand/Kconfig b/drivers/bcmdrivers/nand/Kconfig +new file mode 100644 +index 0000000..1cd1050 +--- /dev/null ++++ b/drivers/bcmdrivers/nand/Kconfig +@@ -0,0 +1,24 @@ ++menuconfig IPROC_MTD_NAND ++ tristate "NAND support" ++ depends on ARCH_IPROC ++ select MTD ++ select MTD_NAND ++ default n ++ help ++ This selects a driver for the iProc NAND Controller. ++ ++ If unsure, say N. ++ ++if IPROC_MTD_NAND ++ ++config IPROC_MTD_NAND_USE_JFFS2 ++ bool "Use JFFS2 on NAND" ++ default n ++ help ++ Enable this if JFFS2 will be used on NAND. This is to solve compatibility ++ issue for the NAND controller to work with JFFS2 (with some performance ++ degrade). ++ ++ If unsure, say N. ++ ++endif # IPROC_MTD_NAND +diff --git a/drivers/bcmdrivers/nand/Makefile b/drivers/bcmdrivers/nand/Makefile +new file mode 100644 +index 0000000..5d2b01d +--- /dev/null ++++ b/drivers/bcmdrivers/nand/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_IPROC_MTD_NAND) += iproc_mtd_nand.o ++iproc_mtd_nand-objs := nand_iproc.o +diff --git a/drivers/bcmdrivers/nand/nand_iproc.c b/drivers/bcmdrivers/nand/nand_iproc.c +new file mode 100644 +index 0000000..f4b5d90 +--- /dev/null ++++ b/drivers/bcmdrivers/nand/nand_iproc.c +@@ -0,0 +1,1733 @@ ++ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "../../mtd/mtdcore.h" ++ ++/* ++ * Current version of NAND controller includes spare area for ECC calculation. ++ * This is not what some file system (eg. JFFS2) expects because they could ++ * write OOB first and data later. Thus we need to do some special handling. ++ */ ++#ifdef CONFIG_IPROC_MTD_NAND_USE_JFFS2 ++#define NAND_MTD_WRITE_OOB_SEPARATELY ++#endif /* CONFIG_IPROC_MTD_NAND_USE_JFFS2 */ ++#define NAND_REPORT_ECC_UNCORR_ERRORS ++ ++/* ++ * This flag controls if WP stays on between erase/write ++ * commands to mitigate flash corruption due to power glitches. Values: ++ * 0: NAND_WP is not used or not available ++ * 1: NAND_WP is set by default, cleared for erase/write operations ++ * 2: NAND_WP is always cleared ++ */ ++static int wp_on = 1; ++module_param(wp_on, int, 0444); ++ ++/*********************************************************************** ++ * Definitions ++ ***********************************************************************/ ++ ++#ifdef IPROC_NAND_DEBUG ++#define DBG(args...) printk(args) ++#else ++#define DBG(args...) do { } while(0) ++#endif ++ ++/* ++ * Controller/driver specific ++ */ ++#define DRV_NAME "nand_iproc" ++#define MAX_CONTROLLER_OOB 64 ++ ++/* ++ * NAND flash commands ++ */ ++#define CMD_PAGE_READ 0x01 ++#define CMD_SPARE_AREA_READ 0x02 ++#define CMD_STATUS_READ 0x03 ++#define CMD_PROGRAM_PAGE 0x04 ++#define CMD_PROGRAM_SPARE_AREA 0x05 ++#define CMD_COPY_BACK 0x06 ++#define CMD_DEVICE_ID_READ 0x07 ++#define CMD_BLOCK_ERASE 0x08 ++#define CMD_FLASH_RESET 0x09 ++#define CMD_BLOCKS_LOCK 0x0a ++#define CMD_BLOCKS_LOCK_DOWN 0x0b ++#define CMD_BLOCKS_UNLOCK 0x0c ++#define CMD_READ_BLOCKS_LOCK_STATUS 0x0d ++#define CMD_PARAMETER_READ 0x0e ++#define CMD_PARAMETER_CHANGE_COL 0x0f ++#define CMD_LOW_LEVEL_OP 0x10 ++ ++/* ++ * NAND controller register offset ++ */ ++#define NCREG_REVISION 0x000 /* Revision */ ++#define NCREG_CMD_START 0x004 /* Flash Command Start */ ++#define NCREG_CMD_EXT_ADDRESS 0x008 /* Flash Command Extended Address */ ++#define NCREG_CMD_ADDRESS 0x00c /* Flash Command Address */ ++#define NCREG_CMD_END_ADDRESS 0x010 /* Flash Command End Address */ ++#define NCREG_INTFC_STATUS 0x014 /* Flash Interface Status */ ++#define NCREG_CS_NAND_SELECT 0x018 /* Flash EBI CS Select */ ++#define NCREG_CS_NAND_XOR 0x01c /* Flash EBI CS Address XOR with 1FC0 Control */ ++#define NCREG_LL_OP 0x020 /* Flash Low Level Operation */ ++#define NCREG_MPLANE_BASE_EXT_ADDRESS 0x024 /* Flash Multiplane base address */ ++#define NCREG_MPLANE_BASE_ADDRESS 0x028 /* Flash Multiplane base address */ ++#define NCREG_ACC_CONTROL_CS0 0x050 /* Flash Access Control */ ++#define NCREG_CONFIG_CS0 0x054 /* Flash Config */ ++#define NCREG_TIMING_1_CS0 0x058 /* Flash Timing Parameters 1 */ ++#define NCREG_TIMING_2_CS0 0x05c /* Flash Timing Parameters 2 */ ++#define NCREG_ACC_CONTROL_CS1 0x060 /* Flash Access Control */ ++#define NCREG_CONFIG_CS1 0x064 /* Flash Config */ ++#define NCREG_TIMING_1_CS1 0x068 /* Flash Timing Parameters 1 */ ++#define NCREG_TIMING_2_CS1 0x06c /* Flash Timing Parameters 2 */ ++#define NCREG_ACC_CONTROL_CS2 0x070 /* Flash Access Control */ ++#define NCREG_CONFIG_CS2 0x074 /* Flash Config */ ++#define NCREG_TIMING_1_CS2 0x078 /* Flash Timing Parameters 1 */ ++#define NCREG_TIMING_2_CS2 0x07c /* Flash Timing Parameters 2 */ ++#define NCREG_CORR_STAT_THRESHOLD 0x0c0 /* Correctable Error Reporting Threshold */ ++#define NCREG_BLK_WR_PROTECT 0x0c8 /* Block Write Protect Enable and Size for EBI_CS0b */ ++#define NCREG_MULTIPLANE_OPCODES_1 0x0cc /* Flash Multiplane Customerized Opcodes */ ++#define NCREG_MULTIPLANE_OPCODES_2 0x0d0 /* Flash Multiplane Customerized Opcodes */ ++#define NCREG_MULTIPLANE_CTRL 0x0d4 /* Flash Multiplane Control */ ++#define NCREG_UNCORR_ERROR_COUNT 0x0fc /* Read Uncorrectable Event Count */ ++#define NCREG_CORR_ERROR_COUNT 0x100 /* Read Error Count */ ++#define NCREG_READ_ERROR_COUNT 0x104 /* Read Error Count */ ++#define NCREG_BLOCK_LOCK_STATUS 0x108 /* Flash Block Lock Status */ ++#define NCREG_ECC_CORR_EXT_ADDR 0x10c /* ECC Correctable Error Extended Address */ ++#define NCREG_ECC_CORR_ADDR 0x110 /* ECC Correctable Error Address */ ++#define NCREG_ECC_UNC_EXT_ADDR 0x114 /* ECC Uncorrectable Error Extended Address */ ++#define NCREG_ECC_UNC_ADDR 0x118 /* ECC Uncorrectable Error Address */ ++#define NCREG_FLASH_READ_EXT_ADDR 0x11c /* Flash Read Data Extended Address */ ++#define NCREG_FLASH_READ_ADDR 0x120 /* Flash Read Data Address */ ++#define NCREG_PROGRAM_PAGE_EXT_ADDR 0x124 /* Page Program Extended Address */ ++#define NCREG_PROGRAM_PAGE_ADDR 0x128 /* Page Program Address */ ++#define NCREG_COPY_BACK_EXT_ADDR 0x12c /* Copy Back Extended Address */ ++#define NCREG_COPY_BACK_ADDR 0x130 /* Copy Back Address */ ++#define NCREG_BLOCK_ERASE_EXT_ADDR 0x134 /* Block Erase Extended Address */ ++#define NCREG_BLOCK_ERASE_ADDR 0x138 /* Block Erase Address */ ++#define NCREG_INV_READ_EXT_ADDR 0x13c /* Flash Invalid Data Extended Address */ ++#define NCREG_INV_READ_ADDR 0x140 /* Flash Invalid Data Address */ ++#define NCREG_INIT_STATUS 0x144 /* Initialization status */ ++#define NCREG_ONFI_STATUS 0x148 /* ONFI Status */ ++#define NCREG_ONFI_DEBUG_DATA 0x14c /* ONFI Debug Data */ ++#define NCREG_SEMAPHORE 0x150 /* Semaphore */ ++#define NCREG_FLASH_DEVICE_ID 0x194 /* Flash Device ID */ ++#define NCREG_FLASH_DEVICE_ID_EXT 0x198 /* Flash Extended Device ID */ ++#define NCREG_LL_RDDATA 0x19c /* Flash Low Level Read Data */ ++#define NCREG_SPARE_AREA_READ_OFS_0 0x200 /* Flash Spare Area Read Bytes */ ++#define NCREG_SPARE_AREA_WRITE_OFS_0 0x280 /* Flash Spare Area Write Bytes */ ++#define NCREG_FLASH_CACHE_BASE 0x400 /* Flash Cache Buffer Access */ ++ ++/* ++ * Required NAND controller register fields ++ */ ++#define NCFLD_CMD_START_OPCODE_SHIFT 24 ++#define NCFLD_INTFC_STATUS_FLASH_STATUS_MASK 0x000000FF ++#define NCFLD_CS_NAND_SELECT_AUTO_DEVID_CONFIG 0x40000000 ++#define NCFLD_CS_NAND_SELECT_WP 0x20000000 ++#define NCFLD_CS_NAND_SELECT_DIRECT_ACCESS_CS_MASK 0x000000FF ++#define NCFLD_CS_NAND_XOR_CS_MASK 0x000000FF ++#define NCFLD_CONFIG_CS0_BLOCK_SIZE_MASK 0x70000000 ++#define NCFLD_CONFIG_CS0_BLOCK_SIZE_SHIFT 28 ++#define NCFLD_CONFIG_CS0_DEVICE_SIZE_MASK 0x0f000000 ++#define NCFLD_CONFIG_CS0_DEVICE_SIZE_SHIFT 24 ++#define NCFLD_CONFIG_CS0_DEVICE_WIDTH_MASK 0x00800000 ++#define NCFLD_CONFIG_CS0_DEVICE_WIDTH_SHIFT 23 ++#define NCFLD_CONFIG_CS0_PAGE_SIZE_MASK 0x00300000 ++#define NCFLD_CONFIG_CS0_PAGE_SIZE_SHIFT 20 ++#define NCFLD_CONFIG_CS0_FUL_ADR_BYTES_MASK 0x00070000 ++#define NCFLD_CONFIG_CS0_FUL_ADR_BYTES_SHIFT 16 ++#define NCFLD_CONFIG_CS0_COL_ADR_BYTES_MASK 0x00007000 ++#define NCFLD_CONFIG_CS0_COL_ADR_BYTES_SHIFT 12 ++#define NCFLD_CONFIG_CS0_BLK_ADR_BYTES_MASK 0x00000700 ++#define NCFLD_CONFIG_CS0_BLK_ADR_BYTES_SHIFT 8 ++#define NCFLD_ACC_CONTROL_CS0_RD_ECC_EN_MASK 0x80000000 ++#define NCFLD_ACC_CONTROL_CS0_RD_ECC_EN_SHIFT 31 ++#define NCFLD_ACC_CONTROL_CS0_WR_ECC_EN_MASK 0x40000000 ++#define NCFLD_ACC_CONTROL_CS0_WR_ECC_EN_SHIFT 30 ++#define NCFLD_ACC_CONTROL_CS0_FAST_PGM_RDIN_MASK 0x10000000 ++#define NCFLD_ACC_CONTROL_CS0_FAST_PGM_RDIN_SHIFT 28 ++#define NCFLD_ACC_CONTROL_CS0_RD_ERASED_ECC_EN_MASK 0x08000000 ++#define NCFLD_ACC_CONTROL_CS0_RD_ERASED_ECC_EN_SHIFT 27 ++#define NCFLD_ACC_CONTROL_CS0_PARTIAL_PAGE_EN_MASK 0x04000000 ++#define NCFLD_ACC_CONTROL_CS0_PARTIAL_PAGE_EN_SHIFT 26 ++#define NCFLD_ACC_CONTROL_CS0_PAGE_HIT_EN_MASK 0x01000000 ++#define NCFLD_ACC_CONTROL_CS0_PAGE_HIT_EN_SHIFT 24 ++#define NCFLD_ACC_CONTROL_CS0_ECC_LEVEL_MASK 0x001f0000 ++#define NCFLD_ACC_CONTROL_CS0_ECC_LEVEL_SHIFT 16 ++#define NCFLD_ACC_CONTROL_CS0_SECTOR_SIZE_1K_MASK 0x00000080 ++#define NCFLD_ACC_CONTROL_CS0_SECTOR_SIZE_1K_SHIFT 7 ++#define NCFLD_ACC_CONTROL_CS0_SPARE_AREA_SIZE_MASK 0x0000007f ++#define NCFLD_ACC_CONTROL_CS0_SPARE_AREA_SIZE_SHIFT 0 ++#define NCFLD_CORR_STAT_THRESHOLD_CS0_MASK 0x0000003f ++#define NCFLD_CORR_STAT_THRESHOLD_CS0_SHIFT 0 ++#define NCFLD_CORR_STAT_THRESHOLD_CS1_MASK 0x00000fc0 ++#define NCFLD_CORR_STAT_THRESHOLD_CS1_SHIFT 6 ++ ++/* ++ * IDM register base (for interrupts) ++ */ ++#define IDMREG_NAND_IO_CONTROL_DIRECT 0x00000000 ++ ++/* ++ * Required IDM NAND IO Control register fields ++ */ ++#define IDMFLD_NAND_IO_CONTROL_DIRECT_AXI_BE_MODE (1UL << 28) ++#define IDMFLD_NAND_IO_CONTROL_DIRECT_APB_LE_MODE (1UL << 24) ++#define IDMFLD_NAND_IO_CONTROL_DIRECT_IRQ_SHIFT 2 ++ ++/* ++ * Interrupts ++ */ ++#define NCINTR_NP_READ 0 ++#define NCINTR_BLKERA 1 ++#define NCINTR_CPYBK 2 ++#define NCINTR_PGMPG 3 ++#define NCINTR_CTLRDY 4 ++#define NCINTR_RBPIN 5 ++#define NCINTR_UNC 6 ++#define NCINTR_CORR 7 ++ ++/* 512B flash cache in the NAND controller HW */ ++#define FC_SHIFT 9U ++#define FC_BYTES 512U ++#define FC_WORDS (FC_BYTES >> 2) ++#define FC(x) (NCREG_FLASH_CACHE_BASE + ((x) << 2)) ++ ++/* ++ * Register access macros - generic ++ */ ++#define REG_RD(ptr) readl(ptr) ++#define REG_WR(ptr, val) writel(val, ptr) ++ ++/* ++ * Register access macros - NAND flash controller ++ */ ++#define NAND_REG_RD(x) REG_RD(ctrl.nand_regs + (x)) ++#define NAND_REG_WR(x, y) \ ++ do { REG_WR(ctrl.nand_regs + (x), (y)); } while(0) ++#define NAND_REG_UNSET(x, y) \ ++ do { NAND_REG_WR((x), NAND_REG_RD(x) & ~(y)); } while(0) ++#define NAND_REG_SET(x, y) \ ++ do { NAND_REG_WR((x), NAND_REG_RD(x) | (y)); } while(0) ++#define NAND_REG_WR_RB(x, y) \ ++ do { NAND_REG_WR((x), (y)); NAND_REG_RD(x); } while(0) ++#define NAND_REG_SET_RB(x, y) \ ++ do { NAND_REG_SET((x), (y)); NAND_REG_RD(x); } while(0) ++#define NAND_REG_UNSET_RB(x, y) \ ++ do { NAND_REG_UNSET((x), (y)); NAND_REG_RD(x); } while(0) ++ ++/* ++ * IRQ operations ++ */ ++ ++#define NAND_ENABLE_IRQ(bit) do { \ ++ REG_WR(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT, \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT) | \ ++ (1UL << ((bit) + IDMFLD_NAND_IO_CONTROL_DIRECT_IRQ_SHIFT)) \ ++ ); \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT); \ ++} while (0) ++ ++#define NAND_DISABLE_IRQ(bit) do { \ ++ REG_WR(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT, \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT) & \ ++ ~(1UL << ((bit) + IDMFLD_NAND_IO_CONTROL_DIRECT_IRQ_SHIFT)) \ ++ ); \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT); \ ++} while (0) ++ ++#define NAND_ACK_IRQ(bit) do { \ ++ REG_WR(((u32 *)ctrl.nand_intr_regs) + (bit), 1); \ ++ REG_RD(((u32 *)ctrl.nand_intr_regs) + (bit)); \ ++} while(0) ++ ++#define NAND_TEST_IRQ(bit) (REG_RD(((u32 *)ctrl.nand_intr_regs) + (bit)) & 1) ++ ++/* ++ * Data access macros for endianness ++ */ ++#ifdef __LITTLE_ENDIAN ++#define NAND_BEGIN_DATA_ACCESS() do { \ ++ REG_WR(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT, \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT) | \ ++ IDMFLD_NAND_IO_CONTROL_DIRECT_APB_LE_MODE \ ++ ); \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT); \ ++} while (0) ++ ++#define NAND_END_DATA_ACCESS() do { \ ++ REG_WR(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT, \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT) & \ ++ ~IDMFLD_NAND_IO_CONTROL_DIRECT_APB_LE_MODE \ ++ ); \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT); \ ++} while (0) ++#else /* !__LITTLE_ENDIAN */ ++#define NAND_BEGIN_DATA_ACCESS() do { } while (0) ++#define NAND_END_DATA_ACCESS() do { } while (0) ++#endif /* !__LITTLE_ENDIAN */ ++ ++/* ++ * Misc NAND controller configuration/status macros ++ */ ++ ++#define NC_REG_CONFIG(cs) (NCREG_CONFIG_CS0 + ((cs) << 4)) ++ ++#define WR_CONFIG(cs, field, val) do { \ ++ u32 reg = NC_REG_CONFIG(cs), contents = NAND_REG_RD(reg); \ ++ contents &= ~(NCFLD_CONFIG_CS0_##field##_MASK); \ ++ contents |= (val) << NCFLD_CONFIG_CS0_##field##_SHIFT; \ ++ NAND_REG_WR(reg, contents); \ ++} while(0) ++ ++#define RD_CONFIG(cs, field) \ ++ ((NAND_REG_RD(NC_REG_CONFIG(cs)) & NCFLD_CONFIG_CS0_##field##_MASK) \ ++ >> NCFLD_CONFIG_CS0_##field##_SHIFT) ++ ++#define NC_REG_ACC_CONTROL(cs) (NCREG_ACC_CONTROL_CS0 + ((cs) << 4)) ++ ++#define WR_ACC_CONTROL(cs, field, val) do { \ ++ u32 reg = NC_REG_ACC_CONTROL(cs), contents = NAND_REG_RD(reg); \ ++ contents &= ~(NCFLD_ACC_CONTROL_CS0_##field##_MASK); \ ++ contents |= (val) << NCFLD_ACC_CONTROL_CS0_##field##_SHIFT; \ ++ NAND_REG_WR(reg, contents); \ ++} while(0) ++ ++#define RD_ACC_CONTROL(cs, field) \ ++ ((NAND_REG_RD(NC_REG_ACC_CONTROL(cs)) & \ ++ NCFLD_ACC_CONTROL_CS0_##field##_MASK) \ ++ >> NCFLD_ACC_CONTROL_CS0_##field##_SHIFT) ++ ++#define CORR_ERROR_COUNT (NAND_REG_RD(NCREG_CORR_ERROR_COUNT)) ++#define UNCORR_ERROR_COUNT (NAND_REG_RD(NCREG_UNCORR_ERROR_COUNT)) ++ ++#define WR_CORR_THRESH(cs, val) do { \ ++ u32 contents = NAND_REG_RD(NCREG_CORR_STAT_THRESHOLD); \ ++ u32 shift = NCFLD_CORR_STAT_THRESHOLD_CS1_SHIFT * (cs); \ ++ contents &= ~(NCFLD_CORR_STAT_THRESHOLD_CS0_MASK << shift); \ ++ contents |= ((val) & NCFLD_CORR_STAT_THRESHOLD_CS0_MASK) << shift; \ ++ NAND_REG_WR(NCREG_CORR_STAT_THRESHOLD, contents); \ ++} while(0) ++ ++/* ++ * Internal structures ++ */ ++struct iproc_nand_controller { ++ struct nand_hw_control controller; ++ int irq; ++ int cmd_pending; ++ struct completion done; ++ int boot_inited; ++ ++ volatile void *nand_regs; ++ volatile void *nand_intr_regs; ++ volatile void *idm_nand_regs; ++}; ++ ++struct iproc_nand_cfg { ++ u64 device_size; ++ unsigned int block_size; ++ unsigned int page_size; ++ unsigned int spare_area_size; ++ unsigned int device_width; ++ unsigned int col_adr_bytes; ++ unsigned int blk_adr_bytes; ++ unsigned int ful_adr_bytes; ++ unsigned int sector_size_1k; ++}; ++ ++struct iproc_nand_host { ++ u32 buf[FC_WORDS]; ++ struct nand_chip chip; ++ struct mtd_info mtd; ++ struct platform_device *pdev; ++ int cs; ++ unsigned int last_cmd; ++ unsigned int last_byte; ++ u64 last_addr; ++ struct iproc_nand_cfg hwcfg; ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ u16 eccpos; ++ u16 eccbytes; ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++}; ++ ++static struct nand_ecclayout iproc_nand_oob_layout; ++ ++struct iproc_nand_exception { ++ const char *name; ++ int id[7]; ++ int idlen; /* usable */ ++ unsigned int chipsize; /* MB */ ++ unsigned int writesize; /* B */ ++ unsigned int erasesize; /* B */ ++ unsigned int oobsize; /* B per page */ ++ int chipoptions; ++ int badblockpos; ++}; ++ ++/* ++ * Global variables ++ */ ++ ++static struct iproc_nand_controller ctrl; ++ ++static struct iproc_nand_exception iproc_exceptions_list[] = { ++ {"Micron MT29F8G08ABACA", ++ {0x2C, 0xD3, 0x90, 0xA6, 0x64, 0x00, 0x00}, ++ 5, 0x00400, 4096, 0x040000, 224}, ++ {"Micron MT29F16G08ABABA", ++ {0x2C, 0x48, 0x00, 0x26, 0x89, 0x00, 0x00}, ++ 5, 0x00800, 4096, 0x080000, 224}, ++ {"Micron MT29F16G08CBABA", ++ {0x2C, 0x48, 0x04, 0x46, 0x85, 0x00, 0x00}, ++ 5, 0x00800, 4096, 0x100000, 224}, ++ {"Micron MT29F16G08CBACA", ++ {0x2C, 0x48, 0x04, 0x4A, 0xA5, 0x00, 0x00}, ++ 5, 0x00800, 4096, 0x100000, 224}, ++ {"Micron MT29F16G08MAA", ++ {0x2C, 0xD5, 0x94, 0x3E, 0x74, 0x00, 0x00}, ++ 5, 0x00800, 4096, 0x080000, 218}, ++ {"Micron MT29F32G08CBACA", ++ {0x2C, 0x68, 0x04, 0x4A, 0xA9, 0x00, 0x00}, ++ 5, 0x01000, 4096, 0x100000, 224}, ++ {"Micron MT29F64G08CBAAA", ++ {0x2C, 0x88, 0x04, 0x4B, 0xA9, 0x00, 0x00}, ++ 5, 0x02000, 8192, 0x200000, 448}, ++ {"Micron MT29F256G08CJAAA", ++ {0x2C, 0xA8, 0x05, 0xCB, 0xA9, 0x00, 0x00}, ++ 5, 0x08000, 8192, 0x200000, 448}, ++ {NULL,} ++}; ++ ++/* Used for running nand_scan_ident without the built-in heuristics */ ++static struct nand_flash_dev iproc_empty_flash_table[] = { ++ {NULL,} ++}; ++ ++/* ECC bytes required per 512B */ ++static const uint8_t nand_iproc_ecc_levels[2] = { 18, 21 }; ++static const uint8_t nand_iproc_ecc_bytes[] = { ++ 0, 2, 4, 6, 7, 9, 11, 13, 14, 16, 18, 20, 21, 23, 25, ++ 27, /* or 3 if SPARE_AREA_SIZE == 16 && SECTOR_SIZE_1K == 0*/ ++ 28, 30, 32, 34, 35 ++}; ++ ++/* Strap settings */ ++struct nand_strap_type_t { ++ uint8_t sector_1k; ++ uint8_t ecclevel; ++ uint16_t spare_size; ++}; ++static const struct nand_strap_type_t nand_strap_types[] = { ++ { 0, 0, 16 }, ++ { 0, 15, 16 }, ++ { 0, 4, 16 }, ++ { 0, 8, 16 }, ++ { 0, 8, 27 }, ++ { 0, 12, 27 }, ++ { 1, 12, 27 }, ++ { 1, 15, 27 }, ++ { 1, 20, 45 }, ++}; ++static const uint32_t nand_strap_page_sizes[] = { 2048, 2048, 4096, 8192 }; ++ ++/*********************************************************************** ++ * Internal support functions ++ ***********************************************************************/ ++ ++static void ++iproc_nand_wp(struct mtd_info *mtd, int wp) ++{ ++ if (wp_on == 1) { ++ static int old_wp = -1; ++ if (old_wp != wp) { ++ DBG("%s: WP %s\n", __func__, wp ? "on" : "off"); ++ old_wp = wp; ++ } ++ if (wp) { ++ NAND_REG_SET_RB(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_WP); ++ } else { ++ NAND_REG_UNSET_RB(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_WP); ++ } ++ } ++} ++ ++/* Helper functions for reading and writing OOB registers */ ++static inline unsigned char ++oob_reg_read(int offs) ++{ ++ if (offs >= MAX_CONTROLLER_OOB) ++ return 0x77; ++ ++ return NAND_REG_RD(NCREG_SPARE_AREA_READ_OFS_0 + (offs & ~0x03)) ++ >> (24 - ((offs & 0x03) << 3)); ++} ++ ++static inline void ++oob_reg_write(int offs, unsigned long data) ++{ ++ if (offs >= MAX_CONTROLLER_OOB) ++ return; ++ ++ NAND_REG_WR(NCREG_SPARE_AREA_WRITE_OFS_0 + (offs & ~0x03), ++ data); ++} ++ ++/* ++ * read_oob_from_regs - read data from OOB registers ++ * @i: sub-page sector index ++ * @oob: buffer to read to ++ * @sas: spare area sector size (i.e., OOB size per FLASH_CACHE) ++ * @sector_1k: 1 for 1KiB sectors, 0 for 512B, other values are illegal ++ */ ++static int ++read_oob_from_regs(int i, u8 *oob, int sas, int sector_1k) ++{ ++ int tbytes = sas << sector_1k; ++ int j; ++ ++ /* Adjust OOB values for 1K sector size */ ++ if (sector_1k && (i & 0x01)) ++ tbytes = max(0, tbytes - MAX_CONTROLLER_OOB); ++ tbytes = min(tbytes, MAX_CONTROLLER_OOB); ++ ++ for (j = 0; j < tbytes; j++) ++ oob[j] = oob_reg_read(j); ++ return tbytes; ++} ++ ++/* ++ * write_oob_to_regs - write data to OOB registers ++ * @i: sub-page sector index ++ * @oob: buffer to write from ++ * @sas: spare area sector size (i.e., OOB size per FLASH_CACHE) ++ * @sector_1k: 1 for 1KiB sectors, 0 for 512B, other values are illegal ++ */ ++static int ++write_oob_to_regs(int i, const u8 *oob, int sas, int sector_1k) ++{ ++ int tbytes = sas << sector_1k; ++ int j; ++ ++ /* Adjust OOB values for 1K sector size */ ++ if (sector_1k && (i & 0x01)) ++ tbytes = max(0, tbytes - MAX_CONTROLLER_OOB); ++ tbytes = min(tbytes, MAX_CONTROLLER_OOB); ++ ++ for (j = 0; j < tbytes; j += 4) ++ oob_reg_write(j, ++ (oob[j + 0] << 24) | ++ (oob[j + 1] << 16) | ++ (oob[j + 2] << 8) | ++ (oob[j + 3] << 0)); ++ return tbytes; ++} ++ ++static irqreturn_t ++iproc_nand_irq(int irq, void *data) ++{ ++ if (NAND_TEST_IRQ(NCINTR_CTLRDY)) { ++ NAND_ACK_IRQ(NCINTR_CTLRDY); ++ if (ctrl.cmd_pending) { ++ /* ++ * If the direct access region (eg. 0x1c000000 on NS) is accessed, ++ * IRQ handler will also be called with NCINTR_CTLRDY asserted. ++ * Thus we need to filter these events by ctrl.cmd_pending, or ++ * ctrl.done will be mistakenly set and cause incorrect result for ++ * the following command. ++ * We actually should avoid direct access to the mapped region when ++ * NAND driver is running. ++ */ ++ complete(&ctrl.done); ++ } ++ return IRQ_HANDLED; ++ } ++ return IRQ_NONE; ++} ++ ++static void ++iproc_nand_send_cmd(int cmd) ++{ ++ DBG("%s: native cmd %d addr_lo 0x%lx\n", __func__, cmd,(unsigned long)NAND_REG_RD(NCREG_CMD_ADDRESS)); ++ BUG_ON(ctrl.cmd_pending != 0); ++ ctrl.cmd_pending = cmd; ++ mb(); ++ NAND_REG_WR(NCREG_CMD_START, cmd << NCFLD_CMD_START_OPCODE_SHIFT); ++} ++ ++/*********************************************************************** ++ * NAND MTD API: read/program/erase ++ ***********************************************************************/ ++ ++static void ++iproc_nand_cmd_ctrl(struct mtd_info *mtd, int dat, ++ unsigned int ctrl) ++{ ++ /* intentionally left blank */ ++} ++ ++static int ++iproc_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_host *host = chip->priv; ++ ++ DBG("%s: native cmd %d\n", __func__, ctrl.cmd_pending); ++ if (ctrl.cmd_pending && ++ wait_for_completion_timeout(&ctrl.done, HZ / 10) <= 0) { ++ dev_err(&host->pdev->dev, ++ "timeout waiting for command %u (%ld)\n", ++ host->last_cmd, (unsigned long)NAND_REG_RD(NCREG_CMD_START) >> 24); ++ dev_err(&host->pdev->dev, ++ "irq status %08lx, intfc status %08lx\n", ++ (unsigned long)NAND_TEST_IRQ(NCINTR_CTLRDY), ++ (unsigned long)NAND_REG_RD(NCREG_INTFC_STATUS)); ++ } ++ ctrl.cmd_pending = 0; ++ iproc_nand_wp(mtd, 1); ++ return NAND_REG_RD(NCREG_INTFC_STATUS) & ++ NCFLD_INTFC_STATUS_FLASH_STATUS_MASK; ++} ++ ++static void ++iproc_nand_cmdfunc(struct mtd_info *mtd, unsigned command, ++ int column, int page_addr) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_host *host = chip->priv; ++ u64 addr = (u64)page_addr << chip->page_shift; ++ int native_cmd = 0; ++ ++ if (command == NAND_CMD_READID ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) ++ || command == NAND_CMD_PARAM ++#endif ++ ) ++ addr = (u64)column; ++ ++ DBG("%s: cmd 0x%x addr 0x%llx\n", __func__, command,(unsigned long long)addr); ++ host->last_cmd = command; ++ host->last_byte = 0; ++ host->last_addr = addr; ++ ++ switch (command) { ++ case NAND_CMD_RESET: ++ native_cmd = CMD_FLASH_RESET; ++ break; ++ case NAND_CMD_STATUS: ++ native_cmd = CMD_STATUS_READ; ++ break; ++ case NAND_CMD_READID: ++ native_cmd = CMD_DEVICE_ID_READ; ++ break; ++ case NAND_CMD_READOOB: ++ native_cmd = CMD_SPARE_AREA_READ; ++ break; ++ case NAND_CMD_ERASE1: ++ native_cmd = CMD_BLOCK_ERASE; ++ iproc_nand_wp(mtd, 0); ++ break; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) ++ case NAND_CMD_PARAM: ++ native_cmd = CMD_PARAMETER_READ; ++ break; ++#endif ++ } ++ ++ if (!native_cmd) ++ return; ++ ++ NAND_REG_WR_RB(NCREG_CMD_EXT_ADDRESS, ++ (host->cs << 16) | ((addr >> 32) & 0xffff)); ++ NAND_REG_WR_RB(NCREG_CMD_ADDRESS, addr & 0xffffffff); ++ ++ iproc_nand_send_cmd(native_cmd); ++ iproc_nand_waitfunc(mtd, chip); ++} ++ ++static uint8_t ++iproc_nand_read_byte(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_host *host = chip->priv; ++ uint8_t ret = 0; ++ ++ switch (host->last_cmd) { ++ case NAND_CMD_READID: ++ if (host->last_byte < 4) ++ ret = NAND_REG_RD(NCREG_FLASH_DEVICE_ID) >> ++ (24 - (host->last_byte << 3)); ++ else if (host->last_byte < 8) ++ ret = NAND_REG_RD(NCREG_FLASH_DEVICE_ID_EXT) >> ++ (56 - (host->last_byte << 3)); ++ break; ++ ++ case NAND_CMD_READOOB: ++ ret = oob_reg_read(host->last_byte); ++ break; ++ ++ case NAND_CMD_STATUS: ++ ret = NAND_REG_RD(NCREG_INTFC_STATUS) & ++ NCFLD_INTFC_STATUS_FLASH_STATUS_MASK; ++ if (wp_on) { ++ /* Hide WP status from MTD */ ++ ret |= NAND_STATUS_WP; ++ } ++ break; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) ++ case NAND_CMD_PARAM: ++ if (host->last_byte < FC_BYTES) ++ ret = NAND_REG_RD(FC(host->last_byte >> 2)) >> ++ (24 - ((host->last_byte & 0x03) << 3)); ++ break; ++#endif ++ } ++ ++ DBG("%s: byte = 0x%02x\n", __func__, ret); ++ host->last_byte++; ++ ++ return ret; ++} ++ ++static void ++iproc_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) ++{ ++ int i; ++ ++ for (i = 0; i < len; i++, buf++) ++ *buf = iproc_nand_read_byte(mtd); ++} ++ ++/* Copied from nand_base.c to support custom iproc_check_exceptions() */ ++static void ++iproc_nand_erase_cmd(struct mtd_info *mtd, int page) ++{ ++ struct nand_chip *chip = mtd->priv; ++ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); ++} ++ ++/* ++ * Assumes proper CS is already set ++ */ ++static void ++iproc_nand_read_by_pio(struct mtd_info *mtd, ++ struct nand_chip *chip, u64 addr, unsigned int trans, ++ u32 *buf, u8 *oob) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ int i, j; ++ ++ for (i = 0; i < trans; i++, addr += FC_BYTES) { ++ NAND_REG_WR_RB(NCREG_CMD_ADDRESS, addr & 0xffffffff); ++ /* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */ ++ iproc_nand_send_cmd(CMD_PAGE_READ); ++ iproc_nand_waitfunc(mtd, chip); ++ ++ if (likely(buf)) { ++ NAND_BEGIN_DATA_ACCESS(); ++ for (j = 0; j < FC_WORDS; j++, buf++) ++ *buf = NAND_REG_RD(FC(j)); ++ NAND_END_DATA_ACCESS(); ++ } ++ ++ if (oob) ++ oob += read_oob_from_regs(i, oob, ++ mtd->oobsize / trans, host->hwcfg.sector_size_1k); ++ } ++} ++ ++static int ++iproc_nand_read(struct mtd_info *mtd, ++ struct nand_chip *chip, u64 addr, unsigned int trans, ++ u32 *buf, u8 *oob) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ u64 err_addr; ++ DBG("%s %llx -> %p\n", __func__, (unsigned long long)addr, buf); ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* If reading OOB only, don't enable ECC correction */ ++ if (!buf) { ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 0); ++ } ++ ++ /* We must read spare area to check false uncorrectable errors. */ ++ if (oob == NULL) { ++ oob = (u8 *)host->buf; ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ NAND_REG_WR_RB(NCREG_ECC_UNC_ADDR, 0); ++ NAND_REG_WR_RB(NCREG_ECC_CORR_ADDR, 0); ++ NAND_REG_WR_RB(NCREG_CMD_EXT_ADDRESS, ++ (host->cs << 16) | ((addr >> 32) & 0xffff)); ++ ++ iproc_nand_read_by_pio(mtd, chip, addr, trans, buf, oob); ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* Rollback ECC correction */ ++ if (!buf) { ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 1); ++ ++ /* No ECC correction was performed */ ++ return 0; ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ /* Check correctable errors */ ++ err_addr = NAND_REG_RD(NCREG_ECC_CORR_ADDR) | ++ ((u64)(NAND_REG_RD(NCREG_ECC_CORR_EXT_ADDR) & 0xffff) << 32); ++ if (err_addr) { ++ printk(KERN_DEBUG "%s: corrected error at 0x%llx\n", ++ DRV_NAME, (unsigned long long)err_addr); ++ mtd->ecc_stats.corrected += CORR_ERROR_COUNT; ++ /* NAND layer expects zero on ECC errors */ ++ return 0; ++ } ++ ++ /* Check uncorrectable errors */ ++ err_addr = NAND_REG_RD(NCREG_ECC_UNC_ADDR) | ++ ((u64)(NAND_REG_RD(NCREG_ECC_UNC_EXT_ADDR) & 0xffff) << 32); ++ if (err_addr != 0) { ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ int i; ++ ++ /* Check if ECC bytes are FFs. Only the first sector is required. */ ++ for(i=0; ieccbytes; i++) { ++ if (oob[host->eccpos + i] != 0xFF) { ++ break; ++ } ++ } ++ if (i == host->eccbytes) { ++ /* False alarm (the page was written with OOB only and ECC off) */ ++ return 0; ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++#ifdef NAND_REPORT_ECC_UNCORR_ERRORS ++ printk(KERN_WARNING "%s: uncorrectable error at 0x%llx\n", ++ DRV_NAME, (unsigned long long)err_addr); ++ mtd->ecc_stats.failed += UNCORR_ERROR_COUNT; ++#endif /* NAND_REPORT_ECC_UNCORR_ERRORS */ ++ ++ /* NAND layer expects zero on ECC errors */ ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static int ++iproc_nand_read_page(struct mtd_info *mtd, ++ struct nand_chip *chip, uint8_t *buf, int page) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ return iproc_nand_read(mtd, chip, host->last_addr, ++ mtd->writesize >> FC_SHIFT, (u32 *)buf, ++ (u8 *)chip->oob_poi); ++} ++ ++static int ++iproc_nand_read_page_raw(struct mtd_info *mtd, ++ struct nand_chip *chip, uint8_t *buf, int page) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ int ret; ++ ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 0); ++ ret = iproc_nand_read(mtd, chip, host->last_addr, ++ mtd->writesize >> FC_SHIFT, ++ (u32 *)buf, (u8 *)chip->oob_poi); ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 1); ++ return ret; ++} ++ ++static int ++iproc_nand_read_oob(struct mtd_info *mtd, ++ struct nand_chip *chip, int page, int sndcmd) ++{ ++ return iproc_nand_read(mtd, chip, (u64)page << chip->page_shift, ++ mtd->writesize >> FC_SHIFT, ++ NULL, (u8 *)chip->oob_poi); ++} ++ ++#ifdef NAND_BBT_USE_FLASH ++/* Patched MTD implementation */ ++static int ++iproc_nand_read_oob_raw(struct mtd_info *mtd, ++ struct nand_chip *chip, int page, int sndcmd) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 0); ++ iproc_nand_read(mtd, chip, (u64)page << chip->page_shift, ++ mtd->writesize >> FC_SHIFT, ++ NULL, (u8 *)chip->oob_poi); ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 1); ++ return 0; ++} ++#endif ++ ++static int ++iproc_nand_read_subpage(struct mtd_info *mtd, ++ struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, ++ uint8_t *bufpoi) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ return iproc_nand_read(mtd, chip, host->last_addr + data_offs, ++ readlen >> FC_SHIFT, (u32 *)bufpoi, NULL); ++} ++ ++static int ++iproc_nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, ++ int len) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_host *host = chip->priv; ++ unsigned int i, j; ++ int err; ++ u64 addr = host->last_addr; ++ u32 *src = (u32 *)buf, *dst; ++ ++ for (i = 0; i < (mtd->writesize >> FC_SHIFT); i++) { ++ err = iproc_nand_read(mtd, chip, addr, 1, host->buf, NULL); ++ ++ if (err) { ++ dev_info(&host->pdev->dev, ++ "verify failed at 0x%llx (error %d)\n", ++ (unsigned long long)addr, err); ++ return -EFAULT; ++ } ++ dst = host->buf; ++ ++ for (j = 0; j < FC_WORDS; j++, src++, dst++) ++ if (*src != le32_to_cpu(*dst)) { ++ dev_info(&host->pdev->dev, ++ "mismatch at 0x%llx (read %08lx, " ++ "expected %08lx)\n", ++ (unsigned long long)addr + (j << 2), ++ (unsigned long)*dst, ++ (unsigned long)*src); ++ return -EFAULT; ++ } ++ addr += FC_BYTES; ++ } ++ return 0; ++} ++ ++static int ++iproc_nand_write(struct mtd_info *mtd, ++ struct nand_chip *chip, u64 addr, const u32 *buf, u8 *oob) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ unsigned int i = 0, j, trans = mtd->writesize >> FC_SHIFT; ++ int status; ++ ++ DBG("%s %llx <- %p\n", __func__, (unsigned long long)addr, buf); ++ ++ if (unlikely((u32)buf & 0x03)) { ++ dev_warn(&host->pdev->dev, "unaligned buffer: %p\n", buf); ++ buf = (u32 *)((u32)buf & ~0x03); ++ } ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* Merge (AND) the new and old OOB data */ ++ if (oob) { ++ ++ u8 *oob0 = (u8 *)host->buf; ++ int i; ++ ++ /* Read the spare area from flash */ ++ iproc_nand_read(mtd, chip, addr, 8, NULL, oob0); ++ ++ /* AND them with new OOB data */ ++ for(i=0; ioobsize; i++) { ++ oob[i] &= oob0[i]; ++ } ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ NAND_REG_WR_RB(NCREG_CMD_EXT_ADDRESS, ++ (host->cs << 16) | ((addr >> 32) & 0xffff)); ++ ++ for (j = 0; j < MAX_CONTROLLER_OOB; j += 4) ++ oob_reg_write(j, 0xffffffff); ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* Disable ECC generation if writing OOB only */ ++ if (!buf) { ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 0); ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ for (; i < trans; i++, addr += FC_BYTES) { ++ ++ /* full address MUST be set before populating FC */ ++ NAND_REG_WR_RB(NCREG_CMD_ADDRESS, addr & 0xffffffff); ++ ++ if (buf) { ++ NAND_BEGIN_DATA_ACCESS(); ++ for (j = 0; j < FC_WORDS; j++, buf++) ++ NAND_REG_WR(FC(j), *buf); ++ NAND_END_DATA_ACCESS(); ++ } else if (oob) { ++ for (j = 0; j < FC_WORDS; j++) ++ NAND_REG_WR(FC(j), 0xffffffff); ++ } ++ ++ if (oob) { ++ oob += write_oob_to_regs(i, oob, mtd->oobsize / trans, ++ host->hwcfg.sector_size_1k); ++ } ++ ++ iproc_nand_wp(mtd, 0); ++ ++ /* we cannot use SPARE_AREA_PROGRAM when PARTIAL_PAGE_EN=0 */ ++ iproc_nand_send_cmd(CMD_PROGRAM_PAGE); ++ status = iproc_nand_waitfunc(mtd, chip); ++ ++ if (status & NAND_STATUS_FAIL) { ++ dev_info(&host->pdev->dev, "program failed at %llx\n", ++ (unsigned long long)addr); ++ return -EIO; ++ } ++ } ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* Rollback ECC generation */ ++ if (!buf) { ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 1); ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ return 0; ++} ++ ++static void ++iproc_nand_write_page(struct mtd_info *mtd, ++ struct nand_chip *chip, const uint8_t *buf) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ iproc_nand_write(mtd, chip, host->last_addr, (u32 *)buf, (u8 *)chip->oob_poi); ++} ++ ++static void ++iproc_nand_write_page_raw(struct mtd_info *mtd, ++ struct nand_chip *chip, const uint8_t *buf) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 0); ++ iproc_nand_write(mtd, chip, host->last_addr, (u32 *)buf, ++ (u8 *)chip->oob_poi); ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 1); ++} ++ ++static int ++iproc_nand_write_oob(struct mtd_info *mtd, ++ struct nand_chip *chip, int page) ++{ ++ return iproc_nand_write(mtd, chip, (u64)page << chip->page_shift, NULL, ++ (u8 *)chip->oob_poi); ++} ++ ++#ifdef NAND_BBT_USE_FLASH ++/* Patched MTD implementation */ ++static int ++iproc_nand_write_oob_raw(struct mtd_info *mtd, ++ struct nand_chip *chip, int page) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ int r; ++ ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 0); ++ r = iproc_nand_write(mtd, chip, (u64)page << chip->page_shift, NULL, ++ (u8 *)chip->oob_poi); ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 1); ++ return r; ++} ++#endif ++ ++ ++/*********************************************************************** ++ * Per-CS setup (1 NAND device) ++ ***********************************************************************/ ++ ++static const unsigned int block_sizes[] = { 8, 16, 128, 256, 512, 1024, 2048 }; ++static const unsigned int page_sizes[] = { 512, 2048, 4096, 8192 }; ++ ++static void ++iproc_nand_set_cfg(struct iproc_nand_host *host, ++ struct iproc_nand_cfg *cfg) ++{ ++ int i, found; ++ ++ for (i = 0, found = 0; i < ARRAY_SIZE(block_sizes); i++) ++ if ((block_sizes[i] << 10) == cfg->block_size) { ++ WR_CONFIG(host->cs, BLOCK_SIZE, i); ++ found = 1; ++ } ++ if (!found) ++ dev_warn(&host->pdev->dev, "invalid block size %u\n", ++ cfg->block_size); ++ ++ for (i = 0, found = 0; i < ARRAY_SIZE(page_sizes); i++) ++ if (page_sizes[i] == cfg->page_size) { ++ WR_CONFIG(host->cs, PAGE_SIZE, i); ++ found = 1; ++ } ++ if (!found) ++ dev_warn(&host->pdev->dev, "invalid page size %u\n", ++ cfg->page_size); ++ ++ if (fls64(cfg->device_size) < 23) ++ dev_warn(&host->pdev->dev, "invalid device size 0x%llx\n", ++ (unsigned long long)cfg->device_size); ++ ++ WR_CONFIG(host->cs, DEVICE_SIZE, fls64(cfg->device_size) - 23); ++ WR_CONFIG(host->cs, DEVICE_WIDTH, cfg->device_width == 16 ? 1 : 0); ++ WR_CONFIG(host->cs, COL_ADR_BYTES, cfg->col_adr_bytes); ++ WR_CONFIG(host->cs, BLK_ADR_BYTES, cfg->blk_adr_bytes); ++ WR_CONFIG(host->cs, FUL_ADR_BYTES, cfg->ful_adr_bytes); ++ ++ WR_ACC_CONTROL(host->cs, SPARE_AREA_SIZE, cfg->spare_area_size); ++ WR_ACC_CONTROL(host->cs, SECTOR_SIZE_1K, cfg->sector_size_1k); ++} ++ ++static void ++iproc_nand_get_cfg(struct iproc_nand_host *host, ++ struct iproc_nand_cfg *cfg) ++{ ++ cfg->block_size = RD_CONFIG(host->cs, BLOCK_SIZE); ++ cfg->device_size = (4ULL << 20) << RD_CONFIG(host->cs, DEVICE_SIZE); ++ cfg->page_size = RD_CONFIG(host->cs, PAGE_SIZE); ++ cfg->device_width = RD_CONFIG(host->cs, DEVICE_WIDTH) ? 16 : 8; ++ cfg->col_adr_bytes = RD_CONFIG(host->cs, COL_ADR_BYTES); ++ cfg->blk_adr_bytes = RD_CONFIG(host->cs, BLK_ADR_BYTES); ++ cfg->ful_adr_bytes = RD_CONFIG(host->cs, FUL_ADR_BYTES); ++ cfg->spare_area_size = RD_ACC_CONTROL(host->cs, SPARE_AREA_SIZE); ++ cfg->sector_size_1k = RD_ACC_CONTROL(host->cs, SECTOR_SIZE_1K); ++ ++ if (cfg->block_size < ARRAY_SIZE(block_sizes)) ++ cfg->block_size = block_sizes[cfg->block_size] << 10; ++ else ++ cfg->block_size = 128 << 10; ++ ++ if (cfg->page_size < ARRAY_SIZE(page_sizes)) ++ cfg->page_size = page_sizes[cfg->page_size]; ++ else ++ cfg->page_size = 2048; ++} ++ ++static void ++iproc_nand_print_cfg(char *buf, struct iproc_nand_cfg *cfg) ++{ ++ sprintf(buf, ++ "%lluMiB total, %uKiB blocks, %u%s pages, %uB OOB, %u-bit", ++ (unsigned long long)cfg->device_size >> 20, ++ cfg->block_size >> 10, ++ cfg->page_size >= 1024 ? cfg->page_size >> 10 : cfg->page_size, ++ cfg->page_size >= 1024 ? "KiB" : "B", ++ cfg->spare_area_size, cfg->device_width); ++} ++ ++static int __devinit ++iproc_nand_setup_dev( ++ struct iproc_nand_host *host, ++ struct brcmnand_platform_data *pd) ++{ ++ struct mtd_info *mtd = &host->mtd; ++ struct nand_chip *chip = &host->chip; ++ struct iproc_nand_cfg orig_cfg, new_cfg; ++ struct nand_oobfree *free = iproc_nand_oob_layout.oobfree; ++ char msg[128]; ++ unsigned int ecclevel; ++ ++ iproc_nand_get_cfg(host, &orig_cfg); ++ host->hwcfg = orig_cfg; ++ ++ memset(&new_cfg, 0, sizeof(new_cfg)); ++ new_cfg.device_size = mtd->size; ++ new_cfg.block_size = mtd->erasesize; ++ new_cfg.page_size = mtd->writesize; ++ new_cfg.spare_area_size = mtd->oobsize / (mtd->writesize >> FC_SHIFT); ++ new_cfg.device_width = (chip->options & NAND_BUSWIDTH_16) ? 16 : 8; ++ new_cfg.col_adr_bytes = 2; ++ ++ if (mtd->writesize > 512) ++ if (mtd->size >= (256 << 20)) ++ new_cfg.blk_adr_bytes = 3; ++ else ++ new_cfg.blk_adr_bytes = 2; ++ else ++ if (mtd->size >= (64 << 20)) ++ new_cfg.blk_adr_bytes = 3; ++ else ++ new_cfg.blk_adr_bytes = 2; ++ new_cfg.ful_adr_bytes = new_cfg.blk_adr_bytes + new_cfg.col_adr_bytes; ++ ++ /* Original ECC level */ ++ ecclevel = RD_ACC_CONTROL(host->cs, ECC_LEVEL); ++ ++ /* Check settings inherited from bootloader */ ++ if(ctrl.boot_inited) { ++ ++ /* Check basic device attributes first */ ++ int sz1k = orig_cfg.sector_size_1k? 1 : 0; ++ if (orig_cfg.device_size != new_cfg.device_size || ++ orig_cfg.block_size != new_cfg.block_size || ++ orig_cfg.page_size != new_cfg.page_size || ++ orig_cfg.device_width != new_cfg.device_width || ++ orig_cfg.col_adr_bytes != new_cfg.col_adr_bytes || ++ orig_cfg.blk_adr_bytes != new_cfg.blk_adr_bytes || ++ orig_cfg.ful_adr_bytes != new_cfg.ful_adr_bytes || ++ ecclevel == 0 || ecclevel >= nand_iproc_ecc_levels[sz1k] || ++ orig_cfg.spare_area_size > new_cfg.spare_area_size || ++ nand_iproc_ecc_bytes[ecclevel] > orig_cfg.spare_area_size) { ++ ++ ctrl.boot_inited = 0; ++ printk(KERN_INFO "%s: invalid bootloader settings\n", DRV_NAME); ++ ++ } else { ++ /* Bootloader has initialized the flash correctly. */ ++ new_cfg = orig_cfg; ++ iproc_nand_print_cfg(msg, &orig_cfg); ++ printk(KERN_INFO "%s: following bootloader settings\n", DRV_NAME); ++ printk(KERN_INFO "%s: %s\n", DRV_NAME, msg); ++ } ++ } ++ ++ /* Decide ECC settings ourselves if it's not initialized before */ ++ if (!ctrl.boot_inited) { ++ ++ /* Check if strap settings are valid */ ++ if (pd->strap_type > 0 && ++ nand_strap_page_sizes[pd->strap_page_size] == new_cfg.page_size && ++ nand_strap_types[pd->strap_type].spare_size <= mtd->writesize ) { ++ ++ /* It's valid, follow the strap settings */ ++ new_cfg.spare_area_size = nand_strap_types[pd->strap_type].spare_size; ++ new_cfg.sector_size_1k = nand_strap_types[pd->strap_type].sector_1k; ++ ecclevel = nand_strap_types[pd->strap_type].ecclevel; ++ if (pd->strap_page_size == 0) { ++ new_cfg.blk_adr_bytes = 2; ++ new_cfg.ful_adr_bytes = 4; ++ } else { ++ new_cfg.blk_adr_bytes = 3; ++ new_cfg.ful_adr_bytes = 5; ++ } ++ ++ iproc_nand_print_cfg(msg, &new_cfg); ++ printk(KERN_INFO "%s: following strap settings\n", DRV_NAME); ++ printk(KERN_INFO "%s: %s\n", DRV_NAME, msg); ++ ++ } else { ++ ++ /* ++ * Strap settings are not valid, decide the settings on our own ++ */ ++ ++ /* Trying to fit with available strap settings */ ++ new_cfg.spare_area_size = new_cfg.spare_area_size >= 27 ? 27 : 16; ++ new_cfg.sector_size_1k = 0; ++ if (new_cfg.spare_area_size == 27) { ++ ecclevel = 12; ++ new_cfg.sector_size_1k = (new_cfg.page_size >= 2048) ? 1 : 0; ++ } else if (chip->badblockpos == NAND_SMALL_BADBLOCK_POS) { ++ ecclevel = 4; ++ } else { ++ ecclevel = 8; ++ } ++ ++ iproc_nand_print_cfg(msg, &new_cfg); ++ printk(KERN_ERR "*ERROR* Invalid board strap settings for NAND!"); ++ printk(KERN_INFO "%s: overriding invalid strap settings\n", ++ DRV_NAME); ++ printk(KERN_INFO "%s: %s\n", DRV_NAME, msg); ++ } ++ ++ iproc_nand_set_cfg(host, &new_cfg); ++ host->hwcfg = new_cfg; ++ ++ WR_ACC_CONTROL(host->cs, ECC_LEVEL, ecclevel); ++ /* threshold = ceil(BCH-level * 0.75) */ ++ WR_CORR_THRESH(host->cs, ((ecclevel << new_cfg.sector_size_1k) ++ * 3 + 2) / 4); ++ ++ /* Account for 24-bit per 1024-byte ECC settings */ ++ if (new_cfg.sector_size_1k) ++ printk(KERN_INFO "%s: ECC set to BCH-%u (1KiB sector)\n", ++ DRV_NAME, ecclevel << 1); ++ else ++ printk(KERN_INFO "%s: ECC set to BCH-%u (512B sector)\n", ++ DRV_NAME, ecclevel); ++ } ++ ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 1); ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 1); ++ WR_ACC_CONTROL(host->cs, FAST_PGM_RDIN, 0); ++ WR_ACC_CONTROL(host->cs, RD_ERASED_ECC_EN, 0); ++ WR_ACC_CONTROL(host->cs, PARTIAL_PAGE_EN, 0); ++ WR_ACC_CONTROL(host->cs, PAGE_HIT_EN, 1); ++ ++ mb(); ++ ++ /* Adjust MTD oobsize according to the configuration */ ++ mtd->oobsize = new_cfg.spare_area_size * (mtd->writesize >> FC_SHIFT); ++ ++ /* Adjust ECC layout for storing usb OOB data */ ++ free->length = 0; ++ if (ecclevel < nand_iproc_ecc_levels[new_cfg.sector_size_1k]) { ++ ++ uint8_t steps = mtd->writesize >> FC_SHIFT; ++ uint8_t eccbytes = nand_iproc_ecc_bytes[ecclevel]; ++ ++ /* Special case: using Hamming code when ecclevel == 15 */ ++ if (ecclevel == 15) { ++ if (new_cfg.spare_area_size == 16 && !new_cfg.sector_size_1k) { ++ eccbytes = 3; ++ } ++ } ++ ++ /* These are not really used. We still prepare them for safety. */ ++ iproc_nand_oob_layout.eccbytes = eccbytes * steps; ++ chip->ecc.bytes = eccbytes; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) ++ chip->ecc.strength = ecclevel; ++#endif ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ host->eccpos = ++ (new_cfg.spare_area_size - eccbytes) << new_cfg.sector_size_1k; ++ host->eccbytes = eccbytes << new_cfg.sector_size_1k; ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ /* Create oobfree for storing user OOB data */ ++ if (new_cfg.spare_area_size > eccbytes) { ++ ++ unsigned int spare_size; ++ uint8_t i, cnt; ++ ++ spare_size = new_cfg.spare_area_size << new_cfg.sector_size_1k; ++ eccbytes <<= new_cfg.sector_size_1k; ++ steps >>= new_cfg.sector_size_1k; ++ if (steps > MTD_MAX_OOBFREE_ENTRIES) { ++ steps = MTD_MAX_OOBFREE_ENTRIES; ++ } ++ for(i=0, cnt=0; ioffset = i * spare_size; ++ free->length = 6; ++ ++ } else { ++ ++ /* BCH: ECC bytes at the bottom */ ++ free->offset = i * spare_size; ++ free->length = spare_size - eccbytes; ++ } ++ ++ /* Reserve the first two bytes of the page */ ++ if (i == 0) { ++ if (free->length <= 2) { ++ /* Don't claim this entry if less than 2 bytes */ ++ continue; ++ } ++ free->offset += 2; ++ free->length -= 2; ++ } ++ ++ if (eccbytes == 3) { ++ /* Hamming code: the 2nd free part */ ++ free++; ++ cnt++; ++ if (cnt < MTD_MAX_OOBFREE_ENTRIES) { ++ free->offset = i * spare_size + 9; ++ free->length = 7; ++ } else { ++ /* The structure limits us. */ ++ break; ++ } ++ } ++ ++ free++; ++ cnt++; ++ } ++ if (cnt < MTD_MAX_OOBFREE_ENTRIES) { ++ /* Terminater */ ++ free->length = 0; ++ } ++ ++ /* Print out oob space information */ ++ free = iproc_nand_oob_layout.oobfree; ++ if (free->length) { ++ spare_size = 0; ++ while(free->length) { ++ spare_size += free->length; ++ free++; ++ } ++ printk(KERN_INFO "%s: user oob per page: %u bytes (%u steps)\n", ++ DRV_NAME, spare_size, (int)steps); ++ } ++ } ++ } ++ ++ if (iproc_nand_oob_layout.oobfree[0].length == 0) { ++ printk(KERN_INFO "%s: no oob space available\n", DRV_NAME); ++ } ++ ++ return 0; ++} ++ ++static int ++iproc_check_exceptions(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_exception *list = iproc_exceptions_list; ++ int i; ++ u8 id_data[8]; ++ ++ /* ++ * run default nand_base initialization w/o built-in ID table; ++ * should return error, so we tell it to be "silent" ++ */ ++ chip->options |= NAND_SCAN_SILENT_NODEV; ++ nand_scan_ident(mtd, 1, iproc_empty_flash_table); ++ chip->options &= ~NAND_SCAN_SILENT_NODEV; ++ ++ /* Send the command for reading device ID */ ++ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); ++ ++ for (i = 0; i < 8; i++) ++ id_data[i] = chip->read_byte(mtd); ++ ++ for (; list->name != NULL; list++) { ++ for (i = 0; i < list->idlen; i++) ++ if (id_data[i] != list->id[i]) ++ break; ++ if (i == list->idlen) ++ break; ++ } ++ ++ if (!list->name) ++ return -ENODEV; ++ ++ chip->chipsize = (uint64_t)list->chipsize << 20; ++ mtd->size = chip->chipsize; ++ ++ mtd->erasesize = list->erasesize; ++ mtd->writesize = list->writesize; ++ mtd->oobsize = list->oobsize; ++ ++ chip->options |= list->chipoptions; ++ chip->badblockpos = list->badblockpos; ++ ++ /* The 3rd id byte holds MLC / multichip data */ ++ chip->cellinfo = id_data[2]; ++ ++ chip->numchips = 1; ++ ++ /* Calculate the address shift from the page size */ ++ chip->page_shift = ffs(mtd->writesize) - 1; ++ /* Convert chipsize to number of pages per chip -1. */ ++ chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; ++ ++ chip->bbt_erase_shift = chip->phys_erase_shift = ++ ffs(mtd->erasesize) - 1; ++ chip->chip_shift = fls64(chip->chipsize) - 1; ++ ++ chip->erase_cmd = iproc_nand_erase_cmd; ++ ++ printk(KERN_INFO "%s: heuristics exception detected, %s\n", ++ DRV_NAME, list->name); ++ return 0; ++} ++ ++static int __devinit ++iproc_nand_probe(struct platform_device *pdev) ++{ ++ struct brcmnand_platform_data *pd = pdev->dev.platform_data; ++ struct iproc_nand_host *host; ++ struct mtd_info *mtd; ++ struct nand_chip *chip; ++ int ret = 0; ++ ++#if defined(CONFIG_MTD_PARTITIONS) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)) ++ int nr_parts; ++ struct mtd_partition *parts; ++ const char *part_probe_types[] = { "cmdlinepart", NULL }; ++#endif ++ ++ DBG("%s: id %d cs %d\n", __func__, pdev->id, pd->chip_select); ++ ++ host = kzalloc(sizeof(*host), GFP_KERNEL); ++ if (!host) { ++ dev_err(&pdev->dev, "can't allocate memory\n"); ++ return -ENOMEM; ++ } ++ ++ host->cs = pd->chip_select; ++ ++ mtd = &host->mtd; ++ chip = &host->chip; ++ host->pdev = pdev; ++ dev_set_drvdata(&pdev->dev, host); ++ ++ chip->priv = host; ++ mtd->priv = chip; ++ mtd->name = dev_name(&pdev->dev); ++ mtd->owner = THIS_MODULE; ++ mtd->dev.parent = &pdev->dev; ++ ++ chip->IO_ADDR_R = (void *)0xdeadbeef; ++ chip->IO_ADDR_W = (void *)0xdeadbeef; ++ ++ chip->cmd_ctrl = iproc_nand_cmd_ctrl; ++ chip->cmdfunc = iproc_nand_cmdfunc; ++ chip->waitfunc = iproc_nand_waitfunc; ++ chip->read_byte = iproc_nand_read_byte; ++ chip->read_buf = iproc_nand_read_buf; ++ chip->verify_buf = iproc_nand_verify_buf; ++ ++ chip->ecc.mode = NAND_ECC_HW; ++ chip->ecc.size = 512; ++ chip->ecc.layout = &iproc_nand_oob_layout; ++ chip->ecc.read_page = (void *) iproc_nand_read_page; ++ chip->ecc.read_subpage = iproc_nand_read_subpage; ++ chip->ecc.write_page = (void *) iproc_nand_write_page; ++ chip->ecc.read_page_raw = (void *) iproc_nand_read_page_raw; ++ chip->ecc.write_page_raw = (void *) iproc_nand_write_page_raw; ++ ++#ifdef NAND_BBT_USE_FLASH ++ /* Patched MTD implementation */ ++ chip->ecc.write_oob_raw = iproc_nand_write_oob_raw; ++ chip->ecc.read_oob_raw = (void *) iproc_nand_read_oob_raw; ++#endif ++ ++ chip->ecc.read_oob = (void *) iproc_nand_read_oob; ++ chip->ecc.write_oob = iproc_nand_write_oob; ++ ++ chip->controller = &ctrl.controller; ++ ++ if (iproc_check_exceptions(mtd) && nand_scan_ident(mtd, 1, NULL)) { ++ ret = -ENXIO; ++ goto err1; ++ } ++ ++ chip->options |= NAND_NO_SUBPAGE_WRITE | NAND_SKIP_BBTSCAN; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) ++ chip->options |= NAND_NO_AUTOINCR; ++#endif ++ ++#ifdef NAND_BBT_USE_FLASH ++ /* patched MTD implementation */ ++ chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; ++#else /* Standard MTD implementation */ ++ chip->options |= NAND_USE_FLASH_BBT; ++#ifdef NAND_USE_FLASH_BBT_NO_OOB ++ chip->options |= NAND_USE_FLASH_BBT_NO_OOB; ++#endif /* NAND_USE_FLASH_BBT_NO_OOB */ ++#endif /* NAND_BBT_USE_FLASH */ ++ ++ if (iproc_nand_setup_dev(host, pd) || nand_scan_tail(mtd) || ++ chip->scan_bbt(mtd)) { ++ ret = -ENXIO; ++ goto err1; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) ++ mtd_device_parse_register(mtd, NULL, NULL, pd->parts, pd->nr_parts); ++#else ++#ifdef CONFIG_MTD_PARTITIONS ++ nr_parts = parse_mtd_partitions(mtd, part_probe_types, &parts, 0); ++ if (nr_parts <= 0) { ++ nr_parts = pd->nr_parts; ++ parts = pd->parts; ++ } ++ ++ if (nr_parts) ++ add_mtd_partitions(mtd, parts, nr_parts); ++ else ++#endif ++ add_mtd_device(mtd); ++#endif ++ ++ return 0; ++ ++err1: ++ kfree(host); ++ return ret; ++} ++ ++static int __devexit ++iproc_nand_remove(struct platform_device *pdev) ++{ ++ struct iproc_nand_host *host = dev_get_drvdata(&pdev->dev); ++ struct mtd_info *mtd = &host->mtd; ++ ++ nand_release(mtd); ++ dev_set_drvdata(&pdev->dev, NULL); ++ kfree(host); ++ ++ return 0; ++} ++ ++/*********************************************************************** ++ * Platform driver setup (per controller) ++ ***********************************************************************/ ++static struct platform_driver iproc_nand_driver = { ++ .probe = iproc_nand_probe, ++ .remove = __devexit_p(iproc_nand_remove), ++ .driver = { ++ .name = "nand_iproc", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init iproc_nand_init(void) ++{ ++ int err = -ENODEV; ++ ++ init_completion(&ctrl.done); ++ spin_lock_init(&ctrl.controller.lock); ++ init_waitqueue_head(&ctrl.controller.wq); ++ ctrl.cmd_pending = 0; ++ ctrl.boot_inited = 1; ++ ++ /* Initialize registers and IRQ */ ++ ctrl.nand_regs = ctrl.nand_intr_regs = ctrl.idm_nand_regs = NULL; ++ ctrl.nand_regs = (volatile void *)ioremap(NAND_NAND_FLASH_REV, 0x1000); ++ if (!ctrl.nand_regs) { ++ printk(KERN_ERR "%s: can't ioremap\n", DRV_NAME); ++ err = -EIO; ++ goto err; ++ } ++ ctrl.nand_intr_regs = ctrl.nand_regs + ++ (NAND_DIRECT_READ_RD_MISS - NAND_NAND_FLASH_REV); ++ ctrl.idm_nand_regs = (volatile void *)ioremap(IPROC_IDM_NAND_REG_BASE, 4); ++ if (!ctrl.idm_nand_regs) { ++ printk(KERN_ERR "%s: can't ioremap\n", DRV_NAME); ++ err = -EIO; ++ goto err; ++ } ++ ctrl.irq = IPROC_NAND_IRQ_START; ++ DBG("%s: nand_regs - %p\n", __func__, ctrl.nand_regs); ++ DBG("%s: nand_intr_regs - %p\n", __func__, ctrl.nand_intr_regs); ++ DBG("%s: idm_nand_regs - %p\n", __func__, ctrl.idm_nand_regs); ++ DBG("%s: irq - %d\n", __func__, ctrl.irq); ++ ++ /* If bootloader has initialized it, auto-config should be cleared */ ++ if (NAND_REG_RD(NCREG_CS_NAND_SELECT) & ++ NCFLD_CS_NAND_SELECT_AUTO_DEVID_CONFIG) { ++ ctrl.boot_inited = 0; ++ } ++ ++ /* Perform basic controller initialization */ ++ NAND_REG_UNSET(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_AUTO_DEVID_CONFIG); ++ NAND_REG_UNSET(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_DIRECT_ACCESS_CS_MASK); ++ NAND_REG_UNSET(NCREG_CS_NAND_XOR, NCFLD_CS_NAND_XOR_CS_MASK); ++ if (wp_on == 2) { ++ /* Permanently remove write-protection */ ++ NAND_REG_UNSET(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_WP); ++ } ++ ++ /* Attach IRQ handler */ ++ NAND_ACK_IRQ(NCINTR_CTLRDY); ++ NAND_ENABLE_IRQ(NCINTR_CTLRDY); ++ err = request_irq((unsigned int)ctrl.irq, iproc_nand_irq, 0, ++ DRV_NAME, &ctrl); ++ if (err < 0) { ++ printk(KERN_ERR "%s: unable to allocate IRQ (error %d)\n", DRV_NAME, err); ++ goto err; ++ } ++ ++ err = platform_driver_register(&iproc_nand_driver); ++ if (err < 0) { ++ printk(KERN_ERR "%s: can't register platform driver " ++ "(error %d)\n", DRV_NAME, err); ++ free_irq(ctrl.irq, &ctrl); ++ goto err; ++ } ++ ++ printk(KERN_INFO DRV_NAME ": NAND controller driver is loaded\n"); ++ return 0; ++ ++err: ++ NAND_DISABLE_IRQ(NCINTR_CTLRDY); ++ if (ctrl.idm_nand_regs) { ++ iounmap(ctrl.idm_nand_regs); ++ ctrl.idm_nand_regs = NULL; ++ } ++ ctrl.nand_intr_regs = NULL; ++ if (ctrl.nand_regs) { ++ iounmap(ctrl.nand_regs); ++ ctrl.nand_regs = NULL; ++ } ++ return err; ++} ++ ++static void __exit iproc_nand_exit(void) ++{ ++ platform_driver_unregister(&iproc_nand_driver); ++ free_irq(ctrl.irq, &ctrl); ++ NAND_DISABLE_IRQ(NCINTR_CTLRDY); ++ if (ctrl.idm_nand_regs) { ++ iounmap(ctrl.idm_nand_regs); ++ ctrl.idm_nand_regs = NULL; ++ } ++ ctrl.nand_intr_regs = NULL; ++ if (ctrl.nand_regs) { ++ iounmap(ctrl.nand_regs); ++ ctrl.nand_regs = NULL; ++ } ++} ++ ++module_init(iproc_nand_init); ++module_exit(iproc_nand_exit); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("NAND driver for iProc chips"); +diff --git a/drivers/bcmdrivers/pmu/.gitignore b/drivers/bcmdrivers/pmu/.gitignore +new file mode 100644 +index 0000000..af7303c +--- /dev/null ++++ b/drivers/bcmdrivers/pmu/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/.iproc_pmu.o.cmd ++/.iproc-pmu.o.cmd ++/built-in.o ++/iproc_pmu.o ++/iproc-pmu.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/pmu/Kconfig b/drivers/bcmdrivers/pmu/Kconfig +new file mode 100644 +index 0000000..8b09c0c +--- /dev/null ++++ b/drivers/bcmdrivers/pmu/Kconfig +@@ -0,0 +1,9 @@ ++ ++config IPROC_PMU ++ tristate "Iproc PMU support" ++ depends on ARCH_IPROC ++ default y ++ help ++ Iproc PMU support ++ This config provides kernel-side support for iProc PMU description. ++ Its generic driver is perf_event.c +diff --git a/drivers/bcmdrivers/pmu/Makefile b/drivers/bcmdrivers/pmu/Makefile +new file mode 100644 +index 0000000..b491218 +--- /dev/null ++++ b/drivers/bcmdrivers/pmu/Makefile +@@ -0,0 +1,8 @@ ++# iproc TDM support ++ ++EXTRA_CFLAGS += -I$(BCMDRIVERS_DIR)/gmac/src/include ++KBUILD_CFLAGS += -DBCMDRIVER -Dlinux ++ ++iproc_pmu-objs := iproc-pmu.o ++ ++obj-$(CONFIG_IPROC_PMU) += iproc_pmu.o +diff --git a/drivers/bcmdrivers/pmu/iproc-pmu.c b/drivers/bcmdrivers/pmu/iproc-pmu.c +new file mode 100644 +index 0000000..83e1aec +--- /dev/null ++++ b/drivers/bcmdrivers/pmu/iproc-pmu.c +@@ -0,0 +1,61 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * PMU device description to Iproc ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static struct resource iproc_pmu_resource = { ++ .start = BCM_INT_ID_IHOST_PMU, ++ .end = BCM_INT_ID_IHOST_PMU+1, ++ .flags = IORESOURCE_IRQ, ++}; ++ ++ ++static struct platform_device iproc_pmu_device = { ++ .name = "arm-pmu", ++ .id = ARM_PMU_DEVICE_CPU, ++ .dev = { ++ .init_name = "arm-pmu", ++ }, ++ .num_resources = 1, ++ .resource = &iproc_pmu_resource, ++}; ++ ++ ++static int __init iproc_pmu_init(void) ++{ ++ int ret; ++ printk(KERN_INFO "Registering iproc_pmu_device\n"); ++ ret = platform_device_register(&iproc_pmu_device); ++ return ret; ++} ++module_init(iproc_pmu_init); ++ ++ ++/* Module information */ ++MODULE_DESCRIPTION("IPROC PMU Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/pwm/.gitignore b/drivers/bcmdrivers/pwm/.gitignore +new file mode 100644 +index 0000000..6e1da9b +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/.iproc_pwm.o.cmd ++/.iproc_pwmc.o.cmd ++/built-in.o ++/iproc_pwm.o ++/iproc_pwmc.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/pwm/Kconfig b/drivers/bcmdrivers/pwm/Kconfig +new file mode 100644 +index 0000000..c3bf727 +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/Kconfig +@@ -0,0 +1,8 @@ ++config IPROC_PWM ++ tristate "PWM support" ++ depends on ARCH_IPROC ++ default n ++ help ++ Add PWM support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/pwm/Makefile b/drivers/bcmdrivers/pwm/Makefile +new file mode 100644 +index 0000000..18ac980 +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_PWM) += iproc_pwm.o ++iproc_pwm-objs := iproc_pwmc.o +diff --git a/drivers/bcmdrivers/pwm/iproc_pwmc.c b/drivers/bcmdrivers/pwm/iproc_pwmc.c +new file mode 100644 +index 0000000..4ea9255 +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/iproc_pwmc.c +@@ -0,0 +1,411 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 5) ++#include "iproc_pwmc_3x.c" ++#else ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++ ++#define IPROC_PWM_CHANNEL_CNT 4 ++#define PWM_PRESCALER_MAX 63 /* 6 bits field */ ++ ++ ++#define PWM_CTL_ENABLE_SHIFT (0) ++#define PWM_CTL_POLARITY_SHIFT (8) ++ ++#define PWM_PRESCALE_PWM3_PRESCALE_SHIFT (0) ++#define PWM_PRESCALE_PWM3_PRESCALE_MASK (0x0000003F) ++#define PWM_PRESCALE_PWM2_PRESCALE_SHIFT (6) ++#define PWM_PRESCALE_PWM2_PRESCALE_MASK (0x00000FC0) ++#define PWM_PRESCALE_PWM1_PRESCALE_SHIFT (12) ++#define PWM_PRESCALE_PWM1_PRESCALE_MASK (0x0003F000) ++#define PWM_PRESCALE_PWM0_PRESCALE_SHIFT (18) ++#define PWM_PRESCALE_PWM0_PRESCALE_MASK (0x00FC0000) ++ ++#define PWM_DUTY_HI_CNT0_SHIFT (0) ++#define PWM_DUTY_HI_CNT0_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT1_SHIFT (0) ++#define PWM_DUTY_HI_CNT1_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT2_SHIFT (0) ++#define PWM_DUTY_HI_CNT2_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT3_SHIFT (0) ++#define PWM_DUTY_HI_CNT3_MASK (0xFFFF) ++ ++#define PWM_PERIOD_CNT0_SHIFT (0) ++#define PWM_PERIOD_CNT0_MASK (0xFFFF) ++#define PWM_PERIOD_CNT1_SHIFT (0) ++#define PWM_PERIOD_CNT1_MASK (0xFFFF) ++#define PWM_PERIOD_CNT2_SHIFT (0) ++#define PWM_PERIOD_CNT2_MASK (0xFFFF) ++#define PWM_PERIOD_CNT3_SHIFT (0) ++#define PWM_PERIOD_CNT3_MASK (0xFFFF) ++ ++ ++struct pwm_reg_def { ++ u32 mask ; ++ u32 shift ; ++ u32 offset ; ++} ; ++ ++#define PWM_REG_DEF(c, m, s, a) \ ++ [c] = { \ ++ .mask = m, \ ++ .shift = s, \ ++ .offset = a \ ++ } ++ ++static const ++struct pwm_reg_def pwm_chan_pre_scaler_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_PRESCALE_PWM0_PRESCALE_MASK, ++ PWM_PRESCALE_PWM0_PRESCALE_SHIFT, CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(1, PWM_PRESCALE_PWM1_PRESCALE_MASK, ++ PWM_PRESCALE_PWM1_PRESCALE_SHIFT, CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(2, PWM_PRESCALE_PWM2_PRESCALE_MASK, ++ PWM_PRESCALE_PWM2_PRESCALE_SHIFT, CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(3, PWM_PRESCALE_PWM3_PRESCALE_MASK, ++ PWM_PRESCALE_PWM3_PRESCALE_SHIFT, CCB_PWM_PRESCALE_BASE), ++} ; ++ ++static const ++struct pwm_reg_def pwm_chan_period_cnt_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_PERIOD_CNT0_MASK, ++ PWM_PERIOD_CNT0_SHIFT, CCB_PWM_PERIOD_COUNT0_BASE), ++ PWM_REG_DEF(1, PWM_PERIOD_CNT1_MASK, ++ PWM_PERIOD_CNT1_SHIFT, CCB_PWM_PERIOD_COUNT1_BASE), ++ PWM_REG_DEF(2, PWM_PERIOD_CNT2_MASK, ++ PWM_PERIOD_CNT2_SHIFT, CCB_PWM_PERIOD_COUNT2_BASE), ++ PWM_REG_DEF(3, PWM_PERIOD_CNT3_MASK, ++ PWM_PERIOD_CNT3_SHIFT, CCB_PWM_PERIOD_COUNT3_BASE), ++} ; ++ ++static const ++struct pwm_reg_def pwm_chan_duty_cycle_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_DUTY_HI_CNT0_MASK, ++ PWM_DUTY_HI_CNT0_SHIFT, CCB_PWM_DUTY_HI_COUNT0_BASE), ++ PWM_REG_DEF(1, PWM_DUTY_HI_CNT1_MASK, ++ PWM_DUTY_HI_CNT1_SHIFT, CCB_PWM_DUTY_HI_COUNT1_BASE), ++ PWM_REG_DEF(2, PWM_DUTY_HI_CNT2_MASK, ++ PWM_DUTY_HI_CNT2_SHIFT, CCB_PWM_DUTY_HI_COUNT2_BASE), ++ PWM_REG_DEF(3, PWM_DUTY_HI_CNT3_MASK, ++ PWM_DUTY_HI_CNT3_SHIFT, CCB_PWM_DUTY_HI_COUNT3_BASE), ++} ; ++ ++ ++struct iproc_pwmc { ++ struct pwm_device *p[IPROC_PWM_CHANNEL_CNT]; ++ struct pwm_device_ops ops; ++ void __iomem *iobase; ++ struct clk *clk; ++}; ++ ++ ++static int iproc_get_chan(const struct iproc_pwmc *ap, const struct pwm_device *p) ++{ ++ int chan; ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) ++ if (p == ap->p[chan]) ++ return chan; ++ BUG(); ++ return 0; ++} ++ ++static void iproc_pwmc_clear_set_bit(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int shift, unsigned char en_dis) ++{ ++ unsigned long val = readl(ap->iobase + offset ) ; ++ ++ // Clear bit. ++ clear_bit(shift,&val) ; ++ if ( en_dis == 1 ) ++ set_bit(shift,&val); ++ ++ writel(val, (ap->iobase + offset )); ++} ++ ++ ++static void iproc_pwmc_set_field(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int mask, unsigned int shift, unsigned int wval) ++{ ++ unsigned int val = readl(ap->iobase + offset ) ; ++ ++ val = (val & ~mask) | ( wval << shift ) ; ++ writel(val, (ap->iobase + offset )); ++} ++ ++static void iproc_pwmc_get_field(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int mask, unsigned int shift, unsigned int *val) ++{ ++ *val = readl(ap->iobase + offset ) ; ++ *val = ( *val & mask ) >> shift ; ++} ++ ++ ++static void iproc_pwmc_start(const struct iproc_pwmc *ap, int chan) ++{ ++ ++ iproc_pwmc_clear_set_bit(ap, CCB_PWM_CTL_BASE, ++ (PWM_CTL_ENABLE_SHIFT + chan), 1) ; ++} ++ ++static void iproc_pwmc_stop(const struct iproc_pwmc *ap, int chan) ++{ ++ ++ iproc_pwmc_clear_set_bit(ap, CCB_PWM_CTL_BASE, ++ (PWM_CTL_ENABLE_SHIFT + chan), 0) ; ++ ++ ++} ++static void iproc_pwmc_config_polarity(struct iproc_pwmc *ap, int chan, ++ struct pwm_config *c) ++{ ++ struct pwm_device *p = ap->p[chan]; ++ ++ if ( c->polarity ){ ++ iproc_pwmc_clear_set_bit(ap, CCB_PWM_CTL_BASE, ++ (PWM_CTL_POLARITY_SHIFT + chan), 1) ; ++ }else{ ++ iproc_pwmc_clear_set_bit(ap, CCB_PWM_CTL_BASE, ++ (PWM_CTL_POLARITY_SHIFT + chan), 0) ; ++ } ++ p->polarity = c->polarity ? 1 : 0; ++ ++ if (BIT(chan) & (readl(ap->iobase + CCB_PWM_CTL_BASE)&0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(ap, chan) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(ap, chan) ; ++ } ++ ++} ++ ++ ++static void iproc_pwmc_config_duty_ticks(struct iproc_pwmc *ap, int chan, ++ struct pwm_config *c) ++{ ++ struct pwm_device *p = ap->p[chan]; ++ unsigned int pre_scaler = 0 ; ++ unsigned int duty_cnt = 0 ; ++ ++ iproc_pwmc_get_field(ap, pwm_chan_pre_scaler_info[chan].offset, ++ pwm_chan_pre_scaler_info[chan].mask, pwm_chan_pre_scaler_info[chan].shift, ++ &pre_scaler) ; ++ ++ /* Read prescaler value from register. */ ++ duty_cnt = c->duty_ticks / (pre_scaler + 1) ; ++ ++ /* program duty cycle. */ ++ iproc_pwmc_set_field(ap, pwm_chan_duty_cycle_info[chan].offset, ++ pwm_chan_duty_cycle_info[chan].mask, ++ pwm_chan_duty_cycle_info[chan].shift, duty_cnt) ; ++ ++ if (BIT(chan) & (readl(ap->iobase + CCB_PWM_CTL_BASE)&0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(ap, chan) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(ap, chan) ; ++ } ++ p->duty_ticks = c->duty_ticks; ++ ++} ++ ++static int iproc_pwmc_config_period_ticks(struct iproc_pwmc *ap, int chan, ++ struct pwm_config *c) ++{ ++ unsigned int pcnt ; ++ unsigned char pre_scaler = 0 ; ++ struct pwm_device *p = ap->p[chan]; ++ ++ pre_scaler = c->period_ticks / 0xFFFF ; ++ if ( pre_scaler > PWM_PRESCALER_MAX ) ++ pre_scaler = PWM_PRESCALER_MAX ; ++ ++ pcnt = c->period_ticks / (pre_scaler + 1) ; ++ ++ /* programe prescaler */ ++ iproc_pwmc_set_field(ap, pwm_chan_pre_scaler_info[chan].offset, ++ pwm_chan_pre_scaler_info[chan].mask, ++ pwm_chan_pre_scaler_info[chan].shift, pre_scaler) ; ++ ++ /* program period count. */ ++ iproc_pwmc_set_field(ap, pwm_chan_period_cnt_info[chan].offset, ++ pwm_chan_period_cnt_info[chan].mask, ++ pwm_chan_period_cnt_info[chan].shift, pcnt) ; ++ if (BIT(chan) & (readl(ap->iobase + CCB_PWM_CTL_BASE)&0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(ap, chan) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(ap, chan) ; ++ } ++ ++ p->period_ticks = c->period_ticks; ++ ++ return 0; ++} ++ ++static int iproc_pwmc_request(struct pwm_device *p) ++{ ++ struct iproc_pwmc *ap = pwm_get_drvdata(p); ++ int chan = iproc_get_chan(ap, p); ++ ++ /* 1M */ ++ p->tick_hz = 1000000UL; ++ iproc_pwmc_stop(ap,chan); ++ ++ return 0; ++} ++ ++static int iproc_pwmc_config(struct pwm_device *p, struct pwm_config *c) ++{ ++ struct iproc_pwmc *ap = pwm_get_drvdata(p); ++ int chan = iproc_get_chan(ap, p); ++ int ret; ++ ++ if (test_bit(PWM_CONFIG_PERIOD_TICKS, &c->config_mask)) { ++ ret = iproc_pwmc_config_period_ticks(ap, chan, c); ++ if (ret) ++ return ret; ++ if (!test_bit(PWM_CONFIG_DUTY_TICKS, &c->config_mask)) { ++ struct pwm_config d = { ++ .config_mask = PWM_CONFIG_DUTY_TICKS, ++ .duty_ticks = p->duty_ticks, ++ }; ++ iproc_pwmc_config_duty_ticks(ap, chan, &d); ++ } ++ } ++ ++ if (test_bit(PWM_CONFIG_DUTY_TICKS, &c->config_mask)) ++ iproc_pwmc_config_duty_ticks(ap, chan, c); ++ ++ if (test_bit(PWM_CONFIG_POLARITY, &c->config_mask)) ++ iproc_pwmc_config_polarity(ap, chan, c); ++ ++ if (test_bit(PWM_CONFIG_START, &c->config_mask)) ++ iproc_pwmc_start(ap, chan); ++ ++ if (test_bit(PWM_CONFIG_STOP, &c->config_mask)) ++ iproc_pwmc_stop(ap, chan); ++ ++ return 0; ++} ++ ++ ++static const struct pwm_device_ops iproc_pwm_ops = { ++ .request = iproc_pwmc_request, ++ .config = iproc_pwmc_config, ++ .owner = THIS_MODULE, ++}; ++ ++ ++static int __devinit iproc_pwmc_probe(struct platform_device *pdev) ++{ ++ struct iproc_pwmc *ap; ++ struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ int chan; ++ int ret = 0; ++ ++ ap = kzalloc(sizeof(*ap), GFP_KERNEL); ++ if (!ap) { ++ ret = -ENOMEM; ++ goto err_iproc_pwmc_alloc; ++ } ++ ++ platform_set_drvdata(pdev, ap); ++ ++ ap->iobase = ioremap_nocache(r->start, resource_size(r)); ++ if (!ap->iobase) { ++ ret = -ENODEV; ++ goto err_ioremap; ++ } ++ printk(KERN_INFO "iproc_pwmc_probe iobase %p phys:%x\n", ++ ap->iobase,r->start); ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) { ++ ap->p[chan] = pwm_register(&iproc_pwm_ops, &pdev->dev, "%s:%d", ++ dev_name(&pdev->dev), chan); ++ if (IS_ERR_OR_NULL(ap->p[chan])) ++ goto err_pwm_register; ++ pwm_set_drvdata(ap->p[chan], ap); ++ } ++ ++ return 0; ++ ++err_pwm_register: ++ while (--chan > 0) ++ pwm_unregister(ap->p[chan]); ++ ++ iounmap(ap->iobase); ++err_ioremap: ++ platform_set_drvdata(pdev, NULL); ++ kfree(ap); ++err_iproc_pwmc_alloc: ++ printk(KERN_ERR "%s: error, returning %d\n", __func__, ret); ++return ret; ++} ++ ++static int __devexit iproc_pwmc_remove(struct platform_device *pdev) ++{ ++ struct iproc_pwmc *ap = platform_get_drvdata(pdev); ++ int chan; ++ ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) ++ pwm_unregister(ap->p[chan]); ++ ++ iounmap(ap->iobase); ++ ++ kfree(ap); ++ return 0; ++} ++ ++static struct platform_driver iproc_pwmc_driver = { ++ .driver = { ++ .name = "iproc_pwmc", ++ .owner = THIS_MODULE, ++ }, ++ .probe = iproc_pwmc_probe, ++ .remove = __devexit_p(iproc_pwmc_remove), ++}; ++ ++static int __init iproc_pwmc_init(void) ++{ ++ return platform_driver_register(&iproc_pwmc_driver); ++} ++ ++static void __exit iproc_pwmc_exit(void) ++{ ++ platform_driver_unregister(&iproc_pwmc_driver); ++} ++module_init(iproc_pwmc_init); ++module_exit(iproc_pwmc_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Driver for iProc PWMC"); ++MODULE_LICENSE("GPL"); ++ ++#endif +diff --git a/drivers/bcmdrivers/pwm/iproc_pwmc_3x.c b/drivers/bcmdrivers/pwm/iproc_pwmc_3x.c +new file mode 100644 +index 0000000..c410014 +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/iproc_pwmc_3x.c +@@ -0,0 +1,575 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#ifdef CONFIG_DEBUG_FS ++#include ++#endif ++ ++#include ++ ++ ++#define IPROC_PWM_CHANNEL_CNT 4 ++#define PWM_PRESCALER_MAX 63 /* 6 bits field */ ++ ++ ++#define PWM_CTL_ENABLE_SHIFT (0) ++#define PWM_CTL_POLARITY_SHIFT (8) ++ ++#define PWM_PRESCALE_PWM3_PRESCALE_SHIFT (0) ++#define PWM_PRESCALE_PWM3_PRESCALE_MASK (0x0000003F) ++#define PWM_PRESCALE_PWM2_PRESCALE_SHIFT (6) ++#define PWM_PRESCALE_PWM2_PRESCALE_MASK (0x00000FC0) ++#define PWM_PRESCALE_PWM1_PRESCALE_SHIFT (12) ++#define PWM_PRESCALE_PWM1_PRESCALE_MASK (0x0003F000) ++#define PWM_PRESCALE_PWM0_PRESCALE_SHIFT (18) ++#define PWM_PRESCALE_PWM0_PRESCALE_MASK (0x00FC0000) ++ ++#define PWM_DUTY_HI_CNT0_SHIFT (0) ++#define PWM_DUTY_HI_CNT0_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT1_SHIFT (0) ++#define PWM_DUTY_HI_CNT1_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT2_SHIFT (0) ++#define PWM_DUTY_HI_CNT2_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT3_SHIFT (0) ++#define PWM_DUTY_HI_CNT3_MASK (0xFFFF) ++ ++#define PWM_PERIOD_CNT0_SHIFT (0) ++#define PWM_PERIOD_CNT0_MASK (0xFFFF) ++#define PWM_PERIOD_CNT1_SHIFT (0) ++#define PWM_PERIOD_CNT1_MASK (0xFFFF) ++#define PWM_PERIOD_CNT2_SHIFT (0) ++#define PWM_PERIOD_CNT2_MASK (0xFFFF) ++#define PWM_PERIOD_CNT3_SHIFT (0) ++#define PWM_PERIOD_CNT3_MASK (0xFFFF) ++ ++ ++struct pwm_reg_def { ++ u32 mask ; ++ u32 shift ; ++ u32 offset ; ++} ; ++ ++#define PWM_REG_DEF(c, m, s, a) \ ++ [c] = { \ ++ .mask = m, \ ++ .shift = s, \ ++ .offset = a \ ++ } ++ ++static const ++struct pwm_reg_def pwm_chan_pre_scaler_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_PRESCALE_PWM0_PRESCALE_MASK, ++ PWM_PRESCALE_PWM0_PRESCALE_SHIFT, IPROC_CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(1, PWM_PRESCALE_PWM1_PRESCALE_MASK, ++ PWM_PRESCALE_PWM1_PRESCALE_SHIFT, IPROC_CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(2, PWM_PRESCALE_PWM2_PRESCALE_MASK, ++ PWM_PRESCALE_PWM2_PRESCALE_SHIFT, IPROC_CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(3, PWM_PRESCALE_PWM3_PRESCALE_MASK, ++ PWM_PRESCALE_PWM3_PRESCALE_SHIFT, IPROC_CCB_PWM_PRESCALE_BASE), ++} ; ++ ++static const ++struct pwm_reg_def pwm_chan_period_cnt_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_PERIOD_CNT0_MASK, ++ PWM_PERIOD_CNT0_SHIFT, IPROC_CCB_PWM_PERIOD_COUNT0_BASE), ++ PWM_REG_DEF(1, PWM_PERIOD_CNT1_MASK, ++ PWM_PERIOD_CNT1_SHIFT, IPROC_CCB_PWM_PERIOD_COUNT1_BASE), ++ PWM_REG_DEF(2, PWM_PERIOD_CNT2_MASK, ++ PWM_PERIOD_CNT2_SHIFT, IPROC_CCB_PWM_PERIOD_COUNT2_BASE), ++ PWM_REG_DEF(3, PWM_PERIOD_CNT3_MASK, ++ PWM_PERIOD_CNT3_SHIFT, IPROC_CCB_PWM_PERIOD_COUNT3_BASE), ++} ; ++ ++static const ++struct pwm_reg_def pwm_chan_duty_cycle_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_DUTY_HI_CNT0_MASK, ++ PWM_DUTY_HI_CNT0_SHIFT, IPROC_CCB_PWM_DUTY_HI_COUNT0_BASE), ++ PWM_REG_DEF(1, PWM_DUTY_HI_CNT1_MASK, ++ PWM_DUTY_HI_CNT1_SHIFT, IPROC_CCB_PWM_DUTY_HI_COUNT1_BASE), ++ PWM_REG_DEF(2, PWM_DUTY_HI_CNT2_MASK, ++ PWM_DUTY_HI_CNT2_SHIFT, IPROC_CCB_PWM_DUTY_HI_COUNT2_BASE), ++ PWM_REG_DEF(3, PWM_DUTY_HI_CNT3_MASK, ++ PWM_DUTY_HI_CNT3_SHIFT, IPROC_CCB_PWM_DUTY_HI_COUNT3_BASE), ++} ; ++ ++#ifdef CONFIG_DEBUG_FS ++struct iproc_pwm_config_debug_fs{ ++ struct dentry *period; ++ struct dentry *duty; ++ struct dentry *polarity; ++ struct dentry *run; ++}; ++#endif ++ ++struct iproc_pwm_config { ++ struct device *dev; ++ struct pwm_device *pwm; ++ int pwm_id; ++ int duty_ns; ++ int period_ns; ++ u32 duty_ticks; ++ u32 period_ticks; ++ u8 polarity; ++ int running; ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *debugfs_entry; ++ struct iproc_pwm_config_debug_fs config_entry; ++#endif ++ ++}; ++ ++ ++struct iproc_pwmc { ++ void __iomem *iobase; ++ unsigned long tick_hz; ++ struct pwm_chip chip; ++ struct iproc_pwm_config *config[IPROC_PWM_CHANNEL_CNT]; ++}; ++ ++ ++#ifdef CONFIG_DEBUG_FS ++static int __init iproc_pwmc_debugfs_init(void); ++void iproc_pwmc_debugfs_add_chan(struct iproc_pwmc *ap, int chan); ++ ++static struct dentry *debugfs_base; ++ ++static int _debug_pwm_config_set(void *data, u64 val) ++{ ++ struct iproc_pwm_config *config = data; ++ ++ if (val) { ++ iproc_pwmc_config_polarity(config->pwm->chip, config->pwm, config->polarity); ++ pwm_config(config->pwm, config->duty_ns, config->period_ns); ++ pwm_enable(config->pwm); ++ config->running = 1; ++ } else { ++ pwm_disable(config->pwm); ++ config->running = 0; ++ } ++ return 0; ++} ++static int _debug_pwm_config_get(void *data, u64 *val) ++{ ++ struct iproc_pwm_config *config = data; ++ ++ *val = config->running; ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(iproc_pwm_config_fop, _debug_pwm_config_get, ++ _debug_pwm_config_set, "%llu\n"); ++ ++static int _debug_pwm_export_set(void *data, u64 val) ++{ ++ ++ struct iproc_pwm_config *config = data; ++ struct pwm_device *pwm; ++ char pwm_id[16]; ++ ++ sprintf(pwm_id, "pwm-%d", config->pwm_id); ++ ++ if (val) { ++ pwm = pwm_get(config->dev,pwm_id); ++ config->pwm = pwm; ++ config->config_entry.polarity = debugfs_create_u8("polarity", S_IRUGO | S_IWUSR, config->debugfs_entry, ++ &config->polarity); ++ config->config_entry.period = debugfs_create_u32("period_ns", S_IRUGO | S_IWUSR, config->debugfs_entry, ++ &config->period_ns); ++ config->config_entry.duty = debugfs_create_u32("duty_ns", S_IRUGO | S_IWUSR, config->debugfs_entry, ++ &config->duty_ns); ++ config->config_entry.run = debugfs_create_file("run", S_IRUGO | S_IWUSR, config->debugfs_entry, ++ data, &iproc_pwm_config_fop); ++ ++ } else { ++ debugfs_remove(config->config_entry.polarity); ++ debugfs_remove(config->config_entry.period); ++ debugfs_remove(config->config_entry.duty); ++ debugfs_remove(config->config_entry.run); ++ pwm_disable(config->pwm); ++ pwm_put(config->pwm); ++ config->pwm = NULL; ++ } ++ ++ return 0; ++} ++static int _debug_pwm_export_get(void *data, u64 *val) ++{ ++ struct iproc_pwm_config *config = data; ++ ++ if(config->pwm){ ++ *val = 1; ++ } else { ++ *val = 0; ++ } ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(iproc_pwm_export_fop, _debug_pwm_export_get, ++ _debug_pwm_export_set, "%llu\n"); ++ ++void iproc_pwmc_debugfs_add_chan(struct iproc_pwmc *ap, int chan) ++{ ++ char fname[16]; ++ ++ if (!debugfs_base) ++ return; ++ ++ ++ sprintf(fname, "iproc-pwm%d", chan); ++ ap->config[chan]->debugfs_entry = debugfs_create_dir(fname, debugfs_base); ++ ++ ++ debugfs_create_file("export", S_IRUGO | S_IWUSR, ap->config[chan]->debugfs_entry, ++ ap->config[chan], &iproc_pwm_export_fop); ++ ++} ++static int __init iproc_pwmc_debugfs_init(void) ++{ ++ ++ debugfs_base = debugfs_create_dir("iproc", NULL); ++ if (!debugfs_base) ++ return -ENOMEM; ++ ++ return 0; ++} ++#endif ++ ++ ++static int iproc_get_chan(const struct iproc_pwmc *ap, const struct pwm_device *p) ++{ ++ int chan; ++ ++ chan = p->hwpwm; ++ return chan; ++} ++ ++static void iproc_pwmc_clear_set_bit(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int shift, unsigned char en_dis) ++{ ++ unsigned long val = readl(ap->iobase + offset ) ; ++ ++ // Clear bit. ++ clear_bit(shift,&val) ; ++ if ( en_dis == 1 ) ++ set_bit(shift,&val); ++ ++ writel(val, (ap->iobase + offset )); ++} ++ ++ ++static void iproc_pwmc_set_field(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int mask, unsigned int shift, unsigned int wval) ++{ ++ unsigned int val = readl(ap->iobase + offset ) ; ++ ++ val = (val & ~mask) | ( wval << shift ) ; ++ writel(val, (ap->iobase + offset )); ++} ++ ++static void iproc_pwmc_get_field(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int mask, unsigned int shift, unsigned int *val) ++{ ++ *val = readl(ap->iobase + offset ) ; ++ *val = ( *val & mask ) >> shift ; ++} ++ ++ ++#define to_iproc_chip(chip) container_of(chip, struct iproc_pwmc, chip) ++static int iproc_pwmc_start(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct iproc_pwmc *ap = to_iproc_chip(chip); ++ int chan = iproc_get_chan(ap, pwm); ++ ++ iproc_pwmc_clear_set_bit(ap, IPROC_CCB_PWM_CTL_BASE, ++ (PWM_CTL_ENABLE_SHIFT + chan), 1) ; ++ ++ return 0; ++} ++ ++static void iproc_pwmc_stop(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct iproc_pwmc *ap = to_iproc_chip(chip); ++ int chan = iproc_get_chan(ap, pwm); ++ ++ iproc_pwmc_clear_set_bit(ap, IPROC_CCB_PWM_CTL_BASE, ++ (PWM_CTL_ENABLE_SHIFT + chan), 0) ; ++ ++} ++static int iproc_pwmc_request(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ iproc_pwmc_stop(chip, pwm); ++ return 0; ++} ++ ++static void iproc_pwmc_config_duty_ticks(struct iproc_pwmc *ap, int chan, ++ unsigned long duty_ticks) ++{ ++ /*struct pwm_device *p = ap->p[chan];*/ ++ unsigned int pre_scaler = 0 ; ++ unsigned int duty_cnt = 0 ; ++ ++ iproc_pwmc_get_field(ap, pwm_chan_pre_scaler_info[chan].offset, ++ pwm_chan_pre_scaler_info[chan].mask, pwm_chan_pre_scaler_info[chan].shift, ++ &pre_scaler) ; ++ ++ /* Read prescaler value from register. */ ++ duty_cnt = duty_ticks / (pre_scaler + 1) ; ++ ++ /* program duty cycle. */ ++ iproc_pwmc_set_field(ap, pwm_chan_duty_cycle_info[chan].offset, ++ pwm_chan_duty_cycle_info[chan].mask, ++ pwm_chan_duty_cycle_info[chan].shift, duty_cnt) ; ++ ++ if (BIT(chan) & (readl(ap->iobase + IPROC_CCB_PWM_CTL_BASE) & 0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(&ap->chip, ap->config[chan]->pwm) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(&ap->chip, ap->config[chan]->pwm) ; ++ } ++ ++} ++ ++static int iproc_pwmc_config_period_ticks(struct iproc_pwmc *ap, int chan, ++ unsigned long period_ticks) ++{ ++ unsigned int pcnt ; ++ unsigned char pre_scaler = 0 ; ++ /*struct pwm_device *p = ap->p[chan]; */ ++ ++ pre_scaler = period_ticks / 0xFFFF ; ++ if ( pre_scaler > PWM_PRESCALER_MAX ) ++ pre_scaler = PWM_PRESCALER_MAX ; ++ ++ pcnt = period_ticks / (pre_scaler + 1) ; ++ ++ /* programe prescaler */ ++ iproc_pwmc_set_field(ap, pwm_chan_pre_scaler_info[chan].offset, ++ pwm_chan_pre_scaler_info[chan].mask, ++ pwm_chan_pre_scaler_info[chan].shift, pre_scaler) ; ++ ++ /* program period count. */ ++ iproc_pwmc_set_field(ap, pwm_chan_period_cnt_info[chan].offset, ++ pwm_chan_period_cnt_info[chan].mask, ++ pwm_chan_period_cnt_info[chan].shift, pcnt) ; ++ ++ if (BIT(chan) & (readl(ap->iobase + IPROC_CCB_PWM_CTL_BASE) & 0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(&ap->chip, ap->config[chan]->pwm) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(&ap->chip, ap->config[chan]->pwm) ; ++ } ++ ++ return 0; ++} ++static unsigned long pwm_ns_to_ticks(struct iproc_pwmc *ap, unsigned long nsecs) ++{ ++ unsigned long long ticks; ++ ++ ticks = nsecs; ++ ticks *= ap->tick_hz; ++ do_div(ticks,1000000000UL); ++ ++ return ticks; ++} ++ ++int iproc_pwmc_config_polarity(struct pwm_chip *chip, ++ struct pwm_device *p, int polarity) ++{ ++ ++ struct iproc_pwmc *ap = to_iproc_chip(chip); ++ int chan = iproc_get_chan(ap, p); ++ ++ if (polarity) { ++ iproc_pwmc_clear_set_bit(ap, IPROC_CCB_PWM_CTL_BASE, ++ (PWM_CTL_POLARITY_SHIFT + chan), 1) ; ++ } else { ++ iproc_pwmc_clear_set_bit(ap, IPROC_CCB_PWM_CTL_BASE, ++ (PWM_CTL_POLARITY_SHIFT + chan), 0) ; ++ } ++ ++ if (BIT(chan) & (readl(ap->iobase + IPROC_CCB_PWM_CTL_BASE) & 0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(&ap->chip, ap->config[chan]->pwm) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(&ap->chip, ap->config[chan]->pwm) ; ++ } ++ ap->config[chan]->polarity = polarity; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(iproc_pwmc_config_polarity); ++ ++ ++static int iproc_pwmc_config(struct pwm_chip *chip, ++ struct pwm_device *p, int duty_ns, int period_ns) ++{ ++ struct iproc_pwmc *ap = to_iproc_chip(chip); ++ int chan = iproc_get_chan(ap, p); ++ int ret; ++ unsigned long period_ticks, duty_ticks; ++ ++ period_ticks = pwm_ns_to_ticks(ap, period_ns); ++ ret = iproc_pwmc_config_period_ticks(ap, chan, period_ticks); ++ if (ret) ++ return ret; ++ ap->config[chan]->period_ticks = period_ticks; ++ ap->config[chan]->period_ns = period_ns; ++ ++ duty_ticks = pwm_ns_to_ticks(ap, duty_ns); ++ iproc_pwmc_config_duty_ticks(ap, chan, duty_ticks); ++ ap->config[chan]->duty_ticks = duty_ticks; ++ ap->config[chan]->duty_ns = duty_ns; ++ ++ return 0; ++} ++ ++ ++static const struct pwm_ops iproc_pwm_ops = { ++ .enable = iproc_pwmc_start, ++ .disable = iproc_pwmc_stop, ++ .request = iproc_pwmc_request, ++ .free = iproc_pwmc_stop, ++ .config = iproc_pwmc_config, ++ .owner = THIS_MODULE, ++}; ++ ++ ++static int __devinit iproc_pwmc_probe(struct platform_device *pdev) ++{ ++ struct iproc_pwmc *ap; ++ struct resource *r; ++ int ret = 0; ++ int chan; ++ ++ ap = devm_kzalloc(&pdev->dev, sizeof(*ap), GFP_KERNEL); ++ if (!ap) { ++ dev_err(&pdev->dev, "failed to allocate memory\n"); ++ return -ENOMEM; ++ } ++#ifdef CONFIG_MACH_NSP ++ ap->tick_hz = 25000000UL; ++#else ++ ap->tick_hz = 1000000UL; ++#endif ++ ap->chip.ops = &iproc_pwm_ops; ++ ap->chip.dev = &pdev->dev; ++ ap->chip.base = -1; ++ ap->chip.npwm = IPROC_PWM_CHANNEL_CNT; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (r == NULL) { ++ dev_err(&pdev->dev, "no memory resource defined\n"); ++ return -ENODEV; ++ } ++ ++ ap->iobase = devm_request_and_ioremap(&pdev->dev, r); ++ if (!ap->iobase) { ++ return -EADDRNOTAVAIL; ++ } ++ printk(KERN_INFO "iproc_pwmc_probe iobase %p phys:%x\n", ++ ap->iobase,r->start); ++ ret = pwmchip_add(&ap->chip); ++ if (ret < 0) ++ return ret; ++ ++ platform_set_drvdata(pdev, ap); ++ ++ ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) { ++ ap->config[chan] = kzalloc(sizeof(struct iproc_pwm_config), GFP_KERNEL); ++ ap->config[chan]->pwm_id = chan; ++ ap->config[chan]->dev = &pdev->dev; ++ } ++ ++ ++#ifdef CONFIG_DEBUG_FS ++ iproc_pwmc_debugfs_init(); ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) { ++ iproc_pwmc_debugfs_add_chan(ap,chan); ++ } ++#endif ++ ++ return 0; ++ ++} ++ ++static int __devexit iproc_pwmc_remove(struct platform_device *pdev) ++{ ++ struct iproc_pwmc *ap; ++ int chan; ++ ++ ap = platform_get_drvdata(pdev); ++ ++#ifdef CONFIG_DEBUG_FS ++ if (debugfs_base) ++ debugfs_remove_recursive(debugfs_base); ++ ++#endif ++ ++ if (ap == NULL) ++ return -ENODEV; ++ ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++){ ++ kfree(ap->config[chan]); ++ } ++ pwmchip_remove(&ap->chip); ++ ++ devm_iounmap(&pdev->dev,ap->iobase); ++ kfree(ap); ++ ++ return 0; ++} ++ ++static struct platform_driver iproc_pwmc_driver = { ++ .driver = { ++ .name = "iproc_pwmc", ++ .owner = THIS_MODULE, ++ }, ++ .probe = iproc_pwmc_probe, ++ .remove = __devexit_p(iproc_pwmc_remove), ++}; ++ ++static int __init iproc_pwmc_init(void) ++{ ++ return platform_driver_register(&iproc_pwmc_driver); ++} ++ ++static void __exit iproc_pwmc_exit(void) ++{ ++ platform_driver_unregister(&iproc_pwmc_driver); ++} ++module_init(iproc_pwmc_init); ++module_exit(iproc_pwmc_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Driver for iProc PWMC"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/qspi/.gitignore b/drivers/bcmdrivers/qspi/.gitignore +new file mode 100644 +index 0000000..d03ee50 +--- /dev/null ++++ b/drivers/bcmdrivers/qspi/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order ++/.iproc_qspi.o.cmd ++/.qspi_iproc.o.cmd ++/iproc_qspi.o ++/qspi_iproc.o +diff --git a/drivers/bcmdrivers/qspi/Kconfig b/drivers/bcmdrivers/qspi/Kconfig +new file mode 100644 +index 0000000..fac545c +--- /dev/null ++++ b/drivers/bcmdrivers/qspi/Kconfig +@@ -0,0 +1,72 @@ ++menuconfig IPROC_QSPI ++ tristate "QSPI support" ++ depends on ARCH_IPROC ++ select SPI ++ select SPI_MASTER ++ select MTD ++ select MTD_M25P80 ++ select M25PXX_USE_FAST_READ ++ default n ++ help ++ This selects a driver for the iProc QSPI Controller (for serial flash). ++ ++ If unsure, say N. ++ ++if IPROC_QSPI ++ ++choice ++ prompt "Multi I/O SPI support" ++ default IPROC_QSPI_SINGLE_MODE ++ help ++ Number of (multi I/O) data lanes supported by the SPI flash. ++ ++config IPROC_QSPI_SINGLE_MODE ++ bool "Single lane" ++ help ++ Single lane. ++ ++config IPROC_QSPI_DUAL_MODE ++ bool "Dual mode" ++ help ++ Dual mode. ++ ++config IPROC_QSPI_QUAD_MODE ++ bool "Quad mode" ++ help ++ Quad mode. ++ ++endchoice ++ ++config IPROC_QSPI_MULTI_LANE_ADDR ++ bool "Use multi lanes also for address" ++ depends on IPROC_QSPI_DUAL_MODE || IPROC_QSPI_QUAD_MODE ++ default y ++ help ++ Use multi lanes also for address. ++ ++config IPROC_QSPI_READ_CMD ++ hex "Flash opcode for multi I/O read" ++ depends on IPROC_QSPI_DUAL_MODE || IPROC_QSPI_QUAD_MODE ++ range 0x00 0xff ++ default 0xbb if IPROC_QSPI_DUAL_MODE ++ default 0xeb ++ help ++ Flash opcode to send to flash for multip I/O read. ++ ++config IPROC_QSPI_READ_DUMMY_CYCLES ++ int "Dummy cycles for multi I/O read operation" ++ depends on IPROC_QSPI_DUAL_MODE || IPROC_QSPI_QUAD_MODE ++ range 0 255 ++ default 8 if IPROC_QSPI_DUAL_MODE ++ default 10 ++ help ++ Dummy cycles for flash read operation ++ ++config IPROC_QSPI_MAX_HZ ++ int "Maximal SPI clock in HZ" ++ range 1 1000000000 ++ default 62500000 ++ help ++ The maximal SPI clock (in Hz) supported by the flash. ++ ++endif # IPROC_QSPI +diff --git a/drivers/bcmdrivers/qspi/Makefile b/drivers/bcmdrivers/qspi/Makefile +new file mode 100644 +index 0000000..be164d1 +--- /dev/null ++++ b/drivers/bcmdrivers/qspi/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_QSPI) += iproc_qspi.o ++iproc_qspi-objs := qspi_iproc.o +diff --git a/drivers/bcmdrivers/qspi/qspi_iproc.c b/drivers/bcmdrivers/qspi/qspi_iproc.c +new file mode 100755 +index 0000000..2643787 +--- /dev/null ++++ b/drivers/bcmdrivers/qspi/qspi_iproc.c +@@ -0,0 +1,1807 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DBG(...) /* */ ++ ++/* ++ * Interrupts ++ */ ++ ++#define QSPI_INTR_COUNT (7) ++ ++#define QSPI_INTR_MSPI_HALTED_MASK (0x00000040) ++#define QSPI_INTR_MSPI_DONE_MASK (0x00000020) ++#define QSPI_INTR_BSPI_LR_OVERREAD_MASK (0x00000010) ++#define QSPI_INTR_BSPI_LR_SESSION_DONE_MASK (0x00000008) ++#define QSPI_INTR_BSPI_LR_IMPATIENT_MASK (0x00000004) ++#define QSPI_INTR_BSPI_LR_SESSION_ABORTED_MASK (0x00000002) ++#define QSPI_INTR_BSPI_LR_FULLNESS_REACHED_MASK (0x00000001) ++ ++#define BSPI_LR_INTERRUPTS_DATA \ ++ (QSPI_INTR_BSPI_LR_SESSION_DONE_MASK | \ ++ QSPI_INTR_BSPI_LR_FULLNESS_REACHED_MASK) ++ ++#define BSPI_LR_INTERRUPTS_ERROR \ ++ (QSPI_INTR_BSPI_LR_OVERREAD_MASK | \ ++ QSPI_INTR_BSPI_LR_IMPATIENT_MASK | \ ++ QSPI_INTR_BSPI_LR_SESSION_ABORTED_MASK) ++ ++#define BSPI_LR_INTERRUPTS_ALL \ ++ (BSPI_LR_INTERRUPTS_ERROR | \ ++ BSPI_LR_INTERRUPTS_DATA) ++ ++#define SPBR_MIN 8U ++#define SPBR_MAX 255U ++#define DEFAULT_SPEED_HZ 25000000UL ++#define MSPI_REFCLK_SOURCE "c_clk125" /* To be doubled */ ++#define MSPI_REFCLK_SOURCE_DEVID "iproc_slow" ++ ++/* ++ * Flash opcode and parameters ++ */ ++#define OPCODE_RDID 0x9f ++#define OPCODE_WREN 0x06 ++#define OPCODE_WRDI 0x04 ++#define OPCODE_WRR 0x01 ++#define OPCODE_RCR 0x35 ++#define OPCODE_READ 0x03 ++#define OPCODE_RDSR 0x05 ++#define OPCODE_WRSR 0x01 ++#define OPCODE_RDFSR 0x70 ++#define OPCODE_FAST_READ 0x0B ++#define OPCODE_FAST_READ_4B 0x0C ++#define OPCODE_EN4B 0xB7 ++#define OPCODE_EX4B 0xE9 ++#define OPCODE_BRWR 0x17 ++ ++#define BSPI_WIDTH_1BIT 1 ++#define BSPI_WIDTH_2BIT 2 ++#define BSPI_WIDTH_4BIT 4 ++ ++#define BSPI_ADDRLEN_3BYTES 3 ++#define BSPI_ADDRLEN_4BYTES 4 ++ ++#define BSPI_FLASH_TYPE_SPANSION 0 ++#define BSPI_FLASH_TYPE_MACRONIX 1 ++#define BSPI_FLASH_TYPE_NUMONYX 2 ++#define BSPI_FLASH_TYPE_SST 3 ++#define BSPI_FLASH_TYPE_UNKNOWN -1 ++ ++/* ++ * Register masks/fields/values ++ */ ++#define QSPI_BSPI_RAF_STATUS_FIFO_EMPTY_MASK (0x00000002) ++#define QSPI_BSPI_RAF_CONTROL_START_MASK (0x00000001) ++#define QSPI_BSPI_RAF_CONTROL_CLEAR_MASK (0x00000002) ++#define QSPI_BSPI_BPP_ADDR_BPP_SELECT_MASK (0x00010000) ++#define QSPI_BSPI_BPP_MODE_BPP_MASK (0x00000100) ++#define QSPI_BSPI_FLEX_MODE_ENABLE_MASK (0x00000001) ++ ++ ++/* ++ * Module parameters ++ */ ++ ++/* Mulit I/O for read: 0 - single, 1 - dual, 2 - quad */ ++#ifdef CONFIG_IPROC_QSPI_SINGLE_MODE ++static int io_mode = 0; ++#else /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++#ifdef CONFIG_IPROC_QSPI_DUAL_MODE ++static int io_mode = 1; ++#else /* !CONFIG_IPROC_QSPI_DUAL_MODE */ ++static int io_mode = 2; ++#endif /* !CONFIG_IPROC_QSPI_DUAL_MODE */ ++#endif /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++module_param(io_mode, int, 0444); ++ ++/* Multi I/O for address (only if not in single mode) */ ++#ifdef CONFIG_IPROC_QSPI_MULTI_LANE_ADDR ++static int addr_multi = 1; ++#else /* !CONFIG_IPROC_QSPI_MULTI_LANE_ADDR */ ++static int addr_multi = 0; ++#endif /* !CONFIG_IPROC_QSPI_MULTI_LANE_ADDR */ ++module_param(addr_multi, int, 0444); ++ ++/* Read opcode (only if not in single mode) */ ++#ifdef CONFIG_IPROC_QSPI_SINGLE_MODE ++static int read_opcode = OPCODE_FAST_READ; ++#else /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++static int read_opcode = CONFIG_IPROC_QSPI_READ_CMD; ++#endif /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++module_param(read_opcode, int, 0444); ++ ++/* Dummy cycles for read (only if not in single mode) */ ++#ifdef CONFIG_IPROC_QSPI_SINGLE_MODE ++static int dummy_cycles = 8; ++#else /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++static int dummy_cycles = CONFIG_IPROC_QSPI_READ_DUMMY_CYCLES; ++#endif /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++module_param(dummy_cycles, int, 0444); ++ ++/* Max SPI clock HZ */ ++static int max_hz = 0; ++module_param(max_hz, int, 0444); ++ ++/* Spansion high performance mode */ ++static int bspi_hp; ++module_param(bspi_hp, int, 0444); ++ ++struct bcmspi_parms { ++ u32 speed_hz; ++ u8 chip_select; ++ u8 mode; ++ u8 bits_per_word; ++}; ++ ++struct position { ++ struct spi_message *msg; ++ struct spi_transfer *trans; ++ int byte; ++ int mspi_16bit; ++}; ++ ++#define NUM_TXRAM 32 ++#define NUM_RXRAM 32 ++#define NUM_CDRAM 16 ++ ++struct bcm_mspi_hw { ++ u32 spcr0_lsb; /* 0x000 */ ++ u32 spcr0_msb; /* 0x004 */ ++ u32 spcr1_lsb; /* 0x008 */ ++ u32 spcr1_msb; /* 0x00c */ ++ u32 newqp; /* 0x010 */ ++ u32 endqp; /* 0x014 */ ++ u32 spcr2; /* 0x018 */ ++ u32 reserved0; /* 0x01c */ ++ u32 mspi_status; /* 0x020 */ ++ u32 cptqp; /* 0x024 */ ++ u32 reserved1[6]; /* 0x028 */ ++ u32 txram[NUM_TXRAM]; /* 0x040 */ ++ u32 rxram[NUM_RXRAM]; /* 0x0c0 */ ++ u32 cdram[NUM_CDRAM]; /* 0x140 */ ++ u32 write_lock; /* 0x180 */ ++ u32 disable_flush_gen; /* 0x184 */ ++}; ++ ++struct bcm_bspi_hw { ++ u32 revision_id; /* 0x000 */ ++ u32 scratch; /* 0x004 */ ++ u32 mast_n_boot_ctrl; /* 0x008 */ ++ u32 busy_status; /* 0x00c */ ++ u32 intr_status; /* 0x010 */ ++ u32 b0_status; /* 0x014 */ ++ u32 b0_ctrl; /* 0x018 */ ++ u32 b1_status; /* 0x01c */ ++ u32 b1_ctrl; /* 0x020 */ ++ u32 strap_override_ctrl; /* 0x024 */ ++ u32 flex_mode_enable; /* 0x028 */ ++ u32 bits_per_cycle; /* 0x02C */ ++ u32 bits_per_phase; /* 0x030 */ ++ u32 cmd_and_mode_byte; /* 0x034 */ ++ u32 flash_upper_addr_byte; /* 0x038 */ ++ u32 xor_value; /* 0x03C */ ++ u32 xor_enable; /* 0x040 */ ++ u32 pio_mode_enable; /* 0x044 */ ++ u32 pio_iodir; /* 0x048 */ ++ u32 pio_data; /* 0x04C */ ++}; ++ ++struct bcm_bspi_raf { ++ u32 start_address; /* 0x00 */ ++ u32 num_words; /* 0x04 */ ++ u32 ctrl; /* 0x08 */ ++ u32 fullness; /* 0x0C */ ++ u32 watermark; /* 0x10 */ ++ u32 status; /* 0x14 */ ++ u32 read_data; /* 0x18 */ ++ u32 word_cnt; /* 0x1C */ ++ u32 curr_addr; /* 0x20 */ ++}; ++ ++struct bcm_idm_qspi_ctrl { ++ u32 io_ctrl_direct; ++}; ++ ++struct bcm_cru_control { ++ u32 cru_control; ++}; ++ ++struct bcm_flex_mode { ++ int width; ++ int addrlen; ++ int hp; ++}; ++ ++#define STATE_IDLE 0 ++#define STATE_RUNNING 1 ++#define STATE_SHUTDOWN 2 ++ ++struct bcmspi_priv { ++ struct platform_device *pdev; ++ struct spi_master *master; ++ spinlock_t lock; ++ struct bcmspi_parms last_parms; ++ struct position pos; ++ struct list_head msg_queue; ++ int state; ++ int outstanding_bytes; ++ int next_udelay; ++ int cs_change; ++ unsigned int mspi_refclk; ++ unsigned int max_speed_hz; ++ volatile struct bcm_mspi_hw *mspi_hw; ++ int irq; ++ struct tasklet_struct tasklet; ++ int curr_cs; ++ ++ /* BSPI */ ++ volatile struct bcm_bspi_hw *bspi_hw; ++ volatile struct bcm_cru_control *cru_hw; ++ int bspi_enabled; ++ /* all chip selects controlled by BSPI */ ++ int bspi_chip_select; ++ ++ /* LR */ ++ volatile struct bcm_bspi_raf *bspi_hw_raf; ++ struct spi_transfer *cur_xfer; ++ u32 cur_xfer_idx; ++ u32 cur_xfer_len; ++ u32 xfer_status; ++ struct spi_message *cur_msg; ++ u32 actual_length; ++ u32 raf_next_addr; ++ u32 raf_next_len; ++ ++ /* Interrupts */ ++ volatile u32 *qspi_intr; ++ volatile struct bcm_idm_qspi_ctrl *idm_qspi; ++ ++ /* current flex mode settings */ ++ struct bcm_flex_mode flex_mode; ++}; ++ ++static void bcmspi_enable_interrupt(struct bcmspi_priv *priv, u32 mask) ++{ ++ priv->idm_qspi->io_ctrl_direct |= cpu_to_le32(mask << 2); ++} ++ ++static void bcmspi_disable_interrupt(struct bcmspi_priv *priv, u32 mask) ++{ ++ priv->idm_qspi->io_ctrl_direct &= cpu_to_le32(~(mask << 2)); ++} ++ ++static void bcmspi_clear_interrupt(struct bcmspi_priv *priv, u32 mask) ++{ ++ int i; ++ ++ for(i=0; iqspi_intr[i] = cpu_to_le32(1); ++ } ++ } ++} ++ ++static u32 bcmspi_read_interrupt(struct bcmspi_priv *priv) ++{ ++ int i; ++ u32 status = 0; ++ ++ for(i=0; iqspi_intr[i] & cpu_to_le32(1)) { ++ status |= 1UL << i; ++ } ++ } ++ ++ return status; ++} ++ ++static void bcmspi_flush_prefetch_buffers(struct bcmspi_priv *priv) ++{ ++ priv->bspi_hw->b0_ctrl = 0; ++ priv->bspi_hw->b1_ctrl = 0; ++ priv->bspi_hw->b0_ctrl = cpu_to_le32(1); ++ priv->bspi_hw->b1_ctrl = cpu_to_le32(1); ++} ++ ++static int bcmspi_lr_is_fifo_empty(struct bcmspi_priv *priv) ++{ ++ return priv->bspi_hw_raf->status & cpu_to_le32(QSPI_BSPI_RAF_STATUS_FIFO_EMPTY_MASK); ++} ++ ++static inline u32 bcmspi_lr_read_fifo(struct bcmspi_priv *priv) ++{ ++ /* for performance reasons return the raw data, rather than ++ * byte-swapped data. This works because the caller writes ++ * values 32-bits at a time to the destination buffer, giving ++ * an automatic byte-swap on big-endian machines. */ ++ ++ return priv->bspi_hw_raf->read_data; ++} ++ ++static inline void bcmspi_lr_start(struct bcmspi_priv *priv) ++{ ++ priv->bspi_hw_raf->ctrl = cpu_to_le32(QSPI_BSPI_RAF_CONTROL_START_MASK); ++} ++ ++static inline void bcmspi_lr_clear(struct bcmspi_priv *priv) ++{ ++ priv->bspi_hw_raf->ctrl = cpu_to_le32(QSPI_BSPI_RAF_CONTROL_CLEAR_MASK); ++ bcmspi_flush_prefetch_buffers(priv); ++} ++ ++static inline int bcmspi_is_4_byte_mode(struct bcmspi_priv *priv) ++{ ++ return priv->flex_mode.addrlen == BSPI_ADDRLEN_4BYTES; ++} ++ ++static int bcmbspi_flash_type(struct bcmspi_priv *priv); ++ ++static int bcmspi_set_flex_mode(struct bcmspi_priv *priv, ++ int width, int addrlen, int hp) ++{ ++ int bpc = 0, bpp = dummy_cycles, command = read_opcode; ++ int flex_mode = 1, error = 0; ++ ++ switch (width) { ++ case BSPI_WIDTH_1BIT: ++ if (addrlen == BSPI_ADDRLEN_3BYTES) { ++ /* default mode, does not need flex_cmd */ ++ flex_mode = 0; ++ } else { ++ bpp = 8; /* dummy cycles */ ++ if (bcmbspi_flash_type(priv) == BSPI_FLASH_TYPE_SPANSION) ++ command = OPCODE_FAST_READ_4B; ++ else ++ command = OPCODE_FAST_READ; ++ } ++ break; ++ case BSPI_WIDTH_2BIT: ++ bpc = 0x00000001; /* only data is 2-bit */ ++ if (addr_multi) { ++ bpc |= 0x00010000; ++ } ++ if (hp) { ++ bpc |= 0x00010100; /* address and mode are 2-bit too */ ++ bpp |= QSPI_BSPI_BPP_MODE_BPP_MASK; ++ } ++ break; ++ case BSPI_WIDTH_4BIT: ++ bpc = 0x00000002; /* only data is 4-bit */ ++ if (addr_multi) { ++ bpc |= 0x00020000; ++ } ++ if (hp) { ++ bpc |= 0x00020200; /* address and mode are 4-bit too */ ++ bpp |= QSPI_BSPI_BPP_MODE_BPP_MASK; ++ } ++ break; ++ default: ++ error = 1; ++ break; ++ } ++ ++ if (addrlen == BSPI_ADDRLEN_4BYTES) { ++ bpp |= QSPI_BSPI_BPP_ADDR_BPP_SELECT_MASK; ++ } ++ ++ if (!error) { ++ priv->bspi_hw->flex_mode_enable = 0; ++ priv->bspi_hw->bits_per_cycle = cpu_to_le32(bpc); ++ priv->bspi_hw->bits_per_phase = cpu_to_le32(bpp); ++ priv->bspi_hw->cmd_and_mode_byte = cpu_to_le32(command); ++ priv->bspi_hw->flex_mode_enable = flex_mode ? ++ cpu_to_le32(QSPI_BSPI_FLEX_MODE_ENABLE_MASK) ++ : 0; ++ DBG("%s: width=%d addrlen=%d hp=%d\n", ++ __func__, width, addrlen, hp); ++ DBG("%s: fme=%08x bpc=%08x bpp=%08x cmd=%08x\n", __func__, ++ le32_to_cpu(priv->bspi_hw->flex_mode_enable), ++ le32_to_cpu(priv->bspi_hw->bits_per_cycle), ++ le32_to_cpu(priv->bspi_hw->bits_per_phase), ++ le32_to_cpu(priv->bspi_hw->cmd_and_mode_byte)); ++ } ++ ++ return error; ++} ++ ++static void bcmspi_set_mode(struct bcmspi_priv *priv, ++ int width, int addrlen, int hp) ++{ ++ int error = 0; ++ int show_info = 0; ++ ++ if (width != -1 || hp != -1) { ++ /* Don't print things if only for address mode change because it ++ * could be very frequent. */ ++ show_info = 1; ++ } ++ if (width == -1) ++ width = priv->flex_mode.width; ++ if (addrlen == -1) ++ addrlen = priv->flex_mode.addrlen; ++ if (hp == -1) ++ hp = priv->flex_mode.hp; ++ ++ error = bcmspi_set_flex_mode(priv, width, addrlen, hp); ++ ++ if (!error) { ++ priv->flex_mode.width = width; ++ priv->flex_mode.addrlen = addrlen; ++ priv->flex_mode.hp = hp; ++ if (show_info) { ++ dev_info(&priv->pdev->dev, ++ "%d-lane output, %d-byte address%s\n", ++ priv->flex_mode.width, ++ priv->flex_mode.addrlen, ++ priv->flex_mode.hp ? ", high-performance mode" : ""); ++ } ++ } else ++ dev_warn(&priv->pdev->dev, ++ "INVALID COMBINATION: width=%d addrlen=%d hp=%d\n", ++ width, addrlen, hp); ++} ++ ++static void bcmspi_set_chip_select(struct bcmspi_priv *priv, int cs) ++{ ++ if (priv->curr_cs != cs) { ++ DBG("Switching CS%1d => CS%1d\n", ++ priv->curr_cs, cs); ++ ++ /* We don't have multiple chip selects for now */ ++ } ++ priv->curr_cs = cs; ++ ++} ++ ++static inline int is_bspi_chip_select(struct bcmspi_priv *priv, u8 cs) ++{ ++ return priv->bspi_chip_select & (1 << cs); ++} ++ ++static void bcmspi_disable_bspi(struct bcmspi_priv *priv) ++{ ++ int i; ++ ++ if (!priv->bspi_hw || !priv->bspi_enabled) ++ return; ++ if ((priv->bspi_hw->mast_n_boot_ctrl & cpu_to_le32(1)) == 1) { ++ priv->bspi_enabled = 0; ++ return; ++ } ++ ++ DBG("disabling bspi\n"); ++ for (i = 0; i < 1000; i++) { ++ if ((priv->bspi_hw->busy_status & cpu_to_le32(1)) == 0) { ++ priv->bspi_hw->mast_n_boot_ctrl = cpu_to_le32(1); ++ priv->bspi_enabled = 0; ++ udelay(1); ++ return; ++ } ++ udelay(1); ++ } ++ dev_warn(&priv->pdev->dev, "timeout setting MSPI mode\n"); ++} ++ ++static void bcmspi_enable_bspi(struct bcmspi_priv *priv) ++{ ++ if (!priv->bspi_hw || priv->bspi_enabled) ++ return; ++ if ((priv->bspi_hw->mast_n_boot_ctrl & cpu_to_le32(1)) == 0) { ++ priv->bspi_enabled = 1; ++ return; ++ } ++ ++ DBG("enabling bspi\n"); ++ priv->bspi_hw->mast_n_boot_ctrl = 0; ++ priv->bspi_enabled = 1; ++} ++ ++static void bcmspi_hw_set_parms(struct bcmspi_priv *priv, ++ const struct bcmspi_parms *xp) ++{ ++ if (xp->speed_hz) { ++ unsigned int spbr = priv->mspi_refclk / (2 * xp->speed_hz); ++ ++ priv->mspi_hw->spcr0_lsb = cpu_to_le32(max(min(spbr, SPBR_MAX), SPBR_MIN)); ++ } else { ++ priv->mspi_hw->spcr0_lsb = cpu_to_le32(SPBR_MIN); ++ } ++ ++ if (priv->pos.msg == NULL || xp->bits_per_word > 8) { ++ /* Global hw init or 16bit spi_transfer */ ++ int bits = xp->bits_per_word; ++ bits = bits? (bits == 16? 0 : bits) : 8; ++ priv->mspi_hw->spcr0_msb = cpu_to_le32(0x80 | /* Master */ ++ (bits << 2) | ++ (xp->mode & 3)); ++ } else { ++ /* Configure for a new 8-bit spi_transfer */ ++ if (priv->pos.byte == 0) { ++ /* Use 16-bit MSPI transfer for performance if applicable */ ++ if (priv->pos.mspi_16bit ^ (!(priv->pos.trans->len & 1))) { ++ /* Update it only if needed */ ++ priv->pos.mspi_16bit = !priv->pos.mspi_16bit; ++ priv->mspi_hw->spcr0_msb = cpu_to_le32(0x80 | /* Master */ ++ ((priv->pos.mspi_16bit? 0 : 8) << 2) | ++ (xp->mode & 3)); ++ } ++ } ++ } ++ priv->last_parms = *xp; ++} ++ ++#define PARMS_NO_OVERRIDE 0 ++#define PARMS_OVERRIDE 1 ++ ++static int bcmspi_update_parms(struct bcmspi_priv *priv, ++ struct spi_device *spidev, struct spi_transfer *trans, int override) ++{ ++ struct bcmspi_parms xp; ++ ++ xp.speed_hz = min(trans->speed_hz ? trans->speed_hz : ++ (spidev->max_speed_hz ? spidev->max_speed_hz : DEFAULT_SPEED_HZ), ++ DEFAULT_SPEED_HZ); ++ xp.chip_select = spidev->chip_select; ++ xp.mode = spidev->mode; ++ xp.bits_per_word = trans->bits_per_word ? trans->bits_per_word : ++ (spidev->bits_per_word ? spidev->bits_per_word : 8); ++ ++ if ((override == PARMS_OVERRIDE) || ++ ((xp.speed_hz == priv->last_parms.speed_hz) && ++ (xp.chip_select == priv->last_parms.chip_select) && ++ (xp.mode == priv->last_parms.mode) && ++ (xp.bits_per_word == priv->last_parms.bits_per_word))) { ++ bcmspi_hw_set_parms(priv, &xp); ++ return 0; ++ } ++ /* no override, and parms do not match */ ++ return 1; ++} ++ ++ ++static int bcmspi_setup(struct spi_device *spi) ++{ ++ struct bcmspi_parms *xp; ++ struct bcmspi_priv *priv = spi_master_get_devdata(spi->master); ++ unsigned int speed_hz; ++ ++ DBG("%s\n", __func__); ++ ++ if (spi->bits_per_word > 16) ++ return -EINVAL; ++ ++ /* Module parameter override */ ++ if (max_hz != 0) { ++ speed_hz = max_hz; ++ } else { ++ speed_hz = spi->max_speed_hz; ++ } ++ ++ xp = spi_get_ctldata(spi); ++ if (!xp) { ++ xp = kzalloc(sizeof(struct bcmspi_parms), GFP_KERNEL); ++ if (!xp) ++ return -ENOMEM; ++ spi_set_ctldata(spi, xp); ++ } ++ if (speed_hz < priv->max_speed_hz) ++ xp->speed_hz = speed_hz; ++ else ++ xp->speed_hz = 0; ++ ++ priv->cru_hw->cru_control &= cpu_to_le32(~0x00000006); ++ (void)priv->cru_hw->cru_control; /* Need to read back */ ++ if (speed_hz >= 62500000) { ++ priv->cru_hw->cru_control |= cpu_to_le32(0x00000006); ++ } else if (speed_hz >= 50000000) { ++ priv->cru_hw->cru_control |= cpu_to_le32(0x00000002); ++ } else if (speed_hz >= 31250000) { ++ priv->cru_hw->cru_control |= cpu_to_le32(0x00000004); ++ } ++ (void)priv->cru_hw->cru_control; /* Need to read back */ ++ ++ xp->chip_select = spi->chip_select; ++ xp->mode = spi->mode; ++ xp->bits_per_word = spi->bits_per_word ? spi->bits_per_word : 8; ++ ++ return 0; ++} ++ ++/* stop at end of transfer, no other reason */ ++#define FNB_BREAK_NONE 0 ++/* stop at end of spi_message */ ++#define FNB_BREAK_EOM 1 ++/* stop at end of spi_transfer if delay */ ++#define FNB_BREAK_DELAY 2 ++/* stop at end of spi_transfer if cs_change */ ++#define FNB_BREAK_CS_CHANGE 4 ++/* stop if we run out of bytes */ ++#define FNB_BREAK_NO_BYTES 8 ++/* stop at end of spi_transfer */ ++#define FNB_BREAK_EOT 16 ++ ++/* events that make us stop filling TX slots */ ++#define FNB_BREAK_TX (FNB_BREAK_EOM | FNB_BREAK_DELAY | \ ++ FNB_BREAK_CS_CHANGE) ++ ++/* events that make us deassert CS */ ++#define FNB_BREAK_DESELECT (FNB_BREAK_EOM | FNB_BREAK_CS_CHANGE) ++ ++ ++static int find_next_byte(struct bcmspi_priv *priv, struct position *p, ++ struct list_head *completed, int flags) ++{ ++ int ret = FNB_BREAK_NONE; ++ ++ p->byte++; ++ ++ while (p->byte >= p->trans->len) { ++ /* we're at the end of the spi_transfer */ ++ ++ /* in TX mode, need to pause for a delay or CS change */ ++ if (p->trans->delay_usecs && (flags & FNB_BREAK_DELAY)) ++ ret |= FNB_BREAK_DELAY; ++ if (p->trans->cs_change && (flags & FNB_BREAK_CS_CHANGE)) ++ ret |= FNB_BREAK_CS_CHANGE; ++ if (ret) ++ return ret; ++ ++ /* advance to next spi_message? */ ++ if (list_is_last(&p->trans->transfer_list, ++ &p->msg->transfers)) { ++ struct spi_message *next_msg = NULL; ++ ++ /* TX breaks at the end of each message as well */ ++ if (!completed || (flags & FNB_BREAK_EOM)) { ++ DBG("find_next_byte: advance msg exit\n"); ++ return FNB_BREAK_EOM; ++ } ++ if (!list_is_last(&p->msg->queue, &priv->msg_queue)) { ++ next_msg = list_entry(p->msg->queue.next, ++ struct spi_message, queue); ++ } ++ /* delete from run queue, add to completion queue */ ++ list_del(&p->msg->queue); ++ list_add_tail(&p->msg->queue, completed); ++ ++ p->msg = next_msg; ++ p->byte = 0; ++ if (p->msg == NULL) { ++ p->trans = NULL; ++ ret = FNB_BREAK_NO_BYTES; ++ break; ++ } ++ ++ /* ++ * move on to the first spi_transfer of the new ++ * spi_message ++ */ ++ p->trans = list_entry(p->msg->transfers.next, ++ struct spi_transfer, transfer_list); ++ } else { ++ /* or just advance to the next spi_transfer */ ++ p->trans = list_entry(p->trans->transfer_list.next, ++ struct spi_transfer, transfer_list); ++ p->byte = 0; ++ ++ /* Separate spi_transfers into MSPI transfers */ ++ ret = FNB_BREAK_EOT; ++ } ++ } ++ DBG("find_next_byte: msg %p trans %p len %d byte %d ret %x\n", ++ p->msg, p->trans, p->trans ? p->trans->len : 0, p->byte, ret); ++ return ret; ++} ++ ++static void read_from_hw(struct bcmspi_priv *priv, struct list_head *completed) ++{ ++ struct position p; ++ int slot = 0, n = priv->outstanding_bytes; ++ ++ DBG("%s\n", __func__); ++ ++ p = priv->pos; ++ ++ while (n > 0) { ++ BUG_ON(p.msg == NULL); ++ ++ if (p.trans->bits_per_word <= 8) { ++ u8 *buf = p.trans->rx_buf; ++ ++ if (buf) { ++ ++ if (p.mspi_16bit) { ++ /* Using 16-bit SPI transfers for performance */ ++ buf[p.byte] = ++ le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 0]) & 0xff; ++ DBG("RD %02x\n", buf ? buf[p.byte] : 0xff); ++ buf[p.byte + 1] = ++ le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 1]) & 0xff; ++ DBG("RD %02x\n", buf ? buf[p.byte + 1] : 0xff); ++ } else { ++ buf[p.byte] = ++ le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 1]) & 0xff; ++ DBG("RD %02x\n", buf ? buf[p.byte] : 0xff); ++ } ++ } ++ } else { ++ u16 *buf = p.trans->rx_buf; ++ ++ if (buf) { ++ buf[p.byte] = ++ ((le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 1]) & 0xff) << 0) | ++ ((le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 0] & 0xff)) << 8); ++ DBG("RD %04x\n", buf ? buf[p.byte] : 0xffff); ++ } ++ } ++ slot++; ++ n--; ++ p.msg->actual_length++; ++ if (p.mspi_16bit) { ++ p.byte++; ++ p.msg->actual_length++; ++ } ++ ++ find_next_byte(priv, &p, completed, FNB_BREAK_NONE); ++ } ++ ++ priv->pos = p; ++ priv->outstanding_bytes = 0; ++} ++ ++static void write_to_hw(struct bcmspi_priv *priv) ++{ ++ struct position p; ++ int slot = 0, fnb = 0; ++ struct spi_message *msg = NULL; ++ ++ DBG("%s\n", __func__); ++ ++ bcmspi_disable_bspi(priv); ++ ++ p = priv->pos; ++ ++ while (1) { ++ if (p.msg == NULL) ++ break; ++ if (!msg) { ++ msg = p.msg; ++ bcmspi_update_parms(priv, msg->spi, p.trans, ++ PARMS_OVERRIDE); ++ } else { ++ /* break if the speed, bits, etc. changed */ ++ if (bcmspi_update_parms(priv, msg->spi, p.trans, ++ PARMS_NO_OVERRIDE)) { ++ DBG("parms don't match, breaking\n"); ++ break; ++ } ++ } ++ if (p.trans->bits_per_word <= 8) { ++ const u8 *buf = p.trans->tx_buf; ++ ++ priv->mspi_hw->txram[slot << 1] = cpu_to_le32(buf ? ++ (buf[p.byte] & 0xff) : 0xff); ++ DBG("WR %02x\n", buf ? buf[p.byte] : 0xff); ++ ++ if (priv->pos.mspi_16bit) { ++ /* Using 16-bit SPI transfers for performance */ ++ p.byte++; ++ priv->mspi_hw->txram[(slot << 1) + 1] = cpu_to_le32(buf ? ++ (buf[p.byte] & 0xff) : 0xff); ++ DBG("WR %02x\n", buf ? buf[p.byte] : 0xff); ++ priv->mspi_hw->cdram[slot] = cpu_to_le32(0xce); ++ } else { ++ priv->mspi_hw->cdram[slot] = cpu_to_le32(0x8e); ++ } ++ ++ } else { ++ const u16 *buf = p.trans->tx_buf; ++ ++ priv->mspi_hw->txram[(slot << 1) + 0] = cpu_to_le32(buf ? ++ (buf[p.byte] >> 8) : 0xff); ++ priv->mspi_hw->txram[(slot << 1) + 1] = cpu_to_le32(buf ? ++ (buf[p.byte] & 0xff) : 0xff); ++ DBG("WR %04x\n", buf ? buf[p.byte] : 0xffff); ++ priv->mspi_hw->cdram[slot] = cpu_to_le32(0xce); ++ } ++ slot++; ++ ++ fnb = find_next_byte(priv, &p, NULL, FNB_BREAK_TX); ++ ++ if (fnb & FNB_BREAK_CS_CHANGE) ++ priv->cs_change = 1; ++ if (fnb & FNB_BREAK_DELAY) ++ priv->next_udelay = p.trans->delay_usecs; ++ if (fnb || (slot == NUM_CDRAM)) ++ break; ++ } ++ ++ if (slot) { ++ DBG("submitting %d slots\n", slot); ++ priv->mspi_hw->newqp = 0; ++ priv->mspi_hw->endqp = cpu_to_le32(slot - 1); ++ ++ /* deassert CS on the final byte */ ++ if (fnb & FNB_BREAK_DESELECT) ++ priv->mspi_hw->cdram[slot - 1] &= cpu_to_le32(~0x80); ++ ++ /* tell HIF_MSPI which CS to use */ ++ bcmspi_set_chip_select(priv, msg->spi->chip_select); ++ ++ priv->mspi_hw->write_lock = cpu_to_le32(1); ++ priv->mspi_hw->spcr2 = cpu_to_le32(0xe0); /* cont | spe | spifie */ ++ ++ priv->state = STATE_RUNNING; ++ priv->outstanding_bytes = slot; ++ } else { ++ priv->mspi_hw->write_lock = 0; ++ priv->state = STATE_IDLE; ++ } ++} ++ ++#define DWORD_ALIGNED(a) (!(((unsigned long)(a)) & 3)) ++#define ACROSS_16MB(a, l) (((a) ^ ((a) + (l) - 1)) & 0xFF000000) ++ ++static int bcmspi_emulate_flash_read(struct bcmspi_priv *priv, ++ struct spi_message *msg) ++{ ++ u32 addr, len; ++ int idx = 0; /* Also used for checking continuation */ ++ unsigned long flags = 0; ++ ++ /* Check if it's a continuation */ ++ if (priv->raf_next_len != 0) { ++ ++ /* Continuation (read across 16MB boundary) */ ++ addr = priv->raf_next_addr; ++ len = priv->raf_next_len; ++ ++ /* Update upper address byte */ ++ if (bcmspi_is_4_byte_mode(priv)) { ++ priv->bspi_hw->flash_upper_addr_byte = cpu_to_le32(addr & 0xFF000000); ++ /* Flush prefecth buffers since upper byte changed */ ++ bcmspi_flush_prefetch_buffers(priv); ++ } ++ ++ } else { ++ ++ /* It's the first session of this transfer */ ++ struct spi_transfer *trans; ++ u8 *buf; ++ ++ /* acquire lock when the MSPI is idle */ ++ while (1) { ++ spin_lock_irqsave(&priv->lock, flags); ++ if (priv->state == STATE_IDLE) ++ break; ++ spin_unlock_irqrestore(&priv->lock, flags); ++ if (priv->state == STATE_SHUTDOWN) ++ return -EIO; ++ udelay(1); ++ } ++ bcmspi_set_chip_select(priv, msg->spi->chip_select); ++ ++ /* first transfer - OPCODE_READ + 3-byte address */ ++ trans = list_entry(msg->transfers.next, struct spi_transfer, ++ transfer_list); ++ buf = (void *)trans->tx_buf; ++ ++ idx = 1; ++ ++ /* Check upper address byte for 4-byte mode */ ++ if (bcmspi_is_4_byte_mode(priv)) { ++ addr = buf[idx++] << 24; ++ } else { ++ addr = 0; ++ } ++ ++ /* ++ * addr coming into this function is a raw flash offset ++ * we need to convert it to the BSPI address ++ */ ++ addr |= (buf[idx] << 16) | (buf[idx+1] << 8) | buf[idx+2]; ++ ++ /* second transfer - read result into buffer */ ++ trans = list_entry(msg->transfers.next->next, struct spi_transfer, ++ transfer_list); ++ ++ buf = (void *)trans->rx_buf; ++ ++ len = trans->len; ++ ++ /* non-aligned and very short transfers are handled by MSPI */ ++ if (unlikely(!DWORD_ALIGNED(addr) || ++ !DWORD_ALIGNED(buf) || ++ len < sizeof(u32) || ++ !priv->bspi_hw_raf)) { ++ spin_unlock_irqrestore(&priv->lock, flags); ++ return -1; ++ } ++ ++ /* Flush prefetch buffers only if upper address byte changed */ ++ if ((addr & 0xFF000000) != le32_to_cpu(priv->bspi_hw->flash_upper_addr_byte)) { ++ bcmspi_flush_prefetch_buffers(priv); ++ /* Update upper address byte */ ++ priv->bspi_hw->flash_upper_addr_byte = cpu_to_le32(addr & 0xFF000000); ++ } ++ ++ /* Switching to BSPI */ ++ bcmspi_enable_bspi(priv); ++ ++ DBG("%s: dst %p src %p len %x addr BSPI %06x\n", ++ __func__, buf, addr, len, addr); ++ ++ /* initialize software parameters */ ++ priv->xfer_status = 0; ++ priv->cur_xfer = trans; ++ priv->cur_xfer_idx = 0; ++ priv->cur_msg = msg; ++ priv->actual_length = idx + 4 + trans->len; ++ } ++ ++ if (bcmspi_is_4_byte_mode(priv) && ACROSS_16MB(addr, len)) { ++ ++ /* Size for the first session */ ++ u32 bytes = 0x1000000 - (addr & 0x00FFFFFF); ++ ++ /* Address and size for remaining sessions */ ++ priv->raf_next_addr = addr + bytes; ++ priv->raf_next_len = len - bytes; ++ ++ len = bytes; ++ ++ } else { ++ priv->raf_next_len = 0; ++ } ++ ++ /* Length for this session */ ++ priv->cur_xfer_len = len; ++ ++ /* setup hardware */ ++ /* address must be 4-byte aligned */ ++ priv->bspi_hw_raf->start_address = cpu_to_le32(addr & 0x00FFFFFF); ++ priv->bspi_hw_raf->num_words = cpu_to_le32((len + 3) >> 2); ++ priv->bspi_hw_raf->watermark = 0; ++ ++ DBG("READ: %08x %08x (%08x)\n", addr, ((len + 3) >> 2), len); ++ ++ bcmspi_clear_interrupt(priv, 0xffffffff); ++ bcmspi_enable_interrupt(priv, BSPI_LR_INTERRUPTS_ALL); ++ bcmspi_lr_start(priv); ++ ++ if (idx) { ++ spin_unlock_irqrestore(&priv->lock, flags); ++ } ++ ++ return 0; ++} ++ ++/* ++ * m25p80_read() calls wait_till_ready() before each read to check ++ * the flash status register for pending writes. ++ * ++ * This can be safely skipped if our last transaction was just an ++ * emulated BSPI read. ++ */ ++static int bcmspi_emulate_flash_rdsr(struct bcmspi_priv *priv, ++ struct spi_message *msg) ++{ ++ u8 *buf; ++ struct spi_transfer *trans; ++ ++ if (priv->bspi_enabled == 0) ++ return 1; ++ ++ trans = list_entry(msg->transfers.next->next, struct spi_transfer, ++ transfer_list); ++ ++ buf = (void *)trans->rx_buf; ++ *buf = 0x00; ++ ++ msg->actual_length = 2; ++ msg->status = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ spi_finalize_current_message(priv->master); ++#else ++ msg->complete(msg->context); ++#endif ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++static int bcmspi_prepare_transfer(struct spi_master *master) ++{ ++ return 0; ++} ++ ++static int bcmspi_unprepare_transfer(struct spi_master *master) ++{ ++ return 0; ++} ++#endif ++ ++static int bcmspi_transfer_one(struct spi_master *master, struct spi_message *msg) ++{ ++ struct bcmspi_priv *priv = spi_master_get_devdata(master); ++ unsigned long flags; ++ ++ if (is_bspi_chip_select(priv, msg->spi->chip_select)) { ++ struct spi_transfer *trans; ++ ++ trans = list_entry(msg->transfers.next, ++ struct spi_transfer, transfer_list); ++ if (trans && trans->len && trans->tx_buf) { ++ u8 command = ((u8 *)trans->tx_buf)[0]; ++ switch (command) { ++ case OPCODE_FAST_READ: ++ if (bcmspi_emulate_flash_read(priv, msg) == 0) ++ return 0; ++ break; ++ case OPCODE_RDSR: ++ if (bcmspi_emulate_flash_rdsr(priv, msg) == 0) ++ return 0; ++ break; ++ case OPCODE_EN4B: ++ DBG("ENABLE 4-BYTE MODE\n"); ++ bcmspi_set_mode(priv, -1, BSPI_ADDRLEN_4BYTES, -1); ++ break; ++ case OPCODE_EX4B: ++ DBG("DISABLE 4-BYTE MODE\n"); ++ bcmspi_set_mode(priv, -1, BSPI_ADDRLEN_3BYTES, -1); ++ break; ++ case OPCODE_BRWR: ++ { ++ u8 enable = ((u8 *)trans->tx_buf)[1]; ++ DBG("%s 4-BYTE MODE\n", enable ? "ENABLE" : "DISABLE"); ++ bcmspi_set_mode(priv, -1, ++ enable ? BSPI_ADDRLEN_4BYTES : ++ BSPI_ADDRLEN_3BYTES, -1); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ /* Mark prefetch buffers dirty (by using upper byte) if needed */ ++ switch(command) { ++ case OPCODE_RDID: ++ case OPCODE_WREN: ++ case OPCODE_WRDI: ++ case OPCODE_RCR: ++ case OPCODE_READ: ++ case OPCODE_RDSR: ++ case OPCODE_WRSR: ++ case OPCODE_RDFSR: ++ case OPCODE_FAST_READ: ++ case OPCODE_FAST_READ_4B: ++ case OPCODE_EN4B: ++ case OPCODE_EX4B: ++ case OPCODE_BRWR: ++ /* These are known opcodes that are not writing/erasing */ ++ break; ++ default: ++ /* Could be writing/erasing; mark buffers dirty */ ++ priv->bspi_hw->flash_upper_addr_byte = cpu_to_le32(0x80); ++ break; ++ } ++ } ++ } ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ ++ if (priv->state == STATE_SHUTDOWN) { ++ spin_unlock_irqrestore(&priv->lock, flags); ++ return -EIO; ++ } ++ ++ msg->actual_length = 0; ++ ++ list_add_tail(&msg->queue, &priv->msg_queue); ++ ++ if (priv->state == STATE_IDLE) { ++ BUG_ON(priv->pos.msg != NULL); ++ priv->pos.msg = msg; ++ priv->pos.trans = list_entry(msg->transfers.next, ++ struct spi_transfer, transfer_list); ++ priv->pos.byte = 0; ++ ++ write_to_hw(priv); ++ } ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) ++static int bcmspi_transfer(struct spi_device *spi, struct spi_message *msg) ++{ ++ return bcmspi_transfer_one(spi->master, msg); ++} ++#endif ++ ++static void bcmspi_cleanup(struct spi_device *spi) ++{ ++ struct bcmspi_parms *xp = spi_get_ctldata(spi); ++ ++ DBG("%s\n", __func__); ++ ++ kfree(xp); ++} ++ ++static irqreturn_t bcmspi_interrupt(int irq, void *dev_id) ++{ ++ struct bcmspi_priv *priv = dev_id; ++ ++ if (priv->bspi_enabled && priv->cur_xfer) { ++ int done = 0; ++ u32 status = bcmspi_read_interrupt(priv); ++ u32 *buf = (u32 *)priv->cur_xfer->rx_buf; ++ if (status & BSPI_LR_INTERRUPTS_DATA) { ++ while (!bcmspi_lr_is_fifo_empty(priv)) { ++ u32 data = bcmspi_lr_read_fifo(priv); ++ if (likely(priv->cur_xfer_len >= 4)) { ++ buf[priv->cur_xfer_idx++] = data; ++ priv->cur_xfer_len -= 4; ++ } else { ++ /* ++ * Read out remaining bytes, make sure ++ * we do not cross the buffer boundary ++ */ ++ u8 *cbuf = ++ (u8 *)&buf[priv->cur_xfer_idx]; ++ data = cpu_to_le32(data); ++ while (priv->cur_xfer_len) { ++ *cbuf++ = (u8)data; ++ data >>= 8; ++ priv->cur_xfer_len--; ++ } ++ } ++ } ++ } ++ if (status & BSPI_LR_INTERRUPTS_ERROR) { ++ dev_err(&priv->pdev->dev, "ERROR %02x\n", status); ++ priv->xfer_status = -EIO; ++ } else if ((status & QSPI_INTR_BSPI_LR_SESSION_DONE_MASK) && ++ priv->cur_xfer_len == 0) { ++ ++ if (priv->raf_next_len) { ++ ++ /* Continuation for reading across 16MB boundary */ ++ bcmspi_disable_interrupt(priv, BSPI_LR_INTERRUPTS_ALL); ++ bcmspi_emulate_flash_read(priv, NULL); ++ return IRQ_HANDLED; ++ ++ } else { ++ done = 1; ++ } ++ } ++ ++ if (done) { ++ priv->cur_xfer = NULL; ++ bcmspi_disable_interrupt(priv, BSPI_LR_INTERRUPTS_ALL); ++ ++ if (priv->xfer_status) { ++ bcmspi_lr_clear(priv); ++ } else { ++ if (priv->cur_msg) { ++ priv->cur_msg->actual_length = priv->actual_length; ++ priv->cur_msg->status = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ spi_finalize_current_message(priv->master); ++#else ++ priv->cur_msg->complete(priv->cur_msg->context); ++#endif ++ } ++ } ++ priv->cur_msg = NULL; ++ } ++ bcmspi_clear_interrupt(priv, status); ++ return IRQ_HANDLED; ++ } ++ ++ if (priv->mspi_hw->mspi_status & cpu_to_le32(1)) { ++ /* clear interrupt */ ++ priv->mspi_hw->mspi_status &= cpu_to_le32(~1); ++ bcmspi_clear_interrupt(priv, QSPI_INTR_MSPI_DONE_MASK); ++ ++ tasklet_schedule(&priv->tasklet); ++ return IRQ_HANDLED; ++ } else ++ return IRQ_NONE; ++} ++ ++static void bcmspi_complete(void *arg) ++{ ++ complete(arg); ++} ++ ++static void bcmspi_tasklet(unsigned long param) ++{ ++ struct bcmspi_priv *priv = (void *)param; ++ struct list_head completed; ++ struct spi_message *msg; ++ unsigned long flags; ++ ++ INIT_LIST_HEAD(&completed); ++ spin_lock_irqsave(&priv->lock, flags); ++ ++ if (priv->next_udelay) { ++ udelay(priv->next_udelay); ++ priv->next_udelay = 0; ++ } ++ ++ msg = priv->pos.msg; ++ ++ read_from_hw(priv, &completed); ++ if (priv->cs_change) { ++ udelay(10); ++ priv->cs_change = 0; ++ } ++ ++ write_to_hw(priv); ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ while (!list_empty(&completed)) { ++ msg = list_first_entry(&completed, struct spi_message, queue); ++ list_del(&msg->queue); ++ msg->status = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ if (msg->complete == bcmspi_complete) ++ msg->complete(msg->context); ++ else ++ spi_finalize_current_message(priv->master); ++#else ++ if (msg->complete) ++ msg->complete(msg->context); ++#endif ++ ++ } ++} ++ ++static struct spi_master *default_master; ++ ++static int bcmspi_simple_transaction(struct bcmspi_parms *xp, ++ const void *tx_buf, int tx_len, void *rx_buf, int rx_len) ++{ ++ DECLARE_COMPLETION_ONSTACK(fini); ++ struct spi_message m; ++ struct spi_transfer t_tx, t_rx; ++ struct spi_device spi; ++ int ret; ++ ++ memset(&spi, 0, sizeof(spi)); ++ spi.max_speed_hz = xp->speed_hz; ++ spi.chip_select = xp->chip_select; ++ spi.mode = xp->mode; ++ spi.bits_per_word = xp->bits_per_word; ++ spi.master = default_master; ++ ++ spi_message_init(&m); ++ m.complete = bcmspi_complete; ++ m.context = &fini; ++ m.spi = &spi; ++ ++ memset(&t_tx, 0, sizeof(t_tx)); ++ memset(&t_rx, 0, sizeof(t_rx)); ++ t_tx.tx_buf = tx_buf; ++ t_tx.len = tx_len; ++ t_rx.rx_buf = rx_buf; ++ t_rx.len = rx_len; ++ ++ if (tx_len) ++ spi_message_add_tail(&t_tx, &m); ++ if (rx_len) ++ spi_message_add_tail(&t_rx, &m); ++ ++ ret = bcmspi_transfer_one(default_master, &m); ++ if (!ret) ++ wait_for_completion(&fini); ++ return ret; ++} ++ ++static void bcmspi_hw_init(struct bcmspi_priv *priv) ++{ ++ const struct bcmspi_parms bcmspi_default_parms_cs0 = { ++ .speed_hz = DEFAULT_SPEED_HZ, ++ .chip_select = 0, ++ .mode = SPI_MODE_3, ++ .bits_per_word = 8, ++ }; ++ ++ priv->mspi_hw->spcr1_lsb = 0; ++ priv->mspi_hw->spcr1_msb = 0; ++ priv->mspi_hw->newqp = 0; ++ priv->mspi_hw->endqp = 0; ++ priv->mspi_hw->spcr2 = cpu_to_le32(0x20); /* spifie */ ++ ++ bcmspi_hw_set_parms(priv, &bcmspi_default_parms_cs0); ++ ++ priv->bspi_enabled = 1; ++ bcmspi_disable_bspi(priv); ++} ++ ++static void bcmspi_hw_uninit(struct bcmspi_priv *priv) ++{ ++ priv->mspi_hw->spcr2 = 0x0; /* disable irq and enable bits */ ++ bcmspi_enable_bspi(priv); ++} ++ ++static int bcmbspi_flash_type(struct bcmspi_priv *priv) ++{ ++ char tx_buf[4]; ++ unsigned char jedec_id[5] = {0}; ++ int bspi_flash; ++ ++ /* Read ID */ ++ tx_buf[0] = OPCODE_RDID; ++ bcmspi_simple_transaction(&priv->last_parms, tx_buf, 1, &jedec_id, 5); ++ ++ switch (jedec_id[0]) { ++ case 0x01: /* Spansion */ ++ case 0xef: ++ bspi_flash = BSPI_FLASH_TYPE_SPANSION; ++ break; ++ case 0xc2: /* Macronix */ ++ bspi_flash = BSPI_FLASH_TYPE_MACRONIX; ++ break; ++ case 0xbf: /* SST */ ++ bspi_flash = BSPI_FLASH_TYPE_SST; ++ break; ++ case 0x89: /* Numonyx */ ++ bspi_flash = BSPI_FLASH_TYPE_NUMONYX; ++ break; ++ default: ++ bspi_flash = BSPI_FLASH_TYPE_UNKNOWN; ++ break; ++ } ++ return bspi_flash; ++} ++ ++static int bcmspi_set_quad_mode(struct bcmspi_priv *priv, int _enable) ++{ ++ char tx_buf[4]; ++ unsigned char cfg_reg, sts_reg; ++ ++ switch (bcmbspi_flash_type(priv)) { ++ case BSPI_FLASH_TYPE_SPANSION: ++ /* RCR */ ++ tx_buf[0] = OPCODE_RCR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &cfg_reg, 1); ++ if (_enable) ++ cfg_reg |= 0x2; ++ else ++ cfg_reg &= ~0x2; ++ /* WREN */ ++ tx_buf[0] = OPCODE_WREN; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, NULL, 0); ++ /* WRR */ ++ tx_buf[0] = OPCODE_WRR; ++ tx_buf[1] = 0; /* status register */ ++ tx_buf[2] = cfg_reg; /* configuration register */ ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 3, NULL, 0); ++ /* wait till ready */ ++ do { ++ tx_buf[0] = OPCODE_RDSR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &sts_reg, 1); ++ udelay(1); ++ } while (sts_reg & 1); ++ break; ++ case BSPI_FLASH_TYPE_MACRONIX: ++ /* RDSR */ ++ tx_buf[0] = OPCODE_RDSR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &cfg_reg, 1); ++ if (_enable) ++ cfg_reg |= 0x40; ++ else ++ cfg_reg &= ~0x40; ++ /* WREN */ ++ tx_buf[0] = OPCODE_WREN; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, NULL, 0); ++ /* WRSR */ ++ tx_buf[0] = OPCODE_WRSR; ++ tx_buf[1] = cfg_reg; /* status register */ ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 2, NULL, 0); ++ /* wait till ready */ ++ do { ++ tx_buf[0] = OPCODE_RDSR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &sts_reg, 1); ++ udelay(1); ++ } while (sts_reg & 1); ++ /* RDSR */ ++ tx_buf[0] = OPCODE_RDSR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &cfg_reg, 1); ++ break; ++ case BSPI_FLASH_TYPE_SST: ++ case BSPI_FLASH_TYPE_NUMONYX: ++ /* TODO - send Quad mode control command */ ++ break; ++ default: ++ return _enable ? -1 : 0; ++ } ++ ++ return 0; ++} ++ ++static int bcmspi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct brcmspi_platform_data *pdata; ++ struct bcmspi_priv *priv; ++ struct spi_master *master; ++ struct resource *res; ++ struct clk *clk; ++ int ret; ++ u32 irq; ++ ++ DBG("bcmspi_probe\n"); ++ ++ pdata = (struct brcmspi_platform_data *)pdev->dev.platform_data; ++ ++ master = spi_alloc_master(dev, sizeof(struct bcmspi_priv)); ++ if (!master) { ++ dev_err(&pdev->dev, "error allocating spi_master\n"); ++ return -ENOMEM; ++ } ++ ++ priv = spi_master_get_devdata(master); ++ ++ priv->pdev = pdev; ++ priv->state = STATE_IDLE; ++ priv->pos.msg = NULL; ++ priv->pos.mspi_16bit = 0; ++ priv->master = master; ++ priv->raf_next_len = 0; ++ ++ master->bus_num = pdev->id; ++ master->num_chipselect = 1; ++ master->mode_bits = SPI_MODE_3; ++ ++ master->setup = bcmspi_setup; ++ master->cleanup = bcmspi_cleanup; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ master->prepare_transfer_hardware = bcmspi_prepare_transfer; ++ master->unprepare_transfer_hardware = bcmspi_unprepare_transfer; ++ master->transfer_one_message = bcmspi_transfer_one; ++ master->transfer = NULL; ++#else ++ master->transfer = bcmspi_transfer; ++#endif ++ ++ priv->mspi_hw = NULL; ++ priv->bspi_hw = NULL; ++ priv->bspi_hw_raf = NULL; ++ priv->qspi_intr = NULL; ++ priv->idm_qspi = NULL; ++ priv->irq = -1; ++ ++#ifdef CONFIG_MACH_CYGNUS ++ /* Get MSPI reference clock and max speed hz */ ++ clk = clk_get_sys(NULL, MSPI_REFCLK_SOURCE); ++ if (!clk) { ++ dev_err(&pdev->dev, "can't get reference clock frequency by %s\n", ++ MSPI_REFCLK_SOURCE); ++ ret = -EIO; ++ goto err2; ++ } ++ ++ if(clk < 0xc0008000) ++ { ++ printk(KERN_INFO "ERROR-Cygnus: QSPI clk=0x%x \n"); ++ } ++ ++ priv->mspi_refclk = 310000 * 2 ;//(unsigned int)25000000 * 2; ++ ++#else ++ /* Get MSPI reference clock and max speed hz */ ++ clk = clk_get_sys(MSPI_REFCLK_SOURCE_DEVID, MSPI_REFCLK_SOURCE); ++ if (!clk) { ++ dev_err(&pdev->dev, "can't get reference clock frequency by %s\n", ++ MSPI_REFCLK_SOURCE); ++ ret = -EIO; ++ goto err2; ++ } ++ priv->mspi_refclk = (unsigned int)clk_get_rate(clk) * 2; ++#endif /* CONFIG_MACH_CYGNUS */ ++ ++ priv->max_speed_hz = priv->mspi_refclk / (2 * SPBR_MIN); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "can't get resource 0\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ /* MSPI register range */ ++ priv->mspi_hw = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->mspi_hw) { ++ dev_err(&pdev->dev, "can't ioremap\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ DBG("priv->mspi_hw=%p\n", priv->mspi_hw); ++ ++ /* BSPI register range */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (res) { ++ priv->bspi_hw = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->bspi_hw) { ++ dev_err(&pdev->dev, "can't ioremap BSPI range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else ++ priv->bspi_hw = NULL; ++ DBG("priv->bspi_hw=%p\n", priv->bspi_hw); ++ ++ /* BSPI_RAF register range */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ if (res) { ++ priv->bspi_hw_raf = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->bspi_hw_raf) { ++ dev_err(&pdev->dev, "can't ioremap BSPI_RAF range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else ++ priv->bspi_hw_raf = NULL; ++ DBG("priv->bspi_hw_raf=%p\n", priv->bspi_hw_raf); ++ ++ /* QSPI interrupt register range */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 3); ++ if (res) { ++ priv->qspi_intr = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->qspi_intr) { ++ dev_err(&pdev->dev, "can't ioremap QSPI interrupt range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else { ++ dev_err(&pdev->dev, "can't get resource 3\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ DBG("priv->qspi_intr=%p\n", priv->qspi_intr); ++ ++ /* IDM QSPI io ctrl register range */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 4); ++ if (res) { ++ priv->idm_qspi = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->idm_qspi) { ++ dev_err(&pdev->dev, "can't ioremap IDM QSPI range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else { ++ dev_err(&pdev->dev, "can't get resource 4\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ DBG("priv->idm_qspi=%p\n", priv->idm_qspi); ++ ++ /* CRU control register */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 5); ++ if (res) { ++ priv->cru_hw = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->cru_hw) { ++ dev_err(&pdev->dev, "can't ioremap CRU range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else { ++ dev_err(&pdev->dev, "can't get resource 4\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ DBG("priv->cru_hw=%p\n", priv->cru_hw); ++ ++ /* IRQ */ ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no IRQ defined\n"); ++ ret = -ENODEV; ++ goto err2; ++ } ++ ++ /* Basic initialization (before enabling interrupts) */ ++ priv->bspi_hw->mast_n_boot_ctrl = cpu_to_le32(1); ++ bcmspi_disable_interrupt(priv, 0xffffffff); ++ bcmspi_clear_interrupt(priv, 0xffffffff); ++ bcmspi_enable_interrupt(priv, QSPI_INTR_MSPI_DONE_MASK); ++ ++ /* Request all IRQs */ ++ for(irq=(u32)res->start; irq<=(u32)res->end; irq++) { ++ ret = request_irq(irq, bcmspi_interrupt, 0, "qspi_iproc", priv); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "unable to allocate IRQ\n"); ++ goto err1; ++ } ++ } ++ ++ bcmspi_hw_init(priv); ++ priv->curr_cs = -1; ++ ++ priv->bspi_chip_select = (priv->bspi_hw && pdata) ? (1 << pdata->flash_cs) : 0; ++ ++ INIT_LIST_HEAD(&priv->msg_queue); ++ spin_lock_init(&priv->lock); ++ ++ platform_set_drvdata(pdev, priv); ++ ++ tasklet_init(&priv->tasklet, bcmspi_tasklet, (unsigned long)priv); ++ ++ ret = spi_register_master(master); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "can't register master\n"); ++ goto err0; ++ } ++ if (!default_master) ++ default_master = master; ++ ++ /* default values - undefined */ ++ priv->flex_mode.width = ++ priv->flex_mode.addrlen = ++ priv->flex_mode.hp = -1; ++ ++ if (priv->bspi_chip_select) { ++ int bspi_width = BSPI_WIDTH_1BIT; ++ ++ /* Module parameter validation */ ++ if (io_mode != 0) { ++ if (read_opcode < 0 || read_opcode > 255) { ++ dev_err(&pdev->dev, "invalid read_opcode\n"); ++ io_mode = 0; ++ } else if (dummy_cycles < 0 || dummy_cycles > 255) { ++ dev_err(&pdev->dev, "invalid dummy_cycles\n"); ++ io_mode = 0; ++ } ++ } ++ if (io_mode == 2) { ++ bspi_width = BSPI_WIDTH_4BIT; ++ } else if (io_mode == 1) { ++ bspi_width = BSPI_WIDTH_2BIT; ++ } else if (io_mode != 0) { ++ dev_err(&pdev->dev, "invalid io_mode (0/1/2)\n"); ++ } ++ ++ if (io_mode == 2) ++ bcmspi_set_quad_mode(priv, 1); ++ ++ bcmspi_set_mode(priv, bspi_width, BSPI_ADDRLEN_3BYTES, bspi_hp); ++ } ++ ++ return 0; ++ ++err0: ++ bcmspi_hw_uninit(priv); ++err1: ++ for(irq=(u32)res->start; irq<=(u32)res->end; irq++) { ++ free_irq(irq, priv); ++ } ++err2: ++ if (priv->idm_qspi) { ++ iounmap(priv->idm_qspi); ++ } ++ if (priv->qspi_intr) { ++ iounmap(priv->qspi_intr); ++ } ++ if (priv->bspi_hw_raf) { ++ iounmap(priv->bspi_hw_raf); ++ } ++ if (priv->bspi_hw) { ++ iounmap(priv->bspi_hw); ++ } ++ if (priv->mspi_hw) { ++ iounmap(priv->mspi_hw); ++ } ++ spi_master_put(master); ++ return ret; ++} ++ ++static int bcmspi_remove(struct platform_device *pdev) ++{ ++ struct bcmspi_priv *priv = platform_get_drvdata(pdev); ++ unsigned long flags; ++ struct resource *res; ++ u32 irq; ++ ++ /* acquire lock when the MSPI is idle */ ++ while (1) { ++ spin_lock_irqsave(&priv->lock, flags); ++ if (priv->state == STATE_IDLE) ++ break; ++ spin_unlock_irqrestore(&priv->lock, flags); ++ udelay(100); ++ } ++ priv->state = STATE_SHUTDOWN; ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ tasklet_kill(&priv->tasklet); ++ platform_set_drvdata(pdev, NULL); ++ bcmspi_hw_uninit(priv); ++ if (priv->bspi_hw_raf) ++ iounmap(priv->bspi_hw_raf); ++ if (priv->bspi_hw) ++ iounmap((volatile void __iomem *)priv->bspi_hw); ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (res) { ++ for(irq=(u32)res->start; irq<=(u32)res->end; irq++) { ++ free_irq(irq, priv); ++ } ++ } ++ iounmap((volatile void __iomem *)priv->mspi_hw); ++ spi_unregister_master(priv->master); ++ ++ return 0; ++} ++ ++static struct platform_driver driver = { ++ .driver = { ++ .name = "qspi_iproc", ++ .bus = &platform_bus_type, ++ .owner = THIS_MODULE, ++ }, ++ .probe = bcmspi_probe, ++ .remove = __devexit_p(bcmspi_remove), ++}; ++ ++static int __init bcmspi_spi_init(void) ++{ ++ platform_driver_register(&driver); ++ return 0; ++} ++ ++static void __exit bcmspi_spi_exit(void) ++{ ++ platform_driver_unregister(&driver); ++} ++ ++module_init(bcmspi_spi_init); ++module_exit(bcmspi_spi_exit); ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("iProc QSPI driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/smbus/.gitignore b/drivers/bcmdrivers/smbus/.gitignore +new file mode 100644 +index 0000000..0f97013 +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/.iproc_i2c.o.cmd ++/.iproc_smbus.o.cmd ++/built-in.o ++/iproc_i2c.o ++/iproc_smbus.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/smbus/Kconfig b/drivers/bcmdrivers/smbus/Kconfig +new file mode 100644 +index 0000000..9ae0f71 +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/Kconfig +@@ -0,0 +1,8 @@ ++config IPROC_I2C ++ tristate "I2C support" ++ depends on ARCH_IPROC ++ default n ++ help ++ I2C support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/smbus/Makefile b/drivers/bcmdrivers/smbus/Makefile +new file mode 100644 +index 0000000..812c7a1 +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_I2C) += iproc_i2c.o ++iproc_i2c-objs := iproc_smbus.o +diff --git a/drivers/bcmdrivers/smbus/iproc_smbus.c b/drivers/bcmdrivers/smbus/iproc_smbus.c +new file mode 100644 +index 0000000..49e25d6 +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/iproc_smbus.c +@@ -0,0 +1,2043 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "iproc_smbus_regs.h" ++#include "iproc_smbus_defs.h" ++#include "iproc_smbus.h" ++#include ++#include ++#include ++#include ++#include ++ ++//#define IPROC_SMB_DBG 1 ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 37) ++#define init_MUTEX(x) sema_init(x,1) ++#endif ++ ++int brcm_get_hx4_model(void); ++ ++static struct proc_dir_entry *gProcParent; ++static int use_svk_version; ++ ++static int smb_in_intr; ++ ++static struct iproc_smb_drv_int_data *iproc_smbus_list = NULL; ++static int iproc_smbus_block_init(struct iproc_smb_drv_int_data *dev); ++ ++/* Function to read a value from specified register. */ ++static unsigned int iproc_smb_reg_read(unsigned long reg_addr) ++{ ++ unsigned int val; ++ ++ val = ioread32((void *)reg_addr); ++ ++#ifdef IPROC_SMB_DBG ++ if (!smb_in_intr) { ++ printk(KERN_DEBUG "\nRd: addr:0x%08X, val:0x%08X", (unsigned int)reg_addr, val); ++ } ++#endif ++ ++ return(val); ++} ++ ++/* Function to write a value ('val') in to a specified register. */ ++static int iproc_smb_reg_write(unsigned long reg_addr, unsigned int val) ++{ ++ iowrite32(val, (void *)reg_addr); ++ ++#ifdef IPROC_SMB_DBG ++ if (!smb_in_intr) { ++ printk(KERN_DEBUG "\nWr: addr:0x%08X, val:0x%08X", (unsigned int)reg_addr, val); ++ } ++#endif ++ ++ return (0); ++} ++ ++static int iproc_dump_smb_regs(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int regval; ++ unsigned long base_addr = (unsigned long)dev->block_base_addr; ++ ++ printk(KERN_DEBUG "\n----------------------------------------------"); ++ ++ printk(KERN_DEBUG "\nBase addr=0x%08X", (unsigned int)base_addr); ++ ++ printk(KERN_DEBUG "%s: Dumping SMBus registers... ", __func__); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_CFG_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_CFG_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_TIMGCFG_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_TIMGCFG_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_ADDR_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_ADDR_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRFIFOCTL_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_MSTRFIFOCTL_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVFIFOCTL_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_SLVFIFOCTL_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_BITBANGCTL_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_BITBANGCTL_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRCMD_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_MSTRCMD_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVCMD_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_SLVCMD_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTEN_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_EVTEN_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTSTS_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_EVTSTS_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRDATAWR_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_MSTRDATAWR_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRDATARD_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_MSTRDATARD_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVDATAWR_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_SLVDATAWR_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVDATARD_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_SLVDATARD_REG=0x%08X", regval); ++ ++ printk(KERN_DEBUG "\n----------------------------------------------\n\n"); ++ ++ return(0); ++} ++ ++static irqreturn_t iproc_smb_isr(int irq, void*devid) ++{ ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)devid; ++ unsigned int intsts; ++ unsigned int regval; ++ ++ ++ smb_in_intr = 1; ++ ++ intsts = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTSTS_REG); ++ ++ dev->smb_counters.last_int_sts = intsts; ++ ++ if (!intsts) { ++ ++ /* Likely received a spurious interrupt */ ++ ++ return IRQ_NONE; ++ ++ } ++ ++ /* Clear interrupts */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTSTS_REG, intsts); ++ ++ /* Master read or write complete */ ++ if ((intsts & CCB_SMB_MSTRSTARTBUSYEN_MASK) || ++ (intsts & CCB_SMB_MSTRRXEVTSTS_MASK)) { ++ ++ if (intsts & CCB_SMB_MSTRSTARTBUSYEN_MASK) { ++ ++ dev->smb_counters.mstr_start_busy_cnt++; ++ ++ } ++ ++ if (intsts & CCB_SMB_MSTRRXEVTSTS_MASK) { ++ ++ dev->smb_counters.mstr_rx_evt_cnt++; ++ ++ } ++ ++ /* In case of a receive transaction, data will be copied in the recv ++ * function ++ */ ++ complete(&dev->ses_done); ++ ++ } ++ ++ /* If RX FIFO was full we can either read and then flush the FIFO. Or, only ++ * flush the FIFO (since the client process did not read the data on time), ++ * and then the client process can restart the transaction ++ * For now, we will flush the later action. ++ */ ++ if (intsts & CCB_SMB_MSTRRXFIFOFULLSTS_MASK) { ++ ++ dev->smb_counters.mstr_rx_fifo_full_cnt++; ++ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRFIFOCTL_REG); ++ ++ regval |= CCB_SMB_MSTRRXFIFOFLSH_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRFIFOCTL_REG, regval); ++ ++ complete(&dev->ses_done); ++ ++ } ++ ++ smb_in_intr = 0; ++ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * Function to ensure that the previous transaction was completed before ++ * initiating a new transaction. It can also be used in polling mode to ++ * check status of completion of a command ++ */ ++static int iproc_smb_startbusy_wait(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int regval; ++ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG); ++ ++ /* Check if an operation is in progress. During probe it won't be. ++ * But when shutdown/remove was called we want to make sure that ++ * the transaction in progress completed ++ */ ++ if (regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) { ++ unsigned int i = 0; ++ ++ do { ++ ++ msleep(1); /* Wait for 1 msec */ ++ ++ i++; ++ ++ regval = iproc_smb_reg_read( ++ (unsigned long)dev->block_base_addr + CCB_SMB_MSTRCMD_REG); ++ ++ /* If start-busy bit cleared, exit the loop */ ++ } while ((regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) && ++ (i < IPROC_SMB_MAX_RETRIES)); ++ ++ if (i >= IPROC_SMB_MAX_RETRIES) { ++#ifdef IPROC_SMB_DBG ++ printk(KERN_ERR "%s: %s START_BUSY bit didn't clear, exiting\n", ++ __func__, dev->adapter.name); ++#endif ++ return -ETIMEDOUT; ++ ++ } ++ ++ } ++ ++ return 0; ++} ++ ++ ++static unsigned int smbus0_sdaRecoveryCnt = 0, smbus0_sdaFailedCnt = 0, smbus0_startBusyCnt = 0; ++static unsigned int smbus1_sdaRecoveryCnt = 0, smbus1_sdaFailedCnt = 0, smbus1_startBusyCnt = 0; ++ ++/* ++ * Function to recover SMB hangs caused stuck master START_BUSY. ++ * Returns 0 if recovery procedure executed successfully. ++ * Returns -1 if recovery failed. ++ */ ++static int iproc_smb_startbusy_recovery(struct iproc_smb_drv_int_data *dev) ++{ ++ int rc = -1; ++ unsigned int recoveryCnt; ++ ++ if (dev->adapter.nr == 0) { ++ recoveryCnt = ++smbus0_startBusyCnt; ++ } ++ else { ++ recoveryCnt = ++smbus1_startBusyCnt; ++ } ++ ++ printk(KERN_INFO "%s: %s START_BUSY recovery #%d \n", __func__, dev->adapter.name, recoveryCnt); ++ ++ /* reset the SMBus block, wait a minimum of 50 uSecs and then re-initialize */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, CCB_SMB_CFG_RST_MASK); ++ udelay(60); ++ ++ if ( iproc_smbus_block_init(dev) == 0 ) { ++ rc = 0; ++ } ++ ++ return rc; ++} ++ ++ ++ ++/* ++ * Function to recover SMB hang caused by a slave device holding SDA low. ++ * Returns 0 if recovery procedure executed successfully. ++ * Returns -1 if recovery failed. ++ */ ++ ++static int iproc_smb_sda_low_recovery(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int bbReg, cfgReg, cfgSave, recoveryCnt, failedCnt, i; ++ int rc = -1; ++ ++ ++ /* enable bit-bang */ ++ cfgSave = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); ++ cfgReg = cfgSave; ++ cfgReg |= CCB_SMB_CFG_BITBANGEN_MASK; ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, cfgReg); ++ udelay(50); ++ ++ /* start with clock and SDA set high */ ++ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); ++ ++ bbReg |= (CCB_SMB_SMBCLKOUTEN_MASK | CCB_SMB_SMBDATAOUTEN_MASK); ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(5); /* should be sufficient for 100 KHz bus */ ++ ++ /* set up to toggle the clock line with SDA out held high for 9 cycles */ ++ for (i=0; i<18; i++) ++ { ++ /* toggle CLK out */ ++ if ( (bbReg & CCB_SMB_SMBCLKOUTEN_MASK) == 0 ) { ++ bbReg |= CCB_SMB_SMBCLKOUTEN_MASK; /* set clock high */ ++ } ++ else { ++ bbReg &= ~CCB_SMB_SMBCLKOUTEN_MASK; /* set clock low */ ++ } ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(5); ++ } ++ ++ /* check bit 29 -- SMBDAT_IN and make sure SDA not being held low any more */ ++ for ( i=0; i<10; i++ ) ++ { ++ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); ++ bbReg &= CCB_SMB_SMBDATAIN_MASK; ++ ++ if (bbReg) ++ break; ++ ++ udelay(1); ++ } ++ ++ if ( bbReg == 0 ) { ++ /* SDA is still low */ ++ if (dev->adapter.nr == 0) { ++ failedCnt = ++smbus0_sdaFailedCnt; ++ } ++ else { ++ failedCnt = ++smbus1_sdaFailedCnt; ++ } ++ printk(KERN_INFO "\n%s: %s SDA release #%d FAILED.\n", __func__, dev->adapter.name, failedCnt); ++ } ++ else { ++ if (dev->adapter.nr == 0) { ++ recoveryCnt = ++smbus0_sdaRecoveryCnt; ++ } ++ else { ++ recoveryCnt = ++smbus1_sdaRecoveryCnt; ++ } ++ ++ printk(KERN_INFO "%s: %s SDA release #%d SUCCESSFUL.\n", __func__, dev->adapter.name, recoveryCnt); ++ rc = 0; ++ } ++ ++ ++ /* manually issue a stop by transitioning SDA from low to high with clock held high */ ++ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); ++ bbReg &= ~CCB_SMB_SMBCLKOUTEN_MASK; /* set clock low */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(2); ++ ++ bbReg &= ~CCB_SMB_SMBDATAOUTEN_MASK; /* drop SDA low */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(2); ++ ++ bbReg |= CCB_SMB_SMBCLKOUTEN_MASK; /* set clock high */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(5); ++ ++ bbReg |= CCB_SMB_SMBDATAOUTEN_MASK; /* pull SDA high */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(2); ++ ++ ++ /* disable bit-bang and then re-enable the SMB with the saved configuration */ ++ cfgReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); ++ cfgReg &= ~CCB_SMB_CFG_BITBANGEN_MASK; ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, cfgReg); ++ udelay(10); ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, cfgSave); ++ ++ return rc; ++} ++ ++ ++/* ++ * Function to recover SMB hang caused by a slave device hold SDA low. ++ * Returns 0 if recovery procedure executed successfully. ++ * Returns -1 if recovery failed. ++ */ ++static int iproc_smb_timeout_recovery(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int bbReg, mCmdReg; ++ int rc = -1; ++ ++ /* read bit-bang control. If SDA low, attempt SDA release recovery */ ++ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); ++ ++ if ( (bbReg & CCB_SMB_SMBDATAIN_MASK) == 0 ) { ++ if ( iproc_smb_sda_low_recovery( dev ) == 0 ) { ++ rc = 0; ++ } ++ } ++ ++ /* regardless of whether there was an SDA hang or not, see if START_BUSY stuck high */ ++ mCmdReg = iproc_smb_reg_read( (unsigned long)dev->block_base_addr + CCB_SMB_MSTRCMD_REG ); ++ if ( mCmdReg & CCB_SMB_MSTRSTARTBUSYCMD_MASK ) { ++ /* attempt to recover the bus */ ++ if (iproc_smb_startbusy_recovery(dev) == 0) { ++ rc = 0; ++ } ++ } ++ ++ return rc; ++ ++} ++ ++/* ++ * This function copies data to SMBus's Tx FIFO. Valid for write transactions ++ * only ++ * ++ * base_addr: Mapped address of this SMBus instance ++ * dev_addr: SMBus (I2C) device address. We are assuming 7-bit addresses ++ * initially ++ * info: Data to copy in to Tx FIFO. For read commands, the size should be ++ * set to zero by the caller ++ * ++ */ ++static void iproc_smb_write_trans_data(unsigned long base_addr, ++ unsigned short dev_addr, ++ struct iproc_xact_info *info) ++{ ++ unsigned int regval; ++ unsigned int i; ++ unsigned int num_data_bytes = 0; ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n%s: dev_addr=0x%X, offset=%u, cmd_valid=%u, size=%u\n", __func__, dev_addr, info->command, info->cmd_valid, info->size); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Write SMBus device address first */ ++ /* Note, we are assuming 7-bit addresses for now. For 10-bit addresses, ++ * we may have one more write to send the upper 3 bits of 10-bit addr ++ */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, dev_addr); ++ ++ /* If the protocol needs command code, copy it */ ++ if (info->cmd_valid == true) { ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, info->command); ++ ++ } ++ ++ /* Depending on the SMBus protocol, we need to write additional transaction ++ * data in to Tx FIFO. Refer to section 5.5 of SMBus spec for sequence for a ++ * transaction ++ */ ++ switch (info->smb_proto) { ++ ++ case SMBUS_PROT_RECV_BYTE: ++ /* No additional data to be written */ ++ num_data_bytes = 0; ++ break; ++ ++ case SMBUS_PROT_SEND_BYTE: ++ num_data_bytes = info->size; ++ break; ++ ++ case SMBUS_PROT_RD_BYTE: ++ case SMBUS_PROT_RD_WORD: ++ case SMBUS_PROT_BLK_RD: ++ /* Write slave address with R/W~ set (bit #0) */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, ++ dev_addr | 0x1); ++ num_data_bytes = 0; ++ break; ++ ++ case SMBUS_PROT_WR_BYTE: ++ case SMBUS_PROT_WR_WORD: ++ /* No additional bytes to be written. Data portion is written in the ++ * 'for' loop below ++ */ ++ num_data_bytes = info->size; ++ ++ /* Note for hx4 eeprom (at24c64). the low addr bytes can be passed ++ * in to 1st byte of info->data ++ */ ++ break; ++ ++ case SMBUS_PROT_BLK_WR: ++ /* 3rd byte is byte count */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, info->size); ++ num_data_bytes = info->size; ++ break; ++ ++ case SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL: ++ /* Write byte count */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, info->size); ++ num_data_bytes = info->size; ++ break; ++ ++ default: ++ break; ++ ++ } ++ ++ /* Copy actual data from caller, next. In general, for reads, no data is ++ * copied ++ */ ++ for (i = 0; num_data_bytes; --num_data_bytes, i++) { ++ ++ /* For the last byte, set MASTER_WR_STATUS bit. For block rd/wr process ++ * call, we need to program slave addr after copying data byte(s), so ++ * master status bit is set later, after the loop ++ */ ++ if ((num_data_bytes == 1) && ++ (info->smb_proto != SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { ++ regval = info->data[i] | CCB_SMB_MSTRWRSTS_MASK; ++ } ++ else { ++ regval = info->data[i]; ++ } ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, regval); ++ ++ } ++ ++ if (info->smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL) { ++ /* Write device address needed during repeat start condition */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, ++ CCB_SMB_MSTRWRSTS_MASK | dev_addr | 0x1); ++ } ++ ++ return; ++} ++ ++static int iproc_smb_data_send(struct i2c_adapter *adapter, ++ unsigned short addr, ++ struct iproc_xact_info *info) ++{ ++ int rc; ++ unsigned int regval; ++ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(adapter); ++ unsigned long time_left; ++ ++ ++ /* Make sure the previous transaction completed */ ++ rc = iproc_smb_startbusy_wait(dev); ++ ++ if (rc < 0) { ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_ERR "%s: Send: %s bus is busy, attempt recovery \n", ++ __func__, dev->adapter.name); ++#endif ++ /* attempt to recover the bus */ ++ if (iproc_smb_startbusy_recovery(dev) != 0) { ++ ++ return rc; ++ ++ } ++ } ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ ++ /* Enable start_busy interrupt */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG); ++ ++ regval |= CCB_SMB_MSTRSTARTBUSYEN_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG, regval); ++ ++ /* Mark as incomplete before sending the data */ ++ INIT_COMPLETION(dev->ses_done); ++ ++ } ++ ++ /* Write transaction bytes to Tx FIFO */ ++ iproc_smb_write_trans_data((unsigned long)dev->block_base_addr, addr, info); ++ ++ /* Program master command register (0x30) with protocol type and set ++ * start_busy_command bit to initiate the write transaction ++ */ ++ regval = (info->smb_proto << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | ++ CCB_SMB_MSTRSTARTBUSYCMD_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG, regval); ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ ++ /* ++ * Block waiting for the transaction to finish. When it's finished, ++ * we'll be signaled by an interrupt ++ */ ++ time_left = wait_for_completion_timeout(&dev->ses_done, XACT_TIMEOUT); ++ ++ /* Disable start_busy interrupt */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG); ++ ++ regval &= ~CCB_SMB_MSTRSTARTBUSYEN_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG, regval); ++ ++ if (time_left == 0) { ++ ++ printk (KERN_INFO "%s: Send: %s timeout accessing device x%02x\n", ++ __func__, dev->adapter.name, addr); ++ ++ /* attempt to recover the bus */ ++ rc = iproc_smb_timeout_recovery(dev); ++ if ( rc != 0 ) { ++ ++ return -ETIMEDOUT; ++ ++ } ++ else { ++ return -ECOMM; ++ } ++ ++ } ++ ++ } ++ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG); ++ ++ /* If start_busy bit cleared, check if there are any errors */ ++ if (!(regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK)) { ++ ++ /* start_busy bit cleared, check master_status field now */ ++ regval &= CCB_SMB_MSTRSTS_MASK; ++ regval >>= CCB_SMB_MSTRSTS_SHIFT; ++ ++ if (regval != MSTR_STS_XACT_SUCCESS) { ++ ++ /* We can flush Tx FIFO here */ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n\n%s:Send: %s Error in transaction %d to device x%02x, exiting\n", ++ __func__, dev->adapter.name, regval, addr); ++#endif ++ return -EREMOTEIO; ++ ++ } ++ } ++ ++ return(0); ++} ++ ++static int iproc_smb_data_recv(struct i2c_adapter *adapter, ++ unsigned short addr, ++ struct iproc_xact_info *info, ++ unsigned int *num_bytes_read) ++{ ++ int rc; ++ unsigned int regval; ++ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(adapter); ++ unsigned long time_left; ++ ++ /* Make sure the previous transaction completed */ ++ rc = iproc_smb_startbusy_wait(dev); ++ ++ if (rc < 0) { ++#ifdef IPROC_SMB_DBG ++ printk(KERN_ERR "%s: Receive: %s bus is busy, attempt recovery \n", __func__, dev->adapter.name); ++#endif ++ /* attempt to recover the bus */ ++ if (iproc_smb_startbusy_recovery(dev) != 0) { ++ return rc; ++ } ++ } ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ ++ /* Enable start_busy interrupt */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG); ++ ++ /* Set Rx_event_en bit for notification of reception event */ ++ regval |= (CCB_SMB_MSTRSTARTBUSYEN_MASK); ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG, regval); ++ ++ /* Mark as incomplete before sending the data */ ++ INIT_COMPLETION(dev->ses_done); ++ ++ } ++ ++ /* Program all transaction bytes into master Tx FIFO */ ++ iproc_smb_write_trans_data((unsigned long)dev->block_base_addr, addr, info); ++ ++ /* Program master command register (0x30) with protocol type and set ++ * start_busy_command bit to initiate the write transaction ++ */ ++ regval = (info->smb_proto << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | ++ CCB_SMB_MSTRSTARTBUSYCMD_MASK | info->size; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG, regval); ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ ++ /* ++ * Block waiting for the transaction to finish. When it's finished, ++ * we'll be signaled by an interrupt ++ */ ++ time_left = wait_for_completion_timeout(&dev->ses_done, XACT_TIMEOUT); ++ ++ /* Disable start_busy and rx_event interrupts. Above call has handled ++ * the interrupt ++ */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG); ++ ++ regval &= ~(CCB_SMB_MSTRSTARTBUSYEN_MASK); ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG, regval); ++ ++ if (time_left == 0) { ++ ++ printk (KERN_INFO "\n%s: Receive: %s timeout accessing device 0x%02x\n", ++ __func__, dev->adapter.name, addr); ++ ++ /* attempt to recover the bus */ ++ rc = iproc_smb_timeout_recovery(dev); ++ if ( rc != 0 ) { ++ return -ETIMEDOUT; ++ } ++ else { ++ return -ECOMM; ++ } ++ } ++ ++ } ++ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG); ++ ++ /* If start_busy bit cleared, check if there are any errors */ ++ if (!(regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK)) { ++ ++ /* start_busy bit cleared, check master_status field now */ ++ regval &= CCB_SMB_MSTRSTS_MASK; ++ regval >>= CCB_SMB_MSTRSTS_SHIFT; ++ ++ if (regval != MSTR_STS_XACT_SUCCESS) { ++#ifdef IPROC_SMB_DBG ++ /* We can flush Tx FIFO here */ ++ printk(KERN_INFO "\n%s: %s Error in transaction %d to device x%02x, exiting\n", ++ __func__, dev->adapter.name, regval, addr); ++#endif ++ return -EREMOTEIO; ++ ++ } ++ ++ } ++ ++ /* In the isr we will read the received byte, and also deal with ++ * rx fifo full event. The above check is for timeout error. If needed ++ * we may move it to rx isr ++ */ ++ ++ /* Read received byte(s) */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRDATARD_REG); ++ ++ /* For block read, protocol (hw) returns byte count, as the first byte */ ++ if ((info->smb_proto == SMBUS_PROT_BLK_RD) || ++ (info->smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { ++ ++ int i; ++ ++ *num_bytes_read = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ /* Limit to reading a max of 32 bytes only; just a safeguard. If ++ * # bytes read is a number > 32, check transaction set up, and contact ++ * hw engg. Assumption: PEC is disabled ++ */ ++ for (i = 0; (i < *num_bytes_read) && (i < I2C_SMBUS_BLOCK_MAX); i++) { ++ ++ /* Read Rx FIFO for data bytes */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRDATARD_REG); ++ ++ info->data[i] = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ } ++ ++ } ++ else { ++ ++ *info->data = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ *num_bytes_read = 1; ++ ++ if (info->smb_proto == SMBUS_PROT_RD_WORD) { ++ /* Read Rx FIFO for data bytes */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRDATARD_REG); ++ ++ info->data[1] = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ *num_bytes_read = 2; ++ } ++ } ++ ++ return(0); ++} ++ ++static int iproc_smb_xfer(struct i2c_adapter *i2c_adap, u16 addr, ++ unsigned short flags, char read_write, ++ u8 command, int size, union i2c_smbus_data *data) ++{ ++ int rc; ++ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(i2c_adap); ++ struct iproc_xact_info info; ++ unsigned int num_bytes_read = 0; ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n%s: dev=0x%08X\n", __func__, (unsigned int)dev); ++#endif ++ ++ down(&dev->xfer_lock); ++ ++ addr <<= 1; ++ ++ switch (size /* protocol */) { ++ ++ case I2C_SMBUS_QUICK: ++ info.cmd_valid = false; ++ info.command = command; /* not used */ ++ info.smb_proto = SMBUS_PROT_QUICK_CMD; ++ info.data = &data->byte; /* not used */ ++ info.size = 0; ++ info.flags = flags; ++ if (read_write == I2C_SMBUS_READ) { ++ addr |= 0x1; /* read operation */ ++ } ++ break; ++ ++ case I2C_SMBUS_BYTE: ++ info.cmd_valid = false; ++ info.command = command; /* not used */ ++ if (read_write == I2C_SMBUS_WRITE) { ++ ++ info.data = &command; ++ ++ } ++ else { ++ ++ info.data = &data->byte; ++ ++ } ++ info.size = 1; ++ info.flags = flags; ++ ++ if (read_write == I2C_SMBUS_READ) { ++ ++ addr |= 0x1; /* Read operation */ ++ ++ info.smb_proto = SMBUS_PROT_RECV_BYTE; ++ info.data = &data->byte; ++ ++ } ++ else { ++ ++ info.smb_proto = SMBUS_PROT_SEND_BYTE; ++ ++ } ++ break; ++ ++ case I2C_SMBUS_BYTE_DATA: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = &data->byte; ++ info.size = 1; ++ info.flags = flags; ++ ++ if (read_write == I2C_SMBUS_READ) { ++ ++ info.smb_proto = SMBUS_PROT_RD_BYTE; ++ ++ } ++ else { ++ ++ info.smb_proto = SMBUS_PROT_WR_BYTE; ++ //info.smb_proto = SMBUS_PROT_WR_WORD; /* TEMP chg. remove later */ ++ ++ } ++ break; ++ ++ case I2C_SMBUS_WORD_DATA: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = (unsigned char *)(&data->word); ++ info.size = 2; ++ info.flags = flags; ++ if (read_write == I2C_SMBUS_READ) { ++ info.smb_proto = SMBUS_PROT_RD_WORD; ++ } ++ else { ++ info.smb_proto = SMBUS_PROT_WR_WORD; ++ } ++ ++ break; ++ ++ case I2C_SMBUS_BLOCK_DATA: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = &data->block[1]; ++ info.flags = flags; ++ ++ if (read_write == I2C_SMBUS_READ) { ++ ++ info.smb_proto = SMBUS_PROT_BLK_RD; ++ ++ /* Protocol(hw) returns data byte count as part of response */ ++ info.size = 0; ++ ++ } ++ else { ++ ++ info.smb_proto = SMBUS_PROT_BLK_WR; ++ ++ info.size = data->block[0]; /* i2c-core passes the length in ++ this field */ ++ ++ } ++ ++ break; ++ ++ case I2C_SMBUS_BLOCK_PROC_CALL: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = &data->block[1]; ++ info.flags = flags; ++ info.smb_proto = SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL; ++ break; ++ ++ default: ++ printk(KERN_ERR "%s: Unsupported transaction %d\n", __func__, size); ++ up(&dev->xfer_lock); ++ return -EINVAL; ++ ++ } ++ ++ ++ if (read_write == I2C_SMBUS_READ) { ++ /* Refer to i2c_smbus_read_byte for params passed. */ ++ rc = iproc_smb_data_recv(i2c_adap, addr, &info, &num_bytes_read); ++ ++ /* if failed due to bus hang, but recovered, retry once */ ++ if (rc == -ECOMM) { ++ rc = iproc_smb_data_recv(i2c_adap, addr, &info, &num_bytes_read); ++ } ++ ++ /* For block read call, we pass the actual amount of data sent by ++ * slave, as expected by std Linux API ++ */ ++ if ((info.smb_proto == SMBUS_PROT_BLK_RD) || ++ (info.smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { ++ ++ if (rc == 0) { ++ ++ data->block[0] = num_bytes_read; ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_ERR "%s: num bytes read=%u\n", ++ __func__, data->block[0]); ++#endif ++ ++ } ++ } ++ ++ } ++ else { ++ ++ /* Refer to i2c_smbus_write_byte params passed. */ ++ rc = iproc_smb_data_send(i2c_adap, addr, &info); ++ ++ /* if failed due to bus hang, but recovered, retry */ ++ if (rc == -ECOMM) { ++ rc = iproc_smb_data_send(i2c_adap, addr, &info); ++ } ++ ++ } ++ ++ if (rc < 0) { ++#ifdef PROC_SMB_DBG ++ printk(KERN_INFO "%s %s: %s error accessing device 0x%X rc=%d", __func__, dev->adapter.name, ++ (read_write == I2C_SMBUS_READ) ? "Read" : "Write", addr, rc); ++#endif ++ up(&dev->xfer_lock); ++ ++ return -EREMOTEIO; ++ ++ } ++ ++ up(&dev->xfer_lock); ++ ++ return (rc); ++} ++ ++static int ++proc_debug_read(char *buffer, ++ char **start, ++ off_t off, ++ int count, ++ int *eof, ++ void *data) ++{ ++ unsigned int len = 0; ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)data; ++ ++ if (off > 0) ++ return 0; ++ ++ len += sprintf(buffer + len, "Debug print is %s\n", ++ dev->debug ? "enabled" : "disabled"); ++ ++ return len; ++} ++ ++/* Command interface for reading/writing to various I2C/SMBus devices */ ++static int ++proc_debug_write(struct file *file, ++ const char __user *buffer, ++ unsigned long count, ++ void *data) ++{ ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)data; ++ int rc; ++ unsigned char kbuf[MAX_PROC_BUF_SIZE]; ++ union i2c_smbus_data i2cdata; ++ unsigned int val, i2cdev_addr, rd_wr_op; ++ int addr; ++ ++ if (count > MAX_PROC_BUF_SIZE) { ++ ++ count = MAX_PROC_BUF_SIZE; ++ ++ } ++ ++ rc = copy_from_user(kbuf, buffer, count); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: copy_from_user failed status=%d", __func__, rc); ++ ++ return -EFAULT; ++ ++ } ++ ++ rc = sscanf(kbuf, "%u %u %d %u", &rd_wr_op, &i2cdev_addr, &addr, &val); ++ ++ if (rc != 4) { ++ ++ printk(KERN_ERR "\necho args > %s", PROC_ENTRY_DEBUG); ++ printk(KERN_ERR "\nargs (all values should be in decimal)):"); ++ printk(KERN_ERR "\nrd_wr_op: 1 = read, 0 = write"); ++ printk(KERN_ERR "\ni2cdev_addr: I2C device address in decimal"); ++ printk(KERN_ERR "\noffset: offset of location within I2C device"); ++ printk(KERN_ERR "\naddr -1 if offset not applicable"); ++ printk(KERN_ERR "\nval: For write op: 8-bit value.\n" ++ " For read op: not used, may be 0\n\n"); ++ ++ return count; ++ ++ } ++ ++ printk(KERN_DEBUG "\n\nArg values :"); ++ printk(KERN_DEBUG "\nrd_wr_op = %u", rd_wr_op); ++ printk(KERN_DEBUG "\ni2cdev_addr = 0x%X", i2cdev_addr); ++ printk(KERN_DEBUG "\noffset = %d", addr); ++ printk(KERN_DEBUG "\nval = %u", val); ++ ++ if (rd_wr_op > 1) { ++ ++ printk(KERN_ERR "\nError: Invalid rd_wr_op value %u\n\n", rd_wr_op); ++ return count; ++ ++ } ++ ++ if (i2cdev_addr > 127) { ++ ++ printk(KERN_ERR "\nError: i2cdev_addr must be 7-bit value\n\n"); ++ return count; ++ ++ } ++ ++ if (addr > 255) { ++ ++ printk(KERN_ERR "\nError: offset out of range for this device\n\n"); ++ return count; ++ ++ } ++ ++ printk (KERN_ERR "\nCommand can execute slow, please wait...\n"); ++ ++ if (rd_wr_op == 0) { /* Write operation */ ++ ++ i2cdata.byte = val; ++ ++ if (addr == -1) { ++ ++ /* Device does not support, or require an offset to write to the ++ * location ++ */ ++ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, ++ I2C_SMBUS_WRITE, (unsigned char)0, ++ I2C_SMBUS_BYTE, &i2cdata); ++ ++ } ++ else { ++ ++ /* Address required for write access */ ++ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, ++ I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, ++ &i2cdata); ++ } ++ ++ if (rc) { ++ ++ printk (KERN_ERR "\n%s: iproc_smb_xfer:write failed status=%d," ++ " addr=%u, val = 0x%X\n", __func__, rc, addr, val); ++ ++ /* return -EFAULT; */ ++ ++ } ++ else { ++ ++ printk(KERN_ERR "\nWrite OK.\nWrote 0x%X at addr %u\n\n", ++ val, addr); ++ ++ } ++ ++ msleep(1); /* Delay required, since smb(i2c) interface is slow */ ++ ++ } ++ ++ if (rd_wr_op == 1) { /* Read operation */ ++ ++ if (addr == -1) { ++ ++ /* Device does not support, or require an offset to read from the ++ * location ++ */ ++ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, I2C_SMBUS_READ, ++ (unsigned char)0, I2C_SMBUS_BYTE, &i2cdata); ++ ++ } ++ else { ++ ++ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, I2C_SMBUS_READ, ++ addr, I2C_SMBUS_BYTE_DATA, &i2cdata); ++ ++ } ++ ++ if (rc) { ++ ++ printk (KERN_ERR "\n%s: iproc_smb_xfer failed status=%d\n", ++ __func__, rc); ++ ++ /* return -EFAULT; */ ++ ++ } ++ else { ++ ++ printk(KERN_ERR "\nRead OK.\n--------Value read at %u = 0x%X\n\n", ++ addr, i2cdata.byte); ++ ++ } ++ ++ msleep(1); /* Delay required, since smb(i2c) interface is slow */ ++ ++ } ++ ++ iproc_dump_smb_regs(dev); ++ ++ printk(KERN_DEBUG "\n\nLast intr sts = 0x%08X", ++ dev->smb_counters.last_int_sts); ++ ++ printk(KERN_DEBUG "mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n\n", ++ dev->smb_counters.mstr_start_busy_cnt, ++ dev->smb_counters.mstr_rx_evt_cnt, ++ dev->smb_counters.mstr_rx_fifo_full_cnt); ++ ++ return count; ++} ++ ++/* Written for SVK boards */ ++static int ++proc_debug_write_svk(struct file *file, ++ const char __user *buffer, ++ unsigned long count, ++ void *data) ++{ ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)data; ++ int rc; ++ unsigned int debug; ++ unsigned char kbuf[MAX_PROC_BUF_SIZE]; ++ union i2c_smbus_data i2cdata; ++ unsigned int val, addr; ++ ++ if (count > MAX_PROC_BUF_SIZE) { ++ ++ count = MAX_PROC_BUF_SIZE; ++ ++ } ++ ++ rc = copy_from_user(kbuf, buffer, count); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: copy_from_user failed status=%d", __func__, rc); ++ ++ return -EFAULT; ++ ++ } ++ ++ if (sscanf(kbuf, "%u", &debug) != 1) { ++ ++ printk(KERN_ERR "%s: echo > %s\n", __func__, PROC_ENTRY_DEBUG); ++ ++ return count; ++ ++ } ++ ++ if (debug) { ++ ++ dev->debug = 1; ++ ++ } ++ else { ++ ++ dev->debug = 0; ++ ++ } ++ ++ printk (KERN_ERR "\nCommand can execute slow, please wait...\n"); ++ ++ if (!dev->debug) { ++ ++ val = 0xFF; /* Initial value to write */ ++ ++ for(addr = 0x0; addr < 256; val--, addr++) { ++ ++ i2cdata.byte = val; ++ ++ rc = iproc_smb_xfer(&dev->adapter, 0xA0 >> 1, 0x0, I2C_SMBUS_WRITE, ++ addr, I2C_SMBUS_BYTE_DATA, &i2cdata); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: iproc_smb_xfer:write failed status=%d," ++ " addr=%u, val = 0x%X", __func__, rc, addr, val); ++ ++ } ++ else { ++ ++ printk(KERN_DEBUG "\nWrite OK.\nWrote 0x%X at addr %u\n\n", ++ val, addr); ++ ++ } ++ ++ msleep(1); /* Delay required, since smb(i2c) interface is slow */ ++ ++ } ++ ++ } ++ else { ++ ++ int i; ++ ++ /* Note about address expected by AT24C02: To write in correct order ++ * to AT24C02 using block write, refer bottom of page 9 (Write ++ * Operations) of the data sheet regarding internal incrementing of ++ * address. Based on that explanation, we program the addr value below. ++ * Select the 'highest' address in that page (7, 15, 23, and so on) to ++ * write to that page ++ */ ++ addr = debug - 1; ++ ++ val = jiffies % 256; ++ ++ printk(KERN_DEBUG "\nEEPROM page write. Page start addr = %u," ++ " write data: \n\n", debug - 8); ++ ++ for (i = 1; i <= 8; i++) { ++ ++ i2cdata.block[i] = val % 256; /* Fill a sequence pattern */ ++ ++ val++; ++ ++ printk(KERN_DEBUG "\nbyte%d = 0x%02X\n", i, i2cdata.block[i]); ++ ++ } ++ ++ i2cdata.block[0] = 8; ++ ++ rc = iproc_smb_xfer(&dev->adapter, 0xA0 >> 1, 0x0, I2C_SMBUS_WRITE, ++ addr, I2C_SMBUS_BLOCK_DATA, &i2cdata); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: iproc_smb_xfer:write failed status=%d," ++ " addr=%u, val = 0x%X", __func__, rc, addr, val); ++ ++ } ++ else { ++ ++ printk(KERN_DEBUG "\nBlock Write OK.\n\n"); ++ ++ } ++ ++ } ++ ++ iproc_dump_smb_regs(dev); ++ ++ printk(KERN_DEBUG "\n\nLast intr sts = 0x%08X", ++ dev->smb_counters.last_int_sts); ++ ++ printk(KERN_DEBUG "mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n\n", ++ dev->smb_counters.mstr_start_busy_cnt, ++ dev->smb_counters.mstr_rx_evt_cnt, ++ dev->smb_counters.mstr_rx_fifo_full_cnt); ++ ++ return count; ++} ++ ++/* Written for SVK boards */ ++static int ++proc_debug_read_svk(char *buffer, ++ char **start, ++ off_t off, ++ int count, ++ int *eof, ++ void *data) ++{ ++ unsigned int len = 0; ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)data; ++ int rc; ++ union i2c_smbus_data i2cdata; ++ unsigned int addr; ++ ++ if (off > 0) { ++ ++ return 0; ++ ++ } ++ ++ len += sprintf(buffer + len, "Read\n"); ++ ++ printk(KERN_ERR "\nCommand can execute slow, please wait...\n"); ++ ++ for(addr = 0x0; addr < 256; addr++) { ++ ++ /* Read operation */ ++ rc = iproc_smb_xfer(&dev->adapter, 0xA0 >> 1, 0x0, I2C_SMBUS_READ, addr, ++ I2C_SMBUS_BYTE_DATA, &i2cdata); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: iproc_smb_xfer failed status=%d", __func__, rc); ++ ++ } ++ else { ++ ++ printk(KERN_DEBUG "\nRead OK.\n--------Value read at %u = 0x%X\n", ++ addr, i2cdata.byte); ++ ++ } ++ ++ msleep(1); ++ ++ } ++ ++ iproc_dump_smb_regs(dev); ++ ++ printk(KERN_DEBUG "\n\nLast intr sts = 0x%08X", dev->smb_counters.last_int_sts); ++ ++ printk(KERN_DEBUG "mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n\n", ++ dev->smb_counters.mstr_start_busy_cnt, ++ dev->smb_counters.mstr_rx_evt_cnt, ++ dev->smb_counters.mstr_rx_fifo_full_cnt); ++ ++ return len; ++} ++ ++static int proc_init(struct platform_device *pdev) ++{ ++ int rc, id; ++ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); ++ struct procfs *proc = &dev->proc; ++ struct proc_dir_entry *proc_debug; ++ ++ if (pdev->dev.of_node) { ++ id = of_alias_get_id(pdev->dev.of_node, "i2c-controller");; ++ } else { ++ id = pdev->id; ++ } ++ snprintf(proc->name, sizeof(proc->name), "%s%d", PROC_GLOBAL_PARENT_DIR, id); ++ ++ /* sub directory */ ++ proc->parent = proc_mkdir(proc->name, gProcParent); ++ ++ if (proc->parent == NULL) { ++ ++ return -ENOMEM; ++ ++ } ++ ++ proc_debug = create_proc_entry(PROC_ENTRY_DEBUG, 0644, proc->parent); ++ ++ if (proc_debug == NULL) { ++ ++ rc = -ENOMEM; ++ ++ goto err_del_parent; ++ } ++ ++ use_svk_version = 0; /* Do not use SVK version */ ++ ++ if (use_svk_version) { ++ ++ proc_debug->read_proc = proc_debug_read_svk; ++ proc_debug->write_proc = proc_debug_write_svk; ++ ++ } ++ else { ++ ++ proc_debug->read_proc = proc_debug_read; ++ proc_debug->write_proc = proc_debug_write; ++ ++ } ++ ++ proc_debug->data = dev; ++ ++ return 0; ++ ++err_del_parent: ++ remove_proc_entry(proc->name, gProcParent); ++ ++ return rc; ++} ++ ++static int proc_term(struct platform_device *pdev) ++{ ++ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); ++ struct procfs *proc = &dev->proc; ++ ++ remove_proc_entry(PROC_ENTRY_DEBUG, proc->parent); ++ remove_proc_entry(proc->name, gProcParent); ++ ++ return 0; ++} ++ ++/* ++ * This function set clock frequency for SMBus block. As per hardware ++ * engineering, the clock frequency can be changed dynamically. ++ */ ++static int iproc_smb_set_clk_freq(struct iproc_smb_drv_int_data *iproc_i2c) ++{ ++ /* Default clock frequency is 100KHz */ ++ unsigned int bus_speed = 100000; ++ unsigned long base_addr = (unsigned long)iproc_i2c->block_base_addr; ++ unsigned int regval; ++ unsigned int val; ++ int ret; ++ ++ if (iproc_i2c->dev->of_node) { ++ /* DT based instantiation */ ++ ret = of_property_read_u32(iproc_i2c->dev->of_node, ++ "clock-frequency", &bus_speed); ++ if (ret < 0) { ++ dev_info(iproc_i2c->dev, ++ "unable to interpret clock-frequency DT property\n"); ++ bus_speed = 100000; ++ } ++ } else { ++ /* Non-DT based instantiation */ ++ bus_speed = 100000; ++ } ++ ++ if (bus_speed < 100000) { ++ dev_err(iproc_i2c->dev, "%d Hz bus speed not supported\n", ++ bus_speed); ++ dev_err(iproc_i2c->dev, ++ "valid speeds are 100khz and 400khz\n"); ++ return -EINVAL; ++ } else if (bus_speed < 400000) { ++ bus_speed = 100000; ++ } else { ++ bus_speed = 400000; ++ } ++ ++ switch (bus_speed) { ++ case 100000: ++ val = 0; ++ break; ++ ++ case 400000: ++ val = 1; ++ break; ++ ++ default: ++ return -EINVAL; ++ break; ++ ++ } ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_TIMGCFG_REG); ++ ++ SETREGFLDVAL(regval, val, CCB_SMB_TIMGCFG_MODE400_MASK, ++ CCB_SMB_TIMGCFG_MODE400_SHIFT); ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_TIMGCFG_REG, regval); ++ ++ dev_info(iproc_i2c->dev, "bus set to %u Hz\n", bus_speed); ++ return(0); ++} ++ ++static int iproc_smbus_block_init(struct iproc_smb_drv_int_data *dev) ++{ ++ ++ unsigned long base_addr = (unsigned long)dev->block_base_addr; ++ unsigned int regval; ++ ++ /* Flush Tx, Rx FIFOs. Note we are setting the Rx FIFO threshold to 0. ++ * May be OK since we are setting RX_EVENT and RX_FIFO_FULL interrupts ++ */ ++ regval = CCB_SMB_MSTRRXFIFOFLSH_MASK | CCB_SMB_MSTRTXFIFOFLSH_MASK; ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRFIFOCTL_REG, regval); ++ ++ /* Enable SMbus block. Note, we are setting MASTER_RETRY_COUNT to zero ++ * since there will be only one master ++ */ ++ regval = CCB_SMB_CFG_SMBEN_MASK; ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_CFG_REG, regval); ++ ++ /* Wait a minimum of 50 Usec, as per SMB hw doc. But we wait longer */ ++ udelay(100); ++ ++ ++ /* Set default clock frequency baed on device tree */ ++ iproc_smb_set_clk_freq(dev); ++ ++ /* Disable intrs */ ++ regval = 0x0; ++ iproc_smb_reg_write(base_addr + CCB_SMB_EVTEN_REG, regval); ++ ++ /* Clear intrs (W1TC) */ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTSTS_REG); ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_EVTSTS_REG, regval); ++ ++ return(0); ++} ++ ++/* This function enables interrupts */ ++static int iproc_intr_enable(struct iproc_smb_drv_int_data *dev, unsigned int bmap) ++{ ++ unsigned long base_addr = (unsigned long)dev->block_base_addr; ++ unsigned int regval; ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTEN_REG); ++ ++ regval |= bmap; ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_EVTEN_REG, regval); ++ ++ /* Store all interrupts enabled so far. Note bmap can have only 'incremental' ++ * set of events ++ */ ++ dev->evt_enable_bmap = regval; ++ ++ return(0); ++} ++ ++/* This function disables interrupts */ ++static int iproc_intr_disable(struct iproc_smb_drv_int_data *dev, unsigned int bmap) ++{ ++ unsigned long base_addr = (unsigned long)dev->block_base_addr; ++ unsigned int regval; ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTEN_REG); ++ ++ regval &= ~bmap; ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_EVTEN_REG, regval); ++ ++ dev->evt_enable_bmap = regval; ++ ++ return(0); ++} ++ ++/* Verify this sequence with hw engg */ ++static int iproc_smbus_block_deinit(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int regval; ++ int rc; ++ ++ /* Disable all interrupts */ ++ regval = 0x0; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_EVTEN_REG, regval); ++ ++ /* Check if a transaction is in progress */ ++ rc = iproc_smb_startbusy_wait(dev); ++ ++ if (rc < 0) { ++ ++ /* Do not exit the function, since we are most likely shutting down */ ++ printk(KERN_ERR "%s: A transaction is still in progress," ++ "but still continuing ", __func__); ++ ++ } ++ ++ /* Disable SMBus block */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); ++ ++ regval &= ~CCB_SMB_CFG_SMBEN_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, regval); ++ ++ ++ /* Wait for some time */ ++ udelay(100); ++ ++ /* Put the block under reset. Note the RESET bit in reg 0x0 is ++ * self clearing ++ */ ++ regval = CCB_SMB_CFG_RST_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, regval); ++ ++ return(0); ++} ++ ++static u32 iproc_smb_funcs(struct i2c_adapter *adapter) ++{ ++ /* Note: Other SMBus commands can be supported if we know the requirements ++ * more precisely ++ */ ++ return (I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA | ++ I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_QUICK | ++ I2C_FUNC_SMBUS_READ_BYTE); ++} ++ ++static struct i2c_algorithm iproc_smb_algorithm = { ++ /* .name = "iproc-smb", */ ++ .smbus_xfer = iproc_smb_xfer, ++ .master_xfer = NULL, ++ .functionality = iproc_smb_funcs, ++}; ++ ++enum { ++ HX4_NONE = 0, ++ HX4_DNI_3448P, ++ HX4_ACCTON_AS4610_54 ++}; ++ ++static int __devinit iproc_smb_probe(struct platform_device *pdev) ++{ ++ int rc=0, irq, id; ++ struct iproc_smb_drv_int_data *dev; ++ struct i2c_adapter *adap; ++ struct resource *iomem; ++ struct resource *ioarea; ++ ++ if (pdev->dev.of_node) { ++ id = of_alias_get_id(pdev->dev.of_node, "i2c-controller");; ++ } else { ++ id = pdev->id; ++ } ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n%s: Entering probe\n", __func__); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Get register memory resource */ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ if (!iomem) { ++ ++ printk(KERN_ERR "%s: No mem resource\n", __func__); ++ ++ return -ENODEV; ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nGot iomem 0x%p\n", iomem); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Get the interrupt number */ ++ irq = platform_get_irq(pdev, 0); ++ ++ if (irq == -ENXIO) { ++ if (brcm_get_hx4_model() == 0) { ++ printk(KERN_ERR "%s: No irq resource\n", __func__); ++ return -ENODEV; ++ } ++ /* Accton AS4610-54 or DNI-3448P */ ++ if (id == 0) { ++ irq = 127; ++ } else if (id == 1) { ++ irq = 128; ++ } else { ++ printk(KERN_ERR "%s: No irq resource\n", __func__); ++ return -ENODEV; ++ } ++ } ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nGot irqnum %d\n", irq); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Mark the memory region as used */ ++ ioarea = request_mem_region(iomem->start, resource_size(iomem), ++ pdev->name); ++ if (!ioarea) { ++ ++ printk(KERN_ERR "%s: SMBus region already claimed\n", __func__); ++ ++ return -EBUSY; ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nGot ioarea 0x%p\n", ioarea); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Allocate memory for driver's internal data structure */ ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); ++ ++ if (!dev) { ++ ++ printk(KERN_ERR "%s: Couldn't allocate memory for driver's internaldb\n", __func__); ++ ++ rc = -ENOMEM; ++ ++ goto err_release_mem_region; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nGot dev 0x%p\n", dev); ++#endif /* IPROC_SMB_DBG */ ++ ++ dev->dev = &pdev->dev; ++ init_MUTEX(&dev->xfer_lock); ++ init_completion(&dev->ses_done); ++ dev->irq = irq; ++ ++ dev->block_base_addr = ioremap(iomem->start, resource_size(iomem)); ++ ++ if (!dev->block_base_addr) { ++ ++ printk(KERN_ERR "%s: ioremap of register space failed\n", __func__); ++ ++ rc = -ENOMEM; ++ ++ goto err_free_dev_mem; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n ==== Got block_base_addr=0x%08X\n", (unsigned int)dev->block_base_addr); ++ /* iproc_dump_smb_regs(dev); */ ++#endif /* IPROC_SMB_DBG */ ++ ++ dev->enable_evts = ENABLE_INTR; /* Default value, can be changed after ++ initial testing */ ++ ++ platform_set_drvdata(pdev, dev); ++ ++ adap = &dev->adapter; ++ i2c_set_adapdata(adap, dev); /* Verify if this place is OK */ ++ adap->owner = THIS_MODULE; ++ adap->class = UINT_MAX; /* Can be used by any I2C device */ ++ snprintf(adap->name, sizeof(adap->name), "iproc-smb%d", id); ++ adap->algo = &iproc_smb_algorithm; ++ adap->dev.parent = &pdev->dev; /* */ ++ adap->nr = id; ++ adap->dev.of_node = pdev->dev.of_node; ++ ++ /* Init internal regs, disable intrs (and then clear intrs), set fifo ++ * thresholds, etc. ++ */ ++ iproc_smbus_block_init(dev); ++ ++ /* Register ISR handler */ ++ rc = request_irq(dev->irq, iproc_smb_isr, IRQF_SHARED, pdev->name, dev); ++ ++ if (rc) { ++ ++ printk(KERN_ERR "%s: failed to request irq %d, rc=%d\n", __func__, dev->irq, rc); ++ ++ goto err_smb_deinit; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nrequest_irq succeeded\n"); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* ++ * I2C device drivers may be active on return from ++ * i2c_add_numbered_adapter() ++ */ ++ rc = i2c_add_numbered_adapter(adap); ++ ++ if (rc) { ++ ++ printk(KERN_ERR "%s: Failed to add I2C adapter, rc=%d\n", ++ __func__, rc); ++ ++ goto err_free_irq; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\ni2c_add_numbered_adapter succeeded\n"); ++#endif /* IPROC_SMB_DBG */ ++ ++ of_i2c_register_devices(adap); ++ /* Turn on default set of interrupts */ ++ /* For Rx, enable RX fifo full, threshold hit interrupts. Other rx ++ * interrupts will be set in the read/recv transactions, as required ++ * For Tx, enable fifo under run intr. Other intrs will be set in send ++ * write access functions ++ */ ++ iproc_intr_enable(dev, CCB_SMB_MSTRRXFIFOFULLEN_MASK); ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\niproc_intr_enable complete, intrs enabled\n"); ++#endif /* IPROC_SMB_DBG */ ++ ++ rc = proc_init(pdev); ++ ++ if (rc) { ++ ++ printk(KERN_ERR "%s: Failed to install procfs entry, rc=%d\n", ++ __func__, rc); ++ ++ goto err_proc_term; ++ ++ } ++ ++ dev->next = iproc_smbus_list; ++ iproc_smbus_list = dev; ++ ++#ifdef IPROC_SMB_DBG ++ iproc_dump_smb_regs(dev); ++ ++ printk(KERN_DEBUG "%s: probe successful", __func__); ++ ++#endif /* IPROC_SMB_DBG */ ++ ++ return 0; ++ ++err_proc_term: ++ proc_term(pdev); ++ ++err_free_irq: ++ free_irq(dev->irq, dev); ++ ++err_smb_deinit: ++ iproc_smbus_block_deinit(dev); ++ ++ iounmap(dev->block_base_addr); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++err_free_dev_mem: ++ kfree(dev); ++ ++err_release_mem_region: ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++ printk(KERN_ERR "%s: probe failed, error=%d", __func__, rc); ++ ++ return (rc); ++} ++ ++static int iproc_smb_remove(struct platform_device *pdev) ++{ ++ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); ++ struct resource *iomem; ++ unsigned int regval; ++ ++ /* Disable interrupts. */ ++ /* Verify: Should we wait for any in-progress xact to complete? */ ++ iproc_intr_disable(dev, ~0); ++ ++ /* Disable SMbus block */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); ++ ++ regval &= ~CCB_SMB_CFG_SMBEN_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, regval); ++ ++ i2c_del_adapter(&dev->adapter); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ free_irq(dev->irq, dev); ++ ++ iproc_smbus_block_deinit(dev); ++ ++ iounmap(dev->block_base_addr); ++ ++ kfree(dev); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++ return 0; ++} ++ ++static int iproc_smb_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ return (0); ++} ++ ++static int iproc_smb_resume(struct platform_device *pdev) ++{ ++ return (0); ++} ++ ++static struct platform_device_id iproc_smb_id_table[] = { ++ { .name = "iproc-smb", 0 }, ++}; ++MODULE_DEVICE_TABLE(platform, iproc_smb_id_table); ++ ++#ifdef CONFIG_OF ++static const struct of_device_id bcm_iproc_smb_of_match[] = { ++ { .compatible = "iproc-smb" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, bcm_iproc_smb_of_match); ++#endif ++ ++static struct platform_driver iproc_smb_driver = { ++ .driver = { ++ .name = "iproc-smb", ++ .owner = THIS_MODULE, ++ .of_match_table = bcm_iproc_smb_of_match, ++ }, ++ .probe = iproc_smb_probe, ++ .remove = iproc_smb_remove, ++ .suspend = iproc_smb_suspend, ++ .resume = iproc_smb_resume, ++ .id_table = iproc_smb_id_table, ++}; ++ ++ ++static int __init iproc_smb_init(void) ++{ ++ int rc; ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "%s: Entering init", __func__); ++#endif /* IPROC_SMB_DBG */ ++ ++ gProcParent = proc_mkdir(PROC_GLOBAL_PARENT_DIR, NULL); ++ ++ if (gProcParent == NULL) { ++ ++ printk(KERN_ERR "%s: SMBus driver procfs failed\n", __func__); ++ ++ return -ENOMEM; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nproc_mkdir succeeded, gProcParent=0x%08X\n", (unsigned int)gProcParent); ++#endif /* IPROC_SMB_DBG */ ++ ++ rc = platform_driver_register(&iproc_smb_driver); ++ ++ if (rc < 0) { ++ ++ printk(KERN_ERR "%s: SMBus driver init failed, error %d\n", __func__, rc); ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n%s: Called platform_driver_register, rc=%d\n", __func__, rc); ++#endif /* IPROC_SMB_DBG */ ++ ++ ++ iproc_smbus_list = NULL; ++ ++ /* Should we set RESET bit (reg 0x0) here?: Not necessary as per hw engg */ ++ ++ return rc; ++} ++ ++static void __exit iproc_smb_exit(void) ++{ ++ platform_driver_unregister(&iproc_smb_driver); ++ ++ remove_proc_entry(PROC_GLOBAL_PARENT_DIR, NULL); ++} ++ ++module_init(iproc_smb_init); ++module_exit(iproc_smb_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("IPROC I2C (SMBus) Bus Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/smbus/iproc_smbus.h b/drivers/bcmdrivers/smbus/iproc_smbus.h +new file mode 100644 +index 0000000..d2c4973 +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/iproc_smbus.h +@@ -0,0 +1,189 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __IPROC_SMBUS_H__ ++#define __IPROC_SMBUS_H__ ++ ++#define IPROC_I2C_INVALID_ADDR 0xFF ++ ++#define MAX_PROC_BUF_SIZE 256 ++#define MAX_PROC_NAME_SIZE 15 ++#define PROC_GLOBAL_PARENT_DIR "iproc-i2c" ++#define PROC_ENTRY_DEBUG "iproc-i2c-dbg" ++ ++#define IPROC_SMB_MAX_RETRIES 35 ++ ++#define GETREGFLDVAL(regval, mask, startbit) (((regval) & (mask)) >> (startbit)) ++ ++#define SETREGFLDVAL(regval, fldval, mask, startbit) regval = \ ++ (regval & ~(mask)) | \ ++ ((fldval) << (startbit)) ++ ++/* Enum to specify clock speed. The user will provide it during initialization. ++ * If needed, it can be changed dynamically ++ */ ++typedef enum iproc_smb_clk_freq { ++ I2C_SPEED_100KHz = 0, ++ I2C_SPEED_400KHz = 1, ++ I2C_SPEED_INVALID = 255 ++} smb_clk_freq_t; ++ ++/* This enum will be used to notify the user of status of a data transfer ++ * request ++ */ ++typedef enum iproc_smb_error_code { ++ I2C_NO_ERR = 0, ++ I2C_TIMEOUT_ERR = 1, ++ I2C_INVALID_PARAM_ERR = 2, /* Invalid parameter(s) passed to the driver */ ++ I2C_OPER_IN_PROGRESS = 3, /* The driver API was called before the present ++ transfer was completed */ ++ I2C_OPER_ABORT_ERR = 4, /* Transfer aborted unexpectedly, for example a NACK ++ received, before last byte was read/written */ ++ I2C_FUNC_NOT_SUPPORTED = 5, /* Feature or function not supported ++ (e.g., 10-bit addresses, or clock speeds ++ other than 100KHz, 400KHz) */ ++} iproc_smb_error_code_t; ++ ++/* Counters will be used mainly for testing and debugging */ ++struct iproc_smb_counters { ++ unsigned int num_read_requests; ++ unsigned int num_write_requests; ++ unsigned int num_read_errors; ++ unsigned int num_write_errors; ++ unsigned int mstr_rx_evt_cnt; /* ISR counter to check recv event */ ++ unsigned int mstr_start_busy_cnt; /* ISR counter to checking xact sts */ ++ unsigned int mstr_rx_fifo_full_cnt; /* ISR counter to detect rx fifo full */ ++ unsigned int last_int_sts; /* last value of intr status reg */ ++}; ++ ++ ++/* This enum may be used in a call back function to provide the user of the ++ * type of request sent by the user. It can also be used for testing and ++ * debugging purposes ++ */ ++typedef enum iproc_smb_message_type { ++ I2C_DISABLE_MSG = 0, /* To be used after hardware initialization. ++ Driver will _not_ respond to API calls */ ++ I2C_ENABLE_MSG = 1, /* Used after hardware initialization, if required. ++ Driver will start responding to API calls. ++ Will not (re-)program the hardware. */ ++ I2C_READ_MSG = 2, /* I2C read request from application */ ++ I2C_WRITE_MSG = 3 /* I2C write request from application */ ++} iproc_smb_message_type_t; ++ ++/* For debugging purposes, we will store the information about the last ++ * (latest) transfer request from the client application ++ */ ++struct iproc_smb_dbg_trans_info ++{ ++ iproc_smb_message_type_t i2c_last_mesg_type; ++ unsigned int i2c_last_dev_addr; ++ unsigned int i2c_last_num_bytes_xfer_req; ++}; ++ ++struct procfs { ++ char name[MAX_PROC_NAME_SIZE]; ++ struct proc_dir_entry *parent; ++}; ++ ++/* This structure will be used internally by the driver to maintain its ++ * configuration information as well as information programmed in to the ++ * hardware ++ */ ++struct iproc_smb_drv_int_data { ++ struct device *dev; ++ struct iproc_smb_drv_int_data *next; ++ ++ int irq; ++ ++ unsigned int drv_state_init; /* 1 = Initialized, 0 = not initialized */ ++ ++ unsigned int drv_state_open; /* 1 = Accepting transaction requests, ++ 0 = Not accepting transaction requests */ ++ smb_clk_freq_t clk_speed; ++ ++ void __iomem *block_base_addr; /* iomapped virtual base address for ++ register access */ ++ ++ struct i2c_adapter adapter; ++ ++ unsigned int i2c_slave_addr; /* Up to four 7-bit SMB slave addresses can be ++ assigned, we will assume only one for now. ++ Valid only if SMBus will act as a slave ++ device */ ++ ++ struct semaphore xfer_lock; /* Lock for data transfer */ ++ ++ struct completion ses_done; /* To signal the command completion */ ++ ++ struct procfs proc; ++ ++ volatile int debug; ++ ++ unsigned int master_rx_fifo_thr; /* Master FIFO threshold. Interrupt will be ++ generated if the threshold is exceeded */ ++ ++ unsigned int slave_rx_fifo_thr; /* Slave FIFO threshold. Interrupt will be ++ generated if the threshold is exceeded */ ++ ++ unsigned int enable_evts; /* If true, enable interrupts. If false, ++ disable interrupts. Default is false */ ++ unsigned int evt_enable_bmap; /* Bit map of events enabled by the driver */ ++ ++ struct iproc_smb_counters smb_counters; /* Statistics maintained by driver. A caller ++ can request them through an API */ ++}; ++ ++/* Data to be supplied by the platform to initialise the IPROC SMBus (I2C). ++ * block ++ * init: Function called during driver initialization. Used by platform to ++ * configure GPIO functions and similar. ++ */ ++struct iproc_smb_platform_data { ++ int (*init)(struct iproc_smb_drv_int_data *iproc_i2c_info_ptr, int flags); ++ ++ unsigned int flags; ++}; ++ ++/* This structure will be used by the user during driver initialization to pass ++ * initial configuration information to the driver ++ */ ++struct iproc_smb_init_params { ++ unsigned int intr_mode; /* TRUE (1) for enabling interrupt mode, ++ FALSE (0) for polling mode */ ++ unsigned int clock_freq; /* 0=100KHz, 1=400KHz */ ++ void (*i2c_callback_func)(unsigned char *data); /* Application can ++ register a callback ++ function for driver to ++ notify the application ++ of any asynchronous ++ event(s), or exception. ++ Can be NULL */ ++}; ++ ++/* Structure used to pass information to read/write functions. */ ++struct iproc_xact_info { ++ bool cmd_valid; /* true if command field below is valid. Otherwise, false */ ++ unsigned short command; /* Passed by caller to send SMBus command code */ ++ unsigned char *data; /* actual data pased by the caller */ ++ unsigned int size; /* Size of data buffer passed */ ++ unsigned short flags; /* Sent by caller specifying PEC, 10-bit addresses */ ++ unsigned char smb_proto; /* SMBus protocol to use to perform transaction */ ++}; ++ ++#define XACT_TIMEOUT (msecs_to_jiffies(100)) /* Verify if 100 is OK */ ++ ++#endif /* __IPROC_SMBUS_H__ */ +diff --git a/drivers/bcmdrivers/smbus/iproc_smbus_defs.h b/drivers/bcmdrivers/smbus/iproc_smbus_defs.h +new file mode 100644 +index 0000000..856418a +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/iproc_smbus_defs.h +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __IPROC_SMBUS_DEFS_H__ ++#define __IPROC_SMBUS_DEFS_H__ ++ ++/* Transaction error codes defined in Master command register (0x30) */ ++#define MSTR_STS_XACT_SUCCESS 0 ++#define MSTR_STS_LOST_ARB 1 ++#define MSTR_STS_NACK_FIRST_BYTE 2 ++#define MSTR_STS_NACK_NON_FIRST_BYTE 3 /* NACK on a byte other than ++ the first byte */ ++#define MSTR_STS_TTIMEOUT_EXCEEDED 4 ++#define MSTR_STS_TX_TLOW_MEXT_EXCEEDED 5 ++#define MSTR_STS_RX_TLOW_MEXT_EXCEEDED 6 ++ ++/* SMBUS protocol values defined in register 0x30 */ ++#define SMBUS_PROT_QUICK_CMD 0 ++#define SMBUS_PROT_SEND_BYTE 1 ++#define SMBUS_PROT_RECV_BYTE 2 ++#define SMBUS_PROT_WR_BYTE 3 ++#define SMBUS_PROT_RD_BYTE 4 ++#define SMBUS_PROT_WR_WORD 5 ++#define SMBUS_PROT_RD_WORD 6 ++#define SMBUS_PROT_BLK_WR 7 ++#define SMBUS_PROT_BLK_RD 8 ++#define SMBUS_PROT_PROC_CALL 9 ++#define SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL 10 ++ ++#define BUS_BUSY_COUNT 100000 /* Number can be changed later */ ++ ++#define DISABLE_INTR 0 ++#define ENABLE_INTR 1 ++#endif /* __IPROC_SMBUS_DEFS_H__ */ +diff --git a/drivers/bcmdrivers/smbus/iproc_smbus_regs.h b/drivers/bcmdrivers/smbus/iproc_smbus_regs.h +new file mode 100644 +index 0000000..197be7d +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/iproc_smbus_regs.h +@@ -0,0 +1,290 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __IPROC_SMBUS_REGS_H__ ++#define __IPROC_SMBUS_REGS_H__ ++ ++/* --- */ ++#define CCB_SMB_CFG_REG 0x0 ++ ++#define CCB_SMB_CFG_RST_MASK 0x80000000 ++#define CCB_SMB_CFG_RST_SHIFT 31 ++ ++#define CCB_SMB_CFG_SMBEN_MASK 0x40000000 ++#define CCB_SMB_CFG_SMBEN_SHIFT 30 ++ ++#define CCB_SMB_CFG_BITBANGEN_MASK 0x20000000 ++#define CCB_SMB_CFG_BITBANGEN_SHIFT 29 ++ ++#define CCB_SMB_CFG_EN_NIC_SMBADDR0_MASK 0x10000000 ++#define CCB_SMB_CFG_EN_NIC_SMBADDR0_SHIFT 28 ++ ++#define CCB_SMB_CFG_PROMISCMODE_MASK 0x08000000 ++#define CCB_SMB_CFG_PROMISCMODE_SHIFT 27 ++ ++#define CCB_SMB_CFG_TSTMPCNTEN_MASK 0x04000000 ++#define CCB_SMB_CFG_TSTMPCNTEN_SHIFT 26 ++ ++#define CCB_SMB_CFG_MSTRRTRYCNT_MASK 0x000F0000 ++#define CCB_SMB_CFG_MSTRRTRYCNT_SHIFT 16 ++ ++ ++/* --- */ ++#define CCB_SMB_TIMGCFG_REG 0x4 ++ ++#define CCB_SMB_TIMGCFG_MODE400_MASK 0x80000000 ++#define CCB_SMB_TIMGCFG_MODE400_SHIFT 31 ++ ++#define CCB_SMB_TIMGCFG_RNDSLVSTR_MASK 0x7F000000 ++#define CCB_SMB_TIMGCFG_RNDSLVSTR_SHIFT 24 ++ ++#define CCB_SMB_TIMGCFG_PERSLVSTR_MASK 0x00FF0000 ++#define CCB_SMB_TIMGCFG_PERSLVSTR_SHIFT 16 ++ ++#define CCB_SMB_TIMGCFG_IDLTIME_MASK 0x0000FF00 ++#define CCB_SMB_TIMGCFG_IDLTIME_SHIFT 8 ++ ++/* --- */ ++#define CCB_SMB_ADDR_REG 0x8 ++ ++#define CCB_SMB_EN_NIC_SMBADDR3_MASK 0x80000000 ++#define CCB_SMB_EN_NIC_SMBADDR3_SHIFT 31 ++ ++#define CCB_SMB_NIC_SMBADDR3_MASK 0x7F000000 ++#define CCB_SMB_NIC_SMBADDR3_SHIFT 24 ++ ++#define CCB_SMB_EN_NIC_SMBADDR2_MASK 0x00800000 ++#define CCB_SMB_EN_NIC_SMBADDR2_SHIFT 23 ++ ++#define CCB_SMB_NIC_SMBADDR2_MASK 0x007F0000 ++#define CCB_SMB_NIC_SMBADDR2_SHIFT 16 ++ ++#define CCB_SMB_EN_NIC_SMBADDR1_MASK 0x00008000 ++#define CCB_SMB_EN_NIC_SMBADDR1_SHIFT 15 ++ ++#define CCB_SMB_NIC_SMBADDR1_MASK 0x00007F00 ++#define CCB_SMB_NIC_SMBADDR1_SHIFT 8 ++ ++#define CCB_SMB_EN_NIC_SMBADDR0_MASK 0x00000080 ++#define CCB_SMB_EN_NIC_SMBADDR0_SHIFT 7 ++ ++#define CCB_SMB_NIC_SMBADDR0_MASK 0x0000007F ++#define CCB_SMB_NIC_SMBADDR0_SHIFT 0 ++ ++/* --- */ ++#define CCB_SMB_MSTRFIFOCTL_REG 0xC ++ ++#define CCB_SMB_MSTRRXFIFOFLSH_MASK 0x80000000 ++#define CCB_SMB_MSTRRXFIFOFLSH_SHIFT 31 ++ ++#define CCB_SMB_MSTRTXFIFOFLSH_MASK 0x40000000 ++#define CCB_SMB_MSTRTXFIFOFLSH_SHIFT 30 ++ ++#define CCB_SMB_MSTRRXPKTCNT_MASK 0x007F0000 ++#define CCB_SMB_MSTRRXPKTCNT_SHIFT 16 ++ ++#define CCB_SMB_MSTRRXFIFOTHR_MASK 0x00003F00 ++#define CCB_SMB_MSTRRXFIFOTHR_SHIFT 8 ++ ++/* --- */ ++#define CCB_SMB_SLVFIFOCTL_REG 0x10 ++ ++#define CCB_SMB_SLVRXFIFOFLSH_MASK 0x80000000 ++#define CCB_SMB_SLVRXFIFOFLSH_SHIFT 31 ++ ++#define CCB_SMB_SLVTXFIFOFLSH_MASK 0x40000000 ++#define CCB_SMB_SLVTXFIFOFLSH_SHIFT 30 ++ ++#define CCB_SMB_SLVRXPKTCNT_MASK 0x007F0000 ++#define CCB_SMB_SLVRXPKTCNT_SHIFT 16 ++ ++#define CCB_SMB_SLVRXFIFOTHR_MASK 0x00003F00 ++#define CCB_SMB_SLVRXFIFOTHR_SHIFT 8 ++ ++/* --- */ ++#define CCB_SMB_BITBANGCTL_REG 0x14 ++ ++#define CCB_SMB_SMBCLKIN_MASK 0x80000000 ++#define CCB_SMB_SMBCLKIN_SHIFT 31 ++ ++#define CCB_SMB_SMBCLKOUTEN_MASK 0x40000000 ++#define CCB_SMB_SMBCLKOUTEN_SHIFT 30 ++ ++#define CCB_SMB_SMBDATAIN_MASK 0x20000000 ++#define CCB_SMB_SMBDATAIN_SHIFT 29 ++ ++#define CCB_SMB_SMBDATAOUTEN_MASK 0x10000000 ++#define CCB_SMB_SMBDATAOUTEN_SHIFT 28 ++ ++/* --- */ ++#define CCB_SMB_MSTRCMD_REG 0x30 ++ ++#define CCB_SMB_MSTRSTARTBUSYCMD_MASK 0x80000000 ++#define CCB_SMB_MSTRSTARTBUSYCMD_SHIFT 31 ++ ++#define CCB_SMB_MSTRABORT_MASK 0x40000000 ++#define CCB_SMB_MSTRABORT_SHIFT 30 ++ ++#define CCB_SMB_MSTRSTS_MASK 0x0E000000 ++#define CCB_SMB_MSTRSTS_SHIFT 25 ++ ++#define CCB_SMB_MSTRSMBUSPROTO_MASK 0x00001E00 ++#define CCB_SMB_MSTRSMBUSPROTO_SHIFT 9 ++ ++#define CCB_SMB_MSTRPEC_MASK 0x00000100 ++#define CCB_SMB_MSTRPEC_SHIFT 8 ++ ++#define CCB_SMB_MSTRRDBYTECNT_MASK 0x000000FF ++#define CCB_SMB_MSTRRDBYTECNT_SHIFT 0 ++ ++/* --- */ ++#define CCB_SMB_SLVCMD_REG 0x34 ++ ++#define CCB_SMB_SLVSTARTBUSYCMD_MASK 0x80000000 ++#define CCB_SMB_SLVSTARTBUSYCMD_SHIFT 31 ++ ++#define CCB_SMB_SLVABORT_MASK 0x40000000 ++#define CCB_SMB_SLVABORT_SHIFT 30 ++ ++#define CCB_SMB_SLVSTS_MASK 0x03800000 ++#define CCB_SMB_SLVSTS_SHIFT 23 ++ ++#define CCB_SMB_SLVPEC_MASK 0x00000100 ++#define CCB_SMB_SLVPEC_SHIFT 8 ++ ++ ++/* --- */ ++#define CCB_SMB_EVTEN_REG 0x38 ++ ++#define CCB_SMB_MSTRRXFIFOFULLEN_MASK 0x80000000 ++#define CCB_SMB_MSTRRXFIFOFULLEN_SHIFT 31 ++ ++#define CCB_SMB_MSTRRXFIFOTHRHITEN_MASK 0x40000000 ++#define CCB_SMB_MSTRRXFIFOTHRHITEN_SHIFT 30 ++ ++#define CCB_SMB_MSTRRXEVTEN_MASK 0x20000000 ++#define CCB_SMB_MSTRRXEVTEN_SHIFT 29 ++ ++#define CCB_SMB_MSTRSTARTBUSYEN_MASK 0x10000000 ++#define CCB_SMB_MSTRSTARTBUSYEN_SHIFT 28 ++ ++#define CCB_SMB_MSTRTXUNDEN_MASK 0x08000000 ++#define CCB_SMB_MSTRTXUNDEN_SHIFT 27 ++ ++ ++#define CCB_SMB_SLVRXFIFOFULLEN_MASK 0x04000000 ++#define CCB_SMB_SLVRXFIFOFULLEN_SHIFT 26 ++ ++#define CCB_SMB_SLVRXFIFOTHRHITEN_MASK 0x02000000 ++#define CCB_SMB_SLVRXFIFOTHRHITEN_SHIFT 25 ++ ++#define CCB_SMB_SLVRXEVTEN_MASK 0x01000000 ++#define CCB_SMB_SLVRXEVTEN_SHIFT 24 ++ ++#define CCB_SMB_SLVSTARTBUSYEN_MASK 0x00800000 ++#define CCB_SMB_SLVSTARTBUSYEN_SHIFT 23 ++ ++#define CCB_SMB_SLVTXUNDEN_MASK 0x00400000 ++#define CCB_SMB_SLVTXUNDEN_SHIFT 22 ++ ++#define CCB_SMB_SLVRDEVTEN_MASK 0x00200000 ++#define CCB_SMB_SLVRDEVTEN_SHIFT 21 ++ ++ ++/* --- */ ++#define CCB_SMB_EVTSTS_REG 0x3C ++ ++#define CCB_SMB_MSTRRXFIFOFULLSTS_MASK 0x80000000 ++#define CCB_SMB_MSTRRXFIFOFULLSTS_SHIFT 31 ++ ++#define CCB_SMB_MSTRRXFIFOTHRHITSTS_MASK 0x40000000 ++#define CCB_SMB_MSTRRXFIFOTHRHITSTS_SHIFT 30 ++ ++#define CCB_SMB_MSTRRXEVTSTS_MASK 0x20000000 ++#define CCB_SMB_MSTRRXEVTSTS_SHIFT 29 ++ ++#define CCB_SMB_MSTRSTARTBUSYSTS_MASK 0x10000000 ++#define CCB_SMB_MSTRSTARTBUSYSTS_SHIFT 28 ++ ++#define CCB_SMB_MSTRTXUNDSTS_MASK 0x08000000 ++#define CCB_SMB_MSTRTXUNDSTS_SHIFT 27 ++ ++ ++#define CCB_SMB_SLVRXFIFOFULLSTS_MASK 0x04000000 ++#define CCB_SMB_SLVRXFIFOFULLSTS_SHIFT 26 ++ ++#define CCB_SMB_SLVRXFIFOTHRHITSTS_MASK 0x02000000 ++#define CCB_SMB_SLVRXFIFOTHRHITSTS_SHIFT 25 ++ ++#define CCB_SMB_SLVRXEVTSTS_MASK 0x01000000 ++#define CCB_SMB_SLVRXEVTSTS_SHIFT 24 ++ ++#define CCB_SMB_SLVSTARTBUSYSTS_MASK 0x00800000 ++#define CCB_SMB_SLVSTARTBUSYSTS_SHIFT 23 ++ ++#define CCB_SMB_SLVTXUNDSTS_MASK 0x00400000 ++#define CCB_SMB_SLVTXUNDSTS_SHIFT 22 ++ ++#define CCB_SMB_SLVRDEVTSTS_MASK 0x00200000 ++#define CCB_SMB_SLVRDEVTSTS_SHIFT 21 ++ ++ ++/* --- */ ++#define CCB_SMB_MSTRDATAWR_REG 0x40 ++ ++#define CCB_SMB_MSTRWRSTS_MASK 0x80000000 ++#define CCB_SMB_MSTRWRSTS_SHIFT 31 ++ ++#define CCB_SMB_MSTRWRDATA_MASK 0x000000FF ++#define CCB_SMB_MSTRWRDATA_SHIFT 0 ++ ++ ++/* --- */ ++#define CCB_SMB_MSTRDATARD_REG 0x44 ++ ++#define CCB_SMB_MSTRRDSTS_MASK 0xC0000000 ++#define CCB_SMB_MSTRRDSTS_SHIFT 30 ++ ++#define CCB_SMB_MSTRRDPECERR_MASK 0x20000000 ++#define CCB_SMB_MSTRRDPECERR_SHIFT 29 ++ ++#define CCB_SMB_MSTRRDDATA_MASK 0x000000FF ++#define CCB_SMB_MSTRRDDATA_SHIFT 0 ++ ++ ++/* --- */ ++#define CCB_SMB_SLVDATAWR_REG 0x48 ++ ++#define CCB_SMB_SLVWRSTS_MASK 0x80000000 ++#define CCB_SMB_SLVWRSTS_SHIFT 31 ++ ++#define CCB_SMB_SLVWRDATA_MASK 0x000000FF ++#define CCB_SMB_SLVWRDATA_SHIFT 0 ++ ++ ++/* --- */ ++#define CCB_SMB_SLVDATARD_REG 0x4C ++ ++#define CCB_SMB_SLVRDSTS_MASK 0xC0000000 ++#define CCB_SMB_SLVRDSTS_SHIFT 30 ++ ++#define CCB_SMB_SLVRDERRSTS_MASK 0x30000000 ++#define CCB_SMB_SLVRDERRSTS_SHIFT 28 ++ ++#define CCB_SMB_SLVRDDATA_MASK 0x000000FF ++#define CCB_SMB_SLVRDDATA_SHIFT 0 ++ ++#endif /* __IPROC_SMBUS_REGS_H__ */ +diff --git a/drivers/bcmdrivers/timer/.gitignore b/drivers/bcmdrivers/timer/.gitignore +new file mode 100644 +index 0000000..d741861 +--- /dev/null ++++ b/drivers/bcmdrivers/timer/.gitignore +@@ -0,0 +1,4 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/timer/Kconfig b/drivers/bcmdrivers/timer/Kconfig +new file mode 100644 +index 0000000..9dc584f +--- /dev/null ++++ b/drivers/bcmdrivers/timer/Kconfig +@@ -0,0 +1,6 @@ ++config IPROC_CCB_TIMER ++ tristate "ChipcommonB Timer support" ++ depends on ARCH_IPROC ++ help ++ This selects a driver for the ChipcommonB SP804 Timer on Broadcom ++ iProc chips. +diff --git a/drivers/bcmdrivers/timer/Makefile b/drivers/bcmdrivers/timer/Makefile +new file mode 100644 +index 0000000..630ff37 +--- /dev/null ++++ b/drivers/bcmdrivers/timer/Makefile +@@ -0,0 +1,2 @@ ++ ++obj-$(CONFIG_IPROC_CCB_TIMER) += iproc_timer.o +diff --git a/drivers/bcmdrivers/timer/iproc_timer.c b/drivers/bcmdrivers/timer/iproc_timer.c +new file mode 100644 +index 0000000..b9d11fc +--- /dev/null ++++ b/drivers/bcmdrivers/timer/iproc_timer.c +@@ -0,0 +1,479 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "iproc_timer.h" ++ ++/* ++ * Configurations ++ */ ++#define DRV_NAME "iproc_ccb_timer" ++#define REFCLK_SOURCE "c_clk125" ++#define REFCLK_SOURCE_DEVID "iproc_slow" ++#define MAX_NUMBER_OF_TIMERS (4) ++ ++/* ++ * Register offset ++ */ ++#define TIMER_LOAD_OFFSET 0x00 ++#define TIMER_VALUE_OFFSET 0x04 ++#define TIMER_CONTROL_OFFSET 0x08 ++#define TIMER_INTCLR_OFFSET 0x0c ++#define TIMER_RIS_OFFSET 0x10 ++#define TIMER_MIS_OFFSET 0x14 ++ ++/* ++ * Timer Control Register Bits ++ */ ++#define TIMER_CTRL_16BIT (0 << 1) /* 16-bit counter mode */ ++#define TIMER_CTRL_32BIT (1 << 1) /* 32-bit counter mode */ ++#define TIMER_CTRL_IE (1 << 5) /* Interrupt enable */ ++#define TIMER_CTRL_PERIODIC (1 << 6) /* Periodic mode */ ++#define TIMER_CTRL_EN (1 << 7) /* Timer enable */ ++#define TIMER_CTRL_ONESHOTMODE (1 << 0) ++#define TIMER_CTRL_DIV1 (0 << 2) ++#define TIMER_CTRL_PREBY16 (1 << 2) ++#define TIMER_CTRL_PREBY256 (2 << 2) ++ ++/* In case we use physical addresses */ ++#define IO_ADDRESS(x) (x) ++ ++/* Timer instance */ ++typedef struct { ++ int32_t id; /* id for this timer */ ++ uint32_t base; /* timer base address */ ++ uint32_t vec; /* interrupt vector */ ++ int started; /* Whether it has started */ ++ uint64_t interval; /* Interval in ticks; 0 if not inited */ ++ int periodic; /* 1 for periodic; 0 for one-shot */ ++ uint32_t load; /* Actual value to load */ ++ iproc_timer_isr_t isr; /* User interrupt handler */ ++ void * cookie; /* Cookie for user isr */ ++ uint32_t prescale; /* Prescale bits */ ++} timer_map_t; ++ ++/* Actual number of timers */ ++static int timer_count; ++ ++/* Mapping from logical timer to physical timer */ ++static timer_map_t timers_map[MAX_NUMBER_OF_TIMERS]; ++ ++/* Reference clock */ ++static uint32_t timer_refclk; ++ ++/* ++ * Disable timer ++ */ ++static inline void ++hw_timer_disable(timer_map_t *ptimer) ++{ ++ register uint32_t timer_base; ++ ++ timer_base = ptimer->base; ++ writel( ++ readl(IO_ADDRESS(timer_base + TIMER_CONTROL_OFFSET)) & ~TIMER_CTRL_EN, ++ IO_ADDRESS(timer_base + TIMER_CONTROL_OFFSET) ++ ); ++ ++ /* Clear pending interrupt */ ++ writel(1, IO_ADDRESS(timer_base + TIMER_INTCLR_OFFSET)); ++} ++ ++/* ++ * Configure timer ++ */ ++int ++iproc_timer_configure(int timer_id, int periodic, uint64_t interval, ++ iproc_timer_isr_t isr, void *cookie) ++{ ++ timer_map_t *ptimer; ++ uint32_t ctrl = TIMER_CTRL_32BIT; ++ ++ if (timer_id < 0 || timer_id >= timer_count || ++ interval == 0 || interval > iproc_timer_get_max_interval()) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ ++ /* Cannot configure while it's started */ ++ if (ptimer->started) { ++ return -EBUSY; ++ } ++ ++ /* Check how much we need to prescale */ ++ if ((interval >> 32) == 0) { ++ ptimer->prescale = 0; ++ ctrl |= TIMER_CTRL_DIV1; ++ } else { ++ if ((interval >> 36) == 0) { ++ ptimer->prescale = 4; ++ ctrl |= TIMER_CTRL_PREBY16; ++ } else { ++ ptimer->prescale = 8; ++ ctrl |= TIMER_CTRL_PREBY256; ++ } ++ } ++ ++ /* Actual value to load */ ++ ptimer->load = (uint32_t)(interval >> ptimer->prescale); ++ ++ /* Configure periodic/one-shot mode */ ++ ptimer->periodic = periodic; ++ if (periodic) { ++ ++ /* ++ * For periodic mode, don't enable interrupt if user isr is not set ++ * This is to avoid frequent IRQs and degrade system performance. ++ */ ++ if (isr) { ++ ctrl |= TIMER_CTRL_IE; ++ } ++ ctrl |= TIMER_CTRL_PERIODIC; ++ ++ } else { ++ /* For one-shot mode, interrupt must be enabled (to mark it stopped) */ ++ ctrl |= TIMER_CTRL_ONESHOTMODE | TIMER_CTRL_IE; ++ } ++ ++ /* Write to control register */ ++ writel(ctrl, IO_ADDRESS(ptimer->base + TIMER_CONTROL_OFFSET)); ++ ++ /* Record user specified arguments */ ++ ptimer->interval = interval; ++ ptimer->isr = isr; ++ ptimer->cookie = cookie; ++ ++ return 0; ++} ++ ++/* ++ * Start timer ++ */ ++int ++iproc_timer_start(int timer_id) ++{ ++ timer_map_t *ptimer; ++ register uint32_t timer_base; ++ ++ if (timer_id < 0 || timer_id >= timer_count) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ ++ if (ptimer->interval == 0) { ++ return -EPERM; ++ } ++ ++ if (ptimer->started) { ++ return -EBUSY; ++ } ++ ++ ptimer->started = 1; ++ timer_base = ptimer->base; ++ writel(ptimer->load, IO_ADDRESS(timer_base + TIMER_LOAD_OFFSET)); ++ writel( ++ readl(IO_ADDRESS(timer_base + TIMER_CONTROL_OFFSET)) | TIMER_CTRL_EN, ++ IO_ADDRESS(timer_base + TIMER_CONTROL_OFFSET) ++ ); ++ ++ return 0; ++} ++ ++/* ++ * Stop timer ++ */ ++int ++iproc_timer_stop(int timer_id) ++{ ++ timer_map_t *ptimer; ++ ++ if (timer_id < 0 || timer_id >= timer_count) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ ++ if (ptimer->started == 0) { ++ return 0; ++ } ++ ++ ptimer->started = 0; ++ hw_timer_disable(ptimer); ++ ++ return 0; ++} ++ ++/* ++ * Returns timer's counter ++ */ ++uint64_t ++iproc_timer_get_current_ticks(int timer_id) ++{ ++ timer_map_t *ptimer; ++ uint64_t ticks; ++ ++ if (timer_id < 0 || timer_id >= timer_count) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ if (!ptimer->interval || !ptimer->started) { ++ return 0; ++ } ++ ++ /* To return the elapsed ticks, not remaining ticks */ ++ ticks = ++ ptimer->load - readl(IO_ADDRESS(ptimer->base + TIMER_VALUE_OFFSET)); ++ ++ /* Scale back */ ++ return ticks << ptimer->prescale; ++} ++ ++/* ++ * Timer info ++ */ ++int ++iproc_timer_get_info(int timer_id, iproc_timer_info_t *info) ++{ ++ timer_map_t *ptimer; ++ ++ if (timer_id < 0 || timer_id >= timer_count || info == NULL) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ info->configured = ptimer->interval? 1 : 0; ++ info->started = ptimer->started; ++ info->periodic = ptimer->periodic; ++ info->interval = ptimer->interval; ++ info->isr = ptimer->isr; ++ info->cookie = ptimer->cookie; ++ ++ return 0; ++} ++ ++/* ++ * Ticking rate (reference clock frequency): ticks per second ++ */ ++uint32_t ++iproc_timer_get_ticking_rate(void) ++{ ++ return timer_refclk; ++} ++ ++/* ++ * Get max interval in ticks ++ */ ++uint64_t ++iproc_timer_get_max_interval(void) ++{ ++ return (uint64_t)0xFFFFFFFFULL << 8; ++} ++ ++/* ++ * Get number of timers ++ */ ++uint32_t ++iproc_timer_count(void) ++{ ++ return timer_count; ++} ++ ++/* ++ * IRQ handler for the timer ++ */ ++static irqreturn_t ++hw_timer_interrupt(int irq, void *dev_id) ++{ ++ timer_map_t *ptimer = (timer_map_t *)dev_id; ++ ++ /* Check if it's for us */ ++ if (!(readl(IO_ADDRESS(ptimer->base + TIMER_MIS_OFFSET)) & 1)) { ++ return IRQ_NONE; ++ } ++ ++ /* clear the interrupt */ ++ writel(1, IO_ADDRESS(ptimer->base + TIMER_INTCLR_OFFSET)); ++ ++ /* Double confirm if it's enabled by user */ ++ if (ptimer->interval && ptimer->started) { ++ ++ /* If it's one-shot, mark it 'stopped' first */ ++ if (ptimer->periodic == 0) { ++ ptimer->started = 0; ++ ++ /* It doesn't clear the EN bit automatically */ ++ writel( ++ readl( ++ IO_ADDRESS(ptimer->base + TIMER_CONTROL_OFFSET)) & ++ ~TIMER_CTRL_EN, ++ IO_ADDRESS(ptimer->base + TIMER_CONTROL_OFFSET) ++ ); ++ } ++ ++ /* Call user specified ISR */ ++ if (ptimer->isr) { ++ (*ptimer->isr)(ptimer->id, ptimer->cookie); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++/*********************************************************************** ++ * Platform driver setup ++ ***********************************************************************/ ++ ++static int __devinit ++iproc_timer_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ int i; ++ int ret = 0; ++ struct clk *clk; ++ ++ /* Retrieve reference clock frequency */ ++ clk = clk_get_sys(REFCLK_SOURCE_DEVID, REFCLK_SOURCE); ++ if (!clk) { ++ dev_err(&pdev->dev, "can't get reference clock frequency by %s\n", ++ REFCLK_SOURCE); ++ ret = -EIO; ++ goto err2; ++ } ++ timer_refclk = (uint32_t)clk_get_rate(clk); ++ ++ /* Retrieve IRQ from resources (also determine number of timers) */ ++ timer_count = 0; ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no IRQ defined\n"); ++ ret = -ENODEV; ++ goto err2; ++ } ++ for(i = (int)res->start; i <= (int)res->end; i++) { ++ timers_map[timer_count].vec = i; ++ timer_count++; ++ } ++ ++ /* Retrieve register space (in virtual addresses) from resources */ ++ for(i=0; idev, "can't get resource for register space\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ timers_map[i].base = (uint32_t)res->start; ++ } ++ ++ /* Perform basic initialization */ ++ for(i=0; idev, "unable to allocate IRQ\n"); ++ goto err1; ++ } ++ } ++ ++ printk(KERN_INFO "iProc Timer driver: %u timers running at %uHz\n", ++ timer_count, timer_refclk); ++ ++ return 0; ++ ++err1: ++ for(i=0; i ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "usbh_cfg.h" ++ ++#include "bcm_usbh.h" ++ ++#define DEBUG ++#ifdef DEBUG ++#define dbg_printk(fmt, args...) printk(KERN_INFO "%s: " fmt, __func__, ## args) ++#else ++#define dbg_printk(fmt, args...) ++#endif ++ ++#define IPROC_USB2_CLK_CONTROL_ENABLE (0x1800C180) ++#define IPROC_USB2_CLK_CONTROL_ENABLE_VA HW_IO_PHYS_TO_VIRT(IPROC_USB2_CLK_CONTROL_ENABLE) ++#define IPROC_USB2_CLK_CONTROL_PLL (0x1800C164) ++#define IPROC_USB2_CLK_CONTROL_PLL_VA HW_IO_PHYS_TO_VIRT(IPROC_USB2_CLK_CONTROL_PLL) ++#define IPROC_STRAP_SKU_VECTOR (0x1810D500) ++#define IPROC_STRAP_SKU_VECTOR_VA HW_IO_PHYS_TO_VIRT(IPROC_STRAP_SKU_VECTOR) ++#define IPROC_IDM_USB2_RESET_CONTROL (0x18115800) ++#define IPROC_IDM_USB2_RESET_CONTROL_VA HW_IO_PHYS_TO_VIRT(IPROC_IDM_USB2_RESET_CONTROL) ++ ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_NSP) || \ ++ defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_IDM_USB2_IO_CONTROL_DIRECT USB2_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA HW_IO_PHYS_TO_VIRT(IPROC_IDM_USB2_IO_CONTROL_DIRECT) ++#endif ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define IPROC_XGPLL 0x1803fc2c ++#define IPROC_XGPLL_VA HW_IO_PHYS_TO_VIRT(IPROC_XGPLL) ++#define IPROC_USB_PHY_CTRL IPROC_WRAP_USBPHY_CTRL ++#define IPROC_USB_PHY_CTRL_VA HW_IO_PHYS_TO_VIRT(IPROC_USB_PHY_CTRL) ++#define IPROC_WRAP_MISC_STATUS 0x1803fc28 ++#define IPROC_WRAP_MISC_STATUS_VA HW_IO_PHYS_TO_VIRT(IPROC_WRAP_MISC_STATUS) ++#define IPROC_CLK_NDIV_40 0x80 ++#define IPROC_CLK_NDIV_20 0x8C ++#define USB_CLK_NDIV_MASK 0xFE7FFE00 ++#define USB_CLK_PLL_RESET_MASK 0xFF7FFE00 ++#define USB_CLK_PHY_RESET_MASK 0xFFFFFE00 ++#define USB_CLK_NDIV_40 0x30 ++#define USB_CLK_NDIV_20 0x60 ++#define ChipcommonA_GPIOIn_VA HW_IO_PHYS_TO_VIRT(ChipcommonA_GPIOInput) ++#define ChipcommonA_GPIOOut_VA HW_IO_PHYS_TO_VIRT(ChipcommonA_GPIOOut) ++#define ChipcommonA_GPIOOutEn_VA HW_IO_PHYS_TO_VIRT(ChipcommonA_GPIOOutEn) ++#define SUPPLY_USBD_POWER 0xfffffffd ++#endif ++ ++#define IPROC_SKU_STRAP_MASK 0xC ++ ++struct usbh_ctrl_regs { ++ u32 mode; ++#define MODE_ULPI_TTL (1<<0) ++#define MODE_ULPI_PHY (1<<1) ++#define MODE_UTMI_TTL (1<<2) ++#define MODE_UTMI_PHY (1<<3) ++#define MODE_PORT_CFG(port, mode) ((mode) << (4 * port)) ++ ++ u32 strap_q; ++#define STRAP_PWR_STATE_VALID (1 << 7) /* ss_power_state_valid */ ++#define STRAP_SIM_MODE (1 << 6) /* ss_simulation_mode */ ++#define STRAP_OHCI_CNTSEL_SIM (1 << 5) /* ohci_0_cntsel_i_n */ ++#define STRAP_PWR_STATE_NXT_VALID (1 << 4) /* ss_nxt_power_state_valid_i */ ++#define STRAP_PWR_STATE_NXT_SHIFT 2 /* ss_next_power_state_i */ ++#define STRAP_PWR_STATE_NXT_MASK (3 << STRAP_PWR_STATE_NXT_SHIFT) ++#define STRAP_PWR_STATE_SHIFT 0 /* ss_power_state_i */ ++#define STRAP_PWR_STATE_MASK (3 << STRAP_PWR_STATE_SHIFT) ++ ++ u32 framelen_adj_q; ++ u32 framelen_adj_qx[USBH_NUM_PORTS]; ++ u32 misc; ++#define MISC_RESUME_R23_ENABLE (1 << 4) /* ss_utmi_backward_enb_i */ ++#define MISC_RESUME_R23_UTMI_PLUS_DISABLE (1 << 3) /* ss_resume_utmi_pls_dis_i */ ++#define MISC_ULPI_BYPASS_ENABLE (1 << 2) /* ulpi_bypass_en_i */ ++#define MISC_PORT_PWRDWN_OVERCURRENT (1 << 1) /* ss_autoppd_on_overcur_en_i */ ++#define MISC_OHCI_CLK_RESTART (1 << 0) /* app_start_clk_i */ ++ ++}; ++ ++struct usbh_priv { ++ atomic_t probe_done; ++ volatile int init_cnt; ++ struct mutex lock; ++ struct device *dev; ++ struct usbh_cfg hw_cfg; ++ struct clk *peri_clk; ++ struct clk *ahb_clk; ++ struct clk *opt_clk; ++ struct usbh_ctrl_regs __iomem *ctrl_regs; ++}; ++ ++static struct usbh_priv usbh_data; ++ ++int bcm_usbh_suspend(unsigned int host_index) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(bcm_usbh_suspend); ++ ++int bcm_usbh_resume(unsigned int host_index) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(bcm_usbh_resume); ++ ++/* ++ * Function to initialize USB host related low level hardware including PHY, ++ * clocks, etc. ++ * ++ * TODO: expand support for more than one host in the future if needed ++ */ ++int bcm_usbh_init(unsigned int host_index) ++{ ++#ifdef CONFIG_MACH_NS ++ int usb2_clk_cntrl, usb2_clk_enable, sku_vect; ++ ++ sku_vect = readl_relaxed(IPROC_STRAP_SKU_VECTOR_VA); ++ if ((sku_vect & IPROC_SKU_STRAP_MASK) != 0x0) ++ { ++ /* enable clocks */ ++ writel_relaxed(0xEA68, IPROC_USB2_CLK_CONTROL_ENABLE_VA); ++ ++ usb2_clk_cntrl = readl_relaxed(IPROC_USB2_CLK_CONTROL_ENABLE_VA); ++ // printk("USB clk control enable register is: %08x\n", usb2_clk_cntrl); ++ writel_relaxed(0xDD10C3, IPROC_USB2_CLK_CONTROL_PLL_VA); ++ ++ usb2_clk_enable = readl_relaxed(IPROC_USB2_CLK_CONTROL_PLL_VA); ++ // printk("USB clk enable register is: %08x\n", usb2_clk_enable); ++ writel_relaxed(0x0, IPROC_USB2_CLK_CONTROL_ENABLE_VA); ++ ++ usb2_clk_cntrl = readl_relaxed(IPROC_USB2_CLK_CONTROL_ENABLE_VA); ++ // printk("USB clk control enable register is: %08x\n", usb2_clk_cntrl); ++ } ++#endif ++ return 0; ++} ++ ++EXPORT_SYMBOL(bcm_usbh_init); ++ ++/* ++ * Function to terminate USB host related low level hardware including PHY, ++ * clocks, etc. ++ * ++ * TODO: expand support for more than one host in the future if needed ++ */ ++int bcm_usbh_term(unsigned int host_index) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(bcm_usbh_term); ++ ++int InUSBDMode(void) ++{ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) ++ int usbd_detect; ++ usbd_detect = readl_relaxed(ChipcommonA_GPIOIn_VA); ++ if (usbd_detect & 1) ++ { ++ printk("%s: %d gpioin val %08x, ohci host mode will not be functional since in USBD mode\n", __FUNCTION__, __LINE__, usbd_detect); ++ printk("%s: %d to make ohci host mode work, appropriate jumper is needed on the board. Please refer to board schematics.\n", ++ __FUNCTION__, __LINE__); ++ } ++ ++ return (usbd_detect & 1); ++#else ++ return 0; ++#endif ++} ++ ++static int __devinit usbh_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct resource *iomem, *ioarea; ++ ++ memset(&usbh_data, 0, sizeof(usbh_data)); ++ ++ if (pdev->dev.platform_data == NULL) { ++ dev_err(&pdev->dev, "platform_data missing\n"); ++ ret = -EFAULT; ++ goto err_exit; ++ } ++ memcpy(&usbh_data.hw_cfg, pdev->dev.platform_data, ++ sizeof(usbh_data.hw_cfg)); ++ usbh_data.dev = &pdev->dev; ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!iomem) { ++ dev_err(&pdev->dev, "no mem resource\n"); ++ ret = -ENODEV; ++ goto err_exit; ++ } ++ ++ /* mark the memory region as used */ ++ ioarea = request_mem_region(iomem->start, resource_size(iomem), ++ pdev->name); ++ if (!ioarea) { ++ dev_err(&pdev->dev, "memory region already claimed\n"); ++ ret = -EBUSY; ++ goto err_exit; ++ } ++ ++ /* now map the I/O memory */ ++ usbh_data.ctrl_regs = (struct usbh_ctrl_regs __iomem *) ++ ioremap(iomem->start, sizeof(usbh_data.ctrl_regs)); ++ if (!usbh_data.ctrl_regs) { ++ dev_err(&pdev->dev, "failed to remap registers\n"); ++ ret = -ENOMEM; ++ goto err_free_mem_region; ++ } ++ ++ platform_set_drvdata(pdev, &usbh_data); ++ mutex_init(&usbh_data.lock); ++ usbh_data.init_cnt = 0; ++ atomic_set(&usbh_data.probe_done, 1); ++ ++ return 0; ++ ++err_free_mem_region: ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++err_exit: ++ memset(&usbh_data, 0, sizeof(usbh_data)); ++ return ret; ++} ++ ++static int __devexit usbh_remove(struct platform_device *pdev) ++{ ++ struct usbh_priv *drv_data = platform_get_drvdata(pdev); ++ struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ atomic_set(&drv_data->probe_done, 0); ++ platform_set_drvdata(pdev, NULL); ++ iounmap(drv_data->ctrl_regs); ++ release_mem_region(iomem->start, resource_size(iomem)); ++ memset(&usbh_data, 0, sizeof(usbh_data)); ++ ++ return 0; ++} ++ ++static struct platform_driver usbh_driver = ++{ ++ .driver = { ++ .name = "usbh", ++ .owner = THIS_MODULE, ++ }, ++ .probe = usbh_probe, ++ .remove = usbh_remove, ++}; ++ ++static int __init usbh_init(void) ++{ ++ int usb2_reset_state; ++ ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ int clk_enable, k; ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ unsigned int iClk; ++#endif ++ unsigned int USBClk, usbdgpiopwr, pllStatus; ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) ++ /* turn off power for USB device connected to the host */ ++ usbdgpiopwr = readl_relaxed(ChipcommonA_GPIOOut_VA); ++ usbdgpiopwr |= 0x2; ++ writel_relaxed(usbdgpiopwr, ChipcommonA_GPIOOut_VA); ++ writel_relaxed(0x2, ChipcommonA_GPIOOutEn_VA); ++#endif ++ ++ /* Do USB PHY reset */ ++ mdelay(100); ++ USBClk = readl_relaxed(IPROC_USB_PHY_CTRL_VA); ++ /* bring phy pll out of reset if not done already */ ++ if ((USBClk & 0x01000000) == 0 ) ++ { ++ USBClk |= 0x01000000; ++ writel_relaxed(USBClk, IPROC_USB_PHY_CTRL_VA); ++ pllStatus = readl_relaxed(IPROC_WRAP_MISC_STATUS_VA); ++ for (k = 0; k < 100000; k++) ++ { ++ if ((pllStatus & 2) == 2) ++ { ++ printk("USB phy pll locked\n"); ++ break; ++ } ++ pllStatus = readl_relaxed(IPROC_WRAP_MISC_STATUS_VA); ++ } ++ } ++ writel_relaxed(USBClk & (~(1<<23)), IPROC_USB_PHY_CTRL_VA); ++ clk_enable = readl_relaxed(IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ printk("Initial usb2h clock is: %08x\n", clk_enable); ++ clk_enable |= 1; ++ writel_relaxed(clk_enable, IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ clk_enable = readl_relaxed(IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ printk("Initial usb2h clock now is: %08x\n", clk_enable); ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ iClk = readl_relaxed(IPROC_XGPLL_VA); ++ USBClk = readl_relaxed(IPROC_USB_PHY_CTRL_VA); ++ printk("iClk = %08x, USBClk = %08x\n", iClk, USBClk); ++ if ((iClk & 0xff) == IPROC_CLK_NDIV_40) ++ { ++ writel_relaxed((USBClk & USB_CLK_NDIV_MASK) | USB_CLK_NDIV_40, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ writel_relaxed((USBClk & USB_CLK_PLL_RESET_MASK) | USB_CLK_NDIV_40, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ writel_relaxed((USBClk & USB_CLK_PHY_RESET_MASK) | USB_CLK_NDIV_40, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ USBClk = readl_relaxed(IPROC_USB_PHY_CTRL_VA); ++ printk("iClk = %08x, USBClk = %08x\n", iClk, USBClk); ++ } ++ else if ((iClk & 0xff) == IPROC_CLK_NDIV_20) ++ { ++ writel_relaxed((USBClk & USB_CLK_NDIV_MASK) | USB_CLK_NDIV_20, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ writel_relaxed((USBClk & USB_CLK_PLL_RESET_MASK) | USB_CLK_NDIV_20, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ writel_relaxed((USBClk & USB_CLK_PHY_RESET_MASK) | USB_CLK_NDIV_20, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ USBClk = readl_relaxed(IPROC_USB_PHY_CTRL_VA); ++ printk("iClk = %08x, USBClk = %08x\n", iClk, USBClk); ++ } ++#endif ++ mdelay(100); ++ writel_relaxed(USBClk | (1<<23), IPROC_USB_PHY_CTRL_VA); ++ udelay(100); ++#endif ++#if defined(CONFIG_MACH_NSP) ++ int clk_enable; ++ clk_enable = readl_relaxed(IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ printk("Initial usb2h clock is: %08x\n", clk_enable); ++ clk_enable |= 1; ++ writel_relaxed(clk_enable, IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ clk_enable = readl_relaxed(IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ printk("Initial usb2h clock now is: %08x\n", clk_enable); ++#endif ++ ++ usb2_reset_state = readl_relaxed(IPROC_IDM_USB2_RESET_CONTROL_VA); ++ printk("Initial usb2_reset_state is: %08x\n", usb2_reset_state); ++ if ((usb2_reset_state & 1) == 1) ++ { ++ writel_relaxed(0x0, IPROC_IDM_USB2_RESET_CONTROL_VA); ++ usb2_reset_state = readl_relaxed(IPROC_IDM_USB2_RESET_CONTROL_VA); ++ printk("usb2_reset_state is set and now it is: %08x\n", usb2_reset_state); ++ } ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) ++ /* supply power for USB device connected to the host */ ++ mdelay(100); ++ usbdgpiopwr = readl_relaxed(ChipcommonA_GPIOOut_VA); ++ usbdgpiopwr &= SUPPLY_USBD_POWER; ++ writel_relaxed(usbdgpiopwr, ChipcommonA_GPIOOut_VA); ++ writel_relaxed(0x2, ChipcommonA_GPIOOutEn_VA); ++#endif ++ return platform_driver_register(&usbh_driver); ++} ++ ++static void __exit usbh_exit(void) ++{ ++ platform_driver_unregister(&usbh_driver); ++} ++ ++module_init(usbh_init); ++module_exit(usbh_exit); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_DESCRIPTION("Broadcom USB host low-level driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/usb2h/bcm_usbh.h b/drivers/bcmdrivers/usb2h/bcm_usbh.h +new file mode 100644 +index 0000000..019589a +--- /dev/null ++++ b/drivers/bcmdrivers/usb2h/bcm_usbh.h +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BCM_USBH_H_ ++#define _BCM_USBH_H_ ++ ++extern int bcm_usbh_init(unsigned int host_index); ++extern int bcm_usbh_term(unsigned int host_index); ++extern int bcm_usbh_suspend(unsigned int host_index); ++extern int bcm_usbh_resume(unsigned int host_index); ++ ++#endif +diff --git a/drivers/bcmdrivers/usb2h/ehci-bcm.c b/drivers/bcmdrivers/usb2h/ehci-bcm.c +new file mode 100644 +index 0000000..62534b8 +--- /dev/null ++++ b/drivers/bcmdrivers/usb2h/ehci-bcm.c +@@ -0,0 +1,383 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++#include "bcm_usbh.h" ++ ++#define BCM_USBEHCI_MODULE_DESCRIPTION "Broadcom USB EHCI driver" ++#define BCM_USBEHCI_MODULE_VERSION "1.0.0" ++ ++#define BCM_USBEHCI_IRQF_FLAGS (IRQF_DISABLED | IRQF_SHARED) ++#define BCM_USBEHCI_NAME "bcm-ehci" ++ ++#define EHCI_INFO(pdev, fmt, args...) dev_info(&pdev->dev, fmt, ## args) ++#define EHCI_ERR(pdev, fmt, args...) dev_err(&pdev->dev, fmt, ## args) ++#define BCM_USB_FIFO_THRESHOLD 0x00800040 ++ ++struct usb_cfg ++{ ++ void *virt_reg_base; ++ struct usb_hcd *hcd; ++}; ++ ++extern int usb_disabled(void); ++static int hcd_init(struct usb_hcd *hcd); ++ ++static const struct hc_driver ehci_hcd_driver = ++{ ++ .description = hcd_name, ++ .product_desc = BCM_USBEHCI_NAME, ++ .hcd_priv_size = sizeof(struct ehci_hcd), ++ ++ /* ++ * generic hardware linkage ++ */ ++ .irq = ehci_irq, ++ .flags = HCD_USB2 | HCD_MEMORY | HCD_LOCAL_MEM, ++ ++ /* ++ * basic lifecycle operations ++ */ ++ .reset = hcd_init, ++ .start = ehci_run, ++ .stop = ehci_stop, ++ .shutdown = ehci_shutdown, ++ ++ /* ++ * managing i/o requests and associated device resources ++ */ ++ .urb_enqueue = ehci_urb_enqueue, ++ .urb_dequeue = ehci_urb_dequeue, ++ .endpoint_disable = ehci_endpoint_disable, ++ .endpoint_reset = ehci_endpoint_reset, ++ ++ /* ++ * scheduling support ++ */ ++ .get_frame_number = ehci_get_frame, ++ ++ /* ++ * root hub support ++ */ ++ .hub_status_data = ehci_hub_status_data, ++ .hub_control = ehci_hub_control, ++#ifdef CONFIG_PM ++ .bus_suspend = ehci_bus_suspend, ++ .bus_resume = ehci_bus_resume, ++#endif ++ .relinquish_port = ehci_relinquish_port, ++ .port_handed_over = ehci_port_handed_over, ++ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, ++}; ++ ++int hcd_init(struct usb_hcd *hcd) ++{ ++ struct ehci_hcd *ehci; ++ int err; ++ ++ if (!hcd) { ++ printk(KERN_ERR "invalid hcd pointer in %s\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ ehci = hcd_to_ehci(hcd); ++ ++ if ((err = ehci_halt(ehci)) < 0) { ++ printk(KERN_ERR "busnum %d: ehci_halt() failed, err=%d\n", hcd->self.busnum, err); ++ return err; ++ } ++ ++ if ((err = ehci_init(hcd)) < 0) { ++ printk(KERN_ERR "busnum %d: ehci_init() failed, err=%d\n", hcd->self.busnum, err); ++ return err; ++ } ++ ++ /* ++ * Not sure why this is not set by ehci_init(). Convention seems to be ++ * to do it here for reasons unknown. This is a "packed release number". ++ */ ++ ehci->sbrn = 0x20; ++ ++ if ((err = ehci_reset(ehci)) < 0) { ++ printk(KERN_ERR "busnum %d: ehci_reset() failed, err=%d\n", hcd->self.busnum, err); ++ return err; ++ } ++ ++ return 0; ++} ++ ++int bcm_ehci_probe(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb; ++ struct usb_hcd *hcd; ++ struct ehci_hcd *ehci; ++ struct resource *iomem, *ioarea; ++ int ret, irq; ++ ++ if (usb_disabled()) ++ return -ENODEV; ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!iomem) { ++ EHCI_ERR(pdev, "no mem resource\n"); ++ ret = -ENOMEM; ++ goto err_exit; ++ } ++ ++ /* get the irq info */ ++ irq = platform_get_irq(pdev, 0); ++ if (!irq) { ++ EHCI_ERR(pdev, "no irq resource\n"); ++ ret = -ENODEV; ++ goto err_exit; ++ } ++ ++ ioarea = request_mem_region(iomem->start, resource_size(iomem), pdev->name); ++ if (!ioarea) { ++ EHCI_ERR(pdev, "memory region already claimed\n"); ++ ret = -EBUSY; ++ goto err_exit; ++ } ++ ++ usb = kzalloc(sizeof(*usb), GFP_KERNEL); ++ if (!usb) { ++ EHCI_ERR(pdev, "unable to allocate memory for private data\n"); ++ ret = -ENOMEM; ++ goto err_free_iomem; ++ } ++ ++ usb->virt_reg_base = ioremap(iomem->start, resource_size(iomem)); ++ if (!usb->virt_reg_base) { ++ EHCI_ERR(pdev, "ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_free_private_mem; ++ } ++ ++ /* enable clock and PHY */ ++ ret = bcm_usbh_init(pdev->id); ++ if (ret < 0) { ++ EHCI_ERR(pdev, "clock and PHY initialization failed\n"); ++ goto err_io_unmap; ++ } ++ ++ hcd = usb_create_hcd(&ehci_hcd_driver, &pdev->dev, (char *)pdev->name); ++ if (!hcd) { ++ EHCI_ERR(pdev, "usb_create_hcd failed\n"); ++ ret = -ENOMEM; ++ goto err_usb_term; ++ } ++ ++ /* struct ehci_regs def'd in Linux ehci.h which is included by Linux ehci-hcd.c */ ++ usb->hcd = hcd; ++ hcd->rsrc_start = (unsigned int)usb->virt_reg_base; ++ hcd->rsrc_len = sizeof(struct ehci_regs); ++ hcd->regs = usb->virt_reg_base; ++ ++ ehci = hcd_to_ehci(hcd); ++ ehci->caps = hcd->regs; ++ ehci->regs = hcd->regs + HC_LENGTH(ehci,ehci_readl(ehci, &ehci->caps->hc_capbase)); ++ ++ /* cache this readonly data; minimize chip reads */ ++ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); ++ ++ ret = usb_add_hcd(hcd, irq, BCM_USBEHCI_IRQF_FLAGS); ++ if (ret) { ++ EHCI_ERR(pdev, "usb_add_hcd failed\n"); ++ goto err_remove_hcd; ++ } ++ ++ ehci_writel(ehci,BCM_USB_FIFO_THRESHOLD, &ehci->regs->reserved4[6]); ++ ++ ++ platform_set_drvdata(pdev, usb); ++ ++ EHCI_INFO(pdev, "probe done\n"); ++ return 0; ++ ++err_remove_hcd: ++ //usb_remove_hcd(hcd); ++ //usb_put_hcd(hcd); ++ ++err_usb_term: ++ bcm_usbh_term(pdev->id); ++ ++err_io_unmap: ++ iounmap(usb->virt_reg_base); ++ ++err_free_private_mem: ++ kfree(usb); ++ ++err_free_iomem: ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++err_exit: ++ EHCI_ERR(pdev, "probe failed: %d\n", ret); ++ return ret; ++} ++ ++int bcm_ehci_remove(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct resource *iomem; ++ ++ usb_remove_hcd(hcd); ++ usb_put_hcd(hcd); ++ ++ bcm_usbh_term(pdev->id); ++ iounmap(usb->virt_reg_base); ++ kfree(usb); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static void bcm_ehci_shutdown(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ ++ if (hcd->driver->shutdown) ++ hcd->driver->shutdown(hcd); ++} ++ ++#ifdef CONFIG_PM ++static int bcm_ehci_suspend(struct platform_device *pdev, pm_message_t message) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct ehci_hcd *ehci = hcd_to_ehci(hcd); ++ unsigned long flags; ++ int rc = 0; ++ ++ if (time_before(jiffies, ehci->next_statechange)) ++ msleep(10); ++ ++ /* Root hub was already suspended. Disable irq emission and ++ * mark HW unaccessible, bail out if RH has been resumed. Use ++ * the spinlock to properly synchronize with possible pending ++ * RH suspend or resume activity. ++ * ++ * This is still racy as hcd->state is manipulated outside of ++ * any locks =P But that will be a different fix. ++ */ ++ spin_lock_irqsave (&ehci->lock, flags); ++ if (hcd->state != HC_STATE_SUSPENDED) { ++ rc = -EINVAL; ++ goto bail; ++ } ++ ehci_writel(ehci, 0, &ehci->regs->intr_enable); ++ (void)ehci_readl(ehci, &ehci->regs->intr_enable); ++ ++ /* make sure snapshot being resumed re-enumerates everything */ ++ if (message.event == PM_EVENT_PRETHAW) { ++ ehci_halt(ehci); ++ ehci_reset(ehci); ++ } ++ ++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ rc = bcm_usbh_suspend(pdev->id); ++ ++bail: ++ spin_unlock_irqrestore (&ehci->lock, flags); ++ ++ return rc; ++} ++ ++static int bcm_ehci_resume(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct ehci_hcd *ehci = hcd_to_ehci(hcd); ++ int rc; ++ ++ if (time_before(jiffies, ehci->next_statechange)) ++ msleep(100); ++ ++ rc = bcm_usbh_resume(pdev->id); ++ ++ /* Mark hardware accessible again as we are out of D3 state by now */ ++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ ++ /* If CF is still set, we maintained PCI Vaux power. ++ * Just undo the effect of ehci_pci_suspend(). ++ */ ++ if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { ++ int mask = INTR_MASK; ++ ++ if (!hcd->self.root_hub->do_remote_wakeup) ++ mask &= ~STS_PCD; ++ ehci_writel(ehci, mask, &ehci->regs->intr_enable); ++ ehci_readl(ehci, &ehci->regs->intr_enable); ++ return 0; ++ } ++ ++ ehci_dbg(ehci, "lost power, restarting\n"); ++ usb_root_hub_lost_power(hcd->self.root_hub); ++ ++ /* ++ * Else reset, to cope with power loss or flush-to-storage ++ * style "resume" having let BIOS kick in during reboot. ++ */ ++ (void)ehci_halt(ehci); ++ (void)ehci_reset(ehci); ++ ++ /* emptying the schedule aborts any urbs */ ++ spin_lock_irq(&ehci->lock); ++#warning "TODO: ehci->reclaim no longer part of struct ehci_hcd" ++ ehci_work(ehci); ++ spin_unlock_irq(&ehci->lock); ++ ++ ehci_writel(ehci, ehci->command, &ehci->regs->command); ++ ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); ++ ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ ++ ++ /* here we "know" root ports should always stay powered */ ++ ehci_port_power(ehci, 1); ++ ++ hcd->state = HC_STATE_SUSPENDED; ++ ++ return 0; ++} ++ ++#else ++#define bcm_ehci_suspend NULL ++#define bcm_ehci_resume NULL ++#endif /* CONFIG_PM */ ++ ++static struct platform_driver ehci_bcm_driver = ++{ ++ .probe = bcm_ehci_probe, ++ .remove = bcm_ehci_remove, ++ .shutdown = bcm_ehci_shutdown, ++ .suspend = bcm_ehci_suspend, ++ .resume = bcm_ehci_resume, ++ .driver = { ++ .name = BCM_USBEHCI_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++MODULE_DESCRIPTION(BCM_USBEHCI_MODULE_DESCRIPTION); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(BCM_USBEHCI_MODULE_VERSION); +diff --git a/drivers/bcmdrivers/usb2h/ohci-bcm.c b/drivers/bcmdrivers/usb2h/ohci-bcm.c +new file mode 100644 +index 0000000..24b21fe +--- /dev/null ++++ b/drivers/bcmdrivers/usb2h/ohci-bcm.c +@@ -0,0 +1,314 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++#include "bcm_usbh.h" ++ ++#define BCM_USBOHCI_MODULE_DESCRIPTION "Broadcom USB OHCI driver" ++#define BCM_USBOHCI_MODULE_VERSION "1.0.0" ++ ++#define BCM_USBOHCI_IRQF_FLAGS (IRQF_DISABLED | IRQF_SHARED) ++#define BCM_USBOHCI_NAME "bcm-ohci" ++ ++#define OHCI_INFO(pdev, fmt, args...) dev_info(&pdev->dev, fmt, ## args) ++#define OHCI_ERR(pdev, fmt, args...) dev_err(&pdev->dev, fmt, ## args) ++ ++struct usb_cfg ++{ ++ void *virt_reg_base; ++ struct usb_hcd *hcd; ++}; ++ ++extern int usb_disabled(void); ++extern int InUSBDMode(void); ++static int bcm_ohci_start(struct usb_hcd *hcd); ++ ++static const struct hc_driver ohci_hcd_driver = ++{ ++ .description = hcd_name, ++ .product_desc = BCM_USBOHCI_NAME, ++ .hcd_priv_size = sizeof(struct ohci_hcd), ++ ++ /* ++ * generic hardware linkage ++ */ ++ .irq = ohci_irq, ++ .flags = HCD_USB11 | HCD_MEMORY, ++ ++ /* ++ * basic lifecycle operations ++ */ ++ .start = bcm_ohci_start, ++ .stop = ohci_stop, ++ .shutdown = ohci_shutdown, ++#ifdef CONFIG_PM ++ .bus_suspend = ohci_bus_suspend, ++ .bus_resume = ohci_bus_resume, ++#endif ++ ++ /* ++ * managing i/o requests and associated device resources ++ */ ++ .urb_enqueue = ohci_urb_enqueue, ++ .urb_dequeue = ohci_urb_dequeue, ++ .endpoint_disable = ohci_endpoint_disable, ++ ++ /* ++ * scheduling support ++ */ ++ .get_frame_number = ohci_get_frame, ++ ++ /* ++ * root hub support ++ */ ++ .hub_status_data = ohci_hub_status_data, ++ .hub_control = ohci_hub_control, ++}; ++ ++static int bcm_ohci_start(struct usb_hcd *hcd) ++{ ++ struct ohci_hcd *ohci; ++ int err; ++ ++ if (!hcd) { ++ printk(KERN_ERR "invalid hcd pointer in %s\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ ohci = hcd_to_ohci(hcd); ++ ++ if ((err = ohci_init(ohci)) < 0) { ++ printk(KERN_ERR "busnum %d: ohci_init() failed, err=%d\n", hcd->self.busnum, err); ++ return err; ++ } ++ ++ if ((err = ohci_run(ohci)) < 0) { ++ printk(KERN_ERR "busnum %d: ohci_run() failed, err=%d\n", hcd->self.busnum, err); ++ ohci_stop(hcd); ++ return err; ++ } ++ ++ return 0; ++} ++ ++int bcm_ohci_probe(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb; ++ struct usb_hcd *hcd; ++ struct resource *iomem, *ioarea; ++ int ret, irq; ++ ++ if (usb_disabled()) ++ return -ENODEV; ++ ++ if (InUSBDMode()) ++ return -ENODEV; ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!iomem) { ++ OHCI_ERR(pdev, "no mem resource\n"); ++ ret = -ENOMEM; ++ goto err_exit; ++ } ++ ++ /* get the irq info */ ++ irq = platform_get_irq(pdev, 0); ++ if (!irq) { ++ OHCI_ERR(pdev, "no irq resource\n"); ++ ret = -ENODEV; ++ goto err_exit; ++ } ++ ++ ioarea = request_mem_region(iomem->start, resource_size(iomem), pdev->name); ++ if (!ioarea) { ++ OHCI_ERR(pdev, "memory region already claimed\n"); ++ ret = -EBUSY; ++ goto err_exit; ++ } ++ ++ usb = kzalloc(sizeof(*usb), GFP_KERNEL); ++ if (!usb) { ++ OHCI_ERR(pdev, "unable to allocate memory for private data\n"); ++ ret = -ENOMEM; ++ goto err_free_iomem; ++ } ++ ++ usb->virt_reg_base = ioremap(iomem->start, resource_size(iomem)); ++ if (!usb->virt_reg_base) { ++ OHCI_ERR(pdev, "ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_free_private_mem; ++ } ++ ++ /* enable clock and PHY */ ++ ret = bcm_usbh_init(pdev->id); ++ if (ret < 0) { ++ OHCI_ERR(pdev, "clock and PHY initialization failed\n"); ++ goto err_io_unmap; ++ } ++ ++ hcd = usb_create_hcd(&ohci_hcd_driver, &pdev->dev, (char *)pdev->name); ++ if (!hcd) { ++ OHCI_ERR(pdev, "usb_create_hcd failed\n"); ++ ret = -ENOMEM; ++ goto err_usb_term; ++ } ++ ++ /* struct ohci_regs def'd in Linux ohci.h which is included by Linux ohci-hcd.c */ ++ usb->hcd = hcd; ++ hcd->rsrc_start = (unsigned int)usb->virt_reg_base; ++ hcd->rsrc_len = sizeof(struct ohci_regs); ++ hcd->regs = usb->virt_reg_base; ++ ++ ohci_hcd_init(hcd_to_ohci(hcd)); ++ ++ ret = usb_add_hcd(hcd, irq, BCM_USBOHCI_IRQF_FLAGS); ++ if (ret) { ++ OHCI_ERR(pdev, "usb_add_hcd failed\n"); ++ goto err_remove_hcd; ++ } ++ ++ platform_set_drvdata(pdev, usb); ++ ++ OHCI_INFO(pdev, "probe done\n"); ++ return 0; ++ ++err_remove_hcd: ++ //usb_remove_hcd(hcd); ++ //usb_put_hcd(hcd); ++ ++err_usb_term: ++ bcm_usbh_term(pdev->id); ++ ++err_io_unmap: ++ iounmap(usb->virt_reg_base); ++ ++err_free_private_mem: ++ kfree(usb); ++ ++err_free_iomem: ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++err_exit: ++ OHCI_ERR(pdev, "probe failed: %d\n", ret); ++ return ret; ++} ++ ++int bcm_ohci_remove(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct resource *iomem; ++ ++ usb_remove_hcd(hcd); ++ usb_put_hcd(hcd); ++ ++ bcm_usbh_term(pdev->id); ++ iounmap(usb->virt_reg_base); ++ kfree(usb); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static void bcm_ohci_shutdown(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ ++ if (hcd->driver->shutdown) ++ hcd->driver->shutdown(hcd); ++} ++ ++#ifdef CONFIG_PM ++static int bcm_ohci_suspend(struct platform_device *pdev, pm_message_t message) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct ohci_hcd *ohci = hcd_to_ohci(hcd); ++ unsigned long flags; ++ int rc = 0; ++ ++ /* Root hub was already suspended. Disable irq emission and ++ * mark HW unaccessible, bail out if RH has been resumed. Use ++ * the spinlock to properly synchronize with possible pending ++ * RH suspend or resume activity. ++ * ++ * This is still racy as hcd->state is manipulated outside of ++ * any locks =P But that will be a different fix. ++ */ ++ spin_lock_irqsave(&ohci->lock, flags); ++ if (hcd->state != HC_STATE_SUSPENDED) { ++ rc = -EINVAL; ++ goto bail; ++ } ++ ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); ++ (void)ohci_readl(ohci, &ohci->regs->intrdisable); ++ ++ /* make sure snapshot being resumed re-enumerates everything */ ++ if (message.event == PM_EVENT_PRETHAW) ++ ohci_usb_reset(ohci); ++ ++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ rc = bcm_usbh_suspend(pdev->id); ++ ++bail: ++ spin_unlock_irqrestore(&ohci->lock, flags); ++ return rc; ++} ++ ++static int bcm_ohci_resume(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ ++ bcm_usbh_resume(pdev->id); ++ ++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ ohci_finish_controller_resume(hcd); ++ ++ return 0; ++} ++#endif /* CONFIG_PM */ ++ ++/* ++ * Generic platform device driver definition. ++ */ ++static struct platform_driver ohci_bcm_driver = ++{ ++ .probe = bcm_ohci_probe, ++ .remove = bcm_ohci_remove, ++ .shutdown = bcm_ohci_shutdown, ++#ifdef CONFIG_PM ++ .suspend = bcm_ohci_suspend, ++ .resume = bcm_ohci_resume, ++#endif ++ .driver = { ++ .name = BCM_USBOHCI_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++MODULE_DESCRIPTION(BCM_USBOHCI_MODULE_DESCRIPTION); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(BCM_USBOHCI_MODULE_VERSION); +diff --git a/drivers/bcmdrivers/usb2h/usbh_cfg.h b/drivers/bcmdrivers/usb2h/usbh_cfg.h +new file mode 100644 +index 0000000..c00b0ae +--- /dev/null ++++ b/drivers/bcmdrivers/usb2h/usbh_cfg.h +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __ISLAND_USBH_CFG_H ++#define __ISLAND_USBH_CFG_H ++ ++#define USBH_NUM_PORTS 3 ++ ++struct usbh_port_cfg { ++ /* GPIO for host power */ ++ int pwr_gpio; ++ ++ /* GPIO for power fault (over-current) detection */ ++ int pwr_flt_gpio; ++ ++ /* GPIO for PHY reset */ ++ int reset_gpio; ++}; ++ ++/* ++ * USB Host related HW parameters ++ */ ++struct usbh_cfg { ++ /* peripheral clock name string */ ++ char *peri_clk_name; ++ ++ /* AHB bus clock name string */ ++ char *ahb_clk_name; ++ ++ /* the block might require optional clock to be enabled */ ++ char *opt_clk_name; ++ ++ unsigned int num_ports; ++ ++ struct usbh_port_cfg port[USBH_NUM_PORTS]; ++}; ++ ++#endif +diff --git a/drivers/bcmdrivers/wdt/.gitignore b/drivers/bcmdrivers/wdt/.gitignore +new file mode 100644 +index 0000000..d741861 +--- /dev/null ++++ b/drivers/bcmdrivers/wdt/.gitignore +@@ -0,0 +1,4 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/wdt/Kconfig b/drivers/bcmdrivers/wdt/Kconfig +new file mode 100644 +index 0000000..ad0b803 +--- /dev/null ++++ b/drivers/bcmdrivers/wdt/Kconfig +@@ -0,0 +1,7 @@ ++config IPROC_WDT ++ tristate "Watchdog Timer support" ++ select WATCHDOG ++ depends on ARCH_IPROC && MACH_NS ++ help ++ This selects a driver for the hardware watchdog on Broadcom ++ iProc chips. +diff --git a/drivers/bcmdrivers/wdt/Makefile b/drivers/bcmdrivers/wdt/Makefile +new file mode 100644 +index 0000000..aefed3e +--- /dev/null ++++ b/drivers/bcmdrivers/wdt/Makefile +@@ -0,0 +1,2 @@ ++ ++obj-$(CONFIG_IPROC_WDT) += iproc_wdt.o +diff --git a/drivers/bcmdrivers/wdt/iproc_wdt.c b/drivers/bcmdrivers/wdt/iproc_wdt.c +new file mode 100755 +index 0000000..33812fa +--- /dev/null ++++ b/drivers/bcmdrivers/wdt/iproc_wdt.c +@@ -0,0 +1,491 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++#include ++#endif ++ ++/* Chip specific */ ++#define IPROC_WATCHDOG_CLK_HZ 125000000UL ++#define IPROC_WATCHDOG_COUNTER_BITS (28) ++ ++/* Default values */ ++#define TIMEOUT_MAX \ ++ ((int)((1 << IPROC_WATCHDOG_COUNTER_BITS) - 1) / IPROC_WATCHDOG_CLK_HZ) ++#define TIMEOUT_DEFAULT (TIMEOUT_MAX > 60? (int)60 : (int)TIMEOUT_MAX) ++ ++/* module parameters */ ++static int timeout = TIMEOUT_DEFAULT; ++module_param(timeout, int, 0); ++MODULE_PARM_DESC(timeout, ++ "Timeout value. (default=" ++ __MODULE_STRING(TIMEOUT_DEFAULT) ")"); ++ ++static int nowayout = WATCHDOG_NOWAYOUT; ++module_param(nowayout, int, 0); ++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" ++ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++ ++/* Watchdog register offsets and field */ ++#define IPROC_REG_WDT_INTSTATUS 0x20 ++#define IPROC_FLD_WDT_INTSTATUS_WDT_RESET_MASK 0x80000000 ++#define IPROC_REG_WDT_WATCHDOG_COUNTER 0x80 ++ ++/* Register access macro */ ++#define wdt_readl(dev, reg) \ ++ readl_relaxed((dev)->regs + (reg)) ++#define wdt_writel(dev, reg, value) \ ++ writel_relaxed((value), (dev)->regs + (reg)) ++ ++/* Driver specific data */ ++struct wdt_iproc { ++ volatile void *regs; ++ spinlock_t io_lock; ++ int timeout; ++ int boot_status; ++ unsigned long users; ++ struct miscdevice miscdev; ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ SWRR_HANDLE swrr; ++#endif ++}; ++static struct wdt_iproc *wdt; ++static char expect_release; ++ ++/* ++ * Disable the watchdog. ++ */ ++static inline void ++iproc_wdt_stop(void) ++{ ++ spin_lock(&wdt->io_lock); ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (wdt->swrr != NULL) ++ swreset_record_set(wdt->swrr, 0); ++#endif ++ wdt_writel(wdt, ++ IPROC_REG_WDT_WATCHDOG_COUNTER, ++ 0 ++ ); ++ spin_unlock(&wdt->io_lock); ++} ++ ++/* ++ * Enable and reset the watchdog. ++ */ ++static inline void ++iproc_wdt_start(void) ++{ ++ spin_lock(&wdt->io_lock); ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (wdt->swrr != NULL) ++ swreset_record_set(wdt->swrr, 1); ++#endif ++ wdt_writel(wdt, ++ IPROC_REG_WDT_WATCHDOG_COUNTER, ++ wdt->timeout * IPROC_WATCHDOG_CLK_HZ ++ ); ++ spin_unlock(&wdt->io_lock); ++} ++ ++/* ++ * Pat the watchdog timer. ++ */ ++static inline void ++iproc_wdt_pat(void) ++{ ++ iproc_wdt_start(); ++} ++ ++/* ++ * Watchdog device is opened, and watchdog starts running. ++ */ ++static int ++iproc_wdt_open(struct inode *inode, struct file *file) ++{ ++ if (test_and_set_bit(1, &wdt->users)) ++ return -EBUSY; ++ ++ iproc_wdt_start(); ++ return nonseekable_open(inode, file); ++} ++ ++/* ++ * Close the watchdog device. ++ */ ++static int ++iproc_wdt_close(struct inode *inode, struct file *file) ++{ ++ if (expect_release == 1) { ++ iproc_wdt_stop(); ++ } else { ++ dev_dbg(wdt->miscdev.parent, ++ "unexpected close, not stopping watchdog!\n"); ++ iproc_wdt_pat(); ++ } ++ clear_bit(1, &wdt->users); ++ expect_release = 0; ++ return 0; ++} ++ ++/* ++ * Change the watchdog time interval. ++ */ ++static int ++iproc_wdt_settimeout(int time) ++{ ++ if (time < 0 || time > TIMEOUT_MAX) { ++ return -EINVAL; ++ } ++ ++ /* ++ * Set new watchdog time. It will be used when iproc_wdt_start() is ++ * called. ++ */ ++ wdt->timeout = time; ++ return 0; ++} ++ ++/* ++ * Get the watchdog status. ++ */ ++static int ++iproc_wdt_get_status(void) ++{ ++ if (wdt_readl(wdt, IPROC_REG_WDT_INTSTATUS) & ++ IPROC_FLD_WDT_INTSTATUS_WDT_RESET_MASK) { ++ return WDIOF_CARDRESET; ++ } ++ ++ return 0; ++} ++ ++static const struct watchdog_info iproc_wdt_info = { ++ .identity = "iproc watchdog", ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, ++}; ++ ++/* ++ * Handle commands from user-space. ++ */ ++static long ++iproc_wdt_ioctl(struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ int ret = -ENOTTY; ++ int time; ++ void __user *argp = (void __user *)arg; ++ int __user *p = argp; ++ ++ switch (cmd) { ++ case WDIOC_GETSUPPORT: ++ ret = copy_to_user(argp, &iproc_wdt_info, ++ sizeof(iproc_wdt_info)) ? -EFAULT : 0; ++ break; ++ case WDIOC_GETSTATUS: ++ ret = put_user(0, p); ++ break; ++ case WDIOC_GETBOOTSTATUS: ++ ret = put_user(wdt->boot_status, p); ++ break; ++ case WDIOC_SETOPTIONS: ++ ret = get_user(time, p); ++ if (ret) ++ break; ++ if (time & WDIOS_DISABLECARD) ++ iproc_wdt_stop(); ++ if (time & WDIOS_ENABLECARD) ++ iproc_wdt_start(); ++ ret = 0; ++ break; ++ case WDIOC_KEEPALIVE: ++ iproc_wdt_pat(); ++ ret = 0; ++ break; ++ case WDIOC_SETTIMEOUT: ++ ret = get_user(time, p); ++ if (ret) ++ break; ++ ret = iproc_wdt_settimeout(time); ++ if (ret) ++ break; ++ /* Enable new time value */ ++ iproc_wdt_start(); ++ /* fall through */ ++ case WDIOC_GETTIMEOUT: ++ ret = put_user(wdt->timeout, p); ++ break; ++ } ++ ++ return ret; ++} ++ ++static ssize_t ++iproc_wdt_write(struct file *file, const char __user *data, ++ size_t len, loff_t *ppos) ++{ ++ /* See if we got the magic character 'V' and reload the timer */ ++ if (len) { ++ if (!nowayout) { ++ size_t i; ++ ++ /* ++ * note: just in case someone wrote the magic ++ * character five months ago... ++ */ ++ expect_release = 0; ++ ++ /* ++ * scan to see whether or not we got the magic ++ * character ++ */ ++ for (i = 0; i != len; i++) { ++ char c; ++ if (get_user(c, data + i)) ++ return -EFAULT; ++ if (c == 'V') ++ expect_release = 1; ++ } ++ } ++ /* someone wrote to us, we should pat the watchdog */ ++ iproc_wdt_pat(); ++ } ++ return len; ++} ++ ++static int ++iproc_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) ++{ ++ if (code == SYS_DOWN || code == SYS_HALT) { ++ /* Turn the watchdog off */ ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (wdt->swrr != NULL) { ++ swreset_record_set(wdt->swrr, 0); ++ } ++#endif ++ iproc_wdt_stop(); ++ } ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block iproc_wdt_notifier = { ++ .notifier_call = iproc_wdt_notify_sys, ++}; ++ ++static const struct file_operations iproc_wdt_fops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .unlocked_ioctl = iproc_wdt_ioctl, ++ .open = iproc_wdt_open, ++ .release = iproc_wdt_close, ++ .write = iproc_wdt_write, ++}; ++ ++static int __init ++iproc_wdt_probe(struct platform_device *pdev) ++{ ++ struct resource *regs; ++ int ret; ++ ++ if (wdt) { ++ dev_dbg(&pdev->dev, "only 1 wdt instance supported.\n"); ++ return -EBUSY; ++ } ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ dev_dbg(&pdev->dev, "missing resource 0\n"); ++ return -ENXIO; ++ } ++ ++ wdt = kzalloc(sizeof(struct wdt_iproc), GFP_KERNEL); ++ if (!wdt) { ++ dev_dbg(&pdev->dev, "no memory for wdt structure\n"); ++ return -ENOMEM; ++ } ++ ++ wdt->regs = ioremap(regs->start, resource_size(regs)); ++ if (!wdt->regs) { ++ ret = -ENOMEM; ++ dev_dbg(&pdev->dev, "could not map I/O memory\n"); ++ goto err_free; ++ } ++ ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (swreset_record_get_record_count() == 0) { ++ /* No software reset record support */ ++ wdt->swrr = NULL; ++ wdt->boot_status = iproc_wdt_get_status(); ++ } else { ++ wdt->swrr = swreset_record_register("iproc_cca_watchdog"); ++ if (wdt->swrr == NULL) { ++ /* All software reset records are used (unlikely) */ ++ dev_warn(&pdev->dev, "Boot status is not available!\n"); ++ /* Still try to use original watchdog reset status */ ++ wdt->boot_status = iproc_wdt_get_status(); ++ } else { ++ /* Get previous value */ ++ swreset_record_get(wdt->swrr, &wdt->boot_status); ++ /* Clear it */ ++ swreset_record_set(wdt->swrr, 0); ++ } ++ } ++#else ++ wdt->boot_status = iproc_wdt_get_status(); ++#endif ++ ++ /* To avoid treating manual reboot as a watchdog reset */ ++ ret = register_reboot_notifier(&iproc_wdt_notifier); ++ if (ret) { ++ /* In this case, manual reboot could be mistaken as watchdog reset */ ++ dev_dbg(&pdev->dev, "could not register reboot notifier\n"); ++ } ++ ++ expect_release = 0; ++ spin_lock_init(&wdt->io_lock); ++ wdt->users = 0; ++ ++ wdt->miscdev.minor = WATCHDOG_MINOR; ++ wdt->miscdev.name = "watchdog"; ++ wdt->miscdev.fops = &iproc_wdt_fops; ++ wdt->miscdev.parent = &pdev->dev; ++ ++ platform_set_drvdata(pdev, wdt); ++ ++ if (iproc_wdt_settimeout(timeout)) { ++ iproc_wdt_settimeout(TIMEOUT_DEFAULT); ++ dev_dbg(&pdev->dev, ++ "default timeout invalid, set to %d sec.\n", ++ TIMEOUT_DEFAULT); ++ } ++ ++ ret = misc_register(&wdt->miscdev); ++ if (ret) { ++ dev_dbg(&pdev->dev, "failed to register wdt miscdev\n"); ++ goto err_register; ++ } ++ ++ dev_info(&pdev->dev, ++ "iProc Watchdog Timer - timeout=%d sec, nowayout=%d\n", ++ wdt->timeout, nowayout); ++ ++ return 0; ++ ++err_register: ++ platform_set_drvdata(pdev, NULL); ++ iounmap(wdt->regs); ++err_free: ++ kfree(wdt); ++ wdt = NULL; ++ return ret; ++} ++ ++static int __exit ++iproc_wdt_remove(struct platform_device *pdev) ++{ ++ if (wdt && platform_get_drvdata(pdev) == wdt) { ++ /* Stop the timer before we leave */ ++ if (!nowayout) ++ iproc_wdt_stop(); ++ ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (wdt->swrr != NULL) { ++ swreset_record_set(wdt->swrr, 0); ++ swreset_record_unregister(wdt->swrr); ++ wdt->swrr = NULL; ++ } ++#endif ++ unregister_reboot_notifier(&iproc_wdt_notifier); ++ misc_deregister(&wdt->miscdev); ++ iounmap(wdt->regs); ++ kfree(wdt); ++ wdt = NULL; ++ platform_set_drvdata(pdev, NULL); ++ } ++ return 0; ++} ++ ++static void ++iproc_wdt_shutdown(struct platform_device *pdev) ++{ ++ iproc_wdt_stop(); ++} ++ ++#ifdef CONFIG_PM ++static int ++iproc_wdt_suspend(struct platform_device *pdev, pm_message_t message) ++{ ++ iproc_wdt_stop(); ++ return 0; ++} ++ ++static int ++iproc_wdt_resume(struct platform_device *pdev) ++{ ++ if (wdt->users) ++ iproc_wdt_start(); ++ return 0; ++} ++#else ++#define iproc_wdt_suspend NULL ++#define iproc_wdt_resume NULL ++#endif ++ ++/* work with hotplug and coldplug */ ++MODULE_ALIAS("platform:iproc_wdt"); ++ ++static struct platform_driver iproc_wdt_driver = { ++ .remove = __exit_p(iproc_wdt_remove), ++ .suspend = iproc_wdt_suspend, ++ .resume = iproc_wdt_resume, ++ .driver = { ++ .name = "iproc_wdt", ++ .owner = THIS_MODULE, ++ }, ++ .shutdown = iproc_wdt_shutdown, ++}; ++ ++static int __init ++iproc_wdt_init(void) ++{ ++ return platform_driver_probe(&iproc_wdt_driver, iproc_wdt_probe); ++} ++module_init(iproc_wdt_init); ++ ++static void __exit ++iproc_wdt_exit(void) ++{ ++ platform_driver_unregister(&iproc_wdt_driver); ++} ++module_exit(iproc_wdt_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Watchdog driver for Broadcom iProc chips"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index e9e8f3b..1d2ae23 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -377,10 +377,8 @@ static int ath3k_load_patch(struct usb_device *udev) + fw_version.rom_version); + + ret = request_firmware(&firmware, filename, &udev->dev); +- if (ret < 0) { +- BT_ERR("Patch file not found %s", filename); ++ if (ret) + return ret; +- } + + pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8); + pt_version.build_version = *(int *) +@@ -439,10 +437,8 @@ static int ath3k_load_syscfg(struct usb_device *udev) + fw_version.rom_version, clk_value, ".dfu"); + + ret = request_firmware(&firmware, filename, &udev->dev); +- if (ret < 0) { +- BT_ERR("Configuration file not found %s", filename); ++ if (ret) + return ret; +- } + + ret = ath3k_load_fwfile(udev, firmware); + release_firmware(firmware); +diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c +index 54952ab..f35c287 100644 +--- a/drivers/bluetooth/bcm203x.c ++++ b/drivers/bluetooth/bcm203x.c +@@ -194,7 +194,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id + } + + if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) { +- BT_ERR("Mini driver request failed"); + usb_free_urb(data->urb); + kfree(data); + return -EIO; +@@ -221,7 +220,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id + release_firmware(firmware); + + if (request_firmware(&firmware, "BCM2033-FW.bin", &udev->dev) < 0) { +- BT_ERR("Firmware request failed"); + usb_free_urb(data->urb); + kfree(data->buffer); + kfree(data); +diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c +index 61b5914..e1c3fc3 100644 +--- a/drivers/bluetooth/bfusb.c ++++ b/drivers/bluetooth/bfusb.c +@@ -681,10 +681,8 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i + skb_queue_head_init(&data->pending_q); + skb_queue_head_init(&data->completed_q); + +- if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) { +- BT_ERR("Firmware request failed"); ++ if (request_firmware(&firmware, "bfubase.frm", &udev->dev)) + goto error; +- } + + BT_DBG("firmware data %p size %zu", firmware->data, firmware->size); + +diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c +index 4fc0194..b11a3be 100644 +--- a/drivers/bluetooth/bt3c_cs.c ++++ b/drivers/bluetooth/bt3c_cs.c +@@ -594,10 +594,8 @@ static int bt3c_open(bt3c_info_t *info) + + /* Load firmware */ + err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev); +- if (err < 0) { +- BT_ERR("Firmware request failed"); ++ if (err) + goto error; +- } + + err = bt3c_load_firmware(info, firmware->data, firmware->size); + +diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c +index 27b74b0..c82975d 100644 +--- a/drivers/bluetooth/btmrvl_sdio.c ++++ b/drivers/bluetooth/btmrvl_sdio.c +@@ -258,8 +258,6 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card) + ret = request_firmware(&fw_helper, card->helper, + &card->func->dev); + if ((ret < 0) || !fw_helper) { +- BT_ERR("request_firmware(helper) failed, error code = %d", +- ret); + ret = -ENOENT; + goto done; + } +@@ -360,8 +358,6 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card) + ret = request_firmware(&fw_firmware, card->firmware, + &card->func->dev); + if ((ret < 0) || !fw_firmware) { +- BT_ERR("request_firmware(firmware) failed, error code = %d", +- ret); + ret = -ENOENT; + goto done; + } +diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c +index 780498d..444f8b6 100644 +--- a/drivers/char/agp/amd64-agp.c ++++ b/drivers/char/agp/amd64-agp.c +@@ -33,7 +33,7 @@ + #define ULI_X86_64_ENU_SCR_REG 0x54 + + static struct resource *aperture_resource; +-static int __initdata agp_try_unsupported = 1; ++static bool __initdata agp_try_unsupported = 1; + static int agp_bridges_found; + + static void amd64_tlbflush(struct agp_memory *temp) +diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c +index 4b71647..317c28c 100644 +--- a/drivers/char/agp/backend.c ++++ b/drivers/char/agp/backend.c +@@ -194,10 +194,10 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) + + err_out: + if (bridge->driver->needs_scratch_page) { +- void *va = page_address(bridge->scratch_page_page); ++ struct page *page = bridge->scratch_page_page; + +- bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); +- bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); ++ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP); ++ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE); + } + if (got_gatt) + bridge->driver->free_gatt_table(bridge); +@@ -221,10 +221,10 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) + + if (bridge->driver->agp_destroy_page && + bridge->driver->needs_scratch_page) { +- void *va = page_address(bridge->scratch_page_page); ++ struct page *page = bridge->scratch_page_page; + +- bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); +- bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); ++ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP); ++ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE); + } + } + +diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c +index b072648..17e05d1 100644 +--- a/drivers/char/agp/generic.c ++++ b/drivers/char/agp/generic.c +@@ -514,12 +514,12 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ + switch (*bridge_agpstat & 7) { + case 4: + *bridge_agpstat |= (AGPSTAT2_2X | AGPSTAT2_1X); +- printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x4 rate" ++ printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x4 rate. " + "Fixing up support for x2 & x1\n"); + break; + case 2: + *bridge_agpstat |= AGPSTAT2_1X; +- printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x2 rate" ++ printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x2 rate. " + "Fixing up support for x1\n"); + break; + default: +@@ -693,7 +693,7 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ + *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); + *vga_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); + } else { +- printk(KERN_INFO PFX "Fell back to AGPx4 mode because"); ++ printk(KERN_INFO PFX "Fell back to AGPx4 mode because "); + if (!(*bridge_agpstat & AGPSTAT3_8X)) { + printk(KERN_INFO PFX "bridge couldn't do x8. bridge_agpstat:%x (orig=%x)\n", + *bridge_agpstat, origbridge); +@@ -956,7 +956,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) + bridge->driver->cache_flush(); + #ifdef CONFIG_X86 + if (set_memory_uc((unsigned long)table, 1 << page_order)) +- printk(KERN_WARNING "Could not set GATT table memory to UC!"); ++ printk(KERN_WARNING "Could not set GATT table memory to UC!\n"); + + bridge->gatt_table = (void *)table; + #else +diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c +index 58b49d1..4293c48 100644 +--- a/drivers/char/agp/intel-agp.c ++++ b/drivers/char/agp/intel-agp.c +@@ -850,6 +850,7 @@ static struct pci_device_id agp_intel_pci_table[] = { + .subvendor = PCI_ANY_ID, \ + .subdevice = PCI_ANY_ID, \ + } ++ ID(PCI_DEVICE_ID_INTEL_82441), /* for HAS2 support */ + ID(PCI_DEVICE_ID_INTEL_82443LX_0), + ID(PCI_DEVICE_ID_INTEL_82443BX_0), + ID(PCI_DEVICE_ID_INTEL_82443GX_0), +diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c +index 59d4697..4e985cd 100644 +--- a/drivers/char/agp/intel-gtt.c ++++ b/drivers/char/agp/intel-gtt.c +@@ -76,7 +76,6 @@ static struct _intel_private { + struct resource ifp_resource; + int resource_valid; + struct page *scratch_page; +- dma_addr_t scratch_page_dma; + } intel_private; + + #define INTEL_GTT_GEN intel_private.driver->gen +@@ -306,9 +305,9 @@ static int intel_gtt_setup_scratch_page(void) + if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) + return -EINVAL; + +- intel_private.scratch_page_dma = dma_addr; ++ intel_private.base.scratch_page_dma = dma_addr; + } else +- intel_private.scratch_page_dma = page_to_phys(page); ++ intel_private.base.scratch_page_dma = page_to_phys(page); + + intel_private.scratch_page = page; + +@@ -631,7 +630,7 @@ static unsigned int intel_gtt_mappable_entries(void) + static void intel_gtt_teardown_scratch_page(void) + { + set_pages_wb(intel_private.scratch_page, 1); +- pci_unmap_page(intel_private.pcidev, intel_private.scratch_page_dma, ++ pci_unmap_page(intel_private.pcidev, intel_private.base.scratch_page_dma, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + put_page(intel_private.scratch_page); + __free_page(intel_private.scratch_page); +@@ -681,6 +680,7 @@ static int intel_gtt_init(void) + iounmap(intel_private.registers); + return -ENOMEM; + } ++ intel_private.base.gtt = intel_private.gtt; + + global_cache_flush(); /* FIXME: ? */ + +@@ -975,7 +975,7 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries) + unsigned int i; + + for (i = first_entry; i < (first_entry + num_entries); i++) { +- intel_private.driver->write_entry(intel_private.scratch_page_dma, ++ intel_private.driver->write_entry(intel_private.base.scratch_page_dma, + i, 0); + } + readl(intel_private.gtt+i-1); +@@ -1190,7 +1190,6 @@ static inline int needs_idle_maps(void) + { + #ifdef CONFIG_INTEL_IOMMU + const unsigned short gpu_devid = intel_private.pcidev->device; +- extern int intel_iommu_gfx_mapped; + + /* Query intel_iommu to see if we need the workaround. Presumably that + * was loaded first. +diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c +index 29aacd8..08704ae 100644 +--- a/drivers/char/agp/sis-agp.c ++++ b/drivers/char/agp/sis-agp.c +@@ -17,7 +17,7 @@ + #define PCI_DEVICE_ID_SI_662 0x0662 + #define PCI_DEVICE_ID_SI_671 0x0671 + +-static int __devinitdata agp_sis_force_delay = 0; ++static bool __devinitdata agp_sis_force_delay = 0; + static int __devinitdata agp_sis_agp_spec = -1; + + static int sis_fetch_size(void) +diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c +index 052797b..3121310 100644 +--- a/drivers/char/dsp56k.c ++++ b/drivers/char/dsp56k.c +@@ -140,11 +140,8 @@ static int dsp56k_upload(u_char __user *bin, int len) + } + err = request_firmware(&fw, fw_name, &pdev->dev); + platform_device_unregister(pdev); +- if (err) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fw_name, err); ++ if (err) + return err; +- } + if (fw->size % 3) { + printk(KERN_ERR "Bogus length %d in image \"%s\"\n", + fw->size, fw_name); +diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c +index 9658116..9c152ab 100644 +--- a/drivers/char/ramoops.c ++++ b/drivers/char/ramoops.c +@@ -83,8 +83,7 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper, + struct timeval timestamp; + + if (reason != KMSG_DUMP_OOPS && +- reason != KMSG_DUMP_PANIC && +- reason != KMSG_DUMP_KEXEC) ++ reason != KMSG_DUMP_PANIC) + return; + + /* Only dump oopses if dump_oops is set */ +diff --git a/drivers/char/random.c b/drivers/char/random.c +index edf45ae..2e45a87d 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -139,6 +139,9 @@ + * that might otherwise be identical and have very little entropy + * available to them (particularly common in the embedded world). + * ++ * void random_input_words(__u32 *buf, size_t wordcount, int ent_count) ++ * int random_input_wait(void); ++ * + * add_input_randomness() uses the input layer interrupt timing, as well as + * the event type information from the hardware. + * +@@ -152,6 +155,13 @@ + * seek times do not make for good sources of entropy, as their seek + * times are usually fairly consistent. + * ++ * random_input_words() just provides a raw block of entropy to the input ++ * pool, such as from a hardware entropy generator. ++ * ++ * random_input_wait() suspends the caller until such time as the ++ * entropy pool falls below the write threshold, and returns a count of how ++ * much entropy (in bits) is needed to sustain the pool. ++ * + * All of these routines try to estimate how many bits of randomness a + * particular randomness source. They do this by keeping track of the + * first and second order deltas of the event timings. +@@ -821,6 +831,63 @@ void add_disk_randomness(struct gendisk *disk) + } + #endif + ++/* ++ * random_input_words - add bulk entropy to pool ++ * ++ * @buf: buffer to add ++ * @wordcount: number of __u32 words to add ++ * @ent_count: total amount of entropy (in bits) to credit ++ * ++ * this provides bulk input of entropy to the input pool ++ * ++ */ ++void random_input_words(__u32 *buf, size_t wordcount, int ent_count) ++{ ++ mix_pool_bytes(&input_pool, buf, wordcount*4, NULL); ++ ++ credit_entropy_bits(&input_pool, ent_count); ++ ++ DEBUG_ENT("crediting %d bits => %d\n", ++ ent_count, input_pool.entropy_count); ++ /* ++ * Wake up waiting processes if we have enough ++ * entropy. ++ */ ++ if (input_pool.entropy_count >= random_read_wakeup_thresh) ++ wake_up_interruptible(&random_read_wait); ++} ++EXPORT_SYMBOL(random_input_words); ++ ++/* ++ * random_input_wait - wait until random needs entropy ++ * ++ * this function sleeps until the /dev/random subsystem actually ++ * needs more entropy, and then return the amount of entropy ++ * that it would be nice to have added to the system. ++ */ ++int random_input_wait(void) ++{ ++ int count; ++ ++ wait_event_interruptible(random_write_wait, ++ input_pool.entropy_count < random_write_wakeup_thresh); ++ ++ count = random_write_wakeup_thresh - input_pool.entropy_count; ++ ++ /* likely we got woken up due to a signal */ ++ if (count <= 0) count = random_read_wakeup_thresh; ++ ++ DEBUG_ENT("requesting %d bits from input_wait()er %d<%d\n", ++ count, ++ input_pool.entropy_count, random_write_wakeup_thresh); ++ ++ return count; ++} ++EXPORT_SYMBOL(random_input_wait); ++ ++ ++#define EXTRACT_SIZE 10 ++ + /********************************************************************* + * + * Entropy extraction routines +diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c +index 7bac808..13d311e 100644 +--- a/drivers/cpufreq/cpufreq-nforce2.c ++++ b/drivers/cpufreq/cpufreq-nforce2.c +@@ -385,6 +385,14 @@ static struct cpufreq_driver nforce2_driver = { + .owner = THIS_MODULE, + }; + ++#ifdef MODULE ++static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = { ++ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(pci, nforce2_ids); ++#endif ++ + /** + * nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic + * +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index 987a165..8c2df34 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -679,7 +679,7 @@ static struct kobj_type ktype_cpufreq = { + */ + static int cpufreq_add_dev_policy(unsigned int cpu, + struct cpufreq_policy *policy, +- struct sys_device *sys_dev) ++ struct device *dev) + { + int ret = 0; + #ifdef CONFIG_SMP +@@ -728,7 +728,7 @@ static int cpufreq_add_dev_policy(unsigned int cpu, + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + pr_debug("CPU already managed, adding link\n"); +- ret = sysfs_create_link(&sys_dev->kobj, ++ ret = sysfs_create_link(&dev->kobj, + &managed_policy->kobj, + "cpufreq"); + if (ret) +@@ -761,7 +761,7 @@ static int cpufreq_add_dev_symlink(unsigned int cpu, + + for_each_cpu(j, policy->cpus) { + struct cpufreq_policy *managed_policy; +- struct sys_device *cpu_sys_dev; ++ struct device *cpu_dev; + + if (j == cpu) + continue; +@@ -770,8 +770,8 @@ static int cpufreq_add_dev_symlink(unsigned int cpu, + + pr_debug("CPU %u already managed, adding link\n", j); + managed_policy = cpufreq_cpu_get(cpu); +- cpu_sys_dev = get_cpu_sysdev(j); +- ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj, ++ cpu_dev = get_cpu_device(j); ++ ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj, + "cpufreq"); + if (ret) { + cpufreq_cpu_put(managed_policy); +@@ -783,7 +783,7 @@ static int cpufreq_add_dev_symlink(unsigned int cpu, + + static int cpufreq_add_dev_interface(unsigned int cpu, + struct cpufreq_policy *policy, +- struct sys_device *sys_dev) ++ struct device *dev) + { + struct cpufreq_policy new_policy; + struct freq_attr **drv_attr; +@@ -793,7 +793,7 @@ static int cpufreq_add_dev_interface(unsigned int cpu, + + /* prepare interface data */ + ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, +- &sys_dev->kobj, "cpufreq"); ++ &dev->kobj, "cpufreq"); + if (ret) + return ret; + +@@ -866,9 +866,9 @@ err_out_kobj_put: + * with with cpu hotplugging and all hell will break loose. Tried to clean this + * mess up, but more thorough testing is needed. - Mathieu + */ +-static int cpufreq_add_dev(struct sys_device *sys_dev) ++static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) + { +- unsigned int cpu = sys_dev->id; ++ unsigned int cpu = dev->id; + int ret = 0, found = 0; + struct cpufreq_policy *policy; + unsigned long flags; +@@ -947,7 +947,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) + blocking_notifier_call_chain(&cpufreq_policy_notifier_list, + CPUFREQ_START, policy); + +- ret = cpufreq_add_dev_policy(cpu, policy, sys_dev); ++ ret = cpufreq_add_dev_policy(cpu, policy, dev); + if (ret) { + if (ret > 0) + /* This is a managed cpu, symlink created, +@@ -956,7 +956,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) + goto err_unlock_policy; + } + +- ret = cpufreq_add_dev_interface(cpu, policy, sys_dev); ++ ret = cpufreq_add_dev_interface(cpu, policy, dev); + if (ret) + goto err_out_unregister; + +@@ -999,15 +999,15 @@ module_out: + * Caller should already have policy_rwsem in write mode for this CPU. + * This routine frees the rwsem before returning. + */ +-static int __cpufreq_remove_dev(struct sys_device *sys_dev) ++static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) + { +- unsigned int cpu = sys_dev->id; ++ unsigned int cpu = dev->id; + unsigned long flags; + struct cpufreq_policy *data; + struct kobject *kobj; + struct completion *cmp; + #ifdef CONFIG_SMP +- struct sys_device *cpu_sys_dev; ++ struct device *cpu_dev; + unsigned int j; + #endif + +@@ -1032,7 +1032,7 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) + pr_debug("removing link\n"); + cpumask_clear_cpu(cpu, data->cpus); + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); +- kobj = &sys_dev->kobj; ++ kobj = &dev->kobj; + cpufreq_cpu_put(data); + unlock_policy_rwsem_write(cpu); + sysfs_remove_link(kobj, "cpufreq"); +@@ -1071,8 +1071,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) + strncpy(per_cpu(cpufreq_cpu_governor, j), + data->governor->name, CPUFREQ_NAME_LEN); + #endif +- cpu_sys_dev = get_cpu_sysdev(j); +- kobj = &cpu_sys_dev->kobj; ++ cpu_dev = get_cpu_device(j); ++ kobj = &cpu_dev->kobj; + unlock_policy_rwsem_write(cpu); + sysfs_remove_link(kobj, "cpufreq"); + lock_policy_rwsem_write(cpu); +@@ -1112,11 +1112,11 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) + if (unlikely(cpumask_weight(data->cpus) > 1)) { + /* first sibling now owns the new sysfs dir */ + cpumask_clear_cpu(cpu, data->cpus); +- cpufreq_add_dev(get_cpu_sysdev(cpumask_first(data->cpus))); ++ cpufreq_add_dev(get_cpu_device(cpumask_first(data->cpus)), NULL); + + /* finally remove our own symlink */ + lock_policy_rwsem_write(cpu); +- __cpufreq_remove_dev(sys_dev); ++ __cpufreq_remove_dev(dev, sif); + } + #endif + +@@ -1128,9 +1128,9 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) + } + + +-static int cpufreq_remove_dev(struct sys_device *sys_dev) ++static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) + { +- unsigned int cpu = sys_dev->id; ++ unsigned int cpu = dev->id; + int retval; + + if (cpu_is_offline(cpu)) +@@ -1139,7 +1139,7 @@ static int cpufreq_remove_dev(struct sys_device *sys_dev) + if (unlikely(lock_policy_rwsem_write(cpu))) + BUG(); + +- retval = __cpufreq_remove_dev(sys_dev); ++ retval = __cpufreq_remove_dev(dev, sif); + return retval; + } + +@@ -1271,9 +1271,11 @@ out: + } + EXPORT_SYMBOL(cpufreq_get); + +-static struct sysdev_driver cpufreq_sysdev_driver = { +- .add = cpufreq_add_dev, +- .remove = cpufreq_remove_dev, ++static struct subsys_interface cpufreq_interface = { ++ .name = "cpufreq", ++ .subsys = &cpu_subsys, ++ .add_dev = cpufreq_add_dev, ++ .remove_dev = cpufreq_remove_dev, + }; + + +@@ -1765,25 +1767,25 @@ static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) + { + unsigned int cpu = (unsigned long)hcpu; +- struct sys_device *sys_dev; ++ struct device *dev; + +- sys_dev = get_cpu_sysdev(cpu); +- if (sys_dev) { ++ dev = get_cpu_device(cpu); ++ if (dev) { + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: +- cpufreq_add_dev(sys_dev); ++ cpufreq_add_dev(dev, NULL); + break; + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + if (unlikely(lock_policy_rwsem_write(cpu))) + BUG(); + +- __cpufreq_remove_dev(sys_dev); ++ __cpufreq_remove_dev(dev, NULL); + break; + case CPU_DOWN_FAILED: + case CPU_DOWN_FAILED_FROZEN: +- cpufreq_add_dev(sys_dev); ++ cpufreq_add_dev(dev, NULL); + break; + } + } +@@ -1830,8 +1832,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) + cpufreq_driver = driver_data; + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + +- ret = sysdev_driver_register(&cpu_sysdev_class, +- &cpufreq_sysdev_driver); ++ ret = subsys_interface_register(&cpufreq_interface); + if (ret) + goto err_null_driver; + +@@ -1850,7 +1851,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) + if (ret) { + pr_debug("no CPU initialized for driver %s\n", + driver_data->name); +- goto err_sysdev_unreg; ++ goto err_if_unreg; + } + } + +@@ -1858,9 +1859,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) + pr_debug("driver %s up and running\n", driver_data->name); + + return 0; +-err_sysdev_unreg: +- sysdev_driver_unregister(&cpu_sysdev_class, +- &cpufreq_sysdev_driver); ++err_if_unreg: ++ subsys_interface_unregister(&cpufreq_interface); + err_null_driver: + spin_lock_irqsave(&cpufreq_driver_lock, flags); + cpufreq_driver = NULL; +@@ -1887,7 +1887,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) + + pr_debug("unregistering driver %s\n", driver->name); + +- sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver); ++ subsys_interface_unregister(&cpufreq_interface); + unregister_hotcpu_notifier(&cpufreq_cpu_notifier); + + spin_lock_irqsave(&cpufreq_driver_lock, flags); +@@ -1907,8 +1907,7 @@ static int __init cpufreq_core_init(void) + init_rwsem(&per_cpu(cpu_policy_rwsem, cpu)); + } + +- cpufreq_global_kobject = kobject_create_and_add("cpufreq", +- &cpu_sysdev_class.kset.kobj); ++ cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj); + BUG_ON(!cpufreq_global_kobject); + register_syscore_ops(&cpufreq_syscore_ops); + +diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c +index 4bf374d..18f2eb2 100644 +--- a/drivers/cpufreq/cpufreq_stats.c ++++ b/drivers/cpufreq/cpufreq_stats.c +@@ -11,7 +11,6 @@ + + #include + #include +-#include + #include + #include + #include +diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c +index c587db4..960671f 100644 +--- a/drivers/cpufreq/elanfreq.c ++++ b/drivers/cpufreq/elanfreq.c +@@ -23,6 +23,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -277,17 +278,16 @@ static struct cpufreq_driver elanfreq_driver = { + .attr = elanfreq_attr, + }; + ++static const struct x86_cpu_id elan_id[] = { ++ { X86_VENDOR_AMD, 4, 10, }, ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, elan_id); + + static int __init elanfreq_init(void) + { +- struct cpuinfo_x86 *c = &cpu_data(0); +- +- /* Test if we have the right hardware */ +- if ((c->x86_vendor != X86_VENDOR_AMD) || +- (c->x86 != 4) || (c->x86_model != 10)) { +- printk(KERN_INFO "elanfreq: error: no Elan processor found!\n"); ++ if (!x86_match_cpu(elan_id)) + return -ENODEV; +- } + return cpufreq_register_driver(&elanfreq_driver); + } + +diff --git a/drivers/cpufreq/gx-suspmod.c b/drivers/cpufreq/gx-suspmod.c +index ffe1f2c..456bee0 100644 +--- a/drivers/cpufreq/gx-suspmod.c ++++ b/drivers/cpufreq/gx-suspmod.c +@@ -82,6 +82,7 @@ + #include + #include + ++#include + #include + + /* PCI config registers, all at F0 */ +@@ -171,6 +172,7 @@ static struct pci_device_id gx_chipset_tbl[] __initdata = { + { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), }, + { 0, }, + }; ++MODULE_DEVICE_TABLE(pci, gx_chipset_tbl); + + static void gx_write_byte(int reg, int value) + { +@@ -185,13 +187,6 @@ static __init struct pci_dev *gx_detect_chipset(void) + { + struct pci_dev *gx_pci = NULL; + +- /* check if CPU is a MediaGX or a Geode. */ +- if ((boot_cpu_data.x86_vendor != X86_VENDOR_NSC) && +- (boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) { +- pr_debug("error: no MediaGX/Geode processor found!\n"); +- return NULL; +- } +- + /* detect which companion chip is used */ + for_each_pci_dev(gx_pci) { + if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL) +diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c +index f47d26e..0bf5bd1 100644 +--- a/drivers/cpufreq/longhaul.c ++++ b/drivers/cpufreq/longhaul.c +@@ -35,6 +35,7 @@ + #include + + #include ++#include + #include + + #include "longhaul.h" +@@ -76,7 +77,7 @@ static unsigned int longhaul_index; + static int scale_voltage; + static int disable_acpi_c3; + static int revid_errata; +- ++static int enable; + + /* Clock ratios multiplied by 10 */ + static int mults[32]; +@@ -951,14 +952,23 @@ static struct cpufreq_driver longhaul_driver = { + .attr = longhaul_attr, + }; + ++static const struct x86_cpu_id longhaul_id[] = { ++ { X86_VENDOR_CENTAUR, 6 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, longhaul_id); + + static int __init longhaul_init(void) + { + struct cpuinfo_x86 *c = &cpu_data(0); + +- if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6) ++ if (!x86_match_cpu(longhaul_id)) + return -ENODEV; + ++ if (!enable) { ++ printk(KERN_ERR PFX "Option \"enable\" not set. Aborting.\n"); ++ return -ENODEV; ++ } + #ifdef CONFIG_SMP + if (num_online_cpus() > 1) { + printk(KERN_ERR PFX "More than 1 CPU detected, " +@@ -1015,6 +1025,10 @@ MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); + * such. */ + module_param(revid_errata, int, 0644); + MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID"); ++/* By default driver is disabled to prevent incompatible ++ * system freeze. */ ++module_param(enable, int, 0644); ++MODULE_PARM_DESC(enable, "Enable driver"); + + MODULE_AUTHOR("Dave Jones "); + MODULE_DESCRIPTION("Longhaul driver for VIA Cyrix processors."); +diff --git a/drivers/cpufreq/longrun.c b/drivers/cpufreq/longrun.c +index 34ea359..8bc9f5f 100644 +--- a/drivers/cpufreq/longrun.c ++++ b/drivers/cpufreq/longrun.c +@@ -14,6 +14,7 @@ + + #include + #include ++#include + + static struct cpufreq_driver longrun_driver; + +@@ -288,6 +289,12 @@ static struct cpufreq_driver longrun_driver = { + .owner = THIS_MODULE, + }; + ++static const struct x86_cpu_id longrun_ids[] = { ++ { X86_VENDOR_TRANSMETA, X86_FAMILY_ANY, X86_MODEL_ANY, ++ X86_FEATURE_LONGRUN }, ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, longrun_ids); + + /** + * longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver +@@ -296,12 +303,8 @@ static struct cpufreq_driver longrun_driver = { + */ + static int __init longrun_init(void) + { +- struct cpuinfo_x86 *c = &cpu_data(0); +- +- if (c->x86_vendor != X86_VENDOR_TRANSMETA || +- !cpu_has(c, X86_FEATURE_LONGRUN)) ++ if (!x86_match_cpu(longrun_ids)) + return -ENODEV; +- + return cpufreq_register_driver(&longrun_driver); + } + +diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c +index 6be3e07..827629c9 100644 +--- a/drivers/cpufreq/p4-clockmod.c ++++ b/drivers/cpufreq/p4-clockmod.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #include "speedstep-lib.h" + +@@ -289,21 +290,25 @@ static struct cpufreq_driver p4clockmod_driver = { + .attr = p4clockmod_attr, + }; + ++static const struct x86_cpu_id cpufreq_p4_id[] = { ++ { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_ACC }, ++ {} ++}; ++ ++/* ++ * Intentionally no MODULE_DEVICE_TABLE here: this driver should not ++ * be auto loaded. Please don't add one. ++ */ + + static int __init cpufreq_p4_init(void) + { +- struct cpuinfo_x86 *c = &cpu_data(0); + int ret; + + /* + * THERM_CONTROL is architectural for IA32 now, so + * we can rely on the capability checks + */ +- if (c->x86_vendor != X86_VENDOR_INTEL) +- return -ENODEV; +- +- if (!test_cpu_cap(c, X86_FEATURE_ACPI) || +- !test_cpu_cap(c, X86_FEATURE_ACC)) ++ if (!x86_match_cpu(cpufreq_p4_id) || !boot_cpu_has(X86_FEATURE_ACPI)) + return -ENODEV; + + ret = cpufreq_register_driver(&p4clockmod_driver); +diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c +index 2c6b671..e7e87e6 100644 +--- a/drivers/cpufreq/powernow-k6.c ++++ b/drivers/cpufreq/powernow-k6.c +@@ -16,6 +16,7 @@ + #include + #include + ++#include + #include + + #define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long +@@ -303,6 +304,12 @@ static struct cpufreq_driver powernow_k6_driver = { + .attr = powernow_k6_attr, + }; + ++static const struct x86_cpu_id powernow_k6_ids[] = { ++ { X86_VENDOR_AMD, 5, 12 }, ++ { X86_VENDOR_AMD, 5, 13 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, powernow_k6_ids); + + /** + * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver +@@ -313,10 +320,7 @@ static struct cpufreq_driver powernow_k6_driver = { + */ + static int __init powernow_k6_init(void) + { +- struct cpuinfo_x86 *c = &cpu_data(0); +- +- if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) || +- ((c->x86_model != 12) && (c->x86_model != 13))) ++ if (!x86_match_cpu(powernow_k6_ids)) + return -ENODEV; + + if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) { +diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c +index d71d9f3..cf7e1ee 100644 +--- a/drivers/cpufreq/powernow-k7.c ++++ b/drivers/cpufreq/powernow-k7.c +@@ -28,6 +28,7 @@ + #include /* Needed for recalibrate_cpu_khz() */ + #include + #include ++#include + + #ifdef CONFIG_X86_POWERNOW_K7_ACPI + #include +@@ -110,18 +111,19 @@ static int check_fsb(unsigned int fsbspeed) + return delta < 5; + } + ++static const struct x86_cpu_id powernow_k7_cpuids[] = { ++ { X86_VENDOR_AMD, 6, }, ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, powernow_k7_cpuids); ++ + static int check_powernow(void) + { + struct cpuinfo_x86 *c = &cpu_data(0); + unsigned int maxei, eax, ebx, ecx, edx; + +- if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 6)) { +-#ifdef MODULE +- printk(KERN_INFO PFX "This module only works with " +- "AMD K7 CPUs\n"); +-#endif ++ if (!x86_match_cpu(powernow_k7_cpuids)) + return 0; +- } + + /* Get maximum capabilities */ + maxei = cpuid_eax(0x80000000); +diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c +index f6cd315..f1d0ba1 100644 +--- a/drivers/cpufreq/powernow-k8.c ++++ b/drivers/cpufreq/powernow-k8.c +@@ -36,6 +36,7 @@ + #include + + #include ++#include + + #include + #include +@@ -516,6 +517,15 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, + return 0; + } + ++static const struct x86_cpu_id powernow_k8_ids[] = { ++ /* IO based frequency switching */ ++ { X86_VENDOR_AMD, 0xf }, ++ /* MSR based frequency switching supported */ ++ X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE), ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, powernow_k8_ids); ++ + static void check_supported_cpu(void *_rc) + { + u32 eax, ebx, ecx, edx; +@@ -523,13 +533,7 @@ static void check_supported_cpu(void *_rc) + + *rc = -ENODEV; + +- if (__this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_AMD) +- return; +- + eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); +- if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) && +- ((eax & CPUID_XFAM) < CPUID_XFAM_10H)) +- return; + + if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) { + if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || +@@ -1548,6 +1552,9 @@ static int __cpuinit powernowk8_init(void) + unsigned int i, supported_cpus = 0, cpu; + int rv; + ++ if (!x86_match_cpu(powernow_k8_ids)) ++ return -ENODEV; ++ + for_each_online_cpu(i) { + int rc; + smp_call_function_single(i, check_supported_cpu, &rc, 1); +diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c +index 1e205e6..e42e073 100644 +--- a/drivers/cpufreq/sc520_freq.c ++++ b/drivers/cpufreq/sc520_freq.c +@@ -22,6 +22,7 @@ + #include + #include + ++#include + #include + + #define MMCR_BASE 0xfffef000 /* The default base address */ +@@ -150,18 +151,19 @@ static struct cpufreq_driver sc520_freq_driver = { + .attr = sc520_freq_attr, + }; + ++static const struct x86_cpu_id sc520_ids[] = { ++ { X86_VENDOR_AMD, 4, 9 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, sc520_ids); + + static int __init sc520_freq_init(void) + { +- struct cpuinfo_x86 *c = &cpu_data(0); + int err; + +- /* Test if we have the right hardware */ +- if (c->x86_vendor != X86_VENDOR_AMD || +- c->x86 != 4 || c->x86_model != 9) { +- pr_debug("no Elan SC520 processor found!\n"); ++ if (!x86_match_cpu(sc520_ids)) + return -ENODEV; +- } ++ + cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1); + if (!cpuctl) { + printk(KERN_ERR "sc520_freq: error: failed to remap memory\n"); +diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c +index 6ea3455..3a953d5 100644 +--- a/drivers/cpufreq/speedstep-centrino.c ++++ b/drivers/cpufreq/speedstep-centrino.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #define PFX "speedstep-centrino: " + #define MAINTAINER "cpufreq@vger.kernel.org" +@@ -595,6 +596,24 @@ static struct cpufreq_driver centrino_driver = { + .owner = THIS_MODULE, + }; + ++/* ++ * This doesn't replace the detailed checks above because ++ * the generic CPU IDs don't have a way to match for steppings ++ * or ASCII model IDs. ++ */ ++static const struct x86_cpu_id centrino_ids[] = { ++ { X86_VENDOR_INTEL, 6, 9, X86_FEATURE_EST }, ++ { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST }, ++ { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST }, ++ { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST }, ++ { X86_VENDOR_INTEL, 15, 3, X86_FEATURE_EST }, ++ { X86_VENDOR_INTEL, 15, 4, X86_FEATURE_EST }, ++ {} ++}; ++#if 0 ++/* Autoload or not? Do not for now. */ ++MODULE_DEVICE_TABLE(x86cpu, centrino_ids); ++#endif + + /** + * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver +@@ -612,11 +631,8 @@ static struct cpufreq_driver centrino_driver = { + */ + static int __init centrino_init(void) + { +- struct cpuinfo_x86 *cpu = &cpu_data(0); +- +- if (!cpu_has(cpu, X86_FEATURE_EST)) ++ if (!x86_match_cpu(centrino_ids)) + return -ENODEV; +- + return cpufreq_register_driver(¢rino_driver); + } + +diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c +index a748ce7..7432b3a 100644 +--- a/drivers/cpufreq/speedstep-ich.c ++++ b/drivers/cpufreq/speedstep-ich.c +@@ -25,6 +25,8 @@ + #include + #include + ++#include ++ + #include "speedstep-lib.h" + + +@@ -388,6 +390,16 @@ static struct cpufreq_driver speedstep_driver = { + .attr = speedstep_attr, + }; + ++static const struct x86_cpu_id ss_smi_ids[] = { ++ { X86_VENDOR_INTEL, 6, 0xb, }, ++ { X86_VENDOR_INTEL, 6, 0x8, }, ++ { X86_VENDOR_INTEL, 15, 2 }, ++ {} ++}; ++#if 0 ++/* Autoload or not? Do not for now. */ ++MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids); ++#endif + + /** + * speedstep_init - initializes the SpeedStep CPUFreq driver +@@ -398,6 +410,9 @@ static struct cpufreq_driver speedstep_driver = { + */ + static int __init speedstep_init(void) + { ++ if (!x86_match_cpu(ss_smi_ids)) ++ return -ENODEV; ++ + /* detect processor */ + speedstep_processor = speedstep_detect_processor(); + if (!speedstep_processor) { +diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c +index 2c0345a..4ab7a21 100644 +--- a/drivers/cpufreq/speedstep-lib.c ++++ b/drivers/cpufreq/speedstep-lib.c +@@ -249,6 +249,7 @@ EXPORT_SYMBOL_GPL(speedstep_get_frequency); + * DETECT SPEEDSTEP-CAPABLE PROCESSOR * + *********************************************************************/ + ++/* Keep in sync with the x86_cpu_id tables in the different modules */ + unsigned int speedstep_detect_processor(void) + { + struct cpuinfo_x86 *c = &cpu_data(0); +diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c +index 8a97f94..b01926d 100644 +--- a/drivers/cpufreq/speedstep-smi.c ++++ b/drivers/cpufreq/speedstep-smi.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + #include "speedstep-lib.h" + +@@ -391,6 +392,17 @@ static struct cpufreq_driver speedstep_driver = { + .attr = speedstep_attr, + }; + ++static const struct x86_cpu_id ss_smi_ids[] = { ++ { X86_VENDOR_INTEL, 6, 0xb, }, ++ { X86_VENDOR_INTEL, 6, 0x8, }, ++ { X86_VENDOR_INTEL, 15, 2 }, ++ {} ++}; ++#if 0 ++/* Not auto loaded currently */ ++MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids); ++#endif ++ + /** + * speedstep_init - initializes the SpeedStep CPUFreq driver + * +@@ -400,6 +412,9 @@ static struct cpufreq_driver speedstep_driver = { + */ + static int __init speedstep_init(void) + { ++ if (!x86_match_cpu(ss_smi_ids)) ++ return -ENODEV; ++ + speedstep_processor = speedstep_detect_processor(); + + switch (speedstep_processor) { +diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c +index 06ce268..59f4261 100644 +--- a/drivers/cpuidle/cpuidle.c ++++ b/drivers/cpuidle/cpuidle.c +@@ -291,10 +291,10 @@ EXPORT_SYMBOL_GPL(cpuidle_disable_device); + static int __cpuidle_register_device(struct cpuidle_device *dev) + { + int ret; +- struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); ++ struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu); + struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); + +- if (!sys_dev) ++ if (!dev) + return -EINVAL; + if (!try_module_get(cpuidle_driver->owner)) + return -EINVAL; +@@ -303,7 +303,7 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) + + per_cpu(cpuidle_devices, dev->cpu) = dev; + list_add(&dev->device_list, &cpuidle_detected_devices); +- if ((ret = cpuidle_add_sysfs(sys_dev))) { ++ if ((ret = cpuidle_add_sysfs(cpu_dev))) { + module_put(cpuidle_driver->owner); + return ret; + } +@@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device); + */ + void cpuidle_unregister_device(struct cpuidle_device *dev) + { +- struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); ++ struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu); + struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); + + if (dev->registered == 0) +@@ -354,7 +354,7 @@ void cpuidle_unregister_device(struct cpuidle_device *dev) + + cpuidle_disable_device(dev); + +- cpuidle_remove_sysfs(sys_dev); ++ cpuidle_remove_sysfs(cpu_dev); + list_del(&dev->device_list); + wait_for_completion(&dev->kobj_unregister); + per_cpu(cpuidle_devices, dev->cpu) = NULL; +@@ -411,7 +411,7 @@ static int __init cpuidle_init(void) + if (cpuidle_disabled()) + return -ENODEV; + +- ret = cpuidle_add_class_sysfs(&cpu_sysdev_class); ++ ret = cpuidle_add_interface(cpu_subsys.dev_root); + if (ret) + return ret; + +diff --git a/drivers/cpuidle/cpuidle.h b/drivers/cpuidle/cpuidle.h +index 38c3fd8..7db1866 100644 +--- a/drivers/cpuidle/cpuidle.h ++++ b/drivers/cpuidle/cpuidle.h +@@ -5,7 +5,7 @@ + #ifndef __DRIVER_CPUIDLE_H + #define __DRIVER_CPUIDLE_H + +-#include ++#include + + /* For internal use only */ + extern struct cpuidle_governor *cpuidle_curr_governor; +@@ -23,11 +23,11 @@ extern void cpuidle_uninstall_idle_handler(void); + extern int cpuidle_switch_governor(struct cpuidle_governor *gov); + + /* sysfs */ +-extern int cpuidle_add_class_sysfs(struct sysdev_class *cls); +-extern void cpuidle_remove_class_sysfs(struct sysdev_class *cls); ++extern int cpuidle_add_interface(struct device *dev); ++extern void cpuidle_remove_interface(struct device *dev); + extern int cpuidle_add_state_sysfs(struct cpuidle_device *device); + extern void cpuidle_remove_state_sysfs(struct cpuidle_device *device); +-extern int cpuidle_add_sysfs(struct sys_device *sysdev); +-extern void cpuidle_remove_sysfs(struct sys_device *sysdev); ++extern int cpuidle_add_sysfs(struct device *dev); ++extern void cpuidle_remove_sysfs(struct device *dev); + + #endif /* __DRIVER_CPUIDLE_H */ +diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c +index 1e756e1..3fe41fe 100644 +--- a/drivers/cpuidle/sysfs.c ++++ b/drivers/cpuidle/sysfs.c +@@ -22,8 +22,8 @@ static int __init cpuidle_sysfs_setup(char *unused) + } + __setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup); + +-static ssize_t show_available_governors(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t show_available_governors(struct device *dev, ++ struct device_attribute *attr, + char *buf) + { + ssize_t i = 0; +@@ -42,8 +42,8 @@ out: + return i; + } + +-static ssize_t show_current_driver(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t show_current_driver(struct device *dev, ++ struct device_attribute *attr, + char *buf) + { + ssize_t ret; +@@ -59,8 +59,8 @@ static ssize_t show_current_driver(struct sysdev_class *class, + return ret; + } + +-static ssize_t show_current_governor(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t show_current_governor(struct device *dev, ++ struct device_attribute *attr, + char *buf) + { + ssize_t ret; +@@ -75,8 +75,8 @@ static ssize_t show_current_governor(struct sysdev_class *class, + return ret; + } + +-static ssize_t store_current_governor(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t store_current_governor(struct device *dev, ++ struct device_attribute *attr, + const char *buf, size_t count) + { + char gov_name[CPUIDLE_NAME_LEN]; +@@ -109,50 +109,48 @@ static ssize_t store_current_governor(struct sysdev_class *class, + return count; + } + +-static SYSDEV_CLASS_ATTR(current_driver, 0444, show_current_driver, NULL); +-static SYSDEV_CLASS_ATTR(current_governor_ro, 0444, show_current_governor, +- NULL); ++static DEVICE_ATTR(current_driver, 0444, show_current_driver, NULL); ++static DEVICE_ATTR(current_governor_ro, 0444, show_current_governor, NULL); + +-static struct attribute *cpuclass_default_attrs[] = { +- &attr_current_driver.attr, +- &attr_current_governor_ro.attr, ++static struct attribute *cpuidle_default_attrs[] = { ++ &dev_attr_current_driver.attr, ++ &dev_attr_current_governor_ro.attr, + NULL + }; + +-static SYSDEV_CLASS_ATTR(available_governors, 0444, show_available_governors, +- NULL); +-static SYSDEV_CLASS_ATTR(current_governor, 0644, show_current_governor, +- store_current_governor); ++static DEVICE_ATTR(available_governors, 0444, show_available_governors, NULL); ++static DEVICE_ATTR(current_governor, 0644, show_current_governor, ++ store_current_governor); + +-static struct attribute *cpuclass_switch_attrs[] = { +- &attr_available_governors.attr, +- &attr_current_driver.attr, +- &attr_current_governor.attr, ++static struct attribute *cpuidle_switch_attrs[] = { ++ &dev_attr_available_governors.attr, ++ &dev_attr_current_driver.attr, ++ &dev_attr_current_governor.attr, + NULL + }; + +-static struct attribute_group cpuclass_attr_group = { +- .attrs = cpuclass_default_attrs, ++static struct attribute_group cpuidle_attr_group = { ++ .attrs = cpuidle_default_attrs, + .name = "cpuidle", + }; + + /** +- * cpuidle_add_class_sysfs - add CPU global sysfs attributes ++ * cpuidle_add_interface - add CPU global sysfs attributes + */ +-int cpuidle_add_class_sysfs(struct sysdev_class *cls) ++int cpuidle_add_interface(struct device *dev) + { + if (sysfs_switch) +- cpuclass_attr_group.attrs = cpuclass_switch_attrs; ++ cpuidle_attr_group.attrs = cpuidle_switch_attrs; + +- return sysfs_create_group(&cls->kset.kobj, &cpuclass_attr_group); ++ return sysfs_create_group(&dev->kobj, &cpuidle_attr_group); + } + + /** +- * cpuidle_remove_class_sysfs - remove CPU global sysfs attributes ++ * cpuidle_remove_interface - remove CPU global sysfs attributes + */ +-void cpuidle_remove_class_sysfs(struct sysdev_class *cls) ++void cpuidle_remove_interface(struct device *dev) + { +- sysfs_remove_group(&cls->kset.kobj, &cpuclass_attr_group); ++ sysfs_remove_group(&dev->kobj, &cpuidle_attr_group); + } + + struct cpuidle_attr { +@@ -365,16 +363,16 @@ void cpuidle_remove_state_sysfs(struct cpuidle_device *device) + + /** + * cpuidle_add_sysfs - creates a sysfs instance for the target device +- * @sysdev: the target device ++ * @dev: the target device + */ +-int cpuidle_add_sysfs(struct sys_device *sysdev) ++int cpuidle_add_sysfs(struct device *cpu_dev) + { +- int cpu = sysdev->id; ++ int cpu = cpu_dev->id; + struct cpuidle_device *dev; + int error; + + dev = per_cpu(cpuidle_devices, cpu); +- error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &sysdev->kobj, ++ error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj, + "cpuidle"); + if (!error) + kobject_uevent(&dev->kobj, KOBJ_ADD); +@@ -383,11 +381,11 @@ int cpuidle_add_sysfs(struct sys_device *sysdev) + + /** + * cpuidle_remove_sysfs - deletes a sysfs instance on the target device +- * @sysdev: the target device ++ * @dev: the target device + */ +-void cpuidle_remove_sysfs(struct sys_device *sysdev) ++void cpuidle_remove_sysfs(struct device *cpu_dev) + { +- int cpu = sysdev->id; ++ int cpu = cpu_dev->id; + struct cpuidle_device *dev; + + dev = per_cpu(cpuidle_devices, cpu); +diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c +index 87500e6..157d3ec 100644 +--- a/drivers/crypto/padlock-aes.c ++++ b/drivers/crypto/padlock-aes.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -503,12 +504,18 @@ static struct crypto_alg cbc_aes_alg = { + } + }; + ++static struct x86_cpu_id padlock_cpu_id[] = { ++ X86_FEATURE_MATCH(X86_FEATURE_XCRYPT), ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, padlock_cpu_id); ++ + static int __init padlock_init(void) + { + int ret; + struct cpuinfo_x86 *c = &cpu_data(0); + +- if (!cpu_has_xcrypt) ++ if (!x86_match_cpu(padlock_cpu_id)) + return -ENODEV; + + if (!cpu_has_xcrypt_enabled) { +diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c +index 710f3cb..93d7753 100644 +--- a/drivers/crypto/padlock-sha.c ++++ b/drivers/crypto/padlock-sha.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + + struct padlock_sha_desc { +@@ -526,6 +527,12 @@ static struct shash_alg sha256_alg_nano = { + } + }; + ++static struct x86_cpu_id padlock_sha_ids[] = { ++ X86_FEATURE_MATCH(X86_FEATURE_PHE), ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, padlock_sha_ids); ++ + static int __init padlock_init(void) + { + int rc = -ENODEV; +@@ -533,15 +540,8 @@ static int __init padlock_init(void) + struct shash_alg *sha1; + struct shash_alg *sha256; + +- if (!cpu_has_phe) { +- printk(KERN_NOTICE PFX "VIA PadLock Hash Engine not detected.\n"); +- return -ENODEV; +- } +- +- if (!cpu_has_phe_enabled) { +- printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n"); ++ if (!x86_match_cpu(padlock_sha_ids) || !cpu_has_phe_enabled) + return -ENODEV; +- } + + /* Register the newly added algorithm module if on * + * VIA Nano processor, or else just do as before */ +diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig +index a842317..19743e3 100644 +--- a/drivers/dma/Kconfig ++++ b/drivers/dma/Kconfig +@@ -262,6 +262,11 @@ config NET_DMA + Say Y here if you enabled INTEL_IOATDMA or FSL_DMA, otherwise + say N. + ++config NET_DMA_DUMMY ++ bool ++ depends on DMA_ENGINE && NET ++ default (INTEL_IOATDMA || FSL_DMA) ++ + config ASYNC_TX_DMA + bool "Async_tx: Offload support for the async_tx api" + depends on DMA_ENGINE +diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c +index f993955..7021ecb 100644 +--- a/drivers/dma/imx-sdma.c ++++ b/drivers/dma/imx-sdma.c +@@ -1152,10 +1152,8 @@ static void sdma_load_firmware(const struct firmware *fw, void *context) + const struct sdma_script_start_addrs *addr; + unsigned short *ram_code; + +- if (!fw) { +- dev_err(sdma->dev, "firmware not found\n"); ++ if (!fw) + return; +- } + + if (fw->size < sizeof(*header)) + goto err_firmware; +diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c +index 20f7daa..335c173 100644 +--- a/drivers/firmware/dmi_scan.c ++++ b/drivers/firmware/dmi_scan.c +@@ -553,6 +553,10 @@ static bool dmi_is_end_of_table(const struct dmi_system_id *dmi) + return dmi->matches[0].slot == DMI_NONE; + } + ++/* bwh: See comment in */ ++#undef dmi_check_system ++#undef dmi_first_match ++ + /** + * dmi_check_system - check system DMI data + * @list: array of dmi_system_id structures to match against +@@ -568,6 +572,12 @@ static bool dmi_is_end_of_table(const struct dmi_system_id *dmi) + */ + int dmi_check_system(const struct dmi_system_id *list) + { ++ return dmi_check_system_2(list); ++} ++EXPORT_SYMBOL(dmi_check_system); ++ ++int dmi_check_system_2(const struct dmi_system_id *list) ++{ + int count = 0; + const struct dmi_system_id *d; + +@@ -580,7 +590,7 @@ int dmi_check_system(const struct dmi_system_id *list) + + return count; + } +-EXPORT_SYMBOL(dmi_check_system); ++EXPORT_SYMBOL(dmi_check_system_2); + + /** + * dmi_first_match - find dmi_system_id structure matching system DMI data +@@ -596,6 +606,12 @@ EXPORT_SYMBOL(dmi_check_system); + */ + const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list) + { ++ return dmi_first_match_2(list); ++} ++EXPORT_SYMBOL(dmi_first_match); ++ ++const struct dmi_system_id *dmi_first_match_2(const struct dmi_system_id *list) ++{ + const struct dmi_system_id *d; + + for (d = list; !dmi_is_end_of_table(d); d++) +@@ -604,7 +620,7 @@ const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list) + + return NULL; + } +-EXPORT_SYMBOL(dmi_first_match); ++EXPORT_SYMBOL(dmi_first_match_2); + + /** + * dmi_get_system_info - return DMI data value +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 2a64e69..d2c65fe 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -89,6 +89,7 @@ MODULE_AUTHOR("Matt Domsch "); + MODULE_DESCRIPTION("sysfs interface to EFI Variables"); + MODULE_LICENSE("GPL"); + MODULE_VERSION(EFIVARS_VERSION); ++MODULE_ALIAS("platform:efivars"); + + #define DUMP_NAME_LEN 52 + +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index 4e04157..410e264 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -154,13 +154,13 @@ config GPIO_VR41XX + Say yes here to support the NEC VR4100 series General-purpose I/O Uint + + config GPIO_SCH +- tristate "Intel SCH/TunnelCreek GPIO" ++ tristate "Intel SCH/TunnelCreek/Centerton GPIO" + depends on PCI && X86 + select MFD_CORE + select LPC_SCH + help +- Say yes here to support GPIO interface on Intel Poulsbo SCH +- or Intel Tunnel Creek processor. ++ Say yes here to support GPIO interface on Intel Poulsbo SCH, ++ Intel Tunnel Creek processor or Intel Centerton processor. + The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are + powered by the core power rail and are turned off during sleep + modes (S3 and higher). The remaining four GPIOs are powered by +@@ -169,6 +169,9 @@ config GPIO_SCH + system from the Suspend-to-RAM state. + The Intel Tunnel Creek processor has 5 GPIOs powered by the + core power rail and 9 from suspend power supply. ++ The Intel Centerton processor has a total of 30 GPIO pins. ++ Twenty-one are powered by the core power rail and 9 from the ++ suspend power supply. + + config GPIO_U300 + bool "ST-Ericsson U300 COH 901 335/571 GPIO" +@@ -227,7 +230,7 @@ config GPIO_MAX732X_IRQ + controller. It requires the driver to be built in the kernel. + + config GPIO_PCA953X +- tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports" ++ tristate "PCA953x, PCA955x, PCA9698, TCA64xx, and MAX7310 I/O ports" + depends on I2C + help + Say yes here to provide access to several register-oriented +@@ -241,6 +244,8 @@ config GPIO_PCA953X + + 16 bits: pca9535, pca9539, pca9555, tca6416 + ++ 40 bits: pca9698 ++ + config GPIO_PCA953X_IRQ + bool "Interrupt controller support for PCA953x" + depends on GPIO_PCA953X=y +diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c +index 34be13b..60e259f 100644 +--- a/drivers/gpio/gpio-mpc8xxx.c ++++ b/drivers/gpio/gpio-mpc8xxx.c +@@ -296,7 +296,6 @@ static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq, + + irq_set_chip_data(virq, h->host_data); + irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq); +- irq_set_irq_type(virq, IRQ_TYPE_NONE); + + return 0; + } +diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c +index d3f3e8f..5a215fb 100644 +--- a/drivers/gpio/gpio-pca953x.c ++++ b/drivers/gpio/gpio-pca953x.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -28,6 +29,8 @@ + #define PCA953X_INVERT 2 + #define PCA953X_DIRECTION 3 + ++#define REG_ADDR_AI 0x80 ++ + #define PCA957X_IN 0 + #define PCA957X_INVRT 1 + #define PCA957X_BKEN 2 +@@ -43,6 +46,8 @@ + #define PCA957X_TYPE 0x2000 + + static const struct i2c_device_id pca953x_id[] = { ++ { "pca9505", 40 | PCA953X_TYPE | PCA_INT, }, ++ { "pca9506", 40 | PCA953X_TYPE | PCA_INT, }, + { "pca9534", 8 | PCA953X_TYPE | PCA_INT, }, + { "pca9535", 16 | PCA953X_TYPE | PCA_INT, }, + { "pca9536", 4 | PCA953X_TYPE, }, +@@ -55,6 +60,7 @@ static const struct i2c_device_id pca953x_id[] = { + { "pca9557", 8 | PCA953X_TYPE, }, + { "pca9574", 8 | PCA957X_TYPE | PCA_INT, }, + { "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, ++ { "pca9698", 40 | PCA953X_TYPE, }, + + { "max7310", 8 | PCA953X_TYPE, }, + { "max7312", 16 | PCA953X_TYPE | PCA_INT, }, +@@ -63,24 +69,29 @@ static const struct i2c_device_id pca953x_id[] = { + { "pca6107", 8 | PCA953X_TYPE | PCA_INT, }, + { "tca6408", 8 | PCA953X_TYPE | PCA_INT, }, + { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, +- /* NYET: { "tca6424", 24, }, */ ++ { "tca6424", 24 | PCA953X_TYPE | PCA_INT, }, + { } + }; + MODULE_DEVICE_TABLE(i2c, pca953x_id); + ++#define MAX_BANK 5 ++#define BANK_SZ 8 ++ ++#define NBANK(chip) (chip->gpio_chip.ngpio / BANK_SZ) ++ + struct pca953x_chip { + unsigned gpio_start; +- uint16_t reg_output; +- uint16_t reg_direction; ++ u8 reg_output[MAX_BANK]; ++ u8 reg_direction[MAX_BANK]; + struct mutex i2c_lock; + + #ifdef CONFIG_GPIO_PCA953X_IRQ + struct mutex irq_lock; +- uint16_t irq_mask; +- uint16_t irq_stat; +- uint16_t irq_trig_raise; +- uint16_t irq_trig_fall; +- int irq_base; ++ u8 irq_mask[MAX_BANK]; ++ u8 irq_stat[MAX_BANK]; ++ u8 irq_trig_raise[MAX_BANK]; ++ u8 irq_trig_fall[MAX_BANK]; ++ struct irq_domain *domain; + #endif + + struct i2c_client *client; +@@ -89,26 +100,68 @@ struct pca953x_chip { + int chip_type; + }; + +-static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) ++static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val, ++ int off) ++{ ++ int ret; ++ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); ++ int offset = off / BANK_SZ; ++ ++ ret = i2c_smbus_read_byte_data(chip->client, ++ (reg << bank_shift) + offset); ++ *val = ret; ++ ++ if (ret < 0) { ++ dev_err(&chip->client->dev, "failed reading register\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val, ++ int off) ++{ ++ int ret = 0; ++ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); ++ int offset = off / BANK_SZ; ++ ++ ret = i2c_smbus_write_byte_data(chip->client, ++ (reg << bank_shift) + offset, val); ++ ++ if (ret < 0) { ++ dev_err(&chip->client->dev, "failed writing register\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val) + { + int ret = 0; + + if (chip->gpio_chip.ngpio <= 8) +- ret = i2c_smbus_write_byte_data(chip->client, reg, val); +- else { ++ ret = i2c_smbus_write_byte_data(chip->client, reg, *val); ++ else if (chip->gpio_chip.ngpio >= 24) { ++ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); ++ ret = i2c_smbus_write_i2c_block_data(chip->client, ++ (reg << bank_shift) | REG_ADDR_AI, ++ NBANK(chip), val); ++ } else { + switch (chip->chip_type) { + case PCA953X_TYPE: + ret = i2c_smbus_write_word_data(chip->client, +- reg << 1, val); ++ reg << 1, (u16) *val); + break; + case PCA957X_TYPE: + ret = i2c_smbus_write_byte_data(chip->client, reg << 1, +- val & 0xff); ++ val[0]); + if (ret < 0) + break; + ret = i2c_smbus_write_byte_data(chip->client, + (reg << 1) + 1, +- (val & 0xff00) >> 8); ++ val[1]); + break; + } + } +@@ -121,34 +174,42 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) + return 0; + } + +-static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) ++static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val) + { + int ret; + +- if (chip->gpio_chip.ngpio <= 8) ++ if (chip->gpio_chip.ngpio <= 8) { + ret = i2c_smbus_read_byte_data(chip->client, reg); +- else +- ret = i2c_smbus_read_word_data(chip->client, reg << 1); ++ *val = ret; ++ } else if (chip->gpio_chip.ngpio >= 24) { ++ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + ++ ret = i2c_smbus_read_i2c_block_data(chip->client, ++ (reg << bank_shift) | REG_ADDR_AI, ++ NBANK(chip), val); ++ } else { ++ ret = i2c_smbus_read_word_data(chip->client, reg << 1); ++ val[0] = (u16)ret & 0xFF; ++ val[1] = (u16)ret >> 8; ++ } + if (ret < 0) { + dev_err(&chip->client->dev, "failed reading register\n"); + return ret; + } + +- *val = (uint16_t)ret; + return 0; + } + + static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) + { + struct pca953x_chip *chip; +- uint16_t reg_val; ++ u8 reg_val; + int ret, offset = 0; + + chip = container_of(gc, struct pca953x_chip, gpio_chip); + + mutex_lock(&chip->i2c_lock); +- reg_val = chip->reg_direction | (1u << off); ++ reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ)); + + switch (chip->chip_type) { + case PCA953X_TYPE: +@@ -158,11 +219,11 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) + offset = PCA957X_CFG; + break; + } +- ret = pca953x_write_reg(chip, offset, reg_val); ++ ret = pca953x_write_single(chip, offset, reg_val, off); + if (ret) + goto exit; + +- chip->reg_direction = reg_val; ++ chip->reg_direction[off / BANK_SZ] = reg_val; + ret = 0; + exit: + mutex_unlock(&chip->i2c_lock); +@@ -173,7 +234,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, + unsigned off, int val) + { + struct pca953x_chip *chip; +- uint16_t reg_val; ++ u8 reg_val; + int ret, offset = 0; + + chip = container_of(gc, struct pca953x_chip, gpio_chip); +@@ -181,9 +242,11 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, + mutex_lock(&chip->i2c_lock); + /* set output level */ + if (val) +- reg_val = chip->reg_output | (1u << off); ++ reg_val = chip->reg_output[off / BANK_SZ] ++ | (1u << (off % BANK_SZ)); + else +- reg_val = chip->reg_output & ~(1u << off); ++ reg_val = chip->reg_output[off / BANK_SZ] ++ & ~(1u << (off % BANK_SZ)); + + switch (chip->chip_type) { + case PCA953X_TYPE: +@@ -193,14 +256,14 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, + offset = PCA957X_OUT; + break; + } +- ret = pca953x_write_reg(chip, offset, reg_val); ++ ret = pca953x_write_single(chip, offset, reg_val, off); + if (ret) + goto exit; + +- chip->reg_output = reg_val; ++ chip->reg_output[off / BANK_SZ] = reg_val; + + /* then direction */ +- reg_val = chip->reg_direction & ~(1u << off); ++ reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); + switch (chip->chip_type) { + case PCA953X_TYPE: + offset = PCA953X_DIRECTION; +@@ -209,11 +272,11 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, + offset = PCA957X_CFG; + break; + } +- ret = pca953x_write_reg(chip, offset, reg_val); ++ ret = pca953x_write_single(chip, offset, reg_val, off); + if (ret) + goto exit; + +- chip->reg_direction = reg_val; ++ chip->reg_direction[off / BANK_SZ] = reg_val; + ret = 0; + exit: + mutex_unlock(&chip->i2c_lock); +@@ -223,7 +286,7 @@ exit: + static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) + { + struct pca953x_chip *chip; +- uint16_t reg_val; ++ u32 reg_val; + int ret, offset = 0; + + chip = container_of(gc, struct pca953x_chip, gpio_chip); +@@ -237,7 +300,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) + offset = PCA957X_IN; + break; + } +- ret = pca953x_read_reg(chip, offset, ®_val); ++ ret = pca953x_read_single(chip, offset, ®_val, off); + mutex_unlock(&chip->i2c_lock); + if (ret < 0) { + /* NOTE: diagnostic already emitted; that's all we should +@@ -247,22 +310,24 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) + return 0; + } + +- return (reg_val & (1u << off)) ? 1 : 0; ++ return (reg_val & (1u << (off % BANK_SZ))) ? 1 : 0; + } + + static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) + { + struct pca953x_chip *chip; +- uint16_t reg_val; ++ u8 reg_val; + int ret, offset = 0; + + chip = container_of(gc, struct pca953x_chip, gpio_chip); + + mutex_lock(&chip->i2c_lock); + if (val) +- reg_val = chip->reg_output | (1u << off); ++ reg_val = chip->reg_output[off / BANK_SZ] ++ | (1u << (off % BANK_SZ)); + else +- reg_val = chip->reg_output & ~(1u << off); ++ reg_val = chip->reg_output[off / BANK_SZ] ++ & ~(1u << (off % BANK_SZ)); + + switch (chip->chip_type) { + case PCA953X_TYPE: +@@ -272,11 +337,11 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) + offset = PCA957X_OUT; + break; + } +- ret = pca953x_write_reg(chip, offset, reg_val); ++ ret = pca953x_write_single(chip, offset, reg_val, off); + if (ret) + goto exit; + +- chip->reg_output = reg_val; ++ chip->reg_output[off / BANK_SZ] = reg_val; + exit: + mutex_unlock(&chip->i2c_lock); + } +@@ -307,21 +372,21 @@ static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off) + struct pca953x_chip *chip; + + chip = container_of(gc, struct pca953x_chip, gpio_chip); +- return chip->irq_base + off; ++ return irq_create_mapping(chip->domain, off); + } + + static void pca953x_irq_mask(struct irq_data *d) + { + struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); + +- chip->irq_mask &= ~(1 << (d->irq - chip->irq_base)); ++ chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ)); + } + + static void pca953x_irq_unmask(struct irq_data *d) + { + struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); + +- chip->irq_mask |= 1 << (d->irq - chip->irq_base); ++ chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ); + } + + static void pca953x_irq_bus_lock(struct irq_data *d) +@@ -334,17 +399,20 @@ static void pca953x_irq_bus_lock(struct irq_data *d) + static void pca953x_irq_bus_sync_unlock(struct irq_data *d) + { + struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); +- uint16_t new_irqs; +- uint16_t level; ++ u8 new_irqs; ++ int level, i; + + /* Look for any newly setup interrupt */ +- new_irqs = chip->irq_trig_fall | chip->irq_trig_raise; +- new_irqs &= ~chip->reg_direction; +- +- while (new_irqs) { +- level = __ffs(new_irqs); +- pca953x_gpio_direction_input(&chip->gpio_chip, level); +- new_irqs &= ~(1 << level); ++ for (i = 0; i < NBANK(chip); i++) { ++ new_irqs = chip->irq_trig_fall[i] | chip->irq_trig_raise[i]; ++ new_irqs &= ~chip->reg_direction[i]; ++ ++ while (new_irqs) { ++ level = __ffs(new_irqs); ++ pca953x_gpio_direction_input(&chip->gpio_chip, ++ level + (BANK_SZ * i)); ++ new_irqs &= ~(1 << level); ++ } + } + + mutex_unlock(&chip->irq_lock); +@@ -353,8 +421,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) + static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) + { + struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); +- uint16_t level = d->irq - chip->irq_base; +- uint16_t mask = 1 << level; ++ int bank_nb = d->hwirq / BANK_SZ; ++ u8 mask = 1 << (d->hwirq % BANK_SZ); + + if (!(type & IRQ_TYPE_EDGE_BOTH)) { + dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", +@@ -363,14 +431,14 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) + } + + if (type & IRQ_TYPE_EDGE_FALLING) +- chip->irq_trig_fall |= mask; ++ chip->irq_trig_fall[bank_nb] |= mask; + else +- chip->irq_trig_fall &= ~mask; ++ chip->irq_trig_fall[bank_nb] &= ~mask; + + if (type & IRQ_TYPE_EDGE_RISING) +- chip->irq_trig_raise |= mask; ++ chip->irq_trig_raise[bank_nb] |= mask; + else +- chip->irq_trig_raise &= ~mask; ++ chip->irq_trig_raise[bank_nb] &= ~mask; + + return 0; + } +@@ -384,13 +452,13 @@ static struct irq_chip pca953x_irq_chip = { + .irq_set_type = pca953x_irq_set_type, + }; + +-static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) ++static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) + { +- uint16_t cur_stat; +- uint16_t old_stat; +- uint16_t pending; +- uint16_t trigger; +- int ret, offset = 0; ++ u8 cur_stat[MAX_BANK]; ++ u8 old_stat[MAX_BANK]; ++ u8 pendings = 0; ++ u8 trigger[MAX_BANK], triggers = 0; ++ int ret, i, offset = 0; + + switch (chip->chip_type) { + case PCA953X_TYPE: +@@ -400,59 +468,88 @@ static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) + offset = PCA957X_IN; + break; + } +- ret = pca953x_read_reg(chip, offset, &cur_stat); ++ ret = pca953x_read_regs(chip, offset, cur_stat); + if (ret) + return 0; + + /* Remove output pins from the equation */ +- cur_stat &= chip->reg_direction; ++ for (i = 0; i < NBANK(chip); i++) ++ cur_stat[i] &= chip->reg_direction[i]; ++ ++ memcpy(old_stat, chip->irq_stat, NBANK(chip)); + +- old_stat = chip->irq_stat; +- trigger = (cur_stat ^ old_stat) & chip->irq_mask; ++ for (i = 0; i < NBANK(chip); i++) { ++ trigger[i] = (cur_stat[i] ^ old_stat[i]) & chip->irq_mask[i]; ++ triggers += trigger[i]; ++ } + +- if (!trigger) ++ if (!triggers) + return 0; + +- chip->irq_stat = cur_stat; ++ memcpy(chip->irq_stat, cur_stat, NBANK(chip)); + +- pending = (old_stat & chip->irq_trig_fall) | +- (cur_stat & chip->irq_trig_raise); +- pending &= trigger; ++ for (i = 0; i < NBANK(chip); i++) { ++ pending[i] = (old_stat[i] & chip->irq_trig_fall[i]) | ++ (cur_stat[i] & chip->irq_trig_raise[i]); ++ pending[i] &= trigger[i]; ++ pendings += pending[i]; ++ } + +- return pending; ++ return pendings; + } + + static irqreturn_t pca953x_irq_handler(int irq, void *devid) + { + struct pca953x_chip *chip = devid; +- uint16_t pending; +- uint16_t level; +- +- pending = pca953x_irq_pending(chip); ++ u8 pending[MAX_BANK]; ++ u8 level; ++ int i; + +- if (!pending) ++ if (!pca953x_irq_pending(chip, pending)) + return IRQ_HANDLED; + +- do { +- level = __ffs(pending); +- handle_nested_irq(level + chip->irq_base); +- +- pending &= ~(1 << level); +- } while (pending); ++ for (i = 0; i < NBANK(chip); i++) { ++ while (pending[i]) { ++ level = __ffs(pending[i]); ++ handle_nested_irq(irq_find_mapping(chip->domain, ++ level + (BANK_SZ * i))); ++ pending[i] &= ~(1 << level); ++ } ++ } + + return IRQ_HANDLED; + } + ++static int pca953x_gpio_irq_map(struct irq_domain *d, unsigned int irq, ++ irq_hw_number_t hwirq) ++{ ++ irq_clear_status_flags(irq, IRQ_NOREQUEST); ++ irq_set_chip_data(irq, d->host_data); ++ irq_set_chip(irq, &pca953x_irq_chip); ++ irq_set_nested_thread(irq, true); ++#ifdef CONFIG_ARM ++ set_irq_flags(irq, IRQF_VALID); ++#else ++ irq_set_noprobe(irq); ++#endif ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops pca953x_irq_simple_ops = { ++ .map = pca953x_gpio_irq_map, ++ .xlate = irq_domain_xlate_twocell, ++}; ++ + static int pca953x_irq_setup(struct pca953x_chip *chip, + const struct i2c_device_id *id, + int irq_base) + { + struct i2c_client *client = chip->client; +- int ret, offset = 0; ++ int ret, i, offset = 0; + + if (irq_base != -1 + && (id->driver_data & PCA_INT)) { +- int lvl; + + switch (chip->chip_type) { + case PCA953X_TYPE: +@@ -462,37 +559,29 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, + offset = PCA957X_IN; + break; + } +- ret = pca953x_read_reg(chip, offset, &chip->irq_stat); ++ ret = pca953x_read_regs(chip, offset, chip->irq_stat); + if (ret) +- goto out_failed; ++ return ret; + + /* + * There is no way to know which GPIO line generated the + * interrupt. We have to rely on the previous read for + * this purpose. + */ +- chip->irq_stat &= chip->reg_direction; ++ for (i = 0; i < NBANK(chip); i++) ++ chip->irq_stat[i] &= chip->reg_direction[i]; + mutex_init(&chip->irq_lock); + +- chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1); +- if (chip->irq_base < 0) +- goto out_failed; +- +- for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { +- int irq = lvl + chip->irq_base; ++ chip->domain = irq_domain_add_simple(client->dev.of_node, ++ chip->gpio_chip.ngpio, ++ irq_base, ++ &pca953x_irq_simple_ops, ++ chip); ++ if (!chip->domain) ++ return -ENODEV; + +- irq_clear_status_flags(irq, IRQ_NOREQUEST); +- irq_set_chip_data(irq, chip); +- irq_set_chip(irq, &pca953x_irq_chip); +- irq_set_nested_thread(irq, true); +-#ifdef CONFIG_ARM +- set_irq_flags(irq, IRQF_VALID); +-#else +- irq_set_noprobe(irq); +-#endif +- } +- +- ret = request_threaded_irq(client->irq, ++ ret = devm_request_threaded_irq(&client->dev, ++ client->irq, + NULL, + pca953x_irq_handler, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, +@@ -500,26 +589,15 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, + if (ret) { + dev_err(&client->dev, "failed to request irq %d\n", + client->irq); +- goto out_failed; ++ return ret; + } + + chip->gpio_chip.to_irq = pca953x_gpio_to_irq; + } + + return 0; +- +-out_failed: +- chip->irq_base = -1; +- return ret; + } + +-static void pca953x_irq_teardown(struct pca953x_chip *chip) +-{ +- if (chip->irq_base != -1) { +- irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio); +- free_irq(chip->client->irq, chip); +- } +-} + #else /* CONFIG_GPIO_PCA953X_IRQ */ + static int pca953x_irq_setup(struct pca953x_chip *chip, + const struct i2c_device_id *id, +@@ -532,10 +610,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, + + return 0; + } +- +-static void pca953x_irq_teardown(struct pca953x_chip *chip) +-{ +-} + #endif + + /* +@@ -547,7 +621,7 @@ static void pca953x_irq_teardown(struct pca953x_chip *chip) + * WARNING: This is DEPRECATED and will be removed eventually! + */ + static void +-pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) ++pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert) + { + struct device_node *node; + const __be32 *val; +@@ -575,75 +649,80 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) + } + #else + static void +-pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) ++pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert) + { + *gpio_base = -1; + } + #endif + +-static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert) ++static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) + { + int ret; ++ u8 val[MAX_BANK]; + +- ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); ++ ret = pca953x_read_regs(chip, PCA953X_OUTPUT, chip->reg_output); + if (ret) + goto out; + +- ret = pca953x_read_reg(chip, PCA953X_DIRECTION, +- &chip->reg_direction); ++ ret = pca953x_read_regs(chip, PCA953X_DIRECTION, ++ chip->reg_direction); + if (ret) + goto out; + + /* set platform specific polarity inversion */ +- ret = pca953x_write_reg(chip, PCA953X_INVERT, invert); ++ if (invert) ++ memset(val, 0xFF, NBANK(chip)); ++ else ++ memset(val, 0, NBANK(chip)); ++ ++ ret = pca953x_write_regs(chip, PCA953X_INVERT, val); + out: + return ret; + } + +-static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert) ++static int device_pca957x_init(struct pca953x_chip *chip, u32 invert) + { + int ret; +- uint16_t val = 0; +- +- /* Let every port in proper state, that could save power */ +- pca953x_write_reg(chip, PCA957X_PUPD, 0x0); +- pca953x_write_reg(chip, PCA957X_CFG, 0xffff); +- pca953x_write_reg(chip, PCA957X_OUT, 0x0); ++ u8 val[MAX_BANK]; + +- ret = pca953x_read_reg(chip, PCA957X_IN, &val); +- if (ret) +- goto out; +- ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output); ++ ret = pca953x_read_regs(chip, PCA957X_OUT, chip->reg_output); + if (ret) + goto out; +- ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction); ++ ret = pca953x_read_regs(chip, PCA957X_CFG, chip->reg_direction); + if (ret) + goto out; + + /* set platform specific polarity inversion */ +- pca953x_write_reg(chip, PCA957X_INVRT, invert); ++ if (invert) ++ memset(val, 0xFF, NBANK(chip)); ++ else ++ memset(val, 0, NBANK(chip)); ++ pca953x_write_regs(chip, PCA957X_INVRT, val); + + /* To enable register 6, 7 to controll pull up and pull down */ +- pca953x_write_reg(chip, PCA957X_BKEN, 0x202); ++ memset(val, 0x02, NBANK(chip)); ++ pca953x_write_regs(chip, PCA957X_BKEN, val); + + return 0; + out: + return ret; + } + +-static int __devinit pca953x_probe(struct i2c_client *client, ++static int pca953x_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { + struct pca953x_platform_data *pdata; + struct pca953x_chip *chip; +- int irq_base=0, invert=0; ++ int irq_base = 0; + int ret; ++ u32 invert = 0; + +- chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); ++ chip = devm_kzalloc(&client->dev, ++ sizeof(struct pca953x_chip), GFP_KERNEL); + if (chip == NULL) + return -ENOMEM; + +- pdata = client->dev.platform_data; ++ pdata = dev_get_platdata(&client->dev); + if (pdata) { + irq_base = pdata->irq_base; + chip->gpio_start = pdata->gpio_base; +@@ -674,15 +753,15 @@ static int __devinit pca953x_probe(struct i2c_client *client, + else + ret = device_pca957x_init(chip, invert); + if (ret) +- goto out_failed; ++ return ret; + + ret = pca953x_irq_setup(chip, id, irq_base); + if (ret) +- goto out_failed; ++ return ret; + + ret = gpiochip_add(&chip->gpio_chip); + if (ret) +- goto out_failed_irq; ++ return ret; + + if (pdata && pdata->setup) { + ret = pdata->setup(client, chip->gpio_chip.base, +@@ -693,17 +772,11 @@ static int __devinit pca953x_probe(struct i2c_client *client, + + i2c_set_clientdata(client, chip); + return 0; +- +-out_failed_irq: +- pca953x_irq_teardown(chip); +-out_failed: +- kfree(chip); +- return ret; + } + + static int pca953x_remove(struct i2c_client *client) + { +- struct pca953x_platform_data *pdata = client->dev.platform_data; ++ struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev); + struct pca953x_chip *chip = i2c_get_clientdata(client); + int ret = 0; + +@@ -724,14 +797,44 @@ static int pca953x_remove(struct i2c_client *client) + return ret; + } + +- pca953x_irq_teardown(chip); +- kfree(chip); + return 0; + } + ++static const struct of_device_id pca953x_dt_ids[] = { ++ { .compatible = "nxp,pca9505", }, ++ { .compatible = "nxp,pca9506", }, ++ { .compatible = "nxp,pca9534", }, ++ { .compatible = "nxp,pca9535", }, ++ { .compatible = "nxp,pca9536", }, ++ { .compatible = "nxp,pca9537", }, ++ { .compatible = "nxp,pca9538", }, ++ { .compatible = "nxp,pca9539", }, ++ { .compatible = "nxp,pca9554", }, ++ { .compatible = "nxp,pca9555", }, ++ { .compatible = "nxp,pca9556", }, ++ { .compatible = "nxp,pca9557", }, ++ { .compatible = "nxp,pca9574", }, ++ { .compatible = "nxp,pca9575", }, ++ { .compatible = "nxp,pca9698", }, ++ ++ { .compatible = "maxim,max7310", }, ++ { .compatible = "maxim,max7312", }, ++ { .compatible = "maxim,max7313", }, ++ { .compatible = "maxim,max7315", }, ++ ++ { .compatible = "ti,pca6107", }, ++ { .compatible = "ti,tca6408", }, ++ { .compatible = "ti,tca6416", }, ++ { .compatible = "ti,tca6424", }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(of, pca953x_dt_ids); ++ + static struct i2c_driver pca953x_driver = { + .driver = { + .name = "pca953x", ++ .of_match_table = pca953x_dt_ids, + }, + .probe = pca953x_probe, + .remove = pca953x_remove, +diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c +index 1635158..9610ae5 100644 +--- a/drivers/gpio/gpio-sch.c ++++ b/drivers/gpio/gpio-sch.c +@@ -125,13 +125,17 @@ static int sch_gpio_resume_direction_in(struct gpio_chip *gc, + unsigned gpio_num) + { + u8 curr_dirs; ++ unsigned short offset, bit; + + spin_lock(&gpio_lock); + +- curr_dirs = inb(gpio_ba + RGIO); ++ offset = RGIO + gpio_num / 8; ++ bit = gpio_num % 8; ++ ++ curr_dirs = inb(gpio_ba + offset); + +- if (!(curr_dirs & (1 << gpio_num))) +- outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO); ++ if (!(curr_dirs & (1 << bit))) ++ outb(curr_dirs | (1 << bit), gpio_ba + offset); + + spin_unlock(&gpio_lock); + return 0; +@@ -139,22 +143,31 @@ static int sch_gpio_resume_direction_in(struct gpio_chip *gc, + + static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num) + { +- return !!(inb(gpio_ba + RGLV) & (1 << gpio_num)); ++ unsigned short offset, bit; ++ ++ offset = RGLV + gpio_num / 8; ++ bit = gpio_num % 8; ++ ++ return !!(inb(gpio_ba + offset) & (1 << bit)); + } + + static void sch_gpio_resume_set(struct gpio_chip *gc, + unsigned gpio_num, int val) + { + u8 curr_vals; ++ unsigned short offset, bit; + + spin_lock(&gpio_lock); + +- curr_vals = inb(gpio_ba + RGLV); ++ offset = RGLV + gpio_num / 8; ++ bit = gpio_num % 8; ++ ++ curr_vals = inb(gpio_ba + offset); + + if (val) +- outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV); ++ outb(curr_vals | (1 << bit), gpio_ba + offset); + else +- outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV); ++ outb((curr_vals & ~(1 << bit)), gpio_ba + offset); + + spin_unlock(&gpio_lock); + } +@@ -163,14 +176,18 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc, + unsigned gpio_num, int val) + { + u8 curr_dirs; ++ unsigned short offset, bit; + + sch_gpio_resume_set(gc, gpio_num, val); + ++ offset = RGIO + gpio_num / 8; ++ bit = gpio_num % 8; ++ + spin_lock(&gpio_lock); + +- curr_dirs = inb(gpio_ba + RGIO); +- if (curr_dirs & (1 << gpio_num)) +- outb(curr_dirs & ~(1 << gpio_num), gpio_ba + RGIO); ++ curr_dirs = inb(gpio_ba + offset); ++ if (curr_dirs & (1 << bit)) ++ outb(curr_dirs & ~(1 << bit), gpio_ba + offset); + + spin_unlock(&gpio_lock); + return 0; +@@ -185,7 +202,7 @@ static struct gpio_chip sch_gpio_resume = { + .set = sch_gpio_resume_set, + }; + +-static int __devinit sch_gpio_probe(struct platform_device *pdev) ++static int sch_gpio_probe(struct platform_device *pdev) + { + struct resource *res; + int err, id; +@@ -204,36 +221,41 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev) + gpio_ba = res->start; + + switch (id) { +- case PCI_DEVICE_ID_INTEL_SCH_LPC: +- sch_gpio_core.base = 0; +- sch_gpio_core.ngpio = 10; +- +- sch_gpio_resume.base = 10; +- sch_gpio_resume.ngpio = 4; +- +- /* +- * GPIO[6:0] enabled by default +- * GPIO7 is configured by the CMC as SLPIOVR +- * Enable GPIO[9:8] core powered gpios explicitly +- */ +- outb(0x3, gpio_ba + CGEN + 1); +- /* +- * SUS_GPIO[2:0] enabled by default +- * Enable SUS_GPIO3 resume powered gpio explicitly +- */ +- outb(0x8, gpio_ba + RGEN); +- break; +- +- case PCI_DEVICE_ID_INTEL_ITC_LPC: +- sch_gpio_core.base = 0; +- sch_gpio_core.ngpio = 5; +- +- sch_gpio_resume.base = 5; +- sch_gpio_resume.ngpio = 9; +- break; +- +- default: +- return -ENODEV; ++ case PCI_DEVICE_ID_INTEL_SCH_LPC: ++ sch_gpio_core.base = 0; ++ sch_gpio_core.ngpio = 10; ++ sch_gpio_resume.base = 10; ++ sch_gpio_resume.ngpio = 4; ++ /* ++ * GPIO[6:0] enabled by default ++ * GPIO7 is configured by the CMC as SLPIOVR ++ * Enable GPIO[9:8] core powered gpios explicitly ++ */ ++ outb(0x3, gpio_ba + CGEN + 1); ++ /* ++ * SUS_GPIO[2:0] enabled by default ++ * Enable SUS_GPIO3 resume powered gpio explicitly ++ */ ++ outb(0x8, gpio_ba + RGEN); ++ break; ++ ++ case PCI_DEVICE_ID_INTEL_ITC_LPC: ++ sch_gpio_core.base = 0; ++ sch_gpio_core.ngpio = 5; ++ sch_gpio_resume.base = 5; ++ sch_gpio_resume.ngpio = 9; ++ break; ++ ++ case PCI_DEVICE_ID_INTEL_CENTERTON_ILB: ++ sch_gpio_core.base = 0; ++ sch_gpio_core.ngpio = 21; ++ sch_gpio_resume.base = 21; ++ sch_gpio_resume.ngpio = 9; ++ break; ++ ++ default: ++ err = -ENODEV; ++ goto err_sch_gpio_core; + } + + sch_gpio_core.dev = &pdev->dev; +@@ -250,10 +272,8 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev) + return 0; + + err_sch_gpio_resume: +- err = gpiochip_remove(&sch_gpio_core); +- if (err) +- dev_err(&pdev->dev, "%s failed, %d\n", +- "gpiochip_remove()", err); ++ if (gpiochip_remove(&sch_gpio_core)) ++ dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__); + + err_sch_gpio_core: + release_region(res->start, resource_size(res)); +@@ -262,7 +282,7 @@ err_sch_gpio_core: + return err; + } + +-static int __devexit sch_gpio_remove(struct platform_device *pdev) ++static int sch_gpio_remove(struct platform_device *pdev) + { + struct resource *res; + if (gpio_ba) { +@@ -294,7 +314,7 @@ static struct platform_driver sch_gpio_driver = { + .owner = THIS_MODULE, + }, + .probe = sch_gpio_probe, +- .remove = __devexit_p(sch_gpio_remove), ++ .remove = sch_gpio_remove, + }; + + static int __init sch_gpio_init(void) +diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig +index 1368826..cc11488 100644 +--- a/drivers/gpu/drm/Kconfig ++++ b/drivers/gpu/drm/Kconfig +@@ -18,6 +18,11 @@ menuconfig DRM + details. You should also select and configure AGP + (/dev/agpgart) support if it is available for your platform. + ++config DRM_USB ++ tristate ++ depends on DRM ++ select USB ++ + config DRM_KMS_HELPER + tristate + depends on DRM +@@ -27,6 +32,18 @@ config DRM_KMS_HELPER + help + FB and CRTC helpers for KMS drivers. + ++config DRM_LOAD_EDID_FIRMWARE ++ bool "Allow to specify an EDID data set instead of probing for it" ++ depends on DRM_KMS_HELPER ++ help ++ Say Y here, if you want to use EDID data to be loaded from the ++ /lib/firmware directory or one of the provided built-in ++ data sets. This may be necessary, if the graphics adapter or ++ monitor are unable to provide appropriate EDID data. Since this ++ feature is provided as a workaround for broken hardware, the ++ default case is N. Details and instructions how to build your own ++ EDID data are given in Documentation/EDID/HOWTO.txt. ++ + config DRM_TTM + tristate + depends on DRM +@@ -71,6 +88,8 @@ config DRM_RADEON + + source "drivers/gpu/drm/radeon/Kconfig" + ++source "drivers/gpu/drm/nouveau/Kconfig" ++ + config DRM_I810 + tristate "Intel I810" + # !PREEMPT because of missing ioctl locking +@@ -162,3 +181,7 @@ config DRM_SAVAGE + source "drivers/gpu/drm/exynos/Kconfig" + + source "drivers/gpu/drm/vmwgfx/Kconfig" ++ ++source "drivers/gpu/drm/gma500/Kconfig" ++ ++source "drivers/gpu/drm/udl/Kconfig" +diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile +index c0496f6..a858532 100644 +--- a/drivers/gpu/drm/Makefile ++++ b/drivers/gpu/drm/Makefile +@@ -9,20 +9,24 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ + drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ + drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ + drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ +- drm_platform.o drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ ++ drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ + drm_crtc.o drm_modes.o drm_edid.o \ + drm_info.o drm_debugfs.o drm_encoder_slave.o \ +- drm_trace_points.o drm_global.o drm_usb.o ++ drm_trace_points.o drm_global.o + + drm-$(CONFIG_COMPAT) += drm_ioc32.o + ++drm-usb-y := drm_usb.o ++ + drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o ++drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o + + obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o + + CFLAGS_drm_trace_points.o := -I$(src) + + obj-$(CONFIG_DRM) += drm.o ++obj-$(CONFIG_DRM_USB) += drm_usb.o + obj-$(CONFIG_DRM_TTM) += ttm/ + obj-$(CONFIG_DRM_TDFX) += tdfx/ + obj-$(CONFIG_DRM_R128) += r128/ +@@ -36,4 +40,6 @@ obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/ + obj-$(CONFIG_DRM_VIA) +=via/ + obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/ + obj-$(CONFIG_DRM_EXYNOS) +=exynos/ ++obj-$(CONFIG_DRM_GMA500) += gma500/ ++obj-$(CONFIG_DRM_UDL) += udl/ + obj-y += i2c/ +diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c +index 5928653..4b8653b 100644 +--- a/drivers/gpu/drm/drm_cache.c ++++ b/drivers/gpu/drm/drm_cache.c +@@ -41,10 +41,10 @@ drm_clflush_page(struct page *page) + if (unlikely(page == NULL)) + return; + +- page_virtual = kmap_atomic(page, KM_USER0); ++ page_virtual = kmap_atomic(page); + for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) + clflush(page_virtual + i); +- kunmap_atomic(page_virtual, KM_USER0); ++ kunmap_atomic(page_virtual); + } + + static void drm_cache_flush_clflush(struct page *pages[], +@@ -87,10 +87,10 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages) + if (unlikely(page == NULL)) + continue; + +- page_virtual = kmap_atomic(page, KM_USER0); ++ page_virtual = kmap_atomic(page); + flush_dcache_range((unsigned long)page_virtual, + (unsigned long)page_virtual + PAGE_SIZE); +- kunmap_atomic(page_virtual, KM_USER0); ++ kunmap_atomic(page_virtual); + } + #else + printk(KERN_ERR "Architecture has no drm_cache.c support\n"); +diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c +index 6d440fb..325365f 100644 +--- a/drivers/gpu/drm/drm_context.c ++++ b/drivers/gpu/drm/drm_context.c +@@ -154,8 +154,6 @@ int drm_getsareactx(struct drm_device *dev, void *data, + return -EINVAL; + } + +- mutex_unlock(&dev->struct_mutex); +- + request->handle = NULL; + list_for_each_entry(_entry, &dev->maplist, head) { + if (_entry->map == map) { +@@ -164,6 +162,9 @@ int drm_getsareactx(struct drm_device *dev, void *data, + break; + } + } ++ ++ mutex_unlock(&dev->struct_mutex); ++ + if (request->handle == NULL) + return -EINVAL; + +diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c +index 20110b4..5dfd8cc 100644 +--- a/drivers/gpu/drm/drm_crtc.c ++++ b/drivers/gpu/drm/drm_crtc.c +@@ -36,11 +36,7 @@ + #include "drmP.h" + #include "drm_crtc.h" + #include "drm_edid.h" +- +-struct drm_prop_enum_list { +- int type; +- char *name; +-}; ++#include "drm_fourcc.h" + + /* Avoid boilerplate. I'm tired of typing. */ + #define DRM_ENUM_NAME_FN(fnname, list) \ +@@ -297,9 +293,8 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, + int ret; + + ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); +- if (ret) { ++ if (ret) + return ret; +- } + + fb->dev = dev; + fb->funcs = funcs; +@@ -324,6 +319,7 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb) + { + struct drm_device *dev = fb->dev; + struct drm_crtc *crtc; ++ struct drm_plane *plane; + struct drm_mode_set set; + int ret; + +@@ -340,6 +336,18 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb) + } + } + ++ list_for_each_entry(plane, &dev->mode_config.plane_list, head) { ++ if (plane->fb == fb) { ++ /* should turn off the crtc */ ++ ret = plane->funcs->disable_plane(plane); ++ if (ret) ++ DRM_ERROR("failed to disable plane with busy fb\n"); ++ /* disconnect the plane from the fb and crtc: */ ++ plane->fb = NULL; ++ plane->crtc = NULL; ++ } ++ } ++ + drm_mode_object_put(dev, &fb->base); + list_del(&fb->head); + dev->mode_config.num_fb--; +@@ -356,19 +364,31 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup); + * Caller must hold mode config lock. + * + * Inits a new object created as base part of an driver crtc object. ++ * ++ * RETURNS: ++ * Zero on success, error code on failure. + */ +-void drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, ++int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, + const struct drm_crtc_funcs *funcs) + { ++ int ret; ++ + crtc->dev = dev; + crtc->funcs = funcs; + + mutex_lock(&dev->mode_config.mutex); +- drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); ++ ++ ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); ++ if (ret) ++ goto out; + + list_add_tail(&crtc->head, &dev->mode_config.crtc_list); + dev->mode_config.num_crtc++; ++ ++ out: + mutex_unlock(&dev->mode_config.mutex); ++ ++ return ret; + } + EXPORT_SYMBOL(drm_crtc_init); + +@@ -428,7 +448,7 @@ void drm_mode_remove(struct drm_connector *connector, + struct drm_display_mode *mode) + { + list_del(&mode->head); +- kfree(mode); ++ drm_mode_destroy(connector->dev, mode); + } + EXPORT_SYMBOL(drm_mode_remove); + +@@ -440,21 +460,29 @@ EXPORT_SYMBOL(drm_mode_remove); + * @name: user visible name of the connector + * + * LOCKING: +- * Caller must hold @dev's mode_config lock. ++ * Takes mode config lock. + * + * Initialises a preallocated connector. Connectors should be + * subclassed as part of driver connector objects. ++ * ++ * RETURNS: ++ * Zero on success, error code on failure. + */ +-void drm_connector_init(struct drm_device *dev, +- struct drm_connector *connector, +- const struct drm_connector_funcs *funcs, +- int connector_type) ++int drm_connector_init(struct drm_device *dev, ++ struct drm_connector *connector, ++ const struct drm_connector_funcs *funcs, ++ int connector_type) + { ++ int ret; ++ + mutex_lock(&dev->mode_config.mutex); + ++ ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); ++ if (ret) ++ goto out; ++ + connector->dev = dev; + connector->funcs = funcs; +- drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); + connector->connector_type = connector_type; + connector->connector_type_id = + ++drm_connector_enum_list[connector_type].count; /* TODO */ +@@ -474,7 +502,10 @@ void drm_connector_init(struct drm_device *dev, + drm_connector_attach_property(connector, + dev->mode_config.dpms_property, 0); + ++ out: + mutex_unlock(&dev->mode_config.mutex); ++ ++ return ret; + } + EXPORT_SYMBOL(drm_connector_init); + +@@ -483,7 +514,7 @@ EXPORT_SYMBOL(drm_connector_init); + * @connector: connector to cleanup + * + * LOCKING: +- * Caller must hold @dev's mode_config lock. ++ * Takes mode config lock. + * + * Cleans up the connector but doesn't free the object. + */ +@@ -509,23 +540,41 @@ void drm_connector_cleanup(struct drm_connector *connector) + } + EXPORT_SYMBOL(drm_connector_cleanup); + +-void drm_encoder_init(struct drm_device *dev, ++void drm_connector_unplug_all(struct drm_device *dev) ++{ ++ struct drm_connector *connector; ++ ++ /* taking the mode config mutex ends up in a clash with sysfs */ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) ++ drm_sysfs_connector_remove(connector); ++ ++} ++EXPORT_SYMBOL(drm_connector_unplug_all); ++ ++int drm_encoder_init(struct drm_device *dev, + struct drm_encoder *encoder, + const struct drm_encoder_funcs *funcs, + int encoder_type) + { ++ int ret; ++ + mutex_lock(&dev->mode_config.mutex); + +- encoder->dev = dev; ++ ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); ++ if (ret) ++ goto out; + +- drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); ++ encoder->dev = dev; + encoder->encoder_type = encoder_type; + encoder->funcs = funcs; + + list_add_tail(&encoder->head, &dev->mode_config.encoder_list); + dev->mode_config.num_encoder++; + ++ out: + mutex_unlock(&dev->mode_config.mutex); ++ ++ return ret; + } + EXPORT_SYMBOL(drm_encoder_init); + +@@ -540,6 +589,69 @@ void drm_encoder_cleanup(struct drm_encoder *encoder) + } + EXPORT_SYMBOL(drm_encoder_cleanup); + ++int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, ++ unsigned long possible_crtcs, ++ const struct drm_plane_funcs *funcs, ++ const uint32_t *formats, uint32_t format_count, ++ bool priv) ++{ ++ int ret; ++ ++ mutex_lock(&dev->mode_config.mutex); ++ ++ ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); ++ if (ret) ++ goto out; ++ ++ plane->dev = dev; ++ plane->funcs = funcs; ++ plane->format_types = kmalloc(sizeof(uint32_t) * format_count, ++ GFP_KERNEL); ++ if (!plane->format_types) { ++ DRM_DEBUG_KMS("out of memory when allocating plane\n"); ++ drm_mode_object_put(dev, &plane->base); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); ++ plane->format_count = format_count; ++ plane->possible_crtcs = possible_crtcs; ++ ++ /* private planes are not exposed to userspace, but depending on ++ * display hardware, might be convenient to allow sharing programming ++ * for the scanout engine with the crtc implementation. ++ */ ++ if (!priv) { ++ list_add_tail(&plane->head, &dev->mode_config.plane_list); ++ dev->mode_config.num_plane++; ++ } else { ++ INIT_LIST_HEAD(&plane->head); ++ } ++ ++ out: ++ mutex_unlock(&dev->mode_config.mutex); ++ ++ return ret; ++} ++EXPORT_SYMBOL(drm_plane_init); ++ ++void drm_plane_cleanup(struct drm_plane *plane) ++{ ++ struct drm_device *dev = plane->dev; ++ ++ mutex_lock(&dev->mode_config.mutex); ++ kfree(plane->format_types); ++ drm_mode_object_put(dev, &plane->base); ++ /* if not added to a list, it must be a private plane */ ++ if (!list_empty(&plane->head)) { ++ list_del(&plane->head); ++ dev->mode_config.num_plane--; ++ } ++ mutex_unlock(&dev->mode_config.mutex); ++} ++EXPORT_SYMBOL(drm_plane_cleanup); ++ + /** + * drm_mode_create - create a new display mode + * @dev: DRM device +@@ -560,7 +672,11 @@ struct drm_display_mode *drm_mode_create(struct drm_device *dev) + if (!nmode) + return NULL; + +- drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE); ++ if (drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) { ++ kfree(nmode); ++ return NULL; ++ } ++ + return nmode; + } + EXPORT_SYMBOL(drm_mode_create); +@@ -577,6 +693,9 @@ EXPORT_SYMBOL(drm_mode_create); + */ + void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) + { ++ if (!mode) ++ return; ++ + drm_mode_object_put(dev, &mode->base); + + kfree(mode); +@@ -587,7 +706,6 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) + { + struct drm_property *edid; + struct drm_property *dpms; +- int i; + + /* + * Standard properties (apply to all connectors) +@@ -597,11 +715,9 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) + "EDID", 0); + dev->mode_config.edid_property = edid; + +- dpms = drm_property_create(dev, DRM_MODE_PROP_ENUM, +- "DPMS", ARRAY_SIZE(drm_dpms_enum_list)); +- for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++) +- drm_property_add_enum(dpms, i, drm_dpms_enum_list[i].type, +- drm_dpms_enum_list[i].name); ++ dpms = drm_property_create_enum(dev, 0, ++ "DPMS", drm_dpms_enum_list, ++ ARRAY_SIZE(drm_dpms_enum_list)); + dev->mode_config.dpms_property = dpms; + + return 0; +@@ -617,30 +733,21 @@ int drm_mode_create_dvi_i_properties(struct drm_device *dev) + { + struct drm_property *dvi_i_selector; + struct drm_property *dvi_i_subconnector; +- int i; + + if (dev->mode_config.dvi_i_select_subconnector_property) + return 0; + + dvi_i_selector = +- drm_property_create(dev, DRM_MODE_PROP_ENUM, ++ drm_property_create_enum(dev, 0, + "select subconnector", ++ drm_dvi_i_select_enum_list, + ARRAY_SIZE(drm_dvi_i_select_enum_list)); +- for (i = 0; i < ARRAY_SIZE(drm_dvi_i_select_enum_list); i++) +- drm_property_add_enum(dvi_i_selector, i, +- drm_dvi_i_select_enum_list[i].type, +- drm_dvi_i_select_enum_list[i].name); + dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector; + +- dvi_i_subconnector = +- drm_property_create(dev, DRM_MODE_PROP_ENUM | +- DRM_MODE_PROP_IMMUTABLE, ++ dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, + "subconnector", ++ drm_dvi_i_subconnector_enum_list, + ARRAY_SIZE(drm_dvi_i_subconnector_enum_list)); +- for (i = 0; i < ARRAY_SIZE(drm_dvi_i_subconnector_enum_list); i++) +- drm_property_add_enum(dvi_i_subconnector, i, +- drm_dvi_i_subconnector_enum_list[i].type, +- drm_dvi_i_subconnector_enum_list[i].name); + dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector; + + return 0; +@@ -671,51 +778,33 @@ int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, + /* + * Basic connector properties + */ +- tv_selector = drm_property_create(dev, DRM_MODE_PROP_ENUM, ++ tv_selector = drm_property_create_enum(dev, 0, + "select subconnector", ++ drm_tv_select_enum_list, + ARRAY_SIZE(drm_tv_select_enum_list)); +- for (i = 0; i < ARRAY_SIZE(drm_tv_select_enum_list); i++) +- drm_property_add_enum(tv_selector, i, +- drm_tv_select_enum_list[i].type, +- drm_tv_select_enum_list[i].name); + dev->mode_config.tv_select_subconnector_property = tv_selector; + + tv_subconnector = +- drm_property_create(dev, DRM_MODE_PROP_ENUM | +- DRM_MODE_PROP_IMMUTABLE, "subconnector", ++ drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, ++ "subconnector", ++ drm_tv_subconnector_enum_list, + ARRAY_SIZE(drm_tv_subconnector_enum_list)); +- for (i = 0; i < ARRAY_SIZE(drm_tv_subconnector_enum_list); i++) +- drm_property_add_enum(tv_subconnector, i, +- drm_tv_subconnector_enum_list[i].type, +- drm_tv_subconnector_enum_list[i].name); + dev->mode_config.tv_subconnector_property = tv_subconnector; + + /* + * Other, TV specific properties: margins & TV modes. + */ + dev->mode_config.tv_left_margin_property = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "left margin", 2); +- dev->mode_config.tv_left_margin_property->values[0] = 0; +- dev->mode_config.tv_left_margin_property->values[1] = 100; ++ drm_property_create_range(dev, 0, "left margin", 0, 100); + + dev->mode_config.tv_right_margin_property = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "right margin", 2); +- dev->mode_config.tv_right_margin_property->values[0] = 0; +- dev->mode_config.tv_right_margin_property->values[1] = 100; ++ drm_property_create_range(dev, 0, "right margin", 0, 100); + + dev->mode_config.tv_top_margin_property = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "top margin", 2); +- dev->mode_config.tv_top_margin_property->values[0] = 0; +- dev->mode_config.tv_top_margin_property->values[1] = 100; ++ drm_property_create_range(dev, 0, "top margin", 0, 100); + + dev->mode_config.tv_bottom_margin_property = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "bottom margin", 2); +- dev->mode_config.tv_bottom_margin_property->values[0] = 0; +- dev->mode_config.tv_bottom_margin_property->values[1] = 100; ++ drm_property_create_range(dev, 0, "bottom margin", 0, 100); + + dev->mode_config.tv_mode_property = + drm_property_create(dev, DRM_MODE_PROP_ENUM, +@@ -725,40 +814,22 @@ int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, + i, modes[i]); + + dev->mode_config.tv_brightness_property = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "brightness", 2); +- dev->mode_config.tv_brightness_property->values[0] = 0; +- dev->mode_config.tv_brightness_property->values[1] = 100; ++ drm_property_create_range(dev, 0, "brightness", 0, 100); + + dev->mode_config.tv_contrast_property = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "contrast", 2); +- dev->mode_config.tv_contrast_property->values[0] = 0; +- dev->mode_config.tv_contrast_property->values[1] = 100; ++ drm_property_create_range(dev, 0, "contrast", 0, 100); + + dev->mode_config.tv_flicker_reduction_property = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "flicker reduction", 2); +- dev->mode_config.tv_flicker_reduction_property->values[0] = 0; +- dev->mode_config.tv_flicker_reduction_property->values[1] = 100; ++ drm_property_create_range(dev, 0, "flicker reduction", 0, 100); + + dev->mode_config.tv_overscan_property = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "overscan", 2); +- dev->mode_config.tv_overscan_property->values[0] = 0; +- dev->mode_config.tv_overscan_property->values[1] = 100; ++ drm_property_create_range(dev, 0, "overscan", 0, 100); + + dev->mode_config.tv_saturation_property = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "saturation", 2); +- dev->mode_config.tv_saturation_property->values[0] = 0; +- dev->mode_config.tv_saturation_property->values[1] = 100; ++ drm_property_create_range(dev, 0, "saturation", 0, 100); + + dev->mode_config.tv_hue_property = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "hue", 2); +- dev->mode_config.tv_hue_property->values[0] = 0; +- dev->mode_config.tv_hue_property->values[1] = 100; ++ drm_property_create_range(dev, 0, "hue", 0, 100); + + return 0; + } +@@ -774,18 +845,14 @@ EXPORT_SYMBOL(drm_mode_create_tv_properties); + int drm_mode_create_scaling_mode_property(struct drm_device *dev) + { + struct drm_property *scaling_mode; +- int i; + + if (dev->mode_config.scaling_mode_property) + return 0; + + scaling_mode = +- drm_property_create(dev, DRM_MODE_PROP_ENUM, "scaling mode", ++ drm_property_create_enum(dev, 0, "scaling mode", ++ drm_scaling_mode_enum_list, + ARRAY_SIZE(drm_scaling_mode_enum_list)); +- for (i = 0; i < ARRAY_SIZE(drm_scaling_mode_enum_list); i++) +- drm_property_add_enum(scaling_mode, i, +- drm_scaling_mode_enum_list[i].type, +- drm_scaling_mode_enum_list[i].name); + + dev->mode_config.scaling_mode_property = scaling_mode; + +@@ -803,18 +870,14 @@ EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); + int drm_mode_create_dithering_property(struct drm_device *dev) + { + struct drm_property *dithering_mode; +- int i; + + if (dev->mode_config.dithering_mode_property) + return 0; + + dithering_mode = +- drm_property_create(dev, DRM_MODE_PROP_ENUM, "dithering", ++ drm_property_create_enum(dev, 0, "dithering", ++ drm_dithering_mode_enum_list, + ARRAY_SIZE(drm_dithering_mode_enum_list)); +- for (i = 0; i < ARRAY_SIZE(drm_dithering_mode_enum_list); i++) +- drm_property_add_enum(dithering_mode, i, +- drm_dithering_mode_enum_list[i].type, +- drm_dithering_mode_enum_list[i].name); + dev->mode_config.dithering_mode_property = dithering_mode; + + return 0; +@@ -831,20 +894,15 @@ EXPORT_SYMBOL(drm_mode_create_dithering_property); + int drm_mode_create_dirty_info_property(struct drm_device *dev) + { + struct drm_property *dirty_info; +- int i; + + if (dev->mode_config.dirty_info_property) + return 0; + + dirty_info = +- drm_property_create(dev, DRM_MODE_PROP_ENUM | +- DRM_MODE_PROP_IMMUTABLE, ++ drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, + "dirty", ++ drm_dirty_info_enum_list, + ARRAY_SIZE(drm_dirty_info_enum_list)); +- for (i = 0; i < ARRAY_SIZE(drm_dirty_info_enum_list); i++) +- drm_property_add_enum(dirty_info, i, +- drm_dirty_info_enum_list[i].type, +- drm_dirty_info_enum_list[i].name); + dev->mode_config.dirty_info_property = dirty_info; + + return 0; +@@ -871,6 +929,7 @@ void drm_mode_config_init(struct drm_device *dev) + INIT_LIST_HEAD(&dev->mode_config.encoder_list); + INIT_LIST_HEAD(&dev->mode_config.property_list); + INIT_LIST_HEAD(&dev->mode_config.property_blob_list); ++ INIT_LIST_HEAD(&dev->mode_config.plane_list); + idr_init(&dev->mode_config.crtc_idr); + + mutex_lock(&dev->mode_config.mutex); +@@ -927,6 +986,7 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev, + + return 0; + } ++EXPORT_SYMBOL(drm_mode_group_init_legacy_group); + + /** + * drm_mode_config_cleanup - free up DRM mode_config info +@@ -947,6 +1007,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) + struct drm_encoder *encoder, *enct; + struct drm_framebuffer *fb, *fbt; + struct drm_property *property, *pt; ++ struct drm_plane *plane, *plt; + + list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, + head) { +@@ -967,10 +1028,17 @@ void drm_mode_config_cleanup(struct drm_device *dev) + fb->funcs->destroy(fb); + } + ++ list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, ++ head) { ++ plane->funcs->destroy(plane); ++ } ++ + list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { + crtc->funcs->destroy(crtc); + } + ++ idr_remove_all(&dev->mode_config.crtc_idr); ++ idr_destroy(&dev->mode_config.crtc_idr); + } + EXPORT_SYMBOL(drm_mode_config_cleanup); + +@@ -985,9 +1053,16 @@ EXPORT_SYMBOL(drm_mode_config_cleanup); + * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to + * the user. + */ +-void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, +- struct drm_display_mode *in) ++static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, ++ const struct drm_display_mode *in) + { ++ WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX || ++ in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX || ++ in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX || ++ in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX || ++ in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX, ++ "timing values too large for mode info\n"); ++ + out->clock = in->clock; + out->hdisplay = in->hdisplay; + out->hsync_start = in->hsync_start; +@@ -1016,10 +1091,16 @@ void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, + * + * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to + * the caller. ++ * ++ * RETURNS: ++ * Zero on success, errno on failure. + */ +-void drm_crtc_convert_umode(struct drm_display_mode *out, +- struct drm_mode_modeinfo *in) ++static int drm_crtc_convert_umode(struct drm_display_mode *out, ++ const struct drm_mode_modeinfo *in) + { ++ if (in->clock > INT_MAX || in->vrefresh > INT_MAX) ++ return -ERANGE; ++ + out->clock = in->clock; + out->hdisplay = in->hdisplay; + out->hsync_start = in->hsync_start; +@@ -1036,6 +1117,8 @@ void drm_crtc_convert_umode(struct drm_display_mode *out, + out->type = in->type; + strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); + out->name[DRM_DISPLAY_MODE_LEN-1] = 0; ++ ++ return 0; + } + + /** +@@ -1234,7 +1317,7 @@ out: + * @arg: arg from ioctl + * + * LOCKING: +- * Caller? (FIXME) ++ * Takes mode config lock. + * + * Construct a CRTC configuration structure to return to the user. + * +@@ -1294,7 +1377,7 @@ out: + * @arg: arg from ioctl + * + * LOCKING: +- * Caller? (FIXME) ++ * Takes mode config lock. + * + * Construct a connector configuration structure to return to the user. + * +@@ -1379,7 +1462,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, + */ + if ((out_resp->count_modes >= mode_count) && mode_count) { + copied = 0; +- mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr; ++ mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; + list_for_each_entry(mode, &connector->modes, head) { + drm_crtc_convert_to_umode(&u_mode, mode); + if (copy_to_user(mode_ptr + copied, +@@ -1394,8 +1477,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, + + if ((out_resp->count_props >= props_count) && props_count) { + copied = 0; +- prop_ptr = (uint32_t *)(unsigned long)(out_resp->props_ptr); +- prop_values = (uint64_t *)(unsigned long)(out_resp->prop_values_ptr); ++ prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr); ++ prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr); + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] != 0) { + if (put_user(connector->property_ids[i], +@@ -1417,7 +1500,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, + + if ((out_resp->count_encoders >= encoders_count) && encoders_count) { + copied = 0; +- encoder_ptr = (uint32_t *)(unsigned long)(out_resp->encoders_ptr); ++ encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr); + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] != 0) { + if (put_user(connector->encoder_ids[i], +@@ -1471,6 +1554,254 @@ out: + } + + /** ++ * drm_mode_getplane_res - get plane info ++ * @dev: DRM device ++ * @data: ioctl data ++ * @file_priv: DRM file info ++ * ++ * LOCKING: ++ * Takes mode config lock. ++ * ++ * Return an plane count and set of IDs. ++ */ ++int drm_mode_getplane_res(struct drm_device *dev, void *data, ++ struct drm_file *file_priv) ++{ ++ struct drm_mode_get_plane_res *plane_resp = data; ++ struct drm_mode_config *config; ++ struct drm_plane *plane; ++ uint32_t __user *plane_ptr; ++ int copied = 0, ret = 0; ++ ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ ++ mutex_lock(&dev->mode_config.mutex); ++ config = &dev->mode_config; ++ ++ /* ++ * This ioctl is called twice, once to determine how much space is ++ * needed, and the 2nd time to fill it. ++ */ ++ if (config->num_plane && ++ (plane_resp->count_planes >= config->num_plane)) { ++ plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; ++ ++ list_for_each_entry(plane, &config->plane_list, head) { ++ if (put_user(plane->base.id, plane_ptr + copied)) { ++ ret = -EFAULT; ++ goto out; ++ } ++ copied++; ++ } ++ } ++ plane_resp->count_planes = config->num_plane; ++ ++out: ++ mutex_unlock(&dev->mode_config.mutex); ++ return ret; ++} ++ ++/** ++ * drm_mode_getplane - get plane info ++ * @dev: DRM device ++ * @data: ioctl data ++ * @file_priv: DRM file info ++ * ++ * LOCKING: ++ * Takes mode config lock. ++ * ++ * Return plane info, including formats supported, gamma size, any ++ * current fb, etc. ++ */ ++int drm_mode_getplane(struct drm_device *dev, void *data, ++ struct drm_file *file_priv) ++{ ++ struct drm_mode_get_plane *plane_resp = data; ++ struct drm_mode_object *obj; ++ struct drm_plane *plane; ++ uint32_t __user *format_ptr; ++ int ret = 0; ++ ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ ++ mutex_lock(&dev->mode_config.mutex); ++ obj = drm_mode_object_find(dev, plane_resp->plane_id, ++ DRM_MODE_OBJECT_PLANE); ++ if (!obj) { ++ ret = -ENOENT; ++ goto out; ++ } ++ plane = obj_to_plane(obj); ++ ++ if (plane->crtc) ++ plane_resp->crtc_id = plane->crtc->base.id; ++ else ++ plane_resp->crtc_id = 0; ++ ++ if (plane->fb) ++ plane_resp->fb_id = plane->fb->base.id; ++ else ++ plane_resp->fb_id = 0; ++ ++ plane_resp->plane_id = plane->base.id; ++ plane_resp->possible_crtcs = plane->possible_crtcs; ++ plane_resp->gamma_size = plane->gamma_size; ++ ++ /* ++ * This ioctl is called twice, once to determine how much space is ++ * needed, and the 2nd time to fill it. ++ */ ++ if (plane->format_count && ++ (plane_resp->count_format_types >= plane->format_count)) { ++ format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr; ++ if (copy_to_user(format_ptr, ++ plane->format_types, ++ sizeof(uint32_t) * plane->format_count)) { ++ ret = -EFAULT; ++ goto out; ++ } ++ } ++ plane_resp->count_format_types = plane->format_count; ++ ++out: ++ mutex_unlock(&dev->mode_config.mutex); ++ return ret; ++} ++ ++/** ++ * drm_mode_setplane - set up or tear down an plane ++ * @dev: DRM device ++ * @data: ioctl data* ++ * @file_prive: DRM file info ++ * ++ * LOCKING: ++ * Takes mode config lock. ++ * ++ * Set plane info, including placement, fb, scaling, and other factors. ++ * Or pass a NULL fb to disable. ++ */ ++int drm_mode_setplane(struct drm_device *dev, void *data, ++ struct drm_file *file_priv) ++{ ++ struct drm_mode_set_plane *plane_req = data; ++ struct drm_mode_object *obj; ++ struct drm_plane *plane; ++ struct drm_crtc *crtc; ++ struct drm_framebuffer *fb; ++ int ret = 0; ++ unsigned int fb_width, fb_height; ++ int i; ++ ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ ++ mutex_lock(&dev->mode_config.mutex); ++ ++ /* ++ * First, find the plane, crtc, and fb objects. If not available, ++ * we don't bother to call the driver. ++ */ ++ obj = drm_mode_object_find(dev, plane_req->plane_id, ++ DRM_MODE_OBJECT_PLANE); ++ if (!obj) { ++ DRM_DEBUG_KMS("Unknown plane ID %d\n", ++ plane_req->plane_id); ++ ret = -ENOENT; ++ goto out; ++ } ++ plane = obj_to_plane(obj); ++ ++ /* No fb means shut it down */ ++ if (!plane_req->fb_id) { ++ plane->funcs->disable_plane(plane); ++ plane->crtc = NULL; ++ plane->fb = NULL; ++ goto out; ++ } ++ ++ obj = drm_mode_object_find(dev, plane_req->crtc_id, ++ DRM_MODE_OBJECT_CRTC); ++ if (!obj) { ++ DRM_DEBUG_KMS("Unknown crtc ID %d\n", ++ plane_req->crtc_id); ++ ret = -ENOENT; ++ goto out; ++ } ++ crtc = obj_to_crtc(obj); ++ ++ obj = drm_mode_object_find(dev, plane_req->fb_id, ++ DRM_MODE_OBJECT_FB); ++ if (!obj) { ++ DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", ++ plane_req->fb_id); ++ ret = -ENOENT; ++ goto out; ++ } ++ fb = obj_to_fb(obj); ++ ++ /* Check whether this plane supports the fb pixel format. */ ++ for (i = 0; i < plane->format_count; i++) ++ if (fb->pixel_format == plane->format_types[i]) ++ break; ++ if (i == plane->format_count) { ++ DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ fb_width = fb->width << 16; ++ fb_height = fb->height << 16; ++ ++ /* Make sure source coordinates are inside the fb. */ ++ if (plane_req->src_w > fb_width || ++ plane_req->src_x > fb_width - plane_req->src_w || ++ plane_req->src_h > fb_height || ++ plane_req->src_y > fb_height - plane_req->src_h) { ++ DRM_DEBUG_KMS("Invalid source coordinates " ++ "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", ++ plane_req->src_w >> 16, ++ ((plane_req->src_w & 0xffff) * 15625) >> 10, ++ plane_req->src_h >> 16, ++ ((plane_req->src_h & 0xffff) * 15625) >> 10, ++ plane_req->src_x >> 16, ++ ((plane_req->src_x & 0xffff) * 15625) >> 10, ++ plane_req->src_y >> 16, ++ ((plane_req->src_y & 0xffff) * 15625) >> 10); ++ ret = -ENOSPC; ++ goto out; ++ } ++ ++ /* Give drivers some help against integer overflows */ ++ if (plane_req->crtc_w > INT_MAX || ++ plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w || ++ plane_req->crtc_h > INT_MAX || ++ plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) { ++ DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", ++ plane_req->crtc_w, plane_req->crtc_h, ++ plane_req->crtc_x, plane_req->crtc_y); ++ ret = -ERANGE; ++ goto out; ++ } ++ ++ ret = plane->funcs->update_plane(plane, crtc, fb, ++ plane_req->crtc_x, plane_req->crtc_y, ++ plane_req->crtc_w, plane_req->crtc_h, ++ plane_req->src_x, plane_req->src_y, ++ plane_req->src_w, plane_req->src_h); ++ if (!ret) { ++ plane->crtc = crtc; ++ plane->fb = fb; ++ } ++ ++out: ++ mutex_unlock(&dev->mode_config.mutex); ++ ++ return ret; ++} ++ ++/** + * drm_mode_setcrtc - set CRTC configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl +@@ -1478,7 +1809,7 @@ out: + * @arg: arg from ioctl + * + * LOCKING: +- * Caller? (FIXME) ++ * Takes mode config lock. + * + * Build a new CRTC configuration based on user request. + * +@@ -1493,7 +1824,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, + struct drm_mode_config *config = &dev->mode_config; + struct drm_mode_crtc *crtc_req = data; + struct drm_mode_object *obj; +- struct drm_crtc *crtc, *crtcfb; ++ struct drm_crtc *crtc; + struct drm_connector **connector_set = NULL, *connector; + struct drm_framebuffer *fb = NULL; + struct drm_display_mode *mode = NULL; +@@ -1527,14 +1858,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, + /* If we have a mode we need a framebuffer. */ + /* If we pass -1, set the mode with the currently bound fb */ + if (crtc_req->fb_id == -1) { +- list_for_each_entry(crtcfb, +- &dev->mode_config.crtc_list, head) { +- if (crtcfb == crtc) { +- DRM_DEBUG_KMS("Using current fb for " +- "setmode\n"); +- fb = crtc->fb; +- } ++ if (!crtc->fb) { ++ DRM_DEBUG_KMS("CRTC doesn't have current FB\n"); ++ ret = -EINVAL; ++ goto out; + } ++ fb = crtc->fb; + } else { + obj = drm_mode_object_find(dev, crtc_req->fb_id, + DRM_MODE_OBJECT_FB); +@@ -1548,8 +1877,30 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, + } + + mode = drm_mode_create(dev); +- drm_crtc_convert_umode(mode, &crtc_req->mode); ++ if (!mode) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ret = drm_crtc_convert_umode(mode, &crtc_req->mode); ++ if (ret) { ++ DRM_DEBUG_KMS("Invalid mode\n"); ++ goto out; ++ } ++ + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); ++ ++ if (mode->hdisplay > fb->width || ++ mode->vdisplay > fb->height || ++ crtc_req->x > fb->width - mode->hdisplay || ++ crtc_req->y > fb->height - mode->vdisplay) { ++ DRM_DEBUG_KMS("Invalid CRTC viewport %ux%u+%u+%u for fb size %ux%u.\n", ++ mode->hdisplay, mode->vdisplay, ++ crtc_req->x, crtc_req->y, ++ fb->width, fb->height); ++ ret = -ENOSPC; ++ goto out; ++ } + } + + if (crtc_req->count_connectors == 0 && mode) { +@@ -1583,7 +1934,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, + } + + for (i = 0; i < crtc_req->count_connectors; i++) { +- set_connectors_ptr = (uint32_t *)(unsigned long)crtc_req->set_connectors_ptr; ++ set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr; + if (get_user(out_id, &set_connectors_ptr[i])) { + ret = -EFAULT; + goto out; +@@ -1617,6 +1968,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, + + out: + kfree(connector_set); ++ drm_mode_destroy(dev, mode); + mutex_unlock(&dev->mode_config.mutex); + return ret; + } +@@ -1667,6 +2019,42 @@ out: + return ret; + } + ++/* Original addfb only supported RGB formats, so figure out which one */ ++uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) ++{ ++ uint32_t fmt; ++ ++ switch (bpp) { ++ case 8: ++ fmt = DRM_FORMAT_C8; ++ break; ++ case 16: ++ if (depth == 15) ++ fmt = DRM_FORMAT_XRGB1555; ++ else ++ fmt = DRM_FORMAT_RGB565; ++ break; ++ case 24: ++ fmt = DRM_FORMAT_RGB888; ++ break; ++ case 32: ++ if (depth == 24) ++ fmt = DRM_FORMAT_XRGB8888; ++ else if (depth == 30) ++ fmt = DRM_FORMAT_XRGB2101010; ++ else ++ fmt = DRM_FORMAT_ARGB8888; ++ break; ++ default: ++ DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n"); ++ fmt = DRM_FORMAT_XRGB8888; ++ break; ++ } ++ ++ return fmt; ++} ++EXPORT_SYMBOL(drm_mode_legacy_fb_format); ++ + /** + * drm_mode_addfb - add an FB to the graphics configuration + * @inode: inode from the ioctl +@@ -1687,18 +2075,27 @@ out: + int drm_mode_addfb(struct drm_device *dev, + void *data, struct drm_file *file_priv) + { +- struct drm_mode_fb_cmd *r = data; ++ struct drm_mode_fb_cmd *or = data; ++ struct drm_mode_fb_cmd2 r = {}; + struct drm_mode_config *config = &dev->mode_config; + struct drm_framebuffer *fb; + int ret = 0; + ++ /* Use new struct with format internally */ ++ r.fb_id = or->fb_id; ++ r.width = or->width; ++ r.height = or->height; ++ r.pitches[0] = or->pitch; ++ r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); ++ r.handles[0] = or->handle; ++ + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + +- if ((config->min_width > r->width) || (r->width > config->max_width)) ++ if ((config->min_width > r.width) || (r.width > config->max_width)) + return -EINVAL; + +- if ((config->min_height > r->height) || (r->height > config->max_height)) ++ if ((config->min_height > r.height) || (r.height > config->max_height)) + return -EINVAL; + + mutex_lock(&dev->mode_config.mutex); +@@ -1706,6 +2103,138 @@ int drm_mode_addfb(struct drm_device *dev, + /* TODO check buffer is sufficiently large */ + /* TODO setup destructor callback */ + ++ fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); ++ if (IS_ERR(fb)) { ++ DRM_ERROR("could not create framebuffer\n"); ++ ret = PTR_ERR(fb); ++ goto out; ++ } ++ ++ or->fb_id = fb->base.id; ++ list_add(&fb->filp_head, &file_priv->fbs); ++ DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); ++ ++out: ++ mutex_unlock(&dev->mode_config.mutex); ++ return ret; ++} ++ ++static int format_check(struct drm_mode_fb_cmd2 *r) ++{ ++ uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN; ++ ++ switch (format) { ++ case DRM_FORMAT_C8: ++ case DRM_FORMAT_RGB332: ++ case DRM_FORMAT_BGR233: ++ case DRM_FORMAT_XRGB4444: ++ case DRM_FORMAT_XBGR4444: ++ case DRM_FORMAT_RGBX4444: ++ case DRM_FORMAT_BGRX4444: ++ case DRM_FORMAT_ARGB4444: ++ case DRM_FORMAT_ABGR4444: ++ case DRM_FORMAT_RGBA4444: ++ case DRM_FORMAT_BGRA4444: ++ case DRM_FORMAT_XRGB1555: ++ case DRM_FORMAT_XBGR1555: ++ case DRM_FORMAT_RGBX5551: ++ case DRM_FORMAT_BGRX5551: ++ case DRM_FORMAT_ARGB1555: ++ case DRM_FORMAT_ABGR1555: ++ case DRM_FORMAT_RGBA5551: ++ case DRM_FORMAT_BGRA5551: ++ case DRM_FORMAT_RGB565: ++ case DRM_FORMAT_BGR565: ++ case DRM_FORMAT_RGB888: ++ case DRM_FORMAT_BGR888: ++ case DRM_FORMAT_XRGB8888: ++ case DRM_FORMAT_XBGR8888: ++ case DRM_FORMAT_RGBX8888: ++ case DRM_FORMAT_BGRX8888: ++ case DRM_FORMAT_ARGB8888: ++ case DRM_FORMAT_ABGR8888: ++ case DRM_FORMAT_RGBA8888: ++ case DRM_FORMAT_BGRA8888: ++ case DRM_FORMAT_XRGB2101010: ++ case DRM_FORMAT_XBGR2101010: ++ case DRM_FORMAT_RGBX1010102: ++ case DRM_FORMAT_BGRX1010102: ++ case DRM_FORMAT_ARGB2101010: ++ case DRM_FORMAT_ABGR2101010: ++ case DRM_FORMAT_RGBA1010102: ++ case DRM_FORMAT_BGRA1010102: ++ case DRM_FORMAT_YUYV: ++ case DRM_FORMAT_YVYU: ++ case DRM_FORMAT_UYVY: ++ case DRM_FORMAT_VYUY: ++ case DRM_FORMAT_AYUV: ++ case DRM_FORMAT_NV12: ++ case DRM_FORMAT_NV21: ++ case DRM_FORMAT_NV16: ++ case DRM_FORMAT_NV61: ++ case DRM_FORMAT_YUV410: ++ case DRM_FORMAT_YVU410: ++ case DRM_FORMAT_YUV411: ++ case DRM_FORMAT_YVU411: ++ case DRM_FORMAT_YUV420: ++ case DRM_FORMAT_YVU420: ++ case DRM_FORMAT_YUV422: ++ case DRM_FORMAT_YVU422: ++ case DRM_FORMAT_YUV444: ++ case DRM_FORMAT_YVU444: ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++/** ++ * drm_mode_addfb2 - add an FB to the graphics configuration ++ * @inode: inode from the ioctl ++ * @filp: file * from the ioctl ++ * @cmd: cmd from ioctl ++ * @arg: arg from ioctl ++ * ++ * LOCKING: ++ * Takes mode config lock. ++ * ++ * Add a new FB to the specified CRTC, given a user request with format. ++ * ++ * Called by the user via ioctl. ++ * ++ * RETURNS: ++ * Zero on success, errno on failure. ++ */ ++int drm_mode_addfb2(struct drm_device *dev, ++ void *data, struct drm_file *file_priv) ++{ ++ struct drm_mode_fb_cmd2 *r = data; ++ struct drm_mode_config *config = &dev->mode_config; ++ struct drm_framebuffer *fb; ++ int ret = 0; ++ ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ ++ if ((config->min_width > r->width) || (r->width > config->max_width)) { ++ DRM_ERROR("bad framebuffer width %d, should be >= %d && <= %d\n", ++ r->width, config->min_width, config->max_width); ++ return -EINVAL; ++ } ++ if ((config->min_height > r->height) || (r->height > config->max_height)) { ++ DRM_ERROR("bad framebuffer height %d, should be >= %d && <= %d\n", ++ r->height, config->min_height, config->max_height); ++ return -EINVAL; ++ } ++ ++ ret = format_check(r); ++ if (ret) { ++ DRM_ERROR("bad framebuffer format 0x%08x\n", r->pixel_format); ++ return ret; ++ } ++ ++ mutex_lock(&dev->mode_config.mutex); ++ + fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); + if (IS_ERR(fb)) { + DRM_ERROR("could not create framebuffer\n"); +@@ -1789,7 +2318,7 @@ out: + * @arg: arg from ioctl + * + * LOCKING: +- * Caller? (FIXME) ++ * Takes mode config lock. + * + * Lookup the FB given its ID and return info about it. + * +@@ -1821,7 +2350,7 @@ int drm_mode_getfb(struct drm_device *dev, + r->width = fb->width; + r->depth = fb->depth; + r->bpp = fb->bits_per_pixel; +- r->pitch = fb->pitch; ++ r->pitch = fb->pitches[0]; + if (file_priv->is_master || capable(CAP_SYS_ADMIN)) { + ret = fb->funcs->create_handle(fb, file_priv, &r->handle); + } else { +@@ -1863,7 +2392,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, + fb = obj_to_fb(obj); + + num_clips = r->num_clips; +- clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr; ++ clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr; + + if (!num_clips != !clips_ptr) { + ret = -EINVAL; +@@ -1948,38 +2477,48 @@ void drm_fb_release(struct drm_file *priv) + * + * Add @mode to @connector's user mode list. + */ +-static int drm_mode_attachmode(struct drm_device *dev, +- struct drm_connector *connector, +- struct drm_display_mode *mode) ++static void drm_mode_attachmode(struct drm_device *dev, ++ struct drm_connector *connector, ++ struct drm_display_mode *mode) + { +- int ret = 0; +- + list_add_tail(&mode->head, &connector->user_modes); +- return ret; + } + + int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + struct drm_connector *connector; + int ret = 0; +- struct drm_display_mode *dup_mode; +- int need_dup = 0; ++ struct drm_display_mode *dup_mode, *next; ++ LIST_HEAD(list); ++ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (!connector->encoder) +- break; ++ continue; + if (connector->encoder->crtc == crtc) { +- if (need_dup) +- dup_mode = drm_mode_duplicate(dev, mode); +- else +- dup_mode = mode; +- ret = drm_mode_attachmode(dev, connector, dup_mode); +- if (ret) +- return ret; +- need_dup = 1; ++ dup_mode = drm_mode_duplicate(dev, mode); ++ if (!dup_mode) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ list_add_tail(&dup_mode->head, &list); + } + } +- return 0; ++ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ if (!connector->encoder) ++ continue; ++ if (connector->encoder->crtc == crtc) ++ list_move_tail(list.next, &connector->user_modes); ++ } ++ ++ WARN_ON(!list_empty(&list)); ++ ++ out: ++ list_for_each_entry_safe(dup_mode, next, &list, head) ++ drm_mode_destroy(dev, dup_mode); ++ ++ return ret; + } + EXPORT_SYMBOL(drm_mode_attachmode_crtc); + +@@ -2058,9 +2597,14 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev, + goto out; + } + +- drm_crtc_convert_umode(mode, umode); ++ ret = drm_crtc_convert_umode(mode, umode); ++ if (ret) { ++ DRM_DEBUG_KMS("Invalid mode\n"); ++ drm_mode_destroy(dev, mode); ++ goto out; ++ } + +- ret = drm_mode_attachmode(dev, connector, mode); ++ drm_mode_attachmode(dev, connector, mode); + out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +@@ -2101,7 +2645,12 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev, + } + connector = obj_to_connector(obj); + +- drm_crtc_convert_umode(&mode, umode); ++ ret = drm_crtc_convert_umode(&mode, umode); ++ if (ret) { ++ DRM_DEBUG_KMS("Invalid mode\n"); ++ goto out; ++ } ++ + ret = drm_mode_detachmode(dev, connector, &mode); + out: + mutex_unlock(&dev->mode_config.mutex); +@@ -2112,6 +2661,7 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, + const char *name, int num_values) + { + struct drm_property *property = NULL; ++ int ret; + + property = kzalloc(sizeof(struct drm_property), GFP_KERNEL); + if (!property) +@@ -2123,7 +2673,10 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, + goto fail; + } + +- drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY); ++ ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY); ++ if (ret) ++ goto fail; ++ + property->flags = flags; + property->num_values = num_values; + INIT_LIST_HEAD(&property->enum_blob_list); +@@ -2136,11 +2689,59 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, + list_add_tail(&property->head, &dev->mode_config.property_list); + return property; + fail: ++ kfree(property->values); + kfree(property); + return NULL; + } + EXPORT_SYMBOL(drm_property_create); + ++struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags, ++ const char *name, ++ const struct drm_prop_enum_list *props, ++ int num_values) ++{ ++ struct drm_property *property; ++ int i, ret; ++ ++ flags |= DRM_MODE_PROP_ENUM; ++ ++ property = drm_property_create(dev, flags, name, num_values); ++ if (!property) ++ return NULL; ++ ++ for (i = 0; i < num_values; i++) { ++ ret = drm_property_add_enum(property, i, ++ props[i].type, ++ props[i].name); ++ if (ret) { ++ drm_property_destroy(dev, property); ++ return NULL; ++ } ++ } ++ ++ return property; ++} ++EXPORT_SYMBOL(drm_property_create_enum); ++ ++struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, ++ const char *name, ++ uint64_t min, uint64_t max) ++{ ++ struct drm_property *property; ++ ++ flags |= DRM_MODE_PROP_RANGE; ++ ++ property = drm_property_create(dev, flags, name, 2); ++ if (!property) ++ return NULL; ++ ++ property->values[0] = min; ++ property->values[1] = max; ++ ++ return property; ++} ++EXPORT_SYMBOL(drm_property_create_range); ++ + int drm_property_add_enum(struct drm_property *property, int index, + uint64_t value, const char *name) + { +@@ -2259,7 +2860,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, + struct drm_property_enum *prop_enum; + struct drm_mode_property_enum __user *enum_ptr; + struct drm_property_blob *prop_blob; +- uint32_t *blob_id_ptr; ++ uint32_t __user *blob_id_ptr; + uint64_t __user *values_ptr; + uint32_t __user *blob_length_ptr; + +@@ -2289,7 +2890,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, + out_resp->flags = property->flags; + + if ((out_resp->count_values >= value_count) && value_count) { +- values_ptr = (uint64_t *)(unsigned long)out_resp->values_ptr; ++ values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr; + for (i = 0; i < value_count; i++) { + if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) { + ret = -EFAULT; +@@ -2302,7 +2903,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, + if (property->flags & DRM_MODE_PROP_ENUM) { + if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { + copied = 0; +- enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr; ++ enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr; + list_for_each_entry(prop_enum, &property->enum_blob_list, head) { + + if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) { +@@ -2324,8 +2925,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, + if (property->flags & DRM_MODE_PROP_BLOB) { + if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { + copied = 0; +- blob_id_ptr = (uint32_t *)(unsigned long)out_resp->enum_blob_ptr; +- blob_length_ptr = (uint32_t *)(unsigned long)out_resp->values_ptr; ++ blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr; ++ blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr; + + list_for_each_entry(prop_blob, &property->enum_blob_list, head) { + if (put_user(prop_blob->base.id, blob_id_ptr + copied)) { +@@ -2352,6 +2953,7 @@ static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev + void *data) + { + struct drm_property_blob *blob; ++ int ret; + + if (!length || !data) + return NULL; +@@ -2360,13 +2962,16 @@ static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev + if (!blob) + return NULL; + +- blob->data = (void *)((char *)blob + sizeof(struct drm_property_blob)); ++ ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); ++ if (ret) { ++ kfree(blob); ++ return NULL; ++ } ++ + blob->length = length; + + memcpy(blob->data, data, length); + +- drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); +- + list_add_tail(&blob->head, &dev->mode_config.property_blob_list); + return blob; + } +@@ -2386,7 +2991,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, + struct drm_mode_get_blob *out_resp = data; + struct drm_property_blob *blob; + int ret = 0; +- void *blob_ptr; ++ void __user *blob_ptr; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; +@@ -2400,7 +3005,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, + blob = obj_to_blob(obj); + + if (out_resp->length == blob->length) { +- blob_ptr = (void *)(unsigned long)out_resp->data; ++ blob_ptr = (void __user *)(unsigned long)out_resp->data; + if (copy_to_user(blob_ptr, blob->data, blob->length)){ + ret = -EFAULT; + goto done; +@@ -2545,7 +3150,7 @@ void drm_mode_connector_detach_encoder(struct drm_connector *connector, + } + EXPORT_SYMBOL(drm_mode_connector_detach_encoder); + +-bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, ++int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, + int gamma_size) + { + crtc->gamma_size = gamma_size; +@@ -2553,10 +3158,10 @@ bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, + crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL); + if (!crtc->gamma_store) { + crtc->gamma_size = 0; +- return false; ++ return -ENOMEM; + } + +- return true; ++ return 0; + } + EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size); + +@@ -2702,6 +3307,18 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, + goto out; + fb = obj_to_fb(obj); + ++ if (crtc->mode.hdisplay > fb->width || ++ crtc->mode.vdisplay > fb->height || ++ crtc->x > fb->width - crtc->mode.hdisplay || ++ crtc->y > fb->height - crtc->mode.vdisplay) { ++ DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d.\n", ++ fb->width, fb->height, ++ crtc->mode.hdisplay, crtc->mode.vdisplay, ++ crtc->x, crtc->y); ++ ret = -ENOSPC; ++ goto out; ++ } ++ + if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { + ret = -ENOMEM; + spin_lock_irqsave(&dev->event_lock, flags); +@@ -2731,10 +3348,12 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, + + ret = crtc->funcs->page_flip(crtc, fb, e); + if (ret) { +- spin_lock_irqsave(&dev->event_lock, flags); +- file_priv->event_space += sizeof e->event; +- spin_unlock_irqrestore(&dev->event_lock, flags); +- kfree(e); ++ if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { ++ spin_lock_irqsave(&dev->event_lock, flags); ++ file_priv->event_space += sizeof e->event; ++ spin_unlock_irqrestore(&dev->event_lock, flags); ++ kfree(e); ++ } + } + + out: +@@ -2794,3 +3413,72 @@ int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, + + return dev->driver->dumb_destroy(file_priv, dev, args->handle); + } ++ ++/* ++ * Just need to support RGB formats here for compat with code that doesn't ++ * use pixel formats directly yet. ++ */ ++void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, ++ int *bpp) ++{ ++ switch (format) { ++ case DRM_FORMAT_C8: ++ case DRM_FORMAT_RGB332: ++ case DRM_FORMAT_BGR233: ++ *depth = 8; ++ *bpp = 8; ++ break; ++ case DRM_FORMAT_XRGB1555: ++ case DRM_FORMAT_XBGR1555: ++ case DRM_FORMAT_RGBX5551: ++ case DRM_FORMAT_BGRX5551: ++ case DRM_FORMAT_ARGB1555: ++ case DRM_FORMAT_ABGR1555: ++ case DRM_FORMAT_RGBA5551: ++ case DRM_FORMAT_BGRA5551: ++ *depth = 15; ++ *bpp = 16; ++ break; ++ case DRM_FORMAT_RGB565: ++ case DRM_FORMAT_BGR565: ++ *depth = 16; ++ *bpp = 16; ++ break; ++ case DRM_FORMAT_RGB888: ++ case DRM_FORMAT_BGR888: ++ *depth = 24; ++ *bpp = 24; ++ break; ++ case DRM_FORMAT_XRGB8888: ++ case DRM_FORMAT_XBGR8888: ++ case DRM_FORMAT_RGBX8888: ++ case DRM_FORMAT_BGRX8888: ++ *depth = 24; ++ *bpp = 32; ++ break; ++ case DRM_FORMAT_XRGB2101010: ++ case DRM_FORMAT_XBGR2101010: ++ case DRM_FORMAT_RGBX1010102: ++ case DRM_FORMAT_BGRX1010102: ++ case DRM_FORMAT_ARGB2101010: ++ case DRM_FORMAT_ABGR2101010: ++ case DRM_FORMAT_RGBA1010102: ++ case DRM_FORMAT_BGRA1010102: ++ *depth = 30; ++ *bpp = 32; ++ break; ++ case DRM_FORMAT_ARGB8888: ++ case DRM_FORMAT_ABGR8888: ++ case DRM_FORMAT_RGBA8888: ++ case DRM_FORMAT_BGRA8888: ++ *depth = 32; ++ *bpp = 32; ++ break; ++ default: ++ DRM_DEBUG_KMS("unsupported pixel format\n"); ++ *depth = 0; ++ *bpp = 0; ++ break; ++ } ++} ++EXPORT_SYMBOL(drm_fb_get_bpp_depth); +diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c +index 11788f7..b3abf70 100644 +--- a/drivers/gpu/drm/drm_crtc_helper.c ++++ b/drivers/gpu/drm/drm_crtc_helper.c +@@ -34,8 +34,10 @@ + + #include "drmP.h" + #include "drm_crtc.h" ++#include "drm_fourcc.h" + #include "drm_crtc_helper.h" + #include "drm_fb_helper.h" ++#include "drm_edid.h" + + static bool drm_kms_helper_poll = true; + module_param_named(poll, drm_kms_helper_poll, bool, 0600); +@@ -43,12 +45,12 @@ module_param_named(poll, drm_kms_helper_poll, bool, 0600); + static void drm_mode_validate_flag(struct drm_connector *connector, + int flags) + { +- struct drm_display_mode *mode, *t; ++ struct drm_display_mode *mode; + + if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE)) + return; + +- list_for_each_entry_safe(mode, t, &connector->modes, head) { ++ list_for_each_entry(mode, &connector->modes, head) { + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && + !(flags & DRM_MODE_FLAG_INTERLACE)) + mode->status = MODE_NO_INTERLACE; +@@ -86,7 +88,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, + uint32_t maxX, uint32_t maxY) + { + struct drm_device *dev = connector->dev; +- struct drm_display_mode *mode, *t; ++ struct drm_display_mode *mode; + struct drm_connector_helper_funcs *connector_funcs = + connector->helper_private; + int count = 0; +@@ -95,7 +97,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, + drm_get_connector_name(connector)); + /* set all modes to the unverified state */ +- list_for_each_entry_safe(mode, t, &connector->modes, head) ++ list_for_each_entry(mode, &connector->modes, head) + mode->status = MODE_UNVERIFIED; + + if (connector->force) { +@@ -117,7 +119,12 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, + goto prune; + } + +- count = (*connector_funcs->get_modes)(connector); ++#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE ++ count = drm_load_edid_firmware(connector); ++ if (count == 0) ++#endif ++ count = (*connector_funcs->get_modes)(connector); ++ + if (count == 0 && connector->status == connector_status_connected) + count = drm_add_modes_noedid(connector, 1024, 768); + if (count == 0) +@@ -135,7 +142,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, + mode_flags |= DRM_MODE_FLAG_DBLSCAN; + drm_mode_validate_flag(connector, mode_flags); + +- list_for_each_entry_safe(mode, t, &connector->modes, head) { ++ list_for_each_entry(mode, &connector->modes, head) { + if (mode->status == MODE_OK) + mode->status = connector_funcs->mode_valid(connector, + mode); +@@ -151,7 +158,7 @@ prune: + + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, + drm_get_connector_name(connector)); +- list_for_each_entry_safe(mode, t, &connector->modes, head) { ++ list_for_each_entry(mode, &connector->modes, head) { + mode->vrefresh = drm_mode_vrefresh(mode); + + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); +@@ -351,6 +358,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, + return true; + + adjusted_mode = drm_mode_duplicate(dev, mode); ++ if (!adjusted_mode) ++ return false; + + saved_hwmode = crtc->hwmode; + saved_mode = crtc->mode; +@@ -710,7 +719,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) + for (i = 0; i < set->num_connectors; i++) { + DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id, + drm_get_connector_name(set->connectors[i])); +- set->connectors[i]->dpms = DRM_MODE_DPMS_ON; ++ set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON); + } + } + drm_helper_disable_unused_functions(dev); +@@ -847,13 +856,19 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) + EXPORT_SYMBOL(drm_helper_connector_dpms); + + int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, +- struct drm_mode_fb_cmd *mode_cmd) ++ struct drm_mode_fb_cmd2 *mode_cmd) + { ++ int i; ++ + fb->width = mode_cmd->width; + fb->height = mode_cmd->height; +- fb->pitch = mode_cmd->pitch; +- fb->bits_per_pixel = mode_cmd->bpp; +- fb->depth = mode_cmd->depth; ++ for (i = 0; i < 4; i++) { ++ fb->pitches[i] = mode_cmd->pitches[i]; ++ fb->offsets[i] = mode_cmd->offsets[i]; ++ } ++ drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, ++ &fb->bits_per_pixel); ++ fb->pixel_format = mode_cmd->pixel_format; + + return 0; + } +@@ -1008,3 +1023,36 @@ void drm_helper_hpd_irq_event(struct drm_device *dev) + queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0); + } + EXPORT_SYMBOL(drm_helper_hpd_irq_event); ++ ++ ++/** ++ * drm_format_num_planes - get the number of planes for format ++ * @format: pixel format (DRM_FORMAT_*) ++ * ++ * RETURNS: ++ * The number of planes used by the specified pixel format. ++ */ ++int drm_format_num_planes(uint32_t format) ++{ ++ switch (format) { ++ case DRM_FORMAT_YUV410: ++ case DRM_FORMAT_YVU410: ++ case DRM_FORMAT_YUV411: ++ case DRM_FORMAT_YVU411: ++ case DRM_FORMAT_YUV420: ++ case DRM_FORMAT_YVU420: ++ case DRM_FORMAT_YUV422: ++ case DRM_FORMAT_YVU422: ++ case DRM_FORMAT_YUV444: ++ case DRM_FORMAT_YVU444: ++ return 3; ++ case DRM_FORMAT_NV12: ++ case DRM_FORMAT_NV21: ++ case DRM_FORMAT_NV16: ++ case DRM_FORMAT_NV61: ++ return 2; ++ default: ++ return 1; ++ } ++} ++EXPORT_SYMBOL(drm_format_num_planes); +diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c +index 0731d43..91b1265 100644 +--- a/drivers/gpu/drm/drm_drv.c ++++ b/drivers/gpu/drm/drm_drv.c +@@ -61,14 +61,14 @@ static int drm_version(struct drm_device *dev, void *data, + + /** Ioctl table */ + static struct drm_ioctl_desc drm_ioctls[] = { +- DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0), ++ DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), + DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), +- DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0), +- DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0), +- DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0), +- DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, 0), ++ DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), + + DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), +@@ -135,21 +135,25 @@ static struct drm_ioctl_desc drm_ioctls[] = { + DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), + +- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), +- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), +- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED), +- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), +- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), +- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), ++ DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), +@@ -386,6 +390,10 @@ long drm_ioctl(struct file *filp, + unsigned int usize, asize; + + dev = file_priv->minor->dev; ++ ++ if (drm_device_is_unplugged(dev)) ++ return -ENODEV; ++ + atomic_inc(&dev->ioctl_count); + atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); + ++file_priv->ioctl_count; +@@ -456,9 +464,8 @@ long drm_ioctl(struct file *filp, + retcode = -EFAULT; + goto err_i1; + } +- } else if (cmd & IOC_OUT) { ++ } else + memset(kdata, 0, usize); +- } + + if (ioctl->flags & DRM_UNLOCKED) + retcode = func(dev, kdata, file_priv); +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index 72f460e..d75dccb 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -68,6 +68,8 @@ + #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) + /* Force reduced-blanking timings for detailed modes */ + #define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) ++/* Force 8bpc */ ++#define EDID_QUIRK_FORCE_8BPC (1 << 8) + + struct detailed_mode_closure { + struct drm_connector *connector; +@@ -128,6 +130,9 @@ static struct edid_quirk { + + /* Medion MD 30217 PG */ + { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 }, ++ ++ /* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */ ++ { "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC }, + }; + + /*** DDC fetch and block validation ***/ +@@ -157,8 +162,7 @@ EXPORT_SYMBOL(drm_edid_header_is_valid); + * Sanity check the EDID block (base or extension). Return 0 if the block + * doesn't check out, or 1 if it's valid. + */ +-static bool +-drm_edid_block_valid(u8 *raw_edid) ++bool drm_edid_block_valid(u8 *raw_edid) + { + int i; + u8 csum = 0; +@@ -211,6 +215,7 @@ bad: + } + return 0; + } ++EXPORT_SYMBOL(drm_edid_block_valid); + + /** + * drm_edid_is_valid - sanity check EDID data +@@ -234,7 +239,6 @@ bool drm_edid_is_valid(struct edid *edid) + } + EXPORT_SYMBOL(drm_edid_is_valid); + +-#define DDC_ADDR 0x50 + #define DDC_SEGMENT_ADDR 0x30 + /** + * Get EDID information via I2C. +@@ -521,25 +525,10 @@ static void + cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) + { + int i, n = 0; +- u8 rev = ext[0x01], d = ext[0x02]; ++ u8 d = ext[0x02]; + u8 *det_base = ext + d; + +- switch (rev) { +- case 0: +- /* can't happen */ +- return; +- case 1: +- /* have to infer how many blocks we have, check pixel clock */ +- for (i = 0; i < 6; i++) +- if (det_base[18*i] || det_base[18*i+1]) +- n++; +- break; +- default: +- /* explicit count */ +- n = min(ext[0x03] & 0x0f, 6); +- break; +- } +- ++ n = (127 - d) / 18; + for (i = 0; i < n; i++) + cb((struct detailed_timing *)(det_base + 18 * i), closure); + } +@@ -773,7 +762,7 @@ drm_mode_std(struct drm_connector *connector, struct edid *edid, + */ + mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); + if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) { +- kfree(mode); ++ drm_mode_destroy(dev, mode); + mode = drm_gtf_mode_complex(dev, hsize, vsize, + vrefresh_rate, 0, 0, + drm_gtf2_m(edid), +@@ -1342,6 +1331,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, + + #define HDMI_IDENTIFIER 0x000C03 + #define AUDIO_BLOCK 0x01 ++#define VIDEO_BLOCK 0x02 + #define VENDOR_BLOCK 0x03 + #define SPEAKER_BLOCK 0x04 + #define EDID_BASIC_AUDIO (1 << 6) +@@ -1372,6 +1362,47 @@ u8 *drm_find_cea_extension(struct edid *edid) + } + EXPORT_SYMBOL(drm_find_cea_extension); + ++static int ++do_cea_modes (struct drm_connector *connector, u8 *db, u8 len) ++{ ++ struct drm_device *dev = connector->dev; ++ u8 * mode, cea_mode; ++ int modes = 0; ++ ++ for (mode = db; mode < db + len; mode++) { ++ cea_mode = (*mode & 127) - 1; /* CEA modes are numbered 1..127 */ ++ if (cea_mode < drm_num_cea_modes) { ++ struct drm_display_mode *newmode; ++ newmode = drm_mode_duplicate(dev, ++ &edid_cea_modes[cea_mode]); ++ if (newmode) { ++ drm_mode_probed_add(connector, newmode); ++ modes++; ++ } ++ } ++ } ++ ++ return modes; ++} ++ ++static int ++add_cea_modes(struct drm_connector *connector, struct edid *edid) ++{ ++ u8 * cea = drm_find_cea_extension(edid); ++ u8 * db, dbl; ++ int modes = 0; ++ ++ if (cea && cea[1] >= 3) { ++ for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) { ++ dbl = db[0] & 0x1f; ++ if (((db[0] & 0xe0) >> 5) == VIDEO_BLOCK) ++ modes += do_cea_modes (connector, db+1, dbl); ++ } ++ } ++ ++ return modes; ++} ++ + static void + parse_hdmi_vsdb(struct drm_connector *connector, uint8_t *db) + { +@@ -1455,26 +1486,29 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) + eld[18] = edid->prod_code[0]; + eld[19] = edid->prod_code[1]; + +- for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) { +- dbl = db[0] & 0x1f; +- +- switch ((db[0] & 0xe0) >> 5) { +- case AUDIO_BLOCK: /* Audio Data Block, contains SADs */ +- sad_count = dbl / 3; +- memcpy(eld + 20 + mnl, &db[1], dbl); +- break; +- case SPEAKER_BLOCK: /* Speaker Allocation Data Block */ +- eld[7] = db[1]; +- break; +- case VENDOR_BLOCK: +- /* HDMI Vendor-Specific Data Block */ +- if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0) +- parse_hdmi_vsdb(connector, db); +- break; +- default: +- break; ++ if (cea[1] >= 3) ++ for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) { ++ dbl = db[0] & 0x1f; ++ ++ switch ((db[0] & 0xe0) >> 5) { ++ case AUDIO_BLOCK: ++ /* Audio Data Block, contains SADs */ ++ sad_count = dbl / 3; ++ memcpy(eld + 20 + mnl, &db[1], dbl); ++ break; ++ case SPEAKER_BLOCK: ++ /* Speaker Allocation Data Block */ ++ eld[7] = db[1]; ++ break; ++ case VENDOR_BLOCK: ++ /* HDMI Vendor-Specific Data Block */ ++ if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0) ++ parse_hdmi_vsdb(connector, db); ++ break; ++ default: ++ break; ++ } + } +- } + eld[5] |= sad_count << 4; + eld[2] = (20 + mnl + sad_count * 3 + 3) / 4; + +@@ -1746,12 +1780,16 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) + num_modes += add_established_modes(connector, edid); + if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) + num_modes += add_inferred_modes(connector, edid); ++ num_modes += add_cea_modes(connector, edid); + + if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) + edid_fixup_preferred(connector, quirks); + + drm_add_display_info(edid, &connector->display_info); + ++ if (quirks & EDID_QUIRK_FORCE_8BPC) ++ connector->display_info.bpc = 8; ++ + return num_modes; + } + EXPORT_SYMBOL(drm_add_edid_modes); +diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c +new file mode 100644 +index 0000000..da9acba +--- /dev/null ++++ b/drivers/gpu/drm/drm_edid_load.c +@@ -0,0 +1,250 @@ ++/* ++ drm_edid_load.c: use a built-in EDID data set or load it via the firmware ++ interface ++ ++ Copyright (C) 2012 Carsten Emde ++ ++ This program is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public License ++ as published by the Free Software Foundation; either version 2 ++ of the License, or (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++*/ ++ ++#include ++#include ++#include "drmP.h" ++#include "drm_crtc.h" ++#include "drm_crtc_helper.h" ++#include "drm_edid.h" ++ ++static char edid_firmware[PATH_MAX]; ++module_param_string(edid_firmware, edid_firmware, sizeof(edid_firmware), 0644); ++MODULE_PARM_DESC(edid_firmware, "Do not probe monitor, use specified EDID blob " ++ "from built-in data or /lib/firmware instead. "); ++ ++#define GENERIC_EDIDS 4 ++static char *generic_edid_name[GENERIC_EDIDS] = { ++ "edid/1024x768.bin", ++ "edid/1280x1024.bin", ++ "edid/1680x1050.bin", ++ "edid/1920x1080.bin", ++}; ++ ++static u8 generic_edid[GENERIC_EDIDS][128] = { ++ { ++ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, ++ 0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x05, 0x16, 0x01, 0x03, 0x6d, 0x23, 0x1a, 0x78, ++ 0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25, ++ 0x20, 0x50, 0x54, 0x00, 0x08, 0x00, 0x61, 0x40, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x64, 0x19, ++ 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x08, 0x90, ++ 0x36, 0x00, 0x63, 0x0a, 0x11, 0x00, 0x00, 0x18, ++ 0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e, ++ 0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20, ++ 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b, ++ 0x3d, 0x2f, 0x31, 0x07, 0x00, 0x0a, 0x20, 0x20, ++ 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, ++ 0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x58, ++ 0x47, 0x41, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x55, ++ }, ++ { ++ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, ++ 0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x05, 0x16, 0x01, 0x03, 0x6d, 0x2c, 0x23, 0x78, ++ 0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25, ++ 0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0x81, 0x80, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x30, 0x2a, ++ 0x00, 0x98, 0x51, 0x00, 0x2a, 0x40, 0x30, 0x70, ++ 0x13, 0x00, 0xbc, 0x63, 0x11, 0x00, 0x00, 0x1e, ++ 0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e, ++ 0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20, ++ 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b, ++ 0x3d, 0x3e, 0x40, 0x0b, 0x00, 0x0a, 0x20, 0x20, ++ 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, ++ 0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x53, ++ 0x58, 0x47, 0x41, 0x0a, 0x20, 0x20, 0x00, 0xa0, ++ }, ++ { ++ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, ++ 0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x05, 0x16, 0x01, 0x03, 0x6d, 0x2b, 0x1b, 0x78, ++ 0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25, ++ 0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0xb3, 0x00, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x21, 0x39, ++ 0x90, 0x30, 0x62, 0x1a, 0x27, 0x40, 0x68, 0xb0, ++ 0x36, 0x00, 0xb5, 0x11, 0x11, 0x00, 0x00, 0x1e, ++ 0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e, ++ 0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20, ++ 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b, ++ 0x3d, 0x40, 0x42, 0x0f, 0x00, 0x0a, 0x20, 0x20, ++ 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, ++ 0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x57, ++ 0x53, 0x58, 0x47, 0x41, 0x0a, 0x20, 0x00, 0x26, ++ }, ++ { ++ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, ++ 0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x05, 0x16, 0x01, 0x03, 0x6d, 0x32, 0x1c, 0x78, ++ 0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25, ++ 0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0xd1, 0xc0, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, ++ 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, ++ 0x45, 0x00, 0xf4, 0x19, 0x11, 0x00, 0x00, 0x1e, ++ 0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e, ++ 0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20, ++ 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b, ++ 0x3d, 0x42, 0x44, 0x0f, 0x00, 0x0a, 0x20, 0x20, ++ 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, ++ 0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x46, ++ 0x48, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x05, ++ }, ++}; ++ ++static int edid_load(struct drm_connector *connector, char *name, ++ char *connector_name) ++{ ++ const struct firmware *fw; ++ struct platform_device *pdev; ++ u8 *fwdata = NULL, *edid; ++ int fwsize, expected; ++ int builtin = 0, err = 0; ++ int i, valid_extensions = 0; ++ ++ pdev = platform_device_register_simple(connector_name, -1, NULL, 0); ++ if (IS_ERR(pdev)) { ++ DRM_ERROR("Failed to register EDID firmware platform device " ++ "for connector \"%s\"\n", connector_name); ++ err = -EINVAL; ++ goto out; ++ } ++ ++ err = request_firmware(&fw, name, &pdev->dev); ++ platform_device_unregister(pdev); ++ ++ if (err) { ++ i = 0; ++ while (i < GENERIC_EDIDS && strcmp(name, generic_edid_name[i])) ++ i++; ++ if (i < GENERIC_EDIDS) { ++ err = 0; ++ builtin = 1; ++ fwdata = generic_edid[i]; ++ fwsize = sizeof(generic_edid[i]); ++ } ++ } ++ ++ if (err) { ++ DRM_ERROR("Requesting EDID firmware \"%s\" failed (err=%d)\n", ++ name, err); ++ goto out; ++ } ++ ++ if (fwdata == NULL) { ++ fwdata = (u8 *) fw->data; ++ fwsize = fw->size; ++ } ++ ++ expected = (fwdata[0x7e] + 1) * EDID_LENGTH; ++ if (expected != fwsize) { ++ DRM_ERROR("Size of EDID firmware \"%s\" is invalid " ++ "(expected %d, got %d)\n", name, expected, (int) fwsize); ++ err = -EINVAL; ++ goto relfw_out; ++ } ++ ++ edid = kmalloc(fwsize, GFP_KERNEL); ++ if (edid == NULL) { ++ err = -ENOMEM; ++ goto relfw_out; ++ } ++ memcpy(edid, fwdata, fwsize); ++ ++ if (!drm_edid_block_valid(edid)) { ++ DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ", ++ name); ++ kfree(edid); ++ err = -EINVAL; ++ goto relfw_out; ++ } ++ ++ for (i = 1; i <= edid[0x7e]; i++) { ++ if (i != valid_extensions + 1) ++ memcpy(edid + (valid_extensions + 1) * EDID_LENGTH, ++ edid + i * EDID_LENGTH, EDID_LENGTH); ++ if (drm_edid_block_valid(edid + i * EDID_LENGTH)) ++ valid_extensions++; ++ } ++ ++ if (valid_extensions != edid[0x7e]) { ++ edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions; ++ DRM_INFO("Found %d valid extensions instead of %d in EDID data " ++ "\"%s\" for connector \"%s\"\n", valid_extensions, ++ edid[0x7e], name, connector_name); ++ edid[0x7e] = valid_extensions; ++ edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, ++ GFP_KERNEL); ++ if (edid == NULL) { ++ err = -ENOMEM; ++ goto relfw_out; ++ } ++ } ++ ++ connector->display_info.raw_edid = edid; ++ DRM_INFO("Got %s EDID base block and %d extension%s from " ++ "\"%s\" for connector \"%s\"\n", builtin ? "built-in" : ++ "external", valid_extensions, valid_extensions == 1 ? "" : "s", ++ name, connector_name); ++ ++relfw_out: ++ release_firmware(fw); ++ ++out: ++ return err; ++} ++ ++int drm_load_edid_firmware(struct drm_connector *connector) ++{ ++ char *connector_name = drm_get_connector_name(connector); ++ char *edidname = edid_firmware, *last, *colon; ++ int ret = 0; ++ ++ if (*edidname == '\0') ++ return ret; ++ ++ colon = strchr(edidname, ':'); ++ if (colon != NULL) { ++ if (strncmp(connector_name, edidname, colon - edidname)) ++ return ret; ++ edidname = colon + 1; ++ if (*edidname == '\0') ++ return ret; ++ } ++ ++ last = edidname + strlen(edidname) - 1; ++ if (*last == '\n') ++ *last = '\0'; ++ ++ ret = edid_load(connector, edidname, connector_name); ++ if (ret) ++ return 0; ++ ++ drm_mode_connector_update_edid_property(connector, ++ (struct edid *) connector->display_info.raw_edid); ++ ++ return drm_add_edid_modes(connector, (struct edid *) ++ connector->display_info.raw_edid); ++} +diff --git a/drivers/gpu/drm/drm_edid_modes.h b/drivers/gpu/drm/drm_edid_modes.h +index 5f20644..a91ffb1 100644 +--- a/drivers/gpu/drm/drm_edid_modes.h ++++ b/drivers/gpu/drm/drm_edid_modes.h +@@ -378,3 +378,287 @@ static const struct { + { 1920, 1440, 75, 0 }, + }; + static const int num_est3_modes = sizeof(est3_modes) / sizeof(est3_modes[0]); ++ ++/* ++ * Probably taken from CEA-861 spec. ++ * This table is converted from xorg's hw/xfree86/modes/xf86EdidModes.c. ++ */ ++static const struct drm_display_mode edid_cea_modes[] = { ++ /* 640x480@60Hz */ ++ { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, ++ 752, 800, 0, 480, 490, 492, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 720x480@60Hz */ ++ { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736, ++ 798, 858, 0, 480, 489, 495, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 720x480@60Hz */ ++ { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736, ++ 798, 858, 0, 480, 489, 495, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1280x720@60Hz */ ++ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390, ++ 1430, 1650, 0, 720, 725, 730, 750, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 1920x1080i@60Hz */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008, ++ 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1440x480i@60Hz */ ++ { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478, ++ 1602, 1716, 0, 480, 488, 494, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1440x480i@60Hz */ ++ { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478, ++ 1602, 1716, 0, 480, 488, 494, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1440x240@60Hz */ ++ { DRM_MODE("1440x240", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478, ++ 1602, 1716, 0, 240, 244, 247, 262, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1440x240@60Hz */ ++ { DRM_MODE("1440x240", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478, ++ 1602, 1716, 0, 240, 244, 247, 262, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 2880x480i@60Hz */ ++ { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956, ++ 3204, 3432, 0, 480, 488, 494, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 2880x480i@60Hz */ ++ { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956, ++ 3204, 3432, 0, 480, 488, 494, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 2880x240@60Hz */ ++ { DRM_MODE("2880x240", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956, ++ 3204, 3432, 0, 240, 244, 247, 262, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 2880x240@60Hz */ ++ { DRM_MODE("2880x240", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956, ++ 3204, 3432, 0, 240, 244, 247, 262, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1440x480@60Hz */ ++ { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1472, ++ 1596, 1716, 0, 480, 489, 495, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1440x480@60Hz */ ++ { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1472, ++ 1596, 1716, 0, 480, 489, 495, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1920x1080@60Hz */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008, ++ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 720x576@50Hz */ ++ { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732, ++ 796, 864, 0, 576, 581, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 720x576@50Hz */ ++ { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732, ++ 796, 864, 0, 576, 581, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1280x720@50Hz */ ++ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720, ++ 1760, 1980, 0, 720, 725, 730, 750, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 1920x1080i@50Hz */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448, ++ 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1440x576i@50Hz */ ++ { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464, ++ 1590, 1728, 0, 576, 580, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1440x576i@50Hz */ ++ { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464, ++ 1590, 1728, 0, 576, 580, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1440x288@50Hz */ ++ { DRM_MODE("1440x288", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464, ++ 1590, 1728, 0, 288, 290, 293, 312, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1440x288@50Hz */ ++ { DRM_MODE("1440x288", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464, ++ 1590, 1728, 0, 288, 290, 293, 312, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 2880x576i@50Hz */ ++ { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928, ++ 3180, 3456, 0, 576, 580, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 2880x576i@50Hz */ ++ { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928, ++ 3180, 3456, 0, 576, 580, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 2880x288@50Hz */ ++ { DRM_MODE("2880x288", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928, ++ 3180, 3456, 0, 288, 290, 293, 312, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 2880x288@50Hz */ ++ { DRM_MODE("2880x288", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928, ++ 3180, 3456, 0, 288, 290, 293, 312, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1440x576@50Hz */ ++ { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464, ++ 1592, 1728, 0, 576, 581, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1440x576@50Hz */ ++ { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464, ++ 1592, 1728, 0, 576, 581, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1920x1080@50Hz */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448, ++ 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 1920x1080@24Hz */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558, ++ 2602, 2750, 0, 1080, 1084, 1089, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 1920x1080@25Hz */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448, ++ 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 1920x1080@30Hz */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008, ++ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 2880x480@60Hz */ ++ { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2944, ++ 3192, 3432, 0, 480, 489, 495, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 2880x480@60Hz */ ++ { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2944, ++ 3192, 3432, 0, 480, 489, 495, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 2880x576@50Hz */ ++ { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2928, ++ 3184, 3456, 0, 576, 581, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 2880x576@50Hz */ ++ { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2928, ++ 3184, 3456, 0, 576, 581, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1920x1080i@50Hz */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 72000, 1920, 1952, ++ 2120, 2304, 0, 1080, 1126, 1136, 1250, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1920x1080i@100Hz */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448, ++ 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1280x720@100Hz */ ++ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1720, ++ 1760, 1980, 0, 720, 725, 730, 750, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 720x576@100Hz */ ++ { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 54000, 720, 732, ++ 796, 864, 0, 576, 581, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 720x576@100Hz */ ++ { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 54000, 720, 732, ++ 796, 864, 0, 576, 581, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1440x576i@100Hz */ ++ { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464, ++ 1590, 1728, 0, 576, 580, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1440x576i@100Hz */ ++ { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464, ++ 1590, 1728, 0, 576, 580, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1920x1080i@120Hz */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008, ++ 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1280x720@120Hz */ ++ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1390, ++ 1430, 1650, 0, 720, 725, 730, 750, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 720x480@120Hz */ ++ { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 54000, 720, 736, ++ 798, 858, 0, 480, 489, 495, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 720x480@120Hz */ ++ { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 54000, 720, 736, ++ 798, 858, 0, 480, 489, 495, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1440x480i@120Hz */ ++ { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478, ++ 1602, 1716, 0, 480, 488, 494, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1440x480i@120Hz */ ++ { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478, ++ 1602, 1716, 0, 480, 488, 494, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 720x576@200Hz */ ++ { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 108000, 720, 732, ++ 796, 864, 0, 576, 581, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 720x576@200Hz */ ++ { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 108000, 720, 732, ++ 796, 864, 0, 576, 581, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1440x576i@200Hz */ ++ { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464, ++ 1590, 1728, 0, 576, 580, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1440x576i@200Hz */ ++ { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464, ++ 1590, 1728, 0, 576, 580, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 720x480@240Hz */ ++ { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 108000, 720, 736, ++ 798, 858, 0, 480, 489, 495, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 720x480@240Hz */ ++ { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 108000, 720, 736, ++ 798, 858, 0, 480, 489, 495, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, ++ /* 1440x480i@240 */ ++ { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478, ++ 1602, 1716, 0, 480, 488, 494, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1440x480i@240 */ ++ { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478, ++ 1602, 1716, 0, 480, 488, 494, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | ++ DRM_MODE_FLAG_INTERLACE) }, ++ /* 1280x720@24Hz */ ++ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 59400, 1280, 3040, ++ 3080, 3300, 0, 720, 725, 730, 750, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 1280x720@25Hz */ ++ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3700, ++ 3740, 3960, 0, 720, 725, 730, 750, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 1280x720@30Hz */ ++ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3040, ++ 3080, 3300, 0, 720, 725, 730, 750, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 1920x1080@120Hz */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2008, ++ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ /* 1920x1080@100Hz */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448, ++ 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++}; ++static const int drm_num_cea_modes = ++ sizeof (edid_cea_modes) / sizeof (edid_cea_modes[0]); +diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c +index dd58373..a0d6e89 100644 +--- a/drivers/gpu/drm/drm_fb_helper.c ++++ b/drivers/gpu/drm/drm_fb_helper.c +@@ -255,6 +255,13 @@ bool drm_fb_helper_force_kernel_mode(void) + int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed, + void *panic_str) + { ++ /* ++ * It's a waste of time and effort to switch back to text console ++ * if the kernel should reboot before panic messages can be seen. ++ */ ++ if (panic_timeout < 0) ++ return 0; ++ + printk(KERN_ERR "panic occurred, switching back to text console\n"); + return drm_fb_helper_force_kernel_mode(); + } +@@ -299,91 +306,31 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { + static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { }; + #endif + +-static void drm_fb_helper_on(struct fb_info *info) +-{ +- struct drm_fb_helper *fb_helper = info->par; +- struct drm_device *dev = fb_helper->dev; +- struct drm_crtc *crtc; +- struct drm_crtc_helper_funcs *crtc_funcs; +- struct drm_connector *connector; +- struct drm_encoder *encoder; +- int i, j; +- +- /* +- * For each CRTC in this fb, turn the crtc on then, +- * find all associated encoders and turn them on. +- */ +- mutex_lock(&dev->mode_config.mutex); +- for (i = 0; i < fb_helper->crtc_count; i++) { +- crtc = fb_helper->crtc_info[i].mode_set.crtc; +- crtc_funcs = crtc->helper_private; +- +- if (!crtc->enabled) +- continue; +- +- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); +- +- /* Walk the connectors & encoders on this fb turning them on */ +- for (j = 0; j < fb_helper->connector_count; j++) { +- connector = fb_helper->connector_info[j]->connector; +- connector->dpms = DRM_MODE_DPMS_ON; +- drm_connector_property_set_value(connector, +- dev->mode_config.dpms_property, +- DRM_MODE_DPMS_ON); +- } +- /* Found a CRTC on this fb, now find encoders */ +- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { +- if (encoder->crtc == crtc) { +- struct drm_encoder_helper_funcs *encoder_funcs; +- +- encoder_funcs = encoder->helper_private; +- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); +- } +- } +- } +- mutex_unlock(&dev->mode_config.mutex); +-} +- +-static void drm_fb_helper_off(struct fb_info *info, int dpms_mode) ++static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) + { + struct drm_fb_helper *fb_helper = info->par; + struct drm_device *dev = fb_helper->dev; + struct drm_crtc *crtc; +- struct drm_crtc_helper_funcs *crtc_funcs; + struct drm_connector *connector; +- struct drm_encoder *encoder; + int i, j; + + /* +- * For each CRTC in this fb, find all associated encoders +- * and turn them off, then turn off the CRTC. ++ * For each CRTC in this fb, turn the connectors on/off. + */ + mutex_lock(&dev->mode_config.mutex); + for (i = 0; i < fb_helper->crtc_count; i++) { + crtc = fb_helper->crtc_info[i].mode_set.crtc; +- crtc_funcs = crtc->helper_private; + + if (!crtc->enabled) + continue; + +- /* Walk the connectors on this fb and mark them off */ ++ /* Walk the connectors & encoders on this fb turning them on/off */ + for (j = 0; j < fb_helper->connector_count; j++) { + connector = fb_helper->connector_info[j]->connector; +- connector->dpms = dpms_mode; ++ drm_helper_connector_dpms(connector, dpms_mode); + drm_connector_property_set_value(connector, +- dev->mode_config.dpms_property, +- dpms_mode); ++ dev->mode_config.dpms_property, dpms_mode); + } +- /* Found a CRTC on this fb, now find encoders */ +- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { +- if (encoder->crtc == crtc) { +- struct drm_encoder_helper_funcs *encoder_funcs; +- +- encoder_funcs = encoder->helper_private; +- encoder_funcs->dpms(encoder, dpms_mode); +- } +- } +- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); + } + mutex_unlock(&dev->mode_config.mutex); + } +@@ -393,23 +340,23 @@ int drm_fb_helper_blank(int blank, struct fb_info *info) + switch (blank) { + /* Display: On; HSync: On, VSync: On */ + case FB_BLANK_UNBLANK: +- drm_fb_helper_on(info); ++ drm_fb_helper_dpms(info, DRM_MODE_DPMS_ON); + break; + /* Display: Off; HSync: On, VSync: On */ + case FB_BLANK_NORMAL: +- drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY); ++ drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY); + break; + /* Display: Off; HSync: Off, VSync: On */ + case FB_BLANK_HSYNC_SUSPEND: +- drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY); ++ drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY); + break; + /* Display: Off; HSync: On, VSync: Off */ + case FB_BLANK_VSYNC_SUSPEND: +- drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND); ++ drm_fb_helper_dpms(info, DRM_MODE_DPMS_SUSPEND); + break; + /* Display: Off; HSync: Off, VSync: Off */ + case FB_BLANK_POWERDOWN: +- drm_fb_helper_off(info, DRM_MODE_DPMS_OFF); ++ drm_fb_helper_dpms(info, DRM_MODE_DPMS_OFF); + break; + } + return 0; +@@ -423,8 +370,11 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) + for (i = 0; i < helper->connector_count; i++) + kfree(helper->connector_info[i]); + kfree(helper->connector_info); +- for (i = 0; i < helper->crtc_count; i++) ++ for (i = 0; i < helper->crtc_count; i++) { + kfree(helper->crtc_info[i].mode_set.connectors); ++ if (helper->crtc_info[i].mode_set.mode) ++ drm_mode_destroy(helper->dev, helper->crtc_info[i].mode_set.mode); ++ } + kfree(helper->crtc_info); + } + +@@ -467,11 +417,10 @@ int drm_fb_helper_init(struct drm_device *dev, + + i = 0; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { +- fb_helper->crtc_info[i].crtc_id = crtc->base.id; + fb_helper->crtc_info[i].mode_set.crtc = crtc; + i++; + } +- fb_helper->conn_limit = max_conn_count; ++ + return 0; + out_free: + drm_fb_helper_crtc_free(fb_helper); +diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c +index 020b103..0a2e3fe 100644 +--- a/drivers/gpu/drm/drm_fops.c ++++ b/drivers/gpu/drm/drm_fops.c +@@ -133,6 +133,9 @@ int drm_open(struct inode *inode, struct file *filp) + if (!(dev = minor->dev)) + return -ENODEV; + ++ if (drm_device_is_unplugged(dev)) ++ return -ENODEV; ++ + retcode = drm_open_helper(inode, filp, dev); + if (!retcode) { + atomic_inc(&dev->counts[_DRM_STAT_OPENS]); +@@ -184,8 +187,11 @@ int drm_stub_open(struct inode *inode, struct file *filp) + if (!(dev = minor->dev)) + goto out; + ++ if (drm_device_is_unplugged(dev)) ++ goto out; ++ + old_fops = filp->f_op; +- filp->f_op = fops_get(&dev->driver->fops); ++ filp->f_op = fops_get(dev->driver->fops); + if (filp->f_op == NULL) { + filp->f_op = old_fops; + goto out; +@@ -501,12 +507,12 @@ int drm_release(struct inode *inode, struct file *filp) + + drm_events_release(file_priv); + +- if (dev->driver->driver_features & DRIVER_GEM) +- drm_gem_release(dev, file_priv); +- + if (dev->driver->driver_features & DRIVER_MODESET) + drm_fb_release(file_priv); + ++ if (dev->driver->driver_features & DRIVER_GEM) ++ drm_gem_release(dev, file_priv); ++ + mutex_lock(&dev->ctxlist_mutex); + if (!list_empty(&dev->ctxlist)) { + struct drm_ctx_list *pos, *n; +@@ -582,6 +588,8 @@ int drm_release(struct inode *inode, struct file *filp) + retcode = -EBUSY; + } else + retcode = drm_lastclose(dev); ++ if (drm_device_is_unplugged(dev)) ++ drm_put_dev(dev); + } + mutex_unlock(&drm_global_mutex); + +diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c +index 396e60c..0ef358e 100644 +--- a/drivers/gpu/drm/drm_gem.c ++++ b/drivers/gpu/drm/drm_gem.c +@@ -140,7 +140,7 @@ int drm_gem_object_init(struct drm_device *dev, + obj->dev = dev; + obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE); + if (IS_ERR(obj->filp)) +- return -ENOMEM; ++ return PTR_ERR(obj->filp); + + kref_init(&obj->refcount); + atomic_set(&obj->handle_count, 0); +@@ -661,6 +661,9 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) + struct drm_hash_item *hash; + int ret = 0; + ++ if (drm_device_is_unplugged(dev)) ++ return -ENODEV; ++ + mutex_lock(&dev->struct_mutex); + + if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) { +@@ -700,7 +703,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) + */ + drm_gem_object_reference(obj); + +- vma->vm_file = filp; /* Needed for drm_vm_open() */ + drm_vm_open_locked(vma); + + out_unlock: +diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c +index ddd70db..637fcc3 100644 +--- a/drivers/gpu/drm/drm_ioc32.c ++++ b/drivers/gpu/drm/drm_ioc32.c +@@ -315,7 +315,8 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd, + if (err) + return err; + +- if (__get_user(c32.auth, &client->auth) ++ if (__get_user(c32.idx, &client->idx) ++ || __get_user(c32.auth, &client->auth) + || __get_user(c32.pid, &client->pid) + || __get_user(c32.uid, &client->uid) + || __get_user(c32.magic, &client->magic) +diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c +index 904d7e9..cf85155 100644 +--- a/drivers/gpu/drm/drm_ioctl.c ++++ b/drivers/gpu/drm/drm_ioctl.c +@@ -37,6 +37,7 @@ + #include "drm_core.h" + + #include "linux/pci.h" ++#include "linux/export.h" + + /** + * Get the bus id. +@@ -158,14 +159,11 @@ int drm_getmap(struct drm_device *dev, void *data, + int i; + + idx = map->offset; +- +- mutex_lock(&dev->struct_mutex); +- if (idx < 0) { +- mutex_unlock(&dev->struct_mutex); ++ if (idx < 0) + return -EINVAL; +- } + + i = 0; ++ mutex_lock(&dev->struct_mutex); + list_for_each(list, &dev->maplist) { + if (i == idx) { + r_list = list_entry(list, struct drm_map_list, head); +@@ -211,9 +209,9 @@ int drm_getclient(struct drm_device *dev, void *data, + int i; + + idx = client->idx; +- mutex_lock(&dev->struct_mutex); +- + i = 0; ++ ++ mutex_lock(&dev->struct_mutex); + list_for_each_entry(pt, &dev->filelist, lhead) { + if (i++ >= idx) { + client->auth = pt->authenticated; +@@ -249,8 +247,6 @@ int drm_getstats(struct drm_device *dev, void *data, + + memset(stats, 0, sizeof(*stats)); + +- mutex_lock(&dev->struct_mutex); +- + for (i = 0; i < dev->counters; i++) { + if (dev->types[i] == _DRM_STAT_LOCK) + stats->data[i].value = +@@ -262,8 +258,6 @@ int drm_getstats(struct drm_device *dev, void *data, + + stats->count = dev->counters; + +- mutex_unlock(&dev->struct_mutex); +- + return 0; + } + +@@ -283,6 +277,12 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv) + case DRM_CAP_VBLANK_HIGH_CRTC: + req->value = 1; + break; ++ case DRM_CAP_DUMB_PREFERRED_DEPTH: ++ req->value = dev->mode_config.preferred_depth; ++ break; ++ case DRM_CAP_DUMB_PREFER_SHADOW: ++ req->value = dev->mode_config.prefer_shadow; ++ break; + default: + return -EINVAL; + } +@@ -353,3 +353,4 @@ int drm_noop(struct drm_device *dev, void *data, + DRM_DEBUG("\n"); + return 0; + } ++EXPORT_SYMBOL(drm_noop); +diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c +index 73af885..dc33ba5 100644 +--- a/drivers/gpu/drm/drm_irq.c ++++ b/drivers/gpu/drm/drm_irq.c +@@ -305,7 +305,7 @@ static void drm_irq_vgaarb_nokms(void *cookie, bool state) + * \param dev DRM device. + * + * Initializes the IRQ related data. Installs the handler, calling the driver +- * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions ++ * \c irq_preinstall() and \c irq_postinstall() functions + * before and after the installation. + */ + int drm_irq_install(struct drm_device *dev) +@@ -385,7 +385,7 @@ EXPORT_SYMBOL(drm_irq_install); + * + * \param dev DRM device. + * +- * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq. ++ * Calls the driver's \c irq_uninstall() function, and stops the irq. + */ + int drm_irq_uninstall(struct drm_device *dev) + { +diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c +index 632ae24..c79c713 100644 +--- a/drivers/gpu/drm/drm_lock.c ++++ b/drivers/gpu/drm/drm_lock.c +@@ -33,6 +33,7 @@ + * OTHER DEALINGS IN THE SOFTWARE. + */ + ++#include + #include "drmP.h" + + static int drm_notifier(void *priv); +@@ -345,6 +346,7 @@ void drm_idlelock_take(struct drm_lock_data *lock_data) + } + spin_unlock_bh(&lock_data->spinlock); + } ++EXPORT_SYMBOL(drm_idlelock_take); + + void drm_idlelock_release(struct drm_lock_data *lock_data) + { +@@ -364,6 +366,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) + } + spin_unlock_bh(&lock_data->spinlock); + } ++EXPORT_SYMBOL(drm_idlelock_release); + + int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv) + { +diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c +index c8b6b66..c86a0f1 100644 +--- a/drivers/gpu/drm/drm_memory.c ++++ b/drivers/gpu/drm/drm_memory.c +@@ -37,25 +37,6 @@ + #include + #include "drmP.h" + +-/** +- * Called when "/proc/dri/%dev%/mem" is read. +- * +- * \param buf output buffer. +- * \param start start of output data. +- * \param offset requested start offset. +- * \param len requested number of bytes. +- * \param eof whether there is no more data to return. +- * \param data private data. +- * \return number of written bytes. +- * +- * No-op. +- */ +-int drm_mem_info(char *buf, char **start, off_t offset, +- int len, int *eof, void *data) +-{ +- return 0; +-} +- + #if __OS_HAS_AGP + static void *agp_remap(unsigned long offset, unsigned long size, + struct drm_device * dev) +diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c +index 961fb54..7f88de6 100644 +--- a/drivers/gpu/drm/drm_mm.c ++++ b/drivers/gpu/drm/drm_mm.c +@@ -680,33 +680,35 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) + EXPORT_SYMBOL(drm_mm_debug_table); + + #if defined(CONFIG_DEBUG_FS) +-int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) ++static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry) + { +- struct drm_mm_node *entry; +- unsigned long total_used = 0, total_free = 0, total = 0; + unsigned long hole_start, hole_end, hole_size; + +- hole_start = drm_mm_hole_node_start(&mm->head_node); +- hole_end = drm_mm_hole_node_end(&mm->head_node); +- hole_size = hole_end - hole_start; +- if (hole_size) ++ if (entry->hole_follows) { ++ hole_start = drm_mm_hole_node_start(entry); ++ hole_end = drm_mm_hole_node_end(entry); ++ hole_size = hole_end - hole_start; + seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", + hole_start, hole_end, hole_size); +- total_free += hole_size; ++ return hole_size; ++ } ++ ++ return 0; ++} ++ ++int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) ++{ ++ struct drm_mm_node *entry; ++ unsigned long total_used = 0, total_free = 0, total = 0; ++ ++ total_free += drm_mm_dump_hole(m, &mm->head_node); + + drm_mm_for_each_node(entry, mm) { + seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n", + entry->start, entry->start + entry->size, + entry->size); + total_used += entry->size; +- if (entry->hole_follows) { +- hole_start = drm_mm_hole_node_start(entry); +- hole_end = drm_mm_hole_node_end(entry); +- hole_size = hole_end - hole_start; +- seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", +- hole_start, hole_end, hole_size); +- total_free += hole_size; +- } ++ total_free += drm_mm_dump_hole(m, entry); + } + total = total_free + total_used; + +diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c +index fb8e46b..b7adb4a 100644 +--- a/drivers/gpu/drm/drm_modes.c ++++ b/drivers/gpu/drm/drm_modes.c +@@ -686,8 +686,6 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags) + p->crtc_vsync_end /= 2; + p->crtc_vtotal /= 2; + } +- +- p->crtc_vtotal |= 1; + } + + if (p->flags & DRM_MODE_FLAG_DBLSCAN) { +@@ -716,6 +714,27 @@ EXPORT_SYMBOL(drm_mode_set_crtcinfo); + + + /** ++ * drm_mode_copy - copy the mode ++ * @dst: mode to overwrite ++ * @src: mode to copy ++ * ++ * LOCKING: ++ * None. ++ * ++ * Copy an existing mode into another mode, preserving the object id ++ * of the destination mode. ++ */ ++void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src) ++{ ++ int id = dst->base.id; ++ ++ *dst = *src; ++ dst->base.id = id; ++ INIT_LIST_HEAD(&dst->head); ++} ++EXPORT_SYMBOL(drm_mode_copy); ++ ++/** + * drm_mode_duplicate - allocate and duplicate an existing mode + * @m: mode to duplicate + * +@@ -729,16 +748,13 @@ struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, + const struct drm_display_mode *mode) + { + struct drm_display_mode *nmode; +- int new_id; + + nmode = drm_mode_create(dev); + if (!nmode) + return NULL; + +- new_id = nmode->base.id; +- *nmode = *mode; +- nmode->base.id = new_id; +- INIT_LIST_HEAD(&nmode->head); ++ drm_mode_copy(nmode, mode); ++ + return nmode; + } + EXPORT_SYMBOL(drm_mode_duplicate); +diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c +index d4d10b7..13f3d93 100644 +--- a/drivers/gpu/drm/drm_pci.c ++++ b/drivers/gpu/drm/drm_pci.c +@@ -324,8 +324,6 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, + if (ret) + goto err_g1; + +- pci_set_master(pdev); +- + dev->pdev = pdev; + dev->dev = &pdev->dev; + +diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c +index ae9db5e..82431dc 100644 +--- a/drivers/gpu/drm/drm_platform.c ++++ b/drivers/gpu/drm/drm_platform.c +@@ -122,7 +122,7 @@ static const char *drm_platform_get_name(struct drm_device *dev) + + static int drm_platform_set_busid(struct drm_device *dev, struct drm_master *master) + { +- int len, ret; ++ int len, ret, id; + + master->unique_len = 13 + strlen(dev->platformdev->name); + master->unique_size = master->unique_len; +@@ -131,8 +131,16 @@ static int drm_platform_set_busid(struct drm_device *dev, struct drm_master *mas + if (master->unique == NULL) + return -ENOMEM; + ++ id = dev->platformdev->id; ++ ++ /* if only a single instance of the platform device, id will be ++ * set to -1.. use 0 instead to avoid a funny looking bus-id: ++ */ ++ if (id == -1) ++ id = 0; ++ + len = snprintf(master->unique, master->unique_len, +- "platform:%s:%02d", dev->platformdev->name, dev->platformdev->id); ++ "platform:%s:%02d", dev->platformdev->name, id); + + if (len > master->unique_len) { + DRM_ERROR("Unique buffer overflowed\n"); +diff --git a/drivers/gpu/drm/drm_sman.c b/drivers/gpu/drm/drm_sman.c +deleted file mode 100644 +index cebce45..0000000 +--- a/drivers/gpu/drm/drm_sman.c ++++ /dev/null +@@ -1,351 +0,0 @@ +-/************************************************************************** +- * +- * Copyright 2006 Tungsten Graphics, Inc., Bismarck., ND., USA. +- * All Rights Reserved. +- * +- * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. +- * +- * The above copyright notice and this permission notice (including the +- * next paragraph) shall be included in all copies or substantial portions +- * of the Software. +- * +- * +- **************************************************************************/ +-/* +- * Simple memory manager interface that keeps track on allocate regions on a +- * per "owner" basis. All regions associated with an "owner" can be released +- * with a simple call. Typically if the "owner" exists. The owner is any +- * "unsigned long" identifier. Can typically be a pointer to a file private +- * struct or a context identifier. +- * +- * Authors: +- * Thomas Hellström +- */ +- +-#include +-#include "drm_sman.h" +- +-struct drm_owner_item { +- struct drm_hash_item owner_hash; +- struct list_head sman_list; +- struct list_head mem_blocks; +-}; +- +-void drm_sman_takedown(struct drm_sman * sman) +-{ +- drm_ht_remove(&sman->user_hash_tab); +- drm_ht_remove(&sman->owner_hash_tab); +- kfree(sman->mm); +-} +- +-EXPORT_SYMBOL(drm_sman_takedown); +- +-int +-drm_sman_init(struct drm_sman * sman, unsigned int num_managers, +- unsigned int user_order, unsigned int owner_order) +-{ +- int ret = 0; +- +- sman->mm = kcalloc(num_managers, sizeof(*sman->mm), GFP_KERNEL); +- if (!sman->mm) { +- ret = -ENOMEM; +- goto out; +- } +- sman->num_managers = num_managers; +- INIT_LIST_HEAD(&sman->owner_items); +- ret = drm_ht_create(&sman->owner_hash_tab, owner_order); +- if (ret) +- goto out1; +- ret = drm_ht_create(&sman->user_hash_tab, user_order); +- if (!ret) +- goto out; +- +- drm_ht_remove(&sman->owner_hash_tab); +-out1: +- kfree(sman->mm); +-out: +- return ret; +-} +- +-EXPORT_SYMBOL(drm_sman_init); +- +-static void *drm_sman_mm_allocate(void *private, unsigned long size, +- unsigned alignment) +-{ +- struct drm_mm *mm = (struct drm_mm *) private; +- struct drm_mm_node *tmp; +- +- tmp = drm_mm_search_free(mm, size, alignment, 1); +- if (!tmp) { +- return NULL; +- } +- tmp = drm_mm_get_block(tmp, size, alignment); +- return tmp; +-} +- +-static void drm_sman_mm_free(void *private, void *ref) +-{ +- struct drm_mm_node *node = (struct drm_mm_node *) ref; +- +- drm_mm_put_block(node); +-} +- +-static void drm_sman_mm_destroy(void *private) +-{ +- struct drm_mm *mm = (struct drm_mm *) private; +- drm_mm_takedown(mm); +- kfree(mm); +-} +- +-static unsigned long drm_sman_mm_offset(void *private, void *ref) +-{ +- struct drm_mm_node *node = (struct drm_mm_node *) ref; +- return node->start; +-} +- +-int +-drm_sman_set_range(struct drm_sman * sman, unsigned int manager, +- unsigned long start, unsigned long size) +-{ +- struct drm_sman_mm *sman_mm; +- struct drm_mm *mm; +- int ret; +- +- BUG_ON(manager >= sman->num_managers); +- +- sman_mm = &sman->mm[manager]; +- mm = kzalloc(sizeof(*mm), GFP_KERNEL); +- if (!mm) { +- return -ENOMEM; +- } +- sman_mm->private = mm; +- ret = drm_mm_init(mm, start, size); +- +- if (ret) { +- kfree(mm); +- return ret; +- } +- +- sman_mm->allocate = drm_sman_mm_allocate; +- sman_mm->free = drm_sman_mm_free; +- sman_mm->destroy = drm_sman_mm_destroy; +- sman_mm->offset = drm_sman_mm_offset; +- +- return 0; +-} +- +-EXPORT_SYMBOL(drm_sman_set_range); +- +-int +-drm_sman_set_manager(struct drm_sman * sman, unsigned int manager, +- struct drm_sman_mm * allocator) +-{ +- BUG_ON(manager >= sman->num_managers); +- sman->mm[manager] = *allocator; +- +- return 0; +-} +-EXPORT_SYMBOL(drm_sman_set_manager); +- +-static struct drm_owner_item *drm_sman_get_owner_item(struct drm_sman * sman, +- unsigned long owner) +-{ +- int ret; +- struct drm_hash_item *owner_hash_item; +- struct drm_owner_item *owner_item; +- +- ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item); +- if (!ret) { +- return drm_hash_entry(owner_hash_item, struct drm_owner_item, +- owner_hash); +- } +- +- owner_item = kzalloc(sizeof(*owner_item), GFP_KERNEL); +- if (!owner_item) +- goto out; +- +- INIT_LIST_HEAD(&owner_item->mem_blocks); +- owner_item->owner_hash.key = owner; +- if (drm_ht_insert_item(&sman->owner_hash_tab, &owner_item->owner_hash)) +- goto out1; +- +- list_add_tail(&owner_item->sman_list, &sman->owner_items); +- return owner_item; +- +-out1: +- kfree(owner_item); +-out: +- return NULL; +-} +- +-struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int manager, +- unsigned long size, unsigned alignment, +- unsigned long owner) +-{ +- void *tmp; +- struct drm_sman_mm *sman_mm; +- struct drm_owner_item *owner_item; +- struct drm_memblock_item *memblock; +- +- BUG_ON(manager >= sman->num_managers); +- +- sman_mm = &sman->mm[manager]; +- tmp = sman_mm->allocate(sman_mm->private, size, alignment); +- +- if (!tmp) { +- return NULL; +- } +- +- memblock = kzalloc(sizeof(*memblock), GFP_KERNEL); +- +- if (!memblock) +- goto out; +- +- memblock->mm_info = tmp; +- memblock->mm = sman_mm; +- memblock->sman = sman; +- +- if (drm_ht_just_insert_please +- (&sman->user_hash_tab, &memblock->user_hash, +- (unsigned long)memblock, 32, 0, 0)) +- goto out1; +- +- owner_item = drm_sman_get_owner_item(sman, owner); +- if (!owner_item) +- goto out2; +- +- list_add_tail(&memblock->owner_list, &owner_item->mem_blocks); +- +- return memblock; +- +-out2: +- drm_ht_remove_item(&sman->user_hash_tab, &memblock->user_hash); +-out1: +- kfree(memblock); +-out: +- sman_mm->free(sman_mm->private, tmp); +- +- return NULL; +-} +- +-EXPORT_SYMBOL(drm_sman_alloc); +- +-static void drm_sman_free(struct drm_memblock_item *item) +-{ +- struct drm_sman *sman = item->sman; +- +- list_del(&item->owner_list); +- drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash); +- item->mm->free(item->mm->private, item->mm_info); +- kfree(item); +-} +- +-int drm_sman_free_key(struct drm_sman *sman, unsigned int key) +-{ +- struct drm_hash_item *hash_item; +- struct drm_memblock_item *memblock_item; +- +- if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item)) +- return -EINVAL; +- +- memblock_item = drm_hash_entry(hash_item, struct drm_memblock_item, +- user_hash); +- drm_sman_free(memblock_item); +- return 0; +-} +- +-EXPORT_SYMBOL(drm_sman_free_key); +- +-static void drm_sman_remove_owner(struct drm_sman *sman, +- struct drm_owner_item *owner_item) +-{ +- list_del(&owner_item->sman_list); +- drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash); +- kfree(owner_item); +-} +- +-int drm_sman_owner_clean(struct drm_sman *sman, unsigned long owner) +-{ +- +- struct drm_hash_item *hash_item; +- struct drm_owner_item *owner_item; +- +- if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) { +- return -1; +- } +- +- owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash); +- if (owner_item->mem_blocks.next == &owner_item->mem_blocks) { +- drm_sman_remove_owner(sman, owner_item); +- return -1; +- } +- +- return 0; +-} +- +-EXPORT_SYMBOL(drm_sman_owner_clean); +- +-static void drm_sman_do_owner_cleanup(struct drm_sman *sman, +- struct drm_owner_item *owner_item) +-{ +- struct drm_memblock_item *entry, *next; +- +- list_for_each_entry_safe(entry, next, &owner_item->mem_blocks, +- owner_list) { +- drm_sman_free(entry); +- } +- drm_sman_remove_owner(sman, owner_item); +-} +- +-void drm_sman_owner_cleanup(struct drm_sman *sman, unsigned long owner) +-{ +- +- struct drm_hash_item *hash_item; +- struct drm_owner_item *owner_item; +- +- if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) { +- +- return; +- } +- +- owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash); +- drm_sman_do_owner_cleanup(sman, owner_item); +-} +- +-EXPORT_SYMBOL(drm_sman_owner_cleanup); +- +-void drm_sman_cleanup(struct drm_sman *sman) +-{ +- struct drm_owner_item *entry, *next; +- unsigned int i; +- struct drm_sman_mm *sman_mm; +- +- list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) { +- drm_sman_do_owner_cleanup(sman, entry); +- } +- if (sman->mm) { +- for (i = 0; i < sman->num_managers; ++i) { +- sman_mm = &sman->mm[i]; +- if (sman_mm->private) { +- sman_mm->destroy(sman_mm->private); +- sman_mm->private = NULL; +- } +- } +- } +-} +- +-EXPORT_SYMBOL(drm_sman_cleanup); +diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c +index 6d7b083..aa454f8 100644 +--- a/drivers/gpu/drm/drm_stub.c ++++ b/drivers/gpu/drm/drm_stub.c +@@ -319,6 +319,7 @@ int drm_fill_in_dev(struct drm_device *dev, + drm_lastclose(dev); + return retcode; + } ++EXPORT_SYMBOL(drm_fill_in_dev); + + + /** +@@ -397,6 +398,7 @@ err_idr: + *minor = NULL; + return ret; + } ++EXPORT_SYMBOL(drm_get_minor); + + /** + * Put a secondary minor number. +@@ -428,6 +430,12 @@ int drm_put_minor(struct drm_minor **minor_p) + *minor_p = NULL; + return 0; + } ++EXPORT_SYMBOL(drm_put_minor); ++ ++static void drm_unplug_minor(struct drm_minor *minor) ++{ ++ drm_sysfs_device_remove(minor); ++} + + /** + * Called via drm_exit() at module unload time or when pci device is +@@ -492,3 +500,21 @@ void drm_put_dev(struct drm_device *dev) + kfree(dev); + } + EXPORT_SYMBOL(drm_put_dev); ++ ++void drm_unplug_dev(struct drm_device *dev) ++{ ++ /* for a USB device */ ++ if (drm_core_check_feature(dev, DRIVER_MODESET)) ++ drm_unplug_minor(dev->control); ++ drm_unplug_minor(dev->primary); ++ ++ mutex_lock(&drm_global_mutex); ++ ++ drm_device_set_unplugged(dev); ++ ++ if (dev->open_count == 0) { ++ drm_put_dev(dev); ++ } ++ mutex_unlock(&drm_global_mutex); ++} ++EXPORT_SYMBOL(drm_unplug_dev); +diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c +index 0f9ef9b..e7101be 100644 +--- a/drivers/gpu/drm/drm_sysfs.c ++++ b/drivers/gpu/drm/drm_sysfs.c +@@ -454,6 +454,8 @@ void drm_sysfs_connector_remove(struct drm_connector *connector) + { + int i; + ++ if (!connector->kdev.parent) ++ return; + DRM_DEBUG("removing \"%s\" from sysfs\n", + drm_get_connector_name(connector)); + +@@ -461,6 +463,7 @@ void drm_sysfs_connector_remove(struct drm_connector *connector) + device_remove_file(&connector->kdev, &connector_attrs[i]); + sysfs_remove_bin_file(&connector->kdev.kobj, &edid_attr); + device_unregister(&connector->kdev); ++ connector->kdev.parent = NULL; + } + EXPORT_SYMBOL(drm_sysfs_connector_remove); + +@@ -533,7 +536,9 @@ err_out: + */ + void drm_sysfs_device_remove(struct drm_minor *minor) + { +- device_unregister(&minor->kdev); ++ if (minor->kdev.parent) ++ device_unregister(&minor->kdev); ++ minor->kdev.parent = NULL; + } + + +diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c +index 471f453..767782a 100644 +--- a/drivers/gpu/drm/drm_usb.c ++++ b/drivers/gpu/drm/drm_usb.c +@@ -1,8 +1,7 @@ + #include "drmP.h" + #include +-#include ++#include + +-#ifdef CONFIG_USB + int drm_get_usb_dev(struct usb_interface *interface, + const struct usb_device_id *id, + struct drm_driver *driver) +@@ -115,4 +114,7 @@ void drm_usb_exit(struct drm_driver *driver, + usb_deregister(udriver); + } + EXPORT_SYMBOL(drm_usb_exit); +-#endif ++ ++MODULE_AUTHOR("David Airlie"); ++MODULE_DESCRIPTION("USB DRM support"); ++MODULE_LICENSE("GPL and additional rights"); +diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c +index 8c03eaf..1495618 100644 +--- a/drivers/gpu/drm/drm_vm.c ++++ b/drivers/gpu/drm/drm_vm.c +@@ -519,7 +519,6 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) + vma->vm_flags |= VM_RESERVED; /* Don't swap */ + vma->vm_flags |= VM_DONTEXPAND; + +- vma->vm_file = filp; /* Needed for drm_vm_open() */ + drm_vm_open_locked(vma); + return 0; + } +@@ -671,7 +670,6 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) + vma->vm_flags |= VM_RESERVED; /* Don't swap */ + vma->vm_flags |= VM_DONTEXPAND; + +- vma->vm_file = filp; /* Needed for drm_vm_open() */ + drm_vm_open_locked(vma); + return 0; + } +@@ -682,6 +680,9 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) + struct drm_device *dev = priv->minor->dev; + int ret; + ++ if (drm_device_is_unplugged(dev)) ++ return -ENODEV; ++ + mutex_lock(&dev->struct_mutex); + ret = drm_mmap_locked(filp, vma); + mutex_unlock(&dev->struct_mutex); +diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig +index 847466a..3343ac4 100644 +--- a/drivers/gpu/drm/exynos/Kconfig ++++ b/drivers/gpu/drm/exynos/Kconfig +@@ -1,7 +1,6 @@ + config DRM_EXYNOS + tristate "DRM Support for Samsung SoC EXYNOS Series" + depends on DRM && PLAT_SAMSUNG +- default n + select DRM_KMS_HELPER + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA +@@ -12,9 +11,19 @@ config DRM_EXYNOS + If M is selected the module will be called exynosdrm. + + config DRM_EXYNOS_FIMD +- tristate "Exynos DRM FIMD" +- depends on DRM_EXYNOS +- default n ++ bool "Exynos DRM FIMD" ++ depends on DRM_EXYNOS && !FB_S3C + help + Choose this option if you want to use Exynos FIMD for DRM. +- If M is selected, the module will be called exynos_drm_fimd ++ ++config DRM_EXYNOS_HDMI ++ bool "Exynos DRM HDMI" ++ depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV ++ help ++ Choose this option if you want to use Exynos HDMI for DRM. ++ ++config DRM_EXYNOS_VIDI ++ bool "Exynos DRM Virtual Display" ++ depends on DRM_EXYNOS ++ help ++ Choose this option if you want to use Exynos VIDI for DRM. +diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile +index 0496d3f..9e0bff8 100644 +--- a/drivers/gpu/drm/exynos/Makefile ++++ b/drivers/gpu/drm/exynos/Makefile +@@ -5,7 +5,13 @@ + ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos + exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \ + exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \ +- exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o ++ exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \ ++ exynos_drm_plane.o + +-obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o +-obj-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o ++exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o ++exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o \ ++ exynos_ddc.o exynos_hdmiphy.o \ ++ exynos_drm_hdmi.o ++exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o ++ ++obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o +diff --git a/drivers/gpu/drm/exynos/exynos_ddc.c b/drivers/gpu/drm/exynos/exynos_ddc.c +new file mode 100644 +index 0000000..7e1051d +--- /dev/null ++++ b/drivers/gpu/drm/exynos/exynos_ddc.c +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (C) 2011 Samsung Electronics Co.Ltd ++ * Authors: ++ * Seung-Woo Kim ++ * Inki Dae ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the 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 "drmP.h" ++ ++#include ++#include ++#include ++ ++ ++#include "exynos_drm_drv.h" ++#include "exynos_hdmi.h" ++ ++static int s5p_ddc_probe(struct i2c_client *client, ++ const struct i2c_device_id *dev_id) ++{ ++ hdmi_attach_ddc_client(client); ++ ++ dev_info(&client->adapter->dev, "attached s5p_ddc " ++ "into i2c adapter successfully\n"); ++ ++ return 0; ++} ++ ++static int s5p_ddc_remove(struct i2c_client *client) ++{ ++ dev_info(&client->adapter->dev, "detached s5p_ddc " ++ "from i2c adapter successfully\n"); ++ ++ return 0; ++} ++ ++static struct i2c_device_id ddc_idtable[] = { ++ {"s5p_ddc", 0}, ++ { }, ++}; ++ ++struct i2c_driver ddc_driver = { ++ .driver = { ++ .name = "s5p_ddc", ++ .owner = THIS_MODULE, ++ }, ++ .id_table = ddc_idtable, ++ .probe = s5p_ddc_probe, ++ .remove = __devexit_p(s5p_ddc_remove), ++ .command = NULL, ++}; +diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c +index 2bb07bc..de8d209 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_buf.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c +@@ -25,45 +25,142 @@ + + #include "drmP.h" + #include "drm.h" ++#include "exynos_drm.h" + + #include "exynos_drm_drv.h" + #include "exynos_drm_gem.h" + #include "exynos_drm_buf.h" + + static int lowlevel_buffer_allocate(struct drm_device *dev, +- struct exynos_drm_gem_buf *buffer) ++ unsigned int flags, struct exynos_drm_gem_buf *buf) + { ++ dma_addr_t start_addr; ++ unsigned int npages, page_size, i = 0; ++ struct scatterlist *sgl; ++ int ret = 0; ++ + DRM_DEBUG_KMS("%s\n", __FILE__); + +- buffer->kvaddr = dma_alloc_writecombine(dev->dev, buffer->size, +- &buffer->dma_addr, GFP_KERNEL); +- if (!buffer->kvaddr) { +- DRM_ERROR("failed to allocate buffer.\n"); ++ if (IS_NONCONTIG_BUFFER(flags)) { ++ DRM_DEBUG_KMS("not support allocation type.\n"); ++ return -EINVAL; ++ } ++ ++ if (buf->dma_addr) { ++ DRM_DEBUG_KMS("already allocated.\n"); ++ return 0; ++ } ++ ++ if (buf->size >= SZ_1M) { ++ npages = buf->size >> SECTION_SHIFT; ++ page_size = SECTION_SIZE; ++ } else if (buf->size >= SZ_64K) { ++ npages = buf->size >> 16; ++ page_size = SZ_64K; ++ } else { ++ npages = buf->size >> PAGE_SHIFT; ++ page_size = PAGE_SIZE; ++ } ++ ++ buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); ++ if (!buf->sgt) { ++ DRM_ERROR("failed to allocate sg table.\n"); + return -ENOMEM; + } + +- DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", +- (unsigned long)buffer->kvaddr, +- (unsigned long)buffer->dma_addr, +- buffer->size); ++ ret = sg_alloc_table(buf->sgt, npages, GFP_KERNEL); ++ if (ret < 0) { ++ DRM_ERROR("failed to initialize sg table.\n"); ++ kfree(buf->sgt); ++ buf->sgt = NULL; ++ return -ENOMEM; ++ } + +- return 0; ++ buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size, ++ &buf->dma_addr, GFP_KERNEL); ++ if (!buf->kvaddr) { ++ DRM_ERROR("failed to allocate buffer.\n"); ++ ret = -ENOMEM; ++ goto err1; ++ } ++ ++ buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL); ++ if (!buf->pages) { ++ DRM_ERROR("failed to allocate pages.\n"); ++ ret = -ENOMEM; ++ goto err2; ++ } ++ ++ sgl = buf->sgt->sgl; ++ start_addr = buf->dma_addr; ++ ++ while (i < npages) { ++ buf->pages[i] = phys_to_page(start_addr); ++ sg_set_page(sgl, buf->pages[i], page_size, 0); ++ sg_dma_address(sgl) = start_addr; ++ start_addr += page_size; ++ sgl = sg_next(sgl); ++ i++; ++ } ++ ++ DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", ++ (unsigned long)buf->kvaddr, ++ (unsigned long)buf->dma_addr, ++ buf->size); ++ ++ return ret; ++err2: ++ dma_free_writecombine(dev->dev, buf->size, buf->kvaddr, ++ (dma_addr_t)buf->dma_addr); ++ buf->dma_addr = (dma_addr_t)NULL; ++err1: ++ sg_free_table(buf->sgt); ++ kfree(buf->sgt); ++ buf->sgt = NULL; ++ ++ return ret; + } + + static void lowlevel_buffer_deallocate(struct drm_device *dev, +- struct exynos_drm_gem_buf *buffer) ++ unsigned int flags, struct exynos_drm_gem_buf *buf) + { + DRM_DEBUG_KMS("%s.\n", __FILE__); + +- if (buffer->dma_addr && buffer->size) +- dma_free_writecombine(dev->dev, buffer->size, buffer->kvaddr, +- (dma_addr_t)buffer->dma_addr); +- else +- DRM_DEBUG_KMS("buffer data are invalid.\n"); ++ /* ++ * release only physically continuous memory and ++ * non-continuous memory would be released by exynos ++ * gem framework. ++ */ ++ if (IS_NONCONTIG_BUFFER(flags)) { ++ DRM_DEBUG_KMS("not support allocation type.\n"); ++ return; ++ } ++ ++ if (!buf->dma_addr) { ++ DRM_DEBUG_KMS("dma_addr is invalid.\n"); ++ return; ++ } ++ ++ DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", ++ (unsigned long)buf->kvaddr, ++ (unsigned long)buf->dma_addr, ++ buf->size); ++ ++ sg_free_table(buf->sgt); ++ ++ kfree(buf->sgt); ++ buf->sgt = NULL; ++ ++ kfree(buf->pages); ++ buf->pages = NULL; ++ ++ dma_free_writecombine(dev->dev, buf->size, buf->kvaddr, ++ (dma_addr_t)buf->dma_addr); ++ buf->dma_addr = (dma_addr_t)NULL; + } + +-struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev, +- unsigned int size) ++struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev, ++ unsigned int size) + { + struct exynos_drm_gem_buf *buffer; + +@@ -73,26 +170,15 @@ struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev, + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) { + DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n"); +- return ERR_PTR(-ENOMEM); ++ return NULL; + } + + buffer->size = size; +- +- /* +- * allocate memory region with size and set the memory information +- * to vaddr and dma_addr of a buffer object. +- */ +- if (lowlevel_buffer_allocate(dev, buffer) < 0) { +- kfree(buffer); +- buffer = NULL; +- return ERR_PTR(-ENOMEM); +- } +- + return buffer; + } + +-void exynos_drm_buf_destroy(struct drm_device *dev, +- struct exynos_drm_gem_buf *buffer) ++void exynos_drm_fini_buf(struct drm_device *dev, ++ struct exynos_drm_gem_buf *buffer) + { + DRM_DEBUG_KMS("%s.\n", __FILE__); + +@@ -101,12 +187,27 @@ void exynos_drm_buf_destroy(struct drm_device *dev, + return; + } + +- lowlevel_buffer_deallocate(dev, buffer); +- + kfree(buffer); + buffer = NULL; + } + +-MODULE_AUTHOR("Inki Dae "); +-MODULE_DESCRIPTION("Samsung SoC DRM Buffer Management Module"); +-MODULE_LICENSE("GPL"); ++int exynos_drm_alloc_buf(struct drm_device *dev, ++ struct exynos_drm_gem_buf *buf, unsigned int flags) ++{ ++ ++ /* ++ * allocate memory region and set the memory information ++ * to vaddr and dma_addr of a buffer object. ++ */ ++ if (lowlevel_buffer_allocate(dev, flags, buf) < 0) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++void exynos_drm_free_buf(struct drm_device *dev, ++ unsigned int flags, struct exynos_drm_gem_buf *buffer) ++{ ++ ++ lowlevel_buffer_deallocate(dev, flags, buffer); ++} +diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.h b/drivers/gpu/drm/exynos/exynos_drm_buf.h +index 6e91f9c..3388e4e 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_buf.h ++++ b/drivers/gpu/drm/exynos/exynos_drm_buf.h +@@ -26,15 +26,22 @@ + #ifndef _EXYNOS_DRM_BUF_H_ + #define _EXYNOS_DRM_BUF_H_ + +-/* allocate physical memory. */ +-struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev, +- unsigned int size); ++/* create and initialize buffer object. */ ++struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev, ++ unsigned int size); + +-/* get memory information of a drm framebuffer. */ +-struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb); ++/* destroy buffer object. */ ++void exynos_drm_fini_buf(struct drm_device *dev, ++ struct exynos_drm_gem_buf *buffer); + +-/* remove allocated physical memory. */ +-void exynos_drm_buf_destroy(struct drm_device *dev, +- struct exynos_drm_gem_buf *buffer); ++/* allocate physical memory region and setup sgt and pages. */ ++int exynos_drm_alloc_buf(struct drm_device *dev, ++ struct exynos_drm_gem_buf *buf, ++ unsigned int flags); ++ ++/* release physical memory region, sgt and pages. */ ++void exynos_drm_free_buf(struct drm_device *dev, ++ unsigned int flags, ++ struct exynos_drm_gem_buf *buffer); + + #endif +diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c +index d620b07..bf791fa 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c +@@ -28,6 +28,7 @@ + #include "drmP.h" + #include "drm_crtc_helper.h" + ++#include + #include "exynos_drm_drv.h" + #include "exynos_drm_encoder.h" + +@@ -44,22 +45,25 @@ struct exynos_drm_connector { + /* convert exynos_video_timings to drm_display_mode */ + static inline void + convert_to_display_mode(struct drm_display_mode *mode, +- struct fb_videomode *timing) ++ struct exynos_drm_panel_info *panel) + { ++ struct fb_videomode *timing = &panel->timing; + DRM_DEBUG_KMS("%s\n", __FILE__); + + mode->clock = timing->pixclock / 1000; + mode->vrefresh = timing->refresh; + + mode->hdisplay = timing->xres; +- mode->hsync_start = mode->hdisplay + timing->left_margin; ++ mode->hsync_start = mode->hdisplay + timing->right_margin; + mode->hsync_end = mode->hsync_start + timing->hsync_len; +- mode->htotal = mode->hsync_end + timing->right_margin; ++ mode->htotal = mode->hsync_end + timing->left_margin; + + mode->vdisplay = timing->yres; +- mode->vsync_start = mode->vdisplay + timing->upper_margin; ++ mode->vsync_start = mode->vdisplay + timing->lower_margin; + mode->vsync_end = mode->vsync_start + timing->vsync_len; +- mode->vtotal = mode->vsync_end + timing->lower_margin; ++ mode->vtotal = mode->vsync_end + timing->upper_margin; ++ mode->width_mm = panel->width_mm; ++ mode->height_mm = panel->height_mm; + + if (timing->vmode & FB_VMODE_INTERLACED) + mode->flags |= DRM_MODE_FLAG_INTERLACE; +@@ -81,14 +85,14 @@ convert_to_video_timing(struct fb_videomode *timing, + timing->refresh = drm_mode_vrefresh(mode); + + timing->xres = mode->hdisplay; +- timing->left_margin = mode->hsync_start - mode->hdisplay; ++ timing->right_margin = mode->hsync_start - mode->hdisplay; + timing->hsync_len = mode->hsync_end - mode->hsync_start; +- timing->right_margin = mode->htotal - mode->hsync_end; ++ timing->left_margin = mode->htotal - mode->hsync_end; + + timing->yres = mode->vdisplay; +- timing->upper_margin = mode->vsync_start - mode->vdisplay; ++ timing->lower_margin = mode->vsync_start - mode->vdisplay; + timing->vsync_len = mode->vsync_end - mode->vsync_start; +- timing->lower_margin = mode->vtotal - mode->vsync_end; ++ timing->upper_margin = mode->vtotal - mode->vsync_end; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + timing->vmode = FB_VMODE_INTERLACED; +@@ -148,16 +152,18 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) + connector->display_info.raw_edid = edid; + } else { + struct drm_display_mode *mode = drm_mode_create(connector->dev); +- struct fb_videomode *timing; ++ struct exynos_drm_panel_info *panel; + +- if (display_ops->get_timing) +- timing = display_ops->get_timing(manager->dev); ++ if (display_ops->get_panel) ++ panel = display_ops->get_panel(manager->dev); + else { + drm_mode_destroy(connector->dev, mode); + return 0; + } + +- convert_to_display_mode(mode, timing); ++ convert_to_display_mode(mode, panel); ++ connector->display_info.width_mm = mode->width_mm; ++ connector->display_info.height_mm = mode->height_mm; + + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_set_name(mode); +@@ -219,6 +225,29 @@ static struct drm_connector_helper_funcs exynos_connector_helper_funcs = { + .best_encoder = exynos_drm_best_encoder, + }; + ++static int exynos_drm_connector_fill_modes(struct drm_connector *connector, ++ unsigned int max_width, unsigned int max_height) ++{ ++ struct exynos_drm_connector *exynos_connector = ++ to_exynos_connector(connector); ++ struct exynos_drm_manager *manager = exynos_connector->manager; ++ struct exynos_drm_manager_ops *ops = manager->ops; ++ unsigned int width, height; ++ ++ width = max_width; ++ height = max_height; ++ ++ /* ++ * if specific driver want to find desired_mode using maxmum ++ * resolution then get max width and height from that driver. ++ */ ++ if (ops && ops->get_max_resol) ++ ops->get_max_resol(manager->dev, &width, &height); ++ ++ return drm_helper_probe_single_connector_modes(connector, width, ++ height); ++} ++ + /* get detection status of display device. */ + static enum drm_connector_status + exynos_drm_connector_detect(struct drm_connector *connector, bool force) +@@ -256,7 +285,7 @@ static void exynos_drm_connector_destroy(struct drm_connector *connector) + + static struct drm_connector_funcs exynos_connector_funcs = { + .dpms = drm_helper_connector_dpms, +- .fill_modes = drm_helper_probe_single_connector_modes, ++ .fill_modes = exynos_drm_connector_fill_modes, + .detect = exynos_drm_connector_detect, + .destroy = exynos_drm_connector_destroy, + }; +@@ -286,6 +315,10 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, + connector->interlace_allowed = true; + connector->polled = DRM_CONNECTOR_POLL_HPD; + break; ++ case EXYNOS_DISPLAY_TYPE_VIDI: ++ type = DRM_MODE_CONNECTOR_VIRTUAL; ++ connector->polled = DRM_CONNECTOR_POLL_HPD; ++ break; + default: + type = DRM_MODE_CONNECTOR_Unknown; + break; +@@ -319,9 +352,3 @@ err_connector: + kfree(exynos_connector); + return NULL; + } +- +-MODULE_AUTHOR("Inki Dae "); +-MODULE_AUTHOR("Joonyoung Shim "); +-MODULE_AUTHOR("Seung-Woo Kim "); +-MODULE_DESCRIPTION("Samsung SoC DRM Connector Driver"); +-MODULE_LICENSE("GPL"); +diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c +index 661a035..eaf630d 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_core.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_core.c +@@ -32,7 +32,6 @@ + #include "exynos_drm_connector.h" + #include "exynos_drm_fbdev.h" + +-static DEFINE_MUTEX(exynos_drm_mutex); + static LIST_HEAD(exynos_drm_subdrv_list); + static struct drm_device *drm_dev; + +@@ -55,13 +54,18 @@ static int exynos_drm_subdrv_probe(struct drm_device *dev, + * + * P.S. note that this driver is considered for modularization. + */ +- ret = subdrv->probe(dev, subdrv->manager.dev); ++ ret = subdrv->probe(dev, subdrv->dev); + if (ret) + return ret; + } + ++ if (!subdrv->manager) ++ return 0; ++ ++ subdrv->manager->dev = subdrv->dev; ++ + /* create and initialize a encoder for this sub driver. */ +- encoder = exynos_drm_encoder_create(dev, &subdrv->manager, ++ encoder = exynos_drm_encoder_create(dev, subdrv->manager, + (1 << MAX_CRTC) - 1); + if (!encoder) { + DRM_ERROR("failed to create encoder\n"); +@@ -116,13 +120,10 @@ int exynos_drm_device_register(struct drm_device *dev) + if (!dev) + return -EINVAL; + +- if (drm_dev) { +- DRM_ERROR("Already drm device were registered\n"); +- return -EBUSY; +- } ++ drm_dev = dev; + +- mutex_lock(&exynos_drm_mutex); + list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) { ++ subdrv->drm_dev = dev; + err = exynos_drm_subdrv_probe(dev, subdrv); + if (err) { + DRM_DEBUG("exynos drm subdrv probe failed.\n"); +@@ -130,9 +131,6 @@ int exynos_drm_device_register(struct drm_device *dev) + } + } + +- drm_dev = dev; +- mutex_unlock(&exynos_drm_mutex); +- + return 0; + } + EXPORT_SYMBOL_GPL(exynos_drm_device_register); +@@ -143,83 +141,28 @@ int exynos_drm_device_unregister(struct drm_device *dev) + + DRM_DEBUG_DRIVER("%s\n", __FILE__); + +- if (!dev || dev != drm_dev) { ++ if (!dev) { + WARN(1, "Unexpected drm device unregister!\n"); + return -EINVAL; + } + +- mutex_lock(&exynos_drm_mutex); + list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) + exynos_drm_subdrv_remove(dev, subdrv); + + drm_dev = NULL; +- mutex_unlock(&exynos_drm_mutex); + + return 0; + } + EXPORT_SYMBOL_GPL(exynos_drm_device_unregister); + +-static int exynos_drm_mode_group_reinit(struct drm_device *dev) +-{ +- struct drm_mode_group *group = &dev->primary->mode_group; +- uint32_t *id_list = group->id_list; +- int ret; +- +- DRM_DEBUG_DRIVER("%s\n", __FILE__); +- +- ret = drm_mode_group_init_legacy_group(dev, group); +- if (ret < 0) +- return ret; +- +- kfree(id_list); +- return 0; +-} +- + int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv) + { +- int err; +- + DRM_DEBUG_DRIVER("%s\n", __FILE__); + + if (!subdrv) + return -EINVAL; + +- mutex_lock(&exynos_drm_mutex); +- if (drm_dev) { +- err = exynos_drm_subdrv_probe(drm_dev, subdrv); +- if (err) { +- DRM_ERROR("failed to probe exynos drm subdrv\n"); +- mutex_unlock(&exynos_drm_mutex); +- return err; +- } +- +- /* +- * if any specific driver such as fimd or hdmi driver called +- * exynos_drm_subdrv_register() later than drm_load(), +- * the fb helper should be re-initialized and re-configured. +- */ +- err = exynos_drm_fbdev_reinit(drm_dev); +- if (err) { +- DRM_ERROR("failed to reinitialize exynos drm fbdev\n"); +- exynos_drm_subdrv_remove(drm_dev, subdrv); +- mutex_unlock(&exynos_drm_mutex); +- return err; +- } +- +- err = exynos_drm_mode_group_reinit(drm_dev); +- if (err) { +- DRM_ERROR("failed to reinitialize mode group\n"); +- exynos_drm_fbdev_fini(drm_dev); +- exynos_drm_subdrv_remove(drm_dev, subdrv); +- mutex_unlock(&exynos_drm_mutex); +- return err; +- } +- } +- +- subdrv->drm_dev = drm_dev; +- + list_add_tail(&subdrv->list, &exynos_drm_subdrv_list); +- mutex_unlock(&exynos_drm_mutex); + + return 0; + } +@@ -227,46 +170,48 @@ EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register); + + int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv) + { +- int ret = -EFAULT; +- + DRM_DEBUG_DRIVER("%s\n", __FILE__); + +- if (!subdrv) { +- DRM_DEBUG("Unexpected exynos drm subdrv unregister!\n"); +- return ret; +- } ++ if (!subdrv) ++ return -EINVAL; + +- mutex_lock(&exynos_drm_mutex); +- if (drm_dev) { +- exynos_drm_subdrv_remove(drm_dev, subdrv); +- list_del(&subdrv->list); ++ list_del(&subdrv->list); + +- /* +- * fb helper should be updated once a sub driver is released +- * to re-configure crtc and connector and also to re-setup +- * drm framebuffer. +- */ +- ret = exynos_drm_fbdev_reinit(drm_dev); +- if (ret < 0) { +- DRM_ERROR("failed fb helper reinit.\n"); +- goto fail; +- } ++ return 0; ++} ++EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister); + +- ret = exynos_drm_mode_group_reinit(drm_dev); +- if (ret < 0) { +- DRM_ERROR("failed drm mode group reinit.\n"); +- goto fail; ++int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file) ++{ ++ struct exynos_drm_subdrv *subdrv; ++ int ret; ++ ++ list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) { ++ if (subdrv->open) { ++ ret = subdrv->open(dev, subdrv->dev, file); ++ if (ret) ++ goto err; + } + } + +-fail: +- mutex_unlock(&exynos_drm_mutex); ++ return 0; ++ ++err: ++ list_for_each_entry_reverse(subdrv, &subdrv->list, list) { ++ if (subdrv->close) ++ subdrv->close(dev, subdrv->dev, file); ++ } + return ret; + } +-EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister); ++EXPORT_SYMBOL_GPL(exynos_drm_subdrv_open); ++ ++void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file) ++{ ++ struct exynos_drm_subdrv *subdrv; + +-MODULE_AUTHOR("Inki Dae "); +-MODULE_AUTHOR("Joonyoung Shim "); +-MODULE_AUTHOR("Seung-Woo Kim "); +-MODULE_DESCRIPTION("Samsung SoC DRM Core Driver"); +-MODULE_LICENSE("GPL"); ++ list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) { ++ if (subdrv->close) ++ subdrv->close(dev, subdrv->dev, file); ++ } ++} ++EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close); +diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c +index ee43cc2..3486ffe 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c +@@ -34,7 +34,6 @@ + #include "exynos_drm_fb.h" + #include "exynos_drm_encoder.h" + #include "exynos_drm_gem.h" +-#include "exynos_drm_buf.h" + + #define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\ + drm_crtc) +@@ -52,11 +51,13 @@ + * drm framework doesn't support multiple irq yet. + * we can refer to the crtc to current hardware interrupt occured through + * this pipe value. ++ * @dpms: store the crtc dpms value + */ + struct exynos_drm_crtc { + struct drm_crtc drm_crtc; + struct exynos_drm_overlay overlay; + unsigned int pipe; ++ unsigned int dpms; + }; + + static void exynos_drm_crtc_apply(struct drm_crtc *crtc) +@@ -78,19 +79,23 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay, + struct exynos_drm_gem_buf *buffer; + unsigned int actual_w; + unsigned int actual_h; ++ int nr = exynos_drm_format_num_buffers(fb->pixel_format); ++ int i; ++ ++ for (i = 0; i < nr; i++) { ++ buffer = exynos_drm_fb_buffer(fb, i); ++ if (!buffer) { ++ DRM_LOG_KMS("buffer is null\n"); ++ return -EFAULT; ++ } + +- buffer = exynos_drm_fb_get_buf(fb); +- if (!buffer) { +- DRM_LOG_KMS("buffer is null.\n"); +- return -EFAULT; +- } +- +- overlay->dma_addr = buffer->dma_addr; +- overlay->vaddr = buffer->kvaddr; ++ overlay->dma_addr[i] = buffer->dma_addr; ++ overlay->vaddr[i] = buffer->kvaddr; + +- DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n", +- (unsigned long)overlay->vaddr, +- (unsigned long)overlay->dma_addr); ++ DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n", ++ i, (unsigned long)overlay->vaddr[i], ++ (unsigned long)overlay->dma_addr[i]); ++ } + + actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w); + actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h); +@@ -101,7 +106,8 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay, + overlay->fb_width = fb->width; + overlay->fb_height = fb->height; + overlay->bpp = fb->bits_per_pixel; +- overlay->pitch = fb->pitch; ++ overlay->pitch = fb->pitches[0]; ++ overlay->pixel_format = fb->pixel_format; + + /* set overlay range to be displayed. */ + overlay->crtc_x = pos->crtc_x; +@@ -153,26 +159,37 @@ static int exynos_drm_crtc_update(struct drm_crtc *crtc) + + static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) + { ++ struct drm_device *dev = crtc->dev; + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + + DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); + ++ if (exynos_crtc->dpms == mode) { ++ DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n"); ++ return; ++ } ++ ++ mutex_lock(&dev->struct_mutex); ++ + switch (mode) { + case DRM_MODE_DPMS_ON: +- exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe, +- exynos_drm_encoder_crtc_commit); ++ exynos_drm_fn_encoder(crtc, &mode, ++ exynos_drm_encoder_crtc_dpms); ++ exynos_crtc->dpms = mode; + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: +- /* TODO */ +- exynos_drm_fn_encoder(crtc, NULL, +- exynos_drm_encoder_crtc_disable); ++ exynos_drm_fn_encoder(crtc, &mode, ++ exynos_drm_encoder_crtc_dpms); ++ exynos_crtc->dpms = mode; + break; + default: +- DRM_DEBUG_KMS("unspecified mode %d\n", mode); ++ DRM_ERROR("unspecified mode %d\n", mode); + break; + } ++ ++ mutex_unlock(&dev->struct_mutex); + } + + static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) +@@ -188,6 +205,28 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc) + + DRM_DEBUG_KMS("%s\n", __FILE__); + ++ /* ++ * when set_crtc is requested from user or at booting time, ++ * crtc->commit would be called without dpms call so if dpms is ++ * no power on then crtc->dpms should be called ++ * with DRM_MODE_DPMS_ON for the hardware power to be on. ++ */ ++ if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) { ++ int mode = DRM_MODE_DPMS_ON; ++ ++ /* ++ * enable hardware(power on) to all encoders hdmi connected ++ * to current crtc. ++ */ ++ exynos_drm_crtc_dpms(crtc, mode); ++ /* ++ * enable dma to all encoders connected to current crtc and ++ * lcd panel. ++ */ ++ exynos_drm_fn_encoder(crtc, &mode, ++ exynos_drm_encoder_dpms_from_crtc); ++ } ++ + exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe, + exynos_drm_encoder_crtc_commit); + } +@@ -210,7 +249,11 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, + { + DRM_DEBUG_KMS("%s\n", __FILE__); + +- mode = adjusted_mode; ++ /* ++ * copy the mode data adjusted by mode_fixup() into crtc->mode ++ * so that hardware can be seet to proper mode. ++ */ ++ memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode)); + + return exynos_drm_crtc_update(crtc); + } +@@ -268,9 +311,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, + */ + event->pipe = exynos_crtc->pipe; + +- list_add_tail(&event->base.link, +- &dev_priv->pageflip_event_list); +- + ret = drm_vblank_get(dev, exynos_crtc->pipe); + if (ret) { + DRM_DEBUG("failed to acquire vblank counter\n"); +@@ -279,6 +319,9 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, + goto out; + } + ++ list_add_tail(&event->base.link, ++ &dev_priv->pageflip_event_list); ++ + crtc->fb = fb; + ret = exynos_drm_crtc_update(crtc); + if (ret) { +@@ -344,6 +387,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) + } + + exynos_crtc->pipe = nr; ++ exynos_crtc->dpms = DRM_MODE_DPMS_OFF; ++ exynos_crtc->overlay.zpos = DEFAULT_ZPOS; + crtc = &exynos_crtc->drm_crtc; + + private->crtc[nr] = crtc; +@@ -357,9 +402,14 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) + int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc) + { + struct exynos_drm_private *private = dev->dev_private; ++ struct exynos_drm_crtc *exynos_crtc = ++ to_exynos_crtc(private->crtc[crtc]); + + DRM_DEBUG_KMS("%s\n", __FILE__); + ++ if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) ++ return -EPERM; ++ + exynos_drm_fn_encoder(private->crtc[crtc], &crtc, + exynos_drm_enable_vblank); + +@@ -369,15 +419,14 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc) + void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc) + { + struct exynos_drm_private *private = dev->dev_private; ++ struct exynos_drm_crtc *exynos_crtc = ++ to_exynos_crtc(private->crtc[crtc]); + + DRM_DEBUG_KMS("%s\n", __FILE__); + ++ if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) ++ return; ++ + exynos_drm_fn_encoder(private->crtc[crtc], &crtc, + exynos_drm_disable_vblank); + } +- +-MODULE_AUTHOR("Inki Dae "); +-MODULE_AUTHOR("Joonyoung Shim "); +-MODULE_AUTHOR("Seung-Woo Kim "); +-MODULE_DESCRIPTION("Samsung SoC DRM CRTC Driver"); +-MODULE_LICENSE("GPL"); +diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c +index 53e2216..a6819b5 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c +@@ -33,16 +33,21 @@ + + #include "exynos_drm_drv.h" + #include "exynos_drm_crtc.h" ++#include "exynos_drm_encoder.h" + #include "exynos_drm_fbdev.h" + #include "exynos_drm_fb.h" + #include "exynos_drm_gem.h" ++#include "exynos_drm_plane.h" ++#include "exynos_drm_vidi.h" + +-#define DRIVER_NAME "exynos-drm" ++#define DRIVER_NAME "exynos" + #define DRIVER_DESC "Samsung SoC DRM" + #define DRIVER_DATE "20110530" + #define DRIVER_MAJOR 1 + #define DRIVER_MINOR 0 + ++#define VBLANK_OFF_DELAY 50000 ++ + static int exynos_drm_load(struct drm_device *dev, unsigned long flags) + { + struct exynos_drm_private *private; +@@ -77,6 +82,12 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) + goto err_crtc; + } + ++ for (nr = 0; nr < MAX_PLANE; nr++) { ++ ret = exynos_plane_init(dev, nr); ++ if (ret) ++ goto err_crtc; ++ } ++ + ret = drm_vblank_init(dev, MAX_CRTC); + if (ret) + goto err_crtc; +@@ -90,6 +101,9 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) + if (ret) + goto err_vblank; + ++ /* setup possible_clones. */ ++ exynos_drm_encoder_setup(dev); ++ + /* + * create and configure fb helper and also exynos specific + * fbdev object. +@@ -100,6 +114,8 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) + goto err_drm_device; + } + ++ drm_vblank_offdelay = VBLANK_OFF_DELAY; ++ + return 0; + + err_drm_device: +@@ -129,17 +145,45 @@ static int exynos_drm_unload(struct drm_device *dev) + return 0; + } + ++static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) ++{ ++ DRM_DEBUG_DRIVER("%s\n", __FILE__); ++ ++ return exynos_drm_subdrv_open(dev, file); ++} ++ + static void exynos_drm_preclose(struct drm_device *dev, +- struct drm_file *file_priv) ++ struct drm_file *file) + { +- struct exynos_drm_private *dev_priv = dev->dev_private; ++ struct exynos_drm_private *private = dev->dev_private; ++ struct drm_pending_vblank_event *e, *t; ++ unsigned long flags; + +- /* +- * drm framework frees all events at release time, +- * so private event list should be cleared. +- */ +- if (!list_empty(&dev_priv->pageflip_event_list)) +- INIT_LIST_HEAD(&dev_priv->pageflip_event_list); ++ DRM_DEBUG_DRIVER("%s\n", __FILE__); ++ ++ /* release events of current file */ ++ spin_lock_irqsave(&dev->event_lock, flags); ++ list_for_each_entry_safe(e, t, &private->pageflip_event_list, ++ base.link) { ++ if (e->base.file_priv == file) { ++ list_del(&e->base.link); ++ e->base.destroy(&e->base); ++ } ++ } ++ spin_unlock_irqrestore(&dev->event_lock, flags); ++ ++ exynos_drm_subdrv_close(dev, file); ++} ++ ++static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) ++{ ++ DRM_DEBUG_DRIVER("%s\n", __FILE__); ++ ++ if (!file->driver_priv) ++ return; ++ ++ kfree(file->driver_priv); ++ file->driver_priv = NULL; + } + + static void exynos_drm_lastclose(struct drm_device *dev) +@@ -163,6 +207,20 @@ static struct drm_ioctl_desc exynos_ioctls[] = { + DRM_AUTH), + DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP, + exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH), ++ DRM_IOCTL_DEF_DRV(EXYNOS_PLANE_SET_ZPOS, exynos_plane_set_zpos_ioctl, ++ DRM_UNLOCKED | DRM_AUTH), ++ DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, ++ vidi_connection_ioctl, DRM_UNLOCKED | DRM_AUTH), ++}; ++ ++static const struct file_operations exynos_drm_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .mmap = exynos_drm_gem_mmap, ++ .poll = drm_poll, ++ .read = drm_read, ++ .unlocked_ioctl = drm_ioctl, ++ .release = drm_release, + }; + + static struct drm_driver exynos_drm_driver = { +@@ -170,8 +228,10 @@ static struct drm_driver exynos_drm_driver = { + DRIVER_MODESET | DRIVER_GEM, + .load = exynos_drm_load, + .unload = exynos_drm_unload, ++ .open = exynos_drm_open, + .preclose = exynos_drm_preclose, + .lastclose = exynos_drm_lastclose, ++ .postclose = exynos_drm_postclose, + .get_vblank_counter = drm_vblank_count, + .enable_vblank = exynos_drm_crtc_enable_vblank, + .disable_vblank = exynos_drm_crtc_disable_vblank, +@@ -182,15 +242,7 @@ static struct drm_driver exynos_drm_driver = { + .dumb_map_offset = exynos_drm_gem_dumb_map_offset, + .dumb_destroy = exynos_drm_gem_dumb_destroy, + .ioctls = exynos_ioctls, +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .mmap = exynos_drm_gem_mmap, +- .poll = drm_poll, +- .read = drm_read, +- .unlocked_ioctl = drm_ioctl, +- .release = drm_release, +- }, ++ .fops = &exynos_drm_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, +@@ -221,15 +273,66 @@ static struct platform_driver exynos_drm_platform_driver = { + .remove = __devexit_p(exynos_drm_platform_remove), + .driver = { + .owner = THIS_MODULE, +- .name = DRIVER_NAME, ++ .name = "exynos-drm", + }, + }; + + static int __init exynos_drm_init(void) + { ++ int ret; ++ + DRM_DEBUG_DRIVER("%s\n", __FILE__); + +- return platform_driver_register(&exynos_drm_platform_driver); ++#ifdef CONFIG_DRM_EXYNOS_FIMD ++ ret = platform_driver_register(&fimd_driver); ++ if (ret < 0) ++ goto out_fimd; ++#endif ++ ++#ifdef CONFIG_DRM_EXYNOS_HDMI ++ ret = platform_driver_register(&hdmi_driver); ++ if (ret < 0) ++ goto out_hdmi; ++ ret = platform_driver_register(&mixer_driver); ++ if (ret < 0) ++ goto out_mixer; ++ ret = platform_driver_register(&exynos_drm_common_hdmi_driver); ++ if (ret < 0) ++ goto out_common_hdmi; ++#endif ++ ++#ifdef CONFIG_DRM_EXYNOS_VIDI ++ ret = platform_driver_register(&vidi_driver); ++ if (ret < 0) ++ goto out_vidi; ++#endif ++ ++ ret = platform_driver_register(&exynos_drm_platform_driver); ++ if (ret < 0) ++ goto out; ++ ++ return 0; ++ ++out: ++#ifdef CONFIG_DRM_EXYNOS_VIDI ++out_vidi: ++ platform_driver_unregister(&vidi_driver); ++#endif ++ ++#ifdef CONFIG_DRM_EXYNOS_HDMI ++ platform_driver_unregister(&exynos_drm_common_hdmi_driver); ++out_common_hdmi: ++ platform_driver_unregister(&mixer_driver); ++out_mixer: ++ platform_driver_unregister(&hdmi_driver); ++out_hdmi: ++#endif ++ ++#ifdef CONFIG_DRM_EXYNOS_FIMD ++ platform_driver_unregister(&fimd_driver); ++out_fimd: ++#endif ++ return ret; + } + + static void __exit exynos_drm_exit(void) +@@ -237,6 +340,20 @@ static void __exit exynos_drm_exit(void) + DRM_DEBUG_DRIVER("%s\n", __FILE__); + + platform_driver_unregister(&exynos_drm_platform_driver); ++ ++#ifdef CONFIG_DRM_EXYNOS_HDMI ++ platform_driver_unregister(&exynos_drm_common_hdmi_driver); ++ platform_driver_unregister(&mixer_driver); ++ platform_driver_unregister(&hdmi_driver); ++#endif ++ ++#ifdef CONFIG_DRM_EXYNOS_VIDI ++ platform_driver_unregister(&vidi_driver); ++#endif ++ ++#ifdef CONFIG_DRM_EXYNOS_FIMD ++ platform_driver_unregister(&fimd_driver); ++#endif + } + + module_init(exynos_drm_init); +diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h +index 5e02e6e..1d81417 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h ++++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h +@@ -32,12 +32,17 @@ + #include + #include "drm.h" + +-#define MAX_CRTC 2 ++#define MAX_CRTC 3 ++#define MAX_PLANE 5 ++#define MAX_FB_BUFFER 4 ++#define DEFAULT_ZPOS -1 + + struct drm_device; + struct exynos_drm_overlay; + struct drm_connector; + ++extern unsigned int drm_vblank_offdelay; ++ + /* this enumerates display type. */ + enum exynos_drm_output_type { + EXYNOS_DISPLAY_TYPE_NONE, +@@ -45,6 +50,8 @@ enum exynos_drm_output_type { + EXYNOS_DISPLAY_TYPE_LCD, + /* HDMI Interface. */ + EXYNOS_DISPLAY_TYPE_HDMI, ++ /* Virtual Display Interface. */ ++ EXYNOS_DISPLAY_TYPE_VIDI, + }; + + /* +@@ -57,8 +64,8 @@ enum exynos_drm_output_type { + struct exynos_drm_overlay_ops { + void (*mode_set)(struct device *subdrv_dev, + struct exynos_drm_overlay *overlay); +- void (*commit)(struct device *subdrv_dev); +- void (*disable)(struct device *subdrv_dev); ++ void (*commit)(struct device *subdrv_dev, int zpos); ++ void (*disable)(struct device *subdrv_dev, int zpos); + }; + + /* +@@ -80,9 +87,11 @@ struct exynos_drm_overlay_ops { + * @scan_flag: interlace or progressive way. + * (it could be DRM_MODE_FLAG_*) + * @bpp: pixel size.(in bit) +- * @dma_addr: bus(accessed by dma) address to the memory region allocated +- * for a overlay. +- * @vaddr: virtual memory addresss to this overlay. ++ * @pixel_format: fourcc pixel format of this overlay ++ * @dma_addr: array of bus(accessed by dma) address to the memory region ++ * allocated for a overlay. ++ * @vaddr: array of virtual memory addresss to this overlay. ++ * @zpos: order of overlay layer(z position). + * @default_win: a window to be enabled. + * @color_key: color key on or off. + * @index_color: if using color key feature then this value would be used +@@ -109,8 +118,10 @@ struct exynos_drm_overlay { + unsigned int scan_flag; + unsigned int bpp; + unsigned int pitch; +- dma_addr_t dma_addr; +- void __iomem *vaddr; ++ uint32_t pixel_format; ++ dma_addr_t dma_addr[MAX_FB_BUFFER]; ++ void __iomem *vaddr[MAX_FB_BUFFER]; ++ int zpos; + + bool default_win; + bool color_key; +@@ -127,7 +138,7 @@ struct exynos_drm_overlay { + * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. + * @is_connected: check for that display is connected or not. + * @get_edid: get edid modes from display driver. +- * @get_timing: get timing object from display driver. ++ * @get_panel: get panel object from display driver. + * @check_timing: check if timing is valid or not. + * @power_on: display device on or off. + */ +@@ -136,7 +147,7 @@ struct exynos_drm_display_ops { + bool (*is_connected)(struct device *dev); + int (*get_edid)(struct device *dev, struct drm_connector *connector, + u8 *edid, int len); +- void *(*get_timing)(struct device *dev); ++ void *(*get_panel)(struct device *dev); + int (*check_timing)(struct device *dev, void *timing); + int (*power_on)(struct device *dev, int mode); + }; +@@ -144,17 +155,27 @@ struct exynos_drm_display_ops { + /* + * Exynos drm manager ops + * ++ * @dpms: control device power. ++ * @apply: set timing, vblank and overlay data to registers. ++ * @mode_fixup: fix mode data comparing to hw specific display mode. + * @mode_set: convert drm_display_mode to hw specific display mode and + * would be called by encoder->mode_set(). ++ * @get_max_resol: get maximum resolution to specific hardware. + * @commit: set current hw specific display mode to hw. +- * @disable: disable hardware specific display mode. + * @enable_vblank: specific driver callback for enabling vblank interrupt. + * @disable_vblank: specific driver callback for disabling vblank interrupt. + */ + struct exynos_drm_manager_ops { ++ void (*dpms)(struct device *subdrv_dev, int mode); ++ void (*apply)(struct device *subdrv_dev); ++ void (*mode_fixup)(struct device *subdrv_dev, ++ struct drm_connector *connector, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode); + void (*mode_set)(struct device *subdrv_dev, void *mode); ++ void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width, ++ unsigned int *height); + void (*commit)(struct device *subdrv_dev); +- void (*disable)(struct device *subdrv_dev); + int (*enable_vblank)(struct device *subdrv_dev); + void (*disable_vblank)(struct device *subdrv_dev); + }; +@@ -204,25 +225,33 @@ struct exynos_drm_private { + * Exynos drm sub driver structure. + * + * @list: sub driver has its own list object to register to exynos drm driver. ++ * @dev: pointer to device object for subdrv device driver. + * @drm_dev: pointer to drm_device and this pointer would be set + * when sub driver calls exynos_drm_subdrv_register(). ++ * @manager: subdrv has its own manager to control a hardware appropriately ++ * and we can access a hardware drawing on this manager. + * @probe: this callback would be called by exynos drm driver after + * subdrv is registered to it. + * @remove: this callback is used to release resources created + * by probe callback. +- * @manager: subdrv has its own manager to control a hardware appropriately +- * and we can access a hardware drawing on this manager. ++ * @open: this would be called with drm device file open. ++ * @close: this would be called with drm device file close. + * @encoder: encoder object owned by this sub driver. + * @connector: connector object owned by this sub driver. + */ + struct exynos_drm_subdrv { + struct list_head list; ++ struct device *dev; + struct drm_device *drm_dev; ++ struct exynos_drm_manager *manager; + + int (*probe)(struct drm_device *drm_dev, struct device *dev); + void (*remove)(struct drm_device *dev); ++ int (*open)(struct drm_device *drm_dev, struct device *dev, ++ struct drm_file *file); ++ void (*close)(struct drm_device *drm_dev, struct device *dev, ++ struct drm_file *file); + +- struct exynos_drm_manager manager; + struct drm_encoder *encoder; + struct drm_connector *connector; + }; +@@ -243,15 +272,19 @@ int exynos_drm_device_unregister(struct drm_device *dev); + * this function would be called by sub drivers such as display controller + * or hdmi driver to register this sub driver object to exynos drm driver + * and when a sub driver is registered to exynos drm driver a probe callback +- * of the sub driver is called and creates its own encoder and connector +- * and then fb helper and drm mode group would be re-initialized. ++ * of the sub driver is called and creates its own encoder and connector. + */ + int exynos_drm_subdrv_register(struct exynos_drm_subdrv *drm_subdrv); + +-/* +- * this function removes subdrv list from exynos drm driver and fb helper +- * and drm mode group would be re-initialized. +- */ ++/* this function removes subdrv list from exynos drm driver */ + int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *drm_subdrv); + ++int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file); ++void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file); ++ ++extern struct platform_driver fimd_driver; ++extern struct platform_driver hdmi_driver; ++extern struct platform_driver mixer_driver; ++extern struct platform_driver exynos_drm_common_hdmi_driver; ++extern struct platform_driver vidi_driver; + #endif +diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c +index 1530614..6e9ac7b 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c +@@ -42,49 +42,68 @@ + * @drm_encoder: encoder object. + * @manager: specific encoder has its own manager to control a hardware + * appropriately and we can access a hardware drawing on this manager. ++ * @dpms: store the encoder dpms value. + */ + struct exynos_drm_encoder { + struct drm_encoder drm_encoder; + struct exynos_drm_manager *manager; ++ int dpms; + }; + +-static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) ++static void exynos_drm_display_power(struct drm_encoder *encoder, int mode) + { + struct drm_device *dev = encoder->dev; + struct drm_connector *connector; + struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); ++ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ if (connector->encoder == encoder) { ++ struct exynos_drm_display_ops *display_ops = ++ manager->display_ops; ++ ++ DRM_DEBUG_KMS("connector[%d] dpms[%d]\n", ++ connector->base.id, mode); ++ if (display_ops && display_ops->power_on) ++ display_ops->power_on(manager->dev, mode); ++ } ++ } ++} ++ ++static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); + struct exynos_drm_manager_ops *manager_ops = manager->ops; ++ struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); + + DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode); + ++ if (exynos_encoder->dpms == mode) { ++ DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n"); ++ return; ++ } ++ ++ mutex_lock(&dev->struct_mutex); ++ + switch (mode) { + case DRM_MODE_DPMS_ON: +- if (manager_ops && manager_ops->commit) +- manager_ops->commit(manager->dev); ++ if (manager_ops && manager_ops->apply) ++ manager_ops->apply(manager->dev); ++ exynos_drm_display_power(encoder, mode); ++ exynos_encoder->dpms = mode; + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: +- /* TODO */ +- if (manager_ops && manager_ops->disable) +- manager_ops->disable(manager->dev); ++ exynos_drm_display_power(encoder, mode); ++ exynos_encoder->dpms = mode; + break; + default: + DRM_ERROR("unspecified mode %d\n", mode); + break; + } + +- list_for_each_entry(connector, &dev->mode_config.connector_list, head) { +- if (connector->encoder == encoder) { +- struct exynos_drm_display_ops *display_ops = +- manager->display_ops; +- +- DRM_DEBUG_KMS("connector[%d] dpms[%d]\n", +- connector->base.id, mode); +- if (display_ops && display_ops->power_on) +- display_ops->power_on(manager->dev, mode); +- } +- } ++ mutex_unlock(&dev->struct_mutex); + } + + static bool +@@ -92,9 +111,19 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) + { ++ struct drm_device *dev = encoder->dev; ++ struct drm_connector *connector; ++ struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); ++ struct exynos_drm_manager_ops *manager_ops = manager->ops; ++ + DRM_DEBUG_KMS("%s\n", __FILE__); + +- /* drm framework doesn't check NULL. */ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ if (connector->encoder == encoder) ++ if (manager_ops && manager_ops->mode_fixup) ++ manager_ops->mode_fixup(manager->dev, connector, ++ mode, adjusted_mode); ++ } + + return true; + } +@@ -113,12 +142,11 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, + + DRM_DEBUG_KMS("%s\n", __FILE__); + +- mode = adjusted_mode; +- + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->encoder == encoder) { + if (manager_ops && manager_ops->mode_set) +- manager_ops->mode_set(manager->dev, mode); ++ manager_ops->mode_set(manager->dev, ++ adjusted_mode); + + if (overlay_ops && overlay_ops->mode_set) + overlay_ops->mode_set(manager->dev, overlay); +@@ -169,7 +197,6 @@ static void exynos_drm_encoder_destroy(struct drm_encoder *encoder) + exynos_encoder->manager->pipe = -1; + + drm_encoder_cleanup(encoder); +- encoder->dev->mode_config.num_encoder--; + kfree(exynos_encoder); + } + +@@ -177,6 +204,41 @@ static struct drm_encoder_funcs exynos_encoder_funcs = { + .destroy = exynos_drm_encoder_destroy, + }; + ++static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder) ++{ ++ struct drm_encoder *clone; ++ struct drm_device *dev = encoder->dev; ++ struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); ++ struct exynos_drm_display_ops *display_ops = ++ exynos_encoder->manager->display_ops; ++ unsigned int clone_mask = 0; ++ int cnt = 0; ++ ++ list_for_each_entry(clone, &dev->mode_config.encoder_list, head) { ++ switch (display_ops->type) { ++ case EXYNOS_DISPLAY_TYPE_LCD: ++ case EXYNOS_DISPLAY_TYPE_HDMI: ++ case EXYNOS_DISPLAY_TYPE_VIDI: ++ clone_mask |= (1 << (cnt++)); ++ break; ++ default: ++ continue; ++ } ++ } ++ ++ return clone_mask; ++} ++ ++void exynos_drm_encoder_setup(struct drm_device *dev) ++{ ++ struct drm_encoder *encoder; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) ++ encoder->possible_clones = exynos_drm_encoder_clones(encoder); ++} ++ + struct drm_encoder * + exynos_drm_encoder_create(struct drm_device *dev, + struct exynos_drm_manager *manager, +@@ -199,6 +261,7 @@ exynos_drm_encoder_create(struct drm_device *dev, + return NULL; + } + ++ exynos_encoder->dpms = DRM_MODE_DPMS_OFF; + exynos_encoder->manager = manager; + encoder = &exynos_encoder->drm_encoder; + encoder->possible_crtcs = possible_crtcs; +@@ -275,12 +338,27 @@ void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data) + manager_ops->disable_vblank(manager->dev); + } + +-void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data) ++void exynos_drm_encoder_crtc_plane_commit(struct drm_encoder *encoder, ++ void *data) + { + struct exynos_drm_manager *manager = + to_exynos_encoder(encoder)->manager; + struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; ++ int zpos = DEFAULT_ZPOS; ++ ++ if (data) ++ zpos = *(int *)data; ++ ++ if (overlay_ops && overlay_ops->commit) ++ overlay_ops->commit(manager->dev, zpos); ++} ++ ++void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data) ++{ ++ struct exynos_drm_manager *manager = ++ to_exynos_encoder(encoder)->manager; + int crtc = *(int *)data; ++ int zpos = DEFAULT_ZPOS; + + DRM_DEBUG_KMS("%s\n", __FILE__); + +@@ -290,8 +368,53 @@ void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data) + */ + manager->pipe = crtc; + +- if (overlay_ops && overlay_ops->commit) +- overlay_ops->commit(manager->dev); ++ exynos_drm_encoder_crtc_plane_commit(encoder, &zpos); ++} ++ ++void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder, void *data) ++{ ++ struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); ++ int mode = *(int *)data; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ exynos_drm_encoder_dpms(encoder, mode); ++ ++ exynos_encoder->dpms = mode; ++} ++ ++void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); ++ struct exynos_drm_manager *manager = exynos_encoder->manager; ++ struct exynos_drm_manager_ops *manager_ops = manager->ops; ++ struct drm_connector *connector; ++ int mode = *(int *)data; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (manager_ops && manager_ops->dpms) ++ manager_ops->dpms(manager->dev, mode); ++ ++ /* ++ * set current dpms mode to the connector connected to ++ * current encoder. connector->dpms would be checked ++ * at drm_helper_connector_dpms() ++ */ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) ++ if (connector->encoder == encoder) ++ connector->dpms = mode; ++ ++ /* ++ * if this condition is ok then it means that the crtc is already ++ * detached from encoder and last function for detaching is properly ++ * done, so clear pipe from manager to prevent repeated call. ++ */ ++ if (mode > DRM_MODE_DPMS_ON) { ++ if (!encoder->crtc) ++ manager->pipe = -1; ++ } + } + + void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data) +@@ -310,23 +433,13 @@ void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data) + struct exynos_drm_manager *manager = + to_exynos_encoder(encoder)->manager; + struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; ++ int zpos = DEFAULT_ZPOS; + + DRM_DEBUG_KMS("\n"); + +- if (overlay_ops && overlay_ops->disable) +- overlay_ops->disable(manager->dev); ++ if (data) ++ zpos = *(int *)data; + +- /* +- * crtc is already detached from encoder and last +- * function for detaching is properly done, so +- * clear pipe from manager to prevent repeated call +- */ +- if (!encoder->crtc) +- manager->pipe = -1; ++ if (overlay_ops && overlay_ops->disable) ++ overlay_ops->disable(manager->dev, zpos); + } +- +-MODULE_AUTHOR("Inki Dae "); +-MODULE_AUTHOR("Joonyoung Shim "); +-MODULE_AUTHOR("Seung-Woo Kim "); +-MODULE_DESCRIPTION("Samsung SoC DRM Encoder Driver"); +-MODULE_LICENSE("GPL"); +diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h +index a22acfb..eb7d231 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h ++++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.h +@@ -30,6 +30,7 @@ + + struct exynos_drm_manager; + ++void exynos_drm_encoder_setup(struct drm_device *dev); + struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev, + struct exynos_drm_manager *mgr, + unsigned int possible_crtcs); +@@ -39,7 +40,12 @@ void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, + void (*fn)(struct drm_encoder *, void *)); + void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data); + void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data); ++void exynos_drm_encoder_crtc_plane_commit(struct drm_encoder *encoder, ++ void *data); + void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data); ++void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder, ++ void *data); ++void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data); + void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data); + void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data); + +diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c +index 5bf4a1a..c38c8f4 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c +@@ -33,7 +33,6 @@ + + #include "exynos_drm_drv.h" + #include "exynos_drm_fb.h" +-#include "exynos_drm_buf.h" + #include "exynos_drm_gem.h" + + #define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb) +@@ -42,15 +41,11 @@ + * exynos specific framebuffer structure. + * + * @fb: drm framebuffer obejct. +- * @exynos_gem_obj: exynos specific gem object containing a gem object. +- * @buffer: pointer to exynos_drm_gem_buffer object. +- * - contain the memory information to memory region allocated +- * at default framebuffer creation. ++ * @exynos_gem_obj: array of exynos specific gem object containing a gem object. + */ + struct exynos_drm_fb { + struct drm_framebuffer fb; +- struct exynos_drm_gem_obj *exynos_gem_obj; +- struct exynos_drm_gem_buf *buffer; ++ struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER]; + }; + + static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) +@@ -61,13 +56,6 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) + + drm_framebuffer_cleanup(fb); + +- /* +- * default framebuffer has no gem object so +- * a buffer of the default framebuffer should be released at here. +- */ +- if (!exynos_fb->exynos_gem_obj && exynos_fb->buffer) +- exynos_drm_buf_destroy(fb->dev, exynos_fb->buffer); +- + kfree(exynos_fb); + exynos_fb = NULL; + } +@@ -81,7 +69,7 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb, + DRM_DEBUG_KMS("%s\n", __FILE__); + + return drm_gem_handle_create(file_priv, +- &exynos_fb->exynos_gem_obj->base, handle); ++ &exynos_fb->exynos_gem_obj[0]->base, handle); + } + + static int exynos_drm_fb_dirty(struct drm_framebuffer *fb, +@@ -102,134 +90,88 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = { + .dirty = exynos_drm_fb_dirty, + }; + +-static struct drm_framebuffer * +-exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev, +- struct drm_mode_fb_cmd *mode_cmd) ++struct drm_framebuffer * ++exynos_drm_framebuffer_init(struct drm_device *dev, ++ struct drm_mode_fb_cmd2 *mode_cmd, ++ struct drm_gem_object *obj) + { + struct exynos_drm_fb *exynos_fb; +- struct drm_framebuffer *fb; +- struct exynos_drm_gem_obj *exynos_gem_obj = NULL; +- struct drm_gem_object *obj; +- unsigned int size; + int ret; + +- DRM_DEBUG_KMS("%s\n", __FILE__); +- +- mode_cmd->pitch = max(mode_cmd->pitch, +- mode_cmd->width * (mode_cmd->bpp >> 3)); +- +- DRM_LOG_KMS("drm fb create(%dx%d)\n", +- mode_cmd->width, mode_cmd->height); +- + exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); + if (!exynos_fb) { +- DRM_ERROR("failed to allocate exynos drm framebuffer.\n"); ++ DRM_ERROR("failed to allocate exynos drm framebuffer\n"); + return ERR_PTR(-ENOMEM); + } + +- fb = &exynos_fb->fb; +- ret = drm_framebuffer_init(dev, fb, &exynos_drm_fb_funcs); ++ ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); + if (ret) { +- DRM_ERROR("failed to initialize framebuffer.\n"); +- goto err_init; ++ DRM_ERROR("failed to initialize framebuffer\n"); ++ return ERR_PTR(ret); + } + +- DRM_LOG_KMS("create: fb id: %d\n", fb->base.id); ++ drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); ++ exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj); + +- size = mode_cmd->pitch * mode_cmd->height; ++ return &exynos_fb->fb; ++} + +- /* +- * mode_cmd->handle could be NULL at booting time or +- * with user request. if NULL, a new buffer or a gem object +- * would be allocated. +- */ +- if (!mode_cmd->handle) { +- if (!file_priv) { +- struct exynos_drm_gem_buf *buffer; +- +- /* +- * in case that file_priv is NULL, it allocates +- * only buffer and this buffer would be used +- * for default framebuffer. +- */ +- buffer = exynos_drm_buf_create(dev, size); +- if (IS_ERR(buffer)) { +- ret = PTR_ERR(buffer); +- goto err_buffer; +- } +- +- exynos_fb->buffer = buffer; +- +- DRM_LOG_KMS("default: dma_addr = 0x%lx, size = 0x%x\n", +- (unsigned long)buffer->dma_addr, size); +- +- goto out; +- } else { +- exynos_gem_obj = exynos_drm_gem_create(dev, file_priv, +- &mode_cmd->handle, +- size); +- if (IS_ERR(exynos_gem_obj)) { +- ret = PTR_ERR(exynos_gem_obj); +- goto err_buffer; +- } +- } +- } else { +- obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); +- if (!obj) { +- DRM_ERROR("failed to lookup gem object.\n"); +- goto err_buffer; +- } ++static struct drm_framebuffer * ++exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, ++ struct drm_mode_fb_cmd2 *mode_cmd) ++{ ++ struct drm_gem_object *obj; ++ struct drm_framebuffer *fb; ++ struct exynos_drm_fb *exynos_fb; ++ int nr; ++ int i; + +- exynos_gem_obj = to_exynos_gem_obj(obj); ++ DRM_DEBUG_KMS("%s\n", __FILE__); + +- drm_gem_object_unreference_unlocked(obj); ++ obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); ++ if (!obj) { ++ DRM_ERROR("failed to lookup gem object\n"); ++ return ERR_PTR(-ENOENT); + } + +- /* +- * if got a exynos_gem_obj from either a handle or +- * a new creation then exynos_fb->exynos_gem_obj is NULL +- * so that default framebuffer has no its own gem object, +- * only its own buffer object. +- */ +- exynos_fb->buffer = exynos_gem_obj->buffer; +- +- DRM_LOG_KMS("dma_addr = 0x%lx, size = 0x%x, gem object = 0x%x\n", +- (unsigned long)exynos_fb->buffer->dma_addr, size, +- (unsigned int)&exynos_gem_obj->base); ++ drm_gem_object_unreference_unlocked(obj); + +-out: +- exynos_fb->exynos_gem_obj = exynos_gem_obj; ++ fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj); ++ if (IS_ERR(fb)) ++ return fb; + +- drm_helper_mode_fill_fb_struct(fb, mode_cmd); ++ exynos_fb = to_exynos_fb(fb); ++ nr = exynos_drm_format_num_buffers(fb->pixel_format); + +- return fb; +- +-err_buffer: +- drm_framebuffer_cleanup(fb); +- +-err_init: +- kfree(exynos_fb); ++ for (i = 1; i < nr; i++) { ++ obj = drm_gem_object_lookup(dev, file_priv, ++ mode_cmd->handles[i]); ++ if (!obj) { ++ DRM_ERROR("failed to lookup gem object\n"); ++ exynos_drm_fb_destroy(fb); ++ return ERR_PTR(-ENOENT); ++ } + +- return ERR_PTR(ret); +-} ++ drm_gem_object_unreference_unlocked(obj); + +-struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev, +- struct drm_file *file_priv, +- struct drm_mode_fb_cmd *mode_cmd) +-{ +- DRM_DEBUG_KMS("%s\n", __FILE__); ++ exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj); ++ } + +- return exynos_drm_fb_init(file_priv, dev, mode_cmd); ++ return fb; + } + +-struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb) ++struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, ++ int index) + { + struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); + struct exynos_drm_gem_buf *buffer; + + DRM_DEBUG_KMS("%s\n", __FILE__); + +- buffer = exynos_fb->buffer; ++ if (index >= MAX_FB_BUFFER) ++ return NULL; ++ ++ buffer = exynos_fb->exynos_gem_obj[index]->buffer; + if (!buffer) + return NULL; + +@@ -250,7 +192,7 @@ static void exynos_drm_output_poll_changed(struct drm_device *dev) + } + + static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { +- .fb_create = exynos_drm_fb_create, ++ .fb_create = exynos_user_fb_create, + .output_poll_changed = exynos_drm_output_poll_changed, + }; + +@@ -269,9 +211,3 @@ void exynos_drm_mode_config_init(struct drm_device *dev) + + dev->mode_config.funcs = &exynos_drm_mode_config_funcs; + } +- +-MODULE_AUTHOR("Inki Dae "); +-MODULE_AUTHOR("Joonyoung Shim "); +-MODULE_AUTHOR("Seung-Woo Kim "); +-MODULE_DESCRIPTION("Samsung SoC DRM FB Driver"); +-MODULE_LICENSE("GPL"); +diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h +index eb35931..3ecb30d 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_fb.h ++++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h +@@ -28,9 +28,27 @@ + #ifndef _EXYNOS_DRM_FB_H_ + #define _EXYNOS_DRM_FB_H + +-struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev, +- struct drm_file *filp, +- struct drm_mode_fb_cmd *mode_cmd); ++static inline int exynos_drm_format_num_buffers(uint32_t format) ++{ ++ switch (format) { ++ case DRM_FORMAT_NV12M: ++ case DRM_FORMAT_NV12MT: ++ return 2; ++ case DRM_FORMAT_YUV420M: ++ return 3; ++ default: ++ return 1; ++ } ++} ++ ++struct drm_framebuffer * ++exynos_drm_framebuffer_init(struct drm_device *dev, ++ struct drm_mode_fb_cmd2 *mode_cmd, ++ struct drm_gem_object *obj); ++ ++/* get memory information of a drm framebuffer */ ++struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, ++ int index); + + void exynos_drm_mode_config_init(struct drm_device *dev); + +diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +index 836f410..d5586cc 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +@@ -34,7 +34,6 @@ + #include "exynos_drm_drv.h" + #include "exynos_drm_fb.h" + #include "exynos_drm_gem.h" +-#include "exynos_drm_buf.h" + + #define MAX_CONNECTOR 4 + #define PREFERRED_BPP 32 +@@ -43,43 +42,17 @@ + drm_fb_helper) + + struct exynos_drm_fbdev { +- struct drm_fb_helper drm_fb_helper; +- struct drm_framebuffer *fb; ++ struct drm_fb_helper drm_fb_helper; ++ struct exynos_drm_gem_obj *exynos_gem_obj; + }; + +-static int exynos_drm_fbdev_set_par(struct fb_info *info) +-{ +- struct fb_var_screeninfo *var = &info->var; +- +- switch (var->bits_per_pixel) { +- case 32: +- case 24: +- case 18: +- case 16: +- case 12: +- info->fix.visual = FB_VISUAL_TRUECOLOR; +- break; +- case 1: +- info->fix.visual = FB_VISUAL_MONO01; +- break; +- default: +- info->fix.visual = FB_VISUAL_PSEUDOCOLOR; +- break; +- } +- +- info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; +- +- return drm_fb_helper_set_par(info); +-} +- +- + static struct fb_ops exynos_drm_fb_ops = { + .owner = THIS_MODULE, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_check_var = drm_fb_helper_check_var, +- .fb_set_par = exynos_drm_fbdev_set_par, ++ .fb_set_par = drm_fb_helper_set_par, + .fb_blank = drm_fb_helper_blank, + .fb_pan_display = drm_fb_helper_pan_display, + .fb_setcmap = drm_fb_helper_setcmap, +@@ -90,26 +63,24 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, + { + struct fb_info *fbi = helper->fbdev; + struct drm_device *dev = helper->dev; +- struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper); + struct exynos_drm_gem_buf *buffer; + unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); + unsigned long offset; + + DRM_DEBUG_KMS("%s\n", __FILE__); + +- exynos_fb->fb = fb; +- +- drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth); ++ drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); + drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height); + +- buffer = exynos_drm_fb_get_buf(fb); ++ /* RGB formats use only one buffer */ ++ buffer = exynos_drm_fb_buffer(fb, 0); + if (!buffer) { + DRM_LOG_KMS("buffer is null.\n"); + return -EFAULT; + } + + offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); +- offset += fbi->var.yoffset * fb->pitch; ++ offset += fbi->var.yoffset * fb->pitches[0]; + + dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr; + fbi->screen_base = buffer->kvaddr + offset; +@@ -124,10 +95,12 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) + { + struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper); ++ struct exynos_drm_gem_obj *exynos_gem_obj; + struct drm_device *dev = helper->dev; + struct fb_info *fbi; +- struct drm_mode_fb_cmd mode_cmd = { 0 }; ++ struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + struct platform_device *pdev = dev->platformdev; ++ unsigned long size; + int ret; + + DRM_DEBUG_KMS("%s\n", __FILE__); +@@ -138,8 +111,9 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, + + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height; +- mode_cmd.bpp = sizes->surface_bpp; +- mode_cmd.depth = sizes->surface_depth; ++ mode_cmd.pitches[0] = sizes->surface_width * (sizes->surface_bpp >> 3); ++ mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, ++ sizes->surface_depth); + + mutex_lock(&dev->struct_mutex); + +@@ -150,14 +124,25 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, + goto out; + } + +- exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd); +- if (IS_ERR_OR_NULL(exynos_fbdev->fb)) { ++ size = mode_cmd.pitches[0] * mode_cmd.height; ++ ++ /* 0 means to allocate physically continuous memory */ ++ exynos_gem_obj = exynos_drm_gem_create(dev, 0, size); ++ if (IS_ERR(exynos_gem_obj)) { ++ ret = PTR_ERR(exynos_gem_obj); ++ goto out; ++ } ++ ++ exynos_fbdev->exynos_gem_obj = exynos_gem_obj; ++ ++ helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, ++ &exynos_gem_obj->base); ++ if (IS_ERR_OR_NULL(helper->fb)) { + DRM_ERROR("failed to create drm framebuffer.\n"); +- ret = PTR_ERR(exynos_fbdev->fb); ++ ret = PTR_ERR(helper->fb); + goto out; + } + +- helper->fb = exynos_fbdev->fb; + helper->fbdev = fbi; + + fbi->par = helper; +@@ -171,8 +156,10 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, + } + + ret = exynos_drm_fbdev_update(helper, helper->fb); +- if (ret < 0) ++ if (ret < 0) { + fb_dealloc_cmap(&fbi->cmap); ++ goto out; ++ } + + /* + * if failed, all resources allocated above would be released by +@@ -184,58 +171,6 @@ out: + return ret; + } + +-static bool +-exynos_drm_fbdev_is_samefb(struct drm_framebuffer *fb, +- struct drm_fb_helper_surface_size *sizes) +-{ +- if (fb->width != sizes->surface_width) +- return false; +- if (fb->height != sizes->surface_height) +- return false; +- if (fb->bits_per_pixel != sizes->surface_bpp) +- return false; +- if (fb->depth != sizes->surface_depth) +- return false; +- +- return true; +-} +- +-static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper, +- struct drm_fb_helper_surface_size *sizes) +-{ +- struct drm_device *dev = helper->dev; +- struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper); +- struct drm_framebuffer *fb = exynos_fbdev->fb; +- struct drm_mode_fb_cmd mode_cmd = { 0 }; +- +- DRM_DEBUG_KMS("%s\n", __FILE__); +- +- if (helper->fb != fb) { +- DRM_ERROR("drm framebuffer is different\n"); +- return -EINVAL; +- } +- +- if (exynos_drm_fbdev_is_samefb(fb, sizes)) +- return 0; +- +- mode_cmd.width = sizes->surface_width; +- mode_cmd.height = sizes->surface_height; +- mode_cmd.bpp = sizes->surface_bpp; +- mode_cmd.depth = sizes->surface_depth; +- +- if (fb->funcs->destroy) +- fb->funcs->destroy(fb); +- +- exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd); +- if (IS_ERR(exynos_fbdev->fb)) { +- DRM_ERROR("failed to allocate fb.\n"); +- return PTR_ERR(exynos_fbdev->fb); +- } +- +- helper->fb = exynos_fbdev->fb; +- return exynos_drm_fbdev_update(helper, helper->fb); +-} +- + static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) + { +@@ -243,6 +178,10 @@ static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper, + + DRM_DEBUG_KMS("%s\n", __FILE__); + ++ /* ++ * with !helper->fb, it means that this funcion is called first time ++ * and after that, the helper->fb would be used as clone mode. ++ */ + if (!helper->fb) { + ret = exynos_drm_fbdev_create(helper, sizes); + if (ret < 0) { +@@ -255,12 +194,6 @@ static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper, + * because register_framebuffer() should be called. + */ + ret = 1; +- } else { +- ret = exynos_drm_fbdev_recreate(helper, sizes); +- if (ret < 0) { +- DRM_ERROR("failed to reconfigure fbdev\n"); +- return ret; +- } + } + + return ret; +@@ -366,6 +299,9 @@ void exynos_drm_fbdev_fini(struct drm_device *dev) + + fbdev = to_exynos_fbdev(private->fb_helper); + ++ if (fbdev->exynos_gem_obj) ++ exynos_drm_gem_destroy(fbdev->exynos_gem_obj); ++ + exynos_drm_fbdev_destroy(dev, private->fb_helper); + kfree(fbdev); + private->fb_helper = NULL; +@@ -380,89 +316,3 @@ void exynos_drm_fbdev_restore_mode(struct drm_device *dev) + + drm_fb_helper_restore_fbdev_mode(private->fb_helper); + } +- +-int exynos_drm_fbdev_reinit(struct drm_device *dev) +-{ +- struct exynos_drm_private *private = dev->dev_private; +- struct drm_fb_helper *fb_helper; +- int ret; +- +- if (!private) +- return -EINVAL; +- +- /* +- * if all sub drivers were unloaded then num_connector is 0 +- * so at this time, the framebuffers also should be destroyed. +- */ +- if (!dev->mode_config.num_connector) { +- exynos_drm_fbdev_fini(dev); +- return 0; +- } +- +- fb_helper = private->fb_helper; +- +- if (fb_helper) { +- struct list_head temp_list; +- +- INIT_LIST_HEAD(&temp_list); +- +- /* +- * fb_helper is reintialized but kernel fb is reused +- * so kernel_fb_list need to be backuped and restored +- */ +- if (!list_empty(&fb_helper->kernel_fb_list)) +- list_replace_init(&fb_helper->kernel_fb_list, +- &temp_list); +- +- drm_fb_helper_fini(fb_helper); +- +- ret = drm_fb_helper_init(dev, fb_helper, +- dev->mode_config.num_crtc, MAX_CONNECTOR); +- if (ret < 0) { +- DRM_ERROR("failed to initialize drm fb helper\n"); +- return ret; +- } +- +- if (!list_empty(&temp_list)) +- list_replace(&temp_list, &fb_helper->kernel_fb_list); +- +- ret = drm_fb_helper_single_add_all_connectors(fb_helper); +- if (ret < 0) { +- DRM_ERROR("failed to add fb helper to connectors\n"); +- goto err; +- } +- +- ret = drm_fb_helper_initial_config(fb_helper, PREFERRED_BPP); +- if (ret < 0) { +- DRM_ERROR("failed to set up hw configuration.\n"); +- goto err; +- } +- } else { +- /* +- * if drm_load() failed whem drm load() was called prior +- * to specific drivers, fb_helper must be NULL and so +- * this fuction should be called again to re-initialize and +- * re-configure the fb helper. it means that this function +- * has been called by the specific drivers. +- */ +- ret = exynos_drm_fbdev_init(dev); +- } +- +- return ret; +- +-err: +- /* +- * if drm_load() failed when drm load() was called prior +- * to specific drivers, the fb_helper must be NULL and so check it. +- */ +- if (fb_helper) +- drm_fb_helper_fini(fb_helper); +- +- return ret; +-} +- +-MODULE_AUTHOR("Inki Dae "); +-MODULE_AUTHOR("Joonyoung Shim "); +-MODULE_AUTHOR("Seung-Woo Kim "); +-MODULE_DESCRIPTION("Samsung SoC DRM FBDEV Driver"); +-MODULE_LICENSE("GPL"); +diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c +index db3b3d9..29fdbfe 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -68,6 +69,7 @@ struct fimd_win_data { + void __iomem *vaddr; + unsigned int buf_offsize; + unsigned int line_size; /* bytes */ ++ bool enabled; + }; + + struct fimd_context { +@@ -84,8 +86,10 @@ struct fimd_context { + unsigned long irq_flags; + u32 vidcon0; + u32 vidcon1; ++ bool suspended; ++ struct mutex lock; + +- struct fb_videomode *timing; ++ struct exynos_drm_panel_info *panel; + }; + + static bool fimd_display_is_connected(struct device *dev) +@@ -97,13 +101,13 @@ static bool fimd_display_is_connected(struct device *dev) + return true; + } + +-static void *fimd_get_timing(struct device *dev) ++static void *fimd_get_panel(struct device *dev) + { + struct fimd_context *ctx = get_fimd_context(dev); + + DRM_DEBUG_KMS("%s\n", __FILE__); + +- return ctx->timing; ++ return ctx->panel; + } + + static int fimd_check_timing(struct device *dev, void *timing) +@@ -119,7 +123,7 @@ static int fimd_display_power_on(struct device *dev, int mode) + { + DRM_DEBUG_KMS("%s\n", __FILE__); + +- /* TODO. */ ++ /* TODO */ + + return 0; + } +@@ -127,17 +131,75 @@ static int fimd_display_power_on(struct device *dev, int mode) + static struct exynos_drm_display_ops fimd_display_ops = { + .type = EXYNOS_DISPLAY_TYPE_LCD, + .is_connected = fimd_display_is_connected, +- .get_timing = fimd_get_timing, ++ .get_panel = fimd_get_panel, + .check_timing = fimd_check_timing, + .power_on = fimd_display_power_on, + }; + ++static void fimd_dpms(struct device *subdrv_dev, int mode) ++{ ++ struct fimd_context *ctx = get_fimd_context(subdrv_dev); ++ ++ DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode); ++ ++ mutex_lock(&ctx->lock); ++ ++ switch (mode) { ++ case DRM_MODE_DPMS_ON: ++ /* ++ * enable fimd hardware only if suspended status. ++ * ++ * P.S. fimd_dpms function would be called at booting time so ++ * clk_enable could be called double time. ++ */ ++ if (ctx->suspended) ++ pm_runtime_get_sync(subdrv_dev); ++ break; ++ case DRM_MODE_DPMS_STANDBY: ++ case DRM_MODE_DPMS_SUSPEND: ++ case DRM_MODE_DPMS_OFF: ++ if (!ctx->suspended) ++ pm_runtime_put_sync(subdrv_dev); ++ break; ++ default: ++ DRM_DEBUG_KMS("unspecified mode %d\n", mode); ++ break; ++ } ++ ++ mutex_unlock(&ctx->lock); ++} ++ ++static void fimd_apply(struct device *subdrv_dev) ++{ ++ struct fimd_context *ctx = get_fimd_context(subdrv_dev); ++ struct exynos_drm_manager *mgr = ctx->subdrv.manager; ++ struct exynos_drm_manager_ops *mgr_ops = mgr->ops; ++ struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops; ++ struct fimd_win_data *win_data; ++ int i; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ for (i = 0; i < WINDOWS_NR; i++) { ++ win_data = &ctx->win_data[i]; ++ if (win_data->enabled && (ovl_ops && ovl_ops->commit)) ++ ovl_ops->commit(subdrv_dev, i); ++ } ++ ++ if (mgr_ops && mgr_ops->commit) ++ mgr_ops->commit(subdrv_dev); ++} ++ + static void fimd_commit(struct device *dev) + { + struct fimd_context *ctx = get_fimd_context(dev); +- struct fb_videomode *timing = ctx->timing; ++ struct exynos_drm_panel_info *panel = ctx->panel; ++ struct fb_videomode *timing = &panel->timing; + u32 val; + ++ if (ctx->suspended) ++ return; ++ + DRM_DEBUG_KMS("%s\n", __FILE__); + + /* setup polarity values from machine code. */ +@@ -177,40 +239,6 @@ static void fimd_commit(struct device *dev) + writel(val, ctx->regs + VIDCON0); + } + +-static void fimd_disable(struct device *dev) +-{ +- struct fimd_context *ctx = get_fimd_context(dev); +- struct exynos_drm_subdrv *subdrv = &ctx->subdrv; +- struct drm_device *drm_dev = subdrv->drm_dev; +- struct exynos_drm_manager *manager = &subdrv->manager; +- u32 val; +- +- DRM_DEBUG_KMS("%s\n", __FILE__); +- +- /* fimd dma off */ +- val = readl(ctx->regs + VIDCON0); +- val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F); +- writel(val, ctx->regs + VIDCON0); +- +- /* +- * if vblank is enabled status with dma off then +- * it disables vsync interrupt. +- */ +- if (drm_dev->vblank_enabled[manager->pipe] && +- atomic_read(&drm_dev->vblank_refcount[manager->pipe])) { +- drm_vblank_put(drm_dev, manager->pipe); +- +- /* +- * if vblank_disable_allowed is 0 then disable +- * vsync interrupt right now else the vsync interrupt +- * would be disabled by drm timer once a current process +- * gives up ownershop of vblank event. +- */ +- if (!drm_dev->vblank_disable_allowed) +- drm_vblank_off(drm_dev, manager->pipe); +- } +-} +- + static int fimd_enable_vblank(struct device *dev) + { + struct fimd_context *ctx = get_fimd_context(dev); +@@ -218,6 +246,9 @@ static int fimd_enable_vblank(struct device *dev) + + DRM_DEBUG_KMS("%s\n", __FILE__); + ++ if (ctx->suspended) ++ return -EPERM; ++ + if (!test_and_set_bit(0, &ctx->irq_flags)) { + val = readl(ctx->regs + VIDINTCON0); + +@@ -242,6 +273,9 @@ static void fimd_disable_vblank(struct device *dev) + + DRM_DEBUG_KMS("%s\n", __FILE__); + ++ if (ctx->suspended) ++ return; ++ + if (test_and_clear_bit(0, &ctx->irq_flags)) { + val = readl(ctx->regs + VIDINTCON0); + +@@ -253,8 +287,9 @@ static void fimd_disable_vblank(struct device *dev) + } + + static struct exynos_drm_manager_ops fimd_manager_ops = { ++ .dpms = fimd_dpms, ++ .apply = fimd_apply, + .commit = fimd_commit, +- .disable = fimd_disable, + .enable_vblank = fimd_enable_vblank, + .disable_vblank = fimd_disable_vblank, + }; +@@ -264,6 +299,7 @@ static void fimd_win_mode_set(struct device *dev, + { + struct fimd_context *ctx = get_fimd_context(dev); + struct fimd_win_data *win_data; ++ int win; + unsigned long offset; + + DRM_DEBUG_KMS("%s\n", __FILE__); +@@ -273,12 +309,19 @@ static void fimd_win_mode_set(struct device *dev, + return; + } + ++ win = overlay->zpos; ++ if (win == DEFAULT_ZPOS) ++ win = ctx->default_win; ++ ++ if (win < 0 || win > WINDOWS_NR) ++ return; ++ + offset = overlay->fb_x * (overlay->bpp >> 3); + offset += overlay->fb_y * overlay->pitch; + + DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch); + +- win_data = &ctx->win_data[ctx->default_win]; ++ win_data = &ctx->win_data[win]; + + win_data->offset_x = overlay->crtc_x; + win_data->offset_y = overlay->crtc_y; +@@ -286,8 +329,8 @@ static void fimd_win_mode_set(struct device *dev, + win_data->ovl_height = overlay->crtc_height; + win_data->fb_width = overlay->fb_width; + win_data->fb_height = overlay->fb_height; +- win_data->dma_addr = overlay->dma_addr + offset; +- win_data->vaddr = overlay->vaddr + offset; ++ win_data->dma_addr = overlay->dma_addr[0] + offset; ++ win_data->vaddr = overlay->vaddr[0] + offset; + win_data->bpp = overlay->bpp; + win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * + (overlay->bpp >> 3); +@@ -381,15 +424,21 @@ static void fimd_win_set_colkey(struct device *dev, unsigned int win) + writel(keycon1, ctx->regs + WKEYCON1_BASE(win)); + } + +-static void fimd_win_commit(struct device *dev) ++static void fimd_win_commit(struct device *dev, int zpos) + { + struct fimd_context *ctx = get_fimd_context(dev); + struct fimd_win_data *win_data; +- int win = ctx->default_win; ++ int win = zpos; + unsigned long val, alpha, size; + + DRM_DEBUG_KMS("%s\n", __FILE__); + ++ if (ctx->suspended) ++ return; ++ ++ if (win == DEFAULT_ZPOS) ++ win = ctx->default_win; ++ + if (win < 0 || win > WINDOWS_NR) + return; + +@@ -472,24 +521,37 @@ static void fimd_win_commit(struct device *dev) + if (win != 0) + fimd_win_set_colkey(dev, win); + ++ /* wincon */ ++ val = readl(ctx->regs + WINCON(win)); ++ val |= WINCONx_ENWIN; ++ writel(val, ctx->regs + WINCON(win)); ++ + /* Enable DMA channel and unprotect windows */ + val = readl(ctx->regs + SHADOWCON); + val |= SHADOWCON_CHx_ENABLE(win); + val &= ~SHADOWCON_WINx_PROTECT(win); + writel(val, ctx->regs + SHADOWCON); ++ ++ win_data->enabled = true; + } + +-static void fimd_win_disable(struct device *dev) ++static void fimd_win_disable(struct device *dev, int zpos) + { + struct fimd_context *ctx = get_fimd_context(dev); +- int win = ctx->default_win; ++ struct fimd_win_data *win_data; ++ int win = zpos; + u32 val; + + DRM_DEBUG_KMS("%s\n", __FILE__); + ++ if (win == DEFAULT_ZPOS) ++ win = ctx->default_win; ++ + if (win < 0 || win > WINDOWS_NR) + return; + ++ win_data = &ctx->win_data[win]; ++ + /* protect windows */ + val = readl(ctx->regs + SHADOWCON); + val |= SHADOWCON_WINx_PROTECT(win); +@@ -505,6 +567,8 @@ static void fimd_win_disable(struct device *dev) + val &= ~SHADOWCON_CHx_ENABLE(win); + val &= ~SHADOWCON_WINx_PROTECT(win); + writel(val, ctx->regs + SHADOWCON); ++ ++ win_data->enabled = false; + } + + static struct exynos_drm_overlay_ops fimd_overlay_ops = { +@@ -513,6 +577,13 @@ static struct exynos_drm_overlay_ops fimd_overlay_ops = { + .disable = fimd_win_disable, + }; + ++static struct exynos_drm_manager fimd_manager = { ++ .pipe = -1, ++ .ops = &fimd_manager_ops, ++ .overlay_ops = &fimd_overlay_ops, ++ .display_ops = &fimd_display_ops, ++}; ++ + static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc) + { + struct exynos_drm_private *dev_priv = drm_dev->dev_private; +@@ -540,8 +611,21 @@ static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc) + wake_up_interruptible(&e->base.file_priv->event_wait); + } + +- if (is_checked) +- drm_vblank_put(drm_dev, crtc); ++ if (is_checked) { ++ /* ++ * call drm_vblank_put only in case that drm_vblank_get was ++ * called. ++ */ ++ if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0) ++ drm_vblank_put(drm_dev, crtc); ++ ++ /* ++ * don't off vblank if vblank_disable_allowed is 1, ++ * because vblank would be off by timer handler. ++ */ ++ if (!drm_dev->vblank_disable_allowed) ++ drm_vblank_off(drm_dev, crtc); ++ } + + spin_unlock_irqrestore(&drm_dev->event_lock, flags); + } +@@ -551,7 +635,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id) + struct fimd_context *ctx = (struct fimd_context *)dev_id; + struct exynos_drm_subdrv *subdrv = &ctx->subdrv; + struct drm_device *drm_dev = subdrv->drm_dev; +- struct exynos_drm_manager *manager = &subdrv->manager; ++ struct exynos_drm_manager *manager = subdrv->manager; + u32 val; + + val = readl(ctx->regs + VIDINTCON1); +@@ -560,19 +644,14 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id) + /* VSYNC interrupt */ + writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1); + +- /* +- * in case that vblank_disable_allowed is 1, it could induce +- * the problem that manager->pipe could be -1 because with +- * disable callback, vsync interrupt isn't disabled and at this moment, +- * vsync interrupt could occur. the vsync interrupt would be disabled +- * by timer handler later. +- */ +- if (manager->pipe == -1) +- return IRQ_HANDLED; ++ /* check the crtc is detached already from encoder */ ++ if (manager->pipe < 0) ++ goto out; + + drm_handle_vblank(drm_dev, manager->pipe); + fimd_finish_pageflip(drm_dev, manager->pipe); + ++out: + return IRQ_HANDLED; + } + +@@ -590,6 +669,13 @@ static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev) + */ + drm_dev->irq_enabled = 1; + ++ /* ++ * with vblank_disable_allowed = 1, vblank interrupt will be disabled ++ * by drm timer once a current process gives up ownership of ++ * vblank event.(after drm_vblank_put function is called) ++ */ ++ drm_dev->vblank_disable_allowed = 1; ++ + return 0; + } + +@@ -662,13 +748,53 @@ static void fimd_clear_win(struct fimd_context *ctx, int win) + writel(val, ctx->regs + SHADOWCON); + } + ++static int fimd_power_on(struct fimd_context *ctx, bool enable) ++{ ++ struct exynos_drm_subdrv *subdrv = &ctx->subdrv; ++ struct device *dev = subdrv->dev; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (enable != false && enable != true) ++ return -EINVAL; ++ ++ if (enable) { ++ int ret; ++ ++ ret = clk_enable(ctx->bus_clk); ++ if (ret < 0) ++ return ret; ++ ++ ret = clk_enable(ctx->lcd_clk); ++ if (ret < 0) { ++ clk_disable(ctx->bus_clk); ++ return ret; ++ } ++ ++ ctx->suspended = false; ++ ++ /* if vblank was enabled status, enable it again. */ ++ if (test_and_clear_bit(0, &ctx->irq_flags)) ++ fimd_enable_vblank(dev); ++ ++ fimd_apply(dev); ++ } else { ++ clk_disable(ctx->lcd_clk); ++ clk_disable(ctx->bus_clk); ++ ++ ctx->suspended = true; ++ } ++ ++ return 0; ++} ++ + static int __devinit fimd_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct fimd_context *ctx; + struct exynos_drm_subdrv *subdrv; + struct exynos_drm_fimd_pdata *pdata; +- struct fb_videomode *timing; ++ struct exynos_drm_panel_info *panel; + struct resource *res; + int win; + int ret = -EINVAL; +@@ -681,9 +807,9 @@ static int __devinit fimd_probe(struct platform_device *pdev) + return -EINVAL; + } + +- timing = &pdata->timing; +- if (!timing) { +- dev_err(dev, "timing is null.\n"); ++ panel = &pdata->panel; ++ if (!panel) { ++ dev_err(dev, "panel is null.\n"); + return -EINVAL; + } + +@@ -698,8 +824,6 @@ static int __devinit fimd_probe(struct platform_device *pdev) + goto err_clk_get; + } + +- clk_enable(ctx->bus_clk); +- + ctx->lcd_clk = clk_get(dev, "sclk_fimd"); + if (IS_ERR(ctx->lcd_clk)) { + dev_err(dev, "failed to get lcd clock\n"); +@@ -707,8 +831,6 @@ static int __devinit fimd_probe(struct platform_device *pdev) + goto err_bus_clk; + } + +- clk_enable(ctx->lcd_clk); +- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "failed to find registers\n"); +@@ -739,37 +861,40 @@ static int __devinit fimd_probe(struct platform_device *pdev) + + ctx->irq = res->start; + +- for (win = 0; win < WINDOWS_NR; win++) +- fimd_clear_win(ctx, win); +- + ret = request_irq(ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx); + if (ret < 0) { + dev_err(dev, "irq request failed.\n"); + goto err_req_irq; + } + +- ctx->clkdiv = fimd_calc_clkdiv(ctx, timing); + ctx->vidcon0 = pdata->vidcon0; + ctx->vidcon1 = pdata->vidcon1; + ctx->default_win = pdata->default_win; +- ctx->timing = timing; +- +- timing->pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv; +- +- DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n", +- timing->pixclock, ctx->clkdiv); ++ ctx->panel = panel; + + subdrv = &ctx->subdrv; + ++ subdrv->dev = dev; ++ subdrv->manager = &fimd_manager; + subdrv->probe = fimd_subdrv_probe; + subdrv->remove = fimd_subdrv_remove; +- subdrv->manager.pipe = -1; +- subdrv->manager.ops = &fimd_manager_ops; +- subdrv->manager.overlay_ops = &fimd_overlay_ops; +- subdrv->manager.display_ops = &fimd_display_ops; +- subdrv->manager.dev = dev; ++ ++ mutex_init(&ctx->lock); + + platform_set_drvdata(pdev, ctx); ++ ++ pm_runtime_enable(dev); ++ pm_runtime_get_sync(dev); ++ ++ ctx->clkdiv = fimd_calc_clkdiv(ctx, &panel->timing); ++ panel->timing.pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv; ++ ++ DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n", ++ panel->timing.pixclock, ctx->clkdiv); ++ ++ for (win = 0; win < WINDOWS_NR; win++) ++ fimd_clear_win(ctx, win); ++ + exynos_drm_subdrv_register(subdrv); + + return 0; +@@ -797,14 +922,25 @@ err_clk_get: + + static int __devexit fimd_remove(struct platform_device *pdev) + { ++ struct device *dev = &pdev->dev; + struct fimd_context *ctx = platform_get_drvdata(pdev); + + DRM_DEBUG_KMS("%s\n", __FILE__); + + exynos_drm_subdrv_unregister(&ctx->subdrv); + ++ if (ctx->suspended) ++ goto out; ++ + clk_disable(ctx->lcd_clk); + clk_disable(ctx->bus_clk); ++ ++ pm_runtime_set_suspended(dev); ++ pm_runtime_put_sync(dev); ++ ++out: ++ pm_runtime_disable(dev); ++ + clk_put(ctx->lcd_clk); + clk_put(ctx->bus_clk); + +@@ -818,29 +954,69 @@ static int __devexit fimd_remove(struct platform_device *pdev) + return 0; + } + +-static struct platform_driver fimd_driver = { +- .probe = fimd_probe, +- .remove = __devexit_p(fimd_remove), +- .driver = { +- .name = "exynos4-fb", +- .owner = THIS_MODULE, +- }, +-}; ++#ifdef CONFIG_PM_SLEEP ++static int fimd_suspend(struct device *dev) ++{ ++ struct fimd_context *ctx = get_fimd_context(dev); ++ ++ if (pm_runtime_suspended(dev)) ++ return 0; ++ ++ /* ++ * do not use pm_runtime_suspend(). if pm_runtime_suspend() is ++ * called here, an error would be returned by that interface ++ * because the usage_count of pm runtime is more than 1. ++ */ ++ return fimd_power_on(ctx, false); ++} ++ ++static int fimd_resume(struct device *dev) ++{ ++ struct fimd_context *ctx = get_fimd_context(dev); ++ ++ /* ++ * if entered to sleep when lcd panel was on, the usage_count ++ * of pm runtime would still be 1 so in this case, fimd driver ++ * should be on directly not drawing on pm runtime interface. ++ */ ++ if (!pm_runtime_suspended(dev)) ++ return fimd_power_on(ctx, true); + +-static int __init fimd_init(void) ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_PM_RUNTIME ++static int fimd_runtime_suspend(struct device *dev) + { +- return platform_driver_register(&fimd_driver); ++ struct fimd_context *ctx = get_fimd_context(dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ return fimd_power_on(ctx, false); + } + +-static void __exit fimd_exit(void) ++static int fimd_runtime_resume(struct device *dev) + { +- platform_driver_unregister(&fimd_driver); ++ struct fimd_context *ctx = get_fimd_context(dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ return fimd_power_on(ctx, true); + } ++#endif + +-module_init(fimd_init); +-module_exit(fimd_exit); ++static const struct dev_pm_ops fimd_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume) ++ SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL) ++}; + +-MODULE_AUTHOR("Joonyoung Shim "); +-MODULE_AUTHOR("Inki Dae "); +-MODULE_DESCRIPTION("Samsung DRM FIMD Driver"); +-MODULE_LICENSE("GPL"); ++struct platform_driver fimd_driver = { ++ .probe = fimd_probe, ++ .remove = __devexit_p(fimd_remove), ++ .driver = { ++ .name = "exynos4-fb", ++ .owner = THIS_MODULE, ++ .pm = &fimd_pm_ops, ++ }, ++}; +diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c +index aba0fe4..01139c8 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c +@@ -26,6 +26,7 @@ + #include "drmP.h" + #include "drm.h" + ++#include + #include + + #include "exynos_drm_drv.h" +@@ -55,118 +56,413 @@ static unsigned int convert_to_vm_err_msg(int msg) + return out_msg; + } + +-static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj) ++static int check_gem_flags(unsigned int flags) + { +- DRM_DEBUG_KMS("%s\n", __FILE__); ++ if (flags & ~(EXYNOS_BO_MASK)) { ++ DRM_ERROR("invalid flags.\n"); ++ return -EINVAL; ++ } + +- return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT; ++ return 0; + } + +-static struct exynos_drm_gem_obj +- *exynos_drm_gem_init(struct drm_device *drm_dev, +- struct drm_file *file_priv, unsigned int *handle, +- unsigned int size) ++static unsigned long roundup_gem_size(unsigned long size, unsigned int flags) + { +- struct exynos_drm_gem_obj *exynos_gem_obj; +- struct drm_gem_object *obj; +- int ret; ++ if (!IS_NONCONTIG_BUFFER(flags)) { ++ if (size >= SZ_1M) ++ return roundup(size, SECTION_SIZE); ++ else if (size >= SZ_64K) ++ return roundup(size, SZ_64K); ++ else ++ goto out; ++ } ++out: ++ return roundup(size, PAGE_SIZE); ++} + +- exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL); +- if (!exynos_gem_obj) { +- DRM_ERROR("failed to allocate exynos gem object.\n"); ++static struct page **exynos_gem_get_pages(struct drm_gem_object *obj, ++ gfp_t gfpmask) ++{ ++ struct inode *inode; ++ struct address_space *mapping; ++ struct page *p, **pages; ++ int i, npages; ++ ++ /* This is the shared memory object that backs the GEM resource */ ++ inode = obj->filp->f_path.dentry->d_inode; ++ mapping = inode->i_mapping; ++ ++ npages = obj->size >> PAGE_SHIFT; ++ ++ pages = drm_malloc_ab(npages, sizeof(struct page *)); ++ if (pages == NULL) + return ERR_PTR(-ENOMEM); ++ ++ gfpmask |= mapping_gfp_mask(mapping); ++ ++ for (i = 0; i < npages; i++) { ++ p = shmem_read_mapping_page_gfp(mapping, i, gfpmask); ++ if (IS_ERR(p)) ++ goto fail; ++ pages[i] = p; + } + +- obj = &exynos_gem_obj->base; ++ return pages; + +- ret = drm_gem_object_init(drm_dev, obj, size); +- if (ret < 0) { +- DRM_ERROR("failed to initialize gem object.\n"); +- ret = -EINVAL; +- goto err_object_init; ++fail: ++ while (i--) ++ page_cache_release(pages[i]); ++ ++ drm_free_large(pages); ++ return ERR_PTR(PTR_ERR(p)); ++} ++ ++static void exynos_gem_put_pages(struct drm_gem_object *obj, ++ struct page **pages, ++ bool dirty, bool accessed) ++{ ++ int i, npages; ++ ++ npages = obj->size >> PAGE_SHIFT; ++ ++ for (i = 0; i < npages; i++) { ++ if (dirty) ++ set_page_dirty(pages[i]); ++ ++ if (accessed) ++ mark_page_accessed(pages[i]); ++ ++ /* Undo the reference we took when populating the table */ ++ page_cache_release(pages[i]); + } + +- DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp); ++ drm_free_large(pages); ++} + +- ret = drm_gem_create_mmap_offset(obj); ++static int exynos_drm_gem_map_pages(struct drm_gem_object *obj, ++ struct vm_area_struct *vma, ++ unsigned long f_vaddr, ++ pgoff_t page_offset) ++{ ++ struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); ++ struct exynos_drm_gem_buf *buf = exynos_gem_obj->buffer; ++ unsigned long pfn; ++ ++ if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) { ++ if (!buf->pages) ++ return -EINTR; ++ ++ pfn = page_to_pfn(buf->pages[page_offset++]); ++ } else ++ pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset; ++ ++ return vm_insert_mixed(vma, f_vaddr, pfn); ++} ++ ++static int exynos_drm_gem_get_pages(struct drm_gem_object *obj) ++{ ++ struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); ++ struct exynos_drm_gem_buf *buf = exynos_gem_obj->buffer; ++ struct scatterlist *sgl; ++ struct page **pages; ++ unsigned int npages, i = 0; ++ int ret; ++ ++ if (buf->pages) { ++ DRM_DEBUG_KMS("already allocated.\n"); ++ return -EINVAL; ++ } ++ ++ pages = exynos_gem_get_pages(obj, GFP_KERNEL); ++ if (IS_ERR(pages)) { ++ DRM_ERROR("failed to get pages.\n"); ++ return PTR_ERR(pages); ++ } ++ ++ npages = obj->size >> PAGE_SHIFT; ++ ++ buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); ++ if (!buf->sgt) { ++ DRM_ERROR("failed to allocate sg table.\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ ret = sg_alloc_table(buf->sgt, npages, GFP_KERNEL); + if (ret < 0) { +- DRM_ERROR("failed to allocate mmap offset.\n"); +- goto err_create_mmap_offset; ++ DRM_ERROR("failed to initialize sg table.\n"); ++ ret = -EFAULT; ++ goto err1; ++ } ++ ++ sgl = buf->sgt->sgl; ++ ++ /* set all pages to sg list. */ ++ while (i < npages) { ++ sg_set_page(sgl, pages[i], PAGE_SIZE, 0); ++ sg_dma_address(sgl) = page_to_phys(pages[i]); ++ i++; ++ sgl = sg_next(sgl); + } + ++ /* add some codes for UNCACHED type here. TODO */ ++ ++ buf->pages = pages; ++ return ret; ++err1: ++ kfree(buf->sgt); ++ buf->sgt = NULL; ++err: ++ exynos_gem_put_pages(obj, pages, true, false); ++ return ret; ++ ++} ++ ++static void exynos_drm_gem_put_pages(struct drm_gem_object *obj) ++{ ++ struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); ++ struct exynos_drm_gem_buf *buf = exynos_gem_obj->buffer; ++ ++ /* ++ * if buffer typs is EXYNOS_BO_NONCONTIG then release all pages ++ * allocated at gem fault handler. ++ */ ++ sg_free_table(buf->sgt); ++ kfree(buf->sgt); ++ buf->sgt = NULL; ++ ++ exynos_gem_put_pages(obj, buf->pages, true, false); ++ buf->pages = NULL; ++ ++ /* add some codes for UNCACHED type here. TODO */ ++} ++ ++static int exynos_drm_gem_handle_create(struct drm_gem_object *obj, ++ struct drm_file *file_priv, ++ unsigned int *handle) ++{ ++ int ret; ++ + /* + * allocate a id of idr table where the obj is registered + * and handle has the id what user can see. + */ + ret = drm_gem_handle_create(file_priv, obj, handle); + if (ret) +- goto err_handle_create; ++ return ret; + + DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle); + + /* drop reference from allocate - handle holds it now. */ + drm_gem_object_unreference_unlocked(obj); + +- return exynos_gem_obj; ++ return 0; ++} ++ ++void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj) ++{ ++ struct drm_gem_object *obj; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (!exynos_gem_obj) ++ return; + +-err_handle_create: +- drm_gem_free_mmap_offset(obj); ++ obj = &exynos_gem_obj->base; ++ ++ DRM_DEBUG_KMS("handle count = %d\n", atomic_read(&obj->handle_count)); ++ ++ if ((exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) && ++ exynos_gem_obj->buffer->pages) ++ exynos_drm_gem_put_pages(obj); ++ else ++ exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags, ++ exynos_gem_obj->buffer); ++ ++ exynos_drm_fini_buf(obj->dev, exynos_gem_obj->buffer); ++ exynos_gem_obj->buffer = NULL; + +-err_create_mmap_offset: ++ if (obj->map_list.map) ++ drm_gem_free_mmap_offset(obj); ++ ++ /* release file pointer to gem object. */ + drm_gem_object_release(obj); + +-err_object_init: + kfree(exynos_gem_obj); ++ exynos_gem_obj = NULL; ++} + +- return ERR_PTR(ret); ++static struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev, ++ unsigned long size) ++{ ++ struct exynos_drm_gem_obj *exynos_gem_obj; ++ struct drm_gem_object *obj; ++ int ret; ++ ++ exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL); ++ if (!exynos_gem_obj) { ++ DRM_ERROR("failed to allocate exynos gem object\n"); ++ return NULL; ++ } ++ ++ exynos_gem_obj->size = size; ++ obj = &exynos_gem_obj->base; ++ ++ ret = drm_gem_object_init(dev, obj, size); ++ if (ret < 0) { ++ DRM_ERROR("failed to initialize gem object\n"); ++ kfree(exynos_gem_obj); ++ return NULL; ++ } ++ ++ DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp); ++ ++ return exynos_gem_obj; + } + + struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, +- struct drm_file *file_priv, +- unsigned int *handle, unsigned long size) ++ unsigned int flags, ++ unsigned long size) + { ++ struct exynos_drm_gem_obj *exynos_gem_obj; ++ struct exynos_drm_gem_buf *buf; ++ int ret; + +- struct exynos_drm_gem_obj *exynos_gem_obj = NULL; +- struct exynos_drm_gem_buf *buffer; ++ if (!size) { ++ DRM_ERROR("invalid size.\n"); ++ return ERR_PTR(-EINVAL); ++ } + +- size = roundup(size, PAGE_SIZE); ++ size = roundup_gem_size(size, flags); ++ DRM_DEBUG_KMS("%s\n", __FILE__); + +- DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size); ++ ret = check_gem_flags(flags); ++ if (ret) ++ return ERR_PTR(ret); + +- buffer = exynos_drm_buf_create(dev, size); +- if (IS_ERR(buffer)) { +- return ERR_CAST(buffer); +- } ++ buf = exynos_drm_init_buf(dev, size); ++ if (!buf) ++ return ERR_PTR(-ENOMEM); + +- exynos_gem_obj = exynos_drm_gem_init(dev, file_priv, handle, size); +- if (IS_ERR(exynos_gem_obj)) { +- exynos_drm_buf_destroy(dev, buffer); +- return exynos_gem_obj; ++ exynos_gem_obj = exynos_drm_gem_init(dev, size); ++ if (!exynos_gem_obj) { ++ ret = -ENOMEM; ++ goto err_fini_buf; + } + +- exynos_gem_obj->buffer = buffer; ++ exynos_gem_obj->buffer = buf; ++ ++ /* set memory type and cache attribute from user side. */ ++ exynos_gem_obj->flags = flags; ++ ++ /* ++ * allocate all pages as desired size if user wants to allocate ++ * physically non-continuous memory. ++ */ ++ if (flags & EXYNOS_BO_NONCONTIG) { ++ ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base); ++ if (ret < 0) { ++ drm_gem_object_release(&exynos_gem_obj->base); ++ goto err_fini_buf; ++ } ++ } else { ++ ret = exynos_drm_alloc_buf(dev, buf, flags); ++ if (ret < 0) { ++ drm_gem_object_release(&exynos_gem_obj->base); ++ goto err_fini_buf; ++ } ++ } + + return exynos_gem_obj; ++ ++err_fini_buf: ++ exynos_drm_fini_buf(dev, buf); ++ return ERR_PTR(ret); + } + + int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv) ++ struct drm_file *file_priv) + { + struct drm_exynos_gem_create *args = data; +- struct exynos_drm_gem_obj *exynos_gem_obj = NULL; ++ struct exynos_drm_gem_obj *exynos_gem_obj; ++ int ret; + + DRM_DEBUG_KMS("%s\n", __FILE__); + +- exynos_gem_obj = exynos_drm_gem_create(dev, file_priv, +- &args->handle, args->size); ++ exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size); + if (IS_ERR(exynos_gem_obj)) + return PTR_ERR(exynos_gem_obj); + ++ ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv, ++ &args->handle); ++ if (ret) { ++ exynos_drm_gem_destroy(exynos_gem_obj); ++ return ret; ++ } ++ + return 0; + } + ++void *exynos_drm_gem_get_dma_addr(struct drm_device *dev, ++ unsigned int gem_handle, ++ struct drm_file *file_priv) ++{ ++ struct exynos_drm_gem_obj *exynos_gem_obj; ++ struct drm_gem_object *obj; ++ ++ obj = drm_gem_object_lookup(dev, file_priv, gem_handle); ++ if (!obj) { ++ DRM_ERROR("failed to lookup gem object.\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ exynos_gem_obj = to_exynos_gem_obj(obj); ++ ++ if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) { ++ DRM_DEBUG_KMS("not support NONCONTIG type.\n"); ++ drm_gem_object_unreference_unlocked(obj); ++ ++ /* TODO */ ++ return ERR_PTR(-EINVAL); ++ } ++ ++ return &exynos_gem_obj->buffer->dma_addr; ++} ++ ++void exynos_drm_gem_put_dma_addr(struct drm_device *dev, ++ unsigned int gem_handle, ++ struct drm_file *file_priv) ++{ ++ struct exynos_drm_gem_obj *exynos_gem_obj; ++ struct drm_gem_object *obj; ++ ++ obj = drm_gem_object_lookup(dev, file_priv, gem_handle); ++ if (!obj) { ++ DRM_ERROR("failed to lookup gem object.\n"); ++ return; ++ } ++ ++ exynos_gem_obj = to_exynos_gem_obj(obj); ++ ++ if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) { ++ DRM_DEBUG_KMS("not support NONCONTIG type.\n"); ++ drm_gem_object_unreference_unlocked(obj); ++ ++ /* TODO */ ++ return; ++ } ++ ++ drm_gem_object_unreference_unlocked(obj); ++ ++ /* ++ * decrease obj->refcount one more time because we has already ++ * increased it at exynos_drm_gem_get_dma_addr(). ++ */ ++ drm_gem_object_unreference_unlocked(obj); ++} ++ + int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv) ++ struct drm_file *file_priv) + { + struct drm_exynos_gem_map_off *args = data; + +@@ -185,21 +481,23 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data, + } + + static int exynos_drm_gem_mmap_buffer(struct file *filp, +- struct vm_area_struct *vma) ++ struct vm_area_struct *vma) + { + struct drm_gem_object *obj = filp->private_data; + struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); + struct exynos_drm_gem_buf *buffer; +- unsigned long pfn, vm_size; ++ unsigned long pfn, vm_size, usize, uaddr = vma->vm_start; ++ int ret; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + vma->vm_flags |= (VM_IO | VM_RESERVED); + ++ /* in case of direct mapping, always having non-cachable attribute */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +- vma->vm_file = filp; + +- vm_size = vma->vm_end - vma->vm_start; ++ vm_size = usize = vma->vm_end - vma->vm_start; ++ + /* + * a buffer contains information to physically continuous memory + * allocated by user request or at framebuffer creation. +@@ -210,18 +508,39 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp, + if (vm_size > buffer->size) + return -EINVAL; + +- /* +- * get page frame number to physical memory to be mapped +- * to user space. +- */ +- pfn = ((unsigned long)exynos_gem_obj->buffer->dma_addr) >> PAGE_SHIFT; +- +- DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn); +- +- if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size, +- vma->vm_page_prot)) { +- DRM_ERROR("failed to remap pfn range.\n"); +- return -EAGAIN; ++ if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) { ++ int i = 0; ++ ++ if (!buffer->pages) ++ return -EINVAL; ++ ++ vma->vm_flags |= VM_MIXEDMAP; ++ ++ do { ++ ret = vm_insert_page(vma, uaddr, buffer->pages[i++]); ++ if (ret) { ++ DRM_ERROR("failed to remap user space.\n"); ++ return ret; ++ } ++ ++ uaddr += PAGE_SIZE; ++ usize -= PAGE_SIZE; ++ } while (usize > 0); ++ } else { ++ /* ++ * get page frame number to physical memory to be mapped ++ * to user space. ++ */ ++ pfn = ((unsigned long)exynos_gem_obj->buffer->dma_addr) >> ++ PAGE_SHIFT; ++ ++ DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn); ++ ++ if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size, ++ vma->vm_page_prot)) { ++ DRM_ERROR("failed to remap pfn range.\n"); ++ return -EAGAIN; ++ } + } + + return 0; +@@ -232,7 +551,7 @@ static const struct file_operations exynos_drm_gem_fops = { + }; + + int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv) ++ struct drm_file *file_priv) + { + struct drm_exynos_gem_mmap *args = data; + struct drm_gem_object *obj; +@@ -278,32 +597,19 @@ int exynos_drm_gem_init_object(struct drm_gem_object *obj) + return 0; + } + +-void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj) ++void exynos_drm_gem_free_object(struct drm_gem_object *obj) + { +- struct exynos_drm_gem_obj *exynos_gem_obj; +- + DRM_DEBUG_KMS("%s\n", __FILE__); + +- DRM_DEBUG_KMS("handle count = %d\n", +- atomic_read(&gem_obj->handle_count)); +- +- if (gem_obj->map_list.map) +- drm_gem_free_mmap_offset(gem_obj); +- +- /* release file pointer to gem object. */ +- drm_gem_object_release(gem_obj); +- +- exynos_gem_obj = to_exynos_gem_obj(gem_obj); +- +- exynos_drm_buf_destroy(gem_obj->dev, exynos_gem_obj->buffer); +- +- kfree(exynos_gem_obj); ++ exynos_drm_gem_destroy(to_exynos_gem_obj(obj)); + } + + int exynos_drm_gem_dumb_create(struct drm_file *file_priv, +- struct drm_device *dev, struct drm_mode_create_dumb *args) ++ struct drm_device *dev, ++ struct drm_mode_create_dumb *args) + { + struct exynos_drm_gem_obj *exynos_gem_obj; ++ int ret; + + DRM_DEBUG_KMS("%s\n", __FILE__); + +@@ -314,21 +620,29 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv, + */ + + args->pitch = args->width * args->bpp >> 3; +- args->size = args->pitch * args->height; ++ args->size = PAGE_ALIGN(args->pitch * args->height); + +- exynos_gem_obj = exynos_drm_gem_create(dev, file_priv, &args->handle, +- args->size); ++ exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size); + if (IS_ERR(exynos_gem_obj)) + return PTR_ERR(exynos_gem_obj); + ++ ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv, ++ &args->handle); ++ if (ret) { ++ exynos_drm_gem_destroy(exynos_gem_obj); ++ return ret; ++ } ++ + return 0; + } + + int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, +- struct drm_device *dev, uint32_t handle, uint64_t *offset) ++ struct drm_device *dev, uint32_t handle, ++ uint64_t *offset) + { + struct exynos_drm_gem_obj *exynos_gem_obj; + struct drm_gem_object *obj; ++ int ret = 0; + + DRM_DEBUG_KMS("%s\n", __FILE__); + +@@ -343,19 +657,46 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, + obj = drm_gem_object_lookup(dev, file_priv, handle); + if (!obj) { + DRM_ERROR("failed to lookup gem object.\n"); +- mutex_unlock(&dev->struct_mutex); +- return -EINVAL; ++ ret = -EINVAL; ++ goto unlock; + } + + exynos_gem_obj = to_exynos_gem_obj(obj); + +- *offset = get_gem_mmap_offset(&exynos_gem_obj->base); +- +- drm_gem_object_unreference(obj); ++ if (!exynos_gem_obj->base.map_list.map) { ++ ret = drm_gem_create_mmap_offset(&exynos_gem_obj->base); ++ if (ret) ++ goto out; ++ } + ++ *offset = (u64)exynos_gem_obj->base.map_list.hash.key << PAGE_SHIFT; + DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset); + ++out: ++ drm_gem_object_unreference(obj); ++unlock: + mutex_unlock(&dev->struct_mutex); ++ return ret; ++} ++ ++int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv, ++ struct drm_device *dev, ++ unsigned int handle) ++{ ++ int ret; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ /* ++ * obj->refcount and obj->handle_count are decreased and ++ * if both them are 0 then exynos_drm_gem_free_object() ++ * would be called by callback to release resources. ++ */ ++ ret = drm_gem_handle_delete(file_priv, handle); ++ if (ret < 0) { ++ DRM_ERROR("failed to delete drm_gem_handle.\n"); ++ return ret; ++ } + + return 0; + } +@@ -363,21 +704,20 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, + int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) + { + struct drm_gem_object *obj = vma->vm_private_data; +- struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); + struct drm_device *dev = obj->dev; +- unsigned long pfn; ++ unsigned long f_vaddr; + pgoff_t page_offset; + int ret; + + page_offset = ((unsigned long)vmf->virtual_address - + vma->vm_start) >> PAGE_SHIFT; ++ f_vaddr = (unsigned long)vmf->virtual_address; + + mutex_lock(&dev->struct_mutex); + +- pfn = (((unsigned long)exynos_gem_obj->buffer->dma_addr) >> +- PAGE_SHIFT) + page_offset; +- +- ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn); ++ ret = exynos_drm_gem_map_pages(obj, vma, f_vaddr, page_offset); ++ if (ret < 0) ++ DRM_ERROR("failed to map pages.\n"); + + mutex_unlock(&dev->struct_mutex); + +@@ -402,29 +742,3 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) + + return ret; + } +- +- +-int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv, +- struct drm_device *dev, unsigned int handle) +-{ +- int ret; +- +- DRM_DEBUG_KMS("%s\n", __FILE__); +- +- /* +- * obj->refcount and obj->handle_count are decreased and +- * if both them are 0 then exynos_drm_gem_free_object() +- * would be called by callback to release resources. +- */ +- ret = drm_gem_handle_delete(file_priv, handle); +- if (ret < 0) { +- DRM_ERROR("failed to delete drm_gem_handle.\n"); +- return ret; +- } +- +- return 0; +-} +- +-MODULE_AUTHOR("Inki Dae "); +-MODULE_DESCRIPTION("Samsung SoC DRM GEM Module"); +-MODULE_LICENSE("GPL"); +diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h +index ef87973..4ed8420 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h ++++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h +@@ -29,6 +29,8 @@ + #define to_exynos_gem_obj(x) container_of(x,\ + struct exynos_drm_gem_obj, base) + ++#define IS_NONCONTIG_BUFFER(f) (f & EXYNOS_BO_NONCONTIG) ++ + /* + * exynos drm gem buffer structure. + * +@@ -36,11 +38,15 @@ + * @dma_addr: bus address(accessed by dma) to allocated memory region. + * - this address could be physical address without IOMMU and + * device address with IOMMU. ++ * @sgt: sg table to transfer page data. ++ * @pages: contain all pages to allocated memory region. + * @size: size of allocated memory region. + */ + struct exynos_drm_gem_buf { + void __iomem *kvaddr; + dma_addr_t dma_addr; ++ struct sg_table *sgt; ++ struct page **pages; + unsigned long size; + }; + +@@ -55,19 +61,26 @@ struct exynos_drm_gem_buf { + * by user request or at framebuffer creation. + * continuous memory region allocated by user request + * or at framebuffer creation. ++ * @size: total memory size to physically non-continuous memory region. ++ * @flags: indicate memory type to allocated buffer and cache attruibute. + * + * P.S. this object would be transfered to user as kms_bo.handle so + * user can access the buffer through kms_bo.handle. + */ + struct exynos_drm_gem_obj { +- struct drm_gem_object base; +- struct exynos_drm_gem_buf *buffer; ++ struct drm_gem_object base; ++ struct exynos_drm_gem_buf *buffer; ++ unsigned long size; ++ unsigned int flags; + }; + +-/* create a new buffer and get a new gem handle. */ ++/* destroy a buffer with gem object */ ++void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj); ++ ++/* create a new buffer with gem object */ + struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, +- struct drm_file *file_priv, +- unsigned int *handle, unsigned long size); ++ unsigned int flags, ++ unsigned long size); + + /* + * request gem object creation and buffer allocation as the size +@@ -75,15 +88,36 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, + * height and bpp. + */ + int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv); ++ struct drm_file *file_priv); ++ ++/* ++ * get dma address from gem handle and this function could be used for ++ * other drivers such as 2d/3d acceleration drivers. ++ * with this function call, gem object reference count would be increased. ++ */ ++void *exynos_drm_gem_get_dma_addr(struct drm_device *dev, ++ unsigned int gem_handle, ++ struct drm_file *file_priv); ++ ++/* ++ * put dma address from gem handle and this function could be used for ++ * other drivers such as 2d/3d acceleration drivers. ++ * with this function call, gem object reference count would be decreased. ++ */ ++void exynos_drm_gem_put_dma_addr(struct drm_device *dev, ++ unsigned int gem_handle, ++ struct drm_file *file_priv); + + /* get buffer offset to map to user space. */ + int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv); ++ struct drm_file *file_priv); + +-/* unmap a buffer from user space. */ +-int exynos_drm_gem_munmap_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv); ++/* ++ * mmap the physically continuous memory that a gem object contains ++ * to user space. ++ */ ++int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv); + + /* initialize gem object. */ + int exynos_drm_gem_init_object(struct drm_gem_object *obj); +@@ -93,24 +127,13 @@ void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj); + + /* create memory region for drm framebuffer. */ + int exynos_drm_gem_dumb_create(struct drm_file *file_priv, +- struct drm_device *dev, struct drm_mode_create_dumb *args); ++ struct drm_device *dev, ++ struct drm_mode_create_dumb *args); + + /* map memory region for drm framebuffer to user space. */ + int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, +- struct drm_device *dev, uint32_t handle, uint64_t *offset); +- +-/* page fault handler and mmap fault address(virtual) to physical memory. */ +-int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); +- +-/* +- * mmap the physically continuous memory that a gem object contains +- * to user space. +- */ +-int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +- +-/* set vm_flags and we can change the vm attribute to other one at here. */ +-int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); ++ struct drm_device *dev, uint32_t handle, ++ uint64_t *offset); + + /* + * destroy memory region allocated. +@@ -118,6 +141,13 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); + * would be released by drm_gem_handle_delete(). + */ + int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv, +- struct drm_device *dev, unsigned int handle); ++ struct drm_device *dev, ++ unsigned int handle); ++ ++/* page fault handler and mmap fault address(virtual) to physical memory. */ ++int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); ++ ++/* set vm_flags and we can change the vm attribute to other one at here. */ ++int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); + + #endif +diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +new file mode 100644 +index 0000000..3424463 +--- /dev/null ++++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +@@ -0,0 +1,377 @@ ++/* ++ * Copyright (C) 2011 Samsung Electronics Co.Ltd ++ * Authors: ++ * Inki Dae ++ * Seung-Woo Kim ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the 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 "drmP.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "exynos_drm_drv.h" ++#include "exynos_drm_hdmi.h" ++ ++#define to_context(dev) platform_get_drvdata(to_platform_device(dev)) ++#define to_subdrv(dev) to_context(dev) ++#define get_ctx_from_subdrv(subdrv) container_of(subdrv,\ ++ struct drm_hdmi_context, subdrv); ++ ++/* these callback points shoud be set by specific drivers. */ ++static struct exynos_hdmi_ops *hdmi_ops; ++static struct exynos_mixer_ops *mixer_ops; ++ ++struct drm_hdmi_context { ++ struct exynos_drm_subdrv subdrv; ++ struct exynos_drm_hdmi_context *hdmi_ctx; ++ struct exynos_drm_hdmi_context *mixer_ctx; ++}; ++ ++void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops) ++{ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (ops) ++ hdmi_ops = ops; ++} ++ ++void exynos_mixer_ops_register(struct exynos_mixer_ops *ops) ++{ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (ops) ++ mixer_ops = ops; ++} ++ ++static bool drm_hdmi_is_connected(struct device *dev) ++{ ++ struct drm_hdmi_context *ctx = to_context(dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (hdmi_ops && hdmi_ops->is_connected) ++ return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx); ++ ++ return false; ++} ++ ++static int drm_hdmi_get_edid(struct device *dev, ++ struct drm_connector *connector, u8 *edid, int len) ++{ ++ struct drm_hdmi_context *ctx = to_context(dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (hdmi_ops && hdmi_ops->get_edid) ++ return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid, ++ len); ++ ++ return 0; ++} ++ ++static int drm_hdmi_check_timing(struct device *dev, void *timing) ++{ ++ struct drm_hdmi_context *ctx = to_context(dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (hdmi_ops && hdmi_ops->check_timing) ++ return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing); ++ ++ return 0; ++} ++ ++static int drm_hdmi_power_on(struct device *dev, int mode) ++{ ++ struct drm_hdmi_context *ctx = to_context(dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (hdmi_ops && hdmi_ops->power_on) ++ return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode); ++ ++ return 0; ++} ++ ++static struct exynos_drm_display_ops drm_hdmi_display_ops = { ++ .type = EXYNOS_DISPLAY_TYPE_HDMI, ++ .is_connected = drm_hdmi_is_connected, ++ .get_edid = drm_hdmi_get_edid, ++ .check_timing = drm_hdmi_check_timing, ++ .power_on = drm_hdmi_power_on, ++}; ++ ++static int drm_hdmi_enable_vblank(struct device *subdrv_dev) ++{ ++ struct drm_hdmi_context *ctx = to_context(subdrv_dev); ++ struct exynos_drm_subdrv *subdrv = &ctx->subdrv; ++ struct exynos_drm_manager *manager = subdrv->manager; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (mixer_ops && mixer_ops->enable_vblank) ++ return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx, ++ manager->pipe); ++ ++ return 0; ++} ++ ++static void drm_hdmi_disable_vblank(struct device *subdrv_dev) ++{ ++ struct drm_hdmi_context *ctx = to_context(subdrv_dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (mixer_ops && mixer_ops->disable_vblank) ++ return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx); ++} ++ ++static void drm_hdmi_mode_fixup(struct device *subdrv_dev, ++ struct drm_connector *connector, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct drm_hdmi_context *ctx = to_context(subdrv_dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (hdmi_ops && hdmi_ops->mode_fixup) ++ hdmi_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector, mode, ++ adjusted_mode); ++} ++ ++static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode) ++{ ++ struct drm_hdmi_context *ctx = to_context(subdrv_dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (hdmi_ops && hdmi_ops->mode_set) ++ hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode); ++} ++ ++static void drm_hdmi_get_max_resol(struct device *subdrv_dev, ++ unsigned int *width, unsigned int *height) ++{ ++ struct drm_hdmi_context *ctx = to_context(subdrv_dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (hdmi_ops && hdmi_ops->get_max_resol) ++ hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height); ++} ++ ++static void drm_hdmi_commit(struct device *subdrv_dev) ++{ ++ struct drm_hdmi_context *ctx = to_context(subdrv_dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (hdmi_ops && hdmi_ops->commit) ++ hdmi_ops->commit(ctx->hdmi_ctx->ctx); ++} ++ ++static void drm_hdmi_dpms(struct device *subdrv_dev, int mode) ++{ ++ struct drm_hdmi_context *ctx = to_context(subdrv_dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ switch (mode) { ++ case DRM_MODE_DPMS_ON: ++ break; ++ case DRM_MODE_DPMS_STANDBY: ++ case DRM_MODE_DPMS_SUSPEND: ++ case DRM_MODE_DPMS_OFF: ++ if (hdmi_ops && hdmi_ops->disable) ++ hdmi_ops->disable(ctx->hdmi_ctx->ctx); ++ break; ++ default: ++ DRM_DEBUG_KMS("unkown dps mode: %d\n", mode); ++ break; ++ } ++} ++ ++static struct exynos_drm_manager_ops drm_hdmi_manager_ops = { ++ .dpms = drm_hdmi_dpms, ++ .enable_vblank = drm_hdmi_enable_vblank, ++ .disable_vblank = drm_hdmi_disable_vblank, ++ .mode_fixup = drm_hdmi_mode_fixup, ++ .mode_set = drm_hdmi_mode_set, ++ .get_max_resol = drm_hdmi_get_max_resol, ++ .commit = drm_hdmi_commit, ++}; ++ ++static void drm_mixer_mode_set(struct device *subdrv_dev, ++ struct exynos_drm_overlay *overlay) ++{ ++ struct drm_hdmi_context *ctx = to_context(subdrv_dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (mixer_ops && mixer_ops->win_mode_set) ++ mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay); ++} ++ ++static void drm_mixer_commit(struct device *subdrv_dev, int zpos) ++{ ++ struct drm_hdmi_context *ctx = to_context(subdrv_dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (mixer_ops && mixer_ops->win_commit) ++ mixer_ops->win_commit(ctx->mixer_ctx->ctx, zpos); ++} ++ ++static void drm_mixer_disable(struct device *subdrv_dev, int zpos) ++{ ++ struct drm_hdmi_context *ctx = to_context(subdrv_dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (mixer_ops && mixer_ops->win_disable) ++ mixer_ops->win_disable(ctx->mixer_ctx->ctx, zpos); ++} ++ ++static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = { ++ .mode_set = drm_mixer_mode_set, ++ .commit = drm_mixer_commit, ++ .disable = drm_mixer_disable, ++}; ++ ++static struct exynos_drm_manager hdmi_manager = { ++ .pipe = -1, ++ .ops = &drm_hdmi_manager_ops, ++ .overlay_ops = &drm_hdmi_overlay_ops, ++ .display_ops = &drm_hdmi_display_ops, ++}; ++ ++static int hdmi_subdrv_probe(struct drm_device *drm_dev, ++ struct device *dev) ++{ ++ struct exynos_drm_subdrv *subdrv = to_subdrv(dev); ++ struct drm_hdmi_context *ctx; ++ struct platform_device *pdev = to_platform_device(dev); ++ struct exynos_drm_common_hdmi_pd *pd; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ pd = pdev->dev.platform_data; ++ ++ if (!pd) { ++ DRM_DEBUG_KMS("platform data is null.\n"); ++ return -EFAULT; ++ } ++ ++ if (!pd->hdmi_dev) { ++ DRM_DEBUG_KMS("hdmi device is null.\n"); ++ return -EFAULT; ++ } ++ ++ if (!pd->mixer_dev) { ++ DRM_DEBUG_KMS("mixer device is null.\n"); ++ return -EFAULT; ++ } ++ ++ ctx = get_ctx_from_subdrv(subdrv); ++ ++ ctx->hdmi_ctx = (struct exynos_drm_hdmi_context *) ++ to_context(pd->hdmi_dev); ++ if (!ctx->hdmi_ctx) { ++ DRM_DEBUG_KMS("hdmi context is null.\n"); ++ return -EFAULT; ++ } ++ ++ ctx->hdmi_ctx->drm_dev = drm_dev; ++ ++ ctx->mixer_ctx = (struct exynos_drm_hdmi_context *) ++ to_context(pd->mixer_dev); ++ if (!ctx->mixer_ctx) { ++ DRM_DEBUG_KMS("mixer context is null.\n"); ++ return -EFAULT; ++ } ++ ++ ctx->mixer_ctx->drm_dev = drm_dev; ++ ++ return 0; ++} ++ ++static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct exynos_drm_subdrv *subdrv; ++ struct drm_hdmi_context *ctx; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) { ++ DRM_LOG_KMS("failed to alloc common hdmi context.\n"); ++ return -ENOMEM; ++ } ++ ++ subdrv = &ctx->subdrv; ++ ++ subdrv->dev = dev; ++ subdrv->manager = &hdmi_manager; ++ subdrv->probe = hdmi_subdrv_probe; ++ ++ platform_set_drvdata(pdev, subdrv); ++ ++ exynos_drm_subdrv_register(subdrv); ++ ++ return 0; ++} ++ ++static int hdmi_runtime_suspend(struct device *dev) ++{ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ return 0; ++} ++ ++static int hdmi_runtime_resume(struct device *dev) ++{ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops hdmi_pm_ops = { ++ .runtime_suspend = hdmi_runtime_suspend, ++ .runtime_resume = hdmi_runtime_resume, ++}; ++ ++static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev) ++{ ++ struct drm_hdmi_context *ctx = platform_get_drvdata(pdev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ exynos_drm_subdrv_unregister(&ctx->subdrv); ++ kfree(ctx); ++ ++ return 0; ++} ++ ++struct platform_driver exynos_drm_common_hdmi_driver = { ++ .probe = exynos_drm_hdmi_probe, ++ .remove = __devexit_p(exynos_drm_hdmi_remove), ++ .driver = { ++ .name = "exynos-drm-hdmi", ++ .owner = THIS_MODULE, ++ .pm = &hdmi_pm_ops, ++ }, ++}; +diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +new file mode 100644 +index 0000000..f3ae192 +--- /dev/null ++++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +@@ -0,0 +1,73 @@ ++/* exynos_drm_hdmi.h ++ * ++ * Copyright (c) 2011 Samsung Electronics Co., Ltd. ++ * Authoer: Inki Dae ++ * ++ * 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 (including the next ++ * paragraph) 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 ++ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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. ++ */ ++ ++#ifndef _EXYNOS_DRM_HDMI_H_ ++#define _EXYNOS_DRM_HDMI_H_ ++ ++/* ++ * exynos hdmi common context structure. ++ * ++ * @drm_dev: pointer to drm_device. ++ * @ctx: pointer to the context of specific device driver. ++ * this context should be hdmi_context or mixer_context. ++ */ ++struct exynos_drm_hdmi_context { ++ struct drm_device *drm_dev; ++ void *ctx; ++}; ++ ++struct exynos_hdmi_ops { ++ /* display */ ++ bool (*is_connected)(void *ctx); ++ int (*get_edid)(void *ctx, struct drm_connector *connector, ++ u8 *edid, int len); ++ int (*check_timing)(void *ctx, void *timing); ++ int (*power_on)(void *ctx, int mode); ++ ++ /* manager */ ++ void (*mode_fixup)(void *ctx, struct drm_connector *connector, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode); ++ void (*mode_set)(void *ctx, void *mode); ++ void (*get_max_resol)(void *ctx, unsigned int *width, ++ unsigned int *height); ++ void (*commit)(void *ctx); ++ void (*disable)(void *ctx); ++}; ++ ++struct exynos_mixer_ops { ++ /* manager */ ++ int (*enable_vblank)(void *ctx, int pipe); ++ void (*disable_vblank)(void *ctx); ++ ++ /* overlay */ ++ void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay); ++ void (*win_commit)(void *ctx, int zpos); ++ void (*win_disable)(void *ctx, int zpos); ++}; ++ ++void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops); ++void exynos_mixer_ops_register(struct exynos_mixer_ops *ops); ++#endif +diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c +new file mode 100644 +index 0000000..f92fe4c +--- /dev/null ++++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c +@@ -0,0 +1,171 @@ ++/* ++ * Copyright (C) 2011 Samsung Electronics Co.Ltd ++ * Authors: Joonyoung Shim ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the 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 "drmP.h" ++ ++#include "exynos_drm.h" ++#include "exynos_drm_crtc.h" ++#include "exynos_drm_drv.h" ++#include "exynos_drm_encoder.h" ++ ++struct exynos_plane { ++ struct drm_plane base; ++ struct exynos_drm_overlay overlay; ++ bool enabled; ++}; ++ ++static const uint32_t formats[] = { ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_ARGB8888, ++ DRM_FORMAT_NV12, ++ DRM_FORMAT_NV12M, ++ DRM_FORMAT_NV12MT, ++}; ++ ++static int ++exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ++ struct drm_framebuffer *fb, int crtc_x, int crtc_y, ++ unsigned int crtc_w, unsigned int crtc_h, ++ uint32_t src_x, uint32_t src_y, ++ uint32_t src_w, uint32_t src_h) ++{ ++ struct exynos_plane *exynos_plane = ++ container_of(plane, struct exynos_plane, base); ++ struct exynos_drm_overlay *overlay = &exynos_plane->overlay; ++ struct exynos_drm_crtc_pos pos; ++ unsigned int x = src_x >> 16; ++ unsigned int y = src_y >> 16; ++ int ret; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos)); ++ pos.crtc_x = crtc_x; ++ pos.crtc_y = crtc_y; ++ pos.crtc_w = crtc_w; ++ pos.crtc_h = crtc_h; ++ ++ pos.fb_x = x; ++ pos.fb_y = y; ++ ++ /* TODO: scale feature */ ++ ret = exynos_drm_overlay_update(overlay, fb, &crtc->mode, &pos); ++ if (ret < 0) ++ return ret; ++ ++ exynos_drm_fn_encoder(crtc, overlay, ++ exynos_drm_encoder_crtc_mode_set); ++ exynos_drm_fn_encoder(crtc, &overlay->zpos, ++ exynos_drm_encoder_crtc_plane_commit); ++ ++ exynos_plane->enabled = true; ++ ++ return 0; ++} ++ ++static int exynos_disable_plane(struct drm_plane *plane) ++{ ++ struct exynos_plane *exynos_plane = ++ container_of(plane, struct exynos_plane, base); ++ struct exynos_drm_overlay *overlay = &exynos_plane->overlay; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ if (!exynos_plane->enabled) ++ return 0; ++ ++ exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, ++ exynos_drm_encoder_crtc_disable); ++ ++ exynos_plane->enabled = false; ++ exynos_plane->overlay.zpos = DEFAULT_ZPOS; ++ ++ return 0; ++} ++ ++static void exynos_plane_destroy(struct drm_plane *plane) ++{ ++ struct exynos_plane *exynos_plane = ++ container_of(plane, struct exynos_plane, base); ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ exynos_disable_plane(plane); ++ drm_plane_cleanup(plane); ++ kfree(exynos_plane); ++} ++ ++static struct drm_plane_funcs exynos_plane_funcs = { ++ .update_plane = exynos_update_plane, ++ .disable_plane = exynos_disable_plane, ++ .destroy = exynos_plane_destroy, ++}; ++ ++int exynos_plane_init(struct drm_device *dev, unsigned int nr) ++{ ++ struct exynos_plane *exynos_plane; ++ uint32_t possible_crtcs; ++ ++ exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL); ++ if (!exynos_plane) ++ return -ENOMEM; ++ ++ /* all CRTCs are available */ ++ possible_crtcs = (1 << MAX_CRTC) - 1; ++ ++ exynos_plane->overlay.zpos = DEFAULT_ZPOS; ++ ++ return drm_plane_init(dev, &exynos_plane->base, possible_crtcs, ++ &exynos_plane_funcs, formats, ARRAY_SIZE(formats), ++ false); ++} ++ ++int exynos_plane_set_zpos_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv) ++{ ++ struct drm_exynos_plane_set_zpos *zpos_req = data; ++ struct drm_mode_object *obj; ++ struct drm_plane *plane; ++ struct exynos_plane *exynos_plane; ++ int ret = 0; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ ++ if (zpos_req->zpos < 0 || zpos_req->zpos >= MAX_PLANE) { ++ if (zpos_req->zpos != DEFAULT_ZPOS) { ++ DRM_ERROR("zpos not within limits\n"); ++ return -EINVAL; ++ } ++ } ++ ++ mutex_lock(&dev->mode_config.mutex); ++ ++ obj = drm_mode_object_find(dev, zpos_req->plane_id, ++ DRM_MODE_OBJECT_PLANE); ++ if (!obj) { ++ DRM_DEBUG_KMS("Unknown plane ID %d\n", ++ zpos_req->plane_id); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ plane = obj_to_plane(obj); ++ exynos_plane = container_of(plane, struct exynos_plane, base); ++ ++ exynos_plane->overlay.zpos = zpos_req->zpos; ++ ++out: ++ mutex_unlock(&dev->mode_config.mutex); ++ return ret; ++} +diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h +new file mode 100644 +index 0000000..16b71f8 +--- /dev/null ++++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h +@@ -0,0 +1,14 @@ ++/* ++ * Copyright (C) 2011 Samsung Electronics Co.Ltd ++ * Authors: Joonyoung Shim ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ */ ++ ++int exynos_plane_init(struct drm_device *dev, unsigned int nr); ++int exynos_plane_set_zpos_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv); +diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c +new file mode 100644 +index 0000000..7b9c153 +--- /dev/null ++++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c +@@ -0,0 +1,680 @@ ++/* exynos_drm_vidi.c ++ * ++ * Copyright (C) 2012 Samsung Electronics Co.Ltd ++ * Authors: ++ * Inki Dae ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the 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 "drmP.h" ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "drm_edid.h" ++#include "drm_crtc_helper.h" ++ ++#include "exynos_drm_drv.h" ++#include "exynos_drm_crtc.h" ++#include "exynos_drm_encoder.h" ++ ++/* vidi has totally three virtual windows. */ ++#define WINDOWS_NR 3 ++ ++#define get_vidi_context(dev) platform_get_drvdata(to_platform_device(dev)) ++ ++struct vidi_win_data { ++ unsigned int offset_x; ++ unsigned int offset_y; ++ unsigned int ovl_width; ++ unsigned int ovl_height; ++ unsigned int fb_width; ++ unsigned int fb_height; ++ unsigned int bpp; ++ dma_addr_t dma_addr; ++ void __iomem *vaddr; ++ unsigned int buf_offsize; ++ unsigned int line_size; /* bytes */ ++ bool enabled; ++}; ++ ++struct vidi_context { ++ struct exynos_drm_subdrv subdrv; ++ struct drm_crtc *crtc; ++ struct vidi_win_data win_data[WINDOWS_NR]; ++ struct edid *raw_edid; ++ unsigned int clkdiv; ++ unsigned int default_win; ++ unsigned long irq_flags; ++ unsigned int connected; ++ bool vblank_on; ++ bool suspended; ++ struct work_struct work; ++ struct mutex lock; ++}; ++ ++static const char fake_edid_info[] = { ++ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x05, 0x05, ++ 0x00, 0x00, 0x00, 0x00, 0x30, 0x12, 0x01, 0x03, 0x80, 0x10, 0x09, 0x78, ++ 0x0a, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0xbd, ++ 0xee, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x66, 0x21, 0x50, 0xb0, 0x51, 0x00, ++ 0x1b, 0x30, 0x40, 0x70, 0x36, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, ++ 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, ++ 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, ++ 0x4b, 0x1a, 0x44, 0x17, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, ++ 0x00, 0x00, 0x00, 0xfc, 0x00, 0x53, 0x41, 0x4d, 0x53, 0x55, 0x4e, 0x47, ++ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xbc, 0x02, 0x03, 0x1e, 0xf1, ++ 0x46, 0x84, 0x05, 0x03, 0x10, 0x20, 0x22, 0x23, 0x09, 0x07, 0x07, 0x83, ++ 0x01, 0x00, 0x00, 0xe2, 0x00, 0x0f, 0x67, 0x03, 0x0c, 0x00, 0x10, 0x00, ++ 0xb8, 0x2d, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c, ++ 0x25, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x9e, 0x8c, 0x0a, 0xd0, 0x8a, ++ 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xa0, 0x5a, 0x00, 0x00, ++ 0x00, 0x18, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, ++ 0x45, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x06 ++}; ++ ++static void vidi_fake_vblank_handler(struct work_struct *work); ++ ++static bool vidi_display_is_connected(struct device *dev) ++{ ++ struct vidi_context *ctx = get_vidi_context(dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ /* ++ * connection request would come from user side ++ * to do hotplug through specific ioctl. ++ */ ++ return ctx->connected ? true : false; ++} ++ ++static int vidi_get_edid(struct device *dev, struct drm_connector *connector, ++ u8 *edid, int len) ++{ ++ struct vidi_context *ctx = get_vidi_context(dev); ++ struct edid *raw_edid; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ /* ++ * the edid data comes from user side and it would be set ++ * to ctx->raw_edid through specific ioctl. ++ */ ++ if (!ctx->raw_edid) { ++ DRM_DEBUG_KMS("raw_edid is null.\n"); ++ return -EFAULT; ++ } ++ ++ raw_edid = kzalloc(len, GFP_KERNEL); ++ if (!raw_edid) { ++ DRM_DEBUG_KMS("failed to allocate raw_edid.\n"); ++ return -ENOMEM; ++ } ++ ++ memcpy(raw_edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions) ++ * EDID_LENGTH, len)); ++ ++ /* attach the edid data to connector. */ ++ connector->display_info.raw_edid = (char *)raw_edid; ++ ++ memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions) ++ * EDID_LENGTH, len)); ++ ++ return 0; ++} ++ ++static void *vidi_get_panel(struct device *dev) ++{ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ /* TODO. */ ++ ++ return NULL; ++} ++ ++static int vidi_check_timing(struct device *dev, void *timing) ++{ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ /* TODO. */ ++ ++ return 0; ++} ++ ++static int vidi_display_power_on(struct device *dev, int mode) ++{ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ /* TODO */ ++ ++ return 0; ++} ++ ++static struct exynos_drm_display_ops vidi_display_ops = { ++ .type = EXYNOS_DISPLAY_TYPE_VIDI, ++ .is_connected = vidi_display_is_connected, ++ .get_edid = vidi_get_edid, ++ .get_panel = vidi_get_panel, ++ .check_timing = vidi_check_timing, ++ .power_on = vidi_display_power_on, ++}; ++ ++static void vidi_dpms(struct device *subdrv_dev, int mode) ++{ ++ struct vidi_context *ctx = get_vidi_context(subdrv_dev); ++ ++ DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode); ++ ++ mutex_lock(&ctx->lock); ++ ++ switch (mode) { ++ case DRM_MODE_DPMS_ON: ++ /* TODO. */ ++ break; ++ case DRM_MODE_DPMS_STANDBY: ++ case DRM_MODE_DPMS_SUSPEND: ++ case DRM_MODE_DPMS_OFF: ++ /* TODO. */ ++ break; ++ default: ++ DRM_DEBUG_KMS("unspecified mode %d\n", mode); ++ break; ++ } ++ ++ mutex_unlock(&ctx->lock); ++} ++ ++static void vidi_apply(struct device *subdrv_dev) ++{ ++ struct vidi_context *ctx = get_vidi_context(subdrv_dev); ++ struct exynos_drm_manager *mgr = ctx->subdrv.manager; ++ struct exynos_drm_manager_ops *mgr_ops = mgr->ops; ++ struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops; ++ struct vidi_win_data *win_data; ++ int i; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ for (i = 0; i < WINDOWS_NR; i++) { ++ win_data = &ctx->win_data[i]; ++ if (win_data->enabled && (ovl_ops && ovl_ops->commit)) ++ ovl_ops->commit(subdrv_dev, i); ++ } ++ ++ if (mgr_ops && mgr_ops->commit) ++ mgr_ops->commit(subdrv_dev); ++} ++ ++static void vidi_commit(struct device *dev) ++{ ++ struct vidi_context *ctx = get_vidi_context(dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (ctx->suspended) ++ return; ++} ++ ++static int vidi_enable_vblank(struct device *dev) ++{ ++ struct vidi_context *ctx = get_vidi_context(dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (ctx->suspended) ++ return -EPERM; ++ ++ if (!test_and_set_bit(0, &ctx->irq_flags)) ++ ctx->vblank_on = true; ++ ++ return 0; ++} ++ ++static void vidi_disable_vblank(struct device *dev) ++{ ++ struct vidi_context *ctx = get_vidi_context(dev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (ctx->suspended) ++ return; ++ ++ if (test_and_clear_bit(0, &ctx->irq_flags)) ++ ctx->vblank_on = false; ++} ++ ++static struct exynos_drm_manager_ops vidi_manager_ops = { ++ .dpms = vidi_dpms, ++ .apply = vidi_apply, ++ .commit = vidi_commit, ++ .enable_vblank = vidi_enable_vblank, ++ .disable_vblank = vidi_disable_vblank, ++}; ++ ++static void vidi_win_mode_set(struct device *dev, ++ struct exynos_drm_overlay *overlay) ++{ ++ struct vidi_context *ctx = get_vidi_context(dev); ++ struct vidi_win_data *win_data; ++ int win; ++ unsigned long offset; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (!overlay) { ++ dev_err(dev, "overlay is NULL\n"); ++ return; ++ } ++ ++ win = overlay->zpos; ++ if (win == DEFAULT_ZPOS) ++ win = ctx->default_win; ++ ++ if (win < 0 || win > WINDOWS_NR) ++ return; ++ ++ offset = overlay->fb_x * (overlay->bpp >> 3); ++ offset += overlay->fb_y * overlay->pitch; ++ ++ DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch); ++ ++ win_data = &ctx->win_data[win]; ++ ++ win_data->offset_x = overlay->crtc_x; ++ win_data->offset_y = overlay->crtc_y; ++ win_data->ovl_width = overlay->crtc_width; ++ win_data->ovl_height = overlay->crtc_height; ++ win_data->fb_width = overlay->fb_width; ++ win_data->fb_height = overlay->fb_height; ++ win_data->dma_addr = overlay->dma_addr[0] + offset; ++ win_data->vaddr = overlay->vaddr[0] + offset; ++ win_data->bpp = overlay->bpp; ++ win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * ++ (overlay->bpp >> 3); ++ win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3); ++ ++ /* ++ * some parts of win_data should be transferred to user side ++ * through specific ioctl. ++ */ ++ ++ DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n", ++ win_data->offset_x, win_data->offset_y); ++ DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", ++ win_data->ovl_width, win_data->ovl_height); ++ DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n", ++ (unsigned long)win_data->dma_addr, ++ (unsigned long)win_data->vaddr); ++ DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", ++ overlay->fb_width, overlay->crtc_width); ++} ++ ++static void vidi_win_commit(struct device *dev, int zpos) ++{ ++ struct vidi_context *ctx = get_vidi_context(dev); ++ struct vidi_win_data *win_data; ++ int win = zpos; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (ctx->suspended) ++ return; ++ ++ if (win == DEFAULT_ZPOS) ++ win = ctx->default_win; ++ ++ if (win < 0 || win > WINDOWS_NR) ++ return; ++ ++ win_data = &ctx->win_data[win]; ++ ++ win_data->enabled = true; ++ ++ DRM_DEBUG_KMS("dma_addr = 0x%x\n", win_data->dma_addr); ++ ++ if (ctx->vblank_on) ++ schedule_work(&ctx->work); ++} ++ ++static void vidi_win_disable(struct device *dev, int zpos) ++{ ++ struct vidi_context *ctx = get_vidi_context(dev); ++ struct vidi_win_data *win_data; ++ int win = zpos; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (win == DEFAULT_ZPOS) ++ win = ctx->default_win; ++ ++ if (win < 0 || win > WINDOWS_NR) ++ return; ++ ++ win_data = &ctx->win_data[win]; ++ win_data->enabled = false; ++ ++ /* TODO. */ ++} ++ ++static struct exynos_drm_overlay_ops vidi_overlay_ops = { ++ .mode_set = vidi_win_mode_set, ++ .commit = vidi_win_commit, ++ .disable = vidi_win_disable, ++}; ++ ++static struct exynos_drm_manager vidi_manager = { ++ .pipe = -1, ++ .ops = &vidi_manager_ops, ++ .overlay_ops = &vidi_overlay_ops, ++ .display_ops = &vidi_display_ops, ++}; ++ ++static void vidi_finish_pageflip(struct drm_device *drm_dev, int crtc) ++{ ++ struct exynos_drm_private *dev_priv = drm_dev->dev_private; ++ struct drm_pending_vblank_event *e, *t; ++ struct timeval now; ++ unsigned long flags; ++ bool is_checked = false; ++ ++ spin_lock_irqsave(&drm_dev->event_lock, flags); ++ ++ list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list, ++ base.link) { ++ /* if event's pipe isn't same as crtc then ignore it. */ ++ if (crtc != e->pipe) ++ continue; ++ ++ is_checked = true; ++ ++ do_gettimeofday(&now); ++ e->event.sequence = 0; ++ e->event.tv_sec = now.tv_sec; ++ e->event.tv_usec = now.tv_usec; ++ ++ list_move_tail(&e->base.link, &e->base.file_priv->event_list); ++ wake_up_interruptible(&e->base.file_priv->event_wait); ++ } ++ ++ if (is_checked) { ++ /* ++ * call drm_vblank_put only in case that drm_vblank_get was ++ * called. ++ */ ++ if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0) ++ drm_vblank_put(drm_dev, crtc); ++ ++ /* ++ * don't off vblank if vblank_disable_allowed is 1, ++ * because vblank would be off by timer handler. ++ */ ++ if (!drm_dev->vblank_disable_allowed) ++ drm_vblank_off(drm_dev, crtc); ++ } ++ ++ spin_unlock_irqrestore(&drm_dev->event_lock, flags); ++} ++ ++static void vidi_fake_vblank_handler(struct work_struct *work) ++{ ++ struct vidi_context *ctx = container_of(work, struct vidi_context, ++ work); ++ struct exynos_drm_subdrv *subdrv = &ctx->subdrv; ++ struct exynos_drm_manager *manager = subdrv->manager; ++ ++ if (manager->pipe < 0) ++ return; ++ ++ /* refresh rate is about 50Hz. */ ++ usleep_range(16000, 20000); ++ ++ drm_handle_vblank(subdrv->drm_dev, manager->pipe); ++ vidi_finish_pageflip(subdrv->drm_dev, manager->pipe); ++} ++ ++static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev) ++{ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ /* ++ * enable drm irq mode. ++ * - with irq_enabled = 1, we can use the vblank feature. ++ * ++ * P.S. note that we wouldn't use drm irq handler but ++ * just specific driver own one instead because ++ * drm framework supports only one irq handler. ++ */ ++ drm_dev->irq_enabled = 1; ++ ++ /* ++ * with vblank_disable_allowed = 1, vblank interrupt will be disabled ++ * by drm timer once a current process gives up ownership of ++ * vblank event.(after drm_vblank_put function is called) ++ */ ++ drm_dev->vblank_disable_allowed = 1; ++ ++ return 0; ++} ++ ++static void vidi_subdrv_remove(struct drm_device *drm_dev) ++{ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ /* TODO. */ ++} ++ ++static int vidi_power_on(struct vidi_context *ctx, bool enable) ++{ ++ struct exynos_drm_subdrv *subdrv = &ctx->subdrv; ++ struct device *dev = subdrv->dev; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (enable != false && enable != true) ++ return -EINVAL; ++ ++ if (enable) { ++ ctx->suspended = false; ++ ++ /* if vblank was enabled status, enable it again. */ ++ if (test_and_clear_bit(0, &ctx->irq_flags)) ++ vidi_enable_vblank(dev); ++ ++ vidi_apply(dev); ++ } else { ++ ctx->suspended = true; ++ } ++ ++ return 0; ++} ++ ++static int vidi_show_connection(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int rc; ++ struct vidi_context *ctx = get_vidi_context(dev); ++ ++ mutex_lock(&ctx->lock); ++ ++ rc = sprintf(buf, "%d\n", ctx->connected); ++ ++ mutex_unlock(&ctx->lock); ++ ++ return rc; ++} ++ ++static int vidi_store_connection(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ struct vidi_context *ctx = get_vidi_context(dev); ++ int ret; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ ret = kstrtoint(buf, 0, &ctx->connected); ++ if (ret) ++ return ret; ++ ++ if (ctx->connected > 1) ++ return -EINVAL; ++ ++ DRM_DEBUG_KMS("requested connection.\n"); ++ ++ drm_helper_hpd_irq_event(ctx->subdrv.drm_dev); ++ ++ return len; ++} ++ ++static DEVICE_ATTR(connection, 0644, vidi_show_connection, ++ vidi_store_connection); ++ ++int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, ++ struct drm_file *file_priv) ++{ ++ struct vidi_context *ctx = NULL; ++ struct drm_encoder *encoder; ++ struct exynos_drm_manager *manager; ++ struct exynos_drm_display_ops *display_ops; ++ struct drm_exynos_vidi_connection *vidi = data; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ if (!vidi) { ++ DRM_DEBUG_KMS("user data for vidi is null.\n"); ++ return -EINVAL; ++ } ++ ++ if (!vidi->edid) { ++ DRM_DEBUG_KMS("edid data is null.\n"); ++ return -EINVAL; ++ } ++ ++ if (vidi->connection > 1) { ++ DRM_DEBUG_KMS("connection should be 0 or 1.\n"); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(encoder, &drm_dev->mode_config.encoder_list, ++ head) { ++ manager = exynos_drm_get_manager(encoder); ++ display_ops = manager->display_ops; ++ ++ if (display_ops->type == EXYNOS_DISPLAY_TYPE_VIDI) { ++ ctx = get_vidi_context(manager->dev); ++ break; ++ } ++ } ++ ++ if (!ctx) { ++ DRM_DEBUG_KMS("not found virtual device type encoder.\n"); ++ return -EINVAL; ++ } ++ ++ if (ctx->connected == vidi->connection) { ++ DRM_DEBUG_KMS("same connection request.\n"); ++ return -EINVAL; ++ } ++ ++ if (vidi->connection) ++ ctx->raw_edid = (struct edid *)vidi->edid; ++ ++ ctx->connected = vidi->connection; ++ drm_helper_hpd_irq_event(ctx->subdrv.drm_dev); ++ ++ return 0; ++} ++ ++static int __devinit vidi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct vidi_context *ctx; ++ struct exynos_drm_subdrv *subdrv; ++ int ret; ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ ctx->default_win = 0; ++ ++ INIT_WORK(&ctx->work, vidi_fake_vblank_handler); ++ ++ /* for test */ ++ ctx->raw_edid = (struct edid *)fake_edid_info; ++ ++ subdrv = &ctx->subdrv; ++ subdrv->dev = dev; ++ subdrv->manager = &vidi_manager; ++ subdrv->probe = vidi_subdrv_probe; ++ subdrv->remove = vidi_subdrv_remove; ++ ++ mutex_init(&ctx->lock); ++ ++ platform_set_drvdata(pdev, ctx); ++ ++ ret = device_create_file(&pdev->dev, &dev_attr_connection); ++ if (ret < 0) ++ DRM_INFO("failed to create connection sysfs.\n"); ++ ++ exynos_drm_subdrv_register(subdrv); ++ ++ return 0; ++} ++ ++static int __devexit vidi_remove(struct platform_device *pdev) ++{ ++ struct vidi_context *ctx = platform_get_drvdata(pdev); ++ ++ DRM_DEBUG_KMS("%s\n", __FILE__); ++ ++ exynos_drm_subdrv_unregister(&ctx->subdrv); ++ ++ kfree(ctx); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int vidi_suspend(struct device *dev) ++{ ++ struct vidi_context *ctx = get_vidi_context(dev); ++ ++ return vidi_power_on(ctx, false); ++} ++ ++static int vidi_resume(struct device *dev) ++{ ++ struct vidi_context *ctx = get_vidi_context(dev); ++ ++ return vidi_power_on(ctx, true); ++} ++#endif ++ ++static const struct dev_pm_ops vidi_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(vidi_suspend, vidi_resume) ++}; ++ ++struct platform_driver vidi_driver = { ++ .probe = vidi_probe, ++ .remove = __devexit_p(vidi_remove), ++ .driver = { ++ .name = "exynos-drm-vidi", ++ .owner = THIS_MODULE, ++ .pm = &vidi_pm_ops, ++ }, ++}; +diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.h b/drivers/gpu/drm/exynos/exynos_drm_vidi.h +new file mode 100644 +index 0000000..a4babe4 +--- /dev/null ++++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.h +@@ -0,0 +1,36 @@ ++/* exynos_drm_vidi.h ++ * ++ * Copyright (c) 2012 Samsung Electronics Co., Ltd. ++ * Author: Inki Dae ++ * ++ * 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 (including the next ++ * paragraph) 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 ++ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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. ++ */ ++ ++#ifndef _EXYNOS_DRM_VIDI_H_ ++#define _EXYNOS_DRM_VIDI_H_ ++ ++#ifdef CONFIG_DRM_EXYNOS_VIDI ++int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, ++ struct drm_file *file_priv); ++#else ++#define vidi_connection_ioctl NULL ++#endif ++ ++#endif +diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c +new file mode 100644 +index 0000000..b003538 +--- /dev/null ++++ b/drivers/gpu/drm/exynos/exynos_hdmi.c +@@ -0,0 +1,2389 @@ ++/* ++ * Copyright (C) 2011 Samsung Electronics Co.Ltd ++ * Authors: ++ * Seung-Woo Kim ++ * Inki Dae ++ * Joonyoung Shim ++ * ++ * Based on drivers/media/video/s5p-tv/hdmi_drv.c ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ */ ++ ++#include "drmP.h" ++#include "drm_edid.h" ++#include "drm_crtc_helper.h" ++ ++#include "regs-hdmi.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "exynos_drm_drv.h" ++#include "exynos_drm_hdmi.h" ++ ++#include "exynos_hdmi.h" ++ ++#define MAX_WIDTH 1920 ++#define MAX_HEIGHT 1080 ++#define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev)) ++ ++struct hdmi_resources { ++ struct clk *hdmi; ++ struct clk *sclk_hdmi; ++ struct clk *sclk_pixel; ++ struct clk *sclk_hdmiphy; ++ struct clk *hdmiphy; ++ struct regulator_bulk_data *regul_bulk; ++ int regul_count; ++}; ++ ++struct hdmi_context { ++ struct device *dev; ++ struct drm_device *drm_dev; ++ struct fb_videomode *default_timing; ++ unsigned int is_v13:1; ++ unsigned int default_win; ++ unsigned int default_bpp; ++ bool hpd_handle; ++ bool enabled; ++ ++ struct resource *regs_res; ++ void __iomem *regs; ++ unsigned int irq; ++ struct workqueue_struct *wq; ++ struct work_struct hotplug_work; ++ ++ struct i2c_client *ddc_port; ++ struct i2c_client *hdmiphy_port; ++ ++ /* current hdmiphy conf index */ ++ int cur_conf; ++ ++ struct hdmi_resources res; ++ void *parent_ctx; ++}; ++ ++/* HDMI Version 1.3 */ ++static const u8 hdmiphy_v13_conf27[32] = { ++ 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, ++ 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87, ++ 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0, ++ 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00, ++}; ++ ++static const u8 hdmiphy_v13_conf27_027[32] = { ++ 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64, ++ 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87, ++ 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0, ++ 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00, ++}; ++ ++static const u8 hdmiphy_v13_conf74_175[32] = { ++ 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B, ++ 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9, ++ 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0, ++ 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00, ++}; ++ ++static const u8 hdmiphy_v13_conf74_25[32] = { ++ 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40, ++ 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba, ++ 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0, ++ 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00, ++}; ++ ++static const u8 hdmiphy_v13_conf148_5[32] = { ++ 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40, ++ 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba, ++ 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0, ++ 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00, ++}; ++ ++struct hdmi_v13_tg_regs { ++ u8 cmd; ++ u8 h_fsz_l; ++ u8 h_fsz_h; ++ u8 hact_st_l; ++ u8 hact_st_h; ++ u8 hact_sz_l; ++ u8 hact_sz_h; ++ u8 v_fsz_l; ++ u8 v_fsz_h; ++ u8 vsync_l; ++ u8 vsync_h; ++ u8 vsync2_l; ++ u8 vsync2_h; ++ u8 vact_st_l; ++ u8 vact_st_h; ++ u8 vact_sz_l; ++ u8 vact_sz_h; ++ u8 field_chg_l; ++ u8 field_chg_h; ++ u8 vact_st2_l; ++ u8 vact_st2_h; ++ u8 vsync_top_hdmi_l; ++ u8 vsync_top_hdmi_h; ++ u8 vsync_bot_hdmi_l; ++ u8 vsync_bot_hdmi_h; ++ u8 field_top_hdmi_l; ++ u8 field_top_hdmi_h; ++ u8 field_bot_hdmi_l; ++ u8 field_bot_hdmi_h; ++}; ++ ++struct hdmi_v13_core_regs { ++ u8 h_blank[2]; ++ u8 v_blank[3]; ++ u8 h_v_line[3]; ++ u8 vsync_pol[1]; ++ u8 int_pro_mode[1]; ++ u8 v_blank_f[3]; ++ u8 h_sync_gen[3]; ++ u8 v_sync_gen1[3]; ++ u8 v_sync_gen2[3]; ++ u8 v_sync_gen3[3]; ++}; ++ ++struct hdmi_v13_preset_conf { ++ struct hdmi_v13_core_regs core; ++ struct hdmi_v13_tg_regs tg; ++}; ++ ++struct hdmi_v13_conf { ++ int width; ++ int height; ++ int vrefresh; ++ bool interlace; ++ const u8 *hdmiphy_data; ++ const struct hdmi_v13_preset_conf *conf; ++}; ++ ++static const struct hdmi_v13_preset_conf hdmi_v13_conf_480p = { ++ .core = { ++ .h_blank = {0x8a, 0x00}, ++ .v_blank = {0x0d, 0x6a, 0x01}, ++ .h_v_line = {0x0d, 0xa2, 0x35}, ++ .vsync_pol = {0x01}, ++ .int_pro_mode = {0x00}, ++ .v_blank_f = {0x00, 0x00, 0x00}, ++ .h_sync_gen = {0x0e, 0x30, 0x11}, ++ .v_sync_gen1 = {0x0f, 0x90, 0x00}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0x5a, 0x03, /* h_fsz */ ++ 0x8a, 0x00, 0xd0, 0x02, /* hact */ ++ 0x0d, 0x02, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x2d, 0x00, 0xe0, 0x01, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x49, 0x02, /* vact_st2 */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ }, ++}; ++ ++static const struct hdmi_v13_preset_conf hdmi_v13_conf_720p60 = { ++ .core = { ++ .h_blank = {0x72, 0x01}, ++ .v_blank = {0xee, 0xf2, 0x00}, ++ .h_v_line = {0xee, 0x22, 0x67}, ++ .vsync_pol = {0x00}, ++ .int_pro_mode = {0x00}, ++ .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */ ++ .h_sync_gen = {0x6c, 0x50, 0x02}, ++ .v_sync_gen1 = {0x0a, 0x50, 0x00}, ++ .v_sync_gen2 = {0x01, 0x10, 0x00}, ++ .v_sync_gen3 = {0x01, 0x10, 0x00}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0x72, 0x06, /* h_fsz */ ++ 0x71, 0x01, 0x01, 0x05, /* hact */ ++ 0xee, 0x02, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x1e, 0x00, 0xd0, 0x02, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x49, 0x02, /* vact_st2 */ ++ 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ }, ++}; ++ ++static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i50 = { ++ .core = { ++ .h_blank = {0xd0, 0x02}, ++ .v_blank = {0x32, 0xB2, 0x00}, ++ .h_v_line = {0x65, 0x04, 0xa5}, ++ .vsync_pol = {0x00}, ++ .int_pro_mode = {0x01}, ++ .v_blank_f = {0x49, 0x2A, 0x23}, ++ .h_sync_gen = {0x0E, 0xEA, 0x08}, ++ .v_sync_gen1 = {0x07, 0x20, 0x00}, ++ .v_sync_gen2 = {0x39, 0x42, 0x23}, ++ .v_sync_gen3 = {0x38, 0x87, 0x73}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0x50, 0x0A, /* h_fsz */ ++ 0xCF, 0x02, 0x81, 0x07, /* hact */ ++ 0x65, 0x04, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x16, 0x00, 0x1c, 0x02, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x49, 0x02, /* vact_st2 */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ }, ++}; ++ ++static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p50 = { ++ .core = { ++ .h_blank = {0xd0, 0x02}, ++ .v_blank = {0x65, 0x6c, 0x01}, ++ .h_v_line = {0x65, 0x04, 0xa5}, ++ .vsync_pol = {0x00}, ++ .int_pro_mode = {0x00}, ++ .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */ ++ .h_sync_gen = {0x0e, 0xea, 0x08}, ++ .v_sync_gen1 = {0x09, 0x40, 0x00}, ++ .v_sync_gen2 = {0x01, 0x10, 0x00}, ++ .v_sync_gen3 = {0x01, 0x10, 0x00}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0x50, 0x0A, /* h_fsz */ ++ 0xCF, 0x02, 0x81, 0x07, /* hact */ ++ 0x65, 0x04, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x2d, 0x00, 0x38, 0x04, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x48, 0x02, /* vact_st2 */ ++ 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ }, ++}; ++ ++static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i60 = { ++ .core = { ++ .h_blank = {0x18, 0x01}, ++ .v_blank = {0x32, 0xB2, 0x00}, ++ .h_v_line = {0x65, 0x84, 0x89}, ++ .vsync_pol = {0x00}, ++ .int_pro_mode = {0x01}, ++ .v_blank_f = {0x49, 0x2A, 0x23}, ++ .h_sync_gen = {0x56, 0x08, 0x02}, ++ .v_sync_gen1 = {0x07, 0x20, 0x00}, ++ .v_sync_gen2 = {0x39, 0x42, 0x23}, ++ .v_sync_gen3 = {0xa4, 0x44, 0x4a}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0x98, 0x08, /* h_fsz */ ++ 0x17, 0x01, 0x81, 0x07, /* hact */ ++ 0x65, 0x04, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x16, 0x00, 0x1c, 0x02, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x49, 0x02, /* vact_st2 */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ }, ++}; ++ ++static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p60 = { ++ .core = { ++ .h_blank = {0x18, 0x01}, ++ .v_blank = {0x65, 0x6c, 0x01}, ++ .h_v_line = {0x65, 0x84, 0x89}, ++ .vsync_pol = {0x00}, ++ .int_pro_mode = {0x00}, ++ .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */ ++ .h_sync_gen = {0x56, 0x08, 0x02}, ++ .v_sync_gen1 = {0x09, 0x40, 0x00}, ++ .v_sync_gen2 = {0x01, 0x10, 0x00}, ++ .v_sync_gen3 = {0x01, 0x10, 0x00}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0x98, 0x08, /* h_fsz */ ++ 0x17, 0x01, 0x81, 0x07, /* hact */ ++ 0x65, 0x04, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x2d, 0x00, 0x38, 0x04, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x48, 0x02, /* vact_st2 */ ++ 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ }, ++}; ++ ++static const struct hdmi_v13_conf hdmi_v13_confs[] = { ++ { 1280, 720, 60, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 }, ++ { 1280, 720, 50, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 }, ++ { 720, 480, 60, false, hdmiphy_v13_conf27_027, &hdmi_v13_conf_480p }, ++ { 1920, 1080, 50, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i50 }, ++ { 1920, 1080, 50, false, hdmiphy_v13_conf148_5, ++ &hdmi_v13_conf_1080p50 }, ++ { 1920, 1080, 60, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i60 }, ++ { 1920, 1080, 60, false, hdmiphy_v13_conf148_5, ++ &hdmi_v13_conf_1080p60 }, ++}; ++ ++/* HDMI Version 1.4 */ ++static const u8 hdmiphy_conf27_027[32] = { ++ 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08, ++ 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80, ++ 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, ++ 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, ++}; ++ ++static const u8 hdmiphy_conf74_25[32] = { ++ 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08, ++ 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, ++ 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, ++ 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, ++}; ++ ++static const u8 hdmiphy_conf148_5[32] = { ++ 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08, ++ 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, ++ 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, ++ 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00, ++}; ++ ++struct hdmi_tg_regs { ++ u8 cmd; ++ u8 h_fsz_l; ++ u8 h_fsz_h; ++ u8 hact_st_l; ++ u8 hact_st_h; ++ u8 hact_sz_l; ++ u8 hact_sz_h; ++ u8 v_fsz_l; ++ u8 v_fsz_h; ++ u8 vsync_l; ++ u8 vsync_h; ++ u8 vsync2_l; ++ u8 vsync2_h; ++ u8 vact_st_l; ++ u8 vact_st_h; ++ u8 vact_sz_l; ++ u8 vact_sz_h; ++ u8 field_chg_l; ++ u8 field_chg_h; ++ u8 vact_st2_l; ++ u8 vact_st2_h; ++ u8 vact_st3_l; ++ u8 vact_st3_h; ++ u8 vact_st4_l; ++ u8 vact_st4_h; ++ u8 vsync_top_hdmi_l; ++ u8 vsync_top_hdmi_h; ++ u8 vsync_bot_hdmi_l; ++ u8 vsync_bot_hdmi_h; ++ u8 field_top_hdmi_l; ++ u8 field_top_hdmi_h; ++ u8 field_bot_hdmi_l; ++ u8 field_bot_hdmi_h; ++ u8 tg_3d; ++}; ++ ++struct hdmi_core_regs { ++ u8 h_blank[2]; ++ u8 v2_blank[2]; ++ u8 v1_blank[2]; ++ u8 v_line[2]; ++ u8 h_line[2]; ++ u8 hsync_pol[1]; ++ u8 vsync_pol[1]; ++ u8 int_pro_mode[1]; ++ u8 v_blank_f0[2]; ++ u8 v_blank_f1[2]; ++ u8 h_sync_start[2]; ++ u8 h_sync_end[2]; ++ u8 v_sync_line_bef_2[2]; ++ u8 v_sync_line_bef_1[2]; ++ u8 v_sync_line_aft_2[2]; ++ u8 v_sync_line_aft_1[2]; ++ u8 v_sync_line_aft_pxl_2[2]; ++ u8 v_sync_line_aft_pxl_1[2]; ++ u8 v_blank_f2[2]; /* for 3D mode */ ++ u8 v_blank_f3[2]; /* for 3D mode */ ++ u8 v_blank_f4[2]; /* for 3D mode */ ++ u8 v_blank_f5[2]; /* for 3D mode */ ++ u8 v_sync_line_aft_3[2]; ++ u8 v_sync_line_aft_4[2]; ++ u8 v_sync_line_aft_5[2]; ++ u8 v_sync_line_aft_6[2]; ++ u8 v_sync_line_aft_pxl_3[2]; ++ u8 v_sync_line_aft_pxl_4[2]; ++ u8 v_sync_line_aft_pxl_5[2]; ++ u8 v_sync_line_aft_pxl_6[2]; ++ u8 vact_space_1[2]; ++ u8 vact_space_2[2]; ++ u8 vact_space_3[2]; ++ u8 vact_space_4[2]; ++ u8 vact_space_5[2]; ++ u8 vact_space_6[2]; ++}; ++ ++struct hdmi_preset_conf { ++ struct hdmi_core_regs core; ++ struct hdmi_tg_regs tg; ++}; ++ ++struct hdmi_conf { ++ int width; ++ int height; ++ int vrefresh; ++ bool interlace; ++ const u8 *hdmiphy_data; ++ const struct hdmi_preset_conf *conf; ++}; ++ ++static const struct hdmi_preset_conf hdmi_conf_480p60 = { ++ .core = { ++ .h_blank = {0x8a, 0x00}, ++ .v2_blank = {0x0d, 0x02}, ++ .v1_blank = {0x2d, 0x00}, ++ .v_line = {0x0d, 0x02}, ++ .h_line = {0x5a, 0x03}, ++ .hsync_pol = {0x01}, ++ .vsync_pol = {0x01}, ++ .int_pro_mode = {0x00}, ++ .v_blank_f0 = {0xff, 0xff}, ++ .v_blank_f1 = {0xff, 0xff}, ++ .h_sync_start = {0x0e, 0x00}, ++ .h_sync_end = {0x4c, 0x00}, ++ .v_sync_line_bef_2 = {0x0f, 0x00}, ++ .v_sync_line_bef_1 = {0x09, 0x00}, ++ .v_sync_line_aft_2 = {0xff, 0xff}, ++ .v_sync_line_aft_1 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_2 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_1 = {0xff, 0xff}, ++ .v_blank_f2 = {0xff, 0xff}, ++ .v_blank_f3 = {0xff, 0xff}, ++ .v_blank_f4 = {0xff, 0xff}, ++ .v_blank_f5 = {0xff, 0xff}, ++ .v_sync_line_aft_3 = {0xff, 0xff}, ++ .v_sync_line_aft_4 = {0xff, 0xff}, ++ .v_sync_line_aft_5 = {0xff, 0xff}, ++ .v_sync_line_aft_6 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_3 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_4 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_5 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_6 = {0xff, 0xff}, ++ .vact_space_1 = {0xff, 0xff}, ++ .vact_space_2 = {0xff, 0xff}, ++ .vact_space_3 = {0xff, 0xff}, ++ .vact_space_4 = {0xff, 0xff}, ++ .vact_space_5 = {0xff, 0xff}, ++ .vact_space_6 = {0xff, 0xff}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0x5a, 0x03, /* h_fsz */ ++ 0x8a, 0x00, 0xd0, 0x02, /* hact */ ++ 0x0d, 0x02, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x2d, 0x00, 0xe0, 0x01, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x48, 0x02, /* vact_st2 */ ++ 0x00, 0x00, /* vact_st3 */ ++ 0x00, 0x00, /* vact_st4 */ ++ 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ 0x00, /* 3d FP */ ++ }, ++}; ++ ++static const struct hdmi_preset_conf hdmi_conf_720p50 = { ++ .core = { ++ .h_blank = {0xbc, 0x02}, ++ .v2_blank = {0xee, 0x02}, ++ .v1_blank = {0x1e, 0x00}, ++ .v_line = {0xee, 0x02}, ++ .h_line = {0xbc, 0x07}, ++ .hsync_pol = {0x00}, ++ .vsync_pol = {0x00}, ++ .int_pro_mode = {0x00}, ++ .v_blank_f0 = {0xff, 0xff}, ++ .v_blank_f1 = {0xff, 0xff}, ++ .h_sync_start = {0xb6, 0x01}, ++ .h_sync_end = {0xde, 0x01}, ++ .v_sync_line_bef_2 = {0x0a, 0x00}, ++ .v_sync_line_bef_1 = {0x05, 0x00}, ++ .v_sync_line_aft_2 = {0xff, 0xff}, ++ .v_sync_line_aft_1 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_2 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_1 = {0xff, 0xff}, ++ .v_blank_f2 = {0xff, 0xff}, ++ .v_blank_f3 = {0xff, 0xff}, ++ .v_blank_f4 = {0xff, 0xff}, ++ .v_blank_f5 = {0xff, 0xff}, ++ .v_sync_line_aft_3 = {0xff, 0xff}, ++ .v_sync_line_aft_4 = {0xff, 0xff}, ++ .v_sync_line_aft_5 = {0xff, 0xff}, ++ .v_sync_line_aft_6 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_3 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_4 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_5 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_6 = {0xff, 0xff}, ++ .vact_space_1 = {0xff, 0xff}, ++ .vact_space_2 = {0xff, 0xff}, ++ .vact_space_3 = {0xff, 0xff}, ++ .vact_space_4 = {0xff, 0xff}, ++ .vact_space_5 = {0xff, 0xff}, ++ .vact_space_6 = {0xff, 0xff}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0xbc, 0x07, /* h_fsz */ ++ 0xbc, 0x02, 0x00, 0x05, /* hact */ ++ 0xee, 0x02, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x1e, 0x00, 0xd0, 0x02, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x48, 0x02, /* vact_st2 */ ++ 0x00, 0x00, /* vact_st3 */ ++ 0x00, 0x00, /* vact_st4 */ ++ 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ 0x00, /* 3d FP */ ++ }, ++}; ++ ++static const struct hdmi_preset_conf hdmi_conf_720p60 = { ++ .core = { ++ .h_blank = {0x72, 0x01}, ++ .v2_blank = {0xee, 0x02}, ++ .v1_blank = {0x1e, 0x00}, ++ .v_line = {0xee, 0x02}, ++ .h_line = {0x72, 0x06}, ++ .hsync_pol = {0x00}, ++ .vsync_pol = {0x00}, ++ .int_pro_mode = {0x00}, ++ .v_blank_f0 = {0xff, 0xff}, ++ .v_blank_f1 = {0xff, 0xff}, ++ .h_sync_start = {0x6c, 0x00}, ++ .h_sync_end = {0x94, 0x00}, ++ .v_sync_line_bef_2 = {0x0a, 0x00}, ++ .v_sync_line_bef_1 = {0x05, 0x00}, ++ .v_sync_line_aft_2 = {0xff, 0xff}, ++ .v_sync_line_aft_1 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_2 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_1 = {0xff, 0xff}, ++ .v_blank_f2 = {0xff, 0xff}, ++ .v_blank_f3 = {0xff, 0xff}, ++ .v_blank_f4 = {0xff, 0xff}, ++ .v_blank_f5 = {0xff, 0xff}, ++ .v_sync_line_aft_3 = {0xff, 0xff}, ++ .v_sync_line_aft_4 = {0xff, 0xff}, ++ .v_sync_line_aft_5 = {0xff, 0xff}, ++ .v_sync_line_aft_6 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_3 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_4 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_5 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_6 = {0xff, 0xff}, ++ .vact_space_1 = {0xff, 0xff}, ++ .vact_space_2 = {0xff, 0xff}, ++ .vact_space_3 = {0xff, 0xff}, ++ .vact_space_4 = {0xff, 0xff}, ++ .vact_space_5 = {0xff, 0xff}, ++ .vact_space_6 = {0xff, 0xff}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0x72, 0x06, /* h_fsz */ ++ 0x72, 0x01, 0x00, 0x05, /* hact */ ++ 0xee, 0x02, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x1e, 0x00, 0xd0, 0x02, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x48, 0x02, /* vact_st2 */ ++ 0x00, 0x00, /* vact_st3 */ ++ 0x00, 0x00, /* vact_st4 */ ++ 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ 0x00, /* 3d FP */ ++ }, ++}; ++ ++static const struct hdmi_preset_conf hdmi_conf_1080i50 = { ++ .core = { ++ .h_blank = {0xd0, 0x02}, ++ .v2_blank = {0x32, 0x02}, ++ .v1_blank = {0x16, 0x00}, ++ .v_line = {0x65, 0x04}, ++ .h_line = {0x50, 0x0a}, ++ .hsync_pol = {0x00}, ++ .vsync_pol = {0x00}, ++ .int_pro_mode = {0x01}, ++ .v_blank_f0 = {0x49, 0x02}, ++ .v_blank_f1 = {0x65, 0x04}, ++ .h_sync_start = {0x0e, 0x02}, ++ .h_sync_end = {0x3a, 0x02}, ++ .v_sync_line_bef_2 = {0x07, 0x00}, ++ .v_sync_line_bef_1 = {0x02, 0x00}, ++ .v_sync_line_aft_2 = {0x39, 0x02}, ++ .v_sync_line_aft_1 = {0x34, 0x02}, ++ .v_sync_line_aft_pxl_2 = {0x38, 0x07}, ++ .v_sync_line_aft_pxl_1 = {0x38, 0x07}, ++ .v_blank_f2 = {0xff, 0xff}, ++ .v_blank_f3 = {0xff, 0xff}, ++ .v_blank_f4 = {0xff, 0xff}, ++ .v_blank_f5 = {0xff, 0xff}, ++ .v_sync_line_aft_3 = {0xff, 0xff}, ++ .v_sync_line_aft_4 = {0xff, 0xff}, ++ .v_sync_line_aft_5 = {0xff, 0xff}, ++ .v_sync_line_aft_6 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_3 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_4 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_5 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_6 = {0xff, 0xff}, ++ .vact_space_1 = {0xff, 0xff}, ++ .vact_space_2 = {0xff, 0xff}, ++ .vact_space_3 = {0xff, 0xff}, ++ .vact_space_4 = {0xff, 0xff}, ++ .vact_space_5 = {0xff, 0xff}, ++ .vact_space_6 = {0xff, 0xff}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0x50, 0x0a, /* h_fsz */ ++ 0xd0, 0x02, 0x80, 0x07, /* hact */ ++ 0x65, 0x04, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x16, 0x00, 0x1c, 0x02, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x49, 0x02, /* vact_st2 */ ++ 0x00, 0x00, /* vact_st3 */ ++ 0x00, 0x00, /* vact_st4 */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ 0x00, /* 3d FP */ ++ }, ++}; ++ ++static const struct hdmi_preset_conf hdmi_conf_1080i60 = { ++ .core = { ++ .h_blank = {0x18, 0x01}, ++ .v2_blank = {0x32, 0x02}, ++ .v1_blank = {0x16, 0x00}, ++ .v_line = {0x65, 0x04}, ++ .h_line = {0x98, 0x08}, ++ .hsync_pol = {0x00}, ++ .vsync_pol = {0x00}, ++ .int_pro_mode = {0x01}, ++ .v_blank_f0 = {0x49, 0x02}, ++ .v_blank_f1 = {0x65, 0x04}, ++ .h_sync_start = {0x56, 0x00}, ++ .h_sync_end = {0x82, 0x00}, ++ .v_sync_line_bef_2 = {0x07, 0x00}, ++ .v_sync_line_bef_1 = {0x02, 0x00}, ++ .v_sync_line_aft_2 = {0x39, 0x02}, ++ .v_sync_line_aft_1 = {0x34, 0x02}, ++ .v_sync_line_aft_pxl_2 = {0xa4, 0x04}, ++ .v_sync_line_aft_pxl_1 = {0xa4, 0x04}, ++ .v_blank_f2 = {0xff, 0xff}, ++ .v_blank_f3 = {0xff, 0xff}, ++ .v_blank_f4 = {0xff, 0xff}, ++ .v_blank_f5 = {0xff, 0xff}, ++ .v_sync_line_aft_3 = {0xff, 0xff}, ++ .v_sync_line_aft_4 = {0xff, 0xff}, ++ .v_sync_line_aft_5 = {0xff, 0xff}, ++ .v_sync_line_aft_6 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_3 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_4 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_5 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_6 = {0xff, 0xff}, ++ .vact_space_1 = {0xff, 0xff}, ++ .vact_space_2 = {0xff, 0xff}, ++ .vact_space_3 = {0xff, 0xff}, ++ .vact_space_4 = {0xff, 0xff}, ++ .vact_space_5 = {0xff, 0xff}, ++ .vact_space_6 = {0xff, 0xff}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0x98, 0x08, /* h_fsz */ ++ 0x18, 0x01, 0x80, 0x07, /* hact */ ++ 0x65, 0x04, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x16, 0x00, 0x1c, 0x02, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x49, 0x02, /* vact_st2 */ ++ 0x00, 0x00, /* vact_st3 */ ++ 0x00, 0x00, /* vact_st4 */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ 0x00, /* 3d FP */ ++ }, ++}; ++ ++static const struct hdmi_preset_conf hdmi_conf_1080p50 = { ++ .core = { ++ .h_blank = {0xd0, 0x02}, ++ .v2_blank = {0x65, 0x04}, ++ .v1_blank = {0x2d, 0x00}, ++ .v_line = {0x65, 0x04}, ++ .h_line = {0x50, 0x0a}, ++ .hsync_pol = {0x00}, ++ .vsync_pol = {0x00}, ++ .int_pro_mode = {0x00}, ++ .v_blank_f0 = {0xff, 0xff}, ++ .v_blank_f1 = {0xff, 0xff}, ++ .h_sync_start = {0x0e, 0x02}, ++ .h_sync_end = {0x3a, 0x02}, ++ .v_sync_line_bef_2 = {0x09, 0x00}, ++ .v_sync_line_bef_1 = {0x04, 0x00}, ++ .v_sync_line_aft_2 = {0xff, 0xff}, ++ .v_sync_line_aft_1 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_2 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_1 = {0xff, 0xff}, ++ .v_blank_f2 = {0xff, 0xff}, ++ .v_blank_f3 = {0xff, 0xff}, ++ .v_blank_f4 = {0xff, 0xff}, ++ .v_blank_f5 = {0xff, 0xff}, ++ .v_sync_line_aft_3 = {0xff, 0xff}, ++ .v_sync_line_aft_4 = {0xff, 0xff}, ++ .v_sync_line_aft_5 = {0xff, 0xff}, ++ .v_sync_line_aft_6 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_3 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_4 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_5 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_6 = {0xff, 0xff}, ++ .vact_space_1 = {0xff, 0xff}, ++ .vact_space_2 = {0xff, 0xff}, ++ .vact_space_3 = {0xff, 0xff}, ++ .vact_space_4 = {0xff, 0xff}, ++ .vact_space_5 = {0xff, 0xff}, ++ .vact_space_6 = {0xff, 0xff}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0x50, 0x0a, /* h_fsz */ ++ 0xd0, 0x02, 0x80, 0x07, /* hact */ ++ 0x65, 0x04, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x2d, 0x00, 0x38, 0x04, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x48, 0x02, /* vact_st2 */ ++ 0x00, 0x00, /* vact_st3 */ ++ 0x00, 0x00, /* vact_st4 */ ++ 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ 0x00, /* 3d FP */ ++ }, ++}; ++ ++static const struct hdmi_preset_conf hdmi_conf_1080p60 = { ++ .core = { ++ .h_blank = {0x18, 0x01}, ++ .v2_blank = {0x65, 0x04}, ++ .v1_blank = {0x2d, 0x00}, ++ .v_line = {0x65, 0x04}, ++ .h_line = {0x98, 0x08}, ++ .hsync_pol = {0x00}, ++ .vsync_pol = {0x00}, ++ .int_pro_mode = {0x00}, ++ .v_blank_f0 = {0xff, 0xff}, ++ .v_blank_f1 = {0xff, 0xff}, ++ .h_sync_start = {0x56, 0x00}, ++ .h_sync_end = {0x82, 0x00}, ++ .v_sync_line_bef_2 = {0x09, 0x00}, ++ .v_sync_line_bef_1 = {0x04, 0x00}, ++ .v_sync_line_aft_2 = {0xff, 0xff}, ++ .v_sync_line_aft_1 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_2 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_1 = {0xff, 0xff}, ++ .v_blank_f2 = {0xff, 0xff}, ++ .v_blank_f3 = {0xff, 0xff}, ++ .v_blank_f4 = {0xff, 0xff}, ++ .v_blank_f5 = {0xff, 0xff}, ++ .v_sync_line_aft_3 = {0xff, 0xff}, ++ .v_sync_line_aft_4 = {0xff, 0xff}, ++ .v_sync_line_aft_5 = {0xff, 0xff}, ++ .v_sync_line_aft_6 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_3 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_4 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_5 = {0xff, 0xff}, ++ .v_sync_line_aft_pxl_6 = {0xff, 0xff}, ++ /* other don't care */ ++ }, ++ .tg = { ++ 0x00, /* cmd */ ++ 0x98, 0x08, /* h_fsz */ ++ 0x18, 0x01, 0x80, 0x07, /* hact */ ++ 0x65, 0x04, /* v_fsz */ ++ 0x01, 0x00, 0x33, 0x02, /* vsync */ ++ 0x2d, 0x00, 0x38, 0x04, /* vact */ ++ 0x33, 0x02, /* field_chg */ ++ 0x48, 0x02, /* vact_st2 */ ++ 0x00, 0x00, /* vact_st3 */ ++ 0x00, 0x00, /* vact_st4 */ ++ 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ ++ 0x01, 0x00, 0x33, 0x02, /* field top/bot */ ++ 0x00, /* 3d FP */ ++ }, ++}; ++ ++static const struct hdmi_conf hdmi_confs[] = { ++ { 720, 480, 60, false, hdmiphy_conf27_027, &hdmi_conf_480p60 }, ++ { 1280, 720, 50, false, hdmiphy_conf74_25, &hdmi_conf_720p50 }, ++ { 1280, 720, 60, false, hdmiphy_conf74_25, &hdmi_conf_720p60 }, ++ { 1920, 1080, 50, true, hdmiphy_conf74_25, &hdmi_conf_1080i50 }, ++ { 1920, 1080, 60, true, hdmiphy_conf74_25, &hdmi_conf_1080i60 }, ++ { 1920, 1080, 50, false, hdmiphy_conf148_5, &hdmi_conf_1080p50 }, ++ { 1920, 1080, 60, false, hdmiphy_conf148_5, &hdmi_conf_1080p60 }, ++}; ++ ++ ++static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id) ++{ ++ return readl(hdata->regs + reg_id); ++} ++ ++static inline void hdmi_reg_writeb(struct hdmi_context *hdata, ++ u32 reg_id, u8 value) ++{ ++ writeb(value, hdata->regs + reg_id); ++} ++ ++static inline void hdmi_reg_writemask(struct hdmi_context *hdata, ++ u32 reg_id, u32 value, u32 mask) ++{ ++ u32 old = readl(hdata->regs + reg_id); ++ value = (value & mask) | (old & ~mask); ++ writel(value, hdata->regs + reg_id); ++} ++ ++static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix) ++{ ++#define DUMPREG(reg_id) \ ++ DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \ ++ readl(hdata->regs + reg_id)) ++ DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix); ++ DUMPREG(HDMI_INTC_FLAG); ++ DUMPREG(HDMI_INTC_CON); ++ DUMPREG(HDMI_HPD_STATUS); ++ DUMPREG(HDMI_V13_PHY_RSTOUT); ++ DUMPREG(HDMI_V13_PHY_VPLL); ++ DUMPREG(HDMI_V13_PHY_CMU); ++ DUMPREG(HDMI_V13_CORE_RSTOUT); ++ ++ DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix); ++ DUMPREG(HDMI_CON_0); ++ DUMPREG(HDMI_CON_1); ++ DUMPREG(HDMI_CON_2); ++ DUMPREG(HDMI_SYS_STATUS); ++ DUMPREG(HDMI_V13_PHY_STATUS); ++ DUMPREG(HDMI_STATUS_EN); ++ DUMPREG(HDMI_HPD); ++ DUMPREG(HDMI_MODE_SEL); ++ DUMPREG(HDMI_V13_HPD_GEN); ++ DUMPREG(HDMI_V13_DC_CONTROL); ++ DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN); ++ ++ DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix); ++ DUMPREG(HDMI_H_BLANK_0); ++ DUMPREG(HDMI_H_BLANK_1); ++ DUMPREG(HDMI_V13_V_BLANK_0); ++ DUMPREG(HDMI_V13_V_BLANK_1); ++ DUMPREG(HDMI_V13_V_BLANK_2); ++ DUMPREG(HDMI_V13_H_V_LINE_0); ++ DUMPREG(HDMI_V13_H_V_LINE_1); ++ DUMPREG(HDMI_V13_H_V_LINE_2); ++ DUMPREG(HDMI_VSYNC_POL); ++ DUMPREG(HDMI_INT_PRO_MODE); ++ DUMPREG(HDMI_V13_V_BLANK_F_0); ++ DUMPREG(HDMI_V13_V_BLANK_F_1); ++ DUMPREG(HDMI_V13_V_BLANK_F_2); ++ DUMPREG(HDMI_V13_H_SYNC_GEN_0); ++ DUMPREG(HDMI_V13_H_SYNC_GEN_1); ++ DUMPREG(HDMI_V13_H_SYNC_GEN_2); ++ DUMPREG(HDMI_V13_V_SYNC_GEN_1_0); ++ DUMPREG(HDMI_V13_V_SYNC_GEN_1_1); ++ DUMPREG(HDMI_V13_V_SYNC_GEN_1_2); ++ DUMPREG(HDMI_V13_V_SYNC_GEN_2_0); ++ DUMPREG(HDMI_V13_V_SYNC_GEN_2_1); ++ DUMPREG(HDMI_V13_V_SYNC_GEN_2_2); ++ DUMPREG(HDMI_V13_V_SYNC_GEN_3_0); ++ DUMPREG(HDMI_V13_V_SYNC_GEN_3_1); ++ DUMPREG(HDMI_V13_V_SYNC_GEN_3_2); ++ ++ DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix); ++ DUMPREG(HDMI_TG_CMD); ++ DUMPREG(HDMI_TG_H_FSZ_L); ++ DUMPREG(HDMI_TG_H_FSZ_H); ++ DUMPREG(HDMI_TG_HACT_ST_L); ++ DUMPREG(HDMI_TG_HACT_ST_H); ++ DUMPREG(HDMI_TG_HACT_SZ_L); ++ DUMPREG(HDMI_TG_HACT_SZ_H); ++ DUMPREG(HDMI_TG_V_FSZ_L); ++ DUMPREG(HDMI_TG_V_FSZ_H); ++ DUMPREG(HDMI_TG_VSYNC_L); ++ DUMPREG(HDMI_TG_VSYNC_H); ++ DUMPREG(HDMI_TG_VSYNC2_L); ++ DUMPREG(HDMI_TG_VSYNC2_H); ++ DUMPREG(HDMI_TG_VACT_ST_L); ++ DUMPREG(HDMI_TG_VACT_ST_H); ++ DUMPREG(HDMI_TG_VACT_SZ_L); ++ DUMPREG(HDMI_TG_VACT_SZ_H); ++ DUMPREG(HDMI_TG_FIELD_CHG_L); ++ DUMPREG(HDMI_TG_FIELD_CHG_H); ++ DUMPREG(HDMI_TG_VACT_ST2_L); ++ DUMPREG(HDMI_TG_VACT_ST2_H); ++ DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L); ++ DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H); ++ DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L); ++ DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H); ++ DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L); ++ DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H); ++ DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L); ++ DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H); ++#undef DUMPREG ++} ++ ++static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix) ++{ ++ int i; ++ ++#define DUMPREG(reg_id) \ ++ DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \ ++ readl(hdata->regs + reg_id)) ++ ++ DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix); ++ DUMPREG(HDMI_INTC_CON); ++ DUMPREG(HDMI_INTC_FLAG); ++ DUMPREG(HDMI_HPD_STATUS); ++ DUMPREG(HDMI_INTC_CON_1); ++ DUMPREG(HDMI_INTC_FLAG_1); ++ DUMPREG(HDMI_PHY_STATUS_0); ++ DUMPREG(HDMI_PHY_STATUS_PLL); ++ DUMPREG(HDMI_PHY_CON_0); ++ DUMPREG(HDMI_PHY_RSTOUT); ++ DUMPREG(HDMI_PHY_VPLL); ++ DUMPREG(HDMI_PHY_CMU); ++ DUMPREG(HDMI_CORE_RSTOUT); ++ ++ DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix); ++ DUMPREG(HDMI_CON_0); ++ DUMPREG(HDMI_CON_1); ++ DUMPREG(HDMI_CON_2); ++ DUMPREG(HDMI_SYS_STATUS); ++ DUMPREG(HDMI_PHY_STATUS_0); ++ DUMPREG(HDMI_STATUS_EN); ++ DUMPREG(HDMI_HPD); ++ DUMPREG(HDMI_MODE_SEL); ++ DUMPREG(HDMI_ENC_EN); ++ DUMPREG(HDMI_DC_CONTROL); ++ DUMPREG(HDMI_VIDEO_PATTERN_GEN); ++ ++ DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix); ++ DUMPREG(HDMI_H_BLANK_0); ++ DUMPREG(HDMI_H_BLANK_1); ++ DUMPREG(HDMI_V2_BLANK_0); ++ DUMPREG(HDMI_V2_BLANK_1); ++ DUMPREG(HDMI_V1_BLANK_0); ++ DUMPREG(HDMI_V1_BLANK_1); ++ DUMPREG(HDMI_V_LINE_0); ++ DUMPREG(HDMI_V_LINE_1); ++ DUMPREG(HDMI_H_LINE_0); ++ DUMPREG(HDMI_H_LINE_1); ++ DUMPREG(HDMI_HSYNC_POL); ++ ++ DUMPREG(HDMI_VSYNC_POL); ++ DUMPREG(HDMI_INT_PRO_MODE); ++ DUMPREG(HDMI_V_BLANK_F0_0); ++ DUMPREG(HDMI_V_BLANK_F0_1); ++ DUMPREG(HDMI_V_BLANK_F1_0); ++ DUMPREG(HDMI_V_BLANK_F1_1); ++ ++ DUMPREG(HDMI_H_SYNC_START_0); ++ DUMPREG(HDMI_H_SYNC_START_1); ++ DUMPREG(HDMI_H_SYNC_END_0); ++ DUMPREG(HDMI_H_SYNC_END_1); ++ ++ DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0); ++ DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1); ++ DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0); ++ DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1); ++ ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1); ++ ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1); ++ ++ DUMPREG(HDMI_V_BLANK_F2_0); ++ DUMPREG(HDMI_V_BLANK_F2_1); ++ DUMPREG(HDMI_V_BLANK_F3_0); ++ DUMPREG(HDMI_V_BLANK_F3_1); ++ DUMPREG(HDMI_V_BLANK_F4_0); ++ DUMPREG(HDMI_V_BLANK_F4_1); ++ DUMPREG(HDMI_V_BLANK_F5_0); ++ DUMPREG(HDMI_V_BLANK_F5_1); ++ ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1); ++ ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0); ++ DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1); ++ ++ DUMPREG(HDMI_VACT_SPACE_1_0); ++ DUMPREG(HDMI_VACT_SPACE_1_1); ++ DUMPREG(HDMI_VACT_SPACE_2_0); ++ DUMPREG(HDMI_VACT_SPACE_2_1); ++ DUMPREG(HDMI_VACT_SPACE_3_0); ++ DUMPREG(HDMI_VACT_SPACE_3_1); ++ DUMPREG(HDMI_VACT_SPACE_4_0); ++ DUMPREG(HDMI_VACT_SPACE_4_1); ++ DUMPREG(HDMI_VACT_SPACE_5_0); ++ DUMPREG(HDMI_VACT_SPACE_5_1); ++ DUMPREG(HDMI_VACT_SPACE_6_0); ++ DUMPREG(HDMI_VACT_SPACE_6_1); ++ ++ DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix); ++ DUMPREG(HDMI_TG_CMD); ++ DUMPREG(HDMI_TG_H_FSZ_L); ++ DUMPREG(HDMI_TG_H_FSZ_H); ++ DUMPREG(HDMI_TG_HACT_ST_L); ++ DUMPREG(HDMI_TG_HACT_ST_H); ++ DUMPREG(HDMI_TG_HACT_SZ_L); ++ DUMPREG(HDMI_TG_HACT_SZ_H); ++ DUMPREG(HDMI_TG_V_FSZ_L); ++ DUMPREG(HDMI_TG_V_FSZ_H); ++ DUMPREG(HDMI_TG_VSYNC_L); ++ DUMPREG(HDMI_TG_VSYNC_H); ++ DUMPREG(HDMI_TG_VSYNC2_L); ++ DUMPREG(HDMI_TG_VSYNC2_H); ++ DUMPREG(HDMI_TG_VACT_ST_L); ++ DUMPREG(HDMI_TG_VACT_ST_H); ++ DUMPREG(HDMI_TG_VACT_SZ_L); ++ DUMPREG(HDMI_TG_VACT_SZ_H); ++ DUMPREG(HDMI_TG_FIELD_CHG_L); ++ DUMPREG(HDMI_TG_FIELD_CHG_H); ++ DUMPREG(HDMI_TG_VACT_ST2_L); ++ DUMPREG(HDMI_TG_VACT_ST2_H); ++ DUMPREG(HDMI_TG_VACT_ST3_L); ++ DUMPREG(HDMI_TG_VACT_ST3_H); ++ DUMPREG(HDMI_TG_VACT_ST4_L); ++ DUMPREG(HDMI_TG_VACT_ST4_H); ++ DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L); ++ DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H); ++ DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L); ++ DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H); ++ DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L); ++ DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H); ++ DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L); ++ DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H); ++ DUMPREG(HDMI_TG_3D); ++ ++ DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix); ++ DUMPREG(HDMI_AVI_CON); ++ DUMPREG(HDMI_AVI_HEADER0); ++ DUMPREG(HDMI_AVI_HEADER1); ++ DUMPREG(HDMI_AVI_HEADER2); ++ DUMPREG(HDMI_AVI_CHECK_SUM); ++ DUMPREG(HDMI_VSI_CON); ++ DUMPREG(HDMI_VSI_HEADER0); ++ DUMPREG(HDMI_VSI_HEADER1); ++ DUMPREG(HDMI_VSI_HEADER2); ++ for (i = 0; i < 7; ++i) ++ DUMPREG(HDMI_VSI_DATA(i)); ++ ++#undef DUMPREG ++} ++ ++static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix) ++{ ++ if (hdata->is_v13) ++ hdmi_v13_regs_dump(hdata, prefix); ++ else ++ hdmi_v14_regs_dump(hdata, prefix); ++} ++ ++static int hdmi_v13_conf_index(struct drm_display_mode *mode) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i) ++ if (hdmi_v13_confs[i].width == mode->hdisplay && ++ hdmi_v13_confs[i].height == mode->vdisplay && ++ hdmi_v13_confs[i].vrefresh == mode->vrefresh && ++ hdmi_v13_confs[i].interlace == ++ ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? ++ true : false)) ++ return i; ++ ++ return -EINVAL; ++} ++ ++static int hdmi_v14_conf_index(struct drm_display_mode *mode) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(hdmi_confs); ++i) ++ if (hdmi_confs[i].width == mode->hdisplay && ++ hdmi_confs[i].height == mode->vdisplay && ++ hdmi_confs[i].vrefresh == mode->vrefresh && ++ hdmi_confs[i].interlace == ++ ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? ++ true : false)) ++ return i; ++ ++ return -EINVAL; ++} ++ ++static int hdmi_conf_index(struct hdmi_context *hdata, ++ struct drm_display_mode *mode) ++{ ++ if (hdata->is_v13) ++ return hdmi_v13_conf_index(mode); ++ ++ return hdmi_v14_conf_index(mode); ++} ++ ++static bool hdmi_is_connected(void *ctx) ++{ ++ struct hdmi_context *hdata = ctx; ++ u32 val = hdmi_reg_read(hdata, HDMI_HPD_STATUS); ++ ++ if (val) ++ return true; ++ ++ return false; ++} ++ ++static int hdmi_get_edid(void *ctx, struct drm_connector *connector, ++ u8 *edid, int len) ++{ ++ struct edid *raw_edid; ++ struct hdmi_context *hdata = ctx; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ if (!hdata->ddc_port) ++ return -ENODEV; ++ ++ raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); ++ if (raw_edid) { ++ memcpy(edid, raw_edid, min((1 + raw_edid->extensions) ++ * EDID_LENGTH, len)); ++ DRM_DEBUG_KMS("width[%d] x height[%d]\n", ++ raw_edid->width_cm, raw_edid->height_cm); ++ } else { ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static int hdmi_v13_check_timing(struct fb_videomode *check_timing) ++{ ++ int i; ++ ++ DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n", ++ check_timing->xres, check_timing->yres, ++ check_timing->refresh, (check_timing->vmode & ++ FB_VMODE_INTERLACED) ? true : false); ++ ++ for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i) ++ if (hdmi_v13_confs[i].width == check_timing->xres && ++ hdmi_v13_confs[i].height == check_timing->yres && ++ hdmi_v13_confs[i].vrefresh == check_timing->refresh && ++ hdmi_v13_confs[i].interlace == ++ ((check_timing->vmode & FB_VMODE_INTERLACED) ? ++ true : false)) ++ return 0; ++ ++ /* TODO */ ++ ++ return -EINVAL; ++} ++ ++static int hdmi_v14_check_timing(struct fb_videomode *check_timing) ++{ ++ int i; ++ ++ DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n", ++ check_timing->xres, check_timing->yres, ++ check_timing->refresh, (check_timing->vmode & ++ FB_VMODE_INTERLACED) ? true : false); ++ ++ for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++) ++ if (hdmi_confs[i].width == check_timing->xres && ++ hdmi_confs[i].height == check_timing->yres && ++ hdmi_confs[i].vrefresh == check_timing->refresh && ++ hdmi_confs[i].interlace == ++ ((check_timing->vmode & FB_VMODE_INTERLACED) ? ++ true : false)) ++ return 0; ++ ++ /* TODO */ ++ ++ return -EINVAL; ++} ++ ++static int hdmi_check_timing(void *ctx, void *timing) ++{ ++ struct hdmi_context *hdata = ctx; ++ struct fb_videomode *check_timing = timing; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", check_timing->xres, ++ check_timing->yres, check_timing->refresh, ++ check_timing->vmode); ++ ++ if (hdata->is_v13) ++ return hdmi_v13_check_timing(check_timing); ++ else ++ return hdmi_v14_check_timing(check_timing); ++} ++ ++static int hdmi_display_power_on(void *ctx, int mode) ++{ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ switch (mode) { ++ case DRM_MODE_DPMS_ON: ++ DRM_DEBUG_KMS("hdmi [on]\n"); ++ break; ++ case DRM_MODE_DPMS_STANDBY: ++ break; ++ case DRM_MODE_DPMS_SUSPEND: ++ break; ++ case DRM_MODE_DPMS_OFF: ++ DRM_DEBUG_KMS("hdmi [off]\n"); ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static void hdmi_set_acr(u32 freq, u8 *acr) ++{ ++ u32 n, cts; ++ ++ switch (freq) { ++ case 32000: ++ n = 4096; ++ cts = 27000; ++ break; ++ case 44100: ++ n = 6272; ++ cts = 30000; ++ break; ++ case 88200: ++ n = 12544; ++ cts = 30000; ++ break; ++ case 176400: ++ n = 25088; ++ cts = 30000; ++ break; ++ case 48000: ++ n = 6144; ++ cts = 27000; ++ break; ++ case 96000: ++ n = 12288; ++ cts = 27000; ++ break; ++ case 192000: ++ n = 24576; ++ cts = 27000; ++ break; ++ default: ++ n = 0; ++ cts = 0; ++ break; ++ } ++ ++ acr[1] = cts >> 16; ++ acr[2] = cts >> 8 & 0xff; ++ acr[3] = cts & 0xff; ++ ++ acr[4] = n >> 16; ++ acr[5] = n >> 8 & 0xff; ++ acr[6] = n & 0xff; ++} ++ ++static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr) ++{ ++ hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]); ++ hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]); ++ hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]); ++ hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]); ++ hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]); ++ hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]); ++ hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]); ++ hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]); ++ hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]); ++ ++ if (hdata->is_v13) ++ hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4); ++ else ++ hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4); ++} ++ ++static void hdmi_audio_init(struct hdmi_context *hdata) ++{ ++ u32 sample_rate, bits_per_sample, frame_size_code; ++ u32 data_num, bit_ch, sample_frq; ++ u32 val; ++ u8 acr[7]; ++ ++ sample_rate = 44100; ++ bits_per_sample = 16; ++ frame_size_code = 0; ++ ++ switch (bits_per_sample) { ++ case 20: ++ data_num = 2; ++ bit_ch = 1; ++ break; ++ case 24: ++ data_num = 3; ++ bit_ch = 1; ++ break; ++ default: ++ data_num = 1; ++ bit_ch = 0; ++ break; ++ } ++ ++ hdmi_set_acr(sample_rate, acr); ++ hdmi_reg_acr(hdata, acr); ++ ++ hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE ++ | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE ++ | HDMI_I2S_MUX_ENABLE); ++ ++ hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN ++ | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN); ++ ++ hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN); ++ ++ sample_frq = (sample_rate == 44100) ? 0 : ++ (sample_rate == 48000) ? 2 : ++ (sample_rate == 32000) ? 3 : ++ (sample_rate == 96000) ? 0xa : 0x0; ++ ++ hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS); ++ hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN); ++ ++ val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01; ++ hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val); ++ ++ /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */ ++ hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5) ++ | HDMI_I2S_SEL_LRCK(6)); ++ hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1) ++ | HDMI_I2S_SEL_SDATA2(4)); ++ hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1) ++ | HDMI_I2S_SEL_SDATA2(2)); ++ hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0)); ++ ++ /* I2S_CON_1 & 2 */ ++ hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE ++ | HDMI_I2S_L_CH_LOW_POL); ++ hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE ++ | HDMI_I2S_SET_BIT_CH(bit_ch) ++ | HDMI_I2S_SET_SDATA_BIT(data_num) ++ | HDMI_I2S_BASIC_FORMAT); ++ ++ /* Configure register related to CUV information */ ++ hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0 ++ | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH ++ | HDMI_I2S_COPYRIGHT ++ | HDMI_I2S_LINEAR_PCM ++ | HDMI_I2S_CONSUMER_FORMAT); ++ hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER); ++ hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0)); ++ hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2 ++ | HDMI_I2S_SET_SMP_FREQ(sample_frq)); ++ hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4, ++ HDMI_I2S_ORG_SMP_FREQ_44_1 ++ | HDMI_I2S_WORD_LEN_MAX24_24BITS ++ | HDMI_I2S_WORD_LEN_MAX_24BITS); ++ ++ hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD); ++} ++ ++static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff) ++{ ++ u32 mod; ++ ++ mod = hdmi_reg_read(hdata, HDMI_MODE_SEL); ++ if (mod & HDMI_DVI_MODE_EN) ++ return; ++ ++ hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0); ++ hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ? ++ HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK); ++} ++ ++static void hdmi_conf_reset(struct hdmi_context *hdata) ++{ ++ u32 reg; ++ ++ /* disable hpd handle for drm */ ++ hdata->hpd_handle = false; ++ ++ if (hdata->is_v13) ++ reg = HDMI_V13_CORE_RSTOUT; ++ else ++ reg = HDMI_CORE_RSTOUT; ++ ++ /* resetting HDMI core */ ++ hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT); ++ mdelay(10); ++ hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT); ++ mdelay(10); ++ ++ /* enable hpd handle for drm */ ++ hdata->hpd_handle = true; ++} ++ ++static void hdmi_conf_init(struct hdmi_context *hdata) ++{ ++ /* disable hpd handle for drm */ ++ hdata->hpd_handle = false; ++ ++ /* enable HPD interrupts */ ++ hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | ++ HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); ++ mdelay(10); ++ hdmi_reg_writemask(hdata, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL | ++ HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); ++ ++ /* choose HDMI mode */ ++ hdmi_reg_writemask(hdata, HDMI_MODE_SEL, ++ HDMI_MODE_HDMI_EN, HDMI_MODE_MASK); ++ /* disable bluescreen */ ++ hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN); ++ ++ if (hdata->is_v13) { ++ /* choose bluescreen (fecal) color */ ++ hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12); ++ hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34); ++ hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56); ++ ++ /* enable AVI packet every vsync, fixes purple line problem */ ++ hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02); ++ /* force RGB, look to CEA-861-D, table 7 for more detail */ ++ hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5); ++ hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5); ++ ++ hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02); ++ hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02); ++ hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04); ++ } else { ++ /* enable AVI packet every vsync, fixes purple line problem */ ++ hdmi_reg_writeb(hdata, HDMI_AVI_CON, 0x02); ++ hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 2 << 5); ++ hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5); ++ } ++ ++ /* enable hpd handle for drm */ ++ hdata->hpd_handle = true; ++} ++ ++static void hdmi_v13_timing_apply(struct hdmi_context *hdata) ++{ ++ const struct hdmi_v13_preset_conf *conf = ++ hdmi_v13_confs[hdata->cur_conf].conf; ++ const struct hdmi_v13_core_regs *core = &conf->core; ++ const struct hdmi_v13_tg_regs *tg = &conf->tg; ++ int tries; ++ ++ /* setting core registers */ ++ hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]); ++ hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]); ++ hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]); ++ hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]); ++ hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]); ++ hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]); ++ hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]); ++ hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]); ++ hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]); ++ hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]); ++ hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]); ++ /* Timing generator registers */ ++ hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h); ++ ++ /* waiting for HDMIPHY's PLL to get to steady state */ ++ for (tries = 100; tries; --tries) { ++ u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS); ++ if (val & HDMI_PHY_STATUS_READY) ++ break; ++ mdelay(1); ++ } ++ /* steady state not achieved */ ++ if (tries == 0) { ++ DRM_ERROR("hdmiphy's pll could not reach steady state.\n"); ++ hdmi_regs_dump(hdata, "timing apply"); ++ } ++ ++ clk_disable(hdata->res.sclk_hdmi); ++ clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy); ++ clk_enable(hdata->res.sclk_hdmi); ++ ++ /* enable HDMI and timing generator */ ++ hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN); ++ if (core->int_pro_mode[0]) ++ hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN | ++ HDMI_FIELD_EN); ++ else ++ hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN); ++} ++ ++static void hdmi_v14_timing_apply(struct hdmi_context *hdata) ++{ ++ const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf; ++ const struct hdmi_core_regs *core = &conf->core; ++ const struct hdmi_tg_regs *tg = &conf->tg; ++ int tries; ++ ++ /* setting core registers */ ++ hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]); ++ hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]); ++ hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]); ++ hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]); ++ hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]); ++ hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]); ++ hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]); ++ hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]); ++ hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]); ++ hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]); ++ hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]); ++ hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]); ++ hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]); ++ hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]); ++ hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0, ++ core->v_sync_line_bef_2[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1, ++ core->v_sync_line_bef_2[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0, ++ core->v_sync_line_bef_1[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1, ++ core->v_sync_line_bef_1[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0, ++ core->v_sync_line_aft_2[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1, ++ core->v_sync_line_aft_2[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0, ++ core->v_sync_line_aft_1[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1, ++ core->v_sync_line_aft_1[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, ++ core->v_sync_line_aft_pxl_2[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1, ++ core->v_sync_line_aft_pxl_2[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, ++ core->v_sync_line_aft_pxl_1[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1, ++ core->v_sync_line_aft_pxl_1[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0, ++ core->v_sync_line_aft_3[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1, ++ core->v_sync_line_aft_3[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0, ++ core->v_sync_line_aft_4[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1, ++ core->v_sync_line_aft_4[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0, ++ core->v_sync_line_aft_5[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1, ++ core->v_sync_line_aft_5[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0, ++ core->v_sync_line_aft_6[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1, ++ core->v_sync_line_aft_6[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0, ++ core->v_sync_line_aft_pxl_3[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1, ++ core->v_sync_line_aft_pxl_3[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0, ++ core->v_sync_line_aft_pxl_4[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1, ++ core->v_sync_line_aft_pxl_4[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0, ++ core->v_sync_line_aft_pxl_5[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1, ++ core->v_sync_line_aft_pxl_5[1]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, ++ core->v_sync_line_aft_pxl_6[0]); ++ hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1, ++ core->v_sync_line_aft_pxl_6[1]); ++ hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]); ++ hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]); ++ hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]); ++ hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]); ++ hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]); ++ hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]); ++ hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]); ++ hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]); ++ hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]); ++ hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]); ++ hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]); ++ hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]); ++ ++ /* Timing generator registers */ ++ hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l); ++ hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h); ++ hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d); ++ ++ /* waiting for HDMIPHY's PLL to get to steady state */ ++ for (tries = 100; tries; --tries) { ++ u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0); ++ if (val & HDMI_PHY_STATUS_READY) ++ break; ++ mdelay(1); ++ } ++ /* steady state not achieved */ ++ if (tries == 0) { ++ DRM_ERROR("hdmiphy's pll could not reach steady state.\n"); ++ hdmi_regs_dump(hdata, "timing apply"); ++ } ++ ++ clk_disable(hdata->res.sclk_hdmi); ++ clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy); ++ clk_enable(hdata->res.sclk_hdmi); ++ ++ /* enable HDMI and timing generator */ ++ hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN); ++ if (core->int_pro_mode[0]) ++ hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN | ++ HDMI_FIELD_EN); ++ else ++ hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN); ++} ++ ++static void hdmi_timing_apply(struct hdmi_context *hdata) ++{ ++ if (hdata->is_v13) ++ hdmi_v13_timing_apply(hdata); ++ else ++ hdmi_v14_timing_apply(hdata); ++} ++ ++static void hdmiphy_conf_reset(struct hdmi_context *hdata) ++{ ++ u8 buffer[2]; ++ u32 reg; ++ ++ clk_disable(hdata->res.sclk_hdmi); ++ clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel); ++ clk_enable(hdata->res.sclk_hdmi); ++ ++ /* operation mode */ ++ buffer[0] = 0x1f; ++ buffer[1] = 0x00; ++ ++ if (hdata->hdmiphy_port) ++ i2c_master_send(hdata->hdmiphy_port, buffer, 2); ++ ++ if (hdata->is_v13) ++ reg = HDMI_V13_PHY_RSTOUT; ++ else ++ reg = HDMI_PHY_RSTOUT; ++ ++ /* reset hdmiphy */ ++ hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT); ++ mdelay(10); ++ hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT); ++ mdelay(10); ++} ++ ++static void hdmiphy_conf_apply(struct hdmi_context *hdata) ++{ ++ const u8 *hdmiphy_data; ++ u8 buffer[32]; ++ u8 operation[2]; ++ u8 read_buffer[32] = {0, }; ++ int ret; ++ int i; ++ ++ if (!hdata->hdmiphy_port) { ++ DRM_ERROR("hdmiphy is not attached\n"); ++ return; ++ } ++ ++ /* pixel clock */ ++ if (hdata->is_v13) ++ hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data; ++ else ++ hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data; ++ ++ memcpy(buffer, hdmiphy_data, 32); ++ ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32); ++ if (ret != 32) { ++ DRM_ERROR("failed to configure HDMIPHY via I2C\n"); ++ return; ++ } ++ ++ mdelay(10); ++ ++ /* operation mode */ ++ operation[0] = 0x1f; ++ operation[1] = 0x80; ++ ++ ret = i2c_master_send(hdata->hdmiphy_port, operation, 2); ++ if (ret != 2) { ++ DRM_ERROR("failed to enable hdmiphy\n"); ++ return; ++ } ++ ++ ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32); ++ if (ret < 0) { ++ DRM_ERROR("failed to read hdmiphy config\n"); ++ return; ++ } ++ ++ for (i = 0; i < ret; i++) ++ DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - " ++ "recv [0x%02x]\n", i, buffer[i], read_buffer[i]); ++} ++ ++static void hdmi_conf_apply(struct hdmi_context *hdata) ++{ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ hdmiphy_conf_reset(hdata); ++ hdmiphy_conf_apply(hdata); ++ ++ hdmi_conf_reset(hdata); ++ hdmi_conf_init(hdata); ++ hdmi_audio_init(hdata); ++ ++ /* setting core registers */ ++ hdmi_timing_apply(hdata); ++ hdmi_audio_control(hdata, true); ++ ++ hdmi_regs_dump(hdata, "start"); ++} ++ ++static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct drm_display_mode *m; ++ struct hdmi_context *hdata = ctx; ++ int index; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ drm_mode_set_crtcinfo(adjusted_mode, 0); ++ ++ if (hdata->is_v13) ++ index = hdmi_v13_conf_index(adjusted_mode); ++ else ++ index = hdmi_v14_conf_index(adjusted_mode); ++ ++ /* just return if user desired mode exists. */ ++ if (index >= 0) ++ return; ++ ++ /* ++ * otherwise, find the most suitable mode among modes and change it ++ * to adjusted_mode. ++ */ ++ list_for_each_entry(m, &connector->modes, head) { ++ if (hdata->is_v13) ++ index = hdmi_v13_conf_index(m); ++ else ++ index = hdmi_v14_conf_index(m); ++ ++ if (index >= 0) { ++ DRM_INFO("desired mode doesn't exist so\n"); ++ DRM_INFO("use the most suitable mode among modes.\n"); ++ memcpy(adjusted_mode, m, sizeof(*m)); ++ break; ++ } ++ } ++} ++ ++static void hdmi_mode_set(void *ctx, void *mode) ++{ ++ struct hdmi_context *hdata = ctx; ++ int conf_idx; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ conf_idx = hdmi_conf_index(hdata, mode); ++ if (conf_idx >= 0) ++ hdata->cur_conf = conf_idx; ++ else ++ DRM_DEBUG_KMS("not supported mode\n"); ++} ++ ++static void hdmi_get_max_resol(void *ctx, unsigned int *width, ++ unsigned int *height) ++{ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ *width = MAX_WIDTH; ++ *height = MAX_HEIGHT; ++} ++ ++static void hdmi_commit(void *ctx) ++{ ++ struct hdmi_context *hdata = ctx; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ hdmi_conf_apply(hdata); ++ ++ hdata->enabled = true; ++} ++ ++static void hdmi_disable(void *ctx) ++{ ++ struct hdmi_context *hdata = ctx; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ if (hdata->enabled) { ++ hdmi_audio_control(hdata, false); ++ hdmiphy_conf_reset(hdata); ++ hdmi_conf_reset(hdata); ++ } ++} ++ ++static struct exynos_hdmi_ops hdmi_ops = { ++ /* display */ ++ .is_connected = hdmi_is_connected, ++ .get_edid = hdmi_get_edid, ++ .check_timing = hdmi_check_timing, ++ .power_on = hdmi_display_power_on, ++ ++ /* manager */ ++ .mode_fixup = hdmi_mode_fixup, ++ .mode_set = hdmi_mode_set, ++ .get_max_resol = hdmi_get_max_resol, ++ .commit = hdmi_commit, ++ .disable = hdmi_disable, ++}; ++ ++/* ++ * Handle hotplug events outside the interrupt handler proper. ++ */ ++static void hdmi_hotplug_func(struct work_struct *work) ++{ ++ struct hdmi_context *hdata = ++ container_of(work, struct hdmi_context, hotplug_work); ++ struct exynos_drm_hdmi_context *ctx = ++ (struct exynos_drm_hdmi_context *)hdata->parent_ctx; ++ ++ drm_helper_hpd_irq_event(ctx->drm_dev); ++} ++ ++static irqreturn_t hdmi_irq_handler(int irq, void *arg) ++{ ++ struct exynos_drm_hdmi_context *ctx = arg; ++ struct hdmi_context *hdata = ctx->ctx; ++ u32 intc_flag; ++ ++ intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG); ++ /* clearing flags for HPD plug/unplug */ ++ if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) { ++ DRM_DEBUG_KMS("unplugged, handling:%d\n", hdata->hpd_handle); ++ hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, ++ HDMI_INTC_FLAG_HPD_UNPLUG); ++ } ++ if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) { ++ DRM_DEBUG_KMS("plugged, handling:%d\n", hdata->hpd_handle); ++ hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, ++ HDMI_INTC_FLAG_HPD_PLUG); ++ } ++ ++ if (ctx->drm_dev && hdata->hpd_handle) ++ queue_work(hdata->wq, &hdata->hotplug_work); ++ ++ return IRQ_HANDLED; ++} ++ ++static int __devinit hdmi_resources_init(struct hdmi_context *hdata) ++{ ++ struct device *dev = hdata->dev; ++ struct hdmi_resources *res = &hdata->res; ++ static char *supply[] = { ++ "hdmi-en", ++ "vdd", ++ "vdd_osc", ++ "vdd_pll", ++ }; ++ int i, ret; ++ ++ DRM_DEBUG_KMS("HDMI resource init\n"); ++ ++ memset(res, 0, sizeof *res); ++ ++ /* get clocks, power */ ++ res->hdmi = clk_get(dev, "hdmi"); ++ if (IS_ERR_OR_NULL(res->hdmi)) { ++ DRM_ERROR("failed to get clock 'hdmi'\n"); ++ goto fail; ++ } ++ res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); ++ if (IS_ERR_OR_NULL(res->sclk_hdmi)) { ++ DRM_ERROR("failed to get clock 'sclk_hdmi'\n"); ++ goto fail; ++ } ++ res->sclk_pixel = clk_get(dev, "sclk_pixel"); ++ if (IS_ERR_OR_NULL(res->sclk_pixel)) { ++ DRM_ERROR("failed to get clock 'sclk_pixel'\n"); ++ goto fail; ++ } ++ res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy"); ++ if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) { ++ DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n"); ++ goto fail; ++ } ++ res->hdmiphy = clk_get(dev, "hdmiphy"); ++ if (IS_ERR_OR_NULL(res->hdmiphy)) { ++ DRM_ERROR("failed to get clock 'hdmiphy'\n"); ++ goto fail; ++ } ++ ++ clk_set_parent(res->sclk_hdmi, res->sclk_pixel); ++ ++ res->regul_bulk = kzalloc(ARRAY_SIZE(supply) * ++ sizeof res->regul_bulk[0], GFP_KERNEL); ++ if (!res->regul_bulk) { ++ DRM_ERROR("failed to get memory for regulators\n"); ++ goto fail; ++ } ++ for (i = 0; i < ARRAY_SIZE(supply); ++i) { ++ res->regul_bulk[i].supply = supply[i]; ++ res->regul_bulk[i].consumer = NULL; ++ } ++ ret = regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk); ++ if (ret) { ++ DRM_ERROR("failed to get regulators\n"); ++ goto fail; ++ } ++ res->regul_count = ARRAY_SIZE(supply); ++ ++ return 0; ++fail: ++ DRM_ERROR("HDMI resource init - failed\n"); ++ return -ENODEV; ++} ++ ++static int hdmi_resources_cleanup(struct hdmi_context *hdata) ++{ ++ struct hdmi_resources *res = &hdata->res; ++ ++ regulator_bulk_free(res->regul_count, res->regul_bulk); ++ /* kfree is NULL-safe */ ++ kfree(res->regul_bulk); ++ if (!IS_ERR_OR_NULL(res->hdmiphy)) ++ clk_put(res->hdmiphy); ++ if (!IS_ERR_OR_NULL(res->sclk_hdmiphy)) ++ clk_put(res->sclk_hdmiphy); ++ if (!IS_ERR_OR_NULL(res->sclk_pixel)) ++ clk_put(res->sclk_pixel); ++ if (!IS_ERR_OR_NULL(res->sclk_hdmi)) ++ clk_put(res->sclk_hdmi); ++ if (!IS_ERR_OR_NULL(res->hdmi)) ++ clk_put(res->hdmi); ++ memset(res, 0, sizeof *res); ++ ++ return 0; ++} ++ ++static void hdmi_resource_poweron(struct hdmi_context *hdata) ++{ ++ struct hdmi_resources *res = &hdata->res; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ /* turn HDMI power on */ ++ regulator_bulk_enable(res->regul_count, res->regul_bulk); ++ /* power-on hdmi physical interface */ ++ clk_enable(res->hdmiphy); ++ /* turn clocks on */ ++ clk_enable(res->hdmi); ++ clk_enable(res->sclk_hdmi); ++ ++ hdmiphy_conf_reset(hdata); ++ hdmi_conf_reset(hdata); ++ hdmi_conf_init(hdata); ++ hdmi_audio_init(hdata); ++} ++ ++static void hdmi_resource_poweroff(struct hdmi_context *hdata) ++{ ++ struct hdmi_resources *res = &hdata->res; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ /* turn clocks off */ ++ clk_disable(res->sclk_hdmi); ++ clk_disable(res->hdmi); ++ /* power-off hdmiphy */ ++ clk_disable(res->hdmiphy); ++ /* turn HDMI power off */ ++ regulator_bulk_disable(res->regul_count, res->regul_bulk); ++} ++ ++static int hdmi_runtime_suspend(struct device *dev) ++{ ++ struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev); ++ ++ DRM_DEBUG_KMS("%s\n", __func__); ++ ++ hdmi_resource_poweroff(ctx->ctx); ++ ++ return 0; ++} ++ ++static int hdmi_runtime_resume(struct device *dev) ++{ ++ struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev); ++ ++ DRM_DEBUG_KMS("%s\n", __func__); ++ ++ hdmi_resource_poweron(ctx->ctx); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops hdmi_pm_ops = { ++ .runtime_suspend = hdmi_runtime_suspend, ++ .runtime_resume = hdmi_runtime_resume, ++}; ++ ++static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy; ++ ++void hdmi_attach_ddc_client(struct i2c_client *ddc) ++{ ++ if (ddc) ++ hdmi_ddc = ddc; ++} ++ ++void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy) ++{ ++ if (hdmiphy) ++ hdmi_hdmiphy = hdmiphy; ++} ++ ++static int __devinit hdmi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct exynos_drm_hdmi_context *drm_hdmi_ctx; ++ struct hdmi_context *hdata; ++ struct exynos_drm_hdmi_pdata *pdata; ++ struct resource *res; ++ int ret; ++ ++ DRM_DEBUG_KMS("[%d]\n", __LINE__); ++ ++ pdata = pdev->dev.platform_data; ++ if (!pdata) { ++ DRM_ERROR("no platform data specified\n"); ++ return -EINVAL; ++ } ++ ++ drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL); ++ if (!drm_hdmi_ctx) { ++ DRM_ERROR("failed to allocate common hdmi context.\n"); ++ return -ENOMEM; ++ } ++ ++ hdata = kzalloc(sizeof(struct hdmi_context), GFP_KERNEL); ++ if (!hdata) { ++ DRM_ERROR("out of memory\n"); ++ kfree(drm_hdmi_ctx); ++ return -ENOMEM; ++ } ++ ++ drm_hdmi_ctx->ctx = (void *)hdata; ++ hdata->parent_ctx = (void *)drm_hdmi_ctx; ++ ++ platform_set_drvdata(pdev, drm_hdmi_ctx); ++ ++ hdata->is_v13 = pdata->is_v13; ++ hdata->default_win = pdata->default_win; ++ hdata->default_timing = &pdata->timing; ++ hdata->default_bpp = pdata->bpp; ++ hdata->dev = dev; ++ ++ ret = hdmi_resources_init(hdata); ++ if (ret) { ++ ret = -EINVAL; ++ goto err_data; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ DRM_ERROR("failed to find registers\n"); ++ ret = -ENOENT; ++ goto err_resource; ++ } ++ ++ hdata->regs_res = request_mem_region(res->start, resource_size(res), ++ dev_name(dev)); ++ if (!hdata->regs_res) { ++ DRM_ERROR("failed to claim register region\n"); ++ ret = -ENOENT; ++ goto err_resource; ++ } ++ ++ hdata->regs = ioremap(res->start, resource_size(res)); ++ if (!hdata->regs) { ++ DRM_ERROR("failed to map registers\n"); ++ ret = -ENXIO; ++ goto err_req_region; ++ } ++ ++ /* DDC i2c driver */ ++ if (i2c_add_driver(&ddc_driver)) { ++ DRM_ERROR("failed to register ddc i2c driver\n"); ++ ret = -ENOENT; ++ goto err_iomap; ++ } ++ ++ hdata->ddc_port = hdmi_ddc; ++ ++ /* hdmiphy i2c driver */ ++ if (i2c_add_driver(&hdmiphy_driver)) { ++ DRM_ERROR("failed to register hdmiphy i2c driver\n"); ++ ret = -ENOENT; ++ goto err_ddc; ++ } ++ ++ hdata->hdmiphy_port = hdmi_hdmiphy; ++ ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (res == NULL) { ++ DRM_ERROR("get interrupt resource failed.\n"); ++ ret = -ENXIO; ++ goto err_hdmiphy; ++ } ++ ++ /* create workqueue and hotplug work */ ++ hdata->wq = alloc_workqueue("exynos-drm-hdmi", ++ WQ_UNBOUND | WQ_NON_REENTRANT, 1); ++ if (hdata->wq == NULL) { ++ DRM_ERROR("Failed to create workqueue.\n"); ++ ret = -ENOMEM; ++ goto err_hdmiphy; ++ } ++ INIT_WORK(&hdata->hotplug_work, hdmi_hotplug_func); ++ ++ /* register hpd interrupt */ ++ ret = request_irq(res->start, hdmi_irq_handler, 0, "drm_hdmi", ++ drm_hdmi_ctx); ++ if (ret) { ++ DRM_ERROR("request interrupt failed.\n"); ++ goto err_workqueue; ++ } ++ hdata->irq = res->start; ++ ++ /* register specific callbacks to common hdmi. */ ++ exynos_hdmi_ops_register(&hdmi_ops); ++ ++ hdmi_resource_poweron(hdata); ++ ++ return 0; ++ ++err_workqueue: ++ destroy_workqueue(hdata->wq); ++err_hdmiphy: ++ i2c_del_driver(&hdmiphy_driver); ++err_ddc: ++ i2c_del_driver(&ddc_driver); ++err_iomap: ++ iounmap(hdata->regs); ++err_req_region: ++ release_mem_region(hdata->regs_res->start, ++ resource_size(hdata->regs_res)); ++err_resource: ++ hdmi_resources_cleanup(hdata); ++err_data: ++ kfree(hdata); ++ kfree(drm_hdmi_ctx); ++ return ret; ++} ++ ++static int __devexit hdmi_remove(struct platform_device *pdev) ++{ ++ struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev); ++ struct hdmi_context *hdata = ctx->ctx; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ hdmi_resource_poweroff(hdata); ++ ++ disable_irq(hdata->irq); ++ free_irq(hdata->irq, hdata); ++ ++ cancel_work_sync(&hdata->hotplug_work); ++ destroy_workqueue(hdata->wq); ++ ++ hdmi_resources_cleanup(hdata); ++ ++ iounmap(hdata->regs); ++ ++ release_mem_region(hdata->regs_res->start, ++ resource_size(hdata->regs_res)); ++ ++ /* hdmiphy i2c driver */ ++ i2c_del_driver(&hdmiphy_driver); ++ /* DDC i2c driver */ ++ i2c_del_driver(&ddc_driver); ++ ++ kfree(hdata); ++ ++ return 0; ++} ++ ++struct platform_driver hdmi_driver = { ++ .probe = hdmi_probe, ++ .remove = __devexit_p(hdmi_remove), ++ .driver = { ++ .name = "exynos4-hdmi", ++ .owner = THIS_MODULE, ++ .pm = &hdmi_pm_ops, ++ }, ++}; +diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.h b/drivers/gpu/drm/exynos/exynos_hdmi.h +new file mode 100644 +index 0000000..1c3b6d8 +--- /dev/null ++++ b/drivers/gpu/drm/exynos/exynos_hdmi.h +@@ -0,0 +1,37 @@ ++/* ++ * ++ * Copyright (c) 2011 Samsung Electronics Co., Ltd. ++ * Authors: ++ * Inki Dae ++ * Seung-Woo Kim ++ * ++ * 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 (including the next ++ * paragraph) 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 ++ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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. ++ */ ++ ++#ifndef _EXYNOS_HDMI_H_ ++#define _EXYNOS_HDMI_H_ ++ ++void hdmi_attach_ddc_client(struct i2c_client *ddc); ++void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy); ++ ++extern struct i2c_driver hdmiphy_driver; ++extern struct i2c_driver ddc_driver; ++ ++#endif +diff --git a/drivers/gpu/drm/exynos/exynos_hdmiphy.c b/drivers/gpu/drm/exynos/exynos_hdmiphy.c +new file mode 100644 +index 0000000..9fe2995 +--- /dev/null ++++ b/drivers/gpu/drm/exynos/exynos_hdmiphy.c +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (C) 2011 Samsung Electronics Co.Ltd ++ * Authors: ++ * Seung-Woo Kim ++ * Inki Dae ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the 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 "drmP.h" ++ ++#include ++#include ++#include ++ ++#include "exynos_drm_drv.h" ++#include "exynos_hdmi.h" ++ ++ ++static int hdmiphy_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ hdmi_attach_hdmiphy_client(client); ++ ++ dev_info(&client->adapter->dev, "attached s5p_hdmiphy " ++ "into i2c adapter successfully\n"); ++ ++ return 0; ++} ++ ++static int hdmiphy_remove(struct i2c_client *client) ++{ ++ dev_info(&client->adapter->dev, "detached s5p_hdmiphy " ++ "from i2c adapter successfully\n"); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id hdmiphy_id[] = { ++ { "s5p_hdmiphy", 0 }, ++ { }, ++}; ++ ++struct i2c_driver hdmiphy_driver = { ++ .driver = { ++ .name = "s5p-hdmiphy", ++ .owner = THIS_MODULE, ++ }, ++ .id_table = hdmiphy_id, ++ .probe = hdmiphy_probe, ++ .remove = __devexit_p(hdmiphy_remove), ++ .command = NULL, ++}; ++EXPORT_SYMBOL(hdmiphy_driver); +diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c +new file mode 100644 +index 0000000..e15438c +--- /dev/null ++++ b/drivers/gpu/drm/exynos/exynos_mixer.c +@@ -0,0 +1,1112 @@ ++/* ++ * Copyright (C) 2011 Samsung Electronics Co.Ltd ++ * Authors: ++ * Seung-Woo Kim ++ * Inki Dae ++ * Joonyoung Shim ++ * ++ * Based on drivers/media/video/s5p-tv/mixer_reg.c ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ */ ++ ++#include "drmP.h" ++ ++#include "regs-mixer.h" ++#include "regs-vp.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "exynos_drm_drv.h" ++#include "exynos_drm_hdmi.h" ++ ++#define MIXER_WIN_NR 3 ++#define MIXER_DEFAULT_WIN 0 ++ ++#define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev)) ++ ++struct hdmi_win_data { ++ dma_addr_t dma_addr; ++ void __iomem *vaddr; ++ dma_addr_t chroma_dma_addr; ++ void __iomem *chroma_vaddr; ++ uint32_t pixel_format; ++ unsigned int bpp; ++ unsigned int crtc_x; ++ unsigned int crtc_y; ++ unsigned int crtc_width; ++ unsigned int crtc_height; ++ unsigned int fb_x; ++ unsigned int fb_y; ++ unsigned int fb_width; ++ unsigned int fb_height; ++ unsigned int mode_width; ++ unsigned int mode_height; ++ unsigned int scan_flags; ++}; ++ ++struct mixer_resources { ++ struct device *dev; ++ int irq; ++ void __iomem *mixer_regs; ++ void __iomem *vp_regs; ++ spinlock_t reg_slock; ++ struct clk *mixer; ++ struct clk *vp; ++ struct clk *sclk_mixer; ++ struct clk *sclk_hdmi; ++ struct clk *sclk_dac; ++}; ++ ++struct mixer_context { ++ unsigned int irq; ++ int pipe; ++ bool interlace; ++ ++ struct mixer_resources mixer_res; ++ struct hdmi_win_data win_data[MIXER_WIN_NR]; ++}; ++ ++static const u8 filter_y_horiz_tap8[] = { ++ 0, -1, -1, -1, -1, -1, -1, -1, ++ -1, -1, -1, -1, -1, 0, 0, 0, ++ 0, 2, 4, 5, 6, 6, 6, 6, ++ 6, 5, 5, 4, 3, 2, 1, 1, ++ 0, -6, -12, -16, -18, -20, -21, -20, ++ -20, -18, -16, -13, -10, -8, -5, -2, ++ 127, 126, 125, 121, 114, 107, 99, 89, ++ 79, 68, 57, 46, 35, 25, 16, 8, ++}; ++ ++static const u8 filter_y_vert_tap4[] = { ++ 0, -3, -6, -8, -8, -8, -8, -7, ++ -6, -5, -4, -3, -2, -1, -1, 0, ++ 127, 126, 124, 118, 111, 102, 92, 81, ++ 70, 59, 48, 37, 27, 19, 11, 5, ++ 0, 5, 11, 19, 27, 37, 48, 59, ++ 70, 81, 92, 102, 111, 118, 124, 126, ++ 0, 0, -1, -1, -2, -3, -4, -5, ++ -6, -7, -8, -8, -8, -8, -6, -3, ++}; ++ ++static const u8 filter_cr_horiz_tap4[] = { ++ 0, -3, -6, -8, -8, -8, -8, -7, ++ -6, -5, -4, -3, -2, -1, -1, 0, ++ 127, 126, 124, 118, 111, 102, 92, 81, ++ 70, 59, 48, 37, 27, 19, 11, 5, ++}; ++ ++static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id) ++{ ++ return readl(res->vp_regs + reg_id); ++} ++ ++static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id, ++ u32 val) ++{ ++ writel(val, res->vp_regs + reg_id); ++} ++ ++static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id, ++ u32 val, u32 mask) ++{ ++ u32 old = vp_reg_read(res, reg_id); ++ ++ val = (val & mask) | (old & ~mask); ++ writel(val, res->vp_regs + reg_id); ++} ++ ++static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id) ++{ ++ return readl(res->mixer_regs + reg_id); ++} ++ ++static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id, ++ u32 val) ++{ ++ writel(val, res->mixer_regs + reg_id); ++} ++ ++static inline void mixer_reg_writemask(struct mixer_resources *res, ++ u32 reg_id, u32 val, u32 mask) ++{ ++ u32 old = mixer_reg_read(res, reg_id); ++ ++ val = (val & mask) | (old & ~mask); ++ writel(val, res->mixer_regs + reg_id); ++} ++ ++static void mixer_regs_dump(struct mixer_context *ctx) ++{ ++#define DUMPREG(reg_id) \ ++do { \ ++ DRM_DEBUG_KMS(#reg_id " = %08x\n", \ ++ (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \ ++} while (0) ++ ++ DUMPREG(MXR_STATUS); ++ DUMPREG(MXR_CFG); ++ DUMPREG(MXR_INT_EN); ++ DUMPREG(MXR_INT_STATUS); ++ ++ DUMPREG(MXR_LAYER_CFG); ++ DUMPREG(MXR_VIDEO_CFG); ++ ++ DUMPREG(MXR_GRAPHIC0_CFG); ++ DUMPREG(MXR_GRAPHIC0_BASE); ++ DUMPREG(MXR_GRAPHIC0_SPAN); ++ DUMPREG(MXR_GRAPHIC0_WH); ++ DUMPREG(MXR_GRAPHIC0_SXY); ++ DUMPREG(MXR_GRAPHIC0_DXY); ++ ++ DUMPREG(MXR_GRAPHIC1_CFG); ++ DUMPREG(MXR_GRAPHIC1_BASE); ++ DUMPREG(MXR_GRAPHIC1_SPAN); ++ DUMPREG(MXR_GRAPHIC1_WH); ++ DUMPREG(MXR_GRAPHIC1_SXY); ++ DUMPREG(MXR_GRAPHIC1_DXY); ++#undef DUMPREG ++} ++ ++static void vp_regs_dump(struct mixer_context *ctx) ++{ ++#define DUMPREG(reg_id) \ ++do { \ ++ DRM_DEBUG_KMS(#reg_id " = %08x\n", \ ++ (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \ ++} while (0) ++ ++ DUMPREG(VP_ENABLE); ++ DUMPREG(VP_SRESET); ++ DUMPREG(VP_SHADOW_UPDATE); ++ DUMPREG(VP_FIELD_ID); ++ DUMPREG(VP_MODE); ++ DUMPREG(VP_IMG_SIZE_Y); ++ DUMPREG(VP_IMG_SIZE_C); ++ DUMPREG(VP_PER_RATE_CTRL); ++ DUMPREG(VP_TOP_Y_PTR); ++ DUMPREG(VP_BOT_Y_PTR); ++ DUMPREG(VP_TOP_C_PTR); ++ DUMPREG(VP_BOT_C_PTR); ++ DUMPREG(VP_ENDIAN_MODE); ++ DUMPREG(VP_SRC_H_POSITION); ++ DUMPREG(VP_SRC_V_POSITION); ++ DUMPREG(VP_SRC_WIDTH); ++ DUMPREG(VP_SRC_HEIGHT); ++ DUMPREG(VP_DST_H_POSITION); ++ DUMPREG(VP_DST_V_POSITION); ++ DUMPREG(VP_DST_WIDTH); ++ DUMPREG(VP_DST_HEIGHT); ++ DUMPREG(VP_H_RATIO); ++ DUMPREG(VP_V_RATIO); ++ ++#undef DUMPREG ++} ++ ++static inline void vp_filter_set(struct mixer_resources *res, ++ int reg_id, const u8 *data, unsigned int size) ++{ ++ /* assure 4-byte align */ ++ BUG_ON(size & 3); ++ for (; size; size -= 4, reg_id += 4, data += 4) { ++ u32 val = (data[0] << 24) | (data[1] << 16) | ++ (data[2] << 8) | data[3]; ++ vp_reg_write(res, reg_id, val); ++ } ++} ++ ++static void vp_default_filter(struct mixer_resources *res) ++{ ++ vp_filter_set(res, VP_POLY8_Y0_LL, ++ filter_y_horiz_tap8, sizeof filter_y_horiz_tap8); ++ vp_filter_set(res, VP_POLY4_Y0_LL, ++ filter_y_vert_tap4, sizeof filter_y_vert_tap4); ++ vp_filter_set(res, VP_POLY4_C0_LL, ++ filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4); ++} ++ ++static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) ++{ ++ struct mixer_resources *res = &ctx->mixer_res; ++ ++ /* block update on vsync */ ++ mixer_reg_writemask(res, MXR_STATUS, enable ? ++ MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE); ++ ++ vp_reg_write(res, VP_SHADOW_UPDATE, enable ? ++ VP_SHADOW_UPDATE_ENABLE : 0); ++} ++ ++static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height) ++{ ++ struct mixer_resources *res = &ctx->mixer_res; ++ u32 val; ++ ++ /* choosing between interlace and progressive mode */ ++ val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE : ++ MXR_CFG_SCAN_PROGRASSIVE); ++ ++ /* choosing between porper HD and SD mode */ ++ if (height == 480) ++ val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD; ++ else if (height == 576) ++ val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD; ++ else if (height == 720) ++ val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD; ++ else if (height == 1080) ++ val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD; ++ else ++ val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD; ++ ++ mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK); ++} ++ ++static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) ++{ ++ struct mixer_resources *res = &ctx->mixer_res; ++ u32 val; ++ ++ if (height == 480) { ++ val = MXR_CFG_RGB601_0_255; ++ } else if (height == 576) { ++ val = MXR_CFG_RGB601_0_255; ++ } else if (height == 720) { ++ val = MXR_CFG_RGB709_16_235; ++ mixer_reg_write(res, MXR_CM_COEFF_Y, ++ (1 << 30) | (94 << 20) | (314 << 10) | ++ (32 << 0)); ++ mixer_reg_write(res, MXR_CM_COEFF_CB, ++ (972 << 20) | (851 << 10) | (225 << 0)); ++ mixer_reg_write(res, MXR_CM_COEFF_CR, ++ (225 << 20) | (820 << 10) | (1004 << 0)); ++ } else if (height == 1080) { ++ val = MXR_CFG_RGB709_16_235; ++ mixer_reg_write(res, MXR_CM_COEFF_Y, ++ (1 << 30) | (94 << 20) | (314 << 10) | ++ (32 << 0)); ++ mixer_reg_write(res, MXR_CM_COEFF_CB, ++ (972 << 20) | (851 << 10) | (225 << 0)); ++ mixer_reg_write(res, MXR_CM_COEFF_CR, ++ (225 << 20) | (820 << 10) | (1004 << 0)); ++ } else { ++ val = MXR_CFG_RGB709_16_235; ++ mixer_reg_write(res, MXR_CM_COEFF_Y, ++ (1 << 30) | (94 << 20) | (314 << 10) | ++ (32 << 0)); ++ mixer_reg_write(res, MXR_CM_COEFF_CB, ++ (972 << 20) | (851 << 10) | (225 << 0)); ++ mixer_reg_write(res, MXR_CM_COEFF_CR, ++ (225 << 20) | (820 << 10) | (1004 << 0)); ++ } ++ ++ mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); ++} ++ ++static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable) ++{ ++ struct mixer_resources *res = &ctx->mixer_res; ++ u32 val = enable ? ~0 : 0; ++ ++ switch (win) { ++ case 0: ++ mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); ++ break; ++ case 1: ++ mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); ++ break; ++ case 2: ++ vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); ++ mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE); ++ break; ++ } ++} ++ ++static void mixer_run(struct mixer_context *ctx) ++{ ++ struct mixer_resources *res = &ctx->mixer_res; ++ ++ mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN); ++ ++ mixer_regs_dump(ctx); ++} ++ ++static void vp_video_buffer(struct mixer_context *ctx, int win) ++{ ++ struct mixer_resources *res = &ctx->mixer_res; ++ unsigned long flags; ++ struct hdmi_win_data *win_data; ++ unsigned int full_width, full_height, width, height; ++ unsigned int x_ratio, y_ratio; ++ unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; ++ unsigned int mode_width, mode_height; ++ unsigned int buf_num; ++ dma_addr_t luma_addr[2], chroma_addr[2]; ++ bool tiled_mode = false; ++ bool crcb_mode = false; ++ u32 val; ++ ++ win_data = &ctx->win_data[win]; ++ ++ switch (win_data->pixel_format) { ++ case DRM_FORMAT_NV12MT: ++ tiled_mode = true; ++ case DRM_FORMAT_NV12M: ++ crcb_mode = false; ++ buf_num = 2; ++ break; ++ /* TODO: single buffer format NV12, NV21 */ ++ default: ++ /* ignore pixel format at disable time */ ++ if (!win_data->dma_addr) ++ break; ++ ++ DRM_ERROR("pixel format for vp is wrong [%d].\n", ++ win_data->pixel_format); ++ return; ++ } ++ ++ full_width = win_data->fb_width; ++ full_height = win_data->fb_height; ++ width = win_data->crtc_width; ++ height = win_data->crtc_height; ++ mode_width = win_data->mode_width; ++ mode_height = win_data->mode_height; ++ ++ /* scaling feature: (src << 16) / dst */ ++ x_ratio = (width << 16) / width; ++ y_ratio = (height << 16) / height; ++ ++ src_x_offset = win_data->fb_x; ++ src_y_offset = win_data->fb_y; ++ dst_x_offset = win_data->crtc_x; ++ dst_y_offset = win_data->crtc_y; ++ ++ if (buf_num == 2) { ++ luma_addr[0] = win_data->dma_addr; ++ chroma_addr[0] = win_data->chroma_dma_addr; ++ } else { ++ luma_addr[0] = win_data->dma_addr; ++ chroma_addr[0] = win_data->dma_addr ++ + (full_width * full_height); ++ } ++ ++ if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) { ++ ctx->interlace = true; ++ if (tiled_mode) { ++ luma_addr[1] = luma_addr[0] + 0x40; ++ chroma_addr[1] = chroma_addr[0] + 0x40; ++ } else { ++ luma_addr[1] = luma_addr[0] + full_width; ++ chroma_addr[1] = chroma_addr[0] + full_width; ++ } ++ } else { ++ ctx->interlace = false; ++ luma_addr[1] = 0; ++ chroma_addr[1] = 0; ++ } ++ ++ spin_lock_irqsave(&res->reg_slock, flags); ++ mixer_vsync_set_update(ctx, false); ++ ++ /* interlace or progressive scan mode */ ++ val = (ctx->interlace ? ~0 : 0); ++ vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP); ++ ++ /* setup format */ ++ val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12); ++ val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR); ++ vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK); ++ ++ /* setting size of input image */ ++ vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(full_width) | ++ VP_IMG_VSIZE(full_height)); ++ /* chroma height has to reduced by 2 to avoid chroma distorions */ ++ vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(full_width) | ++ VP_IMG_VSIZE(full_height / 2)); ++ ++ vp_reg_write(res, VP_SRC_WIDTH, width); ++ vp_reg_write(res, VP_SRC_HEIGHT, height); ++ vp_reg_write(res, VP_SRC_H_POSITION, ++ VP_SRC_H_POSITION_VAL(src_x_offset)); ++ vp_reg_write(res, VP_SRC_V_POSITION, src_y_offset); ++ ++ vp_reg_write(res, VP_DST_WIDTH, width); ++ vp_reg_write(res, VP_DST_H_POSITION, dst_x_offset); ++ if (ctx->interlace) { ++ vp_reg_write(res, VP_DST_HEIGHT, height / 2); ++ vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset / 2); ++ } else { ++ vp_reg_write(res, VP_DST_HEIGHT, height); ++ vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset); ++ } ++ ++ vp_reg_write(res, VP_H_RATIO, x_ratio); ++ vp_reg_write(res, VP_V_RATIO, y_ratio); ++ ++ vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE); ++ ++ /* set buffer address to vp */ ++ vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]); ++ vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]); ++ vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]); ++ vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]); ++ ++ mixer_cfg_scan(ctx, mode_height); ++ mixer_cfg_rgb_fmt(ctx, mode_height); ++ mixer_cfg_layer(ctx, win, true); ++ mixer_run(ctx); ++ ++ mixer_vsync_set_update(ctx, true); ++ spin_unlock_irqrestore(&res->reg_slock, flags); ++ ++ vp_regs_dump(ctx); ++} ++ ++static void mixer_graph_buffer(struct mixer_context *ctx, int win) ++{ ++ struct mixer_resources *res = &ctx->mixer_res; ++ unsigned long flags; ++ struct hdmi_win_data *win_data; ++ unsigned int full_width, width, height; ++ unsigned int x_ratio, y_ratio; ++ unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; ++ unsigned int mode_width, mode_height; ++ dma_addr_t dma_addr; ++ unsigned int fmt; ++ u32 val; ++ ++ win_data = &ctx->win_data[win]; ++ ++ #define RGB565 4 ++ #define ARGB1555 5 ++ #define ARGB4444 6 ++ #define ARGB8888 7 ++ ++ switch (win_data->bpp) { ++ case 16: ++ fmt = ARGB4444; ++ break; ++ case 32: ++ fmt = ARGB8888; ++ break; ++ default: ++ fmt = ARGB8888; ++ } ++ ++ dma_addr = win_data->dma_addr; ++ full_width = win_data->fb_width; ++ width = win_data->crtc_width; ++ height = win_data->crtc_height; ++ mode_width = win_data->mode_width; ++ mode_height = win_data->mode_height; ++ ++ /* 2x scaling feature */ ++ x_ratio = 0; ++ y_ratio = 0; ++ ++ src_x_offset = win_data->fb_x; ++ src_y_offset = win_data->fb_y; ++ dst_x_offset = win_data->crtc_x; ++ dst_y_offset = win_data->crtc_y; ++ ++ /* converting dma address base and source offset */ ++ dma_addr = dma_addr ++ + (src_x_offset * win_data->bpp >> 3) ++ + (src_y_offset * full_width * win_data->bpp >> 3); ++ src_x_offset = 0; ++ src_y_offset = 0; ++ ++ if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) ++ ctx->interlace = true; ++ else ++ ctx->interlace = false; ++ ++ spin_lock_irqsave(&res->reg_slock, flags); ++ mixer_vsync_set_update(ctx, false); ++ ++ /* setup format */ ++ mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win), ++ MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK); ++ ++ /* setup geometry */ ++ mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), full_width); ++ ++ val = MXR_GRP_WH_WIDTH(width); ++ val |= MXR_GRP_WH_HEIGHT(height); ++ val |= MXR_GRP_WH_H_SCALE(x_ratio); ++ val |= MXR_GRP_WH_V_SCALE(y_ratio); ++ mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); ++ ++ /* setup offsets in source image */ ++ val = MXR_GRP_SXY_SX(src_x_offset); ++ val |= MXR_GRP_SXY_SY(src_y_offset); ++ mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val); ++ ++ /* setup offsets in display image */ ++ val = MXR_GRP_DXY_DX(dst_x_offset); ++ val |= MXR_GRP_DXY_DY(dst_y_offset); ++ mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val); ++ ++ /* set buffer address to mixer */ ++ mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr); ++ ++ mixer_cfg_scan(ctx, mode_height); ++ mixer_cfg_rgb_fmt(ctx, mode_height); ++ mixer_cfg_layer(ctx, win, true); ++ mixer_run(ctx); ++ ++ mixer_vsync_set_update(ctx, true); ++ spin_unlock_irqrestore(&res->reg_slock, flags); ++} ++ ++static void vp_win_reset(struct mixer_context *ctx) ++{ ++ struct mixer_resources *res = &ctx->mixer_res; ++ int tries = 100; ++ ++ vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING); ++ for (tries = 100; tries; --tries) { ++ /* waiting until VP_SRESET_PROCESSING is 0 */ ++ if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING) ++ break; ++ mdelay(10); ++ } ++ WARN(tries == 0, "failed to reset Video Processor\n"); ++} ++ ++static int mixer_enable_vblank(void *ctx, int pipe) ++{ ++ struct mixer_context *mixer_ctx = ctx; ++ struct mixer_resources *res = &mixer_ctx->mixer_res; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ mixer_ctx->pipe = pipe; ++ ++ /* enable vsync interrupt */ ++ mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC, ++ MXR_INT_EN_VSYNC); ++ ++ return 0; ++} ++ ++static void mixer_disable_vblank(void *ctx) ++{ ++ struct mixer_context *mixer_ctx = ctx; ++ struct mixer_resources *res = &mixer_ctx->mixer_res; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ /* disable vsync interrupt */ ++ mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); ++} ++ ++static void mixer_win_mode_set(void *ctx, ++ struct exynos_drm_overlay *overlay) ++{ ++ struct mixer_context *mixer_ctx = ctx; ++ struct hdmi_win_data *win_data; ++ int win; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ if (!overlay) { ++ DRM_ERROR("overlay is NULL\n"); ++ return; ++ } ++ ++ DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n", ++ overlay->fb_width, overlay->fb_height, ++ overlay->fb_x, overlay->fb_y, ++ overlay->crtc_width, overlay->crtc_height, ++ overlay->crtc_x, overlay->crtc_y); ++ ++ win = overlay->zpos; ++ if (win == DEFAULT_ZPOS) ++ win = MIXER_DEFAULT_WIN; ++ ++ if (win < 0 || win > MIXER_WIN_NR) { ++ DRM_ERROR("overlay plane[%d] is wrong\n", win); ++ return; ++ } ++ ++ win_data = &mixer_ctx->win_data[win]; ++ ++ win_data->dma_addr = overlay->dma_addr[0]; ++ win_data->vaddr = overlay->vaddr[0]; ++ win_data->chroma_dma_addr = overlay->dma_addr[1]; ++ win_data->chroma_vaddr = overlay->vaddr[1]; ++ win_data->pixel_format = overlay->pixel_format; ++ win_data->bpp = overlay->bpp; ++ ++ win_data->crtc_x = overlay->crtc_x; ++ win_data->crtc_y = overlay->crtc_y; ++ win_data->crtc_width = overlay->crtc_width; ++ win_data->crtc_height = overlay->crtc_height; ++ ++ win_data->fb_x = overlay->fb_x; ++ win_data->fb_y = overlay->fb_y; ++ win_data->fb_width = overlay->fb_width; ++ win_data->fb_height = overlay->fb_height; ++ ++ win_data->mode_width = overlay->mode_width; ++ win_data->mode_height = overlay->mode_height; ++ ++ win_data->scan_flags = overlay->scan_flag; ++} ++ ++static void mixer_win_commit(void *ctx, int zpos) ++{ ++ struct mixer_context *mixer_ctx = ctx; ++ int win = zpos; ++ ++ DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); ++ ++ if (win == DEFAULT_ZPOS) ++ win = MIXER_DEFAULT_WIN; ++ ++ if (win < 0 || win > MIXER_WIN_NR) { ++ DRM_ERROR("overlay plane[%d] is wrong\n", win); ++ return; ++ } ++ ++ if (win > 1) ++ vp_video_buffer(mixer_ctx, win); ++ else ++ mixer_graph_buffer(mixer_ctx, win); ++} ++ ++static void mixer_win_disable(void *ctx, int zpos) ++{ ++ struct mixer_context *mixer_ctx = ctx; ++ struct mixer_resources *res = &mixer_ctx->mixer_res; ++ unsigned long flags; ++ int win = zpos; ++ ++ DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); ++ ++ if (win == DEFAULT_ZPOS) ++ win = MIXER_DEFAULT_WIN; ++ ++ if (win < 0 || win > MIXER_WIN_NR) { ++ DRM_ERROR("overlay plane[%d] is wrong\n", win); ++ return; ++ } ++ ++ spin_lock_irqsave(&res->reg_slock, flags); ++ mixer_vsync_set_update(mixer_ctx, false); ++ ++ mixer_cfg_layer(mixer_ctx, win, false); ++ ++ mixer_vsync_set_update(mixer_ctx, true); ++ spin_unlock_irqrestore(&res->reg_slock, flags); ++} ++ ++static struct exynos_mixer_ops mixer_ops = { ++ /* manager */ ++ .enable_vblank = mixer_enable_vblank, ++ .disable_vblank = mixer_disable_vblank, ++ ++ /* overlay */ ++ .win_mode_set = mixer_win_mode_set, ++ .win_commit = mixer_win_commit, ++ .win_disable = mixer_win_disable, ++}; ++ ++/* for pageflip event */ ++static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc) ++{ ++ struct exynos_drm_private *dev_priv = drm_dev->dev_private; ++ struct drm_pending_vblank_event *e, *t; ++ struct timeval now; ++ unsigned long flags; ++ bool is_checked = false; ++ ++ spin_lock_irqsave(&drm_dev->event_lock, flags); ++ ++ list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list, ++ base.link) { ++ /* if event's pipe isn't same as crtc then ignore it. */ ++ if (crtc != e->pipe) ++ continue; ++ ++ is_checked = true; ++ do_gettimeofday(&now); ++ e->event.sequence = 0; ++ e->event.tv_sec = now.tv_sec; ++ e->event.tv_usec = now.tv_usec; ++ ++ list_move_tail(&e->base.link, &e->base.file_priv->event_list); ++ wake_up_interruptible(&e->base.file_priv->event_wait); ++ } ++ ++ if (is_checked) ++ /* ++ * call drm_vblank_put only in case that drm_vblank_get was ++ * called. ++ */ ++ if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0) ++ drm_vblank_put(drm_dev, crtc); ++ ++ spin_unlock_irqrestore(&drm_dev->event_lock, flags); ++} ++ ++static irqreturn_t mixer_irq_handler(int irq, void *arg) ++{ ++ struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg; ++ struct mixer_context *ctx = drm_hdmi_ctx->ctx; ++ struct mixer_resources *res = &ctx->mixer_res; ++ u32 val, val_base; ++ ++ spin_lock(&res->reg_slock); ++ ++ /* read interrupt status for handling and clearing flags for VSYNC */ ++ val = mixer_reg_read(res, MXR_INT_STATUS); ++ ++ /* handling VSYNC */ ++ if (val & MXR_INT_STATUS_VSYNC) { ++ /* interlace scan need to check shadow register */ ++ if (ctx->interlace) { ++ val_base = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0)); ++ if (ctx->win_data[0].dma_addr != val_base) ++ goto out; ++ ++ val_base = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1)); ++ if (ctx->win_data[1].dma_addr != val_base) ++ goto out; ++ } ++ ++ drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe); ++ mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe); ++ } ++ ++out: ++ /* clear interrupts */ ++ if (~val & MXR_INT_EN_VSYNC) { ++ /* vsync interrupt use different bit for read and clear */ ++ val &= ~MXR_INT_EN_VSYNC; ++ val |= MXR_INT_CLEAR_VSYNC; ++ } ++ mixer_reg_write(res, MXR_INT_STATUS, val); ++ ++ spin_unlock(&res->reg_slock); ++ ++ return IRQ_HANDLED; ++} ++ ++static void mixer_win_reset(struct mixer_context *ctx) ++{ ++ struct mixer_resources *res = &ctx->mixer_res; ++ unsigned long flags; ++ u32 val; /* value stored to register */ ++ ++ spin_lock_irqsave(&res->reg_slock, flags); ++ mixer_vsync_set_update(ctx, false); ++ ++ mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK); ++ ++ /* set output in RGB888 mode */ ++ mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK); ++ ++ /* 16 beat burst in DMA */ ++ mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST, ++ MXR_STATUS_BURST_MASK); ++ ++ /* setting default layer priority: layer1 > layer0 > video ++ * because typical usage scenario would be ++ * layer1 - OSD ++ * layer0 - framebuffer ++ * video - video overlay ++ */ ++ val = MXR_LAYER_CFG_GRP1_VAL(3); ++ val |= MXR_LAYER_CFG_GRP0_VAL(2); ++ val |= MXR_LAYER_CFG_VP_VAL(1); ++ mixer_reg_write(res, MXR_LAYER_CFG, val); ++ ++ /* setting background color */ ++ mixer_reg_write(res, MXR_BG_COLOR0, 0x008080); ++ mixer_reg_write(res, MXR_BG_COLOR1, 0x008080); ++ mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); ++ ++ /* setting graphical layers */ ++ ++ val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */ ++ val |= MXR_GRP_CFG_WIN_BLEND_EN; ++ val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */ ++ ++ /* the same configuration for both layers */ ++ mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val); ++ ++ val |= MXR_GRP_CFG_BLEND_PRE_MUL; ++ val |= MXR_GRP_CFG_PIXEL_BLEND_EN; ++ mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val); ++ ++ /* configuration of Video Processor Registers */ ++ vp_win_reset(ctx); ++ vp_default_filter(res); ++ ++ /* disable all layers */ ++ mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE); ++ mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE); ++ mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE); ++ ++ mixer_vsync_set_update(ctx, true); ++ spin_unlock_irqrestore(&res->reg_slock, flags); ++} ++ ++static void mixer_resource_poweron(struct mixer_context *ctx) ++{ ++ struct mixer_resources *res = &ctx->mixer_res; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ clk_enable(res->mixer); ++ clk_enable(res->vp); ++ clk_enable(res->sclk_mixer); ++ ++ mixer_win_reset(ctx); ++} ++ ++static void mixer_resource_poweroff(struct mixer_context *ctx) ++{ ++ struct mixer_resources *res = &ctx->mixer_res; ++ ++ DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); ++ ++ clk_disable(res->mixer); ++ clk_disable(res->vp); ++ clk_disable(res->sclk_mixer); ++} ++ ++static int mixer_runtime_resume(struct device *dev) ++{ ++ struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev); ++ ++ DRM_DEBUG_KMS("resume - start\n"); ++ ++ mixer_resource_poweron(ctx->ctx); ++ ++ return 0; ++} ++ ++static int mixer_runtime_suspend(struct device *dev) ++{ ++ struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev); ++ ++ DRM_DEBUG_KMS("suspend - start\n"); ++ ++ mixer_resource_poweroff(ctx->ctx); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops mixer_pm_ops = { ++ .runtime_suspend = mixer_runtime_suspend, ++ .runtime_resume = mixer_runtime_resume, ++}; ++ ++static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx, ++ struct platform_device *pdev) ++{ ++ struct mixer_context *mixer_ctx = ctx->ctx; ++ struct device *dev = &pdev->dev; ++ struct mixer_resources *mixer_res = &mixer_ctx->mixer_res; ++ struct resource *res; ++ int ret; ++ ++ mixer_res->dev = dev; ++ spin_lock_init(&mixer_res->reg_slock); ++ ++ mixer_res->mixer = clk_get(dev, "mixer"); ++ if (IS_ERR_OR_NULL(mixer_res->mixer)) { ++ dev_err(dev, "failed to get clock 'mixer'\n"); ++ ret = -ENODEV; ++ goto fail; ++ } ++ mixer_res->vp = clk_get(dev, "vp"); ++ if (IS_ERR_OR_NULL(mixer_res->vp)) { ++ dev_err(dev, "failed to get clock 'vp'\n"); ++ ret = -ENODEV; ++ goto fail; ++ } ++ mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer"); ++ if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) { ++ dev_err(dev, "failed to get clock 'sclk_mixer'\n"); ++ ret = -ENODEV; ++ goto fail; ++ } ++ mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); ++ if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) { ++ dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); ++ ret = -ENODEV; ++ goto fail; ++ } ++ mixer_res->sclk_dac = clk_get(dev, "sclk_dac"); ++ if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) { ++ dev_err(dev, "failed to get clock 'sclk_dac'\n"); ++ ret = -ENODEV; ++ goto fail; ++ } ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr"); ++ if (res == NULL) { ++ dev_err(dev, "get memory resource failed.\n"); ++ ret = -ENXIO; ++ goto fail; ++ } ++ ++ clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi); ++ ++ mixer_res->mixer_regs = ioremap(res->start, resource_size(res)); ++ if (mixer_res->mixer_regs == NULL) { ++ dev_err(dev, "register mapping failed.\n"); ++ ret = -ENXIO; ++ goto fail; ++ } ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp"); ++ if (res == NULL) { ++ dev_err(dev, "get memory resource failed.\n"); ++ ret = -ENXIO; ++ goto fail_mixer_regs; ++ } ++ ++ mixer_res->vp_regs = ioremap(res->start, resource_size(res)); ++ if (mixer_res->vp_regs == NULL) { ++ dev_err(dev, "register mapping failed.\n"); ++ ret = -ENXIO; ++ goto fail_mixer_regs; ++ } ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq"); ++ if (res == NULL) { ++ dev_err(dev, "get interrupt resource failed.\n"); ++ ret = -ENXIO; ++ goto fail_vp_regs; ++ } ++ ++ ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx); ++ if (ret) { ++ dev_err(dev, "request interrupt failed.\n"); ++ goto fail_vp_regs; ++ } ++ mixer_res->irq = res->start; ++ ++ return 0; ++ ++fail_vp_regs: ++ iounmap(mixer_res->vp_regs); ++ ++fail_mixer_regs: ++ iounmap(mixer_res->mixer_regs); ++ ++fail: ++ if (!IS_ERR_OR_NULL(mixer_res->sclk_dac)) ++ clk_put(mixer_res->sclk_dac); ++ if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) ++ clk_put(mixer_res->sclk_hdmi); ++ if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer)) ++ clk_put(mixer_res->sclk_mixer); ++ if (!IS_ERR_OR_NULL(mixer_res->vp)) ++ clk_put(mixer_res->vp); ++ if (!IS_ERR_OR_NULL(mixer_res->mixer)) ++ clk_put(mixer_res->mixer); ++ mixer_res->dev = NULL; ++ return ret; ++} ++ ++static void mixer_resources_cleanup(struct mixer_context *ctx) ++{ ++ struct mixer_resources *res = &ctx->mixer_res; ++ ++ disable_irq(res->irq); ++ free_irq(res->irq, ctx); ++ ++ iounmap(res->vp_regs); ++ iounmap(res->mixer_regs); ++} ++ ++static int __devinit mixer_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct exynos_drm_hdmi_context *drm_hdmi_ctx; ++ struct mixer_context *ctx; ++ int ret; ++ ++ dev_info(dev, "probe start\n"); ++ ++ drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL); ++ if (!drm_hdmi_ctx) { ++ DRM_ERROR("failed to allocate common hdmi context.\n"); ++ return -ENOMEM; ++ } ++ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) { ++ DRM_ERROR("failed to alloc mixer context.\n"); ++ kfree(drm_hdmi_ctx); ++ return -ENOMEM; ++ } ++ ++ drm_hdmi_ctx->ctx = (void *)ctx; ++ ++ platform_set_drvdata(pdev, drm_hdmi_ctx); ++ ++ /* acquire resources: regs, irqs, clocks */ ++ ret = mixer_resources_init(drm_hdmi_ctx, pdev); ++ if (ret) ++ goto fail; ++ ++ /* register specific callback point to common hdmi. */ ++ exynos_mixer_ops_register(&mixer_ops); ++ ++ mixer_resource_poweron(ctx); ++ ++ return 0; ++ ++ ++fail: ++ dev_info(dev, "probe failed\n"); ++ return ret; ++} ++ ++static int mixer_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct exynos_drm_hdmi_context *drm_hdmi_ctx = ++ platform_get_drvdata(pdev); ++ struct mixer_context *ctx = drm_hdmi_ctx->ctx; ++ ++ dev_info(dev, "remove successful\n"); ++ ++ mixer_resource_poweroff(ctx); ++ mixer_resources_cleanup(ctx); ++ ++ return 0; ++} ++ ++struct platform_driver mixer_driver = { ++ .driver = { ++ .name = "s5p-mixer", ++ .owner = THIS_MODULE, ++ .pm = &mixer_pm_ops, ++ }, ++ .probe = mixer_probe, ++ .remove = __devexit_p(mixer_remove), ++}; +diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h +new file mode 100644 +index 0000000..3c04bea +--- /dev/null ++++ b/drivers/gpu/drm/exynos/regs-hdmi.h +@@ -0,0 +1,561 @@ ++/* ++ * ++ * Cloned from drivers/media/video/s5p-tv/regs-hdmi.h ++ * ++ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. ++ * http://www.samsung.com/ ++ * ++ * HDMI register header file for Samsung TVOUT 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. ++*/ ++ ++#ifndef SAMSUNG_REGS_HDMI_H ++#define SAMSUNG_REGS_HDMI_H ++ ++/* ++ * Register part ++*/ ++ ++/* HDMI Version 1.3 & Common */ ++#define HDMI_CTRL_BASE(x) ((x) + 0x00000000) ++#define HDMI_CORE_BASE(x) ((x) + 0x00010000) ++#define HDMI_I2S_BASE(x) ((x) + 0x00040000) ++#define HDMI_TG_BASE(x) ((x) + 0x00050000) ++ ++/* Control registers */ ++#define HDMI_INTC_CON HDMI_CTRL_BASE(0x0000) ++#define HDMI_INTC_FLAG HDMI_CTRL_BASE(0x0004) ++#define HDMI_HPD_STATUS HDMI_CTRL_BASE(0x000C) ++#define HDMI_V13_PHY_RSTOUT HDMI_CTRL_BASE(0x0014) ++#define HDMI_V13_PHY_VPLL HDMI_CTRL_BASE(0x0018) ++#define HDMI_V13_PHY_CMU HDMI_CTRL_BASE(0x001C) ++#define HDMI_V13_CORE_RSTOUT HDMI_CTRL_BASE(0x0020) ++ ++/* Core registers */ ++#define HDMI_CON_0 HDMI_CORE_BASE(0x0000) ++#define HDMI_CON_1 HDMI_CORE_BASE(0x0004) ++#define HDMI_CON_2 HDMI_CORE_BASE(0x0008) ++#define HDMI_SYS_STATUS HDMI_CORE_BASE(0x0010) ++#define HDMI_V13_PHY_STATUS HDMI_CORE_BASE(0x0014) ++#define HDMI_STATUS_EN HDMI_CORE_BASE(0x0020) ++#define HDMI_HPD HDMI_CORE_BASE(0x0030) ++#define HDMI_MODE_SEL HDMI_CORE_BASE(0x0040) ++#define HDMI_ENC_EN HDMI_CORE_BASE(0x0044) ++#define HDMI_V13_BLUE_SCREEN_0 HDMI_CORE_BASE(0x0050) ++#define HDMI_V13_BLUE_SCREEN_1 HDMI_CORE_BASE(0x0054) ++#define HDMI_V13_BLUE_SCREEN_2 HDMI_CORE_BASE(0x0058) ++#define HDMI_H_BLANK_0 HDMI_CORE_BASE(0x00A0) ++#define HDMI_H_BLANK_1 HDMI_CORE_BASE(0x00A4) ++#define HDMI_V13_V_BLANK_0 HDMI_CORE_BASE(0x00B0) ++#define HDMI_V13_V_BLANK_1 HDMI_CORE_BASE(0x00B4) ++#define HDMI_V13_V_BLANK_2 HDMI_CORE_BASE(0x00B8) ++#define HDMI_V13_H_V_LINE_0 HDMI_CORE_BASE(0x00C0) ++#define HDMI_V13_H_V_LINE_1 HDMI_CORE_BASE(0x00C4) ++#define HDMI_V13_H_V_LINE_2 HDMI_CORE_BASE(0x00C8) ++#define HDMI_VSYNC_POL HDMI_CORE_BASE(0x00E4) ++#define HDMI_INT_PRO_MODE HDMI_CORE_BASE(0x00E8) ++#define HDMI_V13_V_BLANK_F_0 HDMI_CORE_BASE(0x0110) ++#define HDMI_V13_V_BLANK_F_1 HDMI_CORE_BASE(0x0114) ++#define HDMI_V13_V_BLANK_F_2 HDMI_CORE_BASE(0x0118) ++#define HDMI_V13_H_SYNC_GEN_0 HDMI_CORE_BASE(0x0120) ++#define HDMI_V13_H_SYNC_GEN_1 HDMI_CORE_BASE(0x0124) ++#define HDMI_V13_H_SYNC_GEN_2 HDMI_CORE_BASE(0x0128) ++#define HDMI_V13_V_SYNC_GEN_1_0 HDMI_CORE_BASE(0x0130) ++#define HDMI_V13_V_SYNC_GEN_1_1 HDMI_CORE_BASE(0x0134) ++#define HDMI_V13_V_SYNC_GEN_1_2 HDMI_CORE_BASE(0x0138) ++#define HDMI_V13_V_SYNC_GEN_2_0 HDMI_CORE_BASE(0x0140) ++#define HDMI_V13_V_SYNC_GEN_2_1 HDMI_CORE_BASE(0x0144) ++#define HDMI_V13_V_SYNC_GEN_2_2 HDMI_CORE_BASE(0x0148) ++#define HDMI_V13_V_SYNC_GEN_3_0 HDMI_CORE_BASE(0x0150) ++#define HDMI_V13_V_SYNC_GEN_3_1 HDMI_CORE_BASE(0x0154) ++#define HDMI_V13_V_SYNC_GEN_3_2 HDMI_CORE_BASE(0x0158) ++#define HDMI_V13_ACR_CON HDMI_CORE_BASE(0x0180) ++#define HDMI_V13_AVI_CON HDMI_CORE_BASE(0x0300) ++#define HDMI_V13_AVI_BYTE(n) HDMI_CORE_BASE(0x0320 + 4 * (n)) ++#define HDMI_V13_DC_CONTROL HDMI_CORE_BASE(0x05C0) ++#define HDMI_V13_VIDEO_PATTERN_GEN HDMI_CORE_BASE(0x05C4) ++#define HDMI_V13_HPD_GEN HDMI_CORE_BASE(0x05C8) ++#define HDMI_V13_AUI_CON HDMI_CORE_BASE(0x0360) ++#define HDMI_V13_SPD_CON HDMI_CORE_BASE(0x0400) ++ ++/* Timing generator registers */ ++#define HDMI_TG_CMD HDMI_TG_BASE(0x0000) ++#define HDMI_TG_H_FSZ_L HDMI_TG_BASE(0x0018) ++#define HDMI_TG_H_FSZ_H HDMI_TG_BASE(0x001C) ++#define HDMI_TG_HACT_ST_L HDMI_TG_BASE(0x0020) ++#define HDMI_TG_HACT_ST_H HDMI_TG_BASE(0x0024) ++#define HDMI_TG_HACT_SZ_L HDMI_TG_BASE(0x0028) ++#define HDMI_TG_HACT_SZ_H HDMI_TG_BASE(0x002C) ++#define HDMI_TG_V_FSZ_L HDMI_TG_BASE(0x0030) ++#define HDMI_TG_V_FSZ_H HDMI_TG_BASE(0x0034) ++#define HDMI_TG_VSYNC_L HDMI_TG_BASE(0x0038) ++#define HDMI_TG_VSYNC_H HDMI_TG_BASE(0x003C) ++#define HDMI_TG_VSYNC2_L HDMI_TG_BASE(0x0040) ++#define HDMI_TG_VSYNC2_H HDMI_TG_BASE(0x0044) ++#define HDMI_TG_VACT_ST_L HDMI_TG_BASE(0x0048) ++#define HDMI_TG_VACT_ST_H HDMI_TG_BASE(0x004C) ++#define HDMI_TG_VACT_SZ_L HDMI_TG_BASE(0x0050) ++#define HDMI_TG_VACT_SZ_H HDMI_TG_BASE(0x0054) ++#define HDMI_TG_FIELD_CHG_L HDMI_TG_BASE(0x0058) ++#define HDMI_TG_FIELD_CHG_H HDMI_TG_BASE(0x005C) ++#define HDMI_TG_VACT_ST2_L HDMI_TG_BASE(0x0060) ++#define HDMI_TG_VACT_ST2_H HDMI_TG_BASE(0x0064) ++#define HDMI_TG_VSYNC_TOP_HDMI_L HDMI_TG_BASE(0x0078) ++#define HDMI_TG_VSYNC_TOP_HDMI_H HDMI_TG_BASE(0x007C) ++#define HDMI_TG_VSYNC_BOT_HDMI_L HDMI_TG_BASE(0x0080) ++#define HDMI_TG_VSYNC_BOT_HDMI_H HDMI_TG_BASE(0x0084) ++#define HDMI_TG_FIELD_TOP_HDMI_L HDMI_TG_BASE(0x0088) ++#define HDMI_TG_FIELD_TOP_HDMI_H HDMI_TG_BASE(0x008C) ++#define HDMI_TG_FIELD_BOT_HDMI_L HDMI_TG_BASE(0x0090) ++#define HDMI_TG_FIELD_BOT_HDMI_H HDMI_TG_BASE(0x0094) ++ ++/* ++ * Bit definition part ++ */ ++ ++/* HDMI_INTC_CON */ ++#define HDMI_INTC_EN_GLOBAL (1 << 6) ++#define HDMI_INTC_EN_HPD_PLUG (1 << 3) ++#define HDMI_INTC_EN_HPD_UNPLUG (1 << 2) ++ ++/* HDMI_INTC_FLAG */ ++#define HDMI_INTC_FLAG_HPD_PLUG (1 << 3) ++#define HDMI_INTC_FLAG_HPD_UNPLUG (1 << 2) ++ ++/* HDMI_PHY_RSTOUT */ ++#define HDMI_PHY_SW_RSTOUT (1 << 0) ++ ++/* HDMI_CORE_RSTOUT */ ++#define HDMI_CORE_SW_RSTOUT (1 << 0) ++ ++/* HDMI_CON_0 */ ++#define HDMI_BLUE_SCR_EN (1 << 5) ++#define HDMI_ASP_EN (1 << 2) ++#define HDMI_ASP_DIS (0 << 2) ++#define HDMI_ASP_MASK (1 << 2) ++#define HDMI_EN (1 << 0) ++ ++/* HDMI_PHY_STATUS */ ++#define HDMI_PHY_STATUS_READY (1 << 0) ++ ++/* HDMI_MODE_SEL */ ++#define HDMI_MODE_HDMI_EN (1 << 1) ++#define HDMI_MODE_DVI_EN (1 << 0) ++#define HDMI_DVI_MODE_EN (1) ++#define HDMI_DVI_MODE_DIS (0) ++#define HDMI_MODE_MASK (3 << 0) ++ ++/* HDMI_TG_CMD */ ++#define HDMI_TG_EN (1 << 0) ++#define HDMI_FIELD_EN (1 << 1) ++ ++ ++/* HDMI Version 1.4 */ ++/* Control registers */ ++/* #define HDMI_INTC_CON HDMI_CTRL_BASE(0x0000) */ ++/* #define HDMI_INTC_FLAG HDMI_CTRL_BASE(0x0004) */ ++#define HDMI_HDCP_KEY_LOAD HDMI_CTRL_BASE(0x0008) ++/* #define HDMI_HPD_STATUS HDMI_CTRL_BASE(0x000C) */ ++#define HDMI_INTC_CON_1 HDMI_CTRL_BASE(0x0010) ++#define HDMI_INTC_FLAG_1 HDMI_CTRL_BASE(0x0014) ++#define HDMI_PHY_STATUS_0 HDMI_CTRL_BASE(0x0020) ++#define HDMI_PHY_STATUS_CMU HDMI_CTRL_BASE(0x0024) ++#define HDMI_PHY_STATUS_PLL HDMI_CTRL_BASE(0x0028) ++#define HDMI_PHY_CON_0 HDMI_CTRL_BASE(0x0030) ++#define HDMI_HPD_CTRL HDMI_CTRL_BASE(0x0040) ++#define HDMI_HPD_ST HDMI_CTRL_BASE(0x0044) ++#define HDMI_HPD_TH_X HDMI_CTRL_BASE(0x0050) ++#define HDMI_AUDIO_CLKSEL HDMI_CTRL_BASE(0x0070) ++#define HDMI_PHY_RSTOUT HDMI_CTRL_BASE(0x0074) ++#define HDMI_PHY_VPLL HDMI_CTRL_BASE(0x0078) ++#define HDMI_PHY_CMU HDMI_CTRL_BASE(0x007C) ++#define HDMI_CORE_RSTOUT HDMI_CTRL_BASE(0x0080) ++ ++/* Video related registers */ ++#define HDMI_YMAX HDMI_CORE_BASE(0x0060) ++#define HDMI_YMIN HDMI_CORE_BASE(0x0064) ++#define HDMI_CMAX HDMI_CORE_BASE(0x0068) ++#define HDMI_CMIN HDMI_CORE_BASE(0x006C) ++ ++#define HDMI_V2_BLANK_0 HDMI_CORE_BASE(0x00B0) ++#define HDMI_V2_BLANK_1 HDMI_CORE_BASE(0x00B4) ++#define HDMI_V1_BLANK_0 HDMI_CORE_BASE(0x00B8) ++#define HDMI_V1_BLANK_1 HDMI_CORE_BASE(0x00BC) ++ ++#define HDMI_V_LINE_0 HDMI_CORE_BASE(0x00C0) ++#define HDMI_V_LINE_1 HDMI_CORE_BASE(0x00C4) ++#define HDMI_H_LINE_0 HDMI_CORE_BASE(0x00C8) ++#define HDMI_H_LINE_1 HDMI_CORE_BASE(0x00CC) ++ ++#define HDMI_HSYNC_POL HDMI_CORE_BASE(0x00E0) ++ ++#define HDMI_V_BLANK_F0_0 HDMI_CORE_BASE(0x0110) ++#define HDMI_V_BLANK_F0_1 HDMI_CORE_BASE(0x0114) ++#define HDMI_V_BLANK_F1_0 HDMI_CORE_BASE(0x0118) ++#define HDMI_V_BLANK_F1_1 HDMI_CORE_BASE(0x011C) ++ ++#define HDMI_H_SYNC_START_0 HDMI_CORE_BASE(0x0120) ++#define HDMI_H_SYNC_START_1 HDMI_CORE_BASE(0x0124) ++#define HDMI_H_SYNC_END_0 HDMI_CORE_BASE(0x0128) ++#define HDMI_H_SYNC_END_1 HDMI_CORE_BASE(0x012C) ++ ++#define HDMI_V_SYNC_LINE_BEF_2_0 HDMI_CORE_BASE(0x0130) ++#define HDMI_V_SYNC_LINE_BEF_2_1 HDMI_CORE_BASE(0x0134) ++#define HDMI_V_SYNC_LINE_BEF_1_0 HDMI_CORE_BASE(0x0138) ++#define HDMI_V_SYNC_LINE_BEF_1_1 HDMI_CORE_BASE(0x013C) ++ ++#define HDMI_V_SYNC_LINE_AFT_2_0 HDMI_CORE_BASE(0x0140) ++#define HDMI_V_SYNC_LINE_AFT_2_1 HDMI_CORE_BASE(0x0144) ++#define HDMI_V_SYNC_LINE_AFT_1_0 HDMI_CORE_BASE(0x0148) ++#define HDMI_V_SYNC_LINE_AFT_1_1 HDMI_CORE_BASE(0x014C) ++ ++#define HDMI_V_SYNC_LINE_AFT_PXL_2_0 HDMI_CORE_BASE(0x0150) ++#define HDMI_V_SYNC_LINE_AFT_PXL_2_1 HDMI_CORE_BASE(0x0154) ++#define HDMI_V_SYNC_LINE_AFT_PXL_1_0 HDMI_CORE_BASE(0x0158) ++#define HDMI_V_SYNC_LINE_AFT_PXL_1_1 HDMI_CORE_BASE(0x015C) ++ ++#define HDMI_V_BLANK_F2_0 HDMI_CORE_BASE(0x0160) ++#define HDMI_V_BLANK_F2_1 HDMI_CORE_BASE(0x0164) ++#define HDMI_V_BLANK_F3_0 HDMI_CORE_BASE(0x0168) ++#define HDMI_V_BLANK_F3_1 HDMI_CORE_BASE(0x016C) ++#define HDMI_V_BLANK_F4_0 HDMI_CORE_BASE(0x0170) ++#define HDMI_V_BLANK_F4_1 HDMI_CORE_BASE(0x0174) ++#define HDMI_V_BLANK_F5_0 HDMI_CORE_BASE(0x0178) ++#define HDMI_V_BLANK_F5_1 HDMI_CORE_BASE(0x017C) ++ ++#define HDMI_V_SYNC_LINE_AFT_3_0 HDMI_CORE_BASE(0x0180) ++#define HDMI_V_SYNC_LINE_AFT_3_1 HDMI_CORE_BASE(0x0184) ++#define HDMI_V_SYNC_LINE_AFT_4_0 HDMI_CORE_BASE(0x0188) ++#define HDMI_V_SYNC_LINE_AFT_4_1 HDMI_CORE_BASE(0x018C) ++#define HDMI_V_SYNC_LINE_AFT_5_0 HDMI_CORE_BASE(0x0190) ++#define HDMI_V_SYNC_LINE_AFT_5_1 HDMI_CORE_BASE(0x0194) ++#define HDMI_V_SYNC_LINE_AFT_6_0 HDMI_CORE_BASE(0x0198) ++#define HDMI_V_SYNC_LINE_AFT_6_1 HDMI_CORE_BASE(0x019C) ++ ++#define HDMI_V_SYNC_LINE_AFT_PXL_3_0 HDMI_CORE_BASE(0x01A0) ++#define HDMI_V_SYNC_LINE_AFT_PXL_3_1 HDMI_CORE_BASE(0x01A4) ++#define HDMI_V_SYNC_LINE_AFT_PXL_4_0 HDMI_CORE_BASE(0x01A8) ++#define HDMI_V_SYNC_LINE_AFT_PXL_4_1 HDMI_CORE_BASE(0x01AC) ++#define HDMI_V_SYNC_LINE_AFT_PXL_5_0 HDMI_CORE_BASE(0x01B0) ++#define HDMI_V_SYNC_LINE_AFT_PXL_5_1 HDMI_CORE_BASE(0x01B4) ++#define HDMI_V_SYNC_LINE_AFT_PXL_6_0 HDMI_CORE_BASE(0x01B8) ++#define HDMI_V_SYNC_LINE_AFT_PXL_6_1 HDMI_CORE_BASE(0x01BC) ++ ++#define HDMI_VACT_SPACE_1_0 HDMI_CORE_BASE(0x01C0) ++#define HDMI_VACT_SPACE_1_1 HDMI_CORE_BASE(0x01C4) ++#define HDMI_VACT_SPACE_2_0 HDMI_CORE_BASE(0x01C8) ++#define HDMI_VACT_SPACE_2_1 HDMI_CORE_BASE(0x01CC) ++#define HDMI_VACT_SPACE_3_0 HDMI_CORE_BASE(0x01D0) ++#define HDMI_VACT_SPACE_3_1 HDMI_CORE_BASE(0x01D4) ++#define HDMI_VACT_SPACE_4_0 HDMI_CORE_BASE(0x01D8) ++#define HDMI_VACT_SPACE_4_1 HDMI_CORE_BASE(0x01DC) ++#define HDMI_VACT_SPACE_5_0 HDMI_CORE_BASE(0x01E0) ++#define HDMI_VACT_SPACE_5_1 HDMI_CORE_BASE(0x01E4) ++#define HDMI_VACT_SPACE_6_0 HDMI_CORE_BASE(0x01E8) ++#define HDMI_VACT_SPACE_6_1 HDMI_CORE_BASE(0x01EC) ++ ++#define HDMI_GCP_CON HDMI_CORE_BASE(0x0200) ++#define HDMI_GCP_BYTE1 HDMI_CORE_BASE(0x0210) ++#define HDMI_GCP_BYTE2 HDMI_CORE_BASE(0x0214) ++#define HDMI_GCP_BYTE3 HDMI_CORE_BASE(0x0218) ++ ++/* Audio related registers */ ++#define HDMI_ASP_CON HDMI_CORE_BASE(0x0300) ++#define HDMI_ASP_SP_FLAT HDMI_CORE_BASE(0x0304) ++#define HDMI_ASP_CHCFG0 HDMI_CORE_BASE(0x0310) ++#define HDMI_ASP_CHCFG1 HDMI_CORE_BASE(0x0314) ++#define HDMI_ASP_CHCFG2 HDMI_CORE_BASE(0x0318) ++#define HDMI_ASP_CHCFG3 HDMI_CORE_BASE(0x031C) ++ ++#define HDMI_ACR_CON HDMI_CORE_BASE(0x0400) ++#define HDMI_ACR_MCTS0 HDMI_CORE_BASE(0x0410) ++#define HDMI_ACR_MCTS1 HDMI_CORE_BASE(0x0414) ++#define HDMI_ACR_MCTS2 HDMI_CORE_BASE(0x0418) ++#define HDMI_ACR_CTS0 HDMI_CORE_BASE(0x0420) ++#define HDMI_ACR_CTS1 HDMI_CORE_BASE(0x0424) ++#define HDMI_ACR_CTS2 HDMI_CORE_BASE(0x0428) ++#define HDMI_ACR_N0 HDMI_CORE_BASE(0x0430) ++#define HDMI_ACR_N1 HDMI_CORE_BASE(0x0434) ++#define HDMI_ACR_N2 HDMI_CORE_BASE(0x0438) ++ ++/* Packet related registers */ ++#define HDMI_ACP_CON HDMI_CORE_BASE(0x0500) ++#define HDMI_ACP_TYPE HDMI_CORE_BASE(0x0514) ++#define HDMI_ACP_DATA(n) HDMI_CORE_BASE(0x0520 + 4 * (n)) ++ ++#define HDMI_ISRC_CON HDMI_CORE_BASE(0x0600) ++#define HDMI_ISRC1_HEADER1 HDMI_CORE_BASE(0x0614) ++#define HDMI_ISRC1_DATA(n) HDMI_CORE_BASE(0x0620 + 4 * (n)) ++#define HDMI_ISRC2_DATA(n) HDMI_CORE_BASE(0x06A0 + 4 * (n)) ++ ++#define HDMI_AVI_CON HDMI_CORE_BASE(0x0700) ++#define HDMI_AVI_HEADER0 HDMI_CORE_BASE(0x0710) ++#define HDMI_AVI_HEADER1 HDMI_CORE_BASE(0x0714) ++#define HDMI_AVI_HEADER2 HDMI_CORE_BASE(0x0718) ++#define HDMI_AVI_CHECK_SUM HDMI_CORE_BASE(0x071C) ++#define HDMI_AVI_BYTE(n) HDMI_CORE_BASE(0x0720 + 4 * (n)) ++ ++#define HDMI_AUI_CON HDMI_CORE_BASE(0x0800) ++#define HDMI_AUI_HEADER0 HDMI_CORE_BASE(0x0810) ++#define HDMI_AUI_HEADER1 HDMI_CORE_BASE(0x0814) ++#define HDMI_AUI_HEADER2 HDMI_CORE_BASE(0x0818) ++#define HDMI_AUI_CHECK_SUM HDMI_CORE_BASE(0x081C) ++#define HDMI_AUI_BYTE(n) HDMI_CORE_BASE(0x0820 + 4 * (n)) ++ ++#define HDMI_MPG_CON HDMI_CORE_BASE(0x0900) ++#define HDMI_MPG_CHECK_SUM HDMI_CORE_BASE(0x091C) ++#define HDMI_MPG_DATA(n) HDMI_CORE_BASE(0x0920 + 4 * (n)) ++ ++#define HDMI_SPD_CON HDMI_CORE_BASE(0x0A00) ++#define HDMI_SPD_HEADER0 HDMI_CORE_BASE(0x0A10) ++#define HDMI_SPD_HEADER1 HDMI_CORE_BASE(0x0A14) ++#define HDMI_SPD_HEADER2 HDMI_CORE_BASE(0x0A18) ++#define HDMI_SPD_DATA(n) HDMI_CORE_BASE(0x0A20 + 4 * (n)) ++ ++#define HDMI_GAMUT_CON HDMI_CORE_BASE(0x0B00) ++#define HDMI_GAMUT_HEADER0 HDMI_CORE_BASE(0x0B10) ++#define HDMI_GAMUT_HEADER1 HDMI_CORE_BASE(0x0B14) ++#define HDMI_GAMUT_HEADER2 HDMI_CORE_BASE(0x0B18) ++#define HDMI_GAMUT_METADATA(n) HDMI_CORE_BASE(0x0B20 + 4 * (n)) ++ ++#define HDMI_VSI_CON HDMI_CORE_BASE(0x0C00) ++#define HDMI_VSI_HEADER0 HDMI_CORE_BASE(0x0C10) ++#define HDMI_VSI_HEADER1 HDMI_CORE_BASE(0x0C14) ++#define HDMI_VSI_HEADER2 HDMI_CORE_BASE(0x0C18) ++#define HDMI_VSI_DATA(n) HDMI_CORE_BASE(0x0C20 + 4 * (n)) ++ ++#define HDMI_DC_CONTROL HDMI_CORE_BASE(0x0D00) ++#define HDMI_VIDEO_PATTERN_GEN HDMI_CORE_BASE(0x0D04) ++ ++#define HDMI_AN_SEED_SEL HDMI_CORE_BASE(0x0E48) ++#define HDMI_AN_SEED_0 HDMI_CORE_BASE(0x0E58) ++#define HDMI_AN_SEED_1 HDMI_CORE_BASE(0x0E5C) ++#define HDMI_AN_SEED_2 HDMI_CORE_BASE(0x0E60) ++#define HDMI_AN_SEED_3 HDMI_CORE_BASE(0x0E64) ++ ++/* HDCP related registers */ ++#define HDMI_HDCP_SHA1(n) HDMI_CORE_BASE(0x7000 + 4 * (n)) ++#define HDMI_HDCP_KSV_LIST(n) HDMI_CORE_BASE(0x7050 + 4 * (n)) ++ ++#define HDMI_HDCP_KSV_LIST_CON HDMI_CORE_BASE(0x7064) ++#define HDMI_HDCP_SHA_RESULT HDMI_CORE_BASE(0x7070) ++#define HDMI_HDCP_CTRL1 HDMI_CORE_BASE(0x7080) ++#define HDMI_HDCP_CTRL2 HDMI_CORE_BASE(0x7084) ++#define HDMI_HDCP_CHECK_RESULT HDMI_CORE_BASE(0x7090) ++#define HDMI_HDCP_BKSV(n) HDMI_CORE_BASE(0x70A0 + 4 * (n)) ++#define HDMI_HDCP_AKSV(n) HDMI_CORE_BASE(0x70C0 + 4 * (n)) ++#define HDMI_HDCP_AN(n) HDMI_CORE_BASE(0x70E0 + 4 * (n)) ++ ++#define HDMI_HDCP_BCAPS HDMI_CORE_BASE(0x7100) ++#define HDMI_HDCP_BSTATUS_0 HDMI_CORE_BASE(0x7110) ++#define HDMI_HDCP_BSTATUS_1 HDMI_CORE_BASE(0x7114) ++#define HDMI_HDCP_RI_0 HDMI_CORE_BASE(0x7140) ++#define HDMI_HDCP_RI_1 HDMI_CORE_BASE(0x7144) ++#define HDMI_HDCP_I2C_INT HDMI_CORE_BASE(0x7180) ++#define HDMI_HDCP_AN_INT HDMI_CORE_BASE(0x7190) ++#define HDMI_HDCP_WDT_INT HDMI_CORE_BASE(0x71A0) ++#define HDMI_HDCP_RI_INT HDMI_CORE_BASE(0x71B0) ++#define HDMI_HDCP_RI_COMPARE_0 HDMI_CORE_BASE(0x71D0) ++#define HDMI_HDCP_RI_COMPARE_1 HDMI_CORE_BASE(0x71D4) ++#define HDMI_HDCP_FRAME_COUNT HDMI_CORE_BASE(0x71E0) ++ ++#define HDMI_RGB_ROUND_EN HDMI_CORE_BASE(0xD500) ++#define HDMI_VACT_SPACE_R_0 HDMI_CORE_BASE(0xD504) ++#define HDMI_VACT_SPACE_R_1 HDMI_CORE_BASE(0xD508) ++#define HDMI_VACT_SPACE_G_0 HDMI_CORE_BASE(0xD50C) ++#define HDMI_VACT_SPACE_G_1 HDMI_CORE_BASE(0xD510) ++#define HDMI_VACT_SPACE_B_0 HDMI_CORE_BASE(0xD514) ++#define HDMI_VACT_SPACE_B_1 HDMI_CORE_BASE(0xD518) ++ ++#define HDMI_BLUE_SCREEN_B_0 HDMI_CORE_BASE(0xD520) ++#define HDMI_BLUE_SCREEN_B_1 HDMI_CORE_BASE(0xD524) ++#define HDMI_BLUE_SCREEN_G_0 HDMI_CORE_BASE(0xD528) ++#define HDMI_BLUE_SCREEN_G_1 HDMI_CORE_BASE(0xD52C) ++#define HDMI_BLUE_SCREEN_R_0 HDMI_CORE_BASE(0xD530) ++#define HDMI_BLUE_SCREEN_R_1 HDMI_CORE_BASE(0xD534) ++ ++/* HDMI I2S register */ ++#define HDMI_I2S_CLK_CON HDMI_I2S_BASE(0x000) ++#define HDMI_I2S_CON_1 HDMI_I2S_BASE(0x004) ++#define HDMI_I2S_CON_2 HDMI_I2S_BASE(0x008) ++#define HDMI_I2S_PIN_SEL_0 HDMI_I2S_BASE(0x00c) ++#define HDMI_I2S_PIN_SEL_1 HDMI_I2S_BASE(0x010) ++#define HDMI_I2S_PIN_SEL_2 HDMI_I2S_BASE(0x014) ++#define HDMI_I2S_PIN_SEL_3 HDMI_I2S_BASE(0x018) ++#define HDMI_I2S_DSD_CON HDMI_I2S_BASE(0x01c) ++#define HDMI_I2S_MUX_CON HDMI_I2S_BASE(0x020) ++#define HDMI_I2S_CH_ST_CON HDMI_I2S_BASE(0x024) ++#define HDMI_I2S_CH_ST_0 HDMI_I2S_BASE(0x028) ++#define HDMI_I2S_CH_ST_1 HDMI_I2S_BASE(0x02c) ++#define HDMI_I2S_CH_ST_2 HDMI_I2S_BASE(0x030) ++#define HDMI_I2S_CH_ST_3 HDMI_I2S_BASE(0x034) ++#define HDMI_I2S_CH_ST_4 HDMI_I2S_BASE(0x038) ++#define HDMI_I2S_CH_ST_SH_0 HDMI_I2S_BASE(0x03c) ++#define HDMI_I2S_CH_ST_SH_1 HDMI_I2S_BASE(0x040) ++#define HDMI_I2S_CH_ST_SH_2 HDMI_I2S_BASE(0x044) ++#define HDMI_I2S_CH_ST_SH_3 HDMI_I2S_BASE(0x048) ++#define HDMI_I2S_CH_ST_SH_4 HDMI_I2S_BASE(0x04c) ++#define HDMI_I2S_MUX_CH HDMI_I2S_BASE(0x054) ++#define HDMI_I2S_MUX_CUV HDMI_I2S_BASE(0x058) ++ ++/* I2S bit definition */ ++ ++/* I2S_CLK_CON */ ++#define HDMI_I2S_CLK_DIS (0) ++#define HDMI_I2S_CLK_EN (1) ++ ++/* I2S_CON_1 */ ++#define HDMI_I2S_SCLK_FALLING_EDGE (0 << 1) ++#define HDMI_I2S_SCLK_RISING_EDGE (1 << 1) ++#define HDMI_I2S_L_CH_LOW_POL (0) ++#define HDMI_I2S_L_CH_HIGH_POL (1) ++ ++/* I2S_CON_2 */ ++#define HDMI_I2S_MSB_FIRST_MODE (0 << 6) ++#define HDMI_I2S_LSB_FIRST_MODE (1 << 6) ++#define HDMI_I2S_BIT_CH_32FS (0 << 4) ++#define HDMI_I2S_BIT_CH_48FS (1 << 4) ++#define HDMI_I2S_BIT_CH_RESERVED (2 << 4) ++#define HDMI_I2S_SDATA_16BIT (1 << 2) ++#define HDMI_I2S_SDATA_20BIT (2 << 2) ++#define HDMI_I2S_SDATA_24BIT (3 << 2) ++#define HDMI_I2S_BASIC_FORMAT (0) ++#define HDMI_I2S_L_JUST_FORMAT (2) ++#define HDMI_I2S_R_JUST_FORMAT (3) ++#define HDMI_I2S_CON_2_CLR (~(0xFF)) ++#define HDMI_I2S_SET_BIT_CH(x) (((x) & 0x7) << 4) ++#define HDMI_I2S_SET_SDATA_BIT(x) (((x) & 0x7) << 2) ++ ++/* I2S_PIN_SEL_0 */ ++#define HDMI_I2S_SEL_SCLK(x) (((x) & 0x7) << 4) ++#define HDMI_I2S_SEL_LRCK(x) ((x) & 0x7) ++ ++/* I2S_PIN_SEL_1 */ ++#define HDMI_I2S_SEL_SDATA1(x) (((x) & 0x7) << 4) ++#define HDMI_I2S_SEL_SDATA2(x) ((x) & 0x7) ++ ++/* I2S_PIN_SEL_2 */ ++#define HDMI_I2S_SEL_SDATA3(x) (((x) & 0x7) << 4) ++#define HDMI_I2S_SEL_SDATA2(x) ((x) & 0x7) ++ ++/* I2S_PIN_SEL_3 */ ++#define HDMI_I2S_SEL_DSD(x) ((x) & 0x7) ++ ++/* I2S_DSD_CON */ ++#define HDMI_I2S_DSD_CLK_RI_EDGE (1 << 1) ++#define HDMI_I2S_DSD_CLK_FA_EDGE (0 << 1) ++#define HDMI_I2S_DSD_ENABLE (1) ++#define HDMI_I2S_DSD_DISABLE (0) ++ ++/* I2S_MUX_CON */ ++#define HDMI_I2S_NOISE_FILTER_ZERO (0 << 5) ++#define HDMI_I2S_NOISE_FILTER_2_STAGE (1 << 5) ++#define HDMI_I2S_NOISE_FILTER_3_STAGE (2 << 5) ++#define HDMI_I2S_NOISE_FILTER_4_STAGE (3 << 5) ++#define HDMI_I2S_NOISE_FILTER_5_STAGE (4 << 5) ++#define HDMI_I2S_IN_DISABLE (1 << 4) ++#define HDMI_I2S_IN_ENABLE (0 << 4) ++#define HDMI_I2S_AUD_SPDIF (0 << 2) ++#define HDMI_I2S_AUD_I2S (1 << 2) ++#define HDMI_I2S_AUD_DSD (2 << 2) ++#define HDMI_I2S_CUV_SPDIF_ENABLE (0 << 1) ++#define HDMI_I2S_CUV_I2S_ENABLE (1 << 1) ++#define HDMI_I2S_MUX_DISABLE (0) ++#define HDMI_I2S_MUX_ENABLE (1) ++#define HDMI_I2S_MUX_CON_CLR (~(0xFF)) ++ ++/* I2S_CH_ST_CON */ ++#define HDMI_I2S_CH_STATUS_RELOAD (1) ++#define HDMI_I2S_CH_ST_CON_CLR (~(1)) ++ ++/* I2S_CH_ST_0 / I2S_CH_ST_SH_0 */ ++#define HDMI_I2S_CH_STATUS_MODE_0 (0 << 6) ++#define HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH (0 << 3) ++#define HDMI_I2S_2AUD_CH_WITH_PREEMPH (1 << 3) ++#define HDMI_I2S_DEFAULT_EMPHASIS (0 << 3) ++#define HDMI_I2S_COPYRIGHT (0 << 2) ++#define HDMI_I2S_NO_COPYRIGHT (1 << 2) ++#define HDMI_I2S_LINEAR_PCM (0 << 1) ++#define HDMI_I2S_NO_LINEAR_PCM (1 << 1) ++#define HDMI_I2S_CONSUMER_FORMAT (0) ++#define HDMI_I2S_PROF_FORMAT (1) ++#define HDMI_I2S_CH_ST_0_CLR (~(0xFF)) ++ ++/* I2S_CH_ST_1 / I2S_CH_ST_SH_1 */ ++#define HDMI_I2S_CD_PLAYER (0x00) ++#define HDMI_I2S_DAT_PLAYER (0x03) ++#define HDMI_I2S_DCC_PLAYER (0x43) ++#define HDMI_I2S_MINI_DISC_PLAYER (0x49) ++ ++/* I2S_CH_ST_2 / I2S_CH_ST_SH_2 */ ++#define HDMI_I2S_CHANNEL_NUM_MASK (0xF << 4) ++#define HDMI_I2S_SOURCE_NUM_MASK (0xF) ++#define HDMI_I2S_SET_CHANNEL_NUM(x) (((x) & (0xF)) << 4) ++#define HDMI_I2S_SET_SOURCE_NUM(x) ((x) & (0xF)) ++ ++/* I2S_CH_ST_3 / I2S_CH_ST_SH_3 */ ++#define HDMI_I2S_CLK_ACCUR_LEVEL_1 (1 << 4) ++#define HDMI_I2S_CLK_ACCUR_LEVEL_2 (0 << 4) ++#define HDMI_I2S_CLK_ACCUR_LEVEL_3 (2 << 4) ++#define HDMI_I2S_SMP_FREQ_44_1 (0x0) ++#define HDMI_I2S_SMP_FREQ_48 (0x2) ++#define HDMI_I2S_SMP_FREQ_32 (0x3) ++#define HDMI_I2S_SMP_FREQ_96 (0xA) ++#define HDMI_I2S_SET_SMP_FREQ(x) ((x) & (0xF)) ++ ++/* I2S_CH_ST_4 / I2S_CH_ST_SH_4 */ ++#define HDMI_I2S_ORG_SMP_FREQ_44_1 (0xF << 4) ++#define HDMI_I2S_ORG_SMP_FREQ_88_2 (0x7 << 4) ++#define HDMI_I2S_ORG_SMP_FREQ_22_05 (0xB << 4) ++#define HDMI_I2S_ORG_SMP_FREQ_176_4 (0x3 << 4) ++#define HDMI_I2S_WORD_LEN_NOT_DEFINE (0x0 << 1) ++#define HDMI_I2S_WORD_LEN_MAX24_20BITS (0x1 << 1) ++#define HDMI_I2S_WORD_LEN_MAX24_22BITS (0x2 << 1) ++#define HDMI_I2S_WORD_LEN_MAX24_23BITS (0x4 << 1) ++#define HDMI_I2S_WORD_LEN_MAX24_24BITS (0x5 << 1) ++#define HDMI_I2S_WORD_LEN_MAX24_21BITS (0x6 << 1) ++#define HDMI_I2S_WORD_LEN_MAX20_16BITS (0x1 << 1) ++#define HDMI_I2S_WORD_LEN_MAX20_18BITS (0x2 << 1) ++#define HDMI_I2S_WORD_LEN_MAX20_19BITS (0x4 << 1) ++#define HDMI_I2S_WORD_LEN_MAX20_20BITS (0x5 << 1) ++#define HDMI_I2S_WORD_LEN_MAX20_17BITS (0x6 << 1) ++#define HDMI_I2S_WORD_LEN_MAX_24BITS (1) ++#define HDMI_I2S_WORD_LEN_MAX_20BITS (0) ++ ++/* I2S_MUX_CH */ ++#define HDMI_I2S_CH3_R_EN (1 << 7) ++#define HDMI_I2S_CH3_L_EN (1 << 6) ++#define HDMI_I2S_CH3_EN (3 << 6) ++#define HDMI_I2S_CH2_R_EN (1 << 5) ++#define HDMI_I2S_CH2_L_EN (1 << 4) ++#define HDMI_I2S_CH2_EN (3 << 4) ++#define HDMI_I2S_CH1_R_EN (1 << 3) ++#define HDMI_I2S_CH1_L_EN (1 << 2) ++#define HDMI_I2S_CH1_EN (3 << 2) ++#define HDMI_I2S_CH0_R_EN (1 << 1) ++#define HDMI_I2S_CH0_L_EN (1) ++#define HDMI_I2S_CH0_EN (3) ++#define HDMI_I2S_CH_ALL_EN (0xFF) ++#define HDMI_I2S_MUX_CH_CLR (~HDMI_I2S_CH_ALL_EN) ++ ++/* I2S_MUX_CUV */ ++#define HDMI_I2S_CUV_R_EN (1 << 1) ++#define HDMI_I2S_CUV_L_EN (1) ++#define HDMI_I2S_CUV_RL_EN (0x03) ++ ++/* I2S_CUV_L_R */ ++#define HDMI_I2S_CUV_R_DATA_MASK (0x7 << 4) ++#define HDMI_I2S_CUV_L_DATA_MASK (0x7) ++ ++/* Timing generator registers */ ++/* TG configure/status registers */ ++#define HDMI_TG_VACT_ST3_L HDMI_TG_BASE(0x0068) ++#define HDMI_TG_VACT_ST3_H HDMI_TG_BASE(0x006c) ++#define HDMI_TG_VACT_ST4_L HDMI_TG_BASE(0x0070) ++#define HDMI_TG_VACT_ST4_H HDMI_TG_BASE(0x0074) ++#define HDMI_TG_3D HDMI_TG_BASE(0x00F0) ++ ++#endif /* SAMSUNG_REGS_HDMI_H */ +diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h +new file mode 100644 +index 0000000..fd2f4d1 +--- /dev/null ++++ b/drivers/gpu/drm/exynos/regs-mixer.h +@@ -0,0 +1,141 @@ ++/* ++ * ++ * Cloned from drivers/media/video/s5p-tv/regs-mixer.h ++ * ++ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. ++ * http://www.samsung.com/ ++ * ++ * Mixer register header file for Samsung Mixer 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. ++*/ ++#ifndef SAMSUNG_REGS_MIXER_H ++#define SAMSUNG_REGS_MIXER_H ++ ++/* ++ * Register part ++ */ ++#define MXR_STATUS 0x0000 ++#define MXR_CFG 0x0004 ++#define MXR_INT_EN 0x0008 ++#define MXR_INT_STATUS 0x000C ++#define MXR_LAYER_CFG 0x0010 ++#define MXR_VIDEO_CFG 0x0014 ++#define MXR_GRAPHIC0_CFG 0x0020 ++#define MXR_GRAPHIC0_BASE 0x0024 ++#define MXR_GRAPHIC0_SPAN 0x0028 ++#define MXR_GRAPHIC0_SXY 0x002C ++#define MXR_GRAPHIC0_WH 0x0030 ++#define MXR_GRAPHIC0_DXY 0x0034 ++#define MXR_GRAPHIC0_BLANK 0x0038 ++#define MXR_GRAPHIC1_CFG 0x0040 ++#define MXR_GRAPHIC1_BASE 0x0044 ++#define MXR_GRAPHIC1_SPAN 0x0048 ++#define MXR_GRAPHIC1_SXY 0x004C ++#define MXR_GRAPHIC1_WH 0x0050 ++#define MXR_GRAPHIC1_DXY 0x0054 ++#define MXR_GRAPHIC1_BLANK 0x0058 ++#define MXR_BG_CFG 0x0060 ++#define MXR_BG_COLOR0 0x0064 ++#define MXR_BG_COLOR1 0x0068 ++#define MXR_BG_COLOR2 0x006C ++#define MXR_CM_COEFF_Y 0x0080 ++#define MXR_CM_COEFF_CB 0x0084 ++#define MXR_CM_COEFF_CR 0x0088 ++#define MXR_GRAPHIC0_BASE_S 0x2024 ++#define MXR_GRAPHIC1_BASE_S 0x2044 ++ ++/* for parametrized access to layer registers */ ++#define MXR_GRAPHIC_CFG(i) (0x0020 + (i) * 0x20) ++#define MXR_GRAPHIC_BASE(i) (0x0024 + (i) * 0x20) ++#define MXR_GRAPHIC_SPAN(i) (0x0028 + (i) * 0x20) ++#define MXR_GRAPHIC_SXY(i) (0x002C + (i) * 0x20) ++#define MXR_GRAPHIC_WH(i) (0x0030 + (i) * 0x20) ++#define MXR_GRAPHIC_DXY(i) (0x0034 + (i) * 0x20) ++#define MXR_GRAPHIC_BLANK(i) (0x0038 + (i) * 0x20) ++#define MXR_GRAPHIC_BASE_S(i) (0x2024 + (i) * 0x20) ++ ++/* ++ * Bit definition part ++ */ ++ ++/* generates mask for range of bits */ ++#define MXR_MASK(high_bit, low_bit) \ ++ (((2 << ((high_bit) - (low_bit))) - 1) << (low_bit)) ++ ++#define MXR_MASK_VAL(val, high_bit, low_bit) \ ++ (((val) << (low_bit)) & MXR_MASK(high_bit, low_bit)) ++ ++/* bits for MXR_STATUS */ ++#define MXR_STATUS_16_BURST (1 << 7) ++#define MXR_STATUS_BURST_MASK (1 << 7) ++#define MXR_STATUS_BIG_ENDIAN (1 << 3) ++#define MXR_STATUS_ENDIAN_MASK (1 << 3) ++#define MXR_STATUS_SYNC_ENABLE (1 << 2) ++#define MXR_STATUS_REG_RUN (1 << 0) ++ ++/* bits for MXR_CFG */ ++#define MXR_CFG_RGB601_0_255 (0 << 9) ++#define MXR_CFG_RGB601_16_235 (1 << 9) ++#define MXR_CFG_RGB709_0_255 (2 << 9) ++#define MXR_CFG_RGB709_16_235 (3 << 9) ++#define MXR_CFG_RGB_FMT_MASK 0x600 ++#define MXR_CFG_OUT_YUV444 (0 << 8) ++#define MXR_CFG_OUT_RGB888 (1 << 8) ++#define MXR_CFG_OUT_MASK (1 << 8) ++#define MXR_CFG_DST_SDO (0 << 7) ++#define MXR_CFG_DST_HDMI (1 << 7) ++#define MXR_CFG_DST_MASK (1 << 7) ++#define MXR_CFG_SCAN_HD_720 (0 << 6) ++#define MXR_CFG_SCAN_HD_1080 (1 << 6) ++#define MXR_CFG_GRP1_ENABLE (1 << 5) ++#define MXR_CFG_GRP0_ENABLE (1 << 4) ++#define MXR_CFG_VP_ENABLE (1 << 3) ++#define MXR_CFG_SCAN_INTERLACE (0 << 2) ++#define MXR_CFG_SCAN_PROGRASSIVE (1 << 2) ++#define MXR_CFG_SCAN_NTSC (0 << 1) ++#define MXR_CFG_SCAN_PAL (1 << 1) ++#define MXR_CFG_SCAN_SD (0 << 0) ++#define MXR_CFG_SCAN_HD (1 << 0) ++#define MXR_CFG_SCAN_MASK 0x47 ++ ++/* bits for MXR_GRAPHICn_CFG */ ++#define MXR_GRP_CFG_COLOR_KEY_DISABLE (1 << 21) ++#define MXR_GRP_CFG_BLEND_PRE_MUL (1 << 20) ++#define MXR_GRP_CFG_WIN_BLEND_EN (1 << 17) ++#define MXR_GRP_CFG_PIXEL_BLEND_EN (1 << 16) ++#define MXR_GRP_CFG_FORMAT_VAL(x) MXR_MASK_VAL(x, 11, 8) ++#define MXR_GRP_CFG_FORMAT_MASK MXR_GRP_CFG_FORMAT_VAL(~0) ++#define MXR_GRP_CFG_ALPHA_VAL(x) MXR_MASK_VAL(x, 7, 0) ++ ++/* bits for MXR_GRAPHICn_WH */ ++#define MXR_GRP_WH_H_SCALE(x) MXR_MASK_VAL(x, 28, 28) ++#define MXR_GRP_WH_V_SCALE(x) MXR_MASK_VAL(x, 12, 12) ++#define MXR_GRP_WH_WIDTH(x) MXR_MASK_VAL(x, 26, 16) ++#define MXR_GRP_WH_HEIGHT(x) MXR_MASK_VAL(x, 10, 0) ++ ++/* bits for MXR_GRAPHICn_SXY */ ++#define MXR_GRP_SXY_SX(x) MXR_MASK_VAL(x, 26, 16) ++#define MXR_GRP_SXY_SY(x) MXR_MASK_VAL(x, 10, 0) ++ ++/* bits for MXR_GRAPHICn_DXY */ ++#define MXR_GRP_DXY_DX(x) MXR_MASK_VAL(x, 26, 16) ++#define MXR_GRP_DXY_DY(x) MXR_MASK_VAL(x, 10, 0) ++ ++/* bits for MXR_INT_EN */ ++#define MXR_INT_EN_VSYNC (1 << 11) ++#define MXR_INT_EN_ALL (0x0f << 8) ++ ++/* bit for MXR_INT_STATUS */ ++#define MXR_INT_CLEAR_VSYNC (1 << 11) ++#define MXR_INT_STATUS_VSYNC (1 << 0) ++ ++/* bit for MXR_LAYER_CFG */ ++#define MXR_LAYER_CFG_GRP1_VAL(x) MXR_MASK_VAL(x, 11, 8) ++#define MXR_LAYER_CFG_GRP0_VAL(x) MXR_MASK_VAL(x, 7, 4) ++#define MXR_LAYER_CFG_VP_VAL(x) MXR_MASK_VAL(x, 3, 0) ++ ++#endif /* SAMSUNG_REGS_MIXER_H */ ++ +diff --git a/drivers/gpu/drm/exynos/regs-vp.h b/drivers/gpu/drm/exynos/regs-vp.h +new file mode 100644 +index 0000000..10b737a +--- /dev/null ++++ b/drivers/gpu/drm/exynos/regs-vp.h +@@ -0,0 +1,91 @@ ++/* ++ * ++ * Cloned from drivers/media/video/s5p-tv/regs-vp.h ++ * ++ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. ++ * http://www.samsung.com/ ++ * ++ * Video processor register header file for Samsung Mixer 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. ++ */ ++ ++#ifndef SAMSUNG_REGS_VP_H ++#define SAMSUNG_REGS_VP_H ++ ++/* ++ * Register part ++ */ ++ ++#define VP_ENABLE 0x0000 ++#define VP_SRESET 0x0004 ++#define VP_SHADOW_UPDATE 0x0008 ++#define VP_FIELD_ID 0x000C ++#define VP_MODE 0x0010 ++#define VP_IMG_SIZE_Y 0x0014 ++#define VP_IMG_SIZE_C 0x0018 ++#define VP_PER_RATE_CTRL 0x001C ++#define VP_TOP_Y_PTR 0x0028 ++#define VP_BOT_Y_PTR 0x002C ++#define VP_TOP_C_PTR 0x0030 ++#define VP_BOT_C_PTR 0x0034 ++#define VP_ENDIAN_MODE 0x03CC ++#define VP_SRC_H_POSITION 0x0044 ++#define VP_SRC_V_POSITION 0x0048 ++#define VP_SRC_WIDTH 0x004C ++#define VP_SRC_HEIGHT 0x0050 ++#define VP_DST_H_POSITION 0x0054 ++#define VP_DST_V_POSITION 0x0058 ++#define VP_DST_WIDTH 0x005C ++#define VP_DST_HEIGHT 0x0060 ++#define VP_H_RATIO 0x0064 ++#define VP_V_RATIO 0x0068 ++#define VP_POLY8_Y0_LL 0x006C ++#define VP_POLY4_Y0_LL 0x00EC ++#define VP_POLY4_C0_LL 0x012C ++ ++/* ++ * Bit definition part ++ */ ++ ++/* generates mask for range of bits */ ++ ++#define VP_MASK(high_bit, low_bit) \ ++ (((2 << ((high_bit) - (low_bit))) - 1) << (low_bit)) ++ ++#define VP_MASK_VAL(val, high_bit, low_bit) \ ++ (((val) << (low_bit)) & VP_MASK(high_bit, low_bit)) ++ ++ /* VP_ENABLE */ ++#define VP_ENABLE_ON (1 << 0) ++ ++/* VP_SRESET */ ++#define VP_SRESET_PROCESSING (1 << 0) ++ ++/* VP_SHADOW_UPDATE */ ++#define VP_SHADOW_UPDATE_ENABLE (1 << 0) ++ ++/* VP_MODE */ ++#define VP_MODE_NV12 (0 << 6) ++#define VP_MODE_NV21 (1 << 6) ++#define VP_MODE_LINE_SKIP (1 << 5) ++#define VP_MODE_MEM_LINEAR (0 << 4) ++#define VP_MODE_MEM_TILED (1 << 4) ++#define VP_MODE_FMT_MASK (5 << 4) ++#define VP_MODE_FIELD_ID_AUTO_TOGGLING (1 << 2) ++#define VP_MODE_2D_IPC (1 << 1) ++ ++/* VP_IMG_SIZE_Y */ ++/* VP_IMG_SIZE_C */ ++#define VP_IMG_HSIZE(x) VP_MASK_VAL(x, 29, 16) ++#define VP_IMG_VSIZE(x) VP_MASK_VAL(x, 13, 0) ++ ++/* VP_SRC_H_POSITION */ ++#define VP_SRC_H_POSITION_VAL(x) VP_MASK_VAL(x, 14, 4) ++ ++/* VP_ENDIAN_MODE */ ++#define VP_ENDIAN_MODE_LITTLE (1 << 0) ++ ++#endif /* SAMSUNG_REGS_VP_H */ +diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig +new file mode 100644 +index 0000000..42e665c +--- /dev/null ++++ b/drivers/gpu/drm/gma500/Kconfig +@@ -0,0 +1,33 @@ ++config DRM_GMA500 ++ tristate "Intel GMA5/600 KMS Framebuffer" ++ depends on DRM && PCI && X86 && EXPERIMENTAL ++ select FB_CFB_COPYAREA ++ select FB_CFB_FILLRECT ++ select FB_CFB_IMAGEBLIT ++ select DRM_KMS_HELPER ++ select DRM_TTM ++ help ++ Say yes for an experimental 2D KMS framebuffer driver for the ++ Intel GMA500 ('Poulsbo') and other Intel IMG based graphics ++ devices. ++ ++config DRM_GMA600 ++ bool "Intel GMA600 support (Experimental)" ++ depends on DRM_GMA500 ++ help ++ Say yes to include support for GMA600 (Intel Moorestown/Oaktrail) ++ platforms with LVDS ports. MIPI is not currently supported. ++ ++config DRM_GMA3600 ++ bool "Intel GMA3600/3650 support (Experimental)" ++ depends on DRM_GMA500 ++ help ++ Say yes to include basic support for Intel GMA3600/3650 (Intel ++ Cedar Trail) platforms. ++ ++config DRM_MEDFIELD ++ bool "Intel Medfield support (Experimental)" ++ depends on DRM_GMA500 && X86_INTEL_MID ++ help ++ Say yes to include support for the Intel Medfield platform. ++ +diff --git a/drivers/gpu/drm/gma500/Makefile b/drivers/gpu/drm/gma500/Makefile +new file mode 100644 +index 0000000..1583982 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/Makefile +@@ -0,0 +1,50 @@ ++# ++# KMS driver for the GMA500 ++# ++ccflags-y += -Iinclude/drm ++ ++gma500_gfx-y += gem_glue.o \ ++ accel_2d.o \ ++ backlight.o \ ++ framebuffer.o \ ++ gem.o \ ++ gtt.o \ ++ intel_bios.o \ ++ intel_i2c.o \ ++ intel_gmbus.o \ ++ intel_opregion.o \ ++ mmu.o \ ++ power.o \ ++ psb_drv.o \ ++ psb_intel_display.o \ ++ psb_intel_lvds.o \ ++ psb_intel_modes.o \ ++ psb_intel_sdvo.o \ ++ psb_lid.o \ ++ psb_irq.o \ ++ psb_device.o \ ++ mid_bios.o ++ ++gma500_gfx-$(CONFIG_DRM_GMA3600) += cdv_device.o \ ++ cdv_intel_crt.o \ ++ cdv_intel_display.o \ ++ cdv_intel_hdmi.o \ ++ cdv_intel_lvds.o ++ ++gma500_gfx-$(CONFIG_DRM_GMA600) += oaktrail_device.o \ ++ oaktrail_crtc.o \ ++ oaktrail_lvds.o \ ++ oaktrail_hdmi.o \ ++ oaktrail_hdmi_i2c.o ++ ++gma500_gfx-$(CONFIG_DRM_MEDFIELD) += mdfld_device.o \ ++ mdfld_output.o \ ++ mdfld_intel_display.o \ ++ mdfld_dsi_output.o \ ++ mdfld_dsi_dpi.o \ ++ mdfld_dsi_pkg_sender.o \ ++ mdfld_tpo_vid.o \ ++ mdfld_tmd_vid.o \ ++ tc35876x-dsi-lvds.o ++ ++obj-$(CONFIG_DRM_GMA500) += gma500_gfx.o +diff --git a/drivers/gpu/drm/gma500/accel_2d.c b/drivers/gpu/drm/gma500/accel_2d.c +new file mode 100644 +index 0000000..d5ef1a5 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/accel_2d.c +@@ -0,0 +1,364 @@ ++/************************************************************************** ++ * Copyright (c) 2007-2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to ++ * develop this driver. ++ * ++ **************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "psb_drv.h" ++#include "psb_reg.h" ++#include "framebuffer.h" ++ ++/** ++ * psb_spank - reset the 2D engine ++ * @dev_priv: our PSB DRM device ++ * ++ * Soft reset the graphics engine and then reload the necessary registers. ++ * We use this at initialisation time but it will become relevant for ++ * accelerated X later ++ */ ++void psb_spank(struct drm_psb_private *dev_priv) ++{ ++ PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET | ++ _PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET | ++ _PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET | ++ _PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET); ++ PSB_RSGX32(PSB_CR_SOFT_RESET); ++ ++ msleep(1); ++ ++ PSB_WSGX32(0, PSB_CR_SOFT_RESET); ++ wmb(); ++ PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT, ++ PSB_CR_BIF_CTRL); ++ wmb(); ++ (void) PSB_RSGX32(PSB_CR_BIF_CTRL); ++ ++ msleep(1); ++ PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT, ++ PSB_CR_BIF_CTRL); ++ (void) PSB_RSGX32(PSB_CR_BIF_CTRL); ++ PSB_WSGX32(dev_priv->gtt.gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); ++} ++ ++/** ++ * psb2_2d_wait_available - wait for FIFO room ++ * @dev_priv: our DRM device ++ * @size: size (in dwords) of the command we want to issue ++ * ++ * Wait until there is room to load the FIFO with our data. If the ++ * device is not responding then reset it ++ */ ++static int psb_2d_wait_available(struct drm_psb_private *dev_priv, ++ unsigned size) ++{ ++ uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF); ++ unsigned long t = jiffies + HZ; ++ ++ while (avail < size) { ++ avail = PSB_RSGX32(PSB_CR_2D_SOCIF); ++ if (time_after(jiffies, t)) { ++ psb_spank(dev_priv); ++ return -EIO; ++ } ++ } ++ return 0; ++} ++ ++/** ++ * psb_2d_submit - submit a 2D command ++ * @dev_priv: our DRM device ++ * @cmdbuf: command to issue ++ * @size: length (in dwords) ++ * ++ * Issue one or more 2D commands to the accelerator. This needs to be ++ * serialized later when we add the GEM interfaces for acceleration ++ */ ++static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, ++ unsigned size) ++{ ++ int ret = 0; ++ int i; ++ unsigned submit_size; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev_priv->lock_2d, flags); ++ while (size > 0) { ++ submit_size = (size < 0x60) ? size : 0x60; ++ size -= submit_size; ++ ret = psb_2d_wait_available(dev_priv, submit_size); ++ if (ret) ++ break; ++ ++ submit_size <<= 2; ++ ++ for (i = 0; i < submit_size; i += 4) ++ PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i); ++ ++ (void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4); ++ } ++ spin_unlock_irqrestore(&dev_priv->lock_2d, flags); ++ return ret; ++} ++ ++ ++/** ++ * psb_accel_2d_copy_direction - compute blit order ++ * @xdir: X direction of move ++ * @ydir: Y direction of move ++ * ++ * Compute the correct order setings to ensure that an overlapping blit ++ * correctly copies all the pixels. ++ */ ++static u32 psb_accel_2d_copy_direction(int xdir, int ydir) ++{ ++ if (xdir < 0) ++ return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL : ++ PSB_2D_COPYORDER_TR2BL; ++ else ++ return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR : ++ PSB_2D_COPYORDER_TL2BR; ++} ++ ++/** ++ * psb_accel_2d_copy - accelerated 2D copy ++ * @dev_priv: our DRM device ++ * @src_offset in bytes ++ * @src_stride in bytes ++ * @src_format psb 2D format defines ++ * @dst_offset in bytes ++ * @dst_stride in bytes ++ * @dst_format psb 2D format defines ++ * @src_x offset in pixels ++ * @src_y offset in pixels ++ * @dst_x offset in pixels ++ * @dst_y offset in pixels ++ * @size_x of the copied area ++ * @size_y of the copied area ++ * ++ * Format and issue a 2D accelerated copy command. ++ */ ++static int psb_accel_2d_copy(struct drm_psb_private *dev_priv, ++ uint32_t src_offset, uint32_t src_stride, ++ uint32_t src_format, uint32_t dst_offset, ++ uint32_t dst_stride, uint32_t dst_format, ++ uint16_t src_x, uint16_t src_y, ++ uint16_t dst_x, uint16_t dst_y, ++ uint16_t size_x, uint16_t size_y) ++{ ++ uint32_t blit_cmd; ++ uint32_t buffer[10]; ++ uint32_t *buf; ++ uint32_t direction; ++ ++ buf = buffer; ++ ++ direction = ++ psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y); ++ ++ if (direction == PSB_2D_COPYORDER_BR2TL || ++ direction == PSB_2D_COPYORDER_TR2BL) { ++ src_x += size_x - 1; ++ dst_x += size_x - 1; ++ } ++ if (direction == PSB_2D_COPYORDER_BR2TL || ++ direction == PSB_2D_COPYORDER_BL2TR) { ++ src_y += size_y - 1; ++ dst_y += size_y - 1; ++ } ++ ++ blit_cmd = ++ PSB_2D_BLIT_BH | ++ PSB_2D_ROT_NONE | ++ PSB_2D_DSTCK_DISABLE | ++ PSB_2D_SRCCK_DISABLE | ++ PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction; ++ ++ *buf++ = PSB_2D_FENCE_BH; ++ *buf++ = ++ PSB_2D_DST_SURF_BH | dst_format | (dst_stride << ++ PSB_2D_DST_STRIDE_SHIFT); ++ *buf++ = dst_offset; ++ *buf++ = ++ PSB_2D_SRC_SURF_BH | src_format | (src_stride << ++ PSB_2D_SRC_STRIDE_SHIFT); ++ *buf++ = src_offset; ++ *buf++ = ++ PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) | ++ (src_y << PSB_2D_SRCOFF_YSTART_SHIFT); ++ *buf++ = blit_cmd; ++ *buf++ = ++ (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y << ++ PSB_2D_DST_YSTART_SHIFT); ++ *buf++ = ++ (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y << ++ PSB_2D_DST_YSIZE_SHIFT); ++ *buf++ = PSB_2D_FLUSH_BH; ++ ++ return psbfb_2d_submit(dev_priv, buffer, buf - buffer); ++} ++ ++/** ++ * psbfb_copyarea_accel - copyarea acceleration for /dev/fb ++ * @info: our framebuffer ++ * @a: copyarea parameters from the framebuffer core ++ * ++ * Perform a 2D copy via the accelerator ++ */ ++static void psbfb_copyarea_accel(struct fb_info *info, ++ const struct fb_copyarea *a) ++{ ++ struct psb_fbdev *fbdev = info->par; ++ struct psb_framebuffer *psbfb = &fbdev->pfb; ++ struct drm_device *dev = psbfb->base.dev; ++ struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ uint32_t offset; ++ uint32_t stride; ++ uint32_t src_format; ++ uint32_t dst_format; ++ ++ if (!fb) ++ return; ++ ++ offset = psbfb->gtt->offset; ++ stride = fb->pitches[0]; ++ ++ switch (fb->depth) { ++ case 8: ++ src_format = PSB_2D_SRC_332RGB; ++ dst_format = PSB_2D_DST_332RGB; ++ break; ++ case 15: ++ src_format = PSB_2D_SRC_555RGB; ++ dst_format = PSB_2D_DST_555RGB; ++ break; ++ case 16: ++ src_format = PSB_2D_SRC_565RGB; ++ dst_format = PSB_2D_DST_565RGB; ++ break; ++ case 24: ++ case 32: ++ /* this is wrong but since we don't do blending its okay */ ++ src_format = PSB_2D_SRC_8888ARGB; ++ dst_format = PSB_2D_DST_8888ARGB; ++ break; ++ default: ++ /* software fallback */ ++ cfb_copyarea(info, a); ++ return; ++ } ++ ++ if (!gma_power_begin(dev, false)) { ++ cfb_copyarea(info, a); ++ return; ++ } ++ psb_accel_2d_copy(dev_priv, ++ offset, stride, src_format, ++ offset, stride, dst_format, ++ a->sx, a->sy, a->dx, a->dy, a->width, a->height); ++ gma_power_end(dev); ++} ++ ++/** ++ * psbfb_copyarea - 2D copy interface ++ * @info: our framebuffer ++ * @region: region to copy ++ * ++ * Copy an area of the framebuffer console either by the accelerator ++ * or directly using the cfb helpers according to the request ++ */ ++void psbfb_copyarea(struct fb_info *info, ++ const struct fb_copyarea *region) ++{ ++ if (unlikely(info->state != FBINFO_STATE_RUNNING)) ++ return; ++ ++ /* Avoid the 8 pixel erratum */ ++ if (region->width == 8 || region->height == 8 || ++ (info->flags & FBINFO_HWACCEL_DISABLED)) ++ return cfb_copyarea(info, region); ++ ++ psbfb_copyarea_accel(info, region); ++} ++ ++/** ++ * psbfb_sync - synchronize 2D ++ * @info: our framebuffer ++ * ++ * Wait for the 2D engine to quiesce so that we can do CPU ++ * access to the framebuffer again ++ */ ++int psbfb_sync(struct fb_info *info) ++{ ++ struct psb_fbdev *fbdev = info->par; ++ struct psb_framebuffer *psbfb = &fbdev->pfb; ++ struct drm_device *dev = psbfb->base.dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ unsigned long _end = jiffies + DRM_HZ; ++ int busy = 0; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev_priv->lock_2d, flags); ++ /* ++ * First idle the 2D engine. ++ */ ++ ++ if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) && ++ ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0)) ++ goto out; ++ ++ do { ++ busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY); ++ cpu_relax(); ++ } while (busy && !time_after_eq(jiffies, _end)); ++ ++ if (busy) ++ busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY); ++ if (busy) ++ goto out; ++ ++ do { ++ busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & ++ _PSB_C2B_STATUS_BUSY) != 0); ++ cpu_relax(); ++ } while (busy && !time_after_eq(jiffies, _end)); ++ if (busy) ++ busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & ++ _PSB_C2B_STATUS_BUSY) != 0); ++ ++out: ++ spin_unlock_irqrestore(&dev_priv->lock_2d, flags); ++ return (busy) ? -EBUSY : 0; ++} +diff --git a/drivers/gpu/drm/gma500/backlight.c b/drivers/gpu/drm/gma500/backlight.c +new file mode 100644 +index 0000000..2079395 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/backlight.c +@@ -0,0 +1,49 @@ ++/* ++ * GMA500 Backlight Interface ++ * ++ * Copyright (c) 2009-2011, Intel Corporation. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: Eric Knopp ++ * ++ */ ++ ++#include "psb_drv.h" ++#include "psb_intel_reg.h" ++#include "psb_intel_drv.h" ++#include "intel_bios.h" ++#include "power.h" ++ ++int gma_backlight_init(struct drm_device *dev) ++{ ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ return dev_priv->ops->backlight_init(dev); ++#else ++ return 0; ++#endif ++} ++ ++void gma_backlight_exit(struct drm_device *dev) ++{ ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ if (dev_priv->backlight_device) { ++ dev_priv->backlight_device->props.brightness = 0; ++ backlight_update_status(dev_priv->backlight_device); ++ backlight_device_unregister(dev_priv->backlight_device); ++ } ++#endif ++} +diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c +new file mode 100644 +index 0000000..a54cc73 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/cdv_device.c +@@ -0,0 +1,484 @@ ++/************************************************************************** ++ * Copyright (c) 2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++ ++#include ++#include ++#include ++#include "gma_drm.h" ++#include "psb_drv.h" ++#include "psb_reg.h" ++#include "psb_intel_reg.h" ++#include "intel_bios.h" ++#include "cdv_device.h" ++ ++#define VGA_SR_INDEX 0x3c4 ++#define VGA_SR_DATA 0x3c5 ++ ++static void cdv_disable_vga(struct drm_device *dev) ++{ ++ u8 sr1; ++ u32 vga_reg; ++ ++ vga_reg = VGACNTRL; ++ ++ outb(1, VGA_SR_INDEX); ++ sr1 = inb(VGA_SR_DATA); ++ outb(sr1 | 1<<5, VGA_SR_DATA); ++ udelay(300); ++ ++ REG_WRITE(vga_reg, VGA_DISP_DISABLE); ++ REG_READ(vga_reg); ++} ++ ++static int cdv_output_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ cdv_disable_vga(dev); ++ ++ cdv_intel_crt_init(dev, &dev_priv->mode_dev); ++ cdv_intel_lvds_init(dev, &dev_priv->mode_dev); ++ ++ /* These bits indicate HDMI not SDVO on CDV, but we don't yet support ++ the HDMI interface */ ++ if (REG_READ(SDVOB) & SDVO_DETECTED) ++ cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB); ++ if (REG_READ(SDVOC) & SDVO_DETECTED) ++ cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC); ++ return 0; ++} ++ ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ ++/* ++ * Poulsbo Backlight Interfaces ++ */ ++ ++#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ ++#define BLC_PWM_FREQ_CALC_CONSTANT 32 ++#define MHz 1000000 ++ ++#define PSB_BLC_PWM_PRECISION_FACTOR 10 ++#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE ++#define PSB_BLC_MIN_PWM_REG_FREQ 0x2 ++ ++#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) ++#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) ++ ++static int cdv_brightness; ++static struct backlight_device *cdv_backlight_device; ++ ++static int cdv_get_brightness(struct backlight_device *bd) ++{ ++ /* return locally cached var instead of HW read (due to DPST etc.) */ ++ /* FIXME: ideally return actual value in case firmware fiddled with ++ it */ ++ return cdv_brightness; ++} ++ ++ ++static int cdv_backlight_setup(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ unsigned long core_clock; ++ /* u32 bl_max_freq; */ ++ /* unsigned long value; */ ++ u16 bl_max_freq; ++ uint32_t value; ++ uint32_t blc_pwm_precision_factor; ++ ++ /* get bl_max_freq and pol from dev_priv*/ ++ if (!dev_priv->lvds_bl) { ++ dev_err(dev->dev, "Has no valid LVDS backlight info\n"); ++ return -ENOENT; ++ } ++ bl_max_freq = dev_priv->lvds_bl->freq; ++ blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; ++ ++ core_clock = dev_priv->core_freq; ++ ++ value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; ++ value *= blc_pwm_precision_factor; ++ value /= bl_max_freq; ++ value /= blc_pwm_precision_factor; ++ ++ if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || ++ value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) ++ return -ERANGE; ++ else { ++ /* FIXME */ ++ } ++ return 0; ++} ++ ++static int cdv_set_brightness(struct backlight_device *bd) ++{ ++ int level = bd->props.brightness; ++ ++ /* Percentage 1-100% being valid */ ++ if (level < 1) ++ level = 1; ++ ++ /*cdv_intel_lvds_set_brightness(dev, level); FIXME */ ++ cdv_brightness = level; ++ return 0; ++} ++ ++static const struct backlight_ops cdv_ops = { ++ .get_brightness = cdv_get_brightness, ++ .update_status = cdv_set_brightness, ++}; ++ ++static int cdv_backlight_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int ret; ++ struct backlight_properties props; ++ ++ memset(&props, 0, sizeof(struct backlight_properties)); ++ props.max_brightness = 100; ++ props.type = BACKLIGHT_PLATFORM; ++ ++ cdv_backlight_device = backlight_device_register("psb-bl", ++ NULL, (void *)dev, &cdv_ops, &props); ++ if (IS_ERR(cdv_backlight_device)) ++ return PTR_ERR(cdv_backlight_device); ++ ++ ret = cdv_backlight_setup(dev); ++ if (ret < 0) { ++ backlight_device_unregister(cdv_backlight_device); ++ cdv_backlight_device = NULL; ++ return ret; ++ } ++ cdv_backlight_device->props.brightness = 100; ++ cdv_backlight_device->props.max_brightness = 100; ++ backlight_update_status(cdv_backlight_device); ++ dev_priv->backlight_device = cdv_backlight_device; ++ return 0; ++} ++ ++#endif ++ ++/* ++ * Provide the Cedarview specific chip logic and low level methods ++ * for power management ++ * ++ * FIXME: we need to implement the apm/ospm base management bits ++ * for this and the MID devices. ++ */ ++ ++static inline u32 CDV_MSG_READ32(uint port, uint offset) ++{ ++ int mcr = (0x10<<24) | (port << 16) | (offset << 8); ++ uint32_t ret_val = 0; ++ struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); ++ pci_write_config_dword(pci_root, 0xD0, mcr); ++ pci_read_config_dword(pci_root, 0xD4, &ret_val); ++ pci_dev_put(pci_root); ++ return ret_val; ++} ++ ++static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value) ++{ ++ int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; ++ struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); ++ pci_write_config_dword(pci_root, 0xD4, value); ++ pci_write_config_dword(pci_root, 0xD0, mcr); ++ pci_dev_put(pci_root); ++} ++ ++#define PSB_PM_SSC 0x20 ++#define PSB_PM_SSS 0x30 ++#define PSB_PWRGT_GFX_ON 0x02 ++#define PSB_PWRGT_GFX_OFF 0x01 ++#define PSB_PWRGT_GFX_D0 0x00 ++#define PSB_PWRGT_GFX_D3 0x03 ++ ++static void cdv_init_pm(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 pwr_cnt; ++ int i; ++ ++ dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, ++ PSB_APMBA) & 0xFFFF; ++ dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, ++ PSB_OSPMBA) & 0xFFFF; ++ ++ /* Power status */ ++ pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD); ++ ++ /* Enable the GPU */ ++ pwr_cnt &= ~PSB_PWRGT_GFX_MASK; ++ pwr_cnt |= PSB_PWRGT_GFX_ON; ++ outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD); ++ ++ /* Wait for the GPU power */ ++ for (i = 0; i < 5; i++) { ++ u32 pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS); ++ if ((pwr_sts & PSB_PWRGT_GFX_MASK) == 0) ++ return; ++ udelay(10); ++ } ++ dev_err(dev->dev, "GPU: power management timed out.\n"); ++} ++ ++/** ++ * cdv_save_display_registers - save registers lost on suspend ++ * @dev: our DRM device ++ * ++ * Save the state we need in order to be able to restore the interface ++ * upon resume from suspend ++ */ ++static int cdv_save_display_registers(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_save_area *regs = &dev_priv->regs; ++ struct drm_connector *connector; ++ ++ dev_info(dev->dev, "Saving GPU registers.\n"); ++ ++ pci_read_config_byte(dev->pdev, 0xF4, ®s->cdv.saveLBB); ++ ++ regs->cdv.saveDSPCLK_GATE_D = REG_READ(DSPCLK_GATE_D); ++ regs->cdv.saveRAMCLK_GATE_D = REG_READ(RAMCLK_GATE_D); ++ ++ regs->cdv.saveDSPARB = REG_READ(DSPARB); ++ regs->cdv.saveDSPFW[0] = REG_READ(DSPFW1); ++ regs->cdv.saveDSPFW[1] = REG_READ(DSPFW2); ++ regs->cdv.saveDSPFW[2] = REG_READ(DSPFW3); ++ regs->cdv.saveDSPFW[3] = REG_READ(DSPFW4); ++ regs->cdv.saveDSPFW[4] = REG_READ(DSPFW5); ++ regs->cdv.saveDSPFW[5] = REG_READ(DSPFW6); ++ ++ regs->cdv.saveADPA = REG_READ(ADPA); ++ ++ regs->cdv.savePP_CONTROL = REG_READ(PP_CONTROL); ++ regs->cdv.savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS); ++ regs->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); ++ regs->saveBLC_PWM_CTL2 = REG_READ(BLC_PWM_CTL2); ++ regs->cdv.saveLVDS = REG_READ(LVDS); ++ ++ regs->cdv.savePFIT_CONTROL = REG_READ(PFIT_CONTROL); ++ ++ regs->cdv.savePP_ON_DELAYS = REG_READ(PP_ON_DELAYS); ++ regs->cdv.savePP_OFF_DELAYS = REG_READ(PP_OFF_DELAYS); ++ regs->cdv.savePP_CYCLE = REG_READ(PP_CYCLE); ++ ++ regs->cdv.saveVGACNTRL = REG_READ(VGACNTRL); ++ ++ regs->cdv.saveIER = REG_READ(PSB_INT_ENABLE_R); ++ regs->cdv.saveIMR = REG_READ(PSB_INT_MASK_R); ++ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) ++ connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF); ++ ++ return 0; ++} ++ ++/** ++ * cdv_restore_display_registers - restore lost register state ++ * @dev: our DRM device ++ * ++ * Restore register state that was lost during suspend and resume. ++ * ++ * FIXME: review ++ */ ++static int cdv_restore_display_registers(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_save_area *regs = &dev_priv->regs; ++ struct drm_connector *connector; ++ u32 temp; ++ ++ pci_write_config_byte(dev->pdev, 0xF4, regs->cdv.saveLBB); ++ ++ REG_WRITE(DSPCLK_GATE_D, regs->cdv.saveDSPCLK_GATE_D); ++ REG_WRITE(RAMCLK_GATE_D, regs->cdv.saveRAMCLK_GATE_D); ++ ++ /* BIOS does below anyway */ ++ REG_WRITE(DPIO_CFG, 0); ++ REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N); ++ ++ temp = REG_READ(DPLL_A); ++ if ((temp & DPLL_SYNCLOCK_ENABLE) == 0) { ++ REG_WRITE(DPLL_A, temp | DPLL_SYNCLOCK_ENABLE); ++ REG_READ(DPLL_A); ++ } ++ ++ temp = REG_READ(DPLL_B); ++ if ((temp & DPLL_SYNCLOCK_ENABLE) == 0) { ++ REG_WRITE(DPLL_B, temp | DPLL_SYNCLOCK_ENABLE); ++ REG_READ(DPLL_B); ++ } ++ ++ udelay(500); ++ ++ REG_WRITE(DSPFW1, regs->cdv.saveDSPFW[0]); ++ REG_WRITE(DSPFW2, regs->cdv.saveDSPFW[1]); ++ REG_WRITE(DSPFW3, regs->cdv.saveDSPFW[2]); ++ REG_WRITE(DSPFW4, regs->cdv.saveDSPFW[3]); ++ REG_WRITE(DSPFW5, regs->cdv.saveDSPFW[4]); ++ REG_WRITE(DSPFW6, regs->cdv.saveDSPFW[5]); ++ ++ REG_WRITE(DSPARB, regs->cdv.saveDSPARB); ++ REG_WRITE(ADPA, regs->cdv.saveADPA); ++ ++ REG_WRITE(BLC_PWM_CTL2, regs->saveBLC_PWM_CTL2); ++ REG_WRITE(LVDS, regs->cdv.saveLVDS); ++ REG_WRITE(PFIT_CONTROL, regs->cdv.savePFIT_CONTROL); ++ REG_WRITE(PFIT_PGM_RATIOS, regs->cdv.savePFIT_PGM_RATIOS); ++ REG_WRITE(BLC_PWM_CTL, regs->saveBLC_PWM_CTL); ++ REG_WRITE(PP_ON_DELAYS, regs->cdv.savePP_ON_DELAYS); ++ REG_WRITE(PP_OFF_DELAYS, regs->cdv.savePP_OFF_DELAYS); ++ REG_WRITE(PP_CYCLE, regs->cdv.savePP_CYCLE); ++ REG_WRITE(PP_CONTROL, regs->cdv.savePP_CONTROL); ++ ++ REG_WRITE(VGACNTRL, regs->cdv.saveVGACNTRL); ++ ++ REG_WRITE(PSB_INT_ENABLE_R, regs->cdv.saveIER); ++ REG_WRITE(PSB_INT_MASK_R, regs->cdv.saveIMR); ++ ++ /* Fix arbitration bug */ ++ CDV_MSG_WRITE32(3, 0x30, 0x08027108); ++ ++ drm_mode_config_reset(dev); ++ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) ++ connector->funcs->dpms(connector, DRM_MODE_DPMS_ON); ++ ++ /* Resume the modeset for every activated CRTC */ ++ drm_helper_resume_force_mode(dev); ++ return 0; ++} ++ ++static int cdv_power_down(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 pwr_cnt, pwr_mask, pwr_sts; ++ int tries = 5; ++ ++ pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD); ++ pwr_cnt &= ~PSB_PWRGT_GFX_MASK; ++ pwr_cnt |= PSB_PWRGT_GFX_OFF; ++ pwr_mask = PSB_PWRGT_GFX_MASK; ++ ++ outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD); ++ ++ while (tries--) { ++ pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS); ++ if ((pwr_sts & pwr_mask) == PSB_PWRGT_GFX_D3) ++ return 0; ++ udelay(10); ++ } ++ return 0; ++} ++ ++static int cdv_power_up(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 pwr_cnt, pwr_mask, pwr_sts; ++ int tries = 5; ++ ++ pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD); ++ pwr_cnt &= ~PSB_PWRGT_GFX_MASK; ++ pwr_cnt |= PSB_PWRGT_GFX_ON; ++ pwr_mask = PSB_PWRGT_GFX_MASK; ++ ++ outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD); ++ ++ while (tries--) { ++ pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS); ++ if ((pwr_sts & pwr_mask) == PSB_PWRGT_GFX_D0) ++ return 0; ++ udelay(10); ++ } ++ return 0; ++} ++ ++/* FIXME ? - shared with Poulsbo */ ++static void cdv_get_core_freq(struct drm_device *dev) ++{ ++ uint32_t clock; ++ struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ pci_write_config_dword(pci_root, 0xD0, 0xD0050300); ++ pci_read_config_dword(pci_root, 0xD4, &clock); ++ pci_dev_put(pci_root); ++ ++ switch (clock & 0x07) { ++ case 0: ++ dev_priv->core_freq = 100; ++ break; ++ case 1: ++ dev_priv->core_freq = 133; ++ break; ++ case 2: ++ dev_priv->core_freq = 150; ++ break; ++ case 3: ++ dev_priv->core_freq = 178; ++ break; ++ case 4: ++ dev_priv->core_freq = 200; ++ break; ++ case 5: ++ case 6: ++ case 7: ++ dev_priv->core_freq = 266; ++ default: ++ dev_priv->core_freq = 0; ++ } ++} ++ ++static int cdv_chip_setup(struct drm_device *dev) ++{ ++ cdv_get_core_freq(dev); ++ gma_intel_opregion_init(dev); ++ psb_intel_init_bios(dev); ++ REG_WRITE(PORT_HOTPLUG_EN, 0); ++ REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT)); ++ return 0; ++} ++ ++/* CDV is much like Poulsbo but has MID like SGX offsets and PM */ ++ ++const struct psb_ops cdv_chip_ops = { ++ .name = "GMA3600/3650", ++ .accel_2d = 0, ++ .pipes = 2, ++ .crtcs = 2, ++ .sgx_offset = MRST_SGX_OFFSET, ++ .chip_setup = cdv_chip_setup, ++ ++ .crtc_helper = &cdv_intel_helper_funcs, ++ .crtc_funcs = &cdv_intel_crtc_funcs, ++ ++ .output_init = cdv_output_init, ++ ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ .backlight_init = cdv_backlight_init, ++#endif ++ ++ .init_pm = cdv_init_pm, ++ .save_regs = cdv_save_display_registers, ++ .restore_regs = cdv_restore_display_registers, ++ .power_down = cdv_power_down, ++ .power_up = cdv_power_up, ++}; +diff --git a/drivers/gpu/drm/gma500/cdv_device.h b/drivers/gpu/drm/gma500/cdv_device.h +new file mode 100644 +index 0000000..9561e17 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/cdv_device.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright © 2011 Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs; ++extern const struct drm_crtc_funcs cdv_intel_crtc_funcs; ++extern void cdv_intel_crt_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev); ++extern void cdv_intel_lvds_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev); ++extern void cdv_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, ++ int reg); ++extern struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev, ++ struct drm_crtc *crtc); ++ ++static inline void cdv_intel_wait_for_vblank(struct drm_device *dev) ++{ ++ /* Wait for 20ms, i.e. one cycle at 50hz. */ ++ /* FIXME: msleep ?? */ ++ mdelay(20); ++} ++ ++ +diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c +new file mode 100644 +index 0000000..a71a6cd +--- /dev/null ++++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c +@@ -0,0 +1,340 @@ ++/* ++ * Copyright © 2006-2007 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Eric Anholt ++ */ ++ ++#include ++#include ++ ++#include "intel_bios.h" ++#include "psb_drv.h" ++#include "psb_intel_drv.h" ++#include "psb_intel_reg.h" ++#include "power.h" ++#include "cdv_device.h" ++#include ++ ++ ++static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ u32 temp, reg; ++ reg = ADPA; ++ ++ temp = REG_READ(reg); ++ temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); ++ temp &= ~ADPA_DAC_ENABLE; ++ ++ switch (mode) { ++ case DRM_MODE_DPMS_ON: ++ temp |= ADPA_DAC_ENABLE; ++ break; ++ case DRM_MODE_DPMS_STANDBY: ++ temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE; ++ break; ++ case DRM_MODE_DPMS_SUSPEND: ++ temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE; ++ break; ++ case DRM_MODE_DPMS_OFF: ++ temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE; ++ break; ++ } ++ ++ REG_WRITE(reg, temp); ++} ++ ++static int cdv_intel_crt_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ struct drm_psb_private *dev_priv = connector->dev->dev_private; ++ int max_clock = 0; ++ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ return MODE_NO_DBLESCAN; ++ ++ /* The lowest clock for CDV is 20000KHz */ ++ if (mode->clock < 20000) ++ return MODE_CLOCK_LOW; ++ ++ /* The max clock for CDV is 355 instead of 400 */ ++ max_clock = 355000; ++ if (mode->clock > max_clock) ++ return MODE_CLOCK_HIGH; ++ ++ if (mode->hdisplay > 1680 || mode->vdisplay > 1050) ++ return MODE_PANEL; ++ ++ /* We assume worst case scenario of 32 bpp here, since we don't know */ ++ if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) > ++ dev_priv->vram_stolen_size) ++ return MODE_MEM; ++ ++ return MODE_OK; ++} ++ ++static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ return true; ++} ++ ++static void cdv_intel_crt_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ ++ struct drm_device *dev = encoder->dev; ++ struct drm_crtc *crtc = encoder->crtc; ++ struct psb_intel_crtc *psb_intel_crtc = ++ to_psb_intel_crtc(crtc); ++ int dpll_md_reg; ++ u32 adpa, dpll_md; ++ u32 adpa_reg; ++ ++ if (psb_intel_crtc->pipe == 0) ++ dpll_md_reg = DPLL_A_MD; ++ else ++ dpll_md_reg = DPLL_B_MD; ++ ++ adpa_reg = ADPA; ++ ++ /* ++ * Disable separate mode multiplier used when cloning SDVO to CRT ++ * XXX this needs to be adjusted when we really are cloning ++ */ ++ { ++ dpll_md = REG_READ(dpll_md_reg); ++ REG_WRITE(dpll_md_reg, ++ dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); ++ } ++ ++ adpa = 0; ++ if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) ++ adpa |= ADPA_HSYNC_ACTIVE_HIGH; ++ if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ++ adpa |= ADPA_VSYNC_ACTIVE_HIGH; ++ ++ if (psb_intel_crtc->pipe == 0) ++ adpa |= ADPA_PIPE_A_SELECT; ++ else ++ adpa |= ADPA_PIPE_B_SELECT; ++ ++ REG_WRITE(adpa_reg, adpa); ++} ++ ++ ++/** ++ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. ++ * ++ * \return true if CRT is connected. ++ * \return false if CRT is disconnected. ++ */ ++static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector, ++ bool force) ++{ ++ struct drm_device *dev = connector->dev; ++ u32 hotplug_en; ++ int i, tries = 0, ret = false; ++ u32 adpa_orig; ++ ++ /* disable the DAC when doing the hotplug detection */ ++ ++ adpa_orig = REG_READ(ADPA); ++ ++ REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE)); ++ ++ /* ++ * On a CDV thep, CRT detect sequence need to be done twice ++ * to get a reliable result. ++ */ ++ tries = 2; ++ ++ hotplug_en = REG_READ(PORT_HOTPLUG_EN); ++ hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK); ++ hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; ++ ++ hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; ++ hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; ++ ++ for (i = 0; i < tries ; i++) { ++ unsigned long timeout; ++ /* turn on the FORCE_DETECT */ ++ REG_WRITE(PORT_HOTPLUG_EN, hotplug_en); ++ timeout = jiffies + msecs_to_jiffies(1000); ++ /* wait for FORCE_DETECT to go off */ ++ do { ++ if (!(REG_READ(PORT_HOTPLUG_EN) & ++ CRT_HOTPLUG_FORCE_DETECT)) ++ break; ++ msleep(1); ++ } while (time_after(timeout, jiffies)); ++ } ++ ++ if ((REG_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) != ++ CRT_HOTPLUG_MONITOR_NONE) ++ ret = true; ++ ++ /* Restore the saved ADPA */ ++ REG_WRITE(ADPA, adpa_orig); ++ return ret; ++} ++ ++static enum drm_connector_status cdv_intel_crt_detect( ++ struct drm_connector *connector, bool force) ++{ ++ if (cdv_intel_crt_detect_hotplug(connector, force)) ++ return connector_status_connected; ++ else ++ return connector_status_disconnected; ++} ++ ++static void cdv_intel_crt_destroy(struct drm_connector *connector) ++{ ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ ++ psb_intel_i2c_destroy(psb_intel_encoder->ddc_bus); ++ drm_sysfs_connector_remove(connector); ++ drm_connector_cleanup(connector); ++ kfree(connector); ++} ++ ++static int cdv_intel_crt_get_modes(struct drm_connector *connector) ++{ ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ return psb_intel_ddc_get_modes(connector, &psb_intel_encoder->ddc_bus->adapter); ++} ++ ++static int cdv_intel_crt_set_property(struct drm_connector *connector, ++ struct drm_property *property, ++ uint64_t value) ++{ ++ return 0; ++} ++ ++/* ++ * Routines for controlling stuff on the analog port ++ */ ++ ++static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = { ++ .dpms = cdv_intel_crt_dpms, ++ .mode_fixup = cdv_intel_crt_mode_fixup, ++ .prepare = psb_intel_encoder_prepare, ++ .commit = psb_intel_encoder_commit, ++ .mode_set = cdv_intel_crt_mode_set, ++}; ++ ++static const struct drm_connector_funcs cdv_intel_crt_connector_funcs = { ++ .dpms = drm_helper_connector_dpms, ++ .detect = cdv_intel_crt_detect, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .destroy = cdv_intel_crt_destroy, ++ .set_property = cdv_intel_crt_set_property, ++}; ++ ++static const struct drm_connector_helper_funcs ++ cdv_intel_crt_connector_helper_funcs = { ++ .mode_valid = cdv_intel_crt_mode_valid, ++ .get_modes = cdv_intel_crt_get_modes, ++ .best_encoder = psb_intel_best_encoder, ++}; ++ ++static void cdv_intel_crt_enc_destroy(struct drm_encoder *encoder) ++{ ++ drm_encoder_cleanup(encoder); ++} ++ ++static const struct drm_encoder_funcs cdv_intel_crt_enc_funcs = { ++ .destroy = cdv_intel_crt_enc_destroy, ++}; ++ ++void cdv_intel_crt_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev) ++{ ++ ++ struct psb_intel_connector *psb_intel_connector; ++ struct psb_intel_encoder *psb_intel_encoder; ++ struct drm_connector *connector; ++ struct drm_encoder *encoder; ++ ++ u32 i2c_reg; ++ ++ psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); ++ if (!psb_intel_encoder) ++ return; ++ ++ psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL); ++ if (!psb_intel_connector) ++ goto failed_connector; ++ ++ connector = &psb_intel_connector->base; ++ drm_connector_init(dev, connector, ++ &cdv_intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); ++ ++ encoder = &psb_intel_encoder->base; ++ drm_encoder_init(dev, encoder, ++ &cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC); ++ ++ psb_intel_connector_attach_encoder(psb_intel_connector, ++ psb_intel_encoder); ++ ++ /* Set up the DDC bus. */ ++ i2c_reg = GPIOA; ++ /* Remove the following code for CDV */ ++ /* ++ if (dev_priv->crt_ddc_bus != 0) ++ i2c_reg = dev_priv->crt_ddc_bus; ++ }*/ ++ psb_intel_encoder->ddc_bus = psb_intel_i2c_create(dev, ++ i2c_reg, "CRTDDC_A"); ++ if (!psb_intel_encoder->ddc_bus) { ++ dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " ++ "failed.\n"); ++ goto failed_ddc; ++ } ++ ++ psb_intel_encoder->type = INTEL_OUTPUT_ANALOG; ++ /* ++ psb_intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT); ++ psb_intel_output->crtc_mask = (1 << 0) | (1 << 1); ++ */ ++ connector->interlace_allowed = 0; ++ connector->doublescan_allowed = 0; ++ ++ drm_encoder_helper_add(encoder, &cdv_intel_crt_helper_funcs); ++ drm_connector_helper_add(connector, ++ &cdv_intel_crt_connector_helper_funcs); ++ ++ drm_sysfs_connector_add(connector); ++ ++ return; ++failed_ddc: ++ drm_encoder_cleanup(&psb_intel_encoder->base); ++ drm_connector_cleanup(&psb_intel_connector->base); ++ kfree(psb_intel_connector); ++failed_connector: ++ kfree(psb_intel_encoder); ++ return; ++} +diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c +new file mode 100644 +index 0000000..1ee297b +--- /dev/null ++++ b/drivers/gpu/drm/gma500/cdv_intel_display.c +@@ -0,0 +1,1473 @@ ++/* ++ * Copyright © 2006-2011 Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: ++ * Eric Anholt ++ */ ++ ++#include ++#include ++ ++#include ++#include "framebuffer.h" ++#include "psb_drv.h" ++#include "psb_intel_drv.h" ++#include "psb_intel_reg.h" ++#include "psb_intel_display.h" ++#include "power.h" ++#include "cdv_device.h" ++ ++ ++struct cdv_intel_range_t { ++ int min, max; ++}; ++ ++struct cdv_intel_p2_t { ++ int dot_limit; ++ int p2_slow, p2_fast; ++}; ++ ++struct cdv_intel_clock_t { ++ /* given values */ ++ int n; ++ int m1, m2; ++ int p1, p2; ++ /* derived values */ ++ int dot; ++ int vco; ++ int m; ++ int p; ++}; ++ ++#define INTEL_P2_NUM 2 ++ ++struct cdv_intel_limit_t { ++ struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1; ++ struct cdv_intel_p2_t p2; ++}; ++ ++#define CDV_LIMIT_SINGLE_LVDS_96 0 ++#define CDV_LIMIT_SINGLE_LVDS_100 1 ++#define CDV_LIMIT_DAC_HDMI_27 2 ++#define CDV_LIMIT_DAC_HDMI_96 3 ++ ++static const struct cdv_intel_limit_t cdv_intel_limits[] = { ++ { /* CDV_SIGNLE_LVDS_96MHz */ ++ .dot = {.min = 20000, .max = 115500}, ++ .vco = {.min = 1800000, .max = 3600000}, ++ .n = {.min = 2, .max = 6}, ++ .m = {.min = 60, .max = 160}, ++ .m1 = {.min = 0, .max = 0}, ++ .m2 = {.min = 58, .max = 158}, ++ .p = {.min = 28, .max = 140}, ++ .p1 = {.min = 2, .max = 10}, ++ .p2 = {.dot_limit = 200000, ++ .p2_slow = 14, .p2_fast = 14}, ++ }, ++ { /* CDV_SINGLE_LVDS_100MHz */ ++ .dot = {.min = 20000, .max = 115500}, ++ .vco = {.min = 1800000, .max = 3600000}, ++ .n = {.min = 2, .max = 6}, ++ .m = {.min = 60, .max = 160}, ++ .m1 = {.min = 0, .max = 0}, ++ .m2 = {.min = 58, .max = 158}, ++ .p = {.min = 28, .max = 140}, ++ .p1 = {.min = 2, .max = 10}, ++ /* The single-channel range is 25-112Mhz, and dual-channel ++ * is 80-224Mhz. Prefer single channel as much as possible. ++ */ ++ .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14}, ++ }, ++ { /* CDV_DAC_HDMI_27MHz */ ++ .dot = {.min = 20000, .max = 400000}, ++ .vco = {.min = 1809000, .max = 3564000}, ++ .n = {.min = 1, .max = 1}, ++ .m = {.min = 67, .max = 132}, ++ .m1 = {.min = 0, .max = 0}, ++ .m2 = {.min = 65, .max = 130}, ++ .p = {.min = 5, .max = 90}, ++ .p1 = {.min = 1, .max = 9}, ++ .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, ++ }, ++ { /* CDV_DAC_HDMI_96MHz */ ++ .dot = {.min = 20000, .max = 400000}, ++ .vco = {.min = 1800000, .max = 3600000}, ++ .n = {.min = 2, .max = 6}, ++ .m = {.min = 60, .max = 160}, ++ .m1 = {.min = 0, .max = 0}, ++ .m2 = {.min = 58, .max = 158}, ++ .p = {.min = 5, .max = 100}, ++ .p1 = {.min = 1, .max = 10}, ++ .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, ++ }, ++}; ++ ++#define _wait_for(COND, MS, W) ({ \ ++ unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ ++ int ret__ = 0; \ ++ while (!(COND)) { \ ++ if (time_after(jiffies, timeout__)) { \ ++ ret__ = -ETIMEDOUT; \ ++ break; \ ++ } \ ++ if (W && !in_dbg_master()) \ ++ msleep(W); \ ++ } \ ++ ret__; \ ++}) ++ ++#define wait_for(COND, MS) _wait_for(COND, MS, 1) ++ ++ ++static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val) ++{ ++ int ret; ++ ++ ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); ++ if (ret) { ++ DRM_ERROR("timeout waiting for SB to idle before read\n"); ++ return ret; ++ } ++ ++ REG_WRITE(SB_ADDR, reg); ++ REG_WRITE(SB_PCKT, ++ SET_FIELD(SB_OPCODE_READ, SB_OPCODE) | ++ SET_FIELD(SB_DEST_DPLL, SB_DEST) | ++ SET_FIELD(0xf, SB_BYTE_ENABLE)); ++ ++ ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); ++ if (ret) { ++ DRM_ERROR("timeout waiting for SB to idle after read\n"); ++ return ret; ++ } ++ ++ *val = REG_READ(SB_DATA); ++ ++ return 0; ++} ++ ++static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val) ++{ ++ int ret; ++ static bool dpio_debug = true; ++ u32 temp; ++ ++ if (dpio_debug) { ++ if (cdv_sb_read(dev, reg, &temp) == 0) ++ DRM_DEBUG_KMS("0x%08x: 0x%08x (before)\n", reg, temp); ++ DRM_DEBUG_KMS("0x%08x: 0x%08x\n", reg, val); ++ } ++ ++ ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); ++ if (ret) { ++ DRM_ERROR("timeout waiting for SB to idle before write\n"); ++ return ret; ++ } ++ ++ REG_WRITE(SB_ADDR, reg); ++ REG_WRITE(SB_DATA, val); ++ REG_WRITE(SB_PCKT, ++ SET_FIELD(SB_OPCODE_WRITE, SB_OPCODE) | ++ SET_FIELD(SB_DEST_DPLL, SB_DEST) | ++ SET_FIELD(0xf, SB_BYTE_ENABLE)); ++ ++ ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); ++ if (ret) { ++ DRM_ERROR("timeout waiting for SB to idle after write\n"); ++ return ret; ++ } ++ ++ if (dpio_debug) { ++ if (cdv_sb_read(dev, reg, &temp) == 0) ++ DRM_DEBUG_KMS("0x%08x: 0x%08x (after)\n", reg, temp); ++ } ++ ++ return 0; ++} ++ ++/* Reset the DPIO configuration register. The BIOS does this at every ++ * mode set. ++ */ ++static void cdv_sb_reset(struct drm_device *dev) ++{ ++ ++ REG_WRITE(DPIO_CFG, 0); ++ REG_READ(DPIO_CFG); ++ REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N); ++} ++ ++/* Unlike most Intel display engines, on Cedarview the DPLL registers ++ * are behind this sideband bus. They must be programmed while the ++ * DPLL reference clock is on in the DPLL control register, but before ++ * the DPLL is enabled in the DPLL control register. ++ */ ++static int ++cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, ++ struct cdv_intel_clock_t *clock) ++{ ++ struct psb_intel_crtc *psb_crtc = ++ to_psb_intel_crtc(crtc); ++ int pipe = psb_crtc->pipe; ++ u32 m, n_vco, p; ++ int ret = 0; ++ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; ++ u32 ref_value; ++ ++ cdv_sb_reset(dev); ++ ++ if ((REG_READ(dpll_reg) & DPLL_SYNCLOCK_ENABLE) == 0) { ++ DRM_ERROR("Attempting to set DPLL with refclk disabled\n"); ++ return -EBUSY; ++ } ++ ++ /* Follow the BIOS and write the REF/SFR Register. Hardcoded value */ ++ ref_value = 0x68A701; ++ ++ cdv_sb_write(dev, SB_REF_SFR(pipe), ref_value); ++ ++ /* We don't know what the other fields of these regs are, so ++ * leave them in place. ++ */ ++ ret = cdv_sb_read(dev, SB_M(pipe), &m); ++ if (ret) ++ return ret; ++ m &= ~SB_M_DIVIDER_MASK; ++ m |= ((clock->m2) << SB_M_DIVIDER_SHIFT); ++ ret = cdv_sb_write(dev, SB_M(pipe), m); ++ if (ret) ++ return ret; ++ ++ ret = cdv_sb_read(dev, SB_N_VCO(pipe), &n_vco); ++ if (ret) ++ return ret; ++ ++ /* Follow the BIOS to program the N_DIVIDER REG */ ++ n_vco &= 0xFFFF; ++ n_vco |= 0x107; ++ n_vco &= ~(SB_N_VCO_SEL_MASK | ++ SB_N_DIVIDER_MASK | ++ SB_N_CB_TUNE_MASK); ++ ++ n_vco |= ((clock->n) << SB_N_DIVIDER_SHIFT); ++ ++ if (clock->vco < 2250000) { ++ n_vco |= (2 << SB_N_CB_TUNE_SHIFT); ++ n_vco |= (0 << SB_N_VCO_SEL_SHIFT); ++ } else if (clock->vco < 2750000) { ++ n_vco |= (1 << SB_N_CB_TUNE_SHIFT); ++ n_vco |= (1 << SB_N_VCO_SEL_SHIFT); ++ } else if (clock->vco < 3300000) { ++ n_vco |= (0 << SB_N_CB_TUNE_SHIFT); ++ n_vco |= (2 << SB_N_VCO_SEL_SHIFT); ++ } else { ++ n_vco |= (0 << SB_N_CB_TUNE_SHIFT); ++ n_vco |= (3 << SB_N_VCO_SEL_SHIFT); ++ } ++ ++ ret = cdv_sb_write(dev, SB_N_VCO(pipe), n_vco); ++ if (ret) ++ return ret; ++ ++ ret = cdv_sb_read(dev, SB_P(pipe), &p); ++ if (ret) ++ return ret; ++ p &= ~(SB_P2_DIVIDER_MASK | SB_P1_DIVIDER_MASK); ++ p |= SET_FIELD(clock->p1, SB_P1_DIVIDER); ++ switch (clock->p2) { ++ case 5: ++ p |= SET_FIELD(SB_P2_5, SB_P2_DIVIDER); ++ break; ++ case 10: ++ p |= SET_FIELD(SB_P2_10, SB_P2_DIVIDER); ++ break; ++ case 14: ++ p |= SET_FIELD(SB_P2_14, SB_P2_DIVIDER); ++ break; ++ case 7: ++ p |= SET_FIELD(SB_P2_7, SB_P2_DIVIDER); ++ break; ++ default: ++ DRM_ERROR("Bad P2 clock: %d\n", clock->p2); ++ return -EINVAL; ++ } ++ ret = cdv_sb_write(dev, SB_P(pipe), p); ++ if (ret) ++ return ret; ++ ++ /* always Program the Lane Register for the Pipe A*/ ++ if (pipe == 0) { ++ /* Program the Lane0/1 for HDMI B */ ++ u32 lane_reg, lane_value; ++ ++ lane_reg = PSB_LANE0; ++ cdv_sb_read(dev, lane_reg, &lane_value); ++ lane_value &= ~(LANE_PLL_MASK); ++ lane_value |= LANE_PLL_ENABLE; ++ cdv_sb_write(dev, lane_reg, lane_value); ++ ++ lane_reg = PSB_LANE1; ++ cdv_sb_read(dev, lane_reg, &lane_value); ++ lane_value &= ~(LANE_PLL_MASK); ++ lane_value |= LANE_PLL_ENABLE; ++ cdv_sb_write(dev, lane_reg, lane_value); ++ ++ /* Program the Lane2/3 for HDMI C */ ++ lane_reg = PSB_LANE2; ++ cdv_sb_read(dev, lane_reg, &lane_value); ++ lane_value &= ~(LANE_PLL_MASK); ++ lane_value |= LANE_PLL_ENABLE; ++ cdv_sb_write(dev, lane_reg, lane_value); ++ ++ lane_reg = PSB_LANE3; ++ cdv_sb_read(dev, lane_reg, &lane_value); ++ lane_value &= ~(LANE_PLL_MASK); ++ lane_value |= LANE_PLL_ENABLE; ++ cdv_sb_write(dev, lane_reg, lane_value); ++ } ++ ++ return 0; ++} ++ ++/* ++ * Returns whether any encoder on the specified pipe is of the specified type ++ */ ++static bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_mode_config *mode_config = &dev->mode_config; ++ struct drm_connector *l_entry; ++ ++ list_for_each_entry(l_entry, &mode_config->connector_list, head) { ++ if (l_entry->encoder && l_entry->encoder->crtc == crtc) { ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(l_entry); ++ if (psb_intel_encoder->type == type) ++ return true; ++ } ++ } ++ return false; ++} ++ ++static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc, ++ int refclk) ++{ ++ const struct cdv_intel_limit_t *limit; ++ if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { ++ /* ++ * Now only single-channel LVDS is supported on CDV. If it is ++ * incorrect, please add the dual-channel LVDS. ++ */ ++ if (refclk == 96000) ++ limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96]; ++ else ++ limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100]; ++ } else { ++ if (refclk == 27000) ++ limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27]; ++ else ++ limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_96]; ++ } ++ return limit; ++} ++ ++/* m1 is reserved as 0 in CDV, n is a ring counter */ ++static void cdv_intel_clock(struct drm_device *dev, ++ int refclk, struct cdv_intel_clock_t *clock) ++{ ++ clock->m = clock->m2 + 2; ++ clock->p = clock->p1 * clock->p2; ++ clock->vco = (refclk * clock->m) / clock->n; ++ clock->dot = clock->vco / clock->p; ++} ++ ++ ++#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } ++static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc, ++ const struct cdv_intel_limit_t *limit, ++ struct cdv_intel_clock_t *clock) ++{ ++ if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) ++ INTELPllInvalid("p1 out of range\n"); ++ if (clock->p < limit->p.min || limit->p.max < clock->p) ++ INTELPllInvalid("p out of range\n"); ++ /* unnecessary to check the range of m(m1/M2)/n again */ ++ if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) ++ INTELPllInvalid("vco out of range\n"); ++ /* XXX: We may need to be checking "Dot clock" ++ * depending on the multiplier, connector, etc., ++ * rather than just a single range. ++ */ ++ if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) ++ INTELPllInvalid("dot out of range\n"); ++ ++ return true; ++} ++ ++static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target, ++ int refclk, ++ struct cdv_intel_clock_t *best_clock) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct cdv_intel_clock_t clock; ++ const struct cdv_intel_limit_t *limit = cdv_intel_limit(crtc, refclk); ++ int err = target; ++ ++ ++ if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && ++ (REG_READ(LVDS) & LVDS_PORT_EN) != 0) { ++ /* ++ * For LVDS, if the panel is on, just rely on its current ++ * settings for dual-channel. We haven't figured out how to ++ * reliably set up different single/dual channel state, if we ++ * even can. ++ */ ++ if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) == ++ LVDS_CLKB_POWER_UP) ++ clock.p2 = limit->p2.p2_fast; ++ else ++ clock.p2 = limit->p2.p2_slow; ++ } else { ++ if (target < limit->p2.dot_limit) ++ clock.p2 = limit->p2.p2_slow; ++ else ++ clock.p2 = limit->p2.p2_fast; ++ } ++ ++ memset(best_clock, 0, sizeof(*best_clock)); ++ clock.m1 = 0; ++ /* m1 is reserved as 0 in CDV, n is a ring counter. ++ So skip the m1 loop */ ++ for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) { ++ for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; ++ clock.m2++) { ++ for (clock.p1 = limit->p1.min; ++ clock.p1 <= limit->p1.max; ++ clock.p1++) { ++ int this_err; ++ ++ cdv_intel_clock(dev, refclk, &clock); ++ ++ if (!cdv_intel_PLL_is_valid(crtc, ++ limit, &clock)) ++ continue; ++ ++ this_err = abs(clock.dot - target); ++ if (this_err < err) { ++ *best_clock = clock; ++ err = this_err; ++ } ++ } ++ } ++ } ++ ++ return err != target; ++} ++ ++static int cdv_intel_pipe_set_base(struct drm_crtc *crtc, ++ int x, int y, struct drm_framebuffer *old_fb) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); ++ int pipe = psb_intel_crtc->pipe; ++ unsigned long start, offset; ++ int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); ++ int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); ++ int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; ++ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; ++ u32 dspcntr; ++ int ret = 0; ++ ++ if (!gma_power_begin(dev, true)) ++ return 0; ++ ++ /* no fb bound */ ++ if (!crtc->fb) { ++ dev_err(dev->dev, "No FB bound\n"); ++ goto psb_intel_pipe_cleaner; ++ } ++ ++ ++ /* We are displaying this buffer, make sure it is actually loaded ++ into the GTT */ ++ ret = psb_gtt_pin(psbfb->gtt); ++ if (ret < 0) ++ goto psb_intel_pipe_set_base_exit; ++ start = psbfb->gtt->offset; ++ offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); ++ ++ REG_WRITE(dspstride, crtc->fb->pitches[0]); ++ ++ dspcntr = REG_READ(dspcntr_reg); ++ dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; ++ ++ switch (crtc->fb->bits_per_pixel) { ++ case 8: ++ dspcntr |= DISPPLANE_8BPP; ++ break; ++ case 16: ++ if (crtc->fb->depth == 15) ++ dspcntr |= DISPPLANE_15_16BPP; ++ else ++ dspcntr |= DISPPLANE_16BPP; ++ break; ++ case 24: ++ case 32: ++ dspcntr |= DISPPLANE_32BPP_NO_ALPHA; ++ break; ++ default: ++ dev_err(dev->dev, "Unknown color depth\n"); ++ ret = -EINVAL; ++ goto psb_intel_pipe_set_base_exit; ++ } ++ REG_WRITE(dspcntr_reg, dspcntr); ++ ++ dev_dbg(dev->dev, ++ "Writing base %08lX %08lX %d %d\n", start, offset, x, y); ++ ++ REG_WRITE(dspbase, offset); ++ REG_READ(dspbase); ++ REG_WRITE(dspsurf, start); ++ REG_READ(dspsurf); ++ ++psb_intel_pipe_cleaner: ++ /* If there was a previous display we can now unpin it */ ++ if (old_fb) ++ psb_gtt_unpin(to_psb_fb(old_fb)->gtt); ++ ++psb_intel_pipe_set_base_exit: ++ gma_power_end(dev); ++ return ret; ++} ++ ++/** ++ * Sets the power management mode of the pipe and plane. ++ * ++ * This code should probably grow support for turning the cursor off and back ++ * on appropriately at the same time as we're turning the pipe off/on. ++ */ ++static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; ++ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; ++ int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; ++ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; ++ u32 temp; ++ ++ /* XXX: When our outputs are all unaware of DPMS modes other than off ++ * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. ++ */ ++ switch (mode) { ++ case DRM_MODE_DPMS_ON: ++ case DRM_MODE_DPMS_STANDBY: ++ case DRM_MODE_DPMS_SUSPEND: ++ /* Enable the DPLL */ ++ temp = REG_READ(dpll_reg); ++ if ((temp & DPLL_VCO_ENABLE) == 0) { ++ REG_WRITE(dpll_reg, temp); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ } ++ ++ /* Jim Bish - switch plan and pipe per scott */ ++ /* Enable the plane */ ++ temp = REG_READ(dspcntr_reg); ++ if ((temp & DISPLAY_PLANE_ENABLE) == 0) { ++ REG_WRITE(dspcntr_reg, ++ temp | DISPLAY_PLANE_ENABLE); ++ /* Flush the plane changes */ ++ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); ++ } ++ ++ udelay(150); ++ ++ /* Enable the pipe */ ++ temp = REG_READ(pipeconf_reg); ++ if ((temp & PIPEACONF_ENABLE) == 0) ++ REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); ++ ++ psb_intel_crtc_load_lut(crtc); ++ ++ /* Give the overlay scaler a chance to enable ++ * if it's on this pipe */ ++ /* psb_intel_crtc_dpms_video(crtc, true); TODO */ ++ break; ++ case DRM_MODE_DPMS_OFF: ++ /* Give the overlay scaler a chance to disable ++ * if it's on this pipe */ ++ /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ ++ ++ /* Disable the VGA plane that we never use */ ++ REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); ++ ++ /* Jim Bish - changed pipe/plane here as well. */ ++ ++ /* Wait for vblank for the disable to take effect */ ++ cdv_intel_wait_for_vblank(dev); ++ ++ /* Next, disable display pipes */ ++ temp = REG_READ(pipeconf_reg); ++ if ((temp & PIPEACONF_ENABLE) != 0) { ++ REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); ++ REG_READ(pipeconf_reg); ++ } ++ ++ /* Wait for vblank for the disable to take effect. */ ++ cdv_intel_wait_for_vblank(dev); ++ ++ udelay(150); ++ ++ /* Disable display plane */ ++ temp = REG_READ(dspcntr_reg); ++ if ((temp & DISPLAY_PLANE_ENABLE) != 0) { ++ REG_WRITE(dspcntr_reg, ++ temp & ~DISPLAY_PLANE_ENABLE); ++ /* Flush the plane changes */ ++ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); ++ REG_READ(dspbase_reg); ++ } ++ ++ temp = REG_READ(dpll_reg); ++ if ((temp & DPLL_VCO_ENABLE) != 0) { ++ REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ } ++ ++ /* Wait for the clocks to turn off. */ ++ udelay(150); ++ break; ++ } ++ /*Set FIFO Watermarks*/ ++ REG_WRITE(DSPARB, 0x3F3E); ++} ++ ++static void cdv_intel_crtc_prepare(struct drm_crtc *crtc) ++{ ++ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; ++ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); ++} ++ ++static void cdv_intel_crtc_commit(struct drm_crtc *crtc) ++{ ++ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; ++ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); ++} ++ ++static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ return true; ++} ++ ++ ++/** ++ * Return the pipe currently connected to the panel fitter, ++ * or -1 if the panel fitter is not present or not in use ++ */ ++static int cdv_intel_panel_fitter_pipe(struct drm_device *dev) ++{ ++ u32 pfit_control; ++ ++ pfit_control = REG_READ(PFIT_CONTROL); ++ ++ /* See if the panel fitter is in use */ ++ if ((pfit_control & PFIT_ENABLE) == 0) ++ return -1; ++ return (pfit_control >> 29) & 0x3; ++} ++ ++static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode, ++ int x, int y, ++ struct drm_framebuffer *old_fb) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; ++ int dpll_md_reg = (psb_intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; ++ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; ++ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; ++ int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; ++ int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; ++ int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; ++ int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; ++ int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; ++ int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; ++ int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; ++ int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; ++ int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; ++ int refclk; ++ struct cdv_intel_clock_t clock; ++ u32 dpll = 0, dspcntr, pipeconf; ++ bool ok; ++ bool is_crt = false, is_lvds = false, is_tv = false; ++ bool is_hdmi = false; ++ struct drm_mode_config *mode_config = &dev->mode_config; ++ struct drm_connector *connector; ++ ++ list_for_each_entry(connector, &mode_config->connector_list, head) { ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ ++ if (!connector->encoder ++ || connector->encoder->crtc != crtc) ++ continue; ++ ++ switch (psb_intel_encoder->type) { ++ case INTEL_OUTPUT_LVDS: ++ is_lvds = true; ++ break; ++ case INTEL_OUTPUT_TVOUT: ++ is_tv = true; ++ break; ++ case INTEL_OUTPUT_ANALOG: ++ is_crt = true; ++ break; ++ case INTEL_OUTPUT_HDMI: ++ is_hdmi = true; ++ break; ++ } ++ } ++ ++ refclk = 96000; ++ ++ /* Hack selection about ref clk for CRT */ ++ /* Select 27MHz as the reference clk for HDMI */ ++ if (is_crt || is_hdmi) ++ refclk = 27000; ++ ++ drm_mode_debug_printmodeline(adjusted_mode); ++ ++ ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, ++ &clock); ++ if (!ok) { ++ dev_err(dev->dev, "Couldn't find PLL settings for mode!\n"); ++ return 0; ++ } ++ ++ dpll = DPLL_VGA_MODE_DIS; ++ if (is_tv) { ++ /* XXX: just matching BIOS for now */ ++/* dpll |= PLL_REF_INPUT_TVCLKINBC; */ ++ dpll |= 3; ++ } ++ dpll |= PLL_REF_INPUT_DREFCLK; ++ ++ dpll |= DPLL_SYNCLOCK_ENABLE; ++ dpll |= DPLL_VGA_MODE_DIS; ++ if (is_lvds) ++ dpll |= DPLLB_MODE_LVDS; ++ else ++ dpll |= DPLLB_MODE_DAC_SERIAL; ++ /* dpll |= (2 << 11); */ ++ ++ /* setup pipeconf */ ++ pipeconf = REG_READ(pipeconf_reg); ++ ++ /* Set up the display plane register */ ++ dspcntr = DISPPLANE_GAMMA_ENABLE; ++ ++ if (pipe == 0) ++ dspcntr |= DISPPLANE_SEL_PIPE_A; ++ else ++ dspcntr |= DISPPLANE_SEL_PIPE_B; ++ ++ dspcntr |= DISPLAY_PLANE_ENABLE; ++ pipeconf |= PIPEACONF_ENABLE; ++ ++ REG_WRITE(dpll_reg, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE); ++ REG_READ(dpll_reg); ++ ++ cdv_dpll_set_clock_cdv(dev, crtc, &clock); ++ ++ udelay(150); ++ ++ ++ /* The LVDS pin pair needs to be on before the DPLLs are enabled. ++ * This is an exception to the general rule that mode_set doesn't turn ++ * things on. ++ */ ++ if (is_lvds) { ++ u32 lvds = REG_READ(LVDS); ++ ++ lvds |= ++ LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | ++ LVDS_PIPEB_SELECT; ++ /* Set the B0-B3 data pairs corresponding to ++ * whether we're going to ++ * set the DPLLs for dual-channel mode or not. ++ */ ++ if (clock.p2 == 7) ++ lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; ++ else ++ lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); ++ ++ /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) ++ * appropriately here, but we need to look more ++ * thoroughly into how panels behave in the two modes. ++ */ ++ ++ REG_WRITE(LVDS, lvds); ++ REG_READ(LVDS); ++ } ++ ++ dpll |= DPLL_VCO_ENABLE; ++ ++ /* Disable the panel fitter if it was on our pipe */ ++ if (cdv_intel_panel_fitter_pipe(dev) == pipe) ++ REG_WRITE(PFIT_CONTROL, 0); ++ ++ DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); ++ drm_mode_debug_printmodeline(mode); ++ ++ REG_WRITE(dpll_reg, ++ (REG_READ(dpll_reg) & ~DPLL_LOCK) | DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); /* 42 usec w/o calibration, 110 with. rounded up. */ ++ ++ if (!(REG_READ(dpll_reg) & DPLL_LOCK)) { ++ dev_err(dev->dev, "Failed to get DPLL lock\n"); ++ return -EBUSY; ++ } ++ ++ { ++ int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; ++ REG_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); ++ } ++ ++ REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | ++ ((adjusted_mode->crtc_htotal - 1) << 16)); ++ REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ++ ((adjusted_mode->crtc_hblank_end - 1) << 16)); ++ REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ++ ((adjusted_mode->crtc_hsync_end - 1) << 16)); ++ REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ++ ((adjusted_mode->crtc_vtotal - 1) << 16)); ++ REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ++ ((adjusted_mode->crtc_vblank_end - 1) << 16)); ++ REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ++ ((adjusted_mode->crtc_vsync_end - 1) << 16)); ++ /* pipesrc and dspsize control the size that is scaled from, ++ * which should always be the user's requested size. ++ */ ++ REG_WRITE(dspsize_reg, ++ ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); ++ REG_WRITE(dsppos_reg, 0); ++ REG_WRITE(pipesrc_reg, ++ ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); ++ REG_WRITE(pipeconf_reg, pipeconf); ++ REG_READ(pipeconf_reg); ++ ++ cdv_intel_wait_for_vblank(dev); ++ ++ REG_WRITE(dspcntr_reg, dspcntr); ++ ++ /* Flush the plane changes */ ++ { ++ struct drm_crtc_helper_funcs *crtc_funcs = ++ crtc->helper_private; ++ crtc_funcs->mode_set_base(crtc, x, y, old_fb); ++ } ++ ++ cdv_intel_wait_for_vblank(dev); ++ ++ return 0; ++} ++ ++/** Loads the palette/gamma unit for the CRTC with the prepared values */ ++static void cdv_intel_crtc_load_lut(struct drm_crtc *crtc) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *)dev->dev_private; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int palreg = PALETTE_A; ++ int i; ++ ++ /* The clocks have to be on to load the palette. */ ++ if (!crtc->enabled) ++ return; ++ ++ switch (psb_intel_crtc->pipe) { ++ case 0: ++ break; ++ case 1: ++ palreg = PALETTE_B; ++ break; ++ case 2: ++ palreg = PALETTE_C; ++ break; ++ default: ++ dev_err(dev->dev, "Illegal Pipe Number.\n"); ++ return; ++ } ++ ++ if (gma_power_begin(dev, false)) { ++ for (i = 0; i < 256; i++) { ++ REG_WRITE(palreg + 4 * i, ++ ((psb_intel_crtc->lut_r[i] + ++ psb_intel_crtc->lut_adj[i]) << 16) | ++ ((psb_intel_crtc->lut_g[i] + ++ psb_intel_crtc->lut_adj[i]) << 8) | ++ (psb_intel_crtc->lut_b[i] + ++ psb_intel_crtc->lut_adj[i])); ++ } ++ gma_power_end(dev); ++ } else { ++ for (i = 0; i < 256; i++) { ++ dev_priv->regs.psb.save_palette_a[i] = ++ ((psb_intel_crtc->lut_r[i] + ++ psb_intel_crtc->lut_adj[i]) << 16) | ++ ((psb_intel_crtc->lut_g[i] + ++ psb_intel_crtc->lut_adj[i]) << 8) | ++ (psb_intel_crtc->lut_b[i] + ++ psb_intel_crtc->lut_adj[i]); ++ } ++ ++ } ++} ++ ++/** ++ * Save HW states of giving crtc ++ */ ++static void cdv_intel_crtc_save(struct drm_crtc *crtc) ++{ ++ struct drm_device *dev = crtc->dev; ++ /* struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *)dev->dev_private; */ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; ++ int pipeA = (psb_intel_crtc->pipe == 0); ++ uint32_t paletteReg; ++ int i; ++ ++ if (!crtc_state) { ++ dev_dbg(dev->dev, "No CRTC state found\n"); ++ return; ++ } ++ ++ crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR); ++ crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF); ++ crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC); ++ crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0); ++ crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1); ++ crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B); ++ crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B); ++ crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B); ++ crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B); ++ crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B); ++ crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B); ++ crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B); ++ crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE); ++ ++ /*NOTE: DSPSIZE DSPPOS only for psb*/ ++ crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE); ++ crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS); ++ ++ crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE); ++ ++ DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n", ++ crtc_state->saveDSPCNTR, ++ crtc_state->savePIPECONF, ++ crtc_state->savePIPESRC, ++ crtc_state->saveFP0, ++ crtc_state->saveFP1, ++ crtc_state->saveDPLL, ++ crtc_state->saveHTOTAL, ++ crtc_state->saveHBLANK, ++ crtc_state->saveHSYNC, ++ crtc_state->saveVTOTAL, ++ crtc_state->saveVBLANK, ++ crtc_state->saveVSYNC, ++ crtc_state->saveDSPSTRIDE, ++ crtc_state->saveDSPSIZE, ++ crtc_state->saveDSPPOS, ++ crtc_state->saveDSPBASE ++ ); ++ ++ paletteReg = pipeA ? PALETTE_A : PALETTE_B; ++ for (i = 0; i < 256; ++i) ++ crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2)); ++} ++ ++/** ++ * Restore HW states of giving crtc ++ */ ++static void cdv_intel_crtc_restore(struct drm_crtc *crtc) ++{ ++ struct drm_device *dev = crtc->dev; ++ /* struct drm_psb_private * dev_priv = ++ (struct drm_psb_private *)dev->dev_private; */ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; ++ /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */ ++ int pipeA = (psb_intel_crtc->pipe == 0); ++ uint32_t paletteReg; ++ int i; ++ ++ if (!crtc_state) { ++ dev_dbg(dev->dev, "No crtc state\n"); ++ return; ++ } ++ ++ DRM_DEBUG( ++ "current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n", ++ REG_READ(pipeA ? DSPACNTR : DSPBCNTR), ++ REG_READ(pipeA ? PIPEACONF : PIPEBCONF), ++ REG_READ(pipeA ? PIPEASRC : PIPEBSRC), ++ REG_READ(pipeA ? FPA0 : FPB0), ++ REG_READ(pipeA ? FPA1 : FPB1), ++ REG_READ(pipeA ? DPLL_A : DPLL_B), ++ REG_READ(pipeA ? HTOTAL_A : HTOTAL_B), ++ REG_READ(pipeA ? HBLANK_A : HBLANK_B), ++ REG_READ(pipeA ? HSYNC_A : HSYNC_B), ++ REG_READ(pipeA ? VTOTAL_A : VTOTAL_B), ++ REG_READ(pipeA ? VBLANK_A : VBLANK_B), ++ REG_READ(pipeA ? VSYNC_A : VSYNC_B), ++ REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE), ++ REG_READ(pipeA ? DSPASIZE : DSPBSIZE), ++ REG_READ(pipeA ? DSPAPOS : DSPBPOS), ++ REG_READ(pipeA ? DSPABASE : DSPBBASE) ++ ); ++ ++ DRM_DEBUG( ++ "saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n", ++ crtc_state->saveDSPCNTR, ++ crtc_state->savePIPECONF, ++ crtc_state->savePIPESRC, ++ crtc_state->saveFP0, ++ crtc_state->saveFP1, ++ crtc_state->saveDPLL, ++ crtc_state->saveHTOTAL, ++ crtc_state->saveHBLANK, ++ crtc_state->saveHSYNC, ++ crtc_state->saveVTOTAL, ++ crtc_state->saveVBLANK, ++ crtc_state->saveVSYNC, ++ crtc_state->saveDSPSTRIDE, ++ crtc_state->saveDSPSIZE, ++ crtc_state->saveDSPPOS, ++ crtc_state->saveDSPBASE ++ ); ++ ++ ++ if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) { ++ REG_WRITE(pipeA ? DPLL_A : DPLL_B, ++ crtc_state->saveDPLL & ~DPLL_VCO_ENABLE); ++ REG_READ(pipeA ? DPLL_A : DPLL_B); ++ DRM_DEBUG("write dpll: %x\n", ++ REG_READ(pipeA ? DPLL_A : DPLL_B)); ++ udelay(150); ++ } ++ ++ REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0); ++ REG_READ(pipeA ? FPA0 : FPB0); ++ ++ REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1); ++ REG_READ(pipeA ? FPA1 : FPB1); ++ ++ REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL); ++ REG_READ(pipeA ? DPLL_A : DPLL_B); ++ udelay(150); ++ ++ REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL); ++ REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK); ++ REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC); ++ REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL); ++ REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK); ++ REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC); ++ REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE); ++ ++ REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE); ++ REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS); ++ ++ REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC); ++ REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); ++ REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF); ++ ++ cdv_intel_wait_for_vblank(dev); ++ ++ REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR); ++ REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); ++ ++ cdv_intel_wait_for_vblank(dev); ++ ++ paletteReg = pipeA ? PALETTE_A : PALETTE_B; ++ for (i = 0; i < 256; ++i) ++ REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]); ++} ++ ++static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc, ++ struct drm_file *file_priv, ++ uint32_t handle, ++ uint32_t width, uint32_t height) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; ++ uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; ++ uint32_t temp; ++ size_t addr = 0; ++ struct gtt_range *gt; ++ struct drm_gem_object *obj; ++ int ret; ++ ++ /* if we want to turn of the cursor ignore width and height */ ++ if (!handle) { ++ /* turn off the cursor */ ++ temp = CURSOR_MODE_DISABLE; ++ ++ if (gma_power_begin(dev, false)) { ++ REG_WRITE(control, temp); ++ REG_WRITE(base, 0); ++ gma_power_end(dev); ++ } ++ ++ /* unpin the old GEM object */ ++ if (psb_intel_crtc->cursor_obj) { ++ gt = container_of(psb_intel_crtc->cursor_obj, ++ struct gtt_range, gem); ++ psb_gtt_unpin(gt); ++ drm_gem_object_unreference(psb_intel_crtc->cursor_obj); ++ psb_intel_crtc->cursor_obj = NULL; ++ } ++ ++ return 0; ++ } ++ ++ /* Currently we only support 64x64 cursors */ ++ if (width != 64 || height != 64) { ++ dev_dbg(dev->dev, "we currently only support 64x64 cursors\n"); ++ return -EINVAL; ++ } ++ ++ obj = drm_gem_object_lookup(dev, file_priv, handle); ++ if (!obj) ++ return -ENOENT; ++ ++ if (obj->size < width * height * 4) { ++ dev_dbg(dev->dev, "buffer is to small\n"); ++ return -ENOMEM; ++ } ++ ++ gt = container_of(obj, struct gtt_range, gem); ++ ++ /* Pin the memory into the GTT */ ++ ret = psb_gtt_pin(gt); ++ if (ret) { ++ dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); ++ return ret; ++ } ++ ++ addr = gt->offset; /* Or resource.start ??? */ ++ ++ psb_intel_crtc->cursor_addr = addr; ++ ++ temp = 0; ++ /* set the pipe for the cursor */ ++ temp |= (pipe << 28); ++ temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; ++ ++ if (gma_power_begin(dev, false)) { ++ REG_WRITE(control, temp); ++ REG_WRITE(base, addr); ++ gma_power_end(dev); ++ } ++ ++ /* unpin the old GEM object */ ++ if (psb_intel_crtc->cursor_obj) { ++ gt = container_of(psb_intel_crtc->cursor_obj, ++ struct gtt_range, gem); ++ psb_gtt_unpin(gt); ++ drm_gem_object_unreference(psb_intel_crtc->cursor_obj); ++ psb_intel_crtc->cursor_obj = obj; ++ } ++ return 0; ++} ++ ++static int cdv_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ uint32_t temp = 0; ++ uint32_t adder; ++ ++ ++ if (x < 0) { ++ temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); ++ x = -x; ++ } ++ if (y < 0) { ++ temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); ++ y = -y; ++ } ++ ++ temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); ++ temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); ++ ++ adder = psb_intel_crtc->cursor_addr; ++ ++ if (gma_power_begin(dev, false)) { ++ REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); ++ REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder); ++ gma_power_end(dev); ++ } ++ return 0; ++} ++ ++static void cdv_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, ++ u16 *green, u16 *blue, uint32_t start, uint32_t size) ++{ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int i; ++ int end = (start + size > 256) ? 256 : start + size; ++ ++ for (i = start; i < end; i++) { ++ psb_intel_crtc->lut_r[i] = red[i] >> 8; ++ psb_intel_crtc->lut_g[i] = green[i] >> 8; ++ psb_intel_crtc->lut_b[i] = blue[i] >> 8; ++ } ++ ++ cdv_intel_crtc_load_lut(crtc); ++} ++ ++static int cdv_crtc_set_config(struct drm_mode_set *set) ++{ ++ int ret = 0; ++ struct drm_device *dev = set->crtc->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (!dev_priv->rpm_enabled) ++ return drm_crtc_helper_set_config(set); ++ ++ pm_runtime_forbid(&dev->pdev->dev); ++ ++ ret = drm_crtc_helper_set_config(set); ++ ++ pm_runtime_allow(&dev->pdev->dev); ++ ++ return ret; ++} ++ ++/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ ++ ++/* FIXME: why are we using this, should it be cdv_ in this tree ? */ ++ ++static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock) ++{ ++ clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); ++ clock->p = clock->p1 * clock->p2; ++ clock->vco = refclk * clock->m / (clock->n + 2); ++ clock->dot = clock->vco / clock->p; ++} ++ ++/* Returns the clock of the currently programmed mode of the given pipe. */ ++static int cdv_intel_crtc_clock_get(struct drm_device *dev, ++ struct drm_crtc *crtc) ++{ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ u32 dpll; ++ u32 fp; ++ struct cdv_intel_clock_t clock; ++ bool is_lvds; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (gma_power_begin(dev, false)) { ++ dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B); ++ if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) ++ fp = REG_READ((pipe == 0) ? FPA0 : FPB0); ++ else ++ fp = REG_READ((pipe == 0) ? FPA1 : FPB1); ++ is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN); ++ gma_power_end(dev); ++ } else { ++ dpll = (pipe == 0) ? ++ dev_priv->regs.psb.saveDPLL_A : ++ dev_priv->regs.psb.saveDPLL_B; ++ ++ if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) ++ fp = (pipe == 0) ? ++ dev_priv->regs.psb.saveFPA0 : ++ dev_priv->regs.psb.saveFPB0; ++ else ++ fp = (pipe == 0) ? ++ dev_priv->regs.psb.saveFPA1 : ++ dev_priv->regs.psb.saveFPB1; ++ ++ is_lvds = (pipe == 1) && ++ (dev_priv->regs.psb.saveLVDS & LVDS_PORT_EN); ++ } ++ ++ clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; ++ clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; ++ clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; ++ ++ if (is_lvds) { ++ clock.p1 = ++ ffs((dpll & ++ DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> ++ DPLL_FPA01_P1_POST_DIV_SHIFT); ++ if (clock.p1 == 0) { ++ clock.p1 = 4; ++ dev_err(dev->dev, "PLL %d\n", dpll); ++ } ++ clock.p2 = 14; ++ ++ if ((dpll & PLL_REF_INPUT_MASK) == ++ PLLB_REF_INPUT_SPREADSPECTRUMIN) { ++ /* XXX: might not be 66MHz */ ++ i8xx_clock(66000, &clock); ++ } else ++ i8xx_clock(48000, &clock); ++ } else { ++ if (dpll & PLL_P1_DIVIDE_BY_TWO) ++ clock.p1 = 2; ++ else { ++ clock.p1 = ++ ((dpll & ++ DPLL_FPA01_P1_POST_DIV_MASK_I830) >> ++ DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; ++ } ++ if (dpll & PLL_P2_DIVIDE_BY_4) ++ clock.p2 = 4; ++ else ++ clock.p2 = 2; ++ ++ i8xx_clock(48000, &clock); ++ } ++ ++ /* XXX: It would be nice to validate the clocks, but we can't reuse ++ * i830PllIsValid() because it relies on the xf86_config connector ++ * configuration being accurate, which it isn't necessarily. ++ */ ++ ++ return clock.dot; ++} ++ ++/** Returns the currently programmed mode of the given pipe. */ ++struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev, ++ struct drm_crtc *crtc) ++{ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ struct drm_display_mode *mode; ++ int htot; ++ int hsync; ++ int vtot; ++ int vsync; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (gma_power_begin(dev, false)) { ++ htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); ++ hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B); ++ vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); ++ vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B); ++ gma_power_end(dev); ++ } else { ++ htot = (pipe == 0) ? ++ dev_priv->regs.psb.saveHTOTAL_A : ++ dev_priv->regs.psb.saveHTOTAL_B; ++ hsync = (pipe == 0) ? ++ dev_priv->regs.psb.saveHSYNC_A : ++ dev_priv->regs.psb.saveHSYNC_B; ++ vtot = (pipe == 0) ? ++ dev_priv->regs.psb.saveVTOTAL_A : ++ dev_priv->regs.psb.saveVTOTAL_B; ++ vsync = (pipe == 0) ? ++ dev_priv->regs.psb.saveVSYNC_A : ++ dev_priv->regs.psb.saveVSYNC_B; ++ } ++ ++ mode = kzalloc(sizeof(*mode), GFP_KERNEL); ++ if (!mode) ++ return NULL; ++ ++ mode->clock = cdv_intel_crtc_clock_get(dev, crtc); ++ mode->hdisplay = (htot & 0xffff) + 1; ++ mode->htotal = ((htot & 0xffff0000) >> 16) + 1; ++ mode->hsync_start = (hsync & 0xffff) + 1; ++ mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; ++ mode->vdisplay = (vtot & 0xffff) + 1; ++ mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; ++ mode->vsync_start = (vsync & 0xffff) + 1; ++ mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; ++ ++ drm_mode_set_name(mode); ++ drm_mode_set_crtcinfo(mode, 0); ++ ++ return mode; ++} ++ ++static void cdv_intel_crtc_destroy(struct drm_crtc *crtc) ++{ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ ++ kfree(psb_intel_crtc->crtc_state); ++ drm_crtc_cleanup(crtc); ++ kfree(psb_intel_crtc); ++} ++ ++static void cdv_intel_crtc_disable(struct drm_crtc *crtc) ++{ ++ struct gtt_range *gt; ++ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; ++ ++ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); ++ ++ if (crtc->fb) { ++ gt = to_psb_fb(crtc->fb)->gtt; ++ psb_gtt_unpin(gt); ++ } ++} ++ ++const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = { ++ .dpms = cdv_intel_crtc_dpms, ++ .mode_fixup = cdv_intel_crtc_mode_fixup, ++ .mode_set = cdv_intel_crtc_mode_set, ++ .mode_set_base = cdv_intel_pipe_set_base, ++ .prepare = cdv_intel_crtc_prepare, ++ .commit = cdv_intel_crtc_commit, ++ .disable = cdv_intel_crtc_disable, ++}; ++ ++const struct drm_crtc_funcs cdv_intel_crtc_funcs = { ++ .save = cdv_intel_crtc_save, ++ .restore = cdv_intel_crtc_restore, ++ .cursor_set = cdv_intel_crtc_cursor_set, ++ .cursor_move = cdv_intel_crtc_cursor_move, ++ .gamma_set = cdv_intel_crtc_gamma_set, ++ .set_config = cdv_crtc_set_config, ++ .destroy = cdv_intel_crtc_destroy, ++}; +diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +new file mode 100644 +index 0000000..8d52695 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +@@ -0,0 +1,393 @@ ++/* ++ * Copyright © 2006-2011 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * jim liu ++ * ++ * FIXME: ++ * We should probably make this generic and share it with Medfield ++ */ ++ ++#include ++#include ++#include ++#include ++#include "psb_intel_drv.h" ++#include "psb_drv.h" ++#include "psb_intel_reg.h" ++#include "cdv_device.h" ++#include ++ ++/* hdmi control bits */ ++#define HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9) ++#define HDMI_BORDER_ENABLE (1 << 7) ++#define HDMI_AUDIO_ENABLE (1 << 6) ++#define HDMI_VSYNC_ACTIVE_HIGH (1 << 4) ++#define HDMI_HSYNC_ACTIVE_HIGH (1 << 3) ++/* hdmi-b control bits */ ++#define HDMIB_PIPE_B_SELECT (1 << 30) ++ ++ ++struct mid_intel_hdmi_priv { ++ u32 hdmi_reg; ++ u32 save_HDMIB; ++ bool has_hdmi_sink; ++ bool has_hdmi_audio; ++ /* Should set this when detect hotplug */ ++ bool hdmi_device_connected; ++ struct mdfld_hdmi_i2c *i2c_bus; ++ struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */ ++ struct drm_device *dev; ++}; ++ ++static void cdv_hdmi_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct psb_intel_encoder *psb_intel_encoder = to_psb_intel_encoder(encoder); ++ struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv; ++ u32 hdmib; ++ struct drm_crtc *crtc = encoder->crtc; ++ struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); ++ ++ hdmib = (2 << 10); ++ ++ if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ++ hdmib |= HDMI_VSYNC_ACTIVE_HIGH; ++ if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) ++ hdmib |= HDMI_HSYNC_ACTIVE_HIGH; ++ ++ if (intel_crtc->pipe == 1) ++ hdmib |= HDMIB_PIPE_B_SELECT; ++ ++ if (hdmi_priv->has_hdmi_audio) { ++ hdmib |= HDMI_AUDIO_ENABLE; ++ hdmib |= HDMI_NULL_PACKETS_DURING_VSYNC; ++ } ++ ++ REG_WRITE(hdmi_priv->hdmi_reg, hdmib); ++ REG_READ(hdmi_priv->hdmi_reg); ++} ++ ++static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ return true; ++} ++ ++static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct psb_intel_encoder *psb_intel_encoder = ++ to_psb_intel_encoder(encoder); ++ struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv; ++ u32 hdmib; ++ ++ hdmib = REG_READ(hdmi_priv->hdmi_reg); ++ ++ if (mode != DRM_MODE_DPMS_ON) ++ REG_WRITE(hdmi_priv->hdmi_reg, hdmib & ~HDMIB_PORT_EN); ++ else ++ REG_WRITE(hdmi_priv->hdmi_reg, hdmib | HDMIB_PORT_EN); ++ REG_READ(hdmi_priv->hdmi_reg); ++} ++ ++static void cdv_hdmi_save(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv; ++ ++ hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmi_reg); ++} ++ ++static void cdv_hdmi_restore(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv; ++ ++ REG_WRITE(hdmi_priv->hdmi_reg, hdmi_priv->save_HDMIB); ++ REG_READ(hdmi_priv->hdmi_reg); ++} ++ ++static enum drm_connector_status cdv_hdmi_detect( ++ struct drm_connector *connector, bool force) ++{ ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ struct psb_intel_connector *psb_intel_connector = ++ to_psb_intel_connector(connector); ++ struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv; ++ struct edid *edid = NULL; ++ enum drm_connector_status status = connector_status_disconnected; ++ ++ edid = drm_get_edid(connector, &psb_intel_encoder->i2c_bus->adapter); ++ ++ hdmi_priv->has_hdmi_sink = false; ++ hdmi_priv->has_hdmi_audio = false; ++ if (edid) { ++ if (edid->input & DRM_EDID_INPUT_DIGITAL) { ++ status = connector_status_connected; ++ hdmi_priv->has_hdmi_sink = ++ drm_detect_hdmi_monitor(edid); ++ hdmi_priv->has_hdmi_audio = ++ drm_detect_monitor_audio(edid); ++ } ++ ++ psb_intel_connector->base.display_info.raw_edid = NULL; ++ kfree(edid); ++ } ++ return status; ++} ++ ++static int cdv_hdmi_set_property(struct drm_connector *connector, ++ struct drm_property *property, ++ uint64_t value) ++{ ++ struct drm_encoder *encoder = connector->encoder; ++ ++ if (!strcmp(property->name, "scaling mode") && encoder) { ++ struct psb_intel_crtc *crtc = to_psb_intel_crtc(encoder->crtc); ++ bool centre; ++ uint64_t curValue; ++ ++ if (!crtc) ++ return -1; ++ ++ switch (value) { ++ case DRM_MODE_SCALE_FULLSCREEN: ++ break; ++ case DRM_MODE_SCALE_NO_SCALE: ++ break; ++ case DRM_MODE_SCALE_ASPECT: ++ break; ++ default: ++ return -1; ++ } ++ ++ if (drm_connector_property_get_value(connector, ++ property, &curValue)) ++ return -1; ++ ++ if (curValue == value) ++ return 0; ++ ++ if (drm_connector_property_set_value(connector, ++ property, value)) ++ return -1; ++ ++ centre = (curValue == DRM_MODE_SCALE_NO_SCALE) || ++ (value == DRM_MODE_SCALE_NO_SCALE); ++ ++ if (crtc->saved_mode.hdisplay != 0 && ++ crtc->saved_mode.vdisplay != 0) { ++ if (centre) { ++ if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode, ++ encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb)) ++ return -1; ++ } else { ++ struct drm_encoder_helper_funcs *helpers ++ = encoder->helper_private; ++ helpers->mode_set(encoder, &crtc->saved_mode, ++ &crtc->saved_adjusted_mode); ++ } ++ } ++ } ++ return 0; ++} ++ ++/* ++ * Return the list of HDMI DDC modes if available. ++ */ ++static int cdv_hdmi_get_modes(struct drm_connector *connector) ++{ ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ struct edid *edid = NULL; ++ int ret = 0; ++ ++ edid = drm_get_edid(connector, &psb_intel_encoder->i2c_bus->adapter); ++ if (edid) { ++ drm_mode_connector_update_edid_property(connector, edid); ++ ret = drm_add_edid_modes(connector, edid); ++ kfree(edid); ++ } ++ return ret; ++} ++ ++static int cdv_hdmi_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ struct drm_psb_private *dev_priv = connector->dev->dev_private; ++ ++ if (mode->clock > 165000) ++ return MODE_CLOCK_HIGH; ++ if (mode->clock < 20000) ++ return MODE_CLOCK_HIGH; ++ ++ /* just in case */ ++ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ return MODE_NO_DBLESCAN; ++ ++ /* just in case */ ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) ++ return MODE_NO_INTERLACE; ++ ++ /* We assume worst case scenario of 32 bpp here, since we don't know */ ++ if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) > ++ dev_priv->vram_stolen_size) ++ return MODE_MEM; ++ ++ return MODE_OK; ++} ++ ++static void cdv_hdmi_destroy(struct drm_connector *connector) ++{ ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ ++ if (psb_intel_encoder->i2c_bus) ++ psb_intel_i2c_destroy(psb_intel_encoder->i2c_bus); ++ drm_sysfs_connector_remove(connector); ++ drm_connector_cleanup(connector); ++ kfree(connector); ++} ++ ++static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = { ++ .dpms = cdv_hdmi_dpms, ++ .mode_fixup = cdv_hdmi_mode_fixup, ++ .prepare = psb_intel_encoder_prepare, ++ .mode_set = cdv_hdmi_mode_set, ++ .commit = psb_intel_encoder_commit, ++}; ++ ++static const struct drm_connector_helper_funcs ++ cdv_hdmi_connector_helper_funcs = { ++ .get_modes = cdv_hdmi_get_modes, ++ .mode_valid = cdv_hdmi_mode_valid, ++ .best_encoder = psb_intel_best_encoder, ++}; ++ ++static const struct drm_connector_funcs cdv_hdmi_connector_funcs = { ++ .dpms = drm_helper_connector_dpms, ++ .save = cdv_hdmi_save, ++ .restore = cdv_hdmi_restore, ++ .detect = cdv_hdmi_detect, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .set_property = cdv_hdmi_set_property, ++ .destroy = cdv_hdmi_destroy, ++}; ++ ++void cdv_hdmi_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev, int reg) ++{ ++ struct psb_intel_encoder *psb_intel_encoder; ++ struct psb_intel_connector *psb_intel_connector; ++ struct drm_connector *connector; ++ struct drm_encoder *encoder; ++ struct mid_intel_hdmi_priv *hdmi_priv; ++ int ddc_bus; ++ ++ psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), ++ GFP_KERNEL); ++ ++ if (!psb_intel_encoder) ++ return; ++ ++ psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), ++ GFP_KERNEL); ++ ++ if (!psb_intel_connector) ++ goto err_connector; ++ ++ hdmi_priv = kzalloc(sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL); ++ ++ if (!hdmi_priv) ++ goto err_priv; ++ ++ connector = &psb_intel_connector->base; ++ encoder = &psb_intel_encoder->base; ++ drm_connector_init(dev, connector, ++ &cdv_hdmi_connector_funcs, ++ DRM_MODE_CONNECTOR_DVID); ++ ++ drm_encoder_init(dev, encoder, &psb_intel_lvds_enc_funcs, ++ DRM_MODE_ENCODER_TMDS); ++ ++ psb_intel_connector_attach_encoder(psb_intel_connector, ++ psb_intel_encoder); ++ psb_intel_encoder->type = INTEL_OUTPUT_HDMI; ++ hdmi_priv->hdmi_reg = reg; ++ hdmi_priv->has_hdmi_sink = false; ++ psb_intel_encoder->dev_priv = hdmi_priv; ++ ++ drm_encoder_helper_add(encoder, &cdv_hdmi_helper_funcs); ++ drm_connector_helper_add(connector, ++ &cdv_hdmi_connector_helper_funcs); ++ connector->display_info.subpixel_order = SubPixelHorizontalRGB; ++ connector->interlace_allowed = false; ++ connector->doublescan_allowed = false; ++ ++ drm_connector_attach_property(connector, ++ dev->mode_config.scaling_mode_property, ++ DRM_MODE_SCALE_FULLSCREEN); ++ ++ switch (reg) { ++ case SDVOB: ++ ddc_bus = GPIOE; ++ break; ++ case SDVOC: ++ ddc_bus = GPIOD; ++ break; ++ default: ++ DRM_ERROR("unknown reg 0x%x for HDMI\n", reg); ++ goto failed_ddc; ++ break; ++ } ++ ++ psb_intel_encoder->i2c_bus = psb_intel_i2c_create(dev, ++ ddc_bus, (reg == SDVOB) ? "HDMIB" : "HDMIC"); ++ ++ if (!psb_intel_encoder->i2c_bus) { ++ dev_err(dev->dev, "No ddc adapter available!\n"); ++ goto failed_ddc; ++ } ++ ++ hdmi_priv->hdmi_i2c_adapter = ++ &(psb_intel_encoder->i2c_bus->adapter); ++ hdmi_priv->dev = dev; ++ drm_sysfs_connector_add(connector); ++ return; ++ ++failed_ddc: ++ drm_encoder_cleanup(encoder); ++ drm_connector_cleanup(connector); ++err_priv: ++ kfree(psb_intel_connector); ++err_connector: ++ kfree(psb_intel_encoder); ++} +diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c +new file mode 100644 +index 0000000..8359c1a +--- /dev/null ++++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c +@@ -0,0 +1,734 @@ ++/* ++ * Copyright © 2006-2011 Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: ++ * Eric Anholt ++ * Dave Airlie ++ * Jesse Barnes ++ */ ++ ++#include ++#include ++#include ++ ++#include "intel_bios.h" ++#include "psb_drv.h" ++#include "psb_intel_drv.h" ++#include "psb_intel_reg.h" ++#include "power.h" ++#include ++#include "cdv_device.h" ++ ++/** ++ * LVDS I2C backlight control macros ++ */ ++#define BRIGHTNESS_MAX_LEVEL 100 ++#define BRIGHTNESS_MASK 0xFF ++#define BLC_I2C_TYPE 0x01 ++#define BLC_PWM_TYPT 0x02 ++ ++#define BLC_POLARITY_NORMAL 0 ++#define BLC_POLARITY_INVERSE 1 ++ ++#define PSB_BLC_MAX_PWM_REG_FREQ (0xFFFE) ++#define PSB_BLC_MIN_PWM_REG_FREQ (0x2) ++#define PSB_BLC_PWM_PRECISION_FACTOR (10) ++#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) ++#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) ++ ++struct cdv_intel_lvds_priv { ++ /** ++ * Saved LVDO output states ++ */ ++ uint32_t savePP_ON; ++ uint32_t savePP_OFF; ++ uint32_t saveLVDS; ++ uint32_t savePP_CONTROL; ++ uint32_t savePP_CYCLE; ++ uint32_t savePFIT_CONTROL; ++ uint32_t savePFIT_PGM_RATIOS; ++ uint32_t saveBLC_PWM_CTL; ++}; ++ ++/* ++ * Returns the maximum level of the backlight duty cycle field. ++ */ ++static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 retval; ++ ++ if (gma_power_begin(dev, false)) { ++ retval = ((REG_READ(BLC_PWM_CTL) & ++ BACKLIGHT_MODULATION_FREQ_MASK) >> ++ BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; ++ ++ gma_power_end(dev); ++ } else ++ retval = ((dev_priv->regs.saveBLC_PWM_CTL & ++ BACKLIGHT_MODULATION_FREQ_MASK) >> ++ BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; ++ ++ return retval; ++} ++ ++#if 0 ++/* ++ * Set LVDS backlight level by I2C command ++ */ ++static int cdv_lvds_i2c_set_brightness(struct drm_device *dev, ++ unsigned int level) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus; ++ u8 out_buf[2]; ++ unsigned int blc_i2c_brightness; ++ ++ struct i2c_msg msgs[] = { ++ { ++ .addr = lvds_i2c_bus->slave_addr, ++ .flags = 0, ++ .len = 2, ++ .buf = out_buf, ++ } ++ }; ++ ++ blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level * ++ BRIGHTNESS_MASK / ++ BRIGHTNESS_MAX_LEVEL); ++ ++ if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) ++ blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness; ++ ++ out_buf[0] = dev_priv->lvds_bl->brightnesscmd; ++ out_buf[1] = (u8)blc_i2c_brightness; ++ ++ if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) ++ return 0; ++ ++ DRM_ERROR("I2C transfer error\n"); ++ return -1; ++} ++ ++ ++static int cdv_lvds_pwm_set_brightness(struct drm_device *dev, int level) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ u32 max_pwm_blc; ++ u32 blc_pwm_duty_cycle; ++ ++ max_pwm_blc = cdv_intel_lvds_get_max_backlight(dev); ++ ++ /*BLC_PWM_CTL Should be initiated while backlight device init*/ ++ BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0); ++ ++ blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL; ++ ++ if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) ++ blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle; ++ ++ blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; ++ REG_WRITE(BLC_PWM_CTL, ++ (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | ++ (blc_pwm_duty_cycle)); ++ ++ return 0; ++} ++ ++/* ++ * Set LVDS backlight level either by I2C or PWM ++ */ ++void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (!dev_priv->lvds_bl) { ++ DRM_ERROR("NO LVDS Backlight Info\n"); ++ return; ++ } ++ ++ if (dev_priv->lvds_bl->type == BLC_I2C_TYPE) ++ cdv_lvds_i2c_set_brightness(dev, level); ++ else ++ cdv_lvds_pwm_set_brightness(dev, level); ++} ++#endif ++ ++/** ++ * Sets the backlight level. ++ * ++ * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight(). ++ */ ++static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 blc_pwm_ctl; ++ ++ if (gma_power_begin(dev, false)) { ++ blc_pwm_ctl = ++ REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; ++ REG_WRITE(BLC_PWM_CTL, ++ (blc_pwm_ctl | ++ (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); ++ gma_power_end(dev); ++ } else { ++ blc_pwm_ctl = dev_priv->regs.saveBLC_PWM_CTL & ++ ~BACKLIGHT_DUTY_CYCLE_MASK; ++ dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl | ++ (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); ++ } ++} ++ ++/** ++ * Sets the power state for the panel. ++ */ ++static void cdv_intel_lvds_set_power(struct drm_device *dev, ++ struct drm_encoder *encoder, bool on) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 pp_status; ++ ++ if (!gma_power_begin(dev, true)) ++ return; ++ ++ if (on) { ++ REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | ++ POWER_TARGET_ON); ++ do { ++ pp_status = REG_READ(PP_STATUS); ++ } while ((pp_status & PP_ON) == 0); ++ ++ cdv_intel_lvds_set_backlight(dev, ++ dev_priv->mode_dev.backlight_duty_cycle); ++ } else { ++ cdv_intel_lvds_set_backlight(dev, 0); ++ ++ REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ++ ~POWER_TARGET_ON); ++ do { ++ pp_status = REG_READ(PP_STATUS); ++ } while (pp_status & PP_ON); ++ } ++ gma_power_end(dev); ++} ++ ++static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ if (mode == DRM_MODE_DPMS_ON) ++ cdv_intel_lvds_set_power(dev, encoder, true); ++ else ++ cdv_intel_lvds_set_power(dev, encoder, false); ++ /* XXX: We never power down the LVDS pairs. */ ++} ++ ++static void cdv_intel_lvds_save(struct drm_connector *connector) ++{ ++} ++ ++static void cdv_intel_lvds_restore(struct drm_connector *connector) ++{ ++} ++ ++static int cdv_intel_lvds_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ struct drm_device *dev = connector->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct drm_display_mode *fixed_mode = ++ dev_priv->mode_dev.panel_fixed_mode; ++ ++ /* just in case */ ++ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ return MODE_NO_DBLESCAN; ++ ++ /* just in case */ ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) ++ return MODE_NO_INTERLACE; ++ ++ if (fixed_mode) { ++ if (mode->hdisplay > fixed_mode->hdisplay) ++ return MODE_PANEL; ++ if (mode->vdisplay > fixed_mode->vdisplay) ++ return MODE_PANEL; ++ } ++ return MODE_OK; ++} ++ ++static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ struct drm_encoder *tmp_encoder; ++ struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode; ++ ++ /* Should never happen!! */ ++ list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, ++ head) { ++ if (tmp_encoder != encoder ++ && tmp_encoder->crtc == encoder->crtc) { ++ printk(KERN_ERR "Can't enable LVDS and another " ++ "encoder on the same pipe\n"); ++ return false; ++ } ++ } ++ ++ /* ++ * If we have timings from the BIOS for the panel, put them in ++ * to the adjusted mode. The CRTC will be set up for this mode, ++ * with the panel scaling set up to source from the H/VDisplay ++ * of the original mode. ++ */ ++ if (panel_fixed_mode != NULL) { ++ adjusted_mode->hdisplay = panel_fixed_mode->hdisplay; ++ adjusted_mode->hsync_start = panel_fixed_mode->hsync_start; ++ adjusted_mode->hsync_end = panel_fixed_mode->hsync_end; ++ adjusted_mode->htotal = panel_fixed_mode->htotal; ++ adjusted_mode->vdisplay = panel_fixed_mode->vdisplay; ++ adjusted_mode->vsync_start = panel_fixed_mode->vsync_start; ++ adjusted_mode->vsync_end = panel_fixed_mode->vsync_end; ++ adjusted_mode->vtotal = panel_fixed_mode->vtotal; ++ adjusted_mode->clock = panel_fixed_mode->clock; ++ drm_mode_set_crtcinfo(adjusted_mode, ++ CRTC_INTERLACE_HALVE_V); ++ } ++ ++ /* ++ * XXX: It would be nice to support lower refresh rates on the ++ * panels to reduce power consumption, and perhaps match the ++ * user's requested refresh rate. ++ */ ++ ++ return true; ++} ++ ++static void cdv_intel_lvds_prepare(struct drm_encoder *encoder) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ ++ if (!gma_power_begin(dev, true)) ++ return; ++ ++ mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); ++ mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & ++ BACKLIGHT_DUTY_CYCLE_MASK); ++ ++ cdv_intel_lvds_set_power(dev, encoder, false); ++ ++ gma_power_end(dev); ++} ++ ++static void cdv_intel_lvds_commit(struct drm_encoder *encoder) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ ++ if (mode_dev->backlight_duty_cycle == 0) ++ mode_dev->backlight_duty_cycle = ++ cdv_intel_lvds_get_max_backlight(dev); ++ ++ cdv_intel_lvds_set_power(dev, encoder, true); ++} ++ ++static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 pfit_control; ++ ++ /* ++ * The LVDS pin pair will already have been turned on in the ++ * cdv_intel_crtc_mode_set since it has a large impact on the DPLL ++ * settings. ++ */ ++ ++ /* ++ * Enable automatic panel scaling so that non-native modes fill the ++ * screen. Should be enabled before the pipe is enabled, according to ++ * register description and PRM. ++ */ ++ if (mode->hdisplay != adjusted_mode->hdisplay || ++ mode->vdisplay != adjusted_mode->vdisplay) ++ pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | ++ HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | ++ HORIZ_INTERP_BILINEAR); ++ else ++ pfit_control = 0; ++ ++ if (dev_priv->lvds_dither) ++ pfit_control |= PANEL_8TO6_DITHER_ENABLE; ++ ++ REG_WRITE(PFIT_CONTROL, pfit_control); ++} ++ ++/** ++ * Detect the LVDS connection. ++ * ++ * This always returns CONNECTOR_STATUS_CONNECTED. ++ * This connector should only have ++ * been set up if the LVDS was actually connected anyway. ++ */ ++static enum drm_connector_status cdv_intel_lvds_detect( ++ struct drm_connector *connector, bool force) ++{ ++ return connector_status_connected; ++} ++ ++/** ++ * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. ++ */ ++static int cdv_intel_lvds_get_modes(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ int ret; ++ ++ ret = psb_intel_ddc_get_modes(connector, &psb_intel_encoder->i2c_bus->adapter); ++ ++ if (ret) ++ return ret; ++ ++ /* Didn't get an EDID, so ++ * Set wide sync ranges so we get all modes ++ * handed to valid_mode for checking ++ */ ++ connector->display_info.min_vfreq = 0; ++ connector->display_info.max_vfreq = 200; ++ connector->display_info.min_hfreq = 0; ++ connector->display_info.max_hfreq = 200; ++ if (mode_dev->panel_fixed_mode != NULL) { ++ struct drm_display_mode *mode = ++ drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); ++ drm_mode_probed_add(connector, mode); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * cdv_intel_lvds_destroy - unregister and free LVDS structures ++ * @connector: connector to free ++ * ++ * Unregister the DDC bus for this connector then free the driver private ++ * structure. ++ */ ++static void cdv_intel_lvds_destroy(struct drm_connector *connector) ++{ ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ ++ if (psb_intel_encoder->i2c_bus) ++ psb_intel_i2c_destroy(psb_intel_encoder->i2c_bus); ++ drm_sysfs_connector_remove(connector); ++ drm_connector_cleanup(connector); ++ kfree(connector); ++} ++ ++static int cdv_intel_lvds_set_property(struct drm_connector *connector, ++ struct drm_property *property, ++ uint64_t value) ++{ ++ struct drm_encoder *encoder = connector->encoder; ++ ++ if (!strcmp(property->name, "scaling mode") && encoder) { ++ struct psb_intel_crtc *crtc = ++ to_psb_intel_crtc(encoder->crtc); ++ uint64_t curValue; ++ ++ if (!crtc) ++ return -1; ++ ++ switch (value) { ++ case DRM_MODE_SCALE_FULLSCREEN: ++ break; ++ case DRM_MODE_SCALE_NO_SCALE: ++ break; ++ case DRM_MODE_SCALE_ASPECT: ++ break; ++ default: ++ return -1; ++ } ++ ++ if (drm_connector_property_get_value(connector, ++ property, ++ &curValue)) ++ return -1; ++ ++ if (curValue == value) ++ return 0; ++ ++ if (drm_connector_property_set_value(connector, ++ property, ++ value)) ++ return -1; ++ ++ if (crtc->saved_mode.hdisplay != 0 && ++ crtc->saved_mode.vdisplay != 0) { ++ if (!drm_crtc_helper_set_mode(encoder->crtc, ++ &crtc->saved_mode, ++ encoder->crtc->x, ++ encoder->crtc->y, ++ encoder->crtc->fb)) ++ return -1; ++ } ++ } else if (!strcmp(property->name, "backlight") && encoder) { ++ if (drm_connector_property_set_value(connector, ++ property, ++ value)) ++ return -1; ++ else { ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ struct drm_psb_private *dev_priv = ++ encoder->dev->dev_private; ++ struct backlight_device *bd = ++ dev_priv->backlight_device; ++ bd->props.brightness = value; ++ backlight_update_status(bd); ++#endif ++ } ++ } else if (!strcmp(property->name, "DPMS") && encoder) { ++ struct drm_encoder_helper_funcs *helpers = ++ encoder->helper_private; ++ helpers->dpms(encoder, value); ++ } ++ return 0; ++} ++ ++static const struct drm_encoder_helper_funcs ++ cdv_intel_lvds_helper_funcs = { ++ .dpms = cdv_intel_lvds_encoder_dpms, ++ .mode_fixup = cdv_intel_lvds_mode_fixup, ++ .prepare = cdv_intel_lvds_prepare, ++ .mode_set = cdv_intel_lvds_mode_set, ++ .commit = cdv_intel_lvds_commit, ++}; ++ ++static const struct drm_connector_helper_funcs ++ cdv_intel_lvds_connector_helper_funcs = { ++ .get_modes = cdv_intel_lvds_get_modes, ++ .mode_valid = cdv_intel_lvds_mode_valid, ++ .best_encoder = psb_intel_best_encoder, ++}; ++ ++static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = { ++ .dpms = drm_helper_connector_dpms, ++ .save = cdv_intel_lvds_save, ++ .restore = cdv_intel_lvds_restore, ++ .detect = cdv_intel_lvds_detect, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .set_property = cdv_intel_lvds_set_property, ++ .destroy = cdv_intel_lvds_destroy, ++}; ++ ++ ++static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder) ++{ ++ drm_encoder_cleanup(encoder); ++} ++ ++const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = { ++ .destroy = cdv_intel_lvds_enc_destroy, ++}; ++ ++/** ++ * cdv_intel_lvds_init - setup LVDS connectors on this device ++ * @dev: drm device ++ * ++ * Create the connector, register the LVDS DDC bus, and try to figure out what ++ * modes we can display on the LVDS panel (if present). ++ */ ++void cdv_intel_lvds_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev) ++{ ++ struct psb_intel_encoder *psb_intel_encoder; ++ struct psb_intel_connector *psb_intel_connector; ++ struct cdv_intel_lvds_priv *lvds_priv; ++ struct drm_connector *connector; ++ struct drm_encoder *encoder; ++ struct drm_display_mode *scan; ++ struct drm_crtc *crtc; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 lvds; ++ int pipe; ++ ++ psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), ++ GFP_KERNEL); ++ if (!psb_intel_encoder) ++ return; ++ ++ psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), ++ GFP_KERNEL); ++ if (!psb_intel_connector) ++ goto failed_connector; ++ ++ lvds_priv = kzalloc(sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL); ++ if (!lvds_priv) ++ goto failed_lvds_priv; ++ ++ psb_intel_encoder->dev_priv = lvds_priv; ++ ++ connector = &psb_intel_connector->base; ++ encoder = &psb_intel_encoder->base; ++ ++ ++ drm_connector_init(dev, connector, ++ &cdv_intel_lvds_connector_funcs, ++ DRM_MODE_CONNECTOR_LVDS); ++ ++ drm_encoder_init(dev, encoder, ++ &cdv_intel_lvds_enc_funcs, ++ DRM_MODE_ENCODER_LVDS); ++ ++ ++ psb_intel_connector_attach_encoder(psb_intel_connector, ++ psb_intel_encoder); ++ psb_intel_encoder->type = INTEL_OUTPUT_LVDS; ++ ++ drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs); ++ drm_connector_helper_add(connector, ++ &cdv_intel_lvds_connector_helper_funcs); ++ connector->display_info.subpixel_order = SubPixelHorizontalRGB; ++ connector->interlace_allowed = false; ++ connector->doublescan_allowed = false; ++ ++ /*Attach connector properties*/ ++ drm_connector_attach_property(connector, ++ dev->mode_config.scaling_mode_property, ++ DRM_MODE_SCALE_FULLSCREEN); ++ drm_connector_attach_property(connector, ++ dev_priv->backlight_property, ++ BRIGHTNESS_MAX_LEVEL); ++ ++ /** ++ * Set up I2C bus ++ * FIXME: distroy i2c_bus when exit ++ */ ++ psb_intel_encoder->i2c_bus = psb_intel_i2c_create(dev, ++ GPIOB, ++ "LVDSBLC_B"); ++ if (!psb_intel_encoder->i2c_bus) { ++ dev_printk(KERN_ERR, ++ &dev->pdev->dev, "I2C bus registration failed.\n"); ++ goto failed_blc_i2c; ++ } ++ psb_intel_encoder->i2c_bus->slave_addr = 0x2C; ++ dev_priv->lvds_i2c_bus = psb_intel_encoder->i2c_bus; ++ ++ /* ++ * LVDS discovery: ++ * 1) check for EDID on DDC ++ * 2) check for VBT data ++ * 3) check to see if LVDS is already on ++ * if none of the above, no panel ++ * 4) make sure lid is open ++ * if closed, act like it's not there for now ++ */ ++ ++ /* Set up the DDC bus. */ ++ psb_intel_encoder->ddc_bus = psb_intel_i2c_create(dev, ++ GPIOC, ++ "LVDSDDC_C"); ++ if (!psb_intel_encoder->ddc_bus) { ++ dev_printk(KERN_ERR, &dev->pdev->dev, ++ "DDC bus registration " "failed.\n"); ++ goto failed_ddc; ++ } ++ ++ /* ++ * Attempt to get the fixed panel mode from DDC. Assume that the ++ * preferred mode is the right one. ++ */ ++ psb_intel_ddc_get_modes(connector, ++ &psb_intel_encoder->ddc_bus->adapter); ++ list_for_each_entry(scan, &connector->probed_modes, head) { ++ if (scan->type & DRM_MODE_TYPE_PREFERRED) { ++ mode_dev->panel_fixed_mode = ++ drm_mode_duplicate(dev, scan); ++ goto out; /* FIXME: check for quirks */ ++ } ++ } ++ ++ /* Failed to get EDID, what about VBT? do we need this?*/ ++ if (dev_priv->lfp_lvds_vbt_mode) { ++ mode_dev->panel_fixed_mode = ++ drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); ++ if (mode_dev->panel_fixed_mode) { ++ mode_dev->panel_fixed_mode->type |= ++ DRM_MODE_TYPE_PREFERRED; ++ goto out; /* FIXME: check for quirks */ ++ } ++ } ++ /* ++ * If we didn't get EDID, try checking if the panel is already turned ++ * on. If so, assume that whatever is currently programmed is the ++ * correct mode. ++ */ ++ lvds = REG_READ(LVDS); ++ pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; ++ crtc = psb_intel_get_crtc_from_pipe(dev, pipe); ++ ++ if (crtc && (lvds & LVDS_PORT_EN)) { ++ mode_dev->panel_fixed_mode = ++ cdv_intel_crtc_mode_get(dev, crtc); ++ if (mode_dev->panel_fixed_mode) { ++ mode_dev->panel_fixed_mode->type |= ++ DRM_MODE_TYPE_PREFERRED; ++ goto out; /* FIXME: check for quirks */ ++ } ++ } ++ ++ /* If we still don't have a mode after all that, give up. */ ++ if (!mode_dev->panel_fixed_mode) { ++ DRM_DEBUG ++ ("Found no modes on the lvds, ignoring the LVDS\n"); ++ goto failed_find; ++ } ++ ++out: ++ drm_sysfs_connector_add(connector); ++ return; ++ ++failed_find: ++ printk(KERN_ERR "Failed find\n"); ++ if (psb_intel_encoder->ddc_bus) ++ psb_intel_i2c_destroy(psb_intel_encoder->ddc_bus); ++failed_ddc: ++ printk(KERN_ERR "Failed DDC\n"); ++ if (psb_intel_encoder->i2c_bus) ++ psb_intel_i2c_destroy(psb_intel_encoder->i2c_bus); ++failed_blc_i2c: ++ printk(KERN_ERR "Failed BLC\n"); ++ drm_encoder_cleanup(encoder); ++ drm_connector_cleanup(connector); ++ kfree(lvds_priv); ++failed_lvds_priv: ++ kfree(psb_intel_connector); ++failed_connector: ++ kfree(psb_intel_encoder); ++} +diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c +new file mode 100644 +index 0000000..fa74a86 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/framebuffer.c +@@ -0,0 +1,800 @@ ++/************************************************************************** ++ * Copyright (c) 2007-2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "psb_drv.h" ++#include "psb_intel_reg.h" ++#include "psb_intel_drv.h" ++#include "framebuffer.h" ++#include "gtt.h" ++ ++static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb); ++static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, ++ struct drm_file *file_priv, ++ unsigned int *handle); ++ ++static const struct drm_framebuffer_funcs psb_fb_funcs = { ++ .destroy = psb_user_framebuffer_destroy, ++ .create_handle = psb_user_framebuffer_create_handle, ++}; ++ ++#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16) ++ ++static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green, ++ unsigned blue, unsigned transp, ++ struct fb_info *info) ++{ ++ struct psb_fbdev *fbdev = info->par; ++ struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb; ++ uint32_t v; ++ ++ if (!fb) ++ return -ENOMEM; ++ ++ if (regno > 255) ++ return 1; ++ ++ red = CMAP_TOHW(red, info->var.red.length); ++ blue = CMAP_TOHW(blue, info->var.blue.length); ++ green = CMAP_TOHW(green, info->var.green.length); ++ transp = CMAP_TOHW(transp, info->var.transp.length); ++ ++ v = (red << info->var.red.offset) | ++ (green << info->var.green.offset) | ++ (blue << info->var.blue.offset) | ++ (transp << info->var.transp.offset); ++ ++ if (regno < 16) { ++ switch (fb->bits_per_pixel) { ++ case 16: ++ ((uint32_t *) info->pseudo_palette)[regno] = v; ++ break; ++ case 24: ++ case 32: ++ ((uint32_t *) info->pseudo_palette)[regno] = v; ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info) ++{ ++ struct psb_fbdev *fbdev = info->par; ++ struct psb_framebuffer *psbfb = &fbdev->pfb; ++ struct drm_device *dev = psbfb->base.dev; ++ ++ /* ++ * We have to poke our nose in here. The core fb code assumes ++ * panning is part of the hardware that can be invoked before ++ * the actual fb is mapped. In our case that isn't quite true. ++ */ ++ if (psbfb->gtt->npage) { ++ /* GTT roll shifts in 4K pages, we need to shift the right ++ number of pages */ ++ int pages = info->fix.line_length >> 12; ++ psb_gtt_roll(dev, psbfb->gtt, var->yoffset * pages); ++ } ++ return 0; ++} ++ ++static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ++{ ++ struct psb_framebuffer *psbfb = vma->vm_private_data; ++ struct drm_device *dev = psbfb->base.dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int page_num; ++ int i; ++ unsigned long address; ++ int ret; ++ unsigned long pfn; ++ /* FIXME: assumes fb at stolen base which may not be true */ ++ unsigned long phys_addr = (unsigned long)dev_priv->stolen_base; ++ ++ page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; ++ address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT); ++ ++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ++ ++ for (i = 0; i < page_num; i++) { ++ pfn = (phys_addr >> PAGE_SHIFT); ++ ++ ret = vm_insert_mixed(vma, address, pfn); ++ if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0))) ++ break; ++ else if (unlikely(ret != 0)) { ++ ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; ++ return ret; ++ } ++ address += PAGE_SIZE; ++ phys_addr += PAGE_SIZE; ++ } ++ return VM_FAULT_NOPAGE; ++} ++ ++static void psbfb_vm_open(struct vm_area_struct *vma) ++{ ++} ++ ++static void psbfb_vm_close(struct vm_area_struct *vma) ++{ ++} ++ ++static struct vm_operations_struct psbfb_vm_ops = { ++ .fault = psbfb_vm_fault, ++ .open = psbfb_vm_open, ++ .close = psbfb_vm_close ++}; ++ ++static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) ++{ ++ struct psb_fbdev *fbdev = info->par; ++ struct psb_framebuffer *psbfb = &fbdev->pfb; ++ ++ if (vma->vm_pgoff != 0) ++ return -EINVAL; ++ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) ++ return -EINVAL; ++ ++ if (!psbfb->addr_space) ++ psbfb->addr_space = vma->vm_file->f_mapping; ++ /* ++ * If this is a GEM object then info->screen_base is the virtual ++ * kernel remapping of the object. FIXME: Review if this is ++ * suitable for our mmap work ++ */ ++ vma->vm_ops = &psbfb_vm_ops; ++ vma->vm_private_data = (void *)psbfb; ++ vma->vm_flags |= VM_RESERVED | VM_IO | ++ VM_MIXEDMAP | VM_DONTEXPAND; ++ return 0; ++} ++ ++static int psbfb_ioctl(struct fb_info *info, unsigned int cmd, ++ unsigned long arg) ++{ ++ return -ENOTTY; ++} ++ ++static struct fb_ops psbfb_ops = { ++ .owner = THIS_MODULE, ++ .fb_check_var = drm_fb_helper_check_var, ++ .fb_set_par = drm_fb_helper_set_par, ++ .fb_blank = drm_fb_helper_blank, ++ .fb_setcolreg = psbfb_setcolreg, ++ .fb_fillrect = cfb_fillrect, ++ .fb_copyarea = psbfb_copyarea, ++ .fb_imageblit = cfb_imageblit, ++ .fb_mmap = psbfb_mmap, ++ .fb_sync = psbfb_sync, ++ .fb_ioctl = psbfb_ioctl, ++}; ++ ++static struct fb_ops psbfb_roll_ops = { ++ .owner = THIS_MODULE, ++ .fb_check_var = drm_fb_helper_check_var, ++ .fb_set_par = drm_fb_helper_set_par, ++ .fb_blank = drm_fb_helper_blank, ++ .fb_setcolreg = psbfb_setcolreg, ++ .fb_fillrect = cfb_fillrect, ++ .fb_copyarea = cfb_copyarea, ++ .fb_imageblit = cfb_imageblit, ++ .fb_pan_display = psbfb_pan, ++ .fb_mmap = psbfb_mmap, ++ .fb_ioctl = psbfb_ioctl, ++}; ++ ++static struct fb_ops psbfb_unaccel_ops = { ++ .owner = THIS_MODULE, ++ .fb_check_var = drm_fb_helper_check_var, ++ .fb_set_par = drm_fb_helper_set_par, ++ .fb_blank = drm_fb_helper_blank, ++ .fb_setcolreg = psbfb_setcolreg, ++ .fb_fillrect = cfb_fillrect, ++ .fb_copyarea = cfb_copyarea, ++ .fb_imageblit = cfb_imageblit, ++ .fb_mmap = psbfb_mmap, ++ .fb_ioctl = psbfb_ioctl, ++}; ++ ++/** ++ * psb_framebuffer_init - initialize a framebuffer ++ * @dev: our DRM device ++ * @fb: framebuffer to set up ++ * @mode_cmd: mode description ++ * @gt: backing object ++ * ++ * Configure and fill in the boilerplate for our frame buffer. Return ++ * 0 on success or an error code if we fail. ++ */ ++static int psb_framebuffer_init(struct drm_device *dev, ++ struct psb_framebuffer *fb, ++ struct drm_mode_fb_cmd2 *mode_cmd, ++ struct gtt_range *gt) ++{ ++ u32 bpp, depth; ++ int ret; ++ ++ drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); ++ ++ if (mode_cmd->pitches[0] & 63) ++ return -EINVAL; ++ switch (bpp) { ++ case 8: ++ case 16: ++ case 24: ++ case 32: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs); ++ if (ret) { ++ dev_err(dev->dev, "framebuffer init failed: %d\n", ret); ++ return ret; ++ } ++ drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); ++ fb->gtt = gt; ++ return 0; ++} ++ ++/** ++ * psb_framebuffer_create - create a framebuffer backed by gt ++ * @dev: our DRM device ++ * @mode_cmd: the description of the requested mode ++ * @gt: the backing object ++ * ++ * Create a framebuffer object backed by the gt, and fill in the ++ * boilerplate required ++ * ++ * TODO: review object references ++ */ ++ ++static struct drm_framebuffer *psb_framebuffer_create ++ (struct drm_device *dev, ++ struct drm_mode_fb_cmd2 *mode_cmd, ++ struct gtt_range *gt) ++{ ++ struct psb_framebuffer *fb; ++ int ret; ++ ++ fb = kzalloc(sizeof(*fb), GFP_KERNEL); ++ if (!fb) ++ return ERR_PTR(-ENOMEM); ++ ++ ret = psb_framebuffer_init(dev, fb, mode_cmd, gt); ++ if (ret) { ++ kfree(fb); ++ return ERR_PTR(ret); ++ } ++ return &fb->base; ++} ++ ++/** ++ * psbfb_alloc - allocate frame buffer memory ++ * @dev: the DRM device ++ * @aligned_size: space needed ++ * @force: fall back to GEM buffers if need be ++ * ++ * Allocate the frame buffer. In the usual case we get a GTT range that ++ * is stolen memory backed and life is simple. If there isn't sufficient ++ * we fail as we don't have the virtual mapping space to really vmap it ++ * and the kernel console code can't handle non linear framebuffers. ++ * ++ * Re-address this as and if the framebuffer layer grows this ability. ++ */ ++static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size) ++{ ++ struct gtt_range *backing; ++ /* Begin by trying to use stolen memory backing */ ++ backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1); ++ if (backing) { ++ if (drm_gem_private_object_init(dev, ++ &backing->gem, aligned_size) == 0) ++ return backing; ++ psb_gtt_free_range(dev, backing); ++ } ++ return NULL; ++} ++ ++/** ++ * psbfb_create - create a framebuffer ++ * @fbdev: the framebuffer device ++ * @sizes: specification of the layout ++ * ++ * Create a framebuffer to the specifications provided ++ */ ++static int psbfb_create(struct psb_fbdev *fbdev, ++ struct drm_fb_helper_surface_size *sizes) ++{ ++ struct drm_device *dev = fbdev->psb_fb_helper.dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct fb_info *info; ++ struct drm_framebuffer *fb; ++ struct psb_framebuffer *psbfb = &fbdev->pfb; ++ struct drm_mode_fb_cmd2 mode_cmd; ++ struct device *device = &dev->pdev->dev; ++ int size; ++ int ret; ++ struct gtt_range *backing; ++ u32 bpp, depth; ++ int gtt_roll = 0; ++ int pitch_lines = 0; ++ ++ mode_cmd.width = sizes->surface_width; ++ mode_cmd.height = sizes->surface_height; ++ bpp = sizes->surface_bpp; ++ depth = sizes->surface_depth; ++ ++ /* No 24bit packed */ ++ if (bpp == 24) ++ bpp = 32; ++ ++ do { ++ /* ++ * Acceleration via the GTT requires pitch to be ++ * power of two aligned. Preferably page but less ++ * is ok with some fonts ++ */ ++ mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096 >> pitch_lines); ++ ++ size = mode_cmd.pitches[0] * mode_cmd.height; ++ size = ALIGN(size, PAGE_SIZE); ++ ++ /* Allocate the fb in the GTT with stolen page backing */ ++ backing = psbfb_alloc(dev, size); ++ ++ if (pitch_lines) ++ pitch_lines *= 2; ++ else ++ pitch_lines = 1; ++ gtt_roll++; ++ } while (backing == NULL && pitch_lines <= 16); ++ ++ /* The final pitch we accepted if we succeeded */ ++ pitch_lines /= 2; ++ ++ if (backing == NULL) { ++ /* ++ * We couldn't get the space we wanted, fall back to the ++ * display engine requirement instead. The HW requires ++ * the pitch to be 64 byte aligned ++ */ ++ ++ gtt_roll = 0; /* Don't use GTT accelerated scrolling */ ++ pitch_lines = 64; ++ ++ mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64); ++ ++ size = mode_cmd.pitches[0] * mode_cmd.height; ++ size = ALIGN(size, PAGE_SIZE); ++ ++ /* Allocate the framebuffer in the GTT with stolen page backing */ ++ backing = psbfb_alloc(dev, size); ++ if (backing == NULL) ++ return -ENOMEM; ++ } ++ ++ mutex_lock(&dev->struct_mutex); ++ ++ info = framebuffer_alloc(0, device); ++ if (!info) { ++ ret = -ENOMEM; ++ goto out_err1; ++ } ++ info->par = fbdev; ++ ++ mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); ++ ++ ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing); ++ if (ret) ++ goto out_unref; ++ ++ fb = &psbfb->base; ++ psbfb->fbdev = info; ++ ++ fbdev->psb_fb_helper.fb = fb; ++ fbdev->psb_fb_helper.fbdev = info; ++ ++ drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); ++ strcpy(info->fix.id, "psbfb"); ++ ++ info->flags = FBINFO_DEFAULT; ++ if (dev_priv->ops->accel_2d && pitch_lines > 8) /* 2D engine */ ++ info->fbops = &psbfb_ops; ++ else if (gtt_roll) { /* GTT rolling seems best */ ++ info->fbops = &psbfb_roll_ops; ++ info->flags |= FBINFO_HWACCEL_YPAN; ++ } else /* Software */ ++ info->fbops = &psbfb_unaccel_ops; ++ ++ ret = fb_alloc_cmap(&info->cmap, 256, 0); ++ if (ret) { ++ ret = -ENOMEM; ++ goto out_unref; ++ } ++ ++ info->fix.smem_start = dev->mode_config.fb_base; ++ info->fix.smem_len = size; ++ info->fix.ywrapstep = gtt_roll; ++ info->fix.ypanstep = 0; ++ ++ /* Accessed stolen memory directly */ ++ info->screen_base = (char *)dev_priv->vram_addr + ++ backing->offset; ++ info->screen_size = size; ++ ++ if (dev_priv->gtt.stolen_size) { ++ info->apertures = alloc_apertures(1); ++ if (!info->apertures) { ++ ret = -ENOMEM; ++ goto out_unref; ++ } ++ info->apertures->ranges[0].base = dev->mode_config.fb_base; ++ info->apertures->ranges[0].size = dev_priv->gtt.stolen_size; ++ } ++ ++ drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, ++ sizes->fb_width, sizes->fb_height); ++ ++ info->fix.mmio_start = pci_resource_start(dev->pdev, 0); ++ info->fix.mmio_len = pci_resource_len(dev->pdev, 0); ++ ++ /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ ++ ++ dev_info(dev->dev, "allocated %dx%d fb\n", ++ psbfb->base.width, psbfb->base.height); ++ ++ mutex_unlock(&dev->struct_mutex); ++ return 0; ++out_unref: ++ if (backing->stolen) ++ psb_gtt_free_range(dev, backing); ++ else ++ drm_gem_object_unreference(&backing->gem); ++out_err1: ++ mutex_unlock(&dev->struct_mutex); ++ psb_gtt_free_range(dev, backing); ++ return ret; ++} ++ ++/** ++ * psb_user_framebuffer_create - create framebuffer ++ * @dev: our DRM device ++ * @filp: client file ++ * @cmd: mode request ++ * ++ * Create a new framebuffer backed by a userspace GEM object ++ */ ++static struct drm_framebuffer *psb_user_framebuffer_create ++ (struct drm_device *dev, struct drm_file *filp, ++ struct drm_mode_fb_cmd2 *cmd) ++{ ++ struct gtt_range *r; ++ struct drm_gem_object *obj; ++ ++ /* ++ * Find the GEM object and thus the gtt range object that is ++ * to back this space ++ */ ++ obj = drm_gem_object_lookup(dev, filp, cmd->handles[0]); ++ if (obj == NULL) ++ return ERR_PTR(-ENOENT); ++ ++ /* Let the core code do all the work */ ++ r = container_of(obj, struct gtt_range, gem); ++ return psb_framebuffer_create(dev, cmd, r); ++} ++ ++static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, ++ u16 blue, int regno) ++{ ++ struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); ++ ++ intel_crtc->lut_r[regno] = red >> 8; ++ intel_crtc->lut_g[regno] = green >> 8; ++ intel_crtc->lut_b[regno] = blue >> 8; ++} ++ ++static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red, ++ u16 *green, u16 *blue, int regno) ++{ ++ struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); ++ ++ *red = intel_crtc->lut_r[regno] << 8; ++ *green = intel_crtc->lut_g[regno] << 8; ++ *blue = intel_crtc->lut_b[regno] << 8; ++} ++ ++static int psbfb_probe(struct drm_fb_helper *helper, ++ struct drm_fb_helper_surface_size *sizes) ++{ ++ struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper; ++ int new_fb = 0; ++ int ret; ++ ++ if (!helper->fb) { ++ ret = psbfb_create(psb_fbdev, sizes); ++ if (ret) ++ return ret; ++ new_fb = 1; ++ } ++ return new_fb; ++} ++ ++struct drm_fb_helper_funcs psb_fb_helper_funcs = { ++ .gamma_set = psbfb_gamma_set, ++ .gamma_get = psbfb_gamma_get, ++ .fb_probe = psbfb_probe, ++}; ++ ++static int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev) ++{ ++ struct fb_info *info; ++ struct psb_framebuffer *psbfb = &fbdev->pfb; ++ ++ if (fbdev->psb_fb_helper.fbdev) { ++ info = fbdev->psb_fb_helper.fbdev; ++ unregister_framebuffer(info); ++ if (info->cmap.len) ++ fb_dealloc_cmap(&info->cmap); ++ framebuffer_release(info); ++ } ++ drm_fb_helper_fini(&fbdev->psb_fb_helper); ++ drm_framebuffer_cleanup(&psbfb->base); ++ ++ if (psbfb->gtt) ++ drm_gem_object_unreference(&psbfb->gtt->gem); ++ return 0; ++} ++ ++int psb_fbdev_init(struct drm_device *dev) ++{ ++ struct psb_fbdev *fbdev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL); ++ if (!fbdev) { ++ dev_err(dev->dev, "no memory\n"); ++ return -ENOMEM; ++ } ++ ++ dev_priv->fbdev = fbdev; ++ fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs; ++ ++ drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs, ++ INTELFB_CONN_LIMIT); ++ ++ drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper); ++ drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32); ++ return 0; ++} ++ ++static void psb_fbdev_fini(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (!dev_priv->fbdev) ++ return; ++ ++ psb_fbdev_destroy(dev, dev_priv->fbdev); ++ kfree(dev_priv->fbdev); ++ dev_priv->fbdev = NULL; ++} ++ ++static void psbfb_output_poll_changed(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev; ++ drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper); ++} ++ ++/** ++ * psb_user_framebuffer_create_handle - add hamdle to a framebuffer ++ * @fb: framebuffer ++ * @file_priv: our DRM file ++ * @handle: returned handle ++ * ++ * Our framebuffer object is a GTT range which also contains a GEM ++ * object. We need to turn it into a handle for userspace. GEM will do ++ * the work for us ++ */ ++static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, ++ struct drm_file *file_priv, ++ unsigned int *handle) ++{ ++ struct psb_framebuffer *psbfb = to_psb_fb(fb); ++ struct gtt_range *r = psbfb->gtt; ++ return drm_gem_handle_create(file_priv, &r->gem, handle); ++} ++ ++/** ++ * psb_user_framebuffer_destroy - destruct user created fb ++ * @fb: framebuffer ++ * ++ * User framebuffers are backed by GEM objects so all we have to do is ++ * clean up a bit and drop the reference, GEM will handle the fallout ++ */ ++static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb) ++{ ++ struct psb_framebuffer *psbfb = to_psb_fb(fb); ++ struct gtt_range *r = psbfb->gtt; ++ struct drm_device *dev = fb->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_fbdev *fbdev = dev_priv->fbdev; ++ struct drm_crtc *crtc; ++ int reset = 0; ++ ++ /* Should never get stolen memory for a user fb */ ++ WARN_ON(r->stolen); ++ ++ /* Check if we are erroneously live */ ++ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) ++ if (crtc->fb == fb) ++ reset = 1; ++ ++ if (reset) ++ /* ++ * Now force a sane response before we permit the DRM CRTC ++ * layer to do stupid things like blank the display. Instead ++ * we reset this framebuffer as if the user had forced a reset. ++ * We must do this before the cleanup so that the DRM layer ++ * doesn't get a chance to stick its oar in where it isn't ++ * wanted. ++ */ ++ drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper); ++ ++ /* Let DRM do its clean up */ ++ drm_framebuffer_cleanup(fb); ++ /* We are no longer using the resource in GEM */ ++ drm_gem_object_unreference_unlocked(&r->gem); ++ kfree(fb); ++} ++ ++static const struct drm_mode_config_funcs psb_mode_funcs = { ++ .fb_create = psb_user_framebuffer_create, ++ .output_poll_changed = psbfb_output_poll_changed, ++}; ++ ++static int psb_create_backlight_property(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct drm_property *backlight; ++ ++ if (dev_priv->backlight_property) ++ return 0; ++ ++ backlight = drm_property_create_range(dev, 0, "backlight", 0, 100); ++ ++ dev_priv->backlight_property = backlight; ++ ++ return 0; ++} ++ ++static void psb_setup_outputs(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct drm_connector *connector; ++ ++ drm_mode_create_scaling_mode_property(dev); ++ psb_create_backlight_property(dev); ++ ++ dev_priv->ops->output_init(dev); ++ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, ++ head) { ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ struct drm_encoder *encoder = &psb_intel_encoder->base; ++ int crtc_mask = 0, clone_mask = 0; ++ ++ /* valid crtcs */ ++ switch (psb_intel_encoder->type) { ++ case INTEL_OUTPUT_ANALOG: ++ crtc_mask = (1 << 0); ++ clone_mask = (1 << INTEL_OUTPUT_ANALOG); ++ break; ++ case INTEL_OUTPUT_SDVO: ++ crtc_mask = ((1 << 0) | (1 << 1)); ++ clone_mask = (1 << INTEL_OUTPUT_SDVO); ++ break; ++ case INTEL_OUTPUT_LVDS: ++ if (IS_MRST(dev)) ++ crtc_mask = (1 << 0); ++ else ++ crtc_mask = (1 << 1); ++ clone_mask = (1 << INTEL_OUTPUT_LVDS); ++ break; ++ case INTEL_OUTPUT_MIPI: ++ crtc_mask = (1 << 0); ++ clone_mask = (1 << INTEL_OUTPUT_MIPI); ++ break; ++ case INTEL_OUTPUT_MIPI2: ++ crtc_mask = (1 << 2); ++ clone_mask = (1 << INTEL_OUTPUT_MIPI2); ++ break; ++ case INTEL_OUTPUT_HDMI: ++ if (IS_MFLD(dev)) ++ crtc_mask = (1 << 1); ++ else ++ crtc_mask = (1 << 0); ++ clone_mask = (1 << INTEL_OUTPUT_HDMI); ++ break; ++ } ++ encoder->possible_crtcs = crtc_mask; ++ encoder->possible_clones = ++ psb_intel_connector_clones(dev, clone_mask); ++ } ++} ++ ++void psb_modeset_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ int i; ++ ++ drm_mode_config_init(dev); ++ ++ dev->mode_config.min_width = 0; ++ dev->mode_config.min_height = 0; ++ ++ dev->mode_config.funcs = (void *) &psb_mode_funcs; ++ ++ /* set memory base */ ++ /* Oaktrail and Poulsbo should use BAR 2*/ ++ pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *) ++ &(dev->mode_config.fb_base)); ++ ++ /* num pipes is 2 for PSB but 1 for Mrst */ ++ for (i = 0; i < dev_priv->num_pipe; i++) ++ psb_intel_crtc_init(dev, i, mode_dev); ++ ++ dev->mode_config.max_width = 4096; ++ dev->mode_config.max_height = 4096; ++ ++ psb_setup_outputs(dev); ++} ++ ++void psb_modeset_cleanup(struct drm_device *dev) ++{ ++ mutex_lock(&dev->struct_mutex); ++ ++ drm_kms_helper_poll_fini(dev); ++ psb_fbdev_fini(dev); ++ drm_mode_config_cleanup(dev); ++ ++ mutex_unlock(&dev->struct_mutex); ++} +diff --git a/drivers/gpu/drm/gma500/framebuffer.h b/drivers/gpu/drm/gma500/framebuffer.h +new file mode 100644 +index 0000000..989558a +--- /dev/null ++++ b/drivers/gpu/drm/gma500/framebuffer.h +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (c) 2008-2011, Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: ++ * Eric Anholt ++ * ++ */ ++ ++#ifndef _FRAMEBUFFER_H_ ++#define _FRAMEBUFFER_H_ ++ ++#include ++#include ++ ++#include "psb_drv.h" ++ ++struct psb_framebuffer { ++ struct drm_framebuffer base; ++ struct address_space *addr_space; ++ struct fb_info *fbdev; ++ struct gtt_range *gtt; ++}; ++ ++struct psb_fbdev { ++ struct drm_fb_helper psb_fb_helper; ++ struct psb_framebuffer pfb; ++}; ++ ++#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base) ++ ++extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask); ++ ++#endif ++ +diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c +new file mode 100644 +index 0000000..9fbb868 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/gem.c +@@ -0,0 +1,292 @@ ++/* ++ * psb GEM interface ++ * ++ * Copyright (c) 2011, Intel Corporation. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: Alan Cox ++ * ++ * TODO: ++ * - we need to work out if the MMU is relevant (eg for ++ * accelerated operations on a GEM object) ++ */ ++ ++#include ++#include ++#include "gma_drm.h" ++#include "psb_drv.h" ++ ++int psb_gem_init_object(struct drm_gem_object *obj) ++{ ++ return -EINVAL; ++} ++ ++void psb_gem_free_object(struct drm_gem_object *obj) ++{ ++ struct gtt_range *gtt = container_of(obj, struct gtt_range, gem); ++ drm_gem_object_release_wrap(obj); ++ /* This must occur last as it frees up the memory of the GEM object */ ++ psb_gtt_free_range(obj->dev, gtt); ++} ++ ++int psb_gem_get_aperture(struct drm_device *dev, void *data, ++ struct drm_file *file) ++{ ++ return -EINVAL; ++} ++ ++/** ++ * psb_gem_dumb_map_gtt - buffer mapping for dumb interface ++ * @file: our drm client file ++ * @dev: drm device ++ * @handle: GEM handle to the object (from dumb_create) ++ * ++ * Do the necessary setup to allow the mapping of the frame buffer ++ * into user memory. We don't have to do much here at the moment. ++ */ ++int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, ++ uint32_t handle, uint64_t *offset) ++{ ++ int ret = 0; ++ struct drm_gem_object *obj; ++ ++ if (!(dev->driver->driver_features & DRIVER_GEM)) ++ return -ENODEV; ++ ++ mutex_lock(&dev->struct_mutex); ++ ++ /* GEM does all our handle to object mapping */ ++ obj = drm_gem_object_lookup(dev, file, handle); ++ if (obj == NULL) { ++ ret = -ENOENT; ++ goto unlock; ++ } ++ /* What validation is needed here ? */ ++ ++ /* Make it mmapable */ ++ if (!obj->map_list.map) { ++ ret = gem_create_mmap_offset(obj); ++ if (ret) ++ goto out; ++ } ++ /* GEM should really work out the hash offsets for us */ ++ *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT; ++out: ++ drm_gem_object_unreference(obj); ++unlock: ++ mutex_unlock(&dev->struct_mutex); ++ return ret; ++} ++ ++/** ++ * psb_gem_create - create a mappable object ++ * @file: the DRM file of the client ++ * @dev: our device ++ * @size: the size requested ++ * @handlep: returned handle (opaque number) ++ * ++ * Create a GEM object, fill in the boilerplate and attach a handle to ++ * it so that userspace can speak about it. This does the core work ++ * for the various methods that do/will create GEM objects for things ++ */ ++static int psb_gem_create(struct drm_file *file, ++ struct drm_device *dev, uint64_t size, uint32_t *handlep) ++{ ++ struct gtt_range *r; ++ int ret; ++ u32 handle; ++ ++ size = roundup(size, PAGE_SIZE); ++ ++ /* Allocate our object - for now a direct gtt range which is not ++ stolen memory backed */ ++ r = psb_gtt_alloc_range(dev, size, "gem", 0); ++ if (r == NULL) { ++ dev_err(dev->dev, "no memory for %lld byte GEM object\n", size); ++ return -ENOSPC; ++ } ++ /* Initialize the extra goodies GEM needs to do all the hard work */ ++ if (drm_gem_object_init(dev, &r->gem, size) != 0) { ++ psb_gtt_free_range(dev, r); ++ /* GEM doesn't give an error code so use -ENOMEM */ ++ dev_err(dev->dev, "GEM init failed for %lld\n", size); ++ return -ENOMEM; ++ } ++ /* Give the object a handle so we can carry it more easily */ ++ ret = drm_gem_handle_create(file, &r->gem, &handle); ++ if (ret) { ++ dev_err(dev->dev, "GEM handle failed for %p, %lld\n", ++ &r->gem, size); ++ drm_gem_object_release(&r->gem); ++ psb_gtt_free_range(dev, r); ++ return ret; ++ } ++ /* We have the initial and handle reference but need only one now */ ++ drm_gem_object_unreference(&r->gem); ++ *handlep = handle; ++ return 0; ++} ++ ++/** ++ * psb_gem_dumb_create - create a dumb buffer ++ * @drm_file: our client file ++ * @dev: our device ++ * @args: the requested arguments copied from userspace ++ * ++ * Allocate a buffer suitable for use for a frame buffer of the ++ * form described by user space. Give userspace a handle by which ++ * to reference it. ++ */ ++int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev, ++ struct drm_mode_create_dumb *args) ++{ ++ args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64); ++ args->size = args->pitch * args->height; ++ return psb_gem_create(file, dev, args->size, &args->handle); ++} ++ ++/** ++ * psb_gem_dumb_destroy - destroy a dumb buffer ++ * @file: client file ++ * @dev: our DRM device ++ * @handle: the object handle ++ * ++ * Destroy a handle that was created via psb_gem_dumb_create, at least ++ * we hope it was created that way. i915 seems to assume the caller ++ * does the checking but that might be worth review ! FIXME ++ */ ++int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, ++ uint32_t handle) ++{ ++ /* No special work needed, drop the reference and see what falls out */ ++ return drm_gem_handle_delete(file, handle); ++} ++ ++/** ++ * psb_gem_fault - pagefault handler for GEM objects ++ * @vma: the VMA of the GEM object ++ * @vmf: fault detail ++ * ++ * Invoked when a fault occurs on an mmap of a GEM managed area. GEM ++ * does most of the work for us including the actual map/unmap calls ++ * but we need to do the actual page work. ++ * ++ * This code eventually needs to handle faulting objects in and out ++ * of the GTT and repacking it when we run out of space. We can put ++ * that off for now and for our simple uses ++ * ++ * The VMA was set up by GEM. In doing so it also ensured that the ++ * vma->vm_private_data points to the GEM object that is backing this ++ * mapping. ++ */ ++int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ++{ ++ struct drm_gem_object *obj; ++ struct gtt_range *r; ++ int ret; ++ unsigned long pfn; ++ pgoff_t page_offset; ++ struct drm_device *dev; ++ struct drm_psb_private *dev_priv; ++ ++ obj = vma->vm_private_data; /* GEM object */ ++ dev = obj->dev; ++ dev_priv = dev->dev_private; ++ ++ r = container_of(obj, struct gtt_range, gem); /* Get the gtt range */ ++ ++ /* Make sure we don't parallel update on a fault, nor move or remove ++ something from beneath our feet */ ++ mutex_lock(&dev->struct_mutex); ++ ++ /* For now the mmap pins the object and it stays pinned. As things ++ stand that will do us no harm */ ++ if (r->mmapping == 0) { ++ ret = psb_gtt_pin(r); ++ if (ret < 0) { ++ dev_err(dev->dev, "gma500: pin failed: %d\n", ret); ++ goto fail; ++ } ++ r->mmapping = 1; ++ } ++ ++ /* Page relative to the VMA start - we must calculate this ourselves ++ because vmf->pgoff is the fake GEM offset */ ++ page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start) ++ >> PAGE_SHIFT; ++ ++ /* CPU view of the page, don't go via the GART for CPU writes */ ++ if (r->stolen) ++ pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT; ++ else ++ pfn = page_to_pfn(r->pages[page_offset]); ++ ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); ++ ++fail: ++ mutex_unlock(&dev->struct_mutex); ++ switch (ret) { ++ case 0: ++ case -ERESTARTSYS: ++ case -EINTR: ++ return VM_FAULT_NOPAGE; ++ case -ENOMEM: ++ return VM_FAULT_OOM; ++ default: ++ return VM_FAULT_SIGBUS; ++ } ++} ++ ++static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev, ++ int size, u32 *handle) ++{ ++ struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1); ++ if (gtt == NULL) ++ return -ENOMEM; ++ if (drm_gem_private_object_init(dev, >t->gem, size) != 0) ++ goto free_gtt; ++ if (drm_gem_handle_create(file, >t->gem, handle) == 0) ++ return 0; ++free_gtt: ++ psb_gtt_free_range(dev, gtt); ++ return -ENOMEM; ++} ++ ++/* ++ * GEM interfaces for our specific client ++ */ ++int psb_gem_create_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file) ++{ ++ struct drm_psb_gem_create *args = data; ++ int ret; ++ if (args->flags & GMA_GEM_CREATE_STOLEN) { ++ ret = psb_gem_create_stolen(file, dev, args->size, ++ &args->handle); ++ if (ret == 0) ++ return 0; ++ /* Fall throguh */ ++ args->flags &= ~GMA_GEM_CREATE_STOLEN; ++ } ++ return psb_gem_create(file, dev, args->size, &args->handle); ++} ++ ++int psb_gem_mmap_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file) ++{ ++ struct drm_psb_gem_mmap *args = data; ++ return dev->driver->dumb_map_offset(file, dev, ++ args->handle, &args->offset); ++} ++ +diff --git a/drivers/gpu/drm/gma500/gem_glue.c b/drivers/gpu/drm/gma500/gem_glue.c +new file mode 100644 +index 0000000..3c17634 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/gem_glue.c +@@ -0,0 +1,90 @@ ++/************************************************************************** ++ * Copyright (c) 2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++ ++#include ++#include ++#include "gem_glue.h" ++ ++void drm_gem_object_release_wrap(struct drm_gem_object *obj) ++{ ++ /* Remove the list map if one is present */ ++ if (obj->map_list.map) { ++ struct drm_gem_mm *mm = obj->dev->mm_private; ++ struct drm_map_list *list = &obj->map_list; ++ drm_ht_remove_item(&mm->offset_hash, &list->hash); ++ drm_mm_put_block(list->file_offset_node); ++ kfree(list->map); ++ list->map = NULL; ++ } ++ drm_gem_object_release(obj); ++} ++ ++/** ++ * gem_create_mmap_offset - invent an mmap offset ++ * @obj: our object ++ * ++ * Standard implementation of offset generation for mmap as is ++ * duplicated in several drivers. This belongs in GEM. ++ */ ++int gem_create_mmap_offset(struct drm_gem_object *obj) ++{ ++ struct drm_device *dev = obj->dev; ++ struct drm_gem_mm *mm = dev->mm_private; ++ struct drm_map_list *list; ++ struct drm_local_map *map; ++ int ret; ++ ++ list = &obj->map_list; ++ list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); ++ if (list->map == NULL) ++ return -ENOMEM; ++ map = list->map; ++ map->type = _DRM_GEM; ++ map->size = obj->size; ++ map->handle = obj; ++ ++ list->file_offset_node = drm_mm_search_free(&mm->offset_manager, ++ obj->size / PAGE_SIZE, 0, 0); ++ if (!list->file_offset_node) { ++ dev_err(dev->dev, "failed to allocate offset for bo %d\n", ++ obj->name); ++ ret = -ENOSPC; ++ goto free_it; ++ } ++ list->file_offset_node = drm_mm_get_block(list->file_offset_node, ++ obj->size / PAGE_SIZE, 0); ++ if (!list->file_offset_node) { ++ ret = -ENOMEM; ++ goto free_it; ++ } ++ list->hash.key = list->file_offset_node->start; ++ ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); ++ if (ret) { ++ dev_err(dev->dev, "failed to add to map hash\n"); ++ goto free_mm; ++ } ++ return 0; ++ ++free_mm: ++ drm_mm_put_block(list->file_offset_node); ++free_it: ++ kfree(list->map); ++ list->map = NULL; ++ return ret; ++} +diff --git a/drivers/gpu/drm/gma500/gem_glue.h b/drivers/gpu/drm/gma500/gem_glue.h +new file mode 100644 +index 0000000..ce5ce30 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/gem_glue.h +@@ -0,0 +1,2 @@ ++extern void drm_gem_object_release_wrap(struct drm_gem_object *obj); ++extern int gem_create_mmap_offset(struct drm_gem_object *obj); +diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c +new file mode 100644 +index 0000000..c6465b4 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/gtt.c +@@ -0,0 +1,551 @@ ++/* ++ * Copyright (c) 2007, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: Thomas Hellstrom ++ * Alan Cox ++ */ ++ ++#include ++#include ++#include "psb_drv.h" ++ ++ ++/* ++ * GTT resource allocator - manage page mappings in GTT space ++ */ ++ ++/** ++ * psb_gtt_mask_pte - generate GTT pte entry ++ * @pfn: page number to encode ++ * @type: type of memory in the GTT ++ * ++ * Set the GTT entry for the appropriate memory type. ++ */ ++static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type) ++{ ++ uint32_t mask = PSB_PTE_VALID; ++ ++ if (type & PSB_MMU_CACHED_MEMORY) ++ mask |= PSB_PTE_CACHED; ++ if (type & PSB_MMU_RO_MEMORY) ++ mask |= PSB_PTE_RO; ++ if (type & PSB_MMU_WO_MEMORY) ++ mask |= PSB_PTE_WO; ++ ++ return (pfn << PAGE_SHIFT) | mask; ++} ++ ++/** ++ * psb_gtt_entry - find the GTT entries for a gtt_range ++ * @dev: our DRM device ++ * @r: our GTT range ++ * ++ * Given a gtt_range object return the GTT offset of the page table ++ * entries for this gtt_range ++ */ ++static u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ unsigned long offset; ++ ++ offset = r->resource.start - dev_priv->gtt_mem->start; ++ ++ return dev_priv->gtt_map + (offset >> PAGE_SHIFT); ++} ++ ++/** ++ * psb_gtt_insert - put an object into the GTT ++ * @dev: our DRM device ++ * @r: our GTT range ++ * ++ * Take our preallocated GTT range and insert the GEM object into ++ * the GTT. This is protected via the gtt mutex which the caller ++ * must hold. ++ */ ++static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r) ++{ ++ u32 *gtt_slot, pte; ++ struct page **pages; ++ int i; ++ ++ if (r->pages == NULL) { ++ WARN_ON(1); ++ return -EINVAL; ++ } ++ ++ WARN_ON(r->stolen); /* refcount these maybe ? */ ++ ++ gtt_slot = psb_gtt_entry(dev, r); ++ pages = r->pages; ++ ++ /* Make sure changes are visible to the GPU */ ++ set_pages_array_uc(pages, r->npage); ++ ++ /* Write our page entries into the GTT itself */ ++ for (i = r->roll; i < r->npage; i++) { ++ pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); ++ iowrite32(pte, gtt_slot++); ++ } ++ for (i = 0; i < r->roll; i++) { ++ pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); ++ iowrite32(pte, gtt_slot++); ++ } ++ /* Make sure all the entries are set before we return */ ++ ioread32(gtt_slot - 1); ++ ++ return 0; ++} ++ ++/** ++ * psb_gtt_remove - remove an object from the GTT ++ * @dev: our DRM device ++ * @r: our GTT range ++ * ++ * Remove a preallocated GTT range from the GTT. Overwrite all the ++ * page table entries with the dummy page. This is protected via the gtt ++ * mutex which the caller must hold. ++ */ ++static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 *gtt_slot, pte; ++ int i; ++ ++ WARN_ON(r->stolen); ++ ++ gtt_slot = psb_gtt_entry(dev, r); ++ pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0); ++ ++ for (i = 0; i < r->npage; i++) ++ iowrite32(pte, gtt_slot++); ++ ioread32(gtt_slot - 1); ++ set_pages_array_wb(r->pages, r->npage); ++} ++ ++/** ++ * psb_gtt_roll - set scrolling position ++ * @dev: our DRM device ++ * @r: the gtt mapping we are using ++ * @roll: roll offset ++ * ++ * Roll an existing pinned mapping by moving the pages through the GTT. ++ * This allows us to implement hardware scrolling on the consoles without ++ * a 2D engine ++ */ ++void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll) ++{ ++ u32 *gtt_slot, pte; ++ int i; ++ ++ if (roll >= r->npage) { ++ WARN_ON(1); ++ return; ++ } ++ ++ r->roll = roll; ++ ++ /* Not currently in the GTT - no worry we will write the mapping at ++ the right position when it gets pinned */ ++ if (!r->stolen && !r->in_gart) ++ return; ++ ++ gtt_slot = psb_gtt_entry(dev, r); ++ ++ for (i = r->roll; i < r->npage; i++) { ++ pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); ++ iowrite32(pte, gtt_slot++); ++ } ++ for (i = 0; i < r->roll; i++) { ++ pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); ++ iowrite32(pte, gtt_slot++); ++ } ++ ioread32(gtt_slot - 1); ++} ++ ++/** ++ * psb_gtt_attach_pages - attach and pin GEM pages ++ * @gt: the gtt range ++ * ++ * Pin and build an in kernel list of the pages that back our GEM object. ++ * While we hold this the pages cannot be swapped out. This is protected ++ * via the gtt mutex which the caller must hold. ++ */ ++static int psb_gtt_attach_pages(struct gtt_range *gt) ++{ ++ struct inode *inode; ++ struct address_space *mapping; ++ int i; ++ struct page *p; ++ int pages = gt->gem.size / PAGE_SIZE; ++ ++ WARN_ON(gt->pages); ++ ++ /* This is the shared memory object that backs the GEM resource */ ++ inode = gt->gem.filp->f_path.dentry->d_inode; ++ mapping = inode->i_mapping; ++ ++ gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL); ++ if (gt->pages == NULL) ++ return -ENOMEM; ++ gt->npage = pages; ++ ++ for (i = 0; i < pages; i++) { ++ p = shmem_read_mapping_page(mapping, i); ++ if (IS_ERR(p)) ++ goto err; ++ gt->pages[i] = p; ++ } ++ return 0; ++ ++err: ++ while (i--) ++ page_cache_release(gt->pages[i]); ++ kfree(gt->pages); ++ gt->pages = NULL; ++ return PTR_ERR(p); ++} ++ ++/** ++ * psb_gtt_detach_pages - attach and pin GEM pages ++ * @gt: the gtt range ++ * ++ * Undo the effect of psb_gtt_attach_pages. At this point the pages ++ * must have been removed from the GTT as they could now be paged out ++ * and move bus address. This is protected via the gtt mutex which the ++ * caller must hold. ++ */ ++static void psb_gtt_detach_pages(struct gtt_range *gt) ++{ ++ int i; ++ for (i = 0; i < gt->npage; i++) { ++ /* FIXME: do we need to force dirty */ ++ set_page_dirty(gt->pages[i]); ++ page_cache_release(gt->pages[i]); ++ } ++ kfree(gt->pages); ++ gt->pages = NULL; ++} ++ ++/** ++ * psb_gtt_pin - pin pages into the GTT ++ * @gt: range to pin ++ * ++ * Pin a set of pages into the GTT. The pins are refcounted so that ++ * multiple pins need multiple unpins to undo. ++ * ++ * Non GEM backed objects treat this as a no-op as they are always GTT ++ * backed objects. ++ */ ++int psb_gtt_pin(struct gtt_range *gt) ++{ ++ int ret = 0; ++ struct drm_device *dev = gt->gem.dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ mutex_lock(&dev_priv->gtt_mutex); ++ ++ if (gt->in_gart == 0 && gt->stolen == 0) { ++ ret = psb_gtt_attach_pages(gt); ++ if (ret < 0) ++ goto out; ++ ret = psb_gtt_insert(dev, gt); ++ if (ret < 0) { ++ psb_gtt_detach_pages(gt); ++ goto out; ++ } ++ } ++ gt->in_gart++; ++out: ++ mutex_unlock(&dev_priv->gtt_mutex); ++ return ret; ++} ++ ++/** ++ * psb_gtt_unpin - Drop a GTT pin requirement ++ * @gt: range to pin ++ * ++ * Undoes the effect of psb_gtt_pin. On the last drop the GEM object ++ * will be removed from the GTT which will also drop the page references ++ * and allow the VM to clean up or page stuff. ++ * ++ * Non GEM backed objects treat this as a no-op as they are always GTT ++ * backed objects. ++ */ ++void psb_gtt_unpin(struct gtt_range *gt) ++{ ++ struct drm_device *dev = gt->gem.dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ mutex_lock(&dev_priv->gtt_mutex); ++ ++ WARN_ON(!gt->in_gart); ++ ++ gt->in_gart--; ++ if (gt->in_gart == 0 && gt->stolen == 0) { ++ psb_gtt_remove(dev, gt); ++ psb_gtt_detach_pages(gt); ++ } ++ mutex_unlock(&dev_priv->gtt_mutex); ++} ++ ++/* ++ * GTT resource allocator - allocate and manage GTT address space ++ */ ++ ++/** ++ * psb_gtt_alloc_range - allocate GTT address space ++ * @dev: Our DRM device ++ * @len: length (bytes) of address space required ++ * @name: resource name ++ * @backed: resource should be backed by stolen pages ++ * ++ * Ask the kernel core to find us a suitable range of addresses ++ * to use for a GTT mapping. ++ * ++ * Returns a gtt_range structure describing the object, or NULL on ++ * error. On successful return the resource is both allocated and marked ++ * as in use. ++ */ ++struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, ++ const char *name, int backed) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct gtt_range *gt; ++ struct resource *r = dev_priv->gtt_mem; ++ int ret; ++ unsigned long start, end; ++ ++ if (backed) { ++ /* The start of the GTT is the stolen pages */ ++ start = r->start; ++ end = r->start + dev_priv->gtt.stolen_size - 1; ++ } else { ++ /* The rest we will use for GEM backed objects */ ++ start = r->start + dev_priv->gtt.stolen_size; ++ end = r->end; ++ } ++ ++ gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL); ++ if (gt == NULL) ++ return NULL; ++ gt->resource.name = name; ++ gt->stolen = backed; ++ gt->in_gart = backed; ++ gt->roll = 0; ++ /* Ensure this is set for non GEM objects */ ++ gt->gem.dev = dev; ++ ret = allocate_resource(dev_priv->gtt_mem, >->resource, ++ len, start, end, PAGE_SIZE, NULL, NULL); ++ if (ret == 0) { ++ gt->offset = gt->resource.start - r->start; ++ return gt; ++ } ++ kfree(gt); ++ return NULL; ++} ++ ++/** ++ * psb_gtt_free_range - release GTT address space ++ * @dev: our DRM device ++ * @gt: a mapping created with psb_gtt_alloc_range ++ * ++ * Release a resource that was allocated with psb_gtt_alloc_range. If the ++ * object has been pinned by mmap users we clean this up here currently. ++ */ ++void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt) ++{ ++ /* Undo the mmap pin if we are destroying the object */ ++ if (gt->mmapping) { ++ psb_gtt_unpin(gt); ++ gt->mmapping = 0; ++ } ++ WARN_ON(gt->in_gart && !gt->stolen); ++ release_resource(>->resource); ++ kfree(gt); ++} ++ ++static void psb_gtt_alloc(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ init_rwsem(&dev_priv->gtt.sem); ++} ++ ++void psb_gtt_takedown(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (dev_priv->gtt_map) { ++ iounmap(dev_priv->gtt_map); ++ dev_priv->gtt_map = NULL; ++ } ++ if (dev_priv->gtt_initialized) { ++ pci_write_config_word(dev->pdev, PSB_GMCH_CTRL, ++ dev_priv->gmch_ctrl); ++ PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); ++ (void) PSB_RVDC32(PSB_PGETBL_CTL); ++ } ++ if (dev_priv->vram_addr) ++ iounmap(dev_priv->gtt_map); ++} ++ ++int psb_gtt_init(struct drm_device *dev, int resume) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ unsigned gtt_pages; ++ unsigned long stolen_size, vram_stolen_size; ++ unsigned i, num_pages; ++ unsigned pfn_base; ++ uint32_t vram_pages; ++ uint32_t dvmt_mode = 0; ++ struct psb_gtt *pg; ++ ++ int ret = 0; ++ uint32_t pte; ++ ++ mutex_init(&dev_priv->gtt_mutex); ++ ++ psb_gtt_alloc(dev); ++ pg = &dev_priv->gtt; ++ ++ /* Enable the GTT */ ++ pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl); ++ pci_write_config_word(dev->pdev, PSB_GMCH_CTRL, ++ dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); ++ ++ dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL); ++ PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); ++ (void) PSB_RVDC32(PSB_PGETBL_CTL); ++ ++ /* The root resource we allocate address space from */ ++ dev_priv->gtt_initialized = 1; ++ ++ pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; ++ ++ /* ++ * The video mmu has a hw bug when accessing 0x0D0000000. ++ * Make gatt start at 0x0e000,0000. This doesn't actually ++ * matter for us but may do if the video acceleration ever ++ * gets opened up. ++ */ ++ pg->mmu_gatt_start = 0xE0000000; ++ ++ pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE); ++ gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) ++ >> PAGE_SHIFT; ++ /* CDV doesn't report this. In which case the system has 64 gtt pages */ ++ if (pg->gtt_start == 0 || gtt_pages == 0) { ++ dev_dbg(dev->dev, "GTT PCI BAR not initialized.\n"); ++ gtt_pages = 64; ++ pg->gtt_start = dev_priv->pge_ctl; ++ } ++ ++ pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE); ++ pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE) ++ >> PAGE_SHIFT; ++ dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE]; ++ ++ if (pg->gatt_pages == 0 || pg->gatt_start == 0) { ++ static struct resource fudge; /* Preferably peppermint */ ++ /* This can occur on CDV systems. Fudge it in this case. ++ We really don't care what imaginary space is being allocated ++ at this point */ ++ dev_dbg(dev->dev, "GATT PCI BAR not initialized.\n"); ++ pg->gatt_start = 0x40000000; ++ pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT; ++ /* This is a little confusing but in fact the GTT is providing ++ a view from the GPU into memory and not vice versa. As such ++ this is really allocating space that is not the same as the ++ CPU address space on CDV */ ++ fudge.start = 0x40000000; ++ fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1; ++ fudge.name = "fudge"; ++ fudge.flags = IORESOURCE_MEM; ++ dev_priv->gtt_mem = &fudge; ++ } ++ ++ pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base); ++ vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base ++ - PAGE_SIZE; ++ ++ stolen_size = vram_stolen_size; ++ ++ printk(KERN_INFO "Stolen memory information\n"); ++ printk(KERN_INFO " base in RAM: 0x%x\n", dev_priv->stolen_base); ++ printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n", ++ vram_stolen_size/1024); ++ dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7; ++ printk(KERN_INFO " the correct size should be: %dM(dvmt mode=%d)\n", ++ (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode); ++ ++ if (resume && (gtt_pages != pg->gtt_pages) && ++ (stolen_size != pg->stolen_size)) { ++ dev_err(dev->dev, "GTT resume error.\n"); ++ ret = -EINVAL; ++ goto out_err; ++ } ++ ++ pg->gtt_pages = gtt_pages; ++ pg->stolen_size = stolen_size; ++ dev_priv->vram_stolen_size = vram_stolen_size; ++ ++ /* ++ * Map the GTT and the stolen memory area ++ */ ++ dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start, ++ gtt_pages << PAGE_SHIFT); ++ if (!dev_priv->gtt_map) { ++ dev_err(dev->dev, "Failure to map gtt.\n"); ++ ret = -ENOMEM; ++ goto out_err; ++ } ++ ++ dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size); ++ if (!dev_priv->vram_addr) { ++ dev_err(dev->dev, "Failure to map stolen base.\n"); ++ ret = -ENOMEM; ++ goto out_err; ++ } ++ ++ /* ++ * Insert vram stolen pages into the GTT ++ */ ++ ++ pfn_base = dev_priv->stolen_base >> PAGE_SHIFT; ++ vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT; ++ printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n", ++ num_pages, pfn_base << PAGE_SHIFT, 0); ++ for (i = 0; i < num_pages; ++i) { ++ pte = psb_gtt_mask_pte(pfn_base + i, 0); ++ iowrite32(pte, dev_priv->gtt_map + i); ++ } ++ ++ /* ++ * Init rest of GTT to the scratch page to avoid accidents or scribbles ++ */ ++ ++ pfn_base = page_to_pfn(dev_priv->scratch_page); ++ pte = psb_gtt_mask_pte(pfn_base, 0); ++ for (; i < gtt_pages; ++i) ++ iowrite32(pte, dev_priv->gtt_map + i); ++ ++ (void) ioread32(dev_priv->gtt_map + i - 1); ++ return 0; ++ ++out_err: ++ psb_gtt_takedown(dev); ++ return ret; ++} +diff --git a/drivers/gpu/drm/gma500/gtt.h b/drivers/gpu/drm/gma500/gtt.h +new file mode 100644 +index 0000000..aa17423 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/gtt.h +@@ -0,0 +1,64 @@ ++/************************************************************************** ++ * Copyright (c) 2007-2008, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++ ++#ifndef _PSB_GTT_H_ ++#define _PSB_GTT_H_ ++ ++#include ++ ++/* This wants cleaning up with respect to the psb_dev and un-needed stuff */ ++struct psb_gtt { ++ uint32_t gatt_start; ++ uint32_t mmu_gatt_start; ++ uint32_t gtt_start; ++ uint32_t gtt_phys_start; ++ unsigned gtt_pages; ++ unsigned gatt_pages; ++ unsigned long stolen_size; ++ unsigned long vram_stolen_size; ++ struct rw_semaphore sem; ++}; ++ ++/* Exported functions */ ++extern int psb_gtt_init(struct drm_device *dev, int resume); ++extern void psb_gtt_takedown(struct drm_device *dev); ++ ++/* Each gtt_range describes an allocation in the GTT area */ ++struct gtt_range { ++ struct resource resource; /* Resource for our allocation */ ++ u32 offset; /* GTT offset of our object */ ++ struct drm_gem_object gem; /* GEM high level stuff */ ++ int in_gart; /* Currently in the GART (ref ct) */ ++ bool stolen; /* Backed from stolen RAM */ ++ bool mmapping; /* Is mmappable */ ++ struct page **pages; /* Backing pages if present */ ++ int npage; /* Number of backing pages */ ++ int roll; /* Roll applied to the GTT entries */ ++}; ++ ++extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, ++ const char *name, int backed); ++extern void psb_gtt_kref_put(struct gtt_range *gt); ++extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt); ++extern int psb_gtt_pin(struct gtt_range *gt); ++extern void psb_gtt_unpin(struct gtt_range *gt); ++extern void psb_gtt_roll(struct drm_device *dev, ++ struct gtt_range *gt, int roll); ++ ++#endif +diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c +new file mode 100644 +index 0000000..d4d0c5b +--- /dev/null ++++ b/drivers/gpu/drm/gma500/intel_bios.c +@@ -0,0 +1,303 @@ ++/* ++ * Copyright (c) 2006 Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: ++ * Eric Anholt ++ * ++ */ ++#include ++#include ++#include "gma_drm.h" ++#include "psb_drv.h" ++#include "psb_intel_drv.h" ++#include "psb_intel_reg.h" ++#include "intel_bios.h" ++ ++ ++static void *find_section(struct bdb_header *bdb, int section_id) ++{ ++ u8 *base = (u8 *)bdb; ++ int index = 0; ++ u16 total, current_size; ++ u8 current_id; ++ ++ /* skip to first section */ ++ index += bdb->header_size; ++ total = bdb->bdb_size; ++ ++ /* walk the sections looking for section_id */ ++ while (index < total) { ++ current_id = *(base + index); ++ index++; ++ current_size = *((u16 *)(base + index)); ++ index += 2; ++ if (current_id == section_id) ++ return base + index; ++ index += current_size; ++ } ++ ++ return NULL; ++} ++ ++static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, ++ struct lvds_dvo_timing *dvo_timing) ++{ ++ panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | ++ dvo_timing->hactive_lo; ++ panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + ++ ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); ++ panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + ++ dvo_timing->hsync_pulse_width; ++ panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + ++ ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); ++ ++ panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | ++ dvo_timing->vactive_lo; ++ panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + ++ dvo_timing->vsync_off; ++ panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + ++ dvo_timing->vsync_pulse_width; ++ panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + ++ ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); ++ panel_fixed_mode->clock = dvo_timing->clock * 10; ++ panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; ++ ++ /* Some VBTs have bogus h/vtotal values */ ++ if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) ++ panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; ++ if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) ++ panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; ++ ++ drm_mode_set_name(panel_fixed_mode); ++} ++ ++static void parse_backlight_data(struct drm_psb_private *dev_priv, ++ struct bdb_header *bdb) ++{ ++ struct bdb_lvds_backlight *vbt_lvds_bl = NULL; ++ struct bdb_lvds_backlight *lvds_bl; ++ u8 p_type = 0; ++ void *bl_start = NULL; ++ struct bdb_lvds_options *lvds_opts ++ = find_section(bdb, BDB_LVDS_OPTIONS); ++ ++ dev_priv->lvds_bl = NULL; ++ ++ if (lvds_opts) ++ p_type = lvds_opts->panel_type; ++ else ++ return; ++ ++ bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT); ++ vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type; ++ ++ lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL); ++ if (!lvds_bl) { ++ dev_err(dev_priv->dev->dev, "out of memory for backlight data\n"); ++ return; ++ } ++ memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl)); ++ dev_priv->lvds_bl = lvds_bl; ++} ++ ++/* Try to find integrated panel data */ ++static void parse_lfp_panel_data(struct drm_psb_private *dev_priv, ++ struct bdb_header *bdb) ++{ ++ struct bdb_lvds_options *lvds_options; ++ struct bdb_lvds_lfp_data *lvds_lfp_data; ++ struct bdb_lvds_lfp_data_entry *entry; ++ struct lvds_dvo_timing *dvo_timing; ++ struct drm_display_mode *panel_fixed_mode; ++ ++ /* Defaults if we can't find VBT info */ ++ dev_priv->lvds_dither = 0; ++ dev_priv->lvds_vbt = 0; ++ ++ lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); ++ if (!lvds_options) ++ return; ++ ++ dev_priv->lvds_dither = lvds_options->pixel_dither; ++ if (lvds_options->panel_type == 0xff) ++ return; ++ ++ lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); ++ if (!lvds_lfp_data) ++ return; ++ ++ ++ entry = &lvds_lfp_data->data[lvds_options->panel_type]; ++ dvo_timing = &entry->dvo_timing; ++ ++ panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), ++ GFP_KERNEL); ++ if (panel_fixed_mode == NULL) { ++ dev_err(dev_priv->dev->dev, "out of memory for fixed panel mode\n"); ++ return; ++ } ++ ++ dev_priv->lvds_vbt = 1; ++ fill_detail_timing_data(panel_fixed_mode, dvo_timing); ++ ++ if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) { ++ dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; ++ drm_mode_debug_printmodeline(panel_fixed_mode); ++ } else { ++ dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n"); ++ dev_priv->lvds_vbt = 0; ++ kfree(panel_fixed_mode); ++ } ++ return; ++} ++ ++/* Try to find sdvo panel data */ ++static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv, ++ struct bdb_header *bdb) ++{ ++ struct bdb_sdvo_lvds_options *sdvo_lvds_options; ++ struct lvds_dvo_timing *dvo_timing; ++ struct drm_display_mode *panel_fixed_mode; ++ ++ dev_priv->sdvo_lvds_vbt_mode = NULL; ++ ++ sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); ++ if (!sdvo_lvds_options) ++ return; ++ ++ dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); ++ if (!dvo_timing) ++ return; ++ ++ panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); ++ ++ if (!panel_fixed_mode) ++ return; ++ ++ fill_detail_timing_data(panel_fixed_mode, ++ dvo_timing + sdvo_lvds_options->panel_type); ++ ++ dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; ++ ++ return; ++} ++ ++static void parse_general_features(struct drm_psb_private *dev_priv, ++ struct bdb_header *bdb) ++{ ++ struct bdb_general_features *general; ++ ++ /* Set sensible defaults in case we can't find the general block */ ++ dev_priv->int_tv_support = 1; ++ dev_priv->int_crt_support = 1; ++ ++ general = find_section(bdb, BDB_GENERAL_FEATURES); ++ if (general) { ++ dev_priv->int_tv_support = general->int_tv_support; ++ dev_priv->int_crt_support = general->int_crt_support; ++ dev_priv->lvds_use_ssc = general->enable_ssc; ++ ++ if (dev_priv->lvds_use_ssc) { ++ dev_priv->lvds_ssc_freq ++ = general->ssc_freq ? 100 : 96; ++ } ++ } ++} ++ ++/** ++ * psb_intel_init_bios - initialize VBIOS settings & find VBT ++ * @dev: DRM device ++ * ++ * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers ++ * to appropriate values. ++ * ++ * VBT existence is a sanity check that is relied on by other i830_bios.c code. ++ * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may ++ * feed an updated VBT back through that, compared to what we'll fetch using ++ * this method of groping around in the BIOS data. ++ * ++ * Returns 0 on success, nonzero on failure. ++ */ ++bool psb_intel_init_bios(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct pci_dev *pdev = dev->pdev; ++ struct vbt_header *vbt = NULL; ++ struct bdb_header *bdb; ++ u8 __iomem *bios; ++ size_t size; ++ int i; ++ ++ bios = pci_map_rom(pdev, &size); ++ if (!bios) ++ return -1; ++ ++ /* Scour memory looking for the VBT signature */ ++ for (i = 0; i + 4 < size; i++) { ++ if (!memcmp(bios + i, "$VBT", 4)) { ++ vbt = (struct vbt_header *)(bios + i); ++ break; ++ } ++ } ++ ++ if (!vbt) { ++ dev_err(dev->dev, "VBT signature missing\n"); ++ pci_unmap_rom(pdev, bios); ++ return -1; ++ } ++ ++ bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); ++ ++ /* Grab useful general definitions */ ++ parse_general_features(dev_priv, bdb); ++ parse_lfp_panel_data(dev_priv, bdb); ++ parse_sdvo_panel_data(dev_priv, bdb); ++ parse_backlight_data(dev_priv, bdb); ++ ++ pci_unmap_rom(pdev, bios); ++ ++ return 0; ++} ++ ++/** ++ * Destroy and free VBT data ++ */ ++void psb_intel_destroy_bios(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct drm_display_mode *sdvo_lvds_vbt_mode = ++ dev_priv->sdvo_lvds_vbt_mode; ++ struct drm_display_mode *lfp_lvds_vbt_mode = ++ dev_priv->lfp_lvds_vbt_mode; ++ struct bdb_lvds_backlight *lvds_bl = ++ dev_priv->lvds_bl; ++ ++ /*free sdvo panel mode*/ ++ if (sdvo_lvds_vbt_mode) { ++ dev_priv->sdvo_lvds_vbt_mode = NULL; ++ kfree(sdvo_lvds_vbt_mode); ++ } ++ ++ if (lfp_lvds_vbt_mode) { ++ dev_priv->lfp_lvds_vbt_mode = NULL; ++ kfree(lfp_lvds_vbt_mode); ++ } ++ ++ if (lvds_bl) { ++ dev_priv->lvds_bl = NULL; ++ kfree(lvds_bl); ++ } ++} +diff --git a/drivers/gpu/drm/gma500/intel_bios.h b/drivers/gpu/drm/gma500/intel_bios.h +new file mode 100644 +index 0000000..70f1bf0 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/intel_bios.h +@@ -0,0 +1,430 @@ ++/* ++ * Copyright (c) 2006 Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: ++ * Eric Anholt ++ * ++ */ ++ ++#ifndef _I830_BIOS_H_ ++#define _I830_BIOS_H_ ++ ++#include ++ ++struct vbt_header { ++ u8 signature[20]; /**< Always starts with 'VBT$' */ ++ u16 version; /**< decimal */ ++ u16 header_size; /**< in bytes */ ++ u16 vbt_size; /**< in bytes */ ++ u8 vbt_checksum; ++ u8 reserved0; ++ u32 bdb_offset; /**< from beginning of VBT */ ++ u32 aim_offset[4]; /**< from beginning of VBT */ ++} __attribute__((packed)); ++ ++ ++struct bdb_header { ++ u8 signature[16]; /**< Always 'BIOS_DATA_BLOCK' */ ++ u16 version; /**< decimal */ ++ u16 header_size; /**< in bytes */ ++ u16 bdb_size; /**< in bytes */ ++}; ++ ++/* strictly speaking, this is a "skip" block, but it has interesting info */ ++struct vbios_data { ++ u8 type; /* 0 == desktop, 1 == mobile */ ++ u8 relstage; ++ u8 chipset; ++ u8 lvds_present:1; ++ u8 tv_present:1; ++ u8 rsvd2:6; /* finish byte */ ++ u8 rsvd3[4]; ++ u8 signon[155]; ++ u8 copyright[61]; ++ u16 code_segment; ++ u8 dos_boot_mode; ++ u8 bandwidth_percent; ++ u8 rsvd4; /* popup memory size */ ++ u8 resize_pci_bios; ++ u8 rsvd5; /* is crt already on ddc2 */ ++} __attribute__((packed)); ++ ++/* ++ * There are several types of BIOS data blocks (BDBs), each block has ++ * an ID and size in the first 3 bytes (ID in first, size in next 2). ++ * Known types are listed below. ++ */ ++#define BDB_GENERAL_FEATURES 1 ++#define BDB_GENERAL_DEFINITIONS 2 ++#define BDB_OLD_TOGGLE_LIST 3 ++#define BDB_MODE_SUPPORT_LIST 4 ++#define BDB_GENERIC_MODE_TABLE 5 ++#define BDB_EXT_MMIO_REGS 6 ++#define BDB_SWF_IO 7 ++#define BDB_SWF_MMIO 8 ++#define BDB_DOT_CLOCK_TABLE 9 ++#define BDB_MODE_REMOVAL_TABLE 10 ++#define BDB_CHILD_DEVICE_TABLE 11 ++#define BDB_DRIVER_FEATURES 12 ++#define BDB_DRIVER_PERSISTENCE 13 ++#define BDB_EXT_TABLE_PTRS 14 ++#define BDB_DOT_CLOCK_OVERRIDE 15 ++#define BDB_DISPLAY_SELECT 16 ++/* 17 rsvd */ ++#define BDB_DRIVER_ROTATION 18 ++#define BDB_DISPLAY_REMOVE 19 ++#define BDB_OEM_CUSTOM 20 ++#define BDB_EFP_LIST 21 /* workarounds for VGA hsync/vsync */ ++#define BDB_SDVO_LVDS_OPTIONS 22 ++#define BDB_SDVO_PANEL_DTDS 23 ++#define BDB_SDVO_LVDS_PNP_IDS 24 ++#define BDB_SDVO_LVDS_POWER_SEQ 25 ++#define BDB_TV_OPTIONS 26 ++#define BDB_LVDS_OPTIONS 40 ++#define BDB_LVDS_LFP_DATA_PTRS 41 ++#define BDB_LVDS_LFP_DATA 42 ++#define BDB_LVDS_BACKLIGHT 43 ++#define BDB_LVDS_POWER 44 ++#define BDB_SKIP 254 /* VBIOS private block, ignore */ ++ ++struct bdb_general_features { ++ /* bits 1 */ ++ u8 panel_fitting:2; ++ u8 flexaim:1; ++ u8 msg_enable:1; ++ u8 clear_screen:3; ++ u8 color_flip:1; ++ ++ /* bits 2 */ ++ u8 download_ext_vbt:1; ++ u8 enable_ssc:1; ++ u8 ssc_freq:1; ++ u8 enable_lfp_on_override:1; ++ u8 disable_ssc_ddt:1; ++ u8 rsvd8:3; /* finish byte */ ++ ++ /* bits 3 */ ++ u8 disable_smooth_vision:1; ++ u8 single_dvi:1; ++ u8 rsvd9:6; /* finish byte */ ++ ++ /* bits 4 */ ++ u8 legacy_monitor_detect; ++ ++ /* bits 5 */ ++ u8 int_crt_support:1; ++ u8 int_tv_support:1; ++ u8 rsvd11:6; /* finish byte */ ++} __attribute__((packed)); ++ ++struct bdb_general_definitions { ++ /* DDC GPIO */ ++ u8 crt_ddc_gmbus_pin; ++ ++ /* DPMS bits */ ++ u8 dpms_acpi:1; ++ u8 skip_boot_crt_detect:1; ++ u8 dpms_aim:1; ++ u8 rsvd1:5; /* finish byte */ ++ ++ /* boot device bits */ ++ u8 boot_display[2]; ++ u8 child_dev_size; ++ ++ /* device info */ ++ u8 tv_or_lvds_info[33]; ++ u8 dev1[33]; ++ u8 dev2[33]; ++ u8 dev3[33]; ++ u8 dev4[33]; ++ /* may be another device block here on some platforms */ ++}; ++ ++struct bdb_lvds_options { ++ u8 panel_type; ++ u8 rsvd1; ++ /* LVDS capabilities, stored in a dword */ ++ u8 pfit_mode:2; ++ u8 pfit_text_mode_enhanced:1; ++ u8 pfit_gfx_mode_enhanced:1; ++ u8 pfit_ratio_auto:1; ++ u8 pixel_dither:1; ++ u8 lvds_edid:1; ++ u8 rsvd2:1; ++ u8 rsvd4; ++} __attribute__((packed)); ++ ++struct bdb_lvds_backlight { ++ u8 type:2; ++ u8 pol:1; ++ u8 gpio:3; ++ u8 gmbus:2; ++ u16 freq; ++ u8 minbrightness; ++ u8 i2caddr; ++ u8 brightnesscmd; ++ /*FIXME: more...*/ ++} __attribute__((packed)); ++ ++/* LFP pointer table contains entries to the struct below */ ++struct bdb_lvds_lfp_data_ptr { ++ u16 fp_timing_offset; /* offsets are from start of bdb */ ++ u8 fp_table_size; ++ u16 dvo_timing_offset; ++ u8 dvo_table_size; ++ u16 panel_pnp_id_offset; ++ u8 pnp_table_size; ++} __attribute__((packed)); ++ ++struct bdb_lvds_lfp_data_ptrs { ++ u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */ ++ struct bdb_lvds_lfp_data_ptr ptr[16]; ++} __attribute__((packed)); ++ ++/* LFP data has 3 blocks per entry */ ++struct lvds_fp_timing { ++ u16 x_res; ++ u16 y_res; ++ u32 lvds_reg; ++ u32 lvds_reg_val; ++ u32 pp_on_reg; ++ u32 pp_on_reg_val; ++ u32 pp_off_reg; ++ u32 pp_off_reg_val; ++ u32 pp_cycle_reg; ++ u32 pp_cycle_reg_val; ++ u32 pfit_reg; ++ u32 pfit_reg_val; ++ u16 terminator; ++} __attribute__((packed)); ++ ++struct lvds_dvo_timing { ++ u16 clock; /**< In 10khz */ ++ u8 hactive_lo; ++ u8 hblank_lo; ++ u8 hblank_hi:4; ++ u8 hactive_hi:4; ++ u8 vactive_lo; ++ u8 vblank_lo; ++ u8 vblank_hi:4; ++ u8 vactive_hi:4; ++ u8 hsync_off_lo; ++ u8 hsync_pulse_width; ++ u8 vsync_pulse_width:4; ++ u8 vsync_off:4; ++ u8 rsvd0:6; ++ u8 hsync_off_hi:2; ++ u8 h_image; ++ u8 v_image; ++ u8 max_hv; ++ u8 h_border; ++ u8 v_border; ++ u8 rsvd1:3; ++ u8 digital:2; ++ u8 vsync_positive:1; ++ u8 hsync_positive:1; ++ u8 rsvd2:1; ++} __attribute__((packed)); ++ ++struct lvds_pnp_id { ++ u16 mfg_name; ++ u16 product_code; ++ u32 serial; ++ u8 mfg_week; ++ u8 mfg_year; ++} __attribute__((packed)); ++ ++struct bdb_lvds_lfp_data_entry { ++ struct lvds_fp_timing fp_timing; ++ struct lvds_dvo_timing dvo_timing; ++ struct lvds_pnp_id pnp_id; ++} __attribute__((packed)); ++ ++struct bdb_lvds_lfp_data { ++ struct bdb_lvds_lfp_data_entry data[16]; ++} __attribute__((packed)); ++ ++struct aimdb_header { ++ char signature[16]; ++ char oem_device[20]; ++ u16 aimdb_version; ++ u16 aimdb_header_size; ++ u16 aimdb_size; ++} __attribute__((packed)); ++ ++struct aimdb_block { ++ u8 aimdb_id; ++ u16 aimdb_size; ++} __attribute__((packed)); ++ ++struct vch_panel_data { ++ u16 fp_timing_offset; ++ u8 fp_timing_size; ++ u16 dvo_timing_offset; ++ u8 dvo_timing_size; ++ u16 text_fitting_offset; ++ u8 text_fitting_size; ++ u16 graphics_fitting_offset; ++ u8 graphics_fitting_size; ++} __attribute__((packed)); ++ ++struct vch_bdb_22 { ++ struct aimdb_block aimdb_block; ++ struct vch_panel_data panels[16]; ++} __attribute__((packed)); ++ ++struct bdb_sdvo_lvds_options { ++ u8 panel_backlight; ++ u8 h40_set_panel_type; ++ u8 panel_type; ++ u8 ssc_clk_freq; ++ u16 als_low_trip; ++ u16 als_high_trip; ++ u8 sclalarcoeff_tab_row_num; ++ u8 sclalarcoeff_tab_row_size; ++ u8 coefficient[8]; ++ u8 panel_misc_bits_1; ++ u8 panel_misc_bits_2; ++ u8 panel_misc_bits_3; ++ u8 panel_misc_bits_4; ++} __attribute__((packed)); ++ ++ ++extern bool psb_intel_init_bios(struct drm_device *dev); ++extern void psb_intel_destroy_bios(struct drm_device *dev); ++ ++/* ++ * Driver<->VBIOS interaction occurs through scratch bits in ++ * GR18 & SWF*. ++ */ ++ ++/* GR18 bits are set on display switch and hotkey events */ ++#define GR18_DRIVER_SWITCH_EN (1<<7) /* 0: VBIOS control, 1: driver control */ ++#define GR18_HOTKEY_MASK 0x78 /* See also SWF4 15:0 */ ++#define GR18_HK_NONE (0x0<<3) ++#define GR18_HK_LFP_STRETCH (0x1<<3) ++#define GR18_HK_TOGGLE_DISP (0x2<<3) ++#define GR18_HK_DISP_SWITCH (0x4<<3) /* see SWF14 15:0 for what to enable */ ++#define GR18_HK_POPUP_DISABLED (0x6<<3) ++#define GR18_HK_POPUP_ENABLED (0x7<<3) ++#define GR18_HK_PFIT (0x8<<3) ++#define GR18_HK_APM_CHANGE (0xa<<3) ++#define GR18_HK_MULTIPLE (0xc<<3) ++#define GR18_USER_INT_EN (1<<2) ++#define GR18_A0000_FLUSH_EN (1<<1) ++#define GR18_SMM_EN (1<<0) ++ ++/* Set by driver, cleared by VBIOS */ ++#define SWF00_YRES_SHIFT 16 ++#define SWF00_XRES_SHIFT 0 ++#define SWF00_RES_MASK 0xffff ++ ++/* Set by VBIOS at boot time and driver at runtime */ ++#define SWF01_TV2_FORMAT_SHIFT 8 ++#define SWF01_TV1_FORMAT_SHIFT 0 ++#define SWF01_TV_FORMAT_MASK 0xffff ++ ++#define SWF10_VBIOS_BLC_I2C_EN (1<<29) ++#define SWF10_GTT_OVERRIDE_EN (1<<28) ++#define SWF10_LFP_DPMS_OVR (1<<27) /* override DPMS on display switch */ ++#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24) ++#define SWF10_OLD_TOGGLE 0x0 ++#define SWF10_TOGGLE_LIST_1 0x1 ++#define SWF10_TOGGLE_LIST_2 0x2 ++#define SWF10_TOGGLE_LIST_3 0x3 ++#define SWF10_TOGGLE_LIST_4 0x4 ++#define SWF10_PANNING_EN (1<<23) ++#define SWF10_DRIVER_LOADED (1<<22) ++#define SWF10_EXTENDED_DESKTOP (1<<21) ++#define SWF10_EXCLUSIVE_MODE (1<<20) ++#define SWF10_OVERLAY_EN (1<<19) ++#define SWF10_PLANEB_HOLDOFF (1<<18) ++#define SWF10_PLANEA_HOLDOFF (1<<17) ++#define SWF10_VGA_HOLDOFF (1<<16) ++#define SWF10_ACTIVE_DISP_MASK 0xffff ++#define SWF10_PIPEB_LFP2 (1<<15) ++#define SWF10_PIPEB_EFP2 (1<<14) ++#define SWF10_PIPEB_TV2 (1<<13) ++#define SWF10_PIPEB_CRT2 (1<<12) ++#define SWF10_PIPEB_LFP (1<<11) ++#define SWF10_PIPEB_EFP (1<<10) ++#define SWF10_PIPEB_TV (1<<9) ++#define SWF10_PIPEB_CRT (1<<8) ++#define SWF10_PIPEA_LFP2 (1<<7) ++#define SWF10_PIPEA_EFP2 (1<<6) ++#define SWF10_PIPEA_TV2 (1<<5) ++#define SWF10_PIPEA_CRT2 (1<<4) ++#define SWF10_PIPEA_LFP (1<<3) ++#define SWF10_PIPEA_EFP (1<<2) ++#define SWF10_PIPEA_TV (1<<1) ++#define SWF10_PIPEA_CRT (1<<0) ++ ++#define SWF11_MEMORY_SIZE_SHIFT 16 ++#define SWF11_SV_TEST_EN (1<<15) ++#define SWF11_IS_AGP (1<<14) ++#define SWF11_DISPLAY_HOLDOFF (1<<13) ++#define SWF11_DPMS_REDUCED (1<<12) ++#define SWF11_IS_VBE_MODE (1<<11) ++#define SWF11_PIPEB_ACCESS (1<<10) /* 0 here means pipe a */ ++#define SWF11_DPMS_MASK 0x07 ++#define SWF11_DPMS_OFF (1<<2) ++#define SWF11_DPMS_SUSPEND (1<<1) ++#define SWF11_DPMS_STANDBY (1<<0) ++#define SWF11_DPMS_ON 0 ++ ++#define SWF14_GFX_PFIT_EN (1<<31) ++#define SWF14_TEXT_PFIT_EN (1<<30) ++#define SWF14_LID_STATUS_CLOSED (1<<29) /* 0 here means open */ ++#define SWF14_POPUP_EN (1<<28) ++#define SWF14_DISPLAY_HOLDOFF (1<<27) ++#define SWF14_DISP_DETECT_EN (1<<26) ++#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */ ++#define SWF14_DRIVER_STATUS (1<<24) ++#define SWF14_OS_TYPE_WIN9X (1<<23) ++#define SWF14_OS_TYPE_WINNT (1<<22) ++/* 21:19 rsvd */ ++#define SWF14_PM_TYPE_MASK 0x00070000 ++#define SWF14_PM_ACPI_VIDEO (0x4 << 16) ++#define SWF14_PM_ACPI (0x3 << 16) ++#define SWF14_PM_APM_12 (0x2 << 16) ++#define SWF14_PM_APM_11 (0x1 << 16) ++#define SWF14_HK_REQUEST_MASK 0x0000ffff /* see GR18 6:3 for event type */ ++ /* if GR18 indicates a display switch */ ++#define SWF14_DS_PIPEB_LFP2_EN (1<<15) ++#define SWF14_DS_PIPEB_EFP2_EN (1<<14) ++#define SWF14_DS_PIPEB_TV2_EN (1<<13) ++#define SWF14_DS_PIPEB_CRT2_EN (1<<12) ++#define SWF14_DS_PIPEB_LFP_EN (1<<11) ++#define SWF14_DS_PIPEB_EFP_EN (1<<10) ++#define SWF14_DS_PIPEB_TV_EN (1<<9) ++#define SWF14_DS_PIPEB_CRT_EN (1<<8) ++#define SWF14_DS_PIPEA_LFP2_EN (1<<7) ++#define SWF14_DS_PIPEA_EFP2_EN (1<<6) ++#define SWF14_DS_PIPEA_TV2_EN (1<<5) ++#define SWF14_DS_PIPEA_CRT2_EN (1<<4) ++#define SWF14_DS_PIPEA_LFP_EN (1<<3) ++#define SWF14_DS_PIPEA_EFP_EN (1<<2) ++#define SWF14_DS_PIPEA_TV_EN (1<<1) ++#define SWF14_DS_PIPEA_CRT_EN (1<<0) ++ /* if GR18 indicates a panel fitting request */ ++#define SWF14_PFIT_EN (1<<0) /* 0 means disable */ ++ /* if GR18 indicates an APM change request */ ++#define SWF14_APM_HIBERNATE 0x4 ++#define SWF14_APM_SUSPEND 0x3 ++#define SWF14_APM_STANDBY 0x1 ++#define SWF14_APM_RESTORE 0x0 ++ ++#endif /* _I830_BIOS_H_ */ +diff --git a/drivers/gpu/drm/gma500/intel_gmbus.c b/drivers/gpu/drm/gma500/intel_gmbus.c +new file mode 100644 +index 0000000..9db9052 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/intel_gmbus.c +@@ -0,0 +1,493 @@ ++/* ++ * Copyright (c) 2006 Dave Airlie ++ * Copyright © 2006-2008,2010 Intel Corporation ++ * Jesse Barnes ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Eric Anholt ++ * Chris Wilson ++ */ ++#include ++#include ++#include ++#include "drmP.h" ++#include "drm.h" ++#include "psb_intel_drv.h" ++#include "gma_drm.h" ++#include "psb_drv.h" ++#include "psb_intel_reg.h" ++ ++#define _wait_for(COND, MS, W) ({ \ ++ unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ ++ int ret__ = 0; \ ++ while (! (COND)) { \ ++ if (time_after(jiffies, timeout__)) { \ ++ ret__ = -ETIMEDOUT; \ ++ break; \ ++ } \ ++ if (W && !(in_atomic() || in_dbg_master())) msleep(W); \ ++ } \ ++ ret__; \ ++}) ++ ++#define wait_for(COND, MS) _wait_for(COND, MS, 1) ++#define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0) ++ ++/* Intel GPIO access functions */ ++ ++#define I2C_RISEFALL_TIME 20 ++ ++static inline struct intel_gmbus * ++to_intel_gmbus(struct i2c_adapter *i2c) ++{ ++ return container_of(i2c, struct intel_gmbus, adapter); ++} ++ ++struct intel_gpio { ++ struct i2c_adapter adapter; ++ struct i2c_algo_bit_data algo; ++ struct drm_psb_private *dev_priv; ++ u32 reg; ++}; ++ ++void ++gma_intel_i2c_reset(struct drm_device *dev) ++{ ++ REG_WRITE(GMBUS0, 0); ++} ++ ++static void intel_i2c_quirk_set(struct drm_psb_private *dev_priv, bool enable) ++{ ++ /* When using bit bashing for I2C, this bit needs to be set to 1 */ ++ /* FIXME: We are never Pineview, right? ++ ++ u32 val; ++ ++ if (!IS_PINEVIEW(dev_priv->dev)) ++ return; ++ ++ val = REG_READ(DSPCLK_GATE_D); ++ if (enable) ++ val |= DPCUNIT_CLOCK_GATE_DISABLE; ++ else ++ val &= ~DPCUNIT_CLOCK_GATE_DISABLE; ++ REG_WRITE(DSPCLK_GATE_D, val); ++ ++ return; ++ */ ++} ++ ++static u32 get_reserved(struct intel_gpio *gpio) ++{ ++ struct drm_psb_private *dev_priv = gpio->dev_priv; ++ struct drm_device *dev = dev_priv->dev; ++ u32 reserved = 0; ++ ++ /* On most chips, these bits must be preserved in software. */ ++ reserved = REG_READ(gpio->reg) & ++ (GPIO_DATA_PULLUP_DISABLE | ++ GPIO_CLOCK_PULLUP_DISABLE); ++ ++ return reserved; ++} ++ ++static int get_clock(void *data) ++{ ++ struct intel_gpio *gpio = data; ++ struct drm_psb_private *dev_priv = gpio->dev_priv; ++ struct drm_device *dev = dev_priv->dev; ++ u32 reserved = get_reserved(gpio); ++ REG_WRITE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK); ++ REG_WRITE(gpio->reg, reserved); ++ return (REG_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0; ++} ++ ++static int get_data(void *data) ++{ ++ struct intel_gpio *gpio = data; ++ struct drm_psb_private *dev_priv = gpio->dev_priv; ++ struct drm_device *dev = dev_priv->dev; ++ u32 reserved = get_reserved(gpio); ++ REG_WRITE(gpio->reg, reserved | GPIO_DATA_DIR_MASK); ++ REG_WRITE(gpio->reg, reserved); ++ return (REG_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0; ++} ++ ++static void set_clock(void *data, int state_high) ++{ ++ struct intel_gpio *gpio = data; ++ struct drm_psb_private *dev_priv = gpio->dev_priv; ++ struct drm_device *dev = dev_priv->dev; ++ u32 reserved = get_reserved(gpio); ++ u32 clock_bits; ++ ++ if (state_high) ++ clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; ++ else ++ clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | ++ GPIO_CLOCK_VAL_MASK; ++ ++ REG_WRITE(gpio->reg, reserved | clock_bits); ++ REG_READ(gpio->reg); /* Posting */ ++} ++ ++static void set_data(void *data, int state_high) ++{ ++ struct intel_gpio *gpio = data; ++ struct drm_psb_private *dev_priv = gpio->dev_priv; ++ struct drm_device *dev = dev_priv->dev; ++ u32 reserved = get_reserved(gpio); ++ u32 data_bits; ++ ++ if (state_high) ++ data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; ++ else ++ data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | ++ GPIO_DATA_VAL_MASK; ++ ++ REG_WRITE(gpio->reg, reserved | data_bits); ++ REG_READ(gpio->reg); ++} ++ ++static struct i2c_adapter * ++intel_gpio_create(struct drm_psb_private *dev_priv, u32 pin) ++{ ++ static const int map_pin_to_reg[] = { ++ 0, ++ GPIOB, ++ GPIOA, ++ GPIOC, ++ GPIOD, ++ GPIOE, ++ 0, ++ GPIOF, ++ }; ++ struct intel_gpio *gpio; ++ ++ if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin]) ++ return NULL; ++ ++ gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL); ++ if (gpio == NULL) ++ return NULL; ++ ++ gpio->reg = map_pin_to_reg[pin]; ++ gpio->dev_priv = dev_priv; ++ ++ snprintf(gpio->adapter.name, sizeof(gpio->adapter.name), ++ "gma500 GPIO%c", "?BACDE?F"[pin]); ++ gpio->adapter.owner = THIS_MODULE; ++ gpio->adapter.algo_data = &gpio->algo; ++ gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev; ++ gpio->algo.setsda = set_data; ++ gpio->algo.setscl = set_clock; ++ gpio->algo.getsda = get_data; ++ gpio->algo.getscl = get_clock; ++ gpio->algo.udelay = I2C_RISEFALL_TIME; ++ gpio->algo.timeout = usecs_to_jiffies(2200); ++ gpio->algo.data = gpio; ++ ++ if (i2c_bit_add_bus(&gpio->adapter)) ++ goto out_free; ++ ++ return &gpio->adapter; ++ ++out_free: ++ kfree(gpio); ++ return NULL; ++} ++ ++static int ++intel_i2c_quirk_xfer(struct drm_psb_private *dev_priv, ++ struct i2c_adapter *adapter, ++ struct i2c_msg *msgs, ++ int num) ++{ ++ struct intel_gpio *gpio = container_of(adapter, ++ struct intel_gpio, ++ adapter); ++ int ret; ++ ++ gma_intel_i2c_reset(dev_priv->dev); ++ ++ intel_i2c_quirk_set(dev_priv, true); ++ set_data(gpio, 1); ++ set_clock(gpio, 1); ++ udelay(I2C_RISEFALL_TIME); ++ ++ ret = adapter->algo->master_xfer(adapter, msgs, num); ++ ++ set_data(gpio, 1); ++ set_clock(gpio, 1); ++ intel_i2c_quirk_set(dev_priv, false); ++ ++ return ret; ++} ++ ++static int ++gmbus_xfer(struct i2c_adapter *adapter, ++ struct i2c_msg *msgs, ++ int num) ++{ ++ struct intel_gmbus *bus = container_of(adapter, ++ struct intel_gmbus, ++ adapter); ++ struct drm_psb_private *dev_priv = adapter->algo_data; ++ struct drm_device *dev = dev_priv->dev; ++ int i, reg_offset; ++ ++ if (bus->force_bit) ++ return intel_i2c_quirk_xfer(dev_priv, ++ bus->force_bit, msgs, num); ++ ++ reg_offset = 0; ++ ++ REG_WRITE(GMBUS0 + reg_offset, bus->reg0); ++ ++ for (i = 0; i < num; i++) { ++ u16 len = msgs[i].len; ++ u8 *buf = msgs[i].buf; ++ ++ if (msgs[i].flags & I2C_M_RD) { ++ REG_WRITE(GMBUS1 + reg_offset, ++ GMBUS_CYCLE_WAIT | (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | ++ (len << GMBUS_BYTE_COUNT_SHIFT) | ++ (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | ++ GMBUS_SLAVE_READ | GMBUS_SW_RDY); ++ REG_READ(GMBUS2+reg_offset); ++ do { ++ u32 val, loop = 0; ++ ++ if (wait_for(REG_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) ++ goto timeout; ++ if (REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) ++ goto clear_err; ++ ++ val = REG_READ(GMBUS3 + reg_offset); ++ do { ++ *buf++ = val & 0xff; ++ val >>= 8; ++ } while (--len && ++loop < 4); ++ } while (len); ++ } else { ++ u32 val, loop; ++ ++ val = loop = 0; ++ do { ++ val |= *buf++ << (8 * loop); ++ } while (--len && ++loop < 4); ++ ++ REG_WRITE(GMBUS3 + reg_offset, val); ++ REG_WRITE(GMBUS1 + reg_offset, ++ (i + 1 == num ? GMBUS_CYCLE_STOP : GMBUS_CYCLE_WAIT) | ++ (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) | ++ (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | ++ GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); ++ REG_READ(GMBUS2+reg_offset); ++ ++ while (len) { ++ if (wait_for(REG_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) ++ goto timeout; ++ if (REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) ++ goto clear_err; ++ ++ val = loop = 0; ++ do { ++ val |= *buf++ << (8 * loop); ++ } while (--len && ++loop < 4); ++ ++ REG_WRITE(GMBUS3 + reg_offset, val); ++ REG_READ(GMBUS2+reg_offset); ++ } ++ } ++ ++ if (i + 1 < num && wait_for(REG_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50)) ++ goto timeout; ++ if (REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) ++ goto clear_err; ++ } ++ ++ goto done; ++ ++clear_err: ++ /* Toggle the Software Clear Interrupt bit. This has the effect ++ * of resetting the GMBUS controller and so clearing the ++ * BUS_ERROR raised by the slave's NAK. ++ */ ++ REG_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT); ++ REG_WRITE(GMBUS1 + reg_offset, 0); ++ ++done: ++ /* Mark the GMBUS interface as disabled. We will re-enable it at the ++ * start of the next xfer, till then let it sleep. ++ */ ++ REG_WRITE(GMBUS0 + reg_offset, 0); ++ return i; ++ ++timeout: ++ DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n", ++ bus->reg0 & 0xff, bus->adapter.name); ++ REG_WRITE(GMBUS0 + reg_offset, 0); ++ ++ /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ ++ bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff); ++ if (!bus->force_bit) ++ return -ENOMEM; ++ ++ return intel_i2c_quirk_xfer(dev_priv, bus->force_bit, msgs, num); ++} ++ ++static u32 gmbus_func(struct i2c_adapter *adapter) ++{ ++ struct intel_gmbus *bus = container_of(adapter, ++ struct intel_gmbus, ++ adapter); ++ ++ if (bus->force_bit) ++ bus->force_bit->algo->functionality(bus->force_bit); ++ ++ return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | ++ /* I2C_FUNC_10BIT_ADDR | */ ++ I2C_FUNC_SMBUS_READ_BLOCK_DATA | ++ I2C_FUNC_SMBUS_BLOCK_PROC_CALL); ++} ++ ++static const struct i2c_algorithm gmbus_algorithm = { ++ .master_xfer = gmbus_xfer, ++ .functionality = gmbus_func ++}; ++ ++/** ++ * intel_gmbus_setup - instantiate all Intel i2c GMBuses ++ * @dev: DRM device ++ */ ++int gma_intel_setup_gmbus(struct drm_device *dev) ++{ ++ static const char *names[GMBUS_NUM_PORTS] = { ++ "disabled", ++ "ssc", ++ "vga", ++ "panel", ++ "dpc", ++ "dpb", ++ "reserved", ++ "dpd", ++ }; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int ret, i; ++ ++ dev_priv->gmbus = kcalloc(GMBUS_NUM_PORTS, sizeof(struct intel_gmbus), ++ GFP_KERNEL); ++ if (dev_priv->gmbus == NULL) ++ return -ENOMEM; ++ ++ for (i = 0; i < GMBUS_NUM_PORTS; i++) { ++ struct intel_gmbus *bus = &dev_priv->gmbus[i]; ++ ++ bus->adapter.owner = THIS_MODULE; ++ bus->adapter.class = I2C_CLASS_DDC; ++ snprintf(bus->adapter.name, ++ sizeof(bus->adapter.name), ++ "gma500 gmbus %s", ++ names[i]); ++ ++ bus->adapter.dev.parent = &dev->pdev->dev; ++ bus->adapter.algo_data = dev_priv; ++ ++ bus->adapter.algo = &gmbus_algorithm; ++ ret = i2c_add_adapter(&bus->adapter); ++ if (ret) ++ goto err; ++ ++ /* By default use a conservative clock rate */ ++ bus->reg0 = i | GMBUS_RATE_100KHZ; ++ ++ /* XXX force bit banging until GMBUS is fully debugged */ ++ bus->force_bit = intel_gpio_create(dev_priv, i); ++ } ++ ++ gma_intel_i2c_reset(dev_priv->dev); ++ ++ return 0; ++ ++err: ++ while (--i) { ++ struct intel_gmbus *bus = &dev_priv->gmbus[i]; ++ i2c_del_adapter(&bus->adapter); ++ } ++ kfree(dev_priv->gmbus); ++ dev_priv->gmbus = NULL; ++ return ret; ++} ++ ++void gma_intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed) ++{ ++ struct intel_gmbus *bus = to_intel_gmbus(adapter); ++ ++ /* speed: ++ * 0x0 = 100 KHz ++ * 0x1 = 50 KHz ++ * 0x2 = 400 KHz ++ * 0x3 = 1000 Khz ++ */ ++ bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | (speed << 8); ++} ++ ++void gma_intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) ++{ ++ struct intel_gmbus *bus = to_intel_gmbus(adapter); ++ ++ if (force_bit) { ++ if (bus->force_bit == NULL) { ++ struct drm_psb_private *dev_priv = adapter->algo_data; ++ bus->force_bit = intel_gpio_create(dev_priv, ++ bus->reg0 & 0xff); ++ } ++ } else { ++ if (bus->force_bit) { ++ i2c_del_adapter(bus->force_bit); ++ kfree(bus->force_bit); ++ bus->force_bit = NULL; ++ } ++ } ++} ++ ++void gma_intel_teardown_gmbus(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int i; ++ ++ if (dev_priv->gmbus == NULL) ++ return; ++ ++ for (i = 0; i < GMBUS_NUM_PORTS; i++) { ++ struct intel_gmbus *bus = &dev_priv->gmbus[i]; ++ if (bus->force_bit) { ++ i2c_del_adapter(bus->force_bit); ++ kfree(bus->force_bit); ++ } ++ i2c_del_adapter(&bus->adapter); ++ } ++ ++ kfree(dev_priv->gmbus); ++ dev_priv->gmbus = NULL; ++} +diff --git a/drivers/gpu/drm/gma500/intel_i2c.c b/drivers/gpu/drm/gma500/intel_i2c.c +new file mode 100644 +index 0000000..98a28c2 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/intel_i2c.c +@@ -0,0 +1,169 @@ ++/* ++ * Copyright © 2006-2007 Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: ++ * Eric Anholt ++ */ ++#include ++#include ++#include ++ ++#include "psb_drv.h" ++#include "psb_intel_reg.h" ++ ++/* ++ * Intel GPIO access functions ++ */ ++ ++#define I2C_RISEFALL_TIME 20 ++ ++static int get_clock(void *data) ++{ ++ struct psb_intel_i2c_chan *chan = data; ++ struct drm_device *dev = chan->drm_dev; ++ u32 val; ++ ++ val = REG_READ(chan->reg); ++ return (val & GPIO_CLOCK_VAL_IN) != 0; ++} ++ ++static int get_data(void *data) ++{ ++ struct psb_intel_i2c_chan *chan = data; ++ struct drm_device *dev = chan->drm_dev; ++ u32 val; ++ ++ val = REG_READ(chan->reg); ++ return (val & GPIO_DATA_VAL_IN) != 0; ++} ++ ++static void set_clock(void *data, int state_high) ++{ ++ struct psb_intel_i2c_chan *chan = data; ++ struct drm_device *dev = chan->drm_dev; ++ u32 reserved = 0, clock_bits; ++ ++ /* On most chips, these bits must be preserved in software. */ ++ reserved = ++ REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | ++ GPIO_CLOCK_PULLUP_DISABLE); ++ ++ if (state_high) ++ clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; ++ else ++ clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | ++ GPIO_CLOCK_VAL_MASK; ++ REG_WRITE(chan->reg, reserved | clock_bits); ++ udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ ++} ++ ++static void set_data(void *data, int state_high) ++{ ++ struct psb_intel_i2c_chan *chan = data; ++ struct drm_device *dev = chan->drm_dev; ++ u32 reserved = 0, data_bits; ++ ++ /* On most chips, these bits must be preserved in software. */ ++ reserved = ++ REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | ++ GPIO_CLOCK_PULLUP_DISABLE); ++ ++ if (state_high) ++ data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; ++ else ++ data_bits = ++ GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | ++ GPIO_DATA_VAL_MASK; ++ ++ REG_WRITE(chan->reg, reserved | data_bits); ++ udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ ++} ++ ++/** ++ * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg ++ * @dev: DRM device ++ * @output: driver specific output device ++ * @reg: GPIO reg to use ++ * @name: name for this bus ++ * ++ * Creates and registers a new i2c bus with the Linux i2c layer, for use ++ * in output probing and control (e.g. DDC or SDVO control functions). ++ * ++ * Possible values for @reg include: ++ * %GPIOA ++ * %GPIOB ++ * %GPIOC ++ * %GPIOD ++ * %GPIOE ++ * %GPIOF ++ * %GPIOG ++ * %GPIOH ++ * see PRM for details on how these different busses are used. ++ */ ++struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev, ++ const u32 reg, const char *name) ++{ ++ struct psb_intel_i2c_chan *chan; ++ ++ chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL); ++ if (!chan) ++ goto out_free; ++ ++ chan->drm_dev = dev; ++ chan->reg = reg; ++ snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name); ++ chan->adapter.owner = THIS_MODULE; ++ chan->adapter.algo_data = &chan->algo; ++ chan->adapter.dev.parent = &dev->pdev->dev; ++ chan->algo.setsda = set_data; ++ chan->algo.setscl = set_clock; ++ chan->algo.getsda = get_data; ++ chan->algo.getscl = get_clock; ++ chan->algo.udelay = 20; ++ chan->algo.timeout = usecs_to_jiffies(2200); ++ chan->algo.data = chan; ++ ++ i2c_set_adapdata(&chan->adapter, chan); ++ ++ if (i2c_bit_add_bus(&chan->adapter)) ++ goto out_free; ++ ++ /* JJJ: raise SCL and SDA? */ ++ set_data(chan, 1); ++ set_clock(chan, 1); ++ udelay(20); ++ ++ return chan; ++ ++out_free: ++ kfree(chan); ++ return NULL; ++} ++ ++/** ++ * psb_intel_i2c_destroy - unregister and free i2c bus resources ++ * @output: channel to free ++ * ++ * Unregister the adapter from the i2c layer, then free the structure. ++ */ ++void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan) ++{ ++ if (!chan) ++ return; ++ ++ i2c_del_adapter(&chan->adapter); ++ kfree(chan); ++} +diff --git a/drivers/gpu/drm/gma500/intel_opregion.c b/drivers/gpu/drm/gma500/intel_opregion.c +new file mode 100644 +index 0000000..d946bc1 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/intel_opregion.c +@@ -0,0 +1,81 @@ ++/* ++ * Copyright 2010 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * FIXME: resolve with the i915 version ++ */ ++ ++#include "psb_drv.h" ++ ++struct opregion_header { ++ u8 signature[16]; ++ u32 size; ++ u32 opregion_ver; ++ u8 bios_ver[32]; ++ u8 vbios_ver[16]; ++ u8 driver_ver[16]; ++ u32 mboxes; ++ u8 reserved[164]; ++} __packed; ++ ++struct opregion_apci { ++ /*FIXME: add it later*/ ++} __packed; ++ ++struct opregion_swsci { ++ /*FIXME: add it later*/ ++} __packed; ++ ++struct opregion_acpi { ++ /*FIXME: add it later*/ ++} __packed; ++ ++int gma_intel_opregion_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 opregion_phy; ++ void *base; ++ u32 *lid_state; ++ ++ dev_priv->lid_state = NULL; ++ ++ pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy); ++ if (opregion_phy == 0) ++ return -ENOTSUPP; ++ ++ base = ioremap(opregion_phy, 8*1024); ++ if (!base) ++ return -ENOMEM; ++ ++ lid_state = base + 0x01ac; ++ ++ dev_priv->lid_state = lid_state; ++ dev_priv->lid_last_state = readl(lid_state); ++ return 0; ++} ++ ++int gma_intel_opregion_exit(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ if (dev_priv->lid_state) ++ iounmap(dev_priv->lid_state); ++ return 0; ++} +diff --git a/drivers/gpu/drm/gma500/mdfld_device.c b/drivers/gpu/drm/gma500/mdfld_device.c +new file mode 100644 +index 0000000..af65678 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mdfld_device.c +@@ -0,0 +1,691 @@ ++/************************************************************************** ++ * Copyright (c) 2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++ ++#include "psb_drv.h" ++#include "mid_bios.h" ++#include "mdfld_output.h" ++#include "mdfld_dsi_output.h" ++#include "tc35876x-dsi-lvds.h" ++ ++#include ++ ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ ++#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF ++#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ ++#define BLC_PWM_FREQ_CALC_CONSTANT 32 ++#define MHz 1000000 ++#define BRIGHTNESS_MIN_LEVEL 1 ++#define BRIGHTNESS_MAX_LEVEL 100 ++#define BRIGHTNESS_MASK 0xFF ++#define BLC_POLARITY_NORMAL 0 ++#define BLC_POLARITY_INVERSE 1 ++#define BLC_ADJUSTMENT_MAX 100 ++ ++#define MDFLD_BLC_PWM_PRECISION_FACTOR 10 ++#define MDFLD_BLC_MAX_PWM_REG_FREQ 0xFFFE ++#define MDFLD_BLC_MIN_PWM_REG_FREQ 0x2 ++ ++#define MDFLD_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) ++#define MDFLD_BACKLIGHT_PWM_CTL_SHIFT (16) ++ ++static struct backlight_device *mdfld_backlight_device; ++ ++int mdfld_set_brightness(struct backlight_device *bd) ++{ ++ struct drm_device *dev = ++ (struct drm_device *)bl_get_data(mdfld_backlight_device); ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int level = bd->props.brightness; ++ ++ DRM_DEBUG_DRIVER("backlight level set to %d\n", level); ++ ++ /* Perform value bounds checking */ ++ if (level < BRIGHTNESS_MIN_LEVEL) ++ level = BRIGHTNESS_MIN_LEVEL; ++ ++ if (gma_power_begin(dev, false)) { ++ u32 adjusted_level = 0; ++ ++ /* ++ * Adjust the backlight level with the percent in ++ * dev_priv->blc_adj2 ++ */ ++ adjusted_level = level * dev_priv->blc_adj2; ++ adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX; ++ dev_priv->brightness_adjusted = adjusted_level; ++ ++ if (mdfld_get_panel_type(dev, 0) == TC35876X) { ++ if (dev_priv->dpi_panel_on[0] || ++ dev_priv->dpi_panel_on[2]) ++ tc35876x_brightness_control(dev, ++ dev_priv->brightness_adjusted); ++ } else { ++ if (dev_priv->dpi_panel_on[0]) ++ mdfld_dsi_brightness_control(dev, 0, ++ dev_priv->brightness_adjusted); ++ } ++ ++ if (dev_priv->dpi_panel_on[2]) ++ mdfld_dsi_brightness_control(dev, 2, ++ dev_priv->brightness_adjusted); ++ gma_power_end(dev); ++ } ++ ++ /* cache the brightness for later use */ ++ dev_priv->brightness = level; ++ return 0; ++} ++ ++static int mdfld_get_brightness(struct backlight_device *bd) ++{ ++ struct drm_device *dev = ++ (struct drm_device *)bl_get_data(mdfld_backlight_device); ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ DRM_DEBUG_DRIVER("brightness = 0x%x \n", dev_priv->brightness); ++ ++ /* return locally cached var instead of HW read (due to DPST etc.) */ ++ return dev_priv->brightness; ++} ++ ++static const struct backlight_ops mdfld_ops = { ++ .get_brightness = mdfld_get_brightness, ++ .update_status = mdfld_set_brightness, ++}; ++ ++static int device_backlight_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = (struct drm_psb_private *) ++ dev->dev_private; ++ ++ dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX; ++ dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX; ++ ++ return 0; ++} ++ ++static int mdfld_backlight_init(struct drm_device *dev) ++{ ++ struct backlight_properties props; ++ int ret = 0; ++ ++ memset(&props, 0, sizeof(struct backlight_properties)); ++ props.max_brightness = BRIGHTNESS_MAX_LEVEL; ++ props.type = BACKLIGHT_PLATFORM; ++ mdfld_backlight_device = backlight_device_register("mdfld-bl", ++ NULL, (void *)dev, &mdfld_ops, &props); ++ ++ if (IS_ERR(mdfld_backlight_device)) ++ return PTR_ERR(mdfld_backlight_device); ++ ++ ret = device_backlight_init(dev); ++ if (ret) ++ return ret; ++ ++ mdfld_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL; ++ mdfld_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL; ++ backlight_update_status(mdfld_backlight_device); ++ return 0; ++} ++#endif ++ ++struct backlight_device *mdfld_get_backlight_device(void) ++{ ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ return mdfld_backlight_device; ++#else ++ return NULL; ++#endif ++} ++ ++/* ++ * mdfld_save_display_registers ++ * ++ * Description: We are going to suspend so save current display ++ * register state. ++ * ++ * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio ++ */ ++static int mdfld_save_display_registers(struct drm_device *dev, int pipe) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct medfield_state *regs = &dev_priv->regs.mdfld; ++ int i; ++ ++ /* register */ ++ u32 dpll_reg = MRST_DPLL_A; ++ u32 fp_reg = MRST_FPA0; ++ u32 pipeconf_reg = PIPEACONF; ++ u32 htot_reg = HTOTAL_A; ++ u32 hblank_reg = HBLANK_A; ++ u32 hsync_reg = HSYNC_A; ++ u32 vtot_reg = VTOTAL_A; ++ u32 vblank_reg = VBLANK_A; ++ u32 vsync_reg = VSYNC_A; ++ u32 pipesrc_reg = PIPEASRC; ++ u32 dspstride_reg = DSPASTRIDE; ++ u32 dsplinoff_reg = DSPALINOFF; ++ u32 dsptileoff_reg = DSPATILEOFF; ++ u32 dspsize_reg = DSPASIZE; ++ u32 dsppos_reg = DSPAPOS; ++ u32 dspsurf_reg = DSPASURF; ++ u32 mipi_reg = MIPI; ++ u32 dspcntr_reg = DSPACNTR; ++ u32 dspstatus_reg = PIPEASTAT; ++ u32 palette_reg = PALETTE_A; ++ ++ /* pointer to values */ ++ u32 *dpll_val = ®s->saveDPLL_A; ++ u32 *fp_val = ®s->saveFPA0; ++ u32 *pipeconf_val = ®s->savePIPEACONF; ++ u32 *htot_val = ®s->saveHTOTAL_A; ++ u32 *hblank_val = ®s->saveHBLANK_A; ++ u32 *hsync_val = ®s->saveHSYNC_A; ++ u32 *vtot_val = ®s->saveVTOTAL_A; ++ u32 *vblank_val = ®s->saveVBLANK_A; ++ u32 *vsync_val = ®s->saveVSYNC_A; ++ u32 *pipesrc_val = ®s->savePIPEASRC; ++ u32 *dspstride_val = ®s->saveDSPASTRIDE; ++ u32 *dsplinoff_val = ®s->saveDSPALINOFF; ++ u32 *dsptileoff_val = ®s->saveDSPATILEOFF; ++ u32 *dspsize_val = ®s->saveDSPASIZE; ++ u32 *dsppos_val = ®s->saveDSPAPOS; ++ u32 *dspsurf_val = ®s->saveDSPASURF; ++ u32 *mipi_val = ®s->saveMIPI; ++ u32 *dspcntr_val = ®s->saveDSPACNTR; ++ u32 *dspstatus_val = ®s->saveDSPASTATUS; ++ u32 *palette_val = regs->save_palette_a; ++ ++ switch (pipe) { ++ case 0: ++ break; ++ case 1: ++ /* regester */ ++ dpll_reg = MDFLD_DPLL_B; ++ fp_reg = MDFLD_DPLL_DIV0; ++ pipeconf_reg = PIPEBCONF; ++ htot_reg = HTOTAL_B; ++ hblank_reg = HBLANK_B; ++ hsync_reg = HSYNC_B; ++ vtot_reg = VTOTAL_B; ++ vblank_reg = VBLANK_B; ++ vsync_reg = VSYNC_B; ++ pipesrc_reg = PIPEBSRC; ++ dspstride_reg = DSPBSTRIDE; ++ dsplinoff_reg = DSPBLINOFF; ++ dsptileoff_reg = DSPBTILEOFF; ++ dspsize_reg = DSPBSIZE; ++ dsppos_reg = DSPBPOS; ++ dspsurf_reg = DSPBSURF; ++ dspcntr_reg = DSPBCNTR; ++ dspstatus_reg = PIPEBSTAT; ++ palette_reg = PALETTE_B; ++ ++ /* values */ ++ dpll_val = ®s->saveDPLL_B; ++ fp_val = ®s->saveFPB0; ++ pipeconf_val = ®s->savePIPEBCONF; ++ htot_val = ®s->saveHTOTAL_B; ++ hblank_val = ®s->saveHBLANK_B; ++ hsync_val = ®s->saveHSYNC_B; ++ vtot_val = ®s->saveVTOTAL_B; ++ vblank_val = ®s->saveVBLANK_B; ++ vsync_val = ®s->saveVSYNC_B; ++ pipesrc_val = ®s->savePIPEBSRC; ++ dspstride_val = ®s->saveDSPBSTRIDE; ++ dsplinoff_val = ®s->saveDSPBLINOFF; ++ dsptileoff_val = ®s->saveDSPBTILEOFF; ++ dspsize_val = ®s->saveDSPBSIZE; ++ dsppos_val = ®s->saveDSPBPOS; ++ dspsurf_val = ®s->saveDSPBSURF; ++ dspcntr_val = ®s->saveDSPBCNTR; ++ dspstatus_val = ®s->saveDSPBSTATUS; ++ palette_val = regs->save_palette_b; ++ break; ++ case 2: ++ /* register */ ++ pipeconf_reg = PIPECCONF; ++ htot_reg = HTOTAL_C; ++ hblank_reg = HBLANK_C; ++ hsync_reg = HSYNC_C; ++ vtot_reg = VTOTAL_C; ++ vblank_reg = VBLANK_C; ++ vsync_reg = VSYNC_C; ++ pipesrc_reg = PIPECSRC; ++ dspstride_reg = DSPCSTRIDE; ++ dsplinoff_reg = DSPCLINOFF; ++ dsptileoff_reg = DSPCTILEOFF; ++ dspsize_reg = DSPCSIZE; ++ dsppos_reg = DSPCPOS; ++ dspsurf_reg = DSPCSURF; ++ mipi_reg = MIPI_C; ++ dspcntr_reg = DSPCCNTR; ++ dspstatus_reg = PIPECSTAT; ++ palette_reg = PALETTE_C; ++ ++ /* pointer to values */ ++ pipeconf_val = ®s->savePIPECCONF; ++ htot_val = ®s->saveHTOTAL_C; ++ hblank_val = ®s->saveHBLANK_C; ++ hsync_val = ®s->saveHSYNC_C; ++ vtot_val = ®s->saveVTOTAL_C; ++ vblank_val = ®s->saveVBLANK_C; ++ vsync_val = ®s->saveVSYNC_C; ++ pipesrc_val = ®s->savePIPECSRC; ++ dspstride_val = ®s->saveDSPCSTRIDE; ++ dsplinoff_val = ®s->saveDSPCLINOFF; ++ dsptileoff_val = ®s->saveDSPCTILEOFF; ++ dspsize_val = ®s->saveDSPCSIZE; ++ dsppos_val = ®s->saveDSPCPOS; ++ dspsurf_val = ®s->saveDSPCSURF; ++ mipi_val = ®s->saveMIPI_C; ++ dspcntr_val = ®s->saveDSPCCNTR; ++ dspstatus_val = ®s->saveDSPCSTATUS; ++ palette_val = regs->save_palette_c; ++ break; ++ default: ++ DRM_ERROR("%s, invalid pipe number.\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Pipe & plane A info */ ++ *dpll_val = PSB_RVDC32(dpll_reg); ++ *fp_val = PSB_RVDC32(fp_reg); ++ *pipeconf_val = PSB_RVDC32(pipeconf_reg); ++ *htot_val = PSB_RVDC32(htot_reg); ++ *hblank_val = PSB_RVDC32(hblank_reg); ++ *hsync_val = PSB_RVDC32(hsync_reg); ++ *vtot_val = PSB_RVDC32(vtot_reg); ++ *vblank_val = PSB_RVDC32(vblank_reg); ++ *vsync_val = PSB_RVDC32(vsync_reg); ++ *pipesrc_val = PSB_RVDC32(pipesrc_reg); ++ *dspstride_val = PSB_RVDC32(dspstride_reg); ++ *dsplinoff_val = PSB_RVDC32(dsplinoff_reg); ++ *dsptileoff_val = PSB_RVDC32(dsptileoff_reg); ++ *dspsize_val = PSB_RVDC32(dspsize_reg); ++ *dsppos_val = PSB_RVDC32(dsppos_reg); ++ *dspsurf_val = PSB_RVDC32(dspsurf_reg); ++ *dspcntr_val = PSB_RVDC32(dspcntr_reg); ++ *dspstatus_val = PSB_RVDC32(dspstatus_reg); ++ ++ /*save palette (gamma) */ ++ for (i = 0; i < 256; i++) ++ palette_val[i] = PSB_RVDC32(palette_reg + (i << 2)); ++ ++ if (pipe == 1) { ++ regs->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL); ++ regs->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS); ++ ++ regs->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL); ++ regs->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL); ++ return 0; ++ } ++ ++ *mipi_val = PSB_RVDC32(mipi_reg); ++ return 0; ++} ++ ++/* ++ * mdfld_restore_display_registers ++ * ++ * Description: We are going to resume so restore display register state. ++ * ++ * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio ++ */ ++static int mdfld_restore_display_registers(struct drm_device *dev, int pipe) ++{ ++ /* To get panel out of ULPS mode. */ ++ u32 temp = 0; ++ u32 device_ready_reg = DEVICE_READY_REG; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct mdfld_dsi_config *dsi_config = NULL; ++ struct medfield_state *regs = &dev_priv->regs.mdfld; ++ u32 i = 0; ++ u32 dpll = 0; ++ u32 timeout = 0; ++ ++ /* regester */ ++ u32 dpll_reg = MRST_DPLL_A; ++ u32 fp_reg = MRST_FPA0; ++ u32 pipeconf_reg = PIPEACONF; ++ u32 htot_reg = HTOTAL_A; ++ u32 hblank_reg = HBLANK_A; ++ u32 hsync_reg = HSYNC_A; ++ u32 vtot_reg = VTOTAL_A; ++ u32 vblank_reg = VBLANK_A; ++ u32 vsync_reg = VSYNC_A; ++ u32 pipesrc_reg = PIPEASRC; ++ u32 dspstride_reg = DSPASTRIDE; ++ u32 dsplinoff_reg = DSPALINOFF; ++ u32 dsptileoff_reg = DSPATILEOFF; ++ u32 dspsize_reg = DSPASIZE; ++ u32 dsppos_reg = DSPAPOS; ++ u32 dspsurf_reg = DSPASURF; ++ u32 dspstatus_reg = PIPEASTAT; ++ u32 mipi_reg = MIPI; ++ u32 dspcntr_reg = DSPACNTR; ++ u32 palette_reg = PALETTE_A; ++ ++ /* values */ ++ u32 dpll_val = regs->saveDPLL_A & ~DPLL_VCO_ENABLE; ++ u32 fp_val = regs->saveFPA0; ++ u32 pipeconf_val = regs->savePIPEACONF; ++ u32 htot_val = regs->saveHTOTAL_A; ++ u32 hblank_val = regs->saveHBLANK_A; ++ u32 hsync_val = regs->saveHSYNC_A; ++ u32 vtot_val = regs->saveVTOTAL_A; ++ u32 vblank_val = regs->saveVBLANK_A; ++ u32 vsync_val = regs->saveVSYNC_A; ++ u32 pipesrc_val = regs->savePIPEASRC; ++ u32 dspstride_val = regs->saveDSPASTRIDE; ++ u32 dsplinoff_val = regs->saveDSPALINOFF; ++ u32 dsptileoff_val = regs->saveDSPATILEOFF; ++ u32 dspsize_val = regs->saveDSPASIZE; ++ u32 dsppos_val = regs->saveDSPAPOS; ++ u32 dspsurf_val = regs->saveDSPASURF; ++ u32 dspstatus_val = regs->saveDSPASTATUS; ++ u32 mipi_val = regs->saveMIPI; ++ u32 dspcntr_val = regs->saveDSPACNTR; ++ u32 *palette_val = regs->save_palette_a; ++ ++ switch (pipe) { ++ case 0: ++ dsi_config = dev_priv->dsi_configs[0]; ++ break; ++ case 1: ++ /* regester */ ++ dpll_reg = MDFLD_DPLL_B; ++ fp_reg = MDFLD_DPLL_DIV0; ++ pipeconf_reg = PIPEBCONF; ++ htot_reg = HTOTAL_B; ++ hblank_reg = HBLANK_B; ++ hsync_reg = HSYNC_B; ++ vtot_reg = VTOTAL_B; ++ vblank_reg = VBLANK_B; ++ vsync_reg = VSYNC_B; ++ pipesrc_reg = PIPEBSRC; ++ dspstride_reg = DSPBSTRIDE; ++ dsplinoff_reg = DSPBLINOFF; ++ dsptileoff_reg = DSPBTILEOFF; ++ dspsize_reg = DSPBSIZE; ++ dsppos_reg = DSPBPOS; ++ dspsurf_reg = DSPBSURF; ++ dspcntr_reg = DSPBCNTR; ++ dspstatus_reg = PIPEBSTAT; ++ palette_reg = PALETTE_B; ++ ++ /* values */ ++ dpll_val = regs->saveDPLL_B & ~DPLL_VCO_ENABLE; ++ fp_val = regs->saveFPB0; ++ pipeconf_val = regs->savePIPEBCONF; ++ htot_val = regs->saveHTOTAL_B; ++ hblank_val = regs->saveHBLANK_B; ++ hsync_val = regs->saveHSYNC_B; ++ vtot_val = regs->saveVTOTAL_B; ++ vblank_val = regs->saveVBLANK_B; ++ vsync_val = regs->saveVSYNC_B; ++ pipesrc_val = regs->savePIPEBSRC; ++ dspstride_val = regs->saveDSPBSTRIDE; ++ dsplinoff_val = regs->saveDSPBLINOFF; ++ dsptileoff_val = regs->saveDSPBTILEOFF; ++ dspsize_val = regs->saveDSPBSIZE; ++ dsppos_val = regs->saveDSPBPOS; ++ dspsurf_val = regs->saveDSPBSURF; ++ dspcntr_val = regs->saveDSPBCNTR; ++ dspstatus_val = regs->saveDSPBSTATUS; ++ palette_val = regs->save_palette_b; ++ break; ++ case 2: ++ /* regester */ ++ pipeconf_reg = PIPECCONF; ++ htot_reg = HTOTAL_C; ++ hblank_reg = HBLANK_C; ++ hsync_reg = HSYNC_C; ++ vtot_reg = VTOTAL_C; ++ vblank_reg = VBLANK_C; ++ vsync_reg = VSYNC_C; ++ pipesrc_reg = PIPECSRC; ++ dspstride_reg = DSPCSTRIDE; ++ dsplinoff_reg = DSPCLINOFF; ++ dsptileoff_reg = DSPCTILEOFF; ++ dspsize_reg = DSPCSIZE; ++ dsppos_reg = DSPCPOS; ++ dspsurf_reg = DSPCSURF; ++ mipi_reg = MIPI_C; ++ dspcntr_reg = DSPCCNTR; ++ dspstatus_reg = PIPECSTAT; ++ palette_reg = PALETTE_C; ++ ++ /* values */ ++ pipeconf_val = regs->savePIPECCONF; ++ htot_val = regs->saveHTOTAL_C; ++ hblank_val = regs->saveHBLANK_C; ++ hsync_val = regs->saveHSYNC_C; ++ vtot_val = regs->saveVTOTAL_C; ++ vblank_val = regs->saveVBLANK_C; ++ vsync_val = regs->saveVSYNC_C; ++ pipesrc_val = regs->savePIPECSRC; ++ dspstride_val = regs->saveDSPCSTRIDE; ++ dsplinoff_val = regs->saveDSPCLINOFF; ++ dsptileoff_val = regs->saveDSPCTILEOFF; ++ dspsize_val = regs->saveDSPCSIZE; ++ dsppos_val = regs->saveDSPCPOS; ++ dspsurf_val = regs->saveDSPCSURF; ++ mipi_val = regs->saveMIPI_C; ++ dspcntr_val = regs->saveDSPCCNTR; ++ dspstatus_val = regs->saveDSPCSTATUS; ++ palette_val = regs->save_palette_c; ++ ++ dsi_config = dev_priv->dsi_configs[1]; ++ break; ++ default: ++ DRM_ERROR("%s, invalid pipe number.\n", __func__); ++ return -EINVAL; ++ } ++ ++ /*make sure VGA plane is off. it initializes to on after reset!*/ ++ PSB_WVDC32(0x80000000, VGACNTRL); ++ ++ if (pipe == 1) { ++ PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg); ++ PSB_RVDC32(dpll_reg); ++ ++ PSB_WVDC32(fp_val, fp_reg); ++ } else { ++ ++ dpll = PSB_RVDC32(dpll_reg); ++ ++ if (!(dpll & DPLL_VCO_ENABLE)) { ++ ++ /* When ungating power of DPLL, needs to wait 0.5us ++ before enable the VCO */ ++ if (dpll & MDFLD_PWR_GATE_EN) { ++ dpll &= ~MDFLD_PWR_GATE_EN; ++ PSB_WVDC32(dpll, dpll_reg); ++ /* FIXME_MDFLD PO - change 500 to 1 after PO */ ++ udelay(500); ++ } ++ ++ PSB_WVDC32(fp_val, fp_reg); ++ PSB_WVDC32(dpll_val, dpll_reg); ++ /* FIXME_MDFLD PO - change 500 to 1 after PO */ ++ udelay(500); ++ ++ dpll_val |= DPLL_VCO_ENABLE; ++ PSB_WVDC32(dpll_val, dpll_reg); ++ PSB_RVDC32(dpll_reg); ++ ++ /* wait for DSI PLL to lock */ ++ while (timeout < 20000 && ++ !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { ++ udelay(150); ++ timeout++; ++ } ++ ++ if (timeout == 20000) { ++ DRM_ERROR("%s, can't lock DSIPLL.\n", ++ __func__); ++ return -EINVAL; ++ } ++ } ++ } ++ /* Restore mode */ ++ PSB_WVDC32(htot_val, htot_reg); ++ PSB_WVDC32(hblank_val, hblank_reg); ++ PSB_WVDC32(hsync_val, hsync_reg); ++ PSB_WVDC32(vtot_val, vtot_reg); ++ PSB_WVDC32(vblank_val, vblank_reg); ++ PSB_WVDC32(vsync_val, vsync_reg); ++ PSB_WVDC32(pipesrc_val, pipesrc_reg); ++ PSB_WVDC32(dspstatus_val, dspstatus_reg); ++ ++ /*set up the plane*/ ++ PSB_WVDC32(dspstride_val, dspstride_reg); ++ PSB_WVDC32(dsplinoff_val, dsplinoff_reg); ++ PSB_WVDC32(dsptileoff_val, dsptileoff_reg); ++ PSB_WVDC32(dspsize_val, dspsize_reg); ++ PSB_WVDC32(dsppos_val, dsppos_reg); ++ PSB_WVDC32(dspsurf_val, dspsurf_reg); ++ ++ if (pipe == 1) { ++ /* restore palette (gamma) */ ++ /*DRM_UDELAY(50000); */ ++ for (i = 0; i < 256; i++) ++ PSB_WVDC32(palette_val[i], palette_reg + (i << 2)); ++ ++ PSB_WVDC32(regs->savePFIT_CONTROL, PFIT_CONTROL); ++ PSB_WVDC32(regs->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); ++ ++ /*TODO: resume HDMI port */ ++ ++ /*TODO: resume pipe*/ ++ ++ /*enable the plane*/ ++ PSB_WVDC32(dspcntr_val & ~DISPLAY_PLANE_ENABLE, dspcntr_reg); ++ ++ return 0; ++ } ++ ++ /*set up pipe related registers*/ ++ PSB_WVDC32(mipi_val, mipi_reg); ++ ++ /*setup MIPI adapter + MIPI IP registers*/ ++ if (dsi_config) ++ mdfld_dsi_controller_init(dsi_config, pipe); ++ ++ if (in_atomic() || in_interrupt()) ++ mdelay(20); ++ else ++ msleep(20); ++ ++ /*enable the plane*/ ++ PSB_WVDC32(dspcntr_val, dspcntr_reg); ++ ++ if (in_atomic() || in_interrupt()) ++ mdelay(20); ++ else ++ msleep(20); ++ ++ /* LP Hold Release */ ++ temp = REG_READ(mipi_reg); ++ temp |= LP_OUTPUT_HOLD_RELEASE; ++ REG_WRITE(mipi_reg, temp); ++ mdelay(1); ++ ++ ++ /* Set DSI host to exit from Utra Low Power State */ ++ temp = REG_READ(device_ready_reg); ++ temp &= ~ULPS_MASK; ++ temp |= 0x3; ++ temp |= EXIT_ULPS_DEV_READY; ++ REG_WRITE(device_ready_reg, temp); ++ mdelay(1); ++ ++ temp = REG_READ(device_ready_reg); ++ temp &= ~ULPS_MASK; ++ temp |= EXITING_ULPS; ++ REG_WRITE(device_ready_reg, temp); ++ mdelay(1); ++ ++ /*enable the pipe*/ ++ PSB_WVDC32(pipeconf_val, pipeconf_reg); ++ ++ /* restore palette (gamma) */ ++ /*DRM_UDELAY(50000); */ ++ for (i = 0; i < 256; i++) ++ PSB_WVDC32(palette_val[i], palette_reg + (i << 2)); ++ ++ return 0; ++} ++ ++static int mdfld_save_registers(struct drm_device *dev) ++{ ++ /* mdfld_save_cursor_overlay_registers(dev); */ ++ mdfld_save_display_registers(dev, 0); ++ mdfld_save_display_registers(dev, 2); ++ mdfld_disable_crtc(dev, 0); ++ mdfld_disable_crtc(dev, 2); ++ ++ return 0; ++} ++ ++static int mdfld_restore_registers(struct drm_device *dev) ++{ ++ mdfld_restore_display_registers(dev, 2); ++ mdfld_restore_display_registers(dev, 0); ++ /* mdfld_restore_cursor_overlay_registers(dev); */ ++ ++ return 0; ++} ++ ++static int mdfld_power_down(struct drm_device *dev) ++{ ++ /* FIXME */ ++ return 0; ++} ++ ++static int mdfld_power_up(struct drm_device *dev) ++{ ++ /* FIXME */ ++ return 0; ++} ++ ++const struct psb_ops mdfld_chip_ops = { ++ .name = "mdfld", ++ .accel_2d = 0, ++ .pipes = 3, ++ .crtcs = 3, ++ .sgx_offset = MRST_SGX_OFFSET, ++ ++ .chip_setup = mid_chip_setup, ++ .crtc_helper = &mdfld_helper_funcs, ++ .crtc_funcs = &psb_intel_crtc_funcs, ++ ++ .output_init = mdfld_output_init, ++ ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ .backlight_init = mdfld_backlight_init, ++#endif ++ ++ .save_regs = mdfld_save_registers, ++ .restore_regs = mdfld_restore_registers, ++ .power_down = mdfld_power_down, ++ .power_up = mdfld_power_up, ++}; +diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c +new file mode 100644 +index 0000000..d52358b +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c +@@ -0,0 +1,1017 @@ ++/* ++ * Copyright © 2010 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * jim liu ++ * Jackie Li ++ */ ++ ++#include "mdfld_dsi_dpi.h" ++#include "mdfld_output.h" ++#include "mdfld_dsi_pkg_sender.h" ++#include "psb_drv.h" ++#include "tc35876x-dsi-lvds.h" ++ ++static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, ++ int pipe); ++ ++static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe) ++{ ++ u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe); ++ int timeout = 0; ++ ++ udelay(500); ++ ++ /* This will time out after approximately 2+ seconds */ ++ while ((timeout < 20000) && ++ (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) { ++ udelay(100); ++ timeout++; ++ } ++ ++ if (timeout == 20000) ++ DRM_INFO("MIPI: HS Data FIFO was never cleared!\n"); ++} ++ ++static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe) ++{ ++ u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe); ++ int timeout = 0; ++ ++ udelay(500); ++ ++ /* This will time out after approximately 2+ seconds */ ++ while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) ++ & DSI_FIFO_GEN_HS_CTRL_FULL)) { ++ udelay(100); ++ timeout++; ++ } ++ if (timeout == 20000) ++ DRM_INFO("MIPI: HS CMD FIFO was never cleared!\n"); ++} ++ ++static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe) ++{ ++ u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe); ++ int timeout = 0; ++ ++ udelay(500); ++ ++ /* This will time out after approximately 2+ seconds */ ++ while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & ++ DPI_FIFO_EMPTY) != DPI_FIFO_EMPTY)) { ++ udelay(100); ++ timeout++; ++ } ++ ++ if (timeout == 20000) ++ DRM_ERROR("MIPI: DPI FIFO was never cleared\n"); ++} ++ ++static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe) ++{ ++ u32 intr_stat_reg = MIPI_INTR_STAT_REG(pipe); ++ int timeout = 0; ++ ++ udelay(500); ++ ++ /* This will time out after approximately 2+ seconds */ ++ while ((timeout < 20000) && (!(REG_READ(intr_stat_reg) ++ & DSI_INTR_STATE_SPL_PKG_SENT))) { ++ udelay(100); ++ timeout++; ++ } ++ ++ if (timeout == 20000) ++ DRM_ERROR("MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n"); ++} ++ ++/* For TC35876X */ ++ ++static void dsi_set_device_ready_state(struct drm_device *dev, int state, ++ int pipe) ++{ ++ REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), !!state, 0, 0); ++} ++ ++static void dsi_set_pipe_plane_enable_state(struct drm_device *dev, ++ int state, int pipe) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 pipeconf_reg = PIPEACONF; ++ u32 dspcntr_reg = DSPACNTR; ++ ++ u32 dspcntr = dev_priv->dspcntr[pipe]; ++ u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; ++ ++ if (pipe) { ++ pipeconf_reg = PIPECCONF; ++ dspcntr_reg = DSPCCNTR; ++ } else ++ mipi &= (~0x03); ++ ++ if (state) { ++ /*Set up pipe */ ++ REG_WRITE(pipeconf_reg, BIT(31)); ++ ++ if (REG_BIT_WAIT(pipeconf_reg, 1, 30)) ++ dev_err(&dev->pdev->dev, "%s: Pipe enable timeout\n", ++ __func__); ++ ++ /*Set up display plane */ ++ REG_WRITE(dspcntr_reg, dspcntr); ++ } else { ++ u32 dspbase_reg = pipe ? MDFLD_DSPCBASE : MRST_DSPABASE; ++ ++ /* Put DSI lanes to ULPS to disable pipe */ ++ REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 2, 2, 1); ++ REG_READ(MIPI_DEVICE_READY_REG(pipe)); /* posted write? */ ++ ++ /* LP Hold */ ++ REG_FLD_MOD(MIPI_PORT_CONTROL(pipe), 0, 16, 16); ++ REG_READ(MIPI_PORT_CONTROL(pipe)); /* posted write? */ ++ ++ /* Disable display plane */ ++ REG_FLD_MOD(dspcntr_reg, 0, 31, 31); ++ ++ /* Flush the plane changes ??? posted write? */ ++ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); ++ REG_READ(dspbase_reg); ++ ++ /* Disable PIPE */ ++ REG_FLD_MOD(pipeconf_reg, 0, 31, 31); ++ ++ if (REG_BIT_WAIT(pipeconf_reg, 0, 30)) ++ dev_err(&dev->pdev->dev, "%s: Pipe disable timeout\n", ++ __func__); ++ ++ if (REG_BIT_WAIT(MIPI_GEN_FIFO_STAT_REG(pipe), 1, 28)) ++ dev_err(&dev->pdev->dev, "%s: FIFO not empty\n", ++ __func__); ++ } ++} ++ ++static void mdfld_dsi_configure_down(struct mdfld_dsi_encoder *dsi_encoder, ++ int pipe) ++{ ++ struct mdfld_dsi_dpi_output *dpi_output = ++ MDFLD_DSI_DPI_OUTPUT(dsi_encoder); ++ struct mdfld_dsi_config *dsi_config = ++ mdfld_dsi_encoder_get_config(dsi_encoder); ++ struct drm_device *dev = dsi_config->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (!dev_priv->dpi_panel_on[pipe]) { ++ dev_err(dev->dev, "DPI panel is already off\n"); ++ return; ++ } ++ tc35876x_toshiba_bridge_panel_off(dev); ++ tc35876x_set_bridge_reset_state(dev, 1); ++ dsi_set_pipe_plane_enable_state(dev, 0, pipe); ++ mdfld_dsi_dpi_shut_down(dpi_output, pipe); ++ dsi_set_device_ready_state(dev, 0, pipe); ++} ++ ++static void mdfld_dsi_configure_up(struct mdfld_dsi_encoder *dsi_encoder, ++ int pipe) ++{ ++ struct mdfld_dsi_dpi_output *dpi_output = ++ MDFLD_DSI_DPI_OUTPUT(dsi_encoder); ++ struct mdfld_dsi_config *dsi_config = ++ mdfld_dsi_encoder_get_config(dsi_encoder); ++ struct drm_device *dev = dsi_config->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (dev_priv->dpi_panel_on[pipe]) { ++ dev_err(dev->dev, "DPI panel is already on\n"); ++ return; ++ } ++ ++ /* For resume path sequence */ ++ mdfld_dsi_dpi_shut_down(dpi_output, pipe); ++ dsi_set_device_ready_state(dev, 0, pipe); ++ ++ dsi_set_device_ready_state(dev, 1, pipe); ++ tc35876x_set_bridge_reset_state(dev, 0); ++ tc35876x_configure_lvds_bridge(dev); ++ mdfld_dsi_dpi_turn_on(dpi_output, pipe); /* Send turn on command */ ++ dsi_set_pipe_plane_enable_state(dev, 1, pipe); ++} ++/* End for TC35876X */ ++ ++/* ************************************************************************* *\ ++ * FUNCTION: mdfld_dsi_tpo_ic_init ++ * ++ * DESCRIPTION: This function is called only by mrst_dsi_mode_set and ++ * restore_display_registers. since this function does not ++ * acquire the mutex, it is important that the calling function ++ * does! ++\* ************************************************************************* */ ++static void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe) ++{ ++ struct drm_device *dev = dsi_config->dev; ++ u32 dcsChannelNumber = dsi_config->channel_num; ++ u32 gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe); ++ u32 gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe); ++ u32 gen_ctrl_val = GEN_LONG_WRITE; ++ ++ DRM_INFO("Enter mrst init TPO MIPI display.\n"); ++ ++ gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS; ++ ++ /* Flip page order */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x00008036); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS)); ++ ++ /* 0xF0 */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x005a5af0); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); ++ ++ /* Write protection key */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x005a5af1); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); ++ ++ /* 0xFC */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x005a5afc); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); ++ ++ /* 0xB7 */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x770000b7); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x00000044); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS)); ++ ++ /* 0xB6 */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x000a0ab6); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); ++ ++ /* 0xF2 */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x081010f2); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x4a070708); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x000000c5); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); ++ ++ /* 0xF8 */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x024003f8); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x01030a04); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x0e020220); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x00000004); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS)); ++ ++ /* 0xE2 */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x398fc3e2); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x0000916f); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS)); ++ ++ /* 0xB0 */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x000000b0); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS)); ++ ++ /* 0xF4 */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x240242f4); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x78ee2002); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x2a071050); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x507fee10); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x10300710); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS)); ++ ++ /* 0xBA */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x19fe07ba); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x101c0a31); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x00000010); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); ++ ++ /* 0xBB */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x28ff07bb); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x24280a31); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x00000034); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); ++ ++ /* 0xFB */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x535d05fb); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x1b1a2130); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x221e180e); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x131d2120); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x535d0508); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x1c1a2131); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x231f160d); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x111b2220); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x535c2008); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x1f1d2433); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x2c251a10); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x2c34372d); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x00000023); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS)); ++ ++ /* 0xFA */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x525c0bfa); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x1c1c232f); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x2623190e); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x18212625); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x545d0d0e); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x1e1d2333); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x26231a10); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x1a222725); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x545d280f); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x21202635); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x31292013); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x31393d33); ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x00000029); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS)); ++ ++ /* Set DM */ ++ mdfld_wait_for_HS_DATA_FIFO(dev, pipe); ++ REG_WRITE(gen_data_reg, 0x000100f7); ++ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); ++ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); ++} ++ ++static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count, ++ int num_lane, int bpp) ++{ ++ return (u16)((pixel_clock_count * bpp) / (num_lane * 8)); ++} ++ ++/* ++ * Calculate the dpi time basing on a given drm mode @mode ++ * return 0 on success. ++ * FIXME: I was using proposed mode value for calculation, may need to ++ * use crtc mode values later ++ */ ++int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, ++ struct mdfld_dsi_dpi_timing *dpi_timing, ++ int num_lane, int bpp) ++{ ++ int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive; ++ int pclk_vsync, pclk_vfp, pclk_vbp; ++ ++ pclk_hactive = mode->hdisplay; ++ pclk_hfp = mode->hsync_start - mode->hdisplay; ++ pclk_hsync = mode->hsync_end - mode->hsync_start; ++ pclk_hbp = mode->htotal - mode->hsync_end; ++ ++ pclk_vfp = mode->vsync_start - mode->vdisplay; ++ pclk_vsync = mode->vsync_end - mode->vsync_start; ++ pclk_vbp = mode->vtotal - mode->vsync_end; ++ ++ /* ++ * byte clock counts were calculated by following formula ++ * bclock_count = pclk_count * bpp / num_lane / 8 ++ */ ++ dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count( ++ pclk_hsync, num_lane, bpp); ++ dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count( ++ pclk_hbp, num_lane, bpp); ++ dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count( ++ pclk_hfp, num_lane, bpp); ++ dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count( ++ pclk_hactive, num_lane, bpp); ++ dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count( ++ pclk_vsync, num_lane, bpp); ++ dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count( ++ pclk_vbp, num_lane, bpp); ++ dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count( ++ pclk_vfp, num_lane, bpp); ++ ++ return 0; ++} ++ ++void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, ++ int pipe) ++{ ++ struct drm_device *dev = dsi_config->dev; ++ int lane_count = dsi_config->lane_count; ++ struct mdfld_dsi_dpi_timing dpi_timing; ++ struct drm_display_mode *mode = dsi_config->mode; ++ u32 val; ++ ++ /*un-ready device*/ ++ REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 0, 0, 0); ++ ++ /*init dsi adapter before kicking off*/ ++ REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018); ++ ++ /*enable all interrupts*/ ++ REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff); ++ ++ /*set up func_prg*/ ++ val = lane_count; ++ val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET; ++ ++ switch (dsi_config->bpp) { ++ case 16: ++ val |= DSI_DPI_COLOR_FORMAT_RGB565; ++ break; ++ case 18: ++ val |= DSI_DPI_COLOR_FORMAT_RGB666; ++ break; ++ case 24: ++ val |= DSI_DPI_COLOR_FORMAT_RGB888; ++ break; ++ default: ++ DRM_ERROR("unsupported color format, bpp = %d\n", ++ dsi_config->bpp); ++ } ++ REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), val); ++ ++ REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), ++ (mode->vtotal * mode->htotal * dsi_config->bpp / ++ (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK); ++ REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), ++ 0xffff & DSI_LP_RX_TIMEOUT_MASK); ++ ++ /*max value: 20 clock cycles of txclkesc*/ ++ REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), ++ 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK); ++ ++ /*min 21 txclkesc, max: ffffh*/ ++ REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), ++ 0xffff & DSI_RESET_TIMER_MASK); ++ ++ REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe), ++ mode->vdisplay << 16 | mode->hdisplay); ++ ++ /*set DPI timing registers*/ ++ mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, ++ dsi_config->lane_count, dsi_config->bpp); ++ ++ REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe), ++ dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); ++ REG_WRITE(MIPI_HBP_COUNT_REG(pipe), ++ dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); ++ REG_WRITE(MIPI_HFP_COUNT_REG(pipe), ++ dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); ++ REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe), ++ dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); ++ REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe), ++ dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); ++ REG_WRITE(MIPI_VBP_COUNT_REG(pipe), ++ dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); ++ REG_WRITE(MIPI_VFP_COUNT_REG(pipe), ++ dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); ++ ++ REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x46); ++ ++ /*min: 7d0 max: 4e20*/ ++ REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0x000007d0); ++ ++ /*set up video mode*/ ++ val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE; ++ REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), val); ++ ++ REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000); ++ ++ REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004); ++ ++ /*TODO: figure out how to setup these registers*/ ++ if (mdfld_get_panel_type(dev, pipe) == TC35876X) ++ REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008); ++ else ++ REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150c3408); ++ ++ REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14); ++ ++ if (mdfld_get_panel_type(dev, pipe) == TC35876X) ++ tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */ ++ ++ /*set device ready*/ ++ REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 1, 0, 0); ++} ++ ++void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe) ++{ ++ struct drm_device *dev = output->dev; ++ ++ /* clear special packet sent bit */ ++ if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) ++ REG_WRITE(MIPI_INTR_STAT_REG(pipe), ++ DSI_INTR_STATE_SPL_PKG_SENT); ++ ++ /*send turn on package*/ ++ REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_TURN_ON); ++ ++ /*wait for SPL_PKG_SENT interrupt*/ ++ mdfld_wait_for_SPL_PKG_SENT(dev, pipe); ++ ++ if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) ++ REG_WRITE(MIPI_INTR_STAT_REG(pipe), ++ DSI_INTR_STATE_SPL_PKG_SENT); ++ ++ output->panel_on = 1; ++ ++ /* FIXME the following is disabled to WA the X slow start issue ++ for TMD panel ++ if (pipe == 2) ++ dev_priv->dpi_panel_on2 = true; ++ else if (pipe == 0) ++ dev_priv->dpi_panel_on = true; */ ++} ++ ++static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, ++ int pipe) ++{ ++ struct drm_device *dev = output->dev; ++ ++ /*if output is on, or mode setting didn't happen, ignore this*/ ++ if ((!output->panel_on) || output->first_boot) { ++ output->first_boot = 0; ++ return; ++ } ++ ++ /* Wait for dpi fifo to empty */ ++ mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe); ++ ++ /* Clear the special packet interrupt bit if set */ ++ if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) ++ REG_WRITE(MIPI_INTR_STAT_REG(pipe), ++ DSI_INTR_STATE_SPL_PKG_SENT); ++ ++ if (REG_READ(MIPI_DPI_CONTROL_REG(pipe)) == DSI_DPI_CTRL_HS_SHUTDOWN) ++ goto shutdown_out; ++ ++ REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_SHUTDOWN); ++ ++shutdown_out: ++ output->panel_on = 0; ++ output->first_boot = 0; ++ ++ /* FIXME the following is disabled to WA the X slow start issue ++ for TMD panel ++ if (pipe == 2) ++ dev_priv->dpi_panel_on2 = false; ++ else if (pipe == 0) ++ dev_priv->dpi_panel_on = false; */ ++} ++ ++static void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) ++{ ++ struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); ++ struct mdfld_dsi_dpi_output *dpi_output = ++ MDFLD_DSI_DPI_OUTPUT(dsi_encoder); ++ struct mdfld_dsi_config *dsi_config = ++ mdfld_dsi_encoder_get_config(dsi_encoder); ++ int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); ++ struct drm_device *dev = dsi_config->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ /*start up display island if it was shutdown*/ ++ if (!gma_power_begin(dev, true)) ++ return; ++ ++ if (on) { ++ if (mdfld_get_panel_type(dev, pipe) == TMD_VID) ++ mdfld_dsi_dpi_turn_on(dpi_output, pipe); ++ else if (mdfld_get_panel_type(dev, pipe) == TC35876X) ++ mdfld_dsi_configure_up(dsi_encoder, pipe); ++ else { ++ /*enable mipi port*/ ++ REG_WRITE(MIPI_PORT_CONTROL(pipe), ++ REG_READ(MIPI_PORT_CONTROL(pipe)) | BIT(31)); ++ REG_READ(MIPI_PORT_CONTROL(pipe)); ++ ++ mdfld_dsi_dpi_turn_on(dpi_output, pipe); ++ mdfld_dsi_tpo_ic_init(dsi_config, pipe); ++ } ++ dev_priv->dpi_panel_on[pipe] = true; ++ } else { ++ if (mdfld_get_panel_type(dev, pipe) == TMD_VID) ++ mdfld_dsi_dpi_shut_down(dpi_output, pipe); ++ else if (mdfld_get_panel_type(dev, pipe) == TC35876X) ++ mdfld_dsi_configure_down(dsi_encoder, pipe); ++ else { ++ mdfld_dsi_dpi_shut_down(dpi_output, pipe); ++ ++ /*disable mipi port*/ ++ REG_WRITE(MIPI_PORT_CONTROL(pipe), ++ REG_READ(MIPI_PORT_CONTROL(pipe)) & ~BIT(31)); ++ REG_READ(MIPI_PORT_CONTROL(pipe)); ++ } ++ dev_priv->dpi_panel_on[pipe] = false; ++ } ++ gma_power_end(dev); ++} ++ ++void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode) ++{ ++ mdfld_dsi_dpi_set_power(encoder, mode == DRM_MODE_DPMS_ON); ++} ++ ++bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); ++ struct mdfld_dsi_config *dsi_config = ++ mdfld_dsi_encoder_get_config(dsi_encoder); ++ struct drm_display_mode *fixed_mode = dsi_config->fixed_mode; ++ ++ if (fixed_mode) { ++ adjusted_mode->hdisplay = fixed_mode->hdisplay; ++ adjusted_mode->hsync_start = fixed_mode->hsync_start; ++ adjusted_mode->hsync_end = fixed_mode->hsync_end; ++ adjusted_mode->htotal = fixed_mode->htotal; ++ adjusted_mode->vdisplay = fixed_mode->vdisplay; ++ adjusted_mode->vsync_start = fixed_mode->vsync_start; ++ adjusted_mode->vsync_end = fixed_mode->vsync_end; ++ adjusted_mode->vtotal = fixed_mode->vtotal; ++ adjusted_mode->clock = fixed_mode->clock; ++ drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); ++ } ++ return true; ++} ++ ++void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder) ++{ ++ mdfld_dsi_dpi_set_power(encoder, false); ++} ++ ++void mdfld_dsi_dpi_commit(struct drm_encoder *encoder) ++{ ++ mdfld_dsi_dpi_set_power(encoder, true); ++} ++ ++/* For TC35876X */ ++/* This functionality was implemented in FW in iCDK */ ++/* But removed in DV0 and later. So need to add here. */ ++static void mipi_set_properties(struct mdfld_dsi_config *dsi_config, int pipe) ++{ ++ struct drm_device *dev = dsi_config->dev; ++ ++ REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018); ++ REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff); ++ REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), 0xffffff); ++ REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffffff); ++ REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x14); ++ REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0xff); ++ REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x25); ++ REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0xf0); ++ REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000); ++ REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004); ++ REG_WRITE(MIPI_DBI_BW_CTRL_REG(pipe), 0x00000820); ++ REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14); ++} ++ ++static void mdfld_mipi_set_video_timing(struct mdfld_dsi_config *dsi_config, ++ int pipe) ++{ ++ struct drm_device *dev = dsi_config->dev; ++ struct mdfld_dsi_dpi_timing dpi_timing; ++ struct drm_display_mode *mode = dsi_config->mode; ++ ++ mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, ++ dsi_config->lane_count, ++ dsi_config->bpp); ++ ++ REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe), ++ mode->vdisplay << 16 | mode->hdisplay); ++ REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe), ++ dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); ++ REG_WRITE(MIPI_HBP_COUNT_REG(pipe), ++ dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); ++ REG_WRITE(MIPI_HFP_COUNT_REG(pipe), ++ dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); ++ REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe), ++ dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); ++ REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe), ++ dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); ++ REG_WRITE(MIPI_VBP_COUNT_REG(pipe), ++ dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); ++ REG_WRITE(MIPI_VFP_COUNT_REG(pipe), ++ dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); ++} ++ ++static void mdfld_mipi_config(struct mdfld_dsi_config *dsi_config, int pipe) ++{ ++ struct drm_device *dev = dsi_config->dev; ++ int lane_count = dsi_config->lane_count; ++ ++ if (pipe) { ++ REG_WRITE(MIPI_PORT_CONTROL(0), 0x00000002); ++ REG_WRITE(MIPI_PORT_CONTROL(2), 0x80000000); ++ } else { ++ REG_WRITE(MIPI_PORT_CONTROL(0), 0x80010000); ++ REG_WRITE(MIPI_PORT_CONTROL(2), 0x00); ++ } ++ ++ REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150A600F); ++ REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), 0x0000000F); ++ ++ /* lane_count = 3 */ ++ REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), 0x00000200 | lane_count); ++ ++ mdfld_mipi_set_video_timing(dsi_config, pipe); ++} ++ ++static void mdfld_set_pipe_timing(struct mdfld_dsi_config *dsi_config, int pipe) ++{ ++ struct drm_device *dev = dsi_config->dev; ++ struct drm_display_mode *mode = dsi_config->mode; ++ ++ REG_WRITE(HTOTAL_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1)); ++ REG_WRITE(HBLANK_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1)); ++ REG_WRITE(HSYNC_A, ++ ((mode->hsync_end - 1) << 16) | (mode->hsync_start - 1)); ++ ++ REG_WRITE(VTOTAL_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1)); ++ REG_WRITE(VBLANK_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1)); ++ REG_WRITE(VSYNC_A, ++ ((mode->vsync_end - 1) << 16) | (mode->vsync_start - 1)); ++ ++ REG_WRITE(PIPEASRC, ++ ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); ++} ++/* End for TC35876X */ ++ ++void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); ++ struct mdfld_dsi_dpi_output *dpi_output = ++ MDFLD_DSI_DPI_OUTPUT(dsi_encoder); ++ struct mdfld_dsi_config *dsi_config = ++ mdfld_dsi_encoder_get_config(dsi_encoder); ++ struct drm_device *dev = dsi_config->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); ++ ++ u32 pipeconf_reg = PIPEACONF; ++ u32 dspcntr_reg = DSPACNTR; ++ ++ u32 pipeconf = dev_priv->pipeconf[pipe]; ++ u32 dspcntr = dev_priv->dspcntr[pipe]; ++ u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; ++ ++ if (pipe) { ++ pipeconf_reg = PIPECCONF; ++ dspcntr_reg = DSPCCNTR; ++ } else { ++ if (mdfld_get_panel_type(dev, pipe) == TC35876X) ++ mipi &= (~0x03); /* Use all four lanes */ ++ else ++ mipi |= 2; ++ } ++ ++ /*start up display island if it was shutdown*/ ++ if (!gma_power_begin(dev, true)) ++ return; ++ ++ if (mdfld_get_panel_type(dev, pipe) == TC35876X) { ++ /* ++ * The following logic is required to reset the bridge and ++ * configure. This also starts the DSI clock at 200MHz. ++ */ ++ tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */ ++ tc35876x_toshiba_bridge_panel_on(dev); ++ udelay(100); ++ /* Now start the DSI clock */ ++ REG_WRITE(MRST_DPLL_A, 0x00); ++ REG_WRITE(MRST_FPA0, 0xC1); ++ REG_WRITE(MRST_DPLL_A, 0x00800000); ++ udelay(500); ++ REG_WRITE(MRST_DPLL_A, 0x80800000); ++ ++ if (REG_BIT_WAIT(pipeconf_reg, 1, 29)) ++ dev_err(&dev->pdev->dev, "%s: DSI PLL lock timeout\n", ++ __func__); ++ ++ REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008); ++ ++ mipi_set_properties(dsi_config, pipe); ++ mdfld_mipi_config(dsi_config, pipe); ++ mdfld_set_pipe_timing(dsi_config, pipe); ++ ++ REG_WRITE(DSPABASE, 0x00); ++ REG_WRITE(DSPASTRIDE, (mode->hdisplay * 4)); ++ REG_WRITE(DSPASIZE, ++ ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); ++ ++ REG_WRITE(DSPACNTR, 0x98000000); ++ REG_WRITE(DSPASURF, 0x00); ++ ++ REG_WRITE(VGACNTRL, 0x80000000); ++ REG_WRITE(DEVICE_READY_REG, 0x00000001); ++ ++ REG_WRITE(MIPI_PORT_CONTROL(pipe), 0x80810000); ++ } else { ++ /*set up mipi port FIXME: do at init time */ ++ REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi); ++ } ++ REG_READ(MIPI_PORT_CONTROL(pipe)); ++ ++ if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { ++ /* NOP */ ++ } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) { ++ /* set up DSI controller DPI interface */ ++ mdfld_dsi_dpi_controller_init(dsi_config, pipe); ++ ++ /* Configure MIPI Bridge and Panel */ ++ tc35876x_configure_lvds_bridge(dev); ++ dev_priv->dpi_panel_on[pipe] = true; ++ } else { ++ /*turn on DPI interface*/ ++ mdfld_dsi_dpi_turn_on(dpi_output, pipe); ++ } ++ ++ /*set up pipe*/ ++ REG_WRITE(pipeconf_reg, pipeconf); ++ REG_READ(pipeconf_reg); ++ ++ /*set up display plane*/ ++ REG_WRITE(dspcntr_reg, dspcntr); ++ REG_READ(dspcntr_reg); ++ ++ msleep(20); /* FIXME: this should wait for vblank */ ++ ++ if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { ++ /* NOP */ ++ } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) { ++ mdfld_dsi_dpi_turn_on(dpi_output, pipe); ++ } else { ++ /* init driver ic */ ++ mdfld_dsi_tpo_ic_init(dsi_config, pipe); ++ /*init backlight*/ ++ mdfld_dsi_brightness_init(dsi_config, pipe); ++ } ++ ++ gma_power_end(dev); ++} ++ ++/* ++ * Init DSI DPI encoder. ++ * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector ++ * return pointer of newly allocated DPI encoder, NULL on error ++ */ ++struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, ++ struct mdfld_dsi_connector *dsi_connector, ++ const struct panel_funcs *p_funcs) ++{ ++ struct mdfld_dsi_dpi_output *dpi_output = NULL; ++ struct mdfld_dsi_config *dsi_config; ++ struct drm_connector *connector = NULL; ++ struct drm_encoder *encoder = NULL; ++ int pipe; ++ u32 data; ++ int ret; ++ ++ pipe = dsi_connector->pipe; ++ ++ if (mdfld_get_panel_type(dev, pipe) != TC35876X) { ++ dsi_config = mdfld_dsi_get_config(dsi_connector); ++ ++ /* panel hard-reset */ ++ if (p_funcs->reset) { ++ ret = p_funcs->reset(pipe); ++ if (ret) { ++ DRM_ERROR("Panel %d hard-reset failed\n", pipe); ++ return NULL; ++ } ++ } ++ ++ /* panel drvIC init */ ++ if (p_funcs->drv_ic_init) ++ p_funcs->drv_ic_init(dsi_config, pipe); ++ ++ /* panel power mode detect */ ++ ret = mdfld_dsi_get_power_mode(dsi_config, &data, false); ++ if (ret) { ++ DRM_ERROR("Panel %d get power mode failed\n", pipe); ++ dsi_connector->status = connector_status_disconnected; ++ } else { ++ DRM_INFO("pipe %d power mode 0x%x\n", pipe, data); ++ dsi_connector->status = connector_status_connected; ++ } ++ } ++ ++ dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL); ++ if (!dpi_output) { ++ DRM_ERROR("No memory\n"); ++ return NULL; ++ } ++ ++ if (dsi_connector->pipe) ++ dpi_output->panel_on = 0; ++ else ++ dpi_output->panel_on = 0; ++ ++ dpi_output->dev = dev; ++ if (mdfld_get_panel_type(dev, pipe) != TC35876X) ++ dpi_output->p_funcs = p_funcs; ++ dpi_output->first_boot = 1; ++ ++ /*get fixed mode*/ ++ dsi_config = mdfld_dsi_get_config(dsi_connector); ++ ++ /*create drm encoder object*/ ++ connector = &dsi_connector->base.base; ++ encoder = &dpi_output->base.base.base; ++ drm_encoder_init(dev, ++ encoder, ++ p_funcs->encoder_funcs, ++ DRM_MODE_ENCODER_LVDS); ++ drm_encoder_helper_add(encoder, ++ p_funcs->encoder_helper_funcs); ++ ++ /*attach to given connector*/ ++ drm_mode_connector_attach_encoder(connector, encoder); ++ ++ /*set possible crtcs and clones*/ ++ if (dsi_connector->pipe) { ++ encoder->possible_crtcs = (1 << 2); ++ encoder->possible_clones = (1 << 1); ++ } else { ++ encoder->possible_crtcs = (1 << 0); ++ encoder->possible_clones = (1 << 0); ++ } ++ ++ dsi_connector->base.encoder = &dpi_output->base.base; ++ ++ return &dpi_output->base; ++} +diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h +new file mode 100644 +index 0000000..6f76247 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h +@@ -0,0 +1,79 @@ ++/* ++ * Copyright © 2010 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * jim liu ++ * Jackie Li ++ */ ++ ++#ifndef __MDFLD_DSI_DPI_H__ ++#define __MDFLD_DSI_DPI_H__ ++ ++#include "mdfld_dsi_output.h" ++#include "mdfld_output.h" ++ ++struct mdfld_dsi_dpi_timing { ++ u16 hsync_count; ++ u16 hbp_count; ++ u16 hfp_count; ++ u16 hactive_count; ++ u16 vsync_count; ++ u16 vbp_count; ++ u16 vfp_count; ++}; ++ ++struct mdfld_dsi_dpi_output { ++ struct mdfld_dsi_encoder base; ++ struct drm_device *dev; ++ ++ int panel_on; ++ int first_boot; ++ ++ const struct panel_funcs *p_funcs; ++}; ++ ++#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder)\ ++ container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base) ++ ++/* Export functions */ ++extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, ++ struct mdfld_dsi_dpi_timing *dpi_timing, ++ int num_lane, int bpp); ++extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, ++ struct mdfld_dsi_connector *dsi_connector, ++ const struct panel_funcs *p_funcs); ++ ++/* MDFLD DPI helper functions */ ++extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode); ++extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode); ++extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder); ++extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder); ++extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode); ++extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, ++ int pipe); ++extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, ++ int pipe); ++#endif /*__MDFLD_DSI_DPI_H__*/ +diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c +new file mode 100644 +index 0000000..5675d93 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c +@@ -0,0 +1,621 @@ ++/* ++ * Copyright © 2010 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * jim liu ++ * Jackie Li ++ */ ++ ++#include ++ ++#include "mdfld_dsi_output.h" ++#include "mdfld_dsi_dpi.h" ++#include "mdfld_output.h" ++#include "mdfld_dsi_pkg_sender.h" ++#include "tc35876x-dsi-lvds.h" ++#include ++#include ++ ++/* get the LABC from command line. */ ++static int LABC_control = 1; ++ ++#ifdef MODULE ++module_param(LABC_control, int, 0644); ++#else ++ ++static int __init parse_LABC_control(char *arg) ++{ ++ /* LABC control can be passed in as a cmdline parameter */ ++ /* to enable this feature add LABC=1 to cmdline */ ++ /* to disable this feature add LABC=0 to cmdline */ ++ if (!arg) ++ return -EINVAL; ++ ++ if (!strcasecmp(arg, "0")) ++ LABC_control = 0; ++ else if (!strcasecmp(arg, "1")) ++ LABC_control = 1; ++ ++ return 0; ++} ++early_param("LABC", parse_LABC_control); ++#endif ++ ++/** ++ * Check and see if the generic control or data buffer is empty and ready. ++ */ ++void mdfld_dsi_gen_fifo_ready(struct drm_device *dev, u32 gen_fifo_stat_reg, ++ u32 fifo_stat) ++{ ++ u32 GEN_BF_time_out_count; ++ ++ /* Check MIPI Adatper command registers */ ++ for (GEN_BF_time_out_count = 0; ++ GEN_BF_time_out_count < GEN_FB_TIME_OUT; ++ GEN_BF_time_out_count++) { ++ if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat) ++ break; ++ udelay(100); ++ } ++ ++ if (GEN_BF_time_out_count == GEN_FB_TIME_OUT) ++ DRM_ERROR("mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x.\n", ++ gen_fifo_stat_reg); ++} ++ ++/** ++ * Manage the DSI MIPI keyboard and display brightness. ++ * FIXME: this is exported to OSPM code. should work out an specific ++ * display interface to OSPM. ++ */ ++ ++void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe) ++{ ++ struct mdfld_dsi_pkg_sender *sender = ++ mdfld_dsi_get_pkg_sender(dsi_config); ++ struct drm_device *dev = sender->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 gen_ctrl_val; ++ ++ if (!sender) { ++ DRM_ERROR("No sender found\n"); ++ return; ++ } ++ ++ /* Set default display backlight value to 85% (0xd8)*/ ++ mdfld_dsi_send_mcs_short(sender, write_display_brightness, 0xd8, 1, ++ true); ++ ++ /* Set minimum brightness setting of CABC function to 20% (0x33)*/ ++ mdfld_dsi_send_mcs_short(sender, write_cabc_min_bright, 0x33, 1, true); ++ ++ /* Enable backlight or/and LABC */ ++ gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON | ++ BACKLIGHT_ON; ++ if (LABC_control == 1) ++ gen_ctrl_val |= DISPLAY_DIMMING_ON | DISPLAY_BRIGHTNESS_AUTO ++ | GAMMA_AUTO; ++ ++ if (LABC_control == 1) ++ gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON; ++ ++ dev_priv->mipi_ctrl_display = gen_ctrl_val; ++ ++ mdfld_dsi_send_mcs_short(sender, write_ctrl_display, (u8)gen_ctrl_val, ++ 1, true); ++ ++ mdfld_dsi_send_mcs_short(sender, write_ctrl_cabc, UI_IMAGE, 1, true); ++} ++ ++void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level) ++{ ++ struct mdfld_dsi_pkg_sender *sender; ++ struct drm_psb_private *dev_priv; ++ struct mdfld_dsi_config *dsi_config; ++ u32 gen_ctrl_val = 0; ++ int p_type = TMD_VID; ++ ++ if (!dev || (pipe != 0 && pipe != 2)) { ++ DRM_ERROR("Invalid parameter\n"); ++ return; ++ } ++ ++ p_type = mdfld_get_panel_type(dev, 0); ++ ++ dev_priv = dev->dev_private; ++ ++ if (pipe) ++ dsi_config = dev_priv->dsi_configs[1]; ++ else ++ dsi_config = dev_priv->dsi_configs[0]; ++ ++ sender = mdfld_dsi_get_pkg_sender(dsi_config); ++ ++ if (!sender) { ++ DRM_ERROR("No sender found\n"); ++ return; ++ } ++ ++ gen_ctrl_val = (level * 0xff / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff; ++ ++ dev_dbg(sender->dev->dev, "pipe = %d, gen_ctrl_val = %d.\n", ++ pipe, gen_ctrl_val); ++ ++ if (p_type == TMD_VID) { ++ /* Set display backlight value */ ++ mdfld_dsi_send_mcs_short(sender, tmd_write_display_brightness, ++ (u8)gen_ctrl_val, 1, true); ++ } else { ++ /* Set display backlight value */ ++ mdfld_dsi_send_mcs_short(sender, write_display_brightness, ++ (u8)gen_ctrl_val, 1, true); ++ ++ /* Enable backlight control */ ++ if (level == 0) ++ gen_ctrl_val = 0; ++ else ++ gen_ctrl_val = dev_priv->mipi_ctrl_display; ++ ++ mdfld_dsi_send_mcs_short(sender, write_ctrl_display, ++ (u8)gen_ctrl_val, 1, true); ++ } ++} ++ ++static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config, ++ u8 dcs, u32 *data, bool hs) ++{ ++ struct mdfld_dsi_pkg_sender *sender ++ = mdfld_dsi_get_pkg_sender(dsi_config); ++ ++ if (!sender || !data) { ++ DRM_ERROR("Invalid parameter\n"); ++ return -EINVAL; ++ } ++ ++ return mdfld_dsi_read_mcs(sender, dcs, data, 1, hs); ++} ++ ++int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, u32 *mode, ++ bool hs) ++{ ++ if (!dsi_config || !mode) { ++ DRM_ERROR("Invalid parameter\n"); ++ return -EINVAL; ++ } ++ ++ return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, hs); ++} ++ ++/* ++ * NOTE: this function was used by OSPM. ++ * TODO: will be removed later, should work out display interfaces for OSPM ++ */ ++void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe) ++{ ++ if (!dsi_config || ((pipe != 0) && (pipe != 2))) { ++ DRM_ERROR("Invalid parameters\n"); ++ return; ++ } ++ ++ mdfld_dsi_dpi_controller_init(dsi_config, pipe); ++} ++ ++static void mdfld_dsi_connector_save(struct drm_connector *connector) ++{ ++} ++ ++static void mdfld_dsi_connector_restore(struct drm_connector *connector) ++{ ++} ++ ++/* FIXME: start using the force parameter */ ++static enum drm_connector_status ++mdfld_dsi_connector_detect(struct drm_connector *connector, bool force) ++{ ++ struct mdfld_dsi_connector *dsi_connector ++ = mdfld_dsi_connector(connector); ++ ++ dsi_connector->status = connector_status_connected; ++ ++ return dsi_connector->status; ++} ++ ++static int mdfld_dsi_connector_set_property(struct drm_connector *connector, ++ struct drm_property *property, ++ uint64_t value) ++{ ++ struct drm_encoder *encoder = connector->encoder; ++ ++ if (!strcmp(property->name, "scaling mode") && encoder) { ++ struct psb_intel_crtc *psb_crtc = ++ to_psb_intel_crtc(encoder->crtc); ++ bool centerechange; ++ uint64_t val; ++ ++ if (!psb_crtc) ++ goto set_prop_error; ++ ++ switch (value) { ++ case DRM_MODE_SCALE_FULLSCREEN: ++ break; ++ case DRM_MODE_SCALE_NO_SCALE: ++ break; ++ case DRM_MODE_SCALE_ASPECT: ++ break; ++ default: ++ goto set_prop_error; ++ } ++ ++ if (drm_connector_property_get_value(connector, property, &val)) ++ goto set_prop_error; ++ ++ if (val == value) ++ goto set_prop_done; ++ ++ if (drm_connector_property_set_value(connector, ++ property, value)) ++ goto set_prop_error; ++ ++ centerechange = (val == DRM_MODE_SCALE_NO_SCALE) || ++ (value == DRM_MODE_SCALE_NO_SCALE); ++ ++ if (psb_crtc->saved_mode.hdisplay != 0 && ++ psb_crtc->saved_mode.vdisplay != 0) { ++ if (centerechange) { ++ if (!drm_crtc_helper_set_mode(encoder->crtc, ++ &psb_crtc->saved_mode, ++ encoder->crtc->x, ++ encoder->crtc->y, ++ encoder->crtc->fb)) ++ goto set_prop_error; ++ } else { ++ struct drm_encoder_helper_funcs *funcs = ++ encoder->helper_private; ++ funcs->mode_set(encoder, ++ &psb_crtc->saved_mode, ++ &psb_crtc->saved_adjusted_mode); ++ } ++ } ++ } else if (!strcmp(property->name, "backlight") && encoder) { ++ if (drm_connector_property_set_value(connector, property, ++ value)) ++ goto set_prop_error; ++ else { ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ struct backlight_device *psb_bd; ++ ++ psb_bd = mdfld_get_backlight_device(); ++ if (psb_bd) { ++ psb_bd->props.brightness = value; ++ mdfld_set_brightness(psb_bd); ++ } ++#endif ++ } ++ } ++set_prop_done: ++ return 0; ++set_prop_error: ++ return -1; ++} ++ ++static void mdfld_dsi_connector_destroy(struct drm_connector *connector) ++{ ++ struct mdfld_dsi_connector *dsi_connector = ++ mdfld_dsi_connector(connector); ++ struct mdfld_dsi_pkg_sender *sender; ++ ++ if (!dsi_connector) ++ return; ++ drm_sysfs_connector_remove(connector); ++ drm_connector_cleanup(connector); ++ sender = dsi_connector->pkg_sender; ++ mdfld_dsi_pkg_sender_destroy(sender); ++ kfree(dsi_connector); ++} ++ ++static int mdfld_dsi_connector_get_modes(struct drm_connector *connector) ++{ ++ struct mdfld_dsi_connector *dsi_connector = ++ mdfld_dsi_connector(connector); ++ struct mdfld_dsi_config *dsi_config = ++ mdfld_dsi_get_config(dsi_connector); ++ struct drm_display_mode *fixed_mode = dsi_config->fixed_mode; ++ struct drm_display_mode *dup_mode = NULL; ++ struct drm_device *dev = connector->dev; ++ ++ connector->display_info.min_vfreq = 0; ++ connector->display_info.max_vfreq = 200; ++ connector->display_info.min_hfreq = 0; ++ connector->display_info.max_hfreq = 200; ++ ++ if (fixed_mode) { ++ dev_dbg(dev->dev, "fixed_mode %dx%d\n", ++ fixed_mode->hdisplay, fixed_mode->vdisplay); ++ dup_mode = drm_mode_duplicate(dev, fixed_mode); ++ drm_mode_probed_add(connector, dup_mode); ++ return 1; ++ } ++ DRM_ERROR("Didn't get any modes!\n"); ++ return 0; ++} ++ ++static int mdfld_dsi_connector_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ struct mdfld_dsi_connector *dsi_connector = ++ mdfld_dsi_connector(connector); ++ struct mdfld_dsi_config *dsi_config = ++ mdfld_dsi_get_config(dsi_connector); ++ struct drm_display_mode *fixed_mode = dsi_config->fixed_mode; ++ ++ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ return MODE_NO_DBLESCAN; ++ ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) ++ return MODE_NO_INTERLACE; ++ ++ /** ++ * FIXME: current DC has no fitting unit, reject any mode setting ++ * request ++ * Will figure out a way to do up-scaling(pannel fitting) later. ++ **/ ++ if (fixed_mode) { ++ if (mode->hdisplay != fixed_mode->hdisplay) ++ return MODE_PANEL; ++ ++ if (mode->vdisplay != fixed_mode->vdisplay) ++ return MODE_PANEL; ++ } ++ ++ return MODE_OK; ++} ++ ++static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode) ++{ ++ if (mode == connector->dpms) ++ return; ++ ++ /*first, execute dpms*/ ++ ++ drm_helper_connector_dpms(connector, mode); ++} ++ ++static struct drm_encoder *mdfld_dsi_connector_best_encoder( ++ struct drm_connector *connector) ++{ ++ struct mdfld_dsi_connector *dsi_connector = ++ mdfld_dsi_connector(connector); ++ struct mdfld_dsi_config *dsi_config = ++ mdfld_dsi_get_config(dsi_connector); ++ return &dsi_config->encoder->base.base; ++} ++ ++/*DSI connector funcs*/ ++static const struct drm_connector_funcs mdfld_dsi_connector_funcs = { ++ .dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms, ++ .save = mdfld_dsi_connector_save, ++ .restore = mdfld_dsi_connector_restore, ++ .detect = mdfld_dsi_connector_detect, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .set_property = mdfld_dsi_connector_set_property, ++ .destroy = mdfld_dsi_connector_destroy, ++}; ++ ++/*DSI connector helper funcs*/ ++static const struct drm_connector_helper_funcs ++ mdfld_dsi_connector_helper_funcs = { ++ .get_modes = mdfld_dsi_connector_get_modes, ++ .mode_valid = mdfld_dsi_connector_mode_valid, ++ .best_encoder = mdfld_dsi_connector_best_encoder, ++}; ++ ++static int mdfld_dsi_get_default_config(struct drm_device *dev, ++ struct mdfld_dsi_config *config, int pipe) ++{ ++ if (!dev || !config) { ++ DRM_ERROR("Invalid parameters"); ++ return -EINVAL; ++ } ++ ++ config->bpp = 24; ++ if (mdfld_get_panel_type(dev, pipe) == TC35876X) ++ config->lane_count = 4; ++ else ++ config->lane_count = 2; ++ config->channel_num = 0; ++ ++ if (mdfld_get_panel_type(dev, pipe) == TMD_VID) ++ config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE; ++ else if (mdfld_get_panel_type(dev, pipe) == TC35876X) ++ config->video_mode = ++ MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS; ++ else ++ config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE; ++ ++ return 0; ++} ++ ++int mdfld_dsi_panel_reset(int pipe) ++{ ++ unsigned gpio; ++ int ret = 0; ++ ++ switch (pipe) { ++ case 0: ++ gpio = 128; ++ break; ++ case 2: ++ gpio = 34; ++ break; ++ default: ++ DRM_ERROR("Invalid output\n"); ++ return -EINVAL; ++ } ++ ++ ret = gpio_request(gpio, "gfx"); ++ if (ret) { ++ DRM_ERROR("gpio_rqueset failed\n"); ++ return ret; ++ } ++ ++ ret = gpio_direction_output(gpio, 1); ++ if (ret) { ++ DRM_ERROR("gpio_direction_output failed\n"); ++ goto gpio_error; ++ } ++ ++ gpio_get_value(128); ++ ++gpio_error: ++ if (gpio_is_valid(gpio)) ++ gpio_free(gpio); ++ ++ return ret; ++} ++ ++/* ++ * MIPI output init ++ * @dev drm device ++ * @pipe pipe number. 0 or 2 ++ * @config ++ * ++ * Do the initialization of a MIPI output, including create DRM mode objects ++ * initialization of DSI output on @pipe ++ */ ++void mdfld_dsi_output_init(struct drm_device *dev, ++ int pipe, ++ const struct panel_funcs *p_vid_funcs) ++{ ++ struct mdfld_dsi_config *dsi_config; ++ struct mdfld_dsi_connector *dsi_connector; ++ struct drm_connector *connector; ++ struct mdfld_dsi_encoder *encoder; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct panel_info dsi_panel_info; ++ u32 width_mm, height_mm; ++ ++ dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe); ++ ++ if (!dev || ((pipe != 0) && (pipe != 2))) { ++ DRM_ERROR("Invalid parameter\n"); ++ return; ++ } ++ ++ /*create a new connetor*/ ++ dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL); ++ if (!dsi_connector) { ++ DRM_ERROR("No memory"); ++ return; ++ } ++ ++ dsi_connector->pipe = pipe; ++ ++ dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), ++ GFP_KERNEL); ++ if (!dsi_config) { ++ DRM_ERROR("cannot allocate memory for DSI config\n"); ++ goto dsi_init_err0; ++ } ++ mdfld_dsi_get_default_config(dev, dsi_config, pipe); ++ ++ dsi_connector->private = dsi_config; ++ ++ dsi_config->changed = 1; ++ dsi_config->dev = dev; ++ ++ dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev); ++ if (p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info)) ++ goto dsi_init_err0; ++ ++ width_mm = dsi_panel_info.width_mm; ++ height_mm = dsi_panel_info.height_mm; ++ ++ dsi_config->mode = dsi_config->fixed_mode; ++ dsi_config->connector = dsi_connector; ++ ++ if (!dsi_config->fixed_mode) { ++ DRM_ERROR("No pannel fixed mode was found\n"); ++ goto dsi_init_err0; ++ } ++ ++ if (pipe && dev_priv->dsi_configs[0]) { ++ dsi_config->dvr_ic_inited = 0; ++ dev_priv->dsi_configs[1] = dsi_config; ++ } else if (pipe == 0) { ++ dsi_config->dvr_ic_inited = 1; ++ dev_priv->dsi_configs[0] = dsi_config; ++ } else { ++ DRM_ERROR("Trying to init MIPI1 before MIPI0\n"); ++ goto dsi_init_err0; ++ } ++ ++ ++ connector = &dsi_connector->base.base; ++ drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs, ++ DRM_MODE_CONNECTOR_LVDS); ++ drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs); ++ ++ connector->display_info.subpixel_order = SubPixelHorizontalRGB; ++ connector->display_info.width_mm = width_mm; ++ connector->display_info.height_mm = height_mm; ++ connector->interlace_allowed = false; ++ connector->doublescan_allowed = false; ++ ++ /*attach properties*/ ++ drm_connector_attach_property(connector, ++ dev->mode_config.scaling_mode_property, ++ DRM_MODE_SCALE_FULLSCREEN); ++ drm_connector_attach_property(connector, ++ dev_priv->backlight_property, ++ MDFLD_DSI_BRIGHTNESS_MAX_LEVEL); ++ ++ /*init DSI package sender on this output*/ ++ if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) { ++ DRM_ERROR("Package Sender initialization failed on pipe %d\n", ++ pipe); ++ goto dsi_init_err0; ++ } ++ ++ encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs); ++ if (!encoder) { ++ DRM_ERROR("Create DPI encoder failed\n"); ++ goto dsi_init_err1; ++ } ++ encoder->private = dsi_config; ++ dsi_config->encoder = encoder; ++ encoder->base.type = (pipe == 0) ? INTEL_OUTPUT_MIPI : ++ INTEL_OUTPUT_MIPI2; ++ drm_sysfs_connector_add(connector); ++ return; ++ ++ /*TODO: add code to destroy outputs on error*/ ++dsi_init_err1: ++ /*destroy sender*/ ++ mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender); ++ ++ drm_connector_cleanup(connector); ++ ++ kfree(dsi_config->fixed_mode); ++ kfree(dsi_config); ++dsi_init_err0: ++ kfree(dsi_connector); ++} +diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.h b/drivers/gpu/drm/gma500/mdfld_dsi_output.h +new file mode 100644 +index 0000000..36eb074 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.h +@@ -0,0 +1,377 @@ ++/* ++ * Copyright © 2010 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * jim liu ++ * Jackie Li ++ */ ++ ++#ifndef __MDFLD_DSI_OUTPUT_H__ ++#define __MDFLD_DSI_OUTPUT_H__ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "psb_drv.h" ++#include "psb_intel_drv.h" ++#include "psb_intel_reg.h" ++#include "mdfld_output.h" ++ ++#include ++ ++#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end)) ++#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end)) ++#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end)) ++#define FLD_MOD(orig, val, start, end) \ ++ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) ++ ++#define REG_FLD_MOD(reg, val, start, end) \ ++ REG_WRITE(reg, FLD_MOD(REG_READ(reg), val, start, end)) ++ ++static inline int REGISTER_FLD_WAIT(struct drm_device *dev, u32 reg, ++ u32 val, int start, int end) ++{ ++ int t = 100000; ++ ++ while (FLD_GET(REG_READ(reg), start, end) != val) { ++ if (--t == 0) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++#define REG_FLD_WAIT(reg, val, start, end) \ ++ REGISTER_FLD_WAIT(dev, reg, val, start, end) ++ ++#define REG_BIT_WAIT(reg, val, bitnum) \ ++ REGISTER_FLD_WAIT(dev, reg, val, bitnum, bitnum) ++ ++#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100 ++ ++#ifdef DEBUG ++#define CHECK_PIPE(pipe) ({ \ ++ const typeof(pipe) __pipe = (pipe); \ ++ BUG_ON(__pipe != 0 && __pipe != 2); \ ++ __pipe; }) ++#else ++#define CHECK_PIPE(pipe) (pipe) ++#endif ++ ++/* ++ * Actual MIPIA->MIPIC reg offset is 0x800, value 0x400 is valid for 0 and 2 ++ */ ++#define REG_OFFSET(pipe) (CHECK_PIPE(pipe) * 0x400) ++ ++/* mdfld DSI controller registers */ ++#define MIPI_DEVICE_READY_REG(pipe) (0xb000 + REG_OFFSET(pipe)) ++#define MIPI_INTR_STAT_REG(pipe) (0xb004 + REG_OFFSET(pipe)) ++#define MIPI_INTR_EN_REG(pipe) (0xb008 + REG_OFFSET(pipe)) ++#define MIPI_DSI_FUNC_PRG_REG(pipe) (0xb00c + REG_OFFSET(pipe)) ++#define MIPI_HS_TX_TIMEOUT_REG(pipe) (0xb010 + REG_OFFSET(pipe)) ++#define MIPI_LP_RX_TIMEOUT_REG(pipe) (0xb014 + REG_OFFSET(pipe)) ++#define MIPI_TURN_AROUND_TIMEOUT_REG(pipe) (0xb018 + REG_OFFSET(pipe)) ++#define MIPI_DEVICE_RESET_TIMER_REG(pipe) (0xb01c + REG_OFFSET(pipe)) ++#define MIPI_DPI_RESOLUTION_REG(pipe) (0xb020 + REG_OFFSET(pipe)) ++#define MIPI_DBI_FIFO_THROTTLE_REG(pipe) (0xb024 + REG_OFFSET(pipe)) ++#define MIPI_HSYNC_COUNT_REG(pipe) (0xb028 + REG_OFFSET(pipe)) ++#define MIPI_HBP_COUNT_REG(pipe) (0xb02c + REG_OFFSET(pipe)) ++#define MIPI_HFP_COUNT_REG(pipe) (0xb030 + REG_OFFSET(pipe)) ++#define MIPI_HACTIVE_COUNT_REG(pipe) (0xb034 + REG_OFFSET(pipe)) ++#define MIPI_VSYNC_COUNT_REG(pipe) (0xb038 + REG_OFFSET(pipe)) ++#define MIPI_VBP_COUNT_REG(pipe) (0xb03c + REG_OFFSET(pipe)) ++#define MIPI_VFP_COUNT_REG(pipe) (0xb040 + REG_OFFSET(pipe)) ++#define MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe) (0xb044 + REG_OFFSET(pipe)) ++#define MIPI_DPI_CONTROL_REG(pipe) (0xb048 + REG_OFFSET(pipe)) ++#define MIPI_DPI_DATA_REG(pipe) (0xb04c + REG_OFFSET(pipe)) ++#define MIPI_INIT_COUNT_REG(pipe) (0xb050 + REG_OFFSET(pipe)) ++#define MIPI_MAX_RETURN_PACK_SIZE_REG(pipe) (0xb054 + REG_OFFSET(pipe)) ++#define MIPI_VIDEO_MODE_FORMAT_REG(pipe) (0xb058 + REG_OFFSET(pipe)) ++#define MIPI_EOT_DISABLE_REG(pipe) (0xb05c + REG_OFFSET(pipe)) ++#define MIPI_LP_BYTECLK_REG(pipe) (0xb060 + REG_OFFSET(pipe)) ++#define MIPI_LP_GEN_DATA_REG(pipe) (0xb064 + REG_OFFSET(pipe)) ++#define MIPI_HS_GEN_DATA_REG(pipe) (0xb068 + REG_OFFSET(pipe)) ++#define MIPI_LP_GEN_CTRL_REG(pipe) (0xb06c + REG_OFFSET(pipe)) ++#define MIPI_HS_GEN_CTRL_REG(pipe) (0xb070 + REG_OFFSET(pipe)) ++#define MIPI_GEN_FIFO_STAT_REG(pipe) (0xb074 + REG_OFFSET(pipe)) ++#define MIPI_HS_LS_DBI_ENABLE_REG(pipe) (0xb078 + REG_OFFSET(pipe)) ++#define MIPI_DPHY_PARAM_REG(pipe) (0xb080 + REG_OFFSET(pipe)) ++#define MIPI_DBI_BW_CTRL_REG(pipe) (0xb084 + REG_OFFSET(pipe)) ++#define MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe) (0xb088 + REG_OFFSET(pipe)) ++ ++#define MIPI_CTRL_REG(pipe) (0xb104 + REG_OFFSET(pipe)) ++#define MIPI_DATA_ADD_REG(pipe) (0xb108 + REG_OFFSET(pipe)) ++#define MIPI_DATA_LEN_REG(pipe) (0xb10c + REG_OFFSET(pipe)) ++#define MIPI_CMD_ADD_REG(pipe) (0xb110 + REG_OFFSET(pipe)) ++#define MIPI_CMD_LEN_REG(pipe) (0xb114 + REG_OFFSET(pipe)) ++ ++/* non-uniform reg offset */ ++#define MIPI_PORT_CONTROL(pipe) (CHECK_PIPE(pipe) ? MIPI_C : MIPI) ++ ++#define DSI_DEVICE_READY (0x1) ++#define DSI_POWER_STATE_ULPS_ENTER (0x2 << 1) ++#define DSI_POWER_STATE_ULPS_EXIT (0x1 << 1) ++#define DSI_POWER_STATE_ULPS_OFFSET (0x1) ++ ++ ++#define DSI_ONE_DATA_LANE (0x1) ++#define DSI_TWO_DATA_LANE (0x2) ++#define DSI_THREE_DATA_LANE (0X3) ++#define DSI_FOUR_DATA_LANE (0x4) ++#define DSI_DPI_VIRT_CHANNEL_OFFSET (0x3) ++#define DSI_DBI_VIRT_CHANNEL_OFFSET (0x5) ++#define DSI_DPI_COLOR_FORMAT_RGB565 (0x01 << 7) ++#define DSI_DPI_COLOR_FORMAT_RGB666 (0x02 << 7) ++#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK (0x03 << 7) ++#define DSI_DPI_COLOR_FORMAT_RGB888 (0x04 << 7) ++#define DSI_DBI_COLOR_FORMAT_OPTION2 (0x05 << 13) ++ ++#define DSI_INTR_STATE_RXSOTERROR BIT(0) ++ ++#define DSI_INTR_STATE_SPL_PKG_SENT BIT(30) ++#define DSI_INTR_STATE_TE BIT(31) ++ ++#define DSI_HS_TX_TIMEOUT_MASK (0xffffff) ++ ++#define DSI_LP_RX_TIMEOUT_MASK (0xffffff) ++ ++#define DSI_TURN_AROUND_TIMEOUT_MASK (0x3f) ++ ++#define DSI_RESET_TIMER_MASK (0xffff) ++ ++#define DSI_DBI_FIFO_WM_HALF (0x0) ++#define DSI_DBI_FIFO_WM_QUARTER (0x1) ++#define DSI_DBI_FIFO_WM_LOW (0x2) ++ ++#define DSI_DPI_TIMING_MASK (0xffff) ++ ++#define DSI_INIT_TIMER_MASK (0xffff) ++ ++#define DSI_DBI_RETURN_PACK_SIZE_MASK (0x3ff) ++ ++#define DSI_LP_BYTECLK_MASK (0x0ffff) ++ ++#define DSI_HS_CTRL_GEN_SHORT_W0 (0x03) ++#define DSI_HS_CTRL_GEN_SHORT_W1 (0x13) ++#define DSI_HS_CTRL_GEN_SHORT_W2 (0x23) ++#define DSI_HS_CTRL_GEN_R0 (0x04) ++#define DSI_HS_CTRL_GEN_R1 (0x14) ++#define DSI_HS_CTRL_GEN_R2 (0x24) ++#define DSI_HS_CTRL_GEN_LONG_W (0x29) ++#define DSI_HS_CTRL_MCS_SHORT_W0 (0x05) ++#define DSI_HS_CTRL_MCS_SHORT_W1 (0x15) ++#define DSI_HS_CTRL_MCS_R0 (0x06) ++#define DSI_HS_CTRL_MCS_LONG_W (0x39) ++#define DSI_HS_CTRL_VC_OFFSET (0x06) ++#define DSI_HS_CTRL_WC_OFFSET (0x08) ++ ++#define DSI_FIFO_GEN_HS_DATA_FULL BIT(0) ++#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY BIT(1) ++#define DSI_FIFO_GEN_HS_DATA_EMPTY BIT(2) ++#define DSI_FIFO_GEN_LP_DATA_FULL BIT(8) ++#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY BIT(9) ++#define DSI_FIFO_GEN_LP_DATA_EMPTY BIT(10) ++#define DSI_FIFO_GEN_HS_CTRL_FULL BIT(16) ++#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY BIT(17) ++#define DSI_FIFO_GEN_HS_CTRL_EMPTY BIT(18) ++#define DSI_FIFO_GEN_LP_CTRL_FULL BIT(24) ++#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY BIT(25) ++#define DSI_FIFO_GEN_LP_CTRL_EMPTY BIT(26) ++#define DSI_FIFO_DBI_EMPTY BIT(27) ++#define DSI_FIFO_DPI_EMPTY BIT(28) ++ ++#define DSI_DBI_HS_LP_SWITCH_MASK (0x1) ++ ++#define DSI_HS_LP_SWITCH_COUNTER_OFFSET (0x0) ++#define DSI_LP_HS_SWITCH_COUNTER_OFFSET (0x16) ++ ++#define DSI_DPI_CTRL_HS_SHUTDOWN (0x00000001) ++#define DSI_DPI_CTRL_HS_TURN_ON (0x00000002) ++ ++/*dsi power modes*/ ++#define DSI_POWER_MODE_DISPLAY_ON BIT(2) ++#define DSI_POWER_MODE_NORMAL_ON BIT(3) ++#define DSI_POWER_MODE_SLEEP_OUT BIT(4) ++#define DSI_POWER_MODE_PARTIAL_ON BIT(5) ++#define DSI_POWER_MODE_IDLE_ON BIT(6) ++ ++enum { ++ MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1, ++ MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2, ++ MDFLD_DSI_VIDEO_BURST_MODE = 3, ++}; ++ ++#define DSI_DPI_COMPLETE_LAST_LINE BIT(2) ++#define DSI_DPI_DISABLE_BTA BIT(3) ++ ++struct mdfld_dsi_connector { ++ struct psb_intel_connector base; ++ ++ int pipe; ++ void *private; ++ void *pkg_sender; ++ ++ /* Connection status */ ++ enum drm_connector_status status; ++}; ++ ++struct mdfld_dsi_encoder { ++ struct psb_intel_encoder base; ++ void *private; ++}; ++ ++/* ++ * DSI config, consists of one DSI connector, two DSI encoders. ++ * DRM will pick up on DSI encoder basing on differents configs. ++ */ ++struct mdfld_dsi_config { ++ struct drm_device *dev; ++ struct drm_display_mode *fixed_mode; ++ struct drm_display_mode *mode; ++ ++ struct mdfld_dsi_connector *connector; ++ struct mdfld_dsi_encoder *encoder; ++ ++ int changed; ++ ++ int bpp; ++ int lane_count; ++ /*Virtual channel number for this encoder*/ ++ int channel_num; ++ /*video mode configure*/ ++ int video_mode; ++ ++ int dvr_ic_inited; ++}; ++ ++static inline struct mdfld_dsi_connector *mdfld_dsi_connector( ++ struct drm_connector *connector) ++{ ++ struct psb_intel_connector *psb_connector; ++ ++ psb_connector = to_psb_intel_connector(connector); ++ ++ return container_of(psb_connector, struct mdfld_dsi_connector, base); ++} ++ ++static inline struct mdfld_dsi_encoder *mdfld_dsi_encoder( ++ struct drm_encoder *encoder) ++{ ++ struct psb_intel_encoder *psb_encoder; ++ ++ psb_encoder = to_psb_intel_encoder(encoder); ++ ++ return container_of(psb_encoder, struct mdfld_dsi_encoder, base); ++} ++ ++static inline struct mdfld_dsi_config * ++ mdfld_dsi_get_config(struct mdfld_dsi_connector *connector) ++{ ++ if (!connector) ++ return NULL; ++ return (struct mdfld_dsi_config *)connector->private; ++} ++ ++static inline void *mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config *config) ++{ ++ struct mdfld_dsi_connector *dsi_connector; ++ ++ if (!config) ++ return NULL; ++ ++ dsi_connector = config->connector; ++ ++ if (!dsi_connector) ++ return NULL; ++ ++ return dsi_connector->pkg_sender; ++} ++ ++static inline struct mdfld_dsi_config * ++ mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder *encoder) ++{ ++ if (!encoder) ++ return NULL; ++ return (struct mdfld_dsi_config *)encoder->private; ++} ++ ++static inline struct mdfld_dsi_connector * ++ mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder *encoder) ++{ ++ struct mdfld_dsi_config *config; ++ ++ if (!encoder) ++ return NULL; ++ ++ config = mdfld_dsi_encoder_get_config(encoder); ++ if (!config) ++ return NULL; ++ ++ return config->connector; ++} ++ ++static inline void *mdfld_dsi_encoder_get_pkg_sender( ++ struct mdfld_dsi_encoder *encoder) ++{ ++ struct mdfld_dsi_config *dsi_config; ++ ++ dsi_config = mdfld_dsi_encoder_get_config(encoder); ++ if (!dsi_config) ++ return NULL; ++ ++ return mdfld_dsi_get_pkg_sender(dsi_config); ++} ++ ++static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder *encoder) ++{ ++ struct mdfld_dsi_connector *connector; ++ ++ if (!encoder) ++ return -1; ++ ++ connector = mdfld_dsi_encoder_get_connector(encoder); ++ if (!connector) ++ return -1; ++ return connector->pipe; ++} ++ ++/* Export functions */ ++extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev, ++ u32 gen_fifo_stat_reg, u32 fifo_stat); ++extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, ++ int pipe); ++extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, ++ int level); ++extern void mdfld_dsi_output_init(struct drm_device *dev, ++ int pipe, ++ const struct panel_funcs *p_vid_funcs); ++extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config, ++ int pipe); ++ ++extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, ++ u32 *mode, bool hs); ++extern int mdfld_dsi_panel_reset(int pipe); ++ ++#endif /*__MDFLD_DSI_OUTPUT_H__*/ +diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c +new file mode 100644 +index 0000000..baa0e14 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c +@@ -0,0 +1,694 @@ ++/* ++ * Copyright © 2010 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Jackie Li ++ */ ++ ++#include ++ ++#include "mdfld_dsi_output.h" ++#include "mdfld_dsi_pkg_sender.h" ++#include "mdfld_dsi_dpi.h" ++ ++#define MDFLD_DSI_READ_MAX_COUNT 5000 ++ ++enum data_type { ++ DSI_DT_GENERIC_SHORT_WRITE_0 = 0x03, ++ DSI_DT_GENERIC_SHORT_WRITE_1 = 0x13, ++ DSI_DT_GENERIC_SHORT_WRITE_2 = 0x23, ++ DSI_DT_GENERIC_READ_0 = 0x04, ++ DSI_DT_GENERIC_READ_1 = 0x14, ++ DSI_DT_GENERIC_READ_2 = 0x24, ++ DSI_DT_GENERIC_LONG_WRITE = 0x29, ++ DSI_DT_DCS_SHORT_WRITE_0 = 0x05, ++ DSI_DT_DCS_SHORT_WRITE_1 = 0x15, ++ DSI_DT_DCS_READ = 0x06, ++ DSI_DT_DCS_LONG_WRITE = 0x39, ++}; ++ ++enum { ++ MDFLD_DSI_PANEL_MODE_SLEEP = 0x1, ++}; ++ ++enum { ++ MDFLD_DSI_PKG_SENDER_FREE = 0x0, ++ MDFLD_DSI_PKG_SENDER_BUSY = 0x1, ++}; ++ ++static const char *const dsi_errors[] = { ++ "RX SOT Error", ++ "RX SOT Sync Error", ++ "RX EOT Sync Error", ++ "RX Escape Mode Entry Error", ++ "RX LP TX Sync Error", ++ "RX HS Receive Timeout Error", ++ "RX False Control Error", ++ "RX ECC Single Bit Error", ++ "RX ECC Multibit Error", ++ "RX Checksum Error", ++ "RX DSI Data Type Not Recognised", ++ "RX DSI VC ID Invalid", ++ "TX False Control Error", ++ "TX ECC Single Bit Error", ++ "TX ECC Multibit Error", ++ "TX Checksum Error", ++ "TX DSI Data Type Not Recognised", ++ "TX DSI VC ID invalid", ++ "High Contention", ++ "Low contention", ++ "DPI FIFO Under run", ++ "HS TX Timeout", ++ "LP RX Timeout", ++ "Turn Around ACK Timeout", ++ "ACK With No Error", ++ "RX Invalid TX Length", ++ "RX Prot Violation", ++ "HS Generic Write FIFO Full", ++ "LP Generic Write FIFO Full", ++ "Generic Read Data Avail" ++ "Special Packet Sent", ++ "Tearing Effect", ++}; ++ ++static inline int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender, ++ u32 mask) ++{ ++ struct drm_device *dev = sender->dev; ++ u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg; ++ int retry = 0xffff; ++ ++ while (retry--) { ++ if ((mask & REG_READ(gen_fifo_stat_reg)) == mask) ++ return 0; ++ udelay(100); ++ } ++ DRM_ERROR("fifo is NOT empty 0x%08x\n", REG_READ(gen_fifo_stat_reg)); ++ return -EIO; ++} ++ ++static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender) ++{ ++ return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(10) | BIT(18) | ++ BIT(26) | BIT(27) | BIT(28))); ++} ++ ++static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender) ++{ ++ return wait_for_gen_fifo_empty(sender, (BIT(10) | BIT(26))); ++} ++ ++static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender) ++{ ++ return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(18))); ++} ++ ++static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask) ++{ ++ u32 intr_stat_reg = sender->mipi_intr_stat_reg; ++ struct drm_device *dev = sender->dev; ++ ++ dev_dbg(sender->dev->dev, "Handling error 0x%08x\n", mask); ++ ++ switch (mask) { ++ case BIT(0): ++ case BIT(1): ++ case BIT(2): ++ case BIT(3): ++ case BIT(4): ++ case BIT(5): ++ case BIT(6): ++ case BIT(7): ++ case BIT(8): ++ case BIT(9): ++ case BIT(10): ++ case BIT(11): ++ case BIT(12): ++ case BIT(13): ++ dev_dbg(sender->dev->dev, "No Action required\n"); ++ break; ++ case BIT(14): ++ /*wait for all fifo empty*/ ++ /*wait_for_all_fifos_empty(sender)*/; ++ break; ++ case BIT(15): ++ dev_dbg(sender->dev->dev, "No Action required\n"); ++ break; ++ case BIT(16): ++ break; ++ case BIT(17): ++ break; ++ case BIT(18): ++ case BIT(19): ++ dev_dbg(sender->dev->dev, "High/Low contention detected\n"); ++ /*wait for contention recovery time*/ ++ /*mdelay(10);*/ ++ /*wait for all fifo empty*/ ++ if (0) ++ wait_for_all_fifos_empty(sender); ++ break; ++ case BIT(20): ++ dev_dbg(sender->dev->dev, "No Action required\n"); ++ break; ++ case BIT(21): ++ /*wait for all fifo empty*/ ++ /*wait_for_all_fifos_empty(sender);*/ ++ break; ++ case BIT(22): ++ break; ++ case BIT(23): ++ case BIT(24): ++ case BIT(25): ++ case BIT(26): ++ case BIT(27): ++ dev_dbg(sender->dev->dev, "HS Gen fifo full\n"); ++ REG_WRITE(intr_stat_reg, mask); ++ wait_for_hs_fifos_empty(sender); ++ break; ++ case BIT(28): ++ dev_dbg(sender->dev->dev, "LP Gen fifo full\n"); ++ REG_WRITE(intr_stat_reg, mask); ++ wait_for_lp_fifos_empty(sender); ++ break; ++ case BIT(29): ++ case BIT(30): ++ case BIT(31): ++ dev_dbg(sender->dev->dev, "No Action required\n"); ++ break; ++ } ++ ++ if (mask & REG_READ(intr_stat_reg)) ++ dev_dbg(sender->dev->dev, ++ "Cannot clean interrupt 0x%08x\n", mask); ++ return 0; ++} ++ ++static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender) ++{ ++ struct drm_device *dev = sender->dev; ++ u32 intr_stat_reg = sender->mipi_intr_stat_reg; ++ u32 mask; ++ u32 intr_stat; ++ int i; ++ int err = 0; ++ ++ intr_stat = REG_READ(intr_stat_reg); ++ ++ for (i = 0; i < 32; i++) { ++ mask = (0x00000001UL) << i; ++ if (intr_stat & mask) { ++ dev_dbg(sender->dev->dev, "[DSI]: %s\n", dsi_errors[i]); ++ err = handle_dsi_error(sender, mask); ++ if (err) ++ DRM_ERROR("Cannot handle error\n"); ++ } ++ } ++ return err; ++} ++ ++static int send_short_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type, ++ u8 cmd, u8 param, bool hs) ++{ ++ struct drm_device *dev = sender->dev; ++ u32 ctrl_reg; ++ u32 val; ++ u8 virtual_channel = 0; ++ ++ if (hs) { ++ ctrl_reg = sender->mipi_hs_gen_ctrl_reg; ++ ++ /* FIXME: wait_for_hs_fifos_empty(sender); */ ++ } else { ++ ctrl_reg = sender->mipi_lp_gen_ctrl_reg; ++ ++ /* FIXME: wait_for_lp_fifos_empty(sender); */ ++ } ++ ++ val = FLD_VAL(param, 23, 16) | FLD_VAL(cmd, 15, 8) | ++ FLD_VAL(virtual_channel, 7, 6) | FLD_VAL(data_type, 5, 0); ++ ++ REG_WRITE(ctrl_reg, val); ++ ++ return 0; ++} ++ ++static int send_long_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type, ++ u8 *data, int len, bool hs) ++{ ++ struct drm_device *dev = sender->dev; ++ u32 ctrl_reg; ++ u32 data_reg; ++ u32 val; ++ u8 *p; ++ u8 b1, b2, b3, b4; ++ u8 virtual_channel = 0; ++ int i; ++ ++ if (hs) { ++ ctrl_reg = sender->mipi_hs_gen_ctrl_reg; ++ data_reg = sender->mipi_hs_gen_data_reg; ++ ++ /* FIXME: wait_for_hs_fifos_empty(sender); */ ++ } else { ++ ctrl_reg = sender->mipi_lp_gen_ctrl_reg; ++ data_reg = sender->mipi_lp_gen_data_reg; ++ ++ /* FIXME: wait_for_lp_fifos_empty(sender); */ ++ } ++ ++ p = data; ++ for (i = 0; i < len / 4; i++) { ++ b1 = *p++; ++ b2 = *p++; ++ b3 = *p++; ++ b4 = *p++; ++ ++ REG_WRITE(data_reg, b4 << 24 | b3 << 16 | b2 << 8 | b1); ++ } ++ ++ i = len % 4; ++ if (i) { ++ b1 = 0; b2 = 0; b3 = 0; ++ ++ switch (i) { ++ case 3: ++ b1 = *p++; ++ b2 = *p++; ++ b3 = *p++; ++ break; ++ case 2: ++ b1 = *p++; ++ b2 = *p++; ++ break; ++ case 1: ++ b1 = *p++; ++ break; ++ } ++ ++ REG_WRITE(data_reg, b3 << 16 | b2 << 8 | b1); ++ } ++ ++ val = FLD_VAL(len, 23, 8) | FLD_VAL(virtual_channel, 7, 6) | ++ FLD_VAL(data_type, 5, 0); ++ ++ REG_WRITE(ctrl_reg, val); ++ ++ return 0; ++} ++ ++static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, u8 data_type, ++ u8 *data, u16 len) ++{ ++ u8 cmd; ++ ++ switch (data_type) { ++ case DSI_DT_DCS_SHORT_WRITE_0: ++ case DSI_DT_DCS_SHORT_WRITE_1: ++ case DSI_DT_DCS_LONG_WRITE: ++ cmd = *data; ++ break; ++ default: ++ return 0; ++ } ++ ++ /*this prevents other package sending while doing msleep*/ ++ sender->status = MDFLD_DSI_PKG_SENDER_BUSY; ++ ++ /*wait for 120 milliseconds in case exit_sleep_mode just be sent*/ ++ if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) { ++ /*TODO: replace it with msleep later*/ ++ mdelay(120); ++ } ++ ++ if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) { ++ /*TODO: replace it with msleep later*/ ++ mdelay(120); ++ } ++ return 0; ++} ++ ++static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, u8 data_type, ++ u8 *data, u16 len) ++{ ++ u8 cmd; ++ ++ switch (data_type) { ++ case DSI_DT_DCS_SHORT_WRITE_0: ++ case DSI_DT_DCS_SHORT_WRITE_1: ++ case DSI_DT_DCS_LONG_WRITE: ++ cmd = *data; ++ break; ++ default: ++ return 0; ++ } ++ ++ /*update panel status*/ ++ if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) { ++ sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP; ++ /*TODO: replace it with msleep later*/ ++ mdelay(120); ++ } else if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) { ++ sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP; ++ /*TODO: replace it with msleep later*/ ++ mdelay(120); ++ } else if (unlikely(cmd == DCS_SOFT_RESET)) { ++ /*TODO: replace it with msleep later*/ ++ mdelay(5); ++ } ++ ++ sender->status = MDFLD_DSI_PKG_SENDER_FREE; ++ ++ return 0; ++} ++ ++static int send_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type, ++ u8 *data, u16 len, bool hs) ++{ ++ int ret; ++ ++ /*handle DSI error*/ ++ ret = dsi_error_handler(sender); ++ if (ret) { ++ DRM_ERROR("Error handling failed\n"); ++ return -EAGAIN; ++ } ++ ++ /* send pkg */ ++ if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) { ++ DRM_ERROR("sender is busy\n"); ++ return -EAGAIN; ++ } ++ ++ ret = send_pkg_prepare(sender, data_type, data, len); ++ if (ret) { ++ DRM_ERROR("send_pkg_prepare error\n"); ++ return ret; ++ } ++ ++ switch (data_type) { ++ case DSI_DT_GENERIC_SHORT_WRITE_0: ++ case DSI_DT_GENERIC_SHORT_WRITE_1: ++ case DSI_DT_GENERIC_SHORT_WRITE_2: ++ case DSI_DT_GENERIC_READ_0: ++ case DSI_DT_GENERIC_READ_1: ++ case DSI_DT_GENERIC_READ_2: ++ case DSI_DT_DCS_SHORT_WRITE_0: ++ case DSI_DT_DCS_SHORT_WRITE_1: ++ case DSI_DT_DCS_READ: ++ ret = send_short_pkg(sender, data_type, data[0], data[1], hs); ++ break; ++ case DSI_DT_GENERIC_LONG_WRITE: ++ case DSI_DT_DCS_LONG_WRITE: ++ ret = send_long_pkg(sender, data_type, data, len, hs); ++ break; ++ } ++ ++ send_pkg_done(sender, data_type, data, len); ++ ++ /*FIXME: should I query complete and fifo empty here?*/ ++ ++ return ret; ++} ++ ++int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data, ++ u32 len, bool hs) ++{ ++ unsigned long flags; ++ ++ if (!sender || !data || !len) { ++ DRM_ERROR("Invalid parameters\n"); ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&sender->lock, flags); ++ send_pkg(sender, DSI_DT_DCS_LONG_WRITE, data, len, hs); ++ spin_unlock_irqrestore(&sender->lock, flags); ++ ++ return 0; ++} ++ ++int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd, ++ u8 param, u8 param_num, bool hs) ++{ ++ u8 data[2]; ++ unsigned long flags; ++ u8 data_type; ++ ++ if (!sender) { ++ DRM_ERROR("Invalid parameter\n"); ++ return -EINVAL; ++ } ++ ++ data[0] = cmd; ++ ++ if (param_num) { ++ data_type = DSI_DT_DCS_SHORT_WRITE_1; ++ data[1] = param; ++ } else { ++ data_type = DSI_DT_DCS_SHORT_WRITE_0; ++ data[1] = 0; ++ } ++ ++ spin_lock_irqsave(&sender->lock, flags); ++ send_pkg(sender, data_type, data, sizeof(data), hs); ++ spin_unlock_irqrestore(&sender->lock, flags); ++ ++ return 0; ++} ++ ++int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0, ++ u8 param1, u8 param_num, bool hs) ++{ ++ u8 data[2]; ++ unsigned long flags; ++ u8 data_type; ++ ++ if (!sender || param_num > 2) { ++ DRM_ERROR("Invalid parameter\n"); ++ return -EINVAL; ++ } ++ ++ switch (param_num) { ++ case 0: ++ data_type = DSI_DT_GENERIC_SHORT_WRITE_0; ++ data[0] = 0; ++ data[1] = 0; ++ break; ++ case 1: ++ data_type = DSI_DT_GENERIC_SHORT_WRITE_1; ++ data[0] = param0; ++ data[1] = 0; ++ break; ++ case 2: ++ data_type = DSI_DT_GENERIC_SHORT_WRITE_2; ++ data[0] = param0; ++ data[1] = param1; ++ break; ++ } ++ ++ spin_lock_irqsave(&sender->lock, flags); ++ send_pkg(sender, data_type, data, sizeof(data), hs); ++ spin_unlock_irqrestore(&sender->lock, flags); ++ ++ return 0; ++} ++ ++int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data, ++ u32 len, bool hs) ++{ ++ unsigned long flags; ++ ++ if (!sender || !data || !len) { ++ DRM_ERROR("Invalid parameters\n"); ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&sender->lock, flags); ++ send_pkg(sender, DSI_DT_GENERIC_LONG_WRITE, data, len, hs); ++ spin_unlock_irqrestore(&sender->lock, flags); ++ ++ return 0; ++} ++ ++static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type, ++ u8 *data, u16 len, u32 *data_out, u16 len_out, bool hs) ++{ ++ unsigned long flags; ++ struct drm_device *dev = sender->dev; ++ int i; ++ u32 gen_data_reg; ++ int retry = MDFLD_DSI_READ_MAX_COUNT; ++ ++ if (!sender || !data_out || !len_out) { ++ DRM_ERROR("Invalid parameters\n"); ++ return -EINVAL; ++ } ++ ++ /** ++ * do reading. ++ * 0) send out generic read request ++ * 1) polling read data avail interrupt ++ * 2) read data ++ */ ++ spin_lock_irqsave(&sender->lock, flags); ++ ++ REG_WRITE(sender->mipi_intr_stat_reg, BIT(29)); ++ ++ if ((REG_READ(sender->mipi_intr_stat_reg) & BIT(29))) ++ DRM_ERROR("Can NOT clean read data valid interrupt\n"); ++ ++ /*send out read request*/ ++ send_pkg(sender, data_type, data, len, hs); ++ ++ /*polling read data avail interrupt*/ ++ while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & BIT(29))) { ++ udelay(100); ++ retry--; ++ } ++ ++ if (!retry) { ++ spin_unlock_irqrestore(&sender->lock, flags); ++ return -ETIMEDOUT; ++ } ++ ++ REG_WRITE(sender->mipi_intr_stat_reg, BIT(29)); ++ ++ /*read data*/ ++ if (hs) ++ gen_data_reg = sender->mipi_hs_gen_data_reg; ++ else ++ gen_data_reg = sender->mipi_lp_gen_data_reg; ++ ++ for (i = 0; i < len_out; i++) ++ *(data_out + i) = REG_READ(gen_data_reg); ++ ++ spin_unlock_irqrestore(&sender->lock, flags); ++ ++ return 0; ++} ++ ++int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd, ++ u32 *data, u16 len, bool hs) ++{ ++ if (!sender || !data || !len) { ++ DRM_ERROR("Invalid parameters\n"); ++ return -EINVAL; ++ } ++ ++ return __read_panel_data(sender, DSI_DT_DCS_READ, &cmd, 1, ++ data, len, hs); ++} ++ ++int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector, ++ int pipe) ++{ ++ struct mdfld_dsi_pkg_sender *pkg_sender; ++ struct mdfld_dsi_config *dsi_config = ++ mdfld_dsi_get_config(dsi_connector); ++ struct drm_device *dev = dsi_config->dev; ++ u32 mipi_val = 0; ++ ++ if (!dsi_connector) { ++ DRM_ERROR("Invalid parameter\n"); ++ return -EINVAL; ++ } ++ ++ pkg_sender = dsi_connector->pkg_sender; ++ ++ if (!pkg_sender || IS_ERR(pkg_sender)) { ++ pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender), ++ GFP_KERNEL); ++ if (!pkg_sender) { ++ DRM_ERROR("Create DSI pkg sender failed\n"); ++ return -ENOMEM; ++ } ++ dsi_connector->pkg_sender = (void *)pkg_sender; ++ } ++ ++ pkg_sender->dev = dev; ++ pkg_sender->dsi_connector = dsi_connector; ++ pkg_sender->pipe = pipe; ++ pkg_sender->pkg_num = 0; ++ pkg_sender->panel_mode = 0; ++ pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE; ++ ++ /*init regs*/ ++ if (pipe == 0) { ++ pkg_sender->dpll_reg = MRST_DPLL_A; ++ pkg_sender->dspcntr_reg = DSPACNTR; ++ pkg_sender->pipeconf_reg = PIPEACONF; ++ pkg_sender->dsplinoff_reg = DSPALINOFF; ++ pkg_sender->dspsurf_reg = DSPASURF; ++ pkg_sender->pipestat_reg = PIPEASTAT; ++ } else if (pipe == 2) { ++ pkg_sender->dpll_reg = MRST_DPLL_A; ++ pkg_sender->dspcntr_reg = DSPCCNTR; ++ pkg_sender->pipeconf_reg = PIPECCONF; ++ pkg_sender->dsplinoff_reg = DSPCLINOFF; ++ pkg_sender->dspsurf_reg = DSPCSURF; ++ pkg_sender->pipestat_reg = PIPECSTAT; ++ } ++ ++ pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe); ++ pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe); ++ pkg_sender->mipi_hs_gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe); ++ pkg_sender->mipi_lp_gen_ctrl_reg = MIPI_LP_GEN_CTRL_REG(pipe); ++ pkg_sender->mipi_hs_gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe); ++ pkg_sender->mipi_gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe); ++ pkg_sender->mipi_data_addr_reg = MIPI_DATA_ADD_REG(pipe); ++ pkg_sender->mipi_data_len_reg = MIPI_DATA_LEN_REG(pipe); ++ pkg_sender->mipi_cmd_addr_reg = MIPI_CMD_ADD_REG(pipe); ++ pkg_sender->mipi_cmd_len_reg = MIPI_CMD_LEN_REG(pipe); ++ ++ /*init lock*/ ++ spin_lock_init(&pkg_sender->lock); ++ ++ if (mdfld_get_panel_type(dev, pipe) != TC35876X) { ++ /** ++ * For video mode, don't enable DPI timing output here, ++ * will init the DPI timing output during mode setting. ++ */ ++ mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; ++ ++ if (pipe == 0) ++ mipi_val |= 0x2; ++ ++ REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi_val); ++ REG_READ(MIPI_PORT_CONTROL(pipe)); ++ ++ /* do dsi controller init */ ++ mdfld_dsi_controller_init(dsi_config, pipe); ++ } ++ ++ return 0; ++} ++ ++void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender) ++{ ++ if (!sender || IS_ERR(sender)) ++ return; ++ ++ /*free*/ ++ kfree(sender); ++} ++ ++ +diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h +new file mode 100644 +index 0000000..459cd7e +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h +@@ -0,0 +1,92 @@ ++/* ++ * Copyright © 2010 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Jackie Li ++ */ ++#ifndef __MDFLD_DSI_PKG_SENDER_H__ ++#define __MDFLD_DSI_PKG_SENDER_H__ ++ ++#include ++ ++#define MDFLD_MAX_DCS_PARAM 8 ++ ++struct mdfld_dsi_pkg_sender { ++ struct drm_device *dev; ++ struct mdfld_dsi_connector *dsi_connector; ++ u32 status; ++ u32 panel_mode; ++ ++ int pipe; ++ ++ spinlock_t lock; ++ ++ u32 pkg_num; ++ ++ /* Registers */ ++ u32 dpll_reg; ++ u32 dspcntr_reg; ++ u32 pipeconf_reg; ++ u32 pipestat_reg; ++ u32 dsplinoff_reg; ++ u32 dspsurf_reg; ++ ++ u32 mipi_intr_stat_reg; ++ u32 mipi_lp_gen_data_reg; ++ u32 mipi_hs_gen_data_reg; ++ u32 mipi_lp_gen_ctrl_reg; ++ u32 mipi_hs_gen_ctrl_reg; ++ u32 mipi_gen_fifo_stat_reg; ++ u32 mipi_data_addr_reg; ++ u32 mipi_data_len_reg; ++ u32 mipi_cmd_addr_reg; ++ u32 mipi_cmd_len_reg; ++}; ++ ++/* DCS definitions */ ++#define DCS_SOFT_RESET 0x01 ++#define DCS_ENTER_SLEEP_MODE 0x10 ++#define DCS_EXIT_SLEEP_MODE 0x11 ++#define DCS_SET_DISPLAY_OFF 0x28 ++#define DCS_SET_DISPLAY_ON 0x29 ++#define DCS_SET_COLUMN_ADDRESS 0x2a ++#define DCS_SET_PAGE_ADDRESS 0x2b ++#define DCS_WRITE_MEM_START 0x2c ++#define DCS_SET_TEAR_OFF 0x34 ++#define DCS_SET_TEAR_ON 0x35 ++ ++extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector, ++ int pipe); ++extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender); ++int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd, ++ u8 param, u8 param_num, bool hs); ++int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data, ++ u32 len, bool hs); ++int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0, ++ u8 param1, u8 param_num, bool hs); ++int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data, ++ u32 len, bool hs); ++/* Read interfaces */ ++int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd, ++ u32 *data, u16 len, bool hs); ++ ++#endif +diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c +new file mode 100644 +index 0000000..a35a292 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c +@@ -0,0 +1,1180 @@ ++/* ++ * Copyright © 2006-2007 Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: ++ * Eric Anholt ++ */ ++ ++#include ++#include ++ ++#include ++#include "psb_intel_reg.h" ++#include "psb_intel_display.h" ++#include "framebuffer.h" ++#include "mdfld_output.h" ++#include "mdfld_dsi_output.h" ++ ++/* Hardcoded currently */ ++static int ksel = KSEL_CRYSTAL_19; ++ ++struct psb_intel_range_t { ++ int min, max; ++}; ++ ++struct mrst_limit_t { ++ struct psb_intel_range_t dot, m, p1; ++}; ++ ++struct mrst_clock_t { ++ /* derived values */ ++ int dot; ++ int m; ++ int p1; ++}; ++ ++#define COUNT_MAX 0x10000000 ++ ++void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe) ++{ ++ int count, temp; ++ u32 pipeconf_reg = PIPEACONF; ++ ++ switch (pipe) { ++ case 0: ++ break; ++ case 1: ++ pipeconf_reg = PIPEBCONF; ++ break; ++ case 2: ++ pipeconf_reg = PIPECCONF; ++ break; ++ default: ++ DRM_ERROR("Illegal Pipe Number.\n"); ++ return; ++ } ++ ++ /* FIXME JLIU7_PO */ ++ psb_intel_wait_for_vblank(dev); ++ return; ++ ++ /* Wait for for the pipe disable to take effect. */ ++ for (count = 0; count < COUNT_MAX; count++) { ++ temp = REG_READ(pipeconf_reg); ++ if ((temp & PIPEACONF_PIPE_STATE) == 0) ++ break; ++ } ++} ++ ++void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe) ++{ ++ int count, temp; ++ u32 pipeconf_reg = PIPEACONF; ++ ++ switch (pipe) { ++ case 0: ++ break; ++ case 1: ++ pipeconf_reg = PIPEBCONF; ++ break; ++ case 2: ++ pipeconf_reg = PIPECCONF; ++ break; ++ default: ++ DRM_ERROR("Illegal Pipe Number.\n"); ++ return; ++ } ++ ++ /* FIXME JLIU7_PO */ ++ psb_intel_wait_for_vblank(dev); ++ return; ++ ++ /* Wait for for the pipe enable to take effect. */ ++ for (count = 0; count < COUNT_MAX; count++) { ++ temp = REG_READ(pipeconf_reg); ++ if ((temp & PIPEACONF_PIPE_STATE) == 1) ++ break; ++ } ++} ++ ++static void psb_intel_crtc_prepare(struct drm_crtc *crtc) ++{ ++ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; ++ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); ++} ++ ++static void psb_intel_crtc_commit(struct drm_crtc *crtc) ++{ ++ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; ++ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); ++} ++ ++static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ return true; ++} ++ ++/** ++ * Return the pipe currently connected to the panel fitter, ++ * or -1 if the panel fitter is not present or not in use ++ */ ++static int psb_intel_panel_fitter_pipe(struct drm_device *dev) ++{ ++ u32 pfit_control; ++ ++ pfit_control = REG_READ(PFIT_CONTROL); ++ ++ /* See if the panel fitter is in use */ ++ if ((pfit_control & PFIT_ENABLE) == 0) ++ return -1; ++ ++ /* 965 can place panel fitter on either pipe */ ++ return (pfit_control >> 29) & 0x3; ++} ++ ++static struct drm_device globle_dev; ++ ++void mdfld__intel_plane_set_alpha(int enable) ++{ ++ struct drm_device *dev = &globle_dev; ++ int dspcntr_reg = DSPACNTR; ++ u32 dspcntr; ++ ++ dspcntr = REG_READ(dspcntr_reg); ++ ++ if (enable) { ++ dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA; ++ dspcntr |= DISPPLANE_32BPP; ++ } else { ++ dspcntr &= ~DISPPLANE_32BPP; ++ dspcntr |= DISPPLANE_32BPP_NO_ALPHA; ++ } ++ ++ REG_WRITE(dspcntr_reg, dspcntr); ++} ++ ++static int check_fb(struct drm_framebuffer *fb) ++{ ++ if (!fb) ++ return 0; ++ ++ switch (fb->bits_per_pixel) { ++ case 8: ++ case 16: ++ case 24: ++ case 32: ++ return 0; ++ default: ++ DRM_ERROR("Unknown color depth\n"); ++ return -EINVAL; ++ } ++} ++ ++static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, ++ struct drm_framebuffer *old_fb) ++{ ++ struct drm_device *dev = crtc->dev; ++ /* struct drm_i915_master_private *master_priv; */ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); ++ int pipe = psb_intel_crtc->pipe; ++ unsigned long start, offset; ++ int dsplinoff = DSPALINOFF; ++ int dspsurf = DSPASURF; ++ int dspstride = DSPASTRIDE; ++ int dspcntr_reg = DSPACNTR; ++ u32 dspcntr; ++ int ret; ++ ++ memcpy(&globle_dev, dev, sizeof(struct drm_device)); ++ ++ dev_dbg(dev->dev, "pipe = 0x%x.\n", pipe); ++ ++ /* no fb bound */ ++ if (!crtc->fb) { ++ dev_dbg(dev->dev, "No FB bound\n"); ++ return 0; ++ } ++ ++ ret = check_fb(crtc->fb); ++ if (ret) ++ return ret; ++ ++ switch (pipe) { ++ case 0: ++ dsplinoff = DSPALINOFF; ++ break; ++ case 1: ++ dsplinoff = DSPBLINOFF; ++ dspsurf = DSPBSURF; ++ dspstride = DSPBSTRIDE; ++ dspcntr_reg = DSPBCNTR; ++ break; ++ case 2: ++ dsplinoff = DSPCLINOFF; ++ dspsurf = DSPCSURF; ++ dspstride = DSPCSTRIDE; ++ dspcntr_reg = DSPCCNTR; ++ break; ++ default: ++ DRM_ERROR("Illegal Pipe Number.\n"); ++ return -EINVAL; ++ } ++ ++ if (!gma_power_begin(dev, true)) ++ return 0; ++ ++ start = psbfb->gtt->offset; ++ offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); ++ ++ REG_WRITE(dspstride, crtc->fb->pitches[0]); ++ dspcntr = REG_READ(dspcntr_reg); ++ dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; ++ ++ switch (crtc->fb->bits_per_pixel) { ++ case 8: ++ dspcntr |= DISPPLANE_8BPP; ++ break; ++ case 16: ++ if (crtc->fb->depth == 15) ++ dspcntr |= DISPPLANE_15_16BPP; ++ else ++ dspcntr |= DISPPLANE_16BPP; ++ break; ++ case 24: ++ case 32: ++ dspcntr |= DISPPLANE_32BPP_NO_ALPHA; ++ break; ++ } ++ REG_WRITE(dspcntr_reg, dspcntr); ++ ++ dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n", ++ start, offset, x, y); ++ REG_WRITE(dsplinoff, offset); ++ REG_READ(dsplinoff); ++ REG_WRITE(dspsurf, start); ++ REG_READ(dspsurf); ++ ++ gma_power_end(dev); ++ ++ return 0; ++} ++ ++/* ++ * Disable the pipe, plane and pll. ++ * ++ */ ++void mdfld_disable_crtc(struct drm_device *dev, int pipe) ++{ ++ int dpll_reg = MRST_DPLL_A; ++ int dspcntr_reg = DSPACNTR; ++ int dspbase_reg = MRST_DSPABASE; ++ int pipeconf_reg = PIPEACONF; ++ u32 temp; ++ ++ dev_dbg(dev->dev, "pipe = %d\n", pipe); ++ ++ ++ switch (pipe) { ++ case 0: ++ break; ++ case 1: ++ dpll_reg = MDFLD_DPLL_B; ++ dspcntr_reg = DSPBCNTR; ++ dspbase_reg = DSPBSURF; ++ pipeconf_reg = PIPEBCONF; ++ break; ++ case 2: ++ dpll_reg = MRST_DPLL_A; ++ dspcntr_reg = DSPCCNTR; ++ dspbase_reg = MDFLD_DSPCBASE; ++ pipeconf_reg = PIPECCONF; ++ break; ++ default: ++ DRM_ERROR("Illegal Pipe Number.\n"); ++ return; ++ } ++ ++ if (pipe != 1) ++ mdfld_dsi_gen_fifo_ready(dev, MIPI_GEN_FIFO_STAT_REG(pipe), ++ HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); ++ ++ /* Disable display plane */ ++ temp = REG_READ(dspcntr_reg); ++ if ((temp & DISPLAY_PLANE_ENABLE) != 0) { ++ REG_WRITE(dspcntr_reg, ++ temp & ~DISPLAY_PLANE_ENABLE); ++ /* Flush the plane changes */ ++ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); ++ REG_READ(dspbase_reg); ++ } ++ ++ /* FIXME_JLIU7 MDFLD_PO revisit */ ++ ++ /* Next, disable display pipes */ ++ temp = REG_READ(pipeconf_reg); ++ if ((temp & PIPEACONF_ENABLE) != 0) { ++ temp &= ~PIPEACONF_ENABLE; ++ temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF; ++ REG_WRITE(pipeconf_reg, temp); ++ REG_READ(pipeconf_reg); ++ ++ /* Wait for for the pipe disable to take effect. */ ++ mdfldWaitForPipeDisable(dev, pipe); ++ } ++ ++ temp = REG_READ(dpll_reg); ++ if (temp & DPLL_VCO_ENABLE) { ++ if ((pipe != 1 && ++ !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) ++ & PIPEACONF_ENABLE)) || pipe == 1) { ++ temp &= ~(DPLL_VCO_ENABLE); ++ REG_WRITE(dpll_reg, temp); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to turn off. */ ++ /* FIXME_MDFLD PO may need more delay */ ++ udelay(500); ++ ++ if (!(temp & MDFLD_PWR_GATE_EN)) { ++ /* gating power of DPLL */ ++ REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN); ++ /* FIXME_MDFLD PO - change 500 to 1 after PO */ ++ udelay(5000); ++ } ++ } ++ } ++ ++} ++ ++/** ++ * Sets the power management mode of the pipe and plane. ++ * ++ * This code should probably grow support for turning the cursor off and back ++ * on appropriately at the same time as we're turning the pipe off/on. ++ */ ++static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ int dpll_reg = MRST_DPLL_A; ++ int dspcntr_reg = DSPACNTR; ++ int dspbase_reg = MRST_DSPABASE; ++ int pipeconf_reg = PIPEACONF; ++ u32 pipestat_reg = PIPEASTAT; ++ u32 pipeconf = dev_priv->pipeconf[pipe]; ++ u32 temp; ++ int timeout = 0; ++ ++ dev_dbg(dev->dev, "mode = %d, pipe = %d\n", mode, pipe); ++ ++/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */ ++/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */ ++ ++ switch (pipe) { ++ case 0: ++ break; ++ case 1: ++ dpll_reg = DPLL_B; ++ dspcntr_reg = DSPBCNTR; ++ dspbase_reg = MRST_DSPBBASE; ++ pipeconf_reg = PIPEBCONF; ++ dpll_reg = MDFLD_DPLL_B; ++ break; ++ case 2: ++ dpll_reg = MRST_DPLL_A; ++ dspcntr_reg = DSPCCNTR; ++ dspbase_reg = MDFLD_DSPCBASE; ++ pipeconf_reg = PIPECCONF; ++ pipestat_reg = PIPECSTAT; ++ break; ++ default: ++ DRM_ERROR("Illegal Pipe Number.\n"); ++ return; ++ } ++ ++ if (!gma_power_begin(dev, true)) ++ return; ++ ++ /* XXX: When our outputs are all unaware of DPMS modes other than off ++ * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. ++ */ ++ switch (mode) { ++ case DRM_MODE_DPMS_ON: ++ case DRM_MODE_DPMS_STANDBY: ++ case DRM_MODE_DPMS_SUSPEND: ++ /* Enable the DPLL */ ++ temp = REG_READ(dpll_reg); ++ ++ if ((temp & DPLL_VCO_ENABLE) == 0) { ++ /* When ungating power of DPLL, needs to wait 0.5us ++ before enable the VCO */ ++ if (temp & MDFLD_PWR_GATE_EN) { ++ temp &= ~MDFLD_PWR_GATE_EN; ++ REG_WRITE(dpll_reg, temp); ++ /* FIXME_MDFLD PO - change 500 to 1 after PO */ ++ udelay(500); ++ } ++ ++ REG_WRITE(dpll_reg, temp); ++ REG_READ(dpll_reg); ++ /* FIXME_MDFLD PO - change 500 to 1 after PO */ ++ udelay(500); ++ ++ REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ ++ /** ++ * wait for DSI PLL to lock ++ * NOTE: only need to poll status of pipe 0 and pipe 1, ++ * since both MIPI pipes share the same PLL. ++ */ ++ while ((pipe != 2) && (timeout < 20000) && ++ !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { ++ udelay(150); ++ timeout++; ++ } ++ } ++ ++ /* Enable the plane */ ++ temp = REG_READ(dspcntr_reg); ++ if ((temp & DISPLAY_PLANE_ENABLE) == 0) { ++ REG_WRITE(dspcntr_reg, ++ temp | DISPLAY_PLANE_ENABLE); ++ /* Flush the plane changes */ ++ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); ++ } ++ ++ /* Enable the pipe */ ++ temp = REG_READ(pipeconf_reg); ++ if ((temp & PIPEACONF_ENABLE) == 0) { ++ REG_WRITE(pipeconf_reg, pipeconf); ++ ++ /* Wait for for the pipe enable to take effect. */ ++ mdfldWaitForPipeEnable(dev, pipe); ++ } ++ ++ /*workaround for sighting 3741701 Random X blank display*/ ++ /*perform w/a in video mode only on pipe A or C*/ ++ if (pipe == 0 || pipe == 2) { ++ REG_WRITE(pipestat_reg, REG_READ(pipestat_reg)); ++ msleep(100); ++ if (PIPE_VBLANK_STATUS & REG_READ(pipestat_reg)) ++ dev_dbg(dev->dev, "OK"); ++ else { ++ dev_dbg(dev->dev, "STUCK!!!!"); ++ /*shutdown controller*/ ++ temp = REG_READ(dspcntr_reg); ++ REG_WRITE(dspcntr_reg, ++ temp & ~DISPLAY_PLANE_ENABLE); ++ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); ++ /*mdfld_dsi_dpi_shut_down(dev, pipe);*/ ++ REG_WRITE(0xb048, 1); ++ msleep(100); ++ temp = REG_READ(pipeconf_reg); ++ temp &= ~PIPEACONF_ENABLE; ++ REG_WRITE(pipeconf_reg, temp); ++ msleep(100); /*wait for pipe disable*/ ++ REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0); ++ msleep(100); ++ REG_WRITE(0xb004, REG_READ(0xb004)); ++ /* try to bring the controller back up again*/ ++ REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 1); ++ temp = REG_READ(dspcntr_reg); ++ REG_WRITE(dspcntr_reg, ++ temp | DISPLAY_PLANE_ENABLE); ++ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); ++ /*mdfld_dsi_dpi_turn_on(dev, pipe);*/ ++ REG_WRITE(0xb048, 2); ++ msleep(100); ++ temp = REG_READ(pipeconf_reg); ++ temp |= PIPEACONF_ENABLE; ++ REG_WRITE(pipeconf_reg, temp); ++ } ++ } ++ ++ psb_intel_crtc_load_lut(crtc); ++ ++ /* Give the overlay scaler a chance to enable ++ if it's on this pipe */ ++ /* psb_intel_crtc_dpms_video(crtc, true); TODO */ ++ ++ break; ++ case DRM_MODE_DPMS_OFF: ++ /* Give the overlay scaler a chance to disable ++ * if it's on this pipe */ ++ /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ ++ if (pipe != 1) ++ mdfld_dsi_gen_fifo_ready(dev, ++ MIPI_GEN_FIFO_STAT_REG(pipe), ++ HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); ++ ++ /* Disable the VGA plane that we never use */ ++ REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); ++ ++ /* Disable display plane */ ++ temp = REG_READ(dspcntr_reg); ++ if ((temp & DISPLAY_PLANE_ENABLE) != 0) { ++ REG_WRITE(dspcntr_reg, ++ temp & ~DISPLAY_PLANE_ENABLE); ++ /* Flush the plane changes */ ++ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); ++ REG_READ(dspbase_reg); ++ } ++ ++ /* Next, disable display pipes */ ++ temp = REG_READ(pipeconf_reg); ++ if ((temp & PIPEACONF_ENABLE) != 0) { ++ temp &= ~PIPEACONF_ENABLE; ++ temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF; ++ REG_WRITE(pipeconf_reg, temp); ++ REG_READ(pipeconf_reg); ++ ++ /* Wait for for the pipe disable to take effect. */ ++ mdfldWaitForPipeDisable(dev, pipe); ++ } ++ ++ temp = REG_READ(dpll_reg); ++ if (temp & DPLL_VCO_ENABLE) { ++ if ((pipe != 1 && !((REG_READ(PIPEACONF) ++ | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE)) ++ || pipe == 1) { ++ temp &= ~(DPLL_VCO_ENABLE); ++ REG_WRITE(dpll_reg, temp); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to turn off. */ ++ /* FIXME_MDFLD PO may need more delay */ ++ udelay(500); ++ } ++ } ++ break; ++ } ++ gma_power_end(dev); ++} ++ ++ ++#define MDFLD_LIMT_DPLL_19 0 ++#define MDFLD_LIMT_DPLL_25 1 ++#define MDFLD_LIMT_DPLL_83 2 ++#define MDFLD_LIMT_DPLL_100 3 ++#define MDFLD_LIMT_DSIPLL_19 4 ++#define MDFLD_LIMT_DSIPLL_25 5 ++#define MDFLD_LIMT_DSIPLL_83 6 ++#define MDFLD_LIMT_DSIPLL_100 7 ++ ++#define MDFLD_DOT_MIN 19750 ++#define MDFLD_DOT_MAX 120000 ++#define MDFLD_DPLL_M_MIN_19 113 ++#define MDFLD_DPLL_M_MAX_19 155 ++#define MDFLD_DPLL_P1_MIN_19 2 ++#define MDFLD_DPLL_P1_MAX_19 10 ++#define MDFLD_DPLL_M_MIN_25 101 ++#define MDFLD_DPLL_M_MAX_25 130 ++#define MDFLD_DPLL_P1_MIN_25 2 ++#define MDFLD_DPLL_P1_MAX_25 10 ++#define MDFLD_DPLL_M_MIN_83 64 ++#define MDFLD_DPLL_M_MAX_83 64 ++#define MDFLD_DPLL_P1_MIN_83 2 ++#define MDFLD_DPLL_P1_MAX_83 2 ++#define MDFLD_DPLL_M_MIN_100 64 ++#define MDFLD_DPLL_M_MAX_100 64 ++#define MDFLD_DPLL_P1_MIN_100 2 ++#define MDFLD_DPLL_P1_MAX_100 2 ++#define MDFLD_DSIPLL_M_MIN_19 131 ++#define MDFLD_DSIPLL_M_MAX_19 175 ++#define MDFLD_DSIPLL_P1_MIN_19 3 ++#define MDFLD_DSIPLL_P1_MAX_19 8 ++#define MDFLD_DSIPLL_M_MIN_25 97 ++#define MDFLD_DSIPLL_M_MAX_25 140 ++#define MDFLD_DSIPLL_P1_MIN_25 3 ++#define MDFLD_DSIPLL_P1_MAX_25 9 ++#define MDFLD_DSIPLL_M_MIN_83 33 ++#define MDFLD_DSIPLL_M_MAX_83 92 ++#define MDFLD_DSIPLL_P1_MIN_83 2 ++#define MDFLD_DSIPLL_P1_MAX_83 3 ++#define MDFLD_DSIPLL_M_MIN_100 97 ++#define MDFLD_DSIPLL_M_MAX_100 140 ++#define MDFLD_DSIPLL_P1_MIN_100 3 ++#define MDFLD_DSIPLL_P1_MAX_100 9 ++ ++static const struct mrst_limit_t mdfld_limits[] = { ++ { /* MDFLD_LIMT_DPLL_19 */ ++ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, ++ .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19}, ++ .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19}, ++ }, ++ { /* MDFLD_LIMT_DPLL_25 */ ++ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, ++ .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25}, ++ .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25}, ++ }, ++ { /* MDFLD_LIMT_DPLL_83 */ ++ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, ++ .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83}, ++ .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83}, ++ }, ++ { /* MDFLD_LIMT_DPLL_100 */ ++ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, ++ .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100}, ++ .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100}, ++ }, ++ { /* MDFLD_LIMT_DSIPLL_19 */ ++ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, ++ .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19}, ++ .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19}, ++ }, ++ { /* MDFLD_LIMT_DSIPLL_25 */ ++ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, ++ .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25}, ++ .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25}, ++ }, ++ { /* MDFLD_LIMT_DSIPLL_83 */ ++ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, ++ .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83}, ++ .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83}, ++ }, ++ { /* MDFLD_LIMT_DSIPLL_100 */ ++ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, ++ .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100}, ++ .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100}, ++ }, ++}; ++ ++#define MDFLD_M_MIN 21 ++#define MDFLD_M_MAX 180 ++static const u32 mdfld_m_converts[] = { ++/* M configuration table from 9-bit LFSR table */ ++ 224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */ ++ 173, 342, 171, 85, 298, 149, 74, 37, 18, 265, /* 31 - 40 */ ++ 388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */ ++ 83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */ ++ 341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */ ++ 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */ ++ 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */ ++ 71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */ ++ 253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */ ++ 478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */ ++ 477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */ ++ 210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */ ++ 145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */ ++ 380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */ ++ 103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */ ++ 396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */ ++}; ++ ++static const struct mrst_limit_t *mdfld_limit(struct drm_crtc *crtc) ++{ ++ const struct mrst_limit_t *limit = NULL; ++ struct drm_device *dev = crtc->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI) ++ || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) { ++ if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) ++ limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19]; ++ else if (ksel == KSEL_BYPASS_25) ++ limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25]; ++ else if ((ksel == KSEL_BYPASS_83_100) && ++ (dev_priv->core_freq == 166)) ++ limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83]; ++ else if ((ksel == KSEL_BYPASS_83_100) && ++ (dev_priv->core_freq == 100 || ++ dev_priv->core_freq == 200)) ++ limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100]; ++ } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { ++ if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) ++ limit = &mdfld_limits[MDFLD_LIMT_DPLL_19]; ++ else if (ksel == KSEL_BYPASS_25) ++ limit = &mdfld_limits[MDFLD_LIMT_DPLL_25]; ++ else if ((ksel == KSEL_BYPASS_83_100) && ++ (dev_priv->core_freq == 166)) ++ limit = &mdfld_limits[MDFLD_LIMT_DPLL_83]; ++ else if ((ksel == KSEL_BYPASS_83_100) && ++ (dev_priv->core_freq == 100 || ++ dev_priv->core_freq == 200)) ++ limit = &mdfld_limits[MDFLD_LIMT_DPLL_100]; ++ } else { ++ limit = NULL; ++ dev_dbg(dev->dev, "mdfld_limit Wrong display type.\n"); ++ } ++ ++ return limit; ++} ++ ++/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ ++static void mdfld_clock(int refclk, struct mrst_clock_t *clock) ++{ ++ clock->dot = (refclk * clock->m) / clock->p1; ++} ++ ++/** ++ * Returns a set of divisors for the desired target clock with the given refclk, ++ * or FALSE. Divisor values are the actual divisors for ++ */ ++static bool ++mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk, ++ struct mrst_clock_t *best_clock) ++{ ++ struct mrst_clock_t clock; ++ const struct mrst_limit_t *limit = mdfld_limit(crtc); ++ int err = target; ++ ++ memset(best_clock, 0, sizeof(*best_clock)); ++ ++ for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { ++ for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; ++ clock.p1++) { ++ int this_err; ++ ++ mdfld_clock(refclk, &clock); ++ ++ this_err = abs(clock.dot - target); ++ if (this_err < err) { ++ *best_clock = clock; ++ err = this_err; ++ } ++ } ++ } ++ return err != target; ++} ++ ++static int mdfld_crtc_mode_set(struct drm_crtc *crtc, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode, ++ int x, int y, ++ struct drm_framebuffer *old_fb) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int pipe = psb_intel_crtc->pipe; ++ int fp_reg = MRST_FPA0; ++ int dpll_reg = MRST_DPLL_A; ++ int dspcntr_reg = DSPACNTR; ++ int pipeconf_reg = PIPEACONF; ++ int htot_reg = HTOTAL_A; ++ int hblank_reg = HBLANK_A; ++ int hsync_reg = HSYNC_A; ++ int vtot_reg = VTOTAL_A; ++ int vblank_reg = VBLANK_A; ++ int vsync_reg = VSYNC_A; ++ int dspsize_reg = DSPASIZE; ++ int dsppos_reg = DSPAPOS; ++ int pipesrc_reg = PIPEASRC; ++ u32 *pipeconf = &dev_priv->pipeconf[pipe]; ++ u32 *dspcntr = &dev_priv->dspcntr[pipe]; ++ int refclk = 0; ++ int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0, ++ clk_tmp = 0; ++ struct mrst_clock_t clock; ++ bool ok; ++ u32 dpll = 0, fp = 0; ++ bool is_mipi = false, is_mipi2 = false, is_hdmi = false; ++ struct drm_mode_config *mode_config = &dev->mode_config; ++ struct psb_intel_encoder *psb_intel_encoder = NULL; ++ uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; ++ struct drm_encoder *encoder; ++ struct drm_connector *connector; ++ int timeout = 0; ++ int ret; ++ ++ dev_dbg(dev->dev, "pipe = 0x%x\n", pipe); ++ ++#if 0 ++ if (pipe == 1) { ++ if (!gma_power_begin(dev, true)) ++ return 0; ++ android_hdmi_crtc_mode_set(crtc, mode, adjusted_mode, ++ x, y, old_fb); ++ goto mrst_crtc_mode_set_exit; ++ } ++#endif ++ ++ switch (pipe) { ++ case 0: ++ break; ++ case 1: ++ fp_reg = FPB0; ++ dpll_reg = DPLL_B; ++ dspcntr_reg = DSPBCNTR; ++ pipeconf_reg = PIPEBCONF; ++ htot_reg = HTOTAL_B; ++ hblank_reg = HBLANK_B; ++ hsync_reg = HSYNC_B; ++ vtot_reg = VTOTAL_B; ++ vblank_reg = VBLANK_B; ++ vsync_reg = VSYNC_B; ++ dspsize_reg = DSPBSIZE; ++ dsppos_reg = DSPBPOS; ++ pipesrc_reg = PIPEBSRC; ++ fp_reg = MDFLD_DPLL_DIV0; ++ dpll_reg = MDFLD_DPLL_B; ++ break; ++ case 2: ++ dpll_reg = MRST_DPLL_A; ++ dspcntr_reg = DSPCCNTR; ++ pipeconf_reg = PIPECCONF; ++ htot_reg = HTOTAL_C; ++ hblank_reg = HBLANK_C; ++ hsync_reg = HSYNC_C; ++ vtot_reg = VTOTAL_C; ++ vblank_reg = VBLANK_C; ++ vsync_reg = VSYNC_C; ++ dspsize_reg = DSPCSIZE; ++ dsppos_reg = DSPCPOS; ++ pipesrc_reg = PIPECSRC; ++ break; ++ default: ++ DRM_ERROR("Illegal Pipe Number.\n"); ++ return 0; ++ } ++ ++ ret = check_fb(crtc->fb); ++ if (ret) ++ return ret; ++ ++ dev_dbg(dev->dev, "adjusted_hdisplay = %d\n", ++ adjusted_mode->hdisplay); ++ dev_dbg(dev->dev, "adjusted_vdisplay = %d\n", ++ adjusted_mode->vdisplay); ++ dev_dbg(dev->dev, "adjusted_hsync_start = %d\n", ++ adjusted_mode->hsync_start); ++ dev_dbg(dev->dev, "adjusted_hsync_end = %d\n", ++ adjusted_mode->hsync_end); ++ dev_dbg(dev->dev, "adjusted_htotal = %d\n", ++ adjusted_mode->htotal); ++ dev_dbg(dev->dev, "adjusted_vsync_start = %d\n", ++ adjusted_mode->vsync_start); ++ dev_dbg(dev->dev, "adjusted_vsync_end = %d\n", ++ adjusted_mode->vsync_end); ++ dev_dbg(dev->dev, "adjusted_vtotal = %d\n", ++ adjusted_mode->vtotal); ++ dev_dbg(dev->dev, "adjusted_clock = %d\n", ++ adjusted_mode->clock); ++ dev_dbg(dev->dev, "hdisplay = %d\n", ++ mode->hdisplay); ++ dev_dbg(dev->dev, "vdisplay = %d\n", ++ mode->vdisplay); ++ ++ if (!gma_power_begin(dev, true)) ++ return 0; ++ ++ memcpy(&psb_intel_crtc->saved_mode, mode, ++ sizeof(struct drm_display_mode)); ++ memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, ++ sizeof(struct drm_display_mode)); ++ ++ list_for_each_entry(connector, &mode_config->connector_list, head) { ++ if (!connector) ++ continue; ++ ++ encoder = connector->encoder; ++ ++ if (!encoder) ++ continue; ++ ++ if (encoder->crtc != crtc) ++ continue; ++ ++ psb_intel_encoder = psb_intel_attached_encoder(connector); ++ ++ switch (psb_intel_encoder->type) { ++ case INTEL_OUTPUT_MIPI: ++ is_mipi = true; ++ break; ++ case INTEL_OUTPUT_MIPI2: ++ is_mipi2 = true; ++ break; ++ case INTEL_OUTPUT_HDMI: ++ is_hdmi = true; ++ break; ++ } ++ } ++ ++ /* Disable the VGA plane that we never use */ ++ REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); ++ ++ /* Disable the panel fitter if it was on our pipe */ ++ if (psb_intel_panel_fitter_pipe(dev) == pipe) ++ REG_WRITE(PFIT_CONTROL, 0); ++ ++ /* pipesrc and dspsize control the size that is scaled from, ++ * which should always be the user's requested size. ++ */ ++ if (pipe == 1) { ++ /* FIXME: To make HDMI display with 864x480 (TPO), 480x864 ++ * (PYR) or 480x854 (TMD), set the sprite width/height and ++ * souce image size registers with the adjusted mode for ++ * pipe B. ++ */ ++ ++ /* ++ * The defined sprite rectangle must always be completely ++ * contained within the displayable area of the screen image ++ * (frame buffer). ++ */ ++ REG_WRITE(dspsize_reg, ((min(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16) ++ | (min(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1)); ++ /* Set the CRTC with encoder mode. */ ++ REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) ++ | (mode->crtc_vdisplay - 1)); ++ } else { ++ REG_WRITE(dspsize_reg, ++ ((mode->crtc_vdisplay - 1) << 16) | ++ (mode->crtc_hdisplay - 1)); ++ REG_WRITE(pipesrc_reg, ++ ((mode->crtc_hdisplay - 1) << 16) | ++ (mode->crtc_vdisplay - 1)); ++ } ++ ++ REG_WRITE(dsppos_reg, 0); ++ ++ if (psb_intel_encoder) ++ drm_connector_property_get_value(connector, ++ dev->mode_config.scaling_mode_property, &scalingType); ++ ++ if (scalingType == DRM_MODE_SCALE_NO_SCALE) { ++ /* Medfield doesn't have register support for centering so we ++ * need to mess with the h/vblank and h/vsync start and ends ++ * to get centering ++ */ ++ int offsetX = 0, offsetY = 0; ++ ++ offsetX = (adjusted_mode->crtc_hdisplay - ++ mode->crtc_hdisplay) / 2; ++ offsetY = (adjusted_mode->crtc_vdisplay - ++ mode->crtc_vdisplay) / 2; ++ ++ REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) | ++ ((adjusted_mode->crtc_htotal - 1) << 16)); ++ REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) | ++ ((adjusted_mode->crtc_vtotal - 1) << 16)); ++ REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - ++ offsetX - 1) | ++ ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); ++ REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - ++ offsetX - 1) | ++ ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); ++ REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - ++ offsetY - 1) | ++ ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); ++ REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - ++ offsetY - 1) | ++ ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); ++ } else { ++ REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | ++ ((adjusted_mode->crtc_htotal - 1) << 16)); ++ REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ++ ((adjusted_mode->crtc_vtotal - 1) << 16)); ++ REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ++ ((adjusted_mode->crtc_hblank_end - 1) << 16)); ++ REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ++ ((adjusted_mode->crtc_hsync_end - 1) << 16)); ++ REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ++ ((adjusted_mode->crtc_vblank_end - 1) << 16)); ++ REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ++ ((adjusted_mode->crtc_vsync_end - 1) << 16)); ++ } ++ ++ /* Flush the plane changes */ ++ { ++ struct drm_crtc_helper_funcs *crtc_funcs = ++ crtc->helper_private; ++ crtc_funcs->mode_set_base(crtc, x, y, old_fb); ++ } ++ ++ /* setup pipeconf */ ++ *pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */ ++ ++ /* Set up the display plane register */ ++ *dspcntr = REG_READ(dspcntr_reg); ++ *dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS; ++ *dspcntr |= DISPLAY_PLANE_ENABLE; ++ ++ if (is_mipi2) ++ goto mrst_crtc_mode_set_exit; ++ clk = adjusted_mode->clock; ++ ++ if (is_hdmi) { ++ if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) { ++ refclk = 19200; ++ ++ if (is_mipi || is_mipi2) ++ clk_n = 1, clk_p2 = 8; ++ else if (is_hdmi) ++ clk_n = 1, clk_p2 = 10; ++ } else if (ksel == KSEL_BYPASS_25) { ++ refclk = 25000; ++ ++ if (is_mipi || is_mipi2) ++ clk_n = 1, clk_p2 = 8; ++ else if (is_hdmi) ++ clk_n = 1, clk_p2 = 10; ++ } else if ((ksel == KSEL_BYPASS_83_100) && ++ dev_priv->core_freq == 166) { ++ refclk = 83000; ++ ++ if (is_mipi || is_mipi2) ++ clk_n = 4, clk_p2 = 8; ++ else if (is_hdmi) ++ clk_n = 4, clk_p2 = 10; ++ } else if ((ksel == KSEL_BYPASS_83_100) && ++ (dev_priv->core_freq == 100 || ++ dev_priv->core_freq == 200)) { ++ refclk = 100000; ++ if (is_mipi || is_mipi2) ++ clk_n = 4, clk_p2 = 8; ++ else if (is_hdmi) ++ clk_n = 4, clk_p2 = 10; ++ } ++ ++ if (is_mipi) ++ clk_byte = dev_priv->bpp / 8; ++ else if (is_mipi2) ++ clk_byte = dev_priv->bpp2 / 8; ++ ++ clk_tmp = clk * clk_n * clk_p2 * clk_byte; ++ ++ dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d.\n", ++ clk, clk_n, clk_p2); ++ dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d.\n", ++ adjusted_mode->clock, clk_tmp); ++ ++ ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock); ++ ++ if (!ok) { ++ DRM_ERROR ++ ("mdfldFindBestPLL fail in mdfld_crtc_mode_set.\n"); ++ } else { ++ m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)]; ++ ++ dev_dbg(dev->dev, "dot clock = %d," ++ "m = %d, p1 = %d, m_conv = %d.\n", ++ clock.dot, clock.m, ++ clock.p1, m_conv); ++ } ++ ++ dpll = REG_READ(dpll_reg); ++ ++ if (dpll & DPLL_VCO_ENABLE) { ++ dpll &= ~DPLL_VCO_ENABLE; ++ REG_WRITE(dpll_reg, dpll); ++ REG_READ(dpll_reg); ++ ++ /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */ ++ /* FIXME_MDFLD PO - change 500 to 1 after PO */ ++ udelay(500); ++ ++ /* reset M1, N1 & P1 */ ++ REG_WRITE(fp_reg, 0); ++ dpll &= ~MDFLD_P1_MASK; ++ REG_WRITE(dpll_reg, dpll); ++ /* FIXME_MDFLD PO - change 500 to 1 after PO */ ++ udelay(500); ++ } ++ ++ /* When ungating power of DPLL, needs to wait 0.5us before ++ * enable the VCO */ ++ if (dpll & MDFLD_PWR_GATE_EN) { ++ dpll &= ~MDFLD_PWR_GATE_EN; ++ REG_WRITE(dpll_reg, dpll); ++ /* FIXME_MDFLD PO - change 500 to 1 after PO */ ++ udelay(500); ++ } ++ dpll = 0; ++ ++#if 0 /* FIXME revisit later */ ++ if (ksel == KSEL_CRYSTAL_19 || ksel == KSEL_BYPASS_19 || ++ ksel == KSEL_BYPASS_25) ++ dpll &= ~MDFLD_INPUT_REF_SEL; ++ else if (ksel == KSEL_BYPASS_83_100) ++ dpll |= MDFLD_INPUT_REF_SEL; ++#endif /* FIXME revisit later */ ++ ++ if (is_hdmi) ++ dpll |= MDFLD_VCO_SEL; ++ ++ fp = (clk_n / 2) << 16; ++ fp |= m_conv; ++ ++ /* compute bitmask from p1 value */ ++ dpll |= (1 << (clock.p1 - 2)) << 17; ++ ++#if 0 /* 1080p30 & 720p */ ++ dpll = 0x00050000; ++ fp = 0x000001be; ++#endif ++#if 0 /* 480p */ ++ dpll = 0x02010000; ++ fp = 0x000000d2; ++#endif ++ } else { ++#if 0 /*DBI_TPO_480x864*/ ++ dpll = 0x00020000; ++ fp = 0x00000156; ++#endif /* DBI_TPO_480x864 */ /* get from spec. */ ++ ++ dpll = 0x00800000; ++ fp = 0x000000c1; ++ } ++ ++ REG_WRITE(fp_reg, fp); ++ REG_WRITE(dpll_reg, dpll); ++ /* FIXME_MDFLD PO - change 500 to 1 after PO */ ++ udelay(500); ++ ++ dpll |= DPLL_VCO_ENABLE; ++ REG_WRITE(dpll_reg, dpll); ++ REG_READ(dpll_reg); ++ ++ /* wait for DSI PLL to lock */ ++ while (timeout < 20000 && ++ !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { ++ udelay(150); ++ timeout++; ++ } ++ ++ if (is_mipi) ++ goto mrst_crtc_mode_set_exit; ++ ++ dev_dbg(dev->dev, "is_mipi = 0x%x\n", is_mipi); ++ ++ REG_WRITE(pipeconf_reg, *pipeconf); ++ REG_READ(pipeconf_reg); ++ ++ /* Wait for for the pipe enable to take effect. */ ++ REG_WRITE(dspcntr_reg, *dspcntr); ++ psb_intel_wait_for_vblank(dev); ++ ++mrst_crtc_mode_set_exit: ++ ++ gma_power_end(dev); ++ ++ return 0; ++} ++ ++const struct drm_crtc_helper_funcs mdfld_helper_funcs = { ++ .dpms = mdfld_crtc_dpms, ++ .mode_fixup = psb_intel_crtc_mode_fixup, ++ .mode_set = mdfld_crtc_mode_set, ++ .mode_set_base = mdfld__intel_pipe_set_base, ++ .prepare = psb_intel_crtc_prepare, ++ .commit = psb_intel_crtc_commit, ++}; ++ +diff --git a/drivers/gpu/drm/gma500/mdfld_output.c b/drivers/gpu/drm/gma500/mdfld_output.c +new file mode 100644 +index 0000000..c95966b +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mdfld_output.c +@@ -0,0 +1,74 @@ ++/* ++ * Copyright (c) 2010 Intel Corporation ++ * ++ * 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, sublicensen ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Thomas Eaton ++ * Scott Rowe ++*/ ++ ++#include "mdfld_output.h" ++#include "mdfld_dsi_dpi.h" ++#include "mdfld_dsi_output.h" ++ ++#include "tc35876x-dsi-lvds.h" ++ ++int mdfld_get_panel_type(struct drm_device *dev, int pipe) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ return dev_priv->mdfld_panel_id; ++} ++ ++static void mdfld_init_panel(struct drm_device *dev, int mipi_pipe, ++ int p_type) ++{ ++ switch (p_type) { ++ case TPO_VID: ++ mdfld_dsi_output_init(dev, mipi_pipe, &mdfld_tpo_vid_funcs); ++ break; ++ case TC35876X: ++ tc35876x_init(dev); ++ mdfld_dsi_output_init(dev, mipi_pipe, &mdfld_tc35876x_funcs); ++ break; ++ case TMD_VID: ++ mdfld_dsi_output_init(dev, mipi_pipe, &mdfld_tmd_vid_funcs); ++ break; ++ case HDMI: ++/* if (dev_priv->mdfld_hdmi_present) ++ mdfld_hdmi_init(dev, &dev_priv->mode_dev); */ ++ break; ++ } ++} ++ ++ ++int mdfld_output_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ /* FIXME: hardcoded for now */ ++ dev_priv->mdfld_panel_id = TC35876X; ++ /* MIPI panel 1 */ ++ mdfld_init_panel(dev, 0, dev_priv->mdfld_panel_id); ++ /* HDMI panel */ ++ mdfld_init_panel(dev, 1, HDMI); ++ return 0; ++} ++ +diff --git a/drivers/gpu/drm/gma500/mdfld_output.h b/drivers/gpu/drm/gma500/mdfld_output.h +new file mode 100644 +index 0000000..ab2b27c +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mdfld_output.h +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (c) 2010 Intel Corporation ++ * ++ * 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, sublicensen ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Thomas Eaton ++ * Scott Rowe ++*/ ++ ++#ifndef MDFLD_OUTPUT_H ++#define MDFLD_OUTPUT_H ++ ++#include "psb_drv.h" ++ ++#define TPO_PANEL_WIDTH 84 ++#define TPO_PANEL_HEIGHT 46 ++#define TMD_PANEL_WIDTH 39 ++#define TMD_PANEL_HEIGHT 71 ++ ++struct mdfld_dsi_config; ++ ++enum panel_type { ++ TPO_VID, ++ TMD_VID, ++ HDMI, ++ TC35876X, ++}; ++ ++struct panel_info { ++ u32 width_mm; ++ u32 height_mm; ++ /* Other info */ ++}; ++ ++struct panel_funcs { ++ const struct drm_encoder_funcs *encoder_funcs; ++ const struct drm_encoder_helper_funcs *encoder_helper_funcs; ++ struct drm_display_mode * (*get_config_mode)(struct drm_device *); ++ int (*get_panel_info)(struct drm_device *, int, struct panel_info *); ++ int (*reset)(int pipe); ++ void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe); ++}; ++ ++int mdfld_output_init(struct drm_device *dev); ++ ++struct backlight_device *mdfld_get_backlight_device(void); ++int mdfld_set_brightness(struct backlight_device *bd); ++ ++int mdfld_get_panel_type(struct drm_device *dev, int pipe); ++ ++extern const struct drm_crtc_helper_funcs mdfld_helper_funcs; ++ ++extern const struct panel_funcs mdfld_tmd_vid_funcs; ++extern const struct panel_funcs mdfld_tpo_vid_funcs; ++ ++extern void mdfld_disable_crtc(struct drm_device *dev, int pipe); ++extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe); ++extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe); ++#endif +diff --git a/drivers/gpu/drm/gma500/mdfld_tmd_vid.c b/drivers/gpu/drm/gma500/mdfld_tmd_vid.c +new file mode 100644 +index 0000000..dc0c6c3 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mdfld_tmd_vid.c +@@ -0,0 +1,201 @@ ++/* ++ * Copyright © 2010 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Jim Liu ++ * Jackie Li ++ * Gideon Eaton ++ */ ++ ++#include "mdfld_dsi_dpi.h" ++#include "mdfld_dsi_pkg_sender.h" ++ ++static struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev) ++{ ++ struct drm_display_mode *mode; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD; ++ bool use_gct = false; /*Disable GCT for now*/ ++ ++ mode = kzalloc(sizeof(*mode), GFP_KERNEL); ++ if (!mode) ++ return NULL; ++ ++ if (use_gct) { ++ mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; ++ mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; ++ mode->hsync_start = mode->hdisplay + \ ++ ((ti->hsync_offset_hi << 8) | \ ++ ti->hsync_offset_lo); ++ mode->hsync_end = mode->hsync_start + \ ++ ((ti->hsync_pulse_width_hi << 8) | \ ++ ti->hsync_pulse_width_lo); ++ mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ ++ ti->hblank_lo); ++ mode->vsync_start = \ ++ mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ ++ ti->vsync_offset_lo); ++ mode->vsync_end = \ ++ mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ ++ ti->vsync_pulse_width_lo); ++ mode->vtotal = mode->vdisplay + \ ++ ((ti->vblank_hi << 8) | ti->vblank_lo); ++ mode->clock = ti->pixel_clock * 10; ++ ++ dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); ++ dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); ++ dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); ++ dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); ++ dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); ++ dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); ++ dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); ++ dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); ++ dev_dbg(dev->dev, "clock is %d\n", mode->clock); ++ } else { ++ mode->hdisplay = 480; ++ mode->vdisplay = 854; ++ mode->hsync_start = 487; ++ mode->hsync_end = 490; ++ mode->htotal = 499; ++ mode->vsync_start = 861; ++ mode->vsync_end = 865; ++ mode->vtotal = 873; ++ mode->clock = 33264; ++ } ++ ++ drm_mode_set_name(mode); ++ drm_mode_set_crtcinfo(mode, 0); ++ ++ mode->type |= DRM_MODE_TYPE_PREFERRED; ++ ++ return mode; ++} ++ ++static int tmd_vid_get_panel_info(struct drm_device *dev, ++ int pipe, ++ struct panel_info *pi) ++{ ++ if (!dev || !pi) ++ return -EINVAL; ++ ++ pi->width_mm = TMD_PANEL_WIDTH; ++ pi->height_mm = TMD_PANEL_HEIGHT; ++ ++ return 0; ++} ++ ++/* ************************************************************************* *\ ++ * FUNCTION: mdfld_init_TMD_MIPI ++ * ++ * DESCRIPTION: This function is called only by mrst_dsi_mode_set and ++ * restore_display_registers. since this function does not ++ * acquire the mutex, it is important that the calling function ++ * does! ++\* ************************************************************************* */ ++ ++/* FIXME: make the below data u8 instead of u32; note byte order! */ ++static u32 tmd_cmd_mcap_off[] = {0x000000b2}; ++static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef}; ++static u32 tmd_cmd_set_lane_num[] = {0x006360ef}; ++static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef}; ++static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef}; ++static u32 tmd_cmd_set_mode[] = {0x000000b3}; ++static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef}; ++static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df}; ++static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055}; ++static u32 tmd_cmd_set_video_mode[] = {0x00000153}; ++/*no auto_bl,need add in furture*/ ++static u32 tmd_cmd_enable_backlight[] = {0x00005ab4}; ++static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd}; ++ ++static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config, ++ int pipe) ++{ ++ struct mdfld_dsi_pkg_sender *sender ++ = mdfld_dsi_get_pkg_sender(dsi_config); ++ ++ DRM_INFO("Enter mdfld init TMD MIPI display.\n"); ++ ++ if (!sender) { ++ DRM_ERROR("Cannot get sender\n"); ++ return; ++ } ++ ++ if (dsi_config->dvr_ic_inited) ++ return; ++ ++ msleep(3); ++ ++ /* FIXME: make the below data u8 instead of u32; note byte order! */ ++ ++ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_mcap_off, ++ sizeof(tmd_cmd_mcap_off), false); ++ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_lane_switch, ++ sizeof(tmd_cmd_enable_lane_switch), false); ++ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_lane_num, ++ sizeof(tmd_cmd_set_lane_num), false); ++ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock0, ++ sizeof(tmd_cmd_pushing_clock0), false); ++ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock1, ++ sizeof(tmd_cmd_pushing_clock1), false); ++ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_mode, ++ sizeof(tmd_cmd_set_mode), false); ++ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_sync_pulse_mode, ++ sizeof(tmd_cmd_set_sync_pulse_mode), false); ++ mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_column, ++ sizeof(tmd_cmd_set_column), false); ++ mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_page, ++ sizeof(tmd_cmd_set_page), false); ++ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_video_mode, ++ sizeof(tmd_cmd_set_video_mode), false); ++ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_backlight, ++ sizeof(tmd_cmd_enable_backlight), false); ++ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_backlight_dimming, ++ sizeof(tmd_cmd_set_backlight_dimming), false); ++ ++ dsi_config->dvr_ic_inited = 1; ++} ++ ++/*TPO DPI encoder helper funcs*/ ++static const struct drm_encoder_helper_funcs ++ mdfld_tpo_dpi_encoder_helper_funcs = { ++ .dpms = mdfld_dsi_dpi_dpms, ++ .mode_fixup = mdfld_dsi_dpi_mode_fixup, ++ .prepare = mdfld_dsi_dpi_prepare, ++ .mode_set = mdfld_dsi_dpi_mode_set, ++ .commit = mdfld_dsi_dpi_commit, ++}; ++ ++/*TPO DPI encoder funcs*/ ++static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = { ++ .destroy = drm_encoder_cleanup, ++}; ++ ++const struct panel_funcs mdfld_tmd_vid_funcs = { ++ .encoder_funcs = &mdfld_tpo_dpi_encoder_funcs, ++ .encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs, ++ .get_config_mode = &tmd_vid_get_config_mode, ++ .get_panel_info = tmd_vid_get_panel_info, ++ .reset = mdfld_dsi_panel_reset, ++ .drv_ic_init = mdfld_dsi_tmd_drv_ic_init, ++}; +diff --git a/drivers/gpu/drm/gma500/mdfld_tpo_vid.c b/drivers/gpu/drm/gma500/mdfld_tpo_vid.c +new file mode 100644 +index 0000000..d8d4170 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mdfld_tpo_vid.c +@@ -0,0 +1,124 @@ ++/* ++ * Copyright © 2010 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * jim liu ++ * Jackie Li ++ */ ++ ++#include "mdfld_dsi_dpi.h" ++ ++static struct drm_display_mode *tpo_vid_get_config_mode(struct drm_device *dev) ++{ ++ struct drm_display_mode *mode; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD; ++ bool use_gct = false; ++ ++ mode = kzalloc(sizeof(*mode), GFP_KERNEL); ++ if (!mode) ++ return NULL; ++ ++ if (use_gct) { ++ mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; ++ mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; ++ mode->hsync_start = mode->hdisplay + ++ ((ti->hsync_offset_hi << 8) | ++ ti->hsync_offset_lo); ++ mode->hsync_end = mode->hsync_start + ++ ((ti->hsync_pulse_width_hi << 8) | ++ ti->hsync_pulse_width_lo); ++ mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | ++ ti->hblank_lo); ++ mode->vsync_start = ++ mode->vdisplay + ((ti->vsync_offset_hi << 8) | ++ ti->vsync_offset_lo); ++ mode->vsync_end = ++ mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | ++ ti->vsync_pulse_width_lo); ++ mode->vtotal = mode->vdisplay + ++ ((ti->vblank_hi << 8) | ti->vblank_lo); ++ mode->clock = ti->pixel_clock * 10; ++ ++ dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); ++ dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); ++ dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); ++ dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); ++ dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); ++ dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); ++ dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); ++ dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); ++ dev_dbg(dev->dev, "clock is %d\n", mode->clock); ++ } else { ++ mode->hdisplay = 864; ++ mode->vdisplay = 480; ++ mode->hsync_start = 873; ++ mode->hsync_end = 876; ++ mode->htotal = 887; ++ mode->vsync_start = 487; ++ mode->vsync_end = 490; ++ mode->vtotal = 499; ++ mode->clock = 33264; ++ } ++ ++ drm_mode_set_name(mode); ++ drm_mode_set_crtcinfo(mode, 0); ++ ++ mode->type |= DRM_MODE_TYPE_PREFERRED; ++ ++ return mode; ++} ++ ++static int tpo_vid_get_panel_info(struct drm_device *dev, ++ int pipe, ++ struct panel_info *pi) ++{ ++ if (!dev || !pi) ++ return -EINVAL; ++ ++ pi->width_mm = TPO_PANEL_WIDTH; ++ pi->height_mm = TPO_PANEL_HEIGHT; ++ ++ return 0; ++} ++ ++/*TPO DPI encoder helper funcs*/ ++static const struct drm_encoder_helper_funcs ++ mdfld_tpo_dpi_encoder_helper_funcs = { ++ .dpms = mdfld_dsi_dpi_dpms, ++ .mode_fixup = mdfld_dsi_dpi_mode_fixup, ++ .prepare = mdfld_dsi_dpi_prepare, ++ .mode_set = mdfld_dsi_dpi_mode_set, ++ .commit = mdfld_dsi_dpi_commit, ++}; ++ ++/*TPO DPI encoder funcs*/ ++static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = { ++ .destroy = drm_encoder_cleanup, ++}; ++ ++const struct panel_funcs mdfld_tpo_vid_funcs = { ++ .encoder_funcs = &mdfld_tpo_dpi_encoder_funcs, ++ .encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs, ++ .get_config_mode = &tpo_vid_get_config_mode, ++ .get_panel_info = tpo_vid_get_panel_info, ++}; +diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c +new file mode 100644 +index 0000000..5eee9ad +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mid_bios.c +@@ -0,0 +1,263 @@ ++/************************************************************************** ++ * Copyright (c) 2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++ ++/* TODO ++ * - Split functions by vbt type ++ * - Make them all take drm_device ++ * - Check ioremap failures ++ */ ++ ++#include ++#include ++#include "gma_drm.h" ++#include "psb_drv.h" ++#include "mid_bios.h" ++ ++static void mid_get_fuse_settings(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); ++ uint32_t fuse_value = 0; ++ uint32_t fuse_value_tmp = 0; ++ ++#define FB_REG06 0xD0810600 ++#define FB_MIPI_DISABLE (1 << 11) ++#define FB_REG09 0xD0810900 ++#define FB_REG09 0xD0810900 ++#define FB_SKU_MASK 0x7000 ++#define FB_SKU_SHIFT 12 ++#define FB_SKU_100 0 ++#define FB_SKU_100L 1 ++#define FB_SKU_83 2 ++ if (pci_root == NULL) { ++ WARN_ON(1); ++ return; ++ } ++ ++ ++ pci_write_config_dword(pci_root, 0xD0, FB_REG06); ++ pci_read_config_dword(pci_root, 0xD4, &fuse_value); ++ ++ /* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */ ++ if (IS_MRST(dev)) ++ dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE; ++ ++ DRM_INFO("internal display is %s\n", ++ dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display"); ++ ++ /* Prevent runtime suspend at start*/ ++ if (dev_priv->iLVDS_enable) { ++ dev_priv->is_lvds_on = true; ++ dev_priv->is_mipi_on = false; ++ } else { ++ dev_priv->is_mipi_on = true; ++ dev_priv->is_lvds_on = false; ++ } ++ ++ dev_priv->video_device_fuse = fuse_value; ++ ++ pci_write_config_dword(pci_root, 0xD0, FB_REG09); ++ pci_read_config_dword(pci_root, 0xD4, &fuse_value); ++ ++ dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value); ++ fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT; ++ ++ dev_priv->fuse_reg_value = fuse_value; ++ ++ switch (fuse_value_tmp) { ++ case FB_SKU_100: ++ dev_priv->core_freq = 200; ++ break; ++ case FB_SKU_100L: ++ dev_priv->core_freq = 100; ++ break; ++ case FB_SKU_83: ++ dev_priv->core_freq = 166; ++ break; ++ default: ++ dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n", ++ fuse_value_tmp); ++ dev_priv->core_freq = 0; ++ } ++ dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq); ++ pci_dev_put(pci_root); ++} ++ ++/* ++ * Get the revison ID, B0:D2:F0;0x08 ++ */ ++static void mid_get_pci_revID(struct drm_psb_private *dev_priv) ++{ ++ uint32_t platform_rev_id = 0; ++ struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); ++ ++ if (pci_gfx_root == NULL) { ++ WARN_ON(1); ++ return; ++ } ++ pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id); ++ dev_priv->platform_rev_id = (uint8_t) platform_rev_id; ++ pci_dev_put(pci_gfx_root); ++ dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n", ++ dev_priv->platform_rev_id); ++} ++ ++static void mid_get_vbt_data(struct drm_psb_private *dev_priv) ++{ ++ struct drm_device *dev = dev_priv->dev; ++ struct oaktrail_vbt *vbt = &dev_priv->vbt_data; ++ u32 addr; ++ u16 new_size; ++ u8 *vbt_virtual; ++ u8 bpi; ++ u8 number_desc = 0; ++ struct oaktrail_timing_info *dp_ti = &dev_priv->gct_data.DTD; ++ struct gct_r10_timing_info ti; ++ void *pGCT; ++ struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); ++ ++ /* Get the address of the platform config vbt, B0:D2:F0;0xFC */ ++ pci_read_config_dword(pci_gfx_root, 0xFC, &addr); ++ pci_dev_put(pci_gfx_root); ++ ++ dev_dbg(dev->dev, "drm platform config address is %x\n", addr); ++ ++ /* check for platform config address == 0. */ ++ /* this means fw doesn't support vbt */ ++ ++ if (addr == 0) { ++ vbt->size = 0; ++ return; ++ } ++ ++ /* get the virtual address of the vbt */ ++ vbt_virtual = ioremap(addr, sizeof(*vbt)); ++ if (vbt_virtual == NULL) { ++ vbt->size = 0; ++ return; ++ } ++ ++ memcpy(vbt, vbt_virtual, sizeof(*vbt)); ++ iounmap(vbt_virtual); /* Free virtual address space */ ++ ++ /* No matching signature don't process the data */ ++ if (memcmp(vbt->signature, "$GCT", 4)) { ++ vbt->size = 0; ++ return; ++ } ++ ++ dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision); ++ ++ switch (vbt->revision) { ++ case 0: ++ vbt->oaktrail_gct = ioremap(addr + sizeof(*vbt) - 4, ++ vbt->size - sizeof(*vbt) + 4); ++ pGCT = vbt->oaktrail_gct; ++ bpi = ((struct oaktrail_gct_v1 *)pGCT)->PD.BootPanelIndex; ++ dev_priv->gct_data.bpi = bpi; ++ dev_priv->gct_data.pt = ++ ((struct oaktrail_gct_v1 *)pGCT)->PD.PanelType; ++ memcpy(&dev_priv->gct_data.DTD, ++ &((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].DTD, ++ sizeof(struct oaktrail_timing_info)); ++ dev_priv->gct_data.Panel_Port_Control = ++ ((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control; ++ dev_priv->gct_data.Panel_MIPI_Display_Descriptor = ++ ((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; ++ break; ++ case 1: ++ vbt->oaktrail_gct = ioremap(addr + sizeof(*vbt) - 4, ++ vbt->size - sizeof(*vbt) + 4); ++ pGCT = vbt->oaktrail_gct; ++ bpi = ((struct oaktrail_gct_v2 *)pGCT)->PD.BootPanelIndex; ++ dev_priv->gct_data.bpi = bpi; ++ dev_priv->gct_data.pt = ++ ((struct oaktrail_gct_v2 *)pGCT)->PD.PanelType; ++ memcpy(&dev_priv->gct_data.DTD, ++ &((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].DTD, ++ sizeof(struct oaktrail_timing_info)); ++ dev_priv->gct_data.Panel_Port_Control = ++ ((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control; ++ dev_priv->gct_data.Panel_MIPI_Display_Descriptor = ++ ((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; ++ break; ++ case 0x10: ++ /*header definition changed from rev 01 (v2) to rev 10h. */ ++ /*so, some values have changed location*/ ++ new_size = vbt->checksum; /*checksum contains lo size byte*/ ++ /*LSB of oaktrail_gct contains hi size byte*/ ++ new_size |= ((0xff & (unsigned int)(long)vbt->oaktrail_gct)) << 8; ++ ++ vbt->checksum = vbt->size; /*size contains the checksum*/ ++ if (new_size > 0xff) ++ vbt->size = 0xff; /*restrict size to 255*/ ++ else ++ vbt->size = new_size; ++ ++ /* number of descriptors defined in the GCT */ ++ number_desc = ((0xff00 & (unsigned int)(long)vbt->oaktrail_gct)) >> 8; ++ bpi = ((0xff0000 & (unsigned int)(long)vbt->oaktrail_gct)) >> 16; ++ vbt->oaktrail_gct = ioremap(addr + GCT_R10_HEADER_SIZE, ++ GCT_R10_DISPLAY_DESC_SIZE * number_desc); ++ pGCT = vbt->oaktrail_gct; ++ pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE); ++ dev_priv->gct_data.bpi = bpi; /*save boot panel id*/ ++ ++ /*copy the GCT display timings into a temp structure*/ ++ memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info)); ++ ++ /*now copy the temp struct into the dev_priv->gct_data*/ ++ dp_ti->pixel_clock = ti.pixel_clock; ++ dp_ti->hactive_hi = ti.hactive_hi; ++ dp_ti->hactive_lo = ti.hactive_lo; ++ dp_ti->hblank_hi = ti.hblank_hi; ++ dp_ti->hblank_lo = ti.hblank_lo; ++ dp_ti->hsync_offset_hi = ti.hsync_offset_hi; ++ dp_ti->hsync_offset_lo = ti.hsync_offset_lo; ++ dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi; ++ dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo; ++ dp_ti->vactive_hi = ti.vactive_hi; ++ dp_ti->vactive_lo = ti.vactive_lo; ++ dp_ti->vblank_hi = ti.vblank_hi; ++ dp_ti->vblank_lo = ti.vblank_lo; ++ dp_ti->vsync_offset_hi = ti.vsync_offset_hi; ++ dp_ti->vsync_offset_lo = ti.vsync_offset_lo; ++ dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi; ++ dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo; ++ ++ /* Move the MIPI_Display_Descriptor data from GCT to dev priv */ ++ dev_priv->gct_data.Panel_MIPI_Display_Descriptor = ++ *((u8 *)pGCT + 0x0d); ++ dev_priv->gct_data.Panel_MIPI_Display_Descriptor |= ++ (*((u8 *)pGCT + 0x0e)) << 8; ++ break; ++ default: ++ dev_err(dev->dev, "Unknown revision of GCT!\n"); ++ vbt->size = 0; ++ } ++} ++ ++int mid_chip_setup(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ mid_get_fuse_settings(dev); ++ mid_get_vbt_data(dev_priv); ++ mid_get_pci_revID(dev_priv); ++ return 0; ++} +diff --git a/drivers/gpu/drm/gma500/mid_bios.h b/drivers/gpu/drm/gma500/mid_bios.h +new file mode 100644 +index 0000000..00e7d56 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mid_bios.h +@@ -0,0 +1,21 @@ ++/************************************************************************** ++ * Copyright (c) 2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++ ++extern int mid_chip_setup(struct drm_device *dev); ++ +diff --git a/drivers/gpu/drm/gma500/mmu.c b/drivers/gpu/drm/gma500/mmu.c +new file mode 100644 +index 0000000..49bac41 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/mmu.c +@@ -0,0 +1,849 @@ ++/************************************************************************** ++ * Copyright (c) 2007, Intel Corporation. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++#include ++#include "psb_drv.h" ++#include "psb_reg.h" ++ ++/* ++ * Code for the SGX MMU: ++ */ ++ ++/* ++ * clflush on one processor only: ++ * clflush should apparently flush the cache line on all processors in an ++ * SMP system. ++ */ ++ ++/* ++ * kmap atomic: ++ * The usage of the slots must be completely encapsulated within a spinlock, and ++ * no other functions that may be using the locks for other purposed may be ++ * called from within the locked region. ++ * Since the slots are per processor, this will guarantee that we are the only ++ * user. ++ */ ++ ++/* ++ * TODO: Inserting ptes from an interrupt handler: ++ * This may be desirable for some SGX functionality where the GPU can fault in ++ * needed pages. For that, we need to make an atomic insert_pages function, that ++ * may fail. ++ * If it fails, the caller need to insert the page using a workqueue function, ++ * but on average it should be fast. ++ */ ++ ++struct psb_mmu_driver { ++ /* protects driver- and pd structures. Always take in read mode ++ * before taking the page table spinlock. ++ */ ++ struct rw_semaphore sem; ++ ++ /* protects page tables, directory tables and pt tables. ++ * and pt structures. ++ */ ++ spinlock_t lock; ++ ++ atomic_t needs_tlbflush; ++ ++ uint8_t __iomem *register_map; ++ struct psb_mmu_pd *default_pd; ++ /*uint32_t bif_ctrl;*/ ++ int has_clflush; ++ int clflush_add; ++ unsigned long clflush_mask; ++ ++ struct drm_psb_private *dev_priv; ++}; ++ ++struct psb_mmu_pd; ++ ++struct psb_mmu_pt { ++ struct psb_mmu_pd *pd; ++ uint32_t index; ++ uint32_t count; ++ struct page *p; ++ uint32_t *v; ++}; ++ ++struct psb_mmu_pd { ++ struct psb_mmu_driver *driver; ++ int hw_context; ++ struct psb_mmu_pt **tables; ++ struct page *p; ++ struct page *dummy_pt; ++ struct page *dummy_page; ++ uint32_t pd_mask; ++ uint32_t invalid_pde; ++ uint32_t invalid_pte; ++}; ++ ++static inline uint32_t psb_mmu_pt_index(uint32_t offset) ++{ ++ return (offset >> PSB_PTE_SHIFT) & 0x3FF; ++} ++ ++static inline uint32_t psb_mmu_pd_index(uint32_t offset) ++{ ++ return offset >> PSB_PDE_SHIFT; ++} ++ ++static inline void psb_clflush(void *addr) ++{ ++ __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory"); ++} ++ ++static inline void psb_mmu_clflush(struct psb_mmu_driver *driver, ++ void *addr) ++{ ++ if (!driver->has_clflush) ++ return; ++ ++ mb(); ++ psb_clflush(addr); ++ mb(); ++} ++ ++static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page) ++{ ++ uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT; ++ uint32_t clflush_count = PAGE_SIZE / clflush_add; ++ int i; ++ uint8_t *clf; ++ ++ clf = kmap_atomic(page); ++ mb(); ++ for (i = 0; i < clflush_count; ++i) { ++ psb_clflush(clf); ++ clf += clflush_add; ++ } ++ mb(); ++ kunmap_atomic(clf); ++} ++ ++static void psb_pages_clflush(struct psb_mmu_driver *driver, ++ struct page *page[], unsigned long num_pages) ++{ ++ int i; ++ ++ if (!driver->has_clflush) ++ return ; ++ ++ for (i = 0; i < num_pages; i++) ++ psb_page_clflush(driver, *page++); ++} ++ ++static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver, ++ int force) ++{ ++ atomic_set(&driver->needs_tlbflush, 0); ++} ++ ++static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force) ++{ ++ down_write(&driver->sem); ++ psb_mmu_flush_pd_locked(driver, force); ++ up_write(&driver->sem); ++} ++ ++void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot) ++{ ++ if (rc_prot) ++ down_write(&driver->sem); ++ if (rc_prot) ++ up_write(&driver->sem); ++} ++ ++void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context) ++{ ++ /*ttm_tt_cache_flush(&pd->p, 1);*/ ++ psb_pages_clflush(pd->driver, &pd->p, 1); ++ down_write(&pd->driver->sem); ++ wmb(); ++ psb_mmu_flush_pd_locked(pd->driver, 1); ++ pd->hw_context = hw_context; ++ up_write(&pd->driver->sem); ++ ++} ++ ++static inline unsigned long psb_pd_addr_end(unsigned long addr, ++ unsigned long end) ++{ ++ ++ addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK; ++ return (addr < end) ? addr : end; ++} ++ ++static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type) ++{ ++ uint32_t mask = PSB_PTE_VALID; ++ ++ if (type & PSB_MMU_CACHED_MEMORY) ++ mask |= PSB_PTE_CACHED; ++ if (type & PSB_MMU_RO_MEMORY) ++ mask |= PSB_PTE_RO; ++ if (type & PSB_MMU_WO_MEMORY) ++ mask |= PSB_PTE_WO; ++ ++ return (pfn << PAGE_SHIFT) | mask; ++} ++ ++struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver, ++ int trap_pagefaults, int invalid_type) ++{ ++ struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL); ++ uint32_t *v; ++ int i; ++ ++ if (!pd) ++ return NULL; ++ ++ pd->p = alloc_page(GFP_DMA32); ++ if (!pd->p) ++ goto out_err1; ++ pd->dummy_pt = alloc_page(GFP_DMA32); ++ if (!pd->dummy_pt) ++ goto out_err2; ++ pd->dummy_page = alloc_page(GFP_DMA32); ++ if (!pd->dummy_page) ++ goto out_err3; ++ ++ if (!trap_pagefaults) { ++ pd->invalid_pde = ++ psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt), ++ invalid_type); ++ pd->invalid_pte = ++ psb_mmu_mask_pte(page_to_pfn(pd->dummy_page), ++ invalid_type); ++ } else { ++ pd->invalid_pde = 0; ++ pd->invalid_pte = 0; ++ } ++ ++ v = kmap(pd->dummy_pt); ++ for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) ++ v[i] = pd->invalid_pte; ++ ++ kunmap(pd->dummy_pt); ++ ++ v = kmap(pd->p); ++ for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) ++ v[i] = pd->invalid_pde; ++ ++ kunmap(pd->p); ++ ++ clear_page(kmap(pd->dummy_page)); ++ kunmap(pd->dummy_page); ++ ++ pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024); ++ if (!pd->tables) ++ goto out_err4; ++ ++ pd->hw_context = -1; ++ pd->pd_mask = PSB_PTE_VALID; ++ pd->driver = driver; ++ ++ return pd; ++ ++out_err4: ++ __free_page(pd->dummy_page); ++out_err3: ++ __free_page(pd->dummy_pt); ++out_err2: ++ __free_page(pd->p); ++out_err1: ++ kfree(pd); ++ return NULL; ++} ++ ++static void psb_mmu_free_pt(struct psb_mmu_pt *pt) ++{ ++ __free_page(pt->p); ++ kfree(pt); ++} ++ ++void psb_mmu_free_pagedir(struct psb_mmu_pd *pd) ++{ ++ struct psb_mmu_driver *driver = pd->driver; ++ struct psb_mmu_pt *pt; ++ int i; ++ ++ down_write(&driver->sem); ++ if (pd->hw_context != -1) ++ psb_mmu_flush_pd_locked(driver, 1); ++ ++ /* Should take the spinlock here, but we don't need to do that ++ since we have the semaphore in write mode. */ ++ ++ for (i = 0; i < 1024; ++i) { ++ pt = pd->tables[i]; ++ if (pt) ++ psb_mmu_free_pt(pt); ++ } ++ ++ vfree(pd->tables); ++ __free_page(pd->dummy_page); ++ __free_page(pd->dummy_pt); ++ __free_page(pd->p); ++ kfree(pd); ++ up_write(&driver->sem); ++} ++ ++static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd) ++{ ++ struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL); ++ void *v; ++ uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT; ++ uint32_t clflush_count = PAGE_SIZE / clflush_add; ++ spinlock_t *lock = &pd->driver->lock; ++ uint8_t *clf; ++ uint32_t *ptes; ++ int i; ++ ++ if (!pt) ++ return NULL; ++ ++ pt->p = alloc_page(GFP_DMA32); ++ if (!pt->p) { ++ kfree(pt); ++ return NULL; ++ } ++ ++ spin_lock(lock); ++ ++ v = kmap_atomic(pt->p); ++ clf = (uint8_t *) v; ++ ptes = (uint32_t *) v; ++ for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) ++ *ptes++ = pd->invalid_pte; ++ ++ ++ if (pd->driver->has_clflush && pd->hw_context != -1) { ++ mb(); ++ for (i = 0; i < clflush_count; ++i) { ++ psb_clflush(clf); ++ clf += clflush_add; ++ } ++ mb(); ++ } ++ ++ kunmap_atomic(v); ++ spin_unlock(lock); ++ ++ pt->count = 0; ++ pt->pd = pd; ++ pt->index = 0; ++ ++ return pt; ++} ++ ++static struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd, ++ unsigned long addr) ++{ ++ uint32_t index = psb_mmu_pd_index(addr); ++ struct psb_mmu_pt *pt; ++ uint32_t *v; ++ spinlock_t *lock = &pd->driver->lock; ++ ++ spin_lock(lock); ++ pt = pd->tables[index]; ++ while (!pt) { ++ spin_unlock(lock); ++ pt = psb_mmu_alloc_pt(pd); ++ if (!pt) ++ return NULL; ++ spin_lock(lock); ++ ++ if (pd->tables[index]) { ++ spin_unlock(lock); ++ psb_mmu_free_pt(pt); ++ spin_lock(lock); ++ pt = pd->tables[index]; ++ continue; ++ } ++ ++ v = kmap_atomic(pd->p); ++ pd->tables[index] = pt; ++ v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask; ++ pt->index = index; ++ kunmap_atomic((void *) v); ++ ++ if (pd->hw_context != -1) { ++ psb_mmu_clflush(pd->driver, (void *) &v[index]); ++ atomic_set(&pd->driver->needs_tlbflush, 1); ++ } ++ } ++ pt->v = kmap_atomic(pt->p); ++ return pt; ++} ++ ++static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd, ++ unsigned long addr) ++{ ++ uint32_t index = psb_mmu_pd_index(addr); ++ struct psb_mmu_pt *pt; ++ spinlock_t *lock = &pd->driver->lock; ++ ++ spin_lock(lock); ++ pt = pd->tables[index]; ++ if (!pt) { ++ spin_unlock(lock); ++ return NULL; ++ } ++ pt->v = kmap_atomic(pt->p); ++ return pt; ++} ++ ++static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt) ++{ ++ struct psb_mmu_pd *pd = pt->pd; ++ uint32_t *v; ++ ++ kunmap_atomic(pt->v); ++ if (pt->count == 0) { ++ v = kmap_atomic(pd->p); ++ v[pt->index] = pd->invalid_pde; ++ pd->tables[pt->index] = NULL; ++ ++ if (pd->hw_context != -1) { ++ psb_mmu_clflush(pd->driver, ++ (void *) &v[pt->index]); ++ atomic_set(&pd->driver->needs_tlbflush, 1); ++ } ++ kunmap_atomic(pt->v); ++ spin_unlock(&pd->driver->lock); ++ psb_mmu_free_pt(pt); ++ return; ++ } ++ spin_unlock(&pd->driver->lock); ++} ++ ++static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt, ++ unsigned long addr, uint32_t pte) ++{ ++ pt->v[psb_mmu_pt_index(addr)] = pte; ++} ++ ++static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt, ++ unsigned long addr) ++{ ++ pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte; ++} ++ ++ ++void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, ++ uint32_t mmu_offset, uint32_t gtt_start, ++ uint32_t gtt_pages) ++{ ++ uint32_t *v; ++ uint32_t start = psb_mmu_pd_index(mmu_offset); ++ struct psb_mmu_driver *driver = pd->driver; ++ int num_pages = gtt_pages; ++ ++ down_read(&driver->sem); ++ spin_lock(&driver->lock); ++ ++ v = kmap_atomic(pd->p); ++ v += start; ++ ++ while (gtt_pages--) { ++ *v++ = gtt_start | pd->pd_mask; ++ gtt_start += PAGE_SIZE; ++ } ++ ++ /*ttm_tt_cache_flush(&pd->p, num_pages);*/ ++ psb_pages_clflush(pd->driver, &pd->p, num_pages); ++ kunmap_atomic(v); ++ spin_unlock(&driver->lock); ++ ++ if (pd->hw_context != -1) ++ atomic_set(&pd->driver->needs_tlbflush, 1); ++ ++ up_read(&pd->driver->sem); ++ psb_mmu_flush_pd(pd->driver, 0); ++} ++ ++struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver) ++{ ++ struct psb_mmu_pd *pd; ++ ++ /* down_read(&driver->sem); */ ++ pd = driver->default_pd; ++ /* up_read(&driver->sem); */ ++ ++ return pd; ++} ++ ++void psb_mmu_driver_takedown(struct psb_mmu_driver *driver) ++{ ++ psb_mmu_free_pagedir(driver->default_pd); ++ kfree(driver); ++} ++ ++struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers, ++ int trap_pagefaults, ++ int invalid_type, ++ struct drm_psb_private *dev_priv) ++{ ++ struct psb_mmu_driver *driver; ++ ++ driver = kmalloc(sizeof(*driver), GFP_KERNEL); ++ ++ if (!driver) ++ return NULL; ++ driver->dev_priv = dev_priv; ++ ++ driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults, ++ invalid_type); ++ if (!driver->default_pd) ++ goto out_err1; ++ ++ spin_lock_init(&driver->lock); ++ init_rwsem(&driver->sem); ++ down_write(&driver->sem); ++ driver->register_map = registers; ++ atomic_set(&driver->needs_tlbflush, 1); ++ ++ driver->has_clflush = 0; ++ ++ if (boot_cpu_has(X86_FEATURE_CLFLSH)) { ++ uint32_t tfms, misc, cap0, cap4, clflush_size; ++ ++ /* ++ * clflush size is determined at kernel setup for x86_64 ++ * but not for i386. We have to do it here. ++ */ ++ ++ cpuid(0x00000001, &tfms, &misc, &cap0, &cap4); ++ clflush_size = ((misc >> 8) & 0xff) * 8; ++ driver->has_clflush = 1; ++ driver->clflush_add = ++ PAGE_SIZE * clflush_size / sizeof(uint32_t); ++ driver->clflush_mask = driver->clflush_add - 1; ++ driver->clflush_mask = ~driver->clflush_mask; ++ } ++ ++ up_write(&driver->sem); ++ return driver; ++ ++out_err1: ++ kfree(driver); ++ return NULL; ++} ++ ++static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd, ++ unsigned long address, uint32_t num_pages, ++ uint32_t desired_tile_stride, ++ uint32_t hw_tile_stride) ++{ ++ struct psb_mmu_pt *pt; ++ uint32_t rows = 1; ++ uint32_t i; ++ unsigned long addr; ++ unsigned long end; ++ unsigned long next; ++ unsigned long add; ++ unsigned long row_add; ++ unsigned long clflush_add = pd->driver->clflush_add; ++ unsigned long clflush_mask = pd->driver->clflush_mask; ++ ++ if (!pd->driver->has_clflush) { ++ /*ttm_tt_cache_flush(&pd->p, num_pages);*/ ++ psb_pages_clflush(pd->driver, &pd->p, num_pages); ++ return; ++ } ++ ++ if (hw_tile_stride) ++ rows = num_pages / desired_tile_stride; ++ else ++ desired_tile_stride = num_pages; ++ ++ add = desired_tile_stride << PAGE_SHIFT; ++ row_add = hw_tile_stride << PAGE_SHIFT; ++ mb(); ++ for (i = 0; i < rows; ++i) { ++ ++ addr = address; ++ end = addr + add; ++ ++ do { ++ next = psb_pd_addr_end(addr, end); ++ pt = psb_mmu_pt_map_lock(pd, addr); ++ if (!pt) ++ continue; ++ do { ++ psb_clflush(&pt->v ++ [psb_mmu_pt_index(addr)]); ++ } while (addr += ++ clflush_add, ++ (addr & clflush_mask) < next); ++ ++ psb_mmu_pt_unmap_unlock(pt); ++ } while (addr = next, next != end); ++ address += row_add; ++ } ++ mb(); ++} ++ ++void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd, ++ unsigned long address, uint32_t num_pages) ++{ ++ struct psb_mmu_pt *pt; ++ unsigned long addr; ++ unsigned long end; ++ unsigned long next; ++ unsigned long f_address = address; ++ ++ down_read(&pd->driver->sem); ++ ++ addr = address; ++ end = addr + (num_pages << PAGE_SHIFT); ++ ++ do { ++ next = psb_pd_addr_end(addr, end); ++ pt = psb_mmu_pt_alloc_map_lock(pd, addr); ++ if (!pt) ++ goto out; ++ do { ++ psb_mmu_invalidate_pte(pt, addr); ++ --pt->count; ++ } while (addr += PAGE_SIZE, addr < next); ++ psb_mmu_pt_unmap_unlock(pt); ++ ++ } while (addr = next, next != end); ++ ++out: ++ if (pd->hw_context != -1) ++ psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1); ++ ++ up_read(&pd->driver->sem); ++ ++ if (pd->hw_context != -1) ++ psb_mmu_flush(pd->driver, 0); ++ ++ return; ++} ++ ++void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address, ++ uint32_t num_pages, uint32_t desired_tile_stride, ++ uint32_t hw_tile_stride) ++{ ++ struct psb_mmu_pt *pt; ++ uint32_t rows = 1; ++ uint32_t i; ++ unsigned long addr; ++ unsigned long end; ++ unsigned long next; ++ unsigned long add; ++ unsigned long row_add; ++ unsigned long f_address = address; ++ ++ if (hw_tile_stride) ++ rows = num_pages / desired_tile_stride; ++ else ++ desired_tile_stride = num_pages; ++ ++ add = desired_tile_stride << PAGE_SHIFT; ++ row_add = hw_tile_stride << PAGE_SHIFT; ++ ++ /* down_read(&pd->driver->sem); */ ++ ++ /* Make sure we only need to flush this processor's cache */ ++ ++ for (i = 0; i < rows; ++i) { ++ ++ addr = address; ++ end = addr + add; ++ ++ do { ++ next = psb_pd_addr_end(addr, end); ++ pt = psb_mmu_pt_map_lock(pd, addr); ++ if (!pt) ++ continue; ++ do { ++ psb_mmu_invalidate_pte(pt, addr); ++ --pt->count; ++ ++ } while (addr += PAGE_SIZE, addr < next); ++ psb_mmu_pt_unmap_unlock(pt); ++ ++ } while (addr = next, next != end); ++ address += row_add; ++ } ++ if (pd->hw_context != -1) ++ psb_mmu_flush_ptes(pd, f_address, num_pages, ++ desired_tile_stride, hw_tile_stride); ++ ++ /* up_read(&pd->driver->sem); */ ++ ++ if (pd->hw_context != -1) ++ psb_mmu_flush(pd->driver, 0); ++} ++ ++int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn, ++ unsigned long address, uint32_t num_pages, ++ int type) ++{ ++ struct psb_mmu_pt *pt; ++ uint32_t pte; ++ unsigned long addr; ++ unsigned long end; ++ unsigned long next; ++ unsigned long f_address = address; ++ int ret = 0; ++ ++ down_read(&pd->driver->sem); ++ ++ addr = address; ++ end = addr + (num_pages << PAGE_SHIFT); ++ ++ do { ++ next = psb_pd_addr_end(addr, end); ++ pt = psb_mmu_pt_alloc_map_lock(pd, addr); ++ if (!pt) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ do { ++ pte = psb_mmu_mask_pte(start_pfn++, type); ++ psb_mmu_set_pte(pt, addr, pte); ++ pt->count++; ++ } while (addr += PAGE_SIZE, addr < next); ++ psb_mmu_pt_unmap_unlock(pt); ++ ++ } while (addr = next, next != end); ++ ++out: ++ if (pd->hw_context != -1) ++ psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1); ++ ++ up_read(&pd->driver->sem); ++ ++ if (pd->hw_context != -1) ++ psb_mmu_flush(pd->driver, 1); ++ ++ return ret; ++} ++ ++int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages, ++ unsigned long address, uint32_t num_pages, ++ uint32_t desired_tile_stride, ++ uint32_t hw_tile_stride, int type) ++{ ++ struct psb_mmu_pt *pt; ++ uint32_t rows = 1; ++ uint32_t i; ++ uint32_t pte; ++ unsigned long addr; ++ unsigned long end; ++ unsigned long next; ++ unsigned long add; ++ unsigned long row_add; ++ unsigned long f_address = address; ++ int ret = 0; ++ ++ if (hw_tile_stride) { ++ if (num_pages % desired_tile_stride != 0) ++ return -EINVAL; ++ rows = num_pages / desired_tile_stride; ++ } else { ++ desired_tile_stride = num_pages; ++ } ++ ++ add = desired_tile_stride << PAGE_SHIFT; ++ row_add = hw_tile_stride << PAGE_SHIFT; ++ ++ down_read(&pd->driver->sem); ++ ++ for (i = 0; i < rows; ++i) { ++ ++ addr = address; ++ end = addr + add; ++ ++ do { ++ next = psb_pd_addr_end(addr, end); ++ pt = psb_mmu_pt_alloc_map_lock(pd, addr); ++ if (!pt) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ do { ++ pte = ++ psb_mmu_mask_pte(page_to_pfn(*pages++), ++ type); ++ psb_mmu_set_pte(pt, addr, pte); ++ pt->count++; ++ } while (addr += PAGE_SIZE, addr < next); ++ psb_mmu_pt_unmap_unlock(pt); ++ ++ } while (addr = next, next != end); ++ ++ address += row_add; ++ } ++out: ++ if (pd->hw_context != -1) ++ psb_mmu_flush_ptes(pd, f_address, num_pages, ++ desired_tile_stride, hw_tile_stride); ++ ++ up_read(&pd->driver->sem); ++ ++ if (pd->hw_context != -1) ++ psb_mmu_flush(pd->driver, 1); ++ ++ return ret; ++} ++ ++int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual, ++ unsigned long *pfn) ++{ ++ int ret; ++ struct psb_mmu_pt *pt; ++ uint32_t tmp; ++ spinlock_t *lock = &pd->driver->lock; ++ ++ down_read(&pd->driver->sem); ++ pt = psb_mmu_pt_map_lock(pd, virtual); ++ if (!pt) { ++ uint32_t *v; ++ ++ spin_lock(lock); ++ v = kmap_atomic(pd->p); ++ tmp = v[psb_mmu_pd_index(virtual)]; ++ kunmap_atomic(v); ++ spin_unlock(lock); ++ ++ if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) || ++ !(pd->invalid_pte & PSB_PTE_VALID)) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ret = 0; ++ *pfn = pd->invalid_pte >> PAGE_SHIFT; ++ goto out; ++ } ++ tmp = pt->v[psb_mmu_pt_index(virtual)]; ++ if (!(tmp & PSB_PTE_VALID)) { ++ ret = -EINVAL; ++ } else { ++ ret = 0; ++ *pfn = tmp >> PAGE_SHIFT; ++ } ++ psb_mmu_pt_unmap_unlock(pt); ++out: ++ up_read(&pd->driver->sem); ++ return ret; ++} +diff --git a/drivers/gpu/drm/gma500/oaktrail.h b/drivers/gpu/drm/gma500/oaktrail.h +new file mode 100644 +index 0000000..2da1f36 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/oaktrail.h +@@ -0,0 +1,252 @@ ++/************************************************************************** ++ * Copyright (c) 2007-2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++ ++/* MID device specific descriptors */ ++ ++struct oaktrail_vbt { ++ s8 signature[4]; /*4 bytes,"$GCT" */ ++ u8 revision; ++ u8 size; ++ u8 checksum; ++ void *oaktrail_gct; ++} __packed; ++ ++struct oaktrail_timing_info { ++ u16 pixel_clock; ++ u8 hactive_lo; ++ u8 hblank_lo; ++ u8 hblank_hi:4; ++ u8 hactive_hi:4; ++ u8 vactive_lo; ++ u8 vblank_lo; ++ u8 vblank_hi:4; ++ u8 vactive_hi:4; ++ u8 hsync_offset_lo; ++ u8 hsync_pulse_width_lo; ++ u8 vsync_pulse_width_lo:4; ++ u8 vsync_offset_lo:4; ++ u8 vsync_pulse_width_hi:2; ++ u8 vsync_offset_hi:2; ++ u8 hsync_pulse_width_hi:2; ++ u8 hsync_offset_hi:2; ++ u8 width_mm_lo; ++ u8 height_mm_lo; ++ u8 height_mm_hi:4; ++ u8 width_mm_hi:4; ++ u8 hborder; ++ u8 vborder; ++ u8 unknown0:1; ++ u8 hsync_positive:1; ++ u8 vsync_positive:1; ++ u8 separate_sync:2; ++ u8 stereo:1; ++ u8 unknown6:1; ++ u8 interlaced:1; ++} __packed; ++ ++struct gct_r10_timing_info { ++ u16 pixel_clock; ++ u32 hactive_lo:8; ++ u32 hactive_hi:4; ++ u32 hblank_lo:8; ++ u32 hblank_hi:4; ++ u32 hsync_offset_lo:8; ++ u16 hsync_offset_hi:2; ++ u16 hsync_pulse_width_lo:8; ++ u16 hsync_pulse_width_hi:2; ++ u16 hsync_positive:1; ++ u16 rsvd_1:3; ++ u8 vactive_lo:8; ++ u16 vactive_hi:4; ++ u16 vblank_lo:8; ++ u16 vblank_hi:4; ++ u16 vsync_offset_lo:4; ++ u16 vsync_offset_hi:2; ++ u16 vsync_pulse_width_lo:4; ++ u16 vsync_pulse_width_hi:2; ++ u16 vsync_positive:1; ++ u16 rsvd_2:3; ++} __packed; ++ ++struct oaktrail_panel_descriptor_v1 { ++ u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */ ++ /* 0x61190 if MIPI */ ++ u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/ ++ u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/ ++ u32 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 dword */ ++ /* Register 0x61210 */ ++ struct oaktrail_timing_info DTD;/*18 bytes, Standard definition */ ++ u16 Panel_Backlight_Inverter_Descriptor;/* 16 bits, as follows */ ++ /* Bit 0, Frequency, 15 bits,0 - 32767Hz */ ++ /* Bit 15, Polarity, 1 bit, 0: Normal, 1: Inverted */ ++ u16 Panel_MIPI_Display_Descriptor; ++ /*16 bits, Defined as follows: */ ++ /* if MIPI, 0x0000 if LVDS */ ++ /* Bit 0, Type, 2 bits, */ ++ /* 0: Type-1, */ ++ /* 1: Type-2, */ ++ /* 2: Type-3, */ ++ /* 3: Type-4 */ ++ /* Bit 2, Pixel Format, 4 bits */ ++ /* Bit0: 16bpp (not supported in LNC), */ ++ /* Bit1: 18bpp loosely packed, */ ++ /* Bit2: 18bpp packed, */ ++ /* Bit3: 24bpp */ ++ /* Bit 6, Reserved, 2 bits, 00b */ ++ /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */ ++ /* Bit 14, Reserved, 2 bits, 00b */ ++} __packed; ++ ++struct oaktrail_panel_descriptor_v2 { ++ u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */ ++ /* 0x61190 if MIPI */ ++ u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/ ++ u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/ ++ u8 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 byte */ ++ /* Register 0x61210 */ ++ struct oaktrail_timing_info DTD;/*18 bytes, Standard definition */ ++ u16 Panel_Backlight_Inverter_Descriptor;/*16 bits, as follows*/ ++ /*Bit 0, Frequency, 16 bits, 0 - 32767Hz*/ ++ u8 Panel_Initial_Brightness;/* [7:0] 0 - 100% */ ++ /*Bit 7, Polarity, 1 bit,0: Normal, 1: Inverted*/ ++ u16 Panel_MIPI_Display_Descriptor; ++ /*16 bits, Defined as follows: */ ++ /* if MIPI, 0x0000 if LVDS */ ++ /* Bit 0, Type, 2 bits, */ ++ /* 0: Type-1, */ ++ /* 1: Type-2, */ ++ /* 2: Type-3, */ ++ /* 3: Type-4 */ ++ /* Bit 2, Pixel Format, 4 bits */ ++ /* Bit0: 16bpp (not supported in LNC), */ ++ /* Bit1: 18bpp loosely packed, */ ++ /* Bit2: 18bpp packed, */ ++ /* Bit3: 24bpp */ ++ /* Bit 6, Reserved, 2 bits, 00b */ ++ /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */ ++ /* Bit 14, Reserved, 2 bits, 00b */ ++} __packed; ++ ++union oaktrail_panel_rx { ++ struct { ++ u16 NumberOfLanes:2; /*Num of Lanes, 2 bits,0 = 1 lane,*/ ++ /* 1 = 2 lanes, 2 = 3 lanes, 3 = 4 lanes. */ ++ u16 MaxLaneFreq:3; /* 0: 100MHz, 1: 200MHz, 2: 300MHz, */ ++ /*3: 400MHz, 4: 500MHz, 5: 600MHz, 6: 700MHz, 7: 800MHz.*/ ++ u16 SupportedVideoTransferMode:2; /*0: Non-burst only */ ++ /* 1: Burst and non-burst */ ++ /* 2/3: Reserved */ ++ u16 HSClkBehavior:1; /*0: Continuous, 1: Non-continuous*/ ++ u16 DuoDisplaySupport:1; /*1 bit,0: No, 1: Yes*/ ++ u16 ECC_ChecksumCapabilities:1;/*1 bit,0: No, 1: Yes*/ ++ u16 BidirectionalCommunication:1;/*1 bit,0: No, 1: Yes */ ++ u16 Rsvd:5;/*5 bits,00000b */ ++ } panelrx; ++ u16 panel_receiver; ++} __packed; ++ ++struct oaktrail_gct_v1 { ++ union { /*8 bits,Defined as follows: */ ++ struct { ++ u8 PanelType:4; /*4 bits, Bit field for panels*/ ++ /* 0 - 3: 0 = LVDS, 1 = MIPI*/ ++ /*2 bits,Specifies which of the*/ ++ u8 BootPanelIndex:2; ++ /* 4 panels to use by default*/ ++ u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/ ++ /* the 4 MIPI DSI receivers to use*/ ++ } PD; ++ u8 PanelDescriptor; ++ }; ++ struct oaktrail_panel_descriptor_v1 panel[4];/*panel descrs,38 bytes each*/ ++ union oaktrail_panel_rx panelrx[4]; /* panel receivers*/ ++} __packed; ++ ++struct oaktrail_gct_v2 { ++ union { /*8 bits,Defined as follows: */ ++ struct { ++ u8 PanelType:4; /*4 bits, Bit field for panels*/ ++ /* 0 - 3: 0 = LVDS, 1 = MIPI*/ ++ /*2 bits,Specifies which of the*/ ++ u8 BootPanelIndex:2; ++ /* 4 panels to use by default*/ ++ u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/ ++ /* the 4 MIPI DSI receivers to use*/ ++ } PD; ++ u8 PanelDescriptor; ++ }; ++ struct oaktrail_panel_descriptor_v2 panel[4];/*panel descrs,38 bytes each*/ ++ union oaktrail_panel_rx panelrx[4]; /* panel receivers*/ ++} __packed; ++ ++struct oaktrail_gct_data { ++ u8 bpi; /* boot panel index, number of panel used during boot */ ++ u8 pt; /* panel type, 4 bit field, 0=lvds, 1=mipi */ ++ struct oaktrail_timing_info DTD; /* timing info for the selected panel */ ++ u32 Panel_Port_Control; ++ u32 PP_On_Sequencing;/*1 dword,Register 0x61208,*/ ++ u32 PP_Off_Sequencing;/*1 dword,Register 0x6120C,*/ ++ u32 PP_Cycle_Delay; ++ u16 Panel_Backlight_Inverter_Descriptor; ++ u16 Panel_MIPI_Display_Descriptor; ++} __packed; ++ ++#define MODE_SETTING_IN_CRTC 0x1 ++#define MODE_SETTING_IN_ENCODER 0x2 ++#define MODE_SETTING_ON_GOING 0x3 ++#define MODE_SETTING_IN_DSR 0x4 ++#define MODE_SETTING_ENCODER_DONE 0x8 ++ ++#define GCT_R10_HEADER_SIZE 16 ++#define GCT_R10_DISPLAY_DESC_SIZE 28 ++ ++/* ++ * Moorestown HDMI interfaces ++ */ ++ ++struct oaktrail_hdmi_dev { ++ struct pci_dev *dev; ++ void __iomem *regs; ++ unsigned int mmio, mmio_len; ++ int dpms_mode; ++ struct hdmi_i2c_dev *i2c_dev; ++ ++ /* register state */ ++ u32 saveDPLL_CTRL; ++ u32 saveDPLL_DIV_CTRL; ++ u32 saveDPLL_ADJUST; ++ u32 saveDPLL_UPDATE; ++ u32 saveDPLL_CLK_ENABLE; ++ u32 savePCH_HTOTAL_B; ++ u32 savePCH_HBLANK_B; ++ u32 savePCH_HSYNC_B; ++ u32 savePCH_VTOTAL_B; ++ u32 savePCH_VBLANK_B; ++ u32 savePCH_VSYNC_B; ++ u32 savePCH_PIPEBCONF; ++ u32 savePCH_PIPEBSRC; ++}; ++ ++extern void oaktrail_hdmi_setup(struct drm_device *dev); ++extern void oaktrail_hdmi_teardown(struct drm_device *dev); ++extern int oaktrail_hdmi_i2c_init(struct pci_dev *dev); ++extern void oaktrail_hdmi_i2c_exit(struct pci_dev *dev); ++extern void oaktrail_hdmi_save(struct drm_device *dev); ++extern void oaktrail_hdmi_restore(struct drm_device *dev); ++extern void oaktrail_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev); +diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c +new file mode 100644 +index 0000000..a39b0d0 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c +@@ -0,0 +1,592 @@ ++/* ++ * Copyright © 2009 Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++ ++#include ++#include "framebuffer.h" ++#include "psb_drv.h" ++#include "psb_intel_drv.h" ++#include "psb_intel_reg.h" ++#include "psb_intel_display.h" ++#include "power.h" ++ ++struct psb_intel_range_t { ++ int min, max; ++}; ++ ++struct oaktrail_limit_t { ++ struct psb_intel_range_t dot, m, p1; ++}; ++ ++struct oaktrail_clock_t { ++ /* derived values */ ++ int dot; ++ int m; ++ int p1; ++}; ++ ++#define MRST_LIMIT_LVDS_100L 0 ++#define MRST_LIMIT_LVDS_83 1 ++#define MRST_LIMIT_LVDS_100 2 ++ ++#define MRST_DOT_MIN 19750 ++#define MRST_DOT_MAX 120000 ++#define MRST_M_MIN_100L 20 ++#define MRST_M_MIN_100 10 ++#define MRST_M_MIN_83 12 ++#define MRST_M_MAX_100L 34 ++#define MRST_M_MAX_100 17 ++#define MRST_M_MAX_83 20 ++#define MRST_P1_MIN 2 ++#define MRST_P1_MAX_0 7 ++#define MRST_P1_MAX_1 8 ++ ++static const struct oaktrail_limit_t oaktrail_limits[] = { ++ { /* MRST_LIMIT_LVDS_100L */ ++ .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, ++ .m = {.min = MRST_M_MIN_100L, .max = MRST_M_MAX_100L}, ++ .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, ++ }, ++ { /* MRST_LIMIT_LVDS_83L */ ++ .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, ++ .m = {.min = MRST_M_MIN_83, .max = MRST_M_MAX_83}, ++ .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_0}, ++ }, ++ { /* MRST_LIMIT_LVDS_100 */ ++ .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, ++ .m = {.min = MRST_M_MIN_100, .max = MRST_M_MAX_100}, ++ .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, ++ }, ++}; ++ ++#define MRST_M_MIN 10 ++static const u32 oaktrail_m_converts[] = { ++ 0x2B, 0x15, 0x2A, 0x35, 0x1A, 0x0D, 0x26, 0x33, 0x19, 0x2C, ++ 0x36, 0x3B, 0x1D, 0x2E, 0x37, 0x1B, 0x2D, 0x16, 0x0B, 0x25, ++ 0x12, 0x09, 0x24, 0x32, 0x39, 0x1c, ++}; ++ ++static const struct oaktrail_limit_t *oaktrail_limit(struct drm_crtc *crtc) ++{ ++ const struct oaktrail_limit_t *limit = NULL; ++ struct drm_device *dev = crtc->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) ++ || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) { ++ switch (dev_priv->core_freq) { ++ case 100: ++ limit = &oaktrail_limits[MRST_LIMIT_LVDS_100L]; ++ break; ++ case 166: ++ limit = &oaktrail_limits[MRST_LIMIT_LVDS_83]; ++ break; ++ case 200: ++ limit = &oaktrail_limits[MRST_LIMIT_LVDS_100]; ++ break; ++ } ++ } else { ++ limit = NULL; ++ dev_err(dev->dev, "oaktrail_limit Wrong display type.\n"); ++ } ++ ++ return limit; ++} ++ ++/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ ++static void oaktrail_clock(int refclk, struct oaktrail_clock_t *clock) ++{ ++ clock->dot = (refclk * clock->m) / (14 * clock->p1); ++} ++ ++static void mrstPrintPll(char *prefix, struct oaktrail_clock_t *clock) ++{ ++ pr_debug("%s: dotclock = %d, m = %d, p1 = %d.\n", ++ prefix, clock->dot, clock->m, clock->p1); ++} ++ ++/** ++ * Returns a set of divisors for the desired target clock with the given refclk, ++ * or FALSE. Divisor values are the actual divisors for ++ */ ++static bool ++mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk, ++ struct oaktrail_clock_t *best_clock) ++{ ++ struct oaktrail_clock_t clock; ++ const struct oaktrail_limit_t *limit = oaktrail_limit(crtc); ++ int err = target; ++ ++ memset(best_clock, 0, sizeof(*best_clock)); ++ ++ for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { ++ for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; ++ clock.p1++) { ++ int this_err; ++ ++ oaktrail_clock(refclk, &clock); ++ ++ this_err = abs(clock.dot - target); ++ if (this_err < err) { ++ *best_clock = clock; ++ err = this_err; ++ } ++ } ++ } ++ dev_dbg(crtc->dev->dev, "mrstFindBestPLL err = %d.\n", err); ++ return err != target; ++} ++ ++/** ++ * Sets the power management mode of the pipe and plane. ++ * ++ * This code should probably grow support for turning the cursor off and back ++ * on appropriately at the same time as we're turning the pipe off/on. ++ */ ++static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; ++ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; ++ int dspbase_reg = (pipe == 0) ? MRST_DSPABASE : DSPBBASE; ++ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; ++ u32 temp; ++ ++ if (!gma_power_begin(dev, true)) ++ return; ++ ++ /* XXX: When our outputs are all unaware of DPMS modes other than off ++ * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. ++ */ ++ switch (mode) { ++ case DRM_MODE_DPMS_ON: ++ case DRM_MODE_DPMS_STANDBY: ++ case DRM_MODE_DPMS_SUSPEND: ++ /* Enable the DPLL */ ++ temp = REG_READ(dpll_reg); ++ if ((temp & DPLL_VCO_ENABLE) == 0) { ++ REG_WRITE(dpll_reg, temp); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ } ++ /* Enable the pipe */ ++ temp = REG_READ(pipeconf_reg); ++ if ((temp & PIPEACONF_ENABLE) == 0) ++ REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); ++ /* Enable the plane */ ++ temp = REG_READ(dspcntr_reg); ++ if ((temp & DISPLAY_PLANE_ENABLE) == 0) { ++ REG_WRITE(dspcntr_reg, ++ temp | DISPLAY_PLANE_ENABLE); ++ /* Flush the plane changes */ ++ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); ++ } ++ ++ psb_intel_crtc_load_lut(crtc); ++ ++ /* Give the overlay scaler a chance to enable ++ if it's on this pipe */ ++ /* psb_intel_crtc_dpms_video(crtc, true); TODO */ ++ break; ++ case DRM_MODE_DPMS_OFF: ++ /* Give the overlay scaler a chance to disable ++ * if it's on this pipe */ ++ /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ ++ ++ /* Disable the VGA plane that we never use */ ++ REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); ++ /* Disable display plane */ ++ temp = REG_READ(dspcntr_reg); ++ if ((temp & DISPLAY_PLANE_ENABLE) != 0) { ++ REG_WRITE(dspcntr_reg, ++ temp & ~DISPLAY_PLANE_ENABLE); ++ /* Flush the plane changes */ ++ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); ++ REG_READ(dspbase_reg); ++ } ++ ++ /* Next, disable display pipes */ ++ temp = REG_READ(pipeconf_reg); ++ if ((temp & PIPEACONF_ENABLE) != 0) { ++ REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); ++ REG_READ(pipeconf_reg); ++ } ++ /* Wait for for the pipe disable to take effect. */ ++ psb_intel_wait_for_vblank(dev); ++ ++ temp = REG_READ(dpll_reg); ++ if ((temp & DPLL_VCO_ENABLE) != 0) { ++ REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ } ++ ++ /* Wait for the clocks to turn off. */ ++ udelay(150); ++ break; ++ } ++ ++ /*Set FIFO Watermarks*/ ++ REG_WRITE(DSPARB, 0x3FFF); ++ REG_WRITE(DSPFW1, 0x3F88080A); ++ REG_WRITE(DSPFW2, 0x0b060808); ++ REG_WRITE(DSPFW3, 0x0); ++ REG_WRITE(DSPFW4, 0x08030404); ++ REG_WRITE(DSPFW5, 0x04040404); ++ REG_WRITE(DSPFW6, 0x78); ++ REG_WRITE(0x70400, REG_READ(0x70400) | 0x4000); ++ /* Must write Bit 14 of the Chicken Bit Register */ ++ ++ gma_power_end(dev); ++} ++ ++/** ++ * Return the pipe currently connected to the panel fitter, ++ * or -1 if the panel fitter is not present or not in use ++ */ ++static int oaktrail_panel_fitter_pipe(struct drm_device *dev) ++{ ++ u32 pfit_control; ++ ++ pfit_control = REG_READ(PFIT_CONTROL); ++ ++ /* See if the panel fitter is in use */ ++ if ((pfit_control & PFIT_ENABLE) == 0) ++ return -1; ++ return (pfit_control >> 29) & 3; ++} ++ ++static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode, ++ int x, int y, ++ struct drm_framebuffer *old_fb) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int pipe = psb_intel_crtc->pipe; ++ int fp_reg = (pipe == 0) ? MRST_FPA0 : FPB0; ++ int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; ++ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; ++ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; ++ int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; ++ int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; ++ int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; ++ int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; ++ int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; ++ int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; ++ int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; ++ int refclk = 0; ++ struct oaktrail_clock_t clock; ++ u32 dpll = 0, fp = 0, dspcntr, pipeconf; ++ bool ok, is_sdvo = false; ++ bool is_lvds = false; ++ bool is_mipi = false; ++ struct drm_mode_config *mode_config = &dev->mode_config; ++ struct psb_intel_encoder *psb_intel_encoder = NULL; ++ uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; ++ struct drm_connector *connector; ++ ++ if (!gma_power_begin(dev, true)) ++ return 0; ++ ++ memcpy(&psb_intel_crtc->saved_mode, ++ mode, ++ sizeof(struct drm_display_mode)); ++ memcpy(&psb_intel_crtc->saved_adjusted_mode, ++ adjusted_mode, ++ sizeof(struct drm_display_mode)); ++ ++ list_for_each_entry(connector, &mode_config->connector_list, head) { ++ if (!connector->encoder || connector->encoder->crtc != crtc) ++ continue; ++ ++ psb_intel_encoder = psb_intel_attached_encoder(connector); ++ ++ switch (psb_intel_encoder->type) { ++ case INTEL_OUTPUT_LVDS: ++ is_lvds = true; ++ break; ++ case INTEL_OUTPUT_SDVO: ++ is_sdvo = true; ++ break; ++ case INTEL_OUTPUT_MIPI: ++ is_mipi = true; ++ break; ++ } ++ } ++ ++ /* Disable the VGA plane that we never use */ ++ REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); ++ ++ /* Disable the panel fitter if it was on our pipe */ ++ if (oaktrail_panel_fitter_pipe(dev) == pipe) ++ REG_WRITE(PFIT_CONTROL, 0); ++ ++ REG_WRITE(pipesrc_reg, ++ ((mode->crtc_hdisplay - 1) << 16) | ++ (mode->crtc_vdisplay - 1)); ++ ++ if (psb_intel_encoder) ++ drm_connector_property_get_value(connector, ++ dev->mode_config.scaling_mode_property, &scalingType); ++ ++ if (scalingType == DRM_MODE_SCALE_NO_SCALE) { ++ /* Moorestown doesn't have register support for centering so ++ * we need to mess with the h/vblank and h/vsync start and ++ * ends to get centering */ ++ int offsetX = 0, offsetY = 0; ++ ++ offsetX = (adjusted_mode->crtc_hdisplay - ++ mode->crtc_hdisplay) / 2; ++ offsetY = (adjusted_mode->crtc_vdisplay - ++ mode->crtc_vdisplay) / 2; ++ ++ REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) | ++ ((adjusted_mode->crtc_htotal - 1) << 16)); ++ REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) | ++ ((adjusted_mode->crtc_vtotal - 1) << 16)); ++ REG_WRITE(hblank_reg, ++ (adjusted_mode->crtc_hblank_start - offsetX - 1) | ++ ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); ++ REG_WRITE(hsync_reg, ++ (adjusted_mode->crtc_hsync_start - offsetX - 1) | ++ ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); ++ REG_WRITE(vblank_reg, ++ (adjusted_mode->crtc_vblank_start - offsetY - 1) | ++ ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); ++ REG_WRITE(vsync_reg, ++ (adjusted_mode->crtc_vsync_start - offsetY - 1) | ++ ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); ++ } else { ++ REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | ++ ((adjusted_mode->crtc_htotal - 1) << 16)); ++ REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ++ ((adjusted_mode->crtc_vtotal - 1) << 16)); ++ REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ++ ((adjusted_mode->crtc_hblank_end - 1) << 16)); ++ REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ++ ((adjusted_mode->crtc_hsync_end - 1) << 16)); ++ REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ++ ((adjusted_mode->crtc_vblank_end - 1) << 16)); ++ REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ++ ((adjusted_mode->crtc_vsync_end - 1) << 16)); ++ } ++ ++ /* Flush the plane changes */ ++ { ++ struct drm_crtc_helper_funcs *crtc_funcs = ++ crtc->helper_private; ++ crtc_funcs->mode_set_base(crtc, x, y, old_fb); ++ } ++ ++ /* setup pipeconf */ ++ pipeconf = REG_READ(pipeconf_reg); ++ ++ /* Set up the display plane register */ ++ dspcntr = REG_READ(dspcntr_reg); ++ dspcntr |= DISPPLANE_GAMMA_ENABLE; ++ ++ if (pipe == 0) ++ dspcntr |= DISPPLANE_SEL_PIPE_A; ++ else ++ dspcntr |= DISPPLANE_SEL_PIPE_B; ++ ++ if (is_mipi) ++ goto oaktrail_crtc_mode_set_exit; ++ ++ refclk = dev_priv->core_freq * 1000; ++ ++ dpll = 0; /*BIT16 = 0 for 100MHz reference */ ++ ++ ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock); ++ ++ if (!ok) { ++ dev_dbg(dev->dev, "mrstFindBestPLL fail in oaktrail_crtc_mode_set.\n"); ++ } else { ++ dev_dbg(dev->dev, "oaktrail_crtc_mode_set pixel clock = %d," ++ "m = %x, p1 = %x.\n", clock.dot, clock.m, ++ clock.p1); ++ } ++ ++ fp = oaktrail_m_converts[(clock.m - MRST_M_MIN)] << 8; ++ ++ dpll |= DPLL_VGA_MODE_DIS; ++ ++ ++ dpll |= DPLL_VCO_ENABLE; ++ ++ if (is_lvds) ++ dpll |= DPLLA_MODE_LVDS; ++ else ++ dpll |= DPLLB_MODE_DAC_SERIAL; ++ ++ if (is_sdvo) { ++ int sdvo_pixel_multiply = ++ adjusted_mode->clock / mode->clock; ++ ++ dpll |= DPLL_DVO_HIGH_SPEED; ++ dpll |= ++ (sdvo_pixel_multiply - ++ 1) << SDVO_MULTIPLIER_SHIFT_HIRES; ++ } ++ ++ ++ /* compute bitmask from p1 value */ ++ dpll |= (1 << (clock.p1 - 2)) << 17; ++ ++ dpll |= DPLL_VCO_ENABLE; ++ ++ mrstPrintPll("chosen", &clock); ++ ++ if (dpll & DPLL_VCO_ENABLE) { ++ REG_WRITE(fp_reg, fp); ++ REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ /* Check the DPLLA lock bit PIPEACONF[29] */ ++ udelay(150); ++ } ++ ++ REG_WRITE(fp_reg, fp); ++ REG_WRITE(dpll_reg, dpll); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ ++ /* write it again -- the BIOS does, after all */ ++ REG_WRITE(dpll_reg, dpll); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ ++ REG_WRITE(pipeconf_reg, pipeconf); ++ REG_READ(pipeconf_reg); ++ psb_intel_wait_for_vblank(dev); ++ ++ REG_WRITE(dspcntr_reg, dspcntr); ++ psb_intel_wait_for_vblank(dev); ++ ++oaktrail_crtc_mode_set_exit: ++ gma_power_end(dev); ++ return 0; ++} ++ ++static bool oaktrail_crtc_mode_fixup(struct drm_crtc *crtc, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ return true; ++} ++ ++static int oaktrail_pipe_set_base(struct drm_crtc *crtc, ++ int x, int y, struct drm_framebuffer *old_fb) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); ++ int pipe = psb_intel_crtc->pipe; ++ unsigned long start, offset; ++ ++ int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE); ++ int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); ++ int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; ++ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; ++ u32 dspcntr; ++ int ret = 0; ++ ++ /* no fb bound */ ++ if (!crtc->fb) { ++ dev_dbg(dev->dev, "No FB bound\n"); ++ return 0; ++ } ++ ++ if (!gma_power_begin(dev, true)) ++ return 0; ++ ++ start = psbfb->gtt->offset; ++ offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); ++ ++ REG_WRITE(dspstride, crtc->fb->pitches[0]); ++ ++ dspcntr = REG_READ(dspcntr_reg); ++ dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; ++ ++ switch (crtc->fb->bits_per_pixel) { ++ case 8: ++ dspcntr |= DISPPLANE_8BPP; ++ break; ++ case 16: ++ if (crtc->fb->depth == 15) ++ dspcntr |= DISPPLANE_15_16BPP; ++ else ++ dspcntr |= DISPPLANE_16BPP; ++ break; ++ case 24: ++ case 32: ++ dspcntr |= DISPPLANE_32BPP_NO_ALPHA; ++ break; ++ default: ++ dev_err(dev->dev, "Unknown color depth\n"); ++ ret = -EINVAL; ++ goto pipe_set_base_exit; ++ } ++ REG_WRITE(dspcntr_reg, dspcntr); ++ ++ REG_WRITE(dspbase, offset); ++ REG_READ(dspbase); ++ REG_WRITE(dspsurf, start); ++ REG_READ(dspsurf); ++ ++pipe_set_base_exit: ++ gma_power_end(dev); ++ return ret; ++} ++ ++static void oaktrail_crtc_prepare(struct drm_crtc *crtc) ++{ ++ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; ++ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); ++} ++ ++static void oaktrail_crtc_commit(struct drm_crtc *crtc) ++{ ++ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; ++ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); ++} ++ ++const struct drm_crtc_helper_funcs oaktrail_helper_funcs = { ++ .dpms = oaktrail_crtc_dpms, ++ .mode_fixup = oaktrail_crtc_mode_fixup, ++ .mode_set = oaktrail_crtc_mode_set, ++ .mode_set_base = oaktrail_pipe_set_base, ++ .prepare = oaktrail_crtc_prepare, ++ .commit = oaktrail_crtc_commit, ++}; ++ +diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c +new file mode 100644 +index 0000000..41d1924 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/oaktrail_device.c +@@ -0,0 +1,509 @@ ++/************************************************************************** ++ * Copyright (c) 2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include "gma_drm.h" ++#include "psb_drv.h" ++#include "psb_reg.h" ++#include "psb_intel_reg.h" ++#include ++#include ++#include "mid_bios.h" ++#include "intel_bios.h" ++ ++static int oaktrail_output_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ if (dev_priv->iLVDS_enable) ++ oaktrail_lvds_init(dev, &dev_priv->mode_dev); ++ else ++ dev_err(dev->dev, "DSI is not supported\n"); ++ if (dev_priv->hdmi_priv) ++ oaktrail_hdmi_init(dev, &dev_priv->mode_dev); ++ return 0; ++} ++ ++/* ++ * Provide the low level interfaces for the Moorestown backlight ++ */ ++ ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ ++#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF ++#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ ++#define BLC_PWM_FREQ_CALC_CONSTANT 32 ++#define MHz 1000000 ++#define BLC_ADJUSTMENT_MAX 100 ++ ++static struct backlight_device *oaktrail_backlight_device; ++static int oaktrail_brightness; ++ ++static int oaktrail_set_brightness(struct backlight_device *bd) ++{ ++ struct drm_device *dev = bl_get_data(oaktrail_backlight_device); ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int level = bd->props.brightness; ++ u32 blc_pwm_ctl; ++ u32 max_pwm_blc; ++ ++ /* Percentage 1-100% being valid */ ++ if (level < 1) ++ level = 1; ++ ++ if (gma_power_begin(dev, 0)) { ++ /* Calculate and set the brightness value */ ++ max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16; ++ blc_pwm_ctl = level * max_pwm_blc / 100; ++ ++ /* Adjust the backlight level with the percent in ++ * dev_priv->blc_adj1; ++ */ ++ blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1; ++ blc_pwm_ctl = blc_pwm_ctl / 100; ++ ++ /* Adjust the backlight level with the percent in ++ * dev_priv->blc_adj2; ++ */ ++ blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2; ++ blc_pwm_ctl = blc_pwm_ctl / 100; ++ ++ /* force PWM bit on */ ++ REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2))); ++ REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl); ++ gma_power_end(dev); ++ } ++ oaktrail_brightness = level; ++ return 0; ++} ++ ++static int oaktrail_get_brightness(struct backlight_device *bd) ++{ ++ /* return locally cached var instead of HW read (due to DPST etc.) */ ++ /* FIXME: ideally return actual value in case firmware fiddled with ++ it */ ++ return oaktrail_brightness; ++} ++ ++static int device_backlight_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ unsigned long core_clock; ++ u16 bl_max_freq; ++ uint32_t value; ++ uint32_t blc_pwm_precision_factor; ++ ++ dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX; ++ dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX; ++ bl_max_freq = 256; ++ /* this needs to be set elsewhere */ ++ blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR; ++ ++ core_clock = dev_priv->core_freq; ++ ++ value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; ++ value *= blc_pwm_precision_factor; ++ value /= bl_max_freq; ++ value /= blc_pwm_precision_factor; ++ ++ if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ) ++ return -ERANGE; ++ ++ if (gma_power_begin(dev, false)) { ++ REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2))); ++ REG_WRITE(BLC_PWM_CTL, value | (value << 16)); ++ gma_power_end(dev); ++ } ++ return 0; ++} ++ ++static const struct backlight_ops oaktrail_ops = { ++ .get_brightness = oaktrail_get_brightness, ++ .update_status = oaktrail_set_brightness, ++}; ++ ++static int oaktrail_backlight_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int ret; ++ struct backlight_properties props; ++ ++ memset(&props, 0, sizeof(struct backlight_properties)); ++ props.max_brightness = 100; ++ props.type = BACKLIGHT_PLATFORM; ++ ++ oaktrail_backlight_device = backlight_device_register("oaktrail-bl", ++ NULL, (void *)dev, &oaktrail_ops, &props); ++ ++ if (IS_ERR(oaktrail_backlight_device)) ++ return PTR_ERR(oaktrail_backlight_device); ++ ++ ret = device_backlight_init(dev); ++ if (ret < 0) { ++ backlight_device_unregister(oaktrail_backlight_device); ++ return ret; ++ } ++ oaktrail_backlight_device->props.brightness = 100; ++ oaktrail_backlight_device->props.max_brightness = 100; ++ backlight_update_status(oaktrail_backlight_device); ++ dev_priv->backlight_device = oaktrail_backlight_device; ++ return 0; ++} ++ ++#endif ++ ++/* ++ * Provide the Moorestown specific chip logic and low level methods ++ * for power management ++ */ ++ ++/** ++ * oaktrail_save_display_registers - save registers lost on suspend ++ * @dev: our DRM device ++ * ++ * Save the state we need in order to be able to restore the interface ++ * upon resume from suspend ++ */ ++static int oaktrail_save_display_registers(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_save_area *regs = &dev_priv->regs; ++ int i; ++ u32 pp_stat; ++ ++ /* Display arbitration control + watermarks */ ++ regs->psb.saveDSPARB = PSB_RVDC32(DSPARB); ++ regs->psb.saveDSPFW1 = PSB_RVDC32(DSPFW1); ++ regs->psb.saveDSPFW2 = PSB_RVDC32(DSPFW2); ++ regs->psb.saveDSPFW3 = PSB_RVDC32(DSPFW3); ++ regs->psb.saveDSPFW4 = PSB_RVDC32(DSPFW4); ++ regs->psb.saveDSPFW5 = PSB_RVDC32(DSPFW5); ++ regs->psb.saveDSPFW6 = PSB_RVDC32(DSPFW6); ++ regs->psb.saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); ++ ++ /* Pipe & plane A info */ ++ regs->psb.savePIPEACONF = PSB_RVDC32(PIPEACONF); ++ regs->psb.savePIPEASRC = PSB_RVDC32(PIPEASRC); ++ regs->psb.saveFPA0 = PSB_RVDC32(MRST_FPA0); ++ regs->psb.saveFPA1 = PSB_RVDC32(MRST_FPA1); ++ regs->psb.saveDPLL_A = PSB_RVDC32(MRST_DPLL_A); ++ regs->psb.saveHTOTAL_A = PSB_RVDC32(HTOTAL_A); ++ regs->psb.saveHBLANK_A = PSB_RVDC32(HBLANK_A); ++ regs->psb.saveHSYNC_A = PSB_RVDC32(HSYNC_A); ++ regs->psb.saveVTOTAL_A = PSB_RVDC32(VTOTAL_A); ++ regs->psb.saveVBLANK_A = PSB_RVDC32(VBLANK_A); ++ regs->psb.saveVSYNC_A = PSB_RVDC32(VSYNC_A); ++ regs->psb.saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A); ++ regs->psb.saveDSPACNTR = PSB_RVDC32(DSPACNTR); ++ regs->psb.saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE); ++ regs->psb.saveDSPAADDR = PSB_RVDC32(DSPABASE); ++ regs->psb.saveDSPASURF = PSB_RVDC32(DSPASURF); ++ regs->psb.saveDSPALINOFF = PSB_RVDC32(DSPALINOFF); ++ regs->psb.saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF); ++ ++ /* Save cursor regs */ ++ regs->psb.saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR); ++ regs->psb.saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE); ++ regs->psb.saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS); ++ ++ /* Save palette (gamma) */ ++ for (i = 0; i < 256; i++) ++ regs->psb.save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2)); ++ ++ if (dev_priv->hdmi_priv) ++ oaktrail_hdmi_save(dev); ++ ++ /* Save performance state */ ++ regs->psb.savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE); ++ ++ /* LVDS state */ ++ regs->psb.savePP_CONTROL = PSB_RVDC32(PP_CONTROL); ++ regs->psb.savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS); ++ regs->psb.savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS); ++ regs->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL); ++ regs->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2); ++ regs->psb.saveLVDS = PSB_RVDC32(LVDS); ++ regs->psb.savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL); ++ regs->psb.savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON); ++ regs->psb.savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF); ++ regs->psb.savePP_DIVISOR = PSB_RVDC32(PP_CYCLE); ++ ++ /* HW overlay */ ++ regs->psb.saveOV_OVADD = PSB_RVDC32(OV_OVADD); ++ regs->psb.saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0); ++ regs->psb.saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1); ++ regs->psb.saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2); ++ regs->psb.saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3); ++ regs->psb.saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4); ++ regs->psb.saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5); ++ ++ /* DPST registers */ ++ regs->psb.saveHISTOGRAM_INT_CONTROL_REG = ++ PSB_RVDC32(HISTOGRAM_INT_CONTROL); ++ regs->psb.saveHISTOGRAM_LOGIC_CONTROL_REG = ++ PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); ++ regs->psb.savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC); ++ ++ if (dev_priv->iLVDS_enable) { ++ /* Shut down the panel */ ++ PSB_WVDC32(0, PP_CONTROL); ++ ++ do { ++ pp_stat = PSB_RVDC32(PP_STATUS); ++ } while (pp_stat & 0x80000000); ++ ++ /* Turn off the plane */ ++ PSB_WVDC32(0x58000000, DSPACNTR); ++ /* Trigger the plane disable */ ++ PSB_WVDC32(0, DSPASURF); ++ ++ /* Wait ~4 ticks */ ++ msleep(4); ++ ++ /* Turn off pipe */ ++ PSB_WVDC32(0x0, PIPEACONF); ++ /* Wait ~8 ticks */ ++ msleep(8); ++ ++ /* Turn off PLLs */ ++ PSB_WVDC32(0, MRST_DPLL_A); ++ } ++ return 0; ++} ++ ++/** ++ * oaktrail_restore_display_registers - restore lost register state ++ * @dev: our DRM device ++ * ++ * Restore register state that was lost during suspend and resume. ++ */ ++static int oaktrail_restore_display_registers(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_save_area *regs = &dev_priv->regs; ++ u32 pp_stat; ++ int i; ++ ++ /* Display arbitration + watermarks */ ++ PSB_WVDC32(regs->psb.saveDSPARB, DSPARB); ++ PSB_WVDC32(regs->psb.saveDSPFW1, DSPFW1); ++ PSB_WVDC32(regs->psb.saveDSPFW2, DSPFW2); ++ PSB_WVDC32(regs->psb.saveDSPFW3, DSPFW3); ++ PSB_WVDC32(regs->psb.saveDSPFW4, DSPFW4); ++ PSB_WVDC32(regs->psb.saveDSPFW5, DSPFW5); ++ PSB_WVDC32(regs->psb.saveDSPFW6, DSPFW6); ++ PSB_WVDC32(regs->psb.saveCHICKENBIT, DSPCHICKENBIT); ++ ++ /* Make sure VGA plane is off. it initializes to on after reset!*/ ++ PSB_WVDC32(0x80000000, VGACNTRL); ++ ++ /* set the plls */ ++ PSB_WVDC32(regs->psb.saveFPA0, MRST_FPA0); ++ PSB_WVDC32(regs->psb.saveFPA1, MRST_FPA1); ++ ++ /* Actually enable it */ ++ PSB_WVDC32(regs->psb.saveDPLL_A, MRST_DPLL_A); ++ DRM_UDELAY(150); ++ ++ /* Restore mode */ ++ PSB_WVDC32(regs->psb.saveHTOTAL_A, HTOTAL_A); ++ PSB_WVDC32(regs->psb.saveHBLANK_A, HBLANK_A); ++ PSB_WVDC32(regs->psb.saveHSYNC_A, HSYNC_A); ++ PSB_WVDC32(regs->psb.saveVTOTAL_A, VTOTAL_A); ++ PSB_WVDC32(regs->psb.saveVBLANK_A, VBLANK_A); ++ PSB_WVDC32(regs->psb.saveVSYNC_A, VSYNC_A); ++ PSB_WVDC32(regs->psb.savePIPEASRC, PIPEASRC); ++ PSB_WVDC32(regs->psb.saveBCLRPAT_A, BCLRPAT_A); ++ ++ /* Restore performance mode*/ ++ PSB_WVDC32(regs->psb.savePERF_MODE, MRST_PERF_MODE); ++ ++ /* Enable the pipe*/ ++ if (dev_priv->iLVDS_enable) ++ PSB_WVDC32(regs->psb.savePIPEACONF, PIPEACONF); ++ ++ /* Set up the plane*/ ++ PSB_WVDC32(regs->psb.saveDSPALINOFF, DSPALINOFF); ++ PSB_WVDC32(regs->psb.saveDSPASTRIDE, DSPASTRIDE); ++ PSB_WVDC32(regs->psb.saveDSPATILEOFF, DSPATILEOFF); ++ ++ /* Enable the plane */ ++ PSB_WVDC32(regs->psb.saveDSPACNTR, DSPACNTR); ++ PSB_WVDC32(regs->psb.saveDSPASURF, DSPASURF); ++ ++ /* Enable Cursor A */ ++ PSB_WVDC32(regs->psb.saveDSPACURSOR_CTRL, CURACNTR); ++ PSB_WVDC32(regs->psb.saveDSPACURSOR_POS, CURAPOS); ++ PSB_WVDC32(regs->psb.saveDSPACURSOR_BASE, CURABASE); ++ ++ /* Restore palette (gamma) */ ++ for (i = 0; i < 256; i++) ++ PSB_WVDC32(regs->psb.save_palette_a[i], PALETTE_A + (i << 2)); ++ ++ if (dev_priv->hdmi_priv) ++ oaktrail_hdmi_restore(dev); ++ ++ if (dev_priv->iLVDS_enable) { ++ PSB_WVDC32(regs->saveBLC_PWM_CTL2, BLC_PWM_CTL2); ++ PSB_WVDC32(regs->psb.saveLVDS, LVDS); /*port 61180h*/ ++ PSB_WVDC32(regs->psb.savePFIT_CONTROL, PFIT_CONTROL); ++ PSB_WVDC32(regs->psb.savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); ++ PSB_WVDC32(regs->psb.savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS); ++ PSB_WVDC32(regs->saveBLC_PWM_CTL, BLC_PWM_CTL); ++ PSB_WVDC32(regs->psb.savePP_ON_DELAYS, LVDSPP_ON); ++ PSB_WVDC32(regs->psb.savePP_OFF_DELAYS, LVDSPP_OFF); ++ PSB_WVDC32(regs->psb.savePP_DIVISOR, PP_CYCLE); ++ PSB_WVDC32(regs->psb.savePP_CONTROL, PP_CONTROL); ++ } ++ ++ /* Wait for cycle delay */ ++ do { ++ pp_stat = PSB_RVDC32(PP_STATUS); ++ } while (pp_stat & 0x08000000); ++ ++ /* Wait for panel power up */ ++ do { ++ pp_stat = PSB_RVDC32(PP_STATUS); ++ } while (pp_stat & 0x10000000); ++ ++ /* Restore HW overlay */ ++ PSB_WVDC32(regs->psb.saveOV_OVADD, OV_OVADD); ++ PSB_WVDC32(regs->psb.saveOV_OGAMC0, OV_OGAMC0); ++ PSB_WVDC32(regs->psb.saveOV_OGAMC1, OV_OGAMC1); ++ PSB_WVDC32(regs->psb.saveOV_OGAMC2, OV_OGAMC2); ++ PSB_WVDC32(regs->psb.saveOV_OGAMC3, OV_OGAMC3); ++ PSB_WVDC32(regs->psb.saveOV_OGAMC4, OV_OGAMC4); ++ PSB_WVDC32(regs->psb.saveOV_OGAMC5, OV_OGAMC5); ++ ++ /* DPST registers */ ++ PSB_WVDC32(regs->psb.saveHISTOGRAM_INT_CONTROL_REG, ++ HISTOGRAM_INT_CONTROL); ++ PSB_WVDC32(regs->psb.saveHISTOGRAM_LOGIC_CONTROL_REG, ++ HISTOGRAM_LOGIC_CONTROL); ++ PSB_WVDC32(regs->psb.savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC); ++ ++ return 0; ++} ++ ++/** ++ * oaktrail_power_down - power down the display island ++ * @dev: our DRM device ++ * ++ * Power down the display interface of our device ++ */ ++static int oaktrail_power_down(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 pwr_mask ; ++ u32 pwr_sts; ++ ++ pwr_mask = PSB_PWRGT_DISPLAY_MASK; ++ outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC); ++ ++ while (true) { ++ pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); ++ if ((pwr_sts & pwr_mask) == pwr_mask) ++ break; ++ else ++ udelay(10); ++ } ++ return 0; ++} ++ ++/* ++ * oaktrail_power_up ++ * ++ * Restore power to the specified island(s) (powergating) ++ */ ++static int oaktrail_power_up(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK; ++ u32 pwr_sts, pwr_cnt; ++ ++ pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC); ++ pwr_cnt &= ~pwr_mask; ++ outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC)); ++ ++ while (true) { ++ pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); ++ if ((pwr_sts & pwr_mask) == 0) ++ break; ++ else ++ udelay(10); ++ } ++ return 0; ++} ++ ++ ++static int oaktrail_chip_setup(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct oaktrail_vbt *vbt = &dev_priv->vbt_data; ++ int ret; ++ ++ ret = mid_chip_setup(dev); ++ if (ret < 0) ++ return ret; ++ if (vbt->size == 0) { ++ /* Now pull the BIOS data */ ++ gma_intel_opregion_init(dev); ++ psb_intel_init_bios(dev); ++ } ++ return 0; ++} ++ ++static void oaktrail_teardown(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct oaktrail_vbt *vbt = &dev_priv->vbt_data; ++ ++ oaktrail_hdmi_teardown(dev); ++ if (vbt->size == 0) ++ psb_intel_destroy_bios(dev); ++} ++ ++const struct psb_ops oaktrail_chip_ops = { ++ .name = "Oaktrail", ++ .accel_2d = 1, ++ .pipes = 2, ++ .crtcs = 2, ++ .sgx_offset = MRST_SGX_OFFSET, ++ ++ .chip_setup = oaktrail_chip_setup, ++ .chip_teardown = oaktrail_teardown, ++ .crtc_helper = &oaktrail_helper_funcs, ++ .crtc_funcs = &psb_intel_crtc_funcs, ++ ++ .output_init = oaktrail_output_init, ++ ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ .backlight_init = oaktrail_backlight_init, ++#endif ++ ++ .save_regs = oaktrail_save_display_registers, ++ .restore_regs = oaktrail_restore_display_registers, ++ .power_down = oaktrail_power_down, ++ .power_up = oaktrail_power_up, ++ ++ .i2c_bus = 1, ++}; +diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c +new file mode 100644 +index 0000000..f8b367b +--- /dev/null ++++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c +@@ -0,0 +1,540 @@ ++/* ++ * Copyright © 2010 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Li Peng ++ */ ++ ++#include ++#include ++#include "psb_intel_drv.h" ++#include "psb_intel_reg.h" ++#include "psb_drv.h" ++ ++#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg)) ++#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg)) ++ ++#define HDMI_HCR 0x1000 ++#define HCR_ENABLE_HDCP (1 << 5) ++#define HCR_ENABLE_AUDIO (1 << 2) ++#define HCR_ENABLE_PIXEL (1 << 1) ++#define HCR_ENABLE_TMDS (1 << 0) ++ ++#define HDMI_HICR 0x1004 ++#define HDMI_HSR 0x1008 ++#define HDMI_HISR 0x100C ++#define HDMI_DETECT_HDP (1 << 0) ++ ++#define HDMI_VIDEO_REG 0x3000 ++#define HDMI_UNIT_EN (1 << 7) ++#define HDMI_MODE_OUTPUT (1 << 0) ++#define HDMI_HBLANK_A 0x3100 ++ ++#define HDMI_AUDIO_CTRL 0x4000 ++#define HDMI_ENABLE_AUDIO (1 << 0) ++ ++#define PCH_HTOTAL_B 0x3100 ++#define PCH_HBLANK_B 0x3104 ++#define PCH_HSYNC_B 0x3108 ++#define PCH_VTOTAL_B 0x310C ++#define PCH_VBLANK_B 0x3110 ++#define PCH_VSYNC_B 0x3114 ++#define PCH_PIPEBSRC 0x311C ++ ++#define PCH_PIPEB_DSL 0x3800 ++#define PCH_PIPEB_SLC 0x3804 ++#define PCH_PIPEBCONF 0x3808 ++#define PCH_PIPEBSTAT 0x3824 ++ ++#define CDVO_DFT 0x5000 ++#define CDVO_SLEWRATE 0x5004 ++#define CDVO_STRENGTH 0x5008 ++#define CDVO_RCOMP 0x500C ++ ++#define DPLL_CTRL 0x6000 ++#define DPLL_PDIV_SHIFT 16 ++#define DPLL_PDIV_MASK (0xf << 16) ++#define DPLL_PWRDN (1 << 4) ++#define DPLL_RESET (1 << 3) ++#define DPLL_FASTEN (1 << 2) ++#define DPLL_ENSTAT (1 << 1) ++#define DPLL_DITHEN (1 << 0) ++ ++#define DPLL_DIV_CTRL 0x6004 ++#define DPLL_CLKF_MASK 0xffffffc0 ++#define DPLL_CLKR_MASK (0x3f) ++ ++#define DPLL_CLK_ENABLE 0x6008 ++#define DPLL_EN_DISP (1 << 31) ++#define DPLL_SEL_HDMI (1 << 8) ++#define DPLL_EN_HDMI (1 << 1) ++#define DPLL_EN_VGA (1 << 0) ++ ++#define DPLL_ADJUST 0x600C ++#define DPLL_STATUS 0x6010 ++#define DPLL_UPDATE 0x6014 ++#define DPLL_DFT 0x6020 ++ ++struct intel_range { ++ int min, max; ++}; ++ ++struct oaktrail_hdmi_limit { ++ struct intel_range vco, np, nr, nf; ++}; ++ ++struct oaktrail_hdmi_clock { ++ int np; ++ int nr; ++ int nf; ++ int dot; ++}; ++ ++#define VCO_MIN 320000 ++#define VCO_MAX 1650000 ++#define NP_MIN 1 ++#define NP_MAX 15 ++#define NR_MIN 1 ++#define NR_MAX 64 ++#define NF_MIN 2 ++#define NF_MAX 4095 ++ ++static const struct oaktrail_hdmi_limit oaktrail_hdmi_limit = { ++ .vco = { .min = VCO_MIN, .max = VCO_MAX }, ++ .np = { .min = NP_MIN, .max = NP_MAX }, ++ .nr = { .min = NR_MIN, .max = NR_MAX }, ++ .nf = { .min = NF_MIN, .max = NF_MAX }, ++}; ++ ++static void oaktrail_hdmi_audio_enable(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; ++ ++ HDMI_WRITE(HDMI_HCR, 0x67); ++ HDMI_READ(HDMI_HCR); ++ ++ HDMI_WRITE(0x51a8, 0x10); ++ HDMI_READ(0x51a8); ++ ++ HDMI_WRITE(HDMI_AUDIO_CTRL, 0x1); ++ HDMI_READ(HDMI_AUDIO_CTRL); ++} ++ ++static void oaktrail_hdmi_audio_disable(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; ++ ++ HDMI_WRITE(0x51a8, 0x0); ++ HDMI_READ(0x51a8); ++ ++ HDMI_WRITE(HDMI_AUDIO_CTRL, 0x0); ++ HDMI_READ(HDMI_AUDIO_CTRL); ++ ++ HDMI_WRITE(HDMI_HCR, 0x47); ++ HDMI_READ(HDMI_HCR); ++} ++ ++static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode) ++{ ++ static int dpms_mode = -1; ++ ++ struct drm_device *dev = encoder->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; ++ u32 temp; ++ ++ if (dpms_mode == mode) ++ return; ++ ++ if (mode != DRM_MODE_DPMS_ON) ++ temp = 0x0; ++ else ++ temp = 0x99; ++ ++ dpms_mode = mode; ++ HDMI_WRITE(HDMI_VIDEO_REG, temp); ++} ++ ++static int oaktrail_hdmi_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ struct drm_psb_private *dev_priv = connector->dev->dev_private; ++ if (mode->clock > 165000) ++ return MODE_CLOCK_HIGH; ++ if (mode->clock < 20000) ++ return MODE_CLOCK_LOW; ++ ++ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ return MODE_NO_DBLESCAN; ++ ++ /* We assume worst case scenario of 32 bpp here, since we don't know */ ++ if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) > ++ dev_priv->vram_stolen_size) ++ return MODE_MEM; ++ ++ return MODE_OK; ++} ++ ++static bool oaktrail_hdmi_mode_fixup(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ return true; ++} ++ ++static enum drm_connector_status ++oaktrail_hdmi_detect(struct drm_connector *connector, bool force) ++{ ++ enum drm_connector_status status; ++ struct drm_device *dev = connector->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; ++ u32 temp; ++ ++ temp = HDMI_READ(HDMI_HSR); ++ DRM_DEBUG_KMS("HDMI_HSR %x\n", temp); ++ ++ if ((temp & HDMI_DETECT_HDP) != 0) ++ status = connector_status_connected; ++ else ++ status = connector_status_disconnected; ++ ++ return status; ++} ++ ++static const unsigned char raw_edid[] = { ++ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x2f, 0xa0, ++ 0x53, 0x55, 0x33, 0x30, 0x16, 0x13, 0x01, 0x03, 0x0e, 0x3a, 0x24, 0x78, ++ 0xea, 0xe9, 0xf5, 0xac, 0x51, 0x30, 0xb4, 0x25, 0x11, 0x50, 0x54, 0xa5, ++ 0x4b, 0x00, 0x81, 0x80, 0xa9, 0x40, 0x71, 0x4f, 0xb3, 0x00, 0x01, 0x01, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0, ++ 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x46, 0x6c, 0x21, 0x00, 0x00, 0x1a, ++ 0x00, 0x00, 0x00, 0xff, 0x00, 0x47, 0x4e, 0x37, 0x32, 0x31, 0x39, 0x35, ++ 0x52, 0x30, 0x33, 0x55, 0x53, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44, ++ 0x45, 0x4c, 0x4c, 0x20, 0x32, 0x37, 0x30, 0x39, 0x57, 0x0a, 0x20, 0x20, ++ 0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a, ++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x8d ++}; ++ ++static int oaktrail_hdmi_get_modes(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct i2c_adapter *i2c_adap; ++ struct edid *edid; ++ struct drm_display_mode *mode, *t; ++ int i = 0, ret = 0; ++ ++ i2c_adap = i2c_get_adapter(3); ++ if (i2c_adap == NULL) { ++ DRM_ERROR("No ddc adapter available!\n"); ++ edid = (struct edid *)raw_edid; ++ } else { ++ edid = (struct edid *)raw_edid; ++ /* FIXME ? edid = drm_get_edid(connector, i2c_adap); */ ++ } ++ ++ if (edid) { ++ drm_mode_connector_update_edid_property(connector, edid); ++ ret = drm_add_edid_modes(connector, edid); ++ connector->display_info.raw_edid = NULL; ++ } ++ ++ /* ++ * prune modes that require frame buffer bigger than stolen mem ++ */ ++ list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { ++ if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) { ++ i++; ++ drm_mode_remove(connector, mode); ++ } ++ } ++ return ret - i; ++} ++ ++static void oaktrail_hdmi_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ ++ oaktrail_hdmi_audio_enable(dev); ++ return; ++} ++ ++static void oaktrail_hdmi_destroy(struct drm_connector *connector) ++{ ++ return; ++} ++ ++static const struct drm_encoder_helper_funcs oaktrail_hdmi_helper_funcs = { ++ .dpms = oaktrail_hdmi_dpms, ++ .mode_fixup = oaktrail_hdmi_mode_fixup, ++ .prepare = psb_intel_encoder_prepare, ++ .mode_set = oaktrail_hdmi_mode_set, ++ .commit = psb_intel_encoder_commit, ++}; ++ ++static const struct drm_connector_helper_funcs ++ oaktrail_hdmi_connector_helper_funcs = { ++ .get_modes = oaktrail_hdmi_get_modes, ++ .mode_valid = oaktrail_hdmi_mode_valid, ++ .best_encoder = psb_intel_best_encoder, ++}; ++ ++static const struct drm_connector_funcs oaktrail_hdmi_connector_funcs = { ++ .dpms = drm_helper_connector_dpms, ++ .detect = oaktrail_hdmi_detect, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .destroy = oaktrail_hdmi_destroy, ++}; ++ ++static void oaktrail_hdmi_enc_destroy(struct drm_encoder *encoder) ++{ ++ drm_encoder_cleanup(encoder); ++} ++ ++static const struct drm_encoder_funcs oaktrail_hdmi_enc_funcs = { ++ .destroy = oaktrail_hdmi_enc_destroy, ++}; ++ ++void oaktrail_hdmi_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev) ++{ ++ struct psb_intel_encoder *psb_intel_encoder; ++ struct psb_intel_connector *psb_intel_connector; ++ struct drm_connector *connector; ++ struct drm_encoder *encoder; ++ ++ psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); ++ if (!psb_intel_encoder) ++ return; ++ ++ psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL); ++ if (!psb_intel_connector) ++ goto failed_connector; ++ ++ connector = &psb_intel_connector->base; ++ encoder = &psb_intel_encoder->base; ++ drm_connector_init(dev, connector, ++ &oaktrail_hdmi_connector_funcs, ++ DRM_MODE_CONNECTOR_DVID); ++ ++ drm_encoder_init(dev, encoder, ++ &oaktrail_hdmi_enc_funcs, ++ DRM_MODE_ENCODER_TMDS); ++ ++ psb_intel_connector_attach_encoder(psb_intel_connector, ++ psb_intel_encoder); ++ ++ psb_intel_encoder->type = INTEL_OUTPUT_HDMI; ++ drm_encoder_helper_add(encoder, &oaktrail_hdmi_helper_funcs); ++ drm_connector_helper_add(connector, &oaktrail_hdmi_connector_helper_funcs); ++ ++ connector->display_info.subpixel_order = SubPixelHorizontalRGB; ++ connector->interlace_allowed = false; ++ connector->doublescan_allowed = false; ++ drm_sysfs_connector_add(connector); ++ ++ return; ++ ++failed_connector: ++ kfree(psb_intel_encoder); ++} ++ ++static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = { ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) }, ++ { 0 } ++}; ++ ++void oaktrail_hdmi_setup(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct pci_dev *pdev; ++ struct oaktrail_hdmi_dev *hdmi_dev; ++ int ret; ++ ++ pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x080d, NULL); ++ if (!pdev) ++ return; ++ ++ hdmi_dev = kzalloc(sizeof(struct oaktrail_hdmi_dev), GFP_KERNEL); ++ if (!hdmi_dev) { ++ dev_err(dev->dev, "failed to allocate memory\n"); ++ goto out; ++ } ++ ++ ++ ret = pci_enable_device(pdev); ++ if (ret) { ++ dev_err(dev->dev, "failed to enable hdmi controller\n"); ++ goto free; ++ } ++ ++ hdmi_dev->mmio = pci_resource_start(pdev, 0); ++ hdmi_dev->mmio_len = pci_resource_len(pdev, 0); ++ hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len); ++ if (!hdmi_dev->regs) { ++ dev_err(dev->dev, "failed to map hdmi mmio\n"); ++ goto free; ++ } ++ ++ hdmi_dev->dev = pdev; ++ pci_set_drvdata(pdev, hdmi_dev); ++ ++ /* Initialize i2c controller */ ++ ret = oaktrail_hdmi_i2c_init(hdmi_dev->dev); ++ if (ret) ++ dev_err(dev->dev, "HDMI I2C initialization failed\n"); ++ ++ dev_priv->hdmi_priv = hdmi_dev; ++ oaktrail_hdmi_audio_disable(dev); ++ return; ++ ++free: ++ kfree(hdmi_dev); ++out: ++ return; ++} ++ ++void oaktrail_hdmi_teardown(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; ++ struct pci_dev *pdev; ++ ++ if (hdmi_dev) { ++ pdev = hdmi_dev->dev; ++ pci_set_drvdata(pdev, NULL); ++ oaktrail_hdmi_i2c_exit(pdev); ++ iounmap(hdmi_dev->regs); ++ kfree(hdmi_dev); ++ pci_dev_put(pdev); ++ } ++} ++ ++/* save HDMI register state */ ++void oaktrail_hdmi_save(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; ++ struct psb_state *regs = &dev_priv->regs.psb; ++ int i; ++ ++ /* dpll */ ++ hdmi_dev->saveDPLL_CTRL = PSB_RVDC32(DPLL_CTRL); ++ hdmi_dev->saveDPLL_DIV_CTRL = PSB_RVDC32(DPLL_DIV_CTRL); ++ hdmi_dev->saveDPLL_ADJUST = PSB_RVDC32(DPLL_ADJUST); ++ hdmi_dev->saveDPLL_UPDATE = PSB_RVDC32(DPLL_UPDATE); ++ hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE); ++ ++ /* pipe B */ ++ regs->savePIPEBCONF = PSB_RVDC32(PIPEBCONF); ++ regs->savePIPEBSRC = PSB_RVDC32(PIPEBSRC); ++ regs->saveHTOTAL_B = PSB_RVDC32(HTOTAL_B); ++ regs->saveHBLANK_B = PSB_RVDC32(HBLANK_B); ++ regs->saveHSYNC_B = PSB_RVDC32(HSYNC_B); ++ regs->saveVTOTAL_B = PSB_RVDC32(VTOTAL_B); ++ regs->saveVBLANK_B = PSB_RVDC32(VBLANK_B); ++ regs->saveVSYNC_B = PSB_RVDC32(VSYNC_B); ++ ++ hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF); ++ hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC); ++ hdmi_dev->savePCH_HTOTAL_B = PSB_RVDC32(PCH_HTOTAL_B); ++ hdmi_dev->savePCH_HBLANK_B = PSB_RVDC32(PCH_HBLANK_B); ++ hdmi_dev->savePCH_HSYNC_B = PSB_RVDC32(PCH_HSYNC_B); ++ hdmi_dev->savePCH_VTOTAL_B = PSB_RVDC32(PCH_VTOTAL_B); ++ hdmi_dev->savePCH_VBLANK_B = PSB_RVDC32(PCH_VBLANK_B); ++ hdmi_dev->savePCH_VSYNC_B = PSB_RVDC32(PCH_VSYNC_B); ++ ++ /* plane */ ++ regs->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR); ++ regs->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE); ++ regs->saveDSPBADDR = PSB_RVDC32(DSPBBASE); ++ regs->saveDSPBSURF = PSB_RVDC32(DSPBSURF); ++ regs->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF); ++ regs->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF); ++ ++ /* cursor B */ ++ regs->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR); ++ regs->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE); ++ regs->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS); ++ ++ /* save palette */ ++ for (i = 0; i < 256; i++) ++ regs->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2)); ++} ++ ++/* restore HDMI register state */ ++void oaktrail_hdmi_restore(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; ++ struct psb_state *regs = &dev_priv->regs.psb; ++ int i; ++ ++ /* dpll */ ++ PSB_WVDC32(hdmi_dev->saveDPLL_CTRL, DPLL_CTRL); ++ PSB_WVDC32(hdmi_dev->saveDPLL_DIV_CTRL, DPLL_DIV_CTRL); ++ PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST); ++ PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE); ++ PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE); ++ DRM_UDELAY(150); ++ ++ /* pipe */ ++ PSB_WVDC32(regs->savePIPEBSRC, PIPEBSRC); ++ PSB_WVDC32(regs->saveHTOTAL_B, HTOTAL_B); ++ PSB_WVDC32(regs->saveHBLANK_B, HBLANK_B); ++ PSB_WVDC32(regs->saveHSYNC_B, HSYNC_B); ++ PSB_WVDC32(regs->saveVTOTAL_B, VTOTAL_B); ++ PSB_WVDC32(regs->saveVBLANK_B, VBLANK_B); ++ PSB_WVDC32(regs->saveVSYNC_B, VSYNC_B); ++ ++ PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC); ++ PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B); ++ PSB_WVDC32(hdmi_dev->savePCH_HBLANK_B, PCH_HBLANK_B); ++ PSB_WVDC32(hdmi_dev->savePCH_HSYNC_B, PCH_HSYNC_B); ++ PSB_WVDC32(hdmi_dev->savePCH_VTOTAL_B, PCH_VTOTAL_B); ++ PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B); ++ PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B, PCH_VSYNC_B); ++ ++ PSB_WVDC32(regs->savePIPEBCONF, PIPEBCONF); ++ PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF); ++ ++ /* plane */ ++ PSB_WVDC32(regs->saveDSPBLINOFF, DSPBLINOFF); ++ PSB_WVDC32(regs->saveDSPBSTRIDE, DSPBSTRIDE); ++ PSB_WVDC32(regs->saveDSPBTILEOFF, DSPBTILEOFF); ++ PSB_WVDC32(regs->saveDSPBCNTR, DSPBCNTR); ++ PSB_WVDC32(regs->saveDSPBSURF, DSPBSURF); ++ ++ /* cursor B */ ++ PSB_WVDC32(regs->saveDSPBCURSOR_CTRL, CURBCNTR); ++ PSB_WVDC32(regs->saveDSPBCURSOR_POS, CURBPOS); ++ PSB_WVDC32(regs->saveDSPBCURSOR_BASE, CURBBASE); ++ ++ /* restore palette */ ++ for (i = 0; i < 256; i++) ++ PSB_WVDC32(regs->save_palette_b[i], PALETTE_B + (i << 2)); ++} +diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c +new file mode 100644 +index 0000000..5e84fbd +--- /dev/null ++++ b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c +@@ -0,0 +1,328 @@ ++/* ++ * Copyright © 2010 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Li Peng ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "psb_drv.h" ++ ++#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg)) ++#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg)) ++ ++#define HDMI_HCR 0x1000 ++#define HCR_DETECT_HDP (1 << 6) ++#define HCR_ENABLE_HDCP (1 << 5) ++#define HCR_ENABLE_AUDIO (1 << 2) ++#define HCR_ENABLE_PIXEL (1 << 1) ++#define HCR_ENABLE_TMDS (1 << 0) ++#define HDMI_HICR 0x1004 ++#define HDMI_INTR_I2C_ERROR (1 << 4) ++#define HDMI_INTR_I2C_FULL (1 << 3) ++#define HDMI_INTR_I2C_DONE (1 << 2) ++#define HDMI_INTR_HPD (1 << 0) ++#define HDMI_HSR 0x1008 ++#define HDMI_HISR 0x100C ++#define HDMI_HI2CRDB0 0x1200 ++#define HDMI_HI2CHCR 0x1240 ++#define HI2C_HDCP_WRITE (0 << 2) ++#define HI2C_HDCP_RI_READ (1 << 2) ++#define HI2C_HDCP_READ (2 << 2) ++#define HI2C_EDID_READ (3 << 2) ++#define HI2C_READ_CONTINUE (1 << 1) ++#define HI2C_ENABLE_TRANSACTION (1 << 0) ++ ++#define HDMI_ICRH 0x1100 ++#define HDMI_HI2CTDR0 0x1244 ++#define HDMI_HI2CTDR1 0x1248 ++ ++#define I2C_STAT_INIT 0 ++#define I2C_READ_DONE 1 ++#define I2C_TRANSACTION_DONE 2 ++ ++struct hdmi_i2c_dev { ++ struct i2c_adapter *adap; ++ struct mutex i2c_lock; ++ struct completion complete; ++ int status; ++ struct i2c_msg *msg; ++ int buf_offset; ++}; ++ ++static void hdmi_i2c_irq_enable(struct oaktrail_hdmi_dev *hdmi_dev) ++{ ++ u32 temp; ++ ++ temp = HDMI_READ(HDMI_HICR); ++ temp |= (HDMI_INTR_I2C_ERROR | HDMI_INTR_I2C_FULL | HDMI_INTR_I2C_DONE); ++ HDMI_WRITE(HDMI_HICR, temp); ++ HDMI_READ(HDMI_HICR); ++} ++ ++static void hdmi_i2c_irq_disable(struct oaktrail_hdmi_dev *hdmi_dev) ++{ ++ HDMI_WRITE(HDMI_HICR, 0x0); ++ HDMI_READ(HDMI_HICR); ++} ++ ++static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg) ++{ ++ struct oaktrail_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap); ++ struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; ++ u32 temp; ++ ++ i2c_dev->status = I2C_STAT_INIT; ++ i2c_dev->msg = pmsg; ++ i2c_dev->buf_offset = 0; ++ INIT_COMPLETION(i2c_dev->complete); ++ ++ /* Enable I2C transaction */ ++ temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION; ++ HDMI_WRITE(HDMI_HI2CHCR, temp); ++ HDMI_READ(HDMI_HI2CHCR); ++ ++ while (i2c_dev->status != I2C_TRANSACTION_DONE) ++ wait_for_completion_interruptible_timeout(&i2c_dev->complete, ++ 10 * HZ); ++ ++ return 0; ++} ++ ++static int xfer_write(struct i2c_adapter *adap, struct i2c_msg *pmsg) ++{ ++ /* ++ * XXX: i2c write seems isn't useful for EDID probe, don't do anything ++ */ ++ return 0; ++} ++ ++static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap, ++ struct i2c_msg *pmsg, ++ int num) ++{ ++ struct oaktrail_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap); ++ struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; ++ int i; ++ ++ mutex_lock(&i2c_dev->i2c_lock); ++ ++ /* Enable i2c unit */ ++ HDMI_WRITE(HDMI_ICRH, 0x00008760); ++ ++ /* Enable irq */ ++ hdmi_i2c_irq_enable(hdmi_dev); ++ for (i = 0; i < num; i++) { ++ if (pmsg->len && pmsg->buf) { ++ if (pmsg->flags & I2C_M_RD) ++ xfer_read(adap, pmsg); ++ else ++ xfer_write(adap, pmsg); ++ } ++ pmsg++; /* next message */ ++ } ++ ++ /* Disable irq */ ++ hdmi_i2c_irq_disable(hdmi_dev); ++ ++ mutex_unlock(&i2c_dev->i2c_lock); ++ ++ return i; ++} ++ ++static u32 oaktrail_hdmi_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; ++} ++ ++static const struct i2c_algorithm oaktrail_hdmi_i2c_algorithm = { ++ .master_xfer = oaktrail_hdmi_i2c_access, ++ .functionality = oaktrail_hdmi_i2c_func, ++}; ++ ++static struct i2c_adapter oaktrail_hdmi_i2c_adapter = { ++ .name = "oaktrail_hdmi_i2c", ++ .nr = 3, ++ .owner = THIS_MODULE, ++ .class = I2C_CLASS_DDC, ++ .algo = &oaktrail_hdmi_i2c_algorithm, ++}; ++ ++static void hdmi_i2c_read(struct oaktrail_hdmi_dev *hdmi_dev) ++{ ++ struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; ++ struct i2c_msg *msg = i2c_dev->msg; ++ u8 *buf = msg->buf; ++ u32 temp; ++ int i, offset; ++ ++ offset = i2c_dev->buf_offset; ++ for (i = 0; i < 0x10; i++) { ++ temp = HDMI_READ(HDMI_HI2CRDB0 + (i * 4)); ++ memcpy(buf + (offset + i * 4), &temp, 4); ++ } ++ i2c_dev->buf_offset += (0x10 * 4); ++ ++ /* clearing read buffer full intr */ ++ temp = HDMI_READ(HDMI_HISR); ++ HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_FULL); ++ HDMI_READ(HDMI_HISR); ++ ++ /* continue read transaction */ ++ temp = HDMI_READ(HDMI_HI2CHCR); ++ HDMI_WRITE(HDMI_HI2CHCR, temp | HI2C_READ_CONTINUE); ++ HDMI_READ(HDMI_HI2CHCR); ++ ++ i2c_dev->status = I2C_READ_DONE; ++ return; ++} ++ ++static void hdmi_i2c_transaction_done(struct oaktrail_hdmi_dev *hdmi_dev) ++{ ++ struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; ++ u32 temp; ++ ++ /* clear transaction done intr */ ++ temp = HDMI_READ(HDMI_HISR); ++ HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_DONE); ++ HDMI_READ(HDMI_HISR); ++ ++ ++ temp = HDMI_READ(HDMI_HI2CHCR); ++ HDMI_WRITE(HDMI_HI2CHCR, temp & ~HI2C_ENABLE_TRANSACTION); ++ HDMI_READ(HDMI_HI2CHCR); ++ ++ i2c_dev->status = I2C_TRANSACTION_DONE; ++ return; ++} ++ ++static irqreturn_t oaktrail_hdmi_i2c_handler(int this_irq, void *dev) ++{ ++ struct oaktrail_hdmi_dev *hdmi_dev = dev; ++ struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; ++ u32 stat; ++ ++ stat = HDMI_READ(HDMI_HISR); ++ ++ if (stat & HDMI_INTR_HPD) { ++ HDMI_WRITE(HDMI_HISR, stat | HDMI_INTR_HPD); ++ HDMI_READ(HDMI_HISR); ++ } ++ ++ if (stat & HDMI_INTR_I2C_FULL) ++ hdmi_i2c_read(hdmi_dev); ++ ++ if (stat & HDMI_INTR_I2C_DONE) ++ hdmi_i2c_transaction_done(hdmi_dev); ++ ++ complete(&i2c_dev->complete); ++ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * choose alternate function 2 of GPIO pin 52, 53, ++ * which is used by HDMI I2C logic ++ */ ++static void oaktrail_hdmi_i2c_gpio_fix(void) ++{ ++ void *base; ++ unsigned int gpio_base = 0xff12c000; ++ int gpio_len = 0x1000; ++ u32 temp; ++ ++ base = ioremap((resource_size_t)gpio_base, gpio_len); ++ if (base == NULL) { ++ DRM_ERROR("gpio ioremap fail\n"); ++ return; ++ } ++ ++ temp = readl(base + 0x44); ++ DRM_DEBUG_DRIVER("old gpio val %x\n", temp); ++ writel((temp | 0x00000a00), (base + 0x44)); ++ temp = readl(base + 0x44); ++ DRM_DEBUG_DRIVER("new gpio val %x\n", temp); ++ ++ iounmap(base); ++} ++ ++int oaktrail_hdmi_i2c_init(struct pci_dev *dev) ++{ ++ struct oaktrail_hdmi_dev *hdmi_dev; ++ struct hdmi_i2c_dev *i2c_dev; ++ int ret; ++ ++ hdmi_dev = pci_get_drvdata(dev); ++ ++ i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL); ++ if (i2c_dev == NULL) { ++ DRM_ERROR("Can't allocate interface\n"); ++ ret = -ENOMEM; ++ goto exit; ++ } ++ ++ i2c_dev->adap = &oaktrail_hdmi_i2c_adapter; ++ i2c_dev->status = I2C_STAT_INIT; ++ init_completion(&i2c_dev->complete); ++ mutex_init(&i2c_dev->i2c_lock); ++ i2c_set_adapdata(&oaktrail_hdmi_i2c_adapter, hdmi_dev); ++ hdmi_dev->i2c_dev = i2c_dev; ++ ++ /* Enable HDMI I2C function on gpio */ ++ oaktrail_hdmi_i2c_gpio_fix(); ++ ++ /* request irq */ ++ ret = request_irq(dev->irq, oaktrail_hdmi_i2c_handler, IRQF_SHARED, ++ oaktrail_hdmi_i2c_adapter.name, hdmi_dev); ++ if (ret) { ++ DRM_ERROR("Failed to request IRQ for I2C controller\n"); ++ goto err; ++ } ++ ++ /* Adapter registration */ ++ ret = i2c_add_numbered_adapter(&oaktrail_hdmi_i2c_adapter); ++ return ret; ++ ++err: ++ kfree(i2c_dev); ++exit: ++ return ret; ++} ++ ++void oaktrail_hdmi_i2c_exit(struct pci_dev *dev) ++{ ++ struct oaktrail_hdmi_dev *hdmi_dev; ++ struct hdmi_i2c_dev *i2c_dev; ++ ++ hdmi_dev = pci_get_drvdata(dev); ++ if (i2c_del_adapter(&oaktrail_hdmi_i2c_adapter)) ++ DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n"); ++ ++ i2c_dev = hdmi_dev->i2c_dev; ++ kfree(i2c_dev); ++ free_irq(dev->irq, hdmi_dev); ++} +diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c +new file mode 100644 +index 0000000..654f32b +--- /dev/null ++++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c +@@ -0,0 +1,448 @@ ++/* ++ * Copyright © 2006-2009 Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: ++ * Eric Anholt ++ * Dave Airlie ++ * Jesse Barnes ++ */ ++ ++#include ++#include ++#include ++ ++#include "intel_bios.h" ++#include "psb_drv.h" ++#include "psb_intel_drv.h" ++#include "psb_intel_reg.h" ++#include "power.h" ++#include ++ ++/* The max/min PWM frequency in BPCR[31:17] - */ ++/* The smallest number is 1 (not 0) that can fit in the ++ * 15-bit field of the and then*/ ++/* shifts to the left by one bit to get the actual 16-bit ++ * value that the 15-bits correspond to.*/ ++#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF ++#define BRIGHTNESS_MAX_LEVEL 100 ++ ++/** ++ * Sets the power state for the panel. ++ */ ++static void oaktrail_lvds_set_power(struct drm_device *dev, ++ struct psb_intel_encoder *psb_intel_encoder, ++ bool on) ++{ ++ u32 pp_status; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (!gma_power_begin(dev, true)) ++ return; ++ ++ if (on) { ++ REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | ++ POWER_TARGET_ON); ++ do { ++ pp_status = REG_READ(PP_STATUS); ++ } while ((pp_status & (PP_ON | PP_READY)) == PP_READY); ++ dev_priv->is_lvds_on = true; ++ if (dev_priv->ops->lvds_bl_power) ++ dev_priv->ops->lvds_bl_power(dev, true); ++ } else { ++ if (dev_priv->ops->lvds_bl_power) ++ dev_priv->ops->lvds_bl_power(dev, false); ++ REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ++ ~POWER_TARGET_ON); ++ do { ++ pp_status = REG_READ(PP_STATUS); ++ } while (pp_status & PP_ON); ++ dev_priv->is_lvds_on = false; ++ pm_request_idle(&dev->pdev->dev); ++ } ++ gma_power_end(dev); ++} ++ ++static void oaktrail_lvds_dpms(struct drm_encoder *encoder, int mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct psb_intel_encoder *psb_intel_encoder = ++ to_psb_intel_encoder(encoder); ++ ++ if (mode == DRM_MODE_DPMS_ON) ++ oaktrail_lvds_set_power(dev, psb_intel_encoder, true); ++ else ++ oaktrail_lvds_set_power(dev, psb_intel_encoder, false); ++ ++ /* XXX: We never power down the LVDS pairs. */ ++} ++ ++static void oaktrail_lvds_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ struct drm_mode_config *mode_config = &dev->mode_config; ++ struct drm_connector *connector = NULL; ++ struct drm_crtc *crtc = encoder->crtc; ++ u32 lvds_port; ++ uint64_t v = DRM_MODE_SCALE_FULLSCREEN; ++ ++ if (!gma_power_begin(dev, true)) ++ return; ++ ++ /* ++ * The LVDS pin pair will already have been turned on in the ++ * psb_intel_crtc_mode_set since it has a large impact on the DPLL ++ * settings. ++ */ ++ lvds_port = (REG_READ(LVDS) & ++ (~LVDS_PIPEB_SELECT)) | ++ LVDS_PORT_EN | ++ LVDS_BORDER_EN; ++ ++ /* If the firmware says dither on Moorestown, or the BIOS does ++ on Oaktrail then enable dithering */ ++ if (mode_dev->panel_wants_dither || dev_priv->lvds_dither) ++ lvds_port |= MRST_PANEL_8TO6_DITHER_ENABLE; ++ ++ REG_WRITE(LVDS, lvds_port); ++ ++ /* Find the connector we're trying to set up */ ++ list_for_each_entry(connector, &mode_config->connector_list, head) { ++ if (!connector->encoder || connector->encoder->crtc != crtc) ++ continue; ++ } ++ ++ if (!connector) { ++ DRM_ERROR("Couldn't find connector when setting mode"); ++ return; ++ } ++ ++ drm_connector_property_get_value( ++ connector, ++ dev->mode_config.scaling_mode_property, ++ &v); ++ ++ if (v == DRM_MODE_SCALE_NO_SCALE) ++ REG_WRITE(PFIT_CONTROL, 0); ++ else if (v == DRM_MODE_SCALE_ASPECT) { ++ if ((mode->vdisplay != adjusted_mode->crtc_vdisplay) || ++ (mode->hdisplay != adjusted_mode->crtc_hdisplay)) { ++ if ((adjusted_mode->crtc_hdisplay * mode->vdisplay) == ++ (mode->hdisplay * adjusted_mode->crtc_vdisplay)) ++ REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); ++ else if ((adjusted_mode->crtc_hdisplay * ++ mode->vdisplay) > (mode->hdisplay * ++ adjusted_mode->crtc_vdisplay)) ++ REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | ++ PFIT_SCALING_MODE_PILLARBOX); ++ else ++ REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | ++ PFIT_SCALING_MODE_LETTERBOX); ++ } else ++ REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); ++ } else /*(v == DRM_MODE_SCALE_FULLSCREEN)*/ ++ REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); ++ ++ gma_power_end(dev); ++} ++ ++static void oaktrail_lvds_prepare(struct drm_encoder *encoder) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_encoder *psb_intel_encoder = ++ to_psb_intel_encoder(encoder); ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ ++ if (!gma_power_begin(dev, true)) ++ return; ++ ++ mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); ++ mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & ++ BACKLIGHT_DUTY_CYCLE_MASK); ++ oaktrail_lvds_set_power(dev, psb_intel_encoder, false); ++ gma_power_end(dev); ++} ++ ++static u32 oaktrail_lvds_get_max_backlight(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 ret; ++ ++ if (gma_power_begin(dev, false)) { ++ ret = ((REG_READ(BLC_PWM_CTL) & ++ BACKLIGHT_MODULATION_FREQ_MASK) >> ++ BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; ++ ++ gma_power_end(dev); ++ } else ++ ret = ((dev_priv->regs.saveBLC_PWM_CTL & ++ BACKLIGHT_MODULATION_FREQ_MASK) >> ++ BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; ++ ++ return ret; ++} ++ ++static void oaktrail_lvds_commit(struct drm_encoder *encoder) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_encoder *psb_intel_encoder = ++ to_psb_intel_encoder(encoder); ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ ++ if (mode_dev->backlight_duty_cycle == 0) ++ mode_dev->backlight_duty_cycle = ++ oaktrail_lvds_get_max_backlight(dev); ++ oaktrail_lvds_set_power(dev, psb_intel_encoder, true); ++} ++ ++static const struct drm_encoder_helper_funcs oaktrail_lvds_helper_funcs = { ++ .dpms = oaktrail_lvds_dpms, ++ .mode_fixup = psb_intel_lvds_mode_fixup, ++ .prepare = oaktrail_lvds_prepare, ++ .mode_set = oaktrail_lvds_mode_set, ++ .commit = oaktrail_lvds_commit, ++}; ++ ++static struct drm_display_mode lvds_configuration_modes[] = { ++ /* hard coded fixed mode for TPO LTPS LPJ040K001A */ ++ { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 33264, 800, 836, ++ 846, 1056, 0, 480, 489, 491, 525, 0, 0) }, ++ /* hard coded fixed mode for LVDS 800x480 */ ++ { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 30994, 800, 801, ++ 802, 1024, 0, 480, 481, 482, 525, 0, 0) }, ++ /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ ++ { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1072, ++ 1104, 1184, 0, 600, 603, 604, 608, 0, 0) }, ++ /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ ++ { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1104, ++ 1136, 1184, 0, 600, 603, 604, 608, 0, 0) }, ++ /* hard coded fixed mode for Sharp wsvga LVDS 1024x600 */ ++ { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 48885, 1024, 1124, ++ 1204, 1312, 0, 600, 607, 610, 621, 0, 0) }, ++ /* hard coded fixed mode for LVDS 1024x768 */ ++ { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, ++ 1184, 1344, 0, 768, 771, 777, 806, 0, 0) }, ++ /* hard coded fixed mode for LVDS 1366x768 */ ++ { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 77500, 1366, 1430, ++ 1558, 1664, 0, 768, 769, 770, 776, 0, 0) }, ++}; ++ ++/* Returns the panel fixed mode from configuration. */ ++ ++static void oaktrail_lvds_get_configuration_mode(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev) ++{ ++ struct drm_display_mode *mode = NULL; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD; ++ ++ mode_dev->panel_fixed_mode = NULL; ++ ++ /* Use the firmware provided data on Moorestown */ ++ if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/ ++ mode = kzalloc(sizeof(*mode), GFP_KERNEL); ++ if (!mode) ++ return; ++ ++ mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; ++ mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; ++ mode->hsync_start = mode->hdisplay + \ ++ ((ti->hsync_offset_hi << 8) | \ ++ ti->hsync_offset_lo); ++ mode->hsync_end = mode->hsync_start + \ ++ ((ti->hsync_pulse_width_hi << 8) | \ ++ ti->hsync_pulse_width_lo); ++ mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ ++ ti->hblank_lo); ++ mode->vsync_start = \ ++ mode->vdisplay + ((ti->vsync_offset_hi << 4) | \ ++ ti->vsync_offset_lo); ++ mode->vsync_end = \ ++ mode->vsync_start + ((ti->vsync_pulse_width_hi << 4) | \ ++ ti->vsync_pulse_width_lo); ++ mode->vtotal = mode->vdisplay + \ ++ ((ti->vblank_hi << 8) | ti->vblank_lo); ++ mode->clock = ti->pixel_clock * 10; ++#if 0 ++ printk(KERN_INFO "hdisplay is %d\n", mode->hdisplay); ++ printk(KERN_INFO "vdisplay is %d\n", mode->vdisplay); ++ printk(KERN_INFO "HSS is %d\n", mode->hsync_start); ++ printk(KERN_INFO "HSE is %d\n", mode->hsync_end); ++ printk(KERN_INFO "htotal is %d\n", mode->htotal); ++ printk(KERN_INFO "VSS is %d\n", mode->vsync_start); ++ printk(KERN_INFO "VSE is %d\n", mode->vsync_end); ++ printk(KERN_INFO "vtotal is %d\n", mode->vtotal); ++ printk(KERN_INFO "clock is %d\n", mode->clock); ++#endif ++ mode_dev->panel_fixed_mode = mode; ++ } ++ ++ /* Use the BIOS VBT mode if available */ ++ if (mode_dev->panel_fixed_mode == NULL && mode_dev->vbt_mode) ++ mode_dev->panel_fixed_mode = drm_mode_duplicate(dev, ++ mode_dev->vbt_mode); ++ ++ /* Then try the LVDS VBT mode */ ++ if (mode_dev->panel_fixed_mode == NULL) ++ if (dev_priv->lfp_lvds_vbt_mode) ++ mode_dev->panel_fixed_mode = ++ drm_mode_duplicate(dev, ++ dev_priv->lfp_lvds_vbt_mode); ++ /* Then guess */ ++ if (mode_dev->panel_fixed_mode == NULL) ++ mode_dev->panel_fixed_mode ++ = drm_mode_duplicate(dev, &lvds_configuration_modes[2]); ++ ++ drm_mode_set_name(mode_dev->panel_fixed_mode); ++ drm_mode_set_crtcinfo(mode_dev->panel_fixed_mode, 0); ++} ++ ++/** ++ * oaktrail_lvds_init - setup LVDS connectors on this device ++ * @dev: drm device ++ * ++ * Create the connector, register the LVDS DDC bus, and try to figure out what ++ * modes we can display on the LVDS panel (if present). ++ */ ++void oaktrail_lvds_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev) ++{ ++ struct psb_intel_encoder *psb_intel_encoder; ++ struct psb_intel_connector *psb_intel_connector; ++ struct drm_connector *connector; ++ struct drm_encoder *encoder; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct edid *edid; ++ struct i2c_adapter *i2c_adap; ++ struct drm_display_mode *scan; /* *modes, *bios_mode; */ ++ ++ psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); ++ if (!psb_intel_encoder) ++ return; ++ ++ psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL); ++ if (!psb_intel_connector) ++ goto failed_connector; ++ ++ connector = &psb_intel_connector->base; ++ encoder = &psb_intel_encoder->base; ++ dev_priv->is_lvds_on = true; ++ drm_connector_init(dev, connector, ++ &psb_intel_lvds_connector_funcs, ++ DRM_MODE_CONNECTOR_LVDS); ++ ++ drm_encoder_init(dev, encoder, &psb_intel_lvds_enc_funcs, ++ DRM_MODE_ENCODER_LVDS); ++ ++ psb_intel_connector_attach_encoder(psb_intel_connector, ++ psb_intel_encoder); ++ psb_intel_encoder->type = INTEL_OUTPUT_LVDS; ++ ++ drm_encoder_helper_add(encoder, &oaktrail_lvds_helper_funcs); ++ drm_connector_helper_add(connector, ++ &psb_intel_lvds_connector_helper_funcs); ++ connector->display_info.subpixel_order = SubPixelHorizontalRGB; ++ connector->interlace_allowed = false; ++ connector->doublescan_allowed = false; ++ ++ drm_connector_attach_property(connector, ++ dev->mode_config.scaling_mode_property, ++ DRM_MODE_SCALE_FULLSCREEN); ++ drm_connector_attach_property(connector, ++ dev_priv->backlight_property, ++ BRIGHTNESS_MAX_LEVEL); ++ ++ mode_dev->panel_wants_dither = false; ++ if (dev_priv->vbt_data.size != 0x00) ++ mode_dev->panel_wants_dither = (dev_priv->gct_data. ++ Panel_Port_Control & MRST_PANEL_8TO6_DITHER_ENABLE); ++ if (dev_priv->lvds_dither) ++ mode_dev->panel_wants_dither = 1; ++ ++ /* ++ * LVDS discovery: ++ * 1) check for EDID on DDC ++ * 2) check for VBT data ++ * 3) check to see if LVDS is already on ++ * if none of the above, no panel ++ * 4) make sure lid is open ++ * if closed, act like it's not there for now ++ */ ++ ++ i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus); ++ if (i2c_adap == NULL) ++ dev_err(dev->dev, "No ddc adapter available!\n"); ++ /* ++ * Attempt to get the fixed panel mode from DDC. Assume that the ++ * preferred mode is the right one. ++ */ ++ if (i2c_adap) { ++ edid = drm_get_edid(connector, i2c_adap); ++ if (edid) { ++ drm_mode_connector_update_edid_property(connector, ++ edid); ++ drm_add_edid_modes(connector, edid); ++ kfree(edid); ++ } ++ ++ list_for_each_entry(scan, &connector->probed_modes, head) { ++ if (scan->type & DRM_MODE_TYPE_PREFERRED) { ++ mode_dev->panel_fixed_mode = ++ drm_mode_duplicate(dev, scan); ++ goto out; /* FIXME: check for quirks */ ++ } ++ } ++ } ++ /* ++ * If we didn't get EDID, try geting panel timing ++ * from configuration data ++ */ ++ oaktrail_lvds_get_configuration_mode(dev, mode_dev); ++ ++ if (mode_dev->panel_fixed_mode) { ++ mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; ++ goto out; /* FIXME: check for quirks */ ++ } ++ ++ /* If we still don't have a mode after all that, give up. */ ++ if (!mode_dev->panel_fixed_mode) { ++ dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n"); ++ goto failed_find; ++ } ++ ++out: ++ drm_sysfs_connector_add(connector); ++ return; ++ ++failed_find: ++ dev_dbg(dev->dev, "No LVDS modes found, disabling.\n"); ++ if (psb_intel_encoder->ddc_bus) ++ psb_intel_i2c_destroy(psb_intel_encoder->ddc_bus); ++ ++/* failed_ddc: */ ++ ++ drm_encoder_cleanup(encoder); ++ drm_connector_cleanup(connector); ++ kfree(psb_intel_connector); ++failed_connector: ++ kfree(psb_intel_encoder); ++} ++ +diff --git a/drivers/gpu/drm/gma500/power.c b/drivers/gpu/drm/gma500/power.c +new file mode 100644 +index 0000000..889b854 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/power.c +@@ -0,0 +1,315 @@ ++/************************************************************************** ++ * Copyright (c) 2009-2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Benjamin Defnet ++ * Rajesh Poornachandran ++ * Massively reworked ++ * Alan Cox ++ */ ++ ++#include "power.h" ++#include "psb_drv.h" ++#include "psb_reg.h" ++#include "psb_intel_reg.h" ++#include ++#include ++ ++static struct mutex power_mutex; /* Serialize power ops */ ++static spinlock_t power_ctrl_lock; /* Serialize power claim */ ++ ++/** ++ * gma_power_init - initialise power manager ++ * @dev: our device ++ * ++ * Set up for power management tracking of our hardware. ++ */ ++void gma_power_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ /* FIXME: Move APM/OSPM base into relevant device code */ ++ dev_priv->apm_base = dev_priv->apm_reg & 0xffff; ++ dev_priv->ospm_base &= 0xffff; ++ ++ dev_priv->display_power = true; /* We start active */ ++ dev_priv->display_count = 0; /* Currently no users */ ++ dev_priv->suspended = false; /* And not suspended */ ++ spin_lock_init(&power_ctrl_lock); ++ mutex_init(&power_mutex); ++ ++ if (dev_priv->ops->init_pm) ++ dev_priv->ops->init_pm(dev); ++} ++ ++/** ++ * gma_power_uninit - end power manager ++ * @dev: device to end for ++ * ++ * Undo the effects of gma_power_init ++ */ ++void gma_power_uninit(struct drm_device *dev) ++{ ++ pm_runtime_disable(&dev->pdev->dev); ++ pm_runtime_set_suspended(&dev->pdev->dev); ++} ++ ++/** ++ * gma_suspend_display - suspend the display logic ++ * @dev: our DRM device ++ * ++ * Suspend the display logic of the graphics interface ++ */ ++static void gma_suspend_display(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (dev_priv->suspended) ++ return; ++ dev_priv->ops->save_regs(dev); ++ dev_priv->ops->power_down(dev); ++ dev_priv->display_power = false; ++} ++ ++/** ++ * gma_resume_display - resume display side logic ++ * ++ * Resume the display hardware restoring state and enabling ++ * as necessary. ++ */ ++static void gma_resume_display(struct pci_dev *pdev) ++{ ++ struct drm_device *dev = pci_get_drvdata(pdev); ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ /* turn on the display power island */ ++ dev_priv->ops->power_up(dev); ++ dev_priv->suspended = false; ++ dev_priv->display_power = true; ++ ++ PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); ++ pci_write_config_word(pdev, PSB_GMCH_CTRL, ++ dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); ++ dev_priv->ops->restore_regs(dev); ++} ++ ++/** ++ * gma_suspend_pci - suspend PCI side ++ * @pdev: PCI device ++ * ++ * Perform the suspend processing on our PCI device state ++ */ ++static void gma_suspend_pci(struct pci_dev *pdev) ++{ ++ struct drm_device *dev = pci_get_drvdata(pdev); ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int bsm, vbt; ++ ++ if (dev_priv->suspended) ++ return; ++ ++ pci_save_state(pdev); ++ pci_read_config_dword(pdev, 0x5C, &bsm); ++ dev_priv->regs.saveBSM = bsm; ++ pci_read_config_dword(pdev, 0xFC, &vbt); ++ dev_priv->regs.saveVBT = vbt; ++ pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr); ++ pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data); ++ ++ pci_disable_device(pdev); ++ pci_set_power_state(pdev, PCI_D3hot); ++ ++ dev_priv->suspended = true; ++} ++ ++/** ++ * gma_resume_pci - resume helper ++ * @dev: our PCI device ++ * ++ * Perform the resume processing on our PCI device state - rewrite ++ * register state and re-enable the PCI device ++ */ ++static bool gma_resume_pci(struct pci_dev *pdev) ++{ ++ struct drm_device *dev = pci_get_drvdata(pdev); ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int ret; ++ ++ if (!dev_priv->suspended) ++ return true; ++ ++ pci_set_power_state(pdev, PCI_D0); ++ pci_restore_state(pdev); ++ pci_write_config_dword(pdev, 0x5c, dev_priv->regs.saveBSM); ++ pci_write_config_dword(pdev, 0xFC, dev_priv->regs.saveVBT); ++ /* restoring MSI address and data in PCIx space */ ++ pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr); ++ pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data); ++ ret = pci_enable_device(pdev); ++ ++ if (ret != 0) ++ dev_err(&pdev->dev, "pci_enable failed: %d\n", ret); ++ else ++ dev_priv->suspended = false; ++ return !dev_priv->suspended; ++} ++ ++/** ++ * gma_power_suspend - bus callback for suspend ++ * @pdev: our PCI device ++ * @state: suspend type ++ * ++ * Called back by the PCI layer during a suspend of the system. We ++ * perform the necessary shut down steps and save enough state that ++ * we can undo this when resume is called. ++ */ ++int gma_power_suspend(struct device *_dev) ++{ ++ struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev); ++ struct drm_device *dev = pci_get_drvdata(pdev); ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ mutex_lock(&power_mutex); ++ if (!dev_priv->suspended) { ++ if (dev_priv->display_count) { ++ mutex_unlock(&power_mutex); ++ dev_err(dev->dev, "GPU hardware busy, cannot suspend\n"); ++ return -EBUSY; ++ } ++ psb_irq_uninstall(dev); ++ gma_suspend_display(dev); ++ gma_suspend_pci(pdev); ++ } ++ mutex_unlock(&power_mutex); ++ return 0; ++} ++ ++/** ++ * gma_power_resume - resume power ++ * @pdev: PCI device ++ * ++ * Resume the PCI side of the graphics and then the displays ++ */ ++int gma_power_resume(struct device *_dev) ++{ ++ struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev); ++ struct drm_device *dev = pci_get_drvdata(pdev); ++ ++ mutex_lock(&power_mutex); ++ gma_resume_pci(pdev); ++ gma_resume_display(pdev); ++ psb_irq_preinstall(dev); ++ psb_irq_postinstall(dev); ++ mutex_unlock(&power_mutex); ++ return 0; ++} ++ ++/** ++ * gma_power_is_on - returne true if power is on ++ * @dev: our DRM device ++ * ++ * Returns true if the display island power is on at this moment ++ */ ++bool gma_power_is_on(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ return dev_priv->display_power; ++} ++ ++/** ++ * gma_power_begin - begin requiring power ++ * @dev: our DRM device ++ * @force_on: true to force power on ++ * ++ * Begin an action that requires the display power island is enabled. ++ * We refcount the islands. ++ */ ++bool gma_power_begin(struct drm_device *dev, bool force_on) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&power_ctrl_lock, flags); ++ /* Power already on ? */ ++ if (dev_priv->display_power) { ++ dev_priv->display_count++; ++ pm_runtime_get(&dev->pdev->dev); ++ spin_unlock_irqrestore(&power_ctrl_lock, flags); ++ return true; ++ } ++ if (force_on == false) ++ goto out_false; ++ ++ /* Ok power up needed */ ++ ret = gma_resume_pci(dev->pdev); ++ if (ret == 0) { ++ psb_irq_preinstall(dev); ++ psb_irq_postinstall(dev); ++ pm_runtime_get(&dev->pdev->dev); ++ dev_priv->display_count++; ++ spin_unlock_irqrestore(&power_ctrl_lock, flags); ++ return true; ++ } ++out_false: ++ spin_unlock_irqrestore(&power_ctrl_lock, flags); ++ return false; ++} ++ ++/** ++ * gma_power_end - end use of power ++ * @dev: Our DRM device ++ * ++ * Indicate that one of our gma_power_begin() requested periods when ++ * the diplay island power is needed has completed. ++ */ ++void gma_power_end(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ unsigned long flags; ++ spin_lock_irqsave(&power_ctrl_lock, flags); ++ dev_priv->display_count--; ++ WARN_ON(dev_priv->display_count < 0); ++ spin_unlock_irqrestore(&power_ctrl_lock, flags); ++ pm_runtime_put(&dev->pdev->dev); ++} ++ ++int psb_runtime_suspend(struct device *dev) ++{ ++ return gma_power_suspend(dev); ++} ++ ++int psb_runtime_resume(struct device *dev) ++{ ++ return gma_power_resume(dev); ++} ++ ++int psb_runtime_idle(struct device *dev) ++{ ++ struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev)); ++ struct drm_psb_private *dev_priv = drmdev->dev_private; ++ if (dev_priv->display_count) ++ return 0; ++ else ++ return 1; ++} +diff --git a/drivers/gpu/drm/gma500/power.h b/drivers/gpu/drm/gma500/power.h +new file mode 100644 +index 0000000..1969d2e +--- /dev/null ++++ b/drivers/gpu/drm/gma500/power.h +@@ -0,0 +1,67 @@ ++/************************************************************************** ++ * Copyright (c) 2009-2011, Intel Corporation. ++ * All Rights Reserved. ++ ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Benjamin Defnet ++ * Rajesh Poornachandran ++ * Massively reworked ++ * Alan Cox ++ */ ++#ifndef _PSB_POWERMGMT_H_ ++#define _PSB_POWERMGMT_H_ ++ ++#include ++#include ++ ++void gma_power_init(struct drm_device *dev); ++void gma_power_uninit(struct drm_device *dev); ++ ++/* ++ * The kernel bus power management will call these functions ++ */ ++int gma_power_suspend(struct device *dev); ++int gma_power_resume(struct device *dev); ++ ++/* ++ * These are the functions the driver should use to wrap all hw access ++ * (i.e. register reads and writes) ++ */ ++bool gma_power_begin(struct drm_device *dev, bool force); ++void gma_power_end(struct drm_device *dev); ++ ++/* ++ * Use this function to do an instantaneous check for if the hw is on. ++ * Only use this in cases where you know the mutex is already held such ++ * as in irq install/uninstall and you need to ++ * prevent a deadlock situation. Otherwise use gma_power_begin(). ++ */ ++bool gma_power_is_on(struct drm_device *dev); ++ ++/* ++ * GFX-Runtime PM callbacks ++ */ ++int psb_runtime_suspend(struct device *dev); ++int psb_runtime_resume(struct device *dev); ++int psb_runtime_idle(struct device *dev); ++ ++#endif /*_PSB_POWERMGMT_H_*/ +diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c +new file mode 100644 +index 0000000..328a193 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_device.c +@@ -0,0 +1,332 @@ ++/************************************************************************** ++ * Copyright (c) 2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++ ++#include ++#include ++#include ++#include "gma_drm.h" ++#include "psb_drv.h" ++#include "psb_reg.h" ++#include "psb_intel_reg.h" ++#include "intel_bios.h" ++ ++ ++static int psb_output_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ psb_intel_lvds_init(dev, &dev_priv->mode_dev); ++ psb_intel_sdvo_init(dev, SDVOB); ++ return 0; ++} ++ ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ ++/* ++ * Poulsbo Backlight Interfaces ++ */ ++ ++#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ ++#define BLC_PWM_FREQ_CALC_CONSTANT 32 ++#define MHz 1000000 ++ ++#define PSB_BLC_PWM_PRECISION_FACTOR 10 ++#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE ++#define PSB_BLC_MIN_PWM_REG_FREQ 0x2 ++ ++#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) ++#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) ++ ++static int psb_brightness; ++static struct backlight_device *psb_backlight_device; ++ ++static int psb_get_brightness(struct backlight_device *bd) ++{ ++ /* return locally cached var instead of HW read (due to DPST etc.) */ ++ /* FIXME: ideally return actual value in case firmware fiddled with ++ it */ ++ return psb_brightness; ++} ++ ++ ++static int psb_backlight_setup(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ unsigned long core_clock; ++ /* u32 bl_max_freq; */ ++ /* unsigned long value; */ ++ u16 bl_max_freq; ++ uint32_t value; ++ uint32_t blc_pwm_precision_factor; ++ ++ /* get bl_max_freq and pol from dev_priv*/ ++ if (!dev_priv->lvds_bl) { ++ dev_err(dev->dev, "Has no valid LVDS backlight info\n"); ++ return -ENOENT; ++ } ++ bl_max_freq = dev_priv->lvds_bl->freq; ++ blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; ++ ++ core_clock = dev_priv->core_freq; ++ ++ value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; ++ value *= blc_pwm_precision_factor; ++ value /= bl_max_freq; ++ value /= blc_pwm_precision_factor; ++ ++ if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || ++ value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) ++ return -ERANGE; ++ else { ++ value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; ++ REG_WRITE(BLC_PWM_CTL, ++ (value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value)); ++ } ++ return 0; ++} ++ ++static int psb_set_brightness(struct backlight_device *bd) ++{ ++ struct drm_device *dev = bl_get_data(psb_backlight_device); ++ int level = bd->props.brightness; ++ ++ /* Percentage 1-100% being valid */ ++ if (level < 1) ++ level = 1; ++ ++ psb_intel_lvds_set_brightness(dev, level); ++ psb_brightness = level; ++ return 0; ++} ++ ++static const struct backlight_ops psb_ops = { ++ .get_brightness = psb_get_brightness, ++ .update_status = psb_set_brightness, ++}; ++ ++static int psb_backlight_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ int ret; ++ struct backlight_properties props; ++ ++ memset(&props, 0, sizeof(struct backlight_properties)); ++ props.max_brightness = 100; ++ props.type = BACKLIGHT_PLATFORM; ++ ++ psb_backlight_device = backlight_device_register("psb-bl", ++ NULL, (void *)dev, &psb_ops, &props); ++ if (IS_ERR(psb_backlight_device)) ++ return PTR_ERR(psb_backlight_device); ++ ++ ret = psb_backlight_setup(dev); ++ if (ret < 0) { ++ backlight_device_unregister(psb_backlight_device); ++ psb_backlight_device = NULL; ++ return ret; ++ } ++ psb_backlight_device->props.brightness = 100; ++ psb_backlight_device->props.max_brightness = 100; ++ backlight_update_status(psb_backlight_device); ++ dev_priv->backlight_device = psb_backlight_device; ++ return 0; ++} ++ ++#endif ++ ++/* ++ * Provide the Poulsbo specific chip logic and low level methods ++ * for power management ++ */ ++ ++static void psb_init_pm(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL); ++ gating &= ~3; /* Disable 2D clock gating */ ++ gating |= 1; ++ PSB_WSGX32(gating, PSB_CR_CLKGATECTL); ++ PSB_RSGX32(PSB_CR_CLKGATECTL); ++} ++ ++/** ++ * psb_save_display_registers - save registers lost on suspend ++ * @dev: our DRM device ++ * ++ * Save the state we need in order to be able to restore the interface ++ * upon resume from suspend ++ */ ++static int psb_save_display_registers(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct drm_crtc *crtc; ++ struct drm_connector *connector; ++ struct psb_state *regs = &dev_priv->regs.psb; ++ ++ /* Display arbitration control + watermarks */ ++ regs->saveDSPARB = PSB_RVDC32(DSPARB); ++ regs->saveDSPFW1 = PSB_RVDC32(DSPFW1); ++ regs->saveDSPFW2 = PSB_RVDC32(DSPFW2); ++ regs->saveDSPFW3 = PSB_RVDC32(DSPFW3); ++ regs->saveDSPFW4 = PSB_RVDC32(DSPFW4); ++ regs->saveDSPFW5 = PSB_RVDC32(DSPFW5); ++ regs->saveDSPFW6 = PSB_RVDC32(DSPFW6); ++ regs->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); ++ ++ /* Save crtc and output state */ ++ mutex_lock(&dev->mode_config.mutex); ++ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { ++ if (drm_helper_crtc_in_use(crtc)) ++ crtc->funcs->save(crtc); ++ } ++ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) ++ if (connector->funcs->save) ++ connector->funcs->save(connector); ++ ++ mutex_unlock(&dev->mode_config.mutex); ++ return 0; ++} ++ ++/** ++ * psb_restore_display_registers - restore lost register state ++ * @dev: our DRM device ++ * ++ * Restore register state that was lost during suspend and resume. ++ */ ++static int psb_restore_display_registers(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct drm_crtc *crtc; ++ struct drm_connector *connector; ++ struct psb_state *regs = &dev_priv->regs.psb; ++ ++ /* Display arbitration + watermarks */ ++ PSB_WVDC32(regs->saveDSPARB, DSPARB); ++ PSB_WVDC32(regs->saveDSPFW1, DSPFW1); ++ PSB_WVDC32(regs->saveDSPFW2, DSPFW2); ++ PSB_WVDC32(regs->saveDSPFW3, DSPFW3); ++ PSB_WVDC32(regs->saveDSPFW4, DSPFW4); ++ PSB_WVDC32(regs->saveDSPFW5, DSPFW5); ++ PSB_WVDC32(regs->saveDSPFW6, DSPFW6); ++ PSB_WVDC32(regs->saveCHICKENBIT, DSPCHICKENBIT); ++ ++ /*make sure VGA plane is off. it initializes to on after reset!*/ ++ PSB_WVDC32(0x80000000, VGACNTRL); ++ ++ mutex_lock(&dev->mode_config.mutex); ++ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) ++ if (drm_helper_crtc_in_use(crtc)) ++ crtc->funcs->restore(crtc); ++ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) ++ if (connector->funcs->restore) ++ connector->funcs->restore(connector); ++ ++ mutex_unlock(&dev->mode_config.mutex); ++ return 0; ++} ++ ++static int psb_power_down(struct drm_device *dev) ++{ ++ return 0; ++} ++ ++static int psb_power_up(struct drm_device *dev) ++{ ++ return 0; ++} ++ ++static void psb_get_core_freq(struct drm_device *dev) ++{ ++ uint32_t clock; ++ struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/ ++ /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/ ++ ++ pci_write_config_dword(pci_root, 0xD0, 0xD0050300); ++ pci_read_config_dword(pci_root, 0xD4, &clock); ++ pci_dev_put(pci_root); ++ ++ switch (clock & 0x07) { ++ case 0: ++ dev_priv->core_freq = 100; ++ break; ++ case 1: ++ dev_priv->core_freq = 133; ++ break; ++ case 2: ++ dev_priv->core_freq = 150; ++ break; ++ case 3: ++ dev_priv->core_freq = 178; ++ break; ++ case 4: ++ dev_priv->core_freq = 200; ++ break; ++ case 5: ++ case 6: ++ case 7: ++ dev_priv->core_freq = 266; ++ default: ++ dev_priv->core_freq = 0; ++ } ++} ++ ++static int psb_chip_setup(struct drm_device *dev) ++{ ++ psb_get_core_freq(dev); ++ gma_intel_setup_gmbus(dev); ++ gma_intel_opregion_init(dev); ++ psb_intel_init_bios(dev); ++ return 0; ++} ++ ++static void psb_chip_teardown(struct drm_device *dev) ++{ ++ gma_intel_teardown_gmbus(dev); ++} ++ ++const struct psb_ops psb_chip_ops = { ++ .name = "Poulsbo", ++ .accel_2d = 1, ++ .pipes = 2, ++ .crtcs = 2, ++ .sgx_offset = PSB_SGX_OFFSET, ++ .chip_setup = psb_chip_setup, ++ .chip_teardown = psb_chip_teardown, ++ ++ .crtc_helper = &psb_intel_helper_funcs, ++ .crtc_funcs = &psb_intel_crtc_funcs, ++ ++ .output_init = psb_output_init, ++ ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ .backlight_init = psb_backlight_init, ++#endif ++ ++ .init_pm = psb_init_pm, ++ .save_regs = psb_save_display_registers, ++ .restore_regs = psb_restore_display_registers, ++ .power_down = psb_power_down, ++ .power_up = psb_power_up, ++}; ++ +diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c +new file mode 100644 +index 0000000..09af2ff +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_drv.c +@@ -0,0 +1,706 @@ ++/************************************************************************** ++ * Copyright (c) 2007-2011, Intel Corporation. ++ * All Rights Reserved. ++ * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++ ++#include ++#include ++#include "gma_drm.h" ++#include "psb_drv.h" ++#include "framebuffer.h" ++#include "psb_reg.h" ++#include "psb_intel_reg.h" ++#include "intel_bios.h" ++#include "mid_bios.h" ++#include ++#include "power.h" ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int drm_psb_trap_pagefaults; ++ ++static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent); ++ ++MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults"); ++module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600); ++ ++ ++static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { ++ { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, ++ { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, ++#if defined(CONFIG_DRM_GMA600) ++ { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, ++ { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, ++ { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, ++ { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, ++ { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, ++ { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, ++ { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, ++ { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, ++ /* Atom E620 */ ++ { 0x8086, 0x4108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, ++#endif ++#if defined(CONFIG_DRM_MEDFIELD) ++ {0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, ++ {0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, ++ {0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, ++ {0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, ++ {0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, ++ {0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, ++ {0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, ++ {0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, ++#endif ++#if defined(CONFIG_DRM_GMA3600) ++ { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, ++ { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, ++ { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, ++ { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, ++ { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, ++ { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, ++ { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, ++ { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, ++#endif ++ { 0, } ++}; ++MODULE_DEVICE_TABLE(pci, pciidlist); ++ ++/* ++ * Standard IOCTLs. ++ */ ++ ++#define DRM_IOCTL_GMA_ADB \ ++ DRM_IOWR(DRM_GMA_ADB + DRM_COMMAND_BASE, uint32_t) ++#define DRM_IOCTL_GMA_MODE_OPERATION \ ++ DRM_IOWR(DRM_GMA_MODE_OPERATION + DRM_COMMAND_BASE, \ ++ struct drm_psb_mode_operation_arg) ++#define DRM_IOCTL_GMA_STOLEN_MEMORY \ ++ DRM_IOWR(DRM_GMA_STOLEN_MEMORY + DRM_COMMAND_BASE, \ ++ struct drm_psb_stolen_memory_arg) ++#define DRM_IOCTL_GMA_GAMMA \ ++ DRM_IOWR(DRM_GMA_GAMMA + DRM_COMMAND_BASE, \ ++ struct drm_psb_dpst_lut_arg) ++#define DRM_IOCTL_GMA_DPST_BL \ ++ DRM_IOWR(DRM_GMA_DPST_BL + DRM_COMMAND_BASE, \ ++ uint32_t) ++#define DRM_IOCTL_GMA_GET_PIPE_FROM_CRTC_ID \ ++ DRM_IOWR(DRM_GMA_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \ ++ struct drm_psb_get_pipe_from_crtc_id_arg) ++#define DRM_IOCTL_GMA_GEM_CREATE \ ++ DRM_IOWR(DRM_GMA_GEM_CREATE + DRM_COMMAND_BASE, \ ++ struct drm_psb_gem_create) ++#define DRM_IOCTL_GMA_GEM_MMAP \ ++ DRM_IOWR(DRM_GMA_GEM_MMAP + DRM_COMMAND_BASE, \ ++ struct drm_psb_gem_mmap) ++ ++static int psb_adb_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv); ++static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv); ++static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv); ++static int psb_gamma_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv); ++static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv); ++ ++static struct drm_ioctl_desc psb_ioctls[] = { ++ DRM_IOCTL_DEF_DRV(GMA_ADB, psb_adb_ioctl, DRM_AUTH), ++ DRM_IOCTL_DEF_DRV(GMA_MODE_OPERATION, psb_mode_operation_ioctl, ++ DRM_AUTH), ++ DRM_IOCTL_DEF_DRV(GMA_STOLEN_MEMORY, psb_stolen_memory_ioctl, ++ DRM_AUTH), ++ DRM_IOCTL_DEF_DRV(GMA_GAMMA, psb_gamma_ioctl, DRM_AUTH), ++ DRM_IOCTL_DEF_DRV(GMA_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH), ++ DRM_IOCTL_DEF_DRV(GMA_GET_PIPE_FROM_CRTC_ID, ++ psb_intel_get_pipe_from_crtc_id, 0), ++ DRM_IOCTL_DEF_DRV(GMA_GEM_CREATE, psb_gem_create_ioctl, ++ DRM_UNLOCKED | DRM_AUTH), ++ DRM_IOCTL_DEF_DRV(GMA_GEM_MMAP, psb_gem_mmap_ioctl, ++ DRM_UNLOCKED | DRM_AUTH), ++}; ++ ++static void psb_lastclose(struct drm_device *dev) ++{ ++ return; ++} ++ ++static void psb_do_takedown(struct drm_device *dev) ++{ ++} ++ ++static int psb_do_init(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_gtt *pg = &dev_priv->gtt; ++ ++ uint32_t stolen_gtt; ++ ++ int ret = -ENOMEM; ++ ++ if (pg->mmu_gatt_start & 0x0FFFFFFF) { ++ dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n"); ++ ret = -EINVAL; ++ goto out_err; ++ } ++ ++ ++ stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4; ++ stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT; ++ stolen_gtt = ++ (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages; ++ ++ dev_priv->gatt_free_offset = pg->mmu_gatt_start + ++ (stolen_gtt << PAGE_SHIFT) * 1024; ++ ++ if (1 || drm_debug) { ++ uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID); ++ uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION); ++ DRM_INFO("SGX core id = 0x%08x\n", core_id); ++ DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n", ++ (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >> ++ _PSB_CC_REVISION_MAJOR_SHIFT, ++ (core_rev & _PSB_CC_REVISION_MINOR_MASK) >> ++ _PSB_CC_REVISION_MINOR_SHIFT); ++ DRM_INFO ++ ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n", ++ (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >> ++ _PSB_CC_REVISION_MAINTENANCE_SHIFT, ++ (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >> ++ _PSB_CC_REVISION_DESIGNER_SHIFT); ++ } ++ ++ ++ spin_lock_init(&dev_priv->irqmask_lock); ++ spin_lock_init(&dev_priv->lock_2d); ++ ++ PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0); ++ PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1); ++ PSB_RSGX32(PSB_CR_BIF_BANK1); ++ PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK, ++ PSB_CR_BIF_CTRL); ++ psb_spank(dev_priv); ++ ++ /* mmu_gatt ?? */ ++ PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); ++ return 0; ++out_err: ++ psb_do_takedown(dev); ++ return ret; ++} ++ ++static int psb_driver_unload(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ /* Kill vblank etc here */ ++ ++ gma_backlight_exit(dev); ++ ++ psb_modeset_cleanup(dev); ++ ++ if (dev_priv) { ++ psb_lid_timer_takedown(dev_priv); ++ gma_intel_opregion_exit(dev); ++ ++ if (dev_priv->ops->chip_teardown) ++ dev_priv->ops->chip_teardown(dev); ++ psb_do_takedown(dev); ++ ++ ++ if (dev_priv->pf_pd) { ++ psb_mmu_free_pagedir(dev_priv->pf_pd); ++ dev_priv->pf_pd = NULL; ++ } ++ if (dev_priv->mmu) { ++ struct psb_gtt *pg = &dev_priv->gtt; ++ ++ down_read(&pg->sem); ++ psb_mmu_remove_pfn_sequence( ++ psb_mmu_get_default_pd ++ (dev_priv->mmu), ++ pg->mmu_gatt_start, ++ dev_priv->vram_stolen_size >> PAGE_SHIFT); ++ up_read(&pg->sem); ++ psb_mmu_driver_takedown(dev_priv->mmu); ++ dev_priv->mmu = NULL; ++ } ++ psb_gtt_takedown(dev); ++ if (dev_priv->scratch_page) { ++ __free_page(dev_priv->scratch_page); ++ dev_priv->scratch_page = NULL; ++ } ++ if (dev_priv->vdc_reg) { ++ iounmap(dev_priv->vdc_reg); ++ dev_priv->vdc_reg = NULL; ++ } ++ if (dev_priv->sgx_reg) { ++ iounmap(dev_priv->sgx_reg); ++ dev_priv->sgx_reg = NULL; ++ } ++ ++ kfree(dev_priv); ++ dev->dev_private = NULL; ++ ++ /*destroy VBT data*/ ++ psb_intel_destroy_bios(dev); ++ } ++ ++ gma_power_uninit(dev); ++ ++ return 0; ++} ++ ++ ++static int psb_driver_load(struct drm_device *dev, unsigned long chipset) ++{ ++ struct drm_psb_private *dev_priv; ++ unsigned long resource_start; ++ unsigned long irqflags; ++ int ret = -ENOMEM; ++ struct drm_connector *connector; ++ struct psb_intel_encoder *psb_intel_encoder; ++ ++ dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); ++ if (dev_priv == NULL) ++ return -ENOMEM; ++ ++ dev_priv->ops = (struct psb_ops *)chipset; ++ dev_priv->dev = dev; ++ dev->dev_private = (void *) dev_priv; ++ ++ pci_set_master(dev->pdev); ++ ++ if (!IS_PSB(dev)) { ++ if (pci_enable_msi(dev->pdev)) ++ dev_warn(dev->dev, "Enabling MSI failed!\n"); ++ } ++ ++ dev_priv->num_pipe = dev_priv->ops->pipes; ++ ++ resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE); ++ ++ dev_priv->vdc_reg = ++ ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE); ++ if (!dev_priv->vdc_reg) ++ goto out_err; ++ ++ dev_priv->sgx_reg = ioremap(resource_start + dev_priv->ops->sgx_offset, ++ PSB_SGX_SIZE); ++ if (!dev_priv->sgx_reg) ++ goto out_err; ++ ++ ret = dev_priv->ops->chip_setup(dev); ++ if (ret) ++ goto out_err; ++ ++ /* Init OSPM support */ ++ gma_power_init(dev); ++ ++ ret = -ENOMEM; ++ ++ dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO); ++ if (!dev_priv->scratch_page) ++ goto out_err; ++ ++ set_pages_uc(dev_priv->scratch_page, 1); ++ ++ ret = psb_gtt_init(dev, 0); ++ if (ret) ++ goto out_err; ++ ++ dev_priv->mmu = psb_mmu_driver_init((void *)0, ++ drm_psb_trap_pagefaults, 0, ++ dev_priv); ++ if (!dev_priv->mmu) ++ goto out_err; ++ ++ dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0); ++ if (!dev_priv->pf_pd) ++ goto out_err; ++ ++ psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0); ++ psb_mmu_set_pd_context(dev_priv->pf_pd, 1); ++ ++ ret = psb_do_init(dev); ++ if (ret) ++ return ret; ++ ++ PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE); ++ PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE); ++ ++/* igd_opregion_init(&dev_priv->opregion_dev); */ ++/* acpi_video_register(); */ ++ if (dev_priv->lid_state) ++ psb_lid_timer_init(dev_priv); ++ ++ ret = drm_vblank_init(dev, dev_priv->num_pipe); ++ if (ret) ++ goto out_err; ++ ++ /* ++ * Install interrupt handlers prior to powering off SGX or else we will ++ * crash. ++ */ ++ dev_priv->vdc_irq_mask = 0; ++ dev_priv->pipestat[0] = 0; ++ dev_priv->pipestat[1] = 0; ++ dev_priv->pipestat[2] = 0; ++ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); ++ PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); ++ PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R); ++ PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R); ++ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); ++ if (IS_PSB(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) ++ drm_irq_install(dev); ++ ++ dev->vblank_disable_allowed = 1; ++ ++ dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ ++ ++ dev->driver->get_vblank_counter = psb_get_vblank_counter; ++ ++ psb_modeset_init(dev); ++ psb_fbdev_init(dev); ++ drm_kms_helper_poll_init(dev); ++ ++ /* Only add backlight support if we have LVDS output */ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, ++ head) { ++ psb_intel_encoder = psb_intel_attached_encoder(connector); ++ ++ switch (psb_intel_encoder->type) { ++ case INTEL_OUTPUT_LVDS: ++ case INTEL_OUTPUT_MIPI: ++ ret = gma_backlight_init(dev); ++ break; ++ } ++ } ++ ++ if (ret) ++ return ret; ++#if 0 ++ /*enable runtime pm at last*/ ++ pm_runtime_enable(&dev->pdev->dev); ++ pm_runtime_set_active(&dev->pdev->dev); ++#endif ++ /*Intel drm driver load is done, continue doing pvr load*/ ++ return 0; ++out_err: ++ psb_driver_unload(dev); ++ return ret; ++} ++ ++static int psb_driver_device_is_agp(struct drm_device *dev) ++{ ++ return 0; ++} ++ ++static inline void get_brightness(struct backlight_device *bd) ++{ ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ if (bd) { ++ bd->props.brightness = bd->ops->get_brightness(bd); ++ backlight_update_status(bd); ++ } ++#endif ++} ++ ++static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv) ++{ ++ struct drm_psb_private *dev_priv = psb_priv(dev); ++ uint32_t *arg = data; ++ ++ dev_priv->blc_adj2 = *arg; ++ get_brightness(dev_priv->backlight_device); ++ return 0; ++} ++ ++static int psb_adb_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv) ++{ ++ struct drm_psb_private *dev_priv = psb_priv(dev); ++ uint32_t *arg = data; ++ ++ dev_priv->blc_adj1 = *arg; ++ get_brightness(dev_priv->backlight_device); ++ return 0; ++} ++ ++static int psb_gamma_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv) ++{ ++ struct drm_psb_dpst_lut_arg *lut_arg = data; ++ struct drm_mode_object *obj; ++ struct drm_crtc *crtc; ++ struct drm_connector *connector; ++ struct psb_intel_crtc *psb_intel_crtc; ++ int i = 0; ++ int32_t obj_id; ++ ++ obj_id = lut_arg->output_id; ++ obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR); ++ if (!obj) { ++ dev_dbg(dev->dev, "Invalid Connector object.\n"); ++ return -EINVAL; ++ } ++ ++ connector = obj_to_connector(obj); ++ crtc = connector->encoder->crtc; ++ psb_intel_crtc = to_psb_intel_crtc(crtc); ++ ++ for (i = 0; i < 256; i++) ++ psb_intel_crtc->lut_adj[i] = lut_arg->lut[i]; ++ ++ psb_intel_crtc_load_lut(crtc); ++ ++ return 0; ++} ++ ++static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv) ++{ ++ uint32_t obj_id; ++ uint16_t op; ++ struct drm_mode_modeinfo *umode; ++ struct drm_display_mode *mode = NULL; ++ struct drm_psb_mode_operation_arg *arg; ++ struct drm_mode_object *obj; ++ struct drm_connector *connector; ++ struct drm_connector_helper_funcs *connector_funcs; ++ int ret = 0; ++ int resp = MODE_OK; ++ ++ arg = (struct drm_psb_mode_operation_arg *)data; ++ obj_id = arg->obj_id; ++ op = arg->operation; ++ ++ switch (op) { ++ case PSB_MODE_OPERATION_MODE_VALID: ++ umode = &arg->mode; ++ ++ mutex_lock(&dev->mode_config.mutex); ++ ++ obj = drm_mode_object_find(dev, obj_id, ++ DRM_MODE_OBJECT_CONNECTOR); ++ if (!obj) { ++ ret = -EINVAL; ++ goto mode_op_out; ++ } ++ ++ connector = obj_to_connector(obj); ++ ++ mode = drm_mode_create(dev); ++ if (!mode) { ++ ret = -ENOMEM; ++ goto mode_op_out; ++ } ++ ++ /* drm_crtc_convert_umode(mode, umode); */ ++ { ++ mode->clock = umode->clock; ++ mode->hdisplay = umode->hdisplay; ++ mode->hsync_start = umode->hsync_start; ++ mode->hsync_end = umode->hsync_end; ++ mode->htotal = umode->htotal; ++ mode->hskew = umode->hskew; ++ mode->vdisplay = umode->vdisplay; ++ mode->vsync_start = umode->vsync_start; ++ mode->vsync_end = umode->vsync_end; ++ mode->vtotal = umode->vtotal; ++ mode->vscan = umode->vscan; ++ mode->vrefresh = umode->vrefresh; ++ mode->flags = umode->flags; ++ mode->type = umode->type; ++ strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN); ++ mode->name[DRM_DISPLAY_MODE_LEN-1] = 0; ++ } ++ ++ connector_funcs = (struct drm_connector_helper_funcs *) ++ connector->helper_private; ++ ++ if (connector_funcs->mode_valid) { ++ resp = connector_funcs->mode_valid(connector, mode); ++ arg->data = resp; ++ } ++ ++ /*do some clean up work*/ ++ if (mode) ++ drm_mode_destroy(dev, mode); ++mode_op_out: ++ mutex_unlock(&dev->mode_config.mutex); ++ return ret; ++ ++ default: ++ dev_dbg(dev->dev, "Unsupported psb mode operation\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file_priv) ++{ ++ struct drm_psb_private *dev_priv = psb_priv(dev); ++ struct drm_psb_stolen_memory_arg *arg = data; ++ ++ arg->base = dev_priv->stolen_base; ++ arg->size = dev_priv->vram_stolen_size; ++ ++ return 0; ++} ++ ++static int psb_driver_open(struct drm_device *dev, struct drm_file *priv) ++{ ++ return 0; ++} ++ ++static void psb_driver_close(struct drm_device *dev, struct drm_file *priv) ++{ ++} ++ ++static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct drm_file *file_priv = filp->private_data; ++ struct drm_device *dev = file_priv->minor->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ static unsigned int runtime_allowed; ++ ++ if (runtime_allowed == 1 && dev_priv->is_lvds_on) { ++ runtime_allowed++; ++ pm_runtime_allow(&dev->pdev->dev); ++ dev_priv->rpm_enabled = 1; ++ } ++ return drm_ioctl(filp, cmd, arg); ++ /* FIXME: do we need to wrap the other side of this */ ++} ++ ++ ++/* When a client dies: ++ * - Check for and clean up flipped page state ++ */ ++static void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv) ++{ ++} ++ ++static void psb_remove(struct pci_dev *pdev) ++{ ++ struct drm_device *dev = pci_get_drvdata(pdev); ++ drm_put_dev(dev); ++} ++ ++static const struct dev_pm_ops psb_pm_ops = { ++ .resume = gma_power_resume, ++ .suspend = gma_power_suspend, ++ .runtime_suspend = psb_runtime_suspend, ++ .runtime_resume = psb_runtime_resume, ++ .runtime_idle = psb_runtime_idle, ++}; ++ ++static struct vm_operations_struct psb_gem_vm_ops = { ++ .fault = psb_gem_fault, ++ .open = drm_gem_vm_open, ++ .close = drm_gem_vm_close, ++}; ++ ++static const struct file_operations psb_gem_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = psb_unlocked_ioctl, ++ .mmap = drm_gem_mmap, ++ .poll = drm_poll, ++ .fasync = drm_fasync, ++ .read = drm_read, ++}; ++ ++static struct drm_driver driver = { ++ .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \ ++ DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM , ++ .load = psb_driver_load, ++ .unload = psb_driver_unload, ++ ++ .ioctls = psb_ioctls, ++ .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls), ++ .device_is_agp = psb_driver_device_is_agp, ++ .irq_preinstall = psb_irq_preinstall, ++ .irq_postinstall = psb_irq_postinstall, ++ .irq_uninstall = psb_irq_uninstall, ++ .irq_handler = psb_irq_handler, ++ .enable_vblank = psb_enable_vblank, ++ .disable_vblank = psb_disable_vblank, ++ .get_vblank_counter = psb_get_vblank_counter, ++ .lastclose = psb_lastclose, ++ .open = psb_driver_open, ++ .preclose = psb_driver_preclose, ++ .postclose = psb_driver_close, ++ .reclaim_buffers = drm_core_reclaim_buffers, ++ ++ .gem_init_object = psb_gem_init_object, ++ .gem_free_object = psb_gem_free_object, ++ .gem_vm_ops = &psb_gem_vm_ops, ++ .dumb_create = psb_gem_dumb_create, ++ .dumb_map_offset = psb_gem_dumb_map_gtt, ++ .dumb_destroy = psb_gem_dumb_destroy, ++ .fops = &psb_gem_fops, ++ .name = DRIVER_NAME, ++ .desc = DRIVER_DESC, ++ .date = PSB_DRM_DRIVER_DATE, ++ .major = PSB_DRM_DRIVER_MAJOR, ++ .minor = PSB_DRM_DRIVER_MINOR, ++ .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL ++}; ++ ++static struct pci_driver psb_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = pciidlist, ++ .probe = psb_probe, ++ .remove = psb_remove, ++ .driver = { ++ .pm = &psb_pm_ops, ++ } ++}; ++ ++static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ return drm_get_pci_dev(pdev, ent, &driver); ++} ++ ++static int __init psb_init(void) ++{ ++ return drm_pci_init(&driver, &psb_pci_driver); ++} ++ ++static void __exit psb_exit(void) ++{ ++ drm_pci_exit(&driver, &psb_pci_driver); ++} ++ ++late_initcall(psb_init); ++module_exit(psb_exit); ++ ++MODULE_AUTHOR("Alan Cox and others"); ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h +new file mode 100644 +index 0000000..40ce2c9 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_drv.h +@@ -0,0 +1,993 @@ ++/************************************************************************** ++ * Copyright (c) 2007-2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ **************************************************************************/ ++ ++#ifndef _PSB_DRV_H_ ++#define _PSB_DRV_H_ ++ ++#include ++ ++#include ++#include "drm_global.h" ++#include "gem_glue.h" ++#include "gma_drm.h" ++#include "psb_reg.h" ++#include "psb_intel_drv.h" ++#include "gtt.h" ++#include "power.h" ++#include "oaktrail.h" ++ ++/* Append new drm mode definition here, align with libdrm definition */ ++#define DRM_MODE_SCALE_NO_SCALE 2 ++ ++enum { ++ CHIP_PSB_8108 = 0, /* Poulsbo */ ++ CHIP_PSB_8109 = 1, /* Poulsbo */ ++ CHIP_MRST_4100 = 2, /* Moorestown/Oaktrail */ ++ CHIP_MFLD_0130 = 3, /* Medfield */ ++}; ++ ++#define IS_PSB(dev) (((dev)->pci_device & 0xfffe) == 0x8108) ++#define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100) ++#define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130) ++ ++/* ++ * Driver definitions ++ */ ++ ++#define DRIVER_NAME "gma500" ++#define DRIVER_DESC "DRM driver for the Intel GMA500" ++ ++#define PSB_DRM_DRIVER_DATE "2011-06-06" ++#define PSB_DRM_DRIVER_MAJOR 1 ++#define PSB_DRM_DRIVER_MINOR 0 ++#define PSB_DRM_DRIVER_PATCHLEVEL 0 ++ ++/* ++ * Hardware offsets ++ */ ++#define PSB_VDC_OFFSET 0x00000000 ++#define PSB_VDC_SIZE 0x000080000 ++#define MRST_MMIO_SIZE 0x0000C0000 ++#define MDFLD_MMIO_SIZE 0x000100000 ++#define PSB_SGX_SIZE 0x8000 ++#define PSB_SGX_OFFSET 0x00040000 ++#define MRST_SGX_OFFSET 0x00080000 ++/* ++ * PCI resource identifiers ++ */ ++#define PSB_MMIO_RESOURCE 0 ++#define PSB_GATT_RESOURCE 2 ++#define PSB_GTT_RESOURCE 3 ++/* ++ * PCI configuration ++ */ ++#define PSB_GMCH_CTRL 0x52 ++#define PSB_BSM 0x5C ++#define _PSB_GMCH_ENABLED 0x4 ++#define PSB_PGETBL_CTL 0x2020 ++#define _PSB_PGETBL_ENABLED 0x00000001 ++#define PSB_SGX_2D_SLAVE_PORT 0x4000 ++ ++/* To get rid of */ ++#define PSB_TT_PRIV0_LIMIT (256*1024*1024) ++#define PSB_TT_PRIV0_PLIMIT (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT) ++ ++/* ++ * SGX side MMU definitions (these can probably go) ++ */ ++ ++/* ++ * Flags for external memory type field. ++ */ ++#define PSB_MMU_CACHED_MEMORY 0x0001 /* Bind to MMU only */ ++#define PSB_MMU_RO_MEMORY 0x0002 /* MMU RO memory */ ++#define PSB_MMU_WO_MEMORY 0x0004 /* MMU WO memory */ ++/* ++ * PTE's and PDE's ++ */ ++#define PSB_PDE_MASK 0x003FFFFF ++#define PSB_PDE_SHIFT 22 ++#define PSB_PTE_SHIFT 12 ++/* ++ * Cache control ++ */ ++#define PSB_PTE_VALID 0x0001 /* PTE / PDE valid */ ++#define PSB_PTE_WO 0x0002 /* Write only */ ++#define PSB_PTE_RO 0x0004 /* Read only */ ++#define PSB_PTE_CACHED 0x0008 /* CPU cache coherent */ ++ ++/* ++ * VDC registers and bits ++ */ ++#define PSB_MSVDX_CLOCKGATING 0x2064 ++#define PSB_TOPAZ_CLOCKGATING 0x2068 ++#define PSB_HWSTAM 0x2098 ++#define PSB_INSTPM 0x20C0 ++#define PSB_INT_IDENTITY_R 0x20A4 ++#define _MDFLD_PIPEC_EVENT_FLAG (1<<2) ++#define _MDFLD_PIPEC_VBLANK_FLAG (1<<3) ++#define _PSB_DPST_PIPEB_FLAG (1<<4) ++#define _MDFLD_PIPEB_EVENT_FLAG (1<<4) ++#define _PSB_VSYNC_PIPEB_FLAG (1<<5) ++#define _PSB_DPST_PIPEA_FLAG (1<<6) ++#define _PSB_PIPEA_EVENT_FLAG (1<<6) ++#define _PSB_VSYNC_PIPEA_FLAG (1<<7) ++#define _MDFLD_MIPIA_FLAG (1<<16) ++#define _MDFLD_MIPIC_FLAG (1<<17) ++#define _PSB_IRQ_SGX_FLAG (1<<18) ++#define _PSB_IRQ_MSVDX_FLAG (1<<19) ++#define _LNC_IRQ_TOPAZ_FLAG (1<<20) ++ ++#define _PSB_PIPE_EVENT_FLAG (_PSB_VSYNC_PIPEA_FLAG | \ ++ _PSB_VSYNC_PIPEB_FLAG) ++ ++/* This flag includes all the display IRQ bits excepts the vblank irqs. */ ++#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \ ++ _MDFLD_PIPEB_EVENT_FLAG | \ ++ _PSB_PIPEA_EVENT_FLAG | \ ++ _PSB_VSYNC_PIPEA_FLAG | \ ++ _MDFLD_MIPIA_FLAG | \ ++ _MDFLD_MIPIC_FLAG) ++#define PSB_INT_IDENTITY_R 0x20A4 ++#define PSB_INT_MASK_R 0x20A8 ++#define PSB_INT_ENABLE_R 0x20A0 ++ ++#define _PSB_MMU_ER_MASK 0x0001FF00 ++#define _PSB_MMU_ER_HOST (1 << 16) ++#define GPIOA 0x5010 ++#define GPIOB 0x5014 ++#define GPIOC 0x5018 ++#define GPIOD 0x501c ++#define GPIOE 0x5020 ++#define GPIOF 0x5024 ++#define GPIOG 0x5028 ++#define GPIOH 0x502c ++#define GPIO_CLOCK_DIR_MASK (1 << 0) ++#define GPIO_CLOCK_DIR_IN (0 << 1) ++#define GPIO_CLOCK_DIR_OUT (1 << 1) ++#define GPIO_CLOCK_VAL_MASK (1 << 2) ++#define GPIO_CLOCK_VAL_OUT (1 << 3) ++#define GPIO_CLOCK_VAL_IN (1 << 4) ++#define GPIO_CLOCK_PULLUP_DISABLE (1 << 5) ++#define GPIO_DATA_DIR_MASK (1 << 8) ++#define GPIO_DATA_DIR_IN (0 << 9) ++#define GPIO_DATA_DIR_OUT (1 << 9) ++#define GPIO_DATA_VAL_MASK (1 << 10) ++#define GPIO_DATA_VAL_OUT (1 << 11) ++#define GPIO_DATA_VAL_IN (1 << 12) ++#define GPIO_DATA_PULLUP_DISABLE (1 << 13) ++ ++#define VCLK_DIVISOR_VGA0 0x6000 ++#define VCLK_DIVISOR_VGA1 0x6004 ++#define VCLK_POST_DIV 0x6010 ++ ++#define PSB_COMM_2D (PSB_ENGINE_2D << 4) ++#define PSB_COMM_3D (PSB_ENGINE_3D << 4) ++#define PSB_COMM_TA (PSB_ENGINE_TA << 4) ++#define PSB_COMM_HP (PSB_ENGINE_HP << 4) ++#define PSB_COMM_USER_IRQ (1024 >> 2) ++#define PSB_COMM_USER_IRQ_LOST (PSB_COMM_USER_IRQ + 1) ++#define PSB_COMM_FW (2048 >> 2) ++ ++#define PSB_UIRQ_VISTEST 1 ++#define PSB_UIRQ_OOM_REPLY 2 ++#define PSB_UIRQ_FIRE_TA_REPLY 3 ++#define PSB_UIRQ_FIRE_RASTER_REPLY 4 ++ ++#define PSB_2D_SIZE (256*1024*1024) ++#define PSB_MAX_RELOC_PAGES 1024 ++ ++#define PSB_LOW_REG_OFFS 0x0204 ++#define PSB_HIGH_REG_OFFS 0x0600 ++ ++#define PSB_NUM_VBLANKS 2 ++ ++ ++#define PSB_2D_SIZE (256*1024*1024) ++#define PSB_MAX_RELOC_PAGES 1024 ++ ++#define PSB_LOW_REG_OFFS 0x0204 ++#define PSB_HIGH_REG_OFFS 0x0600 ++ ++#define PSB_NUM_VBLANKS 2 ++#define PSB_WATCHDOG_DELAY (DRM_HZ * 2) ++#define PSB_LID_DELAY (DRM_HZ / 10) ++ ++#define MDFLD_PNW_B0 0x04 ++#define MDFLD_PNW_C0 0x08 ++ ++#define MDFLD_DSR_2D_3D_0 (1 << 0) ++#define MDFLD_DSR_2D_3D_2 (1 << 1) ++#define MDFLD_DSR_CURSOR_0 (1 << 2) ++#define MDFLD_DSR_CURSOR_2 (1 << 3) ++#define MDFLD_DSR_OVERLAY_0 (1 << 4) ++#define MDFLD_DSR_OVERLAY_2 (1 << 5) ++#define MDFLD_DSR_MIPI_CONTROL (1 << 6) ++#define MDFLD_DSR_DAMAGE_MASK_0 ((1 << 0) | (1 << 2) | (1 << 4)) ++#define MDFLD_DSR_DAMAGE_MASK_2 ((1 << 1) | (1 << 3) | (1 << 5)) ++#define MDFLD_DSR_2D_3D (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2) ++ ++#define MDFLD_DSR_RR 45 ++#define MDFLD_DPU_ENABLE (1 << 31) ++#define MDFLD_DSR_FULLSCREEN (1 << 30) ++#define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR) ++ ++#define PSB_PWR_STATE_ON 1 ++#define PSB_PWR_STATE_OFF 2 ++ ++#define PSB_PMPOLICY_NOPM 0 ++#define PSB_PMPOLICY_CLOCKGATING 1 ++#define PSB_PMPOLICY_POWERDOWN 2 ++ ++#define PSB_PMSTATE_POWERUP 0 ++#define PSB_PMSTATE_CLOCKGATED 1 ++#define PSB_PMSTATE_POWERDOWN 2 ++#define PSB_PCIx_MSI_ADDR_LOC 0x94 ++#define PSB_PCIx_MSI_DATA_LOC 0x98 ++ ++/* Medfield crystal settings */ ++#define KSEL_CRYSTAL_19 1 ++#define KSEL_BYPASS_19 5 ++#define KSEL_BYPASS_25 6 ++#define KSEL_BYPASS_83_100 7 ++ ++struct opregion_header; ++struct opregion_acpi; ++struct opregion_swsci; ++struct opregion_asle; ++ ++struct psb_intel_opregion { ++ struct opregion_header *header; ++ struct opregion_acpi *acpi; ++ struct opregion_swsci *swsci; ++ struct opregion_asle *asle; ++ int enabled; ++}; ++ ++struct sdvo_device_mapping { ++ u8 initialized; ++ u8 dvo_port; ++ u8 slave_addr; ++ u8 dvo_wiring; ++ u8 i2c_pin; ++ u8 i2c_speed; ++ u8 ddc_pin; ++}; ++ ++struct intel_gmbus { ++ struct i2c_adapter adapter; ++ struct i2c_adapter *force_bit; ++ u32 reg0; ++}; ++ ++/* ++ * Register save state. This is used to hold the context when the ++ * device is powered off. In the case of Oaktrail this can (but does not ++ * yet) include screen blank. Operations occuring during the save ++ * update the register cache instead. ++ */ ++struct psb_state { ++ uint32_t saveDSPACNTR; ++ uint32_t saveDSPBCNTR; ++ uint32_t savePIPEACONF; ++ uint32_t savePIPEBCONF; ++ uint32_t savePIPEASRC; ++ uint32_t savePIPEBSRC; ++ uint32_t saveFPA0; ++ uint32_t saveFPA1; ++ uint32_t saveDPLL_A; ++ uint32_t saveDPLL_A_MD; ++ uint32_t saveHTOTAL_A; ++ uint32_t saveHBLANK_A; ++ uint32_t saveHSYNC_A; ++ uint32_t saveVTOTAL_A; ++ uint32_t saveVBLANK_A; ++ uint32_t saveVSYNC_A; ++ uint32_t saveDSPASTRIDE; ++ uint32_t saveDSPASIZE; ++ uint32_t saveDSPAPOS; ++ uint32_t saveDSPABASE; ++ uint32_t saveDSPASURF; ++ uint32_t saveDSPASTATUS; ++ uint32_t saveFPB0; ++ uint32_t saveFPB1; ++ uint32_t saveDPLL_B; ++ uint32_t saveDPLL_B_MD; ++ uint32_t saveHTOTAL_B; ++ uint32_t saveHBLANK_B; ++ uint32_t saveHSYNC_B; ++ uint32_t saveVTOTAL_B; ++ uint32_t saveVBLANK_B; ++ uint32_t saveVSYNC_B; ++ uint32_t saveDSPBSTRIDE; ++ uint32_t saveDSPBSIZE; ++ uint32_t saveDSPBPOS; ++ uint32_t saveDSPBBASE; ++ uint32_t saveDSPBSURF; ++ uint32_t saveDSPBSTATUS; ++ uint32_t saveVCLK_DIVISOR_VGA0; ++ uint32_t saveVCLK_DIVISOR_VGA1; ++ uint32_t saveVCLK_POST_DIV; ++ uint32_t saveVGACNTRL; ++ uint32_t saveADPA; ++ uint32_t saveLVDS; ++ uint32_t saveDVOA; ++ uint32_t saveDVOB; ++ uint32_t saveDVOC; ++ uint32_t savePP_ON; ++ uint32_t savePP_OFF; ++ uint32_t savePP_CONTROL; ++ uint32_t savePP_CYCLE; ++ uint32_t savePFIT_CONTROL; ++ uint32_t savePaletteA[256]; ++ uint32_t savePaletteB[256]; ++ uint32_t saveCLOCKGATING; ++ uint32_t saveDSPARB; ++ uint32_t saveDSPATILEOFF; ++ uint32_t saveDSPBTILEOFF; ++ uint32_t saveDSPAADDR; ++ uint32_t saveDSPBADDR; ++ uint32_t savePFIT_AUTO_RATIOS; ++ uint32_t savePFIT_PGM_RATIOS; ++ uint32_t savePP_ON_DELAYS; ++ uint32_t savePP_OFF_DELAYS; ++ uint32_t savePP_DIVISOR; ++ uint32_t saveBCLRPAT_A; ++ uint32_t saveBCLRPAT_B; ++ uint32_t saveDSPALINOFF; ++ uint32_t saveDSPBLINOFF; ++ uint32_t savePERF_MODE; ++ uint32_t saveDSPFW1; ++ uint32_t saveDSPFW2; ++ uint32_t saveDSPFW3; ++ uint32_t saveDSPFW4; ++ uint32_t saveDSPFW5; ++ uint32_t saveDSPFW6; ++ uint32_t saveCHICKENBIT; ++ uint32_t saveDSPACURSOR_CTRL; ++ uint32_t saveDSPBCURSOR_CTRL; ++ uint32_t saveDSPACURSOR_BASE; ++ uint32_t saveDSPBCURSOR_BASE; ++ uint32_t saveDSPACURSOR_POS; ++ uint32_t saveDSPBCURSOR_POS; ++ uint32_t save_palette_a[256]; ++ uint32_t save_palette_b[256]; ++ uint32_t saveOV_OVADD; ++ uint32_t saveOV_OGAMC0; ++ uint32_t saveOV_OGAMC1; ++ uint32_t saveOV_OGAMC2; ++ uint32_t saveOV_OGAMC3; ++ uint32_t saveOV_OGAMC4; ++ uint32_t saveOV_OGAMC5; ++ uint32_t saveOVC_OVADD; ++ uint32_t saveOVC_OGAMC0; ++ uint32_t saveOVC_OGAMC1; ++ uint32_t saveOVC_OGAMC2; ++ uint32_t saveOVC_OGAMC3; ++ uint32_t saveOVC_OGAMC4; ++ uint32_t saveOVC_OGAMC5; ++ ++ /* DPST register save */ ++ uint32_t saveHISTOGRAM_INT_CONTROL_REG; ++ uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG; ++ uint32_t savePWM_CONTROL_LOGIC; ++}; ++ ++struct medfield_state { ++ uint32_t saveDPLL_A; ++ uint32_t saveFPA0; ++ uint32_t savePIPEACONF; ++ uint32_t saveHTOTAL_A; ++ uint32_t saveHBLANK_A; ++ uint32_t saveHSYNC_A; ++ uint32_t saveVTOTAL_A; ++ uint32_t saveVBLANK_A; ++ uint32_t saveVSYNC_A; ++ uint32_t savePIPEASRC; ++ uint32_t saveDSPASTRIDE; ++ uint32_t saveDSPALINOFF; ++ uint32_t saveDSPATILEOFF; ++ uint32_t saveDSPASIZE; ++ uint32_t saveDSPAPOS; ++ uint32_t saveDSPASURF; ++ uint32_t saveDSPACNTR; ++ uint32_t saveDSPASTATUS; ++ uint32_t save_palette_a[256]; ++ uint32_t saveMIPI; ++ ++ uint32_t saveDPLL_B; ++ uint32_t saveFPB0; ++ uint32_t savePIPEBCONF; ++ uint32_t saveHTOTAL_B; ++ uint32_t saveHBLANK_B; ++ uint32_t saveHSYNC_B; ++ uint32_t saveVTOTAL_B; ++ uint32_t saveVBLANK_B; ++ uint32_t saveVSYNC_B; ++ uint32_t savePIPEBSRC; ++ uint32_t saveDSPBSTRIDE; ++ uint32_t saveDSPBLINOFF; ++ uint32_t saveDSPBTILEOFF; ++ uint32_t saveDSPBSIZE; ++ uint32_t saveDSPBPOS; ++ uint32_t saveDSPBSURF; ++ uint32_t saveDSPBCNTR; ++ uint32_t saveDSPBSTATUS; ++ uint32_t save_palette_b[256]; ++ ++ uint32_t savePIPECCONF; ++ uint32_t saveHTOTAL_C; ++ uint32_t saveHBLANK_C; ++ uint32_t saveHSYNC_C; ++ uint32_t saveVTOTAL_C; ++ uint32_t saveVBLANK_C; ++ uint32_t saveVSYNC_C; ++ uint32_t savePIPECSRC; ++ uint32_t saveDSPCSTRIDE; ++ uint32_t saveDSPCLINOFF; ++ uint32_t saveDSPCTILEOFF; ++ uint32_t saveDSPCSIZE; ++ uint32_t saveDSPCPOS; ++ uint32_t saveDSPCSURF; ++ uint32_t saveDSPCCNTR; ++ uint32_t saveDSPCSTATUS; ++ uint32_t save_palette_c[256]; ++ uint32_t saveMIPI_C; ++ ++ uint32_t savePFIT_CONTROL; ++ uint32_t savePFIT_PGM_RATIOS; ++ uint32_t saveHDMIPHYMISCCTL; ++ uint32_t saveHDMIB_CONTROL; ++}; ++ ++struct cdv_state { ++ uint32_t saveDSPCLK_GATE_D; ++ uint32_t saveRAMCLK_GATE_D; ++ uint32_t saveDSPARB; ++ uint32_t saveDSPFW[6]; ++ uint32_t saveADPA; ++ uint32_t savePP_CONTROL; ++ uint32_t savePFIT_PGM_RATIOS; ++ uint32_t saveLVDS; ++ uint32_t savePFIT_CONTROL; ++ uint32_t savePP_ON_DELAYS; ++ uint32_t savePP_OFF_DELAYS; ++ uint32_t savePP_CYCLE; ++ uint32_t saveVGACNTRL; ++ uint32_t saveIER; ++ uint32_t saveIMR; ++ u8 saveLBB; ++}; ++ ++struct psb_save_area { ++ uint32_t saveBSM; ++ uint32_t saveVBT; ++ union { ++ struct psb_state psb; ++ struct medfield_state mdfld; ++ struct cdv_state cdv; ++ }; ++ uint32_t saveBLC_PWM_CTL2; ++ uint32_t saveBLC_PWM_CTL; ++}; ++ ++struct psb_ops; ++ ++#define PSB_NUM_PIPE 3 ++ ++struct drm_psb_private { ++ struct drm_device *dev; ++ const struct psb_ops *ops; ++ ++ struct psb_gtt gtt; ++ ++ /* GTT Memory manager */ ++ struct psb_gtt_mm *gtt_mm; ++ struct page *scratch_page; ++ u32 *gtt_map; ++ uint32_t stolen_base; ++ void *vram_addr; ++ unsigned long vram_stolen_size; ++ int gtt_initialized; ++ u16 gmch_ctrl; /* Saved GTT setup */ ++ u32 pge_ctl; ++ ++ struct mutex gtt_mutex; ++ struct resource *gtt_mem; /* Our PCI resource */ ++ ++ struct psb_mmu_driver *mmu; ++ struct psb_mmu_pd *pf_pd; ++ ++ /* ++ * Register base ++ */ ++ ++ uint8_t *sgx_reg; ++ uint8_t *vdc_reg; ++ uint32_t gatt_free_offset; ++ ++ /* ++ * Fencing / irq. ++ */ ++ ++ uint32_t vdc_irq_mask; ++ uint32_t pipestat[PSB_NUM_PIPE]; ++ ++ spinlock_t irqmask_lock; ++ ++ /* ++ * Power ++ */ ++ ++ bool suspended; ++ bool display_power; ++ int display_count; ++ ++ /* ++ * Modesetting ++ */ ++ struct psb_intel_mode_device mode_dev; ++ ++ struct drm_crtc *plane_to_crtc_mapping[PSB_NUM_PIPE]; ++ struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE]; ++ uint32_t num_pipe; ++ ++ /* ++ * OSPM info (Power management base) (can go ?) ++ */ ++ uint32_t ospm_base; ++ ++ /* ++ * Sizes info ++ */ ++ ++ u32 fuse_reg_value; ++ u32 video_device_fuse; ++ ++ /* PCI revision ID for B0:D2:F0 */ ++ uint8_t platform_rev_id; ++ ++ /* gmbus */ ++ struct intel_gmbus *gmbus; ++ ++ /* Used by SDVO */ ++ int crt_ddc_pin; ++ /* FIXME: The mappings should be parsed from bios but for now we can ++ pretend there are no mappings available */ ++ struct sdvo_device_mapping sdvo_mappings[2]; ++ u32 hotplug_supported_mask; ++ struct drm_property *broadcast_rgb_property; ++ struct drm_property *force_audio_property; ++ ++ /* ++ * LVDS info ++ */ ++ int backlight_duty_cycle; /* restore backlight to this value */ ++ bool panel_wants_dither; ++ struct drm_display_mode *panel_fixed_mode; ++ struct drm_display_mode *lfp_lvds_vbt_mode; ++ struct drm_display_mode *sdvo_lvds_vbt_mode; ++ ++ struct bdb_lvds_backlight *lvds_bl; /* LVDS backlight info from VBT */ ++ struct psb_intel_i2c_chan *lvds_i2c_bus; /* FIXME: Remove this? */ ++ ++ /* Feature bits from the VBIOS */ ++ unsigned int int_tv_support:1; ++ unsigned int lvds_dither:1; ++ unsigned int lvds_vbt:1; ++ unsigned int int_crt_support:1; ++ unsigned int lvds_use_ssc:1; ++ int lvds_ssc_freq; ++ bool is_lvds_on; ++ bool is_mipi_on; ++ u32 mipi_ctrl_display; ++ ++ unsigned int core_freq; ++ uint32_t iLVDS_enable; ++ ++ /* Runtime PM state */ ++ int rpm_enabled; ++ ++ /* MID specific */ ++ struct oaktrail_vbt vbt_data; ++ struct oaktrail_gct_data gct_data; ++ ++ /* Oaktrail HDMI state */ ++ struct oaktrail_hdmi_dev *hdmi_priv; ++ ++ /* ++ * Register state ++ */ ++ ++ struct psb_save_area regs; ++ ++ /* MSI reg save */ ++ uint32_t msi_addr; ++ uint32_t msi_data; ++ ++ ++ /* ++ * LID-Switch ++ */ ++ spinlock_t lid_lock; ++ struct timer_list lid_timer; ++ struct psb_intel_opregion opregion; ++ u32 *lid_state; ++ u32 lid_last_state; ++ ++ /* ++ * Watchdog ++ */ ++ ++ uint32_t apm_reg; ++ uint16_t apm_base; ++ ++ /* ++ * Used for modifying backlight from ++ * xrandr -- consider removing and using HAL instead ++ */ ++ struct backlight_device *backlight_device; ++ struct drm_property *backlight_property; ++ uint32_t blc_adj1; ++ uint32_t blc_adj2; ++ ++ void *fbdev; ++ ++ /* 2D acceleration */ ++ spinlock_t lock_2d; ++ ++ /* ++ * Panel brightness ++ */ ++ int brightness; ++ int brightness_adjusted; ++ ++ bool dsr_enable; ++ u32 dsr_fb_update; ++ bool dpi_panel_on[3]; ++ void *dsi_configs[2]; ++ u32 bpp; ++ u32 bpp2; ++ ++ u32 pipeconf[3]; ++ u32 dspcntr[3]; ++ ++ int mdfld_panel_id; ++}; ++ ++ ++/* ++ * Operations for each board type ++ */ ++ ++struct psb_ops { ++ const char *name; ++ unsigned int accel_2d:1; ++ int pipes; /* Number of output pipes */ ++ int crtcs; /* Number of CRTCs */ ++ int sgx_offset; /* Base offset of SGX device */ ++ ++ /* Sub functions */ ++ struct drm_crtc_helper_funcs const *crtc_helper; ++ struct drm_crtc_funcs const *crtc_funcs; ++ ++ /* Setup hooks */ ++ int (*chip_setup)(struct drm_device *dev); ++ void (*chip_teardown)(struct drm_device *dev); ++ ++ /* Display management hooks */ ++ int (*output_init)(struct drm_device *dev); ++ /* Power management hooks */ ++ void (*init_pm)(struct drm_device *dev); ++ int (*save_regs)(struct drm_device *dev); ++ int (*restore_regs)(struct drm_device *dev); ++ int (*power_up)(struct drm_device *dev); ++ int (*power_down)(struct drm_device *dev); ++ ++ void (*lvds_bl_power)(struct drm_device *dev, bool on); ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ /* Backlight */ ++ int (*backlight_init)(struct drm_device *dev); ++#endif ++ int i2c_bus; /* I2C bus identifier for Moorestown */ ++}; ++ ++ ++ ++struct psb_mmu_driver; ++ ++extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int); ++extern int drm_pick_crtcs(struct drm_device *dev); ++ ++static inline struct drm_psb_private *psb_priv(struct drm_device *dev) ++{ ++ return (struct drm_psb_private *) dev->dev_private; ++} ++ ++/* ++ * MMU stuff. ++ */ ++ ++extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers, ++ int trap_pagefaults, ++ int invalid_type, ++ struct drm_psb_private *dev_priv); ++extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver); ++extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver ++ *driver); ++extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset, ++ uint32_t gtt_start, uint32_t gtt_pages); ++extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver, ++ int trap_pagefaults, ++ int invalid_type); ++extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd); ++extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot); ++extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd, ++ unsigned long address, ++ uint32_t num_pages); ++extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, ++ uint32_t start_pfn, ++ unsigned long address, ++ uint32_t num_pages, int type); ++extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual, ++ unsigned long *pfn); ++ ++/* ++ * Enable / disable MMU for different requestors. ++ */ ++ ++ ++extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context); ++extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages, ++ unsigned long address, uint32_t num_pages, ++ uint32_t desired_tile_stride, ++ uint32_t hw_tile_stride, int type); ++extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd, ++ unsigned long address, uint32_t num_pages, ++ uint32_t desired_tile_stride, ++ uint32_t hw_tile_stride); ++/* ++ *psb_irq.c ++ */ ++ ++extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS); ++extern int psb_irq_enable_dpst(struct drm_device *dev); ++extern int psb_irq_disable_dpst(struct drm_device *dev); ++extern void psb_irq_preinstall(struct drm_device *dev); ++extern int psb_irq_postinstall(struct drm_device *dev); ++extern void psb_irq_uninstall(struct drm_device *dev); ++extern void psb_irq_turn_on_dpst(struct drm_device *dev); ++extern void psb_irq_turn_off_dpst(struct drm_device *dev); ++ ++extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands); ++extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence); ++extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence); ++extern int psb_enable_vblank(struct drm_device *dev, int crtc); ++extern void psb_disable_vblank(struct drm_device *dev, int crtc); ++void ++psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); ++ ++void ++psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); ++ ++extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc); ++ ++/* ++ * intel_opregion.c ++ */ ++extern int gma_intel_opregion_init(struct drm_device *dev); ++extern int gma_intel_opregion_exit(struct drm_device *dev); ++ ++/* ++ * framebuffer.c ++ */ ++extern int psbfb_probed(struct drm_device *dev); ++extern int psbfb_remove(struct drm_device *dev, ++ struct drm_framebuffer *fb); ++/* ++ * accel_2d.c ++ */ ++extern void psbfb_copyarea(struct fb_info *info, ++ const struct fb_copyarea *region); ++extern int psbfb_sync(struct fb_info *info); ++extern void psb_spank(struct drm_psb_private *dev_priv); ++ ++/* ++ * psb_reset.c ++ */ ++ ++extern void psb_lid_timer_init(struct drm_psb_private *dev_priv); ++extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv); ++extern void psb_print_pagefault(struct drm_psb_private *dev_priv); ++ ++/* modesetting */ ++extern void psb_modeset_init(struct drm_device *dev); ++extern void psb_modeset_cleanup(struct drm_device *dev); ++extern int psb_fbdev_init(struct drm_device *dev); ++ ++/* backlight.c */ ++int gma_backlight_init(struct drm_device *dev); ++void gma_backlight_exit(struct drm_device *dev); ++ ++/* oaktrail_crtc.c */ ++extern const struct drm_crtc_helper_funcs oaktrail_helper_funcs; ++ ++/* oaktrail_lvds.c */ ++extern void oaktrail_lvds_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev); ++ ++/* psb_intel_display.c */ ++extern const struct drm_crtc_helper_funcs psb_intel_helper_funcs; ++extern const struct drm_crtc_funcs psb_intel_crtc_funcs; ++ ++/* psb_intel_lvds.c */ ++extern const struct drm_connector_helper_funcs ++ psb_intel_lvds_connector_helper_funcs; ++extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs; ++ ++/* gem.c */ ++extern int psb_gem_init_object(struct drm_gem_object *obj); ++extern void psb_gem_free_object(struct drm_gem_object *obj); ++extern int psb_gem_get_aperture(struct drm_device *dev, void *data, ++ struct drm_file *file); ++extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev, ++ struct drm_mode_create_dumb *args); ++extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, ++ uint32_t handle); ++extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, ++ uint32_t handle, uint64_t *offset); ++extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); ++extern int psb_gem_create_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file); ++extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *file); ++ ++/* psb_device.c */ ++extern const struct psb_ops psb_chip_ops; ++ ++/* oaktrail_device.c */ ++extern const struct psb_ops oaktrail_chip_ops; ++ ++/* mdlfd_device.c */ ++extern const struct psb_ops mdfld_chip_ops; ++ ++/* cdv_device.c */ ++extern const struct psb_ops cdv_chip_ops; ++ ++/* ++ * Debug print bits setting ++ */ ++#define PSB_D_GENERAL (1 << 0) ++#define PSB_D_INIT (1 << 1) ++#define PSB_D_IRQ (1 << 2) ++#define PSB_D_ENTRY (1 << 3) ++/* debug the get H/V BP/FP count */ ++#define PSB_D_HV (1 << 4) ++#define PSB_D_DBI_BF (1 << 5) ++#define PSB_D_PM (1 << 6) ++#define PSB_D_RENDER (1 << 7) ++#define PSB_D_REG (1 << 8) ++#define PSB_D_MSVDX (1 << 9) ++#define PSB_D_TOPAZ (1 << 10) ++ ++extern int drm_psb_no_fb; ++extern int drm_idle_check_interval; ++ ++/* ++ * Utilities ++ */ ++ ++static inline u32 MRST_MSG_READ32(uint port, uint offset) ++{ ++ int mcr = (0xD0<<24) | (port << 16) | (offset << 8); ++ uint32_t ret_val = 0; ++ struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); ++ pci_write_config_dword(pci_root, 0xD0, mcr); ++ pci_read_config_dword(pci_root, 0xD4, &ret_val); ++ pci_dev_put(pci_root); ++ return ret_val; ++} ++static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value) ++{ ++ int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0; ++ struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); ++ pci_write_config_dword(pci_root, 0xD4, value); ++ pci_write_config_dword(pci_root, 0xD0, mcr); ++ pci_dev_put(pci_root); ++} ++static inline u32 MDFLD_MSG_READ32(uint port, uint offset) ++{ ++ int mcr = (0x10<<24) | (port << 16) | (offset << 8); ++ uint32_t ret_val = 0; ++ struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); ++ pci_write_config_dword(pci_root, 0xD0, mcr); ++ pci_read_config_dword(pci_root, 0xD4, &ret_val); ++ pci_dev_put(pci_root); ++ return ret_val; ++} ++static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value) ++{ ++ int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; ++ struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); ++ pci_write_config_dword(pci_root, 0xD4, value); ++ pci_write_config_dword(pci_root, 0xD0, mcr); ++ pci_dev_put(pci_root); ++} ++ ++static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ return ioread32(dev_priv->vdc_reg + reg); ++} ++ ++#define REG_READ(reg) REGISTER_READ(dev, (reg)) ++ ++static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg, ++ uint32_t val) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ iowrite32((val), dev_priv->vdc_reg + (reg)); ++} ++ ++#define REG_WRITE(reg, val) REGISTER_WRITE(dev, (reg), (val)) ++ ++static inline void REGISTER_WRITE16(struct drm_device *dev, ++ uint32_t reg, uint32_t val) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ iowrite16((val), dev_priv->vdc_reg + (reg)); ++} ++ ++#define REG_WRITE16(reg, val) REGISTER_WRITE16(dev, (reg), (val)) ++ ++static inline void REGISTER_WRITE8(struct drm_device *dev, ++ uint32_t reg, uint32_t val) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ iowrite8((val), dev_priv->vdc_reg + (reg)); ++} ++ ++#define REG_WRITE8(reg, val) REGISTER_WRITE8(dev, (reg), (val)) ++ ++#define PSB_WVDC32(_val, _offs) iowrite32(_val, dev_priv->vdc_reg + (_offs)) ++#define PSB_RVDC32(_offs) ioread32(dev_priv->vdc_reg + (_offs)) ++ ++/* #define TRAP_SGX_PM_FAULT 1 */ ++#ifdef TRAP_SGX_PM_FAULT ++#define PSB_RSGX32(_offs) \ ++({ \ ++ if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) { \ ++ printk(KERN_ERR \ ++ "access sgx when it's off!! (READ) %s, %d\n", \ ++ __FILE__, __LINE__); \ ++ melay(1000); \ ++ } \ ++ ioread32(dev_priv->sgx_reg + (_offs)); \ ++}) ++#else ++#define PSB_RSGX32(_offs) ioread32(dev_priv->sgx_reg + (_offs)) ++#endif ++#define PSB_WSGX32(_val, _offs) iowrite32(_val, dev_priv->sgx_reg + (_offs)) ++ ++#define MSVDX_REG_DUMP 0 ++ ++#define PSB_WMSVDX32(_val, _offs) iowrite32(_val, dev_priv->msvdx_reg + (_offs)) ++#define PSB_RMSVDX32(_offs) ioread32(dev_priv->msvdx_reg + (_offs)) ++ ++#endif +diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c +new file mode 100644 +index 0000000..454a9d8 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_intel_display.c +@@ -0,0 +1,1450 @@ ++/* ++ * Copyright © 2006-2011 Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: ++ * Eric Anholt ++ */ ++ ++#include ++#include ++ ++#include ++#include "framebuffer.h" ++#include "psb_drv.h" ++#include "psb_intel_drv.h" ++#include "psb_intel_reg.h" ++#include "psb_intel_display.h" ++#include "power.h" ++ ++struct psb_intel_clock_t { ++ /* given values */ ++ int n; ++ int m1, m2; ++ int p1, p2; ++ /* derived values */ ++ int dot; ++ int vco; ++ int m; ++ int p; ++}; ++ ++struct psb_intel_range_t { ++ int min, max; ++}; ++ ++struct psb_intel_p2_t { ++ int dot_limit; ++ int p2_slow, p2_fast; ++}; ++ ++#define INTEL_P2_NUM 2 ++ ++struct psb_intel_limit_t { ++ struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1; ++ struct psb_intel_p2_t p2; ++}; ++ ++#define I8XX_DOT_MIN 25000 ++#define I8XX_DOT_MAX 350000 ++#define I8XX_VCO_MIN 930000 ++#define I8XX_VCO_MAX 1400000 ++#define I8XX_N_MIN 3 ++#define I8XX_N_MAX 16 ++#define I8XX_M_MIN 96 ++#define I8XX_M_MAX 140 ++#define I8XX_M1_MIN 18 ++#define I8XX_M1_MAX 26 ++#define I8XX_M2_MIN 6 ++#define I8XX_M2_MAX 16 ++#define I8XX_P_MIN 4 ++#define I8XX_P_MAX 128 ++#define I8XX_P1_MIN 2 ++#define I8XX_P1_MAX 33 ++#define I8XX_P1_LVDS_MIN 1 ++#define I8XX_P1_LVDS_MAX 6 ++#define I8XX_P2_SLOW 4 ++#define I8XX_P2_FAST 2 ++#define I8XX_P2_LVDS_SLOW 14 ++#define I8XX_P2_LVDS_FAST 14 /* No fast option */ ++#define I8XX_P2_SLOW_LIMIT 165000 ++ ++#define I9XX_DOT_MIN 20000 ++#define I9XX_DOT_MAX 400000 ++#define I9XX_VCO_MIN 1400000 ++#define I9XX_VCO_MAX 2800000 ++#define I9XX_N_MIN 3 ++#define I9XX_N_MAX 8 ++#define I9XX_M_MIN 70 ++#define I9XX_M_MAX 120 ++#define I9XX_M1_MIN 10 ++#define I9XX_M1_MAX 20 ++#define I9XX_M2_MIN 5 ++#define I9XX_M2_MAX 9 ++#define I9XX_P_SDVO_DAC_MIN 5 ++#define I9XX_P_SDVO_DAC_MAX 80 ++#define I9XX_P_LVDS_MIN 7 ++#define I9XX_P_LVDS_MAX 98 ++#define I9XX_P1_MIN 1 ++#define I9XX_P1_MAX 8 ++#define I9XX_P2_SDVO_DAC_SLOW 10 ++#define I9XX_P2_SDVO_DAC_FAST 5 ++#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000 ++#define I9XX_P2_LVDS_SLOW 14 ++#define I9XX_P2_LVDS_FAST 7 ++#define I9XX_P2_LVDS_SLOW_LIMIT 112000 ++ ++#define INTEL_LIMIT_I8XX_DVO_DAC 0 ++#define INTEL_LIMIT_I8XX_LVDS 1 ++#define INTEL_LIMIT_I9XX_SDVO_DAC 2 ++#define INTEL_LIMIT_I9XX_LVDS 3 ++ ++static const struct psb_intel_limit_t psb_intel_limits[] = { ++ { /* INTEL_LIMIT_I8XX_DVO_DAC */ ++ .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, ++ .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, ++ .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, ++ .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, ++ .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, ++ .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, ++ .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, ++ .p1 = {.min = I8XX_P1_MIN, .max = I8XX_P1_MAX}, ++ .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, ++ .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST}, ++ }, ++ { /* INTEL_LIMIT_I8XX_LVDS */ ++ .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, ++ .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, ++ .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, ++ .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, ++ .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, ++ .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, ++ .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, ++ .p1 = {.min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX}, ++ .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, ++ .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST}, ++ }, ++ { /* INTEL_LIMIT_I9XX_SDVO_DAC */ ++ .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, ++ .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, ++ .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, ++ .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, ++ .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, ++ .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, ++ .p = {.min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX}, ++ .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, ++ .p2 = {.dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, ++ .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = ++ I9XX_P2_SDVO_DAC_FAST}, ++ }, ++ { /* INTEL_LIMIT_I9XX_LVDS */ ++ .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, ++ .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, ++ .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, ++ .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, ++ .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, ++ .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, ++ .p = {.min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX}, ++ .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, ++ /* The single-channel range is 25-112Mhz, and dual-channel ++ * is 80-224Mhz. Prefer single channel as much as possible. ++ */ ++ .p2 = {.dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, ++ .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST}, ++ }, ++}; ++ ++static const struct psb_intel_limit_t *psb_intel_limit(struct drm_crtc *crtc) ++{ ++ const struct psb_intel_limit_t *limit; ++ ++ if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) ++ limit = &psb_intel_limits[INTEL_LIMIT_I9XX_LVDS]; ++ else ++ limit = &psb_intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; ++ return limit; ++} ++ ++/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ ++ ++static void i8xx_clock(int refclk, struct psb_intel_clock_t *clock) ++{ ++ clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); ++ clock->p = clock->p1 * clock->p2; ++ clock->vco = refclk * clock->m / (clock->n + 2); ++ clock->dot = clock->vco / clock->p; ++} ++ ++/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ ++ ++static void i9xx_clock(int refclk, struct psb_intel_clock_t *clock) ++{ ++ clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); ++ clock->p = clock->p1 * clock->p2; ++ clock->vco = refclk * clock->m / (clock->n + 2); ++ clock->dot = clock->vco / clock->p; ++} ++ ++static void psb_intel_clock(struct drm_device *dev, int refclk, ++ struct psb_intel_clock_t *clock) ++{ ++ return i9xx_clock(refclk, clock); ++} ++ ++/** ++ * Returns whether any output on the specified pipe is of the specified type ++ */ ++bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_mode_config *mode_config = &dev->mode_config; ++ struct drm_connector *l_entry; ++ ++ list_for_each_entry(l_entry, &mode_config->connector_list, head) { ++ if (l_entry->encoder && l_entry->encoder->crtc == crtc) { ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(l_entry); ++ if (psb_intel_encoder->type == type) ++ return true; ++ } ++ } ++ return false; ++} ++ ++#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } ++/** ++ * Returns whether the given set of divisors are valid for a given refclk with ++ * the given connectors. ++ */ ++ ++static bool psb_intel_PLL_is_valid(struct drm_crtc *crtc, ++ struct psb_intel_clock_t *clock) ++{ ++ const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); ++ ++ if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) ++ INTELPllInvalid("p1 out of range\n"); ++ if (clock->p < limit->p.min || limit->p.max < clock->p) ++ INTELPllInvalid("p out of range\n"); ++ if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) ++ INTELPllInvalid("m2 out of range\n"); ++ if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) ++ INTELPllInvalid("m1 out of range\n"); ++ if (clock->m1 <= clock->m2) ++ INTELPllInvalid("m1 <= m2\n"); ++ if (clock->m < limit->m.min || limit->m.max < clock->m) ++ INTELPllInvalid("m out of range\n"); ++ if (clock->n < limit->n.min || limit->n.max < clock->n) ++ INTELPllInvalid("n out of range\n"); ++ if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) ++ INTELPllInvalid("vco out of range\n"); ++ /* XXX: We may need to be checking "Dot clock" ++ * depending on the multiplier, connector, etc., ++ * rather than just a single range. ++ */ ++ if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) ++ INTELPllInvalid("dot out of range\n"); ++ ++ return true; ++} ++ ++/** ++ * Returns a set of divisors for the desired target clock with the given ++ * refclk, or FALSE. The returned values represent the clock equation: ++ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. ++ */ ++static bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target, ++ int refclk, ++ struct psb_intel_clock_t *best_clock) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_clock_t clock; ++ const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); ++ int err = target; ++ ++ if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && ++ (REG_READ(LVDS) & LVDS_PORT_EN) != 0) { ++ /* ++ * For LVDS, if the panel is on, just rely on its current ++ * settings for dual-channel. We haven't figured out how to ++ * reliably set up different single/dual channel state, if we ++ * even can. ++ */ ++ if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) == ++ LVDS_CLKB_POWER_UP) ++ clock.p2 = limit->p2.p2_fast; ++ else ++ clock.p2 = limit->p2.p2_slow; ++ } else { ++ if (target < limit->p2.dot_limit) ++ clock.p2 = limit->p2.p2_slow; ++ else ++ clock.p2 = limit->p2.p2_fast; ++ } ++ ++ memset(best_clock, 0, sizeof(*best_clock)); ++ ++ for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; ++ clock.m1++) { ++ for (clock.m2 = limit->m2.min; ++ clock.m2 < clock.m1 && clock.m2 <= limit->m2.max; ++ clock.m2++) { ++ for (clock.n = limit->n.min; ++ clock.n <= limit->n.max; clock.n++) { ++ for (clock.p1 = limit->p1.min; ++ clock.p1 <= limit->p1.max; ++ clock.p1++) { ++ int this_err; ++ ++ psb_intel_clock(dev, refclk, &clock); ++ ++ if (!psb_intel_PLL_is_valid ++ (crtc, &clock)) ++ continue; ++ ++ this_err = abs(clock.dot - target); ++ if (this_err < err) { ++ *best_clock = clock; ++ err = this_err; ++ } ++ } ++ } ++ } ++ } ++ ++ return err != target; ++} ++ ++void psb_intel_wait_for_vblank(struct drm_device *dev) ++{ ++ /* Wait for 20ms, i.e. one cycle at 50hz. */ ++ mdelay(20); ++} ++ ++static int psb_intel_pipe_set_base(struct drm_crtc *crtc, ++ int x, int y, struct drm_framebuffer *old_fb) ++{ ++ struct drm_device *dev = crtc->dev; ++ /* struct drm_i915_master_private *master_priv; */ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); ++ int pipe = psb_intel_crtc->pipe; ++ unsigned long start, offset; ++ int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); ++ int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); ++ int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; ++ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; ++ u32 dspcntr; ++ int ret = 0; ++ ++ if (!gma_power_begin(dev, true)) ++ return 0; ++ ++ /* no fb bound */ ++ if (!crtc->fb) { ++ dev_dbg(dev->dev, "No FB bound\n"); ++ goto psb_intel_pipe_cleaner; ++ } ++ ++ /* We are displaying this buffer, make sure it is actually loaded ++ into the GTT */ ++ ret = psb_gtt_pin(psbfb->gtt); ++ if (ret < 0) ++ goto psb_intel_pipe_set_base_exit; ++ start = psbfb->gtt->offset; ++ ++ offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); ++ ++ REG_WRITE(dspstride, crtc->fb->pitches[0]); ++ ++ dspcntr = REG_READ(dspcntr_reg); ++ dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; ++ ++ switch (crtc->fb->bits_per_pixel) { ++ case 8: ++ dspcntr |= DISPPLANE_8BPP; ++ break; ++ case 16: ++ if (crtc->fb->depth == 15) ++ dspcntr |= DISPPLANE_15_16BPP; ++ else ++ dspcntr |= DISPPLANE_16BPP; ++ break; ++ case 24: ++ case 32: ++ dspcntr |= DISPPLANE_32BPP_NO_ALPHA; ++ break; ++ default: ++ dev_err(dev->dev, "Unknown color depth\n"); ++ ret = -EINVAL; ++ psb_gtt_unpin(psbfb->gtt); ++ goto psb_intel_pipe_set_base_exit; ++ } ++ REG_WRITE(dspcntr_reg, dspcntr); ++ ++ ++ if (0 /* FIXMEAC - check what PSB needs */) { ++ REG_WRITE(dspbase, offset); ++ REG_READ(dspbase); ++ REG_WRITE(dspsurf, start); ++ REG_READ(dspsurf); ++ } else { ++ REG_WRITE(dspbase, start + offset); ++ REG_READ(dspbase); ++ } ++ ++psb_intel_pipe_cleaner: ++ /* If there was a previous display we can now unpin it */ ++ if (old_fb) ++ psb_gtt_unpin(to_psb_fb(old_fb)->gtt); ++ ++psb_intel_pipe_set_base_exit: ++ gma_power_end(dev); ++ return ret; ++} ++ ++/** ++ * Sets the power management mode of the pipe and plane. ++ * ++ * This code should probably grow support for turning the cursor off and back ++ * on appropriately at the same time as we're turning the pipe off/on. ++ */ ++static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode) ++{ ++ struct drm_device *dev = crtc->dev; ++ /* struct drm_i915_master_private *master_priv; */ ++ /* struct drm_i915_private *dev_priv = dev->dev_private; */ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; ++ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; ++ int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; ++ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; ++ u32 temp; ++ ++ /* XXX: When our outputs are all unaware of DPMS modes other than off ++ * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. ++ */ ++ switch (mode) { ++ case DRM_MODE_DPMS_ON: ++ case DRM_MODE_DPMS_STANDBY: ++ case DRM_MODE_DPMS_SUSPEND: ++ /* Enable the DPLL */ ++ temp = REG_READ(dpll_reg); ++ if ((temp & DPLL_VCO_ENABLE) == 0) { ++ REG_WRITE(dpll_reg, temp); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ } ++ ++ /* Enable the pipe */ ++ temp = REG_READ(pipeconf_reg); ++ if ((temp & PIPEACONF_ENABLE) == 0) ++ REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); ++ ++ /* Enable the plane */ ++ temp = REG_READ(dspcntr_reg); ++ if ((temp & DISPLAY_PLANE_ENABLE) == 0) { ++ REG_WRITE(dspcntr_reg, ++ temp | DISPLAY_PLANE_ENABLE); ++ /* Flush the plane changes */ ++ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); ++ } ++ ++ psb_intel_crtc_load_lut(crtc); ++ ++ /* Give the overlay scaler a chance to enable ++ * if it's on this pipe */ ++ /* psb_intel_crtc_dpms_video(crtc, true); TODO */ ++ break; ++ case DRM_MODE_DPMS_OFF: ++ /* Give the overlay scaler a chance to disable ++ * if it's on this pipe */ ++ /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ ++ ++ /* Disable the VGA plane that we never use */ ++ REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); ++ ++ /* Disable display plane */ ++ temp = REG_READ(dspcntr_reg); ++ if ((temp & DISPLAY_PLANE_ENABLE) != 0) { ++ REG_WRITE(dspcntr_reg, ++ temp & ~DISPLAY_PLANE_ENABLE); ++ /* Flush the plane changes */ ++ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); ++ REG_READ(dspbase_reg); ++ } ++ ++ /* Next, disable display pipes */ ++ temp = REG_READ(pipeconf_reg); ++ if ((temp & PIPEACONF_ENABLE) != 0) { ++ REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); ++ REG_READ(pipeconf_reg); ++ } ++ ++ /* Wait for vblank for the disable to take effect. */ ++ psb_intel_wait_for_vblank(dev); ++ ++ temp = REG_READ(dpll_reg); ++ if ((temp & DPLL_VCO_ENABLE) != 0) { ++ REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ } ++ ++ /* Wait for the clocks to turn off. */ ++ udelay(150); ++ break; ++ } ++ ++ /*Set FIFO Watermarks*/ ++ REG_WRITE(DSPARB, 0x3F3E); ++} ++ ++static void psb_intel_crtc_prepare(struct drm_crtc *crtc) ++{ ++ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; ++ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); ++} ++ ++static void psb_intel_crtc_commit(struct drm_crtc *crtc) ++{ ++ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; ++ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); ++} ++ ++void psb_intel_encoder_prepare(struct drm_encoder *encoder) ++{ ++ struct drm_encoder_helper_funcs *encoder_funcs = ++ encoder->helper_private; ++ /* lvds has its own version of prepare see psb_intel_lvds_prepare */ ++ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); ++} ++ ++void psb_intel_encoder_commit(struct drm_encoder *encoder) ++{ ++ struct drm_encoder_helper_funcs *encoder_funcs = ++ encoder->helper_private; ++ /* lvds has its own version of commit see psb_intel_lvds_commit */ ++ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); ++} ++ ++void psb_intel_encoder_destroy(struct drm_encoder *encoder) ++{ ++ struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); ++ ++ drm_encoder_cleanup(encoder); ++ kfree(intel_encoder); ++} ++ ++static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ return true; ++} ++ ++ ++/** ++ * Return the pipe currently connected to the panel fitter, ++ * or -1 if the panel fitter is not present or not in use ++ */ ++static int psb_intel_panel_fitter_pipe(struct drm_device *dev) ++{ ++ u32 pfit_control; ++ ++ pfit_control = REG_READ(PFIT_CONTROL); ++ ++ /* See if the panel fitter is in use */ ++ if ((pfit_control & PFIT_ENABLE) == 0) ++ return -1; ++ /* Must be on PIPE 1 for PSB */ ++ return 1; ++} ++ ++static int psb_intel_crtc_mode_set(struct drm_crtc *crtc, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode, ++ int x, int y, ++ struct drm_framebuffer *old_fb) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; ++ int pipe = psb_intel_crtc->pipe; ++ int fp_reg = (pipe == 0) ? FPA0 : FPB0; ++ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; ++ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; ++ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; ++ int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; ++ int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; ++ int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; ++ int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; ++ int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; ++ int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; ++ int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; ++ int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; ++ int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; ++ int refclk; ++ struct psb_intel_clock_t clock; ++ u32 dpll = 0, fp = 0, dspcntr, pipeconf; ++ bool ok, is_sdvo = false; ++ bool is_lvds = false, is_tv = false; ++ struct drm_mode_config *mode_config = &dev->mode_config; ++ struct drm_connector *connector; ++ ++ /* No scan out no play */ ++ if (crtc->fb == NULL) { ++ crtc_funcs->mode_set_base(crtc, x, y, old_fb); ++ return 0; ++ } ++ ++ list_for_each_entry(connector, &mode_config->connector_list, head) { ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ ++ if (!connector->encoder ++ || connector->encoder->crtc != crtc) ++ continue; ++ ++ switch (psb_intel_encoder->type) { ++ case INTEL_OUTPUT_LVDS: ++ is_lvds = true; ++ break; ++ case INTEL_OUTPUT_SDVO: ++ is_sdvo = true; ++ break; ++ case INTEL_OUTPUT_TVOUT: ++ is_tv = true; ++ break; ++ } ++ } ++ ++ refclk = 96000; ++ ++ ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, ++ &clock); ++ if (!ok) { ++ dev_err(dev->dev, "Couldn't find PLL settings for mode!\n"); ++ return 0; ++ } ++ ++ fp = clock.n << 16 | clock.m1 << 8 | clock.m2; ++ ++ dpll = DPLL_VGA_MODE_DIS; ++ if (is_lvds) { ++ dpll |= DPLLB_MODE_LVDS; ++ dpll |= DPLL_DVO_HIGH_SPEED; ++ } else ++ dpll |= DPLLB_MODE_DAC_SERIAL; ++ if (is_sdvo) { ++ int sdvo_pixel_multiply = ++ adjusted_mode->clock / mode->clock; ++ dpll |= DPLL_DVO_HIGH_SPEED; ++ dpll |= ++ (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; ++ } ++ ++ /* compute bitmask from p1 value */ ++ dpll |= (1 << (clock.p1 - 1)) << 16; ++ switch (clock.p2) { ++ case 5: ++ dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; ++ break; ++ case 7: ++ dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; ++ break; ++ case 10: ++ dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; ++ break; ++ case 14: ++ dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; ++ break; ++ } ++ ++ if (is_tv) { ++ /* XXX: just matching BIOS for now */ ++/* dpll |= PLL_REF_INPUT_TVCLKINBC; */ ++ dpll |= 3; ++ } ++ dpll |= PLL_REF_INPUT_DREFCLK; ++ ++ /* setup pipeconf */ ++ pipeconf = REG_READ(pipeconf_reg); ++ ++ /* Set up the display plane register */ ++ dspcntr = DISPPLANE_GAMMA_ENABLE; ++ ++ if (pipe == 0) ++ dspcntr |= DISPPLANE_SEL_PIPE_A; ++ else ++ dspcntr |= DISPPLANE_SEL_PIPE_B; ++ ++ dspcntr |= DISPLAY_PLANE_ENABLE; ++ pipeconf |= PIPEACONF_ENABLE; ++ dpll |= DPLL_VCO_ENABLE; ++ ++ ++ /* Disable the panel fitter if it was on our pipe */ ++ if (psb_intel_panel_fitter_pipe(dev) == pipe) ++ REG_WRITE(PFIT_CONTROL, 0); ++ ++ drm_mode_debug_printmodeline(mode); ++ ++ if (dpll & DPLL_VCO_ENABLE) { ++ REG_WRITE(fp_reg, fp); ++ REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); ++ REG_READ(dpll_reg); ++ udelay(150); ++ } ++ ++ /* The LVDS pin pair needs to be on before the DPLLs are enabled. ++ * This is an exception to the general rule that mode_set doesn't turn ++ * things on. ++ */ ++ if (is_lvds) { ++ u32 lvds = REG_READ(LVDS); ++ ++ lvds &= ~LVDS_PIPEB_SELECT; ++ if (pipe == 1) ++ lvds |= LVDS_PIPEB_SELECT; ++ ++ lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; ++ /* Set the B0-B3 data pairs corresponding to ++ * whether we're going to ++ * set the DPLLs for dual-channel mode or not. ++ */ ++ lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); ++ if (clock.p2 == 7) ++ lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; ++ ++ /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) ++ * appropriately here, but we need to look more ++ * thoroughly into how panels behave in the two modes. ++ */ ++ ++ REG_WRITE(LVDS, lvds); ++ REG_READ(LVDS); ++ } ++ ++ REG_WRITE(fp_reg, fp); ++ REG_WRITE(dpll_reg, dpll); ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ ++ /* write it again -- the BIOS does, after all */ ++ REG_WRITE(dpll_reg, dpll); ++ ++ REG_READ(dpll_reg); ++ /* Wait for the clocks to stabilize. */ ++ udelay(150); ++ ++ REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | ++ ((adjusted_mode->crtc_htotal - 1) << 16)); ++ REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ++ ((adjusted_mode->crtc_hblank_end - 1) << 16)); ++ REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ++ ((adjusted_mode->crtc_hsync_end - 1) << 16)); ++ REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ++ ((adjusted_mode->crtc_vtotal - 1) << 16)); ++ REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ++ ((adjusted_mode->crtc_vblank_end - 1) << 16)); ++ REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ++ ((adjusted_mode->crtc_vsync_end - 1) << 16)); ++ /* pipesrc and dspsize control the size that is scaled from, ++ * which should always be the user's requested size. ++ */ ++ REG_WRITE(dspsize_reg, ++ ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); ++ REG_WRITE(dsppos_reg, 0); ++ REG_WRITE(pipesrc_reg, ++ ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); ++ REG_WRITE(pipeconf_reg, pipeconf); ++ REG_READ(pipeconf_reg); ++ ++ psb_intel_wait_for_vblank(dev); ++ ++ REG_WRITE(dspcntr_reg, dspcntr); ++ ++ /* Flush the plane changes */ ++ crtc_funcs->mode_set_base(crtc, x, y, old_fb); ++ ++ psb_intel_wait_for_vblank(dev); ++ ++ return 0; ++} ++ ++/** Loads the palette/gamma unit for the CRTC with the prepared values */ ++void psb_intel_crtc_load_lut(struct drm_crtc *crtc) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *)dev->dev_private; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int palreg = PALETTE_A; ++ int i; ++ ++ /* The clocks have to be on to load the palette. */ ++ if (!crtc->enabled) ++ return; ++ ++ switch (psb_intel_crtc->pipe) { ++ case 0: ++ break; ++ case 1: ++ palreg = PALETTE_B; ++ break; ++ case 2: ++ palreg = PALETTE_C; ++ break; ++ default: ++ dev_err(dev->dev, "Illegal Pipe Number.\n"); ++ return; ++ } ++ ++ if (gma_power_begin(dev, false)) { ++ for (i = 0; i < 256; i++) { ++ REG_WRITE(palreg + 4 * i, ++ ((psb_intel_crtc->lut_r[i] + ++ psb_intel_crtc->lut_adj[i]) << 16) | ++ ((psb_intel_crtc->lut_g[i] + ++ psb_intel_crtc->lut_adj[i]) << 8) | ++ (psb_intel_crtc->lut_b[i] + ++ psb_intel_crtc->lut_adj[i])); ++ } ++ gma_power_end(dev); ++ } else { ++ for (i = 0; i < 256; i++) { ++ dev_priv->regs.psb.save_palette_a[i] = ++ ((psb_intel_crtc->lut_r[i] + ++ psb_intel_crtc->lut_adj[i]) << 16) | ++ ((psb_intel_crtc->lut_g[i] + ++ psb_intel_crtc->lut_adj[i]) << 8) | ++ (psb_intel_crtc->lut_b[i] + ++ psb_intel_crtc->lut_adj[i]); ++ } ++ ++ } ++} ++ ++/** ++ * Save HW states of giving crtc ++ */ ++static void psb_intel_crtc_save(struct drm_crtc *crtc) ++{ ++ struct drm_device *dev = crtc->dev; ++ /* struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *)dev->dev_private; */ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; ++ int pipeA = (psb_intel_crtc->pipe == 0); ++ uint32_t paletteReg; ++ int i; ++ ++ if (!crtc_state) { ++ dev_err(dev->dev, "No CRTC state found\n"); ++ return; ++ } ++ ++ crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR); ++ crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF); ++ crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC); ++ crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0); ++ crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1); ++ crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B); ++ crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B); ++ crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B); ++ crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B); ++ crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B); ++ crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B); ++ crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B); ++ crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE); ++ ++ /*NOTE: DSPSIZE DSPPOS only for psb*/ ++ crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE); ++ crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS); ++ ++ crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE); ++ ++ paletteReg = pipeA ? PALETTE_A : PALETTE_B; ++ for (i = 0; i < 256; ++i) ++ crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2)); ++} ++ ++/** ++ * Restore HW states of giving crtc ++ */ ++static void psb_intel_crtc_restore(struct drm_crtc *crtc) ++{ ++ struct drm_device *dev = crtc->dev; ++ /* struct drm_psb_private * dev_priv = ++ (struct drm_psb_private *)dev->dev_private; */ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; ++ /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */ ++ int pipeA = (psb_intel_crtc->pipe == 0); ++ uint32_t paletteReg; ++ int i; ++ ++ if (!crtc_state) { ++ dev_err(dev->dev, "No crtc state\n"); ++ return; ++ } ++ ++ if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) { ++ REG_WRITE(pipeA ? DPLL_A : DPLL_B, ++ crtc_state->saveDPLL & ~DPLL_VCO_ENABLE); ++ REG_READ(pipeA ? DPLL_A : DPLL_B); ++ udelay(150); ++ } ++ ++ REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0); ++ REG_READ(pipeA ? FPA0 : FPB0); ++ ++ REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1); ++ REG_READ(pipeA ? FPA1 : FPB1); ++ ++ REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL); ++ REG_READ(pipeA ? DPLL_A : DPLL_B); ++ udelay(150); ++ ++ REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL); ++ REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK); ++ REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC); ++ REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL); ++ REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK); ++ REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC); ++ REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE); ++ ++ REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE); ++ REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS); ++ ++ REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC); ++ REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); ++ REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF); ++ ++ psb_intel_wait_for_vblank(dev); ++ ++ REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR); ++ REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); ++ ++ psb_intel_wait_for_vblank(dev); ++ ++ paletteReg = pipeA ? PALETTE_A : PALETTE_B; ++ for (i = 0; i < 256; ++i) ++ REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]); ++} ++ ++static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, ++ struct drm_file *file_priv, ++ uint32_t handle, ++ uint32_t width, uint32_t height) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; ++ uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; ++ uint32_t temp; ++ size_t addr = 0; ++ struct gtt_range *gt; ++ struct drm_gem_object *obj; ++ int ret; ++ ++ /* if we want to turn of the cursor ignore width and height */ ++ if (!handle) { ++ /* turn off the cursor */ ++ temp = CURSOR_MODE_DISABLE; ++ ++ if (gma_power_begin(dev, false)) { ++ REG_WRITE(control, temp); ++ REG_WRITE(base, 0); ++ gma_power_end(dev); ++ } ++ ++ /* Unpin the old GEM object */ ++ if (psb_intel_crtc->cursor_obj) { ++ gt = container_of(psb_intel_crtc->cursor_obj, ++ struct gtt_range, gem); ++ psb_gtt_unpin(gt); ++ drm_gem_object_unreference(psb_intel_crtc->cursor_obj); ++ psb_intel_crtc->cursor_obj = NULL; ++ } ++ ++ return 0; ++ } ++ ++ /* Currently we only support 64x64 cursors */ ++ if (width != 64 || height != 64) { ++ dev_dbg(dev->dev, "we currently only support 64x64 cursors\n"); ++ return -EINVAL; ++ } ++ ++ obj = drm_gem_object_lookup(dev, file_priv, handle); ++ if (!obj) ++ return -ENOENT; ++ ++ if (obj->size < width * height * 4) { ++ dev_dbg(dev->dev, "buffer is to small\n"); ++ return -ENOMEM; ++ } ++ ++ gt = container_of(obj, struct gtt_range, gem); ++ ++ /* Pin the memory into the GTT */ ++ ret = psb_gtt_pin(gt); ++ if (ret) { ++ dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); ++ return ret; ++ } ++ ++ ++ addr = gt->offset; /* Or resource.start ??? */ ++ ++ psb_intel_crtc->cursor_addr = addr; ++ ++ temp = 0; ++ /* set the pipe for the cursor */ ++ temp |= (pipe << 28); ++ temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; ++ ++ if (gma_power_begin(dev, false)) { ++ REG_WRITE(control, temp); ++ REG_WRITE(base, addr); ++ gma_power_end(dev); ++ } ++ ++ /* unpin the old bo */ ++ if (psb_intel_crtc->cursor_obj) { ++ gt = container_of(psb_intel_crtc->cursor_obj, ++ struct gtt_range, gem); ++ psb_gtt_unpin(gt); ++ drm_gem_object_unreference(psb_intel_crtc->cursor_obj); ++ psb_intel_crtc->cursor_obj = obj; ++ } ++ return 0; ++} ++ ++static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ uint32_t temp = 0; ++ uint32_t addr; ++ ++ ++ if (x < 0) { ++ temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); ++ x = -x; ++ } ++ if (y < 0) { ++ temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); ++ y = -y; ++ } ++ ++ temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); ++ temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); ++ ++ addr = psb_intel_crtc->cursor_addr; ++ ++ if (gma_power_begin(dev, false)) { ++ REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); ++ REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr); ++ gma_power_end(dev); ++ } ++ return 0; ++} ++ ++void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, ++ u16 *green, u16 *blue, uint32_t type, uint32_t size) ++{ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int i; ++ ++ if (size != 256) ++ return; ++ ++ for (i = 0; i < 256; i++) { ++ psb_intel_crtc->lut_r[i] = red[i] >> 8; ++ psb_intel_crtc->lut_g[i] = green[i] >> 8; ++ psb_intel_crtc->lut_b[i] = blue[i] >> 8; ++ } ++ ++ psb_intel_crtc_load_lut(crtc); ++} ++ ++static int psb_crtc_set_config(struct drm_mode_set *set) ++{ ++ int ret; ++ struct drm_device *dev = set->crtc->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (!dev_priv->rpm_enabled) ++ return drm_crtc_helper_set_config(set); ++ ++ pm_runtime_forbid(&dev->pdev->dev); ++ ret = drm_crtc_helper_set_config(set); ++ pm_runtime_allow(&dev->pdev->dev); ++ return ret; ++} ++ ++/* Returns the clock of the currently programmed mode of the given pipe. */ ++static int psb_intel_crtc_clock_get(struct drm_device *dev, ++ struct drm_crtc *crtc) ++{ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ u32 dpll; ++ u32 fp; ++ struct psb_intel_clock_t clock; ++ bool is_lvds; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (gma_power_begin(dev, false)) { ++ dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B); ++ if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) ++ fp = REG_READ((pipe == 0) ? FPA0 : FPB0); ++ else ++ fp = REG_READ((pipe == 0) ? FPA1 : FPB1); ++ is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN); ++ gma_power_end(dev); ++ } else { ++ dpll = (pipe == 0) ? ++ dev_priv->regs.psb.saveDPLL_A : ++ dev_priv->regs.psb.saveDPLL_B; ++ ++ if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) ++ fp = (pipe == 0) ? ++ dev_priv->regs.psb.saveFPA0 : ++ dev_priv->regs.psb.saveFPB0; ++ else ++ fp = (pipe == 0) ? ++ dev_priv->regs.psb.saveFPA1 : ++ dev_priv->regs.psb.saveFPB1; ++ ++ is_lvds = (pipe == 1) && (dev_priv->regs.psb.saveLVDS & ++ LVDS_PORT_EN); ++ } ++ ++ clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; ++ clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; ++ clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; ++ ++ if (is_lvds) { ++ clock.p1 = ++ ffs((dpll & ++ DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> ++ DPLL_FPA01_P1_POST_DIV_SHIFT); ++ clock.p2 = 14; ++ ++ if ((dpll & PLL_REF_INPUT_MASK) == ++ PLLB_REF_INPUT_SPREADSPECTRUMIN) { ++ /* XXX: might not be 66MHz */ ++ i8xx_clock(66000, &clock); ++ } else ++ i8xx_clock(48000, &clock); ++ } else { ++ if (dpll & PLL_P1_DIVIDE_BY_TWO) ++ clock.p1 = 2; ++ else { ++ clock.p1 = ++ ((dpll & ++ DPLL_FPA01_P1_POST_DIV_MASK_I830) >> ++ DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; ++ } ++ if (dpll & PLL_P2_DIVIDE_BY_4) ++ clock.p2 = 4; ++ else ++ clock.p2 = 2; ++ ++ i8xx_clock(48000, &clock); ++ } ++ ++ /* XXX: It would be nice to validate the clocks, but we can't reuse ++ * i830PllIsValid() because it relies on the xf86_config connector ++ * configuration being accurate, which it isn't necessarily. ++ */ ++ ++ return clock.dot; ++} ++ ++/** Returns the currently programmed mode of the given pipe. */ ++struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, ++ struct drm_crtc *crtc) ++{ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ int pipe = psb_intel_crtc->pipe; ++ struct drm_display_mode *mode; ++ int htot; ++ int hsync; ++ int vtot; ++ int vsync; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (gma_power_begin(dev, false)) { ++ htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); ++ hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B); ++ vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); ++ vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B); ++ gma_power_end(dev); ++ } else { ++ htot = (pipe == 0) ? ++ dev_priv->regs.psb.saveHTOTAL_A : ++ dev_priv->regs.psb.saveHTOTAL_B; ++ hsync = (pipe == 0) ? ++ dev_priv->regs.psb.saveHSYNC_A : ++ dev_priv->regs.psb.saveHSYNC_B; ++ vtot = (pipe == 0) ? ++ dev_priv->regs.psb.saveVTOTAL_A : ++ dev_priv->regs.psb.saveVTOTAL_B; ++ vsync = (pipe == 0) ? ++ dev_priv->regs.psb.saveVSYNC_A : ++ dev_priv->regs.psb.saveVSYNC_B; ++ } ++ ++ mode = kzalloc(sizeof(*mode), GFP_KERNEL); ++ if (!mode) ++ return NULL; ++ ++ mode->clock = psb_intel_crtc_clock_get(dev, crtc); ++ mode->hdisplay = (htot & 0xffff) + 1; ++ mode->htotal = ((htot & 0xffff0000) >> 16) + 1; ++ mode->hsync_start = (hsync & 0xffff) + 1; ++ mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; ++ mode->vdisplay = (vtot & 0xffff) + 1; ++ mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; ++ mode->vsync_start = (vsync & 0xffff) + 1; ++ mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; ++ ++ drm_mode_set_name(mode); ++ drm_mode_set_crtcinfo(mode, 0); ++ ++ return mode; ++} ++ ++void psb_intel_crtc_destroy(struct drm_crtc *crtc) ++{ ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct gtt_range *gt; ++ ++ /* Unpin the old GEM object */ ++ if (psb_intel_crtc->cursor_obj) { ++ gt = container_of(psb_intel_crtc->cursor_obj, ++ struct gtt_range, gem); ++ psb_gtt_unpin(gt); ++ drm_gem_object_unreference(psb_intel_crtc->cursor_obj); ++ psb_intel_crtc->cursor_obj = NULL; ++ } ++ kfree(psb_intel_crtc->crtc_state); ++ drm_crtc_cleanup(crtc); ++ kfree(psb_intel_crtc); ++} ++ ++static void psb_intel_crtc_disable(struct drm_crtc *crtc) ++{ ++ struct gtt_range *gt; ++ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; ++ ++ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); ++ ++ if (crtc->fb) { ++ gt = to_psb_fb(crtc->fb)->gtt; ++ psb_gtt_unpin(gt); ++ } ++} ++ ++const struct drm_crtc_helper_funcs psb_intel_helper_funcs = { ++ .dpms = psb_intel_crtc_dpms, ++ .mode_fixup = psb_intel_crtc_mode_fixup, ++ .mode_set = psb_intel_crtc_mode_set, ++ .mode_set_base = psb_intel_pipe_set_base, ++ .prepare = psb_intel_crtc_prepare, ++ .commit = psb_intel_crtc_commit, ++ .disable = psb_intel_crtc_disable, ++}; ++ ++const struct drm_crtc_funcs psb_intel_crtc_funcs = { ++ .save = psb_intel_crtc_save, ++ .restore = psb_intel_crtc_restore, ++ .cursor_set = psb_intel_crtc_cursor_set, ++ .cursor_move = psb_intel_crtc_cursor_move, ++ .gamma_set = psb_intel_crtc_gamma_set, ++ .set_config = psb_crtc_set_config, ++ .destroy = psb_intel_crtc_destroy, ++}; ++ ++/* ++ * Set the default value of cursor control and base register ++ * to zero. This is a workaround for h/w defect on Oaktrail ++ */ ++static void psb_intel_cursor_init(struct drm_device *dev, int pipe) ++{ ++ u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR }; ++ u32 base[3] = { CURABASE, CURBBASE, CURCBASE }; ++ ++ REG_WRITE(control[pipe], 0); ++ REG_WRITE(base[pipe], 0); ++} ++ ++void psb_intel_crtc_init(struct drm_device *dev, int pipe, ++ struct psb_intel_mode_device *mode_dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_crtc *psb_intel_crtc; ++ int i; ++ uint16_t *r_base, *g_base, *b_base; ++ ++ /* We allocate a extra array of drm_connector pointers ++ * for fbdev after the crtc */ ++ psb_intel_crtc = ++ kzalloc(sizeof(struct psb_intel_crtc) + ++ (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), ++ GFP_KERNEL); ++ if (psb_intel_crtc == NULL) ++ return; ++ ++ psb_intel_crtc->crtc_state = ++ kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL); ++ if (!psb_intel_crtc->crtc_state) { ++ dev_err(dev->dev, "Crtc state error: No memory\n"); ++ kfree(psb_intel_crtc); ++ return; ++ } ++ ++ /* Set the CRTC operations from the chip specific data */ ++ drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs); ++ ++ drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256); ++ psb_intel_crtc->pipe = pipe; ++ psb_intel_crtc->plane = pipe; ++ ++ r_base = psb_intel_crtc->base.gamma_store; ++ g_base = r_base + 256; ++ b_base = g_base + 256; ++ for (i = 0; i < 256; i++) { ++ psb_intel_crtc->lut_r[i] = i; ++ psb_intel_crtc->lut_g[i] = i; ++ psb_intel_crtc->lut_b[i] = i; ++ r_base[i] = i << 8; ++ g_base[i] = i << 8; ++ b_base[i] = i << 8; ++ ++ psb_intel_crtc->lut_adj[i] = 0; ++ } ++ ++ psb_intel_crtc->mode_dev = mode_dev; ++ psb_intel_crtc->cursor_addr = 0; ++ ++ drm_crtc_helper_add(&psb_intel_crtc->base, ++ dev_priv->ops->crtc_helper); ++ ++ /* Setup the array of drm_connector pointer array */ ++ psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base; ++ BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || ++ dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL); ++ dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] = ++ &psb_intel_crtc->base; ++ dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] = ++ &psb_intel_crtc->base; ++ psb_intel_crtc->mode_set.connectors = ++ (struct drm_connector **) (psb_intel_crtc + 1); ++ psb_intel_crtc->mode_set.num_connectors = 0; ++ psb_intel_cursor_init(dev, pipe); ++} ++ ++int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, ++ struct drm_file *file_priv) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data; ++ struct drm_mode_object *drmmode_obj; ++ struct psb_intel_crtc *crtc; ++ ++ if (!dev_priv) { ++ dev_err(dev->dev, "called with no initialization\n"); ++ return -EINVAL; ++ } ++ ++ drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id, ++ DRM_MODE_OBJECT_CRTC); ++ ++ if (!drmmode_obj) { ++ dev_err(dev->dev, "no such CRTC id\n"); ++ return -EINVAL; ++ } ++ ++ crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj)); ++ pipe_from_crtc_id->pipe = crtc->pipe; ++ ++ return 0; ++} ++ ++struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) ++{ ++ struct drm_crtc *crtc = NULL; ++ ++ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ if (psb_intel_crtc->pipe == pipe) ++ break; ++ } ++ return crtc; ++} ++ ++int psb_intel_connector_clones(struct drm_device *dev, int type_mask) ++{ ++ int index_mask = 0; ++ struct drm_connector *connector; ++ int entry = 0; ++ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, ++ head) { ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ if (type_mask & (1 << psb_intel_encoder->type)) ++ index_mask |= (1 << entry); ++ entry++; ++ } ++ return index_mask; ++} ++ ++/* current intel driver doesn't take advantage of encoders ++ always give back the encoder for the connector ++*/ ++struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector) ++{ ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ ++ return &psb_intel_encoder->base; ++} ++ ++void psb_intel_connector_attach_encoder(struct psb_intel_connector *connector, ++ struct psb_intel_encoder *encoder) ++{ ++ connector->encoder = encoder; ++ drm_mode_connector_attach_encoder(&connector->base, ++ &encoder->base); ++} +diff --git a/drivers/gpu/drm/gma500/psb_intel_display.h b/drivers/gpu/drm/gma500/psb_intel_display.h +new file mode 100644 +index 0000000..535b49a +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_intel_display.h +@@ -0,0 +1,28 @@ ++/* copyright (c) 2008, Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: ++ * Eric Anholt ++ */ ++ ++#ifndef _INTEL_DISPLAY_H_ ++#define _INTEL_DISPLAY_H_ ++ ++bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type); ++void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, ++ u16 *green, u16 *blue, uint32_t type, uint32_t size); ++void psb_intel_crtc_destroy(struct drm_crtc *crtc); ++ ++#endif +diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h +new file mode 100644 +index 0000000..f40535e +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_intel_drv.h +@@ -0,0 +1,289 @@ ++/* ++ * Copyright (c) 2009-2011, Intel Corporation. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ */ ++ ++#ifndef __INTEL_DRV_H__ ++#define __INTEL_DRV_H__ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * Display related stuff ++ */ ++ ++/* store information about an Ixxx DVO */ ++/* The i830->i865 use multiple DVOs with multiple i2cs */ ++/* the i915, i945 have a single sDVO i2c bus - which is different */ ++#define MAX_OUTPUTS 6 ++/* maximum connectors per crtcs in the mode set */ ++#define INTELFB_CONN_LIMIT 4 ++ ++#define INTEL_I2C_BUS_DVO 1 ++#define INTEL_I2C_BUS_SDVO 2 ++ ++/* Intel Pipe Clone Bit */ ++#define INTEL_HDMIB_CLONE_BIT 1 ++#define INTEL_HDMIC_CLONE_BIT 2 ++#define INTEL_HDMID_CLONE_BIT 3 ++#define INTEL_HDMIE_CLONE_BIT 4 ++#define INTEL_HDMIF_CLONE_BIT 5 ++#define INTEL_SDVO_NON_TV_CLONE_BIT 6 ++#define INTEL_SDVO_TV_CLONE_BIT 7 ++#define INTEL_SDVO_LVDS_CLONE_BIT 8 ++#define INTEL_ANALOG_CLONE_BIT 9 ++#define INTEL_TV_CLONE_BIT 10 ++#define INTEL_DP_B_CLONE_BIT 11 ++#define INTEL_DP_C_CLONE_BIT 12 ++#define INTEL_DP_D_CLONE_BIT 13 ++#define INTEL_LVDS_CLONE_BIT 14 ++#define INTEL_DVO_TMDS_CLONE_BIT 15 ++#define INTEL_DVO_LVDS_CLONE_BIT 16 ++#define INTEL_EDP_CLONE_BIT 17 ++ ++/* these are outputs from the chip - integrated only ++ * external chips are via DVO or SDVO output */ ++#define INTEL_OUTPUT_UNUSED 0 ++#define INTEL_OUTPUT_ANALOG 1 ++#define INTEL_OUTPUT_DVO 2 ++#define INTEL_OUTPUT_SDVO 3 ++#define INTEL_OUTPUT_LVDS 4 ++#define INTEL_OUTPUT_TVOUT 5 ++#define INTEL_OUTPUT_HDMI 6 ++#define INTEL_OUTPUT_MIPI 7 ++#define INTEL_OUTPUT_MIPI2 8 ++ ++#define INTEL_DVO_CHIP_NONE 0 ++#define INTEL_DVO_CHIP_LVDS 1 ++#define INTEL_DVO_CHIP_TMDS 2 ++#define INTEL_DVO_CHIP_TVOUT 4 ++ ++#define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0) ++#define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT) ++ ++static inline void ++psb_intel_mode_set_pixel_multiplier(struct drm_display_mode *mode, ++ int multiplier) ++{ ++ mode->clock *= multiplier; ++ mode->private_flags |= multiplier; ++} ++ ++static inline int ++psb_intel_mode_get_pixel_multiplier(const struct drm_display_mode *mode) ++{ ++ return (mode->private_flags & INTEL_MODE_PIXEL_MULTIPLIER_MASK) ++ >> INTEL_MODE_PIXEL_MULTIPLIER_SHIFT; ++} ++ ++ ++/* ++ * Hold information useally put on the device driver privates here, ++ * since it needs to be shared across multiple of devices drivers privates. ++ */ ++struct psb_intel_mode_device { ++ ++ /* ++ * Abstracted memory manager operations ++ */ ++ size_t(*bo_offset) (struct drm_device *dev, void *bo); ++ ++ /* ++ * Cursor (Can go ?) ++ */ ++ int cursor_needs_physical; ++ ++ /* ++ * LVDS info ++ */ ++ int backlight_duty_cycle; /* restore backlight to this value */ ++ bool panel_wants_dither; ++ struct drm_display_mode *panel_fixed_mode; ++ struct drm_display_mode *panel_fixed_mode2; ++ struct drm_display_mode *vbt_mode; /* if any */ ++ ++ uint32_t saveBLC_PWM_CTL; ++}; ++ ++struct psb_intel_i2c_chan { ++ /* for getting at dev. private (mmio etc.) */ ++ struct drm_device *drm_dev; ++ u32 reg; /* GPIO reg */ ++ struct i2c_adapter adapter; ++ struct i2c_algo_bit_data algo; ++ u8 slave_addr; ++}; ++ ++struct psb_intel_encoder { ++ struct drm_encoder base; ++ int type; ++ bool needs_tv_clock; ++ void (*hot_plug)(struct psb_intel_encoder *); ++ int crtc_mask; ++ int clone_mask; ++ void *dev_priv; /* For sdvo_priv, lvds_priv, etc... */ ++ ++ /* FIXME: Either make SDVO and LVDS store it's i2c here or give CDV it's ++ own set of output privates */ ++ struct psb_intel_i2c_chan *i2c_bus; ++ struct psb_intel_i2c_chan *ddc_bus; ++}; ++ ++struct psb_intel_connector { ++ struct drm_connector base; ++ struct psb_intel_encoder *encoder; ++}; ++ ++struct psb_intel_crtc_state { ++ uint32_t saveDSPCNTR; ++ uint32_t savePIPECONF; ++ uint32_t savePIPESRC; ++ uint32_t saveDPLL; ++ uint32_t saveFP0; ++ uint32_t saveFP1; ++ uint32_t saveHTOTAL; ++ uint32_t saveHBLANK; ++ uint32_t saveHSYNC; ++ uint32_t saveVTOTAL; ++ uint32_t saveVBLANK; ++ uint32_t saveVSYNC; ++ uint32_t saveDSPSTRIDE; ++ uint32_t saveDSPSIZE; ++ uint32_t saveDSPPOS; ++ uint32_t saveDSPBASE; ++ uint32_t savePalette[256]; ++}; ++ ++struct psb_intel_crtc { ++ struct drm_crtc base; ++ int pipe; ++ int plane; ++ uint32_t cursor_addr; ++ u8 lut_r[256], lut_g[256], lut_b[256]; ++ u8 lut_adj[256]; ++ struct psb_intel_framebuffer *fbdev_fb; ++ /* a mode_set for fbdev users on this crtc */ ++ struct drm_mode_set mode_set; ++ ++ /* GEM object that holds our cursor */ ++ struct drm_gem_object *cursor_obj; ++ ++ struct drm_display_mode saved_mode; ++ struct drm_display_mode saved_adjusted_mode; ++ ++ struct psb_intel_mode_device *mode_dev; ++ ++ /*crtc mode setting flags*/ ++ u32 mode_flags; ++ ++ /* Saved Crtc HW states */ ++ struct psb_intel_crtc_state *crtc_state; ++}; ++ ++#define to_psb_intel_crtc(x) \ ++ container_of(x, struct psb_intel_crtc, base) ++#define to_psb_intel_connector(x) \ ++ container_of(x, struct psb_intel_connector, base) ++#define to_psb_intel_encoder(x) \ ++ container_of(x, struct psb_intel_encoder, base) ++#define to_psb_intel_framebuffer(x) \ ++ container_of(x, struct psb_intel_framebuffer, base) ++ ++struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev, ++ const u32 reg, const char *name); ++void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan); ++int psb_intel_ddc_get_modes(struct drm_connector *connector, ++ struct i2c_adapter *adapter); ++extern bool psb_intel_ddc_probe(struct i2c_adapter *adapter); ++ ++extern void psb_intel_crtc_init(struct drm_device *dev, int pipe, ++ struct psb_intel_mode_device *mode_dev); ++extern void psb_intel_crt_init(struct drm_device *dev); ++extern bool psb_intel_sdvo_init(struct drm_device *dev, int output_device); ++extern void psb_intel_dvo_init(struct drm_device *dev); ++extern void psb_intel_tv_init(struct drm_device *dev); ++extern void psb_intel_lvds_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev); ++extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level); ++extern void oaktrail_lvds_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev); ++extern void oaktrail_wait_for_INTR_PKT_SENT(struct drm_device *dev); ++extern void oaktrail_dsi_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev); ++extern void mid_dsi_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev, int dsi_num); ++ ++extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc); ++extern void psb_intel_encoder_prepare(struct drm_encoder *encoder); ++extern void psb_intel_encoder_commit(struct drm_encoder *encoder); ++extern void psb_intel_encoder_destroy(struct drm_encoder *encoder); ++ ++static inline struct psb_intel_encoder *psb_intel_attached_encoder( ++ struct drm_connector *connector) ++{ ++ return to_psb_intel_connector(connector)->encoder; ++} ++ ++extern void psb_intel_connector_attach_encoder( ++ struct psb_intel_connector *connector, ++ struct psb_intel_encoder *encoder); ++ ++extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector ++ *connector); ++ ++extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, ++ struct drm_crtc *crtc); ++extern void psb_intel_wait_for_vblank(struct drm_device *dev); ++extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, ++ struct drm_file *file_priv); ++extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, ++ int pipe); ++extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, ++ int sdvoB); ++extern int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector); ++extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, ++ int enable); ++extern int intelfb_probe(struct drm_device *dev); ++extern int intelfb_remove(struct drm_device *dev, ++ struct drm_framebuffer *fb); ++extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device ++ *dev, struct ++ drm_mode_fb_cmd ++ *mode_cmd, ++ void *mm_private); ++extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode); ++extern int psb_intel_lvds_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode); ++extern int psb_intel_lvds_set_property(struct drm_connector *connector, ++ struct drm_property *property, ++ uint64_t value); ++extern void psb_intel_lvds_destroy(struct drm_connector *connector); ++extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs; ++ ++/* intel_gmbus.c */ ++extern void gma_intel_i2c_reset(struct drm_device *dev); ++extern int gma_intel_setup_gmbus(struct drm_device *dev); ++extern void gma_intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed); ++extern void gma_intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit); ++extern void gma_intel_teardown_gmbus(struct drm_device *dev); ++ ++#endif /* __INTEL_DRV_H__ */ +diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c +new file mode 100644 +index 0000000..c83f5b5 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c +@@ -0,0 +1,867 @@ ++/* ++ * Copyright © 2006-2007 Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: ++ * Eric Anholt ++ * Dave Airlie ++ * Jesse Barnes ++ */ ++ ++#include ++#include ++ ++#include "intel_bios.h" ++#include "psb_drv.h" ++#include "psb_intel_drv.h" ++#include "psb_intel_reg.h" ++#include "power.h" ++#include ++ ++/* ++ * LVDS I2C backlight control macros ++ */ ++#define BRIGHTNESS_MAX_LEVEL 100 ++#define BRIGHTNESS_MASK 0xFF ++#define BLC_I2C_TYPE 0x01 ++#define BLC_PWM_TYPT 0x02 ++ ++#define BLC_POLARITY_NORMAL 0 ++#define BLC_POLARITY_INVERSE 1 ++ ++#define PSB_BLC_MAX_PWM_REG_FREQ (0xFFFE) ++#define PSB_BLC_MIN_PWM_REG_FREQ (0x2) ++#define PSB_BLC_PWM_PRECISION_FACTOR (10) ++#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) ++#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) ++ ++struct psb_intel_lvds_priv { ++ /* ++ * Saved LVDO output states ++ */ ++ uint32_t savePP_ON; ++ uint32_t savePP_OFF; ++ uint32_t saveLVDS; ++ uint32_t savePP_CONTROL; ++ uint32_t savePP_CYCLE; ++ uint32_t savePFIT_CONTROL; ++ uint32_t savePFIT_PGM_RATIOS; ++ uint32_t saveBLC_PWM_CTL; ++ ++ struct psb_intel_i2c_chan *i2c_bus; ++ struct psb_intel_i2c_chan *ddc_bus; ++}; ++ ++ ++/* ++ * Returns the maximum level of the backlight duty cycle field. ++ */ ++static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 ret; ++ ++ if (gma_power_begin(dev, false)) { ++ ret = REG_READ(BLC_PWM_CTL); ++ gma_power_end(dev); ++ } else /* Powered off, use the saved value */ ++ ret = dev_priv->regs.saveBLC_PWM_CTL; ++ ++ /* Top 15bits hold the frequency mask */ ++ ret = (ret & BACKLIGHT_MODULATION_FREQ_MASK) >> ++ BACKLIGHT_MODULATION_FREQ_SHIFT; ++ ++ ret *= 2; /* Return a 16bit range as needed for setting */ ++ if (ret == 0) ++ dev_err(dev->dev, "BL bug: Reg %08x save %08X\n", ++ REG_READ(BLC_PWM_CTL), dev_priv->regs.saveBLC_PWM_CTL); ++ return ret; ++} ++ ++/* ++ * Set LVDS backlight level by I2C command ++ * ++ * FIXME: at some point we need to both track this for PM and also ++ * disable runtime pm on MRST if the brightness is nil (ie blanked) ++ */ ++static int psb_lvds_i2c_set_brightness(struct drm_device *dev, ++ unsigned int level) ++{ ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *)dev->dev_private; ++ ++ struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus; ++ u8 out_buf[2]; ++ unsigned int blc_i2c_brightness; ++ ++ struct i2c_msg msgs[] = { ++ { ++ .addr = lvds_i2c_bus->slave_addr, ++ .flags = 0, ++ .len = 2, ++ .buf = out_buf, ++ } ++ }; ++ ++ blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level * ++ BRIGHTNESS_MASK / ++ BRIGHTNESS_MAX_LEVEL); ++ ++ if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) ++ blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness; ++ ++ out_buf[0] = dev_priv->lvds_bl->brightnesscmd; ++ out_buf[1] = (u8)blc_i2c_brightness; ++ ++ if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) { ++ dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n", ++ dev_priv->lvds_bl->brightnesscmd, ++ blc_i2c_brightness); ++ return 0; ++ } ++ ++ dev_err(dev->dev, "I2C transfer error\n"); ++ return -1; ++} ++ ++ ++static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level) ++{ ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *)dev->dev_private; ++ ++ u32 max_pwm_blc; ++ u32 blc_pwm_duty_cycle; ++ ++ max_pwm_blc = psb_intel_lvds_get_max_backlight(dev); ++ ++ /*BLC_PWM_CTL Should be initiated while backlight device init*/ ++ BUG_ON(max_pwm_blc == 0); ++ ++ blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL; ++ ++ if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) ++ blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle; ++ ++ blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; ++ REG_WRITE(BLC_PWM_CTL, ++ (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | ++ (blc_pwm_duty_cycle)); ++ ++ dev_info(dev->dev, "Backlight lvds set brightness %08x\n", ++ (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | ++ (blc_pwm_duty_cycle)); ++ ++ return 0; ++} ++ ++/* ++ * Set LVDS backlight level either by I2C or PWM ++ */ ++void psb_intel_lvds_set_brightness(struct drm_device *dev, int level) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ dev_dbg(dev->dev, "backlight level is %d\n", level); ++ ++ if (!dev_priv->lvds_bl) { ++ dev_err(dev->dev, "NO LVDS backlight info\n"); ++ return; ++ } ++ ++ if (dev_priv->lvds_bl->type == BLC_I2C_TYPE) ++ psb_lvds_i2c_set_brightness(dev, level); ++ else ++ psb_lvds_pwm_set_brightness(dev, level); ++} ++ ++/* ++ * Sets the backlight level. ++ * ++ * level: backlight level, from 0 to psb_intel_lvds_get_max_backlight(). ++ */ ++static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 blc_pwm_ctl; ++ ++ if (gma_power_begin(dev, false)) { ++ blc_pwm_ctl = REG_READ(BLC_PWM_CTL); ++ blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK; ++ REG_WRITE(BLC_PWM_CTL, ++ (blc_pwm_ctl | ++ (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); ++ dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl | ++ (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); ++ gma_power_end(dev); ++ } else { ++ blc_pwm_ctl = dev_priv->regs.saveBLC_PWM_CTL & ++ ~BACKLIGHT_DUTY_CYCLE_MASK; ++ dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl | ++ (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); ++ } ++} ++ ++/* ++ * Sets the power state for the panel. ++ */ ++static void psb_intel_lvds_set_power(struct drm_device *dev, bool on) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ u32 pp_status; ++ ++ if (!gma_power_begin(dev, true)) { ++ dev_err(dev->dev, "set power, chip off!\n"); ++ return; ++ } ++ ++ if (on) { ++ REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | ++ POWER_TARGET_ON); ++ do { ++ pp_status = REG_READ(PP_STATUS); ++ } while ((pp_status & PP_ON) == 0); ++ ++ psb_intel_lvds_set_backlight(dev, ++ mode_dev->backlight_duty_cycle); ++ } else { ++ psb_intel_lvds_set_backlight(dev, 0); ++ ++ REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ++ ~POWER_TARGET_ON); ++ do { ++ pp_status = REG_READ(PP_STATUS); ++ } while (pp_status & PP_ON); ++ } ++ ++ gma_power_end(dev); ++} ++ ++static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ ++ if (mode == DRM_MODE_DPMS_ON) ++ psb_intel_lvds_set_power(dev, true); ++ else ++ psb_intel_lvds_set_power(dev, false); ++ ++ /* XXX: We never power down the LVDS pairs. */ ++} ++ ++static void psb_intel_lvds_save(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *)dev->dev_private; ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ struct psb_intel_lvds_priv *lvds_priv = ++ (struct psb_intel_lvds_priv *)psb_intel_encoder->dev_priv; ++ ++ lvds_priv->savePP_ON = REG_READ(LVDSPP_ON); ++ lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF); ++ lvds_priv->saveLVDS = REG_READ(LVDS); ++ lvds_priv->savePP_CONTROL = REG_READ(PP_CONTROL); ++ lvds_priv->savePP_CYCLE = REG_READ(PP_CYCLE); ++ /*lvds_priv->savePP_DIVISOR = REG_READ(PP_DIVISOR);*/ ++ lvds_priv->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); ++ lvds_priv->savePFIT_CONTROL = REG_READ(PFIT_CONTROL); ++ lvds_priv->savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS); ++ ++ /*TODO: move backlight_duty_cycle to psb_intel_lvds_priv*/ ++ dev_priv->backlight_duty_cycle = (dev_priv->regs.saveBLC_PWM_CTL & ++ BACKLIGHT_DUTY_CYCLE_MASK); ++ ++ /* ++ * If the light is off at server startup, ++ * just make it full brightness ++ */ ++ if (dev_priv->backlight_duty_cycle == 0) ++ dev_priv->backlight_duty_cycle = ++ psb_intel_lvds_get_max_backlight(dev); ++ ++ dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", ++ lvds_priv->savePP_ON, ++ lvds_priv->savePP_OFF, ++ lvds_priv->saveLVDS, ++ lvds_priv->savePP_CONTROL, ++ lvds_priv->savePP_CYCLE, ++ lvds_priv->saveBLC_PWM_CTL); ++} ++ ++static void psb_intel_lvds_restore(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ u32 pp_status; ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ struct psb_intel_lvds_priv *lvds_priv = ++ (struct psb_intel_lvds_priv *)psb_intel_encoder->dev_priv; ++ ++ dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", ++ lvds_priv->savePP_ON, ++ lvds_priv->savePP_OFF, ++ lvds_priv->saveLVDS, ++ lvds_priv->savePP_CONTROL, ++ lvds_priv->savePP_CYCLE, ++ lvds_priv->saveBLC_PWM_CTL); ++ ++ REG_WRITE(BLC_PWM_CTL, lvds_priv->saveBLC_PWM_CTL); ++ REG_WRITE(PFIT_CONTROL, lvds_priv->savePFIT_CONTROL); ++ REG_WRITE(PFIT_PGM_RATIOS, lvds_priv->savePFIT_PGM_RATIOS); ++ REG_WRITE(LVDSPP_ON, lvds_priv->savePP_ON); ++ REG_WRITE(LVDSPP_OFF, lvds_priv->savePP_OFF); ++ /*REG_WRITE(PP_DIVISOR, lvds_priv->savePP_DIVISOR);*/ ++ REG_WRITE(PP_CYCLE, lvds_priv->savePP_CYCLE); ++ REG_WRITE(PP_CONTROL, lvds_priv->savePP_CONTROL); ++ REG_WRITE(LVDS, lvds_priv->saveLVDS); ++ ++ if (lvds_priv->savePP_CONTROL & POWER_TARGET_ON) { ++ REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | ++ POWER_TARGET_ON); ++ do { ++ pp_status = REG_READ(PP_STATUS); ++ } while ((pp_status & PP_ON) == 0); ++ } else { ++ REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ++ ~POWER_TARGET_ON); ++ do { ++ pp_status = REG_READ(PP_STATUS); ++ } while (pp_status & PP_ON); ++ } ++} ++ ++int psb_intel_lvds_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ struct drm_psb_private *dev_priv = connector->dev->dev_private; ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ struct drm_display_mode *fixed_mode = ++ dev_priv->mode_dev.panel_fixed_mode; ++ ++ if (psb_intel_encoder->type == INTEL_OUTPUT_MIPI2) ++ fixed_mode = dev_priv->mode_dev.panel_fixed_mode2; ++ ++ /* just in case */ ++ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ return MODE_NO_DBLESCAN; ++ ++ /* just in case */ ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) ++ return MODE_NO_INTERLACE; ++ ++ if (fixed_mode) { ++ if (mode->hdisplay > fixed_mode->hdisplay) ++ return MODE_PANEL; ++ if (mode->vdisplay > fixed_mode->vdisplay) ++ return MODE_PANEL; ++ } ++ return MODE_OK; ++} ++ ++bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ struct psb_intel_crtc *psb_intel_crtc = ++ to_psb_intel_crtc(encoder->crtc); ++ struct drm_encoder *tmp_encoder; ++ struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode; ++ struct psb_intel_encoder *psb_intel_encoder = ++ to_psb_intel_encoder(encoder); ++ ++ if (psb_intel_encoder->type == INTEL_OUTPUT_MIPI2) ++ panel_fixed_mode = mode_dev->panel_fixed_mode2; ++ ++ /* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */ ++ if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) { ++ printk(KERN_ERR "Can't support LVDS on pipe A\n"); ++ return false; ++ } ++ if (IS_MRST(dev) && psb_intel_crtc->pipe != 0) { ++ printk(KERN_ERR "Must use PIPE A\n"); ++ return false; ++ } ++ /* Should never happen!! */ ++ list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, ++ head) { ++ if (tmp_encoder != encoder ++ && tmp_encoder->crtc == encoder->crtc) { ++ printk(KERN_ERR "Can't enable LVDS and another " ++ "encoder on the same pipe\n"); ++ return false; ++ } ++ } ++ ++ /* ++ * If we have timings from the BIOS for the panel, put them in ++ * to the adjusted mode. The CRTC will be set up for this mode, ++ * with the panel scaling set up to source from the H/VDisplay ++ * of the original mode. ++ */ ++ if (panel_fixed_mode != NULL) { ++ adjusted_mode->hdisplay = panel_fixed_mode->hdisplay; ++ adjusted_mode->hsync_start = panel_fixed_mode->hsync_start; ++ adjusted_mode->hsync_end = panel_fixed_mode->hsync_end; ++ adjusted_mode->htotal = panel_fixed_mode->htotal; ++ adjusted_mode->vdisplay = panel_fixed_mode->vdisplay; ++ adjusted_mode->vsync_start = panel_fixed_mode->vsync_start; ++ adjusted_mode->vsync_end = panel_fixed_mode->vsync_end; ++ adjusted_mode->vtotal = panel_fixed_mode->vtotal; ++ adjusted_mode->clock = panel_fixed_mode->clock; ++ drm_mode_set_crtcinfo(adjusted_mode, ++ CRTC_INTERLACE_HALVE_V); ++ } ++ ++ /* ++ * XXX: It would be nice to support lower refresh rates on the ++ * panels to reduce power consumption, and perhaps match the ++ * user's requested refresh rate. ++ */ ++ ++ return true; ++} ++ ++static void psb_intel_lvds_prepare(struct drm_encoder *encoder) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ ++ if (!gma_power_begin(dev, true)) ++ return; ++ ++ mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); ++ mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & ++ BACKLIGHT_DUTY_CYCLE_MASK); ++ ++ psb_intel_lvds_set_power(dev, false); ++ ++ gma_power_end(dev); ++} ++ ++static void psb_intel_lvds_commit(struct drm_encoder *encoder) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ ++ if (mode_dev->backlight_duty_cycle == 0) ++ mode_dev->backlight_duty_cycle = ++ psb_intel_lvds_get_max_backlight(dev); ++ ++ psb_intel_lvds_set_power(dev, true); ++} ++ ++static void psb_intel_lvds_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 pfit_control; ++ ++ /* ++ * The LVDS pin pair will already have been turned on in the ++ * psb_intel_crtc_mode_set since it has a large impact on the DPLL ++ * settings. ++ */ ++ ++ /* ++ * Enable automatic panel scaling so that non-native modes fill the ++ * screen. Should be enabled before the pipe is enabled, according to ++ * register description and PRM. ++ */ ++ if (mode->hdisplay != adjusted_mode->hdisplay || ++ mode->vdisplay != adjusted_mode->vdisplay) ++ pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | ++ HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | ++ HORIZ_INTERP_BILINEAR); ++ else ++ pfit_control = 0; ++ ++ if (dev_priv->lvds_dither) ++ pfit_control |= PANEL_8TO6_DITHER_ENABLE; ++ ++ REG_WRITE(PFIT_CONTROL, pfit_control); ++} ++ ++/* ++ * Detect the LVDS connection. ++ * ++ * This always returns CONNECTOR_STATUS_CONNECTED. ++ * This connector should only have ++ * been set up if the LVDS was actually connected anyway. ++ */ ++static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector ++ *connector, bool force) ++{ ++ return connector_status_connected; ++} ++ ++/* ++ * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. ++ */ ++static int psb_intel_lvds_get_modes(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ struct psb_intel_lvds_priv *lvds_priv = psb_intel_encoder->dev_priv; ++ int ret = 0; ++ ++ if (!IS_MRST(dev)) ++ ret = psb_intel_ddc_get_modes(connector, &lvds_priv->i2c_bus->adapter); ++ ++ if (ret) ++ return ret; ++ ++ /* Didn't get an EDID, so ++ * Set wide sync ranges so we get all modes ++ * handed to valid_mode for checking ++ */ ++ connector->display_info.min_vfreq = 0; ++ connector->display_info.max_vfreq = 200; ++ connector->display_info.min_hfreq = 0; ++ connector->display_info.max_hfreq = 200; ++ ++ if (mode_dev->panel_fixed_mode != NULL) { ++ struct drm_display_mode *mode = ++ drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); ++ drm_mode_probed_add(connector, mode); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * psb_intel_lvds_destroy - unregister and free LVDS structures ++ * @connector: connector to free ++ * ++ * Unregister the DDC bus for this connector then free the driver private ++ * structure. ++ */ ++void psb_intel_lvds_destroy(struct drm_connector *connector) ++{ ++ struct psb_intel_encoder *psb_intel_encoder = ++ psb_intel_attached_encoder(connector); ++ struct psb_intel_lvds_priv *lvds_priv = psb_intel_encoder->dev_priv; ++ ++ if (lvds_priv->ddc_bus) ++ psb_intel_i2c_destroy(lvds_priv->ddc_bus); ++ drm_sysfs_connector_remove(connector); ++ drm_connector_cleanup(connector); ++ kfree(connector); ++} ++ ++int psb_intel_lvds_set_property(struct drm_connector *connector, ++ struct drm_property *property, ++ uint64_t value) ++{ ++ struct drm_encoder *encoder = connector->encoder; ++ ++ if (!encoder) ++ return -1; ++ ++ if (!strcmp(property->name, "scaling mode")) { ++ struct psb_intel_crtc *crtc = ++ to_psb_intel_crtc(encoder->crtc); ++ uint64_t curval; ++ ++ if (!crtc) ++ goto set_prop_error; ++ ++ switch (value) { ++ case DRM_MODE_SCALE_FULLSCREEN: ++ break; ++ case DRM_MODE_SCALE_NO_SCALE: ++ break; ++ case DRM_MODE_SCALE_ASPECT: ++ break; ++ default: ++ goto set_prop_error; ++ } ++ ++ if (drm_connector_property_get_value(connector, ++ property, ++ &curval)) ++ goto set_prop_error; ++ ++ if (curval == value) ++ goto set_prop_done; ++ ++ if (drm_connector_property_set_value(connector, ++ property, ++ value)) ++ goto set_prop_error; ++ ++ if (crtc->saved_mode.hdisplay != 0 && ++ crtc->saved_mode.vdisplay != 0) { ++ if (!drm_crtc_helper_set_mode(encoder->crtc, ++ &crtc->saved_mode, ++ encoder->crtc->x, ++ encoder->crtc->y, ++ encoder->crtc->fb)) ++ goto set_prop_error; ++ } ++ } else if (!strcmp(property->name, "backlight")) { ++ if (drm_connector_property_set_value(connector, ++ property, ++ value)) ++ goto set_prop_error; ++ else { ++#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE ++ struct drm_psb_private *devp = ++ encoder->dev->dev_private; ++ struct backlight_device *bd = devp->backlight_device; ++ if (bd) { ++ bd->props.brightness = value; ++ backlight_update_status(bd); ++ } ++#endif ++ } ++ } else if (!strcmp(property->name, "DPMS")) { ++ struct drm_encoder_helper_funcs *hfuncs ++ = encoder->helper_private; ++ hfuncs->dpms(encoder, value); ++ } ++ ++set_prop_done: ++ return 0; ++set_prop_error: ++ return -1; ++} ++ ++static const struct drm_encoder_helper_funcs psb_intel_lvds_helper_funcs = { ++ .dpms = psb_intel_lvds_encoder_dpms, ++ .mode_fixup = psb_intel_lvds_mode_fixup, ++ .prepare = psb_intel_lvds_prepare, ++ .mode_set = psb_intel_lvds_mode_set, ++ .commit = psb_intel_lvds_commit, ++}; ++ ++const struct drm_connector_helper_funcs ++ psb_intel_lvds_connector_helper_funcs = { ++ .get_modes = psb_intel_lvds_get_modes, ++ .mode_valid = psb_intel_lvds_mode_valid, ++ .best_encoder = psb_intel_best_encoder, ++}; ++ ++const struct drm_connector_funcs psb_intel_lvds_connector_funcs = { ++ .dpms = drm_helper_connector_dpms, ++ .save = psb_intel_lvds_save, ++ .restore = psb_intel_lvds_restore, ++ .detect = psb_intel_lvds_detect, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .set_property = psb_intel_lvds_set_property, ++ .destroy = psb_intel_lvds_destroy, ++}; ++ ++ ++static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder) ++{ ++ drm_encoder_cleanup(encoder); ++} ++ ++const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = { ++ .destroy = psb_intel_lvds_enc_destroy, ++}; ++ ++ ++ ++/** ++ * psb_intel_lvds_init - setup LVDS connectors on this device ++ * @dev: drm device ++ * ++ * Create the connector, register the LVDS DDC bus, and try to figure out what ++ * modes we can display on the LVDS panel (if present). ++ */ ++void psb_intel_lvds_init(struct drm_device *dev, ++ struct psb_intel_mode_device *mode_dev) ++{ ++ struct psb_intel_encoder *psb_intel_encoder; ++ struct psb_intel_connector *psb_intel_connector; ++ struct psb_intel_lvds_priv *lvds_priv; ++ struct drm_connector *connector; ++ struct drm_encoder *encoder; ++ struct drm_display_mode *scan; /* *modes, *bios_mode; */ ++ struct drm_crtc *crtc; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ u32 lvds; ++ int pipe; ++ ++ psb_intel_encoder = ++ kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); ++ if (!psb_intel_encoder) { ++ dev_err(dev->dev, "psb_intel_encoder allocation error\n"); ++ return; ++ } ++ ++ psb_intel_connector = ++ kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL); ++ if (!psb_intel_connector) { ++ dev_err(dev->dev, "psb_intel_connector allocation error\n"); ++ goto failed_encoder; ++ } ++ ++ lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL); ++ if (!lvds_priv) { ++ dev_err(dev->dev, "LVDS private allocation error\n"); ++ goto failed_connector; ++ } ++ ++ psb_intel_encoder->dev_priv = lvds_priv; ++ ++ connector = &psb_intel_connector->base; ++ encoder = &psb_intel_encoder->base; ++ drm_connector_init(dev, connector, ++ &psb_intel_lvds_connector_funcs, ++ DRM_MODE_CONNECTOR_LVDS); ++ ++ drm_encoder_init(dev, encoder, ++ &psb_intel_lvds_enc_funcs, ++ DRM_MODE_ENCODER_LVDS); ++ ++ psb_intel_connector_attach_encoder(psb_intel_connector, ++ psb_intel_encoder); ++ psb_intel_encoder->type = INTEL_OUTPUT_LVDS; ++ ++ drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs); ++ drm_connector_helper_add(connector, ++ &psb_intel_lvds_connector_helper_funcs); ++ connector->display_info.subpixel_order = SubPixelHorizontalRGB; ++ connector->interlace_allowed = false; ++ connector->doublescan_allowed = false; ++ ++ /*Attach connector properties*/ ++ drm_connector_attach_property(connector, ++ dev->mode_config.scaling_mode_property, ++ DRM_MODE_SCALE_FULLSCREEN); ++ drm_connector_attach_property(connector, ++ dev_priv->backlight_property, ++ BRIGHTNESS_MAX_LEVEL); ++ ++ /* ++ * Set up I2C bus ++ * FIXME: distroy i2c_bus when exit ++ */ ++ lvds_priv->i2c_bus = psb_intel_i2c_create(dev, GPIOB, "LVDSBLC_B"); ++ if (!lvds_priv->i2c_bus) { ++ dev_printk(KERN_ERR, ++ &dev->pdev->dev, "I2C bus registration failed.\n"); ++ goto failed_blc_i2c; ++ } ++ lvds_priv->i2c_bus->slave_addr = 0x2C; ++ dev_priv->lvds_i2c_bus = lvds_priv->i2c_bus; ++ ++ /* ++ * LVDS discovery: ++ * 1) check for EDID on DDC ++ * 2) check for VBT data ++ * 3) check to see if LVDS is already on ++ * if none of the above, no panel ++ * 4) make sure lid is open ++ * if closed, act like it's not there for now ++ */ ++ ++ /* Set up the DDC bus. */ ++ lvds_priv->ddc_bus = psb_intel_i2c_create(dev, GPIOC, "LVDSDDC_C"); ++ if (!lvds_priv->ddc_bus) { ++ dev_printk(KERN_ERR, &dev->pdev->dev, ++ "DDC bus registration " "failed.\n"); ++ goto failed_ddc; ++ } ++ ++ /* ++ * Attempt to get the fixed panel mode from DDC. Assume that the ++ * preferred mode is the right one. ++ */ ++ psb_intel_ddc_get_modes(connector, &lvds_priv->ddc_bus->adapter); ++ list_for_each_entry(scan, &connector->probed_modes, head) { ++ if (scan->type & DRM_MODE_TYPE_PREFERRED) { ++ mode_dev->panel_fixed_mode = ++ drm_mode_duplicate(dev, scan); ++ goto out; /* FIXME: check for quirks */ ++ } ++ } ++ ++ /* Failed to get EDID, what about VBT? do we need this? */ ++ if (mode_dev->vbt_mode) ++ mode_dev->panel_fixed_mode = ++ drm_mode_duplicate(dev, mode_dev->vbt_mode); ++ ++ if (!mode_dev->panel_fixed_mode) ++ if (dev_priv->lfp_lvds_vbt_mode) ++ mode_dev->panel_fixed_mode = ++ drm_mode_duplicate(dev, ++ dev_priv->lfp_lvds_vbt_mode); ++ ++ /* ++ * If we didn't get EDID, try checking if the panel is already turned ++ * on. If so, assume that whatever is currently programmed is the ++ * correct mode. ++ */ ++ lvds = REG_READ(LVDS); ++ pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; ++ crtc = psb_intel_get_crtc_from_pipe(dev, pipe); ++ ++ if (crtc && (lvds & LVDS_PORT_EN)) { ++ mode_dev->panel_fixed_mode = ++ psb_intel_crtc_mode_get(dev, crtc); ++ if (mode_dev->panel_fixed_mode) { ++ mode_dev->panel_fixed_mode->type |= ++ DRM_MODE_TYPE_PREFERRED; ++ goto out; /* FIXME: check for quirks */ ++ } ++ } ++ ++ /* If we still don't have a mode after all that, give up. */ ++ if (!mode_dev->panel_fixed_mode) { ++ dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n"); ++ goto failed_find; ++ } ++ ++ /* ++ * Blacklist machines with BIOSes that list an LVDS panel without ++ * actually having one. ++ */ ++out: ++ drm_sysfs_connector_add(connector); ++ return; ++ ++failed_find: ++ if (lvds_priv->ddc_bus) ++ psb_intel_i2c_destroy(lvds_priv->ddc_bus); ++failed_ddc: ++ if (lvds_priv->i2c_bus) ++ psb_intel_i2c_destroy(lvds_priv->i2c_bus); ++failed_blc_i2c: ++ drm_encoder_cleanup(encoder); ++ drm_connector_cleanup(connector); ++failed_connector: ++ kfree(psb_intel_connector); ++failed_encoder: ++ kfree(psb_intel_encoder); ++} ++ +diff --git a/drivers/gpu/drm/gma500/psb_intel_modes.c b/drivers/gpu/drm/gma500/psb_intel_modes.c +new file mode 100644 +index 0000000..4fca0d6 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_intel_modes.c +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (c) 2007 Intel Corporation ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authers: Jesse Barnes ++ */ ++ ++#include ++#include ++#include ++#include "psb_intel_drv.h" ++ ++/** ++ * psb_intel_ddc_probe ++ * ++ */ ++bool psb_intel_ddc_probe(struct i2c_adapter *adapter) ++{ ++ u8 out_buf[] = { 0x0, 0x0 }; ++ u8 buf[2]; ++ int ret; ++ struct i2c_msg msgs[] = { ++ { ++ .addr = 0x50, ++ .flags = 0, ++ .len = 1, ++ .buf = out_buf, ++ }, ++ { ++ .addr = 0x50, ++ .flags = I2C_M_RD, ++ .len = 1, ++ .buf = buf, ++ } ++ }; ++ ++ ret = i2c_transfer(adapter, msgs, 2); ++ if (ret == 2) ++ return true; ++ ++ return false; ++} ++ ++/** ++ * psb_intel_ddc_get_modes - get modelist from monitor ++ * @connector: DRM connector device to use ++ * ++ * Fetch the EDID information from @connector using the DDC bus. ++ */ ++int psb_intel_ddc_get_modes(struct drm_connector *connector, ++ struct i2c_adapter *adapter) ++{ ++ struct edid *edid; ++ int ret = 0; ++ ++ edid = drm_get_edid(connector, adapter); ++ if (edid) { ++ drm_mode_connector_update_edid_property(connector, edid); ++ ret = drm_add_edid_modes(connector, edid); ++ kfree(edid); ++ } ++ return ret; ++} +diff --git a/drivers/gpu/drm/gma500/psb_intel_reg.h b/drivers/gpu/drm/gma500/psb_intel_reg.h +new file mode 100644 +index 0000000..e89d3a2 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_intel_reg.h +@@ -0,0 +1,1318 @@ ++/* ++ * Copyright (c) 2009, Intel Corporation. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++#ifndef __PSB_INTEL_REG_H__ ++#define __PSB_INTEL_REG_H__ ++ ++/* ++ * GPIO regs ++ */ ++#define GPIOA 0x5010 ++#define GPIOB 0x5014 ++#define GPIOC 0x5018 ++#define GPIOD 0x501c ++#define GPIOE 0x5020 ++#define GPIOF 0x5024 ++#define GPIOG 0x5028 ++#define GPIOH 0x502c ++# define GPIO_CLOCK_DIR_MASK (1 << 0) ++# define GPIO_CLOCK_DIR_IN (0 << 1) ++# define GPIO_CLOCK_DIR_OUT (1 << 1) ++# define GPIO_CLOCK_VAL_MASK (1 << 2) ++# define GPIO_CLOCK_VAL_OUT (1 << 3) ++# define GPIO_CLOCK_VAL_IN (1 << 4) ++# define GPIO_CLOCK_PULLUP_DISABLE (1 << 5) ++# define GPIO_DATA_DIR_MASK (1 << 8) ++# define GPIO_DATA_DIR_IN (0 << 9) ++# define GPIO_DATA_DIR_OUT (1 << 9) ++# define GPIO_DATA_VAL_MASK (1 << 10) ++# define GPIO_DATA_VAL_OUT (1 << 11) ++# define GPIO_DATA_VAL_IN (1 << 12) ++# define GPIO_DATA_PULLUP_DISABLE (1 << 13) ++ ++#define GMBUS0 0x5100 /* clock/port select */ ++#define GMBUS_RATE_100KHZ (0<<8) ++#define GMBUS_RATE_50KHZ (1<<8) ++#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */ ++#define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */ ++#define GMBUS_HOLD_EXT (1<<7) /* 300ns hold time, rsvd on Pineview */ ++#define GMBUS_PORT_DISABLED 0 ++#define GMBUS_PORT_SSC 1 ++#define GMBUS_PORT_VGADDC 2 ++#define GMBUS_PORT_PANEL 3 ++#define GMBUS_PORT_DPC 4 /* HDMIC */ ++#define GMBUS_PORT_DPB 5 /* SDVO, HDMIB */ ++ /* 6 reserved */ ++#define GMBUS_PORT_DPD 7 /* HDMID */ ++#define GMBUS_NUM_PORTS 8 ++#define GMBUS1 0x5104 /* command/status */ ++#define GMBUS_SW_CLR_INT (1<<31) ++#define GMBUS_SW_RDY (1<<30) ++#define GMBUS_ENT (1<<29) /* enable timeout */ ++#define GMBUS_CYCLE_NONE (0<<25) ++#define GMBUS_CYCLE_WAIT (1<<25) ++#define GMBUS_CYCLE_INDEX (2<<25) ++#define GMBUS_CYCLE_STOP (4<<25) ++#define GMBUS_BYTE_COUNT_SHIFT 16 ++#define GMBUS_SLAVE_INDEX_SHIFT 8 ++#define GMBUS_SLAVE_ADDR_SHIFT 1 ++#define GMBUS_SLAVE_READ (1<<0) ++#define GMBUS_SLAVE_WRITE (0<<0) ++#define GMBUS2 0x5108 /* status */ ++#define GMBUS_INUSE (1<<15) ++#define GMBUS_HW_WAIT_PHASE (1<<14) ++#define GMBUS_STALL_TIMEOUT (1<<13) ++#define GMBUS_INT (1<<12) ++#define GMBUS_HW_RDY (1<<11) ++#define GMBUS_SATOER (1<<10) ++#define GMBUS_ACTIVE (1<<9) ++#define GMBUS3 0x510c /* data buffer bytes 3-0 */ ++#define GMBUS4 0x5110 /* interrupt mask (Pineview+) */ ++#define GMBUS_SLAVE_TIMEOUT_EN (1<<4) ++#define GMBUS_NAK_EN (1<<3) ++#define GMBUS_IDLE_EN (1<<2) ++#define GMBUS_HW_WAIT_EN (1<<1) ++#define GMBUS_HW_RDY_EN (1<<0) ++#define GMBUS5 0x5120 /* byte index */ ++#define GMBUS_2BYTE_INDEX_EN (1<<31) ++ ++#define BLC_PWM_CTL 0x61254 ++#define BLC_PWM_CTL2 0x61250 ++#define BLC_PWM_CTL_C 0x62254 ++#define BLC_PWM_CTL2_C 0x62250 ++#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) ++/* ++ * This is the most significant 15 bits of the number of backlight cycles in a ++ * complete cycle of the modulated backlight control. ++ * ++ * The actual value is this field multiplied by two. ++ */ ++#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) ++#define BLM_LEGACY_MODE (1 << 16) ++/* ++ * This is the number of cycles out of the backlight modulation cycle for which ++ * the backlight is on. ++ * ++ * This field must be no greater than the number of cycles in the complete ++ * backlight modulation cycle. ++ */ ++#define BACKLIGHT_DUTY_CYCLE_SHIFT (0) ++#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) ++ ++#define I915_GCFGC 0xf0 ++#define I915_LOW_FREQUENCY_ENABLE (1 << 7) ++#define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4) ++#define I915_DISPLAY_CLOCK_333_MHZ (4 << 4) ++#define I915_DISPLAY_CLOCK_MASK (7 << 4) ++ ++#define I855_HPLLCC 0xc0 ++#define I855_CLOCK_CONTROL_MASK (3 << 0) ++#define I855_CLOCK_133_200 (0 << 0) ++#define I855_CLOCK_100_200 (1 << 0) ++#define I855_CLOCK_100_133 (2 << 0) ++#define I855_CLOCK_166_250 (3 << 0) ++ ++/* I830 CRTC registers */ ++#define HTOTAL_A 0x60000 ++#define HBLANK_A 0x60004 ++#define HSYNC_A 0x60008 ++#define VTOTAL_A 0x6000c ++#define VBLANK_A 0x60010 ++#define VSYNC_A 0x60014 ++#define PIPEASRC 0x6001c ++#define BCLRPAT_A 0x60020 ++#define VSYNCSHIFT_A 0x60028 ++ ++#define HTOTAL_B 0x61000 ++#define HBLANK_B 0x61004 ++#define HSYNC_B 0x61008 ++#define VTOTAL_B 0x6100c ++#define VBLANK_B 0x61010 ++#define VSYNC_B 0x61014 ++#define PIPEBSRC 0x6101c ++#define BCLRPAT_B 0x61020 ++#define VSYNCSHIFT_B 0x61028 ++ ++#define HTOTAL_C 0x62000 ++#define HBLANK_C 0x62004 ++#define HSYNC_C 0x62008 ++#define VTOTAL_C 0x6200c ++#define VBLANK_C 0x62010 ++#define VSYNC_C 0x62014 ++#define PIPECSRC 0x6201c ++#define BCLRPAT_C 0x62020 ++#define VSYNCSHIFT_C 0x62028 ++ ++#define PP_STATUS 0x61200 ++# define PP_ON (1 << 31) ++/* ++ * Indicates that all dependencies of the panel are on: ++ * ++ * - PLL enabled ++ * - pipe enabled ++ * - LVDS/DVOB/DVOC on ++ */ ++#define PP_READY (1 << 30) ++#define PP_SEQUENCE_NONE (0 << 28) ++#define PP_SEQUENCE_ON (1 << 28) ++#define PP_SEQUENCE_OFF (2 << 28) ++#define PP_SEQUENCE_MASK 0x30000000 ++#define PP_CONTROL 0x61204 ++#define POWER_TARGET_ON (1 << 0) ++ ++#define LVDSPP_ON 0x61208 ++#define LVDSPP_OFF 0x6120c ++#define PP_CYCLE 0x61210 ++ ++#define PP_ON_DELAYS 0x61208 /* Cedartrail */ ++#define PP_OFF_DELAYS 0x6120c /* Cedartrail */ ++ ++#define PFIT_CONTROL 0x61230 ++#define PFIT_ENABLE (1 << 31) ++#define PFIT_PIPE_MASK (3 << 29) ++#define PFIT_PIPE_SHIFT 29 ++#define PFIT_SCALING_MODE_PILLARBOX (1 << 27) ++#define PFIT_SCALING_MODE_LETTERBOX (3 << 26) ++#define VERT_INTERP_DISABLE (0 << 10) ++#define VERT_INTERP_BILINEAR (1 << 10) ++#define VERT_INTERP_MASK (3 << 10) ++#define VERT_AUTO_SCALE (1 << 9) ++#define HORIZ_INTERP_DISABLE (0 << 6) ++#define HORIZ_INTERP_BILINEAR (1 << 6) ++#define HORIZ_INTERP_MASK (3 << 6) ++#define HORIZ_AUTO_SCALE (1 << 5) ++#define PANEL_8TO6_DITHER_ENABLE (1 << 3) ++ ++#define PFIT_PGM_RATIOS 0x61234 ++#define PFIT_VERT_SCALE_MASK 0xfff00000 ++#define PFIT_HORIZ_SCALE_MASK 0x0000fff0 ++ ++#define PFIT_AUTO_RATIOS 0x61238 ++ ++#define DPLL_A 0x06014 ++#define DPLL_B 0x06018 ++#define DPLL_VCO_ENABLE (1 << 31) ++#define DPLL_DVO_HIGH_SPEED (1 << 30) ++#define DPLL_SYNCLOCK_ENABLE (1 << 29) ++#define DPLL_VGA_MODE_DIS (1 << 28) ++#define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */ ++#define DPLLB_MODE_LVDS (2 << 26) /* i915 */ ++#define DPLL_MODE_MASK (3 << 26) ++#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */ ++#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */ ++#define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */ ++#define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ ++#define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ ++#define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ ++#define DPLL_LOCK (1 << 15) /* CDV */ ++ ++/* ++ * The i830 generation, in DAC/serial mode, defines p1 as two plus this ++ * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set. ++ */ ++# define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 ++/* ++ * The i830 generation, in LVDS mode, defines P1 as the bit number set within ++ * this field (only one bit may be set). ++ */ ++#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 ++#define DPLL_FPA01_P1_POST_DIV_SHIFT 16 ++#define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required ++ * in DVO non-gang */ ++# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ ++#define PLL_REF_INPUT_DREFCLK (0 << 13) ++#define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ ++#define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO ++ * TVCLKIN */ ++#define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) ++#define PLL_REF_INPUT_MASK (3 << 13) ++#define PLL_LOAD_PULSE_PHASE_SHIFT 9 ++/* ++ * Parallel to Serial Load Pulse phase selection. ++ * Selects the phase for the 10X DPLL clock for the PCIe ++ * digital display port. The range is 4 to 13; 10 or more ++ * is just a flip delay. The default is 6 ++ */ ++#define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT) ++#define DISPLAY_RATE_SELECT_FPA1 (1 << 8) ++ ++/* ++ * SDVO multiplier for 945G/GM. Not used on 965. ++ * ++ * DPLL_MD_UDI_MULTIPLIER_MASK ++ */ ++#define SDVO_MULTIPLIER_MASK 0x000000ff ++#define SDVO_MULTIPLIER_SHIFT_HIRES 4 ++#define SDVO_MULTIPLIER_SHIFT_VGA 0 ++ ++/* ++ * PLL_MD ++ */ ++/* Pipe A SDVO/UDI clock multiplier/divider register for G965. */ ++#define DPLL_A_MD 0x0601c ++/* Pipe B SDVO/UDI clock multiplier/divider register for G965. */ ++#define DPLL_B_MD 0x06020 ++/* ++ * UDI pixel divider, controlling how many pixels are stuffed into a packet. ++ * ++ * Value is pixels minus 1. Must be set to 1 pixel for SDVO. ++ */ ++#define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000 ++#define DPLL_MD_UDI_DIVIDER_SHIFT 24 ++/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */ ++#define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000 ++#define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16 ++/* ++ * SDVO/UDI pixel multiplier. ++ * ++ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus ++ * clock rate is 10 times the DPLL clock. At low resolution/refresh rate ++ * modes, the bus rate would be below the limits, so SDVO allows for stuffing ++ * dummy bytes in the datastream at an increased clock rate, with both sides of ++ * the link knowing how many bytes are fill. ++ * ++ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock ++ * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be ++ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and ++ * through an SDVO command. ++ * ++ * This register field has values of multiplication factor minus 1, with ++ * a maximum multiplier of 5 for SDVO. ++ */ ++#define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00 ++#define DPLL_MD_UDI_MULTIPLIER_SHIFT 8 ++/* ++ * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. ++ * This best be set to the default value (3) or the CRT won't work. No, ++ * I don't entirely understand what this does... ++ */ ++#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f ++#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 ++ ++#define DPLL_TEST 0x606c ++#define DPLLB_TEST_SDVO_DIV_1 (0 << 22) ++#define DPLLB_TEST_SDVO_DIV_2 (1 << 22) ++#define DPLLB_TEST_SDVO_DIV_4 (2 << 22) ++#define DPLLB_TEST_SDVO_DIV_MASK (3 << 22) ++#define DPLLB_TEST_N_BYPASS (1 << 19) ++#define DPLLB_TEST_M_BYPASS (1 << 18) ++#define DPLLB_INPUT_BUFFER_ENABLE (1 << 16) ++#define DPLLA_TEST_N_BYPASS (1 << 3) ++#define DPLLA_TEST_M_BYPASS (1 << 2) ++#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) ++ ++#define ADPA 0x61100 ++#define ADPA_DAC_ENABLE (1 << 31) ++#define ADPA_DAC_DISABLE 0 ++#define ADPA_PIPE_SELECT_MASK (1 << 30) ++#define ADPA_PIPE_A_SELECT 0 ++#define ADPA_PIPE_B_SELECT (1 << 30) ++#define ADPA_USE_VGA_HVPOLARITY (1 << 15) ++#define ADPA_SETS_HVPOLARITY 0 ++#define ADPA_VSYNC_CNTL_DISABLE (1 << 11) ++#define ADPA_VSYNC_CNTL_ENABLE 0 ++#define ADPA_HSYNC_CNTL_DISABLE (1 << 10) ++#define ADPA_HSYNC_CNTL_ENABLE 0 ++#define ADPA_VSYNC_ACTIVE_HIGH (1 << 4) ++#define ADPA_VSYNC_ACTIVE_LOW 0 ++#define ADPA_HSYNC_ACTIVE_HIGH (1 << 3) ++#define ADPA_HSYNC_ACTIVE_LOW 0 ++ ++#define FPA0 0x06040 ++#define FPA1 0x06044 ++#define FPB0 0x06048 ++#define FPB1 0x0604c ++#define FP_N_DIV_MASK 0x003f0000 ++#define FP_N_DIV_SHIFT 16 ++#define FP_M1_DIV_MASK 0x00003f00 ++#define FP_M1_DIV_SHIFT 8 ++#define FP_M2_DIV_MASK 0x0000003f ++#define FP_M2_DIV_SHIFT 0 ++ ++#define PORT_HOTPLUG_EN 0x61110 ++#define SDVOB_HOTPLUG_INT_EN (1 << 26) ++#define SDVOC_HOTPLUG_INT_EN (1 << 25) ++#define TV_HOTPLUG_INT_EN (1 << 18) ++#define CRT_HOTPLUG_INT_EN (1 << 9) ++#define CRT_HOTPLUG_FORCE_DETECT (1 << 3) ++/* CDV.. */ ++#define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8) ++#define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7) ++#define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7) ++#define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5) ++#define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5) ++#define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5) ++#define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5) ++#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5) ++#define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4) ++#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4) ++#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) ++#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) ++#define CRT_HOTPLUG_DETECT_MASK 0x000000F8 ++ ++#define PORT_HOTPLUG_STAT 0x61114 ++#define CRT_HOTPLUG_INT_STATUS (1 << 11) ++#define TV_HOTPLUG_INT_STATUS (1 << 10) ++#define CRT_HOTPLUG_MONITOR_MASK (3 << 8) ++#define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) ++#define CRT_HOTPLUG_MONITOR_MONO (2 << 8) ++#define CRT_HOTPLUG_MONITOR_NONE (0 << 8) ++#define SDVOC_HOTPLUG_INT_STATUS (1 << 7) ++#define SDVOB_HOTPLUG_INT_STATUS (1 << 6) ++ ++#define SDVOB 0x61140 ++#define SDVOC 0x61160 ++#define SDVO_ENABLE (1 << 31) ++#define SDVO_PIPE_B_SELECT (1 << 30) ++#define SDVO_STALL_SELECT (1 << 29) ++#define SDVO_INTERRUPT_ENABLE (1 << 26) ++#define SDVO_COLOR_RANGE_16_235 (1 << 8) ++#define SDVO_AUDIO_ENABLE (1 << 6) ++ ++/** ++ * 915G/GM SDVO pixel multiplier. ++ * ++ * Programmed value is multiplier - 1, up to 5x. ++ * ++ * DPLL_MD_UDI_MULTIPLIER_MASK ++ */ ++#define SDVO_PORT_MULTIPLY_MASK (7 << 23) ++#define SDVO_PORT_MULTIPLY_SHIFT 23 ++#define SDVO_PHASE_SELECT_MASK (15 << 19) ++#define SDVO_PHASE_SELECT_DEFAULT (6 << 19) ++#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) ++#define SDVOC_GANG_MODE (1 << 16) ++#define SDVO_BORDER_ENABLE (1 << 7) ++#define SDVOB_PCIE_CONCURRENCY (1 << 3) ++#define SDVO_DETECTED (1 << 2) ++/* Bits to be preserved when writing */ ++#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14)) ++#define SDVOC_PRESERVE_MASK (1 << 17) ++ ++/* ++ * This register controls the LVDS output enable, pipe selection, and data ++ * format selection. ++ * ++ * All of the clock/data pairs are force powered down by power sequencing. ++ */ ++#define LVDS 0x61180 ++/* ++ * Enables the LVDS port. This bit must be set before DPLLs are enabled, as ++ * the DPLL semantics change when the LVDS is assigned to that pipe. ++ */ ++#define LVDS_PORT_EN (1 << 31) ++/* Selects pipe B for LVDS data. Must be set on pre-965. */ ++#define LVDS_PIPEB_SELECT (1 << 30) ++ ++/* Turns on border drawing to allow centered display. */ ++#define LVDS_BORDER_EN (1 << 15) ++ ++/* ++ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per ++ * pixel. ++ */ ++#define LVDS_A0A2_CLKA_POWER_MASK (3 << 8) ++#define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8) ++#define LVDS_A0A2_CLKA_POWER_UP (3 << 8) ++/* ++ * Controls the A3 data pair, which contains the additional LSBs for 24 bit ++ * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be ++ * on. ++ */ ++#define LVDS_A3_POWER_MASK (3 << 6) ++#define LVDS_A3_POWER_DOWN (0 << 6) ++#define LVDS_A3_POWER_UP (3 << 6) ++/* ++ * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP ++ * is set. ++ */ ++#define LVDS_CLKB_POWER_MASK (3 << 4) ++#define LVDS_CLKB_POWER_DOWN (0 << 4) ++#define LVDS_CLKB_POWER_UP (3 << 4) ++/* ++ * Controls the B0-B3 data pairs. This must be set to match the DPLL p2 ++ * setting for whether we are in dual-channel mode. The B3 pair will ++ * additionally only be powered up when LVDS_A3_POWER_UP is set. ++ */ ++#define LVDS_B0B3_POWER_MASK (3 << 2) ++#define LVDS_B0B3_POWER_DOWN (0 << 2) ++#define LVDS_B0B3_POWER_UP (3 << 2) ++ ++#define PIPEACONF 0x70008 ++#define PIPEACONF_ENABLE (1 << 31) ++#define PIPEACONF_DISABLE 0 ++#define PIPEACONF_DOUBLE_WIDE (1 << 30) ++#define PIPECONF_ACTIVE (1 << 30) ++#define I965_PIPECONF_ACTIVE (1 << 30) ++#define PIPECONF_DSIPLL_LOCK (1 << 29) ++#define PIPEACONF_SINGLE_WIDE 0 ++#define PIPEACONF_PIPE_UNLOCKED 0 ++#define PIPEACONF_DSR (1 << 26) ++#define PIPEACONF_PIPE_LOCKED (1 << 25) ++#define PIPEACONF_PALETTE 0 ++#define PIPECONF_FORCE_BORDER (1 << 25) ++#define PIPEACONF_GAMMA (1 << 24) ++#define PIPECONF_PROGRESSIVE (0 << 21) ++#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) ++#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) ++#define PIPECONF_PLANE_OFF (1 << 19) ++#define PIPECONF_CURSOR_OFF (1 << 18) ++ ++#define PIPEBCONF 0x71008 ++#define PIPEBCONF_ENABLE (1 << 31) ++#define PIPEBCONF_DISABLE 0 ++#define PIPEBCONF_DOUBLE_WIDE (1 << 30) ++#define PIPEBCONF_DISABLE 0 ++#define PIPEBCONF_GAMMA (1 << 24) ++#define PIPEBCONF_PALETTE 0 ++ ++#define PIPECCONF 0x72008 ++ ++#define PIPEBGCMAXRED 0x71010 ++#define PIPEBGCMAXGREEN 0x71014 ++#define PIPEBGCMAXBLUE 0x71018 ++ ++#define PIPEASTAT 0x70024 ++#define PIPEBSTAT 0x71024 ++#define PIPECSTAT 0x72024 ++#define PIPE_VBLANK_INTERRUPT_STATUS (1UL << 1) ++#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL << 2) ++#define PIPE_VBLANK_CLEAR (1 << 1) ++#define PIPE_VBLANK_STATUS (1 << 1) ++#define PIPE_TE_STATUS (1UL << 6) ++#define PIPE_DPST_EVENT_STATUS (1UL << 7) ++#define PIPE_VSYNC_CLEAR (1UL << 9) ++#define PIPE_VSYNC_STATUS (1UL << 9) ++#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS (1UL << 10) ++#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS (1UL << 11) ++#define PIPE_VBLANK_INTERRUPT_ENABLE (1UL << 17) ++#define PIPE_START_VBLANK_INTERRUPT_ENABLE (1UL << 18) ++#define PIPE_TE_ENABLE (1UL << 22) ++#define PIPE_DPST_EVENT_ENABLE (1UL << 23) ++#define PIPE_VSYNC_ENABL (1UL << 25) ++#define PIPE_HDMI_AUDIO_UNDERRUN (1UL << 26) ++#define PIPE_HDMI_AUDIO_BUFFER_DONE (1UL << 27) ++#define PIPE_HDMI_AUDIO_INT_MASK (PIPE_HDMI_AUDIO_UNDERRUN | \ ++ PIPE_HDMI_AUDIO_BUFFER_DONE) ++#define PIPE_EVENT_MASK ((1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)|(1 << 24)|(1 << 23)|(1 << 22)|(1 << 21)|(1 << 20)|(1 << 16)) ++#define PIPE_VBLANK_MASK ((1 << 25)|(1 << 24)|(1 << 18)|(1 << 17)) ++#define HISTOGRAM_INT_CONTROL 0x61268 ++#define HISTOGRAM_BIN_DATA 0X61264 ++#define HISTOGRAM_LOGIC_CONTROL 0x61260 ++#define PWM_CONTROL_LOGIC 0x61250 ++#define PIPE_HOTPLUG_INTERRUPT_STATUS (1UL << 10) ++#define HISTOGRAM_INTERRUPT_ENABLE (1UL << 31) ++#define HISTOGRAM_LOGIC_ENABLE (1UL << 31) ++#define PWM_LOGIC_ENABLE (1UL << 31) ++#define PWM_PHASEIN_ENABLE (1UL << 25) ++#define PWM_PHASEIN_INT_ENABLE (1UL << 24) ++#define PWM_PHASEIN_VB_COUNT 0x00001f00 ++#define PWM_PHASEIN_INC 0x0000001f ++#define HISTOGRAM_INT_CTRL_CLEAR (1UL << 30) ++#define DPST_YUV_LUMA_MODE 0 ++ ++struct dpst_ie_histogram_control { ++ union { ++ uint32_t data; ++ struct { ++ uint32_t bin_reg_index:7; ++ uint32_t reserved:4; ++ uint32_t bin_reg_func_select:1; ++ uint32_t sync_to_phase_in:1; ++ uint32_t alt_enhancement_mode:2; ++ uint32_t reserved1:1; ++ uint32_t sync_to_phase_in_count:8; ++ uint32_t histogram_mode_select:1; ++ uint32_t reserved2:4; ++ uint32_t ie_pipe_assignment:1; ++ uint32_t ie_mode_table_enabled:1; ++ uint32_t ie_histogram_enable:1; ++ }; ++ }; ++}; ++ ++struct dpst_guardband { ++ union { ++ uint32_t data; ++ struct { ++ uint32_t guardband:22; ++ uint32_t guardband_interrupt_delay:8; ++ uint32_t interrupt_status:1; ++ uint32_t interrupt_enable:1; ++ }; ++ }; ++}; ++ ++#define PIPEAFRAMEHIGH 0x70040 ++#define PIPEAFRAMEPIXEL 0x70044 ++#define PIPEBFRAMEHIGH 0x71040 ++#define PIPEBFRAMEPIXEL 0x71044 ++#define PIPECFRAMEHIGH 0x72040 ++#define PIPECFRAMEPIXEL 0x72044 ++#define PIPE_FRAME_HIGH_MASK 0x0000ffff ++#define PIPE_FRAME_HIGH_SHIFT 0 ++#define PIPE_FRAME_LOW_MASK 0xff000000 ++#define PIPE_FRAME_LOW_SHIFT 24 ++#define PIPE_PIXEL_MASK 0x00ffffff ++#define PIPE_PIXEL_SHIFT 0 ++ ++#define DSPARB 0x70030 ++#define DSPFW1 0x70034 ++#define DSPFW2 0x70038 ++#define DSPFW3 0x7003c ++#define DSPFW4 0x70050 ++#define DSPFW5 0x70054 ++#define DSPFW6 0x70058 ++#define DSPCHICKENBIT 0x70400 ++#define DSPACNTR 0x70180 ++#define DSPBCNTR 0x71180 ++#define DSPCCNTR 0x72180 ++#define DISPLAY_PLANE_ENABLE (1 << 31) ++#define DISPLAY_PLANE_DISABLE 0 ++#define DISPPLANE_GAMMA_ENABLE (1 << 30) ++#define DISPPLANE_GAMMA_DISABLE 0 ++#define DISPPLANE_PIXFORMAT_MASK (0xf << 26) ++#define DISPPLANE_8BPP (0x2 << 26) ++#define DISPPLANE_15_16BPP (0x4 << 26) ++#define DISPPLANE_16BPP (0x5 << 26) ++#define DISPPLANE_32BPP_NO_ALPHA (0x6 << 26) ++#define DISPPLANE_32BPP (0x7 << 26) ++#define DISPPLANE_STEREO_ENABLE (1 << 25) ++#define DISPPLANE_STEREO_DISABLE 0 ++#define DISPPLANE_SEL_PIPE_MASK (1 << 24) ++#define DISPPLANE_SEL_PIPE_POS 24 ++#define DISPPLANE_SEL_PIPE_A 0 ++#define DISPPLANE_SEL_PIPE_B (1 << 24) ++#define DISPPLANE_SRC_KEY_ENABLE (1 << 22) ++#define DISPPLANE_SRC_KEY_DISABLE 0 ++#define DISPPLANE_LINE_DOUBLE (1 << 20) ++#define DISPPLANE_NO_LINE_DOUBLE 0 ++#define DISPPLANE_STEREO_POLARITY_FIRST 0 ++#define DISPPLANE_STEREO_POLARITY_SECOND (1 << 18) ++/* plane B only */ ++#define DISPPLANE_ALPHA_TRANS_ENABLE (1 << 15) ++#define DISPPLANE_ALPHA_TRANS_DISABLE 0 ++#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0 ++#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1) ++#define DISPPLANE_BOTTOM (4) ++ ++#define DSPABASE 0x70184 ++#define DSPALINOFF 0x70184 ++#define DSPASTRIDE 0x70188 ++ ++#define DSPBBASE 0x71184 ++#define DSPBLINOFF 0X71184 ++#define DSPBADDR DSPBBASE ++#define DSPBSTRIDE 0x71188 ++ ++#define DSPCBASE 0x72184 ++#define DSPCLINOFF 0x72184 ++#define DSPCSTRIDE 0x72188 ++ ++#define DSPAKEYVAL 0x70194 ++#define DSPAKEYMASK 0x70198 ++ ++#define DSPAPOS 0x7018C /* reserved */ ++#define DSPASIZE 0x70190 ++#define DSPBPOS 0x7118C ++#define DSPBSIZE 0x71190 ++#define DSPCPOS 0x7218C ++#define DSPCSIZE 0x72190 ++ ++#define DSPASURF 0x7019C ++#define DSPATILEOFF 0x701A4 ++ ++#define DSPBSURF 0x7119C ++#define DSPBTILEOFF 0x711A4 ++ ++#define DSPCSURF 0x7219C ++#define DSPCTILEOFF 0x721A4 ++#define DSPCKEYMAXVAL 0x721A0 ++#define DSPCKEYMINVAL 0x72194 ++#define DSPCKEYMSK 0x72198 ++ ++#define VGACNTRL 0x71400 ++#define VGA_DISP_DISABLE (1 << 31) ++#define VGA_2X_MODE (1 << 30) ++#define VGA_PIPE_B_SELECT (1 << 29) ++ ++/* ++ * Overlay registers ++ */ ++#define OV_C_OFFSET 0x08000 ++#define OV_OVADD 0x30000 ++#define OV_DOVASTA 0x30008 ++# define OV_PIPE_SELECT ((1 << 6)|(1 << 7)) ++# define OV_PIPE_SELECT_POS 6 ++# define OV_PIPE_A 0 ++# define OV_PIPE_C 1 ++#define OV_OGAMC5 0x30010 ++#define OV_OGAMC4 0x30014 ++#define OV_OGAMC3 0x30018 ++#define OV_OGAMC2 0x3001C ++#define OV_OGAMC1 0x30020 ++#define OV_OGAMC0 0x30024 ++#define OVC_OVADD 0x38000 ++#define OVC_DOVCSTA 0x38008 ++#define OVC_OGAMC5 0x38010 ++#define OVC_OGAMC4 0x38014 ++#define OVC_OGAMC3 0x38018 ++#define OVC_OGAMC2 0x3801C ++#define OVC_OGAMC1 0x38020 ++#define OVC_OGAMC0 0x38024 ++ ++/* ++ * Some BIOS scratch area registers. The 845 (and 830?) store the amount ++ * of video memory available to the BIOS in SWF1. ++ */ ++#define SWF0 0x71410 ++#define SWF1 0x71414 ++#define SWF2 0x71418 ++#define SWF3 0x7141c ++#define SWF4 0x71420 ++#define SWF5 0x71424 ++#define SWF6 0x71428 ++ ++/* ++ * 855 scratch registers. ++ */ ++#define SWF00 0x70410 ++#define SWF01 0x70414 ++#define SWF02 0x70418 ++#define SWF03 0x7041c ++#define SWF04 0x70420 ++#define SWF05 0x70424 ++#define SWF06 0x70428 ++ ++#define SWF10 SWF0 ++#define SWF11 SWF1 ++#define SWF12 SWF2 ++#define SWF13 SWF3 ++#define SWF14 SWF4 ++#define SWF15 SWF5 ++#define SWF16 SWF6 ++ ++#define SWF30 0x72414 ++#define SWF31 0x72418 ++#define SWF32 0x7241c ++ ++ ++/* ++ * Palette registers ++ */ ++#define PALETTE_A 0x0a000 ++#define PALETTE_B 0x0a800 ++#define PALETTE_C 0x0ac00 ++ ++/* Cursor A & B regs */ ++#define CURACNTR 0x70080 ++#define CURSOR_MODE_DISABLE 0x00 ++#define CURSOR_MODE_64_32B_AX 0x07 ++#define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX) ++#define MCURSOR_GAMMA_ENABLE (1 << 26) ++#define CURABASE 0x70084 ++#define CURAPOS 0x70088 ++#define CURSOR_POS_MASK 0x007FF ++#define CURSOR_POS_SIGN 0x8000 ++#define CURSOR_X_SHIFT 0 ++#define CURSOR_Y_SHIFT 16 ++#define CURBCNTR 0x700c0 ++#define CURBBASE 0x700c4 ++#define CURBPOS 0x700c8 ++#define CURCCNTR 0x700e0 ++#define CURCBASE 0x700e4 ++#define CURCPOS 0x700e8 ++ ++/* ++ * Interrupt Registers ++ */ ++#define IER 0x020a0 ++#define IIR 0x020a4 ++#define IMR 0x020a8 ++#define ISR 0x020ac ++ ++/* ++ * MOORESTOWN delta registers ++ */ ++#define MRST_DPLL_A 0x0f014 ++#define MDFLD_DPLL_B 0x0f018 ++#define MDFLD_INPUT_REF_SEL (1 << 14) ++#define MDFLD_VCO_SEL (1 << 16) ++#define DPLLA_MODE_LVDS (2 << 26) /* mrst */ ++#define MDFLD_PLL_LATCHEN (1 << 28) ++#define MDFLD_PWR_GATE_EN (1 << 30) ++#define MDFLD_P1_MASK (0x1FF << 17) ++#define MRST_FPA0 0x0f040 ++#define MRST_FPA1 0x0f044 ++#define MDFLD_DPLL_DIV0 0x0f048 ++#define MDFLD_DPLL_DIV1 0x0f04c ++#define MRST_PERF_MODE 0x020f4 ++ ++/* ++ * MEDFIELD HDMI registers ++ */ ++#define HDMIPHYMISCCTL 0x61134 ++#define HDMI_PHY_POWER_DOWN 0x7f ++#define HDMIB_CONTROL 0x61140 ++#define HDMIB_PORT_EN (1 << 31) ++#define HDMIB_PIPE_B_SELECT (1 << 30) ++#define HDMIB_NULL_PACKET (1 << 9) ++#define HDMIB_HDCP_PORT (1 << 5) ++ ++/* #define LVDS 0x61180 */ ++#define MRST_PANEL_8TO6_DITHER_ENABLE (1 << 25) ++#define MRST_PANEL_24_DOT_1_FORMAT (1 << 24) ++#define LVDS_A3_POWER_UP_0_OUTPUT (1 << 6) ++ ++#define MIPI 0x61190 ++#define MIPI_C 0x62190 ++#define MIPI_PORT_EN (1 << 31) ++/* Turns on border drawing to allow centered display. */ ++#define SEL_FLOPPED_HSTX (1 << 23) ++#define PASS_FROM_SPHY_TO_AFE (1 << 16) ++#define MIPI_BORDER_EN (1 << 15) ++#define MIPIA_3LANE_MIPIC_1LANE 0x1 ++#define MIPIA_2LANE_MIPIC_2LANE 0x2 ++#define TE_TRIGGER_DSI_PROTOCOL (1 << 2) ++#define TE_TRIGGER_GPIO_PIN (1 << 3) ++#define MIPI_TE_COUNT 0x61194 ++ ++/* #define PP_CONTROL 0x61204 */ ++#define POWER_DOWN_ON_RESET (1 << 1) ++ ++/* #define PFIT_CONTROL 0x61230 */ ++#define PFIT_PIPE_SELECT (3 << 29) ++#define PFIT_PIPE_SELECT_SHIFT (29) ++ ++/* #define BLC_PWM_CTL 0x61254 */ ++#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT (16) ++#define MRST_BACKLIGHT_MODULATION_FREQ_MASK (0xffff << 16) ++ ++/* #define PIPEACONF 0x70008 */ ++#define PIPEACONF_PIPE_STATE (1 << 30) ++/* #define DSPACNTR 0x70180 */ ++ ++#define MRST_DSPABASE 0x7019c ++#define MRST_DSPBBASE 0x7119c ++#define MDFLD_DSPCBASE 0x7219c ++ ++/* ++ * Moorestown registers. ++ */ ++ ++/* ++ * MIPI IP registers ++ */ ++#define MIPIC_REG_OFFSET 0x800 ++ ++#define DEVICE_READY_REG 0xb000 ++#define LP_OUTPUT_HOLD (1 << 16) ++#define EXIT_ULPS_DEV_READY 0x3 ++#define LP_OUTPUT_HOLD_RELEASE 0x810000 ++# define ENTERING_ULPS (2 << 1) ++# define EXITING_ULPS (1 << 1) ++# define ULPS_MASK (3 << 1) ++# define BUS_POSSESSION (1 << 3) ++#define INTR_STAT_REG 0xb004 ++#define RX_SOT_ERROR (1 << 0) ++#define RX_SOT_SYNC_ERROR (1 << 1) ++#define RX_ESCAPE_MODE_ENTRY_ERROR (1 << 3) ++#define RX_LP_TX_SYNC_ERROR (1 << 4) ++#define RX_HS_RECEIVE_TIMEOUT_ERROR (1 << 5) ++#define RX_FALSE_CONTROL_ERROR (1 << 6) ++#define RX_ECC_SINGLE_BIT_ERROR (1 << 7) ++#define RX_ECC_MULTI_BIT_ERROR (1 << 8) ++#define RX_CHECKSUM_ERROR (1 << 9) ++#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 10) ++#define RX_DSI_VC_ID_INVALID (1 << 11) ++#define TX_FALSE_CONTROL_ERROR (1 << 12) ++#define TX_ECC_SINGLE_BIT_ERROR (1 << 13) ++#define TX_ECC_MULTI_BIT_ERROR (1 << 14) ++#define TX_CHECKSUM_ERROR (1 << 15) ++#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 16) ++#define TX_DSI_VC_ID_INVALID (1 << 17) ++#define HIGH_CONTENTION (1 << 18) ++#define LOW_CONTENTION (1 << 19) ++#define DPI_FIFO_UNDER_RUN (1 << 20) ++#define HS_TX_TIMEOUT (1 << 21) ++#define LP_RX_TIMEOUT (1 << 22) ++#define TURN_AROUND_ACK_TIMEOUT (1 << 23) ++#define ACK_WITH_NO_ERROR (1 << 24) ++#define HS_GENERIC_WR_FIFO_FULL (1 << 27) ++#define LP_GENERIC_WR_FIFO_FULL (1 << 28) ++#define SPL_PKT_SENT (1 << 30) ++#define INTR_EN_REG 0xb008 ++#define DSI_FUNC_PRG_REG 0xb00c ++#define DPI_CHANNEL_NUMBER_POS 0x03 ++#define DBI_CHANNEL_NUMBER_POS 0x05 ++#define FMT_DPI_POS 0x07 ++#define FMT_DBI_POS 0x0A ++#define DBI_DATA_WIDTH_POS 0x0D ++ ++/* DPI PIXEL FORMATS */ ++#define RGB_565_FMT 0x01 /* RGB 565 FORMAT */ ++#define RGB_666_FMT 0x02 /* RGB 666 FORMAT */ ++#define LRGB_666_FMT 0x03 /* RGB LOOSELY PACKED ++ * 666 FORMAT ++ */ ++#define RGB_888_FMT 0x04 /* RGB 888 FORMAT */ ++#define VIRTUAL_CHANNEL_NUMBER_0 0x00 /* Virtual channel 0 */ ++#define VIRTUAL_CHANNEL_NUMBER_1 0x01 /* Virtual channel 1 */ ++#define VIRTUAL_CHANNEL_NUMBER_2 0x02 /* Virtual channel 2 */ ++#define VIRTUAL_CHANNEL_NUMBER_3 0x03 /* Virtual channel 3 */ ++ ++#define DBI_NOT_SUPPORTED 0x00 /* command mode ++ * is not supported ++ */ ++#define DBI_DATA_WIDTH_16BIT 0x01 /* 16 bit data */ ++#define DBI_DATA_WIDTH_9BIT 0x02 /* 9 bit data */ ++#define DBI_DATA_WIDTH_8BIT 0x03 /* 8 bit data */ ++#define DBI_DATA_WIDTH_OPT1 0x04 /* option 1 */ ++#define DBI_DATA_WIDTH_OPT2 0x05 /* option 2 */ ++ ++#define HS_TX_TIMEOUT_REG 0xb010 ++#define LP_RX_TIMEOUT_REG 0xb014 ++#define TURN_AROUND_TIMEOUT_REG 0xb018 ++#define DEVICE_RESET_REG 0xb01C ++#define DPI_RESOLUTION_REG 0xb020 ++#define RES_V_POS 0x10 ++#define DBI_RESOLUTION_REG 0xb024 /* Reserved for MDFLD */ ++#define HORIZ_SYNC_PAD_COUNT_REG 0xb028 ++#define HORIZ_BACK_PORCH_COUNT_REG 0xb02C ++#define HORIZ_FRONT_PORCH_COUNT_REG 0xb030 ++#define HORIZ_ACTIVE_AREA_COUNT_REG 0xb034 ++#define VERT_SYNC_PAD_COUNT_REG 0xb038 ++#define VERT_BACK_PORCH_COUNT_REG 0xb03c ++#define VERT_FRONT_PORCH_COUNT_REG 0xb040 ++#define HIGH_LOW_SWITCH_COUNT_REG 0xb044 ++#define DPI_CONTROL_REG 0xb048 ++#define DPI_SHUT_DOWN (1 << 0) ++#define DPI_TURN_ON (1 << 1) ++#define DPI_COLOR_MODE_ON (1 << 2) ++#define DPI_COLOR_MODE_OFF (1 << 3) ++#define DPI_BACK_LIGHT_ON (1 << 4) ++#define DPI_BACK_LIGHT_OFF (1 << 5) ++#define DPI_LP (1 << 6) ++#define DPI_DATA_REG 0xb04c ++#define DPI_BACK_LIGHT_ON_DATA 0x07 ++#define DPI_BACK_LIGHT_OFF_DATA 0x17 ++#define INIT_COUNT_REG 0xb050 ++#define MAX_RET_PAK_REG 0xb054 ++#define VIDEO_FMT_REG 0xb058 ++#define COMPLETE_LAST_PCKT (1 << 2) ++#define EOT_DISABLE_REG 0xb05c ++#define ENABLE_CLOCK_STOPPING (1 << 1) ++#define LP_BYTECLK_REG 0xb060 ++#define LP_GEN_DATA_REG 0xb064 ++#define HS_GEN_DATA_REG 0xb068 ++#define LP_GEN_CTRL_REG 0xb06C ++#define HS_GEN_CTRL_REG 0xb070 ++#define DCS_CHANNEL_NUMBER_POS 0x6 ++#define MCS_COMMANDS_POS 0x8 ++#define WORD_COUNTS_POS 0x8 ++#define MCS_PARAMETER_POS 0x10 ++#define GEN_FIFO_STAT_REG 0xb074 ++#define HS_DATA_FIFO_FULL (1 << 0) ++#define HS_DATA_FIFO_HALF_EMPTY (1 << 1) ++#define HS_DATA_FIFO_EMPTY (1 << 2) ++#define LP_DATA_FIFO_FULL (1 << 8) ++#define LP_DATA_FIFO_HALF_EMPTY (1 << 9) ++#define LP_DATA_FIFO_EMPTY (1 << 10) ++#define HS_CTRL_FIFO_FULL (1 << 16) ++#define HS_CTRL_FIFO_HALF_EMPTY (1 << 17) ++#define HS_CTRL_FIFO_EMPTY (1 << 18) ++#define LP_CTRL_FIFO_FULL (1 << 24) ++#define LP_CTRL_FIFO_HALF_EMPTY (1 << 25) ++#define LP_CTRL_FIFO_EMPTY (1 << 26) ++#define DBI_FIFO_EMPTY (1 << 27) ++#define DPI_FIFO_EMPTY (1 << 28) ++#define HS_LS_DBI_ENABLE_REG 0xb078 ++#define TXCLKESC_REG 0xb07c ++#define DPHY_PARAM_REG 0xb080 ++#define DBI_BW_CTRL_REG 0xb084 ++#define CLK_LANE_SWT_REG 0xb088 ++ ++/* ++ * MIPI Adapter registers ++ */ ++#define MIPI_CONTROL_REG 0xb104 ++#define MIPI_2X_CLOCK_BITS ((1 << 0) | (1 << 1)) ++#define MIPI_DATA_ADDRESS_REG 0xb108 ++#define MIPI_DATA_LENGTH_REG 0xb10C ++#define MIPI_COMMAND_ADDRESS_REG 0xb110 ++#define MIPI_COMMAND_LENGTH_REG 0xb114 ++#define MIPI_READ_DATA_RETURN_REG0 0xb118 ++#define MIPI_READ_DATA_RETURN_REG1 0xb11C ++#define MIPI_READ_DATA_RETURN_REG2 0xb120 ++#define MIPI_READ_DATA_RETURN_REG3 0xb124 ++#define MIPI_READ_DATA_RETURN_REG4 0xb128 ++#define MIPI_READ_DATA_RETURN_REG5 0xb12C ++#define MIPI_READ_DATA_RETURN_REG6 0xb130 ++#define MIPI_READ_DATA_RETURN_REG7 0xb134 ++#define MIPI_READ_DATA_VALID_REG 0xb138 ++ ++/* DBI COMMANDS */ ++#define soft_reset 0x01 ++/* ++ * The display module performs a software reset. ++ * Registers are written with their SW Reset default values. ++ */ ++#define get_power_mode 0x0a ++/* ++ * The display module returns the current power mode ++ */ ++#define get_address_mode 0x0b ++/* ++ * The display module returns the current status. ++ */ ++#define get_pixel_format 0x0c ++/* ++ * This command gets the pixel format for the RGB image data ++ * used by the interface. ++ */ ++#define get_display_mode 0x0d ++/* ++ * The display module returns the Display Image Mode status. ++ */ ++#define get_signal_mode 0x0e ++/* ++ * The display module returns the Display Signal Mode. ++ */ ++#define get_diagnostic_result 0x0f ++/* ++ * The display module returns the self-diagnostic results following ++ * a Sleep Out command. ++ */ ++#define enter_sleep_mode 0x10 ++/* ++ * This command causes the display module to enter the Sleep mode. ++ * In this mode, all unnecessary blocks inside the display module are ++ * disabled except interface communication. This is the lowest power ++ * mode the display module supports. ++ */ ++#define exit_sleep_mode 0x11 ++/* ++ * This command causes the display module to exit Sleep mode. ++ * All blocks inside the display module are enabled. ++ */ ++#define enter_partial_mode 0x12 ++/* ++ * This command causes the display module to enter the Partial Display ++ * Mode. The Partial Display Mode window is described by the ++ * set_partial_area command. ++ */ ++#define enter_normal_mode 0x13 ++/* ++ * This command causes the display module to enter the Normal mode. ++ * Normal Mode is defined as Partial Display mode and Scroll mode are off ++ */ ++#define exit_invert_mode 0x20 ++/* ++ * This command causes the display module to stop inverting the image ++ * data on the display device. The frame memory contents remain unchanged. ++ * No status bits are changed. ++ */ ++#define enter_invert_mode 0x21 ++/* ++ * This command causes the display module to invert the image data only on ++ * the display device. The frame memory contents remain unchanged. ++ * No status bits are changed. ++ */ ++#define set_gamma_curve 0x26 ++/* ++ * This command selects the desired gamma curve for the display device. ++ * Four fixed gamma curves are defined in section DCS spec. ++ */ ++#define set_display_off 0x28 ++/* ************************************************************************* *\ ++This command causes the display module to stop displaying the image data ++on the display device. The frame memory contents remain unchanged. ++No status bits are changed. ++\* ************************************************************************* */ ++#define set_display_on 0x29 ++/* ************************************************************************* *\ ++This command causes the display module to start displaying the image data ++on the display device. The frame memory contents remain unchanged. ++No status bits are changed. ++\* ************************************************************************* */ ++#define set_column_address 0x2a ++/* ++ * This command defines the column extent of the frame memory accessed by ++ * the hostprocessor with the read_memory_continue and ++ * write_memory_continue commands. ++ * No status bits are changed. ++ */ ++#define set_page_addr 0x2b ++/* ++ * This command defines the page extent of the frame memory accessed by ++ * the host processor with the write_memory_continue and ++ * read_memory_continue command. ++ * No status bits are changed. ++ */ ++#define write_mem_start 0x2c ++/* ++ * This command transfers image data from the host processor to the ++ * display modules frame memory starting at the pixel location specified ++ * by preceding set_column_address and set_page_address commands. ++ */ ++#define set_partial_area 0x30 ++/* ++ * This command defines the Partial Display mode s display area. ++ * There are two parameters associated with this command, the first ++ * defines the Start Row (SR) and the second the End Row (ER). SR and ER ++ * refer to the Frame Memory Line Pointer. ++ */ ++#define set_scroll_area 0x33 ++/* ++ * This command defines the display modules Vertical Scrolling Area. ++ */ ++#define set_tear_off 0x34 ++/* ++ * This command turns off the display modules Tearing Effect output ++ * signal on the TE signal line. ++ */ ++#define set_tear_on 0x35 ++/* ++ * This command turns on the display modules Tearing Effect output signal ++ * on the TE signal line. ++ */ ++#define set_address_mode 0x36 ++/* ++ * This command sets the data order for transfers from the host processor ++ * to display modules frame memory,bits B[7:5] and B3, and from the ++ * display modules frame memory to the display device, bits B[2:0] and B4. ++ */ ++#define set_scroll_start 0x37 ++/* ++ * This command sets the start of the vertical scrolling area in the frame ++ * memory. The vertical scrolling area is fully defined when this command ++ * is used with the set_scroll_area command The set_scroll_start command ++ * has one parameter, the Vertical Scroll Pointer. The VSP defines the ++ * line in the frame memory that is written to the display device as the ++ * first line of the vertical scroll area. ++ */ ++#define exit_idle_mode 0x38 ++/* ++ * This command causes the display module to exit Idle mode. ++ */ ++#define enter_idle_mode 0x39 ++/* ++ * This command causes the display module to enter Idle Mode. ++ * In Idle Mode, color expression is reduced. Colors are shown on the ++ * display device using the MSB of each of the R, G and B color ++ * components in the frame memory ++ */ ++#define set_pixel_format 0x3a ++/* ++ * This command sets the pixel format for the RGB image data used by the ++ * interface. ++ * Bits D[6:4] DPI Pixel Format Definition ++ * Bits D[2:0] DBI Pixel Format Definition ++ * Bits D7 and D3 are not used. ++ */ ++#define DCS_PIXEL_FORMAT_3bpp 0x1 ++#define DCS_PIXEL_FORMAT_8bpp 0x2 ++#define DCS_PIXEL_FORMAT_12bpp 0x3 ++#define DCS_PIXEL_FORMAT_16bpp 0x5 ++#define DCS_PIXEL_FORMAT_18bpp 0x6 ++#define DCS_PIXEL_FORMAT_24bpp 0x7 ++ ++#define write_mem_cont 0x3c ++ ++/* ++ * This command transfers image data from the host processor to the ++ * display module's frame memory continuing from the pixel location ++ * following the previous write_memory_continue or write_memory_start ++ * command. ++ */ ++#define set_tear_scanline 0x44 ++/* ++ * This command turns on the display modules Tearing Effect output signal ++ * on the TE signal line when the display module reaches line N. ++ */ ++#define get_scanline 0x45 ++/* ++ * The display module returns the current scanline, N, used to update the ++ * display device. The total number of scanlines on a display device is ++ * defined as VSYNC + VBP + VACT + VFP.The first scanline is defined as ++ * the first line of V Sync and is denoted as Line 0. ++ * When in Sleep Mode, the value returned by get_scanline is undefined. ++ */ ++ ++/* MCS or Generic COMMANDS */ ++/* MCS/generic data type */ ++#define GEN_SHORT_WRITE_0 0x03 /* generic short write, no parameters */ ++#define GEN_SHORT_WRITE_1 0x13 /* generic short write, 1 parameters */ ++#define GEN_SHORT_WRITE_2 0x23 /* generic short write, 2 parameters */ ++#define GEN_READ_0 0x04 /* generic read, no parameters */ ++#define GEN_READ_1 0x14 /* generic read, 1 parameters */ ++#define GEN_READ_2 0x24 /* generic read, 2 parameters */ ++#define GEN_LONG_WRITE 0x29 /* generic long write */ ++#define MCS_SHORT_WRITE_0 0x05 /* MCS short write, no parameters */ ++#define MCS_SHORT_WRITE_1 0x15 /* MCS short write, 1 parameters */ ++#define MCS_READ 0x06 /* MCS read, no parameters */ ++#define MCS_LONG_WRITE 0x39 /* MCS long write */ ++/* MCS/generic commands */ ++/* TPO MCS */ ++#define write_display_profile 0x50 ++#define write_display_brightness 0x51 ++#define write_ctrl_display 0x53 ++#define write_ctrl_cabc 0x55 ++ #define UI_IMAGE 0x01 ++ #define STILL_IMAGE 0x02 ++ #define MOVING_IMAGE 0x03 ++#define write_hysteresis 0x57 ++#define write_gamma_setting 0x58 ++#define write_cabc_min_bright 0x5e ++#define write_kbbc_profile 0x60 ++/* TMD MCS */ ++#define tmd_write_display_brightness 0x8c ++ ++/* ++ * This command is used to control ambient light, panel backlight ++ * brightness and gamma settings. ++ */ ++#define BRIGHT_CNTL_BLOCK_ON (1 << 5) ++#define AMBIENT_LIGHT_SENSE_ON (1 << 4) ++#define DISPLAY_DIMMING_ON (1 << 3) ++#define BACKLIGHT_ON (1 << 2) ++#define DISPLAY_BRIGHTNESS_AUTO (1 << 1) ++#define GAMMA_AUTO (1 << 0) ++ ++/* DCS Interface Pixel Formats */ ++#define DCS_PIXEL_FORMAT_3BPP 0x1 ++#define DCS_PIXEL_FORMAT_8BPP 0x2 ++#define DCS_PIXEL_FORMAT_12BPP 0x3 ++#define DCS_PIXEL_FORMAT_16BPP 0x5 ++#define DCS_PIXEL_FORMAT_18BPP 0x6 ++#define DCS_PIXEL_FORMAT_24BPP 0x7 ++/* ONE PARAMETER READ DATA */ ++#define addr_mode_data 0xfc ++#define diag_res_data 0x00 ++#define disp_mode_data 0x23 ++#define pxl_fmt_data 0x77 ++#define pwr_mode_data 0x74 ++#define sig_mode_data 0x00 ++/* TWO PARAMETERS READ DATA */ ++#define scanline_data1 0xff ++#define scanline_data2 0xff ++#define NON_BURST_MODE_SYNC_PULSE 0x01 /* Non Burst Mode ++ * with Sync Pulse ++ */ ++#define NON_BURST_MODE_SYNC_EVENTS 0x02 /* Non Burst Mode ++ * with Sync events ++ */ ++#define BURST_MODE 0x03 /* Burst Mode */ ++#define DBI_COMMAND_BUFFER_SIZE 0x240 /* 0x32 */ /* 0x120 */ ++ /* Allocate at least ++ * 0x100 Byte with 32 ++ * byte alignment ++ */ ++#define DBI_DATA_BUFFER_SIZE 0x120 /* Allocate at least ++ * 0x100 Byte with 32 ++ * byte alignment ++ */ ++#define DBI_CB_TIME_OUT 0xFFFF ++ ++#define GEN_FB_TIME_OUT 2000 ++ ++#define SKU_83 0x01 ++#define SKU_100 0x02 ++#define SKU_100L 0x04 ++#define SKU_BYPASS 0x08 ++ ++/* Some handy macros for playing with bitfields. */ ++#define PSB_MASK(high, low) (((1<<((high)-(low)+1))-1)<<(low)) ++#define SET_FIELD(value, field) (((value) << field ## _SHIFT) & field ## _MASK) ++#define GET_FIELD(word, field) (((word) & field ## _MASK) >> field ## _SHIFT) ++ ++#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) ++ ++/* PCI config space */ ++ ++#define SB_PCKT 0x02100 /* cedarview */ ++# define SB_OPCODE_MASK PSB_MASK(31, 16) ++# define SB_OPCODE_SHIFT 16 ++# define SB_OPCODE_READ 0 ++# define SB_OPCODE_WRITE 1 ++# define SB_DEST_MASK PSB_MASK(15, 8) ++# define SB_DEST_SHIFT 8 ++# define SB_DEST_DPLL 0x88 ++# define SB_BYTE_ENABLE_MASK PSB_MASK(7, 4) ++# define SB_BYTE_ENABLE_SHIFT 4 ++# define SB_BUSY (1 << 0) ++ ++#define DSPCLK_GATE_D 0x6200 ++# define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* Fixed value on CDV */ ++# define DPOUNIT_CLOCK_GATE_DISABLE (1 << 11) ++# define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) ++ ++#define RAMCLK_GATE_D 0x6210 ++ ++/* 32-bit value read/written from the DPIO reg. */ ++#define SB_DATA 0x02104 /* cedarview */ ++/* 32-bit address of the DPIO reg to be read/written. */ ++#define SB_ADDR 0x02108 /* cedarview */ ++#define DPIO_CFG 0x02110 /* cedarview */ ++# define DPIO_MODE_SELECT_1 (1 << 3) ++# define DPIO_MODE_SELECT_0 (1 << 2) ++# define DPIO_SFR_BYPASS (1 << 1) ++/* reset is active low */ ++# define DPIO_CMN_RESET_N (1 << 0) ++ ++/* Cedarview sideband registers */ ++#define _SB_M_A 0x8008 ++#define _SB_M_B 0x8028 ++#define SB_M(pipe) _PIPE(pipe, _SB_M_A, _SB_M_B) ++# define SB_M_DIVIDER_MASK (0xFF << 24) ++# define SB_M_DIVIDER_SHIFT 24 ++ ++#define _SB_N_VCO_A 0x8014 ++#define _SB_N_VCO_B 0x8034 ++#define SB_N_VCO(pipe) _PIPE(pipe, _SB_N_VCO_A, _SB_N_VCO_B) ++#define SB_N_VCO_SEL_MASK PSB_MASK(31, 30) ++#define SB_N_VCO_SEL_SHIFT 30 ++#define SB_N_DIVIDER_MASK PSB_MASK(29, 26) ++#define SB_N_DIVIDER_SHIFT 26 ++#define SB_N_CB_TUNE_MASK PSB_MASK(25, 24) ++#define SB_N_CB_TUNE_SHIFT 24 ++ ++#define _SB_REF_A 0x8018 ++#define _SB_REF_B 0x8038 ++#define SB_REF_SFR(pipe) _PIPE(pipe, _SB_REF_A, _SB_REF_B) ++ ++#define _SB_P_A 0x801c ++#define _SB_P_B 0x803c ++#define SB_P(pipe) _PIPE(pipe, _SB_P_A, _SB_P_B) ++#define SB_P2_DIVIDER_MASK PSB_MASK(31, 30) ++#define SB_P2_DIVIDER_SHIFT 30 ++#define SB_P2_10 0 /* HDMI, DP, DAC */ ++#define SB_P2_5 1 /* DAC */ ++#define SB_P2_14 2 /* LVDS single */ ++#define SB_P2_7 3 /* LVDS double */ ++#define SB_P1_DIVIDER_MASK PSB_MASK(15, 12) ++#define SB_P1_DIVIDER_SHIFT 12 ++ ++#define PSB_LANE0 0x120 ++#define PSB_LANE1 0x220 ++#define PSB_LANE2 0x2320 ++#define PSB_LANE3 0x2420 ++ ++#define LANE_PLL_MASK (0x7 << 20) ++#define LANE_PLL_ENABLE (0x3 << 20) ++ ++ ++#endif +diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c +new file mode 100644 +index 0000000..36330ca +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c +@@ -0,0 +1,2607 @@ ++/* ++ * Copyright 2006 Dave Airlie ++ * Copyright © 2006-2007 Intel Corporation ++ * Jesse Barnes ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Eric Anholt ++ */ ++#include ++#include ++#include ++#include ++#include "drmP.h" ++#include "drm.h" ++#include "drm_crtc.h" ++#include "drm_edid.h" ++#include "psb_intel_drv.h" ++#include "gma_drm.h" ++#include "psb_drv.h" ++#include "psb_intel_sdvo_regs.h" ++#include "psb_intel_reg.h" ++ ++#define SDVO_TMDS_MASK (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1) ++#define SDVO_RGB_MASK (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1) ++#define SDVO_LVDS_MASK (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1) ++#define SDVO_TV_MASK (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0) ++ ++#define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\ ++ SDVO_TV_MASK) ++ ++#define IS_TV(c) (c->output_flag & SDVO_TV_MASK) ++#define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) ++#define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) ++#define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) ++ ++ ++static const char *tv_format_names[] = { ++ "NTSC_M" , "NTSC_J" , "NTSC_443", ++ "PAL_B" , "PAL_D" , "PAL_G" , ++ "PAL_H" , "PAL_I" , "PAL_M" , ++ "PAL_N" , "PAL_NC" , "PAL_60" , ++ "SECAM_B" , "SECAM_D" , "SECAM_G" , ++ "SECAM_K" , "SECAM_K1", "SECAM_L" , ++ "SECAM_60" ++}; ++ ++#define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names)) ++ ++struct psb_intel_sdvo { ++ struct psb_intel_encoder base; ++ ++ struct i2c_adapter *i2c; ++ u8 slave_addr; ++ ++ struct i2c_adapter ddc; ++ ++ /* Register for the SDVO device: SDVOB or SDVOC */ ++ int sdvo_reg; ++ ++ /* Active outputs controlled by this SDVO output */ ++ uint16_t controlled_output; ++ ++ /* ++ * Capabilities of the SDVO device returned by ++ * i830_sdvo_get_capabilities() ++ */ ++ struct psb_intel_sdvo_caps caps; ++ ++ /* Pixel clock limitations reported by the SDVO device, in kHz */ ++ int pixel_clock_min, pixel_clock_max; ++ ++ /* ++ * For multiple function SDVO device, ++ * this is for current attached outputs. ++ */ ++ uint16_t attached_output; ++ ++ /** ++ * This is used to select the color range of RBG outputs in HDMI mode. ++ * It is only valid when using TMDS encoding and 8 bit per color mode. ++ */ ++ uint32_t color_range; ++ ++ /** ++ * This is set if we're going to treat the device as TV-out. ++ * ++ * While we have these nice friendly flags for output types that ought ++ * to decide this for us, the S-Video output on our HDMI+S-Video card ++ * shows up as RGB1 (VGA). ++ */ ++ bool is_tv; ++ ++ /* This is for current tv format name */ ++ int tv_format_index; ++ ++ /** ++ * This is set if we treat the device as HDMI, instead of DVI. ++ */ ++ bool is_hdmi; ++ bool has_hdmi_monitor; ++ bool has_hdmi_audio; ++ ++ /** ++ * This is set if we detect output of sdvo device as LVDS and ++ * have a valid fixed mode to use with the panel. ++ */ ++ bool is_lvds; ++ ++ /** ++ * This is sdvo fixed pannel mode pointer ++ */ ++ struct drm_display_mode *sdvo_lvds_fixed_mode; ++ ++ /* DDC bus used by this SDVO encoder */ ++ uint8_t ddc_bus; ++ ++ /* Input timings for adjusted_mode */ ++ struct psb_intel_sdvo_dtd input_dtd; ++}; ++ ++struct psb_intel_sdvo_connector { ++ struct psb_intel_connector base; ++ ++ /* Mark the type of connector */ ++ uint16_t output_flag; ++ ++ int force_audio; ++ ++ /* This contains all current supported TV format */ ++ u8 tv_format_supported[TV_FORMAT_NUM]; ++ int format_supported_num; ++ struct drm_property *tv_format; ++ ++ /* add the property for the SDVO-TV */ ++ struct drm_property *left; ++ struct drm_property *right; ++ struct drm_property *top; ++ struct drm_property *bottom; ++ struct drm_property *hpos; ++ struct drm_property *vpos; ++ struct drm_property *contrast; ++ struct drm_property *saturation; ++ struct drm_property *hue; ++ struct drm_property *sharpness; ++ struct drm_property *flicker_filter; ++ struct drm_property *flicker_filter_adaptive; ++ struct drm_property *flicker_filter_2d; ++ struct drm_property *tv_chroma_filter; ++ struct drm_property *tv_luma_filter; ++ struct drm_property *dot_crawl; ++ ++ /* add the property for the SDVO-TV/LVDS */ ++ struct drm_property *brightness; ++ ++ /* Add variable to record current setting for the above property */ ++ u32 left_margin, right_margin, top_margin, bottom_margin; ++ ++ /* this is to get the range of margin.*/ ++ u32 max_hscan, max_vscan; ++ u32 max_hpos, cur_hpos; ++ u32 max_vpos, cur_vpos; ++ u32 cur_brightness, max_brightness; ++ u32 cur_contrast, max_contrast; ++ u32 cur_saturation, max_saturation; ++ u32 cur_hue, max_hue; ++ u32 cur_sharpness, max_sharpness; ++ u32 cur_flicker_filter, max_flicker_filter; ++ u32 cur_flicker_filter_adaptive, max_flicker_filter_adaptive; ++ u32 cur_flicker_filter_2d, max_flicker_filter_2d; ++ u32 cur_tv_chroma_filter, max_tv_chroma_filter; ++ u32 cur_tv_luma_filter, max_tv_luma_filter; ++ u32 cur_dot_crawl, max_dot_crawl; ++}; ++ ++static struct psb_intel_sdvo *to_psb_intel_sdvo(struct drm_encoder *encoder) ++{ ++ return container_of(encoder, struct psb_intel_sdvo, base.base); ++} ++ ++static struct psb_intel_sdvo *intel_attached_sdvo(struct drm_connector *connector) ++{ ++ return container_of(psb_intel_attached_encoder(connector), ++ struct psb_intel_sdvo, base); ++} ++ ++static struct psb_intel_sdvo_connector *to_psb_intel_sdvo_connector(struct drm_connector *connector) ++{ ++ return container_of(to_psb_intel_connector(connector), struct psb_intel_sdvo_connector, base); ++} ++ ++static bool ++psb_intel_sdvo_output_setup(struct psb_intel_sdvo *psb_intel_sdvo, uint16_t flags); ++static bool ++psb_intel_sdvo_tv_create_property(struct psb_intel_sdvo *psb_intel_sdvo, ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector, ++ int type); ++static bool ++psb_intel_sdvo_create_enhance_property(struct psb_intel_sdvo *psb_intel_sdvo, ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector); ++ ++/** ++ * Writes the SDVOB or SDVOC with the given value, but always writes both ++ * SDVOB and SDVOC to work around apparent hardware issues (according to ++ * comments in the BIOS). ++ */ ++static void psb_intel_sdvo_write_sdvox(struct psb_intel_sdvo *psb_intel_sdvo, u32 val) ++{ ++ struct drm_device *dev = psb_intel_sdvo->base.base.dev; ++ u32 bval = val, cval = val; ++ int i; ++ ++ if (psb_intel_sdvo->sdvo_reg == SDVOB) { ++ cval = REG_READ(SDVOC); ++ } else { ++ bval = REG_READ(SDVOB); ++ } ++ /* ++ * Write the registers twice for luck. Sometimes, ++ * writing them only once doesn't appear to 'stick'. ++ * The BIOS does this too. Yay, magic ++ */ ++ for (i = 0; i < 2; i++) ++ { ++ REG_WRITE(SDVOB, bval); ++ REG_READ(SDVOB); ++ REG_WRITE(SDVOC, cval); ++ REG_READ(SDVOC); ++ } ++} ++ ++static bool psb_intel_sdvo_read_byte(struct psb_intel_sdvo *psb_intel_sdvo, u8 addr, u8 *ch) ++{ ++ struct i2c_msg msgs[] = { ++ { ++ .addr = psb_intel_sdvo->slave_addr, ++ .flags = 0, ++ .len = 1, ++ .buf = &addr, ++ }, ++ { ++ .addr = psb_intel_sdvo->slave_addr, ++ .flags = I2C_M_RD, ++ .len = 1, ++ .buf = ch, ++ } ++ }; ++ int ret; ++ ++ if ((ret = i2c_transfer(psb_intel_sdvo->i2c, msgs, 2)) == 2) ++ return true; ++ ++ DRM_DEBUG_KMS("i2c transfer returned %d\n", ret); ++ return false; ++} ++ ++#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} ++/** Mapping of command numbers to names, for debug output */ ++static const struct _sdvo_cmd_name { ++ u8 cmd; ++ const char *name; ++} sdvo_cmd_names[] = { ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POWER_STATE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DISPLAY_POWER_STATE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS), ++ ++ /* Add the op code for SDVO enhancements */ ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HPOS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HPOS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HPOS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_VPOS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_VPOS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_VPOS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_2D), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_2D), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_2D), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SHARPNESS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SHARPNESS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SHARPNESS), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DOT_CRAWL), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DOT_CRAWL), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_CHROMA_FILTER), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_CHROMA_FILTER), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_CHROMA_FILTER), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_LUMA_FILTER), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_LUMA_FILTER), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_LUMA_FILTER), ++ ++ /* HDMI op code */ ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_PIXEL_REPLI), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_COLORIMETRY), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_AUDIO_STAT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_AV_SPLIT), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_TXRATE), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_DATA), ++ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA), ++}; ++ ++#define IS_SDVOB(reg) (reg == SDVOB) ++#define SDVO_NAME(svdo) (IS_SDVOB((svdo)->sdvo_reg) ? "SDVOB" : "SDVOC") ++ ++static void psb_intel_sdvo_debug_write(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd, ++ const void *args, int args_len) ++{ ++ int i; ++ ++ DRM_DEBUG_KMS("%s: W: %02X ", ++ SDVO_NAME(psb_intel_sdvo), cmd); ++ for (i = 0; i < args_len; i++) ++ DRM_LOG_KMS("%02X ", ((u8 *)args)[i]); ++ for (; i < 8; i++) ++ DRM_LOG_KMS(" "); ++ for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) { ++ if (cmd == sdvo_cmd_names[i].cmd) { ++ DRM_LOG_KMS("(%s)", sdvo_cmd_names[i].name); ++ break; ++ } ++ } ++ if (i == ARRAY_SIZE(sdvo_cmd_names)) ++ DRM_LOG_KMS("(%02X)", cmd); ++ DRM_LOG_KMS("\n"); ++} ++ ++static const char *cmd_status_names[] = { ++ "Power on", ++ "Success", ++ "Not supported", ++ "Invalid arg", ++ "Pending", ++ "Target not specified", ++ "Scaling not supported" ++}; ++ ++static bool psb_intel_sdvo_write_cmd(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd, ++ const void *args, int args_len) ++{ ++ u8 buf[args_len*2 + 2], status; ++ struct i2c_msg msgs[args_len + 3]; ++ int i, ret; ++ ++ psb_intel_sdvo_debug_write(psb_intel_sdvo, cmd, args, args_len); ++ ++ for (i = 0; i < args_len; i++) { ++ msgs[i].addr = psb_intel_sdvo->slave_addr; ++ msgs[i].flags = 0; ++ msgs[i].len = 2; ++ msgs[i].buf = buf + 2 *i; ++ buf[2*i + 0] = SDVO_I2C_ARG_0 - i; ++ buf[2*i + 1] = ((u8*)args)[i]; ++ } ++ msgs[i].addr = psb_intel_sdvo->slave_addr; ++ msgs[i].flags = 0; ++ msgs[i].len = 2; ++ msgs[i].buf = buf + 2*i; ++ buf[2*i + 0] = SDVO_I2C_OPCODE; ++ buf[2*i + 1] = cmd; ++ ++ /* the following two are to read the response */ ++ status = SDVO_I2C_CMD_STATUS; ++ msgs[i+1].addr = psb_intel_sdvo->slave_addr; ++ msgs[i+1].flags = 0; ++ msgs[i+1].len = 1; ++ msgs[i+1].buf = &status; ++ ++ msgs[i+2].addr = psb_intel_sdvo->slave_addr; ++ msgs[i+2].flags = I2C_M_RD; ++ msgs[i+2].len = 1; ++ msgs[i+2].buf = &status; ++ ++ ret = i2c_transfer(psb_intel_sdvo->i2c, msgs, i+3); ++ if (ret < 0) { ++ DRM_DEBUG_KMS("I2c transfer returned %d\n", ret); ++ return false; ++ } ++ if (ret != i+3) { ++ /* failure in I2C transfer */ ++ DRM_DEBUG_KMS("I2c transfer returned %d/%d\n", ret, i+3); ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo, ++ void *response, int response_len) ++{ ++ u8 retry = 5; ++ u8 status; ++ int i; ++ ++ DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(psb_intel_sdvo)); ++ ++ /* ++ * The documentation states that all commands will be ++ * processed within 15µs, and that we need only poll ++ * the status byte a maximum of 3 times in order for the ++ * command to be complete. ++ * ++ * Check 5 times in case the hardware failed to read the docs. ++ */ ++ if (!psb_intel_sdvo_read_byte(psb_intel_sdvo, ++ SDVO_I2C_CMD_STATUS, ++ &status)) ++ goto log_fail; ++ ++ while (status == SDVO_CMD_STATUS_PENDING && retry--) { ++ udelay(15); ++ if (!psb_intel_sdvo_read_byte(psb_intel_sdvo, ++ SDVO_I2C_CMD_STATUS, ++ &status)) ++ goto log_fail; ++ } ++ ++ if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) ++ DRM_LOG_KMS("(%s)", cmd_status_names[status]); ++ else ++ DRM_LOG_KMS("(??? %d)", status); ++ ++ if (status != SDVO_CMD_STATUS_SUCCESS) ++ goto log_fail; ++ ++ /* Read the command response */ ++ for (i = 0; i < response_len; i++) { ++ if (!psb_intel_sdvo_read_byte(psb_intel_sdvo, ++ SDVO_I2C_RETURN_0 + i, ++ &((u8 *)response)[i])) ++ goto log_fail; ++ DRM_LOG_KMS(" %02X", ((u8 *)response)[i]); ++ } ++ DRM_LOG_KMS("\n"); ++ return true; ++ ++log_fail: ++ DRM_LOG_KMS("... failed\n"); ++ return false; ++} ++ ++static int psb_intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) ++{ ++ if (mode->clock >= 100000) ++ return 1; ++ else if (mode->clock >= 50000) ++ return 2; ++ else ++ return 4; ++} ++ ++static bool psb_intel_sdvo_set_control_bus_switch(struct psb_intel_sdvo *psb_intel_sdvo, ++ u8 ddc_bus) ++{ ++ /* This must be the immediately preceding write before the i2c xfer */ ++ return psb_intel_sdvo_write_cmd(psb_intel_sdvo, ++ SDVO_CMD_SET_CONTROL_BUS_SWITCH, ++ &ddc_bus, 1); ++} ++ ++static bool psb_intel_sdvo_set_value(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd, const void *data, int len) ++{ ++ if (!psb_intel_sdvo_write_cmd(psb_intel_sdvo, cmd, data, len)) ++ return false; ++ ++ return psb_intel_sdvo_read_response(psb_intel_sdvo, NULL, 0); ++} ++ ++static bool ++psb_intel_sdvo_get_value(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd, void *value, int len) ++{ ++ if (!psb_intel_sdvo_write_cmd(psb_intel_sdvo, cmd, NULL, 0)) ++ return false; ++ ++ return psb_intel_sdvo_read_response(psb_intel_sdvo, value, len); ++} ++ ++static bool psb_intel_sdvo_set_target_input(struct psb_intel_sdvo *psb_intel_sdvo) ++{ ++ struct psb_intel_sdvo_set_target_input_args targets = {0}; ++ return psb_intel_sdvo_set_value(psb_intel_sdvo, ++ SDVO_CMD_SET_TARGET_INPUT, ++ &targets, sizeof(targets)); ++} ++ ++/** ++ * Return whether each input is trained. ++ * ++ * This function is making an assumption about the layout of the response, ++ * which should be checked against the docs. ++ */ ++static bool psb_intel_sdvo_get_trained_inputs(struct psb_intel_sdvo *psb_intel_sdvo, bool *input_1, bool *input_2) ++{ ++ struct psb_intel_sdvo_get_trained_inputs_response response; ++ ++ BUILD_BUG_ON(sizeof(response) != 1); ++ if (!psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_TRAINED_INPUTS, ++ &response, sizeof(response))) ++ return false; ++ ++ *input_1 = response.input0_trained; ++ *input_2 = response.input1_trained; ++ return true; ++} ++ ++static bool psb_intel_sdvo_set_active_outputs(struct psb_intel_sdvo *psb_intel_sdvo, ++ u16 outputs) ++{ ++ return psb_intel_sdvo_set_value(psb_intel_sdvo, ++ SDVO_CMD_SET_ACTIVE_OUTPUTS, ++ &outputs, sizeof(outputs)); ++} ++ ++static bool psb_intel_sdvo_set_encoder_power_state(struct psb_intel_sdvo *psb_intel_sdvo, ++ int mode) ++{ ++ u8 state = SDVO_ENCODER_STATE_ON; ++ ++ switch (mode) { ++ case DRM_MODE_DPMS_ON: ++ state = SDVO_ENCODER_STATE_ON; ++ break; ++ case DRM_MODE_DPMS_STANDBY: ++ state = SDVO_ENCODER_STATE_STANDBY; ++ break; ++ case DRM_MODE_DPMS_SUSPEND: ++ state = SDVO_ENCODER_STATE_SUSPEND; ++ break; ++ case DRM_MODE_DPMS_OFF: ++ state = SDVO_ENCODER_STATE_OFF; ++ break; ++ } ++ ++ return psb_intel_sdvo_set_value(psb_intel_sdvo, ++ SDVO_CMD_SET_ENCODER_POWER_STATE, &state, sizeof(state)); ++} ++ ++static bool psb_intel_sdvo_get_input_pixel_clock_range(struct psb_intel_sdvo *psb_intel_sdvo, ++ int *clock_min, ++ int *clock_max) ++{ ++ struct psb_intel_sdvo_pixel_clock_range clocks; ++ ++ BUILD_BUG_ON(sizeof(clocks) != 4); ++ if (!psb_intel_sdvo_get_value(psb_intel_sdvo, ++ SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, ++ &clocks, sizeof(clocks))) ++ return false; ++ ++ /* Convert the values from units of 10 kHz to kHz. */ ++ *clock_min = clocks.min * 10; ++ *clock_max = clocks.max * 10; ++ return true; ++} ++ ++static bool psb_intel_sdvo_set_target_output(struct psb_intel_sdvo *psb_intel_sdvo, ++ u16 outputs) ++{ ++ return psb_intel_sdvo_set_value(psb_intel_sdvo, ++ SDVO_CMD_SET_TARGET_OUTPUT, ++ &outputs, sizeof(outputs)); ++} ++ ++static bool psb_intel_sdvo_set_timing(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd, ++ struct psb_intel_sdvo_dtd *dtd) ++{ ++ return psb_intel_sdvo_set_value(psb_intel_sdvo, cmd, &dtd->part1, sizeof(dtd->part1)) && ++ psb_intel_sdvo_set_value(psb_intel_sdvo, cmd + 1, &dtd->part2, sizeof(dtd->part2)); ++} ++ ++static bool psb_intel_sdvo_set_input_timing(struct psb_intel_sdvo *psb_intel_sdvo, ++ struct psb_intel_sdvo_dtd *dtd) ++{ ++ return psb_intel_sdvo_set_timing(psb_intel_sdvo, ++ SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd); ++} ++ ++static bool psb_intel_sdvo_set_output_timing(struct psb_intel_sdvo *psb_intel_sdvo, ++ struct psb_intel_sdvo_dtd *dtd) ++{ ++ return psb_intel_sdvo_set_timing(psb_intel_sdvo, ++ SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd); ++} ++ ++static bool ++psb_intel_sdvo_create_preferred_input_timing(struct psb_intel_sdvo *psb_intel_sdvo, ++ uint16_t clock, ++ uint16_t width, ++ uint16_t height) ++{ ++ struct psb_intel_sdvo_preferred_input_timing_args args; ++ ++ memset(&args, 0, sizeof(args)); ++ args.clock = clock; ++ args.width = width; ++ args.height = height; ++ args.interlace = 0; ++ ++ if (psb_intel_sdvo->is_lvds && ++ (psb_intel_sdvo->sdvo_lvds_fixed_mode->hdisplay != width || ++ psb_intel_sdvo->sdvo_lvds_fixed_mode->vdisplay != height)) ++ args.scaled = 1; ++ ++ return psb_intel_sdvo_set_value(psb_intel_sdvo, ++ SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, ++ &args, sizeof(args)); ++} ++ ++static bool psb_intel_sdvo_get_preferred_input_timing(struct psb_intel_sdvo *psb_intel_sdvo, ++ struct psb_intel_sdvo_dtd *dtd) ++{ ++ BUILD_BUG_ON(sizeof(dtd->part1) != 8); ++ BUILD_BUG_ON(sizeof(dtd->part2) != 8); ++ return psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1, ++ &dtd->part1, sizeof(dtd->part1)) && ++ psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2, ++ &dtd->part2, sizeof(dtd->part2)); ++} ++ ++static bool psb_intel_sdvo_set_clock_rate_mult(struct psb_intel_sdvo *psb_intel_sdvo, u8 val) ++{ ++ return psb_intel_sdvo_set_value(psb_intel_sdvo, SDVO_CMD_SET_CLOCK_RATE_MULT, &val, 1); ++} ++ ++static void psb_intel_sdvo_get_dtd_from_mode(struct psb_intel_sdvo_dtd *dtd, ++ const struct drm_display_mode *mode) ++{ ++ uint16_t width, height; ++ uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len; ++ uint16_t h_sync_offset, v_sync_offset; ++ ++ width = mode->crtc_hdisplay; ++ height = mode->crtc_vdisplay; ++ ++ /* do some mode translations */ ++ h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start; ++ h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; ++ ++ v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start; ++ v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; ++ ++ h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; ++ v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; ++ ++ dtd->part1.clock = mode->clock / 10; ++ dtd->part1.h_active = width & 0xff; ++ dtd->part1.h_blank = h_blank_len & 0xff; ++ dtd->part1.h_high = (((width >> 8) & 0xf) << 4) | ++ ((h_blank_len >> 8) & 0xf); ++ dtd->part1.v_active = height & 0xff; ++ dtd->part1.v_blank = v_blank_len & 0xff; ++ dtd->part1.v_high = (((height >> 8) & 0xf) << 4) | ++ ((v_blank_len >> 8) & 0xf); ++ ++ dtd->part2.h_sync_off = h_sync_offset & 0xff; ++ dtd->part2.h_sync_width = h_sync_len & 0xff; ++ dtd->part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | ++ (v_sync_len & 0xf); ++ dtd->part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) | ++ ((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) | ++ ((v_sync_len & 0x30) >> 4); ++ ++ dtd->part2.dtd_flags = 0x18; ++ if (mode->flags & DRM_MODE_FLAG_PHSYNC) ++ dtd->part2.dtd_flags |= 0x2; ++ if (mode->flags & DRM_MODE_FLAG_PVSYNC) ++ dtd->part2.dtd_flags |= 0x4; ++ ++ dtd->part2.sdvo_flags = 0; ++ dtd->part2.v_sync_off_high = v_sync_offset & 0xc0; ++ dtd->part2.reserved = 0; ++} ++ ++static void psb_intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode, ++ const struct psb_intel_sdvo_dtd *dtd) ++{ ++ mode->hdisplay = dtd->part1.h_active; ++ mode->hdisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8; ++ mode->hsync_start = mode->hdisplay + dtd->part2.h_sync_off; ++ mode->hsync_start += (dtd->part2.sync_off_width_high & 0xc0) << 2; ++ mode->hsync_end = mode->hsync_start + dtd->part2.h_sync_width; ++ mode->hsync_end += (dtd->part2.sync_off_width_high & 0x30) << 4; ++ mode->htotal = mode->hdisplay + dtd->part1.h_blank; ++ mode->htotal += (dtd->part1.h_high & 0xf) << 8; ++ ++ mode->vdisplay = dtd->part1.v_active; ++ mode->vdisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8; ++ mode->vsync_start = mode->vdisplay; ++ mode->vsync_start += (dtd->part2.v_sync_off_width >> 4) & 0xf; ++ mode->vsync_start += (dtd->part2.sync_off_width_high & 0x0c) << 2; ++ mode->vsync_start += dtd->part2.v_sync_off_high & 0xc0; ++ mode->vsync_end = mode->vsync_start + ++ (dtd->part2.v_sync_off_width & 0xf); ++ mode->vsync_end += (dtd->part2.sync_off_width_high & 0x3) << 4; ++ mode->vtotal = mode->vdisplay + dtd->part1.v_blank; ++ mode->vtotal += (dtd->part1.v_high & 0xf) << 8; ++ ++ mode->clock = dtd->part1.clock * 10; ++ ++ mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); ++ if (dtd->part2.dtd_flags & 0x2) ++ mode->flags |= DRM_MODE_FLAG_PHSYNC; ++ if (dtd->part2.dtd_flags & 0x4) ++ mode->flags |= DRM_MODE_FLAG_PVSYNC; ++} ++ ++static bool psb_intel_sdvo_check_supp_encode(struct psb_intel_sdvo *psb_intel_sdvo) ++{ ++ struct psb_intel_sdvo_encode encode; ++ ++ BUILD_BUG_ON(sizeof(encode) != 2); ++ return psb_intel_sdvo_get_value(psb_intel_sdvo, ++ SDVO_CMD_GET_SUPP_ENCODE, ++ &encode, sizeof(encode)); ++} ++ ++static bool psb_intel_sdvo_set_encode(struct psb_intel_sdvo *psb_intel_sdvo, ++ uint8_t mode) ++{ ++ return psb_intel_sdvo_set_value(psb_intel_sdvo, SDVO_CMD_SET_ENCODE, &mode, 1); ++} ++ ++static bool psb_intel_sdvo_set_colorimetry(struct psb_intel_sdvo *psb_intel_sdvo, ++ uint8_t mode) ++{ ++ return psb_intel_sdvo_set_value(psb_intel_sdvo, SDVO_CMD_SET_COLORIMETRY, &mode, 1); ++} ++ ++#if 0 ++static void psb_intel_sdvo_dump_hdmi_buf(struct psb_intel_sdvo *psb_intel_sdvo) ++{ ++ int i, j; ++ uint8_t set_buf_index[2]; ++ uint8_t av_split; ++ uint8_t buf_size; ++ uint8_t buf[48]; ++ uint8_t *pos; ++ ++ psb_intel_sdvo_get_value(encoder, SDVO_CMD_GET_HBUF_AV_SPLIT, &av_split, 1); ++ ++ for (i = 0; i <= av_split; i++) { ++ set_buf_index[0] = i; set_buf_index[1] = 0; ++ psb_intel_sdvo_write_cmd(encoder, SDVO_CMD_SET_HBUF_INDEX, ++ set_buf_index, 2); ++ psb_intel_sdvo_write_cmd(encoder, SDVO_CMD_GET_HBUF_INFO, NULL, 0); ++ psb_intel_sdvo_read_response(encoder, &buf_size, 1); ++ ++ pos = buf; ++ for (j = 0; j <= buf_size; j += 8) { ++ psb_intel_sdvo_write_cmd(encoder, SDVO_CMD_GET_HBUF_DATA, ++ NULL, 0); ++ psb_intel_sdvo_read_response(encoder, pos, 8); ++ pos += 8; ++ } ++ } ++} ++#endif ++ ++static bool psb_intel_sdvo_set_avi_infoframe(struct psb_intel_sdvo *psb_intel_sdvo) ++{ ++ DRM_INFO("HDMI is not supported yet"); ++ ++ return false; ++#if 0 ++ struct dip_infoframe avi_if = { ++ .type = DIP_TYPE_AVI, ++ .ver = DIP_VERSION_AVI, ++ .len = DIP_LEN_AVI, ++ }; ++ uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; ++ uint8_t set_buf_index[2] = { 1, 0 }; ++ uint64_t *data = (uint64_t *)&avi_if; ++ unsigned i; ++ ++ intel_dip_infoframe_csum(&avi_if); ++ ++ if (!psb_intel_sdvo_set_value(psb_intel_sdvo, ++ SDVO_CMD_SET_HBUF_INDEX, ++ set_buf_index, 2)) ++ return false; ++ ++ for (i = 0; i < sizeof(avi_if); i += 8) { ++ if (!psb_intel_sdvo_set_value(psb_intel_sdvo, ++ SDVO_CMD_SET_HBUF_DATA, ++ data, 8)) ++ return false; ++ data++; ++ } ++ ++ return psb_intel_sdvo_set_value(psb_intel_sdvo, ++ SDVO_CMD_SET_HBUF_TXRATE, ++ &tx_rate, 1); ++#endif ++} ++ ++static bool psb_intel_sdvo_set_tv_format(struct psb_intel_sdvo *psb_intel_sdvo) ++{ ++ struct psb_intel_sdvo_tv_format format; ++ uint32_t format_map; ++ ++ format_map = 1 << psb_intel_sdvo->tv_format_index; ++ memset(&format, 0, sizeof(format)); ++ memcpy(&format, &format_map, min(sizeof(format), sizeof(format_map))); ++ ++ BUILD_BUG_ON(sizeof(format) != 6); ++ return psb_intel_sdvo_set_value(psb_intel_sdvo, ++ SDVO_CMD_SET_TV_FORMAT, ++ &format, sizeof(format)); ++} ++ ++static bool ++psb_intel_sdvo_set_output_timings_from_mode(struct psb_intel_sdvo *psb_intel_sdvo, ++ struct drm_display_mode *mode) ++{ ++ struct psb_intel_sdvo_dtd output_dtd; ++ ++ if (!psb_intel_sdvo_set_target_output(psb_intel_sdvo, ++ psb_intel_sdvo->attached_output)) ++ return false; ++ ++ psb_intel_sdvo_get_dtd_from_mode(&output_dtd, mode); ++ if (!psb_intel_sdvo_set_output_timing(psb_intel_sdvo, &output_dtd)) ++ return false; ++ ++ return true; ++} ++ ++static bool ++psb_intel_sdvo_set_input_timings_for_mode(struct psb_intel_sdvo *psb_intel_sdvo, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ /* Reset the input timing to the screen. Assume always input 0. */ ++ if (!psb_intel_sdvo_set_target_input(psb_intel_sdvo)) ++ return false; ++ ++ if (!psb_intel_sdvo_create_preferred_input_timing(psb_intel_sdvo, ++ mode->clock / 10, ++ mode->hdisplay, ++ mode->vdisplay)) ++ return false; ++ ++ if (!psb_intel_sdvo_get_preferred_input_timing(psb_intel_sdvo, ++ &psb_intel_sdvo->input_dtd)) ++ return false; ++ ++ psb_intel_sdvo_get_mode_from_dtd(adjusted_mode, &psb_intel_sdvo->input_dtd); ++ ++ drm_mode_set_crtcinfo(adjusted_mode, 0); ++ return true; ++} ++ ++static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); ++ int multiplier; ++ ++ /* We need to construct preferred input timings based on our ++ * output timings. To do that, we have to set the output ++ * timings, even though this isn't really the right place in ++ * the sequence to do it. Oh well. ++ */ ++ if (psb_intel_sdvo->is_tv) { ++ if (!psb_intel_sdvo_set_output_timings_from_mode(psb_intel_sdvo, mode)) ++ return false; ++ ++ (void) psb_intel_sdvo_set_input_timings_for_mode(psb_intel_sdvo, ++ mode, ++ adjusted_mode); ++ } else if (psb_intel_sdvo->is_lvds) { ++ if (!psb_intel_sdvo_set_output_timings_from_mode(psb_intel_sdvo, ++ psb_intel_sdvo->sdvo_lvds_fixed_mode)) ++ return false; ++ ++ (void) psb_intel_sdvo_set_input_timings_for_mode(psb_intel_sdvo, ++ mode, ++ adjusted_mode); ++ } ++ ++ /* Make the CRTC code factor in the SDVO pixel multiplier. The ++ * SDVO device will factor out the multiplier during mode_set. ++ */ ++ multiplier = psb_intel_sdvo_get_pixel_multiplier(adjusted_mode); ++ psb_intel_mode_set_pixel_multiplier(adjusted_mode, multiplier); ++ ++ return true; ++} ++ ++static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct drm_crtc *crtc = encoder->crtc; ++ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); ++ struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); ++ u32 sdvox; ++ struct psb_intel_sdvo_in_out_map in_out; ++ struct psb_intel_sdvo_dtd input_dtd; ++ int pixel_multiplier = psb_intel_mode_get_pixel_multiplier(adjusted_mode); ++ int rate; ++ ++ if (!mode) ++ return; ++ ++ /* First, set the input mapping for the first input to our controlled ++ * output. This is only correct if we're a single-input device, in ++ * which case the first input is the output from the appropriate SDVO ++ * channel on the motherboard. In a two-input device, the first input ++ * will be SDVOB and the second SDVOC. ++ */ ++ in_out.in0 = psb_intel_sdvo->attached_output; ++ in_out.in1 = 0; ++ ++ psb_intel_sdvo_set_value(psb_intel_sdvo, ++ SDVO_CMD_SET_IN_OUT_MAP, ++ &in_out, sizeof(in_out)); ++ ++ /* Set the output timings to the screen */ ++ if (!psb_intel_sdvo_set_target_output(psb_intel_sdvo, ++ psb_intel_sdvo->attached_output)) ++ return; ++ ++ /* We have tried to get input timing in mode_fixup, and filled into ++ * adjusted_mode. ++ */ ++ if (psb_intel_sdvo->is_tv || psb_intel_sdvo->is_lvds) { ++ input_dtd = psb_intel_sdvo->input_dtd; ++ } else { ++ /* Set the output timing to the screen */ ++ if (!psb_intel_sdvo_set_target_output(psb_intel_sdvo, ++ psb_intel_sdvo->attached_output)) ++ return; ++ ++ psb_intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); ++ (void) psb_intel_sdvo_set_output_timing(psb_intel_sdvo, &input_dtd); ++ } ++ ++ /* Set the input timing to the screen. Assume always input 0. */ ++ if (!psb_intel_sdvo_set_target_input(psb_intel_sdvo)) ++ return; ++ ++ if (psb_intel_sdvo->has_hdmi_monitor) { ++ psb_intel_sdvo_set_encode(psb_intel_sdvo, SDVO_ENCODE_HDMI); ++ psb_intel_sdvo_set_colorimetry(psb_intel_sdvo, ++ SDVO_COLORIMETRY_RGB256); ++ psb_intel_sdvo_set_avi_infoframe(psb_intel_sdvo); ++ } else ++ psb_intel_sdvo_set_encode(psb_intel_sdvo, SDVO_ENCODE_DVI); ++ ++ if (psb_intel_sdvo->is_tv && ++ !psb_intel_sdvo_set_tv_format(psb_intel_sdvo)) ++ return; ++ ++ (void) psb_intel_sdvo_set_input_timing(psb_intel_sdvo, &input_dtd); ++ ++ switch (pixel_multiplier) { ++ default: ++ case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break; ++ case 2: rate = SDVO_CLOCK_RATE_MULT_2X; break; ++ case 4: rate = SDVO_CLOCK_RATE_MULT_4X; break; ++ } ++ if (!psb_intel_sdvo_set_clock_rate_mult(psb_intel_sdvo, rate)) ++ return; ++ ++ /* Set the SDVO control regs. */ ++ sdvox = REG_READ(psb_intel_sdvo->sdvo_reg); ++ switch (psb_intel_sdvo->sdvo_reg) { ++ case SDVOB: ++ sdvox &= SDVOB_PRESERVE_MASK; ++ break; ++ case SDVOC: ++ sdvox &= SDVOC_PRESERVE_MASK; ++ break; ++ } ++ sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; ++ ++ if (psb_intel_crtc->pipe == 1) ++ sdvox |= SDVO_PIPE_B_SELECT; ++ if (psb_intel_sdvo->has_hdmi_audio) ++ sdvox |= SDVO_AUDIO_ENABLE; ++ ++ /* FIXME: Check if this is needed for PSB ++ sdvox |= (pixel_multiplier - 1) << SDVO_PORT_MULTIPLY_SHIFT; ++ */ ++ ++ if (input_dtd.part2.sdvo_flags & SDVO_NEED_TO_STALL) ++ sdvox |= SDVO_STALL_SELECT; ++ psb_intel_sdvo_write_sdvox(psb_intel_sdvo, sdvox); ++} ++ ++static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); ++ u32 temp; ++ ++ switch (mode) { ++ case DRM_MODE_DPMS_ON: ++ DRM_DEBUG("DPMS_ON"); ++ break; ++ case DRM_MODE_DPMS_OFF: ++ DRM_DEBUG("DPMS_OFF"); ++ break; ++ default: ++ DRM_DEBUG("DPMS: %d", mode); ++ } ++ ++ if (mode != DRM_MODE_DPMS_ON) { ++ psb_intel_sdvo_set_active_outputs(psb_intel_sdvo, 0); ++ if (0) ++ psb_intel_sdvo_set_encoder_power_state(psb_intel_sdvo, mode); ++ ++ if (mode == DRM_MODE_DPMS_OFF) { ++ temp = REG_READ(psb_intel_sdvo->sdvo_reg); ++ if ((temp & SDVO_ENABLE) != 0) { ++ psb_intel_sdvo_write_sdvox(psb_intel_sdvo, temp & ~SDVO_ENABLE); ++ } ++ } ++ } else { ++ bool input1, input2; ++ int i; ++ u8 status; ++ ++ temp = REG_READ(psb_intel_sdvo->sdvo_reg); ++ if ((temp & SDVO_ENABLE) == 0) ++ psb_intel_sdvo_write_sdvox(psb_intel_sdvo, temp | SDVO_ENABLE); ++ for (i = 0; i < 2; i++) ++ psb_intel_wait_for_vblank(dev); ++ ++ status = psb_intel_sdvo_get_trained_inputs(psb_intel_sdvo, &input1, &input2); ++ /* Warn if the device reported failure to sync. ++ * A lot of SDVO devices fail to notify of sync, but it's ++ * a given it the status is a success, we succeeded. ++ */ ++ if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { ++ DRM_DEBUG_KMS("First %s output reported failure to " ++ "sync\n", SDVO_NAME(psb_intel_sdvo)); ++ } ++ ++ if (0) ++ psb_intel_sdvo_set_encoder_power_state(psb_intel_sdvo, mode); ++ psb_intel_sdvo_set_active_outputs(psb_intel_sdvo, psb_intel_sdvo->attached_output); ++ } ++ return; ++} ++ ++static int psb_intel_sdvo_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ struct drm_psb_private *dev_priv = connector->dev->dev_private; ++ struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); ++ ++ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ return MODE_NO_DBLESCAN; ++ ++ if (psb_intel_sdvo->pixel_clock_min > mode->clock) ++ return MODE_CLOCK_LOW; ++ ++ if (psb_intel_sdvo->pixel_clock_max < mode->clock) ++ return MODE_CLOCK_HIGH; ++ ++ if (psb_intel_sdvo->is_lvds) { ++ if (mode->hdisplay > psb_intel_sdvo->sdvo_lvds_fixed_mode->hdisplay) ++ return MODE_PANEL; ++ ++ if (mode->vdisplay > psb_intel_sdvo->sdvo_lvds_fixed_mode->vdisplay) ++ return MODE_PANEL; ++ } ++ ++ /* We assume worst case scenario of 32 bpp here, since we don't know */ ++ if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) > ++ dev_priv->vram_stolen_size) ++ return MODE_MEM; ++ ++ return MODE_OK; ++} ++ ++static bool psb_intel_sdvo_get_capabilities(struct psb_intel_sdvo *psb_intel_sdvo, struct psb_intel_sdvo_caps *caps) ++{ ++ BUILD_BUG_ON(sizeof(*caps) != 8); ++ if (!psb_intel_sdvo_get_value(psb_intel_sdvo, ++ SDVO_CMD_GET_DEVICE_CAPS, ++ caps, sizeof(*caps))) ++ return false; ++ ++ DRM_DEBUG_KMS("SDVO capabilities:\n" ++ " vendor_id: %d\n" ++ " device_id: %d\n" ++ " device_rev_id: %d\n" ++ " sdvo_version_major: %d\n" ++ " sdvo_version_minor: %d\n" ++ " sdvo_inputs_mask: %d\n" ++ " smooth_scaling: %d\n" ++ " sharp_scaling: %d\n" ++ " up_scaling: %d\n" ++ " down_scaling: %d\n" ++ " stall_support: %d\n" ++ " output_flags: %d\n", ++ caps->vendor_id, ++ caps->device_id, ++ caps->device_rev_id, ++ caps->sdvo_version_major, ++ caps->sdvo_version_minor, ++ caps->sdvo_inputs_mask, ++ caps->smooth_scaling, ++ caps->sharp_scaling, ++ caps->up_scaling, ++ caps->down_scaling, ++ caps->stall_support, ++ caps->output_flags); ++ ++ return true; ++} ++ ++/* No use! */ ++#if 0 ++struct drm_connector* psb_intel_sdvo_find(struct drm_device *dev, int sdvoB) ++{ ++ struct drm_connector *connector = NULL; ++ struct psb_intel_sdvo *iout = NULL; ++ struct psb_intel_sdvo *sdvo; ++ ++ /* find the sdvo connector */ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ iout = to_psb_intel_sdvo(connector); ++ ++ if (iout->type != INTEL_OUTPUT_SDVO) ++ continue; ++ ++ sdvo = iout->dev_priv; ++ ++ if (sdvo->sdvo_reg == SDVOB && sdvoB) ++ return connector; ++ ++ if (sdvo->sdvo_reg == SDVOC && !sdvoB) ++ return connector; ++ ++ } ++ ++ return NULL; ++} ++ ++int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector) ++{ ++ u8 response[2]; ++ u8 status; ++ struct psb_intel_sdvo *psb_intel_sdvo; ++ DRM_DEBUG_KMS("\n"); ++ ++ if (!connector) ++ return 0; ++ ++ psb_intel_sdvo = to_psb_intel_sdvo(connector); ++ ++ return psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, ++ &response, 2) && response[0]; ++} ++ ++void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, int on) ++{ ++ u8 response[2]; ++ u8 status; ++ struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(connector); ++ ++ psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); ++ psb_intel_sdvo_read_response(psb_intel_sdvo, &response, 2); ++ ++ if (on) { ++ psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0); ++ status = psb_intel_sdvo_read_response(psb_intel_sdvo, &response, 2); ++ ++ psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); ++ } else { ++ response[0] = 0; ++ response[1] = 0; ++ psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); ++ } ++ ++ psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); ++ psb_intel_sdvo_read_response(psb_intel_sdvo, &response, 2); ++} ++#endif ++ ++static bool ++psb_intel_sdvo_multifunc_encoder(struct psb_intel_sdvo *psb_intel_sdvo) ++{ ++ /* Is there more than one type of output? */ ++ int caps = psb_intel_sdvo->caps.output_flags & 0xf; ++ return caps & -caps; ++} ++ ++static struct edid * ++psb_intel_sdvo_get_edid(struct drm_connector *connector) ++{ ++ struct psb_intel_sdvo *sdvo = intel_attached_sdvo(connector); ++ return drm_get_edid(connector, &sdvo->ddc); ++} ++ ++/* Mac mini hack -- use the same DDC as the analog connector */ ++static struct edid * ++psb_intel_sdvo_get_analog_edid(struct drm_connector *connector) ++{ ++ struct drm_psb_private *dev_priv = connector->dev->dev_private; ++ ++ return drm_get_edid(connector, ++ &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); ++ return NULL; ++} ++ ++static enum drm_connector_status ++psb_intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) ++{ ++ struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); ++ enum drm_connector_status status; ++ struct edid *edid; ++ ++ edid = psb_intel_sdvo_get_edid(connector); ++ ++ if (edid == NULL && psb_intel_sdvo_multifunc_encoder(psb_intel_sdvo)) { ++ u8 ddc, saved_ddc = psb_intel_sdvo->ddc_bus; ++ ++ /* ++ * Don't use the 1 as the argument of DDC bus switch to get ++ * the EDID. It is used for SDVO SPD ROM. ++ */ ++ for (ddc = psb_intel_sdvo->ddc_bus >> 1; ddc > 1; ddc >>= 1) { ++ psb_intel_sdvo->ddc_bus = ddc; ++ edid = psb_intel_sdvo_get_edid(connector); ++ if (edid) ++ break; ++ } ++ /* ++ * If we found the EDID on the other bus, ++ * assume that is the correct DDC bus. ++ */ ++ if (edid == NULL) ++ psb_intel_sdvo->ddc_bus = saved_ddc; ++ } ++ ++ /* ++ * When there is no edid and no monitor is connected with VGA ++ * port, try to use the CRT ddc to read the EDID for DVI-connector. ++ */ ++ if (edid == NULL) ++ edid = psb_intel_sdvo_get_analog_edid(connector); ++ ++ status = connector_status_unknown; ++ if (edid != NULL) { ++ /* DDC bus is shared, match EDID to connector type */ ++ if (edid->input & DRM_EDID_INPUT_DIGITAL) { ++ status = connector_status_connected; ++ if (psb_intel_sdvo->is_hdmi) { ++ psb_intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid); ++ psb_intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid); ++ } ++ } else ++ status = connector_status_disconnected; ++ connector->display_info.raw_edid = NULL; ++ kfree(edid); ++ } ++ ++ if (status == connector_status_connected) { ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); ++ if (psb_intel_sdvo_connector->force_audio) ++ psb_intel_sdvo->has_hdmi_audio = psb_intel_sdvo_connector->force_audio > 0; ++ } ++ ++ return status; ++} ++ ++static enum drm_connector_status ++psb_intel_sdvo_detect(struct drm_connector *connector, bool force) ++{ ++ uint16_t response; ++ struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); ++ enum drm_connector_status ret; ++ ++ if (!psb_intel_sdvo_write_cmd(psb_intel_sdvo, ++ SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0)) ++ return connector_status_unknown; ++ ++ /* add 30ms delay when the output type might be TV */ ++ if (psb_intel_sdvo->caps.output_flags & ++ (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_CVBS0)) ++ mdelay(30); ++ ++ if (!psb_intel_sdvo_read_response(psb_intel_sdvo, &response, 2)) ++ return connector_status_unknown; ++ ++ DRM_DEBUG_KMS("SDVO response %d %d [%x]\n", ++ response & 0xff, response >> 8, ++ psb_intel_sdvo_connector->output_flag); ++ ++ if (response == 0) ++ return connector_status_disconnected; ++ ++ psb_intel_sdvo->attached_output = response; ++ ++ psb_intel_sdvo->has_hdmi_monitor = false; ++ psb_intel_sdvo->has_hdmi_audio = false; ++ ++ if ((psb_intel_sdvo_connector->output_flag & response) == 0) ++ ret = connector_status_disconnected; ++ else if (IS_TMDS(psb_intel_sdvo_connector)) ++ ret = psb_intel_sdvo_hdmi_sink_detect(connector); ++ else { ++ struct edid *edid; ++ ++ /* if we have an edid check it matches the connection */ ++ edid = psb_intel_sdvo_get_edid(connector); ++ if (edid == NULL) ++ edid = psb_intel_sdvo_get_analog_edid(connector); ++ if (edid != NULL) { ++ if (edid->input & DRM_EDID_INPUT_DIGITAL) ++ ret = connector_status_disconnected; ++ else ++ ret = connector_status_connected; ++ connector->display_info.raw_edid = NULL; ++ kfree(edid); ++ } else ++ ret = connector_status_connected; ++ } ++ ++ /* May update encoder flag for like clock for SDVO TV, etc.*/ ++ if (ret == connector_status_connected) { ++ psb_intel_sdvo->is_tv = false; ++ psb_intel_sdvo->is_lvds = false; ++ psb_intel_sdvo->base.needs_tv_clock = false; ++ ++ if (response & SDVO_TV_MASK) { ++ psb_intel_sdvo->is_tv = true; ++ psb_intel_sdvo->base.needs_tv_clock = true; ++ } ++ if (response & SDVO_LVDS_MASK) ++ psb_intel_sdvo->is_lvds = psb_intel_sdvo->sdvo_lvds_fixed_mode != NULL; ++ } ++ ++ return ret; ++} ++ ++static void psb_intel_sdvo_get_ddc_modes(struct drm_connector *connector) ++{ ++ struct edid *edid; ++ ++ /* set the bus switch and get the modes */ ++ edid = psb_intel_sdvo_get_edid(connector); ++ ++ /* ++ * Mac mini hack. On this device, the DVI-I connector shares one DDC ++ * link between analog and digital outputs. So, if the regular SDVO ++ * DDC fails, check to see if the analog output is disconnected, in ++ * which case we'll look there for the digital DDC data. ++ */ ++ if (edid == NULL) ++ edid = psb_intel_sdvo_get_analog_edid(connector); ++ ++ if (edid != NULL) { ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); ++ bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); ++ bool connector_is_digital = !!IS_TMDS(psb_intel_sdvo_connector); ++ ++ if (connector_is_digital == monitor_is_digital) { ++ drm_mode_connector_update_edid_property(connector, edid); ++ drm_add_edid_modes(connector, edid); ++ } ++ ++ connector->display_info.raw_edid = NULL; ++ kfree(edid); ++ } ++} ++ ++/* ++ * Set of SDVO TV modes. ++ * Note! This is in reply order (see loop in get_tv_modes). ++ * XXX: all 60Hz refresh? ++ */ ++static const struct drm_display_mode sdvo_tv_modes[] = { ++ { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815, 320, 321, 384, ++ 416, 0, 200, 201, 232, 233, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 6814, 320, 321, 384, ++ 416, 0, 240, 241, 272, 273, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 9910, 400, 401, 464, ++ 496, 0, 300, 301, 332, 333, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 16913, 640, 641, 704, ++ 736, 0, 350, 351, 382, 383, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121, 640, 641, 704, ++ 736, 0, 400, 401, 432, 433, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 22654, 640, 641, 704, ++ 736, 0, 480, 481, 512, 513, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("704x480", DRM_MODE_TYPE_DRIVER, 24624, 704, 705, 768, ++ 800, 0, 480, 481, 512, 513, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("704x576", DRM_MODE_TYPE_DRIVER, 29232, 704, 705, 768, ++ 800, 0, 576, 577, 608, 609, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("720x350", DRM_MODE_TYPE_DRIVER, 18751, 720, 721, 784, ++ 816, 0, 350, 351, 382, 383, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 21199, 720, 721, 784, ++ 816, 0, 400, 401, 432, 433, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 25116, 720, 721, 784, ++ 816, 0, 480, 481, 512, 513, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("720x540", DRM_MODE_TYPE_DRIVER, 28054, 720, 721, 784, ++ 816, 0, 540, 541, 572, 573, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 29816, 720, 721, 784, ++ 816, 0, 576, 577, 608, 609, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("768x576", DRM_MODE_TYPE_DRIVER, 31570, 768, 769, 832, ++ 864, 0, 576, 577, 608, 609, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 34030, 800, 801, 864, ++ 896, 0, 600, 601, 632, 633, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 36581, 832, 833, 896, ++ 928, 0, 624, 625, 656, 657, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("920x766", DRM_MODE_TYPE_DRIVER, 48707, 920, 921, 984, ++ 1016, 0, 766, 767, 798, 799, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 53827, 1024, 1025, 1088, ++ 1120, 0, 768, 769, 800, 801, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++ { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 87265, 1280, 1281, 1344, ++ 1376, 0, 1024, 1025, 1056, 1057, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, ++}; ++ ++static void psb_intel_sdvo_get_tv_modes(struct drm_connector *connector) ++{ ++ struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); ++ struct psb_intel_sdvo_sdtv_resolution_request tv_res; ++ uint32_t reply = 0, format_map = 0; ++ int i; ++ ++ /* Read the list of supported input resolutions for the selected TV ++ * format. ++ */ ++ format_map = 1 << psb_intel_sdvo->tv_format_index; ++ memcpy(&tv_res, &format_map, ++ min(sizeof(format_map), sizeof(struct psb_intel_sdvo_sdtv_resolution_request))); ++ ++ if (!psb_intel_sdvo_set_target_output(psb_intel_sdvo, psb_intel_sdvo->attached_output)) ++ return; ++ ++ BUILD_BUG_ON(sizeof(tv_res) != 3); ++ if (!psb_intel_sdvo_write_cmd(psb_intel_sdvo, ++ SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, ++ &tv_res, sizeof(tv_res))) ++ return; ++ if (!psb_intel_sdvo_read_response(psb_intel_sdvo, &reply, 3)) ++ return; ++ ++ for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++) ++ if (reply & (1 << i)) { ++ struct drm_display_mode *nmode; ++ nmode = drm_mode_duplicate(connector->dev, ++ &sdvo_tv_modes[i]); ++ if (nmode) ++ drm_mode_probed_add(connector, nmode); ++ } ++} ++ ++static void psb_intel_sdvo_get_lvds_modes(struct drm_connector *connector) ++{ ++ struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); ++ struct drm_psb_private *dev_priv = connector->dev->dev_private; ++ struct drm_display_mode *newmode; ++ ++ /* ++ * Attempt to get the mode list from DDC. ++ * Assume that the preferred modes are ++ * arranged in priority order. ++ */ ++ psb_intel_ddc_get_modes(connector, psb_intel_sdvo->i2c); ++ if (list_empty(&connector->probed_modes) == false) ++ goto end; ++ ++ /* Fetch modes from VBT */ ++ if (dev_priv->sdvo_lvds_vbt_mode != NULL) { ++ newmode = drm_mode_duplicate(connector->dev, ++ dev_priv->sdvo_lvds_vbt_mode); ++ if (newmode != NULL) { ++ /* Guarantee the mode is preferred */ ++ newmode->type = (DRM_MODE_TYPE_PREFERRED | ++ DRM_MODE_TYPE_DRIVER); ++ drm_mode_probed_add(connector, newmode); ++ } ++ } ++ ++end: ++ list_for_each_entry(newmode, &connector->probed_modes, head) { ++ if (newmode->type & DRM_MODE_TYPE_PREFERRED) { ++ psb_intel_sdvo->sdvo_lvds_fixed_mode = ++ drm_mode_duplicate(connector->dev, newmode); ++ ++ drm_mode_set_crtcinfo(psb_intel_sdvo->sdvo_lvds_fixed_mode, ++ 0); ++ ++ psb_intel_sdvo->is_lvds = true; ++ break; ++ } ++ } ++ ++} ++ ++static int psb_intel_sdvo_get_modes(struct drm_connector *connector) ++{ ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); ++ ++ if (IS_TV(psb_intel_sdvo_connector)) ++ psb_intel_sdvo_get_tv_modes(connector); ++ else if (IS_LVDS(psb_intel_sdvo_connector)) ++ psb_intel_sdvo_get_lvds_modes(connector); ++ else ++ psb_intel_sdvo_get_ddc_modes(connector); ++ ++ return !list_empty(&connector->probed_modes); ++} ++ ++static void ++psb_intel_sdvo_destroy_enhance_property(struct drm_connector *connector) ++{ ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); ++ struct drm_device *dev = connector->dev; ++ ++ if (psb_intel_sdvo_connector->left) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->left); ++ if (psb_intel_sdvo_connector->right) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->right); ++ if (psb_intel_sdvo_connector->top) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->top); ++ if (psb_intel_sdvo_connector->bottom) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->bottom); ++ if (psb_intel_sdvo_connector->hpos) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->hpos); ++ if (psb_intel_sdvo_connector->vpos) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->vpos); ++ if (psb_intel_sdvo_connector->saturation) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->saturation); ++ if (psb_intel_sdvo_connector->contrast) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->contrast); ++ if (psb_intel_sdvo_connector->hue) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->hue); ++ if (psb_intel_sdvo_connector->sharpness) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->sharpness); ++ if (psb_intel_sdvo_connector->flicker_filter) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter); ++ if (psb_intel_sdvo_connector->flicker_filter_2d) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_2d); ++ if (psb_intel_sdvo_connector->flicker_filter_adaptive) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_adaptive); ++ if (psb_intel_sdvo_connector->tv_luma_filter) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->tv_luma_filter); ++ if (psb_intel_sdvo_connector->tv_chroma_filter) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->tv_chroma_filter); ++ if (psb_intel_sdvo_connector->dot_crawl) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->dot_crawl); ++ if (psb_intel_sdvo_connector->brightness) ++ drm_property_destroy(dev, psb_intel_sdvo_connector->brightness); ++} ++ ++static void psb_intel_sdvo_destroy(struct drm_connector *connector) ++{ ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); ++ ++ if (psb_intel_sdvo_connector->tv_format) ++ drm_property_destroy(connector->dev, ++ psb_intel_sdvo_connector->tv_format); ++ ++ psb_intel_sdvo_destroy_enhance_property(connector); ++ drm_sysfs_connector_remove(connector); ++ drm_connector_cleanup(connector); ++ kfree(connector); ++} ++ ++static bool psb_intel_sdvo_detect_hdmi_audio(struct drm_connector *connector) ++{ ++ struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); ++ struct edid *edid; ++ bool has_audio = false; ++ ++ if (!psb_intel_sdvo->is_hdmi) ++ return false; ++ ++ edid = psb_intel_sdvo_get_edid(connector); ++ if (edid != NULL && edid->input & DRM_EDID_INPUT_DIGITAL) ++ has_audio = drm_detect_monitor_audio(edid); ++ ++ return has_audio; ++} ++ ++static int ++psb_intel_sdvo_set_property(struct drm_connector *connector, ++ struct drm_property *property, ++ uint64_t val) ++{ ++ struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); ++ struct drm_psb_private *dev_priv = connector->dev->dev_private; ++ uint16_t temp_value; ++ uint8_t cmd; ++ int ret; ++ ++ ret = drm_connector_property_set_value(connector, property, val); ++ if (ret) ++ return ret; ++ ++ if (property == dev_priv->force_audio_property) { ++ int i = val; ++ bool has_audio; ++ ++ if (i == psb_intel_sdvo_connector->force_audio) ++ return 0; ++ ++ psb_intel_sdvo_connector->force_audio = i; ++ ++ if (i == 0) ++ has_audio = psb_intel_sdvo_detect_hdmi_audio(connector); ++ else ++ has_audio = i > 0; ++ ++ if (has_audio == psb_intel_sdvo->has_hdmi_audio) ++ return 0; ++ ++ psb_intel_sdvo->has_hdmi_audio = has_audio; ++ goto done; ++ } ++ ++ if (property == dev_priv->broadcast_rgb_property) { ++ if (val == !!psb_intel_sdvo->color_range) ++ return 0; ++ ++ psb_intel_sdvo->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0; ++ goto done; ++ } ++ ++#define CHECK_PROPERTY(name, NAME) \ ++ if (psb_intel_sdvo_connector->name == property) { \ ++ if (psb_intel_sdvo_connector->cur_##name == temp_value) return 0; \ ++ if (psb_intel_sdvo_connector->max_##name < temp_value) return -EINVAL; \ ++ cmd = SDVO_CMD_SET_##NAME; \ ++ psb_intel_sdvo_connector->cur_##name = temp_value; \ ++ goto set_value; \ ++ } ++ ++ if (property == psb_intel_sdvo_connector->tv_format) { ++ if (val >= TV_FORMAT_NUM) ++ return -EINVAL; ++ ++ if (psb_intel_sdvo->tv_format_index == ++ psb_intel_sdvo_connector->tv_format_supported[val]) ++ return 0; ++ ++ psb_intel_sdvo->tv_format_index = psb_intel_sdvo_connector->tv_format_supported[val]; ++ goto done; ++ } else if (IS_TV_OR_LVDS(psb_intel_sdvo_connector)) { ++ temp_value = val; ++ if (psb_intel_sdvo_connector->left == property) { ++ drm_connector_property_set_value(connector, ++ psb_intel_sdvo_connector->right, val); ++ if (psb_intel_sdvo_connector->left_margin == temp_value) ++ return 0; ++ ++ psb_intel_sdvo_connector->left_margin = temp_value; ++ psb_intel_sdvo_connector->right_margin = temp_value; ++ temp_value = psb_intel_sdvo_connector->max_hscan - ++ psb_intel_sdvo_connector->left_margin; ++ cmd = SDVO_CMD_SET_OVERSCAN_H; ++ goto set_value; ++ } else if (psb_intel_sdvo_connector->right == property) { ++ drm_connector_property_set_value(connector, ++ psb_intel_sdvo_connector->left, val); ++ if (psb_intel_sdvo_connector->right_margin == temp_value) ++ return 0; ++ ++ psb_intel_sdvo_connector->left_margin = temp_value; ++ psb_intel_sdvo_connector->right_margin = temp_value; ++ temp_value = psb_intel_sdvo_connector->max_hscan - ++ psb_intel_sdvo_connector->left_margin; ++ cmd = SDVO_CMD_SET_OVERSCAN_H; ++ goto set_value; ++ } else if (psb_intel_sdvo_connector->top == property) { ++ drm_connector_property_set_value(connector, ++ psb_intel_sdvo_connector->bottom, val); ++ if (psb_intel_sdvo_connector->top_margin == temp_value) ++ return 0; ++ ++ psb_intel_sdvo_connector->top_margin = temp_value; ++ psb_intel_sdvo_connector->bottom_margin = temp_value; ++ temp_value = psb_intel_sdvo_connector->max_vscan - ++ psb_intel_sdvo_connector->top_margin; ++ cmd = SDVO_CMD_SET_OVERSCAN_V; ++ goto set_value; ++ } else if (psb_intel_sdvo_connector->bottom == property) { ++ drm_connector_property_set_value(connector, ++ psb_intel_sdvo_connector->top, val); ++ if (psb_intel_sdvo_connector->bottom_margin == temp_value) ++ return 0; ++ ++ psb_intel_sdvo_connector->top_margin = temp_value; ++ psb_intel_sdvo_connector->bottom_margin = temp_value; ++ temp_value = psb_intel_sdvo_connector->max_vscan - ++ psb_intel_sdvo_connector->top_margin; ++ cmd = SDVO_CMD_SET_OVERSCAN_V; ++ goto set_value; ++ } ++ CHECK_PROPERTY(hpos, HPOS) ++ CHECK_PROPERTY(vpos, VPOS) ++ CHECK_PROPERTY(saturation, SATURATION) ++ CHECK_PROPERTY(contrast, CONTRAST) ++ CHECK_PROPERTY(hue, HUE) ++ CHECK_PROPERTY(brightness, BRIGHTNESS) ++ CHECK_PROPERTY(sharpness, SHARPNESS) ++ CHECK_PROPERTY(flicker_filter, FLICKER_FILTER) ++ CHECK_PROPERTY(flicker_filter_2d, FLICKER_FILTER_2D) ++ CHECK_PROPERTY(flicker_filter_adaptive, FLICKER_FILTER_ADAPTIVE) ++ CHECK_PROPERTY(tv_chroma_filter, TV_CHROMA_FILTER) ++ CHECK_PROPERTY(tv_luma_filter, TV_LUMA_FILTER) ++ CHECK_PROPERTY(dot_crawl, DOT_CRAWL) ++ } ++ ++ return -EINVAL; /* unknown property */ ++ ++set_value: ++ if (!psb_intel_sdvo_set_value(psb_intel_sdvo, cmd, &temp_value, 2)) ++ return -EIO; ++ ++ ++done: ++ if (psb_intel_sdvo->base.base.crtc) { ++ struct drm_crtc *crtc = psb_intel_sdvo->base.base.crtc; ++ drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x, ++ crtc->y, crtc->fb); ++ } ++ ++ return 0; ++#undef CHECK_PROPERTY ++} ++ ++static const struct drm_encoder_helper_funcs psb_intel_sdvo_helper_funcs = { ++ .dpms = psb_intel_sdvo_dpms, ++ .mode_fixup = psb_intel_sdvo_mode_fixup, ++ .prepare = psb_intel_encoder_prepare, ++ .mode_set = psb_intel_sdvo_mode_set, ++ .commit = psb_intel_encoder_commit, ++}; ++ ++static const struct drm_connector_funcs psb_intel_sdvo_connector_funcs = { ++ .dpms = drm_helper_connector_dpms, ++ .detect = psb_intel_sdvo_detect, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .set_property = psb_intel_sdvo_set_property, ++ .destroy = psb_intel_sdvo_destroy, ++}; ++ ++static const struct drm_connector_helper_funcs psb_intel_sdvo_connector_helper_funcs = { ++ .get_modes = psb_intel_sdvo_get_modes, ++ .mode_valid = psb_intel_sdvo_mode_valid, ++ .best_encoder = psb_intel_best_encoder, ++}; ++ ++static void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder) ++{ ++ struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); ++ ++ if (psb_intel_sdvo->sdvo_lvds_fixed_mode != NULL) ++ drm_mode_destroy(encoder->dev, ++ psb_intel_sdvo->sdvo_lvds_fixed_mode); ++ ++ i2c_del_adapter(&psb_intel_sdvo->ddc); ++ psb_intel_encoder_destroy(encoder); ++} ++ ++static const struct drm_encoder_funcs psb_intel_sdvo_enc_funcs = { ++ .destroy = psb_intel_sdvo_enc_destroy, ++}; ++ ++static void ++psb_intel_sdvo_guess_ddc_bus(struct psb_intel_sdvo *sdvo) ++{ ++ /* FIXME: At the moment, ddc_bus = 2 is the only thing that works. ++ * We need to figure out if this is true for all available poulsbo ++ * hardware, or if we need to fiddle with the guessing code above. ++ * The problem might go away if we can parse sdvo mappings from bios */ ++ sdvo->ddc_bus = 2; ++ ++#if 0 ++ uint16_t mask = 0; ++ unsigned int num_bits; ++ ++ /* Make a mask of outputs less than or equal to our own priority in the ++ * list. ++ */ ++ switch (sdvo->controlled_output) { ++ case SDVO_OUTPUT_LVDS1: ++ mask |= SDVO_OUTPUT_LVDS1; ++ case SDVO_OUTPUT_LVDS0: ++ mask |= SDVO_OUTPUT_LVDS0; ++ case SDVO_OUTPUT_TMDS1: ++ mask |= SDVO_OUTPUT_TMDS1; ++ case SDVO_OUTPUT_TMDS0: ++ mask |= SDVO_OUTPUT_TMDS0; ++ case SDVO_OUTPUT_RGB1: ++ mask |= SDVO_OUTPUT_RGB1; ++ case SDVO_OUTPUT_RGB0: ++ mask |= SDVO_OUTPUT_RGB0; ++ break; ++ } ++ ++ /* Count bits to find what number we are in the priority list. */ ++ mask &= sdvo->caps.output_flags; ++ num_bits = hweight16(mask); ++ /* If more than 3 outputs, default to DDC bus 3 for now. */ ++ if (num_bits > 3) ++ num_bits = 3; ++ ++ /* Corresponds to SDVO_CONTROL_BUS_DDCx */ ++ sdvo->ddc_bus = 1 << num_bits; ++#endif ++} ++ ++/** ++ * Choose the appropriate DDC bus for control bus switch command for this ++ * SDVO output based on the controlled output. ++ * ++ * DDC bus number assignment is in a priority order of RGB outputs, then TMDS ++ * outputs, then LVDS outputs. ++ */ ++static void ++psb_intel_sdvo_select_ddc_bus(struct drm_psb_private *dev_priv, ++ struct psb_intel_sdvo *sdvo, u32 reg) ++{ ++ struct sdvo_device_mapping *mapping; ++ ++ if (IS_SDVOB(reg)) ++ mapping = &(dev_priv->sdvo_mappings[0]); ++ else ++ mapping = &(dev_priv->sdvo_mappings[1]); ++ ++ if (mapping->initialized) ++ sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4); ++ else ++ psb_intel_sdvo_guess_ddc_bus(sdvo); ++} ++ ++static void ++psb_intel_sdvo_select_i2c_bus(struct drm_psb_private *dev_priv, ++ struct psb_intel_sdvo *sdvo, u32 reg) ++{ ++ struct sdvo_device_mapping *mapping; ++ u8 pin, speed; ++ ++ if (IS_SDVOB(reg)) ++ mapping = &dev_priv->sdvo_mappings[0]; ++ else ++ mapping = &dev_priv->sdvo_mappings[1]; ++ ++ pin = GMBUS_PORT_DPB; ++ speed = GMBUS_RATE_1MHZ >> 8; ++ if (mapping->initialized) { ++ pin = mapping->i2c_pin; ++ speed = mapping->i2c_speed; ++ } ++ ++ if (pin < GMBUS_NUM_PORTS) { ++ sdvo->i2c = &dev_priv->gmbus[pin].adapter; ++ gma_intel_gmbus_set_speed(sdvo->i2c, speed); ++ gma_intel_gmbus_force_bit(sdvo->i2c, true); ++ } else ++ sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter; ++} ++ ++static bool ++psb_intel_sdvo_is_hdmi_connector(struct psb_intel_sdvo *psb_intel_sdvo, int device) ++{ ++ return psb_intel_sdvo_check_supp_encode(psb_intel_sdvo); ++} ++ ++static u8 ++psb_intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct sdvo_device_mapping *my_mapping, *other_mapping; ++ ++ if (IS_SDVOB(sdvo_reg)) { ++ my_mapping = &dev_priv->sdvo_mappings[0]; ++ other_mapping = &dev_priv->sdvo_mappings[1]; ++ } else { ++ my_mapping = &dev_priv->sdvo_mappings[1]; ++ other_mapping = &dev_priv->sdvo_mappings[0]; ++ } ++ ++ /* If the BIOS described our SDVO device, take advantage of it. */ ++ if (my_mapping->slave_addr) ++ return my_mapping->slave_addr; ++ ++ /* If the BIOS only described a different SDVO device, use the ++ * address that it isn't using. ++ */ ++ if (other_mapping->slave_addr) { ++ if (other_mapping->slave_addr == 0x70) ++ return 0x72; ++ else ++ return 0x70; ++ } ++ ++ /* No SDVO device info is found for another DVO port, ++ * so use mapping assumption we had before BIOS parsing. ++ */ ++ if (IS_SDVOB(sdvo_reg)) ++ return 0x70; ++ else ++ return 0x72; ++} ++ ++static void ++psb_intel_sdvo_connector_init(struct psb_intel_sdvo_connector *connector, ++ struct psb_intel_sdvo *encoder) ++{ ++ drm_connector_init(encoder->base.base.dev, ++ &connector->base.base, ++ &psb_intel_sdvo_connector_funcs, ++ connector->base.base.connector_type); ++ ++ drm_connector_helper_add(&connector->base.base, ++ &psb_intel_sdvo_connector_helper_funcs); ++ ++ connector->base.base.interlace_allowed = 0; ++ connector->base.base.doublescan_allowed = 0; ++ connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB; ++ ++ psb_intel_connector_attach_encoder(&connector->base, &encoder->base); ++ drm_sysfs_connector_add(&connector->base.base); ++} ++ ++static void ++psb_intel_sdvo_add_hdmi_properties(struct psb_intel_sdvo_connector *connector) ++{ ++ /* FIXME: We don't support HDMI at the moment ++ struct drm_device *dev = connector->base.base.dev; ++ ++ intel_attach_force_audio_property(&connector->base.base); ++ if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev)) ++ intel_attach_broadcast_rgb_property(&connector->base.base); ++ */ ++} ++ ++static bool ++psb_intel_sdvo_dvi_init(struct psb_intel_sdvo *psb_intel_sdvo, int device) ++{ ++ struct drm_encoder *encoder = &psb_intel_sdvo->base.base; ++ struct drm_connector *connector; ++ struct psb_intel_connector *intel_connector; ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector; ++ ++ psb_intel_sdvo_connector = kzalloc(sizeof(struct psb_intel_sdvo_connector), GFP_KERNEL); ++ if (!psb_intel_sdvo_connector) ++ return false; ++ ++ if (device == 0) { ++ psb_intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS0; ++ psb_intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS0; ++ } else if (device == 1) { ++ psb_intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS1; ++ psb_intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS1; ++ } ++ ++ intel_connector = &psb_intel_sdvo_connector->base; ++ connector = &intel_connector->base; ++ // connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; ++ encoder->encoder_type = DRM_MODE_ENCODER_TMDS; ++ connector->connector_type = DRM_MODE_CONNECTOR_DVID; ++ ++ if (psb_intel_sdvo_is_hdmi_connector(psb_intel_sdvo, device)) { ++ connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; ++ psb_intel_sdvo->is_hdmi = true; ++ } ++ psb_intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | ++ (1 << INTEL_ANALOG_CLONE_BIT)); ++ ++ psb_intel_sdvo_connector_init(psb_intel_sdvo_connector, psb_intel_sdvo); ++ if (psb_intel_sdvo->is_hdmi) ++ psb_intel_sdvo_add_hdmi_properties(psb_intel_sdvo_connector); ++ ++ return true; ++} ++ ++static bool ++psb_intel_sdvo_tv_init(struct psb_intel_sdvo *psb_intel_sdvo, int type) ++{ ++ struct drm_encoder *encoder = &psb_intel_sdvo->base.base; ++ struct drm_connector *connector; ++ struct psb_intel_connector *intel_connector; ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector; ++ ++ psb_intel_sdvo_connector = kzalloc(sizeof(struct psb_intel_sdvo_connector), GFP_KERNEL); ++ if (!psb_intel_sdvo_connector) ++ return false; ++ ++ intel_connector = &psb_intel_sdvo_connector->base; ++ connector = &intel_connector->base; ++ encoder->encoder_type = DRM_MODE_ENCODER_TVDAC; ++ connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO; ++ ++ psb_intel_sdvo->controlled_output |= type; ++ psb_intel_sdvo_connector->output_flag = type; ++ ++ psb_intel_sdvo->is_tv = true; ++ psb_intel_sdvo->base.needs_tv_clock = true; ++ psb_intel_sdvo->base.clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT; ++ ++ psb_intel_sdvo_connector_init(psb_intel_sdvo_connector, psb_intel_sdvo); ++ ++ if (!psb_intel_sdvo_tv_create_property(psb_intel_sdvo, psb_intel_sdvo_connector, type)) ++ goto err; ++ ++ if (!psb_intel_sdvo_create_enhance_property(psb_intel_sdvo, psb_intel_sdvo_connector)) ++ goto err; ++ ++ return true; ++ ++err: ++ psb_intel_sdvo_destroy(connector); ++ return false; ++} ++ ++static bool ++psb_intel_sdvo_analog_init(struct psb_intel_sdvo *psb_intel_sdvo, int device) ++{ ++ struct drm_encoder *encoder = &psb_intel_sdvo->base.base; ++ struct drm_connector *connector; ++ struct psb_intel_connector *intel_connector; ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector; ++ ++ psb_intel_sdvo_connector = kzalloc(sizeof(struct psb_intel_sdvo_connector), GFP_KERNEL); ++ if (!psb_intel_sdvo_connector) ++ return false; ++ ++ intel_connector = &psb_intel_sdvo_connector->base; ++ connector = &intel_connector->base; ++ connector->polled = DRM_CONNECTOR_POLL_CONNECT; ++ encoder->encoder_type = DRM_MODE_ENCODER_DAC; ++ connector->connector_type = DRM_MODE_CONNECTOR_VGA; ++ ++ if (device == 0) { ++ psb_intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB0; ++ psb_intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB0; ++ } else if (device == 1) { ++ psb_intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB1; ++ psb_intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1; ++ } ++ ++ psb_intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | ++ (1 << INTEL_ANALOG_CLONE_BIT)); ++ ++ psb_intel_sdvo_connector_init(psb_intel_sdvo_connector, ++ psb_intel_sdvo); ++ return true; ++} ++ ++static bool ++psb_intel_sdvo_lvds_init(struct psb_intel_sdvo *psb_intel_sdvo, int device) ++{ ++ struct drm_encoder *encoder = &psb_intel_sdvo->base.base; ++ struct drm_connector *connector; ++ struct psb_intel_connector *intel_connector; ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector; ++ ++ psb_intel_sdvo_connector = kzalloc(sizeof(struct psb_intel_sdvo_connector), GFP_KERNEL); ++ if (!psb_intel_sdvo_connector) ++ return false; ++ ++ intel_connector = &psb_intel_sdvo_connector->base; ++ connector = &intel_connector->base; ++ encoder->encoder_type = DRM_MODE_ENCODER_LVDS; ++ connector->connector_type = DRM_MODE_CONNECTOR_LVDS; ++ ++ if (device == 0) { ++ psb_intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS0; ++ psb_intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0; ++ } else if (device == 1) { ++ psb_intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS1; ++ psb_intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; ++ } ++ ++ psb_intel_sdvo->base.clone_mask = ((1 << INTEL_ANALOG_CLONE_BIT) | ++ (1 << INTEL_SDVO_LVDS_CLONE_BIT)); ++ ++ psb_intel_sdvo_connector_init(psb_intel_sdvo_connector, psb_intel_sdvo); ++ if (!psb_intel_sdvo_create_enhance_property(psb_intel_sdvo, psb_intel_sdvo_connector)) ++ goto err; ++ ++ return true; ++ ++err: ++ psb_intel_sdvo_destroy(connector); ++ return false; ++} ++ ++static bool ++psb_intel_sdvo_output_setup(struct psb_intel_sdvo *psb_intel_sdvo, uint16_t flags) ++{ ++ psb_intel_sdvo->is_tv = false; ++ psb_intel_sdvo->base.needs_tv_clock = false; ++ psb_intel_sdvo->is_lvds = false; ++ ++ /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/ ++ ++ if (flags & SDVO_OUTPUT_TMDS0) ++ if (!psb_intel_sdvo_dvi_init(psb_intel_sdvo, 0)) ++ return false; ++ ++ if ((flags & SDVO_TMDS_MASK) == SDVO_TMDS_MASK) ++ if (!psb_intel_sdvo_dvi_init(psb_intel_sdvo, 1)) ++ return false; ++ ++ /* TV has no XXX1 function block */ ++ if (flags & SDVO_OUTPUT_SVID0) ++ if (!psb_intel_sdvo_tv_init(psb_intel_sdvo, SDVO_OUTPUT_SVID0)) ++ return false; ++ ++ if (flags & SDVO_OUTPUT_CVBS0) ++ if (!psb_intel_sdvo_tv_init(psb_intel_sdvo, SDVO_OUTPUT_CVBS0)) ++ return false; ++ ++ if (flags & SDVO_OUTPUT_RGB0) ++ if (!psb_intel_sdvo_analog_init(psb_intel_sdvo, 0)) ++ return false; ++ ++ if ((flags & SDVO_RGB_MASK) == SDVO_RGB_MASK) ++ if (!psb_intel_sdvo_analog_init(psb_intel_sdvo, 1)) ++ return false; ++ ++ if (flags & SDVO_OUTPUT_LVDS0) ++ if (!psb_intel_sdvo_lvds_init(psb_intel_sdvo, 0)) ++ return false; ++ ++ if ((flags & SDVO_LVDS_MASK) == SDVO_LVDS_MASK) ++ if (!psb_intel_sdvo_lvds_init(psb_intel_sdvo, 1)) ++ return false; ++ ++ if ((flags & SDVO_OUTPUT_MASK) == 0) { ++ unsigned char bytes[2]; ++ ++ psb_intel_sdvo->controlled_output = 0; ++ memcpy(bytes, &psb_intel_sdvo->caps.output_flags, 2); ++ DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n", ++ SDVO_NAME(psb_intel_sdvo), ++ bytes[0], bytes[1]); ++ return false; ++ } ++ psb_intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1); ++ ++ return true; ++} ++ ++static bool psb_intel_sdvo_tv_create_property(struct psb_intel_sdvo *psb_intel_sdvo, ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector, ++ int type) ++{ ++ struct drm_device *dev = psb_intel_sdvo->base.base.dev; ++ struct psb_intel_sdvo_tv_format format; ++ uint32_t format_map, i; ++ ++ if (!psb_intel_sdvo_set_target_output(psb_intel_sdvo, type)) ++ return false; ++ ++ BUILD_BUG_ON(sizeof(format) != 6); ++ if (!psb_intel_sdvo_get_value(psb_intel_sdvo, ++ SDVO_CMD_GET_SUPPORTED_TV_FORMATS, ++ &format, sizeof(format))) ++ return false; ++ ++ memcpy(&format_map, &format, min(sizeof(format_map), sizeof(format))); ++ ++ if (format_map == 0) ++ return false; ++ ++ psb_intel_sdvo_connector->format_supported_num = 0; ++ for (i = 0 ; i < TV_FORMAT_NUM; i++) ++ if (format_map & (1 << i)) ++ psb_intel_sdvo_connector->tv_format_supported[psb_intel_sdvo_connector->format_supported_num++] = i; ++ ++ ++ psb_intel_sdvo_connector->tv_format = ++ drm_property_create(dev, DRM_MODE_PROP_ENUM, ++ "mode", psb_intel_sdvo_connector->format_supported_num); ++ if (!psb_intel_sdvo_connector->tv_format) ++ return false; ++ ++ for (i = 0; i < psb_intel_sdvo_connector->format_supported_num; i++) ++ drm_property_add_enum( ++ psb_intel_sdvo_connector->tv_format, i, ++ i, tv_format_names[psb_intel_sdvo_connector->tv_format_supported[i]]); ++ ++ psb_intel_sdvo->tv_format_index = psb_intel_sdvo_connector->tv_format_supported[0]; ++ drm_connector_attach_property(&psb_intel_sdvo_connector->base.base, ++ psb_intel_sdvo_connector->tv_format, 0); ++ return true; ++ ++} ++ ++#define ENHANCEMENT(name, NAME) do { \ ++ if (enhancements.name) { \ ++ if (!psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_MAX_##NAME, &data_value, 4) || \ ++ !psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_##NAME, &response, 2)) \ ++ return false; \ ++ psb_intel_sdvo_connector->max_##name = data_value[0]; \ ++ psb_intel_sdvo_connector->cur_##name = response; \ ++ psb_intel_sdvo_connector->name = \ ++ drm_property_create_range(dev, 0, #name, 0, data_value[0]); \ ++ if (!psb_intel_sdvo_connector->name) return false; \ ++ drm_connector_attach_property(connector, \ ++ psb_intel_sdvo_connector->name, \ ++ psb_intel_sdvo_connector->cur_##name); \ ++ DRM_DEBUG_KMS(#name ": max %d, default %d, current %d\n", \ ++ data_value[0], data_value[1], response); \ ++ } \ ++} while(0) ++ ++static bool ++psb_intel_sdvo_create_enhance_property_tv(struct psb_intel_sdvo *psb_intel_sdvo, ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector, ++ struct psb_intel_sdvo_enhancements_reply enhancements) ++{ ++ struct drm_device *dev = psb_intel_sdvo->base.base.dev; ++ struct drm_connector *connector = &psb_intel_sdvo_connector->base.base; ++ uint16_t response, data_value[2]; ++ ++ /* when horizontal overscan is supported, Add the left/right property */ ++ if (enhancements.overscan_h) { ++ if (!psb_intel_sdvo_get_value(psb_intel_sdvo, ++ SDVO_CMD_GET_MAX_OVERSCAN_H, ++ &data_value, 4)) ++ return false; ++ ++ if (!psb_intel_sdvo_get_value(psb_intel_sdvo, ++ SDVO_CMD_GET_OVERSCAN_H, ++ &response, 2)) ++ return false; ++ ++ psb_intel_sdvo_connector->max_hscan = data_value[0]; ++ psb_intel_sdvo_connector->left_margin = data_value[0] - response; ++ psb_intel_sdvo_connector->right_margin = psb_intel_sdvo_connector->left_margin; ++ psb_intel_sdvo_connector->left = ++ drm_property_create_range(dev, 0, "left_margin", 0, data_value[0]); ++ if (!psb_intel_sdvo_connector->left) ++ return false; ++ ++ drm_connector_attach_property(connector, ++ psb_intel_sdvo_connector->left, ++ psb_intel_sdvo_connector->left_margin); ++ ++ psb_intel_sdvo_connector->right = ++ drm_property_create_range(dev, 0, "right_margin", 0, data_value[0]); ++ if (!psb_intel_sdvo_connector->right) ++ return false; ++ ++ drm_connector_attach_property(connector, ++ psb_intel_sdvo_connector->right, ++ psb_intel_sdvo_connector->right_margin); ++ DRM_DEBUG_KMS("h_overscan: max %d, " ++ "default %d, current %d\n", ++ data_value[0], data_value[1], response); ++ } ++ ++ if (enhancements.overscan_v) { ++ if (!psb_intel_sdvo_get_value(psb_intel_sdvo, ++ SDVO_CMD_GET_MAX_OVERSCAN_V, ++ &data_value, 4)) ++ return false; ++ ++ if (!psb_intel_sdvo_get_value(psb_intel_sdvo, ++ SDVO_CMD_GET_OVERSCAN_V, ++ &response, 2)) ++ return false; ++ ++ psb_intel_sdvo_connector->max_vscan = data_value[0]; ++ psb_intel_sdvo_connector->top_margin = data_value[0] - response; ++ psb_intel_sdvo_connector->bottom_margin = psb_intel_sdvo_connector->top_margin; ++ psb_intel_sdvo_connector->top = ++ drm_property_create_range(dev, 0, "top_margin", 0, data_value[0]); ++ if (!psb_intel_sdvo_connector->top) ++ return false; ++ ++ drm_connector_attach_property(connector, ++ psb_intel_sdvo_connector->top, ++ psb_intel_sdvo_connector->top_margin); ++ ++ psb_intel_sdvo_connector->bottom = ++ drm_property_create_range(dev, 0, "bottom_margin", 0, data_value[0]); ++ if (!psb_intel_sdvo_connector->bottom) ++ return false; ++ ++ drm_connector_attach_property(connector, ++ psb_intel_sdvo_connector->bottom, ++ psb_intel_sdvo_connector->bottom_margin); ++ DRM_DEBUG_KMS("v_overscan: max %d, " ++ "default %d, current %d\n", ++ data_value[0], data_value[1], response); ++ } ++ ++ ENHANCEMENT(hpos, HPOS); ++ ENHANCEMENT(vpos, VPOS); ++ ENHANCEMENT(saturation, SATURATION); ++ ENHANCEMENT(contrast, CONTRAST); ++ ENHANCEMENT(hue, HUE); ++ ENHANCEMENT(sharpness, SHARPNESS); ++ ENHANCEMENT(brightness, BRIGHTNESS); ++ ENHANCEMENT(flicker_filter, FLICKER_FILTER); ++ ENHANCEMENT(flicker_filter_adaptive, FLICKER_FILTER_ADAPTIVE); ++ ENHANCEMENT(flicker_filter_2d, FLICKER_FILTER_2D); ++ ENHANCEMENT(tv_chroma_filter, TV_CHROMA_FILTER); ++ ENHANCEMENT(tv_luma_filter, TV_LUMA_FILTER); ++ ++ if (enhancements.dot_crawl) { ++ if (!psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_DOT_CRAWL, &response, 2)) ++ return false; ++ ++ psb_intel_sdvo_connector->max_dot_crawl = 1; ++ psb_intel_sdvo_connector->cur_dot_crawl = response & 0x1; ++ psb_intel_sdvo_connector->dot_crawl = ++ drm_property_create_range(dev, 0, "dot_crawl", 0, 1); ++ if (!psb_intel_sdvo_connector->dot_crawl) ++ return false; ++ ++ drm_connector_attach_property(connector, ++ psb_intel_sdvo_connector->dot_crawl, ++ psb_intel_sdvo_connector->cur_dot_crawl); ++ DRM_DEBUG_KMS("dot crawl: current %d\n", response); ++ } ++ ++ return true; ++} ++ ++static bool ++psb_intel_sdvo_create_enhance_property_lvds(struct psb_intel_sdvo *psb_intel_sdvo, ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector, ++ struct psb_intel_sdvo_enhancements_reply enhancements) ++{ ++ struct drm_device *dev = psb_intel_sdvo->base.base.dev; ++ struct drm_connector *connector = &psb_intel_sdvo_connector->base.base; ++ uint16_t response, data_value[2]; ++ ++ ENHANCEMENT(brightness, BRIGHTNESS); ++ ++ return true; ++} ++#undef ENHANCEMENT ++ ++static bool psb_intel_sdvo_create_enhance_property(struct psb_intel_sdvo *psb_intel_sdvo, ++ struct psb_intel_sdvo_connector *psb_intel_sdvo_connector) ++{ ++ union { ++ struct psb_intel_sdvo_enhancements_reply reply; ++ uint16_t response; ++ } enhancements; ++ ++ BUILD_BUG_ON(sizeof(enhancements) != 2); ++ ++ enhancements.response = 0; ++ psb_intel_sdvo_get_value(psb_intel_sdvo, ++ SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS, ++ &enhancements, sizeof(enhancements)); ++ if (enhancements.response == 0) { ++ DRM_DEBUG_KMS("No enhancement is supported\n"); ++ return true; ++ } ++ ++ if (IS_TV(psb_intel_sdvo_connector)) ++ return psb_intel_sdvo_create_enhance_property_tv(psb_intel_sdvo, psb_intel_sdvo_connector, enhancements.reply); ++ else if(IS_LVDS(psb_intel_sdvo_connector)) ++ return psb_intel_sdvo_create_enhance_property_lvds(psb_intel_sdvo, psb_intel_sdvo_connector, enhancements.reply); ++ else ++ return true; ++} ++ ++static int psb_intel_sdvo_ddc_proxy_xfer(struct i2c_adapter *adapter, ++ struct i2c_msg *msgs, ++ int num) ++{ ++ struct psb_intel_sdvo *sdvo = adapter->algo_data; ++ ++ if (!psb_intel_sdvo_set_control_bus_switch(sdvo, sdvo->ddc_bus)) ++ return -EIO; ++ ++ return sdvo->i2c->algo->master_xfer(sdvo->i2c, msgs, num); ++} ++ ++static u32 psb_intel_sdvo_ddc_proxy_func(struct i2c_adapter *adapter) ++{ ++ struct psb_intel_sdvo *sdvo = adapter->algo_data; ++ return sdvo->i2c->algo->functionality(sdvo->i2c); ++} ++ ++static const struct i2c_algorithm psb_intel_sdvo_ddc_proxy = { ++ .master_xfer = psb_intel_sdvo_ddc_proxy_xfer, ++ .functionality = psb_intel_sdvo_ddc_proxy_func ++}; ++ ++static bool ++psb_intel_sdvo_init_ddc_proxy(struct psb_intel_sdvo *sdvo, ++ struct drm_device *dev) ++{ ++ sdvo->ddc.owner = THIS_MODULE; ++ sdvo->ddc.class = I2C_CLASS_DDC; ++ snprintf(sdvo->ddc.name, I2C_NAME_SIZE, "SDVO DDC proxy"); ++ sdvo->ddc.dev.parent = &dev->pdev->dev; ++ sdvo->ddc.algo_data = sdvo; ++ sdvo->ddc.algo = &psb_intel_sdvo_ddc_proxy; ++ ++ return i2c_add_adapter(&sdvo->ddc) == 0; ++} ++ ++bool psb_intel_sdvo_init(struct drm_device *dev, int sdvo_reg) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ struct psb_intel_encoder *psb_intel_encoder; ++ struct psb_intel_sdvo *psb_intel_sdvo; ++ int i; ++ ++ psb_intel_sdvo = kzalloc(sizeof(struct psb_intel_sdvo), GFP_KERNEL); ++ if (!psb_intel_sdvo) ++ return false; ++ ++ psb_intel_sdvo->sdvo_reg = sdvo_reg; ++ psb_intel_sdvo->slave_addr = psb_intel_sdvo_get_slave_addr(dev, sdvo_reg) >> 1; ++ psb_intel_sdvo_select_i2c_bus(dev_priv, psb_intel_sdvo, sdvo_reg); ++ if (!psb_intel_sdvo_init_ddc_proxy(psb_intel_sdvo, dev)) { ++ kfree(psb_intel_sdvo); ++ return false; ++ } ++ ++ /* encoder type will be decided later */ ++ psb_intel_encoder = &psb_intel_sdvo->base; ++ psb_intel_encoder->type = INTEL_OUTPUT_SDVO; ++ drm_encoder_init(dev, &psb_intel_encoder->base, &psb_intel_sdvo_enc_funcs, 0); ++ ++ /* Read the regs to test if we can talk to the device */ ++ for (i = 0; i < 0x40; i++) { ++ u8 byte; ++ ++ if (!psb_intel_sdvo_read_byte(psb_intel_sdvo, i, &byte)) { ++ DRM_DEBUG_KMS("No SDVO device found on SDVO%c\n", ++ IS_SDVOB(sdvo_reg) ? 'B' : 'C'); ++ goto err; ++ } ++ } ++ ++ if (IS_SDVOB(sdvo_reg)) ++ dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; ++ else ++ dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; ++ ++ drm_encoder_helper_add(&psb_intel_encoder->base, &psb_intel_sdvo_helper_funcs); ++ ++ /* In default case sdvo lvds is false */ ++ if (!psb_intel_sdvo_get_capabilities(psb_intel_sdvo, &psb_intel_sdvo->caps)) ++ goto err; ++ ++ if (psb_intel_sdvo_output_setup(psb_intel_sdvo, ++ psb_intel_sdvo->caps.output_flags) != true) { ++ DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", ++ IS_SDVOB(sdvo_reg) ? 'B' : 'C'); ++ goto err; ++ } ++ ++ psb_intel_sdvo_select_ddc_bus(dev_priv, psb_intel_sdvo, sdvo_reg); ++ ++ /* Set the input timing to the screen. Assume always input 0. */ ++ if (!psb_intel_sdvo_set_target_input(psb_intel_sdvo)) ++ goto err; ++ ++ if (!psb_intel_sdvo_get_input_pixel_clock_range(psb_intel_sdvo, ++ &psb_intel_sdvo->pixel_clock_min, ++ &psb_intel_sdvo->pixel_clock_max)) ++ goto err; ++ ++ DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " ++ "clock range %dMHz - %dMHz, " ++ "input 1: %c, input 2: %c, " ++ "output 1: %c, output 2: %c\n", ++ SDVO_NAME(psb_intel_sdvo), ++ psb_intel_sdvo->caps.vendor_id, psb_intel_sdvo->caps.device_id, ++ psb_intel_sdvo->caps.device_rev_id, ++ psb_intel_sdvo->pixel_clock_min / 1000, ++ psb_intel_sdvo->pixel_clock_max / 1000, ++ (psb_intel_sdvo->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', ++ (psb_intel_sdvo->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', ++ /* check currently supported outputs */ ++ psb_intel_sdvo->caps.output_flags & ++ (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N', ++ psb_intel_sdvo->caps.output_flags & ++ (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); ++ return true; ++ ++err: ++ drm_encoder_cleanup(&psb_intel_encoder->base); ++ i2c_del_adapter(&psb_intel_sdvo->ddc); ++ kfree(psb_intel_sdvo); ++ ++ return false; ++} +diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo_regs.h b/drivers/gpu/drm/gma500/psb_intel_sdvo_regs.h +new file mode 100644 +index 0000000..600e797 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_intel_sdvo_regs.h +@@ -0,0 +1,723 @@ ++/* ++ * Copyright ? 2006-2007 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Eric Anholt ++ */ ++ ++/** ++ * @file SDVO command definitions and structures. ++ */ ++ ++#define SDVO_OUTPUT_FIRST (0) ++#define SDVO_OUTPUT_TMDS0 (1 << 0) ++#define SDVO_OUTPUT_RGB0 (1 << 1) ++#define SDVO_OUTPUT_CVBS0 (1 << 2) ++#define SDVO_OUTPUT_SVID0 (1 << 3) ++#define SDVO_OUTPUT_YPRPB0 (1 << 4) ++#define SDVO_OUTPUT_SCART0 (1 << 5) ++#define SDVO_OUTPUT_LVDS0 (1 << 6) ++#define SDVO_OUTPUT_TMDS1 (1 << 8) ++#define SDVO_OUTPUT_RGB1 (1 << 9) ++#define SDVO_OUTPUT_CVBS1 (1 << 10) ++#define SDVO_OUTPUT_SVID1 (1 << 11) ++#define SDVO_OUTPUT_YPRPB1 (1 << 12) ++#define SDVO_OUTPUT_SCART1 (1 << 13) ++#define SDVO_OUTPUT_LVDS1 (1 << 14) ++#define SDVO_OUTPUT_LAST (14) ++ ++struct psb_intel_sdvo_caps { ++ u8 vendor_id; ++ u8 device_id; ++ u8 device_rev_id; ++ u8 sdvo_version_major; ++ u8 sdvo_version_minor; ++ unsigned int sdvo_inputs_mask:2; ++ unsigned int smooth_scaling:1; ++ unsigned int sharp_scaling:1; ++ unsigned int up_scaling:1; ++ unsigned int down_scaling:1; ++ unsigned int stall_support:1; ++ unsigned int pad:1; ++ u16 output_flags; ++} __attribute__((packed)); ++ ++/** This matches the EDID DTD structure, more or less */ ++struct psb_intel_sdvo_dtd { ++ struct { ++ u16 clock; /**< pixel clock, in 10kHz units */ ++ u8 h_active; /**< lower 8 bits (pixels) */ ++ u8 h_blank; /**< lower 8 bits (pixels) */ ++ u8 h_high; /**< upper 4 bits each h_active, h_blank */ ++ u8 v_active; /**< lower 8 bits (lines) */ ++ u8 v_blank; /**< lower 8 bits (lines) */ ++ u8 v_high; /**< upper 4 bits each v_active, v_blank */ ++ } part1; ++ ++ struct { ++ u8 h_sync_off; /**< lower 8 bits, from hblank start */ ++ u8 h_sync_width; /**< lower 8 bits (pixels) */ ++ /** lower 4 bits each vsync offset, vsync width */ ++ u8 v_sync_off_width; ++ /** ++ * 2 high bits of hsync offset, 2 high bits of hsync width, ++ * bits 4-5 of vsync offset, and 2 high bits of vsync width. ++ */ ++ u8 sync_off_width_high; ++ u8 dtd_flags; ++ u8 sdvo_flags; ++ /** bits 6-7 of vsync offset at bits 6-7 */ ++ u8 v_sync_off_high; ++ u8 reserved; ++ } part2; ++} __attribute__((packed)); ++ ++struct psb_intel_sdvo_pixel_clock_range { ++ u16 min; /**< pixel clock, in 10kHz units */ ++ u16 max; /**< pixel clock, in 10kHz units */ ++} __attribute__((packed)); ++ ++struct psb_intel_sdvo_preferred_input_timing_args { ++ u16 clock; ++ u16 width; ++ u16 height; ++ u8 interlace:1; ++ u8 scaled:1; ++ u8 pad:6; ++} __attribute__((packed)); ++ ++/* I2C registers for SDVO */ ++#define SDVO_I2C_ARG_0 0x07 ++#define SDVO_I2C_ARG_1 0x06 ++#define SDVO_I2C_ARG_2 0x05 ++#define SDVO_I2C_ARG_3 0x04 ++#define SDVO_I2C_ARG_4 0x03 ++#define SDVO_I2C_ARG_5 0x02 ++#define SDVO_I2C_ARG_6 0x01 ++#define SDVO_I2C_ARG_7 0x00 ++#define SDVO_I2C_OPCODE 0x08 ++#define SDVO_I2C_CMD_STATUS 0x09 ++#define SDVO_I2C_RETURN_0 0x0a ++#define SDVO_I2C_RETURN_1 0x0b ++#define SDVO_I2C_RETURN_2 0x0c ++#define SDVO_I2C_RETURN_3 0x0d ++#define SDVO_I2C_RETURN_4 0x0e ++#define SDVO_I2C_RETURN_5 0x0f ++#define SDVO_I2C_RETURN_6 0x10 ++#define SDVO_I2C_RETURN_7 0x11 ++#define SDVO_I2C_VENDOR_BEGIN 0x20 ++ ++/* Status results */ ++#define SDVO_CMD_STATUS_POWER_ON 0x0 ++#define SDVO_CMD_STATUS_SUCCESS 0x1 ++#define SDVO_CMD_STATUS_NOTSUPP 0x2 ++#define SDVO_CMD_STATUS_INVALID_ARG 0x3 ++#define SDVO_CMD_STATUS_PENDING 0x4 ++#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED 0x5 ++#define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6 ++ ++/* SDVO commands, argument/result registers */ ++ ++#define SDVO_CMD_RESET 0x01 ++ ++/** Returns a struct intel_sdvo_caps */ ++#define SDVO_CMD_GET_DEVICE_CAPS 0x02 ++ ++#define SDVO_CMD_GET_FIRMWARE_REV 0x86 ++# define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0 ++# define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1 ++# define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2 ++ ++/** ++ * Reports which inputs are trained (managed to sync). ++ * ++ * Devices must have trained within 2 vsyncs of a mode change. ++ */ ++#define SDVO_CMD_GET_TRAINED_INPUTS 0x03 ++struct psb_intel_sdvo_get_trained_inputs_response { ++ unsigned int input0_trained:1; ++ unsigned int input1_trained:1; ++ unsigned int pad:6; ++} __attribute__((packed)); ++ ++/** Returns a struct intel_sdvo_output_flags of active outputs. */ ++#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04 ++ ++/** ++ * Sets the current set of active outputs. ++ * ++ * Takes a struct intel_sdvo_output_flags. Must be preceded by a SET_IN_OUT_MAP ++ * on multi-output devices. ++ */ ++#define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05 ++ ++/** ++ * Returns the current mapping of SDVO inputs to outputs on the device. ++ * ++ * Returns two struct intel_sdvo_output_flags structures. ++ */ ++#define SDVO_CMD_GET_IN_OUT_MAP 0x06 ++struct psb_intel_sdvo_in_out_map { ++ u16 in0, in1; ++}; ++ ++/** ++ * Sets the current mapping of SDVO inputs to outputs on the device. ++ * ++ * Takes two struct i380_sdvo_output_flags structures. ++ */ ++#define SDVO_CMD_SET_IN_OUT_MAP 0x07 ++ ++/** ++ * Returns a struct intel_sdvo_output_flags of attached displays. ++ */ ++#define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b ++ ++/** ++ * Returns a struct intel_sdvo_ouptut_flags of displays supporting hot plugging. ++ */ ++#define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c ++ ++/** ++ * Takes a struct intel_sdvo_output_flags. ++ */ ++#define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d ++ ++/** ++ * Returns a struct intel_sdvo_output_flags of displays with hot plug ++ * interrupts enabled. ++ */ ++#define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e ++ ++#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f ++struct intel_sdvo_get_interrupt_event_source_response { ++ u16 interrupt_status; ++ unsigned int ambient_light_interrupt:1; ++ unsigned int hdmi_audio_encrypt_change:1; ++ unsigned int pad:6; ++} __attribute__((packed)); ++ ++/** ++ * Selects which input is affected by future input commands. ++ * ++ * Commands affected include SET_INPUT_TIMINGS_PART[12], ++ * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12], ++ * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS. ++ */ ++#define SDVO_CMD_SET_TARGET_INPUT 0x10 ++struct psb_intel_sdvo_set_target_input_args { ++ unsigned int target_1:1; ++ unsigned int pad:7; ++} __attribute__((packed)); ++ ++/** ++ * Takes a struct intel_sdvo_output_flags of which outputs are targeted by ++ * future output commands. ++ * ++ * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12], ++ * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE. ++ */ ++#define SDVO_CMD_SET_TARGET_OUTPUT 0x11 ++ ++#define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12 ++#define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13 ++#define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14 ++#define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15 ++#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16 ++#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17 ++#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18 ++#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19 ++/* Part 1 */ ++# define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0 ++# define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1 ++# define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2 ++# define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3 ++# define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4 ++# define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5 ++# define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6 ++# define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7 ++/* Part 2 */ ++# define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0 ++# define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1 ++# define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2 ++# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3 ++# define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4 ++# define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7) ++# define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5) ++# define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3) ++# define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1) ++# define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5 ++# define SDVO_DTD_SDVO_FLAG_STALL (1 << 7) ++# define SDVO_DTD_SDVO_FLAG_CENTERED (0 << 6) ++# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT (1 << 6) ++# define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4) ++# define SDVO_DTD_SDVO_FLAG_SCALING_NONE (0 << 4) ++# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP (1 << 4) ++# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4) ++# define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6 ++ ++/** ++ * Generates a DTD based on the given width, height, and flags. ++ * ++ * This will be supported by any device supporting scaling or interlaced ++ * modes. ++ */ ++#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a ++# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0 ++# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1 ++# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2 ++# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3 ++# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4 ++# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5 ++# define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6 ++# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0) ++# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1) ++ ++#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b ++#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c ++ ++/** Returns a struct intel_sdvo_pixel_clock_range */ ++#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d ++/** Returns a struct intel_sdvo_pixel_clock_range */ ++#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e ++ ++/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */ ++#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f ++ ++/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ ++#define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20 ++/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ ++#define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21 ++# define SDVO_CLOCK_RATE_MULT_1X (1 << 0) ++# define SDVO_CLOCK_RATE_MULT_2X (1 << 1) ++# define SDVO_CLOCK_RATE_MULT_4X (1 << 3) ++ ++#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 ++/** 6 bytes of bit flags for TV formats shared by all TV format functions */ ++struct psb_intel_sdvo_tv_format { ++ unsigned int ntsc_m:1; ++ unsigned int ntsc_j:1; ++ unsigned int ntsc_443:1; ++ unsigned int pal_b:1; ++ unsigned int pal_d:1; ++ unsigned int pal_g:1; ++ unsigned int pal_h:1; ++ unsigned int pal_i:1; ++ ++ unsigned int pal_m:1; ++ unsigned int pal_n:1; ++ unsigned int pal_nc:1; ++ unsigned int pal_60:1; ++ unsigned int secam_b:1; ++ unsigned int secam_d:1; ++ unsigned int secam_g:1; ++ unsigned int secam_k:1; ++ ++ unsigned int secam_k1:1; ++ unsigned int secam_l:1; ++ unsigned int secam_60:1; ++ unsigned int hdtv_std_smpte_240m_1080i_59:1; ++ unsigned int hdtv_std_smpte_240m_1080i_60:1; ++ unsigned int hdtv_std_smpte_260m_1080i_59:1; ++ unsigned int hdtv_std_smpte_260m_1080i_60:1; ++ unsigned int hdtv_std_smpte_274m_1080i_50:1; ++ ++ unsigned int hdtv_std_smpte_274m_1080i_59:1; ++ unsigned int hdtv_std_smpte_274m_1080i_60:1; ++ unsigned int hdtv_std_smpte_274m_1080p_23:1; ++ unsigned int hdtv_std_smpte_274m_1080p_24:1; ++ unsigned int hdtv_std_smpte_274m_1080p_25:1; ++ unsigned int hdtv_std_smpte_274m_1080p_29:1; ++ unsigned int hdtv_std_smpte_274m_1080p_30:1; ++ unsigned int hdtv_std_smpte_274m_1080p_50:1; ++ ++ unsigned int hdtv_std_smpte_274m_1080p_59:1; ++ unsigned int hdtv_std_smpte_274m_1080p_60:1; ++ unsigned int hdtv_std_smpte_295m_1080i_50:1; ++ unsigned int hdtv_std_smpte_295m_1080p_50:1; ++ unsigned int hdtv_std_smpte_296m_720p_59:1; ++ unsigned int hdtv_std_smpte_296m_720p_60:1; ++ unsigned int hdtv_std_smpte_296m_720p_50:1; ++ unsigned int hdtv_std_smpte_293m_480p_59:1; ++ ++ unsigned int hdtv_std_smpte_170m_480i_59:1; ++ unsigned int hdtv_std_iturbt601_576i_50:1; ++ unsigned int hdtv_std_iturbt601_576p_50:1; ++ unsigned int hdtv_std_eia_7702a_480i_60:1; ++ unsigned int hdtv_std_eia_7702a_480p_60:1; ++ unsigned int pad:3; ++} __attribute__((packed)); ++ ++#define SDVO_CMD_GET_TV_FORMAT 0x28 ++ ++#define SDVO_CMD_SET_TV_FORMAT 0x29 ++ ++/** Returns the resolutiosn that can be used with the given TV format */ ++#define SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT 0x83 ++struct psb_intel_sdvo_sdtv_resolution_request { ++ unsigned int ntsc_m:1; ++ unsigned int ntsc_j:1; ++ unsigned int ntsc_443:1; ++ unsigned int pal_b:1; ++ unsigned int pal_d:1; ++ unsigned int pal_g:1; ++ unsigned int pal_h:1; ++ unsigned int pal_i:1; ++ ++ unsigned int pal_m:1; ++ unsigned int pal_n:1; ++ unsigned int pal_nc:1; ++ unsigned int pal_60:1; ++ unsigned int secam_b:1; ++ unsigned int secam_d:1; ++ unsigned int secam_g:1; ++ unsigned int secam_k:1; ++ ++ unsigned int secam_k1:1; ++ unsigned int secam_l:1; ++ unsigned int secam_60:1; ++ unsigned int pad:5; ++} __attribute__((packed)); ++ ++struct psb_intel_sdvo_sdtv_resolution_reply { ++ unsigned int res_320x200:1; ++ unsigned int res_320x240:1; ++ unsigned int res_400x300:1; ++ unsigned int res_640x350:1; ++ unsigned int res_640x400:1; ++ unsigned int res_640x480:1; ++ unsigned int res_704x480:1; ++ unsigned int res_704x576:1; ++ ++ unsigned int res_720x350:1; ++ unsigned int res_720x400:1; ++ unsigned int res_720x480:1; ++ unsigned int res_720x540:1; ++ unsigned int res_720x576:1; ++ unsigned int res_768x576:1; ++ unsigned int res_800x600:1; ++ unsigned int res_832x624:1; ++ ++ unsigned int res_920x766:1; ++ unsigned int res_1024x768:1; ++ unsigned int res_1280x1024:1; ++ unsigned int pad:5; ++} __attribute__((packed)); ++ ++/* Get supported resolution with squire pixel aspect ratio that can be ++ scaled for the requested HDTV format */ ++#define SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT 0x85 ++ ++struct psb_intel_sdvo_hdtv_resolution_request { ++ unsigned int hdtv_std_smpte_240m_1080i_59:1; ++ unsigned int hdtv_std_smpte_240m_1080i_60:1; ++ unsigned int hdtv_std_smpte_260m_1080i_59:1; ++ unsigned int hdtv_std_smpte_260m_1080i_60:1; ++ unsigned int hdtv_std_smpte_274m_1080i_50:1; ++ unsigned int hdtv_std_smpte_274m_1080i_59:1; ++ unsigned int hdtv_std_smpte_274m_1080i_60:1; ++ unsigned int hdtv_std_smpte_274m_1080p_23:1; ++ ++ unsigned int hdtv_std_smpte_274m_1080p_24:1; ++ unsigned int hdtv_std_smpte_274m_1080p_25:1; ++ unsigned int hdtv_std_smpte_274m_1080p_29:1; ++ unsigned int hdtv_std_smpte_274m_1080p_30:1; ++ unsigned int hdtv_std_smpte_274m_1080p_50:1; ++ unsigned int hdtv_std_smpte_274m_1080p_59:1; ++ unsigned int hdtv_std_smpte_274m_1080p_60:1; ++ unsigned int hdtv_std_smpte_295m_1080i_50:1; ++ ++ unsigned int hdtv_std_smpte_295m_1080p_50:1; ++ unsigned int hdtv_std_smpte_296m_720p_59:1; ++ unsigned int hdtv_std_smpte_296m_720p_60:1; ++ unsigned int hdtv_std_smpte_296m_720p_50:1; ++ unsigned int hdtv_std_smpte_293m_480p_59:1; ++ unsigned int hdtv_std_smpte_170m_480i_59:1; ++ unsigned int hdtv_std_iturbt601_576i_50:1; ++ unsigned int hdtv_std_iturbt601_576p_50:1; ++ ++ unsigned int hdtv_std_eia_7702a_480i_60:1; ++ unsigned int hdtv_std_eia_7702a_480p_60:1; ++ unsigned int pad:6; ++} __attribute__((packed)); ++ ++struct psb_intel_sdvo_hdtv_resolution_reply { ++ unsigned int res_640x480:1; ++ unsigned int res_800x600:1; ++ unsigned int res_1024x768:1; ++ unsigned int res_1280x960:1; ++ unsigned int res_1400x1050:1; ++ unsigned int res_1600x1200:1; ++ unsigned int res_1920x1440:1; ++ unsigned int res_2048x1536:1; ++ ++ unsigned int res_2560x1920:1; ++ unsigned int res_3200x2400:1; ++ unsigned int res_3840x2880:1; ++ unsigned int pad1:5; ++ ++ unsigned int res_848x480:1; ++ unsigned int res_1064x600:1; ++ unsigned int res_1280x720:1; ++ unsigned int res_1360x768:1; ++ unsigned int res_1704x960:1; ++ unsigned int res_1864x1050:1; ++ unsigned int res_1920x1080:1; ++ unsigned int res_2128x1200:1; ++ ++ unsigned int res_2560x1400:1; ++ unsigned int res_2728x1536:1; ++ unsigned int res_3408x1920:1; ++ unsigned int res_4264x2400:1; ++ unsigned int res_5120x2880:1; ++ unsigned int pad2:3; ++ ++ unsigned int res_768x480:1; ++ unsigned int res_960x600:1; ++ unsigned int res_1152x720:1; ++ unsigned int res_1124x768:1; ++ unsigned int res_1536x960:1; ++ unsigned int res_1680x1050:1; ++ unsigned int res_1728x1080:1; ++ unsigned int res_1920x1200:1; ++ ++ unsigned int res_2304x1440:1; ++ unsigned int res_2456x1536:1; ++ unsigned int res_3072x1920:1; ++ unsigned int res_3840x2400:1; ++ unsigned int res_4608x2880:1; ++ unsigned int pad3:3; ++ ++ unsigned int res_1280x1024:1; ++ unsigned int pad4:7; ++ ++ unsigned int res_1280x768:1; ++ unsigned int pad5:7; ++} __attribute__((packed)); ++ ++/* Get supported power state returns info for encoder and monitor, rely on ++ last SetTargetInput and SetTargetOutput calls */ ++#define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a ++/* Get power state returns info for encoder and monitor, rely on last ++ SetTargetInput and SetTargetOutput calls */ ++#define SDVO_CMD_GET_POWER_STATE 0x2b ++#define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b ++#define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c ++# define SDVO_ENCODER_STATE_ON (1 << 0) ++# define SDVO_ENCODER_STATE_STANDBY (1 << 1) ++# define SDVO_ENCODER_STATE_SUSPEND (1 << 2) ++# define SDVO_ENCODER_STATE_OFF (1 << 3) ++# define SDVO_MONITOR_STATE_ON (1 << 4) ++# define SDVO_MONITOR_STATE_STANDBY (1 << 5) ++# define SDVO_MONITOR_STATE_SUSPEND (1 << 6) ++# define SDVO_MONITOR_STATE_OFF (1 << 7) ++ ++#define SDVO_CMD_GET_MAX_PANEL_POWER_SEQUENCING 0x2d ++#define SDVO_CMD_GET_PANEL_POWER_SEQUENCING 0x2e ++#define SDVO_CMD_SET_PANEL_POWER_SEQUENCING 0x2f ++/** ++ * The panel power sequencing parameters are in units of milliseconds. ++ * The high fields are bits 8:9 of the 10-bit values. ++ */ ++struct psb_sdvo_panel_power_sequencing { ++ u8 t0; ++ u8 t1; ++ u8 t2; ++ u8 t3; ++ u8 t4; ++ ++ unsigned int t0_high:2; ++ unsigned int t1_high:2; ++ unsigned int t2_high:2; ++ unsigned int t3_high:2; ++ ++ unsigned int t4_high:2; ++ unsigned int pad:6; ++} __attribute__((packed)); ++ ++#define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL 0x30 ++struct sdvo_max_backlight_reply { ++ u8 max_value; ++ u8 default_value; ++} __attribute__((packed)); ++ ++#define SDVO_CMD_GET_BACKLIGHT_LEVEL 0x31 ++#define SDVO_CMD_SET_BACKLIGHT_LEVEL 0x32 ++ ++#define SDVO_CMD_GET_AMBIENT_LIGHT 0x33 ++struct sdvo_get_ambient_light_reply { ++ u16 trip_low; ++ u16 trip_high; ++ u16 value; ++} __attribute__((packed)); ++#define SDVO_CMD_SET_AMBIENT_LIGHT 0x34 ++struct sdvo_set_ambient_light_reply { ++ u16 trip_low; ++ u16 trip_high; ++ unsigned int enable:1; ++ unsigned int pad:7; ++} __attribute__((packed)); ++ ++/* Set display power state */ ++#define SDVO_CMD_SET_DISPLAY_POWER_STATE 0x7d ++# define SDVO_DISPLAY_STATE_ON (1 << 0) ++# define SDVO_DISPLAY_STATE_STANDBY (1 << 1) ++# define SDVO_DISPLAY_STATE_SUSPEND (1 << 2) ++# define SDVO_DISPLAY_STATE_OFF (1 << 3) ++ ++#define SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS 0x84 ++struct psb_intel_sdvo_enhancements_reply { ++ unsigned int flicker_filter:1; ++ unsigned int flicker_filter_adaptive:1; ++ unsigned int flicker_filter_2d:1; ++ unsigned int saturation:1; ++ unsigned int hue:1; ++ unsigned int brightness:1; ++ unsigned int contrast:1; ++ unsigned int overscan_h:1; ++ ++ unsigned int overscan_v:1; ++ unsigned int hpos:1; ++ unsigned int vpos:1; ++ unsigned int sharpness:1; ++ unsigned int dot_crawl:1; ++ unsigned int dither:1; ++ unsigned int tv_chroma_filter:1; ++ unsigned int tv_luma_filter:1; ++} __attribute__((packed)); ++ ++/* Picture enhancement limits below are dependent on the current TV format, ++ * and thus need to be queried and set after it. ++ */ ++#define SDVO_CMD_GET_MAX_FLICKER_FILTER 0x4d ++#define SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE 0x7b ++#define SDVO_CMD_GET_MAX_FLICKER_FILTER_2D 0x52 ++#define SDVO_CMD_GET_MAX_SATURATION 0x55 ++#define SDVO_CMD_GET_MAX_HUE 0x58 ++#define SDVO_CMD_GET_MAX_BRIGHTNESS 0x5b ++#define SDVO_CMD_GET_MAX_CONTRAST 0x5e ++#define SDVO_CMD_GET_MAX_OVERSCAN_H 0x61 ++#define SDVO_CMD_GET_MAX_OVERSCAN_V 0x64 ++#define SDVO_CMD_GET_MAX_HPOS 0x67 ++#define SDVO_CMD_GET_MAX_VPOS 0x6a ++#define SDVO_CMD_GET_MAX_SHARPNESS 0x6d ++#define SDVO_CMD_GET_MAX_TV_CHROMA_FILTER 0x74 ++#define SDVO_CMD_GET_MAX_TV_LUMA_FILTER 0x77 ++struct psb_intel_sdvo_enhancement_limits_reply { ++ u16 max_value; ++ u16 default_value; ++} __attribute__((packed)); ++ ++#define SDVO_CMD_GET_LVDS_PANEL_INFORMATION 0x7f ++#define SDVO_CMD_SET_LVDS_PANEL_INFORMATION 0x80 ++# define SDVO_LVDS_COLOR_DEPTH_18 (0 << 0) ++# define SDVO_LVDS_COLOR_DEPTH_24 (1 << 0) ++# define SDVO_LVDS_CONNECTOR_SPWG (0 << 2) ++# define SDVO_LVDS_CONNECTOR_OPENLDI (1 << 2) ++# define SDVO_LVDS_SINGLE_CHANNEL (0 << 4) ++# define SDVO_LVDS_DUAL_CHANNEL (1 << 4) ++ ++#define SDVO_CMD_GET_FLICKER_FILTER 0x4e ++#define SDVO_CMD_SET_FLICKER_FILTER 0x4f ++#define SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE 0x50 ++#define SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE 0x51 ++#define SDVO_CMD_GET_FLICKER_FILTER_2D 0x53 ++#define SDVO_CMD_SET_FLICKER_FILTER_2D 0x54 ++#define SDVO_CMD_GET_SATURATION 0x56 ++#define SDVO_CMD_SET_SATURATION 0x57 ++#define SDVO_CMD_GET_HUE 0x59 ++#define SDVO_CMD_SET_HUE 0x5a ++#define SDVO_CMD_GET_BRIGHTNESS 0x5c ++#define SDVO_CMD_SET_BRIGHTNESS 0x5d ++#define SDVO_CMD_GET_CONTRAST 0x5f ++#define SDVO_CMD_SET_CONTRAST 0x60 ++#define SDVO_CMD_GET_OVERSCAN_H 0x62 ++#define SDVO_CMD_SET_OVERSCAN_H 0x63 ++#define SDVO_CMD_GET_OVERSCAN_V 0x65 ++#define SDVO_CMD_SET_OVERSCAN_V 0x66 ++#define SDVO_CMD_GET_HPOS 0x68 ++#define SDVO_CMD_SET_HPOS 0x69 ++#define SDVO_CMD_GET_VPOS 0x6b ++#define SDVO_CMD_SET_VPOS 0x6c ++#define SDVO_CMD_GET_SHARPNESS 0x6e ++#define SDVO_CMD_SET_SHARPNESS 0x6f ++#define SDVO_CMD_GET_TV_CHROMA_FILTER 0x75 ++#define SDVO_CMD_SET_TV_CHROMA_FILTER 0x76 ++#define SDVO_CMD_GET_TV_LUMA_FILTER 0x78 ++#define SDVO_CMD_SET_TV_LUMA_FILTER 0x79 ++struct psb_intel_sdvo_enhancements_arg { ++ u16 value; ++}__attribute__((packed)); ++ ++#define SDVO_CMD_GET_DOT_CRAWL 0x70 ++#define SDVO_CMD_SET_DOT_CRAWL 0x71 ++# define SDVO_DOT_CRAWL_ON (1 << 0) ++# define SDVO_DOT_CRAWL_DEFAULT_ON (1 << 1) ++ ++#define SDVO_CMD_GET_DITHER 0x72 ++#define SDVO_CMD_SET_DITHER 0x73 ++# define SDVO_DITHER_ON (1 << 0) ++# define SDVO_DITHER_DEFAULT_ON (1 << 1) ++ ++#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a ++# define SDVO_CONTROL_BUS_PROM (1 << 0) ++# define SDVO_CONTROL_BUS_DDC1 (1 << 1) ++# define SDVO_CONTROL_BUS_DDC2 (1 << 2) ++# define SDVO_CONTROL_BUS_DDC3 (1 << 3) ++ ++/* HDMI op codes */ ++#define SDVO_CMD_GET_SUPP_ENCODE 0x9d ++#define SDVO_CMD_GET_ENCODE 0x9e ++#define SDVO_CMD_SET_ENCODE 0x9f ++ #define SDVO_ENCODE_DVI 0x0 ++ #define SDVO_ENCODE_HDMI 0x1 ++#define SDVO_CMD_SET_PIXEL_REPLI 0x8b ++#define SDVO_CMD_GET_PIXEL_REPLI 0x8c ++#define SDVO_CMD_GET_COLORIMETRY_CAP 0x8d ++#define SDVO_CMD_SET_COLORIMETRY 0x8e ++ #define SDVO_COLORIMETRY_RGB256 0x0 ++ #define SDVO_COLORIMETRY_RGB220 0x1 ++ #define SDVO_COLORIMETRY_YCrCb422 0x3 ++ #define SDVO_COLORIMETRY_YCrCb444 0x4 ++#define SDVO_CMD_GET_COLORIMETRY 0x8f ++#define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90 ++#define SDVO_CMD_SET_AUDIO_STAT 0x91 ++#define SDVO_CMD_GET_AUDIO_STAT 0x92 ++#define SDVO_CMD_SET_HBUF_INDEX 0x93 ++#define SDVO_CMD_GET_HBUF_INDEX 0x94 ++#define SDVO_CMD_GET_HBUF_INFO 0x95 ++#define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 ++#define SDVO_CMD_GET_HBUF_AV_SPLIT 0x97 ++#define SDVO_CMD_SET_HBUF_DATA 0x98 ++#define SDVO_CMD_GET_HBUF_DATA 0x99 ++#define SDVO_CMD_SET_HBUF_TXRATE 0x9a ++#define SDVO_CMD_GET_HBUF_TXRATE 0x9b ++ #define SDVO_HBUF_TX_DISABLED (0 << 6) ++ #define SDVO_HBUF_TX_ONCE (2 << 6) ++ #define SDVO_HBUF_TX_VSYNC (3 << 6) ++#define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c ++#define SDVO_NEED_TO_STALL (1 << 7) ++ ++struct psb_intel_sdvo_encode { ++ u8 dvi_rev; ++ u8 hdmi_rev; ++} __attribute__ ((packed)); +diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c +new file mode 100644 +index 0000000..1869586 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_irq.c +@@ -0,0 +1,622 @@ ++/************************************************************************** ++ * Copyright (c) 2007, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to ++ * develop this driver. ++ * ++ **************************************************************************/ ++/* ++ */ ++ ++#include ++#include "psb_drv.h" ++#include "psb_reg.h" ++#include "psb_intel_reg.h" ++#include "power.h" ++#include "psb_irq.h" ++#include "mdfld_output.h" ++ ++/* ++ * inline functions ++ */ ++ ++static inline u32 ++psb_pipestat(int pipe) ++{ ++ if (pipe == 0) ++ return PIPEASTAT; ++ if (pipe == 1) ++ return PIPEBSTAT; ++ if (pipe == 2) ++ return PIPECSTAT; ++ BUG(); ++} ++ ++static inline u32 ++mid_pipe_event(int pipe) ++{ ++ if (pipe == 0) ++ return _PSB_PIPEA_EVENT_FLAG; ++ if (pipe == 1) ++ return _MDFLD_PIPEB_EVENT_FLAG; ++ if (pipe == 2) ++ return _MDFLD_PIPEC_EVENT_FLAG; ++ BUG(); ++} ++ ++static inline u32 ++mid_pipe_vsync(int pipe) ++{ ++ if (pipe == 0) ++ return _PSB_VSYNC_PIPEA_FLAG; ++ if (pipe == 1) ++ return _PSB_VSYNC_PIPEB_FLAG; ++ if (pipe == 2) ++ return _MDFLD_PIPEC_VBLANK_FLAG; ++ BUG(); ++} ++ ++static inline u32 ++mid_pipeconf(int pipe) ++{ ++ if (pipe == 0) ++ return PIPEACONF; ++ if (pipe == 1) ++ return PIPEBCONF; ++ if (pipe == 2) ++ return PIPECCONF; ++ BUG(); ++} ++ ++void ++psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) ++{ ++ if ((dev_priv->pipestat[pipe] & mask) != mask) { ++ u32 reg = psb_pipestat(pipe); ++ dev_priv->pipestat[pipe] |= mask; ++ /* Enable the interrupt, clear any pending status */ ++ if (gma_power_begin(dev_priv->dev, false)) { ++ u32 writeVal = PSB_RVDC32(reg); ++ writeVal |= (mask | (mask >> 16)); ++ PSB_WVDC32(writeVal, reg); ++ (void) PSB_RVDC32(reg); ++ gma_power_end(dev_priv->dev); ++ } ++ } ++} ++ ++void ++psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) ++{ ++ if ((dev_priv->pipestat[pipe] & mask) != 0) { ++ u32 reg = psb_pipestat(pipe); ++ dev_priv->pipestat[pipe] &= ~mask; ++ if (gma_power_begin(dev_priv->dev, false)) { ++ u32 writeVal = PSB_RVDC32(reg); ++ writeVal &= ~mask; ++ PSB_WVDC32(writeVal, reg); ++ (void) PSB_RVDC32(reg); ++ gma_power_end(dev_priv->dev); ++ } ++ } ++} ++ ++static void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe) ++{ ++ if (gma_power_begin(dev_priv->dev, false)) { ++ u32 pipe_event = mid_pipe_event(pipe); ++ dev_priv->vdc_irq_mask |= pipe_event; ++ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); ++ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); ++ gma_power_end(dev_priv->dev); ++ } ++} ++ ++static void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe) ++{ ++ if (dev_priv->pipestat[pipe] == 0) { ++ if (gma_power_begin(dev_priv->dev, false)) { ++ u32 pipe_event = mid_pipe_event(pipe); ++ dev_priv->vdc_irq_mask &= ~pipe_event; ++ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); ++ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); ++ gma_power_end(dev_priv->dev); ++ } ++ } ++} ++ ++/** ++ * Display controller interrupt handler for pipe event. ++ * ++ */ ++static void mid_pipe_event_handler(struct drm_device *dev, int pipe) ++{ ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *) dev->dev_private; ++ ++ uint32_t pipe_stat_val = 0; ++ uint32_t pipe_stat_reg = psb_pipestat(pipe); ++ uint32_t pipe_enable = dev_priv->pipestat[pipe]; ++ uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16; ++ uint32_t pipe_clear; ++ uint32_t i = 0; ++ ++ spin_lock(&dev_priv->irqmask_lock); ++ ++ pipe_stat_val = PSB_RVDC32(pipe_stat_reg); ++ pipe_stat_val &= pipe_enable | pipe_status; ++ pipe_stat_val &= pipe_stat_val >> 16; ++ ++ spin_unlock(&dev_priv->irqmask_lock); ++ ++ /* Clear the 2nd level interrupt status bits ++ * Sometimes the bits are very sticky so we repeat until they unstick */ ++ for (i = 0; i < 0xffff; i++) { ++ PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg); ++ pipe_clear = PSB_RVDC32(pipe_stat_reg) & pipe_status; ++ ++ if (pipe_clear == 0) ++ break; ++ } ++ ++ if (pipe_clear) ++ dev_err(dev->dev, ++ "%s, can't clear status bits for pipe %d, its value = 0x%x.\n", ++ __func__, pipe, PSB_RVDC32(pipe_stat_reg)); ++ ++ if (pipe_stat_val & PIPE_VBLANK_STATUS) ++ drm_handle_vblank(dev, pipe); ++ ++ if (pipe_stat_val & PIPE_TE_STATUS) ++ drm_handle_vblank(dev, pipe); ++} ++ ++/* ++ * Display controller interrupt handler. ++ */ ++static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) ++{ ++ if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG) ++ mid_pipe_event_handler(dev, 0); ++ ++ if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG) ++ mid_pipe_event_handler(dev, 1); ++} ++ ++irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) ++{ ++ struct drm_device *dev = (struct drm_device *) arg; ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *) dev->dev_private; ++ ++ uint32_t vdc_stat, dsp_int = 0, sgx_int = 0; ++ int handled = 0; ++ ++ spin_lock(&dev_priv->irqmask_lock); ++ ++ vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R); ++ ++ if (vdc_stat & _PSB_PIPE_EVENT_FLAG) ++ dsp_int = 1; ++ ++ /* FIXME: Handle Medfield ++ if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG) ++ dsp_int = 1; ++ */ ++ ++ if (vdc_stat & _PSB_IRQ_SGX_FLAG) ++ sgx_int = 1; ++ ++ vdc_stat &= dev_priv->vdc_irq_mask; ++ spin_unlock(&dev_priv->irqmask_lock); ++ ++ if (dsp_int && gma_power_is_on(dev)) { ++ psb_vdc_interrupt(dev, vdc_stat); ++ handled = 1; ++ } ++ ++ if (sgx_int) { ++ /* Not expected - we have it masked, shut it up */ ++ u32 s, s2; ++ s = PSB_RSGX32(PSB_CR_EVENT_STATUS); ++ s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2); ++ PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR); ++ PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2); ++ /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but ++ we may as well poll even if we add that ! */ ++ handled = 1; ++ } ++ ++ PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R); ++ (void) PSB_RVDC32(PSB_INT_IDENTITY_R); ++ DRM_READMEMORYBARRIER(); ++ ++ if (!handled) ++ return IRQ_NONE; ++ ++ return IRQ_HANDLED; ++} ++ ++void psb_irq_preinstall(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *) dev->dev_private; ++ unsigned long irqflags; ++ ++ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); ++ ++ if (gma_power_is_on(dev)) ++ PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); ++ if (dev->vblank_enabled[0]) ++ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; ++ if (dev->vblank_enabled[1]) ++ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; ++ ++ /* FIXME: Handle Medfield irq mask ++ if (dev->vblank_enabled[1]) ++ dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG; ++ if (dev->vblank_enabled[2]) ++ dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; ++ */ ++ ++ /* This register is safe even if display island is off */ ++ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); ++ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); ++} ++ ++int psb_irq_postinstall(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *) dev->dev_private; ++ unsigned long irqflags; ++ ++ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); ++ ++ /* This register is safe even if display island is off */ ++ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); ++ PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); ++ ++ if (dev->vblank_enabled[0]) ++ psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); ++ else ++ psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); ++ ++ if (dev->vblank_enabled[1]) ++ psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); ++ else ++ psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); ++ ++ if (dev->vblank_enabled[2]) ++ psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); ++ else ++ psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); ++ ++ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); ++ return 0; ++} ++ ++void psb_irq_uninstall(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *) dev->dev_private; ++ unsigned long irqflags; ++ ++ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); ++ ++ PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); ++ ++ if (dev->vblank_enabled[0]) ++ psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); ++ ++ if (dev->vblank_enabled[1]) ++ psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); ++ ++ if (dev->vblank_enabled[2]) ++ psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); ++ ++ dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | ++ _PSB_IRQ_MSVDX_FLAG | ++ _LNC_IRQ_TOPAZ_FLAG; ++ ++ /* These two registers are safe even if display island is off */ ++ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); ++ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); ++ ++ wmb(); ++ ++ /* This register is safe even if display island is off */ ++ PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R); ++ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); ++} ++ ++void psb_irq_turn_on_dpst(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *) dev->dev_private; ++ u32 hist_reg; ++ u32 pwm_reg; ++ ++ if (gma_power_begin(dev, false)) { ++ PSB_WVDC32(1 << 31, HISTOGRAM_LOGIC_CONTROL); ++ hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); ++ PSB_WVDC32(1 << 31, HISTOGRAM_INT_CONTROL); ++ hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); ++ ++ PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC); ++ pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); ++ PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE ++ | PWM_PHASEIN_INT_ENABLE, ++ PWM_CONTROL_LOGIC); ++ pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); ++ ++ psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); ++ ++ hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); ++ PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR, ++ HISTOGRAM_INT_CONTROL); ++ pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); ++ PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE, ++ PWM_CONTROL_LOGIC); ++ ++ gma_power_end(dev); ++ } ++} ++ ++int psb_irq_enable_dpst(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *) dev->dev_private; ++ unsigned long irqflags; ++ ++ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); ++ ++ /* enable DPST */ ++ mid_enable_pipe_event(dev_priv, 0); ++ psb_irq_turn_on_dpst(dev); ++ ++ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); ++ return 0; ++} ++ ++void psb_irq_turn_off_dpst(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *) dev->dev_private; ++ u32 hist_reg; ++ u32 pwm_reg; ++ ++ if (gma_power_begin(dev, false)) { ++ PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL); ++ hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); ++ ++ psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); ++ ++ pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); ++ PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE), ++ PWM_CONTROL_LOGIC); ++ pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); ++ ++ gma_power_end(dev); ++ } ++} ++ ++int psb_irq_disable_dpst(struct drm_device *dev) ++{ ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *) dev->dev_private; ++ unsigned long irqflags; ++ ++ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); ++ ++ mid_disable_pipe_event(dev_priv, 0); ++ psb_irq_turn_off_dpst(dev); ++ ++ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); ++ ++ return 0; ++} ++ ++#ifdef PSB_FIXME ++static int psb_vblank_do_wait(struct drm_device *dev, ++ unsigned int *sequence, atomic_t *counter) ++{ ++ unsigned int cur_vblank; ++ int ret = 0; ++ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, ++ (((cur_vblank = atomic_read(counter)) ++ - *sequence) <= (1 << 23))); ++ *sequence = cur_vblank; ++ ++ return ret; ++} ++#endif ++ ++/* ++ * It is used to enable VBLANK interrupt ++ */ ++int psb_enable_vblank(struct drm_device *dev, int pipe) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ unsigned long irqflags; ++ uint32_t reg_val = 0; ++ uint32_t pipeconf_reg = mid_pipeconf(pipe); ++ ++ /* Medfield is different - we should perhaps extract out vblank ++ and blacklight etc ops */ ++ if (IS_MFLD(dev)) ++ return mdfld_enable_te(dev, pipe); ++ ++ if (gma_power_begin(dev, false)) { ++ reg_val = REG_READ(pipeconf_reg); ++ gma_power_end(dev); ++ } ++ ++ if (!(reg_val & PIPEACONF_ENABLE)) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); ++ ++ if (pipe == 0) ++ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; ++ else if (pipe == 1) ++ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; ++ ++ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); ++ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); ++ psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); ++ ++ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); ++ ++ return 0; ++} ++ ++/* ++ * It is used to disable VBLANK interrupt ++ */ ++void psb_disable_vblank(struct drm_device *dev, int pipe) ++{ ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ unsigned long irqflags; ++ ++ if (IS_MFLD(dev)) ++ mdfld_disable_te(dev, pipe); ++ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); ++ ++ if (pipe == 0) ++ dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEA_FLAG; ++ else if (pipe == 1) ++ dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEB_FLAG; ++ ++ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); ++ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); ++ psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); ++ ++ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); ++} ++ ++/* ++ * It is used to enable TE interrupt ++ */ ++int mdfld_enable_te(struct drm_device *dev, int pipe) ++{ ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *) dev->dev_private; ++ unsigned long irqflags; ++ uint32_t reg_val = 0; ++ uint32_t pipeconf_reg = mid_pipeconf(pipe); ++ ++ if (gma_power_begin(dev, false)) { ++ reg_val = REG_READ(pipeconf_reg); ++ gma_power_end(dev); ++ } ++ ++ if (!(reg_val & PIPEACONF_ENABLE)) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); ++ ++ mid_enable_pipe_event(dev_priv, pipe); ++ psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE); ++ ++ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); ++ ++ return 0; ++} ++ ++/* ++ * It is used to disable TE interrupt ++ */ ++void mdfld_disable_te(struct drm_device *dev, int pipe) ++{ ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *) dev->dev_private; ++ unsigned long irqflags; ++ ++ if (!dev_priv->dsr_enable) ++ return; ++ ++ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); ++ ++ mid_disable_pipe_event(dev_priv, pipe); ++ psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE); ++ ++ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); ++} ++ ++/* Called from drm generic code, passed a 'crtc', which ++ * we use as a pipe index ++ */ ++u32 psb_get_vblank_counter(struct drm_device *dev, int pipe) ++{ ++ uint32_t high_frame = PIPEAFRAMEHIGH; ++ uint32_t low_frame = PIPEAFRAMEPIXEL; ++ uint32_t pipeconf_reg = PIPEACONF; ++ uint32_t reg_val = 0; ++ uint32_t high1 = 0, high2 = 0, low = 0, count = 0; ++ ++ switch (pipe) { ++ case 0: ++ break; ++ case 1: ++ high_frame = PIPEBFRAMEHIGH; ++ low_frame = PIPEBFRAMEPIXEL; ++ pipeconf_reg = PIPEBCONF; ++ break; ++ case 2: ++ high_frame = PIPECFRAMEHIGH; ++ low_frame = PIPECFRAMEPIXEL; ++ pipeconf_reg = PIPECCONF; ++ break; ++ default: ++ dev_err(dev->dev, "%s, invalid pipe.\n", __func__); ++ return 0; ++ } ++ ++ if (!gma_power_begin(dev, false)) ++ return 0; ++ ++ reg_val = REG_READ(pipeconf_reg); ++ ++ if (!(reg_val & PIPEACONF_ENABLE)) { ++ dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n", ++ pipe); ++ goto psb_get_vblank_counter_exit; ++ } ++ ++ /* ++ * High & low register fields aren't synchronized, so make sure ++ * we get a low value that's stable across two reads of the high ++ * register. ++ */ ++ do { ++ high1 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> ++ PIPE_FRAME_HIGH_SHIFT); ++ low = ((REG_READ(low_frame) & PIPE_FRAME_LOW_MASK) >> ++ PIPE_FRAME_LOW_SHIFT); ++ high2 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> ++ PIPE_FRAME_HIGH_SHIFT); ++ } while (high1 != high2); ++ ++ count = (high1 << 8) | low; ++ ++psb_get_vblank_counter_exit: ++ ++ gma_power_end(dev); ++ ++ return count; ++} ++ +diff --git a/drivers/gpu/drm/gma500/psb_irq.h b/drivers/gpu/drm/gma500/psb_irq.h +new file mode 100644 +index 0000000..603045b +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_irq.h +@@ -0,0 +1,47 @@ ++/************************************************************************** ++ * Copyright (c) 2009-2011, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: ++ * Benjamin Defnet ++ * Rajesh Poornachandran ++ * ++ **************************************************************************/ ++ ++#ifndef _SYSIRQ_H_ ++#define _SYSIRQ_H_ ++ ++#include ++ ++bool sysirq_init(struct drm_device *dev); ++void sysirq_uninit(struct drm_device *dev); ++ ++void psb_irq_preinstall(struct drm_device *dev); ++int psb_irq_postinstall(struct drm_device *dev); ++void psb_irq_uninstall(struct drm_device *dev); ++irqreturn_t psb_irq_handler(DRM_IRQ_ARGS); ++ ++int psb_irq_enable_dpst(struct drm_device *dev); ++int psb_irq_disable_dpst(struct drm_device *dev); ++void psb_irq_turn_on_dpst(struct drm_device *dev); ++void psb_irq_turn_off_dpst(struct drm_device *dev); ++int psb_enable_vblank(struct drm_device *dev, int pipe); ++void psb_disable_vblank(struct drm_device *dev, int pipe); ++u32 psb_get_vblank_counter(struct drm_device *dev, int pipe); ++ ++int mdfld_enable_te(struct drm_device *dev, int pipe); ++void mdfld_disable_te(struct drm_device *dev, int pipe); ++#endif /* _SYSIRQ_H_ */ +diff --git a/drivers/gpu/drm/gma500/psb_lid.c b/drivers/gpu/drm/gma500/psb_lid.c +new file mode 100644 +index 0000000..b867aab +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_lid.c +@@ -0,0 +1,88 @@ ++/************************************************************************** ++ * Copyright (c) 2007, Intel Corporation. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Authors: Thomas Hellstrom ++ **************************************************************************/ ++ ++#include ++#include "psb_drv.h" ++#include "psb_reg.h" ++#include "psb_intel_reg.h" ++#include ++ ++static void psb_lid_timer_func(unsigned long data) ++{ ++ struct drm_psb_private * dev_priv = (struct drm_psb_private *)data; ++ struct drm_device *dev = (struct drm_device *)dev_priv->dev; ++ struct timer_list *lid_timer = &dev_priv->lid_timer; ++ unsigned long irq_flags; ++ u32 *lid_state = dev_priv->lid_state; ++ u32 pp_status; ++ ++ if (readl(lid_state) == dev_priv->lid_last_state) ++ goto lid_timer_schedule; ++ ++ if ((readl(lid_state)) & 0x01) { ++ /*lid state is open*/ ++ REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON); ++ do { ++ pp_status = REG_READ(PP_STATUS); ++ } while ((pp_status & PP_ON) == 0); ++ ++ /*FIXME: should be backlight level before*/ ++ psb_intel_lvds_set_brightness(dev, 100); ++ } else { ++ psb_intel_lvds_set_brightness(dev, 0); ++ ++ REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON); ++ do { ++ pp_status = REG_READ(PP_STATUS); ++ } while ((pp_status & PP_ON) == 0); ++ } ++ dev_priv->lid_last_state = readl(lid_state); ++ ++lid_timer_schedule: ++ spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); ++ if (!timer_pending(lid_timer)) { ++ lid_timer->expires = jiffies + PSB_LID_DELAY; ++ add_timer(lid_timer); ++ } ++ spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); ++} ++ ++void psb_lid_timer_init(struct drm_psb_private *dev_priv) ++{ ++ struct timer_list *lid_timer = &dev_priv->lid_timer; ++ unsigned long irq_flags; ++ ++ spin_lock_init(&dev_priv->lid_lock); ++ spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); ++ ++ init_timer(lid_timer); ++ ++ lid_timer->data = (unsigned long)dev_priv; ++ lid_timer->function = psb_lid_timer_func; ++ lid_timer->expires = jiffies + PSB_LID_DELAY; ++ ++ add_timer(lid_timer); ++ spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); ++} ++ ++void psb_lid_timer_takedown(struct drm_psb_private *dev_priv) ++{ ++ del_timer_sync(&dev_priv->lid_timer); ++} ++ +diff --git a/drivers/gpu/drm/gma500/psb_reg.h b/drivers/gpu/drm/gma500/psb_reg.h +new file mode 100644 +index 0000000..b81c7c1 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/psb_reg.h +@@ -0,0 +1,582 @@ ++/************************************************************************** ++ * ++ * Copyright (c) (2005-2007) Imagination Technologies Limited. ++ * Copyright (c) 2007, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.. ++ * ++ **************************************************************************/ ++ ++#ifndef _PSB_REG_H_ ++#define _PSB_REG_H_ ++ ++#define PSB_CR_CLKGATECTL 0x0000 ++#define _PSB_C_CLKGATECTL_AUTO_MAN_REG (1 << 24) ++#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT (20) ++#define _PSB_C_CLKGATECTL_USE_CLKG_MASK (0x3 << 20) ++#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT (16) ++#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK (0x3 << 16) ++#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT (12) ++#define _PSB_C_CLKGATECTL_TA_CLKG_MASK (0x3 << 12) ++#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT (8) ++#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK (0x3 << 8) ++#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT (4) ++#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK (0x3 << 4) ++#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT (0) ++#define _PSB_C_CLKGATECTL_2D_CLKG_MASK (0x3 << 0) ++#define _PSB_C_CLKGATECTL_CLKG_ENABLED (0) ++#define _PSB_C_CLKGATECTL_CLKG_DISABLED (1) ++#define _PSB_C_CLKGATECTL_CLKG_AUTO (2) ++ ++#define PSB_CR_CORE_ID 0x0010 ++#define _PSB_CC_ID_ID_SHIFT (16) ++#define _PSB_CC_ID_ID_MASK (0xFFFF << 16) ++#define _PSB_CC_ID_CONFIG_SHIFT (0) ++#define _PSB_CC_ID_CONFIG_MASK (0xFFFF << 0) ++ ++#define PSB_CR_CORE_REVISION 0x0014 ++#define _PSB_CC_REVISION_DESIGNER_SHIFT (24) ++#define _PSB_CC_REVISION_DESIGNER_MASK (0xFF << 24) ++#define _PSB_CC_REVISION_MAJOR_SHIFT (16) ++#define _PSB_CC_REVISION_MAJOR_MASK (0xFF << 16) ++#define _PSB_CC_REVISION_MINOR_SHIFT (8) ++#define _PSB_CC_REVISION_MINOR_MASK (0xFF << 8) ++#define _PSB_CC_REVISION_MAINTENANCE_SHIFT (0) ++#define _PSB_CC_REVISION_MAINTENANCE_MASK (0xFF << 0) ++ ++#define PSB_CR_DESIGNER_REV_FIELD1 0x0018 ++ ++#define PSB_CR_SOFT_RESET 0x0080 ++#define _PSB_CS_RESET_TSP_RESET (1 << 6) ++#define _PSB_CS_RESET_ISP_RESET (1 << 5) ++#define _PSB_CS_RESET_USE_RESET (1 << 4) ++#define _PSB_CS_RESET_TA_RESET (1 << 3) ++#define _PSB_CS_RESET_DPM_RESET (1 << 2) ++#define _PSB_CS_RESET_TWOD_RESET (1 << 1) ++#define _PSB_CS_RESET_BIF_RESET (1 << 0) ++ ++#define PSB_CR_DESIGNER_REV_FIELD2 0x001C ++ ++#define PSB_CR_EVENT_HOST_ENABLE2 0x0110 ++ ++#define PSB_CR_EVENT_STATUS2 0x0118 ++ ++#define PSB_CR_EVENT_HOST_CLEAR2 0x0114 ++#define _PSB_CE2_BIF_REQUESTER_FAULT (1 << 4) ++ ++#define PSB_CR_EVENT_STATUS 0x012C ++ ++#define PSB_CR_EVENT_HOST_ENABLE 0x0130 ++ ++#define PSB_CR_EVENT_HOST_CLEAR 0x0134 ++#define _PSB_CE_MASTER_INTERRUPT (1 << 31) ++#define _PSB_CE_TA_DPM_FAULT (1 << 28) ++#define _PSB_CE_TWOD_COMPLETE (1 << 27) ++#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS (1 << 25) ++#define _PSB_CE_DPM_TA_MEM_FREE (1 << 24) ++#define _PSB_CE_PIXELBE_END_RENDER (1 << 18) ++#define _PSB_CE_SW_EVENT (1 << 14) ++#define _PSB_CE_TA_FINISHED (1 << 13) ++#define _PSB_CE_TA_TERMINATE (1 << 12) ++#define _PSB_CE_DPM_REACHED_MEM_THRESH (1 << 3) ++#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL (1 << 2) ++#define _PSB_CE_DPM_OUT_OF_MEMORY_MT (1 << 1) ++#define _PSB_CE_DPM_3D_MEM_FREE (1 << 0) ++ ++ ++#define PSB_USE_OFFSET_MASK 0x0007FFFF ++#define PSB_USE_OFFSET_SIZE (PSB_USE_OFFSET_MASK + 1) ++#define PSB_CR_USE_CODE_BASE0 0x0A0C ++#define PSB_CR_USE_CODE_BASE1 0x0A10 ++#define PSB_CR_USE_CODE_BASE2 0x0A14 ++#define PSB_CR_USE_CODE_BASE3 0x0A18 ++#define PSB_CR_USE_CODE_BASE4 0x0A1C ++#define PSB_CR_USE_CODE_BASE5 0x0A20 ++#define PSB_CR_USE_CODE_BASE6 0x0A24 ++#define PSB_CR_USE_CODE_BASE7 0x0A28 ++#define PSB_CR_USE_CODE_BASE8 0x0A2C ++#define PSB_CR_USE_CODE_BASE9 0x0A30 ++#define PSB_CR_USE_CODE_BASE10 0x0A34 ++#define PSB_CR_USE_CODE_BASE11 0x0A38 ++#define PSB_CR_USE_CODE_BASE12 0x0A3C ++#define PSB_CR_USE_CODE_BASE13 0x0A40 ++#define PSB_CR_USE_CODE_BASE14 0x0A44 ++#define PSB_CR_USE_CODE_BASE15 0x0A48 ++#define PSB_CR_USE_CODE_BASE(_i) (0x0A0C + ((_i) << 2)) ++#define _PSB_CUC_BASE_DM_SHIFT (25) ++#define _PSB_CUC_BASE_DM_MASK (0x3 << 25) ++#define _PSB_CUC_BASE_ADDR_SHIFT (0) /* 1024-bit aligned address? */ ++#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT (7) ++#define _PSB_CUC_BASE_ADDR_MASK (0x1FFFFFF << 0) ++#define _PSB_CUC_DM_VERTEX (0) ++#define _PSB_CUC_DM_PIXEL (1) ++#define _PSB_CUC_DM_RESERVED (2) ++#define _PSB_CUC_DM_EDM (3) ++ ++#define PSB_CR_PDS_EXEC_BASE 0x0AB8 ++#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT (20) /* 1MB aligned address */ ++#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT (20) ++ ++#define PSB_CR_EVENT_KICKER 0x0AC4 ++#define _PSB_CE_KICKER_ADDRESS_SHIFT (4) /* 128-bit aligned address */ ++ ++#define PSB_CR_EVENT_KICK 0x0AC8 ++#define _PSB_CE_KICK_NOW (1 << 0) ++ ++#define PSB_CR_BIF_DIR_LIST_BASE1 0x0C38 ++ ++#define PSB_CR_BIF_CTRL 0x0C00 ++#define _PSB_CB_CTRL_CLEAR_FAULT (1 << 4) ++#define _PSB_CB_CTRL_INVALDC (1 << 3) ++#define _PSB_CB_CTRL_FLUSH (1 << 2) ++ ++#define PSB_CR_BIF_INT_STAT 0x0C04 ++ ++#define PSB_CR_BIF_FAULT 0x0C08 ++#define _PSB_CBI_STAT_PF_N_RW (1 << 14) ++#define _PSB_CBI_STAT_FAULT_SHIFT (0) ++#define _PSB_CBI_STAT_FAULT_MASK (0x3FFF << 0) ++#define _PSB_CBI_STAT_FAULT_CACHE (1 << 1) ++#define _PSB_CBI_STAT_FAULT_TA (1 << 2) ++#define _PSB_CBI_STAT_FAULT_VDM (1 << 3) ++#define _PSB_CBI_STAT_FAULT_2D (1 << 4) ++#define _PSB_CBI_STAT_FAULT_PBE (1 << 5) ++#define _PSB_CBI_STAT_FAULT_TSP (1 << 6) ++#define _PSB_CBI_STAT_FAULT_ISP (1 << 7) ++#define _PSB_CBI_STAT_FAULT_USSEPDS (1 << 8) ++#define _PSB_CBI_STAT_FAULT_HOST (1 << 9) ++ ++#define PSB_CR_BIF_BANK0 0x0C78 ++#define PSB_CR_BIF_BANK1 0x0C7C ++#define PSB_CR_BIF_DIR_LIST_BASE0 0x0C84 ++#define PSB_CR_BIF_TWOD_REQ_BASE 0x0C88 ++#define PSB_CR_BIF_3D_REQ_BASE 0x0CAC ++ ++#define PSB_CR_2D_SOCIF 0x0E18 ++#define _PSB_C2_SOCIF_FREESPACE_SHIFT (0) ++#define _PSB_C2_SOCIF_FREESPACE_MASK (0xFF << 0) ++#define _PSB_C2_SOCIF_EMPTY (0x80 << 0) ++ ++#define PSB_CR_2D_BLIT_STATUS 0x0E04 ++#define _PSB_C2B_STATUS_BUSY (1 << 24) ++#define _PSB_C2B_STATUS_COMPLETE_SHIFT (0) ++#define _PSB_C2B_STATUS_COMPLETE_MASK (0xFFFFFF << 0) ++ ++/* ++ * 2D defs. ++ */ ++ ++/* ++ * 2D Slave Port Data : Block Header's Object Type ++ */ ++ ++#define PSB_2D_CLIP_BH (0x00000000) ++#define PSB_2D_PAT_BH (0x10000000) ++#define PSB_2D_CTRL_BH (0x20000000) ++#define PSB_2D_SRC_OFF_BH (0x30000000) ++#define PSB_2D_MASK_OFF_BH (0x40000000) ++#define PSB_2D_RESERVED1_BH (0x50000000) ++#define PSB_2D_RESERVED2_BH (0x60000000) ++#define PSB_2D_FENCE_BH (0x70000000) ++#define PSB_2D_BLIT_BH (0x80000000) ++#define PSB_2D_SRC_SURF_BH (0x90000000) ++#define PSB_2D_DST_SURF_BH (0xA0000000) ++#define PSB_2D_PAT_SURF_BH (0xB0000000) ++#define PSB_2D_SRC_PAL_BH (0xC0000000) ++#define PSB_2D_PAT_PAL_BH (0xD0000000) ++#define PSB_2D_MASK_SURF_BH (0xE0000000) ++#define PSB_2D_FLUSH_BH (0xF0000000) ++ ++/* ++ * Clip Definition block (PSB_2D_CLIP_BH) ++ */ ++#define PSB_2D_CLIPCOUNT_MAX (1) ++#define PSB_2D_CLIPCOUNT_MASK (0x00000000) ++#define PSB_2D_CLIPCOUNT_CLRMASK (0xFFFFFFFF) ++#define PSB_2D_CLIPCOUNT_SHIFT (0) ++/* clip rectangle min & max */ ++#define PSB_2D_CLIP_XMAX_MASK (0x00FFF000) ++#define PSB_2D_CLIP_XMAX_CLRMASK (0xFF000FFF) ++#define PSB_2D_CLIP_XMAX_SHIFT (12) ++#define PSB_2D_CLIP_XMIN_MASK (0x00000FFF) ++#define PSB_2D_CLIP_XMIN_CLRMASK (0x00FFF000) ++#define PSB_2D_CLIP_XMIN_SHIFT (0) ++/* clip rectangle offset */ ++#define PSB_2D_CLIP_YMAX_MASK (0x00FFF000) ++#define PSB_2D_CLIP_YMAX_CLRMASK (0xFF000FFF) ++#define PSB_2D_CLIP_YMAX_SHIFT (12) ++#define PSB_2D_CLIP_YMIN_MASK (0x00000FFF) ++#define PSB_2D_CLIP_YMIN_CLRMASK (0x00FFF000) ++#define PSB_2D_CLIP_YMIN_SHIFT (0) ++ ++/* ++ * Pattern Control (PSB_2D_PAT_BH) ++ */ ++#define PSB_2D_PAT_HEIGHT_MASK (0x0000001F) ++#define PSB_2D_PAT_HEIGHT_SHIFT (0) ++#define PSB_2D_PAT_WIDTH_MASK (0x000003E0) ++#define PSB_2D_PAT_WIDTH_SHIFT (5) ++#define PSB_2D_PAT_YSTART_MASK (0x00007C00) ++#define PSB_2D_PAT_YSTART_SHIFT (10) ++#define PSB_2D_PAT_XSTART_MASK (0x000F8000) ++#define PSB_2D_PAT_XSTART_SHIFT (15) ++ ++/* ++ * 2D Control block (PSB_2D_CTRL_BH) ++ */ ++/* Present Flags */ ++#define PSB_2D_SRCCK_CTRL (0x00000001) ++#define PSB_2D_DSTCK_CTRL (0x00000002) ++#define PSB_2D_ALPHA_CTRL (0x00000004) ++/* Colour Key Colour (SRC/DST)*/ ++#define PSB_2D_CK_COL_MASK (0xFFFFFFFF) ++#define PSB_2D_CK_COL_CLRMASK (0x00000000) ++#define PSB_2D_CK_COL_SHIFT (0) ++/* Colour Key Mask (SRC/DST)*/ ++#define PSB_2D_CK_MASK_MASK (0xFFFFFFFF) ++#define PSB_2D_CK_MASK_CLRMASK (0x00000000) ++#define PSB_2D_CK_MASK_SHIFT (0) ++/* Alpha Control (Alpha/RGB)*/ ++#define PSB_2D_GBLALPHA_MASK (0x000FF000) ++#define PSB_2D_GBLALPHA_CLRMASK (0xFFF00FFF) ++#define PSB_2D_GBLALPHA_SHIFT (12) ++#define PSB_2D_SRCALPHA_OP_MASK (0x00700000) ++#define PSB_2D_SRCALPHA_OP_CLRMASK (0xFF8FFFFF) ++#define PSB_2D_SRCALPHA_OP_SHIFT (20) ++#define PSB_2D_SRCALPHA_OP_ONE (0x00000000) ++#define PSB_2D_SRCALPHA_OP_SRC (0x00100000) ++#define PSB_2D_SRCALPHA_OP_DST (0x00200000) ++#define PSB_2D_SRCALPHA_OP_SG (0x00300000) ++#define PSB_2D_SRCALPHA_OP_DG (0x00400000) ++#define PSB_2D_SRCALPHA_OP_GBL (0x00500000) ++#define PSB_2D_SRCALPHA_OP_ZERO (0x00600000) ++#define PSB_2D_SRCALPHA_INVERT (0x00800000) ++#define PSB_2D_SRCALPHA_INVERT_CLR (0xFF7FFFFF) ++#define PSB_2D_DSTALPHA_OP_MASK (0x07000000) ++#define PSB_2D_DSTALPHA_OP_CLRMASK (0xF8FFFFFF) ++#define PSB_2D_DSTALPHA_OP_SHIFT (24) ++#define PSB_2D_DSTALPHA_OP_ONE (0x00000000) ++#define PSB_2D_DSTALPHA_OP_SRC (0x01000000) ++#define PSB_2D_DSTALPHA_OP_DST (0x02000000) ++#define PSB_2D_DSTALPHA_OP_SG (0x03000000) ++#define PSB_2D_DSTALPHA_OP_DG (0x04000000) ++#define PSB_2D_DSTALPHA_OP_GBL (0x05000000) ++#define PSB_2D_DSTALPHA_OP_ZERO (0x06000000) ++#define PSB_2D_DSTALPHA_INVERT (0x08000000) ++#define PSB_2D_DSTALPHA_INVERT_CLR (0xF7FFFFFF) ++ ++#define PSB_2D_PRE_MULTIPLICATION_ENABLE (0x10000000) ++#define PSB_2D_PRE_MULTIPLICATION_CLRMASK (0xEFFFFFFF) ++#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE (0x20000000) ++#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK (0xDFFFFFFF) ++ ++/* ++ *Source Offset (PSB_2D_SRC_OFF_BH) ++ */ ++#define PSB_2D_SRCOFF_XSTART_MASK ((0x00000FFF) << 12) ++#define PSB_2D_SRCOFF_XSTART_SHIFT (12) ++#define PSB_2D_SRCOFF_YSTART_MASK (0x00000FFF) ++#define PSB_2D_SRCOFF_YSTART_SHIFT (0) ++ ++/* ++ * Mask Offset (PSB_2D_MASK_OFF_BH) ++ */ ++#define PSB_2D_MASKOFF_XSTART_MASK ((0x00000FFF) << 12) ++#define PSB_2D_MASKOFF_XSTART_SHIFT (12) ++#define PSB_2D_MASKOFF_YSTART_MASK (0x00000FFF) ++#define PSB_2D_MASKOFF_YSTART_SHIFT (0) ++ ++/* ++ * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored ++ */ ++ ++/* ++ *Blit Rectangle (PSB_2D_BLIT_BH) ++ */ ++ ++#define PSB_2D_ROT_MASK (3 << 25) ++#define PSB_2D_ROT_CLRMASK (~PSB_2D_ROT_MASK) ++#define PSB_2D_ROT_NONE (0 << 25) ++#define PSB_2D_ROT_90DEGS (1 << 25) ++#define PSB_2D_ROT_180DEGS (2 << 25) ++#define PSB_2D_ROT_270DEGS (3 << 25) ++ ++#define PSB_2D_COPYORDER_MASK (3 << 23) ++#define PSB_2D_COPYORDER_CLRMASK (~PSB_2D_COPYORDER_MASK) ++#define PSB_2D_COPYORDER_TL2BR (0 << 23) ++#define PSB_2D_COPYORDER_BR2TL (1 << 23) ++#define PSB_2D_COPYORDER_TR2BL (2 << 23) ++#define PSB_2D_COPYORDER_BL2TR (3 << 23) ++ ++#define PSB_2D_DSTCK_CLRMASK (0xFF9FFFFF) ++#define PSB_2D_DSTCK_DISABLE (0x00000000) ++#define PSB_2D_DSTCK_PASS (0x00200000) ++#define PSB_2D_DSTCK_REJECT (0x00400000) ++ ++#define PSB_2D_SRCCK_CLRMASK (0xFFE7FFFF) ++#define PSB_2D_SRCCK_DISABLE (0x00000000) ++#define PSB_2D_SRCCK_PASS (0x00080000) ++#define PSB_2D_SRCCK_REJECT (0x00100000) ++ ++#define PSB_2D_CLIP_ENABLE (0x00040000) ++ ++#define PSB_2D_ALPHA_ENABLE (0x00020000) ++ ++#define PSB_2D_PAT_CLRMASK (0xFFFEFFFF) ++#define PSB_2D_PAT_MASK (0x00010000) ++#define PSB_2D_USE_PAT (0x00010000) ++#define PSB_2D_USE_FILL (0x00000000) ++/* ++ * Tungsten Graphics note on rop codes: If rop A and rop B are ++ * identical, the mask surface will not be read and need not be ++ * set up. ++ */ ++ ++#define PSB_2D_ROP3B_MASK (0x0000FF00) ++#define PSB_2D_ROP3B_CLRMASK (0xFFFF00FF) ++#define PSB_2D_ROP3B_SHIFT (8) ++/* rop code A */ ++#define PSB_2D_ROP3A_MASK (0x000000FF) ++#define PSB_2D_ROP3A_CLRMASK (0xFFFFFF00) ++#define PSB_2D_ROP3A_SHIFT (0) ++ ++#define PSB_2D_ROP4_MASK (0x0000FFFF) ++/* ++ * DWORD0: (Only pass if Pattern control == Use Fill Colour) ++ * Fill Colour RGBA8888 ++ */ ++#define PSB_2D_FILLCOLOUR_MASK (0xFFFFFFFF) ++#define PSB_2D_FILLCOLOUR_SHIFT (0) ++/* ++ * DWORD1: (Always Present) ++ * X Start (Dest) ++ * Y Start (Dest) ++ */ ++#define PSB_2D_DST_XSTART_MASK (0x00FFF000) ++#define PSB_2D_DST_XSTART_CLRMASK (0xFF000FFF) ++#define PSB_2D_DST_XSTART_SHIFT (12) ++#define PSB_2D_DST_YSTART_MASK (0x00000FFF) ++#define PSB_2D_DST_YSTART_CLRMASK (0xFFFFF000) ++#define PSB_2D_DST_YSTART_SHIFT (0) ++/* ++ * DWORD2: (Always Present) ++ * X Size (Dest) ++ * Y Size (Dest) ++ */ ++#define PSB_2D_DST_XSIZE_MASK (0x00FFF000) ++#define PSB_2D_DST_XSIZE_CLRMASK (0xFF000FFF) ++#define PSB_2D_DST_XSIZE_SHIFT (12) ++#define PSB_2D_DST_YSIZE_MASK (0x00000FFF) ++#define PSB_2D_DST_YSIZE_CLRMASK (0xFFFFF000) ++#define PSB_2D_DST_YSIZE_SHIFT (0) ++ ++/* ++ * Source Surface (PSB_2D_SRC_SURF_BH) ++ */ ++/* ++ * WORD 0 ++ */ ++ ++#define PSB_2D_SRC_FORMAT_MASK (0x00078000) ++#define PSB_2D_SRC_1_PAL (0x00000000) ++#define PSB_2D_SRC_2_PAL (0x00008000) ++#define PSB_2D_SRC_4_PAL (0x00010000) ++#define PSB_2D_SRC_8_PAL (0x00018000) ++#define PSB_2D_SRC_8_ALPHA (0x00020000) ++#define PSB_2D_SRC_4_ALPHA (0x00028000) ++#define PSB_2D_SRC_332RGB (0x00030000) ++#define PSB_2D_SRC_4444ARGB (0x00038000) ++#define PSB_2D_SRC_555RGB (0x00040000) ++#define PSB_2D_SRC_1555ARGB (0x00048000) ++#define PSB_2D_SRC_565RGB (0x00050000) ++#define PSB_2D_SRC_0888ARGB (0x00058000) ++#define PSB_2D_SRC_8888ARGB (0x00060000) ++#define PSB_2D_SRC_8888UYVY (0x00068000) ++#define PSB_2D_SRC_RESERVED (0x00070000) ++#define PSB_2D_SRC_1555ARGB_LOOKUP (0x00078000) ++ ++ ++#define PSB_2D_SRC_STRIDE_MASK (0x00007FFF) ++#define PSB_2D_SRC_STRIDE_CLRMASK (0xFFFF8000) ++#define PSB_2D_SRC_STRIDE_SHIFT (0) ++/* ++ * WORD 1 - Base Address ++ */ ++#define PSB_2D_SRC_ADDR_MASK (0x0FFFFFFC) ++#define PSB_2D_SRC_ADDR_CLRMASK (0x00000003) ++#define PSB_2D_SRC_ADDR_SHIFT (2) ++#define PSB_2D_SRC_ADDR_ALIGNSHIFT (2) ++ ++/* ++ * Pattern Surface (PSB_2D_PAT_SURF_BH) ++ */ ++/* ++ * WORD 0 ++ */ ++ ++#define PSB_2D_PAT_FORMAT_MASK (0x00078000) ++#define PSB_2D_PAT_1_PAL (0x00000000) ++#define PSB_2D_PAT_2_PAL (0x00008000) ++#define PSB_2D_PAT_4_PAL (0x00010000) ++#define PSB_2D_PAT_8_PAL (0x00018000) ++#define PSB_2D_PAT_8_ALPHA (0x00020000) ++#define PSB_2D_PAT_4_ALPHA (0x00028000) ++#define PSB_2D_PAT_332RGB (0x00030000) ++#define PSB_2D_PAT_4444ARGB (0x00038000) ++#define PSB_2D_PAT_555RGB (0x00040000) ++#define PSB_2D_PAT_1555ARGB (0x00048000) ++#define PSB_2D_PAT_565RGB (0x00050000) ++#define PSB_2D_PAT_0888ARGB (0x00058000) ++#define PSB_2D_PAT_8888ARGB (0x00060000) ++ ++#define PSB_2D_PAT_STRIDE_MASK (0x00007FFF) ++#define PSB_2D_PAT_STRIDE_CLRMASK (0xFFFF8000) ++#define PSB_2D_PAT_STRIDE_SHIFT (0) ++/* ++ * WORD 1 - Base Address ++ */ ++#define PSB_2D_PAT_ADDR_MASK (0x0FFFFFFC) ++#define PSB_2D_PAT_ADDR_CLRMASK (0x00000003) ++#define PSB_2D_PAT_ADDR_SHIFT (2) ++#define PSB_2D_PAT_ADDR_ALIGNSHIFT (2) ++ ++/* ++ * Destination Surface (PSB_2D_DST_SURF_BH) ++ */ ++/* ++ * WORD 0 ++ */ ++ ++#define PSB_2D_DST_FORMAT_MASK (0x00078000) ++#define PSB_2D_DST_332RGB (0x00030000) ++#define PSB_2D_DST_4444ARGB (0x00038000) ++#define PSB_2D_DST_555RGB (0x00040000) ++#define PSB_2D_DST_1555ARGB (0x00048000) ++#define PSB_2D_DST_565RGB (0x00050000) ++#define PSB_2D_DST_0888ARGB (0x00058000) ++#define PSB_2D_DST_8888ARGB (0x00060000) ++#define PSB_2D_DST_8888AYUV (0x00070000) ++ ++#define PSB_2D_DST_STRIDE_MASK (0x00007FFF) ++#define PSB_2D_DST_STRIDE_CLRMASK (0xFFFF8000) ++#define PSB_2D_DST_STRIDE_SHIFT (0) ++/* ++ * WORD 1 - Base Address ++ */ ++#define PSB_2D_DST_ADDR_MASK (0x0FFFFFFC) ++#define PSB_2D_DST_ADDR_CLRMASK (0x00000003) ++#define PSB_2D_DST_ADDR_SHIFT (2) ++#define PSB_2D_DST_ADDR_ALIGNSHIFT (2) ++ ++/* ++ * Mask Surface (PSB_2D_MASK_SURF_BH) ++ */ ++/* ++ * WORD 0 ++ */ ++#define PSB_2D_MASK_STRIDE_MASK (0x00007FFF) ++#define PSB_2D_MASK_STRIDE_CLRMASK (0xFFFF8000) ++#define PSB_2D_MASK_STRIDE_SHIFT (0) ++/* ++ * WORD 1 - Base Address ++ */ ++#define PSB_2D_MASK_ADDR_MASK (0x0FFFFFFC) ++#define PSB_2D_MASK_ADDR_CLRMASK (0x00000003) ++#define PSB_2D_MASK_ADDR_SHIFT (2) ++#define PSB_2D_MASK_ADDR_ALIGNSHIFT (2) ++ ++/* ++ * Source Palette (PSB_2D_SRC_PAL_BH) ++ */ ++ ++#define PSB_2D_SRCPAL_ADDR_SHIFT (0) ++#define PSB_2D_SRCPAL_ADDR_CLRMASK (0xF0000007) ++#define PSB_2D_SRCPAL_ADDR_MASK (0x0FFFFFF8) ++#define PSB_2D_SRCPAL_BYTEALIGN (1024) ++ ++/* ++ * Pattern Palette (PSB_2D_PAT_PAL_BH) ++ */ ++ ++#define PSB_2D_PATPAL_ADDR_SHIFT (0) ++#define PSB_2D_PATPAL_ADDR_CLRMASK (0xF0000007) ++#define PSB_2D_PATPAL_ADDR_MASK (0x0FFFFFF8) ++#define PSB_2D_PATPAL_BYTEALIGN (1024) ++ ++/* ++ * Rop3 Codes (2 LS bytes) ++ */ ++ ++#define PSB_2D_ROP3_SRCCOPY (0xCCCC) ++#define PSB_2D_ROP3_PATCOPY (0xF0F0) ++#define PSB_2D_ROP3_WHITENESS (0xFFFF) ++#define PSB_2D_ROP3_BLACKNESS (0x0000) ++#define PSB_2D_ROP3_SRC (0xCC) ++#define PSB_2D_ROP3_PAT (0xF0) ++#define PSB_2D_ROP3_DST (0xAA) ++ ++/* ++ * Sizes. ++ */ ++ ++#define PSB_SCENE_HW_COOKIE_SIZE 16 ++#define PSB_TA_MEM_HW_COOKIE_SIZE 16 ++ ++/* ++ * Scene stuff. ++ */ ++ ++#define PSB_NUM_HW_SCENES 2 ++ ++/* ++ * Scheduler completion actions. ++ */ ++ ++#define PSB_RASTER_BLOCK 0 ++#define PSB_RASTER 1 ++#define PSB_RETURN 2 ++#define PSB_TA 3 ++ ++/* Power management */ ++#define PSB_PUNIT_PORT 0x04 ++#define PSB_OSPMBA 0x78 ++#define PSB_APMBA 0x7a ++#define PSB_APM_CMD 0x0 ++#define PSB_APM_STS 0x04 ++#define PSB_PWRGT_VID_ENC_MASK 0x30 ++#define PSB_PWRGT_VID_DEC_MASK 0xc ++#define PSB_PWRGT_GL3_MASK 0xc0 ++ ++#define PSB_PM_SSC 0x20 ++#define PSB_PM_SSS 0x30 ++#define PSB_PWRGT_DISPLAY_MASK 0xc /*on a different BA than video/gfx*/ ++#define MDFLD_PWRGT_DISPLAY_A_CNTR 0x0000000c ++#define MDFLD_PWRGT_DISPLAY_B_CNTR 0x0000c000 ++#define MDFLD_PWRGT_DISPLAY_C_CNTR 0x00030000 ++#define MDFLD_PWRGT_DISP_MIPI_CNTR 0x000c0000 ++#define MDFLD_PWRGT_DISPLAY_CNTR (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR) /* 0x000fc00c */ ++/* Display SSS register bits are different in A0 vs. B0 */ ++#define PSB_PWRGT_GFX_MASK 0x3 ++#define MDFLD_PWRGT_DISPLAY_A_STS 0x000000c0 ++#define MDFLD_PWRGT_DISPLAY_B_STS 0x00000300 ++#define MDFLD_PWRGT_DISPLAY_C_STS 0x00000c00 ++#define PSB_PWRGT_GFX_MASK_B0 0xc3 ++#define MDFLD_PWRGT_DISPLAY_A_STS_B0 0x0000000c ++#define MDFLD_PWRGT_DISPLAY_B_STS_B0 0x0000c000 ++#define MDFLD_PWRGT_DISPLAY_C_STS_B0 0x00030000 ++#define MDFLD_PWRGT_DISP_MIPI_STS 0x000c0000 ++#define MDFLD_PWRGT_DISPLAY_STS_A0 (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */ ++#define MDFLD_PWRGT_DISPLAY_STS_B0 (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */ ++#endif +diff --git a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c +new file mode 100644 +index 0000000..4a07ab5 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c +@@ -0,0 +1,829 @@ ++/* ++ * Copyright © 2011 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ */ ++ ++#include "mdfld_dsi_dpi.h" ++#include "mdfld_output.h" ++#include "mdfld_dsi_pkg_sender.h" ++#include "tc35876x-dsi-lvds.h" ++#include ++#include ++#include ++#include ++ ++static struct i2c_client *tc35876x_client; ++static struct i2c_client *cmi_lcd_i2c_client; ++ ++#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end)) ++#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end)) ++ ++/* DSI D-PHY Layer Registers */ ++#define D0W_DPHYCONTTX 0x0004 ++#define CLW_DPHYCONTRX 0x0020 ++#define D0W_DPHYCONTRX 0x0024 ++#define D1W_DPHYCONTRX 0x0028 ++#define D2W_DPHYCONTRX 0x002C ++#define D3W_DPHYCONTRX 0x0030 ++#define COM_DPHYCONTRX 0x0038 ++#define CLW_CNTRL 0x0040 ++#define D0W_CNTRL 0x0044 ++#define D1W_CNTRL 0x0048 ++#define D2W_CNTRL 0x004C ++#define D3W_CNTRL 0x0050 ++#define DFTMODE_CNTRL 0x0054 ++ ++/* DSI PPI Layer Registers */ ++#define PPI_STARTPPI 0x0104 ++#define PPI_BUSYPPI 0x0108 ++#define PPI_LINEINITCNT 0x0110 ++#define PPI_LPTXTIMECNT 0x0114 ++#define PPI_LANEENABLE 0x0134 ++#define PPI_TX_RX_TA 0x013C ++#define PPI_CLS_ATMR 0x0140 ++#define PPI_D0S_ATMR 0x0144 ++#define PPI_D1S_ATMR 0x0148 ++#define PPI_D2S_ATMR 0x014C ++#define PPI_D3S_ATMR 0x0150 ++#define PPI_D0S_CLRSIPOCOUNT 0x0164 ++#define PPI_D1S_CLRSIPOCOUNT 0x0168 ++#define PPI_D2S_CLRSIPOCOUNT 0x016C ++#define PPI_D3S_CLRSIPOCOUNT 0x0170 ++#define CLS_PRE 0x0180 ++#define D0S_PRE 0x0184 ++#define D1S_PRE 0x0188 ++#define D2S_PRE 0x018C ++#define D3S_PRE 0x0190 ++#define CLS_PREP 0x01A0 ++#define D0S_PREP 0x01A4 ++#define D1S_PREP 0x01A8 ++#define D2S_PREP 0x01AC ++#define D3S_PREP 0x01B0 ++#define CLS_ZERO 0x01C0 ++#define D0S_ZERO 0x01C4 ++#define D1S_ZERO 0x01C8 ++#define D2S_ZERO 0x01CC ++#define D3S_ZERO 0x01D0 ++#define PPI_CLRFLG 0x01E0 ++#define PPI_CLRSIPO 0x01E4 ++#define HSTIMEOUT 0x01F0 ++#define HSTIMEOUTENABLE 0x01F4 ++ ++/* DSI Protocol Layer Registers */ ++#define DSI_STARTDSI 0x0204 ++#define DSI_BUSYDSI 0x0208 ++#define DSI_LANEENABLE 0x0210 ++#define DSI_LANESTATUS0 0x0214 ++#define DSI_LANESTATUS1 0x0218 ++#define DSI_INTSTATUS 0x0220 ++#define DSI_INTMASK 0x0224 ++#define DSI_INTCLR 0x0228 ++#define DSI_LPTXTO 0x0230 ++ ++/* DSI General Registers */ ++#define DSIERRCNT 0x0300 ++ ++/* DSI Application Layer Registers */ ++#define APLCTRL 0x0400 ++#define RDPKTLN 0x0404 ++ ++/* Video Path Registers */ ++#define VPCTRL 0x0450 ++#define HTIM1 0x0454 ++#define HTIM2 0x0458 ++#define VTIM1 0x045C ++#define VTIM2 0x0460 ++#define VFUEN 0x0464 ++ ++/* LVDS Registers */ ++#define LVMX0003 0x0480 ++#define LVMX0407 0x0484 ++#define LVMX0811 0x0488 ++#define LVMX1215 0x048C ++#define LVMX1619 0x0490 ++#define LVMX2023 0x0494 ++#define LVMX2427 0x0498 ++#define LVCFG 0x049C ++#define LVPHY0 0x04A0 ++#define LVPHY1 0x04A4 ++ ++/* System Registers */ ++#define SYSSTAT 0x0500 ++#define SYSRST 0x0504 ++ ++/* GPIO Registers */ ++/*#define GPIOC 0x0520*/ ++#define GPIOO 0x0524 ++#define GPIOI 0x0528 ++ ++/* I2C Registers */ ++#define I2CTIMCTRL 0x0540 ++#define I2CMADDR 0x0544 ++#define WDATAQ 0x0548 ++#define RDATAQ 0x054C ++ ++/* Chip/Rev Registers */ ++#define IDREG 0x0580 ++ ++/* Debug Registers */ ++#define DEBUG00 0x05A0 ++#define DEBUG01 0x05A4 ++ ++/* Panel CABC registers */ ++#define PANEL_PWM_CONTROL 0x90 ++#define PANEL_FREQ_DIVIDER_HI 0x91 ++#define PANEL_FREQ_DIVIDER_LO 0x92 ++#define PANEL_DUTY_CONTROL 0x93 ++#define PANEL_MODIFY_RGB 0x94 ++#define PANEL_FRAMERATE_CONTROL 0x96 ++#define PANEL_PWM_MIN 0x97 ++#define PANEL_PWM_REF 0x98 ++#define PANEL_PWM_MAX 0x99 ++#define PANEL_ALLOW_DISTORT 0x9A ++#define PANEL_BYPASS_PWMI 0x9B ++ ++/* Panel color management registers */ ++#define PANEL_CM_ENABLE 0x700 ++#define PANEL_CM_HUE 0x701 ++#define PANEL_CM_SATURATION 0x702 ++#define PANEL_CM_INTENSITY 0x703 ++#define PANEL_CM_BRIGHTNESS 0x704 ++#define PANEL_CM_CE_ENABLE 0x705 ++#define PANEL_CM_PEAK_EN 0x710 ++#define PANEL_CM_GAIN 0x711 ++#define PANEL_CM_HUETABLE_START 0x730 ++#define PANEL_CM_HUETABLE_END 0x747 /* inclusive */ ++ ++/* Input muxing for registers LVMX0003...LVMX2427 */ ++enum { ++ INPUT_R0, /* 0 */ ++ INPUT_R1, ++ INPUT_R2, ++ INPUT_R3, ++ INPUT_R4, ++ INPUT_R5, ++ INPUT_R6, ++ INPUT_R7, ++ INPUT_G0, /* 8 */ ++ INPUT_G1, ++ INPUT_G2, ++ INPUT_G3, ++ INPUT_G4, ++ INPUT_G5, ++ INPUT_G6, ++ INPUT_G7, ++ INPUT_B0, /* 16 */ ++ INPUT_B1, ++ INPUT_B2, ++ INPUT_B3, ++ INPUT_B4, ++ INPUT_B5, ++ INPUT_B6, ++ INPUT_B7, ++ INPUT_HSYNC, /* 24 */ ++ INPUT_VSYNC, ++ INPUT_DE, ++ LOGIC_0, ++ /* 28...31 undefined */ ++}; ++ ++#define INPUT_MUX(lvmx03, lvmx02, lvmx01, lvmx00) \ ++ (FLD_VAL(lvmx03, 29, 24) | FLD_VAL(lvmx02, 20, 16) | \ ++ FLD_VAL(lvmx01, 12, 8) | FLD_VAL(lvmx00, 4, 0)) ++ ++/** ++ * tc35876x_regw - Write DSI-LVDS bridge register using I2C ++ * @client: struct i2c_client to use ++ * @reg: register address ++ * @value: value to write ++ * ++ * Returns 0 on success, or a negative error value. ++ */ ++static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value) ++{ ++ int r; ++ u8 tx_data[] = { ++ /* NOTE: Register address big-endian, data little-endian. */ ++ (reg >> 8) & 0xff, ++ reg & 0xff, ++ value & 0xff, ++ (value >> 8) & 0xff, ++ (value >> 16) & 0xff, ++ (value >> 24) & 0xff, ++ }; ++ struct i2c_msg msgs[] = { ++ { ++ .addr = client->addr, ++ .flags = 0, ++ .buf = tx_data, ++ .len = ARRAY_SIZE(tx_data), ++ }, ++ }; ++ ++ r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); ++ if (r < 0) { ++ dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x error %d\n", ++ __func__, reg, value, r); ++ return r; ++ } ++ ++ if (r < ARRAY_SIZE(msgs)) { ++ dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x msgs %d\n", ++ __func__, reg, value, r); ++ return -EAGAIN; ++ } ++ ++ dev_dbg(&client->dev, "%s: reg 0x%04x val 0x%08x\n", ++ __func__, reg, value); ++ ++ return 0; ++} ++ ++/** ++ * tc35876x_regr - Read DSI-LVDS bridge register using I2C ++ * @client: struct i2c_client to use ++ * @reg: register address ++ * @value: pointer for storing the value ++ * ++ * Returns 0 on success, or a negative error value. ++ */ ++static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value) ++{ ++ int r; ++ u8 tx_data[] = { ++ (reg >> 8) & 0xff, ++ reg & 0xff, ++ }; ++ u8 rx_data[4]; ++ struct i2c_msg msgs[] = { ++ { ++ .addr = client->addr, ++ .flags = 0, ++ .buf = tx_data, ++ .len = ARRAY_SIZE(tx_data), ++ }, ++ { ++ .addr = client->addr, ++ .flags = I2C_M_RD, ++ .buf = rx_data, ++ .len = ARRAY_SIZE(rx_data), ++ }, ++ }; ++ ++ r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); ++ if (r < 0) { ++ dev_err(&client->dev, "%s: reg 0x%04x error %d\n", __func__, ++ reg, r); ++ return r; ++ } ++ ++ if (r < ARRAY_SIZE(msgs)) { ++ dev_err(&client->dev, "%s: reg 0x%04x msgs %d\n", __func__, ++ reg, r); ++ return -EAGAIN; ++ } ++ ++ *value = rx_data[0] << 24 | rx_data[1] << 16 | ++ rx_data[2] << 8 | rx_data[3]; ++ ++ dev_dbg(&client->dev, "%s: reg 0x%04x value 0x%08x\n", __func__, ++ reg, *value); ++ ++ return 0; ++} ++ ++void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state) ++{ ++ struct tc35876x_platform_data *pdata; ++ ++ if (WARN(!tc35876x_client, "%s called before probe", __func__)) ++ return; ++ ++ dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state); ++ ++ pdata = dev_get_platdata(&tc35876x_client->dev); ++ ++ if (pdata->gpio_bridge_reset == -1) ++ return; ++ ++ if (state) { ++ gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0); ++ mdelay(10); ++ } else { ++ /* Pull MIPI Bridge reset pin to Low */ ++ gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0); ++ mdelay(20); ++ /* Pull MIPI Bridge reset pin to High */ ++ gpio_set_value_cansleep(pdata->gpio_bridge_reset, 1); ++ mdelay(40); ++ } ++} ++ ++void tc35876x_configure_lvds_bridge(struct drm_device *dev) ++{ ++ struct i2c_client *i2c = tc35876x_client; ++ u32 ppi_lptxtimecnt; ++ u32 txtagocnt; ++ u32 txtasurecnt; ++ u32 id; ++ ++ if (WARN(!tc35876x_client, "%s called before probe", __func__)) ++ return; ++ ++ dev_dbg(&tc35876x_client->dev, "%s\n", __func__); ++ ++ if (!tc35876x_regr(i2c, IDREG, &id)) ++ dev_info(&tc35876x_client->dev, "tc35876x ID 0x%08x\n", id); ++ else ++ dev_err(&tc35876x_client->dev, "Cannot read ID\n"); ++ ++ ppi_lptxtimecnt = 4; ++ txtagocnt = (5 * ppi_lptxtimecnt - 3) / 4; ++ txtasurecnt = 3 * ppi_lptxtimecnt / 2; ++ tc35876x_regw(i2c, PPI_TX_RX_TA, FLD_VAL(txtagocnt, 26, 16) | ++ FLD_VAL(txtasurecnt, 10, 0)); ++ tc35876x_regw(i2c, PPI_LPTXTIMECNT, FLD_VAL(ppi_lptxtimecnt, 10, 0)); ++ ++ tc35876x_regw(i2c, PPI_D0S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0)); ++ tc35876x_regw(i2c, PPI_D1S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0)); ++ tc35876x_regw(i2c, PPI_D2S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0)); ++ tc35876x_regw(i2c, PPI_D3S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0)); ++ ++ /* Enabling MIPI & PPI lanes, Enable 4 lanes */ ++ tc35876x_regw(i2c, PPI_LANEENABLE, ++ BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); ++ tc35876x_regw(i2c, DSI_LANEENABLE, ++ BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); ++ tc35876x_regw(i2c, PPI_STARTPPI, BIT(0)); ++ tc35876x_regw(i2c, DSI_STARTDSI, BIT(0)); ++ ++ /* Setting LVDS output frequency */ ++ tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) | ++ FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0)); /* 0x00048006 */ ++ ++ /* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */ ++ tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5)); ++ ++ /* Horizontal back porch and horizontal pulse width. 0x00280028 */ ++ tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0)); ++ ++ /* Horizontal front porch and horizontal active video size. 0x00500500*/ ++ tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0)); ++ ++ /* Vertical back porch and vertical sync pulse width. 0x000e000a */ ++ tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0)); ++ ++ /* Vertical front porch and vertical display size. 0x000e0320 */ ++ tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0)); ++ ++ /* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */ ++ tc35876x_regw(i2c, VFUEN, BIT(0)); ++ ++ /* Soft reset LCD controller. */ ++ tc35876x_regw(i2c, SYSRST, BIT(2)); ++ ++ /* LVDS-TX input muxing */ ++ tc35876x_regw(i2c, LVMX0003, ++ INPUT_MUX(INPUT_R5, INPUT_R4, INPUT_R3, INPUT_R2)); ++ tc35876x_regw(i2c, LVMX0407, ++ INPUT_MUX(INPUT_G2, INPUT_R7, INPUT_R1, INPUT_R6)); ++ tc35876x_regw(i2c, LVMX0811, ++ INPUT_MUX(INPUT_G1, INPUT_G0, INPUT_G4, INPUT_G3)); ++ tc35876x_regw(i2c, LVMX1215, ++ INPUT_MUX(INPUT_B2, INPUT_G7, INPUT_G6, INPUT_G5)); ++ tc35876x_regw(i2c, LVMX1619, ++ INPUT_MUX(INPUT_B4, INPUT_B3, INPUT_B1, INPUT_B0)); ++ tc35876x_regw(i2c, LVMX2023, ++ INPUT_MUX(LOGIC_0, INPUT_B7, INPUT_B6, INPUT_B5)); ++ tc35876x_regw(i2c, LVMX2427, ++ INPUT_MUX(INPUT_R0, INPUT_DE, INPUT_VSYNC, INPUT_HSYNC)); ++ ++ /* Enable LVDS transmitter. */ ++ tc35876x_regw(i2c, LVCFG, BIT(0)); ++ ++ /* Clear notifications. Don't write reserved bits. Was write 0xffffffff ++ * to 0x0288, must be in error?! */ ++ tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0)); ++} ++ ++#define GPIOPWMCTRL 0x38F ++#define PWM0CLKDIV0 0x62 /* low byte */ ++#define PWM0CLKDIV1 0x61 /* high byte */ ++ ++#define SYSTEMCLK 19200000UL /* 19.2 MHz */ ++#define PWM_FREQUENCY 9600 /* Hz */ ++ ++/* f = baseclk / (clkdiv + 1) => clkdiv = (baseclk - f) / f */ ++static inline u16 calc_clkdiv(unsigned long baseclk, unsigned int f) ++{ ++ return (baseclk - f) / f; ++} ++ ++static void tc35876x_brightness_init(struct drm_device *dev) ++{ ++ int ret; ++ u8 pwmctrl; ++ u16 clkdiv; ++ ++ /* Make sure the PWM reference is the 19.2 MHz system clock. Read first ++ * instead of setting directly to catch potential conflicts between PWM ++ * users. */ ++ ret = intel_scu_ipc_ioread8(GPIOPWMCTRL, &pwmctrl); ++ if (ret || pwmctrl != 0x01) { ++ if (ret) ++ dev_err(&dev->pdev->dev, "GPIOPWMCTRL read failed\n"); ++ else ++ dev_warn(&dev->pdev->dev, "GPIOPWMCTRL was not set to system clock (pwmctrl = 0x%02x)\n", pwmctrl); ++ ++ ret = intel_scu_ipc_iowrite8(GPIOPWMCTRL, 0x01); ++ if (ret) ++ dev_err(&dev->pdev->dev, "GPIOPWMCTRL set failed\n"); ++ } ++ ++ clkdiv = calc_clkdiv(SYSTEMCLK, PWM_FREQUENCY); ++ ++ ret = intel_scu_ipc_iowrite8(PWM0CLKDIV1, (clkdiv >> 8) & 0xff); ++ if (!ret) ++ ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, clkdiv & 0xff); ++ ++ if (ret) ++ dev_err(&dev->pdev->dev, "PWM0CLKDIV set failed\n"); ++ else ++ dev_dbg(&dev->pdev->dev, "PWM0CLKDIV set to 0x%04x (%d Hz)\n", ++ clkdiv, PWM_FREQUENCY); ++} ++ ++#define PWM0DUTYCYCLE 0x67 ++ ++void tc35876x_brightness_control(struct drm_device *dev, int level) ++{ ++ int ret; ++ u8 duty_val; ++ u8 panel_duty_val; ++ ++ level = clamp(level, 0, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL); ++ ++ /* PWM duty cycle 0x00...0x63 corresponds to 0...99% */ ++ duty_val = level * 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL; ++ ++ /* I won't pretend to understand this formula. The panel spec is quite ++ * bad engrish. ++ */ ++ panel_duty_val = (2 * level - 100) * 0xA9 / ++ MDFLD_DSI_BRIGHTNESS_MAX_LEVEL + 0x56; ++ ++ ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val); ++ if (ret) ++ dev_err(&tc35876x_client->dev, "%s: ipc write fail\n", ++ __func__); ++ ++ if (cmi_lcd_i2c_client) { ++ ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client, ++ PANEL_PWM_MAX, panel_duty_val); ++ if (ret < 0) ++ dev_err(&cmi_lcd_i2c_client->dev, "%s: i2c write failed\n", ++ __func__); ++ } ++} ++ ++void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev) ++{ ++ struct tc35876x_platform_data *pdata; ++ ++ if (WARN(!tc35876x_client, "%s called before probe", __func__)) ++ return; ++ ++ dev_dbg(&tc35876x_client->dev, "%s\n", __func__); ++ ++ pdata = dev_get_platdata(&tc35876x_client->dev); ++ ++ if (pdata->gpio_panel_bl_en != -1) ++ gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 0); ++ ++ if (pdata->gpio_panel_vadd != -1) ++ gpio_set_value_cansleep(pdata->gpio_panel_vadd, 0); ++} ++ ++void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev) ++{ ++ struct tc35876x_platform_data *pdata; ++ struct drm_psb_private *dev_priv = dev->dev_private; ++ ++ if (WARN(!tc35876x_client, "%s called before probe", __func__)) ++ return; ++ ++ dev_dbg(&tc35876x_client->dev, "%s\n", __func__); ++ ++ pdata = dev_get_platdata(&tc35876x_client->dev); ++ ++ if (pdata->gpio_panel_vadd != -1) { ++ gpio_set_value_cansleep(pdata->gpio_panel_vadd, 1); ++ msleep(260); ++ } ++ ++ if (cmi_lcd_i2c_client) { ++ int ret; ++ dev_dbg(&cmi_lcd_i2c_client->dev, "setting TCON\n"); ++ /* Bit 4 is average_saving. Setting it to 1, the brightness is ++ * referenced to the average of the frame content. 0 means ++ * reference to the maximum of frame contents. Bits 3:0 are ++ * allow_distort. When set to a nonzero value, all color values ++ * between 255-allow_distort*2 and 255 are mapped to the ++ * 255-allow_distort*2 value. ++ */ ++ ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client, ++ PANEL_ALLOW_DISTORT, 0x10); ++ if (ret < 0) ++ dev_err(&cmi_lcd_i2c_client->dev, ++ "i2c write failed (%d)\n", ret); ++ ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client, ++ PANEL_BYPASS_PWMI, 0); ++ if (ret < 0) ++ dev_err(&cmi_lcd_i2c_client->dev, ++ "i2c write failed (%d)\n", ret); ++ /* Set minimum brightness value - this is tunable */ ++ ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client, ++ PANEL_PWM_MIN, 0x35); ++ if (ret < 0) ++ dev_err(&cmi_lcd_i2c_client->dev, ++ "i2c write failed (%d)\n", ret); ++ } ++ ++ if (pdata->gpio_panel_bl_en != -1) ++ gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 1); ++ ++ tc35876x_brightness_control(dev, dev_priv->brightness_adjusted); ++} ++ ++static struct drm_display_mode *tc35876x_get_config_mode(struct drm_device *dev) ++{ ++ struct drm_display_mode *mode; ++ ++ dev_dbg(&dev->pdev->dev, "%s\n", __func__); ++ ++ mode = kzalloc(sizeof(*mode), GFP_KERNEL); ++ if (!mode) ++ return NULL; ++ ++ /* FIXME: do this properly. */ ++ mode->hdisplay = 1280; ++ mode->vdisplay = 800; ++ mode->hsync_start = 1360; ++ mode->hsync_end = 1400; ++ mode->htotal = 1440; ++ mode->vsync_start = 814; ++ mode->vsync_end = 824; ++ mode->vtotal = 838; ++ mode->clock = 33324 << 1; ++ ++ dev_info(&dev->pdev->dev, "hdisplay(w) = %d\n", mode->hdisplay); ++ dev_info(&dev->pdev->dev, "vdisplay(h) = %d\n", mode->vdisplay); ++ dev_info(&dev->pdev->dev, "HSS = %d\n", mode->hsync_start); ++ dev_info(&dev->pdev->dev, "HSE = %d\n", mode->hsync_end); ++ dev_info(&dev->pdev->dev, "htotal = %d\n", mode->htotal); ++ dev_info(&dev->pdev->dev, "VSS = %d\n", mode->vsync_start); ++ dev_info(&dev->pdev->dev, "VSE = %d\n", mode->vsync_end); ++ dev_info(&dev->pdev->dev, "vtotal = %d\n", mode->vtotal); ++ dev_info(&dev->pdev->dev, "clock = %d\n", mode->clock); ++ ++ drm_mode_set_name(mode); ++ drm_mode_set_crtcinfo(mode, 0); ++ ++ mode->type |= DRM_MODE_TYPE_PREFERRED; ++ ++ return mode; ++} ++ ++/* DV1 Active area 216.96 x 135.6 mm */ ++#define DV1_PANEL_WIDTH 217 ++#define DV1_PANEL_HEIGHT 136 ++ ++static int tc35876x_get_panel_info(struct drm_device *dev, int pipe, ++ struct panel_info *pi) ++{ ++ if (!dev || !pi) ++ return -EINVAL; ++ ++ pi->width_mm = DV1_PANEL_WIDTH; ++ pi->height_mm = DV1_PANEL_HEIGHT; ++ ++ return 0; ++} ++ ++static int tc35876x_bridge_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct tc35876x_platform_data *pdata; ++ ++ dev_info(&client->dev, "%s\n", __func__); ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { ++ dev_err(&client->dev, "%s: i2c_check_functionality() failed\n", ++ __func__); ++ return -ENODEV; ++ } ++ ++ pdata = dev_get_platdata(&client->dev); ++ if (!pdata) { ++ dev_err(&client->dev, "%s: no platform data\n", __func__); ++ return -ENODEV; ++ } ++ ++ if (pdata->gpio_bridge_reset != -1) { ++ gpio_request(pdata->gpio_bridge_reset, "tc35876x bridge reset"); ++ gpio_direction_output(pdata->gpio_bridge_reset, 0); ++ } ++ ++ if (pdata->gpio_panel_bl_en != -1) { ++ gpio_request(pdata->gpio_panel_bl_en, "tc35876x panel bl en"); ++ gpio_direction_output(pdata->gpio_panel_bl_en, 0); ++ } ++ ++ if (pdata->gpio_panel_vadd != -1) { ++ gpio_request(pdata->gpio_panel_vadd, "tc35876x panel vadd"); ++ gpio_direction_output(pdata->gpio_panel_vadd, 0); ++ } ++ ++ tc35876x_client = client; ++ ++ return 0; ++} ++ ++static int tc35876x_bridge_remove(struct i2c_client *client) ++{ ++ struct tc35876x_platform_data *pdata = dev_get_platdata(&client->dev); ++ ++ dev_dbg(&client->dev, "%s\n", __func__); ++ ++ if (pdata->gpio_bridge_reset != -1) ++ gpio_free(pdata->gpio_bridge_reset); ++ ++ if (pdata->gpio_panel_bl_en != -1) ++ gpio_free(pdata->gpio_panel_bl_en); ++ ++ if (pdata->gpio_panel_vadd != -1) ++ gpio_free(pdata->gpio_panel_vadd); ++ ++ tc35876x_client = NULL; ++ ++ return 0; ++} ++ ++static const struct i2c_device_id tc35876x_bridge_id[] = { ++ { "i2c_disp_brig", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, tc35876x_bridge_id); ++ ++static struct i2c_driver tc35876x_bridge_i2c_driver = { ++ .driver = { ++ .name = "i2c_disp_brig", ++ }, ++ .id_table = tc35876x_bridge_id, ++ .probe = tc35876x_bridge_probe, ++ .remove = __devexit_p(tc35876x_bridge_remove), ++}; ++ ++/* LCD panel I2C */ ++static int cmi_lcd_i2c_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ dev_info(&client->dev, "%s\n", __func__); ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { ++ dev_err(&client->dev, "%s: i2c_check_functionality() failed\n", ++ __func__); ++ return -ENODEV; ++ } ++ ++ cmi_lcd_i2c_client = client; ++ ++ return 0; ++} ++ ++static int cmi_lcd_i2c_remove(struct i2c_client *client) ++{ ++ dev_dbg(&client->dev, "%s\n", __func__); ++ ++ cmi_lcd_i2c_client = NULL; ++ ++ return 0; ++} ++ ++static const struct i2c_device_id cmi_lcd_i2c_id[] = { ++ { "cmi-lcd", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, cmi_lcd_i2c_id); ++ ++static struct i2c_driver cmi_lcd_i2c_driver = { ++ .driver = { ++ .name = "cmi-lcd", ++ }, ++ .id_table = cmi_lcd_i2c_id, ++ .probe = cmi_lcd_i2c_probe, ++ .remove = __devexit_p(cmi_lcd_i2c_remove), ++}; ++ ++/* HACK to create I2C device while it's not created by platform code */ ++#define CMI_LCD_I2C_ADAPTER 2 ++#define CMI_LCD_I2C_ADDR 0x60 ++ ++static int cmi_lcd_hack_create_device(void) ++{ ++ struct i2c_adapter *adapter; ++ struct i2c_client *client; ++ struct i2c_board_info info = { ++ .type = "cmi-lcd", ++ .addr = CMI_LCD_I2C_ADDR, ++ }; ++ ++ pr_debug("%s\n", __func__); ++ ++ adapter = i2c_get_adapter(CMI_LCD_I2C_ADAPTER); ++ if (!adapter) { ++ pr_err("%s: i2c_get_adapter(%d) failed\n", __func__, ++ CMI_LCD_I2C_ADAPTER); ++ return -EINVAL; ++ } ++ ++ client = i2c_new_device(adapter, &info); ++ if (!client) { ++ pr_err("%s: i2c_new_device() failed\n", __func__); ++ i2c_put_adapter(adapter); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct drm_encoder_helper_funcs tc35876x_encoder_helper_funcs = { ++ .dpms = mdfld_dsi_dpi_dpms, ++ .mode_fixup = mdfld_dsi_dpi_mode_fixup, ++ .prepare = mdfld_dsi_dpi_prepare, ++ .mode_set = mdfld_dsi_dpi_mode_set, ++ .commit = mdfld_dsi_dpi_commit, ++}; ++ ++static const struct drm_encoder_funcs tc35876x_encoder_funcs = { ++ .destroy = drm_encoder_cleanup, ++}; ++ ++const struct panel_funcs mdfld_tc35876x_funcs = { ++ .encoder_funcs = &tc35876x_encoder_funcs, ++ .encoder_helper_funcs = &tc35876x_encoder_helper_funcs, ++ .get_config_mode = tc35876x_get_config_mode, ++ .get_panel_info = tc35876x_get_panel_info, ++}; ++ ++void tc35876x_init(struct drm_device *dev) ++{ ++ int r; ++ ++ dev_dbg(&dev->pdev->dev, "%s\n", __func__); ++ ++ cmi_lcd_hack_create_device(); ++ ++ r = i2c_add_driver(&cmi_lcd_i2c_driver); ++ if (r < 0) ++ dev_err(&dev->pdev->dev, ++ "%s: i2c_add_driver() for %s failed (%d)\n", ++ __func__, cmi_lcd_i2c_driver.driver.name, r); ++ ++ r = i2c_add_driver(&tc35876x_bridge_i2c_driver); ++ if (r < 0) ++ dev_err(&dev->pdev->dev, ++ "%s: i2c_add_driver() for %s failed (%d)\n", ++ __func__, tc35876x_bridge_i2c_driver.driver.name, r); ++ ++ tc35876x_brightness_init(dev); ++} ++ ++void tc35876x_exit(void) ++{ ++ pr_debug("%s\n", __func__); ++ ++ i2c_del_driver(&tc35876x_bridge_i2c_driver); ++ ++ if (cmi_lcd_i2c_client) ++ i2c_del_driver(&cmi_lcd_i2c_driver); ++} +diff --git a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h +new file mode 100644 +index 0000000..b14b7f9 +--- /dev/null ++++ b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h +@@ -0,0 +1,38 @@ ++/* ++ * Copyright © 2011 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ */ ++ ++#ifndef __MDFLD_DSI_LVDS_BRIDGE_H__ ++#define __MDFLD_DSI_LVDS_BRIDGE_H__ ++ ++void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state); ++void tc35876x_configure_lvds_bridge(struct drm_device *dev); ++void tc35876x_brightness_control(struct drm_device *dev, int level); ++void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev); ++void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev); ++void tc35876x_init(struct drm_device *dev); ++void tc35876x_exit(void); ++ ++extern const struct panel_funcs mdfld_tc35876x_funcs; ++ ++#endif /*__MDFLD_DSI_LVDS_BRIDGE_H__*/ +diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c +index 07d55df..d3f2e87 100644 +--- a/drivers/gpu/drm/i2c/ch7006_drv.c ++++ b/drivers/gpu/drm/i2c/ch7006_drv.c +@@ -252,10 +252,7 @@ static int ch7006_encoder_create_resources(struct drm_encoder *encoder, + + drm_mode_create_tv_properties(dev, NUM_TV_NORMS, ch7006_tv_norm_names); + +- priv->scale_property = drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "scale", 2); +- priv->scale_property->values[0] = 0; +- priv->scale_property->values[1] = 2; ++ priv->scale_property = drm_property_create_range(dev, 0, "scale", 0, 2); + + drm_connector_attach_property(connector, conf->tv_select_subconnector_property, + priv->select_subconnector); +diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c +index 8f371e8..2c8a60c 100644 +--- a/drivers/gpu/drm/i810/i810_dma.c ++++ b/drivers/gpu/drm/i810/i810_dma.c +@@ -99,7 +99,6 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) + buf_priv = buf->dev_private; + + vma->vm_flags |= (VM_IO | VM_DONTCOPY); +- vma->vm_file = filp; + + buf_priv->currently_mapped = I810_BUF_MAPPED; + +@@ -222,8 +221,6 @@ static int i810_dma_cleanup(struct drm_device *dev) + pci_free_consistent(dev->pdev, PAGE_SIZE, + dev_priv->hw_status_page, + dev_priv->dma_status_page); +- /* Need to rewrite hardware status page */ +- I810_WRITE(0x02080, 0x1ffff000); + } + kfree(dev->dev_private); + dev->dev_private = NULL; +@@ -1210,6 +1207,8 @@ int i810_driver_load(struct drm_device *dev, unsigned long flags) + dev->types[8] = _DRM_STAT_SECONDARY; + dev->types[9] = _DRM_STAT_DMA; + ++ pci_set_master(dev->pdev); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c +index d4266bd..ec12f7d 100644 +--- a/drivers/gpu/drm/i810/i810_drv.c ++++ b/drivers/gpu/drm/i810/i810_drv.c +@@ -43,6 +43,17 @@ static struct pci_device_id pciidlist[] = { + i810_PCI_IDS + }; + ++static const struct file_operations i810_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .mmap = drm_mmap, ++ .poll = drm_poll, ++ .fasync = drm_fasync, ++ .llseek = noop_llseek, ++}; ++ + static struct drm_driver driver = { + .driver_features = + DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | +@@ -55,17 +66,7 @@ static struct drm_driver driver = { + .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked, + .dma_quiescent = i810_driver_dma_quiescent, + .ioctls = i810_ioctls, +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = drm_ioctl, +- .mmap = drm_mmap, +- .poll = drm_poll, +- .fasync = drm_fasync, +- .llseek = noop_llseek, +- }, +- ++ .fops = &i810_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, +diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile +index 0ae6a7c..ce7fc77 100644 +--- a/drivers/gpu/drm/i915/Makefile ++++ b/drivers/gpu/drm/i915/Makefile +@@ -3,7 +3,7 @@ + # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. + + ccflags-y := -Iinclude/drm +-i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ ++i915-y := i915_drv.o i915_dma.o i915_irq.o \ + i915_debugfs.o \ + i915_suspend.o \ + i915_gem.o \ +@@ -28,6 +28,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ + intel_dvo.o \ + intel_ringbuffer.o \ + intel_overlay.o \ ++ intel_sprite.o \ + intel_opregion.o \ + dvo_ch7xxx.o \ + dvo_ch7017.o \ +diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c +index 9b4e5c6..29f8107 100644 +--- a/drivers/gpu/drm/i915/i915_debugfs.c ++++ b/drivers/gpu/drm/i915/i915_debugfs.c +@@ -84,6 +84,7 @@ static int i915_capabilities(struct seq_file *m, void *data) + B(supports_tv); + B(has_bsd_ring); + B(has_blt_ring); ++ B(has_llc); + #undef B + + return 0; +@@ -122,11 +123,11 @@ static const char *cache_level_str(int type) + static void + describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) + { +- seq_printf(m, "%pK: %s%s %8zd %04x %04x %d %d%s%s%s", ++ seq_printf(m, "%pK: %s%s %8zdKiB %04x %04x %d %d%s%s%s", + &obj->base, + get_pin_flag(obj), + get_tiling_flag(obj), +- obj->base.size, ++ obj->base.size / 1024, + obj->base.read_domains, + obj->base.write_domain, + obj->last_rendering_seqno, +@@ -564,45 +565,6 @@ static int i915_hws_info(struct seq_file *m, void *data) + return 0; + } + +-static void i915_dump_object(struct seq_file *m, +- struct io_mapping *mapping, +- struct drm_i915_gem_object *obj) +-{ +- int page, page_count, i; +- +- page_count = obj->base.size / PAGE_SIZE; +- for (page = 0; page < page_count; page++) { +- u32 *mem = io_mapping_map_wc(mapping, +- obj->gtt_offset + page * PAGE_SIZE); +- for (i = 0; i < PAGE_SIZE; i += 4) +- seq_printf(m, "%08x : %08x\n", i, mem[i / 4]); +- io_mapping_unmap(mem); +- } +-} +- +-static int i915_batchbuffer_info(struct seq_file *m, void *data) +-{ +- struct drm_info_node *node = (struct drm_info_node *) m->private; +- struct drm_device *dev = node->minor->dev; +- drm_i915_private_t *dev_priv = dev->dev_private; +- struct drm_i915_gem_object *obj; +- int ret; +- +- ret = mutex_lock_interruptible(&dev->struct_mutex); +- if (ret) +- return ret; +- +- list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) { +- if (obj->base.read_domains & I915_GEM_DOMAIN_COMMAND) { +- seq_printf(m, "--- gtt_offset = 0x%08x\n", obj->gtt_offset); +- i915_dump_object(m, dev_priv->mm.gtt_mapping, obj); +- } +- } +- +- mutex_unlock(&dev->struct_mutex); +- return 0; +-} +- + static int i915_ringbuffer_data(struct seq_file *m, void *data) + { + struct drm_info_node *node = (struct drm_info_node *) m->private; +@@ -654,7 +616,7 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data) + seq_printf(m, " Size : %08x\n", ring->size); + seq_printf(m, " Active : %08x\n", intel_ring_get_active_head(ring)); + seq_printf(m, " NOPID : %08x\n", I915_READ_NOPID(ring)); +- if (IS_GEN6(dev)) { ++ if (IS_GEN6(dev) || IS_GEN7(dev)) { + seq_printf(m, " Sync 0 : %08x\n", I915_READ_SYNC_0(ring)); + seq_printf(m, " Sync 1 : %08x\n", I915_READ_SYNC_1(ring)); + } +@@ -669,9 +631,9 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data) + static const char *ring_str(int ring) + { + switch (ring) { +- case RING_RENDER: return " render"; +- case RING_BSD: return " bsd"; +- case RING_BLT: return " blt"; ++ case RCS: return "render"; ++ case VCS: return "bsd"; ++ case BCS: return "blt"; + default: return ""; + } + } +@@ -714,7 +676,7 @@ static void print_error_buffers(struct seq_file *m, + seq_printf(m, "%s [%d]:\n", name, count); + + while (count--) { +- seq_printf(m, " %08x %8u %04x %04x %08x%s%s%s%s%s%s", ++ seq_printf(m, " %08x %8u %04x %04x %08x%s%s%s%s%s%s%s", + err->gtt_offset, + err->size, + err->read_domains, +@@ -724,6 +686,7 @@ static void print_error_buffers(struct seq_file *m, + tiling_flag(err->tiling), + dirty_flag(err->dirty), + purgeable_flag(err->purgeable), ++ err->ring != -1 ? " " : "", + ring_str(err->ring), + cache_level_str(err->cache_level)); + +@@ -737,6 +700,38 @@ static void print_error_buffers(struct seq_file *m, + } + } + ++static void i915_ring_error_state(struct seq_file *m, ++ struct drm_device *dev, ++ struct drm_i915_error_state *error, ++ unsigned ring) ++{ ++ seq_printf(m, "%s command stream:\n", ring_str(ring)); ++ seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]); ++ seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]); ++ seq_printf(m, " ACTHD: 0x%08x\n", error->acthd[ring]); ++ seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]); ++ seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]); ++ seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone[ring]); ++ if (ring == RCS && INTEL_INFO(dev)->gen >= 4) { ++ seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1); ++ seq_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr); ++ } ++ if (INTEL_INFO(dev)->gen >= 4) ++ seq_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]); ++ seq_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]); ++ if (INTEL_INFO(dev)->gen >= 6) { ++ seq_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]); ++ seq_printf(m, " FAULT_REG: 0x%08x\n", error->fault_reg[ring]); ++ seq_printf(m, " SYNC_0: 0x%08x\n", ++ error->semaphore_mboxes[ring][0]); ++ seq_printf(m, " SYNC_1: 0x%08x\n", ++ error->semaphore_mboxes[ring][1]); ++ } ++ seq_printf(m, " seqno: 0x%08x\n", error->seqno[ring]); ++ seq_printf(m, " ring->head: 0x%08x\n", error->cpu_ring_head[ring]); ++ seq_printf(m, " ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]); ++} ++ + static int i915_error_state(struct seq_file *m, void *unused) + { + struct drm_info_node *node = (struct drm_info_node *) m->private; +@@ -744,7 +739,7 @@ static int i915_error_state(struct seq_file *m, void *unused) + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_error_state *error; + unsigned long flags; +- int i, page, offset, elt; ++ int i, j, page, offset, elt; + + spin_lock_irqsave(&dev_priv->error_lock, flags); + if (!dev_priv->first_error) { +@@ -760,35 +755,20 @@ static int i915_error_state(struct seq_file *m, void *unused) + seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device); + seq_printf(m, "EIR: 0x%08x\n", error->eir); + seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); ++ ++ for (i = 0; i < dev_priv->num_fence_regs; i++) ++ seq_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); ++ + if (INTEL_INFO(dev)->gen >= 6) { + seq_printf(m, "ERROR: 0x%08x\n", error->error); +- seq_printf(m, "Blitter command stream:\n"); +- seq_printf(m, " ACTHD: 0x%08x\n", error->bcs_acthd); +- seq_printf(m, " IPEIR: 0x%08x\n", error->bcs_ipeir); +- seq_printf(m, " IPEHR: 0x%08x\n", error->bcs_ipehr); +- seq_printf(m, " INSTDONE: 0x%08x\n", error->bcs_instdone); +- seq_printf(m, " seqno: 0x%08x\n", error->bcs_seqno); +- seq_printf(m, "Video (BSD) command stream:\n"); +- seq_printf(m, " ACTHD: 0x%08x\n", error->vcs_acthd); +- seq_printf(m, " IPEIR: 0x%08x\n", error->vcs_ipeir); +- seq_printf(m, " IPEHR: 0x%08x\n", error->vcs_ipehr); +- seq_printf(m, " INSTDONE: 0x%08x\n", error->vcs_instdone); +- seq_printf(m, " seqno: 0x%08x\n", error->vcs_seqno); ++ seq_printf(m, "DONE_REG: 0x%08x\n", error->done_reg); + } +- seq_printf(m, "Render command stream:\n"); +- seq_printf(m, " ACTHD: 0x%08x\n", error->acthd); +- seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir); +- seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr); +- seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone); +- if (INTEL_INFO(dev)->gen >= 4) { +- seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1); +- seq_printf(m, " INSTPS: 0x%08x\n", error->instps); +- } +- seq_printf(m, " INSTPM: 0x%08x\n", error->instpm); +- seq_printf(m, " seqno: 0x%08x\n", error->seqno); + +- for (i = 0; i < dev_priv->num_fence_regs; i++) +- seq_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); ++ i915_ring_error_state(m, dev, error, RCS); ++ if (HAS_BLT(dev)) ++ i915_ring_error_state(m, dev, error, BCS); ++ if (HAS_BSD(dev)) ++ i915_ring_error_state(m, dev, error, VCS); + + if (error->active_bo) + print_error_buffers(m, "Active", +@@ -800,10 +780,10 @@ static int i915_error_state(struct seq_file *m, void *unused) + error->pinned_bo, + error->pinned_bo_count); + +- for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) { +- if (error->batchbuffer[i]) { +- struct drm_i915_error_object *obj = error->batchbuffer[i]; ++ for (i = 0; i < ARRAY_SIZE(error->ring); i++) { ++ struct drm_i915_error_object *obj; + ++ if ((obj = error->ring[i].batchbuffer)) { + seq_printf(m, "%s --- gtt_offset = 0x%08x\n", + dev_priv->ring[i].name, + obj->gtt_offset); +@@ -815,11 +795,20 @@ static int i915_error_state(struct seq_file *m, void *unused) + } + } + } +- } + +- for (i = 0; i < ARRAY_SIZE(error->ringbuffer); i++) { +- if (error->ringbuffer[i]) { +- struct drm_i915_error_object *obj = error->ringbuffer[i]; ++ if (error->ring[i].num_requests) { ++ seq_printf(m, "%s --- %d requests\n", ++ dev_priv->ring[i].name, ++ error->ring[i].num_requests); ++ for (j = 0; j < error->ring[i].num_requests; j++) { ++ seq_printf(m, " seqno 0x%08x, emitted %ld, tail 0x%08x\n", ++ error->ring[i].requests[j].seqno, ++ error->ring[i].requests[j].jiffies, ++ error->ring[i].requests[j].tail); ++ } ++ } ++ ++ if ((obj = error->ring[i].ringbuffer)) { + seq_printf(m, "%s --- ringbuffer = 0x%08x\n", + dev_priv->ring[i].name, + obj->gtt_offset); +@@ -1003,7 +992,7 @@ static int i915_inttoext_table(struct seq_file *m, void *unused) + return 0; + } + +-static int i915_drpc_info(struct seq_file *m, void *unused) ++static int ironlake_drpc_info(struct seq_file *m) + { + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; +@@ -1070,6 +1059,95 @@ static int i915_drpc_info(struct seq_file *m, void *unused) + return 0; + } + ++static int gen6_drpc_info(struct seq_file *m) ++{ ++ ++ struct drm_info_node *node = (struct drm_info_node *) m->private; ++ struct drm_device *dev = node->minor->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ u32 rpmodectl1, gt_core_status, rcctl1; ++ unsigned forcewake_count; ++ int count=0, ret; ++ ++ ++ ret = mutex_lock_interruptible(&dev->struct_mutex); ++ if (ret) ++ return ret; ++ ++ spin_lock_irq(&dev_priv->gt_lock); ++ forcewake_count = dev_priv->forcewake_count; ++ spin_unlock_irq(&dev_priv->gt_lock); ++ ++ if (forcewake_count) { ++ seq_printf(m, "RC information inaccurate because somebody " ++ "holds a forcewake reference \n"); ++ } else { ++ /* NB: we cannot use forcewake, else we read the wrong values */ ++ while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1)) ++ udelay(10); ++ seq_printf(m, "RC information accurate: %s\n", yesno(count < 51)); ++ } ++ ++ gt_core_status = readl(dev_priv->regs + GEN6_GT_CORE_STATUS); ++ trace_i915_reg_rw(false, GEN6_GT_CORE_STATUS, gt_core_status, 4); ++ ++ rpmodectl1 = I915_READ(GEN6_RP_CONTROL); ++ rcctl1 = I915_READ(GEN6_RC_CONTROL); ++ mutex_unlock(&dev->struct_mutex); ++ ++ seq_printf(m, "Video Turbo Mode: %s\n", ++ yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO)); ++ seq_printf(m, "HW control enabled: %s\n", ++ yesno(rpmodectl1 & GEN6_RP_ENABLE)); ++ seq_printf(m, "SW control enabled: %s\n", ++ yesno((rpmodectl1 & GEN6_RP_MEDIA_MODE_MASK) == ++ GEN6_RP_MEDIA_SW_MODE)); ++ seq_printf(m, "RC1e Enabled: %s\n", ++ yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE)); ++ seq_printf(m, "RC6 Enabled: %s\n", ++ yesno(rcctl1 & GEN6_RC_CTL_RC6_ENABLE)); ++ seq_printf(m, "Deep RC6 Enabled: %s\n", ++ yesno(rcctl1 & GEN6_RC_CTL_RC6p_ENABLE)); ++ seq_printf(m, "Deepest RC6 Enabled: %s\n", ++ yesno(rcctl1 & GEN6_RC_CTL_RC6pp_ENABLE)); ++ seq_printf(m, "Current RC state: "); ++ switch (gt_core_status & GEN6_RCn_MASK) { ++ case GEN6_RC0: ++ if (gt_core_status & GEN6_CORE_CPD_STATE_MASK) ++ seq_printf(m, "Core Power Down\n"); ++ else ++ seq_printf(m, "on\n"); ++ break; ++ case GEN6_RC3: ++ seq_printf(m, "RC3\n"); ++ break; ++ case GEN6_RC6: ++ seq_printf(m, "RC6\n"); ++ break; ++ case GEN6_RC7: ++ seq_printf(m, "RC7\n"); ++ break; ++ default: ++ seq_printf(m, "Unknown\n"); ++ break; ++ } ++ ++ seq_printf(m, "Core Power Down: %s\n", ++ yesno(gt_core_status & GEN6_CORE_CPD_STATE_MASK)); ++ return 0; ++} ++ ++static int i915_drpc_info(struct seq_file *m, void *unused) ++{ ++ struct drm_info_node *node = (struct drm_info_node *) m->private; ++ struct drm_device *dev = node->minor->dev; ++ ++ if (IS_GEN6(dev) || IS_GEN7(dev)) ++ return gen6_drpc_info(m); ++ else ++ return ironlake_drpc_info(m); ++} ++ + static int i915_fbc_status(struct seq_file *m, void *unused) + { + struct drm_info_node *node = (struct drm_info_node *) m->private; +@@ -1148,6 +1226,9 @@ static int i915_emon_status(struct seq_file *m, void *unused) + unsigned long temp, chipset, gfx; + int ret; + ++ if (!IS_GEN5(dev)) ++ return -ENODEV; ++ + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; +@@ -1327,9 +1408,108 @@ static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data) + return 0; + } + ++static const char *swizzle_string(unsigned swizzle) ++{ ++ switch(swizzle) { ++ case I915_BIT_6_SWIZZLE_NONE: ++ return "none"; ++ case I915_BIT_6_SWIZZLE_9: ++ return "bit9"; ++ case I915_BIT_6_SWIZZLE_9_10: ++ return "bit9/bit10"; ++ case I915_BIT_6_SWIZZLE_9_11: ++ return "bit9/bit11"; ++ case I915_BIT_6_SWIZZLE_9_10_11: ++ return "bit9/bit10/bit11"; ++ case I915_BIT_6_SWIZZLE_9_17: ++ return "bit9/bit17"; ++ case I915_BIT_6_SWIZZLE_9_10_17: ++ return "bit9/bit10/bit17"; ++ case I915_BIT_6_SWIZZLE_UNKNOWN: ++ return "unkown"; ++ } ++ ++ return "bug"; ++} ++ ++static int i915_swizzle_info(struct seq_file *m, void *data) ++{ ++ struct drm_info_node *node = (struct drm_info_node *) m->private; ++ struct drm_device *dev = node->minor->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ ++ mutex_lock(&dev->struct_mutex); ++ seq_printf(m, "bit6 swizzle for X-tiling = %s\n", ++ swizzle_string(dev_priv->mm.bit_6_swizzle_x)); ++ seq_printf(m, "bit6 swizzle for Y-tiling = %s\n", ++ swizzle_string(dev_priv->mm.bit_6_swizzle_y)); ++ ++ if (IS_GEN3(dev) || IS_GEN4(dev)) { ++ seq_printf(m, "DDC = 0x%08x\n", ++ I915_READ(DCC)); ++ seq_printf(m, "C0DRB3 = 0x%04x\n", ++ I915_READ16(C0DRB3)); ++ seq_printf(m, "C1DRB3 = 0x%04x\n", ++ I915_READ16(C1DRB3)); ++ } else if (IS_GEN6(dev) || IS_GEN7(dev)) { ++ seq_printf(m, "MAD_DIMM_C0 = 0x%08x\n", ++ I915_READ(MAD_DIMM_C0)); ++ seq_printf(m, "MAD_DIMM_C1 = 0x%08x\n", ++ I915_READ(MAD_DIMM_C1)); ++ seq_printf(m, "MAD_DIMM_C2 = 0x%08x\n", ++ I915_READ(MAD_DIMM_C2)); ++ seq_printf(m, "TILECTL = 0x%08x\n", ++ I915_READ(TILECTL)); ++ seq_printf(m, "ARB_MODE = 0x%08x\n", ++ I915_READ(ARB_MODE)); ++ seq_printf(m, "DISP_ARB_CTL = 0x%08x\n", ++ I915_READ(DISP_ARB_CTL)); ++ } ++ mutex_unlock(&dev->struct_mutex); ++ ++ return 0; ++} ++ ++static int i915_ppgtt_info(struct seq_file *m, void *data) ++{ ++ struct drm_info_node *node = (struct drm_info_node *) m->private; ++ struct drm_device *dev = node->minor->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_ring_buffer *ring; ++ int i, ret; ++ ++ ++ ret = mutex_lock_interruptible(&dev->struct_mutex); ++ if (ret) ++ return ret; ++ if (INTEL_INFO(dev)->gen == 6) ++ seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE)); ++ ++ for (i = 0; i < I915_NUM_RINGS; i++) { ++ ring = &dev_priv->ring[i]; ++ ++ seq_printf(m, "%s\n", ring->name); ++ if (INTEL_INFO(dev)->gen == 7) ++ seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(RING_MODE_GEN7(ring))); ++ seq_printf(m, "PP_DIR_BASE: 0x%08x\n", I915_READ(RING_PP_DIR_BASE(ring))); ++ seq_printf(m, "PP_DIR_BASE_READ: 0x%08x\n", I915_READ(RING_PP_DIR_BASE_READ(ring))); ++ seq_printf(m, "PP_DIR_DCLV: 0x%08x\n", I915_READ(RING_PP_DIR_DCLV(ring))); ++ } ++ if (dev_priv->mm.aliasing_ppgtt) { ++ struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; ++ ++ seq_printf(m, "aliasing PPGTT:\n"); ++ seq_printf(m, "pd gtt offset: 0x%08x\n", ppgtt->pd_offset); ++ } ++ seq_printf(m, "ECOCHK: 0x%08x\n", I915_READ(GAM_ECOCHK)); ++ mutex_unlock(&dev->struct_mutex); ++ ++ return 0; ++} ++ + static int +-i915_wedged_open(struct inode *inode, +- struct file *filp) ++i915_debugfs_common_open(struct inode *inode, ++ struct file *filp) + { + filp->private_data = inode->i_private; + return 0; +@@ -1385,20 +1565,12 @@ i915_wedged_write(struct file *filp, + + static const struct file_operations i915_wedged_fops = { + .owner = THIS_MODULE, +- .open = i915_wedged_open, ++ .open = i915_debugfs_common_open, + .read = i915_wedged_read, + .write = i915_wedged_write, + .llseek = default_llseek, + }; + +-static int +-i915_max_freq_open(struct inode *inode, +- struct file *filp) +-{ +- filp->private_data = inode->i_private; +- return 0; +-} +- + static ssize_t + i915_max_freq_read(struct file *filp, + char __user *ubuf, +@@ -1455,20 +1627,12 @@ i915_max_freq_write(struct file *filp, + + static const struct file_operations i915_max_freq_fops = { + .owner = THIS_MODULE, +- .open = i915_max_freq_open, ++ .open = i915_debugfs_common_open, + .read = i915_max_freq_read, + .write = i915_max_freq_write, + .llseek = default_llseek, + }; + +-static int +-i915_cache_sharing_open(struct inode *inode, +- struct file *filp) +-{ +- filp->private_data = inode->i_private; +- return 0; +-} +- + static ssize_t + i915_cache_sharing_read(struct file *filp, + char __user *ubuf, +@@ -1534,7 +1698,7 @@ i915_cache_sharing_write(struct file *filp, + + static const struct file_operations i915_cache_sharing_fops = { + .owner = THIS_MODULE, +- .open = i915_cache_sharing_open, ++ .open = i915_debugfs_common_open, + .read = i915_cache_sharing_read, + .write = i915_cache_sharing_write, + .llseek = default_llseek, +@@ -1566,28 +1730,13 @@ drm_add_fake_info_node(struct drm_minor *minor, + return 0; + } + +-static int i915_wedged_create(struct dentry *root, struct drm_minor *minor) +-{ +- struct drm_device *dev = minor->dev; +- struct dentry *ent; +- +- ent = debugfs_create_file("i915_wedged", +- S_IRUGO | S_IWUSR, +- root, dev, +- &i915_wedged_fops); +- if (IS_ERR(ent)) +- return PTR_ERR(ent); +- +- return drm_add_fake_info_node(minor, ent, &i915_wedged_fops); +-} +- + static int i915_forcewake_open(struct inode *inode, struct file *file) + { + struct drm_device *dev = inode->i_private; + struct drm_i915_private *dev_priv = dev->dev_private; + int ret; + +- if (!IS_GEN6(dev)) ++ if (INTEL_INFO(dev)->gen < 6) + return 0; + + ret = mutex_lock_interruptible(&dev->struct_mutex); +@@ -1604,7 +1753,7 @@ int i915_forcewake_release(struct inode *inode, struct file *file) + struct drm_device *dev = inode->i_private; + struct drm_i915_private *dev_priv = dev->dev_private; + +- if (!IS_GEN6(dev)) ++ if (INTEL_INFO(dev)->gen < 6) + return 0; + + /* +@@ -1642,34 +1791,22 @@ static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor) + return drm_add_fake_info_node(minor, ent, &i915_forcewake_fops); + } + +-static int i915_max_freq_create(struct dentry *root, struct drm_minor *minor) ++static int i915_debugfs_create(struct dentry *root, ++ struct drm_minor *minor, ++ const char *name, ++ const struct file_operations *fops) + { + struct drm_device *dev = minor->dev; + struct dentry *ent; + +- ent = debugfs_create_file("i915_max_freq", ++ ent = debugfs_create_file(name, + S_IRUGO | S_IWUSR, + root, dev, +- &i915_max_freq_fops); ++ fops); + if (IS_ERR(ent)) + return PTR_ERR(ent); + +- return drm_add_fake_info_node(minor, ent, &i915_max_freq_fops); +-} +- +-static int i915_cache_sharing_create(struct dentry *root, struct drm_minor *minor) +-{ +- struct drm_device *dev = minor->dev; +- struct dentry *ent; +- +- ent = debugfs_create_file("i915_cache_sharing", +- S_IRUGO | S_IWUSR, +- root, dev, +- &i915_cache_sharing_fops); +- if (IS_ERR(ent)) +- return PTR_ERR(ent); +- +- return drm_add_fake_info_node(minor, ent, &i915_cache_sharing_fops); ++ return drm_add_fake_info_node(minor, ent, fops); + } + + static struct drm_info_list i915_debugfs_list[] = { +@@ -1695,7 +1832,6 @@ static struct drm_info_list i915_debugfs_list[] = { + {"i915_bsd_ringbuffer_info", i915_ringbuffer_info, 0, (void *)VCS}, + {"i915_blt_ringbuffer_data", i915_ringbuffer_data, 0, (void *)BCS}, + {"i915_blt_ringbuffer_info", i915_ringbuffer_info, 0, (void *)BCS}, +- {"i915_batchbuffers", i915_batchbuffer_info, 0}, + {"i915_error_state", i915_error_state, 0}, + {"i915_rstdby_delays", i915_rstdby_delays, 0}, + {"i915_cur_delayinfo", i915_cur_delayinfo, 0}, +@@ -1711,6 +1847,8 @@ static struct drm_info_list i915_debugfs_list[] = { + {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0}, + {"i915_context_status", i915_context_status, 0}, + {"i915_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0}, ++ {"i915_swizzle_info", i915_swizzle_info, 0}, ++ {"i915_ppgtt_info", i915_ppgtt_info, 0}, + }; + #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) + +@@ -1718,17 +1856,25 @@ int i915_debugfs_init(struct drm_minor *minor) + { + int ret; + +- ret = i915_wedged_create(minor->debugfs_root, minor); ++ ret = i915_debugfs_create(minor->debugfs_root, minor, ++ "i915_wedged", ++ &i915_wedged_fops); + if (ret) + return ret; + + ret = i915_forcewake_create(minor->debugfs_root, minor); + if (ret) + return ret; +- ret = i915_max_freq_create(minor->debugfs_root, minor); ++ ++ ret = i915_debugfs_create(minor->debugfs_root, minor, ++ "i915_max_freq", ++ &i915_max_freq_fops); + if (ret) + return ret; +- ret = i915_cache_sharing_create(minor->debugfs_root, minor); ++ ++ ret = i915_debugfs_create(minor->debugfs_root, minor, ++ "i915_cache_sharing", ++ &i915_cache_sharing_fops); + if (ret) + return ret; + +diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c +index ca67338..05bf620 100644 +--- a/drivers/gpu/drm/i915/i915_dma.c ++++ b/drivers/gpu/drm/i915/i915_dma.c +@@ -781,6 +781,12 @@ static int i915_getparam(struct drm_device *dev, void *data, + case I915_PARAM_HAS_RELAXED_DELTA: + value = 1; + break; ++ case I915_PARAM_HAS_GEN7_SOL_RESET: ++ value = 1; ++ break; ++ case I915_PARAM_HAS_LLC: ++ value = HAS_LLC(dev); ++ break; + default: + DRM_DEBUG_DRIVER("Unknown parameter %d\n", + param->param); +@@ -1177,6 +1183,21 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev) + return can_switch; + } + ++static bool ++intel_enable_ppgtt(struct drm_device *dev) ++{ ++ if (i915_enable_ppgtt >= 0) ++ return i915_enable_ppgtt; ++ ++#ifdef CONFIG_INTEL_IOMMU ++ /* Disable ppgtt on SNB if VT-d is on. */ ++ if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) ++ return false; ++#endif ++ ++ return true; ++} ++ + static int i915_load_gem_init(struct drm_device *dev) + { + struct drm_i915_private *dev_priv = dev->dev_private; +@@ -1190,22 +1211,41 @@ static int i915_load_gem_init(struct drm_device *dev) + /* Basic memrange allocator for stolen space */ + drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size); + +- /* Let GEM Manage all of the aperture. +- * +- * However, leave one page at the end still bound to the scratch page. +- * There are a number of places where the hardware apparently +- * prefetches past the end of the object, and we've seen multiple +- * hangs with the GPU head pointer stuck in a batchbuffer bound +- * at the last page of the aperture. One page should be enough to +- * keep any prefetching inside of the aperture. +- */ +- i915_gem_do_init(dev, 0, mappable_size, gtt_size - PAGE_SIZE); +- + mutex_lock(&dev->struct_mutex); +- ret = i915_gem_init_ringbuffer(dev); ++ if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) { ++ /* PPGTT pdes are stolen from global gtt ptes, so shrink the ++ * aperture accordingly when using aliasing ppgtt. */ ++ gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE; ++ /* For paranoia keep the guard page in between. */ ++ gtt_size -= PAGE_SIZE; ++ ++ i915_gem_do_init(dev, 0, mappable_size, gtt_size); ++ ++ ret = i915_gem_init_aliasing_ppgtt(dev); ++ if (ret) { ++ mutex_unlock(&dev->struct_mutex); ++ return ret; ++ } ++ } else { ++ /* Let GEM Manage all of the aperture. ++ * ++ * However, leave one page at the end still bound to the scratch ++ * page. There are a number of places where the hardware ++ * apparently prefetches past the end of the object, and we've ++ * seen multiple hangs with the GPU head pointer stuck in a ++ * batchbuffer bound at the last page of the aperture. One page ++ * should be enough to keep any prefetching inside of the ++ * aperture. ++ */ ++ i915_gem_do_init(dev, 0, mappable_size, gtt_size - PAGE_SIZE); ++ } ++ ++ ret = i915_gem_init_hw(dev); + mutex_unlock(&dev->struct_mutex); +- if (ret) ++ if (ret) { ++ i915_gem_cleanup_aliasing_ppgtt(dev); + return ret; ++ } + + /* Try to set up FBC with a reasonable compressed buffer size */ + if (I915_HAS_FBC(dev) && i915_powersave) { +@@ -1292,6 +1332,7 @@ cleanup_gem: + mutex_lock(&dev->struct_mutex); + i915_gem_cleanup_ringbuffer(dev); + mutex_unlock(&dev->struct_mutex); ++ i915_gem_cleanup_aliasing_ppgtt(dev); + cleanup_vga_switcheroo: + vga_switcheroo_unregister_client(dev->pdev); + cleanup_vga_client: +@@ -1660,6 +1701,9 @@ void i915_update_gfx_val(struct drm_i915_private *dev_priv) + unsigned long diffms; + u32 count; + ++ if (dev_priv->info->gen != 5) ++ return; ++ + getrawmonotonic(&now); + diff1 = timespec_sub(now, dev_priv->last_time2); + +@@ -1955,7 +1999,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) + goto put_bridge; + } + +- i915_kick_out_firmware_fb(dev_priv); ++ if (drm_core_check_feature(dev, DRIVER_MODESET)) ++ i915_kick_out_firmware_fb(dev_priv); ++ ++ pci_set_master(dev->pdev); + + /* overlay on gen2 is broken and can't address above 1G */ + if (IS_GEN2(dev)) +@@ -2101,12 +2148,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) + setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, + (unsigned long) dev); + +- spin_lock(&mchdev_lock); +- i915_mch_dev = dev_priv; +- dev_priv->mchdev_lock = &mchdev_lock; +- spin_unlock(&mchdev_lock); ++ if (IS_GEN5(dev)) { ++ spin_lock(&mchdev_lock); ++ i915_mch_dev = dev_priv; ++ dev_priv->mchdev_lock = &mchdev_lock; ++ spin_unlock(&mchdev_lock); + +- ips_ping_for_i915_load(); ++ ips_ping_for_i915_load(); ++ } + + return 0; + +@@ -2149,7 +2198,7 @@ int i915_driver_unload(struct drm_device *dev) + unregister_shrinker(&dev_priv->mm.inactive_shrinker); + + mutex_lock(&dev->struct_mutex); +- ret = i915_gpu_idle(dev); ++ ret = i915_gpu_idle(dev, true); + if (ret) + DRM_ERROR("failed to idle hardware: %d\n", ret); + mutex_unlock(&dev->struct_mutex); +@@ -2202,6 +2251,7 @@ int i915_driver_unload(struct drm_device *dev) + i915_gem_free_all_phys_object(dev); + i915_gem_cleanup_ringbuffer(dev); + mutex_unlock(&dev->struct_mutex); ++ i915_gem_cleanup_aliasing_ppgtt(dev); + if (I915_HAS_FBC(dev) && i915_powersave) + i915_cleanup_compression(dev); + drm_mm_takedown(&dev_priv->mm.stolen); +@@ -2267,18 +2317,12 @@ void i915_driver_lastclose(struct drm_device * dev) + + i915_gem_lastclose(dev); + +- if (dev_priv->agp_heap) +- i915_mem_takedown(&(dev_priv->agp_heap)); +- + i915_dma_cleanup(dev); + } + + void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) + { +- drm_i915_private_t *dev_priv = dev->dev_private; + i915_gem_release(dev, file_priv); +- if (!drm_core_check_feature(dev, DRIVER_MODESET)) +- i915_mem_release(dev, file_priv, dev_priv->agp_heap); + } + + void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) +@@ -2297,11 +2341,11 @@ struct drm_ioctl_desc i915_ioctls[] = { + DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), +- DRM_IOCTL_DEF_DRV(I915_ALLOC, i915_mem_alloc, DRM_AUTH), +- DRM_IOCTL_DEF_DRV(I915_FREE, i915_mem_free, DRM_AUTH), +- DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), ++ DRM_IOCTL_DEF_DRV(I915_ALLOC, drm_noop, DRM_AUTH), ++ DRM_IOCTL_DEF_DRV(I915_FREE, drm_noop, DRM_AUTH), ++ DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH), +- DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), ++ DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), +@@ -2329,6 +2373,8 @@ struct drm_ioctl_desc i915_ioctls[] = { + DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), ++ DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), ++ DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + }; + + int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); +diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c +index 452bc51..89f3d4a 100644 +--- a/drivers/gpu/drm/i915/i915_drv.c ++++ b/drivers/gpu/drm/i915/i915_drv.c +@@ -66,7 +66,11 @@ MODULE_PARM_DESC(semaphores, + int i915_enable_rc6 __read_mostly = -1; + module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0400); + MODULE_PARM_DESC(i915_enable_rc6, +- "Enable power-saving render C-state 6 (default: -1 (use per-chip default)"); ++ "Enable power-saving render C-state 6. " ++ "Different stages can be selected via bitmask values " ++ "(0 = disable; 1 = enable rc6; 2 = enable deep rc6; 4 = enable deepest rc6). " ++ "For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. " ++ "default: -1 (use per-chip default)"); + + int i915_enable_fbc __read_mostly = -1; + module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600); +@@ -103,6 +107,11 @@ MODULE_PARM_DESC(enable_hangcheck, + "WARNING: Disabling this can cause system wide hangs. " + "(default: true)"); + ++int i915_enable_ppgtt __read_mostly = -1; ++module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600); ++MODULE_PARM_DESC(i915_enable_ppgtt, ++ "Enable PPGTT (default: true)"); ++ + static struct drm_driver driver; + extern int intel_agp_enabled; + +@@ -198,7 +207,7 @@ static const struct intel_device_info intel_pineview_info = { + + static const struct intel_device_info intel_ironlake_d_info = { + .gen = 5, +- .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, ++ .need_gfx_hws = 1, .has_hotplug = 1, + .has_bsd_ring = 1, + }; + +@@ -214,6 +223,7 @@ static const struct intel_device_info intel_sandybridge_d_info = { + .need_gfx_hws = 1, .has_hotplug = 1, + .has_bsd_ring = 1, + .has_blt_ring = 1, ++ .has_llc = 1, + .has_force_wake = 1, + }; + +@@ -223,6 +233,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { + .has_fbc = 1, + .has_bsd_ring = 1, + .has_blt_ring = 1, ++ .has_llc = 1, + .has_force_wake = 1, + }; + +@@ -231,6 +242,7 @@ static const struct intel_device_info intel_ivybridge_d_info = { + .need_gfx_hws = 1, .has_hotplug = 1, + .has_bsd_ring = 1, + .has_blt_ring = 1, ++ .has_llc = 1, + .has_force_wake = 1, + }; + +@@ -240,6 +252,7 @@ static const struct intel_device_info intel_ivybridge_m_info = { + .has_fbc = 0, /* FBC is not enabled on Ivybridge mobile yet */ + .has_bsd_ring = 1, + .has_blt_ring = 1, ++ .has_llc = 1, + .has_force_wake = 1, + }; + +@@ -381,16 +394,27 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) + spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); + } + ++static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) ++{ ++ u32 gtfifodbg; ++ gtfifodbg = I915_READ_NOTRACE(GTFIFODBG); ++ if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK, ++ "MMIO read or write has been dropped %x\n", gtfifodbg)) ++ I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); ++} ++ + void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) + { + I915_WRITE_NOTRACE(FORCEWAKE, 0); +- POSTING_READ(FORCEWAKE); ++ /* The below doubles as a POSTING_READ */ ++ gen6_gt_check_fifodbg(dev_priv); + } + + void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) + { + I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0); +- POSTING_READ(FORCEWAKE_MT); ++ /* The below doubles as a POSTING_READ */ ++ gen6_gt_check_fifodbg(dev_priv); + } + + /* +@@ -406,8 +430,10 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) + spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); + } + +-void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) ++int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) + { ++ int ret = 0; ++ + if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { + int loop = 500; + u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); +@@ -415,10 +441,13 @@ void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) + udelay(10); + fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); + } +- WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES); ++ if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES)) ++ ++ret; + dev_priv->gt_fifo_count = fifo; + } + dev_priv->gt_fifo_count--; ++ ++ return ret; + } + + static int i915_drm_freeze(struct drm_device *dev) +@@ -503,7 +532,7 @@ static int i915_drm_thaw(struct drm_device *dev) + mutex_lock(&dev->struct_mutex); + dev_priv->mm.suspended = 0; + +- error = i915_gem_init_ringbuffer(dev); ++ error = i915_gem_init_hw(dev); + mutex_unlock(&dev->struct_mutex); + + if (HAS_PCH_SPLIT(dev)) +@@ -614,13 +643,40 @@ static int ironlake_do_reset(struct drm_device *dev, u8 flags) + static int gen6_do_reset(struct drm_device *dev, u8 flags) + { + struct drm_i915_private *dev_priv = dev->dev_private; ++ int ret; ++ unsigned long irqflags; ++ ++ /* Hold gt_lock across reset to prevent any register access ++ * with forcewake not set correctly ++ */ ++ spin_lock_irqsave(&dev_priv->gt_lock, irqflags); ++ ++ /* Reset the chip */ ++ ++ /* GEN6_GDRST is not in the gt power well, no need to check ++ * for fifo space for the write or forcewake the chip for ++ * the read ++ */ ++ I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL); ++ ++ /* Spin waiting for the device to ack the reset request */ ++ ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500); + +- I915_WRITE(GEN6_GDRST, GEN6_GRDOM_FULL); +- return wait_for((I915_READ(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500); ++ /* If reset with a user forcewake, try to restore, otherwise turn it off */ ++ if (dev_priv->forcewake_count) ++ dev_priv->display.force_wake_get(dev_priv); ++ else ++ dev_priv->display.force_wake_put(dev_priv); ++ ++ /* Restore fifo count */ ++ dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); ++ ++ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); ++ return ret; + } + + /** +- * i965_reset - reset chip after a hang ++ * i915_reset - reset chip after a hang + * @dev: drm device to reset + * @flags: reset domains + * +@@ -643,7 +699,6 @@ int i915_reset(struct drm_device *dev, u8 flags) + * need to + */ + bool need_display = true; +- unsigned long irqflags; + int ret; + + if (!i915_try_reset) +@@ -661,11 +716,6 @@ int i915_reset(struct drm_device *dev, u8 flags) + case 7: + case 6: + ret = gen6_do_reset(dev, flags); +- /* If reset with a user forcewake, try to restore */ +- spin_lock_irqsave(&dev_priv->gt_lock, irqflags); +- if (dev_priv->forcewake_count) +- dev_priv->display.force_wake_get(dev_priv); +- spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); + break; + case 5: + ret = ironlake_do_reset(dev, flags); +@@ -702,12 +752,16 @@ int i915_reset(struct drm_device *dev, u8 flags) + !dev_priv->mm.suspended) { + dev_priv->mm.suspended = 0; + ++ i915_gem_init_swizzling(dev); ++ + dev_priv->ring[RCS].init(&dev_priv->ring[RCS]); + if (HAS_BSD(dev)) + dev_priv->ring[VCS].init(&dev_priv->ring[VCS]); + if (HAS_BLT(dev)) + dev_priv->ring[BCS].init(&dev_priv->ring[BCS]); + ++ i915_gem_init_ppgtt(dev); ++ + mutex_unlock(&dev->struct_mutex); + drm_irq_uninstall(dev); + drm_mode_config_reset(dev); +@@ -830,6 +884,21 @@ static struct vm_operations_struct i915_gem_vm_ops = { + .close = drm_gem_vm_close, + }; + ++static const struct file_operations i915_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .mmap = drm_gem_mmap, ++ .poll = drm_poll, ++ .fasync = drm_fasync, ++ .read = drm_read, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = i915_compat_ioctl, ++#endif ++ .llseek = noop_llseek, ++}; ++ + static struct drm_driver driver = { + /* Don't use MTRRs here; the Xserver or userspace app should + * deal with them for Intel hardware. +@@ -863,21 +932,7 @@ static struct drm_driver driver = { + .dumb_map_offset = i915_gem_mmap_gtt, + .dumb_destroy = i915_gem_dumb_destroy, + .ioctls = i915_ioctls, +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = drm_ioctl, +- .mmap = drm_gem_mmap, +- .poll = drm_poll, +- .fasync = drm_fasync, +- .read = drm_read, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = i915_compat_ioctl, +-#endif +- .llseek = noop_llseek, +- }, +- ++ .fops = &i915_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, +@@ -945,17 +1000,21 @@ MODULE_LICENSE("GPL and additional rights"); + /* We give fast paths for the really cool registers */ + #define NEEDS_FORCE_WAKE(dev_priv, reg) \ + ((HAS_FORCE_WAKE((dev_priv)->dev)) && \ +- ((reg) < 0x40000) && \ +- ((reg) != FORCEWAKE) && \ +- ((reg) != ECOBUS)) ++ ((reg) < 0x40000) && \ ++ ((reg) != FORCEWAKE)) + + #define __i915_read(x, y) \ + u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ + u##x val = 0; \ + if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ +- gen6_gt_force_wake_get(dev_priv); \ ++ unsigned long irqflags; \ ++ spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \ ++ if (dev_priv->forcewake_count == 0) \ ++ dev_priv->display.force_wake_get(dev_priv); \ + val = read##y(dev_priv->regs + reg); \ +- gen6_gt_force_wake_put(dev_priv); \ ++ if (dev_priv->forcewake_count == 0) \ ++ dev_priv->display.force_wake_put(dev_priv); \ ++ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \ + } else { \ + val = read##y(dev_priv->regs + reg); \ + } \ +@@ -971,11 +1030,15 @@ __i915_read(64, q) + + #define __i915_write(x, y) \ + void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ ++ u32 __fifo_ret = 0; \ + trace_i915_reg_rw(true, reg, val, sizeof(val)); \ + if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ +- __gen6_gt_wait_for_fifo(dev_priv); \ ++ __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ + } \ + write##y(val, dev_priv->regs + reg); \ ++ if (unlikely(__fifo_ret)) { \ ++ gen6_gt_check_fifodbg(dev_priv); \ ++ } \ + } + __i915_write(8, b) + __i915_write(16, w) +diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h +index 61274bf..a8f00d0 100644 +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -35,6 +35,7 @@ + #include "intel_ringbuffer.h" + #include + #include ++#include + #include + #include + +@@ -135,6 +136,7 @@ struct drm_i915_fence_reg { + struct list_head lru_list; + struct drm_i915_gem_object *obj; + uint32_t setup_seqno; ++ int pin_count; + }; + + struct sdvo_device_mapping { +@@ -152,33 +154,40 @@ struct drm_i915_error_state { + u32 eir; + u32 pgtbl_er; + u32 pipestat[I915_MAX_PIPES]; +- u32 ipeir; +- u32 ipehr; +- u32 instdone; +- u32 acthd; ++ u32 tail[I915_NUM_RINGS]; ++ u32 head[I915_NUM_RINGS]; ++ u32 ipeir[I915_NUM_RINGS]; ++ u32 ipehr[I915_NUM_RINGS]; ++ u32 instdone[I915_NUM_RINGS]; ++ u32 acthd[I915_NUM_RINGS]; ++ u32 semaphore_mboxes[I915_NUM_RINGS][I915_NUM_RINGS - 1]; ++ /* our own tracking of ring head and tail */ ++ u32 cpu_ring_head[I915_NUM_RINGS]; ++ u32 cpu_ring_tail[I915_NUM_RINGS]; + u32 error; /* gen6+ */ +- u32 bcs_acthd; /* gen6+ blt engine */ +- u32 bcs_ipehr; +- u32 bcs_ipeir; +- u32 bcs_instdone; +- u32 bcs_seqno; +- u32 vcs_acthd; /* gen6+ bsd engine */ +- u32 vcs_ipehr; +- u32 vcs_ipeir; +- u32 vcs_instdone; +- u32 vcs_seqno; +- u32 instpm; +- u32 instps; ++ u32 instpm[I915_NUM_RINGS]; ++ u32 instps[I915_NUM_RINGS]; + u32 instdone1; +- u32 seqno; ++ u32 seqno[I915_NUM_RINGS]; + u64 bbaddr; ++ u32 fault_reg[I915_NUM_RINGS]; ++ u32 done_reg; ++ u32 faddr[I915_NUM_RINGS]; + u64 fence[I915_MAX_NUM_FENCES]; + struct timeval time; +- struct drm_i915_error_object { +- int page_count; +- u32 gtt_offset; +- u32 *pages[0]; +- } *ringbuffer[I915_NUM_RINGS], *batchbuffer[I915_NUM_RINGS]; ++ struct drm_i915_error_ring { ++ struct drm_i915_error_object { ++ int page_count; ++ u32 gtt_offset; ++ u32 *pages[0]; ++ } *ringbuffer, *batchbuffer; ++ struct drm_i915_error_request { ++ long jiffies; ++ u32 seqno; ++ u32 tail; ++ } *requests; ++ int num_requests; ++ } ring[I915_NUM_RINGS]; + struct drm_i915_error_buffer { + u32 size; + u32 name; +@@ -191,7 +200,7 @@ struct drm_i915_error_state { + u32 tiling:2; + u32 dirty:1; + u32 purgeable:1; +- u32 ring:4; ++ s32 ring:4; + u32 cache_level:2; + } *active_bo, *pinned_bo; + u32 active_bo_count, pinned_bo_count; +@@ -207,6 +216,8 @@ struct drm_i915_display_funcs { + int (*get_display_clock_speed)(struct drm_device *dev); + int (*get_fifo_size)(struct drm_device *dev, int plane); + void (*update_wm)(struct drm_device *dev); ++ void (*update_sprite_wm)(struct drm_device *dev, int pipe, ++ uint32_t sprite_width, int pixel_size); + int (*crtc_mode_set)(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, +@@ -254,6 +265,17 @@ struct intel_device_info { + u8 supports_tv:1; + u8 has_bsd_ring:1; + u8 has_blt_ring:1; ++ u8 has_llc:1; ++}; ++ ++#define I915_PPGTT_PD_ENTRIES 512 ++#define I915_PPGTT_PT_ENTRIES 1024 ++struct i915_hw_ppgtt { ++ unsigned num_pd_entries; ++ struct page **pt_pages; ++ uint32_t pd_offset; ++ dma_addr_t *pt_dma_addr; ++ dma_addr_t scratch_page_dma_addr; + }; + + enum no_fbc_reason { +@@ -280,6 +302,16 @@ enum intel_pch { + struct intel_fbdev; + struct intel_fbc_work; + ++struct intel_gmbus { ++ struct i2c_adapter adapter; ++ bool force_bit; ++ bool has_gpio; ++ u32 reg0; ++ u32 gpio_reg; ++ struct i2c_algo_bit_data bit_algo; ++ struct drm_i915_private *dev_priv; ++}; ++ + typedef struct drm_i915_private { + struct drm_device *dev; + +@@ -297,11 +329,11 @@ typedef struct drm_i915_private { + /** gt_lock is also taken in irq contexts. */ + struct spinlock gt_lock; + +- struct intel_gmbus { +- struct i2c_adapter adapter; +- struct i2c_adapter *force_bit; +- u32 reg0; +- } *gmbus; ++ struct intel_gmbus *gmbus; ++ ++ /** gmbus_mutex protects against concurrent usage of the single hw gmbus ++ * controller on different i2c buses. */ ++ struct mutex gmbus_mutex; + + struct pci_dev *bridge_dev; + struct intel_ring_buffer ring[I915_NUM_RINGS]; +@@ -336,7 +368,6 @@ typedef struct drm_i915_private { + + int tex_lru_log_granularity; + int allow_batchbuffer; +- struct mem_block *agp_heap; + unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; + int vblank_pipe; + int num_pipe; +@@ -361,6 +392,7 @@ typedef struct drm_i915_private { + + /* overlay */ + struct intel_overlay *overlay; ++ bool sprite_scaling_enabled; + + /* LVDS info */ + int backlight_level; /* restore backlight to this value */ +@@ -586,6 +618,9 @@ typedef struct drm_i915_private { + struct io_mapping *gtt_mapping; + int gtt_mtrr; + ++ /** PPGTT used for aliasing the PPGTT with the GTT */ ++ struct i915_hw_ppgtt *aliasing_ppgtt; ++ + struct shrinker inactive_shrinker; + + /** +@@ -751,6 +786,13 @@ typedef struct drm_i915_private { + struct drm_property *force_audio_property; + } drm_i915_private_t; + ++enum hdmi_force_audio { ++ HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */ ++ HDMI_AUDIO_OFF, /* force turn off HDMI audio */ ++ HDMI_AUDIO_AUTO, /* trust EDID */ ++ HDMI_AUDIO_ON, /* force turn on HDMI audio */ ++}; ++ + enum i915_cache_level { + I915_CACHE_NONE, + I915_CACHE_LLC, +@@ -843,6 +885,8 @@ struct drm_i915_gem_object { + + unsigned int cache_level:2; + ++ unsigned int has_aliasing_ppgtt_mapping:1; ++ + struct page **pages; + + /** +@@ -920,6 +964,9 @@ struct drm_i915_gem_request { + /** GEM sequence number associated with this request. */ + uint32_t seqno; + ++ /** Postion in the ringbuffer of the end of the request */ ++ u32 tail; ++ + /** Time at which this request was emitted, in jiffies. */ + unsigned long emitted_jiffies; + +@@ -976,8 +1023,11 @@ struct drm_i915_file_private { + + #define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring) + #define HAS_BLT(dev) (INTEL_INFO(dev)->has_blt_ring) ++#define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) + #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) + ++#define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >=6) ++ + #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) + #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) + +@@ -1010,6 +1060,27 @@ struct drm_i915_file_private { + + #include "i915_trace.h" + ++/** ++ * RC6 is a special power stage which allows the GPU to enter an very ++ * low-voltage mode when idle, using down to 0V while at this stage. This ++ * stage is entered automatically when the GPU is idle when RC6 support is ++ * enabled, and as soon as new workload arises GPU wakes up automatically as well. ++ * ++ * There are different RC6 modes available in Intel GPU, which differentiate ++ * among each other with the latency required to enter and leave RC6 and ++ * voltage consumed by the GPU in different states. ++ * ++ * The combination of the following flags define which states GPU is allowed ++ * to enter, while RC6 is the normal RC6 state, RC6p is the deep RC6, and ++ * RC6pp is deepest RC6. Their support by hardware varies according to the ++ * GPU, BIOS, chipset and platform. RC6 is usually the safest one and the one ++ * which brings the most power savings; deeper states save more power, but ++ * require higher latency to switch to and wake up. ++ */ ++#define INTEL_RC6_ENABLE (1<<0) ++#define INTEL_RC6p_ENABLE (1<<1) ++#define INTEL_RC6pp_ENABLE (1<<2) ++ + extern struct drm_ioctl_desc i915_ioctls[]; + extern int i915_max_ioctl; + extern unsigned int i915_fbpercrtc __always_unused; +@@ -1022,6 +1093,7 @@ extern int i915_vbt_sdvo_panel_type __read_mostly; + extern int i915_enable_rc6 __read_mostly; + extern int i915_enable_fbc __read_mostly; + extern bool i915_enable_hangcheck __read_mostly; ++extern int i915_enable_ppgtt __read_mostly; + + extern int i915_suspend(struct drm_device *dev, pm_message_t state); + extern int i915_resume(struct drm_device *dev); +@@ -1083,18 +1155,6 @@ extern void i915_destroy_error_state(struct drm_device *dev); + #endif + + +-/* i915_mem.c */ +-extern int i915_mem_alloc(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +-extern int i915_mem_free(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +-extern int i915_mem_init_heap(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +-extern int i915_mem_destroy_heap(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +-extern void i915_mem_takedown(struct mem_block **heap); +-extern void i915_mem_release(struct drm_device * dev, +- struct drm_file *file_priv, struct mem_block *heap); + /* i915_gem.c */ + int i915_gem_init_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +@@ -1180,26 +1240,49 @@ int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined); + int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj); + ++static inline void ++i915_gem_object_pin_fence(struct drm_i915_gem_object *obj) ++{ ++ if (obj->fence_reg != I915_FENCE_REG_NONE) { ++ struct drm_i915_private *dev_priv = obj->base.dev->dev_private; ++ dev_priv->fence_regs[obj->fence_reg].pin_count++; ++ } ++} ++ ++static inline void ++i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj) ++{ ++ if (obj->fence_reg != I915_FENCE_REG_NONE) { ++ struct drm_i915_private *dev_priv = obj->base.dev->dev_private; ++ dev_priv->fence_regs[obj->fence_reg].pin_count--; ++ } ++} ++ + void i915_gem_retire_requests(struct drm_device *dev); ++void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring); ++ + void i915_gem_reset(struct drm_device *dev); + void i915_gem_clflush_object(struct drm_i915_gem_object *obj); + int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj, + uint32_t read_domains, + uint32_t write_domain); + int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj); +-int __must_check i915_gem_init_ringbuffer(struct drm_device *dev); ++int __must_check i915_gem_init_hw(struct drm_device *dev); ++void i915_gem_init_swizzling(struct drm_device *dev); ++void i915_gem_init_ppgtt(struct drm_device *dev); + void i915_gem_cleanup_ringbuffer(struct drm_device *dev); + void i915_gem_do_init(struct drm_device *dev, + unsigned long start, + unsigned long mappable_end, + unsigned long end); +-int __must_check i915_gpu_idle(struct drm_device *dev); ++int __must_check i915_gpu_idle(struct drm_device *dev, bool do_retire); + int __must_check i915_gem_idle(struct drm_device *dev); + int __must_check i915_add_request(struct intel_ring_buffer *ring, + struct drm_file *file, + struct drm_i915_gem_request *request); + int __must_check i915_wait_request(struct intel_ring_buffer *ring, +- uint32_t seqno); ++ uint32_t seqno, ++ bool do_retire); + int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); + int __must_check + i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, +@@ -1226,6 +1309,14 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, + enum i915_cache_level cache_level); + + /* i915_gem_gtt.c */ ++int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev); ++void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev); ++void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, ++ struct drm_i915_gem_object *obj, ++ enum i915_cache_level cache_level); ++void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, ++ struct drm_i915_gem_object *obj); ++ + void i915_gem_restore_gtt_mappings(struct drm_device *dev); + int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj); + void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj, +@@ -1365,14 +1456,7 @@ extern void intel_display_print_error_state(struct seq_file *m, + */ + void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); + void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); +-void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv); +- +-/* We give fast paths for the really cool registers */ +-#define NEEDS_FORCE_WAKE(dev_priv, reg) \ +- (((dev_priv)->info->gen >= 6) && \ +- ((reg) < 0x40000) && \ +- ((reg) != FORCEWAKE) && \ +- ((reg) != ECOBUS)) ++int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv); + + #define __i915_read(x, y) \ + u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg); +diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c +index 315a49e..2e98422c 100644 +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -58,6 +58,7 @@ static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj); + + static int i915_gem_inactive_shrink(struct shrinker *shrinker, + struct shrink_control *sc); ++static void i915_gem_object_truncate(struct drm_i915_gem_object *obj); + + /* some bookkeeping */ + static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv, +@@ -258,73 +259,6 @@ static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj) + obj->tiling_mode != I915_TILING_NONE; + } + +-static inline void +-slow_shmem_copy(struct page *dst_page, +- int dst_offset, +- struct page *src_page, +- int src_offset, +- int length) +-{ +- char *dst_vaddr, *src_vaddr; +- +- dst_vaddr = kmap(dst_page); +- src_vaddr = kmap(src_page); +- +- memcpy(dst_vaddr + dst_offset, src_vaddr + src_offset, length); +- +- kunmap(src_page); +- kunmap(dst_page); +-} +- +-static inline void +-slow_shmem_bit17_copy(struct page *gpu_page, +- int gpu_offset, +- struct page *cpu_page, +- int cpu_offset, +- int length, +- int is_read) +-{ +- char *gpu_vaddr, *cpu_vaddr; +- +- /* Use the unswizzled path if this page isn't affected. */ +- if ((page_to_phys(gpu_page) & (1 << 17)) == 0) { +- if (is_read) +- return slow_shmem_copy(cpu_page, cpu_offset, +- gpu_page, gpu_offset, length); +- else +- return slow_shmem_copy(gpu_page, gpu_offset, +- cpu_page, cpu_offset, length); +- } +- +- gpu_vaddr = kmap(gpu_page); +- cpu_vaddr = kmap(cpu_page); +- +- /* Copy the data, XORing A6 with A17 (1). The user already knows he's +- * XORing with the other bits (A9 for Y, A9 and A10 for X) +- */ +- while (length > 0) { +- int cacheline_end = ALIGN(gpu_offset + 1, 64); +- int this_length = min(cacheline_end - gpu_offset, length); +- int swizzled_gpu_offset = gpu_offset ^ 64; +- +- if (is_read) { +- memcpy(cpu_vaddr + cpu_offset, +- gpu_vaddr + swizzled_gpu_offset, +- this_length); +- } else { +- memcpy(gpu_vaddr + swizzled_gpu_offset, +- cpu_vaddr + cpu_offset, +- this_length); +- } +- cpu_offset += this_length; +- gpu_offset += this_length; +- length -= this_length; +- } +- +- kunmap(cpu_page); +- kunmap(gpu_page); +-} +- + /** + * This is the fast shmem pread path, which attempts to copy_from_user directly + * from the backing pages of the object to the user's address space. On a +@@ -385,6 +319,58 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, + return 0; + } + ++static inline int ++__copy_to_user_swizzled(char __user *cpu_vaddr, ++ const char *gpu_vaddr, int gpu_offset, ++ int length) ++{ ++ int ret, cpu_offset = 0; ++ ++ while (length > 0) { ++ int cacheline_end = ALIGN(gpu_offset + 1, 64); ++ int this_length = min(cacheline_end - gpu_offset, length); ++ int swizzled_gpu_offset = gpu_offset ^ 64; ++ ++ ret = __copy_to_user(cpu_vaddr + cpu_offset, ++ gpu_vaddr + swizzled_gpu_offset, ++ this_length); ++ if (ret) ++ return ret + length; ++ ++ cpu_offset += this_length; ++ gpu_offset += this_length; ++ length -= this_length; ++ } ++ ++ return 0; ++} ++ ++static inline int ++__copy_from_user_swizzled(char __user *gpu_vaddr, int gpu_offset, ++ const char *cpu_vaddr, ++ int length) ++{ ++ int ret, cpu_offset = 0; ++ ++ while (length > 0) { ++ int cacheline_end = ALIGN(gpu_offset + 1, 64); ++ int this_length = min(cacheline_end - gpu_offset, length); ++ int swizzled_gpu_offset = gpu_offset ^ 64; ++ ++ ret = __copy_from_user(gpu_vaddr + swizzled_gpu_offset, ++ cpu_vaddr + cpu_offset, ++ this_length); ++ if (ret) ++ return ret + length; ++ ++ cpu_offset += this_length; ++ gpu_offset += this_length; ++ length -= this_length; ++ } ++ ++ return 0; ++} ++ + /** + * This is the fallback shmem pread path, which allocates temporary storage + * in kernel space to copy_to_user into outside of the struct_mutex, so we +@@ -398,72 +384,34 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, + struct drm_file *file) + { + struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping; +- struct mm_struct *mm = current->mm; +- struct page **user_pages; ++ char __user *user_data; + ssize_t remain; +- loff_t offset, pinned_pages, i; +- loff_t first_data_page, last_data_page, num_pages; +- int shmem_page_offset; +- int data_page_index, data_page_offset; +- int page_length; +- int ret; +- uint64_t data_ptr = args->data_ptr; +- int do_bit17_swizzling; ++ loff_t offset; ++ int shmem_page_offset, page_length, ret; ++ int obj_do_bit17_swizzling, page_do_bit17_swizzling; + ++ user_data = (char __user *) (uintptr_t) args->data_ptr; + remain = args->size; + +- /* Pin the user pages containing the data. We can't fault while +- * holding the struct mutex, yet we want to hold it while +- * dereferencing the user data. +- */ +- first_data_page = data_ptr / PAGE_SIZE; +- last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; +- num_pages = last_data_page - first_data_page + 1; ++ obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); + +- user_pages = drm_malloc_ab(num_pages, sizeof(struct page *)); +- if (user_pages == NULL) +- return -ENOMEM; ++ offset = args->offset; + + mutex_unlock(&dev->struct_mutex); +- down_read(&mm->mmap_sem); +- pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, +- num_pages, 1, 0, user_pages, NULL); +- up_read(&mm->mmap_sem); +- mutex_lock(&dev->struct_mutex); +- if (pinned_pages < num_pages) { +- ret = -EFAULT; +- goto out; +- } +- +- ret = i915_gem_object_set_cpu_read_domain_range(obj, +- args->offset, +- args->size); +- if (ret) +- goto out; +- +- do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); +- +- offset = args->offset; + + while (remain > 0) { + struct page *page; ++ char *vaddr; + + /* Operation in this page + * + * shmem_page_offset = offset within page in shmem file +- * data_page_index = page number in get_user_pages return +- * data_page_offset = offset with data_page_index page. + * page_length = bytes to copy for this page + */ + shmem_page_offset = offset_in_page(offset); +- data_page_index = data_ptr / PAGE_SIZE - first_data_page; +- data_page_offset = offset_in_page(data_ptr); +- + page_length = remain; + if ((shmem_page_offset + page_length) > PAGE_SIZE) + page_length = PAGE_SIZE - shmem_page_offset; +- if ((data_page_offset + page_length) > PAGE_SIZE) +- page_length = PAGE_SIZE - data_page_offset; + + page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); + if (IS_ERR(page)) { +@@ -471,36 +419,38 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, + goto out; + } + +- if (do_bit17_swizzling) { +- slow_shmem_bit17_copy(page, +- shmem_page_offset, +- user_pages[data_page_index], +- data_page_offset, +- page_length, +- 1); +- } else { +- slow_shmem_copy(user_pages[data_page_index], +- data_page_offset, +- page, +- shmem_page_offset, +- page_length); +- } ++ page_do_bit17_swizzling = obj_do_bit17_swizzling && ++ (page_to_phys(page) & (1 << 17)) != 0; ++ ++ vaddr = kmap(page); ++ if (page_do_bit17_swizzling) ++ ret = __copy_to_user_swizzled(user_data, ++ vaddr, shmem_page_offset, ++ page_length); ++ else ++ ret = __copy_to_user(user_data, ++ vaddr + shmem_page_offset, ++ page_length); ++ kunmap(page); + + mark_page_accessed(page); + page_cache_release(page); + ++ if (ret) { ++ ret = -EFAULT; ++ goto out; ++ } ++ + remain -= page_length; +- data_ptr += page_length; ++ user_data += page_length; + offset += page_length; + } + + out: +- for (i = 0; i < pinned_pages; i++) { +- SetPageDirty(user_pages[i]); +- mark_page_accessed(user_pages[i]); +- page_cache_release(user_pages[i]); +- } +- drm_free_large(user_pages); ++ mutex_lock(&dev->struct_mutex); ++ /* Fixup: Kill any reinstated backing storage pages */ ++ if (obj->madv == __I915_MADV_PURGED) ++ i915_gem_object_truncate(obj); + + return ret; + } +@@ -841,71 +791,36 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, + struct drm_file *file) + { + struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping; +- struct mm_struct *mm = current->mm; +- struct page **user_pages; + ssize_t remain; +- loff_t offset, pinned_pages, i; +- loff_t first_data_page, last_data_page, num_pages; +- int shmem_page_offset; +- int data_page_index, data_page_offset; +- int page_length; +- int ret; +- uint64_t data_ptr = args->data_ptr; +- int do_bit17_swizzling; ++ loff_t offset; ++ char __user *user_data; ++ int shmem_page_offset, page_length, ret; ++ int obj_do_bit17_swizzling, page_do_bit17_swizzling; + ++ user_data = (char __user *) (uintptr_t) args->data_ptr; + remain = args->size; + +- /* Pin the user pages containing the data. We can't fault while +- * holding the struct mutex, and all of the pwrite implementations +- * want to hold it while dereferencing the user data. +- */ +- first_data_page = data_ptr / PAGE_SIZE; +- last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; +- num_pages = last_data_page - first_data_page + 1; +- +- user_pages = drm_malloc_ab(num_pages, sizeof(struct page *)); +- if (user_pages == NULL) +- return -ENOMEM; +- +- mutex_unlock(&dev->struct_mutex); +- down_read(&mm->mmap_sem); +- pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, +- num_pages, 0, 0, user_pages, NULL); +- up_read(&mm->mmap_sem); +- mutex_lock(&dev->struct_mutex); +- if (pinned_pages < num_pages) { +- ret = -EFAULT; +- goto out; +- } +- +- ret = i915_gem_object_set_to_cpu_domain(obj, 1); +- if (ret) +- goto out; +- +- do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); ++ obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); + + offset = args->offset; + obj->dirty = 1; + ++ mutex_unlock(&dev->struct_mutex); ++ + while (remain > 0) { + struct page *page; ++ char *vaddr; + + /* Operation in this page + * + * shmem_page_offset = offset within page in shmem file +- * data_page_index = page number in get_user_pages return +- * data_page_offset = offset with data_page_index page. + * page_length = bytes to copy for this page + */ + shmem_page_offset = offset_in_page(offset); +- data_page_index = data_ptr / PAGE_SIZE - first_data_page; +- data_page_offset = offset_in_page(data_ptr); + + page_length = remain; + if ((shmem_page_offset + page_length) > PAGE_SIZE) + page_length = PAGE_SIZE - shmem_page_offset; +- if ((data_page_offset + page_length) > PAGE_SIZE) +- page_length = PAGE_SIZE - data_page_offset; + + page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); + if (IS_ERR(page)) { +@@ -913,34 +828,45 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, + goto out; + } + +- if (do_bit17_swizzling) { +- slow_shmem_bit17_copy(page, +- shmem_page_offset, +- user_pages[data_page_index], +- data_page_offset, +- page_length, +- 0); +- } else { +- slow_shmem_copy(page, +- shmem_page_offset, +- user_pages[data_page_index], +- data_page_offset, +- page_length); +- } ++ page_do_bit17_swizzling = obj_do_bit17_swizzling && ++ (page_to_phys(page) & (1 << 17)) != 0; ++ ++ vaddr = kmap(page); ++ if (page_do_bit17_swizzling) ++ ret = __copy_from_user_swizzled(vaddr, shmem_page_offset, ++ user_data, ++ page_length); ++ else ++ ret = __copy_from_user(vaddr + shmem_page_offset, ++ user_data, ++ page_length); ++ kunmap(page); + + set_page_dirty(page); + mark_page_accessed(page); + page_cache_release(page); + ++ if (ret) { ++ ret = -EFAULT; ++ goto out; ++ } ++ + remain -= page_length; +- data_ptr += page_length; ++ user_data += page_length; + offset += page_length; + } + + out: +- for (i = 0; i < pinned_pages; i++) +- page_cache_release(user_pages[i]); +- drm_free_large(user_pages); ++ mutex_lock(&dev->struct_mutex); ++ /* Fixup: Kill any reinstated backing storage pages */ ++ if (obj->madv == __I915_MADV_PURGED) ++ i915_gem_object_truncate(obj); ++ /* and flush dirty cachelines in case the object isn't in the cpu write ++ * domain anymore. */ ++ if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) { ++ i915_gem_clflush_object(obj); ++ intel_gtt_chipset_flush(); ++ } + + return ret; + } +@@ -996,11 +922,14 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, + * pread/pwrite currently are reading and writing from the CPU + * perspective, requiring manual detiling by the client. + */ +- if (obj->phys_obj) ++ if (obj->phys_obj) { + ret = i915_gem_phys_pwrite(dev, obj, args, file); +- else if (obj->gtt_space && +- obj->tiling_mode == I915_TILING_NONE && +- obj->base.write_domain != I915_GEM_DOMAIN_CPU) { ++ goto out; ++ } ++ ++ if (obj->gtt_space && ++ obj->tiling_mode == I915_TILING_NONE && ++ obj->base.write_domain != I915_GEM_DOMAIN_CPU) { + ret = i915_gem_object_pin(obj, 0, true); + if (ret) + goto out; +@@ -1019,18 +948,24 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, + + out_unpin: + i915_gem_object_unpin(obj); +- } else { +- ret = i915_gem_object_set_to_cpu_domain(obj, 1); +- if (ret) +- goto out; + +- ret = -EFAULT; +- if (!i915_gem_object_needs_bit17_swizzle(obj)) +- ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file); +- if (ret == -EFAULT) +- ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file); ++ if (ret != -EFAULT) ++ goto out; ++ /* Fall through to the shmfs paths because the gtt paths might ++ * fail with non-page-backed user pointers (e.g. gtt mappings ++ * when moving data between textures). */ + } + ++ ret = i915_gem_object_set_to_cpu_domain(obj, 1); ++ if (ret) ++ goto out; ++ ++ ret = -EFAULT; ++ if (!i915_gem_object_needs_bit17_swizzle(obj)) ++ ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file); ++ if (ret == -EFAULT) ++ ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file); ++ + out: + drm_gem_object_unreference(&obj->base); + unlock: +@@ -1142,7 +1077,6 @@ int + i915_gem_mmap_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) + { +- struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_mmap *args = data; + struct drm_gem_object *obj; + unsigned long addr; +@@ -1154,11 +1088,6 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, + if (obj == NULL) + return -ENOENT; + +- if (obj->size > dev_priv->mm.gtt_mappable_end) { +- drm_gem_object_unreference_unlocked(obj); +- return -E2BIG; +- } +- + down_write(¤t->mm->mmap_sem); + addr = do_mmap(obj->filp, 0, args->size, + PROT_READ | PROT_WRITE, MAP_SHARED, +@@ -1687,12 +1616,20 @@ i915_add_request(struct intel_ring_buffer *ring, + { + drm_i915_private_t *dev_priv = ring->dev->dev_private; + uint32_t seqno; ++ u32 request_ring_position; + int was_empty; + int ret; + + BUG_ON(request == NULL); + seqno = i915_gem_next_request_seqno(ring); + ++ /* Record the position of the start of the request so that ++ * should we detect the updated seqno part-way through the ++ * GPU processing the request, we never over-estimate the ++ * position of the head. ++ */ ++ request_ring_position = intel_ring_get_tail(ring); ++ + ret = ring->add_request(ring, &seqno); + if (ret) + return ret; +@@ -1701,6 +1638,7 @@ i915_add_request(struct intel_ring_buffer *ring, + + request->seqno = seqno; + request->ring = ring; ++ request->tail = request_ring_position; + request->emitted_jiffies = jiffies; + was_empty = list_empty(&ring->request_list); + list_add_tail(&request->list, &ring->request_list); +@@ -1715,7 +1653,7 @@ i915_add_request(struct intel_ring_buffer *ring, + spin_unlock(&file_priv->mm.lock); + } + +- ring->outstanding_lazy_request = false; ++ ring->outstanding_lazy_request = 0; + + if (!dev_priv->mm.suspended) { + if (i915_enable_hangcheck) { +@@ -1837,7 +1775,7 @@ void i915_gem_reset(struct drm_device *dev) + /** + * This function clears the request list as sequence numbers are passed. + */ +-static void ++void + i915_gem_retire_requests_ring(struct intel_ring_buffer *ring) + { + uint32_t seqno; +@@ -1865,6 +1803,12 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring) + break; + + trace_i915_gem_request_retire(ring, request->seqno); ++ /* We know the GPU must have read the request to have ++ * sent us the seqno + interrupt, so use the position ++ * of tail of the request to update the last known position ++ * of the GPU head. ++ */ ++ ring->last_retired_head = request->tail; + + list_del(&request->list); + i915_gem_request_remove_from_client(request); +@@ -1977,7 +1921,8 @@ i915_gem_retire_work_handler(struct work_struct *work) + */ + int + i915_wait_request(struct intel_ring_buffer *ring, +- uint32_t seqno) ++ uint32_t seqno, ++ bool do_retire) + { + drm_i915_private_t *dev_priv = ring->dev->dev_private; + u32 ier; +@@ -2040,9 +1985,9 @@ i915_wait_request(struct intel_ring_buffer *ring, + || atomic_read(&dev_priv->mm.wedged)); + + ring->irq_put(ring); +- } else if (wait_for(i915_seqno_passed(ring->get_seqno(ring), +- seqno) || +- atomic_read(&dev_priv->mm.wedged), 3000)) ++ } else if (wait_for_atomic(i915_seqno_passed(ring->get_seqno(ring), ++ seqno) || ++ atomic_read(&dev_priv->mm.wedged), 3000)) + ret = -EBUSY; + ring->waiting_seqno = 0; + +@@ -2051,17 +1996,12 @@ i915_wait_request(struct intel_ring_buffer *ring, + if (atomic_read(&dev_priv->mm.wedged)) + ret = -EAGAIN; + +- if (ret && ret != -ERESTARTSYS) +- DRM_ERROR("%s returns %d (awaiting %d at %d, next %d)\n", +- __func__, ret, seqno, ring->get_seqno(ring), +- dev_priv->next_seqno); +- + /* Directly dispatch request retiring. While we have the work queue + * to handle this, the waiter on a request often wants an associated + * buffer to have made it to the inactive list, and we would need + * a separate wait queue to handle that. + */ +- if (ret == 0) ++ if (ret == 0 && do_retire) + i915_gem_retire_requests_ring(ring); + + return ret; +@@ -2085,7 +2025,8 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj) + * it. + */ + if (obj->active) { +- ret = i915_wait_request(obj->ring, obj->last_rendering_seqno); ++ ret = i915_wait_request(obj->ring, obj->last_rendering_seqno, ++ true); + if (ret) + return ret; + } +@@ -2123,6 +2064,7 @@ static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj) + int + i915_gem_object_unbind(struct drm_i915_gem_object *obj) + { ++ drm_i915_private_t *dev_priv = obj->base.dev->dev_private; + int ret = 0; + + if (obj->gtt_space == NULL) +@@ -2167,6 +2109,11 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj) + trace_i915_gem_object_unbind(obj); + + i915_gem_gtt_unbind_object(obj); ++ if (obj->has_aliasing_ppgtt_mapping) { ++ i915_ppgtt_unbind_object(dev_priv->mm.aliasing_ppgtt, obj); ++ obj->has_aliasing_ppgtt_mapping = 0; ++ } ++ + i915_gem_object_put_pages_gtt(obj); + + list_del_init(&obj->gtt_list); +@@ -2206,7 +2153,7 @@ i915_gem_flush_ring(struct intel_ring_buffer *ring, + return 0; + } + +-static int i915_ring_idle(struct intel_ring_buffer *ring) ++static int i915_ring_idle(struct intel_ring_buffer *ring, bool do_retire) + { + int ret; + +@@ -2220,18 +2167,18 @@ static int i915_ring_idle(struct intel_ring_buffer *ring) + return ret; + } + +- return i915_wait_request(ring, i915_gem_next_request_seqno(ring)); ++ return i915_wait_request(ring, i915_gem_next_request_seqno(ring), ++ do_retire); + } + +-int +-i915_gpu_idle(struct drm_device *dev) ++int i915_gpu_idle(struct drm_device *dev, bool do_retire) + { + drm_i915_private_t *dev_priv = dev->dev_private; + int ret, i; + + /* Flush everything onto the inactive list. */ + for (i = 0; i < I915_NUM_RINGS; i++) { +- ret = i915_ring_idle(&dev_priv->ring[i]); ++ ret = i915_ring_idle(&dev_priv->ring[i], do_retire); + if (ret) + return ret; + } +@@ -2248,13 +2195,6 @@ static int sandybridge_write_fence_reg(struct drm_i915_gem_object *obj, + int regnum = obj->fence_reg; + uint64_t val; + +- /* Adjust fence size to match tiled area */ +- if (obj->tiling_mode != I915_TILING_NONE) { +- uint32_t row_size = obj->stride * +- (obj->tiling_mode == I915_TILING_Y ? 32 : 8); +- size = (size / row_size) * row_size; +- } +- + val = (uint64_t)((obj->gtt_offset + size - 4096) & + 0xfffff000) << 32; + val |= obj->gtt_offset & 0xfffff000; +@@ -2292,13 +2232,6 @@ static int i965_write_fence_reg(struct drm_i915_gem_object *obj, + int regnum = obj->fence_reg; + uint64_t val; + +- /* Adjust fence size to match tiled area */ +- if (obj->tiling_mode != I915_TILING_NONE) { +- uint32_t row_size = obj->stride * +- (obj->tiling_mode == I915_TILING_Y ? 32 : 8); +- size = (size / row_size) * row_size; +- } +- + val = (uint64_t)((obj->gtt_offset + size - 4096) & + 0xfffff000) << 32; + val |= obj->gtt_offset & 0xfffff000; +@@ -2448,7 +2381,8 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj, + if (!ring_passed_seqno(obj->last_fenced_ring, + obj->last_fenced_seqno)) { + ret = i915_wait_request(obj->last_fenced_ring, +- obj->last_fenced_seqno); ++ obj->last_fenced_seqno, ++ true); + if (ret) + return ret; + } +@@ -2480,6 +2414,8 @@ i915_gem_object_put_fence(struct drm_i915_gem_object *obj) + + if (obj->fence_reg != I915_FENCE_REG_NONE) { + struct drm_i915_private *dev_priv = obj->base.dev->dev_private; ++ ++ WARN_ON(dev_priv->fence_regs[obj->fence_reg].pin_count); + i915_gem_clear_fence_reg(obj->base.dev, + &dev_priv->fence_regs[obj->fence_reg]); + +@@ -2504,7 +2440,7 @@ i915_find_fence_reg(struct drm_device *dev, + if (!reg->obj) + return reg; + +- if (!reg->obj->pin_count) ++ if (!reg->pin_count) + avail = reg; + } + +@@ -2514,7 +2450,7 @@ i915_find_fence_reg(struct drm_device *dev, + /* None available, try to steal one or wait for a user to finish */ + avail = first = NULL; + list_for_each_entry(reg, &dev_priv->mm.fence_list, lru_list) { +- if (reg->obj->pin_count) ++ if (reg->pin_count) + continue; + + if (first == NULL) +@@ -2594,7 +2530,8 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, + if (!ring_passed_seqno(obj->last_fenced_ring, + reg->setup_seqno)) { + ret = i915_wait_request(obj->last_fenced_ring, +- reg->setup_seqno); ++ reg->setup_seqno, ++ true); + if (ret) + return ret; + } +@@ -2613,7 +2550,7 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, + + reg = i915_find_fence_reg(dev, pipelined); + if (reg == NULL) +- return -ENOSPC; ++ return -EDEADLK; + + ret = i915_gem_object_flush_fence(obj, pipelined); + if (ret) +@@ -2724,6 +2661,7 @@ i915_gem_clear_fence_reg(struct drm_device *dev, + list_del_init(®->lru_list); + reg->obj = NULL; + reg->setup_seqno = 0; ++ reg->pin_count = 0; + } + + /** +@@ -3010,6 +2948,8 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) + int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, + enum i915_cache_level cache_level) + { ++ struct drm_device *dev = obj->base.dev; ++ drm_i915_private_t *dev_priv = dev->dev_private; + int ret; + + if (obj->cache_level == cache_level) +@@ -3038,6 +2978,9 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, + } + + i915_gem_gtt_rebind_object(obj, cache_level); ++ if (obj->has_aliasing_ppgtt_mapping) ++ i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt, ++ obj, cache_level); + } + + if (cache_level == I915_CACHE_NONE) { +@@ -3376,8 +3319,8 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) + + if (ret == 0 && atomic_read(&dev_priv->mm.wedged)) + ret = -EIO; +- } else if (wait_for(i915_seqno_passed(ring->get_seqno(ring), +- seqno) || ++ } else if (wait_for_atomic(i915_seqno_passed(ring->get_seqno(ring), ++ seqno) || + atomic_read(&dev_priv->mm.wedged), 3000)) { + ret = -EBUSY; + } +@@ -3688,8 +3631,8 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, + obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->base.read_domains = I915_GEM_DOMAIN_CPU; + +- if (IS_GEN6(dev) || IS_GEN7(dev)) { +- /* On Gen6, we can have the GPU use the LLC (the CPU ++ if (HAS_LLC(dev)) { ++ /* On some devices, we can have the GPU use the LLC (the CPU + * cache) for about a 10% performance improvement + * compared to uncached. Graphics requests other than + * display scanout are coherent with the CPU in +@@ -3779,7 +3722,7 @@ i915_gem_idle(struct drm_device *dev) + return 0; + } + +- ret = i915_gpu_idle(dev); ++ ret = i915_gpu_idle(dev, true); + if (ret) { + mutex_unlock(&dev->struct_mutex); + return ret; +@@ -3814,12 +3757,91 @@ i915_gem_idle(struct drm_device *dev) + return 0; + } + ++void i915_gem_init_swizzling(struct drm_device *dev) ++{ ++ drm_i915_private_t *dev_priv = dev->dev_private; ++ ++ if (INTEL_INFO(dev)->gen < 5 || ++ dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_NONE) ++ return; ++ ++ I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) | ++ DISP_TILE_SURFACE_SWIZZLING); ++ ++ if (IS_GEN5(dev)) ++ return; ++ ++ I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_SWZCTL); ++ if (IS_GEN6(dev)) ++ I915_WRITE(ARB_MODE, ARB_MODE_ENABLE(ARB_MODE_SWIZZLE_SNB)); ++ else ++ I915_WRITE(ARB_MODE, ARB_MODE_ENABLE(ARB_MODE_SWIZZLE_IVB)); ++} ++ ++void i915_gem_init_ppgtt(struct drm_device *dev) ++{ ++ drm_i915_private_t *dev_priv = dev->dev_private; ++ uint32_t pd_offset; ++ struct intel_ring_buffer *ring; ++ struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; ++ uint32_t __iomem *pd_addr; ++ uint32_t pd_entry; ++ int i; ++ ++ if (!dev_priv->mm.aliasing_ppgtt) ++ return; ++ ++ ++ pd_addr = dev_priv->mm.gtt->gtt + ppgtt->pd_offset/sizeof(uint32_t); ++ for (i = 0; i < ppgtt->num_pd_entries; i++) { ++ dma_addr_t pt_addr; ++ ++ if (dev_priv->mm.gtt->needs_dmar) ++ pt_addr = ppgtt->pt_dma_addr[i]; ++ else ++ pt_addr = page_to_phys(ppgtt->pt_pages[i]); ++ ++ pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr); ++ pd_entry |= GEN6_PDE_VALID; ++ ++ writel(pd_entry, pd_addr + i); ++ } ++ readl(pd_addr); ++ ++ pd_offset = ppgtt->pd_offset; ++ pd_offset /= 64; /* in cachelines, */ ++ pd_offset <<= 16; ++ ++ if (INTEL_INFO(dev)->gen == 6) { ++ uint32_t ecochk = I915_READ(GAM_ECOCHK); ++ I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT | ++ ECOCHK_PPGTT_CACHE64B); ++ I915_WRITE(GFX_MODE, GFX_MODE_ENABLE(GFX_PPGTT_ENABLE)); ++ } else if (INTEL_INFO(dev)->gen >= 7) { ++ I915_WRITE(GAM_ECOCHK, ECOCHK_PPGTT_CACHE64B); ++ /* GFX_MODE is per-ring on gen7+ */ ++ } ++ ++ for (i = 0; i < I915_NUM_RINGS; i++) { ++ ring = &dev_priv->ring[i]; ++ ++ if (INTEL_INFO(dev)->gen >= 7) ++ I915_WRITE(RING_MODE_GEN7(ring), ++ GFX_MODE_ENABLE(GFX_PPGTT_ENABLE)); ++ ++ I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G); ++ I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset); ++ } ++} ++ + int +-i915_gem_init_ringbuffer(struct drm_device *dev) ++i915_gem_init_hw(struct drm_device *dev) + { + drm_i915_private_t *dev_priv = dev->dev_private; + int ret; + ++ i915_gem_init_swizzling(dev); ++ + ret = intel_init_render_ring_buffer(dev); + if (ret) + return ret; +@@ -3838,6 +3860,8 @@ i915_gem_init_ringbuffer(struct drm_device *dev) + + dev_priv->next_seqno = 1; + ++ i915_gem_init_ppgtt(dev); ++ + return 0; + + cleanup_bsd_ring: +@@ -3875,7 +3899,7 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, + mutex_lock(&dev->struct_mutex); + dev_priv->mm.suspended = 0; + +- ret = i915_gem_init_ringbuffer(dev); ++ ret = i915_gem_init_hw(dev); + if (ret != 0) { + mutex_unlock(&dev->struct_mutex); + return ret; +@@ -4270,7 +4294,7 @@ rescan: + * This has a dramatic impact to reduce the number of + * OOM-killer events whilst running the GPU aggressively. + */ +- if (i915_gpu_idle(dev) == 0) ++ if (i915_gpu_idle(dev, true) == 0) + goto rescan; + } + mutex_unlock(&dev->struct_mutex); +diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c +index ead5d00..21a8271 100644 +--- a/drivers/gpu/drm/i915/i915_gem_evict.c ++++ b/drivers/gpu/drm/i915/i915_gem_evict.c +@@ -36,7 +36,6 @@ static bool + mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind) + { + list_add(&obj->exec_list, unwind); +- drm_gem_object_reference(&obj->base); + return drm_mm_scan_add_block(obj->gtt_space); + } + +@@ -49,21 +48,6 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, + struct drm_i915_gem_object *obj; + int ret = 0; + +- i915_gem_retire_requests(dev); +- +- /* Re-check for free space after retiring requests */ +- if (mappable) { +- if (drm_mm_search_free_in_range(&dev_priv->mm.gtt_space, +- min_size, alignment, 0, +- dev_priv->mm.gtt_mappable_end, +- 0)) +- return 0; +- } else { +- if (drm_mm_search_free(&dev_priv->mm.gtt_space, +- min_size, alignment, 0)) +- return 0; +- } +- + trace_i915_gem_evict(dev, min_size, alignment, mappable); + + /* +@@ -139,7 +123,6 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, + BUG_ON(ret); + + list_del_init(&obj->exec_list); +- drm_gem_object_unreference(&obj->base); + } + + /* We expect the caller to unpin, evict all and try again, or give up. +@@ -158,10 +141,10 @@ found: + exec_list); + if (drm_mm_scan_remove_block(obj->gtt_space)) { + list_move(&obj->exec_list, &eviction_list); ++ drm_gem_object_reference(&obj->base); + continue; + } + list_del_init(&obj->exec_list); +- drm_gem_object_unreference(&obj->base); + } + + /* Unbinding will emit any required flushes */ +@@ -195,7 +178,7 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only) + trace_i915_gem_evict_everything(dev, purgeable_only); + + /* Flush everything (on to the inactive lists) and evict */ +- ret = i915_gpu_idle(dev); ++ ret = i915_gpu_idle(dev, true); + if (ret) + return ret; + +diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +index a0b69ae..e97ed61 100644 +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -203,9 +203,9 @@ i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj, + cd->invalidate_domains |= invalidate_domains; + cd->flush_domains |= flush_domains; + if (flush_domains & I915_GEM_GPU_DOMAINS) +- cd->flush_rings |= obj->ring->id; ++ cd->flush_rings |= intel_ring_flag(obj->ring); + if (invalidate_domains & I915_GEM_GPU_DOMAINS) +- cd->flush_rings |= ring->id; ++ cd->flush_rings |= intel_ring_flag(ring); + } + + struct eb_objects { +@@ -303,8 +303,9 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, + reloc->write_domain); + return ret; + } +- if (unlikely((reloc->write_domain | reloc->read_domains) & I915_GEM_DOMAIN_CPU)) { +- DRM_DEBUG("reloc with read/write CPU domains: " ++ if (unlikely((reloc->write_domain | reloc->read_domains) ++ & ~I915_GEM_GPU_DOMAINS)) { ++ DRM_DEBUG("reloc with read/write non-GPU domains: " + "obj %p target %d offset %d " + "read %08x write %08x", + obj, reloc->target_handle, +@@ -461,11 +462,60 @@ i915_gem_execbuffer_relocate(struct drm_device *dev, + return ret; + } + ++#define __EXEC_OBJECT_HAS_FENCE (1<<31) ++ ++static int ++pin_and_fence_object(struct drm_i915_gem_object *obj, ++ struct intel_ring_buffer *ring) ++{ ++ struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; ++ bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; ++ bool need_fence, need_mappable; ++ int ret; ++ ++ need_fence = ++ has_fenced_gpu_access && ++ entry->flags & EXEC_OBJECT_NEEDS_FENCE && ++ obj->tiling_mode != I915_TILING_NONE; ++ need_mappable = ++ entry->relocation_count ? true : need_fence; ++ ++ ret = i915_gem_object_pin(obj, entry->alignment, need_mappable); ++ if (ret) ++ return ret; ++ ++ if (has_fenced_gpu_access) { ++ if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) { ++ if (obj->tiling_mode) { ++ ret = i915_gem_object_get_fence(obj, ring); ++ if (ret) ++ goto err_unpin; ++ ++ entry->flags |= __EXEC_OBJECT_HAS_FENCE; ++ i915_gem_object_pin_fence(obj); ++ } else { ++ ret = i915_gem_object_put_fence(obj); ++ if (ret) ++ goto err_unpin; ++ } ++ obj->pending_fenced_gpu_access = true; ++ } ++ } ++ ++ entry->offset = obj->gtt_offset; ++ return 0; ++ ++err_unpin: ++ i915_gem_object_unpin(obj); ++ return ret; ++} ++ + static int + i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, + struct drm_file *file, + struct list_head *objects) + { ++ drm_i915_private_t *dev_priv = ring->dev->dev_private; + struct drm_i915_gem_object *obj; + int ret, retry; + bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; +@@ -518,6 +568,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, + list_for_each_entry(obj, objects, exec_list) { + struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; + bool need_fence, need_mappable; ++ + if (!obj->gtt_space) + continue; + +@@ -532,59 +583,55 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, + (need_mappable && !obj->map_and_fenceable)) + ret = i915_gem_object_unbind(obj); + else +- ret = i915_gem_object_pin(obj, +- entry->alignment, +- need_mappable); ++ ret = pin_and_fence_object(obj, ring); + if (ret) + goto err; +- +- entry++; + } + + /* Bind fresh objects */ + list_for_each_entry(obj, objects, exec_list) { +- struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; +- bool need_fence; ++ if (obj->gtt_space) ++ continue; + +- need_fence = +- has_fenced_gpu_access && +- entry->flags & EXEC_OBJECT_NEEDS_FENCE && +- obj->tiling_mode != I915_TILING_NONE; ++ ret = pin_and_fence_object(obj, ring); ++ if (ret) { ++ int ret_ignore; ++ ++ /* This can potentially raise a harmless ++ * -EINVAL if we failed to bind in the above ++ * call. It cannot raise -EINTR since we know ++ * that the bo is freshly bound and so will ++ * not need to be flushed or waited upon. ++ */ ++ ret_ignore = i915_gem_object_unbind(obj); ++ (void)ret_ignore; ++ WARN_ON(obj->gtt_space); ++ break; ++ } ++ } + +- if (!obj->gtt_space) { +- bool need_mappable = +- entry->relocation_count ? true : need_fence; ++ /* Decrement pin count for bound objects */ ++ list_for_each_entry(obj, objects, exec_list) { ++ struct drm_i915_gem_exec_object2 *entry; + +- ret = i915_gem_object_pin(obj, +- entry->alignment, +- need_mappable); +- if (ret) +- break; +- } ++ if (!obj->gtt_space) ++ continue; + +- if (has_fenced_gpu_access) { +- if (need_fence) { +- ret = i915_gem_object_get_fence(obj, ring); +- if (ret) +- break; +- } else if (entry->flags & EXEC_OBJECT_NEEDS_FENCE && +- obj->tiling_mode == I915_TILING_NONE) { +- /* XXX pipelined! */ +- ret = i915_gem_object_put_fence(obj); +- if (ret) +- break; +- } +- obj->pending_fenced_gpu_access = +- !!(entry->flags & EXEC_OBJECT_NEEDS_FENCE); ++ entry = obj->exec_entry; ++ if (entry->flags & __EXEC_OBJECT_HAS_FENCE) { ++ i915_gem_object_unpin_fence(obj); ++ entry->flags &= ~__EXEC_OBJECT_HAS_FENCE; + } + +- entry->offset = obj->gtt_offset; +- } ++ i915_gem_object_unpin(obj); + +- /* Decrement pin count for bound objects */ +- list_for_each_entry(obj, objects, exec_list) { +- if (obj->gtt_space) +- i915_gem_object_unpin(obj); ++ /* ... and ensure ppgtt mapping exist if needed. */ ++ if (dev_priv->mm.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) { ++ i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt, ++ obj, obj->cache_level); ++ ++ obj->has_aliasing_ppgtt_mapping = 1; ++ } + } + + if (ret != -ENOSPC || retry > 1) +@@ -601,16 +648,19 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, + } while (1); + + err: +- obj = list_entry(obj->exec_list.prev, +- struct drm_i915_gem_object, +- exec_list); +- while (objects != &obj->exec_list) { +- if (obj->gtt_space) +- i915_gem_object_unpin(obj); ++ list_for_each_entry_continue_reverse(obj, objects, exec_list) { ++ struct drm_i915_gem_exec_object2 *entry; + +- obj = list_entry(obj->exec_list.prev, +- struct drm_i915_gem_object, +- exec_list); ++ if (!obj->gtt_space) ++ continue; ++ ++ entry = obj->exec_entry; ++ if (entry->flags & __EXEC_OBJECT_HAS_FENCE) { ++ i915_gem_object_unpin_fence(obj); ++ entry->flags &= ~__EXEC_OBJECT_HAS_FENCE; ++ } ++ ++ i915_gem_object_unpin(obj); + } + + return ret; +@@ -679,9 +729,9 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, + * relocations were valid. + */ + for (j = 0; j < exec[i].relocation_count; j++) { +- if (__copy_to_user(&user_relocs[j].presumed_offset, +- &invalid_offset, +- sizeof(invalid_offset))) { ++ if (copy_to_user(&user_relocs[j].presumed_offset, ++ &invalid_offset, ++ sizeof(invalid_offset))) { + ret = -EFAULT; + mutex_lock(&dev->struct_mutex); + goto err; +@@ -998,6 +1048,31 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev, + } + + static int ++i915_reset_gen7_sol_offsets(struct drm_device *dev, ++ struct intel_ring_buffer *ring) ++{ ++ drm_i915_private_t *dev_priv = dev->dev_private; ++ int ret, i; ++ ++ if (!IS_GEN7(dev) || ring != &dev_priv->ring[RCS]) ++ return 0; ++ ++ ret = intel_ring_begin(ring, 4 * 3); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < 4; i++) { ++ intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); ++ intel_ring_emit(ring, GEN7_SO_WRITE_OFFSET(i)); ++ intel_ring_emit(ring, 0); ++ } ++ ++ intel_ring_advance(ring); ++ ++ return 0; ++} ++ ++static int + i915_gem_do_execbuffer(struct drm_device *dev, void *data, + struct drm_file *file, + struct drm_i915_gem_execbuffer2 *args, +@@ -1193,7 +1268,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, + * so every billion or so execbuffers, we need to stall + * the GPU in order to reset the counters. + */ +- ret = i915_gpu_idle(dev); ++ ret = i915_gpu_idle(dev, true); + if (ret) + goto err; + +@@ -1216,6 +1291,12 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, + dev_priv->relative_constants_mode = mode; + } + ++ if (args->flags & I915_EXEC_GEN7_SOL_RESET) { ++ ret = i915_reset_gen7_sol_offsets(dev, ring); ++ if (ret) ++ goto err; ++ } ++ + trace_i915_gem_ring_dispatch(ring, seqno); + + exec_start = batch_obj->gtt_offset + args->batch_start_offset; +@@ -1325,21 +1406,19 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, + + ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); + if (!ret) { +- struct drm_i915_gem_exec_object __user *user_exec_list = +- (void __user *)(uintptr_t)args->buffers_ptr; +- + /* Copy the new buffer offsets back to the user's exec list. */ +- for (i = 0; i < args->buffer_count; i++) { +- ret = __copy_to_user(&user_exec_list[i].offset, +- &exec2_list[i].offset, +- sizeof(user_exec_list[i].offset)); +- if (ret) { +- ret = -EFAULT; +- DRM_DEBUG("failed to copy %d exec entries " +- "back to user (%d)\n", +- args->buffer_count, ret); +- break; +- } ++ for (i = 0; i < args->buffer_count; i++) ++ exec_list[i].offset = exec2_list[i].offset; ++ /* ... and back out to userspace */ ++ ret = copy_to_user((struct drm_i915_relocation_entry __user *) ++ (uintptr_t) args->buffers_ptr, ++ exec_list, ++ sizeof(*exec_list) * args->buffer_count); ++ if (ret) { ++ ret = -EFAULT; ++ DRM_DEBUG("failed to copy %d exec entries " ++ "back to user (%d)\n", ++ args->buffer_count, ret); + } + } + +@@ -1386,21 +1465,15 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, + ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list); + if (!ret) { + /* Copy the new buffer offsets back to the user's exec list. */ +- struct drm_i915_gem_exec_object2 __user *user_exec_list = +- (void __user *)(uintptr_t)args->buffers_ptr; +- int i; +- +- for (i = 0; i < args->buffer_count; i++) { +- ret = __copy_to_user(&user_exec_list[i].offset, +- &exec2_list[i].offset, +- sizeof(user_exec_list[i].offset)); +- if (ret) { +- ret = -EFAULT; +- DRM_DEBUG("failed to copy %d exec entries " +- "back to user\n", +- args->buffer_count); +- break; +- } ++ ret = copy_to_user((struct drm_i915_relocation_entry __user *) ++ (uintptr_t) args->buffers_ptr, ++ exec2_list, ++ sizeof(*exec2_list) * args->buffer_count); ++ if (ret) { ++ ret = -EFAULT; ++ DRM_DEBUG("failed to copy %d exec entries " ++ "back to user (%d)\n", ++ args->buffer_count, ret); + } + } + +diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c +index 6042c5e..99a7855 100644 +--- a/drivers/gpu/drm/i915/i915_gem_gtt.c ++++ b/drivers/gpu/drm/i915/i915_gem_gtt.c +@@ -29,6 +29,270 @@ + #include "i915_trace.h" + #include "intel_drv.h" + ++/* PPGTT support for Sandybdrige/Gen6 and later */ ++static void i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt, ++ unsigned first_entry, ++ unsigned num_entries) ++{ ++ uint32_t *pt_vaddr; ++ uint32_t scratch_pte; ++ unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES; ++ unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; ++ unsigned last_pte, i; ++ ++ scratch_pte = GEN6_PTE_ADDR_ENCODE(ppgtt->scratch_page_dma_addr); ++ scratch_pte |= GEN6_PTE_VALID | GEN6_PTE_CACHE_LLC; ++ ++ while (num_entries) { ++ last_pte = first_pte + num_entries; ++ if (last_pte > I915_PPGTT_PT_ENTRIES) ++ last_pte = I915_PPGTT_PT_ENTRIES; ++ ++ pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]); ++ ++ for (i = first_pte; i < last_pte; i++) ++ pt_vaddr[i] = scratch_pte; ++ ++ kunmap_atomic(pt_vaddr); ++ ++ num_entries -= last_pte - first_pte; ++ first_pte = 0; ++ act_pd++; ++ } ++} ++ ++int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) ++{ ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct i915_hw_ppgtt *ppgtt; ++ unsigned first_pd_entry_in_global_pt; ++ int i; ++ int ret = -ENOMEM; ++ ++ /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 ++ * entries. For aliasing ppgtt support we just steal them at the end for ++ * now. */ ++ first_pd_entry_in_global_pt = dev_priv->mm.gtt->gtt_total_entries - I915_PPGTT_PD_ENTRIES; ++ ++ ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); ++ if (!ppgtt) ++ return ret; ++ ++ ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES; ++ ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries, ++ GFP_KERNEL); ++ if (!ppgtt->pt_pages) ++ goto err_ppgtt; ++ ++ for (i = 0; i < ppgtt->num_pd_entries; i++) { ++ ppgtt->pt_pages[i] = alloc_page(GFP_KERNEL); ++ if (!ppgtt->pt_pages[i]) ++ goto err_pt_alloc; ++ } ++ ++ if (dev_priv->mm.gtt->needs_dmar) { ++ ppgtt->pt_dma_addr = kzalloc(sizeof(dma_addr_t) ++ *ppgtt->num_pd_entries, ++ GFP_KERNEL); ++ if (!ppgtt->pt_dma_addr) ++ goto err_pt_alloc; ++ } ++ ++ for (i = 0; i < ppgtt->num_pd_entries; i++) { ++ dma_addr_t pt_addr; ++ if (dev_priv->mm.gtt->needs_dmar) { ++ pt_addr = pci_map_page(dev->pdev, ppgtt->pt_pages[i], ++ 0, 4096, ++ PCI_DMA_BIDIRECTIONAL); ++ ++ if (pci_dma_mapping_error(dev->pdev, ++ pt_addr)) { ++ ret = -EIO; ++ goto err_pd_pin; ++ ++ } ++ ppgtt->pt_dma_addr[i] = pt_addr; ++ } else ++ pt_addr = page_to_phys(ppgtt->pt_pages[i]); ++ } ++ ++ ppgtt->scratch_page_dma_addr = dev_priv->mm.gtt->scratch_page_dma; ++ ++ i915_ppgtt_clear_range(ppgtt, 0, ++ ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES); ++ ++ ppgtt->pd_offset = (first_pd_entry_in_global_pt)*sizeof(uint32_t); ++ ++ dev_priv->mm.aliasing_ppgtt = ppgtt; ++ ++ return 0; ++ ++err_pd_pin: ++ if (ppgtt->pt_dma_addr) { ++ for (i--; i >= 0; i--) ++ pci_unmap_page(dev->pdev, ppgtt->pt_dma_addr[i], ++ 4096, PCI_DMA_BIDIRECTIONAL); ++ } ++err_pt_alloc: ++ kfree(ppgtt->pt_dma_addr); ++ for (i = 0; i < ppgtt->num_pd_entries; i++) { ++ if (ppgtt->pt_pages[i]) ++ __free_page(ppgtt->pt_pages[i]); ++ } ++ kfree(ppgtt->pt_pages); ++err_ppgtt: ++ kfree(ppgtt); ++ ++ return ret; ++} ++ ++void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev) ++{ ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; ++ int i; ++ ++ if (!ppgtt) ++ return; ++ ++ if (ppgtt->pt_dma_addr) { ++ for (i = 0; i < ppgtt->num_pd_entries; i++) ++ pci_unmap_page(dev->pdev, ppgtt->pt_dma_addr[i], ++ 4096, PCI_DMA_BIDIRECTIONAL); ++ } ++ ++ kfree(ppgtt->pt_dma_addr); ++ for (i = 0; i < ppgtt->num_pd_entries; i++) ++ __free_page(ppgtt->pt_pages[i]); ++ kfree(ppgtt->pt_pages); ++ kfree(ppgtt); ++} ++ ++static void i915_ppgtt_insert_sg_entries(struct i915_hw_ppgtt *ppgtt, ++ struct scatterlist *sg_list, ++ unsigned sg_len, ++ unsigned first_entry, ++ uint32_t pte_flags) ++{ ++ uint32_t *pt_vaddr, pte; ++ unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES; ++ unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; ++ unsigned i, j, m, segment_len; ++ dma_addr_t page_addr; ++ struct scatterlist *sg; ++ ++ /* init sg walking */ ++ sg = sg_list; ++ i = 0; ++ segment_len = sg_dma_len(sg) >> PAGE_SHIFT; ++ m = 0; ++ ++ while (i < sg_len) { ++ pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]); ++ ++ for (j = first_pte; j < I915_PPGTT_PT_ENTRIES; j++) { ++ page_addr = sg_dma_address(sg) + (m << PAGE_SHIFT); ++ pte = GEN6_PTE_ADDR_ENCODE(page_addr); ++ pt_vaddr[j] = pte | pte_flags; ++ ++ /* grab the next page */ ++ m++; ++ if (m == segment_len) { ++ sg = sg_next(sg); ++ i++; ++ if (i == sg_len) ++ break; ++ ++ segment_len = sg_dma_len(sg) >> PAGE_SHIFT; ++ m = 0; ++ } ++ } ++ ++ kunmap_atomic(pt_vaddr); ++ ++ first_pte = 0; ++ act_pd++; ++ } ++} ++ ++static void i915_ppgtt_insert_pages(struct i915_hw_ppgtt *ppgtt, ++ unsigned first_entry, unsigned num_entries, ++ struct page **pages, uint32_t pte_flags) ++{ ++ uint32_t *pt_vaddr, pte; ++ unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES; ++ unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; ++ unsigned last_pte, i; ++ dma_addr_t page_addr; ++ ++ while (num_entries) { ++ last_pte = first_pte + num_entries; ++ last_pte = min_t(unsigned, last_pte, I915_PPGTT_PT_ENTRIES); ++ ++ pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]); ++ ++ for (i = first_pte; i < last_pte; i++) { ++ page_addr = page_to_phys(*pages); ++ pte = GEN6_PTE_ADDR_ENCODE(page_addr); ++ pt_vaddr[i] = pte | pte_flags; ++ ++ pages++; ++ } ++ ++ kunmap_atomic(pt_vaddr); ++ ++ num_entries -= last_pte - first_pte; ++ first_pte = 0; ++ act_pd++; ++ } ++} ++ ++void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, ++ struct drm_i915_gem_object *obj, ++ enum i915_cache_level cache_level) ++{ ++ struct drm_device *dev = obj->base.dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ uint32_t pte_flags = GEN6_PTE_VALID; ++ ++ switch (cache_level) { ++ case I915_CACHE_LLC_MLC: ++ pte_flags |= GEN6_PTE_CACHE_LLC_MLC; ++ break; ++ case I915_CACHE_LLC: ++ pte_flags |= GEN6_PTE_CACHE_LLC; ++ break; ++ case I915_CACHE_NONE: ++ pte_flags |= GEN6_PTE_UNCACHED; ++ break; ++ default: ++ BUG(); ++ } ++ ++ if (dev_priv->mm.gtt->needs_dmar) { ++ BUG_ON(!obj->sg_list); ++ ++ i915_ppgtt_insert_sg_entries(ppgtt, ++ obj->sg_list, ++ obj->num_sg, ++ obj->gtt_space->start >> PAGE_SHIFT, ++ pte_flags); ++ } else ++ i915_ppgtt_insert_pages(ppgtt, ++ obj->gtt_space->start >> PAGE_SHIFT, ++ obj->base.size >> PAGE_SHIFT, ++ obj->pages, ++ pte_flags); ++} ++ ++void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, ++ struct drm_i915_gem_object *obj) ++{ ++ i915_ppgtt_clear_range(ppgtt, ++ obj->gtt_space->start >> PAGE_SHIFT, ++ obj->base.size >> PAGE_SHIFT); ++} ++ + /* XXX kill agp_type! */ + static unsigned int cache_level_to_agp_type(struct drm_device *dev, + enum i915_cache_level cache_level) +@@ -55,7 +319,7 @@ static bool do_idling(struct drm_i915_private *dev_priv) + + if (unlikely(dev_priv->mm.gtt->do_idle_maps)) { + dev_priv->mm.interruptible = false; +- if (i915_gpu_idle(dev_priv->dev)) { ++ if (i915_gpu_idle(dev_priv->dev, false)) { + DRM_ERROR("Couldn't idle GPU\n"); + /* Wait a bit, in hopes it avoids the hang */ + udelay(10); +diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c +index 861223b..1a93066 100644 +--- a/drivers/gpu/drm/i915/i915_gem_tiling.c ++++ b/drivers/gpu/drm/i915/i915_gem_tiling.c +@@ -93,8 +93,23 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) + uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; + + if (INTEL_INFO(dev)->gen >= 6) { +- swizzle_x = I915_BIT_6_SWIZZLE_NONE; +- swizzle_y = I915_BIT_6_SWIZZLE_NONE; ++ uint32_t dimm_c0, dimm_c1; ++ dimm_c0 = I915_READ(MAD_DIMM_C0); ++ dimm_c1 = I915_READ(MAD_DIMM_C1); ++ dimm_c0 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK; ++ dimm_c1 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK; ++ /* Enable swizzling when the channels are populated with ++ * identically sized dimms. We don't need to check the 3rd ++ * channel because no cpu with gpu attached ships in that ++ * configuration. Also, swizzling only makes sense for 2 ++ * channels anyway. */ ++ if (dimm_c0 == dimm_c1) { ++ swizzle_x = I915_BIT_6_SWIZZLE_9_10; ++ swizzle_y = I915_BIT_6_SWIZZLE_9; ++ } else { ++ swizzle_x = I915_BIT_6_SWIZZLE_NONE; ++ swizzle_y = I915_BIT_6_SWIZZLE_NONE; ++ } + } else if (IS_GEN5(dev)) { + /* On Ironlake whatever DRAM config, GPU always do + * same swizzling setup. +diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c +index 93e74fb..c8d88a6 100644 +--- a/drivers/gpu/drm/i915/i915_irq.c ++++ b/drivers/gpu/drm/i915/i915_irq.c +@@ -716,7 +716,6 @@ i915_error_object_create(struct drm_i915_private *dev_priv, + reloc_offset = src->gtt_offset; + for (page = 0; page < page_count; page++) { + unsigned long flags; +- void __iomem *s; + void *d; + + d = kmalloc(PAGE_SIZE, GFP_ATOMIC); +@@ -724,10 +723,29 @@ i915_error_object_create(struct drm_i915_private *dev_priv, + goto unwind; + + local_irq_save(flags); +- s = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, +- reloc_offset); +- memcpy_fromio(d, s, PAGE_SIZE); +- io_mapping_unmap_atomic(s); ++ if (reloc_offset < dev_priv->mm.gtt_mappable_end) { ++ void __iomem *s; ++ ++ /* Simply ignore tiling or any overlapping fence. ++ * It's part of the error state, and this hopefully ++ * captures what the GPU read. ++ */ ++ ++ s = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, ++ reloc_offset); ++ memcpy_fromio(d, s, PAGE_SIZE); ++ io_mapping_unmap_atomic(s); ++ } else { ++ void *s; ++ ++ drm_clflush_pages(&src->pages[page], 1); ++ ++ s = kmap_atomic(src->pages[page]); ++ memcpy(d, s, PAGE_SIZE); ++ kunmap_atomic(s); ++ ++ drm_clflush_pages(&src->pages[page], 1); ++ } + local_irq_restore(flags); + + dst->pages[page] = d; +@@ -766,11 +784,11 @@ i915_error_state_free(struct drm_device *dev, + { + int i; + +- for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) +- i915_error_object_free(error->batchbuffer[i]); +- +- for (i = 0; i < ARRAY_SIZE(error->ringbuffer); i++) +- i915_error_object_free(error->ringbuffer[i]); ++ for (i = 0; i < ARRAY_SIZE(error->ring); i++) { ++ i915_error_object_free(error->ring[i].batchbuffer); ++ i915_error_object_free(error->ring[i].ringbuffer); ++ kfree(error->ring[i].requests); ++ } + + kfree(error->active_bo); + kfree(error->overlay); +@@ -800,7 +818,7 @@ static u32 capture_bo_list(struct drm_i915_error_buffer *err, + err->tiling = obj->tiling_mode; + err->dirty = obj->dirty; + err->purgeable = obj->madv != I915_MADV_WILLNEED; +- err->ring = obj->ring ? obj->ring->id : 0; ++ err->ring = obj->ring ? obj->ring->id : -1; + err->cache_level = obj->cache_level; + + if (++i == count) +@@ -872,6 +890,92 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv, + return NULL; + } + ++static void i915_record_ring_state(struct drm_device *dev, ++ struct drm_i915_error_state *error, ++ struct intel_ring_buffer *ring) ++{ ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ ++ if (INTEL_INFO(dev)->gen >= 6) { ++ error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base)); ++ error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring)); ++ error->semaphore_mboxes[ring->id][0] ++ = I915_READ(RING_SYNC_0(ring->mmio_base)); ++ error->semaphore_mboxes[ring->id][1] ++ = I915_READ(RING_SYNC_1(ring->mmio_base)); ++ } ++ ++ if (INTEL_INFO(dev)->gen >= 4) { ++ error->ipeir[ring->id] = I915_READ(RING_IPEIR(ring->mmio_base)); ++ error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base)); ++ error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base)); ++ error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base)); ++ if (ring->id == RCS) { ++ error->instdone1 = I915_READ(INSTDONE1); ++ error->bbaddr = I915_READ64(BB_ADDR); ++ } ++ } else { ++ error->ipeir[ring->id] = I915_READ(IPEIR); ++ error->ipehr[ring->id] = I915_READ(IPEHR); ++ error->instdone[ring->id] = I915_READ(INSTDONE); ++ } ++ ++ error->instpm[ring->id] = I915_READ(RING_INSTPM(ring->mmio_base)); ++ error->seqno[ring->id] = ring->get_seqno(ring); ++ error->acthd[ring->id] = intel_ring_get_active_head(ring); ++ error->head[ring->id] = I915_READ_HEAD(ring); ++ error->tail[ring->id] = I915_READ_TAIL(ring); ++ ++ error->cpu_ring_head[ring->id] = ring->head; ++ error->cpu_ring_tail[ring->id] = ring->tail; ++} ++ ++static void i915_gem_record_rings(struct drm_device *dev, ++ struct drm_i915_error_state *error) ++{ ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct drm_i915_gem_request *request; ++ int i, count; ++ ++ for (i = 0; i < I915_NUM_RINGS; i++) { ++ struct intel_ring_buffer *ring = &dev_priv->ring[i]; ++ ++ if (ring->obj == NULL) ++ continue; ++ ++ i915_record_ring_state(dev, error, ring); ++ ++ error->ring[i].batchbuffer = ++ i915_error_first_batchbuffer(dev_priv, ring); ++ ++ error->ring[i].ringbuffer = ++ i915_error_object_create(dev_priv, ring->obj); ++ ++ count = 0; ++ list_for_each_entry(request, &ring->request_list, list) ++ count++; ++ ++ error->ring[i].num_requests = count; ++ error->ring[i].requests = ++ kmalloc(count*sizeof(struct drm_i915_error_request), ++ GFP_ATOMIC); ++ if (error->ring[i].requests == NULL) { ++ error->ring[i].num_requests = 0; ++ continue; ++ } ++ ++ count = 0; ++ list_for_each_entry(request, &ring->request_list, list) { ++ struct drm_i915_error_request *erq; ++ ++ erq = &error->ring[i].requests[count++]; ++ erq->seqno = request->seqno; ++ erq->jiffies = request->emitted_jiffies; ++ erq->tail = request->tail; ++ } ++ } ++} ++ + /** + * i915_capture_error_state - capture an error record for later analysis + * @dev: drm device +@@ -896,7 +1000,7 @@ static void i915_capture_error_state(struct drm_device *dev) + return; + + /* Account for pipe specific data like PIPE*STAT */ +- error = kmalloc(sizeof(*error), GFP_ATOMIC); ++ error = kzalloc(sizeof(*error), GFP_ATOMIC); + if (!error) { + DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); + return; +@@ -905,59 +1009,18 @@ static void i915_capture_error_state(struct drm_device *dev) + DRM_INFO("capturing error event; look for more information in /debug/dri/%d/i915_error_state\n", + dev->primary->index); + +- error->seqno = dev_priv->ring[RCS].get_seqno(&dev_priv->ring[RCS]); + error->eir = I915_READ(EIR); + error->pgtbl_er = I915_READ(PGTBL_ER); + for_each_pipe(pipe) + error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); +- error->instpm = I915_READ(INSTPM); +- error->error = 0; ++ + if (INTEL_INFO(dev)->gen >= 6) { + error->error = I915_READ(ERROR_GEN6); +- +- error->bcs_acthd = I915_READ(BCS_ACTHD); +- error->bcs_ipehr = I915_READ(BCS_IPEHR); +- error->bcs_ipeir = I915_READ(BCS_IPEIR); +- error->bcs_instdone = I915_READ(BCS_INSTDONE); +- error->bcs_seqno = 0; +- if (dev_priv->ring[BCS].get_seqno) +- error->bcs_seqno = dev_priv->ring[BCS].get_seqno(&dev_priv->ring[BCS]); +- +- error->vcs_acthd = I915_READ(VCS_ACTHD); +- error->vcs_ipehr = I915_READ(VCS_IPEHR); +- error->vcs_ipeir = I915_READ(VCS_IPEIR); +- error->vcs_instdone = I915_READ(VCS_INSTDONE); +- error->vcs_seqno = 0; +- if (dev_priv->ring[VCS].get_seqno) +- error->vcs_seqno = dev_priv->ring[VCS].get_seqno(&dev_priv->ring[VCS]); +- } +- if (INTEL_INFO(dev)->gen >= 4) { +- error->ipeir = I915_READ(IPEIR_I965); +- error->ipehr = I915_READ(IPEHR_I965); +- error->instdone = I915_READ(INSTDONE_I965); +- error->instps = I915_READ(INSTPS); +- error->instdone1 = I915_READ(INSTDONE1); +- error->acthd = I915_READ(ACTHD_I965); +- error->bbaddr = I915_READ64(BB_ADDR); +- } else { +- error->ipeir = I915_READ(IPEIR); +- error->ipehr = I915_READ(IPEHR); +- error->instdone = I915_READ(INSTDONE); +- error->acthd = I915_READ(ACTHD); +- error->bbaddr = 0; ++ error->done_reg = I915_READ(DONE_REG); + } +- i915_gem_record_fences(dev, error); + +- /* Record the active batch and ring buffers */ +- for (i = 0; i < I915_NUM_RINGS; i++) { +- error->batchbuffer[i] = +- i915_error_first_batchbuffer(dev_priv, +- &dev_priv->ring[i]); +- +- error->ringbuffer[i] = +- i915_error_object_create(dev_priv, +- dev_priv->ring[i].obj); +- } ++ i915_gem_record_fences(dev, error); ++ i915_gem_record_rings(dev, error); + + /* Record buffers on the active and pinned lists. */ + error->active_bo = NULL; +@@ -1013,11 +1076,12 @@ void i915_destroy_error_state(struct drm_device *dev) + { + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_error_state *error; ++ unsigned long flags; + +- spin_lock(&dev_priv->error_lock); ++ spin_lock_irqsave(&dev_priv->error_lock, flags); + error = dev_priv->first_error; + dev_priv->first_error = NULL; +- spin_unlock(&dev_priv->error_lock); ++ spin_unlock_irqrestore(&dev_priv->error_lock, flags); + + if (error) + i915_error_state_free(dev, error); +@@ -1203,7 +1267,7 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) + } else { + int dspaddr = DSPADDR(intel_crtc->plane); + stall_detected = I915_READ(dspaddr) == (obj->gtt_offset + +- crtc->y * crtc->fb->pitch + ++ crtc->y * crtc->fb->pitches[0] + + crtc->x * crtc->fb->bits_per_pixel/8); + } + +@@ -1647,13 +1711,6 @@ static bool kick_ring(struct intel_ring_buffer *ring) + I915_WRITE_CTL(ring, tmp); + return true; + } +- if (IS_GEN6(dev) && +- (tmp & RING_WAIT_SEMAPHORE)) { +- DRM_ERROR("Kicking stuck semaphore on %s\n", +- ring->name); +- I915_WRITE_CTL(ring, tmp); +- return true; +- } + return false; + } + +@@ -1703,6 +1760,7 @@ void i915_hangcheck_elapsed(unsigned long data) + dev_priv->last_instdone1 == instdone1) { + if (dev_priv->hangcheck_count++ > 1) { + DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); ++ i915_handle_error(dev, true); + + if (!IS_GEN2(dev)) { + /* Is the chip hanging on a WAIT_FOR_EVENT? +@@ -1710,7 +1768,6 @@ void i915_hangcheck_elapsed(unsigned long data) + * and break the hang. This should work on + * all but the second generation chipsets. + */ +- + if (kick_ring(&dev_priv->ring[RCS])) + goto repeat; + +@@ -1723,7 +1780,6 @@ void i915_hangcheck_elapsed(unsigned long data) + goto repeat; + } + +- i915_handle_error(dev, true); + return; + } + } else { +@@ -1750,23 +1806,8 @@ static void ironlake_irq_preinstall(struct drm_device *dev) + + atomic_set(&dev_priv->irq_received, 0); + +- INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); +- INIT_WORK(&dev_priv->error_work, i915_error_work_func); +- if (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) +- INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); + + I915_WRITE(HWSTAM, 0xeffe); +- if (IS_GEN6(dev) || IS_GEN7(dev)) { +- /* Workaround stalls observed on Sandy Bridge GPUs by +- * making the blitter command streamer generate a +- * write to the Hardware Status Page for +- * MI_USER_INTERRUPT. This appears to serialize the +- * previous seqno write out before the interrupt +- * happens. +- */ +- I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT); +- I915_WRITE(GEN6_BSD_HWSTAM, ~GEN6_BSD_USER_INTERRUPT); +- } + + /* XXX hotplug from PCH */ + +@@ -1938,9 +1979,6 @@ static void i915_driver_irq_preinstall(struct drm_device * dev) + + atomic_set(&dev_priv->irq_received, 0); + +- INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); +- INIT_WORK(&dev_priv->error_work, i915_error_work_func); +- + if (I915_HAS_HOTPLUG(dev)) { + I915_WRITE(PORT_HOTPLUG_EN, 0); + I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); +@@ -2097,8 +2135,160 @@ static void i915_driver_irq_uninstall(struct drm_device * dev) + I915_WRITE(IIR, I915_READ(IIR)); + } + ++static void i8xx_irq_preinstall(struct drm_device * dev) ++{ ++ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; ++ int pipe; ++ ++ atomic_set(&dev_priv->irq_received, 0); ++ ++ for_each_pipe(pipe) ++ I915_WRITE(PIPESTAT(pipe), 0); ++ I915_WRITE16(IMR, 0xffff); ++ I915_WRITE16(IER, 0x0); ++ POSTING_READ16(IER); ++} ++ ++static int i8xx_irq_postinstall(struct drm_device *dev) ++{ ++ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; ++ ++ dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; ++ ++ dev_priv->pipestat[0] = 0; ++ dev_priv->pipestat[1] = 0; ++ ++ I915_WRITE16(EMR, ++ ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH)); ++ ++ /* Unmask the interrupts that we always want on. */ ++ dev_priv->irq_mask = ++ ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | ++ I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | ++ I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | ++ I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT | ++ I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); ++ I915_WRITE16(IMR, dev_priv->irq_mask); ++ ++ I915_WRITE16(IER, ++ I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | ++ I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | ++ I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT | ++ I915_USER_INTERRUPT); ++ POSTING_READ16(IER); ++ ++ return 0; ++} ++ ++static irqreturn_t i8xx_irq_handler(DRM_IRQ_ARGS) ++{ ++ struct drm_device *dev = (struct drm_device *) arg; ++ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; ++ struct drm_i915_master_private *master_priv; ++ u16 iir, new_iir; ++ u32 pipe_stats[2]; ++ unsigned long irqflags; ++ int irq_received; ++ int pipe; ++ u16 flip_mask = ++ I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | ++ I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT; ++ ++ atomic_inc(&dev_priv->irq_received); ++ ++ iir = I915_READ16(IIR); ++ if (iir == 0) ++ return IRQ_NONE; ++ ++ while (iir & ~flip_mask) { ++ /* Can't rely on pipestat interrupt bit in iir as it might ++ * have been cleared after the pipestat interrupt was received. ++ * It doesn't set the bit in iir again, but it still produces ++ * interrupts (for non-MSI). ++ */ ++ spin_lock_irqsave(&dev_priv->irq_lock, irqflags); ++ if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) ++ i915_handle_error(dev, false); ++ ++ for_each_pipe(pipe) { ++ int reg = PIPESTAT(pipe); ++ pipe_stats[pipe] = I915_READ(reg); ++ ++ /* ++ * Clear the PIPE*STAT regs before the IIR ++ */ ++ if (pipe_stats[pipe] & 0x8000ffff) { ++ if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) ++ DRM_DEBUG_DRIVER("pipe %c underrun\n", ++ pipe_name(pipe)); ++ I915_WRITE(reg, pipe_stats[pipe]); ++ irq_received = 1; ++ } ++ } ++ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); ++ ++ I915_WRITE16(IIR, iir & ~flip_mask); ++ new_iir = I915_READ16(IIR); /* Flush posted writes */ ++ ++ if (dev->primary->master) { ++ master_priv = dev->primary->master->driver_priv; ++ if (master_priv->sarea_priv) ++ master_priv->sarea_priv->last_dispatch = ++ READ_BREADCRUMB(dev_priv); ++ } ++ ++ if (iir & I915_USER_INTERRUPT) ++ notify_ring(dev, &dev_priv->ring[RCS]); ++ ++ if (pipe_stats[0] & PIPE_VBLANK_INTERRUPT_STATUS && ++ drm_handle_vblank(dev, 0)) { ++ if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) { ++ intel_prepare_page_flip(dev, 0); ++ intel_finish_page_flip(dev, 0); ++ flip_mask &= ~I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT; ++ } ++ } ++ ++ if (pipe_stats[1] & PIPE_VBLANK_INTERRUPT_STATUS && ++ drm_handle_vblank(dev, 1)) { ++ if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) { ++ intel_prepare_page_flip(dev, 1); ++ intel_finish_page_flip(dev, 1); ++ flip_mask &= ~I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT; ++ } ++ } ++ ++ iir = new_iir; ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void i8xx_irq_uninstall(struct drm_device * dev) ++{ ++ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; ++ int pipe; ++ ++ dev_priv->vblank_pipe = 0; ++ ++ for_each_pipe(pipe) { ++ /* Clear enable bits; then clear status bits */ ++ I915_WRITE(PIPESTAT(pipe), 0); ++ I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe))); ++ } ++ I915_WRITE16(IMR, 0xffff); ++ I915_WRITE16(IER, 0x0); ++ I915_WRITE16(IIR, I915_READ16(IIR)); ++} ++ + void intel_irq_init(struct drm_device *dev) + { ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ ++ INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); ++ INIT_WORK(&dev_priv->error_work, i915_error_work_func); ++ INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); ++ + dev->driver->get_vblank_counter = i915_get_vblank_counter; + dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ + if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { +@@ -2128,10 +2318,17 @@ void intel_irq_init(struct drm_device *dev) + dev->driver->enable_vblank = ironlake_enable_vblank; + dev->driver->disable_vblank = ironlake_disable_vblank; + } else { +- dev->driver->irq_preinstall = i915_driver_irq_preinstall; +- dev->driver->irq_postinstall = i915_driver_irq_postinstall; +- dev->driver->irq_uninstall = i915_driver_irq_uninstall; +- dev->driver->irq_handler = i915_driver_irq_handler; ++ if (INTEL_INFO(dev)->gen == 2) { ++ dev->driver->irq_preinstall = i8xx_irq_preinstall; ++ dev->driver->irq_postinstall = i8xx_irq_postinstall; ++ dev->driver->irq_handler = i8xx_irq_handler; ++ dev->driver->irq_uninstall = i8xx_irq_uninstall; ++ } else { ++ dev->driver->irq_preinstall = i915_driver_irq_preinstall; ++ dev->driver->irq_postinstall = i915_driver_irq_postinstall; ++ dev->driver->irq_uninstall = i915_driver_irq_uninstall; ++ dev->driver->irq_handler = i915_driver_irq_handler; ++ } + dev->driver->enable_vblank = i915_enable_vblank; + dev->driver->disable_vblank = i915_disable_vblank; + } +diff --git a/drivers/gpu/drm/i915/i915_mem.c b/drivers/gpu/drm/i915/i915_mem.c +deleted file mode 100644 +index cc8f6d4..0000000 +--- a/drivers/gpu/drm/i915/i915_mem.c ++++ /dev/null +@@ -1,387 +0,0 @@ +-/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*- +- */ +-/* +- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. +- * All Rights Reserved. +- * +- * 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, sub license, 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 (including the +- * next paragraph) 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 NON-INFRINGEMENT. +- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. +- * +- */ +- +-#include "drmP.h" +-#include "drm.h" +-#include "i915_drm.h" +-#include "i915_drv.h" +- +-/* This memory manager is integrated into the global/local lru +- * mechanisms used by the clients. Specifically, it operates by +- * setting the 'in_use' fields of the global LRU to indicate whether +- * this region is privately allocated to a client. +- * +- * This does require the client to actually respect that field. +- * +- * Currently no effort is made to allocate 'private' memory in any +- * clever way - the LRU information isn't used to determine which +- * block to allocate, and the ring is drained prior to allocations -- +- * in other words allocation is expensive. +- */ +-static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use) +-{ +- drm_i915_private_t *dev_priv = dev->dev_private; +- struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; +- drm_i915_sarea_t *sarea_priv = master_priv->sarea_priv; +- struct drm_tex_region *list; +- unsigned shift, nr; +- unsigned start; +- unsigned end; +- unsigned i; +- int age; +- +- shift = dev_priv->tex_lru_log_granularity; +- nr = I915_NR_TEX_REGIONS; +- +- start = p->start >> shift; +- end = (p->start + p->size - 1) >> shift; +- +- age = ++sarea_priv->texAge; +- list = sarea_priv->texList; +- +- /* Mark the regions with the new flag and update their age. Move +- * them to head of list to preserve LRU semantics. +- */ +- for (i = start; i <= end; i++) { +- list[i].in_use = in_use; +- list[i].age = age; +- +- /* remove_from_list(i) +- */ +- list[(unsigned)list[i].next].prev = list[i].prev; +- list[(unsigned)list[i].prev].next = list[i].next; +- +- /* insert_at_head(list, i) +- */ +- list[i].prev = nr; +- list[i].next = list[nr].next; +- list[(unsigned)list[nr].next].prev = i; +- list[nr].next = i; +- } +-} +- +-/* Very simple allocator for agp memory, working on a static range +- * already mapped into each client's address space. +- */ +- +-static struct mem_block *split_block(struct mem_block *p, int start, int size, +- struct drm_file *file_priv) +-{ +- /* Maybe cut off the start of an existing block */ +- if (start > p->start) { +- struct mem_block *newblock = kmalloc(sizeof(*newblock), +- GFP_KERNEL); +- if (!newblock) +- goto out; +- newblock->start = start; +- newblock->size = p->size - (start - p->start); +- newblock->file_priv = NULL; +- newblock->next = p->next; +- newblock->prev = p; +- p->next->prev = newblock; +- p->next = newblock; +- p->size -= newblock->size; +- p = newblock; +- } +- +- /* Maybe cut off the end of an existing block */ +- if (size < p->size) { +- struct mem_block *newblock = kmalloc(sizeof(*newblock), +- GFP_KERNEL); +- if (!newblock) +- goto out; +- newblock->start = start + size; +- newblock->size = p->size - size; +- newblock->file_priv = NULL; +- newblock->next = p->next; +- newblock->prev = p; +- p->next->prev = newblock; +- p->next = newblock; +- p->size = size; +- } +- +- out: +- /* Our block is in the middle */ +- p->file_priv = file_priv; +- return p; +-} +- +-static struct mem_block *alloc_block(struct mem_block *heap, int size, +- int align2, struct drm_file *file_priv) +-{ +- struct mem_block *p; +- int mask = (1 << align2) - 1; +- +- for (p = heap->next; p != heap; p = p->next) { +- int start = (p->start + mask) & ~mask; +- if (p->file_priv == NULL && start + size <= p->start + p->size) +- return split_block(p, start, size, file_priv); +- } +- +- return NULL; +-} +- +-static struct mem_block *find_block(struct mem_block *heap, int start) +-{ +- struct mem_block *p; +- +- for (p = heap->next; p != heap; p = p->next) +- if (p->start == start) +- return p; +- +- return NULL; +-} +- +-static void free_block(struct mem_block *p) +-{ +- p->file_priv = NULL; +- +- /* Assumes a single contiguous range. Needs a special file_priv in +- * 'heap' to stop it being subsumed. +- */ +- if (p->next->file_priv == NULL) { +- struct mem_block *q = p->next; +- p->size += q->size; +- p->next = q->next; +- p->next->prev = p; +- kfree(q); +- } +- +- if (p->prev->file_priv == NULL) { +- struct mem_block *q = p->prev; +- q->size += p->size; +- q->next = p->next; +- q->next->prev = q; +- kfree(p); +- } +-} +- +-/* Initialize. How to check for an uninitialized heap? +- */ +-static int init_heap(struct mem_block **heap, int start, int size) +-{ +- struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL); +- +- if (!blocks) +- return -ENOMEM; +- +- *heap = kmalloc(sizeof(**heap), GFP_KERNEL); +- if (!*heap) { +- kfree(blocks); +- return -ENOMEM; +- } +- +- blocks->start = start; +- blocks->size = size; +- blocks->file_priv = NULL; +- blocks->next = blocks->prev = *heap; +- +- memset(*heap, 0, sizeof(**heap)); +- (*heap)->file_priv = (struct drm_file *) -1; +- (*heap)->next = (*heap)->prev = blocks; +- return 0; +-} +- +-/* Free all blocks associated with the releasing file. +- */ +-void i915_mem_release(struct drm_device * dev, struct drm_file *file_priv, +- struct mem_block *heap) +-{ +- struct mem_block *p; +- +- if (!heap || !heap->next) +- return; +- +- for (p = heap->next; p != heap; p = p->next) { +- if (p->file_priv == file_priv) { +- p->file_priv = NULL; +- mark_block(dev, p, 0); +- } +- } +- +- /* Assumes a single contiguous range. Needs a special file_priv in +- * 'heap' to stop it being subsumed. +- */ +- for (p = heap->next; p != heap; p = p->next) { +- while (p->file_priv == NULL && p->next->file_priv == NULL) { +- struct mem_block *q = p->next; +- p->size += q->size; +- p->next = q->next; +- p->next->prev = p; +- kfree(q); +- } +- } +-} +- +-/* Shutdown. +- */ +-void i915_mem_takedown(struct mem_block **heap) +-{ +- struct mem_block *p; +- +- if (!*heap) +- return; +- +- for (p = (*heap)->next; p != *heap;) { +- struct mem_block *q = p; +- p = p->next; +- kfree(q); +- } +- +- kfree(*heap); +- *heap = NULL; +-} +- +-static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region) +-{ +- switch (region) { +- case I915_MEM_REGION_AGP: +- return &dev_priv->agp_heap; +- default: +- return NULL; +- } +-} +- +-/* IOCTL HANDLERS */ +- +-int i915_mem_alloc(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- drm_i915_private_t *dev_priv = dev->dev_private; +- drm_i915_mem_alloc_t *alloc = data; +- struct mem_block *block, **heap; +- +- if (!dev_priv) { +- DRM_ERROR("called with no initialization\n"); +- return -EINVAL; +- } +- +- heap = get_heap(dev_priv, alloc->region); +- if (!heap || !*heap) +- return -EFAULT; +- +- /* Make things easier on ourselves: all allocations at least +- * 4k aligned. +- */ +- if (alloc->alignment < 12) +- alloc->alignment = 12; +- +- block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv); +- +- if (!block) +- return -ENOMEM; +- +- mark_block(dev, block, 1); +- +- if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, +- sizeof(int))) { +- DRM_ERROR("copy_to_user\n"); +- return -EFAULT; +- } +- +- return 0; +-} +- +-int i915_mem_free(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- drm_i915_private_t *dev_priv = dev->dev_private; +- drm_i915_mem_free_t *memfree = data; +- struct mem_block *block, **heap; +- +- if (!dev_priv) { +- DRM_ERROR("called with no initialization\n"); +- return -EINVAL; +- } +- +- heap = get_heap(dev_priv, memfree->region); +- if (!heap || !*heap) +- return -EFAULT; +- +- block = find_block(*heap, memfree->region_offset); +- if (!block) +- return -EFAULT; +- +- if (block->file_priv != file_priv) +- return -EPERM; +- +- mark_block(dev, block, 0); +- free_block(block); +- return 0; +-} +- +-int i915_mem_init_heap(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- drm_i915_private_t *dev_priv = dev->dev_private; +- drm_i915_mem_init_heap_t *initheap = data; +- struct mem_block **heap; +- +- if (!dev_priv) { +- DRM_ERROR("called with no initialization\n"); +- return -EINVAL; +- } +- +- heap = get_heap(dev_priv, initheap->region); +- if (!heap) +- return -EFAULT; +- +- if (*heap) { +- DRM_ERROR("heap already initialized?"); +- return -EFAULT; +- } +- +- return init_heap(heap, initheap->start, initheap->size); +-} +- +-int i915_mem_destroy_heap(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- drm_i915_private_t *dev_priv = dev->dev_private; +- drm_i915_mem_destroy_heap_t *destroyheap = data; +- struct mem_block **heap; +- +- if (!dev_priv) { +- DRM_ERROR("called with no initialization\n"); +- return -EINVAL; +- } +- +- heap = get_heap(dev_priv, destroyheap->region); +- if (!heap) { +- DRM_ERROR("get_heap failed"); +- return -EFAULT; +- } +- +- if (!*heap) { +- DRM_ERROR("heap not initialized?"); +- return -EFAULT; +- } +- +- i915_mem_takedown(heap); +- return 0; +-} +diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h +index ddb22e7..ea6a2ab 100644 +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -37,7 +37,6 @@ + */ + #define INTEL_GMCH_CTRL 0x52 + #define INTEL_GMCH_VGA_DISABLE (1 << 1) +-#define SNB_GMCH_CTRL 0x50 + + /* PCI config space */ + +@@ -89,12 +88,45 @@ + #define GEN6_MBC_SNPCR_LOW (2<<21) + #define GEN6_MBC_SNPCR_MIN (3<<21) /* only 1/16th of the cache is shared */ + ++#define GEN6_MBCTL 0x0907c ++#define GEN6_MBCTL_ENABLE_BOOT_FETCH (1 << 4) ++#define GEN6_MBCTL_CTX_FETCH_NEEDED (1 << 3) ++#define GEN6_MBCTL_BME_UPDATE_ENABLE (1 << 2) ++#define GEN6_MBCTL_MAE_UPDATE_ENABLE (1 << 1) ++#define GEN6_MBCTL_BOOT_FETCH_MECH (1 << 0) ++ + #define GEN6_GDRST 0x941c + #define GEN6_GRDOM_FULL (1 << 0) + #define GEN6_GRDOM_RENDER (1 << 1) + #define GEN6_GRDOM_MEDIA (1 << 2) + #define GEN6_GRDOM_BLT (1 << 3) + ++/* PPGTT stuff */ ++#define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0)) ++ ++#define GEN6_PDE_VALID (1 << 0) ++#define GEN6_PDE_LARGE_PAGE (2 << 0) /* use 32kb pages */ ++/* gen6+ has bit 11-4 for physical addr bit 39-32 */ ++#define GEN6_PDE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) ++ ++#define GEN6_PTE_VALID (1 << 0) ++#define GEN6_PTE_UNCACHED (1 << 1) ++#define GEN6_PTE_CACHE_LLC (2 << 1) ++#define GEN6_PTE_CACHE_LLC_MLC (3 << 1) ++#define GEN6_PTE_CACHE_BITS (3 << 1) ++#define GEN6_PTE_GFDT (1 << 3) ++#define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) ++ ++#define RING_PP_DIR_BASE(ring) ((ring)->mmio_base+0x228) ++#define RING_PP_DIR_BASE_READ(ring) ((ring)->mmio_base+0x518) ++#define RING_PP_DIR_DCLV(ring) ((ring)->mmio_base+0x220) ++#define PP_DIR_DCLV_2G 0xffffffff ++ ++#define GAM_ECOCHK 0x4090 ++#define ECOCHK_SNB_BIT (1<<10) ++#define ECOCHK_PPGTT_CACHE64B (0x3<<3) ++#define ECOCHK_PPGTT_CACHE4B (0x0<<3) ++ + /* VGA stuff */ + + #define VGA_ST01_MDA 0x3ba +@@ -306,6 +338,12 @@ + #define FENCE_REG_SANDYBRIDGE_0 0x100000 + #define SANDYBRIDGE_FENCE_PITCH_SHIFT 32 + ++/* control register for cpu gtt access */ ++#define TILECTL 0x101000 ++#define TILECTL_SWZCTL (1 << 0) ++#define TILECTL_TLB_PREFETCH_DIS (1 << 2) ++#define TILECTL_BACKSNOOP_DIS (1 << 3) ++ + /* + * Instruction and interrupt control regs + */ +@@ -329,7 +367,14 @@ + #define RING_MAX_IDLE(base) ((base)+0x54) + #define RING_HWS_PGA(base) ((base)+0x80) + #define RING_HWS_PGA_GEN6(base) ((base)+0x2080) ++#define ARB_MODE 0x04030 ++#define ARB_MODE_SWIZZLE_SNB (1<<4) ++#define ARB_MODE_SWIZZLE_IVB (1<<5) ++#define ARB_MODE_ENABLE(x) GFX_MODE_ENABLE(x) ++#define ARB_MODE_DISABLE(x) GFX_MODE_DISABLE(x) + #define RENDER_HWS_PGA_GEN7 (0x04080) ++#define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id) ++#define DONE_REG 0x40b0 + #define BSD_HWS_PGA_GEN7 (0x04180) + #define BLT_HWS_PGA_GEN7 (0x04280) + #define RING_ACTHD(base) ((base)+0x74) +@@ -363,7 +408,12 @@ + #define IPEIR_I965 0x02064 + #define IPEHR_I965 0x02068 + #define INSTDONE_I965 0x0206c +-#define RING_INSTPM(base) ((base)+0xc0) ++#define RING_IPEIR(base) ((base)+0x64) ++#define RING_IPEHR(base) ((base)+0x68) ++#define RING_INSTDONE(base) ((base)+0x6c) ++#define RING_INSTPS(base) ((base)+0x70) ++#define RING_DMA_FADD(base) ((base)+0x78) ++#define RING_INSTPM(base) ((base)+0xc0) + #define INSTPS 0x02070 /* 965+ only */ + #define INSTDONE1 0x0207c /* 965+ only */ + #define ACTHD_I965 0x02074 +@@ -377,14 +427,6 @@ + #define INSTDONE 0x02090 + #define NOPID 0x02094 + #define HWSTAM 0x02098 +-#define VCS_INSTDONE 0x1206C +-#define VCS_IPEIR 0x12064 +-#define VCS_IPEHR 0x12068 +-#define VCS_ACTHD 0x12074 +-#define BCS_INSTDONE 0x2206C +-#define BCS_IPEIR 0x22064 +-#define BCS_IPEHR 0x22068 +-#define BCS_ACTHD 0x22074 + + #define ERROR_GEN6 0x040a0 + +@@ -412,6 +454,7 @@ + + #define GFX_MODE 0x02520 + #define GFX_MODE_GEN7 0x0229c ++#define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c) + #define GFX_RUN_LIST_ENABLE (1<<15) + #define GFX_TLB_INVALIDATE_ALWAYS (1<<13) + #define GFX_SURFACE_FAULT_ENABLE (1<<12) +@@ -1072,6 +1115,29 @@ + #define C0DRB3 0x10206 + #define C1DRB3 0x10606 + ++/** snb MCH registers for reading the DRAM channel configuration */ ++#define MAD_DIMM_C0 (MCHBAR_MIRROR_BASE_SNB + 0x5004) ++#define MAD_DIMM_C1 (MCHBAR_MIRROR_BASE_SNB + 0x5008) ++#define MAD_DIMM_C2 (MCHBAR_MIRROR_BASE_SNB + 0x500C) ++#define MAD_DIMM_ECC_MASK (0x3 << 24) ++#define MAD_DIMM_ECC_OFF (0x0 << 24) ++#define MAD_DIMM_ECC_IO_ON_LOGIC_OFF (0x1 << 24) ++#define MAD_DIMM_ECC_IO_OFF_LOGIC_ON (0x2 << 24) ++#define MAD_DIMM_ECC_ON (0x3 << 24) ++#define MAD_DIMM_ENH_INTERLEAVE (0x1 << 22) ++#define MAD_DIMM_RANK_INTERLEAVE (0x1 << 21) ++#define MAD_DIMM_B_WIDTH_X16 (0x1 << 20) /* X8 chips if unset */ ++#define MAD_DIMM_A_WIDTH_X16 (0x1 << 19) /* X8 chips if unset */ ++#define MAD_DIMM_B_DUAL_RANK (0x1 << 18) ++#define MAD_DIMM_A_DUAL_RANK (0x1 << 17) ++#define MAD_DIMM_A_SELECT (0x1 << 16) ++/* DIMM sizes are in multiples of 256mb. */ ++#define MAD_DIMM_B_SIZE_SHIFT 8 ++#define MAD_DIMM_B_SIZE_MASK (0xff << MAD_DIMM_B_SIZE_SHIFT) ++#define MAD_DIMM_A_SIZE_SHIFT 0 ++#define MAD_DIMM_A_SIZE_MASK (0xff << MAD_DIMM_A_SIZE_SHIFT) ++ ++ + /* Clocking configuration register */ + #define CLKCFG 0x10c00 + #define CLKCFG_FSB_400 (5 << 0) /* hrawclk 100 */ +@@ -1351,6 +1417,7 @@ + #define _VSYNC_A 0x60014 + #define _PIPEASRC 0x6001c + #define _BCLRPAT_A 0x60020 ++#define _VSYNCSHIFT_A 0x60028 + + /* Pipe B timing regs */ + #define _HTOTAL_B 0x61000 +@@ -1361,6 +1428,8 @@ + #define _VSYNC_B 0x61014 + #define _PIPEBSRC 0x6101c + #define _BCLRPAT_B 0x61020 ++#define _VSYNCSHIFT_B 0x61028 ++ + + #define HTOTAL(pipe) _PIPE(pipe, _HTOTAL_A, _HTOTAL_B) + #define HBLANK(pipe) _PIPE(pipe, _HBLANK_A, _HBLANK_B) +@@ -1369,6 +1438,7 @@ + #define VBLANK(pipe) _PIPE(pipe, _VBLANK_A, _VBLANK_B) + #define VSYNC(pipe) _PIPE(pipe, _VSYNC_A, _VSYNC_B) + #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B) ++#define VSYNCSHIFT(pipe) _PIPE(pipe, _VSYNCSHIFT_A, _VSYNCSHIFT_B) + + /* VGA port control */ + #define ADPA 0x61100 +@@ -1568,10 +1638,6 @@ + + /* Video Data Island Packet control */ + #define VIDEO_DIP_DATA 0x61178 +-/* Read the description of VIDEO_DIP_DATA (before Haswel) or VIDEO_DIP_ECC +- * (Haswell and newer) to see which VIDEO_DIP_DATA byte corresponds to each byte +- * of the infoframe structure specified by CEA-861. */ +-#define VIDEO_DIP_DATA_SIZE 32 + #define VIDEO_DIP_CTL 0x61170 + #define VIDEO_DIP_ENABLE (1 << 31) + #define VIDEO_DIP_PORT_B (1 << 29) +@@ -2365,9 +2431,21 @@ + #define PIPECONF_PALETTE 0 + #define PIPECONF_GAMMA (1<<24) + #define PIPECONF_FORCE_BORDER (1<<25) +-#define PIPECONF_PROGRESSIVE (0 << 21) ++#define PIPECONF_INTERLACE_MASK (7 << 21) ++/* Note that pre-gen3 does not support interlaced display directly. Panel ++ * fitting must be disabled on pre-ilk for interlaced. */ ++#define PIPECONF_PROGRESSIVE (0 << 21) ++#define PIPECONF_INTERLACE_W_SYNC_SHIFT_PANEL (4 << 21) /* gen4 only */ ++#define PIPECONF_INTERLACE_W_SYNC_SHIFT (5 << 21) /* gen4 only */ + #define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) +-#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) ++#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) /* gen3 only */ ++/* Ironlake and later have a complete new set of values for interlaced. PFIT ++ * means panel fitter required, PF means progressive fetch, DBL means power ++ * saving pixel doubling. */ ++#define PIPECONF_PFIT_PF_INTERLACED_ILK (1 << 21) ++#define PIPECONF_INTERLACED_ILK (3 << 21) ++#define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */ ++#define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */ + #define PIPECONF_CXSR_DOWNCLOCK (1<<16) + #define PIPECONF_BPP_MASK (0x000000e0) + #define PIPECONF_BPP_8 (0<<5) +@@ -2506,6 +2584,8 @@ + #define WM3_LP_ILK 0x45110 + #define WM3_LP_EN (1<<31) + #define WM1S_LP_ILK 0x45120 ++#define WM2S_LP_IVB 0x45124 ++#define WM3S_LP_IVB 0x45128 + #define WM1S_LP_EN (1<<31) + + /* Memory latency timer register */ +@@ -2722,6 +2802,140 @@ + #define _DSPBSURF 0x7119C + #define _DSPBTILEOFF 0x711A4 + ++/* Sprite A control */ ++#define _DVSACNTR 0x72180 ++#define DVS_ENABLE (1<<31) ++#define DVS_GAMMA_ENABLE (1<<30) ++#define DVS_PIXFORMAT_MASK (3<<25) ++#define DVS_FORMAT_YUV422 (0<<25) ++#define DVS_FORMAT_RGBX101010 (1<<25) ++#define DVS_FORMAT_RGBX888 (2<<25) ++#define DVS_FORMAT_RGBX161616 (3<<25) ++#define DVS_SOURCE_KEY (1<<22) ++#define DVS_RGB_ORDER_XBGR (1<<20) ++#define DVS_YUV_BYTE_ORDER_MASK (3<<16) ++#define DVS_YUV_ORDER_YUYV (0<<16) ++#define DVS_YUV_ORDER_UYVY (1<<16) ++#define DVS_YUV_ORDER_YVYU (2<<16) ++#define DVS_YUV_ORDER_VYUY (3<<16) ++#define DVS_DEST_KEY (1<<2) ++#define DVS_TRICKLE_FEED_DISABLE (1<<14) ++#define DVS_TILED (1<<10) ++#define _DVSALINOFF 0x72184 ++#define _DVSASTRIDE 0x72188 ++#define _DVSAPOS 0x7218c ++#define _DVSASIZE 0x72190 ++#define _DVSAKEYVAL 0x72194 ++#define _DVSAKEYMSK 0x72198 ++#define _DVSASURF 0x7219c ++#define _DVSAKEYMAXVAL 0x721a0 ++#define _DVSATILEOFF 0x721a4 ++#define _DVSASURFLIVE 0x721ac ++#define _DVSASCALE 0x72204 ++#define DVS_SCALE_ENABLE (1<<31) ++#define DVS_FILTER_MASK (3<<29) ++#define DVS_FILTER_MEDIUM (0<<29) ++#define DVS_FILTER_ENHANCING (1<<29) ++#define DVS_FILTER_SOFTENING (2<<29) ++#define DVS_VERTICAL_OFFSET_HALF (1<<28) /* must be enabled below */ ++#define DVS_VERTICAL_OFFSET_ENABLE (1<<27) ++#define _DVSAGAMC 0x72300 ++ ++#define _DVSBCNTR 0x73180 ++#define _DVSBLINOFF 0x73184 ++#define _DVSBSTRIDE 0x73188 ++#define _DVSBPOS 0x7318c ++#define _DVSBSIZE 0x73190 ++#define _DVSBKEYVAL 0x73194 ++#define _DVSBKEYMSK 0x73198 ++#define _DVSBSURF 0x7319c ++#define _DVSBKEYMAXVAL 0x731a0 ++#define _DVSBTILEOFF 0x731a4 ++#define _DVSBSURFLIVE 0x731ac ++#define _DVSBSCALE 0x73204 ++#define _DVSBGAMC 0x73300 ++ ++#define DVSCNTR(pipe) _PIPE(pipe, _DVSACNTR, _DVSBCNTR) ++#define DVSLINOFF(pipe) _PIPE(pipe, _DVSALINOFF, _DVSBLINOFF) ++#define DVSSTRIDE(pipe) _PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE) ++#define DVSPOS(pipe) _PIPE(pipe, _DVSAPOS, _DVSBPOS) ++#define DVSSURF(pipe) _PIPE(pipe, _DVSASURF, _DVSBSURF) ++#define DVSKEYMAX(pipe) _PIPE(pipe, _DVSAKEYMAXVAL, _DVSBKEYMAXVAL) ++#define DVSSIZE(pipe) _PIPE(pipe, _DVSASIZE, _DVSBSIZE) ++#define DVSSCALE(pipe) _PIPE(pipe, _DVSASCALE, _DVSBSCALE) ++#define DVSTILEOFF(pipe) _PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF) ++#define DVSKEYVAL(pipe) _PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL) ++#define DVSKEYMSK(pipe) _PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK) ++ ++#define _SPRA_CTL 0x70280 ++#define SPRITE_ENABLE (1<<31) ++#define SPRITE_GAMMA_ENABLE (1<<30) ++#define SPRITE_PIXFORMAT_MASK (7<<25) ++#define SPRITE_FORMAT_YUV422 (0<<25) ++#define SPRITE_FORMAT_RGBX101010 (1<<25) ++#define SPRITE_FORMAT_RGBX888 (2<<25) ++#define SPRITE_FORMAT_RGBX161616 (3<<25) ++#define SPRITE_FORMAT_YUV444 (4<<25) ++#define SPRITE_FORMAT_XR_BGR101010 (5<<25) /* Extended range */ ++#define SPRITE_CSC_ENABLE (1<<24) ++#define SPRITE_SOURCE_KEY (1<<22) ++#define SPRITE_RGB_ORDER_RGBX (1<<20) /* only for 888 and 161616 */ ++#define SPRITE_YUV_TO_RGB_CSC_DISABLE (1<<19) ++#define SPRITE_YUV_CSC_FORMAT_BT709 (1<<18) /* 0 is BT601 */ ++#define SPRITE_YUV_BYTE_ORDER_MASK (3<<16) ++#define SPRITE_YUV_ORDER_YUYV (0<<16) ++#define SPRITE_YUV_ORDER_UYVY (1<<16) ++#define SPRITE_YUV_ORDER_YVYU (2<<16) ++#define SPRITE_YUV_ORDER_VYUY (3<<16) ++#define SPRITE_TRICKLE_FEED_DISABLE (1<<14) ++#define SPRITE_INT_GAMMA_ENABLE (1<<13) ++#define SPRITE_TILED (1<<10) ++#define SPRITE_DEST_KEY (1<<2) ++#define _SPRA_LINOFF 0x70284 ++#define _SPRA_STRIDE 0x70288 ++#define _SPRA_POS 0x7028c ++#define _SPRA_SIZE 0x70290 ++#define _SPRA_KEYVAL 0x70294 ++#define _SPRA_KEYMSK 0x70298 ++#define _SPRA_SURF 0x7029c ++#define _SPRA_KEYMAX 0x702a0 ++#define _SPRA_TILEOFF 0x702a4 ++#define _SPRA_SCALE 0x70304 ++#define SPRITE_SCALE_ENABLE (1<<31) ++#define SPRITE_FILTER_MASK (3<<29) ++#define SPRITE_FILTER_MEDIUM (0<<29) ++#define SPRITE_FILTER_ENHANCING (1<<29) ++#define SPRITE_FILTER_SOFTENING (2<<29) ++#define SPRITE_VERTICAL_OFFSET_HALF (1<<28) /* must be enabled below */ ++#define SPRITE_VERTICAL_OFFSET_ENABLE (1<<27) ++#define _SPRA_GAMC 0x70400 ++ ++#define _SPRB_CTL 0x71280 ++#define _SPRB_LINOFF 0x71284 ++#define _SPRB_STRIDE 0x71288 ++#define _SPRB_POS 0x7128c ++#define _SPRB_SIZE 0x71290 ++#define _SPRB_KEYVAL 0x71294 ++#define _SPRB_KEYMSK 0x71298 ++#define _SPRB_SURF 0x7129c ++#define _SPRB_KEYMAX 0x712a0 ++#define _SPRB_TILEOFF 0x712a4 ++#define _SPRB_SCALE 0x71304 ++#define _SPRB_GAMC 0x71400 ++ ++#define SPRCTL(pipe) _PIPE(pipe, _SPRA_CTL, _SPRB_CTL) ++#define SPRLINOFF(pipe) _PIPE(pipe, _SPRA_LINOFF, _SPRB_LINOFF) ++#define SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _SPRB_STRIDE) ++#define SPRPOS(pipe) _PIPE(pipe, _SPRA_POS, _SPRB_POS) ++#define SPRSIZE(pipe) _PIPE(pipe, _SPRA_SIZE, _SPRB_SIZE) ++#define SPRKEYVAL(pipe) _PIPE(pipe, _SPRA_KEYVAL, _SPRB_KEYVAL) ++#define SPRKEYMSK(pipe) _PIPE(pipe, _SPRA_KEYMSK, _SPRB_KEYMSK) ++#define SPRSURF(pipe) _PIPE(pipe, _SPRA_SURF, _SPRB_SURF) ++#define SPRKEYMAX(pipe) _PIPE(pipe, _SPRA_KEYMAX, _SPRB_KEYMAX) ++#define SPRTILEOFF(pipe) _PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF) ++#define SPRSCALE(pipe) _PIPE(pipe, _SPRA_SCALE, _SPRB_SCALE) ++#define SPRGAMC(pipe) _PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC) ++ + /* VBIOS regs */ + #define VGACNTRL 0x71400 + # define VGA_DISP_DISABLE (1 << 31) +@@ -2931,6 +3145,10 @@ + #define ILK_DPFC_DIS1 (1<<8) + #define ILK_DPFC_DIS2 (1<<9) + ++#define IVB_CHICKEN3 0x4200c ++# define CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE (1 << 5) ++# define CHICKEN3_DGMG_DONE_FIX_DISABLE (1 << 2) ++ + #define DISP_ARB_CTL 0x45000 + #define DISP_TILE_SURFACE_SWIZZLING (1<<13) + #define DISP_FBC_WM_DIS (1<<15) +@@ -3126,6 +3344,7 @@ + #define _TRANS_VSYNC_A 0xe0014 + #define TRANS_VSYNC_END_SHIFT 16 + #define TRANS_VSYNC_START_SHIFT 0 ++#define _TRANS_VSYNCSHIFT_A 0xe0028 + + #define _TRANSA_DATA_M1 0xe0030 + #define _TRANSA_DATA_N1 0xe0034 +@@ -3156,6 +3375,7 @@ + #define _TRANS_VTOTAL_B 0xe100c + #define _TRANS_VBLANK_B 0xe1010 + #define _TRANS_VSYNC_B 0xe1014 ++#define _TRANS_VSYNCSHIFT_B 0xe1028 + + #define TRANS_HTOTAL(pipe) _PIPE(pipe, _TRANS_HTOTAL_A, _TRANS_HTOTAL_B) + #define TRANS_HBLANK(pipe) _PIPE(pipe, _TRANS_HBLANK_A, _TRANS_HBLANK_B) +@@ -3163,6 +3383,8 @@ + #define TRANS_VTOTAL(pipe) _PIPE(pipe, _TRANS_VTOTAL_A, _TRANS_VTOTAL_B) + #define TRANS_VBLANK(pipe) _PIPE(pipe, _TRANS_VBLANK_A, _TRANS_VBLANK_B) + #define TRANS_VSYNC(pipe) _PIPE(pipe, _TRANS_VSYNC_A, _TRANS_VSYNC_B) ++#define TRANS_VSYNCSHIFT(pipe) _PIPE(pipe, _TRANS_VSYNCSHIFT_A, \ ++ _TRANS_VSYNCSHIFT_B) + + #define _TRANSB_DATA_M1 0xe1030 + #define _TRANSB_DATA_N1 0xe1034 +@@ -3196,7 +3418,10 @@ + #define TRANS_FSYNC_DELAY_HB4 (3<<27) + #define TRANS_DP_AUDIO_ONLY (1<<26) + #define TRANS_DP_VIDEO_AUDIO (0<<26) ++#define TRANS_INTERLACE_MASK (7<<21) + #define TRANS_PROGRESSIVE (0<<21) ++#define TRANS_INTERLACED (3<<21) ++#define TRANS_LEGACY_INTERLACED_ILK (2<<21) + #define TRANS_8BPC (0<<5) + #define TRANS_10BPC (1<<5) + #define TRANS_6BPC (2<<5) +@@ -3535,9 +3760,18 @@ + #define ECOBUS 0xa180 + #define FORCEWAKE_MT_ENABLE (1<<5) + ++#define GTFIFODBG 0x120000 ++#define GT_FIFO_CPU_ERROR_MASK 7 ++#define GT_FIFO_OVFERR (1<<2) ++#define GT_FIFO_IAWRERR (1<<1) ++#define GT_FIFO_IARDERR (1<<0) ++ + #define GT_FIFO_FREE_ENTRIES 0x120008 + #define GT_FIFO_NUM_RESERVED_ENTRIES 20 + ++#define GEN6_UCGCTL1 0x9400 ++# define GEN6_BLBUNIT_CLOCK_GATE_DISABLE (1 << 5) ++ + #define GEN6_UCGCTL2 0x9404 + # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13) + # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) +@@ -3625,6 +3859,14 @@ + #define GEN6_PCODE_DATA 0x138128 + #define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8 + ++#define GEN6_GT_CORE_STATUS 0x138060 ++#define GEN6_CORE_CPD_STATE_MASK (7<<4) ++#define GEN6_RCn_MASK 7 ++#define GEN6_RC0 0 ++#define GEN6_RC3 2 ++#define GEN6_RC6 3 ++#define GEN6_RC7 4 ++ + #define G4X_AUD_VID_DID 0x62020 + #define INTEL_AUDIO_DEVCL 0x808629FB + #define INTEL_AUDIO_DEVBLC 0x80862801 +@@ -3637,17 +3879,35 @@ + #define G4X_ELD_ACK (1 << 4) + #define G4X_HDMIW_HDMIEDID 0x6210C + +-#define GEN5_HDMIW_HDMIEDID_A 0xE2050 +-#define GEN5_AUD_CNTL_ST_A 0xE20B4 +-#define GEN5_ELD_BUFFER_SIZE (0x1f << 10) +-#define GEN5_ELD_ADDRESS (0x1f << 5) +-#define GEN5_ELD_ACK (1 << 4) +-#define GEN5_AUD_CNTL_ST2 0xE20C0 +-#define GEN5_ELD_VALIDB (1 << 0) +-#define GEN5_CP_READYB (1 << 1) +- +-#define GEN7_HDMIW_HDMIEDID_A 0xE5050 +-#define GEN7_AUD_CNTRL_ST_A 0xE50B4 +-#define GEN7_AUD_CNTRL_ST2 0xE50C0 ++#define IBX_HDMIW_HDMIEDID_A 0xE2050 ++#define IBX_AUD_CNTL_ST_A 0xE20B4 ++#define IBX_ELD_BUFFER_SIZE (0x1f << 10) ++#define IBX_ELD_ADDRESS (0x1f << 5) ++#define IBX_ELD_ACK (1 << 4) ++#define IBX_AUD_CNTL_ST2 0xE20C0 ++#define IBX_ELD_VALIDB (1 << 0) ++#define IBX_CP_READYB (1 << 1) ++ ++#define CPT_HDMIW_HDMIEDID_A 0xE5050 ++#define CPT_AUD_CNTL_ST_A 0xE50B4 ++#define CPT_AUD_CNTRL_ST2 0xE50C0 ++ ++/* These are the 4 32-bit write offset registers for each stream ++ * output buffer. It determines the offset from the ++ * 3DSTATE_SO_BUFFERs that the next streamed vertex output goes to. ++ */ ++#define GEN7_SO_WRITE_OFFSET(n) (0x5280 + (n) * 4) ++ ++#define IBX_AUD_CONFIG_A 0xe2000 ++#define CPT_AUD_CONFIG_A 0xe5000 ++#define AUD_CONFIG_N_VALUE_INDEX (1 << 29) ++#define AUD_CONFIG_N_PROG_ENABLE (1 << 28) ++#define AUD_CONFIG_UPPER_N_SHIFT 20 ++#define AUD_CONFIG_UPPER_N_VALUE (0xff << 20) ++#define AUD_CONFIG_LOWER_N_SHIFT 4 ++#define AUD_CONFIG_LOWER_N_VALUE (0xfff << 4) ++#define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16 ++#define AUD_CONFIG_PIXEL_CLOCK_HDMI (0xf << 16) ++#define AUD_CONFIG_DISABLE_NCTS (1 << 3) + + #endif /* _I915_REG_H_ */ +diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c +index f38d196..0d13778 100644 +--- a/drivers/gpu/drm/i915/i915_suspend.c ++++ b/drivers/gpu/drm/i915/i915_suspend.c +@@ -28,6 +28,7 @@ + #include "drm.h" + #include "i915_drm.h" + #include "intel_drv.h" ++#include "i915_reg.h" + + static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe) + { +@@ -39,7 +40,7 @@ static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe) + return false; + + if (HAS_PCH_SPLIT(dev)) +- dpll_reg = (pipe == PIPE_A) ? _PCH_DPLL_A : _PCH_DPLL_B; ++ dpll_reg = PCH_DPLL(pipe); + else + dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B; + +diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c +index cb91210..bae3edf 100644 +--- a/drivers/gpu/drm/i915/intel_acpi.c ++++ b/drivers/gpu/drm/i915/intel_acpi.c +@@ -208,7 +208,7 @@ static bool intel_dsm_pci_probe(struct pci_dev *pdev) + + ret = intel_dsm(dhandle, INTEL_DSM_FN_SUPPORTED_FUNCTIONS, 0); + if (ret < 0) { +- DRM_ERROR("failed to get supported _DSM functions\n"); ++ DRM_DEBUG_KMS("failed to get supported _DSM functions\n"); + return false; + } + +diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c +index 96d5cfc..d9e359a 100644 +--- a/drivers/gpu/drm/i915/intel_bios.c ++++ b/drivers/gpu/drm/i915/intel_bios.c +@@ -605,7 +605,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, + DRM_DEBUG_KMS("no child dev is parsed from VBT\n"); + return; + } +- dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL); ++ dev_priv->child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL); + if (!dev_priv->child_dev) { + DRM_DEBUG_KMS("No memory space for child device\n"); + return; +@@ -719,7 +719,7 @@ intel_parse_bios(struct drm_device *dev) + } + + if (!vbt) { +- DRM_ERROR("VBT signature missing\n"); ++ DRM_DEBUG_DRIVER("VBT signature missing\n"); + pci_unmap_rom(pdev, bios); + return -1; + } +diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h +index 8af3735..dbda6e3 100644 +--- a/drivers/gpu/drm/i915/intel_bios.h ++++ b/drivers/gpu/drm/i915/intel_bios.h +@@ -467,8 +467,12 @@ struct edp_link_params { + struct bdb_edp { + struct edp_power_seq power_seqs[16]; + u32 color_depth; +- u32 sdrrs_msa_timing_delay; + struct edp_link_params link_params[16]; ++ u32 sdrrs_msa_timing_delay; ++ ++ /* ith bit indicates enabled/disabled for (i+1)th panel */ ++ u16 edp_s3d_feature; ++ u16 edp_t3_optimization; + } __attribute__ ((packed)); + + void intel_setup_bios(struct drm_device *dev); +diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c +index fee0ad0..b4f71c2 100644 +--- a/drivers/gpu/drm/i915/intel_crt.c ++++ b/drivers/gpu/drm/i915/intel_crt.c +@@ -24,6 +24,7 @@ + * Eric Anholt + */ + ++#include + #include + #include + #include "drmP.h" +@@ -265,6 +266,36 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) + return ret; + } + ++static struct edid *intel_crt_get_edid(struct drm_connector *connector, ++ struct i2c_adapter *i2c) ++{ ++ struct edid *edid; ++ ++ edid = drm_get_edid(connector, i2c); ++ ++ if (!edid && !intel_gmbus_is_forced_bit(i2c)) { ++ DRM_DEBUG_KMS("CRT GMBUS EDID read failed, retry using GPIO bit-banging\n"); ++ intel_gmbus_force_bit(i2c, true); ++ edid = drm_get_edid(connector, i2c); ++ intel_gmbus_force_bit(i2c, false); ++ } ++ ++ return edid; ++} ++ ++/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */ ++static int intel_crt_ddc_get_modes(struct drm_connector *connector, ++ struct i2c_adapter *adapter) ++{ ++ struct edid *edid; ++ ++ edid = intel_crt_get_edid(connector, adapter); ++ if (!edid) ++ return 0; ++ ++ return intel_connector_update_modes(connector, edid); ++} ++ + static bool intel_crt_detect_ddc(struct drm_connector *connector) + { + struct intel_crt *crt = intel_attached_crt(connector); +@@ -278,7 +309,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector) + struct edid *edid; + bool is_digital = false; + +- edid = drm_get_edid(connector, ++ edid = intel_crt_get_edid(connector, + &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); + /* + * This may be a DVI-I connector with a shared DDC +@@ -429,8 +460,8 @@ intel_crt_detect(struct drm_connector *connector, bool force) + { + struct drm_device *dev = connector->dev; + struct intel_crt *crt = intel_attached_crt(connector); +- struct drm_crtc *crtc; + enum drm_connector_status status; ++ struct intel_load_detect_pipe tmp; + + if (I915_HAS_HOTPLUG(dev)) { + if (intel_crt_detect_hotplug(connector)) { +@@ -449,23 +480,16 @@ intel_crt_detect(struct drm_connector *connector, bool force) + return connector->status; + + /* for pre-945g platforms use load detect */ +- crtc = crt->base.base.crtc; +- if (crtc && crtc->enabled) { +- status = intel_crt_load_detect(crt); +- } else { +- struct intel_load_detect_pipe tmp; +- +- if (intel_get_load_detect_pipe(&crt->base, connector, NULL, +- &tmp)) { +- if (intel_crt_detect_ddc(connector)) +- status = connector_status_connected; +- else +- status = intel_crt_load_detect(crt); +- intel_release_load_detect_pipe(&crt->base, connector, +- &tmp); +- } else +- status = connector_status_unknown; +- } ++ if (intel_get_load_detect_pipe(&crt->base, connector, NULL, ++ &tmp)) { ++ if (intel_crt_detect_ddc(connector)) ++ status = connector_status_connected; ++ else ++ status = intel_crt_load_detect(crt); ++ intel_release_load_detect_pipe(&crt->base, connector, ++ &tmp); ++ } else ++ status = connector_status_unknown; + + return status; + } +@@ -483,13 +507,13 @@ static int intel_crt_get_modes(struct drm_connector *connector) + struct drm_i915_private *dev_priv = dev->dev_private; + int ret; + +- ret = intel_ddc_get_modes(connector, ++ ret = intel_crt_ddc_get_modes(connector, + &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); + if (ret || !IS_G4X(dev)) + return ret; + + /* Try to probe digital port for output in DVI-I -> VGA mode. */ +- return intel_ddc_get_modes(connector, ++ return intel_crt_ddc_get_modes(connector, + &dev_priv->gmbus[GMBUS_PORT_DPB].adapter); + } + +@@ -540,6 +564,32 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = { + .destroy = intel_encoder_destroy, + }; + ++static int intel_no_crt_dmi_callback(const struct dmi_system_id *id) ++{ ++ DRM_DEBUG_KMS("Skipping CRT initialization for %s\n", id->ident); ++ return 1; ++} ++ ++static const struct dmi_system_id intel_no_crt[] = { ++ { ++ .callback = intel_no_crt_dmi_callback, ++ .ident = "ACER ZGB", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ACER"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), ++ }, ++ }, ++ { ++ .callback = intel_no_crt_dmi_callback, ++ .ident = "DELL XPS 8700", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "XPS 8700"), ++ }, ++ }, ++ { } ++}; ++ + void intel_crt_init(struct drm_device *dev) + { + struct drm_connector *connector; +@@ -547,6 +597,10 @@ void intel_crt_init(struct drm_device *dev) + struct intel_connector *intel_connector; + struct drm_i915_private *dev_priv = dev->dev_private; + ++ /* Skip machines without VGA that falsely report hotplug events */ ++ if (dmi_check_system(intel_no_crt)) ++ return; ++ + crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL); + if (!crt) + return; +@@ -571,7 +625,10 @@ void intel_crt_init(struct drm_device *dev) + 1 << INTEL_ANALOG_CLONE_BIT | + 1 << INTEL_SDVO_LVDS_CLONE_BIT); + crt->base.crtc_mask = (1 << 0) | (1 << 1); +- connector->interlace_allowed = 1; ++ if (IS_GEN2(dev)) ++ connector->interlace_allowed = 0; ++ else ++ connector->interlace_allowed = 1; + connector->doublescan_allowed = 0; + + drm_encoder_helper_add(&crt->base.base, &intel_crt_helper_funcs); +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 27999d9..c975c99 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -76,7 +76,7 @@ struct intel_limit { + intel_range_t dot, vco, n, m, m1, m2, p, p1; + intel_p2_t p2; + bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, +- int, int, intel_clock_t *); ++ int, int, intel_clock_t *, intel_clock_t *); + }; + + /* FDI */ +@@ -84,17 +84,21 @@ struct intel_limit { + + static bool + intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, +- int target, int refclk, intel_clock_t *best_clock); ++ int target, int refclk, intel_clock_t *match_clock, ++ intel_clock_t *best_clock); + static bool + intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, +- int target, int refclk, intel_clock_t *best_clock); ++ int target, int refclk, intel_clock_t *match_clock, ++ intel_clock_t *best_clock); + + static bool + intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, +- int target, int refclk, intel_clock_t *best_clock); ++ int target, int refclk, intel_clock_t *match_clock, ++ intel_clock_t *best_clock); + static bool + intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, +- int target, int refclk, intel_clock_t *best_clock); ++ int target, int refclk, intel_clock_t *match_clock, ++ intel_clock_t *best_clock); + + static inline u32 /* units of 100MHz */ + intel_fdi_link_freq(struct drm_device *dev) +@@ -535,7 +539,8 @@ static bool intel_PLL_is_valid(struct drm_device *dev, + + static bool + intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, +- int target, int refclk, intel_clock_t *best_clock) ++ int target, int refclk, intel_clock_t *match_clock, ++ intel_clock_t *best_clock) + + { + struct drm_device *dev = crtc->dev; +@@ -581,6 +586,9 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, + if (!intel_PLL_is_valid(dev, limit, + &clock)) + continue; ++ if (match_clock && ++ clock.p != match_clock->p) ++ continue; + + this_err = abs(clock.dot - target); + if (this_err < err) { +@@ -597,7 +605,8 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, + + static bool + intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, +- int target, int refclk, intel_clock_t *best_clock) ++ int target, int refclk, intel_clock_t *match_clock, ++ intel_clock_t *best_clock) + { + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; +@@ -644,6 +653,9 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, + if (!intel_PLL_is_valid(dev, limit, + &clock)) + continue; ++ if (match_clock && ++ clock.p != match_clock->p) ++ continue; + + this_err = abs(clock.dot - target); + if (this_err < err_most) { +@@ -661,7 +673,8 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, + + static bool + intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, +- int target, int refclk, intel_clock_t *best_clock) ++ int target, int refclk, intel_clock_t *match_clock, ++ intel_clock_t *best_clock) + { + struct drm_device *dev = crtc->dev; + intel_clock_t clock; +@@ -687,7 +700,8 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, + /* DisplayPort has only two frequencies, 162MHz and 270MHz */ + static bool + intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, +- int target, int refclk, intel_clock_t *best_clock) ++ int target, int refclk, intel_clock_t *match_clock, ++ intel_clock_t *best_clock) + { + intel_clock_t clock; + if (target < 200000) { +@@ -934,13 +948,17 @@ static void assert_panel_unlocked(struct drm_i915_private *dev_priv, + pipe_name(pipe)); + } + +-static void assert_pipe(struct drm_i915_private *dev_priv, +- enum pipe pipe, bool state) ++void assert_pipe(struct drm_i915_private *dev_priv, ++ enum pipe pipe, bool state) + { + int reg; + u32 val; + bool cur_state; + ++ /* if we need the pipe A quirk it must be always on */ ++ if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ++ state = true; ++ + reg = PIPECONF(pipe); + val = I915_READ(reg); + cur_state = !!(val & PIPECONF_ENABLE); +@@ -948,22 +966,25 @@ static void assert_pipe(struct drm_i915_private *dev_priv, + "pipe %c assertion failure (expected %s, current %s)\n", + pipe_name(pipe), state_string(state), state_string(cur_state)); + } +-#define assert_pipe_enabled(d, p) assert_pipe(d, p, true) +-#define assert_pipe_disabled(d, p) assert_pipe(d, p, false) + +-static void assert_plane_enabled(struct drm_i915_private *dev_priv, +- enum plane plane) ++static void assert_plane(struct drm_i915_private *dev_priv, ++ enum plane plane, bool state) + { + int reg; + u32 val; ++ bool cur_state; + + reg = DSPCNTR(plane); + val = I915_READ(reg); +- WARN(!(val & DISPLAY_PLANE_ENABLE), +- "plane %c assertion failure, should be active but is disabled\n", +- plane_name(plane)); ++ cur_state = !!(val & DISPLAY_PLANE_ENABLE); ++ WARN(cur_state != state, ++ "plane %c assertion failure (expected %s, current %s)\n", ++ plane_name(plane), state_string(state), state_string(cur_state)); + } + ++#define assert_plane_enabled(d, p) assert_plane(d, p, true) ++#define assert_plane_disabled(d, p) assert_plane(d, p, false) ++ + static void assert_planes_disabled(struct drm_i915_private *dev_priv, + enum pipe pipe) + { +@@ -972,8 +993,14 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv, + int cur_pipe; + + /* Planes are fixed to pipes on ILK+ */ +- if (HAS_PCH_SPLIT(dev_priv->dev)) ++ if (HAS_PCH_SPLIT(dev_priv->dev)) { ++ reg = DSPCNTR(pipe); ++ val = I915_READ(reg); ++ WARN((val & DISPLAY_PLANE_ENABLE), ++ "plane %c assertion failure, should be disabled but not\n", ++ plane_name(pipe)); + return; ++ } + + /* Need to check both planes against the pipe */ + for (i = 0; i < 2; i++) { +@@ -1225,7 +1252,8 @@ static void intel_disable_pch_pll(struct drm_i915_private *dev_priv, + enum pipe pipe) + { + int reg; +- u32 val; ++ u32 val, pll_mask = TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL, ++ pll_sel = TRANSC_DPLL_ENABLE; + + if (pipe > 1) + return; +@@ -1236,6 +1264,15 @@ static void intel_disable_pch_pll(struct drm_i915_private *dev_priv, + /* Make sure transcoder isn't still depending on us */ + assert_transcoder_disabled(dev_priv, pipe); + ++ if (pipe == 0) ++ pll_sel |= TRANSC_DPLLA_SEL; ++ else if (pipe == 1) ++ pll_sel |= TRANSC_DPLLB_SEL; ++ ++ ++ if ((I915_READ(PCH_DPLL_SEL) & pll_mask) == pll_sel) ++ return; ++ + reg = PCH_DPLL(pipe); + val = I915_READ(reg); + val &= ~DPLL_VCO_ENABLE; +@@ -1248,7 +1285,8 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv, + enum pipe pipe) + { + int reg; +- u32 val; ++ u32 val, pipeconf_val; ++ struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + + /* PCH only available on ILK+ */ + BUG_ON(dev_priv->info->gen < 5); +@@ -1262,6 +1300,7 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv, + + reg = TRANSCONF(pipe); + val = I915_READ(reg); ++ pipeconf_val = I915_READ(PIPECONF(pipe)); + + if (HAS_PCH_IBX(dev_priv->dev)) { + /* +@@ -1269,8 +1308,19 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv, + * that in pipeconf reg. + */ + val &= ~PIPE_BPC_MASK; +- val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK; ++ val |= pipeconf_val & PIPE_BPC_MASK; + } ++ ++ val &= ~TRANS_INTERLACE_MASK; ++ if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) ++ if (HAS_PCH_IBX(dev_priv->dev) && ++ intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) ++ val |= TRANS_LEGACY_INTERLACED_ILK; ++ else ++ val |= TRANS_INTERLACED; ++ else ++ val |= TRANS_PROGRESSIVE; ++ + I915_WRITE(reg, val | TRANS_ENABLE); + if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100)) + DRM_ERROR("failed to enable transcoder %d\n", pipe); +@@ -1530,8 +1580,8 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) + u32 fbc_ctl, fbc_ctl2; + + cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE; +- if (fb->pitch < cfb_pitch) +- cfb_pitch = fb->pitch; ++ if (fb->pitches[0] < cfb_pitch) ++ cfb_pitch = fb->pitches[0]; + + /* FBC_CTL wants 64B units */ + cfb_pitch = (cfb_pitch / 64) - 1; +@@ -2023,6 +2073,8 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, + ret = i915_gem_object_get_fence(obj, pipelined); + if (ret) + goto err_unpin; ++ ++ i915_gem_object_pin_fence(obj); + } + + dev_priv->mm.interruptible = true; +@@ -2035,6 +2087,12 @@ err_interruptible: + return ret; + } + ++void intel_unpin_fb_obj(struct drm_i915_gem_object *obj) ++{ ++ i915_gem_object_unpin_fence(obj); ++ i915_gem_object_unpin(obj); ++} ++ + static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, + int x, int y) + { +@@ -2092,11 +2150,11 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, + I915_WRITE(reg, dspcntr); + + Start = obj->gtt_offset; +- Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8); ++ Offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); + + DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", +- Start, Offset, x, y, fb->pitch); +- I915_WRITE(DSPSTRIDE(plane), fb->pitch); ++ Start, Offset, x, y, fb->pitches[0]); ++ I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); + if (INTEL_INFO(dev)->gen >= 4) { + I915_WRITE(DSPSURF(plane), Start); + I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); +@@ -2173,11 +2231,11 @@ static int ironlake_update_plane(struct drm_crtc *crtc, + I915_WRITE(reg, dspcntr); + + Start = obj->gtt_offset; +- Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8); ++ Offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); + + DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", +- Start, Offset, x, y, fb->pitch); +- I915_WRITE(DSPSTRIDE(plane), fb->pitch); ++ Start, Offset, x, y, fb->pitches[0]); ++ I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); + I915_WRITE(DSPSURF(plane), Start); + I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); + I915_WRITE(DSPADDR(plane), Offset); +@@ -2276,7 +2334,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, + ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y, + LEAVE_ATOMIC_MODE_SET); + if (ret) { +- i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); ++ intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj); + mutex_unlock(&dev->struct_mutex); + DRM_ERROR("failed to update base address\n"); + return ret; +@@ -2284,7 +2342,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, + + if (old_fb) { + intel_wait_for_vblank(dev, intel_crtc->pipe); +- i915_gem_object_unpin(to_intel_framebuffer(old_fb)->obj); ++ intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj); + } + + mutex_unlock(&dev->struct_mutex); +@@ -2428,9 +2486,11 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) + udelay(150); + + /* Ironlake workaround, enable clock pointer after FDI enable*/ +- I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR); +- I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR | +- FDI_RX_PHASE_SYNC_POINTER_EN); ++ if (HAS_PCH_IBX(dev)) { ++ I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR); ++ I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR | ++ FDI_RX_PHASE_SYNC_POINTER_EN); ++ } + + reg = FDI_RX_IIR(pipe); + for (tries = 0; tries < 5; tries++) { +@@ -2943,6 +3003,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) + I915_WRITE(TRANS_VTOTAL(pipe), I915_READ(VTOTAL(pipe))); + I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe))); + I915_WRITE(TRANS_VSYNC(pipe), I915_READ(VSYNC(pipe))); ++ I915_WRITE(TRANS_VSYNCSHIFT(pipe), I915_READ(VSYNCSHIFT(pipe))); + + intel_fdi_normal_train(crtc); + +@@ -3340,10 +3401,12 @@ static void intel_crtc_disable(struct drm_crtc *crtc) + struct drm_device *dev = crtc->dev; + + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); ++ assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); ++ assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); + + if (crtc->fb) { + mutex_lock(&dev->struct_mutex); +- i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); ++ intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj); + mutex_unlock(&dev->struct_mutex); + } + } +@@ -3417,10 +3480,10 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, + return false; + } + +- /* XXX some encoders set the crtcinfo, others don't. +- * Obviously we need some form of conflict resolution here... +- */ +- if (adjusted_mode->crtc_htotal == 0) ++ /* All interlaced capable intel hw wants timings in frames. Note though ++ * that intel_lvds_mode_fixup does some funny tricks with the crtc ++ * timings, so we need to be careful not to clobber these.*/ ++ if (!(adjusted_mode->private_flags & INTEL_MODE_CRTC_TIMINGS_SET)) + drm_mode_set_crtcinfo(adjusted_mode, 0); + + return true; +@@ -4536,10 +4599,11 @@ static void ironlake_update_wm(struct drm_device *dev) + */ + } + +-static void sandybridge_update_wm(struct drm_device *dev) ++void sandybridge_update_wm(struct drm_device *dev) + { + struct drm_i915_private *dev_priv = dev->dev_private; + int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ ++ u32 val; + int fbc_wm, plane_wm, cursor_wm; + unsigned int enabled; + +@@ -4548,8 +4612,10 @@ static void sandybridge_update_wm(struct drm_device *dev) + &sandybridge_display_wm_info, latency, + &sandybridge_cursor_wm_info, latency, + &plane_wm, &cursor_wm)) { +- I915_WRITE(WM0_PIPEA_ILK, +- (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); ++ val = I915_READ(WM0_PIPEA_ILK); ++ val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); ++ I915_WRITE(WM0_PIPEA_ILK, val | ++ ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); + DRM_DEBUG_KMS("FIFO watermarks For pipe A -" + " plane %d, " "cursor: %d\n", + plane_wm, cursor_wm); +@@ -4560,8 +4626,10 @@ static void sandybridge_update_wm(struct drm_device *dev) + &sandybridge_display_wm_info, latency, + &sandybridge_cursor_wm_info, latency, + &plane_wm, &cursor_wm)) { +- I915_WRITE(WM0_PIPEB_ILK, +- (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); ++ val = I915_READ(WM0_PIPEB_ILK); ++ val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); ++ I915_WRITE(WM0_PIPEB_ILK, val | ++ ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); + DRM_DEBUG_KMS("FIFO watermarks For pipe B -" + " plane %d, cursor: %d\n", + plane_wm, cursor_wm); +@@ -4574,8 +4642,10 @@ static void sandybridge_update_wm(struct drm_device *dev) + &sandybridge_display_wm_info, latency, + &sandybridge_cursor_wm_info, latency, + &plane_wm, &cursor_wm)) { +- I915_WRITE(WM0_PIPEC_IVB, +- (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); ++ val = I915_READ(WM0_PIPEC_IVB); ++ val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); ++ I915_WRITE(WM0_PIPEC_IVB, val | ++ ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); + DRM_DEBUG_KMS("FIFO watermarks For pipe C -" + " plane %d, cursor: %d\n", + plane_wm, cursor_wm); +@@ -4596,7 +4666,8 @@ static void sandybridge_update_wm(struct drm_device *dev) + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); + +- if (!single_plane_enabled(enabled)) ++ if (!single_plane_enabled(enabled) || ++ dev_priv->sprite_scaling_enabled) + return; + enabled = ffs(enabled) - 1; + +@@ -4646,6 +4717,161 @@ static void sandybridge_update_wm(struct drm_device *dev) + cursor_wm); + } + ++static bool ++sandybridge_compute_sprite_wm(struct drm_device *dev, int plane, ++ uint32_t sprite_width, int pixel_size, ++ const struct intel_watermark_params *display, ++ int display_latency_ns, int *sprite_wm) ++{ ++ struct drm_crtc *crtc; ++ int clock; ++ int entries, tlb_miss; ++ ++ crtc = intel_get_crtc_for_plane(dev, plane); ++ if (crtc->fb == NULL || !crtc->enabled) { ++ *sprite_wm = display->guard_size; ++ return false; ++ } ++ ++ clock = crtc->mode.clock; ++ ++ /* Use the small buffer method to calculate the sprite watermark */ ++ entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; ++ tlb_miss = display->fifo_size*display->cacheline_size - ++ sprite_width * 8; ++ if (tlb_miss > 0) ++ entries += tlb_miss; ++ entries = DIV_ROUND_UP(entries, display->cacheline_size); ++ *sprite_wm = entries + display->guard_size; ++ if (*sprite_wm > (int)display->max_wm) ++ *sprite_wm = display->max_wm; ++ ++ return true; ++} ++ ++static bool ++sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane, ++ uint32_t sprite_width, int pixel_size, ++ const struct intel_watermark_params *display, ++ int latency_ns, int *sprite_wm) ++{ ++ struct drm_crtc *crtc; ++ unsigned long line_time_us; ++ int clock; ++ int line_count, line_size; ++ int small, large; ++ int entries; ++ ++ if (!latency_ns) { ++ *sprite_wm = 0; ++ return false; ++ } ++ ++ crtc = intel_get_crtc_for_plane(dev, plane); ++ clock = crtc->mode.clock; ++ if (!clock) { ++ *sprite_wm = 0; ++ return false; ++ } ++ ++ line_time_us = (sprite_width * 1000) / clock; ++ if (!line_time_us) { ++ *sprite_wm = 0; ++ return false; ++ } ++ ++ line_count = (latency_ns / line_time_us + 1000) / 1000; ++ line_size = sprite_width * pixel_size; ++ ++ /* Use the minimum of the small and large buffer method for primary */ ++ small = ((clock * pixel_size / 1000) * latency_ns) / 1000; ++ large = line_count * line_size; ++ ++ entries = DIV_ROUND_UP(min(small, large), display->cacheline_size); ++ *sprite_wm = entries + display->guard_size; ++ ++ return *sprite_wm > 0x3ff ? false : true; ++} ++ ++static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe, ++ uint32_t sprite_width, int pixel_size) ++{ ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ ++ u32 val; ++ int sprite_wm, reg; ++ int ret; ++ ++ switch (pipe) { ++ case 0: ++ reg = WM0_PIPEA_ILK; ++ break; ++ case 1: ++ reg = WM0_PIPEB_ILK; ++ break; ++ case 2: ++ reg = WM0_PIPEC_IVB; ++ break; ++ default: ++ return; /* bad pipe */ ++ } ++ ++ ret = sandybridge_compute_sprite_wm(dev, pipe, sprite_width, pixel_size, ++ &sandybridge_display_wm_info, ++ latency, &sprite_wm); ++ if (!ret) { ++ DRM_DEBUG_KMS("failed to compute sprite wm for pipe %d\n", ++ pipe); ++ return; ++ } ++ ++ val = I915_READ(reg); ++ val &= ~WM0_PIPE_SPRITE_MASK; ++ I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT)); ++ DRM_DEBUG_KMS("sprite watermarks For pipe %d - %d\n", pipe, sprite_wm); ++ ++ ++ ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, ++ pixel_size, ++ &sandybridge_display_srwm_info, ++ SNB_READ_WM1_LATENCY() * 500, ++ &sprite_wm); ++ if (!ret) { ++ DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %d\n", ++ pipe); ++ return; ++ } ++ I915_WRITE(WM1S_LP_ILK, sprite_wm); ++ ++ /* Only IVB has two more LP watermarks for sprite */ ++ if (!IS_IVYBRIDGE(dev)) ++ return; ++ ++ ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, ++ pixel_size, ++ &sandybridge_display_srwm_info, ++ SNB_READ_WM2_LATENCY() * 500, ++ &sprite_wm); ++ if (!ret) { ++ DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %d\n", ++ pipe); ++ return; ++ } ++ I915_WRITE(WM2S_LP_IVB, sprite_wm); ++ ++ ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, ++ pixel_size, ++ &sandybridge_display_srwm_info, ++ SNB_READ_WM3_LATENCY() * 500, ++ &sprite_wm); ++ if (!ret) { ++ DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %d\n", ++ pipe); ++ return; ++ } ++ I915_WRITE(WM3S_LP_IVB, sprite_wm); ++} ++ + /** + * intel_update_watermarks - update FIFO watermark values based on current modes + * +@@ -4686,6 +4912,16 @@ static void intel_update_watermarks(struct drm_device *dev) + dev_priv->display.update_wm(dev); + } + ++void intel_update_sprite_watermarks(struct drm_device *dev, int pipe, ++ uint32_t sprite_width, int pixel_size) ++{ ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ ++ if (dev_priv->display.update_sprite_wm) ++ dev_priv->display.update_sprite_wm(dev, pipe, sprite_width, ++ pixel_size); ++} ++ + static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) + { + if (i915_panel_use_ssc >= 0) +@@ -4833,6 +5069,82 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, + return display_bpc != bpc; + } + ++static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ int refclk; ++ ++ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && ++ intel_panel_use_ssc(dev_priv) && num_connectors < 2) { ++ refclk = dev_priv->lvds_ssc_freq * 1000; ++ DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", ++ refclk / 1000); ++ } else if (!IS_GEN2(dev)) { ++ refclk = 96000; ++ } else { ++ refclk = 48000; ++ } ++ ++ return refclk; ++} ++ ++static void i9xx_adjust_sdvo_tv_clock(struct drm_display_mode *adjusted_mode, ++ intel_clock_t *clock) ++{ ++ /* SDVO TV has fixed PLL values depend on its clock range, ++ this mirrors vbios setting. */ ++ if (adjusted_mode->clock >= 100000 ++ && adjusted_mode->clock < 140500) { ++ clock->p1 = 2; ++ clock->p2 = 10; ++ clock->n = 3; ++ clock->m1 = 16; ++ clock->m2 = 8; ++ } else if (adjusted_mode->clock >= 140500 ++ && adjusted_mode->clock <= 200000) { ++ clock->p1 = 1; ++ clock->p2 = 10; ++ clock->n = 6; ++ clock->m1 = 12; ++ clock->m2 = 8; ++ } ++} ++ ++static void i9xx_update_pll_dividers(struct drm_crtc *crtc, ++ intel_clock_t *clock, ++ intel_clock_t *reduced_clock) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); ++ int pipe = intel_crtc->pipe; ++ u32 fp, fp2 = 0; ++ ++ if (IS_PINEVIEW(dev)) { ++ fp = (1 << clock->n) << 16 | clock->m1 << 8 | clock->m2; ++ if (reduced_clock) ++ fp2 = (1 << reduced_clock->n) << 16 | ++ reduced_clock->m1 << 8 | reduced_clock->m2; ++ } else { ++ fp = clock->n << 16 | clock->m1 << 8 | clock->m2; ++ if (reduced_clock) ++ fp2 = reduced_clock->n << 16 | reduced_clock->m1 << 8 | ++ reduced_clock->m2; ++ } ++ ++ I915_WRITE(FP0(pipe), fp); ++ ++ intel_crtc->lowfreq_avail = false; ++ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && ++ reduced_clock && i915_powersave) { ++ I915_WRITE(FP1(pipe), fp2); ++ intel_crtc->lowfreq_avail = true; ++ } else { ++ I915_WRITE(FP1(pipe), fp); ++ } ++} ++ + static int i9xx_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, +@@ -4846,7 +5158,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, + int plane = intel_crtc->plane; + int refclk, num_connectors = 0; + intel_clock_t clock, reduced_clock; +- u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; ++ u32 dpll, dspcntr, pipeconf, vsyncshift; + bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; + bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; + struct drm_mode_config *mode_config = &dev->mode_config; +@@ -4887,15 +5199,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, + num_connectors++; + } + +- if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { +- refclk = dev_priv->lvds_ssc_freq * 1000; +- DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", +- refclk / 1000); +- } else if (!IS_GEN2(dev)) { +- refclk = 96000; +- } else { +- refclk = 48000; +- } ++ refclk = i9xx_get_refclk(crtc, num_connectors); + + /* + * Returns a set of divisors for the desired target clock with the given +@@ -4903,7 +5207,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + */ + limit = intel_limit(crtc, refclk); +- ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); ++ ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL, ++ &clock); + if (!ok) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return -EINVAL; +@@ -4913,53 +5218,24 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, + intel_crtc_update_cursor(crtc, true); + + if (is_lvds && dev_priv->lvds_downclock_avail) { ++ /* ++ * Ensure we match the reduced clock's P to the target clock. ++ * If the clocks don't match, we can't switch the display clock ++ * by using the FP0/FP1. In such case we will disable the LVDS ++ * downclock feature. ++ */ + has_reduced_clock = limit->find_pll(limit, crtc, + dev_priv->lvds_downclock, + refclk, ++ &clock, + &reduced_clock); +- if (has_reduced_clock && (clock.p != reduced_clock.p)) { +- /* +- * If the different P is found, it means that we can't +- * switch the display clock by using the FP0/FP1. +- * In such case we will disable the LVDS downclock +- * feature. +- */ +- DRM_DEBUG_KMS("Different P is found for " +- "LVDS clock/downclock\n"); +- has_reduced_clock = 0; +- } +- } +- /* SDVO TV has fixed PLL values depend on its clock range, +- this mirrors vbios setting. */ +- if (is_sdvo && is_tv) { +- if (adjusted_mode->clock >= 100000 +- && adjusted_mode->clock < 140500) { +- clock.p1 = 2; +- clock.p2 = 10; +- clock.n = 3; +- clock.m1 = 16; +- clock.m2 = 8; +- } else if (adjusted_mode->clock >= 140500 +- && adjusted_mode->clock <= 200000) { +- clock.p1 = 1; +- clock.p2 = 10; +- clock.n = 6; +- clock.m1 = 12; +- clock.m2 = 8; +- } + } + +- if (IS_PINEVIEW(dev)) { +- fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; +- if (has_reduced_clock) +- fp2 = (1 << reduced_clock.n) << 16 | +- reduced_clock.m1 << 8 | reduced_clock.m2; +- } else { +- fp = clock.n << 16 | clock.m1 << 8 | clock.m2; +- if (has_reduced_clock) +- fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | +- reduced_clock.m2; +- } ++ if (is_sdvo && is_tv) ++ i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock); ++ ++ i9xx_update_pll_dividers(crtc, &clock, has_reduced_clock ? ++ &reduced_clock : NULL); + + dpll = DPLL_VGA_MODE_DIS; + +@@ -5033,8 +5309,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, + /* Set up the display plane register */ + dspcntr = DISPPLANE_GAMMA_ENABLE; + +- /* Ironlake's plane is forced to pipe, bit 24 is to +- enable color space conversion */ + if (pipe == 0) + dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; + else +@@ -5069,7 +5343,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, + DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); + drm_mode_debug_printmodeline(mode); + +- I915_WRITE(FP0(pipe), fp); + I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); + + POSTING_READ(DPLL(pipe)); +@@ -5156,33 +5429,32 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, + I915_WRITE(DPLL(pipe), dpll); + } + +- intel_crtc->lowfreq_avail = false; +- if (is_lvds && has_reduced_clock && i915_powersave) { +- I915_WRITE(FP1(pipe), fp2); +- intel_crtc->lowfreq_avail = true; +- if (HAS_PIPE_CXSR(dev)) { ++ if (HAS_PIPE_CXSR(dev)) { ++ if (intel_crtc->lowfreq_avail) { + DRM_DEBUG_KMS("enabling CxSR downclocking\n"); + pipeconf |= PIPECONF_CXSR_DOWNCLOCK; +- } +- } else { +- I915_WRITE(FP1(pipe), fp); +- if (HAS_PIPE_CXSR(dev)) { ++ } else { + DRM_DEBUG_KMS("disabling CxSR downclocking\n"); + pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; + } + } + +- if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { ++ pipeconf &= ~PIPECONF_INTERLACE_MASK; ++ if (!IS_GEN2(dev) && ++ adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { + pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION; + /* the chip adds 2 halflines automatically */ +- adjusted_mode->crtc_vdisplay -= 1; + adjusted_mode->crtc_vtotal -= 1; +- adjusted_mode->crtc_vblank_start -= 1; + adjusted_mode->crtc_vblank_end -= 1; +- adjusted_mode->crtc_vsync_end -= 1; +- adjusted_mode->crtc_vsync_start -= 1; +- } else +- pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */ ++ vsyncshift = adjusted_mode->crtc_hsync_start ++ - adjusted_mode->crtc_htotal/2; ++ } else { ++ pipeconf |= PIPECONF_PROGRESSIVE; ++ vsyncshift = 0; ++ } ++ ++ if (!IS_GEN3(dev)) ++ I915_WRITE(VSYNCSHIFT(pipe), vsyncshift); + + I915_WRITE(HTOTAL(pipe), + (adjusted_mode->crtc_hdisplay - 1) | +@@ -5299,7 +5571,8 @@ void ironlake_init_pch_refclk(struct drm_device *dev) + if (intel_panel_use_ssc(dev_priv) && can_ssc) { + DRM_DEBUG_KMS("Using SSC on panel\n"); + temp |= DREF_SSC1_ENABLE; +- } ++ } else ++ temp &= ~DREF_SSC1_ENABLE; + + /* Get SSC going before enabling the outputs */ + I915_WRITE(PCH_DREF_CONTROL, temp); +@@ -5448,7 +5721,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + */ + limit = intel_limit(crtc, refclk); +- ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); ++ ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL, ++ &clock); + if (!ok) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return -EINVAL; +@@ -5458,21 +5732,17 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, + intel_crtc_update_cursor(crtc, true); + + if (is_lvds && dev_priv->lvds_downclock_avail) { ++ /* ++ * Ensure we match the reduced clock's P to the target clock. ++ * If the clocks don't match, we can't switch the display clock ++ * by using the FP0/FP1. In such case we will disable the LVDS ++ * downclock feature. ++ */ + has_reduced_clock = limit->find_pll(limit, crtc, + dev_priv->lvds_downclock, + refclk, ++ &clock, + &reduced_clock); +- if (has_reduced_clock && (clock.p != reduced_clock.p)) { +- /* +- * If the different P is found, it means that we can't +- * switch the display clock by using the FP0/FP1. +- * In such case we will disable the LVDS downclock +- * feature. +- */ +- DRM_DEBUG_KMS("Different P is found for " +- "LVDS clock/downclock\n"); +- has_reduced_clock = 0; +- } + } + /* SDVO TV has fixed PLL values depend on its clock range, + this mirrors vbios setting. */ +@@ -5767,17 +6037,19 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, + } + } + ++ pipeconf &= ~PIPECONF_INTERLACE_MASK; + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { +- pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION; ++ pipeconf |= PIPECONF_INTERLACED_ILK; + /* the chip adds 2 halflines automatically */ +- adjusted_mode->crtc_vdisplay -= 1; + adjusted_mode->crtc_vtotal -= 1; +- adjusted_mode->crtc_vblank_start -= 1; + adjusted_mode->crtc_vblank_end -= 1; +- adjusted_mode->crtc_vsync_end -= 1; +- adjusted_mode->crtc_vsync_start -= 1; +- } else +- pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */ ++ I915_WRITE(VSYNCSHIFT(pipe), ++ adjusted_mode->crtc_hsync_start ++ - adjusted_mode->crtc_htotal/2); ++ } else { ++ pipeconf |= PIPECONF_PROGRESSIVE; ++ I915_WRITE(VSYNCSHIFT(pipe), 0); ++ } + + I915_WRITE(HTOTAL(pipe), + (adjusted_mode->crtc_hdisplay - 1) | +@@ -5820,12 +6092,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, + + intel_wait_for_vblank(dev, pipe); + +- if (IS_GEN5(dev)) { +- /* enable address swizzle for tiling buffer */ +- temp = I915_READ(DISP_ARB_CTL); +- I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING); +- } +- + I915_WRITE(DSPCNTR(plane), dspcntr); + POSTING_READ(DSPCNTR(plane)); + +@@ -5852,14 +6118,45 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, + + ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode, + x, y, old_fb); +- + drm_vblank_post_modeset(dev, pipe); + +- intel_crtc->dpms_mode = DRM_MODE_DPMS_ON; ++ if (ret) ++ intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF; ++ else ++ intel_crtc->dpms_mode = DRM_MODE_DPMS_ON; + + return ret; + } + ++static bool intel_eld_uptodate(struct drm_connector *connector, ++ int reg_eldv, uint32_t bits_eldv, ++ int reg_elda, uint32_t bits_elda, ++ int reg_edid) ++{ ++ struct drm_i915_private *dev_priv = connector->dev->dev_private; ++ uint8_t *eld = connector->eld; ++ uint32_t i; ++ ++ i = I915_READ(reg_eldv); ++ i &= bits_eldv; ++ ++ if (!eld[0]) ++ return !i; ++ ++ if (!i) ++ return false; ++ ++ i = I915_READ(reg_elda); ++ i &= ~bits_elda; ++ I915_WRITE(reg_elda, i); ++ ++ for (i = 0; i < eld[2]; i++) ++ if (I915_READ(reg_edid) != *((uint32_t *)eld + i)) ++ return false; ++ ++ return true; ++} ++ + static void g4x_write_eld(struct drm_connector *connector, + struct drm_crtc *crtc) + { +@@ -5876,6 +6173,12 @@ static void g4x_write_eld(struct drm_connector *connector, + else + eldv = G4X_ELDV_DEVCTG; + ++ if (intel_eld_uptodate(connector, ++ G4X_AUD_CNTL_ST, eldv, ++ G4X_AUD_CNTL_ST, G4X_ELD_ADDR, ++ G4X_HDMIW_HDMIEDID)) ++ return; ++ + i = I915_READ(G4X_AUD_CNTL_ST); + i &= ~(eldv | G4X_ELD_ADDR); + len = (i >> 9) & 0x1f; /* ELD buffer size */ +@@ -5903,22 +6206,26 @@ static void ironlake_write_eld(struct drm_connector *connector, + uint32_t i; + int len; + int hdmiw_hdmiedid; ++ int aud_config; + int aud_cntl_st; + int aud_cntrl_st2; + + if (HAS_PCH_IBX(connector->dev)) { +- hdmiw_hdmiedid = GEN5_HDMIW_HDMIEDID_A; +- aud_cntl_st = GEN5_AUD_CNTL_ST_A; +- aud_cntrl_st2 = GEN5_AUD_CNTL_ST2; ++ hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID_A; ++ aud_config = IBX_AUD_CONFIG_A; ++ aud_cntl_st = IBX_AUD_CNTL_ST_A; ++ aud_cntrl_st2 = IBX_AUD_CNTL_ST2; + } else { +- hdmiw_hdmiedid = GEN7_HDMIW_HDMIEDID_A; +- aud_cntl_st = GEN7_AUD_CNTRL_ST_A; +- aud_cntrl_st2 = GEN7_AUD_CNTRL_ST2; ++ hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID_A; ++ aud_config = CPT_AUD_CONFIG_A; ++ aud_cntl_st = CPT_AUD_CNTL_ST_A; ++ aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; + } + + i = to_intel_crtc(crtc)->pipe; + hdmiw_hdmiedid += i * 0x100; + aud_cntl_st += i * 0x100; ++ aud_config += i * 0x100; + + DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i)); + +@@ -5927,14 +6234,27 @@ static void ironlake_write_eld(struct drm_connector *connector, + if (!i) { + DRM_DEBUG_DRIVER("Audio directed to unknown port\n"); + /* operate blindly on all ports */ +- eldv = GEN5_ELD_VALIDB; +- eldv |= GEN5_ELD_VALIDB << 4; +- eldv |= GEN5_ELD_VALIDB << 8; ++ eldv = IBX_ELD_VALIDB; ++ eldv |= IBX_ELD_VALIDB << 4; ++ eldv |= IBX_ELD_VALIDB << 8; + } else { + DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i); +- eldv = GEN5_ELD_VALIDB << ((i - 1) * 4); ++ eldv = IBX_ELD_VALIDB << ((i - 1) * 4); + } + ++ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { ++ DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); ++ eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ ++ I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ ++ } else ++ I915_WRITE(aud_config, 0); ++ ++ if (intel_eld_uptodate(connector, ++ aud_cntrl_st2, eldv, ++ aud_cntl_st, IBX_ELD_ADDRESS, ++ hdmiw_hdmiedid)) ++ return; ++ + i = I915_READ(aud_cntrl_st2); + i &= ~eldv; + I915_WRITE(aud_cntrl_st2, i); +@@ -5942,13 +6262,8 @@ static void ironlake_write_eld(struct drm_connector *connector, + if (!eld[0]) + return; + +- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { +- DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); +- eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ +- } +- + i = I915_READ(aud_cntl_st); +- i &= ~GEN5_ELD_ADDRESS; ++ i &= ~IBX_ELD_ADDRESS; + I915_WRITE(aud_cntl_st, i); + + len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */ +@@ -6332,7 +6647,7 @@ static struct drm_display_mode load_detect_mode = { + + static struct drm_framebuffer * + intel_framebuffer_create(struct drm_device *dev, +- struct drm_mode_fb_cmd *mode_cmd, ++ struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_i915_gem_object *obj) + { + struct intel_framebuffer *intel_fb; +@@ -6374,7 +6689,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, + int depth, int bpp) + { + struct drm_i915_gem_object *obj; +- struct drm_mode_fb_cmd mode_cmd; ++ struct drm_mode_fb_cmd2 mode_cmd; + + obj = i915_gem_alloc_object(dev, + intel_framebuffer_size_for_mode(mode, bpp)); +@@ -6383,9 +6698,9 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, + + mode_cmd.width = mode->hdisplay; + mode_cmd.height = mode->vdisplay; +- mode_cmd.depth = depth; +- mode_cmd.bpp = bpp; +- mode_cmd.pitch = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp); ++ mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width, ++ bpp); ++ mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); + + return intel_framebuffer_create(dev, &mode_cmd, obj); + } +@@ -6406,11 +6721,11 @@ mode_fits_in_fbdev(struct drm_device *dev, + return NULL; + + fb = &dev_priv->fbdev->ifb.base; +- if (fb->pitch < intel_framebuffer_pitch_for_width(mode->hdisplay, +- fb->bits_per_pixel)) ++ if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay, ++ fb->bits_per_pixel)) + return NULL; + +- if (obj->base.size < mode->vdisplay * fb->pitch) ++ if (obj->base.size < mode->vdisplay * fb->pitches[0]) + return NULL; + + return fb; +@@ -6742,9 +7057,7 @@ static void intel_increase_pllclock(struct drm_crtc *crtc) + if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) { + DRM_DEBUG_DRIVER("upclocking LVDS\n"); + +- /* Unlock panel regs */ +- I915_WRITE(PP_CONTROL, +- I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); ++ assert_panel_unlocked(dev_priv, pipe); + + dpll &= ~DISPLAY_RATE_SELECT_FPA1; + I915_WRITE(dpll_reg, dpll); +@@ -6753,9 +7066,6 @@ static void intel_increase_pllclock(struct drm_crtc *crtc) + dpll = I915_READ(dpll_reg); + if (dpll & DISPLAY_RATE_SELECT_FPA1) + DRM_DEBUG_DRIVER("failed to upclock LVDS!\n"); +- +- /* ...and lock them again */ +- I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3); + } + + /* Schedule downclock */ +@@ -6768,9 +7078,6 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc) + struct drm_device *dev = crtc->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +- int pipe = intel_crtc->pipe; +- int dpll_reg = DPLL(pipe); +- int dpll = I915_READ(dpll_reg); + + if (HAS_PCH_SPLIT(dev)) + return; +@@ -6783,23 +7090,22 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc) + * the manual case. + */ + if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) { ++ int pipe = intel_crtc->pipe; ++ int dpll_reg = DPLL(pipe); ++ u32 dpll; ++ + DRM_DEBUG_DRIVER("downclocking LVDS\n"); + +- /* Unlock panel regs */ +- I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | +- PANEL_UNLOCK_REGS); ++ assert_panel_unlocked(dev_priv, pipe); + ++ dpll = I915_READ(dpll_reg); + dpll |= DISPLAY_RATE_SELECT_FPA1; + I915_WRITE(dpll_reg, dpll); + intel_wait_for_vblank(dev, pipe); + dpll = I915_READ(dpll_reg); + if (!(dpll & DISPLAY_RATE_SELECT_FPA1)) + DRM_DEBUG_DRIVER("failed to downclock LVDS!\n"); +- +- /* ...and lock them again */ +- I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3); + } +- + } + + /** +@@ -6912,7 +7218,7 @@ static void intel_unpin_work_fn(struct work_struct *__work) + container_of(__work, struct intel_unpin_work, work); + + mutex_lock(&work->dev->struct_mutex); +- i915_gem_object_unpin(work->old_fb_obj); ++ intel_unpin_fb_obj(work->old_fb_obj); + drm_gem_object_unreference(&work->pending_flip_obj->base); + drm_gem_object_unreference(&work->old_fb_obj->base); + +@@ -7058,7 +7364,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev, + goto err; + + /* Offset into the new buffer for cases of shared fbs between CRTCs */ +- offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8; ++ offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; + + ret = BEGIN_LP_RING(6); + if (ret) +@@ -7075,16 +7381,16 @@ static int intel_gen2_queue_flip(struct drm_device *dev, + OUT_RING(MI_NOOP); + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); +- OUT_RING(fb->pitch); ++ OUT_RING(fb->pitches[0]); + OUT_RING(obj->gtt_offset + offset); +- OUT_RING(MI_NOOP); ++ OUT_RING(0); /* aux display base address, unused */ + + intel_mark_page_flip_active(intel_crtc); + ADVANCE_LP_RING(); + return 0; + + err_unpin: +- i915_gem_object_unpin(obj); ++ intel_unpin_fb_obj(obj); + err: + return ret; + } +@@ -7105,7 +7411,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev, + goto err; + + /* Offset into the new buffer for cases of shared fbs between CRTCs */ +- offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8; ++ offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; + + ret = BEGIN_LP_RING(6); + if (ret) +@@ -7119,7 +7425,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev, + OUT_RING(MI_NOOP); + OUT_RING(MI_DISPLAY_FLIP_I915 | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); +- OUT_RING(fb->pitch); ++ OUT_RING(fb->pitches[0]); + OUT_RING(obj->gtt_offset + offset); + OUT_RING(MI_NOOP); + +@@ -7128,7 +7434,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev, + return 0; + + err_unpin: +- i915_gem_object_unpin(obj); ++ intel_unpin_fb_obj(obj); + err: + return ret; + } +@@ -7157,7 +7463,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev, + */ + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); +- OUT_RING(fb->pitch); ++ OUT_RING(fb->pitches[0]); + OUT_RING(obj->gtt_offset | obj->tiling_mode); + + /* XXX Enabling the panel-fitter across page-flip is so far +@@ -7173,7 +7479,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev, + return 0; + + err_unpin: +- i915_gem_object_unpin(obj); ++ intel_unpin_fb_obj(obj); + err: + return ret; + } +@@ -7198,10 +7504,16 @@ static int intel_gen6_queue_flip(struct drm_device *dev, + + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); +- OUT_RING(fb->pitch | obj->tiling_mode); ++ OUT_RING(fb->pitches[0] | obj->tiling_mode); + OUT_RING(obj->gtt_offset); + +- pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE; ++ /* Contrary to the suggestions in the documentation, ++ * "Enable Panel Fitter" does not seem to be required when page ++ * flipping with a non-native mode, and worse causes a normal ++ * modeset to fail. ++ * pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE; ++ */ ++ pf = 0; + pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; + OUT_RING(pf | pipesrc); + +@@ -7210,7 +7522,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev, + return 0; + + err_unpin: +- i915_gem_object_unpin(obj); ++ intel_unpin_fb_obj(obj); + err: + return ret; + } +@@ -7252,26 +7564,12 @@ static int intel_gen7_queue_flip(struct drm_device *dev, + goto err_unpin; + } + +- /* +- * BSpec MI_DISPLAY_FLIP for IVB: +- * "The full packet must be contained within the same cache line." +- * +- * Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same +- * cacheline, if we ever start emitting more commands before +- * the MI_DISPLAY_FLIP we may need to first emit everything else, +- * then do the cacheline alignment, and finally emit the +- * MI_DISPLAY_FLIP. +- */ +- ret = intel_ring_cacheline_align(ring); +- if (ret) +- goto err_unpin; +- + ret = intel_ring_begin(ring, 4); + if (ret) + goto err_unpin; + + intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); +- intel_ring_emit(ring, (fb->pitch | obj->tiling_mode)); ++ intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); + intel_ring_emit(ring, (obj->gtt_offset)); + intel_ring_emit(ring, (MI_NOOP)); + +@@ -7280,7 +7578,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, + return 0; + + err_unpin: +- i915_gem_object_unpin(obj); ++ intel_unpin_fb_obj(obj); + err: + return ret; + } +@@ -7575,10 +7873,9 @@ static void intel_setup_outputs(struct drm_device *dev) + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_encoder *encoder; + bool dpd_is_edp = false; +- bool has_lvds = false; ++ bool has_lvds; + +- if (IS_MOBILE(dev) && !IS_I830(dev)) +- has_lvds = intel_lvds_init(dev); ++ has_lvds = intel_lvds_init(dev); + if (!has_lvds && !HAS_PCH_SPLIT(dev)) { + /* disable the panel fitter on everything but LVDS */ + I915_WRITE(PFIT_CONTROL, 0); +@@ -7707,7 +8004,7 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = { + + int intel_framebuffer_init(struct drm_device *dev, + struct intel_framebuffer *intel_fb, +- struct drm_mode_fb_cmd *mode_cmd, ++ struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_i915_gem_object *obj) + { + int ret; +@@ -7715,21 +8012,27 @@ int intel_framebuffer_init(struct drm_device *dev, + if (obj->tiling_mode == I915_TILING_Y) + return -EINVAL; + +- if (mode_cmd->pitch & 63) ++ if (mode_cmd->pitches[0] & 63) + return -EINVAL; + +- switch (mode_cmd->bpp) { +- case 8: +- case 16: +- /* Only pre-ILK can handle 5:5:5 */ +- if (mode_cmd->depth == 15 && !HAS_PCH_SPLIT(dev)) +- return -EINVAL; ++ switch (mode_cmd->pixel_format) { ++ case DRM_FORMAT_RGB332: ++ case DRM_FORMAT_RGB565: ++ case DRM_FORMAT_XRGB8888: ++ case DRM_FORMAT_XBGR8888: ++ case DRM_FORMAT_ARGB8888: ++ case DRM_FORMAT_XRGB2101010: ++ case DRM_FORMAT_ARGB2101010: ++ /* RGB formats are common across chipsets */ + break; +- +- case 24: +- case 32: ++ case DRM_FORMAT_YUYV: ++ case DRM_FORMAT_UYVY: ++ case DRM_FORMAT_YVYU: ++ case DRM_FORMAT_VYUY: + break; + default: ++ DRM_DEBUG_KMS("unsupported pixel format %u\n", ++ mode_cmd->pixel_format); + return -EINVAL; + } + +@@ -7747,11 +8050,12 @@ int intel_framebuffer_init(struct drm_device *dev, + static struct drm_framebuffer * + intel_user_framebuffer_create(struct drm_device *dev, + struct drm_file *filp, +- struct drm_mode_fb_cmd *mode_cmd) ++ struct drm_mode_fb_cmd2 *mode_cmd) + { + struct drm_i915_gem_object *obj; + +- obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle)); ++ obj = to_intel_bo(drm_gem_object_lookup(dev, filp, ++ mode_cmd->handles[0])); + if (&obj->base == NULL) + return ERR_PTR(-ENOENT); + +@@ -8020,7 +8324,7 @@ void intel_init_emon(struct drm_device *dev) + dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK); + } + +-static bool intel_enable_rc6(struct drm_device *dev) ++static int intel_enable_rc6(struct drm_device *dev) + { + /* + * Respect the kernel parameter if it is set +@@ -8038,11 +8342,11 @@ static bool intel_enable_rc6(struct drm_device *dev) + * Disable rc6 on Sandybridge + */ + if (INTEL_INFO(dev)->gen == 6) { +- DRM_DEBUG_DRIVER("Sandybridge: RC6 disabled\n"); +- return 0; ++ DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); ++ return INTEL_RC6_ENABLE; + } +- DRM_DEBUG_DRIVER("RC6 enabled\n"); +- return 1; ++ DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n"); ++ return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); + } + + void gen6_enable_rps(struct drm_i915_private *dev_priv) +@@ -8050,7 +8354,9 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) + u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); + u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); + u32 pcu_mbox, rc6_mask = 0; ++ u32 gtfifodbg; + int cur_freq, min_freq, max_freq; ++ int rc6_mode; + int i; + + /* Here begins a magic sequence of register writes to enable +@@ -8061,6 +8367,13 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) + */ + I915_WRITE(GEN6_RC_STATE, 0); + mutex_lock(&dev_priv->dev->struct_mutex); ++ ++ /* Clear the DBG now so we don't confuse earlier errors */ ++ if ((gtfifodbg = I915_READ(GTFIFODBG))) { ++ DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg); ++ I915_WRITE(GTFIFODBG, gtfifodbg); ++ } ++ + gen6_gt_force_wake_get(dev_priv); + + /* disable the counters and set deterministic thresholds */ +@@ -8081,9 +8394,20 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) + I915_WRITE(GEN6_RC6p_THRESHOLD, 150000); + I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ + +- if (intel_enable_rc6(dev_priv->dev)) +- rc6_mask = GEN6_RC_CTL_RC6_ENABLE | +- ((IS_GEN7(dev_priv->dev)) ? GEN6_RC_CTL_RC6p_ENABLE : 0); ++ rc6_mode = intel_enable_rc6(dev_priv->dev); ++ if (rc6_mode & INTEL_RC6_ENABLE) ++ rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; ++ ++ if (rc6_mode & INTEL_RC6p_ENABLE) ++ rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; ++ ++ if (rc6_mode & INTEL_RC6pp_ENABLE) ++ rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; ++ ++ DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", ++ (rc6_mode & INTEL_RC6_ENABLE) ? "on" : "off", ++ (rc6_mode & INTEL_RC6p_ENABLE) ? "on" : "off", ++ (rc6_mode & INTEL_RC6pp_ENABLE) ? "on" : "off"); + + I915_WRITE(GEN6_RC_CONTROL, + rc6_mask | +@@ -8311,6 +8635,10 @@ static void gen6_init_clock_gating(struct drm_device *dev) + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); + ++ I915_WRITE(GEN6_UCGCTL1, ++ I915_READ(GEN6_UCGCTL1) | ++ GEN6_BLBUNIT_CLOCK_GATE_DISABLE); ++ + /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock + * gating disable must be set. Failure to set it results in + * flickering pixels due to Z write ordering failures after +@@ -8389,6 +8717,10 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) + + I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); + ++ I915_WRITE(IVB_CHICKEN3, ++ CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | ++ CHICKEN3_DGMG_DONE_FIX_DISABLE); ++ + /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ + I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, + GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); +@@ -8699,9 +9031,15 @@ static void intel_init_display(struct drm_device *dev) + if (IS_IVYBRIDGE(dev)) { + u32 ecobus; + ++ /* A small trick here - if the bios hasn't configured MT forcewake, ++ * and if the device is in RC6, then force_wake_mt_get will not wake ++ * the device and the ECOBUS read will return zero. Which will be ++ * (correctly) interpreted by the test below as MT forcewake being ++ * disabled. ++ */ + mutex_lock(&dev->struct_mutex); + __gen6_gt_force_wake_mt_get(dev_priv); +- ecobus = I915_READ(ECOBUS); ++ ecobus = I915_READ_NOTRACE(ECOBUS); + __gen6_gt_force_wake_mt_put(dev_priv); + mutex_unlock(&dev->struct_mutex); + +@@ -8733,6 +9071,7 @@ static void intel_init_display(struct drm_device *dev) + } else if (IS_GEN6(dev)) { + if (SNB_READ_WM0_LATENCY()) { + dev_priv->display.update_wm = sandybridge_update_wm; ++ dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; + } else { + DRM_DEBUG_KMS("Failed to read display plane latency. " + "Disable CxSR\n"); +@@ -8746,6 +9085,7 @@ static void intel_init_display(struct drm_device *dev) + dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; + if (SNB_READ_WM0_LATENCY()) { + dev_priv->display.update_wm = sandybridge_update_wm; ++ dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; + } else { + DRM_DEBUG_KMS("Failed to read display plane latency. " + "Disable CxSR\n"); +@@ -8851,24 +9191,24 @@ static void quirk_ssc_force_disable(struct drm_device *dev) + } + + /* +- * A machine (e.g. Acer Aspire 5734Z) may need to invert the panel backlight +- * brightness value ++ * Some machines (Dell XPS13) suffer broken backlight controls if ++ * BLM_PCH_PWM_ENABLE is set. + */ +-static void quirk_invert_brightness(struct drm_device *dev) ++static void quirk_no_pcm_pwm_enable(struct drm_device *dev) + { + struct drm_i915_private *dev_priv = dev->dev_private; +- dev_priv->quirks |= QUIRK_INVERT_BRIGHTNESS; ++ dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE; ++ DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n"); + } + + /* +- * Some machines (Dell XPS13) suffer broken backlight controls if +- * BLM_PCH_PWM_ENABLE is set. ++ * A machine (e.g. Acer Aspire 5734Z) may need to invert the panel backlight ++ * brightness value + */ +-static void quirk_no_pcm_pwm_enable(struct drm_device *dev) ++static void quirk_invert_brightness(struct drm_device *dev) + { + struct drm_i915_private *dev_priv = dev->dev_private; +- dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE; +- DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n"); ++ dev_priv->quirks |= QUIRK_INVERT_BRIGHTNESS; + } + + struct intel_quirk { +@@ -8907,8 +9247,6 @@ static const struct intel_dmi_quirk intel_dmi_quirks[] = { + }; + + struct intel_quirk intel_quirks[] = { +- /* HP Compaq 2730p needs pipe A force quirk (LP: #291555) */ +- { 0x2a42, 0x103c, 0x30eb, quirk_pipea_force }, + /* HP Mini needs pipe A force quirk (LP: #322104) */ + { 0x27ae, 0x103c, 0x361a, quirk_pipea_force }, + +@@ -8946,12 +9284,6 @@ struct intel_quirk intel_quirks[] = { + /* Acer/Packard Bell NCL20 */ + { 0x2a42, 0x1025, 0x034b, quirk_invert_brightness }, + +- /* Acer Aspire 4736Z */ +- { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness }, +- +- /* Acer Aspire 5336 */ +- { 0x2a42, 0x1025, 0x048a, quirk_invert_brightness }, +- + /* Dell XPS13 HD Sandy Bridge */ + { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable }, + /* Dell XPS13 HD and XPS13 FHD Ivy Bridge */ +@@ -9022,13 +9354,16 @@ void i915_redisable_vga(struct drm_device *dev) + void intel_modeset_init(struct drm_device *dev) + { + struct drm_i915_private *dev_priv = dev->dev_private; +- int i; ++ int i, ret; + + drm_mode_config_init(dev); + + dev->mode_config.min_width = 0; + dev->mode_config.min_height = 0; + ++ dev->mode_config.preferred_depth = 24; ++ dev->mode_config.prefer_shadow = 1; ++ + dev->mode_config.funcs = (void *)&intel_mode_funcs; + + intel_init_quirks(dev); +@@ -9052,6 +9387,9 @@ void intel_modeset_init(struct drm_device *dev) + + for (i = 0; i < dev_priv->num_pipe; i++) { + intel_crtc_init(dev, i); ++ ret = intel_plane_init(dev, i); ++ if (ret) ++ DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret); + } + + /* Just disable it once at startup */ +@@ -9161,15 +9499,14 @@ void intel_connector_attach_encoder(struct intel_connector *connector, + int intel_modeset_vga_set_state(struct drm_device *dev, bool state) + { + struct drm_i915_private *dev_priv = dev->dev_private; +- unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL; + u16 gmch_ctrl; + +- pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl); ++ pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl); + if (state) + gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE; + else + gmch_ctrl |= INTEL_GMCH_VGA_DISABLE; +- pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl); ++ pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl); + return 0; + } + +diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c +index ca75076..9a3ecd6 100644 +--- a/drivers/gpu/drm/i915/intel_dp.c ++++ b/drivers/gpu/drm/i915/intel_dp.c +@@ -49,7 +49,7 @@ struct intel_dp { + uint32_t DP; + uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; + bool has_audio; +- int force_audio; ++ enum hdmi_force_audio force_audio; + uint32_t color_range; + int dpms_mode; + uint8_t link_bw; +@@ -384,7 +384,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, + else + aux_clock_divider = 225; /* eDP input clock at 450Mhz */ + } else if (HAS_PCH_SPLIT(dev)) +- aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */ ++ aux_clock_divider = 63; /* IRL input clock fixed at 125Mhz */ + else + aux_clock_divider = intel_hrawclk(dev) / 2; + +@@ -437,6 +437,10 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); ++ ++ if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | ++ DP_AUX_CH_CTL_RECEIVE_ERROR)) ++ continue; + if (status & DP_AUX_CH_CTL_DONE) + break; + } +@@ -483,7 +487,6 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, + uint8_t msg[20]; + int msg_bytes; + uint8_t ack; +- int retry; + + intel_dp_check_edp(intel_dp); + if (send_bytes > 16) +@@ -494,20 +497,18 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, + msg[3] = send_bytes - 1; + memcpy(&msg[4], send, send_bytes); + msg_bytes = send_bytes + 4; +- for (retry = 0; retry < 7; retry++) { ++ for (;;) { + ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1); + if (ret < 0) + return ret; + if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) +- return send_bytes; ++ break; + else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) +- usleep_range(400, 500); ++ udelay(100); + else + return -EIO; + } +- +- DRM_ERROR("too many retries, giving up\n"); +- return -EIO; ++ return send_bytes; + } + + /* Write a single byte to the aux channel in native mode */ +@@ -529,7 +530,6 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, + int reply_bytes; + uint8_t ack; + int ret; +- int retry; + + intel_dp_check_edp(intel_dp); + msg[0] = AUX_NATIVE_READ << 4; +@@ -540,7 +540,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, + msg_bytes = 4; + reply_bytes = recv_bytes + 1; + +- for (retry = 0; retry < 7; retry++) { ++ for (;;) { + ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, + reply, reply_bytes); + if (ret == 0) +@@ -553,13 +553,10 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, + return ret - 1; + } + else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) +- usleep_range(400, 500); ++ udelay(100); + else + return -EIO; + } +- +- DRM_ERROR("too many retries, giving up\n"); +- return -EIO; + } + + static int +@@ -2155,8 +2152,8 @@ intel_dp_detect(struct drm_connector *connector, bool force) + if (status != connector_status_connected) + return status; + +- if (intel_dp->force_audio) { +- intel_dp->has_audio = intel_dp->force_audio > 0; ++ if (intel_dp->force_audio != HDMI_AUDIO_AUTO) { ++ intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON); + } else { + edid = intel_dp_get_edid(connector, &intel_dp->adapter); + if (edid) { +@@ -2256,10 +2253,10 @@ intel_dp_set_property(struct drm_connector *connector, + + intel_dp->force_audio = i; + +- if (i == 0) ++ if (i == HDMI_AUDIO_AUTO) + has_audio = intel_dp_detect_audio(connector); + else +- has_audio = i > 0; ++ has_audio = (i == HDMI_AUDIO_ON); + + if (has_audio == intel_dp->has_audio) + return 0; +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index 5212284..018dfbd 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -26,6 +26,7 @@ + #define __INTEL_DRV_H__ + + #include ++#include "i915_drm.h" + #include "i915_drv.h" + #include "drm_crtc.h" + #include "drm_crtc_helper.h" +@@ -39,7 +40,7 @@ + ret__ = -ETIMEDOUT; \ + break; \ + } \ +- if (W && !(in_atomic() || in_dbg_master())) msleep(W); \ ++ if (W && drm_can_sleep()) msleep(W); \ + } \ + ret__; \ + }) +@@ -47,13 +48,6 @@ + #define wait_for(COND, MS) _wait_for(COND, MS, 1) + #define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0) + +-#define MSLEEP(x) do { \ +- if (in_dbg_master()) \ +- mdelay(x); \ +- else \ +- msleep(x); \ +-} while (0) +- + #define KHz(x) (1000*x) + #define MHz(x) KHz(1000*x) + +@@ -111,6 +105,10 @@ + #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0) + #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT) + #define INTEL_MODE_DP_FORCE_6BPC (0x10) ++/* This flag must be set by the encoder's mode_fixup if it changes the crtc ++ * timings in the mode to prevent the crtc fixup from overwriting them. ++ * Currently only lvds needs that. */ ++#define INTEL_MODE_CRTC_TIMINGS_SET (0x20) + + static inline void + intel_mode_set_pixel_multiplier(struct drm_display_mode *mode, +@@ -177,10 +175,32 @@ struct intel_crtc { + bool use_pll_a; + }; + ++struct intel_plane { ++ struct drm_plane base; ++ enum pipe pipe; ++ struct drm_i915_gem_object *obj; ++ bool primary_disabled; ++ int max_downscale; ++ u32 lut_r[1024], lut_g[1024], lut_b[1024]; ++ void (*update_plane)(struct drm_plane *plane, ++ struct drm_framebuffer *fb, ++ struct drm_i915_gem_object *obj, ++ int crtc_x, int crtc_y, ++ unsigned int crtc_w, unsigned int crtc_h, ++ uint32_t x, uint32_t y, ++ uint32_t src_w, uint32_t src_h); ++ void (*disable_plane)(struct drm_plane *plane); ++ int (*update_colorkey)(struct drm_plane *plane, ++ struct drm_intel_sprite_colorkey *key); ++ void (*get_colorkey)(struct drm_plane *plane, ++ struct drm_intel_sprite_colorkey *key); ++}; ++ + #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) + #define to_intel_connector(x) container_of(x, struct intel_connector, base) + #define to_intel_encoder(x) container_of(x, struct intel_encoder, base) + #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) ++#define to_intel_plane(x) container_of(x, struct intel_plane, base) + + #define DIP_HEADER_SIZE 5 + +@@ -271,6 +291,8 @@ struct intel_fbc_work { + int interval; + }; + ++int intel_connector_update_modes(struct drm_connector *connector, ++ struct edid *edid); + int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); + extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus); + +@@ -293,6 +315,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, + extern bool intel_dpd_is_edp(struct drm_device *dev); + extern void intel_edp_link_config(struct intel_encoder *, int *, int *); + extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder); ++extern int intel_plane_init(struct drm_device *dev, enum pipe pipe); + + /* intel_panel.c */ + extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, +@@ -360,10 +383,11 @@ extern void intel_init_emon(struct drm_device *dev); + extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, + struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined); ++extern void intel_unpin_fb_obj(struct drm_i915_gem_object *obj); + + extern int intel_framebuffer_init(struct drm_device *dev, + struct intel_framebuffer *ifb, +- struct drm_mode_fb_cmd *mode_cmd, ++ struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_i915_gem_object *obj); + extern int intel_fbdev_init(struct drm_device *dev); + extern void intel_fbdev_fini(struct drm_device *dev); +@@ -383,9 +407,25 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data, + extern void intel_fb_output_poll_changed(struct drm_device *dev); + extern void intel_fb_restore_mode(struct drm_device *dev); + ++extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, ++ bool state); ++#define assert_pipe_enabled(d, p) assert_pipe(d, p, true) ++#define assert_pipe_disabled(d, p) assert_pipe(d, p, false) ++ + extern void intel_init_clock_gating(struct drm_device *dev); + extern void intel_write_eld(struct drm_encoder *encoder, + struct drm_display_mode *mode); + extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe); + ++/* For use by IVB LP watermark workaround in intel_sprite.c */ ++extern void sandybridge_update_wm(struct drm_device *dev); ++extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe, ++ uint32_t sprite_width, ++ int pixel_size); ++ ++extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data, ++ struct drm_file *file_priv); ++extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data, ++ struct drm_file *file_priv); ++ + #endif /* __INTEL_DRV_H__ */ +diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c +index 8ac91b8..69bea56 100644 +--- a/drivers/gpu/drm/i915/intel_dvo.c ++++ b/drivers/gpu/drm/i915/intel_dvo.c +@@ -157,7 +157,6 @@ static bool intel_dvo_mode_fixup(struct drm_encoder *encoder, + C(vsync_end); + C(vtotal); + C(clock); +- drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); + #undef C + } + +diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c +index d0ce34b..6e9ee33 100644 +--- a/drivers/gpu/drm/i915/intel_fb.c ++++ b/drivers/gpu/drm/i915/intel_fb.c +@@ -65,7 +65,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, + struct drm_i915_private *dev_priv = dev->dev_private; + struct fb_info *info; + struct drm_framebuffer *fb; +- struct drm_mode_fb_cmd mode_cmd; ++ struct drm_mode_fb_cmd2 mode_cmd; + struct drm_i915_gem_object *obj; + struct device *device = &dev->pdev->dev; + int size, ret; +@@ -77,11 +77,12 @@ static int intelfb_create(struct intel_fbdev *ifbdev, + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height; + +- mode_cmd.bpp = sizes->surface_bpp; +- mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64); +- mode_cmd.depth = sizes->surface_depth; ++ mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) / ++ 8), 64); ++ mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, ++ sizes->surface_depth); + +- size = mode_cmd.pitch * mode_cmd.height; ++ size = mode_cmd.pitches[0] * mode_cmd.height; + size = ALIGN(size, PAGE_SIZE); + obj = i915_gem_alloc_object(dev, size); + if (!obj) { +@@ -148,14 +149,10 @@ static int intelfb_create(struct intel_fbdev *ifbdev, + + // memset(info->screen_base, 0, size); + +- drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); ++ drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); + +- info->pixmap.size = 64*1024; +- info->pixmap.buf_align = 8; +- info->pixmap.access_align = 32; +- info->pixmap.flags = FB_PIXMAP_SYSTEM; +- info->pixmap.scan_align = 1; ++ /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ + + DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", + fb->width, fb->height, +@@ -279,8 +276,18 @@ void intel_fb_restore_mode(struct drm_device *dev) + { + int ret; + drm_i915_private_t *dev_priv = dev->dev_private; ++ struct drm_mode_config *config = &dev->mode_config; ++ struct drm_plane *plane; ++ ++ mutex_lock(&dev->mode_config.mutex); + + ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper); + if (ret) + DRM_DEBUG("failed to restore crtc mode\n"); ++ ++ /* Be sure to shut off any planes that may be active */ ++ list_for_each_entry(plane, &config->plane_list, head) ++ plane->funcs->disable_plane(plane); ++ ++ mutex_unlock(&dev->mode_config.mutex); + } +diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c +index 497da2a..c60100d 100644 +--- a/drivers/gpu/drm/i915/intel_hdmi.c ++++ b/drivers/gpu/drm/i915/intel_hdmi.c +@@ -44,7 +44,7 @@ struct intel_hdmi { + uint32_t color_range; + bool has_hdmi_sink; + bool has_audio; +- int force_audio; ++ enum hdmi_force_audio force_audio; + void (*write_infoframe)(struct drm_encoder *encoder, + struct dip_infoframe *frame); + }; +@@ -143,9 +143,6 @@ static void i9xx_write_infoframe(struct drm_encoder *encoder, + I915_WRITE(VIDEO_DIP_DATA, *data); + data++; + } +- /* Write every possible data byte to force correct ECC calculation. */ +- for (; i < VIDEO_DIP_DATA_SIZE; i += 4) +- I915_WRITE(VIDEO_DIP_DATA, 0); + mmiowb(); + + flags |= intel_infoframe_flags(frame); +@@ -179,9 +176,6 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder, + I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); + data++; + } +- /* Write every possible data byte to force correct ECC calculation. */ +- for (; i < VIDEO_DIP_DATA_SIZE; i += 4) +- I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); + mmiowb(); + + flags |= intel_infoframe_flags(frame); +@@ -351,7 +345,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) + if (edid) { + if (edid->input & DRM_EDID_INPUT_DIGITAL) { + status = connector_status_connected; +- intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); ++ if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI) ++ intel_hdmi->has_hdmi_sink = ++ drm_detect_hdmi_monitor(edid); + intel_hdmi->has_audio = drm_detect_monitor_audio(edid); + } + connector->display_info.raw_edid = NULL; +@@ -359,8 +355,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) + } + + if (status == connector_status_connected) { +- if (intel_hdmi->force_audio) +- intel_hdmi->has_audio = intel_hdmi->force_audio > 0; ++ if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO) ++ intel_hdmi->has_audio = ++ (intel_hdmi->force_audio == HDMI_AUDIO_ON); + } + + return status; +@@ -414,7 +411,7 @@ intel_hdmi_set_property(struct drm_connector *connector, + return ret; + + if (property == dev_priv->force_audio_property) { +- int i = val; ++ enum hdmi_force_audio i = val; + bool has_audio; + + if (i == intel_hdmi->force_audio) +@@ -422,13 +419,13 @@ intel_hdmi_set_property(struct drm_connector *connector, + + intel_hdmi->force_audio = i; + +- if (i == 0) ++ if (i == HDMI_AUDIO_AUTO) + has_audio = intel_hdmi_detect_audio(connector); + else +- has_audio = i > 0; ++ has_audio = (i == HDMI_AUDIO_ON); + +- if (has_audio == intel_hdmi->has_audio) +- return 0; ++ if (i == HDMI_AUDIO_OFF_DVI) ++ intel_hdmi->has_hdmi_sink = 0; + + intel_hdmi->has_audio = has_audio; + goto done; +@@ -526,7 +523,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) + intel_encoder->type = INTEL_OUTPUT_HDMI; + + connector->polled = DRM_CONNECTOR_POLL_HPD; +- connector->interlace_allowed = 0; ++ connector->interlace_allowed = 1; + connector->doublescan_allowed = 0; + intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); + +diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c +index d30cccc..8fdc957 100644 +--- a/drivers/gpu/drm/i915/intel_i2c.c ++++ b/drivers/gpu/drm/i915/intel_i2c.c +@@ -37,7 +37,7 @@ + + /* Intel GPIO access functions */ + +-#define I2C_RISEFALL_TIME 20 ++#define I2C_RISEFALL_TIME 10 + + static inline struct intel_gmbus * + to_intel_gmbus(struct i2c_adapter *i2c) +@@ -45,13 +45,6 @@ to_intel_gmbus(struct i2c_adapter *i2c) + return container_of(i2c, struct intel_gmbus, adapter); + } + +-struct intel_gpio { +- struct i2c_adapter adapter; +- struct i2c_algo_bit_data algo; +- struct drm_i915_private *dev_priv; +- u32 reg; +-}; +- + void + intel_i2c_reset(struct drm_device *dev) + { +@@ -78,15 +71,15 @@ static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable) + I915_WRITE(DSPCLK_GATE_D, val); + } + +-static u32 get_reserved(struct intel_gpio *gpio) ++static u32 get_reserved(struct intel_gmbus *bus) + { +- struct drm_i915_private *dev_priv = gpio->dev_priv; ++ struct drm_i915_private *dev_priv = bus->dev_priv; + struct drm_device *dev = dev_priv->dev; + u32 reserved = 0; + + /* On most chips, these bits must be preserved in software. */ + if (!IS_I830(dev) && !IS_845G(dev)) +- reserved = I915_READ_NOTRACE(gpio->reg) & ++ reserved = I915_READ_NOTRACE(bus->gpio_reg) & + (GPIO_DATA_PULLUP_DISABLE | + GPIO_CLOCK_PULLUP_DISABLE); + +@@ -95,29 +88,29 @@ static u32 get_reserved(struct intel_gpio *gpio) + + static int get_clock(void *data) + { +- struct intel_gpio *gpio = data; +- struct drm_i915_private *dev_priv = gpio->dev_priv; +- u32 reserved = get_reserved(gpio); +- I915_WRITE_NOTRACE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK); +- I915_WRITE_NOTRACE(gpio->reg, reserved); +- return (I915_READ_NOTRACE(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0; ++ struct intel_gmbus *bus = data; ++ struct drm_i915_private *dev_priv = bus->dev_priv; ++ u32 reserved = get_reserved(bus); ++ I915_WRITE_NOTRACE(bus->gpio_reg, reserved | GPIO_CLOCK_DIR_MASK); ++ I915_WRITE_NOTRACE(bus->gpio_reg, reserved); ++ return (I915_READ_NOTRACE(bus->gpio_reg) & GPIO_CLOCK_VAL_IN) != 0; + } + + static int get_data(void *data) + { +- struct intel_gpio *gpio = data; +- struct drm_i915_private *dev_priv = gpio->dev_priv; +- u32 reserved = get_reserved(gpio); +- I915_WRITE_NOTRACE(gpio->reg, reserved | GPIO_DATA_DIR_MASK); +- I915_WRITE_NOTRACE(gpio->reg, reserved); +- return (I915_READ_NOTRACE(gpio->reg) & GPIO_DATA_VAL_IN) != 0; ++ struct intel_gmbus *bus = data; ++ struct drm_i915_private *dev_priv = bus->dev_priv; ++ u32 reserved = get_reserved(bus); ++ I915_WRITE_NOTRACE(bus->gpio_reg, reserved | GPIO_DATA_DIR_MASK); ++ I915_WRITE_NOTRACE(bus->gpio_reg, reserved); ++ return (I915_READ_NOTRACE(bus->gpio_reg) & GPIO_DATA_VAL_IN) != 0; + } + + static void set_clock(void *data, int state_high) + { +- struct intel_gpio *gpio = data; +- struct drm_i915_private *dev_priv = gpio->dev_priv; +- u32 reserved = get_reserved(gpio); ++ struct intel_gmbus *bus = data; ++ struct drm_i915_private *dev_priv = bus->dev_priv; ++ u32 reserved = get_reserved(bus); + u32 clock_bits; + + if (state_high) +@@ -126,15 +119,15 @@ static void set_clock(void *data, int state_high) + clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | + GPIO_CLOCK_VAL_MASK; + +- I915_WRITE_NOTRACE(gpio->reg, reserved | clock_bits); +- POSTING_READ(gpio->reg); ++ I915_WRITE_NOTRACE(bus->gpio_reg, reserved | clock_bits); ++ POSTING_READ(bus->gpio_reg); + } + + static void set_data(void *data, int state_high) + { +- struct intel_gpio *gpio = data; +- struct drm_i915_private *dev_priv = gpio->dev_priv; +- u32 reserved = get_reserved(gpio); ++ struct intel_gmbus *bus = data; ++ struct drm_i915_private *dev_priv = bus->dev_priv; ++ u32 reserved = get_reserved(bus); + u32 data_bits; + + if (state_high) +@@ -143,13 +136,14 @@ static void set_data(void *data, int state_high) + data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | + GPIO_DATA_VAL_MASK; + +- I915_WRITE_NOTRACE(gpio->reg, reserved | data_bits); +- POSTING_READ(gpio->reg); ++ I915_WRITE_NOTRACE(bus->gpio_reg, reserved | data_bits); ++ POSTING_READ(bus->gpio_reg); + } + +-static struct i2c_adapter * +-intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin) ++static bool ++intel_gpio_setup(struct intel_gmbus *bus, u32 pin) + { ++ struct drm_i915_private *dev_priv = bus->dev_priv; + static const int map_pin_to_reg[] = { + 0, + GPIOB, +@@ -160,65 +154,48 @@ intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin) + 0, + GPIOF, + }; +- struct intel_gpio *gpio; ++ struct i2c_algo_bit_data *algo; + + if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin]) +- return NULL; ++ return false; + +- gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL); +- if (gpio == NULL) +- return NULL; ++ algo = &bus->bit_algo; + +- gpio->reg = map_pin_to_reg[pin]; ++ bus->gpio_reg = map_pin_to_reg[pin]; + if (HAS_PCH_SPLIT(dev_priv->dev)) +- gpio->reg += PCH_GPIOA - GPIOA; +- gpio->dev_priv = dev_priv; +- +- snprintf(gpio->adapter.name, sizeof(gpio->adapter.name), +- "i915 GPIO%c", "?BACDE?F"[pin]); +- gpio->adapter.owner = THIS_MODULE; +- gpio->adapter.algo_data = &gpio->algo; +- gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev; +- gpio->algo.setsda = set_data; +- gpio->algo.setscl = set_clock; +- gpio->algo.getsda = get_data; +- gpio->algo.getscl = get_clock; +- gpio->algo.udelay = I2C_RISEFALL_TIME; +- gpio->algo.timeout = usecs_to_jiffies(2200); +- gpio->algo.data = gpio; +- +- if (i2c_bit_add_bus(&gpio->adapter)) +- goto out_free; +- +- return &gpio->adapter; +- +-out_free: +- kfree(gpio); +- return NULL; ++ bus->gpio_reg += PCH_GPIOA - GPIOA; ++ ++ bus->adapter.algo_data = algo; ++ algo->setsda = set_data; ++ algo->setscl = set_clock; ++ algo->getsda = get_data; ++ algo->getscl = get_clock; ++ algo->udelay = I2C_RISEFALL_TIME; ++ algo->timeout = usecs_to_jiffies(2200); ++ algo->data = bus; ++ ++ return true; + } + + static int +-intel_i2c_quirk_xfer(struct drm_i915_private *dev_priv, +- struct i2c_adapter *adapter, ++intel_i2c_quirk_xfer(struct intel_gmbus *bus, + struct i2c_msg *msgs, + int num) + { +- struct intel_gpio *gpio = container_of(adapter, +- struct intel_gpio, +- adapter); ++ struct drm_i915_private *dev_priv = bus->dev_priv; + int ret; + + intel_i2c_reset(dev_priv->dev); + + intel_i2c_quirk_set(dev_priv, true); +- set_data(gpio, 1); +- set_clock(gpio, 1); ++ set_data(bus, 1); ++ set_clock(bus, 1); + udelay(I2C_RISEFALL_TIME); + +- ret = adapter->algo->master_xfer(adapter, msgs, num); ++ ret = i2c_bit_algo.master_xfer(&bus->adapter, msgs, num); + +- set_data(gpio, 1); +- set_clock(gpio, 1); ++ set_data(bus, 1); ++ set_clock(bus, 1); + intel_i2c_quirk_set(dev_priv, false); + + return ret; +@@ -232,12 +209,15 @@ gmbus_xfer(struct i2c_adapter *adapter, + struct intel_gmbus *bus = container_of(adapter, + struct intel_gmbus, + adapter); +- struct drm_i915_private *dev_priv = adapter->algo_data; +- int i, reg_offset; ++ struct drm_i915_private *dev_priv = bus->dev_priv; ++ int i, reg_offset, ret; + +- if (bus->force_bit) +- return intel_i2c_quirk_xfer(dev_priv, +- bus->force_bit, msgs, num); ++ mutex_lock(&dev_priv->gmbus_mutex); ++ ++ if (bus->force_bit) { ++ ret = intel_i2c_quirk_xfer(bus, msgs, num); ++ goto out; ++ } + + reg_offset = HAS_PCH_SPLIT(dev_priv->dev) ? PCH_GMBUS0 - GMBUS0 : 0; + +@@ -249,7 +229,8 @@ gmbus_xfer(struct i2c_adapter *adapter, + + if (msgs[i].flags & I2C_M_RD) { + I915_WRITE(GMBUS1 + reg_offset, +- GMBUS_CYCLE_WAIT | (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | ++ GMBUS_CYCLE_WAIT | ++ (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | + (len << GMBUS_BYTE_COUNT_SHIFT) | + (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | + GMBUS_SLAVE_READ | GMBUS_SW_RDY); +@@ -278,7 +259,8 @@ gmbus_xfer(struct i2c_adapter *adapter, + + I915_WRITE(GMBUS3 + reg_offset, val); + I915_WRITE(GMBUS1 + reg_offset, +- (i + 1 == num ? GMBUS_CYCLE_STOP : GMBUS_CYCLE_WAIT) | ++ GMBUS_CYCLE_WAIT | ++ (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | + (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) | + (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | + GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); +@@ -317,11 +299,15 @@ clear_err: + I915_WRITE(GMBUS1 + reg_offset, 0); + + done: +- /* Mark the GMBUS interface as disabled. We will re-enable it at the +- * start of the next xfer, till then let it sleep. ++ /* Mark the GMBUS interface as disabled after waiting for idle. ++ * We will re-enable it at the start of the next xfer, ++ * till then let it sleep. + */ ++ if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, 10)) ++ DRM_INFO("GMBUS timed out waiting for idle\n"); + I915_WRITE(GMBUS0 + reg_offset, 0); +- return i; ++ ret = i; ++ goto out; + + timeout: + DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n", +@@ -329,23 +315,21 @@ timeout: + I915_WRITE(GMBUS0 + reg_offset, 0); + + /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ +- bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff); +- if (!bus->force_bit) +- return -ENOMEM; +- +- return intel_i2c_quirk_xfer(dev_priv, bus->force_bit, msgs, num); ++ if (!bus->has_gpio) { ++ ret = -EIO; ++ } else { ++ bus->force_bit = true; ++ ret = intel_i2c_quirk_xfer(bus, msgs, num); ++ } ++out: ++ mutex_unlock(&dev_priv->gmbus_mutex); ++ return ret; + } + + static u32 gmbus_func(struct i2c_adapter *adapter) + { +- struct intel_gmbus *bus = container_of(adapter, +- struct intel_gmbus, +- adapter); +- +- if (bus->force_bit) +- bus->force_bit->algo->functionality(bus->force_bit); +- +- return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | ++ return i2c_bit_algo.functionality(adapter) & ++ (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + /* I2C_FUNC_10BIT_ADDR | */ + I2C_FUNC_SMBUS_READ_BLOCK_DATA | + I2C_FUNC_SMBUS_BLOCK_PROC_CALL); +@@ -375,11 +359,13 @@ int intel_setup_gmbus(struct drm_device *dev) + struct drm_i915_private *dev_priv = dev->dev_private; + int ret, i; + +- dev_priv->gmbus = kcalloc(sizeof(struct intel_gmbus), GMBUS_NUM_PORTS, ++ dev_priv->gmbus = kcalloc(GMBUS_NUM_PORTS, sizeof(struct intel_gmbus), + GFP_KERNEL); + if (dev_priv->gmbus == NULL) + return -ENOMEM; + ++ mutex_init(&dev_priv->gmbus_mutex); ++ + for (i = 0; i < GMBUS_NUM_PORTS; i++) { + struct intel_gmbus *bus = &dev_priv->gmbus[i]; + +@@ -391,7 +377,7 @@ int intel_setup_gmbus(struct drm_device *dev) + names[i]); + + bus->adapter.dev.parent = &dev->pdev->dev; +- bus->adapter.algo_data = dev_priv; ++ bus->dev_priv = dev_priv; + + bus->adapter.algo = &gmbus_algorithm; + ret = i2c_add_adapter(&bus->adapter); +@@ -401,8 +387,11 @@ int intel_setup_gmbus(struct drm_device *dev) + /* By default use a conservative clock rate */ + bus->reg0 = i | GMBUS_RATE_100KHZ; + ++ bus->has_gpio = intel_gpio_setup(bus, i); ++ + /* XXX force bit banging until GMBUS is fully debugged */ +- bus->force_bit = intel_gpio_create(dev_priv, i); ++ if (bus->has_gpio) ++ bus->force_bit = true; + } + + intel_i2c_reset(dev_priv->dev); +@@ -430,19 +419,8 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) + { + struct intel_gmbus *bus = to_intel_gmbus(adapter); + +- if (force_bit) { +- if (bus->force_bit == NULL) { +- struct drm_i915_private *dev_priv = adapter->algo_data; +- bus->force_bit = intel_gpio_create(dev_priv, +- bus->reg0 & 0xff); +- } +- } else { +- if (bus->force_bit) { +- i2c_del_adapter(bus->force_bit); +- kfree(bus->force_bit); +- bus->force_bit = NULL; +- } +- } ++ if (bus->has_gpio) ++ bus->force_bit = force_bit; + } + + void intel_teardown_gmbus(struct drm_device *dev) +@@ -455,10 +433,6 @@ void intel_teardown_gmbus(struct drm_device *dev) + + for (i = 0; i < GMBUS_NUM_PORTS; i++) { + struct intel_gmbus *bus = &dev_priv->gmbus[i]; +- if (bus->force_bit) { +- i2c_del_adapter(bus->force_bit); +- kfree(bus->force_bit); +- } + i2c_del_adapter(&bus->adapter); + } + +diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c +index 4da8182..77190cc 100644 +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -187,6 +187,8 @@ centre_horizontally(struct drm_display_mode *mode, + + mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos; + mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width; ++ ++ mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET; + } + + static void +@@ -208,6 +210,8 @@ centre_vertically(struct drm_display_mode *mode, + + mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos; + mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width; ++ ++ mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET; + } + + static inline u32 panel_fitter_scaling(u32 source, u32 target) +@@ -283,6 +287,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, + for_each_pipe(pipe) + I915_WRITE(BCLRPAT(pipe), 0); + ++ drm_mode_set_crtcinfo(adjusted_mode, 0); ++ + switch (intel_lvds->fitting_mode) { + case DRM_MODE_SCALE_CENTER: + /* +@@ -893,6 +899,18 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev, + return false; + } + ++static bool intel_lvds_supported(struct drm_device *dev) ++{ ++ /* With the introduction of the PCH we gained a dedicated ++ * LVDS presence pin, use it. */ ++ if (HAS_PCH_SPLIT(dev)) ++ return true; ++ ++ /* Otherwise LVDS was only attached to mobile products, ++ * except for the inglorious 830gm */ ++ return IS_MOBILE(dev) && !IS_I830(dev); ++} ++ + /** + * intel_lvds_init - setup LVDS connectors on this device + * @dev: drm device +@@ -914,17 +932,8 @@ bool intel_lvds_init(struct drm_device *dev) + int pipe; + u8 pin; + +- /* +- * Unlock registers and just leave them unlocked. Do this before +- * checking quirk lists to avoid bogus WARNINGs. +- */ +- if (HAS_PCH_SPLIT(dev)) { +- I915_WRITE(PCH_PP_CONTROL, +- I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); +- } else { +- I915_WRITE(PP_CONTROL, +- I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); +- } ++ if (!intel_lvds_supported(dev)) ++ return false; + + /* Skip init on machines we know falsely report LVDS */ + if (dmi_check_system(intel_no_lvds)) +@@ -1100,6 +1109,19 @@ out: + pwm = I915_READ(BLC_PWM_PCH_CTL1); + pwm |= PWM_PCH_ENABLE; + I915_WRITE(BLC_PWM_PCH_CTL1, pwm); ++ /* ++ * Unlock registers and just ++ * leave them unlocked ++ */ ++ I915_WRITE(PCH_PP_CONTROL, ++ I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); ++ } else { ++ /* ++ * Unlock registers and just ++ * leave them unlocked ++ */ ++ I915_WRITE(PP_CONTROL, ++ I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); + } + dev_priv->lid_notifier.notifier_call = intel_lid_notify; + if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) { +diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c +index be2c6fe..9a2b270 100644 +--- a/drivers/gpu/drm/i915/intel_modes.c ++++ b/drivers/gpu/drm/i915/intel_modes.c +@@ -28,6 +28,7 @@ + #include + #include + #include "drmP.h" ++#include "drm_edid.h" + #include "intel_drv.h" + #include "i915_drv.h" + +@@ -42,13 +43,13 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus) + u8 buf[2]; + struct i2c_msg msgs[] = { + { +- .addr = 0x50, ++ .addr = DDC_ADDR, + .flags = 0, + .len = 1, + .buf = out_buf, + }, + { +- .addr = 0x50, ++ .addr = DDC_ADDR, + .flags = I2C_M_RD, + .len = 1, + .buf = buf, +@@ -59,6 +60,25 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus) + } + + /** ++ * intel_connector_update_modes - update connector from edid ++ * @connector: DRM connector device to use ++ * @edid: previously read EDID information ++ */ ++int intel_connector_update_modes(struct drm_connector *connector, ++ struct edid *edid) ++{ ++ int ret; ++ ++ drm_mode_connector_update_edid_property(connector, edid); ++ ret = drm_add_edid_modes(connector, edid); ++ drm_edid_to_eld(connector, edid); ++ connector->display_info.raw_edid = NULL; ++ kfree(edid); ++ ++ return ret; ++} ++ ++/** + * intel_ddc_get_modes - get modelist from monitor + * @connector: DRM connector device to use + * @adapter: i2c adapter +@@ -69,24 +89,19 @@ int intel_ddc_get_modes(struct drm_connector *connector, + struct i2c_adapter *adapter) + { + struct edid *edid; +- int ret = 0; + + edid = drm_get_edid(connector, adapter); +- if (edid) { +- drm_mode_connector_update_edid_property(connector, edid); +- ret = drm_add_edid_modes(connector, edid); +- drm_edid_to_eld(connector, edid); +- connector->display_info.raw_edid = NULL; +- kfree(edid); +- } ++ if (!edid) ++ return 0; + +- return ret; ++ return intel_connector_update_modes(connector, edid); + } + +-static const char *force_audio_names[] = { +- "off", +- "auto", +- "on", ++static const struct drm_prop_enum_list force_audio_names[] = { ++ { HDMI_AUDIO_OFF_DVI, "force-dvi" }, ++ { HDMI_AUDIO_OFF, "off" }, ++ { HDMI_AUDIO_AUTO, "auto" }, ++ { HDMI_AUDIO_ON, "on" }, + }; + + void +@@ -95,27 +110,24 @@ intel_attach_force_audio_property(struct drm_connector *connector) + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_property *prop; +- int i; + + prop = dev_priv->force_audio_property; + if (prop == NULL) { +- prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, ++ prop = drm_property_create_enum(dev, 0, + "audio", ++ force_audio_names, + ARRAY_SIZE(force_audio_names)); + if (prop == NULL) + return; + +- for (i = 0; i < ARRAY_SIZE(force_audio_names); i++) +- drm_property_add_enum(prop, i, i-1, force_audio_names[i]); +- + dev_priv->force_audio_property = prop; + } + drm_connector_attach_property(connector, prop, 0); + } + +-static const char *broadcast_rgb_names[] = { +- "Full", +- "Limited 16:235", ++static const struct drm_prop_enum_list broadcast_rgb_names[] = { ++ { 0, "Full" }, ++ { 1, "Limited 16:235" }, + }; + + void +@@ -124,19 +136,16 @@ intel_attach_broadcast_rgb_property(struct drm_connector *connector) + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_property *prop; +- int i; + + prop = dev_priv->broadcast_rgb_property; + if (prop == NULL) { +- prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, ++ prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, + "Broadcast RGB", ++ broadcast_rgb_names, + ARRAY_SIZE(broadcast_rgb_names)); + if (prop == NULL) + return; + +- for (i = 0; i < ARRAY_SIZE(broadcast_rgb_names); i++) +- drm_property_add_enum(prop, i, i, broadcast_rgb_names[i]); +- + dev_priv->broadcast_rgb_property = prop; + } + +diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c +index 478b51f..5ba5e66 100644 +--- a/drivers/gpu/drm/i915/intel_overlay.c ++++ b/drivers/gpu/drm/i915/intel_overlay.c +@@ -25,8 +25,6 @@ + * + * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c + */ +- +-#include + #include "drmP.h" + #include "drm.h" + #include "i915_drm.h" +@@ -227,7 +225,8 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, + } + overlay->last_flip_req = request->seqno; + overlay->flip_tail = tail; +- ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req); ++ ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req, ++ true); + if (ret) + return ret; + +@@ -263,7 +262,7 @@ i830_activate_pipe_a(struct drm_device *dev) + DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n"); + + mode = drm_mode_duplicate(dev, &vesa_640x480); +- drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); ++ drm_mode_set_crtcinfo(mode, 0); + if (!drm_crtc_helper_set_mode(&crtc->base, mode, + crtc->base.x, crtc->base.y, + crtc->base.fb)) +@@ -456,7 +455,8 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) + if (overlay->last_flip_req == 0) + return 0; + +- ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req); ++ ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req, ++ true); + if (ret) + return ret; + +@@ -943,10 +943,10 @@ static int check_overlay_dst(struct intel_overlay *overlay, + { + struct drm_display_mode *mode = &overlay->crtc->base.mode; + +- if (rec->dst_x < mode->crtc_hdisplay && +- rec->dst_x + rec->dst_width <= mode->crtc_hdisplay && +- rec->dst_y < mode->crtc_vdisplay && +- rec->dst_y + rec->dst_height <= mode->crtc_vdisplay) ++ if (rec->dst_x < mode->hdisplay && ++ rec->dst_x + rec->dst_width <= mode->hdisplay && ++ rec->dst_y < mode->vdisplay && ++ rec->dst_y + rec->dst_height <= mode->vdisplay) + return 0; + else + return -EINVAL; +diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c +index 04cb34a..0bae2bb 100644 +--- a/drivers/gpu/drm/i915/intel_panel.c ++++ b/drivers/gpu/drm/i915/intel_panel.c +@@ -48,8 +48,6 @@ intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, + adjusted_mode->vtotal = fixed_mode->vtotal; + + adjusted_mode->clock = fixed_mode->clock; +- +- drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); + } + + /* adjusted_mode has been preset to be the panel's fixed mode */ +@@ -142,8 +140,8 @@ static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv) + dev_priv->saveBLC_PWM_CTL2 = val; + } else if (val == 0) { + I915_WRITE(BLC_PWM_PCH_CTL2, +- dev_priv->saveBLC_PWM_CTL); +- val = dev_priv->saveBLC_PWM_CTL; ++ dev_priv->saveBLC_PWM_CTL2); ++ val = dev_priv->saveBLC_PWM_CTL2; + } + } else { + val = I915_READ(BLC_PWM_CTL); +diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c +index 8ee068e..bd66291 100644 +--- a/drivers/gpu/drm/i915/intel_ringbuffer.c ++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c +@@ -263,6 +263,8 @@ static int init_ring_common(struct intel_ring_buffer *ring) + I915_WRITE_HEAD(ring, 0); + ring->write_tail(ring, 0); + ++ /* Initialize the ring. */ ++ I915_WRITE_START(ring, obj->gtt_offset); + head = I915_READ_HEAD(ring) & HEAD_ADDR; + + /* G45 ring initialization fails to reset head to zero */ +@@ -288,11 +290,6 @@ static int init_ring_common(struct intel_ring_buffer *ring) + } + } + +- /* Initialize the ring. This must happen _after_ we've cleared the ring +- * registers with the above sequence (the readback of the HEAD registers +- * also enforces ordering), otherwise the hw might lose the new ring +- * register values. */ +- I915_WRITE_START(ring, obj->gtt_offset); + I915_WRITE_CTL(ring, + ((ring->size - PAGE_SIZE) & RING_NR_PAGES) + | RING_VALID); +@@ -318,6 +315,7 @@ static int init_ring_common(struct intel_ring_buffer *ring) + ring->head = I915_READ_HEAD(ring); + ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; + ring->space = ring_space(ring); ++ ring->last_retired_head = -1; + } + + out: +@@ -615,6 +613,7 @@ pc_render_add_request(struct intel_ring_buffer *ring, + PIPE_CONTROL_FLUSH(ring, scratch_addr); + scratch_addr += 128; + PIPE_CONTROL_FLUSH(ring, scratch_addr); ++ + intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | + PIPE_CONTROL_WRITE_FLUSH | + PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | +@@ -657,7 +656,7 @@ gen6_ring_get_seqno(struct intel_ring_buffer *ring) + /* Workaround to force correct ordering between irq and seqno writes on + * ivb (and maybe also on snb) by reading from a CS register (like + * ACTHD) before reading the status page. */ +- if (IS_GEN7(dev)) ++ if (IS_GEN6(dev) || IS_GEN7(dev)) + intel_ring_get_active_head(ring); + return intel_read_status_page(ring, I915_GEM_HWS_INDEX); + } +@@ -695,16 +694,26 @@ static void + i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask) + { + dev_priv->irq_mask &= ~mask; +- I915_WRITE(IMR, dev_priv->irq_mask); +- POSTING_READ(IMR); ++ if (IS_GEN2(dev_priv->dev)) { ++ I915_WRITE16(IMR, dev_priv->irq_mask); ++ POSTING_READ16(IMR); ++ } else { ++ I915_WRITE(IMR, dev_priv->irq_mask); ++ POSTING_READ(IMR); ++ } + } + + static void + i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask) + { + dev_priv->irq_mask |= mask; +- I915_WRITE(IMR, dev_priv->irq_mask); +- POSTING_READ(IMR); ++ if (IS_GEN2(dev_priv->dev)) { ++ I915_WRITE16(IMR, dev_priv->irq_mask); ++ POSTING_READ16(IMR); ++ } else { ++ I915_WRITE(IMR, dev_priv->irq_mask); ++ POSTING_READ(IMR); ++ } + } + + static bool +@@ -758,13 +767,13 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring) + */ + if (IS_GEN7(dev)) { + switch (ring->id) { +- case RING_RENDER: ++ case RCS: + mmio = RENDER_HWS_PGA_GEN7; + break; +- case RING_BLT: ++ case BCS: + mmio = BLT_HWS_PGA_GEN7; + break; +- case RING_BSD: ++ case VCS: + mmio = BSD_HWS_PGA_GEN7; + break; + } +@@ -842,8 +851,7 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag) + /* It looks like we need to prevent the gt from suspending while waiting + * for an notifiy irq, otherwise irqs seem to get lost on at least the + * blt/bsd rings on ivb. */ +- if (IS_GEN7(dev)) +- gen6_gt_force_wake_get(dev_priv); ++ gen6_gt_force_wake_get(dev_priv); + + spin_lock(&ring->irq_lock); + if (ring->irq_refcount++ == 0) { +@@ -870,8 +878,7 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag) + } + spin_unlock(&ring->irq_lock); + +- if (IS_GEN7(dev)) +- gen6_gt_force_wake_put(dev_priv); ++ gen6_gt_force_wake_put(dev_priv); + } + + static bool +@@ -1157,14 +1164,105 @@ static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring) + return 0; + } + ++static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno) ++{ ++ struct drm_i915_private *dev_priv = ring->dev->dev_private; ++ bool was_interruptible; ++ int ret; ++ ++ /* XXX As we have not yet audited all the paths to check that ++ * they are ready for ERESTARTSYS from intel_ring_begin, do not ++ * allow us to be interruptible by a signal. ++ */ ++ was_interruptible = dev_priv->mm.interruptible; ++ dev_priv->mm.interruptible = false; ++ ++ ret = i915_wait_request(ring, seqno, true); ++ ++ dev_priv->mm.interruptible = was_interruptible; ++ ++ return ret; ++} ++ ++static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n) ++{ ++ struct drm_i915_gem_request *request; ++ u32 seqno = 0; ++ int ret; ++ ++ i915_gem_retire_requests_ring(ring); ++ ++ if (ring->last_retired_head != -1) { ++ ring->head = ring->last_retired_head; ++ ring->last_retired_head = -1; ++ ring->space = ring_space(ring); ++ if (ring->space >= n) ++ return 0; ++ } ++ ++ list_for_each_entry(request, &ring->request_list, list) { ++ int space; ++ ++ if (request->tail == -1) ++ continue; ++ ++ space = request->tail - (ring->tail + 8); ++ if (space < 0) ++ space += ring->size; ++ if (space >= n) { ++ seqno = request->seqno; ++ break; ++ } ++ ++ /* Consume this request in case we need more space than ++ * is available and so need to prevent a race between ++ * updating last_retired_head and direct reads of ++ * I915_RING_HEAD. It also provides a nice sanity check. ++ */ ++ request->tail = -1; ++ } ++ ++ if (seqno == 0) ++ return -ENOSPC; ++ ++ ret = intel_ring_wait_seqno(ring, seqno); ++ if (ret) ++ return ret; ++ ++ if (WARN_ON(ring->last_retired_head == -1)) ++ return -ENOSPC; ++ ++ ring->head = ring->last_retired_head; ++ ring->last_retired_head = -1; ++ ring->space = ring_space(ring); ++ if (WARN_ON(ring->space < n)) ++ return -ENOSPC; ++ ++ return 0; ++} ++ + int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) + { + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long end; ++ int ret; ++ ++ ret = intel_ring_wait_request(ring, n); ++ if (ret != -ENOSPC) ++ return ret; + + trace_i915_ring_wait_begin(ring); +- end = jiffies + 3 * HZ; ++ if (drm_core_check_feature(dev, DRIVER_GEM)) ++ /* With GEM the hangcheck timer should kick us out of the loop, ++ * leaving it early runs the risk of corrupting GEM state (due ++ * to running on almost untested codepaths). But on resume ++ * timers don't work yet, so prevent a complete hang in that ++ * case by choosing an insanely large timeout. */ ++ end = jiffies + 60 * HZ; ++ else ++ end = jiffies + 3 * HZ; ++ + do { + ring->head = I915_READ_HEAD(ring); + ring->space = ring_space(ring); +@@ -1213,27 +1311,6 @@ int intel_ring_begin(struct intel_ring_buffer *ring, + return 0; + } + +-/* Align the ring tail to a cacheline boundary */ +-int intel_ring_cacheline_align(struct intel_ring_buffer *ring) +-{ +- int num_dwords = (64 - (ring->tail & 63)) / sizeof(uint32_t); +- int ret; +- +- if (num_dwords == 0) +- return 0; +- +- ret = intel_ring_begin(ring, num_dwords); +- if (ret) +- return ret; +- +- while (num_dwords--) +- intel_ring_emit(ring, MI_NOOP); +- +- intel_ring_advance(ring); +- +- return 0; +-} +- + void intel_ring_advance(struct intel_ring_buffer *ring) + { + ring->tail &= ring->size - 1; +@@ -1242,7 +1319,7 @@ void intel_ring_advance(struct intel_ring_buffer *ring) + + static const struct intel_ring_buffer render_ring = { + .name = "render ring", +- .id = RING_RENDER, ++ .id = RCS, + .mmio_base = RENDER_RING_BASE, + .size = 32 * PAGE_SIZE, + .init = init_render_ring, +@@ -1265,7 +1342,7 @@ static const struct intel_ring_buffer render_ring = { + + static const struct intel_ring_buffer bsd_ring = { + .name = "bsd ring", +- .id = RING_BSD, ++ .id = VCS, + .mmio_base = BSD_RING_BASE, + .size = 32 * PAGE_SIZE, + .init = init_ring_common, +@@ -1375,7 +1452,7 @@ gen6_bsd_ring_put_irq(struct intel_ring_buffer *ring) + /* ring buffer for Video Codec for Gen6+ */ + static const struct intel_ring_buffer gen6_bsd_ring = { + .name = "gen6 bsd ring", +- .id = RING_BSD, ++ .id = VCS, + .mmio_base = GEN6_BSD_RING_BASE, + .size = 32 * PAGE_SIZE, + .init = init_ring_common, +@@ -1411,79 +1488,13 @@ blt_ring_put_irq(struct intel_ring_buffer *ring) + GEN6_BLITTER_USER_INTERRUPT); + } + +- +-/* Workaround for some stepping of SNB, +- * each time when BLT engine ring tail moved, +- * the first command in the ring to be parsed +- * should be MI_BATCH_BUFFER_START +- */ +-#define NEED_BLT_WORKAROUND(dev) \ +- (IS_GEN6(dev) && (dev->pdev->revision < 8)) +- +-static inline struct drm_i915_gem_object * +-to_blt_workaround(struct intel_ring_buffer *ring) +-{ +- return ring->private; +-} +- +-static int blt_ring_init(struct intel_ring_buffer *ring) +-{ +- if (NEED_BLT_WORKAROUND(ring->dev)) { +- struct drm_i915_gem_object *obj; +- u32 *ptr; +- int ret; +- +- obj = i915_gem_alloc_object(ring->dev, 4096); +- if (obj == NULL) +- return -ENOMEM; +- +- ret = i915_gem_object_pin(obj, 4096, true); +- if (ret) { +- drm_gem_object_unreference(&obj->base); +- return ret; +- } +- +- ptr = kmap(obj->pages[0]); +- *ptr++ = MI_BATCH_BUFFER_END; +- *ptr++ = MI_NOOP; +- kunmap(obj->pages[0]); +- +- ret = i915_gem_object_set_to_gtt_domain(obj, false); +- if (ret) { +- i915_gem_object_unpin(obj); +- drm_gem_object_unreference(&obj->base); +- return ret; +- } +- +- ring->private = obj; +- } +- +- return init_ring_common(ring); +-} +- +-static int blt_ring_begin(struct intel_ring_buffer *ring, +- int num_dwords) +-{ +- if (ring->private) { +- int ret = intel_ring_begin(ring, num_dwords+2); +- if (ret) +- return ret; +- +- intel_ring_emit(ring, MI_BATCH_BUFFER_START); +- intel_ring_emit(ring, to_blt_workaround(ring)->gtt_offset); +- +- return 0; +- } else +- return intel_ring_begin(ring, 4); +-} +- + static int blt_ring_flush(struct intel_ring_buffer *ring, + u32 invalidate, u32 flush) + { + uint32_t cmd; + int ret; + +- ret = blt_ring_begin(ring, 4); ++ ret = intel_ring_begin(ring, 4); + if (ret) + return ret; + +@@ -1498,22 +1509,12 @@ static int blt_ring_flush(struct intel_ring_buffer *ring, + return 0; + } + +-static void blt_ring_cleanup(struct intel_ring_buffer *ring) +-{ +- if (!ring->private) +- return; +- +- i915_gem_object_unpin(ring->private); +- drm_gem_object_unreference(ring->private); +- ring->private = NULL; +-} +- + static const struct intel_ring_buffer gen6_blt_ring = { + .name = "blt ring", +- .id = RING_BLT, ++ .id = BCS, + .mmio_base = BLT_RING_BASE, + .size = 32 * PAGE_SIZE, +- .init = blt_ring_init, ++ .init = init_ring_common, + .write_tail = ring_write_tail, + .flush = blt_ring_flush, + .add_request = gen6_add_request, +@@ -1521,7 +1522,6 @@ static const struct intel_ring_buffer gen6_blt_ring = { + .irq_get = blt_ring_get_irq, + .irq_put = blt_ring_put_irq, + .dispatch_execbuffer = gen6_ring_dispatch_execbuffer, +- .cleanup = blt_ring_cleanup, + .sync_to = gen6_blt_ring_sync_to, + .semaphore_register = {MI_SEMAPHORE_SYNC_BR, + MI_SEMAPHORE_SYNC_BV, +diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h +index d83cc97..bc0365b 100644 +--- a/drivers/gpu/drm/i915/intel_ringbuffer.h ++++ b/drivers/gpu/drm/i915/intel_ringbuffer.h +@@ -1,13 +1,6 @@ + #ifndef _INTEL_RINGBUFFER_H_ + #define _INTEL_RINGBUFFER_H_ + +-enum { +- RCS = 0x0, +- VCS, +- BCS, +- I915_NUM_RINGS, +-}; +- + struct intel_hw_status_page { + u32 __iomem *page_addr; + unsigned int gfx_addr; +@@ -36,10 +29,11 @@ struct intel_hw_status_page { + struct intel_ring_buffer { + const char *name; + enum intel_ring_id { +- RING_RENDER = 0x1, +- RING_BSD = 0x2, +- RING_BLT = 0x4, ++ RCS = 0x0, ++ VCS, ++ BCS, + } id; ++#define I915_NUM_RINGS 3 + u32 mmio_base; + void __iomem *virtual_start; + struct drm_device *dev; +@@ -52,6 +46,16 @@ struct intel_ring_buffer { + int effective_size; + struct intel_hw_status_page status_page; + ++ /** We track the position of the requests in the ring buffer, and ++ * when each is retired we increment last_retired_head as the GPU ++ * must have finished processing the request and so we know we ++ * can advance the ringbuffer up to that position. ++ * ++ * last_retired_head is set to -1 after the value is consumed so ++ * we can detect new retirements. ++ */ ++ u32 last_retired_head; ++ + spinlock_t irq_lock; + u32 irq_refcount; + u32 irq_mask; +@@ -119,6 +123,12 @@ struct intel_ring_buffer { + void *private; + }; + ++static inline unsigned ++intel_ring_flag(struct intel_ring_buffer *ring) ++{ ++ return 1 << ring->id; ++} ++ + static inline u32 + intel_ring_sync_index(struct intel_ring_buffer *ring, + struct intel_ring_buffer *other) +@@ -174,7 +184,6 @@ static inline int intel_wait_ring_idle(struct intel_ring_buffer *ring) + } + + int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n); +-int __must_check intel_ring_cacheline_align(struct intel_ring_buffer *ring); + + static inline void intel_ring_emit(struct intel_ring_buffer *ring, + u32 data) +@@ -194,6 +203,11 @@ int intel_init_blt_ring_buffer(struct drm_device *dev); + u32 intel_ring_get_active_head(struct intel_ring_buffer *ring); + void intel_ring_setup_status_page(struct intel_ring_buffer *ring); + ++static inline u32 intel_ring_get_tail(struct intel_ring_buffer *ring) ++{ ++ return ring->tail; ++} ++ + static inline void i915_trace_irq_get(struct intel_ring_buffer *ring, u32 seqno) + { + if (ring->trace_irq_seqno == 0 && ring->irq_get(ring)) +diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c +index 00ec0dd..8d55a33 100644 +--- a/drivers/gpu/drm/i915/intel_sdvo.c ++++ b/drivers/gpu/drm/i915/intel_sdvo.c +@@ -148,7 +148,7 @@ struct intel_sdvo_connector { + /* Mark the type of connector */ + uint16_t output_flag; + +- int force_audio; ++ enum hdmi_force_audio force_audio; + + /* This contains all current supported TV format */ + u8 tv_format_supported[TV_FORMAT_NUM]; +@@ -982,7 +982,6 @@ intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, + + intel_sdvo_get_mode_from_dtd(adjusted_mode, &intel_sdvo->input_dtd); + +- drm_mode_set_crtcinfo(adjusted_mode, 0); + return true; + } + +@@ -1351,8 +1350,8 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector) + + if (status == connector_status_connected) { + struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); +- if (intel_sdvo_connector->force_audio) +- intel_sdvo->has_hdmi_audio = intel_sdvo_connector->force_audio > 0; ++ if (intel_sdvo_connector->force_audio != HDMI_AUDIO_AUTO) ++ intel_sdvo->has_hdmi_audio = (intel_sdvo_connector->force_audio == HDMI_AUDIO_ON); + } + + return status; +@@ -1727,10 +1726,10 @@ intel_sdvo_set_property(struct drm_connector *connector, + + intel_sdvo_connector->force_audio = i; + +- if (i == 0) ++ if (i == HDMI_AUDIO_AUTO) + has_audio = intel_sdvo_detect_hdmi_audio(connector); + else +- has_audio = i > 0; ++ has_audio = (i == HDMI_AUDIO_ON); + + if (has_audio == intel_sdvo->has_hdmi_audio) + return 0; +@@ -2028,7 +2027,7 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector, + drm_connector_helper_add(&connector->base.base, + &intel_sdvo_connector_helper_funcs); + +- connector->base.base.interlace_allowed = 0; ++ connector->base.base.interlace_allowed = 1; + connector->base.base.doublescan_allowed = 0; + connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB; + +@@ -2332,10 +2331,8 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, + intel_sdvo_connector->max_##name = data_value[0]; \ + intel_sdvo_connector->cur_##name = response; \ + intel_sdvo_connector->name = \ +- drm_property_create(dev, DRM_MODE_PROP_RANGE, #name, 2); \ ++ drm_property_create_range(dev, 0, #name, 0, data_value[0]); \ + if (!intel_sdvo_connector->name) return false; \ +- intel_sdvo_connector->name->values[0] = 0; \ +- intel_sdvo_connector->name->values[1] = data_value[0]; \ + drm_connector_attach_property(connector, \ + intel_sdvo_connector->name, \ + intel_sdvo_connector->cur_##name); \ +@@ -2369,25 +2366,19 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, + intel_sdvo_connector->left_margin = data_value[0] - response; + intel_sdvo_connector->right_margin = intel_sdvo_connector->left_margin; + intel_sdvo_connector->left = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "left_margin", 2); ++ drm_property_create_range(dev, 0, "left_margin", 0, data_value[0]); + if (!intel_sdvo_connector->left) + return false; + +- intel_sdvo_connector->left->values[0] = 0; +- intel_sdvo_connector->left->values[1] = data_value[0]; + drm_connector_attach_property(connector, + intel_sdvo_connector->left, + intel_sdvo_connector->left_margin); + + intel_sdvo_connector->right = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "right_margin", 2); ++ drm_property_create_range(dev, 0, "right_margin", 0, data_value[0]); + if (!intel_sdvo_connector->right) + return false; + +- intel_sdvo_connector->right->values[0] = 0; +- intel_sdvo_connector->right->values[1] = data_value[0]; + drm_connector_attach_property(connector, + intel_sdvo_connector->right, + intel_sdvo_connector->right_margin); +@@ -2411,25 +2402,21 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, + intel_sdvo_connector->top_margin = data_value[0] - response; + intel_sdvo_connector->bottom_margin = intel_sdvo_connector->top_margin; + intel_sdvo_connector->top = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "top_margin", 2); ++ drm_property_create_range(dev, 0, ++ "top_margin", 0, data_value[0]); + if (!intel_sdvo_connector->top) + return false; + +- intel_sdvo_connector->top->values[0] = 0; +- intel_sdvo_connector->top->values[1] = data_value[0]; + drm_connector_attach_property(connector, + intel_sdvo_connector->top, + intel_sdvo_connector->top_margin); + + intel_sdvo_connector->bottom = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "bottom_margin", 2); ++ drm_property_create_range(dev, 0, ++ "bottom_margin", 0, data_value[0]); + if (!intel_sdvo_connector->bottom) + return false; + +- intel_sdvo_connector->bottom->values[0] = 0; +- intel_sdvo_connector->bottom->values[1] = data_value[0]; + drm_connector_attach_property(connector, + intel_sdvo_connector->bottom, + intel_sdvo_connector->bottom_margin); +@@ -2458,12 +2445,10 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, + intel_sdvo_connector->max_dot_crawl = 1; + intel_sdvo_connector->cur_dot_crawl = response & 0x1; + intel_sdvo_connector->dot_crawl = +- drm_property_create(dev, DRM_MODE_PROP_RANGE, "dot_crawl", 2); ++ drm_property_create_range(dev, 0, "dot_crawl", 0, 1); + if (!intel_sdvo_connector->dot_crawl) + return false; + +- intel_sdvo_connector->dot_crawl->values[0] = 0; +- intel_sdvo_connector->dot_crawl->values[1] = 1; + drm_connector_attach_property(connector, + intel_sdvo_connector->dot_crawl, + intel_sdvo_connector->cur_dot_crawl); +diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h +index 4193c54..770bdd6 100644 +--- a/drivers/gpu/drm/i915/intel_sdvo_regs.h ++++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h +@@ -1,5 +1,5 @@ + /* +- * Copyright © 2006-2007 Intel Corporation ++ * Copyright © 2006-2007 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), +diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c +new file mode 100644 +index 0000000..e90dfb6 +--- /dev/null ++++ b/drivers/gpu/drm/i915/intel_sprite.c +@@ -0,0 +1,666 @@ ++/* ++ * Copyright © 2011 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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. ++ * ++ * Authors: ++ * Jesse Barnes ++ * ++ * New plane/sprite handling. ++ * ++ * The older chips had a separate interface for programming plane related ++ * registers; newer ones are much simpler and we can use the new DRM plane ++ * support. ++ */ ++#include "drmP.h" ++#include "drm_crtc.h" ++#include "drm_fourcc.h" ++#include "intel_drv.h" ++#include "i915_drm.h" ++#include "i915_drv.h" ++ ++static void ++ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, ++ struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, ++ unsigned int crtc_w, unsigned int crtc_h, ++ uint32_t x, uint32_t y, ++ uint32_t src_w, uint32_t src_h) ++{ ++ struct drm_device *dev = plane->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_plane *intel_plane = to_intel_plane(plane); ++ int pipe = intel_plane->pipe; ++ u32 sprctl, sprscale = 0; ++ int pixel_size; ++ ++ sprctl = I915_READ(SPRCTL(pipe)); ++ ++ /* Mask out pixel format bits in case we change it */ ++ sprctl &= ~SPRITE_PIXFORMAT_MASK; ++ sprctl &= ~SPRITE_RGB_ORDER_RGBX; ++ sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK; ++ ++ switch (fb->pixel_format) { ++ case DRM_FORMAT_XBGR8888: ++ sprctl |= SPRITE_FORMAT_RGBX888; ++ pixel_size = 4; ++ break; ++ case DRM_FORMAT_XRGB8888: ++ sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; ++ pixel_size = 4; ++ break; ++ case DRM_FORMAT_YUYV: ++ sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV; ++ pixel_size = 2; ++ break; ++ case DRM_FORMAT_YVYU: ++ sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU; ++ pixel_size = 2; ++ break; ++ case DRM_FORMAT_UYVY: ++ sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY; ++ pixel_size = 2; ++ break; ++ case DRM_FORMAT_VYUY: ++ sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY; ++ pixel_size = 2; ++ break; ++ default: ++ DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n"); ++ sprctl |= DVS_FORMAT_RGBX888; ++ pixel_size = 4; ++ break; ++ } ++ ++ if (obj->tiling_mode != I915_TILING_NONE) ++ sprctl |= SPRITE_TILED; ++ ++ /* must disable */ ++ sprctl |= SPRITE_TRICKLE_FEED_DISABLE; ++ sprctl |= SPRITE_ENABLE; ++ ++ /* Sizes are 0 based */ ++ src_w--; ++ src_h--; ++ crtc_w--; ++ crtc_h--; ++ ++ intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size); ++ ++ /* ++ * IVB workaround: must disable low power watermarks for at least ++ * one frame before enabling scaling. LP watermarks can be re-enabled ++ * when scaling is disabled. ++ */ ++ if (crtc_w != src_w || crtc_h != src_h) { ++ dev_priv->sprite_scaling_enabled = true; ++ sandybridge_update_wm(dev); ++ intel_wait_for_vblank(dev, pipe); ++ sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; ++ } else { ++ dev_priv->sprite_scaling_enabled = false; ++ /* potentially re-enable LP watermarks */ ++ sandybridge_update_wm(dev); ++ } ++ ++ I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); ++ I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); ++ if (obj->tiling_mode != I915_TILING_NONE) { ++ I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); ++ } else { ++ unsigned long offset; ++ ++ offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); ++ I915_WRITE(SPRLINOFF(pipe), offset); ++ } ++ I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); ++ I915_WRITE(SPRSCALE(pipe), sprscale); ++ I915_WRITE(SPRCTL(pipe), sprctl); ++ I915_WRITE(SPRSURF(pipe), obj->gtt_offset); ++ POSTING_READ(SPRSURF(pipe)); ++} ++ ++static void ++ivb_disable_plane(struct drm_plane *plane) ++{ ++ struct drm_device *dev = plane->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_plane *intel_plane = to_intel_plane(plane); ++ int pipe = intel_plane->pipe; ++ ++ I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE); ++ /* Can't leave the scaler enabled... */ ++ I915_WRITE(SPRSCALE(pipe), 0); ++ /* Activate double buffered register update */ ++ I915_WRITE(SPRSURF(pipe), 0); ++ POSTING_READ(SPRSURF(pipe)); ++} ++ ++static int ++ivb_update_colorkey(struct drm_plane *plane, ++ struct drm_intel_sprite_colorkey *key) ++{ ++ struct drm_device *dev = plane->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_plane *intel_plane; ++ u32 sprctl; ++ int ret = 0; ++ ++ intel_plane = to_intel_plane(plane); ++ ++ I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value); ++ I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value); ++ I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask); ++ ++ sprctl = I915_READ(SPRCTL(intel_plane->pipe)); ++ sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY); ++ if (key->flags & I915_SET_COLORKEY_DESTINATION) ++ sprctl |= SPRITE_DEST_KEY; ++ else if (key->flags & I915_SET_COLORKEY_SOURCE) ++ sprctl |= SPRITE_SOURCE_KEY; ++ I915_WRITE(SPRCTL(intel_plane->pipe), sprctl); ++ ++ POSTING_READ(SPRKEYMSK(intel_plane->pipe)); ++ ++ return ret; ++} ++ ++static void ++ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key) ++{ ++ struct drm_device *dev = plane->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_plane *intel_plane; ++ u32 sprctl; ++ ++ intel_plane = to_intel_plane(plane); ++ ++ key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe)); ++ key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe)); ++ key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe)); ++ key->flags = 0; ++ ++ sprctl = I915_READ(SPRCTL(intel_plane->pipe)); ++ ++ if (sprctl & SPRITE_DEST_KEY) ++ key->flags = I915_SET_COLORKEY_DESTINATION; ++ else if (sprctl & SPRITE_SOURCE_KEY) ++ key->flags = I915_SET_COLORKEY_SOURCE; ++ else ++ key->flags = I915_SET_COLORKEY_NONE; ++} ++ ++static void ++snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, ++ struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, ++ unsigned int crtc_w, unsigned int crtc_h, ++ uint32_t x, uint32_t y, ++ uint32_t src_w, uint32_t src_h) ++{ ++ struct drm_device *dev = plane->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_plane *intel_plane = to_intel_plane(plane); ++ int pipe = intel_plane->pipe, pixel_size; ++ u32 dvscntr, dvsscale = 0; ++ ++ dvscntr = I915_READ(DVSCNTR(pipe)); ++ ++ /* Mask out pixel format bits in case we change it */ ++ dvscntr &= ~DVS_PIXFORMAT_MASK; ++ dvscntr &= ~DVS_RGB_ORDER_XBGR; ++ dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK; ++ ++ switch (fb->pixel_format) { ++ case DRM_FORMAT_XBGR8888: ++ dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR; ++ pixel_size = 4; ++ break; ++ case DRM_FORMAT_XRGB8888: ++ dvscntr |= DVS_FORMAT_RGBX888; ++ pixel_size = 4; ++ break; ++ case DRM_FORMAT_YUYV: ++ dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV; ++ pixel_size = 2; ++ break; ++ case DRM_FORMAT_YVYU: ++ dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU; ++ pixel_size = 2; ++ break; ++ case DRM_FORMAT_UYVY: ++ dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY; ++ pixel_size = 2; ++ break; ++ case DRM_FORMAT_VYUY: ++ dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY; ++ pixel_size = 2; ++ break; ++ default: ++ DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n"); ++ dvscntr |= DVS_FORMAT_RGBX888; ++ pixel_size = 4; ++ break; ++ } ++ ++ if (obj->tiling_mode != I915_TILING_NONE) ++ dvscntr |= DVS_TILED; ++ ++ /* must disable */ ++ dvscntr |= DVS_TRICKLE_FEED_DISABLE; ++ dvscntr |= DVS_ENABLE; ++ ++ /* Sizes are 0 based */ ++ src_w--; ++ src_h--; ++ crtc_w--; ++ crtc_h--; ++ ++ intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size); ++ ++ if (crtc_w != src_w || crtc_h != src_h) ++ dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; ++ ++ I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); ++ I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); ++ if (obj->tiling_mode != I915_TILING_NONE) { ++ I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x); ++ } else { ++ unsigned long offset; ++ ++ offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); ++ I915_WRITE(DVSLINOFF(pipe), offset); ++ } ++ I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); ++ I915_WRITE(DVSSCALE(pipe), dvsscale); ++ I915_WRITE(DVSCNTR(pipe), dvscntr); ++ I915_WRITE(DVSSURF(pipe), obj->gtt_offset); ++ POSTING_READ(DVSSURF(pipe)); ++} ++ ++static void ++snb_disable_plane(struct drm_plane *plane) ++{ ++ struct drm_device *dev = plane->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_plane *intel_plane = to_intel_plane(plane); ++ int pipe = intel_plane->pipe; ++ ++ I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE); ++ /* Disable the scaler */ ++ I915_WRITE(DVSSCALE(pipe), 0); ++ /* Flush double buffered register updates */ ++ I915_WRITE(DVSSURF(pipe), 0); ++ POSTING_READ(DVSSURF(pipe)); ++} ++ ++static void ++intel_enable_primary(struct drm_crtc *crtc) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); ++ int reg = DSPCNTR(intel_crtc->plane); ++ ++ I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); ++} ++ ++static void ++intel_disable_primary(struct drm_crtc *crtc) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); ++ int reg = DSPCNTR(intel_crtc->plane); ++ ++ I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); ++} ++ ++static int ++snb_update_colorkey(struct drm_plane *plane, ++ struct drm_intel_sprite_colorkey *key) ++{ ++ struct drm_device *dev = plane->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_plane *intel_plane; ++ u32 dvscntr; ++ int ret = 0; ++ ++ intel_plane = to_intel_plane(plane); ++ ++ I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value); ++ I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value); ++ I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask); ++ ++ dvscntr = I915_READ(DVSCNTR(intel_plane->pipe)); ++ dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY); ++ if (key->flags & I915_SET_COLORKEY_DESTINATION) ++ dvscntr |= DVS_DEST_KEY; ++ else if (key->flags & I915_SET_COLORKEY_SOURCE) ++ dvscntr |= DVS_SOURCE_KEY; ++ I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr); ++ ++ POSTING_READ(DVSKEYMSK(intel_plane->pipe)); ++ ++ return ret; ++} ++ ++static void ++snb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key) ++{ ++ struct drm_device *dev = plane->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_plane *intel_plane; ++ u32 dvscntr; ++ ++ intel_plane = to_intel_plane(plane); ++ ++ key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe)); ++ key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe)); ++ key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe)); ++ key->flags = 0; ++ ++ dvscntr = I915_READ(DVSCNTR(intel_plane->pipe)); ++ ++ if (dvscntr & DVS_DEST_KEY) ++ key->flags = I915_SET_COLORKEY_DESTINATION; ++ else if (dvscntr & DVS_SOURCE_KEY) ++ key->flags = I915_SET_COLORKEY_SOURCE; ++ else ++ key->flags = I915_SET_COLORKEY_NONE; ++} ++ ++static int ++intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ++ struct drm_framebuffer *fb, int crtc_x, int crtc_y, ++ unsigned int crtc_w, unsigned int crtc_h, ++ uint32_t src_x, uint32_t src_y, ++ uint32_t src_w, uint32_t src_h) ++{ ++ struct drm_device *dev = plane->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); ++ struct intel_plane *intel_plane = to_intel_plane(plane); ++ struct intel_framebuffer *intel_fb; ++ struct drm_i915_gem_object *obj, *old_obj; ++ int pipe = intel_plane->pipe; ++ int ret = 0; ++ int x = src_x >> 16, y = src_y >> 16; ++ int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay; ++ bool disable_primary = false; ++ ++ intel_fb = to_intel_framebuffer(fb); ++ obj = intel_fb->obj; ++ ++ old_obj = intel_plane->obj; ++ ++ src_w = src_w >> 16; ++ src_h = src_h >> 16; ++ ++ /* Pipe must be running... */ ++ if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE)) ++ return -EINVAL; ++ ++ if (crtc_x >= primary_w || crtc_y >= primary_h) ++ return -EINVAL; ++ ++ /* Don't modify another pipe's plane */ ++ if (intel_plane->pipe != intel_crtc->pipe) ++ return -EINVAL; ++ ++ /* ++ * Clamp the width & height into the visible area. Note we don't ++ * try to scale the source if part of the visible region is offscreen. ++ * The caller must handle that by adjusting source offset and size. ++ */ ++ if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) { ++ crtc_w += crtc_x; ++ crtc_x = 0; ++ } ++ if ((crtc_x + crtc_w) <= 0) /* Nothing to display */ ++ goto out; ++ if ((crtc_x + crtc_w) > primary_w) ++ crtc_w = primary_w - crtc_x; ++ ++ if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) { ++ crtc_h += crtc_y; ++ crtc_y = 0; ++ } ++ if ((crtc_y + crtc_h) <= 0) /* Nothing to display */ ++ goto out; ++ if (crtc_y + crtc_h > primary_h) ++ crtc_h = primary_h - crtc_y; ++ ++ if (!crtc_w || !crtc_h) /* Again, nothing to display */ ++ goto out; ++ ++ /* ++ * We can take a larger source and scale it down, but ++ * only so much... 16x is the max on SNB. ++ */ ++ if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale) ++ return -EINVAL; ++ ++ /* ++ * If the sprite is completely covering the primary plane, ++ * we can disable the primary and save power. ++ */ ++ if ((crtc_x == 0) && (crtc_y == 0) && ++ (crtc_w == primary_w) && (crtc_h == primary_h)) ++ disable_primary = true; ++ ++ mutex_lock(&dev->struct_mutex); ++ ++ ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); ++ if (ret) ++ goto out_unlock; ++ ++ intel_plane->obj = obj; ++ ++ /* ++ * Be sure to re-enable the primary before the sprite is no longer ++ * covering it fully. ++ */ ++ if (!disable_primary && intel_plane->primary_disabled) { ++ intel_enable_primary(crtc); ++ intel_plane->primary_disabled = false; ++ } ++ ++ intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, ++ crtc_w, crtc_h, x, y, src_w, src_h); ++ ++ if (disable_primary) { ++ intel_disable_primary(crtc); ++ intel_plane->primary_disabled = true; ++ } ++ ++ /* Unpin old obj after new one is active to avoid ugliness */ ++ if (old_obj) { ++ /* ++ * It's fairly common to simply update the position of ++ * an existing object. In that case, we don't need to ++ * wait for vblank to avoid ugliness, we only need to ++ * do the pin & ref bookkeeping. ++ */ ++ if (old_obj != obj) { ++ mutex_unlock(&dev->struct_mutex); ++ intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); ++ mutex_lock(&dev->struct_mutex); ++ } ++ intel_unpin_fb_obj(old_obj); ++ } ++ ++out_unlock: ++ mutex_unlock(&dev->struct_mutex); ++out: ++ return ret; ++} ++ ++static int ++intel_disable_plane(struct drm_plane *plane) ++{ ++ struct drm_device *dev = plane->dev; ++ struct intel_plane *intel_plane = to_intel_plane(plane); ++ int ret = 0; ++ ++ if (intel_plane->primary_disabled) { ++ intel_enable_primary(plane->crtc); ++ intel_plane->primary_disabled = false; ++ } ++ ++ intel_plane->disable_plane(plane); ++ ++ if (!intel_plane->obj) ++ goto out; ++ ++ mutex_lock(&dev->struct_mutex); ++ intel_unpin_fb_obj(intel_plane->obj); ++ intel_plane->obj = NULL; ++ mutex_unlock(&dev->struct_mutex); ++out: ++ ++ return ret; ++} ++ ++static void intel_destroy_plane(struct drm_plane *plane) ++{ ++ struct intel_plane *intel_plane = to_intel_plane(plane); ++ intel_disable_plane(plane); ++ drm_plane_cleanup(plane); ++ kfree(intel_plane); ++} ++ ++int intel_sprite_set_colorkey(struct drm_device *dev, void *data, ++ struct drm_file *file_priv) ++{ ++ struct drm_intel_sprite_colorkey *set = data; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct drm_mode_object *obj; ++ struct drm_plane *plane; ++ struct intel_plane *intel_plane; ++ int ret = 0; ++ ++ if (!dev_priv) ++ return -EINVAL; ++ ++ /* Make sure we don't try to enable both src & dest simultaneously */ ++ if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) ++ return -EINVAL; ++ ++ mutex_lock(&dev->mode_config.mutex); ++ ++ obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE); ++ if (!obj) { ++ ret = -EINVAL; ++ goto out_unlock; ++ } ++ ++ plane = obj_to_plane(obj); ++ intel_plane = to_intel_plane(plane); ++ ret = intel_plane->update_colorkey(plane, set); ++ ++out_unlock: ++ mutex_unlock(&dev->mode_config.mutex); ++ return ret; ++} ++ ++int intel_sprite_get_colorkey(struct drm_device *dev, void *data, ++ struct drm_file *file_priv) ++{ ++ struct drm_intel_sprite_colorkey *get = data; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct drm_mode_object *obj; ++ struct drm_plane *plane; ++ struct intel_plane *intel_plane; ++ int ret = 0; ++ ++ if (!dev_priv) ++ return -EINVAL; ++ ++ mutex_lock(&dev->mode_config.mutex); ++ ++ obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE); ++ if (!obj) { ++ ret = -EINVAL; ++ goto out_unlock; ++ } ++ ++ plane = obj_to_plane(obj); ++ intel_plane = to_intel_plane(plane); ++ intel_plane->get_colorkey(plane, get); ++ ++out_unlock: ++ mutex_unlock(&dev->mode_config.mutex); ++ return ret; ++} ++ ++static const struct drm_plane_funcs intel_plane_funcs = { ++ .update_plane = intel_update_plane, ++ .disable_plane = intel_disable_plane, ++ .destroy = intel_destroy_plane, ++}; ++ ++static uint32_t snb_plane_formats[] = { ++ DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_YUYV, ++ DRM_FORMAT_YVYU, ++ DRM_FORMAT_UYVY, ++ DRM_FORMAT_VYUY, ++}; ++ ++int ++intel_plane_init(struct drm_device *dev, enum pipe pipe) ++{ ++ struct intel_plane *intel_plane; ++ unsigned long possible_crtcs; ++ int ret; ++ ++ if (!(IS_GEN6(dev) || IS_GEN7(dev))) ++ return -ENODEV; ++ ++ intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL); ++ if (!intel_plane) ++ return -ENOMEM; ++ ++ if (IS_GEN6(dev)) { ++ intel_plane->max_downscale = 16; ++ intel_plane->update_plane = snb_update_plane; ++ intel_plane->disable_plane = snb_disable_plane; ++ intel_plane->update_colorkey = snb_update_colorkey; ++ intel_plane->get_colorkey = snb_get_colorkey; ++ } else if (IS_GEN7(dev)) { ++ intel_plane->max_downscale = 2; ++ intel_plane->update_plane = ivb_update_plane; ++ intel_plane->disable_plane = ivb_disable_plane; ++ intel_plane->update_colorkey = ivb_update_colorkey; ++ intel_plane->get_colorkey = ivb_get_colorkey; ++ } ++ ++ intel_plane->pipe = pipe; ++ possible_crtcs = (1 << pipe); ++ ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, ++ &intel_plane_funcs, snb_plane_formats, ++ ARRAY_SIZE(snb_plane_formats), false); ++ if (ret) ++ kfree(intel_plane); ++ ++ return ret; ++} ++ +diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c +index b221f2b..c82b1d4 100644 +--- a/drivers/gpu/drm/i915/intel_tv.c ++++ b/drivers/gpu/drm/i915/intel_tv.c +@@ -674,7 +674,7 @@ static const struct tv_mode tv_modes[] = { + .filter_table = filter_table, + }, + { +- .name = "480p@59.94Hz", ++ .name = "480p", + .clock = 107520, + .refresh = 59940, + .oversample = TV_OVERSAMPLE_4X, +@@ -698,30 +698,6 @@ static const struct tv_mode tv_modes[] = { + .filter_table = filter_table, + }, + { +- .name = "480p@60Hz", +- .clock = 107520, +- .refresh = 60000, +- .oversample = TV_OVERSAMPLE_4X, +- .component_only = 1, +- +- .hsync_end = 64, .hblank_end = 122, +- .hblank_start = 842, .htotal = 856, +- +- .progressive = true, .trilevel_sync = false, +- +- .vsync_start_f1 = 12, .vsync_start_f2 = 12, +- .vsync_len = 12, +- +- .veq_ena = false, +- +- .vi_end_f1 = 44, .vi_end_f2 = 44, +- .nbr_end = 479, +- +- .burst_ena = false, +- +- .filter_table = filter_table, +- }, +- { + .name = "576p", + .clock = 107520, + .refresh = 50000, +@@ -731,7 +707,7 @@ static const struct tv_mode tv_modes[] = { + .hsync_end = 64, .hblank_end = 139, + .hblank_start = 859, .htotal = 863, + +- .progressive = true, .trilevel_sync = false, ++ .progressive = true, .trilevel_sync = false, + + .vsync_start_f1 = 10, .vsync_start_f2 = 10, + .vsync_len = 10, +@@ -770,30 +746,6 @@ static const struct tv_mode tv_modes[] = { + .filter_table = filter_table, + }, + { +- .name = "720p@59.94Hz", +- .clock = 148800, +- .refresh = 59940, +- .oversample = TV_OVERSAMPLE_2X, +- .component_only = 1, +- +- .hsync_end = 80, .hblank_end = 300, +- .hblank_start = 1580, .htotal = 1651, +- +- .progressive = true, .trilevel_sync = true, +- +- .vsync_start_f1 = 10, .vsync_start_f2 = 10, +- .vsync_len = 10, +- +- .veq_ena = false, +- +- .vi_end_f1 = 29, .vi_end_f2 = 29, +- .nbr_end = 719, +- +- .burst_ena = false, +- +- .filter_table = filter_table, +- }, +- { + .name = "720p@50Hz", + .clock = 148800, + .refresh = 50000, +@@ -870,32 +822,6 @@ static const struct tv_mode tv_modes[] = { + + .filter_table = filter_table, + }, +- { +- .name = "1080i@59.94Hz", +- .clock = 148800, +- .refresh = 29970, +- .oversample = TV_OVERSAMPLE_2X, +- .component_only = 1, +- +- .hsync_end = 88, .hblank_end = 235, +- .hblank_start = 2155, .htotal = 2201, +- +- .progressive = false, .trilevel_sync = true, +- +- .vsync_start_f1 = 4, .vsync_start_f2 = 5, +- .vsync_len = 10, +- +- .veq_ena = true, .veq_start_f1 = 4, +- .veq_start_f2 = 4, .veq_len = 10, +- +- +- .vi_end_f1 = 21, .vi_end_f2 = 22, +- .nbr_end = 539, +- +- .burst_ena = false, +- +- .filter_table = filter_table, +- }, + }; + + static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder) +@@ -1367,7 +1293,7 @@ intel_tv_detect(struct drm_connector *connector, bool force) + int type; + + mode = reported_modes[0]; +- drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V); ++ drm_mode_set_crtcinfo(&mode, 0); + + if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) { + type = intel_tv_detect_type(intel_tv, connector); +@@ -1599,14 +1525,9 @@ static int tv_is_present_in_vbt(struct drm_device *dev) + /* + * If the device type is not TV, continue. + */ +- switch (p_child->device_type) { +- case DEVICE_TYPE_INT_TV: +- case DEVICE_TYPE_TV: +- case DEVICE_TYPE_TV_SVIDEO_COMPOSITE: +- break; +- default: ++ if (p_child->device_type != DEVICE_TYPE_INT_TV && ++ p_child->device_type != DEVICE_TYPE_TV) + continue; +- } + /* Only when the addin_offset is non-zero, it is regarded + * as present. + */ +diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c +index 5ccb65de..507aa3d 100644 +--- a/drivers/gpu/drm/mga/mga_dma.c ++++ b/drivers/gpu/drm/mga/mga_dma.c +@@ -403,6 +403,8 @@ int mga_driver_load(struct drm_device *dev, unsigned long flags) + dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; + dev_priv->chipset = flags; + ++ pci_set_master(dev->pdev); ++ + dev_priv->mmio_base = pci_resource_start(dev->pdev, 1); + dev_priv->mmio_size = pci_resource_len(dev->pdev, 1); + +diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c +index 33daa29..f9a925d 100644 +--- a/drivers/gpu/drm/mga/mga_drv.c ++++ b/drivers/gpu/drm/mga/mga_drv.c +@@ -44,6 +44,20 @@ static struct pci_device_id pciidlist[] = { + mga_PCI_IDS + }; + ++static const struct file_operations mga_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .mmap = drm_mmap, ++ .poll = drm_poll, ++ .fasync = drm_fasync, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = mga_compat_ioctl, ++#endif ++ .llseek = noop_llseek, ++}; ++ + static struct drm_driver driver = { + .driver_features = + DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | +@@ -64,20 +78,7 @@ static struct drm_driver driver = { + .reclaim_buffers = drm_core_reclaim_buffers, + .ioctls = mga_ioctls, + .dma_ioctl = mga_dma_buffers, +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = drm_ioctl, +- .mmap = drm_mmap, +- .poll = drm_poll, +- .fasync = drm_fasync, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = mga_compat_ioctl, +-#endif +- .llseek = noop_llseek, +- }, +- ++ .fops = &mga_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, +diff --git a/drivers/gpu/drm/mga/mga_warp.c b/drivers/gpu/drm/mga/mga_warp.c +index 722a91b..fe070ba 100644 +--- a/drivers/gpu/drm/mga/mga_warp.c ++++ b/drivers/gpu/drm/mga/mga_warp.c +@@ -80,11 +80,8 @@ int mga_warp_install_microcode(drm_mga_private_t *dev_priv) + } + rc = request_ihex_firmware(&fw, firmware_name, &pdev->dev); + platform_device_unregister(pdev); +- if (rc) { +- DRM_ERROR("mga: Failed to load microcode \"%s\"\n", +- firmware_name); ++ if (rc) + return rc; +- } + + size = 0; + where = 0; +diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig +index ca16399..9323de1 100644 +--- a/drivers/gpu/drm/nouveau/Kconfig ++++ b/drivers/gpu/drm/nouveau/Kconfig +@@ -11,8 +11,9 @@ config DRM_NOUVEAU + select FRAMEBUFFER_CONSOLE if !EXPERT + select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT + select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && INPUT +- select ACPI_WMI if ACPI +- select MXM_WMI if ACPI ++ select ACPI_WMI if ACPI && X86 ++ select MXM_WMI if ACPI && X86 ++ select POWER_SUPPLY + help + Choose this option for open-source nVidia support. + +diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile +index 35ef5b1..c4e0ae6 100644 +--- a/drivers/gpu/drm/nouveau/Makefile ++++ b/drivers/gpu/drm/nouveau/Makefile +@@ -9,19 +9,23 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ + nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ + nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ + nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ +- nouveau_dp.o nouveau_ramht.o \ ++ nouveau_hdmi.o nouveau_dp.o nouveau_ramht.o \ + nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ +- nouveau_mm.o nouveau_vm.o \ ++ nouveau_mm.o nouveau_vm.o nouveau_mxm.o nouveau_gpio.o \ + nv04_timer.o \ + nv04_mc.o nv40_mc.o nv50_mc.o \ +- nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ ++ nv04_fb.o nv10_fb.o nv20_fb.o nv30_fb.o nv40_fb.o \ ++ nv50_fb.o nvc0_fb.o \ + nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o nvc0_fifo.o \ + nv04_graph.o nv10_graph.o nv20_graph.o \ + nv40_graph.o nv50_graph.o nvc0_graph.o \ + nv40_grctx.o nv50_grctx.o nvc0_grctx.o \ +- nv84_crypt.o \ ++ nv84_crypt.o nv98_crypt.o \ + nva3_copy.o nvc0_copy.o \ + nv31_mpeg.o nv50_mpeg.o \ ++ nv84_bsp.o \ ++ nv84_vp.o \ ++ nv98_ppp.o \ + nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ + nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ + nv04_crtc.o nv04_display.o nv04_cursor.o \ +@@ -38,6 +42,8 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ + nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o + nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o + nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o ++ifdef CONFIG_X86 + nouveau-$(CONFIG_ACPI) += nouveau_acpi.o ++endif + + obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o +diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c +index 5ee8cca..4339694 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c ++++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c +@@ -18,12 +18,6 @@ + + #include + +-#define NOUVEAU_DSM_SUPPORTED 0x00 +-#define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00 +- +-#define NOUVEAU_DSM_ACTIVE 0x01 +-#define NOUVEAU_DSM_ACTIVE_QUERY 0x00 +- + #define NOUVEAU_DSM_LED 0x02 + #define NOUVEAU_DSM_LED_STATE 0x00 + #define NOUVEAU_DSM_LED_OFF 0x10 +@@ -35,6 +29,9 @@ + #define NOUVEAU_DSM_POWER_SPEED 0x01 + #define NOUVEAU_DSM_POWER_STAMINA 0x02 + ++#define NOUVEAU_DSM_OPTIMUS_FN 0x1A ++#define NOUVEAU_DSM_OPTIMUS_ARGS 0x03000001 ++ + static struct nouveau_dsm_priv { + bool dsm_detected; + bool optimus_detected; +@@ -61,7 +58,8 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * + struct acpi_object_list input; + union acpi_object params[4]; + union acpi_object *obj; +- int err; ++ int i, err; ++ char args_buff[4]; + + input.count = 4; + input.pointer = params; +@@ -73,7 +71,11 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * + params[2].type = ACPI_TYPE_INTEGER; + params[2].integer.value = func; + params[3].type = ACPI_TYPE_BUFFER; +- params[3].buffer.length = 0; ++ params[3].buffer.length = 4; ++ /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ ++ for (i = 0; i < 4; i++) ++ args_buff[i] = (arg >> i * 8) & 0xFF; ++ params[3].buffer.pointer = args_buff; + + err = acpi_evaluate_object(handle, "_DSM", &input, &output); + if (err) { +@@ -148,6 +150,23 @@ static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) + return 0; + } + ++/* Returns 1 if a DSM function is usable and 0 otherwise */ ++static int nouveau_test_dsm(acpi_handle test_handle, ++ int (*dsm_func)(acpi_handle, int, int, uint32_t *), ++ int sfnc) ++{ ++ u32 result = 0; ++ ++ /* Function 0 returns a Buffer containing available functions. The args ++ * parameter is ignored for function 0, so just put 0 in it */ ++ if (dsm_func(test_handle, 0, 0, &result)) ++ return 0; ++ ++ /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If ++ * the n-th bit is enabled, function n is supported */ ++ return result & 1 && result & (1 << sfnc); ++} ++ + static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) + { + mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); +@@ -168,6 +187,10 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero + + static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id) + { ++ /* perhaps the _DSM functions are mutually exclusive, but prepare for ++ * the future */ ++ if (!nouveau_dsm_priv.dsm_detected && nouveau_dsm_priv.optimus_detected) ++ return 0; + if (id == VGA_SWITCHEROO_IGD) + return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA); + else +@@ -180,6 +203,11 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id, + if (id == VGA_SWITCHEROO_IGD) + return 0; + ++ /* Optimus laptops have the card already disabled in ++ * nouveau_switcheroo_set_state */ ++ if (!nouveau_dsm_priv.dsm_detected && nouveau_dsm_priv.optimus_detected) ++ return 0; ++ + return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state); + } + +@@ -212,8 +240,7 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) + { + acpi_handle dhandle, nvidia_handle; + acpi_status status; +- int ret, retval = 0; +- uint32_t result; ++ int retval = 0; + + dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); + if (!dhandle) +@@ -224,13 +251,11 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) + return false; + } + +- ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED, +- NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result); +- if (ret == 0) ++ if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) + retval |= NOUVEAU_DSM_HAS_MUX; + +- ret = nouveau_optimus_dsm(dhandle, 0, 0, &result); +- if (ret == 0) ++ if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm, ++ NOUVEAU_DSM_OPTIMUS_FN)) + retval |= NOUVEAU_DSM_HAS_OPT; + + if (retval) +@@ -269,15 +294,22 @@ static bool nouveau_dsm_detect(void) + } + + if (vga_count == 2 && has_dsm && guid_valid) { +- acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer); ++ acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, ++ &buffer); + printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", +- acpi_method_name); ++ acpi_method_name); + nouveau_dsm_priv.dsm_detected = true; + ret = true; + } + +- if (has_optimus == 1) ++ if (has_optimus == 1) { ++ acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, ++ &buffer); ++ printk(KERN_INFO "VGA switcheroo: detected Optimus DSM method %s handle\n", ++ acpi_method_name); + nouveau_dsm_priv.optimus_detected = true; ++ ret = true; ++ } + + return ret; + } +@@ -293,6 +325,17 @@ void nouveau_register_dsm_handler(void) + vga_switcheroo_register_handler(&nouveau_dsm_handler); + } + ++/* Must be called for Optimus models before the card can be turned off */ ++void nouveau_switcheroo_optimus_dsm(void) ++{ ++ u32 result = 0; ++ if (!nouveau_dsm_priv.optimus_detected) ++ return; ++ ++ nouveau_optimus_dsm(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_FN, ++ NOUVEAU_DSM_OPTIMUS_ARGS, &result); ++} ++ + void nouveau_unregister_dsm_handler(void) + { + vga_switcheroo_unregister_handler(); +diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c +index 5fc201b..0be4a81 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_bios.c ++++ b/drivers/gpu/drm/nouveau/nouveau_bios.c +@@ -27,6 +27,7 @@ + #include "nouveau_drv.h" + #include "nouveau_hw.h" + #include "nouveau_encoder.h" ++#include "nouveau_gpio.h" + + #include + +@@ -34,9 +35,6 @@ + #define NV_CIO_CRE_44_HEADA 0x0 + #define NV_CIO_CRE_44_HEADB 0x3 + #define FEATURE_MOBILE 0x10 /* also FEATURE_QUADRO for BMP */ +-#define LEGACY_I2C_CRT 0x80 +-#define LEGACY_I2C_PANEL 0x81 +-#define LEGACY_I2C_TV 0x82 + + #define EDID1_LEN 128 + +@@ -67,195 +65,233 @@ static bool nv_cksum(const uint8_t *data, unsigned int length) + } + + static int +-score_vbios(struct drm_device *dev, const uint8_t *data, const bool writeable) ++score_vbios(struct nvbios *bios, const bool writeable) + { +- if (!(data[0] == 0x55 && data[1] == 0xAA)) { +- NV_TRACEWARN(dev, "... BIOS signature not found\n"); ++ if (!bios->data || bios->data[0] != 0x55 || bios->data[1] != 0xAA) { ++ NV_TRACEWARN(bios->dev, "... BIOS signature not found\n"); + return 0; + } + +- if (nv_cksum(data, data[2] * 512)) { +- NV_TRACEWARN(dev, "... BIOS checksum invalid\n"); ++ if (nv_cksum(bios->data, bios->data[2] * 512)) { ++ NV_TRACEWARN(bios->dev, "... BIOS checksum invalid\n"); + /* if a ro image is somewhat bad, it's probably all rubbish */ + return writeable ? 2 : 1; +- } else +- NV_TRACE(dev, "... appears to be valid\n"); ++ } + ++ NV_TRACE(bios->dev, "... appears to be valid\n"); + return 3; + } + +-static void load_vbios_prom(struct drm_device *dev, uint8_t *data) ++static void ++bios_shadow_prom(struct nvbios *bios) + { ++ struct drm_device *dev = bios->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +- uint32_t pci_nv_20, save_pci_nv_20; +- int pcir_ptr; ++ u32 pcireg, access; ++ u16 pcir; + int i; + ++ /* enable access to rom */ + if (dev_priv->card_type >= NV_50) +- pci_nv_20 = 0x88050; ++ pcireg = 0x088050; + else +- pci_nv_20 = NV_PBUS_PCI_NV_20; ++ pcireg = NV_PBUS_PCI_NV_20; ++ access = nv_mask(dev, pcireg, 0x00000001, 0x00000000); + +- /* enable ROM access */ +- save_pci_nv_20 = nvReadMC(dev, pci_nv_20); +- nvWriteMC(dev, pci_nv_20, +- save_pci_nv_20 & ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED); ++ /* bail if no rom signature, with a workaround for a PROM reading ++ * issue on some chipsets. the first read after a period of ++ * inactivity returns the wrong result, so retry the first header ++ * byte a few times before giving up as a workaround ++ */ ++ i = 16; ++ do { ++ if (nv_rd08(dev, NV_PROM_OFFSET + 0) == 0x55) ++ break; ++ } while (i--); + +- /* bail if no rom signature */ +- if (nv_rd08(dev, NV_PROM_OFFSET) != 0x55 || +- nv_rd08(dev, NV_PROM_OFFSET + 1) != 0xaa) ++ if (!i || nv_rd08(dev, NV_PROM_OFFSET + 1) != 0xaa) + goto out; + + /* additional check (see note below) - read PCI record header */ +- pcir_ptr = nv_rd08(dev, NV_PROM_OFFSET + 0x18) | +- nv_rd08(dev, NV_PROM_OFFSET + 0x19) << 8; +- if (nv_rd08(dev, NV_PROM_OFFSET + pcir_ptr) != 'P' || +- nv_rd08(dev, NV_PROM_OFFSET + pcir_ptr + 1) != 'C' || +- nv_rd08(dev, NV_PROM_OFFSET + pcir_ptr + 2) != 'I' || +- nv_rd08(dev, NV_PROM_OFFSET + pcir_ptr + 3) != 'R') ++ pcir = nv_rd08(dev, NV_PROM_OFFSET + 0x18) | ++ nv_rd08(dev, NV_PROM_OFFSET + 0x19) << 8; ++ if (nv_rd08(dev, NV_PROM_OFFSET + pcir + 0) != 'P' || ++ nv_rd08(dev, NV_PROM_OFFSET + pcir + 1) != 'C' || ++ nv_rd08(dev, NV_PROM_OFFSET + pcir + 2) != 'I' || ++ nv_rd08(dev, NV_PROM_OFFSET + pcir + 3) != 'R') + goto out; + +- /* on some 6600GT/6800LE prom reads are messed up. nvclock alleges a +- * a good read may be obtained by waiting or re-reading (cargocult: 5x) +- * each byte. we'll hope pramin has something usable instead +- */ +- for (i = 0; i < NV_PROM_SIZE; i++) +- data[i] = nv_rd08(dev, NV_PROM_OFFSET + i); ++ /* read entire bios image to system memory */ ++ bios->length = nv_rd08(dev, NV_PROM_OFFSET + 2) * 512; ++ bios->data = kmalloc(bios->length, GFP_KERNEL); ++ if (bios->data) { ++ for (i = 0; i < bios->length; i++) ++ bios->data[i] = nv_rd08(dev, NV_PROM_OFFSET + i); ++ } + + out: +- /* disable ROM access */ +- nvWriteMC(dev, pci_nv_20, +- save_pci_nv_20 | NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED); ++ /* disable access to rom */ ++ nv_wr32(dev, pcireg, access); + } + +-static void load_vbios_pramin(struct drm_device *dev, uint8_t *data) ++static void ++bios_shadow_pramin(struct nvbios *bios) + { ++ struct drm_device *dev = bios->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +- uint32_t old_bar0_pramin = 0; ++ u32 bar0 = 0; + int i; + + if (dev_priv->card_type >= NV_50) { + u64 addr = (u64)(nv_rd32(dev, 0x619f04) & 0xffffff00) << 8; + if (!addr) { +- addr = (u64)nv_rd32(dev, 0x1700) << 16; ++ addr = (u64)nv_rd32(dev, 0x001700) << 16; + addr += 0xf0000; + } + +- old_bar0_pramin = nv_rd32(dev, 0x1700); +- nv_wr32(dev, 0x1700, addr >> 16); ++ bar0 = nv_mask(dev, 0x001700, 0xffffffff, addr >> 16); + } + + /* bail if no rom signature */ +- if (nv_rd08(dev, NV_PRAMIN_OFFSET) != 0x55 || ++ if (nv_rd08(dev, NV_PRAMIN_OFFSET + 0) != 0x55 || + nv_rd08(dev, NV_PRAMIN_OFFSET + 1) != 0xaa) + goto out; + +- for (i = 0; i < NV_PROM_SIZE; i++) +- data[i] = nv_rd08(dev, NV_PRAMIN_OFFSET + i); ++ bios->length = nv_rd08(dev, NV_PRAMIN_OFFSET + 2) * 512; ++ bios->data = kmalloc(bios->length, GFP_KERNEL); ++ if (bios->data) { ++ for (i = 0; i < bios->length; i++) ++ bios->data[i] = nv_rd08(dev, NV_PRAMIN_OFFSET + i); ++ } + + out: + if (dev_priv->card_type >= NV_50) +- nv_wr32(dev, 0x1700, old_bar0_pramin); ++ nv_wr32(dev, 0x001700, bar0); ++} ++ ++static void ++bios_shadow_pci(struct nvbios *bios) ++{ ++ struct pci_dev *pdev = bios->dev->pdev; ++ size_t length; ++ ++ if (!pci_enable_rom(pdev)) { ++ void __iomem *rom = pci_map_rom(pdev, &length); ++ if (rom && length) { ++ bios->data = kmalloc(length, GFP_KERNEL); ++ if (bios->data) { ++ memcpy_fromio(bios->data, rom, length); ++ bios->length = length; ++ } ++ } ++ if (rom) ++ pci_unmap_rom(pdev, rom); ++ ++ pci_disable_rom(pdev); ++ } + } + +-static void load_vbios_pci(struct drm_device *dev, uint8_t *data) ++static void ++bios_shadow_acpi(struct nvbios *bios) + { +- void __iomem *rom = NULL; +- size_t rom_len; +- int ret; ++ struct pci_dev *pdev = bios->dev->pdev; ++ int ptr, len, ret; ++ u8 data[3]; + +- ret = pci_enable_rom(dev->pdev); +- if (ret) ++ if (!nouveau_acpi_rom_supported(pdev)) + return; + +- rom = pci_map_rom(dev->pdev, &rom_len); +- if (!rom) +- goto out; +- memcpy_fromio(data, rom, rom_len); +- pci_unmap_rom(dev->pdev, rom); ++ ret = nouveau_acpi_get_bios_chunk(data, 0, sizeof(data)); ++ if (ret != sizeof(data)) ++ return; + +-out: +- pci_disable_rom(dev->pdev); +-} ++ bios->length = min(data[2] * 512, 65536); ++ bios->data = kmalloc(bios->length, GFP_KERNEL); ++ if (!bios->data) ++ return; + +-static void load_vbios_acpi(struct drm_device *dev, uint8_t *data) +-{ +- int i; +- int ret; +- int size = 64 * 1024; ++ len = bios->length; ++ ptr = 0; ++ while (len) { ++ int size = (len > ROM_BIOS_PAGE) ? ROM_BIOS_PAGE : len; + +- if (!nouveau_acpi_rom_supported(dev->pdev)) +- return; ++ ret = nouveau_acpi_get_bios_chunk(bios->data, ptr, size); ++ if (ret != size) { ++ kfree(bios->data); ++ bios->data = NULL; ++ return; ++ } + +- for (i = 0; i < (size / ROM_BIOS_PAGE); i++) { +- ret = nouveau_acpi_get_bios_chunk(data, +- (i * ROM_BIOS_PAGE), +- ROM_BIOS_PAGE); +- if (ret <= 0) +- break; ++ len -= size; ++ ptr += size; + } +- return; + } + + struct methods { + const char desc[8]; +- void (*loadbios)(struct drm_device *, uint8_t *); ++ void (*shadow)(struct nvbios *); + const bool rw; ++ int score; ++ u32 size; ++ u8 *data; + }; + +-static struct methods shadow_methods[] = { +- { "PRAMIN", load_vbios_pramin, true }, +- { "PROM", load_vbios_prom, false }, +- { "PCIROM", load_vbios_pci, true }, +- { "ACPI", load_vbios_acpi, true }, +-}; +-#define NUM_SHADOW_METHODS ARRAY_SIZE(shadow_methods) +- +-static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data) +-{ +- struct methods *methods = shadow_methods; +- int testscore = 3; +- int scores[NUM_SHADOW_METHODS], i; ++static bool ++bios_shadow(struct drm_device *dev) ++{ ++ struct methods shadow_methods[] = { ++ { "PRAMIN", bios_shadow_pramin, true, 0, 0, NULL }, ++ { "PROM", bios_shadow_prom, false, 0, 0, NULL }, ++ { "ACPI", bios_shadow_acpi, true, 0, 0, NULL }, ++ { "PCIROM", bios_shadow_pci, true, 0, 0, NULL }, ++ {} ++ }; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvbios *bios = &dev_priv->vbios; ++ struct methods *mthd, *best; + + if (nouveau_vbios) { +- for (i = 0; i < NUM_SHADOW_METHODS; i++) +- if (!strcasecmp(nouveau_vbios, methods[i].desc)) +- break; +- +- if (i < NUM_SHADOW_METHODS) { +- NV_INFO(dev, "Attempting to use BIOS image from %s\n", +- methods[i].desc); ++ mthd = shadow_methods; ++ do { ++ if (strcasecmp(nouveau_vbios, mthd->desc)) ++ continue; ++ NV_INFO(dev, "VBIOS source: %s\n", mthd->desc); + +- methods[i].loadbios(dev, data); +- if (score_vbios(dev, data, methods[i].rw)) ++ mthd->shadow(bios); ++ mthd->score = score_vbios(bios, mthd->rw); ++ if (mthd->score) + return true; +- } ++ } while ((++mthd)->shadow); + + NV_ERROR(dev, "VBIOS source \'%s\' invalid\n", nouveau_vbios); + } + +- for (i = 0; i < NUM_SHADOW_METHODS; i++) { +- NV_TRACE(dev, "Attempting to load BIOS image from %s\n", +- methods[i].desc); +- data[0] = data[1] = 0; /* avoid reuse of previous image */ +- methods[i].loadbios(dev, data); +- scores[i] = score_vbios(dev, data, methods[i].rw); +- if (scores[i] == testscore) +- return true; +- } +- +- while (--testscore > 0) { +- for (i = 0; i < NUM_SHADOW_METHODS; i++) { +- if (scores[i] == testscore) { +- NV_TRACE(dev, "Using BIOS image from %s\n", +- methods[i].desc); +- methods[i].loadbios(dev, data); +- return true; +- } ++ mthd = shadow_methods; ++ do { ++ NV_TRACE(dev, "Checking %s for VBIOS\n", mthd->desc); ++ mthd->shadow(bios); ++ mthd->score = score_vbios(bios, mthd->rw); ++ mthd->size = bios->length; ++ mthd->data = bios->data; ++ } while (mthd->score != 3 && (++mthd)->shadow); ++ ++ mthd = shadow_methods; ++ best = mthd; ++ do { ++ if (mthd->score > best->score) { ++ kfree(best->data); ++ best = mthd; + } ++ } while ((++mthd)->shadow); ++ ++ if (best->score) { ++ NV_TRACE(dev, "Using VBIOS from %s\n", best->desc); ++ bios->length = best->size; ++ bios->data = best->data; ++ return true; + } + +- NV_ERROR(dev, "No valid BIOS image found\n"); ++ NV_ERROR(dev, "No valid VBIOS image found\n"); + return false; + } + +@@ -723,115 +759,19 @@ static int dcb_entry_idx_from_crtchead(struct drm_device *dev) + return dcb_entry; + } + +-static int +-read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, int index, struct dcb_i2c_entry *i2c) +-{ +- uint8_t dcb_i2c_ver = dcb_version, headerlen = 0, entry_len = 4; +- int i2c_entries = DCB_MAX_NUM_I2C_ENTRIES; +- int recordoffset = 0, rdofs = 1, wrofs = 0; +- uint8_t port_type = 0; +- +- if (!i2ctable) +- return -EINVAL; +- +- if (dcb_version >= 0x30) { +- if (i2ctable[0] != dcb_version) /* necessary? */ +- NV_WARN(dev, +- "DCB I2C table version mismatch (%02X vs %02X)\n", +- i2ctable[0], dcb_version); +- dcb_i2c_ver = i2ctable[0]; +- headerlen = i2ctable[1]; +- if (i2ctable[2] <= DCB_MAX_NUM_I2C_ENTRIES) +- i2c_entries = i2ctable[2]; +- else +- NV_WARN(dev, +- "DCB I2C table has more entries than indexable " +- "(%d entries, max %d)\n", i2ctable[2], +- DCB_MAX_NUM_I2C_ENTRIES); +- entry_len = i2ctable[3]; +- /* [4] is i2c_default_indices, read in parse_dcb_table() */ +- } +- /* +- * It's your own fault if you call this function on a DCB 1.1 BIOS -- +- * the test below is for DCB 1.2 +- */ +- if (dcb_version < 0x14) { +- recordoffset = 2; +- rdofs = 0; +- wrofs = 1; +- } +- +- if (index == 0xf) +- return 0; +- if (index >= i2c_entries) { +- NV_ERROR(dev, "DCB I2C index too big (%d >= %d)\n", +- index, i2ctable[2]); +- return -ENOENT; +- } +- if (i2ctable[headerlen + entry_len * index + 3] == 0xff) { +- NV_ERROR(dev, "DCB I2C entry invalid\n"); +- return -EINVAL; +- } +- +- if (dcb_i2c_ver >= 0x30) { +- port_type = i2ctable[headerlen + recordoffset + 3 + entry_len * index]; +- +- /* +- * Fixup for chips using same address offset for read and +- * write. +- */ +- if (port_type == 4) /* seen on C51 */ +- rdofs = wrofs = 1; +- if (port_type >= 5) /* G80+ */ +- rdofs = wrofs = 0; +- } +- +- if (dcb_i2c_ver >= 0x40) { +- if (port_type != 5 && port_type != 6) +- NV_WARN(dev, "DCB I2C table has port type %d\n", port_type); +- +- i2c->entry = ROM32(i2ctable[headerlen + recordoffset + entry_len * index]); +- } +- +- i2c->port_type = port_type; +- i2c->read = i2ctable[headerlen + recordoffset + rdofs + entry_len * index]; +- i2c->write = i2ctable[headerlen + recordoffset + wrofs + entry_len * index]; +- +- return 0; +-} +- + static struct nouveau_i2c_chan * + init_i2c_device_find(struct drm_device *dev, int i2c_index) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct dcb_table *dcb = &dev_priv->vbios.dcb; +- + if (i2c_index == 0xff) { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct dcb_table *dcb = &dev_priv->vbios.dcb; + /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */ +- int idx = dcb_entry_idx_from_crtchead(dev), shift = 0; +- int default_indices = dcb->i2c_default_indices; ++ int idx = dcb_entry_idx_from_crtchead(dev); + ++ i2c_index = NV_I2C_DEFAULT(0); + if (idx != 0x7f && dcb->entry[idx].i2c_upper_default) +- shift = 4; +- +- i2c_index = (default_indices >> shift) & 0xf; ++ i2c_index = NV_I2C_DEFAULT(1); + } +- if (i2c_index == 0x80) /* g80+ */ +- i2c_index = dcb->i2c_default_indices & 0xf; +- else +- if (i2c_index == 0x81) +- i2c_index = (dcb->i2c_default_indices & 0xf0) >> 4; +- +- if (i2c_index >= DCB_MAX_NUM_I2C_ENTRIES) { +- NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index); +- return NULL; +- } +- +- /* Make sure i2c table entry has been parsed, it may not +- * have been if this is a bus not referenced by a DCB encoder +- */ +- read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table, +- i2c_index, &dcb->i2c[i2c_index]); + + return nouveau_i2c_find(dev, i2c_index); + } +@@ -1199,17 +1139,14 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + + switch (cond) { + case 0: +- { +- struct dcb_connector_table_entry *ent = +- &bios->dcb.connector.entry[dcb->connector]; +- +- if (ent->type != DCB_CONNECTOR_eDP) ++ entry = dcb_conn(dev, dcb->connector); ++ if (!entry || entry[0] != DCB_CONNECTOR_eDP) + iexec->execute = false; +- } + break; + case 1: + case 2: +- if (!(entry[5] & cond)) ++ if ((table[0] < 0x40 && !(entry[5] & cond)) || ++ (table[0] == 0x40 && !(entry[4] & cond))) + iexec->execute = false; + break; + case 5: +@@ -3227,49 +3164,6 @@ init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + return 1; + } + +-static void +-init_gpio_unknv50(struct nvbios *bios, struct dcb_gpio_entry *gpio) +-{ +- const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; +- u32 r, s, v; +- +- /* Not a clue, needs de-magicing */ +- r = nv50_gpio_ctl[gpio->line >> 4]; +- s = (gpio->line & 0x0f); +- v = bios_rd32(bios, r) & ~(0x00010001 << s); +- switch ((gpio->entry & 0x06000000) >> 25) { +- case 1: +- v |= (0x00000001 << s); +- break; +- case 2: +- v |= (0x00010000 << s); +- break; +- default: +- break; +- } +- +- bios_wr32(bios, r, v); +-} +- +-static void +-init_gpio_unknvd0(struct nvbios *bios, struct dcb_gpio_entry *gpio) +-{ +- u32 v, i; +- +- v = bios_rd32(bios, 0x00d610 + (gpio->line * 4)); +- v &= 0xffffff00; +- v |= (gpio->entry & 0x00ff0000) >> 16; +- bios_wr32(bios, 0x00d610 + (gpio->line * 4), v); +- +- i = (gpio->entry & 0x1f000000) >> 24; +- if (i) { +- v = bios_rd32(bios, 0x00d640 + ((i - 1) * 4)); +- v &= 0xffffff00; +- v |= gpio->line; +- bios_wr32(bios, 0x00d640 + ((i - 1) * 4), v); +- } +-} +- + static int + init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + { +@@ -3282,35 +3176,8 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + * each GPIO according to various values listed in each entry + */ + +- struct drm_nouveau_private *dev_priv = bios->dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- int i; +- +- if (dev_priv->card_type < NV_50) { +- NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); +- return 1; +- } +- +- if (!iexec->execute) +- return 1; +- +- for (i = 0; i < bios->dcb.gpio.entries; i++) { +- struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i]; +- +- BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry); +- +- BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n", +- offset, gpio->tag, gpio->state_default); +- +- if (!bios->execute) +- continue; +- +- pgpio->set(bios->dev, gpio->tag, gpio->state_default); +- if (dev_priv->card_type < NV_D0) +- init_gpio_unknv50(bios, gpio); +- else +- init_gpio_unknvd0(bios, gpio); +- } ++ if (iexec->execute && bios->execute) ++ nouveau_gpio_reset(bios->dev); + + return 1; + } +@@ -4407,18 +4274,6 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b + break; + } + +- /* Dell Latitude D620 reports a too-high value for the dual-link +- * transition freq, causing us to program the panel incorrectly. +- * +- * It doesn't appear the VBIOS actually uses its transition freq +- * (90000kHz), instead it uses the "Number of LVDS channels" field +- * out of the panel ID structure (http://www.spwg.org/). +- * +- * For the moment, a quirk will do :) +- */ +- if (nv_match_device(dev, 0x01d7, 0x1028, 0x01c2)) +- bios->fp.duallink_transition_clk = 80000; +- + /* set dual_link flag for EDID case */ + if (pxclk && (chip_version < 0x25 || chip_version > 0x28)) + bios->fp.dual_link = (pxclk >= bios->fp.duallink_transition_clk); +@@ -4541,7 +4396,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, + NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n", + dcbent->type, dcbent->location, dcbent->or); + for (i = 0; i < table[3]; i++) { +- otable = ROMPTR(bios, table[table[1] + (i * table[2])]); ++ otable = ROMPTR(dev, table[table[1] + (i * table[2])]); + if (otable && bios_encoder_match(dcbent, ROM32(otable[0]))) + break; + } +@@ -4719,7 +4574,7 @@ static struct pll_mapping nv84_pll_mapping[] = { + { PLL_CORE , 0x004028 }, + { PLL_SHADER, 0x004020 }, + { PLL_MEMORY, 0x004008 }, +- { PLL_UNK05 , 0x004030 }, ++ { PLL_VDEC , 0x004030 }, + { PLL_UNK41 , 0x00e818 }, + { PLL_VPLL0 , 0x614100 }, + { PLL_VPLL1 , 0x614900 }, +@@ -5485,6 +5340,9 @@ bit_table(struct drm_device *dev, u8 id, struct bit_entry *bit) + struct nvbios *bios = &dev_priv->vbios; + u8 entries, *entry; + ++ if (bios->type != NVBIOS_BIT) ++ return -ENODEV; ++ + entries = bios->data[bios->offset + 10]; + entry = &bios->data[bios->offset + 12]; + while (entries--) { +@@ -5493,7 +5351,7 @@ bit_table(struct drm_device *dev, u8 id, struct bit_entry *bit) + bit->version = entry[1]; + bit->length = ROM16(entry[2]); + bit->offset = ROM16(entry[4]); +- bit->data = ROMPTR(bios, entry[4]); ++ bit->data = ROMPTR(dev, entry[4]); + return 0; + } + +@@ -5598,10 +5456,6 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi + uint16_t legacy_scripts_offset, legacy_i2c_offset; + + /* load needed defaults in case we can't parse this info */ +- bios->dcb.i2c[0].write = NV_CIO_CRE_DDC_WR__INDEX; +- bios->dcb.i2c[0].read = NV_CIO_CRE_DDC_STATUS__INDEX; +- bios->dcb.i2c[1].write = NV_CIO_CRE_DDC0_WR__INDEX; +- bios->dcb.i2c[1].read = NV_CIO_CRE_DDC0_STATUS__INDEX; + bios->digital_min_front_porch = 0x4b; + bios->fmaxvco = 256000; + bios->fminvco = 128000; +@@ -5709,14 +5563,6 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi + bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset]; + bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1]; + bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2]; +- if (bios->data[legacy_i2c_offset + 4]) +- bios->dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4]; +- if (bios->data[legacy_i2c_offset + 5]) +- bios->dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5]; +- if (bios->data[legacy_i2c_offset + 6]) +- bios->dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6]; +- if (bios->data[legacy_i2c_offset + 7]) +- bios->dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7]; + + if (bmplength > 74) { + bios->fmaxvco = ROM32(bmp[67]); +@@ -5767,286 +5613,128 @@ static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len) + return 0; + } + +-static struct dcb_gpio_entry * +-new_gpio_entry(struct nvbios *bios) +-{ +- struct drm_device *dev = bios->dev; +- struct dcb_gpio_table *gpio = &bios->dcb.gpio; +- +- if (gpio->entries >= DCB_MAX_NUM_GPIO_ENTRIES) { +- NV_ERROR(dev, "exceeded maximum number of gpio entries!!\n"); +- return NULL; +- } +- +- return &gpio->entry[gpio->entries++]; +-} +- +-struct dcb_gpio_entry * +-nouveau_bios_gpio_entry(struct drm_device *dev, enum dcb_gpio_tag tag) ++void * ++dcb_table(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nvbios *bios = &dev_priv->vbios; +- int i; +- +- for (i = 0; i < bios->dcb.gpio.entries; i++) { +- if (bios->dcb.gpio.entry[i].tag != tag) +- continue; ++ u8 *dcb = NULL; + +- return &bios->dcb.gpio.entry[i]; ++ if (dev_priv->card_type > NV_04) ++ dcb = ROMPTR(dev, dev_priv->vbios.data[0x36]); ++ if (!dcb) { ++ NV_WARNONCE(dev, "No DCB data found in VBIOS\n"); ++ return NULL; + } + +- return NULL; +-} +- +-static void +-parse_dcb_gpio_table(struct nvbios *bios) +-{ +- struct drm_device *dev = bios->dev; +- struct dcb_gpio_entry *e; +- u8 headerlen, entries, recordlen; +- u8 *dcb, *gpio = NULL, *entry; +- int i; +- +- dcb = ROMPTR(bios, bios->data[0x36]); ++ if (dcb[0] >= 0x41) { ++ NV_WARNONCE(dev, "DCB version 0x%02x unknown\n", dcb[0]); ++ return NULL; ++ } else + if (dcb[0] >= 0x30) { +- gpio = ROMPTR(bios, dcb[10]); +- if (!gpio) +- goto no_table; +- +- headerlen = gpio[1]; +- entries = gpio[2]; +- recordlen = gpio[3]; ++ if (ROM32(dcb[6]) == 0x4edcbdcb) ++ return dcb; + } else +- if (dcb[0] >= 0x22 && dcb[-1] >= 0x13) { +- gpio = ROMPTR(bios, dcb[-15]); +- if (!gpio) +- goto no_table; +- +- headerlen = 3; +- entries = gpio[2]; +- recordlen = gpio[1]; ++ if (dcb[0] >= 0x20) { ++ if (ROM32(dcb[4]) == 0x4edcbdcb) ++ return dcb; + } else +- if (dcb[0] >= 0x22) { +- /* No GPIO table present, parse the TVDAC GPIO data. */ +- uint8_t *tvdac_gpio = &dcb[-5]; +- +- if (tvdac_gpio[0] & 1) { +- e = new_gpio_entry(bios); +- e->tag = DCB_GPIO_TVDAC0; +- e->line = tvdac_gpio[1] >> 4; +- e->invert = tvdac_gpio[0] & 2; +- } +- +- goto no_table; ++ if (dcb[0] >= 0x15) { ++ if (!memcmp(&dcb[-7], "DEV_REC", 7)) ++ return dcb; + } else { +- NV_DEBUG(dev, "no/unknown gpio table on DCB 0x%02x\n", dcb[0]); +- goto no_table; +- } +- +- entry = gpio + headerlen; +- for (i = 0; i < entries; i++, entry += recordlen) { +- e = new_gpio_entry(bios); +- if (!e) +- break; +- +- if (gpio[0] < 0x40) { +- e->entry = ROM16(entry[0]); +- e->tag = (e->entry & 0x07e0) >> 5; +- if (e->tag == 0x3f) { +- bios->dcb.gpio.entries--; +- continue; +- } +- +- e->line = (e->entry & 0x001f); +- e->invert = ((e->entry & 0xf800) >> 11) != 4; +- } else { +- e->entry = ROM32(entry[0]); +- e->tag = (e->entry & 0x0000ff00) >> 8; +- if (e->tag == 0xff) { +- bios->dcb.gpio.entries--; +- continue; +- } +- +- e->line = (e->entry & 0x0000001f) >> 0; +- if (gpio[0] == 0x40) { +- e->state_default = (e->entry & 0x01000000) >> 24; +- e->state[0] = (e->entry & 0x18000000) >> 27; +- e->state[1] = (e->entry & 0x60000000) >> 29; +- } else { +- e->state_default = (e->entry & 0x00000080) >> 7; +- e->state[0] = (entry[4] >> 4) & 3; +- e->state[1] = (entry[4] >> 6) & 3; +- } +- } +- } +- +-no_table: +- /* Apple iMac G4 NV18 */ +- if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { +- e = new_gpio_entry(bios); +- if (e) { +- e->tag = DCB_GPIO_TVDAC0; +- e->line = 4; +- } +- } +-} +- +-struct dcb_connector_table_entry * +-nouveau_bios_connector_entry(struct drm_device *dev, int index) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nvbios *bios = &dev_priv->vbios; +- struct dcb_connector_table_entry *cte; +- +- if (index >= bios->dcb.connector.entries) +- return NULL; +- +- cte = &bios->dcb.connector.entry[index]; +- if (cte->type == 0xff) ++ /* ++ * v1.4 (some NV15/16, NV11+) seems the same as v1.5, but ++ * always has the same single (crt) entry, even when tv-out ++ * present, so the conclusion is this version cannot really ++ * be used. ++ * ++ * v1.2 tables (some NV6/10, and NV15+) normally have the ++ * same 5 entries, which are not specific to the card and so ++ * no use. ++ * ++ * v1.2 does have an I2C table that read_dcb_i2c_table can ++ * handle, but cards exist (nv11 in #14821) with a bad i2c ++ * table pointer, so use the indices parsed in ++ * parse_bmp_structure. ++ * ++ * v1.1 (NV5+, maybe some NV4) is entirely unhelpful ++ */ ++ NV_WARNONCE(dev, "No useful DCB data in VBIOS\n"); + return NULL; ++ } + +- return cte; ++ NV_WARNONCE(dev, "DCB header validation failed\n"); ++ return NULL; + } + +-static enum dcb_connector_type +-divine_connector_type(struct nvbios *bios, int index) ++void * ++dcb_outp(struct drm_device *dev, u8 idx) + { +- struct dcb_table *dcb = &bios->dcb; +- unsigned encoders = 0, type = DCB_CONNECTOR_NONE; +- int i; +- +- for (i = 0; i < dcb->entries; i++) { +- if (dcb->entry[i].connector == index) +- encoders |= (1 << dcb->entry[i].type); +- } +- +- if (encoders & (1 << OUTPUT_DP)) { +- if (encoders & (1 << OUTPUT_TMDS)) +- type = DCB_CONNECTOR_DP; +- else +- type = DCB_CONNECTOR_eDP; ++ u8 *dcb = dcb_table(dev); ++ if (dcb && dcb[0] >= 0x30) { ++ if (idx < dcb[2]) ++ return dcb + dcb[1] + (idx * dcb[3]); + } else +- if (encoders & (1 << OUTPUT_TMDS)) { +- if (encoders & (1 << OUTPUT_ANALOG)) +- type = DCB_CONNECTOR_DVI_I; +- else +- type = DCB_CONNECTOR_DVI_D; +- } else +- if (encoders & (1 << OUTPUT_ANALOG)) { +- type = DCB_CONNECTOR_VGA; +- } else +- if (encoders & (1 << OUTPUT_LVDS)) { +- type = DCB_CONNECTOR_LVDS; ++ if (dcb && dcb[0] >= 0x20) { ++ u8 *i2c = ROMPTR(dev, dcb[2]); ++ u8 *ent = dcb + 8 + (idx * 8); ++ if (i2c && ent < i2c) ++ return ent; + } else +- if (encoders & (1 << OUTPUT_TV)) { +- type = DCB_CONNECTOR_TV_0; ++ if (dcb && dcb[0] >= 0x15) { ++ u8 *i2c = ROMPTR(dev, dcb[2]); ++ u8 *ent = dcb + 4 + (idx * 10); ++ if (i2c && ent < i2c) ++ return ent; + } + +- return type; ++ return NULL; + } + +-static void +-apply_dcb_connector_quirks(struct nvbios *bios, int idx) +-{ +- struct dcb_connector_table_entry *cte = &bios->dcb.connector.entry[idx]; +- struct drm_device *dev = bios->dev; ++int ++dcb_outp_foreach(struct drm_device *dev, void *data, ++ int (*exec)(struct drm_device *, void *, int idx, u8 *outp)) ++{ ++ int ret, idx = -1; ++ u8 *outp = NULL; ++ while ((outp = dcb_outp(dev, ++idx))) { ++ if (ROM32(outp[0]) == 0x00000000) ++ break; /* seen on an NV11 with DCB v1.5 */ ++ if (ROM32(outp[0]) == 0xffffffff) ++ break; /* seen on an NV17 with DCB v2.0 */ ++ ++ if ((outp[0] & 0x0f) == OUTPUT_UNUSED) ++ continue; ++ if ((outp[0] & 0x0f) == OUTPUT_EOL) ++ break; + +- /* Gigabyte NX85T */ +- if (nv_match_device(dev, 0x0421, 0x1458, 0x344c)) { +- if (cte->type == DCB_CONNECTOR_HDMI_1) +- cte->type = DCB_CONNECTOR_DVI_I; ++ ret = exec(dev, data, idx, outp); ++ if (ret) ++ return ret; + } + +- /* Gigabyte GV-NX86T512H */ +- if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) { +- if (cte->type == DCB_CONNECTOR_HDMI_1) +- cte->type = DCB_CONNECTOR_DVI_I; +- } ++ return 0; + } + +-static const u8 hpd_gpio[16] = { +- 0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff, +- 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x60, +-}; +- +-static void +-parse_dcb_connector_table(struct nvbios *bios) ++u8 * ++dcb_conntab(struct drm_device *dev) + { +- struct drm_device *dev = bios->dev; +- struct dcb_connector_table *ct = &bios->dcb.connector; +- struct dcb_connector_table_entry *cte; +- uint8_t *conntab = &bios->data[bios->dcb.connector_table_ptr]; +- uint8_t *entry; +- int i; +- +- if (!bios->dcb.connector_table_ptr) { +- NV_DEBUG_KMS(dev, "No DCB connector table present\n"); +- return; +- } +- +- NV_INFO(dev, "DCB connector table: VHER 0x%02x %d %d %d\n", +- conntab[0], conntab[1], conntab[2], conntab[3]); +- if ((conntab[0] != 0x30 && conntab[0] != 0x40) || +- (conntab[3] != 2 && conntab[3] != 4)) { +- NV_ERROR(dev, " Unknown! Please report.\n"); +- return; ++ u8 *dcb = dcb_table(dev); ++ if (dcb && dcb[0] >= 0x30 && dcb[1] >= 0x16) { ++ u8 *conntab = ROMPTR(dev, dcb[0x14]); ++ if (conntab && conntab[0] >= 0x30 && conntab[0] <= 0x40) ++ return conntab; + } ++ return NULL; ++} + +- ct->entries = conntab[2]; +- +- entry = conntab + conntab[1]; +- cte = &ct->entry[0]; +- for (i = 0; i < conntab[2]; i++, entry += conntab[3], cte++) { +- cte->index = i; +- if (conntab[3] == 2) +- cte->entry = ROM16(entry[0]); +- else +- cte->entry = ROM32(entry[0]); +- +- cte->type = (cte->entry & 0x000000ff) >> 0; +- cte->index2 = (cte->entry & 0x00000f00) >> 8; +- +- cte->gpio_tag = ffs((cte->entry & 0x07033000) >> 12); +- cte->gpio_tag = hpd_gpio[cte->gpio_tag]; +- +- if (cte->type == 0xff) +- continue; +- +- apply_dcb_connector_quirks(bios, i); +- +- NV_INFO(dev, " %d: 0x%08x: type 0x%02x idx %d tag 0x%02x\n", +- i, cte->entry, cte->type, cte->index, cte->gpio_tag); +- +- /* check for known types, fallback to guessing the type +- * from attached encoders if we hit an unknown. +- */ +- switch (cte->type) { +- case DCB_CONNECTOR_VGA: +- case DCB_CONNECTOR_TV_0: +- case DCB_CONNECTOR_TV_1: +- case DCB_CONNECTOR_TV_3: +- case DCB_CONNECTOR_DVI_I: +- case DCB_CONNECTOR_DVI_D: +- case DCB_CONNECTOR_LVDS: +- case DCB_CONNECTOR_LVDS_SPWG: +- case DCB_CONNECTOR_DP: +- case DCB_CONNECTOR_eDP: +- case DCB_CONNECTOR_HDMI_0: +- case DCB_CONNECTOR_HDMI_1: +- break; +- default: +- cte->type = divine_connector_type(bios, cte->index); +- NV_WARN(dev, "unknown type, using 0x%02x\n", cte->type); +- break; +- } +- +- if (nouveau_override_conntype) { +- int type = divine_connector_type(bios, cte->index); +- if (type != cte->type) +- NV_WARN(dev, " -> type 0x%02x\n", cte->type); +- } +- +- } ++u8 * ++dcb_conn(struct drm_device *dev, u8 idx) ++{ ++ u8 *conntab = dcb_conntab(dev); ++ if (conntab && idx < conntab[2]) ++ return conntab + conntab[1] + (idx * conntab[3]); ++ return NULL; + } + + static struct dcb_entry *new_dcb_entry(struct dcb_table *dcb) +@@ -6079,8 +5767,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, + entry->type = conn & 0xf; + entry->i2c_index = (conn >> 4) & 0xf; + entry->heads = (conn >> 8) & 0xf; +- if (dcb->version >= 0x40) +- entry->connector = (conn >> 12) & 0xf; ++ entry->connector = (conn >> 12) & 0xf; + entry->bus = (conn >> 16) & 0xf; + entry->location = (conn >> 20) & 0x3; + entry->or = (conn >> 24) & 0xf; +@@ -6252,25 +5939,6 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, + return true; + } + +-static bool parse_dcb_entry(struct drm_device *dev, struct dcb_table *dcb, +- uint32_t conn, uint32_t conf) +-{ +- struct dcb_entry *entry = new_dcb_entry(dcb); +- bool ret; +- +- if (dcb->version >= 0x20) +- ret = parse_dcb20_entry(dev, dcb, conn, conf, entry); +- else +- ret = parse_dcb15_entry(dev, dcb, conn, conf, entry); +- if (!ret) +- return ret; +- +- read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table, +- entry->i2c_index, &dcb->i2c[entry->i2c_index]); +- +- return true; +-} +- + static + void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) + { +@@ -6431,154 +6099,122 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios) + #endif + + /* Make up some sane defaults */ +- fabricate_dcb_output(dcb, OUTPUT_ANALOG, LEGACY_I2C_CRT, 1, 1); ++ fabricate_dcb_output(dcb, OUTPUT_ANALOG, ++ bios->legacy.i2c_indices.crt, 1, 1); + + if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) +- fabricate_dcb_output(dcb, OUTPUT_TV, LEGACY_I2C_TV, ++ fabricate_dcb_output(dcb, OUTPUT_TV, ++ bios->legacy.i2c_indices.tv, + all_heads, 0); + + else if (bios->tmds.output0_script_ptr || + bios->tmds.output1_script_ptr) +- fabricate_dcb_output(dcb, OUTPUT_TMDS, LEGACY_I2C_PANEL, ++ fabricate_dcb_output(dcb, OUTPUT_TMDS, ++ bios->legacy.i2c_indices.panel, + all_heads, 1); + } + + static int +-parse_dcb_table(struct drm_device *dev, struct nvbios *bios) ++parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct dcb_table *dcb = &bios->dcb; +- uint16_t dcbptr = 0, i2ctabptr = 0; +- uint8_t *dcbtable; +- uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES; +- bool configblock = true; +- int recordlength = 8, confofs = 4; +- int i; +- +- /* get the offset from 0x36 */ +- if (dev_priv->card_type > NV_04) { +- dcbptr = ROM16(bios->data[0x36]); +- if (dcbptr == 0x0000) +- NV_WARN(dev, "No output data (DCB) found in BIOS\n"); +- } +- +- /* this situation likely means a really old card, pre DCB */ +- if (dcbptr == 0x0) { +- fabricate_dcb_encoder_table(dev, bios); +- return 0; +- } +- +- dcbtable = &bios->data[dcbptr]; +- +- /* get DCB version */ +- dcb->version = dcbtable[0]; +- NV_TRACE(dev, "Found Display Configuration Block version %d.%d\n", +- dcb->version >> 4, dcb->version & 0xf); +- +- if (dcb->version >= 0x20) { /* NV17+ */ +- uint32_t sig; ++ struct dcb_table *dcb = &dev_priv->vbios.dcb; ++ u32 conf = (dcb->version >= 0x20) ? ROM32(outp[4]) : ROM32(outp[6]); ++ u32 conn = ROM32(outp[0]); ++ bool ret; + +- if (dcb->version >= 0x30) { /* NV40+ */ +- headerlen = dcbtable[1]; +- entries = dcbtable[2]; +- recordlength = dcbtable[3]; +- i2ctabptr = ROM16(dcbtable[4]); +- sig = ROM32(dcbtable[6]); +- dcb->gpio_table_ptr = ROM16(dcbtable[10]); +- dcb->connector_table_ptr = ROM16(dcbtable[20]); +- } else { +- i2ctabptr = ROM16(dcbtable[2]); +- sig = ROM32(dcbtable[4]); +- headerlen = 8; +- } ++ if (apply_dcb_encoder_quirks(dev, idx, &conn, &conf)) { ++ struct dcb_entry *entry = new_dcb_entry(dcb); + +- if (sig != 0x4edcbdcb) { +- NV_ERROR(dev, "Bad Display Configuration Block " +- "signature (%08X)\n", sig); +- return -EINVAL; +- } +- } else if (dcb->version >= 0x15) { /* some NV11 and NV20 */ +- char sig[8] = { 0 }; ++ NV_TRACEWARN(dev, "DCB outp %02d: %08x %08x\n", idx, conn, conf); + +- strncpy(sig, (char *)&dcbtable[-7], 7); +- i2ctabptr = ROM16(dcbtable[2]); +- recordlength = 10; +- confofs = 6; ++ if (dcb->version >= 0x20) ++ ret = parse_dcb20_entry(dev, dcb, conn, conf, entry); ++ else ++ ret = parse_dcb15_entry(dev, dcb, conn, conf, entry); ++ if (!ret) ++ return 1; /* stop parsing */ + +- if (strcmp(sig, "DEV_REC")) { +- NV_ERROR(dev, "Bad Display Configuration Block " +- "signature (%s)\n", sig); +- return -EINVAL; +- } +- } else { +- /* +- * v1.4 (some NV15/16, NV11+) seems the same as v1.5, but always +- * has the same single (crt) entry, even when tv-out present, so +- * the conclusion is this version cannot really be used. +- * v1.2 tables (some NV6/10, and NV15+) normally have the same +- * 5 entries, which are not specific to the card and so no use. +- * v1.2 does have an I2C table that read_dcb_i2c_table can +- * handle, but cards exist (nv11 in #14821) with a bad i2c table +- * pointer, so use the indices parsed in parse_bmp_structure. +- * v1.1 (NV5+, maybe some NV4) is entirely unhelpful ++ /* Ignore the I2C index for on-chip TV-out, as there ++ * are cards with bogus values (nv31m in bug 23212), ++ * and it's otherwise useless. + */ +- NV_TRACEWARN(dev, "No useful information in BIOS output table; " +- "adding all possible outputs\n"); +- fabricate_dcb_encoder_table(dev, bios); +- return 0; ++ if (entry->type == OUTPUT_TV && ++ entry->location == DCB_LOC_ON_CHIP) ++ entry->i2c_index = 0x0f; + } + +- if (!i2ctabptr) +- NV_WARN(dev, "No pointer to DCB I2C port table\n"); +- else { +- dcb->i2c_table = &bios->data[i2ctabptr]; +- if (dcb->version >= 0x30) +- dcb->i2c_default_indices = dcb->i2c_table[4]; ++ return 0; ++} + +- /* +- * Parse the "management" I2C bus, used for hardware +- * monitoring and some external TMDS transmitters. +- */ +- if (dcb->version >= 0x22) { +- int idx = (dcb->version >= 0x40 ? +- dcb->i2c_default_indices & 0xf : +- 2); ++static void ++dcb_fake_connectors(struct nvbios *bios) ++{ ++ struct dcb_table *dcbt = &bios->dcb; ++ u8 map[16] = { }; ++ int i, idx = 0; + +- read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table, +- idx, &dcb->i2c[idx]); ++ /* heuristic: if we ever get a non-zero connector field, assume ++ * that all the indices are valid and we don't need fake them. ++ * ++ * and, as usual, a blacklist of boards with bad bios data.. ++ */ ++ if (!nv_match_device(bios->dev, 0x0392, 0x107d, 0x20a2)) { ++ for (i = 0; i < dcbt->entries; i++) { ++ if (dcbt->entry[i].connector) ++ return; + } + } + +- if (entries > DCB_MAX_NUM_ENTRIES) +- entries = DCB_MAX_NUM_ENTRIES; +- +- for (i = 0; i < entries; i++) { +- uint32_t connection, config = 0; +- +- connection = ROM32(dcbtable[headerlen + recordlength * i]); +- if (configblock) +- config = ROM32(dcbtable[headerlen + confofs + recordlength * i]); +- +- /* seen on an NV11 with DCB v1.5 */ +- if (connection == 0x00000000) +- break; ++ /* no useful connector info available, we need to make it up ++ * ourselves. the rule here is: anything on the same i2c bus ++ * is considered to be on the same connector. any output ++ * without an associated i2c bus is assigned its own unique ++ * connector index. ++ */ ++ for (i = 0; i < dcbt->entries; i++) { ++ u8 i2c = dcbt->entry[i].i2c_index; ++ if (i2c == 0x0f) { ++ dcbt->entry[i].connector = idx++; ++ } else { ++ if (!map[i2c]) ++ map[i2c] = ++idx; ++ dcbt->entry[i].connector = map[i2c] - 1; ++ } ++ } + +- /* seen on an NV17 with DCB v2.0 */ +- if (connection == 0xffffffff) +- break; ++ /* if we created more than one connector, destroy the connector ++ * table - just in case it has random, rather than stub, entries. ++ */ ++ if (i > 1) { ++ u8 *conntab = dcb_conntab(bios->dev); ++ if (conntab) ++ conntab[0] = 0x00; ++ } ++} + +- if ((connection & 0x0000000f) == 0x0000000f) +- continue; ++static int ++parse_dcb_table(struct drm_device *dev, struct nvbios *bios) ++{ ++ struct dcb_table *dcb = &bios->dcb; ++ u8 *dcbt, *conn; ++ int idx; ++ ++ dcbt = dcb_table(dev); ++ if (!dcbt) { ++ /* handle pre-DCB boards */ ++ if (bios->type == NVBIOS_BMP) { ++ fabricate_dcb_encoder_table(dev, bios); ++ return 0; ++ } + +- if (!apply_dcb_encoder_quirks(dev, i, &connection, &config)) +- continue; ++ return -EINVAL; ++ } + +- NV_TRACEWARN(dev, "Raw DCB entry %d: %08x %08x\n", +- dcb->entries, connection, config); ++ NV_TRACE(dev, "DCB version %d.%d\n", dcbt[0] >> 4, dcbt[0] & 0xf); + +- if (!parse_dcb_entry(dev, dcb, connection, config)) +- break; +- } ++ dcb->version = dcbt[0]; ++ dcb_outp_foreach(dev, NULL, parse_dcb_entry); + + /* + * apart for v2.1+ not being known for requiring merging, this +@@ -6590,77 +6226,19 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios) + if (!dcb->entries) + return -ENXIO; + +- parse_dcb_gpio_table(bios); +- parse_dcb_connector_table(bios); +- return 0; +-} +- +-static void +-fixup_legacy_connector(struct nvbios *bios) +-{ +- struct dcb_table *dcb = &bios->dcb; +- int i, i2c, i2c_conn[DCB_MAX_NUM_I2C_ENTRIES] = { }; +- +- /* +- * DCB 3.0 also has the table in most cases, but there are some cards +- * where the table is filled with stub entries, and the DCB entriy +- * indices are all 0. We don't need the connector indices on pre-G80 +- * chips (yet?) so limit the use to DCB 4.0 and above. +- */ +- if (dcb->version >= 0x40) +- return; +- +- dcb->connector.entries = 0; +- +- /* +- * No known connector info before v3.0, so make it up. the rule here +- * is: anything on the same i2c bus is considered to be on the same +- * connector. any output without an associated i2c bus is assigned +- * its own unique connector index. +- */ +- for (i = 0; i < dcb->entries; i++) { +- /* +- * Ignore the I2C index for on-chip TV-out, as there +- * are cards with bogus values (nv31m in bug 23212), +- * and it's otherwise useless. +- */ +- if (dcb->entry[i].type == OUTPUT_TV && +- dcb->entry[i].location == DCB_LOC_ON_CHIP) +- dcb->entry[i].i2c_index = 0xf; +- i2c = dcb->entry[i].i2c_index; +- +- if (i2c_conn[i2c]) { +- dcb->entry[i].connector = i2c_conn[i2c] - 1; +- continue; ++ /* dump connector table entries to log, if any exist */ ++ idx = -1; ++ while ((conn = dcb_conn(dev, ++idx))) { ++ if (conn[0] != 0xff) { ++ NV_TRACE(dev, "DCB conn %02d: ", idx); ++ if (dcb_conntab(dev)[3] < 4) ++ printk("%04x\n", ROM16(conn[0])); ++ else ++ printk("%08x\n", ROM32(conn[0])); + } +- +- dcb->entry[i].connector = dcb->connector.entries++; +- if (i2c != 0xf) +- i2c_conn[i2c] = dcb->connector.entries; +- } +- +- /* Fake the connector table as well as just connector indices */ +- for (i = 0; i < dcb->connector.entries; i++) { +- dcb->connector.entry[i].index = i; +- dcb->connector.entry[i].type = divine_connector_type(bios, i); +- dcb->connector.entry[i].gpio_tag = 0xff; +- } +-} +- +-static void +-fixup_legacy_i2c(struct nvbios *bios) +-{ +- struct dcb_table *dcb = &bios->dcb; +- int i; +- +- for (i = 0; i < dcb->entries; i++) { +- if (dcb->entry[i].i2c_index == LEGACY_I2C_CRT) +- dcb->entry[i].i2c_index = bios->legacy.i2c_indices.crt; +- if (dcb->entry[i].i2c_index == LEGACY_I2C_PANEL) +- dcb->entry[i].i2c_index = bios->legacy.i2c_indices.panel; +- if (dcb->entry[i].i2c_index == LEGACY_I2C_TV) +- dcb->entry[i].i2c_index = bios->legacy.i2c_indices.tv; + } ++ dcb_fake_connectors(bios); ++ return 0; + } + + static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bios, uint16_t hwsq_offset, int entry) +@@ -6799,11 +6377,7 @@ static bool NVInitVBIOS(struct drm_device *dev) + spin_lock_init(&bios->lock); + bios->dev = dev; + +- if (!NVShadowVBIOS(dev, bios->data)) +- return false; +- +- bios->length = NV_PROM_SIZE; +- return true; ++ return bios_shadow(dev); + } + + static int nouveau_parse_vbios_struct(struct drm_device *dev) +@@ -6879,19 +6453,6 @@ nouveau_run_vbios_init(struct drm_device *dev) + return ret; + } + +-static void +-nouveau_bios_i2c_devices_takedown(struct drm_device *dev) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nvbios *bios = &dev_priv->vbios; +- struct dcb_i2c_entry *entry; +- int i; +- +- entry = &bios->dcb.i2c[0]; +- for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++, entry++) +- nouveau_i2c_fini(dev, entry); +-} +- + static bool + nouveau_bios_posted(struct drm_device *dev) + { +@@ -6928,12 +6489,17 @@ nouveau_bios_init(struct drm_device *dev) + if (ret) + return ret; + +- ret = parse_dcb_table(dev, bios); ++ ret = nouveau_i2c_init(dev); + if (ret) + return ret; + +- fixup_legacy_i2c(bios); +- fixup_legacy_connector(bios); ++ ret = nouveau_mxm_init(dev); ++ if (ret) ++ return ret; ++ ++ ret = parse_dcb_table(dev, bios); ++ if (ret) ++ return ret; + + if (!bios->major_version) /* we don't run version 0 bios */ + return 0; +@@ -6971,5 +6537,10 @@ nouveau_bios_init(struct drm_device *dev) + void + nouveau_bios_takedown(struct drm_device *dev) + { +- nouveau_bios_i2c_devices_takedown(dev); ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ nouveau_mxm_fini(dev); ++ nouveau_i2c_fini(dev); ++ ++ kfree(dev_priv->vbios.data); + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h +index 8adb69e..298a3af 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_bios.h ++++ b/drivers/gpu/drm/nouveau/nouveau_bios.h +@@ -34,9 +34,14 @@ + + #define DCB_LOC_ON_CHIP 0 + +-#define ROM16(x) le16_to_cpu(*(uint16_t *)&(x)) +-#define ROM32(x) le32_to_cpu(*(uint32_t *)&(x)) +-#define ROMPTR(bios, x) (ROM16(x) ? &(bios)->data[ROM16(x)] : NULL) ++#define ROM16(x) le16_to_cpu(*(u16 *)&(x)) ++#define ROM32(x) le32_to_cpu(*(u32 *)&(x)) ++#define ROM48(x) ({ u8 *p = &(x); (u64)ROM16(p[4]) << 32 | ROM32(p[0]); }) ++#define ROM64(x) le64_to_cpu(*(u64 *)&(x)) ++#define ROMPTR(d,x) ({ \ ++ struct drm_nouveau_private *dev_priv = (d)->dev_private; \ ++ ROM16(x) ? &dev_priv->vbios.data[ROM16(x)] : NULL; \ ++}) + + struct bit_entry { + uint8_t id; +@@ -48,30 +53,13 @@ struct bit_entry { + + int bit_table(struct drm_device *, u8 id, struct bit_entry *); + +-struct dcb_i2c_entry { +- uint32_t entry; +- uint8_t port_type; +- uint8_t read, write; +- struct nouveau_i2c_chan *chan; +-}; +- + enum dcb_gpio_tag { +- DCB_GPIO_TVDAC0 = 0xc, ++ DCB_GPIO_PANEL_POWER = 0x01, ++ DCB_GPIO_TVDAC0 = 0x0c, + DCB_GPIO_TVDAC1 = 0x2d, +-}; +- +-struct dcb_gpio_entry { +- enum dcb_gpio_tag tag; +- int line; +- bool invert; +- uint32_t entry; +- uint8_t state_default; +- uint8_t state[2]; +-}; +- +-struct dcb_gpio_table { +- int entries; +- struct dcb_gpio_entry entry[DCB_MAX_NUM_GPIO_ENTRIES]; ++ DCB_GPIO_PWM_FAN = 0x09, ++ DCB_GPIO_FAN_SENSE = 0x3d, ++ DCB_GPIO_UNUSED = 0xff + }; + + enum dcb_connector_type { +@@ -81,29 +69,19 @@ enum dcb_connector_type { + DCB_CONNECTOR_TV_3 = 0x13, + DCB_CONNECTOR_DVI_I = 0x30, + DCB_CONNECTOR_DVI_D = 0x31, ++ DCB_CONNECTOR_DMS59_0 = 0x38, ++ DCB_CONNECTOR_DMS59_1 = 0x39, + DCB_CONNECTOR_LVDS = 0x40, + DCB_CONNECTOR_LVDS_SPWG = 0x41, + DCB_CONNECTOR_DP = 0x46, + DCB_CONNECTOR_eDP = 0x47, + DCB_CONNECTOR_HDMI_0 = 0x60, + DCB_CONNECTOR_HDMI_1 = 0x61, ++ DCB_CONNECTOR_DMS59_DP0 = 0x64, ++ DCB_CONNECTOR_DMS59_DP1 = 0x65, + DCB_CONNECTOR_NONE = 0xff + }; + +-struct dcb_connector_table_entry { +- uint8_t index; +- uint32_t entry; +- enum dcb_connector_type type; +- uint8_t index2; +- uint8_t gpio_tag; +- void *drm; +-}; +- +-struct dcb_connector_table { +- int entries; +- struct dcb_connector_table_entry entry[DCB_MAX_NUM_CONNECTOR_ENTRIES]; +-}; +- + enum dcb_type { + OUTPUT_ANALOG = 0, + OUTPUT_TV = 1, +@@ -111,6 +89,7 @@ enum dcb_type { + OUTPUT_LVDS = 3, + OUTPUT_DP = 6, + OUTPUT_EOL = 14, /* DCB 4.0+, appears to be end-of-list */ ++ OUTPUT_UNUSED = 15, + OUTPUT_ANY = -1 + }; + +@@ -155,18 +134,8 @@ struct dcb_entry { + + struct dcb_table { + uint8_t version; +- + int entries; + struct dcb_entry entry[DCB_MAX_NUM_ENTRIES]; +- +- uint8_t *i2c_table; +- uint8_t i2c_default_indices; +- struct dcb_i2c_entry i2c[DCB_MAX_NUM_I2C_ENTRIES]; +- +- uint16_t gpio_table_ptr; +- struct dcb_gpio_table gpio; +- uint16_t connector_table_ptr; +- struct dcb_connector_table connector; + }; + + enum nouveau_or { +@@ -195,7 +164,7 @@ enum pll_types { + PLL_SHADER = 0x02, + PLL_UNK03 = 0x03, + PLL_MEMORY = 0x04, +- PLL_UNK05 = 0x05, ++ PLL_VDEC = 0x05, + PLL_UNK40 = 0x40, + PLL_UNK41 = 0x41, + PLL_UNK42 = 0x42, +@@ -244,6 +213,8 @@ struct nvbios { + NVBIOS_BIT + } type; + uint16_t offset; ++ uint32_t length; ++ uint8_t *data; + + uint8_t chip_version; + +@@ -254,8 +225,6 @@ struct nvbios { + + spinlock_t lock; + +- uint8_t data[NV_PROM_SIZE]; +- unsigned int length; + bool execute; + + uint8_t major_version; +@@ -333,4 +302,11 @@ struct nvbios { + } legacy; + }; + ++void *dcb_table(struct drm_device *); ++void *dcb_outp(struct drm_device *, u8 idx); ++int dcb_outp_foreach(struct drm_device *, void *data, ++ int (*)(struct drm_device *, void *, int idx, u8 *outp)); ++u8 *dcb_conntab(struct drm_device *); ++u8 *dcb_conn(struct drm_device *, u8 idx); ++ + #endif +diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c +index 2bb29c9..2c3d5c8 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_bo.c ++++ b/drivers/gpu/drm/nouveau/nouveau_bo.c +@@ -28,6 +28,7 @@ + */ + + #include "drmP.h" ++#include "ttm/ttm_page_alloc.h" + + #include "nouveau_drm.h" + #include "nouveau_drv.h" +@@ -92,6 +93,7 @@ nouveau_bo_new(struct drm_device *dev, int size, int align, + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_bo *nvbo; ++ size_t acc_size; + int ret; + + nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL); +@@ -114,9 +116,12 @@ nouveau_bo_new(struct drm_device *dev, int size, int align, + nvbo->bo.mem.num_pages = size >> PAGE_SHIFT; + nouveau_bo_placement_set(nvbo, flags, 0); + ++ acc_size = ttm_bo_dma_acc_size(&dev_priv->ttm.bdev, size, ++ sizeof(struct nouveau_bo)); ++ + ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size, + ttm_bo_type_device, &nvbo->placement, +- align >> PAGE_SHIFT, 0, false, NULL, size, ++ align >> PAGE_SHIFT, 0, false, NULL, acc_size, + nouveau_bo_del_ttm); + if (ret) { + /* ttm will call nouveau_bo_del_ttm if it fails.. */ +@@ -343,8 +348,10 @@ nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val) + *mem = val; + } + +-static struct ttm_backend * +-nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev) ++static struct ttm_tt * ++nouveau_ttm_tt_create(struct ttm_bo_device *bdev, ++ unsigned long size, uint32_t page_flags, ++ struct page *dummy_read_page) + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); + struct drm_device *dev = dev_priv->dev; +@@ -352,11 +359,13 @@ nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev) + switch (dev_priv->gart_info.type) { + #if __OS_HAS_AGP + case NOUVEAU_GART_AGP: +- return ttm_agp_backend_init(bdev, dev->agp->bridge); ++ return ttm_agp_tt_create(bdev, dev->agp->bridge, ++ size, page_flags, dummy_read_page); + #endif + case NOUVEAU_GART_PDMA: + case NOUVEAU_GART_HW: +- return nouveau_sgdma_init_ttm(dev); ++ return nouveau_sgdma_create_ttm(bdev, size, page_flags, ++ dummy_read_page); + default: + NV_ERROR(dev, "Unknown GART type %d\n", + dev_priv->gart_info.type); +@@ -673,8 +682,7 @@ nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo, + if (mem->mem_type == TTM_PL_VRAM) + nouveau_vm_map(vma, node); + else +- nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT, +- node, node->pages); ++ nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT, node); + + return 0; + } +@@ -685,16 +693,12 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, + struct ttm_mem_reg *new_mem) + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); ++ struct nouveau_channel *chan = chan = dev_priv->channel; + struct nouveau_bo *nvbo = nouveau_bo(bo); + struct ttm_mem_reg *old_mem = &bo->mem; +- struct nouveau_channel *chan; + int ret; + +- chan = nvbo->channel; +- if (!chan) { +- chan = dev_priv->channel; +- mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); +- } ++ mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); + + /* create temporary vmas for the transfer and attach them to the + * old nouveau_mem node, these will get cleaned up after ttm has +@@ -726,8 +730,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, + } + + out: +- if (chan == dev_priv->channel) +- mutex_unlock(&chan->mutex); ++ mutex_unlock(&chan->mutex); + return ret; + } + +@@ -801,19 +804,22 @@ out: + static void + nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) + { +- struct nouveau_mem *node = new_mem->mm_node; + struct nouveau_bo *nvbo = nouveau_bo(bo); + struct nouveau_vma *vma; + ++ /* ttm can now (stupidly) pass the driver bos it didn't create... */ ++ if (bo->destroy != nouveau_bo_del_ttm) ++ return; ++ + list_for_each_entry(vma, &nvbo->vma_list, head) { +- if (new_mem->mem_type == TTM_PL_VRAM) { ++ if (new_mem && new_mem->mem_type == TTM_PL_VRAM) { + nouveau_vm_map(vma, new_mem->mm_node); + } else +- if (new_mem->mem_type == TTM_PL_TT && ++ if (new_mem && new_mem->mem_type == TTM_PL_TT && + nvbo->page_shift == vma->vm->spg_shift) { + nouveau_vm_map_sg(vma, 0, new_mem-> + num_pages << PAGE_SHIFT, +- node, node->pages); ++ new_mem->mm_node); + } else { + nouveau_vm_unmap(vma); + } +@@ -1044,8 +1050,94 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) + nouveau_fence_unref(&old_fence); + } + ++static int ++nouveau_ttm_tt_populate(struct ttm_tt *ttm) ++{ ++ struct ttm_dma_tt *ttm_dma = (void *)ttm; ++ struct drm_nouveau_private *dev_priv; ++ struct drm_device *dev; ++ unsigned i; ++ int r; ++ ++ if (ttm->state != tt_unpopulated) ++ return 0; ++ ++ dev_priv = nouveau_bdev(ttm->bdev); ++ dev = dev_priv->dev; ++ ++#if __OS_HAS_AGP ++ if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { ++ return ttm_agp_tt_populate(ttm); ++ } ++#endif ++ ++#ifdef CONFIG_SWIOTLB ++ if (swiotlb_nr_tbl()) { ++ return ttm_dma_populate((void *)ttm, dev->dev); ++ } ++#endif ++ ++ r = ttm_pool_populate(ttm); ++ if (r) { ++ return r; ++ } ++ ++ for (i = 0; i < ttm->num_pages; i++) { ++ ttm_dma->dma_address[i] = pci_map_page(dev->pdev, ttm->pages[i], ++ 0, PAGE_SIZE, ++ PCI_DMA_BIDIRECTIONAL); ++ if (pci_dma_mapping_error(dev->pdev, ttm_dma->dma_address[i])) { ++ while (--i) { ++ pci_unmap_page(dev->pdev, ttm_dma->dma_address[i], ++ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); ++ ttm_dma->dma_address[i] = 0; ++ } ++ ttm_pool_unpopulate(ttm); ++ return -EFAULT; ++ } ++ } ++ return 0; ++} ++ ++static void ++nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) ++{ ++ struct ttm_dma_tt *ttm_dma = (void *)ttm; ++ struct drm_nouveau_private *dev_priv; ++ struct drm_device *dev; ++ unsigned i; ++ ++ dev_priv = nouveau_bdev(ttm->bdev); ++ dev = dev_priv->dev; ++ ++#if __OS_HAS_AGP ++ if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { ++ ttm_agp_tt_unpopulate(ttm); ++ return; ++ } ++#endif ++ ++#ifdef CONFIG_SWIOTLB ++ if (swiotlb_nr_tbl()) { ++ ttm_dma_unpopulate((void *)ttm, dev->dev); ++ return; ++ } ++#endif ++ ++ for (i = 0; i < ttm->num_pages; i++) { ++ if (ttm_dma->dma_address[i]) { ++ pci_unmap_page(dev->pdev, ttm_dma->dma_address[i], ++ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); ++ } ++ } ++ ++ ttm_pool_unpopulate(ttm); ++} ++ + struct ttm_bo_driver nouveau_bo_driver = { +- .create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry, ++ .ttm_tt_create = &nouveau_ttm_tt_create, ++ .ttm_tt_populate = &nouveau_ttm_tt_populate, ++ .ttm_tt_unpopulate = &nouveau_ttm_tt_unpopulate, + .invalidate_caches = nouveau_bo_invalidate_caches, + .init_mem_type = nouveau_bo_init_mem_type, + .evict_flags = nouveau_bo_evict_flags, +@@ -1091,7 +1183,7 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm, + nouveau_vm_map(vma, nvbo->bo.mem.mm_node); + else + if (nvbo->bo.mem.mem_type == TTM_PL_TT) +- nouveau_vm_map_sg(vma, 0, size, node, node->pages); ++ nouveau_vm_map_sg(vma, 0, size, node); + + list_add_tail(&vma->head, &nvbo->vma_list); + vma->refcount = 1; +diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c +index bb6ec9e..846afb0 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_channel.c ++++ b/drivers/gpu/drm/nouveau/nouveau_channel.c +@@ -122,7 +122,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, + struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); + struct nouveau_channel *chan; + unsigned long flags; +- int ret; ++ int ret, i; + + /* allocate and lock channel structure */ + chan = kzalloc(sizeof(*chan), GFP_KERNEL); +@@ -184,9 +184,11 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, + return ret; + } + +- nouveau_dma_pre_init(chan); ++ nouveau_dma_init(chan); + chan->user_put = 0x40; + chan->user_get = 0x44; ++ if (dev_priv->card_type >= NV_50) ++ chan->user_get_hi = 0x60; + + /* disable the fifo caches */ + pfifo->reassign(dev, false); +@@ -200,9 +202,18 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, + + pfifo->reassign(dev, true); + +- ret = nouveau_dma_init(chan); +- if (!ret) +- ret = nouveau_fence_channel_init(chan); ++ /* Insert NOPs for NOUVEAU_DMA_SKIPS */ ++ ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); ++ if (ret) { ++ nouveau_channel_put(&chan); ++ return ret; ++ } ++ ++ for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) ++ OUT_RING (chan, 0x00000000); ++ FIRE_RING(chan); ++ ++ ret = nouveau_fence_channel_init(chan); + if (ret) { + nouveau_channel_put(&chan); + return ret; +@@ -425,18 +436,11 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, + } + + if (dev_priv->card_type < NV_C0) { +- init->subchan[0].handle = NvM2MF; +- if (dev_priv->card_type < NV_50) +- init->subchan[0].grclass = 0x0039; +- else +- init->subchan[0].grclass = 0x5039; ++ init->subchan[0].handle = 0x00000000; ++ init->subchan[0].grclass = 0x0000; + init->subchan[1].handle = NvSw; + init->subchan[1].grclass = NV_SW; + init->nr_subchan = 2; +- } else { +- init->subchan[0].handle = 0x9039; +- init->subchan[0].grclass = 0x9039; +- init->nr_subchan = 1; + } + + /* Named memory object area */ +diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c +index 1e72db5..7b11edb 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_connector.c ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c +@@ -35,6 +35,7 @@ + #include "nouveau_encoder.h" + #include "nouveau_crtc.h" + #include "nouveau_connector.h" ++#include "nouveau_gpio.h" + #include "nouveau_hw.h" + + static void nouveau_connector_hotplug(void *, int); +@@ -78,29 +79,11 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder) + return NULL; + } + +-/*TODO: This could use improvement, and learn to handle the fixed +- * BIOS tables etc. It's fine currently, for its only user. +- */ +-int +-nouveau_connector_bpp(struct drm_connector *connector) +-{ +- struct nouveau_connector *nv_connector = nouveau_connector(connector); +- +- if (nv_connector->edid && nv_connector->edid->revision >= 4) { +- u8 bpc = ((nv_connector->edid->input & 0x70) >> 3) + 4; +- if (bpc > 4) +- return bpc; +- } +- +- return 18; +-} +- + static void + nouveau_connector_destroy(struct drm_connector *connector) + { + struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct drm_nouveau_private *dev_priv; +- struct nouveau_gpio_engine *pgpio; + struct drm_device *dev; + + if (!nv_connector) +@@ -110,10 +93,9 @@ nouveau_connector_destroy(struct drm_connector *connector) + dev_priv = dev->dev_private; + NV_DEBUG_KMS(dev, "\n"); + +- pgpio = &dev_priv->engine.gpio; +- if (pgpio->irq_unregister) { +- pgpio->irq_unregister(dev, nv_connector->dcb->gpio_tag, +- nouveau_connector_hotplug, connector); ++ if (nv_connector->hpd != DCB_GPIO_UNUSED) { ++ nouveau_gpio_isr_del(dev, 0, nv_connector->hpd, 0xff, ++ nouveau_connector_hotplug, connector); + } + + kfree(nv_connector->edid); +@@ -198,6 +180,10 @@ nouveau_connector_set_encoder(struct drm_connector *connector, + return; + nv_connector->detected_encoder = nv_encoder; + ++ if (dev_priv->card_type >= NV_50) { ++ connector->interlace_allowed = true; ++ connector->doublescan_allowed = true; ++ } else + if (nv_encoder->dcb->type == OUTPUT_LVDS || + nv_encoder->dcb->type == OUTPUT_TMDS) { + connector->doublescan_allowed = false; +@@ -214,7 +200,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector, + connector->interlace_allowed = true; + } + +- if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) { ++ if (nv_connector->type == DCB_CONNECTOR_DVI_I) { + drm_connector_property_set_value(connector, + dev->mode_config.dvi_i_subconnector_property, + nv_encoder->dcb->type == OUTPUT_TMDS ? +@@ -397,7 +383,7 @@ nouveau_connector_force(struct drm_connector *connector) + struct nouveau_encoder *nv_encoder; + int type; + +- if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) { ++ if (nv_connector->type == DCB_CONNECTOR_DVI_I) { + if (connector->force == DRM_FORCE_ON_DIGITAL) + type = OUTPUT_TMDS; + else +@@ -420,15 +406,21 @@ static int + nouveau_connector_set_property(struct drm_connector *connector, + struct drm_property *property, uint64_t value) + { ++ struct drm_nouveau_private *dev_priv = connector->dev->dev_private; ++ struct nouveau_display_engine *disp = &dev_priv->engine.display; + struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; + struct drm_encoder *encoder = to_drm_encoder(nv_encoder); + struct drm_device *dev = connector->dev; ++ struct nouveau_crtc *nv_crtc; + int ret; + ++ nv_crtc = NULL; ++ if (connector->encoder && connector->encoder->crtc) ++ nv_crtc = nouveau_crtc(connector->encoder->crtc); ++ + /* Scaling mode */ + if (property == dev->mode_config.scaling_mode_property) { +- struct nouveau_crtc *nv_crtc = NULL; + bool modeset = false; + + switch (value) { +@@ -454,8 +446,6 @@ nouveau_connector_set_property(struct drm_connector *connector, + modeset = true; + nv_connector->scaling_mode = value; + +- if (connector->encoder && connector->encoder->crtc) +- nv_crtc = nouveau_crtc(connector->encoder->crtc); + if (!nv_crtc) + return 0; + +@@ -467,7 +457,7 @@ nouveau_connector_set_property(struct drm_connector *connector, + if (!ret) + return -EINVAL; + } else { +- ret = nv_crtc->set_scale(nv_crtc, value, true); ++ ret = nv_crtc->set_scale(nv_crtc, true); + if (ret) + return ret; + } +@@ -475,23 +465,71 @@ nouveau_connector_set_property(struct drm_connector *connector, + return 0; + } + +- /* Dithering */ +- if (property == dev->mode_config.dithering_mode_property) { +- struct nouveau_crtc *nv_crtc = NULL; ++ /* Underscan */ ++ if (property == disp->underscan_property) { ++ if (nv_connector->underscan != value) { ++ nv_connector->underscan = value; ++ if (!nv_crtc || !nv_crtc->set_scale) ++ return 0; + +- if (value == DRM_MODE_DITHERING_ON) +- nv_connector->use_dithering = true; +- else +- nv_connector->use_dithering = false; ++ return nv_crtc->set_scale(nv_crtc, true); ++ } ++ ++ return 0; ++ } ++ ++ if (property == disp->underscan_hborder_property) { ++ if (nv_connector->underscan_hborder != value) { ++ nv_connector->underscan_hborder = value; ++ if (!nv_crtc || !nv_crtc->set_scale) ++ return 0; ++ ++ return nv_crtc->set_scale(nv_crtc, true); ++ } ++ ++ return 0; ++ } ++ ++ if (property == disp->underscan_vborder_property) { ++ if (nv_connector->underscan_vborder != value) { ++ nv_connector->underscan_vborder = value; ++ if (!nv_crtc || !nv_crtc->set_scale) ++ return 0; ++ ++ return nv_crtc->set_scale(nv_crtc, true); ++ } ++ ++ return 0; ++ } + +- if (connector->encoder && connector->encoder->crtc) +- nv_crtc = nouveau_crtc(connector->encoder->crtc); ++ /* Dithering */ ++ if (property == disp->dithering_mode) { ++ nv_connector->dithering_mode = value; ++ if (!nv_crtc || !nv_crtc->set_dither) ++ return 0; ++ ++ return nv_crtc->set_dither(nv_crtc, true); ++ } + ++ if (property == disp->dithering_depth) { ++ nv_connector->dithering_depth = value; + if (!nv_crtc || !nv_crtc->set_dither) + return 0; + +- return nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, +- true); ++ return nv_crtc->set_dither(nv_crtc, true); ++ } ++ ++ if (nv_crtc && nv_crtc->set_color_vibrance) { ++ /* Hue */ ++ if (property == disp->vibrant_hue_property) { ++ nv_crtc->vibrant_hue = value - 90; ++ return nv_crtc->set_color_vibrance(nv_crtc, true); ++ } ++ /* Saturation */ ++ if (property == disp->color_vibrance_property) { ++ nv_crtc->color_vibrance = value - 100; ++ return nv_crtc->set_color_vibrance(nv_crtc, true); ++ } + } + + if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV) +@@ -617,7 +655,7 @@ nouveau_connector_detect_depth(struct drm_connector *connector) + return; + + /* EDID 1.4 is *supposed* to be supported on eDP, but, Apple... */ +- if (nv_connector->dcb->type == DCB_CONNECTOR_eDP) { ++ if (nv_connector->type == DCB_CONNECTOR_eDP) { + connector->display_info.bpc = 6; + return; + } +@@ -641,7 +679,7 @@ nouveau_connector_detect_depth(struct drm_connector *connector) + * know which if_is_24bit flag to check... + */ + if (nv_connector->edid && +- nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) ++ nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) + duallink = ((u8 *)nv_connector->edid)[121] == 2; + else + duallink = mode->clock >= bios->fp.duallink_transition_clk; +@@ -680,6 +718,12 @@ nouveau_connector_get_modes(struct drm_connector *connector) + nv_connector->native_mode = drm_mode_duplicate(dev, &mode); + } + ++ /* Determine display colour depth for everything except LVDS now, ++ * DP requires this before mode_valid() is called. ++ */ ++ if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) ++ nouveau_connector_detect_depth(connector); ++ + /* Find the native mode if this is a digital panel, if we didn't + * find any modes through DDC previously add the native mode to + * the list of modes. +@@ -695,18 +739,19 @@ nouveau_connector_get_modes(struct drm_connector *connector) + ret = 1; + } + +- /* Attempt to determine display colour depth, this has to happen after +- * we've determined the "native" mode for LVDS, as the VBIOS tables +- * require us to compare against a pixel clock in some cases.. ++ /* Determine LVDS colour depth, must happen after determining ++ * "native" mode as some VBIOS tables require us to use the ++ * pixel clock as part of the lookup... + */ +- nouveau_connector_detect_depth(connector); ++ if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ++ nouveau_connector_detect_depth(connector); + + if (nv_encoder->dcb->type == OUTPUT_TV) + ret = get_slave_funcs(encoder)->get_modes(encoder, connector); + +- if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || +- nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG || +- nv_connector->dcb->type == DCB_CONNECTOR_eDP) ++ if (nv_connector->type == DCB_CONNECTOR_LVDS || ++ nv_connector->type == DCB_CONNECTOR_LVDS_SPWG || ++ nv_connector->type == DCB_CONNECTOR_eDP) + ret += nouveau_connector_scaler_modes_add(connector); + + return ret; +@@ -765,7 +810,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, + case OUTPUT_DP: + max_clock = nv_encoder->dp.link_nr; + max_clock *= nv_encoder->dp.link_bw; +- clock = clock * nouveau_connector_bpp(connector) / 10; ++ clock = clock * (connector->display_info.bpc * 3) / 10; + break; + default: + BUG_ON(1); +@@ -823,96 +868,188 @@ nouveau_connector_funcs_lvds = { + .force = nouveau_connector_force + }; + ++static int ++drm_conntype_from_dcb(enum dcb_connector_type dcb) ++{ ++ switch (dcb) { ++ case DCB_CONNECTOR_VGA : return DRM_MODE_CONNECTOR_VGA; ++ case DCB_CONNECTOR_TV_0 : ++ case DCB_CONNECTOR_TV_1 : ++ case DCB_CONNECTOR_TV_3 : return DRM_MODE_CONNECTOR_TV; ++ case DCB_CONNECTOR_DMS59_0 : ++ case DCB_CONNECTOR_DMS59_1 : ++ case DCB_CONNECTOR_DVI_I : return DRM_MODE_CONNECTOR_DVII; ++ case DCB_CONNECTOR_DVI_D : return DRM_MODE_CONNECTOR_DVID; ++ case DCB_CONNECTOR_LVDS : ++ case DCB_CONNECTOR_LVDS_SPWG: return DRM_MODE_CONNECTOR_LVDS; ++ case DCB_CONNECTOR_DMS59_DP0: ++ case DCB_CONNECTOR_DMS59_DP1: ++ case DCB_CONNECTOR_DP : return DRM_MODE_CONNECTOR_DisplayPort; ++ case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP; ++ case DCB_CONNECTOR_HDMI_0 : ++ case DCB_CONNECTOR_HDMI_1 : return DRM_MODE_CONNECTOR_HDMIA; ++ default: ++ break; ++ } ++ ++ return DRM_MODE_CONNECTOR_Unknown; ++} ++ + struct drm_connector * + nouveau_connector_create(struct drm_device *dev, int index) + { + const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ struct nouveau_display_engine *disp = &dev_priv->engine.display; + struct nouveau_connector *nv_connector = NULL; +- struct dcb_connector_table_entry *dcb = NULL; + struct drm_connector *connector; + int type, ret = 0; ++ bool dummy; + + NV_DEBUG_KMS(dev, "\n"); + +- if (index >= dev_priv->vbios.dcb.connector.entries) +- return ERR_PTR(-EINVAL); +- +- dcb = &dev_priv->vbios.dcb.connector.entry[index]; +- if (dcb->drm) +- return dcb->drm; +- +- switch (dcb->type) { +- case DCB_CONNECTOR_VGA: +- type = DRM_MODE_CONNECTOR_VGA; +- break; +- case DCB_CONNECTOR_TV_0: +- case DCB_CONNECTOR_TV_1: +- case DCB_CONNECTOR_TV_3: +- type = DRM_MODE_CONNECTOR_TV; +- break; +- case DCB_CONNECTOR_DVI_I: +- type = DRM_MODE_CONNECTOR_DVII; +- break; +- case DCB_CONNECTOR_DVI_D: +- type = DRM_MODE_CONNECTOR_DVID; +- break; +- case DCB_CONNECTOR_HDMI_0: +- case DCB_CONNECTOR_HDMI_1: +- type = DRM_MODE_CONNECTOR_HDMIA; +- break; +- case DCB_CONNECTOR_LVDS: +- case DCB_CONNECTOR_LVDS_SPWG: +- type = DRM_MODE_CONNECTOR_LVDS; +- funcs = &nouveau_connector_funcs_lvds; +- break; +- case DCB_CONNECTOR_DP: +- type = DRM_MODE_CONNECTOR_DisplayPort; +- break; +- case DCB_CONNECTOR_eDP: +- type = DRM_MODE_CONNECTOR_eDP; +- break; +- default: +- NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type); +- return ERR_PTR(-EINVAL); ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ nv_connector = nouveau_connector(connector); ++ if (nv_connector->index == index) ++ return connector; + } + + nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); + if (!nv_connector) + return ERR_PTR(-ENOMEM); +- nv_connector->dcb = dcb; ++ + connector = &nv_connector->base; ++ nv_connector->index = index; ++ ++ /* attempt to parse vbios connector type and hotplug gpio */ ++ nv_connector->dcb = dcb_conn(dev, index); ++ if (nv_connector->dcb) { ++ static const u8 hpd[16] = { ++ 0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x60, ++ }; ++ ++ u32 entry = ROM16(nv_connector->dcb[0]); ++ if (dcb_conntab(dev)[3] >= 4) ++ entry |= (u32)ROM16(nv_connector->dcb[2]) << 16; ++ ++ nv_connector->hpd = ffs((entry & 0x07033000) >> 12); ++ nv_connector->hpd = hpd[nv_connector->hpd]; ++ ++ nv_connector->type = nv_connector->dcb[0]; ++ if (drm_conntype_from_dcb(nv_connector->type) == ++ DRM_MODE_CONNECTOR_Unknown) { ++ NV_WARN(dev, "unknown connector type %02x\n", ++ nv_connector->type); ++ nv_connector->type = DCB_CONNECTOR_NONE; ++ } + +- /* defaults, will get overridden in detect() */ +- connector->interlace_allowed = false; +- connector->doublescan_allowed = false; ++ /* Gigabyte NX85T */ ++ if (nv_match_device(dev, 0x0421, 0x1458, 0x344c)) { ++ if (nv_connector->type == DCB_CONNECTOR_HDMI_1) ++ nv_connector->type = DCB_CONNECTOR_DVI_I; ++ } + +- drm_connector_init(dev, connector, funcs, type); +- drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); ++ /* Gigabyte GV-NX86T512H */ ++ if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) { ++ if (nv_connector->type == DCB_CONNECTOR_HDMI_1) ++ nv_connector->type = DCB_CONNECTOR_DVI_I; ++ } ++ } else { ++ nv_connector->type = DCB_CONNECTOR_NONE; ++ nv_connector->hpd = DCB_GPIO_UNUSED; ++ } ++ ++ /* no vbios data, or an unknown dcb connector type - attempt to ++ * figure out something suitable ourselves ++ */ ++ if (nv_connector->type == DCB_CONNECTOR_NONE) { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct dcb_table *dcbt = &dev_priv->vbios.dcb; ++ u32 encoders = 0; ++ int i; ++ ++ for (i = 0; i < dcbt->entries; i++) { ++ if (dcbt->entry[i].connector == nv_connector->index) ++ encoders |= (1 << dcbt->entry[i].type); ++ } + +- /* Check if we need dithering enabled */ +- if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { +- bool dummy, is_24bit = false; ++ if (encoders & (1 << OUTPUT_DP)) { ++ if (encoders & (1 << OUTPUT_TMDS)) ++ nv_connector->type = DCB_CONNECTOR_DP; ++ else ++ nv_connector->type = DCB_CONNECTOR_eDP; ++ } else ++ if (encoders & (1 << OUTPUT_TMDS)) { ++ if (encoders & (1 << OUTPUT_ANALOG)) ++ nv_connector->type = DCB_CONNECTOR_DVI_I; ++ else ++ nv_connector->type = DCB_CONNECTOR_DVI_D; ++ } else ++ if (encoders & (1 << OUTPUT_ANALOG)) { ++ nv_connector->type = DCB_CONNECTOR_VGA; ++ } else ++ if (encoders & (1 << OUTPUT_LVDS)) { ++ nv_connector->type = DCB_CONNECTOR_LVDS; ++ } else ++ if (encoders & (1 << OUTPUT_TV)) { ++ nv_connector->type = DCB_CONNECTOR_TV_0; ++ } ++ } + +- ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &is_24bit); ++ type = drm_conntype_from_dcb(nv_connector->type); ++ if (type == DRM_MODE_CONNECTOR_LVDS) { ++ ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &dummy); + if (ret) { +- NV_ERROR(dev, "Error parsing LVDS table, disabling " +- "LVDS\n"); +- goto fail; ++ NV_ERROR(dev, "Error parsing LVDS table, disabling\n"); ++ kfree(nv_connector); ++ return ERR_PTR(ret); + } + +- nv_connector->use_dithering = !is_24bit; ++ funcs = &nouveau_connector_funcs_lvds; ++ } else { ++ funcs = &nouveau_connector_funcs; + } + ++ /* defaults, will get overridden in detect() */ ++ connector->interlace_allowed = false; ++ connector->doublescan_allowed = false; ++ ++ drm_connector_init(dev, connector, funcs, type); ++ drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); ++ + /* Init DVI-I specific properties */ +- if (dcb->type == DCB_CONNECTOR_DVI_I) { +- drm_mode_create_dvi_i_properties(dev); ++ if (nv_connector->type == DCB_CONNECTOR_DVI_I) + drm_connector_attach_property(connector, dev->mode_config.dvi_i_subconnector_property, 0); +- drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0); ++ ++ /* Add overscan compensation options to digital outputs */ ++ if (disp->underscan_property && ++ (type == DRM_MODE_CONNECTOR_DVID || ++ type == DRM_MODE_CONNECTOR_DVII || ++ type == DRM_MODE_CONNECTOR_HDMIA || ++ type == DRM_MODE_CONNECTOR_DisplayPort)) { ++ drm_connector_attach_property(connector, ++ disp->underscan_property, ++ UNDERSCAN_OFF); ++ drm_connector_attach_property(connector, ++ disp->underscan_hborder_property, ++ 0); ++ drm_connector_attach_property(connector, ++ disp->underscan_vborder_property, ++ 0); + } + +- switch (dcb->type) { ++ /* Add hue and saturation options */ ++ if (disp->vibrant_hue_property) ++ drm_connector_attach_property(connector, ++ disp->vibrant_hue_property, ++ 90); ++ if (disp->color_vibrance_property) ++ drm_connector_attach_property(connector, ++ disp->color_vibrance_property, ++ 150); ++ ++ switch (nv_connector->type) { + case DCB_CONNECTOR_VGA: + if (dev_priv->card_type >= NV_50) { + drm_connector_attach_property(connector, +@@ -931,32 +1068,32 @@ nouveau_connector_create(struct drm_device *dev, int index) + drm_connector_attach_property(connector, + dev->mode_config.scaling_mode_property, + nv_connector->scaling_mode); +- drm_connector_attach_property(connector, +- dev->mode_config.dithering_mode_property, +- nv_connector->use_dithering ? +- DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); ++ if (disp->dithering_mode) { ++ nv_connector->dithering_mode = DITHERING_MODE_AUTO; ++ drm_connector_attach_property(connector, ++ disp->dithering_mode, ++ nv_connector->dithering_mode); ++ } ++ if (disp->dithering_depth) { ++ nv_connector->dithering_depth = DITHERING_DEPTH_AUTO; ++ drm_connector_attach_property(connector, ++ disp->dithering_depth, ++ nv_connector->dithering_depth); ++ } + break; + } + +- if (nv_connector->dcb->gpio_tag != 0xff && pgpio->irq_register) { +- pgpio->irq_register(dev, nv_connector->dcb->gpio_tag, +- nouveau_connector_hotplug, connector); +- +- connector->polled = DRM_CONNECTOR_POLL_HPD; +- } else { +- connector->polled = DRM_CONNECTOR_POLL_CONNECT; ++ connector->polled = DRM_CONNECTOR_POLL_CONNECT; ++ if (nv_connector->hpd != DCB_GPIO_UNUSED) { ++ ret = nouveau_gpio_isr_add(dev, 0, nv_connector->hpd, 0xff, ++ nouveau_connector_hotplug, ++ connector); ++ if (ret == 0) ++ connector->polled = DRM_CONNECTOR_POLL_HPD; + } + + drm_sysfs_connector_add(connector); +- +- dcb->drm = connector; +- return dcb->drm; +- +-fail: +- drm_connector_cleanup(connector); +- kfree(connector); +- return ERR_PTR(ret); +- ++ return connector; + } + + static void +diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h +index 711b1e9..e485702 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_connector.h ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.h +@@ -30,13 +30,43 @@ + #include "drm_edid.h" + #include "nouveau_i2c.h" + ++enum nouveau_underscan_type { ++ UNDERSCAN_OFF, ++ UNDERSCAN_ON, ++ UNDERSCAN_AUTO, ++}; ++ ++/* the enum values specifically defined here match nv50/nvd0 hw values, and ++ * the code relies on this ++ */ ++enum nouveau_dithering_mode { ++ DITHERING_MODE_OFF = 0x00, ++ DITHERING_MODE_ON = 0x01, ++ DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON, ++ DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON, ++ DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON, ++ DITHERING_MODE_AUTO ++}; ++ ++enum nouveau_dithering_depth { ++ DITHERING_DEPTH_6BPC = 0x00, ++ DITHERING_DEPTH_8BPC = 0x02, ++ DITHERING_DEPTH_AUTO ++}; ++ + struct nouveau_connector { + struct drm_connector base; ++ enum dcb_connector_type type; ++ u8 index; ++ u8 *dcb; ++ u8 hpd; + +- struct dcb_connector_table_entry *dcb; +- ++ int dithering_mode; ++ int dithering_depth; + int scaling_mode; +- bool use_dithering; ++ enum nouveau_underscan_type underscan; ++ u32 underscan_hborder; ++ u32 underscan_vborder; + + struct nouveau_encoder *detected_encoder; + struct edid *edid; +diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h +index bf8e128..e6d0d1e 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h ++++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h +@@ -32,11 +32,11 @@ struct nouveau_crtc { + + int index; + +- struct drm_display_mode *mode; +- + uint32_t dpms_saved_fp_control; + uint32_t fp_users; + int saturation; ++ int color_vibrance; ++ int vibrant_hue; + int sharpness; + int last_dpms; + +@@ -67,8 +67,9 @@ struct nouveau_crtc { + int depth; + } lut; + +- int (*set_dither)(struct nouveau_crtc *crtc, bool on, bool update); +- int (*set_scale)(struct nouveau_crtc *crtc, int mode, bool update); ++ int (*set_dither)(struct nouveau_crtc *crtc, bool update); ++ int (*set_scale)(struct nouveau_crtc *crtc, bool update); ++ int (*set_color_vibrance)(struct nouveau_crtc *crtc, bool update); + }; + + static inline struct nouveau_crtc *nouveau_crtc(struct drm_crtc *crtc) +diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c +index 8e15923..fa2ec49 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c ++++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c +@@ -44,7 +44,7 @@ nouveau_debugfs_channel_info(struct seq_file *m, void *data) + seq_printf(m, "channel id : %d\n", chan->id); + + seq_printf(m, "cpu fifo state:\n"); +- seq_printf(m, " base: 0x%08x\n", chan->pushbuf_base); ++ seq_printf(m, " base: 0x%10llx\n", chan->pushbuf_base); + seq_printf(m, " max: 0x%08x\n", chan->dma.max << 2); + seq_printf(m, " cur: 0x%08x\n", chan->dma.cur << 2); + seq_printf(m, " put: 0x%08x\n", chan->dma.put << 2); +@@ -178,6 +178,7 @@ static struct drm_info_list nouveau_debugfs_list[] = { + { "memory", nouveau_debugfs_memory_info, 0, NULL }, + { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL }, + { "ttm_page_pool", ttm_page_alloc_debugfs, 0, NULL }, ++ { "ttm_dma_page_pool", ttm_dma_page_alloc_debugfs, 0, NULL }, + }; + #define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list) + +diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c +index 6adef06..f233b8f 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_display.c ++++ b/drivers/gpu/drm/nouveau/nouveau_display.c +@@ -32,6 +32,8 @@ + #include "nouveau_hw.h" + #include "nouveau_crtc.h" + #include "nouveau_dma.h" ++#include "nouveau_connector.h" ++#include "nouveau_gpio.h" + #include "nv50_display.h" + + static void +@@ -64,7 +66,7 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = { + int + nouveau_framebuffer_init(struct drm_device *dev, + struct nouveau_framebuffer *nv_fb, +- struct drm_mode_fb_cmd *mode_cmd, ++ struct drm_mode_fb_cmd2 *mode_cmd, + struct nouveau_bo *nvbo) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -107,14 +109,14 @@ nouveau_framebuffer_init(struct drm_device *dev, + + if (!tile_flags) { + if (dev_priv->card_type < NV_D0) +- nv_fb->r_pitch = 0x00100000 | fb->pitch; ++ nv_fb->r_pitch = 0x00100000 | fb->pitches[0]; + else +- nv_fb->r_pitch = 0x01000000 | fb->pitch; ++ nv_fb->r_pitch = 0x01000000 | fb->pitches[0]; + } else { + u32 mode = nvbo->tile_mode; + if (dev_priv->card_type >= NV_C0) + mode >>= 4; +- nv_fb->r_pitch = ((fb->pitch / 4) << 4) | mode; ++ nv_fb->r_pitch = ((fb->pitches[0] / 4) << 4) | mode; + } + } + +@@ -124,13 +126,13 @@ nouveau_framebuffer_init(struct drm_device *dev, + static struct drm_framebuffer * + nouveau_user_framebuffer_create(struct drm_device *dev, + struct drm_file *file_priv, +- struct drm_mode_fb_cmd *mode_cmd) ++ struct drm_mode_fb_cmd2 *mode_cmd) + { + struct nouveau_framebuffer *nouveau_fb; + struct drm_gem_object *gem; + int ret; + +- gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); ++ gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); + if (!gem) + return ERR_PTR(-ENOENT); + +@@ -147,11 +149,207 @@ nouveau_user_framebuffer_create(struct drm_device *dev, + return &nouveau_fb->base; + } + +-const struct drm_mode_config_funcs nouveau_mode_config_funcs = { ++static const struct drm_mode_config_funcs nouveau_mode_config_funcs = { + .fb_create = nouveau_user_framebuffer_create, + .output_poll_changed = nouveau_fbcon_output_poll_changed, + }; + ++ ++struct nouveau_drm_prop_enum_list { ++ u8 gen_mask; ++ int type; ++ char *name; ++}; ++ ++static struct nouveau_drm_prop_enum_list underscan[] = { ++ { 6, UNDERSCAN_AUTO, "auto" }, ++ { 6, UNDERSCAN_OFF, "off" }, ++ { 6, UNDERSCAN_ON, "on" }, ++ {} ++}; ++ ++static struct nouveau_drm_prop_enum_list dither_mode[] = { ++ { 7, DITHERING_MODE_AUTO, "auto" }, ++ { 7, DITHERING_MODE_OFF, "off" }, ++ { 1, DITHERING_MODE_ON, "on" }, ++ { 6, DITHERING_MODE_STATIC2X2, "static 2x2" }, ++ { 6, DITHERING_MODE_DYNAMIC2X2, "dynamic 2x2" }, ++ { 4, DITHERING_MODE_TEMPORAL, "temporal" }, ++ {} ++}; ++ ++static struct nouveau_drm_prop_enum_list dither_depth[] = { ++ { 6, DITHERING_DEPTH_AUTO, "auto" }, ++ { 6, DITHERING_DEPTH_6BPC, "6 bpc" }, ++ { 6, DITHERING_DEPTH_8BPC, "8 bpc" }, ++ {} ++}; ++ ++#define PROP_ENUM(p,gen,n,list) do { \ ++ struct nouveau_drm_prop_enum_list *l = (list); \ ++ int c = 0; \ ++ while (l->gen_mask) { \ ++ if (l->gen_mask & (1 << (gen))) \ ++ c++; \ ++ l++; \ ++ } \ ++ if (c) { \ ++ p = drm_property_create(dev, DRM_MODE_PROP_ENUM, n, c); \ ++ l = (list); \ ++ c = 0; \ ++ while (p && l->gen_mask) { \ ++ if (l->gen_mask & (1 << (gen))) { \ ++ drm_property_add_enum(p, c, l->type, l->name); \ ++ c++; \ ++ } \ ++ l++; \ ++ } \ ++ } \ ++} while(0) ++ ++int ++nouveau_display_init(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_display_engine *disp = &dev_priv->engine.display; ++ struct drm_connector *connector; ++ int ret; ++ ++ ret = disp->init(dev); ++ if (ret) ++ return ret; ++ ++ /* power on internal panel if it's not already. the init tables of ++ * some vbios default this to off for some reason, causing the ++ * panel to not work after resume ++ */ ++ if (nouveau_gpio_func_get(dev, DCB_GPIO_PANEL_POWER) == 0) { ++ nouveau_gpio_func_set(dev, DCB_GPIO_PANEL_POWER, true); ++ msleep(300); ++ } ++ ++ /* enable polling for external displays */ ++ drm_kms_helper_poll_enable(dev); ++ ++ /* enable hotplug interrupts */ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ struct nouveau_connector *conn = nouveau_connector(connector); ++ nouveau_gpio_irq(dev, 0, conn->hpd, 0xff, true); ++ } ++ ++ return ret; ++} ++ ++void ++nouveau_display_fini(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_display_engine *disp = &dev_priv->engine.display; ++ struct drm_connector *connector; ++ ++ /* disable hotplug interrupts */ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ struct nouveau_connector *conn = nouveau_connector(connector); ++ nouveau_gpio_irq(dev, 0, conn->hpd, 0xff, false); ++ } ++ ++ drm_kms_helper_poll_disable(dev); ++ disp->fini(dev); ++} ++ ++int ++nouveau_display_create(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_display_engine *disp = &dev_priv->engine.display; ++ int ret, gen; ++ ++ drm_mode_config_init(dev); ++ drm_mode_create_scaling_mode_property(dev); ++ drm_mode_create_dvi_i_properties(dev); ++ ++ if (dev_priv->card_type < NV_50) ++ gen = 0; ++ else ++ if (dev_priv->card_type < NV_D0) ++ gen = 1; ++ else ++ gen = 2; ++ ++ PROP_ENUM(disp->dithering_mode, gen, "dithering mode", dither_mode); ++ PROP_ENUM(disp->dithering_depth, gen, "dithering depth", dither_depth); ++ PROP_ENUM(disp->underscan_property, gen, "underscan", underscan); ++ ++ disp->underscan_hborder_property = ++ drm_property_create_range(dev, 0, "underscan hborder", 0, 128); ++ ++ disp->underscan_vborder_property = ++ drm_property_create_range(dev, 0, "underscan vborder", 0, 128); ++ ++ if (gen == 1) { ++ disp->vibrant_hue_property = ++ drm_property_create(dev, DRM_MODE_PROP_RANGE, ++ "vibrant hue", 2); ++ disp->vibrant_hue_property->values[0] = 0; ++ disp->vibrant_hue_property->values[1] = 180; /* -90..+90 */ ++ ++ disp->color_vibrance_property = ++ drm_property_create(dev, DRM_MODE_PROP_RANGE, ++ "color vibrance", 2); ++ disp->color_vibrance_property->values[0] = 0; ++ disp->color_vibrance_property->values[1] = 200; /* -100..+100 */ ++ } ++ ++ dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; ++ dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); ++ ++ dev->mode_config.min_width = 0; ++ dev->mode_config.min_height = 0; ++ if (dev_priv->card_type < NV_10) { ++ dev->mode_config.max_width = 2048; ++ dev->mode_config.max_height = 2048; ++ } else ++ if (dev_priv->card_type < NV_50) { ++ dev->mode_config.max_width = 4096; ++ dev->mode_config.max_height = 4096; ++ } else { ++ dev->mode_config.max_width = 8192; ++ dev->mode_config.max_height = 8192; ++ } ++ ++ dev->mode_config.preferred_depth = 24; ++ dev->mode_config.prefer_shadow = 1; ++ ++ drm_kms_helper_poll_init(dev); ++ drm_kms_helper_poll_disable(dev); ++ ++ ret = disp->create(dev); ++ if (ret) ++ return ret; ++ ++ if (dev->mode_config.num_crtc) { ++ ret = drm_vblank_init(dev, dev->mode_config.num_crtc); ++ if (ret) ++ return ret; ++ } ++ ++ return ret; ++} ++ ++void ++nouveau_display_destroy(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_display_engine *disp = &dev_priv->engine.display; ++ ++ drm_vblank_cleanup(dev); ++ ++ disp->destroy(dev); ++ ++ drm_kms_helper_poll_fini(dev); ++ drm_mode_config_cleanup(dev); ++} ++ + int + nouveau_vblank_enable(struct drm_device *dev, int crtc) + { +@@ -243,15 +441,19 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, + goto fail; + + /* Emit the pageflip */ +- ret = RING_SPACE(chan, 2); ++ ret = RING_SPACE(chan, 3); + if (ret) + goto fail; + +- if (dev_priv->card_type < NV_C0) ++ if (dev_priv->card_type < NV_C0) { + BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); +- else +- BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0500, 1); +- OUT_RING (chan, 0); ++ OUT_RING (chan, 0x00000000); ++ OUT_RING (chan, 0x00000000); ++ } else { ++ BEGIN_NVC0(chan, 2, 0, NV10_SUBCHAN_REF_CNT, 1); ++ OUT_RING (chan, ++chan->fence.sequence); ++ BEGIN_NVC0(chan, 8, 0, NVSW_SUBCHAN_PAGE_FLIP, 0x0000); ++ } + FIRE_RING (chan); + + ret = nouveau_fence_new(chan, pfence, true); +@@ -294,7 +496,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, + /* Initialize a page flip struct */ + *s = (struct nouveau_page_flip_state) + { { }, event, nouveau_crtc(crtc)->index, +- fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y, ++ fb->bits_per_pixel, fb->pitches[0], crtc->x, crtc->y, + new_bo->bo.offset }; + + /* Choose the channel the flip will be handled in */ +@@ -305,7 +507,10 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, + + /* Emit a page flip */ + if (dev_priv->card_type >= NV_50) { +- ret = nv50_display_flip_next(crtc, fb, chan); ++ if (dev_priv->card_type >= NV_D0) ++ ret = nvd0_display_flip_next(crtc, fb, chan, 0); ++ else ++ ret = nv50_display_flip_next(crtc, fb, chan); + if (ret) { + nouveau_channel_put(&chan); + goto fail_unreserve; +diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c +index 00bc6ea..295932e 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_dma.c ++++ b/drivers/gpu/drm/nouveau/nouveau_dma.c +@@ -31,7 +31,7 @@ + #include "nouveau_ramht.h" + + void +-nouveau_dma_pre_init(struct nouveau_channel *chan) ++nouveau_dma_init(struct nouveau_channel *chan) + { + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nouveau_bo *pushbuf = chan->pushbuf_bo; +@@ -54,65 +54,6 @@ nouveau_dma_pre_init(struct nouveau_channel *chan) + chan->dma.free = chan->dma.max - chan->dma.cur; + } + +-int +-nouveau_dma_init(struct nouveau_channel *chan) +-{ +- struct drm_device *dev = chan->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- int ret, i; +- +- if (dev_priv->card_type >= NV_C0) { +- ret = nouveau_gpuobj_gr_new(chan, 0x9039, 0x9039); +- if (ret) +- return ret; +- +- ret = RING_SPACE(chan, 2); +- if (ret) +- return ret; +- +- BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0000, 1); +- OUT_RING (chan, 0x00009039); +- FIRE_RING (chan); +- return 0; +- } +- +- /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ +- ret = nouveau_gpuobj_gr_new(chan, NvM2MF, dev_priv->card_type < NV_50 ? +- 0x0039 : 0x5039); +- if (ret) +- return ret; +- +- /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */ +- ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfe0, 0x1000, +- &chan->m2mf_ntfy); +- if (ret) +- return ret; +- +- /* Insert NOPS for NOUVEAU_DMA_SKIPS */ +- ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); +- if (ret) +- return ret; +- +- for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) +- OUT_RING(chan, 0); +- +- /* Initialise NV_MEMORY_TO_MEMORY_FORMAT */ +- ret = RING_SPACE(chan, 6); +- if (ret) +- return ret; +- BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1); +- OUT_RING (chan, NvM2MF); +- BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3); +- OUT_RING (chan, NvNotify0); +- OUT_RING (chan, chan->vram_handle); +- OUT_RING (chan, chan->gart_handle); +- +- /* Sit back and pray the channel works.. */ +- FIRE_RING(chan); +- +- return 0; +-} +- + void + OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords) + { +@@ -134,11 +75,13 @@ OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords) + * -EBUSY if timeout exceeded + */ + static inline int +-READ_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout) ++READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout) + { +- uint32_t val; ++ uint64_t val; + + val = nvchan_rd32(chan, chan->user_get); ++ if (chan->user_get_hi) ++ val |= (uint64_t)nvchan_rd32(chan, chan->user_get_hi) << 32; + + /* reset counter as long as GET is still advancing, this is + * to avoid misdetecting a GPU lockup if the GPU happens to +@@ -218,8 +161,8 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count) + static int + nv50_dma_wait(struct nouveau_channel *chan, int slots, int count) + { +- uint32_t cnt = 0, prev_get = 0; +- int ret; ++ uint64_t prev_get = 0; ++ int ret, cnt = 0; + + ret = nv50_dma_push_wait(chan, slots + 1); + if (unlikely(ret)) +@@ -261,8 +204,8 @@ nv50_dma_wait(struct nouveau_channel *chan, int slots, int count) + int + nouveau_dma_wait(struct nouveau_channel *chan, int slots, int size) + { +- uint32_t prev_get = 0, cnt = 0; +- int get; ++ uint64_t prev_get = 0; ++ int cnt = 0, get; + + if (chan->dma.ib_max) + return nv50_dma_wait(chan, slots, size); +diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c +index de5efe7..d996134 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_dp.c ++++ b/drivers/gpu/drm/nouveau/nouveau_dp.c +@@ -29,6 +29,7 @@ + #include "nouveau_connector.h" + #include "nouveau_encoder.h" + #include "nouveau_crtc.h" ++#include "nouveau_gpio.h" + + /****************************************************************************** + * aux channel util functions +@@ -160,121 +161,9 @@ out: + return ret; + } + +-static u32 +-dp_link_bw_get(struct drm_device *dev, int or, int link) +-{ +- u32 ctrl = nv_rd32(dev, 0x614300 + (or * 0x800)); +- if (!(ctrl & 0x000c0000)) +- return 162000; +- return 270000; +-} +- +-static int +-dp_lane_count_get(struct drm_device *dev, int or, int link) +-{ +- u32 ctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); +- switch (ctrl & 0x000f0000) { +- case 0x00010000: return 1; +- case 0x00030000: return 2; +- default: +- return 4; +- } +-} +- +-void +-nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) +-{ +- const u32 symbol = 100000; +- int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; +- int TU, VTUi, VTUf, VTUa; +- u64 link_data_rate, link_ratio, unk; +- u32 best_diff = 64 * symbol; +- u32 link_nr, link_bw, r; +- +- /* calculate packed data rate for each lane */ +- link_nr = dp_lane_count_get(dev, or, link); +- link_data_rate = (clk * bpp / 8) / link_nr; +- +- /* calculate ratio of packed data rate to link symbol rate */ +- link_bw = dp_link_bw_get(dev, or, link); +- link_ratio = link_data_rate * symbol; +- r = do_div(link_ratio, link_bw); +- +- for (TU = 64; TU >= 32; TU--) { +- /* calculate average number of valid symbols in each TU */ +- u32 tu_valid = link_ratio * TU; +- u32 calc, diff; +- +- /* find a hw representation for the fraction.. */ +- VTUi = tu_valid / symbol; +- calc = VTUi * symbol; +- diff = tu_valid - calc; +- if (diff) { +- if (diff >= (symbol / 2)) { +- VTUf = symbol / (symbol - diff); +- if (symbol - (VTUf * diff)) +- VTUf++; +- +- if (VTUf <= 15) { +- VTUa = 1; +- calc += symbol - (symbol / VTUf); +- } else { +- VTUa = 0; +- VTUf = 1; +- calc += symbol; +- } +- } else { +- VTUa = 0; +- VTUf = min((int)(symbol / diff), 15); +- calc += symbol / VTUf; +- } +- +- diff = calc - tu_valid; +- } else { +- /* no remainder, but the hw doesn't like the fractional +- * part to be zero. decrement the integer part and +- * have the fraction add a whole symbol back +- */ +- VTUa = 0; +- VTUf = 1; +- VTUi--; +- } +- +- if (diff < best_diff) { +- best_diff = diff; +- bestTU = TU; +- bestVTUa = VTUa; +- bestVTUf = VTUf; +- bestVTUi = VTUi; +- if (diff == 0) +- break; +- } +- } +- +- if (!bestTU) { +- NV_ERROR(dev, "DP: unable to find suitable config\n"); +- return; +- } +- +- /* XXX close to vbios numbers, but not right */ +- unk = (symbol - link_ratio) * bestTU; +- unk *= link_ratio; +- r = do_div(unk, symbol); +- r = do_div(unk, symbol); +- unk += 6; +- +- nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); +- nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | +- bestVTUf << 16 | +- bestVTUi << 8 | +- unk); +-} +- + u8 * + nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nvbios *bios = &dev_priv->vbios; + struct bit_entry d; + u8 *table; + int i; +@@ -289,7 +178,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) + return NULL; + } + +- table = ROMPTR(bios, d.data[0]); ++ table = ROMPTR(dev, d.data[0]); + if (!table) { + NV_ERROR(dev, "displayport table pointer invalid\n"); + return NULL; +@@ -299,6 +188,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) + case 0x20: + case 0x21: + case 0x30: ++ case 0x40: + break; + default: + NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]); +@@ -306,7 +196,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) + } + + for (i = 0; i < table[3]; i++) { +- *entry = ROMPTR(bios, table[table[1] + (i * table[2])]); ++ *entry = ROMPTR(dev, table[table[1] + (i * table[2])]); + if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0]))) + return table; + } +@@ -319,13 +209,10 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) + * link training + *****************************************************************************/ + struct dp_state { ++ struct dp_train_func *func; + struct dcb_entry *dcb; +- u8 *table; +- u8 *entry; + int auxch; + int crtc; +- int or; +- int link; + u8 *dpcd; + int link_nr; + u32 link_bw; +@@ -336,143 +223,58 @@ struct dp_state { + static void + dp_set_link_config(struct drm_device *dev, struct dp_state *dp) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- int or = dp->or, link = dp->link; +- u8 *entry, sink[2]; +- u32 dp_ctrl; +- u16 script; ++ u8 sink[2]; + + NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); + +- /* set selected link rate on source */ +- switch (dp->link_bw) { +- case 270000: +- nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00040000); +- sink[0] = DP_LINK_BW_2_7; +- break; +- default: +- nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00000000); +- sink[0] = DP_LINK_BW_1_62; +- break; +- } +- +- /* offset +0x0a of each dp encoder table entry is a pointer to another +- * table, that has (among other things) pointers to more scripts that +- * need to be executed, this time depending on link speed. +- */ +- entry = ROMPTR(&dev_priv->vbios, dp->entry[10]); +- if (entry) { +- if (dp->table[0] < 0x30) { +- while (dp->link_bw < (ROM16(entry[0]) * 10)) +- entry += 4; +- script = ROM16(entry[2]); +- } else { +- while (dp->link_bw < (entry[0] * 27000)) +- entry += 3; +- script = ROM16(entry[1]); +- } +- +- nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); +- } ++ /* set desired link configuration on the source */ ++ dp->func->link_set(dev, dp->dcb, dp->crtc, dp->link_nr, dp->link_bw, ++ dp->dpcd[2] & DP_ENHANCED_FRAME_CAP); + +- /* configure lane count on the source */ +- dp_ctrl = ((1 << dp->link_nr) - 1) << 16; ++ /* inform the sink of the new configuration */ ++ sink[0] = dp->link_bw / 27000; + sink[1] = dp->link_nr; +- if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) { +- dp_ctrl |= 0x00004000; ++ if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) + sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; +- } +- +- nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x001f4000, dp_ctrl); + +- /* inform the sink of the new configuration */ + auxch_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2); + } + + static void +-dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 tp) ++dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern) + { + u8 sink_tp; + +- NV_DEBUG_KMS(dev, "training pattern %d\n", tp); ++ NV_DEBUG_KMS(dev, "training pattern %d\n", pattern); + +- nv_mask(dev, NV50_SOR_DP_CTRL(dp->or, dp->link), 0x0f000000, tp << 24); ++ dp->func->train_set(dev, dp->dcb, pattern); + + auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1); + sink_tp &= ~DP_TRAINING_PATTERN_MASK; +- sink_tp |= tp; ++ sink_tp |= pattern; + auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1); + } + +-static const u8 nv50_lane_map[] = { 16, 8, 0, 24 }; +-static const u8 nvaf_lane_map[] = { 24, 16, 8, 0 }; +- + static int + dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- u32 mask = 0, drv = 0, pre = 0, unk = 0; +- const u8 *shifts; +- int link = dp->link; +- int or = dp->or; + int i; + +- if (dev_priv->chipset != 0xaf) +- shifts = nv50_lane_map; +- else +- shifts = nvaf_lane_map; +- + for (i = 0; i < dp->link_nr; i++) { +- u8 *conf = dp->entry + dp->table[4]; + u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; + u8 lpre = (lane & 0x0c) >> 2; + u8 lvsw = (lane & 0x03) >> 0; + +- mask |= 0xff << shifts[i]; +- unk |= 1 << (shifts[i] >> 3); +- + dp->conf[i] = (lpre << 3) | lvsw; + if (lvsw == DP_TRAIN_VOLTAGE_SWING_1200) + dp->conf[i] |= DP_TRAIN_MAX_SWING_REACHED; +- if (lpre == DP_TRAIN_PRE_EMPHASIS_9_5) ++ if ((lpre << 3) == DP_TRAIN_PRE_EMPHASIS_9_5) + dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + + NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]); +- +- if (dp->table[0] < 0x30) { +- u8 *last = conf + (dp->entry[4] * dp->table[5]); +- while (lvsw != conf[0] || lpre != conf[1]) { +- conf += dp->table[5]; +- if (conf >= last) +- return -EINVAL; +- } +- +- conf += 2; +- } else { +- /* no lookup table anymore, set entries for each +- * combination of voltage swing and pre-emphasis +- * level allowed by the DP spec. +- */ +- switch (lvsw) { +- case 0: lpre += 0; break; +- case 1: lpre += 4; break; +- case 2: lpre += 7; break; +- case 3: lpre += 9; break; +- } +- +- conf = conf + (lpre * dp->table[5]); +- conf++; +- } +- +- drv |= conf[0] << shifts[i]; +- pre |= conf[1] << shifts[i]; +- unk = (unk & ~0x0000ff00) | (conf[2] << 8); ++ dp->func->train_adj(dev, dp->dcb, i, lvsw, lpre); + } + +- nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, drv); +- nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, pre); +- nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff0f, unk); +- + return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4); + } + +@@ -556,11 +358,61 @@ dp_link_train_eq(struct drm_device *dev, struct dp_state *dp) + return eq_done ? 0 : -1; + } + ++static void ++dp_set_downspread(struct drm_device *dev, struct dp_state *dp, bool enable) ++{ ++ u16 script = 0x0000; ++ u8 *entry, *table = nouveau_dp_bios_data(dev, dp->dcb, &entry); ++ if (table) { ++ if (table[0] >= 0x20 && table[0] <= 0x30) { ++ if (enable) script = ROM16(entry[12]); ++ else script = ROM16(entry[14]); ++ } else ++ if (table[0] == 0x40) { ++ if (enable) script = ROM16(entry[11]); ++ else script = ROM16(entry[13]); ++ } ++ } ++ ++ nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); ++} ++ ++static void ++dp_link_train_init(struct drm_device *dev, struct dp_state *dp) ++{ ++ u16 script = 0x0000; ++ u8 *entry, *table = nouveau_dp_bios_data(dev, dp->dcb, &entry); ++ if (table) { ++ if (table[0] >= 0x20 && table[0] <= 0x30) ++ script = ROM16(entry[6]); ++ else ++ if (table[0] == 0x40) ++ script = ROM16(entry[5]); ++ } ++ ++ nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); ++} ++ ++static void ++dp_link_train_fini(struct drm_device *dev, struct dp_state *dp) ++{ ++ u16 script = 0x0000; ++ u8 *entry, *table = nouveau_dp_bios_data(dev, dp->dcb, &entry); ++ if (table) { ++ if (table[0] >= 0x20 && table[0] <= 0x30) ++ script = ROM16(entry[8]); ++ else ++ if (table[0] == 0x40) ++ script = ROM16(entry[7]); ++ } ++ ++ nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); ++} ++ + bool +-nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) ++nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, ++ struct dp_train_func *func) + { +- struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); + struct nouveau_connector *nv_connector = +@@ -575,34 +427,26 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) + if (!auxch) + return false; + +- dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry); +- if (!dp.table) +- return -EINVAL; +- ++ dp.func = func; + dp.dcb = nv_encoder->dcb; + dp.crtc = nv_crtc->index; +- dp.auxch = auxch->rd; +- dp.or = nv_encoder->or; +- dp.link = !(nv_encoder->dcb->sorconf.link & 1); ++ dp.auxch = auxch->drive; + dp.dpcd = nv_encoder->dp.dpcd; + ++ /* adjust required bandwidth for 8B/10B coding overhead */ ++ datarate = (datarate / 8) * 10; ++ + /* some sinks toggle hotplug in response to some of the actions + * we take during link training (DP_SET_POWER is one), we need + * to ignore them for the moment to avoid races. + */ +- pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); ++ nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, false); + + /* enable down-spreading, if possible */ +- if (dp.table[1] >= 16) { +- u16 script = ROM16(dp.entry[14]); +- if (nv_encoder->dp.dpcd[3] & 1) +- script = ROM16(dp.entry[12]); +- +- nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc); +- } ++ dp_set_downspread(dev, &dp, nv_encoder->dp.dpcd[3] & 1); + + /* execute pre-train script from vbios */ +- nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc); ++ dp_link_train_init(dev, &dp); + + /* start off at highest link rate supported by encoder and display */ + while (*link_bw > nv_encoder->dp.link_bw) +@@ -636,13 +480,36 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) + dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); + + /* execute post-train script from vbios */ +- nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc); ++ dp_link_train_fini(dev, &dp); + + /* re-enable hotplug detect */ +- pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); ++ nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, true); + return true; + } + ++void ++nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate, ++ struct dp_train_func *func) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_i2c_chan *auxch; ++ u8 status; ++ ++ auxch = nouveau_i2c_find(encoder->dev, nv_encoder->dcb->i2c_index); ++ if (!auxch) ++ return; ++ ++ if (mode == DRM_MODE_DPMS_ON) ++ status = DP_SET_POWER_D0; ++ else ++ status = DP_SET_POWER_D3; ++ ++ nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); ++ ++ if (mode == DRM_MODE_DPMS_ON) ++ nouveau_dp_link_train(encoder, datarate, func); ++} ++ + bool + nouveau_dp_detect(struct drm_encoder *encoder) + { +@@ -656,7 +523,7 @@ nouveau_dp_detect(struct drm_encoder *encoder) + if (!auxch) + return false; + +- ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8); ++ ret = auxch_tx(dev, auxch->drive, 9, DP_DPCD_REV, dpcd, 8); + if (ret) + return false; + +@@ -684,7 +551,7 @@ int + nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, + uint8_t *data, int data_nr) + { +- return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr); ++ return auxch_tx(auxch->dev, auxch->drive, cmd, addr, data, data_nr); + } + + static int +diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c +index 8c084c0..05091c2 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drv.c ++++ b/drivers/gpu/drm/nouveau/nouveau_drv.c +@@ -57,6 +57,10 @@ MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); + int nouveau_vram_notify = 0; + module_param_named(vram_notify, nouveau_vram_notify, int, 0400); + ++MODULE_PARM_DESC(vram_type, "Override detected VRAM type"); ++char *nouveau_vram_type; ++module_param_named(vram_type, nouveau_vram_type, charp, 0400); ++ + MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)"); + int nouveau_duallink = 1; + module_param_named(duallink, nouveau_duallink, int, 0400); +@@ -89,7 +93,7 @@ MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type"); + int nouveau_override_conntype = 0; + module_param_named(override_conntype, nouveau_override_conntype, int, 0400); + +-MODULE_PARM_DESC(tv_disable, "Disable TV-out detection\n"); ++MODULE_PARM_DESC(tv_disable, "Disable TV-out detection"); + int nouveau_tv_disable = 0; + module_param_named(tv_disable, nouveau_tv_disable, int, 0400); + +@@ -104,26 +108,30 @@ module_param_named(tv_norm, nouveau_tv_norm, charp, 0400); + MODULE_PARM_DESC(reg_debug, "Register access debug bitmask:\n" + "\t\t0x1 mc, 0x2 video, 0x4 fb, 0x8 extdev,\n" + "\t\t0x10 crtc, 0x20 ramdac, 0x40 vgacrtc, 0x80 rmvio,\n" +- "\t\t0x100 vgaattr, 0x200 EVO (G80+). "); ++ "\t\t0x100 vgaattr, 0x200 EVO (G80+)"); + int nouveau_reg_debug; + module_param_named(reg_debug, nouveau_reg_debug, int, 0600); + +-MODULE_PARM_DESC(perflvl, "Performance level (default: boot)\n"); ++MODULE_PARM_DESC(perflvl, "Performance level (default: boot)"); + char *nouveau_perflvl; + module_param_named(perflvl, nouveau_perflvl, charp, 0400); + +-MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)\n"); ++MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)"); + int nouveau_perflvl_wr; + module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); + +-MODULE_PARM_DESC(msi, "Enable MSI (default: off)\n"); ++MODULE_PARM_DESC(msi, "Enable MSI (default: off)"); + int nouveau_msi; + module_param_named(msi, nouveau_msi, int, 0400); + +-MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n"); ++MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)"); + int nouveau_ctxfw; + module_param_named(ctxfw, nouveau_ctxfw, int, 0400); + ++MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS"); ++int nouveau_mxmdcb = 1; ++module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400); ++ + int nouveau_fbpercrtc; + #if 0 + module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); +@@ -179,8 +187,11 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) + return 0; + + if (dev->mode_config.num_crtc) { +- NV_INFO(dev, "Disabling fbcon acceleration...\n"); +- nouveau_fbcon_save_disable_accel(dev); ++ NV_INFO(dev, "Disabling display...\n"); ++ nouveau_display_fini(dev); ++ ++ NV_INFO(dev, "Disabling fbcon...\n"); ++ nouveau_fbcon_set_suspend(dev, 1); + } + + NV_INFO(dev, "Unpinning framebuffer(s)...\n"); +@@ -222,7 +233,7 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) + + ret = dev_priv->eng[e]->fini(dev, e, true); + if (ret) { +- NV_ERROR(dev, "... engine %d failed: %d\n", i, ret); ++ NV_ERROR(dev, "... engine %d failed: %d\n", e, ret); + goto out_abort; + } + } +@@ -248,12 +259,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) + pci_set_power_state(pdev, PCI_D3hot); + } + +- if (dev->mode_config.num_crtc) { +- console_lock(); +- nouveau_fbcon_set_suspend(dev, 1); +- console_unlock(); +- nouveau_fbcon_restore_accel(dev); +- } + return 0; + + out_abort: +@@ -279,9 +284,6 @@ nouveau_pci_resume(struct pci_dev *pdev) + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) + return 0; + +- if (dev->mode_config.num_crtc) +- nouveau_fbcon_save_disable_accel(dev); +- + NV_INFO(dev, "We're back, enabling device...\n"); + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); +@@ -301,8 +303,6 @@ nouveau_pci_resume(struct pci_dev *pdev) + if (ret) + return ret; + +- nouveau_pm_resume(dev); +- + if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { + ret = nouveau_mem_init_agp(dev); + if (ret) { +@@ -342,6 +342,8 @@ nouveau_pci_resume(struct pci_dev *pdev) + } + } + ++ nouveau_pm_resume(dev); ++ + NV_INFO(dev, "Restoring mode...\n"); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_framebuffer *nouveau_fb; +@@ -363,15 +365,11 @@ nouveau_pci_resume(struct pci_dev *pdev) + NV_ERROR(dev, "Could not pin/map cursor.\n"); + } + +- engine->display.init(dev); +- +- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { +- struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); +- u32 offset = nv_crtc->cursor.nvbo->bo.offset; ++ if (dev->mode_config.num_crtc) { ++ nouveau_fbcon_set_suspend(dev, 0); ++ nouveau_fbcon_zfill_all(dev); + +- nv_crtc->cursor.set_offset(nv_crtc, offset); +- nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, +- nv_crtc->cursor_saved_y); ++ nouveau_display_init(dev); + } + + /* Force CLUT to get re-loaded during modeset */ +@@ -381,21 +379,35 @@ nouveau_pci_resume(struct pci_dev *pdev) + nv_crtc->lut.depth = 0; + } + +- if (dev->mode_config.num_crtc) { +- console_lock(); +- nouveau_fbcon_set_suspend(dev, 0); +- console_unlock(); ++ drm_helper_resume_force_mode(dev); + +- nouveau_fbcon_zfill_all(dev); +- } ++ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ u32 offset = nv_crtc->cursor.nvbo->bo.offset; + +- drm_helper_resume_force_mode(dev); ++ nv_crtc->cursor.set_offset(nv_crtc, offset); ++ nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, ++ nv_crtc->cursor_saved_y); ++ } + +- if (dev->mode_config.num_crtc) +- nouveau_fbcon_restore_accel(dev); + return 0; + } + ++static const struct file_operations nouveau_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .mmap = nouveau_ttm_mmap, ++ .poll = drm_poll, ++ .fasync = drm_fasync, ++ .read = drm_read, ++#if defined(CONFIG_COMPAT) ++ .compat_ioctl = nouveau_compat_ioctl, ++#endif ++ .llseek = noop_llseek, ++}; ++ + static struct drm_driver driver = { + .driver_features = + DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | +@@ -421,21 +433,7 @@ static struct drm_driver driver = { + .disable_vblank = nouveau_vblank_disable, + .reclaim_buffers = drm_core_reclaim_buffers, + .ioctls = nouveau_ioctls, +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = drm_ioctl, +- .mmap = nouveau_ttm_mmap, +- .poll = drm_poll, +- .fasync = drm_fasync, +- .read = drm_read, +-#if defined(CONFIG_COMPAT) +- .compat_ioctl = nouveau_compat_ioctl, +-#endif +- .llseek = noop_llseek, +- }, +- ++ .fops = &nouveau_driver_fops, + .gem_init_object = nouveau_gem_object_new, + .gem_free_object = nouveau_gem_object_del, + .gem_open_object = nouveau_gem_object_open, +diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h +index 4c0be3a..4ce03af 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drv.h ++++ b/drivers/gpu/drm/nouveau/nouveau_drv.h +@@ -26,15 +26,15 @@ + #define __NOUVEAU_DRV_H__ + + #define DRIVER_AUTHOR "Stephane Marchesin" +-#define DRIVER_EMAIL "dri-devel@lists.sourceforge.net" ++#define DRIVER_EMAIL "nouveau@lists.freedesktop.org" + + #define DRIVER_NAME "nouveau" + #define DRIVER_DESC "nVidia Riva/TNT/GeForce" +-#define DRIVER_DATE "20090420" ++#define DRIVER_DATE "20120316" + +-#define DRIVER_MAJOR 0 ++#define DRIVER_MAJOR 1 + #define DRIVER_MINOR 0 +-#define DRIVER_PATCHLEVEL 16 ++#define DRIVER_PATCHLEVEL 0 + + #define NOUVEAU_FAMILY 0x0000FFFF + #define NOUVEAU_FLAGS 0xFFFF0000 +@@ -113,8 +113,6 @@ struct nouveau_bo { + int pbbo_index; + bool validate_mapped; + +- struct nouveau_channel *channel; +- + struct list_head vma_list; + unsigned page_shift; + +@@ -163,6 +161,9 @@ enum nouveau_flags { + #define NVOBJ_ENGINE_COPY0 3 + #define NVOBJ_ENGINE_COPY1 4 + #define NVOBJ_ENGINE_MPEG 5 ++#define NVOBJ_ENGINE_PPP NVOBJ_ENGINE_MPEG ++#define NVOBJ_ENGINE_BSP 6 ++#define NVOBJ_ENGINE_VP 7 + #define NVOBJ_ENGINE_DISPLAY 15 + #define NVOBJ_ENGINE_NR 16 + +@@ -229,6 +230,7 @@ struct nouveau_channel { + /* mapping of the regs controlling the fifo */ + void __iomem *user; + uint32_t user_get; ++ uint32_t user_get_hi; + uint32_t user_put; + + /* Fencing */ +@@ -246,7 +248,7 @@ struct nouveau_channel { + struct nouveau_gpuobj *pushbuf; + struct nouveau_bo *pushbuf_bo; + struct nouveau_vma pushbuf_vma; +- uint32_t pushbuf_base; ++ uint64_t pushbuf_base; + + /* Notifier memory */ + struct nouveau_bo *notifier_bo; +@@ -292,7 +294,7 @@ struct nouveau_channel { + + uint32_t sw_subchannel[8]; + +- struct nouveau_vma dispc_vma[2]; ++ struct nouveau_vma dispc_vma[4]; + struct { + struct nouveau_gpuobj *vblsem; + uint32_t vblsem_head; +@@ -393,24 +395,28 @@ struct nouveau_display_engine { + int (*early_init)(struct drm_device *); + void (*late_takedown)(struct drm_device *); + int (*create)(struct drm_device *); +- int (*init)(struct drm_device *); + void (*destroy)(struct drm_device *); ++ int (*init)(struct drm_device *); ++ void (*fini)(struct drm_device *); ++ ++ struct drm_property *dithering_mode; ++ struct drm_property *dithering_depth; ++ struct drm_property *underscan_property; ++ struct drm_property *underscan_hborder_property; ++ struct drm_property *underscan_vborder_property; ++ /* not really hue and saturation: */ ++ struct drm_property *vibrant_hue_property; ++ struct drm_property *color_vibrance_property; + }; + + struct nouveau_gpio_engine { +- void *priv; +- +- int (*init)(struct drm_device *); +- void (*takedown)(struct drm_device *); +- +- int (*get)(struct drm_device *, enum dcb_gpio_tag); +- int (*set)(struct drm_device *, enum dcb_gpio_tag, int state); +- +- int (*irq_register)(struct drm_device *, enum dcb_gpio_tag, +- void (*)(void *, int), void *); +- void (*irq_unregister)(struct drm_device *, enum dcb_gpio_tag, +- void (*)(void *, int), void *); +- bool (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); ++ spinlock_t lock; ++ struct list_head isr; ++ int (*init)(struct drm_device *); ++ void (*fini)(struct drm_device *); ++ int (*drive)(struct drm_device *, int line, int dir, int out); ++ int (*sense)(struct drm_device *, int line); ++ void (*irq_enable)(struct drm_device *, int line, bool); + }; + + struct nouveau_pm_voltage_level { +@@ -427,64 +433,91 @@ struct nouveau_pm_voltage { + int nr_level; + }; + ++/* Exclusive upper limits */ ++#define NV_MEM_CL_DDR2_MAX 8 ++#define NV_MEM_WR_DDR2_MAX 9 ++#define NV_MEM_CL_DDR3_MAX 17 ++#define NV_MEM_WR_DDR3_MAX 17 ++#define NV_MEM_CL_GDDR3_MAX 16 ++#define NV_MEM_WR_GDDR3_MAX 18 ++#define NV_MEM_CL_GDDR5_MAX 21 ++#define NV_MEM_WR_GDDR5_MAX 20 ++ + struct nouveau_pm_memtiming { + int id; +- u32 reg_0; /* 0x10f290 on Fermi, 0x100220 for older */ +- u32 reg_1; +- u32 reg_2; +- u32 reg_3; +- u32 reg_4; +- u32 reg_5; +- u32 reg_6; +- u32 reg_7; +- u32 reg_8; +- /* To be written to 0x1002c0 */ +- u8 CL; +- u8 WR; ++ ++ u32 reg[9]; ++ u32 mr[4]; ++ ++ u8 tCWL; ++ ++ u8 odt; ++ u8 drive_strength; + }; + +-struct nouveau_pm_tbl_header{ ++struct nouveau_pm_tbl_header { + u8 version; + u8 header_len; + u8 entry_cnt; + u8 entry_len; + }; + +-struct nouveau_pm_tbl_entry{ ++struct nouveau_pm_tbl_entry { + u8 tWR; +- u8 tUNK_1; ++ u8 tWTR; + u8 tCL; +- u8 tRP; /* Byte 3 */ ++ u8 tRC; + u8 empty_4; +- u8 tRAS; /* Byte 5 */ ++ u8 tRFC; /* Byte 5 */ + u8 empty_6; +- u8 tRFC; /* Byte 7 */ ++ u8 tRAS; /* Byte 7 */ + u8 empty_8; +- u8 tRC; /* Byte 9 */ +- u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; +- u8 empty_15,empty_16,empty_17; +- u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; ++ u8 tRP; /* Byte 9 */ ++ u8 tRCDRD; ++ u8 tRCDWR; ++ u8 tRRD; ++ u8 tUNK_13; ++ u8 RAM_FT1; /* 14, a bitmask of random RAM features */ ++ u8 empty_15; ++ u8 tUNK_16; ++ u8 empty_17; ++ u8 tUNK_18; ++ u8 tCWL; ++ u8 tUNK_20, tUNK_21; + }; + +-/* nouveau_mem.c */ +-void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, +- struct nouveau_pm_tbl_entry *e, uint8_t magic_number, +- struct nouveau_pm_memtiming *timing); ++struct nouveau_pm_profile; ++struct nouveau_pm_profile_func { ++ void (*destroy)(struct nouveau_pm_profile *); ++ void (*init)(struct nouveau_pm_profile *); ++ void (*fini)(struct nouveau_pm_profile *); ++ struct nouveau_pm_level *(*select)(struct nouveau_pm_profile *); ++}; ++ ++struct nouveau_pm_profile { ++ const struct nouveau_pm_profile_func *func; ++ struct list_head head; ++ char name[8]; ++}; + + #define NOUVEAU_PM_MAX_LEVEL 8 + struct nouveau_pm_level { ++ struct nouveau_pm_profile profile; + struct device_attribute dev_attr; + char name[32]; + int id; + +- u32 core; ++ struct nouveau_pm_memtiming timing; + u32 memory; ++ u16 memscript; ++ ++ u32 core; + u32 shader; + u32 rop; + u32 copy; + u32 daemon; + u32 vdec; +- u32 unk05; /* nv50:nva3, roughly.. */ ++ u32 dom6; + u32 unka0; /* nva3:nvc0 */ + u32 hub01; /* nvc0- */ + u32 hub06; /* nvc0- */ +@@ -493,9 +526,6 @@ struct nouveau_pm_level { + u32 volt_min; /* microvolts */ + u32 volt_max; + u8 fanspeed; +- +- u16 memscript; +- struct nouveau_pm_memtiming *timing; + }; + + struct nouveau_pm_temp_sensor_constants { +@@ -512,19 +542,26 @@ struct nouveau_pm_threshold_temp { + s16 fan_boost; + }; + +-struct nouveau_pm_memtimings { +- bool supported; +- struct nouveau_pm_memtiming *timing; +- int nr_timing; ++struct nouveau_pm_fan { ++ u32 percent; ++ u32 min_duty; ++ u32 max_duty; ++ u32 pwm_freq; ++ u32 pwm_divisor; + }; + + struct nouveau_pm_engine { + struct nouveau_pm_voltage voltage; + struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL]; + int nr_perflvl; +- struct nouveau_pm_memtimings memtimings; + struct nouveau_pm_temp_sensor_constants sensor_constants; + struct nouveau_pm_threshold_temp threshold_temp; ++ struct nouveau_pm_fan fan; ++ ++ struct nouveau_pm_profile *profile_ac; ++ struct nouveau_pm_profile *profile_dc; ++ struct nouveau_pm_profile *profile; ++ struct list_head profiles; + + struct nouveau_pm_level boot; + struct nouveau_pm_level *cur; +@@ -532,19 +569,14 @@ struct nouveau_pm_engine { + struct device *hwmon; + struct notifier_block acpi_nb; + +- int (*clock_get)(struct drm_device *, u32 id); +- void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *, +- u32 id, int khz); +- void (*clock_set)(struct drm_device *, void *); +- + int (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); + void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); +- void (*clocks_set)(struct drm_device *, void *); ++ int (*clocks_set)(struct drm_device *, void *); + + int (*voltage_get)(struct drm_device *); + int (*voltage_set)(struct drm_device *, int voltage); +- int (*fanspeed_get)(struct drm_device *); +- int (*fanspeed_set)(struct drm_device *, int fanspeed); ++ int (*pwm_get)(struct drm_device *, int line, u32*, u32*); ++ int (*pwm_set)(struct drm_device *, int line, u32, u32); + int (*temp_get)(struct drm_device *); + }; + +@@ -661,14 +693,15 @@ struct nv04_mode_state { + }; + + enum nouveau_card_type { +- NV_04 = 0x00, ++ NV_04 = 0x04, + NV_10 = 0x10, + NV_20 = 0x20, + NV_30 = 0x30, + NV_40 = 0x40, + NV_50 = 0x50, + NV_C0 = 0xc0, +- NV_D0 = 0xd0 ++ NV_D0 = 0xd0, ++ NV_E0 = 0xe0, + }; + + struct drm_nouveau_private { +@@ -764,8 +797,22 @@ struct drm_nouveau_private { + } tile; + + /* VRAM/fb configuration */ ++ enum { ++ NV_MEM_TYPE_UNKNOWN = 0, ++ NV_MEM_TYPE_STOLEN, ++ NV_MEM_TYPE_SGRAM, ++ NV_MEM_TYPE_SDRAM, ++ NV_MEM_TYPE_DDR1, ++ NV_MEM_TYPE_DDR2, ++ NV_MEM_TYPE_DDR3, ++ NV_MEM_TYPE_GDDR2, ++ NV_MEM_TYPE_GDDR3, ++ NV_MEM_TYPE_GDDR4, ++ NV_MEM_TYPE_GDDR5 ++ } vram_type; + uint64_t vram_size; + uint64_t vram_sys_base; ++ bool vram_rank_B; + + uint64_t fb_available_size; + uint64_t fb_mappable_pages; +@@ -780,6 +827,8 @@ struct drm_nouveau_private { + struct nouveau_vm *chan_vm; + + struct nvbios vbios; ++ u8 *mxms; ++ struct list_head i2c_ports; + + struct nv04_mode_state mode_reg; + struct nv04_mode_state saved_reg; +@@ -836,6 +885,7 @@ extern int nouveau_uscript_lvds; + extern int nouveau_uscript_tmds; + extern int nouveau_vram_pushbuf; + extern int nouveau_vram_notify; ++extern char *nouveau_vram_type; + extern int nouveau_fbpercrtc; + extern int nouveau_tv_disable; + extern char *nouveau_tv_norm; +@@ -850,6 +900,7 @@ extern char *nouveau_perflvl; + extern int nouveau_perflvl_wr; + extern int nouveau_msi; + extern int nouveau_ctxfw; ++extern int nouveau_mxmdcb; + + extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); + extern int nouveau_pci_resume(struct pci_dev *pdev); +@@ -883,8 +934,12 @@ extern void nouveau_mem_gart_fini(struct drm_device *); + extern int nouveau_mem_init_agp(struct drm_device *); + extern int nouveau_mem_reset_agp(struct drm_device *); + extern void nouveau_mem_close(struct drm_device *); +-extern int nouveau_mem_detect(struct drm_device *); + extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags); ++extern int nouveau_mem_timing_calc(struct drm_device *, u32 freq, ++ struct nouveau_pm_memtiming *); ++extern void nouveau_mem_timing_read(struct drm_device *, ++ struct nouveau_pm_memtiming *); ++extern int nouveau_mem_vbios_type(struct drm_device *); + extern struct nouveau_tile_reg *nv10_mem_set_tiling( + struct drm_device *dev, uint32_t addr, uint32_t size, + uint32_t pitch, uint32_t flags); +@@ -1000,7 +1055,10 @@ extern int nouveau_sgdma_init(struct drm_device *); + extern void nouveau_sgdma_takedown(struct drm_device *); + extern uint32_t nouveau_sgdma_get_physical(struct drm_device *, + uint32_t offset); +-extern struct ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *); ++extern struct ttm_tt *nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev, ++ unsigned long size, ++ uint32_t page_flags, ++ struct page *dummy_read_page); + + /* nouveau_debugfs.c */ + #if defined(CONFIG_DRM_NOUVEAU_DEBUG) +@@ -1032,21 +1090,22 @@ nouveau_debugfs_channel_fini(struct nouveau_channel *chan) + #endif + + /* nouveau_dma.c */ +-extern void nouveau_dma_pre_init(struct nouveau_channel *); +-extern int nouveau_dma_init(struct nouveau_channel *); ++extern void nouveau_dma_init(struct nouveau_channel *); + extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size); + + /* nouveau_acpi.c */ + #define ROM_BIOS_PAGE 4096 +-#if defined(CONFIG_ACPI) ++#if defined(CONFIG_ACPI) && defined(CONFIG_X86) + void nouveau_register_dsm_handler(void); + void nouveau_unregister_dsm_handler(void); ++void nouveau_switcheroo_optimus_dsm(void); + int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); + bool nouveau_acpi_rom_supported(struct pci_dev *pdev); + int nouveau_acpi_edid(struct drm_device *, struct drm_connector *); + #else + static inline void nouveau_register_dsm_handler(void) {} + static inline void nouveau_unregister_dsm_handler(void) {} ++static inline void nouveau_switcheroo_optimus_dsm(void) {} + static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; } + static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; } + static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return -EINVAL; } +@@ -1072,8 +1131,6 @@ extern int nouveau_run_vbios_init(struct drm_device *); + extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table, + struct dcb_entry *, int crtc); + extern void nouveau_bios_init_exec(struct drm_device *, uint16_t table); +-extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *, +- enum dcb_gpio_tag); + extern struct dcb_connector_table_entry * + nouveau_bios_connector_entry(struct drm_device *, int index); + extern u32 get_pll_register(struct drm_device *, enum pll_types); +@@ -1091,24 +1148,26 @@ extern int call_lvds_script(struct drm_device *, struct dcb_entry *, int head, + enum LVDS_script, int pxclk); + bool bios_encoder_match(struct dcb_entry *, u32 hash); + ++/* nouveau_mxm.c */ ++int nouveau_mxm_init(struct drm_device *dev); ++void nouveau_mxm_fini(struct drm_device *dev); ++ + /* nouveau_ttm.c */ + int nouveau_ttm_global_init(struct drm_nouveau_private *); + void nouveau_ttm_global_release(struct drm_nouveau_private *); + int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); + +-/* nouveau_dp.c */ +-int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, +- uint8_t *data, int data_nr); +-bool nouveau_dp_detect(struct drm_encoder *); +-bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate); +-void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32); +-u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **); ++/* nouveau_hdmi.c */ ++void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); + + /* nv04_fb.c */ ++extern int nv04_fb_vram_init(struct drm_device *); + extern int nv04_fb_init(struct drm_device *); + extern void nv04_fb_takedown(struct drm_device *); + + /* nv10_fb.c */ ++extern int nv10_fb_vram_init(struct drm_device *dev); ++extern int nv1a_fb_vram_init(struct drm_device *dev); + extern int nv10_fb_init(struct drm_device *); + extern void nv10_fb_takedown(struct drm_device *); + extern void nv10_fb_init_tile_region(struct drm_device *dev, int i, +@@ -1117,6 +1176,16 @@ extern void nv10_fb_init_tile_region(struct drm_device *dev, int i, + extern void nv10_fb_set_tile_region(struct drm_device *dev, int i); + extern void nv10_fb_free_tile_region(struct drm_device *dev, int i); + ++/* nv20_fb.c */ ++extern int nv20_fb_vram_init(struct drm_device *dev); ++extern int nv20_fb_init(struct drm_device *); ++extern void nv20_fb_takedown(struct drm_device *); ++extern void nv20_fb_init_tile_region(struct drm_device *dev, int i, ++ uint32_t addr, uint32_t size, ++ uint32_t pitch, uint32_t flags); ++extern void nv20_fb_set_tile_region(struct drm_device *dev, int i); ++extern void nv20_fb_free_tile_region(struct drm_device *dev, int i); ++ + /* nv30_fb.c */ + extern int nv30_fb_init(struct drm_device *); + extern void nv30_fb_takedown(struct drm_device *); +@@ -1126,6 +1195,7 @@ extern void nv30_fb_init_tile_region(struct drm_device *dev, int i, + extern void nv30_fb_free_tile_region(struct drm_device *dev, int i); + + /* nv40_fb.c */ ++extern int nv40_fb_vram_init(struct drm_device *dev); + extern int nv40_fb_init(struct drm_device *); + extern void nv40_fb_takedown(struct drm_device *); + extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); +@@ -1222,6 +1292,9 @@ extern int nvc0_graph_isr_chid(struct drm_device *dev, u64 inst); + /* nv84_crypt.c */ + extern int nv84_crypt_create(struct drm_device *); + ++/* nv98_crypt.c */ ++extern int nv98_crypt_create(struct drm_device *dev); ++ + /* nva3_copy.c */ + extern int nva3_copy_create(struct drm_device *dev); + +@@ -1234,6 +1307,17 @@ extern int nv31_mpeg_create(struct drm_device *dev); + /* nv50_mpeg.c */ + extern int nv50_mpeg_create(struct drm_device *dev); + ++/* nv84_bsp.c */ ++/* nv98_bsp.c */ ++extern int nv84_bsp_create(struct drm_device *dev); ++ ++/* nv84_vp.c */ ++/* nv98_vp.c */ ++extern int nv84_vp_create(struct drm_device *dev); ++ ++/* nv98_ppp.c */ ++extern int nv98_ppp_create(struct drm_device *dev); ++ + /* nv04_instmem.c */ + extern int nv04_instmem_init(struct drm_device *); + extern void nv04_instmem_takedown(struct drm_device *); +@@ -1311,13 +1395,19 @@ extern int nv17_tv_create(struct drm_connector *, struct dcb_entry *); + extern int nv04_display_early_init(struct drm_device *); + extern void nv04_display_late_takedown(struct drm_device *); + extern int nv04_display_create(struct drm_device *); +-extern int nv04_display_init(struct drm_device *); + extern void nv04_display_destroy(struct drm_device *); ++extern int nv04_display_init(struct drm_device *); ++extern void nv04_display_fini(struct drm_device *); + + /* nvd0_display.c */ + extern int nvd0_display_create(struct drm_device *); +-extern int nvd0_display_init(struct drm_device *); + extern void nvd0_display_destroy(struct drm_device *); ++extern int nvd0_display_init(struct drm_device *); ++extern void nvd0_display_fini(struct drm_device *); ++struct nouveau_bo *nvd0_display_crtc_sema(struct drm_device *, int crtc); ++void nvd0_display_flip_stop(struct drm_crtc *); ++int nvd0_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, ++ struct nouveau_channel *, u32 swap_interval); + + /* nv04_crtc.c */ + extern int nv04_crtc_create(struct drm_device *, int index); +@@ -1412,6 +1502,10 @@ extern int nouveau_gem_ioctl_info(struct drm_device *, void *, + struct drm_file *); + + /* nouveau_display.c */ ++int nouveau_display_create(struct drm_device *dev); ++void nouveau_display_destroy(struct drm_device *dev); ++int nouveau_display_init(struct drm_device *dev); ++void nouveau_display_fini(struct drm_device *dev); + int nouveau_vblank_enable(struct drm_device *dev, int crtc); + void nouveau_vblank_disable(struct drm_device *dev, int crtc); + int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, +@@ -1426,23 +1520,22 @@ int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, + uint32_t handle); + + /* nv10_gpio.c */ +-int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); +-int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); ++int nv10_gpio_init(struct drm_device *dev); ++void nv10_gpio_fini(struct drm_device *dev); ++int nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out); ++int nv10_gpio_sense(struct drm_device *dev, int line); ++void nv10_gpio_irq_enable(struct drm_device *, int line, bool on); + + /* nv50_gpio.c */ + int nv50_gpio_init(struct drm_device *dev); + void nv50_gpio_fini(struct drm_device *dev); +-int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); +-int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); +-int nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); +-int nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); +-int nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag, +- void (*)(void *, int), void *); +-void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag, +- void (*)(void *, int), void *); +-bool nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on); +- +-/* nv50_calc. */ ++int nv50_gpio_drive(struct drm_device *dev, int line, int dir, int out); ++int nv50_gpio_sense(struct drm_device *dev, int line); ++void nv50_gpio_irq_enable(struct drm_device *, int line, bool on); ++int nvd0_gpio_drive(struct drm_device *dev, int line, int dir, int out); ++int nvd0_gpio_sense(struct drm_device *dev, int line); ++ ++/* nv50_calc.c */ + int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, + int *N1, int *M1, int *N2, int *M2, int *P); + int nva3_calc_pll(struct drm_device *, struct pll_lims *, +@@ -1565,6 +1658,13 @@ extern void nv_wo32(struct nouveau_gpuobj *, u32 offset, u32 val); + #define NV_TRACEWARN(d, fmt, arg...) NV_PRINTK(KERN_NOTICE, d, fmt, ##arg) + #define NV_TRACE(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg) + #define NV_WARN(d, fmt, arg...) NV_PRINTK(KERN_WARNING, d, fmt, ##arg) ++#define NV_WARNONCE(d, fmt, arg...) do { \ ++ static int _warned = 0; \ ++ if (!_warned) { \ ++ NV_WARN(d, fmt, ##arg); \ ++ _warned = 1; \ ++ } \ ++} while(0) + + /* nouveau_reg_debug bitmask */ + enum { +@@ -1652,6 +1752,7 @@ nv44_graph_class(struct drm_device *dev) + #define NV_MEM_ACCESS_RW (NV_MEM_ACCESS_RO | NV_MEM_ACCESS_WO) + #define NV_MEM_ACCESS_SYS 4 + #define NV_MEM_ACCESS_VM 8 ++#define NV_MEM_ACCESS_NOSNOOP 16 + + #define NV_MEM_TARGET_VRAM 0 + #define NV_MEM_TARGET_PCI 1 +@@ -1662,13 +1763,27 @@ nv44_graph_class(struct drm_device *dev) + #define NV_MEM_TYPE_VM 0x7f + #define NV_MEM_COMP_VM 0x03 + ++/* FIFO methods */ ++#define NV01_SUBCHAN_OBJECT 0x00000000 ++#define NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH 0x00000010 ++#define NV84_SUBCHAN_SEMAPHORE_ADDRESS_LOW 0x00000014 ++#define NV84_SUBCHAN_SEMAPHORE_SEQUENCE 0x00000018 ++#define NV84_SUBCHAN_SEMAPHORE_TRIGGER 0x0000001c ++#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL 0x00000001 ++#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG 0x00000002 ++#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL 0x00000004 ++#define NV84_SUBCHAN_NOTIFY_INTR 0x00000020 ++#define NV84_SUBCHAN_WRCACHE_FLUSH 0x00000024 ++#define NV10_SUBCHAN_REF_CNT 0x00000050 ++#define NVSW_SUBCHAN_PAGE_FLIP 0x00000054 ++#define NV11_SUBCHAN_DMA_SEMAPHORE 0x00000060 ++#define NV11_SUBCHAN_SEMAPHORE_OFFSET 0x00000064 ++#define NV11_SUBCHAN_SEMAPHORE_ACQUIRE 0x00000068 ++#define NV11_SUBCHAN_SEMAPHORE_RELEASE 0x0000006c ++#define NV40_SUBCHAN_YIELD 0x00000080 ++ + /* NV_SW object class */ + #define NV_SW 0x0000506e +-#define NV_SW_DMA_SEMAPHORE 0x00000060 +-#define NV_SW_SEMAPHORE_OFFSET 0x00000064 +-#define NV_SW_SEMAPHORE_ACQUIRE 0x00000068 +-#define NV_SW_SEMAPHORE_RELEASE 0x0000006c +-#define NV_SW_YIELD 0x00000080 + #define NV_SW_DMA_VBLSEM 0x0000018c + #define NV_SW_VBLSEM_OFFSET 0x00000400 + #define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 +diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h +index e5d6e3f..3dc14a3 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h ++++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h +@@ -32,6 +32,14 @@ + + #define NV_DPMS_CLEARED 0x80 + ++struct dp_train_func { ++ void (*link_set)(struct drm_device *, struct dcb_entry *, int crtc, ++ int nr, u32 bw, bool enhframe); ++ void (*train_set)(struct drm_device *, struct dcb_entry *, u8 pattern); ++ void (*train_adj)(struct drm_device *, struct dcb_entry *, ++ u8 lane, u8 swing, u8 preem); ++}; ++ + struct nouveau_encoder { + struct drm_encoder_slave base; + +@@ -78,9 +86,19 @@ get_slave_funcs(struct drm_encoder *enc) + return to_encoder_slave(enc)->slave_funcs; + } + ++/* nouveau_dp.c */ ++int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, ++ uint8_t *data, int data_nr); ++bool nouveau_dp_detect(struct drm_encoder *); ++void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate, ++ struct dp_train_func *); ++u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **); ++ + struct nouveau_connector * + nouveau_encoder_connector_get(struct nouveau_encoder *encoder); + int nv50_sor_create(struct drm_connector *, struct dcb_entry *); ++void nv50_sor_dp_calc_tu(struct drm_device *, int, int, u32, u32); + int nv50_dac_create(struct drm_connector *, struct dcb_entry *); + ++ + #endif /* __NOUVEAU_ENCODER_H__ */ +diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h +index 95c843e..f3fb649 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fb.h ++++ b/drivers/gpu/drm/nouveau/nouveau_fb.h +@@ -42,8 +42,6 @@ nouveau_framebuffer(struct drm_framebuffer *fb) + return container_of(fb, struct nouveau_framebuffer, base); + } + +-extern const struct drm_mode_config_funcs nouveau_mode_config_funcs; +- + int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb, +- struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo); ++ struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo); + #endif /* __NOUVEAU_FB_H__ */ +diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +index cc0801d..6fd2211 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c ++++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #include "drmP.h" + #include "drm.h" +@@ -281,7 +282,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, + struct nouveau_framebuffer *nouveau_fb; + struct nouveau_channel *chan; + struct nouveau_bo *nvbo; +- struct drm_mode_fb_cmd mode_cmd; ++ struct drm_mode_fb_cmd2 mode_cmd; + struct pci_dev *pdev = dev->pdev; + struct device *device = &pdev->dev; + int size, ret; +@@ -289,12 +290,13 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height; + +- mode_cmd.bpp = sizes->surface_bpp; +- mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3); +- mode_cmd.pitch = roundup(mode_cmd.pitch, 256); +- mode_cmd.depth = sizes->surface_depth; ++ mode_cmd.pitches[0] = mode_cmd.width * (sizes->surface_bpp >> 3); ++ mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], 256); + +- size = mode_cmd.pitch * mode_cmd.height; ++ mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, ++ sizes->surface_depth); ++ ++ size = mode_cmd.pitches[0] * mode_cmd.height; + size = roundup(size, PAGE_SIZE); + + ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM, +@@ -369,7 +371,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, + info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo); + info->screen_size = size; + +- drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); ++ drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_var(info, &nfbdev->helper, sizes->fb_width, sizes->fb_height); + + /* Set aperture base/size for vesafb takeover */ +@@ -379,11 +381,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, + goto out_unref; + } + +- info->pixmap.size = 64*1024; +- info->pixmap.buf_align = 8; +- info->pixmap.access_align = 32; +- info->pixmap.flags = FB_PIXMAP_SYSTEM; +- info->pixmap.scan_align = 1; ++ /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ + + mutex_unlock(&dev->struct_mutex); + +@@ -547,7 +545,13 @@ void nouveau_fbcon_restore_accel(struct drm_device *dev) + void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ console_lock(); ++ if (state == 0) ++ nouveau_fbcon_save_disable_accel(dev); + fb_set_suspend(dev_priv->nfbdev->helper.fbdev, state); ++ if (state == 1) ++ nouveau_fbcon_restore_accel(dev); ++ console_unlock(); + } + + void nouveau_fbcon_zfill_all(struct drm_device *dev) +diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c +index 2f6daae..c1dc20f 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fence.c ++++ b/drivers/gpu/drm/nouveau/nouveau_fence.c +@@ -93,18 +93,17 @@ nouveau_fence_update(struct nouveau_channel *chan) + } + + list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { +- sequence = fence->sequence; ++ if (fence->sequence > chan->fence.sequence_ack) ++ break; ++ + fence->signalled = true; + list_del(&fence->entry); +- +- if (unlikely(fence->work)) ++ if (fence->work) + fence->work(fence->priv, true); + + kref_put(&fence->refcount, nouveau_fence_del); +- +- if (sequence == chan->fence.sequence_ack) +- break; + } ++ + out: + spin_unlock(&chan->fence.lock); + } +@@ -165,9 +164,9 @@ nouveau_fence_emit(struct nouveau_fence *fence) + + if (USE_REFCNT(dev)) { + if (dev_priv->card_type < NV_C0) +- BEGIN_RING(chan, NvSubSw, 0x0050, 1); ++ BEGIN_RING(chan, 0, NV10_SUBCHAN_REF_CNT, 1); + else +- BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0050, 1); ++ BEGIN_NVC0(chan, 2, 0, NV10_SUBCHAN_REF_CNT, 1); + } else { + BEGIN_RING(chan, NvSubSw, 0x0150, 1); + } +@@ -344,7 +343,7 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) + if (ret) + return ret; + +- BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3); ++ BEGIN_RING(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 3); + OUT_RING (chan, NvSema); + OUT_RING (chan, offset); + OUT_RING (chan, 1); +@@ -354,9 +353,9 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) + if (ret) + return ret; + +- BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); ++ BEGIN_RING(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); + OUT_RING (chan, chan->vram_handle); +- BEGIN_RING(chan, NvSubSw, 0x0010, 4); ++ BEGIN_RING(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); + OUT_RING (chan, upper_32_bits(offset)); + OUT_RING (chan, lower_32_bits(offset)); + OUT_RING (chan, 1); +@@ -366,7 +365,7 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) + if (ret) + return ret; + +- BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); ++ BEGIN_NVC0(chan, 2, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); + OUT_RING (chan, upper_32_bits(offset)); + OUT_RING (chan, lower_32_bits(offset)); + OUT_RING (chan, 1); +@@ -397,10 +396,10 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) + if (ret) + return ret; + +- BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2); ++ BEGIN_RING(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2); + OUT_RING (chan, NvSema); + OUT_RING (chan, offset); +- BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1); ++ BEGIN_RING(chan, 0, NV11_SUBCHAN_SEMAPHORE_RELEASE, 1); + OUT_RING (chan, 1); + } else + if (dev_priv->chipset < 0xc0) { +@@ -408,9 +407,9 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) + if (ret) + return ret; + +- BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); ++ BEGIN_RING(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); + OUT_RING (chan, chan->vram_handle); +- BEGIN_RING(chan, NvSubSw, 0x0010, 4); ++ BEGIN_RING(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); + OUT_RING (chan, upper_32_bits(offset)); + OUT_RING (chan, lower_32_bits(offset)); + OUT_RING (chan, 1); +@@ -420,7 +419,7 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) + if (ret) + return ret; + +- BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); ++ BEGIN_NVC0(chan, 2, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); + OUT_RING (chan, upper_32_bits(offset)); + OUT_RING (chan, lower_32_bits(offset)); + OUT_RING (chan, 1); +@@ -510,7 +509,7 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) + if (ret) + return ret; + +- BEGIN_RING(chan, NvSubSw, 0, 1); ++ BEGIN_RING(chan, NvSubSw, NV01_SUBCHAN_OBJECT, 1); + OUT_RING (chan, NvSw); + FIRE_RING (chan); + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c +index bd0b1fc..2f46bbf 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_gem.c ++++ b/drivers/gpu/drm/nouveau/nouveau_gem.c +@@ -427,9 +427,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, + return ret; + } + +- nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan; + ret = nouveau_bo_validate(nvbo, true, false, false); +- nvbo->channel = NULL; + if (unlikely(ret)) { + if (ret != -ERESTARTSYS) + NV_ERROR(dev, "fail ttm_validate\n"); +@@ -679,19 +677,13 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, + return PTR_ERR(bo); + } + +- /* Mark push buffers as being used on PFIFO, the validation code +- * will then make sure that if the pushbuf bo moves, that they +- * happen on the kernel channel, which will in turn cause a sync +- * to happen before we try and submit the push buffer. +- */ ++ /* Ensure all push buffers are on validate list */ + for (i = 0; i < req->nr_push; i++) { + if (push[i].bo_index >= req->nr_buffers) { + NV_ERROR(dev, "push %d buffer not in list\n", i); + ret = -EINVAL; + goto out_prevalid; + } +- +- bo[push[i].bo_index].read_domains |= (1 << 31); + } + + /* Validate buffer list */ +diff --git a/drivers/gpu/drm/nouveau/nouveau_gpio.c b/drivers/gpu/drm/nouveau/nouveau_gpio.c +new file mode 100644 +index 0000000..a580cc6 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nouveau_gpio.c +@@ -0,0 +1,400 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ * ++ * Authors: Ben Skeggs ++ */ ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++#include "nouveau_i2c.h" ++#include "nouveau_gpio.h" ++ ++static u8 * ++dcb_gpio_table(struct drm_device *dev) ++{ ++ u8 *dcb = dcb_table(dev); ++ if (dcb) { ++ if (dcb[0] >= 0x30 && dcb[1] >= 0x0c) ++ return ROMPTR(dev, dcb[0x0a]); ++ if (dcb[0] >= 0x22 && dcb[-1] >= 0x13) ++ return ROMPTR(dev, dcb[-15]); ++ } ++ return NULL; ++} ++ ++static u8 * ++dcb_gpio_entry(struct drm_device *dev, int idx, int ent, u8 *version) ++{ ++ u8 *table = dcb_gpio_table(dev); ++ if (table) { ++ *version = table[0]; ++ if (*version < 0x30 && ent < table[2]) ++ return table + 3 + (ent * table[1]); ++ else if (ent < table[2]) ++ return table + table[1] + (ent * table[3]); ++ } ++ return NULL; ++} ++ ++int ++nouveau_gpio_drive(struct drm_device *dev, int idx, int line, int dir, int out) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ ++ return pgpio->drive ? pgpio->drive(dev, line, dir, out) : -ENODEV; ++} ++ ++int ++nouveau_gpio_sense(struct drm_device *dev, int idx, int line) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ ++ return pgpio->sense ? pgpio->sense(dev, line) : -ENODEV; ++} ++ ++int ++nouveau_gpio_find(struct drm_device *dev, int idx, u8 func, u8 line, ++ struct gpio_func *gpio) ++{ ++ u8 *table, *entry, version; ++ int i = -1; ++ ++ if (line == 0xff && func == 0xff) ++ return -EINVAL; ++ ++ while ((entry = dcb_gpio_entry(dev, idx, ++i, &version))) { ++ if (version < 0x40) { ++ u16 data = ROM16(entry[0]); ++ *gpio = (struct gpio_func) { ++ .line = (data & 0x001f) >> 0, ++ .func = (data & 0x07e0) >> 5, ++ .log[0] = (data & 0x1800) >> 11, ++ .log[1] = (data & 0x6000) >> 13, ++ }; ++ } else ++ if (version < 0x41) { ++ *gpio = (struct gpio_func) { ++ .line = entry[0] & 0x1f, ++ .func = entry[1], ++ .log[0] = (entry[3] & 0x18) >> 3, ++ .log[1] = (entry[3] & 0x60) >> 5, ++ }; ++ } else { ++ *gpio = (struct gpio_func) { ++ .line = entry[0] & 0x3f, ++ .func = entry[1], ++ .log[0] = (entry[4] & 0x30) >> 4, ++ .log[1] = (entry[4] & 0xc0) >> 6, ++ }; ++ } ++ ++ if ((line == 0xff || line == gpio->line) && ++ (func == 0xff || func == gpio->func)) ++ return 0; ++ } ++ ++ /* DCB 2.2, fixed TVDAC GPIO data */ ++ if ((table = dcb_table(dev)) && table[0] >= 0x22) { ++ if (func == DCB_GPIO_TVDAC0) { ++ *gpio = (struct gpio_func) { ++ .func = DCB_GPIO_TVDAC0, ++ .line = table[-4] >> 4, ++ .log[0] = !!(table[-5] & 2), ++ .log[1] = !(table[-5] & 2), ++ }; ++ return 0; ++ } ++ } ++ ++ /* Apple iMac G4 NV18 */ ++ if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { ++ if (func == DCB_GPIO_TVDAC0) { ++ *gpio = (struct gpio_func) { ++ .func = DCB_GPIO_TVDAC0, ++ .line = 4, ++ .log[0] = 0, ++ .log[1] = 1, ++ }; ++ return 0; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++int ++nouveau_gpio_set(struct drm_device *dev, int idx, u8 tag, u8 line, int state) ++{ ++ struct gpio_func gpio; ++ int ret; ++ ++ ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); ++ if (ret == 0) { ++ int dir = !!(gpio.log[state] & 0x02); ++ int out = !!(gpio.log[state] & 0x01); ++ ret = nouveau_gpio_drive(dev, idx, gpio.line, dir, out); ++ } ++ ++ return ret; ++} ++ ++int ++nouveau_gpio_get(struct drm_device *dev, int idx, u8 tag, u8 line) ++{ ++ struct gpio_func gpio; ++ int ret; ++ ++ ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); ++ if (ret == 0) { ++ ret = nouveau_gpio_sense(dev, idx, gpio.line); ++ if (ret >= 0) ++ ret = (ret == (gpio.log[1] & 1)); ++ } ++ ++ return ret; ++} ++ ++int ++nouveau_gpio_irq(struct drm_device *dev, int idx, u8 tag, u8 line, bool on) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ struct gpio_func gpio; ++ int ret; ++ ++ ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); ++ if (ret == 0) { ++ if (idx == 0 && pgpio->irq_enable) ++ pgpio->irq_enable(dev, gpio.line, on); ++ else ++ ret = -ENODEV; ++ } ++ ++ return ret; ++} ++ ++struct gpio_isr { ++ struct drm_device *dev; ++ struct list_head head; ++ struct work_struct work; ++ int idx; ++ struct gpio_func func; ++ void (*handler)(void *, int); ++ void *data; ++ bool inhibit; ++}; ++ ++static void ++nouveau_gpio_isr_bh(struct work_struct *work) ++{ ++ struct gpio_isr *isr = container_of(work, struct gpio_isr, work); ++ struct drm_device *dev = isr->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ unsigned long flags; ++ int state; ++ ++ state = nouveau_gpio_get(dev, isr->idx, isr->func.func, isr->func.line); ++ if (state >= 0) ++ isr->handler(isr->data, state); ++ ++ spin_lock_irqsave(&pgpio->lock, flags); ++ isr->inhibit = false; ++ spin_unlock_irqrestore(&pgpio->lock, flags); ++} ++ ++void ++nouveau_gpio_isr(struct drm_device *dev, int idx, u32 line_mask) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ struct gpio_isr *isr; ++ ++ if (idx != 0) ++ return; ++ ++ spin_lock(&pgpio->lock); ++ list_for_each_entry(isr, &pgpio->isr, head) { ++ if (line_mask & (1 << isr->func.line)) { ++ if (isr->inhibit) ++ continue; ++ isr->inhibit = true; ++ schedule_work(&isr->work); ++ } ++ } ++ spin_unlock(&pgpio->lock); ++} ++ ++int ++nouveau_gpio_isr_add(struct drm_device *dev, int idx, u8 tag, u8 line, ++ void (*handler)(void *, int), void *data) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ struct gpio_isr *isr; ++ unsigned long flags; ++ int ret; ++ ++ isr = kzalloc(sizeof(*isr), GFP_KERNEL); ++ if (!isr) ++ return -ENOMEM; ++ ++ ret = nouveau_gpio_find(dev, idx, tag, line, &isr->func); ++ if (ret) { ++ kfree(isr); ++ return ret; ++ } ++ ++ INIT_WORK(&isr->work, nouveau_gpio_isr_bh); ++ isr->dev = dev; ++ isr->handler = handler; ++ isr->data = data; ++ isr->idx = idx; ++ ++ spin_lock_irqsave(&pgpio->lock, flags); ++ list_add(&isr->head, &pgpio->isr); ++ spin_unlock_irqrestore(&pgpio->lock, flags); ++ return 0; ++} ++ ++void ++nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line, ++ void (*handler)(void *, int), void *data) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ struct gpio_isr *isr, *tmp; ++ struct gpio_func func; ++ unsigned long flags; ++ LIST_HEAD(tofree); ++ int ret; ++ ++ ret = nouveau_gpio_find(dev, idx, tag, line, &func); ++ if (ret == 0) { ++ spin_lock_irqsave(&pgpio->lock, flags); ++ list_for_each_entry_safe(isr, tmp, &pgpio->isr, head) { ++ if (memcmp(&isr->func, &func, sizeof(func)) || ++ isr->idx != idx || ++ isr->handler != handler || isr->data != data) ++ continue; ++ list_move(&isr->head, &tofree); ++ } ++ spin_unlock_irqrestore(&pgpio->lock, flags); ++ ++ list_for_each_entry_safe(isr, tmp, &tofree, head) { ++ flush_work_sync(&isr->work); ++ kfree(isr); ++ } ++ } ++} ++ ++int ++nouveau_gpio_create(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ ++ INIT_LIST_HEAD(&pgpio->isr); ++ spin_lock_init(&pgpio->lock); ++ ++ return nouveau_gpio_init(dev); ++} ++ ++void ++nouveau_gpio_destroy(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ ++ nouveau_gpio_fini(dev); ++ BUG_ON(!list_empty(&pgpio->isr)); ++} ++ ++int ++nouveau_gpio_init(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ int ret = 0; ++ ++ if (pgpio->init) ++ ret = pgpio->init(dev); ++ ++ return ret; ++} ++ ++void ++nouveau_gpio_fini(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ ++ if (pgpio->fini) ++ pgpio->fini(dev); ++} ++ ++void ++nouveau_gpio_reset(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u8 *entry, version; ++ int ent = -1; ++ ++ while ((entry = dcb_gpio_entry(dev, 0, ++ent, &version))) { ++ u8 func = 0xff, line, defs, unk0, unk1; ++ if (version >= 0x41) { ++ defs = !!(entry[0] & 0x80); ++ line = entry[0] & 0x3f; ++ func = entry[1]; ++ unk0 = entry[2]; ++ unk1 = entry[3] & 0x1f; ++ } else ++ if (version >= 0x40) { ++ line = entry[0] & 0x1f; ++ func = entry[1]; ++ defs = !!(entry[3] & 0x01); ++ unk0 = !!(entry[3] & 0x02); ++ unk1 = !!(entry[3] & 0x04); ++ } else { ++ break; ++ } ++ ++ if (func == 0xff) ++ continue; ++ ++ nouveau_gpio_func_set(dev, func, defs); ++ ++ if (dev_priv->card_type >= NV_D0) { ++ nv_mask(dev, 0x00d610 + (line * 4), 0xff, unk0); ++ if (unk1--) ++ nv_mask(dev, 0x00d640 + (unk1 * 4), 0xff, line); ++ } else ++ if (dev_priv->card_type >= NV_50) { ++ static const u32 regs[] = { 0xe100, 0xe28c }; ++ u32 val = (unk1 << 16) | unk0; ++ u32 reg = regs[line >> 4]; line &= 0x0f; ++ ++ nv_mask(dev, reg, 0x00010001 << line, val << line); ++ } ++ } ++} +diff --git a/drivers/gpu/drm/nouveau/nouveau_gpio.h b/drivers/gpu/drm/nouveau/nouveau_gpio.h +new file mode 100644 +index 0000000..64c5cb0 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nouveau_gpio.h +@@ -0,0 +1,71 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ */ ++ ++#ifndef __NOUVEAU_GPIO_H__ ++#define __NOUVEAU_GPIO_H__ ++ ++struct gpio_func { ++ u8 func; ++ u8 line; ++ u8 log[2]; ++}; ++ ++/* nouveau_gpio.c */ ++int nouveau_gpio_create(struct drm_device *); ++void nouveau_gpio_destroy(struct drm_device *); ++int nouveau_gpio_init(struct drm_device *); ++void nouveau_gpio_fini(struct drm_device *); ++void nouveau_gpio_reset(struct drm_device *); ++int nouveau_gpio_drive(struct drm_device *, int idx, int line, ++ int dir, int out); ++int nouveau_gpio_sense(struct drm_device *, int idx, int line); ++int nouveau_gpio_find(struct drm_device *, int idx, u8 tag, u8 line, ++ struct gpio_func *); ++int nouveau_gpio_set(struct drm_device *, int idx, u8 tag, u8 line, int state); ++int nouveau_gpio_get(struct drm_device *, int idx, u8 tag, u8 line); ++int nouveau_gpio_irq(struct drm_device *, int idx, u8 tag, u8 line, bool on); ++void nouveau_gpio_isr(struct drm_device *, int idx, u32 mask); ++int nouveau_gpio_isr_add(struct drm_device *, int idx, u8 tag, u8 line, ++ void (*)(void *, int state), void *data); ++void nouveau_gpio_isr_del(struct drm_device *, int idx, u8 tag, u8 line, ++ void (*)(void *, int state), void *data); ++ ++static inline bool ++nouveau_gpio_func_valid(struct drm_device *dev, u8 tag) ++{ ++ struct gpio_func func; ++ return (nouveau_gpio_find(dev, 0, tag, 0xff, &func)) == 0; ++} ++ ++static inline int ++nouveau_gpio_func_set(struct drm_device *dev, u8 tag, int state) ++{ ++ return nouveau_gpio_set(dev, 0, tag, 0xff, state); ++} ++ ++static inline int ++nouveau_gpio_func_get(struct drm_device *dev, u8 tag) ++{ ++ return nouveau_gpio_get(dev, 0, tag, 0xff); ++} ++ ++#endif +diff --git a/drivers/gpu/drm/nouveau/nouveau_hdmi.c b/drivers/gpu/drm/nouveau/nouveau_hdmi.c +new file mode 100644 +index 0000000..c3de363 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nouveau_hdmi.c +@@ -0,0 +1,260 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ * ++ * Authors: Ben Skeggs ++ */ ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++#include "nouveau_connector.h" ++#include "nouveau_encoder.h" ++#include "nouveau_crtc.h" ++ ++static bool ++hdmi_sor(struct drm_encoder *encoder) ++{ ++ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; ++ if (dev_priv->chipset < 0xa3 || ++ dev_priv->chipset == 0xaa || ++ dev_priv->chipset == 0xac) ++ return false; ++ return true; ++} ++ ++static inline u32 ++hdmi_base(struct drm_encoder *encoder) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); ++ if (!hdmi_sor(encoder)) ++ return 0x616500 + (nv_crtc->index * 0x800); ++ return 0x61c500 + (nv_encoder->or * 0x800); ++} ++ ++static void ++hdmi_wr32(struct drm_encoder *encoder, u32 reg, u32 val) ++{ ++ nv_wr32(encoder->dev, hdmi_base(encoder) + reg, val); ++} ++ ++static u32 ++hdmi_rd32(struct drm_encoder *encoder, u32 reg) ++{ ++ return nv_rd32(encoder->dev, hdmi_base(encoder) + reg); ++} ++ ++static u32 ++hdmi_mask(struct drm_encoder *encoder, u32 reg, u32 mask, u32 val) ++{ ++ u32 tmp = hdmi_rd32(encoder, reg); ++ hdmi_wr32(encoder, reg, (tmp & ~mask) | val); ++ return tmp; ++} ++ ++static void ++nouveau_audio_disconnect(struct drm_encoder *encoder) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ u32 or = nv_encoder->or * 0x800; ++ ++ if (hdmi_sor(encoder)) { ++ nv_mask(dev, 0x61c448 + or, 0x00000003, 0x00000000); ++ } ++} ++ ++static void ++nouveau_audio_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_connector *nv_connector; ++ struct drm_device *dev = encoder->dev; ++ u32 or = nv_encoder->or * 0x800; ++ int i; ++ ++ nv_connector = nouveau_encoder_connector_get(nv_encoder); ++ if (!drm_detect_monitor_audio(nv_connector->edid)) { ++ nouveau_audio_disconnect(encoder); ++ return; ++ } ++ ++ if (hdmi_sor(encoder)) { ++ nv_mask(dev, 0x61c448 + or, 0x00000001, 0x00000001); ++ ++ drm_edid_to_eld(&nv_connector->base, nv_connector->edid); ++ if (nv_connector->base.eld[0]) { ++ u8 *eld = nv_connector->base.eld; ++ for (i = 0; i < eld[2] * 4; i++) ++ nv_wr32(dev, 0x61c440 + or, (i << 8) | eld[i]); ++ for (i = eld[2] * 4; i < 0x60; i++) ++ nv_wr32(dev, 0x61c440 + or, (i << 8) | 0x00); ++ nv_mask(dev, 0x61c448 + or, 0x00000002, 0x00000002); ++ } ++ } ++} ++ ++static void ++nouveau_hdmi_infoframe(struct drm_encoder *encoder, u32 ctrl, u8 *frame) ++{ ++ /* calculate checksum for the infoframe */ ++ u8 sum = 0, i; ++ for (i = 0; i < frame[2]; i++) ++ sum += frame[i]; ++ frame[3] = 256 - sum; ++ ++ /* disable infoframe, and write header */ ++ hdmi_mask(encoder, ctrl + 0x00, 0x00000001, 0x00000000); ++ hdmi_wr32(encoder, ctrl + 0x08, *(u32 *)frame & 0xffffff); ++ ++ /* register scans tell me the audio infoframe has only one set of ++ * subpack regs, according to tegra (gee nvidia, it'd be nice if we ++ * could get those docs too!), the hdmi block pads out the rest of ++ * the packet on its own. ++ */ ++ if (ctrl == 0x020) ++ frame[2] = 6; ++ ++ /* write out checksum and data, weird weird 7 byte register pairs */ ++ for (i = 0; i < frame[2] + 1; i += 7) { ++ u32 rsubpack = ctrl + 0x0c + ((i / 7) * 8); ++ u32 *subpack = (u32 *)&frame[3 + i]; ++ hdmi_wr32(encoder, rsubpack + 0, subpack[0]); ++ hdmi_wr32(encoder, rsubpack + 4, subpack[1] & 0xffffff); ++ } ++ ++ /* enable the infoframe */ ++ hdmi_mask(encoder, ctrl, 0x00000001, 0x00000001); ++} ++ ++static void ++nouveau_hdmi_video_infoframe(struct drm_encoder *encoder, ++ struct drm_display_mode *mode) ++{ ++ const u8 Y = 0, A = 0, B = 0, S = 0, C = 0, M = 0, R = 0; ++ const u8 ITC = 0, EC = 0, Q = 0, SC = 0, VIC = 0, PR = 0; ++ const u8 bar_top = 0, bar_bottom = 0, bar_left = 0, bar_right = 0; ++ u8 frame[20]; ++ ++ frame[0x00] = 0x82; /* AVI infoframe */ ++ frame[0x01] = 0x02; /* version */ ++ frame[0x02] = 0x0d; /* length */ ++ frame[0x03] = 0x00; ++ frame[0x04] = (Y << 5) | (A << 4) | (B << 2) | S; ++ frame[0x05] = (C << 6) | (M << 4) | R; ++ frame[0x06] = (ITC << 7) | (EC << 4) | (Q << 2) | SC; ++ frame[0x07] = VIC; ++ frame[0x08] = PR; ++ frame[0x09] = bar_top & 0xff; ++ frame[0x0a] = bar_top >> 8; ++ frame[0x0b] = bar_bottom & 0xff; ++ frame[0x0c] = bar_bottom >> 8; ++ frame[0x0d] = bar_left & 0xff; ++ frame[0x0e] = bar_left >> 8; ++ frame[0x0f] = bar_right & 0xff; ++ frame[0x10] = bar_right >> 8; ++ frame[0x11] = 0x00; ++ frame[0x12] = 0x00; ++ frame[0x13] = 0x00; ++ ++ nouveau_hdmi_infoframe(encoder, 0x020, frame); ++} ++ ++static void ++nouveau_hdmi_audio_infoframe(struct drm_encoder *encoder, ++ struct drm_display_mode *mode) ++{ ++ const u8 CT = 0x00, CC = 0x01, ceaSS = 0x00, SF = 0x00, FMT = 0x00; ++ const u8 CA = 0x00, DM_INH = 0, LSV = 0x00; ++ u8 frame[12]; ++ ++ frame[0x00] = 0x84; /* Audio infoframe */ ++ frame[0x01] = 0x01; /* version */ ++ frame[0x02] = 0x0a; /* length */ ++ frame[0x03] = 0x00; ++ frame[0x04] = (CT << 4) | CC; ++ frame[0x05] = (SF << 2) | ceaSS; ++ frame[0x06] = FMT; ++ frame[0x07] = CA; ++ frame[0x08] = (DM_INH << 7) | (LSV << 3); ++ frame[0x09] = 0x00; ++ frame[0x0a] = 0x00; ++ frame[0x0b] = 0x00; ++ ++ nouveau_hdmi_infoframe(encoder, 0x000, frame); ++} ++ ++static void ++nouveau_hdmi_disconnect(struct drm_encoder *encoder) ++{ ++ nouveau_audio_disconnect(encoder); ++ ++ /* disable audio and avi infoframes */ ++ hdmi_mask(encoder, 0x000, 0x00000001, 0x00000000); ++ hdmi_mask(encoder, 0x020, 0x00000001, 0x00000000); ++ ++ /* disable hdmi */ ++ hdmi_mask(encoder, 0x0a4, 0x40000000, 0x00000000); ++} ++ ++void ++nouveau_hdmi_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_connector *nv_connector; ++ struct drm_device *dev = encoder->dev; ++ u32 max_ac_packet, rekey; ++ ++ nv_connector = nouveau_encoder_connector_get(nv_encoder); ++ if (!mode || !nv_connector || !nv_connector->edid || ++ !drm_detect_hdmi_monitor(nv_connector->edid)) { ++ nouveau_hdmi_disconnect(encoder); ++ return; ++ } ++ ++ nouveau_hdmi_video_infoframe(encoder, mode); ++ nouveau_hdmi_audio_infoframe(encoder, mode); ++ ++ hdmi_mask(encoder, 0x0d0, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ ++ hdmi_mask(encoder, 0x068, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ ++ hdmi_mask(encoder, 0x078, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ ++ ++ nv_mask(dev, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ ++ nv_mask(dev, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ ++ nv_mask(dev, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ ++ ++ /* value matches nvidia binary driver, and tegra constant */ ++ rekey = 56; ++ ++ max_ac_packet = mode->htotal - mode->hdisplay; ++ max_ac_packet -= rekey; ++ max_ac_packet -= 18; /* constant from tegra */ ++ max_ac_packet /= 32; ++ ++ /* enable hdmi */ ++ hdmi_mask(encoder, 0x0a4, 0x5f1f003f, 0x40000000 | /* enable */ ++ 0x1f000000 | /* unknown */ ++ max_ac_packet << 16 | ++ rekey); ++ ++ nouveau_audio_mode_set(encoder, mode); ++} +diff --git a/drivers/gpu/drm/nouveau/nouveau_hwsq.h b/drivers/gpu/drm/nouveau/nouveau_hwsq.h +new file mode 100644 +index 0000000..6976875 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nouveau_hwsq.h +@@ -0,0 +1,115 @@ ++/* ++ * Copyright 2010 Red Hat Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ * ++ * Authors: Ben Skeggs ++ */ ++ ++#ifndef __NOUVEAU_HWSQ_H__ ++#define __NOUVEAU_HWSQ_H__ ++ ++struct hwsq_ucode { ++ u8 data[0x200]; ++ union { ++ u8 *u08; ++ u16 *u16; ++ u32 *u32; ++ } ptr; ++ u16 len; ++ ++ u32 reg; ++ u32 val; ++}; ++ ++static inline void ++hwsq_init(struct hwsq_ucode *hwsq) ++{ ++ hwsq->ptr.u08 = hwsq->data; ++ hwsq->reg = 0xffffffff; ++ hwsq->val = 0xffffffff; ++} ++ ++static inline void ++hwsq_fini(struct hwsq_ucode *hwsq) ++{ ++ do { ++ *hwsq->ptr.u08++ = 0x7f; ++ hwsq->len = hwsq->ptr.u08 - hwsq->data; ++ } while (hwsq->len & 3); ++ hwsq->ptr.u08 = hwsq->data; ++} ++ ++static inline void ++hwsq_usec(struct hwsq_ucode *hwsq, u8 usec) ++{ ++ u32 shift = 0; ++ while (usec & ~3) { ++ usec >>= 2; ++ shift++; ++ } ++ ++ *hwsq->ptr.u08++ = (shift << 2) | usec; ++} ++ ++static inline void ++hwsq_setf(struct hwsq_ucode *hwsq, u8 flag, int val) ++{ ++ flag += 0x80; ++ if (val >= 0) ++ flag += 0x20; ++ if (val >= 1) ++ flag += 0x20; ++ *hwsq->ptr.u08++ = flag; ++} ++ ++static inline void ++hwsq_op5f(struct hwsq_ucode *hwsq, u8 v0, u8 v1) ++{ ++ *hwsq->ptr.u08++ = 0x5f; ++ *hwsq->ptr.u08++ = v0; ++ *hwsq->ptr.u08++ = v1; ++} ++ ++static inline void ++hwsq_wr32(struct hwsq_ucode *hwsq, u32 reg, u32 val) ++{ ++ if (val != hwsq->val) { ++ if ((val & 0xffff0000) == (hwsq->val & 0xffff0000)) { ++ *hwsq->ptr.u08++ = 0x42; ++ *hwsq->ptr.u16++ = (val & 0x0000ffff); ++ } else { ++ *hwsq->ptr.u08++ = 0xe2; ++ *hwsq->ptr.u32++ = val; ++ } ++ ++ hwsq->val = val; ++ } ++ ++ if ((reg & 0xffff0000) == (hwsq->reg & 0xffff0000)) { ++ *hwsq->ptr.u08++ = 0x40; ++ *hwsq->ptr.u16++ = (reg & 0x0000ffff); ++ } else { ++ *hwsq->ptr.u08++ = 0xe0; ++ *hwsq->ptr.u32++ = reg; ++ } ++ hwsq->reg = reg; ++} ++ ++#endif +diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c +index d39b220..77e5646 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_i2c.c ++++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c +@@ -30,83 +30,83 @@ + #include "nouveau_hw.h" + + static void +-nv04_i2c_setscl(void *data, int state) ++i2c_drive_scl(void *data, int state) + { +- struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; +- uint8_t val; +- +- val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xd0) | (state ? 0x20 : 0); +- NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01); +-} +- +-static void +-nv04_i2c_setsda(void *data, int state) +-{ +- struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; +- uint8_t val; +- +- val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xe0) | (state ? 0x10 : 0); +- NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01); +-} +- +-static int +-nv04_i2c_getscl(void *data) +-{ +- struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; +- +- return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 4); +-} +- +-static int +-nv04_i2c_getsda(void *data) +-{ +- struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; +- +- return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 8); +-} +- +-static void +-nv4e_i2c_setscl(void *data, int state) +-{ +- struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; +- uint8_t val; +- +- val = (nv_rd32(dev, i2c->wr) & 0xd0) | (state ? 0x20 : 0); +- nv_wr32(dev, i2c->wr, val | 0x01); ++ struct nouveau_i2c_chan *port = data; ++ if (port->type == 0) { ++ u8 val = NVReadVgaCrtc(port->dev, 0, port->drive); ++ if (state) val |= 0x20; ++ else val &= 0xdf; ++ NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01); ++ } else ++ if (port->type == 4) { ++ nv_mask(port->dev, port->drive, 0x2f, state ? 0x21 : 0x01); ++ } else ++ if (port->type == 5) { ++ if (state) port->state |= 0x01; ++ else port->state &= 0xfe; ++ nv_wr32(port->dev, port->drive, 4 | port->state); ++ } + } + + static void +-nv4e_i2c_setsda(void *data, int state) ++i2c_drive_sda(void *data, int state) + { +- struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; +- uint8_t val; +- +- val = (nv_rd32(dev, i2c->wr) & 0xe0) | (state ? 0x10 : 0); +- nv_wr32(dev, i2c->wr, val | 0x01); ++ struct nouveau_i2c_chan *port = data; ++ if (port->type == 0) { ++ u8 val = NVReadVgaCrtc(port->dev, 0, port->drive); ++ if (state) val |= 0x10; ++ else val &= 0xef; ++ NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01); ++ } else ++ if (port->type == 4) { ++ nv_mask(port->dev, port->drive, 0x1f, state ? 0x11 : 0x01); ++ } else ++ if (port->type == 5) { ++ if (state) port->state |= 0x02; ++ else port->state &= 0xfd; ++ nv_wr32(port->dev, port->drive, 4 | port->state); ++ } + } + + static int +-nv4e_i2c_getscl(void *data) ++i2c_sense_scl(void *data) + { +- struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; +- +- return !!((nv_rd32(dev, i2c->rd) >> 16) & 4); ++ struct nouveau_i2c_chan *port = data; ++ struct drm_nouveau_private *dev_priv = port->dev->dev_private; ++ if (port->type == 0) { ++ return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x04); ++ } else ++ if (port->type == 4) { ++ return !!(nv_rd32(port->dev, port->sense) & 0x00040000); ++ } else ++ if (port->type == 5) { ++ if (dev_priv->card_type < NV_D0) ++ return !!(nv_rd32(port->dev, port->sense) & 0x01); ++ else ++ return !!(nv_rd32(port->dev, port->sense) & 0x10); ++ } ++ return 0; + } + + static int +-nv4e_i2c_getsda(void *data) ++i2c_sense_sda(void *data) + { +- struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; +- +- return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); ++ struct nouveau_i2c_chan *port = data; ++ struct drm_nouveau_private *dev_priv = port->dev->dev_private; ++ if (port->type == 0) { ++ return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x08); ++ } else ++ if (port->type == 4) { ++ return !!(nv_rd32(port->dev, port->sense) & 0x00080000); ++ } else ++ if (port->type == 5) { ++ if (dev_priv->card_type < NV_D0) ++ return !!(nv_rd32(port->dev, port->sense) & 0x02); ++ else ++ return !!(nv_rd32(port->dev, port->sense) & 0x20); ++ } ++ return 0; + } + + static const uint32_t nv50_i2c_port[] = { +@@ -114,177 +114,223 @@ static const uint32_t nv50_i2c_port[] = { + 0x00e254, 0x00e274, 0x00e764, 0x00e780, + 0x00e79c, 0x00e7b8 + }; +-#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) + +-static int +-nv50_i2c_getscl(void *data) +-{ +- struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; +- +- return !!(nv_rd32(dev, i2c->rd) & 1); +-} +- +- +-static int +-nv50_i2c_getsda(void *data) ++static u8 * ++i2c_table(struct drm_device *dev, u8 *version) + { +- struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; +- +- return !!(nv_rd32(dev, i2c->rd) & 2); +-} ++ u8 *dcb = dcb_table(dev), *i2c = NULL; ++ if (dcb) { ++ if (dcb[0] >= 0x15) ++ i2c = ROMPTR(dev, dcb[2]); ++ if (dcb[0] >= 0x30) ++ i2c = ROMPTR(dev, dcb[4]); ++ } + +-static void +-nv50_i2c_setscl(void *data, int state) +-{ +- struct nouveau_i2c_chan *i2c = data; ++ /* early revisions had no version number, use dcb version */ ++ if (i2c) { ++ *version = dcb[0]; ++ if (*version >= 0x30) ++ *version = i2c[0]; ++ } + +- nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); ++ return i2c; + } + +-static void +-nv50_i2c_setsda(void *data, int state) ++int ++nouveau_i2c_init(struct drm_device *dev) + { +- struct nouveau_i2c_chan *i2c = data; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvbios *bios = &dev_priv->vbios; ++ struct nouveau_i2c_chan *port; ++ u8 version = 0x00, entries, recordlen; ++ u8 *i2c, *entry, legacy[2][4] = {}; ++ int ret, i; ++ ++ INIT_LIST_HEAD(&dev_priv->i2c_ports); ++ ++ i2c = i2c_table(dev, &version); ++ if (!i2c) { ++ u8 *bmp = &bios->data[bios->offset]; ++ if (bios->type != NVBIOS_BMP) ++ return -ENODEV; ++ ++ legacy[0][0] = NV_CIO_CRE_DDC_WR__INDEX; ++ legacy[0][1] = NV_CIO_CRE_DDC_STATUS__INDEX; ++ legacy[1][0] = NV_CIO_CRE_DDC0_WR__INDEX; ++ legacy[1][1] = NV_CIO_CRE_DDC0_STATUS__INDEX; ++ ++ /* BMP (from v4.0) has i2c info in the structure, it's in a ++ * fixed location on earlier VBIOS ++ */ ++ if (bmp[5] < 4) ++ i2c = &bios->data[0x48]; ++ else ++ i2c = &bmp[0x36]; ++ ++ if (i2c[4]) legacy[0][0] = i2c[4]; ++ if (i2c[5]) legacy[0][1] = i2c[5]; ++ if (i2c[6]) legacy[1][0] = i2c[6]; ++ if (i2c[7]) legacy[1][1] = i2c[7]; ++ } + +- nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0)); +- i2c->data = state; +-} ++ if (version >= 0x30) { ++ entry = i2c[1] + i2c; ++ entries = i2c[2]; ++ recordlen = i2c[3]; ++ } else ++ if (version) { ++ entry = i2c; ++ entries = 16; ++ recordlen = 4; ++ } else { ++ entry = legacy[0]; ++ entries = 2; ++ recordlen = 4; ++ } + +-static int +-nvd0_i2c_getscl(void *data) +-{ +- struct nouveau_i2c_chan *i2c = data; +- return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10); +-} ++ for (i = 0; i < entries; i++, entry += recordlen) { ++ port = kzalloc(sizeof(*port), GFP_KERNEL); ++ if (port == NULL) { ++ nouveau_i2c_fini(dev); ++ return -ENOMEM; ++ } + +-static int +-nvd0_i2c_getsda(void *data) +-{ +- struct nouveau_i2c_chan *i2c = data; +- return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20); +-} ++ port->type = entry[3]; ++ if (version < 0x30) { ++ port->type &= 0x07; ++ if (port->type == 0x07) ++ port->type = 0xff; ++ } + +-int +-nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_i2c_chan *i2c; +- int ret; ++ if (port->type == 0xff) { ++ kfree(port); ++ continue; ++ } + +- if (entry->chan) +- return -EEXIST; ++ switch (port->type) { ++ case 0: /* NV04:NV50 */ ++ port->drive = entry[0]; ++ port->sense = entry[1]; ++ break; ++ case 4: /* NV4E */ ++ port->drive = 0x600800 + entry[1]; ++ port->sense = port->drive; ++ break; ++ case 5: /* NV50- */ ++ port->drive = entry[0] & 0x0f; ++ if (dev_priv->card_type < NV_D0) { ++ if (port->drive >= ARRAY_SIZE(nv50_i2c_port)) ++ break; ++ port->drive = nv50_i2c_port[port->drive]; ++ port->sense = port->drive; ++ } else { ++ port->drive = 0x00d014 + (port->drive * 0x20); ++ port->sense = port->drive; ++ } ++ break; ++ case 6: /* NV50- DP AUX */ ++ port->drive = entry[0]; ++ port->sense = port->drive; ++ port->adapter.algo = &nouveau_dp_i2c_algo; ++ break; ++ default: ++ break; ++ } + +- if (dev_priv->card_type >= NV_50 && +- dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) { +- NV_ERROR(dev, "unknown i2c port %d\n", entry->read); +- return -EINVAL; +- } ++ if (!port->adapter.algo && !port->drive) { ++ NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n", ++ i, port->type, port->drive, port->sense); ++ kfree(port); ++ continue; ++ } + +- i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); +- if (i2c == NULL) +- return -ENOMEM; +- +- switch (entry->port_type) { +- case 0: +- i2c->bit.setsda = nv04_i2c_setsda; +- i2c->bit.setscl = nv04_i2c_setscl; +- i2c->bit.getsda = nv04_i2c_getsda; +- i2c->bit.getscl = nv04_i2c_getscl; +- i2c->rd = entry->read; +- i2c->wr = entry->write; +- break; +- case 4: +- i2c->bit.setsda = nv4e_i2c_setsda; +- i2c->bit.setscl = nv4e_i2c_setscl; +- i2c->bit.getsda = nv4e_i2c_getsda; +- i2c->bit.getscl = nv4e_i2c_getscl; +- i2c->rd = 0x600800 + entry->read; +- i2c->wr = 0x600800 + entry->write; +- break; +- case 5: +- i2c->bit.setsda = nv50_i2c_setsda; +- i2c->bit.setscl = nv50_i2c_setscl; +- if (dev_priv->card_type < NV_D0) { +- i2c->bit.getsda = nv50_i2c_getsda; +- i2c->bit.getscl = nv50_i2c_getscl; +- i2c->rd = nv50_i2c_port[entry->read]; +- i2c->wr = i2c->rd; ++ snprintf(port->adapter.name, sizeof(port->adapter.name), ++ "nouveau-%s-%d", pci_name(dev->pdev), i); ++ port->adapter.owner = THIS_MODULE; ++ port->adapter.dev.parent = &dev->pdev->dev; ++ port->dev = dev; ++ port->index = i; ++ port->dcb = ROM32(entry[0]); ++ i2c_set_adapdata(&port->adapter, i2c); ++ ++ if (port->adapter.algo != &nouveau_dp_i2c_algo) { ++ port->adapter.algo_data = &port->bit; ++ port->bit.udelay = 10; ++ port->bit.timeout = usecs_to_jiffies(2200); ++ port->bit.data = port; ++ port->bit.setsda = i2c_drive_sda; ++ port->bit.setscl = i2c_drive_scl; ++ port->bit.getsda = i2c_sense_sda; ++ port->bit.getscl = i2c_sense_scl; ++ ++ i2c_drive_scl(port, 0); ++ i2c_drive_sda(port, 1); ++ i2c_drive_scl(port, 1); ++ ++ ret = i2c_bit_add_bus(&port->adapter); + } else { +- i2c->bit.getsda = nvd0_i2c_getsda; +- i2c->bit.getscl = nvd0_i2c_getscl; +- i2c->rd = 0x00d014 + (entry->read * 0x20); +- i2c->wr = i2c->rd; ++ port->adapter.algo = &nouveau_dp_i2c_algo; ++ ret = i2c_add_adapter(&port->adapter); + } +- break; +- case 6: +- i2c->rd = entry->read; +- i2c->wr = entry->write; +- break; +- default: +- NV_ERROR(dev, "DCB I2C port type %d unknown\n", +- entry->port_type); +- kfree(i2c); +- return -EINVAL; +- } + +- snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), +- "nouveau-%s-%d", pci_name(dev->pdev), index); +- i2c->adapter.owner = THIS_MODULE; +- i2c->adapter.dev.parent = &dev->pdev->dev; +- i2c->dev = dev; +- i2c_set_adapdata(&i2c->adapter, i2c); +- +- if (entry->port_type < 6) { +- i2c->adapter.algo_data = &i2c->bit; +- i2c->bit.udelay = 40; +- i2c->bit.timeout = usecs_to_jiffies(5000); +- i2c->bit.data = i2c; +- ret = i2c_bit_add_bus(&i2c->adapter); +- } else { +- i2c->adapter.algo = &nouveau_dp_i2c_algo; +- ret = i2c_add_adapter(&i2c->adapter); +- } ++ if (ret) { ++ NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret); ++ kfree(port); ++ continue; ++ } + +- if (ret) { +- NV_ERROR(dev, "Failed to register i2c %d\n", index); +- kfree(i2c); +- return ret; ++ list_add_tail(&port->head, &dev_priv->i2c_ports); + } + +- entry->chan = i2c; + return 0; + } + + void +-nouveau_i2c_fini(struct drm_device *dev, struct dcb_i2c_entry *entry) ++nouveau_i2c_fini(struct drm_device *dev) + { +- if (!entry->chan) +- return; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_i2c_chan *port, *tmp; + +- i2c_del_adapter(&entry->chan->adapter); +- kfree(entry->chan); +- entry->chan = NULL; ++ list_for_each_entry_safe(port, tmp, &dev_priv->i2c_ports, head) { ++ i2c_del_adapter(&port->adapter); ++ kfree(port); ++ } + } + + struct nouveau_i2c_chan * +-nouveau_i2c_find(struct drm_device *dev, int index) ++nouveau_i2c_find(struct drm_device *dev, u8 index) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct dcb_i2c_entry *i2c = &dev_priv->vbios.dcb.i2c[index]; ++ struct nouveau_i2c_chan *port; ++ ++ if (index == NV_I2C_DEFAULT(0) || ++ index == NV_I2C_DEFAULT(1)) { ++ u8 version, *i2c = i2c_table(dev, &version); ++ if (i2c && version >= 0x30) { ++ if (index == NV_I2C_DEFAULT(0)) ++ index = (i2c[4] & 0x0f); ++ else ++ index = (i2c[4] & 0xf0) >> 4; ++ } else { ++ index = 2; ++ } ++ } + +- if (index >= DCB_MAX_NUM_I2C_ENTRIES) +- return NULL; ++ list_for_each_entry(port, &dev_priv->i2c_ports, head) { ++ if (port->index == index) ++ break; ++ } + +- if (dev_priv->card_type >= NV_50 && (i2c->entry & 0x00000100)) { +- uint32_t reg = 0xe500, val; ++ if (&port->head == &dev_priv->i2c_ports) ++ return NULL; + +- if (i2c->port_type == 6) { +- reg += i2c->read * 0x50; ++ if (dev_priv->card_type >= NV_50 && (port->dcb & 0x00000100)) { ++ u32 reg = 0x00e500, val; ++ if (port->type == 6) { ++ reg += port->drive * 0x50; + val = 0x2002; + } else { +- reg += ((i2c->entry & 0x1e00) >> 9) * 0x50; ++ reg += ((port->dcb & 0x1e00) >> 9) * 0x50; + val = 0xe001; + } + +@@ -294,9 +340,7 @@ nouveau_i2c_find(struct drm_device *dev, int index) + nv_mask(dev, reg + 0x00, 0x0000f003, val); + } + +- if (!i2c->chan && nouveau_i2c_init(dev, i2c, index)) +- return NULL; +- return i2c->chan; ++ return port; + } + + bool +@@ -331,9 +375,13 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what, + struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); + int i; + +- NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index); ++ if (!i2c) { ++ NV_DEBUG(dev, "No bus when probing %s on %d\n", what, index); ++ return -ENODEV; ++ } + +- for (i = 0; i2c && info[i].addr; i++) { ++ NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, i2c->index); ++ for (i = 0; info[i].addr; i++) { + if (nouveau_probe_i2c_addr(i2c, info[i].addr) && + (!match || match(i2c, &info[i]))) { + NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); +@@ -342,6 +390,5 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what, + } + + NV_DEBUG(dev, "No devices found.\n"); +- + return -ENODEV; + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h +index 422b62f..1d08389 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_i2c.h ++++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h +@@ -27,20 +27,26 @@ + #include + #include "drm_dp_helper.h" + +-struct dcb_i2c_entry; ++#define NV_I2C_PORT(n) (0x00 + (n)) ++#define NV_I2C_PORT_NUM 0x10 ++#define NV_I2C_DEFAULT(n) (0x80 + (n)) + + struct nouveau_i2c_chan { + struct i2c_adapter adapter; + struct drm_device *dev; + struct i2c_algo_bit_data bit; +- unsigned rd; +- unsigned wr; +- unsigned data; ++ struct list_head head; ++ u8 index; ++ u8 type; ++ u32 dcb; ++ u32 drive; ++ u32 sense; ++ u32 state; + }; + +-int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index); +-void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *); +-struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); ++int nouveau_i2c_init(struct drm_device *); ++void nouveau_i2c_fini(struct drm_device *); ++struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, u8 index); + bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); + int nouveau_i2c_identify(struct drm_device *dev, const char *what, + struct i2c_board_info *info, +diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c +index 36bec48..b08065f 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_mem.c ++++ b/drivers/gpu/drm/nouveau/nouveau_mem.c +@@ -26,7 +26,8 @@ + * DEALINGS IN THE SOFTWARE. + * + * Authors: +- * Keith Whitwell ++ * Ben Skeggs ++ * Roy Spliet + */ + + +@@ -192,75 +193,6 @@ nouveau_mem_gart_fini(struct drm_device *dev) + } + } + +-static uint32_t +-nouveau_mem_detect_nv04(struct drm_device *dev) +-{ +- uint32_t boot0 = nv_rd32(dev, NV04_PFB_BOOT_0); +- +- if (boot0 & 0x00000100) +- return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024; +- +- switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) { +- case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB: +- return 32 * 1024 * 1024; +- case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB: +- return 16 * 1024 * 1024; +- case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB: +- return 8 * 1024 * 1024; +- case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB: +- return 4 * 1024 * 1024; +- } +- +- return 0; +-} +- +-static uint32_t +-nouveau_mem_detect_nforce(struct drm_device *dev) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct pci_dev *bridge; +- uint32_t mem; +- +- bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); +- if (!bridge) { +- NV_ERROR(dev, "no bridge device\n"); +- return 0; +- } +- +- if (dev_priv->flags & NV_NFORCE) { +- pci_read_config_dword(bridge, 0x7C, &mem); +- return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024; +- } else +- if (dev_priv->flags & NV_NFORCE2) { +- pci_read_config_dword(bridge, 0x84, &mem); +- return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024; +- } +- +- NV_ERROR(dev, "impossible!\n"); +- return 0; +-} +- +-int +-nouveau_mem_detect(struct drm_device *dev) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- +- if (dev_priv->card_type == NV_04) { +- dev_priv->vram_size = nouveau_mem_detect_nv04(dev); +- } else +- if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) { +- dev_priv->vram_size = nouveau_mem_detect_nforce(dev); +- } else +- if (dev_priv->card_type < NV_50) { +- dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); +- dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; +- } +- +- if (dev_priv->vram_size) +- return 0; +- return -ENOMEM; +-} +- + bool + nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags) + { +@@ -385,11 +317,29 @@ nouveau_mem_init_agp(struct drm_device *dev) + return 0; + } + ++static const struct vram_types { ++ int value; ++ const char *name; ++} vram_type_map[] = { ++ { NV_MEM_TYPE_STOLEN , "stolen system memory" }, ++ { NV_MEM_TYPE_SGRAM , "SGRAM" }, ++ { NV_MEM_TYPE_SDRAM , "SDRAM" }, ++ { NV_MEM_TYPE_DDR1 , "DDR1" }, ++ { NV_MEM_TYPE_DDR2 , "DDR2" }, ++ { NV_MEM_TYPE_DDR3 , "DDR3" }, ++ { NV_MEM_TYPE_GDDR2 , "GDDR2" }, ++ { NV_MEM_TYPE_GDDR3 , "GDDR3" }, ++ { NV_MEM_TYPE_GDDR4 , "GDDR4" }, ++ { NV_MEM_TYPE_GDDR5 , "GDDR5" }, ++ { NV_MEM_TYPE_UNKNOWN, "unknown type" } ++}; ++ + int + nouveau_mem_vram_init(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; ++ const struct vram_types *vram_type; + int ret, dma_bits; + + dma_bits = 32; +@@ -407,6 +357,12 @@ nouveau_mem_vram_init(struct drm_device *dev) + ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); + if (ret) + return ret; ++ ret = pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); ++ if (ret) { ++ /* Reset to default value. */ ++ pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32)); ++ } ++ + + ret = nouveau_ttm_global_init(dev_priv); + if (ret) +@@ -421,7 +377,21 @@ nouveau_mem_vram_init(struct drm_device *dev) + return ret; + } + +- NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); ++ vram_type = vram_type_map; ++ while (vram_type->value != NV_MEM_TYPE_UNKNOWN) { ++ if (nouveau_vram_type) { ++ if (!strcasecmp(nouveau_vram_type, vram_type->name)) ++ break; ++ dev_priv->vram_type = vram_type->value; ++ } else { ++ if (vram_type->value == dev_priv->vram_type) ++ break; ++ } ++ vram_type++; ++ } ++ ++ NV_INFO(dev, "Detected %dMiB VRAM (%s)\n", ++ (int)(dev_priv->vram_size >> 20), vram_type->name); + if (dev_priv->vram_sys_base) { + NV_INFO(dev, "Stolen system memory at: 0x%010llx\n", + dev_priv->vram_sys_base); +@@ -502,216 +472,617 @@ nouveau_mem_gart_init(struct drm_device *dev) + return 0; + } + +-/* XXX: For now a dummy. More samples required, possibly even a card +- * Called from nouveau_perf.c */ +-void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, +- struct nouveau_pm_tbl_entry *e, uint8_t magic_number, +- struct nouveau_pm_memtiming *timing) { +- +- NV_DEBUG(dev,"Timing entry format unknown, please contact nouveau developers"); +-} +- +-void nv40_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, +- struct nouveau_pm_tbl_entry *e, uint8_t magic_number, +- struct nouveau_pm_memtiming *timing) { +- +- timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP); ++static int ++nv40_mem_timing_calc(struct drm_device *dev, u32 freq, ++ struct nouveau_pm_tbl_entry *e, u8 len, ++ struct nouveau_pm_memtiming *boot, ++ struct nouveau_pm_memtiming *t) ++{ ++ t->reg[0] = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC); + + /* XXX: I don't trust the -1's and +1's... they must come + * from somewhere! */ +- timing->reg_1 = (e->tWR + 2 + magic_number) << 24 | +- 1 << 16 | +- (e->tUNK_1 + 2 + magic_number) << 8 | +- (e->tCL + 2 - magic_number); +- timing->reg_2 = (magic_number << 24 | e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10); +- timing->reg_2 |= 0x20200000; +- +- NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", timing->id, +- timing->reg_0, timing->reg_1,timing->reg_2); ++ t->reg[1] = (e->tWR + 2 + (t->tCWL - 1)) << 24 | ++ 1 << 16 | ++ (e->tWTR + 2 + (t->tCWL - 1)) << 8 | ++ (e->tCL + 2 - (t->tCWL - 1)); ++ ++ t->reg[2] = 0x20200000 | ++ ((t->tCWL - 1) << 24 | ++ e->tRRD << 16 | ++ e->tRCDWR << 8 | ++ e->tRCDRD); ++ ++ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", t->id, ++ t->reg[0], t->reg[1], t->reg[2]); ++ return 0; + } + +-void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P, struct nouveau_pm_tbl_header *hdr, +- struct nouveau_pm_tbl_entry *e, uint8_t magic_number,struct nouveau_pm_memtiming *timing) { ++static int ++nv50_mem_timing_calc(struct drm_device *dev, u32 freq, ++ struct nouveau_pm_tbl_entry *e, u8 len, ++ struct nouveau_pm_memtiming *boot, ++ struct nouveau_pm_memtiming *t) ++{ + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct bit_entry P; ++ uint8_t unk18 = 1, unk20 = 0, unk21 = 0, tmp7_3; + +- uint8_t unk18 = 1, +- unk19 = 1, +- unk20 = 0, +- unk21 = 0; ++ if (bit_table(dev, 'P', &P)) ++ return -EINVAL; + +- switch (min(hdr->entry_len, (u8) 22)) { ++ switch (min(len, (u8) 22)) { + case 22: + unk21 = e->tUNK_21; + case 21: + unk20 = e->tUNK_20; + case 20: +- unk19 = e->tUNK_19; ++ if (e->tCWL > 0) ++ t->tCWL = e->tCWL; + case 19: + unk18 = e->tUNK_18; + break; + } + +- timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP); ++ t->reg[0] = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC); + +- /* XXX: I don't trust the -1's and +1's... they must come +- * from somewhere! */ +- timing->reg_1 = (e->tWR + unk19 + 1 + magic_number) << 24 | +- max(unk18, (u8) 1) << 16 | +- (e->tUNK_1 + unk19 + 1 + magic_number) << 8; +- if (dev_priv->chipset == 0xa8) { +- timing->reg_1 |= (e->tCL - 1); +- } else { +- timing->reg_1 |= (e->tCL + 2 - magic_number); +- } +- timing->reg_2 = (e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10); +- +- timing->reg_5 = (e->tRAS << 24 | e->tRC); +- timing->reg_5 += max(e->tUNK_10, e->tUNK_11) << 16; +- +- if (P->version == 1) { +- timing->reg_2 |= magic_number << 24; +- timing->reg_3 = (0x14 + e->tCL) << 24 | +- 0x16 << 16 | +- (e->tCL - 1) << 8 | +- (e->tCL - 1); +- timing->reg_4 = (nv_rd32(dev,0x10022c) & 0xffff0000) | e->tUNK_13 << 8 | e->tUNK_13; +- timing->reg_5 |= (e->tCL + 2) << 8; +- timing->reg_7 = 0x4000202 | (e->tCL - 1) << 16; ++ t->reg[1] = (e->tWR + 2 + (t->tCWL - 1)) << 24 | ++ max(unk18, (u8) 1) << 16 | ++ (e->tWTR + 2 + (t->tCWL - 1)) << 8; ++ ++ t->reg[2] = ((t->tCWL - 1) << 24 | ++ e->tRRD << 16 | ++ e->tRCDWR << 8 | ++ e->tRCDRD); ++ ++ t->reg[4] = e->tUNK_13 << 8 | e->tUNK_13; ++ ++ t->reg[5] = (e->tRFC << 24 | max(e->tRCDRD, e->tRCDWR) << 16 | e->tRP); ++ ++ t->reg[8] = boot->reg[8] & 0xffffff00; ++ ++ if (P.version == 1) { ++ t->reg[1] |= (e->tCL + 2 - (t->tCWL - 1)); ++ ++ t->reg[3] = (0x14 + e->tCL) << 24 | ++ 0x16 << 16 | ++ (e->tCL - 1) << 8 | ++ (e->tCL - 1); ++ ++ t->reg[4] |= boot->reg[4] & 0xffff0000; ++ ++ t->reg[6] = (0x33 - t->tCWL) << 16 | ++ t->tCWL << 8 | ++ (0x2e + e->tCL - t->tCWL); ++ ++ t->reg[7] = 0x4000202 | (e->tCL - 1) << 16; ++ ++ /* XXX: P.version == 1 only has DDR2 and GDDR3? */ ++ if (dev_priv->vram_type == NV_MEM_TYPE_DDR2) { ++ t->reg[5] |= (e->tCL + 3) << 8; ++ t->reg[6] |= (t->tCWL - 2) << 8; ++ t->reg[8] |= (e->tCL - 4); ++ } else { ++ t->reg[5] |= (e->tCL + 2) << 8; ++ t->reg[6] |= t->tCWL << 8; ++ t->reg[8] |= (e->tCL - 2); ++ } + } else { +- timing->reg_2 |= (unk19 - 1) << 24; +- /* XXX: reg_10022c for recentish cards pretty much unknown*/ +- timing->reg_3 = e->tCL - 1; +- timing->reg_4 = (unk20 << 24 | unk21 << 16 | +- e->tUNK_13 << 8 | e->tUNK_13); ++ t->reg[1] |= (5 + e->tCL - (t->tCWL)); ++ ++ /* XXX: 0xb? 0x30? */ ++ t->reg[3] = (0x30 + e->tCL) << 24 | ++ (boot->reg[3] & 0x00ff0000)| ++ (0xb + e->tCL) << 8 | ++ (e->tCL - 1); ++ ++ t->reg[4] |= (unk20 << 24 | unk21 << 16); ++ + /* XXX: +6? */ +- timing->reg_5 |= (unk19 + 6) << 8; ++ t->reg[5] |= (t->tCWL + 6) << 8; + +- /* XXX: reg_10023c currently unknown +- * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */ +- timing->reg_7 = 0x202; ++ t->reg[6] = (0x5a + e->tCL) << 16 | ++ (6 - e->tCL + t->tCWL) << 8 | ++ (0x50 + e->tCL - t->tCWL); ++ ++ tmp7_3 = (boot->reg[7] & 0xff000000) >> 24; ++ t->reg[7] = (tmp7_3 << 24) | ++ ((tmp7_3 - 6 + e->tCL) << 16) | ++ 0x202; + } + +- NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", timing->id, +- timing->reg_0, timing->reg_1, +- timing->reg_2, timing->reg_3); ++ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", t->id, ++ t->reg[0], t->reg[1], t->reg[2], t->reg[3]); + NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", +- timing->reg_4, timing->reg_5, +- timing->reg_6, timing->reg_7); +- NV_DEBUG(dev, " 240: %08x\n", timing->reg_8); +-} +- +-void nvc0_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, +- struct nouveau_pm_tbl_entry *e, struct nouveau_pm_memtiming *timing) { +- timing->reg_0 = (e->tRC << 24 | (e->tRFC & 0x7f) << 17 | e->tRAS << 8 | e->tRP); +- timing->reg_1 = (nv_rd32(dev,0x10f294) & 0xff000000) | (e->tUNK_11&0x0f) << 20 | (e->tUNK_19 << 7) | (e->tCL & 0x0f); +- timing->reg_2 = (nv_rd32(dev,0x10f298) & 0xff0000ff) | e->tWR << 16 | e->tUNK_1 << 8; +- timing->reg_3 = e->tUNK_20 << 9 | e->tUNK_13; +- timing->reg_4 = (nv_rd32(dev,0x10f2a0) & 0xfff000ff) | e->tUNK_12 << 15; +- NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", timing->id, +- timing->reg_0, timing->reg_1, +- timing->reg_2, timing->reg_3); +- NV_DEBUG(dev, " 2a0: %08x %08x %08x %08x\n", +- timing->reg_4, timing->reg_5, +- timing->reg_6, timing->reg_7); ++ t->reg[4], t->reg[5], t->reg[6], t->reg[7]); ++ NV_DEBUG(dev, " 240: %08x\n", t->reg[8]); ++ return 0; ++} ++ ++static int ++nvc0_mem_timing_calc(struct drm_device *dev, u32 freq, ++ struct nouveau_pm_tbl_entry *e, u8 len, ++ struct nouveau_pm_memtiming *boot, ++ struct nouveau_pm_memtiming *t) ++{ ++ if (e->tCWL > 0) ++ t->tCWL = e->tCWL; ++ ++ t->reg[0] = (e->tRP << 24 | (e->tRAS & 0x7f) << 17 | ++ e->tRFC << 8 | e->tRC); ++ ++ t->reg[1] = (boot->reg[1] & 0xff000000) | ++ (e->tRCDWR & 0x0f) << 20 | ++ (e->tRCDRD & 0x0f) << 14 | ++ (t->tCWL << 7) | ++ (e->tCL & 0x0f); ++ ++ t->reg[2] = (boot->reg[2] & 0xff0000ff) | ++ e->tWR << 16 | e->tWTR << 8; ++ ++ t->reg[3] = (e->tUNK_20 & 0x1f) << 9 | ++ (e->tUNK_21 & 0xf) << 5 | ++ (e->tUNK_13 & 0x1f); ++ ++ t->reg[4] = (boot->reg[4] & 0xfff00fff) | ++ (e->tRRD&0x1f) << 15; ++ ++ NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", t->id, ++ t->reg[0], t->reg[1], t->reg[2], t->reg[3]); ++ NV_DEBUG(dev, " 2a0: %08x\n", t->reg[4]); ++ return 0; + } + + /** +- * Processes the Memory Timing BIOS table, stores generated +- * register values +- * @pre init scripts were run, memtiming regs are initialized ++ * MR generation methods + */ +-void +-nouveau_mem_timing_init(struct drm_device *dev) ++ ++static int ++nouveau_mem_ddr2_mr(struct drm_device *dev, u32 freq, ++ struct nouveau_pm_tbl_entry *e, u8 len, ++ struct nouveau_pm_memtiming *boot, ++ struct nouveau_pm_memtiming *t) ++{ ++ t->drive_strength = 0; ++ if (len < 15) { ++ t->odt = boot->odt; ++ } else { ++ t->odt = e->RAM_FT1 & 0x07; ++ } ++ ++ if (e->tCL >= NV_MEM_CL_DDR2_MAX) { ++ NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL); ++ return -ERANGE; ++ } ++ ++ if (e->tWR >= NV_MEM_WR_DDR2_MAX) { ++ NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR); ++ return -ERANGE; ++ } ++ ++ if (t->odt > 3) { ++ NV_WARN(dev, "(%u) Invalid odt value, assuming disabled: %x", ++ t->id, t->odt); ++ t->odt = 0; ++ } ++ ++ t->mr[0] = (boot->mr[0] & 0x100f) | ++ (e->tCL) << 4 | ++ (e->tWR - 1) << 9; ++ t->mr[1] = (boot->mr[1] & 0x101fbb) | ++ (t->odt & 0x1) << 2 | ++ (t->odt & 0x2) << 5; ++ ++ NV_DEBUG(dev, "(%u) MR: %08x", t->id, t->mr[0]); ++ return 0; ++} ++ ++uint8_t nv_mem_wr_lut_ddr3[NV_MEM_WR_DDR3_MAX] = { ++ 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0}; ++ ++static int ++nouveau_mem_ddr3_mr(struct drm_device *dev, u32 freq, ++ struct nouveau_pm_tbl_entry *e, u8 len, ++ struct nouveau_pm_memtiming *boot, ++ struct nouveau_pm_memtiming *t) ++{ ++ u8 cl = e->tCL - 4; ++ ++ t->drive_strength = 0; ++ if (len < 15) { ++ t->odt = boot->odt; ++ } else { ++ t->odt = e->RAM_FT1 & 0x07; ++ } ++ ++ if (e->tCL >= NV_MEM_CL_DDR3_MAX || e->tCL < 4) { ++ NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL); ++ return -ERANGE; ++ } ++ ++ if (e->tWR >= NV_MEM_WR_DDR3_MAX || e->tWR < 4) { ++ NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR); ++ return -ERANGE; ++ } ++ ++ if (e->tCWL < 5) { ++ NV_WARN(dev, "(%u) Invalid tCWL: %u", t->id, e->tCWL); ++ return -ERANGE; ++ } ++ ++ t->mr[0] = (boot->mr[0] & 0x180b) | ++ /* CAS */ ++ (cl & 0x7) << 4 | ++ (cl & 0x8) >> 1 | ++ (nv_mem_wr_lut_ddr3[e->tWR]) << 9; ++ t->mr[1] = (boot->mr[1] & 0x101dbb) | ++ (t->odt & 0x1) << 2 | ++ (t->odt & 0x2) << 5 | ++ (t->odt & 0x4) << 7; ++ t->mr[2] = (boot->mr[2] & 0x20ffb7) | (e->tCWL - 5) << 3; ++ ++ NV_DEBUG(dev, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[2]); ++ return 0; ++} ++ ++uint8_t nv_mem_cl_lut_gddr3[NV_MEM_CL_GDDR3_MAX] = { ++ 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3, 8, 9, 10, 11}; ++uint8_t nv_mem_wr_lut_gddr3[NV_MEM_WR_GDDR3_MAX] = { ++ 0, 0, 0, 0, 0, 2, 3, 8, 9, 10, 11, 0, 0, 1, 1, 0, 3}; ++ ++static int ++nouveau_mem_gddr3_mr(struct drm_device *dev, u32 freq, ++ struct nouveau_pm_tbl_entry *e, u8 len, ++ struct nouveau_pm_memtiming *boot, ++ struct nouveau_pm_memtiming *t) ++{ ++ if (len < 15) { ++ t->drive_strength = boot->drive_strength; ++ t->odt = boot->odt; ++ } else { ++ t->drive_strength = (e->RAM_FT1 & 0x30) >> 4; ++ t->odt = e->RAM_FT1 & 0x07; ++ } ++ ++ if (e->tCL >= NV_MEM_CL_GDDR3_MAX) { ++ NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL); ++ return -ERANGE; ++ } ++ ++ if (e->tWR >= NV_MEM_WR_GDDR3_MAX) { ++ NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR); ++ return -ERANGE; ++ } ++ ++ if (t->odt > 3) { ++ NV_WARN(dev, "(%u) Invalid odt value, assuming autocal: %x", ++ t->id, t->odt); ++ t->odt = 0; ++ } ++ ++ t->mr[0] = (boot->mr[0] & 0xe0b) | ++ /* CAS */ ++ ((nv_mem_cl_lut_gddr3[e->tCL] & 0x7) << 4) | ++ ((nv_mem_cl_lut_gddr3[e->tCL] & 0x8) >> 2); ++ t->mr[1] = (boot->mr[1] & 0x100f40) | t->drive_strength | ++ (t->odt << 2) | ++ (nv_mem_wr_lut_gddr3[e->tWR] & 0xf) << 4; ++ t->mr[2] = boot->mr[2]; ++ ++ NV_DEBUG(dev, "(%u) MR: %08x %08x %08x", t->id, ++ t->mr[0], t->mr[1], t->mr[2]); ++ return 0; ++} ++ ++static int ++nouveau_mem_gddr5_mr(struct drm_device *dev, u32 freq, ++ struct nouveau_pm_tbl_entry *e, u8 len, ++ struct nouveau_pm_memtiming *boot, ++ struct nouveau_pm_memtiming *t) ++{ ++ if (len < 15) { ++ t->drive_strength = boot->drive_strength; ++ t->odt = boot->odt; ++ } else { ++ t->drive_strength = (e->RAM_FT1 & 0x30) >> 4; ++ t->odt = e->RAM_FT1 & 0x03; ++ } ++ ++ if (e->tCL >= NV_MEM_CL_GDDR5_MAX) { ++ NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL); ++ return -ERANGE; ++ } ++ ++ if (e->tWR >= NV_MEM_WR_GDDR5_MAX) { ++ NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR); ++ return -ERANGE; ++ } ++ ++ if (t->odt > 3) { ++ NV_WARN(dev, "(%u) Invalid odt value, assuming autocal: %x", ++ t->id, t->odt); ++ t->odt = 0; ++ } ++ ++ t->mr[0] = (boot->mr[0] & 0x007) | ++ ((e->tCL - 5) << 3) | ++ ((e->tWR - 4) << 8); ++ t->mr[1] = (boot->mr[1] & 0x1007f0) | ++ t->drive_strength | ++ (t->odt << 2); ++ ++ NV_DEBUG(dev, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[1]); ++ return 0; ++} ++ ++int ++nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, ++ struct nouveau_pm_memtiming *t) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; +- struct nouveau_pm_memtimings *memtimings = &pm->memtimings; +- struct nvbios *bios = &dev_priv->vbios; +- struct bit_entry P; +- struct nouveau_pm_tbl_header *hdr = NULL; +- uint8_t magic_number; +- u8 *entry; +- int i; ++ struct nouveau_pm_memtiming *boot = &pm->boot.timing; ++ struct nouveau_pm_tbl_entry *e; ++ u8 ver, len, *ptr, *ramcfg; ++ int ret; ++ ++ ptr = nouveau_perf_timing(dev, freq, &ver, &len); ++ if (!ptr || ptr[0] == 0x00) { ++ *t = *boot; ++ return 0; ++ } ++ e = (struct nouveau_pm_tbl_entry *)ptr; ++ ++ t->tCWL = boot->tCWL; ++ ++ switch (dev_priv->card_type) { ++ case NV_40: ++ ret = nv40_mem_timing_calc(dev, freq, e, len, boot, t); ++ break; ++ case NV_50: ++ ret = nv50_mem_timing_calc(dev, freq, e, len, boot, t); ++ break; ++ case NV_C0: ++ ret = nvc0_mem_timing_calc(dev, freq, e, len, boot, t); ++ break; ++ default: ++ ret = -ENODEV; ++ break; ++ } + +- if (bios->type == NVBIOS_BIT) { +- if (bit_table(dev, 'P', &P)) +- return; ++ switch (dev_priv->vram_type * !ret) { ++ case NV_MEM_TYPE_GDDR3: ++ ret = nouveau_mem_gddr3_mr(dev, freq, e, len, boot, t); ++ break; ++ case NV_MEM_TYPE_GDDR5: ++ ret = nouveau_mem_gddr5_mr(dev, freq, e, len, boot, t); ++ break; ++ case NV_MEM_TYPE_DDR2: ++ ret = nouveau_mem_ddr2_mr(dev, freq, e, len, boot, t); ++ break; ++ case NV_MEM_TYPE_DDR3: ++ ret = nouveau_mem_ddr3_mr(dev, freq, e, len, boot, t); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } + +- if (P.version == 1) +- hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[4]); ++ ramcfg = nouveau_perf_ramcfg(dev, freq, &ver, &len); ++ if (ramcfg) { ++ int dll_off; ++ ++ if (ver == 0x00) ++ dll_off = !!(ramcfg[3] & 0x04); + else +- if (P.version == 2) +- hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[8]); +- else { +- NV_WARN(dev, "unknown mem for BIT P %d\n", P.version); ++ dll_off = !!(ramcfg[2] & 0x40); ++ ++ switch (dev_priv->vram_type) { ++ case NV_MEM_TYPE_GDDR3: ++ t->mr[1] &= ~0x00000040; ++ t->mr[1] |= 0x00000040 * dll_off; ++ break; ++ default: ++ t->mr[1] &= ~0x00000001; ++ t->mr[1] |= 0x00000001 * dll_off; ++ break; + } ++ } ++ ++ return ret; ++} ++ ++void ++nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 timing_base, timing_regs, mr_base; ++ int i; ++ ++ if (dev_priv->card_type >= 0xC0) { ++ timing_base = 0x10f290; ++ mr_base = 0x10f300; + } else { +- NV_DEBUG(dev, "BMP version too old for memory\n"); +- return; ++ timing_base = 0x100220; ++ mr_base = 0x1002c0; + } + +- if (!hdr) { +- NV_DEBUG(dev, "memory timing table pointer invalid\n"); ++ t->id = -1; ++ ++ switch (dev_priv->card_type) { ++ case NV_50: ++ timing_regs = 9; ++ break; ++ case NV_C0: ++ case NV_D0: ++ timing_regs = 5; ++ break; ++ case NV_30: ++ case NV_40: ++ timing_regs = 3; ++ break; ++ default: ++ timing_regs = 0; + return; + } ++ for(i = 0; i < timing_regs; i++) ++ t->reg[i] = nv_rd32(dev, timing_base + (0x04 * i)); ++ ++ t->tCWL = 0; ++ if (dev_priv->card_type < NV_C0) { ++ t->tCWL = ((nv_rd32(dev, 0x100228) & 0x0f000000) >> 24) + 1; ++ } else if (dev_priv->card_type <= NV_D0) { ++ t->tCWL = ((nv_rd32(dev, 0x10f294) & 0x00000f80) >> 7); ++ } + +- if (hdr->version != 0x10) { +- NV_WARN(dev, "memory timing table 0x%02x unknown\n", hdr->version); +- return; ++ t->mr[0] = nv_rd32(dev, mr_base); ++ t->mr[1] = nv_rd32(dev, mr_base + 0x04); ++ t->mr[2] = nv_rd32(dev, mr_base + 0x20); ++ t->mr[3] = nv_rd32(dev, mr_base + 0x24); ++ ++ t->odt = 0; ++ t->drive_strength = 0; ++ ++ switch (dev_priv->vram_type) { ++ case NV_MEM_TYPE_DDR3: ++ t->odt |= (t->mr[1] & 0x200) >> 7; ++ case NV_MEM_TYPE_DDR2: ++ t->odt |= (t->mr[1] & 0x04) >> 2 | ++ (t->mr[1] & 0x40) >> 5; ++ break; ++ case NV_MEM_TYPE_GDDR3: ++ case NV_MEM_TYPE_GDDR5: ++ t->drive_strength = t->mr[1] & 0x03; ++ t->odt = (t->mr[1] & 0x0c) >> 2; ++ break; ++ default: ++ break; + } ++} + +- /* validate record length */ +- if (hdr->entry_len < 15) { +- NV_ERROR(dev, "mem timing table length unknown: %d\n", hdr->entry_len); +- return; ++int ++nouveau_mem_exec(struct nouveau_mem_exec_func *exec, ++ struct nouveau_pm_level *perflvl) ++{ ++ struct drm_nouveau_private *dev_priv = exec->dev->dev_private; ++ struct nouveau_pm_memtiming *info = &perflvl->timing; ++ u32 tMRD = 1000, tCKSRE = 0, tCKSRX = 0, tXS = 0, tDLLK = 0; ++ u32 mr[3] = { info->mr[0], info->mr[1], info->mr[2] }; ++ u32 mr1_dlloff; ++ ++ switch (dev_priv->vram_type) { ++ case NV_MEM_TYPE_DDR2: ++ tDLLK = 2000; ++ mr1_dlloff = 0x00000001; ++ break; ++ case NV_MEM_TYPE_DDR3: ++ tDLLK = 12000; ++ mr1_dlloff = 0x00000001; ++ break; ++ case NV_MEM_TYPE_GDDR3: ++ tDLLK = 40000; ++ mr1_dlloff = 0x00000040; ++ break; ++ default: ++ NV_ERROR(exec->dev, "cannot reclock unsupported memtype\n"); ++ return -ENODEV; + } + +- /* parse vbios entries into common format */ +- memtimings->timing = +- kcalloc(hdr->entry_cnt, sizeof(*memtimings->timing), GFP_KERNEL); +- if (!memtimings->timing) +- return; ++ /* fetch current MRs */ ++ switch (dev_priv->vram_type) { ++ case NV_MEM_TYPE_GDDR3: ++ case NV_MEM_TYPE_DDR3: ++ mr[2] = exec->mrg(exec, 2); ++ default: ++ mr[1] = exec->mrg(exec, 1); ++ mr[0] = exec->mrg(exec, 0); ++ break; ++ } + +- /* Get "some number" from the timing reg for NV_40 and NV_50 +- * Used in calculations later... source unknown */ +- magic_number = 0; +- if (P.version == 1) { +- magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24; ++ /* DLL 'on' -> DLL 'off' mode, disable before entering self-refresh */ ++ if (!(mr[1] & mr1_dlloff) && (info->mr[1] & mr1_dlloff)) { ++ exec->precharge(exec); ++ exec->mrs (exec, 1, mr[1] | mr1_dlloff); ++ exec->wait(exec, tMRD); + } + +- entry = (u8*) hdr + hdr->header_len; +- for (i = 0; i < hdr->entry_cnt; i++, entry += hdr->entry_len) { +- struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i]; +- if (entry[0] == 0) +- continue; ++ /* enter self-refresh mode */ ++ exec->precharge(exec); ++ exec->refresh(exec); ++ exec->refresh(exec); ++ exec->refresh_auto(exec, false); ++ exec->refresh_self(exec, true); ++ exec->wait(exec, tCKSRE); ++ ++ /* modify input clock frequency */ ++ exec->clock_set(exec); ++ ++ /* exit self-refresh mode */ ++ exec->wait(exec, tCKSRX); ++ exec->precharge(exec); ++ exec->refresh_self(exec, false); ++ exec->refresh_auto(exec, true); ++ exec->wait(exec, tXS); ++ ++ /* update MRs */ ++ if (mr[2] != info->mr[2]) { ++ exec->mrs (exec, 2, info->mr[2]); ++ exec->wait(exec, tMRD); ++ } ++ ++ if (mr[1] != info->mr[1]) { ++ /* need to keep DLL off until later, at least on GDDR3 */ ++ exec->mrs (exec, 1, info->mr[1] | (mr[1] & mr1_dlloff)); ++ exec->wait(exec, tMRD); ++ } ++ ++ if (mr[0] != info->mr[0]) { ++ exec->mrs (exec, 0, info->mr[0]); ++ exec->wait(exec, tMRD); ++ } + +- timing->id = i; +- timing->WR = entry[0]; +- timing->CL = entry[2]; ++ /* update PFB timing registers */ ++ exec->timing_set(exec); + +- if(dev_priv->card_type <= NV_40) { +- nv40_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]); +- } else if(dev_priv->card_type == NV_50){ +- nv50_mem_timing_entry(dev,&P,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]); +- } else if(dev_priv->card_type == NV_C0) { +- nvc0_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,&pm->memtimings.timing[i]); ++ /* DLL (enable + ) reset */ ++ if (!(info->mr[1] & mr1_dlloff)) { ++ if (mr[1] & mr1_dlloff) { ++ exec->mrs (exec, 1, info->mr[1]); ++ exec->wait(exec, tMRD); + } ++ exec->mrs (exec, 0, info->mr[0] | 0x00000100); ++ exec->wait(exec, tMRD); ++ exec->mrs (exec, 0, info->mr[0] | 0x00000000); ++ exec->wait(exec, tMRD); ++ exec->wait(exec, tDLLK); ++ if (dev_priv->vram_type == NV_MEM_TYPE_GDDR3) ++ exec->precharge(exec); + } + +- memtimings->nr_timing = hdr->entry_cnt; +- memtimings->supported = P.version == 1; ++ return 0; + } + +-void +-nouveau_mem_timing_fini(struct drm_device *dev) ++int ++nouveau_mem_vbios_type(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_pm_memtimings *mem = &dev_priv->engine.pm.memtimings; ++ struct bit_entry M; ++ u8 ramcfg = (nv_rd32(dev, 0x101000) & 0x0000003c) >> 2; ++ if (!bit_table(dev, 'M', &M) || M.version != 2 || M.length < 5) { ++ u8 *table = ROMPTR(dev, M.data[3]); ++ if (table && table[0] == 0x10 && ramcfg < table[3]) { ++ u8 *entry = table + table[1] + (ramcfg * table[2]); ++ switch (entry[0] & 0x0f) { ++ case 0: return NV_MEM_TYPE_DDR2; ++ case 1: return NV_MEM_TYPE_DDR3; ++ case 2: return NV_MEM_TYPE_GDDR3; ++ case 3: return NV_MEM_TYPE_GDDR5; ++ default: ++ break; ++ } + +- if(mem->timing) { +- kfree(mem->timing); +- mem->timing = NULL; ++ } + } ++ return NV_MEM_TYPE_UNKNOWN; + } + + static int +diff --git a/drivers/gpu/drm/nouveau/nouveau_mxm.c b/drivers/gpu/drm/nouveau/nouveau_mxm.c +new file mode 100644 +index 0000000..07d0d1e +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nouveau_mxm.c +@@ -0,0 +1,723 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ * ++ * Authors: Ben Skeggs ++ */ ++ ++#include ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++ ++#define MXM_DBG(dev, fmt, args...) NV_DEBUG((dev), "MXM: " fmt, ##args) ++#define MXM_MSG(dev, fmt, args...) NV_INFO((dev), "MXM: " fmt, ##args) ++ ++static u8 * ++mxms_data(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ return dev_priv->mxms; ++ ++} ++ ++static u16 ++mxms_version(struct drm_device *dev) ++{ ++ u8 *mxms = mxms_data(dev); ++ u16 version = (mxms[4] << 8) | mxms[5]; ++ switch (version ) { ++ case 0x0200: ++ case 0x0201: ++ case 0x0300: ++ return version; ++ default: ++ break; ++ } ++ ++ MXM_DBG(dev, "unknown version %d.%d\n", mxms[4], mxms[5]); ++ return 0x0000; ++} ++ ++static u16 ++mxms_headerlen(struct drm_device *dev) ++{ ++ return 8; ++} ++ ++static u16 ++mxms_structlen(struct drm_device *dev) ++{ ++ return *(u16 *)&mxms_data(dev)[6]; ++} ++ ++static bool ++mxms_checksum(struct drm_device *dev) ++{ ++ u16 size = mxms_headerlen(dev) + mxms_structlen(dev); ++ u8 *mxms = mxms_data(dev), sum = 0; ++ while (size--) ++ sum += *mxms++; ++ if (sum) { ++ MXM_DBG(dev, "checksum invalid\n"); ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mxms_valid(struct drm_device *dev) ++{ ++ u8 *mxms = mxms_data(dev); ++ if (*(u32 *)mxms != 0x5f4d584d) { ++ MXM_DBG(dev, "signature invalid\n"); ++ return false; ++ } ++ ++ if (!mxms_version(dev) || !mxms_checksum(dev)) ++ return false; ++ ++ return true; ++} ++ ++static bool ++mxms_foreach(struct drm_device *dev, u8 types, ++ bool (*exec)(struct drm_device *, u8 *, void *), void *info) ++{ ++ u8 *mxms = mxms_data(dev); ++ u8 *desc = mxms + mxms_headerlen(dev); ++ u8 *fini = desc + mxms_structlen(dev) - 1; ++ while (desc < fini) { ++ u8 type = desc[0] & 0x0f; ++ u8 headerlen = 0; ++ u8 recordlen = 0; ++ u8 entries = 0; ++ ++ switch (type) { ++ case 0: /* Output Device Structure */ ++ if (mxms_version(dev) >= 0x0300) ++ headerlen = 8; ++ else ++ headerlen = 6; ++ break; ++ case 1: /* System Cooling Capability Structure */ ++ case 2: /* Thermal Structure */ ++ case 3: /* Input Power Structure */ ++ headerlen = 4; ++ break; ++ case 4: /* GPIO Device Structure */ ++ headerlen = 4; ++ recordlen = 2; ++ entries = (ROM32(desc[0]) & 0x01f00000) >> 20; ++ break; ++ case 5: /* Vendor Specific Structure */ ++ headerlen = 8; ++ break; ++ case 6: /* Backlight Control Structure */ ++ if (mxms_version(dev) >= 0x0300) { ++ headerlen = 4; ++ recordlen = 8; ++ entries = (desc[1] & 0xf0) >> 4; ++ } else { ++ headerlen = 8; ++ } ++ break; ++ case 7: /* Fan Control Structure */ ++ headerlen = 8; ++ recordlen = 4; ++ entries = desc[1] & 0x07; ++ break; ++ default: ++ MXM_DBG(dev, "unknown descriptor type %d\n", type); ++ return false; ++ } ++ ++ if ((drm_debug & DRM_UT_DRIVER) && (exec == NULL)) { ++ static const char * mxms_desc_name[] = { ++ "ODS", "SCCS", "TS", "IPS", ++ "GSD", "VSS", "BCS", "FCS", ++ }; ++ u8 *dump = desc; ++ int i, j; ++ ++ MXM_DBG(dev, "%4s: ", mxms_desc_name[type]); ++ for (j = headerlen - 1; j >= 0; j--) ++ printk("%02x", dump[j]); ++ printk("\n"); ++ dump += headerlen; ++ ++ for (i = 0; i < entries; i++, dump += recordlen) { ++ MXM_DBG(dev, " "); ++ for (j = recordlen - 1; j >= 0; j--) ++ printk("%02x", dump[j]); ++ printk("\n"); ++ } ++ } ++ ++ if (types & (1 << type)) { ++ if (!exec(dev, desc, info)) ++ return false; ++ } ++ ++ desc += headerlen + (entries * recordlen); ++ } ++ ++ return true; ++} ++ ++static u8 * ++mxm_table(struct drm_device *dev, u8 *size) ++{ ++ struct bit_entry x; ++ ++ if (bit_table(dev, 'x', &x)) { ++ MXM_DBG(dev, "BIT 'x' table not present\n"); ++ return NULL; ++ } ++ ++ if (x.version != 1 || x.length < 3) { ++ MXM_MSG(dev, "BIT x table %d/%d unknown\n", ++ x.version, x.length); ++ return NULL; ++ } ++ ++ *size = x.length; ++ return x.data; ++} ++ ++/* These map MXM v2.x digital connection values to the appropriate SOR/link, ++ * hopefully they're correct for all boards within the same chipset... ++ * ++ * MXM v3.x VBIOS are nicer and provide pointers to these tables. ++ */ ++static u8 nv84_sor_map[16] = { ++ 0x00, 0x12, 0x22, 0x11, 0x32, 0x31, 0x11, 0x31, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++}; ++ ++static u8 nv92_sor_map[16] = { ++ 0x00, 0x12, 0x22, 0x11, 0x32, 0x31, 0x11, 0x31, ++ 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++}; ++ ++static u8 nv94_sor_map[16] = { ++ 0x00, 0x14, 0x24, 0x11, 0x34, 0x31, 0x11, 0x31, ++ 0x11, 0x31, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00 ++}; ++ ++static u8 nv96_sor_map[16] = { ++ 0x00, 0x14, 0x24, 0x00, 0x34, 0x00, 0x11, 0x31, ++ 0x11, 0x31, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00 ++}; ++ ++static u8 nv98_sor_map[16] = { ++ 0x00, 0x14, 0x12, 0x11, 0x00, 0x31, 0x11, 0x31, ++ 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++}; ++ ++static u8 ++mxm_sor_map(struct drm_device *dev, u8 conn) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u8 len, *mxm = mxm_table(dev, &len); ++ if (mxm && len >= 6) { ++ u8 *map = ROMPTR(dev, mxm[4]); ++ if (map) { ++ if (map[0] == 0x10) { ++ if (conn < map[3]) ++ return map[map[1] + conn]; ++ return 0x00; ++ } ++ ++ MXM_MSG(dev, "unknown sor map 0x%02x\n", map[0]); ++ } ++ } ++ ++ if (dev_priv->chipset == 0x84 || dev_priv->chipset == 0x86) ++ return nv84_sor_map[conn]; ++ if (dev_priv->chipset == 0x92) ++ return nv92_sor_map[conn]; ++ if (dev_priv->chipset == 0x94) ++ return nv94_sor_map[conn]; ++ if (dev_priv->chipset == 0x96) ++ return nv96_sor_map[conn]; ++ if (dev_priv->chipset == 0x98) ++ return nv98_sor_map[conn]; ++ ++ MXM_MSG(dev, "missing sor map\n"); ++ return 0x00; ++} ++ ++static u8 ++mxm_ddc_map(struct drm_device *dev, u8 port) ++{ ++ u8 len, *mxm = mxm_table(dev, &len); ++ if (mxm && len >= 8) { ++ u8 *map = ROMPTR(dev, mxm[6]); ++ if (map) { ++ if (map[0] == 0x10) { ++ if (port < map[3]) ++ return map[map[1] + port]; ++ return 0x00; ++ } ++ ++ MXM_MSG(dev, "unknown ddc map 0x%02x\n", map[0]); ++ } ++ } ++ ++ /* v2.x: directly write port as dcb i2cidx */ ++ return (port << 4) | port; ++} ++ ++struct mxms_odev { ++ u8 outp_type; ++ u8 conn_type; ++ u8 ddc_port; ++ u8 dig_conn; ++}; ++ ++static void ++mxms_output_device(struct drm_device *dev, u8 *pdata, struct mxms_odev *desc) ++{ ++ u64 data = ROM32(pdata[0]); ++ if (mxms_version(dev) >= 0x0300) ++ data |= (u64)ROM16(pdata[4]) << 32; ++ ++ desc->outp_type = (data & 0x00000000000000f0ULL) >> 4; ++ desc->ddc_port = (data & 0x0000000000000f00ULL) >> 8; ++ desc->conn_type = (data & 0x000000000001f000ULL) >> 12; ++ desc->dig_conn = (data & 0x0000000000780000ULL) >> 19; ++} ++ ++struct context { ++ u32 *outp; ++ struct mxms_odev desc; ++}; ++ ++static bool ++mxm_match_tmds_partner(struct drm_device *dev, u8 *data, void *info) ++{ ++ struct context *ctx = info; ++ struct mxms_odev desc; ++ ++ mxms_output_device(dev, data, &desc); ++ if (desc.outp_type == 2 && ++ desc.dig_conn == ctx->desc.dig_conn) ++ return false; ++ return true; ++} ++ ++static bool ++mxm_match_dcb(struct drm_device *dev, u8 *data, void *info) ++{ ++ struct context *ctx = info; ++ u64 desc = *(u64 *)data; ++ ++ mxms_output_device(dev, data, &ctx->desc); ++ ++ /* match dcb encoder type to mxm-ods device type */ ++ if ((ctx->outp[0] & 0x0000000f) != ctx->desc.outp_type) ++ return true; ++ ++ /* digital output, have some extra stuff to match here, there's a ++ * table in the vbios that provides a mapping from the mxm digital ++ * connection enum values to SOR/link ++ */ ++ if ((desc & 0x00000000000000f0) >= 0x20) { ++ /* check against sor index */ ++ u8 link = mxm_sor_map(dev, ctx->desc.dig_conn); ++ if ((ctx->outp[0] & 0x0f000000) != (link & 0x0f) << 24) ++ return true; ++ ++ /* check dcb entry has a compatible link field */ ++ link = (link & 0x30) >> 4; ++ if ((link & ((ctx->outp[1] & 0x00000030) >> 4)) != link) ++ return true; ++ } ++ ++ /* mark this descriptor accounted for by setting invalid device type, ++ * except of course some manufactures don't follow specs properly and ++ * we need to avoid killing off the TMDS function on DP connectors ++ * if MXM-SIS is missing an entry for it. ++ */ ++ data[0] &= ~0xf0; ++ if (ctx->desc.outp_type == 6 && ctx->desc.conn_type == 6 && ++ mxms_foreach(dev, 0x01, mxm_match_tmds_partner, ctx)) { ++ data[0] |= 0x20; /* modify descriptor to match TMDS now */ ++ } else { ++ data[0] |= 0xf0; ++ } ++ ++ return false; ++} ++ ++static int ++mxm_dcb_sanitise_entry(struct drm_device *dev, void *data, int idx, u8 *dcbe) ++{ ++ struct context ctx = { .outp = (u32 *)dcbe }; ++ u8 type, i2cidx, link; ++ u8 *conn; ++ ++ /* look for an output device structure that matches this dcb entry. ++ * if one isn't found, disable it. ++ */ ++ if (mxms_foreach(dev, 0x01, mxm_match_dcb, &ctx)) { ++ MXM_DBG(dev, "disable %d: 0x%08x 0x%08x\n", ++ idx, ctx.outp[0], ctx.outp[1]); ++ ctx.outp[0] |= 0x0000000f; ++ return 0; ++ } ++ ++ /* modify the output's ddc/aux port, there's a pointer to a table ++ * with the mapping from mxm ddc/aux port to dcb i2c_index in the ++ * vbios mxm table ++ */ ++ i2cidx = mxm_ddc_map(dev, ctx.desc.ddc_port); ++ if ((ctx.outp[0] & 0x0000000f) != OUTPUT_DP) ++ i2cidx = (i2cidx & 0x0f) << 4; ++ else ++ i2cidx = (i2cidx & 0xf0); ++ ++ if (i2cidx != 0xf0) { ++ ctx.outp[0] &= ~0x000000f0; ++ ctx.outp[0] |= i2cidx; ++ } ++ ++ /* override dcb sorconf.link, based on what mxm data says */ ++ switch (ctx.desc.outp_type) { ++ case 0x00: /* Analog CRT */ ++ case 0x01: /* Analog TV/HDTV */ ++ break; ++ default: ++ link = mxm_sor_map(dev, ctx.desc.dig_conn) & 0x30; ++ ctx.outp[1] &= ~0x00000030; ++ ctx.outp[1] |= link; ++ break; ++ } ++ ++ /* we may need to fixup various other vbios tables based on what ++ * the descriptor says the connector type should be. ++ * ++ * in a lot of cases, the vbios tables will claim DVI-I is possible, ++ * and the mxm data says the connector is really HDMI. another ++ * common example is DP->eDP. ++ */ ++ conn = dcb_conn(dev, (ctx.outp[0] & 0x0000f000) >> 12); ++ type = conn[0]; ++ switch (ctx.desc.conn_type) { ++ case 0x01: /* LVDS */ ++ ctx.outp[1] |= 0x00000004; /* use_power_scripts */ ++ /* XXX: modify default link width in LVDS table */ ++ break; ++ case 0x02: /* HDMI */ ++ type = DCB_CONNECTOR_HDMI_1; ++ break; ++ case 0x03: /* DVI-D */ ++ type = DCB_CONNECTOR_DVI_D; ++ break; ++ case 0x0e: /* eDP, falls through to DPint */ ++ ctx.outp[1] |= 0x00010000; ++ case 0x07: /* DP internal, wtf is this?? HP8670w */ ++ ctx.outp[1] |= 0x00000004; /* use_power_scripts? */ ++ type = DCB_CONNECTOR_eDP; ++ break; ++ default: ++ break; ++ } ++ ++ if (mxms_version(dev) >= 0x0300) ++ conn[0] = type; ++ ++ return 0; ++} ++ ++static bool ++mxm_show_unmatched(struct drm_device *dev, u8 *data, void *info) ++{ ++ u64 desc = *(u64 *)data; ++ if ((desc & 0xf0) != 0xf0) ++ MXM_MSG(dev, "unmatched output device 0x%016llx\n", desc); ++ return true; ++} ++ ++static void ++mxm_dcb_sanitise(struct drm_device *dev) ++{ ++ u8 *dcb = dcb_table(dev); ++ if (!dcb || dcb[0] != 0x40) { ++ MXM_DBG(dev, "unsupported DCB version\n"); ++ return; ++ } ++ ++ dcb_outp_foreach(dev, NULL, mxm_dcb_sanitise_entry); ++ mxms_foreach(dev, 0x01, mxm_show_unmatched, NULL); ++} ++ ++static bool ++mxm_shadow_rom_fetch(struct nouveau_i2c_chan *i2c, u8 addr, ++ u8 offset, u8 size, u8 *data) ++{ ++ struct i2c_msg msgs[] = { ++ { .addr = addr, .flags = 0, .len = 1, .buf = &offset }, ++ { .addr = addr, .flags = I2C_M_RD, .len = size, .buf = data, }, ++ }; ++ ++ return i2c_transfer(&i2c->adapter, msgs, 2) == 2; ++} ++ ++static bool ++mxm_shadow_rom(struct drm_device *dev, u8 version) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_i2c_chan *i2c = NULL; ++ u8 i2cidx, mxms[6], addr, size; ++ ++ i2cidx = mxm_ddc_map(dev, 1 /* LVDS_DDC */) & 0x0f; ++ if (i2cidx < 0x0f) ++ i2c = nouveau_i2c_find(dev, i2cidx); ++ if (!i2c) ++ return false; ++ ++ addr = 0x54; ++ if (!mxm_shadow_rom_fetch(i2c, addr, 0, 6, mxms)) { ++ addr = 0x56; ++ if (!mxm_shadow_rom_fetch(i2c, addr, 0, 6, mxms)) ++ return false; ++ } ++ ++ dev_priv->mxms = mxms; ++ size = mxms_headerlen(dev) + mxms_structlen(dev); ++ dev_priv->mxms = kmalloc(size, GFP_KERNEL); ++ ++ if (dev_priv->mxms && ++ mxm_shadow_rom_fetch(i2c, addr, 0, size, dev_priv->mxms)) ++ return true; ++ ++ kfree(dev_priv->mxms); ++ dev_priv->mxms = NULL; ++ return false; ++} ++ ++#if defined(CONFIG_ACPI) ++static bool ++mxm_shadow_dsm(struct drm_device *dev, u8 version) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ static char muid[] = { ++ 0x00, 0xA4, 0x04, 0x40, 0x7D, 0x91, 0xF2, 0x4C, ++ 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65 ++ }; ++ u32 mxms_args[] = { 0x00000000 }; ++ union acpi_object args[4] = { ++ /* _DSM MUID */ ++ { .buffer.type = 3, ++ .buffer.length = sizeof(muid), ++ .buffer.pointer = muid, ++ }, ++ /* spec says this can be zero to mean "highest revision", but ++ * of course there's at least one bios out there which fails ++ * unless you pass in exactly the version it supports.. ++ */ ++ { .integer.type = ACPI_TYPE_INTEGER, ++ .integer.value = (version & 0xf0) << 4 | (version & 0x0f), ++ }, ++ /* MXMS function */ ++ { .integer.type = ACPI_TYPE_INTEGER, ++ .integer.value = 0x00000010, ++ }, ++ /* Pointer to MXMS arguments */ ++ { .buffer.type = ACPI_TYPE_BUFFER, ++ .buffer.length = sizeof(mxms_args), ++ .buffer.pointer = (char *)mxms_args, ++ }, ++ }; ++ struct acpi_object_list list = { ARRAY_SIZE(args), args }; ++ struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; ++ union acpi_object *obj; ++ acpi_handle handle; ++ int ret; ++ ++ handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev); ++ if (!handle) ++ return false; ++ ++ ret = acpi_evaluate_object(handle, "_DSM", &list, &retn); ++ if (ret) { ++ MXM_DBG(dev, "DSM MXMS failed: %d\n", ret); ++ return false; ++ } ++ ++ obj = retn.pointer; ++ if (obj->type == ACPI_TYPE_BUFFER) { ++ dev_priv->mxms = kmemdup(obj->buffer.pointer, ++ obj->buffer.length, GFP_KERNEL); ++ } else ++ if (obj->type == ACPI_TYPE_INTEGER) { ++ MXM_DBG(dev, "DSM MXMS returned 0x%llx\n", obj->integer.value); ++ } ++ ++ kfree(obj); ++ return dev_priv->mxms != NULL; ++} ++#endif ++ ++#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) ++ ++#define WMI_WMMX_GUID "F6CB5C3C-9CAE-4EBD-B577-931EA32A2CC0" ++ ++static u8 ++wmi_wmmx_mxmi(struct drm_device *dev, u8 version) ++{ ++ u32 mxmi_args[] = { 0x494D584D /* MXMI */, version, 0 }; ++ struct acpi_buffer args = { sizeof(mxmi_args), mxmi_args }; ++ struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; ++ union acpi_object *obj; ++ acpi_status status; ++ ++ status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn); ++ if (ACPI_FAILURE(status)) { ++ MXM_DBG(dev, "WMMX MXMI returned %d\n", status); ++ return 0x00; ++ } ++ ++ obj = retn.pointer; ++ if (obj->type == ACPI_TYPE_INTEGER) { ++ version = obj->integer.value; ++ MXM_DBG(dev, "WMMX MXMI version %d.%d\n", ++ (version >> 4), version & 0x0f); ++ } else { ++ version = 0; ++ MXM_DBG(dev, "WMMX MXMI returned non-integer\n"); ++ } ++ ++ kfree(obj); ++ return version; ++} ++ ++static bool ++mxm_shadow_wmi(struct drm_device *dev, u8 version) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 mxms_args[] = { 0x534D584D /* MXMS */, version, 0 }; ++ struct acpi_buffer args = { sizeof(mxms_args), mxms_args }; ++ struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; ++ union acpi_object *obj; ++ acpi_status status; ++ ++ if (!wmi_has_guid(WMI_WMMX_GUID)) { ++ MXM_DBG(dev, "WMMX GUID not found\n"); ++ return false; ++ } ++ ++ mxms_args[1] = wmi_wmmx_mxmi(dev, 0x00); ++ if (!mxms_args[1]) ++ mxms_args[1] = wmi_wmmx_mxmi(dev, version); ++ if (!mxms_args[1]) ++ return false; ++ ++ status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn); ++ if (ACPI_FAILURE(status)) { ++ MXM_DBG(dev, "WMMX MXMS returned %d\n", status); ++ return false; ++ } ++ ++ obj = retn.pointer; ++ if (obj->type == ACPI_TYPE_BUFFER) { ++ dev_priv->mxms = kmemdup(obj->buffer.pointer, ++ obj->buffer.length, GFP_KERNEL); ++ } ++ ++ kfree(obj); ++ return dev_priv->mxms != NULL; ++} ++#endif ++ ++struct mxm_shadow_h { ++ const char *name; ++ bool (*exec)(struct drm_device *, u8 version); ++} _mxm_shadow[] = { ++ { "ROM", mxm_shadow_rom }, ++#if defined(CONFIG_ACPI) ++ { "DSM", mxm_shadow_dsm }, ++#endif ++#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) ++ { "WMI", mxm_shadow_wmi }, ++#endif ++ {} ++}; ++ ++static int ++mxm_shadow(struct drm_device *dev, u8 version) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct mxm_shadow_h *shadow = _mxm_shadow; ++ do { ++ MXM_DBG(dev, "checking %s\n", shadow->name); ++ if (shadow->exec(dev, version)) { ++ if (mxms_valid(dev)) ++ return 0; ++ kfree(dev_priv->mxms); ++ dev_priv->mxms = NULL; ++ } ++ } while ((++shadow)->name); ++ return -ENOENT; ++} ++ ++int ++nouveau_mxm_init(struct drm_device *dev) ++{ ++ u8 mxm_size, *mxm = mxm_table(dev, &mxm_size); ++ if (!mxm || !mxm[0]) { ++ MXM_MSG(dev, "no VBIOS data, nothing to do\n"); ++ return 0; ++ } ++ ++ MXM_MSG(dev, "BIOS version %d.%d\n", mxm[0] >> 4, mxm[0] & 0x0f); ++ ++ if (mxm_shadow(dev, mxm[0])) { ++ MXM_MSG(dev, "failed to locate valid SIS\n"); ++#if 0 ++ /* we should, perhaps, fall back to some kind of limited ++ * mode here if the x86 vbios hasn't already done the ++ * work for us (so we prevent loading with completely ++ * whacked vbios tables). ++ */ ++ return -EINVAL; ++#else ++ return 0; ++#endif ++ } ++ ++ MXM_MSG(dev, "MXMS Version %d.%d\n", ++ mxms_version(dev) >> 8, mxms_version(dev) & 0xff); ++ mxms_foreach(dev, 0, NULL, NULL); ++ ++ if (nouveau_mxmdcb) ++ mxm_dcb_sanitise(dev); ++ return 0; ++} ++ ++void ++nouveau_mxm_fini(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ kfree(dev_priv->mxms); ++ dev_priv->mxms = NULL; ++} +diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c +index 6abdbe6..2ef883c 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_notifier.c ++++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c +@@ -115,7 +115,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *nobj = NULL; + struct drm_mm_node *mem; +- uint32_t offset; ++ uint64_t offset; + int target, ret; + + mem = drm_mm_search_free_in_range(&chan->notifier_heap, size, 0, +diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c +index 960c0ae..cc419fa 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_object.c ++++ b/drivers/gpu/drm/nouveau/nouveau_object.c +@@ -723,14 +723,14 @@ nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm) + nv_wo32(chan->ramin, 0x020c, 0x000000ff); + + /* map display semaphore buffers into channel's vm */ +- if (dev_priv->card_type >= NV_D0) +- return 0; +- +- for (i = 0; i < 2; i++) { +- struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i]; +- +- ret = nouveau_bo_vma_add(dispc->sem.bo, chan->vm, +- &chan->dispc_vma[i]); ++ for (i = 0; i < dev->mode_config.num_crtc; i++) { ++ struct nouveau_bo *bo; ++ if (dev_priv->card_type >= NV_D0) ++ bo = nvd0_display_crtc_sema(dev, i); ++ else ++ bo = nv50_display(dev)->crtc[i].sem.bo; ++ ++ ret = nouveau_bo_vma_add(bo, chan->vm, &chan->dispc_vma[i]); + if (ret) + return ret; + } +@@ -879,9 +879,14 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) + + NV_DEBUG(dev, "ch%d\n", chan->id); + +- if (dev_priv->card_type >= NV_50 && dev_priv->card_type <= NV_C0) { ++ if (dev_priv->card_type >= NV_D0) { ++ for (i = 0; i < dev->mode_config.num_crtc; i++) { ++ struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i); ++ nouveau_bo_vma_del(bo, &chan->dispc_vma[i]); ++ } ++ } else ++ if (dev_priv->card_type >= NV_50) { + struct nv50_display *disp = nv50_display(dev); +- + for (i = 0; i < dev->mode_config.num_crtc; i++) { + struct nv50_display_crtc *dispc = &disp->crtc[i]; + nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]); +diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c +index 33d03fb..69a528d 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_perf.c ++++ b/drivers/gpu/drm/nouveau/nouveau_perf.c +@@ -27,6 +27,178 @@ + #include "nouveau_drv.h" + #include "nouveau_pm.h" + ++static u8 * ++nouveau_perf_table(struct drm_device *dev, u8 *ver) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvbios *bios = &dev_priv->vbios; ++ struct bit_entry P; ++ ++ if (!bit_table(dev, 'P', &P) && P.version && P.version <= 2) { ++ u8 *perf = ROMPTR(dev, P.data[0]); ++ if (perf) { ++ *ver = perf[0]; ++ return perf; ++ } ++ } ++ ++ if (bios->type == NVBIOS_BMP) { ++ if (bios->data[bios->offset + 6] >= 0x25) { ++ u8 *perf = ROMPTR(dev, bios->data[bios->offset + 0x94]); ++ if (perf) { ++ *ver = perf[1]; ++ return perf; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++static u8 * ++nouveau_perf_entry(struct drm_device *dev, int idx, ++ u8 *ver, u8 *hdr, u8 *cnt, u8 *len) ++{ ++ u8 *perf = nouveau_perf_table(dev, ver); ++ if (perf) { ++ if (*ver >= 0x12 && *ver < 0x20 && idx < perf[2]) { ++ *hdr = perf[3]; ++ *cnt = 0; ++ *len = 0; ++ return perf + perf[0] + idx * perf[3]; ++ } else ++ if (*ver >= 0x20 && *ver < 0x40 && idx < perf[2]) { ++ *hdr = perf[3]; ++ *cnt = perf[4]; ++ *len = perf[5]; ++ return perf + perf[1] + idx * (*hdr + (*cnt * *len)); ++ } else ++ if (*ver >= 0x40 && *ver < 0x41 && idx < perf[5]) { ++ *hdr = perf[2]; ++ *cnt = perf[4]; ++ *len = perf[3]; ++ return perf + perf[1] + idx * (*hdr + (*cnt * *len)); ++ } ++ } ++ return NULL; ++} ++ ++static u8 * ++nouveau_perf_rammap(struct drm_device *dev, u32 freq, ++ u8 *ver, u8 *hdr, u8 *cnt, u8 *len) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct bit_entry P; ++ u8 *perf, i = 0; ++ ++ if (!bit_table(dev, 'P', &P) && P.version == 2) { ++ u8 *rammap = ROMPTR(dev, P.data[4]); ++ if (rammap) { ++ u8 *ramcfg = rammap + rammap[1]; ++ ++ *ver = rammap[0]; ++ *hdr = rammap[2]; ++ *cnt = rammap[4]; ++ *len = rammap[3]; ++ ++ freq /= 1000; ++ for (i = 0; i < rammap[5]; i++) { ++ if (freq >= ROM16(ramcfg[0]) && ++ freq <= ROM16(ramcfg[2])) ++ return ramcfg; ++ ++ ramcfg += *hdr + (*cnt * *len); ++ } ++ } ++ ++ return NULL; ++ } ++ ++ if (dev_priv->chipset == 0x49 || ++ dev_priv->chipset == 0x4b) ++ freq /= 2; ++ ++ while ((perf = nouveau_perf_entry(dev, i++, ver, hdr, cnt, len))) { ++ if (*ver >= 0x20 && *ver < 0x25) { ++ if (perf[0] != 0xff && freq <= ROM16(perf[11]) * 1000) ++ break; ++ } else ++ if (*ver >= 0x25 && *ver < 0x40) { ++ if (perf[0] != 0xff && freq <= ROM16(perf[12]) * 1000) ++ break; ++ } ++ } ++ ++ if (perf) { ++ u8 *ramcfg = perf + *hdr; ++ *ver = 0x00; ++ *hdr = 0; ++ return ramcfg; ++ } ++ ++ return NULL; ++} ++ ++u8 * ++nouveau_perf_ramcfg(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvbios *bios = &dev_priv->vbios; ++ u8 strap, hdr, cnt; ++ u8 *rammap; ++ ++ strap = (nv_rd32(dev, 0x101000) & 0x0000003c) >> 2; ++ if (bios->ram_restrict_tbl_ptr) ++ strap = bios->data[bios->ram_restrict_tbl_ptr + strap]; ++ ++ rammap = nouveau_perf_rammap(dev, freq, ver, &hdr, &cnt, len); ++ if (rammap && strap < cnt) ++ return rammap + hdr + (strap * *len); ++ ++ return NULL; ++} ++ ++u8 * ++nouveau_perf_timing(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvbios *bios = &dev_priv->vbios; ++ struct bit_entry P; ++ u8 *perf, *timing = NULL; ++ u8 i = 0, hdr, cnt; ++ ++ if (bios->type == NVBIOS_BMP) { ++ while ((perf = nouveau_perf_entry(dev, i++, ver, &hdr, &cnt, ++ len)) && *ver == 0x15) { ++ if (freq <= ROM32(perf[5]) * 20) { ++ *ver = 0x00; ++ *len = 14; ++ return perf + 41; ++ } ++ } ++ return NULL; ++ } ++ ++ if (!bit_table(dev, 'P', &P)) { ++ if (P.version == 1) ++ timing = ROMPTR(dev, P.data[4]); ++ else ++ if (P.version == 2) ++ timing = ROMPTR(dev, P.data[8]); ++ } ++ ++ if (timing && timing[0] == 0x10) { ++ u8 *ramcfg = nouveau_perf_ramcfg(dev, freq, ver, len); ++ if (ramcfg && ramcfg[1] < timing[2]) { ++ *ver = timing[0]; ++ *len = timing[3]; ++ return timing + timing[1] + (ramcfg[1] * timing[3]); ++ } ++ } ++ ++ return NULL; ++} ++ + static void + legacy_perf_init(struct drm_device *dev) + { +@@ -41,7 +213,7 @@ legacy_perf_init(struct drm_device *dev) + return; + } + +- perf = ROMPTR(bios, bmp[0x73]); ++ perf = ROMPTR(dev, bmp[0x73]); + if (!perf) { + NV_DEBUG(dev, "No memclock table pointer found.\n"); + return; +@@ -72,75 +244,11 @@ legacy_perf_init(struct drm_device *dev) + pm->nr_perflvl = 1; + } + +-static struct nouveau_pm_memtiming * +-nouveau_perf_timing(struct drm_device *dev, struct bit_entry *P, +- u16 memclk, u8 *entry, u8 recordlen, u8 entries) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_pm_engine *pm = &dev_priv->engine.pm; +- struct nvbios *bios = &dev_priv->vbios; +- u8 ramcfg; +- int i; +- +- /* perf v2 has a separate "timing map" table, we have to match +- * the target memory clock to a specific entry, *then* use +- * ramcfg to select the correct subentry +- */ +- if (P->version == 2) { +- u8 *tmap = ROMPTR(bios, P->data[4]); +- if (!tmap) { +- NV_DEBUG(dev, "no timing map pointer\n"); +- return NULL; +- } +- +- if (tmap[0] != 0x10) { +- NV_WARN(dev, "timing map 0x%02x unknown\n", tmap[0]); +- return NULL; +- } +- +- entry = tmap + tmap[1]; +- recordlen = tmap[2] + (tmap[4] * tmap[3]); +- for (i = 0; i < tmap[5]; i++, entry += recordlen) { +- if (memclk >= ROM16(entry[0]) && +- memclk <= ROM16(entry[2])) +- break; +- } +- +- if (i == tmap[5]) { +- NV_WARN(dev, "no match in timing map table\n"); +- return NULL; +- } +- +- entry += tmap[2]; +- recordlen = tmap[3]; +- entries = tmap[4]; +- } +- +- ramcfg = (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & 0x0000003c) >> 2; +- if (bios->ram_restrict_tbl_ptr) +- ramcfg = bios->data[bios->ram_restrict_tbl_ptr + ramcfg]; +- +- if (ramcfg >= entries) { +- NV_WARN(dev, "ramcfg strap out of bounds!\n"); +- return NULL; +- } +- +- entry += ramcfg * recordlen; +- if (entry[1] >= pm->memtimings.nr_timing) { +- if (entry[1] != 0xff) +- NV_WARN(dev, "timingset %d does not exist\n", entry[1]); +- return NULL; +- } +- +- return &pm->memtimings.timing[entry[1]]; +-} +- + static void +-nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P, +- struct nouveau_pm_level *perflvl) ++nouveau_perf_voltage(struct drm_device *dev, struct nouveau_pm_level *perflvl) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nvbios *bios = &dev_priv->vbios; ++ struct bit_entry P; + u8 *vmap; + int id; + +@@ -159,13 +267,13 @@ nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P, + /* on newer ones, the perflvl stores an index into yet another + * vbios table containing a min/max voltage value for the perflvl + */ +- if (P->version != 2 || P->length < 34) { ++ if (bit_table(dev, 'P', &P) || P.version != 2 || P.length < 34) { + NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n", +- P->version, P->length); ++ P.version, P.length); + return; + } + +- vmap = ROMPTR(bios, P->data[32]); ++ vmap = ROMPTR(dev, P.data[32]); + if (!vmap) { + NV_DEBUG(dev, "volt map table pointer invalid\n"); + return; +@@ -184,129 +292,70 @@ nouveau_perf_init(struct drm_device *dev) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nvbios *bios = &dev_priv->vbios; +- struct bit_entry P; +- struct nouveau_pm_memtimings *memtimings = &pm->memtimings; +- struct nouveau_pm_tbl_header mt_hdr; +- u8 version, headerlen, recordlen, entries; +- u8 *perf, *entry; +- int vid, i; +- +- if (bios->type == NVBIOS_BIT) { +- if (bit_table(dev, 'P', &P)) +- return; +- +- if (P.version != 1 && P.version != 2) { +- NV_WARN(dev, "unknown perf for BIT P %d\n", P.version); +- return; +- } +- +- perf = ROMPTR(bios, P.data[0]); +- version = perf[0]; +- headerlen = perf[1]; +- if (version < 0x40) { +- recordlen = perf[3] + (perf[4] * perf[5]); +- entries = perf[2]; +- } else { +- recordlen = perf[2] + (perf[3] * perf[4]); +- entries = perf[5]; +- } +- } else { +- if (bios->data[bios->offset + 6] < 0x25) { +- legacy_perf_init(dev); +- return; +- } +- +- perf = ROMPTR(bios, bios->data[bios->offset + 0x94]); +- if (!perf) { +- NV_DEBUG(dev, "perf table pointer invalid\n"); +- return; +- } +- +- version = perf[1]; +- headerlen = perf[0]; +- recordlen = perf[3]; +- entries = perf[2]; +- } ++ u8 *perf, ver, hdr, cnt, len; ++ int ret, vid, i = -1; + +- if (entries > NOUVEAU_PM_MAX_LEVEL) { +- NV_DEBUG(dev, "perf table has too many entries - buggy vbios?\n"); +- entries = NOUVEAU_PM_MAX_LEVEL; ++ if (bios->type == NVBIOS_BMP && bios->data[bios->offset + 6] < 0x25) { ++ legacy_perf_init(dev); ++ return; + } + +- entry = perf + headerlen; +- +- /* For version 0x15, initialize memtiming table */ +- if(version == 0x15) { +- memtimings->timing = +- kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); +- if (!memtimings->timing) { +- NV_WARN(dev,"Could not allocate memtiming table\n"); +- return; +- } ++ perf = nouveau_perf_table(dev, &ver); ++ if (ver >= 0x20 && ver < 0x40) ++ pm->fan.pwm_divisor = ROM16(perf[6]); + +- mt_hdr.entry_cnt = entries; +- mt_hdr.entry_len = 14; +- mt_hdr.version = version; +- mt_hdr.header_len = 4; +- } +- +- for (i = 0; i < entries; i++) { ++ while ((perf = nouveau_perf_entry(dev, ++i, &ver, &hdr, &cnt, &len))) { + struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; + +- perflvl->timing = NULL; +- +- if (entry[0] == 0xff) { +- entry += recordlen; ++ if (perf[0] == 0xff) + continue; +- } + +- switch (version) { ++ switch (ver) { + case 0x12: + case 0x13: + case 0x15: +- perflvl->fanspeed = entry[55]; +- if (recordlen > 56) +- perflvl->volt_min = entry[56]; +- perflvl->core = ROM32(entry[1]) * 10; +- perflvl->memory = ROM32(entry[5]) * 20; ++ perflvl->fanspeed = perf[55]; ++ if (hdr > 56) ++ perflvl->volt_min = perf[56]; ++ perflvl->core = ROM32(perf[1]) * 10; ++ perflvl->memory = ROM32(perf[5]) * 20; + break; + case 0x21: + case 0x23: + case 0x24: +- perflvl->fanspeed = entry[4]; +- perflvl->volt_min = entry[5]; +- perflvl->shader = ROM16(entry[6]) * 1000; ++ perflvl->fanspeed = perf[4]; ++ perflvl->volt_min = perf[5]; ++ perflvl->shader = ROM16(perf[6]) * 1000; + perflvl->core = perflvl->shader; +- perflvl->core += (signed char)entry[8] * 1000; ++ perflvl->core += (signed char)perf[8] * 1000; + if (dev_priv->chipset == 0x49 || + dev_priv->chipset == 0x4b) +- perflvl->memory = ROM16(entry[11]) * 1000; ++ perflvl->memory = ROM16(perf[11]) * 1000; + else +- perflvl->memory = ROM16(entry[11]) * 2000; +- ++ perflvl->memory = ROM16(perf[11]) * 2000; + break; + case 0x25: +- perflvl->fanspeed = entry[4]; +- perflvl->volt_min = entry[5]; +- perflvl->core = ROM16(entry[6]) * 1000; +- perflvl->shader = ROM16(entry[10]) * 1000; +- perflvl->memory = ROM16(entry[12]) * 1000; ++ perflvl->fanspeed = perf[4]; ++ perflvl->volt_min = perf[5]; ++ perflvl->core = ROM16(perf[6]) * 1000; ++ perflvl->shader = ROM16(perf[10]) * 1000; ++ perflvl->memory = ROM16(perf[12]) * 1000; + break; + case 0x30: +- perflvl->memscript = ROM16(entry[2]); ++ perflvl->memscript = ROM16(perf[2]); + case 0x35: +- perflvl->fanspeed = entry[6]; +- perflvl->volt_min = entry[7]; +- perflvl->core = ROM16(entry[8]) * 1000; +- perflvl->shader = ROM16(entry[10]) * 1000; +- perflvl->memory = ROM16(entry[12]) * 1000; +- /*XXX: confirm on 0x35 */ +- perflvl->unk05 = ROM16(entry[16]) * 1000; ++ perflvl->fanspeed = perf[6]; ++ perflvl->volt_min = perf[7]; ++ perflvl->core = ROM16(perf[8]) * 1000; ++ perflvl->shader = ROM16(perf[10]) * 1000; ++ perflvl->memory = ROM16(perf[12]) * 1000; ++ perflvl->vdec = ROM16(perf[16]) * 1000; ++ perflvl->dom6 = ROM16(perf[20]) * 1000; + break; + case 0x40: +-#define subent(n) (ROM16(entry[perf[2] + ((n) * perf[3])]) & 0xfff) * 1000 ++#define subent(n) ((ROM16(perf[hdr + (n) * len]) & 0xfff) * 1000) + perflvl->fanspeed = 0; /*XXX*/ +- perflvl->volt_min = entry[2]; ++ perflvl->volt_min = perf[2]; + if (dev_priv->card_type == NV_50) { + perflvl->core = subent(0); + perflvl->shader = subent(1); +@@ -329,36 +378,34 @@ nouveau_perf_init(struct drm_device *dev) + } + + /* make sure vid is valid */ +- nouveau_perf_voltage(dev, &P, perflvl); ++ nouveau_perf_voltage(dev, perflvl); + if (pm->voltage.supported && perflvl->volt_min) { + vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min); + if (vid < 0) { +- NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i); +- entry += recordlen; ++ NV_DEBUG(dev, "perflvl %d, bad vid\n", i); + continue; + } + } + + /* get the corresponding memory timings */ +- if (version == 0x15) { +- memtimings->timing[i].id = i; +- nv30_mem_timing_entry(dev,&mt_hdr,(struct nouveau_pm_tbl_entry*) &entry[41],0,&memtimings->timing[i]); +- perflvl->timing = &memtimings->timing[i]; +- } else if (version > 0x15) { +- /* last 3 args are for < 0x40, ignored for >= 0x40 */ +- perflvl->timing = +- nouveau_perf_timing(dev, &P, +- perflvl->memory / 1000, +- entry + perf[3], +- perf[5], perf[4]); ++ ret = nouveau_mem_timing_calc(dev, perflvl->memory, ++ &perflvl->timing); ++ if (ret) { ++ NV_DEBUG(dev, "perflvl %d, bad timing: %d\n", i, ret); ++ continue; + } + + snprintf(perflvl->name, sizeof(perflvl->name), + "performance_level_%d", i); + perflvl->id = i; +- pm->nr_perflvl++; + +- entry += recordlen; ++ snprintf(perflvl->profile.name, sizeof(perflvl->profile.name), ++ "%d", perflvl->id); ++ perflvl->profile.func = &nouveau_pm_static_profile_func; ++ list_add_tail(&perflvl->profile.head, &pm->profiles); ++ ++ ++ pm->nr_perflvl++; + } + } + +diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c +index a539fd2..da3e7c3 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_pm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_pm.c +@@ -26,6 +26,7 @@ + + #include "nouveau_drv.h" + #include "nouveau_pm.h" ++#include "nouveau_gpio.h" + + #ifdef CONFIG_ACPI + #include +@@ -35,22 +36,98 @@ + #include + + static int +-nouveau_pm_clock_set(struct drm_device *dev, struct nouveau_pm_level *perflvl, +- u8 id, u32 khz) ++nouveau_pwmfan_get(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; +- void *pre_state; ++ struct gpio_func gpio; ++ u32 divs, duty; ++ int ret; + +- if (khz == 0) +- return 0; ++ if (!pm->pwm_get) ++ return -ENODEV; ++ ++ ret = nouveau_gpio_find(dev, 0, DCB_GPIO_PWM_FAN, 0xff, &gpio); ++ if (ret == 0) { ++ ret = pm->pwm_get(dev, gpio.line, &divs, &duty); ++ if (ret == 0 && divs) { ++ divs = max(divs, duty); ++ if (dev_priv->card_type <= NV_40 || (gpio.log[0] & 1)) ++ duty = divs - duty; ++ return (duty * 100) / divs; ++ } ++ ++ return nouveau_gpio_func_get(dev, gpio.func) * 100; ++ } ++ ++ return -ENODEV; ++} ++ ++static int ++nouveau_pwmfan_set(struct drm_device *dev, int percent) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; ++ struct gpio_func gpio; ++ u32 divs, duty; ++ int ret; ++ ++ if (!pm->pwm_set) ++ return -ENODEV; ++ ++ ret = nouveau_gpio_find(dev, 0, DCB_GPIO_PWM_FAN, 0xff, &gpio); ++ if (ret == 0) { ++ divs = pm->fan.pwm_divisor; ++ if (pm->fan.pwm_freq) { ++ /*XXX: PNVIO clock more than likely... */ ++ divs = 135000 / pm->fan.pwm_freq; ++ if (dev_priv->chipset < 0xa3) ++ divs /= 4; ++ } ++ ++ duty = ((divs * percent) + 99) / 100; ++ if (dev_priv->card_type <= NV_40 || (gpio.log[0] & 1)) ++ duty = divs - duty; ++ ++ ret = pm->pwm_set(dev, gpio.line, divs, duty); ++ if (!ret) ++ pm->fan.percent = percent; ++ return ret; ++ } ++ ++ return -ENODEV; ++} ++ ++static int ++nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, ++ struct nouveau_pm_level *a, struct nouveau_pm_level *b) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; ++ int ret; + +- pre_state = pm->clock_pre(dev, perflvl, id, khz); +- if (IS_ERR(pre_state)) +- return PTR_ERR(pre_state); ++ /*XXX: not on all boards, we should control based on temperature ++ * on recent boards.. or maybe on some other factor we don't ++ * know about? ++ */ ++ if (a->fanspeed && b->fanspeed && b->fanspeed > a->fanspeed) { ++ ret = nouveau_pwmfan_set(dev, perflvl->fanspeed); ++ if (ret && ret != -ENODEV) { ++ NV_ERROR(dev, "fanspeed set failed: %d\n", ret); ++ return ret; ++ } ++ } ++ ++ if (pm->voltage.supported && pm->voltage_set) { ++ if (perflvl->volt_min && b->volt_min > a->volt_min) { ++ ret = pm->voltage_set(dev, perflvl->volt_min); ++ if (ret) { ++ NV_ERROR(dev, "voltage set failed: %d\n", ret); ++ return ret; ++ } ++ } ++ } + +- if (pre_state) +- pm->clock_set(dev, pre_state); + return 0; + } + +@@ -59,34 +136,90 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; ++ void *state; + int ret; + + if (perflvl == pm->cur) + return 0; + +- if (pm->voltage.supported && pm->voltage_set && perflvl->volt_min) { +- ret = pm->voltage_set(dev, perflvl->volt_min); +- if (ret) { +- NV_ERROR(dev, "voltage_set %d failed: %d\n", +- perflvl->volt_min, ret); +- } +- } ++ ret = nouveau_pm_perflvl_aux(dev, perflvl, pm->cur, perflvl); ++ if (ret) ++ return ret; + +- if (pm->clocks_pre) { +- void *state = pm->clocks_pre(dev, perflvl); +- if (IS_ERR(state)) +- return PTR_ERR(state); +- pm->clocks_set(dev, state); +- } else +- if (pm->clock_set) { +- nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); +- nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); +- nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); +- nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); ++ state = pm->clocks_pre(dev, perflvl); ++ if (IS_ERR(state)) { ++ ret = PTR_ERR(state); ++ goto error; + } ++ ret = pm->clocks_set(dev, state); ++ if (ret) ++ goto error; ++ ++ ret = nouveau_pm_perflvl_aux(dev, perflvl, perflvl, pm->cur); ++ if (ret) ++ return ret; + + pm->cur = perflvl; + return 0; ++ ++error: ++ /* restore the fan speed and voltage before leaving */ ++ nouveau_pm_perflvl_aux(dev, perflvl, perflvl, pm->cur); ++ return ret; ++} ++ ++void ++nouveau_pm_trigger(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; ++ struct nouveau_pm_profile *profile = NULL; ++ struct nouveau_pm_level *perflvl = NULL; ++ int ret; ++ ++ /* select power profile based on current power source */ ++ if (power_supply_is_system_supplied()) ++ profile = pm->profile_ac; ++ else ++ profile = pm->profile_dc; ++ ++ if (profile != pm->profile) { ++ pm->profile->func->fini(pm->profile); ++ pm->profile = profile; ++ pm->profile->func->init(pm->profile); ++ } ++ ++ /* select performance level based on profile */ ++ perflvl = profile->func->select(profile); ++ ++ /* change perflvl, if necessary */ ++ if (perflvl != pm->cur) { ++ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; ++ u64 time0 = ptimer->read(dev); ++ ++ NV_INFO(dev, "setting performance level: %d", perflvl->id); ++ ret = nouveau_pm_perflvl_set(dev, perflvl); ++ if (ret) ++ NV_INFO(dev, "> reclocking failed: %d\n\n", ret); ++ ++ NV_INFO(dev, "> reclocking took %lluns\n\n", ++ ptimer->read(dev) - time0); ++ } ++} ++ ++static struct nouveau_pm_profile * ++profile_find(struct drm_device *dev, const char *string) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; ++ struct nouveau_pm_profile *profile; ++ ++ list_for_each_entry(profile, &pm->profiles, head) { ++ if (!strncmp(profile->name, string, sizeof(profile->name))) ++ return profile; ++ } ++ ++ return NULL; + } + + static int +@@ -94,33 +227,55 @@ nouveau_pm_profile_set(struct drm_device *dev, const char *profile) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; +- struct nouveau_pm_level *perflvl = NULL; ++ struct nouveau_pm_profile *ac = NULL, *dc = NULL; ++ char string[16], *cur = string, *ptr; + + /* safety precaution, for now */ + if (nouveau_perflvl_wr != 7777) + return -EPERM; + +- if (!strncmp(profile, "boot", 4)) +- perflvl = &pm->boot; +- else { +- int pl = simple_strtol(profile, NULL, 10); +- int i; ++ strncpy(string, profile, sizeof(string)); ++ string[sizeof(string) - 1] = 0; ++ if ((ptr = strchr(string, '\n'))) ++ *ptr = '\0'; + +- for (i = 0; i < pm->nr_perflvl; i++) { +- if (pm->perflvl[i].id == pl) { +- perflvl = &pm->perflvl[i]; +- break; +- } +- } ++ ptr = strsep(&cur, ","); ++ if (ptr) ++ ac = profile_find(dev, ptr); + +- if (!perflvl) +- return -EINVAL; +- } ++ ptr = strsep(&cur, ","); ++ if (ptr) ++ dc = profile_find(dev, ptr); ++ else ++ dc = ac; ++ ++ if (ac == NULL || dc == NULL) ++ return -EINVAL; + +- NV_INFO(dev, "setting performance level: %s\n", profile); +- return nouveau_pm_perflvl_set(dev, perflvl); ++ pm->profile_ac = ac; ++ pm->profile_dc = dc; ++ nouveau_pm_trigger(dev); ++ return 0; + } + ++static void ++nouveau_pm_static_dummy(struct nouveau_pm_profile *profile) ++{ ++} ++ ++static struct nouveau_pm_level * ++nouveau_pm_static_select(struct nouveau_pm_profile *profile) ++{ ++ return container_of(profile, struct nouveau_pm_level, profile); ++} ++ ++const struct nouveau_pm_profile_func nouveau_pm_static_profile_func = { ++ .destroy = nouveau_pm_static_dummy, ++ .init = nouveau_pm_static_dummy, ++ .fini = nouveau_pm_static_dummy, ++ .select = nouveau_pm_static_select, ++}; ++ + static int + nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) + { +@@ -134,23 +289,6 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) + ret = pm->clocks_get(dev, perflvl); + if (ret) + return ret; +- } else +- if (pm->clock_get) { +- ret = pm->clock_get(dev, PLL_CORE); +- if (ret > 0) +- perflvl->core = ret; +- +- ret = pm->clock_get(dev, PLL_MEMORY); +- if (ret > 0) +- perflvl->memory = ret; +- +- ret = pm->clock_get(dev, PLL_SHADER); +- if (ret > 0) +- perflvl->shader = ret; +- +- ret = pm->clock_get(dev, PLL_UNK05); +- if (ret > 0) +- perflvl->unk05 = ret; + } + + if (pm->voltage.supported && pm->voltage_get) { +@@ -161,13 +299,18 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) + } + } + ++ ret = nouveau_pwmfan_get(dev); ++ if (ret > 0) ++ perflvl->fanspeed = ret; ++ ++ nouveau_mem_timing_read(dev, &perflvl->timing); + return 0; + } + + static void + nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) + { +- char c[16], s[16], v[32], f[16], t[16], m[16]; ++ char c[16], s[16], v[32], f[16], m[16]; + + c[0] = '\0'; + if (perflvl->core) +@@ -195,18 +338,15 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) + if (perflvl->fanspeed) + snprintf(f, sizeof(f), " fanspeed %d%%", perflvl->fanspeed); + +- t[0] = '\0'; +- if (perflvl->timing) +- snprintf(t, sizeof(t), " timing %d", perflvl->timing->id); +- +- snprintf(ptr, len, "%s%s%s%s%s%s\n", c, s, m, t, v, f); ++ snprintf(ptr, len, "%s%s%s%s%s\n", c, s, m, v, f); + } + + static ssize_t + nouveau_pm_get_perflvl_info(struct device *d, + struct device_attribute *a, char *buf) + { +- struct nouveau_pm_level *perflvl = (struct nouveau_pm_level *)a; ++ struct nouveau_pm_level *perflvl = ++ container_of(a, struct nouveau_pm_level, dev_attr); + char *ptr = buf; + int len = PAGE_SIZE; + +@@ -228,12 +368,8 @@ nouveau_pm_get_perflvl(struct device *d, struct device_attribute *a, char *buf) + int len = PAGE_SIZE, ret; + char *ptr = buf; + +- if (!pm->cur) +- snprintf(ptr, len, "setting: boot\n"); +- else if (pm->cur == &pm->boot) +- snprintf(ptr, len, "setting: boot\nc:"); +- else +- snprintf(ptr, len, "setting: static %d\nc:", pm->cur->id); ++ snprintf(ptr, len, "profile: %s, %s\nc:", ++ pm->profile_ac->name, pm->profile_dc->name); + ptr += strlen(buf); + len -= strlen(buf); + +@@ -345,7 +481,7 @@ nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a, + struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; + long value; + +- if (strict_strtol(buf, 10, &value) == -EINVAL) ++ if (kstrtol(buf, 10, &value) == -EINVAL) + return count; + + temp->down_clock = value/1000; +@@ -380,7 +516,7 @@ nouveau_hwmon_set_critical_temp(struct device *d, struct device_attribute *a, + struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; + long value; + +- if (strict_strtol(buf, 10, &value) == -EINVAL) ++ if (kstrtol(buf, 10, &value) == -EINVAL) + return count; + + temp->critical = value/1000; +@@ -412,6 +548,172 @@ static SENSOR_DEVICE_ATTR(update_rate, S_IRUGO, + nouveau_hwmon_show_update_rate, + NULL, 0); + ++static ssize_t ++nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr, ++ char *buf) ++{ ++ struct drm_device *dev = dev_get_drvdata(d); ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; ++ struct gpio_func gpio; ++ u32 cycles, cur, prev; ++ u64 start; ++ int ret; ++ ++ ret = nouveau_gpio_find(dev, 0, DCB_GPIO_FAN_SENSE, 0xff, &gpio); ++ if (ret) ++ return ret; ++ ++ /* Monitor the GPIO input 0x3b for 250ms. ++ * When the fan spins, it changes the value of GPIO FAN_SENSE. ++ * We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation. ++ */ ++ start = ptimer->read(dev); ++ prev = nouveau_gpio_sense(dev, 0, gpio.line); ++ cycles = 0; ++ do { ++ cur = nouveau_gpio_sense(dev, 0, gpio.line); ++ if (prev != cur) { ++ cycles++; ++ prev = cur; ++ } ++ ++ usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ ++ } while (ptimer->read(dev) - start < 250000000); ++ ++ /* interpolate to get rpm */ ++ return sprintf(buf, "%i\n", cycles / 4 * 4 * 60); ++} ++static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input, ++ NULL, 0); ++ ++static ssize_t ++nouveau_hwmon_get_pwm0(struct device *d, struct device_attribute *a, char *buf) ++{ ++ struct drm_device *dev = dev_get_drvdata(d); ++ int ret; ++ ++ ret = nouveau_pwmfan_get(dev); ++ if (ret < 0) ++ return ret; ++ ++ return sprintf(buf, "%i\n", ret); ++} ++ ++static ssize_t ++nouveau_hwmon_set_pwm0(struct device *d, struct device_attribute *a, ++ const char *buf, size_t count) ++{ ++ struct drm_device *dev = dev_get_drvdata(d); ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; ++ int ret = -ENODEV; ++ long value; ++ ++ if (nouveau_perflvl_wr != 7777) ++ return -EPERM; ++ ++ if (kstrtol(buf, 10, &value) == -EINVAL) ++ return -EINVAL; ++ ++ if (value < pm->fan.min_duty) ++ value = pm->fan.min_duty; ++ if (value > pm->fan.max_duty) ++ value = pm->fan.max_duty; ++ ++ ret = nouveau_pwmfan_set(dev, value); ++ if (ret) ++ return ret; ++ ++ return count; ++} ++ ++static SENSOR_DEVICE_ATTR(pwm0, S_IRUGO | S_IWUSR, ++ nouveau_hwmon_get_pwm0, ++ nouveau_hwmon_set_pwm0, 0); ++ ++static ssize_t ++nouveau_hwmon_get_pwm0_min(struct device *d, ++ struct device_attribute *a, char *buf) ++{ ++ struct drm_device *dev = dev_get_drvdata(d); ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; ++ ++ return sprintf(buf, "%i\n", pm->fan.min_duty); ++} ++ ++static ssize_t ++nouveau_hwmon_set_pwm0_min(struct device *d, struct device_attribute *a, ++ const char *buf, size_t count) ++{ ++ struct drm_device *dev = dev_get_drvdata(d); ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; ++ long value; ++ ++ if (kstrtol(buf, 10, &value) == -EINVAL) ++ return -EINVAL; ++ ++ if (value < 0) ++ value = 0; ++ ++ if (pm->fan.max_duty - value < 10) ++ value = pm->fan.max_duty - 10; ++ ++ if (value < 10) ++ pm->fan.min_duty = 10; ++ else ++ pm->fan.min_duty = value; ++ ++ return count; ++} ++ ++static SENSOR_DEVICE_ATTR(pwm0_min, S_IRUGO | S_IWUSR, ++ nouveau_hwmon_get_pwm0_min, ++ nouveau_hwmon_set_pwm0_min, 0); ++ ++static ssize_t ++nouveau_hwmon_get_pwm0_max(struct device *d, ++ struct device_attribute *a, char *buf) ++{ ++ struct drm_device *dev = dev_get_drvdata(d); ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; ++ ++ return sprintf(buf, "%i\n", pm->fan.max_duty); ++} ++ ++static ssize_t ++nouveau_hwmon_set_pwm0_max(struct device *d, struct device_attribute *a, ++ const char *buf, size_t count) ++{ ++ struct drm_device *dev = dev_get_drvdata(d); ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pm_engine *pm = &dev_priv->engine.pm; ++ long value; ++ ++ if (kstrtol(buf, 10, &value) == -EINVAL) ++ return -EINVAL; ++ ++ if (value < 0) ++ value = 0; ++ ++ if (value - pm->fan.min_duty < 10) ++ value = pm->fan.min_duty + 10; ++ ++ if (value > 100) ++ pm->fan.max_duty = 100; ++ else ++ pm->fan.max_duty = value; ++ ++ return count; ++} ++ ++static SENSOR_DEVICE_ATTR(pwm0_max, S_IRUGO | S_IWUSR, ++ nouveau_hwmon_get_pwm0_max, ++ nouveau_hwmon_set_pwm0_max, 0); ++ + static struct attribute *hwmon_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, +@@ -420,20 +722,36 @@ static struct attribute *hwmon_attributes[] = { + &sensor_dev_attr_update_rate.dev_attr.attr, + NULL + }; ++static struct attribute *hwmon_fan_rpm_attributes[] = { ++ &sensor_dev_attr_fan0_input.dev_attr.attr, ++ NULL ++}; ++static struct attribute *hwmon_pwm_fan_attributes[] = { ++ &sensor_dev_attr_pwm0.dev_attr.attr, ++ &sensor_dev_attr_pwm0_min.dev_attr.attr, ++ &sensor_dev_attr_pwm0_max.dev_attr.attr, ++ NULL ++}; + + static const struct attribute_group hwmon_attrgroup = { + .attrs = hwmon_attributes, + }; ++static const struct attribute_group hwmon_fan_rpm_attrgroup = { ++ .attrs = hwmon_fan_rpm_attributes, ++}; ++static const struct attribute_group hwmon_pwm_fan_attrgroup = { ++ .attrs = hwmon_pwm_fan_attributes, ++}; + #endif + + static int + nouveau_hwmon_init(struct drm_device *dev) + { +-#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; ++#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) + struct device *hwmon_dev; +- int ret; ++ int ret = 0; + + if (!pm->temp_get) + return -ENODEV; +@@ -446,17 +764,46 @@ nouveau_hwmon_init(struct drm_device *dev) + return ret; + } + dev_set_drvdata(hwmon_dev, dev); ++ ++ /* default sysfs entries */ + ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); + if (ret) { +- NV_ERROR(dev, +- "Unable to create hwmon sysfs file: %d\n", ret); +- hwmon_device_unregister(hwmon_dev); +- return ret; ++ if (ret) ++ goto error; ++ } ++ ++ /* if the card has a pwm fan */ ++ /*XXX: incorrect, need better detection for this, some boards have ++ * the gpio entries for pwm fan control even when there's no ++ * actual fan connected to it... therm table? */ ++ if (nouveau_pwmfan_get(dev) >= 0) { ++ ret = sysfs_create_group(&dev->pdev->dev.kobj, ++ &hwmon_pwm_fan_attrgroup); ++ if (ret) ++ goto error; ++ } ++ ++ /* if the card can read the fan rpm */ ++ if (nouveau_gpio_func_valid(dev, DCB_GPIO_FAN_SENSE)) { ++ ret = sysfs_create_group(&dev->pdev->dev.kobj, ++ &hwmon_fan_rpm_attrgroup); ++ if (ret) ++ goto error; + } + + pm->hwmon = hwmon_dev; +-#endif ++ ++ return 0; ++ ++error: ++ NV_ERROR(dev, "Unable to create some hwmon sysfs files: %d\n", ret); ++ hwmon_device_unregister(hwmon_dev); ++ pm->hwmon = NULL; ++ return ret; ++#else ++ pm->hwmon = NULL; + return 0; ++#endif + } + + static void +@@ -468,6 +815,11 @@ nouveau_hwmon_fini(struct drm_device *dev) + + if (pm->hwmon) { + sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); ++ sysfs_remove_group(&dev->pdev->dev.kobj, ++ &hwmon_pwm_fan_attrgroup); ++ sysfs_remove_group(&dev->pdev->dev.kobj, ++ &hwmon_fan_rpm_attrgroup); ++ + hwmon_device_unregister(pm->hwmon); + } + #endif +@@ -486,6 +838,7 @@ nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data) + bool ac = power_supply_is_system_supplied(); + + NV_DEBUG(dev, "power supply changed: %s\n", ac ? "AC" : "DC"); ++ nouveau_pm_trigger(dev); + } + + return NOTIFY_OK; +@@ -500,35 +853,48 @@ nouveau_pm_init(struct drm_device *dev) + char info[256]; + int ret, i; + +- nouveau_mem_timing_init(dev); ++ /* parse aux tables from vbios */ + nouveau_volt_init(dev); +- nouveau_perf_init(dev); + nouveau_temp_init(dev); + ++ /* determine current ("boot") performance level */ ++ ret = nouveau_pm_perflvl_get(dev, &pm->boot); ++ if (ret) { ++ NV_ERROR(dev, "failed to determine boot perflvl\n"); ++ return ret; ++ } ++ ++ strncpy(pm->boot.name, "boot", 4); ++ strncpy(pm->boot.profile.name, "boot", 4); ++ pm->boot.profile.func = &nouveau_pm_static_profile_func; ++ ++ INIT_LIST_HEAD(&pm->profiles); ++ list_add(&pm->boot.profile.head, &pm->profiles); ++ ++ pm->profile_ac = &pm->boot.profile; ++ pm->profile_dc = &pm->boot.profile; ++ pm->profile = &pm->boot.profile; ++ pm->cur = &pm->boot; ++ ++ /* add performance levels from vbios */ ++ nouveau_perf_init(dev); ++ ++ /* display available performance levels */ + NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl); + for (i = 0; i < pm->nr_perflvl; i++) { + nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info)); + NV_INFO(dev, "%d:%s", pm->perflvl[i].id, info); + } + +- /* determine current ("boot") performance level */ +- ret = nouveau_pm_perflvl_get(dev, &pm->boot); +- if (ret == 0) { +- strncpy(pm->boot.name, "boot", 4); +- pm->cur = &pm->boot; +- +- nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); +- NV_INFO(dev, "c:%s", info); +- } ++ nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); ++ NV_INFO(dev, "c:%s", info); + + /* switch performance levels now if requested */ +- if (nouveau_perflvl != NULL) { +- ret = nouveau_pm_profile_set(dev, nouveau_perflvl); +- if (ret) { +- NV_ERROR(dev, "error setting perflvl \"%s\": %d\n", +- nouveau_perflvl, ret); +- } +- } ++ if (nouveau_perflvl != NULL) ++ nouveau_pm_profile_set(dev, nouveau_perflvl); ++ ++ /* determine the current fan speed */ ++ pm->fan.percent = nouveau_pwmfan_get(dev); + + nouveau_sysfs_init(dev); + nouveau_hwmon_init(dev); +@@ -545,6 +911,12 @@ nouveau_pm_fini(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; ++ struct nouveau_pm_profile *profile, *tmp; ++ ++ list_for_each_entry_safe(profile, tmp, &pm->profiles, head) { ++ list_del(&profile->head); ++ profile->func->destroy(profile); ++ } + + if (pm->cur != &pm->boot) + nouveau_pm_perflvl_set(dev, &pm->boot); +@@ -552,7 +924,6 @@ nouveau_pm_fini(struct drm_device *dev) + nouveau_temp_fini(dev); + nouveau_perf_fini(dev); + nouveau_volt_fini(dev); +- nouveau_mem_timing_fini(dev); + + #if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY) + unregister_acpi_notifier(&pm->acpi_nb); +@@ -574,4 +945,5 @@ nouveau_pm_resume(struct drm_device *dev) + perflvl = pm->cur; + pm->cur = &pm->boot; + nouveau_pm_perflvl_set(dev, perflvl); ++ nouveau_pwmfan_set(dev, pm->fan.percent); + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h +index 8ac02cd..3f82dfe 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_pm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_pm.h +@@ -25,10 +25,30 @@ + #ifndef __NOUVEAU_PM_H__ + #define __NOUVEAU_PM_H__ + ++struct nouveau_mem_exec_func { ++ struct drm_device *dev; ++ void (*precharge)(struct nouveau_mem_exec_func *); ++ void (*refresh)(struct nouveau_mem_exec_func *); ++ void (*refresh_auto)(struct nouveau_mem_exec_func *, bool); ++ void (*refresh_self)(struct nouveau_mem_exec_func *, bool); ++ void (*wait)(struct nouveau_mem_exec_func *, u32 nsec); ++ u32 (*mrg)(struct nouveau_mem_exec_func *, int mr); ++ void (*mrs)(struct nouveau_mem_exec_func *, int mr, u32 data); ++ void (*clock_set)(struct nouveau_mem_exec_func *); ++ void (*timing_set)(struct nouveau_mem_exec_func *); ++ void *priv; ++}; ++ ++/* nouveau_mem.c */ ++int nouveau_mem_exec(struct nouveau_mem_exec_func *, ++ struct nouveau_pm_level *); ++ + /* nouveau_pm.c */ + int nouveau_pm_init(struct drm_device *dev); + void nouveau_pm_fini(struct drm_device *dev); + void nouveau_pm_resume(struct drm_device *dev); ++extern const struct nouveau_pm_profile_func nouveau_pm_static_profile_func; ++void nouveau_pm_trigger(struct drm_device *dev); + + /* nouveau_volt.c */ + void nouveau_volt_init(struct drm_device *); +@@ -41,35 +61,41 @@ int nouveau_voltage_gpio_set(struct drm_device *, int voltage); + /* nouveau_perf.c */ + void nouveau_perf_init(struct drm_device *); + void nouveau_perf_fini(struct drm_device *); ++u8 *nouveau_perf_timing(struct drm_device *, u32 freq, u8 *ver, u8 *len); ++u8 *nouveau_perf_ramcfg(struct drm_device *, u32 freq, u8 *ver, u8 *len); + + /* nouveau_mem.c */ + void nouveau_mem_timing_init(struct drm_device *); + void nouveau_mem_timing_fini(struct drm_device *); + + /* nv04_pm.c */ +-int nv04_pm_clock_get(struct drm_device *, u32 id); +-void *nv04_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, +- u32 id, int khz); +-void nv04_pm_clock_set(struct drm_device *, void *); ++int nv04_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); ++void *nv04_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); ++int nv04_pm_clocks_set(struct drm_device *, void *); + + /* nv40_pm.c */ + int nv40_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); + void *nv40_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); +-void nv40_pm_clocks_set(struct drm_device *, void *); ++int nv40_pm_clocks_set(struct drm_device *, void *); ++int nv40_pm_pwm_get(struct drm_device *, int, u32 *, u32 *); ++int nv40_pm_pwm_set(struct drm_device *, int, u32, u32); + + /* nv50_pm.c */ +-int nv50_pm_clock_get(struct drm_device *, u32 id); +-void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, +- u32 id, int khz); +-void nv50_pm_clock_set(struct drm_device *, void *); ++int nv50_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); ++void *nv50_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); ++int nv50_pm_clocks_set(struct drm_device *, void *); ++int nv50_pm_pwm_get(struct drm_device *, int, u32 *, u32 *); ++int nv50_pm_pwm_set(struct drm_device *, int, u32, u32); + + /* nva3_pm.c */ + int nva3_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); + void *nva3_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); +-void nva3_pm_clocks_set(struct drm_device *, void *); ++int nva3_pm_clocks_set(struct drm_device *, void *); + + /* nvc0_pm.c */ + int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); ++void *nvc0_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); ++int nvc0_pm_clocks_set(struct drm_device *, void *); + + /* nouveau_temp.c */ + void nouveau_temp_init(struct drm_device *dev); +diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c +index c8a463b..47f245e 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c ++++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c +@@ -8,91 +8,30 @@ + #define NV_CTXDMA_PAGE_MASK (NV_CTXDMA_PAGE_SIZE - 1) + + struct nouveau_sgdma_be { +- struct ttm_backend backend; ++ /* this has to be the first field so populate/unpopulated in ++ * nouve_bo.c works properly, otherwise have to move them here ++ */ ++ struct ttm_dma_tt ttm; + struct drm_device *dev; +- +- dma_addr_t *pages; +- unsigned nr_pages; +- bool unmap_pages; +- + u64 offset; +- bool bound; + }; + +-static int +-nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages, +- struct page **pages, struct page *dummy_read_page, +- dma_addr_t *dma_addrs) +-{ +- struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; +- struct drm_device *dev = nvbe->dev; +- int i; +- +- NV_DEBUG(nvbe->dev, "num_pages = %ld\n", num_pages); +- +- nvbe->pages = dma_addrs; +- nvbe->nr_pages = num_pages; +- nvbe->unmap_pages = true; +- +- /* this code path isn't called and is incorrect anyways */ +- if (0) { /* dma_addrs[0] != DMA_ERROR_CODE) { */ +- nvbe->unmap_pages = false; +- return 0; +- } +- +- for (i = 0; i < num_pages; i++) { +- nvbe->pages[i] = pci_map_page(dev->pdev, pages[i], 0, +- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); +- if (pci_dma_mapping_error(dev->pdev, nvbe->pages[i])) { +- nvbe->nr_pages = --i; +- be->func->clear(be); +- return -EFAULT; +- } +- } +- +- return 0; +-} +- + static void +-nouveau_sgdma_clear(struct ttm_backend *be) ++nouveau_sgdma_destroy(struct ttm_tt *ttm) + { +- struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; +- struct drm_device *dev = nvbe->dev; +- +- if (nvbe->bound) +- be->func->unbind(be); ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; + +- if (nvbe->unmap_pages) { +- while (nvbe->nr_pages--) { +- pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages], +- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); +- } +- nvbe->unmap_pages = false; +- } +- +- nvbe->pages = NULL; +-} +- +-static void +-nouveau_sgdma_destroy(struct ttm_backend *be) +-{ +- struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; +- +- if (be) { ++ if (ttm) { + NV_DEBUG(nvbe->dev, "\n"); +- +- if (nvbe) { +- if (nvbe->pages) +- be->func->clear(be); +- kfree(nvbe); +- } ++ ttm_dma_tt_fini(&nvbe->ttm); ++ kfree(nvbe); + } + } + + static int +-nv04_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) ++nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem) + { +- struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; + struct drm_device *dev = nvbe->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; +@@ -102,8 +41,8 @@ nv04_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) + + nvbe->offset = mem->start << PAGE_SHIFT; + pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2; +- for (i = 0; i < nvbe->nr_pages; i++) { +- dma_addr_t dma_offset = nvbe->pages[i]; ++ for (i = 0; i < ttm->num_pages; i++) { ++ dma_addr_t dma_offset = nvbe->ttm.dma_address[i]; + uint32_t offset_l = lower_32_bits(dma_offset); + + for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++) { +@@ -112,14 +51,13 @@ nv04_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) + } + } + +- nvbe->bound = true; + return 0; + } + + static int +-nv04_sgdma_unbind(struct ttm_backend *be) ++nv04_sgdma_unbind(struct ttm_tt *ttm) + { +- struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; + struct drm_device *dev = nvbe->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; +@@ -127,22 +65,19 @@ nv04_sgdma_unbind(struct ttm_backend *be) + + NV_DEBUG(dev, "\n"); + +- if (!nvbe->bound) ++ if (ttm->state != tt_bound) + return 0; + + pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2; +- for (i = 0; i < nvbe->nr_pages; i++) { ++ for (i = 0; i < ttm->num_pages; i++) { + for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++) + nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000); + } + +- nvbe->bound = false; + return 0; + } + + static struct ttm_backend_func nv04_sgdma_backend = { +- .populate = nouveau_sgdma_populate, +- .clear = nouveau_sgdma_clear, + .bind = nv04_sgdma_bind, + .unbind = nv04_sgdma_unbind, + .destroy = nouveau_sgdma_destroy +@@ -161,14 +96,14 @@ nv41_sgdma_flush(struct nouveau_sgdma_be *nvbe) + } + + static int +-nv41_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) ++nv41_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem) + { +- struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; + struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; + struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; +- dma_addr_t *list = nvbe->pages; ++ dma_addr_t *list = nvbe->ttm.dma_address; + u32 pte = mem->start << 2; +- u32 cnt = nvbe->nr_pages; ++ u32 cnt = ttm->num_pages; + + nvbe->offset = mem->start << PAGE_SHIFT; + +@@ -178,18 +113,17 @@ nv41_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) + } + + nv41_sgdma_flush(nvbe); +- nvbe->bound = true; + return 0; + } + + static int +-nv41_sgdma_unbind(struct ttm_backend *be) ++nv41_sgdma_unbind(struct ttm_tt *ttm) + { +- struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; + struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; + struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; + u32 pte = (nvbe->offset >> 12) << 2; +- u32 cnt = nvbe->nr_pages; ++ u32 cnt = ttm->num_pages; + + while (cnt--) { + nv_wo32(pgt, pte, 0x00000000); +@@ -197,24 +131,22 @@ nv41_sgdma_unbind(struct ttm_backend *be) + } + + nv41_sgdma_flush(nvbe); +- nvbe->bound = false; + return 0; + } + + static struct ttm_backend_func nv41_sgdma_backend = { +- .populate = nouveau_sgdma_populate, +- .clear = nouveau_sgdma_clear, + .bind = nv41_sgdma_bind, + .unbind = nv41_sgdma_unbind, + .destroy = nouveau_sgdma_destroy + }; + + static void +-nv44_sgdma_flush(struct nouveau_sgdma_be *nvbe) ++nv44_sgdma_flush(struct ttm_tt *ttm) + { ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; + struct drm_device *dev = nvbe->dev; + +- nv_wr32(dev, 0x100814, (nvbe->nr_pages - 1) << 12); ++ nv_wr32(dev, 0x100814, (ttm->num_pages - 1) << 12); + nv_wr32(dev, 0x100808, nvbe->offset | 0x20); + if (!nv_wait(dev, 0x100808, 0x00000001, 0x00000001)) + NV_ERROR(dev, "gart flush timeout: 0x%08x\n", +@@ -273,14 +205,14 @@ nv44_sgdma_fill(struct nouveau_gpuobj *pgt, dma_addr_t *list, u32 base, u32 cnt) + } + + static int +-nv44_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) ++nv44_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem) + { +- struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; + struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; + struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; +- dma_addr_t *list = nvbe->pages; ++ dma_addr_t *list = nvbe->ttm.dma_address; + u32 pte = mem->start << 2, tmp[4]; +- u32 cnt = nvbe->nr_pages; ++ u32 cnt = ttm->num_pages; + int i; + + nvbe->offset = mem->start << PAGE_SHIFT; +@@ -308,19 +240,18 @@ nv44_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) + if (cnt) + nv44_sgdma_fill(pgt, list, pte, cnt); + +- nv44_sgdma_flush(nvbe); +- nvbe->bound = true; ++ nv44_sgdma_flush(ttm); + return 0; + } + + static int +-nv44_sgdma_unbind(struct ttm_backend *be) ++nv44_sgdma_unbind(struct ttm_tt *ttm) + { +- struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; + struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; + struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; + u32 pte = (nvbe->offset >> 12) << 2; +- u32 cnt = nvbe->nr_pages; ++ u32 cnt = ttm->num_pages; + + if (pte & 0x0000000c) { + u32 max = 4 - ((pte >> 2) & 0x3); +@@ -342,55 +273,47 @@ nv44_sgdma_unbind(struct ttm_backend *be) + if (cnt) + nv44_sgdma_fill(pgt, NULL, pte, cnt); + +- nv44_sgdma_flush(nvbe); +- nvbe->bound = false; ++ nv44_sgdma_flush(ttm); + return 0; + } + + static struct ttm_backend_func nv44_sgdma_backend = { +- .populate = nouveau_sgdma_populate, +- .clear = nouveau_sgdma_clear, + .bind = nv44_sgdma_bind, + .unbind = nv44_sgdma_unbind, + .destroy = nouveau_sgdma_destroy + }; + + static int +-nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) ++nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem) + { +- struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; + struct nouveau_mem *node = mem->mm_node; ++ + /* noop: bound in move_notify() */ +- node->pages = nvbe->pages; +- nvbe->pages = (dma_addr_t *)node; +- nvbe->bound = true; ++ node->pages = nvbe->ttm.dma_address; + return 0; + } + + static int +-nv50_sgdma_unbind(struct ttm_backend *be) ++nv50_sgdma_unbind(struct ttm_tt *ttm) + { +- struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; +- struct nouveau_mem *node = (struct nouveau_mem *)nvbe->pages; + /* noop: unbound in move_notify() */ +- nvbe->pages = node->pages; +- node->pages = NULL; +- nvbe->bound = false; + return 0; + } + + static struct ttm_backend_func nv50_sgdma_backend = { +- .populate = nouveau_sgdma_populate, +- .clear = nouveau_sgdma_clear, + .bind = nv50_sgdma_bind, + .unbind = nv50_sgdma_unbind, + .destroy = nouveau_sgdma_destroy + }; + +-struct ttm_backend * +-nouveau_sgdma_init_ttm(struct drm_device *dev) ++struct ttm_tt * ++nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev, ++ unsigned long size, uint32_t page_flags, ++ struct page *dummy_read_page) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); ++ struct drm_device *dev = dev_priv->dev; + struct nouveau_sgdma_be *nvbe; + + nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL); +@@ -398,9 +321,13 @@ nouveau_sgdma_init_ttm(struct drm_device *dev) + return NULL; + + nvbe->dev = dev; ++ nvbe->ttm.ttm.func = dev_priv->gart_info.func; + +- nvbe->backend.func = dev_priv->gart_info.func; +- return &nvbe->backend; ++ if (ttm_dma_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page)) { ++ kfree(nvbe); ++ return NULL; ++ } ++ return &nvbe->ttm.ttm; + } + + int +diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c +index 01adcfb..b096cf2 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_state.c ++++ b/drivers/gpu/drm/nouveau/nouveau_state.c +@@ -36,6 +36,7 @@ + #include "nouveau_drm.h" + #include "nouveau_fbcon.h" + #include "nouveau_ramht.h" ++#include "nouveau_gpio.h" + #include "nouveau_pm.h" + #include "nv50_display.h" + +@@ -81,17 +82,13 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->display.early_init = nv04_display_early_init; + engine->display.late_takedown = nv04_display_late_takedown; + engine->display.create = nv04_display_create; +- engine->display.init = nv04_display_init; + engine->display.destroy = nv04_display_destroy; +- engine->gpio.init = nouveau_stub_init; +- engine->gpio.takedown = nouveau_stub_takedown; +- engine->gpio.get = NULL; +- engine->gpio.set = NULL; +- engine->gpio.irq_enable = NULL; +- engine->pm.clock_get = nv04_pm_clock_get; +- engine->pm.clock_pre = nv04_pm_clock_pre; +- engine->pm.clock_set = nv04_pm_clock_set; +- engine->vram.init = nouveau_mem_detect; ++ engine->display.init = nv04_display_init; ++ engine->display.fini = nv04_display_fini; ++ engine->pm.clocks_get = nv04_pm_clocks_get; ++ engine->pm.clocks_pre = nv04_pm_clocks_pre; ++ engine->pm.clocks_set = nv04_pm_clocks_set; ++ engine->vram.init = nv04_fb_vram_init; + engine->vram.takedown = nouveau_stub_takedown; + engine->vram.flags_valid = nouveau_mem_flags_valid; + break; +@@ -130,17 +127,19 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->display.early_init = nv04_display_early_init; + engine->display.late_takedown = nv04_display_late_takedown; + engine->display.create = nv04_display_create; +- engine->display.init = nv04_display_init; + engine->display.destroy = nv04_display_destroy; +- engine->gpio.init = nouveau_stub_init; +- engine->gpio.takedown = nouveau_stub_takedown; +- engine->gpio.get = nv10_gpio_get; +- engine->gpio.set = nv10_gpio_set; +- engine->gpio.irq_enable = NULL; +- engine->pm.clock_get = nv04_pm_clock_get; +- engine->pm.clock_pre = nv04_pm_clock_pre; +- engine->pm.clock_set = nv04_pm_clock_set; +- engine->vram.init = nouveau_mem_detect; ++ engine->display.init = nv04_display_init; ++ engine->display.fini = nv04_display_fini; ++ engine->gpio.drive = nv10_gpio_drive; ++ engine->gpio.sense = nv10_gpio_sense; ++ engine->pm.clocks_get = nv04_pm_clocks_get; ++ engine->pm.clocks_pre = nv04_pm_clocks_pre; ++ engine->pm.clocks_set = nv04_pm_clocks_set; ++ if (dev_priv->chipset == 0x1a || ++ dev_priv->chipset == 0x1f) ++ engine->vram.init = nv1a_fb_vram_init; ++ else ++ engine->vram.init = nv10_fb_vram_init; + engine->vram.takedown = nouveau_stub_takedown; + engine->vram.flags_valid = nouveau_mem_flags_valid; + break; +@@ -159,11 +158,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + engine->timer.takedown = nv04_timer_takedown; +- engine->fb.init = nv10_fb_init; +- engine->fb.takedown = nv10_fb_takedown; +- engine->fb.init_tile_region = nv10_fb_init_tile_region; +- engine->fb.set_tile_region = nv10_fb_set_tile_region; +- engine->fb.free_tile_region = nv10_fb_free_tile_region; ++ engine->fb.init = nv20_fb_init; ++ engine->fb.takedown = nv20_fb_takedown; ++ engine->fb.init_tile_region = nv20_fb_init_tile_region; ++ engine->fb.set_tile_region = nv20_fb_set_tile_region; ++ engine->fb.free_tile_region = nv20_fb_free_tile_region; + engine->fifo.channels = 32; + engine->fifo.init = nv10_fifo_init; + engine->fifo.takedown = nv04_fifo_fini; +@@ -179,17 +178,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->display.early_init = nv04_display_early_init; + engine->display.late_takedown = nv04_display_late_takedown; + engine->display.create = nv04_display_create; +- engine->display.init = nv04_display_init; + engine->display.destroy = nv04_display_destroy; +- engine->gpio.init = nouveau_stub_init; +- engine->gpio.takedown = nouveau_stub_takedown; +- engine->gpio.get = nv10_gpio_get; +- engine->gpio.set = nv10_gpio_set; +- engine->gpio.irq_enable = NULL; +- engine->pm.clock_get = nv04_pm_clock_get; +- engine->pm.clock_pre = nv04_pm_clock_pre; +- engine->pm.clock_set = nv04_pm_clock_set; +- engine->vram.init = nouveau_mem_detect; ++ engine->display.init = nv04_display_init; ++ engine->display.fini = nv04_display_fini; ++ engine->gpio.drive = nv10_gpio_drive; ++ engine->gpio.sense = nv10_gpio_sense; ++ engine->pm.clocks_get = nv04_pm_clocks_get; ++ engine->pm.clocks_pre = nv04_pm_clocks_pre; ++ engine->pm.clocks_set = nv04_pm_clocks_set; ++ engine->vram.init = nv20_fb_vram_init; + engine->vram.takedown = nouveau_stub_takedown; + engine->vram.flags_valid = nouveau_mem_flags_valid; + break; +@@ -228,19 +225,17 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->display.early_init = nv04_display_early_init; + engine->display.late_takedown = nv04_display_late_takedown; + engine->display.create = nv04_display_create; +- engine->display.init = nv04_display_init; + engine->display.destroy = nv04_display_destroy; +- engine->gpio.init = nouveau_stub_init; +- engine->gpio.takedown = nouveau_stub_takedown; +- engine->gpio.get = nv10_gpio_get; +- engine->gpio.set = nv10_gpio_set; +- engine->gpio.irq_enable = NULL; +- engine->pm.clock_get = nv04_pm_clock_get; +- engine->pm.clock_pre = nv04_pm_clock_pre; +- engine->pm.clock_set = nv04_pm_clock_set; ++ engine->display.init = nv04_display_init; ++ engine->display.fini = nv04_display_fini; ++ engine->gpio.drive = nv10_gpio_drive; ++ engine->gpio.sense = nv10_gpio_sense; ++ engine->pm.clocks_get = nv04_pm_clocks_get; ++ engine->pm.clocks_pre = nv04_pm_clocks_pre; ++ engine->pm.clocks_set = nv04_pm_clocks_set; + engine->pm.voltage_get = nouveau_voltage_gpio_get; + engine->pm.voltage_set = nouveau_voltage_gpio_set; +- engine->vram.init = nouveau_mem_detect; ++ engine->vram.init = nv20_fb_vram_init; + engine->vram.takedown = nouveau_stub_takedown; + engine->vram.flags_valid = nouveau_mem_flags_valid; + break; +@@ -280,20 +275,23 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->display.early_init = nv04_display_early_init; + engine->display.late_takedown = nv04_display_late_takedown; + engine->display.create = nv04_display_create; +- engine->display.init = nv04_display_init; + engine->display.destroy = nv04_display_destroy; +- engine->gpio.init = nouveau_stub_init; +- engine->gpio.takedown = nouveau_stub_takedown; +- engine->gpio.get = nv10_gpio_get; +- engine->gpio.set = nv10_gpio_set; +- engine->gpio.irq_enable = NULL; ++ engine->display.init = nv04_display_init; ++ engine->display.fini = nv04_display_fini; ++ engine->gpio.init = nv10_gpio_init; ++ engine->gpio.fini = nv10_gpio_fini; ++ engine->gpio.drive = nv10_gpio_drive; ++ engine->gpio.sense = nv10_gpio_sense; ++ engine->gpio.irq_enable = nv10_gpio_irq_enable; + engine->pm.clocks_get = nv40_pm_clocks_get; + engine->pm.clocks_pre = nv40_pm_clocks_pre; + engine->pm.clocks_set = nv40_pm_clocks_set; + engine->pm.voltage_get = nouveau_voltage_gpio_get; + engine->pm.voltage_set = nouveau_voltage_gpio_set; + engine->pm.temp_get = nv40_temp_get; +- engine->vram.init = nouveau_mem_detect; ++ engine->pm.pwm_get = nv40_pm_pwm_get; ++ engine->pm.pwm_set = nv40_pm_pwm_set; ++ engine->vram.init = nv40_fb_vram_init; + engine->vram.takedown = nouveau_stub_takedown; + engine->vram.flags_valid = nouveau_mem_flags_valid; + break; +@@ -335,14 +333,13 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->display.early_init = nv50_display_early_init; + engine->display.late_takedown = nv50_display_late_takedown; + engine->display.create = nv50_display_create; +- engine->display.init = nv50_display_init; + engine->display.destroy = nv50_display_destroy; ++ engine->display.init = nv50_display_init; ++ engine->display.fini = nv50_display_fini; + engine->gpio.init = nv50_gpio_init; +- engine->gpio.takedown = nv50_gpio_fini; +- engine->gpio.get = nv50_gpio_get; +- engine->gpio.set = nv50_gpio_set; +- engine->gpio.irq_register = nv50_gpio_irq_register; +- engine->gpio.irq_unregister = nv50_gpio_irq_unregister; ++ engine->gpio.fini = nv50_gpio_fini; ++ engine->gpio.drive = nv50_gpio_drive; ++ engine->gpio.sense = nv50_gpio_sense; + engine->gpio.irq_enable = nv50_gpio_irq_enable; + switch (dev_priv->chipset) { + case 0x84: +@@ -355,9 +352,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + case 0xaa: + case 0xac: + case 0x50: +- engine->pm.clock_get = nv50_pm_clock_get; +- engine->pm.clock_pre = nv50_pm_clock_pre; +- engine->pm.clock_set = nv50_pm_clock_set; ++ engine->pm.clocks_get = nv50_pm_clocks_get; ++ engine->pm.clocks_pre = nv50_pm_clocks_pre; ++ engine->pm.clocks_set = nv50_pm_clocks_set; + break; + default: + engine->pm.clocks_get = nva3_pm_clocks_get; +@@ -371,6 +368,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->pm.temp_get = nv84_temp_get; + else + engine->pm.temp_get = nv40_temp_get; ++ engine->pm.pwm_get = nv50_pm_pwm_get; ++ engine->pm.pwm_set = nv50_pm_pwm_set; + engine->vram.init = nv50_vram_init; + engine->vram.takedown = nv50_vram_fini; + engine->vram.get = nv50_vram_new; +@@ -408,14 +407,13 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->display.early_init = nv50_display_early_init; + engine->display.late_takedown = nv50_display_late_takedown; + engine->display.create = nv50_display_create; +- engine->display.init = nv50_display_init; + engine->display.destroy = nv50_display_destroy; ++ engine->display.init = nv50_display_init; ++ engine->display.fini = nv50_display_fini; + engine->gpio.init = nv50_gpio_init; +- engine->gpio.takedown = nouveau_stub_takedown; +- engine->gpio.get = nv50_gpio_get; +- engine->gpio.set = nv50_gpio_set; +- engine->gpio.irq_register = nv50_gpio_irq_register; +- engine->gpio.irq_unregister = nv50_gpio_irq_unregister; ++ engine->gpio.fini = nv50_gpio_fini; ++ engine->gpio.drive = nv50_gpio_drive; ++ engine->gpio.sense = nv50_gpio_sense; + engine->gpio.irq_enable = nv50_gpio_irq_enable; + engine->vram.init = nvc0_vram_init; + engine->vram.takedown = nv50_vram_fini; +@@ -424,8 +422,12 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->vram.flags_valid = nvc0_vram_flags_valid; + engine->pm.temp_get = nv84_temp_get; + engine->pm.clocks_get = nvc0_pm_clocks_get; ++ engine->pm.clocks_pre = nvc0_pm_clocks_pre; ++ engine->pm.clocks_set = nvc0_pm_clocks_set; + engine->pm.voltage_get = nouveau_voltage_gpio_get; + engine->pm.voltage_set = nouveau_voltage_gpio_set; ++ engine->pm.pwm_get = nv50_pm_pwm_get; ++ engine->pm.pwm_set = nv50_pm_pwm_set; + break; + case 0xd0: + engine->instmem.init = nvc0_instmem_init; +@@ -458,24 +460,67 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->display.early_init = nouveau_stub_init; + engine->display.late_takedown = nouveau_stub_takedown; + engine->display.create = nvd0_display_create; +- engine->display.init = nvd0_display_init; + engine->display.destroy = nvd0_display_destroy; ++ engine->display.init = nvd0_display_init; ++ engine->display.fini = nvd0_display_fini; + engine->gpio.init = nv50_gpio_init; +- engine->gpio.takedown = nouveau_stub_takedown; +- engine->gpio.get = nvd0_gpio_get; +- engine->gpio.set = nvd0_gpio_set; +- engine->gpio.irq_register = nv50_gpio_irq_register; +- engine->gpio.irq_unregister = nv50_gpio_irq_unregister; ++ engine->gpio.fini = nv50_gpio_fini; ++ engine->gpio.drive = nvd0_gpio_drive; ++ engine->gpio.sense = nvd0_gpio_sense; + engine->gpio.irq_enable = nv50_gpio_irq_enable; + engine->vram.init = nvc0_vram_init; + engine->vram.takedown = nv50_vram_fini; + engine->vram.get = nvc0_vram_new; + engine->vram.put = nv50_vram_del; + engine->vram.flags_valid = nvc0_vram_flags_valid; ++ engine->pm.temp_get = nv84_temp_get; + engine->pm.clocks_get = nvc0_pm_clocks_get; ++ engine->pm.clocks_pre = nvc0_pm_clocks_pre; ++ engine->pm.clocks_set = nvc0_pm_clocks_set; + engine->pm.voltage_get = nouveau_voltage_gpio_get; + engine->pm.voltage_set = nouveau_voltage_gpio_set; + break; ++ case 0xe0: ++ engine->instmem.init = nvc0_instmem_init; ++ engine->instmem.takedown = nvc0_instmem_takedown; ++ engine->instmem.suspend = nvc0_instmem_suspend; ++ engine->instmem.resume = nvc0_instmem_resume; ++ engine->instmem.get = nv50_instmem_get; ++ engine->instmem.put = nv50_instmem_put; ++ engine->instmem.map = nv50_instmem_map; ++ engine->instmem.unmap = nv50_instmem_unmap; ++ engine->instmem.flush = nv84_instmem_flush; ++ engine->mc.init = nv50_mc_init; ++ engine->mc.takedown = nv50_mc_takedown; ++ engine->timer.init = nv04_timer_init; ++ engine->timer.read = nv04_timer_read; ++ engine->timer.takedown = nv04_timer_takedown; ++ engine->fb.init = nvc0_fb_init; ++ engine->fb.takedown = nvc0_fb_takedown; ++ engine->fifo.channels = 0; ++ engine->fifo.init = nouveau_stub_init; ++ engine->fifo.takedown = nouveau_stub_takedown; ++ engine->fifo.disable = nvc0_fifo_disable; ++ engine->fifo.enable = nvc0_fifo_enable; ++ engine->fifo.reassign = nvc0_fifo_reassign; ++ engine->fifo.unload_context = nouveau_stub_init; ++ engine->display.early_init = nouveau_stub_init; ++ engine->display.late_takedown = nouveau_stub_takedown; ++ engine->display.create = nvd0_display_create; ++ engine->display.destroy = nvd0_display_destroy; ++ engine->display.init = nvd0_display_init; ++ engine->display.fini = nvd0_display_fini; ++ engine->gpio.init = nv50_gpio_init; ++ engine->gpio.fini = nv50_gpio_fini; ++ engine->gpio.drive = nvd0_gpio_drive; ++ engine->gpio.sense = nvd0_gpio_sense; ++ engine->gpio.irq_enable = nv50_gpio_irq_enable; ++ engine->vram.init = nvc0_vram_init; ++ engine->vram.takedown = nv50_vram_fini; ++ engine->vram.get = nvc0_vram_new; ++ engine->vram.put = nv50_vram_del; ++ engine->vram.flags_valid = nvc0_vram_flags_valid; ++ break; + default: + NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); + return 1; +@@ -527,6 +572,7 @@ static void nouveau_switcheroo_set_state(struct pci_dev *pdev, + printk(KERN_ERR "VGA switcheroo: switched nouveau off\n"); + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; + drm_kms_helper_poll_disable(dev); ++ nouveau_switcheroo_optimus_dsm(); + nouveau_pci_suspend(pdev, pmm); + dev->switch_power_state = DRM_SWITCH_POWER_OFF; + } +@@ -549,6 +595,75 @@ static bool nouveau_switcheroo_can_switch(struct pci_dev *pdev) + return can_switch; + } + ++static void ++nouveau_card_channel_fini(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ if (dev_priv->channel) ++ nouveau_channel_put_unlocked(&dev_priv->channel); ++} ++ ++static int ++nouveau_card_channel_init(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_channel *chan; ++ int ret, oclass; ++ ++ ret = nouveau_channel_alloc(dev, &chan, NULL, NvDmaFB, NvDmaTT); ++ dev_priv->channel = chan; ++ if (ret) ++ return ret; ++ ++ mutex_unlock(&dev_priv->channel->mutex); ++ ++ if (dev_priv->card_type <= NV_50) { ++ if (dev_priv->card_type < NV_50) ++ oclass = 0x0039; ++ else ++ oclass = 0x5039; ++ ++ ret = nouveau_gpuobj_gr_new(chan, NvM2MF, oclass); ++ if (ret) ++ goto error; ++ ++ ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfe0, 0x1000, ++ &chan->m2mf_ntfy); ++ if (ret) ++ goto error; ++ ++ ret = RING_SPACE(chan, 6); ++ if (ret) ++ goto error; ++ ++ BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1); ++ OUT_RING (chan, NvM2MF); ++ BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3); ++ OUT_RING (chan, NvNotify0); ++ OUT_RING (chan, chan->vram_handle); ++ OUT_RING (chan, chan->gart_handle); ++ } else ++ if (dev_priv->card_type <= NV_D0) { ++ ret = nouveau_gpuobj_gr_new(chan, 0x9039, 0x9039); ++ if (ret) ++ goto error; ++ ++ ret = RING_SPACE(chan, 2); ++ if (ret) ++ goto error; ++ ++ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0000, 1); ++ OUT_RING (chan, 0x00009039); ++ } ++ ++ FIRE_RING (chan); ++error: ++ if (ret) ++ nouveau_card_channel_fini(dev); ++ return ret; ++} ++ + int + nouveau_card_init(struct drm_device *dev) + { +@@ -589,47 +704,45 @@ nouveau_card_init(struct drm_device *dev) + nv_mask(dev, 0x00088080, 0x00000800, 0x00000000); + } + +- nouveau_pm_init(dev); +- +- ret = engine->vram.init(dev); ++ /* PMC */ ++ ret = engine->mc.init(dev); + if (ret) + goto out_bios; + +- ret = nouveau_gpuobj_init(dev); ++ /* PTIMER */ ++ ret = engine->timer.init(dev); + if (ret) +- goto out_vram; ++ goto out_mc; + +- ret = engine->instmem.init(dev); ++ /* PFB */ ++ ret = engine->fb.init(dev); + if (ret) +- goto out_gpuobj; ++ goto out_timer; + +- ret = nouveau_mem_vram_init(dev); ++ ret = engine->vram.init(dev); + if (ret) +- goto out_instmem; ++ goto out_fb; + +- ret = nouveau_mem_gart_init(dev); ++ /* PGPIO */ ++ ret = nouveau_gpio_create(dev); + if (ret) +- goto out_ttmvram; ++ goto out_vram; + +- /* PMC */ +- ret = engine->mc.init(dev); ++ ret = nouveau_gpuobj_init(dev); + if (ret) +- goto out_gart; ++ goto out_gpio; + +- /* PGPIO */ +- ret = engine->gpio.init(dev); ++ ret = engine->instmem.init(dev); + if (ret) +- goto out_mc; ++ goto out_gpuobj; + +- /* PTIMER */ +- ret = engine->timer.init(dev); ++ ret = nouveau_mem_vram_init(dev); + if (ret) +- goto out_gpio; ++ goto out_instmem; + +- /* PFB */ +- ret = engine->fb.init(dev); ++ ret = nouveau_mem_gart_init(dev); + if (ret) +- goto out_timer; ++ goto out_ttmvram; + + if (!dev_priv->noaccel) { + switch (dev_priv->card_type) { +@@ -650,6 +763,7 @@ nouveau_card_init(struct drm_device *dev) + nv50_graph_create(dev); + break; + case NV_C0: ++ case NV_D0: + nvc0_graph_create(dev); + break; + default: +@@ -665,6 +779,11 @@ nouveau_card_init(struct drm_device *dev) + case 0xa0: + nv84_crypt_create(dev); + break; ++ case 0x98: ++ case 0xaa: ++ case 0xac: ++ nv98_crypt_create(dev); ++ break; + } + + switch (dev_priv->card_type) { +@@ -686,15 +805,25 @@ nouveau_card_init(struct drm_device *dev) + break; + } + ++ if (dev_priv->chipset >= 0xa3 || dev_priv->chipset == 0x98) { ++ nv84_bsp_create(dev); ++ nv84_vp_create(dev); ++ nv98_ppp_create(dev); ++ } else ++ if (dev_priv->chipset >= 0x84) { ++ nv50_mpeg_create(dev); ++ nv84_bsp_create(dev); ++ nv84_vp_create(dev); ++ } else ++ if (dev_priv->chipset >= 0x50) { ++ nv50_mpeg_create(dev); ++ } else + if (dev_priv->card_type == NV_40 || + dev_priv->chipset == 0x31 || + dev_priv->chipset == 0x34 || +- dev_priv->chipset == 0x36) ++ dev_priv->chipset == 0x36) { + nv31_mpeg_create(dev); +- else +- if (dev_priv->card_type == NV_50 && +- (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0)) +- nv50_mpeg_create(dev); ++ } + + for (e = 0; e < NVOBJ_ENGINE_NR; e++) { + if (dev_priv->eng[e]) { +@@ -714,63 +843,41 @@ nouveau_card_init(struct drm_device *dev) + if (ret) + goto out_fifo; + +- /* initialise general modesetting */ +- drm_mode_config_init(dev); +- drm_mode_create_scaling_mode_property(dev); +- drm_mode_create_dithering_property(dev); +- dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; +- dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); +- dev->mode_config.min_width = 0; +- dev->mode_config.min_height = 0; +- if (dev_priv->card_type < NV_10) { +- dev->mode_config.max_width = 2048; +- dev->mode_config.max_height = 2048; +- } else +- if (dev_priv->card_type < NV_50) { +- dev->mode_config.max_width = 4096; +- dev->mode_config.max_height = 4096; +- } else { +- dev->mode_config.max_width = 8192; +- dev->mode_config.max_height = 8192; +- } +- +- ret = engine->display.create(dev); ++ ret = nouveau_display_create(dev); + if (ret) + goto out_irq; + + nouveau_backlight_init(dev); ++ nouveau_pm_init(dev); + +- if (dev_priv->eng[NVOBJ_ENGINE_GR]) { +- ret = nouveau_fence_init(dev); +- if (ret) +- goto out_disp; ++ ret = nouveau_fence_init(dev); ++ if (ret) ++ goto out_pm; + +- ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL, +- NvDmaFB, NvDmaTT); ++ if (dev_priv->eng[NVOBJ_ENGINE_GR]) { ++ ret = nouveau_card_channel_init(dev); + if (ret) + goto out_fence; +- +- mutex_unlock(&dev_priv->channel->mutex); + } + + if (dev->mode_config.num_crtc) { +- ret = drm_vblank_init(dev, dev->mode_config.num_crtc); ++ ret = nouveau_display_init(dev); + if (ret) + goto out_chan; + + nouveau_fbcon_init(dev); +- drm_kms_helper_poll_init(dev); + } + + return 0; + + out_chan: +- nouveau_channel_put_unlocked(&dev_priv->channel); ++ nouveau_card_channel_fini(dev); + out_fence: + nouveau_fence_fini(dev); +-out_disp: ++out_pm: ++ nouveau_pm_fini(dev); + nouveau_backlight_exit(dev); +- engine->display.destroy(dev); ++ nouveau_display_destroy(dev); + out_irq: + nouveau_irq_fini(dev); + out_fifo: +@@ -785,15 +892,6 @@ out_engine: + dev_priv->eng[e]->destroy(dev,e ); + } + } +- +- engine->fb.takedown(dev); +-out_timer: +- engine->timer.takedown(dev); +-out_gpio: +- engine->gpio.takedown(dev); +-out_mc: +- engine->mc.takedown(dev); +-out_gart: + nouveau_mem_gart_fini(dev); + out_ttmvram: + nouveau_mem_vram_fini(dev); +@@ -801,10 +899,17 @@ out_instmem: + engine->instmem.takedown(dev); + out_gpuobj: + nouveau_gpuobj_takedown(dev); ++out_gpio: ++ nouveau_gpio_destroy(dev); + out_vram: + engine->vram.takedown(dev); ++out_fb: ++ engine->fb.takedown(dev); ++out_timer: ++ engine->timer.takedown(dev); ++out_mc: ++ engine->mc.takedown(dev); + out_bios: +- nouveau_pm_fini(dev); + nouveau_bios_takedown(dev); + out_display_early: + engine->display.late_takedown(dev); +@@ -820,19 +925,15 @@ static void nouveau_card_takedown(struct drm_device *dev) + int e; + + if (dev->mode_config.num_crtc) { +- drm_kms_helper_poll_fini(dev); + nouveau_fbcon_fini(dev); +- drm_vblank_cleanup(dev); +- } +- +- if (dev_priv->channel) { +- nouveau_channel_put_unlocked(&dev_priv->channel); +- nouveau_fence_fini(dev); ++ nouveau_display_fini(dev); + } + ++ nouveau_card_channel_fini(dev); ++ nouveau_fence_fini(dev); ++ nouveau_pm_fini(dev); + nouveau_backlight_exit(dev); +- engine->display.destroy(dev); +- drm_mode_config_cleanup(dev); ++ nouveau_display_destroy(dev); + + if (!dev_priv->noaccel) { + engine->fifo.takedown(dev); +@@ -843,11 +944,6 @@ static void nouveau_card_takedown(struct drm_device *dev) + } + } + } +- engine->fb.takedown(dev); +- engine->timer.takedown(dev); +- engine->gpio.takedown(dev); +- engine->mc.takedown(dev); +- engine->display.late_takedown(dev); + + if (dev_priv->vga_ram) { + nouveau_bo_unpin(dev_priv->vga_ram); +@@ -863,12 +959,17 @@ static void nouveau_card_takedown(struct drm_device *dev) + + engine->instmem.takedown(dev); + nouveau_gpuobj_takedown(dev); +- engine->vram.takedown(dev); + +- nouveau_irq_fini(dev); ++ nouveau_gpio_destroy(dev); ++ engine->vram.takedown(dev); ++ engine->fb.takedown(dev); ++ engine->timer.takedown(dev); ++ engine->mc.takedown(dev); + +- nouveau_pm_fini(dev); + nouveau_bios_takedown(dev); ++ engine->display.late_takedown(dev); ++ ++ nouveau_irq_fini(dev); + + vga_client_register(dev->pdev, NULL, NULL, NULL); + } +@@ -998,8 +1099,8 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev) + int nouveau_load(struct drm_device *dev, unsigned long flags) + { + struct drm_nouveau_private *dev_priv; +- uint32_t reg0, strap; +- resource_size_t mmio_start_offs; ++ unsigned long long offset, length; ++ uint32_t reg0 = ~0, strap; + int ret; + + dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); +@@ -1010,83 +1111,90 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) + dev->dev_private = dev_priv; + dev_priv->dev = dev; + ++ pci_set_master(dev->pdev); ++ + dev_priv->flags = flags & NOUVEAU_FLAGS; + + NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", + dev->pci_vendor, dev->pci_device, dev->pdev->class); + +- /* resource 0 is mmio regs */ +- /* resource 1 is linear FB */ +- /* resource 2 is RAMIN (mmio regs + 0x1000000) */ +- /* resource 6 is bios */ ++ /* first up, map the start of mmio and determine the chipset */ ++ dev_priv->mmio = ioremap(pci_resource_start(dev->pdev, 0), PAGE_SIZE); ++ if (dev_priv->mmio) { ++#ifdef __BIG_ENDIAN ++ /* put the card into big-endian mode if it's not */ ++ if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001) ++ nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001); ++ DRM_MEMORYBARRIER(); ++#endif + +- /* map the mmio regs */ +- mmio_start_offs = pci_resource_start(dev->pdev, 0); +- dev_priv->mmio = ioremap(mmio_start_offs, 0x00800000); +- if (!dev_priv->mmio) { +- NV_ERROR(dev, "Unable to initialize the mmio mapping. " +- "Please report your setup to " DRIVER_EMAIL "\n"); ++ /* determine chipset and derive architecture from it */ ++ reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); ++ if ((reg0 & 0x0f000000) > 0) { ++ dev_priv->chipset = (reg0 & 0xff00000) >> 20; ++ switch (dev_priv->chipset & 0xf0) { ++ case 0x10: ++ case 0x20: ++ case 0x30: ++ dev_priv->card_type = dev_priv->chipset & 0xf0; ++ break; ++ case 0x40: ++ case 0x60: ++ dev_priv->card_type = NV_40; ++ break; ++ case 0x50: ++ case 0x80: ++ case 0x90: ++ case 0xa0: ++ dev_priv->card_type = NV_50; ++ break; ++ case 0xc0: ++ dev_priv->card_type = NV_C0; ++ break; ++ case 0xd0: ++ dev_priv->card_type = NV_D0; ++ break; ++ case 0xe0: ++ dev_priv->card_type = NV_E0; ++ break; ++ default: ++ break; ++ } ++ } else ++ if ((reg0 & 0xff00fff0) == 0x20004000) { ++ if (reg0 & 0x00f00000) ++ dev_priv->chipset = 0x05; ++ else ++ dev_priv->chipset = 0x04; ++ dev_priv->card_type = NV_04; ++ } ++ ++ iounmap(dev_priv->mmio); ++ } ++ ++ if (!dev_priv->card_type) { ++ NV_ERROR(dev, "unsupported chipset 0x%08x\n", reg0); + ret = -EINVAL; + goto err_priv; + } +- NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", +- (unsigned long long)mmio_start_offs); + +-#ifdef __BIG_ENDIAN +- /* Put the card in BE mode if it's not */ +- if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001) +- nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001); ++ NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", ++ dev_priv->card_type, reg0); + +- DRM_MEMORYBARRIER(); +-#endif ++ /* map the mmio regs, limiting the amount to preserve vmap space */ ++ offset = pci_resource_start(dev->pdev, 0); ++ length = pci_resource_len(dev->pdev, 0); ++ if (dev_priv->card_type < NV_E0) ++ length = min(length, (unsigned long long)0x00800000); + +- /* Time to determine the card architecture */ +- reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); +- +- /* We're dealing with >=NV10 */ +- if ((reg0 & 0x0f000000) > 0) { +- /* Bit 27-20 contain the architecture in hex */ +- dev_priv->chipset = (reg0 & 0xff00000) >> 20; +- /* NV04 or NV05 */ +- } else if ((reg0 & 0xff00fff0) == 0x20004000) { +- if (reg0 & 0x00f00000) +- dev_priv->chipset = 0x05; +- else +- dev_priv->chipset = 0x04; +- } else +- dev_priv->chipset = 0xff; +- +- switch (dev_priv->chipset & 0xf0) { +- case 0x00: +- case 0x10: +- case 0x20: +- case 0x30: +- dev_priv->card_type = dev_priv->chipset & 0xf0; +- break; +- case 0x40: +- case 0x60: +- dev_priv->card_type = NV_40; +- break; +- case 0x50: +- case 0x80: +- case 0x90: +- case 0xa0: +- dev_priv->card_type = NV_50; +- break; +- case 0xc0: +- dev_priv->card_type = NV_C0; +- break; +- case 0xd0: +- dev_priv->card_type = NV_D0; +- break; +- default: +- NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); ++ dev_priv->mmio = ioremap(offset, length); ++ if (!dev_priv->mmio) { ++ NV_ERROR(dev, "Unable to initialize the mmio mapping. " ++ "Please report your setup to " DRIVER_EMAIL "\n"); + ret = -EINVAL; +- goto err_mmio; ++ goto err_priv; + } +- +- NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", +- dev_priv->card_type, reg0); ++ NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", offset); + + /* determine frequency of timing crystal */ + strap = nv_rd32(dev, 0x101000); +@@ -1112,13 +1220,11 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) + dev_priv->noaccel = !!nouveau_noaccel; + if (nouveau_noaccel == -1) { + switch (dev_priv->chipset) { +-#if 0 +- case 0xXX: /* known broken */ ++ case 0xd9: /* known broken */ + NV_INFO(dev, "acceleration disabled by default, pass " + "noaccel=0 to force enable\n"); + dev_priv->noaccel = true; + break; +-#endif + default: + dev_priv->noaccel = false; + break; +@@ -1146,7 +1252,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) + } + } else { + dev_priv->ramin_size = 1 * 1024 * 1024; +- dev_priv->ramin = ioremap(mmio_start_offs + NV_RAMIN, ++ dev_priv->ramin = ioremap(offset + NV_RAMIN, + dev_priv->ramin_size); + if (!dev_priv->ramin) { + NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n"); +@@ -1240,7 +1346,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, + getparam->value = 1; + break; + case NOUVEAU_GETPARAM_HAS_PAGEFLIP: +- getparam->value = dev_priv->card_type < NV_D0; ++ getparam->value = 1; + break; + case NOUVEAU_GETPARAM_GRAPH_UNITS: + /* NV40 and NV50 versions are quite different, but register +diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c +index 5a46446..0f5a301 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_temp.c ++++ b/drivers/gpu/drm/nouveau/nouveau_temp.c +@@ -55,6 +55,10 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) + temps->down_clock = 100; + temps->fan_boost = 90; + ++ /* Set the default range for the pwm fan */ ++ pm->fan.min_duty = 30; ++ pm->fan.max_duty = 100; ++ + /* Set the known default values to setup the temperature sensor */ + if (dev_priv->card_type >= NV_40) { + switch (dev_priv->chipset) { +@@ -156,11 +160,26 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) + case 0x13: + sensor->slope_div = value; + break; ++ case 0x22: ++ pm->fan.min_duty = value & 0xff; ++ pm->fan.max_duty = (value & 0xff00) >> 8; ++ break; ++ case 0x26: ++ pm->fan.pwm_freq = value; ++ break; + } + temp += recordlen; + } + + nouveau_temp_safety_checks(dev); ++ ++ /* check the fan min/max settings */ ++ if (pm->fan.min_duty < 10) ++ pm->fan.min_duty = 10; ++ if (pm->fan.max_duty > 100) ++ pm->fan.max_duty = 100; ++ if (pm->fan.max_duty < pm->fan.min_duty) ++ pm->fan.max_duty = pm->fan.min_duty; + } + + static int +@@ -267,8 +286,6 @@ probe_monitoring_device(struct nouveau_i2c_chan *i2c, + static void + nouveau_temp_probe_i2c(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct dcb_table *dcb = &dev_priv->vbios.dcb; + struct i2c_board_info info[] = { + { I2C_BOARD_INFO("w83l785ts", 0x2d) }, + { I2C_BOARD_INFO("w83781d", 0x2d) }, +@@ -277,11 +294,9 @@ nouveau_temp_probe_i2c(struct drm_device *dev) + { I2C_BOARD_INFO("lm99", 0x4c) }, + { } + }; +- int idx = (dcb->version >= 0x40 ? +- dcb->i2c_default_indices & 0xf : 2); + + nouveau_i2c_identify(dev, "monitoring device", info, +- probe_monitoring_device, idx); ++ probe_monitoring_device, NV_I2C_DEFAULT(0)); + } + + void +@@ -297,9 +312,9 @@ nouveau_temp_init(struct drm_device *dev) + return; + + if (P.version == 1) +- temp = ROMPTR(bios, P.data[12]); ++ temp = ROMPTR(dev, P.data[12]); + else if (P.version == 2) +- temp = ROMPTR(bios, P.data[16]); ++ temp = ROMPTR(dev, P.data[16]); + else + NV_WARN(dev, "unknown temp for BIT P %d\n", P.version); + +diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c +index ef0832b..2bf6c03 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_vm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_vm.c +@@ -78,9 +78,10 @@ nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) + + void + nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, +- struct nouveau_mem *mem, dma_addr_t *list) ++ struct nouveau_mem *mem) + { + struct nouveau_vm *vm = vma->vm; ++ dma_addr_t *list = mem->pages; + int big = vma->node->type != vm->spg_shift; + u32 offset = vma->node->offset + (delta >> 12); + u32 bits = vma->node->type - 12; +diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h +index 6ce995f..4fb6e72 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_vm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_vm.h +@@ -89,7 +89,7 @@ void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *); + void nouveau_vm_unmap(struct nouveau_vma *); + void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); + void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, +- struct nouveau_mem *, dma_addr_t *); ++ struct nouveau_mem *); + + /* nv50_vm.c */ + void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, +diff --git a/drivers/gpu/drm/nouveau/nouveau_volt.c b/drivers/gpu/drm/nouveau/nouveau_volt.c +index 86d03e1..b010cb9 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_volt.c ++++ b/drivers/gpu/drm/nouveau/nouveau_volt.c +@@ -26,6 +26,7 @@ + + #include "nouveau_drv.h" + #include "nouveau_pm.h" ++#include "nouveau_gpio.h" + + static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; + static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); +@@ -34,7 +35,6 @@ int + nouveau_voltage_gpio_get(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; + struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; + u8 vid = 0; + int i; +@@ -43,7 +43,7 @@ nouveau_voltage_gpio_get(struct drm_device *dev) + if (!(volt->vid_mask & (1 << i))) + continue; + +- vid |= gpio->get(dev, vidtag[i]) << i; ++ vid |= nouveau_gpio_func_get(dev, vidtag[i]) << i; + } + + return nouveau_volt_lvl_lookup(dev, vid); +@@ -53,7 +53,6 @@ int + nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; + struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; + int vid, i; + +@@ -65,7 +64,7 @@ nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) + if (!(volt->vid_mask & (1 << i))) + continue; + +- gpio->set(dev, vidtag[i], !!(vid & (1 << i))); ++ nouveau_gpio_func_set(dev, vidtag[i], !!(vid & (1 << i))); + } + + return 0; +@@ -117,10 +116,10 @@ nouveau_volt_init(struct drm_device *dev) + return; + + if (P.version == 1) +- volt = ROMPTR(bios, P.data[16]); ++ volt = ROMPTR(dev, P.data[16]); + else + if (P.version == 2) +- volt = ROMPTR(bios, P.data[12]); ++ volt = ROMPTR(dev, P.data[12]); + else { + NV_WARN(dev, "unknown volt for BIT P %d\n", P.version); + } +@@ -130,7 +129,7 @@ nouveau_volt_init(struct drm_device *dev) + return; + } + +- volt = ROMPTR(bios, bios->data[bios->offset + 0x98]); ++ volt = ROMPTR(dev, bios->data[bios->offset + 0x98]); + } + + if (!volt) { +@@ -194,7 +193,7 @@ nouveau_volt_init(struct drm_device *dev) + return; + } + +- if (!nouveau_bios_gpio_entry(dev, vidtag[i])) { ++ if (!nouveau_gpio_func_valid(dev, vidtag[i])) { + NV_DEBUG(dev, "vid bit %d has no gpio tag\n", i); + return; + } +diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c +index 5e45398..728d075 100644 +--- a/drivers/gpu/drm/nouveau/nv04_crtc.c ++++ b/drivers/gpu/drm/nouveau/nv04_crtc.c +@@ -364,7 +364,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) + regp->CRTC[NV_CIO_CR_VRE_INDEX] = 1 << 5 | XLATE(vertEnd, 0, NV_CIO_CR_VRE_3_0); + regp->CRTC[NV_CIO_CR_VDE_INDEX] = vertDisplay; + /* framebuffer can be larger than crtc scanout area. */ +- regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = fb->pitch / 8; ++ regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = fb->pitches[0] / 8; + regp->CRTC[NV_CIO_CR_ULINE_INDEX] = 0x00; + regp->CRTC[NV_CIO_CR_VBS_INDEX] = vertBlankStart; + regp->CRTC[NV_CIO_CR_VBE_INDEX] = vertBlankEnd; +@@ -377,9 +377,9 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) + + /* framebuffer can be larger than crtc scanout area. */ + regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = +- XLATE(fb->pitch / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); ++ XLATE(fb->pitches[0] / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); + regp->CRTC[NV_CIO_CRE_42] = +- XLATE(fb->pitch / 8, 11, NV_CIO_CRE_42_OFFSET_11); ++ XLATE(fb->pitches[0] / 8, 11, NV_CIO_CRE_42_OFFSET_11); + regp->CRTC[NV_CIO_CRE_RPC1_INDEX] = mode->crtc_hdisplay < 1280 ? + MASK(NV_CIO_CRE_RPC1_LARGE) : 0x00; + regp->CRTC[NV_CIO_CRE_LSR_INDEX] = XLATE(horizBlankEnd, 6, NV_CIO_CRE_LSR_HBE_6) | +@@ -835,18 +835,18 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, + NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL, + regp->ramdac_gen_ctrl); + +- regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = drm_fb->pitch >> 3; ++ regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = drm_fb->pitches[0] >> 3; + regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = +- XLATE(drm_fb->pitch >> 3, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); ++ XLATE(drm_fb->pitches[0] >> 3, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); + regp->CRTC[NV_CIO_CRE_42] = +- XLATE(drm_fb->pitch / 8, 11, NV_CIO_CRE_42_OFFSET_11); ++ XLATE(drm_fb->pitches[0] / 8, 11, NV_CIO_CRE_42_OFFSET_11); + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_RPC0_INDEX); + crtc_wr_cio_state(crtc, regp, NV_CIO_CR_OFFSET_INDEX); + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_42); + + /* Update the framebuffer location. */ + regp->fb_start = nv_crtc->fb.offset & ~3; +- regp->fb_start += (y * drm_fb->pitch) + (x * drm_fb->bits_per_pixel / 8); ++ regp->fb_start += (y * drm_fb->pitches[0]) + (x * drm_fb->bits_per_pixel / 8); + nv_set_crtc_base(dev, nv_crtc->index, regp->fb_start); + + /* Update the arbitration parameters. */ +diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c +index 2d6bfd0..f180dcf 100644 +--- a/drivers/gpu/drm/nouveau/nv04_dac.c ++++ b/drivers/gpu/drm/nouveau/nv04_dac.c +@@ -32,6 +32,7 @@ + #include "nouveau_connector.h" + #include "nouveau_crtc.h" + #include "nouveau_hw.h" ++#include "nouveau_gpio.h" + #include "nvreg.h" + + int nv04_dac_output_offset(struct drm_encoder *encoder) +@@ -220,7 +221,6 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) + { + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; + struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); + uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, +@@ -252,11 +252,11 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) + nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); + } + +- saved_gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1); +- saved_gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0); ++ saved_gpio1 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC1); ++ saved_gpio0 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC0); + +- gpio->set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV); +- gpio->set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); ++ nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV); ++ nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); + + msleep(4); + +@@ -306,8 +306,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) + nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); + nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); + +- gpio->set(dev, DCB_GPIO_TVDAC1, saved_gpio1); +- gpio->set(dev, DCB_GPIO_TVDAC0, saved_gpio0); ++ nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, saved_gpio1); ++ nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, saved_gpio0); + + return sample; + } +diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c +index 752440c..71b6235 100644 +--- a/drivers/gpu/drm/nouveau/nv04_dfp.c ++++ b/drivers/gpu/drm/nouveau/nv04_dfp.c +@@ -289,6 +289,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, + struct nouveau_connector *nv_connector = nouveau_crtc_connector_get(nv_crtc); + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_display_mode *output_mode = &nv_encoder->mode; ++ struct drm_connector *connector = &nv_connector->base; + uint32_t mode_ratio, panel_ratio; + + NV_DEBUG_KMS(dev, "Output mode on CRTC %d:\n", nv_crtc->index); +@@ -340,10 +341,15 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, + output_mode->clock > 165000) + regp->fp_control |= (2 << 24); + if (nv_encoder->dcb->type == OUTPUT_LVDS) { +- bool duallink, dummy; ++ bool duallink = false, dummy; ++ if (nv_connector->edid && ++ nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) { ++ duallink = (((u8 *)nv_connector->edid)[121] == 2); ++ } else { ++ nouveau_bios_parse_lvds_table(dev, output_mode->clock, ++ &duallink, &dummy); ++ } + +- nouveau_bios_parse_lvds_table(dev, output_mode->clock, +- &duallink, &dummy); + if (duallink) + regp->fp_control |= (8 << 28); + } else +@@ -407,7 +413,9 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, + } + + /* Output property. */ +- if (nv_connector->use_dithering) { ++ if ((nv_connector->dithering_mode == DITHERING_MODE_ON) || ++ (nv_connector->dithering_mode == DITHERING_MODE_AUTO && ++ encoder->crtc->fb->depth > connector->display_info.bpc * 3)) { + if (dev_priv->chipset == 0x11) + regp->dither = savep->dither | 0x00010000; + else { +@@ -496,7 +504,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) + + static inline bool is_powersaving_dpms(int mode) + { +- return (mode != DRM_MODE_DPMS_ON); ++ return mode != DRM_MODE_DPMS_ON && mode != NV_DPMS_CLEARED; + } + + static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) +diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c +index 6bd8518..7047d37 100644 +--- a/drivers/gpu/drm/nouveau/nv04_display.c ++++ b/drivers/gpu/drm/nouveau/nv04_display.c +@@ -243,6 +243,11 @@ nv04_display_init(struct drm_device *dev) + return 0; + } + ++void ++nv04_display_fini(struct drm_device *dev) ++{ ++} ++ + static void + nv04_vblank_crtc0_isr(struct drm_device *dev) + { +diff --git a/drivers/gpu/drm/nouveau/nv04_fb.c b/drivers/gpu/drm/nouveau/nv04_fb.c +index 638cf60..d5eedd6 100644 +--- a/drivers/gpu/drm/nouveau/nv04_fb.c ++++ b/drivers/gpu/drm/nouveau/nv04_fb.c +@@ -4,6 +4,40 @@ + #include "nouveau_drm.h" + + int ++nv04_fb_vram_init(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 boot0 = nv_rd32(dev, NV04_PFB_BOOT_0); ++ ++ if (boot0 & 0x00000100) { ++ dev_priv->vram_size = ((boot0 >> 12) & 0xf) * 2 + 2; ++ dev_priv->vram_size *= 1024 * 1024; ++ } else { ++ switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) { ++ case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB: ++ dev_priv->vram_size = 32 * 1024 * 1024; ++ break; ++ case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB: ++ dev_priv->vram_size = 16 * 1024 * 1024; ++ break; ++ case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB: ++ dev_priv->vram_size = 8 * 1024 * 1024; ++ break; ++ case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB: ++ dev_priv->vram_size = 4 * 1024 * 1024; ++ break; ++ } ++ } ++ ++ if ((boot0 & 0x00000038) <= 0x10) ++ dev_priv->vram_type = NV_MEM_TYPE_SGRAM; ++ else ++ dev_priv->vram_type = NV_MEM_TYPE_SDRAM; ++ ++ return 0; ++} ++ ++int + nv04_fb_init(struct drm_device *dev) + { + /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows +diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c +index 9ae92a8..6e75899 100644 +--- a/drivers/gpu/drm/nouveau/nv04_pm.c ++++ b/drivers/gpu/drm/nouveau/nv04_pm.c +@@ -27,68 +27,111 @@ + #include "nouveau_hw.h" + #include "nouveau_pm.h" + +-struct nv04_pm_state { ++int ++nv04_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ int ret; ++ ++ ret = nouveau_hw_get_clock(dev, PLL_CORE); ++ if (ret < 0) ++ return ret; ++ perflvl->core = ret; ++ ++ ret = nouveau_hw_get_clock(dev, PLL_MEMORY); ++ if (ret < 0) ++ return ret; ++ perflvl->memory = ret; ++ ++ return 0; ++} ++ ++struct nv04_pm_clock { + struct pll_lims pll; + struct nouveau_pll_vals calc; + }; + +-int +-nv04_pm_clock_get(struct drm_device *dev, u32 id) ++struct nv04_pm_state { ++ struct nv04_pm_clock core; ++ struct nv04_pm_clock memory; ++}; ++ ++static int ++calc_pll(struct drm_device *dev, u32 id, int khz, struct nv04_pm_clock *clk) + { +- return nouveau_hw_get_clock(dev, id); ++ int ret; ++ ++ ret = get_pll_limits(dev, id, &clk->pll); ++ if (ret) ++ return ret; ++ ++ ret = nouveau_calc_pll_mnp(dev, &clk->pll, khz, &clk->calc); ++ if (!ret) ++ return -EINVAL; ++ ++ return 0; + } + + void * +-nv04_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, +- u32 id, int khz) ++nv04_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) + { +- struct nv04_pm_state *state; ++ struct nv04_pm_state *info; + int ret; + +- state = kzalloc(sizeof(*state), GFP_KERNEL); +- if (!state) ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) + return ERR_PTR(-ENOMEM); + +- ret = get_pll_limits(dev, id, &state->pll); +- if (ret) { +- kfree(state); +- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); +- } ++ ret = calc_pll(dev, PLL_CORE, perflvl->core, &info->core); ++ if (ret) ++ goto error; + +- ret = nouveau_calc_pll_mnp(dev, &state->pll, khz, &state->calc); +- if (!ret) { +- kfree(state); +- return ERR_PTR(-EINVAL); ++ if (perflvl->memory) { ++ ret = calc_pll(dev, PLL_MEMORY, perflvl->memory, &info->memory); ++ if (ret) ++ goto error; + } + +- return state; ++ return info; ++error: ++ kfree(info); ++ return ERR_PTR(ret); + } + +-void +-nv04_pm_clock_set(struct drm_device *dev, void *pre_state) ++static void ++prog_pll(struct drm_device *dev, struct nv04_pm_clock *clk) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; +- struct nv04_pm_state *state = pre_state; +- u32 reg = state->pll.reg; ++ u32 reg = clk->pll.reg; + + /* thank the insane nouveau_hw_setpll() interface for this */ + if (dev_priv->card_type >= NV_40) + reg += 4; + +- nouveau_hw_setpll(dev, reg, &state->calc); ++ nouveau_hw_setpll(dev, reg, &clk->calc); ++} ++ ++int ++nv04_pm_clocks_set(struct drm_device *dev, void *pre_state) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; ++ struct nv04_pm_state *state = pre_state; ++ ++ prog_pll(dev, &state->core); + +- if (dev_priv->card_type < NV_30 && reg == NV_PRAMDAC_MPLL_COEFF) { +- if (dev_priv->card_type == NV_20) +- nv_mask(dev, 0x1002c4, 0, 1 << 20); ++ if (state->memory.pll.reg) { ++ prog_pll(dev, &state->memory); ++ if (dev_priv->card_type < NV_30) { ++ if (dev_priv->card_type == NV_20) ++ nv_mask(dev, 0x1002c4, 0, 1 << 20); + +- /* Reset the DLLs */ +- nv_mask(dev, 0x1002c0, 0, 1 << 8); ++ /* Reset the DLLs */ ++ nv_mask(dev, 0x1002c0, 0, 1 << 8); ++ } + } + +- if (reg == NV_PRAMDAC_NVPLL_COEFF) +- ptimer->init(dev); ++ ptimer->init(dev); + + kfree(state); ++ return 0; + } +- +diff --git a/drivers/gpu/drm/nouveau/nv04_timer.c b/drivers/gpu/drm/nouveau/nv04_timer.c +index 263301b..55c9452 100644 +--- a/drivers/gpu/drm/nouveau/nv04_timer.c ++++ b/drivers/gpu/drm/nouveau/nv04_timer.c +@@ -2,6 +2,7 @@ + #include "drm.h" + #include "nouveau_drv.h" + #include "nouveau_drm.h" ++#include "nouveau_hw.h" + + int + nv04_timer_init(struct drm_device *dev) +@@ -17,7 +18,7 @@ nv04_timer_init(struct drm_device *dev) + + /* determine base clock for timer source */ + if (dev_priv->chipset < 0x40) { +- n = dev_priv->engine.pm.clock_get(dev, PLL_CORE); ++ n = nouveau_hw_get_clock(dev, PLL_CORE); + } else + if (dev_priv->chipset == 0x40) { + /*XXX: figure this out */ +diff --git a/drivers/gpu/drm/nouveau/nv10_fb.c b/drivers/gpu/drm/nouveau/nv10_fb.c +index f78181a..420b1608 100644 +--- a/drivers/gpu/drm/nouveau/nv10_fb.c ++++ b/drivers/gpu/drm/nouveau/nv10_fb.c +@@ -3,81 +3,16 @@ + #include "nouveau_drv.h" + #include "nouveau_drm.h" + +-static struct drm_mm_node * +-nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; +- struct drm_mm_node *mem; +- int ret; +- +- ret = drm_mm_pre_get(&pfb->tag_heap); +- if (ret) +- return NULL; +- +- spin_lock(&dev_priv->tile.lock); +- mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0); +- if (mem) +- mem = drm_mm_get_block_atomic(mem, size, 0); +- spin_unlock(&dev_priv->tile.lock); +- +- return mem; +-} +- +-static void +-nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node *mem) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- +- spin_lock(&dev_priv->tile.lock); +- drm_mm_put_block(mem); +- spin_unlock(&dev_priv->tile.lock); +-} +- + void + nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch, uint32_t flags) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; +- int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16); + +- tile->addr = addr; ++ tile->addr = 0x80000000 | addr; + tile->limit = max(1u, addr + size) - 1; + tile->pitch = pitch; +- +- if (dev_priv->card_type == NV_20) { +- if (flags & NOUVEAU_GEM_TILE_ZETA) { +- /* +- * Allocate some of the on-die tag memory, +- * used to store Z compression meta-data (most +- * likely just a bitmap determining if a given +- * tile is compressed or not). +- */ +- tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256); +- +- if (tile->tag_mem) { +- /* Enable Z compression */ +- if (dev_priv->chipset >= 0x25) +- tile->zcomp = tile->tag_mem->start | +- (bpp == 16 ? +- NV25_PFB_ZCOMP_MODE_16 : +- NV25_PFB_ZCOMP_MODE_32); +- else +- tile->zcomp = tile->tag_mem->start | +- NV20_PFB_ZCOMP_EN | +- (bpp == 16 ? 0 : +- NV20_PFB_ZCOMP_MODE_32); +- } +- +- tile->addr |= 3; +- } else { +- tile->addr |= 1; +- } +- +- } else { +- tile->addr |= 1 << 31; +- } + } + + void +@@ -86,11 +21,6 @@ nv10_fb_free_tile_region(struct drm_device *dev, int i) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + +- if (tile->tag_mem) { +- nv20_fb_free_tag(dev, tile->tag_mem); +- tile->tag_mem = NULL; +- } +- + tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; + } + +@@ -103,9 +33,48 @@ nv10_fb_set_tile_region(struct drm_device *dev, int i) + nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); + nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); + nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); ++} ++ ++int ++nv1a_fb_vram_init(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct pci_dev *bridge; ++ uint32_t mem, mib; ++ ++ bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); ++ if (!bridge) { ++ NV_ERROR(dev, "no bridge device\n"); ++ return 0; ++ } ++ ++ if (dev_priv->chipset == 0x1a) { ++ pci_read_config_dword(bridge, 0x7c, &mem); ++ mib = ((mem >> 6) & 31) + 1; ++ } else { ++ pci_read_config_dword(bridge, 0x84, &mem); ++ mib = ((mem >> 4) & 127) + 1; ++ } ++ ++ dev_priv->vram_size = mib * 1024 * 1024; ++ return 0; ++} ++ ++int ++nv10_fb_vram_init(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 fifo_data = nv_rd32(dev, NV04_PFB_FIFO_DATA); ++ u32 cfg0 = nv_rd32(dev, 0x100200); + +- if (dev_priv->card_type == NV_20) +- nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp); ++ dev_priv->vram_size = fifo_data & NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; ++ ++ if (cfg0 & 0x00000001) ++ dev_priv->vram_type = NV_MEM_TYPE_DDR1; ++ else ++ dev_priv->vram_type = NV_MEM_TYPE_SDRAM; ++ ++ return 0; + } + + int +@@ -115,14 +84,8 @@ nv10_fb_init(struct drm_device *dev) + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + int i; + +- pfb->num_tiles = NV10_PFB_TILE__SIZE; +- +- if (dev_priv->card_type == NV_20) +- drm_mm_init(&pfb->tag_heap, 0, +- (dev_priv->chipset >= 0x25 ? +- 64 * 1024 : 32 * 1024)); +- + /* Turn all the tiling regions off. */ ++ pfb->num_tiles = NV10_PFB_TILE__SIZE; + for (i = 0; i < pfb->num_tiles; i++) + pfb->set_tile_region(dev, i); + +@@ -138,7 +101,4 @@ nv10_fb_takedown(struct drm_device *dev) + + for (i = 0; i < pfb->num_tiles; i++) + pfb->free_tile_region(dev, i); +- +- if (dev_priv->card_type == NV_20) +- drm_mm_takedown(&pfb->tag_heap); + } +diff --git a/drivers/gpu/drm/nouveau/nv10_gpio.c b/drivers/gpu/drm/nouveau/nv10_gpio.c +index 007fc29..9d79180 100644 +--- a/drivers/gpu/drm/nouveau/nv10_gpio.c ++++ b/drivers/gpu/drm/nouveau/nv10_gpio.c +@@ -27,66 +27,97 @@ + #include "drmP.h" + #include "nouveau_drv.h" + #include "nouveau_hw.h" ++#include "nouveau_gpio.h" + +-static bool +-get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift, +- uint32_t *mask) ++int ++nv10_gpio_sense(struct drm_device *dev, int line) + { +- if (ent->line < 2) { +- *reg = NV_PCRTC_GPIO; +- *shift = ent->line * 16; +- *mask = 0x11; +- +- } else if (ent->line < 10) { +- *reg = NV_PCRTC_GPIO_EXT; +- *shift = (ent->line - 2) * 4; +- *mask = 0x3; ++ if (line < 2) { ++ line = line * 16; ++ line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO) >> line; ++ return !!(line & 0x0100); ++ } else ++ if (line < 10) { ++ line = (line - 2) * 4; ++ line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT) >> line; ++ return !!(line & 0x04); ++ } else ++ if (line < 14) { ++ line = (line - 10) * 4; ++ line = NVReadCRTC(dev, 0, NV_PCRTC_850) >> line; ++ return !!(line & 0x04); ++ } + +- } else if (ent->line < 14) { +- *reg = NV_PCRTC_850; +- *shift = (ent->line - 10) * 4; +- *mask = 0x3; ++ return -EINVAL; ++} + ++int ++nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out) ++{ ++ u32 reg, mask, data; ++ ++ if (line < 2) { ++ line = line * 16; ++ reg = NV_PCRTC_GPIO; ++ mask = 0x00000011; ++ data = (dir << 4) | out; ++ } else ++ if (line < 10) { ++ line = (line - 2) * 4; ++ reg = NV_PCRTC_GPIO_EXT; ++ mask = 0x00000003; ++ data = (dir << 1) | out; ++ } else ++ if (line < 14) { ++ line = (line - 10) * 4; ++ reg = NV_PCRTC_850; ++ mask = 0x00000003; ++ data = (dir << 1) | out; + } else { +- return false; ++ return -EINVAL; + } + +- return true; ++ mask = NVReadCRTC(dev, 0, reg) & ~(mask << line); ++ NVWriteCRTC(dev, 0, reg, mask | (data << line)); ++ return 0; + } + +-int +-nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) ++void ++nv10_gpio_irq_enable(struct drm_device *dev, int line, bool on) + { +- struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); +- uint32_t reg, shift, mask, value; ++ u32 mask = 0x00010001 << line; + +- if (!ent) +- return -ENODEV; ++ nv_wr32(dev, 0x001104, mask); ++ nv_mask(dev, 0x001144, mask, on ? mask : 0); ++} + +- if (!get_gpio_location(ent, ®, &shift, &mask)) +- return -ENODEV; ++static void ++nv10_gpio_isr(struct drm_device *dev) ++{ ++ u32 intr = nv_rd32(dev, 0x1104); ++ u32 hi = (intr & 0x0000ffff) >> 0; ++ u32 lo = (intr & 0xffff0000) >> 16; + +- value = NVReadCRTC(dev, 0, reg) >> shift; ++ nouveau_gpio_isr(dev, 0, hi | lo); + +- return (ent->invert ? 1 : 0) ^ (value & 1); ++ nv_wr32(dev, 0x001104, intr); + } + + int +-nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) ++nv10_gpio_init(struct drm_device *dev) + { +- struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); +- uint32_t reg, shift, mask, value; +- +- if (!ent) +- return -ENODEV; +- +- if (!get_gpio_location(ent, ®, &shift, &mask)) +- return -ENODEV; +- +- value = ((ent->invert ? 1 : 0) ^ (state ? 1 : 0)) << shift; +- mask = ~(mask << shift); +- +- NVWriteCRTC(dev, 0, reg, value | (NVReadCRTC(dev, 0, reg) & mask)); +- ++ nv_wr32(dev, 0x001140, 0x00000000); ++ nv_wr32(dev, 0x001100, 0xffffffff); ++ nv_wr32(dev, 0x001144, 0x00000000); ++ nv_wr32(dev, 0x001104, 0xffffffff); ++ nouveau_irq_register(dev, 28, nv10_gpio_isr); /* PBUS */ + return 0; + } ++ ++void ++nv10_gpio_fini(struct drm_device *dev) ++{ ++ nv_wr32(dev, 0x001140, 0x00000000); ++ nv_wr32(dev, 0x001144, 0x00000000); ++ nouveau_irq_unregister(dev, 28); ++} +diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c +index 3900ceb..696d7e7 100644 +--- a/drivers/gpu/drm/nouveau/nv17_tv.c ++++ b/drivers/gpu/drm/nouveau/nv17_tv.c +@@ -30,6 +30,7 @@ + #include "nouveau_encoder.h" + #include "nouveau_connector.h" + #include "nouveau_crtc.h" ++#include "nouveau_gpio.h" + #include "nouveau_hw.h" + #include "nv17_tv.h" + +@@ -37,7 +38,6 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) + { + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; + uint32_t testval, regoffset = nv04_dac_output_offset(encoder); + uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, + fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; +@@ -53,8 +53,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) + head = (dacclk & 0x100) >> 8; + + /* Save the previous state. */ +- gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1); +- gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0); ++ gpio1 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC1); ++ gpio0 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC0); + fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); + fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); + fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); +@@ -65,8 +65,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) + ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); + + /* Prepare the DAC for load detection. */ +- gpio->set(dev, DCB_GPIO_TVDAC1, true); +- gpio->set(dev, DCB_GPIO_TVDAC0, true); ++ nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, true); ++ nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, true); + + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); +@@ -111,8 +111,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); +- gpio->set(dev, DCB_GPIO_TVDAC1, gpio1); +- gpio->set(dev, DCB_GPIO_TVDAC0, gpio0); ++ nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, gpio1); ++ nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, gpio0); + + return sample; + } +@@ -357,8 +357,6 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, + static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) + { + struct drm_device *dev = encoder->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; + struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; + struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); + +@@ -383,8 +381,8 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) + + nv_load_ptv(dev, regs, 200); + +- gpio->set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); +- gpio->set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); ++ nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); ++ nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); + + nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); + } +diff --git a/drivers/gpu/drm/nouveau/nv20_fb.c b/drivers/gpu/drm/nouveau/nv20_fb.c +new file mode 100644 +index 0000000..19bd640 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nv20_fb.c +@@ -0,0 +1,148 @@ ++#include "drmP.h" ++#include "drm.h" ++#include "nouveau_drv.h" ++#include "nouveau_drm.h" ++ ++static struct drm_mm_node * ++nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; ++ struct drm_mm_node *mem; ++ int ret; ++ ++ ret = drm_mm_pre_get(&pfb->tag_heap); ++ if (ret) ++ return NULL; ++ ++ spin_lock(&dev_priv->tile.lock); ++ mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0); ++ if (mem) ++ mem = drm_mm_get_block_atomic(mem, size, 0); ++ spin_unlock(&dev_priv->tile.lock); ++ ++ return mem; ++} ++ ++static void ++nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node **pmem) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct drm_mm_node *mem = *pmem; ++ if (mem) { ++ spin_lock(&dev_priv->tile.lock); ++ drm_mm_put_block(mem); ++ spin_unlock(&dev_priv->tile.lock); ++ *pmem = NULL; ++ } ++} ++ ++void ++nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, ++ uint32_t size, uint32_t pitch, uint32_t flags) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; ++ int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16); ++ ++ tile->addr = 0x00000001 | addr; ++ tile->limit = max(1u, addr + size) - 1; ++ tile->pitch = pitch; ++ ++ /* Allocate some of the on-die tag memory, used to store Z ++ * compression meta-data (most likely just a bitmap determining ++ * if a given tile is compressed or not). ++ */ ++ if (flags & NOUVEAU_GEM_TILE_ZETA) { ++ tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256); ++ if (tile->tag_mem) { ++ /* Enable Z compression */ ++ tile->zcomp = tile->tag_mem->start; ++ if (dev_priv->chipset >= 0x25) { ++ if (bpp == 16) ++ tile->zcomp |= NV25_PFB_ZCOMP_MODE_16; ++ else ++ tile->zcomp |= NV25_PFB_ZCOMP_MODE_32; ++ } else { ++ tile->zcomp |= NV20_PFB_ZCOMP_EN; ++ if (bpp != 16) ++ tile->zcomp |= NV20_PFB_ZCOMP_MODE_32; ++ } ++ } ++ ++ tile->addr |= 2; ++ } ++} ++ ++void ++nv20_fb_free_tile_region(struct drm_device *dev, int i) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; ++ ++ tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; ++ nv20_fb_free_tag(dev, &tile->tag_mem); ++} ++ ++void ++nv20_fb_set_tile_region(struct drm_device *dev, int i) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; ++ ++ nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); ++ nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); ++ nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); ++ nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp); ++} ++ ++int ++nv20_fb_vram_init(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 mem_size = nv_rd32(dev, 0x10020c); ++ u32 pbus1218 = nv_rd32(dev, 0x001218); ++ ++ dev_priv->vram_size = mem_size & 0xff000000; ++ switch (pbus1218 & 0x00000300) { ++ case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break; ++ case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; ++ case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; ++ case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_GDDR2; break; ++ } ++ ++ return 0; ++} ++ ++int ++nv20_fb_init(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; ++ int i; ++ ++ if (dev_priv->chipset >= 0x25) ++ drm_mm_init(&pfb->tag_heap, 0, 64 * 1024); ++ else ++ drm_mm_init(&pfb->tag_heap, 0, 32 * 1024); ++ ++ /* Turn all the tiling regions off. */ ++ pfb->num_tiles = NV10_PFB_TILE__SIZE; ++ for (i = 0; i < pfb->num_tiles; i++) ++ pfb->set_tile_region(dev, i); ++ ++ return 0; ++} ++ ++void ++nv20_fb_takedown(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; ++ int i; ++ ++ for (i = 0; i < pfb->num_tiles; i++) ++ pfb->free_tile_region(dev, i); ++ ++ drm_mm_takedown(&pfb->tag_heap); ++} +diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c +index f0ac2a7..7fbcb33 100644 +--- a/drivers/gpu/drm/nouveau/nv40_fb.c ++++ b/drivers/gpu/drm/nouveau/nv40_fb.c +@@ -72,6 +72,51 @@ nv44_fb_init_gart(struct drm_device *dev) + } + + int ++nv40_fb_vram_init(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ /* 0x001218 is actually present on a few other NV4X I looked at, ++ * and even contains sane values matching 0x100474. From looking ++ * at various vbios images however, this isn't the case everywhere. ++ * So, I chose to use the same regs I've seen NVIDIA reading around ++ * the memory detection, hopefully that'll get us the right numbers ++ */ ++ if (dev_priv->chipset == 0x40) { ++ u32 pbus1218 = nv_rd32(dev, 0x001218); ++ switch (pbus1218 & 0x00000300) { ++ case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break; ++ case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; ++ case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; ++ case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break; ++ } ++ } else ++ if (dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) { ++ u32 pfb914 = nv_rd32(dev, 0x100914); ++ switch (pfb914 & 0x00000003) { ++ case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; ++ case 0x00000001: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break; ++ case 0x00000002: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; ++ case 0x00000003: break; ++ } ++ } else ++ if (dev_priv->chipset != 0x4e) { ++ u32 pfb474 = nv_rd32(dev, 0x100474); ++ if (pfb474 & 0x00000004) ++ dev_priv->vram_type = NV_MEM_TYPE_GDDR3; ++ if (pfb474 & 0x00000002) ++ dev_priv->vram_type = NV_MEM_TYPE_DDR2; ++ if (pfb474 & 0x00000001) ++ dev_priv->vram_type = NV_MEM_TYPE_DDR1; ++ } else { ++ dev_priv->vram_type = NV_MEM_TYPE_STOLEN; ++ } ++ ++ dev_priv->vram_size = nv_rd32(dev, 0x10020c) & 0xff000000; ++ return 0; ++} ++ ++int + nv40_fb_init(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c +index e676b0d..c761538 100644 +--- a/drivers/gpu/drm/nouveau/nv40_pm.c ++++ b/drivers/gpu/drm/nouveau/nv40_pm.c +@@ -222,7 +222,7 @@ nv40_pm_gr_idle(void *data) + return true; + } + +-void ++int + nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -231,7 +231,7 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) + struct bit_entry M; + u32 crtc_mask = 0; + u8 sr1[2]; +- int i; ++ int i, ret = -EAGAIN; + + /* determine which CRTCs are active, fetch VGA_SR1 for each */ + for (i = 0; i < 2; i++) { +@@ -263,6 +263,8 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) + if (!nv_wait_cb(dev, nv40_pm_gr_idle, dev)) + goto resume; + ++ ret = 0; ++ + /* set engine clocks */ + nv_mask(dev, 0x00c040, 0x00000333, 0x00000000); + nv_wr32(dev, 0x004004, info->npll_coef); +@@ -345,4 +347,48 @@ resume: + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + kfree(info); ++ return ret; ++} ++ ++int ++nv40_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) ++{ ++ if (line == 2) { ++ u32 reg = nv_rd32(dev, 0x0010f0); ++ if (reg & 0x80000000) { ++ *duty = (reg & 0x7fff0000) >> 16; ++ *divs = (reg & 0x00007fff); ++ return 0; ++ } ++ } else ++ if (line == 9) { ++ u32 reg = nv_rd32(dev, 0x0015f4); ++ if (reg & 0x80000000) { ++ *divs = nv_rd32(dev, 0x0015f8); ++ *duty = (reg & 0x7fffffff); ++ return 0; ++ } ++ } else { ++ NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", line); ++ return -ENODEV; ++ } ++ ++ return -EINVAL; ++} ++ ++int ++nv40_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty) ++{ ++ if (line == 2) { ++ nv_wr32(dev, 0x0010f0, 0x80000000 | (duty << 16) | divs); ++ } else ++ if (line == 9) { ++ nv_wr32(dev, 0x0015f8, divs); ++ nv_wr32(dev, 0x0015f4, duty | 0x80000000); ++ } else { ++ NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", line); ++ return -ENODEV; ++ } ++ ++ return 0; + } +diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c +index 882080e..701b927 100644 +--- a/drivers/gpu/drm/nouveau/nv50_crtc.c ++++ b/drivers/gpu/drm/nouveau/nv50_crtc.c +@@ -132,30 +132,74 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) + } + + static int +-nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) ++nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) ++{ ++ struct nouveau_channel *evo = nv50_display(nv_crtc->base.dev)->master; ++ struct nouveau_connector *nv_connector; ++ struct drm_connector *connector; ++ int head = nv_crtc->index, ret; ++ u32 mode = 0x00; ++ ++ nv_connector = nouveau_crtc_connector_get(nv_crtc); ++ connector = &nv_connector->base; ++ if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) { ++ if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3) ++ mode = DITHERING_MODE_DYNAMIC2X2; ++ } else { ++ mode = nv_connector->dithering_mode; ++ } ++ ++ if (nv_connector->dithering_depth == DITHERING_DEPTH_AUTO) { ++ if (connector->display_info.bpc >= 8) ++ mode |= DITHERING_DEPTH_8BPC; ++ } else { ++ mode |= nv_connector->dithering_depth; ++ } ++ ++ ret = RING_SPACE(evo, 2 + (update ? 2 : 0)); ++ if (ret == 0) { ++ BEGIN_RING(evo, 0, NV50_EVO_CRTC(head, DITHER_CTRL), 1); ++ OUT_RING (evo, mode); ++ if (update) { ++ BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); ++ OUT_RING (evo, 0); ++ FIRE_RING (evo); ++ } ++ } ++ ++ return ret; ++} ++ ++static int ++nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update) + { + struct drm_device *dev = nv_crtc->base.dev; + struct nouveau_channel *evo = nv50_display(dev)->master; + int ret; ++ int adj; ++ u32 hue, vib; + +- NV_DEBUG_KMS(dev, "\n"); ++ NV_DEBUG_KMS(dev, "vibrance = %i, hue = %i\n", ++ nv_crtc->color_vibrance, nv_crtc->vibrant_hue); + + ret = RING_SPACE(evo, 2 + (update ? 2 : 0)); + if (ret) { +- NV_ERROR(dev, "no space while setting dither\n"); ++ NV_ERROR(dev, "no space while setting color vibrance\n"); + return ret; + } + +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, DITHER_CTRL), 1); +- if (on) +- OUT_RING(evo, NV50_EVO_CRTC_DITHER_CTRL_ON); +- else +- OUT_RING(evo, NV50_EVO_CRTC_DITHER_CTRL_OFF); ++ adj = (nv_crtc->color_vibrance > 0) ? 50 : 0; ++ vib = ((nv_crtc->color_vibrance * 2047 + adj) / 100) & 0xfff; ++ ++ hue = ((nv_crtc->vibrant_hue * 2047) / 100) & 0xfff; ++ ++ BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1); ++ OUT_RING (evo, (hue << 20) | (vib << 8)); + + if (update) { + BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); +- OUT_RING(evo, 0); +- FIRE_RING(evo); ++ OUT_RING (evo, 0); ++ FIRE_RING (evo); + } + + return 0; +@@ -180,80 +224,103 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) + } + + static int +-nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) ++nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) + { +- struct nouveau_connector *nv_connector = +- nouveau_crtc_connector_get(nv_crtc); +- struct drm_device *dev = nv_crtc->base.dev; ++ struct nouveau_connector *nv_connector; ++ struct drm_crtc *crtc = &nv_crtc->base; ++ struct drm_device *dev = crtc->dev; + struct nouveau_channel *evo = nv50_display(dev)->master; +- struct drm_display_mode *native_mode = NULL; +- struct drm_display_mode *mode = &nv_crtc->base.mode; +- uint32_t outX, outY, horiz, vert; +- int ret; ++ struct drm_display_mode *umode = &crtc->mode; ++ struct drm_display_mode *omode; ++ int scaling_mode, ret; ++ u32 ctrl = 0, oX, oY; + + NV_DEBUG_KMS(dev, "\n"); + +- switch (scaling_mode) { +- case DRM_MODE_SCALE_NONE: +- break; +- default: +- if (!nv_connector || !nv_connector->native_mode) { +- NV_ERROR(dev, "No native mode, forcing panel scaling\n"); +- scaling_mode = DRM_MODE_SCALE_NONE; ++ nv_connector = nouveau_crtc_connector_get(nv_crtc); ++ if (!nv_connector || !nv_connector->native_mode) { ++ NV_ERROR(dev, "no native mode, forcing panel scaling\n"); ++ scaling_mode = DRM_MODE_SCALE_NONE; ++ } else { ++ scaling_mode = nv_connector->scaling_mode; ++ } ++ ++ /* start off at the resolution we programmed the crtc for, this ++ * effectively handles NONE/FULL scaling ++ */ ++ if (scaling_mode != DRM_MODE_SCALE_NONE) ++ omode = nv_connector->native_mode; ++ else ++ omode = umode; ++ ++ oX = omode->hdisplay; ++ oY = omode->vdisplay; ++ if (omode->flags & DRM_MODE_FLAG_DBLSCAN) ++ oY *= 2; ++ ++ /* add overscan compensation if necessary, will keep the aspect ++ * ratio the same as the backend mode unless overridden by the ++ * user setting both hborder and vborder properties. ++ */ ++ if (nv_connector && ( nv_connector->underscan == UNDERSCAN_ON || ++ (nv_connector->underscan == UNDERSCAN_AUTO && ++ nv_connector->edid && ++ drm_detect_hdmi_monitor(nv_connector->edid)))) { ++ u32 bX = nv_connector->underscan_hborder; ++ u32 bY = nv_connector->underscan_vborder; ++ u32 aspect = (oY << 19) / oX; ++ ++ if (bX) { ++ oX -= (bX * 2); ++ if (bY) oY -= (bY * 2); ++ else oY = ((oX * aspect) + (aspect / 2)) >> 19; + } else { +- native_mode = nv_connector->native_mode; ++ oX -= (oX >> 4) + 32; ++ if (bY) oY -= (bY * 2); ++ else oY = ((oX * aspect) + (aspect / 2)) >> 19; + } +- break; + } + ++ /* handle CENTER/ASPECT scaling, taking into account the areas ++ * removed already for overscan compensation ++ */ + switch (scaling_mode) { ++ case DRM_MODE_SCALE_CENTER: ++ oX = min((u32)umode->hdisplay, oX); ++ oY = min((u32)umode->vdisplay, oY); ++ /* fall-through */ + case DRM_MODE_SCALE_ASPECT: +- horiz = (native_mode->hdisplay << 19) / mode->hdisplay; +- vert = (native_mode->vdisplay << 19) / mode->vdisplay; +- +- if (vert > horiz) { +- outX = (mode->hdisplay * horiz) >> 19; +- outY = (mode->vdisplay * horiz) >> 19; ++ if (oY < oX) { ++ u32 aspect = (umode->hdisplay << 19) / umode->vdisplay; ++ oX = ((oY * aspect) + (aspect / 2)) >> 19; + } else { +- outX = (mode->hdisplay * vert) >> 19; +- outY = (mode->vdisplay * vert) >> 19; ++ u32 aspect = (umode->vdisplay << 19) / umode->hdisplay; ++ oY = ((oX * aspect) + (aspect / 2)) >> 19; + } + break; +- case DRM_MODE_SCALE_FULLSCREEN: +- outX = native_mode->hdisplay; +- outY = native_mode->vdisplay; +- break; +- case DRM_MODE_SCALE_CENTER: +- case DRM_MODE_SCALE_NONE: + default: +- outX = mode->hdisplay; +- outY = mode->vdisplay; + break; + } + +- ret = RING_SPACE(evo, update ? 7 : 5); ++ if (umode->hdisplay != oX || umode->vdisplay != oY || ++ umode->flags & DRM_MODE_FLAG_INTERLACE || ++ umode->flags & DRM_MODE_FLAG_DBLSCAN) ++ ctrl |= NV50_EVO_CRTC_SCALE_CTRL_ACTIVE; ++ ++ ret = RING_SPACE(evo, 5); + if (ret) + return ret; + +- /* Got a better name for SCALER_ACTIVE? */ +- /* One day i've got to really figure out why this is needed. */ + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_CTRL), 1); +- if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) || +- (mode->flags & DRM_MODE_FLAG_INTERLACE) || +- mode->hdisplay != outX || mode->vdisplay != outY) { +- OUT_RING(evo, NV50_EVO_CRTC_SCALE_CTRL_ACTIVE); +- } else { +- OUT_RING(evo, NV50_EVO_CRTC_SCALE_CTRL_INACTIVE); +- } +- ++ OUT_RING (evo, ctrl); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_RES1), 2); +- OUT_RING(evo, outY << 16 | outX); +- OUT_RING(evo, outY << 16 | outX); ++ OUT_RING (evo, oY << 16 | oX); ++ OUT_RING (evo, oY << 16 | oX); + + if (update) { +- BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); +- OUT_RING(evo, 0); +- FIRE_RING(evo); ++ nv50_display_flip_stop(crtc); ++ nv50_display_sync(dev); ++ nv50_display_flip_next(crtc, crtc->fb, NULL); + } + + return 0; +@@ -333,7 +400,6 @@ nv50_crtc_destroy(struct drm_crtc *crtc) + nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); + nouveau_bo_unmap(nv_crtc->cursor.nvbo); + nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); +- kfree(nv_crtc->mode); + kfree(nv_crtc); + } + +@@ -441,39 +507,6 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode) + { + } + +-static int +-nv50_crtc_wait_complete(struct drm_crtc *crtc) +-{ +- struct drm_device *dev = crtc->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; +- struct nv50_display *disp = nv50_display(dev); +- struct nouveau_channel *evo = disp->master; +- u64 start; +- int ret; +- +- ret = RING_SPACE(evo, 6); +- if (ret) +- return ret; +- BEGIN_RING(evo, 0, 0x0084, 1); +- OUT_RING (evo, 0x80000000); +- BEGIN_RING(evo, 0, 0x0080, 1); +- OUT_RING (evo, 0); +- BEGIN_RING(evo, 0, 0x0084, 1); +- OUT_RING (evo, 0x00000000); +- +- nv_wo32(disp->ntfy, 0x000, 0x00000000); +- FIRE_RING (evo); +- +- start = ptimer->read(dev); +- do { +- if (nv_ro32(disp->ntfy, 0x000)) +- return 0; +- } while (ptimer->read(dev) - start < 2000000000ULL); +- +- return -EBUSY; +-} +- + static void + nv50_crtc_prepare(struct drm_crtc *crtc) + { +@@ -497,7 +530,7 @@ nv50_crtc_commit(struct drm_crtc *crtc) + + nv50_crtc_blank(nv_crtc, false); + drm_vblank_post_modeset(dev, nv_crtc->index); +- nv50_crtc_wait_complete(crtc); ++ nv50_display_sync(dev); + nv50_display_flip_next(crtc, crtc->fb, NULL); + } + +@@ -579,8 +612,6 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, + OUT_RING (evo, fb->base.depth == 8 ? + NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); + +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1); +- OUT_RING (evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1); + OUT_RING (evo, (y << 16) | x); + +@@ -593,90 +624,77 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, + } + + static int +-nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode, int x, int y, ++nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, ++ struct drm_display_mode *mode, int x, int y, + struct drm_framebuffer *old_fb) + { + struct drm_device *dev = crtc->dev; + struct nouveau_channel *evo = nv50_display(dev)->master; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); +- struct nouveau_connector *nv_connector = NULL; +- uint32_t hsync_dur, vsync_dur, hsync_start_to_end, vsync_start_to_end; +- uint32_t hunk1, vunk1, vunk2a, vunk2b; ++ u32 head = nv_crtc->index * 0x400; ++ u32 ilace = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 1; ++ u32 vscan = (mode->flags & DRM_MODE_FLAG_DBLSCAN) ? 2 : 1; ++ u32 hactive, hsynce, hbackp, hfrontp, hblanke, hblanks; ++ u32 vactive, vsynce, vbackp, vfrontp, vblanke, vblanks; ++ u32 vblan2e = 0, vblan2s = 1; + int ret; + +- /* Find the connector attached to this CRTC */ +- nv_connector = nouveau_crtc_connector_get(nv_crtc); +- +- *nv_crtc->mode = *adjusted_mode; +- +- NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); ++ /* hw timing description looks like this: ++ * ++ * <---------display---------> ++ * ______ ++ * |____________|---------------------------|____________| ++ * ++ * ^ synce ^ blanke ^ blanks ^ active ++ * ++ * interlaced modes also have 2 additional values pointing at the end ++ * and start of the next field's blanking period. ++ */ + +- hsync_dur = adjusted_mode->hsync_end - adjusted_mode->hsync_start; +- vsync_dur = adjusted_mode->vsync_end - adjusted_mode->vsync_start; +- hsync_start_to_end = adjusted_mode->htotal - adjusted_mode->hsync_start; +- vsync_start_to_end = adjusted_mode->vtotal - adjusted_mode->vsync_start; +- /* I can't give this a proper name, anyone else can? */ +- hunk1 = adjusted_mode->htotal - +- adjusted_mode->hsync_start + adjusted_mode->hdisplay; +- vunk1 = adjusted_mode->vtotal - +- adjusted_mode->vsync_start + adjusted_mode->vdisplay; +- /* Another strange value, this time only for interlaced adjusted_modes. */ +- vunk2a = 2 * adjusted_mode->vtotal - +- adjusted_mode->vsync_start + adjusted_mode->vdisplay; +- vunk2b = adjusted_mode->vtotal - +- adjusted_mode->vsync_start + adjusted_mode->vtotal; +- +- if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { +- vsync_dur /= 2; +- vsync_start_to_end /= 2; +- vunk1 /= 2; +- vunk2a /= 2; +- vunk2b /= 2; +- /* magic */ +- if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) { +- vsync_start_to_end -= 1; +- vunk1 -= 1; +- vunk2a -= 1; +- vunk2b -= 1; +- } ++ hactive = mode->htotal; ++ hsynce = mode->hsync_end - mode->hsync_start - 1; ++ hbackp = mode->htotal - mode->hsync_end; ++ hblanke = hsynce + hbackp; ++ hfrontp = mode->hsync_start - mode->hdisplay; ++ hblanks = mode->htotal - hfrontp - 1; ++ ++ vactive = mode->vtotal * vscan / ilace; ++ vsynce = ((mode->vsync_end - mode->vsync_start) * vscan / ilace) - 1; ++ vbackp = (mode->vtotal - mode->vsync_end) * vscan / ilace; ++ vblanke = vsynce + vbackp; ++ vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace; ++ vblanks = vactive - vfrontp - 1; ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) { ++ vblan2e = vactive + vsynce + vbackp; ++ vblan2s = vblan2e + (mode->vdisplay * vscan / ilace); ++ vactive = (vactive * 2) + 1; + } + +- ret = RING_SPACE(evo, 17); +- if (ret) +- return ret; +- +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLOCK), 2); +- OUT_RING(evo, adjusted_mode->clock | 0x800000); +- OUT_RING(evo, (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 0); +- +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, DISPLAY_START), 5); +- OUT_RING(evo, 0); +- OUT_RING(evo, (adjusted_mode->vtotal << 16) | adjusted_mode->htotal); +- OUT_RING(evo, (vsync_dur - 1) << 16 | (hsync_dur - 1)); +- OUT_RING(evo, (vsync_start_to_end - 1) << 16 | +- (hsync_start_to_end - 1)); +- OUT_RING(evo, (vunk1 - 1) << 16 | (hunk1 - 1)); +- +- if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, UNK0824), 1); +- OUT_RING(evo, (vunk2b - 1) << 16 | (vunk2a - 1)); +- } else { +- OUT_RING(evo, 0); +- OUT_RING(evo, 0); ++ ret = RING_SPACE(evo, 18); ++ if (ret == 0) { ++ BEGIN_RING(evo, 0, 0x0804 + head, 2); ++ OUT_RING (evo, 0x00800000 | mode->clock); ++ OUT_RING (evo, (ilace == 2) ? 2 : 0); ++ BEGIN_RING(evo, 0, 0x0810 + head, 6); ++ OUT_RING (evo, 0x00000000); /* border colour */ ++ OUT_RING (evo, (vactive << 16) | hactive); ++ OUT_RING (evo, ( vsynce << 16) | hsynce); ++ OUT_RING (evo, (vblanke << 16) | hblanke); ++ OUT_RING (evo, (vblanks << 16) | hblanks); ++ OUT_RING (evo, (vblan2e << 16) | vblan2s); ++ BEGIN_RING(evo, 0, 0x082c + head, 1); ++ OUT_RING (evo, 0x00000000); ++ BEGIN_RING(evo, 0, 0x0900 + head, 1); ++ OUT_RING (evo, 0x00000311); /* makes sync channel work */ ++ BEGIN_RING(evo, 0, 0x08c8 + head, 1); ++ OUT_RING (evo, (umode->vdisplay << 16) | umode->hdisplay); ++ BEGIN_RING(evo, 0, 0x08d4 + head, 1); ++ OUT_RING (evo, 0x00000000); /* screen position */ + } + +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, UNK082C), 1); +- OUT_RING(evo, 0); +- +- /* This is the actual resolution of the mode. */ +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, REAL_RES), 1); +- OUT_RING(evo, (mode->vdisplay << 16) | mode->hdisplay); +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_CENTER_OFFSET), 1); +- OUT_RING(evo, NV50_EVO_CRTC_SCALE_CENTER_OFFSET_VAL(0, 0)); +- +- nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false); +- nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false); ++ nv_crtc->set_dither(nv_crtc, false); ++ nv_crtc->set_scale(nv_crtc, false); ++ nv_crtc->set_color_vibrance(nv_crtc, false); + + return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); + } +@@ -692,7 +710,7 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + if (ret) + return ret; + +- ret = nv50_crtc_wait_complete(crtc); ++ ret = nv50_display_sync(crtc->dev); + if (ret) + return ret; + +@@ -711,7 +729,7 @@ nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc, + if (ret) + return ret; + +- return nv50_crtc_wait_complete(crtc); ++ return nv50_display_sync(crtc->dev); + } + + static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { +@@ -737,11 +755,8 @@ nv50_crtc_create(struct drm_device *dev, int index) + if (!nv_crtc) + return -ENOMEM; + +- nv_crtc->mode = kzalloc(sizeof(*nv_crtc->mode), GFP_KERNEL); +- if (!nv_crtc->mode) { +- kfree(nv_crtc); +- return -ENOMEM; +- } ++ nv_crtc->color_vibrance = 50; ++ nv_crtc->vibrant_hue = 0; + + /* Default CLUT parameters, will be activated on the hw upon + * first mode set. +@@ -764,7 +779,6 @@ nv50_crtc_create(struct drm_device *dev, int index) + } + + if (ret) { +- kfree(nv_crtc->mode); + kfree(nv_crtc); + return ret; + } +@@ -774,6 +788,7 @@ nv50_crtc_create(struct drm_device *dev, int index) + /* set function pointers */ + nv_crtc->set_dither = nv50_crtc_set_dither; + nv_crtc->set_scale = nv50_crtc_set_scale; ++ nv_crtc->set_color_vibrance = nv50_crtc_set_color_vibrance; + + drm_crtc_init(dev, &nv_crtc->base, &nv50_crtc_funcs); + drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs); +diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c +index 808f3ec..55c5633 100644 +--- a/drivers/gpu/drm/nouveau/nv50_dac.c ++++ b/drivers/gpu/drm/nouveau/nv50_dac.c +@@ -190,21 +190,13 @@ nv50_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, + } + + if (connector->scaling_mode != DRM_MODE_SCALE_NONE && +- connector->native_mode) { +- int id = adjusted_mode->base.id; +- *adjusted_mode = *connector->native_mode; +- adjusted_mode->base.id = id; +- } ++ connector->native_mode) ++ drm_mode_copy(adjusted_mode, connector->native_mode); + + return true; + } + + static void +-nv50_dac_prepare(struct drm_encoder *encoder) +-{ +-} +- +-static void + nv50_dac_commit(struct drm_encoder *encoder) + { + } +@@ -266,7 +258,7 @@ static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = { + .save = nv50_dac_save, + .restore = nv50_dac_restore, + .mode_fixup = nv50_dac_mode_fixup, +- .prepare = nv50_dac_prepare, ++ .prepare = nv50_dac_disconnect, + .commit = nv50_dac_commit, + .mode_set = nv50_dac_mode_set, + .get_crtc = nv50_dac_crtc_get, +diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c +index 06de250..8b78b9c 100644 +--- a/drivers/gpu/drm/nouveau/nv50_display.c ++++ b/drivers/gpu/drm/nouveau/nv50_display.c +@@ -50,9 +50,76 @@ nv50_sor_nr(struct drm_device *dev) + return 4; + } + ++u32 ++nv50_display_active_crtcs(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 mask = 0; ++ int i; ++ ++ if (dev_priv->chipset < 0x90 || ++ dev_priv->chipset == 0x92 || ++ dev_priv->chipset == 0xa0) { ++ for (i = 0; i < 2; i++) ++ mask |= nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); ++ } else { ++ for (i = 0; i < 4; i++) ++ mask |= nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); ++ } ++ ++ for (i = 0; i < 3; i++) ++ mask |= nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); ++ ++ return mask & 3; ++} ++ ++static int ++evo_icmd(struct drm_device *dev, int ch, u32 mthd, u32 data) ++{ ++ int ret = 0; ++ nv_mask(dev, 0x610300 + (ch * 0x08), 0x00000001, 0x00000001); ++ nv_wr32(dev, 0x610304 + (ch * 0x08), data); ++ nv_wr32(dev, 0x610300 + (ch * 0x08), 0x80000001 | mthd); ++ if (!nv_wait(dev, 0x610300 + (ch * 0x08), 0x80000000, 0x00000000)) ++ ret = -EBUSY; ++ if (ret || (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)) ++ NV_INFO(dev, "EvoPIO: %d 0x%04x 0x%08x\n", ch, mthd, data); ++ nv_mask(dev, 0x610300 + (ch * 0x08), 0x00000001, 0x00000000); ++ return ret; ++} ++ + int + nv50_display_early_init(struct drm_device *dev) + { ++ u32 ctrl = nv_rd32(dev, 0x610200); ++ int i; ++ ++ /* check if master evo channel is already active, a good a sign as any ++ * that the display engine is in a weird state (hibernate/kexec), if ++ * it is, do our best to reset the display engine... ++ */ ++ if ((ctrl & 0x00000003) == 0x00000003) { ++ NV_INFO(dev, "PDISP: EVO(0) 0x%08x, resetting...\n", ctrl); ++ ++ /* deactivate both heads first, PDISP will disappear forever ++ * (well, until you power cycle) on some boards as soon as ++ * PMC_ENABLE is hit unless they are.. ++ */ ++ for (i = 0; i < 2; i++) { ++ evo_icmd(dev, 0, 0x0880 + (i * 0x400), 0x05000000); ++ evo_icmd(dev, 0, 0x089c + (i * 0x400), 0); ++ evo_icmd(dev, 0, 0x0840 + (i * 0x400), 0); ++ evo_icmd(dev, 0, 0x0844 + (i * 0x400), 0); ++ evo_icmd(dev, 0, 0x085c + (i * 0x400), 0); ++ evo_icmd(dev, 0, 0x0874 + (i * 0x400), 0); ++ } ++ evo_icmd(dev, 0, 0x0080, 0); ++ ++ /* reset PDISP */ ++ nv_mask(dev, 0x000200, 0x40000000, 0x00000000); ++ nv_mask(dev, 0x000200, 0x40000000, 0x40000000); ++ } ++ + return 0; + } + +@@ -62,11 +129,40 @@ nv50_display_late_takedown(struct drm_device *dev) + } + + int +-nv50_display_init(struct drm_device *dev) ++nv50_display_sync(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- struct drm_connector *connector; ++ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; ++ struct nv50_display *disp = nv50_display(dev); ++ struct nouveau_channel *evo = disp->master; ++ u64 start; ++ int ret; ++ ++ ret = RING_SPACE(evo, 6); ++ if (ret == 0) { ++ BEGIN_RING(evo, 0, 0x0084, 1); ++ OUT_RING (evo, 0x80000000); ++ BEGIN_RING(evo, 0, 0x0080, 1); ++ OUT_RING (evo, 0); ++ BEGIN_RING(evo, 0, 0x0084, 1); ++ OUT_RING (evo, 0x00000000); ++ ++ nv_wo32(disp->ntfy, 0x000, 0x00000000); ++ FIRE_RING (evo); ++ ++ start = ptimer->read(dev); ++ do { ++ if (nv_ro32(disp->ntfy, 0x000)) ++ return 0; ++ } while (ptimer->read(dev) - start < 2000000000ULL); ++ } ++ ++ return -EBUSY; ++} ++ ++int ++nv50_display_init(struct drm_device *dev) ++{ + struct nouveau_channel *evo; + int ret, i; + u32 val; +@@ -161,16 +257,6 @@ nv50_display_init(struct drm_device *dev) + NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 | + NV50_PDISPLAY_INTR_EN_1_CLK_UNK40); + +- /* enable hotplug interrupts */ +- list_for_each_entry(connector, &dev->mode_config.connector_list, head) { +- struct nouveau_connector *conn = nouveau_connector(connector); +- +- if (conn->dcb->gpio_tag == 0xff) +- continue; +- +- pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); +- } +- + ret = nv50_evo_init(dev); + if (ret) + return ret; +@@ -178,36 +264,19 @@ nv50_display_init(struct drm_device *dev) + + nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); + +- ret = RING_SPACE(evo, 15); ++ ret = RING_SPACE(evo, 3); + if (ret) + return ret; + BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2); +- OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED); +- OUT_RING(evo, NvEvoSync); +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1); +- OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE); +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1); +- OUT_RING(evo, 0); +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, DISPLAY_START), 1); +- OUT_RING(evo, 0); +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); +- OUT_RING(evo, 0); +- /* required to make display sync channels not hate life */ +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK900), 1); +- OUT_RING (evo, 0x00000311); +- BEGIN_RING(evo, 0, NV50_EVO_CRTC(1, UNK900), 1); +- OUT_RING (evo, 0x00000311); +- FIRE_RING(evo); +- if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) +- NV_ERROR(dev, "evo pushbuf stalled\n"); +- ++ OUT_RING (evo, NV50_EVO_UNK84_NOTIFY_DISABLED); ++ OUT_RING (evo, NvEvoSync); + +- return 0; ++ return nv50_display_sync(dev); + } + +-static int nv50_display_disable(struct drm_device *dev) ++void ++nv50_display_fini(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_display *disp = nv50_display(dev); + struct nouveau_channel *evo = disp->master; + struct drm_crtc *drm_crtc; +@@ -270,18 +339,10 @@ static int nv50_display_disable(struct drm_device *dev) + + /* disable interrupts. */ + nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, 0x00000000); +- +- /* disable hotplug interrupts */ +- nv_wr32(dev, 0xe054, 0xffffffff); +- nv_wr32(dev, 0xe050, 0x00000000); +- if (dev_priv->chipset >= 0x90) { +- nv_wr32(dev, 0xe074, 0xffffffff); +- nv_wr32(dev, 0xe070, 0x00000000); +- } +- return 0; + } + +-int nv50_display_create(struct drm_device *dev) ++int ++nv50_display_create(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct dcb_table *dcb = &dev_priv->vbios.dcb; +@@ -341,7 +402,7 @@ int nv50_display_create(struct drm_device *dev) + tasklet_init(&priv->tasklet, nv50_display_bh, (unsigned long)dev); + nouveau_irq_register(dev, 26, nv50_display_isr); + +- ret = nv50_display_init(dev); ++ ret = nv50_evo_create(dev); + if (ret) { + nv50_display_destroy(dev); + return ret; +@@ -357,7 +418,7 @@ nv50_display_destroy(struct drm_device *dev) + + NV_DEBUG_KMS(dev, "\n"); + +- nv50_display_disable(dev); ++ nv50_evo_destroy(dev); + nouveau_irq_unregister(dev, 26); + kfree(disp); + } +@@ -413,15 +474,15 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, + } + + if (dev_priv->chipset < 0xc0) { +- BEGIN_RING(chan, NvSubSw, 0x0060, 2); ++ BEGIN_RING(chan, 0, 0x0060, 2); + OUT_RING (chan, NvEvoSema0 + nv_crtc->index); + OUT_RING (chan, dispc->sem.offset); +- BEGIN_RING(chan, NvSubSw, 0x006c, 1); ++ BEGIN_RING(chan, 0, 0x006c, 1); + OUT_RING (chan, 0xf00d0000 | dispc->sem.value); +- BEGIN_RING(chan, NvSubSw, 0x0064, 2); ++ BEGIN_RING(chan, 0, 0x0064, 2); + OUT_RING (chan, dispc->sem.offset ^ 0x10); + OUT_RING (chan, 0x74b1e000); +- BEGIN_RING(chan, NvSubSw, 0x0060, 1); ++ BEGIN_RING(chan, 0, 0x0060, 1); + if (dev_priv->chipset < 0x84) + OUT_RING (chan, NvSema); + else +@@ -429,12 +490,12 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, + } else { + u64 offset = chan->dispc_vma[nv_crtc->index].offset; + offset += dispc->sem.offset; +- BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); ++ BEGIN_NVC0(chan, 2, 0, 0x0010, 4); + OUT_RING (chan, upper_32_bits(offset)); + OUT_RING (chan, lower_32_bits(offset)); + OUT_RING (chan, 0xf00d0000 | dispc->sem.value); + OUT_RING (chan, 0x1002); +- BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); ++ BEGIN_NVC0(chan, 2, 0, 0x0010, 4); + OUT_RING (chan, upper_32_bits(offset)); + OUT_RING (chan, lower_32_bits(offset ^ 0x10)); + OUT_RING (chan, 0x74b1e000); +@@ -521,7 +582,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, + } else { + /* determine number of lvds links */ + if (nv_connector && nv_connector->edid && +- nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) { ++ nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) { + /* http://www.spwg.org */ + if (((u8 *)nv_connector->edid)[121] == 2) + script |= 0x0100; +@@ -722,8 +783,8 @@ nv50_display_unk20_handler(struct drm_device *dev) + if (crtc >= 0) { + pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)); + pclk &= 0x003fffff; +- +- nv50_crtc_set_clock(dev, crtc, pclk); ++ if (pclk) ++ nv50_crtc_set_clock(dev, crtc, pclk); + + tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc)); + tmp &= ~0x000000f; +@@ -802,9 +863,9 @@ nv50_display_unk20_handler(struct drm_device *dev) + if (type == OUTPUT_DP) { + int link = !(dcb->dpconf.sor.link & 1); + if ((mc & 0x000f0000) == 0x00020000) +- nouveau_dp_tu_update(dev, or, link, pclk, 18); ++ nv50_sor_dp_calc_tu(dev, or, link, pclk, 18); + else +- nouveau_dp_tu_update(dev, or, link, pclk, 24); ++ nv50_sor_dp_calc_tu(dev, or, link, pclk, 24); + } + + if (dcb->type != OUTPUT_ANALOG) { +diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h +index c2da503..5d3dd14 100644 +--- a/drivers/gpu/drm/nouveau/nv50_display.h ++++ b/drivers/gpu/drm/nouveau/nv50_display.h +@@ -69,14 +69,20 @@ int nv50_display_early_init(struct drm_device *dev); + void nv50_display_late_takedown(struct drm_device *dev); + int nv50_display_create(struct drm_device *dev); + int nv50_display_init(struct drm_device *dev); ++void nv50_display_fini(struct drm_device *dev); + void nv50_display_destroy(struct drm_device *dev); + int nv50_crtc_blank(struct nouveau_crtc *, bool blank); + int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); + ++u32 nv50_display_active_crtcs(struct drm_device *); ++ ++int nv50_display_sync(struct drm_device *); + int nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, + struct nouveau_channel *chan); + void nv50_display_flip_stop(struct drm_crtc *); + ++int nv50_evo_create(struct drm_device *dev); ++void nv50_evo_destroy(struct drm_device *dev); + int nv50_evo_init(struct drm_device *dev); + void nv50_evo_fini(struct drm_device *dev); + void nv50_evo_dmaobj_init(struct nouveau_gpuobj *, u32 memtype, u64 base, +diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c +index c99d975..9b962e9 100644 +--- a/drivers/gpu/drm/nouveau/nv50_evo.c ++++ b/drivers/gpu/drm/nouveau/nv50_evo.c +@@ -218,7 +218,7 @@ nv50_evo_channel_fini(struct nouveau_channel *evo) + } + } + +-static void ++void + nv50_evo_destroy(struct drm_device *dev) + { + struct nv50_display *disp = nv50_display(dev); +@@ -235,7 +235,7 @@ nv50_evo_destroy(struct drm_device *dev) + nv50_evo_channel_del(&disp->master); + } + +-static int ++int + nv50_evo_create(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -388,12 +388,6 @@ nv50_evo_init(struct drm_device *dev) + struct nv50_display *disp = nv50_display(dev); + int ret, i; + +- if (!disp->master) { +- ret = nv50_evo_create(dev); +- if (ret) +- return ret; +- } +- + ret = nv50_evo_channel_init(disp->master); + if (ret) + return ret; +@@ -420,6 +414,4 @@ nv50_evo_fini(struct drm_device *dev) + + if (disp->master) + nv50_evo_channel_fini(disp->master); +- +- nv50_evo_destroy(dev); + } +diff --git a/drivers/gpu/drm/nouveau/nv50_evo.h b/drivers/gpu/drm/nouveau/nv50_evo.h +index 3860ca6..771d879 100644 +--- a/drivers/gpu/drm/nouveau/nv50_evo.h ++++ b/drivers/gpu/drm/nouveau/nv50_evo.h +@@ -104,7 +104,8 @@ + #define NV50_EVO_CRTC_SCALE_CTRL_INACTIVE 0x00000000 + #define NV50_EVO_CRTC_SCALE_CTRL_ACTIVE 0x00000009 + #define NV50_EVO_CRTC_COLOR_CTRL 0x000008a8 +-#define NV50_EVO_CRTC_COLOR_CTRL_COLOR 0x00040000 ++#define NV50_EVO_CRTC_COLOR_CTRL_VIBRANCE 0x000fff00 ++#define NV50_EVO_CRTC_COLOR_CTRL_HUE 0xfff00000 + #define NV50_EVO_CRTC_FB_POS 0x000008c0 + #define NV50_EVO_CRTC_REAL_RES 0x000008c8 + #define NV50_EVO_CRTC_SCALE_CENTER_OFFSET 0x000008d4 +diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c +index c34a074..3bc2a56 100644 +--- a/drivers/gpu/drm/nouveau/nv50_fifo.c ++++ b/drivers/gpu/drm/nouveau/nv50_fifo.c +@@ -230,6 +230,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *ramfc = NULL; ++ uint64_t ib_offset = chan->pushbuf_base + chan->dma.ib_base * 4; + unsigned long flags; + int ret; + +@@ -280,8 +281,9 @@ nv50_fifo_create_context(struct nouveau_channel *chan) + nv_wo32(ramfc, 0x7c, 0x30000001); + nv_wo32(ramfc, 0x78, 0x00000000); + nv_wo32(ramfc, 0x3c, 0x403f6078); +- nv_wo32(ramfc, 0x50, chan->pushbuf_base + chan->dma.ib_base * 4); +- nv_wo32(ramfc, 0x54, drm_order(chan->dma.ib_max + 1) << 16); ++ nv_wo32(ramfc, 0x50, lower_32_bits(ib_offset)); ++ nv_wo32(ramfc, 0x54, upper_32_bits(ib_offset) | ++ drm_order(chan->dma.ib_max + 1) << 16); + + if (dev_priv->chipset != 0x50) { + nv_wo32(chan->ramin, 0, chan->id); +diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c +index 793a5cc..f429e6a 100644 +--- a/drivers/gpu/drm/nouveau/nv50_gpio.c ++++ b/drivers/gpu/drm/nouveau/nv50_gpio.c +@@ -25,229 +25,95 @@ + #include "drmP.h" + #include "nouveau_drv.h" + #include "nouveau_hw.h" ++#include "nouveau_gpio.h" + + #include "nv50_display.h" + +-static void nv50_gpio_isr(struct drm_device *dev); +-static void nv50_gpio_isr_bh(struct work_struct *work); +- +-struct nv50_gpio_priv { +- struct list_head handlers; +- spinlock_t lock; +-}; +- +-struct nv50_gpio_handler { +- struct drm_device *dev; +- struct list_head head; +- struct work_struct work; +- bool inhibit; +- +- struct dcb_gpio_entry *gpio; +- +- void (*handler)(void *data, int state); +- void *data; +-}; +- + static int +-nv50_gpio_location(struct dcb_gpio_entry *gpio, uint32_t *reg, uint32_t *shift) ++nv50_gpio_location(int line, u32 *reg, u32 *shift) + { + const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; + +- if (gpio->line >= 32) ++ if (line >= 32) + return -EINVAL; + +- *reg = nv50_gpio_reg[gpio->line >> 3]; +- *shift = (gpio->line & 7) << 2; ++ *reg = nv50_gpio_reg[line >> 3]; ++ *shift = (line & 7) << 2; + return 0; + } + + int +-nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) ++nv50_gpio_drive(struct drm_device *dev, int line, int dir, int out) + { +- struct dcb_gpio_entry *gpio; +- uint32_t r, s, v; +- +- gpio = nouveau_bios_gpio_entry(dev, tag); +- if (!gpio) +- return -ENOENT; ++ u32 reg, shift; + +- if (nv50_gpio_location(gpio, &r, &s)) ++ if (nv50_gpio_location(line, ®, &shift)) + return -EINVAL; + +- v = nv_rd32(dev, r) >> (s + 2); +- return ((v & 1) == (gpio->state[1] & 1)); ++ nv_mask(dev, reg, 7 << shift, (((dir ^ 1) << 1) | out) << shift); ++ return 0; + } + + int +-nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) ++nv50_gpio_sense(struct drm_device *dev, int line) + { +- struct dcb_gpio_entry *gpio; +- uint32_t r, s, v; +- +- gpio = nouveau_bios_gpio_entry(dev, tag); +- if (!gpio) +- return -ENOENT; ++ u32 reg, shift; + +- if (nv50_gpio_location(gpio, &r, &s)) ++ if (nv50_gpio_location(line, ®, &shift)) + return -EINVAL; + +- v = nv_rd32(dev, r) & ~(0x3 << s); +- v |= (gpio->state[state] ^ 2) << s; +- nv_wr32(dev, r, v); +- return 0; ++ return !!(nv_rd32(dev, reg) & (4 << shift)); + } + +-int +-nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) ++void ++nv50_gpio_irq_enable(struct drm_device *dev, int line, bool on) + { +- struct dcb_gpio_entry *gpio; +- u32 v; +- +- gpio = nouveau_bios_gpio_entry(dev, tag); +- if (!gpio) +- return -ENOENT; ++ u32 reg = line < 16 ? 0xe050 : 0xe070; ++ u32 mask = 0x00010001 << (line & 0xf); + +- v = nv_rd32(dev, 0x00d610 + (gpio->line * 4)); +- v &= 0x00004000; +- return (!!v == (gpio->state[1] & 1)); ++ nv_wr32(dev, reg + 4, mask); ++ nv_mask(dev, reg + 0, mask, on ? mask : 0); + } + + int +-nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) ++nvd0_gpio_drive(struct drm_device *dev, int line, int dir, int out) + { +- struct dcb_gpio_entry *gpio; +- u32 v; +- +- gpio = nouveau_bios_gpio_entry(dev, tag); +- if (!gpio) +- return -ENOENT; +- +- v = gpio->state[state] ^ 2; +- +- nv_mask(dev, 0x00d610 + (gpio->line * 4), 0x00003000, v << 12); ++ u32 data = ((dir ^ 1) << 13) | (out << 12); ++ nv_mask(dev, 0x00d610 + (line * 4), 0x00003000, data); ++ nv_mask(dev, 0x00d604, 0x00000001, 0x00000001); /* update? */ + return 0; + } + + int +-nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag, +- void (*handler)(void *, int), void *data) ++nvd0_gpio_sense(struct drm_device *dev, int line) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- struct nv50_gpio_priv *priv = pgpio->priv; +- struct nv50_gpio_handler *gpioh; +- struct dcb_gpio_entry *gpio; +- unsigned long flags; +- +- gpio = nouveau_bios_gpio_entry(dev, tag); +- if (!gpio) +- return -ENOENT; +- +- gpioh = kzalloc(sizeof(*gpioh), GFP_KERNEL); +- if (!gpioh) +- return -ENOMEM; +- +- INIT_WORK(&gpioh->work, nv50_gpio_isr_bh); +- gpioh->dev = dev; +- gpioh->gpio = gpio; +- gpioh->handler = handler; +- gpioh->data = data; +- +- spin_lock_irqsave(&priv->lock, flags); +- list_add(&gpioh->head, &priv->handlers); +- spin_unlock_irqrestore(&priv->lock, flags); +- return 0; ++ return !!(nv_rd32(dev, 0x00d610 + (line * 4)) & 0x00004000); + } + +-void +-nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag, +- void (*handler)(void *, int), void *data) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- struct nv50_gpio_priv *priv = pgpio->priv; +- struct nv50_gpio_handler *gpioh, *tmp; +- struct dcb_gpio_entry *gpio; +- LIST_HEAD(tofree); +- unsigned long flags; +- +- gpio = nouveau_bios_gpio_entry(dev, tag); +- if (!gpio) +- return; +- +- spin_lock_irqsave(&priv->lock, flags); +- list_for_each_entry_safe(gpioh, tmp, &priv->handlers, head) { +- if (gpioh->gpio != gpio || +- gpioh->handler != handler || +- gpioh->data != data) +- continue; +- list_move(&gpioh->head, &tofree); +- } +- spin_unlock_irqrestore(&priv->lock, flags); +- +- list_for_each_entry_safe(gpioh, tmp, &tofree, head) { +- flush_work_sync(&gpioh->work); +- kfree(gpioh); +- } +-} +- +-bool +-nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on) +-{ +- struct dcb_gpio_entry *gpio; +- u32 reg, mask; +- +- gpio = nouveau_bios_gpio_entry(dev, tag); +- if (!gpio) +- return false; +- +- reg = gpio->line < 16 ? 0xe050 : 0xe070; +- mask = 0x00010001 << (gpio->line & 0xf); +- +- nv_wr32(dev, reg + 4, mask); +- reg = nv_mask(dev, reg + 0, mask, on ? mask : 0); +- return (reg & mask) == mask; +-} +- +-static int +-nv50_gpio_create(struct drm_device *dev) ++static void ++nv50_gpio_isr(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- struct nv50_gpio_priv *priv; +- +- priv = kzalloc(sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; ++ u32 intr0, intr1 = 0; ++ u32 hi, lo; + +- INIT_LIST_HEAD(&priv->handlers); +- spin_lock_init(&priv->lock); +- pgpio->priv = priv; +- return 0; +-} ++ intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); ++ if (dev_priv->chipset >= 0x90) ++ intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); + +-static void +-nv50_gpio_destroy(struct drm_device *dev) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ hi = (intr0 & 0x0000ffff) | (intr1 << 16); ++ lo = (intr0 >> 16) | (intr1 & 0xffff0000); ++ nouveau_gpio_isr(dev, 0, hi | lo); + +- kfree(pgpio->priv); +- pgpio->priv = NULL; ++ nv_wr32(dev, 0xe054, intr0); ++ if (dev_priv->chipset >= 0x90) ++ nv_wr32(dev, 0xe074, intr1); + } + + int + nv50_gpio_init(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- int ret; +- +- if (!pgpio->priv) { +- ret = nv50_gpio_create(dev); +- if (ret) +- return ret; +- } + + /* disable, and ack any pending gpio interrupts */ + nv_wr32(dev, 0xe050, 0x00000000); +@@ -270,64 +136,4 @@ nv50_gpio_fini(struct drm_device *dev) + if (dev_priv->chipset >= 0x90) + nv_wr32(dev, 0xe070, 0x00000000); + nouveau_irq_unregister(dev, 21); +- +- nv50_gpio_destroy(dev); +-} +- +-static void +-nv50_gpio_isr_bh(struct work_struct *work) +-{ +- struct nv50_gpio_handler *gpioh = +- container_of(work, struct nv50_gpio_handler, work); +- struct drm_nouveau_private *dev_priv = gpioh->dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- struct nv50_gpio_priv *priv = pgpio->priv; +- unsigned long flags; +- int state; +- +- state = pgpio->get(gpioh->dev, gpioh->gpio->tag); +- if (state < 0) +- return; +- +- gpioh->handler(gpioh->data, state); +- +- spin_lock_irqsave(&priv->lock, flags); +- gpioh->inhibit = false; +- spin_unlock_irqrestore(&priv->lock, flags); +-} +- +-static void +-nv50_gpio_isr(struct drm_device *dev) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- struct nv50_gpio_priv *priv = pgpio->priv; +- struct nv50_gpio_handler *gpioh; +- u32 intr0, intr1 = 0; +- u32 hi, lo, ch; +- +- intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); +- if (dev_priv->chipset >= 0x90) +- intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); +- +- hi = (intr0 & 0x0000ffff) | (intr1 << 16); +- lo = (intr0 >> 16) | (intr1 & 0xffff0000); +- ch = hi | lo; +- +- nv_wr32(dev, 0xe054, intr0); +- if (dev_priv->chipset >= 0x90) +- nv_wr32(dev, 0xe074, intr1); +- +- spin_lock(&priv->lock); +- list_for_each_entry(gpioh, &priv->handlers, head) { +- if (!(ch & (1 << gpioh->gpio->line))) +- continue; +- +- if (gpioh->inhibit) +- continue; +- gpioh->inhibit = true; +- +- schedule_work(&gpioh->work); +- } +- spin_unlock(&priv->lock); + } +diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c +index ac601f7..33d5711 100644 +--- a/drivers/gpu/drm/nouveau/nv50_graph.c ++++ b/drivers/gpu/drm/nouveau/nv50_graph.c +@@ -616,9 +616,9 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, + } + break; + case 7: /* MP error */ +- if (ustatus & 0x00010000) { ++ if (ustatus & 0x04030000) { + nv50_pgraph_mp_trap(dev, i, display); +- ustatus &= ~0x00010000; ++ ustatus &= ~0x04030000; + } + break; + case 8: /* TPDMA error */ +diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c +index 3d5a86b..d020ed4 100644 +--- a/drivers/gpu/drm/nouveau/nv50_pm.c ++++ b/drivers/gpu/drm/nouveau/nv50_pm.c +@@ -25,122 +25,862 @@ + #include "drmP.h" + #include "nouveau_drv.h" + #include "nouveau_bios.h" ++#include "nouveau_hw.h" + #include "nouveau_pm.h" ++#include "nouveau_hwsq.h" ++#include "nv50_display.h" ++ ++enum clk_src { ++ clk_src_crystal, ++ clk_src_href, ++ clk_src_hclk, ++ clk_src_hclkm3, ++ clk_src_hclkm3d2, ++ clk_src_host, ++ clk_src_nvclk, ++ clk_src_sclk, ++ clk_src_mclk, ++ clk_src_vdec, ++ clk_src_dom6 ++}; ++ ++static u32 read_clk(struct drm_device *, enum clk_src); ++ ++static u32 ++read_div(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ switch (dev_priv->chipset) { ++ case 0x50: /* it exists, but only has bit 31, not the dividers.. */ ++ case 0x84: ++ case 0x86: ++ case 0x98: ++ case 0xa0: ++ return nv_rd32(dev, 0x004700); ++ case 0x92: ++ case 0x94: ++ case 0x96: ++ return nv_rd32(dev, 0x004800); ++ default: ++ return 0x00000000; ++ } ++} ++ ++static u32 ++read_pll_src(struct drm_device *dev, u32 base) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 coef, ref = read_clk(dev, clk_src_crystal); ++ u32 rsel = nv_rd32(dev, 0x00e18c); ++ int P, N, M, id; ++ ++ switch (dev_priv->chipset) { ++ case 0x50: ++ case 0xa0: ++ switch (base) { ++ case 0x4020: ++ case 0x4028: id = !!(rsel & 0x00000004); break; ++ case 0x4008: id = !!(rsel & 0x00000008); break; ++ case 0x4030: id = 0; break; ++ default: ++ NV_ERROR(dev, "ref: bad pll 0x%06x\n", base); ++ return 0; ++ } ++ ++ coef = nv_rd32(dev, 0x00e81c + (id * 0x0c)); ++ ref *= (coef & 0x01000000) ? 2 : 4; ++ P = (coef & 0x00070000) >> 16; ++ N = ((coef & 0x0000ff00) >> 8) + 1; ++ M = ((coef & 0x000000ff) >> 0) + 1; ++ break; ++ case 0x84: ++ case 0x86: ++ case 0x92: ++ coef = nv_rd32(dev, 0x00e81c); ++ P = (coef & 0x00070000) >> 16; ++ N = (coef & 0x0000ff00) >> 8; ++ M = (coef & 0x000000ff) >> 0; ++ break; ++ case 0x94: ++ case 0x96: ++ case 0x98: ++ rsel = nv_rd32(dev, 0x00c050); ++ switch (base) { ++ case 0x4020: rsel = (rsel & 0x00000003) >> 0; break; ++ case 0x4008: rsel = (rsel & 0x0000000c) >> 2; break; ++ case 0x4028: rsel = (rsel & 0x00001800) >> 11; break; ++ case 0x4030: rsel = 3; break; ++ default: ++ NV_ERROR(dev, "ref: bad pll 0x%06x\n", base); ++ return 0; ++ } ++ ++ switch (rsel) { ++ case 0: id = 1; break; ++ case 1: return read_clk(dev, clk_src_crystal); ++ case 2: return read_clk(dev, clk_src_href); ++ case 3: id = 0; break; ++ } ++ ++ coef = nv_rd32(dev, 0x00e81c + (id * 0x28)); ++ P = (nv_rd32(dev, 0x00e824 + (id * 0x28)) >> 16) & 7; ++ P += (coef & 0x00070000) >> 16; ++ N = (coef & 0x0000ff00) >> 8; ++ M = (coef & 0x000000ff) >> 0; ++ break; ++ default: ++ BUG_ON(1); ++ } ++ ++ if (M) ++ return (ref * N / M) >> P; ++ return 0; ++} ++ ++static u32 ++read_pll_ref(struct drm_device *dev, u32 base) ++{ ++ u32 src, mast = nv_rd32(dev, 0x00c040); ++ ++ switch (base) { ++ case 0x004028: ++ src = !!(mast & 0x00200000); ++ break; ++ case 0x004020: ++ src = !!(mast & 0x00400000); ++ break; ++ case 0x004008: ++ src = !!(mast & 0x00010000); ++ break; ++ case 0x004030: ++ src = !!(mast & 0x02000000); ++ break; ++ case 0x00e810: ++ return read_clk(dev, clk_src_crystal); ++ default: ++ NV_ERROR(dev, "bad pll 0x%06x\n", base); ++ return 0; ++ } ++ ++ if (src) ++ return read_clk(dev, clk_src_href); ++ return read_pll_src(dev, base); ++} ++ ++static u32 ++read_pll(struct drm_device *dev, u32 base) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 mast = nv_rd32(dev, 0x00c040); ++ u32 ctrl = nv_rd32(dev, base + 0); ++ u32 coef = nv_rd32(dev, base + 4); ++ u32 ref = read_pll_ref(dev, base); ++ u32 clk = 0; ++ int N1, N2, M1, M2; ++ ++ if (base == 0x004028 && (mast & 0x00100000)) { ++ /* wtf, appears to only disable post-divider on nva0 */ ++ if (dev_priv->chipset != 0xa0) ++ return read_clk(dev, clk_src_dom6); ++ } ++ ++ N2 = (coef & 0xff000000) >> 24; ++ M2 = (coef & 0x00ff0000) >> 16; ++ N1 = (coef & 0x0000ff00) >> 8; ++ M1 = (coef & 0x000000ff); ++ if ((ctrl & 0x80000000) && M1) { ++ clk = ref * N1 / M1; ++ if ((ctrl & 0x40000100) == 0x40000000) { ++ if (M2) ++ clk = clk * N2 / M2; ++ else ++ clk = 0; ++ } ++ } ++ ++ return clk; ++} ++ ++static u32 ++read_clk(struct drm_device *dev, enum clk_src src) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 mast = nv_rd32(dev, 0x00c040); ++ u32 P = 0; ++ ++ switch (src) { ++ case clk_src_crystal: ++ return dev_priv->crystal; ++ case clk_src_href: ++ return 100000; /* PCIE reference clock */ ++ case clk_src_hclk: ++ return read_clk(dev, clk_src_href) * 27778 / 10000; ++ case clk_src_hclkm3: ++ return read_clk(dev, clk_src_hclk) * 3; ++ case clk_src_hclkm3d2: ++ return read_clk(dev, clk_src_hclk) * 3 / 2; ++ case clk_src_host: ++ switch (mast & 0x30000000) { ++ case 0x00000000: return read_clk(dev, clk_src_href); ++ case 0x10000000: break; ++ case 0x20000000: /* !0x50 */ ++ case 0x30000000: return read_clk(dev, clk_src_hclk); ++ } ++ break; ++ case clk_src_nvclk: ++ if (!(mast & 0x00100000)) ++ P = (nv_rd32(dev, 0x004028) & 0x00070000) >> 16; ++ switch (mast & 0x00000003) { ++ case 0x00000000: return read_clk(dev, clk_src_crystal) >> P; ++ case 0x00000001: return read_clk(dev, clk_src_dom6); ++ case 0x00000002: return read_pll(dev, 0x004020) >> P; ++ case 0x00000003: return read_pll(dev, 0x004028) >> P; ++ } ++ break; ++ case clk_src_sclk: ++ P = (nv_rd32(dev, 0x004020) & 0x00070000) >> 16; ++ switch (mast & 0x00000030) { ++ case 0x00000000: ++ if (mast & 0x00000080) ++ return read_clk(dev, clk_src_host) >> P; ++ return read_clk(dev, clk_src_crystal) >> P; ++ case 0x00000010: break; ++ case 0x00000020: return read_pll(dev, 0x004028) >> P; ++ case 0x00000030: return read_pll(dev, 0x004020) >> P; ++ } ++ break; ++ case clk_src_mclk: ++ P = (nv_rd32(dev, 0x004008) & 0x00070000) >> 16; ++ if (nv_rd32(dev, 0x004008) & 0x00000200) { ++ switch (mast & 0x0000c000) { ++ case 0x00000000: ++ return read_clk(dev, clk_src_crystal) >> P; ++ case 0x00008000: ++ case 0x0000c000: ++ return read_clk(dev, clk_src_href) >> P; ++ } ++ } else { ++ return read_pll(dev, 0x004008) >> P; ++ } ++ break; ++ case clk_src_vdec: ++ P = (read_div(dev) & 0x00000700) >> 8; ++ switch (dev_priv->chipset) { ++ case 0x84: ++ case 0x86: ++ case 0x92: ++ case 0x94: ++ case 0x96: ++ case 0xa0: ++ switch (mast & 0x00000c00) { ++ case 0x00000000: ++ if (dev_priv->chipset == 0xa0) /* wtf?? */ ++ return read_clk(dev, clk_src_nvclk) >> P; ++ return read_clk(dev, clk_src_crystal) >> P; ++ case 0x00000400: ++ return 0; ++ case 0x00000800: ++ if (mast & 0x01000000) ++ return read_pll(dev, 0x004028) >> P; ++ return read_pll(dev, 0x004030) >> P; ++ case 0x00000c00: ++ return read_clk(dev, clk_src_nvclk) >> P; ++ } ++ break; ++ case 0x98: ++ switch (mast & 0x00000c00) { ++ case 0x00000000: ++ return read_clk(dev, clk_src_nvclk) >> P; ++ case 0x00000400: ++ return 0; ++ case 0x00000800: ++ return read_clk(dev, clk_src_hclkm3d2) >> P; ++ case 0x00000c00: ++ return read_clk(dev, clk_src_mclk) >> P; ++ } ++ break; ++ } ++ break; ++ case clk_src_dom6: ++ switch (dev_priv->chipset) { ++ case 0x50: ++ case 0xa0: ++ return read_pll(dev, 0x00e810) >> 2; ++ case 0x84: ++ case 0x86: ++ case 0x92: ++ case 0x94: ++ case 0x96: ++ case 0x98: ++ P = (read_div(dev) & 0x00000007) >> 0; ++ switch (mast & 0x0c000000) { ++ case 0x00000000: return read_clk(dev, clk_src_href); ++ case 0x04000000: break; ++ case 0x08000000: return read_clk(dev, clk_src_hclk); ++ case 0x0c000000: ++ return read_clk(dev, clk_src_hclkm3) >> P; ++ } ++ break; ++ default: ++ break; ++ } ++ default: ++ break; ++ } ++ ++ NV_DEBUG(dev, "unknown clock source %d 0x%08x\n", src, mast); ++ return 0; ++} ++ ++int ++nv50_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ if (dev_priv->chipset == 0xaa || ++ dev_priv->chipset == 0xac) ++ return 0; ++ ++ perflvl->core = read_clk(dev, clk_src_nvclk); ++ perflvl->shader = read_clk(dev, clk_src_sclk); ++ perflvl->memory = read_clk(dev, clk_src_mclk); ++ if (dev_priv->chipset != 0x50) { ++ perflvl->vdec = read_clk(dev, clk_src_vdec); ++ perflvl->dom6 = read_clk(dev, clk_src_dom6); ++ } ++ ++ return 0; ++} + + struct nv50_pm_state { + struct nouveau_pm_level *perflvl; +- struct pll_lims pll; +- enum pll_types type; +- int N, M, P; ++ struct hwsq_ucode eclk_hwsq; ++ struct hwsq_ucode mclk_hwsq; ++ u32 mscript; ++ u32 mmast; ++ u32 mctrl; ++ u32 mcoef; + }; + +-int +-nv50_pm_clock_get(struct drm_device *dev, u32 id) ++static u32 ++calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, ++ u32 clk, int *N1, int *M1, int *log2P) + { +- struct pll_lims pll; +- int P, N, M, ret; +- u32 reg0, reg1; ++ struct nouveau_pll_vals coef; ++ int ret; + +- ret = get_pll_limits(dev, id, &pll); ++ ret = get_pll_limits(dev, reg, pll); + if (ret) +- return ret; ++ return 0; ++ ++ pll->vco2.maxfreq = 0; ++ pll->refclk = read_pll_ref(dev, reg); ++ if (!pll->refclk) ++ return 0; ++ ++ ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef); ++ if (ret == 0) ++ return 0; + +- reg0 = nv_rd32(dev, pll.reg + 0); +- reg1 = nv_rd32(dev, pll.reg + 4); +- +- if ((reg0 & 0x80000000) == 0) { +- if (id == PLL_SHADER) { +- NV_DEBUG(dev, "Shader PLL is disabled. " +- "Shader clock is twice the core\n"); +- ret = nv50_pm_clock_get(dev, PLL_CORE); +- if (ret > 0) +- return ret << 1; +- } else if (id == PLL_MEMORY) { +- NV_DEBUG(dev, "Memory PLL is disabled. " +- "Memory clock is equal to the ref_clk\n"); +- return pll.refclk; ++ *N1 = coef.N1; ++ *M1 = coef.M1; ++ *log2P = coef.log2P; ++ return ret; ++} ++ ++static inline u32 ++calc_div(u32 src, u32 target, int *div) ++{ ++ u32 clk0 = src, clk1 = src; ++ for (*div = 0; *div <= 7; (*div)++) { ++ if (clk0 <= target) { ++ clk1 = clk0 << (*div ? 1 : 0); ++ break; + } ++ clk0 >>= 1; ++ } ++ ++ if (target - clk0 <= clk1 - target) ++ return clk0; ++ (*div)--; ++ return clk1; ++} ++ ++static inline u32 ++clk_same(u32 a, u32 b) ++{ ++ return ((a / 1000) == (b / 1000)); ++} ++ ++static void ++mclk_precharge(struct nouveau_mem_exec_func *exec) ++{ ++ struct nv50_pm_state *info = exec->priv; ++ struct hwsq_ucode *hwsq = &info->mclk_hwsq; ++ ++ hwsq_wr32(hwsq, 0x1002d4, 0x00000001); ++} ++ ++static void ++mclk_refresh(struct nouveau_mem_exec_func *exec) ++{ ++ struct nv50_pm_state *info = exec->priv; ++ struct hwsq_ucode *hwsq = &info->mclk_hwsq; ++ ++ hwsq_wr32(hwsq, 0x1002d0, 0x00000001); ++} ++ ++static void ++mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable) ++{ ++ struct nv50_pm_state *info = exec->priv; ++ struct hwsq_ucode *hwsq = &info->mclk_hwsq; ++ ++ hwsq_wr32(hwsq, 0x100210, enable ? 0x80000000 : 0x00000000); ++} ++ ++static void ++mclk_refresh_self(struct nouveau_mem_exec_func *exec, bool enable) ++{ ++ struct nv50_pm_state *info = exec->priv; ++ struct hwsq_ucode *hwsq = &info->mclk_hwsq; ++ ++ hwsq_wr32(hwsq, 0x1002dc, enable ? 0x00000001 : 0x00000000); ++} ++ ++static void ++mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec) ++{ ++ struct nv50_pm_state *info = exec->priv; ++ struct hwsq_ucode *hwsq = &info->mclk_hwsq; ++ ++ if (nsec > 1000) ++ hwsq_usec(hwsq, (nsec + 500) / 1000); ++} ++ ++static u32 ++mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) ++{ ++ if (mr <= 1) ++ return nv_rd32(exec->dev, 0x1002c0 + ((mr - 0) * 4)); ++ if (mr <= 3) ++ return nv_rd32(exec->dev, 0x1002e0 + ((mr - 2) * 4)); ++ return 0; ++} ++ ++static void ++mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) ++{ ++ struct drm_nouveau_private *dev_priv = exec->dev->dev_private; ++ struct nv50_pm_state *info = exec->priv; ++ struct hwsq_ucode *hwsq = &info->mclk_hwsq; ++ ++ if (mr <= 1) { ++ if (dev_priv->vram_rank_B) ++ hwsq_wr32(hwsq, 0x1002c8 + ((mr - 0) * 4), data); ++ hwsq_wr32(hwsq, 0x1002c0 + ((mr - 0) * 4), data); ++ } else ++ if (mr <= 3) { ++ if (dev_priv->vram_rank_B) ++ hwsq_wr32(hwsq, 0x1002e8 + ((mr - 2) * 4), data); ++ hwsq_wr32(hwsq, 0x1002e0 + ((mr - 2) * 4), data); ++ } ++} ++ ++static void ++mclk_clock_set(struct nouveau_mem_exec_func *exec) ++{ ++ struct nv50_pm_state *info = exec->priv; ++ struct hwsq_ucode *hwsq = &info->mclk_hwsq; ++ u32 ctrl = nv_rd32(exec->dev, 0x004008); ++ ++ info->mmast = nv_rd32(exec->dev, 0x00c040); ++ info->mmast &= ~0xc0000000; /* get MCLK_2 from HREF */ ++ info->mmast |= 0x0000c000; /* use MCLK_2 as MPLL_BYPASS clock */ ++ ++ hwsq_wr32(hwsq, 0xc040, info->mmast); ++ hwsq_wr32(hwsq, 0x4008, ctrl | 0x00000200); /* bypass MPLL */ ++ if (info->mctrl & 0x80000000) ++ hwsq_wr32(hwsq, 0x400c, info->mcoef); ++ hwsq_wr32(hwsq, 0x4008, info->mctrl); ++} ++ ++static void ++mclk_timing_set(struct nouveau_mem_exec_func *exec) ++{ ++ struct drm_device *dev = exec->dev; ++ struct nv50_pm_state *info = exec->priv; ++ struct nouveau_pm_level *perflvl = info->perflvl; ++ struct hwsq_ucode *hwsq = &info->mclk_hwsq; ++ int i; ++ ++ for (i = 0; i < 9; i++) { ++ u32 reg = 0x100220 + (i * 4); ++ u32 val = nv_rd32(dev, reg); ++ if (val != perflvl->timing.reg[i]) ++ hwsq_wr32(hwsq, reg, perflvl->timing.reg[i]); ++ } ++} ++ ++static int ++calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, ++ struct nv50_pm_state *info) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 crtc_mask = nv50_display_active_crtcs(dev); ++ struct nouveau_mem_exec_func exec = { ++ .dev = dev, ++ .precharge = mclk_precharge, ++ .refresh = mclk_refresh, ++ .refresh_auto = mclk_refresh_auto, ++ .refresh_self = mclk_refresh_self, ++ .wait = mclk_wait, ++ .mrg = mclk_mrg, ++ .mrs = mclk_mrs, ++ .clock_set = mclk_clock_set, ++ .timing_set = mclk_timing_set, ++ .priv = info ++ }; ++ struct hwsq_ucode *hwsq = &info->mclk_hwsq; ++ struct pll_lims pll; ++ int N, M, P; ++ int ret; ++ ++ /* use pcie refclock if possible, otherwise use mpll */ ++ info->mctrl = nv_rd32(dev, 0x004008); ++ info->mctrl &= ~0x81ff0200; ++ if (clk_same(perflvl->memory, read_clk(dev, clk_src_href))) { ++ info->mctrl |= 0x00000200 | (pll.log2p_bias << 19); ++ } else { ++ ret = calc_pll(dev, 0x4008, &pll, perflvl->memory, &N, &M, &P); ++ if (ret == 0) ++ return -EINVAL; ++ ++ info->mctrl |= 0x80000000 | (P << 22) | (P << 16); ++ info->mctrl |= pll.log2p_bias << 19; ++ info->mcoef = (N << 8) | M; + } + +- P = (reg0 & 0x00070000) >> 16; +- N = (reg1 & 0x0000ff00) >> 8; +- M = (reg1 & 0x000000ff); ++ /* build the ucode which will reclock the memory for us */ ++ hwsq_init(hwsq); ++ if (crtc_mask) { ++ hwsq_op5f(hwsq, crtc_mask, 0x00); /* wait for scanout */ ++ hwsq_op5f(hwsq, crtc_mask, 0x01); /* wait for vblank */ ++ } ++ if (dev_priv->chipset >= 0x92) ++ hwsq_wr32(hwsq, 0x611200, 0x00003300); /* disable scanout */ ++ hwsq_setf(hwsq, 0x10, 0); /* disable bus access */ ++ hwsq_op5f(hwsq, 0x00, 0x01); /* no idea :s */ + +- return ((pll.refclk * N / M) >> P); ++ ret = nouveau_mem_exec(&exec, perflvl); ++ if (ret) ++ return ret; ++ ++ hwsq_setf(hwsq, 0x10, 1); /* enable bus access */ ++ hwsq_op5f(hwsq, 0x00, 0x00); /* no idea, reverse of 0x00, 0x01? */ ++ if (dev_priv->chipset >= 0x92) ++ hwsq_wr32(hwsq, 0x611200, 0x00003330); /* enable scanout */ ++ hwsq_fini(hwsq); ++ return 0; + } + + void * +-nv50_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, +- u32 id, int khz) ++nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) + { +- struct nv50_pm_state *state; +- int dummy, ret; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_pm_state *info; ++ struct hwsq_ucode *hwsq; ++ struct pll_lims pll; ++ u32 out, mast, divs, ctrl; ++ int clk, ret = -EINVAL; ++ int N, M, P1, P2; + +- state = kzalloc(sizeof(*state), GFP_KERNEL); +- if (!state) ++ if (dev_priv->chipset == 0xaa || ++ dev_priv->chipset == 0xac) ++ return ERR_PTR(-ENODEV); ++ ++ info = kmalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) + return ERR_PTR(-ENOMEM); +- state->type = id; +- state->perflvl = perflvl; ++ info->perflvl = perflvl; ++ ++ /* memory: build hwsq ucode which we'll use to reclock memory. ++ * use pcie refclock if possible, otherwise use mpll */ ++ info->mclk_hwsq.len = 0; ++ if (perflvl->memory) { ++ ret = calc_mclk(dev, perflvl, info); ++ if (ret) ++ goto error; ++ info->mscript = perflvl->memscript; ++ } ++ ++ divs = read_div(dev); ++ mast = info->mmast; ++ ++ /* start building HWSQ script for engine reclocking */ ++ hwsq = &info->eclk_hwsq; ++ hwsq_init(hwsq); ++ hwsq_setf(hwsq, 0x10, 0); /* disable bus access */ ++ hwsq_op5f(hwsq, 0x00, 0x01); /* wait for access disabled? */ ++ ++ /* vdec/dom6: switch to "safe" clocks temporarily */ ++ if (perflvl->vdec) { ++ mast &= ~0x00000c00; ++ divs &= ~0x00000700; ++ } ++ ++ if (perflvl->dom6) { ++ mast &= ~0x0c000000; ++ divs &= ~0x00000007; ++ } ++ ++ hwsq_wr32(hwsq, 0x00c040, mast); ++ ++ /* vdec: avoid modifying xpll until we know exactly how the other ++ * clock domains work, i suspect at least some of them can also be ++ * tied to xpll... ++ */ ++ if (perflvl->vdec) { ++ /* see how close we can get using nvclk as a source */ ++ clk = calc_div(perflvl->core, perflvl->vdec, &P1); ++ ++ /* see how close we can get using xpll/hclk as a source */ ++ if (dev_priv->chipset != 0x98) ++ out = read_pll(dev, 0x004030); ++ else ++ out = read_clk(dev, clk_src_hclkm3d2); ++ out = calc_div(out, perflvl->vdec, &P2); ++ ++ /* select whichever gets us closest */ ++ if (abs((int)perflvl->vdec - clk) <= ++ abs((int)perflvl->vdec - out)) { ++ if (dev_priv->chipset != 0x98) ++ mast |= 0x00000c00; ++ divs |= P1 << 8; ++ } else { ++ mast |= 0x00000800; ++ divs |= P2 << 8; ++ } ++ } ++ ++ /* dom6: nfi what this is, but we're limited to various combinations ++ * of the host clock frequency ++ */ ++ if (perflvl->dom6) { ++ if (clk_same(perflvl->dom6, read_clk(dev, clk_src_href))) { ++ mast |= 0x00000000; ++ } else ++ if (clk_same(perflvl->dom6, read_clk(dev, clk_src_hclk))) { ++ mast |= 0x08000000; ++ } else { ++ clk = read_clk(dev, clk_src_hclk) * 3; ++ clk = calc_div(clk, perflvl->dom6, &P1); ++ ++ mast |= 0x0c000000; ++ divs |= P1; ++ } ++ } ++ ++ /* vdec/dom6: complete switch to new clocks */ ++ switch (dev_priv->chipset) { ++ case 0x92: ++ case 0x94: ++ case 0x96: ++ hwsq_wr32(hwsq, 0x004800, divs); ++ break; ++ default: ++ hwsq_wr32(hwsq, 0x004700, divs); ++ break; ++ } ++ ++ hwsq_wr32(hwsq, 0x00c040, mast); ++ ++ /* core/shader: make sure sclk/nvclk are disconnected from their ++ * PLLs (nvclk to dom6, sclk to hclk) ++ */ ++ if (dev_priv->chipset < 0x92) ++ mast = (mast & ~0x001000b0) | 0x00100080; ++ else ++ mast = (mast & ~0x000000b3) | 0x00000081; ++ ++ hwsq_wr32(hwsq, 0x00c040, mast); ++ ++ /* core: for the moment at least, always use nvpll */ ++ clk = calc_pll(dev, 0x4028, &pll, perflvl->core, &N, &M, &P1); ++ if (clk == 0) ++ goto error; ++ ++ ctrl = nv_rd32(dev, 0x004028) & ~0xc03f0100; ++ mast &= ~0x00100000; ++ mast |= 3; ++ ++ hwsq_wr32(hwsq, 0x004028, 0x80000000 | (P1 << 19) | (P1 << 16) | ctrl); ++ hwsq_wr32(hwsq, 0x00402c, (N << 8) | M); ++ ++ /* shader: tie to nvclk if possible, otherwise use spll. have to be ++ * very careful that the shader clock is at least twice the core, or ++ * some chipsets will be very unhappy. i expect most or all of these ++ * cases will be handled by tying to nvclk, but it's possible there's ++ * corners ++ */ ++ ctrl = nv_rd32(dev, 0x004020) & ~0xc03f0100; ++ ++ if (P1-- && perflvl->shader == (perflvl->core << 1)) { ++ hwsq_wr32(hwsq, 0x004020, (P1 << 19) | (P1 << 16) | ctrl); ++ hwsq_wr32(hwsq, 0x00c040, 0x00000020 | mast); ++ } else { ++ clk = calc_pll(dev, 0x4020, &pll, perflvl->shader, &N, &M, &P1); ++ if (clk == 0) ++ goto error; ++ ctrl |= 0x80000000; ++ ++ hwsq_wr32(hwsq, 0x004020, (P1 << 19) | (P1 << 16) | ctrl); ++ hwsq_wr32(hwsq, 0x004024, (N << 8) | M); ++ hwsq_wr32(hwsq, 0x00c040, 0x00000030 | mast); ++ } ++ ++ hwsq_setf(hwsq, 0x10, 1); /* enable bus access */ ++ hwsq_op5f(hwsq, 0x00, 0x00); /* wait for access enabled? */ ++ hwsq_fini(hwsq); ++ ++ return info; ++error: ++ kfree(info); ++ return ERR_PTR(ret); ++} ++ ++static int ++prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 hwsq_data, hwsq_kick; ++ int i; + +- ret = get_pll_limits(dev, id, &state->pll); +- if (ret < 0) { +- kfree(state); +- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); ++ if (dev_priv->chipset < 0x94) { ++ hwsq_data = 0x001400; ++ hwsq_kick = 0x00000003; ++ } else { ++ hwsq_data = 0x080000; ++ hwsq_kick = 0x00000001; + } ++ /* upload hwsq ucode */ ++ nv_mask(dev, 0x001098, 0x00000008, 0x00000000); ++ nv_wr32(dev, 0x001304, 0x00000000); ++ if (dev_priv->chipset >= 0x92) ++ nv_wr32(dev, 0x001318, 0x00000000); ++ for (i = 0; i < hwsq->len / 4; i++) ++ nv_wr32(dev, hwsq_data + (i * 4), hwsq->ptr.u32[i]); ++ nv_mask(dev, 0x001098, 0x00000018, 0x00000018); ++ ++ /* launch, and wait for completion */ ++ nv_wr32(dev, 0x00130c, hwsq_kick); ++ if (!nv_wait(dev, 0x001308, 0x00000100, 0x00000000)) { ++ NV_ERROR(dev, "hwsq ucode exec timed out\n"); ++ NV_ERROR(dev, "0x001308: 0x%08x\n", nv_rd32(dev, 0x001308)); ++ for (i = 0; i < hwsq->len / 4; i++) { ++ NV_ERROR(dev, "0x%06x: 0x%08x\n", 0x1400 + (i * 4), ++ nv_rd32(dev, 0x001400 + (i * 4))); ++ } + +- ret = nv50_calc_pll(dev, &state->pll, khz, &state->N, &state->M, +- &dummy, &dummy, &state->P); +- if (ret < 0) { +- kfree(state); +- return ERR_PTR(ret); ++ return -EIO; + } + +- return state; ++ return 0; + } + +-void +-nv50_pm_clock_set(struct drm_device *dev, void *pre_state) ++int ++nv50_pm_clocks_set(struct drm_device *dev, void *data) + { +- struct nv50_pm_state *state = pre_state; +- struct nouveau_pm_level *perflvl = state->perflvl; +- u32 reg = state->pll.reg, tmp; +- struct bit_entry BIT_M; +- u16 script; +- int N = state->N; +- int M = state->M; +- int P = state->P; ++ struct nv50_pm_state *info = data; ++ struct bit_entry M; ++ int ret = -EBUSY; ++ ++ /* halt and idle execution engines */ ++ nv_mask(dev, 0x002504, 0x00000001, 0x00000001); ++ if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) ++ goto resume; ++ if (!nv_wait(dev, 0x00251c, 0x0000003f, 0x0000003f)) ++ goto resume; + +- if (state->type == PLL_MEMORY && perflvl->memscript && +- bit_table(dev, 'M', &BIT_M) == 0 && +- BIT_M.version == 1 && BIT_M.length >= 0x0b) { +- script = ROM16(BIT_M.data[0x05]); +- if (script) +- nouveau_bios_run_init_table(dev, script, NULL, -1); +- script = ROM16(BIT_M.data[0x07]); +- if (script) +- nouveau_bios_run_init_table(dev, script, NULL, -1); +- script = ROM16(BIT_M.data[0x09]); +- if (script) +- nouveau_bios_run_init_table(dev, script, NULL, -1); ++ /* program memory clock, if necessary - must come before engine clock ++ * reprogramming due to how we construct the hwsq scripts in pre() ++ */ ++ if (info->mclk_hwsq.len) { ++ /* execute some scripts that do ??? from the vbios.. */ ++ if (!bit_table(dev, 'M', &M) && M.version == 1) { ++ if (M.length >= 6) ++ nouveau_bios_init_exec(dev, ROM16(M.data[5])); ++ if (M.length >= 8) ++ nouveau_bios_init_exec(dev, ROM16(M.data[7])); ++ if (M.length >= 10) ++ nouveau_bios_init_exec(dev, ROM16(M.data[9])); ++ nouveau_bios_init_exec(dev, info->mscript); ++ } + +- nouveau_bios_run_init_table(dev, perflvl->memscript, NULL, -1); ++ ret = prog_hwsq(dev, &info->mclk_hwsq); ++ if (ret) ++ goto resume; + } + +- if (state->type == PLL_MEMORY) { +- nv_wr32(dev, 0x100210, 0); +- nv_wr32(dev, 0x1002dc, 1); ++ /* program engine clocks */ ++ ret = prog_hwsq(dev, &info->eclk_hwsq); ++ ++resume: ++ nv_mask(dev, 0x002504, 0x00000001, 0x00000000); ++ kfree(info); ++ return ret; ++} ++ ++static int ++pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx) ++{ ++ if (*line == 0x04) { ++ *ctrl = 0x00e100; ++ *line = 4; ++ *indx = 0; ++ } else ++ if (*line == 0x09) { ++ *ctrl = 0x00e100; ++ *line = 9; ++ *indx = 1; ++ } else ++ if (*line == 0x10) { ++ *ctrl = 0x00e28c; ++ *line = 0; ++ *indx = 0; ++ } else { ++ NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", *line); ++ return -ENODEV; + } + +- tmp = nv_rd32(dev, reg + 0) & 0xfff8ffff; +- tmp |= 0x80000000 | (P << 16); +- nv_wr32(dev, reg + 0, tmp); +- nv_wr32(dev, reg + 4, (N << 8) | M); ++ return 0; ++} ++ ++int ++nv50_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) ++{ ++ int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id); ++ if (ret) ++ return ret; + +- if (state->type == PLL_MEMORY) { +- nv_wr32(dev, 0x1002dc, 0); +- nv_wr32(dev, 0x100210, 0x80000000); ++ if (nv_rd32(dev, ctrl) & (1 << line)) { ++ *divs = nv_rd32(dev, 0x00e114 + (id * 8)); ++ *duty = nv_rd32(dev, 0x00e118 + (id * 8)); ++ return 0; + } + +- kfree(state); ++ return -EINVAL; + } + ++int ++nv50_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty) ++{ ++ int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id); ++ if (ret) ++ return ret; ++ ++ nv_mask(dev, ctrl, 0x00010001 << line, 0x00000001 << line); ++ nv_wr32(dev, 0x00e114 + (id * 8), divs); ++ nv_wr32(dev, 0x00e118 + (id * 8), duty | 0x80000000); ++ return 0; ++} +diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c +index 2633aa8..2746402 100644 +--- a/drivers/gpu/drm/nouveau/nv50_sor.c ++++ b/drivers/gpu/drm/nouveau/nv50_sor.c +@@ -36,6 +36,193 @@ + #include "nouveau_crtc.h" + #include "nv50_display.h" + ++static u32 ++nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_entry *dcb, u8 lane) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */ ++ static const u8 nv50[] = { 16, 8, 0, 24 }; ++ if (dev_priv->chipset == 0xaf) ++ return nvaf[lane]; ++ return nv50[lane]; ++} ++ ++static void ++nv50_sor_dp_train_set(struct drm_device *dev, struct dcb_entry *dcb, u8 pattern) ++{ ++ u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); ++ nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x0f000000, pattern << 24); ++} ++ ++static void ++nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_entry *dcb, ++ u8 lane, u8 swing, u8 preem) ++{ ++ u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); ++ u32 shift = nv50_sor_dp_lane_map(dev, dcb, lane); ++ u32 mask = 0x000000ff << shift; ++ u8 *table, *entry, *config; ++ ++ table = nouveau_dp_bios_data(dev, dcb, &entry); ++ if (!table || (table[0] != 0x20 && table[0] != 0x21)) { ++ NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n"); ++ return; ++ } ++ ++ config = entry + table[4]; ++ while (config[0] != swing || config[1] != preem) { ++ config += table[5]; ++ if (config >= entry + table[4] + entry[4] * table[5]) ++ return; ++ } ++ ++ nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, config[2] << shift); ++ nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, config[3] << shift); ++ nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff00, config[4] << 8); ++} ++ ++static void ++nv50_sor_dp_link_set(struct drm_device *dev, struct dcb_entry *dcb, int crtc, ++ int link_nr, u32 link_bw, bool enhframe) ++{ ++ u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); ++ u32 dpctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)) & ~0x001f4000; ++ u32 clksor = nv_rd32(dev, 0x614300 + (or * 0x800)) & ~0x000c0000; ++ u8 *table, *entry, mask; ++ int i; ++ ++ table = nouveau_dp_bios_data(dev, dcb, &entry); ++ if (!table || (table[0] != 0x20 && table[0] != 0x21)) { ++ NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n"); ++ return; ++ } ++ ++ entry = ROMPTR(dev, entry[10]); ++ if (entry) { ++ while (link_bw < ROM16(entry[0]) * 10) ++ entry += 4; ++ ++ nouveau_bios_run_init_table(dev, ROM16(entry[2]), dcb, crtc); ++ } ++ ++ dpctrl |= ((1 << link_nr) - 1) << 16; ++ if (enhframe) ++ dpctrl |= 0x00004000; ++ ++ if (link_bw > 162000) ++ clksor |= 0x00040000; ++ ++ nv_wr32(dev, 0x614300 + (or * 0x800), clksor); ++ nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), dpctrl); ++ ++ mask = 0; ++ for (i = 0; i < link_nr; i++) ++ mask |= 1 << (nv50_sor_dp_lane_map(dev, dcb, i) >> 3); ++ nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000000f, mask); ++} ++ ++static void ++nv50_sor_dp_link_get(struct drm_device *dev, u32 or, u32 link, u32 *nr, u32 *bw) ++{ ++ u32 dpctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)) & 0x000f0000; ++ u32 clksor = nv_rd32(dev, 0x614300 + (or * 0x800)); ++ if (clksor & 0x000c0000) ++ *bw = 270000; ++ else ++ *bw = 162000; ++ ++ if (dpctrl > 0x00030000) *nr = 4; ++ else if (dpctrl > 0x00010000) *nr = 2; ++ else *nr = 1; ++} ++ ++void ++nv50_sor_dp_calc_tu(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) ++{ ++ const u32 symbol = 100000; ++ int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; ++ int TU, VTUi, VTUf, VTUa; ++ u64 link_data_rate, link_ratio, unk; ++ u32 best_diff = 64 * symbol; ++ u32 link_nr, link_bw, r; ++ ++ /* calculate packed data rate for each lane */ ++ nv50_sor_dp_link_get(dev, or, link, &link_nr, &link_bw); ++ link_data_rate = (clk * bpp / 8) / link_nr; ++ ++ /* calculate ratio of packed data rate to link symbol rate */ ++ link_ratio = link_data_rate * symbol; ++ r = do_div(link_ratio, link_bw); ++ ++ for (TU = 64; TU >= 32; TU--) { ++ /* calculate average number of valid symbols in each TU */ ++ u32 tu_valid = link_ratio * TU; ++ u32 calc, diff; ++ ++ /* find a hw representation for the fraction.. */ ++ VTUi = tu_valid / symbol; ++ calc = VTUi * symbol; ++ diff = tu_valid - calc; ++ if (diff) { ++ if (diff >= (symbol / 2)) { ++ VTUf = symbol / (symbol - diff); ++ if (symbol - (VTUf * diff)) ++ VTUf++; ++ ++ if (VTUf <= 15) { ++ VTUa = 1; ++ calc += symbol - (symbol / VTUf); ++ } else { ++ VTUa = 0; ++ VTUf = 1; ++ calc += symbol; ++ } ++ } else { ++ VTUa = 0; ++ VTUf = min((int)(symbol / diff), 15); ++ calc += symbol / VTUf; ++ } ++ ++ diff = calc - tu_valid; ++ } else { ++ /* no remainder, but the hw doesn't like the fractional ++ * part to be zero. decrement the integer part and ++ * have the fraction add a whole symbol back ++ */ ++ VTUa = 0; ++ VTUf = 1; ++ VTUi--; ++ } ++ ++ if (diff < best_diff) { ++ best_diff = diff; ++ bestTU = TU; ++ bestVTUa = VTUa; ++ bestVTUf = VTUf; ++ bestVTUi = VTUi; ++ if (diff == 0) ++ break; ++ } ++ } ++ ++ if (!bestTU) { ++ NV_ERROR(dev, "DP: unable to find suitable config\n"); ++ return; ++ } ++ ++ /* XXX close to vbios numbers, but not right */ ++ unk = (symbol - link_ratio) * bestTU; ++ unk *= link_ratio; ++ r = do_div(unk, symbol); ++ r = do_div(unk, symbol); ++ unk += 6; ++ ++ nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); ++ nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | ++ bestVTUf << 16 | ++ bestVTUi << 8 | ++ unk); ++} + static void + nv50_sor_disconnect(struct drm_encoder *encoder) + { +@@ -60,6 +247,8 @@ nv50_sor_disconnect(struct drm_encoder *encoder) + BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); + OUT_RING (evo, 0); + ++ nouveau_hdmi_mode_set(encoder, NULL); ++ + nv_encoder->crtc = NULL; + nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; + } +@@ -115,20 +304,13 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) + } + + if (nv_encoder->dcb->type == OUTPUT_DP) { +- struct nouveau_i2c_chan *auxch; +- +- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); +- if (!auxch) +- return; ++ struct dp_train_func func = { ++ .link_set = nv50_sor_dp_link_set, ++ .train_set = nv50_sor_dp_train_set, ++ .train_adj = nv50_sor_dp_train_adj ++ }; + +- if (mode == DRM_MODE_DPMS_ON) { +- u8 status = DP_SET_POWER_D0; +- nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); +- nouveau_dp_link_train(encoder, nv_encoder->dp.datarate); +- } else { +- u8 status = DP_SET_POWER_D3; +- nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); +- } ++ nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, &func); + } + } + +@@ -160,11 +342,8 @@ nv50_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, + } + + if (connector->scaling_mode != DRM_MODE_SCALE_NONE && +- connector->native_mode) { +- int id = adjusted_mode->base.id; +- *adjusted_mode = *connector->native_mode; +- adjusted_mode->base.id = id; +- } ++ connector->native_mode) ++ drm_mode_copy(adjusted_mode, connector->native_mode); + + return true; + } +@@ -172,6 +351,12 @@ nv50_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, + static void + nv50_sor_prepare(struct drm_encoder *encoder) + { ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ nv50_sor_disconnect(encoder); ++ if (nv_encoder->dcb->type == OUTPUT_DP) { ++ /* avoid race between link training and supervisor intr */ ++ nv50_display_sync(encoder->dev); ++ } + } + + static void +@@ -180,8 +365,8 @@ nv50_sor_commit(struct drm_encoder *encoder) + } + + static void +-nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) ++nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, ++ struct drm_display_mode *mode) + { + struct nouveau_channel *evo = nv50_display(encoder->dev)->master; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +@@ -193,24 +378,27 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + + NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n", + nv_encoder->or, nv_encoder->dcb->type, crtc->index); ++ nv_encoder->crtc = encoder->crtc; + + switch (nv_encoder->dcb->type) { + case OUTPUT_TMDS: + if (nv_encoder->dcb->sorconf.link & 1) { +- if (adjusted_mode->clock < 165000) ++ if (mode->clock < 165000) + mode_ctl = 0x0100; + else + mode_ctl = 0x0500; + } else + mode_ctl = 0x0200; ++ ++ nouveau_hdmi_mode_set(encoder, mode); + break; + case OUTPUT_DP: + nv_connector = nouveau_encoder_connector_get(nv_encoder); + if (nv_connector && nv_connector->base.display_info.bpc == 6) { +- nv_encoder->dp.datarate = crtc->mode->clock * 18 / 8; ++ nv_encoder->dp.datarate = mode->clock * 18 / 8; + mode_ctl |= 0x00020000; + } else { +- nv_encoder->dp.datarate = crtc->mode->clock * 24 / 8; ++ nv_encoder->dp.datarate = mode->clock * 24 / 8; + mode_ctl |= 0x00050000; + } + +@@ -228,10 +416,10 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + else + mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC0; + +- if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ++ if (mode->flags & DRM_MODE_FLAG_NHSYNC) + mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NHSYNC; + +- if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ++ if (mode->flags & DRM_MODE_FLAG_NVSYNC) + mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC; + + nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); +@@ -239,12 +427,11 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + ret = RING_SPACE(evo, 2); + if (ret) { + NV_ERROR(dev, "no space while connecting SOR\n"); ++ nv_encoder->crtc = NULL; + return; + } + BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); + OUT_RING(evo, mode_ctl); +- +- nv_encoder->crtc = encoder->crtc; + } + + static struct drm_crtc * +diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c +index 40b84f2..44fbac9 100644 +--- a/drivers/gpu/drm/nouveau/nv50_vm.c ++++ b/drivers/gpu/drm/nouveau/nv50_vm.c +@@ -48,7 +48,7 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, + phys |= 0x60; + else if (coverage <= 64 * 1024 * 1024) + phys |= 0x40; +- else if (coverage < 128 * 1024 * 1024) ++ else if (coverage <= 128 * 1024 * 1024) + phys |= 0x20; + } + +@@ -57,27 +57,15 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, + } + + static inline u64 +-nv50_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) ++vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) + { +- struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private; +- + phys |= 1; /* present */ + phys |= (u64)memtype << 40; +- +- /* IGPs don't have real VRAM, re-target to stolen system memory */ +- if (target == 0 && dev_priv->vram_sys_base) { +- phys += dev_priv->vram_sys_base; +- target = 3; +- } +- + phys |= target << 4; +- + if (vma->access & NV_MEM_ACCESS_SYS) + phys |= (1 << 6); +- + if (!(vma->access & NV_MEM_ACCESS_WO)) + phys |= (1 << 3); +- + return phys; + } + +@@ -85,11 +73,19 @@ void + nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) + { ++ struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private; + u32 comp = (mem->memtype & 0x180) >> 7; +- u32 block; ++ u32 block, target; + int i; + +- phys = nv50_vm_addr(vma, phys, mem->memtype, 0); ++ /* IGPs don't have real VRAM, re-target to stolen system memory */ ++ target = 0; ++ if (dev_priv->vram_sys_base) { ++ phys += dev_priv->vram_sys_base; ++ target = 3; ++ } ++ ++ phys = vm_addr(vma, phys, mem->memtype, target); + pte <<= 3; + cnt <<= 3; + +@@ -125,9 +121,10 @@ void + nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) + { ++ u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 3 : 2; + pte <<= 3; + while (cnt--) { +- u64 phys = nv50_vm_addr(vma, (u64)*list++, mem->memtype, 2); ++ u64 phys = vm_addr(vma, (u64)*list++, mem->memtype, target); + nv_wo32(pgt, pte + 0, lower_32_bits(phys)); + nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + pte += 8; +diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c +index 2e45e57..9ed9ae39 100644 +--- a/drivers/gpu/drm/nouveau/nv50_vram.c ++++ b/drivers/gpu/drm/nouveau/nv50_vram.c +@@ -189,8 +189,25 @@ nv50_vram_init(struct drm_device *dev) + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ ++ u32 pfb714 = nv_rd32(dev, 0x100714); + u32 rblock, length; + ++ switch (pfb714 & 0x00000007) { ++ case 0: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; ++ case 1: ++ if (nouveau_mem_vbios_type(dev) == NV_MEM_TYPE_DDR3) ++ dev_priv->vram_type = NV_MEM_TYPE_DDR3; ++ else ++ dev_priv->vram_type = NV_MEM_TYPE_DDR2; ++ break; ++ case 2: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; ++ case 3: dev_priv->vram_type = NV_MEM_TYPE_GDDR4; break; ++ case 4: dev_priv->vram_type = NV_MEM_TYPE_GDDR5; break; ++ default: ++ break; ++ } ++ ++ dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x100200) & 0x4); + dev_priv->vram_size = nv_rd32(dev, 0x10020c); + dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; + dev_priv->vram_size &= 0xffffffff00ULL; +diff --git a/drivers/gpu/drm/nouveau/nv84_bsp.c b/drivers/gpu/drm/nouveau/nv84_bsp.c +new file mode 100644 +index 0000000..7487573 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nv84_bsp.c +@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ * ++ * Authors: Ben Skeggs ++ */ ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++#include "nouveau_util.h" ++#include "nouveau_vm.h" ++#include "nouveau_ramht.h" ++ ++/*XXX: This stub is currently used on NV98+ also, as soon as this becomes ++ * more than just an enable/disable stub this needs to be split out to ++ * nv98_bsp.c... ++ */ ++ ++struct nv84_bsp_engine { ++ struct nouveau_exec_engine base; ++}; ++ ++static int ++nv84_bsp_fini(struct drm_device *dev, int engine, bool suspend) ++{ ++ if (!(nv_rd32(dev, 0x000200) & 0x00008000)) ++ return 0; ++ ++ nv_mask(dev, 0x000200, 0x00008000, 0x00000000); ++ return 0; ++} ++ ++static int ++nv84_bsp_init(struct drm_device *dev, int engine) ++{ ++ nv_mask(dev, 0x000200, 0x00008000, 0x00000000); ++ nv_mask(dev, 0x000200, 0x00008000, 0x00008000); ++ return 0; ++} ++ ++static void ++nv84_bsp_destroy(struct drm_device *dev, int engine) ++{ ++ struct nv84_bsp_engine *pbsp = nv_engine(dev, engine); ++ ++ NVOBJ_ENGINE_DEL(dev, BSP); ++ ++ kfree(pbsp); ++} ++ ++int ++nv84_bsp_create(struct drm_device *dev) ++{ ++ struct nv84_bsp_engine *pbsp; ++ ++ pbsp = kzalloc(sizeof(*pbsp), GFP_KERNEL); ++ if (!pbsp) ++ return -ENOMEM; ++ ++ pbsp->base.destroy = nv84_bsp_destroy; ++ pbsp->base.init = nv84_bsp_init; ++ pbsp->base.fini = nv84_bsp_fini; ++ ++ NVOBJ_ENGINE_ADD(dev, BSP, &pbsp->base); ++ return 0; ++} +diff --git a/drivers/gpu/drm/nouveau/nv84_vp.c b/drivers/gpu/drm/nouveau/nv84_vp.c +new file mode 100644 +index 0000000..6570d30 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nv84_vp.c +@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ * ++ * Authors: Ben Skeggs ++ */ ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++#include "nouveau_util.h" ++#include "nouveau_vm.h" ++#include "nouveau_ramht.h" ++ ++/*XXX: This stub is currently used on NV98+ also, as soon as this becomes ++ * more than just an enable/disable stub this needs to be split out to ++ * nv98_vp.c... ++ */ ++ ++struct nv84_vp_engine { ++ struct nouveau_exec_engine base; ++}; ++ ++static int ++nv84_vp_fini(struct drm_device *dev, int engine, bool suspend) ++{ ++ if (!(nv_rd32(dev, 0x000200) & 0x00020000)) ++ return 0; ++ ++ nv_mask(dev, 0x000200, 0x00020000, 0x00000000); ++ return 0; ++} ++ ++static int ++nv84_vp_init(struct drm_device *dev, int engine) ++{ ++ nv_mask(dev, 0x000200, 0x00020000, 0x00000000); ++ nv_mask(dev, 0x000200, 0x00020000, 0x00020000); ++ return 0; ++} ++ ++static void ++nv84_vp_destroy(struct drm_device *dev, int engine) ++{ ++ struct nv84_vp_engine *pvp = nv_engine(dev, engine); ++ ++ NVOBJ_ENGINE_DEL(dev, VP); ++ ++ kfree(pvp); ++} ++ ++int ++nv84_vp_create(struct drm_device *dev) ++{ ++ struct nv84_vp_engine *pvp; ++ ++ pvp = kzalloc(sizeof(*pvp), GFP_KERNEL); ++ if (!pvp) ++ return -ENOMEM; ++ ++ pvp->base.destroy = nv84_vp_destroy; ++ pvp->base.init = nv84_vp_init; ++ pvp->base.fini = nv84_vp_fini; ++ ++ NVOBJ_ENGINE_ADD(dev, VP, &pvp->base); ++ return 0; ++} +diff --git a/drivers/gpu/drm/nouveau/nv98_crypt.c b/drivers/gpu/drm/nouveau/nv98_crypt.c +new file mode 100644 +index 0000000..db94ff0 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nv98_crypt.c +@@ -0,0 +1,78 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ * ++ * Authors: Ben Skeggs ++ */ ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++#include "nouveau_util.h" ++#include "nouveau_vm.h" ++#include "nouveau_ramht.h" ++ ++struct nv98_crypt_engine { ++ struct nouveau_exec_engine base; ++}; ++ ++static int ++nv98_crypt_fini(struct drm_device *dev, int engine, bool suspend) ++{ ++ if (!(nv_rd32(dev, 0x000200) & 0x00004000)) ++ return 0; ++ ++ nv_mask(dev, 0x000200, 0x00004000, 0x00000000); ++ return 0; ++} ++ ++static int ++nv98_crypt_init(struct drm_device *dev, int engine) ++{ ++ nv_mask(dev, 0x000200, 0x00004000, 0x00000000); ++ nv_mask(dev, 0x000200, 0x00004000, 0x00004000); ++ return 0; ++} ++ ++static void ++nv98_crypt_destroy(struct drm_device *dev, int engine) ++{ ++ struct nv98_crypt_engine *pcrypt = nv_engine(dev, engine); ++ ++ NVOBJ_ENGINE_DEL(dev, CRYPT); ++ ++ kfree(pcrypt); ++} ++ ++int ++nv98_crypt_create(struct drm_device *dev) ++{ ++ struct nv98_crypt_engine *pcrypt; ++ ++ pcrypt = kzalloc(sizeof(*pcrypt), GFP_KERNEL); ++ if (!pcrypt) ++ return -ENOMEM; ++ ++ pcrypt->base.destroy = nv98_crypt_destroy; ++ pcrypt->base.init = nv98_crypt_init; ++ pcrypt->base.fini = nv98_crypt_fini; ++ ++ NVOBJ_ENGINE_ADD(dev, CRYPT, &pcrypt->base); ++ return 0; ++} +diff --git a/drivers/gpu/drm/nouveau/nv98_ppp.c b/drivers/gpu/drm/nouveau/nv98_ppp.c +new file mode 100644 +index 0000000..a987dd6 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nv98_ppp.c +@@ -0,0 +1,78 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ * ++ * Authors: Ben Skeggs ++ */ ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++#include "nouveau_util.h" ++#include "nouveau_vm.h" ++#include "nouveau_ramht.h" ++ ++struct nv98_ppp_engine { ++ struct nouveau_exec_engine base; ++}; ++ ++static int ++nv98_ppp_fini(struct drm_device *dev, int engine, bool suspend) ++{ ++ if (!(nv_rd32(dev, 0x000200) & 0x00000002)) ++ return 0; ++ ++ nv_mask(dev, 0x000200, 0x00000002, 0x00000000); ++ return 0; ++} ++ ++static int ++nv98_ppp_init(struct drm_device *dev, int engine) ++{ ++ nv_mask(dev, 0x000200, 0x00000002, 0x00000000); ++ nv_mask(dev, 0x000200, 0x00000002, 0x00000002); ++ return 0; ++} ++ ++static void ++nv98_ppp_destroy(struct drm_device *dev, int engine) ++{ ++ struct nv98_ppp_engine *pppp = nv_engine(dev, engine); ++ ++ NVOBJ_ENGINE_DEL(dev, PPP); ++ ++ kfree(pppp); ++} ++ ++int ++nv98_ppp_create(struct drm_device *dev) ++{ ++ struct nv98_ppp_engine *pppp; ++ ++ pppp = kzalloc(sizeof(*pppp), GFP_KERNEL); ++ if (!pppp) ++ return -ENOMEM; ++ ++ pppp->base.destroy = nv98_ppp_destroy; ++ pppp->base.init = nv98_ppp_init; ++ pppp->base.fini = nv98_ppp_fini; ++ ++ NVOBJ_ENGINE_ADD(dev, PPP, &pppp->base); ++ return 0; ++} +diff --git a/drivers/gpu/drm/nouveau/nva3_copy.fuc b/drivers/gpu/drm/nouveau/nva3_copy.fuc +index d894731..219850d 100644 +--- a/drivers/gpu/drm/nouveau/nva3_copy.fuc ++++ b/drivers/gpu/drm/nouveau/nva3_copy.fuc +@@ -31,8 +31,9 @@ + */ + + ifdef(`NVA3', +-.section nva3_pcopy_data, +-.section nvc0_pcopy_data ++.section #nva3_pcopy_data ++, ++.section #nvc0_pcopy_data + ) + + ctx_object: .b32 0 +@@ -42,7 +43,7 @@ ctx_dma_query: .b32 0 + ctx_dma_src: .b32 0 + ctx_dma_dst: .b32 0 + ,) +-.equ ctx_dma_count 3 ++.equ #ctx_dma_count 3 + ctx_query_address_high: .b32 0 + ctx_query_address_low: .b32 0 + ctx_query_counter: .b32 0 +@@ -78,64 +79,65 @@ ctx_ycnt: .b32 0 + dispatch_table: + // mthd 0x0000, NAME + .b16 0x000 1 +-.b32 ctx_object ~0xffffffff ++.b32 #ctx_object ~0xffffffff + // mthd 0x0100, NOP + .b16 0x040 1 +-.b32 0x00010000 + cmd_nop ~0xffffffff ++.b32 0x00010000 + #cmd_nop ~0xffffffff + // mthd 0x0140, PM_TRIGGER + .b16 0x050 1 +-.b32 0x00010000 + cmd_pm_trigger ~0xffffffff ++.b32 0x00010000 + #cmd_pm_trigger ~0xffffffff + ifdef(`NVA3', ` + // mthd 0x0180-0x018c, DMA_ +-.b16 0x060 ctx_dma_count ++.b16 0x060 #ctx_dma_count + dispatch_dma: +-.b32 0x00010000 + cmd_dma ~0xffffffff +-.b32 0x00010000 + cmd_dma ~0xffffffff +-.b32 0x00010000 + cmd_dma ~0xffffffff ++.b32 0x00010000 + #cmd_dma ~0xffffffff ++.b32 0x00010000 + #cmd_dma ~0xffffffff ++.b32 0x00010000 + #cmd_dma ~0xffffffff + ',) + // mthd 0x0200-0x0218, SRC_TILE + .b16 0x80 7 +-.b32 ctx_src_tile_mode ~0x00000fff +-.b32 ctx_src_xsize ~0x0007ffff +-.b32 ctx_src_ysize ~0x00001fff +-.b32 ctx_src_zsize ~0x000007ff +-.b32 ctx_src_zoff ~0x00000fff +-.b32 ctx_src_xoff ~0x0007ffff +-.b32 ctx_src_yoff ~0x00001fff ++.b32 #ctx_src_tile_mode ~0x00000fff ++.b32 #ctx_src_xsize ~0x0007ffff ++.b32 #ctx_src_ysize ~0x00001fff ++.b32 #ctx_src_zsize ~0x000007ff ++.b32 #ctx_src_zoff ~0x00000fff ++.b32 #ctx_src_xoff ~0x0007ffff ++.b32 #ctx_src_yoff ~0x00001fff + // mthd 0x0220-0x0238, DST_TILE + .b16 0x88 7 +-.b32 ctx_dst_tile_mode ~0x00000fff +-.b32 ctx_dst_xsize ~0x0007ffff +-.b32 ctx_dst_ysize ~0x00001fff +-.b32 ctx_dst_zsize ~0x000007ff +-.b32 ctx_dst_zoff ~0x00000fff +-.b32 ctx_dst_xoff ~0x0007ffff +-.b32 ctx_dst_yoff ~0x00001fff ++.b32 #ctx_dst_tile_mode ~0x00000fff ++.b32 #ctx_dst_xsize ~0x0007ffff ++.b32 #ctx_dst_ysize ~0x00001fff ++.b32 #ctx_dst_zsize ~0x000007ff ++.b32 #ctx_dst_zoff ~0x00000fff ++.b32 #ctx_dst_xoff ~0x0007ffff ++.b32 #ctx_dst_yoff ~0x00001fff + // mthd 0x0300-0x0304, EXEC, WRCACHE_FLUSH + .b16 0xc0 2 +-.b32 0x00010000 + cmd_exec ~0xffffffff +-.b32 0x00010000 + cmd_wrcache_flush ~0xffffffff ++.b32 0x00010000 + #cmd_exec ~0xffffffff ++.b32 0x00010000 + #cmd_wrcache_flush ~0xffffffff + // mthd 0x030c-0x0340, various stuff + .b16 0xc3 14 +-.b32 ctx_src_address_high ~0x000000ff +-.b32 ctx_src_address_low ~0xffffffff +-.b32 ctx_dst_address_high ~0x000000ff +-.b32 ctx_dst_address_low ~0xffffffff +-.b32 ctx_src_pitch ~0x0007ffff +-.b32 ctx_dst_pitch ~0x0007ffff +-.b32 ctx_xcnt ~0x0000ffff +-.b32 ctx_ycnt ~0x00001fff +-.b32 ctx_format ~0x0333ffff +-.b32 ctx_swz_const0 ~0xffffffff +-.b32 ctx_swz_const1 ~0xffffffff +-.b32 ctx_query_address_high ~0x000000ff +-.b32 ctx_query_address_low ~0xffffffff +-.b32 ctx_query_counter ~0xffffffff ++.b32 #ctx_src_address_high ~0x000000ff ++.b32 #ctx_src_address_low ~0xffffffff ++.b32 #ctx_dst_address_high ~0x000000ff ++.b32 #ctx_dst_address_low ~0xffffffff ++.b32 #ctx_src_pitch ~0x0007ffff ++.b32 #ctx_dst_pitch ~0x0007ffff ++.b32 #ctx_xcnt ~0x0000ffff ++.b32 #ctx_ycnt ~0x00001fff ++.b32 #ctx_format ~0x0333ffff ++.b32 #ctx_swz_const0 ~0xffffffff ++.b32 #ctx_swz_const1 ~0xffffffff ++.b32 #ctx_query_address_high ~0x000000ff ++.b32 #ctx_query_address_low ~0xffffffff ++.b32 #ctx_query_counter ~0xffffffff + .b16 0x800 0 + + ifdef(`NVA3', +-.section nva3_pcopy_code, +-.section nvc0_pcopy_code ++.section #nva3_pcopy_code ++, ++.section #nvc0_pcopy_code + ) + + main: +@@ -143,12 +145,12 @@ main: + mov $sp $r0 + + // setup i0 handler and route fifo and ctxswitch to it +- mov $r1 ih ++ mov $r1 #ih + mov $iv0 $r1 + mov $r1 0x400 + movw $r2 0xfff3 + sethi $r2 0 +- iowr I[$r2 + 0x300] $r2 ++ iowr I[$r1 + 0x300] $r2 + + // enable interrupts + or $r2 0xc +@@ -164,19 +166,19 @@ main: + bset $flags $p0 + spin: + sleep $p0 +- bra spin ++ bra #spin + + // i0 handler + ih: + iord $r1 I[$r0 + 0x200] + + and $r2 $r1 0x00000008 +- bra e ih_no_chsw +- call chsw ++ bra e #ih_no_chsw ++ call #chsw + ih_no_chsw: + and $r2 $r1 0x00000004 +- bra e ih_no_cmd +- call dispatch ++ bra e #ih_no_cmd ++ call #dispatch + + ih_no_cmd: + and $r1 $r1 0x0000000c +@@ -235,9 +237,9 @@ ifdef(`NVA3', ` + sethi $r4 0x60000 + + // swap! +- bra $p1 swctx_load ++ bra $p1 #swctx_load + xdst $r0 $r4 +- bra swctx_done ++ bra #swctx_done + swctx_load: + xdld $r0 $r4 + swctx_done: +@@ -251,9 +253,9 @@ chsw: + + // if it's active, unload it and return + xbit $r15 $r3 0x1e +- bra e chsw_no_unload ++ bra e #chsw_no_unload + bclr $flags $p1 +- call swctx ++ call #swctx + bclr $r3 0x1e + iowr I[$r2] $r3 + mov $r4 1 +@@ -266,20 +268,20 @@ chsw: + + // is there a channel waiting to be loaded? + xbit $r13 $r3 0x1e +- bra e chsw_finish_load ++ bra e #chsw_finish_load + bset $flags $p1 +- call swctx ++ call #swctx + ifdef(`NVA3', + // load dma objects back into TARGET regs +- mov $r5 ctx_dma +- mov $r6 ctx_dma_count ++ mov $r5 #ctx_dma ++ mov $r6 #ctx_dma_count + chsw_load_ctx_dma: + ld b32 $r7 D[$r5 + $r6 * 4] + add b32 $r8 $r6 0x180 + shl b32 $r8 8 + iowr I[$r8] $r7 + sub b32 $r6 1 +- bra nc chsw_load_ctx_dma ++ bra nc #chsw_load_ctx_dma + ,) + + chsw_finish_load: +@@ -297,7 +299,7 @@ dispatch: + shl b32 $r2 0x10 + + // lookup method in the dispatch table, ILLEGAL_MTHD if not found +- mov $r5 dispatch_table ++ mov $r5 #dispatch_table + clear b32 $r6 + clear b32 $r7 + dispatch_loop: +@@ -305,14 +307,14 @@ dispatch: + ld b16 $r7 D[$r5 + 2] + add b32 $r5 4 + cmpu b32 $r4 $r6 +- bra c dispatch_illegal_mthd ++ bra c #dispatch_illegal_mthd + add b32 $r7 $r6 + cmpu b32 $r4 $r7 +- bra c dispatch_valid_mthd ++ bra c #dispatch_valid_mthd + sub b32 $r7 $r6 + shl b32 $r7 3 + add b32 $r5 $r7 +- bra dispatch_loop ++ bra #dispatch_loop + + // ensure no bits set in reserved fields, INVALID_BITFIELD + dispatch_valid_mthd: +@@ -322,20 +324,20 @@ dispatch: + ld b32 $r5 D[$r4 + 4] + and $r5 $r3 + cmpu b32 $r5 0 +- bra ne dispatch_invalid_bitfield ++ bra ne #dispatch_invalid_bitfield + + // depending on dispatch flags: execute method, or save data as state + ld b16 $r5 D[$r4 + 0] + ld b16 $r6 D[$r4 + 2] + cmpu b32 $r6 0 +- bra ne dispatch_cmd ++ bra ne #dispatch_cmd + st b32 D[$r5] $r3 +- bra dispatch_done ++ bra #dispatch_done + dispatch_cmd: + bclr $flags $p1 + call $r5 +- bra $p1 dispatch_error +- bra dispatch_done ++ bra $p1 #dispatch_error ++ bra #dispatch_done + + dispatch_invalid_bitfield: + or $r2 2 +@@ -353,7 +355,7 @@ dispatch: + iord $r2 I[$r0 + 0x200] + and $r2 0x40 + cmpu b32 $r2 0 +- bra ne hostirq_wait ++ bra ne #hostirq_wait + + dispatch_done: + mov $r2 0x1d00 +@@ -409,10 +411,10 @@ ifdef(`NVA3', + // $r2: hostirq state + // $r3: data + cmd_dma: +- sub b32 $r4 dispatch_dma ++ sub b32 $r4 #dispatch_dma + shr b32 $r4 1 + bset $r3 0x1e +- st b32 D[$r4 + ctx_dma] $r3 ++ st b32 D[$r4 + #ctx_dma] $r3 + add b32 $r4 0x600 + shl b32 $r4 6 + iowr I[$r4] $r3 +@@ -430,7 +432,7 @@ cmd_exec_set_format: + st b32 D[$sp + 0x0c] $r0 + + // extract cpp, src_ncomp and dst_ncomp from FORMAT +- ld b32 $r4 D[$r0 + ctx_format] ++ ld b32 $r4 D[$r0 + #ctx_format] + extr $r5 $r4 16:17 + add b32 $r5 1 + extr $r6 $r4 20:21 +@@ -448,22 +450,22 @@ cmd_exec_set_format: + clear b32 $r11 + bpc_loop: + cmpu b8 $r10 4 +- bra nc cmp_c0 ++ bra nc #cmp_c0 + mulu $r12 $r10 $r5 + add b32 $r12 $r11 + bset $flags $p2 +- bra bpc_next ++ bra #bpc_next + cmp_c0: +- bra ne cmp_c1 ++ bra ne #cmp_c1 + mov $r12 0x10 + add b32 $r12 $r11 +- bra bpc_next ++ bra #bpc_next + cmp_c1: + cmpu b8 $r10 6 +- bra nc cmp_zero ++ bra nc #cmp_zero + mov $r12 0x14 + add b32 $r12 $r11 +- bra bpc_next ++ bra #bpc_next + cmp_zero: + mov $r12 0x80 + bpc_next: +@@ -471,22 +473,22 @@ cmd_exec_set_format: + add b32 $r8 1 + add b32 $r11 1 + cmpu b32 $r11 $r5 +- bra c bpc_loop ++ bra c #bpc_loop + add b32 $r9 1 + cmpu b32 $r9 $r7 +- bra c ncomp_loop ++ bra c #ncomp_loop + + // SRC_XCNT = (xcnt * src_cpp), or 0 if no src ref in swz (hw will hang) + mulu $r6 $r5 +- st b32 D[$r0 + ctx_src_cpp] $r6 +- ld b32 $r8 D[$r0 + ctx_xcnt] ++ st b32 D[$r0 + #ctx_src_cpp] $r6 ++ ld b32 $r8 D[$r0 + #ctx_xcnt] + mulu $r6 $r8 +- bra $p2 dst_xcnt ++ bra $p2 #dst_xcnt + clear b32 $r6 + + dst_xcnt: + mulu $r7 $r5 +- st b32 D[$r0 + ctx_dst_cpp] $r7 ++ st b32 D[$r0 + #ctx_dst_cpp] $r7 + mulu $r7 $r8 + + mov $r5 0x810 +@@ -494,10 +496,10 @@ cmd_exec_set_format: + iowr I[$r5 + 0x000] $r6 + iowr I[$r5 + 0x100] $r7 + add b32 $r5 0x800 +- ld b32 $r6 D[$r0 + ctx_dst_cpp] ++ ld b32 $r6 D[$r0 + #ctx_dst_cpp] + sub b32 $r6 1 + shl b32 $r6 8 +- ld b32 $r7 D[$r0 + ctx_src_cpp] ++ ld b32 $r7 D[$r0 + #ctx_src_cpp] + sub b32 $r7 1 + or $r6 $r7 + iowr I[$r5 + 0x000] $r6 +@@ -511,9 +513,9 @@ cmd_exec_set_format: + ld b32 $r6 D[$sp + 0x0c] + iowr I[$r5 + 0x300] $r6 + add b32 $r5 0x400 +- ld b32 $r6 D[$r0 + ctx_swz_const0] ++ ld b32 $r6 D[$r0 + #ctx_swz_const0] + iowr I[$r5 + 0x000] $r6 +- ld b32 $r6 D[$r0 + ctx_swz_const1] ++ ld b32 $r6 D[$r0 + #ctx_swz_const1] + iowr I[$r5 + 0x100] $r6 + add $sp 0x10 + ret +@@ -543,7 +545,7 @@ cmd_exec_set_format: + // + cmd_exec_set_surface_tiled: + // translate TILE_MODE into Tp, Th, Td shift values +- ld b32 $r7 D[$r5 + ctx_src_tile_mode] ++ ld b32 $r7 D[$r5 + #ctx_src_tile_mode] + extr $r9 $r7 8:11 + extr $r8 $r7 4:7 + ifdef(`NVA3', +@@ -553,9 +555,9 @@ ifdef(`NVA3', + ) + extr $r7 $r7 0:3 + cmp b32 $r7 0xe +- bra ne xtile64 ++ bra ne #xtile64 + mov $r7 4 +- bra xtileok ++ bra #xtileok + xtile64: + xbit $r7 $flags $p2 + add b32 $r7 17 +@@ -565,8 +567,8 @@ ifdef(`NVA3', + + // Op = (x * cpp) & ((1 << Tp) - 1) + // Tx = (x * cpp) >> Tp +- ld b32 $r10 D[$r5 + ctx_src_xoff] +- ld b32 $r11 D[$r5 + ctx_src_cpp] ++ ld b32 $r10 D[$r5 + #ctx_src_xoff] ++ ld b32 $r11 D[$r5 + #ctx_src_cpp] + mulu $r10 $r11 + mov $r11 1 + shl b32 $r11 $r7 +@@ -576,7 +578,7 @@ ifdef(`NVA3', + + // Tyo = y & ((1 << Th) - 1) + // Ty = y >> Th +- ld b32 $r13 D[$r5 + ctx_src_yoff] ++ ld b32 $r13 D[$r5 + #ctx_src_yoff] + mov $r14 1 + shl b32 $r14 $r8 + sub b32 $r14 1 +@@ -598,8 +600,8 @@ ifdef(`NVA3', + add b32 $r12 $r11 + + // nTx = ((w * cpp) + ((1 << Tp) - 1) >> Tp) +- ld b32 $r15 D[$r5 + ctx_src_xsize] +- ld b32 $r11 D[$r5 + ctx_src_cpp] ++ ld b32 $r15 D[$r5 + #ctx_src_xsize] ++ ld b32 $r11 D[$r5 + #ctx_src_cpp] + mulu $r15 $r11 + mov $r11 1 + shl b32 $r11 $r7 +@@ -609,7 +611,7 @@ ifdef(`NVA3', + push $r15 + + // nTy = (h + ((1 << Th) - 1)) >> Th +- ld b32 $r15 D[$r5 + ctx_src_ysize] ++ ld b32 $r15 D[$r5 + #ctx_src_ysize] + mov $r11 1 + shl b32 $r11 $r8 + sub b32 $r11 1 +@@ -629,7 +631,7 @@ ifdef(`NVA3', + // Tz = z >> Td + // Op += Tzo << Tys + // Ts = Tys + Td +- ld b32 $r8 D[$r5 + ctx_src_zoff] ++ ld b32 $r8 D[$r5 + #ctx_src_zoff] + mov $r14 1 + shl b32 $r14 $r9 + sub b32 $r14 1 +@@ -656,8 +658,8 @@ ifdef(`NVA3', + + // SRC_ADDRESS_LOW = (Ot + Op) & 0xffffffff + // CFG_ADDRESS_HIGH |= ((Ot + Op) >> 32) << 16 +- ld b32 $r7 D[$r5 + ctx_src_address_low] +- ld b32 $r8 D[$r5 + ctx_src_address_high] ++ ld b32 $r7 D[$r5 + #ctx_src_address_low] ++ ld b32 $r8 D[$r5 + #ctx_src_address_high] + add b32 $r10 $r12 + add b32 $r7 $r10 + adc b32 $r8 0 +@@ -677,14 +679,14 @@ cmd_exec_set_surface_linear: + xbit $r6 $flags $p2 + add b32 $r6 0x202 + shl b32 $r6 8 +- ld b32 $r7 D[$r5 + ctx_src_address_low] ++ ld b32 $r7 D[$r5 + #ctx_src_address_low] + iowr I[$r6 + 0x000] $r7 + add b32 $r6 0x400 +- ld b32 $r7 D[$r5 + ctx_src_address_high] ++ ld b32 $r7 D[$r5 + #ctx_src_address_high] + shl b32 $r7 16 + iowr I[$r6 + 0x000] $r7 + add b32 $r6 0x400 +- ld b32 $r7 D[$r5 + ctx_src_pitch] ++ ld b32 $r7 D[$r5 + #ctx_src_pitch] + iowr I[$r6 + 0x000] $r7 + ret + +@@ -697,7 +699,7 @@ cmd_exec_wait: + loop: + iord $r1 I[$r0] + and $r1 1 +- bra ne loop ++ bra ne #loop + pop $r1 + pop $r0 + ret +@@ -705,18 +707,18 @@ cmd_exec_wait: + cmd_exec_query: + // if QUERY_SHORT not set, write out { -, 0, TIME_LO, TIME_HI } + xbit $r4 $r3 13 +- bra ne query_counter +- call cmd_exec_wait ++ bra ne #query_counter ++ call #cmd_exec_wait + mov $r4 0x80c + shl b32 $r4 6 +- ld b32 $r5 D[$r0 + ctx_query_address_low] ++ ld b32 $r5 D[$r0 + #ctx_query_address_low] + add b32 $r5 4 + iowr I[$r4 + 0x000] $r5 + iowr I[$r4 + 0x100] $r0 + mov $r5 0xc + iowr I[$r4 + 0x200] $r5 + add b32 $r4 0x400 +- ld b32 $r5 D[$r0 + ctx_query_address_high] ++ ld b32 $r5 D[$r0 + #ctx_query_address_high] + shl b32 $r5 16 + iowr I[$r4 + 0x000] $r5 + add b32 $r4 0x500 +@@ -741,16 +743,16 @@ cmd_exec_query: + + // write COUNTER + query_counter: +- call cmd_exec_wait ++ call #cmd_exec_wait + mov $r4 0x80c + shl b32 $r4 6 +- ld b32 $r5 D[$r0 + ctx_query_address_low] ++ ld b32 $r5 D[$r0 + #ctx_query_address_low] + iowr I[$r4 + 0x000] $r5 + iowr I[$r4 + 0x100] $r0 + mov $r5 0x4 + iowr I[$r4 + 0x200] $r5 + add b32 $r4 0x400 +- ld b32 $r5 D[$r0 + ctx_query_address_high] ++ ld b32 $r5 D[$r0 + #ctx_query_address_high] + shl b32 $r5 16 + iowr I[$r4 + 0x000] $r5 + add b32 $r4 0x500 +@@ -759,7 +761,7 @@ cmd_exec_query: + mov $r5 0x00001110 + sethi $r5 0x13120000 + iowr I[$r4 + 0x100] $r5 +- ld b32 $r5 D[$r0 + ctx_query_counter] ++ ld b32 $r5 D[$r0 + #ctx_query_counter] + add b32 $r4 0x500 + iowr I[$r4 + 0x000] $r5 + mov $r5 0x00002601 +@@ -787,22 +789,22 @@ cmd_exec_query: + // $r2: hostirq state + // $r3: data + cmd_exec: +- call cmd_exec_wait ++ call #cmd_exec_wait + + // if format requested, call function to calculate it, otherwise + // fill in cpp/xcnt for both surfaces as if (cpp == 1) + xbit $r15 $r3 0 +- bra e cmd_exec_no_format +- call cmd_exec_set_format ++ bra e #cmd_exec_no_format ++ call #cmd_exec_set_format + mov $r4 0x200 +- bra cmd_exec_init_src_surface ++ bra #cmd_exec_init_src_surface + cmd_exec_no_format: + mov $r6 0x810 + shl b32 $r6 6 + mov $r7 1 +- st b32 D[$r0 + ctx_src_cpp] $r7 +- st b32 D[$r0 + ctx_dst_cpp] $r7 +- ld b32 $r7 D[$r0 + ctx_xcnt] ++ st b32 D[$r0 + #ctx_src_cpp] $r7 ++ st b32 D[$r0 + #ctx_dst_cpp] $r7 ++ ld b32 $r7 D[$r0 + #ctx_xcnt] + iowr I[$r6 + 0x000] $r7 + iowr I[$r6 + 0x100] $r7 + clear b32 $r4 +@@ -811,28 +813,28 @@ cmd_exec: + bclr $flags $p2 + clear b32 $r5 + xbit $r15 $r3 4 +- bra e src_tiled +- call cmd_exec_set_surface_linear +- bra cmd_exec_init_dst_surface ++ bra e #src_tiled ++ call #cmd_exec_set_surface_linear ++ bra #cmd_exec_init_dst_surface + src_tiled: +- call cmd_exec_set_surface_tiled ++ call #cmd_exec_set_surface_tiled + bset $r4 7 + + cmd_exec_init_dst_surface: + bset $flags $p2 +- mov $r5 ctx_dst_address_high - ctx_src_address_high ++ mov $r5 #ctx_dst_address_high - #ctx_src_address_high + xbit $r15 $r3 8 +- bra e dst_tiled +- call cmd_exec_set_surface_linear +- bra cmd_exec_kick ++ bra e #dst_tiled ++ call #cmd_exec_set_surface_linear ++ bra #cmd_exec_kick + dst_tiled: +- call cmd_exec_set_surface_tiled ++ call #cmd_exec_set_surface_tiled + bset $r4 8 + + cmd_exec_kick: + mov $r5 0x800 + shl b32 $r5 6 +- ld b32 $r6 D[$r0 + ctx_ycnt] ++ ld b32 $r6 D[$r0 + #ctx_ycnt] + iowr I[$r5 + 0x100] $r6 + mov $r6 0x0041 + // SRC_TARGET = 1, DST_TARGET = 2 +@@ -842,8 +844,8 @@ cmd_exec: + + // if requested, queue up a QUERY write after the copy has completed + xbit $r15 $r3 12 +- bra e cmd_exec_done +- call cmd_exec_query ++ bra e #cmd_exec_done ++ call #cmd_exec_query + + cmd_exec_done: + ret +diff --git a/drivers/gpu/drm/nouveau/nva3_copy.fuc.h b/drivers/gpu/drm/nouveau/nva3_copy.fuc.h +index e2a0e88..37d6de3 100644 +--- a/drivers/gpu/drm/nouveau/nva3_copy.fuc.h ++++ b/drivers/gpu/drm/nouveau/nva3_copy.fuc.h +@@ -190,7 +190,7 @@ u32 nva3_pcopy_code[] = { + 0xf10010fe, + 0xf1040017, + 0xf0fff327, +- 0x22d00023, ++ 0x12d00023, + 0x0c25f0c0, + 0xf40012d0, + 0x17f11031, +diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c +index 618c144..9e636e6 100644 +--- a/drivers/gpu/drm/nouveau/nva3_pm.c ++++ b/drivers/gpu/drm/nouveau/nva3_pm.c +@@ -287,12 +287,13 @@ nva3_pm_grcp_idle(void *data) + return false; + } + +-void ++int + nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nva3_pm_state *info = pre_state; + unsigned long flags; ++ int ret = -EAGAIN; + + /* prevent any new grctx switches from starting */ + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); +@@ -328,6 +329,8 @@ nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) + nv_wr32(dev, 0x100210, 0x80000000); + } + ++ ret = 0; ++ + cleanup: + /* unfreeze PFIFO */ + nv_mask(dev, 0x002504, 0x00000001, 0x00000000); +@@ -339,4 +342,5 @@ cleanup: + nv_mask(dev, 0x400824, 0x10000000, 0x10000000); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + kfree(info); ++ return ret; + } +diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h b/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h +index 9e87036..cd879f3 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h ++++ b/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h +@@ -178,7 +178,7 @@ u32 nvc0_pcopy_code[] = { + 0xf10010fe, + 0xf1040017, + 0xf0fff327, +- 0x22d00023, ++ 0x12d00023, + 0x0c25f0c0, + 0xf40012d0, + 0x17f11031, +diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c +index 5bf5503..f704e94 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_fb.c ++++ b/drivers/gpu/drm/nouveau/nvc0_fb.c +@@ -54,6 +54,11 @@ nvc0_mfb_isr(struct drm_device *dev) + nvc0_mfb_subp_isr(dev, unit, subp); + units &= ~(1 << unit); + } ++ ++ /* we do something horribly wrong and upset PMFB a lot, so mask off ++ * interrupts from it after the first one until it's fixed ++ */ ++ nv_mask(dev, 0x000640, 0x02000000, 0x00000000); + } + + static void +diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c +index dcbe0d5..50d68a7 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_fifo.c ++++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c +@@ -436,6 +436,24 @@ nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit) + printk(" on channel 0x%010llx\n", (u64)inst << 12); + } + ++static int ++nvc0_fifo_page_flip(struct drm_device *dev, u32 chid) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_channel *chan = NULL; ++ unsigned long flags; ++ int ret = -EINVAL; ++ ++ spin_lock_irqsave(&dev_priv->channels.lock, flags); ++ if (likely(chid >= 0 && chid < dev_priv->engine.fifo.channels)) { ++ chan = dev_priv->channels.ptr[chid]; ++ if (likely(chan)) ++ ret = nouveau_finish_page_flip(chan, NULL); ++ } ++ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); ++ return ret; ++} ++ + static void + nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) + { +@@ -445,11 +463,21 @@ nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) + u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f; + u32 subc = (addr & 0x00070000); + u32 mthd = (addr & 0x00003ffc); ++ u32 show = stat; + +- NV_INFO(dev, "PSUBFIFO %d:", unit); +- nouveau_bitfield_print(nvc0_fifo_subfifo_intr, stat); +- NV_INFO(dev, "PSUBFIFO %d: ch %d subc %d mthd 0x%04x data 0x%08x\n", +- unit, chid, subc, mthd, data); ++ if (stat & 0x00200000) { ++ if (mthd == 0x0054) { ++ if (!nvc0_fifo_page_flip(dev, chid)) ++ show &= ~0x00200000; ++ } ++ } ++ ++ if (show) { ++ NV_INFO(dev, "PFIFO%d:", unit); ++ nouveau_bitfield_print(nvc0_fifo_subfifo_intr, show); ++ NV_INFO(dev, "PFIFO%d: ch %d subc %d mthd 0x%04x data 0x%08x\n", ++ unit, chid, subc, mthd, data); ++ } + + nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008); + nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); +diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c +index ecfafd7..2e5dd66 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_graph.c ++++ b/drivers/gpu/drm/nouveau/nvc0_graph.c +@@ -333,14 +333,6 @@ nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend) + return 0; + } + +-static int +-nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, +- u32 class, u32 mthd, u32 data) +-{ +- nouveau_finish_page_flip(chan, NULL); +- return 0; +-} +- + static void + nvc0_graph_init_obj418880(struct drm_device *dev) + { +@@ -740,10 +732,8 @@ nvc0_graph_create_fw(struct drm_device *dev, const char *fwname, + if (ret) { + snprintf(f, sizeof(f), "nouveau/%s", fwname); + ret = request_firmware(&fw, f, &dev->pdev->dev); +- if (ret) { +- NV_ERROR(dev, "failed to load %s\n", fwname); ++ if (ret) + return ret; +- } + } + + fuc->size = fw->size; +@@ -875,19 +865,20 @@ nvc0_graph_create(struct drm_device *dev) + case 0xcf: /* 4/0/0/0, 3 */ + priv->magic_not_rop_nr = 0x03; + break; ++ case 0xd9: /* 1/0/0/0, 1 */ ++ priv->magic_not_rop_nr = 0x01; ++ break; + } + + if (!priv->magic_not_rop_nr) { + NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", + priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2], + priv->tp_nr[3], priv->rop_nr); +- /* use 0xc3's values... */ +- priv->magic_not_rop_nr = 0x03; ++ priv->magic_not_rop_nr = 0x00; + } + + NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ + NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ +- NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip); + NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ + if (fermi >= 0x9197) + NVOBJ_CLASS(dev, 0x9197, GR); /* 3D (NVC1-) */ +diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.fuc b/drivers/gpu/drm/nouveau/nvc0_graph.fuc +index 2a4b6dc..e6b2288 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_graph.fuc ++++ b/drivers/gpu/drm/nouveau/nvc0_graph.fuc +@@ -71,9 +71,9 @@ queue_put: + ld b32 $r9 D[$r13 + 0x4] // PUT + xor $r8 8 + cmpu b32 $r8 $r9 +- bra ne queue_put_next ++ bra ne #queue_put_next + mov $r15 E_CMD_OVERFLOW +- call error ++ call #error + ret + + // store cmd/data on queue +@@ -104,7 +104,7 @@ queue_get: + ld b32 $r8 D[$r13 + 0x0] // GET + ld b32 $r9 D[$r13 + 0x4] // PUT + cmpu b32 $r8 $r9 +- bra e queue_get_done ++ bra e #queue_get_done + // fetch first cmd/data pair + and $r9 $r8 7 + shl b32 $r9 3 +@@ -135,9 +135,9 @@ nv_rd32: + nv_rd32_wait: + iord $r12 I[$r11 + 0x000] + xbit $r12 $r12 31 +- bra ne nv_rd32_wait ++ bra ne #nv_rd32_wait + mov $r10 6 // DONE_MMIO_RD +- call wait_doneo ++ call #wait_doneo + iord $r15 I[$r11 + 0x100] // MMIO_RDVAL + ret + +@@ -157,7 +157,7 @@ nv_wr32: + nv_wr32_wait: + iord $r12 I[$r11 + 0x000] + xbit $r12 $r12 31 +- bra ne nv_wr32_wait ++ bra ne #nv_wr32_wait + ret + + // (re)set watchdog timer +@@ -193,7 +193,7 @@ $1: + shl b32 $r8 6 + iord $r8 I[$r8 + 0x000] // DONE + xbit $r8 $r8 $r10 +- bra $2 wait_done_$1 ++ bra $2 #wait_done_$1 + trace_clr(T_WAIT) + ret + ') +@@ -216,7 +216,7 @@ mmctx_size: + add b32 $r9 $r8 + add b32 $r14 4 + cmpu b32 $r14 $r15 +- bra ne nv_mmctx_size_loop ++ bra ne #nv_mmctx_size_loop + mov b32 $r15 $r9 + ret + +@@ -238,12 +238,12 @@ mmctx_xfer: + shl b32 $r8 6 + clear b32 $r9 + or $r11 $r11 +- bra e mmctx_base_disabled ++ bra e #mmctx_base_disabled + iowr I[$r8 + 0x000] $r11 // MMCTX_BASE + bset $r9 0 // BASE_EN + mmctx_base_disabled: + or $r14 $r14 +- bra e mmctx_multi_disabled ++ bra e #mmctx_multi_disabled + iowr I[$r8 + 0x200] $r14 // MMCTX_MULTI_STRIDE + iowr I[$r8 + 0x300] $r15 // MMCTX_MULTI_MASK + bset $r9 1 // MULTI_EN +@@ -264,7 +264,7 @@ mmctx_xfer: + mmctx_wait_free: + iord $r14 I[$r8 + 0x000] // MMCTX_CTRL + and $r14 0x1f +- bra e mmctx_wait_free ++ bra e #mmctx_wait_free + + // queue up an entry + ld b32 $r14 D[$r12] +@@ -272,19 +272,19 @@ mmctx_xfer: + iowr I[$r8 + 0x300] $r14 + add b32 $r12 4 + cmpu b32 $r12 $r13 +- bra ne mmctx_exec_loop ++ bra ne #mmctx_exec_loop + + xbit $r11 $r10 2 +- bra ne mmctx_stop ++ bra ne #mmctx_stop + // wait for queue to empty + mmctx_fini_wait: + iord $r11 I[$r8 + 0x000] // MMCTX_CTRL + and $r11 0x1f + cmpu b32 $r11 0x10 +- bra ne mmctx_fini_wait ++ bra ne #mmctx_fini_wait + mov $r10 2 // DONE_MMCTX +- call wait_donez +- bra mmctx_done ++ call #wait_donez ++ bra #mmctx_done + mmctx_stop: + xbit $r11 $r10 0 + shl b32 $r11 16 // DIR +@@ -295,7 +295,7 @@ mmctx_xfer: + // wait for STOP_TRIGGER to clear + iord $r11 I[$r8 + 0x000] // MMCTX_CTRL + xbit $r11 $r11 18 +- bra ne mmctx_stop_wait ++ bra ne #mmctx_stop_wait + mmctx_done: + trace_clr(T_MMCTX) + ret +@@ -305,7 +305,7 @@ mmctx_xfer: + strand_wait: + push $r10 + mov $r10 2 +- call wait_donez ++ call #wait_donez + pop $r10 + ret + +@@ -316,7 +316,7 @@ strand_pre: + sethi $r8 0x20000 + mov $r9 0xc + iowr I[$r8] $r9 +- call strand_wait ++ call #strand_wait + ret + + // unknown - call after issuing strand commands +@@ -326,7 +326,7 @@ strand_post: + sethi $r8 0x20000 + mov $r9 0xd + iowr I[$r8] $r9 +- call strand_wait ++ call #strand_wait + ret + + // Selects strand set?! +@@ -341,11 +341,11 @@ strand_set: + iowr I[$r10 + 0x000] $r12 // 0x93c = 0xf + mov $r12 0xb + iowr I[$r11 + 0x000] $r12 // 0x928 = 0xb +- call strand_wait ++ call #strand_wait + iowr I[$r10 + 0x000] $r14 // 0x93c = + mov $r12 0xa + iowr I[$r11 + 0x000] $r12 // 0x928 = 0xa +- call strand_wait ++ call #strand_wait + ret + + // Initialise strand context data +@@ -357,22 +357,22 @@ strand_set: + // + strand_ctx_init: + trace_set(T_STRINIT) +- call strand_pre ++ call #strand_pre + mov $r14 3 +- call strand_set ++ call #strand_set + mov $r10 0x46fc + sethi $r10 0x20000 + add b32 $r11 $r10 0x400 + iowr I[$r10 + 0x100] $r0 // STRAND_FIRST_GENE = 0 + mov $r12 1 + iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_FIRST_GENE +- call strand_wait ++ call #strand_wait + sub b32 $r12 $r0 1 + iowr I[$r10 + 0x000] $r12 // STRAND_GENE_CNT = 0xffffffff + mov $r12 2 + iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_GENE_CNT +- call strand_wait +- call strand_post ++ call #strand_wait ++ call #strand_post + + // read the size of each strand, poke the context offset of + // each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry +@@ -391,7 +391,7 @@ strand_ctx_init: + add b32 $r14 $r10 + add b32 $r8 4 + sub b32 $r9 1 +- bra ne ctx_init_strand_loop ++ bra ne #ctx_init_strand_loop + + shl b32 $r14 8 + sub b32 $r15 $r14 $r15 +diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.h b/drivers/gpu/drm/nouveau/nvc0_graph.h +index 636fe98..91d44ea 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_graph.h ++++ b/drivers/gpu/drm/nouveau/nvc0_graph.h +@@ -87,6 +87,7 @@ nvc0_graph_class(struct drm_device *dev) + case 0xc1: + return 0x9197; + case 0xc8: ++ case 0xd9: + return 0x9297; + default: + return 0; +diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c +index 96b0b93..de77842 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grctx.c ++++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c +@@ -1268,6 +1268,17 @@ nvc0_grctx_generate_9039(struct drm_device *dev) + static void + nvc0_grctx_generate_90c0(struct drm_device *dev) + { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int i; ++ ++ for (i = 0; dev_priv->chipset == 0xd9 && i < 4; i++) { ++ nv_mthd(dev, 0x90c0, 0x2700 + (i * 0x40), 0x00000000); ++ nv_mthd(dev, 0x90c0, 0x2720 + (i * 0x40), 0x00000000); ++ nv_mthd(dev, 0x90c0, 0x2704 + (i * 0x40), 0x00000000); ++ nv_mthd(dev, 0x90c0, 0x2724 + (i * 0x40), 0x00000000); ++ nv_mthd(dev, 0x90c0, 0x2708 + (i * 0x40), 0x00000000); ++ nv_mthd(dev, 0x90c0, 0x2728 + (i * 0x40), 0x00000000); ++ } + nv_mthd(dev, 0x90c0, 0x270c, 0x00000000); + nv_mthd(dev, 0x90c0, 0x272c, 0x00000000); + nv_mthd(dev, 0x90c0, 0x274c, 0x00000000); +@@ -1276,6 +1287,12 @@ nvc0_grctx_generate_90c0(struct drm_device *dev) + nv_mthd(dev, 0x90c0, 0x27ac, 0x00000000); + nv_mthd(dev, 0x90c0, 0x27cc, 0x00000000); + nv_mthd(dev, 0x90c0, 0x27ec, 0x00000000); ++ for (i = 0; dev_priv->chipset == 0xd9 && i < 4; i++) { ++ nv_mthd(dev, 0x90c0, 0x2710 + (i * 0x40), 0x00014000); ++ nv_mthd(dev, 0x90c0, 0x2730 + (i * 0x40), 0x00014000); ++ nv_mthd(dev, 0x90c0, 0x2714 + (i * 0x40), 0x00000040); ++ nv_mthd(dev, 0x90c0, 0x2734 + (i * 0x40), 0x00000040); ++ } + nv_mthd(dev, 0x90c0, 0x030c, 0x00000001); + nv_mthd(dev, 0x90c0, 0x1944, 0x00000000); + nv_mthd(dev, 0x90c0, 0x0758, 0x00000100); +@@ -1471,14 +1488,20 @@ nvc0_grctx_generate_shaders(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + +- if (dev_priv->chipset != 0xc1) { +- nv_wr32(dev, 0x405800, 0x078000bf); +- nv_wr32(dev, 0x405830, 0x02180000); +- } else { ++ if (dev_priv->chipset == 0xd9) { + nv_wr32(dev, 0x405800, 0x0f8000bf); + nv_wr32(dev, 0x405830, 0x02180218); ++ nv_wr32(dev, 0x405834, 0x08000000); ++ } else ++ if (dev_priv->chipset == 0xc1) { ++ nv_wr32(dev, 0x405800, 0x0f8000bf); ++ nv_wr32(dev, 0x405830, 0x02180218); ++ nv_wr32(dev, 0x405834, 0x00000000); ++ } else { ++ nv_wr32(dev, 0x405800, 0x078000bf); ++ nv_wr32(dev, 0x405830, 0x02180000); ++ nv_wr32(dev, 0x405834, 0x00000000); + } +- nv_wr32(dev, 0x405834, 0x00000000); + nv_wr32(dev, 0x405838, 0x00000000); + nv_wr32(dev, 0x405854, 0x00000000); + nv_wr32(dev, 0x405870, 0x00000001); +@@ -1509,7 +1532,10 @@ nvc0_grctx_generate_unk64xx(struct drm_device *dev) + nv_wr32(dev, 0x4064ac, 0x00003fff); + nv_wr32(dev, 0x4064b4, 0x00000000); + nv_wr32(dev, 0x4064b8, 0x00000000); +- if (dev_priv->chipset == 0xc1) { ++ if (dev_priv->chipset == 0xd9) ++ nv_wr32(dev, 0x4064bc, 0x00000000); ++ if (dev_priv->chipset == 0xc1 || ++ dev_priv->chipset == 0xd9) { + nv_wr32(dev, 0x4064c0, 0x80140078); + nv_wr32(dev, 0x4064c4, 0x0086ffff); + } +@@ -1550,10 +1576,23 @@ nvc0_grctx_generate_rop(struct drm_device *dev) + /* ROPC_BROADCAST */ + nv_wr32(dev, 0x408800, 0x02802a3c); + nv_wr32(dev, 0x408804, 0x00000040); +- nv_wr32(dev, 0x408808, chipset != 0xc1 ? 0x0003e00d : 0x1003e005); +- nv_wr32(dev, 0x408900, 0x3080b801); +- nv_wr32(dev, 0x408904, chipset != 0xc1 ? 0x02000001 : 0x62000001); +- nv_wr32(dev, 0x408908, 0x00c80929); ++ if (chipset == 0xd9) { ++ nv_wr32(dev, 0x408808, 0x1043e005); ++ nv_wr32(dev, 0x408900, 0x3080b801); ++ nv_wr32(dev, 0x408904, 0x1043e005); ++ nv_wr32(dev, 0x408908, 0x00c8102f); ++ } else ++ if (chipset == 0xc1) { ++ nv_wr32(dev, 0x408808, 0x1003e005); ++ nv_wr32(dev, 0x408900, 0x3080b801); ++ nv_wr32(dev, 0x408904, 0x62000001); ++ nv_wr32(dev, 0x408908, 0x00c80929); ++ } else { ++ nv_wr32(dev, 0x408808, 0x0003e00d); ++ nv_wr32(dev, 0x408900, 0x3080b801); ++ nv_wr32(dev, 0x408904, 0x02000001); ++ nv_wr32(dev, 0x408908, 0x00c80929); ++ } + nv_wr32(dev, 0x40890c, 0x00000000); + nv_wr32(dev, 0x408980, 0x0000011d); + } +@@ -1572,7 +1611,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev) + nv_wr32(dev, 0x418408, 0x00000000); + nv_wr32(dev, 0x41840c, 0x00001008); + nv_wr32(dev, 0x418410, 0x0fff0fff); +- nv_wr32(dev, 0x418414, 0x00200fff); ++ nv_wr32(dev, 0x418414, chipset != 0xd9 ? 0x00200fff : 0x02200fff); + nv_wr32(dev, 0x418450, 0x00000000); + nv_wr32(dev, 0x418454, 0x00000000); + nv_wr32(dev, 0x418458, 0x00000000); +@@ -1587,14 +1626,17 @@ nvc0_grctx_generate_gpc(struct drm_device *dev) + nv_wr32(dev, 0x418700, 0x00000002); + nv_wr32(dev, 0x418704, 0x00000080); + nv_wr32(dev, 0x418708, 0x00000000); +- nv_wr32(dev, 0x41870c, 0x07c80000); ++ nv_wr32(dev, 0x41870c, chipset != 0xd9 ? 0x07c80000 : 0x00000000); + nv_wr32(dev, 0x418710, 0x00000000); +- nv_wr32(dev, 0x418800, 0x0006860a); ++ nv_wr32(dev, 0x418800, chipset != 0xd9 ? 0x0006860a : 0x7006860a); + nv_wr32(dev, 0x418808, 0x00000000); + nv_wr32(dev, 0x41880c, 0x00000000); + nv_wr32(dev, 0x418810, 0x00000000); + nv_wr32(dev, 0x418828, 0x00008442); +- nv_wr32(dev, 0x418830, chipset != 0xc1 ? 0x00000001 : 0x10000001); ++ if (chipset == 0xc1 || chipset == 0xd9) ++ nv_wr32(dev, 0x418830, 0x10000001); ++ else ++ nv_wr32(dev, 0x418830, 0x00000001); + nv_wr32(dev, 0x4188d8, 0x00000008); + nv_wr32(dev, 0x4188e0, 0x01000000); + nv_wr32(dev, 0x4188e8, 0x00000000); +@@ -1602,7 +1644,12 @@ nvc0_grctx_generate_gpc(struct drm_device *dev) + nv_wr32(dev, 0x4188f0, 0x00000000); + nv_wr32(dev, 0x4188f4, 0x00000000); + nv_wr32(dev, 0x4188f8, 0x00000000); +- nv_wr32(dev, 0x4188fc, chipset != 0xc1 ? 0x00100000 : 0x00100018); ++ if (chipset == 0xd9) ++ nv_wr32(dev, 0x4188fc, 0x20100008); ++ else if (chipset == 0xc1) ++ nv_wr32(dev, 0x4188fc, 0x00100018); ++ else ++ nv_wr32(dev, 0x4188fc, 0x00100000); + nv_wr32(dev, 0x41891c, 0x00ff00ff); + nv_wr32(dev, 0x418924, 0x00000000); + nv_wr32(dev, 0x418928, 0x00ffff00); +@@ -1616,7 +1663,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev) + nv_wr32(dev, 0x418a14 + (i * 0x20), 0x00000000); + nv_wr32(dev, 0x418a18 + (i * 0x20), 0x00000000); + } +- nv_wr32(dev, 0x418b00, 0x00000000); ++ nv_wr32(dev, 0x418b00, chipset != 0xd9 ? 0x00000000 : 0x00000006); + nv_wr32(dev, 0x418b08, 0x0a418820); + nv_wr32(dev, 0x418b0c, 0x062080e6); + nv_wr32(dev, 0x418b10, 0x020398a4); +@@ -1633,7 +1680,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev) + nv_wr32(dev, 0x418c24, 0x00000000); + nv_wr32(dev, 0x418c28, 0x00000000); + nv_wr32(dev, 0x418c2c, 0x00000000); +- if (chipset == 0xc1) ++ if (chipset == 0xc1 || chipset == 0xd9) + nv_wr32(dev, 0x418c6c, 0x00000001); + nv_wr32(dev, 0x418c80, 0x20200004); + nv_wr32(dev, 0x418c8c, 0x00000001); +@@ -1653,7 +1700,10 @@ nvc0_grctx_generate_tp(struct drm_device *dev) + nv_wr32(dev, 0x419818, 0x00000000); + nv_wr32(dev, 0x41983c, 0x00038bc7); + nv_wr32(dev, 0x419848, 0x00000000); +- nv_wr32(dev, 0x419864, chipset != 0xc1 ? 0x0000012a : 0x00000129); ++ if (chipset == 0xc1 || chipset == 0xd9) ++ nv_wr32(dev, 0x419864, 0x00000129); ++ else ++ nv_wr32(dev, 0x419864, 0x0000012a); + nv_wr32(dev, 0x419888, 0x00000000); + nv_wr32(dev, 0x419a00, 0x000001f0); + nv_wr32(dev, 0x419a04, 0x00000001); +@@ -1663,7 +1713,9 @@ nvc0_grctx_generate_tp(struct drm_device *dev) + nv_wr32(dev, 0x419a14, 0x00000200); + nv_wr32(dev, 0x419a1c, 0x00000000); + nv_wr32(dev, 0x419a20, 0x00000800); +- if (chipset != 0xc0 && chipset != 0xc8) ++ if (chipset == 0xd9) ++ nv_wr32(dev, 0x00419ac4, 0x0017f440); ++ else if (chipset != 0xc0 && chipset != 0xc8) + nv_wr32(dev, 0x00419ac4, 0x0007f440); + nv_wr32(dev, 0x419b00, 0x0a418820); + nv_wr32(dev, 0x419b04, 0x062080e6); +@@ -1672,21 +1724,33 @@ nvc0_grctx_generate_tp(struct drm_device *dev) + nv_wr32(dev, 0x419b10, 0x0a418820); + nv_wr32(dev, 0x419b14, 0x000000e6); + nv_wr32(dev, 0x419bd0, 0x00900103); +- nv_wr32(dev, 0x419be0, chipset != 0xc1 ? 0x00000001 : 0x00400001); ++ if (chipset == 0xc1 || chipset == 0xd9) ++ nv_wr32(dev, 0x419be0, 0x00400001); ++ else ++ nv_wr32(dev, 0x419be0, 0x00000001); + nv_wr32(dev, 0x419be4, 0x00000000); +- nv_wr32(dev, 0x419c00, 0x00000002); ++ nv_wr32(dev, 0x419c00, chipset != 0xd9 ? 0x00000002 : 0x0000000a); + nv_wr32(dev, 0x419c04, 0x00000006); + nv_wr32(dev, 0x419c08, 0x00000002); + nv_wr32(dev, 0x419c20, 0x00000000); +- if (chipset == 0xce || chipset == 0xcf) ++ if (dev_priv->chipset == 0xd9) { ++ nv_wr32(dev, 0x419c24, 0x00084210); ++ nv_wr32(dev, 0x419c28, 0x3cf3cf3c); + nv_wr32(dev, 0x419cb0, 0x00020048); +- else ++ } else ++ if (chipset == 0xce || chipset == 0xcf) { ++ nv_wr32(dev, 0x419cb0, 0x00020048); ++ } else { + nv_wr32(dev, 0x419cb0, 0x00060048); ++ } + nv_wr32(dev, 0x419ce8, 0x00000000); + nv_wr32(dev, 0x419cf4, 0x00000183); +- nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000); ++ if (chipset == 0xc1 || chipset == 0xd9) ++ nv_wr32(dev, 0x419d20, 0x12180000); ++ else ++ nv_wr32(dev, 0x419d20, 0x02180000); + nv_wr32(dev, 0x419d24, 0x00001fff); +- if (chipset == 0xc1) ++ if (chipset == 0xc1 || chipset == 0xd9) + nv_wr32(dev, 0x419d44, 0x02180218); + nv_wr32(dev, 0x419e04, 0x00000000); + nv_wr32(dev, 0x419e08, 0x00000000); +@@ -1986,6 +2050,10 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + nv_icmd(dev, 0x00000215, 0x00000040); + nv_icmd(dev, 0x00000216, 0x00000040); + nv_icmd(dev, 0x00000217, 0x00000040); ++ if (dev_priv->chipset == 0xd9) { ++ for (i = 0x0400; i <= 0x0417; i++) ++ nv_icmd(dev, i, 0x00000040); ++ } + nv_icmd(dev, 0x00000218, 0x0000c080); + nv_icmd(dev, 0x00000219, 0x0000c080); + nv_icmd(dev, 0x0000021a, 0x0000c080); +@@ -1994,6 +2062,10 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + nv_icmd(dev, 0x0000021d, 0x0000c080); + nv_icmd(dev, 0x0000021e, 0x0000c080); + nv_icmd(dev, 0x0000021f, 0x0000c080); ++ if (dev_priv->chipset == 0xd9) { ++ for (i = 0x0440; i <= 0x0457; i++) ++ nv_icmd(dev, i, 0x0000c080); ++ } + nv_icmd(dev, 0x000000ad, 0x0000013e); + nv_icmd(dev, 0x000000e1, 0x00000010); + nv_icmd(dev, 0x00000290, 0x00000000); +@@ -2556,7 +2628,8 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + nv_icmd(dev, 0x0000053f, 0xffff0000); + nv_icmd(dev, 0x00000585, 0x0000003f); + nv_icmd(dev, 0x00000576, 0x00000003); +- if (dev_priv->chipset == 0xc1) ++ if (dev_priv->chipset == 0xc1 || ++ dev_priv->chipset == 0xd9) + nv_icmd(dev, 0x0000057b, 0x00000059); + nv_icmd(dev, 0x00000586, 0x00000040); + nv_icmd(dev, 0x00000582, 0x00000080); +@@ -2658,6 +2731,8 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + nv_icmd(dev, 0x00000957, 0x00000003); + nv_icmd(dev, 0x0000095e, 0x20164010); + nv_icmd(dev, 0x0000095f, 0x00000020); ++ if (dev_priv->chipset == 0xd9) ++ nv_icmd(dev, 0x0000097d, 0x00000020); + nv_icmd(dev, 0x00000683, 0x00000006); + nv_icmd(dev, 0x00000685, 0x003fffff); + nv_icmd(dev, 0x00000687, 0x00000c48); +diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc +index 06f5e26..15272be 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc ++++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc +@@ -32,7 +32,7 @@ + * - watchdog timer around ctx operations + */ + +-.section nvc0_grgpc_data ++.section #nvc0_grgpc_data + include(`nvc0_graph.fuc') + gpc_id: .b32 0 + gpc_mmio_list_head: .b32 0 +@@ -48,40 +48,45 @@ cmd_queue: queue_init + // chipset descriptions + chipsets: + .b8 0xc0 0 0 0 +-.b16 nvc0_gpc_mmio_head +-.b16 nvc0_gpc_mmio_tail +-.b16 nvc0_tpc_mmio_head +-.b16 nvc0_tpc_mmio_tail ++.b16 #nvc0_gpc_mmio_head ++.b16 #nvc0_gpc_mmio_tail ++.b16 #nvc0_tpc_mmio_head ++.b16 #nvc0_tpc_mmio_tail + .b8 0xc1 0 0 0 +-.b16 nvc0_gpc_mmio_head +-.b16 nvc1_gpc_mmio_tail +-.b16 nvc0_tpc_mmio_head +-.b16 nvc1_tpc_mmio_tail ++.b16 #nvc0_gpc_mmio_head ++.b16 #nvc1_gpc_mmio_tail ++.b16 #nvc0_tpc_mmio_head ++.b16 #nvc1_tpc_mmio_tail + .b8 0xc3 0 0 0 +-.b16 nvc0_gpc_mmio_head +-.b16 nvc0_gpc_mmio_tail +-.b16 nvc0_tpc_mmio_head +-.b16 nvc3_tpc_mmio_tail ++.b16 #nvc0_gpc_mmio_head ++.b16 #nvc0_gpc_mmio_tail ++.b16 #nvc0_tpc_mmio_head ++.b16 #nvc3_tpc_mmio_tail + .b8 0xc4 0 0 0 +-.b16 nvc0_gpc_mmio_head +-.b16 nvc0_gpc_mmio_tail +-.b16 nvc0_tpc_mmio_head +-.b16 nvc3_tpc_mmio_tail ++.b16 #nvc0_gpc_mmio_head ++.b16 #nvc0_gpc_mmio_tail ++.b16 #nvc0_tpc_mmio_head ++.b16 #nvc3_tpc_mmio_tail + .b8 0xc8 0 0 0 +-.b16 nvc0_gpc_mmio_head +-.b16 nvc0_gpc_mmio_tail +-.b16 nvc0_tpc_mmio_head +-.b16 nvc0_tpc_mmio_tail ++.b16 #nvc0_gpc_mmio_head ++.b16 #nvc0_gpc_mmio_tail ++.b16 #nvc0_tpc_mmio_head ++.b16 #nvc0_tpc_mmio_tail + .b8 0xce 0 0 0 +-.b16 nvc0_gpc_mmio_head +-.b16 nvc0_gpc_mmio_tail +-.b16 nvc0_tpc_mmio_head +-.b16 nvc3_tpc_mmio_tail ++.b16 #nvc0_gpc_mmio_head ++.b16 #nvc0_gpc_mmio_tail ++.b16 #nvc0_tpc_mmio_head ++.b16 #nvc3_tpc_mmio_tail + .b8 0xcf 0 0 0 +-.b16 nvc0_gpc_mmio_head +-.b16 nvc0_gpc_mmio_tail +-.b16 nvc0_tpc_mmio_head +-.b16 nvcf_tpc_mmio_tail ++.b16 #nvc0_gpc_mmio_head ++.b16 #nvc0_gpc_mmio_tail ++.b16 #nvc0_tpc_mmio_head ++.b16 #nvcf_tpc_mmio_tail ++.b8 0xd9 0 0 0 ++.b16 #nvd9_gpc_mmio_head ++.b16 #nvd9_gpc_mmio_tail ++.b16 #nvd9_tpc_mmio_head ++.b16 #nvd9_tpc_mmio_tail + .b8 0 0 0 0 + + // GPC mmio lists +@@ -114,6 +119,35 @@ nvc0_gpc_mmio_tail: + mmctx_data(0x000c6c, 1); + nvc1_gpc_mmio_tail: + ++nvd9_gpc_mmio_head: ++mmctx_data(0x000380, 1) ++mmctx_data(0x000400, 2) ++mmctx_data(0x00040c, 3) ++mmctx_data(0x000450, 9) ++mmctx_data(0x000600, 1) ++mmctx_data(0x000684, 1) ++mmctx_data(0x000700, 5) ++mmctx_data(0x000800, 1) ++mmctx_data(0x000808, 3) ++mmctx_data(0x000828, 1) ++mmctx_data(0x000830, 1) ++mmctx_data(0x0008d8, 1) ++mmctx_data(0x0008e0, 1) ++mmctx_data(0x0008e8, 6) ++mmctx_data(0x00091c, 1) ++mmctx_data(0x000924, 3) ++mmctx_data(0x000b00, 1) ++mmctx_data(0x000b08, 6) ++mmctx_data(0x000bb8, 1) ++mmctx_data(0x000c08, 1) ++mmctx_data(0x000c10, 8) ++mmctx_data(0x000c6c, 1) ++mmctx_data(0x000c80, 1) ++mmctx_data(0x000c8c, 1) ++mmctx_data(0x001000, 3) ++mmctx_data(0x001014, 1) ++nvd9_gpc_mmio_tail: ++ + // TPC mmio lists + nvc0_tpc_mmio_head: + mmctx_data(0x000018, 1) +@@ -146,9 +180,34 @@ nvc3_tpc_mmio_tail: + mmctx_data(0x000544, 1) + nvc1_tpc_mmio_tail: + ++nvd9_tpc_mmio_head: ++mmctx_data(0x000018, 1) ++mmctx_data(0x00003c, 1) ++mmctx_data(0x000048, 1) ++mmctx_data(0x000064, 1) ++mmctx_data(0x000088, 1) ++mmctx_data(0x000200, 6) ++mmctx_data(0x00021c, 2) ++mmctx_data(0x0002c4, 1) ++mmctx_data(0x000300, 6) ++mmctx_data(0x0003d0, 1) ++mmctx_data(0x0003e0, 2) ++mmctx_data(0x000400, 3) ++mmctx_data(0x000420, 3) ++mmctx_data(0x0004b0, 1) ++mmctx_data(0x0004e8, 1) ++mmctx_data(0x0004f4, 1) ++mmctx_data(0x000520, 2) ++mmctx_data(0x000544, 1) ++mmctx_data(0x000604, 4) ++mmctx_data(0x000644, 20) ++mmctx_data(0x000698, 1) ++mmctx_data(0x0006e0, 1) ++mmctx_data(0x000750, 3) ++nvd9_tpc_mmio_tail: + +-.section nvc0_grgpc_code +-bra init ++.section #nvc0_grgpc_code ++bra #init + define(`include_code') + include(`nvc0_graph.fuc') + +@@ -160,10 +219,10 @@ error: + push $r14 + mov $r14 -0x67ec // 0x9814 + sethi $r14 0x400000 +- call nv_wr32 // HUB_CTXCTL_CC_SCRATCH[5] = error code ++ call #nv_wr32 // HUB_CTXCTL_CC_SCRATCH[5] = error code + add b32 $r14 0x41c + mov $r15 1 +- call nv_wr32 // HUB_CTXCTL_INTR_UP_SET ++ call #nv_wr32 // HUB_CTXCTL_INTR_UP_SET + pop $r14 + ret + +@@ -190,7 +249,7 @@ init: + iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE + + // setup i0 handler, and route all interrupts to it +- mov $r1 ih ++ mov $r1 #ih + mov $iv0 $r1 + mov $r1 0x400 + iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH +@@ -210,24 +269,24 @@ init: + and $r2 0x1f + shl b32 $r3 $r2 + sub b32 $r3 1 +- st b32 D[$r0 + tpc_count] $r2 +- st b32 D[$r0 + tpc_mask] $r3 ++ st b32 D[$r0 + #tpc_count] $r2 ++ st b32 D[$r0 + #tpc_mask] $r3 + add b32 $r1 0x400 + iord $r2 I[$r1 + 0x000] // MYINDEX +- st b32 D[$r0 + gpc_id] $r2 ++ st b32 D[$r0 + #gpc_id] $r2 + + // find context data for this chipset + mov $r2 0x800 + shl b32 $r2 6 + iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0] +- mov $r1 chipsets - 12 ++ mov $r1 #chipsets - 12 + init_find_chipset: + add b32 $r1 12 + ld b32 $r3 D[$r1 + 0x00] + cmpu b32 $r3 $r2 +- bra e init_context ++ bra e #init_context + cmpu b32 $r3 0 +- bra ne init_find_chipset ++ bra ne #init_find_chipset + // unknown chipset + ret + +@@ -253,19 +312,19 @@ init: + clear b32 $r15 + ld b16 $r14 D[$r1 + 4] + ld b16 $r15 D[$r1 + 6] +- st b16 D[$r0 + gpc_mmio_list_head] $r14 +- st b16 D[$r0 + gpc_mmio_list_tail] $r15 +- call mmctx_size ++ st b16 D[$r0 + #gpc_mmio_list_head] $r14 ++ st b16 D[$r0 + #gpc_mmio_list_tail] $r15 ++ call #mmctx_size + add b32 $r2 $r15 + add b32 $r3 $r15 + + // calculate per-TPC mmio context size, store the list pointers + ld b16 $r14 D[$r1 + 8] + ld b16 $r15 D[$r1 + 10] +- st b16 D[$r0 + tpc_mmio_list_head] $r14 +- st b16 D[$r0 + tpc_mmio_list_tail] $r15 +- call mmctx_size +- ld b32 $r14 D[$r0 + tpc_count] ++ st b16 D[$r0 + #tpc_mmio_list_head] $r14 ++ st b16 D[$r0 + #tpc_mmio_list_tail] $r15 ++ call #mmctx_size ++ ld b32 $r14 D[$r0 + #tpc_count] + mulu $r14 $r15 + add b32 $r2 $r14 + add b32 $r3 $r14 +@@ -283,7 +342,7 @@ init: + + // calculate size of strand context data + mov b32 $r15 $r2 +- call strand_ctx_init ++ call #strand_ctx_init + add b32 $r3 $r15 + + // save context size, and tell HUB we're done +@@ -301,13 +360,13 @@ init: + main: + bset $flags $p0 + sleep $p0 +- mov $r13 cmd_queue +- call queue_get +- bra $p1 main ++ mov $r13 #cmd_queue ++ call #queue_get ++ bra $p1 #main + + // 0x0000-0x0003 are all context transfers + cmpu b32 $r14 0x04 +- bra nc main_not_ctx_xfer ++ bra nc #main_not_ctx_xfer + // fetch $flags and mask off $p1/$p2 + mov $r1 $flags + mov $r2 0x0006 +@@ -318,14 +377,14 @@ main: + or $r1 $r14 + mov $flags $r1 + // transfer context data +- call ctx_xfer +- bra main ++ call #ctx_xfer ++ bra #main + + main_not_ctx_xfer: + shl b32 $r15 $r14 16 + or $r15 E_BAD_COMMAND +- call error +- bra main ++ call #error ++ bra #main + + // interrupt handler + ih: +@@ -342,13 +401,13 @@ ih: + // incoming fifo command? + iord $r10 I[$r0 + 0x200] // INTR + and $r11 $r10 0x00000004 +- bra e ih_no_fifo ++ bra e #ih_no_fifo + // queue incoming fifo command for later processing + mov $r11 0x1900 +- mov $r13 cmd_queue ++ mov $r13 #cmd_queue + iord $r14 I[$r11 + 0x100] // FIFO_CMD + iord $r15 I[$r11 + 0x000] // FIFO_DATA +- call queue_put ++ call #queue_put + add b32 $r11 0x400 + mov $r14 1 + iowr I[$r11 + 0x000] $r14 // FIFO_ACK +@@ -374,11 +433,11 @@ ih: + // + hub_barrier_done: + mov $r15 1 +- ld b32 $r14 D[$r0 + gpc_id] ++ ld b32 $r14 D[$r0 + #gpc_id] + shl b32 $r15 $r14 + mov $r14 -0x6be8 // 0x409418 - HUB_BAR_SET + sethi $r14 0x400000 +- call nv_wr32 ++ call #nv_wr32 + ret + + // Disables various things, waits a bit, and re-enables them.. +@@ -395,7 +454,7 @@ ctx_redswitch: + mov $r15 8 + ctx_redswitch_delay: + sub b32 $r15 1 +- bra ne ctx_redswitch_delay ++ bra ne #ctx_redswitch_delay + mov $r15 0xa20 + iowr I[$r14] $r15 // GPC_RED_SWITCH = UNK11, ENABLE, POWER + ret +@@ -413,8 +472,8 @@ ctx_xfer: + mov $r1 0xa04 + shl b32 $r1 6 + iowr I[$r1 + 0x000] $r15// MEM_BASE +- bra not $p1 ctx_xfer_not_load +- call ctx_redswitch ++ bra not $p1 #ctx_xfer_not_load ++ call #ctx_redswitch + ctx_xfer_not_load: + + // strands +@@ -422,7 +481,7 @@ ctx_xfer: + sethi $r1 0x20000 + mov $r2 0xc + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c +- call strand_wait ++ call #strand_wait + mov $r2 0x47fc + sethi $r2 0x20000 + iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00 +@@ -435,46 +494,46 @@ ctx_xfer: + or $r10 2 // first + mov $r11 0x0000 + sethi $r11 0x500000 +- ld b32 $r12 D[$r0 + gpc_id] ++ ld b32 $r12 D[$r0 + #gpc_id] + shl b32 $r12 15 + add b32 $r11 $r12 // base = NV_PGRAPH_GPCn +- ld b32 $r12 D[$r0 + gpc_mmio_list_head] +- ld b32 $r13 D[$r0 + gpc_mmio_list_tail] ++ ld b32 $r12 D[$r0 + #gpc_mmio_list_head] ++ ld b32 $r13 D[$r0 + #gpc_mmio_list_tail] + mov $r14 0 // not multi +- call mmctx_xfer ++ call #mmctx_xfer + + // per-TPC mmio context + xbit $r10 $flags $p1 // direction + or $r10 4 // last + mov $r11 0x4000 + sethi $r11 0x500000 // base = NV_PGRAPH_GPC0_TPC0 +- ld b32 $r12 D[$r0 + gpc_id] ++ ld b32 $r12 D[$r0 + #gpc_id] + shl b32 $r12 15 + add b32 $r11 $r12 // base = NV_PGRAPH_GPCn_TPC0 +- ld b32 $r12 D[$r0 + tpc_mmio_list_head] +- ld b32 $r13 D[$r0 + tpc_mmio_list_tail] +- ld b32 $r15 D[$r0 + tpc_mask] ++ ld b32 $r12 D[$r0 + #tpc_mmio_list_head] ++ ld b32 $r13 D[$r0 + #tpc_mmio_list_tail] ++ ld b32 $r15 D[$r0 + #tpc_mask] + mov $r14 0x800 // stride = 0x800 +- call mmctx_xfer ++ call #mmctx_xfer + + // wait for strands to finish +- call strand_wait ++ call #strand_wait + + // if load, or a save without a load following, do some + // unknown stuff that's done after finishing a block of + // strand commands +- bra $p1 ctx_xfer_post +- bra not $p2 ctx_xfer_done ++ bra $p1 #ctx_xfer_post ++ bra not $p2 #ctx_xfer_done + ctx_xfer_post: + mov $r1 0x4afc + sethi $r1 0x20000 + mov $r2 0xd + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0d +- call strand_wait ++ call #strand_wait + + // mark completion in HUB's barrier + ctx_xfer_done: +- call hub_barrier_done ++ call #hub_barrier_done + ret + + .align 256 +diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h +index 6f82032..a988b8a 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h ++++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h +@@ -25,26 +25,29 @@ uint32_t nvc0_grgpc_data[] = { + 0x00000000, + 0x00000000, + 0x000000c0, +- 0x011c00bc, +- 0x01700120, ++ 0x012800c8, ++ 0x01e40194, + 0x000000c1, +- 0x012000bc, +- 0x01840120, ++ 0x012c00c8, ++ 0x01f80194, + 0x000000c3, +- 0x011c00bc, +- 0x01800120, ++ 0x012800c8, ++ 0x01f40194, + 0x000000c4, +- 0x011c00bc, +- 0x01800120, ++ 0x012800c8, ++ 0x01f40194, + 0x000000c8, +- 0x011c00bc, +- 0x01700120, ++ 0x012800c8, ++ 0x01e40194, + 0x000000ce, +- 0x011c00bc, +- 0x01800120, ++ 0x012800c8, ++ 0x01f40194, + 0x000000cf, +- 0x011c00bc, +- 0x017c0120, ++ 0x012800c8, ++ 0x01f00194, ++ 0x000000d9, ++ 0x0194012c, ++ 0x025401f8, + 0x00000000, + 0x00000380, + 0x14000400, +@@ -71,6 +74,32 @@ uint32_t nvc0_grgpc_data[] = { + 0x08001000, + 0x00001014, + 0x00000c6c, ++ 0x00000380, ++ 0x04000400, ++ 0x0800040c, ++ 0x20000450, ++ 0x00000600, ++ 0x00000684, ++ 0x10000700, ++ 0x00000800, ++ 0x08000808, ++ 0x00000828, ++ 0x00000830, ++ 0x000008d8, ++ 0x000008e0, ++ 0x140008e8, ++ 0x0000091c, ++ 0x08000924, ++ 0x00000b00, ++ 0x14000b08, ++ 0x00000bb8, ++ 0x00000c08, ++ 0x1c000c10, ++ 0x00000c6c, ++ 0x00000c80, ++ 0x00000c8c, ++ 0x08001000, ++ 0x00001014, + 0x00000018, + 0x0000003c, + 0x00000048, +@@ -96,6 +125,29 @@ uint32_t nvc0_grgpc_data[] = { + 0x000006e0, + 0x000004bc, + 0x00000544, ++ 0x00000018, ++ 0x0000003c, ++ 0x00000048, ++ 0x00000064, ++ 0x00000088, ++ 0x14000200, ++ 0x0400021c, ++ 0x000002c4, ++ 0x14000300, ++ 0x000003d0, ++ 0x040003e0, ++ 0x08000400, ++ 0x08000420, ++ 0x000004b0, ++ 0x000004e8, ++ 0x000004f4, ++ 0x04000520, ++ 0x00000544, ++ 0x0c000604, ++ 0x4c000644, ++ 0x00000698, ++ 0x000006e0, ++ 0x08000750, + }; + + uint32_t nvc0_grgpc_code[] = { +diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc +index e4f8c7e..98acddb 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc ++++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc +@@ -27,7 +27,7 @@ + * m4 nvc0_grhub.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grhub.fuc.h + */ + +-.section nvc0_grhub_data ++.section #nvc0_grhub_data + include(`nvc0_graph.fuc') + gpc_count: .b32 0 + rop_count: .b32 0 +@@ -39,26 +39,29 @@ ctx_current: .b32 0 + + chipsets: + .b8 0xc0 0 0 0 +-.b16 nvc0_hub_mmio_head +-.b16 nvc0_hub_mmio_tail ++.b16 #nvc0_hub_mmio_head ++.b16 #nvc0_hub_mmio_tail + .b8 0xc1 0 0 0 +-.b16 nvc0_hub_mmio_head +-.b16 nvc1_hub_mmio_tail ++.b16 #nvc0_hub_mmio_head ++.b16 #nvc1_hub_mmio_tail + .b8 0xc3 0 0 0 +-.b16 nvc0_hub_mmio_head +-.b16 nvc0_hub_mmio_tail ++.b16 #nvc0_hub_mmio_head ++.b16 #nvc0_hub_mmio_tail + .b8 0xc4 0 0 0 +-.b16 nvc0_hub_mmio_head +-.b16 nvc0_hub_mmio_tail ++.b16 #nvc0_hub_mmio_head ++.b16 #nvc0_hub_mmio_tail + .b8 0xc8 0 0 0 +-.b16 nvc0_hub_mmio_head +-.b16 nvc0_hub_mmio_tail ++.b16 #nvc0_hub_mmio_head ++.b16 #nvc0_hub_mmio_tail + .b8 0xce 0 0 0 +-.b16 nvc0_hub_mmio_head +-.b16 nvc0_hub_mmio_tail ++.b16 #nvc0_hub_mmio_head ++.b16 #nvc0_hub_mmio_tail + .b8 0xcf 0 0 0 +-.b16 nvc0_hub_mmio_head +-.b16 nvc0_hub_mmio_tail ++.b16 #nvc0_hub_mmio_head ++.b16 #nvc0_hub_mmio_tail ++.b8 0xd9 0 0 0 ++.b16 #nvd9_hub_mmio_head ++.b16 #nvd9_hub_mmio_tail + .b8 0 0 0 0 + + nvc0_hub_mmio_head: +@@ -105,6 +108,48 @@ nvc0_hub_mmio_tail: + mmctx_data(0x4064c0, 2) + nvc1_hub_mmio_tail: + ++nvd9_hub_mmio_head: ++mmctx_data(0x17e91c, 2) ++mmctx_data(0x400204, 2) ++mmctx_data(0x404004, 10) ++mmctx_data(0x404044, 1) ++mmctx_data(0x404094, 14) ++mmctx_data(0x4040d0, 7) ++mmctx_data(0x4040f8, 1) ++mmctx_data(0x404130, 3) ++mmctx_data(0x404150, 3) ++mmctx_data(0x404164, 2) ++mmctx_data(0x404178, 2) ++mmctx_data(0x404200, 8) ++mmctx_data(0x404404, 14) ++mmctx_data(0x404460, 4) ++mmctx_data(0x404480, 1) ++mmctx_data(0x404498, 1) ++mmctx_data(0x404604, 4) ++mmctx_data(0x404618, 32) ++mmctx_data(0x404698, 21) ++mmctx_data(0x4046f0, 2) ++mmctx_data(0x404700, 22) ++mmctx_data(0x405800, 1) ++mmctx_data(0x405830, 3) ++mmctx_data(0x405854, 1) ++mmctx_data(0x405870, 4) ++mmctx_data(0x405a00, 2) ++mmctx_data(0x405a18, 1) ++mmctx_data(0x406020, 1) ++mmctx_data(0x406028, 4) ++mmctx_data(0x4064a8, 2) ++mmctx_data(0x4064b4, 5) ++mmctx_data(0x407804, 1) ++mmctx_data(0x40780c, 6) ++mmctx_data(0x4078bc, 1) ++mmctx_data(0x408000, 7) ++mmctx_data(0x408064, 1) ++mmctx_data(0x408800, 3) ++mmctx_data(0x408900, 4) ++mmctx_data(0x408980, 1) ++nvd9_hub_mmio_tail: ++ + .align 256 + chan_data: + chan_mmio_count: .b32 0 +@@ -113,8 +158,8 @@ chan_mmio_address: .b32 0 + .align 256 + xfer_data: .b32 0 + +-.section nvc0_grhub_code +-bra init ++.section #nvc0_grhub_code ++bra #init + define(`include_code') + include(`nvc0_graph.fuc') + +@@ -157,7 +202,7 @@ init: + iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE + + // setup i0 handler, and route all interrupts to it +- mov $r1 ih ++ mov $r1 #ih + mov $iv0 $r1 + mov $r1 0x400 + iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH +@@ -201,11 +246,11 @@ init: + // fetch enabled GPC/ROP counts + mov $r14 -0x69fc // 0x409604 + sethi $r14 0x400000 +- call nv_rd32 ++ call #nv_rd32 + extr $r1 $r15 16:20 +- st b32 D[$r0 + rop_count] $r1 ++ st b32 D[$r0 + #rop_count] $r1 + and $r15 0x1f +- st b32 D[$r0 + gpc_count] $r15 ++ st b32 D[$r0 + #gpc_count] $r15 + + // set BAR_REQMASK to GPC mask + mov $r1 1 +@@ -220,14 +265,14 @@ init: + mov $r2 0x800 + shl b32 $r2 6 + iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0] +- mov $r15 chipsets - 8 ++ mov $r15 #chipsets - 8 + init_find_chipset: + add b32 $r15 8 + ld b32 $r3 D[$r15 + 0x00] + cmpu b32 $r3 $r2 +- bra e init_context ++ bra e #init_context + cmpu b32 $r3 0 +- bra ne init_find_chipset ++ bra ne #init_find_chipset + // unknown chipset + ret + +@@ -239,9 +284,9 @@ init: + ld b16 $r14 D[$r15 + 4] + ld b16 $r15 D[$r15 + 6] + sethi $r14 0 +- st b32 D[$r0 + hub_mmio_list_head] $r14 +- st b32 D[$r0 + hub_mmio_list_tail] $r15 +- call mmctx_size ++ st b32 D[$r0 + #hub_mmio_list_head] $r14 ++ st b32 D[$r0 + #hub_mmio_list_tail] $r15 ++ call #mmctx_size + + // set mmctx base addresses now so we don't have to do it later, + // they don't (currently) ever change +@@ -260,7 +305,7 @@ init: + add b32 $r1 1 + shl b32 $r1 8 + mov b32 $r15 $r1 +- call strand_ctx_init ++ call #strand_ctx_init + add b32 $r1 $r15 + + // initialise each GPC in sequence by passing in the offset of its +@@ -271,40 +316,40 @@ init: + // when it has completed, and return the size of its context data + // in GPCn_CC_SCRATCH[1] + // +- ld b32 $r3 D[$r0 + gpc_count] ++ ld b32 $r3 D[$r0 + #gpc_count] + mov $r4 0x2000 + sethi $r4 0x500000 + init_gpc: + // setup, and start GPC ucode running + add b32 $r14 $r4 0x804 + mov b32 $r15 $r1 +- call nv_wr32 // CC_SCRATCH[1] = ctx offset ++ call #nv_wr32 // CC_SCRATCH[1] = ctx offset + add b32 $r14 $r4 0x800 + mov b32 $r15 $r2 +- call nv_wr32 // CC_SCRATCH[0] = chipset ++ call #nv_wr32 // CC_SCRATCH[0] = chipset + add b32 $r14 $r4 0x10c + clear b32 $r15 +- call nv_wr32 ++ call #nv_wr32 + add b32 $r14 $r4 0x104 +- call nv_wr32 // ENTRY ++ call #nv_wr32 // ENTRY + add b32 $r14 $r4 0x100 + mov $r15 2 // CTRL_START_TRIGGER +- call nv_wr32 // CTRL ++ call #nv_wr32 // CTRL + + // wait for it to complete, and adjust context size + add b32 $r14 $r4 0x800 + init_gpc_wait: +- call nv_rd32 ++ call #nv_rd32 + xbit $r15 $r15 31 +- bra e init_gpc_wait ++ bra e #init_gpc_wait + add b32 $r14 $r4 0x804 +- call nv_rd32 ++ call #nv_rd32 + add b32 $r1 $r15 + + // next! + add b32 $r4 0x8000 + sub b32 $r3 1 +- bra ne init_gpc ++ bra ne #init_gpc + + // save context size, and tell host we're ready + mov $r2 0x800 +@@ -322,13 +367,13 @@ main: + // sleep until we have something to do + bset $flags $p0 + sleep $p0 +- mov $r13 cmd_queue +- call queue_get +- bra $p1 main ++ mov $r13 #cmd_queue ++ call #queue_get ++ bra $p1 #main + + // context switch, requested by GPU? + cmpu b32 $r14 0x4001 +- bra ne main_not_ctx_switch ++ bra ne #main_not_ctx_switch + trace_set(T_AUTO) + mov $r1 0xb00 + shl b32 $r1 6 +@@ -336,39 +381,39 @@ main: + iord $r1 I[$r1 + 0x000] // CHAN_CUR + + xbit $r3 $r1 31 +- bra e chsw_no_prev ++ bra e #chsw_no_prev + xbit $r3 $r2 31 +- bra e chsw_prev_no_next ++ bra e #chsw_prev_no_next + push $r2 + mov b32 $r2 $r1 + trace_set(T_SAVE) + bclr $flags $p1 + bset $flags $p2 +- call ctx_xfer ++ call #ctx_xfer + trace_clr(T_SAVE); + pop $r2 + trace_set(T_LOAD); + bset $flags $p1 +- call ctx_xfer ++ call #ctx_xfer + trace_clr(T_LOAD); +- bra chsw_done ++ bra #chsw_done + chsw_prev_no_next: + push $r2 + mov b32 $r2 $r1 + bclr $flags $p1 + bclr $flags $p2 +- call ctx_xfer ++ call #ctx_xfer + pop $r2 + mov $r1 0xb00 + shl b32 $r1 6 + iowr I[$r1] $r2 +- bra chsw_done ++ bra #chsw_done + chsw_no_prev: + xbit $r3 $r2 31 +- bra e chsw_done ++ bra e #chsw_done + bset $flags $p1 + bclr $flags $p2 +- call ctx_xfer ++ call #ctx_xfer + + // ack the context switch request + chsw_done: +@@ -377,32 +422,32 @@ main: + mov $r2 1 + iowr I[$r1 + 0x000] $r2 // 0x409b0c + trace_clr(T_AUTO) +- bra main ++ bra #main + + // request to set current channel? (*not* a context switch) + main_not_ctx_switch: + cmpu b32 $r14 0x0001 +- bra ne main_not_ctx_chan ++ bra ne #main_not_ctx_chan + mov b32 $r2 $r15 +- call ctx_chan +- bra main_done ++ call #ctx_chan ++ bra #main_done + + // request to store current channel context? + main_not_ctx_chan: + cmpu b32 $r14 0x0002 +- bra ne main_not_ctx_save ++ bra ne #main_not_ctx_save + trace_set(T_SAVE) + bclr $flags $p1 + bclr $flags $p2 +- call ctx_xfer ++ call #ctx_xfer + trace_clr(T_SAVE) +- bra main_done ++ bra #main_done + + main_not_ctx_save: + shl b32 $r15 $r14 16 + or $r15 E_BAD_COMMAND +- call error +- bra main ++ call #error ++ bra #main + + main_done: + mov $r1 0x820 +@@ -410,7 +455,7 @@ main: + clear b32 $r2 + bset $r2 31 + iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000 +- bra main ++ bra #main + + // interrupt handler + ih: +@@ -427,13 +472,13 @@ ih: + // incoming fifo command? + iord $r10 I[$r0 + 0x200] // INTR + and $r11 $r10 0x00000004 +- bra e ih_no_fifo ++ bra e #ih_no_fifo + // queue incoming fifo command for later processing + mov $r11 0x1900 +- mov $r13 cmd_queue ++ mov $r13 #cmd_queue + iord $r14 I[$r11 + 0x100] // FIFO_CMD + iord $r15 I[$r11 + 0x000] // FIFO_DATA +- call queue_put ++ call #queue_put + add b32 $r11 0x400 + mov $r14 1 + iowr I[$r11 + 0x000] $r14 // FIFO_ACK +@@ -441,18 +486,18 @@ ih: + // context switch request? + ih_no_fifo: + and $r11 $r10 0x00000100 +- bra e ih_no_ctxsw ++ bra e #ih_no_ctxsw + // enqueue a context switch for later processing +- mov $r13 cmd_queue ++ mov $r13 #cmd_queue + mov $r14 0x4001 +- call queue_put ++ call #queue_put + + // anything we didn't handle, bring it to the host's attention + ih_no_ctxsw: + mov $r11 0x104 + not b32 $r11 + and $r11 $r10 $r11 +- bra e ih_no_other ++ bra e #ih_no_other + mov $r10 0xc1c + shl b32 $r10 6 + iowr I[$r10] $r11 // INTR_UP_SET +@@ -478,11 +523,11 @@ ctx_4160s: + mov $r14 0x4160 + sethi $r14 0x400000 + mov $r15 1 +- call nv_wr32 ++ call #nv_wr32 + ctx_4160s_wait: +- call nv_rd32 ++ call #nv_rd32 + xbit $r15 $r15 4 +- bra e ctx_4160s_wait ++ bra e #ctx_4160s_wait + ret + + // Without clearing again at end of xfer, some things cause PGRAPH +@@ -492,7 +537,7 @@ ctx_4160c: + mov $r14 0x4160 + sethi $r14 0x400000 + clear b32 $r15 +- call nv_wr32 ++ call #nv_wr32 + ret + + // Again, not real sure +@@ -503,7 +548,7 @@ ctx_4170s: + mov $r14 0x4170 + sethi $r14 0x400000 + or $r15 0x10 +- call nv_wr32 ++ call #nv_wr32 + ret + + // Waits for a ctx_4170s() call to complete +@@ -511,9 +556,9 @@ ctx_4170s: + ctx_4170w: + mov $r14 0x4170 + sethi $r14 0x400000 +- call nv_rd32 ++ call #nv_rd32 + and $r15 0x10 +- bra ne ctx_4170w ++ bra ne #ctx_4170w + ret + + // Disables various things, waits a bit, and re-enables them.. +@@ -530,7 +575,7 @@ ctx_redswitch: + mov $r15 8 + ctx_redswitch_delay: + sub b32 $r15 1 +- bra ne ctx_redswitch_delay ++ bra ne #ctx_redswitch_delay + mov $r15 0x770 + iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL + ret +@@ -546,10 +591,10 @@ ctx_86c: + iowr I[$r14] $r15 // HUB(0x86c) = val + mov $r14 -0x75ec + sethi $r14 0x400000 +- call nv_wr32 // ROP(0xa14) = val ++ call #nv_wr32 // ROP(0xa14) = val + mov $r14 -0x5794 + sethi $r14 0x410000 +- call nv_wr32 // GPC(0x86c) = val ++ call #nv_wr32 // GPC(0x86c) = val + ret + + // ctx_load - load's a channel's ctxctl data, and selects its vm +@@ -561,7 +606,7 @@ ctx_load: + + // switch to channel, somewhat magic in parts.. + mov $r10 12 // DONE_UNK12 +- call wait_donez ++ call #wait_donez + mov $r1 0xa24 + shl b32 $r1 6 + iowr I[$r1 + 0x000] $r0 // 0x409a24 +@@ -576,7 +621,7 @@ ctx_load: + ctx_chan_wait_0: + iord $r4 I[$r1 + 0x100] + and $r4 0x1f +- bra ne ctx_chan_wait_0 ++ bra ne #ctx_chan_wait_0 + iowr I[$r3 + 0x000] $r2 // CHAN_CUR + + // load channel header, fetch PGRAPH context pointer +@@ -595,19 +640,19 @@ ctx_load: + sethi $r2 0x80000000 + iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vram + mov $r1 0x10 // chan + 0x0210 +- mov $r2 xfer_data ++ mov $r2 #xfer_data + sethi $r2 0x00020000 // 16 bytes + xdld $r1 $r2 + xdwait + trace_clr(T_LCHAN) + + // update current context +- ld b32 $r1 D[$r0 + xfer_data + 4] ++ ld b32 $r1 D[$r0 + #xfer_data + 4] + shl b32 $r1 24 +- ld b32 $r2 D[$r0 + xfer_data + 0] ++ ld b32 $r2 D[$r0 + #xfer_data + 0] + shr b32 $r2 8 + or $r1 $r2 +- st b32 D[$r0 + ctx_current] $r1 ++ st b32 D[$r0 + #ctx_current] $r1 + + // set transfer base to start of context, and fetch context header + trace_set(T_LCTXH) +@@ -618,7 +663,7 @@ ctx_load: + mov $r1 0xa20 + shl b32 $r1 6 + iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vm +- mov $r1 chan_data ++ mov $r1 #chan_data + sethi $r1 0x00060000 // 256 bytes + xdld $r0 $r1 + xdwait +@@ -635,10 +680,10 @@ ctx_load: + // In: $r2 channel address + // + ctx_chan: +- call ctx_4160s +- call ctx_load ++ call #ctx_4160s ++ call #ctx_load + mov $r10 12 // DONE_UNK12 +- call wait_donez ++ call #wait_donez + mov $r1 0xa10 + shl b32 $r1 6 + mov $r2 5 +@@ -646,8 +691,8 @@ ctx_chan: + ctx_chan_wait: + iord $r2 I[$r1 + 0x000] + or $r2 $r2 +- bra ne ctx_chan_wait +- call ctx_4160c ++ bra ne #ctx_chan_wait ++ call #ctx_4160c + ret + + // Execute per-context state overrides list +@@ -661,7 +706,7 @@ ctx_chan: + // + ctx_mmio_exec: + // set transfer base to be the mmio list +- ld b32 $r3 D[$r0 + chan_mmio_address] ++ ld b32 $r3 D[$r0 + #chan_mmio_address] + mov $r2 0xa04 + shl b32 $r2 6 + iowr I[$r2 + 0x000] $r3 // MEM_BASE +@@ -670,31 +715,31 @@ ctx_mmio_exec: + ctx_mmio_loop: + // fetch next 256 bytes of mmio list if necessary + and $r4 $r3 0xff +- bra ne ctx_mmio_pull +- mov $r5 xfer_data ++ bra ne #ctx_mmio_pull ++ mov $r5 #xfer_data + sethi $r5 0x00060000 // 256 bytes + xdld $r3 $r5 + xdwait + + // execute a single list entry + ctx_mmio_pull: +- ld b32 $r14 D[$r4 + xfer_data + 0x00] +- ld b32 $r15 D[$r4 + xfer_data + 0x04] +- call nv_wr32 ++ ld b32 $r14 D[$r4 + #xfer_data + 0x00] ++ ld b32 $r15 D[$r4 + #xfer_data + 0x04] ++ call #nv_wr32 + + // next! + add b32 $r3 8 + sub b32 $r1 1 +- bra ne ctx_mmio_loop ++ bra ne #ctx_mmio_loop + + // set transfer base back to the current context + ctx_mmio_done: +- ld b32 $r3 D[$r0 + ctx_current] ++ ld b32 $r3 D[$r0 + #ctx_current] + iowr I[$r2 + 0x000] $r3 // MEM_BASE + + // disable the mmio list now, we don't need/want to execute it again +- st b32 D[$r0 + chan_mmio_count] $r0 +- mov $r1 chan_data ++ st b32 D[$r0 + #chan_mmio_count] $r0 ++ mov $r1 #chan_data + sethi $r1 0x00060000 // 256 bytes + xdst $r0 $r1 + xdwait +@@ -709,46 +754,46 @@ ctx_mmio_exec: + // on load it means: "a save preceeded this load" + // + ctx_xfer: +- bra not $p1 ctx_xfer_pre +- bra $p2 ctx_xfer_pre_load ++ bra not $p1 #ctx_xfer_pre ++ bra $p2 #ctx_xfer_pre_load + ctx_xfer_pre: + mov $r15 0x10 +- call ctx_86c +- call ctx_4160s +- bra not $p1 ctx_xfer_exec ++ call #ctx_86c ++ call #ctx_4160s ++ bra not $p1 #ctx_xfer_exec + + ctx_xfer_pre_load: + mov $r15 2 +- call ctx_4170s +- call ctx_4170w +- call ctx_redswitch ++ call #ctx_4170s ++ call #ctx_4170w ++ call #ctx_redswitch + clear b32 $r15 +- call ctx_4170s +- call ctx_load ++ call #ctx_4170s ++ call #ctx_load + + // fetch context pointer, and initiate xfer on all GPCs + ctx_xfer_exec: +- ld b32 $r1 D[$r0 + ctx_current] ++ ld b32 $r1 D[$r0 + #ctx_current] + mov $r2 0x414 + shl b32 $r2 6 + iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset + mov $r14 -0x5b00 + sethi $r14 0x410000 + mov b32 $r15 $r1 +- call nv_wr32 // GPC_BCAST_WRCMD_DATA = ctx pointer ++ call #nv_wr32 // GPC_BCAST_WRCMD_DATA = ctx pointer + add b32 $r14 4 + xbit $r15 $flags $p1 + xbit $r2 $flags $p2 + shl b32 $r2 1 + or $r15 $r2 +- call nv_wr32 // GPC_BCAST_WRCMD_CMD = GPC_XFER(type) ++ call #nv_wr32 // GPC_BCAST_WRCMD_CMD = GPC_XFER(type) + + // strands + mov $r1 0x4afc + sethi $r1 0x20000 + mov $r2 0xc + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c +- call strand_wait ++ call #strand_wait + mov $r2 0x47fc + sethi $r2 0x20000 + iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00 +@@ -760,22 +805,22 @@ ctx_xfer: + xbit $r10 $flags $p1 // direction + or $r10 6 // first, last + mov $r11 0 // base = 0 +- ld b32 $r12 D[$r0 + hub_mmio_list_head] +- ld b32 $r13 D[$r0 + hub_mmio_list_tail] ++ ld b32 $r12 D[$r0 + #hub_mmio_list_head] ++ ld b32 $r13 D[$r0 + #hub_mmio_list_tail] + mov $r14 0 // not multi +- call mmctx_xfer ++ call #mmctx_xfer + + // wait for GPCs to all complete + mov $r10 8 // DONE_BAR +- call wait_doneo ++ call #wait_doneo + + // wait for strand xfer to complete +- call strand_wait ++ call #strand_wait + + // post-op +- bra $p1 ctx_xfer_post ++ bra $p1 #ctx_xfer_post + mov $r10 12 // DONE_UNK12 +- call wait_donez ++ call #wait_donez + mov $r1 0xa10 + shl b32 $r1 6 + mov $r2 5 +@@ -783,27 +828,27 @@ ctx_xfer: + ctx_xfer_post_save_wait: + iord $r2 I[$r1] + or $r2 $r2 +- bra ne ctx_xfer_post_save_wait ++ bra ne #ctx_xfer_post_save_wait + +- bra $p2 ctx_xfer_done ++ bra $p2 #ctx_xfer_done + ctx_xfer_post: + mov $r15 2 +- call ctx_4170s ++ call #ctx_4170s + clear b32 $r15 +- call ctx_86c +- call strand_post +- call ctx_4170w ++ call #ctx_86c ++ call #strand_post ++ call #ctx_4170w + clear b32 $r15 +- call ctx_4170s ++ call #ctx_4170s + +- bra not $p1 ctx_xfer_no_post_mmio +- ld b32 $r1 D[$r0 + chan_mmio_count] ++ bra not $p1 #ctx_xfer_no_post_mmio ++ ld b32 $r1 D[$r0 + #chan_mmio_count] + or $r1 $r1 +- bra e ctx_xfer_no_post_mmio +- call ctx_mmio_exec ++ bra e #ctx_xfer_no_post_mmio ++ call #ctx_mmio_exec + + ctx_xfer_no_post_mmio: +- call ctx_4160c ++ call #ctx_4160c + + ctx_xfer_done: + ret +diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h +index 241d326..c5ed307 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h ++++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h +@@ -23,19 +23,21 @@ uint32_t nvc0_grhub_data[] = { + 0x00000000, + 0x00000000, + 0x000000c0, +- 0x01340098, ++ 0x013c00a0, + 0x000000c1, +- 0x01380098, ++ 0x014000a0, + 0x000000c3, +- 0x01340098, ++ 0x013c00a0, + 0x000000c4, +- 0x01340098, ++ 0x013c00a0, + 0x000000c8, +- 0x01340098, ++ 0x013c00a0, + 0x000000ce, +- 0x01340098, ++ 0x013c00a0, + 0x000000cf, +- 0x01340098, ++ 0x013c00a0, ++ 0x000000d9, ++ 0x01dc0140, + 0x00000000, + 0x0417e91c, + 0x04400204, +@@ -77,47 +79,45 @@ uint32_t nvc0_grhub_data[] = { + 0x0c408900, + 0x00408980, + 0x044064c0, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, +- 0x00000000, ++ 0x0417e91c, ++ 0x04400204, ++ 0x24404004, ++ 0x00404044, ++ 0x34404094, ++ 0x184040d0, ++ 0x004040f8, ++ 0x08404130, ++ 0x08404150, ++ 0x04404164, ++ 0x04404178, ++ 0x1c404200, ++ 0x34404404, ++ 0x0c404460, ++ 0x00404480, ++ 0x00404498, ++ 0x0c404604, ++ 0x7c404618, ++ 0x50404698, ++ 0x044046f0, ++ 0x54404700, ++ 0x00405800, ++ 0x08405830, ++ 0x00405854, ++ 0x0c405870, ++ 0x04405a00, ++ 0x00405a18, ++ 0x00406020, ++ 0x0c406028, ++ 0x044064a8, ++ 0x104064b4, ++ 0x00407804, ++ 0x1440780c, ++ 0x004078bc, ++ 0x18408000, ++ 0x00408064, ++ 0x08408800, ++ 0x0c408900, ++ 0x00408980, + 0x00000000, + 0x00000000, + 0x00000000, +diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c +index 929aded..ce65f81 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_pm.c ++++ b/drivers/gpu/drm/nouveau/nvc0_pm.c +@@ -153,3 +153,240 @@ nvc0_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) + perflvl->vdec = read_clk(dev, 0x0e); + return 0; + } ++ ++struct nvc0_pm_clock { ++ u32 freq; ++ u32 ssel; ++ u32 mdiv; ++ u32 dsrc; ++ u32 ddiv; ++ u32 coef; ++}; ++ ++struct nvc0_pm_state { ++ struct nvc0_pm_clock eng[16]; ++}; ++ ++static u32 ++calc_div(struct drm_device *dev, int clk, u32 ref, u32 freq, u32 *ddiv) ++{ ++ u32 div = min((ref * 2) / freq, (u32)65); ++ if (div < 2) ++ div = 2; ++ ++ *ddiv = div - 2; ++ return (ref * 2) / div; ++} ++ ++static u32 ++calc_src(struct drm_device *dev, int clk, u32 freq, u32 *dsrc, u32 *ddiv) ++{ ++ u32 sclk; ++ ++ /* use one of the fixed frequencies if possible */ ++ *ddiv = 0x00000000; ++ switch (freq) { ++ case 27000: ++ case 108000: ++ *dsrc = 0x00000000; ++ if (freq == 108000) ++ *dsrc |= 0x00030000; ++ return freq; ++ case 100000: ++ *dsrc = 0x00000002; ++ return freq; ++ default: ++ *dsrc = 0x00000003; ++ break; ++ } ++ ++ /* otherwise, calculate the closest divider */ ++ sclk = read_vco(dev, clk); ++ if (clk < 7) ++ sclk = calc_div(dev, clk, sclk, freq, ddiv); ++ return sclk; ++} ++ ++static u32 ++calc_pll(struct drm_device *dev, int clk, u32 freq, u32 *coef) ++{ ++ struct pll_lims limits; ++ int N, M, P, ret; ++ ++ ret = get_pll_limits(dev, 0x137000 + (clk * 0x20), &limits); ++ if (ret) ++ return 0; ++ ++ limits.refclk = read_div(dev, clk, 0x137120, 0x137140); ++ if (!limits.refclk) ++ return 0; ++ ++ ret = nva3_calc_pll(dev, &limits, freq, &N, NULL, &M, &P); ++ if (ret <= 0) ++ return 0; ++ ++ *coef = (P << 16) | (N << 8) | M; ++ return ret; ++} ++ ++/* A (likely rather simplified and incomplete) view of the clock tree ++ * ++ * Key: ++ * ++ * S: source select ++ * D: divider ++ * P: pll ++ * F: switch ++ * ++ * Engine clocks: ++ * ++ * 137250(D) ---- 137100(F0) ---- 137160(S)/1371d0(D) ------------------- ref ++ * (F1) ---- 1370X0(P) ---- 137120(S)/137140(D) ---- ref ++ * ++ * Not all registers exist for all clocks. For example: clocks >= 8 don't ++ * have their own PLL (all tied to clock 7's PLL when in PLL mode), nor do ++ * they have the divider at 1371d0, though the source selection at 137160 ++ * still exists. You must use the divider at 137250 for these instead. ++ * ++ * Memory clock: ++ * ++ * TBD, read_mem() above is likely very wrong... ++ * ++ */ ++ ++static int ++calc_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info, u32 freq) ++{ ++ u32 src0, div0, div1D, div1P = 0; ++ u32 clk0, clk1 = 0; ++ ++ /* invalid clock domain */ ++ if (!freq) ++ return 0; ++ ++ /* first possible path, using only dividers */ ++ clk0 = calc_src(dev, clk, freq, &src0, &div0); ++ clk0 = calc_div(dev, clk, clk0, freq, &div1D); ++ ++ /* see if we can get any closer using PLLs */ ++ if (clk0 != freq && (0x00004387 & (1 << clk))) { ++ if (clk < 7) ++ clk1 = calc_pll(dev, clk, freq, &info->coef); ++ else ++ clk1 = read_pll(dev, 0x1370e0); ++ clk1 = calc_div(dev, clk, clk1, freq, &div1P); ++ } ++ ++ /* select the method which gets closest to target freq */ ++ if (abs((int)freq - clk0) <= abs((int)freq - clk1)) { ++ info->dsrc = src0; ++ if (div0) { ++ info->ddiv |= 0x80000000; ++ info->ddiv |= div0 << 8; ++ info->ddiv |= div0; ++ } ++ if (div1D) { ++ info->mdiv |= 0x80000000; ++ info->mdiv |= div1D; ++ } ++ info->ssel = 0; ++ info->freq = clk0; ++ } else { ++ if (div1P) { ++ info->mdiv |= 0x80000000; ++ info->mdiv |= div1P << 8; ++ } ++ info->ssel = (1 << clk); ++ info->freq = clk1; ++ } ++ ++ return 0; ++} ++ ++void * ++nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvc0_pm_state *info; ++ int ret; ++ ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return ERR_PTR(-ENOMEM); ++ ++ /* NFI why this is still in the performance table, the ROPCs appear ++ * to get their clock from clock 2 ("hub07", actually hub05 on this ++ * chip, but, anyway...) as well. nvatiming confirms hub05 and ROP ++ * are always the same freq with the binary driver even when the ++ * performance table says they should differ. ++ */ ++ if (dev_priv->chipset == 0xd9) ++ perflvl->rop = 0; ++ ++ if ((ret = calc_clk(dev, 0x00, &info->eng[0x00], perflvl->shader)) || ++ (ret = calc_clk(dev, 0x01, &info->eng[0x01], perflvl->rop)) || ++ (ret = calc_clk(dev, 0x02, &info->eng[0x02], perflvl->hub07)) || ++ (ret = calc_clk(dev, 0x07, &info->eng[0x07], perflvl->hub06)) || ++ (ret = calc_clk(dev, 0x08, &info->eng[0x08], perflvl->hub01)) || ++ (ret = calc_clk(dev, 0x09, &info->eng[0x09], perflvl->copy)) || ++ (ret = calc_clk(dev, 0x0c, &info->eng[0x0c], perflvl->daemon)) || ++ (ret = calc_clk(dev, 0x0e, &info->eng[0x0e], perflvl->vdec))) { ++ kfree(info); ++ return ERR_PTR(ret); ++ } ++ ++ return info; ++} ++ ++static void ++prog_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info) ++{ ++ /* program dividers at 137160/1371d0 first */ ++ if (clk < 7 && !info->ssel) { ++ nv_mask(dev, 0x1371d0 + (clk * 0x04), 0x80003f3f, info->ddiv); ++ nv_wr32(dev, 0x137160 + (clk * 0x04), info->dsrc); ++ } ++ ++ /* switch clock to non-pll mode */ ++ nv_mask(dev, 0x137100, (1 << clk), 0x00000000); ++ nv_wait(dev, 0x137100, (1 << clk), 0x00000000); ++ ++ /* reprogram pll */ ++ if (clk < 7) { ++ /* make sure it's disabled first... */ ++ u32 base = 0x137000 + (clk * 0x20); ++ u32 ctrl = nv_rd32(dev, base + 0x00); ++ if (ctrl & 0x00000001) { ++ nv_mask(dev, base + 0x00, 0x00000004, 0x00000000); ++ nv_mask(dev, base + 0x00, 0x00000001, 0x00000000); ++ } ++ /* program it to new values, if necessary */ ++ if (info->ssel) { ++ nv_wr32(dev, base + 0x04, info->coef); ++ nv_mask(dev, base + 0x00, 0x00000001, 0x00000001); ++ nv_wait(dev, base + 0x00, 0x00020000, 0x00020000); ++ nv_mask(dev, base + 0x00, 0x00020004, 0x00000004); ++ } ++ } ++ ++ /* select pll/non-pll mode, and program final clock divider */ ++ nv_mask(dev, 0x137100, (1 << clk), info->ssel); ++ nv_wait(dev, 0x137100, (1 << clk), info->ssel); ++ nv_mask(dev, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv); ++} ++ ++int ++nvc0_pm_clocks_set(struct drm_device *dev, void *data) ++{ ++ struct nvc0_pm_state *info = data; ++ int i; ++ ++ for (i = 0; i < 16; i++) { ++ if (!info->eng[i].freq) ++ continue; ++ prog_clk(dev, i, &info->eng[i]); ++ } ++ ++ kfree(info); ++ return 0; ++} +diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c +index 9e35294..30d2bd5 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_vm.c ++++ b/drivers/gpu/drm/nouveau/nvc0_vm.c +@@ -77,9 +77,11 @@ void + nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) + { ++ u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 7 : 5; ++ + pte <<= 3; + while (cnt--) { +- u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, 5); ++ u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, target); + nv_wo32(pgt, pte + 0, lower_32_bits(phys)); + nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + pte += 8; +diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c +index ce984d5..a7eef89 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_vram.c ++++ b/drivers/gpu/drm/nouveau/nvc0_vram.c +@@ -106,31 +106,32 @@ nvc0_vram_init(struct drm_device *dev) + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ +- u32 parts = nv_rd32(dev, 0x121c74); ++ u32 parts = nv_rd32(dev, 0x022438); ++ u32 pmask = nv_rd32(dev, 0x022554); + u32 bsize = nv_rd32(dev, 0x10f20c); + u32 offset, length; + bool uniform = true; + int ret, part; + + NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); +- NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize); ++ NV_DEBUG(dev, "parts 0x%08x mask 0x%08x\n", parts, pmask); ++ ++ dev_priv->vram_type = nouveau_mem_vbios_type(dev); ++ dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x10f200) & 0x00000004); + + /* read amount of vram attached to each memory controller */ +- part = 0; +- while (parts) { +- u32 psize = nv_rd32(dev, 0x11020c + (part++ * 0x1000)); +- if (psize == 0) +- continue; +- parts--; +- +- if (psize != bsize) { +- if (psize < bsize) +- bsize = psize; +- uniform = false; ++ for (part = 0; part < parts; part++) { ++ if (!(pmask & (1 << part))) { ++ u32 psize = nv_rd32(dev, 0x11020c + (part * 0x1000)); ++ if (psize != bsize) { ++ if (psize < bsize) ++ bsize = psize; ++ uniform = false; ++ } ++ ++ NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize); ++ dev_priv->vram_size += (u64)psize << 20; + } +- +- NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize); +- dev_priv->vram_size += (u64)psize << 20; + } + + /* if all controllers have the same amount attached, there's no holes */ +diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c +index 3002d82..8a555fb 100644 +--- a/drivers/gpu/drm/nouveau/nvd0_display.c ++++ b/drivers/gpu/drm/nouveau/nvd0_display.c +@@ -35,12 +35,34 @@ + #include "nouveau_fb.h" + #include "nv50_display.h" + ++#define EVO_DMA_NR 9 ++ ++#define EVO_MASTER (0x00) ++#define EVO_FLIP(c) (0x01 + (c)) ++#define EVO_OVLY(c) (0x05 + (c)) ++#define EVO_OIMM(c) (0x09 + (c)) ++#define EVO_CURS(c) (0x0d + (c)) ++ ++/* offsets in shared sync bo of various structures */ ++#define EVO_SYNC(c, o) ((c) * 0x0100 + (o)) ++#define EVO_MAST_NTFY EVO_SYNC( 0, 0x00) ++#define EVO_FLIP_SEM0(c) EVO_SYNC((c), 0x00) ++#define EVO_FLIP_SEM1(c) EVO_SYNC((c), 0x10) ++ ++struct evo { ++ int idx; ++ dma_addr_t handle; ++ u32 *ptr; ++ struct { ++ u32 offset; ++ u16 value; ++ } sem; ++}; ++ + struct nvd0_display { + struct nouveau_gpuobj *mem; +- struct { +- dma_addr_t handle; +- u32 *ptr; +- } evo[1]; ++ struct nouveau_bo *sync; ++ struct evo evo[9]; + + struct tasklet_struct tasklet; + u32 modeset; +@@ -53,6 +75,15 @@ nvd0_display(struct drm_device *dev) + return dev_priv->engine.display.priv; + } + ++static struct drm_crtc * ++nvd0_display_crtc_get(struct drm_encoder *encoder) ++{ ++ return nouveau_encoder(encoder)->crtc; ++} ++ ++/****************************************************************************** ++ * EVO channel helpers ++ *****************************************************************************/ + static inline int + evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data) + { +@@ -84,6 +115,9 @@ evo_wait(struct drm_device *dev, int id, int nr) + put = 0; + } + ++ if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) ++ NV_INFO(dev, "Evo%d: %p START\n", id, disp->evo[id].ptr + put); ++ + return disp->evo[id].ptr + put; + } + +@@ -91,104 +125,372 @@ static void + evo_kick(u32 *push, struct drm_device *dev, int id) + { + struct nvd0_display *disp = nvd0_display(dev); ++ ++ if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) { ++ u32 curp = nv_rd32(dev, 0x640000 + (id * 0x1000)) >> 2; ++ u32 *cur = disp->evo[id].ptr + curp; ++ ++ while (cur < push) ++ NV_INFO(dev, "Evo%d: 0x%08x\n", id, *cur++); ++ NV_INFO(dev, "Evo%d: %p KICK!\n", id, push); ++ } ++ + nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2); + } + + #define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m)) + #define evo_data(p,d) *((p)++) = (d) + +-static struct drm_crtc * +-nvd0_display_crtc_get(struct drm_encoder *encoder) ++static int ++evo_init_dma(struct drm_device *dev, int ch) + { +- return nouveau_encoder(encoder)->crtc; ++ struct nvd0_display *disp = nvd0_display(dev); ++ u32 flags; ++ ++ flags = 0x00000000; ++ if (ch == EVO_MASTER) ++ flags |= 0x01000000; ++ ++ nv_wr32(dev, 0x610494 + (ch * 0x0010), (disp->evo[ch].handle >> 8) | 3); ++ nv_wr32(dev, 0x610498 + (ch * 0x0010), 0x00010000); ++ nv_wr32(dev, 0x61049c + (ch * 0x0010), 0x00000001); ++ nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010); ++ nv_wr32(dev, 0x640000 + (ch * 0x1000), 0x00000000); ++ nv_wr32(dev, 0x610490 + (ch * 0x0010), 0x00000013 | flags); ++ if (!nv_wait(dev, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000)) { ++ NV_ERROR(dev, "PDISP: ch%d 0x%08x\n", ch, ++ nv_rd32(dev, 0x610490 + (ch * 0x0010))); ++ return -EBUSY; ++ } ++ ++ nv_mask(dev, 0x610090, (1 << ch), (1 << ch)); ++ nv_mask(dev, 0x6100a0, (1 << ch), (1 << ch)); ++ return 0; ++} ++ ++static void ++evo_fini_dma(struct drm_device *dev, int ch) ++{ ++ if (!(nv_rd32(dev, 0x610490 + (ch * 0x0010)) & 0x00000010)) ++ return; ++ ++ nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000000); ++ nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000003, 0x00000000); ++ nv_wait(dev, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000); ++ nv_mask(dev, 0x610090, (1 << ch), 0x00000000); ++ nv_mask(dev, 0x6100a0, (1 << ch), 0x00000000); ++} ++ ++static inline void ++evo_piow(struct drm_device *dev, int ch, u16 mthd, u32 data) ++{ ++ nv_wr32(dev, 0x640000 + (ch * 0x1000) + mthd, data); ++} ++ ++static int ++evo_init_pio(struct drm_device *dev, int ch) ++{ ++ nv_wr32(dev, 0x610490 + (ch * 0x0010), 0x00000001); ++ if (!nv_wait(dev, 0x610490 + (ch * 0x0010), 0x00010000, 0x00010000)) { ++ NV_ERROR(dev, "PDISP: ch%d 0x%08x\n", ch, ++ nv_rd32(dev, 0x610490 + (ch * 0x0010))); ++ return -EBUSY; ++ } ++ ++ nv_mask(dev, 0x610090, (1 << ch), (1 << ch)); ++ nv_mask(dev, 0x6100a0, (1 << ch), (1 << ch)); ++ return 0; ++} ++ ++static void ++evo_fini_pio(struct drm_device *dev, int ch) ++{ ++ if (!(nv_rd32(dev, 0x610490 + (ch * 0x0010)) & 0x00000001)) ++ return; ++ ++ nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010); ++ nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000001, 0x00000000); ++ nv_wait(dev, 0x610490 + (ch * 0x0010), 0x00010000, 0x00000000); ++ nv_mask(dev, 0x610090, (1 << ch), 0x00000000); ++ nv_mask(dev, 0x6100a0, (1 << ch), 0x00000000); ++} ++ ++static bool ++evo_sync_wait(void *data) ++{ ++ return nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000; ++} ++ ++static int ++evo_sync(struct drm_device *dev, int ch) ++{ ++ struct nvd0_display *disp = nvd0_display(dev); ++ u32 *push = evo_wait(dev, ch, 8); ++ if (push) { ++ nouveau_bo_wr32(disp->sync, EVO_MAST_NTFY, 0x00000000); ++ evo_mthd(push, 0x0084, 1); ++ evo_data(push, 0x80000000 | EVO_MAST_NTFY); ++ evo_mthd(push, 0x0080, 2); ++ evo_data(push, 0x00000000); ++ evo_data(push, 0x00000000); ++ evo_kick(push, dev, ch); ++ if (nv_wait_cb(dev, evo_sync_wait, disp->sync)) ++ return 0; ++ } ++ ++ return -EBUSY; ++} ++ ++/****************************************************************************** ++ * Page flipping channel ++ *****************************************************************************/ ++struct nouveau_bo * ++nvd0_display_crtc_sema(struct drm_device *dev, int crtc) ++{ ++ return nvd0_display(dev)->sync; ++} ++ ++void ++nvd0_display_flip_stop(struct drm_crtc *crtc) ++{ ++ struct nvd0_display *disp = nvd0_display(crtc->dev); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ struct evo *evo = &disp->evo[EVO_FLIP(nv_crtc->index)]; ++ u32 *push; ++ ++ push = evo_wait(crtc->dev, evo->idx, 8); ++ if (push) { ++ evo_mthd(push, 0x0084, 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x0094, 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x00c0, 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ evo_kick(push, crtc->dev, evo->idx); ++ } ++} ++ ++int ++nvd0_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, ++ struct nouveau_channel *chan, u32 swap_interval) ++{ ++ struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); ++ struct nvd0_display *disp = nvd0_display(crtc->dev); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ struct evo *evo = &disp->evo[EVO_FLIP(nv_crtc->index)]; ++ u64 offset; ++ u32 *push; ++ int ret; ++ ++ evo_sync(crtc->dev, EVO_MASTER); ++ ++ swap_interval <<= 4; ++ if (swap_interval == 0) ++ swap_interval |= 0x100; ++ ++ push = evo_wait(crtc->dev, evo->idx, 128); ++ if (unlikely(push == NULL)) ++ return -EBUSY; ++ ++ /* synchronise with the rendering channel, if necessary */ ++ if (likely(chan)) { ++ ret = RING_SPACE(chan, 10); ++ if (ret) ++ return ret; ++ ++ offset = chan->dispc_vma[nv_crtc->index].offset; ++ offset += evo->sem.offset; ++ ++ BEGIN_NVC0(chan, 2, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); ++ OUT_RING (chan, upper_32_bits(offset)); ++ OUT_RING (chan, lower_32_bits(offset)); ++ OUT_RING (chan, 0xf00d0000 | evo->sem.value); ++ OUT_RING (chan, 0x1002); ++ BEGIN_NVC0(chan, 2, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); ++ OUT_RING (chan, upper_32_bits(offset)); ++ OUT_RING (chan, lower_32_bits(offset ^ 0x10)); ++ OUT_RING (chan, 0x74b1e000); ++ OUT_RING (chan, 0x1001); ++ FIRE_RING (chan); ++ } else { ++ nouveau_bo_wr32(disp->sync, evo->sem.offset / 4, ++ 0xf00d0000 | evo->sem.value); ++ evo_sync(crtc->dev, EVO_MASTER); ++ } ++ ++ /* queue the flip */ ++ evo_mthd(push, 0x0100, 1); ++ evo_data(push, 0xfffe0000); ++ evo_mthd(push, 0x0084, 1); ++ evo_data(push, swap_interval); ++ if (!(swap_interval & 0x00000100)) { ++ evo_mthd(push, 0x00e0, 1); ++ evo_data(push, 0x40000000); ++ } ++ evo_mthd(push, 0x0088, 4); ++ evo_data(push, evo->sem.offset); ++ evo_data(push, 0xf00d0000 | evo->sem.value); ++ evo_data(push, 0x74b1e000); ++ evo_data(push, NvEvoSync); ++ evo_mthd(push, 0x00a0, 2); ++ evo_data(push, 0x00000000); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x00c0, 1); ++ evo_data(push, nv_fb->r_dma); ++ evo_mthd(push, 0x0110, 2); ++ evo_data(push, 0x00000000); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x0400, 5); ++ evo_data(push, nv_fb->nvbo->bo.offset >> 8); ++ evo_data(push, 0); ++ evo_data(push, (fb->height << 16) | fb->width); ++ evo_data(push, nv_fb->r_pitch); ++ evo_data(push, nv_fb->r_format); ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ evo_kick(push, crtc->dev, evo->idx); ++ ++ evo->sem.offset ^= 0x10; ++ evo->sem.value++; ++ return 0; + } + + /****************************************************************************** + * CRTC + *****************************************************************************/ + static int +-nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) ++nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) + { ++ struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; + struct drm_device *dev = nv_crtc->base.dev; +- u32 *push, mode; ++ struct nouveau_connector *nv_connector; ++ struct drm_connector *connector; ++ u32 *push, mode = 0x00; ++ u32 mthd; + +- mode = 0x00000000; +- if (on) { +- /* 0x11: 6bpc dynamic 2x2 +- * 0x13: 8bpc dynamic 2x2 +- * 0x19: 6bpc static 2x2 +- * 0x1b: 8bpc static 2x2 +- * 0x21: 6bpc temporal +- * 0x23: 8bpc temporal +- */ +- mode = 0x00000011; ++ nv_connector = nouveau_crtc_connector_get(nv_crtc); ++ connector = &nv_connector->base; ++ if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) { ++ if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3) ++ mode = DITHERING_MODE_DYNAMIC2X2; ++ } else { ++ mode = nv_connector->dithering_mode; + } + +- push = evo_wait(dev, 0, 4); ++ if (nv_connector->dithering_depth == DITHERING_DEPTH_AUTO) { ++ if (connector->display_info.bpc >= 8) ++ mode |= DITHERING_DEPTH_8BPC; ++ } else { ++ mode |= nv_connector->dithering_depth; ++ } ++ ++ if (dev_priv->card_type < NV_E0) ++ mthd = 0x0490 + (nv_crtc->index * 0x0300); ++ else ++ mthd = 0x04a0 + (nv_crtc->index * 0x0300); ++ ++ push = evo_wait(dev, EVO_MASTER, 4); + if (push) { +- evo_mthd(push, 0x0490 + (nv_crtc->index * 0x300), 1); ++ evo_mthd(push, mthd, 1); + evo_data(push, mode); + if (update) { + evo_mthd(push, 0x0080, 1); + evo_data(push, 0x00000000); + } +- evo_kick(push, dev, 0); ++ evo_kick(push, dev, EVO_MASTER); + } + + return 0; + } + + static int +-nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, int type, bool update) ++nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) + { +- struct drm_display_mode *mode = &nv_crtc->base.mode; ++ struct drm_display_mode *omode, *umode = &nv_crtc->base.mode; + struct drm_device *dev = nv_crtc->base.dev; ++ struct drm_crtc *crtc = &nv_crtc->base; + struct nouveau_connector *nv_connector; +- u32 *push, outX, outY; +- +- outX = mode->hdisplay; +- outY = mode->vdisplay; ++ int mode = DRM_MODE_SCALE_NONE; ++ u32 oX, oY, *push; + ++ /* start off at the resolution we programmed the crtc for, this ++ * effectively handles NONE/FULL scaling ++ */ + nv_connector = nouveau_crtc_connector_get(nv_crtc); +- if (nv_connector && nv_connector->native_mode) { +- struct drm_display_mode *native = nv_connector->native_mode; +- u32 xratio = (native->hdisplay << 19) / mode->hdisplay; +- u32 yratio = (native->vdisplay << 19) / mode->vdisplay; +- +- switch (type) { +- case DRM_MODE_SCALE_ASPECT: +- if (xratio > yratio) { +- outX = (mode->hdisplay * yratio) >> 19; +- outY = (mode->vdisplay * yratio) >> 19; +- } else { +- outX = (mode->hdisplay * xratio) >> 19; +- outY = (mode->vdisplay * xratio) >> 19; +- } +- break; +- case DRM_MODE_SCALE_FULLSCREEN: +- outX = native->hdisplay; +- outY = native->vdisplay; +- break; +- default: +- break; ++ if (nv_connector && nv_connector->native_mode) ++ mode = nv_connector->scaling_mode; ++ ++ if (mode != DRM_MODE_SCALE_NONE) ++ omode = nv_connector->native_mode; ++ else ++ omode = umode; ++ ++ oX = omode->hdisplay; ++ oY = omode->vdisplay; ++ if (omode->flags & DRM_MODE_FLAG_DBLSCAN) ++ oY *= 2; ++ ++ /* add overscan compensation if necessary, will keep the aspect ++ * ratio the same as the backend mode unless overridden by the ++ * user setting both hborder and vborder properties. ++ */ ++ if (nv_connector && ( nv_connector->underscan == UNDERSCAN_ON || ++ (nv_connector->underscan == UNDERSCAN_AUTO && ++ nv_connector->edid && ++ drm_detect_hdmi_monitor(nv_connector->edid)))) { ++ u32 bX = nv_connector->underscan_hborder; ++ u32 bY = nv_connector->underscan_vborder; ++ u32 aspect = (oY << 19) / oX; ++ ++ if (bX) { ++ oX -= (bX * 2); ++ if (bY) oY -= (bY * 2); ++ else oY = ((oX * aspect) + (aspect / 2)) >> 19; ++ } else { ++ oX -= (oX >> 4) + 32; ++ if (bY) oY -= (bY * 2); ++ else oY = ((oX * aspect) + (aspect / 2)) >> 19; + } + } + +- push = evo_wait(dev, 0, 16); ++ /* handle CENTER/ASPECT scaling, taking into account the areas ++ * removed already for overscan compensation ++ */ ++ switch (mode) { ++ case DRM_MODE_SCALE_CENTER: ++ oX = min((u32)umode->hdisplay, oX); ++ oY = min((u32)umode->vdisplay, oY); ++ /* fall-through */ ++ case DRM_MODE_SCALE_ASPECT: ++ if (oY < oX) { ++ u32 aspect = (umode->hdisplay << 19) / umode->vdisplay; ++ oX = ((oY * aspect) + (aspect / 2)) >> 19; ++ } else { ++ u32 aspect = (umode->vdisplay << 19) / umode->hdisplay; ++ oY = ((oX * aspect) + (aspect / 2)) >> 19; ++ } ++ break; ++ default: ++ break; ++ } ++ ++ push = evo_wait(dev, EVO_MASTER, 8); + if (push) { + evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3); +- evo_data(push, (outY << 16) | outX); +- evo_data(push, (outY << 16) | outX); +- evo_data(push, (outY << 16) | outX); ++ evo_data(push, (oY << 16) | oX); ++ evo_data(push, (oY << 16) | oX); ++ evo_data(push, (oY << 16) | oX); + evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1); + evo_data(push, 0x00000000); + evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1); +- evo_data(push, (mode->vdisplay << 16) | mode->hdisplay); ++ evo_data(push, (umode->vdisplay << 16) | umode->hdisplay); ++ evo_kick(push, dev, EVO_MASTER); + if (update) { +- evo_mthd(push, 0x0080, 1); +- evo_data(push, 0x00000000); ++ nvd0_display_flip_stop(crtc); ++ nvd0_display_flip_next(crtc, crtc->fb, NULL, 1); + } +- evo_kick(push, dev, 0); + } + + return 0; +@@ -201,7 +503,7 @@ nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb, + struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb); + u32 *push; + +- push = evo_wait(fb->dev, 0, 16); ++ push = evo_wait(fb->dev, EVO_MASTER, 16); + if (push) { + evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1); + evo_data(push, nvfb->nvbo->bo.offset >> 8); +@@ -216,7 +518,7 @@ nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb, + evo_mthd(push, 0x0080, 1); + evo_data(push, 0x00000000); + } +- evo_kick(push, fb->dev, 0); ++ evo_kick(push, fb->dev, EVO_MASTER); + } + + nv_crtc->fb.tile_flags = nvfb->r_dma; +@@ -227,7 +529,7 @@ static void + nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update) + { + struct drm_device *dev = nv_crtc->base.dev; +- u32 *push = evo_wait(dev, 0, 16); ++ u32 *push = evo_wait(dev, EVO_MASTER, 16); + if (push) { + if (show) { + evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2); +@@ -247,7 +549,7 @@ nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update) + evo_data(push, 0x00000000); + } + +- evo_kick(push, dev, 0); ++ evo_kick(push, dev, EVO_MASTER); + } + } + +@@ -262,7 +564,9 @@ nvd0_crtc_prepare(struct drm_crtc *crtc) + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + u32 *push; + +- push = evo_wait(crtc->dev, 0, 2); ++ nvd0_display_flip_stop(crtc); ++ ++ push = evo_wait(crtc->dev, EVO_MASTER, 2); + if (push) { + evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); + evo_data(push, 0x00000000); +@@ -270,7 +574,7 @@ nvd0_crtc_prepare(struct drm_crtc *crtc) + evo_data(push, 0x03000000); + evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1); + evo_data(push, 0x00000000); +- evo_kick(push, crtc->dev, 0); ++ evo_kick(push, crtc->dev, EVO_MASTER); + } + + nvd0_crtc_cursor_show(nv_crtc, false, false); +@@ -282,7 +586,7 @@ nvd0_crtc_commit(struct drm_crtc *crtc) + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + u32 *push; + +- push = evo_wait(crtc->dev, 0, 32); ++ push = evo_wait(crtc->dev, EVO_MASTER, 32); + if (push) { + evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); + evo_data(push, nv_crtc->fb.tile_flags); +@@ -295,10 +599,11 @@ nvd0_crtc_commit(struct drm_crtc *crtc) + evo_data(push, NvEvoVRAM); + evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1); + evo_data(push, 0xffffff00); +- evo_kick(push, crtc->dev, 0); ++ evo_kick(push, crtc->dev, EVO_MASTER); + } + + nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, true); ++ nvd0_display_flip_next(crtc, crtc->fb, NULL, 1); + } + + static bool +@@ -333,53 +638,61 @@ nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, + { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct nouveau_connector *nv_connector; +- u32 htotal = mode->htotal; +- u32 vtotal = mode->vtotal; +- u32 hsyncw = mode->hsync_end - mode->hsync_start - 1; +- u32 vsyncw = mode->vsync_end - mode->vsync_start - 1; +- u32 hfrntp = mode->hsync_start - mode->hdisplay; +- u32 vfrntp = mode->vsync_start - mode->vdisplay; +- u32 hbackp = mode->htotal - mode->hsync_end; +- u32 vbackp = mode->vtotal - mode->vsync_end; +- u32 hss2be = hsyncw + hbackp; +- u32 vss2be = vsyncw + vbackp; +- u32 hss2de = htotal - hfrntp; +- u32 vss2de = vtotal - vfrntp; +- u32 syncs, *push; ++ u32 ilace = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 1; ++ u32 vscan = (mode->flags & DRM_MODE_FLAG_DBLSCAN) ? 2 : 1; ++ u32 hactive, hsynce, hbackp, hfrontp, hblanke, hblanks; ++ u32 vactive, vsynce, vbackp, vfrontp, vblanke, vblanks; ++ u32 vblan2e = 0, vblan2s = 1; ++ u32 *push; + int ret; + +- syncs = 0x00000001; +- if (mode->flags & DRM_MODE_FLAG_NHSYNC) +- syncs |= 0x00000008; +- if (mode->flags & DRM_MODE_FLAG_NVSYNC) +- syncs |= 0x00000010; ++ hactive = mode->htotal; ++ hsynce = mode->hsync_end - mode->hsync_start - 1; ++ hbackp = mode->htotal - mode->hsync_end; ++ hblanke = hsynce + hbackp; ++ hfrontp = mode->hsync_start - mode->hdisplay; ++ hblanks = mode->htotal - hfrontp - 1; ++ ++ vactive = mode->vtotal * vscan / ilace; ++ vsynce = ((mode->vsync_end - mode->vsync_start) * vscan / ilace) - 1; ++ vbackp = (mode->vtotal - mode->vsync_end) * vscan / ilace; ++ vblanke = vsynce + vbackp; ++ vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace; ++ vblanks = vactive - vfrontp - 1; ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) { ++ vblan2e = vactive + vsynce + vbackp; ++ vblan2s = vblan2e + (mode->vdisplay * vscan / ilace); ++ vactive = (vactive * 2) + 1; ++ } + + ret = nvd0_crtc_swap_fbs(crtc, old_fb); + if (ret) + return ret; + +- push = evo_wait(crtc->dev, 0, 64); ++ push = evo_wait(crtc->dev, EVO_MASTER, 64); + if (push) { +- evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 5); ++ evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 6); + evo_data(push, 0x00000000); +- evo_data(push, (vtotal << 16) | htotal); +- evo_data(push, (vsyncw << 16) | hsyncw); +- evo_data(push, (vss2be << 16) | hss2be); +- evo_data(push, (vss2de << 16) | hss2de); ++ evo_data(push, (vactive << 16) | hactive); ++ evo_data(push, ( vsynce << 16) | hsynce); ++ evo_data(push, (vblanke << 16) | hblanke); ++ evo_data(push, (vblanks << 16) | hblanks); ++ evo_data(push, (vblan2e << 16) | vblan2s); + evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1); + evo_data(push, 0x00000000); /* ??? */ + evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3); + evo_data(push, mode->clock * 1000); + evo_data(push, 0x00200000); /* ??? */ + evo_data(push, mode->clock * 1000); +- evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 1); +- evo_data(push, syncs); +- evo_kick(push, crtc->dev, 0); ++ evo_mthd(push, 0x04d0 + (nv_crtc->index * 0x300), 2); ++ evo_data(push, 0x00000311); ++ evo_data(push, 0x00000100); ++ evo_kick(push, crtc->dev, EVO_MASTER); + } + + nv_connector = nouveau_crtc_connector_get(nv_crtc); +- nvd0_crtc_set_dither(nv_crtc, nv_connector->use_dithering, false); +- nvd0_crtc_set_scale(nv_crtc, nv_connector->scaling_mode, false); ++ nvd0_crtc_set_dither(nv_crtc, false); ++ nvd0_crtc_set_scale(nv_crtc, false); + nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, false); + return 0; + } +@@ -400,7 +713,9 @@ nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + if (ret) + return ret; + ++ nvd0_display_flip_stop(crtc); + nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, true); ++ nvd0_display_flip_next(crtc, crtc->fb, NULL, 1); + return 0; + } + +@@ -410,6 +725,7 @@ nvd0_crtc_mode_set_base_atomic(struct drm_crtc *crtc, + enum mode_set_atomic state) + { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ nvd0_display_flip_stop(crtc); + nvd0_crtc_set_image(nv_crtc, fb, x, y, true); + return 0; + } +@@ -472,10 +788,10 @@ static int + nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) + { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); +- const u32 data = (y << 16) | (x & 0xffff); ++ int ch = EVO_CURS(nv_crtc->index); + +- nv_wr32(crtc->dev, 0x64d084 + (nv_crtc->index * 0x1000), data); +- nv_wr32(crtc->dev, 0x64d080 + (nv_crtc->index * 0x1000), 0x00000000); ++ evo_piow(crtc->dev, ch, 0x0084, (y << 16) | (x & 0xffff)); ++ evo_piow(crtc->dev, ch, 0x0080, 0x00000000); + return 0; + } + +@@ -525,6 +841,7 @@ static const struct drm_crtc_funcs nvd0_crtc_func = { + .gamma_set = nvd0_crtc_gamma_set, + .set_config = drm_crtc_helper_set_config, + .destroy = nvd0_crtc_destroy, ++ .page_flip = nouveau_crtc_page_flip, + }; + + static void +@@ -640,11 +957,6 @@ nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, + } + + static void +-nvd0_dac_prepare(struct drm_encoder *encoder) +-{ +-} +- +-static void + nvd0_dac_commit(struct drm_encoder *encoder) + { + } +@@ -655,16 +967,29 @@ nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); +- u32 *push; ++ u32 syncs, magic, *push; ++ ++ syncs = 0x00000001; ++ if (mode->flags & DRM_MODE_FLAG_NHSYNC) ++ syncs |= 0x00000008; ++ if (mode->flags & DRM_MODE_FLAG_NVSYNC) ++ syncs |= 0x00000010; ++ ++ magic = 0x31ec6000 | (nv_crtc->index << 25); ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) ++ magic |= 0x00000001; + + nvd0_dac_dpms(encoder, DRM_MODE_DPMS_ON); + +- push = evo_wait(encoder->dev, 0, 4); ++ push = evo_wait(encoder->dev, EVO_MASTER, 8); + if (push) { +- evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 2); ++ evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2); ++ evo_data(push, syncs); ++ evo_data(push, magic); ++ evo_mthd(push, 0x0180 + (nv_encoder->or * 0x020), 2); + evo_data(push, 1 << nv_crtc->index); + evo_data(push, 0x00ff); +- evo_kick(push, encoder->dev, 0); ++ evo_kick(push, encoder->dev, EVO_MASTER); + } + + nv_encoder->crtc = encoder->crtc; +@@ -680,13 +1005,13 @@ nvd0_dac_disconnect(struct drm_encoder *encoder) + if (nv_encoder->crtc) { + nvd0_crtc_prepare(nv_encoder->crtc); + +- push = evo_wait(dev, 0, 4); ++ push = evo_wait(dev, EVO_MASTER, 4); + if (push) { + evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 1); + evo_data(push, 0x00000000); + evo_mthd(push, 0x0080, 1); + evo_data(push, 0x00000000); +- evo_kick(push, dev, 0); ++ evo_kick(push, dev, EVO_MASTER); + } + + nv_encoder->crtc = NULL; +@@ -724,7 +1049,7 @@ nvd0_dac_destroy(struct drm_encoder *encoder) + static const struct drm_encoder_helper_funcs nvd0_dac_hfunc = { + .dpms = nvd0_dac_dpms, + .mode_fixup = nvd0_dac_mode_fixup, +- .prepare = nvd0_dac_prepare, ++ .prepare = nvd0_dac_disconnect, + .commit = nvd0_dac_commit, + .mode_set = nvd0_dac_mode_set, + .disable = nvd0_dac_disconnect, +@@ -760,8 +1085,253 @@ nvd0_dac_create(struct drm_connector *connector, struct dcb_entry *dcbe) + } + + /****************************************************************************** ++ * Audio ++ *****************************************************************************/ ++static void ++nvd0_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_connector *nv_connector; ++ struct drm_device *dev = encoder->dev; ++ int i, or = nv_encoder->or * 0x30; ++ ++ nv_connector = nouveau_encoder_connector_get(nv_encoder); ++ if (!drm_detect_monitor_audio(nv_connector->edid)) ++ return; ++ ++ nv_mask(dev, 0x10ec10 + or, 0x80000003, 0x80000001); ++ ++ drm_edid_to_eld(&nv_connector->base, nv_connector->edid); ++ if (nv_connector->base.eld[0]) { ++ u8 *eld = nv_connector->base.eld; ++ ++ for (i = 0; i < eld[2] * 4; i++) ++ nv_wr32(dev, 0x10ec00 + or, (i << 8) | eld[i]); ++ for (i = eld[2] * 4; i < 0x60; i++) ++ nv_wr32(dev, 0x10ec00 + or, (i << 8) | 0x00); ++ ++ nv_mask(dev, 0x10ec10 + or, 0x80000002, 0x80000002); ++ } ++} ++ ++static void ++nvd0_audio_disconnect(struct drm_encoder *encoder) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ int or = nv_encoder->or * 0x30; ++ ++ nv_mask(dev, 0x10ec10 + or, 0x80000003, 0x80000000); ++} ++ ++/****************************************************************************** ++ * HDMI ++ *****************************************************************************/ ++static void ++nvd0_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); ++ struct nouveau_connector *nv_connector; ++ struct drm_device *dev = encoder->dev; ++ int head = nv_crtc->index * 0x800; ++ u32 rekey = 56; /* binary driver, and tegra constant */ ++ u32 max_ac_packet; ++ ++ nv_connector = nouveau_encoder_connector_get(nv_encoder); ++ if (!drm_detect_hdmi_monitor(nv_connector->edid)) ++ return; ++ ++ max_ac_packet = mode->htotal - mode->hdisplay; ++ max_ac_packet -= rekey; ++ max_ac_packet -= 18; /* constant from tegra */ ++ max_ac_packet /= 32; ++ ++ /* AVI InfoFrame */ ++ nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000000); ++ nv_wr32(dev, 0x61671c + head, 0x000d0282); ++ nv_wr32(dev, 0x616720 + head, 0x0000006f); ++ nv_wr32(dev, 0x616724 + head, 0x00000000); ++ nv_wr32(dev, 0x616728 + head, 0x00000000); ++ nv_wr32(dev, 0x61672c + head, 0x00000000); ++ nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000001); ++ ++ /* ??? InfoFrame? */ ++ nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000000); ++ nv_wr32(dev, 0x6167ac + head, 0x00000010); ++ nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000001); ++ ++ /* HDMI_CTRL */ ++ nv_mask(dev, 0x616798 + head, 0x401f007f, 0x40000000 | rekey | ++ max_ac_packet << 16); ++ ++ /* NFI, audio doesn't work without it though.. */ ++ nv_mask(dev, 0x616548 + head, 0x00000070, 0x00000000); ++ ++ nvd0_audio_mode_set(encoder, mode); ++} ++ ++static void ++nvd0_hdmi_disconnect(struct drm_encoder *encoder) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); ++ struct drm_device *dev = encoder->dev; ++ int head = nv_crtc->index * 0x800; ++ ++ nvd0_audio_disconnect(encoder); ++ ++ nv_mask(dev, 0x616798 + head, 0x40000000, 0x00000000); ++ nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000000); ++ nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000000); ++} ++ ++/****************************************************************************** + * SOR + *****************************************************************************/ ++static inline u32 ++nvd0_sor_dp_lane_map(struct drm_device *dev, struct dcb_entry *dcb, u8 lane) ++{ ++ static const u8 nvd0[] = { 16, 8, 0, 24 }; ++ return nvd0[lane]; ++} ++ ++static void ++nvd0_sor_dp_train_set(struct drm_device *dev, struct dcb_entry *dcb, u8 pattern) ++{ ++ const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); ++ const u32 loff = (or * 0x800) + (link * 0x80); ++ nv_mask(dev, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern); ++} ++ ++static void ++nvd0_sor_dp_train_adj(struct drm_device *dev, struct dcb_entry *dcb, ++ u8 lane, u8 swing, u8 preem) ++{ ++ const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); ++ const u32 loff = (or * 0x800) + (link * 0x80); ++ u32 shift = nvd0_sor_dp_lane_map(dev, dcb, lane); ++ u32 mask = 0x000000ff << shift; ++ u8 *table, *entry, *config = NULL; ++ ++ switch (swing) { ++ case 0: preem += 0; break; ++ case 1: preem += 4; break; ++ case 2: preem += 7; break; ++ case 3: preem += 9; break; ++ } ++ ++ table = nouveau_dp_bios_data(dev, dcb, &entry); ++ if (table) { ++ if (table[0] == 0x30) { ++ config = entry + table[4]; ++ config += table[5] * preem; ++ } else ++ if (table[0] == 0x40) { ++ config = table + table[1]; ++ config += table[2] * table[3]; ++ config += table[6] * preem; ++ } ++ } ++ ++ if (!config) { ++ NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n"); ++ return; ++ } ++ ++ nv_mask(dev, 0x61c118 + loff, mask, config[1] << shift); ++ nv_mask(dev, 0x61c120 + loff, mask, config[2] << shift); ++ nv_mask(dev, 0x61c130 + loff, 0x0000ff00, config[3] << 8); ++ nv_mask(dev, 0x61c13c + loff, 0x00000000, 0x00000000); ++} ++ ++static void ++nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_entry *dcb, int crtc, ++ int link_nr, u32 link_bw, bool enhframe) ++{ ++ const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); ++ const u32 loff = (or * 0x800) + (link * 0x80); ++ const u32 soff = (or * 0x800); ++ u32 dpctrl = nv_rd32(dev, 0x61c10c + loff) & ~0x001f4000; ++ u32 clksor = nv_rd32(dev, 0x612300 + soff) & ~0x007c0000; ++ u32 script = 0x0000, lane_mask = 0; ++ u8 *table, *entry; ++ int i; ++ ++ link_bw /= 27000; ++ ++ table = nouveau_dp_bios_data(dev, dcb, &entry); ++ if (table) { ++ if (table[0] == 0x30) entry = ROMPTR(dev, entry[10]); ++ else if (table[0] == 0x40) entry = ROMPTR(dev, entry[9]); ++ else entry = NULL; ++ ++ while (entry) { ++ if (entry[0] >= link_bw) ++ break; ++ entry += 3; ++ } ++ ++ nouveau_bios_run_init_table(dev, script, dcb, crtc); ++ } ++ ++ clksor |= link_bw << 18; ++ dpctrl |= ((1 << link_nr) - 1) << 16; ++ if (enhframe) ++ dpctrl |= 0x00004000; ++ ++ for (i = 0; i < link_nr; i++) ++ lane_mask |= 1 << (nvd0_sor_dp_lane_map(dev, dcb, i) >> 3); ++ ++ nv_wr32(dev, 0x612300 + soff, clksor); ++ nv_wr32(dev, 0x61c10c + loff, dpctrl); ++ nv_mask(dev, 0x61c130 + loff, 0x0000000f, lane_mask); ++} ++ ++static void ++nvd0_sor_dp_link_get(struct drm_device *dev, struct dcb_entry *dcb, ++ u32 *link_nr, u32 *link_bw) ++{ ++ const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); ++ const u32 loff = (or * 0x800) + (link * 0x80); ++ const u32 soff = (or * 0x800); ++ u32 dpctrl = nv_rd32(dev, 0x61c10c + loff) & 0x000f0000; ++ u32 clksor = nv_rd32(dev, 0x612300 + soff); ++ ++ if (dpctrl > 0x00030000) *link_nr = 4; ++ else if (dpctrl > 0x00010000) *link_nr = 2; ++ else *link_nr = 1; ++ ++ *link_bw = (clksor & 0x007c0000) >> 18; ++ *link_bw *= 27000; ++} ++ ++static void ++nvd0_sor_dp_calc_tu(struct drm_device *dev, struct dcb_entry *dcb, ++ u32 crtc, u32 datarate) ++{ ++ const u32 symbol = 100000; ++ const u32 TU = 64; ++ u32 link_nr, link_bw; ++ u64 ratio, value; ++ ++ nvd0_sor_dp_link_get(dev, dcb, &link_nr, &link_bw); ++ ++ ratio = datarate; ++ ratio *= symbol; ++ do_div(ratio, link_nr * link_bw); ++ ++ value = (symbol - ratio) * TU; ++ value *= ratio; ++ do_div(value, symbol); ++ do_div(value, symbol); ++ ++ value += 5; ++ value |= 0x08000000; ++ ++ nv_wr32(dev, 0x616610 + (crtc * 0x800), value); ++} ++ + static void + nvd0_sor_dpms(struct drm_encoder *encoder, int mode) + { +@@ -794,6 +1364,16 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) + nv_mask(dev, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl); + nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); + nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000); ++ ++ if (nv_encoder->dcb->type == OUTPUT_DP) { ++ struct dp_train_func func = { ++ .link_set = nvd0_sor_dp_link_set, ++ .train_set = nvd0_sor_dp_train_set, ++ .train_adj = nvd0_sor_dp_train_adj ++ }; ++ ++ nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, &func); ++ } + } + + static bool +@@ -816,8 +1396,37 @@ nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, + } + + static void ++nvd0_sor_disconnect(struct drm_encoder *encoder) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ u32 *push; ++ ++ if (nv_encoder->crtc) { ++ nvd0_crtc_prepare(nv_encoder->crtc); ++ ++ push = evo_wait(dev, EVO_MASTER, 4); ++ if (push) { ++ evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ evo_kick(push, dev, EVO_MASTER); ++ } ++ ++ nvd0_hdmi_disconnect(encoder); ++ ++ nv_encoder->crtc = NULL; ++ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; ++ } ++} ++ ++static void + nvd0_sor_prepare(struct drm_encoder *encoder) + { ++ nvd0_sor_disconnect(encoder); ++ if (nouveau_encoder(encoder)->dcb->type == OUTPUT_DP) ++ evo_sync(encoder->dev, EVO_MASTER); + } + + static void +@@ -829,13 +1438,25 @@ static void + nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, + struct drm_display_mode *mode) + { +- struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; ++ struct drm_device *dev = encoder->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); + struct nouveau_connector *nv_connector; + struct nvbios *bios = &dev_priv->vbios; + u32 mode_ctrl = (1 << nv_crtc->index); +- u32 *push, or_config; ++ u32 syncs, magic, *push; ++ u32 or_config; ++ ++ syncs = 0x00000001; ++ if (mode->flags & DRM_MODE_FLAG_NHSYNC) ++ syncs |= 0x00000008; ++ if (mode->flags & DRM_MODE_FLAG_NVSYNC) ++ syncs |= 0x00000010; ++ ++ magic = 0x31ec6000 | (nv_crtc->index << 25); ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) ++ magic |= 0x00000001; + + nv_connector = nouveau_encoder_connector_get(nv_encoder); + switch (nv_encoder->dcb->type) { +@@ -852,6 +1473,8 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, + or_config = (mode_ctrl & 0x00000f00) >> 8; + if (mode->clock >= 165000) + or_config |= 0x0100; ++ ++ nvd0_hdmi_mode_set(encoder, mode); + break; + case OUTPUT_LVDS: + or_config = (mode_ctrl & 0x00000f00) >> 8; +@@ -861,7 +1484,7 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, + if (bios->fp.if_is_24bit) + or_config |= 0x0200; + } else { +- if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) { ++ if (nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) { + if (((u8 *)nv_connector->edid)[121] == 2) + or_config |= 0x0100; + } else +@@ -882,6 +1505,22 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, + + } + break; ++ case OUTPUT_DP: ++ if (nv_connector->base.display_info.bpc == 6) { ++ nv_encoder->dp.datarate = mode->clock * 18 / 8; ++ syncs |= 0x00000140; ++ } else { ++ nv_encoder->dp.datarate = mode->clock * 24 / 8; ++ syncs |= 0x00000180; ++ } ++ ++ if (nv_encoder->dcb->sorconf.link & 1) ++ mode_ctrl |= 0x00000800; ++ else ++ mode_ctrl |= 0x00000900; ++ ++ or_config = (mode_ctrl & 0x00000f00) >> 8; ++ break; + default: + BUG_ON(1); + break; +@@ -889,42 +1528,26 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, + + nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON); + +- push = evo_wait(encoder->dev, 0, 4); ++ if (nv_encoder->dcb->type == OUTPUT_DP) { ++ nvd0_sor_dp_calc_tu(dev, nv_encoder->dcb, nv_crtc->index, ++ nv_encoder->dp.datarate); ++ } ++ ++ push = evo_wait(dev, EVO_MASTER, 8); + if (push) { +- evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 2); ++ evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2); ++ evo_data(push, syncs); ++ evo_data(push, magic); ++ evo_mthd(push, 0x0200 + (nv_encoder->or * 0x020), 2); + evo_data(push, mode_ctrl); + evo_data(push, or_config); +- evo_kick(push, encoder->dev, 0); ++ evo_kick(push, dev, EVO_MASTER); + } + + nv_encoder->crtc = encoder->crtc; + } + + static void +-nvd0_sor_disconnect(struct drm_encoder *encoder) +-{ +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct drm_device *dev = encoder->dev; +- u32 *push; +- +- if (nv_encoder->crtc) { +- nvd0_crtc_prepare(nv_encoder->crtc); +- +- push = evo_wait(dev, 0, 4); +- if (push) { +- evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1); +- evo_data(push, 0x00000000); +- evo_mthd(push, 0x0080, 1); +- evo_data(push, 0x00000000); +- evo_kick(push, dev, 0); +- } +- +- nv_encoder->crtc = NULL; +- nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; +- } +-} +- +-static void + nvd0_sor_destroy(struct drm_encoder *encoder) + { + drm_encoder_cleanup(encoder); +@@ -976,17 +1599,19 @@ static struct dcb_entry * + lookup_dcb(struct drm_device *dev, int id, u32 mc) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- int type, or, i; ++ int type, or, i, link = -1; + + if (id < 4) { + type = OUTPUT_ANALOG; + or = id; + } else { + switch (mc & 0x00000f00) { +- case 0x00000000: type = OUTPUT_LVDS; break; +- case 0x00000100: type = OUTPUT_TMDS; break; +- case 0x00000200: type = OUTPUT_TMDS; break; +- case 0x00000500: type = OUTPUT_TMDS; break; ++ case 0x00000000: link = 0; type = OUTPUT_LVDS; break; ++ case 0x00000100: link = 0; type = OUTPUT_TMDS; break; ++ case 0x00000200: link = 1; type = OUTPUT_TMDS; break; ++ case 0x00000500: link = 0; type = OUTPUT_TMDS; break; ++ case 0x00000800: link = 0; type = OUTPUT_DP; break; ++ case 0x00000900: link = 1; type = OUTPUT_DP; break; + default: + NV_ERROR(dev, "PDISP: unknown SOR mc 0x%08x\n", mc); + return NULL; +@@ -997,7 +1622,8 @@ lookup_dcb(struct drm_device *dev, int id, u32 mc) + + for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { + struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; +- if (dcb->type == type && (dcb->or & (1 << or))) ++ if (dcb->type == type && (dcb->or & (1 << or)) && ++ (link < 0 || link == !(dcb->sorconf.link & 1))) + return dcb; + } + +@@ -1048,7 +1674,9 @@ nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) + } + + pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; +- if (mask & 0x00010000) { ++ NV_DEBUG_KMS(dev, "PDISP: crtc %d pclk %d mask 0x%08x\n", ++ crtc, pclk, mask); ++ if (pclk && (mask & 0x00010000)) { + nv50_crtc_set_clock(dev, crtc, pclk); + } + +@@ -1072,6 +1700,7 @@ nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) + break; + case OUTPUT_TMDS: + case OUTPUT_LVDS: ++ case OUTPUT_DP: + if (cfg & 0x00000100) + tmp = 0x00000101; + else +@@ -1122,7 +1751,7 @@ nvd0_display_bh(unsigned long data) + { + struct drm_device *dev = (struct drm_device *)data; + struct nvd0_display *disp = nvd0_display(dev); +- u32 mask, crtc; ++ u32 mask = 0, crtc = ~0; + int i; + + if (drm_debug & (DRM_UT_DRIVER | DRM_UT_KMS)) { +@@ -1138,12 +1767,8 @@ nvd0_display_bh(unsigned long data) + } + } + +- mask = nv_rd32(dev, 0x6101d4); +- crtc = 0; +- if (!mask) { +- mask = nv_rd32(dev, 0x6109d4); +- crtc = 1; +- } ++ while (!mask && ++crtc < dev->mode_config.num_crtc) ++ mask = nv_rd32(dev, 0x6101d4 + (crtc * 0x800)); + + if (disp->modeset & 0x00000001) + nvd0_display_unk1_handler(dev, crtc, mask); +@@ -1158,6 +1783,13 @@ nvd0_display_intr(struct drm_device *dev) + { + struct nvd0_display *disp = nvd0_display(dev); + u32 intr = nv_rd32(dev, 0x610088); ++ int i; ++ ++ if (intr & 0x00000001) { ++ u32 stat = nv_rd32(dev, 0x61008c); ++ nv_wr32(dev, 0x61008c, stat); ++ intr &= ~0x00000001; ++ } + + if (intr & 0x00000002) { + u32 stat = nv_rd32(dev, 0x61009c); +@@ -1196,16 +1828,13 @@ nvd0_display_intr(struct drm_device *dev) + intr &= ~0x00100000; + } + +- if (intr & 0x01000000) { +- u32 stat = nv_rd32(dev, 0x6100bc); +- nv_wr32(dev, 0x6100bc, stat); +- intr &= ~0x01000000; +- } +- +- if (intr & 0x02000000) { +- u32 stat = nv_rd32(dev, 0x6108bc); +- nv_wr32(dev, 0x6108bc, stat); +- intr &= ~0x02000000; ++ for (i = 0; i < dev->mode_config.num_crtc; i++) { ++ u32 mask = 0x01000000 << i; ++ if (intr & mask) { ++ u32 stat = nv_rd32(dev, 0x6100bc + (i * 0x800)); ++ nv_wr32(dev, 0x6100bc + (i * 0x800), stat); ++ intr &= ~mask; ++ } + } + + if (intr) +@@ -1215,38 +1844,29 @@ nvd0_display_intr(struct drm_device *dev) + /****************************************************************************** + * Init + *****************************************************************************/ +-static void ++void + nvd0_display_fini(struct drm_device *dev) + { + int i; + +- /* fini cursors */ +- for (i = 14; i >= 13; i--) { +- if (!(nv_rd32(dev, 0x610490 + (i * 0x10)) & 0x00000001)) +- continue; +- +- nv_mask(dev, 0x610490 + (i * 0x10), 0x00000001, 0x00000000); +- nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00000000); +- nv_mask(dev, 0x610090, 1 << i, 0x00000000); +- nv_mask(dev, 0x6100a0, 1 << i, 0x00000000); ++ /* fini cursors + overlays + flips */ ++ for (i = 1; i >= 0; i--) { ++ evo_fini_pio(dev, EVO_CURS(i)); ++ evo_fini_pio(dev, EVO_OIMM(i)); ++ evo_fini_dma(dev, EVO_OVLY(i)); ++ evo_fini_dma(dev, EVO_FLIP(i)); + } + + /* fini master */ +- if (nv_rd32(dev, 0x610490) & 0x00000010) { +- nv_mask(dev, 0x610490, 0x00000010, 0x00000000); +- nv_mask(dev, 0x610490, 0x00000003, 0x00000000); +- nv_wait(dev, 0x610490, 0x80000000, 0x00000000); +- nv_mask(dev, 0x610090, 0x00000001, 0x00000000); +- nv_mask(dev, 0x6100a0, 0x00000001, 0x00000000); +- } ++ evo_fini_dma(dev, EVO_MASTER); + } + + int + nvd0_display_init(struct drm_device *dev) + { + struct nvd0_display *disp = nvd0_display(dev); ++ int ret, i; + u32 *push; +- int i; + + if (nv_rd32(dev, 0x6100ac) & 0x00000100) { + nv_wr32(dev, 0x6100ac, 0x00000100); +@@ -1271,7 +1891,7 @@ nvd0_display_init(struct drm_device *dev) + nv_wr32(dev, 0x6301c4 + (i * 0x800), sor); + } + +- for (i = 0; i < 2; i++) { ++ for (i = 0; i < dev->mode_config.num_crtc; i++) { + u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800)); + u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800)); + u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800)); +@@ -1285,36 +1905,24 @@ nvd0_display_init(struct drm_device *dev) + nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307); + + /* init master */ +- nv_wr32(dev, 0x610494, (disp->evo[0].handle >> 8) | 3); +- nv_wr32(dev, 0x610498, 0x00010000); +- nv_wr32(dev, 0x61049c, 0x00000001); +- nv_mask(dev, 0x610490, 0x00000010, 0x00000010); +- nv_wr32(dev, 0x640000, 0x00000000); +- nv_wr32(dev, 0x610490, 0x01000013); +- if (!nv_wait(dev, 0x610490, 0x80000000, 0x00000000)) { +- NV_ERROR(dev, "PDISP: master 0x%08x\n", +- nv_rd32(dev, 0x610490)); +- return -EBUSY; ++ ret = evo_init_dma(dev, EVO_MASTER); ++ if (ret) ++ goto error; ++ ++ /* init flips + overlays + cursors */ ++ for (i = 0; i < dev->mode_config.num_crtc; i++) { ++ if ((ret = evo_init_dma(dev, EVO_FLIP(i))) || ++ (ret = evo_init_dma(dev, EVO_OVLY(i))) || ++ (ret = evo_init_pio(dev, EVO_OIMM(i))) || ++ (ret = evo_init_pio(dev, EVO_CURS(i)))) ++ goto error; + } +- nv_mask(dev, 0x610090, 0x00000001, 0x00000001); +- nv_mask(dev, 0x6100a0, 0x00000001, 0x00000001); + +- /* init cursors */ +- for (i = 13; i <= 14; i++) { +- nv_wr32(dev, 0x610490 + (i * 0x10), 0x00000001); +- if (!nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00010000)) { +- NV_ERROR(dev, "PDISP: curs%d 0x%08x\n", i, +- nv_rd32(dev, 0x610490 + (i * 0x10))); +- return -EBUSY; +- } +- +- nv_mask(dev, 0x610090, 1 << i, 1 << i); +- nv_mask(dev, 0x6100a0, 1 << i, 1 << i); ++ push = evo_wait(dev, EVO_MASTER, 32); ++ if (!push) { ++ ret = -EBUSY; ++ goto error; + } +- +- push = evo_wait(dev, 0, 32); +- if (!push) +- return -EBUSY; + evo_mthd(push, 0x0088, 1); + evo_data(push, NvEvoSync); + evo_mthd(push, 0x0084, 1); +@@ -1323,9 +1931,12 @@ nvd0_display_init(struct drm_device *dev) + evo_data(push, 0x80000000); + evo_mthd(push, 0x008c, 1); + evo_data(push, 0x00000000); +- evo_kick(push, dev, 0); ++ evo_kick(push, dev, EVO_MASTER); + +- return 0; ++error: ++ if (ret) ++ nvd0_display_fini(dev); ++ return ret; + } + + void +@@ -1334,11 +1945,16 @@ nvd0_display_destroy(struct drm_device *dev) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvd0_display *disp = nvd0_display(dev); + struct pci_dev *pdev = dev->pdev; ++ int i; + +- nvd0_display_fini(dev); ++ for (i = 0; i < EVO_DMA_NR; i++) { ++ struct evo *evo = &disp->evo[i]; ++ pci_free_consistent(pdev, PAGE_SIZE, evo->ptr, evo->handle); ++ } + +- pci_free_consistent(pdev, PAGE_SIZE, disp->evo[0].ptr, disp->evo[0].handle); + nouveau_gpuobj_ref(NULL, &disp->mem); ++ nouveau_bo_unmap(disp->sync); ++ nouveau_bo_ref(NULL, &disp->sync); + nouveau_irq_unregister(dev, 26); + + dev_priv->engine.display.priv = NULL; +@@ -1355,7 +1971,7 @@ nvd0_display_create(struct drm_device *dev) + struct pci_dev *pdev = dev->pdev; + struct nvd0_display *disp; + struct dcb_entry *dcbe; +- int ret, i; ++ int crtcs, ret, i; + + disp = kzalloc(sizeof(*disp), GFP_KERNEL); + if (!disp) +@@ -1363,7 +1979,8 @@ nvd0_display_create(struct drm_device *dev) + dev_priv->engine.display.priv = disp; + + /* create crtc objects to represent the hw heads */ +- for (i = 0; i < 2; i++) { ++ crtcs = nv_rd32(dev, 0x022448); ++ for (i = 0; i < crtcs; i++) { + ret = nvd0_crtc_create(dev, i); + if (ret) + goto out; +@@ -1384,6 +2001,7 @@ nvd0_display_create(struct drm_device *dev) + switch (dcbe->type) { + case OUTPUT_TMDS: + case OUTPUT_LVDS: ++ case OUTPUT_DP: + nvd0_sor_create(connector, dcbe); + break; + case OUTPUT_ANALOG: +@@ -1410,61 +2028,83 @@ nvd0_display_create(struct drm_device *dev) + tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev); + nouveau_irq_register(dev, 26, nvd0_display_intr); + ++ /* small shared memory area we use for notifiers and semaphores */ ++ ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, ++ 0, 0x0000, &disp->sync); ++ if (!ret) { ++ ret = nouveau_bo_pin(disp->sync, TTM_PL_FLAG_VRAM); ++ if (!ret) ++ ret = nouveau_bo_map(disp->sync); ++ if (ret) ++ nouveau_bo_ref(NULL, &disp->sync); ++ } ++ ++ if (ret) ++ goto out; ++ + /* hash table and dma objects for the memory areas we care about */ + ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000, + NVOBJ_FLAG_ZERO_ALLOC, &disp->mem); + if (ret) + goto out; + +- nv_wo32(disp->mem, 0x1000, 0x00000049); +- nv_wo32(disp->mem, 0x1004, (disp->mem->vinst + 0x2000) >> 8); +- nv_wo32(disp->mem, 0x1008, (disp->mem->vinst + 0x2fff) >> 8); +- nv_wo32(disp->mem, 0x100c, 0x00000000); +- nv_wo32(disp->mem, 0x1010, 0x00000000); +- nv_wo32(disp->mem, 0x1014, 0x00000000); +- nv_wo32(disp->mem, 0x0000, NvEvoSync); +- nv_wo32(disp->mem, 0x0004, (0x1000 << 9) | 0x00000001); +- +- nv_wo32(disp->mem, 0x1020, 0x00000049); +- nv_wo32(disp->mem, 0x1024, 0x00000000); +- nv_wo32(disp->mem, 0x1028, (dev_priv->vram_size - 1) >> 8); +- nv_wo32(disp->mem, 0x102c, 0x00000000); +- nv_wo32(disp->mem, 0x1030, 0x00000000); +- nv_wo32(disp->mem, 0x1034, 0x00000000); +- nv_wo32(disp->mem, 0x0008, NvEvoVRAM); +- nv_wo32(disp->mem, 0x000c, (0x1020 << 9) | 0x00000001); +- +- nv_wo32(disp->mem, 0x1040, 0x00000009); +- nv_wo32(disp->mem, 0x1044, 0x00000000); +- nv_wo32(disp->mem, 0x1048, (dev_priv->vram_size - 1) >> 8); +- nv_wo32(disp->mem, 0x104c, 0x00000000); +- nv_wo32(disp->mem, 0x1050, 0x00000000); +- nv_wo32(disp->mem, 0x1054, 0x00000000); +- nv_wo32(disp->mem, 0x0010, NvEvoVRAM_LP); +- nv_wo32(disp->mem, 0x0014, (0x1040 << 9) | 0x00000001); +- +- nv_wo32(disp->mem, 0x1060, 0x0fe00009); +- nv_wo32(disp->mem, 0x1064, 0x00000000); +- nv_wo32(disp->mem, 0x1068, (dev_priv->vram_size - 1) >> 8); +- nv_wo32(disp->mem, 0x106c, 0x00000000); +- nv_wo32(disp->mem, 0x1070, 0x00000000); +- nv_wo32(disp->mem, 0x1074, 0x00000000); +- nv_wo32(disp->mem, 0x0018, NvEvoFB32); +- nv_wo32(disp->mem, 0x001c, (0x1060 << 9) | 0x00000001); +- +- pinstmem->flush(dev); ++ /* create evo dma channels */ ++ for (i = 0; i < EVO_DMA_NR; i++) { ++ struct evo *evo = &disp->evo[i]; ++ u64 offset = disp->sync->bo.offset; ++ u32 dmao = 0x1000 + (i * 0x100); ++ u32 hash = 0x0000 + (i * 0x040); ++ ++ evo->idx = i; ++ evo->sem.offset = EVO_SYNC(evo->idx, 0x00); ++ evo->ptr = pci_alloc_consistent(pdev, PAGE_SIZE, &evo->handle); ++ if (!evo->ptr) { ++ ret = -ENOMEM; ++ goto out; ++ } + +- /* push buffers for evo channels */ +- disp->evo[0].ptr = +- pci_alloc_consistent(pdev, PAGE_SIZE, &disp->evo[0].handle); +- if (!disp->evo[0].ptr) { +- ret = -ENOMEM; +- goto out; ++ nv_wo32(disp->mem, dmao + 0x00, 0x00000049); ++ nv_wo32(disp->mem, dmao + 0x04, (offset + 0x0000) >> 8); ++ nv_wo32(disp->mem, dmao + 0x08, (offset + 0x0fff) >> 8); ++ nv_wo32(disp->mem, dmao + 0x0c, 0x00000000); ++ nv_wo32(disp->mem, dmao + 0x10, 0x00000000); ++ nv_wo32(disp->mem, dmao + 0x14, 0x00000000); ++ nv_wo32(disp->mem, hash + 0x00, NvEvoSync); ++ nv_wo32(disp->mem, hash + 0x04, 0x00000001 | (i << 27) | ++ ((dmao + 0x00) << 9)); ++ ++ nv_wo32(disp->mem, dmao + 0x20, 0x00000049); ++ nv_wo32(disp->mem, dmao + 0x24, 0x00000000); ++ nv_wo32(disp->mem, dmao + 0x28, (dev_priv->vram_size - 1) >> 8); ++ nv_wo32(disp->mem, dmao + 0x2c, 0x00000000); ++ nv_wo32(disp->mem, dmao + 0x30, 0x00000000); ++ nv_wo32(disp->mem, dmao + 0x34, 0x00000000); ++ nv_wo32(disp->mem, hash + 0x08, NvEvoVRAM); ++ nv_wo32(disp->mem, hash + 0x0c, 0x00000001 | (i << 27) | ++ ((dmao + 0x20) << 9)); ++ ++ nv_wo32(disp->mem, dmao + 0x40, 0x00000009); ++ nv_wo32(disp->mem, dmao + 0x44, 0x00000000); ++ nv_wo32(disp->mem, dmao + 0x48, (dev_priv->vram_size - 1) >> 8); ++ nv_wo32(disp->mem, dmao + 0x4c, 0x00000000); ++ nv_wo32(disp->mem, dmao + 0x50, 0x00000000); ++ nv_wo32(disp->mem, dmao + 0x54, 0x00000000); ++ nv_wo32(disp->mem, hash + 0x10, NvEvoVRAM_LP); ++ nv_wo32(disp->mem, hash + 0x14, 0x00000001 | (i << 27) | ++ ((dmao + 0x40) << 9)); ++ ++ nv_wo32(disp->mem, dmao + 0x60, 0x0fe00009); ++ nv_wo32(disp->mem, dmao + 0x64, 0x00000000); ++ nv_wo32(disp->mem, dmao + 0x68, (dev_priv->vram_size - 1) >> 8); ++ nv_wo32(disp->mem, dmao + 0x6c, 0x00000000); ++ nv_wo32(disp->mem, dmao + 0x70, 0x00000000); ++ nv_wo32(disp->mem, dmao + 0x74, 0x00000000); ++ nv_wo32(disp->mem, hash + 0x18, NvEvoFB32); ++ nv_wo32(disp->mem, hash + 0x1c, 0x00000001 | (i << 27) | ++ ((dmao + 0x60) << 9)); + } + +- ret = nvd0_display_init(dev); +- if (ret) +- goto out; ++ pinstmem->flush(dev); + + out: + if (ret) +diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c +index bcac90b..bc29462 100644 +--- a/drivers/gpu/drm/r128/r128_cce.c ++++ b/drivers/gpu/drm/r128/r128_cce.c +@@ -155,11 +155,8 @@ static int r128_cce_load_microcode(drm_r128_private_t *dev_priv) + } + rc = request_firmware(&fw, FIRMWARE_NAME, &pdev->dev); + platform_device_unregister(pdev); +- if (rc) { +- printk(KERN_ERR "r128_cce: Failed to load firmware \"%s\"\n", +- FIRMWARE_NAME); ++ if (rc) + return rc; +- } + + if (fw->size != 256 * 8) { + printk(KERN_ERR +diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c +index 4c8796b..88718fa 100644 +--- a/drivers/gpu/drm/r128/r128_drv.c ++++ b/drivers/gpu/drm/r128/r128_drv.c +@@ -42,6 +42,20 @@ static struct pci_device_id pciidlist[] = { + r128_PCI_IDS + }; + ++static const struct file_operations r128_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .mmap = drm_mmap, ++ .poll = drm_poll, ++ .fasync = drm_fasync, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = r128_compat_ioctl, ++#endif ++ .llseek = noop_llseek, ++}; ++ + static struct drm_driver driver = { + .driver_features = + DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | +@@ -60,21 +74,7 @@ static struct drm_driver driver = { + .reclaim_buffers = drm_core_reclaim_buffers, + .ioctls = r128_ioctls, + .dma_ioctl = r128_cce_buffers, +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = drm_ioctl, +- .mmap = drm_mmap, +- .poll = drm_poll, +- .fasync = drm_fasync, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = r128_compat_ioctl, +-#endif +- .llseek = noop_llseek, +- }, +- +- ++ .fops = &r128_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, +@@ -85,6 +85,7 @@ static struct drm_driver driver = { + + int r128_driver_load(struct drm_device *dev, unsigned long flags) + { ++ pci_set_master(dev->pdev); + return drm_vblank_init(dev, 1); + } + +diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile +index cf8b4bc..9d83729 100644 +--- a/drivers/gpu/drm/radeon/Makefile ++++ b/drivers/gpu/drm/radeon/Makefile +@@ -70,7 +70,8 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ + r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ + r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \ + evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \ +- radeon_trace_points.o ni.o cayman_blit_shaders.o atombios_encoders.o ++ radeon_trace_points.o ni.o cayman_blit_shaders.o atombios_encoders.o \ ++ radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o si_blit_shaders.o + + radeon-$(CONFIG_COMPAT) += radeon_ioc32.o + radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o +@@ -78,4 +79,4 @@ radeon-$(CONFIG_ACPI) += radeon_acpi.o + + obj-$(CONFIG_DRM_RADEON)+= radeon.o + +-CFLAGS_radeon_trace_points.o := -I$(src) +\ No newline at end of file ++CFLAGS_radeon_trace_points.o := -I$(src) +diff --git a/drivers/gpu/drm/radeon/ObjectID.h b/drivers/gpu/drm/radeon/ObjectID.h +index c61c3fe..ca4b038 100644 +--- a/drivers/gpu/drm/radeon/ObjectID.h ++++ b/drivers/gpu/drm/radeon/ObjectID.h +@@ -85,6 +85,7 @@ + #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA 0x1F + #define ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 0x20 + #define ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 0x21 ++#define ENCODER_OBJECT_ID_INTERNAL_VCE 0x24 + + #define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO 0xFF + +@@ -387,6 +388,10 @@ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_NUTMEG << OBJECT_ID_SHIFT) + ++#define ENCODER_VCE_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ ++ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ ++ ENCODER_OBJECT_ID_INTERNAL_VCE << OBJECT_ID_SHIFT) ++ + /****************************************************/ + /* Connector Object ID definition - Shared with BIOS */ + /****************************************************/ +diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c +index afb351a..daa1e34 100644 +--- a/drivers/gpu/drm/radeon/atom.c ++++ b/drivers/gpu/drm/radeon/atom.c +@@ -665,6 +665,8 @@ static void atom_op_delay(atom_exec_context *ctx, int *ptr, int arg) + SDEBUG(" count: %d\n", count); + if (arg == ATOM_UNIT_MICROSEC) + udelay(count); ++ else if (!drm_can_sleep()) ++ mdelay(count); + else + msleep(count); + } +diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h +index 4760466..4b04ba3 100644 +--- a/drivers/gpu/drm/radeon/atombios.h ++++ b/drivers/gpu/drm/radeon/atombios.h +@@ -7270,6 +7270,8 @@ typedef struct _ATOM_PPLIB_THERMALCONTROLLER + #define ATOM_PP_THERMALCONTROLLER_EMC2103 13 /* 0x0D */ // Only fan control will be implemented, do NOT show this in PPGen. + #define ATOM_PP_THERMALCONTROLLER_SUMO 14 /* 0x0E */ // Sumo type, used internally + #define ATOM_PP_THERMALCONTROLLER_NISLANDS 15 ++#define ATOM_PP_THERMALCONTROLLER_SISLANDS 16 ++#define ATOM_PP_THERMALCONTROLLER_LM96163 17 + + // Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal. + // We probably should reserve the bit 0x80 for this use. +@@ -7285,6 +7287,7 @@ typedef struct _ATOM_PPLIB_STATE + UCHAR ucClockStateIndices[1]; // variable-sized + } ATOM_PPLIB_STATE; + ++ + typedef struct _ATOM_PPLIB_FANTABLE + { + UCHAR ucFanTableFormat; // Change this if the table format changes or version changes so that the other fields are not the same. +@@ -7297,12 +7300,20 @@ typedef struct _ATOM_PPLIB_FANTABLE + USHORT usPWMHigh; // The PWM value at THigh. + } ATOM_PPLIB_FANTABLE; + ++typedef struct _ATOM_PPLIB_FANTABLE2 ++{ ++ ATOM_PPLIB_FANTABLE basicTable; ++ USHORT usTMax; // The max temperature ++} ATOM_PPLIB_FANTABLE2; ++ + typedef struct _ATOM_PPLIB_EXTENDEDHEADER + { + USHORT usSize; + ULONG ulMaxEngineClock; // For Overdrive. + ULONG ulMaxMemoryClock; // For Overdrive. + // Add extra system parameters here, always adjust size to include all fields. ++ USHORT usVCETableOffset; //points to ATOM_PPLIB_VCE_Table ++ USHORT usUVDTableOffset; //points to ATOM_PPLIB_UVD_Table + } ATOM_PPLIB_EXTENDEDHEADER; + + //// ATOM_PPLIB_POWERPLAYTABLE::ulPlatformCaps +@@ -7325,6 +7336,7 @@ typedef struct _ATOM_PPLIB_EXTENDEDHEADER + #define ATOM_PP_PLATFORM_CAP_REGULATOR_HOT 0x00010000 // Enable the 'regulator hot' feature. + #define ATOM_PP_PLATFORM_CAP_BACO 0x00020000 // Does the driver supports BACO state. + ++ + typedef struct _ATOM_PPLIB_POWERPLAYTABLE + { + ATOM_COMMON_TABLE_HEADER sHeader; +@@ -7383,7 +7395,8 @@ typedef struct _ATOM_PPLIB_POWERPLAYTABLE4 + USHORT usVddciDependencyOnMCLKOffset; + USHORT usVddcDependencyOnMCLKOffset; + USHORT usMaxClockVoltageOnDCOffset; +- USHORT usReserved[2]; ++ USHORT usVddcPhaseShedLimitsTableOffset; // Points to ATOM_PPLIB_PhaseSheddingLimits_Table ++ USHORT usReserved; + } ATOM_PPLIB_POWERPLAYTABLE4, *LPATOM_PPLIB_POWERPLAYTABLE4; + + typedef struct _ATOM_PPLIB_POWERPLAYTABLE5 +@@ -7393,8 +7406,9 @@ typedef struct _ATOM_PPLIB_POWERPLAYTABLE5 + ULONG ulNearTDPLimit; + ULONG ulSQRampingThreshold; + USHORT usCACLeakageTableOffset; // Points to ATOM_PPLIB_CAC_Leakage_Table +- ULONG ulCACLeakage; // TBD, this parameter is still under discussion. Change to ulReserved if not needed. +- ULONG ulReserved; ++ ULONG ulCACLeakage; // The iLeakage for driver calculated CAC leakage table ++ USHORT usTDPODLimit; ++ USHORT usLoadLineSlope; // in milliOhms * 100 + } ATOM_PPLIB_POWERPLAYTABLE5, *LPATOM_PPLIB_POWERPLAYTABLE5; + + //// ATOM_PPLIB_NONCLOCK_INFO::usClassification +@@ -7423,6 +7437,7 @@ typedef struct _ATOM_PPLIB_POWERPLAYTABLE5 + //// ATOM_PPLIB_NONCLOCK_INFO::usClassification2 + #define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001 + #define ATOM_PPLIB_CLASSIFICATION2_ULV 0x0002 ++#define ATOM_PPLIB_CLASSIFICATION2_MVC 0x0004 //Multi-View Codec (BD-3D) + + //// ATOM_PPLIB_NONCLOCK_INFO::ulCapsAndSettings + #define ATOM_PPLIB_SINGLE_DISPLAY_ONLY 0x00000001 +@@ -7446,7 +7461,9 @@ typedef struct _ATOM_PPLIB_POWERPLAYTABLE5 + + #define ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING 0x00001000 + #define ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS 0x00002000 +-#define ATOM_PPLIB_DISALLOW_ON_DC 0x00004000 ++ ++#define ATOM_PPLIB_DISALLOW_ON_DC 0x00004000 ++ + #define ATOM_PPLIB_ENABLE_VARIBRIGHT 0x00008000 + + //memory related flags +@@ -7508,7 +7525,7 @@ typedef struct _ATOM_PPLIB_R600_CLOCK_INFO + #define ATOM_PPLIB_R600_FLAGS_UVDSAFE 2 + #define ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE 4 + #define ATOM_PPLIB_R600_FLAGS_MEMORY_ODT_OFF 8 +-#define ATOM_PPLIB_R600_FLAGS_MEMORY_DLL_OFF 16 ++#define ATOM_PPLIB_R600_FLAGS_MEMORY_DLL_OFF 16 + #define ATOM_PPLIB_R600_FLAGS_LOWPOWER 32 // On the RV770 use 'low power' setting (sequencer S0). + + typedef struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO +@@ -7527,6 +7544,24 @@ typedef struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO + + } ATOM_PPLIB_EVERGREEN_CLOCK_INFO; + ++typedef struct _ATOM_PPLIB_SI_CLOCK_INFO ++{ ++ USHORT usEngineClockLow; ++ UCHAR ucEngineClockHigh; ++ ++ USHORT usMemoryClockLow; ++ UCHAR ucMemoryClockHigh; ++ ++ USHORT usVDDC; ++ USHORT usVDDCI; ++ UCHAR ucPCIEGen; ++ UCHAR ucUnused1; ++ ++ ULONG ulFlags; // ATOM_PPLIB_SI_FLAGS_*, no flag is necessary for now ++ ++} ATOM_PPLIB_SI_CLOCK_INFO; ++ ++ + typedef struct _ATOM_PPLIB_RS780_CLOCK_INFO + + { +@@ -7539,7 +7574,7 @@ typedef struct _ATOM_PPLIB_RS780_CLOCK_INFO + UCHAR ucPadding; // For proper alignment and size. + USHORT usVDDC; // For the 780, use: None, Low, High, Variable + UCHAR ucMaxHTLinkWidth; // From SBIOS - {2, 4, 8, 16} +- UCHAR ucMinHTLinkWidth; // From SBIOS - {2, 4, 8, 16}. Effective only if CDLW enabled. Minimum down stream width could be bigger as display BW requirement. ++ UCHAR ucMinHTLinkWidth; // From SBIOS - {2, 4, 8, 16}. Effective only if CDLW enabled. Minimum down stream width could be bigger as display BW requriement. + USHORT usHTLinkFreq; // See definition ATOM_PPLIB_RS780_HTLINKFREQ_xxx or in MHz(>=200). + ULONG ulFlags; + } ATOM_PPLIB_RS780_CLOCK_INFO; +@@ -7561,9 +7596,7 @@ typedef struct _ATOM_PPLIB_SUMO_CLOCK_INFO{ + USHORT usEngineClockLow; //clockfrequency & 0xFFFF. The unit is in 10khz + UCHAR ucEngineClockHigh; //clockfrequency >> 16. + UCHAR vddcIndex; //2-bit vddc index; +- UCHAR leakage; //please use 8-bit absolute value, not the 6-bit % value +- //please initalize to 0 +- UCHAR rsv; ++ USHORT tdpLimit; + //please initalize to 0 + USHORT rsv1; + //please initialize to 0s +@@ -7586,7 +7619,7 @@ typedef struct _ATOM_PPLIB_STATE_V2 + UCHAR clockInfoIndex[1]; + } ATOM_PPLIB_STATE_V2; + +-typedef struct StateArray{ ++typedef struct _StateArray{ + //how many states we have + UCHAR ucNumEntries; + +@@ -7594,18 +7627,17 @@ typedef struct StateArray{ + }StateArray; + + +-typedef struct ClockInfoArray{ ++typedef struct _ClockInfoArray{ + //how many clock levels we have + UCHAR ucNumEntries; + +- //sizeof(ATOM_PPLIB_SUMO_CLOCK_INFO) ++ //sizeof(ATOM_PPLIB_CLOCK_INFO) + UCHAR ucEntrySize; + +- //this is for Sumo +- ATOM_PPLIB_SUMO_CLOCK_INFO clockInfo[1]; ++ UCHAR clockInfo[1]; + }ClockInfoArray; + +-typedef struct NonClockInfoArray{ ++typedef struct _NonClockInfoArray{ + + //how many non-clock levels we have. normally should be same as number of states + UCHAR ucNumEntries; +@@ -7644,6 +7676,124 @@ typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Table + ATOM_PPLIB_Clock_Voltage_Limit_Record entries[1]; // Dynamically allocate entries. + }ATOM_PPLIB_Clock_Voltage_Limit_Table; + ++typedef struct _ATOM_PPLIB_CAC_Leakage_Record ++{ ++ USHORT usVddc; // We use this field for the "fake" standardized VDDC for power calculations ++ ULONG ulLeakageValue; ++}ATOM_PPLIB_CAC_Leakage_Record; ++ ++typedef struct _ATOM_PPLIB_CAC_Leakage_Table ++{ ++ UCHAR ucNumEntries; // Number of entries. ++ ATOM_PPLIB_CAC_Leakage_Record entries[1]; // Dynamically allocate entries. ++}ATOM_PPLIB_CAC_Leakage_Table; ++ ++typedef struct _ATOM_PPLIB_PhaseSheddingLimits_Record ++{ ++ USHORT usVoltage; ++ USHORT usSclkLow; ++ UCHAR ucSclkHigh; ++ USHORT usMclkLow; ++ UCHAR ucMclkHigh; ++}ATOM_PPLIB_PhaseSheddingLimits_Record; ++ ++typedef struct _ATOM_PPLIB_PhaseSheddingLimits_Table ++{ ++ UCHAR ucNumEntries; // Number of entries. ++ ATOM_PPLIB_PhaseSheddingLimits_Record entries[1]; // Dynamically allocate entries. ++}ATOM_PPLIB_PhaseSheddingLimits_Table; ++ ++typedef struct _VCEClockInfo{ ++ USHORT usEVClkLow; ++ UCHAR ucEVClkHigh; ++ USHORT usECClkLow; ++ UCHAR ucECClkHigh; ++}VCEClockInfo; ++ ++typedef struct _VCEClockInfoArray{ ++ UCHAR ucNumEntries; ++ VCEClockInfo entries[1]; ++}VCEClockInfoArray; ++ ++typedef struct _ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record ++{ ++ USHORT usVoltage; ++ UCHAR ucVCEClockInfoIndex; ++}ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record; ++ ++typedef struct _ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table ++{ ++ UCHAR numEntries; ++ ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record entries[1]; ++}ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table; ++ ++typedef struct _ATOM_PPLIB_VCE_State_Record ++{ ++ UCHAR ucVCEClockInfoIndex; ++ UCHAR ucClockInfoIndex; //highest 2 bits indicates memory p-states, lower 6bits indicates index to ClockInfoArrary ++}ATOM_PPLIB_VCE_State_Record; ++ ++typedef struct _ATOM_PPLIB_VCE_State_Table ++{ ++ UCHAR numEntries; ++ ATOM_PPLIB_VCE_State_Record entries[1]; ++}ATOM_PPLIB_VCE_State_Table; ++ ++ ++typedef struct _ATOM_PPLIB_VCE_Table ++{ ++ UCHAR revid; ++// VCEClockInfoArray array; ++// ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table limits; ++// ATOM_PPLIB_VCE_State_Table states; ++}ATOM_PPLIB_VCE_Table; ++ ++ ++typedef struct _UVDClockInfo{ ++ USHORT usVClkLow; ++ UCHAR ucVClkHigh; ++ USHORT usDClkLow; ++ UCHAR ucDClkHigh; ++}UVDClockInfo; ++ ++typedef struct _UVDClockInfoArray{ ++ UCHAR ucNumEntries; ++ UVDClockInfo entries[1]; ++}UVDClockInfoArray; ++ ++typedef struct _ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record ++{ ++ USHORT usVoltage; ++ UCHAR ucUVDClockInfoIndex; ++}ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record; ++ ++typedef struct _ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table ++{ ++ UCHAR numEntries; ++ ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record entries[1]; ++}ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table; ++ ++typedef struct _ATOM_PPLIB_UVD_State_Record ++{ ++ UCHAR ucUVDClockInfoIndex; ++ UCHAR ucClockInfoIndex; //highest 2 bits indicates memory p-states, lower 6bits indicates index to ClockInfoArrary ++}ATOM_PPLIB_UVD_State_Record; ++ ++typedef struct _ATOM_PPLIB_UVD_State_Table ++{ ++ UCHAR numEntries; ++ ATOM_PPLIB_UVD_State_Record entries[1]; ++}ATOM_PPLIB_UVD_State_Table; ++ ++ ++typedef struct _ATOM_PPLIB_UVD_Table ++{ ++ UCHAR revid; ++// UVDClockInfoArray array; ++// ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table limits; ++// ATOM_PPLIB_UVD_State_Table states; ++}ATOM_PPLIB_UVD_Table; ++ + /**************************************************************************/ + + +diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c +index 76c4f2a..af6790c 100644 +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -231,6 +231,22 @@ static void atombios_blank_crtc(struct drm_crtc *crtc, int state) + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + } + ++static void atombios_powergate_crtc(struct drm_crtc *crtc, int state) ++{ ++ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); ++ struct drm_device *dev = crtc->dev; ++ struct radeon_device *rdev = dev->dev_private; ++ int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating); ++ ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args; ++ ++ memset(&args, 0, sizeof(args)); ++ ++ args.ucDispPipeId = radeon_crtc->crtc_id; ++ args.ucEnable = state; ++ ++ atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); ++} ++ + void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) + { + struct drm_device *dev = crtc->dev; +@@ -243,7 +259,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) + /* adjust pm to dpms changes BEFORE enabling crtcs */ + radeon_pm_compute_clocks(rdev); + atombios_enable_crtc(crtc, ATOM_ENABLE); +- if (ASIC_IS_DCE3(rdev)) ++ if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) + atombios_enable_crtc_memreq(crtc, ATOM_ENABLE); + atombios_blank_crtc(crtc, ATOM_DISABLE); + drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); +@@ -255,7 +271,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) + drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); + if (radeon_crtc->enabled) + atombios_blank_crtc(crtc, ATOM_ENABLE); +- if (ASIC_IS_DCE3(rdev)) ++ if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) + atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); + atombios_enable_crtc(crtc, ATOM_DISABLE); + radeon_crtc->enabled = false; +@@ -359,15 +375,12 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + } + +-static void atombios_disable_ss(struct drm_crtc *crtc) ++static void atombios_disable_ss(struct radeon_device *rdev, int pll_id) + { +- struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); +- struct drm_device *dev = crtc->dev; +- struct radeon_device *rdev = dev->dev_private; + u32 ss_cntl; + + if (ASIC_IS_DCE4(rdev)) { +- switch (radeon_crtc->pll_id) { ++ switch (pll_id) { + case ATOM_PPLL1: + ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL); + ss_cntl &= ~EVERGREEN_PxPLL_SS_EN; +@@ -383,7 +396,7 @@ static void atombios_disable_ss(struct drm_crtc *crtc) + return; + } + } else if (ASIC_IS_AVIVO(rdev)) { +- switch (radeon_crtc->pll_id) { ++ switch (pll_id) { + case ATOM_PPLL1: + ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL); + ss_cntl &= ~1; +@@ -410,16 +423,31 @@ union atom_enable_ss { + ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 v3; + }; + +-static void atombios_crtc_program_ss(struct drm_crtc *crtc, ++static void atombios_crtc_program_ss(struct radeon_device *rdev, + int enable, + int pll_id, ++ int crtc_id, + struct radeon_atom_ss *ss) + { +- struct drm_device *dev = crtc->dev; +- struct radeon_device *rdev = dev->dev_private; ++ unsigned i; + int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); + union atom_enable_ss args; + ++ if (!enable) { ++ for (i = 0; i < rdev->num_crtc; i++) { ++ if (rdev->mode_info.crtcs[i] && ++ rdev->mode_info.crtcs[i]->enabled && ++ i != crtc_id && ++ pll_id == rdev->mode_info.crtcs[i]->pll_id) { ++ /* one other crtc is using this pll don't turn ++ * off spread spectrum as it might turn off ++ * display on active crtc ++ */ ++ return; ++ } ++ } ++ } ++ + memset(&args, 0, sizeof(args)); + + if (ASIC_IS_DCE5(rdev)) { +@@ -445,7 +473,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc, + return; + } + args.v3.ucEnable = enable; +- if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK)) ++ if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev)) + args.v3.ucEnable = ATOM_DISABLE; + } else if (ASIC_IS_DCE4(rdev)) { + args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); +@@ -483,7 +511,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc, + } else if (ASIC_IS_AVIVO(rdev)) { + if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || + (ss->type & ATOM_EXTERNAL_SS_MASK)) { +- atombios_disable_ss(crtc); ++ atombios_disable_ss(rdev, pll_id); + return; + } + args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); +@@ -495,7 +523,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc, + } else { + if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || + (ss->type & ATOM_EXTERNAL_SS_MASK)) { +- atombios_disable_ss(crtc); ++ atombios_disable_ss(rdev, pll_id); + return; + } + args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); +@@ -527,6 +555,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, + int encoder_mode = 0; + u32 dp_clock = mode->clock; + int bpc = 8; ++ bool is_duallink = false; + + /* reset the pll flags */ + pll->flags = 0; +@@ -546,7 +575,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, + if (rdev->family < CHIP_RV770) + pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP; + /* use frac fb div on APUs */ +- if (ASIC_IS_DCE41(rdev)) ++ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) + pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV; + /* use frac fb div on RS780/RS880 */ + if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880)) +@@ -566,9 +595,10 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, + if (encoder->crtc == crtc) { + radeon_encoder = to_radeon_encoder(encoder); + connector = radeon_get_connector_for_encoder(encoder); +- if (connector) +- bpc = connector->display_info.bpc; ++ /* if (connector && connector->display_info.bpc) ++ bpc = connector->display_info.bpc; */ + encoder_mode = atombios_get_encoder_mode(encoder); ++ is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock); + if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || + (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) { + if (connector) { +@@ -664,7 +694,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, + if (dig->coherent_mode) + args.v3.sInput.ucDispPllConfig |= + DISPPLL_CONFIG_COHERENT_MODE; +- if (mode->clock > 165000) ++ if (is_duallink) + args.v3.sInput.ucDispPllConfig |= + DISPPLL_CONFIG_DUAL_LINK; + } +@@ -714,11 +744,9 @@ union set_pixel_clock { + /* on DCE5, make sure the voltage is high enough to support the + * required disp clk. + */ +-static void atombios_crtc_set_dcpll(struct drm_crtc *crtc, ++static void atombios_crtc_set_disp_eng_pll(struct radeon_device *rdev, + u32 dispclk) + { +- struct drm_device *dev = crtc->dev; +- struct radeon_device *rdev = dev->dev_private; + u8 frev, crev; + int index; + union set_pixel_clock args; +@@ -746,7 +774,12 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc, + * SetPixelClock provides the dividers + */ + args.v6.ulDispEngClkFreq = cpu_to_le32(dispclk); +- args.v6.ucPpll = ATOM_DCPLL; ++ if (ASIC_IS_DCE61(rdev)) ++ args.v6.ucPpll = ATOM_EXT_PLL1; ++ else if (ASIC_IS_DCE6(rdev)) ++ args.v6.ucPpll = ATOM_PPLL0; ++ else ++ args.v6.ucPpll = ATOM_DCPLL; + break; + default: + DRM_ERROR("Unknown table version %d %d\n", frev, crev); +@@ -943,7 +976,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; + int dp_clock; +- bpc = connector->display_info.bpc; ++ ++ /* if (connector->display_info.bpc) ++ bpc = connector->display_info.bpc; */ + + switch (encoder_mode) { + case ATOM_ENCODER_MODE_DP_MST: +@@ -964,13 +999,10 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode + ss_enabled = + radeon_atombios_get_ppll_ss_info(rdev, &ss, + ATOM_DP_SS_ID1); +- } else { ++ } else + ss_enabled = + radeon_atombios_get_ppll_ss_info(rdev, &ss, + ATOM_DP_SS_ID1); +- } +- /* disable spread spectrum on DCE3 DP */ +- ss_enabled = false; + } + break; + case ATOM_ENCODER_MODE_LVDS: +@@ -1015,7 +1047,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode + radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, + &ref_div, &post_div); + +- atombios_crtc_program_ss(crtc, ATOM_DISABLE, radeon_crtc->pll_id, &ss); ++ atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss); + + atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, + encoder_mode, radeon_encoder->encoder_id, mode->clock, +@@ -1038,7 +1070,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode + ss.step = step_size; + } + +- atombios_crtc_program_ss(crtc, ATOM_ENABLE, radeon_crtc->pll_id, &ss); ++ atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss); + } + } + +@@ -1055,6 +1087,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, + struct radeon_bo *rbo; + uint64_t fb_location; + uint32_t fb_format, fb_pitch_pixels, tiling_flags; ++ unsigned bankw, bankh, mtaspect, tile_split; + u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); + u32 tmp, viewport_w, viewport_h; + int r; +@@ -1145,20 +1178,13 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, + break; + } + +- switch ((tmp & 0xf000) >> 12) { +- case 0: /* 1KB rows */ +- default: +- fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB); +- break; +- case 1: /* 2KB rows */ +- fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB); +- break; +- case 2: /* 4KB rows */ +- fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB); +- break; +- } +- + fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1); ++ ++ evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split); ++ fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split); ++ fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw); ++ fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh); ++ fb_format |= EVERGREEN_GRPH_MACRO_TILE_ASPECT(mtaspect); + } else if (tiling_flags & RADEON_TILING_MICRO) + fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1); + +@@ -1203,7 +1229,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, + WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width); + WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height); + +- fb_pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8); ++ fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); + WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1); + +@@ -1372,7 +1398,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, + WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width); + WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height); + +- fb_pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8); ++ fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); + WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); + +@@ -1474,7 +1500,36 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) + struct drm_crtc *test_crtc; + uint32_t pll_in_use = 0; + +- if (ASIC_IS_DCE4(rdev)) { ++ if (ASIC_IS_DCE61(rdev)) { ++ list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { ++ if (test_encoder->crtc && (test_encoder->crtc == crtc)) { ++ struct radeon_encoder *test_radeon_encoder = ++ to_radeon_encoder(test_encoder); ++ struct radeon_encoder_atom_dig *dig = ++ test_radeon_encoder->enc_priv; ++ ++ if ((test_radeon_encoder->encoder_id == ++ ENCODER_OBJECT_ID_INTERNAL_UNIPHY) && ++ (dig->linkb == false)) /* UNIPHY A uses PPLL2 */ ++ return ATOM_PPLL2; ++ } ++ } ++ /* UNIPHY B/C/D/E/F */ ++ list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { ++ struct radeon_crtc *radeon_test_crtc; ++ ++ if (crtc == test_crtc) ++ continue; ++ ++ radeon_test_crtc = to_radeon_crtc(test_crtc); ++ if ((radeon_test_crtc->pll_id == ATOM_PPLL0) || ++ (radeon_test_crtc->pll_id == ATOM_PPLL1)) ++ pll_in_use |= (1 << radeon_test_crtc->pll_id); ++ } ++ if (!(pll_in_use & 4)) ++ return ATOM_PPLL0; ++ return ATOM_PPLL1; ++ } else if (ASIC_IS_DCE4(rdev)) { + list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { + if (test_encoder->crtc && (test_encoder->crtc == crtc)) { + /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock, +@@ -1489,6 +1544,8 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) + if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { + if (rdev->clock.dp_extclk) + return ATOM_PPLL_INVALID; ++ else if (ASIC_IS_DCE6(rdev)) ++ return ATOM_PPLL0; + else if (ASIC_IS_DCE5(rdev)) + return ATOM_DCPLL; + } +@@ -1515,6 +1572,26 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) + + } + ++void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev) ++{ ++ /* always set DCPLL */ ++ if (ASIC_IS_DCE6(rdev)) ++ atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk); ++ else if (ASIC_IS_DCE4(rdev)) { ++ struct radeon_atom_ss ss; ++ bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss, ++ ASIC_INTERNAL_SS_ON_DCPLL, ++ rdev->clock.default_dispclk); ++ if (ss_enabled) ++ atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, -1, &ss); ++ /* XXX: DCE5, make sure voltage, dispclk is high enough */ ++ atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk); ++ if (ss_enabled) ++ atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, -1, &ss); ++ } ++ ++} ++ + int atombios_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, +@@ -1536,19 +1613,6 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, + } + } + +- /* always set DCPLL */ +- if (ASIC_IS_DCE4(rdev)) { +- struct radeon_atom_ss ss; +- bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss, +- ASIC_INTERNAL_SS_ON_DCPLL, +- rdev->clock.default_dispclk); +- if (ss_enabled) +- atombios_crtc_program_ss(crtc, ATOM_DISABLE, ATOM_DCPLL, &ss); +- /* XXX: DCE5, make sure voltage, dispclk is high enough */ +- atombios_crtc_set_dcpll(crtc, rdev->clock.default_dispclk); +- if (ss_enabled) +- atombios_crtc_program_ss(crtc, ATOM_ENABLE, ATOM_DCPLL, &ss); +- } + atombios_crtc_set_pll(crtc, adjusted_mode); + + if (ASIC_IS_DCE4(rdev)) +@@ -1582,18 +1646,28 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, + static void atombios_crtc_prepare(struct drm_crtc *crtc) + { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); ++ struct drm_device *dev = crtc->dev; ++ struct radeon_device *rdev = dev->dev_private; + ++ radeon_crtc->in_mode_set = true; + /* pick pll */ + radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); + ++ /* disable crtc pair power gating before programming */ ++ if (ASIC_IS_DCE6(rdev)) ++ atombios_powergate_crtc(crtc, ATOM_DISABLE); ++ + atombios_lock_crtc(crtc, ATOM_ENABLE); + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + } + + static void atombios_crtc_commit(struct drm_crtc *crtc) + { ++ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); ++ + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); + atombios_lock_crtc(crtc, ATOM_DISABLE); ++ radeon_crtc->in_mode_set = false; + } + + static void atombios_crtc_disable(struct drm_crtc *crtc) +@@ -1605,6 +1679,8 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) + int i; + + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); ++ if (ASIC_IS_DCE6(rdev)) ++ atombios_powergate_crtc(crtc, ATOM_ENABLE); + + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->mode_info.crtcs[i] && +@@ -1625,6 +1701,12 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) + atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, + 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss); + break; ++ case ATOM_PPLL0: ++ /* disable the ppll */ ++ if (ASIC_IS_DCE61(rdev)) ++ atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, ++ 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss); ++ break; + default: + break; + } +diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c +index 3e34f1e..5325c20 100644 +--- a/drivers/gpu/drm/radeon/atombios_dp.c ++++ b/drivers/gpu/drm/radeon/atombios_dp.c +@@ -45,6 +45,41 @@ static char *pre_emph_names[] = { + }; + + /***** radeon AUX functions *****/ ++ ++/* Atom needs data in little endian format ++ * so swap as appropriate when copying data to ++ * or from atom. Note that atom operates on ++ * dw units. ++ */ ++void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le) ++{ ++#ifdef __BIG_ENDIAN ++ u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */ ++ u32 *dst32, *src32; ++ int i; ++ ++ memcpy(src_tmp, src, num_bytes); ++ src32 = (u32 *)src_tmp; ++ dst32 = (u32 *)dst_tmp; ++ if (to_le) { ++ for (i = 0; i < ((num_bytes + 3) / 4); i++) ++ dst32[i] = cpu_to_le32(src32[i]); ++ memcpy(dst, dst_tmp, num_bytes); ++ } else { ++ u8 dws = num_bytes & ~3; ++ for (i = 0; i < ((num_bytes + 3) / 4); i++) ++ dst32[i] = le32_to_cpu(src32[i]); ++ memcpy(dst, dst_tmp, dws); ++ if (num_bytes % 4) { ++ for (i = 0; i < (num_bytes % 4); i++) ++ dst[dws+i] = dst_tmp[dws+i]; ++ } ++ } ++#else ++ memcpy(dst, src, num_bytes); ++#endif ++} ++ + union aux_channel_transaction { + PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; + PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; +@@ -64,12 +99,12 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, + + memset(&args, 0, sizeof(args)); + +- base = (unsigned char *)rdev->mode_info.atom_context->scratch; ++ base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); + +- memcpy(base, send, send_bytes); ++ radeon_atom_copy_swap(base, send, send_bytes, true); + +- args.v1.lpAuxRequest = 0; +- args.v1.lpDataOut = 16; ++ args.v1.lpAuxRequest = cpu_to_le16((u16)(0 + 4)); ++ args.v1.lpDataOut = cpu_to_le16((u16)(16 + 4)); + args.v1.ucDataOutLen = 0; + args.v1.ucChannelID = chan->rec.i2c_id; + args.v1.ucDelay = delay / 10; +@@ -89,7 +124,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, + /* flags not zero */ + if (args.v1.ucReplyStatus == 2) { + DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); +- return -EIO; ++ return -EBUSY; + } + + /* error */ +@@ -103,7 +138,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, + recv_bytes = recv_size; + + if (recv && recv_size) +- memcpy(recv, base + 16, recv_bytes); ++ radeon_atom_copy_swap(recv, base + 16, recv_bytes, false); + + return recv_bytes; + } +@@ -406,10 +441,13 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], + /* get bpc from the EDID */ + static int convert_bpc_to_bpp(int bpc) + { ++#if 0 + if (bpc == 0) + return 24; + else + return bpc * 3; ++#endif ++ return 24; + } + + /* get the max pix clock supported by the link rate and lane num */ +@@ -744,7 +782,8 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) + + /* set the lane count on the sink */ + tmp = dp_info->dp_lane_count; +- if (dp_info->dpcd[0] >= 0x11) ++ if (dp_info->dpcd[DP_DPCD_REV] >= 0x11 && ++ dp_info->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP) + tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp); + +diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c +index 286f1fa..dd5c14e 100644 +--- a/drivers/gpu/drm/radeon/atombios_encoders.c ++++ b/drivers/gpu/drm/radeon/atombios_encoders.c +@@ -57,22 +57,6 @@ static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) + } + } + +-static struct drm_connector * +-radeon_get_connector_for_encoder_init(struct drm_encoder *encoder) +-{ +- struct drm_device *dev = encoder->dev; +- struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); +- struct drm_connector *connector; +- struct radeon_connector *radeon_connector; +- +- list_for_each_entry(connector, &dev->mode_config.connector_list, head) { +- radeon_connector = to_radeon_connector(connector); +- if (radeon_encoder->devices & radeon_connector->devices) +- return connector; +- } +- return NULL; +-} +- + static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +@@ -257,7 +241,7 @@ atombios_dvo_setup(struct drm_encoder *encoder, int action) + /* R4xx, R5xx */ + args.ext_tmds.sXTmdsEncoder.ucEnable = action; + +- if (radeon_encoder->pixel_clock > 165000) ++ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL; + + args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB; +@@ -269,7 +253,7 @@ atombios_dvo_setup(struct drm_encoder *encoder, int action) + /* DFP1, CRT1, TV1 depending on the type of port */ + args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX; + +- if (radeon_encoder->pixel_clock > 165000) ++ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL; + break; + case 3: +@@ -353,7 +337,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) + } else { + if (dig->linkb) + args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; +- if (radeon_encoder->pixel_clock > 165000) ++ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; + /*if (pScrn->rgbBits == 8) */ + args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; +@@ -392,7 +376,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) + } else { + if (dig->linkb) + args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; +- if (radeon_encoder->pixel_clock > 165000) ++ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; + } + break; +@@ -412,9 +396,9 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) + int + atombios_get_encoder_mode(struct drm_encoder *encoder) + { +- struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; ++ struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + struct radeon_connector_atom_dig *dig_connector; +@@ -438,13 +422,11 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ +- if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) { +- /* fix me */ +- if (ASIC_IS_DCE4(rdev)) +- return ATOM_ENCODER_MODE_DVI; +- else +- return ATOM_ENCODER_MODE_HDMI; +- } else if (radeon_connector->use_digital) ++ if (drm_detect_hdmi_monitor(radeon_connector->edid) && ++ radeon_audio && ++ !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */ ++ return ATOM_ENCODER_MODE_HDMI; ++ else if (radeon_connector->use_digital) + return ATOM_ENCODER_MODE_DVI; + else + return ATOM_ENCODER_MODE_CRT; +@@ -452,13 +434,11 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) + case DRM_MODE_CONNECTOR_DVID: + case DRM_MODE_CONNECTOR_HDMIA: + default: +- if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) { +- /* fix me */ +- if (ASIC_IS_DCE4(rdev)) +- return ATOM_ENCODER_MODE_DVI; +- else +- return ATOM_ENCODER_MODE_HDMI; +- } else ++ if (drm_detect_hdmi_monitor(radeon_connector->edid) && ++ radeon_audio && ++ !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */ ++ return ATOM_ENCODER_MODE_HDMI; ++ else + return ATOM_ENCODER_MODE_DVI; + break; + case DRM_MODE_CONNECTOR_LVDS: +@@ -469,13 +449,11 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) + if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) + return ATOM_ENCODER_MODE_DP; +- else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) { +- /* fix me */ +- if (ASIC_IS_DCE4(rdev)) +- return ATOM_ENCODER_MODE_DVI; +- else +- return ATOM_ENCODER_MODE_HDMI; +- } else ++ else if (drm_detect_hdmi_monitor(radeon_connector->edid) && ++ radeon_audio && ++ !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */ ++ return ATOM_ENCODER_MODE_HDMI; ++ else + return ATOM_ENCODER_MODE_DVI; + break; + case DRM_MODE_CONNECTOR_eDP: +@@ -510,7 +488,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) + * - 2 DIG encoder blocks. + * DIG1/2 can drive UNIPHY0/1/2 link A or link B + * +- * DCE 4.0/5.0 ++ * DCE 4.0/5.0/6.0 + * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). + * Supports up to 6 digital outputs + * - 6 DIG encoder blocks. +@@ -526,7 +504,11 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) + * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). + * Supports up to 6 digital outputs + * - 2 DIG encoder blocks. ++ * llano + * DIG1/2 can drive UNIPHY0/1/2 link A or link B ++ * ontario ++ * DIG1 drives UNIPHY0/1/2 link A ++ * DIG2 drives UNIPHY0/1/2 link B + * + * Routing + * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) +@@ -568,7 +550,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo + dp_clock = dig_connector->dp_clock; + dp_lane_count = dig_connector->dp_lane_count; + hpd_id = radeon_connector->hpd.hpd; +- bpc = connector->display_info.bpc; ++ /* bpc = connector->display_info.bpc; */ + } + + /* no dig encoder assigned */ +@@ -602,7 +584,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo + + if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)) + args.v1.ucLaneNum = dp_lane_count; +- else if (radeon_encoder->pixel_clock > 165000) ++ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v1.ucLaneNum = 8; + else + args.v1.ucLaneNum = 4; +@@ -637,7 +619,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo + + if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)) + args.v3.ucLaneNum = dp_lane_count; +- else if (radeon_encoder->pixel_clock > 165000) ++ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v3.ucLaneNum = 8; + else + args.v3.ucLaneNum = 4; +@@ -677,7 +659,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo + + if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)) + args.v4.ucLaneNum = dp_lane_count; +- else if (radeon_encoder->pixel_clock > 165000) ++ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v4.ucLaneNum = 8; + else + args.v4.ucLaneNum = 4; +@@ -734,6 +716,7 @@ union dig_transmitter_control { + DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4; ++ DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5; + }; + + void +@@ -754,6 +737,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + int connector_object_id = 0; + int igp_lane_info = 0; + int dig_encoder = dig->dig_encoder; ++ int hpd_id = RADEON_HPD_NONE; + + if (action == ATOM_TRANSMITTER_ACTION_INIT) { + connector = radeon_get_connector_for_encoder_init(encoder); +@@ -769,6 +753,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; + ++ hpd_id = radeon_connector->hpd.hpd; + dp_clock = dig_connector->dp_clock; + dp_lane_count = dig_connector->dp_lane_count; + connector_object_id = +@@ -821,7 +806,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + if (is_dp) + args.v1.usPixelClock = + cpu_to_le16(dp_clock / 10); +- else if (radeon_encoder->pixel_clock > 165000) ++ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); + else + args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); +@@ -836,7 +821,8 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + + if ((rdev->flags & RADEON_IS_IGP) && + (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { +- if (is_dp || (radeon_encoder->pixel_clock <= 165000)) { ++ if (is_dp || ++ !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) { + if (igp_lane_info & 0x1) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; + else if (igp_lane_info & 0x2) +@@ -863,7 +849,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (dig->coherent_mode) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; +- if (radeon_encoder->pixel_clock > 165000) ++ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; + } + break; +@@ -878,7 +864,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + if (is_dp) + args.v2.usPixelClock = + cpu_to_le16(dp_clock / 10); +- else if (radeon_encoder->pixel_clock > 165000) ++ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); + else + args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); +@@ -906,7 +892,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (dig->coherent_mode) + args.v2.acConfig.fCoherentMode = 1; +- if (radeon_encoder->pixel_clock > 165000) ++ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v2.acConfig.fDualLinkConnector = 1; + } + break; +@@ -921,7 +907,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + if (is_dp) + args.v3.usPixelClock = + cpu_to_le16(dp_clock / 10); +- else if (radeon_encoder->pixel_clock > 165000) ++ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); + else + args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); +@@ -929,7 +915,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + + if (is_dp) + args.v3.ucLaneNum = dp_lane_count; +- else if (radeon_encoder->pixel_clock > 165000) ++ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v3.ucLaneNum = 8; + else + args.v3.ucLaneNum = 4; +@@ -966,7 +952,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (dig->coherent_mode) + args.v3.acConfig.fCoherentMode = 1; +- if (radeon_encoder->pixel_clock > 165000) ++ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v3.acConfig.fDualLinkConnector = 1; + } + break; +@@ -981,7 +967,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + if (is_dp) + args.v4.usPixelClock = + cpu_to_le16(dp_clock / 10); +- else if (radeon_encoder->pixel_clock > 165000) ++ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); + else + args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); +@@ -989,7 +975,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + + if (is_dp) + args.v4.ucLaneNum = dp_lane_count; +- else if (radeon_encoder->pixel_clock > 165000) ++ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v4.ucLaneNum = 8; + else + args.v4.ucLaneNum = 4; +@@ -1029,10 +1015,64 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (dig->coherent_mode) + args.v4.acConfig.fCoherentMode = 1; +- if (radeon_encoder->pixel_clock > 165000) ++ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v4.acConfig.fDualLinkConnector = 1; + } + break; ++ case 5: ++ args.v5.ucAction = action; ++ if (is_dp) ++ args.v5.usSymClock = cpu_to_le16(dp_clock / 10); ++ else ++ args.v5.usSymClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); ++ ++ switch (radeon_encoder->encoder_id) { ++ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: ++ if (dig->linkb) ++ args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB; ++ else ++ args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA; ++ break; ++ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: ++ if (dig->linkb) ++ args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD; ++ else ++ args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC; ++ break; ++ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: ++ if (dig->linkb) ++ args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF; ++ else ++ args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE; ++ break; ++ } ++ if (is_dp) ++ args.v5.ucLaneNum = dp_lane_count; ++ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) ++ args.v5.ucLaneNum = 8; ++ else ++ args.v5.ucLaneNum = 4; ++ args.v5.ucConnObjId = connector_object_id; ++ args.v5.ucDigMode = atombios_get_encoder_mode(encoder); ++ ++ if (is_dp && rdev->clock.dp_extclk) ++ args.v5.asConfig.ucPhyClkSrcId = ENCODER_REFCLK_SRC_EXTCLK; ++ else ++ args.v5.asConfig.ucPhyClkSrcId = pll_id; ++ ++ if (is_dp) ++ args.v5.asConfig.ucCoherentMode = 1; /* DP requires coherent */ ++ else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { ++ if (dig->coherent_mode) ++ args.v5.asConfig.ucCoherentMode = 1; ++ } ++ if (hpd_id == RADEON_HPD_NONE) ++ args.v5.asConfig.ucHPDSel = 0; ++ else ++ args.v5.asConfig.ucHPDSel = hpd_id + 1; ++ args.v5.ucDigEncoderSel = 1 << dig_encoder; ++ args.v5.ucDPLaneSet = lane_set; ++ break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + break; +@@ -1128,7 +1168,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder, + dp_lane_count = dig_connector->dp_lane_count; + connector_object_id = + (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; +- bpc = connector->display_info.bpc; ++ /* bpc = connector->display_info.bpc; */ + } + + memset(&args, 0, sizeof(args)); +@@ -1152,7 +1192,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder, + if (dp_clock == 270000) + args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; + args.v1.sDigEncoder.ucLaneNum = dp_lane_count; +- } else if (radeon_encoder->pixel_clock > 165000) ++ } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v1.sDigEncoder.ucLaneNum = 8; + else + args.v1.sDigEncoder.ucLaneNum = 4; +@@ -1171,7 +1211,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder, + else if (dp_clock == 540000) + args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; + args.v3.sExtEncoder.ucLaneNum = dp_lane_count; +- } else if (radeon_encoder->pixel_clock > 165000) ++ } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) + args.v3.sExtEncoder.ucLaneNum = 8; + else + args.v3.sExtEncoder.ucLaneNum = 4; +@@ -1369,7 +1409,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) + ATOM_ENCODER_CMD_SETUP_PANEL_MODE, + dig->panel_mode); + if (ext_encoder) { +- if (ASIC_IS_DCE41(rdev)) ++ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); + } +@@ -1448,7 +1488,7 @@ radeon_atom_encoder_dpms_ext(struct drm_encoder *encoder, + switch (mode) { + case DRM_MODE_DPMS_ON: + default: +- if (ASIC_IS_DCE41(rdev)) { ++ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) { + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT); + atombios_external_encoder_setup(encoder, ext_encoder, +@@ -1459,7 +1499,7 @@ radeon_atom_encoder_dpms_ext(struct drm_encoder *encoder, + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: +- if (ASIC_IS_DCE41(rdev)) { ++ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) { + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING); + atombios_external_encoder_setup(encoder, ext_encoder, +@@ -1741,13 +1781,34 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *test_encoder; +- struct radeon_encoder_atom_dig *dig; ++ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + uint32_t dig_enc_in_use = 0; + +- /* DCE4/5 */ +- if (ASIC_IS_DCE4(rdev)) { +- dig = radeon_encoder->enc_priv; +- if (ASIC_IS_DCE41(rdev)) { ++ if (ASIC_IS_DCE6(rdev)) { ++ /* DCE6 */ ++ switch (radeon_encoder->encoder_id) { ++ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: ++ if (dig->linkb) ++ return 1; ++ else ++ return 0; ++ break; ++ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: ++ if (dig->linkb) ++ return 3; ++ else ++ return 2; ++ break; ++ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: ++ if (dig->linkb) ++ return 5; ++ else ++ return 4; ++ break; ++ } ++ } else if (ASIC_IS_DCE4(rdev)) { ++ /* DCE4/5 */ ++ if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) { + /* ontario follows DCE4 */ + if (rdev->family == CHIP_PALM) { + if (dig->linkb) +@@ -1835,7 +1896,7 @@ radeon_atom_encoder_init(struct radeon_device *rdev) + break; + } + +- if (ext_encoder && ASIC_IS_DCE41(rdev)) ++ if (ext_encoder && (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))) + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT); + } +diff --git a/drivers/gpu/drm/radeon/atombios_i2c.c b/drivers/gpu/drm/radeon/atombios_i2c.c +new file mode 100644 +index 0000000..9ed94a8 +--- /dev/null ++++ b/drivers/gpu/drm/radeon/atombios_i2c.c +@@ -0,0 +1,141 @@ ++/* ++ * Copyright 2011 Advanced Micro Devices, Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ * ++ * Authors: Alex Deucher ++ * ++ */ ++#include "drmP.h" ++#include "radeon_drm.h" ++#include "radeon.h" ++#include "atom.h" ++ ++extern void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); ++ ++#define TARGET_HW_I2C_CLOCK 50 ++ ++/* these are a limitation of ProcessI2cChannelTransaction not the hw */ ++#define ATOM_MAX_HW_I2C_WRITE 2 ++#define ATOM_MAX_HW_I2C_READ 255 ++ ++static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan, ++ u8 slave_addr, u8 flags, ++ u8 *buf, u8 num) ++{ ++ struct drm_device *dev = chan->dev; ++ struct radeon_device *rdev = dev->dev_private; ++ PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args; ++ int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction); ++ unsigned char *base; ++ u16 out; ++ ++ memset(&args, 0, sizeof(args)); ++ ++ base = (unsigned char *)rdev->mode_info.atom_context->scratch; ++ ++ if (flags & HW_I2C_WRITE) { ++ if (num > ATOM_MAX_HW_I2C_WRITE) { ++ DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 2)\n", num); ++ return -EINVAL; ++ } ++ memcpy(&out, buf, num); ++ args.lpI2CDataOut = cpu_to_le16(out); ++ } else { ++ if (num > ATOM_MAX_HW_I2C_READ) { ++ DRM_ERROR("hw i2c: tried to read too many bytes (%d vs 255)\n", num); ++ return -EINVAL; ++ } ++ } ++ ++ args.ucI2CSpeed = TARGET_HW_I2C_CLOCK; ++ args.ucRegIndex = 0; ++ args.ucTransBytes = num; ++ args.ucSlaveAddr = slave_addr << 1; ++ args.ucLineNumber = chan->rec.i2c_id; ++ ++ atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); ++ ++ /* error */ ++ if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) { ++ DRM_DEBUG_KMS("hw_i2c error\n"); ++ return -EIO; ++ } ++ ++ if (!(flags & HW_I2C_WRITE)) ++ radeon_atom_copy_swap(buf, base, num, false); ++ ++ return 0; ++} ++ ++int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap, ++ struct i2c_msg *msgs, int num) ++{ ++ struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap); ++ struct i2c_msg *p; ++ int i, remaining, current_count, buffer_offset, max_bytes, ret; ++ u8 buf = 0, flags; ++ ++ /* check for bus probe */ ++ p = &msgs[0]; ++ if ((num == 1) && (p->len == 0)) { ++ ret = radeon_process_i2c_ch(i2c, ++ p->addr, HW_I2C_WRITE, ++ &buf, 1); ++ if (ret) ++ return ret; ++ else ++ return num; ++ } ++ ++ for (i = 0; i < num; i++) { ++ p = &msgs[i]; ++ remaining = p->len; ++ buffer_offset = 0; ++ /* max_bytes are a limitation of ProcessI2cChannelTransaction not the hw */ ++ if (p->flags & I2C_M_RD) { ++ max_bytes = ATOM_MAX_HW_I2C_READ; ++ flags = HW_I2C_READ; ++ } else { ++ max_bytes = ATOM_MAX_HW_I2C_WRITE; ++ flags = HW_I2C_WRITE; ++ } ++ while (remaining) { ++ if (remaining > max_bytes) ++ current_count = max_bytes; ++ else ++ current_count = remaining; ++ ret = radeon_process_i2c_ch(i2c, ++ p->addr, flags, ++ &p->buf[buffer_offset], current_count); ++ if (ret) ++ return ret; ++ remaining -= current_count; ++ buffer_offset += current_count; ++ } ++ } ++ ++ return num; ++} ++ ++u32 radeon_atom_hw_i2c_func(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ +diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.c b/drivers/gpu/drm/radeon/cayman_blit_shaders.c +index 7b4eeb7..19a0114 100644 +--- a/drivers/gpu/drm/radeon/cayman_blit_shaders.c ++++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.c +@@ -24,6 +24,7 @@ + * Alex Deucher + */ + ++#include + #include + #include + +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 5d78973..13d3003 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -50,6 +50,39 @@ static const u32 crtc_offsets[6] = + static void evergreen_gpu_init(struct radeon_device *rdev); + void evergreen_fini(struct radeon_device *rdev); + void evergreen_pcie_gen2_enable(struct radeon_device *rdev); ++extern void cayman_cp_int_cntl_setup(struct radeon_device *rdev, ++ int ring, u32 cp_int_cntl); ++ ++void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw, ++ unsigned *bankh, unsigned *mtaspect, ++ unsigned *tile_split) ++{ ++ *bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK; ++ *bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK; ++ *mtaspect = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK; ++ *tile_split = (tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK; ++ switch (*bankw) { ++ default: ++ case 1: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_1; break; ++ case 2: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_2; break; ++ case 4: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_4; break; ++ case 8: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_8; break; ++ } ++ switch (*bankh) { ++ default: ++ case 1: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_1; break; ++ case 2: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_2; break; ++ case 4: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_4; break; ++ case 8: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_8; break; ++ } ++ switch (*mtaspect) { ++ default: ++ case 1: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1; break; ++ case 2: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2; break; ++ case 4: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4; break; ++ case 8: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8; break; ++ } ++} + + void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) + { +@@ -587,7 +620,7 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, + return 0; + } + +-static u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev) ++u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev) + { + u32 tmp = RREG32(MC_SHARED_CHMAP); + +@@ -1136,11 +1169,24 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav + crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN; + if (crtc_enabled) { + save->crtc_enabled[i] = true; +- tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); +- if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { +- dce4_wait_for_vblank(rdev, i); +- tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; +- WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); ++ if (ASIC_IS_DCE6(rdev)) { ++ tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); ++ if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { ++ radeon_wait_for_vblank(rdev, i); ++ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); ++ tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; ++ WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); ++ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); ++ } ++ } else { ++ tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); ++ if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { ++ radeon_wait_for_vblank(rdev, i); ++ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); ++ tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; ++ WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); ++ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); ++ } + } + /* wait for the next frame */ + frame_count = radeon_get_vblank_counter(rdev, i); +@@ -1149,12 +1195,21 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav + break; + udelay(1); + } ++ ++ /* XXX this is a hack to avoid strange behavior with EFI on certain systems */ ++ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); ++ tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); ++ tmp &= ~EVERGREEN_CRTC_MASTER_EN; ++ WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); ++ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); ++ save->crtc_enabled[i] = false; ++ /* ***** */ + } else { + save->crtc_enabled[i] = false; + } + } + +- evergreen_mc_wait_for_idle(rdev); ++ radeon_mc_wait_for_idle(rdev); + + blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); + if ((blackout & BLACKOUT_MODE_MASK) != 1) { +@@ -1166,6 +1221,22 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav + } + /* wait for the MC to settle */ + udelay(100); ++ ++ /* lock double buffered regs */ ++ for (i = 0; i < rdev->num_crtc; i++) { ++ if (save->crtc_enabled[i]) { ++ tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]); ++ if (!(tmp & EVERGREEN_GRPH_UPDATE_LOCK)) { ++ tmp |= EVERGREEN_GRPH_UPDATE_LOCK; ++ WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp); ++ } ++ tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]); ++ if (!(tmp & 1)) { ++ tmp |= 1; ++ WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp); ++ } ++ } ++ } + } + + void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) +@@ -1187,6 +1258,33 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s + WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); + ++ /* unlock regs and wait for update */ ++ for (i = 0; i < rdev->num_crtc; i++) { ++ if (save->crtc_enabled[i]) { ++ tmp = RREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i]); ++ if ((tmp & 0x3) != 0) { ++ tmp &= ~0x3; ++ WREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i], tmp); ++ } ++ tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]); ++ if (tmp & EVERGREEN_GRPH_UPDATE_LOCK) { ++ tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK; ++ WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp); ++ } ++ tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]); ++ if (tmp & 1) { ++ tmp &= ~1; ++ WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp); ++ } ++ for (j = 0; j < rdev->usec_timeout; j++) { ++ tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]); ++ if ((tmp & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) == 0) ++ break; ++ udelay(1); ++ } ++ } ++ } ++ + /* unblackout the MC */ + tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); + tmp &= ~BLACKOUT_MODE_MASK; +@@ -1196,9 +1294,19 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s + + for (i = 0; i < rdev->num_crtc; i++) { + if (save->crtc_enabled[i]) { +- tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); +- tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; +- WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); ++ if (ASIC_IS_DCE6(rdev)) { ++ tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); ++ tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; ++ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); ++ WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); ++ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); ++ } else { ++ tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); ++ tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; ++ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); ++ WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); ++ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); ++ } + /* wait for the next frame */ + frame_count = radeon_get_vblank_counter(rdev, i); + for (j = 0; j < rdev->usec_timeout; j++) { +@@ -1258,7 +1366,10 @@ void evergreen_mc_program(struct radeon_device *rdev) + rdev->mc.vram_end >> 12); + } + WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12); +- if (rdev->flags & RADEON_IS_IGP) { ++ /* llano/ontario only */ ++ if ((rdev->family == CHIP_PALM) || ++ (rdev->family == CHIP_SUMO) || ++ (rdev->family == CHIP_SUMO2)) { + tmp = RREG32(MC_FUS_VM_FB_OFFSET) & 0x000FFFFF; + tmp |= ((rdev->mc.vram_end >> 20) & 0xF) << 24; + tmp |= ((rdev->mc.vram_start >> 20) & 0xF) << 20; +@@ -1293,18 +1404,20 @@ void evergreen_mc_program(struct radeon_device *rdev) + */ + void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) + { ++ struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; ++ + /* set to DX10/11 mode */ +- radeon_ring_write(rdev, PACKET3(PACKET3_MODE_CONTROL, 0)); +- radeon_ring_write(rdev, 1); ++ radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); ++ radeon_ring_write(ring, 1); + /* FIXME: implement */ +- radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); ++ radeon_ring_write(ring, + #ifdef __BIG_ENDIAN + (2 << 0) | + #endif + (ib->gpu_addr & 0xFFFFFFFC)); +- radeon_ring_write(rdev, upper_32_bits(ib->gpu_addr) & 0xFF); +- radeon_ring_write(rdev, ib->length_dw); ++ radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF); ++ radeon_ring_write(ring, ib->length_dw); + } + + +@@ -1342,71 +1455,73 @@ static int evergreen_cp_load_microcode(struct radeon_device *rdev) + + static int evergreen_cp_start(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r, i; + uint32_t cp_me; + +- r = radeon_ring_lock(rdev, 7); ++ r = radeon_ring_lock(rdev, ring, 7); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } +- radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); +- radeon_ring_write(rdev, 0x1); +- radeon_ring_write(rdev, 0x0); +- radeon_ring_write(rdev, rdev->config.evergreen.max_hw_contexts - 1); +- radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); ++ radeon_ring_write(ring, 0x1); ++ radeon_ring_write(ring, 0x0); ++ radeon_ring_write(ring, rdev->config.evergreen.max_hw_contexts - 1); ++ radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_unlock_commit(rdev, ring); + + cp_me = 0xff; + WREG32(CP_ME_CNTL, cp_me); + +- r = radeon_ring_lock(rdev, evergreen_default_size + 19); ++ r = radeon_ring_lock(rdev, ring, evergreen_default_size + 19); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + + /* setup clear context state */ +- radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); +- radeon_ring_write(rdev, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); ++ radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); ++ radeon_ring_write(ring, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); + + for (i = 0; i < evergreen_default_size; i++) +- radeon_ring_write(rdev, evergreen_default_state[i]); ++ radeon_ring_write(ring, evergreen_default_state[i]); + +- radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); +- radeon_ring_write(rdev, PACKET3_PREAMBLE_END_CLEAR_STATE); ++ radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); ++ radeon_ring_write(ring, PACKET3_PREAMBLE_END_CLEAR_STATE); + + /* set clear context state */ +- radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0)); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0)); ++ radeon_ring_write(ring, 0); + + /* SQ_VTX_BASE_VTX_LOC */ +- radeon_ring_write(rdev, 0xc0026f00); +- radeon_ring_write(rdev, 0x00000000); +- radeon_ring_write(rdev, 0x00000000); +- radeon_ring_write(rdev, 0x00000000); ++ radeon_ring_write(ring, 0xc0026f00); ++ radeon_ring_write(ring, 0x00000000); ++ radeon_ring_write(ring, 0x00000000); ++ radeon_ring_write(ring, 0x00000000); + + /* Clear consts */ +- radeon_ring_write(rdev, 0xc0036f00); +- radeon_ring_write(rdev, 0x00000bc4); +- radeon_ring_write(rdev, 0xffffffff); +- radeon_ring_write(rdev, 0xffffffff); +- radeon_ring_write(rdev, 0xffffffff); ++ radeon_ring_write(ring, 0xc0036f00); ++ radeon_ring_write(ring, 0x00000bc4); ++ radeon_ring_write(ring, 0xffffffff); ++ radeon_ring_write(ring, 0xffffffff); ++ radeon_ring_write(ring, 0xffffffff); + +- radeon_ring_write(rdev, 0xc0026900); +- radeon_ring_write(rdev, 0x00000316); +- radeon_ring_write(rdev, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ +- radeon_ring_write(rdev, 0x00000010); /* */ ++ radeon_ring_write(ring, 0xc0026900); ++ radeon_ring_write(ring, 0x00000316); ++ radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ ++ radeon_ring_write(ring, 0x00000010); /* */ + +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_unlock_commit(rdev, ring); + + return 0; + } + + int evergreen_cp_resume(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 tmp; + u32 rb_bufsz; + int r; +@@ -1424,13 +1539,14 @@ int evergreen_cp_resume(struct radeon_device *rdev) + RREG32(GRBM_SOFT_RESET); + + /* Set ring buffer size */ +- rb_bufsz = drm_order(rdev->cp.ring_size / 8); ++ rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; + #ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; + #endif + WREG32(CP_RB_CNTL, tmp); +- WREG32(CP_SEM_WAIT_TIMER, 0x4); ++ WREG32(CP_SEM_WAIT_TIMER, 0x0); ++ WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); + + /* Set the write pointer delay */ + WREG32(CP_RB_WPTR_DELAY, 0); +@@ -1438,8 +1554,8 @@ int evergreen_cp_resume(struct radeon_device *rdev) + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA); + WREG32(CP_RB_RPTR_WR, 0); +- rdev->cp.wptr = 0; +- WREG32(CP_RB_WPTR, rdev->cp.wptr); ++ ring->wptr = 0; ++ WREG32(CP_RB_WPTR, ring->wptr); + + /* set the wb address wether it's enabled or not */ + WREG32(CP_RB_RPTR_ADDR, +@@ -1457,16 +1573,16 @@ int evergreen_cp_resume(struct radeon_device *rdev) + mdelay(1); + WREG32(CP_RB_CNTL, tmp); + +- WREG32(CP_RB_BASE, rdev->cp.gpu_addr >> 8); ++ WREG32(CP_RB_BASE, ring->gpu_addr >> 8); + WREG32(CP_DEBUG, (1 << 27) | (1 << 28)); + +- rdev->cp.rptr = RREG32(CP_RB_RPTR); ++ ring->rptr = RREG32(CP_RB_RPTR); + + evergreen_cp_start(rdev); +- rdev->cp.ready = true; +- r = radeon_ring_test(rdev); ++ ring->ready = true; ++ r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); + if (r) { +- rdev->cp.ready = false; ++ ring->ready = false; + return r; + } + return 0; +@@ -1897,7 +2013,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev) + + + mc_shared_chmap = RREG32(MC_SHARED_CHMAP); +- if (rdev->flags & RADEON_IS_IGP) ++ if ((rdev->family == CHIP_PALM) || ++ (rdev->family == CHIP_SUMO) || ++ (rdev->family == CHIP_SUMO2)) + mc_arb_ramcfg = RREG32(FUS_MC_ARB_RAMCFG); + else + mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); +@@ -2301,7 +2419,9 @@ int evergreen_mc_init(struct radeon_device *rdev) + + /* Get VRAM informations */ + rdev->mc.vram_is_ddr = true; +- if (rdev->flags & RADEON_IS_IGP) ++ if ((rdev->family == CHIP_PALM) || ++ (rdev->family == CHIP_SUMO) || ++ (rdev->family == CHIP_SUMO2)) + tmp = RREG32(FUS_MC_ARB_RAMCFG); + else + tmp = RREG32(MC_ARB_RAMCFG); +@@ -2333,14 +2453,16 @@ int evergreen_mc_init(struct radeon_device *rdev) + rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); + rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); + /* Setup GPU memory space */ +- if (rdev->flags & RADEON_IS_IGP) { ++ if ((rdev->family == CHIP_PALM) || ++ (rdev->family == CHIP_SUMO) || ++ (rdev->family == CHIP_SUMO2)) { + /* size in bytes on fusion */ + rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); + rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); + } else { +- /* size in MB on evergreen */ +- rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; +- rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; ++ /* size in MB on evergreen/cayman/tn */ ++ rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; ++ rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; + } + rdev->mc.visible_vram_size = rdev->mc.aper_size; + r700_vram_gtt_location(rdev, &rdev->mc); +@@ -2349,7 +2471,7 @@ int evergreen_mc_init(struct radeon_device *rdev) + return 0; + } + +-bool evergreen_gpu_is_lockup(struct radeon_device *rdev) ++bool evergreen_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) + { + u32 srbm_status; + u32 grbm_status; +@@ -2362,19 +2484,19 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev) + grbm_status_se0 = RREG32(GRBM_STATUS_SE0); + grbm_status_se1 = RREG32(GRBM_STATUS_SE1); + if (!(grbm_status & GUI_ACTIVE)) { +- r100_gpu_lockup_update(lockup, &rdev->cp); ++ r100_gpu_lockup_update(lockup, ring); + return false; + } + /* force CP activities */ +- r = radeon_ring_lock(rdev, 2); ++ r = radeon_ring_lock(rdev, ring, 2); + if (!r) { + /* PACKET2 NOP */ +- radeon_ring_write(rdev, 0x80000000); +- radeon_ring_write(rdev, 0x80000000); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_unlock_commit(rdev, ring); + } +- rdev->cp.rptr = RREG32(CP_RB_RPTR); +- return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp); ++ ring->rptr = RREG32(CP_RB_RPTR); ++ return r100_gpu_cp_is_lockup(rdev, lockup, ring); + } + + static int evergreen_gpu_soft_reset(struct radeon_device *rdev) +@@ -2466,7 +2588,13 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev) + { + u32 tmp; + +- WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); ++ if (rdev->family >= CHIP_CAYMAN) { ++ cayman_cp_int_cntl_setup(rdev, 0, ++ CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); ++ cayman_cp_int_cntl_setup(rdev, 1, 0); ++ cayman_cp_int_cntl_setup(rdev, 2, 0); ++ } else ++ WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + WREG32(GRBM_INT_CNTL, 0); + WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); + WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); +@@ -2490,7 +2618,9 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev) + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } + +- WREG32(DACA_AUTODETECT_INT_CONTROL, 0); ++ /* only one DAC on DCE6 */ ++ if (!ASIC_IS_DCE6(rdev)) ++ WREG32(DACA_AUTODETECT_INT_CONTROL, 0); + WREG32(DACB_AUTODETECT_INT_CONTROL, 0); + + tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; +@@ -2511,6 +2641,7 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev) + int evergreen_irq_set(struct radeon_device *rdev) + { + u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; ++ u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0; + u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; + u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; + u32 grbm_int_cntl = 0; +@@ -2535,11 +2666,28 @@ int evergreen_irq_set(struct radeon_device *rdev) + hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; + hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; + +- if (rdev->irq.sw_int) { +- DRM_DEBUG("evergreen_irq_set: sw int\n"); +- cp_int_cntl |= RB_INT_ENABLE; +- cp_int_cntl |= TIME_STAMP_INT_ENABLE; ++ if (rdev->family >= CHIP_CAYMAN) { ++ /* enable CP interrupts on all rings */ ++ if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { ++ DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); ++ cp_int_cntl |= TIME_STAMP_INT_ENABLE; ++ } ++ if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP1_INDEX]) { ++ DRM_DEBUG("evergreen_irq_set: sw int cp1\n"); ++ cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; ++ } ++ if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP2_INDEX]) { ++ DRM_DEBUG("evergreen_irq_set: sw int cp2\n"); ++ cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; ++ } ++ } else { ++ if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { ++ DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); ++ cp_int_cntl |= RB_INT_ENABLE; ++ cp_int_cntl |= TIME_STAMP_INT_ENABLE; ++ } + } ++ + if (rdev->irq.crtc_vblank_int[0] || + rdev->irq.pflip[0]) { + DRM_DEBUG("evergreen_irq_set: vblank 0\n"); +@@ -2599,7 +2747,12 @@ int evergreen_irq_set(struct radeon_device *rdev) + grbm_int_cntl |= GUI_IDLE_INT_ENABLE; + } + +- WREG32(CP_INT_CNTL, cp_int_cntl); ++ if (rdev->family >= CHIP_CAYMAN) { ++ cayman_cp_int_cntl_setup(rdev, 0, cp_int_cntl); ++ cayman_cp_int_cntl_setup(rdev, 1, cp_int_cntl1); ++ cayman_cp_int_cntl_setup(rdev, 2, cp_int_cntl2); ++ } else ++ WREG32(CP_INT_CNTL, cp_int_cntl); + WREG32(GRBM_INT_CNTL, grbm_int_cntl); + + WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1); +@@ -2768,7 +2921,6 @@ static u32 evergreen_get_ih_wptr(struct radeon_device *rdev) + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); +- wptr &= ~RB_OVERFLOW; + } + return (wptr & rdev->ih.ptr_mask); + } +@@ -3018,11 +3170,24 @@ restart_ih: + case 177: /* CP_INT in IB1 */ + case 178: /* CP_INT in IB2 */ + DRM_DEBUG("IH: CP int: 0x%08x\n", src_data); +- radeon_fence_process(rdev); ++ radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; + case 181: /* CP EOP event */ + DRM_DEBUG("IH: CP EOP\n"); +- radeon_fence_process(rdev); ++ if (rdev->family >= CHIP_CAYMAN) { ++ switch (src_data) { ++ case 0: ++ radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ break; ++ case 1: ++ radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP1_INDEX); ++ break; ++ case 2: ++ radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP2_INDEX); ++ break; ++ } ++ } else ++ radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; + case 233: /* GUI IDLE */ + DRM_DEBUG("IH: GUI idle\n"); +@@ -3052,6 +3217,7 @@ restart_ih: + + static int evergreen_startup(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + + /* enable pcie gen2 link */ +@@ -3098,7 +3264,7 @@ static int evergreen_startup(struct radeon_device *rdev) + r = evergreen_blit_init(rdev); + if (r) { + r600_blit_fini(rdev); +- rdev->asic->copy = NULL; ++ rdev->asic->copy.copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } + +@@ -3107,6 +3273,12 @@ static int evergreen_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ + /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); +@@ -3122,7 +3294,9 @@ static int evergreen_startup(struct radeon_device *rdev) + } + evergreen_irq_set(rdev); + +- r = radeon_ring_init(rdev, rdev->cp.ring_size); ++ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, ++ R600_CP_RB_RPTR, R600_CP_RB_WPTR, ++ 0, 0xfffff, RADEON_CP_PACKET2); + if (r) + return r; + r = evergreen_cp_load_microcode(rdev); +@@ -3132,6 +3306,23 @@ static int evergreen_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); ++ if (r) { ++ DRM_ERROR("radeon: failed testing IB (%d).\n", r); ++ rdev->accel_working = false; ++ return r; ++ } ++ ++ r = r600_audio_init(rdev); ++ if (r) { ++ DRM_ERROR("radeon: audio init failed\n"); ++ return r; ++ } ++ + return 0; + } + +@@ -3151,15 +3342,11 @@ int evergreen_resume(struct radeon_device *rdev) + /* post card */ + atom_asic_init(rdev->mode_info.atom_context); + ++ rdev->accel_working = true; + r = evergreen_startup(rdev); + if (r) { + DRM_ERROR("evergreen startup failed on resume\n"); +- return r; +- } +- +- r = r600_ib_test(rdev); +- if (r) { +- DRM_ERROR("radeon: failed testing IB (%d).\n", r); ++ rdev->accel_working = false; + return r; + } + +@@ -3169,13 +3356,17 @@ int evergreen_resume(struct radeon_device *rdev) + + int evergreen_suspend(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ ++ r600_audio_fini(rdev); + /* FIXME: we should wait for ring to be empty */ ++ radeon_ib_pool_suspend(rdev); ++ r600_blit_suspend(rdev); + r700_cp_stop(rdev); +- rdev->cp.ready = false; ++ ring->ready = false; + evergreen_irq_suspend(rdev); + radeon_wb_disable(rdev); + evergreen_pcie_gart_disable(rdev); +- r600_blit_suspend(rdev); + + return 0; + } +@@ -3246,8 +3437,8 @@ int evergreen_init(struct radeon_device *rdev) + if (r) + return r; + +- rdev->cp.ring_obj = NULL; +- r600_ring_init(rdev, 1024 * 1024); ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; ++ r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); + + rdev->ih.ring_obj = NULL; + r600_ih_ring_init(rdev, 64 * 1024); +@@ -3256,29 +3447,24 @@ int evergreen_init(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_ib_pool_init(rdev); + rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ + r = evergreen_startup(rdev); + if (r) { + dev_err(rdev->dev, "disabling GPU acceleration\n"); + r700_cp_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); ++ r100_ib_fini(rdev); + radeon_irq_kms_fini(rdev); + evergreen_pcie_gart_fini(rdev); + rdev->accel_working = false; + } +- if (rdev->accel_working) { +- r = radeon_ib_pool_init(rdev); +- if (r) { +- DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); +- rdev->accel_working = false; +- } +- r = r600_ib_test(rdev); +- if (r) { +- DRM_ERROR("radeon: failed testing IB (%d).\n", r); +- rdev->accel_working = false; +- } +- } + + /* Don't start up if the MC ucode is missing on BTC parts. + * The default clocks and voltages before the MC ucode +@@ -3296,15 +3482,17 @@ int evergreen_init(struct radeon_device *rdev) + + void evergreen_fini(struct radeon_device *rdev) + { ++ r600_audio_fini(rdev); + r600_blit_fini(rdev); + r700_cp_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); +- radeon_ib_pool_fini(rdev); ++ r100_ib_fini(rdev); + radeon_irq_kms_fini(rdev); + evergreen_pcie_gart_fini(rdev); + r600_vram_scratch_fini(rdev); + radeon_gem_fini(rdev); ++ radeon_semaphore_driver_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_agp_fini(rdev); + radeon_bo_fini(rdev); +diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c +index 914e5af..222acd2 100644 +--- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c ++++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c +@@ -32,23 +32,14 @@ + #include "evergreend.h" + #include "evergreen_blit_shaders.h" + #include "cayman_blit_shaders.h" +- +-#define DI_PT_RECTLIST 0x11 +-#define DI_INDEX_SIZE_16_BIT 0x0 +-#define DI_SRC_SEL_AUTO_INDEX 0x2 +- +-#define FMT_8 0x1 +-#define FMT_5_6_5 0x8 +-#define FMT_8_8_8_8 0x1a +-#define COLOR_8 0x1 +-#define COLOR_5_6_5 0x8 +-#define COLOR_8_8_8_8 0x1a ++#include "radeon_blit_common.h" + + /* emits 17 */ + static void + set_render_target(struct radeon_device *rdev, int format, + int w, int h, u64 gpu_addr) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 cb_color_info; + int pitch, slice; + +@@ -62,23 +53,23 @@ set_render_target(struct radeon_device *rdev, int format, + pitch = (w / 8) - 1; + slice = ((w * h) / 64) - 1; + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 15)); +- radeon_ring_write(rdev, (CB_COLOR0_BASE - PACKET3_SET_CONTEXT_REG_START) >> 2); +- radeon_ring_write(rdev, gpu_addr >> 8); +- radeon_ring_write(rdev, pitch); +- radeon_ring_write(rdev, slice); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, cb_color_info); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, (w - 1) | ((h - 1) << 16)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 15)); ++ radeon_ring_write(ring, (CB_COLOR0_BASE - PACKET3_SET_CONTEXT_REG_START) >> 2); ++ radeon_ring_write(ring, gpu_addr >> 8); ++ radeon_ring_write(ring, pitch); ++ radeon_ring_write(ring, slice); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, cb_color_info); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, (w - 1) | ((h - 1) << 16)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); + } + + /* emits 5dw */ +@@ -87,6 +78,7 @@ cp_set_surface_sync(struct radeon_device *rdev, + u32 sync_type, u32 size, + u64 mc_addr) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 cp_coher_size; + + if (size == 0xffffffff) +@@ -99,39 +91,40 @@ cp_set_surface_sync(struct radeon_device *rdev, + * to the RB directly. For IBs, the CP programs this as part of the + * surface_sync packet. + */ +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); +- radeon_ring_write(rdev, (0x85e8 - PACKET3_SET_CONFIG_REG_START) >> 2); +- radeon_ring_write(rdev, 0); /* CP_COHER_CNTL2 */ ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(ring, (0x85e8 - PACKET3_SET_CONFIG_REG_START) >> 2); ++ radeon_ring_write(ring, 0); /* CP_COHER_CNTL2 */ + } +- radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3)); +- radeon_ring_write(rdev, sync_type); +- radeon_ring_write(rdev, cp_coher_size); +- radeon_ring_write(rdev, mc_addr >> 8); +- radeon_ring_write(rdev, 10); /* poll interval */ ++ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); ++ radeon_ring_write(ring, sync_type); ++ radeon_ring_write(ring, cp_coher_size); ++ radeon_ring_write(ring, mc_addr >> 8); ++ radeon_ring_write(ring, 10); /* poll interval */ + } + + /* emits 11dw + 1 surface sync = 16dw */ + static void + set_shaders(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u64 gpu_addr; + + /* VS */ + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.vs_offset; +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 3)); +- radeon_ring_write(rdev, (SQ_PGM_START_VS - PACKET3_SET_CONTEXT_REG_START) >> 2); +- radeon_ring_write(rdev, gpu_addr >> 8); +- radeon_ring_write(rdev, 2); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 3)); ++ radeon_ring_write(ring, (SQ_PGM_START_VS - PACKET3_SET_CONTEXT_REG_START) >> 2); ++ radeon_ring_write(ring, gpu_addr >> 8); ++ radeon_ring_write(ring, 2); ++ radeon_ring_write(ring, 0); + + /* PS */ + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.ps_offset; +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 4)); +- radeon_ring_write(rdev, (SQ_PGM_START_PS - PACKET3_SET_CONTEXT_REG_START) >> 2); +- radeon_ring_write(rdev, gpu_addr >> 8); +- radeon_ring_write(rdev, 1); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 2); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 4)); ++ radeon_ring_write(ring, (SQ_PGM_START_PS - PACKET3_SET_CONTEXT_REG_START) >> 2); ++ radeon_ring_write(ring, gpu_addr >> 8); ++ radeon_ring_write(ring, 1); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 2); + + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.vs_offset; + cp_set_surface_sync(rdev, PACKET3_SH_ACTION_ENA, 512, gpu_addr); +@@ -141,6 +134,7 @@ set_shaders(struct radeon_device *rdev) + static void + set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 sq_vtx_constant_word2, sq_vtx_constant_word3; + + /* high addr, stride */ +@@ -155,16 +149,16 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr) + SQ_VTCX_SEL_Z(SQ_SEL_Z) | + SQ_VTCX_SEL_W(SQ_SEL_W); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8)); +- radeon_ring_write(rdev, 0x580); +- radeon_ring_write(rdev, gpu_addr & 0xffffffff); +- radeon_ring_write(rdev, 48 - 1); /* size */ +- radeon_ring_write(rdev, sq_vtx_constant_word2); +- radeon_ring_write(rdev, sq_vtx_constant_word3); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_BUFFER)); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_RESOURCE, 8)); ++ radeon_ring_write(ring, 0x580); ++ radeon_ring_write(ring, gpu_addr & 0xffffffff); ++ radeon_ring_write(ring, 48 - 1); /* size */ ++ radeon_ring_write(ring, sq_vtx_constant_word2); ++ radeon_ring_write(ring, sq_vtx_constant_word3); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_BUFFER)); + + if ((rdev->family == CHIP_CEDAR) || + (rdev->family == CHIP_PALM) || +@@ -185,6 +179,7 @@ set_tex_resource(struct radeon_device *rdev, + int format, int w, int h, int pitch, + u64 gpu_addr, u32 size) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 sq_tex_resource_word0, sq_tex_resource_word1; + u32 sq_tex_resource_word4, sq_tex_resource_word7; + +@@ -208,16 +203,16 @@ set_tex_resource(struct radeon_device *rdev, + cp_set_surface_sync(rdev, + PACKET3_TC_ACTION_ENA, size, gpu_addr); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, sq_tex_resource_word0); +- radeon_ring_write(rdev, sq_tex_resource_word1); +- radeon_ring_write(rdev, gpu_addr >> 8); +- radeon_ring_write(rdev, gpu_addr >> 8); +- radeon_ring_write(rdev, sq_tex_resource_word4); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, sq_tex_resource_word7); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_RESOURCE, 8)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, sq_tex_resource_word0); ++ radeon_ring_write(ring, sq_tex_resource_word1); ++ radeon_ring_write(ring, gpu_addr >> 8); ++ radeon_ring_write(ring, gpu_addr >> 8); ++ radeon_ring_write(ring, sq_tex_resource_word4); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, sq_tex_resource_word7); + } + + /* emits 12 */ +@@ -225,53 +220,55 @@ static void + set_scissors(struct radeon_device *rdev, int x1, int y1, + int x2, int y2) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + /* workaround some hw bugs */ + if (x2 == 0) + x1 = 1; + if (y2 == 0) + y1 = 1; +- if (rdev->family == CHIP_CAYMAN) { ++ if (rdev->family >= CHIP_CAYMAN) { + if ((x2 == 1) && (y2 == 1)) + x2 = 2; + } + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); +- radeon_ring_write(rdev, (PA_SC_SCREEN_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); +- radeon_ring_write(rdev, (x1 << 0) | (y1 << 16)); +- radeon_ring_write(rdev, (x2 << 0) | (y2 << 16)); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); ++ radeon_ring_write(ring, (PA_SC_SCREEN_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); ++ radeon_ring_write(ring, (x1 << 0) | (y1 << 16)); ++ radeon_ring_write(ring, (x2 << 0) | (y2 << 16)); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); +- radeon_ring_write(rdev, (PA_SC_GENERIC_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); +- radeon_ring_write(rdev, (x1 << 0) | (y1 << 16) | (1 << 31)); +- radeon_ring_write(rdev, (x2 << 0) | (y2 << 16)); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); ++ radeon_ring_write(ring, (PA_SC_GENERIC_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); ++ radeon_ring_write(ring, (x1 << 0) | (y1 << 16) | (1 << 31)); ++ radeon_ring_write(ring, (x2 << 0) | (y2 << 16)); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); +- radeon_ring_write(rdev, (PA_SC_WINDOW_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); +- radeon_ring_write(rdev, (x1 << 0) | (y1 << 16) | (1 << 31)); +- radeon_ring_write(rdev, (x2 << 0) | (y2 << 16)); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); ++ radeon_ring_write(ring, (PA_SC_WINDOW_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); ++ radeon_ring_write(ring, (x1 << 0) | (y1 << 16) | (1 << 31)); ++ radeon_ring_write(ring, (x2 << 0) | (y2 << 16)); + } + + /* emits 10 */ + static void + draw_auto(struct radeon_device *rdev) + { +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); +- radeon_ring_write(rdev, (VGT_PRIMITIVE_TYPE - PACKET3_SET_CONFIG_REG_START) >> 2); +- radeon_ring_write(rdev, DI_PT_RECTLIST); ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(ring, (VGT_PRIMITIVE_TYPE - PACKET3_SET_CONFIG_REG_START) >> 2); ++ radeon_ring_write(ring, DI_PT_RECTLIST); + +- radeon_ring_write(rdev, PACKET3(PACKET3_INDEX_TYPE, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET3(PACKET3_INDEX_TYPE, 0)); ++ radeon_ring_write(ring, + #ifdef __BIG_ENDIAN + (2 << 2) | + #endif + DI_INDEX_SIZE_16_BIT); + +- radeon_ring_write(rdev, PACKET3(PACKET3_NUM_INSTANCES, 0)); +- radeon_ring_write(rdev, 1); ++ radeon_ring_write(ring, PACKET3(PACKET3_NUM_INSTANCES, 0)); ++ radeon_ring_write(ring, 1); + +- radeon_ring_write(rdev, PACKET3(PACKET3_DRAW_INDEX_AUTO, 1)); +- radeon_ring_write(rdev, 3); +- radeon_ring_write(rdev, DI_SRC_SEL_AUTO_INDEX); ++ radeon_ring_write(ring, PACKET3(PACKET3_DRAW_INDEX_AUTO, 1)); ++ radeon_ring_write(ring, 3); ++ radeon_ring_write(ring, DI_SRC_SEL_AUTO_INDEX); + + } + +@@ -279,6 +276,7 @@ draw_auto(struct radeon_device *rdev) + static void + set_default_state(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 sq_config, sq_gpr_resource_mgmt_1, sq_gpr_resource_mgmt_2, sq_gpr_resource_mgmt_3; + u32 sq_thread_resource_mgmt, sq_thread_resource_mgmt_2; + u32 sq_stack_resource_mgmt_1, sq_stack_resource_mgmt_2, sq_stack_resource_mgmt_3; +@@ -292,8 +290,8 @@ set_default_state(struct radeon_device *rdev) + int dwords; + + /* set clear context state */ +- radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0)); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0)); ++ radeon_ring_write(ring, 0); + + if (rdev->family < CHIP_CAYMAN) { + switch (rdev->family) { +@@ -550,60 +548,60 @@ set_default_state(struct radeon_device *rdev) + NUM_LS_STACK_ENTRIES(num_ls_stack_entries)); + + /* disable dyn gprs */ +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); +- radeon_ring_write(rdev, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(ring, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2); ++ radeon_ring_write(ring, 0); + + /* setup LDS */ +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); +- radeon_ring_write(rdev, (SQ_LDS_RESOURCE_MGMT - PACKET3_SET_CONFIG_REG_START) >> 2); +- radeon_ring_write(rdev, 0x10001000); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(ring, (SQ_LDS_RESOURCE_MGMT - PACKET3_SET_CONFIG_REG_START) >> 2); ++ radeon_ring_write(ring, 0x10001000); + + /* SQ config */ +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 11)); +- radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2); +- radeon_ring_write(rdev, sq_config); +- radeon_ring_write(rdev, sq_gpr_resource_mgmt_1); +- radeon_ring_write(rdev, sq_gpr_resource_mgmt_2); +- radeon_ring_write(rdev, sq_gpr_resource_mgmt_3); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, sq_thread_resource_mgmt); +- radeon_ring_write(rdev, sq_thread_resource_mgmt_2); +- radeon_ring_write(rdev, sq_stack_resource_mgmt_1); +- radeon_ring_write(rdev, sq_stack_resource_mgmt_2); +- radeon_ring_write(rdev, sq_stack_resource_mgmt_3); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 11)); ++ radeon_ring_write(ring, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2); ++ radeon_ring_write(ring, sq_config); ++ radeon_ring_write(ring, sq_gpr_resource_mgmt_1); ++ radeon_ring_write(ring, sq_gpr_resource_mgmt_2); ++ radeon_ring_write(ring, sq_gpr_resource_mgmt_3); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, sq_thread_resource_mgmt); ++ radeon_ring_write(ring, sq_thread_resource_mgmt_2); ++ radeon_ring_write(ring, sq_stack_resource_mgmt_1); ++ radeon_ring_write(ring, sq_stack_resource_mgmt_2); ++ radeon_ring_write(ring, sq_stack_resource_mgmt_3); + } + + /* CONTEXT_CONTROL */ +- radeon_ring_write(rdev, 0xc0012800); +- radeon_ring_write(rdev, 0x80000000); +- radeon_ring_write(rdev, 0x80000000); ++ radeon_ring_write(ring, 0xc0012800); ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_write(ring, 0x80000000); + + /* SQ_VTX_BASE_VTX_LOC */ +- radeon_ring_write(rdev, 0xc0026f00); +- radeon_ring_write(rdev, 0x00000000); +- radeon_ring_write(rdev, 0x00000000); +- radeon_ring_write(rdev, 0x00000000); ++ radeon_ring_write(ring, 0xc0026f00); ++ radeon_ring_write(ring, 0x00000000); ++ radeon_ring_write(ring, 0x00000000); ++ radeon_ring_write(ring, 0x00000000); + + /* SET_SAMPLER */ +- radeon_ring_write(rdev, 0xc0036e00); +- radeon_ring_write(rdev, 0x00000000); +- radeon_ring_write(rdev, 0x00000012); +- radeon_ring_write(rdev, 0x00000000); +- radeon_ring_write(rdev, 0x00000000); ++ radeon_ring_write(ring, 0xc0036e00); ++ radeon_ring_write(ring, 0x00000000); ++ radeon_ring_write(ring, 0x00000012); ++ radeon_ring_write(ring, 0x00000000); ++ radeon_ring_write(ring, 0x00000000); + + /* set to DX10/11 mode */ +- radeon_ring_write(rdev, PACKET3(PACKET3_MODE_CONTROL, 0)); +- radeon_ring_write(rdev, 1); ++ radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); ++ radeon_ring_write(ring, 1); + + /* emit an IB pointing at default state */ + dwords = ALIGN(rdev->r600_blit.state_len, 0x10); + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset; +- radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); +- radeon_ring_write(rdev, gpu_addr & 0xFFFFFFFC); +- radeon_ring_write(rdev, upper_32_bits(gpu_addr) & 0xFF); +- radeon_ring_write(rdev, dwords); ++ radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); ++ radeon_ring_write(ring, gpu_addr & 0xFFFFFFFC); ++ radeon_ring_write(ring, upper_32_bits(gpu_addr) & 0xFF); ++ radeon_ring_write(ring, dwords); + + } + +diff --git a/drivers/gpu/drm/radeon/evergreen_blit_shaders.c b/drivers/gpu/drm/radeon/evergreen_blit_shaders.c +index 3a10399..f85c0af 100644 +--- a/drivers/gpu/drm/radeon/evergreen_blit_shaders.c ++++ b/drivers/gpu/drm/radeon/evergreen_blit_shaders.c +@@ -24,6 +24,7 @@ + * Alex Deucher + */ + ++#include + #include + #include + +diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c +index cd4590a..7b4cfc5 100644 +--- a/drivers/gpu/drm/radeon/evergreen_cs.c ++++ b/drivers/gpu/drm/radeon/evergreen_cs.c +@@ -31,6 +31,9 @@ + #include "evergreen_reg_safe.h" + #include "cayman_reg_safe.h" + ++#define MAX(a,b) (((a)>(b))?(a):(b)) ++#define MIN(a,b) (((a)<(b))?(a):(b)) ++ + static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, + struct radeon_cs_reloc **cs_reloc); + +@@ -40,42 +43,47 @@ struct evergreen_cs_track { + u32 npipes; + u32 row_size; + /* value we track */ +- u32 nsamples; +- u32 cb_color_base_last[12]; ++ u32 nsamples; /* unused */ + struct radeon_bo *cb_color_bo[12]; + u32 cb_color_bo_offset[12]; +- struct radeon_bo *cb_color_fmask_bo[8]; +- struct radeon_bo *cb_color_cmask_bo[8]; ++ struct radeon_bo *cb_color_fmask_bo[8]; /* unused */ ++ struct radeon_bo *cb_color_cmask_bo[8]; /* unused */ + u32 cb_color_info[12]; + u32 cb_color_view[12]; +- u32 cb_color_pitch_idx[12]; +- u32 cb_color_slice_idx[12]; +- u32 cb_color_dim_idx[12]; +- u32 cb_color_dim[12]; + u32 cb_color_pitch[12]; + u32 cb_color_slice[12]; +- u32 cb_color_cmask_slice[8]; +- u32 cb_color_fmask_slice[8]; ++ u32 cb_color_slice_idx[12]; ++ u32 cb_color_attrib[12]; ++ u32 cb_color_cmask_slice[8];/* unused */ ++ u32 cb_color_fmask_slice[8];/* unused */ + u32 cb_target_mask; +- u32 cb_shader_mask; ++ u32 cb_shader_mask; /* unused */ + u32 vgt_strmout_config; + u32 vgt_strmout_buffer_config; ++ struct radeon_bo *vgt_strmout_bo[4]; ++ u32 vgt_strmout_bo_offset[4]; ++ u32 vgt_strmout_size[4]; + u32 db_depth_control; + u32 db_depth_view; ++ u32 db_depth_slice; + u32 db_depth_size; +- u32 db_depth_size_idx; + u32 db_z_info; +- u32 db_z_idx; + u32 db_z_read_offset; + u32 db_z_write_offset; + struct radeon_bo *db_z_read_bo; + struct radeon_bo *db_z_write_bo; + u32 db_s_info; +- u32 db_s_idx; + u32 db_s_read_offset; + u32 db_s_write_offset; + struct radeon_bo *db_s_read_bo; + struct radeon_bo *db_s_write_bo; ++ bool sx_misc_kill_all_prims; ++ bool cb_dirty; ++ bool db_dirty; ++ bool streamout_dirty; ++ u32 htile_offset; ++ u32 htile_surface; ++ struct radeon_bo *htile_bo; + }; + + static u32 evergreen_cs_get_aray_mode(u32 tiling_flags) +@@ -103,19 +111,6 @@ static u32 evergreen_cs_get_num_banks(u32 nbanks) + } + } + +-static u32 evergreen_cs_get_tile_split(u32 row_size) +-{ +- switch (row_size) { +- case 1: +- default: +- return ADDR_SURF_TILE_SPLIT_1KB; +- case 2: +- return ADDR_SURF_TILE_SPLIT_2KB; +- case 4: +- return ADDR_SURF_TILE_SPLIT_4KB; +- } +-} +- + static void evergreen_cs_track_init(struct evergreen_cs_track *track) + { + int i; +@@ -128,50 +123,861 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) + } + + for (i = 0; i < 12; i++) { +- track->cb_color_base_last[i] = 0; + track->cb_color_bo[i] = NULL; + track->cb_color_bo_offset[i] = 0xFFFFFFFF; + track->cb_color_info[i] = 0; +- track->cb_color_view[i] = 0; +- track->cb_color_pitch_idx[i] = 0; +- track->cb_color_slice_idx[i] = 0; +- track->cb_color_dim[i] = 0; ++ track->cb_color_view[i] = 0xFFFFFFFF; + track->cb_color_pitch[i] = 0; +- track->cb_color_slice[i] = 0; +- track->cb_color_dim[i] = 0; ++ track->cb_color_slice[i] = 0xfffffff; ++ track->cb_color_slice_idx[i] = 0; + } + track->cb_target_mask = 0xFFFFFFFF; + track->cb_shader_mask = 0xFFFFFFFF; ++ track->cb_dirty = true; + ++ track->db_depth_slice = 0xffffffff; + track->db_depth_view = 0xFFFFC000; + track->db_depth_size = 0xFFFFFFFF; +- track->db_depth_size_idx = 0; + track->db_depth_control = 0xFFFFFFFF; + track->db_z_info = 0xFFFFFFFF; +- track->db_z_idx = 0xFFFFFFFF; + track->db_z_read_offset = 0xFFFFFFFF; + track->db_z_write_offset = 0xFFFFFFFF; + track->db_z_read_bo = NULL; + track->db_z_write_bo = NULL; + track->db_s_info = 0xFFFFFFFF; +- track->db_s_idx = 0xFFFFFFFF; + track->db_s_read_offset = 0xFFFFFFFF; + track->db_s_write_offset = 0xFFFFFFFF; + track->db_s_read_bo = NULL; + track->db_s_write_bo = NULL; ++ track->db_dirty = true; ++ track->htile_bo = NULL; ++ track->htile_offset = 0xFFFFFFFF; ++ track->htile_surface = 0; ++ ++ for (i = 0; i < 4; i++) { ++ track->vgt_strmout_size[i] = 0; ++ track->vgt_strmout_bo[i] = NULL; ++ track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; ++ } ++ track->streamout_dirty = true; ++ track->sx_misc_kill_all_prims = false; + } + +-static int evergreen_cs_track_check(struct radeon_cs_parser *p) ++struct eg_surface { ++ /* value gathered from cs */ ++ unsigned nbx; ++ unsigned nby; ++ unsigned format; ++ unsigned mode; ++ unsigned nbanks; ++ unsigned bankw; ++ unsigned bankh; ++ unsigned tsplit; ++ unsigned mtilea; ++ unsigned nsamples; ++ /* output value */ ++ unsigned bpe; ++ unsigned layer_size; ++ unsigned palign; ++ unsigned halign; ++ unsigned long base_align; ++}; ++ ++static int evergreen_surface_check_linear(struct radeon_cs_parser *p, ++ struct eg_surface *surf, ++ const char *prefix) ++{ ++ surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples; ++ surf->base_align = surf->bpe; ++ surf->palign = 1; ++ surf->halign = 1; ++ return 0; ++} ++ ++static int evergreen_surface_check_linear_aligned(struct radeon_cs_parser *p, ++ struct eg_surface *surf, ++ const char *prefix) ++{ ++ struct evergreen_cs_track *track = p->track; ++ unsigned palign; ++ ++ palign = MAX(64, track->group_size / surf->bpe); ++ surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples; ++ surf->base_align = track->group_size; ++ surf->palign = palign; ++ surf->halign = 1; ++ if (surf->nbx & (palign - 1)) { ++ if (prefix) { ++ dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n", ++ __func__, __LINE__, prefix, surf->nbx, palign); ++ } ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int evergreen_surface_check_1d(struct radeon_cs_parser *p, ++ struct eg_surface *surf, ++ const char *prefix) ++{ ++ struct evergreen_cs_track *track = p->track; ++ unsigned palign; ++ ++ palign = track->group_size / (8 * surf->bpe * surf->nsamples); ++ palign = MAX(8, palign); ++ surf->layer_size = surf->nbx * surf->nby * surf->bpe; ++ surf->base_align = track->group_size; ++ surf->palign = palign; ++ surf->halign = 8; ++ if ((surf->nbx & (palign - 1))) { ++ if (prefix) { ++ dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d (%d %d %d)\n", ++ __func__, __LINE__, prefix, surf->nbx, palign, ++ track->group_size, surf->bpe, surf->nsamples); ++ } ++ return -EINVAL; ++ } ++ if ((surf->nby & (8 - 1))) { ++ if (prefix) { ++ dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with 8\n", ++ __func__, __LINE__, prefix, surf->nby); ++ } ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int evergreen_surface_check_2d(struct radeon_cs_parser *p, ++ struct eg_surface *surf, ++ const char *prefix) ++{ ++ struct evergreen_cs_track *track = p->track; ++ unsigned palign, halign, tileb, slice_pt; ++ unsigned mtile_pr, mtile_ps, mtileb; ++ ++ tileb = 64 * surf->bpe * surf->nsamples; ++ slice_pt = 1; ++ if (tileb > surf->tsplit) { ++ slice_pt = tileb / surf->tsplit; ++ } ++ tileb = tileb / slice_pt; ++ /* macro tile width & height */ ++ palign = (8 * surf->bankw * track->npipes) * surf->mtilea; ++ halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; ++ mtileb = (palign / 8) * (halign / 8) * tileb;; ++ mtile_pr = surf->nbx / palign; ++ mtile_ps = (mtile_pr * surf->nby) / halign; ++ surf->layer_size = mtile_ps * mtileb * slice_pt; ++ surf->base_align = (palign / 8) * (halign / 8) * tileb; ++ surf->palign = palign; ++ surf->halign = halign; ++ ++ if ((surf->nbx & (palign - 1))) { ++ if (prefix) { ++ dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n", ++ __func__, __LINE__, prefix, surf->nbx, palign); ++ } ++ return -EINVAL; ++ } ++ if ((surf->nby & (halign - 1))) { ++ if (prefix) { ++ dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with %d\n", ++ __func__, __LINE__, prefix, surf->nby, halign); ++ } ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int evergreen_surface_check(struct radeon_cs_parser *p, ++ struct eg_surface *surf, ++ const char *prefix) ++{ ++ /* some common value computed here */ ++ surf->bpe = r600_fmt_get_blocksize(surf->format); ++ ++ switch (surf->mode) { ++ case ARRAY_LINEAR_GENERAL: ++ return evergreen_surface_check_linear(p, surf, prefix); ++ case ARRAY_LINEAR_ALIGNED: ++ return evergreen_surface_check_linear_aligned(p, surf, prefix); ++ case ARRAY_1D_TILED_THIN1: ++ return evergreen_surface_check_1d(p, surf, prefix); ++ case ARRAY_2D_TILED_THIN1: ++ return evergreen_surface_check_2d(p, surf, prefix); ++ default: ++ dev_warn(p->dev, "%s:%d %s invalid array mode %d\n", ++ __func__, __LINE__, prefix, surf->mode); ++ return -EINVAL; ++ } ++ return -EINVAL; ++} ++ ++static int evergreen_surface_value_conv_check(struct radeon_cs_parser *p, ++ struct eg_surface *surf, ++ const char *prefix) ++{ ++ switch (surf->mode) { ++ case ARRAY_2D_TILED_THIN1: ++ break; ++ case ARRAY_LINEAR_GENERAL: ++ case ARRAY_LINEAR_ALIGNED: ++ case ARRAY_1D_TILED_THIN1: ++ return 0; ++ default: ++ dev_warn(p->dev, "%s:%d %s invalid array mode %d\n", ++ __func__, __LINE__, prefix, surf->mode); ++ return -EINVAL; ++ } ++ ++ switch (surf->nbanks) { ++ case 0: surf->nbanks = 2; break; ++ case 1: surf->nbanks = 4; break; ++ case 2: surf->nbanks = 8; break; ++ case 3: surf->nbanks = 16; break; ++ default: ++ dev_warn(p->dev, "%s:%d %s invalid number of banks %d\n", ++ __func__, __LINE__, prefix, surf->nbanks); ++ return -EINVAL; ++ } ++ switch (surf->bankw) { ++ case 0: surf->bankw = 1; break; ++ case 1: surf->bankw = 2; break; ++ case 2: surf->bankw = 4; break; ++ case 3: surf->bankw = 8; break; ++ default: ++ dev_warn(p->dev, "%s:%d %s invalid bankw %d\n", ++ __func__, __LINE__, prefix, surf->bankw); ++ return -EINVAL; ++ } ++ switch (surf->bankh) { ++ case 0: surf->bankh = 1; break; ++ case 1: surf->bankh = 2; break; ++ case 2: surf->bankh = 4; break; ++ case 3: surf->bankh = 8; break; ++ default: ++ dev_warn(p->dev, "%s:%d %s invalid bankh %d\n", ++ __func__, __LINE__, prefix, surf->bankh); ++ return -EINVAL; ++ } ++ switch (surf->mtilea) { ++ case 0: surf->mtilea = 1; break; ++ case 1: surf->mtilea = 2; break; ++ case 2: surf->mtilea = 4; break; ++ case 3: surf->mtilea = 8; break; ++ default: ++ dev_warn(p->dev, "%s:%d %s invalid macro tile aspect %d\n", ++ __func__, __LINE__, prefix, surf->mtilea); ++ return -EINVAL; ++ } ++ switch (surf->tsplit) { ++ case 0: surf->tsplit = 64; break; ++ case 1: surf->tsplit = 128; break; ++ case 2: surf->tsplit = 256; break; ++ case 3: surf->tsplit = 512; break; ++ case 4: surf->tsplit = 1024; break; ++ case 5: surf->tsplit = 2048; break; ++ case 6: surf->tsplit = 4096; break; ++ default: ++ dev_warn(p->dev, "%s:%d %s invalid tile split %d\n", ++ __func__, __LINE__, prefix, surf->tsplit); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned id) ++{ ++ struct evergreen_cs_track *track = p->track; ++ struct eg_surface surf; ++ unsigned pitch, slice, mslice; ++ unsigned long offset; ++ int r; ++ ++ mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1; ++ pitch = track->cb_color_pitch[id]; ++ slice = track->cb_color_slice[id]; ++ surf.nbx = (pitch + 1) * 8; ++ surf.nby = ((slice + 1) * 64) / surf.nbx; ++ surf.mode = G_028C70_ARRAY_MODE(track->cb_color_info[id]); ++ surf.format = G_028C70_FORMAT(track->cb_color_info[id]); ++ surf.tsplit = G_028C74_TILE_SPLIT(track->cb_color_attrib[id]); ++ surf.nbanks = G_028C74_NUM_BANKS(track->cb_color_attrib[id]); ++ surf.bankw = G_028C74_BANK_WIDTH(track->cb_color_attrib[id]); ++ surf.bankh = G_028C74_BANK_HEIGHT(track->cb_color_attrib[id]); ++ surf.mtilea = G_028C74_MACRO_TILE_ASPECT(track->cb_color_attrib[id]); ++ surf.nsamples = 1; ++ ++ if (!r600_fmt_is_valid_color(surf.format)) { ++ dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08x)\n", ++ __func__, __LINE__, surf.format, ++ id, track->cb_color_info[id]); ++ return -EINVAL; ++ } ++ ++ r = evergreen_surface_value_conv_check(p, &surf, "cb"); ++ if (r) { ++ return r; ++ } ++ ++ r = evergreen_surface_check(p, &surf, "cb"); ++ if (r) { ++ dev_warn(p->dev, "%s:%d cb[%d] invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", ++ __func__, __LINE__, id, track->cb_color_pitch[id], ++ track->cb_color_slice[id], track->cb_color_attrib[id], ++ track->cb_color_info[id]); ++ return r; ++ } ++ ++ offset = track->cb_color_bo_offset[id] << 8; ++ if (offset & (surf.base_align - 1)) { ++ dev_warn(p->dev, "%s:%d cb[%d] bo base %ld not aligned with %ld\n", ++ __func__, __LINE__, id, offset, surf.base_align); ++ return -EINVAL; ++ } ++ ++ offset += surf.layer_size * mslice; ++ if (offset > radeon_bo_size(track->cb_color_bo[id])) { ++ /* old ddx are broken they allocate bo with w*h*bpp but ++ * program slice with ALIGN(h, 8), catch this and patch ++ * command stream. ++ */ ++ if (!surf.mode) { ++ volatile u32 *ib = p->ib->ptr; ++ unsigned long tmp, nby, bsize, size, min = 0; ++ ++ /* find the height the ddx wants */ ++ if (surf.nby > 8) { ++ min = surf.nby - 8; ++ } ++ bsize = radeon_bo_size(track->cb_color_bo[id]); ++ tmp = track->cb_color_bo_offset[id] << 8; ++ for (nby = surf.nby; nby > min; nby--) { ++ size = nby * surf.nbx * surf.bpe * surf.nsamples; ++ if ((tmp + size * mslice) <= bsize) { ++ break; ++ } ++ } ++ if (nby > min) { ++ surf.nby = nby; ++ slice = ((nby * surf.nbx) / 64) - 1; ++ if (!evergreen_surface_check(p, &surf, "cb")) { ++ /* check if this one works */ ++ tmp += surf.layer_size * mslice; ++ if (tmp <= bsize) { ++ ib[track->cb_color_slice_idx[id]] = slice; ++ goto old_ddx_ok; ++ } ++ } ++ } ++ } ++ dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " ++ "offset %d, max layer %d, bo size %ld, slice %d)\n", ++ __func__, __LINE__, id, surf.layer_size, ++ track->cb_color_bo_offset[id] << 8, mslice, ++ radeon_bo_size(track->cb_color_bo[id]), slice); ++ dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", ++ __func__, __LINE__, surf.nbx, surf.nby, ++ surf.mode, surf.bpe, surf.nsamples, ++ surf.bankw, surf.bankh, ++ surf.tsplit, surf.mtilea); ++ return -EINVAL; ++ } ++old_ddx_ok: ++ ++ return 0; ++} ++ ++static int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p, ++ unsigned nbx, unsigned nby) + { + struct evergreen_cs_track *track = p->track; ++ unsigned long size; + +- /* we don't support stream out buffer yet */ +- if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) { +- dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); ++ if (track->htile_bo == NULL) { ++ dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n", ++ __func__, __LINE__, track->db_z_info); + return -EINVAL; + } + +- /* XXX fill in */ ++ if (G_028ABC_LINEAR(track->htile_surface)) { ++ /* pitch must be 16 htiles aligned == 16 * 8 pixel aligned */ ++ nbx = round_up(nbx, 16 * 8); ++ /* height is npipes htiles aligned == npipes * 8 pixel aligned */ ++ nby = round_up(nby, track->npipes * 8); ++ } else { ++ switch (track->npipes) { ++ case 8: ++ nbx = round_up(nbx, 64 * 8); ++ nby = round_up(nby, 64 * 8); ++ break; ++ case 4: ++ nbx = round_up(nbx, 64 * 8); ++ nby = round_up(nby, 32 * 8); ++ break; ++ case 2: ++ nbx = round_up(nbx, 32 * 8); ++ nby = round_up(nby, 32 * 8); ++ break; ++ case 1: ++ nbx = round_up(nbx, 32 * 8); ++ nby = round_up(nby, 16 * 8); ++ break; ++ default: ++ dev_warn(p->dev, "%s:%d invalid num pipes %d\n", ++ __func__, __LINE__, track->npipes); ++ return -EINVAL; ++ } ++ } ++ /* compute number of htile */ ++ nbx = nbx / 8; ++ nby = nby / 8; ++ size = nbx * nby * 4; ++ size += track->htile_offset; ++ ++ if (size > radeon_bo_size(track->htile_bo)) { ++ dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n", ++ __func__, __LINE__, radeon_bo_size(track->htile_bo), ++ size, nbx, nby); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) ++{ ++ struct evergreen_cs_track *track = p->track; ++ struct eg_surface surf; ++ unsigned pitch, slice, mslice; ++ unsigned long offset; ++ int r; ++ ++ mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; ++ pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size); ++ slice = track->db_depth_slice; ++ surf.nbx = (pitch + 1) * 8; ++ surf.nby = ((slice + 1) * 64) / surf.nbx; ++ surf.mode = G_028040_ARRAY_MODE(track->db_z_info); ++ surf.format = G_028044_FORMAT(track->db_s_info); ++ surf.tsplit = G_028044_TILE_SPLIT(track->db_s_info); ++ surf.nbanks = G_028040_NUM_BANKS(track->db_z_info); ++ surf.bankw = G_028040_BANK_WIDTH(track->db_z_info); ++ surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info); ++ surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info); ++ surf.nsamples = 1; ++ ++ if (surf.format != 1) { ++ dev_warn(p->dev, "%s:%d stencil invalid format %d\n", ++ __func__, __LINE__, surf.format); ++ return -EINVAL; ++ } ++ /* replace by color format so we can use same code */ ++ surf.format = V_028C70_COLOR_8; ++ ++ r = evergreen_surface_value_conv_check(p, &surf, "stencil"); ++ if (r) { ++ return r; ++ } ++ ++ r = evergreen_surface_check(p, &surf, NULL); ++ if (r) { ++ /* old userspace doesn't compute proper depth/stencil alignment ++ * check that alignment against a bigger byte per elements and ++ * only report if that alignment is wrong too. ++ */ ++ surf.format = V_028C70_COLOR_8_8_8_8; ++ r = evergreen_surface_check(p, &surf, "stencil"); ++ if (r) { ++ dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", ++ __func__, __LINE__, track->db_depth_size, ++ track->db_depth_slice, track->db_s_info, track->db_z_info); ++ } ++ return r; ++ } ++ ++ offset = track->db_s_read_offset << 8; ++ if (offset & (surf.base_align - 1)) { ++ dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", ++ __func__, __LINE__, offset, surf.base_align); ++ return -EINVAL; ++ } ++ offset += surf.layer_size * mslice; ++ if (offset > radeon_bo_size(track->db_s_read_bo)) { ++ dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, " ++ "offset %ld, max layer %d, bo size %ld)\n", ++ __func__, __LINE__, surf.layer_size, ++ (unsigned long)track->db_s_read_offset << 8, mslice, ++ radeon_bo_size(track->db_s_read_bo)); ++ dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", ++ __func__, __LINE__, track->db_depth_size, ++ track->db_depth_slice, track->db_s_info, track->db_z_info); ++ return -EINVAL; ++ } ++ ++ offset = track->db_s_write_offset << 8; ++ if (offset & (surf.base_align - 1)) { ++ dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", ++ __func__, __LINE__, offset, surf.base_align); ++ return -EINVAL; ++ } ++ offset += surf.layer_size * mslice; ++ if (offset > radeon_bo_size(track->db_s_write_bo)) { ++ dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, " ++ "offset %ld, max layer %d, bo size %ld)\n", ++ __func__, __LINE__, surf.layer_size, ++ (unsigned long)track->db_s_write_offset << 8, mslice, ++ radeon_bo_size(track->db_s_write_bo)); ++ return -EINVAL; ++ } ++ ++ /* hyperz */ ++ if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) { ++ r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby); ++ if (r) { ++ return r; ++ } ++ } ++ ++ return 0; ++} ++ ++static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p) ++{ ++ struct evergreen_cs_track *track = p->track; ++ struct eg_surface surf; ++ unsigned pitch, slice, mslice; ++ unsigned long offset; ++ int r; ++ ++ mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; ++ pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size); ++ slice = track->db_depth_slice; ++ surf.nbx = (pitch + 1) * 8; ++ surf.nby = ((slice + 1) * 64) / surf.nbx; ++ surf.mode = G_028040_ARRAY_MODE(track->db_z_info); ++ surf.format = G_028040_FORMAT(track->db_z_info); ++ surf.tsplit = G_028040_TILE_SPLIT(track->db_z_info); ++ surf.nbanks = G_028040_NUM_BANKS(track->db_z_info); ++ surf.bankw = G_028040_BANK_WIDTH(track->db_z_info); ++ surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info); ++ surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info); ++ surf.nsamples = 1; ++ ++ switch (surf.format) { ++ case V_028040_Z_16: ++ surf.format = V_028C70_COLOR_16; ++ break; ++ case V_028040_Z_24: ++ case V_028040_Z_32_FLOAT: ++ surf.format = V_028C70_COLOR_8_8_8_8; ++ break; ++ default: ++ dev_warn(p->dev, "%s:%d depth invalid format %d\n", ++ __func__, __LINE__, surf.format); ++ return -EINVAL; ++ } ++ ++ r = evergreen_surface_value_conv_check(p, &surf, "depth"); ++ if (r) { ++ dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n", ++ __func__, __LINE__, track->db_depth_size, ++ track->db_depth_slice, track->db_z_info); ++ return r; ++ } ++ ++ r = evergreen_surface_check(p, &surf, "depth"); ++ if (r) { ++ dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n", ++ __func__, __LINE__, track->db_depth_size, ++ track->db_depth_slice, track->db_z_info); ++ return r; ++ } ++ ++ offset = track->db_z_read_offset << 8; ++ if (offset & (surf.base_align - 1)) { ++ dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", ++ __func__, __LINE__, offset, surf.base_align); ++ return -EINVAL; ++ } ++ offset += surf.layer_size * mslice; ++ if (offset > radeon_bo_size(track->db_z_read_bo)) { ++ dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, " ++ "offset %ld, max layer %d, bo size %ld)\n", ++ __func__, __LINE__, surf.layer_size, ++ (unsigned long)track->db_z_read_offset << 8, mslice, ++ radeon_bo_size(track->db_z_read_bo)); ++ return -EINVAL; ++ } ++ ++ offset = track->db_z_write_offset << 8; ++ if (offset & (surf.base_align - 1)) { ++ dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", ++ __func__, __LINE__, offset, surf.base_align); ++ return -EINVAL; ++ } ++ offset += surf.layer_size * mslice; ++ if (offset > radeon_bo_size(track->db_z_write_bo)) { ++ dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, " ++ "offset %ld, max layer %d, bo size %ld)\n", ++ __func__, __LINE__, surf.layer_size, ++ (unsigned long)track->db_z_write_offset << 8, mslice, ++ radeon_bo_size(track->db_z_write_bo)); ++ return -EINVAL; ++ } ++ ++ /* hyperz */ ++ if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) { ++ r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby); ++ if (r) { ++ return r; ++ } ++ } ++ ++ return 0; ++} ++ ++static int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p, ++ struct radeon_bo *texture, ++ struct radeon_bo *mipmap, ++ unsigned idx) ++{ ++ struct eg_surface surf; ++ unsigned long toffset, moffset; ++ unsigned dim, llevel, mslice, width, height, depth, i; ++ u32 texdw[8]; ++ int r; ++ ++ texdw[0] = radeon_get_ib_value(p, idx + 0); ++ texdw[1] = radeon_get_ib_value(p, idx + 1); ++ texdw[2] = radeon_get_ib_value(p, idx + 2); ++ texdw[3] = radeon_get_ib_value(p, idx + 3); ++ texdw[4] = radeon_get_ib_value(p, idx + 4); ++ texdw[5] = radeon_get_ib_value(p, idx + 5); ++ texdw[6] = radeon_get_ib_value(p, idx + 6); ++ texdw[7] = radeon_get_ib_value(p, idx + 7); ++ dim = G_030000_DIM(texdw[0]); ++ llevel = G_030014_LAST_LEVEL(texdw[5]); ++ mslice = G_030014_LAST_ARRAY(texdw[5]) + 1; ++ width = G_030000_TEX_WIDTH(texdw[0]) + 1; ++ height = G_030004_TEX_HEIGHT(texdw[1]) + 1; ++ depth = G_030004_TEX_DEPTH(texdw[1]) + 1; ++ surf.format = G_03001C_DATA_FORMAT(texdw[7]); ++ surf.nbx = (G_030000_PITCH(texdw[0]) + 1) * 8; ++ surf.nbx = r600_fmt_get_nblocksx(surf.format, surf.nbx); ++ surf.nby = r600_fmt_get_nblocksy(surf.format, height); ++ surf.mode = G_030004_ARRAY_MODE(texdw[1]); ++ surf.tsplit = G_030018_TILE_SPLIT(texdw[6]); ++ surf.nbanks = G_03001C_NUM_BANKS(texdw[7]); ++ surf.bankw = G_03001C_BANK_WIDTH(texdw[7]); ++ surf.bankh = G_03001C_BANK_HEIGHT(texdw[7]); ++ surf.mtilea = G_03001C_MACRO_TILE_ASPECT(texdw[7]); ++ surf.nsamples = 1; ++ toffset = texdw[2] << 8; ++ moffset = texdw[3] << 8; ++ ++ if (!r600_fmt_is_valid_texture(surf.format, p->family)) { ++ dev_warn(p->dev, "%s:%d texture invalid format %d\n", ++ __func__, __LINE__, surf.format); ++ return -EINVAL; ++ } ++ switch (dim) { ++ case V_030000_SQ_TEX_DIM_1D: ++ case V_030000_SQ_TEX_DIM_2D: ++ case V_030000_SQ_TEX_DIM_CUBEMAP: ++ case V_030000_SQ_TEX_DIM_1D_ARRAY: ++ case V_030000_SQ_TEX_DIM_2D_ARRAY: ++ depth = 1; ++ case V_030000_SQ_TEX_DIM_3D: ++ break; ++ default: ++ dev_warn(p->dev, "%s:%d texture invalid dimension %d\n", ++ __func__, __LINE__, dim); ++ return -EINVAL; ++ } ++ ++ r = evergreen_surface_value_conv_check(p, &surf, "texture"); ++ if (r) { ++ return r; ++ } ++ ++ /* align height */ ++ evergreen_surface_check(p, &surf, NULL); ++ surf.nby = ALIGN(surf.nby, surf.halign); ++ ++ r = evergreen_surface_check(p, &surf, "texture"); ++ if (r) { ++ dev_warn(p->dev, "%s:%d texture invalid 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", ++ __func__, __LINE__, texdw[0], texdw[1], texdw[4], ++ texdw[5], texdw[6], texdw[7]); ++ return r; ++ } ++ ++ /* check texture size */ ++ if (toffset & (surf.base_align - 1)) { ++ dev_warn(p->dev, "%s:%d texture bo base %ld not aligned with %ld\n", ++ __func__, __LINE__, toffset, surf.base_align); ++ return -EINVAL; ++ } ++ if (moffset & (surf.base_align - 1)) { ++ dev_warn(p->dev, "%s:%d mipmap bo base %ld not aligned with %ld\n", ++ __func__, __LINE__, moffset, surf.base_align); ++ return -EINVAL; ++ } ++ if (dim == SQ_TEX_DIM_3D) { ++ toffset += surf.layer_size * depth; ++ } else { ++ toffset += surf.layer_size * mslice; ++ } ++ if (toffset > radeon_bo_size(texture)) { ++ dev_warn(p->dev, "%s:%d texture bo too small (layer size %d, " ++ "offset %ld, max layer %d, depth %d, bo size %ld) (%d %d)\n", ++ __func__, __LINE__, surf.layer_size, ++ (unsigned long)texdw[2] << 8, mslice, ++ depth, radeon_bo_size(texture), ++ surf.nbx, surf.nby); ++ return -EINVAL; ++ } ++ ++ /* check mipmap size */ ++ for (i = 1; i <= llevel; i++) { ++ unsigned w, h, d; ++ ++ w = r600_mip_minify(width, i); ++ h = r600_mip_minify(height, i); ++ d = r600_mip_minify(depth, i); ++ surf.nbx = r600_fmt_get_nblocksx(surf.format, w); ++ surf.nby = r600_fmt_get_nblocksy(surf.format, h); ++ ++ switch (surf.mode) { ++ case ARRAY_2D_TILED_THIN1: ++ if (surf.nbx < surf.palign || surf.nby < surf.halign) { ++ surf.mode = ARRAY_1D_TILED_THIN1; ++ } ++ /* recompute alignment */ ++ evergreen_surface_check(p, &surf, NULL); ++ break; ++ case ARRAY_LINEAR_GENERAL: ++ case ARRAY_LINEAR_ALIGNED: ++ case ARRAY_1D_TILED_THIN1: ++ break; ++ default: ++ dev_warn(p->dev, "%s:%d invalid array mode %d\n", ++ __func__, __LINE__, surf.mode); ++ return -EINVAL; ++ } ++ surf.nbx = ALIGN(surf.nbx, surf.palign); ++ surf.nby = ALIGN(surf.nby, surf.halign); ++ ++ r = evergreen_surface_check(p, &surf, "mipmap"); ++ if (r) { ++ return r; ++ } ++ ++ if (dim == SQ_TEX_DIM_3D) { ++ moffset += surf.layer_size * d; ++ } else { ++ moffset += surf.layer_size * mslice; ++ } ++ if (moffset > radeon_bo_size(mipmap)) { ++ dev_warn(p->dev, "%s:%d mipmap [%d] bo too small (layer size %d, " ++ "offset %ld, coffset %ld, max layer %d, depth %d, " ++ "bo size %ld) level0 (%d %d %d)\n", ++ __func__, __LINE__, i, surf.layer_size, ++ (unsigned long)texdw[3] << 8, moffset, mslice, ++ d, radeon_bo_size(mipmap), ++ width, height, depth); ++ dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", ++ __func__, __LINE__, surf.nbx, surf.nby, ++ surf.mode, surf.bpe, surf.nsamples, ++ surf.bankw, surf.bankh, ++ surf.tsplit, surf.mtilea); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++static int evergreen_cs_track_check(struct radeon_cs_parser *p) ++{ ++ struct evergreen_cs_track *track = p->track; ++ unsigned tmp, i; ++ int r; ++ unsigned buffer_mask = 0; ++ ++ /* check streamout */ ++ if (track->streamout_dirty && track->vgt_strmout_config) { ++ for (i = 0; i < 4; i++) { ++ if (track->vgt_strmout_config & (1 << i)) { ++ buffer_mask |= (track->vgt_strmout_buffer_config >> (i * 4)) & 0xf; ++ } ++ } ++ ++ for (i = 0; i < 4; i++) { ++ if (buffer_mask & (1 << i)) { ++ if (track->vgt_strmout_bo[i]) { ++ u64 offset = (u64)track->vgt_strmout_bo_offset[i] + ++ (u64)track->vgt_strmout_size[i]; ++ if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) { ++ DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n", ++ i, offset, ++ radeon_bo_size(track->vgt_strmout_bo[i])); ++ return -EINVAL; ++ } ++ } else { ++ dev_warn(p->dev, "No buffer for streamout %d\n", i); ++ return -EINVAL; ++ } ++ } ++ } ++ track->streamout_dirty = false; ++ } ++ ++ if (track->sx_misc_kill_all_prims) ++ return 0; ++ ++ /* check that we have a cb for each enabled target ++ */ ++ if (track->cb_dirty) { ++ tmp = track->cb_target_mask; ++ for (i = 0; i < 8; i++) { ++ u32 format = G_028C70_FORMAT(track->cb_color_info[i]); ++ ++ if (format != V_028C70_COLOR_INVALID && ++ (tmp >> (i * 4)) & 0xF) { ++ /* at least one component is enabled */ ++ if (track->cb_color_bo[i] == NULL) { ++ dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n", ++ __func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i); ++ return -EINVAL; ++ } ++ /* check cb */ ++ r = evergreen_cs_track_validate_cb(p, i); ++ if (r) { ++ return r; ++ } ++ } ++ } ++ track->cb_dirty = false; ++ } ++ ++ if (track->db_dirty) { ++ /* Check stencil buffer */ ++ if (G_028800_STENCIL_ENABLE(track->db_depth_control)) { ++ r = evergreen_cs_track_validate_stencil(p); ++ if (r) ++ return r; ++ } ++ /* Check depth buffer */ ++ if (G_028800_Z_ENABLE(track->db_depth_control)) { ++ r = evergreen_cs_track_validate_depth(p); ++ if (r) ++ return r; ++ } ++ track->db_dirty = false; ++ } ++ + return 0; + } + +@@ -503,6 +1309,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + break; + case DB_DEPTH_CONTROL: + track->db_depth_control = radeon_get_ib_value(p, idx); ++ track->db_dirty = true; + break; + case CAYMAN_DB_EQAA: + if (p->rdev->family < CHIP_CAYMAN) { +@@ -520,7 +1327,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + break; + case DB_Z_INFO: + track->db_z_info = radeon_get_ib_value(p, idx); +- if (!p->keep_tiling_flags) { ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " +@@ -532,20 +1339,35 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { ++ unsigned bankw, bankh, mtaspect, tile_split; ++ ++ evergreen_tiling_fields(reloc->lobj.tiling_flags, ++ &bankw, &bankh, &mtaspect, ++ &tile_split); + ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); +- ib[idx] |= DB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size)); ++ ib[idx] |= DB_TILE_SPLIT(tile_split) | ++ DB_BANK_WIDTH(bankw) | ++ DB_BANK_HEIGHT(bankh) | ++ DB_MACRO_TILE_ASPECT(mtaspect); + } + } ++ track->db_dirty = true; + break; + case DB_STENCIL_INFO: + track->db_s_info = radeon_get_ib_value(p, idx); ++ track->db_dirty = true; + break; + case DB_DEPTH_VIEW: + track->db_depth_view = radeon_get_ib_value(p, idx); ++ track->db_dirty = true; + break; + case DB_DEPTH_SIZE: + track->db_depth_size = radeon_get_ib_value(p, idx); +- track->db_depth_size_idx = idx; ++ track->db_dirty = true; ++ break; ++ case R_02805C_DB_DEPTH_SLICE: ++ track->db_depth_slice = radeon_get_ib_value(p, idx); ++ track->db_dirty = true; + break; + case DB_Z_READ_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); +@@ -557,6 +1379,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + track->db_z_read_offset = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->db_z_read_bo = reloc->robj; ++ track->db_dirty = true; + break; + case DB_Z_WRITE_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); +@@ -568,6 +1391,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + track->db_z_write_offset = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->db_z_write_bo = reloc->robj; ++ track->db_dirty = true; + break; + case DB_STENCIL_READ_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); +@@ -579,6 +1403,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + track->db_s_read_offset = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->db_s_read_bo = reloc->robj; ++ track->db_dirty = true; + break; + case DB_STENCIL_WRITE_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); +@@ -590,18 +1415,56 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + track->db_s_write_offset = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->db_s_write_bo = reloc->robj; ++ track->db_dirty = true; + break; + case VGT_STRMOUT_CONFIG: + track->vgt_strmout_config = radeon_get_ib_value(p, idx); ++ track->streamout_dirty = true; + break; + case VGT_STRMOUT_BUFFER_CONFIG: + track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); ++ track->streamout_dirty = true; + break; ++ case VGT_STRMOUT_BUFFER_BASE_0: ++ case VGT_STRMOUT_BUFFER_BASE_1: ++ case VGT_STRMOUT_BUFFER_BASE_2: ++ case VGT_STRMOUT_BUFFER_BASE_3: ++ r = evergreen_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ dev_warn(p->dev, "bad SET_CONTEXT_REG " ++ "0x%04X\n", reg); ++ return -EINVAL; ++ } ++ tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; ++ track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; ++ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); ++ track->vgt_strmout_bo[tmp] = reloc->robj; ++ track->streamout_dirty = true; ++ break; ++ case VGT_STRMOUT_BUFFER_SIZE_0: ++ case VGT_STRMOUT_BUFFER_SIZE_1: ++ case VGT_STRMOUT_BUFFER_SIZE_2: ++ case VGT_STRMOUT_BUFFER_SIZE_3: ++ tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; ++ /* size in register is DWs, convert to bytes */ ++ track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; ++ track->streamout_dirty = true; ++ break; ++ case CP_COHER_BASE: ++ r = evergreen_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ dev_warn(p->dev, "missing reloc for CP_COHER_BASE " ++ "0x%04X\n", reg); ++ return -EINVAL; ++ } ++ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + case CB_TARGET_MASK: + track->cb_target_mask = radeon_get_ib_value(p, idx); ++ track->cb_dirty = true; + break; + case CB_SHADER_MASK: + track->cb_shader_mask = radeon_get_ib_value(p, idx); ++ track->cb_dirty = true; + break; + case PA_SC_AA_CONFIG: + if (p->rdev->family >= CHIP_CAYMAN) { +@@ -631,6 +1494,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + case CB_COLOR7_VIEW: + tmp = (reg - CB_COLOR0_VIEW) / 0x3c; + track->cb_color_view[tmp] = radeon_get_ib_value(p, idx); ++ track->cb_dirty = true; + break; + case CB_COLOR8_VIEW: + case CB_COLOR9_VIEW: +@@ -638,6 +1502,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + case CB_COLOR11_VIEW: + tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8; + track->cb_color_view[tmp] = radeon_get_ib_value(p, idx); ++ track->cb_dirty = true; + break; + case CB_COLOR0_INFO: + case CB_COLOR1_INFO: +@@ -649,7 +1514,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + case CB_COLOR7_INFO: + tmp = (reg - CB_COLOR0_INFO) / 0x3c; + track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); +- if (!p->keep_tiling_flags) { ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " +@@ -659,6 +1524,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + } ++ track->cb_dirty = true; + break; + case CB_COLOR8_INFO: + case CB_COLOR9_INFO: +@@ -666,7 +1532,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + case CB_COLOR11_INFO: + tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8; + track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); +- if (!p->keep_tiling_flags) { ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " +@@ -676,6 +1542,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + } ++ track->cb_dirty = true; + break; + case CB_COLOR0_PITCH: + case CB_COLOR1_PITCH: +@@ -687,7 +1554,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + case CB_COLOR7_PITCH: + tmp = (reg - CB_COLOR0_PITCH) / 0x3c; + track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx); +- track->cb_color_pitch_idx[tmp] = idx; ++ track->cb_dirty = true; + break; + case CB_COLOR8_PITCH: + case CB_COLOR9_PITCH: +@@ -695,7 +1562,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + case CB_COLOR11_PITCH: + tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8; + track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx); +- track->cb_color_pitch_idx[tmp] = idx; ++ track->cb_dirty = true; + break; + case CB_COLOR0_SLICE: + case CB_COLOR1_SLICE: +@@ -708,6 +1575,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + tmp = (reg - CB_COLOR0_SLICE) / 0x3c; + track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); + track->cb_color_slice_idx[tmp] = idx; ++ track->cb_dirty = true; + break; + case CB_COLOR8_SLICE: + case CB_COLOR9_SLICE: +@@ -716,6 +1584,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8; + track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); + track->cb_color_slice_idx[tmp] = idx; ++ track->cb_dirty = true; + break; + case CB_COLOR0_ATTRIB: + case CB_COLOR1_ATTRIB: +@@ -725,6 +1594,30 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + case CB_COLOR5_ATTRIB: + case CB_COLOR6_ATTRIB: + case CB_COLOR7_ATTRIB: ++ r = evergreen_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ dev_warn(p->dev, "bad SET_CONTEXT_REG " ++ "0x%04X\n", reg); ++ return -EINVAL; ++ } ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { ++ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { ++ unsigned bankw, bankh, mtaspect, tile_split; ++ ++ evergreen_tiling_fields(reloc->lobj.tiling_flags, ++ &bankw, &bankh, &mtaspect, ++ &tile_split); ++ ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); ++ ib[idx] |= CB_TILE_SPLIT(tile_split) | ++ CB_BANK_WIDTH(bankw) | ++ CB_BANK_HEIGHT(bankh) | ++ CB_MACRO_TILE_ASPECT(mtaspect); ++ } ++ } ++ tmp = ((reg - CB_COLOR0_ATTRIB) / 0x3c); ++ track->cb_color_attrib[tmp] = ib[idx]; ++ track->cb_dirty = true; ++ break; + case CB_COLOR8_ATTRIB: + case CB_COLOR9_ATTRIB: + case CB_COLOR10_ATTRIB: +@@ -735,30 +1628,23 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + "0x%04X\n", reg); + return -EINVAL; + } +- if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { +- ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); +- ib[idx] |= CB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size)); ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { ++ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { ++ unsigned bankw, bankh, mtaspect, tile_split; ++ ++ evergreen_tiling_fields(reloc->lobj.tiling_flags, ++ &bankw, &bankh, &mtaspect, ++ &tile_split); ++ ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); ++ ib[idx] |= CB_TILE_SPLIT(tile_split) | ++ CB_BANK_WIDTH(bankw) | ++ CB_BANK_HEIGHT(bankh) | ++ CB_MACRO_TILE_ASPECT(mtaspect); ++ } + } +- break; +- case CB_COLOR0_DIM: +- case CB_COLOR1_DIM: +- case CB_COLOR2_DIM: +- case CB_COLOR3_DIM: +- case CB_COLOR4_DIM: +- case CB_COLOR5_DIM: +- case CB_COLOR6_DIM: +- case CB_COLOR7_DIM: +- tmp = (reg - CB_COLOR0_DIM) / 0x3c; +- track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx); +- track->cb_color_dim_idx[tmp] = idx; +- break; +- case CB_COLOR8_DIM: +- case CB_COLOR9_DIM: +- case CB_COLOR10_DIM: +- case CB_COLOR11_DIM: +- tmp = ((reg - CB_COLOR8_DIM) / 0x1c) + 8; +- track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx); +- track->cb_color_dim_idx[tmp] = idx; ++ tmp = ((reg - CB_COLOR8_ATTRIB) / 0x1c) + 8; ++ track->cb_color_attrib[tmp] = ib[idx]; ++ track->cb_dirty = true; + break; + case CB_COLOR0_FMASK: + case CB_COLOR1_FMASK: +@@ -833,8 +1719,8 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + tmp = (reg - CB_COLOR0_BASE) / 0x3c; + track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); +- track->cb_color_base_last[tmp] = ib[idx]; + track->cb_color_bo[tmp] = reloc->robj; ++ track->cb_dirty = true; + break; + case CB_COLOR8_BASE: + case CB_COLOR9_BASE: +@@ -849,8 +1735,25 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8; + track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx); + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); +- track->cb_color_base_last[tmp] = ib[idx]; + track->cb_color_bo[tmp] = reloc->robj; ++ track->cb_dirty = true; ++ break; ++ case DB_HTILE_DATA_BASE: ++ r = evergreen_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ dev_warn(p->dev, "bad SET_CONTEXT_REG " ++ "0x%04X\n", reg); ++ return -EINVAL; ++ } ++ track->htile_offset = radeon_get_ib_value(p, idx); ++ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); ++ track->htile_bo = reloc->robj; ++ track->db_dirty = true; ++ break; ++ case DB_HTILE_SURFACE: ++ /* 8x8 only */ ++ track->htile_surface = radeon_get_ib_value(p, idx); ++ track->db_dirty = true; + break; + case CB_IMMED0_BASE: + case CB_IMMED1_BASE: +@@ -864,7 +1767,6 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + case CB_IMMED9_BASE: + case CB_IMMED10_BASE: + case CB_IMMED11_BASE: +- case DB_HTILE_DATA_BASE: + case SQ_PGM_START_FS: + case SQ_PGM_START_ES: + case SQ_PGM_START_VS: +@@ -989,6 +1891,9 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; ++ case SX_MISC: ++ track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0; ++ break; + default: + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return -EINVAL; +@@ -996,22 +1901,30 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + return 0; + } + +-/** +- * evergreen_check_texture_resource() - check if register is authorized or not +- * @p: parser structure holding parsing context +- * @idx: index into the cs buffer +- * @texture: texture's bo structure +- * @mipmap: mipmap's bo structure +- * +- * This function will check that the resource has valid field and that +- * the texture and mipmap bo object are big enough to cover this resource. +- */ +-static int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx, +- struct radeon_bo *texture, +- struct radeon_bo *mipmap) ++static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + { +- /* XXX fill in */ +- return 0; ++ u32 last_reg, m, i; ++ ++ if (p->rdev->family >= CHIP_CAYMAN) ++ last_reg = ARRAY_SIZE(cayman_reg_safe_bm); ++ else ++ last_reg = ARRAY_SIZE(evergreen_reg_safe_bm); ++ ++ i = (reg >> 7); ++ if (i >= last_reg) { ++ dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); ++ return false; ++ } ++ m = 1 << ((reg >> 2) & 31); ++ if (p->rdev->family >= CHIP_CAYMAN) { ++ if (!(cayman_reg_safe_bm[i] & m)) ++ return true; ++ } else { ++ if (!(evergreen_reg_safe_bm[i] & m)) ++ return true; ++ } ++ dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); ++ return false; + } + + static int evergreen_packet3_check(struct radeon_cs_parser *p, +@@ -1036,6 +1949,8 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + { + int pred_op; + int tmp; ++ uint64_t offset; ++ + if (pkt->count != 1) { + DRM_ERROR("bad SET PREDICATION\n"); + return -EINVAL; +@@ -1059,8 +1974,12 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + return -EINVAL; + } + +- ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff); ++ offset = reloc->lobj.gpu_offset + ++ (idx_value & 0xfffffff0) + ++ ((u64)(tmp & 0xff) << 32); ++ ++ ib[idx + 0] = offset; ++ ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff); + } + break; + case PACKET3_CONTEXT_CONTROL: +@@ -1088,6 +2007,9 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + } + break; + case PACKET3_INDEX_BASE: ++ { ++ uint64_t offset; ++ + if (pkt->count != 1) { + DRM_ERROR("bad INDEX_BASE\n"); + return -EINVAL; +@@ -1097,15 +2019,24 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + DRM_ERROR("bad INDEX_BASE\n"); + return -EINVAL; + } +- ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ ++ offset = reloc->lobj.gpu_offset + ++ idx_value + ++ ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); ++ ++ ib[idx+0] = offset; ++ ib[idx+1] = upper_32_bits(offset) & 0xff; ++ + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; ++ } + case PACKET3_DRAW_INDEX: ++ { ++ uint64_t offset; + if (pkt->count != 3) { + DRM_ERROR("bad DRAW_INDEX\n"); + return -EINVAL; +@@ -1115,15 +2046,25 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + DRM_ERROR("bad DRAW_INDEX\n"); + return -EINVAL; + } +- ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ ++ offset = reloc->lobj.gpu_offset + ++ idx_value + ++ ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); ++ ++ ib[idx+0] = offset; ++ ib[idx+1] = upper_32_bits(offset) & 0xff; ++ + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; ++ } + case PACKET3_DRAW_INDEX_2: ++ { ++ uint64_t offset; ++ + if (pkt->count != 4) { + DRM_ERROR("bad DRAW_INDEX_2\n"); + return -EINVAL; +@@ -1133,14 +2074,21 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + DRM_ERROR("bad DRAW_INDEX_2\n"); + return -EINVAL; + } +- ib[idx+1] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ ++ offset = reloc->lobj.gpu_offset + ++ radeon_get_ib_value(p, idx+1) + ++ ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); ++ ++ ib[idx+1] = offset; ++ ib[idx+2] = upper_32_bits(offset) & 0xff; ++ + r = evergreen_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; ++ } + case PACKET3_DRAW_INDEX_AUTO: + if (pkt->count != 1) { + DRM_ERROR("bad DRAW_INDEX_AUTO\n"); +@@ -1231,13 +2179,20 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + } + /* bit 4 is reg (0) or mem (1) */ + if (idx_value & 0x10) { ++ uint64_t offset; ++ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad WAIT_REG_MEM\n"); + return -EINVAL; + } +- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ ++ offset = reloc->lobj.gpu_offset + ++ (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + ++ ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); ++ ++ ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffffc); ++ ib[idx+2] = upper_32_bits(offset) & 0xff; + } + break; + case PACKET3_SURFACE_SYNC: +@@ -1262,16 +2217,25 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + return -EINVAL; + } + if (pkt->count) { ++ uint64_t offset; ++ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad EVENT_WRITE\n"); + return -EINVAL; + } +- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ offset = reloc->lobj.gpu_offset + ++ (radeon_get_ib_value(p, idx+1) & 0xfffffff8) + ++ ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); ++ ++ ib[idx+1] = offset & 0xfffffff8; ++ ib[idx+2] = upper_32_bits(offset) & 0xff; + } + break; + case PACKET3_EVENT_WRITE_EOP: ++ { ++ uint64_t offset; ++ + if (pkt->count != 4) { + DRM_ERROR("bad EVENT_WRITE_EOP\n"); + return -EINVAL; +@@ -1281,10 +2245,19 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + DRM_ERROR("bad EVENT_WRITE_EOP\n"); + return -EINVAL; + } +- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ ++ offset = reloc->lobj.gpu_offset + ++ (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + ++ ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); ++ ++ ib[idx+1] = offset & 0xfffffffc; ++ ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); + break; ++ } + case PACKET3_EVENT_WRITE_EOS: ++ { ++ uint64_t offset; ++ + if (pkt->count != 3) { + DRM_ERROR("bad EVENT_WRITE_EOS\n"); + return -EINVAL; +@@ -1294,9 +2267,15 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + DRM_ERROR("bad EVENT_WRITE_EOS\n"); + return -EINVAL; + } +- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ ++ offset = reloc->lobj.gpu_offset + ++ (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + ++ ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); ++ ++ ib[idx+1] = offset & 0xfffffffc; ++ ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); + break; ++ } + case PACKET3_SET_CONFIG_REG: + start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; + end_reg = 4 * pkt->count + start_reg - 4; +@@ -1344,6 +2323,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + } + for (i = 0; i < (pkt->count / 8); i++) { + struct radeon_bo *texture, *mipmap; ++ u32 toffset, moffset; + u32 size, offset; + + switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) { +@@ -1354,32 +2334,42 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + DRM_ERROR("bad SET_RESOURCE (tex)\n"); + return -EINVAL; + } +- ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); +- if (!p->keep_tiling_flags) { ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + ib[idx+1+(i*8)+1] |= + TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { +- ib[idx+1+(i*8)+6] |= +- TEX_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size)); ++ unsigned bankw, bankh, mtaspect, tile_split; ++ ++ evergreen_tiling_fields(reloc->lobj.tiling_flags, ++ &bankw, &bankh, &mtaspect, ++ &tile_split); ++ ib[idx+1+(i*8)+6] |= TEX_TILE_SPLIT(tile_split); + ib[idx+1+(i*8)+7] |= ++ TEX_BANK_WIDTH(bankw) | ++ TEX_BANK_HEIGHT(bankh) | ++ MACRO_TILE_ASPECT(mtaspect) | + TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); + } + } + texture = reloc->robj; ++ toffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + /* tex mip base */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET_RESOURCE (tex)\n"); + return -EINVAL; + } +- ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); ++ moffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + mipmap = reloc->robj; +- r = evergreen_check_texture_resource(p, idx+1+(i*8), +- texture, mipmap); ++ r = evergreen_cs_track_validate_texture(p, texture, mipmap, idx+1+(i*8)); + if (r) + return r; ++ ib[idx+1+(i*8)+2] += toffset; ++ ib[idx+1+(i*8)+3] += moffset; + break; + case SQ_TEX_VTX_VALID_BUFFER: ++ { ++ uint64_t offset64; + /* vtx base */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { +@@ -1391,11 +2381,15 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) { + /* force size to size of the buffer */ + dev_warn(p->dev, "vbo resource seems too big for the bo\n"); +- ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj); ++ ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj) - offset; + } +- ib[idx+1+(i*8)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff); +- ib[idx+1+(i*8)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ ++ offset64 = reloc->lobj.gpu_offset + offset; ++ ib[idx+1+(i*8)+0] = offset64; ++ ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) | ++ (upper_32_bits(offset64) & 0xff); + break; ++ } + case SQ_TEX_VTX_INVALID_TEXTURE: + case SQ_TEX_VTX_INVALID_BUFFER: + default: +@@ -1451,6 +2445,104 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + return -EINVAL; + } + break; ++ case PACKET3_STRMOUT_BUFFER_UPDATE: ++ if (pkt->count != 4) { ++ DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); ++ return -EINVAL; ++ } ++ /* Updating memory at DST_ADDRESS. */ ++ if (idx_value & 0x1) { ++ u64 offset; ++ r = evergreen_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); ++ return -EINVAL; ++ } ++ offset = radeon_get_ib_value(p, idx+1); ++ offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; ++ if ((offset + 4) > radeon_bo_size(reloc->robj)) { ++ DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n", ++ offset + 4, radeon_bo_size(reloc->robj)); ++ return -EINVAL; ++ } ++ offset += reloc->lobj.gpu_offset; ++ ib[idx+1] = offset; ++ ib[idx+2] = upper_32_bits(offset) & 0xff; ++ } ++ /* Reading data from SRC_ADDRESS. */ ++ if (((idx_value >> 1) & 0x3) == 2) { ++ u64 offset; ++ r = evergreen_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); ++ return -EINVAL; ++ } ++ offset = radeon_get_ib_value(p, idx+3); ++ offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; ++ if ((offset + 4) > radeon_bo_size(reloc->robj)) { ++ DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n", ++ offset + 4, radeon_bo_size(reloc->robj)); ++ return -EINVAL; ++ } ++ offset += reloc->lobj.gpu_offset; ++ ib[idx+3] = offset; ++ ib[idx+4] = upper_32_bits(offset) & 0xff; ++ } ++ break; ++ case PACKET3_COPY_DW: ++ if (pkt->count != 4) { ++ DRM_ERROR("bad COPY_DW (invalid count)\n"); ++ return -EINVAL; ++ } ++ if (idx_value & 0x1) { ++ u64 offset; ++ /* SRC is memory. */ ++ r = evergreen_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ DRM_ERROR("bad COPY_DW (missing src reloc)\n"); ++ return -EINVAL; ++ } ++ offset = radeon_get_ib_value(p, idx+1); ++ offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; ++ if ((offset + 4) > radeon_bo_size(reloc->robj)) { ++ DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n", ++ offset + 4, radeon_bo_size(reloc->robj)); ++ return -EINVAL; ++ } ++ offset += reloc->lobj.gpu_offset; ++ ib[idx+1] = offset; ++ ib[idx+2] = upper_32_bits(offset) & 0xff; ++ } else { ++ /* SRC is a reg. */ ++ reg = radeon_get_ib_value(p, idx+1) << 2; ++ if (!evergreen_is_safe_reg(p, reg, idx+1)) ++ return -EINVAL; ++ } ++ if (idx_value & 0x2) { ++ u64 offset; ++ /* DST is memory. */ ++ r = evergreen_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); ++ return -EINVAL; ++ } ++ offset = radeon_get_ib_value(p, idx+3); ++ offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; ++ if ((offset + 4) > radeon_bo_size(reloc->robj)) { ++ DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n", ++ offset + 4, radeon_bo_size(reloc->robj)); ++ return -EINVAL; ++ } ++ offset += reloc->lobj.gpu_offset; ++ ib[idx+3] = offset; ++ ib[idx+4] = upper_32_bits(offset) & 0xff; ++ } else { ++ /* DST is a reg. */ ++ reg = radeon_get_ib_value(p, idx+3) << 2; ++ if (!evergreen_is_safe_reg(p, reg, idx+3)) ++ return -EINVAL; ++ } ++ break; + case PACKET3_NOP: + break; + default: +@@ -1572,3 +2664,247 @@ int evergreen_cs_parse(struct radeon_cs_parser *p) + return 0; + } + ++/* vm parser */ ++static bool evergreen_vm_reg_valid(u32 reg) ++{ ++ /* context regs are fine */ ++ if (reg >= 0x28000) ++ return true; ++ ++ /* check config regs */ ++ switch (reg) { ++ case WAIT_UNTIL: ++ case GRBM_GFX_INDEX: ++ case CP_STRMOUT_CNTL: ++ case CP_COHER_CNTL: ++ case CP_COHER_SIZE: ++ case VGT_VTX_VECT_EJECT_REG: ++ case VGT_CACHE_INVALIDATION: ++ case VGT_GS_VERTEX_REUSE: ++ case VGT_PRIMITIVE_TYPE: ++ case VGT_INDEX_TYPE: ++ case VGT_NUM_INDICES: ++ case VGT_NUM_INSTANCES: ++ case VGT_COMPUTE_DIM_X: ++ case VGT_COMPUTE_DIM_Y: ++ case VGT_COMPUTE_DIM_Z: ++ case VGT_COMPUTE_START_X: ++ case VGT_COMPUTE_START_Y: ++ case VGT_COMPUTE_START_Z: ++ case VGT_COMPUTE_INDEX: ++ case VGT_COMPUTE_THREAD_GROUP_SIZE: ++ case VGT_HS_OFFCHIP_PARAM: ++ case PA_CL_ENHANCE: ++ case PA_SU_LINE_STIPPLE_VALUE: ++ case PA_SC_LINE_STIPPLE_STATE: ++ case PA_SC_ENHANCE: ++ case SQ_DYN_GPR_CNTL_PS_FLUSH_REQ: ++ case SQ_DYN_GPR_SIMD_LOCK_EN: ++ case SQ_CONFIG: ++ case SQ_GPR_RESOURCE_MGMT_1: ++ case SQ_GLOBAL_GPR_RESOURCE_MGMT_1: ++ case SQ_GLOBAL_GPR_RESOURCE_MGMT_2: ++ case SQ_CONST_MEM_BASE: ++ case SQ_STATIC_THREAD_MGMT_1: ++ case SQ_STATIC_THREAD_MGMT_2: ++ case SQ_STATIC_THREAD_MGMT_3: ++ case SPI_CONFIG_CNTL: ++ case SPI_CONFIG_CNTL_1: ++ case TA_CNTL_AUX: ++ case DB_DEBUG: ++ case DB_DEBUG2: ++ case DB_DEBUG3: ++ case DB_DEBUG4: ++ case DB_WATERMARKS: ++ case TD_PS_BORDER_COLOR_INDEX: ++ case TD_PS_BORDER_COLOR_RED: ++ case TD_PS_BORDER_COLOR_GREEN: ++ case TD_PS_BORDER_COLOR_BLUE: ++ case TD_PS_BORDER_COLOR_ALPHA: ++ case TD_VS_BORDER_COLOR_INDEX: ++ case TD_VS_BORDER_COLOR_RED: ++ case TD_VS_BORDER_COLOR_GREEN: ++ case TD_VS_BORDER_COLOR_BLUE: ++ case TD_VS_BORDER_COLOR_ALPHA: ++ case TD_GS_BORDER_COLOR_INDEX: ++ case TD_GS_BORDER_COLOR_RED: ++ case TD_GS_BORDER_COLOR_GREEN: ++ case TD_GS_BORDER_COLOR_BLUE: ++ case TD_GS_BORDER_COLOR_ALPHA: ++ case TD_HS_BORDER_COLOR_INDEX: ++ case TD_HS_BORDER_COLOR_RED: ++ case TD_HS_BORDER_COLOR_GREEN: ++ case TD_HS_BORDER_COLOR_BLUE: ++ case TD_HS_BORDER_COLOR_ALPHA: ++ case TD_LS_BORDER_COLOR_INDEX: ++ case TD_LS_BORDER_COLOR_RED: ++ case TD_LS_BORDER_COLOR_GREEN: ++ case TD_LS_BORDER_COLOR_BLUE: ++ case TD_LS_BORDER_COLOR_ALPHA: ++ case TD_CS_BORDER_COLOR_INDEX: ++ case TD_CS_BORDER_COLOR_RED: ++ case TD_CS_BORDER_COLOR_GREEN: ++ case TD_CS_BORDER_COLOR_BLUE: ++ case TD_CS_BORDER_COLOR_ALPHA: ++ case SQ_ESGS_RING_SIZE: ++ case SQ_GSVS_RING_SIZE: ++ case SQ_ESTMP_RING_SIZE: ++ case SQ_GSTMP_RING_SIZE: ++ case SQ_HSTMP_RING_SIZE: ++ case SQ_LSTMP_RING_SIZE: ++ case SQ_PSTMP_RING_SIZE: ++ case SQ_VSTMP_RING_SIZE: ++ case SQ_ESGS_RING_ITEMSIZE: ++ case SQ_ESTMP_RING_ITEMSIZE: ++ case SQ_GSTMP_RING_ITEMSIZE: ++ case SQ_GSVS_RING_ITEMSIZE: ++ case SQ_GS_VERT_ITEMSIZE: ++ case SQ_GS_VERT_ITEMSIZE_1: ++ case SQ_GS_VERT_ITEMSIZE_2: ++ case SQ_GS_VERT_ITEMSIZE_3: ++ case SQ_GSVS_RING_OFFSET_1: ++ case SQ_GSVS_RING_OFFSET_2: ++ case SQ_GSVS_RING_OFFSET_3: ++ case SQ_HSTMP_RING_ITEMSIZE: ++ case SQ_LSTMP_RING_ITEMSIZE: ++ case SQ_PSTMP_RING_ITEMSIZE: ++ case SQ_VSTMP_RING_ITEMSIZE: ++ case VGT_TF_RING_SIZE: ++ case SQ_ESGS_RING_BASE: ++ case SQ_GSVS_RING_BASE: ++ case SQ_ESTMP_RING_BASE: ++ case SQ_GSTMP_RING_BASE: ++ case SQ_HSTMP_RING_BASE: ++ case SQ_LSTMP_RING_BASE: ++ case SQ_PSTMP_RING_BASE: ++ case SQ_VSTMP_RING_BASE: ++ case CAYMAN_VGT_OFFCHIP_LDS_BASE: ++ case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS: ++ return true; ++ default: ++ DRM_ERROR("Invalid register 0x%x in CS\n", reg); ++ return false; ++ } ++} ++ ++static int evergreen_vm_packet3_check(struct radeon_device *rdev, ++ u32 *ib, struct radeon_cs_packet *pkt) ++{ ++ u32 idx = pkt->idx + 1; ++ u32 idx_value = ib[idx]; ++ u32 start_reg, end_reg, reg, i; ++ ++ switch (pkt->opcode) { ++ case PACKET3_NOP: ++ case PACKET3_SET_BASE: ++ case PACKET3_CLEAR_STATE: ++ case PACKET3_INDEX_BUFFER_SIZE: ++ case PACKET3_DISPATCH_DIRECT: ++ case PACKET3_DISPATCH_INDIRECT: ++ case PACKET3_MODE_CONTROL: ++ case PACKET3_SET_PREDICATION: ++ case PACKET3_COND_EXEC: ++ case PACKET3_PRED_EXEC: ++ case PACKET3_DRAW_INDIRECT: ++ case PACKET3_DRAW_INDEX_INDIRECT: ++ case PACKET3_INDEX_BASE: ++ case PACKET3_DRAW_INDEX_2: ++ case PACKET3_CONTEXT_CONTROL: ++ case PACKET3_DRAW_INDEX_OFFSET: ++ case PACKET3_INDEX_TYPE: ++ case PACKET3_DRAW_INDEX: ++ case PACKET3_DRAW_INDEX_AUTO: ++ case PACKET3_DRAW_INDEX_IMMD: ++ case PACKET3_NUM_INSTANCES: ++ case PACKET3_DRAW_INDEX_MULTI_AUTO: ++ case PACKET3_STRMOUT_BUFFER_UPDATE: ++ case PACKET3_DRAW_INDEX_OFFSET_2: ++ case PACKET3_DRAW_INDEX_MULTI_ELEMENT: ++ case PACKET3_MPEG_INDEX: ++ case PACKET3_WAIT_REG_MEM: ++ case PACKET3_MEM_WRITE: ++ case PACKET3_SURFACE_SYNC: ++ case PACKET3_EVENT_WRITE: ++ case PACKET3_EVENT_WRITE_EOP: ++ case PACKET3_EVENT_WRITE_EOS: ++ case PACKET3_SET_CONTEXT_REG: ++ case PACKET3_SET_BOOL_CONST: ++ case PACKET3_SET_LOOP_CONST: ++ case PACKET3_SET_RESOURCE: ++ case PACKET3_SET_SAMPLER: ++ case PACKET3_SET_CTL_CONST: ++ case PACKET3_SET_RESOURCE_OFFSET: ++ case PACKET3_SET_CONTEXT_REG_INDIRECT: ++ case PACKET3_SET_RESOURCE_INDIRECT: ++ case CAYMAN_PACKET3_DEALLOC_STATE: ++ break; ++ case PACKET3_COND_WRITE: ++ if (idx_value & 0x100) { ++ reg = ib[idx + 5] * 4; ++ if (!evergreen_vm_reg_valid(reg)) ++ return -EINVAL; ++ } ++ break; ++ case PACKET3_COPY_DW: ++ if (idx_value & 0x2) { ++ reg = ib[idx + 3] * 4; ++ if (!evergreen_vm_reg_valid(reg)) ++ return -EINVAL; ++ } ++ break; ++ case PACKET3_SET_CONFIG_REG: ++ start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; ++ end_reg = 4 * pkt->count + start_reg - 4; ++ if ((start_reg < PACKET3_SET_CONFIG_REG_START) || ++ (start_reg >= PACKET3_SET_CONFIG_REG_END) || ++ (end_reg >= PACKET3_SET_CONFIG_REG_END)) { ++ DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n"); ++ return -EINVAL; ++ } ++ for (i = 0; i < pkt->count; i++) { ++ reg = start_reg + (4 * i); ++ if (!evergreen_vm_reg_valid(reg)) ++ return -EINVAL; ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) ++{ ++ int ret = 0; ++ u32 idx = 0; ++ struct radeon_cs_packet pkt; ++ ++ do { ++ pkt.idx = idx; ++ pkt.type = CP_PACKET_GET_TYPE(ib->ptr[idx]); ++ pkt.count = CP_PACKET_GET_COUNT(ib->ptr[idx]); ++ pkt.one_reg_wr = 0; ++ switch (pkt.type) { ++ case PACKET_TYPE0: ++ dev_err(rdev->dev, "Packet0 not allowed!\n"); ++ ret = -EINVAL; ++ break; ++ case PACKET_TYPE2: ++ idx += 1; ++ break; ++ case PACKET_TYPE3: ++ pkt.opcode = CP_PACKET3_GET_OPCODE(ib->ptr[idx]); ++ ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt); ++ idx += pkt.count + 2; ++ break; ++ default: ++ dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type); ++ ret = -EINVAL; ++ break; ++ } ++ if (ret) ++ break; ++ } while (idx < ib->length_dw); ++ ++ return ret; ++} +diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h +index e022776..e534e5d 100644 +--- a/drivers/gpu/drm/radeon/evergreen_reg.h ++++ b/drivers/gpu/drm/radeon/evergreen_reg.h +@@ -35,6 +35,14 @@ + #define EVERGREEN_P1PLL_SS_CNTL 0x414 + #define EVERGREEN_P2PLL_SS_CNTL 0x454 + # define EVERGREEN_PxPLL_SS_EN (1 << 12) ++ ++#define EVERGREEN_AUDIO_PLL1_MUL 0x5b0 ++#define EVERGREEN_AUDIO_PLL1_DIV 0x5b4 ++#define EVERGREEN_AUDIO_PLL1_UNK 0x5bc ++ ++#define EVERGREEN_AUDIO_ENABLE 0x5e78 ++#define EVERGREEN_AUDIO_VENDOR_ID 0x5ec0 ++ + /* GRPH blocks at 0x6800, 0x7400, 0x10000, 0x10c00, 0x11800, 0x12400 */ + #define EVERGREEN_GRPH_ENABLE 0x6800 + #define EVERGREEN_GRPH_CONTROL 0x6804 +@@ -217,10 +225,17 @@ + #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 + #define EVERGREEN_MASTER_UPDATE_MODE 0x6ef8 + #define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4 ++#define EVERGREEN_MASTER_UPDATE_LOCK 0x6ef4 ++#define EVERGREEN_MASTER_UPDATE_MODE 0x6ef8 + + #define EVERGREEN_DC_GPIO_HPD_MASK 0x64b0 + #define EVERGREEN_DC_GPIO_HPD_A 0x64b4 + #define EVERGREEN_DC_GPIO_HPD_EN 0x64b8 + #define EVERGREEN_DC_GPIO_HPD_Y 0x64bc + ++/* HDMI blocks at 0x7030, 0x7c30, 0x10830, 0x11430, 0x12030, 0x12c30 */ ++#define EVERGREEN_HDMI_BASE 0x7030 ++ ++#define EVERGREEN_HDMI_CONFIG_OFFSET 0xf0 ++ + #endif +diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h +index 47f3bd2..52aabf2 100644 +--- a/drivers/gpu/drm/radeon/evergreend.h ++++ b/drivers/gpu/drm/radeon/evergreend.h +@@ -81,6 +81,11 @@ + #define FB_READ_EN (1 << 0) + #define FB_WRITE_EN (1 << 1) + ++#define CP_STRMOUT_CNTL 0x84FC ++ ++#define CP_COHER_CNTL 0x85F0 ++#define CP_COHER_SIZE 0x85F4 ++#define CP_COHER_BASE 0x85F8 + #define CP_ME_CNTL 0x86D8 + #define CP_ME_HALT (1 << 28) + #define CP_PFP_HALT (1 << 26) +@@ -112,6 +117,7 @@ + #define CP_RB_WPTR_ADDR_HI 0xC11C + #define CP_RB_WPTR_DELAY 0x8704 + #define CP_SEM_WAIT_TIMER 0x85BC ++#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 + #define CP_DEBUG 0xC1FC + + +@@ -250,6 +256,7 @@ + #define PA_CL_ENHANCE 0x8A14 + #define CLIP_VTX_REORDER_ENA (1 << 0) + #define NUM_CLIP_SEQ(x) ((x) << 1) ++#define PA_SC_ENHANCE 0x8BF0 + #define PA_SC_AA_CONFIG 0x28C04 + #define MSAA_NUM_SAMPLES_SHIFT 0 + #define MSAA_NUM_SAMPLES_MASK 0x3 +@@ -328,6 +335,8 @@ + #define SQ_GPR_RESOURCE_MGMT_3 0x8C0C + #define NUM_HS_GPRS(x) ((x) << 0) + #define NUM_LS_GPRS(x) ((x) << 16) ++#define SQ_GLOBAL_GPR_RESOURCE_MGMT_1 0x8C10 ++#define SQ_GLOBAL_GPR_RESOURCE_MGMT_2 0x8C14 + #define SQ_THREAD_RESOURCE_MGMT 0x8C18 + #define NUM_PS_THREADS(x) ((x) << 0) + #define NUM_VS_THREADS(x) ((x) << 8) +@@ -346,6 +355,10 @@ + #define NUM_HS_STACK_ENTRIES(x) ((x) << 0) + #define NUM_LS_STACK_ENTRIES(x) ((x) << 16) + #define SQ_DYN_GPR_CNTL_PS_FLUSH_REQ 0x8D8C ++#define SQ_DYN_GPR_SIMD_LOCK_EN 0x8D94 ++#define SQ_STATIC_THREAD_MGMT_1 0x8E20 ++#define SQ_STATIC_THREAD_MGMT_2 0x8E24 ++#define SQ_STATIC_THREAD_MGMT_3 0x8E28 + #define SQ_LDS_RESOURCE_MGMT 0x8E2C + + #define SQ_MS_FIFO_SIZES 0x8CF0 +@@ -704,6 +717,7 @@ + #define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 + #define PACKET3_MEM_SEMAPHORE 0x39 + #define PACKET3_MPEG_INDEX 0x3A ++#define PACKET3_COPY_DW 0x3B + #define PACKET3_WAIT_REG_MEM 0x3C + #define PACKET3_MEM_WRITE 0x3D + #define PACKET3_INDIRECT_BUFFER 0x32 +@@ -781,6 +795,8 @@ + #define SQ_TEX_VTX_VALID_TEXTURE 0x2 + #define SQ_TEX_VTX_VALID_BUFFER 0x3 + ++#define VGT_VTX_VECT_EJECT_REG 0x88b0 ++ + #define SQ_CONST_MEM_BASE 0x8df8 + + #define SQ_ESGS_RING_BASE 0x8c40 +@@ -905,23 +921,160 @@ + #define PA_SC_SCREEN_SCISSOR_TL 0x28030 + #define PA_SC_GENERIC_SCISSOR_TL 0x28240 + #define PA_SC_WINDOW_SCISSOR_TL 0x28204 +-#define VGT_PRIMITIVE_TYPE 0x8958 + ++#define VGT_PRIMITIVE_TYPE 0x8958 ++#define VGT_INDEX_TYPE 0x895C ++ ++#define VGT_NUM_INDICES 0x8970 ++ ++#define VGT_COMPUTE_DIM_X 0x8990 ++#define VGT_COMPUTE_DIM_Y 0x8994 ++#define VGT_COMPUTE_DIM_Z 0x8998 ++#define VGT_COMPUTE_START_X 0x899C ++#define VGT_COMPUTE_START_Y 0x89A0 ++#define VGT_COMPUTE_START_Z 0x89A4 ++#define VGT_COMPUTE_INDEX 0x89A8 ++#define VGT_COMPUTE_THREAD_GROUP_SIZE 0x89AC ++#define VGT_HS_OFFCHIP_PARAM 0x89B0 ++ ++#define DB_DEBUG 0x9830 ++#define DB_DEBUG2 0x9834 ++#define DB_DEBUG3 0x9838 ++#define DB_DEBUG4 0x983C ++#define DB_WATERMARKS 0x9854 + #define DB_DEPTH_CONTROL 0x28800 ++#define R_028800_DB_DEPTH_CONTROL 0x028800 ++#define S_028800_STENCIL_ENABLE(x) (((x) & 0x1) << 0) ++#define G_028800_STENCIL_ENABLE(x) (((x) >> 0) & 0x1) ++#define C_028800_STENCIL_ENABLE 0xFFFFFFFE ++#define S_028800_Z_ENABLE(x) (((x) & 0x1) << 1) ++#define G_028800_Z_ENABLE(x) (((x) >> 1) & 0x1) ++#define C_028800_Z_ENABLE 0xFFFFFFFD ++#define S_028800_Z_WRITE_ENABLE(x) (((x) & 0x1) << 2) ++#define G_028800_Z_WRITE_ENABLE(x) (((x) >> 2) & 0x1) ++#define C_028800_Z_WRITE_ENABLE 0xFFFFFFFB ++#define S_028800_ZFUNC(x) (((x) & 0x7) << 4) ++#define G_028800_ZFUNC(x) (((x) >> 4) & 0x7) ++#define C_028800_ZFUNC 0xFFFFFF8F ++#define S_028800_BACKFACE_ENABLE(x) (((x) & 0x1) << 7) ++#define G_028800_BACKFACE_ENABLE(x) (((x) >> 7) & 0x1) ++#define C_028800_BACKFACE_ENABLE 0xFFFFFF7F ++#define S_028800_STENCILFUNC(x) (((x) & 0x7) << 8) ++#define G_028800_STENCILFUNC(x) (((x) >> 8) & 0x7) ++#define C_028800_STENCILFUNC 0xFFFFF8FF ++#define V_028800_STENCILFUNC_NEVER 0x00000000 ++#define V_028800_STENCILFUNC_LESS 0x00000001 ++#define V_028800_STENCILFUNC_EQUAL 0x00000002 ++#define V_028800_STENCILFUNC_LEQUAL 0x00000003 ++#define V_028800_STENCILFUNC_GREATER 0x00000004 ++#define V_028800_STENCILFUNC_NOTEQUAL 0x00000005 ++#define V_028800_STENCILFUNC_GEQUAL 0x00000006 ++#define V_028800_STENCILFUNC_ALWAYS 0x00000007 ++#define S_028800_STENCILFAIL(x) (((x) & 0x7) << 11) ++#define G_028800_STENCILFAIL(x) (((x) >> 11) & 0x7) ++#define C_028800_STENCILFAIL 0xFFFFC7FF ++#define V_028800_STENCIL_KEEP 0x00000000 ++#define V_028800_STENCIL_ZERO 0x00000001 ++#define V_028800_STENCIL_REPLACE 0x00000002 ++#define V_028800_STENCIL_INCR 0x00000003 ++#define V_028800_STENCIL_DECR 0x00000004 ++#define V_028800_STENCIL_INVERT 0x00000005 ++#define V_028800_STENCIL_INCR_WRAP 0x00000006 ++#define V_028800_STENCIL_DECR_WRAP 0x00000007 ++#define S_028800_STENCILZPASS(x) (((x) & 0x7) << 14) ++#define G_028800_STENCILZPASS(x) (((x) >> 14) & 0x7) ++#define C_028800_STENCILZPASS 0xFFFE3FFF ++#define S_028800_STENCILZFAIL(x) (((x) & 0x7) << 17) ++#define G_028800_STENCILZFAIL(x) (((x) >> 17) & 0x7) ++#define C_028800_STENCILZFAIL 0xFFF1FFFF ++#define S_028800_STENCILFUNC_BF(x) (((x) & 0x7) << 20) ++#define G_028800_STENCILFUNC_BF(x) (((x) >> 20) & 0x7) ++#define C_028800_STENCILFUNC_BF 0xFF8FFFFF ++#define S_028800_STENCILFAIL_BF(x) (((x) & 0x7) << 23) ++#define G_028800_STENCILFAIL_BF(x) (((x) >> 23) & 0x7) ++#define C_028800_STENCILFAIL_BF 0xFC7FFFFF ++#define S_028800_STENCILZPASS_BF(x) (((x) & 0x7) << 26) ++#define G_028800_STENCILZPASS_BF(x) (((x) >> 26) & 0x7) ++#define C_028800_STENCILZPASS_BF 0xE3FFFFFF ++#define S_028800_STENCILZFAIL_BF(x) (((x) & 0x7) << 29) ++#define G_028800_STENCILZFAIL_BF(x) (((x) >> 29) & 0x7) ++#define C_028800_STENCILZFAIL_BF 0x1FFFFFFF + #define DB_DEPTH_VIEW 0x28008 ++#define R_028008_DB_DEPTH_VIEW 0x00028008 ++#define S_028008_SLICE_START(x) (((x) & 0x7FF) << 0) ++#define G_028008_SLICE_START(x) (((x) >> 0) & 0x7FF) ++#define C_028008_SLICE_START 0xFFFFF800 ++#define S_028008_SLICE_MAX(x) (((x) & 0x7FF) << 13) ++#define G_028008_SLICE_MAX(x) (((x) >> 13) & 0x7FF) ++#define C_028008_SLICE_MAX 0xFF001FFF + #define DB_HTILE_DATA_BASE 0x28014 ++#define DB_HTILE_SURFACE 0x28abc ++#define S_028ABC_HTILE_WIDTH(x) (((x) & 0x1) << 0) ++#define G_028ABC_HTILE_WIDTH(x) (((x) >> 0) & 0x1) ++#define C_028ABC_HTILE_WIDTH 0xFFFFFFFE ++#define S_028ABC_HTILE_HEIGHT(x) (((x) & 0x1) << 1) ++#define G_028ABC_HTILE_HEIGHT(x) (((x) >> 1) & 0x1) ++#define C_028ABC_HTILE_HEIGHT 0xFFFFFFFD ++#define G_028ABC_LINEAR(x) (((x) >> 2) & 0x1) + #define DB_Z_INFO 0x28040 + # define Z_ARRAY_MODE(x) ((x) << 4) + # define DB_TILE_SPLIT(x) (((x) & 0x7) << 8) + # define DB_NUM_BANKS(x) (((x) & 0x3) << 12) + # define DB_BANK_WIDTH(x) (((x) & 0x3) << 16) + # define DB_BANK_HEIGHT(x) (((x) & 0x3) << 20) ++# define DB_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 24) ++#define R_028040_DB_Z_INFO 0x028040 ++#define S_028040_FORMAT(x) (((x) & 0x3) << 0) ++#define G_028040_FORMAT(x) (((x) >> 0) & 0x3) ++#define C_028040_FORMAT 0xFFFFFFFC ++#define V_028040_Z_INVALID 0x00000000 ++#define V_028040_Z_16 0x00000001 ++#define V_028040_Z_24 0x00000002 ++#define V_028040_Z_32_FLOAT 0x00000003 ++#define S_028040_ARRAY_MODE(x) (((x) & 0xF) << 4) ++#define G_028040_ARRAY_MODE(x) (((x) >> 4) & 0xF) ++#define C_028040_ARRAY_MODE 0xFFFFFF0F ++#define S_028040_READ_SIZE(x) (((x) & 0x1) << 28) ++#define G_028040_READ_SIZE(x) (((x) >> 28) & 0x1) ++#define C_028040_READ_SIZE 0xEFFFFFFF ++#define S_028040_TILE_SURFACE_ENABLE(x) (((x) & 0x1) << 29) ++#define G_028040_TILE_SURFACE_ENABLE(x) (((x) >> 29) & 0x1) ++#define C_028040_TILE_SURFACE_ENABLE 0xDFFFFFFF ++#define S_028040_ZRANGE_PRECISION(x) (((x) & 0x1) << 31) ++#define G_028040_ZRANGE_PRECISION(x) (((x) >> 31) & 0x1) ++#define C_028040_ZRANGE_PRECISION 0x7FFFFFFF ++#define S_028040_TILE_SPLIT(x) (((x) & 0x7) << 8) ++#define G_028040_TILE_SPLIT(x) (((x) >> 8) & 0x7) ++#define S_028040_NUM_BANKS(x) (((x) & 0x3) << 12) ++#define G_028040_NUM_BANKS(x) (((x) >> 12) & 0x3) ++#define S_028040_BANK_WIDTH(x) (((x) & 0x3) << 16) ++#define G_028040_BANK_WIDTH(x) (((x) >> 16) & 0x3) ++#define S_028040_BANK_HEIGHT(x) (((x) & 0x3) << 20) ++#define G_028040_BANK_HEIGHT(x) (((x) >> 20) & 0x3) ++#define S_028040_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 24) ++#define G_028040_MACRO_TILE_ASPECT(x) (((x) >> 24) & 0x3) + #define DB_STENCIL_INFO 0x28044 ++#define R_028044_DB_STENCIL_INFO 0x028044 ++#define S_028044_FORMAT(x) (((x) & 0x1) << 0) ++#define G_028044_FORMAT(x) (((x) >> 0) & 0x1) ++#define C_028044_FORMAT 0xFFFFFFFE ++#define G_028044_TILE_SPLIT(x) (((x) >> 8) & 0x7) + #define DB_Z_READ_BASE 0x28048 + #define DB_STENCIL_READ_BASE 0x2804c + #define DB_Z_WRITE_BASE 0x28050 + #define DB_STENCIL_WRITE_BASE 0x28054 + #define DB_DEPTH_SIZE 0x28058 ++#define R_028058_DB_DEPTH_SIZE 0x028058 ++#define S_028058_PITCH_TILE_MAX(x) (((x) & 0x7FF) << 0) ++#define G_028058_PITCH_TILE_MAX(x) (((x) >> 0) & 0x7FF) ++#define C_028058_PITCH_TILE_MAX 0xFFFFF800 ++#define S_028058_HEIGHT_TILE_MAX(x) (((x) & 0x7FF) << 11) ++#define G_028058_HEIGHT_TILE_MAX(x) (((x) >> 11) & 0x7FF) ++#define C_028058_HEIGHT_TILE_MAX 0xFFC007FF ++#define R_02805C_DB_DEPTH_SLICE 0x02805C ++#define S_02805C_SLICE_TILE_MAX(x) (((x) & 0x3FFFFF) << 0) ++#define G_02805C_SLICE_TILE_MAX(x) (((x) >> 0) & 0x3FFFFF) ++#define C_02805C_SLICE_TILE_MAX 0xFFC00000 + + #define SQ_PGM_START_PS 0x28840 + #define SQ_PGM_START_VS 0x2885c +@@ -931,6 +1084,14 @@ + #define SQ_PGM_START_HS 0x288b8 + #define SQ_PGM_START_LS 0x288d0 + ++#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 ++#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 ++#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 ++#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 ++#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 ++#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 ++#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 ++#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 + #define VGT_STRMOUT_CONFIG 0x28b94 + #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98 + +@@ -957,6 +1118,114 @@ + #define CB_COLOR0_PITCH 0x28c64 + #define CB_COLOR0_SLICE 0x28c68 + #define CB_COLOR0_VIEW 0x28c6c ++#define R_028C6C_CB_COLOR0_VIEW 0x00028C6C ++#define S_028C6C_SLICE_START(x) (((x) & 0x7FF) << 0) ++#define G_028C6C_SLICE_START(x) (((x) >> 0) & 0x7FF) ++#define C_028C6C_SLICE_START 0xFFFFF800 ++#define S_028C6C_SLICE_MAX(x) (((x) & 0x7FF) << 13) ++#define G_028C6C_SLICE_MAX(x) (((x) >> 13) & 0x7FF) ++#define C_028C6C_SLICE_MAX 0xFF001FFF ++#define R_028C70_CB_COLOR0_INFO 0x028C70 ++#define S_028C70_ENDIAN(x) (((x) & 0x3) << 0) ++#define G_028C70_ENDIAN(x) (((x) >> 0) & 0x3) ++#define C_028C70_ENDIAN 0xFFFFFFFC ++#define S_028C70_FORMAT(x) (((x) & 0x3F) << 2) ++#define G_028C70_FORMAT(x) (((x) >> 2) & 0x3F) ++#define C_028C70_FORMAT 0xFFFFFF03 ++#define V_028C70_COLOR_INVALID 0x00000000 ++#define V_028C70_COLOR_8 0x00000001 ++#define V_028C70_COLOR_4_4 0x00000002 ++#define V_028C70_COLOR_3_3_2 0x00000003 ++#define V_028C70_COLOR_16 0x00000005 ++#define V_028C70_COLOR_16_FLOAT 0x00000006 ++#define V_028C70_COLOR_8_8 0x00000007 ++#define V_028C70_COLOR_5_6_5 0x00000008 ++#define V_028C70_COLOR_6_5_5 0x00000009 ++#define V_028C70_COLOR_1_5_5_5 0x0000000A ++#define V_028C70_COLOR_4_4_4_4 0x0000000B ++#define V_028C70_COLOR_5_5_5_1 0x0000000C ++#define V_028C70_COLOR_32 0x0000000D ++#define V_028C70_COLOR_32_FLOAT 0x0000000E ++#define V_028C70_COLOR_16_16 0x0000000F ++#define V_028C70_COLOR_16_16_FLOAT 0x00000010 ++#define V_028C70_COLOR_8_24 0x00000011 ++#define V_028C70_COLOR_8_24_FLOAT 0x00000012 ++#define V_028C70_COLOR_24_8 0x00000013 ++#define V_028C70_COLOR_24_8_FLOAT 0x00000014 ++#define V_028C70_COLOR_10_11_11 0x00000015 ++#define V_028C70_COLOR_10_11_11_FLOAT 0x00000016 ++#define V_028C70_COLOR_11_11_10 0x00000017 ++#define V_028C70_COLOR_11_11_10_FLOAT 0x00000018 ++#define V_028C70_COLOR_2_10_10_10 0x00000019 ++#define V_028C70_COLOR_8_8_8_8 0x0000001A ++#define V_028C70_COLOR_10_10_10_2 0x0000001B ++#define V_028C70_COLOR_X24_8_32_FLOAT 0x0000001C ++#define V_028C70_COLOR_32_32 0x0000001D ++#define V_028C70_COLOR_32_32_FLOAT 0x0000001E ++#define V_028C70_COLOR_16_16_16_16 0x0000001F ++#define V_028C70_COLOR_16_16_16_16_FLOAT 0x00000020 ++#define V_028C70_COLOR_32_32_32_32 0x00000022 ++#define V_028C70_COLOR_32_32_32_32_FLOAT 0x00000023 ++#define V_028C70_COLOR_32_32_32_FLOAT 0x00000030 ++#define S_028C70_ARRAY_MODE(x) (((x) & 0xF) << 8) ++#define G_028C70_ARRAY_MODE(x) (((x) >> 8) & 0xF) ++#define C_028C70_ARRAY_MODE 0xFFFFF0FF ++#define V_028C70_ARRAY_LINEAR_GENERAL 0x00000000 ++#define V_028C70_ARRAY_LINEAR_ALIGNED 0x00000001 ++#define V_028C70_ARRAY_1D_TILED_THIN1 0x00000002 ++#define V_028C70_ARRAY_2D_TILED_THIN1 0x00000004 ++#define S_028C70_NUMBER_TYPE(x) (((x) & 0x7) << 12) ++#define G_028C70_NUMBER_TYPE(x) (((x) >> 12) & 0x7) ++#define C_028C70_NUMBER_TYPE 0xFFFF8FFF ++#define V_028C70_NUMBER_UNORM 0x00000000 ++#define V_028C70_NUMBER_SNORM 0x00000001 ++#define V_028C70_NUMBER_USCALED 0x00000002 ++#define V_028C70_NUMBER_SSCALED 0x00000003 ++#define V_028C70_NUMBER_UINT 0x00000004 ++#define V_028C70_NUMBER_SINT 0x00000005 ++#define V_028C70_NUMBER_SRGB 0x00000006 ++#define V_028C70_NUMBER_FLOAT 0x00000007 ++#define S_028C70_COMP_SWAP(x) (((x) & 0x3) << 15) ++#define G_028C70_COMP_SWAP(x) (((x) >> 15) & 0x3) ++#define C_028C70_COMP_SWAP 0xFFFE7FFF ++#define V_028C70_SWAP_STD 0x00000000 ++#define V_028C70_SWAP_ALT 0x00000001 ++#define V_028C70_SWAP_STD_REV 0x00000002 ++#define V_028C70_SWAP_ALT_REV 0x00000003 ++#define S_028C70_FAST_CLEAR(x) (((x) & 0x1) << 17) ++#define G_028C70_FAST_CLEAR(x) (((x) >> 17) & 0x1) ++#define C_028C70_FAST_CLEAR 0xFFFDFFFF ++#define S_028C70_COMPRESSION(x) (((x) & 0x3) << 18) ++#define G_028C70_COMPRESSION(x) (((x) >> 18) & 0x3) ++#define C_028C70_COMPRESSION 0xFFF3FFFF ++#define S_028C70_BLEND_CLAMP(x) (((x) & 0x1) << 19) ++#define G_028C70_BLEND_CLAMP(x) (((x) >> 19) & 0x1) ++#define C_028C70_BLEND_CLAMP 0xFFF7FFFF ++#define S_028C70_BLEND_BYPASS(x) (((x) & 0x1) << 20) ++#define G_028C70_BLEND_BYPASS(x) (((x) >> 20) & 0x1) ++#define C_028C70_BLEND_BYPASS 0xFFEFFFFF ++#define S_028C70_SIMPLE_FLOAT(x) (((x) & 0x1) << 21) ++#define G_028C70_SIMPLE_FLOAT(x) (((x) >> 21) & 0x1) ++#define C_028C70_SIMPLE_FLOAT 0xFFDFFFFF ++#define S_028C70_ROUND_MODE(x) (((x) & 0x1) << 22) ++#define G_028C70_ROUND_MODE(x) (((x) >> 22) & 0x1) ++#define C_028C70_ROUND_MODE 0xFFBFFFFF ++#define S_028C70_TILE_COMPACT(x) (((x) & 0x1) << 23) ++#define G_028C70_TILE_COMPACT(x) (((x) >> 23) & 0x1) ++#define C_028C70_TILE_COMPACT 0xFF7FFFFF ++#define S_028C70_SOURCE_FORMAT(x) (((x) & 0x3) << 24) ++#define G_028C70_SOURCE_FORMAT(x) (((x) >> 24) & 0x3) ++#define C_028C70_SOURCE_FORMAT 0xFCFFFFFF ++#define V_028C70_EXPORT_4C_32BPC 0x0 ++#define V_028C70_EXPORT_4C_16BPC 0x1 ++#define V_028C70_EXPORT_2C_32BPC 0x2 /* Do not use */ ++#define S_028C70_RAT(x) (((x) & 0x1) << 26) ++#define G_028C70_RAT(x) (((x) >> 26) & 0x1) ++#define C_028C70_RAT 0xFBFFFFFF ++#define S_028C70_RESOURCE_TYPE(x) (((x) & 0x7) << 27) ++#define G_028C70_RESOURCE_TYPE(x) (((x) >> 27) & 0x7) ++#define C_028C70_RESOURCE_TYPE 0xC7FFFFFF ++ + #define CB_COLOR0_INFO 0x28c70 + # define CB_FORMAT(x) ((x) << 2) + # define CB_ARRAY_MODE(x) ((x) << 8) +@@ -967,6 +1236,20 @@ + # define CB_SOURCE_FORMAT(x) ((x) << 24) + # define CB_SF_EXPORT_FULL 0 + # define CB_SF_EXPORT_NORM 1 ++#define R_028C74_CB_COLOR0_ATTRIB 0x028C74 ++#define S_028C74_NON_DISP_TILING_ORDER(x) (((x) & 0x1) << 4) ++#define G_028C74_NON_DISP_TILING_ORDER(x) (((x) >> 4) & 0x1) ++#define C_028C74_NON_DISP_TILING_ORDER 0xFFFFFFEF ++#define S_028C74_TILE_SPLIT(x) (((x) & 0xf) << 5) ++#define G_028C74_TILE_SPLIT(x) (((x) >> 5) & 0xf) ++#define S_028C74_NUM_BANKS(x) (((x) & 0x3) << 10) ++#define G_028C74_NUM_BANKS(x) (((x) >> 10) & 0x3) ++#define S_028C74_BANK_WIDTH(x) (((x) & 0x3) << 13) ++#define G_028C74_BANK_WIDTH(x) (((x) >> 13) & 0x3) ++#define S_028C74_BANK_HEIGHT(x) (((x) & 0x3) << 16) ++#define G_028C74_BANK_HEIGHT(x) (((x) >> 16) & 0x3) ++#define S_028C74_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 19) ++#define G_028C74_MACRO_TILE_ASPECT(x) (((x) >> 19) & 0x3) + #define CB_COLOR0_ATTRIB 0x28c74 + # define CB_TILE_SPLIT(x) (((x) & 0x7) << 5) + # define ADDR_SURF_TILE_SPLIT_64B 0 +@@ -991,6 +1274,7 @@ + # define ADDR_SURF_BANK_HEIGHT_2 1 + # define ADDR_SURF_BANK_HEIGHT_4 2 + # define ADDR_SURF_BANK_HEIGHT_8 3 ++# define CB_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 19) + #define CB_COLOR0_DIM 0x28c78 + /* only CB0-7 blocks have these regs */ + #define CB_COLOR0_CMASK 0x28c7c +@@ -1179,9 +1463,144 @@ + #define SQ_TEX_RESOURCE_WORD6_0 0x30018 + # define TEX_TILE_SPLIT(x) (((x) & 0x7) << 29) + #define SQ_TEX_RESOURCE_WORD7_0 0x3001c ++# define MACRO_TILE_ASPECT(x) (((x) & 0x3) << 6) + # define TEX_BANK_WIDTH(x) (((x) & 0x3) << 8) + # define TEX_BANK_HEIGHT(x) (((x) & 0x3) << 10) + # define TEX_NUM_BANKS(x) (((x) & 0x3) << 16) ++#define R_030000_SQ_TEX_RESOURCE_WORD0_0 0x030000 ++#define S_030000_DIM(x) (((x) & 0x7) << 0) ++#define G_030000_DIM(x) (((x) >> 0) & 0x7) ++#define C_030000_DIM 0xFFFFFFF8 ++#define V_030000_SQ_TEX_DIM_1D 0x00000000 ++#define V_030000_SQ_TEX_DIM_2D 0x00000001 ++#define V_030000_SQ_TEX_DIM_3D 0x00000002 ++#define V_030000_SQ_TEX_DIM_CUBEMAP 0x00000003 ++#define V_030000_SQ_TEX_DIM_1D_ARRAY 0x00000004 ++#define V_030000_SQ_TEX_DIM_2D_ARRAY 0x00000005 ++#define V_030000_SQ_TEX_DIM_2D_MSAA 0x00000006 ++#define V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA 0x00000007 ++#define S_030000_NON_DISP_TILING_ORDER(x) (((x) & 0x1) << 5) ++#define G_030000_NON_DISP_TILING_ORDER(x) (((x) >> 5) & 0x1) ++#define C_030000_NON_DISP_TILING_ORDER 0xFFFFFFDF ++#define S_030000_PITCH(x) (((x) & 0xFFF) << 6) ++#define G_030000_PITCH(x) (((x) >> 6) & 0xFFF) ++#define C_030000_PITCH 0xFFFC003F ++#define S_030000_TEX_WIDTH(x) (((x) & 0x3FFF) << 18) ++#define G_030000_TEX_WIDTH(x) (((x) >> 18) & 0x3FFF) ++#define C_030000_TEX_WIDTH 0x0003FFFF ++#define R_030004_SQ_TEX_RESOURCE_WORD1_0 0x030004 ++#define S_030004_TEX_HEIGHT(x) (((x) & 0x3FFF) << 0) ++#define G_030004_TEX_HEIGHT(x) (((x) >> 0) & 0x3FFF) ++#define C_030004_TEX_HEIGHT 0xFFFFC000 ++#define S_030004_TEX_DEPTH(x) (((x) & 0x1FFF) << 14) ++#define G_030004_TEX_DEPTH(x) (((x) >> 14) & 0x1FFF) ++#define C_030004_TEX_DEPTH 0xF8003FFF ++#define S_030004_ARRAY_MODE(x) (((x) & 0xF) << 28) ++#define G_030004_ARRAY_MODE(x) (((x) >> 28) & 0xF) ++#define C_030004_ARRAY_MODE 0x0FFFFFFF ++#define R_030008_SQ_TEX_RESOURCE_WORD2_0 0x030008 ++#define S_030008_BASE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0) ++#define G_030008_BASE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF) ++#define C_030008_BASE_ADDRESS 0x00000000 ++#define R_03000C_SQ_TEX_RESOURCE_WORD3_0 0x03000C ++#define S_03000C_MIP_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0) ++#define G_03000C_MIP_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF) ++#define C_03000C_MIP_ADDRESS 0x00000000 ++#define R_030010_SQ_TEX_RESOURCE_WORD4_0 0x030010 ++#define S_030010_FORMAT_COMP_X(x) (((x) & 0x3) << 0) ++#define G_030010_FORMAT_COMP_X(x) (((x) >> 0) & 0x3) ++#define C_030010_FORMAT_COMP_X 0xFFFFFFFC ++#define V_030010_SQ_FORMAT_COMP_UNSIGNED 0x00000000 ++#define V_030010_SQ_FORMAT_COMP_SIGNED 0x00000001 ++#define V_030010_SQ_FORMAT_COMP_UNSIGNED_BIASED 0x00000002 ++#define S_030010_FORMAT_COMP_Y(x) (((x) & 0x3) << 2) ++#define G_030010_FORMAT_COMP_Y(x) (((x) >> 2) & 0x3) ++#define C_030010_FORMAT_COMP_Y 0xFFFFFFF3 ++#define S_030010_FORMAT_COMP_Z(x) (((x) & 0x3) << 4) ++#define G_030010_FORMAT_COMP_Z(x) (((x) >> 4) & 0x3) ++#define C_030010_FORMAT_COMP_Z 0xFFFFFFCF ++#define S_030010_FORMAT_COMP_W(x) (((x) & 0x3) << 6) ++#define G_030010_FORMAT_COMP_W(x) (((x) >> 6) & 0x3) ++#define C_030010_FORMAT_COMP_W 0xFFFFFF3F ++#define S_030010_NUM_FORMAT_ALL(x) (((x) & 0x3) << 8) ++#define G_030010_NUM_FORMAT_ALL(x) (((x) >> 8) & 0x3) ++#define C_030010_NUM_FORMAT_ALL 0xFFFFFCFF ++#define V_030010_SQ_NUM_FORMAT_NORM 0x00000000 ++#define V_030010_SQ_NUM_FORMAT_INT 0x00000001 ++#define V_030010_SQ_NUM_FORMAT_SCALED 0x00000002 ++#define S_030010_SRF_MODE_ALL(x) (((x) & 0x1) << 10) ++#define G_030010_SRF_MODE_ALL(x) (((x) >> 10) & 0x1) ++#define C_030010_SRF_MODE_ALL 0xFFFFFBFF ++#define V_030010_SRF_MODE_ZERO_CLAMP_MINUS_ONE 0x00000000 ++#define V_030010_SRF_MODE_NO_ZERO 0x00000001 ++#define S_030010_FORCE_DEGAMMA(x) (((x) & 0x1) << 11) ++#define G_030010_FORCE_DEGAMMA(x) (((x) >> 11) & 0x1) ++#define C_030010_FORCE_DEGAMMA 0xFFFFF7FF ++#define S_030010_ENDIAN_SWAP(x) (((x) & 0x3) << 12) ++#define G_030010_ENDIAN_SWAP(x) (((x) >> 12) & 0x3) ++#define C_030010_ENDIAN_SWAP 0xFFFFCFFF ++#define S_030010_DST_SEL_X(x) (((x) & 0x7) << 16) ++#define G_030010_DST_SEL_X(x) (((x) >> 16) & 0x7) ++#define C_030010_DST_SEL_X 0xFFF8FFFF ++#define V_030010_SQ_SEL_X 0x00000000 ++#define V_030010_SQ_SEL_Y 0x00000001 ++#define V_030010_SQ_SEL_Z 0x00000002 ++#define V_030010_SQ_SEL_W 0x00000003 ++#define V_030010_SQ_SEL_0 0x00000004 ++#define V_030010_SQ_SEL_1 0x00000005 ++#define S_030010_DST_SEL_Y(x) (((x) & 0x7) << 19) ++#define G_030010_DST_SEL_Y(x) (((x) >> 19) & 0x7) ++#define C_030010_DST_SEL_Y 0xFFC7FFFF ++#define S_030010_DST_SEL_Z(x) (((x) & 0x7) << 22) ++#define G_030010_DST_SEL_Z(x) (((x) >> 22) & 0x7) ++#define C_030010_DST_SEL_Z 0xFE3FFFFF ++#define S_030010_DST_SEL_W(x) (((x) & 0x7) << 25) ++#define G_030010_DST_SEL_W(x) (((x) >> 25) & 0x7) ++#define C_030010_DST_SEL_W 0xF1FFFFFF ++#define S_030010_BASE_LEVEL(x) (((x) & 0xF) << 28) ++#define G_030010_BASE_LEVEL(x) (((x) >> 28) & 0xF) ++#define C_030010_BASE_LEVEL 0x0FFFFFFF ++#define R_030014_SQ_TEX_RESOURCE_WORD5_0 0x030014 ++#define S_030014_LAST_LEVEL(x) (((x) & 0xF) << 0) ++#define G_030014_LAST_LEVEL(x) (((x) >> 0) & 0xF) ++#define C_030014_LAST_LEVEL 0xFFFFFFF0 ++#define S_030014_BASE_ARRAY(x) (((x) & 0x1FFF) << 4) ++#define G_030014_BASE_ARRAY(x) (((x) >> 4) & 0x1FFF) ++#define C_030014_BASE_ARRAY 0xFFFE000F ++#define S_030014_LAST_ARRAY(x) (((x) & 0x1FFF) << 17) ++#define G_030014_LAST_ARRAY(x) (((x) >> 17) & 0x1FFF) ++#define C_030014_LAST_ARRAY 0xC001FFFF ++#define R_030018_SQ_TEX_RESOURCE_WORD6_0 0x030018 ++#define S_030018_MAX_ANISO(x) (((x) & 0x7) << 0) ++#define G_030018_MAX_ANISO(x) (((x) >> 0) & 0x7) ++#define C_030018_MAX_ANISO 0xFFFFFFF8 ++#define S_030018_PERF_MODULATION(x) (((x) & 0x7) << 3) ++#define G_030018_PERF_MODULATION(x) (((x) >> 3) & 0x7) ++#define C_030018_PERF_MODULATION 0xFFFFFFC7 ++#define S_030018_INTERLACED(x) (((x) & 0x1) << 6) ++#define G_030018_INTERLACED(x) (((x) >> 6) & 0x1) ++#define C_030018_INTERLACED 0xFFFFFFBF ++#define S_030018_TILE_SPLIT(x) (((x) & 0x7) << 29) ++#define G_030018_TILE_SPLIT(x) (((x) >> 29) & 0x7) ++#define R_03001C_SQ_TEX_RESOURCE_WORD7_0 0x03001C ++#define S_03001C_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 6) ++#define G_03001C_MACRO_TILE_ASPECT(x) (((x) >> 6) & 0x3) ++#define S_03001C_BANK_WIDTH(x) (((x) & 0x3) << 8) ++#define G_03001C_BANK_WIDTH(x) (((x) >> 8) & 0x3) ++#define S_03001C_BANK_HEIGHT(x) (((x) & 0x3) << 10) ++#define G_03001C_BANK_HEIGHT(x) (((x) >> 10) & 0x3) ++#define S_03001C_NUM_BANKS(x) (((x) & 0x3) << 16) ++#define G_03001C_NUM_BANKS(x) (((x) >> 16) & 0x3) ++#define S_03001C_TYPE(x) (((x) & 0x3) << 30) ++#define G_03001C_TYPE(x) (((x) >> 30) & 0x3) ++#define C_03001C_TYPE 0x3FFFFFFF ++#define V_03001C_SQ_TEX_VTX_INVALID_TEXTURE 0x00000000 ++#define V_03001C_SQ_TEX_VTX_INVALID_BUFFER 0x00000001 ++#define V_03001C_SQ_TEX_VTX_VALID_TEXTURE 0x00000002 ++#define V_03001C_SQ_TEX_VTX_VALID_BUFFER 0x00000003 ++#define S_03001C_DATA_FORMAT(x) (((x) & 0x3F) << 0) ++#define G_03001C_DATA_FORMAT(x) (((x) >> 0) & 0x3F) ++#define C_03001C_DATA_FORMAT 0xFFFFFFC0 + + #define SQ_VTX_CONSTANT_WORD0_0 0x30000 + #define SQ_VTX_CONSTANT_WORD1_0 0x30004 +@@ -1202,8 +1621,40 @@ + #define SQ_VTX_CONSTANT_WORD6_0 0x30018 + #define SQ_VTX_CONSTANT_WORD7_0 0x3001c + ++#define TD_PS_BORDER_COLOR_INDEX 0xA400 ++#define TD_PS_BORDER_COLOR_RED 0xA404 ++#define TD_PS_BORDER_COLOR_GREEN 0xA408 ++#define TD_PS_BORDER_COLOR_BLUE 0xA40C ++#define TD_PS_BORDER_COLOR_ALPHA 0xA410 ++#define TD_VS_BORDER_COLOR_INDEX 0xA414 ++#define TD_VS_BORDER_COLOR_RED 0xA418 ++#define TD_VS_BORDER_COLOR_GREEN 0xA41C ++#define TD_VS_BORDER_COLOR_BLUE 0xA420 ++#define TD_VS_BORDER_COLOR_ALPHA 0xA424 ++#define TD_GS_BORDER_COLOR_INDEX 0xA428 ++#define TD_GS_BORDER_COLOR_RED 0xA42C ++#define TD_GS_BORDER_COLOR_GREEN 0xA430 ++#define TD_GS_BORDER_COLOR_BLUE 0xA434 ++#define TD_GS_BORDER_COLOR_ALPHA 0xA438 ++#define TD_HS_BORDER_COLOR_INDEX 0xA43C ++#define TD_HS_BORDER_COLOR_RED 0xA440 ++#define TD_HS_BORDER_COLOR_GREEN 0xA444 ++#define TD_HS_BORDER_COLOR_BLUE 0xA448 ++#define TD_HS_BORDER_COLOR_ALPHA 0xA44C ++#define TD_LS_BORDER_COLOR_INDEX 0xA450 ++#define TD_LS_BORDER_COLOR_RED 0xA454 ++#define TD_LS_BORDER_COLOR_GREEN 0xA458 ++#define TD_LS_BORDER_COLOR_BLUE 0xA45C ++#define TD_LS_BORDER_COLOR_ALPHA 0xA460 ++#define TD_CS_BORDER_COLOR_INDEX 0xA464 ++#define TD_CS_BORDER_COLOR_RED 0xA468 ++#define TD_CS_BORDER_COLOR_GREEN 0xA46C ++#define TD_CS_BORDER_COLOR_BLUE 0xA470 ++#define TD_CS_BORDER_COLOR_ALPHA 0xA474 ++ + /* cayman 3D regs */ +-#define CAYMAN_VGT_OFFCHIP_LDS_BASE 0x89B0 ++#define CAYMAN_VGT_OFFCHIP_LDS_BASE 0x89B4 ++#define CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS 0x8E48 + #define CAYMAN_DB_EQAA 0x28804 + #define CAYMAN_DB_DEPTH_INFO 0x2803C + #define CAYMAN_PA_SC_AA_CONFIG 0x28BE0 +diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c +index 77e6fb1..a03ef51 100644 +--- a/drivers/gpu/drm/radeon/ni.c ++++ b/drivers/gpu/drm/radeon/ni.c +@@ -42,6 +42,8 @@ extern void evergreen_irq_suspend(struct radeon_device *rdev); + extern int evergreen_mc_init(struct radeon_device *rdev); + extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev); + extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev); ++extern void si_rlc_fini(struct radeon_device *rdev); ++extern int si_rlc_init(struct radeon_device *rdev); + + #define EVERGREEN_PFP_UCODE_SIZE 1120 + #define EVERGREEN_PM4_UCODE_SIZE 1376 +@@ -53,6 +55,8 @@ extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev); + #define CAYMAN_RLC_UCODE_SIZE 1024 + #define CAYMAN_MC_UCODE_SIZE 6037 + ++#define ARUBA_RLC_UCODE_SIZE 1536 ++ + /* Firmware Names */ + MODULE_FIRMWARE("radeon/BARTS_pfp.bin"); + MODULE_FIRMWARE("radeon/BARTS_me.bin"); +@@ -68,6 +72,9 @@ MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin"); + MODULE_FIRMWARE("radeon/CAYMAN_me.bin"); + MODULE_FIRMWARE("radeon/CAYMAN_mc.bin"); + MODULE_FIRMWARE("radeon/CAYMAN_rlc.bin"); ++MODULE_FIRMWARE("radeon/ARUBA_pfp.bin"); ++MODULE_FIRMWARE("radeon/ARUBA_me.bin"); ++MODULE_FIRMWARE("radeon/ARUBA_rlc.bin"); + + #define BTC_IO_MC_REGS_SIZE 29 + +@@ -326,6 +333,15 @@ int ni_init_microcode(struct radeon_device *rdev) + rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4; + mc_req_size = CAYMAN_MC_UCODE_SIZE * 4; + break; ++ case CHIP_ARUBA: ++ chip_name = "ARUBA"; ++ rlc_chip_name = "ARUBA"; ++ /* pfp/me same size as CAYMAN */ ++ pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4; ++ me_req_size = CAYMAN_PM4_UCODE_SIZE * 4; ++ rlc_req_size = ARUBA_RLC_UCODE_SIZE * 4; ++ mc_req_size = 0; ++ break; + default: BUG(); + } + +@@ -365,24 +381,23 @@ int ni_init_microcode(struct radeon_device *rdev) + err = -EINVAL; + } + +- snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); +- err = request_firmware(&rdev->mc_fw, fw_name, &pdev->dev); +- if (err) +- goto out; +- if (rdev->mc_fw->size != mc_req_size) { +- printk(KERN_ERR +- "ni_mc: Bogus length %zu in firmware \"%s\"\n", +- rdev->mc_fw->size, fw_name); +- err = -EINVAL; ++ /* no MC ucode on TN */ ++ if (!(rdev->flags & RADEON_IS_IGP)) { ++ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); ++ err = request_firmware(&rdev->mc_fw, fw_name, &pdev->dev); ++ if (err) ++ goto out; ++ if (rdev->mc_fw->size != mc_req_size) { ++ printk(KERN_ERR ++ "ni_mc: Bogus length %zu in firmware \"%s\"\n", ++ rdev->mc_fw->size, fw_name); ++ err = -EINVAL; ++ } + } + out: + platform_device_unregister(pdev); + + if (err) { +- if (err != -EINVAL) +- printk(KERN_ERR +- "ni_cp: Failed to load firmware \"%s\"\n", +- fw_name); + release_firmware(rdev->pfp_fw); + rdev->pfp_fw = NULL; + release_firmware(rdev->me_fw); +@@ -478,6 +493,7 @@ static u32 cayman_get_tile_pipe_to_backend_map(struct radeon_device *rdev, + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * CAYMAN_MAX_PIPES); + switch (rdev->family) { + case CHIP_CAYMAN: ++ case CHIP_ARUBA: + force_no_swizzle = true; + break; + default: +@@ -610,7 +626,6 @@ static void cayman_gpu_init(struct radeon_device *rdev) + + switch (rdev->family) { + case CHIP_CAYMAN: +- default: + rdev->config.cayman.max_shader_engines = 2; + rdev->config.cayman.max_pipes_per_simd = 4; + rdev->config.cayman.max_tile_pipes = 8; +@@ -632,6 +647,79 @@ static void cayman_gpu_init(struct radeon_device *rdev) + rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; + rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; + break; ++ case CHIP_ARUBA: ++ default: ++ rdev->config.cayman.max_shader_engines = 1; ++ rdev->config.cayman.max_pipes_per_simd = 4; ++ rdev->config.cayman.max_tile_pipes = 2; ++ if ((rdev->pdev->device == 0x9900) || ++ (rdev->pdev->device == 0x9901) || ++ (rdev->pdev->device == 0x9905) || ++ (rdev->pdev->device == 0x9906) || ++ (rdev->pdev->device == 0x9907) || ++ (rdev->pdev->device == 0x9908) || ++ (rdev->pdev->device == 0x9909) || ++ (rdev->pdev->device == 0x990B) || ++ (rdev->pdev->device == 0x990C) || ++ (rdev->pdev->device == 0x990F) || ++ (rdev->pdev->device == 0x9910) || ++ (rdev->pdev->device == 0x9917) || ++ (rdev->pdev->device == 0x9999) || ++ (rdev->pdev->device == 0x999C)) { ++ rdev->config.cayman.max_simds_per_se = 6; ++ rdev->config.cayman.max_backends_per_se = 2; ++ rdev->config.cayman.max_hw_contexts = 8; ++ rdev->config.cayman.sx_max_export_size = 256; ++ rdev->config.cayman.sx_max_export_pos_size = 64; ++ rdev->config.cayman.sx_max_export_smx_size = 192; ++ } else if ((rdev->pdev->device == 0x9903) || ++ (rdev->pdev->device == 0x9904) || ++ (rdev->pdev->device == 0x990A) || ++ (rdev->pdev->device == 0x990D) || ++ (rdev->pdev->device == 0x990E) || ++ (rdev->pdev->device == 0x9913) || ++ (rdev->pdev->device == 0x9918) || ++ (rdev->pdev->device == 0x999D)) { ++ rdev->config.cayman.max_simds_per_se = 4; ++ rdev->config.cayman.max_backends_per_se = 2; ++ rdev->config.cayman.max_hw_contexts = 8; ++ rdev->config.cayman.sx_max_export_size = 256; ++ rdev->config.cayman.sx_max_export_pos_size = 64; ++ rdev->config.cayman.sx_max_export_smx_size = 192; ++ } else if ((rdev->pdev->device == 0x9919) || ++ (rdev->pdev->device == 0x9990) || ++ (rdev->pdev->device == 0x9991) || ++ (rdev->pdev->device == 0x9994) || ++ (rdev->pdev->device == 0x9995) || ++ (rdev->pdev->device == 0x9996) || ++ (rdev->pdev->device == 0x999A) || ++ (rdev->pdev->device == 0x99A0)) { ++ rdev->config.cayman.max_simds_per_se = 3; ++ rdev->config.cayman.max_backends_per_se = 1; ++ rdev->config.cayman.max_hw_contexts = 4; ++ rdev->config.cayman.sx_max_export_size = 128; ++ rdev->config.cayman.sx_max_export_pos_size = 32; ++ rdev->config.cayman.sx_max_export_smx_size = 96; ++ } else { ++ rdev->config.cayman.max_simds_per_se = 2; ++ rdev->config.cayman.max_backends_per_se = 1; ++ rdev->config.cayman.max_hw_contexts = 4; ++ rdev->config.cayman.sx_max_export_size = 128; ++ rdev->config.cayman.sx_max_export_pos_size = 32; ++ rdev->config.cayman.sx_max_export_smx_size = 96; ++ } ++ rdev->config.cayman.max_texture_channel_caches = 2; ++ rdev->config.cayman.max_gprs = 256; ++ rdev->config.cayman.max_threads = 256; ++ rdev->config.cayman.max_gs_threads = 32; ++ rdev->config.cayman.max_stack_entries = 512; ++ rdev->config.cayman.sx_num_of_sets = 8; ++ rdev->config.cayman.sq_num_cf_insts = 2; ++ ++ rdev->config.cayman.sc_prim_fifo_size = 0x40; ++ rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; ++ rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; ++ break; + } + + /* Initialize HDP */ +@@ -652,7 +740,9 @@ static void cayman_gpu_init(struct radeon_device *rdev) + + cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE); + cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); +- cgts_tcc_disable = 0xff000000; ++ cgts_tcc_disable = 0xffff0000; ++ for (i = 0; i < rdev->config.cayman.max_texture_channel_caches; i++) ++ cgts_tcc_disable &= ~(1 << (16 + i)); + gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE); + gc_user_shader_pipe_config = RREG32(GC_USER_SHADER_PIPE_CONFIG); + cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE); +@@ -804,17 +894,23 @@ static void cayman_gpu_init(struct radeon_device *rdev) + rdev->config.cayman.tile_config |= (3 << 0); + break; + } +- switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { +- case 0: /* four banks */ +- rdev->config.cayman.tile_config |= 0 << 4; +- break; +- case 1: /* eight banks */ ++ ++ /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ ++ if (rdev->flags & RADEON_IS_IGP) + rdev->config.cayman.tile_config |= 1 << 4; +- break; +- case 2: /* sixteen banks */ +- default: +- rdev->config.cayman.tile_config |= 2 << 4; +- break; ++ else { ++ switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { ++ case 0: /* four banks */ ++ rdev->config.cayman.tile_config |= 0 << 4; ++ break; ++ case 1: /* eight banks */ ++ rdev->config.cayman.tile_config |= 1 << 4; ++ break; ++ case 2: /* sixteen banks */ ++ default: ++ rdev->config.cayman.tile_config |= 2 << 4; ++ break; ++ } + } + rdev->config.cayman.tile_config |= + ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; +@@ -825,6 +921,8 @@ static void cayman_gpu_init(struct radeon_device *rdev) + WREG32(GB_BACKEND_MAP, gb_backend_map); + WREG32(GB_ADDR_CONFIG, gb_addr_config); + WREG32(DMIF_ADDR_CONFIG, gb_addr_config); ++ if (ASIC_IS_DCE6(rdev)) ++ WREG32(DMIF_ADDR_CALC, gb_addr_config); + WREG32(HDP_ADDR_CONFIG, gb_addr_config); + + /* primary versions */ +@@ -944,7 +1042,7 @@ void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev) + + int cayman_pcie_gart_enable(struct radeon_device *rdev) + { +- int r; ++ int i, r; + + if (rdev->gart.robj == NULL) { + dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); +@@ -955,9 +1053,12 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev) + return r; + radeon_gart_restore(rdev); + /* Setup TLB control */ +- WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB | ++ WREG32(MC_VM_MX_L1_TLB_CNTL, ++ (0xA << 7) | ++ ENABLE_L1_TLB | + ENABLE_L1_FRAGMENT_PROCESSING | + SYSTEM_ACCESS_MODE_NOT_IN_SYS | ++ ENABLE_ADVANCED_DRIVER_MODEL | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | +@@ -977,9 +1078,26 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev) + WREG32(VM_CONTEXT0_CNTL2, 0); + WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | + RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); +- /* disable context1-7 */ ++ ++ WREG32(0x15D4, 0); ++ WREG32(0x15D8, 0); ++ WREG32(0x15DC, 0); ++ ++ /* empty context1-7 */ ++ for (i = 1; i < 8; i++) { ++ WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0); ++ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), 0); ++ WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), ++ rdev->gart.table_addr >> 12); ++ } ++ ++ /* enable context1-7 */ ++ WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, ++ (u32)(rdev->dummy_page.addr >> 12)); + WREG32(VM_CONTEXT1_CNTL2, 0); + WREG32(VM_CONTEXT1_CNTL, 0); ++ WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | ++ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); + + cayman_pcie_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", +@@ -1016,9 +1134,69 @@ void cayman_pcie_gart_fini(struct radeon_device *rdev) + radeon_gart_fini(rdev); + } + ++void cayman_cp_int_cntl_setup(struct radeon_device *rdev, ++ int ring, u32 cp_int_cntl) ++{ ++ u32 srbm_gfx_cntl = RREG32(SRBM_GFX_CNTL) & ~3; ++ ++ WREG32(SRBM_GFX_CNTL, srbm_gfx_cntl | (ring & 3)); ++ WREG32(CP_INT_CNTL, cp_int_cntl); ++} ++ + /* + * CP. + */ ++void cayman_fence_ring_emit(struct radeon_device *rdev, ++ struct radeon_fence *fence) ++{ ++ struct radeon_ring *ring = &rdev->ring[fence->ring]; ++ u64 addr = rdev->fence_drv[fence->ring].gpu_addr; ++ ++ /* flush read cache over gart for this vmid */ ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); ++ radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); ++ radeon_ring_write(ring, 0xFFFFFFFF); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 10); /* poll interval */ ++ /* EVENT_WRITE_EOP - flush caches, send int */ ++ radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); ++ radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); ++ radeon_ring_write(ring, addr & 0xffffffff); ++ radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); ++ radeon_ring_write(ring, fence->seq); ++ radeon_ring_write(ring, 0); ++} ++ ++void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) ++{ ++ struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; ++ ++ /* set to DX10/11 mode */ ++ radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); ++ radeon_ring_write(ring, 1); ++ radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); ++ radeon_ring_write(ring, ++#ifdef __BIG_ENDIAN ++ (2 << 0) | ++#endif ++ (ib->gpu_addr & 0xFFFFFFFC)); ++ radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF); ++ radeon_ring_write(ring, ib->length_dw | (ib->vm_id << 24)); ++ ++ /* flush read cache over gart for this vmid */ ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); ++ radeon_ring_write(ring, ib->vm_id); ++ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); ++ radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); ++ radeon_ring_write(ring, 0xFFFFFFFF); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 10); /* poll interval */ ++} ++ + static void cayman_cp_enable(struct radeon_device *rdev, bool enable) + { + if (enable) +@@ -1059,63 +1237,64 @@ static int cayman_cp_load_microcode(struct radeon_device *rdev) + + static int cayman_cp_start(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r, i; + +- r = radeon_ring_lock(rdev, 7); ++ r = radeon_ring_lock(rdev, ring, 7); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } +- radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); +- radeon_ring_write(rdev, 0x1); +- radeon_ring_write(rdev, 0x0); +- radeon_ring_write(rdev, rdev->config.cayman.max_hw_contexts - 1); +- radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); ++ radeon_ring_write(ring, 0x1); ++ radeon_ring_write(ring, 0x0); ++ radeon_ring_write(ring, rdev->config.cayman.max_hw_contexts - 1); ++ radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_unlock_commit(rdev, ring); + + cayman_cp_enable(rdev, true); + +- r = radeon_ring_lock(rdev, cayman_default_size + 19); ++ r = radeon_ring_lock(rdev, ring, cayman_default_size + 19); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + + /* setup clear context state */ +- radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); +- radeon_ring_write(rdev, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); ++ radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); ++ radeon_ring_write(ring, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); + + for (i = 0; i < cayman_default_size; i++) +- radeon_ring_write(rdev, cayman_default_state[i]); ++ radeon_ring_write(ring, cayman_default_state[i]); + +- radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); +- radeon_ring_write(rdev, PACKET3_PREAMBLE_END_CLEAR_STATE); ++ radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); ++ radeon_ring_write(ring, PACKET3_PREAMBLE_END_CLEAR_STATE); + + /* set clear context state */ +- radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0)); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0)); ++ radeon_ring_write(ring, 0); + + /* SQ_VTX_BASE_VTX_LOC */ +- radeon_ring_write(rdev, 0xc0026f00); +- radeon_ring_write(rdev, 0x00000000); +- radeon_ring_write(rdev, 0x00000000); +- radeon_ring_write(rdev, 0x00000000); ++ radeon_ring_write(ring, 0xc0026f00); ++ radeon_ring_write(ring, 0x00000000); ++ radeon_ring_write(ring, 0x00000000); ++ radeon_ring_write(ring, 0x00000000); + + /* Clear consts */ +- radeon_ring_write(rdev, 0xc0036f00); +- radeon_ring_write(rdev, 0x00000bc4); +- radeon_ring_write(rdev, 0xffffffff); +- radeon_ring_write(rdev, 0xffffffff); +- radeon_ring_write(rdev, 0xffffffff); ++ radeon_ring_write(ring, 0xc0036f00); ++ radeon_ring_write(ring, 0x00000bc4); ++ radeon_ring_write(ring, 0xffffffff); ++ radeon_ring_write(ring, 0xffffffff); ++ radeon_ring_write(ring, 0xffffffff); + +- radeon_ring_write(rdev, 0xc0026900); +- radeon_ring_write(rdev, 0x00000316); +- radeon_ring_write(rdev, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ +- radeon_ring_write(rdev, 0x00000010); /* */ ++ radeon_ring_write(ring, 0xc0026900); ++ radeon_ring_write(ring, 0x00000316); ++ radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ ++ radeon_ring_write(ring, 0x00000010); /* */ + +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_unlock_commit(rdev, ring); + + /* XXX init other rings */ + +@@ -1125,11 +1304,12 @@ static int cayman_cp_start(struct radeon_device *rdev) + static void cayman_cp_fini(struct radeon_device *rdev) + { + cayman_cp_enable(rdev, false); +- radeon_ring_fini(rdev); ++ radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + } + + int cayman_cp_resume(struct radeon_device *rdev) + { ++ struct radeon_ring *ring; + u32 tmp; + u32 rb_bufsz; + int r; +@@ -1146,7 +1326,8 @@ int cayman_cp_resume(struct radeon_device *rdev) + WREG32(GRBM_SOFT_RESET, 0); + RREG32(GRBM_SOFT_RESET); + +- WREG32(CP_SEM_WAIT_TIMER, 0x4); ++ WREG32(CP_SEM_WAIT_TIMER, 0x0); ++ WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); + + /* Set the write pointer delay */ + WREG32(CP_RB_WPTR_DELAY, 0); +@@ -1155,7 +1336,8 @@ int cayman_cp_resume(struct radeon_device *rdev) + + /* ring 0 - compute and gfx */ + /* Set ring buffer size */ +- rb_bufsz = drm_order(rdev->cp.ring_size / 8); ++ ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; + #ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +@@ -1164,8 +1346,8 @@ int cayman_cp_resume(struct radeon_device *rdev) + + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA); +- rdev->cp.wptr = 0; +- WREG32(CP_RB0_WPTR, rdev->cp.wptr); ++ ring->wptr = 0; ++ WREG32(CP_RB0_WPTR, ring->wptr); + + /* set the wb address wether it's enabled or not */ + WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC); +@@ -1182,13 +1364,14 @@ int cayman_cp_resume(struct radeon_device *rdev) + mdelay(1); + WREG32(CP_RB0_CNTL, tmp); + +- WREG32(CP_RB0_BASE, rdev->cp.gpu_addr >> 8); ++ WREG32(CP_RB0_BASE, ring->gpu_addr >> 8); + +- rdev->cp.rptr = RREG32(CP_RB0_RPTR); ++ ring->rptr = RREG32(CP_RB0_RPTR); + + /* ring1 - compute only */ + /* Set ring buffer size */ +- rb_bufsz = drm_order(rdev->cp1.ring_size / 8); ++ ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; ++ rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; + #ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +@@ -1197,8 +1380,8 @@ int cayman_cp_resume(struct radeon_device *rdev) + + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA); +- rdev->cp1.wptr = 0; +- WREG32(CP_RB1_WPTR, rdev->cp1.wptr); ++ ring->wptr = 0; ++ WREG32(CP_RB1_WPTR, ring->wptr); + + /* set the wb address wether it's enabled or not */ + WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC); +@@ -1207,13 +1390,14 @@ int cayman_cp_resume(struct radeon_device *rdev) + mdelay(1); + WREG32(CP_RB1_CNTL, tmp); + +- WREG32(CP_RB1_BASE, rdev->cp1.gpu_addr >> 8); ++ WREG32(CP_RB1_BASE, ring->gpu_addr >> 8); + +- rdev->cp1.rptr = RREG32(CP_RB1_RPTR); ++ ring->rptr = RREG32(CP_RB1_RPTR); + + /* ring2 - compute only */ + /* Set ring buffer size */ +- rb_bufsz = drm_order(rdev->cp2.ring_size / 8); ++ ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; ++ rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; + #ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +@@ -1222,8 +1406,8 @@ int cayman_cp_resume(struct radeon_device *rdev) + + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA); +- rdev->cp2.wptr = 0; +- WREG32(CP_RB2_WPTR, rdev->cp2.wptr); ++ ring->wptr = 0; ++ WREG32(CP_RB2_WPTR, ring->wptr); + + /* set the wb address wether it's enabled or not */ + WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC); +@@ -1232,28 +1416,28 @@ int cayman_cp_resume(struct radeon_device *rdev) + mdelay(1); + WREG32(CP_RB2_CNTL, tmp); + +- WREG32(CP_RB2_BASE, rdev->cp2.gpu_addr >> 8); ++ WREG32(CP_RB2_BASE, ring->gpu_addr >> 8); + +- rdev->cp2.rptr = RREG32(CP_RB2_RPTR); ++ ring->rptr = RREG32(CP_RB2_RPTR); + + /* start the rings */ + cayman_cp_start(rdev); +- rdev->cp.ready = true; +- rdev->cp1.ready = true; +- rdev->cp2.ready = true; ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true; ++ rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; ++ rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; + /* this only test cp0 */ +- r = radeon_ring_test(rdev); ++ r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + if (r) { +- rdev->cp.ready = false; +- rdev->cp1.ready = false; +- rdev->cp2.ready = false; ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; ++ rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; ++ rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; + return r; + } + + return 0; + } + +-bool cayman_gpu_is_lockup(struct radeon_device *rdev) ++bool cayman_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) + { + u32 srbm_status; + u32 grbm_status; +@@ -1266,20 +1450,20 @@ bool cayman_gpu_is_lockup(struct radeon_device *rdev) + grbm_status_se0 = RREG32(GRBM_STATUS_SE0); + grbm_status_se1 = RREG32(GRBM_STATUS_SE1); + if (!(grbm_status & GUI_ACTIVE)) { +- r100_gpu_lockup_update(lockup, &rdev->cp); ++ r100_gpu_lockup_update(lockup, ring); + return false; + } + /* force CP activities */ +- r = radeon_ring_lock(rdev, 2); ++ r = radeon_ring_lock(rdev, ring, 2); + if (!r) { + /* PACKET2 NOP */ +- radeon_ring_write(rdev, 0x80000000); +- radeon_ring_write(rdev, 0x80000000); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_unlock_commit(rdev, ring); + } + /* XXX deal with CP0,1,2 */ +- rdev->cp.rptr = RREG32(CP_RB0_RPTR); +- return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp); ++ ring->rptr = RREG32(ring->rptr_reg); ++ return r100_gpu_cp_is_lockup(rdev, lockup, ring); + } + + static int cayman_gpu_soft_reset(struct radeon_device *rdev) +@@ -1299,6 +1483,15 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev) + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", + RREG32(SRBM_STATUS)); ++ dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_ADDR 0x%08X\n", ++ RREG32(0x14F8)); ++ dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n", ++ RREG32(0x14D8)); ++ dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", ++ RREG32(0x14FC)); ++ dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", ++ RREG32(0x14DC)); ++ + evergreen_mc_stop(rdev, &save); + if (evergreen_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); +@@ -1329,6 +1522,7 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev) + (void)RREG32(GRBM_SOFT_RESET); + /* Wait a little for things to settle down */ + udelay(50); ++ + dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", +@@ -1348,6 +1542,7 @@ int cayman_asic_reset(struct radeon_device *rdev) + + static int cayman_startup(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + + /* enable pcie gen2 link */ +@@ -1355,18 +1550,29 @@ static int cayman_startup(struct radeon_device *rdev) + + evergreen_mc_program(rdev); + +- if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { +- r = ni_init_microcode(rdev); ++ if (rdev->flags & RADEON_IS_IGP) { ++ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { ++ r = ni_init_microcode(rdev); ++ if (r) { ++ DRM_ERROR("Failed to load firmware!\n"); ++ return r; ++ } ++ } ++ } else { ++ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { ++ r = ni_init_microcode(rdev); ++ if (r) { ++ DRM_ERROR("Failed to load firmware!\n"); ++ return r; ++ } ++ } ++ ++ r = ni_mc_load_microcode(rdev); + if (r) { +- DRM_ERROR("Failed to load firmware!\n"); ++ DRM_ERROR("Failed to load MC firmware!\n"); + return r; + } + } +- r = ni_mc_load_microcode(rdev); +- if (r) { +- DRM_ERROR("Failed to load MC firmware!\n"); +- return r; +- } + + r = r600_vram_scratch_init(rdev); + if (r) +@@ -1380,15 +1586,42 @@ static int cayman_startup(struct radeon_device *rdev) + r = evergreen_blit_init(rdev); + if (r) { + r600_blit_fini(rdev); +- rdev->asic->copy = NULL; ++ rdev->asic->copy.copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } + ++ /* allocate rlc buffers */ ++ if (rdev->flags & RADEON_IS_IGP) { ++ r = si_rlc_init(rdev); ++ if (r) { ++ DRM_ERROR("Failed to init rlc BOs!\n"); ++ return r; ++ } ++ } ++ + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ ++ r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ ++ r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP2_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ + /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); +@@ -1404,7 +1637,9 @@ static int cayman_startup(struct radeon_device *rdev) + } + evergreen_irq_set(rdev); + +- r = radeon_ring_init(rdev, rdev->cp.ring_size); ++ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, ++ CP_RB0_RPTR, CP_RB0_WPTR, ++ 0, 0xfffff, RADEON_CP_PACKET2); + if (r) + return r; + r = cayman_cp_load_microcode(rdev); +@@ -1414,6 +1649,21 @@ static int cayman_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); ++ if (r) { ++ DRM_ERROR("radeon: failed testing IB (%d).\n", r); ++ rdev->accel_working = false; ++ return r; ++ } ++ ++ r = radeon_vm_manager_start(rdev); ++ if (r) ++ return r; ++ + return 0; + } + +@@ -1428,32 +1678,27 @@ int cayman_resume(struct radeon_device *rdev) + /* post card */ + atom_asic_init(rdev->mode_info.atom_context); + ++ rdev->accel_working = true; + r = cayman_startup(rdev); + if (r) { + DRM_ERROR("cayman startup failed on resume\n"); ++ rdev->accel_working = false; + return r; + } +- +- r = r600_ib_test(rdev); +- if (r) { +- DRM_ERROR("radeon: failled testing IB (%d).\n", r); +- return r; +- } +- + return r; +- + } + + int cayman_suspend(struct radeon_device *rdev) + { + /* FIXME: we should wait for ring to be empty */ ++ radeon_ib_pool_suspend(rdev); ++ radeon_vm_manager_suspend(rdev); ++ r600_blit_suspend(rdev); + cayman_cp_enable(rdev, false); +- rdev->cp.ready = false; ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; + evergreen_irq_suspend(rdev); + radeon_wb_disable(rdev); + cayman_pcie_gart_disable(rdev); +- r600_blit_suspend(rdev); +- + return 0; + } + +@@ -1465,6 +1710,7 @@ int cayman_suspend(struct radeon_device *rdev) + */ + int cayman_init(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + + /* This don't do much */ +@@ -1513,8 +1759,8 @@ int cayman_init(struct radeon_device *rdev) + if (r) + return r; + +- rdev->cp.ring_obj = NULL; +- r600_ring_init(rdev, 1024 * 1024); ++ ring->ring_obj = NULL; ++ r600_ring_init(rdev, ring, 1024 * 1024); + + rdev->ih.ring_obj = NULL; + r600_ih_ring_init(rdev, 64 * 1024); +@@ -1523,35 +1769,40 @@ int cayman_init(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_ib_pool_init(rdev); + rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ r = radeon_vm_manager_init(rdev); ++ if (r) { ++ dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); ++ } ++ + r = cayman_startup(rdev); + if (r) { + dev_err(rdev->dev, "disabling GPU acceleration\n"); + cayman_cp_fini(rdev); + r600_irq_fini(rdev); ++ if (rdev->flags & RADEON_IS_IGP) ++ si_rlc_fini(rdev); + radeon_wb_fini(rdev); ++ r100_ib_fini(rdev); ++ radeon_vm_manager_fini(rdev); + radeon_irq_kms_fini(rdev); + cayman_pcie_gart_fini(rdev); + rdev->accel_working = false; + } +- if (rdev->accel_working) { +- r = radeon_ib_pool_init(rdev); +- if (r) { +- DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); +- rdev->accel_working = false; +- } +- r = r600_ib_test(rdev); +- if (r) { +- DRM_ERROR("radeon: failed testing IB (%d).\n", r); +- rdev->accel_working = false; +- } +- } + + /* Don't start up if the MC ucode is missing. + * The default clocks and voltages before the MC ucode + * is loaded are not suffient for advanced operations. ++ * ++ * We can skip this check for TN, because there is no MC ++ * ucode. + */ +- if (!rdev->mc_fw) { ++ if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) { + DRM_ERROR("radeon: MC ucode required for NI+.\n"); + return -EINVAL; + } +@@ -1564,12 +1815,16 @@ void cayman_fini(struct radeon_device *rdev) + r600_blit_fini(rdev); + cayman_cp_fini(rdev); + r600_irq_fini(rdev); ++ if (rdev->flags & RADEON_IS_IGP) ++ si_rlc_fini(rdev); + radeon_wb_fini(rdev); +- radeon_ib_pool_fini(rdev); ++ radeon_vm_manager_fini(rdev); ++ r100_ib_fini(rdev); + radeon_irq_kms_fini(rdev); + cayman_pcie_gart_fini(rdev); + r600_vram_scratch_fini(rdev); + radeon_gem_fini(rdev); ++ radeon_semaphore_driver_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); +@@ -1577,3 +1832,89 @@ void cayman_fini(struct radeon_device *rdev) + rdev->bios = NULL; + } + ++/* ++ * vm ++ */ ++int cayman_vm_init(struct radeon_device *rdev) ++{ ++ /* number of VMs */ ++ rdev->vm_manager.nvm = 8; ++ /* base offset of vram pages */ ++ if (rdev->flags & RADEON_IS_IGP) { ++ u64 tmp = RREG32(FUS_MC_VM_FB_OFFSET); ++ tmp <<= 22; ++ rdev->vm_manager.vram_base_offset = tmp; ++ } else ++ rdev->vm_manager.vram_base_offset = 0; ++ return 0; ++} ++ ++void cayman_vm_fini(struct radeon_device *rdev) ++{ ++} ++ ++int cayman_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm, int id) ++{ ++ WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (id << 2), 0); ++ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (id << 2), vm->last_pfn); ++ WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (id << 2), vm->pt_gpu_addr >> 12); ++ /* flush hdp cache */ ++ WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); ++ /* bits 0-7 are the VM contexts0-7 */ ++ WREG32(VM_INVALIDATE_REQUEST, 1 << id); ++ return 0; ++} ++ ++void cayman_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm) ++{ ++ WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (vm->id << 2), 0); ++ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (vm->id << 2), 0); ++ WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2), 0); ++ /* flush hdp cache */ ++ WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); ++ /* bits 0-7 are the VM contexts0-7 */ ++ WREG32(VM_INVALIDATE_REQUEST, 1 << vm->id); ++} ++ ++void cayman_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm) ++{ ++ if (vm->id == -1) ++ return; ++ ++ /* flush hdp cache */ ++ WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); ++ /* bits 0-7 are the VM contexts0-7 */ ++ WREG32(VM_INVALIDATE_REQUEST, 1 << vm->id); ++} ++ ++#define R600_PTE_VALID (1 << 0) ++#define R600_PTE_SYSTEM (1 << 1) ++#define R600_PTE_SNOOPED (1 << 2) ++#define R600_PTE_READABLE (1 << 5) ++#define R600_PTE_WRITEABLE (1 << 6) ++ ++uint32_t cayman_vm_page_flags(struct radeon_device *rdev, ++ struct radeon_vm *vm, ++ uint32_t flags) ++{ ++ uint32_t r600_flags = 0; ++ ++ r600_flags |= (flags & RADEON_VM_PAGE_VALID) ? R600_PTE_VALID : 0; ++ r600_flags |= (flags & RADEON_VM_PAGE_READABLE) ? R600_PTE_READABLE : 0; ++ r600_flags |= (flags & RADEON_VM_PAGE_WRITEABLE) ? R600_PTE_WRITEABLE : 0; ++ if (flags & RADEON_VM_PAGE_SYSTEM) { ++ r600_flags |= R600_PTE_SYSTEM; ++ r600_flags |= (flags & RADEON_VM_PAGE_SNOOPED) ? R600_PTE_SNOOPED : 0; ++ } ++ return r600_flags; ++} ++ ++void cayman_vm_set_page(struct radeon_device *rdev, struct radeon_vm *vm, ++ unsigned pfn, uint64_t addr, uint32_t flags) ++{ ++ void __iomem *ptr = (void *)vm->pt; ++ ++ addr = addr & 0xFFFFFFFFFFFFF000ULL; ++ addr |= flags; ++ writeq(addr, ptr + (pfn * 8)); ++} +diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h +index 4672869..d90b8b7 100644 +--- a/drivers/gpu/drm/radeon/nid.h ++++ b/drivers/gpu/drm/radeon/nid.h +@@ -42,6 +42,13 @@ + #define CAYMAN_MAX_TCC_MASK 0xFF + + #define DMIF_ADDR_CONFIG 0xBD4 ++ ++/* DCE6 only */ ++#define DMIF_ADDR_CALC 0xC00 ++ ++#define SRBM_GFX_CNTL 0x0E44 ++#define RINGID(x) (((x) & 0x3) << 0) ++#define VMID(x) (((x) & 0x7) << 0) + #define SRBM_STATUS 0x0E50 + + #define VM_CONTEXT0_REQUEST_RESPONSE 0x1470 +@@ -103,6 +110,7 @@ + #define SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 3) + #define SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 5) + #define ENABLE_ADVANCED_DRIVER_MODEL (1 << 6) ++#define FUS_MC_VM_FB_OFFSET 0x2068 + + #define MC_SHARED_BLACKOUT_CNTL 0x20ac + #define MC_ARB_RAMCFG 0x2760 +@@ -219,6 +227,8 @@ + #define SCRATCH_UMSK 0x8540 + #define SCRATCH_ADDR 0x8544 + #define CP_SEM_WAIT_TIMER 0x85BC ++#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 ++#define CP_COHER_CNTL2 0x85E8 + #define CP_ME_CNTL 0x86D8 + #define CP_ME_HALT (1 << 28) + #define CP_PFP_HALT (1 << 26) +@@ -394,6 +404,12 @@ + #define CP_RB0_RPTR_ADDR 0xC10C + #define CP_RB0_RPTR_ADDR_HI 0xC110 + #define CP_RB0_WPTR 0xC114 ++ ++#define CP_INT_CNTL 0xC124 ++# define CNTX_BUSY_INT_ENABLE (1 << 19) ++# define CNTX_EMPTY_INT_ENABLE (1 << 20) ++# define TIME_STAMP_INT_ENABLE (1 << 26) ++ + #define CP_RB1_BASE 0xC180 + #define CP_RB1_CNTL 0xC184 + #define CP_RB1_RPTR_ADDR 0xC188 +@@ -411,6 +427,10 @@ + #define CP_ME_RAM_DATA 0xC160 + #define CP_DEBUG 0xC1FC + ++#define VGT_EVENT_INITIATOR 0x28a90 ++# define CACHE_FLUSH_AND_INV_EVENT_TS (0x14 << 0) ++# define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0) ++ + /* + * PM4 + */ +@@ -445,6 +465,7 @@ + #define PACKET3_DISPATCH_DIRECT 0x15 + #define PACKET3_DISPATCH_INDIRECT 0x16 + #define PACKET3_INDIRECT_BUFFER_END 0x17 ++#define PACKET3_MODE_CONTROL 0x18 + #define PACKET3_SET_PREDICATION 0x20 + #define PACKET3_REG_RMW 0x21 + #define PACKET3_COND_EXEC 0x22 +@@ -494,7 +515,27 @@ + #define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) + #define PACKET3_COND_WRITE 0x45 + #define PACKET3_EVENT_WRITE 0x46 ++#define EVENT_TYPE(x) ((x) << 0) ++#define EVENT_INDEX(x) ((x) << 8) ++ /* 0 - any non-TS event ++ * 1 - ZPASS_DONE ++ * 2 - SAMPLE_PIPELINESTAT ++ * 3 - SAMPLE_STREAMOUTSTAT* ++ * 4 - *S_PARTIAL_FLUSH ++ * 5 - TS events ++ */ + #define PACKET3_EVENT_WRITE_EOP 0x47 ++#define DATA_SEL(x) ((x) << 29) ++ /* 0 - discard ++ * 1 - send low 32bit data ++ * 2 - send 64bit data ++ * 3 - send 64bit counter value ++ */ ++#define INT_SEL(x) ((x) << 24) ++ /* 0 - none ++ * 1 - interrupt only (DATA_SEL = 0) ++ * 2 - interrupt when data write is confirmed ++ */ + #define PACKET3_EVENT_WRITE_EOS 0x48 + #define PACKET3_PREAMBLE_CNTL 0x4A + # define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE (2 << 28) +diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c +index dfd1267..9f2efa8 100644 +--- a/drivers/gpu/drm/radeon/r100.c ++++ b/drivers/gpu/drm/radeon/r100.c +@@ -65,6 +65,40 @@ MODULE_FIRMWARE(FIRMWARE_R520); + + #include "r100_track.h" + ++void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) ++{ ++ struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; ++ int i; ++ ++ if (radeon_crtc->crtc_id == 0) { ++ if (RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN) { ++ for (i = 0; i < rdev->usec_timeout; i++) { ++ if (!(RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR)) ++ break; ++ udelay(1); ++ } ++ for (i = 0; i < rdev->usec_timeout; i++) { ++ if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR) ++ break; ++ udelay(1); ++ } ++ } ++ } else { ++ if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN) { ++ for (i = 0; i < rdev->usec_timeout; i++) { ++ if (!(RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR)) ++ break; ++ udelay(1); ++ } ++ for (i = 0; i < rdev->usec_timeout; i++) { ++ if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR) ++ break; ++ udelay(1); ++ } ++ } ++ } ++} ++ + /* This files gather functions specifics to: + * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 + */ +@@ -87,23 +121,27 @@ int r100_reloc_pitch_offset(struct radeon_cs_parser *p, + r100_cs_dump_packet(p, pkt); + return r; + } ++ + value = radeon_get_ib_value(p, idx); + tmp = value & 0x003fffff; + tmp += (((u32)reloc->lobj.gpu_offset) >> 10); + +- if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) +- tile_flags |= RADEON_DST_TILE_MACRO; +- if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { +- if (reg == RADEON_SRC_PITCH_OFFSET) { +- DRM_ERROR("Cannot src blit from microtiled surface\n"); +- r100_cs_dump_packet(p, pkt); +- return -EINVAL; ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { ++ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) ++ tile_flags |= RADEON_DST_TILE_MACRO; ++ if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { ++ if (reg == RADEON_SRC_PITCH_OFFSET) { ++ DRM_ERROR("Cannot src blit from microtiled surface\n"); ++ r100_cs_dump_packet(p, pkt); ++ return -EINVAL; ++ } ++ tile_flags |= RADEON_DST_TILE_MICRO; + } +- tile_flags |= RADEON_DST_TILE_MICRO; +- } + +- tmp |= tile_flags; +- p->ib->ptr[idx] = (value & 0x3fc00000) | tmp; ++ tmp |= tile_flags; ++ p->ib->ptr[idx] = (value & 0x3fc00000) | tmp; ++ } else ++ p->ib->ptr[idx] = (value & 0xffc00000) | tmp; + return 0; + } + +@@ -412,7 +450,7 @@ void r100_pm_misc(struct radeon_device *rdev) + /* set pcie lanes */ + if ((rdev->flags & RADEON_IS_PCIE) && + !(rdev->flags & RADEON_IS_IGP) && +- rdev->asic->set_pcie_lanes && ++ rdev->asic->pm.set_pcie_lanes && + (ps->pcie_lanes != + rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) { + radeon_set_pcie_lanes(rdev, +@@ -592,8 +630,8 @@ int r100_pci_gart_init(struct radeon_device *rdev) + if (r) + return r; + rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; +- rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush; +- rdev->asic->gart_set_page = &r100_pci_gart_set_page; ++ rdev->asic->gart.tlb_flush = &r100_pci_gart_tlb_flush; ++ rdev->asic->gart.set_page = &r100_pci_gart_set_page; + return radeon_gart_table_ram_alloc(rdev); + } + +@@ -667,7 +705,7 @@ int r100_irq_set(struct radeon_device *rdev) + WREG32(R_000040_GEN_INT_CNTL, 0); + return -EINVAL; + } +- if (rdev->irq.sw_int) { ++ if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { + tmp |= RADEON_SW_INT_ENABLE; + } + if (rdev->irq.gui_idle) { +@@ -743,7 +781,7 @@ int r100_irq_process(struct radeon_device *rdev) + while (status) { + /* SW interrupt */ + if (status & RADEON_SW_INT_TEST) { +- radeon_fence_process(rdev); ++ radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + } + /* gui idle interrupt */ + if (status & RADEON_GUI_IDLE_STAT) { +@@ -813,25 +851,36 @@ u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc) + void r100_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence) + { ++ struct radeon_ring *ring = &rdev->ring[fence->ring]; ++ + /* We have to make sure that caches are flushed before + * CPU might read something from VRAM. */ +- radeon_ring_write(rdev, PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, RADEON_RB3D_DC_FLUSH_ALL); +- radeon_ring_write(rdev, PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, RADEON_RB3D_ZC_FLUSH_ALL); ++ radeon_ring_write(ring, PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, RADEON_RB3D_DC_FLUSH_ALL); ++ radeon_ring_write(ring, PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, RADEON_RB3D_ZC_FLUSH_ALL); + /* Wait until IDLE & CLEAN */ +- radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); +- radeon_ring_write(rdev, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); +- radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0)); +- radeon_ring_write(rdev, rdev->config.r100.hdp_cntl | ++ radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); ++ radeon_ring_write(ring, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); ++ radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); ++ radeon_ring_write(ring, rdev->config.r100.hdp_cntl | + RADEON_HDP_READ_BUFFER_INVALIDATE); +- radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0)); +- radeon_ring_write(rdev, rdev->config.r100.hdp_cntl); ++ radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); ++ radeon_ring_write(ring, rdev->config.r100.hdp_cntl); + /* Emit fence sequence & fire IRQ */ +- radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0)); +- radeon_ring_write(rdev, fence->seq); +- radeon_ring_write(rdev, PACKET0(RADEON_GEN_INT_STATUS, 0)); +- radeon_ring_write(rdev, RADEON_SW_INT_FIRE); ++ radeon_ring_write(ring, PACKET0(rdev->fence_drv[fence->ring].scratch_reg, 0)); ++ radeon_ring_write(ring, fence->seq); ++ radeon_ring_write(ring, PACKET0(RADEON_GEN_INT_STATUS, 0)); ++ radeon_ring_write(ring, RADEON_SW_INT_FIRE); ++} ++ ++void r100_semaphore_ring_emit(struct radeon_device *rdev, ++ struct radeon_ring *ring, ++ struct radeon_semaphore *semaphore, ++ bool emit_wait) ++{ ++ /* Unused on older asics, since we don't have semaphores or multiple rings */ ++ BUG(); + } + + int r100_copy_blit(struct radeon_device *rdev, +@@ -840,6 +889,7 @@ int r100_copy_blit(struct radeon_device *rdev, + unsigned num_gpu_pages, + struct radeon_fence *fence) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + uint32_t cur_pages; + uint32_t stride_bytes = RADEON_GPU_PAGE_SIZE; + uint32_t pitch; +@@ -857,7 +907,7 @@ int r100_copy_blit(struct radeon_device *rdev, + + /* Ask for enough room for blit + flush + fence */ + ndw = 64 + (10 * num_loops); +- r = radeon_ring_lock(rdev, ndw); ++ r = radeon_ring_lock(rdev, ring, ndw); + if (r) { + DRM_ERROR("radeon: moving bo (%d) asking for %u dw.\n", r, ndw); + return -EINVAL; +@@ -871,8 +921,8 @@ int r100_copy_blit(struct radeon_device *rdev, + + /* pages are in Y direction - height + page width in X direction - width */ +- radeon_ring_write(rdev, PACKET3(PACKET3_BITBLT_MULTI, 8)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET3(PACKET3_BITBLT_MULTI, 8)); ++ radeon_ring_write(ring, + RADEON_GMC_SRC_PITCH_OFFSET_CNTL | + RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_SRC_CLIPPING | +@@ -884,26 +934,26 @@ int r100_copy_blit(struct radeon_device *rdev, + RADEON_DP_SRC_SOURCE_MEMORY | + RADEON_GMC_CLR_CMP_CNTL_DIS | + RADEON_GMC_WR_MSK_DIS); +- radeon_ring_write(rdev, (pitch << 22) | (src_offset >> 10)); +- radeon_ring_write(rdev, (pitch << 22) | (dst_offset >> 10)); +- radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16)); +- radeon_ring_write(rdev, num_gpu_pages); +- radeon_ring_write(rdev, num_gpu_pages); +- radeon_ring_write(rdev, cur_pages | (stride_pixels << 16)); +- } +- radeon_ring_write(rdev, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, RADEON_RB2D_DC_FLUSH_ALL); +- radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, (pitch << 22) | (src_offset >> 10)); ++ radeon_ring_write(ring, (pitch << 22) | (dst_offset >> 10)); ++ radeon_ring_write(ring, (0x1fff) | (0x1fff << 16)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, (0x1fff) | (0x1fff << 16)); ++ radeon_ring_write(ring, num_gpu_pages); ++ radeon_ring_write(ring, num_gpu_pages); ++ radeon_ring_write(ring, cur_pages | (stride_pixels << 16)); ++ } ++ radeon_ring_write(ring, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, RADEON_RB2D_DC_FLUSH_ALL); ++ radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); ++ radeon_ring_write(ring, + RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_HOST_IDLECLEAN | + RADEON_WAIT_DMA_GUI_IDLE); + if (fence) { + r = radeon_fence_emit(rdev, fence); + } +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_unlock_commit(rdev, ring); + return r; + } + +@@ -922,21 +972,21 @@ static int r100_cp_wait_for_idle(struct radeon_device *rdev) + return -1; + } + +-void r100_ring_start(struct radeon_device *rdev) ++void r100_ring_start(struct radeon_device *rdev, struct radeon_ring *ring) + { + int r; + +- r = radeon_ring_lock(rdev, 2); ++ r = radeon_ring_lock(rdev, ring, 2); + if (r) { + return; + } +- radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET0(RADEON_ISYNC_CNTL, 0)); ++ radeon_ring_write(ring, + RADEON_ISYNC_ANY2D_IDLE3D | + RADEON_ISYNC_ANY3D_IDLE2D | + RADEON_ISYNC_WAIT_IDLEGUI | + RADEON_ISYNC_CPSCRATCH_IDLEGUI); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_unlock_commit(rdev, ring); + } + + +@@ -998,10 +1048,7 @@ static int r100_cp_init_microcode(struct radeon_device *rdev) + + err = request_firmware(&rdev->me_fw, fw_name, &pdev->dev); + platform_device_unregister(pdev); +- if (err) { +- printk(KERN_ERR "radeon_cp: Failed to load firmware \"%s\"\n", +- fw_name); +- } else if (rdev->me_fw->size % 8) { ++ if (err == 0 && rdev->me_fw->size % 8) { + printk(KERN_ERR + "radeon_cp: Bogus length %zu in firmware \"%s\"\n", + rdev->me_fw->size, fw_name); +@@ -1037,6 +1084,7 @@ static void r100_cp_load_microcode(struct radeon_device *rdev) + + int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + unsigned rb_bufsz; + unsigned rb_blksz; + unsigned max_fetch; +@@ -1062,7 +1110,9 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) + rb_bufsz = drm_order(ring_size / 8); + ring_size = (1 << (rb_bufsz + 1)) * 4; + r100_cp_load_microcode(rdev); +- r = radeon_ring_init(rdev, ring_size); ++ r = radeon_ring_init(rdev, ring, ring_size, RADEON_WB_CP_RPTR_OFFSET, ++ RADEON_CP_RB_RPTR, RADEON_CP_RB_WPTR, ++ 0, 0x7fffff, RADEON_CP_PACKET2); + if (r) { + return r; + } +@@ -1071,7 +1121,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) + rb_blksz = 9; + /* cp will read 128bytes at a time (4 dwords) */ + max_fetch = 1; +- rdev->cp.align_mask = 16 - 1; ++ ring->align_mask = 16 - 1; + /* Write to CP_RB_WPTR will be delayed for pre_write_timer clocks */ + pre_write_timer = 64; + /* Force CP_RB_WPTR write if written more than one time before the +@@ -1101,13 +1151,13 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) + WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_NO_UPDATE); + + /* Set ring address */ +- DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr); +- WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr); ++ DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)ring->gpu_addr); ++ WREG32(RADEON_CP_RB_BASE, ring->gpu_addr); + /* Force read & write ptr to 0 */ + WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA | RADEON_RB_NO_UPDATE); + WREG32(RADEON_CP_RB_RPTR_WR, 0); +- rdev->cp.wptr = 0; +- WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr); ++ ring->wptr = 0; ++ WREG32(RADEON_CP_RB_WPTR, ring->wptr); + + /* set the wb address whether it's enabled or not */ + WREG32(R_00070C_CP_RB_RPTR_ADDR, +@@ -1123,7 +1173,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) + + WREG32(RADEON_CP_RB_CNTL, tmp); + udelay(10); +- rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); ++ ring->rptr = RREG32(RADEON_CP_RB_RPTR); + /* Set cp mode to bus mastering & enable cp*/ + WREG32(RADEON_CP_CSQ_MODE, + REG_SET(RADEON_INDIRECT2_START, indirect2_start) | +@@ -1131,13 +1181,13 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) + WREG32(RADEON_CP_RB_WPTR_DELAY, 0); + WREG32(RADEON_CP_CSQ_MODE, 0x00004D4D); + WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM); +- radeon_ring_start(rdev); +- r = radeon_ring_test(rdev); ++ radeon_ring_start(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); ++ r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); + if (r) { + DRM_ERROR("radeon: cp isn't working (%d).\n", r); + return r; + } +- rdev->cp.ready = true; ++ ring->ready = true; + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + return 0; + } +@@ -1149,7 +1199,7 @@ void r100_cp_fini(struct radeon_device *rdev) + } + /* Disable ring */ + r100_cp_disable(rdev); +- radeon_ring_fini(rdev); ++ radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + DRM_INFO("radeon: cp finalized\n"); + } + +@@ -1157,7 +1207,7 @@ void r100_cp_disable(struct radeon_device *rdev) + { + /* Disable ring */ + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); +- rdev->cp.ready = false; ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; + WREG32(RADEON_CP_CSQ_MODE, 0); + WREG32(RADEON_CP_CSQ_CNTL, 0); + WREG32(R_000770_SCRATCH_UMSK, 0); +@@ -1167,13 +1217,6 @@ void r100_cp_disable(struct radeon_device *rdev) + } + } + +-void r100_cp_commit(struct radeon_device *rdev) +-{ +- WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr); +- (void)RREG32(RADEON_CP_RB_WPTR); +-} +- +- + /* + * CS functions + */ +@@ -1547,7 +1590,17 @@ static int r100_packet0_check(struct radeon_cs_parser *p, + r100_cs_dump_packet(p, pkt); + return r; + } +- ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { ++ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) ++ tile_flags |= RADEON_TXO_MACRO_TILE; ++ if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) ++ tile_flags |= RADEON_TXO_MICRO_TILE_X2; ++ ++ tmp = idx_value & ~(0x7 << 2); ++ tmp |= tile_flags; ++ ib[idx] = tmp + ((u32)reloc->lobj.gpu_offset); ++ } else ++ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + track->textures[i].robj = reloc->robj; + track->tex_dirty = true; + break; +@@ -1618,15 +1671,17 @@ static int r100_packet0_check(struct radeon_cs_parser *p, + r100_cs_dump_packet(p, pkt); + return r; + } +- +- if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) +- tile_flags |= RADEON_COLOR_TILE_ENABLE; +- if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) +- tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; +- +- tmp = idx_value & ~(0x7 << 16); +- tmp |= tile_flags; +- ib[idx] = tmp; ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { ++ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) ++ tile_flags |= RADEON_COLOR_TILE_ENABLE; ++ if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) ++ tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; ++ ++ tmp = idx_value & ~(0x7 << 16); ++ tmp |= tile_flags; ++ ib[idx] = tmp; ++ } else ++ ib[idx] = idx_value; + + track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK; + track->cb_dirty = true; +@@ -2101,9 +2156,9 @@ int r100_mc_wait_for_idle(struct radeon_device *rdev) + return -1; + } + +-void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, struct radeon_cp *cp) ++void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, struct radeon_ring *ring) + { +- lockup->last_cp_rptr = cp->rptr; ++ lockup->last_cp_rptr = ring->rptr; + lockup->last_jiffies = jiffies; + } + +@@ -2128,20 +2183,20 @@ void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, struct radeon_cp *cp + * false positive when CP is just gived nothing to do. + * + **/ +-bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *lockup, struct radeon_cp *cp) ++bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *lockup, struct radeon_ring *ring) + { + unsigned long cjiffies, elapsed; + + cjiffies = jiffies; + if (!time_after(cjiffies, lockup->last_jiffies)) { + /* likely a wrap around */ +- lockup->last_cp_rptr = cp->rptr; ++ lockup->last_cp_rptr = ring->rptr; + lockup->last_jiffies = jiffies; + return false; + } +- if (cp->rptr != lockup->last_cp_rptr) { ++ if (ring->rptr != lockup->last_cp_rptr) { + /* CP is still working no lockup */ +- lockup->last_cp_rptr = cp->rptr; ++ lockup->last_cp_rptr = ring->rptr; + lockup->last_jiffies = jiffies; + return false; + } +@@ -2154,32 +2209,31 @@ bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *l + return false; + } + +-bool r100_gpu_is_lockup(struct radeon_device *rdev) ++bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) + { + u32 rbbm_status; + int r; + + rbbm_status = RREG32(R_000E40_RBBM_STATUS); + if (!G_000E40_GUI_ACTIVE(rbbm_status)) { +- r100_gpu_lockup_update(&rdev->config.r100.lockup, &rdev->cp); ++ r100_gpu_lockup_update(&rdev->config.r100.lockup, ring); + return false; + } + /* force CP activities */ +- r = radeon_ring_lock(rdev, 2); ++ r = radeon_ring_lock(rdev, ring, 2); + if (!r) { + /* PACKET2 NOP */ +- radeon_ring_write(rdev, 0x80000000); +- radeon_ring_write(rdev, 0x80000000); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_unlock_commit(rdev, ring); + } +- rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); +- return r100_gpu_cp_is_lockup(rdev, &rdev->config.r100.lockup, &rdev->cp); ++ ring->rptr = RREG32(ring->rptr_reg); ++ return r100_gpu_cp_is_lockup(rdev, &rdev->config.r100.lockup, ring); + } + + void r100_bm_disable(struct radeon_device *rdev) + { + u32 tmp; +- u16 tmp16; + + /* disable bus mastering */ + tmp = RREG32(R_000030_BUS_CNTL); +@@ -2190,8 +2244,7 @@ void r100_bm_disable(struct radeon_device *rdev) + WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000040); + tmp = RREG32(RADEON_BUS_CNTL); + mdelay(1); +- pci_read_config_word(rdev->pdev, 0x4, &tmp16); +- pci_write_config_word(rdev->pdev, 0x4, tmp16 & 0xFFFB); ++ pci_clear_master(rdev->pdev); + mdelay(1); + } + +@@ -2501,7 +2554,7 @@ static void r100_pll_errata_after_data(struct radeon_device *rdev) + * or the chip could hang on a subsequent access + */ + if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) { +- udelay(5000); ++ mdelay(5); + } + + /* This function is required to workaround a hardware bug in some (all?) +@@ -2582,21 +2635,22 @@ static int r100_debugfs_cp_ring_info(struct seq_file *m, void *data) + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + uint32_t rdp, wdp; + unsigned count, i, j; + +- radeon_ring_free_size(rdev); ++ radeon_ring_free_size(rdev, ring); + rdp = RREG32(RADEON_CP_RB_RPTR); + wdp = RREG32(RADEON_CP_RB_WPTR); +- count = (rdp + rdev->cp.ring_size - wdp) & rdev->cp.ptr_mask; ++ count = (rdp + ring->ring_size - wdp) & ring->ptr_mask; + seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); + seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp); + seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp); +- seq_printf(m, "%u free dwords in ring\n", rdev->cp.ring_free_dw); ++ seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); + seq_printf(m, "%u dwords in ring\n", count); + for (j = 0; j <= count; j++) { +- i = (rdp + j) & rdev->cp.ptr_mask; +- seq_printf(m, "r[%04d]=0x%08x\n", i, rdev->cp.ring[i]); ++ i = (rdp + j) & ring->ptr_mask; ++ seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]); + } + return 0; + } +@@ -3638,7 +3692,7 @@ void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track + } + } + +-int r100_ring_test(struct radeon_device *rdev) ++int r100_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) + { + uint32_t scratch; + uint32_t tmp = 0; +@@ -3651,15 +3705,15 @@ int r100_ring_test(struct radeon_device *rdev) + return r; + } + WREG32(scratch, 0xCAFEDEAD); +- r = radeon_ring_lock(rdev, 2); ++ r = radeon_ring_lock(rdev, ring, 2); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + radeon_scratch_free(rdev, scratch); + return r; + } +- radeon_ring_write(rdev, PACKET0(scratch, 0)); +- radeon_ring_write(rdev, 0xDEADBEEF); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_write(ring, PACKET0(scratch, 0)); ++ radeon_ring_write(ring, 0xDEADBEEF); ++ radeon_ring_unlock_commit(rdev, ring); + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(scratch); + if (tmp == 0xDEADBEEF) { +@@ -3680,12 +3734,14 @@ int r100_ring_test(struct radeon_device *rdev) + + void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) + { +- radeon_ring_write(rdev, PACKET0(RADEON_CP_IB_BASE, 1)); +- radeon_ring_write(rdev, ib->gpu_addr); +- radeon_ring_write(rdev, ib->length_dw); ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ ++ radeon_ring_write(ring, PACKET0(RADEON_CP_IB_BASE, 1)); ++ radeon_ring_write(ring, ib->gpu_addr); ++ radeon_ring_write(ring, ib->length_dw); + } + +-int r100_ib_test(struct radeon_device *rdev) ++int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) + { + struct radeon_ib *ib; + uint32_t scratch; +@@ -3699,7 +3755,7 @@ int r100_ib_test(struct radeon_device *rdev) + return r; + } + WREG32(scratch, 0xCAFEDEAD); +- r = radeon_ib_get(rdev, &ib); ++ r = radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX, &ib, 256); + if (r) { + return r; + } +@@ -3743,34 +3799,16 @@ int r100_ib_test(struct radeon_device *rdev) + + void r100_ib_fini(struct radeon_device *rdev) + { ++ radeon_ib_pool_suspend(rdev); + radeon_ib_pool_fini(rdev); + } + +-int r100_ib_init(struct radeon_device *rdev) +-{ +- int r; +- +- r = radeon_ib_pool_init(rdev); +- if (r) { +- dev_err(rdev->dev, "failed initializing IB pool (%d).\n", r); +- r100_ib_fini(rdev); +- return r; +- } +- r = r100_ib_test(rdev); +- if (r) { +- dev_err(rdev->dev, "failed testing IB (%d).\n", r); +- r100_ib_fini(rdev); +- return r; +- } +- return 0; +-} +- + void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save) + { + /* Shutdown CP we shouldn't need to do that but better be safe than + * sorry + */ +- rdev->cp.ready = false; ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; + WREG32(R_000740_CP_CSQ_CNTL, 0); + + /* Save few CRTC registers */ +@@ -3908,6 +3946,12 @@ static int r100_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ + /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); +@@ -3923,16 +3967,25 @@ static int r100_startup(struct radeon_device *rdev) + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } +- r = r100_ib_init(rdev); ++ ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + if (r) { +- dev_err(rdev->dev, "failed initializing IB (%d).\n", r); ++ dev_err(rdev->dev, "failed testing IB (%d).\n", r); ++ rdev->accel_working = false; + return r; + } ++ + return 0; + } + + int r100_resume(struct radeon_device *rdev) + { ++ int r; ++ + /* Make sur GART are not working */ + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_disable(rdev); +@@ -3950,11 +4003,18 @@ int r100_resume(struct radeon_device *rdev) + r100_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); +- return r100_startup(rdev); ++ ++ rdev->accel_working = true; ++ r = r100_startup(rdev); ++ if (r) { ++ rdev->accel_working = false; ++ } ++ return r; + } + + int r100_suspend(struct radeon_device *rdev) + { ++ radeon_ib_pool_suspend(rdev); + r100_cp_disable(rdev); + radeon_wb_disable(rdev); + r100_irq_disable(rdev); +@@ -4070,7 +4130,14 @@ int r100_init(struct radeon_device *rdev) + return r; + } + r100_set_safe_registers(rdev); ++ ++ r = radeon_ib_pool_init(rdev); + rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ + r = r100_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ +diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c +index a1f3ba0..a59cc47 100644 +--- a/drivers/gpu/drm/radeon/r200.c ++++ b/drivers/gpu/drm/radeon/r200.c +@@ -87,6 +87,7 @@ int r200_copy_dma(struct radeon_device *rdev, + unsigned num_gpu_pages, + struct radeon_fence *fence) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + uint32_t size; + uint32_t cur_size; + int i, num_loops; +@@ -95,33 +96,33 @@ int r200_copy_dma(struct radeon_device *rdev, + /* radeon pitch is /64 */ + size = num_gpu_pages << RADEON_GPU_PAGE_SHIFT; + num_loops = DIV_ROUND_UP(size, 0x1FFFFF); +- r = radeon_ring_lock(rdev, num_loops * 4 + 64); ++ r = radeon_ring_lock(rdev, ring, num_loops * 4 + 64); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + return r; + } + /* Must wait for 2D idle & clean before DMA or hangs might happen */ +- radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); +- radeon_ring_write(rdev, (1 << 16)); ++ radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); ++ radeon_ring_write(ring, (1 << 16)); + for (i = 0; i < num_loops; i++) { + cur_size = size; + if (cur_size > 0x1FFFFF) { + cur_size = 0x1FFFFF; + } + size -= cur_size; +- radeon_ring_write(rdev, PACKET0(0x720, 2)); +- radeon_ring_write(rdev, src_offset); +- radeon_ring_write(rdev, dst_offset); +- radeon_ring_write(rdev, cur_size | (1 << 31) | (1 << 30)); ++ radeon_ring_write(ring, PACKET0(0x720, 2)); ++ radeon_ring_write(ring, src_offset); ++ radeon_ring_write(ring, dst_offset); ++ radeon_ring_write(ring, cur_size | (1 << 31) | (1 << 30)); + src_offset += cur_size; + dst_offset += cur_size; + } +- radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); +- radeon_ring_write(rdev, RADEON_WAIT_DMA_GUI_IDLE); ++ radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); ++ radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE); + if (fence) { + r = radeon_fence_emit(rdev, fence); + } +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_unlock_commit(rdev, ring); + return r; + } + +@@ -214,7 +215,17 @@ int r200_packet0_check(struct radeon_cs_parser *p, + r100_cs_dump_packet(p, pkt); + return r; + } +- ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { ++ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) ++ tile_flags |= R200_TXO_MACRO_TILE; ++ if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) ++ tile_flags |= R200_TXO_MICRO_TILE; ++ ++ tmp = idx_value & ~(0x7 << 2); ++ tmp |= tile_flags; ++ ib[idx] = tmp + ((u32)reloc->lobj.gpu_offset); ++ } else ++ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + track->textures[i].robj = reloc->robj; + track->tex_dirty = true; + break; +@@ -276,14 +287,17 @@ int r200_packet0_check(struct radeon_cs_parser *p, + return r; + } + +- if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) +- tile_flags |= RADEON_COLOR_TILE_ENABLE; +- if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) +- tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { ++ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) ++ tile_flags |= RADEON_COLOR_TILE_ENABLE; ++ if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) ++ tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; + +- tmp = idx_value & ~(0x7 << 16); +- tmp |= tile_flags; +- ib[idx] = tmp; ++ tmp = idx_value & ~(0x7 << 16); ++ tmp |= tile_flags; ++ ib[idx] = tmp; ++ } else ++ ib[idx] = idx_value; + + track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK; + track->cb_dirty = true; +diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c +index 441570b..63b53aa 100644 +--- a/drivers/gpu/drm/radeon/r300.c ++++ b/drivers/gpu/drm/radeon/r300.c +@@ -105,8 +105,8 @@ int rv370_pcie_gart_init(struct radeon_device *rdev) + if (r) + DRM_ERROR("Failed to register debugfs file for PCIE gart !\n"); + rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; +- rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush; +- rdev->asic->gart_set_page = &rv370_pcie_gart_set_page; ++ rdev->asic->gart.tlb_flush = &rv370_pcie_gart_tlb_flush; ++ rdev->asic->gart.set_page = &rv370_pcie_gart_set_page; + return radeon_gart_table_vram_alloc(rdev); + } + +@@ -175,36 +175,38 @@ void rv370_pcie_gart_fini(struct radeon_device *rdev) + void r300_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence) + { ++ struct radeon_ring *ring = &rdev->ring[fence->ring]; ++ + /* Who ever call radeon_fence_emit should call ring_lock and ask + * for enough space (today caller are ib schedule and buffer move) */ + /* Write SC register so SC & US assert idle */ +- radeon_ring_write(rdev, PACKET0(R300_RE_SCISSORS_TL, 0)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, PACKET0(R300_RE_SCISSORS_BR, 0)); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET0(R300_RE_SCISSORS_TL, 0)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, PACKET0(R300_RE_SCISSORS_BR, 0)); ++ radeon_ring_write(ring, 0); + /* Flush 3D cache */ +- radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, R300_RB3D_DC_FLUSH); +- radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, R300_ZC_FLUSH); ++ radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, R300_RB3D_DC_FLUSH); ++ radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, R300_ZC_FLUSH); + /* Wait until IDLE & CLEAN */ +- radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); +- radeon_ring_write(rdev, (RADEON_WAIT_3D_IDLECLEAN | ++ radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); ++ radeon_ring_write(ring, (RADEON_WAIT_3D_IDLECLEAN | + RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_DMA_GUI_IDLE)); +- radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0)); +- radeon_ring_write(rdev, rdev->config.r300.hdp_cntl | ++ radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); ++ radeon_ring_write(ring, rdev->config.r300.hdp_cntl | + RADEON_HDP_READ_BUFFER_INVALIDATE); +- radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0)); +- radeon_ring_write(rdev, rdev->config.r300.hdp_cntl); ++ radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); ++ radeon_ring_write(ring, rdev->config.r300.hdp_cntl); + /* Emit fence sequence & fire IRQ */ +- radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0)); +- radeon_ring_write(rdev, fence->seq); +- radeon_ring_write(rdev, PACKET0(RADEON_GEN_INT_STATUS, 0)); +- radeon_ring_write(rdev, RADEON_SW_INT_FIRE); ++ radeon_ring_write(ring, PACKET0(rdev->fence_drv[fence->ring].scratch_reg, 0)); ++ radeon_ring_write(ring, fence->seq); ++ radeon_ring_write(ring, PACKET0(RADEON_GEN_INT_STATUS, 0)); ++ radeon_ring_write(ring, RADEON_SW_INT_FIRE); + } + +-void r300_ring_start(struct radeon_device *rdev) ++void r300_ring_start(struct radeon_device *rdev, struct radeon_ring *ring) + { + unsigned gb_tile_config; + int r; +@@ -227,44 +229,44 @@ void r300_ring_start(struct radeon_device *rdev) + break; + } + +- r = radeon_ring_lock(rdev, 64); ++ r = radeon_ring_lock(rdev, ring, 64); + if (r) { + return; + } +- radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET0(RADEON_ISYNC_CNTL, 0)); ++ radeon_ring_write(ring, + RADEON_ISYNC_ANY2D_IDLE3D | + RADEON_ISYNC_ANY3D_IDLE2D | + RADEON_ISYNC_WAIT_IDLEGUI | + RADEON_ISYNC_CPSCRATCH_IDLEGUI); +- radeon_ring_write(rdev, PACKET0(R300_GB_TILE_CONFIG, 0)); +- radeon_ring_write(rdev, gb_tile_config); +- radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET0(R300_GB_TILE_CONFIG, 0)); ++ radeon_ring_write(ring, gb_tile_config); ++ radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); ++ radeon_ring_write(ring, + RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_3D_IDLECLEAN); +- radeon_ring_write(rdev, PACKET0(R300_DST_PIPE_CONFIG, 0)); +- radeon_ring_write(rdev, R300_PIPE_AUTO_CONFIG); +- radeon_ring_write(rdev, PACKET0(R300_GB_SELECT, 0)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, PACKET0(R300_GB_ENABLE, 0)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); +- radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE); +- radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET0(R300_DST_PIPE_CONFIG, 0)); ++ radeon_ring_write(ring, R300_PIPE_AUTO_CONFIG); ++ radeon_ring_write(ring, PACKET0(R300_GB_SELECT, 0)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, PACKET0(R300_GB_ENABLE, 0)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); ++ radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, R300_ZC_FLUSH | R300_ZC_FREE); ++ radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); ++ radeon_ring_write(ring, + RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_3D_IDLECLEAN); +- radeon_ring_write(rdev, PACKET0(R300_GB_AA_CONFIG, 0)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); +- radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE); +- radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS0, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET0(R300_GB_AA_CONFIG, 0)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); ++ radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, R300_ZC_FLUSH | R300_ZC_FREE); ++ radeon_ring_write(ring, PACKET0(R300_GB_MSPOS0, 0)); ++ radeon_ring_write(ring, + ((6 << R300_MS_X0_SHIFT) | + (6 << R300_MS_Y0_SHIFT) | + (6 << R300_MS_X1_SHIFT) | +@@ -273,8 +275,8 @@ void r300_ring_start(struct radeon_device *rdev) + (6 << R300_MS_Y2_SHIFT) | + (6 << R300_MSBD0_Y_SHIFT) | + (6 << R300_MSBD0_X_SHIFT))); +- radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS1, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET0(R300_GB_MSPOS1, 0)); ++ radeon_ring_write(ring, + ((6 << R300_MS_X3_SHIFT) | + (6 << R300_MS_Y3_SHIFT) | + (6 << R300_MS_X4_SHIFT) | +@@ -282,16 +284,16 @@ void r300_ring_start(struct radeon_device *rdev) + (6 << R300_MS_X5_SHIFT) | + (6 << R300_MS_Y5_SHIFT) | + (6 << R300_MSBD1_SHIFT))); +- radeon_ring_write(rdev, PACKET0(R300_GA_ENHANCE, 0)); +- radeon_ring_write(rdev, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL); +- radeon_ring_write(rdev, PACKET0(R300_GA_POLY_MODE, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET0(R300_GA_ENHANCE, 0)); ++ radeon_ring_write(ring, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL); ++ radeon_ring_write(ring, PACKET0(R300_GA_POLY_MODE, 0)); ++ radeon_ring_write(ring, + R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE); +- radeon_ring_write(rdev, PACKET0(R300_GA_ROUND_MODE, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET0(R300_GA_ROUND_MODE, 0)); ++ radeon_ring_write(ring, + R300_GEOMETRY_ROUND_NEAREST | + R300_COLOR_ROUND_NEAREST); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_unlock_commit(rdev, ring); + } + + void r300_errata(struct radeon_device *rdev) +@@ -375,26 +377,26 @@ void r300_gpu_init(struct radeon_device *rdev) + rdev->num_gb_pipes, rdev->num_z_pipes); + } + +-bool r300_gpu_is_lockup(struct radeon_device *rdev) ++bool r300_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) + { + u32 rbbm_status; + int r; + + rbbm_status = RREG32(R_000E40_RBBM_STATUS); + if (!G_000E40_GUI_ACTIVE(rbbm_status)) { +- r100_gpu_lockup_update(&rdev->config.r300.lockup, &rdev->cp); ++ r100_gpu_lockup_update(&rdev->config.r300.lockup, ring); + return false; + } + /* force CP activities */ +- r = radeon_ring_lock(rdev, 2); ++ r = radeon_ring_lock(rdev, ring, 2); + if (!r) { + /* PACKET2 NOP */ +- radeon_ring_write(rdev, 0x80000000); +- radeon_ring_write(rdev, 0x80000000); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_unlock_commit(rdev, ring); + } +- rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); +- return r100_gpu_cp_is_lockup(rdev, &rdev->config.r300.lockup, &rdev->cp); ++ ring->rptr = RREG32(RADEON_CP_RB_RPTR); ++ return r100_gpu_cp_is_lockup(rdev, &rdev->config.r300.lockup, ring); + } + + int r300_asic_reset(struct radeon_device *rdev) +@@ -701,7 +703,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, + return r; + } + +- if (p->keep_tiling_flags) { ++ if (p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) { + ib[idx] = (idx_value & 31) | /* keep the 1st 5 bits */ + ((idx_value & ~31) + (u32)reloc->lobj.gpu_offset); + } else { +@@ -765,7 +767,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, + /* RB3D_COLORPITCH1 */ + /* RB3D_COLORPITCH2 */ + /* RB3D_COLORPITCH3 */ +- if (!p->keep_tiling_flags) { ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", +@@ -850,7 +852,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, + break; + case 0x4F24: + /* ZB_DEPTHPITCH */ +- if (!p->keep_tiling_flags) { ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", +@@ -1396,6 +1398,12 @@ static int r300_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ + /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); +@@ -1411,16 +1419,25 @@ static int r300_startup(struct radeon_device *rdev) + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } +- r = r100_ib_init(rdev); ++ ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + if (r) { +- dev_err(rdev->dev, "failed initializing IB (%d).\n", r); ++ dev_err(rdev->dev, "failed testing IB (%d).\n", r); ++ rdev->accel_working = false; + return r; + } ++ + return 0; + } + + int r300_resume(struct radeon_device *rdev) + { ++ int r; ++ + /* Make sur GART are not working */ + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); +@@ -1440,11 +1457,18 @@ int r300_resume(struct radeon_device *rdev) + r300_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); +- return r300_startup(rdev); ++ ++ rdev->accel_working = true; ++ r = r300_startup(rdev); ++ if (r) { ++ rdev->accel_working = false; ++ } ++ return r; + } + + int r300_suspend(struct radeon_device *rdev) + { ++ radeon_ib_pool_suspend(rdev); + r100_cp_disable(rdev); + radeon_wb_disable(rdev); + r100_irq_disable(rdev); +@@ -1542,7 +1566,14 @@ int r300_init(struct radeon_device *rdev) + return r; + } + r300_set_reg_safe(rdev); ++ ++ r = radeon_ib_pool_init(rdev); + rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ + r = r300_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ +diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c +index 5b219b8..1a9347f 100644 +--- a/drivers/gpu/drm/radeon/r420.c ++++ b/drivers/gpu/drm/radeon/r420.c +@@ -199,6 +199,8 @@ static void r420_clock_resume(struct radeon_device *rdev) + + static void r420_cp_errata_init(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ + /* RV410 and R420 can lock up if CP DMA to host memory happens + * while the 2D engine is busy. + * +@@ -206,22 +208,24 @@ static void r420_cp_errata_init(struct radeon_device *rdev) + * of the CP init, apparently. + */ + radeon_scratch_get(rdev, &rdev->config.r300.resync_scratch); +- radeon_ring_lock(rdev, 8); +- radeon_ring_write(rdev, PACKET0(R300_CP_RESYNC_ADDR, 1)); +- radeon_ring_write(rdev, rdev->config.r300.resync_scratch); +- radeon_ring_write(rdev, 0xDEADBEEF); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_lock(rdev, ring, 8); ++ radeon_ring_write(ring, PACKET0(R300_CP_RESYNC_ADDR, 1)); ++ radeon_ring_write(ring, rdev->config.r300.resync_scratch); ++ radeon_ring_write(ring, 0xDEADBEEF); ++ radeon_ring_unlock_commit(rdev, ring); + } + + static void r420_cp_errata_fini(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ + /* Catch the RESYNC we dispatched all the way back, + * at the very beginning of the CP init. + */ +- radeon_ring_lock(rdev, 8); +- radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, R300_RB3D_DC_FINISH); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_lock(rdev, ring, 8); ++ radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, R300_RB3D_DC_FINISH); ++ radeon_ring_unlock_commit(rdev, ring); + radeon_scratch_free(rdev, rdev->config.r300.resync_scratch); + } + +@@ -254,6 +258,12 @@ static int r420_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ + /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); +@@ -270,16 +280,25 @@ static int r420_startup(struct radeon_device *rdev) + return r; + } + r420_cp_errata_init(rdev); +- r = r100_ib_init(rdev); ++ ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + if (r) { +- dev_err(rdev->dev, "failed initializing IB (%d).\n", r); ++ dev_err(rdev->dev, "failed testing IB (%d).\n", r); ++ rdev->accel_working = false; + return r; + } ++ + return 0; + } + + int r420_resume(struct radeon_device *rdev) + { ++ int r; ++ + /* Make sur GART are not working */ + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); +@@ -303,11 +322,18 @@ int r420_resume(struct radeon_device *rdev) + r420_clock_resume(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); +- return r420_startup(rdev); ++ ++ rdev->accel_working = true; ++ r = r420_startup(rdev); ++ if (r) { ++ rdev->accel_working = false; ++ } ++ return r; + } + + int r420_suspend(struct radeon_device *rdev) + { ++ radeon_ib_pool_suspend(rdev); + r420_cp_errata_fini(rdev); + r100_cp_disable(rdev); + radeon_wb_disable(rdev); +@@ -416,7 +442,14 @@ int r420_init(struct radeon_device *rdev) + return r; + } + r420_set_reg_safe(rdev); ++ ++ r = radeon_ib_pool_init(rdev); + rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ + r = r420_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ +diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h +index fc43705..ec576aa 100644 +--- a/drivers/gpu/drm/radeon/r500_reg.h ++++ b/drivers/gpu/drm/radeon/r500_reg.h +@@ -351,6 +351,8 @@ + #define AVIVO_D1CRTC_BLANK_CONTROL 0x6084 + #define AVIVO_D1CRTC_INTERLACE_CONTROL 0x6088 + #define AVIVO_D1CRTC_INTERLACE_STATUS 0x608c ++#define AVIVO_D1CRTC_STATUS 0x609c ++# define AVIVO_D1CRTC_V_BLANK (1 << 0) + #define AVIVO_D1CRTC_STATUS_POSITION 0x60a0 + #define AVIVO_D1CRTC_FRAME_COUNT 0x60a4 + #define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4 +@@ -573,6 +575,7 @@ + + #define AVIVO_TMDSA_CNTL 0x7880 + # define AVIVO_TMDSA_CNTL_ENABLE (1 << 0) ++# define AVIVO_TMDSA_CNTL_HDMI_EN (1 << 2) + # define AVIVO_TMDSA_CNTL_HPD_MASK (1 << 4) + # define AVIVO_TMDSA_CNTL_HPD_SELECT (1 << 8) + # define AVIVO_TMDSA_CNTL_SYNC_PHASE (1 << 12) +@@ -633,6 +636,7 @@ + + #define AVIVO_LVTMA_CNTL 0x7a80 + # define AVIVO_LVTMA_CNTL_ENABLE (1 << 0) ++# define AVIVO_LVTMA_CNTL_HDMI_EN (1 << 2) + # define AVIVO_LVTMA_CNTL_HPD_MASK (1 << 4) + # define AVIVO_LVTMA_CNTL_HPD_SELECT (1 << 8) + # define AVIVO_LVTMA_CNTL_SYNC_PHASE (1 << 12) +diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c +index f36a5c9..57be784 100644 +--- a/drivers/gpu/drm/radeon/r520.c ++++ b/drivers/gpu/drm/radeon/r520.c +@@ -33,7 +33,7 @@ + + /* This files gather functions specifics to: r520,rv530,rv560,rv570,r580 */ + +-static int r520_mc_wait_for_idle(struct radeon_device *rdev) ++int r520_mc_wait_for_idle(struct radeon_device *rdev) + { + unsigned i; + uint32_t tmp; +@@ -187,6 +187,12 @@ static int r520_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ + /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); +@@ -202,9 +208,15 @@ static int r520_startup(struct radeon_device *rdev) + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } +- r = r100_ib_init(rdev); ++ ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + if (r) { +- dev_err(rdev->dev, "failed initializing IB (%d).\n", r); ++ dev_err(rdev->dev, "failed testing IB (%d).\n", r); ++ rdev->accel_working = false; + return r; + } + return 0; +@@ -212,6 +224,8 @@ static int r520_startup(struct radeon_device *rdev) + + int r520_resume(struct radeon_device *rdev) + { ++ int r; ++ + /* Make sur GART are not working */ + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); +@@ -229,7 +243,13 @@ int r520_resume(struct radeon_device *rdev) + rv515_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); +- return r520_startup(rdev); ++ ++ rdev->accel_working = true; ++ r = r520_startup(rdev); ++ if (r) { ++ rdev->accel_working = false; ++ } ++ return r; + } + + int r520_init(struct radeon_device *rdev) +@@ -295,7 +315,14 @@ int r520_init(struct radeon_device *rdev) + if (r) + return r; + rv515_set_safe_registers(rdev); ++ ++ r = radeon_ib_pool_init(rdev); + rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ + r = r520_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ +diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c +index e5299a0..79fab68 100644 +--- a/drivers/gpu/drm/radeon/r600.c ++++ b/drivers/gpu/drm/radeon/r600.c +@@ -49,6 +49,7 @@ + #define EVERGREEN_PM4_UCODE_SIZE 1376 + #define EVERGREEN_RLC_UCODE_SIZE 768 + #define CAYMAN_RLC_UCODE_SIZE 1024 ++#define ARUBA_RLC_UCODE_SIZE 1536 + + /* Firmware Names */ + MODULE_FIRMWARE("radeon/R600_pfp.bin"); +@@ -1134,7 +1135,7 @@ static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc + } + if (rdev->flags & RADEON_IS_AGP) { + size_bf = mc->gtt_start; +- size_af = 0xFFFFFFFF - mc->gtt_end + 1; ++ size_af = 0xFFFFFFFF - mc->gtt_end; + if (size_bf > size_af) { + if (mc->mc_vram_size > size_bf) { + dev_warn(rdev->dev, "limiting VRAM\n"); +@@ -1148,7 +1149,7 @@ static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc + mc->real_vram_size = size_af; + mc->mc_vram_size = size_af; + } +- mc->vram_start = mc->gtt_end; ++ mc->vram_start = mc->gtt_end + 1; + } + mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; + dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", +@@ -1344,7 +1345,7 @@ int r600_gpu_soft_reset(struct radeon_device *rdev) + return 0; + } + +-bool r600_gpu_is_lockup(struct radeon_device *rdev) ++bool r600_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) + { + u32 srbm_status; + u32 grbm_status; +@@ -1361,19 +1362,19 @@ bool r600_gpu_is_lockup(struct radeon_device *rdev) + grbm_status = RREG32(R_008010_GRBM_STATUS); + grbm_status2 = RREG32(R_008014_GRBM_STATUS2); + if (!G_008010_GUI_ACTIVE(grbm_status)) { +- r100_gpu_lockup_update(lockup, &rdev->cp); ++ r100_gpu_lockup_update(lockup, ring); + return false; + } + /* force CP activities */ +- r = radeon_ring_lock(rdev, 2); ++ r = radeon_ring_lock(rdev, ring, 2); + if (!r) { + /* PACKET2 NOP */ +- radeon_ring_write(rdev, 0x80000000); +- radeon_ring_write(rdev, 0x80000000); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_unlock_commit(rdev, ring); + } +- rdev->cp.rptr = RREG32(R600_CP_RB_RPTR); +- return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp); ++ ring->rptr = RREG32(ring->rptr_reg); ++ return r100_gpu_cp_is_lockup(rdev, lockup, ring); + } + + int r600_asic_reset(struct radeon_device *rdev) +@@ -2087,10 +2088,6 @@ out: + platform_device_unregister(pdev); + + if (err) { +- if (err != -EINVAL) +- printk(KERN_ERR +- "r600_cp: Failed to load firmware \"%s\"\n", +- fw_name); + release_firmware(rdev->pfp_fw); + rdev->pfp_fw = NULL; + release_firmware(rdev->me_fw); +@@ -2145,27 +2142,28 @@ static int r600_cp_load_microcode(struct radeon_device *rdev) + + int r600_cp_start(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + uint32_t cp_me; + +- r = radeon_ring_lock(rdev, 7); ++ r = radeon_ring_lock(rdev, ring, 7); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } +- radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); +- radeon_ring_write(rdev, 0x1); ++ radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); ++ radeon_ring_write(ring, 0x1); + if (rdev->family >= CHIP_RV770) { +- radeon_ring_write(rdev, 0x0); +- radeon_ring_write(rdev, rdev->config.rv770.max_hw_contexts - 1); ++ radeon_ring_write(ring, 0x0); ++ radeon_ring_write(ring, rdev->config.rv770.max_hw_contexts - 1); + } else { +- radeon_ring_write(rdev, 0x3); +- radeon_ring_write(rdev, rdev->config.r600.max_hw_contexts - 1); ++ radeon_ring_write(ring, 0x3); ++ radeon_ring_write(ring, rdev->config.r600.max_hw_contexts - 1); + } +- radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_unlock_commit(rdev, ring); + + cp_me = 0xff; + WREG32(R_0086D8_CP_ME_CNTL, cp_me); +@@ -2174,6 +2172,7 @@ int r600_cp_start(struct radeon_device *rdev) + + int r600_cp_resume(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 tmp; + u32 rb_bufsz; + int r; +@@ -2185,13 +2184,13 @@ int r600_cp_resume(struct radeon_device *rdev) + WREG32(GRBM_SOFT_RESET, 0); + + /* Set ring buffer size */ +- rb_bufsz = drm_order(rdev->cp.ring_size / 8); ++ rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; + #ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; + #endif + WREG32(CP_RB_CNTL, tmp); +- WREG32(CP_SEM_WAIT_TIMER, 0x4); ++ WREG32(CP_SEM_WAIT_TIMER, 0x0); + + /* Set the write pointer delay */ + WREG32(CP_RB_WPTR_DELAY, 0); +@@ -2199,8 +2198,8 @@ int r600_cp_resume(struct radeon_device *rdev) + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA); + WREG32(CP_RB_RPTR_WR, 0); +- rdev->cp.wptr = 0; +- WREG32(CP_RB_WPTR, rdev->cp.wptr); ++ ring->wptr = 0; ++ WREG32(CP_RB_WPTR, ring->wptr); + + /* set the wb address whether it's enabled or not */ + WREG32(CP_RB_RPTR_ADDR, +@@ -2218,42 +2217,36 @@ int r600_cp_resume(struct radeon_device *rdev) + mdelay(1); + WREG32(CP_RB_CNTL, tmp); + +- WREG32(CP_RB_BASE, rdev->cp.gpu_addr >> 8); ++ WREG32(CP_RB_BASE, ring->gpu_addr >> 8); + WREG32(CP_DEBUG, (1 << 27) | (1 << 28)); + +- rdev->cp.rptr = RREG32(CP_RB_RPTR); ++ ring->rptr = RREG32(CP_RB_RPTR); + + r600_cp_start(rdev); +- rdev->cp.ready = true; +- r = radeon_ring_test(rdev); ++ ring->ready = true; ++ r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); + if (r) { +- rdev->cp.ready = false; ++ ring->ready = false; + return r; + } + return 0; + } + +-void r600_cp_commit(struct radeon_device *rdev) +-{ +- WREG32(CP_RB_WPTR, rdev->cp.wptr); +- (void)RREG32(CP_RB_WPTR); +-} +- +-void r600_ring_init(struct radeon_device *rdev, unsigned ring_size) ++void r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size) + { + u32 rb_bufsz; + + /* Align ring size */ + rb_bufsz = drm_order(ring_size / 8); + ring_size = (1 << (rb_bufsz + 1)) * 4; +- rdev->cp.ring_size = ring_size; +- rdev->cp.align_mask = 16 - 1; ++ ring->ring_size = ring_size; ++ ring->align_mask = 16 - 1; + } + + void r600_cp_fini(struct radeon_device *rdev) + { + r600_cp_stop(rdev); +- radeon_ring_fini(rdev); ++ radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + } + + +@@ -2272,11 +2265,11 @@ void r600_scratch_init(struct radeon_device *rdev) + } + } + +-int r600_ring_test(struct radeon_device *rdev) ++int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) + { + uint32_t scratch; + uint32_t tmp = 0; +- unsigned i; ++ unsigned i, ridx = radeon_ring_index(rdev, ring); + int r; + + r = radeon_scratch_get(rdev, &scratch); +@@ -2285,16 +2278,16 @@ int r600_ring_test(struct radeon_device *rdev) + return r; + } + WREG32(scratch, 0xCAFEDEAD); +- r = radeon_ring_lock(rdev, 3); ++ r = radeon_ring_lock(rdev, ring, 3); + if (r) { +- DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); ++ DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n", ridx, r); + radeon_scratch_free(rdev, scratch); + return r; + } +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); +- radeon_ring_write(rdev, ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); +- radeon_ring_write(rdev, 0xDEADBEEF); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(ring, ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); ++ radeon_ring_write(ring, 0xDEADBEEF); ++ radeon_ring_unlock_commit(rdev, ring); + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(scratch); + if (tmp == 0xDEADBEEF) +@@ -2302,10 +2295,10 @@ int r600_ring_test(struct radeon_device *rdev) + DRM_UDELAY(1); + } + if (i < rdev->usec_timeout) { +- DRM_INFO("ring test succeeded in %d usecs\n", i); ++ DRM_INFO("ring test on %d succeeded in %d usecs\n", ridx, i); + } else { +- DRM_ERROR("radeon: ring test failed (scratch(0x%04X)=0x%08X)\n", +- scratch, tmp); ++ DRM_ERROR("radeon: ring %d test failed (scratch(0x%04X)=0x%08X)\n", ++ ridx, scratch, tmp); + r = -EINVAL; + } + radeon_scratch_free(rdev, scratch); +@@ -2315,6 +2308,7 @@ int r600_ring_test(struct radeon_device *rdev) + void r600_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence) + { ++ struct radeon_ring *ring = &rdev->ring[fence->ring]; + u32 cp_coher_cntl = PACKET3_TC_ACTION_ENA | PACKET3_VC_ACTION_ENA | + PACKET3_SH_ACTION_ENA; + +@@ -2322,44 +2316,59 @@ void r600_fence_ring_emit(struct radeon_device *rdev, + cp_coher_cntl |= PACKET3_FULL_CACHE_ENA; + + if (rdev->wb.use_event) { +- u64 addr = rdev->wb.gpu_addr + R600_WB_EVENT_OFFSET + +- (u64)(rdev->fence_drv.scratch_reg - rdev->scratch.reg_base); ++ u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + /* flush read cache over gart */ +- radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3)); +- radeon_ring_write(rdev, cp_coher_cntl); +- radeon_ring_write(rdev, 0xFFFFFFFF); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 10); /* poll interval */ ++ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); ++ radeon_ring_write(ring, cp_coher_cntl); ++ radeon_ring_write(ring, 0xFFFFFFFF); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 10); /* poll interval */ + /* EVENT_WRITE_EOP - flush caches, send int */ +- radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); +- radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); +- radeon_ring_write(rdev, addr & 0xffffffff); +- radeon_ring_write(rdev, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); +- radeon_ring_write(rdev, fence->seq); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); ++ radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); ++ radeon_ring_write(ring, addr & 0xffffffff); ++ radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); ++ radeon_ring_write(ring, fence->seq); ++ radeon_ring_write(ring, 0); + } else { + /* flush read cache over gart */ +- radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3)); +- radeon_ring_write(rdev, cp_coher_cntl); +- radeon_ring_write(rdev, 0xFFFFFFFF); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 10); /* poll interval */ +- radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0)); +- radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0)); ++ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); ++ radeon_ring_write(ring, cp_coher_cntl); ++ radeon_ring_write(ring, 0xFFFFFFFF); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 10); /* poll interval */ ++ radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0)); ++ radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0)); + /* wait for 3D idle clean */ +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); +- radeon_ring_write(rdev, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(ring, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit); + /* Emit fence sequence & fire IRQ */ +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); +- radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); +- radeon_ring_write(rdev, fence->seq); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(ring, ((rdev->fence_drv[fence->ring].scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); ++ radeon_ring_write(ring, fence->seq); + /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */ +- radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0)); +- radeon_ring_write(rdev, RB_INT_STAT); ++ radeon_ring_write(ring, PACKET0(CP_INT_STATUS, 0)); ++ radeon_ring_write(ring, RB_INT_STAT); + } + } + ++void r600_semaphore_ring_emit(struct radeon_device *rdev, ++ struct radeon_ring *ring, ++ struct radeon_semaphore *semaphore, ++ bool emit_wait) ++{ ++ uint64_t addr = semaphore->gpu_addr; ++ unsigned sel = emit_wait ? PACKET3_SEM_SEL_WAIT : PACKET3_SEM_SEL_SIGNAL; ++ ++ if (rdev->family < CHIP_CAYMAN) ++ sel |= PACKET3_SEM_WAIT_ON_SIGNAL; ++ ++ radeon_ring_write(ring, PACKET3(PACKET3_MEM_SEMAPHORE, 1)); ++ radeon_ring_write(ring, addr & 0xffffffff); ++ radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | sel); ++} ++ + int r600_copy_blit(struct radeon_device *rdev, + uint64_t src_offset, + uint64_t dst_offset, +@@ -2412,6 +2421,7 @@ void r600_clear_surface_reg(struct radeon_device *rdev, int reg) + + int r600_startup(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + + /* enable pcie gen2 link */ +@@ -2442,7 +2452,7 @@ int r600_startup(struct radeon_device *rdev) + r = r600_blit_init(rdev); + if (r) { + r600_blit_fini(rdev); +- rdev->asic->copy = NULL; ++ rdev->asic->copy.copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } + +@@ -2451,6 +2461,12 @@ int r600_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ + /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); +@@ -2466,7 +2482,10 @@ int r600_startup(struct radeon_device *rdev) + } + r600_irq_set(rdev); + +- r = radeon_ring_init(rdev, rdev->cp.ring_size); ++ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, ++ R600_CP_RB_RPTR, R600_CP_RB_WPTR, ++ 0, 0xfffff, RADEON_CP_PACKET2); ++ + if (r) + return r; + r = r600_cp_load_microcode(rdev); +@@ -2476,6 +2495,17 @@ int r600_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); ++ if (r) { ++ DRM_ERROR("radeon: failed testing IB (%d).\n", r); ++ rdev->accel_working = false; ++ return r; ++ } ++ + return 0; + } + +@@ -2504,15 +2534,11 @@ int r600_resume(struct radeon_device *rdev) + /* post card */ + atom_asic_init(rdev->mode_info.atom_context); + ++ rdev->accel_working = true; + r = r600_startup(rdev); + if (r) { + DRM_ERROR("r600 startup failed on resume\n"); +- return r; +- } +- +- r = r600_ib_test(rdev); +- if (r) { +- DRM_ERROR("radeon: failed testing IB (%d).\n", r); ++ rdev->accel_working = false; + return r; + } + +@@ -2528,13 +2554,14 @@ int r600_resume(struct radeon_device *rdev) + int r600_suspend(struct radeon_device *rdev) + { + r600_audio_fini(rdev); ++ radeon_ib_pool_suspend(rdev); ++ r600_blit_suspend(rdev); + /* FIXME: we should wait for ring to be empty */ + r600_cp_stop(rdev); +- rdev->cp.ready = false; ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; + r600_irq_suspend(rdev); + radeon_wb_disable(rdev); + r600_pcie_gart_disable(rdev); +- r600_blit_suspend(rdev); + + return 0; + } +@@ -2601,8 +2628,8 @@ int r600_init(struct radeon_device *rdev) + if (r) + return r; + +- rdev->cp.ring_obj = NULL; +- r600_ring_init(rdev, 1024 * 1024); ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; ++ r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); + + rdev->ih.ring_obj = NULL; + r600_ih_ring_init(rdev, 64 * 1024); +@@ -2611,30 +2638,24 @@ int r600_init(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_ib_pool_init(rdev); + rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ + r = r600_startup(rdev); + if (r) { + dev_err(rdev->dev, "disabling GPU acceleration\n"); + r600_cp_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); ++ r100_ib_fini(rdev); + radeon_irq_kms_fini(rdev); + r600_pcie_gart_fini(rdev); + rdev->accel_working = false; + } +- if (rdev->accel_working) { +- r = radeon_ib_pool_init(rdev); +- if (r) { +- dev_err(rdev->dev, "IB initialization failed (%d).\n", r); +- rdev->accel_working = false; +- } else { +- r = r600_ib_test(rdev); +- if (r) { +- dev_err(rdev->dev, "IB test failed (%d).\n", r); +- rdev->accel_working = false; +- } +- } +- } + + r = r600_audio_init(rdev); + if (r) +@@ -2649,12 +2670,13 @@ void r600_fini(struct radeon_device *rdev) + r600_cp_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); +- radeon_ib_pool_fini(rdev); ++ r100_ib_fini(rdev); + radeon_irq_kms_fini(rdev); + r600_pcie_gart_fini(rdev); + r600_vram_scratch_fini(rdev); + radeon_agp_fini(rdev); + radeon_gem_fini(rdev); ++ radeon_semaphore_driver_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); +@@ -2668,24 +2690,27 @@ void r600_fini(struct radeon_device *rdev) + */ + void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) + { ++ struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; ++ + /* FIXME: implement */ +- radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); ++ radeon_ring_write(ring, + #ifdef __BIG_ENDIAN + (2 << 0) | + #endif + (ib->gpu_addr & 0xFFFFFFFC)); +- radeon_ring_write(rdev, upper_32_bits(ib->gpu_addr) & 0xFF); +- radeon_ring_write(rdev, ib->length_dw); ++ radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF); ++ radeon_ring_write(ring, ib->length_dw); + } + +-int r600_ib_test(struct radeon_device *rdev) ++int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) + { + struct radeon_ib *ib; + uint32_t scratch; + uint32_t tmp = 0; + unsigned i; + int r; ++ int ring_index = radeon_ring_index(rdev, ring); + + r = radeon_scratch_get(rdev, &scratch); + if (r) { +@@ -2693,7 +2718,7 @@ int r600_ib_test(struct radeon_device *rdev) + return r; + } + WREG32(scratch, 0xCAFEDEAD); +- r = radeon_ib_get(rdev, &ib); ++ r = radeon_ib_get(rdev, ring_index, &ib, 256); + if (r) { + DRM_ERROR("radeon: failed to get ib (%d).\n", r); + return r; +@@ -2701,20 +2726,7 @@ int r600_ib_test(struct radeon_device *rdev) + ib->ptr[0] = PACKET3(PACKET3_SET_CONFIG_REG, 1); + ib->ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); + ib->ptr[2] = 0xDEADBEEF; +- ib->ptr[3] = PACKET2(0); +- ib->ptr[4] = PACKET2(0); +- ib->ptr[5] = PACKET2(0); +- ib->ptr[6] = PACKET2(0); +- ib->ptr[7] = PACKET2(0); +- ib->ptr[8] = PACKET2(0); +- ib->ptr[9] = PACKET2(0); +- ib->ptr[10] = PACKET2(0); +- ib->ptr[11] = PACKET2(0); +- ib->ptr[12] = PACKET2(0); +- ib->ptr[13] = PACKET2(0); +- ib->ptr[14] = PACKET2(0); +- ib->ptr[15] = PACKET2(0); +- ib->length_dw = 16; ++ ib->length_dw = 3; + r = radeon_ib_schedule(rdev, ib); + if (r) { + radeon_scratch_free(rdev, scratch); +@@ -2734,7 +2746,7 @@ int r600_ib_test(struct radeon_device *rdev) + DRM_UDELAY(1); + } + if (i < rdev->usec_timeout) { +- DRM_INFO("ib test succeeded in %u usecs\n", i); ++ DRM_INFO("ib test on ring %d succeeded in %u usecs\n", ib->fence->ring, i); + } else { + DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n", + scratch, tmp); +@@ -2768,7 +2780,7 @@ void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size) + rdev->ih.rptr = 0; + } + +-static int r600_ih_ring_alloc(struct radeon_device *rdev) ++int r600_ih_ring_alloc(struct radeon_device *rdev) + { + int r; + +@@ -2804,7 +2816,7 @@ static int r600_ih_ring_alloc(struct radeon_device *rdev) + return 0; + } + +-static void r600_ih_ring_fini(struct radeon_device *rdev) ++void r600_ih_ring_fini(struct radeon_device *rdev) + { + int r; + if (rdev->ih.ring_obj) { +@@ -2828,7 +2840,7 @@ void r600_rlc_stop(struct radeon_device *rdev) + /* r7xx asics need to soft reset RLC before halting */ + WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC); + RREG32(SRBM_SOFT_RESET); +- udelay(15000); ++ mdelay(15); + WREG32(SRBM_SOFT_RESET, 0); + RREG32(SRBM_SOFT_RESET); + } +@@ -2851,10 +2863,17 @@ static int r600_rlc_init(struct radeon_device *rdev) + + r600_rlc_stop(rdev); + +- WREG32(RLC_HB_BASE, 0); + WREG32(RLC_HB_CNTL, 0); +- WREG32(RLC_HB_RPTR, 0); +- WREG32(RLC_HB_WPTR, 0); ++ ++ if (rdev->family == CHIP_ARUBA) { ++ WREG32(TN_RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); ++ WREG32(TN_RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); ++ } ++ if (rdev->family <= CHIP_CAYMAN) { ++ WREG32(RLC_HB_BASE, 0); ++ WREG32(RLC_HB_RPTR, 0); ++ WREG32(RLC_HB_WPTR, 0); ++ } + if (rdev->family <= CHIP_CAICOS) { + WREG32(RLC_HB_WPTR_LSB_ADDR, 0); + WREG32(RLC_HB_WPTR_MSB_ADDR, 0); +@@ -2863,7 +2882,12 @@ static int r600_rlc_init(struct radeon_device *rdev) + WREG32(RLC_UCODE_CNTL, 0); + + fw_data = (const __be32 *)rdev->rlc_fw->data; +- if (rdev->family >= CHIP_CAYMAN) { ++ if (rdev->family >= CHIP_ARUBA) { ++ for (i = 0; i < ARUBA_RLC_UCODE_SIZE; i++) { ++ WREG32(RLC_UCODE_ADDR, i); ++ WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); ++ } ++ } else if (rdev->family >= CHIP_CAYMAN) { + for (i = 0; i < CAYMAN_RLC_UCODE_SIZE; i++) { + WREG32(RLC_UCODE_ADDR, i); + WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); +@@ -3081,7 +3105,7 @@ int r600_irq_set(struct radeon_device *rdev) + hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN; + } + +- if (rdev->irq.sw_int) { ++ if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { + DRM_DEBUG("r600_irq_set: sw int\n"); + cp_int_cntl |= RB_INT_ENABLE; + cp_int_cntl |= TIME_STAMP_INT_ENABLE; +@@ -3283,7 +3307,6 @@ static u32 r600_get_ih_wptr(struct radeon_device *rdev) + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); +- wptr &= ~RB_OVERFLOW; + } + return (wptr & rdev->ih.ptr_mask); + } +@@ -3469,11 +3492,11 @@ restart_ih: + case 177: /* CP_INT in IB1 */ + case 178: /* CP_INT in IB2 */ + DRM_DEBUG("IH: CP int: 0x%08x\n", src_data); +- radeon_fence_process(rdev); ++ radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; + case 181: /* CP EOP event */ + DRM_DEBUG("IH: CP EOP\n"); +- radeon_fence_process(rdev); ++ radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; + case 233: /* GUI IDLE */ + DRM_DEBUG("IH: GUI idle\n"); +@@ -3506,30 +3529,6 @@ restart_ih: + */ + #if defined(CONFIG_DEBUG_FS) + +-static int r600_debugfs_cp_ring_info(struct seq_file *m, void *data) +-{ +- struct drm_info_node *node = (struct drm_info_node *) m->private; +- struct drm_device *dev = node->minor->dev; +- struct radeon_device *rdev = dev->dev_private; +- unsigned count, i, j; +- +- radeon_ring_free_size(rdev); +- count = (rdev->cp.ring_size / 4) - rdev->cp.ring_free_dw; +- seq_printf(m, "CP_STAT 0x%08x\n", RREG32(CP_STAT)); +- seq_printf(m, "CP_RB_WPTR 0x%08x\n", RREG32(CP_RB_WPTR)); +- seq_printf(m, "CP_RB_RPTR 0x%08x\n", RREG32(CP_RB_RPTR)); +- seq_printf(m, "driver's copy of the CP_RB_WPTR 0x%08x\n", rdev->cp.wptr); +- seq_printf(m, "driver's copy of the CP_RB_RPTR 0x%08x\n", rdev->cp.rptr); +- seq_printf(m, "%u free dwords in ring\n", rdev->cp.ring_free_dw); +- seq_printf(m, "%u dwords in ring\n", count); +- i = rdev->cp.rptr; +- for (j = 0; j <= count; j++) { +- seq_printf(m, "r[%04d]=0x%08x\n", i, rdev->cp.ring[i]); +- i = (i + 1) & rdev->cp.ptr_mask; +- } +- return 0; +-} +- + static int r600_debugfs_mc_info(struct seq_file *m, void *data) + { + struct drm_info_node *node = (struct drm_info_node *) m->private; +@@ -3543,7 +3542,6 @@ static int r600_debugfs_mc_info(struct seq_file *m, void *data) + + static struct drm_info_list r600_mc_info_list[] = { + {"r600_mc_info", r600_debugfs_mc_info, 0, NULL}, +- {"r600_ring_info", r600_debugfs_cp_ring_info, 0, NULL}, + }; + #endif + +diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c +index 846fae5..24e3939 100644 +--- a/drivers/gpu/drm/radeon/r600_audio.c ++++ b/drivers/gpu/drm/radeon/r600_audio.c +@@ -36,7 +36,7 @@ + */ + static int r600_audio_chipset_supported(struct radeon_device *rdev) + { +- return (rdev->family >= CHIP_R600 && rdev->family < CHIP_CEDAR) ++ return (rdev->family >= CHIP_R600 && !ASIC_IS_DCE5(rdev)) + || rdev->family == CHIP_RS600 + || rdev->family == CHIP_RS690 + || rdev->family == CHIP_RS740; +@@ -161,8 +161,18 @@ static void r600_audio_update_hdmi(unsigned long param) + */ + static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) + { ++ u32 value = 0; + DRM_INFO("%s audio support\n", enable ? "Enabling" : "Disabling"); +- WREG32_P(R600_AUDIO_ENABLE, enable ? 0x81000000 : 0x0, ~0x81000000); ++ if (ASIC_IS_DCE4(rdev)) { ++ if (enable) { ++ value |= 0x81000000; /* Required to enable audio */ ++ value |= 0x0e1000f0; /* fglrx sets that too */ ++ } ++ WREG32(EVERGREEN_AUDIO_ENABLE, value); ++ } else { ++ WREG32_P(R600_AUDIO_ENABLE, ++ enable ? 0x81000000 : 0x0, ~0x81000000); ++ } + rdev->audio_enabled = enable; + } + +@@ -229,6 +239,7 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; ++ struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + int base_rate = 48000; + + switch (radeon_encoder->encoder_id) { +@@ -248,22 +259,33 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) + return; + } + +- switch (dig->dig_encoder) { +- case 0: +- WREG32(R600_AUDIO_PLL1_MUL, base_rate * 50); +- WREG32(R600_AUDIO_PLL1_DIV, clock * 100); +- WREG32(R600_AUDIO_CLK_SRCSEL, 0); +- break; +- +- case 1: +- WREG32(R600_AUDIO_PLL2_MUL, base_rate * 50); +- WREG32(R600_AUDIO_PLL2_DIV, clock * 100); +- WREG32(R600_AUDIO_CLK_SRCSEL, 1); +- break; +- default: +- dev_err(rdev->dev, "Unsupported DIG on encoder 0x%02X\n", +- radeon_encoder->encoder_id); +- return; ++ if (ASIC_IS_DCE4(rdev)) { ++ /* TODO: other PLLs? */ ++ WREG32(EVERGREEN_AUDIO_PLL1_MUL, base_rate * 10); ++ WREG32(EVERGREEN_AUDIO_PLL1_DIV, clock * 10); ++ WREG32(EVERGREEN_AUDIO_PLL1_UNK, 0x00000071); ++ ++ /* Select DTO source */ ++ WREG32(0x5ac, radeon_crtc->crtc_id); ++ } else { ++ switch (dig->dig_encoder) { ++ case 0: ++ WREG32(R600_AUDIO_PLL1_MUL, base_rate * 50); ++ WREG32(R600_AUDIO_PLL1_DIV, clock * 100); ++ WREG32(R600_AUDIO_CLK_SRCSEL, 0); ++ break; ++ ++ case 1: ++ WREG32(R600_AUDIO_PLL2_MUL, base_rate * 50); ++ WREG32(R600_AUDIO_PLL2_DIV, clock * 100); ++ WREG32(R600_AUDIO_CLK_SRCSEL, 1); ++ break; ++ default: ++ dev_err(rdev->dev, ++ "Unsupported DIG on encoder 0x%02X\n", ++ radeon_encoder->encoder_id); ++ return; ++ } + } + } + +diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c +index e09d281..db38f58 100644 +--- a/drivers/gpu/drm/radeon/r600_blit_kms.c ++++ b/drivers/gpu/drm/radeon/r600_blit_kms.c +@@ -30,26 +30,14 @@ + + #include "r600d.h" + #include "r600_blit_shaders.h" +- +-#define DI_PT_RECTLIST 0x11 +-#define DI_INDEX_SIZE_16_BIT 0x0 +-#define DI_SRC_SEL_AUTO_INDEX 0x2 +- +-#define FMT_8 0x1 +-#define FMT_5_6_5 0x8 +-#define FMT_8_8_8_8 0x1a +-#define COLOR_8 0x1 +-#define COLOR_5_6_5 0x8 +-#define COLOR_8_8_8_8 0x1a +- +-#define RECT_UNIT_H 32 +-#define RECT_UNIT_W (RADEON_GPU_PAGE_SIZE / 4 / RECT_UNIT_H) ++#include "radeon_blit_common.h" + + /* emits 21 on rv770+, 23 on r600 */ + static void + set_render_target(struct radeon_device *rdev, int format, + int w, int h, u64 gpu_addr) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 cb_color_info; + int pitch, slice; + +@@ -63,38 +51,38 @@ set_render_target(struct radeon_device *rdev, int format, + pitch = (w / 8) - 1; + slice = ((w * h) / 64) - 1; + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (CB_COLOR0_BASE - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, gpu_addr >> 8); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (CB_COLOR0_BASE - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, gpu_addr >> 8); + + if (rdev->family > CHIP_R600 && rdev->family < CHIP_RV770) { +- radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_BASE_UPDATE, 0)); +- radeon_ring_write(rdev, 2 << 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_BASE_UPDATE, 0)); ++ radeon_ring_write(ring, 2 << 0); + } + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (CB_COLOR0_SIZE - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, (pitch << 0) | (slice << 10)); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (CB_COLOR0_SIZE - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, (pitch << 0) | (slice << 10)); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (CB_COLOR0_VIEW - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (CB_COLOR0_VIEW - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, 0); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (CB_COLOR0_INFO - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, cb_color_info); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (CB_COLOR0_INFO - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, cb_color_info); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (CB_COLOR0_TILE - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (CB_COLOR0_TILE - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, 0); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (CB_COLOR0_FRAG - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (CB_COLOR0_FRAG - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, 0); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (CB_COLOR0_MASK - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (CB_COLOR0_MASK - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, 0); + } + + /* emits 5dw */ +@@ -103,6 +91,7 @@ cp_set_surface_sync(struct radeon_device *rdev, + u32 sync_type, u32 size, + u64 mc_addr) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 cp_coher_size; + + if (size == 0xffffffff) +@@ -110,17 +99,18 @@ cp_set_surface_sync(struct radeon_device *rdev, + else + cp_coher_size = ((size + 255) >> 8); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3)); +- radeon_ring_write(rdev, sync_type); +- radeon_ring_write(rdev, cp_coher_size); +- radeon_ring_write(rdev, mc_addr >> 8); +- radeon_ring_write(rdev, 10); /* poll interval */ ++ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); ++ radeon_ring_write(ring, sync_type); ++ radeon_ring_write(ring, cp_coher_size); ++ radeon_ring_write(ring, mc_addr >> 8); ++ radeon_ring_write(ring, 10); /* poll interval */ + } + + /* emits 21dw + 1 surface sync = 26dw */ + static void + set_shaders(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u64 gpu_addr; + u32 sq_pgm_resources; + +@@ -129,35 +119,35 @@ set_shaders(struct radeon_device *rdev) + + /* VS */ + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.vs_offset; +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (SQ_PGM_START_VS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, gpu_addr >> 8); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (SQ_PGM_START_VS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, gpu_addr >> 8); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (SQ_PGM_RESOURCES_VS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, sq_pgm_resources); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (SQ_PGM_RESOURCES_VS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, sq_pgm_resources); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (SQ_PGM_CF_OFFSET_VS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (SQ_PGM_CF_OFFSET_VS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, 0); + + /* PS */ + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.ps_offset; +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (SQ_PGM_START_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, gpu_addr >> 8); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (SQ_PGM_START_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, gpu_addr >> 8); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (SQ_PGM_RESOURCES_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, sq_pgm_resources | (1 << 28)); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (SQ_PGM_RESOURCES_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, sq_pgm_resources | (1 << 28)); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (SQ_PGM_EXPORTS_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, 2); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (SQ_PGM_EXPORTS_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, 2); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); +- radeon_ring_write(rdev, (SQ_PGM_CF_OFFSET_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 1)); ++ radeon_ring_write(ring, (SQ_PGM_CF_OFFSET_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, 0); + + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.vs_offset; + cp_set_surface_sync(rdev, PACKET3_SH_ACTION_ENA, 512, gpu_addr); +@@ -167,6 +157,7 @@ set_shaders(struct radeon_device *rdev) + static void + set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 sq_vtx_constant_word2; + + sq_vtx_constant_word2 = SQ_VTXC_BASE_ADDR_HI(upper_32_bits(gpu_addr) & 0xff) | +@@ -175,15 +166,15 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr) + sq_vtx_constant_word2 |= SQ_VTXC_ENDIAN_SWAP(SQ_ENDIAN_8IN32); + #endif + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7)); +- radeon_ring_write(rdev, 0x460); +- radeon_ring_write(rdev, gpu_addr & 0xffffffff); +- radeon_ring_write(rdev, 48 - 1); +- radeon_ring_write(rdev, sq_vtx_constant_word2); +- radeon_ring_write(rdev, 1 << 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, SQ_TEX_VTX_VALID_BUFFER << 30); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_RESOURCE, 7)); ++ radeon_ring_write(ring, 0x460); ++ radeon_ring_write(ring, gpu_addr & 0xffffffff); ++ radeon_ring_write(ring, 48 - 1); ++ radeon_ring_write(ring, sq_vtx_constant_word2); ++ radeon_ring_write(ring, 1 << 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, SQ_TEX_VTX_VALID_BUFFER << 30); + + if ((rdev->family == CHIP_RV610) || + (rdev->family == CHIP_RV620) || +@@ -203,6 +194,7 @@ set_tex_resource(struct radeon_device *rdev, + int format, int w, int h, int pitch, + u64 gpu_addr, u32 size) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4; + + if (h < 1) +@@ -225,15 +217,15 @@ set_tex_resource(struct radeon_device *rdev, + cp_set_surface_sync(rdev, + PACKET3_TC_ACTION_ENA, size, gpu_addr); + +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, sq_tex_resource_word0); +- radeon_ring_write(rdev, sq_tex_resource_word1); +- radeon_ring_write(rdev, gpu_addr >> 8); +- radeon_ring_write(rdev, gpu_addr >> 8); +- radeon_ring_write(rdev, sq_tex_resource_word4); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, SQ_TEX_VTX_VALID_TEXTURE << 30); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_RESOURCE, 7)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, sq_tex_resource_word0); ++ radeon_ring_write(ring, sq_tex_resource_word1); ++ radeon_ring_write(ring, gpu_addr >> 8); ++ radeon_ring_write(ring, gpu_addr >> 8); ++ radeon_ring_write(ring, sq_tex_resource_word4); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, SQ_TEX_VTX_VALID_TEXTURE << 30); + } + + /* emits 12 */ +@@ -241,43 +233,45 @@ static void + set_scissors(struct radeon_device *rdev, int x1, int y1, + int x2, int y2) + { +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); +- radeon_ring_write(rdev, (PA_SC_SCREEN_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, (x1 << 0) | (y1 << 16)); +- radeon_ring_write(rdev, (x2 << 0) | (y2 << 16)); +- +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); +- radeon_ring_write(rdev, (PA_SC_GENERIC_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, (x1 << 0) | (y1 << 16) | (1 << 31)); +- radeon_ring_write(rdev, (x2 << 0) | (y2 << 16)); +- +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); +- radeon_ring_write(rdev, (PA_SC_WINDOW_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, (x1 << 0) | (y1 << 16) | (1 << 31)); +- radeon_ring_write(rdev, (x2 << 0) | (y2 << 16)); ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); ++ radeon_ring_write(ring, (PA_SC_SCREEN_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, (x1 << 0) | (y1 << 16)); ++ radeon_ring_write(ring, (x2 << 0) | (y2 << 16)); ++ ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); ++ radeon_ring_write(ring, (PA_SC_GENERIC_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, (x1 << 0) | (y1 << 16) | (1 << 31)); ++ radeon_ring_write(ring, (x2 << 0) | (y2 << 16)); ++ ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); ++ radeon_ring_write(ring, (PA_SC_WINDOW_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, (x1 << 0) | (y1 << 16) | (1 << 31)); ++ radeon_ring_write(ring, (x2 << 0) | (y2 << 16)); + } + + /* emits 10 */ + static void + draw_auto(struct radeon_device *rdev) + { +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); +- radeon_ring_write(rdev, (VGT_PRIMITIVE_TYPE - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, DI_PT_RECTLIST); ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(ring, (VGT_PRIMITIVE_TYPE - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, DI_PT_RECTLIST); + +- radeon_ring_write(rdev, PACKET3(PACKET3_INDEX_TYPE, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET3(PACKET3_INDEX_TYPE, 0)); ++ radeon_ring_write(ring, + #ifdef __BIG_ENDIAN + (2 << 2) | + #endif + DI_INDEX_SIZE_16_BIT); + +- radeon_ring_write(rdev, PACKET3(PACKET3_NUM_INSTANCES, 0)); +- radeon_ring_write(rdev, 1); ++ radeon_ring_write(ring, PACKET3(PACKET3_NUM_INSTANCES, 0)); ++ radeon_ring_write(ring, 1); + +- radeon_ring_write(rdev, PACKET3(PACKET3_DRAW_INDEX_AUTO, 1)); +- radeon_ring_write(rdev, 3); +- radeon_ring_write(rdev, DI_SRC_SEL_AUTO_INDEX); ++ radeon_ring_write(ring, PACKET3(PACKET3_DRAW_INDEX_AUTO, 1)); ++ radeon_ring_write(ring, 3); ++ radeon_ring_write(ring, DI_SRC_SEL_AUTO_INDEX); + + } + +@@ -285,6 +279,7 @@ draw_auto(struct radeon_device *rdev) + static void + set_default_state(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + u32 sq_config, sq_gpr_resource_mgmt_1, sq_gpr_resource_mgmt_2; + u32 sq_thread_resource_mgmt, sq_stack_resource_mgmt_1, sq_stack_resource_mgmt_2; + int num_ps_gprs, num_vs_gprs, num_temp_gprs, num_gs_gprs, num_es_gprs; +@@ -440,47 +435,62 @@ set_default_state(struct radeon_device *rdev) + /* emit an IB pointing at default state */ + dwords = ALIGN(rdev->r600_blit.state_len, 0x10); + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset; +- radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); ++ radeon_ring_write(ring, + #ifdef __BIG_ENDIAN + (2 << 0) | + #endif + (gpu_addr & 0xFFFFFFFC)); +- radeon_ring_write(rdev, upper_32_bits(gpu_addr) & 0xFF); +- radeon_ring_write(rdev, dwords); ++ radeon_ring_write(ring, upper_32_bits(gpu_addr) & 0xFF); ++ radeon_ring_write(ring, dwords); + + /* SQ config */ +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 6)); +- radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); +- radeon_ring_write(rdev, sq_config); +- radeon_ring_write(rdev, sq_gpr_resource_mgmt_1); +- radeon_ring_write(rdev, sq_gpr_resource_mgmt_2); +- radeon_ring_write(rdev, sq_thread_resource_mgmt); +- radeon_ring_write(rdev, sq_stack_resource_mgmt_1); +- radeon_ring_write(rdev, sq_stack_resource_mgmt_2); ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 6)); ++ radeon_ring_write(ring, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); ++ radeon_ring_write(ring, sq_config); ++ radeon_ring_write(ring, sq_gpr_resource_mgmt_1); ++ radeon_ring_write(ring, sq_gpr_resource_mgmt_2); ++ radeon_ring_write(ring, sq_thread_resource_mgmt); ++ radeon_ring_write(ring, sq_stack_resource_mgmt_1); ++ radeon_ring_write(ring, sq_stack_resource_mgmt_2); + } + ++#define I2F_MAX_BITS 15 ++#define I2F_MAX_INPUT ((1 << I2F_MAX_BITS) - 1) ++#define I2F_SHIFT (24 - I2F_MAX_BITS) ++ ++/* ++ * Converts unsigned integer into 32-bit IEEE floating point representation. ++ * Conversion is not universal and only works for the range from 0 ++ * to 2^I2F_MAX_BITS-1. Currently we only use it with inputs between ++ * 0 and 16384 (inclusive), so I2F_MAX_BITS=15 is enough. If necessary, ++ * I2F_MAX_BITS can be increased, but that will add to the loop iterations ++ * and slow us down. Conversion is done by shifting the input and counting ++ * down until the first 1 reaches bit position 23. The resulting counter ++ * and the shifted input are, respectively, the exponent and the fraction. ++ * The sign is always zero. ++ */ + static uint32_t i2f(uint32_t input) + { + u32 result, i, exponent, fraction; + +- if ((input & 0x3fff) == 0) +- result = 0; /* 0 is a special case */ ++ WARN_ON_ONCE(input > I2F_MAX_INPUT); ++ ++ if ((input & I2F_MAX_INPUT) == 0) ++ result = 0; + else { +- exponent = 140; /* exponent biased by 127; */ +- fraction = (input & 0x3fff) << 10; /* cheat and only +- handle numbers below 2^^15 */ +- for (i = 0; i < 14; i++) { ++ exponent = 126 + I2F_MAX_BITS; ++ fraction = (input & I2F_MAX_INPUT) << I2F_SHIFT; ++ ++ for (i = 0; i < I2F_MAX_BITS; i++) { + if (fraction & 0x800000) + break; + else { +- fraction = fraction << 1; /* keep +- shifting left until top bit = 1 */ ++ fraction = fraction << 1; + exponent = exponent - 1; + } + } +- result = exponent << 23 | (fraction & 0x7fffff); /* mask +- off top bit; assumed 1 */ ++ result = exponent << 23 | (fraction & 0x7fffff); + } + return result; + } +@@ -611,16 +621,17 @@ void r600_blit_fini(struct radeon_device *rdev) + radeon_bo_unref(&rdev->r600_blit.shader_obj); + } + +-static int r600_vb_ib_get(struct radeon_device *rdev) ++static int r600_vb_ib_get(struct radeon_device *rdev, unsigned size) + { + int r; +- r = radeon_ib_get(rdev, &rdev->r600_blit.vb_ib); ++ r = radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX, ++ &rdev->r600_blit.vb_ib, size); + if (r) { + DRM_ERROR("failed to get IB for vertex buffer\n"); + return r; + } + +- rdev->r600_blit.vb_total = 64*1024; ++ rdev->r600_blit.vb_total = size; + rdev->r600_blit.vb_used = 0; + return 0; + } +@@ -679,15 +690,12 @@ static unsigned r600_blit_create_rect(unsigned num_gpu_pages, + + int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + int ring_size; + int num_loops = 0; + int dwords_per_loop = rdev->r600_blit.ring_size_per_loop; + +- r = r600_vb_ib_get(rdev); +- if (r) +- return r; +- + /* num loops */ + while (num_gpu_pages) { + num_gpu_pages -= +@@ -696,10 +704,15 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages) + num_loops++; + } + ++ /* 48 bytes for vertex per loop */ ++ r = r600_vb_ib_get(rdev, (num_loops*48)+256); ++ if (r) ++ return r; ++ + /* calculate number of loops correctly */ + ring_size = num_loops * dwords_per_loop; + ring_size += rdev->r600_blit.ring_size_common; +- r = radeon_ring_lock(rdev, ring_size); ++ r = radeon_ring_lock(rdev, ring, ring_size); + if (r) + return r; + +@@ -718,7 +731,7 @@ void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence) + if (fence) + r = radeon_fence_emit(rdev, fence); + +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_unlock_commit(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + } + + void r600_kms_blit_copy(struct radeon_device *rdev, +diff --git a/drivers/gpu/drm/radeon/r600_blit_shaders.c b/drivers/gpu/drm/radeon/r600_blit_shaders.c +index 73e2c7c..34c8b23 100644 +--- a/drivers/gpu/drm/radeon/r600_blit_shaders.c ++++ b/drivers/gpu/drm/radeon/r600_blit_shaders.c +@@ -24,6 +24,7 @@ + * Alex Deucher + */ + ++#include + #include + #include + +diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c +index c9db493..683eb19 100644 +--- a/drivers/gpu/drm/radeon/r600_cp.c ++++ b/drivers/gpu/drm/radeon/r600_cp.c +@@ -375,10 +375,6 @@ out: + platform_device_unregister(pdev); + + if (err) { +- if (err != -EINVAL) +- printk(KERN_ERR +- "r600_cp: Failed to load firmware \"%s\"\n", +- fw_name); + release_firmware(dev_priv->pfp_fw); + dev_priv->pfp_fw = NULL; + release_firmware(dev_priv->me_fw); +@@ -407,7 +403,7 @@ static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv) + + RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP); + RADEON_READ(R600_GRBM_SOFT_RESET); +- DRM_UDELAY(15000); ++ mdelay(15); + RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); + + fw_data = (const __be32 *)dev_priv->me_fw->data; +@@ -500,7 +496,7 @@ static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv) + + RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP); + RADEON_READ(R600_GRBM_SOFT_RESET); +- DRM_UDELAY(15000); ++ mdelay(15); + RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); + + fw_data = (const __be32 *)dev_priv->pfp_fw->data; +@@ -1797,7 +1793,7 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev, + + RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP); + RADEON_READ(R600_GRBM_SOFT_RESET); +- DRM_UDELAY(15000); ++ mdelay(15); + RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); + + +@@ -1815,7 +1811,7 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev, + dev_priv->ring.size_l2qw); + #endif + +- RADEON_WRITE(R600_CP_SEM_WAIT_TIMER, 0x4); ++ RADEON_WRITE(R600_CP_SEM_WAIT_TIMER, 0x0); + + /* Set the write pointer delay */ + RADEON_WRITE(R600_CP_RB_WPTR_DELAY, 0); +diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c +index cb1acff..3cd9b0e 100644 +--- a/drivers/gpu/drm/radeon/r600_cs.c ++++ b/drivers/gpu/drm/radeon/r600_cs.c +@@ -52,15 +52,20 @@ struct r600_cs_track { + struct radeon_bo *cb_color_bo[8]; + u64 cb_color_bo_mc[8]; + u32 cb_color_bo_offset[8]; +- struct radeon_bo *cb_color_frag_bo[8]; +- struct radeon_bo *cb_color_tile_bo[8]; ++ struct radeon_bo *cb_color_frag_bo[8]; /* unused */ ++ struct radeon_bo *cb_color_tile_bo[8]; /* unused */ + u32 cb_color_info[8]; +- u32 cb_color_size_idx[8]; ++ u32 cb_color_view[8]; ++ u32 cb_color_size_idx[8]; /* unused */ + u32 cb_target_mask; +- u32 cb_shader_mask; ++ u32 cb_shader_mask; /* unused */ + u32 cb_color_size[8]; + u32 vgt_strmout_en; + u32 vgt_strmout_buffer_en; ++ struct radeon_bo *vgt_strmout_bo[4]; ++ u64 vgt_strmout_bo_mc[4]; /* unused */ ++ u32 vgt_strmout_bo_offset[4]; ++ u32 vgt_strmout_size[4]; + u32 db_depth_control; + u32 db_depth_info; + u32 db_depth_size_idx; +@@ -69,13 +74,20 @@ struct r600_cs_track { + u32 db_offset; + struct radeon_bo *db_bo; + u64 db_bo_mc; ++ bool sx_misc_kill_all_prims; ++ bool cb_dirty; ++ bool db_dirty; ++ bool streamout_dirty; ++ struct radeon_bo *htile_bo; ++ u64 htile_offset; ++ u32 htile_surface; + }; + + #define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc, CHIP_R600 } + #define FMT_16_BIT(fmt, vc) [fmt] = { 1, 1, 2, vc, CHIP_R600 } +-#define FMT_24_BIT(fmt) [fmt] = { 1, 1, 3, 0, CHIP_R600 } ++#define FMT_24_BIT(fmt) [fmt] = { 1, 1, 4, 0, CHIP_R600 } + #define FMT_32_BIT(fmt, vc) [fmt] = { 1, 1, 4, vc, CHIP_R600 } +-#define FMT_48_BIT(fmt) [fmt] = { 1, 1, 6, 0, CHIP_R600 } ++#define FMT_48_BIT(fmt) [fmt] = { 1, 1, 8, 0, CHIP_R600 } + #define FMT_64_BIT(fmt, vc) [fmt] = { 1, 1, 8, vc, CHIP_R600 } + #define FMT_96_BIT(fmt) [fmt] = { 1, 1, 12, 0, CHIP_R600 } + #define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16,vc, CHIP_R600 } +@@ -107,7 +119,7 @@ static const struct gpu_formats color_formats_table[] = { + + /* 24-bit */ + FMT_24_BIT(V_038004_FMT_8_8_8), +- ++ + /* 32-bit */ + FMT_32_BIT(V_038004_COLOR_32, 1), + FMT_32_BIT(V_038004_COLOR_32_FLOAT, 1), +@@ -162,22 +174,22 @@ static const struct gpu_formats color_formats_table[] = { + [V_038004_FMT_32_AS_32_32_32_32] = { 1, 1, 4, 0, CHIP_CEDAR}, + }; + +-static bool fmt_is_valid_color(u32 format) ++bool r600_fmt_is_valid_color(u32 format) + { + if (format >= ARRAY_SIZE(color_formats_table)) + return false; +- ++ + if (color_formats_table[format].valid_color) + return true; + + return false; + } + +-static bool fmt_is_valid_texture(u32 format, enum radeon_family family) ++bool r600_fmt_is_valid_texture(u32 format, enum radeon_family family) + { + if (format >= ARRAY_SIZE(color_formats_table)) + return false; +- ++ + if (family < color_formats_table[format].min_family) + return false; + +@@ -187,7 +199,7 @@ static bool fmt_is_valid_texture(u32 format, enum radeon_family family) + return false; + } + +-static int fmt_get_blocksize(u32 format) ++int r600_fmt_get_blocksize(u32 format) + { + if (format >= ARRAY_SIZE(color_formats_table)) + return 0; +@@ -195,7 +207,7 @@ static int fmt_get_blocksize(u32 format) + return color_formats_table[format].blocksize; + } + +-static int fmt_get_nblocksx(u32 format, u32 w) ++int r600_fmt_get_nblocksx(u32 format, u32 w) + { + unsigned bw; + +@@ -209,7 +221,7 @@ static int fmt_get_nblocksx(u32 format, u32 w) + return (w + bw - 1) / bw; + } + +-static int fmt_get_nblocksy(u32 format, u32 h) ++int r600_fmt_get_nblocksy(u32 format, u32 h) + { + unsigned bh; + +@@ -256,7 +268,7 @@ static int r600_get_array_mode_alignment(struct array_mode_checker *values, + break; + case ARRAY_LINEAR_ALIGNED: + *pitch_align = max((u32)64, (u32)(values->group_size / values->blocksize)); +- *height_align = tile_height; ++ *height_align = 1; + *depth_align = 1; + *base_align = values->group_size; + break; +@@ -269,10 +281,9 @@ static int r600_get_array_mode_alignment(struct array_mode_checker *values, + *base_align = values->group_size; + break; + case ARRAY_2D_TILED_THIN1: +- *pitch_align = max((u32)macro_tile_width, +- (u32)(((values->group_size / tile_height) / +- (values->blocksize * values->nsamples)) * +- values->nbanks)) * tile_width; ++ *pitch_align = max((u32)macro_tile_width * tile_width, ++ (u32)((values->group_size * values->nbanks) / ++ (values->blocksize * values->nsamples * tile_width))); + *height_align = macro_tile_height * tile_height; + *depth_align = 1; + *base_align = max(macro_tile_bytes, +@@ -296,12 +307,14 @@ static void r600_cs_track_init(struct r600_cs_track *track) + track->cb_color_size[i] = 0; + track->cb_color_size_idx[i] = 0; + track->cb_color_info[i] = 0; ++ track->cb_color_view[i] = 0xFFFFFFFF; + track->cb_color_bo[i] = NULL; + track->cb_color_bo_offset[i] = 0xFFFFFFFF; + track->cb_color_bo_mc[i] = 0xFFFFFFFF; + } + track->cb_target_mask = 0xFFFFFFFF; + track->cb_shader_mask = 0xFFFFFFFF; ++ track->cb_dirty = true; + track->db_bo = NULL; + track->db_bo_mc = 0xFFFFFFFF; + /* assume the biggest format and that htile is enabled */ +@@ -310,6 +323,19 @@ static void r600_cs_track_init(struct r600_cs_track *track) + track->db_depth_size = 0xFFFFFFFF; + track->db_depth_size_idx = 0; + track->db_depth_control = 0xFFFFFFFF; ++ track->db_dirty = true; ++ track->htile_bo = NULL; ++ track->htile_offset = 0xFFFFFFFF; ++ track->htile_surface = 0; ++ ++ for (i = 0; i < 4; i++) { ++ track->vgt_strmout_size[i] = 0; ++ track->vgt_strmout_bo[i] = NULL; ++ track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; ++ track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; ++ } ++ track->streamout_dirty = true; ++ track->sx_misc_kill_all_prims = false; + } + + static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) +@@ -322,13 +348,14 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) + volatile u32 *ib = p->ib->ptr; + unsigned array_mode; + u32 format; ++ + if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { + dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); + return -EINVAL; + } + size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; + format = G_0280A0_FORMAT(track->cb_color_info[i]); +- if (!fmt_is_valid_color(format)) { ++ if (!r600_fmt_is_valid_color(format)) { + dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n", + __func__, __LINE__, format, + i, track->cb_color_info[i]); +@@ -349,7 +376,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) + array_check.nbanks = track->nbanks; + array_check.npipes = track->npipes; + array_check.nsamples = track->nsamples; +- array_check.blocksize = fmt_get_blocksize(format); ++ array_check.blocksize = r600_fmt_get_blocksize(format); + if (r600_get_array_mode_alignment(&array_check, + &pitch_align, &height_align, &depth_align, &base_align)) { + dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__, +@@ -393,7 +420,18 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) + } + + /* check offset */ +- tmp = fmt_get_nblocksy(format, height) * fmt_get_nblocksx(format, pitch) * fmt_get_blocksize(format); ++ tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * r600_fmt_get_blocksize(format); ++ switch (array_mode) { ++ default: ++ case V_0280A0_ARRAY_LINEAR_GENERAL: ++ case V_0280A0_ARRAY_LINEAR_ALIGNED: ++ tmp += track->cb_color_view[i] & 0xFF; ++ break; ++ case V_0280A0_ARRAY_1D_TILED_THIN1: ++ case V_0280A0_ARRAY_2D_TILED_THIN1: ++ tmp += G_028080_SLICE_MAX(track->cb_color_view[i]) * tmp; ++ break; ++ } + if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { + if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) { + /* the initial DDX does bad things with the CB size occasionally */ +@@ -403,10 +441,13 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) + * broken userspace. + */ + } else { +- dev_warn(p->dev, "%s offset[%d] %d %d %d %lu too big\n", __func__, i, +- array_mode, ++ dev_warn(p->dev, "%s offset[%d] %d %d %d %lu too big (%d %d) (%d %d %d)\n", ++ __func__, i, array_mode, + track->cb_color_bo_offset[i], tmp, +- radeon_bo_size(track->cb_color_bo[i])); ++ radeon_bo_size(track->cb_color_bo[i]), ++ pitch, height, r600_fmt_get_nblocksx(format, pitch), ++ r600_fmt_get_nblocksy(format, height), ++ r600_fmt_get_blocksize(format)); + return -EINVAL; + } + } +@@ -420,154 +461,319 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) + return 0; + } + +-static int r600_cs_track_check(struct radeon_cs_parser *p) ++static int r600_cs_track_validate_db(struct radeon_cs_parser *p) + { + struct r600_cs_track *track = p->track; +- u32 tmp; +- int r, i; ++ u32 nviews, bpe, ntiles, size, slice_tile_max, tmp; ++ u32 height_align, pitch_align, depth_align; ++ u32 pitch = 8192; ++ u32 height = 8192; ++ u64 base_offset, base_align; ++ struct array_mode_checker array_check; ++ int array_mode; + volatile u32 *ib = p->ib->ptr; + +- /* on legacy kernel we don't perform advanced check */ +- if (p->rdev == NULL) +- return 0; +- /* we don't support out buffer yet */ +- if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) { +- dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); ++ ++ if (track->db_bo == NULL) { ++ dev_warn(p->dev, "z/stencil with no depth buffer\n"); + return -EINVAL; + } +- /* check that we have a cb for each enabled target, we don't check +- * shader_mask because it seems mesa isn't always setting it :( +- */ +- tmp = track->cb_target_mask; +- for (i = 0; i < 8; i++) { +- if ((tmp >> (i * 4)) & 0xF) { +- /* at least one component is enabled */ +- if (track->cb_color_bo[i] == NULL) { +- dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n", +- __func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i); +- return -EINVAL; +- } +- /* perform rewrite of CB_COLOR[0-7]_SIZE */ +- r = r600_cs_track_validate_cb(p, i); +- if (r) +- return r; +- } ++ switch (G_028010_FORMAT(track->db_depth_info)) { ++ case V_028010_DEPTH_16: ++ bpe = 2; ++ break; ++ case V_028010_DEPTH_X8_24: ++ case V_028010_DEPTH_8_24: ++ case V_028010_DEPTH_X8_24_FLOAT: ++ case V_028010_DEPTH_8_24_FLOAT: ++ case V_028010_DEPTH_32_FLOAT: ++ bpe = 4; ++ break; ++ case V_028010_DEPTH_X24_8_32_FLOAT: ++ bpe = 8; ++ break; ++ default: ++ dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info)); ++ return -EINVAL; + } +- /* Check depth buffer */ +- if (G_028800_STENCIL_ENABLE(track->db_depth_control) || +- G_028800_Z_ENABLE(track->db_depth_control)) { +- u32 nviews, bpe, ntiles, size, slice_tile_max; +- u32 height, height_align, pitch, pitch_align, depth_align; +- u64 base_offset, base_align; +- struct array_mode_checker array_check; +- int array_mode; +- +- if (track->db_bo == NULL) { +- dev_warn(p->dev, "z/stencil with no depth buffer\n"); ++ if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) { ++ if (!track->db_depth_size_idx) { ++ dev_warn(p->dev, "z/stencil buffer size not set\n"); + return -EINVAL; + } +- if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) { +- dev_warn(p->dev, "this kernel doesn't support z/stencil htile\n"); ++ tmp = radeon_bo_size(track->db_bo) - track->db_offset; ++ tmp = (tmp / bpe) >> 6; ++ if (!tmp) { ++ dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n", ++ track->db_depth_size, bpe, track->db_offset, ++ radeon_bo_size(track->db_bo)); + return -EINVAL; + } +- switch (G_028010_FORMAT(track->db_depth_info)) { +- case V_028010_DEPTH_16: +- bpe = 2; +- break; +- case V_028010_DEPTH_X8_24: +- case V_028010_DEPTH_8_24: +- case V_028010_DEPTH_X8_24_FLOAT: +- case V_028010_DEPTH_8_24_FLOAT: +- case V_028010_DEPTH_32_FLOAT: +- bpe = 4; ++ ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF); ++ } else { ++ size = radeon_bo_size(track->db_bo); ++ /* pitch in pixels */ ++ pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8; ++ slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; ++ slice_tile_max *= 64; ++ height = slice_tile_max / pitch; ++ if (height > 8192) ++ height = 8192; ++ base_offset = track->db_bo_mc + track->db_offset; ++ array_mode = G_028010_ARRAY_MODE(track->db_depth_info); ++ array_check.array_mode = array_mode; ++ array_check.group_size = track->group_size; ++ array_check.nbanks = track->nbanks; ++ array_check.npipes = track->npipes; ++ array_check.nsamples = track->nsamples; ++ array_check.blocksize = bpe; ++ if (r600_get_array_mode_alignment(&array_check, ++ &pitch_align, &height_align, &depth_align, &base_align)) { ++ dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, ++ G_028010_ARRAY_MODE(track->db_depth_info), ++ track->db_depth_info); ++ return -EINVAL; ++ } ++ switch (array_mode) { ++ case V_028010_ARRAY_1D_TILED_THIN1: ++ /* don't break userspace */ ++ height &= ~0x7; + break; +- case V_028010_DEPTH_X24_8_32_FLOAT: +- bpe = 8; ++ case V_028010_ARRAY_2D_TILED_THIN1: + break; + default: +- dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info)); ++ dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, ++ G_028010_ARRAY_MODE(track->db_depth_info), ++ track->db_depth_info); ++ return -EINVAL; ++ } ++ ++ if (!IS_ALIGNED(pitch, pitch_align)) { ++ dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n", ++ __func__, __LINE__, pitch, pitch_align, array_mode); ++ return -EINVAL; ++ } ++ if (!IS_ALIGNED(height, height_align)) { ++ dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n", ++ __func__, __LINE__, height, height_align, array_mode); ++ return -EINVAL; ++ } ++ if (!IS_ALIGNED(base_offset, base_align)) { ++ dev_warn(p->dev, "%s offset 0x%llx, 0x%llx, %d not aligned\n", __func__, ++ base_offset, base_align, array_mode); ++ return -EINVAL; ++ } ++ ++ ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; ++ nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1; ++ tmp = ntiles * bpe * 64 * nviews; ++ if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) { ++ dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n", ++ array_mode, ++ track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset, ++ radeon_bo_size(track->db_bo)); ++ return -EINVAL; ++ } ++ } ++ ++ /* hyperz */ ++ if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) { ++ unsigned long size; ++ unsigned nbx, nby; ++ ++ if (track->htile_bo == NULL) { ++ dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n", ++ __func__, __LINE__, track->db_depth_info); + return -EINVAL; + } + if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) { +- if (!track->db_depth_size_idx) { +- dev_warn(p->dev, "z/stencil buffer size not set\n"); +- return -EINVAL; +- } +- tmp = radeon_bo_size(track->db_bo) - track->db_offset; +- tmp = (tmp / bpe) >> 6; +- if (!tmp) { +- dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n", +- track->db_depth_size, bpe, track->db_offset, +- radeon_bo_size(track->db_bo)); +- return -EINVAL; +- } +- ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF); ++ dev_warn(p->dev, "%s:%d htile can't be enabled with bogus db_depth_size 0x%08x\n", ++ __func__, __LINE__, track->db_depth_size); ++ return -EINVAL; ++ } ++ ++ nbx = pitch; ++ nby = height; ++ if (G_028D24_LINEAR(track->htile_surface)) { ++ /* nbx must be 16 htiles aligned == 16 * 8 pixel aligned */ ++ nbx = round_up(nbx, 16 * 8); ++ /* nby is npipes htiles aligned == npipes * 8 pixel aligned */ ++ nby = round_up(nby, track->npipes * 8); + } else { +- size = radeon_bo_size(track->db_bo); +- /* pitch in pixels */ +- pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8; +- slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; +- slice_tile_max *= 64; +- height = slice_tile_max / pitch; +- if (height > 8192) +- height = 8192; +- base_offset = track->db_bo_mc + track->db_offset; +- array_mode = G_028010_ARRAY_MODE(track->db_depth_info); +- array_check.array_mode = array_mode; +- array_check.group_size = track->group_size; +- array_check.nbanks = track->nbanks; +- array_check.npipes = track->npipes; +- array_check.nsamples = track->nsamples; +- array_check.blocksize = bpe; +- if (r600_get_array_mode_alignment(&array_check, +- &pitch_align, &height_align, &depth_align, &base_align)) { +- dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, +- G_028010_ARRAY_MODE(track->db_depth_info), +- track->db_depth_info); +- return -EINVAL; +- } +- switch (array_mode) { +- case V_028010_ARRAY_1D_TILED_THIN1: +- /* don't break userspace */ +- height &= ~0x7; ++ /* htile widht & nby (8 or 4) make 2 bits number */ ++ tmp = track->htile_surface & 3; ++ /* align is htile align * 8, htile align vary according to ++ * number of pipe and tile width and nby ++ */ ++ switch (track->npipes) { ++ case 8: ++ switch (tmp) { ++ case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ ++ nbx = round_up(nbx, 64 * 8); ++ nby = round_up(nby, 64 * 8); ++ break; ++ case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/ ++ case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/ ++ nbx = round_up(nbx, 64 * 8); ++ nby = round_up(nby, 32 * 8); ++ break; ++ case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/ ++ nbx = round_up(nbx, 32 * 8); ++ nby = round_up(nby, 32 * 8); ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case 4: ++ switch (tmp) { ++ case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ ++ nbx = round_up(nbx, 64 * 8); ++ nby = round_up(nby, 32 * 8); ++ break; ++ case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/ ++ case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/ ++ nbx = round_up(nbx, 32 * 8); ++ nby = round_up(nby, 32 * 8); ++ break; ++ case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/ ++ nbx = round_up(nbx, 32 * 8); ++ nby = round_up(nby, 16 * 8); ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case 2: ++ switch (tmp) { ++ case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ ++ nbx = round_up(nbx, 32 * 8); ++ nby = round_up(nby, 32 * 8); ++ break; ++ case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/ ++ case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/ ++ nbx = round_up(nbx, 32 * 8); ++ nby = round_up(nby, 16 * 8); ++ break; ++ case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/ ++ nbx = round_up(nbx, 16 * 8); ++ nby = round_up(nby, 16 * 8); ++ break; ++ default: ++ return -EINVAL; ++ } + break; +- case V_028010_ARRAY_2D_TILED_THIN1: ++ case 1: ++ switch (tmp) { ++ case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ ++ nbx = round_up(nbx, 32 * 8); ++ nby = round_up(nby, 16 * 8); ++ break; ++ case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/ ++ case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/ ++ nbx = round_up(nbx, 16 * 8); ++ nby = round_up(nby, 16 * 8); ++ break; ++ case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/ ++ nbx = round_up(nbx, 16 * 8); ++ nby = round_up(nby, 8 * 8); ++ break; ++ default: ++ return -EINVAL; ++ } + break; + default: +- dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, +- G_028010_ARRAY_MODE(track->db_depth_info), +- track->db_depth_info); ++ dev_warn(p->dev, "%s:%d invalid num pipes %d\n", ++ __func__, __LINE__, track->npipes); + return -EINVAL; + } ++ } ++ /* compute number of htile */ ++ nbx = G_028D24_HTILE_WIDTH(track->htile_surface) ? nbx / 8 : nbx / 4; ++ nby = G_028D24_HTILE_HEIGHT(track->htile_surface) ? nby / 8 : nby / 4; ++ size = nbx * nby * 4; ++ size += track->htile_offset; ++ ++ if (size > radeon_bo_size(track->htile_bo)) { ++ dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n", ++ __func__, __LINE__, radeon_bo_size(track->htile_bo), ++ size, nbx, nby); ++ return -EINVAL; ++ } ++ } + +- if (!IS_ALIGNED(pitch, pitch_align)) { +- dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n", +- __func__, __LINE__, pitch, pitch_align, array_mode); +- return -EINVAL; +- } +- if (!IS_ALIGNED(height, height_align)) { +- dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n", +- __func__, __LINE__, height, height_align, array_mode); +- return -EINVAL; +- } +- if (!IS_ALIGNED(base_offset, base_align)) { +- dev_warn(p->dev, "%s offset[%d] 0x%llx, 0x%llx, %d not aligned\n", __func__, i, +- base_offset, base_align, array_mode); +- return -EINVAL; ++ track->db_dirty = false; ++ return 0; ++} ++ ++static int r600_cs_track_check(struct radeon_cs_parser *p) ++{ ++ struct r600_cs_track *track = p->track; ++ u32 tmp; ++ int r, i; ++ ++ /* on legacy kernel we don't perform advanced check */ ++ if (p->rdev == NULL) ++ return 0; ++ ++ /* check streamout */ ++ if (track->streamout_dirty && track->vgt_strmout_en) { ++ for (i = 0; i < 4; i++) { ++ if (track->vgt_strmout_buffer_en & (1 << i)) { ++ if (track->vgt_strmout_bo[i]) { ++ u64 offset = (u64)track->vgt_strmout_bo_offset[i] + ++ (u64)track->vgt_strmout_size[i]; ++ if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) { ++ DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n", ++ i, offset, ++ radeon_bo_size(track->vgt_strmout_bo[i])); ++ return -EINVAL; ++ } ++ } else { ++ dev_warn(p->dev, "No buffer for streamout %d\n", i); ++ return -EINVAL; ++ } + } ++ } ++ track->streamout_dirty = false; ++ } + +- ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; +- nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1; +- tmp = ntiles * bpe * 64 * nviews; +- if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) { +- dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n", +- array_mode, +- track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset, +- radeon_bo_size(track->db_bo)); +- return -EINVAL; ++ if (track->sx_misc_kill_all_prims) ++ return 0; ++ ++ /* check that we have a cb for each enabled target, we don't check ++ * shader_mask because it seems mesa isn't always setting it :( ++ */ ++ if (track->cb_dirty) { ++ tmp = track->cb_target_mask; ++ for (i = 0; i < 8; i++) { ++ u32 format = G_0280A0_FORMAT(track->cb_color_info[i]); ++ ++ if (format != V_0280A0_COLOR_INVALID && ++ (tmp >> (i * 4)) & 0xF) { ++ /* at least one component is enabled */ ++ if (track->cb_color_bo[i] == NULL) { ++ dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n", ++ __func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i); ++ return -EINVAL; ++ } ++ /* perform rewrite of CB_COLOR[0-7]_SIZE */ ++ r = r600_cs_track_validate_cb(p, i); ++ if (r) ++ return r; + } + } ++ track->cb_dirty = false; ++ } ++ ++ /* Check depth buffer */ ++ if (track->db_dirty && (G_028800_STENCIL_ENABLE(track->db_depth_control) || ++ G_028800_Z_ENABLE(track->db_depth_control))) { ++ r = r600_cs_track_validate_db(p); ++ if (r) ++ return r; + } ++ + return 0; + } + +@@ -939,9 +1145,10 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + break; + case R_028800_DB_DEPTH_CONTROL: + track->db_depth_control = radeon_get_ib_value(p, idx); ++ track->db_dirty = true; + break; + case R_028010_DB_DEPTH_INFO: +- if (!p->keep_tiling_flags && ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) && + r600_cs_packet_next_is_pkt3_nop(p)) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { +@@ -959,24 +1166,66 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1); + track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1); + } +- } else ++ } else { + track->db_depth_info = radeon_get_ib_value(p, idx); ++ } ++ track->db_dirty = true; + break; + case R_028004_DB_DEPTH_VIEW: + track->db_depth_view = radeon_get_ib_value(p, idx); ++ track->db_dirty = true; + break; + case R_028000_DB_DEPTH_SIZE: + track->db_depth_size = radeon_get_ib_value(p, idx); + track->db_depth_size_idx = idx; ++ track->db_dirty = true; + break; + case R_028AB0_VGT_STRMOUT_EN: + track->vgt_strmout_en = radeon_get_ib_value(p, idx); ++ track->streamout_dirty = true; + break; + case R_028B20_VGT_STRMOUT_BUFFER_EN: + track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); ++ track->streamout_dirty = true; ++ break; ++ case VGT_STRMOUT_BUFFER_BASE_0: ++ case VGT_STRMOUT_BUFFER_BASE_1: ++ case VGT_STRMOUT_BUFFER_BASE_2: ++ case VGT_STRMOUT_BUFFER_BASE_3: ++ r = r600_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ dev_warn(p->dev, "bad SET_CONTEXT_REG " ++ "0x%04X\n", reg); ++ return -EINVAL; ++ } ++ tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; ++ track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; ++ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); ++ track->vgt_strmout_bo[tmp] = reloc->robj; ++ track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; ++ track->streamout_dirty = true; ++ break; ++ case VGT_STRMOUT_BUFFER_SIZE_0: ++ case VGT_STRMOUT_BUFFER_SIZE_1: ++ case VGT_STRMOUT_BUFFER_SIZE_2: ++ case VGT_STRMOUT_BUFFER_SIZE_3: ++ tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; ++ /* size in register is DWs, convert to bytes */ ++ track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; ++ track->streamout_dirty = true; ++ break; ++ case CP_COHER_BASE: ++ r = r600_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ dev_warn(p->dev, "missing reloc for CP_COHER_BASE " ++ "0x%04X\n", reg); ++ return -EINVAL; ++ } ++ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; + case R_028238_CB_TARGET_MASK: + track->cb_target_mask = radeon_get_ib_value(p, idx); ++ track->cb_dirty = true; + break; + case R_02823C_CB_SHADER_MASK: + track->cb_shader_mask = radeon_get_ib_value(p, idx); +@@ -984,6 +1233,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + case R_028C04_PA_SC_AA_CONFIG: + tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx)); + track->nsamples = 1 << tmp; ++ track->cb_dirty = true; + break; + case R_0280A0_CB_COLOR0_INFO: + case R_0280A4_CB_COLOR1_INFO: +@@ -993,7 +1243,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + case R_0280B4_CB_COLOR5_INFO: + case R_0280B8_CB_COLOR6_INFO: + case R_0280BC_CB_COLOR7_INFO: +- if (!p->keep_tiling_flags && ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) && + r600_cs_packet_next_is_pkt3_nop(p)) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { +@@ -1013,6 +1263,19 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4; + track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); + } ++ track->cb_dirty = true; ++ break; ++ case R_028080_CB_COLOR0_VIEW: ++ case R_028084_CB_COLOR1_VIEW: ++ case R_028088_CB_COLOR2_VIEW: ++ case R_02808C_CB_COLOR3_VIEW: ++ case R_028090_CB_COLOR4_VIEW: ++ case R_028094_CB_COLOR5_VIEW: ++ case R_028098_CB_COLOR6_VIEW: ++ case R_02809C_CB_COLOR7_VIEW: ++ tmp = (reg - R_028080_CB_COLOR0_VIEW) / 4; ++ track->cb_color_view[tmp] = radeon_get_ib_value(p, idx); ++ track->cb_dirty = true; + break; + case R_028060_CB_COLOR0_SIZE: + case R_028064_CB_COLOR1_SIZE: +@@ -1025,6 +1288,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + tmp = (reg - R_028060_CB_COLOR0_SIZE) / 4; + track->cb_color_size[tmp] = radeon_get_ib_value(p, idx); + track->cb_color_size_idx[tmp] = idx; ++ track->cb_dirty = true; + break; + /* This register were added late, there is userspace + * which does provide relocation for those but set +@@ -1107,6 +1371,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + track->cb_color_base_last[tmp] = ib[idx]; + track->cb_color_bo[tmp] = reloc->robj; + track->cb_color_bo_mc[tmp] = reloc->lobj.gpu_offset; ++ track->cb_dirty = true; + break; + case DB_DEPTH_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); +@@ -1119,8 +1384,24 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->db_bo = reloc->robj; + track->db_bo_mc = reloc->lobj.gpu_offset; ++ track->db_dirty = true; + break; + case DB_HTILE_DATA_BASE: ++ r = r600_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ dev_warn(p->dev, "bad SET_CONTEXT_REG " ++ "0x%04X\n", reg); ++ return -EINVAL; ++ } ++ track->htile_offset = radeon_get_ib_value(p, idx) << 8; ++ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); ++ track->htile_bo = reloc->robj; ++ track->db_dirty = true; ++ break; ++ case DB_HTILE_SURFACE: ++ track->htile_surface = radeon_get_ib_value(p, idx); ++ track->db_dirty = true; ++ break; + case SQ_PGM_START_FS: + case SQ_PGM_START_ES: + case SQ_PGM_START_VS: +@@ -1191,6 +1472,9 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; ++ case SX_MISC: ++ track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0; ++ break; + default: + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return -EINVAL; +@@ -1198,7 +1482,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) + return 0; + } + +-static unsigned mip_minify(unsigned size, unsigned level) ++unsigned r600_mip_minify(unsigned size, unsigned level) + { + unsigned val; + +@@ -1220,22 +1504,22 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel, + unsigned nlevels = llevel - blevel + 1; + + *l0_size = -1; +- blocksize = fmt_get_blocksize(format); ++ blocksize = r600_fmt_get_blocksize(format); + +- w0 = mip_minify(w0, 0); +- h0 = mip_minify(h0, 0); +- d0 = mip_minify(d0, 0); ++ w0 = r600_mip_minify(w0, 0); ++ h0 = r600_mip_minify(h0, 0); ++ d0 = r600_mip_minify(d0, 0); + for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) { +- width = mip_minify(w0, i); +- nbx = fmt_get_nblocksx(format, width); ++ width = r600_mip_minify(w0, i); ++ nbx = r600_fmt_get_nblocksx(format, width); + + nbx = round_up(nbx, block_align); + +- height = mip_minify(h0, i); +- nby = fmt_get_nblocksy(format, height); ++ height = r600_mip_minify(h0, i); ++ nby = r600_fmt_get_nblocksy(format, height); + nby = round_up(nby, height_align); + +- depth = mip_minify(d0, i); ++ depth = r600_mip_minify(d0, i); + + size = nbx * nby * blocksize; + if (nfaces) +@@ -1293,7 +1577,7 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, + mip_offset <<= 8; + + word0 = radeon_get_ib_value(p, idx + 0); +- if (!p->keep_tiling_flags) { ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + if (tiling_flags & RADEON_TILING_MACRO) + word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); + else if (tiling_flags & RADEON_TILING_MICRO) +@@ -1304,6 +1588,7 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, + h0 = G_038004_TEX_HEIGHT(word1) + 1; + d0 = G_038004_TEX_DEPTH(word1); + nfaces = 1; ++ array = 0; + switch (G_038000_DIM(word0)) { + case V_038000_SQ_TEX_DIM_1D: + case V_038000_SQ_TEX_DIM_2D: +@@ -1326,7 +1611,7 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, + return -EINVAL; + } + format = G_038004_DATA_FORMAT(word1); +- if (!fmt_is_valid_texture(format, p->family)) { ++ if (!r600_fmt_is_valid_texture(format, p->family)) { + dev_warn(p->dev, "%s:%d texture invalid format %d\n", + __func__, __LINE__, format); + return -EINVAL; +@@ -1339,7 +1624,7 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, + array_check.nbanks = track->nbanks; + array_check.npipes = track->npipes; + array_check.nsamples = 1; +- array_check.blocksize = fmt_get_blocksize(format); ++ array_check.blocksize = r600_fmt_get_blocksize(format); + if (r600_get_array_mode_alignment(&array_check, + &pitch_align, &height_align, &depth_align, &base_align)) { + dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n", +@@ -1372,6 +1657,10 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, + word1 = radeon_get_ib_value(p, idx + 5); + blevel = G_038010_BASE_LEVEL(word0); + llevel = G_038014_LAST_LEVEL(word1); ++ if (blevel > llevel) { ++ dev_warn(p->dev, "texture blevel %d > llevel %d\n", ++ blevel, llevel); ++ } + if (array == 1) { + barray = G_038014_BASE_ARRAY(word1); + larray = G_038014_LAST_ARRAY(word1); +@@ -1383,8 +1672,10 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, + &l0_size, &mipmap_size); + /* using get ib will give us the offset into the texture bo */ + if ((l0_size + word2) > radeon_bo_size(texture)) { +- dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n", +- w0, h0, format, word2, l0_size, radeon_bo_size(texture)); ++ dev_warn(p->dev, "texture bo too small ((%d %d) (%d %d) %d %d %d -> %d have %ld)\n", ++ w0, h0, pitch_align, height_align, ++ array_check.array_mode, format, word2, ++ l0_size, radeon_bo_size(texture)); + dev_warn(p->dev, "alignments %d %d %d %lld\n", pitch, pitch_align, height_align, base_align); + return -EINVAL; + } +@@ -1397,6 +1688,22 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, + return 0; + } + ++static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) ++{ ++ u32 m, i; ++ ++ i = (reg >> 7); ++ if (i >= ARRAY_SIZE(r600_reg_safe_bm)) { ++ dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); ++ return false; ++ } ++ m = 1 << ((reg >> 2) & 31); ++ if (!(r600_reg_safe_bm[i] & m)) ++ return true; ++ dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); ++ return false; ++} ++ + static int r600_packet3_check(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt) + { +@@ -1419,6 +1726,8 @@ static int r600_packet3_check(struct radeon_cs_parser *p, + { + int pred_op; + int tmp; ++ uint64_t offset; ++ + if (pkt->count != 1) { + DRM_ERROR("bad SET PREDICATION\n"); + return -EINVAL; +@@ -1442,8 +1751,12 @@ static int r600_packet3_check(struct radeon_cs_parser *p, + return -EINVAL; + } + +- ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff); ++ offset = reloc->lobj.gpu_offset + ++ (idx_value & 0xfffffff0) + ++ ((u64)(tmp & 0xff) << 32); ++ ++ ib[idx + 0] = offset; ++ ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff); + } + break; + +@@ -1467,6 +1780,8 @@ static int r600_packet3_check(struct radeon_cs_parser *p, + } + break; + case PACKET3_DRAW_INDEX: ++ { ++ uint64_t offset; + if (pkt->count != 3) { + DRM_ERROR("bad DRAW_INDEX\n"); + return -EINVAL; +@@ -1476,14 +1791,21 @@ static int r600_packet3_check(struct radeon_cs_parser *p, + DRM_ERROR("bad DRAW_INDEX\n"); + return -EINVAL; + } +- ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ ++ offset = reloc->lobj.gpu_offset + ++ idx_value + ++ ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); ++ ++ ib[idx+0] = offset; ++ ib[idx+1] = upper_32_bits(offset) & 0xff; ++ + r = r600_cs_track_check(p); + if (r) { + dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); + return r; + } + break; ++ } + case PACKET3_DRAW_INDEX_AUTO: + if (pkt->count != 1) { + DRM_ERROR("bad DRAW_INDEX_AUTO\n"); +@@ -1514,13 +1836,20 @@ static int r600_packet3_check(struct radeon_cs_parser *p, + } + /* bit 4 is reg (0) or mem (1) */ + if (idx_value & 0x10) { ++ uint64_t offset; ++ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad WAIT_REG_MEM\n"); + return -EINVAL; + } +- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ ++ offset = reloc->lobj.gpu_offset + ++ (radeon_get_ib_value(p, idx+1) & 0xfffffff0) + ++ ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); ++ ++ ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffff0); ++ ib[idx+2] = upper_32_bits(offset) & 0xff; + } + break; + case PACKET3_SURFACE_SYNC: +@@ -1545,16 +1874,25 @@ static int r600_packet3_check(struct radeon_cs_parser *p, + return -EINVAL; + } + if (pkt->count) { ++ uint64_t offset; ++ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad EVENT_WRITE\n"); + return -EINVAL; + } +- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ offset = reloc->lobj.gpu_offset + ++ (radeon_get_ib_value(p, idx+1) & 0xfffffff8) + ++ ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); ++ ++ ib[idx+1] = offset & 0xfffffff8; ++ ib[idx+2] = upper_32_bits(offset) & 0xff; + } + break; + case PACKET3_EVENT_WRITE_EOP: ++ { ++ uint64_t offset; ++ + if (pkt->count != 4) { + DRM_ERROR("bad EVENT_WRITE_EOP\n"); + return -EINVAL; +@@ -1564,9 +1902,15 @@ static int r600_packet3_check(struct radeon_cs_parser *p, + DRM_ERROR("bad EVENT_WRITE\n"); + return -EINVAL; + } +- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); +- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ ++ offset = reloc->lobj.gpu_offset + ++ (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + ++ ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); ++ ++ ib[idx+1] = offset & 0xfffffffc; ++ ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); + break; ++ } + case PACKET3_SET_CONFIG_REG: + start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_OFFSET; + end_reg = 4 * pkt->count + start_reg - 4; +@@ -1625,7 +1969,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, + return -EINVAL; + } + base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); +- if (!p->keep_tiling_flags) { ++ if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) +@@ -1651,6 +1995,8 @@ static int r600_packet3_check(struct radeon_cs_parser *p, + ib[idx+1+(i*7)+3] += mip_offset; + break; + case SQ_TEX_VTX_VALID_BUFFER: ++ { ++ uint64_t offset64; + /* vtx base */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { +@@ -1663,11 +2009,15 @@ static int r600_packet3_check(struct radeon_cs_parser *p, + /* force size to size of the buffer */ + dev_warn(p->dev, "vbo resource seems too big (%d) for the bo (%ld)\n", + size + offset, radeon_bo_size(reloc->robj)); +- ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj); ++ ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj) - offset; + } +- ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff); +- ib[idx+1+(i*7)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ++ ++ offset64 = reloc->lobj.gpu_offset + offset; ++ ib[idx+1+(i*8)+0] = offset64; ++ ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) | ++ (upper_32_bits(offset64) & 0xff); + break; ++ } + case SQ_TEX_VTX_INVALID_TEXTURE: + case SQ_TEX_VTX_INVALID_BUFFER: + default: +@@ -1742,6 +2092,104 @@ static int r600_packet3_check(struct radeon_cs_parser *p, + return -EINVAL; + } + break; ++ case PACKET3_STRMOUT_BUFFER_UPDATE: ++ if (pkt->count != 4) { ++ DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); ++ return -EINVAL; ++ } ++ /* Updating memory at DST_ADDRESS. */ ++ if (idx_value & 0x1) { ++ u64 offset; ++ r = r600_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); ++ return -EINVAL; ++ } ++ offset = radeon_get_ib_value(p, idx+1); ++ offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; ++ if ((offset + 4) > radeon_bo_size(reloc->robj)) { ++ DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n", ++ offset + 4, radeon_bo_size(reloc->robj)); ++ return -EINVAL; ++ } ++ offset += reloc->lobj.gpu_offset; ++ ib[idx+1] = offset; ++ ib[idx+2] = upper_32_bits(offset) & 0xff; ++ } ++ /* Reading data from SRC_ADDRESS. */ ++ if (((idx_value >> 1) & 0x3) == 2) { ++ u64 offset; ++ r = r600_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); ++ return -EINVAL; ++ } ++ offset = radeon_get_ib_value(p, idx+3); ++ offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; ++ if ((offset + 4) > radeon_bo_size(reloc->robj)) { ++ DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n", ++ offset + 4, radeon_bo_size(reloc->robj)); ++ return -EINVAL; ++ } ++ offset += reloc->lobj.gpu_offset; ++ ib[idx+3] = offset; ++ ib[idx+4] = upper_32_bits(offset) & 0xff; ++ } ++ break; ++ case PACKET3_COPY_DW: ++ if (pkt->count != 4) { ++ DRM_ERROR("bad COPY_DW (invalid count)\n"); ++ return -EINVAL; ++ } ++ if (idx_value & 0x1) { ++ u64 offset; ++ /* SRC is memory. */ ++ r = r600_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ DRM_ERROR("bad COPY_DW (missing src reloc)\n"); ++ return -EINVAL; ++ } ++ offset = radeon_get_ib_value(p, idx+1); ++ offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; ++ if ((offset + 4) > radeon_bo_size(reloc->robj)) { ++ DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n", ++ offset + 4, radeon_bo_size(reloc->robj)); ++ return -EINVAL; ++ } ++ offset += reloc->lobj.gpu_offset; ++ ib[idx+1] = offset; ++ ib[idx+2] = upper_32_bits(offset) & 0xff; ++ } else { ++ /* SRC is a reg. */ ++ reg = radeon_get_ib_value(p, idx+1) << 2; ++ if (!r600_is_safe_reg(p, reg, idx+1)) ++ return -EINVAL; ++ } ++ if (idx_value & 0x2) { ++ u64 offset; ++ /* DST is memory. */ ++ r = r600_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); ++ return -EINVAL; ++ } ++ offset = radeon_get_ib_value(p, idx+3); ++ offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; ++ if ((offset + 4) > radeon_bo_size(reloc->robj)) { ++ DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n", ++ offset + 4, radeon_bo_size(reloc->robj)); ++ return -EINVAL; ++ } ++ offset += reloc->lobj.gpu_offset; ++ ib[idx+3] = offset; ++ ib[idx+4] = upper_32_bits(offset) & 0xff; ++ } else { ++ /* DST is a reg. */ ++ reg = radeon_get_ib_value(p, idx+3) << 2; ++ if (!r600_is_safe_reg(p, reg, idx+3)) ++ return -EINVAL; ++ } ++ break; + case PACKET3_NOP: + break; + default: +diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c +index 57a825d..61ffe3c 100644 +--- a/drivers/gpu/drm/radeon/r600_hdmi.c ++++ b/drivers/gpu/drm/radeon/r600_hdmi.c +@@ -320,7 +320,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod + struct radeon_device *rdev = dev->dev_private; + uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; + +- if (ASIC_IS_DCE4(rdev)) ++ if (ASIC_IS_DCE5(rdev)) + return; + + if (!offset) +@@ -462,13 +462,31 @@ static void r600_hdmi_assign_block(struct drm_encoder *encoder) + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + ++ u16 eg_offsets[] = { ++ EVERGREEN_CRTC0_REGISTER_OFFSET, ++ EVERGREEN_CRTC1_REGISTER_OFFSET, ++ EVERGREEN_CRTC2_REGISTER_OFFSET, ++ EVERGREEN_CRTC3_REGISTER_OFFSET, ++ EVERGREEN_CRTC4_REGISTER_OFFSET, ++ EVERGREEN_CRTC5_REGISTER_OFFSET, ++ }; ++ + if (!dig) { + dev_err(rdev->dev, "Enabling HDMI on non-dig encoder\n"); + return; + } + +- if (ASIC_IS_DCE4(rdev)) { ++ if (ASIC_IS_DCE5(rdev)) { + /* TODO */ ++ } else if (ASIC_IS_DCE4(rdev)) { ++ if (dig->dig_encoder >= ARRAY_SIZE(eg_offsets)) { ++ dev_err(rdev->dev, "Enabling HDMI on unknown dig\n"); ++ return; ++ } ++ radeon_encoder->hdmi_offset = EVERGREEN_HDMI_BASE + ++ eg_offsets[dig->dig_encoder]; ++ radeon_encoder->hdmi_config_offset = radeon_encoder->hdmi_offset ++ + EVERGREEN_HDMI_CONFIG_OFFSET; + } else if (ASIC_IS_DCE3(rdev)) { + radeon_encoder->hdmi_offset = dig->dig_encoder ? + R600_HDMI_BLOCK3 : R600_HDMI_BLOCK1; +@@ -491,7 +509,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder) + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t offset; + +- if (ASIC_IS_DCE4(rdev)) ++ if (ASIC_IS_DCE5(rdev)) + return; + + if (!radeon_encoder->hdmi_offset) { +@@ -504,16 +522,24 @@ void r600_hdmi_enable(struct drm_encoder *encoder) + } + + offset = radeon_encoder->hdmi_offset; +- if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) { ++ if (ASIC_IS_DCE5(rdev)) { ++ /* TODO */ ++ } else if (ASIC_IS_DCE4(rdev)) { ++ WREG32_P(radeon_encoder->hdmi_config_offset + 0xc, 0x1, ~0x1); ++ } else if (ASIC_IS_DCE32(rdev)) { + WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1); +- } else if (ASIC_IS_DCE2(rdev) && !ASIC_IS_DCE3(rdev)) { ++ } else if (ASIC_IS_DCE3(rdev)) { ++ /* TODO */ ++ } else if (ASIC_IS_DCE2(rdev)) { + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: +- WREG32_P(AVIVO_TMDSA_CNTL, 0x4, ~0x4); ++ WREG32_P(AVIVO_TMDSA_CNTL, AVIVO_TMDSA_CNTL_HDMI_EN, ++ ~AVIVO_TMDSA_CNTL_HDMI_EN); + WREG32(offset + R600_HDMI_ENABLE, 0x101); + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: +- WREG32_P(AVIVO_LVTMA_CNTL, 0x4, ~0x4); ++ WREG32_P(AVIVO_LVTMA_CNTL, AVIVO_LVTMA_CNTL_HDMI_EN, ++ ~AVIVO_LVTMA_CNTL_HDMI_EN); + WREG32(offset + R600_HDMI_ENABLE, 0x105); + break; + default: +@@ -525,8 +551,8 @@ void r600_hdmi_enable(struct drm_encoder *encoder) + if (rdev->irq.installed + && rdev->family != CHIP_RS600 + && rdev->family != CHIP_RS690 +- && rdev->family != CHIP_RS740) { +- ++ && rdev->family != CHIP_RS740 ++ && !ASIC_IS_DCE4(rdev)) { + /* if irq is available use it */ + rdev->irq.hdmi[offset == R600_HDMI_BLOCK1 ? 0 : 1] = true; + radeon_irq_set(rdev); +@@ -551,7 +577,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder) + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t offset; + +- if (ASIC_IS_DCE4(rdev)) ++ if (ASIC_IS_DCE5(rdev)) + return; + + offset = radeon_encoder->hdmi_offset; +@@ -570,16 +596,22 @@ void r600_hdmi_disable(struct drm_encoder *encoder) + /* disable polling */ + r600_audio_disable_polling(encoder); + +- if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) { ++ if (ASIC_IS_DCE5(rdev)) { ++ /* TODO */ ++ } else if (ASIC_IS_DCE4(rdev)) { ++ WREG32_P(radeon_encoder->hdmi_config_offset + 0xc, 0, ~0x1); ++ } else if (ASIC_IS_DCE32(rdev)) { + WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1); + } else if (ASIC_IS_DCE2(rdev) && !ASIC_IS_DCE3(rdev)) { + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: +- WREG32_P(AVIVO_TMDSA_CNTL, 0, ~0x4); ++ WREG32_P(AVIVO_TMDSA_CNTL, 0, ++ ~AVIVO_TMDSA_CNTL_HDMI_EN); + WREG32(offset + R600_HDMI_ENABLE, 0); + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: +- WREG32_P(AVIVO_LVTMA_CNTL, 0, ~0x4); ++ WREG32_P(AVIVO_LVTMA_CNTL, 0, ++ ~AVIVO_LVTMA_CNTL_HDMI_EN); + WREG32(offset + R600_HDMI_ENABLE, 0); + break; + default: +diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h +index cb29480..02bb238 100644 +--- a/drivers/gpu/drm/radeon/r600d.h ++++ b/drivers/gpu/drm/radeon/r600d.h +@@ -78,6 +78,20 @@ + + #define CB_COLOR0_SIZE 0x28060 + #define CB_COLOR0_VIEW 0x28080 ++#define R_028080_CB_COLOR0_VIEW 0x028080 ++#define S_028080_SLICE_START(x) (((x) & 0x7FF) << 0) ++#define G_028080_SLICE_START(x) (((x) >> 0) & 0x7FF) ++#define C_028080_SLICE_START 0xFFFFF800 ++#define S_028080_SLICE_MAX(x) (((x) & 0x7FF) << 13) ++#define G_028080_SLICE_MAX(x) (((x) >> 13) & 0x7FF) ++#define C_028080_SLICE_MAX 0xFF001FFF ++#define R_028084_CB_COLOR1_VIEW 0x028084 ++#define R_028088_CB_COLOR2_VIEW 0x028088 ++#define R_02808C_CB_COLOR3_VIEW 0x02808C ++#define R_028090_CB_COLOR4_VIEW 0x028090 ++#define R_028094_CB_COLOR5_VIEW 0x028094 ++#define R_028098_CB_COLOR6_VIEW 0x028098 ++#define R_02809C_CB_COLOR7_VIEW 0x02809C + #define CB_COLOR0_INFO 0x280a0 + # define CB_FORMAT(x) ((x) << 2) + # define CB_ARRAY_MODE(x) ((x) << 8) +@@ -181,6 +195,14 @@ + #define PREZ_MUST_WAIT_FOR_POSTZ_DONE (1 << 31) + #define DB_DEPTH_BASE 0x2800C + #define DB_HTILE_DATA_BASE 0x28014 ++#define DB_HTILE_SURFACE 0x28D24 ++#define S_028D24_HTILE_WIDTH(x) (((x) & 0x1) << 0) ++#define G_028D24_HTILE_WIDTH(x) (((x) >> 0) & 0x1) ++#define C_028D24_HTILE_WIDTH 0xFFFFFFFE ++#define S_028D24_HTILE_HEIGHT(x) (((x) & 0x1) << 1) ++#define G_028D24_HTILE_HEIGHT(x) (((x) >> 1) & 0x1) ++#define C_028D24_HTILE_HEIGHT 0xFFFFFFFD ++#define G_028D24_LINEAR(x) (((x) >> 2) & 0x1) + #define DB_WATERMARKS 0x9838 + #define DEPTH_FREE(x) ((x) << 0) + #define DEPTH_FLUSH(x) ((x) << 5) +@@ -494,6 +516,11 @@ + #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC + #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC + #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C ++#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 ++#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 ++#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 ++#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 ++ + #define VGT_STRMOUT_EN 0x28AB0 + #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 + #define VTX_REUSE_DEPTH_MASK 0x000000FF +@@ -575,6 +602,10 @@ + #define RLC_UCODE_ADDR 0x3f2c + #define RLC_UCODE_DATA 0x3f30 + ++/* new for TN */ ++#define TN_RLC_SAVE_AND_RESTORE_BASE 0x3f10 ++#define TN_RLC_CLEAR_STATE_RESTORE_BASE 0x3f20 ++ + #define SRBM_SOFT_RESET 0xe60 + # define SOFT_RESET_RLC (1 << 13) + +@@ -832,7 +863,11 @@ + #define PACKET3_STRMOUT_BUFFER_UPDATE 0x34 + #define PACKET3_INDIRECT_BUFFER_MP 0x38 + #define PACKET3_MEM_SEMAPHORE 0x39 ++# define PACKET3_SEM_WAIT_ON_SIGNAL (0x1 << 12) ++# define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) ++# define PACKET3_SEM_SEL_WAIT (0x7 << 29) + #define PACKET3_MPEG_INDEX 0x3A ++#define PACKET3_COPY_DW 0x3B + #define PACKET3_WAIT_REG_MEM 0x3C + #define PACKET3_MEM_WRITE 0x3D + #define PACKET3_INDIRECT_BUFFER 0x32 +diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h +index 28e69e9..66150f0 100644 +--- a/drivers/gpu/drm/radeon/radeon.h ++++ b/drivers/gpu/drm/radeon/radeon.h +@@ -107,6 +107,21 @@ extern int radeon_msi; + #define RADEONFB_CONN_LIMIT 4 + #define RADEON_BIOS_NUM_SCRATCH 8 + ++/* max number of rings */ ++#define RADEON_NUM_RINGS 3 ++ ++/* internal ring indices */ ++/* r1xx+ has gfx CP ring */ ++#define RADEON_RING_TYPE_GFX_INDEX 0 ++ ++/* cayman has 2 compute CP rings */ ++#define CAYMAN_RING_TYPE_CP1_INDEX 1 ++#define CAYMAN_RING_TYPE_CP2_INDEX 2 ++ ++/* hardcode those limit for now */ ++#define RADEON_VA_RESERVED_SIZE (8 << 20) ++#define RADEON_IB_VM_MAX_SIZE (64 << 10) ++ + /* + * Errata workarounds. + */ +@@ -127,6 +142,47 @@ bool radeon_get_bios(struct radeon_device *rdev); + + + /* ++ * Mutex which allows recursive locking from the same process. ++ */ ++struct radeon_mutex { ++ struct mutex mutex; ++ struct task_struct *owner; ++ int level; ++}; ++ ++static inline void radeon_mutex_init(struct radeon_mutex *mutex) ++{ ++ mutex_init(&mutex->mutex); ++ mutex->owner = NULL; ++ mutex->level = 0; ++} ++ ++static inline void radeon_mutex_lock(struct radeon_mutex *mutex) ++{ ++ if (mutex_trylock(&mutex->mutex)) { ++ /* The mutex was unlocked before, so it's ours now */ ++ mutex->owner = current; ++ } else if (mutex->owner != current) { ++ /* Another process locked the mutex, take it */ ++ mutex_lock(&mutex->mutex); ++ mutex->owner = current; ++ } ++ /* Otherwise the mutex was already locked by this process */ ++ ++ mutex->level++; ++} ++ ++static inline void radeon_mutex_unlock(struct radeon_mutex *mutex) ++{ ++ if (--mutex->level > 0) ++ return; ++ ++ mutex->owner = NULL; ++ mutex_unlock(&mutex->mutex); ++} ++ ++ ++/* + * Dummy page + */ + struct radeon_dummy_page { +@@ -165,26 +221,30 @@ void radeon_pm_resume(struct radeon_device *rdev); + void radeon_combios_get_power_modes(struct radeon_device *rdev); + void radeon_atombios_get_power_modes(struct radeon_device *rdev); + void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); +-int radeon_atom_get_max_vddc(struct radeon_device *rdev, u16 *voltage); + void rs690_pm_info(struct radeon_device *rdev); + extern int rv6xx_get_temp(struct radeon_device *rdev); + extern int rv770_get_temp(struct radeon_device *rdev); + extern int evergreen_get_temp(struct radeon_device *rdev); + extern int sumo_get_temp(struct radeon_device *rdev); ++extern int si_get_temp(struct radeon_device *rdev); ++extern void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw, ++ unsigned *bankh, unsigned *mtaspect, ++ unsigned *tile_split); + + /* + * Fences. + */ + struct radeon_fence_driver { + uint32_t scratch_reg; ++ uint64_t gpu_addr; ++ volatile uint32_t *cpu_addr; + atomic_t seq; + uint32_t last_seq; + unsigned long last_jiffies; + unsigned long last_timeout; + wait_queue_head_t queue; +- rwlock_t lock; + struct list_head created; +- struct list_head emited; ++ struct list_head emitted; + struct list_head signaled; + bool initialized; + }; +@@ -195,21 +255,26 @@ struct radeon_fence { + struct list_head list; + /* protected by radeon_fence.lock */ + uint32_t seq; +- bool emited; ++ bool emitted; + bool signaled; ++ /* RB, DMA, etc. */ ++ int ring; ++ struct radeon_semaphore *semaphore; + }; + ++int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); + int radeon_fence_driver_init(struct radeon_device *rdev); + void radeon_fence_driver_fini(struct radeon_device *rdev); +-int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence); ++int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence, int ring); + int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence); +-void radeon_fence_process(struct radeon_device *rdev); ++void radeon_fence_process(struct radeon_device *rdev, int ring); + bool radeon_fence_signaled(struct radeon_fence *fence); + int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); +-int radeon_fence_wait_next(struct radeon_device *rdev); +-int radeon_fence_wait_last(struct radeon_device *rdev); ++int radeon_fence_wait_next(struct radeon_device *rdev, int ring); ++int radeon_fence_wait_last(struct radeon_device *rdev, int ring); + struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); + void radeon_fence_unref(struct radeon_fence **fence); ++int radeon_fence_count_emitted(struct radeon_device *rdev, int ring); + + /* + * Tiling registers +@@ -231,6 +296,21 @@ struct radeon_mman { + bool initialized; + }; + ++/* bo virtual address in a specific vm */ ++struct radeon_bo_va { ++ /* bo list is protected by bo being reserved */ ++ struct list_head bo_list; ++ /* vm list is protected by vm mutex */ ++ struct list_head vm_list; ++ /* constant after initialization */ ++ struct radeon_vm *vm; ++ struct radeon_bo *bo; ++ uint64_t soffset; ++ uint64_t eoffset; ++ uint32_t flags; ++ bool valid; ++}; ++ + struct radeon_bo { + /* Protected by gem.mutex */ + struct list_head list; +@@ -244,6 +324,10 @@ struct radeon_bo { + u32 tiling_flags; + u32 pitch; + int surface_reg; ++ /* list of all virtual address to which this bo ++ * is associated to ++ */ ++ struct list_head va; + /* Constant after initialization */ + struct radeon_device *rdev; + struct drm_gem_object gem_base; +@@ -259,6 +343,48 @@ struct radeon_bo_list { + u32 tiling_flags; + }; + ++/* sub-allocation manager, it has to be protected by another lock. ++ * By conception this is an helper for other part of the driver ++ * like the indirect buffer or semaphore, which both have their ++ * locking. ++ * ++ * Principe is simple, we keep a list of sub allocation in offset ++ * order (first entry has offset == 0, last entry has the highest ++ * offset). ++ * ++ * When allocating new object we first check if there is room at ++ * the end total_size - (last_object_offset + last_object_size) >= ++ * alloc_size. If so we allocate new object there. ++ * ++ * When there is not enough room at the end, we start waiting for ++ * each sub object until we reach object_offset+object_size >= ++ * alloc_size, this object then become the sub object we return. ++ * ++ * Alignment can't be bigger than page size. ++ * ++ * Hole are not considered for allocation to keep things simple. ++ * Assumption is that there won't be hole (all object on same ++ * alignment). ++ */ ++struct radeon_sa_manager { ++ struct radeon_bo *bo; ++ struct list_head sa_bo; ++ unsigned size; ++ uint64_t gpu_addr; ++ void *cpu_ptr; ++ uint32_t domain; ++}; ++ ++struct radeon_sa_bo; ++ ++/* sub-allocation buffer */ ++struct radeon_sa_bo { ++ struct list_head list; ++ struct radeon_sa_manager *manager; ++ unsigned offset; ++ unsigned size; ++}; ++ + /* + * GEM objects. + */ +@@ -273,9 +399,6 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, + int alignment, int initial_domain, + bool discardable, bool kernel, + struct drm_gem_object **obj); +-int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain, +- uint64_t *gpu_addr); +-void radeon_gem_object_unpin(struct drm_gem_object *obj); + + int radeon_mode_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, +@@ -288,6 +411,46 @@ int radeon_mode_dumb_destroy(struct drm_file *file_priv, + uint32_t handle); + + /* ++ * Semaphores. ++ */ ++struct radeon_ring; ++ ++#define RADEON_SEMAPHORE_BO_SIZE 256 ++ ++struct radeon_semaphore_driver { ++ rwlock_t lock; ++ struct list_head bo; ++}; ++ ++struct radeon_semaphore_bo; ++ ++/* everything here is constant */ ++struct radeon_semaphore { ++ struct list_head list; ++ uint64_t gpu_addr; ++ uint32_t *cpu_ptr; ++ struct radeon_semaphore_bo *bo; ++}; ++ ++struct radeon_semaphore_bo { ++ struct list_head list; ++ struct radeon_ib *ib; ++ struct list_head free; ++ struct radeon_semaphore semaphores[RADEON_SEMAPHORE_BO_SIZE/8]; ++ unsigned nused; ++}; ++ ++void radeon_semaphore_driver_fini(struct radeon_device *rdev); ++int radeon_semaphore_create(struct radeon_device *rdev, ++ struct radeon_semaphore **semaphore); ++void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring, ++ struct radeon_semaphore *semaphore); ++void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, ++ struct radeon_semaphore *semaphore); ++void radeon_semaphore_free(struct radeon_device *rdev, ++ struct radeon_semaphore *semaphore); ++ ++/* + * GART structures, functions & helpers + */ + struct radeon_mc; +@@ -295,6 +458,7 @@ struct radeon_mc; + #define RADEON_GPU_PAGE_SIZE 4096 + #define RADEON_GPU_PAGE_MASK (RADEON_GPU_PAGE_SIZE - 1) + #define RADEON_GPU_PAGE_SHIFT 12 ++#define RADEON_GPU_PAGE_ALIGN(a) (((a) + RADEON_GPU_PAGE_MASK) & ~RADEON_GPU_PAGE_MASK) + + struct radeon_gart { + dma_addr_t table_addr; +@@ -305,7 +469,6 @@ struct radeon_gart { + unsigned table_size; + struct page **pages; + dma_addr_t *pages_addr; +- bool *ttm_alloced; + bool ready; + }; + +@@ -419,7 +582,7 @@ union radeon_irq_stat_regs { + + struct radeon_irq { + bool installed; +- bool sw_int; ++ bool sw_int[RADEON_NUM_RINGS]; + bool crtc_vblank_int[RADEON_MAX_CRTCS]; + bool pflip[RADEON_MAX_CRTCS]; + wait_queue_head_t vblank_queue; +@@ -429,7 +592,7 @@ struct radeon_irq { + wait_queue_head_t idle_queue; + bool hdmi[RADEON_MAX_HDMI_BLOCKS]; + spinlock_t sw_lock; +- int sw_refcount; ++ int sw_refcount[RADEON_NUM_RINGS]; + union radeon_irq_stat_regs stat_regs; + spinlock_t pflip_lock[RADEON_MAX_CRTCS]; + int pflip_refcount[RADEON_MAX_CRTCS]; +@@ -437,22 +600,24 @@ struct radeon_irq { + + int radeon_irq_kms_init(struct radeon_device *rdev); + void radeon_irq_kms_fini(struct radeon_device *rdev); +-void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev); +-void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev); ++void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring); ++void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring); + void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc); + void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc); + + /* +- * CP & ring. ++ * CP & rings. + */ ++ + struct radeon_ib { +- struct list_head list; ++ struct radeon_sa_bo sa_bo; + unsigned idx; ++ uint32_t length_dw; + uint64_t gpu_addr; +- struct radeon_fence *fence; + uint32_t *ptr; +- uint32_t length_dw; +- bool free; ++ struct radeon_fence *fence; ++ unsigned vm_id; ++ bool is_const_ib; + }; + + /* +@@ -460,20 +625,22 @@ struct radeon_ib { + * mutex protects scheduled_ibs, ready, alloc_bm + */ + struct radeon_ib_pool { +- struct mutex mutex; +- struct radeon_bo *robj; +- struct list_head bogus_ib; +- struct radeon_ib ibs[RADEON_IB_POOL_SIZE]; +- bool ready; +- unsigned head_id; ++ struct radeon_mutex mutex; ++ struct radeon_sa_manager sa_manager; ++ struct radeon_ib ibs[RADEON_IB_POOL_SIZE]; ++ bool ready; ++ unsigned head_id; + }; + +-struct radeon_cp { ++struct radeon_ring { + struct radeon_bo *ring_obj; + volatile uint32_t *ring; + unsigned rptr; ++ unsigned rptr_offs; ++ unsigned rptr_reg; + unsigned wptr; + unsigned wptr_old; ++ unsigned wptr_reg; + unsigned ring_size; + unsigned ring_free_dw; + int count_dw; +@@ -482,6 +649,61 @@ struct radeon_cp { + uint32_t ptr_mask; + struct mutex mutex; + bool ready; ++ u32 ptr_reg_shift; ++ u32 ptr_reg_mask; ++ u32 nop; ++}; ++ ++/* ++ * VM ++ */ ++struct radeon_vm { ++ struct list_head list; ++ struct list_head va; ++ int id; ++ unsigned last_pfn; ++ u64 pt_gpu_addr; ++ u64 *pt; ++ struct radeon_sa_bo sa_bo; ++ struct mutex mutex; ++ /* last fence for cs using this vm */ ++ struct radeon_fence *fence; ++}; ++ ++struct radeon_vm_funcs { ++ int (*init)(struct radeon_device *rdev); ++ void (*fini)(struct radeon_device *rdev); ++ /* cs mutex must be lock for schedule_ib */ ++ int (*bind)(struct radeon_device *rdev, struct radeon_vm *vm, int id); ++ void (*unbind)(struct radeon_device *rdev, struct radeon_vm *vm); ++ void (*tlb_flush)(struct radeon_device *rdev, struct radeon_vm *vm); ++ uint32_t (*page_flags)(struct radeon_device *rdev, ++ struct radeon_vm *vm, ++ uint32_t flags); ++ void (*set_page)(struct radeon_device *rdev, struct radeon_vm *vm, ++ unsigned pfn, uint64_t addr, uint32_t flags); ++}; ++ ++struct radeon_vm_manager { ++ struct list_head lru_vm; ++ uint32_t use_bitmap; ++ struct radeon_sa_manager sa_manager; ++ uint32_t max_pfn; ++ /* fields constant after init */ ++ const struct radeon_vm_funcs *funcs; ++ /* number of VMIDs */ ++ unsigned nvm; ++ /* vram base address for page table entry */ ++ u64 vram_base_offset; ++ /* is vm enabled? */ ++ bool enabled; ++}; ++ ++/* ++ * file private structure ++ */ ++struct radeon_fpriv { ++ struct radeon_vm vm; + }; + + /* +@@ -491,6 +713,7 @@ struct r600_ih { + struct radeon_bo *ring_obj; + volatile uint32_t *ring; + unsigned rptr; ++ unsigned rptr_offs; + unsigned wptr; + unsigned wptr_old; + unsigned ring_size; +@@ -534,23 +757,40 @@ struct r600_blit { + + void r600_blit_suspend(struct radeon_device *rdev); + +-int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib); ++/* ++ * SI RLC stuff ++ */ ++struct si_rlc { ++ /* for power gating */ ++ struct radeon_bo *save_restore_obj; ++ uint64_t save_restore_gpu_addr; ++ /* for clear state */ ++ struct radeon_bo *clear_state_obj; ++ uint64_t clear_state_gpu_addr; ++}; ++ ++int radeon_ib_get(struct radeon_device *rdev, int ring, ++ struct radeon_ib **ib, unsigned size); + void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib); ++bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib); + int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib); + int radeon_ib_pool_init(struct radeon_device *rdev); + void radeon_ib_pool_fini(struct radeon_device *rdev); +-int radeon_ib_test(struct radeon_device *rdev); +-extern void radeon_ib_bogus_add(struct radeon_device *rdev, struct radeon_ib *ib); ++int radeon_ib_pool_start(struct radeon_device *rdev); ++int radeon_ib_pool_suspend(struct radeon_device *rdev); + /* Ring access between begin & end cannot sleep */ +-void radeon_ring_free_size(struct radeon_device *rdev); +-int radeon_ring_alloc(struct radeon_device *rdev, unsigned ndw); +-int radeon_ring_lock(struct radeon_device *rdev, unsigned ndw); +-void radeon_ring_commit(struct radeon_device *rdev); +-void radeon_ring_unlock_commit(struct radeon_device *rdev); +-void radeon_ring_unlock_undo(struct radeon_device *rdev); +-int radeon_ring_test(struct radeon_device *rdev); +-int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size); +-void radeon_ring_fini(struct radeon_device *rdev); ++int radeon_ring_index(struct radeon_device *rdev, struct radeon_ring *cp); ++void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp); ++int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); ++int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); ++void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *cp); ++void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *cp); ++void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *cp); ++int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); ++int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size, ++ unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, ++ u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop); ++void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *cp); + + + /* +@@ -567,12 +807,12 @@ struct radeon_cs_reloc { + struct radeon_cs_chunk { + uint32_t chunk_id; + uint32_t length_dw; +- int kpage_idx[2]; +- uint32_t *kpage[2]; ++ int kpage_idx[2]; ++ uint32_t *kpage[2]; + uint32_t *kdata; +- void __user *user_ptr; +- int last_copied_page; +- int last_page_index; ++ void __user *user_ptr; ++ int last_copied_page; ++ int last_page_index; + }; + + struct radeon_cs_parser { +@@ -593,11 +833,16 @@ struct radeon_cs_parser { + /* indices of various chunks */ + int chunk_ib_idx; + int chunk_relocs_idx; ++ int chunk_flags_idx; ++ int chunk_const_ib_idx; + struct radeon_ib *ib; ++ struct radeon_ib *const_ib; + void *track; + unsigned family; + int parser_error; +- bool keep_tiling_flags; ++ u32 cs_flags; ++ u32 ring; ++ s32 priority; + }; + + extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx); +@@ -733,6 +978,7 @@ enum radeon_int_thermal_type { + THERMAL_TYPE_EVERGREEN, + THERMAL_TYPE_SUMO, + THERMAL_TYPE_NI, ++ THERMAL_TYPE_SI, + }; + + struct radeon_voltage { +@@ -854,11 +1100,20 @@ void radeon_benchmark(struct radeon_device *rdev, int test_number); + * Testing + */ + void radeon_test_moves(struct radeon_device *rdev); ++void radeon_test_ring_sync(struct radeon_device *rdev, ++ struct radeon_ring *cpA, ++ struct radeon_ring *cpB); ++void radeon_test_syncing(struct radeon_device *rdev); + + + /* + * Debugfs + */ ++struct radeon_debugfs { ++ struct drm_info_list *files; ++ unsigned num_files; ++}; ++ + int radeon_debugfs_add_files(struct radeon_device *rdev, + struct drm_info_list *files, + unsigned nfiles); +@@ -874,53 +1129,8 @@ struct radeon_asic { + int (*resume)(struct radeon_device *rdev); + int (*suspend)(struct radeon_device *rdev); + void (*vga_set_state)(struct radeon_device *rdev, bool state); +- bool (*gpu_is_lockup)(struct radeon_device *rdev); ++ bool (*gpu_is_lockup)(struct radeon_device *rdev, struct radeon_ring *cp); + int (*asic_reset)(struct radeon_device *rdev); +- void (*gart_tlb_flush)(struct radeon_device *rdev); +- int (*gart_set_page)(struct radeon_device *rdev, int i, uint64_t addr); +- int (*cp_init)(struct radeon_device *rdev, unsigned ring_size); +- void (*cp_fini)(struct radeon_device *rdev); +- void (*cp_disable)(struct radeon_device *rdev); +- void (*cp_commit)(struct radeon_device *rdev); +- void (*ring_start)(struct radeon_device *rdev); +- int (*ring_test)(struct radeon_device *rdev); +- void (*ring_ib_execute)(struct radeon_device *rdev, struct radeon_ib *ib); +- int (*irq_set)(struct radeon_device *rdev); +- int (*irq_process)(struct radeon_device *rdev); +- u32 (*get_vblank_counter)(struct radeon_device *rdev, int crtc); +- void (*fence_ring_emit)(struct radeon_device *rdev, struct radeon_fence *fence); +- int (*cs_parse)(struct radeon_cs_parser *p); +- int (*copy_blit)(struct radeon_device *rdev, +- uint64_t src_offset, +- uint64_t dst_offset, +- unsigned num_gpu_pages, +- struct radeon_fence *fence); +- int (*copy_dma)(struct radeon_device *rdev, +- uint64_t src_offset, +- uint64_t dst_offset, +- unsigned num_gpu_pages, +- struct radeon_fence *fence); +- int (*copy)(struct radeon_device *rdev, +- uint64_t src_offset, +- uint64_t dst_offset, +- unsigned num_gpu_pages, +- struct radeon_fence *fence); +- uint32_t (*get_engine_clock)(struct radeon_device *rdev); +- void (*set_engine_clock)(struct radeon_device *rdev, uint32_t eng_clock); +- uint32_t (*get_memory_clock)(struct radeon_device *rdev); +- void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock); +- int (*get_pcie_lanes)(struct radeon_device *rdev); +- void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); +- void (*set_clock_gating)(struct radeon_device *rdev, int enable); +- int (*set_surface_reg)(struct radeon_device *rdev, int reg, +- uint32_t tiling_flags, uint32_t pitch, +- uint32_t offset, uint32_t obj_size); +- void (*clear_surface_reg)(struct radeon_device *rdev, int reg); +- void (*bandwidth_update)(struct radeon_device *rdev); +- void (*hpd_init)(struct radeon_device *rdev); +- void (*hpd_fini)(struct radeon_device *rdev); +- bool (*hpd_sense)(struct radeon_device *rdev, enum radeon_hpd_id hpd); +- void (*hpd_set_polarity)(struct radeon_device *rdev, enum radeon_hpd_id hpd); + /* ioctl hw specific callback. Some hw might want to perform special + * operation on specific ioctl. For instance on wait idle some hw + * might want to perform and HDP flush through MMIO as it seems that +@@ -928,17 +1138,99 @@ struct radeon_asic { + * through ring. + */ + void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo); ++ /* check if 3D engine is idle */ + bool (*gui_idle)(struct radeon_device *rdev); ++ /* wait for mc_idle */ ++ int (*mc_wait_for_idle)(struct radeon_device *rdev); ++ /* gart */ ++ struct { ++ void (*tlb_flush)(struct radeon_device *rdev); ++ int (*set_page)(struct radeon_device *rdev, int i, uint64_t addr); ++ } gart; ++ /* ring specific callbacks */ ++ struct { ++ void (*ib_execute)(struct radeon_device *rdev, struct radeon_ib *ib); ++ int (*ib_parse)(struct radeon_device *rdev, struct radeon_ib *ib); ++ void (*emit_fence)(struct radeon_device *rdev, struct radeon_fence *fence); ++ void (*emit_semaphore)(struct radeon_device *rdev, struct radeon_ring *cp, ++ struct radeon_semaphore *semaphore, bool emit_wait); ++ int (*cs_parse)(struct radeon_cs_parser *p); ++ void (*ring_start)(struct radeon_device *rdev, struct radeon_ring *cp); ++ int (*ring_test)(struct radeon_device *rdev, struct radeon_ring *cp); ++ int (*ib_test)(struct radeon_device *rdev, struct radeon_ring *cp); ++ } ring[RADEON_NUM_RINGS]; ++ /* irqs */ ++ struct { ++ int (*set)(struct radeon_device *rdev); ++ int (*process)(struct radeon_device *rdev); ++ } irq; ++ /* displays */ ++ struct { ++ /* display watermarks */ ++ void (*bandwidth_update)(struct radeon_device *rdev); ++ /* get frame count */ ++ u32 (*get_vblank_counter)(struct radeon_device *rdev, int crtc); ++ /* wait for vblank */ ++ void (*wait_for_vblank)(struct radeon_device *rdev, int crtc); ++ } display; ++ /* copy functions for bo handling */ ++ struct { ++ int (*blit)(struct radeon_device *rdev, ++ uint64_t src_offset, ++ uint64_t dst_offset, ++ unsigned num_gpu_pages, ++ struct radeon_fence *fence); ++ u32 blit_ring_index; ++ int (*dma)(struct radeon_device *rdev, ++ uint64_t src_offset, ++ uint64_t dst_offset, ++ unsigned num_gpu_pages, ++ struct radeon_fence *fence); ++ u32 dma_ring_index; ++ /* method used for bo copy */ ++ int (*copy)(struct radeon_device *rdev, ++ uint64_t src_offset, ++ uint64_t dst_offset, ++ unsigned num_gpu_pages, ++ struct radeon_fence *fence); ++ /* ring used for bo copies */ ++ u32 copy_ring_index; ++ } copy; ++ /* surfaces */ ++ struct { ++ int (*set_reg)(struct radeon_device *rdev, int reg, ++ uint32_t tiling_flags, uint32_t pitch, ++ uint32_t offset, uint32_t obj_size); ++ void (*clear_reg)(struct radeon_device *rdev, int reg); ++ } surface; ++ /* hotplug detect */ ++ struct { ++ void (*init)(struct radeon_device *rdev); ++ void (*fini)(struct radeon_device *rdev); ++ bool (*sense)(struct radeon_device *rdev, enum radeon_hpd_id hpd); ++ void (*set_polarity)(struct radeon_device *rdev, enum radeon_hpd_id hpd); ++ } hpd; + /* power management */ +- void (*pm_misc)(struct radeon_device *rdev); +- void (*pm_prepare)(struct radeon_device *rdev); +- void (*pm_finish)(struct radeon_device *rdev); +- void (*pm_init_profile)(struct radeon_device *rdev); +- void (*pm_get_dynpm_state)(struct radeon_device *rdev); ++ struct { ++ void (*misc)(struct radeon_device *rdev); ++ void (*prepare)(struct radeon_device *rdev); ++ void (*finish)(struct radeon_device *rdev); ++ void (*init_profile)(struct radeon_device *rdev); ++ void (*get_dynpm_state)(struct radeon_device *rdev); ++ uint32_t (*get_engine_clock)(struct radeon_device *rdev); ++ void (*set_engine_clock)(struct radeon_device *rdev, uint32_t eng_clock); ++ uint32_t (*get_memory_clock)(struct radeon_device *rdev); ++ void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock); ++ int (*get_pcie_lanes)(struct radeon_device *rdev); ++ void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); ++ void (*set_clock_gating)(struct radeon_device *rdev, int enable); ++ } pm; + /* pageflipping */ +- void (*pre_page_flip)(struct radeon_device *rdev, int crtc); +- u32 (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base); +- void (*post_page_flip)(struct radeon_device *rdev, int crtc); ++ struct { ++ void (*pre_page_flip)(struct radeon_device *rdev, int crtc); ++ u32 (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base); ++ void (*post_page_flip)(struct radeon_device *rdev, int crtc); ++ } pflip; + }; + + /* +@@ -1078,6 +1370,37 @@ struct cayman_asic { + struct r100_gpu_lockup lockup; + }; + ++struct si_asic { ++ unsigned max_shader_engines; ++ unsigned max_pipes_per_simd; ++ unsigned max_tile_pipes; ++ unsigned max_simds_per_se; ++ unsigned max_backends_per_se; ++ unsigned max_texture_channel_caches; ++ unsigned max_gprs; ++ unsigned max_gs_threads; ++ unsigned max_hw_contexts; ++ unsigned sc_prim_fifo_size_frontend; ++ unsigned sc_prim_fifo_size_backend; ++ unsigned sc_hiz_tile_fifo_size; ++ unsigned sc_earlyz_tile_fifo_size; ++ ++ unsigned num_shader_engines; ++ unsigned num_tile_pipes; ++ unsigned num_backends_per_se; ++ unsigned backend_disable_mask_per_asic; ++ unsigned backend_map; ++ unsigned num_texture_channel_caches; ++ unsigned mem_max_burst_length_bytes; ++ unsigned mem_row_size_in_kb; ++ unsigned shader_engine_tile_size; ++ unsigned num_gpus; ++ unsigned multi_gpu_tile_size; ++ ++ unsigned tile_config; ++ struct r100_gpu_lockup lockup; ++}; ++ + union radeon_asic_config { + struct r300_asic r300; + struct r100_asic r100; +@@ -1085,6 +1408,7 @@ union radeon_asic_config { + struct rv770_asic rv770; + struct evergreen_asic evergreen; + struct cayman_asic cayman; ++ struct si_asic si; + }; + + /* +@@ -1117,6 +1441,8 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); + int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); ++int radeon_gem_va_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *filp); + int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); + int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +@@ -1132,47 +1458,6 @@ struct r600_vram_scratch { + + + /* +- * Mutex which allows recursive locking from the same process. +- */ +-struct radeon_mutex { +- struct mutex mutex; +- struct task_struct *owner; +- int level; +-}; +- +-static inline void radeon_mutex_init(struct radeon_mutex *mutex) +-{ +- mutex_init(&mutex->mutex); +- mutex->owner = NULL; +- mutex->level = 0; +-} +- +-static inline void radeon_mutex_lock(struct radeon_mutex *mutex) +-{ +- if (mutex_trylock(&mutex->mutex)) { +- /* The mutex was unlocked before, so it's ours now */ +- mutex->owner = current; +- } else if (mutex->owner != current) { +- /* Another process locked the mutex, take it */ +- mutex_lock(&mutex->mutex); +- mutex->owner = current; +- } +- /* Otherwise the mutex was already locked by this process */ +- +- mutex->level++; +-} +- +-static inline void radeon_mutex_unlock(struct radeon_mutex *mutex) +-{ +- if (--mutex->level > 0) +- return; +- +- mutex->owner = NULL; +- mutex_unlock(&mutex->mutex); +-} +- +- +-/* + * Core structure, functions and helpers. + */ + typedef uint32_t (*radeon_rreg_t)(struct radeon_device*, uint32_t); +@@ -1216,11 +1501,10 @@ struct radeon_device { + struct radeon_mode_info mode_info; + struct radeon_scratch scratch; + struct radeon_mman mman; +- struct radeon_fence_driver fence_drv; +- struct radeon_cp cp; +- /* cayman compute rings */ +- struct radeon_cp cp1; +- struct radeon_cp cp2; ++ rwlock_t fence_lock; ++ struct radeon_fence_driver fence_drv[RADEON_NUM_RINGS]; ++ struct radeon_semaphore_driver semaphore_drv; ++ struct radeon_ring ring[RADEON_NUM_RINGS]; + struct radeon_ib_pool ib_pool; + struct radeon_irq irq; + struct radeon_asic *asic; +@@ -1240,10 +1524,12 @@ struct radeon_device { + const struct firmware *pfp_fw; /* r6/700 PFP firmware */ + const struct firmware *rlc_fw; /* r6/700 RLC firmware */ + const struct firmware *mc_fw; /* NI MC firmware */ ++ const struct firmware *ce_fw; /* SI CE firmware */ + struct r600_blit r600_blit; + struct r600_vram_scratch vram_scratch; + int msi_enabled; /* msi enabled */ + struct r600_ih ih; /* r6/700 interrupt ring */ ++ struct si_rlc rlc; + struct work_struct hotplug_work; + int num_crtc; /* number of crtcs */ + struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ +@@ -1264,6 +1550,11 @@ struct radeon_device { + struct drm_file *cmask_filp; + /* i2c buses */ + struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS]; ++ /* debugfs */ ++ struct radeon_debugfs debugfs[RADEON_DEBUGFS_MAX_COMPONENTS]; ++ unsigned debugfs_count; ++ /* virtual memory */ ++ struct radeon_vm_manager vm_manager; + }; + + int radeon_device_init(struct radeon_device *rdev, +@@ -1382,6 +1673,9 @@ void r100_pll_errata_after_index(struct radeon_device *rdev); + #define ASIC_IS_DCE41(rdev) ((rdev->family >= CHIP_PALM) && \ + (rdev->flags & RADEON_IS_IGP)) + #define ASIC_IS_DCE5(rdev) ((rdev->family >= CHIP_BARTS)) ++#define ASIC_IS_DCE6(rdev) ((rdev->family >= CHIP_ARUBA)) ++#define ASIC_IS_DCE61(rdev) ((rdev->family >= CHIP_ARUBA) && \ ++ (rdev->flags & RADEON_IS_IGP)) + + /* + * BIOS helpers. +@@ -1399,18 +1693,17 @@ void radeon_atombios_fini(struct radeon_device *rdev); + /* + * RING helpers. + */ +- + #if DRM_DEBUG_CODE == 0 +-static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) ++static inline void radeon_ring_write(struct radeon_ring *ring, uint32_t v) + { +- rdev->cp.ring[rdev->cp.wptr++] = v; +- rdev->cp.wptr &= rdev->cp.ptr_mask; +- rdev->cp.count_dw--; +- rdev->cp.ring_free_dw--; ++ ring->ring[ring->wptr++] = v; ++ ring->wptr &= ring->ptr_mask; ++ ring->count_dw--; ++ ring->ring_free_dw--; + } + #else + /* With debugging this is just too big to inline */ +-void radeon_ring_write(struct radeon_device *rdev, uint32_t v); ++void radeon_ring_write(struct radeon_ring *ring, uint32_t v); + #endif + + /* +@@ -1420,46 +1713,53 @@ void radeon_ring_write(struct radeon_device *rdev, uint32_t v); + #define radeon_fini(rdev) (rdev)->asic->fini((rdev)) + #define radeon_resume(rdev) (rdev)->asic->resume((rdev)) + #define radeon_suspend(rdev) (rdev)->asic->suspend((rdev)) +-#define radeon_cs_parse(p) rdev->asic->cs_parse((p)) ++#define radeon_cs_parse(rdev, r, p) (rdev)->asic->ring[(r)].cs_parse((p)) + #define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state)) +-#define radeon_gpu_is_lockup(rdev) (rdev)->asic->gpu_is_lockup((rdev)) ++#define radeon_gpu_is_lockup(rdev, cp) (rdev)->asic->gpu_is_lockup((rdev), (cp)) + #define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev)) +-#define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart_tlb_flush((rdev)) +-#define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart_set_page((rdev), (i), (p)) +-#define radeon_cp_commit(rdev) (rdev)->asic->cp_commit((rdev)) +-#define radeon_ring_start(rdev) (rdev)->asic->ring_start((rdev)) +-#define radeon_ring_test(rdev) (rdev)->asic->ring_test((rdev)) +-#define radeon_ring_ib_execute(rdev, ib) (rdev)->asic->ring_ib_execute((rdev), (ib)) +-#define radeon_irq_set(rdev) (rdev)->asic->irq_set((rdev)) +-#define radeon_irq_process(rdev) (rdev)->asic->irq_process((rdev)) +-#define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->get_vblank_counter((rdev), (crtc)) +-#define radeon_fence_ring_emit(rdev, fence) (rdev)->asic->fence_ring_emit((rdev), (fence)) +-#define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy_blit((rdev), (s), (d), (np), (f)) +-#define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy_dma((rdev), (s), (d), (np), (f)) +-#define radeon_copy(rdev, s, d, np, f) (rdev)->asic->copy((rdev), (s), (d), (np), (f)) +-#define radeon_get_engine_clock(rdev) (rdev)->asic->get_engine_clock((rdev)) +-#define radeon_set_engine_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e)) +-#define radeon_get_memory_clock(rdev) (rdev)->asic->get_memory_clock((rdev)) +-#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_memory_clock((rdev), (e)) +-#define radeon_get_pcie_lanes(rdev) (rdev)->asic->get_pcie_lanes((rdev)) +-#define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l)) +-#define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e)) +-#define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s))) +-#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r))) +-#define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev)) +-#define radeon_hpd_init(rdev) (rdev)->asic->hpd_init((rdev)) +-#define radeon_hpd_fini(rdev) (rdev)->asic->hpd_fini((rdev)) +-#define radeon_hpd_sense(rdev, hpd) (rdev)->asic->hpd_sense((rdev), (hpd)) +-#define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd)) ++#define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart.tlb_flush((rdev)) ++#define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart.set_page((rdev), (i), (p)) ++#define radeon_ring_start(rdev, r, cp) (rdev)->asic->ring[(r)].ring_start((rdev), (cp)) ++#define radeon_ring_test(rdev, r, cp) (rdev)->asic->ring[(r)].ring_test((rdev), (cp)) ++#define radeon_ib_test(rdev, r, cp) (rdev)->asic->ring[(r)].ib_test((rdev), (cp)) ++#define radeon_ring_ib_execute(rdev, r, ib) (rdev)->asic->ring[(r)].ib_execute((rdev), (ib)) ++#define radeon_ring_ib_parse(rdev, r, ib) (rdev)->asic->ring[(r)].ib_parse((rdev), (ib)) ++#define radeon_irq_set(rdev) (rdev)->asic->irq.set((rdev)) ++#define radeon_irq_process(rdev) (rdev)->asic->irq.process((rdev)) ++#define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->display.get_vblank_counter((rdev), (crtc)) ++#define radeon_fence_ring_emit(rdev, r, fence) (rdev)->asic->ring[(r)].emit_fence((rdev), (fence)) ++#define radeon_semaphore_ring_emit(rdev, r, cp, semaphore, emit_wait) (rdev)->asic->ring[(r)].emit_semaphore((rdev), (cp), (semaphore), (emit_wait)) ++#define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy.blit((rdev), (s), (d), (np), (f)) ++#define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy.dma((rdev), (s), (d), (np), (f)) ++#define radeon_copy(rdev, s, d, np, f) (rdev)->asic->copy.copy((rdev), (s), (d), (np), (f)) ++#define radeon_copy_blit_ring_index(rdev) (rdev)->asic->copy.blit_ring_index ++#define radeon_copy_dma_ring_index(rdev) (rdev)->asic->copy.dma_ring_index ++#define radeon_copy_ring_index(rdev) (rdev)->asic->copy.copy_ring_index ++#define radeon_get_engine_clock(rdev) (rdev)->asic->pm.get_engine_clock((rdev)) ++#define radeon_set_engine_clock(rdev, e) (rdev)->asic->pm.set_engine_clock((rdev), (e)) ++#define radeon_get_memory_clock(rdev) (rdev)->asic->pm.get_memory_clock((rdev)) ++#define radeon_set_memory_clock(rdev, e) (rdev)->asic->pm.set_memory_clock((rdev), (e)) ++#define radeon_get_pcie_lanes(rdev) (rdev)->asic->pm.get_pcie_lanes((rdev)) ++#define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->pm.set_pcie_lanes((rdev), (l)) ++#define radeon_set_clock_gating(rdev, e) (rdev)->asic->pm.set_clock_gating((rdev), (e)) ++#define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->surface.set_reg((rdev), (r), (f), (p), (o), (s))) ++#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->surface.clear_reg((rdev), (r))) ++#define radeon_bandwidth_update(rdev) (rdev)->asic->display.bandwidth_update((rdev)) ++#define radeon_hpd_init(rdev) (rdev)->asic->hpd.init((rdev)) ++#define radeon_hpd_fini(rdev) (rdev)->asic->hpd.fini((rdev)) ++#define radeon_hpd_sense(rdev, h) (rdev)->asic->hpd.sense((rdev), (h)) ++#define radeon_hpd_set_polarity(rdev, h) (rdev)->asic->hpd.set_polarity((rdev), (h)) + #define radeon_gui_idle(rdev) (rdev)->asic->gui_idle((rdev)) +-#define radeon_pm_misc(rdev) (rdev)->asic->pm_misc((rdev)) +-#define radeon_pm_prepare(rdev) (rdev)->asic->pm_prepare((rdev)) +-#define radeon_pm_finish(rdev) (rdev)->asic->pm_finish((rdev)) +-#define radeon_pm_init_profile(rdev) (rdev)->asic->pm_init_profile((rdev)) +-#define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm_get_dynpm_state((rdev)) +-#define radeon_pre_page_flip(rdev, crtc) rdev->asic->pre_page_flip((rdev), (crtc)) +-#define radeon_page_flip(rdev, crtc, base) rdev->asic->page_flip((rdev), (crtc), (base)) +-#define radeon_post_page_flip(rdev, crtc) rdev->asic->post_page_flip((rdev), (crtc)) ++#define radeon_pm_misc(rdev) (rdev)->asic->pm.misc((rdev)) ++#define radeon_pm_prepare(rdev) (rdev)->asic->pm.prepare((rdev)) ++#define radeon_pm_finish(rdev) (rdev)->asic->pm.finish((rdev)) ++#define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev)) ++#define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev)) ++#define radeon_pre_page_flip(rdev, crtc) rdev->asic->pflip.pre_page_flip((rdev), (crtc)) ++#define radeon_page_flip(rdev, crtc, base) rdev->asic->pflip.page_flip((rdev), (crtc), (base)) ++#define radeon_post_page_flip(rdev, crtc) rdev->asic->pflip.post_page_flip((rdev), (crtc)) ++#define radeon_wait_for_vblank(rdev, crtc) rdev->asic->display.wait_for_vblank((rdev), (crtc)) ++#define radeon_mc_wait_for_idle(rdev) rdev->asic->mc_wait_for_idle((rdev)) + + /* Common functions */ + /* AGP */ +@@ -1488,12 +1788,49 @@ extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state); + extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size); + + /* ++ * vm ++ */ ++int radeon_vm_manager_init(struct radeon_device *rdev); ++void radeon_vm_manager_fini(struct radeon_device *rdev); ++int radeon_vm_manager_start(struct radeon_device *rdev); ++int radeon_vm_manager_suspend(struct radeon_device *rdev); ++int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); ++void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm); ++int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm); ++void radeon_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm); ++int radeon_vm_bo_update_pte(struct radeon_device *rdev, ++ struct radeon_vm *vm, ++ struct radeon_bo *bo, ++ struct ttm_mem_reg *mem); ++void radeon_vm_bo_invalidate(struct radeon_device *rdev, ++ struct radeon_bo *bo); ++int radeon_vm_bo_add(struct radeon_device *rdev, ++ struct radeon_vm *vm, ++ struct radeon_bo *bo, ++ uint64_t offset, ++ uint32_t flags); ++int radeon_vm_bo_rmv(struct radeon_device *rdev, ++ struct radeon_vm *vm, ++ struct radeon_bo *bo); ++ ++ ++/* + * R600 vram scratch functions + */ + int r600_vram_scratch_init(struct radeon_device *rdev); + void r600_vram_scratch_fini(struct radeon_device *rdev); + + /* ++ * r600 cs checking helper ++ */ ++unsigned r600_mip_minify(unsigned size, unsigned level); ++bool r600_fmt_is_valid_color(u32 format); ++bool r600_fmt_is_valid_texture(u32 format, enum radeon_family family); ++int r600_fmt_get_blocksize(u32 format); ++int r600_fmt_get_nblocksx(u32 format, u32 w); ++int r600_fmt_get_nblocksy(u32 format, u32 h); ++ ++/* + * r600 functions used by radeon_encoder.c + */ + extern void r600_hdmi_enable(struct drm_encoder *encoder); +diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c +index a2e1eae..be4dc2f 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.c ++++ b/drivers/gpu/drm/radeon/radeon_asic.c +@@ -114,13 +114,13 @@ void radeon_agp_disable(struct radeon_device *rdev) + rdev->family == CHIP_R423) { + DRM_INFO("Forcing AGP to PCIE mode\n"); + rdev->flags |= RADEON_IS_PCIE; +- rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush; +- rdev->asic->gart_set_page = &rv370_pcie_gart_set_page; ++ rdev->asic->gart.tlb_flush = &rv370_pcie_gart_tlb_flush; ++ rdev->asic->gart.set_page = &rv370_pcie_gart_set_page; + } else { + DRM_INFO("Forcing AGP to PCI mode\n"); + rdev->flags |= RADEON_IS_PCI; +- rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush; +- rdev->asic->gart_set_page = &r100_pci_gart_set_page; ++ rdev->asic->gart.tlb_flush = &r100_pci_gart_tlb_flush; ++ rdev->asic->gart.set_page = &r100_pci_gart_set_page; + } + rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; + } +@@ -136,44 +136,70 @@ static struct radeon_asic r100_asic = { + .vga_set_state = &r100_vga_set_state, + .gpu_is_lockup = &r100_gpu_is_lockup, + .asic_reset = &r100_asic_reset, +- .gart_tlb_flush = &r100_pci_gart_tlb_flush, +- .gart_set_page = &r100_pci_gart_set_page, +- .cp_commit = &r100_cp_commit, +- .ring_start = &r100_ring_start, +- .ring_test = &r100_ring_test, +- .ring_ib_execute = &r100_ring_ib_execute, +- .irq_set = &r100_irq_set, +- .irq_process = &r100_irq_process, +- .get_vblank_counter = &r100_get_vblank_counter, +- .fence_ring_emit = &r100_fence_ring_emit, +- .cs_parse = &r100_cs_parse, +- .copy_blit = &r100_copy_blit, +- .copy_dma = NULL, +- .copy = &r100_copy_blit, +- .get_engine_clock = &radeon_legacy_get_engine_clock, +- .set_engine_clock = &radeon_legacy_set_engine_clock, +- .get_memory_clock = &radeon_legacy_get_memory_clock, +- .set_memory_clock = NULL, +- .get_pcie_lanes = NULL, +- .set_pcie_lanes = NULL, +- .set_clock_gating = &radeon_legacy_set_clock_gating, +- .set_surface_reg = r100_set_surface_reg, +- .clear_surface_reg = r100_clear_surface_reg, +- .bandwidth_update = &r100_bandwidth_update, +- .hpd_init = &r100_hpd_init, +- .hpd_fini = &r100_hpd_fini, +- .hpd_sense = &r100_hpd_sense, +- .hpd_set_polarity = &r100_hpd_set_polarity, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, +- .pm_misc = &r100_pm_misc, +- .pm_prepare = &r100_pm_prepare, +- .pm_finish = &r100_pm_finish, +- .pm_init_profile = &r100_pm_init_profile, +- .pm_get_dynpm_state = &r100_pm_get_dynpm_state, +- .pre_page_flip = &r100_pre_page_flip, +- .page_flip = &r100_page_flip, +- .post_page_flip = &r100_post_page_flip, ++ .mc_wait_for_idle = &r100_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &r100_pci_gart_tlb_flush, ++ .set_page = &r100_pci_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r100_ring_ib_execute, ++ .emit_fence = &r100_fence_ring_emit, ++ .emit_semaphore = &r100_semaphore_ring_emit, ++ .cs_parse = &r100_cs_parse, ++ .ring_start = &r100_ring_start, ++ .ring_test = &r100_ring_test, ++ .ib_test = &r100_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &r100_irq_set, ++ .process = &r100_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &r100_bandwidth_update, ++ .get_vblank_counter = &r100_get_vblank_counter, ++ .wait_for_vblank = &r100_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r100_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = NULL, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r100_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r100_set_surface_reg, ++ .clear_reg = r100_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &r100_hpd_init, ++ .fini = &r100_hpd_fini, ++ .sense = &r100_hpd_sense, ++ .set_polarity = &r100_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &r100_pm_misc, ++ .prepare = &r100_pm_prepare, ++ .finish = &r100_pm_finish, ++ .init_profile = &r100_pm_init_profile, ++ .get_dynpm_state = &r100_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_legacy_get_engine_clock, ++ .set_engine_clock = &radeon_legacy_set_engine_clock, ++ .get_memory_clock = &radeon_legacy_get_memory_clock, ++ .set_memory_clock = NULL, ++ .get_pcie_lanes = NULL, ++ .set_pcie_lanes = NULL, ++ .set_clock_gating = &radeon_legacy_set_clock_gating, ++ }, ++ .pflip = { ++ .pre_page_flip = &r100_pre_page_flip, ++ .page_flip = &r100_page_flip, ++ .post_page_flip = &r100_post_page_flip, ++ }, + }; + + static struct radeon_asic r200_asic = { +@@ -184,43 +210,70 @@ static struct radeon_asic r200_asic = { + .vga_set_state = &r100_vga_set_state, + .gpu_is_lockup = &r100_gpu_is_lockup, + .asic_reset = &r100_asic_reset, +- .gart_tlb_flush = &r100_pci_gart_tlb_flush, +- .gart_set_page = &r100_pci_gart_set_page, +- .cp_commit = &r100_cp_commit, +- .ring_start = &r100_ring_start, +- .ring_test = &r100_ring_test, +- .ring_ib_execute = &r100_ring_ib_execute, +- .irq_set = &r100_irq_set, +- .irq_process = &r100_irq_process, +- .get_vblank_counter = &r100_get_vblank_counter, +- .fence_ring_emit = &r100_fence_ring_emit, +- .cs_parse = &r100_cs_parse, +- .copy_blit = &r100_copy_blit, +- .copy_dma = &r200_copy_dma, +- .copy = &r100_copy_blit, +- .get_engine_clock = &radeon_legacy_get_engine_clock, +- .set_engine_clock = &radeon_legacy_set_engine_clock, +- .get_memory_clock = &radeon_legacy_get_memory_clock, +- .set_memory_clock = NULL, +- .set_pcie_lanes = NULL, +- .set_clock_gating = &radeon_legacy_set_clock_gating, +- .set_surface_reg = r100_set_surface_reg, +- .clear_surface_reg = r100_clear_surface_reg, +- .bandwidth_update = &r100_bandwidth_update, +- .hpd_init = &r100_hpd_init, +- .hpd_fini = &r100_hpd_fini, +- .hpd_sense = &r100_hpd_sense, +- .hpd_set_polarity = &r100_hpd_set_polarity, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, +- .pm_misc = &r100_pm_misc, +- .pm_prepare = &r100_pm_prepare, +- .pm_finish = &r100_pm_finish, +- .pm_init_profile = &r100_pm_init_profile, +- .pm_get_dynpm_state = &r100_pm_get_dynpm_state, +- .pre_page_flip = &r100_pre_page_flip, +- .page_flip = &r100_page_flip, +- .post_page_flip = &r100_post_page_flip, ++ .mc_wait_for_idle = &r100_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &r100_pci_gart_tlb_flush, ++ .set_page = &r100_pci_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r100_ring_ib_execute, ++ .emit_fence = &r100_fence_ring_emit, ++ .emit_semaphore = &r100_semaphore_ring_emit, ++ .cs_parse = &r100_cs_parse, ++ .ring_start = &r100_ring_start, ++ .ring_test = &r100_ring_test, ++ .ib_test = &r100_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &r100_irq_set, ++ .process = &r100_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &r100_bandwidth_update, ++ .get_vblank_counter = &r100_get_vblank_counter, ++ .wait_for_vblank = &r100_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r100_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = &r200_copy_dma, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r100_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r100_set_surface_reg, ++ .clear_reg = r100_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &r100_hpd_init, ++ .fini = &r100_hpd_fini, ++ .sense = &r100_hpd_sense, ++ .set_polarity = &r100_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &r100_pm_misc, ++ .prepare = &r100_pm_prepare, ++ .finish = &r100_pm_finish, ++ .init_profile = &r100_pm_init_profile, ++ .get_dynpm_state = &r100_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_legacy_get_engine_clock, ++ .set_engine_clock = &radeon_legacy_set_engine_clock, ++ .get_memory_clock = &radeon_legacy_get_memory_clock, ++ .set_memory_clock = NULL, ++ .get_pcie_lanes = NULL, ++ .set_pcie_lanes = NULL, ++ .set_clock_gating = &radeon_legacy_set_clock_gating, ++ }, ++ .pflip = { ++ .pre_page_flip = &r100_pre_page_flip, ++ .page_flip = &r100_page_flip, ++ .post_page_flip = &r100_post_page_flip, ++ }, + }; + + static struct radeon_asic r300_asic = { +@@ -231,44 +284,70 @@ static struct radeon_asic r300_asic = { + .vga_set_state = &r100_vga_set_state, + .gpu_is_lockup = &r300_gpu_is_lockup, + .asic_reset = &r300_asic_reset, +- .gart_tlb_flush = &r100_pci_gart_tlb_flush, +- .gart_set_page = &r100_pci_gart_set_page, +- .cp_commit = &r100_cp_commit, +- .ring_start = &r300_ring_start, +- .ring_test = &r100_ring_test, +- .ring_ib_execute = &r100_ring_ib_execute, +- .irq_set = &r100_irq_set, +- .irq_process = &r100_irq_process, +- .get_vblank_counter = &r100_get_vblank_counter, +- .fence_ring_emit = &r300_fence_ring_emit, +- .cs_parse = &r300_cs_parse, +- .copy_blit = &r100_copy_blit, +- .copy_dma = &r200_copy_dma, +- .copy = &r100_copy_blit, +- .get_engine_clock = &radeon_legacy_get_engine_clock, +- .set_engine_clock = &radeon_legacy_set_engine_clock, +- .get_memory_clock = &radeon_legacy_get_memory_clock, +- .set_memory_clock = NULL, +- .get_pcie_lanes = &rv370_get_pcie_lanes, +- .set_pcie_lanes = &rv370_set_pcie_lanes, +- .set_clock_gating = &radeon_legacy_set_clock_gating, +- .set_surface_reg = r100_set_surface_reg, +- .clear_surface_reg = r100_clear_surface_reg, +- .bandwidth_update = &r100_bandwidth_update, +- .hpd_init = &r100_hpd_init, +- .hpd_fini = &r100_hpd_fini, +- .hpd_sense = &r100_hpd_sense, +- .hpd_set_polarity = &r100_hpd_set_polarity, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, +- .pm_misc = &r100_pm_misc, +- .pm_prepare = &r100_pm_prepare, +- .pm_finish = &r100_pm_finish, +- .pm_init_profile = &r100_pm_init_profile, +- .pm_get_dynpm_state = &r100_pm_get_dynpm_state, +- .pre_page_flip = &r100_pre_page_flip, +- .page_flip = &r100_page_flip, +- .post_page_flip = &r100_post_page_flip, ++ .mc_wait_for_idle = &r300_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &r100_pci_gart_tlb_flush, ++ .set_page = &r100_pci_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r100_ring_ib_execute, ++ .emit_fence = &r300_fence_ring_emit, ++ .emit_semaphore = &r100_semaphore_ring_emit, ++ .cs_parse = &r300_cs_parse, ++ .ring_start = &r300_ring_start, ++ .ring_test = &r100_ring_test, ++ .ib_test = &r100_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &r100_irq_set, ++ .process = &r100_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &r100_bandwidth_update, ++ .get_vblank_counter = &r100_get_vblank_counter, ++ .wait_for_vblank = &r100_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r100_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = &r200_copy_dma, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r100_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r100_set_surface_reg, ++ .clear_reg = r100_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &r100_hpd_init, ++ .fini = &r100_hpd_fini, ++ .sense = &r100_hpd_sense, ++ .set_polarity = &r100_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &r100_pm_misc, ++ .prepare = &r100_pm_prepare, ++ .finish = &r100_pm_finish, ++ .init_profile = &r100_pm_init_profile, ++ .get_dynpm_state = &r100_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_legacy_get_engine_clock, ++ .set_engine_clock = &radeon_legacy_set_engine_clock, ++ .get_memory_clock = &radeon_legacy_get_memory_clock, ++ .set_memory_clock = NULL, ++ .get_pcie_lanes = &rv370_get_pcie_lanes, ++ .set_pcie_lanes = &rv370_set_pcie_lanes, ++ .set_clock_gating = &radeon_legacy_set_clock_gating, ++ }, ++ .pflip = { ++ .pre_page_flip = &r100_pre_page_flip, ++ .page_flip = &r100_page_flip, ++ .post_page_flip = &r100_post_page_flip, ++ }, + }; + + static struct radeon_asic r300_asic_pcie = { +@@ -279,43 +358,70 @@ static struct radeon_asic r300_asic_pcie = { + .vga_set_state = &r100_vga_set_state, + .gpu_is_lockup = &r300_gpu_is_lockup, + .asic_reset = &r300_asic_reset, +- .gart_tlb_flush = &rv370_pcie_gart_tlb_flush, +- .gart_set_page = &rv370_pcie_gart_set_page, +- .cp_commit = &r100_cp_commit, +- .ring_start = &r300_ring_start, +- .ring_test = &r100_ring_test, +- .ring_ib_execute = &r100_ring_ib_execute, +- .irq_set = &r100_irq_set, +- .irq_process = &r100_irq_process, +- .get_vblank_counter = &r100_get_vblank_counter, +- .fence_ring_emit = &r300_fence_ring_emit, +- .cs_parse = &r300_cs_parse, +- .copy_blit = &r100_copy_blit, +- .copy_dma = &r200_copy_dma, +- .copy = &r100_copy_blit, +- .get_engine_clock = &radeon_legacy_get_engine_clock, +- .set_engine_clock = &radeon_legacy_set_engine_clock, +- .get_memory_clock = &radeon_legacy_get_memory_clock, +- .set_memory_clock = NULL, +- .set_pcie_lanes = &rv370_set_pcie_lanes, +- .set_clock_gating = &radeon_legacy_set_clock_gating, +- .set_surface_reg = r100_set_surface_reg, +- .clear_surface_reg = r100_clear_surface_reg, +- .bandwidth_update = &r100_bandwidth_update, +- .hpd_init = &r100_hpd_init, +- .hpd_fini = &r100_hpd_fini, +- .hpd_sense = &r100_hpd_sense, +- .hpd_set_polarity = &r100_hpd_set_polarity, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, +- .pm_misc = &r100_pm_misc, +- .pm_prepare = &r100_pm_prepare, +- .pm_finish = &r100_pm_finish, +- .pm_init_profile = &r100_pm_init_profile, +- .pm_get_dynpm_state = &r100_pm_get_dynpm_state, +- .pre_page_flip = &r100_pre_page_flip, +- .page_flip = &r100_page_flip, +- .post_page_flip = &r100_post_page_flip, ++ .mc_wait_for_idle = &r300_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &rv370_pcie_gart_tlb_flush, ++ .set_page = &rv370_pcie_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r100_ring_ib_execute, ++ .emit_fence = &r300_fence_ring_emit, ++ .emit_semaphore = &r100_semaphore_ring_emit, ++ .cs_parse = &r300_cs_parse, ++ .ring_start = &r300_ring_start, ++ .ring_test = &r100_ring_test, ++ .ib_test = &r100_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &r100_irq_set, ++ .process = &r100_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &r100_bandwidth_update, ++ .get_vblank_counter = &r100_get_vblank_counter, ++ .wait_for_vblank = &r100_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r100_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = &r200_copy_dma, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r100_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r100_set_surface_reg, ++ .clear_reg = r100_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &r100_hpd_init, ++ .fini = &r100_hpd_fini, ++ .sense = &r100_hpd_sense, ++ .set_polarity = &r100_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &r100_pm_misc, ++ .prepare = &r100_pm_prepare, ++ .finish = &r100_pm_finish, ++ .init_profile = &r100_pm_init_profile, ++ .get_dynpm_state = &r100_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_legacy_get_engine_clock, ++ .set_engine_clock = &radeon_legacy_set_engine_clock, ++ .get_memory_clock = &radeon_legacy_get_memory_clock, ++ .set_memory_clock = NULL, ++ .get_pcie_lanes = &rv370_get_pcie_lanes, ++ .set_pcie_lanes = &rv370_set_pcie_lanes, ++ .set_clock_gating = &radeon_legacy_set_clock_gating, ++ }, ++ .pflip = { ++ .pre_page_flip = &r100_pre_page_flip, ++ .page_flip = &r100_page_flip, ++ .post_page_flip = &r100_post_page_flip, ++ }, + }; + + static struct radeon_asic r420_asic = { +@@ -326,44 +432,70 @@ static struct radeon_asic r420_asic = { + .vga_set_state = &r100_vga_set_state, + .gpu_is_lockup = &r300_gpu_is_lockup, + .asic_reset = &r300_asic_reset, +- .gart_tlb_flush = &rv370_pcie_gart_tlb_flush, +- .gart_set_page = &rv370_pcie_gart_set_page, +- .cp_commit = &r100_cp_commit, +- .ring_start = &r300_ring_start, +- .ring_test = &r100_ring_test, +- .ring_ib_execute = &r100_ring_ib_execute, +- .irq_set = &r100_irq_set, +- .irq_process = &r100_irq_process, +- .get_vblank_counter = &r100_get_vblank_counter, +- .fence_ring_emit = &r300_fence_ring_emit, +- .cs_parse = &r300_cs_parse, +- .copy_blit = &r100_copy_blit, +- .copy_dma = &r200_copy_dma, +- .copy = &r100_copy_blit, +- .get_engine_clock = &radeon_atom_get_engine_clock, +- .set_engine_clock = &radeon_atom_set_engine_clock, +- .get_memory_clock = &radeon_atom_get_memory_clock, +- .set_memory_clock = &radeon_atom_set_memory_clock, +- .get_pcie_lanes = &rv370_get_pcie_lanes, +- .set_pcie_lanes = &rv370_set_pcie_lanes, +- .set_clock_gating = &radeon_atom_set_clock_gating, +- .set_surface_reg = r100_set_surface_reg, +- .clear_surface_reg = r100_clear_surface_reg, +- .bandwidth_update = &r100_bandwidth_update, +- .hpd_init = &r100_hpd_init, +- .hpd_fini = &r100_hpd_fini, +- .hpd_sense = &r100_hpd_sense, +- .hpd_set_polarity = &r100_hpd_set_polarity, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, +- .pm_misc = &r100_pm_misc, +- .pm_prepare = &r100_pm_prepare, +- .pm_finish = &r100_pm_finish, +- .pm_init_profile = &r420_pm_init_profile, +- .pm_get_dynpm_state = &r100_pm_get_dynpm_state, +- .pre_page_flip = &r100_pre_page_flip, +- .page_flip = &r100_page_flip, +- .post_page_flip = &r100_post_page_flip, ++ .mc_wait_for_idle = &r300_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &rv370_pcie_gart_tlb_flush, ++ .set_page = &rv370_pcie_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r100_ring_ib_execute, ++ .emit_fence = &r300_fence_ring_emit, ++ .emit_semaphore = &r100_semaphore_ring_emit, ++ .cs_parse = &r300_cs_parse, ++ .ring_start = &r300_ring_start, ++ .ring_test = &r100_ring_test, ++ .ib_test = &r100_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &r100_irq_set, ++ .process = &r100_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &r100_bandwidth_update, ++ .get_vblank_counter = &r100_get_vblank_counter, ++ .wait_for_vblank = &r100_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r100_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = &r200_copy_dma, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r100_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r100_set_surface_reg, ++ .clear_reg = r100_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &r100_hpd_init, ++ .fini = &r100_hpd_fini, ++ .sense = &r100_hpd_sense, ++ .set_polarity = &r100_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &r100_pm_misc, ++ .prepare = &r100_pm_prepare, ++ .finish = &r100_pm_finish, ++ .init_profile = &r420_pm_init_profile, ++ .get_dynpm_state = &r100_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = &radeon_atom_get_memory_clock, ++ .set_memory_clock = &radeon_atom_set_memory_clock, ++ .get_pcie_lanes = &rv370_get_pcie_lanes, ++ .set_pcie_lanes = &rv370_set_pcie_lanes, ++ .set_clock_gating = &radeon_atom_set_clock_gating, ++ }, ++ .pflip = { ++ .pre_page_flip = &r100_pre_page_flip, ++ .page_flip = &r100_page_flip, ++ .post_page_flip = &r100_post_page_flip, ++ }, + }; + + static struct radeon_asic rs400_asic = { +@@ -374,44 +506,70 @@ static struct radeon_asic rs400_asic = { + .vga_set_state = &r100_vga_set_state, + .gpu_is_lockup = &r300_gpu_is_lockup, + .asic_reset = &r300_asic_reset, +- .gart_tlb_flush = &rs400_gart_tlb_flush, +- .gart_set_page = &rs400_gart_set_page, +- .cp_commit = &r100_cp_commit, +- .ring_start = &r300_ring_start, +- .ring_test = &r100_ring_test, +- .ring_ib_execute = &r100_ring_ib_execute, +- .irq_set = &r100_irq_set, +- .irq_process = &r100_irq_process, +- .get_vblank_counter = &r100_get_vblank_counter, +- .fence_ring_emit = &r300_fence_ring_emit, +- .cs_parse = &r300_cs_parse, +- .copy_blit = &r100_copy_blit, +- .copy_dma = &r200_copy_dma, +- .copy = &r100_copy_blit, +- .get_engine_clock = &radeon_legacy_get_engine_clock, +- .set_engine_clock = &radeon_legacy_set_engine_clock, +- .get_memory_clock = &radeon_legacy_get_memory_clock, +- .set_memory_clock = NULL, +- .get_pcie_lanes = NULL, +- .set_pcie_lanes = NULL, +- .set_clock_gating = &radeon_legacy_set_clock_gating, +- .set_surface_reg = r100_set_surface_reg, +- .clear_surface_reg = r100_clear_surface_reg, +- .bandwidth_update = &r100_bandwidth_update, +- .hpd_init = &r100_hpd_init, +- .hpd_fini = &r100_hpd_fini, +- .hpd_sense = &r100_hpd_sense, +- .hpd_set_polarity = &r100_hpd_set_polarity, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, +- .pm_misc = &r100_pm_misc, +- .pm_prepare = &r100_pm_prepare, +- .pm_finish = &r100_pm_finish, +- .pm_init_profile = &r100_pm_init_profile, +- .pm_get_dynpm_state = &r100_pm_get_dynpm_state, +- .pre_page_flip = &r100_pre_page_flip, +- .page_flip = &r100_page_flip, +- .post_page_flip = &r100_post_page_flip, ++ .mc_wait_for_idle = &rs400_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &rs400_gart_tlb_flush, ++ .set_page = &rs400_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r100_ring_ib_execute, ++ .emit_fence = &r300_fence_ring_emit, ++ .emit_semaphore = &r100_semaphore_ring_emit, ++ .cs_parse = &r300_cs_parse, ++ .ring_start = &r300_ring_start, ++ .ring_test = &r100_ring_test, ++ .ib_test = &r100_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &r100_irq_set, ++ .process = &r100_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &r100_bandwidth_update, ++ .get_vblank_counter = &r100_get_vblank_counter, ++ .wait_for_vblank = &r100_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r100_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = &r200_copy_dma, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r100_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r100_set_surface_reg, ++ .clear_reg = r100_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &r100_hpd_init, ++ .fini = &r100_hpd_fini, ++ .sense = &r100_hpd_sense, ++ .set_polarity = &r100_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &r100_pm_misc, ++ .prepare = &r100_pm_prepare, ++ .finish = &r100_pm_finish, ++ .init_profile = &r100_pm_init_profile, ++ .get_dynpm_state = &r100_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_legacy_get_engine_clock, ++ .set_engine_clock = &radeon_legacy_set_engine_clock, ++ .get_memory_clock = &radeon_legacy_get_memory_clock, ++ .set_memory_clock = NULL, ++ .get_pcie_lanes = NULL, ++ .set_pcie_lanes = NULL, ++ .set_clock_gating = &radeon_legacy_set_clock_gating, ++ }, ++ .pflip = { ++ .pre_page_flip = &r100_pre_page_flip, ++ .page_flip = &r100_page_flip, ++ .post_page_flip = &r100_post_page_flip, ++ }, + }; + + static struct radeon_asic rs600_asic = { +@@ -422,44 +580,70 @@ static struct radeon_asic rs600_asic = { + .vga_set_state = &r100_vga_set_state, + .gpu_is_lockup = &r300_gpu_is_lockup, + .asic_reset = &rs600_asic_reset, +- .gart_tlb_flush = &rs600_gart_tlb_flush, +- .gart_set_page = &rs600_gart_set_page, +- .cp_commit = &r100_cp_commit, +- .ring_start = &r300_ring_start, +- .ring_test = &r100_ring_test, +- .ring_ib_execute = &r100_ring_ib_execute, +- .irq_set = &rs600_irq_set, +- .irq_process = &rs600_irq_process, +- .get_vblank_counter = &rs600_get_vblank_counter, +- .fence_ring_emit = &r300_fence_ring_emit, +- .cs_parse = &r300_cs_parse, +- .copy_blit = &r100_copy_blit, +- .copy_dma = &r200_copy_dma, +- .copy = &r100_copy_blit, +- .get_engine_clock = &radeon_atom_get_engine_clock, +- .set_engine_clock = &radeon_atom_set_engine_clock, +- .get_memory_clock = &radeon_atom_get_memory_clock, +- .set_memory_clock = &radeon_atom_set_memory_clock, +- .get_pcie_lanes = NULL, +- .set_pcie_lanes = NULL, +- .set_clock_gating = &radeon_atom_set_clock_gating, +- .set_surface_reg = r100_set_surface_reg, +- .clear_surface_reg = r100_clear_surface_reg, +- .bandwidth_update = &rs600_bandwidth_update, +- .hpd_init = &rs600_hpd_init, +- .hpd_fini = &rs600_hpd_fini, +- .hpd_sense = &rs600_hpd_sense, +- .hpd_set_polarity = &rs600_hpd_set_polarity, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, +- .pm_misc = &rs600_pm_misc, +- .pm_prepare = &rs600_pm_prepare, +- .pm_finish = &rs600_pm_finish, +- .pm_init_profile = &r420_pm_init_profile, +- .pm_get_dynpm_state = &r100_pm_get_dynpm_state, +- .pre_page_flip = &rs600_pre_page_flip, +- .page_flip = &rs600_page_flip, +- .post_page_flip = &rs600_post_page_flip, ++ .mc_wait_for_idle = &rs600_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &rs600_gart_tlb_flush, ++ .set_page = &rs600_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r100_ring_ib_execute, ++ .emit_fence = &r300_fence_ring_emit, ++ .emit_semaphore = &r100_semaphore_ring_emit, ++ .cs_parse = &r300_cs_parse, ++ .ring_start = &r300_ring_start, ++ .ring_test = &r100_ring_test, ++ .ib_test = &r100_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &rs600_irq_set, ++ .process = &rs600_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &rs600_bandwidth_update, ++ .get_vblank_counter = &rs600_get_vblank_counter, ++ .wait_for_vblank = &avivo_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r100_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = &r200_copy_dma, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r100_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r100_set_surface_reg, ++ .clear_reg = r100_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &rs600_hpd_init, ++ .fini = &rs600_hpd_fini, ++ .sense = &rs600_hpd_sense, ++ .set_polarity = &rs600_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &rs600_pm_misc, ++ .prepare = &rs600_pm_prepare, ++ .finish = &rs600_pm_finish, ++ .init_profile = &r420_pm_init_profile, ++ .get_dynpm_state = &r100_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = &radeon_atom_get_memory_clock, ++ .set_memory_clock = &radeon_atom_set_memory_clock, ++ .get_pcie_lanes = NULL, ++ .set_pcie_lanes = NULL, ++ .set_clock_gating = &radeon_atom_set_clock_gating, ++ }, ++ .pflip = { ++ .pre_page_flip = &rs600_pre_page_flip, ++ .page_flip = &rs600_page_flip, ++ .post_page_flip = &rs600_post_page_flip, ++ }, + }; + + static struct radeon_asic rs690_asic = { +@@ -470,44 +654,70 @@ static struct radeon_asic rs690_asic = { + .vga_set_state = &r100_vga_set_state, + .gpu_is_lockup = &r300_gpu_is_lockup, + .asic_reset = &rs600_asic_reset, +- .gart_tlb_flush = &rs400_gart_tlb_flush, +- .gart_set_page = &rs400_gart_set_page, +- .cp_commit = &r100_cp_commit, +- .ring_start = &r300_ring_start, +- .ring_test = &r100_ring_test, +- .ring_ib_execute = &r100_ring_ib_execute, +- .irq_set = &rs600_irq_set, +- .irq_process = &rs600_irq_process, +- .get_vblank_counter = &rs600_get_vblank_counter, +- .fence_ring_emit = &r300_fence_ring_emit, +- .cs_parse = &r300_cs_parse, +- .copy_blit = &r100_copy_blit, +- .copy_dma = &r200_copy_dma, +- .copy = &r200_copy_dma, +- .get_engine_clock = &radeon_atom_get_engine_clock, +- .set_engine_clock = &radeon_atom_set_engine_clock, +- .get_memory_clock = &radeon_atom_get_memory_clock, +- .set_memory_clock = &radeon_atom_set_memory_clock, +- .get_pcie_lanes = NULL, +- .set_pcie_lanes = NULL, +- .set_clock_gating = &radeon_atom_set_clock_gating, +- .set_surface_reg = r100_set_surface_reg, +- .clear_surface_reg = r100_clear_surface_reg, +- .bandwidth_update = &rs690_bandwidth_update, +- .hpd_init = &rs600_hpd_init, +- .hpd_fini = &rs600_hpd_fini, +- .hpd_sense = &rs600_hpd_sense, +- .hpd_set_polarity = &rs600_hpd_set_polarity, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, +- .pm_misc = &rs600_pm_misc, +- .pm_prepare = &rs600_pm_prepare, +- .pm_finish = &rs600_pm_finish, +- .pm_init_profile = &r420_pm_init_profile, +- .pm_get_dynpm_state = &r100_pm_get_dynpm_state, +- .pre_page_flip = &rs600_pre_page_flip, +- .page_flip = &rs600_page_flip, +- .post_page_flip = &rs600_post_page_flip, ++ .mc_wait_for_idle = &rs690_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &rs400_gart_tlb_flush, ++ .set_page = &rs400_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r100_ring_ib_execute, ++ .emit_fence = &r300_fence_ring_emit, ++ .emit_semaphore = &r100_semaphore_ring_emit, ++ .cs_parse = &r300_cs_parse, ++ .ring_start = &r300_ring_start, ++ .ring_test = &r100_ring_test, ++ .ib_test = &r100_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &rs600_irq_set, ++ .process = &rs600_irq_process, ++ }, ++ .display = { ++ .get_vblank_counter = &rs600_get_vblank_counter, ++ .bandwidth_update = &rs690_bandwidth_update, ++ .wait_for_vblank = &avivo_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r100_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = &r200_copy_dma, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r200_copy_dma, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r100_set_surface_reg, ++ .clear_reg = r100_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &rs600_hpd_init, ++ .fini = &rs600_hpd_fini, ++ .sense = &rs600_hpd_sense, ++ .set_polarity = &rs600_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &rs600_pm_misc, ++ .prepare = &rs600_pm_prepare, ++ .finish = &rs600_pm_finish, ++ .init_profile = &r420_pm_init_profile, ++ .get_dynpm_state = &r100_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = &radeon_atom_get_memory_clock, ++ .set_memory_clock = &radeon_atom_set_memory_clock, ++ .get_pcie_lanes = NULL, ++ .set_pcie_lanes = NULL, ++ .set_clock_gating = &radeon_atom_set_clock_gating, ++ }, ++ .pflip = { ++ .pre_page_flip = &rs600_pre_page_flip, ++ .page_flip = &rs600_page_flip, ++ .post_page_flip = &rs600_post_page_flip, ++ }, + }; + + static struct radeon_asic rv515_asic = { +@@ -518,44 +728,70 @@ static struct radeon_asic rv515_asic = { + .vga_set_state = &r100_vga_set_state, + .gpu_is_lockup = &r300_gpu_is_lockup, + .asic_reset = &rs600_asic_reset, +- .gart_tlb_flush = &rv370_pcie_gart_tlb_flush, +- .gart_set_page = &rv370_pcie_gart_set_page, +- .cp_commit = &r100_cp_commit, +- .ring_start = &rv515_ring_start, +- .ring_test = &r100_ring_test, +- .ring_ib_execute = &r100_ring_ib_execute, +- .irq_set = &rs600_irq_set, +- .irq_process = &rs600_irq_process, +- .get_vblank_counter = &rs600_get_vblank_counter, +- .fence_ring_emit = &r300_fence_ring_emit, +- .cs_parse = &r300_cs_parse, +- .copy_blit = &r100_copy_blit, +- .copy_dma = &r200_copy_dma, +- .copy = &r100_copy_blit, +- .get_engine_clock = &radeon_atom_get_engine_clock, +- .set_engine_clock = &radeon_atom_set_engine_clock, +- .get_memory_clock = &radeon_atom_get_memory_clock, +- .set_memory_clock = &radeon_atom_set_memory_clock, +- .get_pcie_lanes = &rv370_get_pcie_lanes, +- .set_pcie_lanes = &rv370_set_pcie_lanes, +- .set_clock_gating = &radeon_atom_set_clock_gating, +- .set_surface_reg = r100_set_surface_reg, +- .clear_surface_reg = r100_clear_surface_reg, +- .bandwidth_update = &rv515_bandwidth_update, +- .hpd_init = &rs600_hpd_init, +- .hpd_fini = &rs600_hpd_fini, +- .hpd_sense = &rs600_hpd_sense, +- .hpd_set_polarity = &rs600_hpd_set_polarity, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, +- .pm_misc = &rs600_pm_misc, +- .pm_prepare = &rs600_pm_prepare, +- .pm_finish = &rs600_pm_finish, +- .pm_init_profile = &r420_pm_init_profile, +- .pm_get_dynpm_state = &r100_pm_get_dynpm_state, +- .pre_page_flip = &rs600_pre_page_flip, +- .page_flip = &rs600_page_flip, +- .post_page_flip = &rs600_post_page_flip, ++ .mc_wait_for_idle = &rv515_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &rv370_pcie_gart_tlb_flush, ++ .set_page = &rv370_pcie_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r100_ring_ib_execute, ++ .emit_fence = &r300_fence_ring_emit, ++ .emit_semaphore = &r100_semaphore_ring_emit, ++ .cs_parse = &r300_cs_parse, ++ .ring_start = &rv515_ring_start, ++ .ring_test = &r100_ring_test, ++ .ib_test = &r100_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &rs600_irq_set, ++ .process = &rs600_irq_process, ++ }, ++ .display = { ++ .get_vblank_counter = &rs600_get_vblank_counter, ++ .bandwidth_update = &rv515_bandwidth_update, ++ .wait_for_vblank = &avivo_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r100_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = &r200_copy_dma, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r100_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r100_set_surface_reg, ++ .clear_reg = r100_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &rs600_hpd_init, ++ .fini = &rs600_hpd_fini, ++ .sense = &rs600_hpd_sense, ++ .set_polarity = &rs600_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &rs600_pm_misc, ++ .prepare = &rs600_pm_prepare, ++ .finish = &rs600_pm_finish, ++ .init_profile = &r420_pm_init_profile, ++ .get_dynpm_state = &r100_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = &radeon_atom_get_memory_clock, ++ .set_memory_clock = &radeon_atom_set_memory_clock, ++ .get_pcie_lanes = &rv370_get_pcie_lanes, ++ .set_pcie_lanes = &rv370_set_pcie_lanes, ++ .set_clock_gating = &radeon_atom_set_clock_gating, ++ }, ++ .pflip = { ++ .pre_page_flip = &rs600_pre_page_flip, ++ .page_flip = &rs600_page_flip, ++ .post_page_flip = &rs600_post_page_flip, ++ }, + }; + + static struct radeon_asic r520_asic = { +@@ -566,44 +802,70 @@ static struct radeon_asic r520_asic = { + .vga_set_state = &r100_vga_set_state, + .gpu_is_lockup = &r300_gpu_is_lockup, + .asic_reset = &rs600_asic_reset, +- .gart_tlb_flush = &rv370_pcie_gart_tlb_flush, +- .gart_set_page = &rv370_pcie_gart_set_page, +- .cp_commit = &r100_cp_commit, +- .ring_start = &rv515_ring_start, +- .ring_test = &r100_ring_test, +- .ring_ib_execute = &r100_ring_ib_execute, +- .irq_set = &rs600_irq_set, +- .irq_process = &rs600_irq_process, +- .get_vblank_counter = &rs600_get_vblank_counter, +- .fence_ring_emit = &r300_fence_ring_emit, +- .cs_parse = &r300_cs_parse, +- .copy_blit = &r100_copy_blit, +- .copy_dma = &r200_copy_dma, +- .copy = &r100_copy_blit, +- .get_engine_clock = &radeon_atom_get_engine_clock, +- .set_engine_clock = &radeon_atom_set_engine_clock, +- .get_memory_clock = &radeon_atom_get_memory_clock, +- .set_memory_clock = &radeon_atom_set_memory_clock, +- .get_pcie_lanes = &rv370_get_pcie_lanes, +- .set_pcie_lanes = &rv370_set_pcie_lanes, +- .set_clock_gating = &radeon_atom_set_clock_gating, +- .set_surface_reg = r100_set_surface_reg, +- .clear_surface_reg = r100_clear_surface_reg, +- .bandwidth_update = &rv515_bandwidth_update, +- .hpd_init = &rs600_hpd_init, +- .hpd_fini = &rs600_hpd_fini, +- .hpd_sense = &rs600_hpd_sense, +- .hpd_set_polarity = &rs600_hpd_set_polarity, + .ioctl_wait_idle = NULL, + .gui_idle = &r100_gui_idle, +- .pm_misc = &rs600_pm_misc, +- .pm_prepare = &rs600_pm_prepare, +- .pm_finish = &rs600_pm_finish, +- .pm_init_profile = &r420_pm_init_profile, +- .pm_get_dynpm_state = &r100_pm_get_dynpm_state, +- .pre_page_flip = &rs600_pre_page_flip, +- .page_flip = &rs600_page_flip, +- .post_page_flip = &rs600_post_page_flip, ++ .mc_wait_for_idle = &r520_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &rv370_pcie_gart_tlb_flush, ++ .set_page = &rv370_pcie_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r100_ring_ib_execute, ++ .emit_fence = &r300_fence_ring_emit, ++ .emit_semaphore = &r100_semaphore_ring_emit, ++ .cs_parse = &r300_cs_parse, ++ .ring_start = &rv515_ring_start, ++ .ring_test = &r100_ring_test, ++ .ib_test = &r100_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &rs600_irq_set, ++ .process = &rs600_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &rv515_bandwidth_update, ++ .get_vblank_counter = &rs600_get_vblank_counter, ++ .wait_for_vblank = &avivo_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r100_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = &r200_copy_dma, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r100_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r100_set_surface_reg, ++ .clear_reg = r100_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &rs600_hpd_init, ++ .fini = &rs600_hpd_fini, ++ .sense = &rs600_hpd_sense, ++ .set_polarity = &rs600_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &rs600_pm_misc, ++ .prepare = &rs600_pm_prepare, ++ .finish = &rs600_pm_finish, ++ .init_profile = &r420_pm_init_profile, ++ .get_dynpm_state = &r100_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = &radeon_atom_get_memory_clock, ++ .set_memory_clock = &radeon_atom_set_memory_clock, ++ .get_pcie_lanes = &rv370_get_pcie_lanes, ++ .set_pcie_lanes = &rv370_set_pcie_lanes, ++ .set_clock_gating = &radeon_atom_set_clock_gating, ++ }, ++ .pflip = { ++ .pre_page_flip = &rs600_pre_page_flip, ++ .page_flip = &rs600_page_flip, ++ .post_page_flip = &rs600_post_page_flip, ++ }, + }; + + static struct radeon_asic r600_asic = { +@@ -611,46 +873,72 @@ static struct radeon_asic r600_asic = { + .fini = &r600_fini, + .suspend = &r600_suspend, + .resume = &r600_resume, +- .cp_commit = &r600_cp_commit, + .vga_set_state = &r600_vga_set_state, + .gpu_is_lockup = &r600_gpu_is_lockup, + .asic_reset = &r600_asic_reset, +- .gart_tlb_flush = &r600_pcie_gart_tlb_flush, +- .gart_set_page = &rs600_gart_set_page, +- .ring_test = &r600_ring_test, +- .ring_ib_execute = &r600_ring_ib_execute, +- .irq_set = &r600_irq_set, +- .irq_process = &r600_irq_process, +- .get_vblank_counter = &rs600_get_vblank_counter, +- .fence_ring_emit = &r600_fence_ring_emit, +- .cs_parse = &r600_cs_parse, +- .copy_blit = &r600_copy_blit, +- .copy_dma = NULL, +- .copy = &r600_copy_blit, +- .get_engine_clock = &radeon_atom_get_engine_clock, +- .set_engine_clock = &radeon_atom_set_engine_clock, +- .get_memory_clock = &radeon_atom_get_memory_clock, +- .set_memory_clock = &radeon_atom_set_memory_clock, +- .get_pcie_lanes = &r600_get_pcie_lanes, +- .set_pcie_lanes = &r600_set_pcie_lanes, +- .set_clock_gating = NULL, +- .set_surface_reg = r600_set_surface_reg, +- .clear_surface_reg = r600_clear_surface_reg, +- .bandwidth_update = &rv515_bandwidth_update, +- .hpd_init = &r600_hpd_init, +- .hpd_fini = &r600_hpd_fini, +- .hpd_sense = &r600_hpd_sense, +- .hpd_set_polarity = &r600_hpd_set_polarity, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, +- .pm_misc = &r600_pm_misc, +- .pm_prepare = &rs600_pm_prepare, +- .pm_finish = &rs600_pm_finish, +- .pm_init_profile = &r600_pm_init_profile, +- .pm_get_dynpm_state = &r600_pm_get_dynpm_state, +- .pre_page_flip = &rs600_pre_page_flip, +- .page_flip = &rs600_page_flip, +- .post_page_flip = &rs600_post_page_flip, ++ .mc_wait_for_idle = &r600_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &r600_pcie_gart_tlb_flush, ++ .set_page = &rs600_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r600_ring_ib_execute, ++ .emit_fence = &r600_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = &r600_cs_parse, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &r600_irq_set, ++ .process = &r600_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &rv515_bandwidth_update, ++ .get_vblank_counter = &rs600_get_vblank_counter, ++ .wait_for_vblank = &avivo_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r600_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = NULL, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r600_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r600_set_surface_reg, ++ .clear_reg = r600_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &r600_hpd_init, ++ .fini = &r600_hpd_fini, ++ .sense = &r600_hpd_sense, ++ .set_polarity = &r600_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &r600_pm_misc, ++ .prepare = &rs600_pm_prepare, ++ .finish = &rs600_pm_finish, ++ .init_profile = &r600_pm_init_profile, ++ .get_dynpm_state = &r600_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = &radeon_atom_get_memory_clock, ++ .set_memory_clock = &radeon_atom_set_memory_clock, ++ .get_pcie_lanes = &r600_get_pcie_lanes, ++ .set_pcie_lanes = &r600_set_pcie_lanes, ++ .set_clock_gating = NULL, ++ }, ++ .pflip = { ++ .pre_page_flip = &rs600_pre_page_flip, ++ .page_flip = &rs600_page_flip, ++ .post_page_flip = &rs600_post_page_flip, ++ }, + }; + + static struct radeon_asic rs780_asic = { +@@ -658,46 +946,72 @@ static struct radeon_asic rs780_asic = { + .fini = &r600_fini, + .suspend = &r600_suspend, + .resume = &r600_resume, +- .cp_commit = &r600_cp_commit, + .gpu_is_lockup = &r600_gpu_is_lockup, + .vga_set_state = &r600_vga_set_state, + .asic_reset = &r600_asic_reset, +- .gart_tlb_flush = &r600_pcie_gart_tlb_flush, +- .gart_set_page = &rs600_gart_set_page, +- .ring_test = &r600_ring_test, +- .ring_ib_execute = &r600_ring_ib_execute, +- .irq_set = &r600_irq_set, +- .irq_process = &r600_irq_process, +- .get_vblank_counter = &rs600_get_vblank_counter, +- .fence_ring_emit = &r600_fence_ring_emit, +- .cs_parse = &r600_cs_parse, +- .copy_blit = &r600_copy_blit, +- .copy_dma = NULL, +- .copy = &r600_copy_blit, +- .get_engine_clock = &radeon_atom_get_engine_clock, +- .set_engine_clock = &radeon_atom_set_engine_clock, +- .get_memory_clock = NULL, +- .set_memory_clock = NULL, +- .get_pcie_lanes = NULL, +- .set_pcie_lanes = NULL, +- .set_clock_gating = NULL, +- .set_surface_reg = r600_set_surface_reg, +- .clear_surface_reg = r600_clear_surface_reg, +- .bandwidth_update = &rs690_bandwidth_update, +- .hpd_init = &r600_hpd_init, +- .hpd_fini = &r600_hpd_fini, +- .hpd_sense = &r600_hpd_sense, +- .hpd_set_polarity = &r600_hpd_set_polarity, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, +- .pm_misc = &r600_pm_misc, +- .pm_prepare = &rs600_pm_prepare, +- .pm_finish = &rs600_pm_finish, +- .pm_init_profile = &rs780_pm_init_profile, +- .pm_get_dynpm_state = &r600_pm_get_dynpm_state, +- .pre_page_flip = &rs600_pre_page_flip, +- .page_flip = &rs600_page_flip, +- .post_page_flip = &rs600_post_page_flip, ++ .mc_wait_for_idle = &r600_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &r600_pcie_gart_tlb_flush, ++ .set_page = &rs600_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r600_ring_ib_execute, ++ .emit_fence = &r600_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = &r600_cs_parse, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &r600_irq_set, ++ .process = &r600_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &rs690_bandwidth_update, ++ .get_vblank_counter = &rs600_get_vblank_counter, ++ .wait_for_vblank = &avivo_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r600_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = NULL, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r600_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r600_set_surface_reg, ++ .clear_reg = r600_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &r600_hpd_init, ++ .fini = &r600_hpd_fini, ++ .sense = &r600_hpd_sense, ++ .set_polarity = &r600_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &r600_pm_misc, ++ .prepare = &rs600_pm_prepare, ++ .finish = &rs600_pm_finish, ++ .init_profile = &rs780_pm_init_profile, ++ .get_dynpm_state = &r600_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = NULL, ++ .set_memory_clock = NULL, ++ .get_pcie_lanes = NULL, ++ .set_pcie_lanes = NULL, ++ .set_clock_gating = NULL, ++ }, ++ .pflip = { ++ .pre_page_flip = &rs600_pre_page_flip, ++ .page_flip = &rs600_page_flip, ++ .post_page_flip = &rs600_post_page_flip, ++ }, + }; + + static struct radeon_asic rv770_asic = { +@@ -705,46 +1019,72 @@ static struct radeon_asic rv770_asic = { + .fini = &rv770_fini, + .suspend = &rv770_suspend, + .resume = &rv770_resume, +- .cp_commit = &r600_cp_commit, + .asic_reset = &r600_asic_reset, + .gpu_is_lockup = &r600_gpu_is_lockup, + .vga_set_state = &r600_vga_set_state, +- .gart_tlb_flush = &r600_pcie_gart_tlb_flush, +- .gart_set_page = &rs600_gart_set_page, +- .ring_test = &r600_ring_test, +- .ring_ib_execute = &r600_ring_ib_execute, +- .irq_set = &r600_irq_set, +- .irq_process = &r600_irq_process, +- .get_vblank_counter = &rs600_get_vblank_counter, +- .fence_ring_emit = &r600_fence_ring_emit, +- .cs_parse = &r600_cs_parse, +- .copy_blit = &r600_copy_blit, +- .copy_dma = NULL, +- .copy = &r600_copy_blit, +- .get_engine_clock = &radeon_atom_get_engine_clock, +- .set_engine_clock = &radeon_atom_set_engine_clock, +- .get_memory_clock = &radeon_atom_get_memory_clock, +- .set_memory_clock = &radeon_atom_set_memory_clock, +- .get_pcie_lanes = &r600_get_pcie_lanes, +- .set_pcie_lanes = &r600_set_pcie_lanes, +- .set_clock_gating = &radeon_atom_set_clock_gating, +- .set_surface_reg = r600_set_surface_reg, +- .clear_surface_reg = r600_clear_surface_reg, +- .bandwidth_update = &rv515_bandwidth_update, +- .hpd_init = &r600_hpd_init, +- .hpd_fini = &r600_hpd_fini, +- .hpd_sense = &r600_hpd_sense, +- .hpd_set_polarity = &r600_hpd_set_polarity, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, +- .pm_misc = &rv770_pm_misc, +- .pm_prepare = &rs600_pm_prepare, +- .pm_finish = &rs600_pm_finish, +- .pm_init_profile = &r600_pm_init_profile, +- .pm_get_dynpm_state = &r600_pm_get_dynpm_state, +- .pre_page_flip = &rs600_pre_page_flip, +- .page_flip = &rv770_page_flip, +- .post_page_flip = &rs600_post_page_flip, ++ .mc_wait_for_idle = &r600_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &r600_pcie_gart_tlb_flush, ++ .set_page = &rs600_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &r600_ring_ib_execute, ++ .emit_fence = &r600_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = &r600_cs_parse, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &r600_irq_set, ++ .process = &r600_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &rv515_bandwidth_update, ++ .get_vblank_counter = &rs600_get_vblank_counter, ++ .wait_for_vblank = &avivo_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r600_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = NULL, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r600_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r600_set_surface_reg, ++ .clear_reg = r600_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &r600_hpd_init, ++ .fini = &r600_hpd_fini, ++ .sense = &r600_hpd_sense, ++ .set_polarity = &r600_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &rv770_pm_misc, ++ .prepare = &rs600_pm_prepare, ++ .finish = &rs600_pm_finish, ++ .init_profile = &r600_pm_init_profile, ++ .get_dynpm_state = &r600_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = &radeon_atom_get_memory_clock, ++ .set_memory_clock = &radeon_atom_set_memory_clock, ++ .get_pcie_lanes = &r600_get_pcie_lanes, ++ .set_pcie_lanes = &r600_set_pcie_lanes, ++ .set_clock_gating = &radeon_atom_set_clock_gating, ++ }, ++ .pflip = { ++ .pre_page_flip = &rs600_pre_page_flip, ++ .page_flip = &rv770_page_flip, ++ .post_page_flip = &rs600_post_page_flip, ++ }, + }; + + static struct radeon_asic evergreen_asic = { +@@ -752,46 +1092,72 @@ static struct radeon_asic evergreen_asic = { + .fini = &evergreen_fini, + .suspend = &evergreen_suspend, + .resume = &evergreen_resume, +- .cp_commit = &r600_cp_commit, + .gpu_is_lockup = &evergreen_gpu_is_lockup, + .asic_reset = &evergreen_asic_reset, + .vga_set_state = &r600_vga_set_state, +- .gart_tlb_flush = &evergreen_pcie_gart_tlb_flush, +- .gart_set_page = &rs600_gart_set_page, +- .ring_test = &r600_ring_test, +- .ring_ib_execute = &evergreen_ring_ib_execute, +- .irq_set = &evergreen_irq_set, +- .irq_process = &evergreen_irq_process, +- .get_vblank_counter = &evergreen_get_vblank_counter, +- .fence_ring_emit = &r600_fence_ring_emit, +- .cs_parse = &evergreen_cs_parse, +- .copy_blit = &r600_copy_blit, +- .copy_dma = NULL, +- .copy = &r600_copy_blit, +- .get_engine_clock = &radeon_atom_get_engine_clock, +- .set_engine_clock = &radeon_atom_set_engine_clock, +- .get_memory_clock = &radeon_atom_get_memory_clock, +- .set_memory_clock = &radeon_atom_set_memory_clock, +- .get_pcie_lanes = &r600_get_pcie_lanes, +- .set_pcie_lanes = &r600_set_pcie_lanes, +- .set_clock_gating = NULL, +- .set_surface_reg = r600_set_surface_reg, +- .clear_surface_reg = r600_clear_surface_reg, +- .bandwidth_update = &evergreen_bandwidth_update, +- .hpd_init = &evergreen_hpd_init, +- .hpd_fini = &evergreen_hpd_fini, +- .hpd_sense = &evergreen_hpd_sense, +- .hpd_set_polarity = &evergreen_hpd_set_polarity, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, +- .pm_misc = &evergreen_pm_misc, +- .pm_prepare = &evergreen_pm_prepare, +- .pm_finish = &evergreen_pm_finish, +- .pm_init_profile = &r600_pm_init_profile, +- .pm_get_dynpm_state = &r600_pm_get_dynpm_state, +- .pre_page_flip = &evergreen_pre_page_flip, +- .page_flip = &evergreen_page_flip, +- .post_page_flip = &evergreen_post_page_flip, ++ .mc_wait_for_idle = &evergreen_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &evergreen_pcie_gart_tlb_flush, ++ .set_page = &rs600_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &evergreen_ring_ib_execute, ++ .emit_fence = &r600_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = &evergreen_cs_parse, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &evergreen_irq_set, ++ .process = &evergreen_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &evergreen_bandwidth_update, ++ .get_vblank_counter = &evergreen_get_vblank_counter, ++ .wait_for_vblank = &dce4_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r600_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = NULL, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r600_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r600_set_surface_reg, ++ .clear_reg = r600_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &evergreen_hpd_init, ++ .fini = &evergreen_hpd_fini, ++ .sense = &evergreen_hpd_sense, ++ .set_polarity = &evergreen_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &evergreen_pm_misc, ++ .prepare = &evergreen_pm_prepare, ++ .finish = &evergreen_pm_finish, ++ .init_profile = &r600_pm_init_profile, ++ .get_dynpm_state = &r600_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = &radeon_atom_get_memory_clock, ++ .set_memory_clock = &radeon_atom_set_memory_clock, ++ .get_pcie_lanes = &r600_get_pcie_lanes, ++ .set_pcie_lanes = &r600_set_pcie_lanes, ++ .set_clock_gating = NULL, ++ }, ++ .pflip = { ++ .pre_page_flip = &evergreen_pre_page_flip, ++ .page_flip = &evergreen_page_flip, ++ .post_page_flip = &evergreen_post_page_flip, ++ }, + }; + + static struct radeon_asic sumo_asic = { +@@ -799,46 +1165,72 @@ static struct radeon_asic sumo_asic = { + .fini = &evergreen_fini, + .suspend = &evergreen_suspend, + .resume = &evergreen_resume, +- .cp_commit = &r600_cp_commit, + .gpu_is_lockup = &evergreen_gpu_is_lockup, + .asic_reset = &evergreen_asic_reset, + .vga_set_state = &r600_vga_set_state, +- .gart_tlb_flush = &evergreen_pcie_gart_tlb_flush, +- .gart_set_page = &rs600_gart_set_page, +- .ring_test = &r600_ring_test, +- .ring_ib_execute = &evergreen_ring_ib_execute, +- .irq_set = &evergreen_irq_set, +- .irq_process = &evergreen_irq_process, +- .get_vblank_counter = &evergreen_get_vblank_counter, +- .fence_ring_emit = &r600_fence_ring_emit, +- .cs_parse = &evergreen_cs_parse, +- .copy_blit = &r600_copy_blit, +- .copy_dma = NULL, +- .copy = &r600_copy_blit, +- .get_engine_clock = &radeon_atom_get_engine_clock, +- .set_engine_clock = &radeon_atom_set_engine_clock, +- .get_memory_clock = NULL, +- .set_memory_clock = NULL, +- .get_pcie_lanes = NULL, +- .set_pcie_lanes = NULL, +- .set_clock_gating = NULL, +- .set_surface_reg = r600_set_surface_reg, +- .clear_surface_reg = r600_clear_surface_reg, +- .bandwidth_update = &evergreen_bandwidth_update, +- .hpd_init = &evergreen_hpd_init, +- .hpd_fini = &evergreen_hpd_fini, +- .hpd_sense = &evergreen_hpd_sense, +- .hpd_set_polarity = &evergreen_hpd_set_polarity, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, +- .pm_misc = &evergreen_pm_misc, +- .pm_prepare = &evergreen_pm_prepare, +- .pm_finish = &evergreen_pm_finish, +- .pm_init_profile = &sumo_pm_init_profile, +- .pm_get_dynpm_state = &r600_pm_get_dynpm_state, +- .pre_page_flip = &evergreen_pre_page_flip, +- .page_flip = &evergreen_page_flip, +- .post_page_flip = &evergreen_post_page_flip, ++ .mc_wait_for_idle = &evergreen_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &evergreen_pcie_gart_tlb_flush, ++ .set_page = &rs600_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &evergreen_ring_ib_execute, ++ .emit_fence = &r600_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = &evergreen_cs_parse, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ }, ++ }, ++ .irq = { ++ .set = &evergreen_irq_set, ++ .process = &evergreen_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &evergreen_bandwidth_update, ++ .get_vblank_counter = &evergreen_get_vblank_counter, ++ .wait_for_vblank = &dce4_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r600_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = NULL, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r600_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r600_set_surface_reg, ++ .clear_reg = r600_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &evergreen_hpd_init, ++ .fini = &evergreen_hpd_fini, ++ .sense = &evergreen_hpd_sense, ++ .set_polarity = &evergreen_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &evergreen_pm_misc, ++ .prepare = &evergreen_pm_prepare, ++ .finish = &evergreen_pm_finish, ++ .init_profile = &sumo_pm_init_profile, ++ .get_dynpm_state = &r600_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = NULL, ++ .set_memory_clock = NULL, ++ .get_pcie_lanes = NULL, ++ .set_pcie_lanes = NULL, ++ .set_clock_gating = NULL, ++ }, ++ .pflip = { ++ .pre_page_flip = &evergreen_pre_page_flip, ++ .page_flip = &evergreen_page_flip, ++ .post_page_flip = &evergreen_post_page_flip, ++ }, + }; + + static struct radeon_asic btc_asic = { +@@ -846,46 +1238,82 @@ static struct radeon_asic btc_asic = { + .fini = &evergreen_fini, + .suspend = &evergreen_suspend, + .resume = &evergreen_resume, +- .cp_commit = &r600_cp_commit, + .gpu_is_lockup = &evergreen_gpu_is_lockup, + .asic_reset = &evergreen_asic_reset, + .vga_set_state = &r600_vga_set_state, +- .gart_tlb_flush = &evergreen_pcie_gart_tlb_flush, +- .gart_set_page = &rs600_gart_set_page, +- .ring_test = &r600_ring_test, +- .ring_ib_execute = &evergreen_ring_ib_execute, +- .irq_set = &evergreen_irq_set, +- .irq_process = &evergreen_irq_process, +- .get_vblank_counter = &evergreen_get_vblank_counter, +- .fence_ring_emit = &r600_fence_ring_emit, +- .cs_parse = &evergreen_cs_parse, +- .copy_blit = &r600_copy_blit, +- .copy_dma = NULL, +- .copy = &r600_copy_blit, +- .get_engine_clock = &radeon_atom_get_engine_clock, +- .set_engine_clock = &radeon_atom_set_engine_clock, +- .get_memory_clock = &radeon_atom_get_memory_clock, +- .set_memory_clock = &radeon_atom_set_memory_clock, +- .get_pcie_lanes = NULL, +- .set_pcie_lanes = NULL, +- .set_clock_gating = NULL, +- .set_surface_reg = r600_set_surface_reg, +- .clear_surface_reg = r600_clear_surface_reg, +- .bandwidth_update = &evergreen_bandwidth_update, +- .hpd_init = &evergreen_hpd_init, +- .hpd_fini = &evergreen_hpd_fini, +- .hpd_sense = &evergreen_hpd_sense, +- .hpd_set_polarity = &evergreen_hpd_set_polarity, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, +- .pm_misc = &evergreen_pm_misc, +- .pm_prepare = &evergreen_pm_prepare, +- .pm_finish = &evergreen_pm_finish, +- .pm_init_profile = &r600_pm_init_profile, +- .pm_get_dynpm_state = &r600_pm_get_dynpm_state, +- .pre_page_flip = &evergreen_pre_page_flip, +- .page_flip = &evergreen_page_flip, +- .post_page_flip = &evergreen_post_page_flip, ++ .mc_wait_for_idle = &evergreen_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &evergreen_pcie_gart_tlb_flush, ++ .set_page = &rs600_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &evergreen_ring_ib_execute, ++ .emit_fence = &r600_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = &evergreen_cs_parse, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &evergreen_irq_set, ++ .process = &evergreen_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &evergreen_bandwidth_update, ++ .get_vblank_counter = &evergreen_get_vblank_counter, ++ .wait_for_vblank = &dce4_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r600_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = NULL, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r600_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r600_set_surface_reg, ++ .clear_reg = r600_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &evergreen_hpd_init, ++ .fini = &evergreen_hpd_fini, ++ .sense = &evergreen_hpd_sense, ++ .set_polarity = &evergreen_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &evergreen_pm_misc, ++ .prepare = &evergreen_pm_prepare, ++ .finish = &evergreen_pm_finish, ++ .init_profile = &r600_pm_init_profile, ++ .get_dynpm_state = &r600_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = &radeon_atom_get_memory_clock, ++ .set_memory_clock = &radeon_atom_set_memory_clock, ++ .get_pcie_lanes = NULL, ++ .set_pcie_lanes = NULL, ++ .set_clock_gating = NULL, ++ }, ++ .pflip = { ++ .pre_page_flip = &evergreen_pre_page_flip, ++ .page_flip = &evergreen_page_flip, ++ .post_page_flip = &evergreen_post_page_flip, ++ }, ++}; ++ ++static const struct radeon_vm_funcs cayman_vm_funcs = { ++ .init = &cayman_vm_init, ++ .fini = &cayman_vm_fini, ++ .bind = &cayman_vm_bind, ++ .unbind = &cayman_vm_unbind, ++ .tlb_flush = &cayman_vm_tlb_flush, ++ .page_flags = &cayman_vm_page_flags, ++ .set_page = &cayman_vm_set_page, + }; + + static struct radeon_asic cayman_asic = { +@@ -893,46 +1321,285 @@ static struct radeon_asic cayman_asic = { + .fini = &cayman_fini, + .suspend = &cayman_suspend, + .resume = &cayman_resume, +- .cp_commit = &r600_cp_commit, + .gpu_is_lockup = &cayman_gpu_is_lockup, + .asic_reset = &cayman_asic_reset, + .vga_set_state = &r600_vga_set_state, +- .gart_tlb_flush = &cayman_pcie_gart_tlb_flush, +- .gart_set_page = &rs600_gart_set_page, +- .ring_test = &r600_ring_test, +- .ring_ib_execute = &evergreen_ring_ib_execute, +- .irq_set = &evergreen_irq_set, +- .irq_process = &evergreen_irq_process, +- .get_vblank_counter = &evergreen_get_vblank_counter, +- .fence_ring_emit = &r600_fence_ring_emit, +- .cs_parse = &evergreen_cs_parse, +- .copy_blit = &r600_copy_blit, +- .copy_dma = NULL, +- .copy = &r600_copy_blit, +- .get_engine_clock = &radeon_atom_get_engine_clock, +- .set_engine_clock = &radeon_atom_set_engine_clock, +- .get_memory_clock = &radeon_atom_get_memory_clock, +- .set_memory_clock = &radeon_atom_set_memory_clock, +- .get_pcie_lanes = NULL, +- .set_pcie_lanes = NULL, +- .set_clock_gating = NULL, +- .set_surface_reg = r600_set_surface_reg, +- .clear_surface_reg = r600_clear_surface_reg, +- .bandwidth_update = &evergreen_bandwidth_update, +- .hpd_init = &evergreen_hpd_init, +- .hpd_fini = &evergreen_hpd_fini, +- .hpd_sense = &evergreen_hpd_sense, +- .hpd_set_polarity = &evergreen_hpd_set_polarity, + .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, +- .pm_misc = &evergreen_pm_misc, +- .pm_prepare = &evergreen_pm_prepare, +- .pm_finish = &evergreen_pm_finish, +- .pm_init_profile = &r600_pm_init_profile, +- .pm_get_dynpm_state = &r600_pm_get_dynpm_state, +- .pre_page_flip = &evergreen_pre_page_flip, +- .page_flip = &evergreen_page_flip, +- .post_page_flip = &evergreen_post_page_flip, ++ .mc_wait_for_idle = &evergreen_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &cayman_pcie_gart_tlb_flush, ++ .set_page = &rs600_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &cayman_ring_ib_execute, ++ .ib_parse = &evergreen_ib_parse, ++ .emit_fence = &cayman_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = &evergreen_cs_parse, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ }, ++ [CAYMAN_RING_TYPE_CP1_INDEX] = { ++ .ib_execute = &cayman_ring_ib_execute, ++ .ib_parse = &evergreen_ib_parse, ++ .emit_fence = &cayman_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = &evergreen_cs_parse, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ }, ++ [CAYMAN_RING_TYPE_CP2_INDEX] = { ++ .ib_execute = &cayman_ring_ib_execute, ++ .ib_parse = &evergreen_ib_parse, ++ .emit_fence = &cayman_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = &evergreen_cs_parse, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &evergreen_irq_set, ++ .process = &evergreen_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &evergreen_bandwidth_update, ++ .get_vblank_counter = &evergreen_get_vblank_counter, ++ .wait_for_vblank = &dce4_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r600_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = NULL, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r600_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r600_set_surface_reg, ++ .clear_reg = r600_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &evergreen_hpd_init, ++ .fini = &evergreen_hpd_fini, ++ .sense = &evergreen_hpd_sense, ++ .set_polarity = &evergreen_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &evergreen_pm_misc, ++ .prepare = &evergreen_pm_prepare, ++ .finish = &evergreen_pm_finish, ++ .init_profile = &r600_pm_init_profile, ++ .get_dynpm_state = &r600_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = &radeon_atom_get_memory_clock, ++ .set_memory_clock = &radeon_atom_set_memory_clock, ++ .get_pcie_lanes = NULL, ++ .set_pcie_lanes = NULL, ++ .set_clock_gating = NULL, ++ }, ++ .pflip = { ++ .pre_page_flip = &evergreen_pre_page_flip, ++ .page_flip = &evergreen_page_flip, ++ .post_page_flip = &evergreen_post_page_flip, ++ }, ++}; ++ ++static struct radeon_asic trinity_asic = { ++ .init = &cayman_init, ++ .fini = &cayman_fini, ++ .suspend = &cayman_suspend, ++ .resume = &cayman_resume, ++ .gpu_is_lockup = &cayman_gpu_is_lockup, ++ .asic_reset = &cayman_asic_reset, ++ .vga_set_state = &r600_vga_set_state, ++ .ioctl_wait_idle = r600_ioctl_wait_idle, ++ .gui_idle = &r600_gui_idle, ++ .mc_wait_for_idle = &evergreen_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &cayman_pcie_gart_tlb_flush, ++ .set_page = &rs600_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &cayman_ring_ib_execute, ++ .ib_parse = &evergreen_ib_parse, ++ .emit_fence = &cayman_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = &evergreen_cs_parse, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ }, ++ [CAYMAN_RING_TYPE_CP1_INDEX] = { ++ .ib_execute = &cayman_ring_ib_execute, ++ .ib_parse = &evergreen_ib_parse, ++ .emit_fence = &cayman_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = &evergreen_cs_parse, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ }, ++ [CAYMAN_RING_TYPE_CP2_INDEX] = { ++ .ib_execute = &cayman_ring_ib_execute, ++ .ib_parse = &evergreen_ib_parse, ++ .emit_fence = &cayman_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = &evergreen_cs_parse, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &evergreen_irq_set, ++ .process = &evergreen_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &dce6_bandwidth_update, ++ .get_vblank_counter = &evergreen_get_vblank_counter, ++ .wait_for_vblank = &dce4_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = &r600_copy_blit, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = NULL, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = &r600_copy_blit, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r600_set_surface_reg, ++ .clear_reg = r600_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &evergreen_hpd_init, ++ .fini = &evergreen_hpd_fini, ++ .sense = &evergreen_hpd_sense, ++ .set_polarity = &evergreen_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &evergreen_pm_misc, ++ .prepare = &evergreen_pm_prepare, ++ .finish = &evergreen_pm_finish, ++ .init_profile = &sumo_pm_init_profile, ++ .get_dynpm_state = &r600_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = NULL, ++ .set_memory_clock = NULL, ++ .get_pcie_lanes = NULL, ++ .set_pcie_lanes = NULL, ++ .set_clock_gating = NULL, ++ }, ++ .pflip = { ++ .pre_page_flip = &evergreen_pre_page_flip, ++ .page_flip = &evergreen_page_flip, ++ .post_page_flip = &evergreen_post_page_flip, ++ }, ++}; ++ ++static const struct radeon_vm_funcs si_vm_funcs = { ++ .init = &si_vm_init, ++ .fini = &si_vm_fini, ++ .bind = &si_vm_bind, ++ .unbind = &si_vm_unbind, ++ .tlb_flush = &si_vm_tlb_flush, ++ .page_flags = &cayman_vm_page_flags, ++ .set_page = &cayman_vm_set_page, ++}; ++ ++static struct radeon_asic si_asic = { ++ .init = &si_init, ++ .fini = &si_fini, ++ .suspend = &si_suspend, ++ .resume = &si_resume, ++ .gpu_is_lockup = &si_gpu_is_lockup, ++ .asic_reset = &si_asic_reset, ++ .vga_set_state = &r600_vga_set_state, ++ .ioctl_wait_idle = r600_ioctl_wait_idle, ++ .gui_idle = &r600_gui_idle, ++ .mc_wait_for_idle = &evergreen_mc_wait_for_idle, ++ .gart = { ++ .tlb_flush = &si_pcie_gart_tlb_flush, ++ .set_page = &rs600_gart_set_page, ++ }, ++ .ring = { ++ [RADEON_RING_TYPE_GFX_INDEX] = { ++ .ib_execute = &si_ring_ib_execute, ++ .ib_parse = &si_ib_parse, ++ .emit_fence = &si_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = NULL, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ }, ++ [CAYMAN_RING_TYPE_CP1_INDEX] = { ++ .ib_execute = &si_ring_ib_execute, ++ .ib_parse = &si_ib_parse, ++ .emit_fence = &si_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = NULL, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ }, ++ [CAYMAN_RING_TYPE_CP2_INDEX] = { ++ .ib_execute = &si_ring_ib_execute, ++ .ib_parse = &si_ib_parse, ++ .emit_fence = &si_fence_ring_emit, ++ .emit_semaphore = &r600_semaphore_ring_emit, ++ .cs_parse = NULL, ++ .ring_test = &r600_ring_test, ++ .ib_test = &r600_ib_test, ++ } ++ }, ++ .irq = { ++ .set = &si_irq_set, ++ .process = &si_irq_process, ++ }, ++ .display = { ++ .bandwidth_update = &dce6_bandwidth_update, ++ .get_vblank_counter = &evergreen_get_vblank_counter, ++ .wait_for_vblank = &dce4_wait_for_vblank, ++ }, ++ .copy = { ++ .blit = NULL, ++ .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .dma = NULL, ++ .dma_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ .copy = NULL, ++ .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, ++ }, ++ .surface = { ++ .set_reg = r600_set_surface_reg, ++ .clear_reg = r600_clear_surface_reg, ++ }, ++ .hpd = { ++ .init = &evergreen_hpd_init, ++ .fini = &evergreen_hpd_fini, ++ .sense = &evergreen_hpd_sense, ++ .set_polarity = &evergreen_hpd_set_polarity, ++ }, ++ .pm = { ++ .misc = &evergreen_pm_misc, ++ .prepare = &evergreen_pm_prepare, ++ .finish = &evergreen_pm_finish, ++ .init_profile = &sumo_pm_init_profile, ++ .get_dynpm_state = &r600_pm_get_dynpm_state, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = &radeon_atom_get_memory_clock, ++ .set_memory_clock = &radeon_atom_set_memory_clock, ++ .get_pcie_lanes = NULL, ++ .set_pcie_lanes = NULL, ++ .set_clock_gating = NULL, ++ }, ++ .pflip = { ++ .pre_page_flip = &evergreen_pre_page_flip, ++ .page_flip = &evergreen_page_flip, ++ .post_page_flip = &evergreen_post_page_flip, ++ }, + }; + + int radeon_asic_init(struct radeon_device *rdev) +@@ -974,10 +1641,10 @@ int radeon_asic_init(struct radeon_device *rdev) + rdev->asic = &r420_asic; + /* handle macs */ + if (rdev->bios == NULL) { +- rdev->asic->get_engine_clock = &radeon_legacy_get_engine_clock; +- rdev->asic->set_engine_clock = &radeon_legacy_set_engine_clock; +- rdev->asic->get_memory_clock = &radeon_legacy_get_memory_clock; +- rdev->asic->set_memory_clock = NULL; ++ rdev->asic->pm.get_engine_clock = &radeon_legacy_get_engine_clock; ++ rdev->asic->pm.set_engine_clock = &radeon_legacy_set_engine_clock; ++ rdev->asic->pm.get_memory_clock = &radeon_legacy_get_memory_clock; ++ rdev->asic->pm.set_memory_clock = NULL; + } + break; + case CHIP_RS400: +@@ -1050,6 +1717,21 @@ int radeon_asic_init(struct radeon_device *rdev) + rdev->asic = &cayman_asic; + /* set num crtcs */ + rdev->num_crtc = 6; ++ rdev->vm_manager.funcs = &cayman_vm_funcs; ++ break; ++ case CHIP_ARUBA: ++ rdev->asic = &trinity_asic; ++ /* set num crtcs */ ++ rdev->num_crtc = 4; ++ rdev->vm_manager.funcs = &cayman_vm_funcs; ++ break; ++ case CHIP_TAHITI: ++ case CHIP_PITCAIRN: ++ case CHIP_VERDE: ++ rdev->asic = &si_asic; ++ /* set num crtcs */ ++ rdev->num_crtc = 6; ++ rdev->vm_manager.funcs = &si_vm_funcs; + break; + default: + /* FIXME: not supported yet */ +@@ -1057,8 +1739,8 @@ int radeon_asic_init(struct radeon_device *rdev) + } + + if (rdev->flags & RADEON_IS_IGP) { +- rdev->asic->get_memory_clock = NULL; +- rdev->asic->set_memory_clock = NULL; ++ rdev->asic->pm.get_memory_clock = NULL; ++ rdev->asic->pm.set_memory_clock = NULL; + } + + return 0; +diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h +index 5aa6670..917e49c 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.h ++++ b/drivers/gpu/drm/radeon/radeon_asic.h +@@ -58,17 +58,20 @@ void r100_fini(struct radeon_device *rdev); + int r100_suspend(struct radeon_device *rdev); + int r100_resume(struct radeon_device *rdev); + void r100_vga_set_state(struct radeon_device *rdev, bool state); +-bool r100_gpu_is_lockup(struct radeon_device *rdev); ++bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); + int r100_asic_reset(struct radeon_device *rdev); + u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc); + void r100_pci_gart_tlb_flush(struct radeon_device *rdev); + int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); +-void r100_cp_commit(struct radeon_device *rdev); +-void r100_ring_start(struct radeon_device *rdev); ++void r100_ring_start(struct radeon_device *rdev, struct radeon_ring *ring); + int r100_irq_set(struct radeon_device *rdev); + int r100_irq_process(struct radeon_device *rdev); + void r100_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence); ++void r100_semaphore_ring_emit(struct radeon_device *rdev, ++ struct radeon_ring *cp, ++ struct radeon_semaphore *semaphore, ++ bool emit_wait); + int r100_cs_parse(struct radeon_cs_parser *p); + void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); + uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg); +@@ -83,7 +86,7 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg, + void r100_clear_surface_reg(struct radeon_device *rdev, int reg); + void r100_bandwidth_update(struct radeon_device *rdev); + void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); +-int r100_ring_test(struct radeon_device *rdev); ++int r100_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); + void r100_hpd_init(struct radeon_device *rdev); + void r100_hpd_fini(struct radeon_device *rdev); + bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); +@@ -101,12 +104,12 @@ void r100_pci_gart_disable(struct radeon_device *rdev); + int r100_debugfs_mc_info_init(struct radeon_device *rdev); + int r100_gui_wait_for_idle(struct radeon_device *rdev); + void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, +- struct radeon_cp *cp); ++ struct radeon_ring *cp); + bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, + struct r100_gpu_lockup *lockup, +- struct radeon_cp *cp); ++ struct radeon_ring *cp); + void r100_ib_fini(struct radeon_device *rdev); +-int r100_ib_init(struct radeon_device *rdev); ++int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); + void r100_irq_disable(struct radeon_device *rdev); + void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save); + void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save); +@@ -136,6 +139,8 @@ extern void r100_pm_get_dynpm_state(struct radeon_device *rdev); + extern void r100_pre_page_flip(struct radeon_device *rdev, int crtc); + extern u32 r100_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); + extern void r100_post_page_flip(struct radeon_device *rdev, int crtc); ++extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc); ++extern int r100_mc_wait_for_idle(struct radeon_device *rdev); + + /* + * r200,rv250,rs300,rv280 +@@ -154,9 +159,9 @@ extern int r300_init(struct radeon_device *rdev); + extern void r300_fini(struct radeon_device *rdev); + extern int r300_suspend(struct radeon_device *rdev); + extern int r300_resume(struct radeon_device *rdev); +-extern bool r300_gpu_is_lockup(struct radeon_device *rdev); ++extern bool r300_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); + extern int r300_asic_reset(struct radeon_device *rdev); +-extern void r300_ring_start(struct radeon_device *rdev); ++extern void r300_ring_start(struct radeon_device *rdev, struct radeon_ring *ring); + extern void r300_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence); + extern int r300_cs_parse(struct radeon_cs_parser *p); +@@ -173,6 +178,7 @@ extern int rv370_pcie_gart_init(struct radeon_device *rdev); + extern void rv370_pcie_gart_fini(struct radeon_device *rdev); + extern int rv370_pcie_gart_enable(struct radeon_device *rdev); + extern void rv370_pcie_gart_disable(struct radeon_device *rdev); ++extern int r300_mc_wait_for_idle(struct radeon_device *rdev); + + /* + * r420,r423,rv410 +@@ -203,6 +209,7 @@ int rs400_gart_enable(struct radeon_device *rdev); + void rs400_gart_adjust_size(struct radeon_device *rdev); + void rs400_gart_disable(struct radeon_device *rdev); + void rs400_gart_fini(struct radeon_device *rdev); ++extern int rs400_mc_wait_for_idle(struct radeon_device *rdev); + + /* + * rs600. +@@ -233,7 +240,8 @@ extern void rs600_pre_page_flip(struct radeon_device *rdev, int crtc); + extern u32 rs600_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); + extern void rs600_post_page_flip(struct radeon_device *rdev, int crtc); + void rs600_set_safe_registers(struct radeon_device *rdev); +- ++extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc); ++extern int rs600_mc_wait_for_idle(struct radeon_device *rdev); + + /* + * rs690,rs740 +@@ -248,6 +256,7 @@ void rs690_bandwidth_update(struct radeon_device *rdev); + void rs690_line_buffer_adjust(struct radeon_device *rdev, + struct drm_display_mode *mode1, + struct drm_display_mode *mode2); ++extern int rs690_mc_wait_for_idle(struct radeon_device *rdev); + + /* + * rv515 +@@ -261,7 +270,7 @@ int rv515_init(struct radeon_device *rdev); + void rv515_fini(struct radeon_device *rdev); + uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); + void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); +-void rv515_ring_start(struct radeon_device *rdev); ++void rv515_ring_start(struct radeon_device *rdev, struct radeon_ring *ring); + void rv515_bandwidth_update(struct radeon_device *rdev); + int rv515_resume(struct radeon_device *rdev); + int rv515_suspend(struct radeon_device *rdev); +@@ -272,13 +281,14 @@ void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save); + void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save); + void rv515_clock_startup(struct radeon_device *rdev); + void rv515_debugfs(struct radeon_device *rdev); +- ++int rv515_mc_wait_for_idle(struct radeon_device *rdev); + + /* + * r520,rv530,rv560,rv570,r580 + */ + int r520_init(struct radeon_device *rdev); + int r520_resume(struct radeon_device *rdev); ++int r520_mc_wait_for_idle(struct radeon_device *rdev); + + /* + * r600,rv610,rv630,rv620,rv635,rv670,rs780,rs880 +@@ -290,22 +300,25 @@ int r600_resume(struct radeon_device *rdev); + void r600_vga_set_state(struct radeon_device *rdev, bool state); + int r600_wb_init(struct radeon_device *rdev); + void r600_wb_fini(struct radeon_device *rdev); +-void r600_cp_commit(struct radeon_device *rdev); + void r600_pcie_gart_tlb_flush(struct radeon_device *rdev); + uint32_t r600_pciep_rreg(struct radeon_device *rdev, uint32_t reg); + void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); + int r600_cs_parse(struct radeon_cs_parser *p); + void r600_fence_ring_emit(struct radeon_device *rdev, + struct radeon_fence *fence); +-bool r600_gpu_is_lockup(struct radeon_device *rdev); ++void r600_semaphore_ring_emit(struct radeon_device *rdev, ++ struct radeon_ring *cp, ++ struct radeon_semaphore *semaphore, ++ bool emit_wait); ++bool r600_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); + int r600_asic_reset(struct radeon_device *rdev); + int r600_set_surface_reg(struct radeon_device *rdev, int reg, + uint32_t tiling_flags, uint32_t pitch, + uint32_t offset, uint32_t obj_size); + void r600_clear_surface_reg(struct radeon_device *rdev, int reg); +-int r600_ib_test(struct radeon_device *rdev); ++int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); + void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); +-int r600_ring_test(struct radeon_device *rdev); ++int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); + int r600_copy_blit(struct radeon_device *rdev, + uint64_t src_offset, uint64_t dst_offset, + unsigned num_gpu_pages, struct radeon_fence *fence); +@@ -325,7 +338,7 @@ extern int r600_get_pcie_lanes(struct radeon_device *rdev); + bool r600_card_posted(struct radeon_device *rdev); + void r600_cp_stop(struct radeon_device *rdev); + int r600_cp_start(struct radeon_device *rdev); +-void r600_ring_init(struct radeon_device *rdev, unsigned ring_size); ++void r600_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size); + int r600_cp_resume(struct radeon_device *rdev); + void r600_cp_fini(struct radeon_device *rdev); + int r600_count_pipe_bits(uint32_t val); +@@ -366,6 +379,7 @@ void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence) + void r600_kms_blit_copy(struct radeon_device *rdev, + u64 src_gpu_addr, u64 dst_gpu_addr, + unsigned num_gpu_pages); ++int r600_mc_wait_for_idle(struct radeon_device *rdev); + + /* + * rv770,rv730,rv710,rv740 +@@ -394,7 +408,7 @@ int evergreen_init(struct radeon_device *rdev); + void evergreen_fini(struct radeon_device *rdev); + int evergreen_suspend(struct radeon_device *rdev); + int evergreen_resume(struct radeon_device *rdev); +-bool evergreen_gpu_is_lockup(struct radeon_device *rdev); ++bool evergreen_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); + int evergreen_asic_reset(struct radeon_device *rdev); + void evergreen_bandwidth_update(struct radeon_device *rdev); + void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); +@@ -414,18 +428,59 @@ extern void sumo_pm_init_profile(struct radeon_device *rdev); + extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc); + extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); + extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc); ++extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc); + void evergreen_disable_interrupt_state(struct radeon_device *rdev); + int evergreen_blit_init(struct radeon_device *rdev); ++int evergreen_mc_wait_for_idle(struct radeon_device *rdev); + + /* + * cayman + */ ++void cayman_fence_ring_emit(struct radeon_device *rdev, ++ struct radeon_fence *fence); + void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev); + int cayman_init(struct radeon_device *rdev); + void cayman_fini(struct radeon_device *rdev); + int cayman_suspend(struct radeon_device *rdev); + int cayman_resume(struct radeon_device *rdev); +-bool cayman_gpu_is_lockup(struct radeon_device *rdev); ++bool cayman_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); + int cayman_asic_reset(struct radeon_device *rdev); ++void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); ++int cayman_vm_init(struct radeon_device *rdev); ++void cayman_vm_fini(struct radeon_device *rdev); ++int cayman_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm, int id); ++void cayman_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm); ++void cayman_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm); ++uint32_t cayman_vm_page_flags(struct radeon_device *rdev, ++ struct radeon_vm *vm, ++ uint32_t flags); ++void cayman_vm_set_page(struct radeon_device *rdev, struct radeon_vm *vm, ++ unsigned pfn, uint64_t addr, uint32_t flags); ++int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); ++ ++/* DCE6 - SI */ ++void dce6_bandwidth_update(struct radeon_device *rdev); ++ ++/* ++ * si ++ */ ++void si_fence_ring_emit(struct radeon_device *rdev, ++ struct radeon_fence *fence); ++void si_pcie_gart_tlb_flush(struct radeon_device *rdev); ++int si_init(struct radeon_device *rdev); ++void si_fini(struct radeon_device *rdev); ++int si_suspend(struct radeon_device *rdev); ++int si_resume(struct radeon_device *rdev); ++bool si_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); ++int si_asic_reset(struct radeon_device *rdev); ++void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); ++int si_irq_set(struct radeon_device *rdev); ++int si_irq_process(struct radeon_device *rdev); ++int si_vm_init(struct radeon_device *rdev); ++void si_vm_fini(struct radeon_device *rdev); ++int si_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm, int id); ++void si_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm); ++void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm); ++int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); + + #endif +diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c +index 24e9756..1ce6743 100644 +--- a/drivers/gpu/drm/radeon/radeon_atombios.c ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c +@@ -56,6 +56,10 @@ extern void + radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, + uint32_t supported_device); + ++/* local */ ++static int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, ++ u16 voltage_id, u16 *voltage); ++ + union atom_supported_devices { + struct _ATOM_SUPPORTED_DEVICES_INFO info; + struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2; +@@ -253,7 +257,9 @@ static struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device + + memset(&hpd, 0, sizeof(struct radeon_hpd)); + +- if (ASIC_IS_DCE4(rdev)) ++ if (ASIC_IS_DCE6(rdev)) ++ reg = SI_DC_GPIO_HPD_A; ++ else if (ASIC_IS_DCE4(rdev)) + reg = EVERGREEN_DC_GPIO_HPD_A; + else + reg = AVIVO_DC_GPIO_HPD_A; +@@ -1880,7 +1886,7 @@ static const char *thermal_controller_names[] = { + "adm1032", + "adm1030", + "max6649", +- "lm63", /* lm64 */ ++ "lm64", + "f75375", + "asc7xxx", + }; +@@ -1891,7 +1897,7 @@ static const char *pp_lib_thermal_controller_names[] = { + "adm1032", + "adm1030", + "max6649", +- "lm63", /* lm64 */ ++ "lm64", + "f75375", + "RV6xx", + "RV770", +@@ -1902,6 +1908,8 @@ static const char *pp_lib_thermal_controller_names[] = { + "emc2103", + "Sumo", + "Northern Islands", ++ "Southern Islands", ++ "lm96163", + }; + + union power_info { +@@ -1918,6 +1926,7 @@ union pplib_clock_info { + struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; + struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; + struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; ++ struct _ATOM_PPLIB_SI_CLOCK_INFO si; + }; + + union pplib_power_state { +@@ -2177,6 +2186,11 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_NI; ++ } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) { ++ DRM_INFO("Internal thermal controller %s fan control\n", ++ (controller->ucFanParameters & ++ ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); ++ rdev->pm.int_thermal_type = THERMAL_TYPE_SI; + } else if ((controller->ucType == + ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || + (controller->ucType == +@@ -2297,6 +2311,7 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, + union pplib_clock_info *clock_info) + { + u32 sclk, mclk; ++ u16 vddc; + + if (rdev->flags & RADEON_IS_IGP) { + if (rdev->family >= CHIP_PALM) { +@@ -2308,6 +2323,19 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, + sclk |= clock_info->rs780.ucLowEngineClockHigh << 16; + rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; + } ++ } else if (ASIC_IS_DCE6(rdev)) { ++ sclk = le16_to_cpu(clock_info->si.usEngineClockLow); ++ sclk |= clock_info->si.ucEngineClockHigh << 16; ++ mclk = le16_to_cpu(clock_info->si.usMemoryClockLow); ++ mclk |= clock_info->si.ucMemoryClockHigh << 16; ++ rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; ++ rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; ++ rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = ++ VOLTAGE_SW; ++ rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = ++ le16_to_cpu(clock_info->si.usVDDC); ++ rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci = ++ le16_to_cpu(clock_info->si.usVDDCI); + } else if (ASIC_IS_DCE4(rdev)) { + sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow); + sclk |= clock_info->evergreen.ucEngineClockHigh << 16; +@@ -2335,11 +2363,18 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, + } + + /* patch up vddc if necessary */ +- if (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage == 0xff01) { +- u16 vddc; +- +- if (radeon_atom_get_max_vddc(rdev, &vddc) == 0) ++ switch (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage) { ++ case ATOM_VIRTUAL_VOLTAGE_ID0: ++ case ATOM_VIRTUAL_VOLTAGE_ID1: ++ case ATOM_VIRTUAL_VOLTAGE_ID2: ++ case ATOM_VIRTUAL_VOLTAGE_ID3: ++ if (radeon_atom_get_max_vddc(rdev, VOLTAGE_TYPE_VDDC, ++ rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage, ++ &vddc) == 0) + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = vddc; ++ break; ++ default: ++ break; + } + + if (rdev->flags & RADEON_IS_IGP) { +@@ -2451,9 +2486,9 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) + int i, j, non_clock_array_index, clock_array_index; + int state_index = 0, mode_index = 0; + union pplib_clock_info *clock_info; +- struct StateArray *state_array; +- struct ClockInfoArray *clock_info_array; +- struct NonClockInfoArray *non_clock_info_array; ++ struct _StateArray *state_array; ++ struct _ClockInfoArray *clock_info_array; ++ struct _NonClockInfoArray *non_clock_info_array; + bool valid; + union power_info *power_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); +@@ -2467,13 +2502,13 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); + + radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); +- state_array = (struct StateArray *) ++ state_array = (struct _StateArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usStateArrayOffset)); +- clock_info_array = (struct ClockInfoArray *) ++ clock_info_array = (struct _ClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); +- non_clock_info_array = (struct NonClockInfoArray *) ++ non_clock_info_array = (struct _NonClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); + if (state_array->ucNumEntries == 0) +@@ -2499,7 +2534,7 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) + for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { + clock_array_index = power_state->v2.clockInfoIndex[j]; + clock_info = (union pplib_clock_info *) +- &clock_info_array->clockInfo[clock_array_index]; ++ &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; + valid = radeon_atombios_parse_pplib_clock_info(rdev, + state_index, mode_index, + clock_info); +@@ -2659,6 +2694,7 @@ union set_voltage { + struct _SET_VOLTAGE_PS_ALLOCATION alloc; + struct _SET_VOLTAGE_PARAMETERS v1; + struct _SET_VOLTAGE_PARAMETERS_V2 v2; ++ struct _SET_VOLTAGE_PARAMETERS_V1_3 v3; + }; + + void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type) +@@ -2685,6 +2721,11 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v + args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE; + args.v2.usVoltageLevel = cpu_to_le16(voltage_level); + break; ++ case 3: ++ args.v3.ucVoltageType = voltage_type; ++ args.v3.ucVoltageMode = ATOM_SET_VOLTAGE; ++ args.v3.usVoltageLevel = cpu_to_le16(voltage_level); ++ break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + return; +@@ -2693,8 +2734,8 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + } + +-int radeon_atom_get_max_vddc(struct radeon_device *rdev, +- u16 *voltage) ++static int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, ++ u16 voltage_id, u16 *voltage) + { + union set_voltage args; + int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); +@@ -2715,6 +2756,15 @@ int radeon_atom_get_max_vddc(struct radeon_device *rdev, + + *voltage = le16_to_cpu(args.v2.usVoltageLevel); + break; ++ case 3: ++ args.v3.ucVoltageType = voltage_type; ++ args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL; ++ args.v3.usVoltageLevel = cpu_to_le16(voltage_id); ++ ++ atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); ++ ++ *voltage = le16_to_cpu(args.v3.usVoltageLevel); ++ break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + return -EINVAL; +@@ -2970,6 +3020,20 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector, + bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5; + } + } ++ if ((radeon_encoder->devices & ATOM_DEVICE_DFP6_SUPPORT) && ++ (radeon_connector->devices & ATOM_DEVICE_DFP6_SUPPORT)) { ++ if (connected) { ++ DRM_DEBUG_KMS("DFP6 connected\n"); ++ bios_0_scratch |= ATOM_S0_DFP6; ++ bios_3_scratch |= ATOM_S3_DFP6_ACTIVE; ++ bios_6_scratch |= ATOM_S6_ACC_REQ_DFP6; ++ } else { ++ DRM_DEBUG_KMS("DFP6 disconnected\n"); ++ bios_0_scratch &= ~ATOM_S0_DFP6; ++ bios_3_scratch &= ~ATOM_S3_DFP6_ACTIVE; ++ bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP6; ++ } ++ } + + if (rdev->family >= CHIP_R600) { + WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch); +@@ -2990,6 +3054,9 @@ radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc) + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t bios_3_scratch; + ++ if (ASIC_IS_DCE4(rdev)) ++ return; ++ + if (rdev->family >= CHIP_R600) + bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH); + else +@@ -3042,6 +3109,9 @@ radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on) + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t bios_2_scratch; + ++ if (ASIC_IS_DCE4(rdev)) ++ return; ++ + if (rdev->family >= CHIP_R600) + bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); + else +diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c +index 2a2cf0b..428bce6 100644 +--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c ++++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c +@@ -202,6 +202,13 @@ static bool radeon_atpx_detect(void) + has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true); + } + ++ /* some newer PX laptops mark the dGPU as a non-VGA display device */ ++ while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { ++ vga_count++; ++ ++ has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true); ++ } ++ + if (has_atpx && vga_count == 2) { + acpi_get_name(radeon_atpx_priv.atpx_handle, ACPI_FULL_PATHNAME, &buffer); + printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", +diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c +index 441de38..89a0eec 100644 +--- a/drivers/gpu/drm/radeon/radeon_benchmark.c ++++ b/drivers/gpu/drm/radeon/radeon_benchmark.c +@@ -43,17 +43,19 @@ static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size, + + start_jiffies = jiffies; + for (i = 0; i < n; i++) { +- r = radeon_fence_create(rdev, &fence); +- if (r) +- return r; +- + switch (flag) { + case RADEON_BENCHMARK_COPY_DMA: ++ r = radeon_fence_create(rdev, &fence, radeon_copy_dma_ring_index(rdev)); ++ if (r) ++ return r; + r = radeon_copy_dma(rdev, saddr, daddr, + size / RADEON_GPU_PAGE_SIZE, + fence); + break; + case RADEON_BENCHMARK_COPY_BLIT: ++ r = radeon_fence_create(rdev, &fence, radeon_copy_blit_ring_index(rdev)); ++ if (r) ++ return r; + r = radeon_copy_blit(rdev, saddr, daddr, + size / RADEON_GPU_PAGE_SIZE, + fence); +@@ -129,7 +131,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, + /* r100 doesn't have dma engine so skip the test */ + /* also, VRAM-to-VRAM test doesn't make much sense for DMA */ + /* skip it as well if domains are the same */ +- if ((rdev->asic->copy_dma) && (sdomain != ddomain)) { ++ if ((rdev->asic->copy.dma) && (sdomain != ddomain)) { + time = radeon_benchmark_do_move(rdev, size, saddr, daddr, + RADEON_BENCHMARK_COPY_DMA, n); + if (time < 0) +@@ -139,7 +141,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, + sdomain, ddomain, "dma"); + } + +- if (rdev->asic->copy_blit) { ++ if (rdev->asic->copy.blit) { + time = radeon_benchmark_do_move(rdev, size, saddr, daddr, + RADEON_BENCHMARK_COPY_BLIT, n); + if (time < 0) +@@ -210,42 +212,42 @@ void radeon_benchmark(struct radeon_device *rdev, int test_number) + break; + case 3: + /* GTT to VRAM, buffer size sweep, powers of 2 */ +- for (i = 1; i <= 65536; i <<= 1) +- radeon_benchmark_move(rdev, i*1024, ++ for (i = 1; i <= 16384; i <<= 1) ++ radeon_benchmark_move(rdev, i * RADEON_GPU_PAGE_SIZE, + RADEON_GEM_DOMAIN_GTT, + RADEON_GEM_DOMAIN_VRAM); + break; + case 4: + /* VRAM to GTT, buffer size sweep, powers of 2 */ +- for (i = 1; i <= 65536; i <<= 1) +- radeon_benchmark_move(rdev, i*1024, ++ for (i = 1; i <= 16384; i <<= 1) ++ radeon_benchmark_move(rdev, i * RADEON_GPU_PAGE_SIZE, + RADEON_GEM_DOMAIN_VRAM, + RADEON_GEM_DOMAIN_GTT); + break; + case 5: + /* VRAM to VRAM, buffer size sweep, powers of 2 */ +- for (i = 1; i <= 65536; i <<= 1) +- radeon_benchmark_move(rdev, i*1024, ++ for (i = 1; i <= 16384; i <<= 1) ++ radeon_benchmark_move(rdev, i * RADEON_GPU_PAGE_SIZE, + RADEON_GEM_DOMAIN_VRAM, + RADEON_GEM_DOMAIN_VRAM); + break; + case 6: + /* GTT to VRAM, buffer size sweep, common modes */ +- for (i = 1; i < RADEON_BENCHMARK_COMMON_MODES_N; i++) ++ for (i = 0; i < RADEON_BENCHMARK_COMMON_MODES_N; i++) + radeon_benchmark_move(rdev, common_modes[i], + RADEON_GEM_DOMAIN_GTT, + RADEON_GEM_DOMAIN_VRAM); + break; + case 7: + /* VRAM to GTT, buffer size sweep, common modes */ +- for (i = 1; i < RADEON_BENCHMARK_COMMON_MODES_N; i++) ++ for (i = 0; i < RADEON_BENCHMARK_COMMON_MODES_N; i++) + radeon_benchmark_move(rdev, common_modes[i], + RADEON_GEM_DOMAIN_VRAM, + RADEON_GEM_DOMAIN_GTT); + break; + case 8: + /* VRAM to VRAM, buffer size sweep, common modes */ +- for (i = 1; i < RADEON_BENCHMARK_COMMON_MODES_N; i++) ++ for (i = 0; i < RADEON_BENCHMARK_COMMON_MODES_N; i++) + radeon_benchmark_move(rdev, common_modes[i], + RADEON_GEM_DOMAIN_VRAM, + RADEON_GEM_DOMAIN_VRAM); +diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c +index 6e98703..ef56e4e 100644 +--- a/drivers/gpu/drm/radeon/radeon_bios.c ++++ b/drivers/gpu/drm/radeon/radeon_bios.c +@@ -177,20 +177,6 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) + } + } + +- if (!found) { +- while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { +- dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); +- if (!dhandle) +- continue; +- +- status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); +- if (!ACPI_FAILURE(status)) { +- found = true; +- break; +- } +- } +- } +- + if (!found) + return false; + +diff --git a/drivers/gpu/drm/radeon/radeon_blit_common.h b/drivers/gpu/drm/radeon/radeon_blit_common.h +new file mode 100644 +index 0000000..4ecbe72 +--- /dev/null ++++ b/drivers/gpu/drm/radeon/radeon_blit_common.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright 2009 Advanced Micro Devices, Inc. ++ * Copyright 2009 Red Hat Inc. ++ * Copyright 2012 Alcatel-Lucent, Inc. ++ * ++ * 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 (including the next ++ * paragraph) 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 HOLDER(S) AND/OR ITS SUPPLIERS 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. ++ * ++ */ ++ ++#ifndef __RADEON_BLIT_COMMON_H__ ++ ++#define DI_PT_RECTLIST 0x11 ++#define DI_INDEX_SIZE_16_BIT 0x0 ++#define DI_SRC_SEL_AUTO_INDEX 0x2 ++ ++#define FMT_8 0x1 ++#define FMT_5_6_5 0x8 ++#define FMT_8_8_8_8 0x1a ++#define COLOR_8 0x1 ++#define COLOR_5_6_5 0x8 ++#define COLOR_8_8_8_8 0x1a ++ ++#define RECT_UNIT_H 32 ++#define RECT_UNIT_W (RADEON_GPU_PAGE_SIZE / 4 / RECT_UNIT_H) ++ ++#define __RADEON_BLIT_COMMON_H__ ++#endif +diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c +index b6e18c8..9c6b29a 100644 +--- a/drivers/gpu/drm/radeon/radeon_clocks.c ++++ b/drivers/gpu/drm/radeon/radeon_clocks.c +@@ -334,7 +334,7 @@ void radeon_get_clock_info(struct drm_device *dev) + + if (!rdev->clock.default_sclk) + rdev->clock.default_sclk = radeon_get_engine_clock(rdev); +- if ((!rdev->clock.default_mclk) && rdev->asic->get_memory_clock) ++ if ((!rdev->clock.default_mclk) && rdev->asic->pm.get_memory_clock) + rdev->clock.default_mclk = radeon_get_memory_clock(rdev); + + rdev->pm.current_sclk = rdev->clock.default_sclk; +@@ -633,7 +633,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) + tmp &= ~(R300_SCLK_FORCE_VAP); + tmp |= RADEON_SCLK_FORCE_CP; + WREG32_PLL(RADEON_SCLK_CNTL, tmp); +- udelay(15000); ++ mdelay(15); + + tmp = RREG32_PLL(R300_SCLK_CNTL2); + tmp &= ~(R300_SCLK_FORCE_TCL | +@@ -651,12 +651,12 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) + tmp |= (RADEON_ENGIN_DYNCLK_MODE | + (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT)); + WREG32_PLL(RADEON_CLK_PWRMGT_CNTL, tmp); +- udelay(15000); ++ mdelay(15); + + tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL); + tmp |= RADEON_SCLK_DYN_START_CNTL; + WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp); +- udelay(15000); ++ mdelay(15); + + /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200 + to lockup randomly, leave them as set by BIOS. +@@ -696,7 +696,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) + tmp |= RADEON_SCLK_MORE_FORCEON; + } + WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); +- udelay(15000); ++ mdelay(15); + } + + /* RV200::A11 A12, RV250::A11 A12 */ +@@ -709,7 +709,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) + tmp |= RADEON_TCL_BYPASS_DISABLE; + WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp); + } +- udelay(15000); ++ mdelay(15); + + /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK) */ + tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); +@@ -722,14 +722,14 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) + RADEON_PIXCLK_TMDS_ALWAYS_ONb); + + WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); +- udelay(15000); ++ mdelay(15); + + tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); + tmp |= (RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + + WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); +- udelay(15000); ++ mdelay(15); + } + } else { + /* Turn everything OFF (ForceON to everything) */ +@@ -861,7 +861,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) + } + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + +- udelay(16000); ++ mdelay(16); + + if ((rdev->family == CHIP_R300) || + (rdev->family == CHIP_R350)) { +@@ -870,7 +870,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + WREG32_PLL(R300_SCLK_CNTL2, tmp); +- udelay(16000); ++ mdelay(16); + } + + if (rdev->flags & RADEON_IS_IGP) { +@@ -878,7 +878,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) + tmp &= ~(RADEON_FORCEON_MCLKA | + RADEON_FORCEON_YCLKA); + WREG32_PLL(RADEON_MCLK_CNTL, tmp); +- udelay(16000); ++ mdelay(16); + } + + if ((rdev->family == CHIP_RV200) || +@@ -887,7 +887,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) + tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); + tmp |= RADEON_SCLK_MORE_FORCEON; + WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); +- udelay(16000); ++ mdelay(16); + } + + tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); +@@ -900,7 +900,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) + RADEON_PIXCLK_TMDS_ALWAYS_ONb); + + WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); +- udelay(16000); ++ mdelay(16); + + tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); + tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | +diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c +index 21e689d..b72eb50 100644 +--- a/drivers/gpu/drm/radeon/radeon_combios.c ++++ b/drivers/gpu/drm/radeon/radeon_combios.c +@@ -2927,7 +2927,7 @@ bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder) + case 4: + val = RBIOS16(index); + index += 2; +- udelay(val * 1000); ++ mdelay(val); + break; + case 6: + slave_addr = id & 0xff; +@@ -3126,7 +3126,7 @@ static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset) + udelay(150); + break; + case 2: +- udelay(1000); ++ mdelay(1); + break; + case 3: + while (tmp--) { +@@ -3157,13 +3157,13 @@ static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset) + /*mclk_cntl |= 0x00001111;*//* ??? */ + WREG32_PLL(RADEON_MCLK_CNTL, + mclk_cntl); +- udelay(10000); ++ mdelay(10); + #endif + WREG32_PLL + (RADEON_CLK_PWRMGT_CNTL, + tmp & + ~RADEON_CG_NO1_DEBUG_0); +- udelay(10000); ++ mdelay(10); + } + break; + default: +diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c +index 683cede..9184bbe 100644 +--- a/drivers/gpu/drm/radeon/radeon_connectors.c ++++ b/drivers/gpu/drm/radeon/radeon_connectors.c +@@ -846,6 +846,27 @@ static int radeon_dvi_get_modes(struct drm_connector *connector) + return ret; + } + ++static bool radeon_check_hpd_status_unchanged(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ struct radeon_device *rdev = dev->dev_private; ++ struct radeon_connector *radeon_connector = to_radeon_connector(connector); ++ enum drm_connector_status status; ++ ++ /* We only trust HPD on R600 and newer ASICS. */ ++ if (rdev->family >= CHIP_R600 ++ && radeon_connector->hpd.hpd != RADEON_HPD_NONE) { ++ if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) ++ status = connector_status_connected; ++ else ++ status = connector_status_disconnected; ++ if (connector->status == status) ++ return true; ++ } ++ ++ return false; ++} ++ + /* + * DVI is complicated + * Do a DDC probe, if DDC probe passes, get the full EDID so +@@ -870,6 +891,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) + enum drm_connector_status ret = connector_status_disconnected; + bool dret = false; + ++ if (!force && radeon_check_hpd_status_unchanged(connector)) ++ return connector->status; ++ + if (radeon_connector->ddc_bus) + dret = radeon_ddc_probe(radeon_connector, false); + if (dret) { +@@ -1080,7 +1104,7 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector, + (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) + return MODE_OK; + else if (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_A) { +- if (ASIC_IS_DCE3(rdev)) { ++ if (ASIC_IS_DCE6(rdev)) { + /* HDMI 1.3+ supports max clock of 340 Mhz */ + if (mode->clock > 340000) + return MODE_CLOCK_HIGH; +@@ -1140,13 +1164,23 @@ static int radeon_dp_get_modes(struct drm_connector *connector) + (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { + struct drm_display_mode *mode; + +- if (!radeon_dig_connector->edp_on) +- atombios_set_edp_panel_power(connector, +- ATOM_TRANSMITTER_ACTION_POWER_ON); +- ret = radeon_ddc_get_modes(radeon_connector); +- if (!radeon_dig_connector->edp_on) +- atombios_set_edp_panel_power(connector, +- ATOM_TRANSMITTER_ACTION_POWER_OFF); ++ if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { ++ if (!radeon_dig_connector->edp_on) ++ atombios_set_edp_panel_power(connector, ++ ATOM_TRANSMITTER_ACTION_POWER_ON); ++ ret = radeon_ddc_get_modes(radeon_connector); ++ if (!radeon_dig_connector->edp_on) ++ atombios_set_edp_panel_power(connector, ++ ATOM_TRANSMITTER_ACTION_POWER_OFF); ++ } else { ++ /* need to setup ddc on the bridge */ ++ if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) != ++ ENCODER_OBJECT_ID_NONE) { ++ if (encoder) ++ radeon_atom_ext_encoder_setup_ddc(encoder); ++ } ++ ret = radeon_ddc_get_modes(radeon_connector); ++ } + + if (ret > 0) { + if (encoder) { +@@ -1157,7 +1191,6 @@ static int radeon_dp_get_modes(struct drm_connector *connector) + return ret; + } + +- encoder = radeon_best_single_encoder(connector); + if (!encoder) + return 0; + +@@ -1264,6 +1297,9 @@ radeon_dp_detect(struct drm_connector *connector, bool force) + struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; + struct drm_encoder *encoder = radeon_best_single_encoder(connector); + ++ if (!force && radeon_check_hpd_status_unchanged(connector)) ++ return connector->status; ++ + if (radeon_connector->edid) { + kfree(radeon_connector->edid); + radeon_connector->edid = NULL; +diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c +index 72ae826..76ae327 100644 +--- a/drivers/gpu/drm/radeon/radeon_cp.c ++++ b/drivers/gpu/drm/radeon/radeon_cp.c +@@ -544,10 +544,7 @@ static int radeon_cp_init_microcode(drm_radeon_private_t *dev_priv) + + err = request_firmware(&dev_priv->me_fw, fw_name, &pdev->dev); + platform_device_unregister(pdev); +- if (err) { +- printk(KERN_ERR "radeon_cp: Failed to load firmware \"%s\"\n", +- fw_name); +- } else if (dev_priv->me_fw->size % 8) { ++ if (err == 0 && dev_priv->me_fw->size % 8) { + printk(KERN_ERR + "radeon_cp: Bogus length %zu in firmware \"%s\"\n", + dev_priv->me_fw->size, fw_name); +@@ -2115,6 +2112,8 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) + break; + } + ++ pci_set_master(dev->pdev); ++ + if (drm_pci_device_is_agp(dev)) + dev_priv->flags |= RADEON_IS_AGP; + else if (pci_is_pcie(dev->pdev)) +diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c +index 0ddc08c..f3ee360 100644 +--- a/drivers/gpu/drm/radeon/radeon_cs.c ++++ b/drivers/gpu/drm/radeon/radeon_cs.c +@@ -58,7 +58,7 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p) + + duplicate = false; + r = (struct drm_radeon_cs_reloc *)&chunk->kdata[i*4]; +- for (j = 0; j < p->nrelocs; j++) { ++ for (j = 0; j < i; j++) { + if (r->handle == p->relocs[j].handle) { + p->relocs_ptr[i] = &p->relocs[j]; + duplicate = true; +@@ -84,16 +84,88 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p) + p->relocs[i].flags = r->flags; + radeon_bo_list_add_object(&p->relocs[i].lobj, + &p->validated); +- } ++ ++ } else ++ p->relocs[i].handle = 0; + } + return radeon_bo_list_validate(&p->validated); + } + ++static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority) ++{ ++ p->priority = priority; ++ ++ switch (ring) { ++ default: ++ DRM_ERROR("unknown ring id: %d\n", ring); ++ return -EINVAL; ++ case RADEON_CS_RING_GFX: ++ p->ring = RADEON_RING_TYPE_GFX_INDEX; ++ break; ++ case RADEON_CS_RING_COMPUTE: ++ if (p->rdev->family >= CHIP_TAHITI) { ++ if (p->priority > 0) ++ p->ring = CAYMAN_RING_TYPE_CP1_INDEX; ++ else ++ p->ring = CAYMAN_RING_TYPE_CP2_INDEX; ++ } else ++ p->ring = RADEON_RING_TYPE_GFX_INDEX; ++ break; ++ } ++ return 0; ++} ++ ++static int radeon_cs_sync_rings(struct radeon_cs_parser *p) ++{ ++ bool sync_to_ring[RADEON_NUM_RINGS] = { }; ++ int i, r; ++ ++ for (i = 0; i < p->nrelocs; i++) { ++ if (!p->relocs[i].robj || !p->relocs[i].robj->tbo.sync_obj) ++ continue; ++ ++ if (!(p->relocs[i].flags & RADEON_RELOC_DONT_SYNC)) { ++ struct radeon_fence *fence = p->relocs[i].robj->tbo.sync_obj; ++ if (!radeon_fence_signaled(fence)) { ++ sync_to_ring[fence->ring] = true; ++ } ++ } ++ } ++ ++ for (i = 0; i < RADEON_NUM_RINGS; ++i) { ++ /* no need to sync to our own or unused rings */ ++ if (i == p->ring || !sync_to_ring[i] || !p->rdev->ring[i].ready) ++ continue; ++ ++ if (!p->ib->fence->semaphore) { ++ r = radeon_semaphore_create(p->rdev, &p->ib->fence->semaphore); ++ if (r) ++ return r; ++ } ++ ++ r = radeon_ring_lock(p->rdev, &p->rdev->ring[i], 3); ++ if (r) ++ return r; ++ radeon_semaphore_emit_signal(p->rdev, i, p->ib->fence->semaphore); ++ radeon_ring_unlock_commit(p->rdev, &p->rdev->ring[i]); ++ ++ r = radeon_ring_lock(p->rdev, &p->rdev->ring[p->ring], 3); ++ if (r) ++ return r; ++ radeon_semaphore_emit_wait(p->rdev, p->ring, p->ib->fence->semaphore); ++ radeon_ring_unlock_commit(p->rdev, &p->rdev->ring[p->ring]); ++ } ++ return 0; ++} ++ ++/* XXX: note that this is called from the legacy UMS CS ioctl as well */ + int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) + { + struct drm_radeon_cs *cs = data; + uint64_t *chunk_array_ptr; +- unsigned size, i, flags = 0; ++ unsigned size, i; ++ u32 ring = RADEON_CS_RING_GFX; ++ s32 priority = 0; + + INIT_LIST_HEAD(&p->validated); + +@@ -105,6 +177,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) + p->idx = 0; + p->chunk_ib_idx = -1; + p->chunk_relocs_idx = -1; ++ p->chunk_flags_idx = -1; ++ p->chunk_const_ib_idx = -1; + p->chunks_array = kcalloc(cs->num_chunks, sizeof(uint64_t), GFP_KERNEL); + if (p->chunks_array == NULL) { + return -ENOMEM; +@@ -114,6 +188,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) + sizeof(uint64_t)*cs->num_chunks)) { + return -EFAULT; + } ++ p->cs_flags = 0; + p->nchunks = cs->num_chunks; + p->chunks = kcalloc(p->nchunks, sizeof(struct radeon_cs_chunk), GFP_KERNEL); + if (p->chunks == NULL) { +@@ -142,16 +217,25 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) + if (p->chunks[i].length_dw == 0) + return -EINVAL; + } +- if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS && +- !p->chunks[i].length_dw) { +- return -EINVAL; ++ if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_CONST_IB) { ++ p->chunk_const_ib_idx = i; ++ /* zero length CONST IB isn't useful */ ++ if (p->chunks[i].length_dw == 0) ++ return -EINVAL; ++ } ++ if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) { ++ p->chunk_flags_idx = i; ++ /* zero length flags aren't useful */ ++ if (p->chunks[i].length_dw == 0) ++ return -EINVAL; + } + + p->chunks[i].length_dw = user_chunk.length_dw; + p->chunks[i].user_ptr = (void __user *)(unsigned long)user_chunk.chunk_data; + + cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data; +- if (p->chunks[i].chunk_id != RADEON_CHUNK_ID_IB) { ++ if ((p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) || ++ (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS)) { + size = p->chunks[i].length_dw * sizeof(uint32_t); + p->chunks[i].kdata = kmalloc(size, GFP_KERNEL); + if (p->chunks[i].kdata == NULL) { +@@ -162,31 +246,55 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) + return -EFAULT; + } + if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) { +- flags = p->chunks[i].kdata[0]; +- } +- } else { +- p->chunks[i].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL); +- p->chunks[i].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL); +- if (p->chunks[i].kpage[0] == NULL || p->chunks[i].kpage[1] == NULL) { +- kfree(p->chunks[i].kpage[0]); +- kfree(p->chunks[i].kpage[1]); +- p->chunks[i].kpage[0] = NULL; +- p->chunks[i].kpage[1] = NULL; +- return -ENOMEM; ++ p->cs_flags = p->chunks[i].kdata[0]; ++ if (p->chunks[i].length_dw > 1) ++ ring = p->chunks[i].kdata[1]; ++ if (p->chunks[i].length_dw > 2) ++ priority = (s32)p->chunks[i].kdata[2]; + } +- p->chunks[i].kpage_idx[0] = -1; +- p->chunks[i].kpage_idx[1] = -1; +- p->chunks[i].last_copied_page = -1; +- p->chunks[i].last_page_index = ((p->chunks[i].length_dw * 4) - 1) / PAGE_SIZE; + } + } +- if (p->chunks[p->chunk_ib_idx].length_dw > (16 * 1024)) { +- DRM_ERROR("cs IB too big: %d\n", +- p->chunks[p->chunk_ib_idx].length_dw); +- return -EINVAL; ++ ++ /* these are KMS only */ ++ if (p->rdev) { ++ if ((p->cs_flags & RADEON_CS_USE_VM) && ++ !p->rdev->vm_manager.enabled) { ++ DRM_ERROR("VM not active on asic!\n"); ++ return -EINVAL; ++ } ++ ++ /* we only support VM on SI+ */ ++ if ((p->rdev->family >= CHIP_TAHITI) && ++ ((p->cs_flags & RADEON_CS_USE_VM) == 0)) { ++ DRM_ERROR("VM required on SI+!\n"); ++ return -EINVAL; ++ } ++ ++ if (radeon_cs_get_ring(p, ring, priority)) ++ return -EINVAL; ++ } ++ ++ /* deal with non-vm */ ++ if ((p->chunk_ib_idx != -1) && ++ ((p->cs_flags & RADEON_CS_USE_VM) == 0) && ++ (p->chunks[p->chunk_ib_idx].chunk_id == RADEON_CHUNK_ID_IB)) { ++ if (p->chunks[p->chunk_ib_idx].length_dw > (16 * 1024)) { ++ DRM_ERROR("cs IB too big: %d\n", ++ p->chunks[p->chunk_ib_idx].length_dw); ++ return -EINVAL; ++ } ++ p->chunks[p->chunk_ib_idx].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL); ++ p->chunks[p->chunk_ib_idx].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL); ++ if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL || ++ p->chunks[p->chunk_ib_idx].kpage[1] == NULL) ++ return -ENOMEM; ++ p->chunks[p->chunk_ib_idx].kpage_idx[0] = -1; ++ p->chunks[p->chunk_ib_idx].kpage_idx[1] = -1; ++ p->chunks[p->chunk_ib_idx].last_copied_page = -1; ++ p->chunks[p->chunk_ib_idx].last_page_index = ++ ((p->chunks[p->chunk_ib_idx].length_dw * 4) - 1) / PAGE_SIZE; + } + +- p->keep_tiling_flags = (flags & RADEON_CS_KEEP_TILING_FLAGS) != 0; + return 0; + } + +@@ -228,14 +336,186 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error) + radeon_ib_free(parser->rdev, &parser->ib); + } + ++static int radeon_cs_ib_chunk(struct radeon_device *rdev, ++ struct radeon_cs_parser *parser) ++{ ++ struct radeon_cs_chunk *ib_chunk; ++ int r; ++ ++ if (parser->chunk_ib_idx == -1) ++ return 0; ++ ++ if (parser->cs_flags & RADEON_CS_USE_VM) ++ return 0; ++ ++ ib_chunk = &parser->chunks[parser->chunk_ib_idx]; ++ /* Copy the packet into the IB, the parser will read from the ++ * input memory (cached) and write to the IB (which can be ++ * uncached). ++ */ ++ r = radeon_ib_get(rdev, parser->ring, &parser->ib, ++ ib_chunk->length_dw * 4); ++ if (r) { ++ DRM_ERROR("Failed to get ib !\n"); ++ return r; ++ } ++ parser->ib->length_dw = ib_chunk->length_dw; ++ r = radeon_cs_parse(rdev, parser->ring, parser); ++ if (r || parser->parser_error) { ++ DRM_ERROR("Invalid command stream !\n"); ++ return r; ++ } ++ r = radeon_cs_finish_pages(parser); ++ if (r) { ++ DRM_ERROR("Invalid command stream !\n"); ++ return r; ++ } ++ r = radeon_cs_sync_rings(parser); ++ if (r) { ++ DRM_ERROR("Failed to synchronize rings !\n"); ++ } ++ parser->ib->vm_id = 0; ++ r = radeon_ib_schedule(rdev, parser->ib); ++ if (r) { ++ DRM_ERROR("Failed to schedule IB !\n"); ++ } ++ return r; ++} ++ ++static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser, ++ struct radeon_vm *vm) ++{ ++ struct radeon_bo_list *lobj; ++ struct radeon_bo *bo; ++ int r; ++ ++ list_for_each_entry(lobj, &parser->validated, tv.head) { ++ bo = lobj->bo; ++ r = radeon_vm_bo_update_pte(parser->rdev, vm, bo, &bo->tbo.mem); ++ if (r) { ++ return r; ++ } ++ } ++ return 0; ++} ++ ++static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, ++ struct radeon_cs_parser *parser) ++{ ++ struct radeon_cs_chunk *ib_chunk; ++ struct radeon_fpriv *fpriv = parser->filp->driver_priv; ++ struct radeon_vm *vm = &fpriv->vm; ++ int r; ++ ++ if (parser->chunk_ib_idx == -1) ++ return 0; ++ ++ if ((parser->cs_flags & RADEON_CS_USE_VM) == 0) ++ return 0; ++ ++ if ((rdev->family >= CHIP_TAHITI) && ++ (parser->chunk_const_ib_idx != -1)) { ++ ib_chunk = &parser->chunks[parser->chunk_const_ib_idx]; ++ if (ib_chunk->length_dw > RADEON_IB_VM_MAX_SIZE) { ++ DRM_ERROR("cs IB CONST too big: %d\n", ib_chunk->length_dw); ++ return -EINVAL; ++ } ++ r = radeon_ib_get(rdev, parser->ring, &parser->const_ib, ++ ib_chunk->length_dw * 4); ++ if (r) { ++ DRM_ERROR("Failed to get const ib !\n"); ++ return r; ++ } ++ parser->const_ib->is_const_ib = true; ++ parser->const_ib->length_dw = ib_chunk->length_dw; ++ /* Copy the packet into the IB */ ++ if (DRM_COPY_FROM_USER(parser->const_ib->ptr, ib_chunk->user_ptr, ++ ib_chunk->length_dw * 4)) { ++ return -EFAULT; ++ } ++ r = radeon_ring_ib_parse(rdev, parser->ring, parser->const_ib); ++ if (r) { ++ return r; ++ } ++ } ++ ++ ib_chunk = &parser->chunks[parser->chunk_ib_idx]; ++ if (ib_chunk->length_dw > RADEON_IB_VM_MAX_SIZE) { ++ DRM_ERROR("cs IB too big: %d\n", ib_chunk->length_dw); ++ return -EINVAL; ++ } ++ r = radeon_ib_get(rdev, parser->ring, &parser->ib, ++ ib_chunk->length_dw * 4); ++ if (r) { ++ DRM_ERROR("Failed to get ib !\n"); ++ return r; ++ } ++ parser->ib->length_dw = ib_chunk->length_dw; ++ /* Copy the packet into the IB */ ++ if (DRM_COPY_FROM_USER(parser->ib->ptr, ib_chunk->user_ptr, ++ ib_chunk->length_dw * 4)) { ++ return -EFAULT; ++ } ++ r = radeon_ring_ib_parse(rdev, parser->ring, parser->ib); ++ if (r) { ++ return r; ++ } ++ ++ mutex_lock(&vm->mutex); ++ r = radeon_vm_bind(rdev, vm); ++ if (r) { ++ goto out; ++ } ++ r = radeon_bo_vm_update_pte(parser, vm); ++ if (r) { ++ goto out; ++ } ++ r = radeon_cs_sync_rings(parser); ++ if (r) { ++ DRM_ERROR("Failed to synchronize rings !\n"); ++ } ++ ++ if ((rdev->family >= CHIP_TAHITI) && ++ (parser->chunk_const_ib_idx != -1)) { ++ parser->const_ib->vm_id = vm->id; ++ /* ib pool is bind at 0 in virtual address space to gpu_addr is the ++ * offset inside the pool bo ++ */ ++ parser->const_ib->gpu_addr = parser->const_ib->sa_bo.offset; ++ r = radeon_ib_schedule(rdev, parser->const_ib); ++ if (r) ++ goto out; ++ } ++ ++ parser->ib->vm_id = vm->id; ++ /* ib pool is bind at 0 in virtual address space to gpu_addr is the ++ * offset inside the pool bo ++ */ ++ parser->ib->gpu_addr = parser->ib->sa_bo.offset; ++ parser->ib->is_const_ib = false; ++ r = radeon_ib_schedule(rdev, parser->ib); ++out: ++ if (!r) { ++ if (vm->fence) { ++ radeon_fence_unref(&vm->fence); ++ } ++ vm->fence = radeon_fence_ref(parser->ib->fence); ++ } ++ mutex_unlock(&fpriv->vm.mutex); ++ return r; ++} ++ + int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) + { + struct radeon_device *rdev = dev->dev_private; + struct radeon_cs_parser parser; +- struct radeon_cs_chunk *ib_chunk; + int r; + + radeon_mutex_lock(&rdev->cs_mutex); ++ if (!rdev->accel_working) { ++ radeon_mutex_unlock(&rdev->cs_mutex); ++ return -EBUSY; ++ } + /* initialize parser */ + memset(&parser, 0, sizeof(struct radeon_cs_parser)); + parser.filp = filp; +@@ -249,13 +529,6 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) + radeon_mutex_unlock(&rdev->cs_mutex); + return r; + } +- r = radeon_ib_get(rdev, &parser.ib); +- if (r) { +- DRM_ERROR("Failed to get ib !\n"); +- radeon_cs_parser_fini(&parser, r); +- radeon_mutex_unlock(&rdev->cs_mutex); +- return r; +- } + r = radeon_cs_parser_relocs(&parser); + if (r) { + if (r != -ERESTARTSYS) +@@ -264,29 +537,15 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) + radeon_mutex_unlock(&rdev->cs_mutex); + return r; + } +- /* Copy the packet into the IB, the parser will read from the +- * input memory (cached) and write to the IB (which can be +- * uncached). */ +- ib_chunk = &parser.chunks[parser.chunk_ib_idx]; +- parser.ib->length_dw = ib_chunk->length_dw; +- r = radeon_cs_parse(&parser); +- if (r || parser.parser_error) { +- DRM_ERROR("Invalid command stream !\n"); +- radeon_cs_parser_fini(&parser, r); +- radeon_mutex_unlock(&rdev->cs_mutex); +- return r; +- } +- r = radeon_cs_finish_pages(&parser); ++ r = radeon_cs_ib_chunk(rdev, &parser); + if (r) { +- DRM_ERROR("Invalid command stream !\n"); +- radeon_cs_parser_fini(&parser, r); +- radeon_mutex_unlock(&rdev->cs_mutex); +- return r; ++ goto out; + } +- r = radeon_ib_schedule(rdev, parser.ib); ++ r = radeon_cs_ib_vm_chunk(rdev, &parser); + if (r) { +- DRM_ERROR("Failed to schedule IB !\n"); ++ goto out; + } ++out: + radeon_cs_parser_fini(&parser, r); + radeon_mutex_unlock(&rdev->cs_mutex); + return r; +diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c +index 2132109..8fb6f41 100644 +--- a/drivers/gpu/drm/radeon/radeon_cursor.c ++++ b/drivers/gpu/drm/radeon/radeon_cursor.c +@@ -197,7 +197,12 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, + + unpin: + if (radeon_crtc->cursor_bo) { +- radeon_gem_object_unpin(radeon_crtc->cursor_bo); ++ robj = gem_to_radeon_bo(radeon_crtc->cursor_bo); ++ ret = radeon_bo_reserve(robj, false); ++ if (likely(ret == 0)) { ++ radeon_bo_unpin(robj); ++ radeon_bo_unreserve(robj); ++ } + drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo); + } + +@@ -233,7 +238,8 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, + y = 0; + } + +- if (ASIC_IS_AVIVO(rdev)) { ++ /* fixed on DCE6 and newer */ ++ if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) { + int i = 0; + struct drm_crtc *crtc_p; + +diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c +index 8cde84b..2f555d7 100644 +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -89,6 +89,10 @@ static const char radeon_family_name[][16] = { + "TURKS", + "CAICOS", + "CAYMAN", ++ "ARUBA", ++ "TAHITI", ++ "PITCAIRN", ++ "VERDE", + "LAST", + }; + +@@ -237,8 +241,8 @@ int radeon_wb_init(struct radeon_device *rdev) + rdev->wb.use_event = true; + } + } +- /* always use writeback/events on NI */ +- if (ASIC_IS_DCE5(rdev)) { ++ /* always use writeback/events on NI, APUs */ ++ if (rdev->family >= CHIP_PALM) { + rdev->wb.enabled = true; + rdev->wb.use_event = true; + } +@@ -720,18 +724,25 @@ int radeon_device_init(struct radeon_device *rdev, + /* mutex initialization are all done here so we + * can recall function without having locking issues */ + radeon_mutex_init(&rdev->cs_mutex); +- mutex_init(&rdev->ib_pool.mutex); +- mutex_init(&rdev->cp.mutex); ++ radeon_mutex_init(&rdev->ib_pool.mutex); ++ for (i = 0; i < RADEON_NUM_RINGS; ++i) ++ mutex_init(&rdev->ring[i].mutex); + mutex_init(&rdev->dc_hw_i2c_mutex); + if (rdev->family >= CHIP_R600) + spin_lock_init(&rdev->ih.lock); + mutex_init(&rdev->gem.mutex); + mutex_init(&rdev->pm.mutex); + mutex_init(&rdev->vram_mutex); +- rwlock_init(&rdev->fence_drv.lock); ++ rwlock_init(&rdev->fence_lock); ++ rwlock_init(&rdev->semaphore_drv.lock); + INIT_LIST_HEAD(&rdev->gem.objects); + init_waitqueue_head(&rdev->irq.vblank_queue); + init_waitqueue_head(&rdev->irq.idle_queue); ++ INIT_LIST_HEAD(&rdev->semaphore_drv.bo); ++ /* initialize vm here */ ++ rdev->vm_manager.use_bitmap = 1; ++ rdev->vm_manager.max_pfn = 1 << 20; ++ INIT_LIST_HEAD(&rdev->vm_manager.lru_vm); + + /* Set asic functions */ + r = radeon_asic_init(rdev); +@@ -768,8 +779,14 @@ int radeon_device_init(struct radeon_device *rdev, + r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); + if (r) { + rdev->need_dma32 = true; ++ dma_bits = 32; + printk(KERN_WARNING "radeon: No suitable DMA available.\n"); + } ++ r = pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); ++ if (r) { ++ pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(32)); ++ printk(KERN_WARNING "radeon: No coherent DMA available.\n"); ++ } + + /* Registers mapping */ + /* TODO: block userspace mapping of io register */ +@@ -817,12 +834,18 @@ int radeon_device_init(struct radeon_device *rdev, + if (r) + return r; + } +- if (radeon_testing) { ++ if ((radeon_testing & 1)) { + if (rdev->accel_working) + radeon_test_moves(rdev); + else + DRM_INFO("radeon: acceleration disabled, skipping move tests\n"); + } ++ if ((radeon_testing & 2)) { ++ if (rdev->accel_working) ++ radeon_test_syncing(rdev); ++ else ++ DRM_INFO("radeon: acceleration disabled, skipping sync tests\n"); ++ } + if (radeon_benchmarking) { + if (rdev->accel_working) + radeon_benchmark(rdev, radeon_benchmarking); +@@ -832,6 +855,8 @@ int radeon_device_init(struct radeon_device *rdev, + return 0; + } + ++static void radeon_debugfs_remove_files(struct radeon_device *rdev); ++ + void radeon_device_fini(struct radeon_device *rdev) + { + DRM_INFO("radeon: finishing device.\n"); +@@ -846,6 +871,7 @@ void radeon_device_fini(struct radeon_device *rdev) + rdev->rio_mem = NULL; + iounmap(rdev->rmmio); + rdev->rmmio = NULL; ++ radeon_debugfs_remove_files(rdev); + } + + +@@ -857,7 +883,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) + struct radeon_device *rdev; + struct drm_crtc *crtc; + struct drm_connector *connector; +- int r; ++ int i, r; + + if (dev == NULL || dev->dev_private == NULL) { + return -ENODEV; +@@ -898,7 +924,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) + /* evict vram memory */ + radeon_bo_evict_vram(rdev); + /* wait for gpu to finish processing current batch */ +- radeon_fence_wait_last(rdev); ++ for (i = 0; i < RADEON_NUM_RINGS; i++) ++ radeon_fence_wait_last(rdev, i); + + radeon_save_bios_scratch_regs(rdev); + +@@ -947,9 +974,11 @@ int radeon_resume_kms(struct drm_device *dev) + radeon_fbdev_set_suspend(rdev, 0); + console_unlock(); + +- /* init dig PHYs */ +- if (rdev->is_atom_bios) ++ /* init dig PHYs, disp eng pll */ ++ if (rdev->is_atom_bios) { + radeon_atom_encoder_init(rdev); ++ radeon_atom_disp_eng_pll_init(rdev); ++ } + /* reset hpd state */ + radeon_hpd_init(rdev); + /* blat the mode back in */ +@@ -999,36 +1028,29 @@ int radeon_gpu_reset(struct radeon_device *rdev) + /* + * Debugfs + */ +-struct radeon_debugfs { +- struct drm_info_list *files; +- unsigned num_files; +-}; +-static struct radeon_debugfs _radeon_debugfs[RADEON_DEBUGFS_MAX_COMPONENTS]; +-static unsigned _radeon_debugfs_count = 0; +- + int radeon_debugfs_add_files(struct radeon_device *rdev, + struct drm_info_list *files, + unsigned nfiles) + { + unsigned i; + +- for (i = 0; i < _radeon_debugfs_count; i++) { +- if (_radeon_debugfs[i].files == files) { ++ for (i = 0; i < rdev->debugfs_count; i++) { ++ if (rdev->debugfs[i].files == files) { + /* Already registered */ + return 0; + } + } + +- i = _radeon_debugfs_count + 1; ++ i = rdev->debugfs_count + 1; + if (i > RADEON_DEBUGFS_MAX_COMPONENTS) { + DRM_ERROR("Reached maximum number of debugfs components.\n"); + DRM_ERROR("Report so we increase " + "RADEON_DEBUGFS_MAX_COMPONENTS.\n"); + return -EINVAL; + } +- _radeon_debugfs[_radeon_debugfs_count].files = files; +- _radeon_debugfs[_radeon_debugfs_count].num_files = nfiles; +- _radeon_debugfs_count = i; ++ rdev->debugfs[rdev->debugfs_count].files = files; ++ rdev->debugfs[rdev->debugfs_count].num_files = nfiles; ++ rdev->debugfs_count = i; + #if defined(CONFIG_DEBUG_FS) + drm_debugfs_create_files(files, nfiles, + rdev->ddev->control->debugfs_root, +@@ -1040,6 +1062,22 @@ int radeon_debugfs_add_files(struct radeon_device *rdev, + return 0; + } + ++static void radeon_debugfs_remove_files(struct radeon_device *rdev) ++{ ++#if defined(CONFIG_DEBUG_FS) ++ unsigned i; ++ ++ for (i = 0; i < rdev->debugfs_count; i++) { ++ drm_debugfs_remove_files(rdev->debugfs[i].files, ++ rdev->debugfs[i].num_files, ++ rdev->ddev->control); ++ drm_debugfs_remove_files(rdev->debugfs[i].files, ++ rdev->debugfs[i].num_files, ++ rdev->ddev->primary); ++ } ++#endif ++} ++ + #if defined(CONFIG_DEBUG_FS) + int radeon_debugfs_init(struct drm_minor *minor) + { +@@ -1048,11 +1086,5 @@ int radeon_debugfs_init(struct drm_minor *minor) + + void radeon_debugfs_cleanup(struct drm_minor *minor) + { +- unsigned i; +- +- for (i = 0; i < _radeon_debugfs_count; i++) { +- drm_debugfs_remove_files(_radeon_debugfs[i].files, +- _radeon_debugfs[i].num_files, minor); +- } + } + #endif +diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c +index ad5d774..adc9bfd 100644 +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -303,8 +303,17 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) + if (update_pending && + (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, + &vpos, &hpos)) && +- (vpos >=0) && +- (vpos < (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100)) { ++ ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || ++ (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) { ++ /* crtc didn't flip in this target vblank interval, ++ * but flip is pending in crtc. Based on the current ++ * scanout position we know that the current frame is ++ * (nearly) complete and the flip will (likely) ++ * complete before the start of the next frame. ++ */ ++ update_pending = 0; ++ } ++ if (update_pending) { + /* crtc didn't flip in this target vblank interval, + * but flip is pending in crtc. It will complete it + * in next vblank interval, so complete the flip at +@@ -393,7 +402,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, + DRM_ERROR("failed to reserve new rbo buffer before flip\n"); + goto pflip_cleanup; + } +- r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &base); ++ /* Only 27 bit offset for legacy CRTC */ ++ r = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, ++ ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base); + if (unlikely(r != 0)) { + radeon_bo_unreserve(rbo); + r = -EINVAL; +@@ -406,7 +417,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, + if (!ASIC_IS_AVIVO(rdev)) { + /* crtc offset is from display base addr not FB location */ + base -= radeon_crtc->legacy_display_base_addr; +- pitch_pixels = fb->pitch / (fb->bits_per_pixel / 8); ++ pitch_pixels = fb->pitches[0] / (fb->bits_per_pixel / 8); + + if (tiling_flags & RADEON_TILING_MACRO) { + if (ASIC_IS_R300(rdev)) { +@@ -522,7 +533,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index) + radeon_legacy_init_crtc(dev, radeon_crtc); + } + +-static const char *encoder_names[36] = { ++static const char *encoder_names[37] = { + "NONE", + "INTERNAL_LVDS", + "INTERNAL_TMDS1", +@@ -559,6 +570,7 @@ static const char *encoder_names[36] = { + "INTERNAL_UNIPHY2", + "NUTMEG", + "TRAVIS", ++ "INTERNAL_VCE" + }; + + static const char *connector_names[15] = { +@@ -1089,29 +1101,36 @@ static const struct drm_framebuffer_funcs radeon_fb_funcs = { + .create_handle = radeon_user_framebuffer_create_handle, + }; + +-void ++int + radeon_framebuffer_init(struct drm_device *dev, + struct radeon_framebuffer *rfb, +- struct drm_mode_fb_cmd *mode_cmd, ++ struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj) + { ++ int ret; + rfb->obj = obj; +- drm_framebuffer_init(dev, &rfb->base, &radeon_fb_funcs); ++ ret = drm_framebuffer_init(dev, &rfb->base, &radeon_fb_funcs); ++ if (ret) { ++ rfb->obj = NULL; ++ return ret; ++ } + drm_helper_mode_fill_fb_struct(&rfb->base, mode_cmd); ++ return 0; + } + + static struct drm_framebuffer * + radeon_user_framebuffer_create(struct drm_device *dev, + struct drm_file *file_priv, +- struct drm_mode_fb_cmd *mode_cmd) ++ struct drm_mode_fb_cmd2 *mode_cmd) + { + struct drm_gem_object *obj; + struct radeon_framebuffer *radeon_fb; ++ int ret; + +- obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); ++ obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); + if (obj == NULL) { + dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, " +- "can't create framebuffer\n", mode_cmd->handle); ++ "can't create framebuffer\n", mode_cmd->handles[0]); + return ERR_PTR(-ENOENT); + } + +@@ -1121,7 +1140,12 @@ radeon_user_framebuffer_create(struct drm_device *dev, + return ERR_PTR(-ENOMEM); + } + +- radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); ++ ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); ++ if (ret) { ++ kfree(radeon_fb); ++ drm_gem_object_unreference_unlocked(obj); ++ return ERR_PTR(ret); ++ } + + return &radeon_fb->base; + } +@@ -1137,11 +1161,6 @@ static const struct drm_mode_config_funcs radeon_mode_funcs = { + .output_poll_changed = radeon_output_poll_changed + }; + +-struct drm_prop_enum_list { +- int type; +- char *name; +-}; +- + static struct drm_prop_enum_list radeon_tmds_pll_enum_list[] = + { { 0, "driver" }, + { 1, "bios" }, +@@ -1166,86 +1185,53 @@ static struct drm_prop_enum_list radeon_underscan_enum_list[] = + + static int radeon_modeset_create_props(struct radeon_device *rdev) + { +- int i, sz; ++ int sz; + + if (rdev->is_atom_bios) { + rdev->mode_info.coherent_mode_property = +- drm_property_create(rdev->ddev, +- DRM_MODE_PROP_RANGE, +- "coherent", 2); ++ drm_property_create_range(rdev->ddev, 0 , "coherent", 0, 1); + if (!rdev->mode_info.coherent_mode_property) + return -ENOMEM; +- +- rdev->mode_info.coherent_mode_property->values[0] = 0; +- rdev->mode_info.coherent_mode_property->values[1] = 1; + } + + if (!ASIC_IS_AVIVO(rdev)) { + sz = ARRAY_SIZE(radeon_tmds_pll_enum_list); + rdev->mode_info.tmds_pll_property = +- drm_property_create(rdev->ddev, +- DRM_MODE_PROP_ENUM, +- "tmds_pll", sz); +- for (i = 0; i < sz; i++) { +- drm_property_add_enum(rdev->mode_info.tmds_pll_property, +- i, +- radeon_tmds_pll_enum_list[i].type, +- radeon_tmds_pll_enum_list[i].name); +- } ++ drm_property_create_enum(rdev->ddev, 0, ++ "tmds_pll", ++ radeon_tmds_pll_enum_list, sz); + } + + rdev->mode_info.load_detect_property = +- drm_property_create(rdev->ddev, +- DRM_MODE_PROP_RANGE, +- "load detection", 2); ++ drm_property_create_range(rdev->ddev, 0, "load detection", 0, 1); + if (!rdev->mode_info.load_detect_property) + return -ENOMEM; +- rdev->mode_info.load_detect_property->values[0] = 0; +- rdev->mode_info.load_detect_property->values[1] = 1; + + drm_mode_create_scaling_mode_property(rdev->ddev); + + sz = ARRAY_SIZE(radeon_tv_std_enum_list); + rdev->mode_info.tv_std_property = +- drm_property_create(rdev->ddev, +- DRM_MODE_PROP_ENUM, +- "tv standard", sz); +- for (i = 0; i < sz; i++) { +- drm_property_add_enum(rdev->mode_info.tv_std_property, +- i, +- radeon_tv_std_enum_list[i].type, +- radeon_tv_std_enum_list[i].name); +- } ++ drm_property_create_enum(rdev->ddev, 0, ++ "tv standard", ++ radeon_tv_std_enum_list, sz); + + sz = ARRAY_SIZE(radeon_underscan_enum_list); + rdev->mode_info.underscan_property = +- drm_property_create(rdev->ddev, +- DRM_MODE_PROP_ENUM, +- "underscan", sz); +- for (i = 0; i < sz; i++) { +- drm_property_add_enum(rdev->mode_info.underscan_property, +- i, +- radeon_underscan_enum_list[i].type, +- radeon_underscan_enum_list[i].name); +- } ++ drm_property_create_enum(rdev->ddev, 0, ++ "underscan", ++ radeon_underscan_enum_list, sz); + + rdev->mode_info.underscan_hborder_property = +- drm_property_create(rdev->ddev, +- DRM_MODE_PROP_RANGE, +- "underscan hborder", 2); ++ drm_property_create_range(rdev->ddev, 0, ++ "underscan hborder", 0, 128); + if (!rdev->mode_info.underscan_hborder_property) + return -ENOMEM; +- rdev->mode_info.underscan_hborder_property->values[0] = 0; +- rdev->mode_info.underscan_hborder_property->values[1] = 128; + + rdev->mode_info.underscan_vborder_property = +- drm_property_create(rdev->ddev, +- DRM_MODE_PROP_RANGE, +- "underscan vborder", 2); ++ drm_property_create_range(rdev->ddev, 0, ++ "underscan vborder", 0, 128); + if (!rdev->mode_info.underscan_vborder_property) + return -ENOMEM; +- rdev->mode_info.underscan_vborder_property->values[0] = 0; +- rdev->mode_info.underscan_vborder_property->values[1] = 128; + + return 0; + } +@@ -1291,6 +1277,9 @@ int radeon_modeset_init(struct radeon_device *rdev) + rdev->ddev->mode_config.max_height = 4096; + } + ++ rdev->ddev->mode_config.preferred_depth = 24; ++ rdev->ddev->mode_config.prefer_shadow = 1; ++ + rdev->ddev->mode_config.fb_base = rdev->mc.aper_base; + + ret = radeon_modeset_create_props(rdev); +@@ -1318,9 +1307,11 @@ int radeon_modeset_init(struct radeon_device *rdev) + return ret; + } + +- /* init dig PHYs */ +- if (rdev->is_atom_bios) ++ /* init dig PHYs, disp eng pll */ ++ if (rdev->is_atom_bios) { + radeon_atom_encoder_init(rdev); ++ radeon_atom_disp_eng_pll_init(rdev); ++ } + + /* initialize hpd */ + radeon_hpd_init(rdev); +diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c +index 71499fc..a504c05 100644 +--- a/drivers/gpu/drm/radeon/radeon_drv.c ++++ b/drivers/gpu/drm/radeon/radeon_drv.c +@@ -37,6 +37,8 @@ + #include "drm_pciids.h" + #include + #include ++#include ++#include + + + /* +@@ -54,9 +56,13 @@ + * 2.10.0 - fusion 2D tiling + * 2.11.0 - backend map, initial compute support for the CS checker + * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS ++ * 2.13.0 - virtual memory support, streamout ++ * 2.14.0 - add evergreen tiling informations ++ * 2.15.0 - add max_pipes query ++ * 2.16.0 - fix evergreen 2D tiled surface calculation + */ + #define KMS_DRIVER_MAJOR 2 +-#define KMS_DRIVER_MINOR 12 ++#define KMS_DRIVER_MINOR 16 + #define KMS_DRIVER_PATCHLEVEL 0 + int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); + int radeon_driver_unload_kms(struct drm_device *dev); +@@ -84,6 +90,10 @@ int radeon_dma_ioctl_kms(struct drm_device *dev, void *data, + struct drm_file *file_priv); + int radeon_gem_object_init(struct drm_gem_object *obj); + void radeon_gem_object_free(struct drm_gem_object *obj); ++int radeon_gem_object_open(struct drm_gem_object *obj, ++ struct drm_file *file_priv); ++void radeon_gem_object_close(struct drm_gem_object *obj, ++ struct drm_file *file_priv); + extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, + int *vpos, int *hpos); + extern struct drm_ioctl_desc radeon_ioctls_kms[]; +@@ -140,7 +150,7 @@ module_param_named(vramlimit, radeon_vram_limit, int, 0600); + MODULE_PARM_DESC(agpmode, "AGP Mode (-1 == PCI)"); + module_param_named(agpmode, radeon_agpmode, int, 0444); + +-MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32,64, etc)\n"); ++MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32, 64, etc)"); + module_param_named(gartsize, radeon_gart_size, int, 0600); + + MODULE_PARM_DESC(benchmark, "Run benchmark"); +@@ -206,6 +216,21 @@ static struct pci_device_id pciidlist[] = { + MODULE_DEVICE_TABLE(pci, pciidlist); + #endif + ++static const struct file_operations radeon_driver_old_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .mmap = drm_mmap, ++ .poll = drm_poll, ++ .fasync = drm_fasync, ++ .read = drm_read, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = radeon_compat_ioctl, ++#endif ++ .llseek = noop_llseek, ++}; ++ + static struct drm_driver driver_old = { + .driver_features = + DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | +@@ -232,21 +257,7 @@ static struct drm_driver driver_old = { + .reclaim_buffers = drm_core_reclaim_buffers, + .ioctls = radeon_ioctls, + .dma_ioctl = radeon_cp_buffers, +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = drm_ioctl, +- .mmap = drm_mmap, +- .poll = drm_poll, +- .fasync = drm_fasync, +- .read = drm_read, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = radeon_compat_ioctl, +-#endif +- .llseek = noop_llseek, +- }, +- ++ .fops = &radeon_driver_old_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, +@@ -257,6 +268,35 @@ static struct drm_driver driver_old = { + + static struct drm_driver kms_driver; + ++/* Test that /lib/firmware/radeon is a directory (or symlink to a ++ * directory). We could try to match the udev search path, but let's ++ * assume people take the easy route and install ++ * firmware-linux-nonfree. ++ */ ++static bool __devinit radeon_firmware_installed(void) ++{ ++ struct path path; ++ ++ if (kern_path("/lib/firmware/radeon", LOOKUP_DIRECTORY | LOOKUP_FOLLOW, ++ &path) == 0) { ++ path_put(&path); ++ return true; ++ } ++ ++ return false; ++} ++ ++static int __devinit ++radeon_ums_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ if (!radeon_firmware_installed()) { ++ DRM_ERROR("radeon DRM requires firmware-linux-nonfree.\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ + static void radeon_kick_out_firmware_fb(struct pci_dev *pdev) + { + struct apertures_struct *ap; +@@ -276,6 +316,12 @@ static void radeon_kick_out_firmware_fb(struct pci_dev *pdev) + static int __devinit + radeon_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + { ++ if ((ent->driver_data & RADEON_FAMILY_MASK) >= CHIP_R600 && ++ !radeon_firmware_installed()) { ++ DRM_ERROR("radeon kernel modesetting for R600 or later requires firmware-linux-nonfree.\n"); ++ return -ENODEV; ++ } ++ + /* Get rid of things like offb */ + radeon_kick_out_firmware_fb(pdev); + +@@ -304,6 +350,20 @@ radeon_pci_resume(struct pci_dev *pdev) + return radeon_resume_kms(dev); + } + ++static const struct file_operations radeon_driver_kms_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .mmap = radeon_mmap, ++ .poll = drm_poll, ++ .fasync = drm_fasync, ++ .read = drm_read, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = radeon_kms_compat_ioctl, ++#endif ++}; ++ + static struct drm_driver kms_driver = { + .driver_features = + DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | +@@ -335,24 +395,13 @@ static struct drm_driver kms_driver = { + .ioctls = radeon_ioctls_kms, + .gem_init_object = radeon_gem_object_init, + .gem_free_object = radeon_gem_object_free, ++ .gem_open_object = radeon_gem_object_open, ++ .gem_close_object = radeon_gem_object_close, + .dma_ioctl = radeon_dma_ioctl_kms, + .dumb_create = radeon_mode_dumb_create, + .dumb_map_offset = radeon_mode_dumb_mmap, + .dumb_destroy = radeon_mode_dumb_destroy, +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = drm_ioctl, +- .mmap = radeon_mmap, +- .poll = drm_poll, +- .fasync = drm_fasync, +- .read = drm_read, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = radeon_kms_compat_ioctl, +-#endif +- }, +- ++ .fops = &radeon_driver_kms_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, +@@ -367,6 +416,7 @@ static struct pci_driver *pdriver; + static struct pci_driver radeon_pci_driver = { + .name = DRIVER_NAME, + .id_table = pciidlist, ++ .probe = radeon_ums_pci_probe, + }; + + static struct pci_driver radeon_kms_pci_driver = { +diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c +index 4b27efa..7467069 100644 +--- a/drivers/gpu/drm/radeon/radeon_encoders.c ++++ b/drivers/gpu/drm/radeon/radeon_encoders.c +@@ -202,6 +202,22 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder) + return NULL; + } + ++struct drm_connector * ++radeon_get_connector_for_encoder_init(struct drm_encoder *encoder) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); ++ struct drm_connector *connector; ++ struct radeon_connector *radeon_connector; ++ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ radeon_connector = to_radeon_connector(connector); ++ if (radeon_encoder->devices & radeon_connector->devices) ++ return connector; ++ } ++ return NULL; ++} ++ + struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder) + { + struct drm_device *dev = encoder->dev; +@@ -288,3 +304,64 @@ void radeon_panel_mode_fixup(struct drm_encoder *encoder, + + } + ++bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder, ++ u32 pixel_clock) ++{ ++ struct drm_device *dev = encoder->dev; ++ struct radeon_device *rdev = dev->dev_private; ++ struct drm_connector *connector; ++ struct radeon_connector *radeon_connector; ++ struct radeon_connector_atom_dig *dig_connector; ++ ++ connector = radeon_get_connector_for_encoder(encoder); ++ /* if we don't have an active device yet, just use one of ++ * the connectors tied to the encoder. ++ */ ++ if (!connector) ++ connector = radeon_get_connector_for_encoder_init(encoder); ++ radeon_connector = to_radeon_connector(connector); ++ ++ switch (connector->connector_type) { ++ case DRM_MODE_CONNECTOR_DVII: ++ case DRM_MODE_CONNECTOR_HDMIB: ++ if (radeon_connector->use_digital) { ++ /* HDMI 1.3 supports up to 340 Mhz over single link */ ++ if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) { ++ if (pixel_clock > 340000) ++ return true; ++ else ++ return false; ++ } else { ++ if (pixel_clock > 165000) ++ return true; ++ else ++ return false; ++ } ++ } else ++ return false; ++ case DRM_MODE_CONNECTOR_DVID: ++ case DRM_MODE_CONNECTOR_HDMIA: ++ case DRM_MODE_CONNECTOR_DisplayPort: ++ dig_connector = radeon_connector->con_priv; ++ if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || ++ (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) ++ return false; ++ else { ++ /* HDMI 1.3 supports up to 340 Mhz over single link */ ++ if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) { ++ if (pixel_clock > 340000) ++ return true; ++ else ++ return false; ++ } else { ++ if (pixel_clock > 165000) ++ return true; ++ else ++ return false; ++ } ++ } ++ default: ++ return false; ++ } ++} ++ +diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h +index ec2f1ea..d1fafea 100644 +--- a/drivers/gpu/drm/radeon/radeon_family.h ++++ b/drivers/gpu/drm/radeon/radeon_family.h +@@ -87,6 +87,10 @@ enum radeon_family { + CHIP_TURKS, + CHIP_CAICOS, + CHIP_CAYMAN, ++ CHIP_ARUBA, ++ CHIP_TAHITI, ++ CHIP_PITCAIRN, ++ CHIP_VERDE, + CHIP_LAST, + }; + +diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c +index 0b7b486..5906914 100644 +--- a/drivers/gpu/drm/radeon/radeon_fb.c ++++ b/drivers/gpu/drm/radeon/radeon_fb.c +@@ -103,7 +103,7 @@ static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) + } + + static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, +- struct drm_mode_fb_cmd *mode_cmd, ++ struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object **gobj_p) + { + struct radeon_device *rdev = rfbdev->rdev; +@@ -114,13 +114,17 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, + int ret; + int aligned_size, size; + int height = mode_cmd->height; ++ u32 bpp, depth; ++ ++ drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + + /* need to align pitch with crtc limits */ +- mode_cmd->pitch = radeon_align_pitch(rdev, mode_cmd->width, mode_cmd->bpp, fb_tiled) * ((mode_cmd->bpp + 1) / 8); ++ mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, bpp, ++ fb_tiled) * ((bpp + 1) / 8); + + if (rdev->family >= CHIP_R600) + height = ALIGN(mode_cmd->height, 8); +- size = mode_cmd->pitch * height; ++ size = mode_cmd->pitches[0] * height; + aligned_size = ALIGN(size, PAGE_SIZE); + ret = radeon_gem_object_create(rdev, aligned_size, 0, + RADEON_GEM_DOMAIN_VRAM, +@@ -137,7 +141,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, + tiling_flags = RADEON_TILING_MACRO; + + #ifdef __BIG_ENDIAN +- switch (mode_cmd->bpp) { ++ switch (bpp) { + case 32: + tiling_flags |= RADEON_TILING_SWAP_32BIT; + break; +@@ -151,7 +155,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, + if (tiling_flags) { + ret = radeon_bo_set_tiling_flags(rbo, + tiling_flags | RADEON_TILING_SURFACE, +- mode_cmd->pitch); ++ mode_cmd->pitches[0]); + if (ret) + dev_err(rdev->dev, "FB failed to set tiling flags\n"); + } +@@ -160,7 +164,10 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, + ret = radeon_bo_reserve(rbo, false); + if (unlikely(ret != 0)) + goto out_unref; +- ret = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, NULL); ++ /* Only 27 bit offset for legacy CRTC */ ++ ret = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, ++ ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, ++ NULL); + if (ret) { + radeon_bo_unreserve(rbo); + goto out_unref; +@@ -187,7 +194,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, + struct radeon_device *rdev = rfbdev->rdev; + struct fb_info *info; + struct drm_framebuffer *fb = NULL; +- struct drm_mode_fb_cmd mode_cmd; ++ struct drm_mode_fb_cmd2 mode_cmd; + struct drm_gem_object *gobj = NULL; + struct radeon_bo *rbo = NULL; + struct device *device = &rdev->pdev->dev; +@@ -201,10 +208,15 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, + if ((sizes->surface_bpp == 24) && ASIC_IS_AVIVO(rdev)) + sizes->surface_bpp = 32; + +- mode_cmd.bpp = sizes->surface_bpp; +- mode_cmd.depth = sizes->surface_depth; ++ mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, ++ sizes->surface_depth); + + ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj); ++ if (ret) { ++ DRM_ERROR("failed to create fbcon object %d\n", ret); ++ return ret; ++ } ++ + rbo = gem_to_radeon_bo(gobj); + + /* okay we have an object now allocate the framebuffer */ +@@ -216,7 +228,11 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, + + info->par = rfbdev; + +- radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj); ++ ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj); ++ if (ret) { ++ DRM_ERROR("failed to initalise framebuffer %d\n", ret); ++ goto out_unref; ++ } + + fb = &rfbdev->rfb.base; + +@@ -228,7 +244,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, + + strcpy(info->fix.id, "radeondrmfb"); + +- drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); ++ drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + + info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; + info->fbops = &radeonfb_ops; +@@ -250,11 +266,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, + info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base; + info->apertures->ranges[0].size = rdev->mc.aper_size; + +- info->pixmap.size = 64*1024; +- info->pixmap.buf_align = 8; +- info->pixmap.access_align = 32; +- info->pixmap.flags = FB_PIXMAP_SYSTEM; +- info->pixmap.scan_align = 1; ++ /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ + + if (info->screen_base == NULL) { + ret = -ENOSPC; +@@ -271,7 +283,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, + DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base); + DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo)); + DRM_INFO("fb depth is %d\n", fb->depth); +- DRM_INFO(" pitch is %d\n", fb->pitch); ++ DRM_INFO(" pitch is %d\n", fb->pitches[0]); + + vga_switcheroo_client_fb_set(rdev->ddev->pdev, info); + return 0; +diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c +index 76ec0e9..4bd36a3 100644 +--- a/drivers/gpu/drm/radeon/radeon_fence.c ++++ b/drivers/gpu/drm/radeon/radeon_fence.c +@@ -40,32 +40,24 @@ + #include "radeon.h" + #include "radeon_trace.h" + +-static void radeon_fence_write(struct radeon_device *rdev, u32 seq) ++static void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring) + { + if (rdev->wb.enabled) { +- u32 scratch_index; +- if (rdev->wb.use_event) +- scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; +- else +- scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; +- rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq); +- } else +- WREG32(rdev->fence_drv.scratch_reg, seq); ++ *rdev->fence_drv[ring].cpu_addr = cpu_to_le32(seq); ++ } else { ++ WREG32(rdev->fence_drv[ring].scratch_reg, seq); ++ } + } + +-static u32 radeon_fence_read(struct radeon_device *rdev) ++static u32 radeon_fence_read(struct radeon_device *rdev, int ring) + { +- u32 seq; ++ u32 seq = 0; + + if (rdev->wb.enabled) { +- u32 scratch_index; +- if (rdev->wb.use_event) +- scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; +- else +- scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; +- seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]); +- } else +- seq = RREG32(rdev->fence_drv.scratch_reg); ++ seq = le32_to_cpu(*rdev->fence_drv[ring].cpu_addr); ++ } else { ++ seq = RREG32(rdev->fence_drv[ring].scratch_reg); ++ } + return seq; + } + +@@ -73,28 +65,28 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) + { + unsigned long irq_flags; + +- write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); +- if (fence->emited) { +- write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); ++ write_lock_irqsave(&rdev->fence_lock, irq_flags); ++ if (fence->emitted) { ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + return 0; + } +- fence->seq = atomic_add_return(1, &rdev->fence_drv.seq); +- if (!rdev->cp.ready) ++ fence->seq = atomic_add_return(1, &rdev->fence_drv[fence->ring].seq); ++ if (!rdev->ring[fence->ring].ready) + /* FIXME: cp is not running assume everythings is done right + * away + */ +- radeon_fence_write(rdev, fence->seq); ++ radeon_fence_write(rdev, fence->seq, fence->ring); + else +- radeon_fence_ring_emit(rdev, fence); ++ radeon_fence_ring_emit(rdev, fence->ring, fence); + + trace_radeon_fence_emit(rdev->ddev, fence->seq); +- fence->emited = true; +- list_move_tail(&fence->list, &rdev->fence_drv.emited); +- write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); ++ fence->emitted = true; ++ list_move_tail(&fence->list, &rdev->fence_drv[fence->ring].emitted); ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + return 0; + } + +-static bool radeon_fence_poll_locked(struct radeon_device *rdev) ++static bool radeon_fence_poll_locked(struct radeon_device *rdev, int ring) + { + struct radeon_fence *fence; + struct list_head *i, *n; +@@ -102,34 +94,34 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev) + bool wake = false; + unsigned long cjiffies; + +- seq = radeon_fence_read(rdev); +- if (seq != rdev->fence_drv.last_seq) { +- rdev->fence_drv.last_seq = seq; +- rdev->fence_drv.last_jiffies = jiffies; +- rdev->fence_drv.last_timeout = RADEON_FENCE_JIFFIES_TIMEOUT; ++ seq = radeon_fence_read(rdev, ring); ++ if (seq != rdev->fence_drv[ring].last_seq) { ++ rdev->fence_drv[ring].last_seq = seq; ++ rdev->fence_drv[ring].last_jiffies = jiffies; ++ rdev->fence_drv[ring].last_timeout = RADEON_FENCE_JIFFIES_TIMEOUT; + } else { + cjiffies = jiffies; +- if (time_after(cjiffies, rdev->fence_drv.last_jiffies)) { +- cjiffies -= rdev->fence_drv.last_jiffies; +- if (time_after(rdev->fence_drv.last_timeout, cjiffies)) { ++ if (time_after(cjiffies, rdev->fence_drv[ring].last_jiffies)) { ++ cjiffies -= rdev->fence_drv[ring].last_jiffies; ++ if (time_after(rdev->fence_drv[ring].last_timeout, cjiffies)) { + /* update the timeout */ +- rdev->fence_drv.last_timeout -= cjiffies; ++ rdev->fence_drv[ring].last_timeout -= cjiffies; + } else { + /* the 500ms timeout is elapsed we should test + * for GPU lockup + */ +- rdev->fence_drv.last_timeout = 1; ++ rdev->fence_drv[ring].last_timeout = 1; + } + } else { + /* wrap around update last jiffies, we will just wait + * a little longer + */ +- rdev->fence_drv.last_jiffies = cjiffies; ++ rdev->fence_drv[ring].last_jiffies = cjiffies; + } + return false; + } + n = NULL; +- list_for_each(i, &rdev->fence_drv.emited) { ++ list_for_each(i, &rdev->fence_drv[ring].emitted) { + fence = list_entry(i, struct radeon_fence, list); + if (fence->seq == seq) { + n = i; +@@ -141,11 +133,11 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev) + i = n; + do { + n = i->prev; +- list_move_tail(i, &rdev->fence_drv.signaled); ++ list_move_tail(i, &rdev->fence_drv[ring].signaled); + fence = list_entry(i, struct radeon_fence, list); + fence->signaled = true; + i = n; +- } while (i != &rdev->fence_drv.emited); ++ } while (i != &rdev->fence_drv[ring].emitted); + wake = true; + } + return wake; +@@ -157,14 +149,18 @@ static void radeon_fence_destroy(struct kref *kref) + struct radeon_fence *fence; + + fence = container_of(kref, struct radeon_fence, kref); +- write_lock_irqsave(&fence->rdev->fence_drv.lock, irq_flags); ++ write_lock_irqsave(&fence->rdev->fence_lock, irq_flags); + list_del(&fence->list); +- fence->emited = false; +- write_unlock_irqrestore(&fence->rdev->fence_drv.lock, irq_flags); ++ fence->emitted = false; ++ write_unlock_irqrestore(&fence->rdev->fence_lock, irq_flags); ++ if (fence->semaphore) ++ radeon_semaphore_free(fence->rdev, fence->semaphore); + kfree(fence); + } + +-int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence) ++int radeon_fence_create(struct radeon_device *rdev, ++ struct radeon_fence **fence, ++ int ring) + { + unsigned long irq_flags; + +@@ -174,18 +170,19 @@ int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence) + } + kref_init(&((*fence)->kref)); + (*fence)->rdev = rdev; +- (*fence)->emited = false; ++ (*fence)->emitted = false; + (*fence)->signaled = false; + (*fence)->seq = 0; ++ (*fence)->ring = ring; ++ (*fence)->semaphore = NULL; + INIT_LIST_HEAD(&(*fence)->list); + +- write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); +- list_add_tail(&(*fence)->list, &rdev->fence_drv.created); +- write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); ++ write_lock_irqsave(&rdev->fence_lock, irq_flags); ++ list_add_tail(&(*fence)->list, &rdev->fence_drv[ring].created); ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + return 0; + } + +- + bool radeon_fence_signaled(struct radeon_fence *fence) + { + unsigned long irq_flags; +@@ -197,21 +194,21 @@ bool radeon_fence_signaled(struct radeon_fence *fence) + if (fence->rdev->gpu_lockup) + return true; + +- write_lock_irqsave(&fence->rdev->fence_drv.lock, irq_flags); ++ write_lock_irqsave(&fence->rdev->fence_lock, irq_flags); + signaled = fence->signaled; + /* if we are shuting down report all fence as signaled */ + if (fence->rdev->shutdown) { + signaled = true; + } +- if (!fence->emited) { +- WARN(1, "Querying an unemited fence : %p !\n", fence); ++ if (!fence->emitted) { ++ WARN(1, "Querying an unemitted fence : %p !\n", fence); + signaled = true; + } + if (!signaled) { +- radeon_fence_poll_locked(fence->rdev); ++ radeon_fence_poll_locked(fence->rdev, fence->ring); + signaled = fence->signaled; + } +- write_unlock_irqrestore(&fence->rdev->fence_drv.lock, irq_flags); ++ write_unlock_irqrestore(&fence->rdev->fence_lock, irq_flags); + return signaled; + } + +@@ -230,24 +227,24 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr) + if (radeon_fence_signaled(fence)) { + return 0; + } +- timeout = rdev->fence_drv.last_timeout; ++ timeout = rdev->fence_drv[fence->ring].last_timeout; + retry: + /* save current sequence used to check for GPU lockup */ +- seq = rdev->fence_drv.last_seq; ++ seq = rdev->fence_drv[fence->ring].last_seq; + trace_radeon_fence_wait_begin(rdev->ddev, seq); + if (intr) { +- radeon_irq_kms_sw_irq_get(rdev); +- r = wait_event_interruptible_timeout(rdev->fence_drv.queue, ++ radeon_irq_kms_sw_irq_get(rdev, fence->ring); ++ r = wait_event_interruptible_timeout(rdev->fence_drv[fence->ring].queue, + radeon_fence_signaled(fence), timeout); +- radeon_irq_kms_sw_irq_put(rdev); ++ radeon_irq_kms_sw_irq_put(rdev, fence->ring); + if (unlikely(r < 0)) { + return r; + } + } else { +- radeon_irq_kms_sw_irq_get(rdev); +- r = wait_event_timeout(rdev->fence_drv.queue, ++ radeon_irq_kms_sw_irq_get(rdev, fence->ring); ++ r = wait_event_timeout(rdev->fence_drv[fence->ring].queue, + radeon_fence_signaled(fence), timeout); +- radeon_irq_kms_sw_irq_put(rdev); ++ radeon_irq_kms_sw_irq_put(rdev, fence->ring); + } + trace_radeon_fence_wait_end(rdev->ddev, seq); + if (unlikely(!radeon_fence_signaled(fence))) { +@@ -258,10 +255,11 @@ retry: + timeout = r; + goto retry; + } +- /* don't protect read access to rdev->fence_drv.last_seq ++ /* don't protect read access to rdev->fence_drv[t].last_seq + * if we experiencing a lockup the value doesn't change + */ +- if (seq == rdev->fence_drv.last_seq && radeon_gpu_is_lockup(rdev)) { ++ if (seq == rdev->fence_drv[fence->ring].last_seq && ++ radeon_gpu_is_lockup(rdev, &rdev->ring[fence->ring])) { + /* good news we believe it's a lockup */ + printk(KERN_WARNING "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", + fence->seq, seq); +@@ -272,20 +270,20 @@ retry: + r = radeon_gpu_reset(rdev); + if (r) + return r; +- radeon_fence_write(rdev, fence->seq); ++ radeon_fence_write(rdev, fence->seq, fence->ring); + rdev->gpu_lockup = false; + } + timeout = RADEON_FENCE_JIFFIES_TIMEOUT; +- write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); +- rdev->fence_drv.last_timeout = RADEON_FENCE_JIFFIES_TIMEOUT; +- rdev->fence_drv.last_jiffies = jiffies; +- write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); ++ write_lock_irqsave(&rdev->fence_lock, irq_flags); ++ rdev->fence_drv[fence->ring].last_timeout = RADEON_FENCE_JIFFIES_TIMEOUT; ++ rdev->fence_drv[fence->ring].last_jiffies = jiffies; ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + goto retry; + } + return 0; + } + +-int radeon_fence_wait_next(struct radeon_device *rdev) ++int radeon_fence_wait_next(struct radeon_device *rdev, int ring) + { + unsigned long irq_flags; + struct radeon_fence *fence; +@@ -294,21 +292,21 @@ int radeon_fence_wait_next(struct radeon_device *rdev) + if (rdev->gpu_lockup) { + return 0; + } +- write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); +- if (list_empty(&rdev->fence_drv.emited)) { +- write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); ++ write_lock_irqsave(&rdev->fence_lock, irq_flags); ++ if (list_empty(&rdev->fence_drv[ring].emitted)) { ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + return 0; + } +- fence = list_entry(rdev->fence_drv.emited.next, ++ fence = list_entry(rdev->fence_drv[ring].emitted.next, + struct radeon_fence, list); + radeon_fence_ref(fence); +- write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + r = radeon_fence_wait(fence, false); + radeon_fence_unref(&fence); + return r; + } + +-int radeon_fence_wait_last(struct radeon_device *rdev) ++int radeon_fence_wait_last(struct radeon_device *rdev, int ring) + { + unsigned long irq_flags; + struct radeon_fence *fence; +@@ -317,15 +315,15 @@ int radeon_fence_wait_last(struct radeon_device *rdev) + if (rdev->gpu_lockup) { + return 0; + } +- write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); +- if (list_empty(&rdev->fence_drv.emited)) { +- write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); ++ write_lock_irqsave(&rdev->fence_lock, irq_flags); ++ if (list_empty(&rdev->fence_drv[ring].emitted)) { ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + return 0; + } +- fence = list_entry(rdev->fence_drv.emited.prev, ++ fence = list_entry(rdev->fence_drv[ring].emitted.prev, + struct radeon_fence, list); + radeon_fence_ref(fence); +- write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + r = radeon_fence_wait(fence, false); + radeon_fence_unref(&fence); + return r; +@@ -347,39 +345,97 @@ void radeon_fence_unref(struct radeon_fence **fence) + } + } + +-void radeon_fence_process(struct radeon_device *rdev) ++void radeon_fence_process(struct radeon_device *rdev, int ring) + { + unsigned long irq_flags; + bool wake; + +- write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); +- wake = radeon_fence_poll_locked(rdev); +- write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); ++ write_lock_irqsave(&rdev->fence_lock, irq_flags); ++ wake = radeon_fence_poll_locked(rdev, ring); ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + if (wake) { +- wake_up_all(&rdev->fence_drv.queue); ++ wake_up_all(&rdev->fence_drv[ring].queue); + } + } + +-int radeon_fence_driver_init(struct radeon_device *rdev) ++int radeon_fence_count_emitted(struct radeon_device *rdev, int ring) ++{ ++ unsigned long irq_flags; ++ int not_processed = 0; ++ ++ read_lock_irqsave(&rdev->fence_lock, irq_flags); ++ if (!rdev->fence_drv[ring].initialized) { ++ read_unlock_irqrestore(&rdev->fence_lock, irq_flags); ++ return 0; ++ } ++ ++ if (!list_empty(&rdev->fence_drv[ring].emitted)) { ++ struct list_head *ptr; ++ list_for_each(ptr, &rdev->fence_drv[ring].emitted) { ++ /* count up to 3, that's enought info */ ++ if (++not_processed >= 3) ++ break; ++ } ++ } ++ read_unlock_irqrestore(&rdev->fence_lock, irq_flags); ++ return not_processed; ++} ++ ++int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) + { + unsigned long irq_flags; ++ uint64_t index; + int r; + +- write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); +- r = radeon_scratch_get(rdev, &rdev->fence_drv.scratch_reg); +- if (r) { +- dev_err(rdev->dev, "fence failed to get scratch register\n"); +- write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); +- return r; ++ write_lock_irqsave(&rdev->fence_lock, irq_flags); ++ radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); ++ if (rdev->wb.use_event) { ++ rdev->fence_drv[ring].scratch_reg = 0; ++ index = R600_WB_EVENT_OFFSET + ring * 4; ++ } else { ++ r = radeon_scratch_get(rdev, &rdev->fence_drv[ring].scratch_reg); ++ if (r) { ++ dev_err(rdev->dev, "fence failed to get scratch register\n"); ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); ++ return r; ++ } ++ index = RADEON_WB_SCRATCH_OFFSET + ++ rdev->fence_drv[ring].scratch_reg - ++ rdev->scratch.reg_base; ++ } ++ rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4]; ++ rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index; ++ radeon_fence_write(rdev, atomic_read(&rdev->fence_drv[ring].seq), ring); ++ rdev->fence_drv[ring].initialized = true; ++ DRM_INFO("fence driver on ring %d use gpu addr 0x%08Lx and cpu addr 0x%p\n", ++ ring, rdev->fence_drv[ring].gpu_addr, rdev->fence_drv[ring].cpu_addr); ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); ++ return 0; ++} ++ ++static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring) ++{ ++ rdev->fence_drv[ring].scratch_reg = -1; ++ rdev->fence_drv[ring].cpu_addr = NULL; ++ rdev->fence_drv[ring].gpu_addr = 0; ++ atomic_set(&rdev->fence_drv[ring].seq, 0); ++ INIT_LIST_HEAD(&rdev->fence_drv[ring].created); ++ INIT_LIST_HEAD(&rdev->fence_drv[ring].emitted); ++ INIT_LIST_HEAD(&rdev->fence_drv[ring].signaled); ++ init_waitqueue_head(&rdev->fence_drv[ring].queue); ++ rdev->fence_drv[ring].initialized = false; ++} ++ ++int radeon_fence_driver_init(struct radeon_device *rdev) ++{ ++ unsigned long irq_flags; ++ int ring; ++ ++ write_lock_irqsave(&rdev->fence_lock, irq_flags); ++ for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { ++ radeon_fence_driver_init_ring(rdev, ring); + } +- radeon_fence_write(rdev, 0); +- atomic_set(&rdev->fence_drv.seq, 0); +- INIT_LIST_HEAD(&rdev->fence_drv.created); +- INIT_LIST_HEAD(&rdev->fence_drv.emited); +- INIT_LIST_HEAD(&rdev->fence_drv.signaled); +- init_waitqueue_head(&rdev->fence_drv.queue); +- rdev->fence_drv.initialized = true; +- write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + if (radeon_debugfs_fence_init(rdev)) { + dev_err(rdev->dev, "fence debugfs file creation failed\n"); + } +@@ -389,14 +445,18 @@ int radeon_fence_driver_init(struct radeon_device *rdev) + void radeon_fence_driver_fini(struct radeon_device *rdev) + { + unsigned long irq_flags; +- +- if (!rdev->fence_drv.initialized) +- return; +- wake_up_all(&rdev->fence_drv.queue); +- write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); +- radeon_scratch_free(rdev, rdev->fence_drv.scratch_reg); +- write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); +- rdev->fence_drv.initialized = false; ++ int ring; ++ ++ for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { ++ if (!rdev->fence_drv[ring].initialized) ++ continue; ++ radeon_fence_wait_last(rdev, ring); ++ wake_up_all(&rdev->fence_drv[ring].queue); ++ write_lock_irqsave(&rdev->fence_lock, irq_flags); ++ radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); ++ write_unlock_irqrestore(&rdev->fence_lock, irq_flags); ++ rdev->fence_drv[ring].initialized = false; ++ } + } + + +@@ -410,14 +470,21 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_fence *fence; +- +- seq_printf(m, "Last signaled fence 0x%08X\n", +- radeon_fence_read(rdev)); +- if (!list_empty(&rdev->fence_drv.emited)) { +- fence = list_entry(rdev->fence_drv.emited.prev, +- struct radeon_fence, list); +- seq_printf(m, "Last emited fence %p with 0x%08X\n", +- fence, fence->seq); ++ int i; ++ ++ for (i = 0; i < RADEON_NUM_RINGS; ++i) { ++ if (!rdev->fence_drv[i].initialized) ++ continue; ++ ++ seq_printf(m, "--- ring %d ---\n", i); ++ seq_printf(m, "Last signaled fence 0x%08X\n", ++ radeon_fence_read(rdev, i)); ++ if (!list_empty(&rdev->fence_drv[i].emitted)) { ++ fence = list_entry(rdev->fence_drv[i].emitted.prev, ++ struct radeon_fence, list); ++ seq_printf(m, "Last emitted fence %p with 0x%08X\n", ++ fence, fence->seq); ++ } + } + return 0; + } +diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c +index d257210..b8e4f96 100644 +--- a/drivers/gpu/drm/radeon/radeon_gart.c ++++ b/drivers/gpu/drm/radeon/radeon_gart.c +@@ -157,9 +157,6 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, + p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); + for (i = 0; i < pages; i++, p++) { + if (rdev->gart.pages[p]) { +- if (!rdev->gart.ttm_alloced[p]) +- pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p], +- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + rdev->gart.pages[p] = NULL; + rdev->gart.pages_addr[p] = rdev->dummy_page.addr; + page_base = rdev->gart.pages_addr[p]; +@@ -193,23 +190,7 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, + p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); + + for (i = 0; i < pages; i++, p++) { +- /* we reverted the patch using dma_addr in TTM for now but this +- * code stops building on alpha so just comment it out for now */ +- if (0) { /*dma_addr[i] != DMA_ERROR_CODE) */ +- rdev->gart.ttm_alloced[p] = true; +- rdev->gart.pages_addr[p] = dma_addr[i]; +- } else { +- /* we need to support large memory configurations */ +- /* assume that unbind have already been call on the range */ +- rdev->gart.pages_addr[p] = pci_map_page(rdev->pdev, pagelist[i], +- 0, PAGE_SIZE, +- PCI_DMA_BIDIRECTIONAL); +- if (pci_dma_mapping_error(rdev->pdev, rdev->gart.pages_addr[p])) { +- /* FIXME: failed to map page (return -ENOMEM?) */ +- radeon_gart_unbind(rdev, offset, pages); +- return -ENOMEM; +- } +- } ++ rdev->gart.pages_addr[p] = dma_addr[i]; + rdev->gart.pages[p] = pagelist[i]; + if (rdev->gart.ptr) { + page_base = rdev->gart.pages_addr[p]; +@@ -278,12 +259,6 @@ int radeon_gart_init(struct radeon_device *rdev) + radeon_gart_fini(rdev); + return -ENOMEM; + } +- rdev->gart.ttm_alloced = kzalloc(sizeof(bool) * +- rdev->gart.num_cpu_pages, GFP_KERNEL); +- if (rdev->gart.ttm_alloced == NULL) { +- radeon_gart_fini(rdev); +- return -ENOMEM; +- } + /* set GART entry to point to the dummy page by default */ + for (i = 0; i < rdev->gart.num_cpu_pages; i++) { + rdev->gart.pages_addr[i] = rdev->dummy_page.addr; +@@ -300,10 +275,418 @@ void radeon_gart_fini(struct radeon_device *rdev) + rdev->gart.ready = false; + kfree(rdev->gart.pages); + kfree(rdev->gart.pages_addr); +- kfree(rdev->gart.ttm_alloced); + rdev->gart.pages = NULL; + rdev->gart.pages_addr = NULL; +- rdev->gart.ttm_alloced = NULL; + + radeon_dummy_page_fini(rdev); + } ++ ++/* ++ * vm helpers ++ * ++ * TODO bind a default page at vm initialization for default address ++ */ ++int radeon_vm_manager_init(struct radeon_device *rdev) ++{ ++ int r; ++ ++ rdev->vm_manager.enabled = false; ++ ++ /* mark first vm as always in use, it's the system one */ ++ /* allocate enough for 2 full VM pts */ ++ r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, ++ rdev->vm_manager.max_pfn * 8 * 2, ++ RADEON_GEM_DOMAIN_VRAM); ++ if (r) { ++ dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", ++ (rdev->vm_manager.max_pfn * 8) >> 10); ++ return r; ++ } ++ ++ r = rdev->vm_manager.funcs->init(rdev); ++ if (r == 0) ++ rdev->vm_manager.enabled = true; ++ ++ return r; ++} ++ ++/* cs mutex must be lock */ ++static void radeon_vm_unbind_locked(struct radeon_device *rdev, ++ struct radeon_vm *vm) ++{ ++ struct radeon_bo_va *bo_va; ++ ++ if (vm->id == -1) { ++ return; ++ } ++ ++ /* wait for vm use to end */ ++ if (vm->fence) { ++ radeon_fence_wait(vm->fence, false); ++ radeon_fence_unref(&vm->fence); ++ } ++ ++ /* hw unbind */ ++ rdev->vm_manager.funcs->unbind(rdev, vm); ++ rdev->vm_manager.use_bitmap &= ~(1 << vm->id); ++ list_del_init(&vm->list); ++ vm->id = -1; ++ radeon_sa_bo_free(rdev, &vm->sa_bo); ++ vm->pt = NULL; ++ ++ list_for_each_entry(bo_va, &vm->va, vm_list) { ++ bo_va->valid = false; ++ } ++} ++ ++void radeon_vm_manager_fini(struct radeon_device *rdev) ++{ ++ if (rdev->vm_manager.sa_manager.bo == NULL) ++ return; ++ radeon_vm_manager_suspend(rdev); ++ rdev->vm_manager.funcs->fini(rdev); ++ radeon_sa_bo_manager_fini(rdev, &rdev->vm_manager.sa_manager); ++ rdev->vm_manager.enabled = false; ++} ++ ++int radeon_vm_manager_start(struct radeon_device *rdev) ++{ ++ if (rdev->vm_manager.sa_manager.bo == NULL) { ++ return -EINVAL; ++ } ++ return radeon_sa_bo_manager_start(rdev, &rdev->vm_manager.sa_manager); ++} ++ ++int radeon_vm_manager_suspend(struct radeon_device *rdev) ++{ ++ struct radeon_vm *vm, *tmp; ++ ++ radeon_mutex_lock(&rdev->cs_mutex); ++ /* unbind all active vm */ ++ list_for_each_entry_safe(vm, tmp, &rdev->vm_manager.lru_vm, list) { ++ radeon_vm_unbind_locked(rdev, vm); ++ } ++ rdev->vm_manager.funcs->fini(rdev); ++ radeon_mutex_unlock(&rdev->cs_mutex); ++ return radeon_sa_bo_manager_suspend(rdev, &rdev->vm_manager.sa_manager); ++} ++ ++/* cs mutex must be lock */ ++void radeon_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm) ++{ ++ mutex_lock(&vm->mutex); ++ radeon_vm_unbind_locked(rdev, vm); ++ mutex_unlock(&vm->mutex); ++} ++ ++/* cs mutex must be lock & vm mutex must be lock */ ++int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm) ++{ ++ struct radeon_vm *vm_evict; ++ unsigned i; ++ int id = -1, r; ++ ++ if (vm == NULL) { ++ return -EINVAL; ++ } ++ ++ if (vm->id != -1) { ++ /* update lru */ ++ list_del_init(&vm->list); ++ list_add_tail(&vm->list, &rdev->vm_manager.lru_vm); ++ return 0; ++ } ++ ++retry: ++ r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, &vm->sa_bo, ++ RADEON_GPU_PAGE_ALIGN(vm->last_pfn * 8), ++ RADEON_GPU_PAGE_SIZE); ++ if (r) { ++ if (list_empty(&rdev->vm_manager.lru_vm)) { ++ return r; ++ } ++ vm_evict = list_first_entry(&rdev->vm_manager.lru_vm, struct radeon_vm, list); ++ radeon_vm_unbind(rdev, vm_evict); ++ goto retry; ++ } ++ vm->pt = rdev->vm_manager.sa_manager.cpu_ptr; ++ vm->pt += (vm->sa_bo.offset >> 3); ++ vm->pt_gpu_addr = rdev->vm_manager.sa_manager.gpu_addr; ++ vm->pt_gpu_addr += vm->sa_bo.offset; ++ memset(vm->pt, 0, RADEON_GPU_PAGE_ALIGN(vm->last_pfn * 8)); ++ ++retry_id: ++ /* search for free vm */ ++ for (i = 0; i < rdev->vm_manager.nvm; i++) { ++ if (!(rdev->vm_manager.use_bitmap & (1 << i))) { ++ id = i; ++ break; ++ } ++ } ++ /* evict vm if necessary */ ++ if (id == -1) { ++ vm_evict = list_first_entry(&rdev->vm_manager.lru_vm, struct radeon_vm, list); ++ radeon_vm_unbind(rdev, vm_evict); ++ goto retry_id; ++ } ++ ++ /* do hw bind */ ++ r = rdev->vm_manager.funcs->bind(rdev, vm, id); ++ if (r) { ++ radeon_sa_bo_free(rdev, &vm->sa_bo); ++ return r; ++ } ++ rdev->vm_manager.use_bitmap |= 1 << id; ++ vm->id = id; ++ list_add_tail(&vm->list, &rdev->vm_manager.lru_vm); ++ return radeon_vm_bo_update_pte(rdev, vm, rdev->ib_pool.sa_manager.bo, ++ &rdev->ib_pool.sa_manager.bo->tbo.mem); ++} ++ ++/* object have to be reserved */ ++int radeon_vm_bo_add(struct radeon_device *rdev, ++ struct radeon_vm *vm, ++ struct radeon_bo *bo, ++ uint64_t offset, ++ uint32_t flags) ++{ ++ struct radeon_bo_va *bo_va, *tmp; ++ struct list_head *head; ++ uint64_t size = radeon_bo_size(bo), last_offset = 0; ++ unsigned last_pfn; ++ ++ bo_va = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); ++ if (bo_va == NULL) { ++ return -ENOMEM; ++ } ++ bo_va->vm = vm; ++ bo_va->bo = bo; ++ bo_va->soffset = offset; ++ bo_va->eoffset = offset + size; ++ bo_va->flags = flags; ++ bo_va->valid = false; ++ INIT_LIST_HEAD(&bo_va->bo_list); ++ INIT_LIST_HEAD(&bo_va->vm_list); ++ /* make sure object fit at this offset */ ++ if (bo_va->soffset >= bo_va->eoffset) { ++ kfree(bo_va); ++ return -EINVAL; ++ } ++ ++ last_pfn = bo_va->eoffset / RADEON_GPU_PAGE_SIZE; ++ if (last_pfn > rdev->vm_manager.max_pfn) { ++ kfree(bo_va); ++ dev_err(rdev->dev, "va above limit (0x%08X > 0x%08X)\n", ++ last_pfn, rdev->vm_manager.max_pfn); ++ return -EINVAL; ++ } ++ ++ mutex_lock(&vm->mutex); ++ if (last_pfn > vm->last_pfn) { ++ /* release mutex and lock in right order */ ++ mutex_unlock(&vm->mutex); ++ radeon_mutex_lock(&rdev->cs_mutex); ++ mutex_lock(&vm->mutex); ++ /* and check again */ ++ if (last_pfn > vm->last_pfn) { ++ /* grow va space 32M by 32M */ ++ unsigned align = ((32 << 20) >> 12) - 1; ++ radeon_vm_unbind_locked(rdev, vm); ++ vm->last_pfn = (last_pfn + align) & ~align; ++ } ++ radeon_mutex_unlock(&rdev->cs_mutex); ++ } ++ head = &vm->va; ++ last_offset = 0; ++ list_for_each_entry(tmp, &vm->va, vm_list) { ++ if (bo_va->soffset >= last_offset && bo_va->eoffset < tmp->soffset) { ++ /* bo can be added before this one */ ++ break; ++ } ++ if (bo_va->soffset >= tmp->soffset && bo_va->soffset < tmp->eoffset) { ++ /* bo and tmp overlap, invalid offset */ ++ dev_err(rdev->dev, "bo %p va 0x%08X conflict with (bo %p 0x%08X 0x%08X)\n", ++ bo, (unsigned)bo_va->soffset, tmp->bo, ++ (unsigned)tmp->soffset, (unsigned)tmp->eoffset); ++ kfree(bo_va); ++ mutex_unlock(&vm->mutex); ++ return -EINVAL; ++ } ++ last_offset = tmp->eoffset; ++ head = &tmp->vm_list; ++ } ++ list_add(&bo_va->vm_list, head); ++ list_add_tail(&bo_va->bo_list, &bo->va); ++ mutex_unlock(&vm->mutex); ++ return 0; ++} ++ ++static u64 radeon_vm_get_addr(struct radeon_device *rdev, ++ struct ttm_mem_reg *mem, ++ unsigned pfn) ++{ ++ u64 addr = 0; ++ ++ switch (mem->mem_type) { ++ case TTM_PL_VRAM: ++ addr = (mem->start << PAGE_SHIFT); ++ addr += pfn * RADEON_GPU_PAGE_SIZE; ++ addr += rdev->vm_manager.vram_base_offset; ++ break; ++ case TTM_PL_TT: ++ /* offset inside page table */ ++ addr = mem->start << PAGE_SHIFT; ++ addr += pfn * RADEON_GPU_PAGE_SIZE; ++ addr = addr >> PAGE_SHIFT; ++ /* page table offset */ ++ addr = rdev->gart.pages_addr[addr]; ++ /* in case cpu page size != gpu page size*/ ++ addr += (pfn * RADEON_GPU_PAGE_SIZE) & (~PAGE_MASK); ++ break; ++ default: ++ break; ++ } ++ return addr; ++} ++ ++/* object have to be reserved & cs mutex took & vm mutex took */ ++int radeon_vm_bo_update_pte(struct radeon_device *rdev, ++ struct radeon_vm *vm, ++ struct radeon_bo *bo, ++ struct ttm_mem_reg *mem) ++{ ++ struct radeon_bo_va *bo_va; ++ unsigned ngpu_pages, i; ++ uint64_t addr = 0, pfn; ++ uint32_t flags; ++ ++ /* nothing to do if vm isn't bound */ ++ if (vm->id == -1) ++ return 0;; ++ ++ bo_va = radeon_bo_va(bo, vm); ++ if (bo_va == NULL) { ++ dev_err(rdev->dev, "bo %p not in vm %p\n", bo, vm); ++ return -EINVAL; ++ } ++ ++ if (bo_va->valid) ++ return 0; ++ ++ ngpu_pages = radeon_bo_ngpu_pages(bo); ++ bo_va->flags &= ~RADEON_VM_PAGE_VALID; ++ bo_va->flags &= ~RADEON_VM_PAGE_SYSTEM; ++ if (mem) { ++ if (mem->mem_type != TTM_PL_SYSTEM) { ++ bo_va->flags |= RADEON_VM_PAGE_VALID; ++ bo_va->valid = true; ++ } ++ if (mem->mem_type == TTM_PL_TT) { ++ bo_va->flags |= RADEON_VM_PAGE_SYSTEM; ++ } ++ } ++ pfn = bo_va->soffset / RADEON_GPU_PAGE_SIZE; ++ flags = rdev->vm_manager.funcs->page_flags(rdev, bo_va->vm, bo_va->flags); ++ for (i = 0, addr = 0; i < ngpu_pages; i++) { ++ if (mem && bo_va->valid) { ++ addr = radeon_vm_get_addr(rdev, mem, i); ++ } ++ rdev->vm_manager.funcs->set_page(rdev, bo_va->vm, i + pfn, addr, flags); ++ } ++ rdev->vm_manager.funcs->tlb_flush(rdev, bo_va->vm); ++ return 0; ++} ++ ++/* object have to be reserved */ ++int radeon_vm_bo_rmv(struct radeon_device *rdev, ++ struct radeon_vm *vm, ++ struct radeon_bo *bo) ++{ ++ struct radeon_bo_va *bo_va; ++ ++ bo_va = radeon_bo_va(bo, vm); ++ if (bo_va == NULL) ++ return 0; ++ ++ radeon_mutex_lock(&rdev->cs_mutex); ++ mutex_lock(&vm->mutex); ++ radeon_vm_bo_update_pte(rdev, vm, bo, NULL); ++ radeon_mutex_unlock(&rdev->cs_mutex); ++ list_del(&bo_va->vm_list); ++ mutex_unlock(&vm->mutex); ++ list_del(&bo_va->bo_list); ++ ++ kfree(bo_va); ++ return 0; ++} ++ ++void radeon_vm_bo_invalidate(struct radeon_device *rdev, ++ struct radeon_bo *bo) ++{ ++ struct radeon_bo_va *bo_va; ++ ++ BUG_ON(!atomic_read(&bo->tbo.reserved)); ++ list_for_each_entry(bo_va, &bo->va, bo_list) { ++ bo_va->valid = false; ++ } ++} ++ ++int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) ++{ ++ int r; ++ ++ vm->id = -1; ++ vm->fence = NULL; ++ mutex_init(&vm->mutex); ++ INIT_LIST_HEAD(&vm->list); ++ INIT_LIST_HEAD(&vm->va); ++ /* SI requires equal sized PTs for all VMs, so always set ++ * last_pfn to max_pfn. cayman allows variable sized ++ * pts so we can grow then as needed. Once we switch ++ * to two level pts we can unify this again. ++ */ ++ if (rdev->family >= CHIP_TAHITI) ++ vm->last_pfn = rdev->vm_manager.max_pfn; ++ else ++ vm->last_pfn = 0; ++ /* map the ib pool buffer at 0 in virtual address space, set ++ * read only ++ */ ++ r = radeon_vm_bo_add(rdev, vm, rdev->ib_pool.sa_manager.bo, 0, ++ RADEON_VM_PAGE_READABLE | RADEON_VM_PAGE_SNOOPED); ++ return r; ++} ++ ++void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) ++{ ++ struct radeon_bo_va *bo_va, *tmp; ++ int r; ++ ++ radeon_mutex_lock(&rdev->cs_mutex); ++ mutex_lock(&vm->mutex); ++ radeon_vm_unbind_locked(rdev, vm); ++ radeon_mutex_unlock(&rdev->cs_mutex); ++ ++ /* remove all bo */ ++ r = radeon_bo_reserve(rdev->ib_pool.sa_manager.bo, false); ++ if (!r) { ++ bo_va = radeon_bo_va(rdev->ib_pool.sa_manager.bo, vm); ++ list_del_init(&bo_va->bo_list); ++ list_del_init(&bo_va->vm_list); ++ radeon_bo_unreserve(rdev->ib_pool.sa_manager.bo); ++ kfree(bo_va); ++ } ++ if (!list_empty(&vm->va)) { ++ dev_err(rdev->dev, "still active bo inside vm\n"); ++ } ++ list_for_each_entry_safe(bo_va, tmp, &vm->va, vm_list) { ++ list_del_init(&bo_va->vm_list); ++ r = radeon_bo_reserve(bo_va->bo, false); ++ if (!r) { ++ list_del_init(&bo_va->bo_list); ++ radeon_bo_unreserve(bo_va->bo); ++ kfree(bo_va); ++ } ++ } ++ mutex_unlock(&vm->mutex); ++} +diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c +index aa1ca2d..c7008b5 100644 +--- a/drivers/gpu/drm/radeon/radeon_gem.c ++++ b/drivers/gpu/drm/radeon/radeon_gem.c +@@ -75,32 +75,6 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, + return 0; + } + +-int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain, +- uint64_t *gpu_addr) +-{ +- struct radeon_bo *robj = gem_to_radeon_bo(obj); +- int r; +- +- r = radeon_bo_reserve(robj, false); +- if (unlikely(r != 0)) +- return r; +- r = radeon_bo_pin(robj, pin_domain, gpu_addr); +- radeon_bo_unreserve(robj); +- return r; +-} +- +-void radeon_gem_object_unpin(struct drm_gem_object *obj) +-{ +- struct radeon_bo *robj = gem_to_radeon_bo(obj); +- int r; +- +- r = radeon_bo_reserve(robj, false); +- if (likely(r == 0)) { +- radeon_bo_unpin(robj); +- radeon_bo_unreserve(robj); +- } +-} +- + int radeon_gem_set_domain(struct drm_gem_object *gobj, + uint32_t rdomain, uint32_t wdomain) + { +@@ -142,6 +116,44 @@ void radeon_gem_fini(struct radeon_device *rdev) + radeon_bo_force_delete(rdev); + } + ++/* ++ * Call from drm_gem_handle_create which appear in both new and open ioctl ++ * case. ++ */ ++int radeon_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv) ++{ ++ return 0; ++} ++ ++void radeon_gem_object_close(struct drm_gem_object *obj, ++ struct drm_file *file_priv) ++{ ++ struct radeon_bo *rbo = gem_to_radeon_bo(obj); ++ struct radeon_device *rdev = rbo->rdev; ++ struct radeon_fpriv *fpriv = file_priv->driver_priv; ++ struct radeon_vm *vm = &fpriv->vm; ++ struct radeon_bo_va *bo_va, *tmp; ++ ++ if (rdev->family < CHIP_CAYMAN) { ++ return; ++ } ++ ++ if (radeon_bo_reserve(rbo, false)) { ++ return; ++ } ++ list_for_each_entry_safe(bo_va, tmp, &rbo->va, bo_list) { ++ if (bo_va->vm == vm) { ++ /* remove from this vm address space */ ++ mutex_lock(&vm->mutex); ++ list_del(&bo_va->vm_list); ++ mutex_unlock(&vm->mutex); ++ list_del(&bo_va->bo_list); ++ kfree(bo_va); ++ } ++ } ++ radeon_bo_unreserve(rbo); ++} ++ + + /* + * GEM ioctls. +@@ -152,6 +164,7 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, + struct radeon_device *rdev = dev->dev_private; + struct drm_radeon_gem_info *args = data; + struct ttm_mem_type_manager *man; ++ unsigned i; + + man = &rdev->mman.bdev.man[TTM_PL_VRAM]; + +@@ -160,8 +173,9 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, + if (rdev->stollen_vga_memory) + args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory); + args->vram_visible -= radeon_fbdev_total_size(rdev); +- args->gart_size = rdev->mc.gtt_size - rdev->cp.ring_size - 4096 - +- RADEON_IB_POOL_SIZE*64*1024; ++ args->gart_size = rdev->mc.gtt_size - 4096 - RADEON_IB_POOL_SIZE*64*1024; ++ for(i = 0; i < RADEON_NUM_RINGS; ++i) ++ args->gart_size -= rdev->ring[i].ring_size; + return 0; + } + +@@ -352,6 +366,109 @@ out: + return r; + } + ++int radeon_gem_va_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *filp) ++{ ++ struct drm_radeon_gem_va *args = data; ++ struct drm_gem_object *gobj; ++ struct radeon_device *rdev = dev->dev_private; ++ struct radeon_fpriv *fpriv = filp->driver_priv; ++ struct radeon_bo *rbo; ++ struct radeon_bo_va *bo_va; ++ u32 invalid_flags; ++ int r = 0; ++ ++ if (!rdev->vm_manager.enabled) { ++ args->operation = RADEON_VA_RESULT_ERROR; ++ return -ENOTTY; ++ } ++ ++ /* !! DONT REMOVE !! ++ * We don't support vm_id yet, to be sure we don't have have broken ++ * userspace, reject anyone trying to use non 0 value thus moving ++ * forward we can use those fields without breaking existant userspace ++ */ ++ if (args->vm_id) { ++ args->operation = RADEON_VA_RESULT_ERROR; ++ return -EINVAL; ++ } ++ ++ if (args->offset < RADEON_VA_RESERVED_SIZE) { ++ dev_err(&dev->pdev->dev, ++ "offset 0x%lX is in reserved area 0x%X\n", ++ (unsigned long)args->offset, ++ RADEON_VA_RESERVED_SIZE); ++ args->operation = RADEON_VA_RESULT_ERROR; ++ return -EINVAL; ++ } ++ ++ /* don't remove, we need to enforce userspace to set the snooped flag ++ * otherwise we will endup with broken userspace and we won't be able ++ * to enable this feature without adding new interface ++ */ ++ invalid_flags = RADEON_VM_PAGE_VALID | RADEON_VM_PAGE_SYSTEM; ++ if ((args->flags & invalid_flags)) { ++ dev_err(&dev->pdev->dev, "invalid flags 0x%08X vs 0x%08X\n", ++ args->flags, invalid_flags); ++ args->operation = RADEON_VA_RESULT_ERROR; ++ return -EINVAL; ++ } ++ if (!(args->flags & RADEON_VM_PAGE_SNOOPED)) { ++ dev_err(&dev->pdev->dev, "only supported snooped mapping for now\n"); ++ args->operation = RADEON_VA_RESULT_ERROR; ++ return -EINVAL; ++ } ++ ++ switch (args->operation) { ++ case RADEON_VA_MAP: ++ case RADEON_VA_UNMAP: ++ break; ++ default: ++ dev_err(&dev->pdev->dev, "unsupported operation %d\n", ++ args->operation); ++ args->operation = RADEON_VA_RESULT_ERROR; ++ return -EINVAL; ++ } ++ ++ gobj = drm_gem_object_lookup(dev, filp, args->handle); ++ if (gobj == NULL) { ++ args->operation = RADEON_VA_RESULT_ERROR; ++ return -ENOENT; ++ } ++ rbo = gem_to_radeon_bo(gobj); ++ r = radeon_bo_reserve(rbo, false); ++ if (r) { ++ args->operation = RADEON_VA_RESULT_ERROR; ++ drm_gem_object_unreference_unlocked(gobj); ++ return r; ++ } ++ switch (args->operation) { ++ case RADEON_VA_MAP: ++ bo_va = radeon_bo_va(rbo, &fpriv->vm); ++ if (bo_va) { ++ args->operation = RADEON_VA_RESULT_VA_EXIST; ++ args->offset = bo_va->soffset; ++ goto out; ++ } ++ r = radeon_vm_bo_add(rdev, &fpriv->vm, rbo, ++ args->offset, args->flags); ++ break; ++ case RADEON_VA_UNMAP: ++ r = radeon_vm_bo_rmv(rdev, &fpriv->vm, rbo); ++ break; ++ default: ++ break; ++ } ++ args->operation = RADEON_VA_RESULT_OK; ++ if (r) { ++ args->operation = RADEON_VA_RESULT_ERROR; ++ } ++out: ++ radeon_bo_unreserve(rbo); ++ drm_gem_object_unreference_unlocked(gobj); ++ return r; ++} ++ + int radeon_mode_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args) +diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c +index 894b5f0..19d68c5 100644 +--- a/drivers/gpu/drm/radeon/radeon_i2c.c ++++ b/drivers/gpu/drm/radeon/radeon_i2c.c +@@ -26,10 +26,15 @@ + #include + + #include "drmP.h" ++#include "drm_edid.h" + #include "radeon_drm.h" + #include "radeon.h" + #include "atom.h" + ++extern int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap, ++ struct i2c_msg *msgs, int num); ++extern u32 radeon_atom_hw_i2c_func(struct i2c_adapter *adap); ++ + /** + * radeon_ddc_probe + * +@@ -41,13 +46,13 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) + int ret; + struct i2c_msg msgs[] = { + { +- .addr = 0x50, ++ .addr = DDC_ADDR, + .flags = 0, + .len = 1, + .buf = &out, + }, + { +- .addr = 0x50, ++ .addr = DDC_ADDR, + .flags = I2C_M_RD, + .len = 8, + .buf = buf, +@@ -888,6 +893,11 @@ static const struct i2c_algorithm radeon_i2c_algo = { + .functionality = radeon_hw_i2c_func, + }; + ++static const struct i2c_algorithm radeon_atom_i2c_algo = { ++ .master_xfer = radeon_atom_hw_i2c_xfer, ++ .functionality = radeon_atom_hw_i2c_func, ++}; ++ + struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, + struct radeon_i2c_bus_rec *rec, + const char *name) +@@ -907,6 +917,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, + i2c->rec = *rec; + i2c->adapter.owner = THIS_MODULE; + i2c->adapter.class = I2C_CLASS_DDC; ++ i2c->adapter.dev.parent = &dev->pdev->dev; + i2c->dev = dev; + i2c_set_adapdata(&i2c->adapter, i2c); + if (rec->mm_i2c || +@@ -923,6 +934,18 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, + DRM_ERROR("Failed to register hw i2c %s\n", name); + goto out_free; + } ++ } else if (rec->hw_capable && ++ radeon_hw_i2c && ++ ASIC_IS_DCE3(rdev)) { ++ /* hw i2c using atom */ ++ snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), ++ "Radeon i2c hw bus %s", name); ++ i2c->adapter.algo = &radeon_atom_i2c_algo; ++ ret = i2c_add_adapter(&i2c->adapter); ++ if (ret) { ++ DRM_ERROR("Failed to register hw i2c %s\n", name); ++ goto out_free; ++ } + } else { + /* set the radeon bit adapter */ + snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), +@@ -934,10 +957,8 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, + i2c->algo.bit.setscl = set_clock; + i2c->algo.bit.getsda = get_data; + i2c->algo.bit.getscl = get_clock; +- i2c->algo.bit.udelay = 20; +- /* vesa says 2.2 ms is enough, 1 jiffy doesn't seem to always +- * make this, 2 jiffies is a lot more reliable */ +- i2c->algo.bit.timeout = 2; ++ i2c->algo.bit.udelay = 10; ++ i2c->algo.bit.timeout = usecs_to_jiffies(2200); /* from VESA */ + i2c->algo.bit.data = i2c; + ret = i2c_bit_add_bus(&i2c->adapter); + if (ret) { +@@ -967,6 +988,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, + i2c->rec = *rec; + i2c->adapter.owner = THIS_MODULE; + i2c->adapter.class = I2C_CLASS_DDC; ++ i2c->adapter.dev.parent = &dev->pdev->dev; + i2c->dev = dev; + snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), + "Radeon aux bus %s", name); +diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c +index 42f5a2b..77c456d 100644 +--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c +@@ -67,7 +67,8 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev) + unsigned i; + + /* Disable *all* interrupts */ +- rdev->irq.sw_int = false; ++ for (i = 0; i < RADEON_NUM_RINGS; i++) ++ rdev->irq.sw_int[i] = false; + rdev->irq.gui_idle = false; + for (i = 0; i < RADEON_MAX_HPD_PINS; i++) + rdev->irq.hpd[i] = false; +@@ -83,9 +84,11 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev) + int radeon_driver_irq_postinstall_kms(struct drm_device *dev) + { + struct radeon_device *rdev = dev->dev_private; ++ unsigned i; + + dev->max_vblank_count = 0x001fffff; +- rdev->irq.sw_int = true; ++ for (i = 0; i < RADEON_NUM_RINGS; i++) ++ rdev->irq.sw_int[i] = true; + radeon_irq_set(rdev); + return 0; + } +@@ -99,7 +102,8 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev) + return; + } + /* Disable *all* interrupts */ +- rdev->irq.sw_int = false; ++ for (i = 0; i < RADEON_NUM_RINGS; i++) ++ rdev->irq.sw_int[i] = false; + rdev->irq.gui_idle = false; + for (i = 0; i < RADEON_MAX_HPD_PINS; i++) + rdev->irq.hpd[i] = false; +@@ -218,26 +222,26 @@ void radeon_irq_kms_fini(struct radeon_device *rdev) + flush_work_sync(&rdev->hotplug_work); + } + +-void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev) ++void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) + { + unsigned long irqflags; + + spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); +- if (rdev->ddev->irq_enabled && (++rdev->irq.sw_refcount == 1)) { +- rdev->irq.sw_int = true; ++ if (rdev->ddev->irq_enabled && (++rdev->irq.sw_refcount[ring] == 1)) { ++ rdev->irq.sw_int[ring] = true; + radeon_irq_set(rdev); + } + spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); + } + +-void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev) ++void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) + { + unsigned long irqflags; + + spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); +- BUG_ON(rdev->ddev->irq_enabled && rdev->irq.sw_refcount <= 0); +- if (rdev->ddev->irq_enabled && (--rdev->irq.sw_refcount == 0)) { +- rdev->irq.sw_int = false; ++ BUG_ON(rdev->ddev->irq_enabled && rdev->irq.sw_refcount[ring] <= 0); ++ if (rdev->ddev->irq_enabled && (--rdev->irq.sw_refcount[ring] == 0)) { ++ rdev->irq.sw_int[ring] = false; + radeon_irq_set(rdev); + } + spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); +diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c +index 4bb9e27..9b46238 100644 +--- a/drivers/gpu/drm/radeon/radeon_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_kms.c +@@ -61,6 +61,8 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) + } + dev->dev_private = (void *)rdev; + ++ pci_set_master(dev->pdev); ++ + /* update BUS flag */ + if (drm_pci_device_is_agp(dev)) { + flags |= RADEON_IS_AGP; +@@ -173,7 +175,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) + value = rdev->accel_working; + break; + case RADEON_INFO_TILING_CONFIG: +- if (rdev->family >= CHIP_CAYMAN) ++ if (rdev->family >= CHIP_TAHITI) ++ value = rdev->config.si.tile_config; ++ else if (rdev->family >= CHIP_CAYMAN) + value = rdev->config.cayman.tile_config; + else if (rdev->family >= CHIP_CEDAR) + value = rdev->config.evergreen.tile_config; +@@ -212,7 +216,10 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) + value = rdev->clock.spll.reference_freq * 10; + break; + case RADEON_INFO_NUM_BACKENDS: +- if (rdev->family >= CHIP_CAYMAN) ++ if (rdev->family >= CHIP_TAHITI) ++ value = rdev->config.si.max_backends_per_se * ++ rdev->config.si.max_shader_engines; ++ else if (rdev->family >= CHIP_CAYMAN) + value = rdev->config.cayman.max_backends_per_se * + rdev->config.cayman.max_shader_engines; + else if (rdev->family >= CHIP_CEDAR) +@@ -226,7 +233,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) + } + break; + case RADEON_INFO_NUM_TILE_PIPES: +- if (rdev->family >= CHIP_CAYMAN) ++ if (rdev->family >= CHIP_TAHITI) ++ value = rdev->config.si.max_tile_pipes; ++ else if (rdev->family >= CHIP_CAYMAN) + value = rdev->config.cayman.max_tile_pipes; + else if (rdev->family >= CHIP_CEDAR) + value = rdev->config.evergreen.max_tile_pipes; +@@ -242,7 +251,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) + value = 1; + break; + case RADEON_INFO_BACKEND_MAP: +- if (rdev->family >= CHIP_CAYMAN) ++ if (rdev->family >= CHIP_TAHITI) ++ value = rdev->config.si.backend_map; ++ else if (rdev->family >= CHIP_CAYMAN) + value = rdev->config.cayman.backend_map; + else if (rdev->family >= CHIP_CEDAR) + value = rdev->config.evergreen.backend_map; +@@ -254,6 +265,33 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) + return -EINVAL; + } + break; ++ case RADEON_INFO_VA_START: ++ /* this is where we report if vm is supported or not */ ++ if (rdev->family < CHIP_CAYMAN) ++ return -EINVAL; ++ value = RADEON_VA_RESERVED_SIZE; ++ break; ++ case RADEON_INFO_IB_VM_MAX_SIZE: ++ /* this is where we report if vm is supported or not */ ++ if (rdev->family < CHIP_CAYMAN) ++ return -EINVAL; ++ value = RADEON_IB_VM_MAX_SIZE; ++ break; ++ case RADEON_INFO_MAX_PIPES: ++ if (rdev->family >= CHIP_TAHITI) ++ value = rdev->config.si.max_pipes_per_simd; ++ else if (rdev->family >= CHIP_CAYMAN) ++ value = rdev->config.cayman.max_pipes_per_simd; ++ else if (rdev->family >= CHIP_CEDAR) ++ value = rdev->config.evergreen.max_pipes; ++ else if (rdev->family >= CHIP_RV770) ++ value = rdev->config.rv770.max_pipes; ++ else if (rdev->family >= CHIP_R600) ++ value = rdev->config.r600.max_pipes; ++ else { ++ return -EINVAL; ++ } ++ break; + default: + DRM_DEBUG_KMS("Invalid request %d\n", info->request); + return -EINVAL; +@@ -274,7 +312,6 @@ int radeon_driver_firstopen_kms(struct drm_device *dev) + return 0; + } + +- + void radeon_driver_lastclose_kms(struct drm_device *dev) + { + vga_switcheroo_process_delayed_switch(); +@@ -282,12 +319,45 @@ void radeon_driver_lastclose_kms(struct drm_device *dev) + + int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) + { ++ struct radeon_device *rdev = dev->dev_private; ++ ++ file_priv->driver_priv = NULL; ++ ++ /* new gpu have virtual address space support */ ++ if (rdev->family >= CHIP_CAYMAN) { ++ struct radeon_fpriv *fpriv; ++ int r; ++ ++ fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); ++ if (unlikely(!fpriv)) { ++ return -ENOMEM; ++ } ++ ++ r = radeon_vm_init(rdev, &fpriv->vm); ++ if (r) { ++ radeon_vm_fini(rdev, &fpriv->vm); ++ kfree(fpriv); ++ return r; ++ } ++ ++ file_priv->driver_priv = fpriv; ++ } + return 0; + } + + void radeon_driver_postclose_kms(struct drm_device *dev, + struct drm_file *file_priv) + { ++ struct radeon_device *rdev = dev->dev_private; ++ ++ /* new gpu have virtual address space support */ ++ if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) { ++ struct radeon_fpriv *fpriv = file_priv->driver_priv; ++ ++ radeon_vm_fini(rdev, &fpriv->vm); ++ kfree(fpriv); ++ file_priv->driver_priv = NULL; ++ } + } + + void radeon_driver_preclose_kms(struct drm_device *dev, +@@ -455,5 +525,6 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = { + DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED), ++ DRM_IOCTL_DEF_DRV(RADEON_GEM_VA, radeon_gem_va_ioctl, DRM_AUTH|DRM_UNLOCKED), + }; + int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms); +diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +index a9238b0..b44bbf5 100644 +--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c ++++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +@@ -420,7 +420,9 @@ retry: + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; +- r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &base); ++ /* Only 27 bit offset for legacy CRTC */ ++ r = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, 1 << 27, ++ &base); + if (unlikely(r != 0)) { + radeon_bo_unreserve(rbo); + +@@ -465,7 +467,7 @@ retry: + + crtc_offset_cntl = 0; + +- pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8); ++ pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + crtc_pitch = (((pitch_pixels * target_fb->bits_per_pixel) + + ((target_fb->bits_per_pixel * 8) - 1)) / + (target_fb->bits_per_pixel * 8)); +@@ -1051,9 +1053,11 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc, + + static void radeon_crtc_prepare(struct drm_crtc *crtc) + { ++ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_crtc *crtci; + ++ radeon_crtc->in_mode_set = true; + /* + * The hardware wedges sometimes if you reconfigure one CRTC + * whilst another is running (see fdo bug #24611). +@@ -1064,6 +1068,7 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc) + + static void radeon_crtc_commit(struct drm_crtc *crtc) + { ++ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_crtc *crtci; + +@@ -1074,6 +1079,7 @@ static void radeon_crtc_commit(struct drm_crtc *crtc) + if (crtci->enabled) + radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON); + } ++ radeon_crtc->in_mode_set = false; + } + + static const struct drm_crtc_helper_funcs legacy_helper_funcs = { +diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +index a906803..53b07a3 100644 +--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c ++++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +@@ -88,7 +88,7 @@ static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode) + lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); + lvds_pll_cntl |= RADEON_LVDS_PLL_EN; + WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); +- udelay(1000); ++ mdelay(1); + + lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); + lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; +@@ -101,7 +101,7 @@ static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode) + (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT)); + if (is_mac) + lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN; +- udelay(panel_pwr_delay * 1000); ++ mdelay(panel_pwr_delay); + WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + break; + case DRM_MODE_DPMS_STANDBY: +@@ -118,10 +118,10 @@ static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode) + WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON); + } +- udelay(panel_pwr_delay * 1000); ++ mdelay(panel_pwr_delay); + WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); +- udelay(panel_pwr_delay * 1000); ++ mdelay(panel_pwr_delay); + break; + } + +@@ -665,7 +665,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc + + WREG32(RADEON_DAC_MACRO_CNTL, tmp); + +- udelay(2000); ++ mdelay(2); + + if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) + found = connector_status_connected; +@@ -1504,7 +1504,7 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder + tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN; + WREG32(RADEON_DAC_CNTL2, tmp); + +- udelay(10000); ++ mdelay(10); + + if (ASIC_IS_R300(rdev)) { + if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) +diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h +index bb42df4..65da706 100644 +--- a/drivers/gpu/drm/radeon/radeon_mode.h ++++ b/drivers/gpu/drm/radeon/radeon_mode.h +@@ -268,6 +268,7 @@ struct radeon_crtc { + u16 lut_r[256], lut_g[256], lut_b[256]; + bool enabled; + bool can_tile; ++ bool in_mode_set; + uint32_t crtc_offset; + struct drm_gem_object *cursor_bo; + uint64_t cursor_addr; +@@ -469,6 +470,10 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev); + + extern struct drm_connector * + radeon_get_connector_for_encoder(struct drm_encoder *encoder); ++extern struct drm_connector * ++radeon_get_connector_for_encoder_init(struct drm_encoder *encoder); ++extern bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder, ++ u32 pixel_clock); + + extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder); + extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector); +@@ -489,6 +494,7 @@ extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder, + struct drm_connector *connector); + extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode); + extern void radeon_atom_encoder_init(struct radeon_device *rdev); ++extern void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev); + extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, + int action, uint8_t lane_num, + uint8_t lane_set); +@@ -646,9 +652,9 @@ extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, + u16 blue, int regno); + extern void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, int regno); +-void radeon_framebuffer_init(struct drm_device *dev, ++int radeon_framebuffer_init(struct drm_device *dev, + struct radeon_framebuffer *rfb, +- struct drm_mode_fb_cmd *mode_cmd, ++ struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj); + + int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); +diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c +index 3e35bbe..df6a4db 100644 +--- a/drivers/gpu/drm/radeon/radeon_object.c ++++ b/drivers/gpu/drm/radeon/radeon_object.c +@@ -46,6 +46,20 @@ static void radeon_bo_clear_surface_reg(struct radeon_bo *bo); + * function are calling it. + */ + ++void radeon_bo_clear_va(struct radeon_bo *bo) ++{ ++ struct radeon_bo_va *bo_va, *tmp; ++ ++ list_for_each_entry_safe(bo_va, tmp, &bo->va, bo_list) { ++ /* remove from all vm address space */ ++ mutex_lock(&bo_va->vm->mutex); ++ list_del(&bo_va->vm_list); ++ mutex_unlock(&bo_va->vm->mutex); ++ list_del(&bo_va->bo_list); ++ kfree(bo_va); ++ } ++} ++ + static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo) + { + struct radeon_bo *bo; +@@ -55,6 +69,7 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo) + list_del_init(&bo->list); + mutex_unlock(&bo->rdev->gem.mutex); + radeon_bo_clear_surface_reg(bo); ++ radeon_bo_clear_va(bo); + drm_gem_object_release(&bo->gem_base); + kfree(bo); + } +@@ -95,6 +110,7 @@ int radeon_bo_create(struct radeon_device *rdev, + enum ttm_bo_type type; + unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT; + unsigned long max_size = 0; ++ size_t acc_size; + int r; + + size = ALIGN(size, PAGE_SIZE); +@@ -117,6 +133,9 @@ int radeon_bo_create(struct radeon_device *rdev, + return -ENOMEM; + } + ++ acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, ++ sizeof(struct radeon_bo)); ++ + retry: + bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); + if (bo == NULL) +@@ -130,12 +149,13 @@ retry: + bo->gem_base.driver_private = NULL; + bo->surface_reg = -1; + INIT_LIST_HEAD(&bo->list); ++ INIT_LIST_HEAD(&bo->va); + radeon_ttm_placement_from_domain(bo, domain); + /* Kernel allocation are uninterruptible */ + mutex_lock(&rdev->vram_mutex); + r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type, +- &bo->placement, page_align, 0, !kernel, NULL, size, +- &radeon_ttm_bo_destroy); ++ &bo->placement, page_align, 0, !kernel, NULL, ++ acc_size, &radeon_ttm_bo_destroy); + mutex_unlock(&rdev->vram_mutex); + if (unlikely(r != 0)) { + if (r != -ERESTARTSYS) { +@@ -213,7 +233,18 @@ int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset, + bo->pin_count++; + if (gpu_addr) + *gpu_addr = radeon_bo_gpu_offset(bo); +- WARN_ON_ONCE(max_offset != 0); ++ ++ if (max_offset != 0) { ++ u64 domain_start; ++ ++ if (domain == RADEON_GEM_DOMAIN_VRAM) ++ domain_start = bo->rdev->mc.vram_start; ++ else ++ domain_start = bo->rdev->mc.gtt_start; ++ WARN_ON_ONCE(max_offset < ++ (radeon_bo_gpu_offset(bo) - domain_start)); ++ } ++ + return 0; + } + radeon_ttm_placement_from_domain(bo, domain); +@@ -441,8 +472,54 @@ static void radeon_bo_clear_surface_reg(struct radeon_bo *bo) + int radeon_bo_set_tiling_flags(struct radeon_bo *bo, + uint32_t tiling_flags, uint32_t pitch) + { ++ struct radeon_device *rdev = bo->rdev; + int r; + ++ if (rdev->family >= CHIP_CEDAR) { ++ unsigned bankw, bankh, mtaspect, tilesplit, stilesplit; ++ ++ bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK; ++ bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK; ++ mtaspect = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK; ++ tilesplit = (tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK; ++ stilesplit = (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK; ++ switch (bankw) { ++ case 0: ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ break; ++ default: ++ return -EINVAL; ++ } ++ switch (bankh) { ++ case 0: ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ break; ++ default: ++ return -EINVAL; ++ } ++ switch (mtaspect) { ++ case 0: ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (tilesplit > 6) { ++ return -EINVAL; ++ } ++ if (stilesplit > 6) { ++ return -EINVAL; ++ } ++ } + r = radeon_bo_reserve(bo, false); + if (unlikely(r != 0)) + return r; +@@ -499,6 +576,7 @@ void radeon_bo_move_notify(struct ttm_buffer_object *bo, + return; + rbo = container_of(bo, struct radeon_bo, tbo); + radeon_bo_check_tiling(rbo, 0, 1); ++ radeon_vm_bo_invalidate(rbo->rdev, rbo); + } + + int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) +@@ -513,30 +591,22 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) + rbo = container_of(bo, struct radeon_bo, tbo); + radeon_bo_check_tiling(rbo, 0, 0); + rdev = rbo->rdev; +- if (bo->mem.mem_type != TTM_PL_VRAM) +- return 0; +- +- size = bo->mem.num_pages << PAGE_SHIFT; +- offset = bo->mem.start << PAGE_SHIFT; +- if ((offset + size) <= rdev->mc.visible_vram_size) +- return 0; +- +- /* hurrah the memory is not visible ! */ +- radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); +- rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; +- r = ttm_bo_validate(bo, &rbo->placement, false, true, false); +- if (unlikely(r == -ENOMEM)) { +- radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); +- return ttm_bo_validate(bo, &rbo->placement, false, true, false); +- } else if (unlikely(r != 0)) { +- return r; ++ if (bo->mem.mem_type == TTM_PL_VRAM) { ++ size = bo->mem.num_pages << PAGE_SHIFT; ++ offset = bo->mem.start << PAGE_SHIFT; ++ if ((offset + size) > rdev->mc.visible_vram_size) { ++ /* hurrah the memory is not visible ! */ ++ radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); ++ rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; ++ r = ttm_bo_validate(bo, &rbo->placement, false, true, false); ++ if (unlikely(r != 0)) ++ return r; ++ offset = bo->mem.start << PAGE_SHIFT; ++ /* this should not happen */ ++ if ((offset + size) > rdev->mc.visible_vram_size) ++ return -EINVAL; ++ } + } +- +- offset = bo->mem.start << PAGE_SHIFT; +- /* this should never happen */ +- if ((offset + size) > rdev->mc.visible_vram_size) +- return -EINVAL; +- + return 0; + } + +@@ -580,3 +650,16 @@ int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait) + } + return 0; + } ++ ++/* object have to be reserved */ ++struct radeon_bo_va *radeon_bo_va(struct radeon_bo *rbo, struct radeon_vm *vm) ++{ ++ struct radeon_bo_va *bo_va; ++ ++ list_for_each_entry(bo_va, &rbo->va, bo_list) { ++ if (bo_va->vm == vm) { ++ return bo_va; ++ } ++ } ++ return NULL; ++} +diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h +index fb3f433..f9104be 100644 +--- a/drivers/gpu/drm/radeon/radeon_object.h ++++ b/drivers/gpu/drm/radeon/radeon_object.h +@@ -83,6 +83,16 @@ static inline bool radeon_bo_is_reserved(struct radeon_bo *bo) + return !!atomic_read(&bo->tbo.reserved); + } + ++static inline unsigned radeon_bo_ngpu_pages(struct radeon_bo *bo) ++{ ++ return (bo->tbo.num_pages << PAGE_SHIFT) / RADEON_GPU_PAGE_SIZE; ++} ++ ++static inline unsigned radeon_bo_gpu_page_alignment(struct radeon_bo *bo) ++{ ++ return (bo->tbo.mem.page_alignment << PAGE_SHIFT) / RADEON_GPU_PAGE_SIZE; ++} ++ + /** + * radeon_bo_mmap_offset - return mmap offset of bo + * @bo: radeon object for which we query the offset +@@ -130,4 +140,26 @@ extern void radeon_bo_move_notify(struct ttm_buffer_object *bo, + struct ttm_mem_reg *mem); + extern int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); + extern int radeon_bo_get_surface_reg(struct radeon_bo *bo); ++extern struct radeon_bo_va *radeon_bo_va(struct radeon_bo *rbo, ++ struct radeon_vm *vm); ++ ++/* ++ * sub allocation ++ */ ++extern int radeon_sa_bo_manager_init(struct radeon_device *rdev, ++ struct radeon_sa_manager *sa_manager, ++ unsigned size, u32 domain); ++extern void radeon_sa_bo_manager_fini(struct radeon_device *rdev, ++ struct radeon_sa_manager *sa_manager); ++extern int radeon_sa_bo_manager_start(struct radeon_device *rdev, ++ struct radeon_sa_manager *sa_manager); ++extern int radeon_sa_bo_manager_suspend(struct radeon_device *rdev, ++ struct radeon_sa_manager *sa_manager); ++extern int radeon_sa_bo_new(struct radeon_device *rdev, ++ struct radeon_sa_manager *sa_manager, ++ struct radeon_sa_bo *sa_bo, ++ unsigned size, unsigned align); ++extern void radeon_sa_bo_free(struct radeon_device *rdev, ++ struct radeon_sa_bo *sa_bo); ++ + #endif +diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c +index b0a0ee4..4c5a793 100644 +--- a/drivers/gpu/drm/radeon/radeon_pm.c ++++ b/drivers/gpu/drm/radeon/radeon_pm.c +@@ -221,7 +221,7 @@ static void radeon_set_power_state(struct radeon_device *rdev) + } + + /* set memory clock */ +- if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { ++ if (rdev->asic->pm.set_memory_clock && (mclk != rdev->pm.current_mclk)) { + radeon_pm_debug_check_in_vbl(rdev, false); + radeon_set_memory_clock(rdev, mclk); + radeon_pm_debug_check_in_vbl(rdev, true); +@@ -252,7 +252,10 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) + + mutex_lock(&rdev->ddev->struct_mutex); + mutex_lock(&rdev->vram_mutex); +- mutex_lock(&rdev->cp.mutex); ++ for (i = 0; i < RADEON_NUM_RINGS; ++i) { ++ if (rdev->ring[i].ring_obj) ++ mutex_lock(&rdev->ring[i].mutex); ++ } + + /* gui idle int has issues on older chips it seems */ + if (rdev->family >= CHIP_R600) { +@@ -268,12 +271,13 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) + radeon_irq_set(rdev); + } + } else { +- if (rdev->cp.ready) { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ if (ring->ready) { + struct radeon_fence *fence; +- radeon_ring_alloc(rdev, 64); +- radeon_fence_create(rdev, &fence); ++ radeon_ring_alloc(rdev, ring, 64); ++ radeon_fence_create(rdev, &fence, radeon_ring_index(rdev, ring)); + radeon_fence_emit(rdev, fence); +- radeon_ring_commit(rdev); ++ radeon_ring_commit(rdev, ring); + radeon_fence_wait(fence, false); + radeon_fence_unref(&fence); + } +@@ -307,7 +311,10 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) + + rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; + +- mutex_unlock(&rdev->cp.mutex); ++ for (i = 0; i < RADEON_NUM_RINGS; ++i) { ++ if (rdev->ring[i].ring_obj) ++ mutex_unlock(&rdev->ring[i].mutex); ++ } + mutex_unlock(&rdev->vram_mutex); + mutex_unlock(&rdev->ddev->struct_mutex); + } +@@ -467,6 +474,9 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev, + case THERMAL_TYPE_SUMO: + temp = sumo_get_temp(rdev); + break; ++ case THERMAL_TYPE_SI: ++ temp = si_get_temp(rdev); ++ break; + default: + temp = 0; + break; +@@ -507,6 +517,10 @@ static int radeon_hwmon_init(struct radeon_device *rdev) + case THERMAL_TYPE_EVERGREEN: + case THERMAL_TYPE_NI: + case THERMAL_TYPE_SUMO: ++ case THERMAL_TYPE_SI: ++ /* No support for TN yet */ ++ if (rdev->family == CHIP_ARUBA) ++ return err; + rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); + if (IS_ERR(rdev->pm.int_hwmon_dev)) { + err = PTR_ERR(rdev->pm.int_hwmon_dev); +@@ -801,19 +815,14 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work) + resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); + mutex_lock(&rdev->pm.mutex); + if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) { +- unsigned long irq_flags; + int not_processed = 0; ++ int i; + +- read_lock_irqsave(&rdev->fence_drv.lock, irq_flags); +- if (!list_empty(&rdev->fence_drv.emited)) { +- struct list_head *ptr; +- list_for_each(ptr, &rdev->fence_drv.emited) { +- /* count up to 3, that's enought info */ +- if (++not_processed >= 3) +- break; +- } ++ for (i = 0; i < RADEON_NUM_RINGS; ++i) { ++ not_processed += radeon_fence_count_emitted(rdev, i); ++ if (not_processed >= 3) ++ break; + } +- read_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); + + if (not_processed >= 3) { /* should upclock */ + if (rdev->pm.dynpm_planned_action == DYNPM_ACTION_DOWNCLOCK) { +@@ -871,11 +880,11 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data) + else + seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev)); + seq_printf(m, "default memory clock: %u0 kHz\n", rdev->pm.default_mclk); +- if (rdev->asic->get_memory_clock) ++ if (rdev->asic->pm.get_memory_clock) + seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); + if (rdev->pm.current_vddc) + seq_printf(m, "voltage: %u mV\n", rdev->pm.current_vddc); +- if (rdev->asic->get_pcie_lanes) ++ if (rdev->asic->pm.get_pcie_lanes) + seq_printf(m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev)); + + return 0; +diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h +index b4ce864..5d8f735 100644 +--- a/drivers/gpu/drm/radeon/radeon_reg.h ++++ b/drivers/gpu/drm/radeon/radeon_reg.h +@@ -56,6 +56,7 @@ + #include "r600_reg.h" + #include "evergreen_reg.h" + #include "ni_reg.h" ++#include "si_reg.h" + + #define RADEON_MC_AGP_LOCATION 0x014c + #define RADEON_MC_AGP_START_MASK 0x0000FFFF +@@ -539,9 +540,11 @@ + + #define RADEON_CRTC2_PITCH 0x032c + #define RADEON_CRTC_STATUS 0x005c ++# define RADEON_CRTC_VBLANK_CUR (1 << 0) + # define RADEON_CRTC_VBLANK_SAVE (1 << 1) + # define RADEON_CRTC_VBLANK_SAVE_CLEAR (1 << 1) + #define RADEON_CRTC2_STATUS 0x03fc ++# define RADEON_CRTC2_VBLANK_CUR (1 << 0) + # define RADEON_CRTC2_VBLANK_SAVE (1 << 1) + # define RADEON_CRTC2_VBLANK_SAVE_CLEAR (1 << 1) + #define RADEON_CRTC_V_SYNC_STRT_WID 0x020c +diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c +index 65be5e8..33eff8b 100644 +--- a/drivers/gpu/drm/radeon/radeon_ring.c ++++ b/drivers/gpu/drm/radeon/radeon_ring.c +@@ -34,6 +34,7 @@ + #include "atom.h" + + int radeon_debugfs_ib_init(struct radeon_device *rdev); ++int radeon_debugfs_ring_init(struct radeon_device *rdev); + + u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx) + { +@@ -60,105 +61,107 @@ u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx) + return idx_value; + } + +-void radeon_ring_write(struct radeon_device *rdev, uint32_t v) ++void radeon_ring_write(struct radeon_ring *ring, uint32_t v) + { + #if DRM_DEBUG_CODE +- if (rdev->cp.count_dw <= 0) { ++ if (ring->count_dw <= 0) { + DRM_ERROR("radeon: writting more dword to ring than expected !\n"); + } + #endif +- rdev->cp.ring[rdev->cp.wptr++] = v; +- rdev->cp.wptr &= rdev->cp.ptr_mask; +- rdev->cp.count_dw--; +- rdev->cp.ring_free_dw--; ++ ring->ring[ring->wptr++] = v; ++ ring->wptr &= ring->ptr_mask; ++ ring->count_dw--; ++ ring->ring_free_dw--; + } + +-void radeon_ib_bogus_cleanup(struct radeon_device *rdev) +-{ +- struct radeon_ib *ib, *n; +- +- list_for_each_entry_safe(ib, n, &rdev->ib_pool.bogus_ib, list) { +- list_del(&ib->list); +- vfree(ib->ptr); +- kfree(ib); +- } +-} +- +-void radeon_ib_bogus_add(struct radeon_device *rdev, struct radeon_ib *ib) ++/* ++ * IB. ++ */ ++bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib) + { +- struct radeon_ib *bib; +- +- bib = kmalloc(sizeof(*bib), GFP_KERNEL); +- if (bib == NULL) +- return; +- bib->ptr = vmalloc(ib->length_dw * 4); +- if (bib->ptr == NULL) { +- kfree(bib); +- return; ++ bool done = false; ++ ++ /* only free ib which have been emited */ ++ if (ib->fence && ib->fence->emitted) { ++ if (radeon_fence_signaled(ib->fence)) { ++ radeon_fence_unref(&ib->fence); ++ radeon_sa_bo_free(rdev, &ib->sa_bo); ++ done = true; ++ } + } +- memcpy(bib->ptr, ib->ptr, ib->length_dw * 4); +- bib->length_dw = ib->length_dw; +- mutex_lock(&rdev->ib_pool.mutex); +- list_add_tail(&bib->list, &rdev->ib_pool.bogus_ib); +- mutex_unlock(&rdev->ib_pool.mutex); ++ return done; + } + +-/* +- * IB. +- */ +-int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib) ++int radeon_ib_get(struct radeon_device *rdev, int ring, ++ struct radeon_ib **ib, unsigned size) + { + struct radeon_fence *fence; +- struct radeon_ib *nib; +- int r = 0, i, c; ++ unsigned cretry = 0; ++ int r = 0, i, idx; + + *ib = NULL; +- r = radeon_fence_create(rdev, &fence); ++ /* align size on 256 bytes */ ++ size = ALIGN(size, 256); ++ ++ r = radeon_fence_create(rdev, &fence, ring); + if (r) { + dev_err(rdev->dev, "failed to create fence for new IB\n"); + return r; + } +- mutex_lock(&rdev->ib_pool.mutex); +- for (i = rdev->ib_pool.head_id, c = 0, nib = NULL; c < RADEON_IB_POOL_SIZE; c++, i++) { +- i &= (RADEON_IB_POOL_SIZE - 1); +- if (rdev->ib_pool.ibs[i].free) { +- nib = &rdev->ib_pool.ibs[i]; +- break; +- } +- } +- if (nib == NULL) { +- /* This should never happen, it means we allocated all +- * IB and haven't scheduled one yet, return EBUSY to +- * userspace hoping that on ioctl recall we get better +- * luck +- */ +- dev_err(rdev->dev, "no free indirect buffer !\n"); +- mutex_unlock(&rdev->ib_pool.mutex); ++ ++ radeon_mutex_lock(&rdev->ib_pool.mutex); ++ idx = rdev->ib_pool.head_id; ++retry: ++ if (cretry > 5) { ++ dev_err(rdev->dev, "failed to get an ib after 5 retry\n"); ++ radeon_mutex_unlock(&rdev->ib_pool.mutex); + radeon_fence_unref(&fence); +- return -EBUSY; ++ return -ENOMEM; + } +- rdev->ib_pool.head_id = (nib->idx + 1) & (RADEON_IB_POOL_SIZE - 1); +- nib->free = false; +- if (nib->fence) { +- mutex_unlock(&rdev->ib_pool.mutex); +- r = radeon_fence_wait(nib->fence, false); +- if (r) { +- dev_err(rdev->dev, "error waiting fence of IB(%u:0x%016lX:%u)\n", +- nib->idx, (unsigned long)nib->gpu_addr, nib->length_dw); +- mutex_lock(&rdev->ib_pool.mutex); +- nib->free = true; +- mutex_unlock(&rdev->ib_pool.mutex); +- radeon_fence_unref(&fence); +- return r; ++ cretry++; ++ for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { ++ radeon_ib_try_free(rdev, &rdev->ib_pool.ibs[idx]); ++ if (rdev->ib_pool.ibs[idx].fence == NULL) { ++ r = radeon_sa_bo_new(rdev, &rdev->ib_pool.sa_manager, ++ &rdev->ib_pool.ibs[idx].sa_bo, ++ size, 256); ++ if (!r) { ++ *ib = &rdev->ib_pool.ibs[idx]; ++ (*ib)->ptr = rdev->ib_pool.sa_manager.cpu_ptr; ++ (*ib)->ptr += ((*ib)->sa_bo.offset >> 2); ++ (*ib)->gpu_addr = rdev->ib_pool.sa_manager.gpu_addr; ++ (*ib)->gpu_addr += (*ib)->sa_bo.offset; ++ (*ib)->fence = fence; ++ (*ib)->vm_id = 0; ++ (*ib)->is_const_ib = false; ++ /* ib are most likely to be allocated in a ring fashion ++ * thus rdev->ib_pool.head_id should be the id of the ++ * oldest ib ++ */ ++ rdev->ib_pool.head_id = (1 + idx); ++ rdev->ib_pool.head_id &= (RADEON_IB_POOL_SIZE - 1); ++ radeon_mutex_unlock(&rdev->ib_pool.mutex); ++ return 0; ++ } + } +- mutex_lock(&rdev->ib_pool.mutex); ++ idx = (idx + 1) & (RADEON_IB_POOL_SIZE - 1); + } +- radeon_fence_unref(&nib->fence); +- nib->fence = fence; +- nib->length_dw = 0; +- mutex_unlock(&rdev->ib_pool.mutex); +- *ib = nib; +- return 0; ++ /* this should be rare event, ie all ib scheduled none signaled yet. ++ */ ++ for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { ++ if (rdev->ib_pool.ibs[idx].fence && rdev->ib_pool.ibs[idx].fence->emitted) { ++ r = radeon_fence_wait(rdev->ib_pool.ibs[idx].fence, false); ++ if (!r) { ++ goto retry; ++ } ++ /* an error happened */ ++ break; ++ } ++ idx = (idx + 1) & (RADEON_IB_POOL_SIZE - 1); ++ } ++ radeon_mutex_unlock(&rdev->ib_pool.mutex); ++ radeon_fence_unref(&fence); ++ return r; + } + + void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib) +@@ -169,250 +172,261 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib) + if (tmp == NULL) { + return; + } +- if (!tmp->fence->emited) ++ radeon_mutex_lock(&rdev->ib_pool.mutex); ++ if (tmp->fence && !tmp->fence->emitted) { ++ radeon_sa_bo_free(rdev, &tmp->sa_bo); + radeon_fence_unref(&tmp->fence); +- mutex_lock(&rdev->ib_pool.mutex); +- tmp->free = true; +- mutex_unlock(&rdev->ib_pool.mutex); ++ } ++ radeon_mutex_unlock(&rdev->ib_pool.mutex); + } + + int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) + { ++ struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; + int r = 0; + +- if (!ib->length_dw || !rdev->cp.ready) { ++ if (!ib->length_dw || !ring->ready) { + /* TODO: Nothings in the ib we should report. */ + DRM_ERROR("radeon: couldn't schedule IB(%u).\n", ib->idx); + return -EINVAL; + } + + /* 64 dwords should be enough for fence too */ +- r = radeon_ring_lock(rdev, 64); ++ r = radeon_ring_lock(rdev, ring, 64); + if (r) { + DRM_ERROR("radeon: scheduling IB failed (%d).\n", r); + return r; + } +- radeon_ring_ib_execute(rdev, ib); ++ radeon_ring_ib_execute(rdev, ib->fence->ring, ib); + radeon_fence_emit(rdev, ib->fence); +- mutex_lock(&rdev->ib_pool.mutex); +- /* once scheduled IB is considered free and protected by the fence */ +- ib->free = true; +- mutex_unlock(&rdev->ib_pool.mutex); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_unlock_commit(rdev, ring); + return 0; + } + + int radeon_ib_pool_init(struct radeon_device *rdev) + { +- void *ptr; +- uint64_t gpu_addr; +- int i; +- int r = 0; ++ struct radeon_sa_manager tmp; ++ int i, r; + +- if (rdev->ib_pool.robj) +- return 0; +- INIT_LIST_HEAD(&rdev->ib_pool.bogus_ib); +- /* Allocate 1M object buffer */ +- r = radeon_bo_create(rdev, RADEON_IB_POOL_SIZE*64*1024, +- PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT, +- &rdev->ib_pool.robj); ++ r = radeon_sa_bo_manager_init(rdev, &tmp, ++ RADEON_IB_POOL_SIZE*64*1024, ++ RADEON_GEM_DOMAIN_GTT); + if (r) { +- DRM_ERROR("radeon: failed to ib pool (%d).\n", r); + return r; + } +- r = radeon_bo_reserve(rdev->ib_pool.robj, false); +- if (unlikely(r != 0)) +- return r; +- r = radeon_bo_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr); +- if (r) { +- radeon_bo_unreserve(rdev->ib_pool.robj); +- DRM_ERROR("radeon: failed to pin ib pool (%d).\n", r); +- return r; +- } +- r = radeon_bo_kmap(rdev->ib_pool.robj, &ptr); +- radeon_bo_unreserve(rdev->ib_pool.robj); +- if (r) { +- DRM_ERROR("radeon: failed to map ib pool (%d).\n", r); +- return r; ++ ++ radeon_mutex_lock(&rdev->ib_pool.mutex); ++ if (rdev->ib_pool.ready) { ++ radeon_mutex_unlock(&rdev->ib_pool.mutex); ++ radeon_sa_bo_manager_fini(rdev, &tmp); ++ return 0; + } +- for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { +- unsigned offset; + +- offset = i * 64 * 1024; +- rdev->ib_pool.ibs[i].gpu_addr = gpu_addr + offset; +- rdev->ib_pool.ibs[i].ptr = ptr + offset; ++ rdev->ib_pool.sa_manager = tmp; ++ INIT_LIST_HEAD(&rdev->ib_pool.sa_manager.sa_bo); ++ for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { ++ rdev->ib_pool.ibs[i].fence = NULL; + rdev->ib_pool.ibs[i].idx = i; + rdev->ib_pool.ibs[i].length_dw = 0; +- rdev->ib_pool.ibs[i].free = true; ++ INIT_LIST_HEAD(&rdev->ib_pool.ibs[i].sa_bo.list); + } + rdev->ib_pool.head_id = 0; + rdev->ib_pool.ready = true; + DRM_INFO("radeon: ib pool ready.\n"); ++ + if (radeon_debugfs_ib_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for IB !\n"); + } +- return r; ++ if (radeon_debugfs_ring_init(rdev)) { ++ DRM_ERROR("Failed to register debugfs file for rings !\n"); ++ } ++ radeon_mutex_unlock(&rdev->ib_pool.mutex); ++ return 0; + } + + void radeon_ib_pool_fini(struct radeon_device *rdev) + { +- int r; +- struct radeon_bo *robj; ++ unsigned i; + +- if (!rdev->ib_pool.ready) { +- return; +- } +- mutex_lock(&rdev->ib_pool.mutex); +- radeon_ib_bogus_cleanup(rdev); +- robj = rdev->ib_pool.robj; +- rdev->ib_pool.robj = NULL; +- mutex_unlock(&rdev->ib_pool.mutex); +- +- if (robj) { +- r = radeon_bo_reserve(robj, false); +- if (likely(r == 0)) { +- radeon_bo_kunmap(robj); +- radeon_bo_unpin(robj); +- radeon_bo_unreserve(robj); ++ radeon_mutex_lock(&rdev->ib_pool.mutex); ++ if (rdev->ib_pool.ready) { ++ for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { ++ radeon_sa_bo_free(rdev, &rdev->ib_pool.ibs[i].sa_bo); ++ radeon_fence_unref(&rdev->ib_pool.ibs[i].fence); + } +- radeon_bo_unref(&robj); ++ radeon_sa_bo_manager_fini(rdev, &rdev->ib_pool.sa_manager); ++ rdev->ib_pool.ready = false; + } ++ radeon_mutex_unlock(&rdev->ib_pool.mutex); ++} ++ ++int radeon_ib_pool_start(struct radeon_device *rdev) ++{ ++ return radeon_sa_bo_manager_start(rdev, &rdev->ib_pool.sa_manager); + } + ++int radeon_ib_pool_suspend(struct radeon_device *rdev) ++{ ++ return radeon_sa_bo_manager_suspend(rdev, &rdev->ib_pool.sa_manager); ++} + + /* + * Ring. + */ +-void radeon_ring_free_size(struct radeon_device *rdev) ++int radeon_ring_index(struct radeon_device *rdev, struct radeon_ring *ring) + { +- if (rdev->wb.enabled) +- rdev->cp.rptr = le32_to_cpu(rdev->wb.wb[RADEON_WB_CP_RPTR_OFFSET/4]); +- else { +- if (rdev->family >= CHIP_R600) +- rdev->cp.rptr = RREG32(R600_CP_RB_RPTR); +- else +- rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); ++ /* r1xx-r5xx only has CP ring */ ++ if (rdev->family < CHIP_R600) ++ return RADEON_RING_TYPE_GFX_INDEX; ++ ++ if (rdev->family >= CHIP_CAYMAN) { ++ if (ring == &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]) ++ return CAYMAN_RING_TYPE_CP1_INDEX; ++ else if (ring == &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]) ++ return CAYMAN_RING_TYPE_CP2_INDEX; + } ++ return RADEON_RING_TYPE_GFX_INDEX; ++} ++ ++void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) ++{ ++ u32 rptr; ++ ++ if (rdev->wb.enabled) ++ rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]); ++ else ++ rptr = RREG32(ring->rptr_reg); ++ ring->rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; + /* This works because ring_size is a power of 2 */ +- rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4)); +- rdev->cp.ring_free_dw -= rdev->cp.wptr; +- rdev->cp.ring_free_dw &= rdev->cp.ptr_mask; +- if (!rdev->cp.ring_free_dw) { +- rdev->cp.ring_free_dw = rdev->cp.ring_size / 4; ++ ring->ring_free_dw = (ring->rptr + (ring->ring_size / 4)); ++ ring->ring_free_dw -= ring->wptr; ++ ring->ring_free_dw &= ring->ptr_mask; ++ if (!ring->ring_free_dw) { ++ ring->ring_free_dw = ring->ring_size / 4; + } + } + +-int radeon_ring_alloc(struct radeon_device *rdev, unsigned ndw) ++ ++int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) + { + int r; + + /* make sure we aren't trying to allocate more space than there is on the ring */ +- if (ndw > (rdev->cp.ring_size / 4)) ++ if (ndw > (ring->ring_size / 4)) + return -ENOMEM; + /* Align requested size with padding so unlock_commit can + * pad safely */ +- ndw = (ndw + rdev->cp.align_mask) & ~rdev->cp.align_mask; +- while (ndw > (rdev->cp.ring_free_dw - 1)) { +- radeon_ring_free_size(rdev); +- if (ndw < rdev->cp.ring_free_dw) { ++ ndw = (ndw + ring->align_mask) & ~ring->align_mask; ++ while (ndw > (ring->ring_free_dw - 1)) { ++ radeon_ring_free_size(rdev, ring); ++ if (ndw < ring->ring_free_dw) { + break; + } +- r = radeon_fence_wait_next(rdev); ++ r = radeon_fence_wait_next(rdev, radeon_ring_index(rdev, ring)); + if (r) + return r; + } +- rdev->cp.count_dw = ndw; +- rdev->cp.wptr_old = rdev->cp.wptr; ++ ring->count_dw = ndw; ++ ring->wptr_old = ring->wptr; + return 0; + } + +-int radeon_ring_lock(struct radeon_device *rdev, unsigned ndw) ++int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) + { + int r; + +- mutex_lock(&rdev->cp.mutex); +- r = radeon_ring_alloc(rdev, ndw); ++ mutex_lock(&ring->mutex); ++ r = radeon_ring_alloc(rdev, ring, ndw); + if (r) { +- mutex_unlock(&rdev->cp.mutex); ++ mutex_unlock(&ring->mutex); + return r; + } + return 0; + } + +-void radeon_ring_commit(struct radeon_device *rdev) ++void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) + { + unsigned count_dw_pad; + unsigned i; + + /* We pad to match fetch size */ +- count_dw_pad = (rdev->cp.align_mask + 1) - +- (rdev->cp.wptr & rdev->cp.align_mask); ++ count_dw_pad = (ring->align_mask + 1) - ++ (ring->wptr & ring->align_mask); + for (i = 0; i < count_dw_pad; i++) { +- radeon_ring_write(rdev, 2 << 30); ++ radeon_ring_write(ring, ring->nop); + } + DRM_MEMORYBARRIER(); +- radeon_cp_commit(rdev); ++ WREG32(ring->wptr_reg, (ring->wptr << ring->ptr_reg_shift) & ring->ptr_reg_mask); ++ (void)RREG32(ring->wptr_reg); + } + +-void radeon_ring_unlock_commit(struct radeon_device *rdev) ++void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring) + { +- radeon_ring_commit(rdev); +- mutex_unlock(&rdev->cp.mutex); ++ radeon_ring_commit(rdev, ring); ++ mutex_unlock(&ring->mutex); + } + +-void radeon_ring_unlock_undo(struct radeon_device *rdev) ++void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring) + { +- rdev->cp.wptr = rdev->cp.wptr_old; +- mutex_unlock(&rdev->cp.mutex); ++ ring->wptr = ring->wptr_old; ++ mutex_unlock(&ring->mutex); + } + +-int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size) ++int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, ++ unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, ++ u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) + { + int r; + +- rdev->cp.ring_size = ring_size; ++ ring->ring_size = ring_size; ++ ring->rptr_offs = rptr_offs; ++ ring->rptr_reg = rptr_reg; ++ ring->wptr_reg = wptr_reg; ++ ring->ptr_reg_shift = ptr_reg_shift; ++ ring->ptr_reg_mask = ptr_reg_mask; ++ ring->nop = nop; + /* Allocate ring buffer */ +- if (rdev->cp.ring_obj == NULL) { +- r = radeon_bo_create(rdev, rdev->cp.ring_size, PAGE_SIZE, true, ++ if (ring->ring_obj == NULL) { ++ r = radeon_bo_create(rdev, ring->ring_size, PAGE_SIZE, true, + RADEON_GEM_DOMAIN_GTT, +- &rdev->cp.ring_obj); ++ &ring->ring_obj); + if (r) { + dev_err(rdev->dev, "(%d) ring create failed\n", r); + return r; + } +- r = radeon_bo_reserve(rdev->cp.ring_obj, false); ++ r = radeon_bo_reserve(ring->ring_obj, false); + if (unlikely(r != 0)) + return r; +- r = radeon_bo_pin(rdev->cp.ring_obj, RADEON_GEM_DOMAIN_GTT, +- &rdev->cp.gpu_addr); ++ r = radeon_bo_pin(ring->ring_obj, RADEON_GEM_DOMAIN_GTT, ++ &ring->gpu_addr); + if (r) { +- radeon_bo_unreserve(rdev->cp.ring_obj); ++ radeon_bo_unreserve(ring->ring_obj); + dev_err(rdev->dev, "(%d) ring pin failed\n", r); + return r; + } +- r = radeon_bo_kmap(rdev->cp.ring_obj, +- (void **)&rdev->cp.ring); +- radeon_bo_unreserve(rdev->cp.ring_obj); ++ r = radeon_bo_kmap(ring->ring_obj, ++ (void **)&ring->ring); ++ radeon_bo_unreserve(ring->ring_obj); + if (r) { + dev_err(rdev->dev, "(%d) ring map failed\n", r); + return r; + } + } +- rdev->cp.ptr_mask = (rdev->cp.ring_size / 4) - 1; +- rdev->cp.ring_free_dw = rdev->cp.ring_size / 4; ++ ring->ptr_mask = (ring->ring_size / 4) - 1; ++ ring->ring_free_dw = ring->ring_size / 4; + return 0; + } + +-void radeon_ring_fini(struct radeon_device *rdev) ++void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring) + { + int r; + struct radeon_bo *ring_obj; + +- mutex_lock(&rdev->cp.mutex); +- ring_obj = rdev->cp.ring_obj; +- rdev->cp.ring = NULL; +- rdev->cp.ring_obj = NULL; +- mutex_unlock(&rdev->cp.mutex); ++ mutex_lock(&ring->mutex); ++ ring_obj = ring->ring_obj; ++ ring->ring = NULL; ++ ring->ring_obj = NULL; ++ mutex_unlock(&ring->mutex); + + if (ring_obj) { + r = radeon_bo_reserve(ring_obj, false); +@@ -425,78 +439,96 @@ void radeon_ring_fini(struct radeon_device *rdev) + } + } + +- + /* + * Debugfs info + */ + #if defined(CONFIG_DEBUG_FS) +-static int radeon_debugfs_ib_info(struct seq_file *m, void *data) ++ ++static int radeon_debugfs_ring_info(struct seq_file *m, void *data) + { + struct drm_info_node *node = (struct drm_info_node *) m->private; +- struct radeon_ib *ib = node->info_ent->data; +- unsigned i; +- +- if (ib == NULL) { +- return 0; +- } +- seq_printf(m, "IB %04u\n", ib->idx); +- seq_printf(m, "IB fence %p\n", ib->fence); +- seq_printf(m, "IB size %05u dwords\n", ib->length_dw); +- for (i = 0; i < ib->length_dw; i++) { +- seq_printf(m, "[%05u]=0x%08X\n", i, ib->ptr[i]); ++ struct drm_device *dev = node->minor->dev; ++ struct radeon_device *rdev = dev->dev_private; ++ int ridx = *(int*)node->info_ent->data; ++ struct radeon_ring *ring = &rdev->ring[ridx]; ++ unsigned count, i, j; ++ ++ radeon_ring_free_size(rdev, ring); ++ count = (ring->ring_size / 4) - ring->ring_free_dw; ++ seq_printf(m, "wptr(0x%04x): 0x%08x\n", ring->wptr_reg, RREG32(ring->wptr_reg)); ++ seq_printf(m, "rptr(0x%04x): 0x%08x\n", ring->rptr_reg, RREG32(ring->rptr_reg)); ++ seq_printf(m, "driver's copy of the wptr: 0x%08x\n", ring->wptr); ++ seq_printf(m, "driver's copy of the rptr: 0x%08x\n", ring->rptr); ++ seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); ++ seq_printf(m, "%u dwords in ring\n", count); ++ i = ring->rptr; ++ for (j = 0; j <= count; j++) { ++ seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]); ++ i = (i + 1) & ring->ptr_mask; + } + return 0; + } + +-static int radeon_debugfs_ib_bogus_info(struct seq_file *m, void *data) ++static int radeon_ring_type_gfx_index = RADEON_RING_TYPE_GFX_INDEX; ++static int cayman_ring_type_cp1_index = CAYMAN_RING_TYPE_CP1_INDEX; ++static int cayman_ring_type_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX; ++ ++static struct drm_info_list radeon_debugfs_ring_info_list[] = { ++ {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_ring_type_gfx_index}, ++ {"radeon_ring_cp1", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp1_index}, ++ {"radeon_ring_cp2", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp2_index}, ++}; ++ ++static int radeon_debugfs_ib_info(struct seq_file *m, void *data) + { + struct drm_info_node *node = (struct drm_info_node *) m->private; +- struct radeon_device *rdev = node->info_ent->data; +- struct radeon_ib *ib; ++ struct drm_device *dev = node->minor->dev; ++ struct radeon_device *rdev = dev->dev_private; ++ struct radeon_ib *ib = &rdev->ib_pool.ibs[*((unsigned*)node->info_ent->data)]; + unsigned i; + +- mutex_lock(&rdev->ib_pool.mutex); +- if (list_empty(&rdev->ib_pool.bogus_ib)) { +- mutex_unlock(&rdev->ib_pool.mutex); +- seq_printf(m, "no bogus IB recorded\n"); ++ if (ib == NULL) { + return 0; + } +- ib = list_first_entry(&rdev->ib_pool.bogus_ib, struct radeon_ib, list); +- list_del_init(&ib->list); +- mutex_unlock(&rdev->ib_pool.mutex); ++ seq_printf(m, "IB %04u\n", ib->idx); ++ seq_printf(m, "IB fence %p\n", ib->fence); + seq_printf(m, "IB size %05u dwords\n", ib->length_dw); + for (i = 0; i < ib->length_dw; i++) { + seq_printf(m, "[%05u]=0x%08X\n", i, ib->ptr[i]); + } +- vfree(ib->ptr); +- kfree(ib); + return 0; + } + + static struct drm_info_list radeon_debugfs_ib_list[RADEON_IB_POOL_SIZE]; + static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32]; ++static unsigned radeon_debugfs_ib_idx[RADEON_IB_POOL_SIZE]; ++#endif + +-static struct drm_info_list radeon_debugfs_ib_bogus_info_list[] = { +- {"radeon_ib_bogus", radeon_debugfs_ib_bogus_info, 0, NULL}, +-}; ++int radeon_debugfs_ring_init(struct radeon_device *rdev) ++{ ++#if defined(CONFIG_DEBUG_FS) ++ if (rdev->family >= CHIP_CAYMAN) ++ return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list, ++ ARRAY_SIZE(radeon_debugfs_ring_info_list)); ++ else ++ return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list, 1); ++#else ++ return 0; + #endif ++} + + int radeon_debugfs_ib_init(struct radeon_device *rdev) + { + #if defined(CONFIG_DEBUG_FS) + unsigned i; +- int r; + +- radeon_debugfs_ib_bogus_info_list[0].data = rdev; +- r = radeon_debugfs_add_files(rdev, radeon_debugfs_ib_bogus_info_list, 1); +- if (r) +- return r; + for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { + sprintf(radeon_debugfs_ib_names[i], "radeon_ib_%04u", i); ++ radeon_debugfs_ib_idx[i] = i; + radeon_debugfs_ib_list[i].name = radeon_debugfs_ib_names[i]; + radeon_debugfs_ib_list[i].show = &radeon_debugfs_ib_info; + radeon_debugfs_ib_list[i].driver_features = 0; +- radeon_debugfs_ib_list[i].data = &rdev->ib_pool.ibs[i]; ++ radeon_debugfs_ib_list[i].data = &radeon_debugfs_ib_idx[i]; + } + return radeon_debugfs_add_files(rdev, radeon_debugfs_ib_list, + RADEON_IB_POOL_SIZE); +diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c +new file mode 100644 +index 0000000..4cce47e +--- /dev/null ++++ b/drivers/gpu/drm/radeon/radeon_sa.c +@@ -0,0 +1,189 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * All Rights Reserved. ++ * ++ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. ++ * ++ * The above copyright notice and this permission notice (including the ++ * next paragraph) shall be included in all copies or substantial portions ++ * of the Software. ++ * ++ */ ++/* ++ * Authors: ++ * Jerome Glisse ++ */ ++#include "drmP.h" ++#include "drm.h" ++#include "radeon.h" ++ ++int radeon_sa_bo_manager_init(struct radeon_device *rdev, ++ struct radeon_sa_manager *sa_manager, ++ unsigned size, u32 domain) ++{ ++ int r; ++ ++ sa_manager->bo = NULL; ++ sa_manager->size = size; ++ sa_manager->domain = domain; ++ INIT_LIST_HEAD(&sa_manager->sa_bo); ++ ++ r = radeon_bo_create(rdev, size, RADEON_GPU_PAGE_SIZE, true, ++ RADEON_GEM_DOMAIN_CPU, &sa_manager->bo); ++ if (r) { ++ dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r); ++ return r; ++ } ++ ++ return r; ++} ++ ++void radeon_sa_bo_manager_fini(struct radeon_device *rdev, ++ struct radeon_sa_manager *sa_manager) ++{ ++ struct radeon_sa_bo *sa_bo, *tmp; ++ ++ if (!list_empty(&sa_manager->sa_bo)) { ++ dev_err(rdev->dev, "sa_manager is not empty, clearing anyway\n"); ++ } ++ list_for_each_entry_safe(sa_bo, tmp, &sa_manager->sa_bo, list) { ++ list_del_init(&sa_bo->list); ++ } ++ radeon_bo_unref(&sa_manager->bo); ++ sa_manager->size = 0; ++} ++ ++int radeon_sa_bo_manager_start(struct radeon_device *rdev, ++ struct radeon_sa_manager *sa_manager) ++{ ++ int r; ++ ++ if (sa_manager->bo == NULL) { ++ dev_err(rdev->dev, "no bo for sa manager\n"); ++ return -EINVAL; ++ } ++ ++ /* map the buffer */ ++ r = radeon_bo_reserve(sa_manager->bo, false); ++ if (r) { ++ dev_err(rdev->dev, "(%d) failed to reserve manager bo\n", r); ++ return r; ++ } ++ r = radeon_bo_pin(sa_manager->bo, sa_manager->domain, &sa_manager->gpu_addr); ++ if (r) { ++ radeon_bo_unreserve(sa_manager->bo); ++ dev_err(rdev->dev, "(%d) failed to pin manager bo\n", r); ++ return r; ++ } ++ r = radeon_bo_kmap(sa_manager->bo, &sa_manager->cpu_ptr); ++ radeon_bo_unreserve(sa_manager->bo); ++ return r; ++} ++ ++int radeon_sa_bo_manager_suspend(struct radeon_device *rdev, ++ struct radeon_sa_manager *sa_manager) ++{ ++ int r; ++ ++ if (sa_manager->bo == NULL) { ++ dev_err(rdev->dev, "no bo for sa manager\n"); ++ return -EINVAL; ++ } ++ ++ r = radeon_bo_reserve(sa_manager->bo, false); ++ if (!r) { ++ radeon_bo_kunmap(sa_manager->bo); ++ radeon_bo_unpin(sa_manager->bo); ++ radeon_bo_unreserve(sa_manager->bo); ++ } ++ return r; ++} ++ ++/* ++ * Principe is simple, we keep a list of sub allocation in offset ++ * order (first entry has offset == 0, last entry has the highest ++ * offset). ++ * ++ * When allocating new object we first check if there is room at ++ * the end total_size - (last_object_offset + last_object_size) >= ++ * alloc_size. If so we allocate new object there. ++ * ++ * When there is not enough room at the end, we start waiting for ++ * each sub object until we reach object_offset+object_size >= ++ * alloc_size, this object then become the sub object we return. ++ * ++ * Alignment can't be bigger than page size ++ */ ++int radeon_sa_bo_new(struct radeon_device *rdev, ++ struct radeon_sa_manager *sa_manager, ++ struct radeon_sa_bo *sa_bo, ++ unsigned size, unsigned align) ++{ ++ struct radeon_sa_bo *tmp; ++ struct list_head *head; ++ unsigned offset = 0, wasted = 0; ++ ++ BUG_ON(align > RADEON_GPU_PAGE_SIZE); ++ BUG_ON(size > sa_manager->size); ++ ++ /* no one ? */ ++ head = sa_manager->sa_bo.prev; ++ if (list_empty(&sa_manager->sa_bo)) { ++ goto out; ++ } ++ ++ /* look for a hole big enough */ ++ offset = 0; ++ list_for_each_entry(tmp, &sa_manager->sa_bo, list) { ++ /* room before this object ? */ ++ if ((tmp->offset - offset) >= size) { ++ head = tmp->list.prev; ++ goto out; ++ } ++ offset = tmp->offset + tmp->size; ++ wasted = offset % align; ++ if (wasted) { ++ wasted = align - wasted; ++ } ++ offset += wasted; ++ } ++ /* room at the end ? */ ++ head = sa_manager->sa_bo.prev; ++ tmp = list_entry(head, struct radeon_sa_bo, list); ++ offset = tmp->offset + tmp->size; ++ wasted = offset % align; ++ if (wasted) { ++ wasted = align - wasted; ++ } ++ offset += wasted; ++ if ((sa_manager->size - offset) < size) { ++ /* failed to find somethings big enough */ ++ return -ENOMEM; ++ } ++ ++out: ++ sa_bo->manager = sa_manager; ++ sa_bo->offset = offset; ++ sa_bo->size = size; ++ list_add(&sa_bo->list, head); ++ return 0; ++} ++ ++void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo *sa_bo) ++{ ++ list_del_init(&sa_bo->list); ++} +diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c +new file mode 100644 +index 0000000..61dd4e3 +--- /dev/null ++++ b/drivers/gpu/drm/radeon/radeon_semaphore.c +@@ -0,0 +1,178 @@ ++/* ++ * Copyright 2011 Christian König. ++ * All Rights Reserved. ++ * ++ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. ++ * ++ * The above copyright notice and this permission notice (including the ++ * next paragraph) shall be included in all copies or substantial portions ++ * of the Software. ++ * ++ */ ++/* ++ * Authors: ++ * Christian König ++ */ ++#include "drmP.h" ++#include "drm.h" ++#include "radeon.h" ++ ++static int radeon_semaphore_add_bo(struct radeon_device *rdev) ++{ ++ struct radeon_semaphore_bo *bo; ++ unsigned long irq_flags; ++ uint64_t gpu_addr; ++ uint32_t *cpu_ptr; ++ int r, i; ++ ++ ++ bo = kmalloc(sizeof(struct radeon_semaphore_bo), GFP_KERNEL); ++ if (bo == NULL) { ++ return -ENOMEM; ++ } ++ INIT_LIST_HEAD(&bo->free); ++ INIT_LIST_HEAD(&bo->list); ++ bo->nused = 0; ++ ++ r = radeon_ib_get(rdev, 0, &bo->ib, RADEON_SEMAPHORE_BO_SIZE); ++ if (r) { ++ dev_err(rdev->dev, "failed to get a bo after 5 retry\n"); ++ kfree(bo); ++ return r; ++ } ++ gpu_addr = rdev->ib_pool.sa_manager.gpu_addr; ++ gpu_addr += bo->ib->sa_bo.offset; ++ cpu_ptr = rdev->ib_pool.sa_manager.cpu_ptr; ++ cpu_ptr += (bo->ib->sa_bo.offset >> 2); ++ for (i = 0; i < (RADEON_SEMAPHORE_BO_SIZE/8); i++) { ++ bo->semaphores[i].gpu_addr = gpu_addr; ++ bo->semaphores[i].cpu_ptr = cpu_ptr; ++ bo->semaphores[i].bo = bo; ++ list_add_tail(&bo->semaphores[i].list, &bo->free); ++ gpu_addr += 8; ++ cpu_ptr += 2; ++ } ++ write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); ++ list_add_tail(&bo->list, &rdev->semaphore_drv.bo); ++ write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags); ++ return 0; ++} ++ ++static void radeon_semaphore_del_bo_locked(struct radeon_device *rdev, ++ struct radeon_semaphore_bo *bo) ++{ ++ radeon_sa_bo_free(rdev, &bo->ib->sa_bo); ++ radeon_fence_unref(&bo->ib->fence); ++ list_del(&bo->list); ++ kfree(bo); ++} ++ ++void radeon_semaphore_shrink_locked(struct radeon_device *rdev) ++{ ++ struct radeon_semaphore_bo *bo, *n; ++ ++ if (list_empty(&rdev->semaphore_drv.bo)) { ++ return; ++ } ++ /* only shrink if first bo has free semaphore */ ++ bo = list_first_entry(&rdev->semaphore_drv.bo, struct radeon_semaphore_bo, list); ++ if (list_empty(&bo->free)) { ++ return; ++ } ++ list_for_each_entry_safe_continue(bo, n, &rdev->semaphore_drv.bo, list) { ++ if (bo->nused) ++ continue; ++ radeon_semaphore_del_bo_locked(rdev, bo); ++ } ++} ++ ++int radeon_semaphore_create(struct radeon_device *rdev, ++ struct radeon_semaphore **semaphore) ++{ ++ struct radeon_semaphore_bo *bo; ++ unsigned long irq_flags; ++ bool do_retry = true; ++ int r; ++ ++retry: ++ *semaphore = NULL; ++ write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); ++ list_for_each_entry(bo, &rdev->semaphore_drv.bo, list) { ++ if (list_empty(&bo->free)) ++ continue; ++ *semaphore = list_first_entry(&bo->free, struct radeon_semaphore, list); ++ (*semaphore)->cpu_ptr[0] = 0; ++ (*semaphore)->cpu_ptr[1] = 0; ++ list_del(&(*semaphore)->list); ++ bo->nused++; ++ break; ++ } ++ write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags); ++ ++ if (*semaphore == NULL) { ++ if (do_retry) { ++ do_retry = false; ++ r = radeon_semaphore_add_bo(rdev); ++ if (r) ++ return r; ++ goto retry; ++ } ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring, ++ struct radeon_semaphore *semaphore) ++{ ++ radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, false); ++} ++ ++void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, ++ struct radeon_semaphore *semaphore) ++{ ++ radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); ++} ++ ++void radeon_semaphore_free(struct radeon_device *rdev, ++ struct radeon_semaphore *semaphore) ++{ ++ unsigned long irq_flags; ++ ++ write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); ++ semaphore->bo->nused--; ++ list_add_tail(&semaphore->list, &semaphore->bo->free); ++ radeon_semaphore_shrink_locked(rdev); ++ write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags); ++} ++ ++void radeon_semaphore_driver_fini(struct radeon_device *rdev) ++{ ++ struct radeon_semaphore_bo *bo, *n; ++ unsigned long irq_flags; ++ ++ write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); ++ /* we force to free everything */ ++ list_for_each_entry_safe(bo, n, &rdev->semaphore_drv.bo, list) { ++ if (!list_empty(&bo->free)) { ++ dev_err(rdev->dev, "still in use semaphore\n"); ++ } ++ radeon_semaphore_del_bo_locked(rdev, bo); ++ } ++ write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags); ++} +diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c +index 602fa35..dc5dcf4 100644 +--- a/drivers/gpu/drm/radeon/radeon_test.c ++++ b/drivers/gpu/drm/radeon/radeon_test.c +@@ -42,7 +42,9 @@ void radeon_test_moves(struct radeon_device *rdev) + /* Number of tests = + * (Total GTT - IB pool - writeback page - ring buffers) / test size + */ +- n = rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - rdev->cp.ring_size; ++ n = rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024; ++ for (i = 0; i < RADEON_NUM_RINGS; ++i) ++ n -= rdev->ring[i].ring_size; + if (rdev->wb.wb_obj) + n -= RADEON_GPU_PAGE_SIZE; + if (rdev->ih.ring_obj) +@@ -104,7 +106,7 @@ void radeon_test_moves(struct radeon_device *rdev) + + radeon_bo_kunmap(gtt_obj[i]); + +- r = radeon_fence_create(rdev, &fence); ++ r = radeon_fence_create(rdev, &fence, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + DRM_ERROR("Failed to create GTT->VRAM fence %d\n", i); + goto out_cleanup; +@@ -153,7 +155,7 @@ void radeon_test_moves(struct radeon_device *rdev) + + radeon_bo_kunmap(vram_obj); + +- r = radeon_fence_create(rdev, &fence); ++ r = radeon_fence_create(rdev, &fence, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + DRM_ERROR("Failed to create VRAM->GTT fence %d\n", i); + goto out_cleanup; +@@ -232,3 +234,264 @@ out_cleanup: + printk(KERN_WARNING "Error while testing BO move.\n"); + } + } ++ ++void radeon_test_ring_sync(struct radeon_device *rdev, ++ struct radeon_ring *ringA, ++ struct radeon_ring *ringB) ++{ ++ struct radeon_fence *fence1 = NULL, *fence2 = NULL; ++ struct radeon_semaphore *semaphore = NULL; ++ int ridxA = radeon_ring_index(rdev, ringA); ++ int ridxB = radeon_ring_index(rdev, ringB); ++ int r; ++ ++ r = radeon_fence_create(rdev, &fence1, ridxA); ++ if (r) { ++ DRM_ERROR("Failed to create sync fence 1\n"); ++ goto out_cleanup; ++ } ++ r = radeon_fence_create(rdev, &fence2, ridxA); ++ if (r) { ++ DRM_ERROR("Failed to create sync fence 2\n"); ++ goto out_cleanup; ++ } ++ ++ r = radeon_semaphore_create(rdev, &semaphore); ++ if (r) { ++ DRM_ERROR("Failed to create semaphore\n"); ++ goto out_cleanup; ++ } ++ ++ r = radeon_ring_lock(rdev, ringA, 64); ++ if (r) { ++ DRM_ERROR("Failed to lock ring A %d\n", ridxA); ++ goto out_cleanup; ++ } ++ radeon_semaphore_emit_wait(rdev, ridxA, semaphore); ++ radeon_fence_emit(rdev, fence1); ++ radeon_semaphore_emit_wait(rdev, ridxA, semaphore); ++ radeon_fence_emit(rdev, fence2); ++ radeon_ring_unlock_commit(rdev, ringA); ++ ++ mdelay(1000); ++ ++ if (radeon_fence_signaled(fence1)) { ++ DRM_ERROR("Fence 1 signaled without waiting for semaphore.\n"); ++ goto out_cleanup; ++ } ++ ++ r = radeon_ring_lock(rdev, ringB, 64); ++ if (r) { ++ DRM_ERROR("Failed to lock ring B %p\n", ringB); ++ goto out_cleanup; ++ } ++ radeon_semaphore_emit_signal(rdev, ridxB, semaphore); ++ radeon_ring_unlock_commit(rdev, ringB); ++ ++ r = radeon_fence_wait(fence1, false); ++ if (r) { ++ DRM_ERROR("Failed to wait for sync fence 1\n"); ++ goto out_cleanup; ++ } ++ ++ mdelay(1000); ++ ++ if (radeon_fence_signaled(fence2)) { ++ DRM_ERROR("Fence 2 signaled without waiting for semaphore.\n"); ++ goto out_cleanup; ++ } ++ ++ r = radeon_ring_lock(rdev, ringB, 64); ++ if (r) { ++ DRM_ERROR("Failed to lock ring B %p\n", ringB); ++ goto out_cleanup; ++ } ++ radeon_semaphore_emit_signal(rdev, ridxB, semaphore); ++ radeon_ring_unlock_commit(rdev, ringB); ++ ++ r = radeon_fence_wait(fence2, false); ++ if (r) { ++ DRM_ERROR("Failed to wait for sync fence 1\n"); ++ goto out_cleanup; ++ } ++ ++out_cleanup: ++ if (semaphore) ++ radeon_semaphore_free(rdev, semaphore); ++ ++ if (fence1) ++ radeon_fence_unref(&fence1); ++ ++ if (fence2) ++ radeon_fence_unref(&fence2); ++ ++ if (r) ++ printk(KERN_WARNING "Error while testing ring sync (%d).\n", r); ++} ++ ++void radeon_test_ring_sync2(struct radeon_device *rdev, ++ struct radeon_ring *ringA, ++ struct radeon_ring *ringB, ++ struct radeon_ring *ringC) ++{ ++ struct radeon_fence *fenceA = NULL, *fenceB = NULL; ++ struct radeon_semaphore *semaphore = NULL; ++ int ridxA = radeon_ring_index(rdev, ringA); ++ int ridxB = radeon_ring_index(rdev, ringB); ++ int ridxC = radeon_ring_index(rdev, ringC); ++ bool sigA, sigB; ++ int i, r; ++ ++ r = radeon_fence_create(rdev, &fenceA, ridxA); ++ if (r) { ++ DRM_ERROR("Failed to create sync fence 1\n"); ++ goto out_cleanup; ++ } ++ r = radeon_fence_create(rdev, &fenceB, ridxB); ++ if (r) { ++ DRM_ERROR("Failed to create sync fence 2\n"); ++ goto out_cleanup; ++ } ++ ++ r = radeon_semaphore_create(rdev, &semaphore); ++ if (r) { ++ DRM_ERROR("Failed to create semaphore\n"); ++ goto out_cleanup; ++ } ++ ++ r = radeon_ring_lock(rdev, ringA, 64); ++ if (r) { ++ DRM_ERROR("Failed to lock ring A %d\n", ridxA); ++ goto out_cleanup; ++ } ++ radeon_semaphore_emit_wait(rdev, ridxA, semaphore); ++ radeon_fence_emit(rdev, fenceA); ++ radeon_ring_unlock_commit(rdev, ringA); ++ ++ r = radeon_ring_lock(rdev, ringB, 64); ++ if (r) { ++ DRM_ERROR("Failed to lock ring B %d\n", ridxB); ++ goto out_cleanup; ++ } ++ radeon_semaphore_emit_wait(rdev, ridxB, semaphore); ++ radeon_fence_emit(rdev, fenceB); ++ radeon_ring_unlock_commit(rdev, ringB); ++ ++ mdelay(1000); ++ ++ if (radeon_fence_signaled(fenceA)) { ++ DRM_ERROR("Fence A signaled without waiting for semaphore.\n"); ++ goto out_cleanup; ++ } ++ if (radeon_fence_signaled(fenceB)) { ++ DRM_ERROR("Fence A signaled without waiting for semaphore.\n"); ++ goto out_cleanup; ++ } ++ ++ r = radeon_ring_lock(rdev, ringC, 64); ++ if (r) { ++ DRM_ERROR("Failed to lock ring B %p\n", ringC); ++ goto out_cleanup; ++ } ++ radeon_semaphore_emit_signal(rdev, ridxC, semaphore); ++ radeon_ring_unlock_commit(rdev, ringC); ++ ++ for (i = 0; i < 30; ++i) { ++ mdelay(100); ++ sigA = radeon_fence_signaled(fenceA); ++ sigB = radeon_fence_signaled(fenceB); ++ if (sigA || sigB) ++ break; ++ } ++ ++ if (!sigA && !sigB) { ++ DRM_ERROR("Neither fence A nor B has been signaled\n"); ++ goto out_cleanup; ++ } else if (sigA && sigB) { ++ DRM_ERROR("Both fence A and B has been signaled\n"); ++ goto out_cleanup; ++ } ++ ++ DRM_INFO("Fence %c was first signaled\n", sigA ? 'A' : 'B'); ++ ++ r = radeon_ring_lock(rdev, ringC, 64); ++ if (r) { ++ DRM_ERROR("Failed to lock ring B %p\n", ringC); ++ goto out_cleanup; ++ } ++ radeon_semaphore_emit_signal(rdev, ridxC, semaphore); ++ radeon_ring_unlock_commit(rdev, ringC); ++ ++ mdelay(1000); ++ ++ r = radeon_fence_wait(fenceA, false); ++ if (r) { ++ DRM_ERROR("Failed to wait for sync fence A\n"); ++ goto out_cleanup; ++ } ++ r = radeon_fence_wait(fenceB, false); ++ if (r) { ++ DRM_ERROR("Failed to wait for sync fence B\n"); ++ goto out_cleanup; ++ } ++ ++out_cleanup: ++ if (semaphore) ++ radeon_semaphore_free(rdev, semaphore); ++ ++ if (fenceA) ++ radeon_fence_unref(&fenceA); ++ ++ if (fenceB) ++ radeon_fence_unref(&fenceB); ++ ++ if (r) ++ printk(KERN_WARNING "Error while testing ring sync (%d).\n", r); ++} ++ ++void radeon_test_syncing(struct radeon_device *rdev) ++{ ++ int i, j, k; ++ ++ for (i = 1; i < RADEON_NUM_RINGS; ++i) { ++ struct radeon_ring *ringA = &rdev->ring[i]; ++ if (!ringA->ready) ++ continue; ++ ++ for (j = 0; j < i; ++j) { ++ struct radeon_ring *ringB = &rdev->ring[j]; ++ if (!ringB->ready) ++ continue; ++ ++ DRM_INFO("Testing syncing between rings %d and %d...\n", i, j); ++ radeon_test_ring_sync(rdev, ringA, ringB); ++ ++ DRM_INFO("Testing syncing between rings %d and %d...\n", j, i); ++ radeon_test_ring_sync(rdev, ringB, ringA); ++ ++ for (k = 0; k < j; ++k) { ++ struct radeon_ring *ringC = &rdev->ring[k]; ++ if (!ringC->ready) ++ continue; ++ ++ DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k); ++ radeon_test_ring_sync2(rdev, ringA, ringB, ringC); ++ ++ DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, k, j); ++ radeon_test_ring_sync2(rdev, ringA, ringC, ringB); ++ ++ DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, i, k); ++ radeon_test_ring_sync2(rdev, ringB, ringA, ringC); ++ ++ DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, k, i); ++ radeon_test_ring_sync2(rdev, ringB, ringC, ringA); ++ ++ DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, i, j); ++ radeon_test_ring_sync2(rdev, ringC, ringA, ringB); ++ ++ DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, j, i); ++ radeon_test_ring_sync2(rdev, ringC, ringB, ringA); ++ } ++ } ++ } ++} +diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c +index 0b5468b..49b55ed 100644 +--- a/drivers/gpu/drm/radeon/radeon_ttm.c ++++ b/drivers/gpu/drm/radeon/radeon_ttm.c +@@ -114,24 +114,6 @@ static void radeon_ttm_global_fini(struct radeon_device *rdev) + } + } + +-struct ttm_backend *radeon_ttm_backend_create(struct radeon_device *rdev); +- +-static struct ttm_backend* +-radeon_create_ttm_backend_entry(struct ttm_bo_device *bdev) +-{ +- struct radeon_device *rdev; +- +- rdev = radeon_get_rdev(bdev); +-#if __OS_HAS_AGP +- if (rdev->flags & RADEON_IS_AGP) { +- return ttm_agp_backend_init(bdev, rdev->ddev->agp->bridge); +- } else +-#endif +- { +- return radeon_ttm_backend_create(rdev); +- } +-} +- + static int radeon_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags) + { + return 0; +@@ -206,7 +188,7 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, + rbo = container_of(bo, struct radeon_bo, tbo); + switch (bo->mem.mem_type) { + case TTM_PL_VRAM: +- if (rbo->rdev->cp.ready == false) ++ if (rbo->rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready == false) + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); + else + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); +@@ -241,10 +223,10 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, + struct radeon_device *rdev; + uint64_t old_start, new_start; + struct radeon_fence *fence; +- int r; ++ int r, i; + + rdev = radeon_get_rdev(bo->bdev); +- r = radeon_fence_create(rdev, &fence); ++ r = radeon_fence_create(rdev, &fence, radeon_copy_ring_index(rdev)); + if (unlikely(r)) { + return r; + } +@@ -273,13 +255,43 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, + DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); + return -EINVAL; + } +- if (!rdev->cp.ready) { +- DRM_ERROR("Trying to move memory with CP turned off.\n"); ++ if (!rdev->ring[radeon_copy_ring_index(rdev)].ready) { ++ DRM_ERROR("Trying to move memory with ring turned off.\n"); + return -EINVAL; + } + + BUILD_BUG_ON((PAGE_SIZE % RADEON_GPU_PAGE_SIZE) != 0); + ++ /* sync other rings */ ++ if (rdev->family >= CHIP_R600) { ++ for (i = 0; i < RADEON_NUM_RINGS; ++i) { ++ /* no need to sync to our own or unused rings */ ++ if (i == radeon_copy_ring_index(rdev) || !rdev->ring[i].ready) ++ continue; ++ ++ if (!fence->semaphore) { ++ r = radeon_semaphore_create(rdev, &fence->semaphore); ++ /* FIXME: handle semaphore error */ ++ if (r) ++ continue; ++ } ++ ++ r = radeon_ring_lock(rdev, &rdev->ring[i], 3); ++ /* FIXME: handle ring lock error */ ++ if (r) ++ continue; ++ radeon_semaphore_emit_signal(rdev, i, fence->semaphore); ++ radeon_ring_unlock_commit(rdev, &rdev->ring[i]); ++ ++ r = radeon_ring_lock(rdev, &rdev->ring[radeon_copy_ring_index(rdev)], 3); ++ /* FIXME: handle ring lock error */ ++ if (r) ++ continue; ++ radeon_semaphore_emit_wait(rdev, radeon_copy_ring_index(rdev), fence->semaphore); ++ radeon_ring_unlock_commit(rdev, &rdev->ring[radeon_copy_ring_index(rdev)]); ++ } ++ } ++ + r = radeon_copy(rdev, old_start, new_start, + new_mem->num_pages * (PAGE_SIZE / RADEON_GPU_PAGE_SIZE), /* GPU pages */ + fence); +@@ -398,7 +410,8 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, + radeon_move_null(bo, new_mem); + return 0; + } +- if (!rdev->cp.ready || rdev->asic->copy == NULL) { ++ if (!rdev->ring[radeon_copy_ring_index(rdev)].ready || ++ rdev->asic->copy.copy == NULL) { + /* use memcpy */ + goto memcpy; + } +@@ -515,8 +528,166 @@ static bool radeon_sync_obj_signaled(void *sync_obj, void *sync_arg) + return radeon_fence_signaled((struct radeon_fence *)sync_obj); + } + ++/* ++ * TTM backend functions. ++ */ ++struct radeon_ttm_tt { ++ struct ttm_dma_tt ttm; ++ struct radeon_device *rdev; ++ u64 offset; ++}; ++ ++static int radeon_ttm_backend_bind(struct ttm_tt *ttm, ++ struct ttm_mem_reg *bo_mem) ++{ ++ struct radeon_ttm_tt *gtt = (void*)ttm; ++ int r; ++ ++ gtt->offset = (unsigned long)(bo_mem->start << PAGE_SHIFT); ++ if (!ttm->num_pages) { ++ WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", ++ ttm->num_pages, bo_mem, ttm); ++ } ++ r = radeon_gart_bind(gtt->rdev, gtt->offset, ++ ttm->num_pages, ttm->pages, gtt->ttm.dma_address); ++ if (r) { ++ DRM_ERROR("failed to bind %lu pages at 0x%08X\n", ++ ttm->num_pages, (unsigned)gtt->offset); ++ return r; ++ } ++ return 0; ++} ++ ++static int radeon_ttm_backend_unbind(struct ttm_tt *ttm) ++{ ++ struct radeon_ttm_tt *gtt = (void *)ttm; ++ ++ radeon_gart_unbind(gtt->rdev, gtt->offset, ttm->num_pages); ++ return 0; ++} ++ ++static void radeon_ttm_backend_destroy(struct ttm_tt *ttm) ++{ ++ struct radeon_ttm_tt *gtt = (void *)ttm; ++ ++ ttm_dma_tt_fini(>t->ttm); ++ kfree(gtt); ++} ++ ++static struct ttm_backend_func radeon_backend_func = { ++ .bind = &radeon_ttm_backend_bind, ++ .unbind = &radeon_ttm_backend_unbind, ++ .destroy = &radeon_ttm_backend_destroy, ++}; ++ ++struct ttm_tt *radeon_ttm_tt_create(struct ttm_bo_device *bdev, ++ unsigned long size, uint32_t page_flags, ++ struct page *dummy_read_page) ++{ ++ struct radeon_device *rdev; ++ struct radeon_ttm_tt *gtt; ++ ++ rdev = radeon_get_rdev(bdev); ++#if __OS_HAS_AGP ++ if (rdev->flags & RADEON_IS_AGP) { ++ return ttm_agp_tt_create(bdev, rdev->ddev->agp->bridge, ++ size, page_flags, dummy_read_page); ++ } ++#endif ++ ++ gtt = kzalloc(sizeof(struct radeon_ttm_tt), GFP_KERNEL); ++ if (gtt == NULL) { ++ return NULL; ++ } ++ gtt->ttm.ttm.func = &radeon_backend_func; ++ gtt->rdev = rdev; ++ if (ttm_dma_tt_init(>t->ttm, bdev, size, page_flags, dummy_read_page)) { ++ kfree(gtt); ++ return NULL; ++ } ++ return >t->ttm.ttm; ++} ++ ++static int radeon_ttm_tt_populate(struct ttm_tt *ttm) ++{ ++ struct radeon_device *rdev; ++ struct radeon_ttm_tt *gtt = (void *)ttm; ++ unsigned i; ++ int r; ++ ++ if (ttm->state != tt_unpopulated) ++ return 0; ++ ++ rdev = radeon_get_rdev(ttm->bdev); ++#if __OS_HAS_AGP ++ if (rdev->flags & RADEON_IS_AGP) { ++ return ttm_agp_tt_populate(ttm); ++ } ++#endif ++ ++#ifdef CONFIG_SWIOTLB ++ if (swiotlb_nr_tbl()) { ++ return ttm_dma_populate(>t->ttm, rdev->dev); ++ } ++#endif ++ ++ r = ttm_pool_populate(ttm); ++ if (r) { ++ return r; ++ } ++ ++ for (i = 0; i < ttm->num_pages; i++) { ++ gtt->ttm.dma_address[i] = pci_map_page(rdev->pdev, ttm->pages[i], ++ 0, PAGE_SIZE, ++ PCI_DMA_BIDIRECTIONAL); ++ if (pci_dma_mapping_error(rdev->pdev, gtt->ttm.dma_address[i])) { ++ while (--i) { ++ pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i], ++ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); ++ gtt->ttm.dma_address[i] = 0; ++ } ++ ttm_pool_unpopulate(ttm); ++ return -EFAULT; ++ } ++ } ++ return 0; ++} ++ ++static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm) ++{ ++ struct radeon_device *rdev; ++ struct radeon_ttm_tt *gtt = (void *)ttm; ++ unsigned i; ++ ++ rdev = radeon_get_rdev(ttm->bdev); ++#if __OS_HAS_AGP ++ if (rdev->flags & RADEON_IS_AGP) { ++ ttm_agp_tt_unpopulate(ttm); ++ return; ++ } ++#endif ++ ++#ifdef CONFIG_SWIOTLB ++ if (swiotlb_nr_tbl()) { ++ ttm_dma_unpopulate(>t->ttm, rdev->dev); ++ return; ++ } ++#endif ++ ++ for (i = 0; i < ttm->num_pages; i++) { ++ if (gtt->ttm.dma_address[i]) { ++ pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i], ++ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); ++ } ++ } ++ ++ ttm_pool_unpopulate(ttm); ++} ++ + static struct ttm_bo_driver radeon_bo_driver = { +- .create_ttm_backend_entry = &radeon_create_ttm_backend_entry, ++ .ttm_tt_create = &radeon_ttm_tt_create, ++ .ttm_tt_populate = &radeon_ttm_tt_populate, ++ .ttm_tt_unpopulate = &radeon_ttm_tt_unpopulate, + .invalidate_caches = &radeon_invalidate_caches, + .init_mem_type = &radeon_init_mem_type, + .evict_flags = &radeon_evict_flags, +@@ -573,7 +744,7 @@ int radeon_ttm_init(struct radeon_device *rdev) + return r; + } + DRM_INFO("radeon: %uM of VRAM memory ready\n", +- (unsigned)rdev->mc.real_vram_size / (1024 * 1024)); ++ (unsigned) (rdev->mc.real_vram_size / (1024 * 1024))); + r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, + rdev->mc.gtt_size >> PAGE_SHIFT); + if (r) { +@@ -680,124 +851,6 @@ int radeon_mmap(struct file *filp, struct vm_area_struct *vma) + } + + +-/* +- * TTM backend functions. +- */ +-struct radeon_ttm_backend { +- struct ttm_backend backend; +- struct radeon_device *rdev; +- unsigned long num_pages; +- struct page **pages; +- struct page *dummy_read_page; +- dma_addr_t *dma_addrs; +- bool populated; +- bool bound; +- unsigned offset; +-}; +- +-static int radeon_ttm_backend_populate(struct ttm_backend *backend, +- unsigned long num_pages, +- struct page **pages, +- struct page *dummy_read_page, +- dma_addr_t *dma_addrs) +-{ +- struct radeon_ttm_backend *gtt; +- +- gtt = container_of(backend, struct radeon_ttm_backend, backend); +- gtt->pages = pages; +- gtt->dma_addrs = dma_addrs; +- gtt->num_pages = num_pages; +- gtt->dummy_read_page = dummy_read_page; +- gtt->populated = true; +- return 0; +-} +- +-static void radeon_ttm_backend_clear(struct ttm_backend *backend) +-{ +- struct radeon_ttm_backend *gtt; +- +- gtt = container_of(backend, struct radeon_ttm_backend, backend); +- gtt->pages = NULL; +- gtt->dma_addrs = NULL; +- gtt->num_pages = 0; +- gtt->dummy_read_page = NULL; +- gtt->populated = false; +- gtt->bound = false; +-} +- +- +-static int radeon_ttm_backend_bind(struct ttm_backend *backend, +- struct ttm_mem_reg *bo_mem) +-{ +- struct radeon_ttm_backend *gtt; +- int r; +- +- gtt = container_of(backend, struct radeon_ttm_backend, backend); +- gtt->offset = bo_mem->start << PAGE_SHIFT; +- if (!gtt->num_pages) { +- WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", +- gtt->num_pages, bo_mem, backend); +- } +- r = radeon_gart_bind(gtt->rdev, gtt->offset, +- gtt->num_pages, gtt->pages, gtt->dma_addrs); +- if (r) { +- DRM_ERROR("failed to bind %lu pages at 0x%08X\n", +- gtt->num_pages, gtt->offset); +- return r; +- } +- gtt->bound = true; +- return 0; +-} +- +-static int radeon_ttm_backend_unbind(struct ttm_backend *backend) +-{ +- struct radeon_ttm_backend *gtt; +- +- gtt = container_of(backend, struct radeon_ttm_backend, backend); +- radeon_gart_unbind(gtt->rdev, gtt->offset, gtt->num_pages); +- gtt->bound = false; +- return 0; +-} +- +-static void radeon_ttm_backend_destroy(struct ttm_backend *backend) +-{ +- struct radeon_ttm_backend *gtt; +- +- gtt = container_of(backend, struct radeon_ttm_backend, backend); +- if (gtt->bound) { +- radeon_ttm_backend_unbind(backend); +- } +- kfree(gtt); +-} +- +-static struct ttm_backend_func radeon_backend_func = { +- .populate = &radeon_ttm_backend_populate, +- .clear = &radeon_ttm_backend_clear, +- .bind = &radeon_ttm_backend_bind, +- .unbind = &radeon_ttm_backend_unbind, +- .destroy = &radeon_ttm_backend_destroy, +-}; +- +-struct ttm_backend *radeon_ttm_backend_create(struct radeon_device *rdev) +-{ +- struct radeon_ttm_backend *gtt; +- +- gtt = kzalloc(sizeof(struct radeon_ttm_backend), GFP_KERNEL); +- if (gtt == NULL) { +- return NULL; +- } +- gtt->backend.bdev = &rdev->mman.bdev; +- gtt->backend.flags = 0; +- gtt->backend.func = &radeon_backend_func; +- gtt->rdev = rdev; +- gtt->pages = NULL; +- gtt->num_pages = 0; +- gtt->dummy_read_page = NULL; +- gtt->populated = false; +- gtt->bound = false; +- return >t->backend; +-} +- + #define RADEON_DEBUGFS_MEM_TYPES 2 + + #if defined(CONFIG_DEBUG_FS) +@@ -820,8 +873,8 @@ static int radeon_mm_dump_table(struct seq_file *m, void *data) + static int radeon_ttm_debugfs_init(struct radeon_device *rdev) + { + #if defined(CONFIG_DEBUG_FS) +- static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES+1]; +- static char radeon_mem_types_names[RADEON_DEBUGFS_MEM_TYPES+1][32]; ++ static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES+2]; ++ static char radeon_mem_types_names[RADEON_DEBUGFS_MEM_TYPES+2][32]; + unsigned i; + + for (i = 0; i < RADEON_DEBUGFS_MEM_TYPES; i++) { +@@ -843,8 +896,17 @@ static int radeon_ttm_debugfs_init(struct radeon_device *rdev) + radeon_mem_types_list[i].name = radeon_mem_types_names[i]; + radeon_mem_types_list[i].show = &ttm_page_alloc_debugfs; + radeon_mem_types_list[i].driver_features = 0; +- radeon_mem_types_list[i].data = NULL; +- return radeon_debugfs_add_files(rdev, radeon_mem_types_list, RADEON_DEBUGFS_MEM_TYPES+1); ++ radeon_mem_types_list[i++].data = NULL; ++#ifdef CONFIG_SWIOTLB ++ if (swiotlb_nr_tbl()) { ++ sprintf(radeon_mem_types_names[i], "ttm_dma_page_pool"); ++ radeon_mem_types_list[i].name = radeon_mem_types_names[i]; ++ radeon_mem_types_list[i].show = &ttm_dma_page_alloc_debugfs; ++ radeon_mem_types_list[i].driver_features = 0; ++ radeon_mem_types_list[i++].data = NULL; ++ } ++#endif ++ return radeon_debugfs_add_files(rdev, radeon_mem_types_list, i); + + #endif + return 0; +diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman +index 2316977..a072fa8 100644 +--- a/drivers/gpu/drm/radeon/reg_srcs/cayman ++++ b/drivers/gpu/drm/radeon/reg_srcs/cayman +@@ -1,5 +1,9 @@ + cayman 0x9400 + 0x0000802C GRBM_GFX_INDEX ++0x00008040 WAIT_UNTIL ++0x000084FC CP_STRMOUT_CNTL ++0x000085F0 CP_COHER_CNTL ++0x000085F4 CP_COHER_SIZE + 0x000088B0 VGT_VTX_VECT_EJECT_REG + 0x000088C4 VGT_CACHE_INVALIDATION + 0x000088D4 VGT_GS_VERTEX_REUSE +@@ -77,7 +81,6 @@ cayman 0x9400 + 0x0002802C DB_DEPTH_CLEAR + 0x00028030 PA_SC_SCREEN_SCISSOR_TL + 0x00028034 PA_SC_SCREEN_SCISSOR_BR +-0x0002805C DB_DEPTH_SLICE + 0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0 + 0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1 + 0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2 +@@ -206,7 +209,6 @@ cayman 0x9400 + 0x00028344 PA_SC_VPORT_ZMAX_14 + 0x00028348 PA_SC_VPORT_ZMIN_15 + 0x0002834C PA_SC_VPORT_ZMAX_15 +-0x00028350 SX_MISC + 0x00028354 SX_SURFACE_SYNC + 0x0002835C SX_SCATTER_EXPORT_SIZE + 0x00028380 SQ_VTX_SEMANTIC_0 +@@ -508,10 +510,16 @@ cayman 0x9400 + 0x00028AA8 IA_MULTI_VGT_PARAM + 0x00028AB4 VGT_REUSE_OFF + 0x00028AB8 VGT_VTX_CNT_EN +-0x00028ABC DB_HTILE_SURFACE + 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 + 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 + 0x00028AC8 DB_PRELOAD_CONTROL ++0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 ++0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 ++0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 ++0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 ++0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET ++0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE ++0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE + 0x00028B38 VGT_GS_MAX_VERT_OUT + 0x00028B54 VGT_SHADER_STAGES_EN + 0x00028B58 VGT_LS_HS_CONFIG +@@ -551,6 +559,18 @@ cayman 0x9400 + 0x00028C34 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_3 + 0x00028C38 PA_SC_AA_MASK_X0_Y0_X1_Y0 + 0x00028C3C PA_SC_AA_MASK_X0_Y1_X1_Y1 ++0x00028C78 CB_COLOR0_DIM ++0x00028CB4 CB_COLOR1_DIM ++0x00028CF0 CB_COLOR2_DIM ++0x00028D2C CB_COLOR3_DIM ++0x00028D68 CB_COLOR4_DIM ++0x00028DA4 CB_COLOR5_DIM ++0x00028DE0 CB_COLOR6_DIM ++0x00028E1C CB_COLOR7_DIM ++0x00028E58 CB_COLOR8_DIM ++0x00028E74 CB_COLOR9_DIM ++0x00028E90 CB_COLOR10_DIM ++0x00028EAC CB_COLOR11_DIM + 0x00028C8C CB_COLOR0_CLEAR_WORD0 + 0x00028C90 CB_COLOR0_CLEAR_WORD1 + 0x00028C94 CB_COLOR0_CLEAR_WORD2 +diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen +index 161737a..b912a37 100644 +--- a/drivers/gpu/drm/radeon/reg_srcs/evergreen ++++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen +@@ -4,6 +4,9 @@ evergreen 0x9400 + 0x00008044 WAIT_UNTIL_POLL_CNTL + 0x00008048 WAIT_UNTIL_POLL_MASK + 0x0000804c WAIT_UNTIL_POLL_REFDATA ++0x000084FC CP_STRMOUT_CNTL ++0x000085F0 CP_COHER_CNTL ++0x000085F4 CP_COHER_SIZE + 0x000088B0 VGT_VTX_VECT_EJECT_REG + 0x000088C4 VGT_CACHE_INVALIDATION + 0x000088D4 VGT_GS_VERTEX_REUSE +@@ -93,7 +96,6 @@ evergreen 0x9400 + 0x0002802C DB_DEPTH_CLEAR + 0x00028030 PA_SC_SCREEN_SCISSOR_TL + 0x00028034 PA_SC_SCREEN_SCISSOR_BR +-0x0002805C DB_DEPTH_SLICE + 0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0 + 0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1 + 0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2 +@@ -222,7 +224,6 @@ evergreen 0x9400 + 0x00028344 PA_SC_VPORT_ZMAX_14 + 0x00028348 PA_SC_VPORT_ZMIN_15 + 0x0002834C PA_SC_VPORT_ZMAX_15 +-0x00028350 SX_MISC + 0x00028354 SX_SURFACE_SYNC + 0x00028380 SQ_VTX_SEMANTIC_0 + 0x00028384 SQ_VTX_SEMANTIC_1 +@@ -518,10 +519,16 @@ evergreen 0x9400 + 0x00028AA4 VGT_INSTANCE_STEP_RATE_1 + 0x00028AB4 VGT_REUSE_OFF + 0x00028AB8 VGT_VTX_CNT_EN +-0x00028ABC DB_HTILE_SURFACE + 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 + 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 + 0x00028AC8 DB_PRELOAD_CONTROL ++0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 ++0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 ++0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 ++0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 ++0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET ++0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE ++0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE + 0x00028B38 VGT_GS_MAX_VERT_OUT + 0x00028B54 VGT_SHADER_STAGES_EN + 0x00028B58 VGT_LS_HS_CONFIG +@@ -554,6 +561,18 @@ evergreen 0x9400 + 0x00028C34 PA_SC_AA_SAMPLE_LOCS_6 + 0x00028C38 PA_SC_AA_SAMPLE_LOCS_7 + 0x00028C3C PA_SC_AA_MASK ++0x00028C78 CB_COLOR0_DIM ++0x00028CB4 CB_COLOR1_DIM ++0x00028CF0 CB_COLOR2_DIM ++0x00028D2C CB_COLOR3_DIM ++0x00028D68 CB_COLOR4_DIM ++0x00028DA4 CB_COLOR5_DIM ++0x00028DE0 CB_COLOR6_DIM ++0x00028E1C CB_COLOR7_DIM ++0x00028E58 CB_COLOR8_DIM ++0x00028E74 CB_COLOR9_DIM ++0x00028E90 CB_COLOR10_DIM ++0x00028EAC CB_COLOR11_DIM + 0x00028C8C CB_COLOR0_CLEAR_WORD0 + 0x00028C90 CB_COLOR0_CLEAR_WORD1 + 0x00028C94 CB_COLOR0_CLEAR_WORD2 +diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 +index 0380c5c..5e659b0 100644 +--- a/drivers/gpu/drm/radeon/reg_srcs/r600 ++++ b/drivers/gpu/drm/radeon/reg_srcs/r600 +@@ -3,6 +3,9 @@ r600 0x9400 + 0x00028230 R7xx_PA_SC_EDGERULE + 0x000286C8 R7xx_SPI_THREAD_GROUPING + 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ ++0x00008490 CP_STRMOUT_CNTL ++0x000085F0 CP_COHER_CNTL ++0x000085F4 CP_COHER_SIZE + 0x000088C4 VGT_CACHE_INVALIDATION + 0x00028A50 VGT_ENHANCE + 0x000088CC VGT_ES_PER_GS +@@ -38,6 +41,13 @@ r600 0x9400 + 0x00028AB4 VGT_REUSE_OFF + 0x00028AB8 VGT_VTX_CNT_EN + 0x000088B0 VGT_VTX_VECT_EJECT_REG ++0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 ++0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 ++0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 ++0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 ++0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET ++0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE ++0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE + 0x00028810 PA_CL_CLIP_CNTL + 0x00008A14 PA_CL_ENHANCE + 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ +@@ -428,7 +438,7 @@ r600 0x9400 + 0x00028638 SPI_VS_OUT_ID_9 + 0x00028438 SX_ALPHA_REF + 0x00028410 SX_ALPHA_TEST_CONTROL +-0x00028350 SX_MISC ++0x00028354 SX_SURFACE_SYNC + 0x00009014 SX_MEMORY_EXPORT_SIZE + 0x00009604 TC_INVALIDATE + 0x00009400 TD_FILTER4 +@@ -703,7 +713,6 @@ r600 0x9400 + 0x0000A710 TD_VS_SAMPLER17_BORDER_RED + 0x00009508 TA_CNTL_AUX + 0x0002802C DB_DEPTH_CLEAR +-0x00028D24 DB_HTILE_SURFACE + 0x00028D34 DB_PREFETCH_LIMIT + 0x00028D30 DB_PRELOAD_CONTROL + 0x00028D0C DB_RENDER_CONTROL +@@ -743,14 +752,6 @@ r600 0x9400 + 0x00028114 CB_COLOR5_MASK + 0x00028118 CB_COLOR6_MASK + 0x0002811C CB_COLOR7_MASK +-0x00028080 CB_COLOR0_VIEW +-0x00028084 CB_COLOR1_VIEW +-0x00028088 CB_COLOR2_VIEW +-0x0002808C CB_COLOR3_VIEW +-0x00028090 CB_COLOR4_VIEW +-0x00028094 CB_COLOR5_VIEW +-0x00028098 CB_COLOR6_VIEW +-0x0002809C CB_COLOR7_VIEW + 0x00028808 CB_COLOR_CONTROL + 0x0002842C CB_FOG_BLUE + 0x00028428 CB_FOG_GREEN +diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c +index c087434..b367d1d 100644 +--- a/drivers/gpu/drm/radeon/rs400.c ++++ b/drivers/gpu/drm/radeon/rs400.c +@@ -413,6 +413,12 @@ static int rs400_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ + /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); +@@ -428,16 +434,25 @@ static int rs400_startup(struct radeon_device *rdev) + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } +- r = r100_ib_init(rdev); ++ ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + if (r) { +- dev_err(rdev->dev, "failed initializing IB (%d).\n", r); ++ dev_err(rdev->dev, "failed testing IB (%d).\n", r); ++ rdev->accel_working = false; + return r; + } ++ + return 0; + } + + int rs400_resume(struct radeon_device *rdev) + { ++ int r; ++ + /* Make sur GART are not working */ + rs400_gart_disable(rdev); + /* Resume clock before doing reset */ +@@ -456,11 +471,18 @@ int rs400_resume(struct radeon_device *rdev) + r300_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); +- return rs400_startup(rdev); ++ ++ rdev->accel_working = true; ++ r = rs400_startup(rdev); ++ if (r) { ++ rdev->accel_working = false; ++ } ++ return r; + } + + int rs400_suspend(struct radeon_device *rdev) + { ++ radeon_ib_pool_suspend(rdev); + r100_cp_disable(rdev); + radeon_wb_disable(rdev); + r100_irq_disable(rdev); +@@ -536,7 +558,14 @@ int rs400_init(struct radeon_device *rdev) + if (r) + return r; + r300_set_reg_safe(rdev); ++ ++ r = radeon_ib_pool_init(rdev); + rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ + r = rs400_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ +diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c +index fc37558..07b6dbf 100644 +--- a/drivers/gpu/drm/radeon/rs600.c ++++ b/drivers/gpu/drm/radeon/rs600.c +@@ -46,6 +46,25 @@ + void rs600_gpu_init(struct radeon_device *rdev); + int rs600_mc_wait_for_idle(struct radeon_device *rdev); + ++void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc) ++{ ++ struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; ++ int i; ++ ++ if (RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset) & AVIVO_CRTC_EN) { ++ for (i = 0; i < rdev->usec_timeout; i++) { ++ if (!(RREG32(AVIVO_D1CRTC_STATUS + radeon_crtc->crtc_offset) & AVIVO_D1CRTC_V_BLANK)) ++ break; ++ udelay(1); ++ } ++ for (i = 0; i < rdev->usec_timeout; i++) { ++ if (RREG32(AVIVO_D1CRTC_STATUS + radeon_crtc->crtc_offset) & AVIVO_D1CRTC_V_BLANK) ++ break; ++ udelay(1); ++ } ++ } ++} ++ + void rs600_pre_page_flip(struct radeon_device *rdev, int crtc) + { + /* enable the pflip int */ +@@ -175,7 +194,7 @@ void rs600_pm_misc(struct radeon_device *rdev) + /* set pcie lanes */ + if ((rdev->flags & RADEON_IS_PCIE) && + !(rdev->flags & RADEON_IS_IGP) && +- rdev->asic->set_pcie_lanes && ++ rdev->asic->pm.set_pcie_lanes && + (ps->pcie_lanes != + rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) { + radeon_set_pcie_lanes(rdev, +@@ -322,16 +341,6 @@ void rs600_hpd_fini(struct radeon_device *rdev) + } + } + +-void rs600_bm_disable(struct radeon_device *rdev) +-{ +- u16 tmp; +- +- /* disable bus mastering */ +- pci_read_config_word(rdev->pdev, 0x4, &tmp); +- pci_write_config_word(rdev->pdev, 0x4, tmp & 0xFFFB); +- mdelay(1); +-} +- + int rs600_asic_reset(struct radeon_device *rdev) + { + struct rv515_mc_save save; +@@ -355,7 +364,8 @@ int rs600_asic_reset(struct radeon_device *rdev) + WREG32(RADEON_CP_RB_CNTL, tmp); + pci_save_state(rdev->pdev); + /* disable bus mastering */ +- rs600_bm_disable(rdev); ++ pci_clear_master(rdev->pdev); ++ mdelay(1); + /* reset GA+VAP */ + WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) | + S_0000F0_SOFT_RESET_GA(1)); +@@ -529,11 +539,10 @@ int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) + return -EINVAL; + } + addr = addr & 0xFFFFFFFFFFFFF000ULL; +- if (addr == rdev->dummy_page.addr) +- addr |= R600_PTE_SYSTEM | R600_PTE_SNOOPED; +- else +- addr |= (R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED | +- R600_PTE_READABLE | R600_PTE_WRITEABLE); ++ if (addr != rdev->dummy_page.addr) ++ addr |= R600_PTE_VALID | R600_PTE_READABLE | ++ R600_PTE_WRITEABLE; ++ addr |= R600_PTE_SYSTEM | R600_PTE_SNOOPED; + writeq(addr, ptr + (i * 8)); + return 0; + } +@@ -552,7 +561,7 @@ int rs600_irq_set(struct radeon_device *rdev) + WREG32(R_000040_GEN_INT_CNTL, 0); + return -EINVAL; + } +- if (rdev->irq.sw_int) { ++ if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { + tmp |= S_000040_SW_INT_EN(1); + } + if (rdev->irq.gui_idle) { +@@ -649,7 +658,7 @@ int rs600_irq_process(struct radeon_device *rdev) + while (status || rdev->irq.stat_regs.r500.disp_int) { + /* SW interrupt */ + if (G_000044_SW_INT(status)) { +- radeon_fence_process(rdev); ++ radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + } + /* GUI idle */ + if (G_000040_GUI_IDLE(status)) { +@@ -854,6 +863,12 @@ static int rs600_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ + /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); +@@ -869,15 +884,21 @@ static int rs600_startup(struct radeon_device *rdev) + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } +- r = r100_ib_init(rdev); ++ ++ r = r600_audio_init(rdev); + if (r) { +- dev_err(rdev->dev, "failed initializing IB (%d).\n", r); ++ dev_err(rdev->dev, "failed initializing audio\n"); + return r; + } + +- r = r600_audio_init(rdev); ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + if (r) { +- dev_err(rdev->dev, "failed initializing audio\n"); ++ dev_err(rdev->dev, "failed testing IB (%d).\n", r); ++ rdev->accel_working = false; + return r; + } + +@@ -886,6 +907,8 @@ static int rs600_startup(struct radeon_device *rdev) + + int rs600_resume(struct radeon_device *rdev) + { ++ int r; ++ + /* Make sur GART are not working */ + rs600_gart_disable(rdev); + /* Resume clock before doing reset */ +@@ -902,11 +925,18 @@ int rs600_resume(struct radeon_device *rdev) + rv515_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); +- return rs600_startup(rdev); ++ ++ rdev->accel_working = true; ++ r = rs600_startup(rdev); ++ if (r) { ++ rdev->accel_working = false; ++ } ++ return r; + } + + int rs600_suspend(struct radeon_device *rdev) + { ++ radeon_ib_pool_suspend(rdev); + r600_audio_fini(rdev); + r100_cp_disable(rdev); + radeon_wb_disable(rdev); +@@ -984,7 +1014,14 @@ int rs600_init(struct radeon_device *rdev) + if (r) + return r; + rs600_set_safe_registers(rdev); ++ ++ r = radeon_ib_pool_init(rdev); + rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ + r = rs600_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ +diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c +index 414a681..c46900c 100644 +--- a/drivers/gpu/drm/radeon/rs690.c ++++ b/drivers/gpu/drm/radeon/rs690.c +@@ -31,7 +31,7 @@ + #include "atom.h" + #include "rs690d.h" + +-static int rs690_mc_wait_for_idle(struct radeon_device *rdev) ++int rs690_mc_wait_for_idle(struct radeon_device *rdev) + { + unsigned i; + uint32_t tmp; +@@ -160,16 +160,6 @@ void rs690_mc_init(struct radeon_device *rdev) + base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); + base = G_000100_MC_FB_START(base) << 16; + rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); +- /* Some boards seem to be configured for 128MB of sideport memory, +- * but really only have 64MB. Just skip the sideport and use +- * UMA memory. +- */ +- if (rdev->mc.igp_sideport_enabled && +- (rdev->mc.real_vram_size == (384 * 1024 * 1024))) { +- base += 128 * 1024 * 1024; +- rdev->mc.real_vram_size -= 128 * 1024 * 1024; +- rdev->mc.mc_vram_size = rdev->mc.real_vram_size; +- } + rs690_pm_info(rdev); + radeon_vram_location(rdev, &rdev->mc, base); + rdev->mc.gtt_base_align = rdev->mc.gtt_size - 1; +@@ -631,6 +621,12 @@ static int rs690_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ + /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); +@@ -646,15 +642,21 @@ static int rs690_startup(struct radeon_device *rdev) + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } +- r = r100_ib_init(rdev); ++ ++ r = r600_audio_init(rdev); + if (r) { +- dev_err(rdev->dev, "failed initializing IB (%d).\n", r); ++ dev_err(rdev->dev, "failed initializing audio\n"); + return r; + } + +- r = r600_audio_init(rdev); ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + if (r) { +- dev_err(rdev->dev, "failed initializing audio\n"); ++ dev_err(rdev->dev, "failed testing IB (%d).\n", r); ++ rdev->accel_working = false; + return r; + } + +@@ -663,6 +665,8 @@ static int rs690_startup(struct radeon_device *rdev) + + int rs690_resume(struct radeon_device *rdev) + { ++ int r; ++ + /* Make sur GART are not working */ + rs400_gart_disable(rdev); + /* Resume clock before doing reset */ +@@ -679,11 +683,18 @@ int rs690_resume(struct radeon_device *rdev) + rv515_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); +- return rs690_startup(rdev); ++ ++ rdev->accel_working = true; ++ r = rs690_startup(rdev); ++ if (r) { ++ rdev->accel_working = false; ++ } ++ return r; + } + + int rs690_suspend(struct radeon_device *rdev) + { ++ radeon_ib_pool_suspend(rdev); + r600_audio_fini(rdev); + r100_cp_disable(rdev); + radeon_wb_disable(rdev); +@@ -762,7 +773,14 @@ int rs690_init(struct radeon_device *rdev) + if (r) + return r; + rs600_set_safe_registers(rdev); ++ ++ r = radeon_ib_pool_init(rdev); + rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ + r = rs690_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ +diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c +index 9103638..0532bbe 100644 +--- a/drivers/gpu/drm/radeon/rv515.c ++++ b/drivers/gpu/drm/radeon/rv515.c +@@ -53,46 +53,46 @@ void rv515_debugfs(struct radeon_device *rdev) + } + } + +-void rv515_ring_start(struct radeon_device *rdev) ++void rv515_ring_start(struct radeon_device *rdev, struct radeon_ring *ring) + { + int r; + +- r = radeon_ring_lock(rdev, 64); ++ r = radeon_ring_lock(rdev, ring, 64); + if (r) { + return; + } +- radeon_ring_write(rdev, PACKET0(ISYNC_CNTL, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET0(ISYNC_CNTL, 0)); ++ radeon_ring_write(ring, + ISYNC_ANY2D_IDLE3D | + ISYNC_ANY3D_IDLE2D | + ISYNC_WAIT_IDLEGUI | + ISYNC_CPSCRATCH_IDLEGUI); +- radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0)); +- radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN); +- radeon_ring_write(rdev, PACKET0(R300_DST_PIPE_CONFIG, 0)); +- radeon_ring_write(rdev, R300_PIPE_AUTO_CONFIG); +- radeon_ring_write(rdev, PACKET0(GB_SELECT, 0)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, PACKET0(GB_ENABLE, 0)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, PACKET0(R500_SU_REG_DEST, 0)); +- radeon_ring_write(rdev, (1 << rdev->num_gb_pipes) - 1); +- radeon_ring_write(rdev, PACKET0(VAP_INDEX_OFFSET, 0)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE); +- radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE); +- radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0)); +- radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN); +- radeon_ring_write(rdev, PACKET0(GB_AA_CONFIG, 0)); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE); +- radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0)); +- radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE); +- radeon_ring_write(rdev, PACKET0(GB_MSPOS0, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET0(WAIT_UNTIL, 0)); ++ radeon_ring_write(ring, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN); ++ radeon_ring_write(ring, PACKET0(R300_DST_PIPE_CONFIG, 0)); ++ radeon_ring_write(ring, R300_PIPE_AUTO_CONFIG); ++ radeon_ring_write(ring, PACKET0(GB_SELECT, 0)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, PACKET0(GB_ENABLE, 0)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, PACKET0(R500_SU_REG_DEST, 0)); ++ radeon_ring_write(ring, (1 << rdev->num_gb_pipes) - 1); ++ radeon_ring_write(ring, PACKET0(VAP_INDEX_OFFSET, 0)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, RB3D_DC_FLUSH | RB3D_DC_FREE); ++ radeon_ring_write(ring, PACKET0(ZB_ZCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, ZC_FLUSH | ZC_FREE); ++ radeon_ring_write(ring, PACKET0(WAIT_UNTIL, 0)); ++ radeon_ring_write(ring, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN); ++ radeon_ring_write(ring, PACKET0(GB_AA_CONFIG, 0)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, RB3D_DC_FLUSH | RB3D_DC_FREE); ++ radeon_ring_write(ring, PACKET0(ZB_ZCACHE_CTLSTAT, 0)); ++ radeon_ring_write(ring, ZC_FLUSH | ZC_FREE); ++ radeon_ring_write(ring, PACKET0(GB_MSPOS0, 0)); ++ radeon_ring_write(ring, + ((6 << MS_X0_SHIFT) | + (6 << MS_Y0_SHIFT) | + (6 << MS_X1_SHIFT) | +@@ -101,8 +101,8 @@ void rv515_ring_start(struct radeon_device *rdev) + (6 << MS_Y2_SHIFT) | + (6 << MSBD0_Y_SHIFT) | + (6 << MSBD0_X_SHIFT))); +- radeon_ring_write(rdev, PACKET0(GB_MSPOS1, 0)); +- radeon_ring_write(rdev, ++ radeon_ring_write(ring, PACKET0(GB_MSPOS1, 0)); ++ radeon_ring_write(ring, + ((6 << MS_X3_SHIFT) | + (6 << MS_Y3_SHIFT) | + (6 << MS_X4_SHIFT) | +@@ -110,15 +110,15 @@ void rv515_ring_start(struct radeon_device *rdev) + (6 << MS_X5_SHIFT) | + (6 << MS_Y5_SHIFT) | + (6 << MSBD1_SHIFT))); +- radeon_ring_write(rdev, PACKET0(GA_ENHANCE, 0)); +- radeon_ring_write(rdev, GA_DEADLOCK_CNTL | GA_FASTSYNC_CNTL); +- radeon_ring_write(rdev, PACKET0(GA_POLY_MODE, 0)); +- radeon_ring_write(rdev, FRONT_PTYPE_TRIANGE | BACK_PTYPE_TRIANGE); +- radeon_ring_write(rdev, PACKET0(GA_ROUND_MODE, 0)); +- radeon_ring_write(rdev, GEOMETRY_ROUND_NEAREST | COLOR_ROUND_NEAREST); +- radeon_ring_write(rdev, PACKET0(0x20C8, 0)); +- radeon_ring_write(rdev, 0); +- radeon_ring_unlock_commit(rdev); ++ radeon_ring_write(ring, PACKET0(GA_ENHANCE, 0)); ++ radeon_ring_write(ring, GA_DEADLOCK_CNTL | GA_FASTSYNC_CNTL); ++ radeon_ring_write(ring, PACKET0(GA_POLY_MODE, 0)); ++ radeon_ring_write(ring, FRONT_PTYPE_TRIANGE | BACK_PTYPE_TRIANGE); ++ radeon_ring_write(ring, PACKET0(GA_ROUND_MODE, 0)); ++ radeon_ring_write(ring, GEOMETRY_ROUND_NEAREST | COLOR_ROUND_NEAREST); ++ radeon_ring_write(ring, PACKET0(0x20C8, 0)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_unlock_commit(rdev, ring); + } + + int rv515_mc_wait_for_idle(struct radeon_device *rdev) +@@ -149,7 +149,7 @@ void rv515_gpu_init(struct radeon_device *rdev) + + if (r100_gui_wait_for_idle(rdev)) { + printk(KERN_WARNING "Failed to wait GUI idle while " +- "reseting GPU. Bad things might happen.\n"); ++ "resetting GPU. Bad things might happen.\n"); + } + rv515_vga_render_disable(rdev); + r420_pipes_init(rdev); +@@ -161,7 +161,7 @@ void rv515_gpu_init(struct radeon_device *rdev) + WREG32_PLL(0x000D, tmp); + if (r100_gui_wait_for_idle(rdev)) { + printk(KERN_WARNING "Failed to wait GUI idle while " +- "reseting GPU. Bad things might happen.\n"); ++ "resetting GPU. Bad things might happen.\n"); + } + if (rv515_mc_wait_for_idle(rdev)) { + printk(KERN_WARNING "Failed to wait MC idle while " +@@ -379,6 +379,12 @@ static int rv515_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ + /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); +@@ -394,9 +400,15 @@ static int rv515_startup(struct radeon_device *rdev) + dev_err(rdev->dev, "failed initializing CP (%d).\n", r); + return r; + } +- r = r100_ib_init(rdev); ++ ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + if (r) { +- dev_err(rdev->dev, "failed initializing IB (%d).\n", r); ++ dev_err(rdev->dev, "failed testing IB (%d).\n", r); ++ rdev->accel_working = false; + return r; + } + return 0; +@@ -404,6 +416,8 @@ static int rv515_startup(struct radeon_device *rdev) + + int rv515_resume(struct radeon_device *rdev) + { ++ int r; ++ + /* Make sur GART are not working */ + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); +@@ -421,7 +435,13 @@ int rv515_resume(struct radeon_device *rdev) + rv515_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); +- return rv515_startup(rdev); ++ ++ rdev->accel_working = true; ++ r = rv515_startup(rdev); ++ if (r) { ++ rdev->accel_working = false; ++ } ++ return r; + } + + int rv515_suspend(struct radeon_device *rdev) +@@ -514,7 +534,14 @@ int rv515_init(struct radeon_device *rdev) + if (r) + return r; + rv515_set_safe_registers(rdev); ++ ++ r = radeon_ib_pool_init(rdev); + rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ + r = rv515_startup(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ +diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c +index 3e72074..1ec1255 100644 +--- a/drivers/gpu/drm/radeon/rv770.c ++++ b/drivers/gpu/drm/radeon/rv770.c +@@ -359,7 +359,7 @@ static int rv770_cp_load_microcode(struct radeon_device *rdev) + void r700_cp_fini(struct radeon_device *rdev) + { + r700_cp_stop(rdev); +- radeon_ring_fini(rdev); ++ radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + } + + /* +@@ -978,7 +978,7 @@ void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) + } + if (rdev->flags & RADEON_IS_AGP) { + size_bf = mc->gtt_start; +- size_af = 0xFFFFFFFF - mc->gtt_end + 1; ++ size_af = 0xFFFFFFFF - mc->gtt_end; + if (size_bf > size_af) { + if (mc->mc_vram_size > size_bf) { + dev_warn(rdev->dev, "limiting VRAM\n"); +@@ -992,7 +992,7 @@ void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) + mc->real_vram_size = size_af; + mc->mc_vram_size = size_af; + } +- mc->vram_start = mc->gtt_end; ++ mc->vram_start = mc->gtt_end + 1; + } + mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; + dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", +@@ -1052,6 +1052,7 @@ int rv770_mc_init(struct radeon_device *rdev) + + static int rv770_startup(struct radeon_device *rdev) + { ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + int r; + + /* enable pcie gen2 link */ +@@ -1083,7 +1084,7 @@ static int rv770_startup(struct radeon_device *rdev) + r = r600_blit_init(rdev); + if (r) { + r600_blit_fini(rdev); +- rdev->asic->copy = NULL; ++ rdev->asic->copy.copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } + +@@ -1092,6 +1093,12 @@ static int rv770_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ + /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); +@@ -1107,7 +1114,9 @@ static int rv770_startup(struct radeon_device *rdev) + } + r600_irq_set(rdev); + +- r = radeon_ring_init(rdev, rdev->cp.ring_size); ++ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, ++ R600_CP_RB_RPTR, R600_CP_RB_WPTR, ++ 0, 0xfffff, RADEON_CP_PACKET2); + if (r) + return r; + r = rv770_cp_load_microcode(rdev); +@@ -1117,6 +1126,17 @@ static int rv770_startup(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); ++ if (r) { ++ dev_err(rdev->dev, "IB test failed (%d).\n", r); ++ rdev->accel_working = false; ++ return r; ++ } ++ + return 0; + } + +@@ -1131,15 +1151,11 @@ int rv770_resume(struct radeon_device *rdev) + /* post card */ + atom_asic_init(rdev->mode_info.atom_context); + ++ rdev->accel_working = true; + r = rv770_startup(rdev); + if (r) { + DRM_ERROR("r600 startup failed on resume\n"); +- return r; +- } +- +- r = r600_ib_test(rdev); +- if (r) { +- DRM_ERROR("radeon: failed testing IB (%d).\n", r); ++ rdev->accel_working = false; + return r; + } + +@@ -1156,13 +1172,14 @@ int rv770_resume(struct radeon_device *rdev) + int rv770_suspend(struct radeon_device *rdev) + { + r600_audio_fini(rdev); ++ radeon_ib_pool_suspend(rdev); ++ r600_blit_suspend(rdev); + /* FIXME: we should wait for ring to be empty */ + r700_cp_stop(rdev); +- rdev->cp.ready = false; ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; + r600_irq_suspend(rdev); + radeon_wb_disable(rdev); + rv770_pcie_gart_disable(rdev); +- r600_blit_suspend(rdev); + + return 0; + } +@@ -1227,8 +1244,8 @@ int rv770_init(struct radeon_device *rdev) + if (r) + return r; + +- rdev->cp.ring_obj = NULL; +- r600_ring_init(rdev, 1024 * 1024); ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; ++ r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); + + rdev->ih.ring_obj = NULL; + r600_ih_ring_init(rdev, 64 * 1024); +@@ -1237,30 +1254,24 @@ int rv770_init(struct radeon_device *rdev) + if (r) + return r; + ++ r = radeon_ib_pool_init(rdev); + rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ + r = rv770_startup(rdev); + if (r) { + dev_err(rdev->dev, "disabling GPU acceleration\n"); + r700_cp_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); ++ r100_ib_fini(rdev); + radeon_irq_kms_fini(rdev); + rv770_pcie_gart_fini(rdev); + rdev->accel_working = false; + } +- if (rdev->accel_working) { +- r = radeon_ib_pool_init(rdev); +- if (r) { +- dev_err(rdev->dev, "IB initialization failed (%d).\n", r); +- rdev->accel_working = false; +- } else { +- r = r600_ib_test(rdev); +- if (r) { +- dev_err(rdev->dev, "IB test failed (%d).\n", r); +- rdev->accel_working = false; +- } +- } +- } + + r = r600_audio_init(rdev); + if (r) { +@@ -1277,11 +1288,12 @@ void rv770_fini(struct radeon_device *rdev) + r700_cp_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); +- radeon_ib_pool_fini(rdev); ++ r100_ib_fini(rdev); + radeon_irq_kms_fini(rdev); + rv770_pcie_gart_fini(rdev); + r600_vram_scratch_fini(rdev); + radeon_gem_fini(rdev); ++ radeon_semaphore_driver_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_agp_fini(rdev); + radeon_bo_fini(rdev); +diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c +new file mode 100644 +index 0000000..e710073 +--- /dev/null ++++ b/drivers/gpu/drm/radeon/si.c +@@ -0,0 +1,4154 @@ ++/* ++ * Copyright 2011 Advanced Micro Devices, Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ * ++ * Authors: Alex Deucher ++ */ ++#include ++#include ++#include ++#include ++#include "drmP.h" ++#include "radeon.h" ++#include "radeon_asic.h" ++#include "radeon_drm.h" ++#include "sid.h" ++#include "atom.h" ++#include "si_blit_shaders.h" ++ ++#define SI_PFP_UCODE_SIZE 2144 ++#define SI_PM4_UCODE_SIZE 2144 ++#define SI_CE_UCODE_SIZE 2144 ++#define SI_RLC_UCODE_SIZE 2048 ++#define SI_MC_UCODE_SIZE 7769 ++ ++MODULE_FIRMWARE("radeon/TAHITI_pfp.bin"); ++MODULE_FIRMWARE("radeon/TAHITI_me.bin"); ++MODULE_FIRMWARE("radeon/TAHITI_ce.bin"); ++MODULE_FIRMWARE("radeon/TAHITI_mc.bin"); ++MODULE_FIRMWARE("radeon/TAHITI_rlc.bin"); ++MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin"); ++MODULE_FIRMWARE("radeon/PITCAIRN_me.bin"); ++MODULE_FIRMWARE("radeon/PITCAIRN_ce.bin"); ++MODULE_FIRMWARE("radeon/PITCAIRN_mc.bin"); ++MODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin"); ++MODULE_FIRMWARE("radeon/VERDE_pfp.bin"); ++MODULE_FIRMWARE("radeon/VERDE_me.bin"); ++MODULE_FIRMWARE("radeon/VERDE_ce.bin"); ++MODULE_FIRMWARE("radeon/VERDE_mc.bin"); ++MODULE_FIRMWARE("radeon/VERDE_rlc.bin"); ++ ++extern int r600_ih_ring_alloc(struct radeon_device *rdev); ++extern void r600_ih_ring_fini(struct radeon_device *rdev); ++extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev); ++extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); ++extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); ++extern u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev); ++ ++/* get temperature in millidegrees */ ++int si_get_temp(struct radeon_device *rdev) ++{ ++ u32 temp; ++ int actual_temp = 0; ++ ++ temp = (RREG32(CG_MULT_THERMAL_STATUS) & CTF_TEMP_MASK) >> ++ CTF_TEMP_SHIFT; ++ ++ if (temp & 0x200) ++ actual_temp = 255; ++ else ++ actual_temp = temp & 0x1ff; ++ ++ actual_temp = (actual_temp * 1000); ++ ++ return actual_temp; ++} ++ ++#define TAHITI_IO_MC_REGS_SIZE 36 ++ ++static const u32 tahiti_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = { ++ {0x0000006f, 0x03044000}, ++ {0x00000070, 0x0480c018}, ++ {0x00000071, 0x00000040}, ++ {0x00000072, 0x01000000}, ++ {0x00000074, 0x000000ff}, ++ {0x00000075, 0x00143400}, ++ {0x00000076, 0x08ec0800}, ++ {0x00000077, 0x040000cc}, ++ {0x00000079, 0x00000000}, ++ {0x0000007a, 0x21000409}, ++ {0x0000007c, 0x00000000}, ++ {0x0000007d, 0xe8000000}, ++ {0x0000007e, 0x044408a8}, ++ {0x0000007f, 0x00000003}, ++ {0x00000080, 0x00000000}, ++ {0x00000081, 0x01000000}, ++ {0x00000082, 0x02000000}, ++ {0x00000083, 0x00000000}, ++ {0x00000084, 0xe3f3e4f4}, ++ {0x00000085, 0x00052024}, ++ {0x00000087, 0x00000000}, ++ {0x00000088, 0x66036603}, ++ {0x00000089, 0x01000000}, ++ {0x0000008b, 0x1c0a0000}, ++ {0x0000008c, 0xff010000}, ++ {0x0000008e, 0xffffefff}, ++ {0x0000008f, 0xfff3efff}, ++ {0x00000090, 0xfff3efbf}, ++ {0x00000094, 0x00101101}, ++ {0x00000095, 0x00000fff}, ++ {0x00000096, 0x00116fff}, ++ {0x00000097, 0x60010000}, ++ {0x00000098, 0x10010000}, ++ {0x00000099, 0x00006000}, ++ {0x0000009a, 0x00001000}, ++ {0x0000009f, 0x00a77400} ++}; ++ ++static const u32 pitcairn_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = { ++ {0x0000006f, 0x03044000}, ++ {0x00000070, 0x0480c018}, ++ {0x00000071, 0x00000040}, ++ {0x00000072, 0x01000000}, ++ {0x00000074, 0x000000ff}, ++ {0x00000075, 0x00143400}, ++ {0x00000076, 0x08ec0800}, ++ {0x00000077, 0x040000cc}, ++ {0x00000079, 0x00000000}, ++ {0x0000007a, 0x21000409}, ++ {0x0000007c, 0x00000000}, ++ {0x0000007d, 0xe8000000}, ++ {0x0000007e, 0x044408a8}, ++ {0x0000007f, 0x00000003}, ++ {0x00000080, 0x00000000}, ++ {0x00000081, 0x01000000}, ++ {0x00000082, 0x02000000}, ++ {0x00000083, 0x00000000}, ++ {0x00000084, 0xe3f3e4f4}, ++ {0x00000085, 0x00052024}, ++ {0x00000087, 0x00000000}, ++ {0x00000088, 0x66036603}, ++ {0x00000089, 0x01000000}, ++ {0x0000008b, 0x1c0a0000}, ++ {0x0000008c, 0xff010000}, ++ {0x0000008e, 0xffffefff}, ++ {0x0000008f, 0xfff3efff}, ++ {0x00000090, 0xfff3efbf}, ++ {0x00000094, 0x00101101}, ++ {0x00000095, 0x00000fff}, ++ {0x00000096, 0x00116fff}, ++ {0x00000097, 0x60010000}, ++ {0x00000098, 0x10010000}, ++ {0x00000099, 0x00006000}, ++ {0x0000009a, 0x00001000}, ++ {0x0000009f, 0x00a47400} ++}; ++ ++static const u32 verde_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = { ++ {0x0000006f, 0x03044000}, ++ {0x00000070, 0x0480c018}, ++ {0x00000071, 0x00000040}, ++ {0x00000072, 0x01000000}, ++ {0x00000074, 0x000000ff}, ++ {0x00000075, 0x00143400}, ++ {0x00000076, 0x08ec0800}, ++ {0x00000077, 0x040000cc}, ++ {0x00000079, 0x00000000}, ++ {0x0000007a, 0x21000409}, ++ {0x0000007c, 0x00000000}, ++ {0x0000007d, 0xe8000000}, ++ {0x0000007e, 0x044408a8}, ++ {0x0000007f, 0x00000003}, ++ {0x00000080, 0x00000000}, ++ {0x00000081, 0x01000000}, ++ {0x00000082, 0x02000000}, ++ {0x00000083, 0x00000000}, ++ {0x00000084, 0xe3f3e4f4}, ++ {0x00000085, 0x00052024}, ++ {0x00000087, 0x00000000}, ++ {0x00000088, 0x66036603}, ++ {0x00000089, 0x01000000}, ++ {0x0000008b, 0x1c0a0000}, ++ {0x0000008c, 0xff010000}, ++ {0x0000008e, 0xffffefff}, ++ {0x0000008f, 0xfff3efff}, ++ {0x00000090, 0xfff3efbf}, ++ {0x00000094, 0x00101101}, ++ {0x00000095, 0x00000fff}, ++ {0x00000096, 0x00116fff}, ++ {0x00000097, 0x60010000}, ++ {0x00000098, 0x10010000}, ++ {0x00000099, 0x00006000}, ++ {0x0000009a, 0x00001000}, ++ {0x0000009f, 0x00a37400} ++}; ++ ++/* ucode loading */ ++static int si_mc_load_microcode(struct radeon_device *rdev) ++{ ++ const __be32 *fw_data; ++ u32 running, blackout = 0; ++ u32 *io_mc_regs; ++ int i, ucode_size, regs_size; ++ ++ if (!rdev->mc_fw) ++ return -EINVAL; ++ ++ switch (rdev->family) { ++ case CHIP_TAHITI: ++ io_mc_regs = (u32 *)&tahiti_io_mc_regs; ++ ucode_size = SI_MC_UCODE_SIZE; ++ regs_size = TAHITI_IO_MC_REGS_SIZE; ++ break; ++ case CHIP_PITCAIRN: ++ io_mc_regs = (u32 *)&pitcairn_io_mc_regs; ++ ucode_size = SI_MC_UCODE_SIZE; ++ regs_size = TAHITI_IO_MC_REGS_SIZE; ++ break; ++ case CHIP_VERDE: ++ default: ++ io_mc_regs = (u32 *)&verde_io_mc_regs; ++ ucode_size = SI_MC_UCODE_SIZE; ++ regs_size = TAHITI_IO_MC_REGS_SIZE; ++ break; ++ } ++ ++ running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK; ++ ++ if (running == 0) { ++ if (running) { ++ blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); ++ WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); ++ } ++ ++ /* reset the engine and set to writable */ ++ WREG32(MC_SEQ_SUP_CNTL, 0x00000008); ++ WREG32(MC_SEQ_SUP_CNTL, 0x00000010); ++ ++ /* load mc io regs */ ++ for (i = 0; i < regs_size; i++) { ++ WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]); ++ WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]); ++ } ++ /* load the MC ucode */ ++ fw_data = (const __be32 *)rdev->mc_fw->data; ++ for (i = 0; i < ucode_size; i++) ++ WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++)); ++ ++ /* put the engine back into the active state */ ++ WREG32(MC_SEQ_SUP_CNTL, 0x00000008); ++ WREG32(MC_SEQ_SUP_CNTL, 0x00000004); ++ WREG32(MC_SEQ_SUP_CNTL, 0x00000001); ++ ++ /* wait for training to complete */ ++ for (i = 0; i < rdev->usec_timeout; i++) { ++ if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D0) ++ break; ++ udelay(1); ++ } ++ for (i = 0; i < rdev->usec_timeout; i++) { ++ if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D1) ++ break; ++ udelay(1); ++ } ++ ++ if (running) ++ WREG32(MC_SHARED_BLACKOUT_CNTL, blackout); ++ } ++ ++ return 0; ++} ++ ++static int si_init_microcode(struct radeon_device *rdev) ++{ ++ struct platform_device *pdev; ++ const char *chip_name; ++ const char *rlc_chip_name; ++ size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size; ++ char fw_name[30]; ++ int err; ++ ++ DRM_DEBUG("\n"); ++ ++ pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0); ++ err = IS_ERR(pdev); ++ if (err) { ++ printk(KERN_ERR "radeon_cp: Failed to register firmware\n"); ++ return -EINVAL; ++ } ++ ++ switch (rdev->family) { ++ case CHIP_TAHITI: ++ chip_name = "TAHITI"; ++ rlc_chip_name = "TAHITI"; ++ pfp_req_size = SI_PFP_UCODE_SIZE * 4; ++ me_req_size = SI_PM4_UCODE_SIZE * 4; ++ ce_req_size = SI_CE_UCODE_SIZE * 4; ++ rlc_req_size = SI_RLC_UCODE_SIZE * 4; ++ mc_req_size = SI_MC_UCODE_SIZE * 4; ++ break; ++ case CHIP_PITCAIRN: ++ chip_name = "PITCAIRN"; ++ rlc_chip_name = "PITCAIRN"; ++ pfp_req_size = SI_PFP_UCODE_SIZE * 4; ++ me_req_size = SI_PM4_UCODE_SIZE * 4; ++ ce_req_size = SI_CE_UCODE_SIZE * 4; ++ rlc_req_size = SI_RLC_UCODE_SIZE * 4; ++ mc_req_size = SI_MC_UCODE_SIZE * 4; ++ break; ++ case CHIP_VERDE: ++ chip_name = "VERDE"; ++ rlc_chip_name = "VERDE"; ++ pfp_req_size = SI_PFP_UCODE_SIZE * 4; ++ me_req_size = SI_PM4_UCODE_SIZE * 4; ++ ce_req_size = SI_CE_UCODE_SIZE * 4; ++ rlc_req_size = SI_RLC_UCODE_SIZE * 4; ++ mc_req_size = SI_MC_UCODE_SIZE * 4; ++ break; ++ default: BUG(); ++ } ++ ++ DRM_INFO("Loading %s Microcode\n", chip_name); ++ ++ snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); ++ err = request_firmware(&rdev->pfp_fw, fw_name, &pdev->dev); ++ if (err) ++ goto out; ++ if (rdev->pfp_fw->size != pfp_req_size) { ++ printk(KERN_ERR ++ "si_cp: Bogus length %zu in firmware \"%s\"\n", ++ rdev->pfp_fw->size, fw_name); ++ err = -EINVAL; ++ goto out; ++ } ++ ++ snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name); ++ err = request_firmware(&rdev->me_fw, fw_name, &pdev->dev); ++ if (err) ++ goto out; ++ if (rdev->me_fw->size != me_req_size) { ++ printk(KERN_ERR ++ "si_cp: Bogus length %zu in firmware \"%s\"\n", ++ rdev->me_fw->size, fw_name); ++ err = -EINVAL; ++ } ++ ++ snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", chip_name); ++ err = request_firmware(&rdev->ce_fw, fw_name, &pdev->dev); ++ if (err) ++ goto out; ++ if (rdev->ce_fw->size != ce_req_size) { ++ printk(KERN_ERR ++ "si_cp: Bogus length %zu in firmware \"%s\"\n", ++ rdev->ce_fw->size, fw_name); ++ err = -EINVAL; ++ } ++ ++ snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name); ++ err = request_firmware(&rdev->rlc_fw, fw_name, &pdev->dev); ++ if (err) ++ goto out; ++ if (rdev->rlc_fw->size != rlc_req_size) { ++ printk(KERN_ERR ++ "si_rlc: Bogus length %zu in firmware \"%s\"\n", ++ rdev->rlc_fw->size, fw_name); ++ err = -EINVAL; ++ } ++ ++ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); ++ err = request_firmware(&rdev->mc_fw, fw_name, &pdev->dev); ++ if (err) ++ goto out; ++ if (rdev->mc_fw->size != mc_req_size) { ++ printk(KERN_ERR ++ "si_mc: Bogus length %zu in firmware \"%s\"\n", ++ rdev->mc_fw->size, fw_name); ++ err = -EINVAL; ++ } ++ ++out: ++ platform_device_unregister(pdev); ++ ++ if (err) { ++ if (err != -EINVAL) ++ printk(KERN_ERR ++ "si_cp: Failed to load firmware \"%s\"\n", ++ fw_name); ++ release_firmware(rdev->pfp_fw); ++ rdev->pfp_fw = NULL; ++ release_firmware(rdev->me_fw); ++ rdev->me_fw = NULL; ++ release_firmware(rdev->ce_fw); ++ rdev->ce_fw = NULL; ++ release_firmware(rdev->rlc_fw); ++ rdev->rlc_fw = NULL; ++ release_firmware(rdev->mc_fw); ++ rdev->mc_fw = NULL; ++ } ++ return err; ++} ++ ++/* watermark setup */ ++static u32 dce6_line_buffer_adjust(struct radeon_device *rdev, ++ struct radeon_crtc *radeon_crtc, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *other_mode) ++{ ++ u32 tmp, buffer_alloc, i; ++ u32 pipe_offset = radeon_crtc->crtc_id * 0x20; ++ /* ++ * Line Buffer Setup ++ * There are 3 line buffers, each one shared by 2 display controllers. ++ * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between ++ * the display controllers. The paritioning is done via one of four ++ * preset allocations specified in bits 21:20: ++ * 0 - half lb ++ * 2 - whole lb, other crtc must be disabled ++ */ ++ /* this can get tricky if we have two large displays on a paired group ++ * of crtcs. Ideally for multiple large displays we'd assign them to ++ * non-linked crtcs for maximum line buffer allocation. ++ */ ++ if (radeon_crtc->base.enabled && mode) { ++ if (other_mode) { ++ tmp = 0; /* 1/2 */ ++ buffer_alloc = 1; ++ } else { ++ tmp = 2; /* whole */ ++ buffer_alloc = 2; ++ } ++ } else { ++ tmp = 0; ++ buffer_alloc = 0; ++ } ++ ++ WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, ++ DC_LB_MEMORY_CONFIG(tmp)); ++ ++ WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset, ++ DMIF_BUFFERS_ALLOCATED(buffer_alloc)); ++ for (i = 0; i < rdev->usec_timeout; i++) { ++ if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) & ++ DMIF_BUFFERS_ALLOCATED_COMPLETED) ++ break; ++ udelay(1); ++ } ++ ++ if (radeon_crtc->base.enabled && mode) { ++ switch (tmp) { ++ case 0: ++ default: ++ return 4096 * 2; ++ case 2: ++ return 8192 * 2; ++ } ++ } ++ ++ /* controller not enabled, so no lb used */ ++ return 0; ++} ++ ++static u32 si_get_number_of_dram_channels(struct radeon_device *rdev) ++{ ++ u32 tmp = RREG32(MC_SHARED_CHMAP); ++ ++ switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { ++ case 0: ++ default: ++ return 1; ++ case 1: ++ return 2; ++ case 2: ++ return 4; ++ case 3: ++ return 8; ++ case 4: ++ return 3; ++ case 5: ++ return 6; ++ case 6: ++ return 10; ++ case 7: ++ return 12; ++ case 8: ++ return 16; ++ } ++} ++ ++struct dce6_wm_params { ++ u32 dram_channels; /* number of dram channels */ ++ u32 yclk; /* bandwidth per dram data pin in kHz */ ++ u32 sclk; /* engine clock in kHz */ ++ u32 disp_clk; /* display clock in kHz */ ++ u32 src_width; /* viewport width */ ++ u32 active_time; /* active display time in ns */ ++ u32 blank_time; /* blank time in ns */ ++ bool interlaced; /* mode is interlaced */ ++ fixed20_12 vsc; /* vertical scale ratio */ ++ u32 num_heads; /* number of active crtcs */ ++ u32 bytes_per_pixel; /* bytes per pixel display + overlay */ ++ u32 lb_size; /* line buffer allocated to pipe */ ++ u32 vtaps; /* vertical scaler taps */ ++}; ++ ++static u32 dce6_dram_bandwidth(struct dce6_wm_params *wm) ++{ ++ /* Calculate raw DRAM Bandwidth */ ++ fixed20_12 dram_efficiency; /* 0.7 */ ++ fixed20_12 yclk, dram_channels, bandwidth; ++ fixed20_12 a; ++ ++ a.full = dfixed_const(1000); ++ yclk.full = dfixed_const(wm->yclk); ++ yclk.full = dfixed_div(yclk, a); ++ dram_channels.full = dfixed_const(wm->dram_channels * 4); ++ a.full = dfixed_const(10); ++ dram_efficiency.full = dfixed_const(7); ++ dram_efficiency.full = dfixed_div(dram_efficiency, a); ++ bandwidth.full = dfixed_mul(dram_channels, yclk); ++ bandwidth.full = dfixed_mul(bandwidth, dram_efficiency); ++ ++ return dfixed_trunc(bandwidth); ++} ++ ++static u32 dce6_dram_bandwidth_for_display(struct dce6_wm_params *wm) ++{ ++ /* Calculate DRAM Bandwidth and the part allocated to display. */ ++ fixed20_12 disp_dram_allocation; /* 0.3 to 0.7 */ ++ fixed20_12 yclk, dram_channels, bandwidth; ++ fixed20_12 a; ++ ++ a.full = dfixed_const(1000); ++ yclk.full = dfixed_const(wm->yclk); ++ yclk.full = dfixed_div(yclk, a); ++ dram_channels.full = dfixed_const(wm->dram_channels * 4); ++ a.full = dfixed_const(10); ++ disp_dram_allocation.full = dfixed_const(3); /* XXX worse case value 0.3 */ ++ disp_dram_allocation.full = dfixed_div(disp_dram_allocation, a); ++ bandwidth.full = dfixed_mul(dram_channels, yclk); ++ bandwidth.full = dfixed_mul(bandwidth, disp_dram_allocation); ++ ++ return dfixed_trunc(bandwidth); ++} ++ ++static u32 dce6_data_return_bandwidth(struct dce6_wm_params *wm) ++{ ++ /* Calculate the display Data return Bandwidth */ ++ fixed20_12 return_efficiency; /* 0.8 */ ++ fixed20_12 sclk, bandwidth; ++ fixed20_12 a; ++ ++ a.full = dfixed_const(1000); ++ sclk.full = dfixed_const(wm->sclk); ++ sclk.full = dfixed_div(sclk, a); ++ a.full = dfixed_const(10); ++ return_efficiency.full = dfixed_const(8); ++ return_efficiency.full = dfixed_div(return_efficiency, a); ++ a.full = dfixed_const(32); ++ bandwidth.full = dfixed_mul(a, sclk); ++ bandwidth.full = dfixed_mul(bandwidth, return_efficiency); ++ ++ return dfixed_trunc(bandwidth); ++} ++ ++static u32 dce6_get_dmif_bytes_per_request(struct dce6_wm_params *wm) ++{ ++ return 32; ++} ++ ++static u32 dce6_dmif_request_bandwidth(struct dce6_wm_params *wm) ++{ ++ /* Calculate the DMIF Request Bandwidth */ ++ fixed20_12 disp_clk_request_efficiency; /* 0.8 */ ++ fixed20_12 disp_clk, sclk, bandwidth; ++ fixed20_12 a, b1, b2; ++ u32 min_bandwidth; ++ ++ a.full = dfixed_const(1000); ++ disp_clk.full = dfixed_const(wm->disp_clk); ++ disp_clk.full = dfixed_div(disp_clk, a); ++ a.full = dfixed_const(dce6_get_dmif_bytes_per_request(wm) / 2); ++ b1.full = dfixed_mul(a, disp_clk); ++ ++ a.full = dfixed_const(1000); ++ sclk.full = dfixed_const(wm->sclk); ++ sclk.full = dfixed_div(sclk, a); ++ a.full = dfixed_const(dce6_get_dmif_bytes_per_request(wm)); ++ b2.full = dfixed_mul(a, sclk); ++ ++ a.full = dfixed_const(10); ++ disp_clk_request_efficiency.full = dfixed_const(8); ++ disp_clk_request_efficiency.full = dfixed_div(disp_clk_request_efficiency, a); ++ ++ min_bandwidth = min(dfixed_trunc(b1), dfixed_trunc(b2)); ++ ++ a.full = dfixed_const(min_bandwidth); ++ bandwidth.full = dfixed_mul(a, disp_clk_request_efficiency); ++ ++ return dfixed_trunc(bandwidth); ++} ++ ++static u32 dce6_available_bandwidth(struct dce6_wm_params *wm) ++{ ++ /* Calculate the Available bandwidth. Display can use this temporarily but not in average. */ ++ u32 dram_bandwidth = dce6_dram_bandwidth(wm); ++ u32 data_return_bandwidth = dce6_data_return_bandwidth(wm); ++ u32 dmif_req_bandwidth = dce6_dmif_request_bandwidth(wm); ++ ++ return min(dram_bandwidth, min(data_return_bandwidth, dmif_req_bandwidth)); ++} ++ ++static u32 dce6_average_bandwidth(struct dce6_wm_params *wm) ++{ ++ /* Calculate the display mode Average Bandwidth ++ * DisplayMode should contain the source and destination dimensions, ++ * timing, etc. ++ */ ++ fixed20_12 bpp; ++ fixed20_12 line_time; ++ fixed20_12 src_width; ++ fixed20_12 bandwidth; ++ fixed20_12 a; ++ ++ a.full = dfixed_const(1000); ++ line_time.full = dfixed_const(wm->active_time + wm->blank_time); ++ line_time.full = dfixed_div(line_time, a); ++ bpp.full = dfixed_const(wm->bytes_per_pixel); ++ src_width.full = dfixed_const(wm->src_width); ++ bandwidth.full = dfixed_mul(src_width, bpp); ++ bandwidth.full = dfixed_mul(bandwidth, wm->vsc); ++ bandwidth.full = dfixed_div(bandwidth, line_time); ++ ++ return dfixed_trunc(bandwidth); ++} ++ ++static u32 dce6_latency_watermark(struct dce6_wm_params *wm) ++{ ++ /* First calcualte the latency in ns */ ++ u32 mc_latency = 2000; /* 2000 ns. */ ++ u32 available_bandwidth = dce6_available_bandwidth(wm); ++ u32 worst_chunk_return_time = (512 * 8 * 1000) / available_bandwidth; ++ u32 cursor_line_pair_return_time = (128 * 4 * 1000) / available_bandwidth; ++ u32 dc_latency = 40000000 / wm->disp_clk; /* dc pipe latency */ ++ u32 other_heads_data_return_time = ((wm->num_heads + 1) * worst_chunk_return_time) + ++ (wm->num_heads * cursor_line_pair_return_time); ++ u32 latency = mc_latency + other_heads_data_return_time + dc_latency; ++ u32 max_src_lines_per_dst_line, lb_fill_bw, line_fill_time; ++ u32 tmp, dmif_size = 12288; ++ fixed20_12 a, b, c; ++ ++ if (wm->num_heads == 0) ++ return 0; ++ ++ a.full = dfixed_const(2); ++ b.full = dfixed_const(1); ++ if ((wm->vsc.full > a.full) || ++ ((wm->vsc.full > b.full) && (wm->vtaps >= 3)) || ++ (wm->vtaps >= 5) || ++ ((wm->vsc.full >= a.full) && wm->interlaced)) ++ max_src_lines_per_dst_line = 4; ++ else ++ max_src_lines_per_dst_line = 2; ++ ++ a.full = dfixed_const(available_bandwidth); ++ b.full = dfixed_const(wm->num_heads); ++ a.full = dfixed_div(a, b); ++ ++ b.full = dfixed_const(mc_latency + 512); ++ c.full = dfixed_const(wm->disp_clk); ++ b.full = dfixed_div(b, c); ++ ++ c.full = dfixed_const(dmif_size); ++ b.full = dfixed_div(c, b); ++ ++ tmp = min(dfixed_trunc(a), dfixed_trunc(b)); ++ ++ b.full = dfixed_const(1000); ++ c.full = dfixed_const(wm->disp_clk); ++ b.full = dfixed_div(c, b); ++ c.full = dfixed_const(wm->bytes_per_pixel); ++ b.full = dfixed_mul(b, c); ++ ++ lb_fill_bw = min(tmp, dfixed_trunc(b)); ++ ++ a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); ++ b.full = dfixed_const(1000); ++ c.full = dfixed_const(lb_fill_bw); ++ b.full = dfixed_div(c, b); ++ a.full = dfixed_div(a, b); ++ line_fill_time = dfixed_trunc(a); ++ ++ if (line_fill_time < wm->active_time) ++ return latency; ++ else ++ return latency + (line_fill_time - wm->active_time); ++ ++} ++ ++static bool dce6_average_bandwidth_vs_dram_bandwidth_for_display(struct dce6_wm_params *wm) ++{ ++ if (dce6_average_bandwidth(wm) <= ++ (dce6_dram_bandwidth_for_display(wm) / wm->num_heads)) ++ return true; ++ else ++ return false; ++}; ++ ++static bool dce6_average_bandwidth_vs_available_bandwidth(struct dce6_wm_params *wm) ++{ ++ if (dce6_average_bandwidth(wm) <= ++ (dce6_available_bandwidth(wm) / wm->num_heads)) ++ return true; ++ else ++ return false; ++}; ++ ++static bool dce6_check_latency_hiding(struct dce6_wm_params *wm) ++{ ++ u32 lb_partitions = wm->lb_size / wm->src_width; ++ u32 line_time = wm->active_time + wm->blank_time; ++ u32 latency_tolerant_lines; ++ u32 latency_hiding; ++ fixed20_12 a; ++ ++ a.full = dfixed_const(1); ++ if (wm->vsc.full > a.full) ++ latency_tolerant_lines = 1; ++ else { ++ if (lb_partitions <= (wm->vtaps + 1)) ++ latency_tolerant_lines = 1; ++ else ++ latency_tolerant_lines = 2; ++ } ++ ++ latency_hiding = (latency_tolerant_lines * line_time + wm->blank_time); ++ ++ if (dce6_latency_watermark(wm) <= latency_hiding) ++ return true; ++ else ++ return false; ++} ++ ++static void dce6_program_watermarks(struct radeon_device *rdev, ++ struct radeon_crtc *radeon_crtc, ++ u32 lb_size, u32 num_heads) ++{ ++ struct drm_display_mode *mode = &radeon_crtc->base.mode; ++ struct dce6_wm_params wm; ++ u32 pixel_period; ++ u32 line_time = 0; ++ u32 latency_watermark_a = 0, latency_watermark_b = 0; ++ u32 priority_a_mark = 0, priority_b_mark = 0; ++ u32 priority_a_cnt = PRIORITY_OFF; ++ u32 priority_b_cnt = PRIORITY_OFF; ++ u32 tmp, arb_control3; ++ fixed20_12 a, b, c; ++ ++ if (radeon_crtc->base.enabled && num_heads && mode) { ++ pixel_period = 1000000 / (u32)mode->clock; ++ line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); ++ priority_a_cnt = 0; ++ priority_b_cnt = 0; ++ ++ wm.yclk = rdev->pm.current_mclk * 10; ++ wm.sclk = rdev->pm.current_sclk * 10; ++ wm.disp_clk = mode->clock; ++ wm.src_width = mode->crtc_hdisplay; ++ wm.active_time = mode->crtc_hdisplay * pixel_period; ++ wm.blank_time = line_time - wm.active_time; ++ wm.interlaced = false; ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) ++ wm.interlaced = true; ++ wm.vsc = radeon_crtc->vsc; ++ wm.vtaps = 1; ++ if (radeon_crtc->rmx_type != RMX_OFF) ++ wm.vtaps = 2; ++ wm.bytes_per_pixel = 4; /* XXX: get this from fb config */ ++ wm.lb_size = lb_size; ++ if (rdev->family == CHIP_ARUBA) ++ wm.dram_channels = evergreen_get_number_of_dram_channels(rdev); ++ else ++ wm.dram_channels = si_get_number_of_dram_channels(rdev); ++ wm.num_heads = num_heads; ++ ++ /* set for high clocks */ ++ latency_watermark_a = min(dce6_latency_watermark(&wm), (u32)65535); ++ /* set for low clocks */ ++ /* wm.yclk = low clk; wm.sclk = low clk */ ++ latency_watermark_b = min(dce6_latency_watermark(&wm), (u32)65535); ++ ++ /* possibly force display priority to high */ ++ /* should really do this at mode validation time... */ ++ if (!dce6_average_bandwidth_vs_dram_bandwidth_for_display(&wm) || ++ !dce6_average_bandwidth_vs_available_bandwidth(&wm) || ++ !dce6_check_latency_hiding(&wm) || ++ (rdev->disp_priority == 2)) { ++ DRM_DEBUG_KMS("force priority to high\n"); ++ priority_a_cnt |= PRIORITY_ALWAYS_ON; ++ priority_b_cnt |= PRIORITY_ALWAYS_ON; ++ } ++ ++ a.full = dfixed_const(1000); ++ b.full = dfixed_const(mode->clock); ++ b.full = dfixed_div(b, a); ++ c.full = dfixed_const(latency_watermark_a); ++ c.full = dfixed_mul(c, b); ++ c.full = dfixed_mul(c, radeon_crtc->hsc); ++ c.full = dfixed_div(c, a); ++ a.full = dfixed_const(16); ++ c.full = dfixed_div(c, a); ++ priority_a_mark = dfixed_trunc(c); ++ priority_a_cnt |= priority_a_mark & PRIORITY_MARK_MASK; ++ ++ a.full = dfixed_const(1000); ++ b.full = dfixed_const(mode->clock); ++ b.full = dfixed_div(b, a); ++ c.full = dfixed_const(latency_watermark_b); ++ c.full = dfixed_mul(c, b); ++ c.full = dfixed_mul(c, radeon_crtc->hsc); ++ c.full = dfixed_div(c, a); ++ a.full = dfixed_const(16); ++ c.full = dfixed_div(c, a); ++ priority_b_mark = dfixed_trunc(c); ++ priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK; ++ } ++ ++ /* select wm A */ ++ arb_control3 = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset); ++ tmp = arb_control3; ++ tmp &= ~LATENCY_WATERMARK_MASK(3); ++ tmp |= LATENCY_WATERMARK_MASK(1); ++ WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset, tmp); ++ WREG32(DPG_PIPE_LATENCY_CONTROL + radeon_crtc->crtc_offset, ++ (LATENCY_LOW_WATERMARK(latency_watermark_a) | ++ LATENCY_HIGH_WATERMARK(line_time))); ++ /* select wm B */ ++ tmp = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset); ++ tmp &= ~LATENCY_WATERMARK_MASK(3); ++ tmp |= LATENCY_WATERMARK_MASK(2); ++ WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset, tmp); ++ WREG32(DPG_PIPE_LATENCY_CONTROL + radeon_crtc->crtc_offset, ++ (LATENCY_LOW_WATERMARK(latency_watermark_b) | ++ LATENCY_HIGH_WATERMARK(line_time))); ++ /* restore original selection */ ++ WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset, arb_control3); ++ ++ /* write the priority marks */ ++ WREG32(PRIORITY_A_CNT + radeon_crtc->crtc_offset, priority_a_cnt); ++ WREG32(PRIORITY_B_CNT + radeon_crtc->crtc_offset, priority_b_cnt); ++ ++} ++ ++void dce6_bandwidth_update(struct radeon_device *rdev) ++{ ++ struct drm_display_mode *mode0 = NULL; ++ struct drm_display_mode *mode1 = NULL; ++ u32 num_heads = 0, lb_size; ++ int i; ++ ++ radeon_update_display_priority(rdev); ++ ++ for (i = 0; i < rdev->num_crtc; i++) { ++ if (rdev->mode_info.crtcs[i]->base.enabled) ++ num_heads++; ++ } ++ for (i = 0; i < rdev->num_crtc; i += 2) { ++ mode0 = &rdev->mode_info.crtcs[i]->base.mode; ++ mode1 = &rdev->mode_info.crtcs[i+1]->base.mode; ++ lb_size = dce6_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i], mode0, mode1); ++ dce6_program_watermarks(rdev, rdev->mode_info.crtcs[i], lb_size, num_heads); ++ lb_size = dce6_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i+1], mode1, mode0); ++ dce6_program_watermarks(rdev, rdev->mode_info.crtcs[i+1], lb_size, num_heads); ++ } ++} ++ ++/* ++ * Core functions ++ */ ++static u32 si_get_tile_pipe_to_backend_map(struct radeon_device *rdev, ++ u32 num_tile_pipes, ++ u32 num_backends_per_asic, ++ u32 *backend_disable_mask_per_asic, ++ u32 num_shader_engines) ++{ ++ u32 backend_map = 0; ++ u32 enabled_backends_mask = 0; ++ u32 enabled_backends_count = 0; ++ u32 num_backends_per_se; ++ u32 cur_pipe; ++ u32 swizzle_pipe[SI_MAX_PIPES]; ++ u32 cur_backend = 0; ++ u32 i; ++ bool force_no_swizzle; ++ ++ /* force legal values */ ++ if (num_tile_pipes < 1) ++ num_tile_pipes = 1; ++ if (num_tile_pipes > rdev->config.si.max_tile_pipes) ++ num_tile_pipes = rdev->config.si.max_tile_pipes; ++ if (num_shader_engines < 1) ++ num_shader_engines = 1; ++ if (num_shader_engines > rdev->config.si.max_shader_engines) ++ num_shader_engines = rdev->config.si.max_shader_engines; ++ if (num_backends_per_asic < num_shader_engines) ++ num_backends_per_asic = num_shader_engines; ++ if (num_backends_per_asic > (rdev->config.si.max_backends_per_se * num_shader_engines)) ++ num_backends_per_asic = rdev->config.si.max_backends_per_se * num_shader_engines; ++ ++ /* make sure we have the same number of backends per se */ ++ num_backends_per_asic = ALIGN(num_backends_per_asic, num_shader_engines); ++ /* set up the number of backends per se */ ++ num_backends_per_se = num_backends_per_asic / num_shader_engines; ++ if (num_backends_per_se > rdev->config.si.max_backends_per_se) { ++ num_backends_per_se = rdev->config.si.max_backends_per_se; ++ num_backends_per_asic = num_backends_per_se * num_shader_engines; ++ } ++ ++ /* create enable mask and count for enabled backends */ ++ for (i = 0; i < SI_MAX_BACKENDS; ++i) { ++ if (((*backend_disable_mask_per_asic >> i) & 1) == 0) { ++ enabled_backends_mask |= (1 << i); ++ ++enabled_backends_count; ++ } ++ if (enabled_backends_count == num_backends_per_asic) ++ break; ++ } ++ ++ /* force the backends mask to match the current number of backends */ ++ if (enabled_backends_count != num_backends_per_asic) { ++ u32 this_backend_enabled; ++ u32 shader_engine; ++ u32 backend_per_se; ++ ++ enabled_backends_mask = 0; ++ enabled_backends_count = 0; ++ *backend_disable_mask_per_asic = SI_MAX_BACKENDS_MASK; ++ for (i = 0; i < SI_MAX_BACKENDS; ++i) { ++ /* calc the current se */ ++ shader_engine = i / rdev->config.si.max_backends_per_se; ++ /* calc the backend per se */ ++ backend_per_se = i % rdev->config.si.max_backends_per_se; ++ /* default to not enabled */ ++ this_backend_enabled = 0; ++ if ((shader_engine < num_shader_engines) && ++ (backend_per_se < num_backends_per_se)) ++ this_backend_enabled = 1; ++ if (this_backend_enabled) { ++ enabled_backends_mask |= (1 << i); ++ *backend_disable_mask_per_asic &= ~(1 << i); ++ ++enabled_backends_count; ++ } ++ } ++ } ++ ++ ++ memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * SI_MAX_PIPES); ++ switch (rdev->family) { ++ case CHIP_TAHITI: ++ case CHIP_PITCAIRN: ++ case CHIP_VERDE: ++ force_no_swizzle = true; ++ break; ++ default: ++ force_no_swizzle = false; ++ break; ++ } ++ if (force_no_swizzle) { ++ bool last_backend_enabled = false; ++ ++ force_no_swizzle = false; ++ for (i = 0; i < SI_MAX_BACKENDS; ++i) { ++ if (((enabled_backends_mask >> i) & 1) == 1) { ++ if (last_backend_enabled) ++ force_no_swizzle = true; ++ last_backend_enabled = true; ++ } else ++ last_backend_enabled = false; ++ } ++ } ++ ++ switch (num_tile_pipes) { ++ case 1: ++ case 3: ++ case 5: ++ case 7: ++ DRM_ERROR("odd number of pipes!\n"); ++ break; ++ case 2: ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 1; ++ break; ++ case 4: ++ if (force_no_swizzle) { ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 1; ++ swizzle_pipe[2] = 2; ++ swizzle_pipe[3] = 3; ++ } else { ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 2; ++ swizzle_pipe[2] = 1; ++ swizzle_pipe[3] = 3; ++ } ++ break; ++ case 6: ++ if (force_no_swizzle) { ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 1; ++ swizzle_pipe[2] = 2; ++ swizzle_pipe[3] = 3; ++ swizzle_pipe[4] = 4; ++ swizzle_pipe[5] = 5; ++ } else { ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 2; ++ swizzle_pipe[2] = 4; ++ swizzle_pipe[3] = 1; ++ swizzle_pipe[4] = 3; ++ swizzle_pipe[5] = 5; ++ } ++ break; ++ case 8: ++ if (force_no_swizzle) { ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 1; ++ swizzle_pipe[2] = 2; ++ swizzle_pipe[3] = 3; ++ swizzle_pipe[4] = 4; ++ swizzle_pipe[5] = 5; ++ swizzle_pipe[6] = 6; ++ swizzle_pipe[7] = 7; ++ } else { ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 2; ++ swizzle_pipe[2] = 4; ++ swizzle_pipe[3] = 6; ++ swizzle_pipe[4] = 1; ++ swizzle_pipe[5] = 3; ++ swizzle_pipe[6] = 5; ++ swizzle_pipe[7] = 7; ++ } ++ break; ++ } ++ ++ for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { ++ while (((1 << cur_backend) & enabled_backends_mask) == 0) ++ cur_backend = (cur_backend + 1) % SI_MAX_BACKENDS; ++ ++ backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4))); ++ ++ cur_backend = (cur_backend + 1) % SI_MAX_BACKENDS; ++ } ++ ++ return backend_map; ++} ++ ++static u32 si_get_disable_mask_per_asic(struct radeon_device *rdev, ++ u32 disable_mask_per_se, ++ u32 max_disable_mask_per_se, ++ u32 num_shader_engines) ++{ ++ u32 disable_field_width_per_se = r600_count_pipe_bits(disable_mask_per_se); ++ u32 disable_mask_per_asic = disable_mask_per_se & max_disable_mask_per_se; ++ ++ if (num_shader_engines == 1) ++ return disable_mask_per_asic; ++ else if (num_shader_engines == 2) ++ return disable_mask_per_asic | (disable_mask_per_asic << disable_field_width_per_se); ++ else ++ return 0xffffffff; ++} ++ ++static void si_tiling_mode_table_init(struct radeon_device *rdev) ++{ ++ const u32 num_tile_mode_states = 32; ++ u32 reg_offset, gb_tile_moden, split_equal_to_row_size; ++ ++ switch (rdev->config.si.mem_row_size_in_kb) { ++ case 1: ++ split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_1KB; ++ break; ++ case 2: ++ default: ++ split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_2KB; ++ break; ++ case 4: ++ split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_4KB; ++ break; ++ } ++ ++ if ((rdev->family == CHIP_TAHITI) || ++ (rdev->family == CHIP_PITCAIRN)) { ++ for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) { ++ switch (reg_offset) { ++ case 0: /* non-AA compressed depth or any compressed stencil */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 1: /* 2xAA/4xAA compressed depth only */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 2: /* 8xAA compressed depth only */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 3: /* 2xAA/4xAA compressed depth with stencil (for depth buffer) */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 4: /* Maps w/ a dimension less than the 2D macro-tile dimensions (for mipmapped depth textures) */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 5: /* Uncompressed 16bpp depth - and stencil buffer allocated with it */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(split_equal_to_row_size) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 6: /* Uncompressed 32bpp depth - and stencil buffer allocated with it */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(split_equal_to_row_size) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); ++ break; ++ case 7: /* Uncompressed 8bpp stencil without depth (drivers typically do not use) */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(split_equal_to_row_size) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 8: /* 1D and 1D Array Surfaces */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | ++ MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 9: /* Displayable maps. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 10: /* Display 8bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 11: /* Display 16bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 12: /* Display 32bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); ++ break; ++ case 13: /* Thin. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 14: /* Thin 8 bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); ++ break; ++ case 15: /* Thin 16 bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); ++ break; ++ case 16: /* Thin 32 bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); ++ break; ++ case 17: /* Thin 64 bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(split_equal_to_row_size) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); ++ break; ++ case 21: /* 8 bpp PRT. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 22: /* 16 bpp PRT */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); ++ break; ++ case 23: /* 32 bpp PRT */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 24: /* 64 bpp PRT */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 25: /* 128 bpp PRT */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) | ++ NUM_BANKS(ADDR_SURF_8_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); ++ break; ++ default: ++ gb_tile_moden = 0; ++ break; ++ } ++ WREG32(GB_TILE_MODE0 + (reg_offset * 4), gb_tile_moden); ++ } ++ } else if (rdev->family == CHIP_VERDE) { ++ for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) { ++ switch (reg_offset) { ++ case 0: /* non-AA compressed depth or any compressed stencil */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); ++ break; ++ case 1: /* 2xAA/4xAA compressed depth only */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); ++ break; ++ case 2: /* 8xAA compressed depth only */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); ++ break; ++ case 3: /* 2xAA/4xAA compressed depth with stencil (for depth buffer) */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); ++ break; ++ case 4: /* Maps w/ a dimension less than the 2D macro-tile dimensions (for mipmapped depth textures) */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 5: /* Uncompressed 16bpp depth - and stencil buffer allocated with it */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(split_equal_to_row_size) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 6: /* Uncompressed 32bpp depth - and stencil buffer allocated with it */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(split_equal_to_row_size) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 7: /* Uncompressed 8bpp stencil without depth (drivers typically do not use) */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(split_equal_to_row_size) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); ++ break; ++ case 8: /* 1D and 1D Array Surfaces */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | ++ MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 9: /* Displayable maps. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 10: /* Display 8bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); ++ break; ++ case 11: /* Display 16bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 12: /* Display 32bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 13: /* Thin. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 14: /* Thin 8 bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 15: /* Thin 16 bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 16: /* Thin 32 bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 17: /* Thin 64 bpp. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P4_8x16) | ++ TILE_SPLIT(split_equal_to_row_size) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 21: /* 8 bpp PRT. */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 22: /* 16 bpp PRT */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); ++ break; ++ case 23: /* 32 bpp PRT */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 24: /* 64 bpp PRT */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | ++ NUM_BANKS(ADDR_SURF_16_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); ++ break; ++ case 25: /* 128 bpp PRT */ ++ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | ++ MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | ++ PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | ++ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) | ++ NUM_BANKS(ADDR_SURF_8_BANK) | ++ BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | ++ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | ++ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); ++ break; ++ default: ++ gb_tile_moden = 0; ++ break; ++ } ++ WREG32(GB_TILE_MODE0 + (reg_offset * 4), gb_tile_moden); ++ } ++ } else ++ DRM_ERROR("unknown asic: 0x%x\n", rdev->family); ++} ++ ++static void si_gpu_init(struct radeon_device *rdev) ++{ ++ u32 cc_rb_backend_disable = 0; ++ u32 cc_gc_shader_array_config; ++ u32 gb_addr_config = 0; ++ u32 mc_shared_chmap, mc_arb_ramcfg; ++ u32 gb_backend_map; ++ u32 cgts_tcc_disable; ++ u32 sx_debug_1; ++ u32 gc_user_shader_array_config; ++ u32 gc_user_rb_backend_disable; ++ u32 cgts_user_tcc_disable; ++ u32 hdp_host_path_cntl; ++ u32 tmp; ++ int i, j; ++ ++ switch (rdev->family) { ++ case CHIP_TAHITI: ++ rdev->config.si.max_shader_engines = 2; ++ rdev->config.si.max_pipes_per_simd = 4; ++ rdev->config.si.max_tile_pipes = 12; ++ rdev->config.si.max_simds_per_se = 8; ++ rdev->config.si.max_backends_per_se = 4; ++ rdev->config.si.max_texture_channel_caches = 12; ++ rdev->config.si.max_gprs = 256; ++ rdev->config.si.max_gs_threads = 32; ++ rdev->config.si.max_hw_contexts = 8; ++ ++ rdev->config.si.sc_prim_fifo_size_frontend = 0x20; ++ rdev->config.si.sc_prim_fifo_size_backend = 0x100; ++ rdev->config.si.sc_hiz_tile_fifo_size = 0x30; ++ rdev->config.si.sc_earlyz_tile_fifo_size = 0x130; ++ break; ++ case CHIP_PITCAIRN: ++ rdev->config.si.max_shader_engines = 2; ++ rdev->config.si.max_pipes_per_simd = 4; ++ rdev->config.si.max_tile_pipes = 8; ++ rdev->config.si.max_simds_per_se = 5; ++ rdev->config.si.max_backends_per_se = 4; ++ rdev->config.si.max_texture_channel_caches = 8; ++ rdev->config.si.max_gprs = 256; ++ rdev->config.si.max_gs_threads = 32; ++ rdev->config.si.max_hw_contexts = 8; ++ ++ rdev->config.si.sc_prim_fifo_size_frontend = 0x20; ++ rdev->config.si.sc_prim_fifo_size_backend = 0x100; ++ rdev->config.si.sc_hiz_tile_fifo_size = 0x30; ++ rdev->config.si.sc_earlyz_tile_fifo_size = 0x130; ++ break; ++ case CHIP_VERDE: ++ default: ++ rdev->config.si.max_shader_engines = 1; ++ rdev->config.si.max_pipes_per_simd = 4; ++ rdev->config.si.max_tile_pipes = 4; ++ rdev->config.si.max_simds_per_se = 2; ++ rdev->config.si.max_backends_per_se = 4; ++ rdev->config.si.max_texture_channel_caches = 4; ++ rdev->config.si.max_gprs = 256; ++ rdev->config.si.max_gs_threads = 32; ++ rdev->config.si.max_hw_contexts = 8; ++ ++ rdev->config.si.sc_prim_fifo_size_frontend = 0x20; ++ rdev->config.si.sc_prim_fifo_size_backend = 0x40; ++ rdev->config.si.sc_hiz_tile_fifo_size = 0x30; ++ rdev->config.si.sc_earlyz_tile_fifo_size = 0x130; ++ break; ++ } ++ ++ /* Initialize HDP */ ++ for (i = 0, j = 0; i < 32; i++, j += 0x18) { ++ WREG32((0x2c14 + j), 0x00000000); ++ WREG32((0x2c18 + j), 0x00000000); ++ WREG32((0x2c1c + j), 0x00000000); ++ WREG32((0x2c20 + j), 0x00000000); ++ WREG32((0x2c24 + j), 0x00000000); ++ } ++ ++ WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); ++ ++ evergreen_fix_pci_max_read_req_size(rdev); ++ ++ WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); ++ ++ mc_shared_chmap = RREG32(MC_SHARED_CHMAP); ++ mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); ++ ++ cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE); ++ cc_gc_shader_array_config = RREG32(CC_GC_SHADER_ARRAY_CONFIG); ++ cgts_tcc_disable = 0xffff0000; ++ for (i = 0; i < rdev->config.si.max_texture_channel_caches; i++) ++ cgts_tcc_disable &= ~(1 << (16 + i)); ++ gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE); ++ gc_user_shader_array_config = RREG32(GC_USER_SHADER_ARRAY_CONFIG); ++ cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE); ++ ++ rdev->config.si.num_shader_engines = rdev->config.si.max_shader_engines; ++ rdev->config.si.num_tile_pipes = rdev->config.si.max_tile_pipes; ++ tmp = ((~gc_user_rb_backend_disable) & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; ++ rdev->config.si.num_backends_per_se = r600_count_pipe_bits(tmp); ++ tmp = (gc_user_rb_backend_disable & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; ++ rdev->config.si.backend_disable_mask_per_asic = ++ si_get_disable_mask_per_asic(rdev, tmp, SI_MAX_BACKENDS_PER_SE_MASK, ++ rdev->config.si.num_shader_engines); ++ rdev->config.si.backend_map = ++ si_get_tile_pipe_to_backend_map(rdev, rdev->config.si.num_tile_pipes, ++ rdev->config.si.num_backends_per_se * ++ rdev->config.si.num_shader_engines, ++ &rdev->config.si.backend_disable_mask_per_asic, ++ rdev->config.si.num_shader_engines); ++ tmp = ((~cgts_user_tcc_disable) & TCC_DISABLE_MASK) >> TCC_DISABLE_SHIFT; ++ rdev->config.si.num_texture_channel_caches = r600_count_pipe_bits(tmp); ++ rdev->config.si.mem_max_burst_length_bytes = 256; ++ tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT; ++ rdev->config.si.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024; ++ if (rdev->config.si.mem_row_size_in_kb > 4) ++ rdev->config.si.mem_row_size_in_kb = 4; ++ /* XXX use MC settings? */ ++ rdev->config.si.shader_engine_tile_size = 32; ++ rdev->config.si.num_gpus = 1; ++ rdev->config.si.multi_gpu_tile_size = 64; ++ ++ gb_addr_config = 0; ++ switch (rdev->config.si.num_tile_pipes) { ++ case 1: ++ gb_addr_config |= NUM_PIPES(0); ++ break; ++ case 2: ++ gb_addr_config |= NUM_PIPES(1); ++ break; ++ case 4: ++ gb_addr_config |= NUM_PIPES(2); ++ break; ++ case 8: ++ default: ++ gb_addr_config |= NUM_PIPES(3); ++ break; ++ } ++ ++ tmp = (rdev->config.si.mem_max_burst_length_bytes / 256) - 1; ++ gb_addr_config |= PIPE_INTERLEAVE_SIZE(tmp); ++ gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.si.num_shader_engines - 1); ++ tmp = (rdev->config.si.shader_engine_tile_size / 16) - 1; ++ gb_addr_config |= SHADER_ENGINE_TILE_SIZE(tmp); ++ switch (rdev->config.si.num_gpus) { ++ case 1: ++ default: ++ gb_addr_config |= NUM_GPUS(0); ++ break; ++ case 2: ++ gb_addr_config |= NUM_GPUS(1); ++ break; ++ case 4: ++ gb_addr_config |= NUM_GPUS(2); ++ break; ++ } ++ switch (rdev->config.si.multi_gpu_tile_size) { ++ case 16: ++ gb_addr_config |= MULTI_GPU_TILE_SIZE(0); ++ break; ++ case 32: ++ default: ++ gb_addr_config |= MULTI_GPU_TILE_SIZE(1); ++ break; ++ case 64: ++ gb_addr_config |= MULTI_GPU_TILE_SIZE(2); ++ break; ++ case 128: ++ gb_addr_config |= MULTI_GPU_TILE_SIZE(3); ++ break; ++ } ++ switch (rdev->config.si.mem_row_size_in_kb) { ++ case 1: ++ default: ++ gb_addr_config |= ROW_SIZE(0); ++ break; ++ case 2: ++ gb_addr_config |= ROW_SIZE(1); ++ break; ++ case 4: ++ gb_addr_config |= ROW_SIZE(2); ++ break; ++ } ++ ++ tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT; ++ rdev->config.si.num_tile_pipes = (1 << tmp); ++ tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; ++ rdev->config.si.mem_max_burst_length_bytes = (tmp + 1) * 256; ++ tmp = (gb_addr_config & NUM_SHADER_ENGINES_MASK) >> NUM_SHADER_ENGINES_SHIFT; ++ rdev->config.si.num_shader_engines = tmp + 1; ++ tmp = (gb_addr_config & NUM_GPUS_MASK) >> NUM_GPUS_SHIFT; ++ rdev->config.si.num_gpus = tmp + 1; ++ tmp = (gb_addr_config & MULTI_GPU_TILE_SIZE_MASK) >> MULTI_GPU_TILE_SIZE_SHIFT; ++ rdev->config.si.multi_gpu_tile_size = 1 << tmp; ++ tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT; ++ rdev->config.si.mem_row_size_in_kb = 1 << tmp; ++ ++ gb_backend_map = ++ si_get_tile_pipe_to_backend_map(rdev, rdev->config.si.num_tile_pipes, ++ rdev->config.si.num_backends_per_se * ++ rdev->config.si.num_shader_engines, ++ &rdev->config.si.backend_disable_mask_per_asic, ++ rdev->config.si.num_shader_engines); ++ ++ /* setup tiling info dword. gb_addr_config is not adequate since it does ++ * not have bank info, so create a custom tiling dword. ++ * bits 3:0 num_pipes ++ * bits 7:4 num_banks ++ * bits 11:8 group_size ++ * bits 15:12 row_size ++ */ ++ rdev->config.si.tile_config = 0; ++ switch (rdev->config.si.num_tile_pipes) { ++ case 1: ++ rdev->config.si.tile_config |= (0 << 0); ++ break; ++ case 2: ++ rdev->config.si.tile_config |= (1 << 0); ++ break; ++ case 4: ++ rdev->config.si.tile_config |= (2 << 0); ++ break; ++ case 8: ++ default: ++ /* XXX what about 12? */ ++ rdev->config.si.tile_config |= (3 << 0); ++ break; ++ } ++ rdev->config.si.tile_config |= ++ ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; ++ rdev->config.si.tile_config |= ++ ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; ++ rdev->config.si.tile_config |= ++ ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; ++ ++ rdev->config.si.backend_map = gb_backend_map; ++ WREG32(GB_ADDR_CONFIG, gb_addr_config); ++ WREG32(DMIF_ADDR_CONFIG, gb_addr_config); ++ WREG32(DMIF_ADDR_CALC, gb_addr_config); ++ WREG32(HDP_ADDR_CONFIG, gb_addr_config); ++ ++ /* primary versions */ ++ WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); ++ WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); ++ WREG32(CC_GC_SHADER_ARRAY_CONFIG, cc_gc_shader_array_config); ++ ++ WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable); ++ ++ /* user versions */ ++ WREG32(GC_USER_RB_BACKEND_DISABLE, cc_rb_backend_disable); ++ WREG32(GC_USER_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); ++ WREG32(GC_USER_SHADER_ARRAY_CONFIG, cc_gc_shader_array_config); ++ ++ WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable); ++ ++ si_tiling_mode_table_init(rdev); ++ ++ /* set HW defaults for 3D engine */ ++ WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) | ++ ROQ_IB2_START(0x2b))); ++ WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60)); ++ ++ sx_debug_1 = RREG32(SX_DEBUG_1); ++ WREG32(SX_DEBUG_1, sx_debug_1); ++ ++ WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4)); ++ ++ WREG32(PA_SC_FIFO_SIZE, (SC_FRONTEND_PRIM_FIFO_SIZE(rdev->config.si.sc_prim_fifo_size_frontend) | ++ SC_BACKEND_PRIM_FIFO_SIZE(rdev->config.si.sc_prim_fifo_size_backend) | ++ SC_HIZ_TILE_FIFO_SIZE(rdev->config.si.sc_hiz_tile_fifo_size) | ++ SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.si.sc_earlyz_tile_fifo_size))); ++ ++ WREG32(VGT_NUM_INSTANCES, 1); ++ ++ WREG32(CP_PERFMON_CNTL, 0); ++ ++ WREG32(SQ_CONFIG, 0); ++ ++ WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | ++ FORCE_EOV_MAX_REZ_CNT(255))); ++ ++ WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) | ++ AUTO_INVLD_EN(ES_AND_GS_AUTO)); ++ ++ WREG32(VGT_GS_VERTEX_REUSE, 16); ++ WREG32(PA_SC_LINE_STIPPLE_STATE, 0); ++ ++ WREG32(CB_PERFCOUNTER0_SELECT0, 0); ++ WREG32(CB_PERFCOUNTER0_SELECT1, 0); ++ WREG32(CB_PERFCOUNTER1_SELECT0, 0); ++ WREG32(CB_PERFCOUNTER1_SELECT1, 0); ++ WREG32(CB_PERFCOUNTER2_SELECT0, 0); ++ WREG32(CB_PERFCOUNTER2_SELECT1, 0); ++ WREG32(CB_PERFCOUNTER3_SELECT0, 0); ++ WREG32(CB_PERFCOUNTER3_SELECT1, 0); ++ ++ tmp = RREG32(HDP_MISC_CNTL); ++ tmp |= HDP_FLUSH_INVALIDATE_CACHE; ++ WREG32(HDP_MISC_CNTL, tmp); ++ ++ hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); ++ WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); ++ ++ WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3)); ++ ++ udelay(50); ++} ++ ++/* ++ * GPU scratch registers helpers function. ++ */ ++static void si_scratch_init(struct radeon_device *rdev) ++{ ++ int i; ++ ++ rdev->scratch.num_reg = 7; ++ rdev->scratch.reg_base = SCRATCH_REG0; ++ for (i = 0; i < rdev->scratch.num_reg; i++) { ++ rdev->scratch.free[i] = true; ++ rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4); ++ } ++} ++ ++void si_fence_ring_emit(struct radeon_device *rdev, ++ struct radeon_fence *fence) ++{ ++ struct radeon_ring *ring = &rdev->ring[fence->ring]; ++ u64 addr = rdev->fence_drv[fence->ring].gpu_addr; ++ ++ /* flush read cache over gart */ ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); ++ radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA | ++ PACKET3_TC_ACTION_ENA | ++ PACKET3_SH_KCACHE_ACTION_ENA | ++ PACKET3_SH_ICACHE_ACTION_ENA); ++ radeon_ring_write(ring, 0xFFFFFFFF); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 10); /* poll interval */ ++ /* EVENT_WRITE_EOP - flush caches, send int */ ++ radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); ++ radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5)); ++ radeon_ring_write(ring, addr & 0xffffffff); ++ radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); ++ radeon_ring_write(ring, fence->seq); ++ radeon_ring_write(ring, 0); ++} ++ ++/* ++ * IB stuff ++ */ ++void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) ++{ ++ struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; ++ u32 header; ++ ++ if (ib->is_const_ib) ++ header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2); ++ else ++ header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); ++ ++ radeon_ring_write(ring, header); ++ radeon_ring_write(ring, ++#ifdef __BIG_ENDIAN ++ (2 << 0) | ++#endif ++ (ib->gpu_addr & 0xFFFFFFFC)); ++ radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); ++ radeon_ring_write(ring, ib->length_dw | (ib->vm_id << 24)); ++ ++ /* flush read cache over gart for this vmid */ ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); ++ radeon_ring_write(ring, ib->vm_id); ++ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); ++ radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA | ++ PACKET3_TC_ACTION_ENA | ++ PACKET3_SH_KCACHE_ACTION_ENA | ++ PACKET3_SH_ICACHE_ACTION_ENA); ++ radeon_ring_write(ring, 0xFFFFFFFF); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 10); /* poll interval */ ++} ++ ++/* ++ * CP. ++ */ ++static void si_cp_enable(struct radeon_device *rdev, bool enable) ++{ ++ if (enable) ++ WREG32(CP_ME_CNTL, 0); ++ else { ++ radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); ++ WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT)); ++ WREG32(SCRATCH_UMSK, 0); ++ } ++ udelay(50); ++} ++ ++static int si_cp_load_microcode(struct radeon_device *rdev) ++{ ++ const __be32 *fw_data; ++ int i; ++ ++ if (!rdev->me_fw || !rdev->pfp_fw) ++ return -EINVAL; ++ ++ si_cp_enable(rdev, false); ++ ++ /* PFP */ ++ fw_data = (const __be32 *)rdev->pfp_fw->data; ++ WREG32(CP_PFP_UCODE_ADDR, 0); ++ for (i = 0; i < SI_PFP_UCODE_SIZE; i++) ++ WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); ++ WREG32(CP_PFP_UCODE_ADDR, 0); ++ ++ /* CE */ ++ fw_data = (const __be32 *)rdev->ce_fw->data; ++ WREG32(CP_CE_UCODE_ADDR, 0); ++ for (i = 0; i < SI_CE_UCODE_SIZE; i++) ++ WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++)); ++ WREG32(CP_CE_UCODE_ADDR, 0); ++ ++ /* ME */ ++ fw_data = (const __be32 *)rdev->me_fw->data; ++ WREG32(CP_ME_RAM_WADDR, 0); ++ for (i = 0; i < SI_PM4_UCODE_SIZE; i++) ++ WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); ++ WREG32(CP_ME_RAM_WADDR, 0); ++ ++ WREG32(CP_PFP_UCODE_ADDR, 0); ++ WREG32(CP_CE_UCODE_ADDR, 0); ++ WREG32(CP_ME_RAM_WADDR, 0); ++ WREG32(CP_ME_RAM_RADDR, 0); ++ return 0; ++} ++ ++static int si_cp_start(struct radeon_device *rdev) ++{ ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ int r, i; ++ ++ r = radeon_ring_lock(rdev, ring, 7 + 4); ++ if (r) { ++ DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); ++ return r; ++ } ++ /* init the CP */ ++ radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); ++ radeon_ring_write(ring, 0x1); ++ radeon_ring_write(ring, 0x0); ++ radeon_ring_write(ring, rdev->config.si.max_hw_contexts - 1); ++ radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); ++ ++ /* init the CE partitions */ ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_BASE, 2)); ++ radeon_ring_write(ring, PACKET3_BASE_INDEX(CE_PARTITION_BASE)); ++ radeon_ring_write(ring, 0xc000); ++ radeon_ring_write(ring, 0xe000); ++ radeon_ring_unlock_commit(rdev, ring); ++ ++ si_cp_enable(rdev, true); ++ ++ r = radeon_ring_lock(rdev, ring, si_default_size + 10); ++ if (r) { ++ DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); ++ return r; ++ } ++ ++ /* setup clear context state */ ++ radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); ++ radeon_ring_write(ring, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); ++ ++ for (i = 0; i < si_default_size; i++) ++ radeon_ring_write(ring, si_default_state[i]); ++ ++ radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); ++ radeon_ring_write(ring, PACKET3_PREAMBLE_END_CLEAR_STATE); ++ ++ /* set clear context state */ ++ radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0)); ++ radeon_ring_write(ring, 0); ++ ++ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); ++ radeon_ring_write(ring, 0x00000316); ++ radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ ++ radeon_ring_write(ring, 0x00000010); /* VGT_OUT_DEALLOC_CNTL */ ++ ++ radeon_ring_unlock_commit(rdev, ring); ++ ++ for (i = RADEON_RING_TYPE_GFX_INDEX; i <= CAYMAN_RING_TYPE_CP2_INDEX; ++i) { ++ ring = &rdev->ring[i]; ++ r = radeon_ring_lock(rdev, ring, 2); ++ ++ /* clear the compute context state */ ++ radeon_ring_write(ring, PACKET3_COMPUTE(PACKET3_CLEAR_STATE, 0)); ++ radeon_ring_write(ring, 0); ++ ++ radeon_ring_unlock_commit(rdev, ring); ++ } ++ ++ return 0; ++} ++ ++static void si_cp_fini(struct radeon_device *rdev) ++{ ++ si_cp_enable(rdev, false); ++ radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); ++ radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); ++ radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); ++} ++ ++static int si_cp_resume(struct radeon_device *rdev) ++{ ++ struct radeon_ring *ring; ++ u32 tmp; ++ u32 rb_bufsz; ++ int r; ++ ++ /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ ++ WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | ++ SOFT_RESET_PA | ++ SOFT_RESET_VGT | ++ SOFT_RESET_SPI | ++ SOFT_RESET_SX)); ++ RREG32(GRBM_SOFT_RESET); ++ mdelay(15); ++ WREG32(GRBM_SOFT_RESET, 0); ++ RREG32(GRBM_SOFT_RESET); ++ ++ WREG32(CP_SEM_WAIT_TIMER, 0x0); ++ WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); ++ ++ /* Set the write pointer delay */ ++ WREG32(CP_RB_WPTR_DELAY, 0); ++ ++ WREG32(CP_DEBUG, 0); ++ WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); ++ ++ /* ring 0 - compute and gfx */ ++ /* Set ring buffer size */ ++ ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ rb_bufsz = drm_order(ring->ring_size / 8); ++ tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; ++#ifdef __BIG_ENDIAN ++ tmp |= BUF_SWAP_32BIT; ++#endif ++ WREG32(CP_RB0_CNTL, tmp); ++ ++ /* Initialize the ring buffer's read and write pointers */ ++ WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA); ++ ring->wptr = 0; ++ WREG32(CP_RB0_WPTR, ring->wptr); ++ ++ /* set the wb address wether it's enabled or not */ ++ WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC); ++ WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); ++ ++ if (rdev->wb.enabled) ++ WREG32(SCRATCH_UMSK, 0xff); ++ else { ++ tmp |= RB_NO_UPDATE; ++ WREG32(SCRATCH_UMSK, 0); ++ } ++ ++ mdelay(1); ++ WREG32(CP_RB0_CNTL, tmp); ++ ++ WREG32(CP_RB0_BASE, ring->gpu_addr >> 8); ++ ++ ring->rptr = RREG32(CP_RB0_RPTR); ++ ++ /* ring1 - compute only */ ++ /* Set ring buffer size */ ++ ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; ++ rb_bufsz = drm_order(ring->ring_size / 8); ++ tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; ++#ifdef __BIG_ENDIAN ++ tmp |= BUF_SWAP_32BIT; ++#endif ++ WREG32(CP_RB1_CNTL, tmp); ++ ++ /* Initialize the ring buffer's read and write pointers */ ++ WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA); ++ ring->wptr = 0; ++ WREG32(CP_RB1_WPTR, ring->wptr); ++ ++ /* set the wb address wether it's enabled or not */ ++ WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC); ++ WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF); ++ ++ mdelay(1); ++ WREG32(CP_RB1_CNTL, tmp); ++ ++ WREG32(CP_RB1_BASE, ring->gpu_addr >> 8); ++ ++ ring->rptr = RREG32(CP_RB1_RPTR); ++ ++ /* ring2 - compute only */ ++ /* Set ring buffer size */ ++ ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; ++ rb_bufsz = drm_order(ring->ring_size / 8); ++ tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; ++#ifdef __BIG_ENDIAN ++ tmp |= BUF_SWAP_32BIT; ++#endif ++ WREG32(CP_RB2_CNTL, tmp); ++ ++ /* Initialize the ring buffer's read and write pointers */ ++ WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA); ++ ring->wptr = 0; ++ WREG32(CP_RB2_WPTR, ring->wptr); ++ ++ /* set the wb address wether it's enabled or not */ ++ WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC); ++ WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF); ++ ++ mdelay(1); ++ WREG32(CP_RB2_CNTL, tmp); ++ ++ WREG32(CP_RB2_BASE, ring->gpu_addr >> 8); ++ ++ ring->rptr = RREG32(CP_RB2_RPTR); ++ ++ /* start the rings */ ++ si_cp_start(rdev); ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true; ++ rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = true; ++ rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = true; ++ r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); ++ if (r) { ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; ++ rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; ++ rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; ++ return r; ++ } ++ r = radeon_ring_test(rdev, CAYMAN_RING_TYPE_CP1_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); ++ if (r) { ++ rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; ++ } ++ r = radeon_ring_test(rdev, CAYMAN_RING_TYPE_CP2_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); ++ if (r) { ++ rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; ++ } ++ ++ return 0; ++} ++ ++bool si_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) ++{ ++ u32 srbm_status; ++ u32 grbm_status, grbm_status2; ++ u32 grbm_status_se0, grbm_status_se1; ++ struct r100_gpu_lockup *lockup = &rdev->config.si.lockup; ++ int r; ++ ++ srbm_status = RREG32(SRBM_STATUS); ++ grbm_status = RREG32(GRBM_STATUS); ++ grbm_status2 = RREG32(GRBM_STATUS2); ++ grbm_status_se0 = RREG32(GRBM_STATUS_SE0); ++ grbm_status_se1 = RREG32(GRBM_STATUS_SE1); ++ if (!(grbm_status & GUI_ACTIVE)) { ++ r100_gpu_lockup_update(lockup, ring); ++ return false; ++ } ++ /* force CP activities */ ++ r = radeon_ring_lock(rdev, ring, 2); ++ if (!r) { ++ /* PACKET2 NOP */ ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_write(ring, 0x80000000); ++ radeon_ring_unlock_commit(rdev, ring); ++ } ++ /* XXX deal with CP0,1,2 */ ++ ring->rptr = RREG32(ring->rptr_reg); ++ return r100_gpu_cp_is_lockup(rdev, lockup, ring); ++} ++ ++static int si_gpu_soft_reset(struct radeon_device *rdev) ++{ ++ struct evergreen_mc_save save; ++ u32 grbm_reset = 0; ++ ++ if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) ++ return 0; ++ ++ dev_info(rdev->dev, "GPU softreset \n"); ++ dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", ++ RREG32(GRBM_STATUS)); ++ dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n", ++ RREG32(GRBM_STATUS2)); ++ dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", ++ RREG32(GRBM_STATUS_SE0)); ++ dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", ++ RREG32(GRBM_STATUS_SE1)); ++ dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", ++ RREG32(SRBM_STATUS)); ++ evergreen_mc_stop(rdev, &save); ++ if (radeon_mc_wait_for_idle(rdev)) { ++ dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); ++ } ++ /* Disable CP parsing/prefetching */ ++ WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT); ++ ++ /* reset all the gfx blocks */ ++ grbm_reset = (SOFT_RESET_CP | ++ SOFT_RESET_CB | ++ SOFT_RESET_DB | ++ SOFT_RESET_GDS | ++ SOFT_RESET_PA | ++ SOFT_RESET_SC | ++ SOFT_RESET_SPI | ++ SOFT_RESET_SX | ++ SOFT_RESET_TC | ++ SOFT_RESET_TA | ++ SOFT_RESET_VGT | ++ SOFT_RESET_IA); ++ ++ dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); ++ WREG32(GRBM_SOFT_RESET, grbm_reset); ++ (void)RREG32(GRBM_SOFT_RESET); ++ udelay(50); ++ WREG32(GRBM_SOFT_RESET, 0); ++ (void)RREG32(GRBM_SOFT_RESET); ++ /* Wait a little for things to settle down */ ++ udelay(50); ++ dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", ++ RREG32(GRBM_STATUS)); ++ dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n", ++ RREG32(GRBM_STATUS2)); ++ dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", ++ RREG32(GRBM_STATUS_SE0)); ++ dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", ++ RREG32(GRBM_STATUS_SE1)); ++ dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", ++ RREG32(SRBM_STATUS)); ++ evergreen_mc_resume(rdev, &save); ++ return 0; ++} ++ ++int si_asic_reset(struct radeon_device *rdev) ++{ ++ return si_gpu_soft_reset(rdev); ++} ++ ++/* MC */ ++static void si_mc_program(struct radeon_device *rdev) ++{ ++ struct evergreen_mc_save save; ++ u32 tmp; ++ int i, j; ++ ++ /* Initialize HDP */ ++ for (i = 0, j = 0; i < 32; i++, j += 0x18) { ++ WREG32((0x2c14 + j), 0x00000000); ++ WREG32((0x2c18 + j), 0x00000000); ++ WREG32((0x2c1c + j), 0x00000000); ++ WREG32((0x2c20 + j), 0x00000000); ++ WREG32((0x2c24 + j), 0x00000000); ++ } ++ WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0); ++ ++ evergreen_mc_stop(rdev, &save); ++ if (radeon_mc_wait_for_idle(rdev)) { ++ dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); ++ } ++ /* Lockout access through VGA aperture*/ ++ WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); ++ /* Update configuration */ ++ WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, ++ rdev->mc.vram_start >> 12); ++ WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, ++ rdev->mc.vram_end >> 12); ++ WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, ++ rdev->vram_scratch.gpu_addr >> 12); ++ tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; ++ tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); ++ WREG32(MC_VM_FB_LOCATION, tmp); ++ /* XXX double check these! */ ++ WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); ++ WREG32(HDP_NONSURFACE_INFO, (2 << 7) | (1 << 30)); ++ WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); ++ WREG32(MC_VM_AGP_BASE, 0); ++ WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF); ++ WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF); ++ if (radeon_mc_wait_for_idle(rdev)) { ++ dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); ++ } ++ evergreen_mc_resume(rdev, &save); ++ /* we need to own VRAM, so turn off the VGA renderer here ++ * to stop it overwriting our objects */ ++ rv515_vga_render_disable(rdev); ++} ++ ++/* SI MC address space is 40 bits */ ++static void si_vram_location(struct radeon_device *rdev, ++ struct radeon_mc *mc, u64 base) ++{ ++ mc->vram_start = base; ++ if (mc->mc_vram_size > (0xFFFFFFFFFFULL - base + 1)) { ++ dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); ++ mc->real_vram_size = mc->aper_size; ++ mc->mc_vram_size = mc->aper_size; ++ } ++ mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; ++ dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n", ++ mc->mc_vram_size >> 20, mc->vram_start, ++ mc->vram_end, mc->real_vram_size >> 20); ++} ++ ++static void si_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) ++{ ++ u64 size_af, size_bf; ++ ++ size_af = ((0xFFFFFFFFFFULL - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align; ++ size_bf = mc->vram_start & ~mc->gtt_base_align; ++ if (size_bf > size_af) { ++ if (mc->gtt_size > size_bf) { ++ dev_warn(rdev->dev, "limiting GTT\n"); ++ mc->gtt_size = size_bf; ++ } ++ mc->gtt_start = (mc->vram_start & ~mc->gtt_base_align) - mc->gtt_size; ++ } else { ++ if (mc->gtt_size > size_af) { ++ dev_warn(rdev->dev, "limiting GTT\n"); ++ mc->gtt_size = size_af; ++ } ++ mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align; ++ } ++ mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; ++ dev_info(rdev->dev, "GTT: %lluM 0x%016llX - 0x%016llX\n", ++ mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end); ++} ++ ++static void si_vram_gtt_location(struct radeon_device *rdev, ++ struct radeon_mc *mc) ++{ ++ if (mc->mc_vram_size > 0xFFC0000000ULL) { ++ /* leave room for at least 1024M GTT */ ++ dev_warn(rdev->dev, "limiting VRAM\n"); ++ mc->real_vram_size = 0xFFC0000000ULL; ++ mc->mc_vram_size = 0xFFC0000000ULL; ++ } ++ si_vram_location(rdev, &rdev->mc, 0); ++ rdev->mc.gtt_base_align = 0; ++ si_gtt_location(rdev, mc); ++} ++ ++static int si_mc_init(struct radeon_device *rdev) ++{ ++ u32 tmp; ++ int chansize, numchan; ++ ++ /* Get VRAM informations */ ++ rdev->mc.vram_is_ddr = true; ++ tmp = RREG32(MC_ARB_RAMCFG); ++ if (tmp & CHANSIZE_OVERRIDE) { ++ chansize = 16; ++ } else if (tmp & CHANSIZE_MASK) { ++ chansize = 64; ++ } else { ++ chansize = 32; ++ } ++ tmp = RREG32(MC_SHARED_CHMAP); ++ switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { ++ case 0: ++ default: ++ numchan = 1; ++ break; ++ case 1: ++ numchan = 2; ++ break; ++ case 2: ++ numchan = 4; ++ break; ++ case 3: ++ numchan = 8; ++ break; ++ case 4: ++ numchan = 3; ++ break; ++ case 5: ++ numchan = 6; ++ break; ++ case 6: ++ numchan = 10; ++ break; ++ case 7: ++ numchan = 12; ++ break; ++ case 8: ++ numchan = 16; ++ break; ++ } ++ rdev->mc.vram_width = numchan * chansize; ++ /* Could aper size report 0 ? */ ++ rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); ++ rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); ++ /* size in MB on si */ ++ tmp = RREG32(CONFIG_MEMSIZE); ++ /* some boards may have garbage in the upper 16 bits */ ++ if (tmp & 0xffff0000) { ++ DRM_INFO("Probable bad vram size: 0x%08x\n", tmp); ++ if (tmp & 0xffff) ++ tmp &= 0xffff; ++ } ++ rdev->mc.mc_vram_size = tmp * 1024ULL * 1024ULL; ++ rdev->mc.real_vram_size = rdev->mc.mc_vram_size; ++ rdev->mc.visible_vram_size = rdev->mc.aper_size; ++ si_vram_gtt_location(rdev, &rdev->mc); ++ radeon_update_bandwidth_info(rdev); ++ ++ return 0; ++} ++ ++/* ++ * GART ++ */ ++void si_pcie_gart_tlb_flush(struct radeon_device *rdev) ++{ ++ /* flush hdp cache */ ++ WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); ++ ++ /* bits 0-15 are the VM contexts0-15 */ ++ WREG32(VM_INVALIDATE_REQUEST, 1); ++} ++ ++int si_pcie_gart_enable(struct radeon_device *rdev) ++{ ++ int r, i; ++ ++ if (rdev->gart.robj == NULL) { ++ dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); ++ return -EINVAL; ++ } ++ r = radeon_gart_table_vram_pin(rdev); ++ if (r) ++ return r; ++ radeon_gart_restore(rdev); ++ /* Setup TLB control */ ++ WREG32(MC_VM_MX_L1_TLB_CNTL, ++ (0xA << 7) | ++ ENABLE_L1_TLB | ++ SYSTEM_ACCESS_MODE_NOT_IN_SYS | ++ ENABLE_ADVANCED_DRIVER_MODEL | ++ SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); ++ /* Setup L2 cache */ ++ WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ++ ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | ++ ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | ++ EFFECTIVE_L2_QUEUE_SIZE(7) | ++ CONTEXT1_IDENTITY_ACCESS_MODE(1)); ++ WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE); ++ WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | ++ L2_CACHE_BIGK_FRAGMENT_SIZE(0)); ++ /* setup context0 */ ++ WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); ++ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); ++ WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); ++ WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, ++ (u32)(rdev->dummy_page.addr >> 12)); ++ WREG32(VM_CONTEXT0_CNTL2, 0); ++ WREG32(VM_CONTEXT0_CNTL, (ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | ++ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT)); ++ ++ WREG32(0x15D4, 0); ++ WREG32(0x15D8, 0); ++ WREG32(0x15DC, 0); ++ ++ /* empty context1-15 */ ++ /* FIXME start with 4G, once using 2 level pt switch to full ++ * vm size space ++ */ ++ /* set vm size, must be a multiple of 4 */ ++ WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); ++ WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn); ++ for (i = 1; i < 16; i++) { ++ if (i < 8) ++ WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), ++ rdev->gart.table_addr >> 12); ++ else ++ WREG32(VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i - 8) << 2), ++ rdev->gart.table_addr >> 12); ++ } ++ ++ /* enable context1-15 */ ++ WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, ++ (u32)(rdev->dummy_page.addr >> 12)); ++ WREG32(VM_CONTEXT1_CNTL2, 0); ++ WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | ++ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); ++ ++ si_pcie_gart_tlb_flush(rdev); ++ DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", ++ (unsigned)(rdev->mc.gtt_size >> 20), ++ (unsigned long long)rdev->gart.table_addr); ++ rdev->gart.ready = true; ++ return 0; ++} ++ ++void si_pcie_gart_disable(struct radeon_device *rdev) ++{ ++ /* Disable all tables */ ++ WREG32(VM_CONTEXT0_CNTL, 0); ++ WREG32(VM_CONTEXT1_CNTL, 0); ++ /* Setup TLB control */ ++ WREG32(MC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE_NOT_IN_SYS | ++ SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); ++ /* Setup L2 cache */ ++ WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | ++ ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | ++ EFFECTIVE_L2_QUEUE_SIZE(7) | ++ CONTEXT1_IDENTITY_ACCESS_MODE(1)); ++ WREG32(VM_L2_CNTL2, 0); ++ WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | ++ L2_CACHE_BIGK_FRAGMENT_SIZE(0)); ++ radeon_gart_table_vram_unpin(rdev); ++} ++ ++void si_pcie_gart_fini(struct radeon_device *rdev) ++{ ++ si_pcie_gart_disable(rdev); ++ radeon_gart_table_vram_free(rdev); ++ radeon_gart_fini(rdev); ++} ++ ++/* vm parser */ ++static bool si_vm_reg_valid(u32 reg) ++{ ++ /* context regs are fine */ ++ if (reg >= 0x28000) ++ return true; ++ ++ /* check config regs */ ++ switch (reg) { ++ case GRBM_GFX_INDEX: ++ case CP_STRMOUT_CNTL: ++ case VGT_VTX_VECT_EJECT_REG: ++ case VGT_CACHE_INVALIDATION: ++ case VGT_ESGS_RING_SIZE: ++ case VGT_GSVS_RING_SIZE: ++ case VGT_GS_VERTEX_REUSE: ++ case VGT_PRIMITIVE_TYPE: ++ case VGT_INDEX_TYPE: ++ case VGT_NUM_INDICES: ++ case VGT_NUM_INSTANCES: ++ case VGT_TF_RING_SIZE: ++ case VGT_HS_OFFCHIP_PARAM: ++ case VGT_TF_MEMORY_BASE: ++ case PA_CL_ENHANCE: ++ case PA_SU_LINE_STIPPLE_VALUE: ++ case PA_SC_LINE_STIPPLE_STATE: ++ case PA_SC_ENHANCE: ++ case SQC_CACHES: ++ case SPI_STATIC_THREAD_MGMT_1: ++ case SPI_STATIC_THREAD_MGMT_2: ++ case SPI_STATIC_THREAD_MGMT_3: ++ case SPI_PS_MAX_WAVE_ID: ++ case SPI_CONFIG_CNTL: ++ case SPI_CONFIG_CNTL_1: ++ case TA_CNTL_AUX: ++ return true; ++ default: ++ DRM_ERROR("Invalid register 0x%x in CS\n", reg); ++ return false; ++ } ++} ++ ++static int si_vm_packet3_ce_check(struct radeon_device *rdev, ++ u32 *ib, struct radeon_cs_packet *pkt) ++{ ++ switch (pkt->opcode) { ++ case PACKET3_NOP: ++ case PACKET3_SET_BASE: ++ case PACKET3_SET_CE_DE_COUNTERS: ++ case PACKET3_LOAD_CONST_RAM: ++ case PACKET3_WRITE_CONST_RAM: ++ case PACKET3_WRITE_CONST_RAM_OFFSET: ++ case PACKET3_DUMP_CONST_RAM: ++ case PACKET3_INCREMENT_CE_COUNTER: ++ case PACKET3_WAIT_ON_DE_COUNTER: ++ case PACKET3_CE_WRITE: ++ break; ++ default: ++ DRM_ERROR("Invalid CE packet3: 0x%x\n", pkt->opcode); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int si_vm_packet3_gfx_check(struct radeon_device *rdev, ++ u32 *ib, struct radeon_cs_packet *pkt) ++{ ++ u32 idx = pkt->idx + 1; ++ u32 idx_value = ib[idx]; ++ u32 start_reg, end_reg, reg, i; ++ ++ switch (pkt->opcode) { ++ case PACKET3_NOP: ++ case PACKET3_SET_BASE: ++ case PACKET3_CLEAR_STATE: ++ case PACKET3_INDEX_BUFFER_SIZE: ++ case PACKET3_DISPATCH_DIRECT: ++ case PACKET3_DISPATCH_INDIRECT: ++ case PACKET3_ALLOC_GDS: ++ case PACKET3_WRITE_GDS_RAM: ++ case PACKET3_ATOMIC_GDS: ++ case PACKET3_ATOMIC: ++ case PACKET3_OCCLUSION_QUERY: ++ case PACKET3_SET_PREDICATION: ++ case PACKET3_COND_EXEC: ++ case PACKET3_PRED_EXEC: ++ case PACKET3_DRAW_INDIRECT: ++ case PACKET3_DRAW_INDEX_INDIRECT: ++ case PACKET3_INDEX_BASE: ++ case PACKET3_DRAW_INDEX_2: ++ case PACKET3_CONTEXT_CONTROL: ++ case PACKET3_INDEX_TYPE: ++ case PACKET3_DRAW_INDIRECT_MULTI: ++ case PACKET3_DRAW_INDEX_AUTO: ++ case PACKET3_DRAW_INDEX_IMMD: ++ case PACKET3_NUM_INSTANCES: ++ case PACKET3_DRAW_INDEX_MULTI_AUTO: ++ case PACKET3_STRMOUT_BUFFER_UPDATE: ++ case PACKET3_DRAW_INDEX_OFFSET_2: ++ case PACKET3_DRAW_INDEX_MULTI_ELEMENT: ++ case PACKET3_DRAW_INDEX_INDIRECT_MULTI: ++ case PACKET3_MPEG_INDEX: ++ case PACKET3_WAIT_REG_MEM: ++ case PACKET3_MEM_WRITE: ++ case PACKET3_PFP_SYNC_ME: ++ case PACKET3_SURFACE_SYNC: ++ case PACKET3_EVENT_WRITE: ++ case PACKET3_EVENT_WRITE_EOP: ++ case PACKET3_EVENT_WRITE_EOS: ++ case PACKET3_SET_CONTEXT_REG: ++ case PACKET3_SET_CONTEXT_REG_INDIRECT: ++ case PACKET3_SET_SH_REG: ++ case PACKET3_SET_SH_REG_OFFSET: ++ case PACKET3_INCREMENT_DE_COUNTER: ++ case PACKET3_WAIT_ON_CE_COUNTER: ++ case PACKET3_WAIT_ON_AVAIL_BUFFER: ++ case PACKET3_ME_WRITE: ++ break; ++ case PACKET3_COPY_DATA: ++ if ((idx_value & 0xf00) == 0) { ++ reg = ib[idx + 3] * 4; ++ if (!si_vm_reg_valid(reg)) ++ return -EINVAL; ++ } ++ break; ++ case PACKET3_WRITE_DATA: ++ if ((idx_value & 0xf00) == 0) { ++ start_reg = ib[idx + 1] * 4; ++ if (idx_value & 0x10000) { ++ if (!si_vm_reg_valid(start_reg)) ++ return -EINVAL; ++ } else { ++ for (i = 0; i < (pkt->count - 2); i++) { ++ reg = start_reg + (4 * i); ++ if (!si_vm_reg_valid(reg)) ++ return -EINVAL; ++ } ++ } ++ } ++ break; ++ case PACKET3_COND_WRITE: ++ if (idx_value & 0x100) { ++ reg = ib[idx + 5] * 4; ++ if (!si_vm_reg_valid(reg)) ++ return -EINVAL; ++ } ++ break; ++ case PACKET3_COPY_DW: ++ if (idx_value & 0x2) { ++ reg = ib[idx + 3] * 4; ++ if (!si_vm_reg_valid(reg)) ++ return -EINVAL; ++ } ++ break; ++ case PACKET3_SET_CONFIG_REG: ++ start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; ++ end_reg = 4 * pkt->count + start_reg - 4; ++ if ((start_reg < PACKET3_SET_CONFIG_REG_START) || ++ (start_reg >= PACKET3_SET_CONFIG_REG_END) || ++ (end_reg >= PACKET3_SET_CONFIG_REG_END)) { ++ DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n"); ++ return -EINVAL; ++ } ++ for (i = 0; i < pkt->count; i++) { ++ reg = start_reg + (4 * i); ++ if (!si_vm_reg_valid(reg)) ++ return -EINVAL; ++ } ++ break; ++ default: ++ DRM_ERROR("Invalid GFX packet3: 0x%x\n", pkt->opcode); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int si_vm_packet3_compute_check(struct radeon_device *rdev, ++ u32 *ib, struct radeon_cs_packet *pkt) ++{ ++ u32 idx = pkt->idx + 1; ++ u32 idx_value = ib[idx]; ++ u32 start_reg, reg, i; ++ ++ switch (pkt->opcode) { ++ case PACKET3_NOP: ++ case PACKET3_SET_BASE: ++ case PACKET3_CLEAR_STATE: ++ case PACKET3_DISPATCH_DIRECT: ++ case PACKET3_DISPATCH_INDIRECT: ++ case PACKET3_ALLOC_GDS: ++ case PACKET3_WRITE_GDS_RAM: ++ case PACKET3_ATOMIC_GDS: ++ case PACKET3_ATOMIC: ++ case PACKET3_OCCLUSION_QUERY: ++ case PACKET3_SET_PREDICATION: ++ case PACKET3_COND_EXEC: ++ case PACKET3_PRED_EXEC: ++ case PACKET3_CONTEXT_CONTROL: ++ case PACKET3_STRMOUT_BUFFER_UPDATE: ++ case PACKET3_WAIT_REG_MEM: ++ case PACKET3_MEM_WRITE: ++ case PACKET3_PFP_SYNC_ME: ++ case PACKET3_SURFACE_SYNC: ++ case PACKET3_EVENT_WRITE: ++ case PACKET3_EVENT_WRITE_EOP: ++ case PACKET3_EVENT_WRITE_EOS: ++ case PACKET3_SET_CONTEXT_REG: ++ case PACKET3_SET_CONTEXT_REG_INDIRECT: ++ case PACKET3_SET_SH_REG: ++ case PACKET3_SET_SH_REG_OFFSET: ++ case PACKET3_INCREMENT_DE_COUNTER: ++ case PACKET3_WAIT_ON_CE_COUNTER: ++ case PACKET3_WAIT_ON_AVAIL_BUFFER: ++ case PACKET3_ME_WRITE: ++ break; ++ case PACKET3_COPY_DATA: ++ if ((idx_value & 0xf00) == 0) { ++ reg = ib[idx + 3] * 4; ++ if (!si_vm_reg_valid(reg)) ++ return -EINVAL; ++ } ++ break; ++ case PACKET3_WRITE_DATA: ++ if ((idx_value & 0xf00) == 0) { ++ start_reg = ib[idx + 1] * 4; ++ if (idx_value & 0x10000) { ++ if (!si_vm_reg_valid(start_reg)) ++ return -EINVAL; ++ } else { ++ for (i = 0; i < (pkt->count - 2); i++) { ++ reg = start_reg + (4 * i); ++ if (!si_vm_reg_valid(reg)) ++ return -EINVAL; ++ } ++ } ++ } ++ break; ++ case PACKET3_COND_WRITE: ++ if (idx_value & 0x100) { ++ reg = ib[idx + 5] * 4; ++ if (!si_vm_reg_valid(reg)) ++ return -EINVAL; ++ } ++ break; ++ case PACKET3_COPY_DW: ++ if (idx_value & 0x2) { ++ reg = ib[idx + 3] * 4; ++ if (!si_vm_reg_valid(reg)) ++ return -EINVAL; ++ } ++ break; ++ default: ++ DRM_ERROR("Invalid Compute packet3: 0x%x\n", pkt->opcode); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) ++{ ++ int ret = 0; ++ u32 idx = 0; ++ struct radeon_cs_packet pkt; ++ ++ do { ++ pkt.idx = idx; ++ pkt.type = CP_PACKET_GET_TYPE(ib->ptr[idx]); ++ pkt.count = CP_PACKET_GET_COUNT(ib->ptr[idx]); ++ pkt.one_reg_wr = 0; ++ switch (pkt.type) { ++ case PACKET_TYPE0: ++ dev_err(rdev->dev, "Packet0 not allowed!\n"); ++ ret = -EINVAL; ++ break; ++ case PACKET_TYPE2: ++ idx += 1; ++ break; ++ case PACKET_TYPE3: ++ pkt.opcode = CP_PACKET3_GET_OPCODE(ib->ptr[idx]); ++ if (ib->is_const_ib) ++ ret = si_vm_packet3_ce_check(rdev, ib->ptr, &pkt); ++ else { ++ switch (ib->fence->ring) { ++ case RADEON_RING_TYPE_GFX_INDEX: ++ ret = si_vm_packet3_gfx_check(rdev, ib->ptr, &pkt); ++ break; ++ case CAYMAN_RING_TYPE_CP1_INDEX: ++ case CAYMAN_RING_TYPE_CP2_INDEX: ++ ret = si_vm_packet3_compute_check(rdev, ib->ptr, &pkt); ++ break; ++ default: ++ dev_err(rdev->dev, "Non-PM4 ring %d !\n", ib->fence->ring); ++ ret = -EINVAL; ++ break; ++ } ++ } ++ idx += pkt.count + 2; ++ break; ++ default: ++ dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type); ++ ret = -EINVAL; ++ break; ++ } ++ if (ret) ++ break; ++ } while (idx < ib->length_dw); ++ ++ return ret; ++} ++ ++/* ++ * vm ++ */ ++int si_vm_init(struct radeon_device *rdev) ++{ ++ /* number of VMs */ ++ rdev->vm_manager.nvm = 16; ++ /* base offset of vram pages */ ++ rdev->vm_manager.vram_base_offset = 0; ++ ++ return 0; ++} ++ ++void si_vm_fini(struct radeon_device *rdev) ++{ ++} ++ ++int si_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm, int id) ++{ ++ if (id < 8) ++ WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (id << 2), vm->pt_gpu_addr >> 12); ++ else ++ WREG32(VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((id - 8) << 2), ++ vm->pt_gpu_addr >> 12); ++ /* flush hdp cache */ ++ WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); ++ /* bits 0-15 are the VM contexts0-15 */ ++ WREG32(VM_INVALIDATE_REQUEST, 1 << id); ++ return 0; ++} ++ ++void si_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm) ++{ ++ if (vm->id < 8) ++ WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2), 0); ++ else ++ WREG32(VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm->id - 8) << 2), 0); ++ /* flush hdp cache */ ++ WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); ++ /* bits 0-15 are the VM contexts0-15 */ ++ WREG32(VM_INVALIDATE_REQUEST, 1 << vm->id); ++} ++ ++void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm) ++{ ++ if (vm->id == -1) ++ return; ++ ++ /* flush hdp cache */ ++ WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); ++ /* bits 0-15 are the VM contexts0-15 */ ++ WREG32(VM_INVALIDATE_REQUEST, 1 << vm->id); ++} ++ ++/* ++ * RLC ++ */ ++void si_rlc_fini(struct radeon_device *rdev) ++{ ++ int r; ++ ++ /* save restore block */ ++ if (rdev->rlc.save_restore_obj) { ++ r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); ++ if (unlikely(r != 0)) ++ dev_warn(rdev->dev, "(%d) reserve RLC sr bo failed\n", r); ++ radeon_bo_unpin(rdev->rlc.save_restore_obj); ++ radeon_bo_unreserve(rdev->rlc.save_restore_obj); ++ ++ radeon_bo_unref(&rdev->rlc.save_restore_obj); ++ rdev->rlc.save_restore_obj = NULL; ++ } ++ ++ /* clear state block */ ++ if (rdev->rlc.clear_state_obj) { ++ r = radeon_bo_reserve(rdev->rlc.clear_state_obj, false); ++ if (unlikely(r != 0)) ++ dev_warn(rdev->dev, "(%d) reserve RLC c bo failed\n", r); ++ radeon_bo_unpin(rdev->rlc.clear_state_obj); ++ radeon_bo_unreserve(rdev->rlc.clear_state_obj); ++ ++ radeon_bo_unref(&rdev->rlc.clear_state_obj); ++ rdev->rlc.clear_state_obj = NULL; ++ } ++} ++ ++int si_rlc_init(struct radeon_device *rdev) ++{ ++ int r; ++ ++ /* save restore block */ ++ if (rdev->rlc.save_restore_obj == NULL) { ++ r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, ++ RADEON_GEM_DOMAIN_VRAM, &rdev->rlc.save_restore_obj); ++ if (r) { ++ dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r); ++ return r; ++ } ++ } ++ ++ r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); ++ if (unlikely(r != 0)) { ++ si_rlc_fini(rdev); ++ return r; ++ } ++ r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM, ++ &rdev->rlc.save_restore_gpu_addr); ++ radeon_bo_unreserve(rdev->rlc.save_restore_obj); ++ if (r) { ++ dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r); ++ si_rlc_fini(rdev); ++ return r; ++ } ++ ++ /* clear state block */ ++ if (rdev->rlc.clear_state_obj == NULL) { ++ r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, ++ RADEON_GEM_DOMAIN_VRAM, &rdev->rlc.clear_state_obj); ++ if (r) { ++ dev_warn(rdev->dev, "(%d) create RLC c bo failed\n", r); ++ si_rlc_fini(rdev); ++ return r; ++ } ++ } ++ r = radeon_bo_reserve(rdev->rlc.clear_state_obj, false); ++ if (unlikely(r != 0)) { ++ si_rlc_fini(rdev); ++ return r; ++ } ++ r = radeon_bo_pin(rdev->rlc.clear_state_obj, RADEON_GEM_DOMAIN_VRAM, ++ &rdev->rlc.clear_state_gpu_addr); ++ radeon_bo_unreserve(rdev->rlc.clear_state_obj); ++ if (r) { ++ dev_warn(rdev->dev, "(%d) pin RLC c bo failed\n", r); ++ si_rlc_fini(rdev); ++ return r; ++ } ++ ++ return 0; ++} ++ ++static void si_rlc_stop(struct radeon_device *rdev) ++{ ++ WREG32(RLC_CNTL, 0); ++} ++ ++static void si_rlc_start(struct radeon_device *rdev) ++{ ++ WREG32(RLC_CNTL, RLC_ENABLE); ++} ++ ++static int si_rlc_resume(struct radeon_device *rdev) ++{ ++ u32 i; ++ const __be32 *fw_data; ++ ++ if (!rdev->rlc_fw) ++ return -EINVAL; ++ ++ si_rlc_stop(rdev); ++ ++ WREG32(RLC_RL_BASE, 0); ++ WREG32(RLC_RL_SIZE, 0); ++ WREG32(RLC_LB_CNTL, 0); ++ WREG32(RLC_LB_CNTR_MAX, 0xffffffff); ++ WREG32(RLC_LB_CNTR_INIT, 0); ++ ++ WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); ++ WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); ++ ++ WREG32(RLC_MC_CNTL, 0); ++ WREG32(RLC_UCODE_CNTL, 0); ++ ++ fw_data = (const __be32 *)rdev->rlc_fw->data; ++ for (i = 0; i < SI_RLC_UCODE_SIZE; i++) { ++ WREG32(RLC_UCODE_ADDR, i); ++ WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); ++ } ++ WREG32(RLC_UCODE_ADDR, 0); ++ ++ si_rlc_start(rdev); ++ ++ return 0; ++} ++ ++static void si_enable_interrupts(struct radeon_device *rdev) ++{ ++ u32 ih_cntl = RREG32(IH_CNTL); ++ u32 ih_rb_cntl = RREG32(IH_RB_CNTL); ++ ++ ih_cntl |= ENABLE_INTR; ++ ih_rb_cntl |= IH_RB_ENABLE; ++ WREG32(IH_CNTL, ih_cntl); ++ WREG32(IH_RB_CNTL, ih_rb_cntl); ++ rdev->ih.enabled = true; ++} ++ ++static void si_disable_interrupts(struct radeon_device *rdev) ++{ ++ u32 ih_rb_cntl = RREG32(IH_RB_CNTL); ++ u32 ih_cntl = RREG32(IH_CNTL); ++ ++ ih_rb_cntl &= ~IH_RB_ENABLE; ++ ih_cntl &= ~ENABLE_INTR; ++ WREG32(IH_RB_CNTL, ih_rb_cntl); ++ WREG32(IH_CNTL, ih_cntl); ++ /* set rptr, wptr to 0 */ ++ WREG32(IH_RB_RPTR, 0); ++ WREG32(IH_RB_WPTR, 0); ++ rdev->ih.enabled = false; ++ rdev->ih.wptr = 0; ++ rdev->ih.rptr = 0; ++} ++ ++static void si_disable_interrupt_state(struct radeon_device *rdev) ++{ ++ u32 tmp; ++ ++ WREG32(CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); ++ WREG32(CP_INT_CNTL_RING1, 0); ++ WREG32(CP_INT_CNTL_RING2, 0); ++ WREG32(GRBM_INT_CNTL, 0); ++ WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); ++ WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); ++ if (rdev->num_crtc >= 4) { ++ WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); ++ WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); ++ } ++ if (rdev->num_crtc >= 6) { ++ WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); ++ WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); ++ } ++ ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); ++ if (rdev->num_crtc >= 4) { ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); ++ } ++ if (rdev->num_crtc >= 6) { ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); ++ } ++ ++ WREG32(DACA_AUTODETECT_INT_CONTROL, 0); ++ ++ tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; ++ WREG32(DC_HPD1_INT_CONTROL, tmp); ++ tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY; ++ WREG32(DC_HPD2_INT_CONTROL, tmp); ++ tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY; ++ WREG32(DC_HPD3_INT_CONTROL, tmp); ++ tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY; ++ WREG32(DC_HPD4_INT_CONTROL, tmp); ++ tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY; ++ WREG32(DC_HPD5_INT_CONTROL, tmp); ++ tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY; ++ WREG32(DC_HPD6_INT_CONTROL, tmp); ++ ++} ++ ++static int si_irq_init(struct radeon_device *rdev) ++{ ++ int ret = 0; ++ int rb_bufsz; ++ u32 interrupt_cntl, ih_cntl, ih_rb_cntl; ++ ++ /* allocate ring */ ++ ret = r600_ih_ring_alloc(rdev); ++ if (ret) ++ return ret; ++ ++ /* disable irqs */ ++ si_disable_interrupts(rdev); ++ ++ /* init rlc */ ++ ret = si_rlc_resume(rdev); ++ if (ret) { ++ r600_ih_ring_fini(rdev); ++ return ret; ++ } ++ ++ /* setup interrupt control */ ++ /* set dummy read address to ring address */ ++ WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8); ++ interrupt_cntl = RREG32(INTERRUPT_CNTL); ++ /* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi ++ * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN ++ */ ++ interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE; ++ /* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */ ++ interrupt_cntl &= ~IH_REQ_NONSNOOP_EN; ++ WREG32(INTERRUPT_CNTL, interrupt_cntl); ++ ++ WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8); ++ rb_bufsz = drm_order(rdev->ih.ring_size / 4); ++ ++ ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | ++ IH_WPTR_OVERFLOW_CLEAR | ++ (rb_bufsz << 1)); ++ ++ if (rdev->wb.enabled) ++ ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE; ++ ++ /* set the writeback address whether it's enabled or not */ ++ WREG32(IH_RB_WPTR_ADDR_LO, (rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFFFFFFFC); ++ WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFF); ++ ++ WREG32(IH_RB_CNTL, ih_rb_cntl); ++ ++ /* set rptr, wptr to 0 */ ++ WREG32(IH_RB_RPTR, 0); ++ WREG32(IH_RB_WPTR, 0); ++ ++ /* Default settings for IH_CNTL (disabled at first) */ ++ ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10) | MC_VMID(0); ++ /* RPTR_REARM only works if msi's are enabled */ ++ if (rdev->msi_enabled) ++ ih_cntl |= RPTR_REARM; ++ WREG32(IH_CNTL, ih_cntl); ++ ++ /* force the active interrupt state to all disabled */ ++ si_disable_interrupt_state(rdev); ++ ++ /* enable irqs */ ++ si_enable_interrupts(rdev); ++ ++ return ret; ++} ++ ++int si_irq_set(struct radeon_device *rdev) ++{ ++ u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; ++ u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0; ++ u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; ++ u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; ++ u32 grbm_int_cntl = 0; ++ u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; ++ ++ if (!rdev->irq.installed) { ++ WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); ++ return -EINVAL; ++ } ++ /* don't enable anything if the ih is disabled */ ++ if (!rdev->ih.enabled) { ++ si_disable_interrupts(rdev); ++ /* force the active interrupt state to all disabled */ ++ si_disable_interrupt_state(rdev); ++ return 0; ++ } ++ ++ hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; ++ hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; ++ hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; ++ hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN; ++ hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; ++ hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; ++ ++ /* enable CP interrupts on all rings */ ++ if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { ++ DRM_DEBUG("si_irq_set: sw int gfx\n"); ++ cp_int_cntl |= TIME_STAMP_INT_ENABLE; ++ } ++ if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP1_INDEX]) { ++ DRM_DEBUG("si_irq_set: sw int cp1\n"); ++ cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; ++ } ++ if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP2_INDEX]) { ++ DRM_DEBUG("si_irq_set: sw int cp2\n"); ++ cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; ++ } ++ if (rdev->irq.crtc_vblank_int[0] || ++ rdev->irq.pflip[0]) { ++ DRM_DEBUG("si_irq_set: vblank 0\n"); ++ crtc1 |= VBLANK_INT_MASK; ++ } ++ if (rdev->irq.crtc_vblank_int[1] || ++ rdev->irq.pflip[1]) { ++ DRM_DEBUG("si_irq_set: vblank 1\n"); ++ crtc2 |= VBLANK_INT_MASK; ++ } ++ if (rdev->irq.crtc_vblank_int[2] || ++ rdev->irq.pflip[2]) { ++ DRM_DEBUG("si_irq_set: vblank 2\n"); ++ crtc3 |= VBLANK_INT_MASK; ++ } ++ if (rdev->irq.crtc_vblank_int[3] || ++ rdev->irq.pflip[3]) { ++ DRM_DEBUG("si_irq_set: vblank 3\n"); ++ crtc4 |= VBLANK_INT_MASK; ++ } ++ if (rdev->irq.crtc_vblank_int[4] || ++ rdev->irq.pflip[4]) { ++ DRM_DEBUG("si_irq_set: vblank 4\n"); ++ crtc5 |= VBLANK_INT_MASK; ++ } ++ if (rdev->irq.crtc_vblank_int[5] || ++ rdev->irq.pflip[5]) { ++ DRM_DEBUG("si_irq_set: vblank 5\n"); ++ crtc6 |= VBLANK_INT_MASK; ++ } ++ if (rdev->irq.hpd[0]) { ++ DRM_DEBUG("si_irq_set: hpd 1\n"); ++ hpd1 |= DC_HPDx_INT_EN; ++ } ++ if (rdev->irq.hpd[1]) { ++ DRM_DEBUG("si_irq_set: hpd 2\n"); ++ hpd2 |= DC_HPDx_INT_EN; ++ } ++ if (rdev->irq.hpd[2]) { ++ DRM_DEBUG("si_irq_set: hpd 3\n"); ++ hpd3 |= DC_HPDx_INT_EN; ++ } ++ if (rdev->irq.hpd[3]) { ++ DRM_DEBUG("si_irq_set: hpd 4\n"); ++ hpd4 |= DC_HPDx_INT_EN; ++ } ++ if (rdev->irq.hpd[4]) { ++ DRM_DEBUG("si_irq_set: hpd 5\n"); ++ hpd5 |= DC_HPDx_INT_EN; ++ } ++ if (rdev->irq.hpd[5]) { ++ DRM_DEBUG("si_irq_set: hpd 6\n"); ++ hpd6 |= DC_HPDx_INT_EN; ++ } ++ if (rdev->irq.gui_idle) { ++ DRM_DEBUG("gui idle\n"); ++ grbm_int_cntl |= GUI_IDLE_INT_ENABLE; ++ } ++ ++ WREG32(CP_INT_CNTL_RING0, cp_int_cntl); ++ WREG32(CP_INT_CNTL_RING1, cp_int_cntl1); ++ WREG32(CP_INT_CNTL_RING2, cp_int_cntl2); ++ ++ WREG32(GRBM_INT_CNTL, grbm_int_cntl); ++ ++ WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1); ++ WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2); ++ if (rdev->num_crtc >= 4) { ++ WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3); ++ WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4); ++ } ++ if (rdev->num_crtc >= 6) { ++ WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5); ++ WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); ++ } ++ ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); ++ if (rdev->num_crtc >= 4) { ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); ++ } ++ if (rdev->num_crtc >= 6) { ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); ++ } ++ ++ WREG32(DC_HPD1_INT_CONTROL, hpd1); ++ WREG32(DC_HPD2_INT_CONTROL, hpd2); ++ WREG32(DC_HPD3_INT_CONTROL, hpd3); ++ WREG32(DC_HPD4_INT_CONTROL, hpd4); ++ WREG32(DC_HPD5_INT_CONTROL, hpd5); ++ WREG32(DC_HPD6_INT_CONTROL, hpd6); ++ ++ return 0; ++} ++ ++static inline void si_irq_ack(struct radeon_device *rdev) ++{ ++ u32 tmp; ++ ++ rdev->irq.stat_regs.evergreen.disp_int = RREG32(DISP_INTERRUPT_STATUS); ++ rdev->irq.stat_regs.evergreen.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); ++ rdev->irq.stat_regs.evergreen.disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2); ++ rdev->irq.stat_regs.evergreen.disp_int_cont3 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE3); ++ rdev->irq.stat_regs.evergreen.disp_int_cont4 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE4); ++ rdev->irq.stat_regs.evergreen.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5); ++ rdev->irq.stat_regs.evergreen.d1grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET); ++ rdev->irq.stat_regs.evergreen.d2grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET); ++ if (rdev->num_crtc >= 4) { ++ rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); ++ rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); ++ } ++ if (rdev->num_crtc >= 6) { ++ rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); ++ rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); ++ } ++ ++ if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED) ++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); ++ if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED) ++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); ++ if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) ++ WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK); ++ if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) ++ WREG32(VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VLINE_ACK); ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) ++ WREG32(VBLANK_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VBLANK_ACK); ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) ++ WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK); ++ ++ if (rdev->num_crtc >= 4) { ++ if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED) ++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); ++ if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED) ++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) ++ WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK); ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) ++ WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK); ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) ++ WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK); ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) ++ WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK); ++ } ++ ++ if (rdev->num_crtc >= 6) { ++ if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED) ++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); ++ if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED) ++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) ++ WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK); ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) ++ WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK); ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) ++ WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK); ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) ++ WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK); ++ } ++ ++ if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { ++ tmp = RREG32(DC_HPD1_INT_CONTROL); ++ tmp |= DC_HPDx_INT_ACK; ++ WREG32(DC_HPD1_INT_CONTROL, tmp); ++ } ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { ++ tmp = RREG32(DC_HPD2_INT_CONTROL); ++ tmp |= DC_HPDx_INT_ACK; ++ WREG32(DC_HPD2_INT_CONTROL, tmp); ++ } ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { ++ tmp = RREG32(DC_HPD3_INT_CONTROL); ++ tmp |= DC_HPDx_INT_ACK; ++ WREG32(DC_HPD3_INT_CONTROL, tmp); ++ } ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { ++ tmp = RREG32(DC_HPD4_INT_CONTROL); ++ tmp |= DC_HPDx_INT_ACK; ++ WREG32(DC_HPD4_INT_CONTROL, tmp); ++ } ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { ++ tmp = RREG32(DC_HPD5_INT_CONTROL); ++ tmp |= DC_HPDx_INT_ACK; ++ WREG32(DC_HPD5_INT_CONTROL, tmp); ++ } ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { ++ tmp = RREG32(DC_HPD5_INT_CONTROL); ++ tmp |= DC_HPDx_INT_ACK; ++ WREG32(DC_HPD6_INT_CONTROL, tmp); ++ } ++} ++ ++static void si_irq_disable(struct radeon_device *rdev) ++{ ++ si_disable_interrupts(rdev); ++ /* Wait and acknowledge irq */ ++ mdelay(1); ++ si_irq_ack(rdev); ++ si_disable_interrupt_state(rdev); ++} ++ ++static void si_irq_suspend(struct radeon_device *rdev) ++{ ++ si_irq_disable(rdev); ++ si_rlc_stop(rdev); ++} ++ ++static void si_irq_fini(struct radeon_device *rdev) ++{ ++ si_irq_suspend(rdev); ++ r600_ih_ring_fini(rdev); ++} ++ ++static inline u32 si_get_ih_wptr(struct radeon_device *rdev) ++{ ++ u32 wptr, tmp; ++ ++ if (rdev->wb.enabled) ++ wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]); ++ else ++ wptr = RREG32(IH_RB_WPTR); ++ ++ if (wptr & RB_OVERFLOW) { ++ /* When a ring buffer overflow happen start parsing interrupt ++ * from the last not overwritten vector (wptr + 16). Hopefully ++ * this should allow us to catchup. ++ */ ++ dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n", ++ wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask); ++ rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask; ++ tmp = RREG32(IH_RB_CNTL); ++ tmp |= IH_WPTR_OVERFLOW_CLEAR; ++ WREG32(IH_RB_CNTL, tmp); ++ } ++ return (wptr & rdev->ih.ptr_mask); ++} ++ ++/* SI IV Ring ++ * Each IV ring entry is 128 bits: ++ * [7:0] - interrupt source id ++ * [31:8] - reserved ++ * [59:32] - interrupt source data ++ * [63:60] - reserved ++ * [71:64] - RINGID ++ * [79:72] - VMID ++ * [127:80] - reserved ++ */ ++int si_irq_process(struct radeon_device *rdev) ++{ ++ u32 wptr; ++ u32 rptr; ++ u32 src_id, src_data, ring_id; ++ u32 ring_index; ++ unsigned long flags; ++ bool queue_hotplug = false; ++ ++ if (!rdev->ih.enabled || rdev->shutdown) ++ return IRQ_NONE; ++ ++ wptr = si_get_ih_wptr(rdev); ++ rptr = rdev->ih.rptr; ++ DRM_DEBUG("si_irq_process start: rptr %d, wptr %d\n", rptr, wptr); ++ ++ spin_lock_irqsave(&rdev->ih.lock, flags); ++ if (rptr == wptr) { ++ spin_unlock_irqrestore(&rdev->ih.lock, flags); ++ return IRQ_NONE; ++ } ++restart_ih: ++ /* Order reading of wptr vs. reading of IH ring data */ ++ rmb(); ++ ++ /* display interrupts */ ++ si_irq_ack(rdev); ++ ++ rdev->ih.wptr = wptr; ++ while (rptr != wptr) { ++ /* wptr/rptr are in bytes! */ ++ ring_index = rptr / 4; ++ src_id = le32_to_cpu(rdev->ih.ring[ring_index]) & 0xff; ++ src_data = le32_to_cpu(rdev->ih.ring[ring_index + 1]) & 0xfffffff; ++ ring_id = le32_to_cpu(rdev->ih.ring[ring_index + 2]) & 0xff; ++ ++ switch (src_id) { ++ case 1: /* D1 vblank/vline */ ++ switch (src_data) { ++ case 0: /* D1 vblank */ ++ if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) { ++ if (rdev->irq.crtc_vblank_int[0]) { ++ drm_handle_vblank(rdev->ddev, 0); ++ rdev->pm.vblank_sync = true; ++ wake_up(&rdev->irq.vblank_queue); ++ } ++ if (rdev->irq.pflip[0]) ++ radeon_crtc_handle_flip(rdev, 0); ++ rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; ++ DRM_DEBUG("IH: D1 vblank\n"); ++ } ++ break; ++ case 1: /* D1 vline */ ++ if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) { ++ rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; ++ DRM_DEBUG("IH: D1 vline\n"); ++ } ++ break; ++ default: ++ DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); ++ break; ++ } ++ break; ++ case 2: /* D2 vblank/vline */ ++ switch (src_data) { ++ case 0: /* D2 vblank */ ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { ++ if (rdev->irq.crtc_vblank_int[1]) { ++ drm_handle_vblank(rdev->ddev, 1); ++ rdev->pm.vblank_sync = true; ++ wake_up(&rdev->irq.vblank_queue); ++ } ++ if (rdev->irq.pflip[1]) ++ radeon_crtc_handle_flip(rdev, 1); ++ rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; ++ DRM_DEBUG("IH: D2 vblank\n"); ++ } ++ break; ++ case 1: /* D2 vline */ ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) { ++ rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; ++ DRM_DEBUG("IH: D2 vline\n"); ++ } ++ break; ++ default: ++ DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); ++ break; ++ } ++ break; ++ case 3: /* D3 vblank/vline */ ++ switch (src_data) { ++ case 0: /* D3 vblank */ ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { ++ if (rdev->irq.crtc_vblank_int[2]) { ++ drm_handle_vblank(rdev->ddev, 2); ++ rdev->pm.vblank_sync = true; ++ wake_up(&rdev->irq.vblank_queue); ++ } ++ if (rdev->irq.pflip[2]) ++ radeon_crtc_handle_flip(rdev, 2); ++ rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; ++ DRM_DEBUG("IH: D3 vblank\n"); ++ } ++ break; ++ case 1: /* D3 vline */ ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { ++ rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; ++ DRM_DEBUG("IH: D3 vline\n"); ++ } ++ break; ++ default: ++ DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); ++ break; ++ } ++ break; ++ case 4: /* D4 vblank/vline */ ++ switch (src_data) { ++ case 0: /* D4 vblank */ ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { ++ if (rdev->irq.crtc_vblank_int[3]) { ++ drm_handle_vblank(rdev->ddev, 3); ++ rdev->pm.vblank_sync = true; ++ wake_up(&rdev->irq.vblank_queue); ++ } ++ if (rdev->irq.pflip[3]) ++ radeon_crtc_handle_flip(rdev, 3); ++ rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; ++ DRM_DEBUG("IH: D4 vblank\n"); ++ } ++ break; ++ case 1: /* D4 vline */ ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { ++ rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; ++ DRM_DEBUG("IH: D4 vline\n"); ++ } ++ break; ++ default: ++ DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); ++ break; ++ } ++ break; ++ case 5: /* D5 vblank/vline */ ++ switch (src_data) { ++ case 0: /* D5 vblank */ ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { ++ if (rdev->irq.crtc_vblank_int[4]) { ++ drm_handle_vblank(rdev->ddev, 4); ++ rdev->pm.vblank_sync = true; ++ wake_up(&rdev->irq.vblank_queue); ++ } ++ if (rdev->irq.pflip[4]) ++ radeon_crtc_handle_flip(rdev, 4); ++ rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; ++ DRM_DEBUG("IH: D5 vblank\n"); ++ } ++ break; ++ case 1: /* D5 vline */ ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { ++ rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; ++ DRM_DEBUG("IH: D5 vline\n"); ++ } ++ break; ++ default: ++ DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); ++ break; ++ } ++ break; ++ case 6: /* D6 vblank/vline */ ++ switch (src_data) { ++ case 0: /* D6 vblank */ ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { ++ if (rdev->irq.crtc_vblank_int[5]) { ++ drm_handle_vblank(rdev->ddev, 5); ++ rdev->pm.vblank_sync = true; ++ wake_up(&rdev->irq.vblank_queue); ++ } ++ if (rdev->irq.pflip[5]) ++ radeon_crtc_handle_flip(rdev, 5); ++ rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; ++ DRM_DEBUG("IH: D6 vblank\n"); ++ } ++ break; ++ case 1: /* D6 vline */ ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { ++ rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; ++ DRM_DEBUG("IH: D6 vline\n"); ++ } ++ break; ++ default: ++ DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); ++ break; ++ } ++ break; ++ case 42: /* HPD hotplug */ ++ switch (src_data) { ++ case 0: ++ if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { ++ rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; ++ queue_hotplug = true; ++ DRM_DEBUG("IH: HPD1\n"); ++ } ++ break; ++ case 1: ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { ++ rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; ++ queue_hotplug = true; ++ DRM_DEBUG("IH: HPD2\n"); ++ } ++ break; ++ case 2: ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { ++ rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; ++ queue_hotplug = true; ++ DRM_DEBUG("IH: HPD3\n"); ++ } ++ break; ++ case 3: ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { ++ rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; ++ queue_hotplug = true; ++ DRM_DEBUG("IH: HPD4\n"); ++ } ++ break; ++ case 4: ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { ++ rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; ++ queue_hotplug = true; ++ DRM_DEBUG("IH: HPD5\n"); ++ } ++ break; ++ case 5: ++ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { ++ rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; ++ queue_hotplug = true; ++ DRM_DEBUG("IH: HPD6\n"); ++ } ++ break; ++ default: ++ DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); ++ break; ++ } ++ break; ++ case 176: /* RINGID0 CP_INT */ ++ radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ break; ++ case 177: /* RINGID1 CP_INT */ ++ radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP1_INDEX); ++ break; ++ case 178: /* RINGID2 CP_INT */ ++ radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP2_INDEX); ++ break; ++ case 181: /* CP EOP event */ ++ DRM_DEBUG("IH: CP EOP\n"); ++ switch (ring_id) { ++ case 0: ++ radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ break; ++ case 1: ++ radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP1_INDEX); ++ break; ++ case 2: ++ radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP2_INDEX); ++ break; ++ } ++ break; ++ case 233: /* GUI IDLE */ ++ DRM_DEBUG("IH: GUI idle\n"); ++ rdev->pm.gui_idle = true; ++ wake_up(&rdev->irq.idle_queue); ++ break; ++ default: ++ DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); ++ break; ++ } ++ ++ /* wptr/rptr are in bytes! */ ++ rptr += 16; ++ rptr &= rdev->ih.ptr_mask; ++ } ++ /* make sure wptr hasn't changed while processing */ ++ wptr = si_get_ih_wptr(rdev); ++ if (wptr != rdev->ih.wptr) ++ goto restart_ih; ++ if (queue_hotplug) ++ schedule_work(&rdev->hotplug_work); ++ rdev->ih.rptr = rptr; ++ WREG32(IH_RB_RPTR, rdev->ih.rptr); ++ spin_unlock_irqrestore(&rdev->ih.lock, flags); ++ return IRQ_HANDLED; ++} ++ ++/* ++ * startup/shutdown callbacks ++ */ ++static int si_startup(struct radeon_device *rdev) ++{ ++ struct radeon_ring *ring; ++ int r; ++ ++ si_mc_program(rdev); ++ ++ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || ++ !rdev->rlc_fw || !rdev->mc_fw) { ++ r = si_init_microcode(rdev); ++ if (r) { ++ DRM_ERROR("Failed to load firmware!\n"); ++ return r; ++ } ++ } ++ ++ r = si_mc_load_microcode(rdev); ++ if (r) { ++ DRM_ERROR("Failed to load MC firmware!\n"); ++ return r; ++ } ++ ++ r = r600_vram_scratch_init(rdev); ++ if (r) ++ return r; ++ ++ r = si_pcie_gart_enable(rdev); ++ if (r) ++ return r; ++ si_gpu_init(rdev); ++ ++#if 0 ++ r = evergreen_blit_init(rdev); ++ if (r) { ++ r600_blit_fini(rdev); ++ rdev->asic->copy = NULL; ++ dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); ++ } ++#endif ++ /* allocate rlc buffers */ ++ r = si_rlc_init(rdev); ++ if (r) { ++ DRM_ERROR("Failed to init rlc BOs!\n"); ++ return r; ++ } ++ ++ /* allocate wb buffer */ ++ r = radeon_wb_init(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ ++ r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ ++ r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP2_INDEX); ++ if (r) { ++ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); ++ return r; ++ } ++ ++ /* Enable IRQ */ ++ if (!rdev->irq.installed) { ++ r = radeon_irq_kms_init(rdev); ++ if (r) ++ return r; ++ } ++ ++ r = si_irq_init(rdev); ++ if (r) { ++ DRM_ERROR("radeon: IH init failed (%d).\n", r); ++ radeon_irq_kms_fini(rdev); ++ return r; ++ } ++ si_irq_set(rdev); ++ ++ ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, ++ CP_RB0_RPTR, CP_RB0_WPTR, ++ 0, 0xfffff, RADEON_CP_PACKET2); ++ if (r) ++ return r; ++ ++ ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; ++ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET, ++ CP_RB1_RPTR, CP_RB1_WPTR, ++ 0, 0xfffff, RADEON_CP_PACKET2); ++ if (r) ++ return r; ++ ++ ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; ++ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET, ++ CP_RB2_RPTR, CP_RB2_WPTR, ++ 0, 0xfffff, RADEON_CP_PACKET2); ++ if (r) ++ return r; ++ ++ r = si_cp_load_microcode(rdev); ++ if (r) ++ return r; ++ r = si_cp_resume(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_pool_start(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); ++ if (r) { ++ DRM_ERROR("radeon: failed testing IB (%d) on CP ring 0\n", r); ++ rdev->accel_working = false; ++ return r; ++ } ++ ++ r = radeon_ib_test(rdev, CAYMAN_RING_TYPE_CP1_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); ++ if (r) { ++ DRM_ERROR("radeon: failed testing IB (%d) on CP ring 1\n", r); ++ rdev->accel_working = false; ++ return r; ++ } ++ ++ r = radeon_ib_test(rdev, CAYMAN_RING_TYPE_CP2_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); ++ if (r) { ++ DRM_ERROR("radeon: failed testing IB (%d) on CP ring 2\n", r); ++ rdev->accel_working = false; ++ return r; ++ } ++ ++ r = radeon_vm_manager_start(rdev); ++ if (r) ++ return r; ++ ++ return 0; ++} ++ ++int si_resume(struct radeon_device *rdev) ++{ ++ int r; ++ ++ /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, ++ * posting will perform necessary task to bring back GPU into good ++ * shape. ++ */ ++ /* post card */ ++ atom_asic_init(rdev->mode_info.atom_context); ++ ++ rdev->accel_working = true; ++ r = si_startup(rdev); ++ if (r) { ++ DRM_ERROR("si startup failed on resume\n"); ++ rdev->accel_working = false; ++ return r; ++ } ++ ++ return r; ++ ++} ++ ++int si_suspend(struct radeon_device *rdev) ++{ ++ /* FIXME: we should wait for ring to be empty */ ++ radeon_ib_pool_suspend(rdev); ++ radeon_vm_manager_suspend(rdev); ++#if 0 ++ r600_blit_suspend(rdev); ++#endif ++ si_cp_enable(rdev, false); ++ rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; ++ rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; ++ rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; ++ si_irq_suspend(rdev); ++ radeon_wb_disable(rdev); ++ si_pcie_gart_disable(rdev); ++ return 0; ++} ++ ++/* Plan is to move initialization in that function and use ++ * helper function so that radeon_device_init pretty much ++ * do nothing more than calling asic specific function. This ++ * should also allow to remove a bunch of callback function ++ * like vram_info. ++ */ ++int si_init(struct radeon_device *rdev) ++{ ++ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ int r; ++ ++ /* This don't do much */ ++ r = radeon_gem_init(rdev); ++ if (r) ++ return r; ++ /* Read BIOS */ ++ if (!radeon_get_bios(rdev)) { ++ if (ASIC_IS_AVIVO(rdev)) ++ return -EINVAL; ++ } ++ /* Must be an ATOMBIOS */ ++ if (!rdev->is_atom_bios) { ++ dev_err(rdev->dev, "Expecting atombios for cayman GPU\n"); ++ return -EINVAL; ++ } ++ r = radeon_atombios_init(rdev); ++ if (r) ++ return r; ++ ++ /* Post card if necessary */ ++ if (!radeon_card_posted(rdev)) { ++ if (!rdev->bios) { ++ dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); ++ return -EINVAL; ++ } ++ DRM_INFO("GPU not posted. posting now...\n"); ++ atom_asic_init(rdev->mode_info.atom_context); ++ } ++ /* Initialize scratch registers */ ++ si_scratch_init(rdev); ++ /* Initialize surface registers */ ++ radeon_surface_init(rdev); ++ /* Initialize clocks */ ++ radeon_get_clock_info(rdev->ddev); ++ ++ /* Fence driver */ ++ r = radeon_fence_driver_init(rdev); ++ if (r) ++ return r; ++ ++ /* initialize memory controller */ ++ r = si_mc_init(rdev); ++ if (r) ++ return r; ++ /* Memory manager */ ++ r = radeon_bo_init(rdev); ++ if (r) ++ return r; ++ ++ ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ++ ring->ring_obj = NULL; ++ r600_ring_init(rdev, ring, 1024 * 1024); ++ ++ ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; ++ ring->ring_obj = NULL; ++ r600_ring_init(rdev, ring, 1024 * 1024); ++ ++ ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; ++ ring->ring_obj = NULL; ++ r600_ring_init(rdev, ring, 1024 * 1024); ++ ++ rdev->ih.ring_obj = NULL; ++ r600_ih_ring_init(rdev, 64 * 1024); ++ ++ r = r600_pcie_gart_init(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_ib_pool_init(rdev); ++ rdev->accel_working = true; ++ if (r) { ++ dev_err(rdev->dev, "IB initialization failed (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ r = radeon_vm_manager_init(rdev); ++ if (r) { ++ dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); ++ } ++ ++ r = si_startup(rdev); ++ if (r) { ++ dev_err(rdev->dev, "disabling GPU acceleration\n"); ++ si_cp_fini(rdev); ++ si_irq_fini(rdev); ++ si_rlc_fini(rdev); ++ radeon_wb_fini(rdev); ++ r100_ib_fini(rdev); ++ radeon_vm_manager_fini(rdev); ++ radeon_irq_kms_fini(rdev); ++ si_pcie_gart_fini(rdev); ++ rdev->accel_working = false; ++ } ++ ++ /* Don't start up if the MC ucode is missing. ++ * The default clocks and voltages before the MC ucode ++ * is loaded are not suffient for advanced operations. ++ */ ++ if (!rdev->mc_fw) { ++ DRM_ERROR("radeon: MC ucode required for NI+.\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++void si_fini(struct radeon_device *rdev) ++{ ++#if 0 ++ r600_blit_fini(rdev); ++#endif ++ si_cp_fini(rdev); ++ si_irq_fini(rdev); ++ si_rlc_fini(rdev); ++ radeon_wb_fini(rdev); ++ radeon_vm_manager_fini(rdev); ++ r100_ib_fini(rdev); ++ radeon_irq_kms_fini(rdev); ++ si_pcie_gart_fini(rdev); ++ r600_vram_scratch_fini(rdev); ++ radeon_gem_fini(rdev); ++ radeon_semaphore_driver_fini(rdev); ++ radeon_fence_driver_fini(rdev); ++ radeon_bo_fini(rdev); ++ radeon_atombios_fini(rdev); ++ kfree(rdev->bios); ++ rdev->bios = NULL; ++} ++ +diff --git a/drivers/gpu/drm/radeon/si_blit_shaders.c b/drivers/gpu/drm/radeon/si_blit_shaders.c +new file mode 100644 +index 0000000..ec415e7 +--- /dev/null ++++ b/drivers/gpu/drm/radeon/si_blit_shaders.c +@@ -0,0 +1,253 @@ ++/* ++ * Copyright 2011 Advanced Micro Devices, Inc. ++ * ++ * 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 (including the next ++ * paragraph) 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 HOLDER(S) AND/OR ITS SUPPLIERS 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. ++ * ++ * Authors: ++ * Alex Deucher ++ */ ++ ++#include ++#include ++#include ++ ++const u32 si_default_state[] = ++{ ++ 0xc0066900, ++ 0x00000000, ++ 0x00000060, /* DB_RENDER_CONTROL */ ++ 0x00000000, /* DB_COUNT_CONTROL */ ++ 0x00000000, /* DB_DEPTH_VIEW */ ++ 0x0000002a, /* DB_RENDER_OVERRIDE */ ++ 0x00000000, /* DB_RENDER_OVERRIDE2 */ ++ 0x00000000, /* DB_HTILE_DATA_BASE */ ++ ++ 0xc0046900, ++ 0x00000008, ++ 0x00000000, /* DB_DEPTH_BOUNDS_MIN */ ++ 0x00000000, /* DB_DEPTH_BOUNDS_MAX */ ++ 0x00000000, /* DB_STENCIL_CLEAR */ ++ 0x00000000, /* DB_DEPTH_CLEAR */ ++ ++ 0xc0036900, ++ 0x0000000f, ++ 0x00000000, /* DB_DEPTH_INFO */ ++ 0x00000000, /* DB_Z_INFO */ ++ 0x00000000, /* DB_STENCIL_INFO */ ++ ++ 0xc0016900, ++ 0x00000080, ++ 0x00000000, /* PA_SC_WINDOW_OFFSET */ ++ ++ 0xc00d6900, ++ 0x00000083, ++ 0x0000ffff, /* PA_SC_CLIPRECT_RULE */ ++ 0x00000000, /* PA_SC_CLIPRECT_0_TL */ ++ 0x20002000, /* PA_SC_CLIPRECT_0_BR */ ++ 0x00000000, ++ 0x20002000, ++ 0x00000000, ++ 0x20002000, ++ 0x00000000, ++ 0x20002000, ++ 0xaaaaaaaa, /* PA_SC_EDGERULE */ ++ 0x00000000, /* PA_SU_HARDWARE_SCREEN_OFFSET */ ++ 0x0000000f, /* CB_TARGET_MASK */ ++ 0x0000000f, /* CB_SHADER_MASK */ ++ ++ 0xc0226900, ++ 0x00000094, ++ 0x80000000, /* PA_SC_VPORT_SCISSOR_0_TL */ ++ 0x20002000, /* PA_SC_VPORT_SCISSOR_0_BR */ ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x00000000, /* PA_SC_VPORT_ZMIN_0 */ ++ 0x3f800000, /* PA_SC_VPORT_ZMAX_0 */ ++ ++ 0xc0026900, ++ 0x000000d9, ++ 0x00000000, /* CP_RINGID */ ++ 0x00000000, /* CP_VMID */ ++ ++ 0xc0046900, ++ 0x00000100, ++ 0xffffffff, /* VGT_MAX_VTX_INDX */ ++ 0x00000000, /* VGT_MIN_VTX_INDX */ ++ 0x00000000, /* VGT_INDX_OFFSET */ ++ 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_INDX */ ++ ++ 0xc0046900, ++ 0x00000105, ++ 0x00000000, /* CB_BLEND_RED */ ++ 0x00000000, /* CB_BLEND_GREEN */ ++ 0x00000000, /* CB_BLEND_BLUE */ ++ 0x00000000, /* CB_BLEND_ALPHA */ ++ ++ 0xc0016900, ++ 0x000001e0, ++ 0x00000000, /* CB_BLEND0_CONTROL */ ++ ++ 0xc00e6900, ++ 0x00000200, ++ 0x00000000, /* DB_DEPTH_CONTROL */ ++ 0x00000000, /* DB_EQAA */ ++ 0x00cc0010, /* CB_COLOR_CONTROL */ ++ 0x00000210, /* DB_SHADER_CONTROL */ ++ 0x00010000, /* PA_CL_CLIP_CNTL */ ++ 0x00000004, /* PA_SU_SC_MODE_CNTL */ ++ 0x00000100, /* PA_CL_VTE_CNTL */ ++ 0x00000000, /* PA_CL_VS_OUT_CNTL */ ++ 0x00000000, /* PA_CL_NANINF_CNTL */ ++ 0x00000000, /* PA_SU_LINE_STIPPLE_CNTL */ ++ 0x00000000, /* PA_SU_LINE_STIPPLE_SCALE */ ++ 0x00000000, /* PA_SU_PRIM_FILTER_CNTL */ ++ 0x00000000, /* */ ++ 0x00000000, /* */ ++ ++ 0xc0116900, ++ 0x00000280, ++ 0x00000000, /* PA_SU_POINT_SIZE */ ++ 0x00000000, /* PA_SU_POINT_MINMAX */ ++ 0x00000008, /* PA_SU_LINE_CNTL */ ++ 0x00000000, /* PA_SC_LINE_STIPPLE */ ++ 0x00000000, /* VGT_OUTPUT_PATH_CNTL */ ++ 0x00000000, /* VGT_HOS_CNTL */ ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, /* VGT_GS_MODE */ ++ ++ 0xc0026900, ++ 0x00000292, ++ 0x00000000, /* PA_SC_MODE_CNTL_0 */ ++ 0x00000000, /* PA_SC_MODE_CNTL_1 */ ++ ++ 0xc0016900, ++ 0x000002a1, ++ 0x00000000, /* VGT_PRIMITIVEID_EN */ ++ ++ 0xc0016900, ++ 0x000002a5, ++ 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_EN */ ++ ++ 0xc0026900, ++ 0x000002a8, ++ 0x00000000, /* VGT_INSTANCE_STEP_RATE_0 */ ++ 0x00000000, ++ ++ 0xc0026900, ++ 0x000002ad, ++ 0x00000000, /* VGT_REUSE_OFF */ ++ 0x00000000, ++ ++ 0xc0016900, ++ 0x000002d5, ++ 0x00000000, /* VGT_SHADER_STAGES_EN */ ++ ++ 0xc0016900, ++ 0x000002dc, ++ 0x0000aa00, /* DB_ALPHA_TO_MASK */ ++ ++ 0xc0066900, ++ 0x000002de, ++ 0x00000000, /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */ ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ ++ 0xc0026900, ++ 0x000002e5, ++ 0x00000000, /* VGT_STRMOUT_CONFIG */ ++ 0x00000000, ++ ++ 0xc01b6900, ++ 0x000002f5, ++ 0x76543210, /* PA_SC_CENTROID_PRIORITY_0 */ ++ 0xfedcba98, /* PA_SC_CENTROID_PRIORITY_1 */ ++ 0x00000000, /* PA_SC_LINE_CNTL */ ++ 0x00000000, /* PA_SC_AA_CONFIG */ ++ 0x00000005, /* PA_SU_VTX_CNTL */ ++ 0x3f800000, /* PA_CL_GB_VERT_CLIP_ADJ */ ++ 0x3f800000, /* PA_CL_GB_VERT_DISC_ADJ */ ++ 0x3f800000, /* PA_CL_GB_HORZ_CLIP_ADJ */ ++ 0x3f800000, /* PA_CL_GB_HORZ_DISC_ADJ */ ++ 0x00000000, /* PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */ ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0xffffffff, /* PA_SC_AA_MASK_X0Y0_X1Y0 */ ++ 0xffffffff, ++ ++ 0xc0026900, ++ 0x00000316, ++ 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ ++ 0x00000010, /* */ ++}; ++ ++const u32 si_default_size = ARRAY_SIZE(si_default_state); +diff --git a/drivers/gpu/drm/radeon/si_blit_shaders.h b/drivers/gpu/drm/radeon/si_blit_shaders.h +new file mode 100644 +index 0000000..c739e51 +--- /dev/null ++++ b/drivers/gpu/drm/radeon/si_blit_shaders.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright 2011 Advanced Micro Devices, Inc. ++ * ++ * 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 (including the next ++ * paragraph) 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 HOLDER(S) AND/OR ITS SUPPLIERS 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. ++ * ++ */ ++ ++#ifndef SI_BLIT_SHADERS_H ++#define SI_BLIT_SHADERS_H ++ ++extern const u32 si_default_state[]; ++ ++extern const u32 si_default_size; ++ ++#endif +diff --git a/drivers/gpu/drm/radeon/si_reg.h b/drivers/gpu/drm/radeon/si_reg.h +new file mode 100644 +index 0000000..eda938a +--- /dev/null ++++ b/drivers/gpu/drm/radeon/si_reg.h +@@ -0,0 +1,33 @@ ++/* ++ * Copyright 2010 Advanced Micro Devices, Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ * ++ * Authors: Alex Deucher ++ */ ++#ifndef __SI_REG_H__ ++#define __SI_REG_H__ ++ ++/* SI */ ++#define SI_DC_GPIO_HPD_MASK 0x65b0 ++#define SI_DC_GPIO_HPD_A 0x65b4 ++#define SI_DC_GPIO_HPD_EN 0x65b8 ++#define SI_DC_GPIO_HPD_Y 0x65bc ++ ++#endif +diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h +new file mode 100644 +index 0000000..a9fcbe4 +--- /dev/null ++++ b/drivers/gpu/drm/radeon/sid.h +@@ -0,0 +1,893 @@ ++/* ++ * Copyright 2011 Advanced Micro Devices, Inc. ++ * ++ * 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 HOLDER(S) OR AUTHOR(S) 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. ++ * ++ * Authors: Alex Deucher ++ */ ++#ifndef SI_H ++#define SI_H ++ ++#define CG_MULT_THERMAL_STATUS 0x714 ++#define ASIC_MAX_TEMP(x) ((x) << 0) ++#define ASIC_MAX_TEMP_MASK 0x000001ff ++#define ASIC_MAX_TEMP_SHIFT 0 ++#define CTF_TEMP(x) ((x) << 9) ++#define CTF_TEMP_MASK 0x0003fe00 ++#define CTF_TEMP_SHIFT 9 ++ ++#define SI_MAX_SH_GPRS 256 ++#define SI_MAX_TEMP_GPRS 16 ++#define SI_MAX_SH_THREADS 256 ++#define SI_MAX_SH_STACK_ENTRIES 4096 ++#define SI_MAX_FRC_EOV_CNT 16384 ++#define SI_MAX_BACKENDS 8 ++#define SI_MAX_BACKENDS_MASK 0xFF ++#define SI_MAX_BACKENDS_PER_SE_MASK 0x0F ++#define SI_MAX_SIMDS 12 ++#define SI_MAX_SIMDS_MASK 0x0FFF ++#define SI_MAX_SIMDS_PER_SE_MASK 0x00FF ++#define SI_MAX_PIPES 8 ++#define SI_MAX_PIPES_MASK 0xFF ++#define SI_MAX_PIPES_PER_SIMD_MASK 0x3F ++#define SI_MAX_LDS_NUM 0xFFFF ++#define SI_MAX_TCC 16 ++#define SI_MAX_TCC_MASK 0xFFFF ++ ++#define VGA_HDP_CONTROL 0x328 ++#define VGA_MEMORY_DISABLE (1 << 4) ++ ++#define DMIF_ADDR_CONFIG 0xBD4 ++ ++#define DMIF_ADDR_CALC 0xC00 ++ ++#define PIPE0_DMIF_BUFFER_CONTROL 0x0ca0 ++# define DMIF_BUFFERS_ALLOCATED(x) ((x) << 0) ++# define DMIF_BUFFERS_ALLOCATED_COMPLETED (1 << 4) ++ ++#define SRBM_STATUS 0xE50 ++ ++#define CC_SYS_RB_BACKEND_DISABLE 0xe80 ++#define GC_USER_SYS_RB_BACKEND_DISABLE 0xe84 ++ ++#define VM_L2_CNTL 0x1400 ++#define ENABLE_L2_CACHE (1 << 0) ++#define ENABLE_L2_FRAGMENT_PROCESSING (1 << 1) ++#define L2_CACHE_PTE_ENDIAN_SWAP_MODE(x) ((x) << 2) ++#define L2_CACHE_PDE_ENDIAN_SWAP_MODE(x) ((x) << 4) ++#define ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE (1 << 9) ++#define ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE (1 << 10) ++#define EFFECTIVE_L2_QUEUE_SIZE(x) (((x) & 7) << 15) ++#define CONTEXT1_IDENTITY_ACCESS_MODE(x) (((x) & 3) << 19) ++#define VM_L2_CNTL2 0x1404 ++#define INVALIDATE_ALL_L1_TLBS (1 << 0) ++#define INVALIDATE_L2_CACHE (1 << 1) ++#define INVALIDATE_CACHE_MODE(x) ((x) << 26) ++#define INVALIDATE_PTE_AND_PDE_CACHES 0 ++#define INVALIDATE_ONLY_PTE_CACHES 1 ++#define INVALIDATE_ONLY_PDE_CACHES 2 ++#define VM_L2_CNTL3 0x1408 ++#define BANK_SELECT(x) ((x) << 0) ++#define L2_CACHE_UPDATE_MODE(x) ((x) << 6) ++#define L2_CACHE_BIGK_FRAGMENT_SIZE(x) ((x) << 15) ++#define L2_CACHE_BIGK_ASSOCIATIVITY (1 << 20) ++#define VM_L2_STATUS 0x140C ++#define L2_BUSY (1 << 0) ++#define VM_CONTEXT0_CNTL 0x1410 ++#define ENABLE_CONTEXT (1 << 0) ++#define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) ++#define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) ++#define VM_CONTEXT1_CNTL 0x1414 ++#define VM_CONTEXT0_CNTL2 0x1430 ++#define VM_CONTEXT1_CNTL2 0x1434 ++#define VM_CONTEXT8_PAGE_TABLE_BASE_ADDR 0x1438 ++#define VM_CONTEXT9_PAGE_TABLE_BASE_ADDR 0x143c ++#define VM_CONTEXT10_PAGE_TABLE_BASE_ADDR 0x1440 ++#define VM_CONTEXT11_PAGE_TABLE_BASE_ADDR 0x1444 ++#define VM_CONTEXT12_PAGE_TABLE_BASE_ADDR 0x1448 ++#define VM_CONTEXT13_PAGE_TABLE_BASE_ADDR 0x144c ++#define VM_CONTEXT14_PAGE_TABLE_BASE_ADDR 0x1450 ++#define VM_CONTEXT15_PAGE_TABLE_BASE_ADDR 0x1454 ++ ++#define VM_INVALIDATE_REQUEST 0x1478 ++#define VM_INVALIDATE_RESPONSE 0x147c ++ ++#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x1518 ++#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR 0x151c ++ ++#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153c ++#define VM_CONTEXT1_PAGE_TABLE_BASE_ADDR 0x1540 ++#define VM_CONTEXT2_PAGE_TABLE_BASE_ADDR 0x1544 ++#define VM_CONTEXT3_PAGE_TABLE_BASE_ADDR 0x1548 ++#define VM_CONTEXT4_PAGE_TABLE_BASE_ADDR 0x154c ++#define VM_CONTEXT5_PAGE_TABLE_BASE_ADDR 0x1550 ++#define VM_CONTEXT6_PAGE_TABLE_BASE_ADDR 0x1554 ++#define VM_CONTEXT7_PAGE_TABLE_BASE_ADDR 0x1558 ++#define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155c ++#define VM_CONTEXT1_PAGE_TABLE_START_ADDR 0x1560 ++ ++#define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157C ++#define VM_CONTEXT1_PAGE_TABLE_END_ADDR 0x1580 ++ ++#define MC_SHARED_CHMAP 0x2004 ++#define NOOFCHAN_SHIFT 12 ++#define NOOFCHAN_MASK 0x0000f000 ++#define MC_SHARED_CHREMAP 0x2008 ++ ++#define MC_VM_FB_LOCATION 0x2024 ++#define MC_VM_AGP_TOP 0x2028 ++#define MC_VM_AGP_BOT 0x202C ++#define MC_VM_AGP_BASE 0x2030 ++#define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 ++#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 ++#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C ++ ++#define MC_VM_MX_L1_TLB_CNTL 0x2064 ++#define ENABLE_L1_TLB (1 << 0) ++#define ENABLE_L1_FRAGMENT_PROCESSING (1 << 1) ++#define SYSTEM_ACCESS_MODE_PA_ONLY (0 << 3) ++#define SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 3) ++#define SYSTEM_ACCESS_MODE_IN_SYS (2 << 3) ++#define SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 3) ++#define SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 5) ++#define ENABLE_ADVANCED_DRIVER_MODEL (1 << 6) ++ ++#define MC_SHARED_BLACKOUT_CNTL 0x20ac ++ ++#define MC_ARB_RAMCFG 0x2760 ++#define NOOFBANK_SHIFT 0 ++#define NOOFBANK_MASK 0x00000003 ++#define NOOFRANK_SHIFT 2 ++#define NOOFRANK_MASK 0x00000004 ++#define NOOFROWS_SHIFT 3 ++#define NOOFROWS_MASK 0x00000038 ++#define NOOFCOLS_SHIFT 6 ++#define NOOFCOLS_MASK 0x000000C0 ++#define CHANSIZE_SHIFT 8 ++#define CHANSIZE_MASK 0x00000100 ++#define CHANSIZE_OVERRIDE (1 << 11) ++#define NOOFGROUPS_SHIFT 12 ++#define NOOFGROUPS_MASK 0x00001000 ++ ++#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x28e8 ++#define TRAIN_DONE_D0 (1 << 30) ++#define TRAIN_DONE_D1 (1 << 31) ++ ++#define MC_SEQ_SUP_CNTL 0x28c8 ++#define RUN_MASK (1 << 0) ++#define MC_SEQ_SUP_PGM 0x28cc ++ ++#define MC_IO_PAD_CNTL_D0 0x29d0 ++#define MEM_FALL_OUT_CMD (1 << 8) ++ ++#define MC_SEQ_IO_DEBUG_INDEX 0x2a44 ++#define MC_SEQ_IO_DEBUG_DATA 0x2a48 ++ ++#define HDP_HOST_PATH_CNTL 0x2C00 ++#define HDP_NONSURFACE_BASE 0x2C04 ++#define HDP_NONSURFACE_INFO 0x2C08 ++#define HDP_NONSURFACE_SIZE 0x2C0C ++ ++#define HDP_ADDR_CONFIG 0x2F48 ++#define HDP_MISC_CNTL 0x2F4C ++#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) ++ ++#define IH_RB_CNTL 0x3e00 ++# define IH_RB_ENABLE (1 << 0) ++# define IH_IB_SIZE(x) ((x) << 1) /* log2 */ ++# define IH_RB_FULL_DRAIN_ENABLE (1 << 6) ++# define IH_WPTR_WRITEBACK_ENABLE (1 << 8) ++# define IH_WPTR_WRITEBACK_TIMER(x) ((x) << 9) /* log2 */ ++# define IH_WPTR_OVERFLOW_ENABLE (1 << 16) ++# define IH_WPTR_OVERFLOW_CLEAR (1 << 31) ++#define IH_RB_BASE 0x3e04 ++#define IH_RB_RPTR 0x3e08 ++#define IH_RB_WPTR 0x3e0c ++# define RB_OVERFLOW (1 << 0) ++# define WPTR_OFFSET_MASK 0x3fffc ++#define IH_RB_WPTR_ADDR_HI 0x3e10 ++#define IH_RB_WPTR_ADDR_LO 0x3e14 ++#define IH_CNTL 0x3e18 ++# define ENABLE_INTR (1 << 0) ++# define IH_MC_SWAP(x) ((x) << 1) ++# define IH_MC_SWAP_NONE 0 ++# define IH_MC_SWAP_16BIT 1 ++# define IH_MC_SWAP_32BIT 2 ++# define IH_MC_SWAP_64BIT 3 ++# define RPTR_REARM (1 << 4) ++# define MC_WRREQ_CREDIT(x) ((x) << 15) ++# define MC_WR_CLEAN_CNT(x) ((x) << 20) ++# define MC_VMID(x) ((x) << 25) ++ ++#define CONFIG_MEMSIZE 0x5428 ++ ++#define INTERRUPT_CNTL 0x5468 ++# define IH_DUMMY_RD_OVERRIDE (1 << 0) ++# define IH_DUMMY_RD_EN (1 << 1) ++# define IH_REQ_NONSNOOP_EN (1 << 3) ++# define GEN_IH_INT_EN (1 << 8) ++#define INTERRUPT_CNTL2 0x546c ++ ++#define HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 ++ ++#define BIF_FB_EN 0x5490 ++#define FB_READ_EN (1 << 0) ++#define FB_WRITE_EN (1 << 1) ++ ++#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 ++ ++#define DC_LB_MEMORY_SPLIT 0x6b0c ++#define DC_LB_MEMORY_CONFIG(x) ((x) << 20) ++ ++#define PRIORITY_A_CNT 0x6b18 ++#define PRIORITY_MARK_MASK 0x7fff ++#define PRIORITY_OFF (1 << 16) ++#define PRIORITY_ALWAYS_ON (1 << 20) ++#define PRIORITY_B_CNT 0x6b1c ++ ++#define DPG_PIPE_ARBITRATION_CONTROL3 0x6cc8 ++# define LATENCY_WATERMARK_MASK(x) ((x) << 16) ++#define DPG_PIPE_LATENCY_CONTROL 0x6ccc ++# define LATENCY_LOW_WATERMARK(x) ((x) << 0) ++# define LATENCY_HIGH_WATERMARK(x) ((x) << 16) ++ ++/* 0x6bb8, 0x77b8, 0x103b8, 0x10fb8, 0x11bb8, 0x127b8 */ ++#define VLINE_STATUS 0x6bb8 ++# define VLINE_OCCURRED (1 << 0) ++# define VLINE_ACK (1 << 4) ++# define VLINE_STAT (1 << 12) ++# define VLINE_INTERRUPT (1 << 16) ++# define VLINE_INTERRUPT_TYPE (1 << 17) ++/* 0x6bbc, 0x77bc, 0x103bc, 0x10fbc, 0x11bbc, 0x127bc */ ++#define VBLANK_STATUS 0x6bbc ++# define VBLANK_OCCURRED (1 << 0) ++# define VBLANK_ACK (1 << 4) ++# define VBLANK_STAT (1 << 12) ++# define VBLANK_INTERRUPT (1 << 16) ++# define VBLANK_INTERRUPT_TYPE (1 << 17) ++ ++/* 0x6b40, 0x7740, 0x10340, 0x10f40, 0x11b40, 0x12740 */ ++#define INT_MASK 0x6b40 ++# define VBLANK_INT_MASK (1 << 0) ++# define VLINE_INT_MASK (1 << 4) ++ ++#define DISP_INTERRUPT_STATUS 0x60f4 ++# define LB_D1_VLINE_INTERRUPT (1 << 2) ++# define LB_D1_VBLANK_INTERRUPT (1 << 3) ++# define DC_HPD1_INTERRUPT (1 << 17) ++# define DC_HPD1_RX_INTERRUPT (1 << 18) ++# define DACA_AUTODETECT_INTERRUPT (1 << 22) ++# define DACB_AUTODETECT_INTERRUPT (1 << 23) ++# define DC_I2C_SW_DONE_INTERRUPT (1 << 24) ++# define DC_I2C_HW_DONE_INTERRUPT (1 << 25) ++#define DISP_INTERRUPT_STATUS_CONTINUE 0x60f8 ++# define LB_D2_VLINE_INTERRUPT (1 << 2) ++# define LB_D2_VBLANK_INTERRUPT (1 << 3) ++# define DC_HPD2_INTERRUPT (1 << 17) ++# define DC_HPD2_RX_INTERRUPT (1 << 18) ++# define DISP_TIMER_INTERRUPT (1 << 24) ++#define DISP_INTERRUPT_STATUS_CONTINUE2 0x60fc ++# define LB_D3_VLINE_INTERRUPT (1 << 2) ++# define LB_D3_VBLANK_INTERRUPT (1 << 3) ++# define DC_HPD3_INTERRUPT (1 << 17) ++# define DC_HPD3_RX_INTERRUPT (1 << 18) ++#define DISP_INTERRUPT_STATUS_CONTINUE3 0x6100 ++# define LB_D4_VLINE_INTERRUPT (1 << 2) ++# define LB_D4_VBLANK_INTERRUPT (1 << 3) ++# define DC_HPD4_INTERRUPT (1 << 17) ++# define DC_HPD4_RX_INTERRUPT (1 << 18) ++#define DISP_INTERRUPT_STATUS_CONTINUE4 0x614c ++# define LB_D5_VLINE_INTERRUPT (1 << 2) ++# define LB_D5_VBLANK_INTERRUPT (1 << 3) ++# define DC_HPD5_INTERRUPT (1 << 17) ++# define DC_HPD5_RX_INTERRUPT (1 << 18) ++#define DISP_INTERRUPT_STATUS_CONTINUE5 0x6150 ++# define LB_D6_VLINE_INTERRUPT (1 << 2) ++# define LB_D6_VBLANK_INTERRUPT (1 << 3) ++# define DC_HPD6_INTERRUPT (1 << 17) ++# define DC_HPD6_RX_INTERRUPT (1 << 18) ++ ++/* 0x6858, 0x7458, 0x10058, 0x10c58, 0x11858, 0x12458 */ ++#define GRPH_INT_STATUS 0x6858 ++# define GRPH_PFLIP_INT_OCCURRED (1 << 0) ++# define GRPH_PFLIP_INT_CLEAR (1 << 8) ++/* 0x685c, 0x745c, 0x1005c, 0x10c5c, 0x1185c, 0x1245c */ ++#define GRPH_INT_CONTROL 0x685c ++# define GRPH_PFLIP_INT_MASK (1 << 0) ++# define GRPH_PFLIP_INT_TYPE (1 << 8) ++ ++#define DACA_AUTODETECT_INT_CONTROL 0x66c8 ++ ++#define DC_HPD1_INT_STATUS 0x601c ++#define DC_HPD2_INT_STATUS 0x6028 ++#define DC_HPD3_INT_STATUS 0x6034 ++#define DC_HPD4_INT_STATUS 0x6040 ++#define DC_HPD5_INT_STATUS 0x604c ++#define DC_HPD6_INT_STATUS 0x6058 ++# define DC_HPDx_INT_STATUS (1 << 0) ++# define DC_HPDx_SENSE (1 << 1) ++# define DC_HPDx_RX_INT_STATUS (1 << 8) ++ ++#define DC_HPD1_INT_CONTROL 0x6020 ++#define DC_HPD2_INT_CONTROL 0x602c ++#define DC_HPD3_INT_CONTROL 0x6038 ++#define DC_HPD4_INT_CONTROL 0x6044 ++#define DC_HPD5_INT_CONTROL 0x6050 ++#define DC_HPD6_INT_CONTROL 0x605c ++# define DC_HPDx_INT_ACK (1 << 0) ++# define DC_HPDx_INT_POLARITY (1 << 8) ++# define DC_HPDx_INT_EN (1 << 16) ++# define DC_HPDx_RX_INT_ACK (1 << 20) ++# define DC_HPDx_RX_INT_EN (1 << 24) ++ ++#define DC_HPD1_CONTROL 0x6024 ++#define DC_HPD2_CONTROL 0x6030 ++#define DC_HPD3_CONTROL 0x603c ++#define DC_HPD4_CONTROL 0x6048 ++#define DC_HPD5_CONTROL 0x6054 ++#define DC_HPD6_CONTROL 0x6060 ++# define DC_HPDx_CONNECTION_TIMER(x) ((x) << 0) ++# define DC_HPDx_RX_INT_TIMER(x) ((x) << 16) ++# define DC_HPDx_EN (1 << 28) ++ ++/* 0x6e98, 0x7a98, 0x10698, 0x11298, 0x11e98, 0x12a98 */ ++#define CRTC_STATUS_FRAME_COUNT 0x6e98 ++ ++#define GRBM_CNTL 0x8000 ++#define GRBM_READ_TIMEOUT(x) ((x) << 0) ++ ++#define GRBM_STATUS2 0x8008 ++#define RLC_RQ_PENDING (1 << 0) ++#define RLC_BUSY (1 << 8) ++#define TC_BUSY (1 << 9) ++ ++#define GRBM_STATUS 0x8010 ++#define CMDFIFO_AVAIL_MASK 0x0000000F ++#define RING2_RQ_PENDING (1 << 4) ++#define SRBM_RQ_PENDING (1 << 5) ++#define RING1_RQ_PENDING (1 << 6) ++#define CF_RQ_PENDING (1 << 7) ++#define PF_RQ_PENDING (1 << 8) ++#define GDS_DMA_RQ_PENDING (1 << 9) ++#define GRBM_EE_BUSY (1 << 10) ++#define DB_CLEAN (1 << 12) ++#define CB_CLEAN (1 << 13) ++#define TA_BUSY (1 << 14) ++#define GDS_BUSY (1 << 15) ++#define VGT_BUSY (1 << 17) ++#define IA_BUSY_NO_DMA (1 << 18) ++#define IA_BUSY (1 << 19) ++#define SX_BUSY (1 << 20) ++#define SPI_BUSY (1 << 22) ++#define BCI_BUSY (1 << 23) ++#define SC_BUSY (1 << 24) ++#define PA_BUSY (1 << 25) ++#define DB_BUSY (1 << 26) ++#define CP_COHERENCY_BUSY (1 << 28) ++#define CP_BUSY (1 << 29) ++#define CB_BUSY (1 << 30) ++#define GUI_ACTIVE (1 << 31) ++#define GRBM_STATUS_SE0 0x8014 ++#define GRBM_STATUS_SE1 0x8018 ++#define SE_DB_CLEAN (1 << 1) ++#define SE_CB_CLEAN (1 << 2) ++#define SE_BCI_BUSY (1 << 22) ++#define SE_VGT_BUSY (1 << 23) ++#define SE_PA_BUSY (1 << 24) ++#define SE_TA_BUSY (1 << 25) ++#define SE_SX_BUSY (1 << 26) ++#define SE_SPI_BUSY (1 << 27) ++#define SE_SC_BUSY (1 << 29) ++#define SE_DB_BUSY (1 << 30) ++#define SE_CB_BUSY (1 << 31) ++ ++#define GRBM_SOFT_RESET 0x8020 ++#define SOFT_RESET_CP (1 << 0) ++#define SOFT_RESET_CB (1 << 1) ++#define SOFT_RESET_RLC (1 << 2) ++#define SOFT_RESET_DB (1 << 3) ++#define SOFT_RESET_GDS (1 << 4) ++#define SOFT_RESET_PA (1 << 5) ++#define SOFT_RESET_SC (1 << 6) ++#define SOFT_RESET_BCI (1 << 7) ++#define SOFT_RESET_SPI (1 << 8) ++#define SOFT_RESET_SX (1 << 10) ++#define SOFT_RESET_TC (1 << 11) ++#define SOFT_RESET_TA (1 << 12) ++#define SOFT_RESET_VGT (1 << 14) ++#define SOFT_RESET_IA (1 << 15) ++ ++#define GRBM_GFX_INDEX 0x802C ++ ++#define GRBM_INT_CNTL 0x8060 ++# define RDERR_INT_ENABLE (1 << 0) ++# define GUI_IDLE_INT_ENABLE (1 << 19) ++ ++#define CP_STRMOUT_CNTL 0x84FC ++#define SCRATCH_REG0 0x8500 ++#define SCRATCH_REG1 0x8504 ++#define SCRATCH_REG2 0x8508 ++#define SCRATCH_REG3 0x850C ++#define SCRATCH_REG4 0x8510 ++#define SCRATCH_REG5 0x8514 ++#define SCRATCH_REG6 0x8518 ++#define SCRATCH_REG7 0x851C ++ ++#define SCRATCH_UMSK 0x8540 ++#define SCRATCH_ADDR 0x8544 ++ ++#define CP_SEM_WAIT_TIMER 0x85BC ++ ++#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 ++ ++#define CP_ME_CNTL 0x86D8 ++#define CP_CE_HALT (1 << 24) ++#define CP_PFP_HALT (1 << 26) ++#define CP_ME_HALT (1 << 28) ++ ++#define CP_COHER_CNTL2 0x85E8 ++ ++#define CP_RB2_RPTR 0x86f8 ++#define CP_RB1_RPTR 0x86fc ++#define CP_RB0_RPTR 0x8700 ++#define CP_RB_WPTR_DELAY 0x8704 ++ ++#define CP_QUEUE_THRESHOLDS 0x8760 ++#define ROQ_IB1_START(x) ((x) << 0) ++#define ROQ_IB2_START(x) ((x) << 8) ++#define CP_MEQ_THRESHOLDS 0x8764 ++#define MEQ1_START(x) ((x) << 0) ++#define MEQ2_START(x) ((x) << 8) ++ ++#define CP_PERFMON_CNTL 0x87FC ++ ++#define VGT_VTX_VECT_EJECT_REG 0x88B0 ++ ++#define VGT_CACHE_INVALIDATION 0x88C4 ++#define CACHE_INVALIDATION(x) ((x) << 0) ++#define VC_ONLY 0 ++#define TC_ONLY 1 ++#define VC_AND_TC 2 ++#define AUTO_INVLD_EN(x) ((x) << 6) ++#define NO_AUTO 0 ++#define ES_AUTO 1 ++#define GS_AUTO 2 ++#define ES_AND_GS_AUTO 3 ++#define VGT_ESGS_RING_SIZE 0x88C8 ++#define VGT_GSVS_RING_SIZE 0x88CC ++ ++#define VGT_GS_VERTEX_REUSE 0x88D4 ++ ++#define VGT_PRIMITIVE_TYPE 0x8958 ++#define VGT_INDEX_TYPE 0x895C ++ ++#define VGT_NUM_INDICES 0x8970 ++#define VGT_NUM_INSTANCES 0x8974 ++ ++#define VGT_TF_RING_SIZE 0x8988 ++ ++#define VGT_HS_OFFCHIP_PARAM 0x89B0 ++ ++#define VGT_TF_MEMORY_BASE 0x89B8 ++ ++#define CC_GC_SHADER_ARRAY_CONFIG 0x89bc ++#define GC_USER_SHADER_ARRAY_CONFIG 0x89c0 ++ ++#define PA_CL_ENHANCE 0x8A14 ++#define CLIP_VTX_REORDER_ENA (1 << 0) ++#define NUM_CLIP_SEQ(x) ((x) << 1) ++ ++#define PA_SU_LINE_STIPPLE_VALUE 0x8A60 ++ ++#define PA_SC_LINE_STIPPLE_STATE 0x8B10 ++ ++#define PA_SC_FORCE_EOV_MAX_CNTS 0x8B24 ++#define FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) ++#define FORCE_EOV_MAX_REZ_CNT(x) ((x) << 16) ++ ++#define PA_SC_FIFO_SIZE 0x8BCC ++#define SC_FRONTEND_PRIM_FIFO_SIZE(x) ((x) << 0) ++#define SC_BACKEND_PRIM_FIFO_SIZE(x) ((x) << 6) ++#define SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 15) ++#define SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 23) ++ ++#define PA_SC_ENHANCE 0x8BF0 ++ ++#define SQ_CONFIG 0x8C00 ++ ++#define SQC_CACHES 0x8C08 ++ ++#define SX_DEBUG_1 0x9060 ++ ++#define SPI_STATIC_THREAD_MGMT_1 0x90E0 ++#define SPI_STATIC_THREAD_MGMT_2 0x90E4 ++#define SPI_STATIC_THREAD_MGMT_3 0x90E8 ++#define SPI_PS_MAX_WAVE_ID 0x90EC ++ ++#define SPI_CONFIG_CNTL 0x9100 ++ ++#define SPI_CONFIG_CNTL_1 0x913C ++#define VTX_DONE_DELAY(x) ((x) << 0) ++#define INTERP_ONE_PRIM_PER_ROW (1 << 4) ++ ++#define CGTS_TCC_DISABLE 0x9148 ++#define CGTS_USER_TCC_DISABLE 0x914C ++#define TCC_DISABLE_MASK 0xFFFF0000 ++#define TCC_DISABLE_SHIFT 16 ++ ++#define TA_CNTL_AUX 0x9508 ++ ++#define CC_RB_BACKEND_DISABLE 0x98F4 ++#define BACKEND_DISABLE(x) ((x) << 16) ++#define GB_ADDR_CONFIG 0x98F8 ++#define NUM_PIPES(x) ((x) << 0) ++#define NUM_PIPES_MASK 0x00000007 ++#define NUM_PIPES_SHIFT 0 ++#define PIPE_INTERLEAVE_SIZE(x) ((x) << 4) ++#define PIPE_INTERLEAVE_SIZE_MASK 0x00000070 ++#define PIPE_INTERLEAVE_SIZE_SHIFT 4 ++#define NUM_SHADER_ENGINES(x) ((x) << 12) ++#define NUM_SHADER_ENGINES_MASK 0x00003000 ++#define NUM_SHADER_ENGINES_SHIFT 12 ++#define SHADER_ENGINE_TILE_SIZE(x) ((x) << 16) ++#define SHADER_ENGINE_TILE_SIZE_MASK 0x00070000 ++#define SHADER_ENGINE_TILE_SIZE_SHIFT 16 ++#define NUM_GPUS(x) ((x) << 20) ++#define NUM_GPUS_MASK 0x00700000 ++#define NUM_GPUS_SHIFT 20 ++#define MULTI_GPU_TILE_SIZE(x) ((x) << 24) ++#define MULTI_GPU_TILE_SIZE_MASK 0x03000000 ++#define MULTI_GPU_TILE_SIZE_SHIFT 24 ++#define ROW_SIZE(x) ((x) << 28) ++#define ROW_SIZE_MASK 0x30000000 ++#define ROW_SIZE_SHIFT 28 ++ ++#define GB_TILE_MODE0 0x9910 ++# define MICRO_TILE_MODE(x) ((x) << 0) ++# define ADDR_SURF_DISPLAY_MICRO_TILING 0 ++# define ADDR_SURF_THIN_MICRO_TILING 1 ++# define ADDR_SURF_DEPTH_MICRO_TILING 2 ++# define ARRAY_MODE(x) ((x) << 2) ++# define ARRAY_LINEAR_GENERAL 0 ++# define ARRAY_LINEAR_ALIGNED 1 ++# define ARRAY_1D_TILED_THIN1 2 ++# define ARRAY_2D_TILED_THIN1 4 ++# define PIPE_CONFIG(x) ((x) << 6) ++# define ADDR_SURF_P2 0 ++# define ADDR_SURF_P4_8x16 4 ++# define ADDR_SURF_P4_16x16 5 ++# define ADDR_SURF_P4_16x32 6 ++# define ADDR_SURF_P4_32x32 7 ++# define ADDR_SURF_P8_16x16_8x16 8 ++# define ADDR_SURF_P8_16x32_8x16 9 ++# define ADDR_SURF_P8_32x32_8x16 10 ++# define ADDR_SURF_P8_16x32_16x16 11 ++# define ADDR_SURF_P8_32x32_16x16 12 ++# define ADDR_SURF_P8_32x32_16x32 13 ++# define ADDR_SURF_P8_32x64_32x32 14 ++# define TILE_SPLIT(x) ((x) << 11) ++# define ADDR_SURF_TILE_SPLIT_64B 0 ++# define ADDR_SURF_TILE_SPLIT_128B 1 ++# define ADDR_SURF_TILE_SPLIT_256B 2 ++# define ADDR_SURF_TILE_SPLIT_512B 3 ++# define ADDR_SURF_TILE_SPLIT_1KB 4 ++# define ADDR_SURF_TILE_SPLIT_2KB 5 ++# define ADDR_SURF_TILE_SPLIT_4KB 6 ++# define BANK_WIDTH(x) ((x) << 14) ++# define ADDR_SURF_BANK_WIDTH_1 0 ++# define ADDR_SURF_BANK_WIDTH_2 1 ++# define ADDR_SURF_BANK_WIDTH_4 2 ++# define ADDR_SURF_BANK_WIDTH_8 3 ++# define BANK_HEIGHT(x) ((x) << 16) ++# define ADDR_SURF_BANK_HEIGHT_1 0 ++# define ADDR_SURF_BANK_HEIGHT_2 1 ++# define ADDR_SURF_BANK_HEIGHT_4 2 ++# define ADDR_SURF_BANK_HEIGHT_8 3 ++# define MACRO_TILE_ASPECT(x) ((x) << 18) ++# define ADDR_SURF_MACRO_ASPECT_1 0 ++# define ADDR_SURF_MACRO_ASPECT_2 1 ++# define ADDR_SURF_MACRO_ASPECT_4 2 ++# define ADDR_SURF_MACRO_ASPECT_8 3 ++# define NUM_BANKS(x) ((x) << 20) ++# define ADDR_SURF_2_BANK 0 ++# define ADDR_SURF_4_BANK 1 ++# define ADDR_SURF_8_BANK 2 ++# define ADDR_SURF_16_BANK 3 ++ ++#define CB_PERFCOUNTER0_SELECT0 0x9a20 ++#define CB_PERFCOUNTER0_SELECT1 0x9a24 ++#define CB_PERFCOUNTER1_SELECT0 0x9a28 ++#define CB_PERFCOUNTER1_SELECT1 0x9a2c ++#define CB_PERFCOUNTER2_SELECT0 0x9a30 ++#define CB_PERFCOUNTER2_SELECT1 0x9a34 ++#define CB_PERFCOUNTER3_SELECT0 0x9a38 ++#define CB_PERFCOUNTER3_SELECT1 0x9a3c ++ ++#define GC_USER_RB_BACKEND_DISABLE 0x9B7C ++#define BACKEND_DISABLE_MASK 0x00FF0000 ++#define BACKEND_DISABLE_SHIFT 16 ++ ++#define TCP_CHAN_STEER_LO 0xac0c ++#define TCP_CHAN_STEER_HI 0xac10 ++ ++#define CP_RB0_BASE 0xC100 ++#define CP_RB0_CNTL 0xC104 ++#define RB_BUFSZ(x) ((x) << 0) ++#define RB_BLKSZ(x) ((x) << 8) ++#define BUF_SWAP_32BIT (2 << 16) ++#define RB_NO_UPDATE (1 << 27) ++#define RB_RPTR_WR_ENA (1 << 31) ++ ++#define CP_RB0_RPTR_ADDR 0xC10C ++#define CP_RB0_RPTR_ADDR_HI 0xC110 ++#define CP_RB0_WPTR 0xC114 ++ ++#define CP_PFP_UCODE_ADDR 0xC150 ++#define CP_PFP_UCODE_DATA 0xC154 ++#define CP_ME_RAM_RADDR 0xC158 ++#define CP_ME_RAM_WADDR 0xC15C ++#define CP_ME_RAM_DATA 0xC160 ++ ++#define CP_CE_UCODE_ADDR 0xC168 ++#define CP_CE_UCODE_DATA 0xC16C ++ ++#define CP_RB1_BASE 0xC180 ++#define CP_RB1_CNTL 0xC184 ++#define CP_RB1_RPTR_ADDR 0xC188 ++#define CP_RB1_RPTR_ADDR_HI 0xC18C ++#define CP_RB1_WPTR 0xC190 ++#define CP_RB2_BASE 0xC194 ++#define CP_RB2_CNTL 0xC198 ++#define CP_RB2_RPTR_ADDR 0xC19C ++#define CP_RB2_RPTR_ADDR_HI 0xC1A0 ++#define CP_RB2_WPTR 0xC1A4 ++#define CP_INT_CNTL_RING0 0xC1A8 ++#define CP_INT_CNTL_RING1 0xC1AC ++#define CP_INT_CNTL_RING2 0xC1B0 ++# define CNTX_BUSY_INT_ENABLE (1 << 19) ++# define CNTX_EMPTY_INT_ENABLE (1 << 20) ++# define WAIT_MEM_SEM_INT_ENABLE (1 << 21) ++# define TIME_STAMP_INT_ENABLE (1 << 26) ++# define CP_RINGID2_INT_ENABLE (1 << 29) ++# define CP_RINGID1_INT_ENABLE (1 << 30) ++# define CP_RINGID0_INT_ENABLE (1 << 31) ++#define CP_INT_STATUS_RING0 0xC1B4 ++#define CP_INT_STATUS_RING1 0xC1B8 ++#define CP_INT_STATUS_RING2 0xC1BC ++# define WAIT_MEM_SEM_INT_STAT (1 << 21) ++# define TIME_STAMP_INT_STAT (1 << 26) ++# define CP_RINGID2_INT_STAT (1 << 29) ++# define CP_RINGID1_INT_STAT (1 << 30) ++# define CP_RINGID0_INT_STAT (1 << 31) ++ ++#define CP_DEBUG 0xC1FC ++ ++#define RLC_CNTL 0xC300 ++# define RLC_ENABLE (1 << 0) ++#define RLC_RL_BASE 0xC304 ++#define RLC_RL_SIZE 0xC308 ++#define RLC_LB_CNTL 0xC30C ++#define RLC_SAVE_AND_RESTORE_BASE 0xC310 ++#define RLC_LB_CNTR_MAX 0xC314 ++#define RLC_LB_CNTR_INIT 0xC318 ++ ++#define RLC_CLEAR_STATE_RESTORE_BASE 0xC320 ++ ++#define RLC_UCODE_ADDR 0xC32C ++#define RLC_UCODE_DATA 0xC330 ++ ++#define RLC_MC_CNTL 0xC344 ++#define RLC_UCODE_CNTL 0xC348 ++ ++#define VGT_EVENT_INITIATOR 0x28a90 ++# define SAMPLE_STREAMOUTSTATS1 (1 << 0) ++# define SAMPLE_STREAMOUTSTATS2 (2 << 0) ++# define SAMPLE_STREAMOUTSTATS3 (3 << 0) ++# define CACHE_FLUSH_TS (4 << 0) ++# define CACHE_FLUSH (6 << 0) ++# define CS_PARTIAL_FLUSH (7 << 0) ++# define VGT_STREAMOUT_RESET (10 << 0) ++# define END_OF_PIPE_INCR_DE (11 << 0) ++# define END_OF_PIPE_IB_END (12 << 0) ++# define RST_PIX_CNT (13 << 0) ++# define VS_PARTIAL_FLUSH (15 << 0) ++# define PS_PARTIAL_FLUSH (16 << 0) ++# define CACHE_FLUSH_AND_INV_TS_EVENT (20 << 0) ++# define ZPASS_DONE (21 << 0) ++# define CACHE_FLUSH_AND_INV_EVENT (22 << 0) ++# define PERFCOUNTER_START (23 << 0) ++# define PERFCOUNTER_STOP (24 << 0) ++# define PIPELINESTAT_START (25 << 0) ++# define PIPELINESTAT_STOP (26 << 0) ++# define PERFCOUNTER_SAMPLE (27 << 0) ++# define SAMPLE_PIPELINESTAT (30 << 0) ++# define SAMPLE_STREAMOUTSTATS (32 << 0) ++# define RESET_VTX_CNT (33 << 0) ++# define VGT_FLUSH (36 << 0) ++# define BOTTOM_OF_PIPE_TS (40 << 0) ++# define DB_CACHE_FLUSH_AND_INV (42 << 0) ++# define FLUSH_AND_INV_DB_DATA_TS (43 << 0) ++# define FLUSH_AND_INV_DB_META (44 << 0) ++# define FLUSH_AND_INV_CB_DATA_TS (45 << 0) ++# define FLUSH_AND_INV_CB_META (46 << 0) ++# define CS_DONE (47 << 0) ++# define PS_DONE (48 << 0) ++# define FLUSH_AND_INV_CB_PIXEL_DATA (49 << 0) ++# define THREAD_TRACE_START (51 << 0) ++# define THREAD_TRACE_STOP (52 << 0) ++# define THREAD_TRACE_FLUSH (54 << 0) ++# define THREAD_TRACE_FINISH (55 << 0) ++ ++/* ++ * PM4 ++ */ ++#define PACKET_TYPE0 0 ++#define PACKET_TYPE1 1 ++#define PACKET_TYPE2 2 ++#define PACKET_TYPE3 3 ++ ++#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) ++#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) ++#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2) ++#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) ++#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \ ++ (((reg) >> 2) & 0xFFFF) | \ ++ ((n) & 0x3FFF) << 16) ++#define CP_PACKET2 0x80000000 ++#define PACKET2_PAD_SHIFT 0 ++#define PACKET2_PAD_MASK (0x3fffffff << 0) ++ ++#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) ++ ++#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \ ++ (((op) & 0xFF) << 8) | \ ++ ((n) & 0x3FFF) << 16) ++ ++#define PACKET3_COMPUTE(op, n) (PACKET3(op, n) | 1 << 1) ++ ++/* Packet 3 types */ ++#define PACKET3_NOP 0x10 ++#define PACKET3_SET_BASE 0x11 ++#define PACKET3_BASE_INDEX(x) ((x) << 0) ++#define GDS_PARTITION_BASE 2 ++#define CE_PARTITION_BASE 3 ++#define PACKET3_CLEAR_STATE 0x12 ++#define PACKET3_INDEX_BUFFER_SIZE 0x13 ++#define PACKET3_DISPATCH_DIRECT 0x15 ++#define PACKET3_DISPATCH_INDIRECT 0x16 ++#define PACKET3_ALLOC_GDS 0x1B ++#define PACKET3_WRITE_GDS_RAM 0x1C ++#define PACKET3_ATOMIC_GDS 0x1D ++#define PACKET3_ATOMIC 0x1E ++#define PACKET3_OCCLUSION_QUERY 0x1F ++#define PACKET3_SET_PREDICATION 0x20 ++#define PACKET3_REG_RMW 0x21 ++#define PACKET3_COND_EXEC 0x22 ++#define PACKET3_PRED_EXEC 0x23 ++#define PACKET3_DRAW_INDIRECT 0x24 ++#define PACKET3_DRAW_INDEX_INDIRECT 0x25 ++#define PACKET3_INDEX_BASE 0x26 ++#define PACKET3_DRAW_INDEX_2 0x27 ++#define PACKET3_CONTEXT_CONTROL 0x28 ++#define PACKET3_INDEX_TYPE 0x2A ++#define PACKET3_DRAW_INDIRECT_MULTI 0x2C ++#define PACKET3_DRAW_INDEX_AUTO 0x2D ++#define PACKET3_DRAW_INDEX_IMMD 0x2E ++#define PACKET3_NUM_INSTANCES 0x2F ++#define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30 ++#define PACKET3_INDIRECT_BUFFER_CONST 0x31 ++#define PACKET3_INDIRECT_BUFFER 0x32 ++#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34 ++#define PACKET3_DRAW_INDEX_OFFSET_2 0x35 ++#define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 ++#define PACKET3_WRITE_DATA 0x37 ++#define PACKET3_DRAW_INDEX_INDIRECT_MULTI 0x38 ++#define PACKET3_MEM_SEMAPHORE 0x39 ++#define PACKET3_MPEG_INDEX 0x3A ++#define PACKET3_COPY_DW 0x3B ++#define PACKET3_WAIT_REG_MEM 0x3C ++#define PACKET3_MEM_WRITE 0x3D ++#define PACKET3_COPY_DATA 0x40 ++#define PACKET3_PFP_SYNC_ME 0x42 ++#define PACKET3_SURFACE_SYNC 0x43 ++# define PACKET3_DEST_BASE_0_ENA (1 << 0) ++# define PACKET3_DEST_BASE_1_ENA (1 << 1) ++# define PACKET3_CB0_DEST_BASE_ENA (1 << 6) ++# define PACKET3_CB1_DEST_BASE_ENA (1 << 7) ++# define PACKET3_CB2_DEST_BASE_ENA (1 << 8) ++# define PACKET3_CB3_DEST_BASE_ENA (1 << 9) ++# define PACKET3_CB4_DEST_BASE_ENA (1 << 10) ++# define PACKET3_CB5_DEST_BASE_ENA (1 << 11) ++# define PACKET3_CB6_DEST_BASE_ENA (1 << 12) ++# define PACKET3_CB7_DEST_BASE_ENA (1 << 13) ++# define PACKET3_DB_DEST_BASE_ENA (1 << 14) ++# define PACKET3_DEST_BASE_2_ENA (1 << 19) ++# define PACKET3_DEST_BASE_3_ENA (1 << 21) ++# define PACKET3_TCL1_ACTION_ENA (1 << 22) ++# define PACKET3_TC_ACTION_ENA (1 << 23) ++# define PACKET3_CB_ACTION_ENA (1 << 25) ++# define PACKET3_DB_ACTION_ENA (1 << 26) ++# define PACKET3_SH_KCACHE_ACTION_ENA (1 << 27) ++# define PACKET3_SH_ICACHE_ACTION_ENA (1 << 29) ++#define PACKET3_ME_INITIALIZE 0x44 ++#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) ++#define PACKET3_COND_WRITE 0x45 ++#define PACKET3_EVENT_WRITE 0x46 ++#define EVENT_TYPE(x) ((x) << 0) ++#define EVENT_INDEX(x) ((x) << 8) ++ /* 0 - any non-TS event ++ * 1 - ZPASS_DONE ++ * 2 - SAMPLE_PIPELINESTAT ++ * 3 - SAMPLE_STREAMOUTSTAT* ++ * 4 - *S_PARTIAL_FLUSH ++ * 5 - EOP events ++ * 6 - EOS events ++ * 7 - CACHE_FLUSH, CACHE_FLUSH_AND_INV_EVENT ++ */ ++#define INV_L2 (1 << 20) ++ /* INV TC L2 cache when EVENT_INDEX = 7 */ ++#define PACKET3_EVENT_WRITE_EOP 0x47 ++#define DATA_SEL(x) ((x) << 29) ++ /* 0 - discard ++ * 1 - send low 32bit data ++ * 2 - send 64bit data ++ * 3 - send 64bit counter value ++ */ ++#define INT_SEL(x) ((x) << 24) ++ /* 0 - none ++ * 1 - interrupt only (DATA_SEL = 0) ++ * 2 - interrupt when data write is confirmed ++ */ ++#define PACKET3_EVENT_WRITE_EOS 0x48 ++#define PACKET3_PREAMBLE_CNTL 0x4A ++# define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE (2 << 28) ++# define PACKET3_PREAMBLE_END_CLEAR_STATE (3 << 28) ++#define PACKET3_ONE_REG_WRITE 0x57 ++#define PACKET3_LOAD_CONFIG_REG 0x5F ++#define PACKET3_LOAD_CONTEXT_REG 0x60 ++#define PACKET3_LOAD_SH_REG 0x61 ++#define PACKET3_SET_CONFIG_REG 0x68 ++#define PACKET3_SET_CONFIG_REG_START 0x00008000 ++#define PACKET3_SET_CONFIG_REG_END 0x0000b000 ++#define PACKET3_SET_CONTEXT_REG 0x69 ++#define PACKET3_SET_CONTEXT_REG_START 0x00028000 ++#define PACKET3_SET_CONTEXT_REG_END 0x00029000 ++#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73 ++#define PACKET3_SET_RESOURCE_INDIRECT 0x74 ++#define PACKET3_SET_SH_REG 0x76 ++#define PACKET3_SET_SH_REG_START 0x0000b000 ++#define PACKET3_SET_SH_REG_END 0x0000c000 ++#define PACKET3_SET_SH_REG_OFFSET 0x77 ++#define PACKET3_ME_WRITE 0x7A ++#define PACKET3_SCRATCH_RAM_WRITE 0x7D ++#define PACKET3_SCRATCH_RAM_READ 0x7E ++#define PACKET3_CE_WRITE 0x7F ++#define PACKET3_LOAD_CONST_RAM 0x80 ++#define PACKET3_WRITE_CONST_RAM 0x81 ++#define PACKET3_WRITE_CONST_RAM_OFFSET 0x82 ++#define PACKET3_DUMP_CONST_RAM 0x83 ++#define PACKET3_INCREMENT_CE_COUNTER 0x84 ++#define PACKET3_INCREMENT_DE_COUNTER 0x85 ++#define PACKET3_WAIT_ON_CE_COUNTER 0x86 ++#define PACKET3_WAIT_ON_DE_COUNTER 0x87 ++#define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88 ++#define PACKET3_SET_CE_DE_COUNTERS 0x89 ++#define PACKET3_WAIT_ON_AVAIL_BUFFER 0x8A ++ ++#endif +diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c +index cb1ee4e..2a25888 100644 +--- a/drivers/gpu/drm/savage/savage_bci.c ++++ b/drivers/gpu/drm/savage/savage_bci.c +@@ -547,6 +547,8 @@ int savage_driver_load(struct drm_device *dev, unsigned long chipset) + + dev_priv->chipset = (enum savage_family)chipset; + ++ pci_set_master(dev->pdev); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c +index 5468d1c..89afe0b 100644 +--- a/drivers/gpu/drm/savage/savage_drv.c ++++ b/drivers/gpu/drm/savage/savage_drv.c +@@ -35,6 +35,17 @@ static struct pci_device_id pciidlist[] = { + savage_PCI_IDS + }; + ++static const struct file_operations savage_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .mmap = drm_mmap, ++ .poll = drm_poll, ++ .fasync = drm_fasync, ++ .llseek = noop_llseek, ++}; ++ + static struct drm_driver driver = { + .driver_features = + DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_PCI_DMA, +@@ -46,17 +57,7 @@ static struct drm_driver driver = { + .reclaim_buffers = savage_reclaim_buffers, + .ioctls = savage_ioctls, + .dma_ioctl = savage_bci_buffers, +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = drm_ioctl, +- .mmap = drm_mmap, +- .poll = drm_poll, +- .fasync = drm_fasync, +- .llseek = noop_llseek, +- }, +- ++ .fops = &savage_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, +diff --git a/drivers/gpu/drm/savage/savage_state.c b/drivers/gpu/drm/savage/savage_state.c +index 8a3e315..b6d8608 100644 +--- a/drivers/gpu/drm/savage/savage_state.c ++++ b/drivers/gpu/drm/savage/savage_state.c +@@ -988,7 +988,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ + * for locking on FreeBSD. + */ + if (cmdbuf->size) { +- kcmd_addr = kmalloc(cmdbuf->size * 8, GFP_KERNEL); ++ kcmd_addr = kmalloc_array(cmdbuf->size, 8, GFP_KERNEL); + if (kcmd_addr == NULL) + return -ENOMEM; + +@@ -1015,8 +1015,8 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ + cmdbuf->vb_addr = kvb_addr; + } + if (cmdbuf->nbox) { +- kbox_addr = kmalloc(cmdbuf->nbox * sizeof(struct drm_clip_rect), +- GFP_KERNEL); ++ kbox_addr = kmalloc_array(cmdbuf->nbox, sizeof(struct drm_clip_rect), ++ GFP_KERNEL); + if (kbox_addr == NULL) { + ret = -ENOMEM; + goto done; +@@ -1057,7 +1057,8 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ + DRM_ERROR("indexed drawing command extends " + "beyond end of command buffer\n"); + DMA_FLUSH(); +- return -EINVAL; ++ ret = -EINVAL; ++ goto done; + } + /* fall through */ + case SAVAGE_CMD_DMA_PRIM: +@@ -1076,7 +1077,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ + cmdbuf->vb_stride, + cmdbuf->nbox, cmdbuf->box_addr); + if (ret != 0) +- return ret; ++ goto done; + first_draw_cmd = NULL; + } + } +diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c +index a9c5716..dd14cd1 100644 +--- a/drivers/gpu/drm/sis/sis_drv.c ++++ b/drivers/gpu/drm/sis/sis_drv.c +@@ -40,51 +40,78 @@ static struct pci_device_id pciidlist[] = { + static int sis_driver_load(struct drm_device *dev, unsigned long chipset) + { + drm_sis_private_t *dev_priv; +- int ret; ++ ++ pci_set_master(dev->pdev); + + dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL); + if (dev_priv == NULL) + return -ENOMEM; + ++ idr_init(&dev_priv->object_idr); + dev->dev_private = (void *)dev_priv; + dev_priv->chipset = chipset; +- ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); +- if (ret) +- kfree(dev_priv); + +- return ret; ++ return 0; + } + + static int sis_driver_unload(struct drm_device *dev) + { + drm_sis_private_t *dev_priv = dev->dev_private; + +- drm_sman_takedown(&dev_priv->sman); ++ idr_remove_all(&dev_priv->object_idr); ++ idr_destroy(&dev_priv->object_idr); ++ + kfree(dev_priv); + + return 0; + } + ++static const struct file_operations sis_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .mmap = drm_mmap, ++ .poll = drm_poll, ++ .fasync = drm_fasync, ++ .llseek = noop_llseek, ++}; ++ ++static int sis_driver_open(struct drm_device *dev, struct drm_file *file) ++{ ++ struct sis_file_private *file_priv; ++ ++ DRM_DEBUG_DRIVER("\n"); ++ file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL); ++ if (!file_priv) ++ return -ENOMEM; ++ ++ file->driver_priv = file_priv; ++ ++ INIT_LIST_HEAD(&file_priv->obj_list); ++ ++ return 0; ++} ++ ++void sis_driver_postclose(struct drm_device *dev, struct drm_file *file) ++{ ++ struct sis_file_private *file_priv = file->driver_priv; ++ ++ kfree(file_priv); ++} ++ + static struct drm_driver driver = { + .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR, + .load = sis_driver_load, + .unload = sis_driver_unload, ++ .open = sis_driver_open, ++ .postclose = sis_driver_postclose, + .dma_quiescent = sis_idle, + .reclaim_buffers = NULL, + .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked, + .lastclose = sis_lastclose, + .ioctls = sis_ioctls, +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = drm_ioctl, +- .mmap = drm_mmap, +- .poll = drm_poll, +- .fasync = drm_fasync, +- .llseek = noop_llseek, +- }, +- ++ .fops = &sis_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, +diff --git a/drivers/gpu/drm/sis/sis_drv.h b/drivers/gpu/drm/sis/sis_drv.h +index 194303c..573758b 100644 +--- a/drivers/gpu/drm/sis/sis_drv.h ++++ b/drivers/gpu/drm/sis/sis_drv.h +@@ -44,7 +44,7 @@ enum sis_family { + SIS_CHIP_315 = 1, + }; + +-#include "drm_sman.h" ++#include "drm_mm.h" + + + #define SIS_BASE (dev_priv->mmio) +@@ -54,12 +54,15 @@ enum sis_family { + typedef struct drm_sis_private { + drm_local_map_t *mmio; + unsigned int idle_fault; +- struct drm_sman sman; + unsigned int chipset; + int vram_initialized; + int agp_initialized; + unsigned long vram_offset; + unsigned long agp_offset; ++ struct drm_mm vram_mm; ++ struct drm_mm agp_mm; ++ /** Mapping of userspace keys to mm objects */ ++ struct idr object_idr; + } drm_sis_private_t; + + extern int sis_idle(struct drm_device *dev); +diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c +index 7fe2b63..dd4a316 100644 +--- a/drivers/gpu/drm/sis/sis_mm.c ++++ b/drivers/gpu/drm/sis/sis_mm.c +@@ -41,40 +41,18 @@ + #define AGP_TYPE 1 + + ++struct sis_memblock { ++ struct drm_mm_node mm_node; ++ struct sis_memreq req; ++ struct list_head owner_list; ++}; ++ + #if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE) + /* fb management via fb device */ + + #define SIS_MM_ALIGN_SHIFT 0 + #define SIS_MM_ALIGN_MASK 0 + +-static void *sis_sman_mm_allocate(void *private, unsigned long size, +- unsigned alignment) +-{ +- struct sis_memreq req; +- +- req.size = size; +- sis_malloc(&req); +- if (req.size == 0) +- return NULL; +- else +- return (void *)(unsigned long)~req.offset; +-} +- +-static void sis_sman_mm_free(void *private, void *ref) +-{ +- sis_free(~((unsigned long)ref)); +-} +- +-static void sis_sman_mm_destroy(void *private) +-{ +- ; +-} +- +-static unsigned long sis_sman_mm_offset(void *private, void *ref) +-{ +- return ~((unsigned long)ref); +-} +- + #else /* CONFIG_FB_SIS[_MODULE] */ + + #define SIS_MM_ALIGN_SHIFT 4 +@@ -86,30 +64,11 @@ static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file + { + drm_sis_private_t *dev_priv = dev->dev_private; + drm_sis_fb_t *fb = data; +- int ret; + + mutex_lock(&dev->struct_mutex); +-#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE) +- { +- struct drm_sman_mm sman_mm; +- sman_mm.private = (void *)0xFFFFFFFF; +- sman_mm.allocate = sis_sman_mm_allocate; +- sman_mm.free = sis_sman_mm_free; +- sman_mm.destroy = sis_sman_mm_destroy; +- sman_mm.offset = sis_sman_mm_offset; +- ret = +- drm_sman_set_manager(&dev_priv->sman, VIDEO_TYPE, &sman_mm); +- } +-#else +- ret = drm_sman_set_range(&dev_priv->sman, VIDEO_TYPE, 0, +- fb->size >> SIS_MM_ALIGN_SHIFT); +-#endif +- +- if (ret) { +- DRM_ERROR("VRAM memory manager initialisation error\n"); +- mutex_unlock(&dev->struct_mutex); +- return ret; +- } ++ /* Unconditionally init the drm_mm, even though we don't use it when the ++ * fb sis driver is available - make cleanup easier. */ ++ drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> SIS_MM_ALIGN_SHIFT); + + dev_priv->vram_initialized = 1; + dev_priv->vram_offset = fb->offset; +@@ -120,13 +79,15 @@ static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file + return 0; + } + +-static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file_priv, ++static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file, + void *data, int pool) + { + drm_sis_private_t *dev_priv = dev->dev_private; + drm_sis_mem_t *mem = data; +- int retval = 0; +- struct drm_memblock_item *item; ++ int retval = 0, user_key; ++ struct sis_memblock *item; ++ struct sis_file_private *file_priv = file->driver_priv; ++ unsigned long offset; + + mutex_lock(&dev->struct_mutex); + +@@ -138,25 +99,68 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file_priv, + return -EINVAL; + } + +- mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT; +- item = drm_sman_alloc(&dev_priv->sman, pool, mem->size, 0, +- (unsigned long)file_priv); ++ item = kzalloc(sizeof(*item), GFP_KERNEL); ++ if (!item) { ++ retval = -ENOMEM; ++ goto fail_alloc; ++ } + +- mutex_unlock(&dev->struct_mutex); +- if (item) { +- mem->offset = ((pool == 0) ? +- dev_priv->vram_offset : dev_priv->agp_offset) + +- (item->mm-> +- offset(item->mm, item->mm_info) << SIS_MM_ALIGN_SHIFT); +- mem->free = item->user_hash.key; +- mem->size = mem->size << SIS_MM_ALIGN_SHIFT; ++ mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT; ++ if (pool == AGP_TYPE) { ++ retval = drm_mm_insert_node(&dev_priv->agp_mm, ++ &item->mm_node, ++ mem->size, 0); ++ offset = item->mm_node.start; + } else { +- mem->offset = 0; +- mem->size = 0; +- mem->free = 0; ++#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE) ++ item->req.size = mem->size; ++ sis_malloc(&item->req); ++ if (item->req.size == 0) ++ retval = -ENOMEM; ++ offset = item->req.offset; ++#else ++ retval = drm_mm_insert_node(&dev_priv->vram_mm, ++ &item->mm_node, ++ mem->size, 0); ++ offset = item->mm_node.start; ++#endif ++ } ++ if (retval) ++ goto fail_alloc; ++ ++again: ++ if (idr_pre_get(&dev_priv->object_idr, GFP_KERNEL) == 0) { + retval = -ENOMEM; ++ goto fail_idr; + } + ++ retval = idr_get_new_above(&dev_priv->object_idr, item, 1, &user_key); ++ if (retval == -EAGAIN) ++ goto again; ++ if (retval) ++ goto fail_idr; ++ ++ list_add(&item->owner_list, &file_priv->obj_list); ++ mutex_unlock(&dev->struct_mutex); ++ ++ mem->offset = ((pool == 0) ? ++ dev_priv->vram_offset : dev_priv->agp_offset) + ++ (offset << SIS_MM_ALIGN_SHIFT); ++ mem->free = user_key; ++ mem->size = mem->size << SIS_MM_ALIGN_SHIFT; ++ ++ return 0; ++ ++fail_idr: ++ drm_mm_remove_node(&item->mm_node); ++fail_alloc: ++ kfree(item); ++ mutex_unlock(&dev->struct_mutex); ++ ++ mem->offset = 0; ++ mem->size = 0; ++ mem->free = 0; ++ + DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size, + mem->offset); + +@@ -167,14 +171,28 @@ static int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *fil + { + drm_sis_private_t *dev_priv = dev->dev_private; + drm_sis_mem_t *mem = data; +- int ret; ++ struct sis_memblock *obj; + + mutex_lock(&dev->struct_mutex); +- ret = drm_sman_free_key(&dev_priv->sman, mem->free); ++ obj = idr_find(&dev_priv->object_idr, mem->free); ++ if (obj == NULL) { ++ mutex_unlock(&dev->struct_mutex); ++ return -EINVAL; ++ } ++ ++ idr_remove(&dev_priv->object_idr, mem->free); ++ list_del(&obj->owner_list); ++ if (drm_mm_node_allocated(&obj->mm_node)) ++ drm_mm_remove_node(&obj->mm_node); ++#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE) ++ else ++ sis_free(obj->req.offset); ++#endif ++ kfree(obj); + mutex_unlock(&dev->struct_mutex); + DRM_DEBUG("free = 0x%lx\n", mem->free); + +- return ret; ++ return 0; + } + + static int sis_fb_alloc(struct drm_device *dev, void *data, +@@ -188,18 +206,10 @@ static int sis_ioctl_agp_init(struct drm_device *dev, void *data, + { + drm_sis_private_t *dev_priv = dev->dev_private; + drm_sis_agp_t *agp = data; +- int ret; + dev_priv = dev->dev_private; + + mutex_lock(&dev->struct_mutex); +- ret = drm_sman_set_range(&dev_priv->sman, AGP_TYPE, 0, +- agp->size >> SIS_MM_ALIGN_SHIFT); +- +- if (ret) { +- DRM_ERROR("AGP memory manager initialisation error\n"); +- mutex_unlock(&dev->struct_mutex); +- return ret; +- } ++ drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> SIS_MM_ALIGN_SHIFT); + + dev_priv->agp_initialized = 1; + dev_priv->agp_offset = agp->offset; +@@ -293,20 +303,26 @@ void sis_lastclose(struct drm_device *dev) + return; + + mutex_lock(&dev->struct_mutex); +- drm_sman_cleanup(&dev_priv->sman); +- dev_priv->vram_initialized = 0; +- dev_priv->agp_initialized = 0; ++ if (dev_priv->vram_initialized) { ++ drm_mm_takedown(&dev_priv->vram_mm); ++ dev_priv->vram_initialized = 0; ++ } ++ if (dev_priv->agp_initialized) { ++ drm_mm_takedown(&dev_priv->agp_mm); ++ dev_priv->agp_initialized = 0; ++ } + dev_priv->mmio = NULL; + mutex_unlock(&dev->struct_mutex); + } + + void sis_reclaim_buffers_locked(struct drm_device *dev, +- struct drm_file *file_priv) ++ struct drm_file *file) + { +- drm_sis_private_t *dev_priv = dev->dev_private; ++ struct sis_file_private *file_priv = file->driver_priv; ++ struct sis_memblock *entry, *next; + + mutex_lock(&dev->struct_mutex); +- if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) { ++ if (list_empty(&file_priv->obj_list)) { + mutex_unlock(&dev->struct_mutex); + return; + } +@@ -314,7 +330,18 @@ void sis_reclaim_buffers_locked(struct drm_device *dev, + if (dev->driver->dma_quiescent) + dev->driver->dma_quiescent(dev); + +- drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv); ++ ++ list_for_each_entry_safe(entry, next, &file_priv->obj_list, ++ owner_list) { ++ list_del(&entry->owner_list); ++ if (drm_mm_node_allocated(&entry->mm_node)) ++ drm_mm_remove_node(&entry->mm_node); ++#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE) ++ else ++ sis_free(entry->req.offset); ++#endif ++ kfree(entry); ++ } + mutex_unlock(&dev->struct_mutex); + return; + } +diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c +index cda2991..1613c78 100644 +--- a/drivers/gpu/drm/tdfx/tdfx_drv.c ++++ b/drivers/gpu/drm/tdfx/tdfx_drv.c +@@ -41,20 +41,21 @@ static struct pci_device_id pciidlist[] = { + tdfx_PCI_IDS + }; + ++static const struct file_operations tdfx_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .mmap = drm_mmap, ++ .poll = drm_poll, ++ .fasync = drm_fasync, ++ .llseek = noop_llseek, ++}; ++ + static struct drm_driver driver = { + .driver_features = DRIVER_USE_MTRR, + .reclaim_buffers = drm_core_reclaim_buffers, +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = drm_ioctl, +- .mmap = drm_mmap, +- .poll = drm_poll, +- .fasync = drm_fasync, +- .llseek = noop_llseek, +- }, +- ++ .fops = &tdfx_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, +diff --git a/drivers/gpu/drm/ttm/Makefile b/drivers/gpu/drm/ttm/Makefile +index f3cf6f0..b2b33dd 100644 +--- a/drivers/gpu/drm/ttm/Makefile ++++ b/drivers/gpu/drm/ttm/Makefile +@@ -7,4 +7,8 @@ ttm-y := ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \ + ttm_object.o ttm_lock.o ttm_execbuf_util.o ttm_page_alloc.o \ + ttm_bo_manager.o + ++ifeq ($(CONFIG_SWIOTLB),y) ++ttm-y += ttm_page_alloc_dma.o ++endif ++ + obj-$(CONFIG_DRM_TTM) += ttm.o +diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c +index 1c4a72f..4a87282 100644 +--- a/drivers/gpu/drm/ttm/ttm_agp_backend.c ++++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c +@@ -29,8 +29,11 @@ + * Keith Packard. + */ + ++#define pr_fmt(fmt) "[TTM] " fmt ++ + #include "ttm/ttm_module.h" + #include "ttm/ttm_bo_driver.h" ++#include "ttm/ttm_page_alloc.h" + #ifdef TTM_HAS_AGP + #include "ttm/ttm_placement.h" + #include +@@ -40,100 +43,77 @@ + #include + + struct ttm_agp_backend { +- struct ttm_backend backend; ++ struct ttm_tt ttm; + struct agp_memory *mem; + struct agp_bridge_data *bridge; + }; + +-static int ttm_agp_populate(struct ttm_backend *backend, +- unsigned long num_pages, struct page **pages, +- struct page *dummy_read_page, +- dma_addr_t *dma_addrs) ++static int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) + { +- struct ttm_agp_backend *agp_be = +- container_of(backend, struct ttm_agp_backend, backend); +- struct page **cur_page, **last_page = pages + num_pages; ++ struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); ++ struct drm_mm_node *node = bo_mem->mm_node; + struct agp_memory *mem; ++ int ret, cached = (bo_mem->placement & TTM_PL_FLAG_CACHED); ++ unsigned i; + +- mem = agp_allocate_memory(agp_be->bridge, num_pages, AGP_USER_MEMORY); ++ mem = agp_allocate_memory(agp_be->bridge, ttm->num_pages, AGP_USER_MEMORY); + if (unlikely(mem == NULL)) + return -ENOMEM; + + mem->page_count = 0; +- for (cur_page = pages; cur_page < last_page; ++cur_page) { +- struct page *page = *cur_page; ++ for (i = 0; i < ttm->num_pages; i++) { ++ struct page *page = ttm->pages[i]; ++ + if (!page) +- page = dummy_read_page; ++ page = ttm->dummy_read_page; + + mem->pages[mem->page_count++] = page; + } + agp_be->mem = mem; +- return 0; +-} +- +-static int ttm_agp_bind(struct ttm_backend *backend, struct ttm_mem_reg *bo_mem) +-{ +- struct ttm_agp_backend *agp_be = +- container_of(backend, struct ttm_agp_backend, backend); +- struct drm_mm_node *node = bo_mem->mm_node; +- struct agp_memory *mem = agp_be->mem; +- int cached = (bo_mem->placement & TTM_PL_FLAG_CACHED); +- int ret; + + mem->is_flushed = 1; + mem->type = (cached) ? AGP_USER_CACHED_MEMORY : AGP_USER_MEMORY; + + ret = agp_bind_memory(mem, node->start); + if (ret) +- printk(KERN_ERR TTM_PFX "AGP Bind memory failed.\n"); ++ pr_err("AGP Bind memory failed\n"); + + return ret; + } + +-static int ttm_agp_unbind(struct ttm_backend *backend) ++static int ttm_agp_unbind(struct ttm_tt *ttm) + { +- struct ttm_agp_backend *agp_be = +- container_of(backend, struct ttm_agp_backend, backend); +- +- if (agp_be->mem->is_bound) +- return agp_unbind_memory(agp_be->mem); +- else +- return 0; +-} ++ struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); + +-static void ttm_agp_clear(struct ttm_backend *backend) +-{ +- struct ttm_agp_backend *agp_be = +- container_of(backend, struct ttm_agp_backend, backend); +- struct agp_memory *mem = agp_be->mem; +- +- if (mem) { +- ttm_agp_unbind(backend); +- agp_free_memory(mem); ++ if (agp_be->mem) { ++ if (agp_be->mem->is_bound) ++ return agp_unbind_memory(agp_be->mem); ++ agp_free_memory(agp_be->mem); ++ agp_be->mem = NULL; + } +- agp_be->mem = NULL; ++ return 0; + } + +-static void ttm_agp_destroy(struct ttm_backend *backend) ++static void ttm_agp_destroy(struct ttm_tt *ttm) + { +- struct ttm_agp_backend *agp_be = +- container_of(backend, struct ttm_agp_backend, backend); ++ struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); + + if (agp_be->mem) +- ttm_agp_clear(backend); ++ ttm_agp_unbind(ttm); ++ ttm_tt_fini(ttm); + kfree(agp_be); + } + + static struct ttm_backend_func ttm_agp_func = { +- .populate = ttm_agp_populate, +- .clear = ttm_agp_clear, + .bind = ttm_agp_bind, + .unbind = ttm_agp_unbind, + .destroy = ttm_agp_destroy, + }; + +-struct ttm_backend *ttm_agp_backend_init(struct ttm_bo_device *bdev, +- struct agp_bridge_data *bridge) ++struct ttm_tt *ttm_agp_tt_create(struct ttm_bo_device *bdev, ++ struct agp_bridge_data *bridge, ++ unsigned long size, uint32_t page_flags, ++ struct page *dummy_read_page) + { + struct ttm_agp_backend *agp_be; + +@@ -143,10 +123,29 @@ struct ttm_backend *ttm_agp_backend_init(struct ttm_bo_device *bdev, + + agp_be->mem = NULL; + agp_be->bridge = bridge; +- agp_be->backend.func = &ttm_agp_func; +- agp_be->backend.bdev = bdev; +- return &agp_be->backend; ++ agp_be->ttm.func = &ttm_agp_func; ++ ++ if (ttm_tt_init(&agp_be->ttm, bdev, size, page_flags, dummy_read_page)) { ++ return NULL; ++ } ++ ++ return &agp_be->ttm; ++} ++EXPORT_SYMBOL(ttm_agp_tt_create); ++ ++int ttm_agp_tt_populate(struct ttm_tt *ttm) ++{ ++ if (ttm->state != tt_unpopulated) ++ return 0; ++ ++ return ttm_pool_populate(ttm); ++} ++EXPORT_SYMBOL(ttm_agp_tt_populate); ++ ++void ttm_agp_tt_unpopulate(struct ttm_tt *ttm) ++{ ++ ttm_pool_unpopulate(ttm); + } +-EXPORT_SYMBOL(ttm_agp_backend_init); ++EXPORT_SYMBOL(ttm_agp_tt_unpopulate); + + #endif +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +index 22a89cd..a67e61b 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -28,6 +28,8 @@ + * Authors: Thomas Hellstrom + */ + ++#define pr_fmt(fmt) "[TTM] " fmt ++ + #include "ttm/ttm_module.h" + #include "ttm/ttm_bo_driver.h" + #include "ttm/ttm_placement.h" +@@ -68,15 +70,13 @@ static void ttm_mem_type_debug(struct ttm_bo_device *bdev, int mem_type) + { + struct ttm_mem_type_manager *man = &bdev->man[mem_type]; + +- printk(KERN_ERR TTM_PFX " has_type: %d\n", man->has_type); +- printk(KERN_ERR TTM_PFX " use_type: %d\n", man->use_type); +- printk(KERN_ERR TTM_PFX " flags: 0x%08X\n", man->flags); +- printk(KERN_ERR TTM_PFX " gpu_offset: 0x%08lX\n", man->gpu_offset); +- printk(KERN_ERR TTM_PFX " size: %llu\n", man->size); +- printk(KERN_ERR TTM_PFX " available_caching: 0x%08X\n", +- man->available_caching); +- printk(KERN_ERR TTM_PFX " default_caching: 0x%08X\n", +- man->default_caching); ++ pr_err(" has_type: %d\n", man->has_type); ++ pr_err(" use_type: %d\n", man->use_type); ++ pr_err(" flags: 0x%08X\n", man->flags); ++ pr_err(" gpu_offset: 0x%08lX\n", man->gpu_offset); ++ pr_err(" size: %llu\n", man->size); ++ pr_err(" available_caching: 0x%08X\n", man->available_caching); ++ pr_err(" default_caching: 0x%08X\n", man->default_caching); + if (mem_type != TTM_PL_SYSTEM) + (*man->func->debug)(man, TTM_PFX); + } +@@ -86,16 +86,16 @@ static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, + { + int i, ret, mem_type; + +- printk(KERN_ERR TTM_PFX "No space for %p (%lu pages, %luK, %luM)\n", +- bo, bo->mem.num_pages, bo->mem.size >> 10, +- bo->mem.size >> 20); ++ pr_err("No space for %p (%lu pages, %luK, %luM)\n", ++ bo, bo->mem.num_pages, bo->mem.size >> 10, ++ bo->mem.size >> 20); + for (i = 0; i < placement->num_placement; i++) { + ret = ttm_mem_type_from_flags(placement->placement[i], + &mem_type); + if (ret) + return; +- printk(KERN_ERR TTM_PFX " placement[%d]=0x%08X (%d)\n", +- i, placement->placement[i], mem_type); ++ pr_err(" placement[%d]=0x%08X (%d)\n", ++ i, placement->placement[i], mem_type); + ttm_mem_type_debug(bo->bdev, mem_type); + } + } +@@ -137,6 +137,7 @@ static void ttm_bo_release_list(struct kref *list_kref) + struct ttm_buffer_object *bo = + container_of(list_kref, struct ttm_buffer_object, list_kref); + struct ttm_bo_device *bdev = bo->bdev; ++ size_t acc_size = bo->acc_size; + + BUG_ON(atomic_read(&bo->list_kref.refcount)); + BUG_ON(atomic_read(&bo->kref.refcount)); +@@ -152,9 +153,9 @@ static void ttm_bo_release_list(struct kref *list_kref) + if (bo->destroy) + bo->destroy(bo); + else { +- ttm_mem_global_free(bdev->glob->mem_glob, bo->acc_size); + kfree(bo); + } ++ ttm_mem_global_free(bdev->glob->mem_glob, acc_size); + } + + int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo, bool interruptible) +@@ -337,29 +338,13 @@ static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc) + if (zero_alloc) + page_flags |= TTM_PAGE_FLAG_ZERO_ALLOC; + case ttm_bo_type_kernel: +- bo->ttm = ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT, +- page_flags, glob->dummy_read_page); ++ bo->ttm = bdev->driver->ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT, ++ page_flags, glob->dummy_read_page); + if (unlikely(bo->ttm == NULL)) + ret = -ENOMEM; + break; +- case ttm_bo_type_user: +- bo->ttm = ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT, +- page_flags | TTM_PAGE_FLAG_USER, +- glob->dummy_read_page); +- if (unlikely(bo->ttm == NULL)) { +- ret = -ENOMEM; +- break; +- } +- +- ret = ttm_tt_set_user(bo->ttm, current, +- bo->buffer_start, bo->num_pages); +- if (unlikely(ret != 0)) { +- ttm_tt_destroy(bo->ttm); +- bo->ttm = NULL; +- } +- break; + default: +- printk(KERN_ERR TTM_PFX "Illegal buffer object type\n"); ++ pr_err("Illegal buffer object type\n"); + ret = -EINVAL; + break; + } +@@ -431,14 +416,25 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, + else + ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, mem); + +- if (ret) ++ if (ret) { ++ if (bdev->driver->move_notify) { ++ struct ttm_mem_reg tmp_mem = *mem; ++ *mem = bo->mem; ++ bo->mem = tmp_mem; ++ bdev->driver->move_notify(bo, mem); ++ bo->mem = *mem; ++ } ++ + goto out_err; ++ } + + moved: + if (bo->evicted) { +- ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement); +- if (ret) +- printk(KERN_ERR TTM_PFX "Can not flush read caches\n"); ++ if (bdev->driver->invalidate_caches) { ++ ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement); ++ if (ret) ++ pr_err("Can not flush read caches\n"); ++ } + bo->evicted = false; + } + +@@ -472,6 +468,9 @@ out_err: + + static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) + { ++ if (bo->bdev->driver->move_notify) ++ bo->bdev->driver->move_notify(bo, NULL); ++ + if (bo->ttm) { + ttm_tt_unbind(bo->ttm); + ttm_tt_destroy(bo->ttm); +@@ -737,9 +736,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible, + + if (unlikely(ret != 0)) { + if (ret != -ERESTARTSYS) { +- printk(KERN_ERR TTM_PFX +- "Failed to expire sync object before " +- "buffer eviction.\n"); ++ pr_err("Failed to expire sync object before buffer eviction\n"); + } + goto out; + } +@@ -760,9 +757,8 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible, + no_wait_reserve, no_wait_gpu); + if (ret) { + if (ret != -ERESTARTSYS) { +- printk(KERN_ERR TTM_PFX +- "Failed to find memory space for " +- "buffer 0x%p eviction.\n", bo); ++ pr_err("Failed to find memory space for buffer 0x%p eviction\n", ++ bo); + ttm_bo_mem_space_debug(bo, &placement); + } + goto out; +@@ -772,7 +768,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible, + no_wait_reserve, no_wait_gpu); + if (ret) { + if (ret != -ERESTARTSYS) +- printk(KERN_ERR TTM_PFX "Buffer eviction failed\n"); ++ pr_err("Buffer eviction failed\n"); + ttm_bo_mem_put(bo, &evict_mem); + goto out; + } +@@ -913,16 +909,12 @@ static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man, + } + + static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man, +- bool disallow_fixed, + uint32_t mem_type, + uint32_t proposed_placement, + uint32_t *masked_placement) + { + uint32_t cur_flags = ttm_bo_type_flags(mem_type); + +- if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && disallow_fixed) +- return false; +- + if ((cur_flags & proposed_placement & TTM_PL_MASK_MEM) == 0) + return false; + +@@ -967,7 +959,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, + man = &bdev->man[mem_type]; + + type_ok = ttm_bo_mt_compatible(man, +- bo->type == ttm_bo_type_user, + mem_type, + placement->placement[i], + &cur_flags); +@@ -1015,7 +1006,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, + if (!man->has_type) + continue; + if (!ttm_bo_mt_compatible(man, +- bo->type == ttm_bo_type_user, + mem_type, + placement->busy_placement[i], + &cur_flags)) +@@ -1193,15 +1183,27 @@ int ttm_bo_init(struct ttm_bo_device *bdev, + { + int ret = 0; + unsigned long num_pages; ++ struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; ++ ++ ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); ++ if (ret) { ++ pr_err("Out of kernel memory\n"); ++ if (destroy) ++ (*destroy)(bo); ++ else ++ kfree(bo); ++ return -ENOMEM; ++ } + + size += buffer_start & ~PAGE_MASK; + num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; + if (num_pages == 0) { +- printk(KERN_ERR TTM_PFX "Illegal buffer object size.\n"); ++ pr_err("Illegal buffer object size\n"); + if (destroy) + (*destroy)(bo); + else + kfree(bo); ++ ttm_mem_global_free(mem_glob, acc_size); + return -EINVAL; + } + bo->destroy = destroy; +@@ -1263,14 +1265,34 @@ out_err: + } + EXPORT_SYMBOL(ttm_bo_init); + +-static inline size_t ttm_bo_size(struct ttm_bo_global *glob, +- unsigned long num_pages) ++size_t ttm_bo_acc_size(struct ttm_bo_device *bdev, ++ unsigned long bo_size, ++ unsigned struct_size) + { +- size_t page_array_size = (num_pages * sizeof(void *) + PAGE_SIZE - 1) & +- PAGE_MASK; ++ unsigned npages = (PAGE_ALIGN(bo_size)) >> PAGE_SHIFT; ++ size_t size = 0; ++ ++ size += ttm_round_pot(struct_size); ++ size += PAGE_ALIGN(npages * sizeof(void *)); ++ size += ttm_round_pot(sizeof(struct ttm_tt)); ++ return size; ++} ++EXPORT_SYMBOL(ttm_bo_acc_size); + +- return glob->ttm_bo_size + 2 * page_array_size; ++size_t ttm_bo_dma_acc_size(struct ttm_bo_device *bdev, ++ unsigned long bo_size, ++ unsigned struct_size) ++{ ++ unsigned npages = (PAGE_ALIGN(bo_size)) >> PAGE_SHIFT; ++ size_t size = 0; ++ ++ size += ttm_round_pot(struct_size); ++ size += PAGE_ALIGN(npages * sizeof(void *)); ++ size += PAGE_ALIGN(npages * sizeof(dma_addr_t)); ++ size += ttm_round_pot(sizeof(struct ttm_dma_tt)); ++ return size; + } ++EXPORT_SYMBOL(ttm_bo_dma_acc_size); + + int ttm_bo_create(struct ttm_bo_device *bdev, + unsigned long size, +@@ -1283,22 +1305,14 @@ int ttm_bo_create(struct ttm_bo_device *bdev, + struct ttm_buffer_object **p_bo) + { + struct ttm_buffer_object *bo; +- struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; ++ size_t acc_size; + int ret; + +- size_t acc_size = +- ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT); +- ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); +- if (unlikely(ret != 0)) +- return ret; +- + bo = kzalloc(sizeof(*bo), GFP_KERNEL); +- +- if (unlikely(bo == NULL)) { +- ttm_mem_global_free(mem_glob, acc_size); ++ if (unlikely(bo == NULL)) + return -ENOMEM; +- } + ++ acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object)); + ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment, + buffer_start, interruptible, + persistent_swap_storage, acc_size, NULL); +@@ -1328,8 +1342,7 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, + if (allow_errors) { + return ret; + } else { +- printk(KERN_ERR TTM_PFX +- "Cleanup eviction failed\n"); ++ pr_err("Cleanup eviction failed\n"); + } + } + spin_lock(&glob->lru_lock); +@@ -1344,14 +1357,14 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) + int ret = -EINVAL; + + if (mem_type >= TTM_NUM_MEM_TYPES) { +- printk(KERN_ERR TTM_PFX "Illegal memory type %d\n", mem_type); ++ pr_err("Illegal memory type %d\n", mem_type); + return ret; + } + man = &bdev->man[mem_type]; + + if (!man->has_type) { +- printk(KERN_ERR TTM_PFX "Trying to take down uninitialized " +- "memory manager type %u\n", mem_type); ++ pr_err("Trying to take down uninitialized memory manager type %u\n", ++ mem_type); + return ret; + } + +@@ -1374,16 +1387,12 @@ int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) + struct ttm_mem_type_manager *man = &bdev->man[mem_type]; + + if (mem_type == 0 || mem_type >= TTM_NUM_MEM_TYPES) { +- printk(KERN_ERR TTM_PFX +- "Illegal memory manager memory type %u.\n", +- mem_type); ++ pr_err("Illegal memory manager memory type %u\n", mem_type); + return -EINVAL; + } + + if (!man->has_type) { +- printk(KERN_ERR TTM_PFX +- "Memory type %u has not been initialized.\n", +- mem_type); ++ pr_err("Memory type %u has not been initialized\n", mem_type); + return 0; + } + +@@ -1468,18 +1477,10 @@ int ttm_bo_global_init(struct drm_global_reference *ref) + ttm_mem_init_shrink(&glob->shrink, ttm_bo_swapout); + ret = ttm_mem_register_shrink(glob->mem_glob, &glob->shrink); + if (unlikely(ret != 0)) { +- printk(KERN_ERR TTM_PFX +- "Could not register buffer object swapout.\n"); ++ pr_err("Could not register buffer object swapout\n"); + goto out_no_shrink; + } + +- glob->ttm_bo_extra_size = +- ttm_round_pot(sizeof(struct ttm_tt)) + +- ttm_round_pot(sizeof(struct ttm_backend)); +- +- glob->ttm_bo_size = glob->ttm_bo_extra_size + +- ttm_round_pot(sizeof(struct ttm_buffer_object)); +- + atomic_set(&glob->bo_count, 0); + + ret = kobject_init_and_add( +@@ -1509,9 +1510,8 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev) + man->use_type = false; + if ((i != TTM_PL_SYSTEM) && ttm_bo_clean_mm(bdev, i)) { + ret = -EBUSY; +- printk(KERN_ERR TTM_PFX +- "DRM memory manager type %d " +- "is not clean.\n", i); ++ pr_err("DRM memory manager type %d is not clean\n", ++ i); + } + man->has_type = false; + } +diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c +index 082fcae..2d69262 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo_util.c ++++ b/drivers/gpu/drm/ttm/ttm_bo_util.c +@@ -244,7 +244,7 @@ static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src, + unsigned long page, + pgprot_t prot) + { +- struct page *d = ttm_tt_get_page(ttm, page); ++ struct page *d = ttm->pages[page]; + void *dst; + + if (!d) +@@ -281,7 +281,7 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst, + unsigned long page, + pgprot_t prot) + { +- struct page *s = ttm_tt_get_page(ttm, page); ++ struct page *s = ttm->pages[page]; + void *src; + + if (!s) +@@ -342,6 +342,14 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, + if (old_iomap == NULL && ttm == NULL) + goto out2; + ++ /* TTM might be null for moves within the same region. ++ */ ++ if (ttm && ttm->state == tt_unpopulated) { ++ ret = ttm->bdev->driver->ttm_tt_populate(ttm); ++ if (ret) ++ goto out1; ++ } ++ + add = 0; + dir = 1; + +@@ -439,6 +447,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, + kref_init(&fbo->list_kref); + kref_init(&fbo->kref); + fbo->destroy = &ttm_transfered_destroy; ++ fbo->acc_size = 0; + + *new_obj = fbo; + return 0; +@@ -502,10 +511,16 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, + { + struct ttm_mem_reg *mem = &bo->mem; pgprot_t prot; + struct ttm_tt *ttm = bo->ttm; +- struct page *d; +- int i; ++ int ret; + + BUG_ON(!ttm); ++ ++ if (ttm->state == tt_unpopulated) { ++ ret = ttm->bdev->driver->ttm_tt_populate(ttm); ++ if (ret) ++ return ret; ++ } ++ + if (num_pages == 1 && (mem->placement & TTM_PL_FLAG_CACHED)) { + /* + * We're mapping a single page, and the desired +@@ -513,18 +528,9 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, + */ + + map->bo_kmap_type = ttm_bo_map_kmap; +- map->page = ttm_tt_get_page(ttm, start_page); ++ map->page = ttm->pages[start_page]; + map->virtual = kmap(map->page); + } else { +- /* +- * Populate the part we're mapping; +- */ +- for (i = start_page; i < start_page + num_pages; ++i) { +- d = ttm_tt_get_page(ttm, i); +- if (!d) +- return -ENOMEM; +- } +- + /* + * We need to use vmap to get the desired page protection + * or to make the buffer object look contiguous. +diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c +index e223175..a877813 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c ++++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c +@@ -28,6 +28,8 @@ + * Authors: Thomas Hellstrom + */ + ++#define pr_fmt(fmt) "[TTM] " fmt ++ + #include + #include + #include +@@ -144,9 +146,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) + } + + page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + +- vma->vm_pgoff - bo->vm_node->start; +- page_last = vma_pages(vma) + vma->vm_pgoff - +- bo->vm_node->start; ++ bo->vm_node->start - vma->vm_pgoff; ++ page_last = ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + ++ bo->vm_node->start - vma->vm_pgoff; + + if (unlikely(page_offset >= bo->num_pages)) { + retval = VM_FAULT_SIGBUS; +@@ -174,18 +176,23 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) + vma->vm_page_prot = (bo->mem.placement & TTM_PL_FLAG_CACHED) ? + vm_get_page_prot(vma->vm_flags) : + ttm_io_prot(bo->mem.placement, vma->vm_page_prot); ++ ++ /* Allocate all page at once, most common usage */ ++ if (ttm->bdev->driver->ttm_tt_populate(ttm)) { ++ retval = VM_FAULT_OOM; ++ goto out_io_unlock; ++ } + } + + /* + * Speculatively prefault a number of pages. Only error on + * first page. + */ +- + for (i = 0; i < TTM_BO_VM_NUM_PREFAULT; ++i) { + if (bo->mem.bus.is_iomem) + pfn = ((bo->mem.bus.base + bo->mem.bus.offset) >> PAGE_SHIFT) + page_offset; + else { +- page = ttm_tt_get_page(ttm, page_offset); ++ page = ttm->pages[page_offset]; + if (unlikely(!page && i == 0)) { + retval = VM_FAULT_OOM; + goto out_io_unlock; +@@ -257,8 +264,7 @@ int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma, + read_unlock(&bdev->vm_lock); + + if (unlikely(bo == NULL)) { +- printk(KERN_ERR TTM_PFX +- "Could not find buffer object to map.\n"); ++ pr_err("Could not find buffer object to map\n"); + return -EINVAL; + } + +diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c +index e70ddd8..23d2ecb 100644 +--- a/drivers/gpu/drm/ttm/ttm_memory.c ++++ b/drivers/gpu/drm/ttm/ttm_memory.c +@@ -25,6 +25,8 @@ + * + **************************************************************************/ + ++#define pr_fmt(fmt) "[TTM] " fmt ++ + #include "ttm/ttm_memory.h" + #include "ttm/ttm_module.h" + #include "ttm/ttm_page_alloc.h" +@@ -74,9 +76,8 @@ static void ttm_mem_zone_kobj_release(struct kobject *kobj) + struct ttm_mem_zone *zone = + container_of(kobj, struct ttm_mem_zone, kobj); + +- printk(KERN_INFO TTM_PFX +- "Zone %7s: Used memory at exit: %llu kiB.\n", +- zone->name, (unsigned long long) zone->used_mem >> 10); ++ pr_info("Zone %7s: Used memory at exit: %llu kiB\n", ++ zone->name, (unsigned long long)zone->used_mem >> 10); + kfree(zone); + } + +@@ -390,11 +391,11 @@ int ttm_mem_global_init(struct ttm_mem_global *glob) + #endif + for (i = 0; i < glob->num_zones; ++i) { + zone = glob->zones[i]; +- printk(KERN_INFO TTM_PFX +- "Zone %7s: Available graphics memory: %llu kiB.\n", +- zone->name, (unsigned long long) zone->max_mem >> 10); ++ pr_info("Zone %7s: Available graphics memory: %llu kiB\n", ++ zone->name, (unsigned long long)zone->max_mem >> 10); + } + ttm_page_alloc_init(glob, glob->zone_kernel->max_mem/(2*PAGE_SIZE)); ++ ttm_dma_page_alloc_init(glob, glob->zone_kernel->max_mem/(2*PAGE_SIZE)); + return 0; + out_no_zone: + ttm_mem_global_release(glob); +@@ -409,6 +410,7 @@ void ttm_mem_global_release(struct ttm_mem_global *glob) + + /* let the page allocator first stop the shrink work. */ + ttm_page_alloc_fini(); ++ ttm_dma_page_alloc_fini(); + + flush_workqueue(glob->swap_queue); + destroy_workqueue(glob->swap_queue); +diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c +index 93577f2..68daca4 100644 +--- a/drivers/gpu/drm/ttm/ttm_object.c ++++ b/drivers/gpu/drm/ttm/ttm_object.c +@@ -49,6 +49,8 @@ + * for fast lookup of ref objects given a base object. + */ + ++#define pr_fmt(fmt) "[TTM] " fmt ++ + #include "ttm/ttm_object.h" + #include "ttm/ttm_module.h" + #include +@@ -232,8 +234,7 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile, + return NULL; + + if (tfile != base->tfile && !base->shareable) { +- printk(KERN_ERR TTM_PFX +- "Attempted access of non-shareable object.\n"); ++ pr_err("Attempted access of non-shareable object\n"); + ttm_base_object_unref(&base); + return NULL; + } +diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c +index 508c64c..578207e 100644 +--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c ++++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c +@@ -30,6 +30,9 @@ + * - Use page->lru to keep a free list + * - doesn't track currently in use pages + */ ++ ++#define pr_fmt(fmt) "[TTM] " fmt ++ + #include + #include + #include +@@ -167,18 +170,13 @@ static ssize_t ttm_pool_store(struct kobject *kobj, + m->options.small = val; + else if (attr == &ttm_page_pool_alloc_size) { + if (val > NUM_PAGES_TO_ALLOC*8) { +- printk(KERN_ERR TTM_PFX +- "Setting allocation size to %lu " +- "is not allowed. Recommended size is " +- "%lu\n", ++ pr_err("Setting allocation size to %lu is not allowed. Recommended size is %lu\n", + NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7), + NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10)); + return size; + } else if (val > NUM_PAGES_TO_ALLOC) { +- printk(KERN_WARNING TTM_PFX +- "Setting allocation size to " +- "larger than %lu is not recommended.\n", +- NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10)); ++ pr_warn("Setting allocation size to larger than %lu is not recommended\n", ++ NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10)); + } + m->options.alloc_size = val; + } +@@ -279,8 +277,7 @@ static void ttm_pages_put(struct page *pages[], unsigned npages) + { + unsigned i; + if (set_pages_array_wb(pages, npages)) +- printk(KERN_ERR TTM_PFX "Failed to set %d pages to wb!\n", +- npages); ++ pr_err("Failed to set %d pages to wb!\n", npages); + for (i = 0; i < npages; ++i) + __free_page(pages[i]); + } +@@ -315,8 +312,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free) + pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), + GFP_KERNEL); + if (!pages_to_free) { +- printk(KERN_ERR TTM_PFX +- "Failed to allocate memory for pool free operation.\n"); ++ pr_err("Failed to allocate memory for pool free operation\n"); + return 0; + } + +@@ -398,18 +394,13 @@ static int ttm_pool_get_num_unused_pages(void) + static int ttm_pool_mm_shrink(struct shrinker *shrink, + struct shrink_control *sc) + { +- static DEFINE_MUTEX(lock); +- static unsigned start_pool; ++ static atomic_t start_pool = ATOMIC_INIT(0); + unsigned i; +- unsigned pool_offset; ++ unsigned pool_offset = atomic_add_return(1, &start_pool); + struct ttm_page_pool *pool; + int shrink_pages = sc->nr_to_scan; + +- if (shrink_pages == 0) +- goto out; +- if (!mutex_trylock(&lock)) +- return -1; +- pool_offset = ++start_pool % NUM_POOLS; ++ pool_offset = pool_offset % NUM_POOLS; + /* select start pool in round robin fashion */ + for (i = 0; i < NUM_POOLS; ++i) { + unsigned nr_free = shrink_pages; +@@ -418,8 +409,6 @@ static int ttm_pool_mm_shrink(struct shrinker *shrink, + pool = &_manager->pools[(i + pool_offset)%NUM_POOLS]; + shrink_pages = ttm_page_pool_free(pool, nr_free); + } +- mutex_unlock(&lock); +-out: + /* return estimated number of unused pages in pool */ + return ttm_pool_get_num_unused_pages(); + } +@@ -445,16 +434,12 @@ static int ttm_set_pages_caching(struct page **pages, + case tt_uncached: + r = set_pages_array_uc(pages, cpages); + if (r) +- printk(KERN_ERR TTM_PFX +- "Failed to set %d pages to uc!\n", +- cpages); ++ pr_err("Failed to set %d pages to uc!\n", cpages); + break; + case tt_wc: + r = set_pages_array_wc(pages, cpages); + if (r) +- printk(KERN_ERR TTM_PFX +- "Failed to set %d pages to wc!\n", +- cpages); ++ pr_err("Failed to set %d pages to wc!\n", cpages); + break; + default: + break; +@@ -499,8 +484,7 @@ static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags, + caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL); + + if (!caching_array) { +- printk(KERN_ERR TTM_PFX +- "Unable to allocate table for new pages."); ++ pr_err("Unable to allocate table for new pages\n"); + return -ENOMEM; + } + +@@ -508,7 +492,7 @@ static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags, + p = alloc_page(gfp_flags); + + if (!p) { +- printk(KERN_ERR TTM_PFX "Unable to get page %u.\n", i); ++ pr_err("Unable to get page %u\n", i); + + /* store already allocated pages in the pool after + * setting the caching state */ +@@ -606,8 +590,7 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, + ++pool->nrefills; + pool->npages += alloc_size; + } else { +- printk(KERN_ERR TTM_PFX +- "Failed to fill pool (%p).", pool); ++ pr_err("Failed to fill pool (%p)\n", pool); + /* If we have any pages left put them to the pool. */ + list_for_each_entry(p, &pool->list, lru) { + ++cpages; +@@ -626,8 +609,10 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, + * @return count of pages still required to fulfill the request. + */ + static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool, +- struct list_head *pages, int ttm_flags, +- enum ttm_caching_state cstate, unsigned count) ++ struct list_head *pages, ++ int ttm_flags, ++ enum ttm_caching_state cstate, ++ unsigned count) + { + unsigned long irq_flags; + struct list_head *p; +@@ -667,17 +652,63 @@ out: + return count; + } + ++/* Put all pages in pages list to correct pool to wait for reuse */ ++static void ttm_put_pages(struct page **pages, unsigned npages, int flags, ++ enum ttm_caching_state cstate) ++{ ++ unsigned long irq_flags; ++ struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); ++ unsigned i; ++ ++ if (pool == NULL) { ++ /* No pool for this memory type so free the pages */ ++ for (i = 0; i < npages; i++) { ++ if (pages[i]) { ++ if (page_count(pages[i]) != 1) ++ pr_err("Erroneous page count. Leaking pages.\n"); ++ __free_page(pages[i]); ++ pages[i] = NULL; ++ } ++ } ++ return; ++ } ++ ++ spin_lock_irqsave(&pool->lock, irq_flags); ++ for (i = 0; i < npages; i++) { ++ if (pages[i]) { ++ if (page_count(pages[i]) != 1) ++ pr_err("Erroneous page count. Leaking pages.\n"); ++ list_add_tail(&pages[i]->lru, &pool->list); ++ pages[i] = NULL; ++ pool->npages++; ++ } ++ } ++ /* Check that we don't go over the pool limit */ ++ npages = 0; ++ if (pool->npages > _manager->options.max_size) { ++ npages = pool->npages - _manager->options.max_size; ++ /* free at least NUM_PAGES_TO_ALLOC number of pages ++ * to reduce calls to set_memory_wb */ ++ if (npages < NUM_PAGES_TO_ALLOC) ++ npages = NUM_PAGES_TO_ALLOC; ++ } ++ spin_unlock_irqrestore(&pool->lock, irq_flags); ++ if (npages) ++ ttm_page_pool_free(pool, npages); ++} ++ + /* + * On success pages list will hold count number of correctly + * cached pages. + */ +-int ttm_get_pages(struct list_head *pages, int flags, +- enum ttm_caching_state cstate, unsigned count, +- dma_addr_t *dma_address) ++static int ttm_get_pages(struct page **pages, unsigned npages, int flags, ++ enum ttm_caching_state cstate) + { + struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); ++ struct list_head plist; + struct page *p = NULL; + gfp_t gfp_flags = GFP_USER; ++ unsigned count; + int r; + + /* set zero flag for page allocation if required */ +@@ -691,30 +722,33 @@ int ttm_get_pages(struct list_head *pages, int flags, + else + gfp_flags |= GFP_HIGHUSER; + +- for (r = 0; r < count; ++r) { ++ for (r = 0; r < npages; ++r) { + p = alloc_page(gfp_flags); + if (!p) { + +- printk(KERN_ERR TTM_PFX +- "Unable to allocate page."); ++ pr_err("Unable to allocate page\n"); + return -ENOMEM; + } + +- list_add(&p->lru, pages); ++ pages[r] = p; + } + return 0; + } + +- + /* combine zero flag to pool flags */ + gfp_flags |= pool->gfp_flags; + + /* First we take pages from the pool */ +- count = ttm_page_pool_get_pages(pool, pages, flags, cstate, count); ++ INIT_LIST_HEAD(&plist); ++ npages = ttm_page_pool_get_pages(pool, &plist, flags, cstate, npages); ++ count = 0; ++ list_for_each_entry(p, &plist, lru) { ++ pages[count++] = p; ++ } + + /* clear the pages coming from the pool if requested */ + if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) { +- list_for_each_entry(p, pages, lru) { ++ list_for_each_entry(p, &plist, lru) { + if (PageHighMem(p)) + clear_highpage(p); + else +@@ -723,67 +757,27 @@ int ttm_get_pages(struct list_head *pages, int flags, + } + + /* If pool didn't have enough pages allocate new one. */ +- if (count > 0) { ++ if (npages > 0) { + /* ttm_alloc_new_pages doesn't reference pool so we can run + * multiple requests in parallel. + **/ +- r = ttm_alloc_new_pages(pages, gfp_flags, flags, cstate, count); ++ INIT_LIST_HEAD(&plist); ++ r = ttm_alloc_new_pages(&plist, gfp_flags, flags, cstate, npages); ++ list_for_each_entry(p, &plist, lru) { ++ pages[count++] = p; ++ } + if (r) { + /* If there is any pages in the list put them back to + * the pool. */ +- printk(KERN_ERR TTM_PFX +- "Failed to allocate extra pages " +- "for large request."); +- ttm_put_pages(pages, 0, flags, cstate, NULL); ++ pr_err("Failed to allocate extra pages for large request\n"); ++ ttm_put_pages(pages, count, flags, cstate); + return r; + } + } + +- + return 0; + } + +-/* Put all pages in pages list to correct pool to wait for reuse */ +-void ttm_put_pages(struct list_head *pages, unsigned page_count, int flags, +- enum ttm_caching_state cstate, dma_addr_t *dma_address) +-{ +- unsigned long irq_flags; +- struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); +- struct page *p, *tmp; +- +- if (pool == NULL) { +- /* No pool for this memory type so free the pages */ +- +- list_for_each_entry_safe(p, tmp, pages, lru) { +- __free_page(p); +- } +- /* Make the pages list empty */ +- INIT_LIST_HEAD(pages); +- return; +- } +- if (page_count == 0) { +- list_for_each_entry_safe(p, tmp, pages, lru) { +- ++page_count; +- } +- } +- +- spin_lock_irqsave(&pool->lock, irq_flags); +- list_splice_init(pages, &pool->list); +- pool->npages += page_count; +- /* Check that we don't go over the pool limit */ +- page_count = 0; +- if (pool->npages > _manager->options.max_size) { +- page_count = pool->npages - _manager->options.max_size; +- /* free at least NUM_PAGES_TO_ALLOC number of pages +- * to reduce calls to set_memory_wb */ +- if (page_count < NUM_PAGES_TO_ALLOC) +- page_count = NUM_PAGES_TO_ALLOC; +- } +- spin_unlock_irqrestore(&pool->lock, irq_flags); +- if (page_count) +- ttm_page_pool_free(pool, page_count); +-} +- + static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, int flags, + char *name) + { +@@ -801,7 +795,7 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages) + + WARN_ON(_manager); + +- printk(KERN_INFO TTM_PFX "Initializing pool allocator.\n"); ++ pr_info("Initializing pool allocator\n"); + + _manager = kzalloc(sizeof(*_manager), GFP_KERNEL); + +@@ -836,7 +830,7 @@ void ttm_page_alloc_fini(void) + { + int i; + +- printk(KERN_INFO TTM_PFX "Finalizing pool allocator.\n"); ++ pr_info("Finalizing pool allocator\n"); + ttm_pool_mm_shrink_fini(_manager); + + for (i = 0; i < NUM_POOLS; ++i) +@@ -846,6 +840,62 @@ void ttm_page_alloc_fini(void) + _manager = NULL; + } + ++int ttm_pool_populate(struct ttm_tt *ttm) ++{ ++ struct ttm_mem_global *mem_glob = ttm->glob->mem_glob; ++ unsigned i; ++ int ret; ++ ++ if (ttm->state != tt_unpopulated) ++ return 0; ++ ++ for (i = 0; i < ttm->num_pages; ++i) { ++ ret = ttm_get_pages(&ttm->pages[i], 1, ++ ttm->page_flags, ++ ttm->caching_state); ++ if (ret != 0) { ++ ttm_pool_unpopulate(ttm); ++ return -ENOMEM; ++ } ++ ++ ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i], ++ false, false); ++ if (unlikely(ret != 0)) { ++ ttm_pool_unpopulate(ttm); ++ return -ENOMEM; ++ } ++ } ++ ++ if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) { ++ ret = ttm_tt_swapin(ttm); ++ if (unlikely(ret != 0)) { ++ ttm_pool_unpopulate(ttm); ++ return ret; ++ } ++ } ++ ++ ttm->state = tt_unbound; ++ return 0; ++} ++EXPORT_SYMBOL(ttm_pool_populate); ++ ++void ttm_pool_unpopulate(struct ttm_tt *ttm) ++{ ++ unsigned i; ++ ++ for (i = 0; i < ttm->num_pages; ++i) { ++ if (ttm->pages[i]) { ++ ttm_mem_global_free_page(ttm->glob->mem_glob, ++ ttm->pages[i]); ++ ttm_put_pages(&ttm->pages[i], 1, ++ ttm->page_flags, ++ ttm->caching_state); ++ } ++ } ++ ttm->state = tt_unpopulated; ++} ++EXPORT_SYMBOL(ttm_pool_unpopulate); ++ + int ttm_page_alloc_debugfs(struct seq_file *m, void *data) + { + struct ttm_page_pool *p; +diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +new file mode 100644 +index 0000000..4f9e548 +--- /dev/null ++++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +@@ -0,0 +1,1134 @@ ++/* ++ * Copyright 2011 (c) Oracle Corp. ++ ++ * 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, sub license, ++ * 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 (including the ++ * next paragraph) 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 NON-INFRINGEMENT. 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. ++ * ++ * Author: Konrad Rzeszutek Wilk ++ */ ++ ++/* ++ * A simple DMA pool losely based on dmapool.c. It has certain advantages ++ * over the DMA pools: ++ * - Pool collects resently freed pages for reuse (and hooks up to ++ * the shrinker). ++ * - Tracks currently in use pages ++ * - Tracks whether the page is UC, WB or cached (and reverts to WB ++ * when freed). ++ */ ++ ++#define pr_fmt(fmt) "[TTM] " fmt ++ ++#include ++#include ++#include /* for seq_printf */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ttm/ttm_bo_driver.h" ++#include "ttm/ttm_page_alloc.h" ++#ifdef TTM_HAS_AGP ++#include ++#endif ++ ++#define NUM_PAGES_TO_ALLOC (PAGE_SIZE/sizeof(struct page *)) ++#define SMALL_ALLOCATION 4 ++#define FREE_ALL_PAGES (~0U) ++/* times are in msecs */ ++#define IS_UNDEFINED (0) ++#define IS_WC (1<<1) ++#define IS_UC (1<<2) ++#define IS_CACHED (1<<3) ++#define IS_DMA32 (1<<4) ++ ++enum pool_type { ++ POOL_IS_UNDEFINED, ++ POOL_IS_WC = IS_WC, ++ POOL_IS_UC = IS_UC, ++ POOL_IS_CACHED = IS_CACHED, ++ POOL_IS_WC_DMA32 = IS_WC | IS_DMA32, ++ POOL_IS_UC_DMA32 = IS_UC | IS_DMA32, ++ POOL_IS_CACHED_DMA32 = IS_CACHED | IS_DMA32, ++}; ++/* ++ * The pool structure. There are usually six pools: ++ * - generic (not restricted to DMA32): ++ * - write combined, uncached, cached. ++ * - dma32 (up to 2^32 - so up 4GB): ++ * - write combined, uncached, cached. ++ * for each 'struct device'. The 'cached' is for pages that are actively used. ++ * The other ones can be shrunk by the shrinker API if neccessary. ++ * @pools: The 'struct device->dma_pools' link. ++ * @type: Type of the pool ++ * @lock: Protects the inuse_list and free_list from concurrnet access. Must be ++ * used with irqsave/irqrestore variants because pool allocator maybe called ++ * from delayed work. ++ * @inuse_list: Pool of pages that are in use. The order is very important and ++ * it is in the order that the TTM pages that are put back are in. ++ * @free_list: Pool of pages that are free to be used. No order requirements. ++ * @dev: The device that is associated with these pools. ++ * @size: Size used during DMA allocation. ++ * @npages_free: Count of available pages for re-use. ++ * @npages_in_use: Count of pages that are in use. ++ * @nfrees: Stats when pool is shrinking. ++ * @nrefills: Stats when the pool is grown. ++ * @gfp_flags: Flags to pass for alloc_page. ++ * @name: Name of the pool. ++ * @dev_name: Name derieved from dev - similar to how dev_info works. ++ * Used during shutdown as the dev_info during release is unavailable. ++ */ ++struct dma_pool { ++ struct list_head pools; /* The 'struct device->dma_pools link */ ++ enum pool_type type; ++ spinlock_t lock; ++ struct list_head inuse_list; ++ struct list_head free_list; ++ struct device *dev; ++ unsigned size; ++ unsigned npages_free; ++ unsigned npages_in_use; ++ unsigned long nfrees; /* Stats when shrunk. */ ++ unsigned long nrefills; /* Stats when grown. */ ++ gfp_t gfp_flags; ++ char name[13]; /* "cached dma32" */ ++ char dev_name[64]; /* Constructed from dev */ ++}; ++ ++/* ++ * The accounting page keeping track of the allocated page along with ++ * the DMA address. ++ * @page_list: The link to the 'page_list' in 'struct dma_pool'. ++ * @vaddr: The virtual address of the page ++ * @dma: The bus address of the page. If the page is not allocated ++ * via the DMA API, it will be -1. ++ */ ++struct dma_page { ++ struct list_head page_list; ++ void *vaddr; ++ struct page *p; ++ dma_addr_t dma; ++}; ++ ++/* ++ * Limits for the pool. They are handled without locks because only place where ++ * they may change is in sysfs store. They won't have immediate effect anyway ++ * so forcing serialization to access them is pointless. ++ */ ++ ++struct ttm_pool_opts { ++ unsigned alloc_size; ++ unsigned max_size; ++ unsigned small; ++}; ++ ++/* ++ * Contains the list of all of the 'struct device' and their corresponding ++ * DMA pools. Guarded by _mutex->lock. ++ * @pools: The link to 'struct ttm_pool_manager->pools' ++ * @dev: The 'struct device' associated with the 'pool' ++ * @pool: The 'struct dma_pool' associated with the 'dev' ++ */ ++struct device_pools { ++ struct list_head pools; ++ struct device *dev; ++ struct dma_pool *pool; ++}; ++ ++/* ++ * struct ttm_pool_manager - Holds memory pools for fast allocation ++ * ++ * @lock: Lock used when adding/removing from pools ++ * @pools: List of 'struct device' and 'struct dma_pool' tuples. ++ * @options: Limits for the pool. ++ * @npools: Total amount of pools in existence. ++ * @shrinker: The structure used by [un|]register_shrinker ++ */ ++struct ttm_pool_manager { ++ struct mutex lock; ++ struct list_head pools; ++ struct ttm_pool_opts options; ++ unsigned npools; ++ struct shrinker mm_shrink; ++ struct kobject kobj; ++}; ++ ++static struct ttm_pool_manager *_manager; ++ ++static struct attribute ttm_page_pool_max = { ++ .name = "pool_max_size", ++ .mode = S_IRUGO | S_IWUSR ++}; ++static struct attribute ttm_page_pool_small = { ++ .name = "pool_small_allocation", ++ .mode = S_IRUGO | S_IWUSR ++}; ++static struct attribute ttm_page_pool_alloc_size = { ++ .name = "pool_allocation_size", ++ .mode = S_IRUGO | S_IWUSR ++}; ++ ++static struct attribute *ttm_pool_attrs[] = { ++ &ttm_page_pool_max, ++ &ttm_page_pool_small, ++ &ttm_page_pool_alloc_size, ++ NULL ++}; ++ ++static void ttm_pool_kobj_release(struct kobject *kobj) ++{ ++ struct ttm_pool_manager *m = ++ container_of(kobj, struct ttm_pool_manager, kobj); ++ kfree(m); ++} ++ ++static ssize_t ttm_pool_store(struct kobject *kobj, struct attribute *attr, ++ const char *buffer, size_t size) ++{ ++ struct ttm_pool_manager *m = ++ container_of(kobj, struct ttm_pool_manager, kobj); ++ int chars; ++ unsigned val; ++ chars = sscanf(buffer, "%u", &val); ++ if (chars == 0) ++ return size; ++ ++ /* Convert kb to number of pages */ ++ val = val / (PAGE_SIZE >> 10); ++ ++ if (attr == &ttm_page_pool_max) ++ m->options.max_size = val; ++ else if (attr == &ttm_page_pool_small) ++ m->options.small = val; ++ else if (attr == &ttm_page_pool_alloc_size) { ++ if (val > NUM_PAGES_TO_ALLOC*8) { ++ pr_err("Setting allocation size to %lu is not allowed. Recommended size is %lu\n", ++ NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7), ++ NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10)); ++ return size; ++ } else if (val > NUM_PAGES_TO_ALLOC) { ++ pr_warn("Setting allocation size to larger than %lu is not recommended\n", ++ NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10)); ++ } ++ m->options.alloc_size = val; ++ } ++ ++ return size; ++} ++ ++static ssize_t ttm_pool_show(struct kobject *kobj, struct attribute *attr, ++ char *buffer) ++{ ++ struct ttm_pool_manager *m = ++ container_of(kobj, struct ttm_pool_manager, kobj); ++ unsigned val = 0; ++ ++ if (attr == &ttm_page_pool_max) ++ val = m->options.max_size; ++ else if (attr == &ttm_page_pool_small) ++ val = m->options.small; ++ else if (attr == &ttm_page_pool_alloc_size) ++ val = m->options.alloc_size; ++ ++ val = val * (PAGE_SIZE >> 10); ++ ++ return snprintf(buffer, PAGE_SIZE, "%u\n", val); ++} ++ ++static const struct sysfs_ops ttm_pool_sysfs_ops = { ++ .show = &ttm_pool_show, ++ .store = &ttm_pool_store, ++}; ++ ++static struct kobj_type ttm_pool_kobj_type = { ++ .release = &ttm_pool_kobj_release, ++ .sysfs_ops = &ttm_pool_sysfs_ops, ++ .default_attrs = ttm_pool_attrs, ++}; ++ ++#ifndef CONFIG_X86 ++static int set_pages_array_wb(struct page **pages, int addrinarray) ++{ ++#ifdef TTM_HAS_AGP ++ int i; ++ ++ for (i = 0; i < addrinarray; i++) ++ unmap_page_from_agp(pages[i]); ++#endif ++ return 0; ++} ++ ++static int set_pages_array_wc(struct page **pages, int addrinarray) ++{ ++#ifdef TTM_HAS_AGP ++ int i; ++ ++ for (i = 0; i < addrinarray; i++) ++ map_page_into_agp(pages[i]); ++#endif ++ return 0; ++} ++ ++static int set_pages_array_uc(struct page **pages, int addrinarray) ++{ ++#ifdef TTM_HAS_AGP ++ int i; ++ ++ for (i = 0; i < addrinarray; i++) ++ map_page_into_agp(pages[i]); ++#endif ++ return 0; ++} ++#endif /* for !CONFIG_X86 */ ++ ++static int ttm_set_pages_caching(struct dma_pool *pool, ++ struct page **pages, unsigned cpages) ++{ ++ int r = 0; ++ /* Set page caching */ ++ if (pool->type & IS_UC) { ++ r = set_pages_array_uc(pages, cpages); ++ if (r) ++ pr_err("%s: Failed to set %d pages to uc!\n", ++ pool->dev_name, cpages); ++ } ++ if (pool->type & IS_WC) { ++ r = set_pages_array_wc(pages, cpages); ++ if (r) ++ pr_err("%s: Failed to set %d pages to wc!\n", ++ pool->dev_name, cpages); ++ } ++ return r; ++} ++ ++static void __ttm_dma_free_page(struct dma_pool *pool, struct dma_page *d_page) ++{ ++ dma_addr_t dma = d_page->dma; ++ dma_free_coherent(pool->dev, pool->size, d_page->vaddr, dma); ++ ++ kfree(d_page); ++ d_page = NULL; ++} ++static struct dma_page *__ttm_dma_alloc_page(struct dma_pool *pool) ++{ ++ struct dma_page *d_page; ++ ++ d_page = kmalloc(sizeof(struct dma_page), GFP_KERNEL); ++ if (!d_page) ++ return NULL; ++ ++ d_page->vaddr = dma_alloc_coherent(pool->dev, pool->size, ++ &d_page->dma, ++ pool->gfp_flags); ++ if (d_page->vaddr) ++ d_page->p = virt_to_page(d_page->vaddr); ++ else { ++ kfree(d_page); ++ d_page = NULL; ++ } ++ return d_page; ++} ++static enum pool_type ttm_to_type(int flags, enum ttm_caching_state cstate) ++{ ++ enum pool_type type = IS_UNDEFINED; ++ ++ if (flags & TTM_PAGE_FLAG_DMA32) ++ type |= IS_DMA32; ++ if (cstate == tt_cached) ++ type |= IS_CACHED; ++ else if (cstate == tt_uncached) ++ type |= IS_UC; ++ else ++ type |= IS_WC; ++ ++ return type; ++} ++ ++static void ttm_pool_update_free_locked(struct dma_pool *pool, ++ unsigned freed_pages) ++{ ++ pool->npages_free -= freed_pages; ++ pool->nfrees += freed_pages; ++ ++} ++ ++/* set memory back to wb and free the pages. */ ++static void ttm_dma_pages_put(struct dma_pool *pool, struct list_head *d_pages, ++ struct page *pages[], unsigned npages) ++{ ++ struct dma_page *d_page, *tmp; ++ ++ /* Don't set WB on WB page pool. */ ++ if (npages && !(pool->type & IS_CACHED) && ++ set_pages_array_wb(pages, npages)) ++ pr_err("%s: Failed to set %d pages to wb!\n", ++ pool->dev_name, npages); ++ ++ list_for_each_entry_safe(d_page, tmp, d_pages, page_list) { ++ list_del(&d_page->page_list); ++ __ttm_dma_free_page(pool, d_page); ++ } ++} ++ ++static void ttm_dma_page_put(struct dma_pool *pool, struct dma_page *d_page) ++{ ++ /* Don't set WB on WB page pool. */ ++ if (!(pool->type & IS_CACHED) && set_pages_array_wb(&d_page->p, 1)) ++ pr_err("%s: Failed to set %d pages to wb!\n", ++ pool->dev_name, 1); ++ ++ list_del(&d_page->page_list); ++ __ttm_dma_free_page(pool, d_page); ++} ++ ++/* ++ * Free pages from pool. ++ * ++ * To prevent hogging the ttm_swap process we only free NUM_PAGES_TO_ALLOC ++ * number of pages in one go. ++ * ++ * @pool: to free the pages from ++ * @nr_free: If set to true will free all pages in pool ++ **/ ++static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free) ++{ ++ unsigned long irq_flags; ++ struct dma_page *dma_p, *tmp; ++ struct page **pages_to_free; ++ struct list_head d_pages; ++ unsigned freed_pages = 0, ++ npages_to_free = nr_free; ++ ++ if (NUM_PAGES_TO_ALLOC < nr_free) ++ npages_to_free = NUM_PAGES_TO_ALLOC; ++#if 0 ++ if (nr_free > 1) { ++ pr_debug("%s: (%s:%d) Attempting to free %d (%d) pages\n", ++ pool->dev_name, pool->name, current->pid, ++ npages_to_free, nr_free); ++ } ++#endif ++ pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), ++ GFP_KERNEL); ++ ++ if (!pages_to_free) { ++ pr_err("%s: Failed to allocate memory for pool free operation\n", ++ pool->dev_name); ++ return 0; ++ } ++ INIT_LIST_HEAD(&d_pages); ++restart: ++ spin_lock_irqsave(&pool->lock, irq_flags); ++ ++ /* We picking the oldest ones off the list */ ++ list_for_each_entry_safe_reverse(dma_p, tmp, &pool->free_list, ++ page_list) { ++ if (freed_pages >= npages_to_free) ++ break; ++ ++ /* Move the dma_page from one list to another. */ ++ list_move(&dma_p->page_list, &d_pages); ++ ++ pages_to_free[freed_pages++] = dma_p->p; ++ /* We can only remove NUM_PAGES_TO_ALLOC at a time. */ ++ if (freed_pages >= NUM_PAGES_TO_ALLOC) { ++ ++ ttm_pool_update_free_locked(pool, freed_pages); ++ /** ++ * Because changing page caching is costly ++ * we unlock the pool to prevent stalling. ++ */ ++ spin_unlock_irqrestore(&pool->lock, irq_flags); ++ ++ ttm_dma_pages_put(pool, &d_pages, pages_to_free, ++ freed_pages); ++ ++ INIT_LIST_HEAD(&d_pages); ++ ++ if (likely(nr_free != FREE_ALL_PAGES)) ++ nr_free -= freed_pages; ++ ++ if (NUM_PAGES_TO_ALLOC >= nr_free) ++ npages_to_free = nr_free; ++ else ++ npages_to_free = NUM_PAGES_TO_ALLOC; ++ ++ freed_pages = 0; ++ ++ /* free all so restart the processing */ ++ if (nr_free) ++ goto restart; ++ ++ /* Not allowed to fall through or break because ++ * following context is inside spinlock while we are ++ * outside here. ++ */ ++ goto out; ++ ++ } ++ } ++ ++ /* remove range of pages from the pool */ ++ if (freed_pages) { ++ ttm_pool_update_free_locked(pool, freed_pages); ++ nr_free -= freed_pages; ++ } ++ ++ spin_unlock_irqrestore(&pool->lock, irq_flags); ++ ++ if (freed_pages) ++ ttm_dma_pages_put(pool, &d_pages, pages_to_free, freed_pages); ++out: ++ kfree(pages_to_free); ++ return nr_free; ++} ++ ++static void ttm_dma_free_pool(struct device *dev, enum pool_type type) ++{ ++ struct device_pools *p; ++ struct dma_pool *pool; ++ ++ if (!dev) ++ return; ++ ++ mutex_lock(&_manager->lock); ++ list_for_each_entry_reverse(p, &_manager->pools, pools) { ++ if (p->dev != dev) ++ continue; ++ pool = p->pool; ++ if (pool->type != type) ++ continue; ++ ++ list_del(&p->pools); ++ kfree(p); ++ _manager->npools--; ++ break; ++ } ++ list_for_each_entry_reverse(pool, &dev->dma_pools, pools) { ++ if (pool->type != type) ++ continue; ++ /* Takes a spinlock.. */ ++ ttm_dma_page_pool_free(pool, FREE_ALL_PAGES); ++ WARN_ON(((pool->npages_in_use + pool->npages_free) != 0)); ++ /* This code path is called after _all_ references to the ++ * struct device has been dropped - so nobody should be ++ * touching it. In case somebody is trying to _add_ we are ++ * guarded by the mutex. */ ++ list_del(&pool->pools); ++ kfree(pool); ++ break; ++ } ++ mutex_unlock(&_manager->lock); ++} ++ ++/* ++ * On free-ing of the 'struct device' this deconstructor is run. ++ * Albeit the pool might have already been freed earlier. ++ */ ++static void ttm_dma_pool_release(struct device *dev, void *res) ++{ ++ struct dma_pool *pool = *(struct dma_pool **)res; ++ ++ if (pool) ++ ttm_dma_free_pool(dev, pool->type); ++} ++ ++static int ttm_dma_pool_match(struct device *dev, void *res, void *match_data) ++{ ++ return *(struct dma_pool **)res == match_data; ++} ++ ++static struct dma_pool *ttm_dma_pool_init(struct device *dev, gfp_t flags, ++ enum pool_type type) ++{ ++ char *n[] = {"wc", "uc", "cached", " dma32", "unknown",}; ++ enum pool_type t[] = {IS_WC, IS_UC, IS_CACHED, IS_DMA32, IS_UNDEFINED}; ++ struct device_pools *sec_pool = NULL; ++ struct dma_pool *pool = NULL, **ptr; ++ unsigned i; ++ int ret = -ENODEV; ++ char *p; ++ ++ if (!dev) ++ return NULL; ++ ++ ptr = devres_alloc(ttm_dma_pool_release, sizeof(*ptr), GFP_KERNEL); ++ if (!ptr) ++ return NULL; ++ ++ ret = -ENOMEM; ++ ++ pool = kmalloc_node(sizeof(struct dma_pool), GFP_KERNEL, ++ dev_to_node(dev)); ++ if (!pool) ++ goto err_mem; ++ ++ sec_pool = kmalloc_node(sizeof(struct device_pools), GFP_KERNEL, ++ dev_to_node(dev)); ++ if (!sec_pool) ++ goto err_mem; ++ ++ INIT_LIST_HEAD(&sec_pool->pools); ++ sec_pool->dev = dev; ++ sec_pool->pool = pool; ++ ++ INIT_LIST_HEAD(&pool->free_list); ++ INIT_LIST_HEAD(&pool->inuse_list); ++ INIT_LIST_HEAD(&pool->pools); ++ spin_lock_init(&pool->lock); ++ pool->dev = dev; ++ pool->npages_free = pool->npages_in_use = 0; ++ pool->nfrees = 0; ++ pool->gfp_flags = flags; ++ pool->size = PAGE_SIZE; ++ pool->type = type; ++ pool->nrefills = 0; ++ p = pool->name; ++ for (i = 0; i < 5; i++) { ++ if (type & t[i]) { ++ p += snprintf(p, sizeof(pool->name) - (p - pool->name), ++ "%s", n[i]); ++ } ++ } ++ *p = 0; ++ /* We copy the name for pr_ calls b/c when dma_pool_destroy is called ++ * - the kobj->name has already been deallocated.*/ ++ snprintf(pool->dev_name, sizeof(pool->dev_name), "%s %s", ++ dev_driver_string(dev), dev_name(dev)); ++ mutex_lock(&_manager->lock); ++ /* You can get the dma_pool from either the global: */ ++ list_add(&sec_pool->pools, &_manager->pools); ++ _manager->npools++; ++ /* or from 'struct device': */ ++ list_add(&pool->pools, &dev->dma_pools); ++ mutex_unlock(&_manager->lock); ++ ++ *ptr = pool; ++ devres_add(dev, ptr); ++ ++ return pool; ++err_mem: ++ devres_free(ptr); ++ kfree(sec_pool); ++ kfree(pool); ++ return ERR_PTR(ret); ++} ++ ++static struct dma_pool *ttm_dma_find_pool(struct device *dev, ++ enum pool_type type) ++{ ++ struct dma_pool *pool, *tmp, *found = NULL; ++ ++ if (type == IS_UNDEFINED) ++ return found; ++ ++ /* NB: We iterate on the 'struct dev' which has no spinlock, but ++ * it does have a kref which we have taken. The kref is taken during ++ * graphic driver loading - in the drm_pci_init it calls either ++ * pci_dev_get or pci_register_driver which both end up taking a kref ++ * on 'struct device'. ++ * ++ * On teardown, the graphic drivers end up quiescing the TTM (put_pages) ++ * and calls the dev_res deconstructors: ttm_dma_pool_release. The nice ++ * thing is at that point of time there are no pages associated with the ++ * driver so this function will not be called. ++ */ ++ list_for_each_entry_safe(pool, tmp, &dev->dma_pools, pools) { ++ if (pool->type != type) ++ continue; ++ found = pool; ++ break; ++ } ++ return found; ++} ++ ++/* ++ * Free pages the pages that failed to change the caching state. If there ++ * are pages that have changed their caching state already put them to the ++ * pool. ++ */ ++static void ttm_dma_handle_caching_state_failure(struct dma_pool *pool, ++ struct list_head *d_pages, ++ struct page **failed_pages, ++ unsigned cpages) ++{ ++ struct dma_page *d_page, *tmp; ++ struct page *p; ++ unsigned i = 0; ++ ++ p = failed_pages[0]; ++ if (!p) ++ return; ++ /* Find the failed page. */ ++ list_for_each_entry_safe(d_page, tmp, d_pages, page_list) { ++ if (d_page->p != p) ++ continue; ++ /* .. and then progress over the full list. */ ++ list_del(&d_page->page_list); ++ __ttm_dma_free_page(pool, d_page); ++ if (++i < cpages) ++ p = failed_pages[i]; ++ else ++ break; ++ } ++ ++} ++ ++/* ++ * Allocate 'count' pages, and put 'need' number of them on the ++ * 'pages' and as well on the 'dma_address' starting at 'dma_offset' offset. ++ * The full list of pages should also be on 'd_pages'. ++ * We return zero for success, and negative numbers as errors. ++ */ ++static int ttm_dma_pool_alloc_new_pages(struct dma_pool *pool, ++ struct list_head *d_pages, ++ unsigned count) ++{ ++ struct page **caching_array; ++ struct dma_page *dma_p; ++ struct page *p; ++ int r = 0; ++ unsigned i, cpages; ++ unsigned max_cpages = min(count, ++ (unsigned)(PAGE_SIZE/sizeof(struct page *))); ++ ++ /* allocate array for page caching change */ ++ caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL); ++ ++ if (!caching_array) { ++ pr_err("%s: Unable to allocate table for new pages\n", ++ pool->dev_name); ++ return -ENOMEM; ++ } ++ ++ if (count > 1) { ++ pr_debug("%s: (%s:%d) Getting %d pages\n", ++ pool->dev_name, pool->name, current->pid, count); ++ } ++ ++ for (i = 0, cpages = 0; i < count; ++i) { ++ dma_p = __ttm_dma_alloc_page(pool); ++ if (!dma_p) { ++ pr_err("%s: Unable to get page %u\n", ++ pool->dev_name, i); ++ ++ /* store already allocated pages in the pool after ++ * setting the caching state */ ++ if (cpages) { ++ r = ttm_set_pages_caching(pool, caching_array, ++ cpages); ++ if (r) ++ ttm_dma_handle_caching_state_failure( ++ pool, d_pages, caching_array, ++ cpages); ++ } ++ r = -ENOMEM; ++ goto out; ++ } ++ p = dma_p->p; ++#ifdef CONFIG_HIGHMEM ++ /* gfp flags of highmem page should never be dma32 so we ++ * we should be fine in such case ++ */ ++ if (!PageHighMem(p)) ++#endif ++ { ++ caching_array[cpages++] = p; ++ if (cpages == max_cpages) { ++ /* Note: Cannot hold the spinlock */ ++ r = ttm_set_pages_caching(pool, caching_array, ++ cpages); ++ if (r) { ++ ttm_dma_handle_caching_state_failure( ++ pool, d_pages, caching_array, ++ cpages); ++ goto out; ++ } ++ cpages = 0; ++ } ++ } ++ list_add(&dma_p->page_list, d_pages); ++ } ++ ++ if (cpages) { ++ r = ttm_set_pages_caching(pool, caching_array, cpages); ++ if (r) ++ ttm_dma_handle_caching_state_failure(pool, d_pages, ++ caching_array, cpages); ++ } ++out: ++ kfree(caching_array); ++ return r; ++} ++ ++/* ++ * @return count of pages still required to fulfill the request. ++ */ ++static int ttm_dma_page_pool_fill_locked(struct dma_pool *pool, ++ unsigned long *irq_flags) ++{ ++ unsigned count = _manager->options.small; ++ int r = pool->npages_free; ++ ++ if (count > pool->npages_free) { ++ struct list_head d_pages; ++ ++ INIT_LIST_HEAD(&d_pages); ++ ++ spin_unlock_irqrestore(&pool->lock, *irq_flags); ++ ++ /* Returns how many more are neccessary to fulfill the ++ * request. */ ++ r = ttm_dma_pool_alloc_new_pages(pool, &d_pages, count); ++ ++ spin_lock_irqsave(&pool->lock, *irq_flags); ++ if (!r) { ++ /* Add the fresh to the end.. */ ++ list_splice(&d_pages, &pool->free_list); ++ ++pool->nrefills; ++ pool->npages_free += count; ++ r = count; ++ } else { ++ struct dma_page *d_page; ++ unsigned cpages = 0; ++ ++ pr_err("%s: Failed to fill %s pool (r:%d)!\n", ++ pool->dev_name, pool->name, r); ++ ++ list_for_each_entry(d_page, &d_pages, page_list) { ++ cpages++; ++ } ++ list_splice_tail(&d_pages, &pool->free_list); ++ pool->npages_free += cpages; ++ r = cpages; ++ } ++ } ++ return r; ++} ++ ++/* ++ * @return count of pages still required to fulfill the request. ++ * The populate list is actually a stack (not that is matters as TTM ++ * allocates one page at a time. ++ */ ++static int ttm_dma_pool_get_pages(struct dma_pool *pool, ++ struct ttm_dma_tt *ttm_dma, ++ unsigned index) ++{ ++ struct dma_page *d_page; ++ struct ttm_tt *ttm = &ttm_dma->ttm; ++ unsigned long irq_flags; ++ int count, r = -ENOMEM; ++ ++ spin_lock_irqsave(&pool->lock, irq_flags); ++ count = ttm_dma_page_pool_fill_locked(pool, &irq_flags); ++ if (count) { ++ d_page = list_first_entry(&pool->free_list, struct dma_page, page_list); ++ ttm->pages[index] = d_page->p; ++ ttm_dma->dma_address[index] = d_page->dma; ++ list_move_tail(&d_page->page_list, &ttm_dma->pages_list); ++ r = 0; ++ pool->npages_in_use += 1; ++ pool->npages_free -= 1; ++ } ++ spin_unlock_irqrestore(&pool->lock, irq_flags); ++ return r; ++} ++ ++/* ++ * On success pages list will hold count number of correctly ++ * cached pages. On failure will hold the negative return value (-ENOMEM, etc). ++ */ ++int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev) ++{ ++ struct ttm_tt *ttm = &ttm_dma->ttm; ++ struct ttm_mem_global *mem_glob = ttm->glob->mem_glob; ++ struct dma_pool *pool; ++ enum pool_type type; ++ unsigned i; ++ gfp_t gfp_flags; ++ int ret; ++ ++ if (ttm->state != tt_unpopulated) ++ return 0; ++ ++ type = ttm_to_type(ttm->page_flags, ttm->caching_state); ++ if (ttm->page_flags & TTM_PAGE_FLAG_DMA32) ++ gfp_flags = GFP_USER | GFP_DMA32; ++ else ++ gfp_flags = GFP_HIGHUSER; ++ if (ttm->page_flags & TTM_PAGE_FLAG_ZERO_ALLOC) ++ gfp_flags |= __GFP_ZERO; ++ ++ pool = ttm_dma_find_pool(dev, type); ++ if (!pool) { ++ pool = ttm_dma_pool_init(dev, gfp_flags, type); ++ if (IS_ERR_OR_NULL(pool)) { ++ return -ENOMEM; ++ } ++ } ++ ++ INIT_LIST_HEAD(&ttm_dma->pages_list); ++ for (i = 0; i < ttm->num_pages; ++i) { ++ ret = ttm_dma_pool_get_pages(pool, ttm_dma, i); ++ if (ret != 0) { ++ ttm_dma_unpopulate(ttm_dma, dev); ++ return -ENOMEM; ++ } ++ ++ ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i], ++ false, false); ++ if (unlikely(ret != 0)) { ++ ttm_dma_unpopulate(ttm_dma, dev); ++ return -ENOMEM; ++ } ++ } ++ ++ if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) { ++ ret = ttm_tt_swapin(ttm); ++ if (unlikely(ret != 0)) { ++ ttm_dma_unpopulate(ttm_dma, dev); ++ return ret; ++ } ++ } ++ ++ ttm->state = tt_unbound; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(ttm_dma_populate); ++ ++/* Get good estimation how many pages are free in pools */ ++static int ttm_dma_pool_get_num_unused_pages(void) ++{ ++ struct device_pools *p; ++ unsigned total = 0; ++ ++ mutex_lock(&_manager->lock); ++ list_for_each_entry(p, &_manager->pools, pools) ++ total += p->pool->npages_free; ++ mutex_unlock(&_manager->lock); ++ return total; ++} ++ ++/* Put all pages in pages list to correct pool to wait for reuse */ ++void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev) ++{ ++ struct ttm_tt *ttm = &ttm_dma->ttm; ++ struct dma_pool *pool; ++ struct dma_page *d_page, *next; ++ enum pool_type type; ++ bool is_cached = false; ++ unsigned count = 0, i, npages = 0; ++ unsigned long irq_flags; ++ ++ type = ttm_to_type(ttm->page_flags, ttm->caching_state); ++ pool = ttm_dma_find_pool(dev, type); ++ if (!pool) ++ return; ++ ++ is_cached = (ttm_dma_find_pool(pool->dev, ++ ttm_to_type(ttm->page_flags, tt_cached)) == pool); ++ ++ /* make sure pages array match list and count number of pages */ ++ list_for_each_entry(d_page, &ttm_dma->pages_list, page_list) { ++ ttm->pages[count] = d_page->p; ++ count++; ++ } ++ ++ spin_lock_irqsave(&pool->lock, irq_flags); ++ pool->npages_in_use -= count; ++ if (is_cached) { ++ pool->nfrees += count; ++ } else { ++ pool->npages_free += count; ++ list_splice(&ttm_dma->pages_list, &pool->free_list); ++ npages = count; ++ if (pool->npages_free > _manager->options.max_size) { ++ npages = pool->npages_free - _manager->options.max_size; ++ /* free at least NUM_PAGES_TO_ALLOC number of pages ++ * to reduce calls to set_memory_wb */ ++ if (npages < NUM_PAGES_TO_ALLOC) ++ npages = NUM_PAGES_TO_ALLOC; ++ } ++ } ++ spin_unlock_irqrestore(&pool->lock, irq_flags); ++ ++ if (is_cached) { ++ list_for_each_entry_safe(d_page, next, &ttm_dma->pages_list, page_list) { ++ ttm_mem_global_free_page(ttm->glob->mem_glob, ++ d_page->p); ++ ttm_dma_page_put(pool, d_page); ++ } ++ } else { ++ for (i = 0; i < count; i++) { ++ ttm_mem_global_free_page(ttm->glob->mem_glob, ++ ttm->pages[i]); ++ } ++ } ++ ++ INIT_LIST_HEAD(&ttm_dma->pages_list); ++ for (i = 0; i < ttm->num_pages; i++) { ++ ttm->pages[i] = NULL; ++ ttm_dma->dma_address[i] = 0; ++ } ++ ++ /* shrink pool if necessary (only on !is_cached pools)*/ ++ if (npages) ++ ttm_dma_page_pool_free(pool, npages); ++ ttm->state = tt_unpopulated; ++} ++EXPORT_SYMBOL_GPL(ttm_dma_unpopulate); ++ ++/** ++ * Callback for mm to request pool to reduce number of page held. ++ */ ++static int ttm_dma_pool_mm_shrink(struct shrinker *shrink, ++ struct shrink_control *sc) ++{ ++ static atomic_t start_pool = ATOMIC_INIT(0); ++ unsigned idx = 0; ++ unsigned pool_offset = atomic_add_return(1, &start_pool); ++ unsigned shrink_pages = sc->nr_to_scan; ++ struct device_pools *p; ++ ++ if (list_empty(&_manager->pools)) ++ return 0; ++ ++ mutex_lock(&_manager->lock); ++ pool_offset = pool_offset % _manager->npools; ++ list_for_each_entry(p, &_manager->pools, pools) { ++ unsigned nr_free; ++ ++ if (!p->dev) ++ continue; ++ if (shrink_pages == 0) ++ break; ++ /* Do it in round-robin fashion. */ ++ if (++idx < pool_offset) ++ continue; ++ nr_free = shrink_pages; ++ shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free); ++ pr_debug("%s: (%s:%d) Asked to shrink %d, have %d more to go\n", ++ p->pool->dev_name, p->pool->name, current->pid, ++ nr_free, shrink_pages); ++ } ++ mutex_unlock(&_manager->lock); ++ /* return estimated number of unused pages in pool */ ++ return ttm_dma_pool_get_num_unused_pages(); ++} ++ ++static void ttm_dma_pool_mm_shrink_init(struct ttm_pool_manager *manager) ++{ ++ manager->mm_shrink.shrink = &ttm_dma_pool_mm_shrink; ++ manager->mm_shrink.seeks = 1; ++ register_shrinker(&manager->mm_shrink); ++} ++ ++static void ttm_dma_pool_mm_shrink_fini(struct ttm_pool_manager *manager) ++{ ++ unregister_shrinker(&manager->mm_shrink); ++} ++ ++int ttm_dma_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages) ++{ ++ int ret = -ENOMEM; ++ ++ WARN_ON(_manager); ++ ++ pr_info("Initializing DMA pool allocator\n"); ++ ++ _manager = kzalloc(sizeof(*_manager), GFP_KERNEL); ++ if (!_manager) ++ goto err_manager; ++ ++ mutex_init(&_manager->lock); ++ INIT_LIST_HEAD(&_manager->pools); ++ ++ _manager->options.max_size = max_pages; ++ _manager->options.small = SMALL_ALLOCATION; ++ _manager->options.alloc_size = NUM_PAGES_TO_ALLOC; ++ ++ /* This takes care of auto-freeing the _manager */ ++ ret = kobject_init_and_add(&_manager->kobj, &ttm_pool_kobj_type, ++ &glob->kobj, "dma_pool"); ++ if (unlikely(ret != 0)) { ++ kobject_put(&_manager->kobj); ++ goto err; ++ } ++ ttm_dma_pool_mm_shrink_init(_manager); ++ return 0; ++err_manager: ++ kfree(_manager); ++ _manager = NULL; ++err: ++ return ret; ++} ++ ++void ttm_dma_page_alloc_fini(void) ++{ ++ struct device_pools *p, *t; ++ ++ pr_info("Finalizing DMA pool allocator\n"); ++ ttm_dma_pool_mm_shrink_fini(_manager); ++ ++ list_for_each_entry_safe_reverse(p, t, &_manager->pools, pools) { ++ dev_dbg(p->dev, "(%s:%d) Freeing.\n", p->pool->name, ++ current->pid); ++ WARN_ON(devres_destroy(p->dev, ttm_dma_pool_release, ++ ttm_dma_pool_match, p->pool)); ++ ttm_dma_free_pool(p->dev, p->pool->type); ++ } ++ kobject_put(&_manager->kobj); ++ _manager = NULL; ++} ++ ++int ttm_dma_page_alloc_debugfs(struct seq_file *m, void *data) ++{ ++ struct device_pools *p; ++ struct dma_pool *pool = NULL; ++ char *h[] = {"pool", "refills", "pages freed", "inuse", "available", ++ "name", "virt", "busaddr"}; ++ ++ if (!_manager) { ++ seq_printf(m, "No pool allocator running.\n"); ++ return 0; ++ } ++ seq_printf(m, "%13s %12s %13s %8s %8s %8s\n", ++ h[0], h[1], h[2], h[3], h[4], h[5]); ++ mutex_lock(&_manager->lock); ++ list_for_each_entry(p, &_manager->pools, pools) { ++ struct device *dev = p->dev; ++ if (!dev) ++ continue; ++ pool = p->pool; ++ seq_printf(m, "%13s %12ld %13ld %8d %8d %8s\n", ++ pool->name, pool->nrefills, ++ pool->nfrees, pool->npages_in_use, ++ pool->npages_free, ++ pool->dev_name); ++ } ++ mutex_unlock(&_manager->lock); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(ttm_dma_page_alloc_debugfs); +diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c +index f9cc548..ea10bbe 100644 +--- a/drivers/gpu/drm/ttm/ttm_tt.c ++++ b/drivers/gpu/drm/ttm/ttm_tt.c +@@ -28,6 +28,8 @@ + * Authors: Thomas Hellstrom + */ + ++#define pr_fmt(fmt) "[TTM] " fmt ++ + #include + #include + #include +@@ -43,139 +45,20 @@ + #include "ttm/ttm_placement.h" + #include "ttm/ttm_page_alloc.h" + +-static int ttm_tt_swapin(struct ttm_tt *ttm); +- + /** + * Allocates storage for pointers to the pages that back the ttm. + */ + static void ttm_tt_alloc_page_directory(struct ttm_tt *ttm) + { +- ttm->pages = drm_calloc_large(ttm->num_pages, sizeof(*ttm->pages)); +- ttm->dma_address = drm_calloc_large(ttm->num_pages, +- sizeof(*ttm->dma_address)); +-} +- +-static void ttm_tt_free_page_directory(struct ttm_tt *ttm) +-{ +- drm_free_large(ttm->pages); +- ttm->pages = NULL; +- drm_free_large(ttm->dma_address); +- ttm->dma_address = NULL; +-} +- +-static void ttm_tt_free_user_pages(struct ttm_tt *ttm) +-{ +- int write; +- int dirty; +- struct page *page; +- int i; +- struct ttm_backend *be = ttm->be; +- +- BUG_ON(!(ttm->page_flags & TTM_PAGE_FLAG_USER)); +- write = ((ttm->page_flags & TTM_PAGE_FLAG_WRITE) != 0); +- dirty = ((ttm->page_flags & TTM_PAGE_FLAG_USER_DIRTY) != 0); +- +- if (be) +- be->func->clear(be); +- +- for (i = 0; i < ttm->num_pages; ++i) { +- page = ttm->pages[i]; +- if (page == NULL) +- continue; +- +- if (page == ttm->dummy_read_page) { +- BUG_ON(write); +- continue; +- } +- +- if (write && dirty && !PageReserved(page)) +- set_page_dirty_lock(page); +- +- ttm->pages[i] = NULL; +- ttm_mem_global_free(ttm->glob->mem_glob, PAGE_SIZE); +- put_page(page); +- } +- ttm->state = tt_unpopulated; +- ttm->first_himem_page = ttm->num_pages; +- ttm->last_lomem_page = -1; ++ ttm->pages = drm_calloc_large(ttm->num_pages, sizeof(void*)); + } + +-static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index) ++static void ttm_dma_tt_alloc_page_directory(struct ttm_dma_tt *ttm) + { +- struct page *p; +- struct list_head h; +- struct ttm_mem_global *mem_glob = ttm->glob->mem_glob; +- int ret; +- +- while (NULL == (p = ttm->pages[index])) { +- +- INIT_LIST_HEAD(&h); +- +- ret = ttm_get_pages(&h, ttm->page_flags, ttm->caching_state, 1, +- &ttm->dma_address[index]); +- +- if (ret != 0) +- return NULL; +- +- p = list_first_entry(&h, struct page, lru); +- +- ret = ttm_mem_global_alloc_page(mem_glob, p, false, false); +- if (unlikely(ret != 0)) +- goto out_err; +- +- if (PageHighMem(p)) +- ttm->pages[--ttm->first_himem_page] = p; +- else +- ttm->pages[++ttm->last_lomem_page] = p; +- } +- return p; +-out_err: +- put_page(p); +- return NULL; +-} +- +-struct page *ttm_tt_get_page(struct ttm_tt *ttm, int index) +-{ +- int ret; +- +- if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) { +- ret = ttm_tt_swapin(ttm); +- if (unlikely(ret != 0)) +- return NULL; +- } +- return __ttm_tt_get_page(ttm, index); +-} +- +-int ttm_tt_populate(struct ttm_tt *ttm) +-{ +- struct page *page; +- unsigned long i; +- struct ttm_backend *be; +- int ret; +- +- if (ttm->state != tt_unpopulated) +- return 0; +- +- if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) { +- ret = ttm_tt_swapin(ttm); +- if (unlikely(ret != 0)) +- return ret; +- } +- +- be = ttm->be; +- +- for (i = 0; i < ttm->num_pages; ++i) { +- page = __ttm_tt_get_page(ttm, i); +- if (!page) +- return -ENOMEM; +- } +- +- be->func->populate(be, ttm->num_pages, ttm->pages, +- ttm->dummy_read_page, ttm->dma_address); +- ttm->state = tt_unbound; +- return 0; ++ ttm->ttm.pages = drm_calloc_large(ttm->ttm.num_pages, sizeof(void*)); ++ ttm->dma_address = drm_calloc_large(ttm->ttm.num_pages, ++ sizeof(*ttm->dma_address)); + } +-EXPORT_SYMBOL(ttm_tt_populate); + + #ifdef CONFIG_X86 + static inline int ttm_tt_set_page_caching(struct page *p, +@@ -278,153 +161,100 @@ int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement) + } + EXPORT_SYMBOL(ttm_tt_set_placement_caching); + +-static void ttm_tt_free_alloced_pages(struct ttm_tt *ttm) +-{ +- int i; +- unsigned count = 0; +- struct list_head h; +- struct page *cur_page; +- struct ttm_backend *be = ttm->be; +- +- INIT_LIST_HEAD(&h); +- +- if (be) +- be->func->clear(be); +- for (i = 0; i < ttm->num_pages; ++i) { +- +- cur_page = ttm->pages[i]; +- ttm->pages[i] = NULL; +- if (cur_page) { +- if (page_count(cur_page) != 1) +- printk(KERN_ERR TTM_PFX +- "Erroneous page count. " +- "Leaking pages.\n"); +- ttm_mem_global_free_page(ttm->glob->mem_glob, +- cur_page); +- list_add(&cur_page->lru, &h); +- count++; +- } +- } +- ttm_put_pages(&h, count, ttm->page_flags, ttm->caching_state, +- ttm->dma_address); +- ttm->state = tt_unpopulated; +- ttm->first_himem_page = ttm->num_pages; +- ttm->last_lomem_page = -1; +-} +- + void ttm_tt_destroy(struct ttm_tt *ttm) + { +- struct ttm_backend *be; +- + if (unlikely(ttm == NULL)) + return; + +- be = ttm->be; +- if (likely(be != NULL)) { +- be->func->destroy(be); +- ttm->be = NULL; ++ if (ttm->state == tt_bound) { ++ ttm_tt_unbind(ttm); + } + +- if (likely(ttm->pages != NULL)) { +- if (ttm->page_flags & TTM_PAGE_FLAG_USER) +- ttm_tt_free_user_pages(ttm); +- else +- ttm_tt_free_alloced_pages(ttm); +- +- ttm_tt_free_page_directory(ttm); ++ if (ttm->state == tt_unbound) { ++ ttm->bdev->driver->ttm_tt_unpopulate(ttm); + } + + if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) && + ttm->swap_storage) + fput(ttm->swap_storage); + +- kfree(ttm); ++ ttm->swap_storage = NULL; ++ ttm->func->destroy(ttm); + } + +-int ttm_tt_set_user(struct ttm_tt *ttm, +- struct task_struct *tsk, +- unsigned long start, unsigned long num_pages) ++int ttm_tt_init(struct ttm_tt *ttm, struct ttm_bo_device *bdev, ++ unsigned long size, uint32_t page_flags, ++ struct page *dummy_read_page) + { +- struct mm_struct *mm = tsk->mm; +- int ret; +- int write = (ttm->page_flags & TTM_PAGE_FLAG_WRITE) != 0; +- struct ttm_mem_global *mem_glob = ttm->glob->mem_glob; +- +- BUG_ON(num_pages != ttm->num_pages); +- BUG_ON((ttm->page_flags & TTM_PAGE_FLAG_USER) == 0); +- +- /** +- * Account user pages as lowmem pages for now. +- */ +- +- ret = ttm_mem_global_alloc(mem_glob, num_pages * PAGE_SIZE, +- false, false); +- if (unlikely(ret != 0)) +- return ret; +- +- down_read(&mm->mmap_sem); +- ret = get_user_pages(tsk, mm, start, num_pages, +- write, 0, ttm->pages, NULL); +- up_read(&mm->mmap_sem); ++ ttm->bdev = bdev; ++ ttm->glob = bdev->glob; ++ ttm->num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; ++ ttm->caching_state = tt_cached; ++ ttm->page_flags = page_flags; ++ ttm->dummy_read_page = dummy_read_page; ++ ttm->state = tt_unpopulated; ++ ttm->swap_storage = NULL; + +- if (ret != num_pages && write) { +- ttm_tt_free_user_pages(ttm); +- ttm_mem_global_free(mem_glob, num_pages * PAGE_SIZE); ++ ttm_tt_alloc_page_directory(ttm); ++ if (!ttm->pages) { ++ ttm_tt_destroy(ttm); ++ pr_err("Failed allocating page table\n"); + return -ENOMEM; + } +- +- ttm->tsk = tsk; +- ttm->start = start; +- ttm->state = tt_unbound; +- + return 0; + } ++EXPORT_SYMBOL(ttm_tt_init); + +-struct ttm_tt *ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, +- uint32_t page_flags, struct page *dummy_read_page) ++void ttm_tt_fini(struct ttm_tt *ttm) + { +- struct ttm_bo_driver *bo_driver = bdev->driver; +- struct ttm_tt *ttm; +- +- if (!bo_driver) +- return NULL; ++ drm_free_large(ttm->pages); ++ ttm->pages = NULL; ++} ++EXPORT_SYMBOL(ttm_tt_fini); + +- ttm = kzalloc(sizeof(*ttm), GFP_KERNEL); +- if (!ttm) +- return NULL; ++int ttm_dma_tt_init(struct ttm_dma_tt *ttm_dma, struct ttm_bo_device *bdev, ++ unsigned long size, uint32_t page_flags, ++ struct page *dummy_read_page) ++{ ++ struct ttm_tt *ttm = &ttm_dma->ttm; + ++ ttm->bdev = bdev; + ttm->glob = bdev->glob; + ttm->num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; +- ttm->first_himem_page = ttm->num_pages; +- ttm->last_lomem_page = -1; + ttm->caching_state = tt_cached; + ttm->page_flags = page_flags; +- + ttm->dummy_read_page = dummy_read_page; ++ ttm->state = tt_unpopulated; ++ ttm->swap_storage = NULL; + +- ttm_tt_alloc_page_directory(ttm); +- if (!ttm->pages) { +- ttm_tt_destroy(ttm); +- printk(KERN_ERR TTM_PFX "Failed allocating page table\n"); +- return NULL; +- } +- ttm->be = bo_driver->create_ttm_backend_entry(bdev); +- if (!ttm->be) { ++ INIT_LIST_HEAD(&ttm_dma->pages_list); ++ ttm_dma_tt_alloc_page_directory(ttm_dma); ++ if (!ttm->pages || !ttm_dma->dma_address) { + ttm_tt_destroy(ttm); +- printk(KERN_ERR TTM_PFX "Failed creating ttm backend entry\n"); +- return NULL; ++ pr_err("Failed allocating page table\n"); ++ return -ENOMEM; + } +- ttm->state = tt_unpopulated; +- return ttm; ++ return 0; + } ++EXPORT_SYMBOL(ttm_dma_tt_init); ++ ++void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma) ++{ ++ struct ttm_tt *ttm = &ttm_dma->ttm; ++ ++ drm_free_large(ttm->pages); ++ ttm->pages = NULL; ++ drm_free_large(ttm_dma->dma_address); ++ ttm_dma->dma_address = NULL; ++} ++EXPORT_SYMBOL(ttm_dma_tt_fini); + + void ttm_tt_unbind(struct ttm_tt *ttm) + { + int ret; +- struct ttm_backend *be = ttm->be; + + if (ttm->state == tt_bound) { +- ret = be->func->unbind(be); ++ ret = ttm->func->unbind(ttm); + BUG_ON(ret); + ttm->state = tt_unbound; + } +@@ -433,7 +263,6 @@ void ttm_tt_unbind(struct ttm_tt *ttm) + int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) + { + int ret = 0; +- struct ttm_backend *be; + + if (!ttm) + return -EINVAL; +@@ -441,25 +270,21 @@ int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) + if (ttm->state == tt_bound) + return 0; + +- be = ttm->be; +- +- ret = ttm_tt_populate(ttm); ++ ret = ttm->bdev->driver->ttm_tt_populate(ttm); + if (ret) + return ret; + +- ret = be->func->bind(be, bo_mem); ++ ret = ttm->func->bind(ttm, bo_mem); + if (unlikely(ret != 0)) + return ret; + + ttm->state = tt_bound; + +- if (ttm->page_flags & TTM_PAGE_FLAG_USER) +- ttm->page_flags |= TTM_PAGE_FLAG_USER_DIRTY; + return 0; + } + EXPORT_SYMBOL(ttm_tt_bind); + +-static int ttm_tt_swapin(struct ttm_tt *ttm) ++int ttm_tt_swapin(struct ttm_tt *ttm) + { + struct address_space *swap_space; + struct file *swap_storage; +@@ -470,16 +295,6 @@ static int ttm_tt_swapin(struct ttm_tt *ttm) + int i; + int ret = -ENOMEM; + +- if (ttm->page_flags & TTM_PAGE_FLAG_USER) { +- ret = ttm_tt_set_user(ttm, ttm->tsk, ttm->start, +- ttm->num_pages); +- if (unlikely(ret != 0)) +- return ret; +- +- ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED; +- return 0; +- } +- + swap_storage = ttm->swap_storage; + BUG_ON(swap_storage == NULL); + +@@ -491,16 +306,16 @@ static int ttm_tt_swapin(struct ttm_tt *ttm) + ret = PTR_ERR(from_page); + goto out_err; + } +- to_page = __ttm_tt_get_page(ttm, i); ++ to_page = ttm->pages[i]; + if (unlikely(to_page == NULL)) + goto out_err; + + preempt_disable(); +- from_virtual = kmap_atomic(from_page, KM_USER0); +- to_virtual = kmap_atomic(to_page, KM_USER1); ++ from_virtual = kmap_atomic(from_page); ++ to_virtual = kmap_atomic(to_page); + memcpy(to_virtual, from_virtual, PAGE_SIZE); +- kunmap_atomic(to_virtual, KM_USER1); +- kunmap_atomic(from_virtual, KM_USER0); ++ kunmap_atomic(to_virtual); ++ kunmap_atomic(from_virtual); + preempt_enable(); + page_cache_release(from_page); + } +@@ -512,7 +327,6 @@ static int ttm_tt_swapin(struct ttm_tt *ttm) + + return 0; + out_err: +- ttm_tt_free_alloced_pages(ttm); + return ret; + } + +@@ -530,24 +344,12 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage) + BUG_ON(ttm->state != tt_unbound && ttm->state != tt_unpopulated); + BUG_ON(ttm->caching_state != tt_cached); + +- /* +- * For user buffers, just unpin the pages, as there should be +- * vma references. +- */ +- +- if (ttm->page_flags & TTM_PAGE_FLAG_USER) { +- ttm_tt_free_user_pages(ttm); +- ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED; +- ttm->swap_storage = NULL; +- return 0; +- } +- + if (!persistent_swap_storage) { + swap_storage = shmem_file_setup("ttm swap", + ttm->num_pages << PAGE_SHIFT, + 0); + if (unlikely(IS_ERR(swap_storage))) { +- printk(KERN_ERR "Failed allocating swap storage.\n"); ++ pr_err("Failed allocating swap storage\n"); + return PTR_ERR(swap_storage); + } + } else +@@ -565,18 +367,18 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage) + goto out_err; + } + preempt_disable(); +- from_virtual = kmap_atomic(from_page, KM_USER0); +- to_virtual = kmap_atomic(to_page, KM_USER1); ++ from_virtual = kmap_atomic(from_page); ++ to_virtual = kmap_atomic(to_page); + memcpy(to_virtual, from_virtual, PAGE_SIZE); +- kunmap_atomic(to_virtual, KM_USER1); +- kunmap_atomic(from_virtual, KM_USER0); ++ kunmap_atomic(to_virtual); ++ kunmap_atomic(from_virtual); + preempt_enable(); + set_page_dirty(to_page); + mark_page_accessed(to_page); + page_cache_release(to_page); + } + +- ttm_tt_free_alloced_pages(ttm); ++ ttm->bdev->driver->ttm_tt_unpopulate(ttm); + ttm->swap_storage = swap_storage; + ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED; + if (persistent_swap_storage) +diff --git a/drivers/gpu/drm/udl/Kconfig b/drivers/gpu/drm/udl/Kconfig +new file mode 100644 +index 0000000..0b5e096 +--- /dev/null ++++ b/drivers/gpu/drm/udl/Kconfig +@@ -0,0 +1,12 @@ ++config DRM_UDL ++ tristate "DisplayLink" ++ depends on DRM && EXPERIMENTAL ++ select DRM_USB ++ select FB_SYS_FILLRECT ++ select FB_SYS_COPYAREA ++ select FB_SYS_IMAGEBLIT ++ select FB_DEFERRED_IO ++ select DRM_KMS_HELPER ++ help ++ This is a KMS driver for the USB displaylink video adapters. ++ Say M/Y to add support for these devices via drm/kms interfaces. +diff --git a/drivers/gpu/drm/udl/Makefile b/drivers/gpu/drm/udl/Makefile +new file mode 100644 +index 0000000..05c7481 +--- /dev/null ++++ b/drivers/gpu/drm/udl/Makefile +@@ -0,0 +1,6 @@ ++ ++ccflags-y := -Iinclude/drm ++ ++udl-y := udl_drv.o udl_modeset.o udl_connector.o udl_encoder.o udl_main.o udl_fb.o udl_transfer.o udl_gem.o ++ ++obj-$(CONFIG_DRM_UDL) := udl.o +diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c +new file mode 100644 +index 0000000..b8e6463 +--- /dev/null ++++ b/drivers/gpu/drm/udl/udl_connector.c +@@ -0,0 +1,165 @@ ++/* ++ * Copyright (C) 2012 Red Hat ++ * based in parts on udlfb.c: ++ * Copyright (C) 2009 Roberto De Ioris ++ * Copyright (C) 2009 Jaya Kumar ++ * Copyright (C) 2009 Bernie Thompson ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License v2. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++ ++#include "drmP.h" ++#include "drm_crtc.h" ++#include "drm_edid.h" ++#include "drm_crtc_helper.h" ++#include "udl_drv.h" ++ ++/* dummy connector to just get EDID, ++ all UDL appear to have a DVI-D */ ++ ++static u8 *udl_get_edid(struct udl_device *udl) ++{ ++ u8 *block; ++ char *rbuf; ++ int ret, i; ++ ++ block = kmalloc(EDID_LENGTH, GFP_KERNEL); ++ if (block == NULL) ++ return NULL; ++ ++ rbuf = kmalloc(2, GFP_KERNEL); ++ if (rbuf == NULL) ++ goto error; ++ ++ for (i = 0; i < EDID_LENGTH; i++) { ++ ret = usb_control_msg(udl->ddev->usbdev, ++ usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), ++ (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2, ++ HZ); ++ if (ret < 1) { ++ DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); ++ goto error; ++ } ++ block[i] = rbuf[1]; ++ } ++ ++ kfree(rbuf); ++ return block; ++ ++error: ++ kfree(block); ++ kfree(rbuf); ++ return NULL; ++} ++ ++static int udl_get_modes(struct drm_connector *connector) ++{ ++ struct udl_device *udl = connector->dev->dev_private; ++ struct edid *edid; ++ int ret; ++ ++ edid = (struct edid *)udl_get_edid(udl); ++ if (!edid) { ++ drm_mode_connector_update_edid_property(connector, NULL); ++ return 0; ++ } ++ ++ connector->display_info.raw_edid = (char *)edid; ++ ++ /* ++ * We only read the main block, but if the monitor reports extension ++ * blocks then the drm edid code expects them to be present, so patch ++ * the extension count to 0. ++ */ ++ edid->checksum += edid->extensions; ++ edid->extensions = 0; ++ ++ drm_mode_connector_update_edid_property(connector, edid); ++ ret = drm_add_edid_modes(connector, edid); ++ connector->display_info.raw_edid = NULL; ++ kfree(edid); ++ return ret; ++} ++ ++static int udl_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ struct udl_device *udl = connector->dev->dev_private; ++ if (!udl->sku_pixel_limit) ++ return 0; ++ ++ if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit) ++ return MODE_VIRTUAL_Y; ++ ++ return 0; ++} ++ ++static enum drm_connector_status ++udl_detect(struct drm_connector *connector, bool force) ++{ ++ if (drm_device_is_unplugged(connector->dev)) ++ return connector_status_disconnected; ++ return connector_status_connected; ++} ++ ++struct drm_encoder *udl_best_single_encoder(struct drm_connector *connector) ++{ ++ int enc_id = connector->encoder_ids[0]; ++ struct drm_mode_object *obj; ++ struct drm_encoder *encoder; ++ ++ obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); ++ if (!obj) ++ return NULL; ++ encoder = obj_to_encoder(obj); ++ return encoder; ++} ++ ++int udl_connector_set_property(struct drm_connector *connector, struct drm_property *property, ++ uint64_t val) ++{ ++ return 0; ++} ++ ++static void udl_connector_destroy(struct drm_connector *connector) ++{ ++ drm_sysfs_connector_remove(connector); ++ drm_connector_cleanup(connector); ++ kfree(connector); ++} ++ ++struct drm_connector_helper_funcs udl_connector_helper_funcs = { ++ .get_modes = udl_get_modes, ++ .mode_valid = udl_mode_valid, ++ .best_encoder = udl_best_single_encoder, ++}; ++ ++struct drm_connector_funcs udl_connector_funcs = { ++ .dpms = drm_helper_connector_dpms, ++ .detect = udl_detect, ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .destroy = udl_connector_destroy, ++ .set_property = udl_connector_set_property, ++}; ++ ++int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder) ++{ ++ struct drm_connector *connector; ++ ++ connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL); ++ if (!connector) ++ return -ENOMEM; ++ ++ drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_DVII); ++ drm_connector_helper_add(connector, &udl_connector_helper_funcs); ++ ++ drm_sysfs_connector_add(connector); ++ drm_mode_connector_attach_encoder(connector, encoder); ++ ++ drm_connector_attach_property(connector, ++ dev->mode_config.dirty_info_property, ++ 1); ++ return 0; ++} +diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c +new file mode 100644 +index 0000000..08eff0d +--- /dev/null ++++ b/drivers/gpu/drm/udl/udl_drv.c +@@ -0,0 +1,112 @@ ++/* ++ * Copyright (C) 2012 Red Hat ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License v2. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++ ++#include ++#include "drm_usb.h" ++#include "drm_crtc_helper.h" ++#include "udl_drv.h" ++ ++static struct drm_driver driver; ++ ++/* ++ * There are many DisplayLink-based graphics products, all with unique PIDs. ++ * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff) ++ * We also require a match on SubClass (0x00) and Protocol (0x00), ++ * which is compatible with all known USB 2.0 era graphics chips and firmware, ++ * but allows DisplayLink to increment those for any future incompatible chips ++ */ ++static struct usb_device_id id_table[] = { ++ {.idVendor = 0x17e9, .bInterfaceClass = 0xff, ++ .bInterfaceSubClass = 0x00, ++ .bInterfaceProtocol = 0x00, ++ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | ++ USB_DEVICE_ID_MATCH_INT_CLASS | ++ USB_DEVICE_ID_MATCH_INT_SUBCLASS | ++ USB_DEVICE_ID_MATCH_INT_PROTOCOL,}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(usb, id_table); ++ ++MODULE_LICENSE("GPL"); ++ ++static int udl_usb_probe(struct usb_interface *interface, ++ const struct usb_device_id *id) ++{ ++ return drm_get_usb_dev(interface, id, &driver); ++} ++ ++static void udl_usb_disconnect(struct usb_interface *interface) ++{ ++ struct drm_device *dev = usb_get_intfdata(interface); ++ ++ drm_kms_helper_poll_disable(dev); ++ drm_connector_unplug_all(dev); ++ udl_fbdev_unplug(dev); ++ udl_drop_usb(dev); ++ drm_unplug_dev(dev); ++} ++ ++static struct vm_operations_struct udl_gem_vm_ops = { ++ .fault = udl_gem_fault, ++ .open = drm_gem_vm_open, ++ .close = drm_gem_vm_close, ++}; ++ ++static const struct file_operations udl_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .mmap = udl_drm_gem_mmap, ++ .poll = drm_poll, ++ .read = drm_read, ++ .unlocked_ioctl = drm_ioctl, ++ .release = drm_release, ++ .fasync = drm_fasync, ++ .llseek = noop_llseek, ++}; ++ ++static struct drm_driver driver = { ++ .driver_features = DRIVER_MODESET | DRIVER_GEM, ++ .load = udl_driver_load, ++ .unload = udl_driver_unload, ++ ++ /* gem hooks */ ++ .gem_init_object = udl_gem_init_object, ++ .gem_free_object = udl_gem_free_object, ++ .gem_vm_ops = &udl_gem_vm_ops, ++ ++ .dumb_create = udl_dumb_create, ++ .dumb_map_offset = udl_gem_mmap, ++ .dumb_destroy = udl_dumb_destroy, ++ .fops = &udl_driver_fops, ++ .name = DRIVER_NAME, ++ .desc = DRIVER_DESC, ++ .date = DRIVER_DATE, ++ .major = DRIVER_MAJOR, ++ .minor = DRIVER_MINOR, ++ .patchlevel = DRIVER_PATCHLEVEL, ++}; ++ ++static struct usb_driver udl_driver = { ++ .name = "udl", ++ .probe = udl_usb_probe, ++ .disconnect = udl_usb_disconnect, ++ .id_table = id_table, ++}; ++ ++static int __init udl_init(void) ++{ ++ return drm_usb_init(&driver, &udl_driver); ++} ++ ++static void __exit udl_exit(void) ++{ ++ drm_usb_exit(&driver, &udl_driver); ++} ++ ++module_init(udl_init); ++module_exit(udl_exit); +diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h +new file mode 100644 +index 0000000..2b8c4fd +--- /dev/null ++++ b/drivers/gpu/drm/udl/udl_drv.h +@@ -0,0 +1,144 @@ ++/* ++ * Copyright (C) 2012 Red Hat ++ * ++ * based in parts on udlfb.c: ++ * Copyright (C) 2009 Roberto De Ioris ++ * Copyright (C) 2009 Jaya Kumar ++ * Copyright (C) 2009 Bernie Thompson ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License v2. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++ ++#ifndef UDL_DRV_H ++#define UDL_DRV_H ++ ++#include ++ ++#define DRIVER_NAME "udl" ++#define DRIVER_DESC "DisplayLink" ++#define DRIVER_DATE "20120220" ++ ++#define DRIVER_MAJOR 0 ++#define DRIVER_MINOR 0 ++#define DRIVER_PATCHLEVEL 1 ++ ++struct udl_device; ++ ++struct urb_node { ++ struct list_head entry; ++ struct udl_device *dev; ++ struct delayed_work release_urb_work; ++ struct urb *urb; ++}; ++ ++struct urb_list { ++ struct list_head list; ++ spinlock_t lock; ++ struct semaphore limit_sem; ++ int available; ++ int count; ++ size_t size; ++}; ++ ++struct udl_fbdev; ++ ++struct udl_device { ++ struct device *dev; ++ struct drm_device *ddev; ++ ++ int sku_pixel_limit; ++ ++ struct urb_list urbs; ++ atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */ ++ ++ struct udl_fbdev *fbdev; ++ char mode_buf[1024]; ++ uint32_t mode_buf_len; ++ atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */ ++ atomic_t bytes_identical; /* saved effort with backbuffer comparison */ ++ atomic_t bytes_sent; /* to usb, after compression including overhead */ ++ atomic_t cpu_kcycles_used; /* transpired during pixel processing */ ++}; ++ ++struct udl_gem_object { ++ struct drm_gem_object base; ++ struct page **pages; ++ void *vmapping; ++}; ++ ++#define to_udl_bo(x) container_of(x, struct udl_gem_object, base) ++ ++struct udl_framebuffer { ++ struct drm_framebuffer base; ++ struct udl_gem_object *obj; ++ bool active_16; /* active on the 16-bit channel */ ++ int x1, y1, x2, y2; /* dirty rect */ ++ spinlock_t dirty_lock; ++}; ++ ++#define to_udl_fb(x) container_of(x, struct udl_framebuffer, base) ++ ++/* modeset */ ++int udl_modeset_init(struct drm_device *dev); ++void udl_modeset_cleanup(struct drm_device *dev); ++int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder); ++ ++struct drm_encoder *udl_encoder_init(struct drm_device *dev); ++ ++struct urb *udl_get_urb(struct drm_device *dev); ++ ++int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len); ++void udl_urb_completion(struct urb *urb); ++ ++int udl_driver_load(struct drm_device *dev, unsigned long flags); ++int udl_driver_unload(struct drm_device *dev); ++ ++int udl_fbdev_init(struct drm_device *dev); ++void udl_fbdev_cleanup(struct drm_device *dev); ++void udl_fbdev_unplug(struct drm_device *dev); ++struct drm_framebuffer * ++udl_fb_user_fb_create(struct drm_device *dev, ++ struct drm_file *file, ++ struct drm_mode_fb_cmd2 *mode_cmd); ++ ++int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, ++ const char *front, char **urb_buf_ptr, ++ u32 byte_offset, u32 device_byte_offset, u32 byte_width, ++ int *ident_ptr, int *sent_ptr); ++ ++int udl_dumb_create(struct drm_file *file_priv, ++ struct drm_device *dev, ++ struct drm_mode_create_dumb *args); ++int udl_gem_mmap(struct drm_file *file_priv, struct drm_device *dev, ++ uint32_t handle, uint64_t *offset); ++int udl_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev, ++ uint32_t handle); ++ ++int udl_gem_init_object(struct drm_gem_object *obj); ++void udl_gem_free_object(struct drm_gem_object *gem_obj); ++struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, ++ size_t size); ++ ++int udl_gem_vmap(struct udl_gem_object *obj); ++void udl_gem_vunmap(struct udl_gem_object *obj); ++int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); ++int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); ++ ++int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, ++ int width, int height); ++ ++int udl_drop_usb(struct drm_device *dev); ++ ++#define CMD_WRITE_RAW8 "\xAF\x60" /**< 8 bit raw write command. */ ++#define CMD_WRITE_RL8 "\xAF\x61" /**< 8 bit run length command. */ ++#define CMD_WRITE_COPY8 "\xAF\x62" /**< 8 bit copy command. */ ++#define CMD_WRITE_RLX8 "\xAF\x63" /**< 8 bit extended run length command. */ ++ ++#define CMD_WRITE_RAW16 "\xAF\x68" /**< 16 bit raw write command. */ ++#define CMD_WRITE_RL16 "\xAF\x69" /**< 16 bit run length command. */ ++#define CMD_WRITE_COPY16 "\xAF\x6A" /**< 16 bit copy command. */ ++#define CMD_WRITE_RLX16 "\xAF\x6B" /**< 16 bit extended run length command. */ ++ ++#endif +diff --git a/drivers/gpu/drm/udl/udl_encoder.c b/drivers/gpu/drm/udl/udl_encoder.c +new file mode 100644 +index 0000000..56e75f0 +--- /dev/null ++++ b/drivers/gpu/drm/udl/udl_encoder.c +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (C) 2012 Red Hat ++ * based in parts on udlfb.c: ++ * Copyright (C) 2009 Roberto De Ioris ++ * Copyright (C) 2009 Jaya Kumar ++ * Copyright (C) 2009 Bernie Thompson ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License v2. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++ ++#include "drmP.h" ++#include "drm_crtc.h" ++#include "drm_crtc_helper.h" ++#include "udl_drv.h" ++ ++/* dummy encoder */ ++void udl_enc_destroy(struct drm_encoder *encoder) ++{ ++ drm_encoder_cleanup(encoder); ++ kfree(encoder); ++} ++ ++static void udl_encoder_disable(struct drm_encoder *encoder) ++{ ++} ++ ++static bool udl_mode_fixup(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ return true; ++} ++ ++static void udl_encoder_prepare(struct drm_encoder *encoder) ++{ ++} ++ ++static void udl_encoder_commit(struct drm_encoder *encoder) ++{ ++} ++ ++static void udl_encoder_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++} ++ ++static void ++udl_encoder_dpms(struct drm_encoder *encoder, int mode) ++{ ++} ++ ++static const struct drm_encoder_helper_funcs udl_helper_funcs = { ++ .dpms = udl_encoder_dpms, ++ .mode_fixup = udl_mode_fixup, ++ .prepare = udl_encoder_prepare, ++ .mode_set = udl_encoder_mode_set, ++ .commit = udl_encoder_commit, ++ .disable = udl_encoder_disable, ++}; ++ ++static const struct drm_encoder_funcs udl_enc_funcs = { ++ .destroy = udl_enc_destroy, ++}; ++ ++struct drm_encoder *udl_encoder_init(struct drm_device *dev) ++{ ++ struct drm_encoder *encoder; ++ ++ encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL); ++ if (!encoder) ++ return NULL; ++ ++ drm_encoder_init(dev, encoder, &udl_enc_funcs, DRM_MODE_ENCODER_TMDS); ++ drm_encoder_helper_add(encoder, &udl_helper_funcs); ++ encoder->possible_crtcs = 1; ++ return encoder; ++} +diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c +new file mode 100644 +index 0000000..f02d223 +--- /dev/null ++++ b/drivers/gpu/drm/udl/udl_fb.c +@@ -0,0 +1,649 @@ ++/* ++ * Copyright (C) 2012 Red Hat ++ * ++ * based in parts on udlfb.c: ++ * Copyright (C) 2009 Roberto De Ioris ++ * Copyright (C) 2009 Jaya Kumar ++ * Copyright (C) 2009 Bernie Thompson ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License v2. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++#include ++#include ++#include ++ ++#include "drmP.h" ++#include "drm.h" ++#include "drm_crtc.h" ++#include "drm_crtc_helper.h" ++#include "udl_drv.h" ++ ++#include "drm_fb_helper.h" ++ ++#define DL_DEFIO_WRITE_DELAY (HZ/20) /* fb_deferred_io.delay in jiffies */ ++ ++static int fb_defio = 0; /* Optionally enable experimental fb_defio mmap support */ ++static int fb_bpp = 16; ++ ++module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); ++module_param(fb_defio, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); ++ ++struct udl_fbdev { ++ struct drm_fb_helper helper; ++ struct udl_framebuffer ufb; ++ struct list_head fbdev_list; ++ int fb_count; ++}; ++ ++#define DL_ALIGN_UP(x, a) ALIGN(x, a) ++#define DL_ALIGN_DOWN(x, a) ALIGN(x-(a-1), a) ++ ++/** Read the red component (0..255) of a 32 bpp colour. */ ++#define DLO_RGB_GETRED(col) (uint8_t)((col) & 0xFF) ++ ++/** Read the green component (0..255) of a 32 bpp colour. */ ++#define DLO_RGB_GETGRN(col) (uint8_t)(((col) >> 8) & 0xFF) ++ ++/** Read the blue component (0..255) of a 32 bpp colour. */ ++#define DLO_RGB_GETBLU(col) (uint8_t)(((col) >> 16) & 0xFF) ++ ++/** Return red/green component of a 16 bpp colour number. */ ++#define DLO_RG16(red, grn) (uint8_t)((((red) & 0xF8) | ((grn) >> 5)) & 0xFF) ++ ++/** Return green/blue component of a 16 bpp colour number. */ ++#define DLO_GB16(grn, blu) (uint8_t)(((((grn) & 0x1C) << 3) | ((blu) >> 3)) & 0xFF) ++ ++/** Return 8 bpp colour number from red, green and blue components. */ ++#define DLO_RGB8(red, grn, blu) ((((red) << 5) | (((grn) & 3) << 3) | ((blu) & 7)) & 0xFF) ++ ++#if 0 ++static uint8_t rgb8(uint32_t col) ++{ ++ uint8_t red = DLO_RGB_GETRED(col); ++ uint8_t grn = DLO_RGB_GETGRN(col); ++ uint8_t blu = DLO_RGB_GETBLU(col); ++ ++ return DLO_RGB8(red, grn, blu); ++} ++ ++static uint16_t rgb16(uint32_t col) ++{ ++ uint8_t red = DLO_RGB_GETRED(col); ++ uint8_t grn = DLO_RGB_GETGRN(col); ++ uint8_t blu = DLO_RGB_GETBLU(col); ++ ++ return (DLO_RG16(red, grn) << 8) + DLO_GB16(grn, blu); ++} ++#endif ++ ++/* ++ * NOTE: fb_defio.c is holding info->fbdefio.mutex ++ * Touching ANY framebuffer memory that triggers a page fault ++ * in fb_defio will cause a deadlock, when it also tries to ++ * grab the same mutex. ++ */ ++static void udlfb_dpy_deferred_io(struct fb_info *info, ++ struct list_head *pagelist) ++{ ++ struct page *cur; ++ struct fb_deferred_io *fbdefio = info->fbdefio; ++ struct udl_fbdev *ufbdev = info->par; ++ struct drm_device *dev = ufbdev->ufb.base.dev; ++ struct udl_device *udl = dev->dev_private; ++ struct urb *urb; ++ char *cmd; ++ cycles_t start_cycles, end_cycles; ++ int bytes_sent = 0; ++ int bytes_identical = 0; ++ int bytes_rendered = 0; ++ ++ if (!fb_defio) ++ return; ++ ++ start_cycles = get_cycles(); ++ ++ urb = udl_get_urb(dev); ++ if (!urb) ++ return; ++ ++ cmd = urb->transfer_buffer; ++ ++ /* walk the written page list and render each to device */ ++ list_for_each_entry(cur, &fbdefio->pagelist, lru) { ++ ++ if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), ++ &urb, (char *) info->fix.smem_start, ++ &cmd, cur->index << PAGE_SHIFT, ++ cur->index << PAGE_SHIFT, ++ PAGE_SIZE, &bytes_identical, &bytes_sent)) ++ goto error; ++ bytes_rendered += PAGE_SIZE; ++ } ++ ++ if (cmd > (char *) urb->transfer_buffer) { ++ /* Send partial buffer remaining before exiting */ ++ int len = cmd - (char *) urb->transfer_buffer; ++ udl_submit_urb(dev, urb, len); ++ bytes_sent += len; ++ } else ++ udl_urb_completion(urb); ++ ++error: ++ atomic_add(bytes_sent, &udl->bytes_sent); ++ atomic_add(bytes_identical, &udl->bytes_identical); ++ atomic_add(bytes_rendered, &udl->bytes_rendered); ++ end_cycles = get_cycles(); ++ atomic_add(((unsigned int) ((end_cycles - start_cycles) ++ >> 10)), /* Kcycles */ ++ &udl->cpu_kcycles_used); ++} ++ ++int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, ++ int width, int height) ++{ ++ struct drm_device *dev = fb->base.dev; ++ struct udl_device *udl = dev->dev_private; ++ int i, ret; ++ char *cmd; ++ cycles_t start_cycles, end_cycles; ++ int bytes_sent = 0; ++ int bytes_identical = 0; ++ struct urb *urb; ++ int aligned_x; ++ int bpp = (fb->base.bits_per_pixel / 8); ++ int x2, y2; ++ bool store_for_later = false; ++ unsigned long flags; ++ ++ if (!fb->active_16) ++ return 0; ++ ++ if (!fb->obj->vmapping) ++ udl_gem_vmap(fb->obj); ++ ++ aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long)); ++ width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long)); ++ x = aligned_x; ++ ++ if ((width <= 0) || ++ (x + width > fb->base.width) || ++ (y + height > fb->base.height)) ++ return -EINVAL; ++ ++ /* if we are in atomic just store the info ++ can't test inside spin lock */ ++ if (in_atomic()) ++ store_for_later = true; ++ ++ x2 = x + width - 1; ++ y2 = y + height - 1; ++ ++ spin_lock_irqsave(&fb->dirty_lock, flags); ++ ++ if (fb->y1 < y) ++ y = fb->y1; ++ if (fb->y2 > y2) ++ y2 = fb->y2; ++ if (fb->x1 < x) ++ x = fb->x1; ++ if (fb->x2 > x2) ++ x2 = fb->x2; ++ ++ if (store_for_later) { ++ fb->x1 = x; ++ fb->x2 = x2; ++ fb->y1 = y; ++ fb->y2 = y2; ++ spin_unlock_irqrestore(&fb->dirty_lock, flags); ++ return 0; ++ } ++ ++ fb->x1 = fb->y1 = INT_MAX; ++ fb->x2 = fb->y2 = 0; ++ ++ spin_unlock_irqrestore(&fb->dirty_lock, flags); ++ start_cycles = get_cycles(); ++ ++ urb = udl_get_urb(dev); ++ if (!urb) ++ return 0; ++ cmd = urb->transfer_buffer; ++ ++ for (i = y; i <= y2 ; i++) { ++ const int line_offset = fb->base.pitches[0] * i; ++ const int byte_offset = line_offset + (x * bpp); ++ const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); ++ if (udl_render_hline(dev, bpp, &urb, ++ (char *) fb->obj->vmapping, ++ &cmd, byte_offset, dev_byte_offset, ++ (x2 - x + 1) * bpp, ++ &bytes_identical, &bytes_sent)) ++ goto error; ++ } ++ ++ if (cmd > (char *) urb->transfer_buffer) { ++ /* Send partial buffer remaining before exiting */ ++ int len = cmd - (char *) urb->transfer_buffer; ++ ret = udl_submit_urb(dev, urb, len); ++ bytes_sent += len; ++ } else ++ udl_urb_completion(urb); ++ ++error: ++ atomic_add(bytes_sent, &udl->bytes_sent); ++ atomic_add(bytes_identical, &udl->bytes_identical); ++ atomic_add(width*height*bpp, &udl->bytes_rendered); ++ end_cycles = get_cycles(); ++ atomic_add(((unsigned int) ((end_cycles - start_cycles) ++ >> 10)), /* Kcycles */ ++ &udl->cpu_kcycles_used); ++ ++ return 0; ++} ++ ++static int udl_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) ++{ ++ unsigned long start = vma->vm_start; ++ unsigned long size = vma->vm_end - vma->vm_start; ++ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; ++ unsigned long page, pos; ++ ++ if (offset + size > info->fix.smem_len) ++ return -EINVAL; ++ ++ pos = (unsigned long)info->fix.smem_start + offset; ++ ++ pr_notice("mmap() framebuffer addr:%lu size:%lu\n", ++ pos, size); ++ ++ while (size > 0) { ++ page = vmalloc_to_pfn((void *)pos); ++ if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) ++ return -EAGAIN; ++ ++ start += PAGE_SIZE; ++ pos += PAGE_SIZE; ++ if (size > PAGE_SIZE) ++ size -= PAGE_SIZE; ++ else ++ size = 0; ++ } ++ ++ vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ ++ return 0; ++} ++ ++static void udl_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) ++{ ++ struct udl_fbdev *ufbdev = info->par; ++ ++ sys_fillrect(info, rect); ++ ++ udl_handle_damage(&ufbdev->ufb, rect->dx, rect->dy, rect->width, ++ rect->height); ++} ++ ++static void udl_fb_copyarea(struct fb_info *info, const struct fb_copyarea *region) ++{ ++ struct udl_fbdev *ufbdev = info->par; ++ ++ sys_copyarea(info, region); ++ ++ udl_handle_damage(&ufbdev->ufb, region->dx, region->dy, region->width, ++ region->height); ++} ++ ++static void udl_fb_imageblit(struct fb_info *info, const struct fb_image *image) ++{ ++ struct udl_fbdev *ufbdev = info->par; ++ ++ sys_imageblit(info, image); ++ ++ udl_handle_damage(&ufbdev->ufb, image->dx, image->dy, image->width, ++ image->height); ++} ++ ++/* ++ * It's common for several clients to have framebuffer open simultaneously. ++ * e.g. both fbcon and X. Makes things interesting. ++ * Assumes caller is holding info->lock (for open and release at least) ++ */ ++static int udl_fb_open(struct fb_info *info, int user) ++{ ++ struct udl_fbdev *ufbdev = info->par; ++ struct drm_device *dev = ufbdev->ufb.base.dev; ++ struct udl_device *udl = dev->dev_private; ++ ++ /* If the USB device is gone, we don't accept new opens */ ++ if (drm_device_is_unplugged(udl->ddev)) ++ return -ENODEV; ++ ++ ufbdev->fb_count++; ++ ++ if (fb_defio && (info->fbdefio == NULL)) { ++ /* enable defio at last moment if not disabled by client */ ++ ++ struct fb_deferred_io *fbdefio; ++ ++ fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); ++ ++ if (fbdefio) { ++ fbdefio->delay = DL_DEFIO_WRITE_DELAY; ++ fbdefio->deferred_io = udlfb_dpy_deferred_io; ++ } ++ ++ info->fbdefio = fbdefio; ++ fb_deferred_io_init(info); ++ } ++ ++ pr_notice("open /dev/fb%d user=%d fb_info=%p count=%d\n", ++ info->node, user, info, ufbdev->fb_count); ++ ++ return 0; ++} ++ ++ ++/* ++ * Assumes caller is holding info->lock mutex (for open and release at least) ++ */ ++static int udl_fb_release(struct fb_info *info, int user) ++{ ++ struct udl_fbdev *ufbdev = info->par; ++ ++ ufbdev->fb_count--; ++ ++ if ((ufbdev->fb_count == 0) && (info->fbdefio)) { ++ fb_deferred_io_cleanup(info); ++ kfree(info->fbdefio); ++ info->fbdefio = NULL; ++ info->fbops->fb_mmap = udl_fb_mmap; ++ } ++ ++ pr_warn("released /dev/fb%d user=%d count=%d\n", ++ info->node, user, ufbdev->fb_count); ++ ++ return 0; ++} ++ ++static struct fb_ops udlfb_ops = { ++ .owner = THIS_MODULE, ++ .fb_check_var = drm_fb_helper_check_var, ++ .fb_set_par = drm_fb_helper_set_par, ++ .fb_fillrect = udl_fb_fillrect, ++ .fb_copyarea = udl_fb_copyarea, ++ .fb_imageblit = udl_fb_imageblit, ++ .fb_pan_display = drm_fb_helper_pan_display, ++ .fb_blank = drm_fb_helper_blank, ++ .fb_setcmap = drm_fb_helper_setcmap, ++ .fb_debug_enter = drm_fb_helper_debug_enter, ++ .fb_debug_leave = drm_fb_helper_debug_leave, ++ .fb_mmap = udl_fb_mmap, ++ .fb_open = udl_fb_open, ++ .fb_release = udl_fb_release, ++}; ++ ++void udl_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, ++ u16 blue, int regno) ++{ ++} ++ ++void udl_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, ++ u16 *blue, int regno) ++{ ++ *red = 0; ++ *green = 0; ++ *blue = 0; ++} ++ ++static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb, ++ struct drm_file *file, ++ unsigned flags, unsigned color, ++ struct drm_clip_rect *clips, ++ unsigned num_clips) ++{ ++ struct udl_framebuffer *ufb = to_udl_fb(fb); ++ int i; ++ ++ if (!ufb->active_16) ++ return 0; ++ ++ for (i = 0; i < num_clips; i++) { ++ udl_handle_damage(ufb, clips[i].x1, clips[i].y1, ++ clips[i].x2 - clips[i].x1, ++ clips[i].y2 - clips[i].y1); ++ } ++ return 0; ++} ++ ++static void udl_user_framebuffer_destroy(struct drm_framebuffer *fb) ++{ ++ struct udl_framebuffer *ufb = to_udl_fb(fb); ++ ++ if (ufb->obj) ++ drm_gem_object_unreference_unlocked(&ufb->obj->base); ++ ++ drm_framebuffer_cleanup(fb); ++ kfree(ufb); ++} ++ ++static const struct drm_framebuffer_funcs udlfb_funcs = { ++ .destroy = udl_user_framebuffer_destroy, ++ .dirty = udl_user_framebuffer_dirty, ++ .create_handle = NULL, ++}; ++ ++ ++static int ++udl_framebuffer_init(struct drm_device *dev, ++ struct udl_framebuffer *ufb, ++ struct drm_mode_fb_cmd2 *mode_cmd, ++ struct udl_gem_object *obj) ++{ ++ int ret; ++ ++ spin_lock_init(&ufb->dirty_lock); ++ ufb->obj = obj; ++ ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs); ++ drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd); ++ return ret; ++} ++ ++ ++static int udlfb_create(struct udl_fbdev *ufbdev, ++ struct drm_fb_helper_surface_size *sizes) ++{ ++ struct drm_device *dev = ufbdev->helper.dev; ++ struct fb_info *info; ++ struct device *device = &dev->usbdev->dev; ++ struct drm_framebuffer *fb; ++ struct drm_mode_fb_cmd2 mode_cmd; ++ struct udl_gem_object *obj; ++ uint32_t size; ++ int ret = 0; ++ ++ if (sizes->surface_bpp == 24) ++ sizes->surface_bpp = 32; ++ ++ mode_cmd.width = sizes->surface_width; ++ mode_cmd.height = sizes->surface_height; ++ mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8); ++ ++ mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, ++ sizes->surface_depth); ++ ++ size = mode_cmd.pitches[0] * mode_cmd.height; ++ size = ALIGN(size, PAGE_SIZE); ++ ++ obj = udl_gem_alloc_object(dev, size); ++ if (!obj) ++ goto out; ++ ++ ret = udl_gem_vmap(obj); ++ if (ret) { ++ DRM_ERROR("failed to vmap fb\n"); ++ goto out_gfree; ++ } ++ ++ info = framebuffer_alloc(0, device); ++ if (!info) { ++ ret = -ENOMEM; ++ goto out_gfree; ++ } ++ info->par = ufbdev; ++ ++ ret = udl_framebuffer_init(dev, &ufbdev->ufb, &mode_cmd, obj); ++ if (ret) ++ goto out_gfree; ++ ++ fb = &ufbdev->ufb.base; ++ ++ ufbdev->helper.fb = fb; ++ ufbdev->helper.fbdev = info; ++ ++ strcpy(info->fix.id, "udldrmfb"); ++ ++ info->screen_base = ufbdev->ufb.obj->vmapping; ++ info->fix.smem_len = size; ++ info->fix.smem_start = (unsigned long)ufbdev->ufb.obj->vmapping; ++ ++ info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; ++ info->fbops = &udlfb_ops; ++ drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); ++ drm_fb_helper_fill_var(info, &ufbdev->helper, sizes->fb_width, sizes->fb_height); ++ ++ ret = fb_alloc_cmap(&info->cmap, 256, 0); ++ if (ret) { ++ ret = -ENOMEM; ++ goto out_gfree; ++ } ++ ++ ++ DRM_DEBUG_KMS("allocated %dx%d vmal %p\n", ++ fb->width, fb->height, ++ ufbdev->ufb.obj->vmapping); ++ ++ return ret; ++out_gfree: ++ drm_gem_object_unreference(&ufbdev->ufb.obj->base); ++out: ++ return ret; ++} ++ ++static int udl_fb_find_or_create_single(struct drm_fb_helper *helper, ++ struct drm_fb_helper_surface_size *sizes) ++{ ++ struct udl_fbdev *ufbdev = (struct udl_fbdev *)helper; ++ int new_fb = 0; ++ int ret; ++ ++ if (!helper->fb) { ++ ret = udlfb_create(ufbdev, sizes); ++ if (ret) ++ return ret; ++ ++ new_fb = 1; ++ } ++ return new_fb; ++} ++ ++static struct drm_fb_helper_funcs udl_fb_helper_funcs = { ++ .gamma_set = udl_crtc_fb_gamma_set, ++ .gamma_get = udl_crtc_fb_gamma_get, ++ .fb_probe = udl_fb_find_or_create_single, ++}; ++ ++static void udl_fbdev_destroy(struct drm_device *dev, ++ struct udl_fbdev *ufbdev) ++{ ++ struct fb_info *info; ++ if (ufbdev->helper.fbdev) { ++ info = ufbdev->helper.fbdev; ++ unregister_framebuffer(info); ++ if (info->cmap.len) ++ fb_dealloc_cmap(&info->cmap); ++ framebuffer_release(info); ++ } ++ drm_fb_helper_fini(&ufbdev->helper); ++ drm_framebuffer_cleanup(&ufbdev->ufb.base); ++ drm_gem_object_unreference_unlocked(&ufbdev->ufb.obj->base); ++} ++ ++int udl_fbdev_init(struct drm_device *dev) ++{ ++ struct udl_device *udl = dev->dev_private; ++ int bpp_sel = fb_bpp; ++ struct udl_fbdev *ufbdev; ++ int ret; ++ ++ ufbdev = kzalloc(sizeof(struct udl_fbdev), GFP_KERNEL); ++ if (!ufbdev) ++ return -ENOMEM; ++ ++ udl->fbdev = ufbdev; ++ ufbdev->helper.funcs = &udl_fb_helper_funcs; ++ ++ ret = drm_fb_helper_init(dev, &ufbdev->helper, ++ 1, 1); ++ if (ret) { ++ kfree(ufbdev); ++ return ret; ++ ++ } ++ ++ drm_fb_helper_single_add_all_connectors(&ufbdev->helper); ++ drm_fb_helper_initial_config(&ufbdev->helper, bpp_sel); ++ return 0; ++} ++ ++void udl_fbdev_cleanup(struct drm_device *dev) ++{ ++ struct udl_device *udl = dev->dev_private; ++ if (!udl->fbdev) ++ return; ++ ++ udl_fbdev_destroy(dev, udl->fbdev); ++ kfree(udl->fbdev); ++ udl->fbdev = NULL; ++} ++ ++void udl_fbdev_unplug(struct drm_device *dev) ++{ ++ struct udl_device *udl = dev->dev_private; ++ struct udl_fbdev *ufbdev; ++ if (!udl->fbdev) ++ return; ++ ++ ufbdev = udl->fbdev; ++ if (ufbdev->helper.fbdev) { ++ struct fb_info *info; ++ info = ufbdev->helper.fbdev; ++ unlink_framebuffer(info); ++ } ++} ++ ++struct drm_framebuffer * ++udl_fb_user_fb_create(struct drm_device *dev, ++ struct drm_file *file, ++ struct drm_mode_fb_cmd2 *mode_cmd) ++{ ++ struct drm_gem_object *obj; ++ struct udl_framebuffer *ufb; ++ int ret; ++ ++ obj = drm_gem_object_lookup(dev, file, mode_cmd->handles[0]); ++ if (obj == NULL) ++ return ERR_PTR(-ENOENT); ++ ++ ufb = kzalloc(sizeof(*ufb), GFP_KERNEL); ++ if (ufb == NULL) ++ return ERR_PTR(-ENOMEM); ++ ++ ret = udl_framebuffer_init(dev, ufb, mode_cmd, to_udl_bo(obj)); ++ if (ret) { ++ kfree(ufb); ++ return ERR_PTR(-EINVAL); ++ } ++ return &ufb->base; ++} +diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c +new file mode 100644 +index 0000000..92f19ef +--- /dev/null ++++ b/drivers/gpu/drm/udl/udl_gem.c +@@ -0,0 +1,241 @@ ++/* ++ * Copyright (C) 2012 Red Hat ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License v2. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++ ++#include "drmP.h" ++#include "udl_drv.h" ++#include ++ ++struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, ++ size_t size) ++{ ++ struct udl_gem_object *obj; ++ ++ obj = kzalloc(sizeof(*obj), GFP_KERNEL); ++ if (obj == NULL) ++ return NULL; ++ ++ if (drm_gem_object_init(dev, &obj->base, size) != 0) { ++ kfree(obj); ++ return NULL; ++ } ++ ++ return obj; ++} ++ ++static int ++udl_gem_create(struct drm_file *file, ++ struct drm_device *dev, ++ uint64_t size, ++ uint32_t *handle_p) ++{ ++ struct udl_gem_object *obj; ++ int ret; ++ u32 handle; ++ ++ size = roundup(size, PAGE_SIZE); ++ ++ obj = udl_gem_alloc_object(dev, size); ++ if (obj == NULL) ++ return -ENOMEM; ++ ++ ret = drm_gem_handle_create(file, &obj->base, &handle); ++ if (ret) { ++ drm_gem_object_release(&obj->base); ++ kfree(obj); ++ return ret; ++ } ++ ++ drm_gem_object_unreference(&obj->base); ++ *handle_p = handle; ++ return 0; ++} ++ ++int udl_dumb_create(struct drm_file *file, ++ struct drm_device *dev, ++ struct drm_mode_create_dumb *args) ++{ ++ args->pitch = args->width * ((args->bpp + 1) / 8); ++ args->size = args->pitch * args->height; ++ return udl_gem_create(file, dev, ++ args->size, &args->handle); ++} ++ ++int udl_dumb_destroy(struct drm_file *file, struct drm_device *dev, ++ uint32_t handle) ++{ ++ return drm_gem_handle_delete(file, handle); ++} ++ ++int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) ++{ ++ int ret; ++ ++ ret = drm_gem_mmap(filp, vma); ++ if (ret) ++ return ret; ++ ++ vma->vm_flags &= ~VM_PFNMAP; ++ vma->vm_flags |= VM_MIXEDMAP; ++ ++ return ret; ++} ++ ++int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ++{ ++ struct udl_gem_object *obj = to_udl_bo(vma->vm_private_data); ++ struct page *page; ++ unsigned int page_offset; ++ int ret = 0; ++ ++ page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> ++ PAGE_SHIFT; ++ ++ if (!obj->pages) ++ return VM_FAULT_SIGBUS; ++ ++ page = obj->pages[page_offset]; ++ ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page); ++ switch (ret) { ++ case -EAGAIN: ++ set_need_resched(); ++ case 0: ++ case -ERESTARTSYS: ++ return VM_FAULT_NOPAGE; ++ case -ENOMEM: ++ return VM_FAULT_OOM; ++ default: ++ return VM_FAULT_SIGBUS; ++ } ++} ++ ++int udl_gem_init_object(struct drm_gem_object *obj) ++{ ++ BUG(); ++ ++ return 0; ++} ++ ++static int udl_gem_get_pages(struct udl_gem_object *obj, gfp_t gfpmask) ++{ ++ int page_count, i; ++ struct page *page; ++ struct inode *inode; ++ struct address_space *mapping; ++ ++ if (obj->pages) ++ return 0; ++ ++ page_count = obj->base.size / PAGE_SIZE; ++ BUG_ON(obj->pages != NULL); ++ obj->pages = drm_malloc_ab(page_count, sizeof(struct page *)); ++ if (obj->pages == NULL) ++ return -ENOMEM; ++ ++ inode = obj->base.filp->f_path.dentry->d_inode; ++ mapping = inode->i_mapping; ++ gfpmask |= mapping_gfp_mask(mapping); ++ ++ for (i = 0; i < page_count; i++) { ++ page = shmem_read_mapping_page_gfp(mapping, i, gfpmask); ++ if (IS_ERR(page)) ++ goto err_pages; ++ obj->pages[i] = page; ++ } ++ ++ return 0; ++err_pages: ++ while (i--) ++ page_cache_release(obj->pages[i]); ++ drm_free_large(obj->pages); ++ obj->pages = NULL; ++ return PTR_ERR(page); ++} ++ ++static void udl_gem_put_pages(struct udl_gem_object *obj) ++{ ++ int page_count = obj->base.size / PAGE_SIZE; ++ int i; ++ ++ for (i = 0; i < page_count; i++) ++ page_cache_release(obj->pages[i]); ++ ++ drm_free_large(obj->pages); ++ obj->pages = NULL; ++} ++ ++int udl_gem_vmap(struct udl_gem_object *obj) ++{ ++ int page_count = obj->base.size / PAGE_SIZE; ++ int ret; ++ ++ ret = udl_gem_get_pages(obj, GFP_KERNEL); ++ if (ret) ++ return ret; ++ ++ obj->vmapping = vmap(obj->pages, page_count, 0, PAGE_KERNEL); ++ if (!obj->vmapping) ++ return -ENOMEM; ++ return 0; ++} ++ ++void udl_gem_vunmap(struct udl_gem_object *obj) ++{ ++ if (obj->vmapping) ++ vunmap(obj->vmapping); ++ ++ udl_gem_put_pages(obj); ++} ++ ++void udl_gem_free_object(struct drm_gem_object *gem_obj) ++{ ++ struct udl_gem_object *obj = to_udl_bo(gem_obj); ++ ++ if (obj->vmapping) ++ udl_gem_vunmap(obj); ++ ++ if (obj->pages) ++ udl_gem_put_pages(obj); ++ ++ if (gem_obj->map_list.map) ++ drm_gem_free_mmap_offset(gem_obj); ++} ++ ++/* the dumb interface doesn't work with the GEM straight MMAP ++ interface, it expects to do MMAP on the drm fd, like normal */ ++int udl_gem_mmap(struct drm_file *file, struct drm_device *dev, ++ uint32_t handle, uint64_t *offset) ++{ ++ struct udl_gem_object *gobj; ++ struct drm_gem_object *obj; ++ int ret = 0; ++ ++ mutex_lock(&dev->struct_mutex); ++ obj = drm_gem_object_lookup(dev, file, handle); ++ if (obj == NULL) { ++ ret = -ENOENT; ++ goto unlock; ++ } ++ gobj = to_udl_bo(obj); ++ ++ ret = udl_gem_get_pages(gobj, GFP_KERNEL); ++ if (ret) ++ return ret; ++ if (!gobj->base.map_list.map) { ++ ret = drm_gem_create_mmap_offset(obj); ++ if (ret) ++ goto out; ++ } ++ ++ *offset = (u64)gobj->base.map_list.hash.key << PAGE_SHIFT; ++ ++out: ++ drm_gem_object_unreference(&gobj->base); ++unlock: ++ mutex_unlock(&dev->struct_mutex); ++ return ret; ++} +diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c +new file mode 100644 +index 0000000..a8d5f09 +--- /dev/null ++++ b/drivers/gpu/drm/udl/udl_main.c +@@ -0,0 +1,338 @@ ++/* ++ * Copyright (C) 2012 Red Hat ++ * ++ * based in parts on udlfb.c: ++ * Copyright (C) 2009 Roberto De Ioris ++ * Copyright (C) 2009 Jaya Kumar ++ * Copyright (C) 2009 Bernie Thompson ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License v2. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++#include "drmP.h" ++#include "udl_drv.h" ++ ++/* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */ ++#define BULK_SIZE 512 ++ ++#define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE) ++#define WRITES_IN_FLIGHT (4) ++#define MAX_VENDOR_DESCRIPTOR_SIZE 256 ++ ++#define GET_URB_TIMEOUT HZ ++#define FREE_URB_TIMEOUT (HZ*2) ++ ++static int udl_parse_vendor_descriptor(struct drm_device *dev, ++ struct usb_device *usbdev) ++{ ++ struct udl_device *udl = dev->dev_private; ++ char *desc; ++ char *buf; ++ char *desc_end; ++ ++ u8 total_len = 0; ++ ++ buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL); ++ if (!buf) ++ return false; ++ desc = buf; ++ ++ total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */ ++ 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE); ++ if (total_len > 5) { ++ DRM_INFO("vendor descriptor length:%x data:%02x %02x %02x %02x" \ ++ "%02x %02x %02x %02x %02x %02x %02x\n", ++ total_len, desc[0], ++ desc[1], desc[2], desc[3], desc[4], desc[5], desc[6], ++ desc[7], desc[8], desc[9], desc[10]); ++ ++ if ((desc[0] != total_len) || /* descriptor length */ ++ (desc[1] != 0x5f) || /* vendor descriptor type */ ++ (desc[2] != 0x01) || /* version (2 bytes) */ ++ (desc[3] != 0x00) || ++ (desc[4] != total_len - 2)) /* length after type */ ++ goto unrecognized; ++ ++ desc_end = desc + total_len; ++ desc += 5; /* the fixed header we've already parsed */ ++ ++ while (desc < desc_end) { ++ u8 length; ++ u16 key; ++ ++ key = *((u16 *) desc); ++ desc += sizeof(u16); ++ length = *desc; ++ desc++; ++ ++ switch (key) { ++ case 0x0200: { /* max_area */ ++ u32 max_area; ++ max_area = le32_to_cpu(*((u32 *)desc)); ++ DRM_DEBUG("DL chip limited to %d pixel modes\n", ++ max_area); ++ udl->sku_pixel_limit = max_area; ++ break; ++ } ++ default: ++ break; ++ } ++ desc += length; ++ } ++ } ++ ++ goto success; ++ ++unrecognized: ++ /* allow udlfb to load for now even if firmware unrecognized */ ++ DRM_ERROR("Unrecognized vendor firmware descriptor\n"); ++ ++success: ++ kfree(buf); ++ return true; ++} ++ ++static void udl_release_urb_work(struct work_struct *work) ++{ ++ struct urb_node *unode = container_of(work, struct urb_node, ++ release_urb_work.work); ++ ++ up(&unode->dev->urbs.limit_sem); ++} ++ ++void udl_urb_completion(struct urb *urb) ++{ ++ struct urb_node *unode = urb->context; ++ struct udl_device *udl = unode->dev; ++ unsigned long flags; ++ ++ /* sync/async unlink faults aren't errors */ ++ if (urb->status) { ++ if (!(urb->status == -ENOENT || ++ urb->status == -ECONNRESET || ++ urb->status == -ESHUTDOWN)) { ++ DRM_ERROR("%s - nonzero write bulk status received: %d\n", ++ __func__, urb->status); ++ atomic_set(&udl->lost_pixels, 1); ++ } ++ } ++ ++ urb->transfer_buffer_length = udl->urbs.size; /* reset to actual */ ++ ++ spin_lock_irqsave(&udl->urbs.lock, flags); ++ list_add_tail(&unode->entry, &udl->urbs.list); ++ udl->urbs.available++; ++ spin_unlock_irqrestore(&udl->urbs.lock, flags); ++ ++#if 0 ++ /* ++ * When using fb_defio, we deadlock if up() is called ++ * while another is waiting. So queue to another process. ++ */ ++ if (fb_defio) ++ schedule_delayed_work(&unode->release_urb_work, 0); ++ else ++#endif ++ up(&udl->urbs.limit_sem); ++} ++ ++static void udl_free_urb_list(struct drm_device *dev) ++{ ++ struct udl_device *udl = dev->dev_private; ++ int count = udl->urbs.count; ++ struct list_head *node; ++ struct urb_node *unode; ++ struct urb *urb; ++ int ret; ++ unsigned long flags; ++ ++ DRM_DEBUG("Waiting for completes and freeing all render urbs\n"); ++ ++ /* keep waiting and freeing, until we've got 'em all */ ++ while (count--) { ++ ++ /* Getting interrupted means a leak, but ok at shutdown*/ ++ ret = down_interruptible(&udl->urbs.limit_sem); ++ if (ret) ++ break; ++ ++ spin_lock_irqsave(&udl->urbs.lock, flags); ++ ++ node = udl->urbs.list.next; /* have reserved one with sem */ ++ list_del_init(node); ++ ++ spin_unlock_irqrestore(&udl->urbs.lock, flags); ++ ++ unode = list_entry(node, struct urb_node, entry); ++ urb = unode->urb; ++ ++ /* Free each separately allocated piece */ ++ usb_free_coherent(urb->dev, udl->urbs.size, ++ urb->transfer_buffer, urb->transfer_dma); ++ usb_free_urb(urb); ++ kfree(node); ++ } ++ udl->urbs.count = 0; ++} ++ ++static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) ++{ ++ struct udl_device *udl = dev->dev_private; ++ int i = 0; ++ struct urb *urb; ++ struct urb_node *unode; ++ char *buf; ++ ++ spin_lock_init(&udl->urbs.lock); ++ ++ udl->urbs.size = size; ++ INIT_LIST_HEAD(&udl->urbs.list); ++ ++ while (i < count) { ++ unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL); ++ if (!unode) ++ break; ++ unode->dev = udl; ++ ++ INIT_DELAYED_WORK(&unode->release_urb_work, ++ udl_release_urb_work); ++ ++ urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!urb) { ++ kfree(unode); ++ break; ++ } ++ unode->urb = urb; ++ ++ buf = usb_alloc_coherent(udl->ddev->usbdev, MAX_TRANSFER, GFP_KERNEL, ++ &urb->transfer_dma); ++ if (!buf) { ++ kfree(unode); ++ usb_free_urb(urb); ++ break; ++ } ++ ++ /* urb->transfer_buffer_length set to actual before submit */ ++ usb_fill_bulk_urb(urb, udl->ddev->usbdev, usb_sndbulkpipe(udl->ddev->usbdev, 1), ++ buf, size, udl_urb_completion, unode); ++ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; ++ ++ list_add_tail(&unode->entry, &udl->urbs.list); ++ ++ i++; ++ } ++ ++ sema_init(&udl->urbs.limit_sem, i); ++ udl->urbs.count = i; ++ udl->urbs.available = i; ++ ++ DRM_DEBUG("allocated %d %d byte urbs\n", i, (int) size); ++ ++ return i; ++} ++ ++struct urb *udl_get_urb(struct drm_device *dev) ++{ ++ struct udl_device *udl = dev->dev_private; ++ int ret = 0; ++ struct list_head *entry; ++ struct urb_node *unode; ++ struct urb *urb = NULL; ++ unsigned long flags; ++ ++ /* Wait for an in-flight buffer to complete and get re-queued */ ++ ret = down_timeout(&udl->urbs.limit_sem, GET_URB_TIMEOUT); ++ if (ret) { ++ atomic_set(&udl->lost_pixels, 1); ++ DRM_INFO("wait for urb interrupted: %x available: %d\n", ++ ret, udl->urbs.available); ++ goto error; ++ } ++ ++ spin_lock_irqsave(&udl->urbs.lock, flags); ++ ++ BUG_ON(list_empty(&udl->urbs.list)); /* reserved one with limit_sem */ ++ entry = udl->urbs.list.next; ++ list_del_init(entry); ++ udl->urbs.available--; ++ ++ spin_unlock_irqrestore(&udl->urbs.lock, flags); ++ ++ unode = list_entry(entry, struct urb_node, entry); ++ urb = unode->urb; ++ ++error: ++ return urb; ++} ++ ++int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len) ++{ ++ struct udl_device *udl = dev->dev_private; ++ int ret; ++ ++ BUG_ON(len > udl->urbs.size); ++ ++ urb->transfer_buffer_length = len; /* set to actual payload len */ ++ ret = usb_submit_urb(urb, GFP_ATOMIC); ++ if (ret) { ++ udl_urb_completion(urb); /* because no one else will */ ++ atomic_set(&udl->lost_pixels, 1); ++ DRM_ERROR("usb_submit_urb error %x\n", ret); ++ } ++ return ret; ++} ++ ++int udl_driver_load(struct drm_device *dev, unsigned long flags) ++{ ++ struct udl_device *udl; ++ int ret; ++ ++ DRM_DEBUG("\n"); ++ udl = kzalloc(sizeof(struct udl_device), GFP_KERNEL); ++ if (!udl) ++ return -ENOMEM; ++ ++ udl->ddev = dev; ++ dev->dev_private = udl; ++ ++ if (!udl_parse_vendor_descriptor(dev, dev->usbdev)) { ++ DRM_ERROR("firmware not recognized. Assume incompatible device\n"); ++ goto err; ++ } ++ ++ if (!udl_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { ++ ret = -ENOMEM; ++ DRM_ERROR("udl_alloc_urb_list failed\n"); ++ goto err; ++ } ++ ++ DRM_DEBUG("\n"); ++ ret = udl_modeset_init(dev); ++ ++ ret = udl_fbdev_init(dev); ++ return 0; ++err: ++ kfree(udl); ++ DRM_ERROR("%d\n", ret); ++ return ret; ++} ++ ++int udl_drop_usb(struct drm_device *dev) ++{ ++ udl_free_urb_list(dev); ++ return 0; ++} ++ ++int udl_driver_unload(struct drm_device *dev) ++{ ++ struct udl_device *udl = dev->dev_private; ++ ++ if (udl->urbs.count) ++ udl_free_urb_list(dev); ++ ++ udl_fbdev_cleanup(dev); ++ udl_modeset_cleanup(dev); ++ kfree(udl); ++ return 0; ++} +diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c +new file mode 100644 +index 0000000..b3ecb3d +--- /dev/null ++++ b/drivers/gpu/drm/udl/udl_modeset.c +@@ -0,0 +1,414 @@ ++/* ++ * Copyright (C) 2012 Red Hat ++ * ++ * based in parts on udlfb.c: ++ * Copyright (C) 2009 Roberto De Ioris ++ * Copyright (C) 2009 Jaya Kumar ++ * Copyright (C) 2009 Bernie Thompson ++ ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License v2. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++ ++#include "drmP.h" ++#include "drm_crtc.h" ++#include "drm_crtc_helper.h" ++#include "udl_drv.h" ++ ++/* ++ * All DisplayLink bulk operations start with 0xAF, followed by specific code ++ * All operations are written to buffers which then later get sent to device ++ */ ++static char *udl_set_register(char *buf, u8 reg, u8 val) ++{ ++ *buf++ = 0xAF; ++ *buf++ = 0x20; ++ *buf++ = reg; ++ *buf++ = val; ++ return buf; ++} ++ ++static char *udl_vidreg_lock(char *buf) ++{ ++ return udl_set_register(buf, 0xFF, 0x00); ++} ++ ++static char *udl_vidreg_unlock(char *buf) ++{ ++ return udl_set_register(buf, 0xFF, 0xFF); ++} ++ ++/* ++ * On/Off for driving the DisplayLink framebuffer to the display ++ * 0x00 H and V sync on ++ * 0x01 H and V sync off (screen blank but powered) ++ * 0x07 DPMS powerdown (requires modeset to come back) ++ */ ++static char *udl_enable_hvsync(char *buf, bool enable) ++{ ++ if (enable) ++ return udl_set_register(buf, 0x1F, 0x00); ++ else ++ return udl_set_register(buf, 0x1F, 0x07); ++} ++ ++static char *udl_set_color_depth(char *buf, u8 selection) ++{ ++ return udl_set_register(buf, 0x00, selection); ++} ++ ++static char *udl_set_base16bpp(char *wrptr, u32 base) ++{ ++ /* the base pointer is 16 bits wide, 0x20 is hi byte. */ ++ wrptr = udl_set_register(wrptr, 0x20, base >> 16); ++ wrptr = udl_set_register(wrptr, 0x21, base >> 8); ++ return udl_set_register(wrptr, 0x22, base); ++} ++ ++/* ++ * DisplayLink HW has separate 16bpp and 8bpp framebuffers. ++ * In 24bpp modes, the low 323 RGB bits go in the 8bpp framebuffer ++ */ ++static char *udl_set_base8bpp(char *wrptr, u32 base) ++{ ++ wrptr = udl_set_register(wrptr, 0x26, base >> 16); ++ wrptr = udl_set_register(wrptr, 0x27, base >> 8); ++ return udl_set_register(wrptr, 0x28, base); ++} ++ ++static char *udl_set_register_16(char *wrptr, u8 reg, u16 value) ++{ ++ wrptr = udl_set_register(wrptr, reg, value >> 8); ++ return udl_set_register(wrptr, reg+1, value); ++} ++ ++/* ++ * This is kind of weird because the controller takes some ++ * register values in a different byte order than other registers. ++ */ ++static char *udl_set_register_16be(char *wrptr, u8 reg, u16 value) ++{ ++ wrptr = udl_set_register(wrptr, reg, value); ++ return udl_set_register(wrptr, reg+1, value >> 8); ++} ++ ++/* ++ * LFSR is linear feedback shift register. The reason we have this is ++ * because the display controller needs to minimize the clock depth of ++ * various counters used in the display path. So this code reverses the ++ * provided value into the lfsr16 value by counting backwards to get ++ * the value that needs to be set in the hardware comparator to get the ++ * same actual count. This makes sense once you read above a couple of ++ * times and think about it from a hardware perspective. ++ */ ++static u16 udl_lfsr16(u16 actual_count) ++{ ++ u32 lv = 0xFFFF; /* This is the lfsr value that the hw starts with */ ++ ++ while (actual_count--) { ++ lv = ((lv << 1) | ++ (((lv >> 15) ^ (lv >> 4) ^ (lv >> 2) ^ (lv >> 1)) & 1)) ++ & 0xFFFF; ++ } ++ ++ return (u16) lv; ++} ++ ++/* ++ * This does LFSR conversion on the value that is to be written. ++ * See LFSR explanation above for more detail. ++ */ ++static char *udl_set_register_lfsr16(char *wrptr, u8 reg, u16 value) ++{ ++ return udl_set_register_16(wrptr, reg, udl_lfsr16(value)); ++} ++ ++/* ++ * This takes a standard fbdev screeninfo struct and all of its monitor mode ++ * details and converts them into the DisplayLink equivalent register commands. ++ ERR(vreg(dev, 0x00, (color_depth == 16) ? 0 : 1)); ++ ERR(vreg_lfsr16(dev, 0x01, xDisplayStart)); ++ ERR(vreg_lfsr16(dev, 0x03, xDisplayEnd)); ++ ERR(vreg_lfsr16(dev, 0x05, yDisplayStart)); ++ ERR(vreg_lfsr16(dev, 0x07, yDisplayEnd)); ++ ERR(vreg_lfsr16(dev, 0x09, xEndCount)); ++ ERR(vreg_lfsr16(dev, 0x0B, hSyncStart)); ++ ERR(vreg_lfsr16(dev, 0x0D, hSyncEnd)); ++ ERR(vreg_big_endian(dev, 0x0F, hPixels)); ++ ERR(vreg_lfsr16(dev, 0x11, yEndCount)); ++ ERR(vreg_lfsr16(dev, 0x13, vSyncStart)); ++ ERR(vreg_lfsr16(dev, 0x15, vSyncEnd)); ++ ERR(vreg_big_endian(dev, 0x17, vPixels)); ++ ERR(vreg_little_endian(dev, 0x1B, pixelClock5KHz)); ++ ++ ERR(vreg(dev, 0x1F, 0)); ++ ++ ERR(vbuf(dev, WRITE_VIDREG_UNLOCK, DSIZEOF(WRITE_VIDREG_UNLOCK))); ++ */ ++static char *udl_set_vid_cmds(char *wrptr, struct drm_display_mode *mode) ++{ ++ u16 xds, yds; ++ u16 xde, yde; ++ u16 yec; ++ ++ /* x display start */ ++ xds = mode->crtc_htotal - mode->crtc_hsync_start; ++ wrptr = udl_set_register_lfsr16(wrptr, 0x01, xds); ++ /* x display end */ ++ xde = xds + mode->crtc_hdisplay; ++ wrptr = udl_set_register_lfsr16(wrptr, 0x03, xde); ++ ++ /* y display start */ ++ yds = mode->crtc_vtotal - mode->crtc_vsync_start; ++ wrptr = udl_set_register_lfsr16(wrptr, 0x05, yds); ++ /* y display end */ ++ yde = yds + mode->crtc_vdisplay; ++ wrptr = udl_set_register_lfsr16(wrptr, 0x07, yde); ++ ++ /* x end count is active + blanking - 1 */ ++ wrptr = udl_set_register_lfsr16(wrptr, 0x09, ++ mode->crtc_htotal - 1); ++ ++ /* libdlo hardcodes hsync start to 1 */ ++ wrptr = udl_set_register_lfsr16(wrptr, 0x0B, 1); ++ ++ /* hsync end is width of sync pulse + 1 */ ++ wrptr = udl_set_register_lfsr16(wrptr, 0x0D, ++ mode->crtc_hsync_end - mode->crtc_hsync_start + 1); ++ ++ /* hpixels is active pixels */ ++ wrptr = udl_set_register_16(wrptr, 0x0F, mode->hdisplay); ++ ++ /* yendcount is vertical active + vertical blanking */ ++ yec = mode->crtc_vtotal; ++ wrptr = udl_set_register_lfsr16(wrptr, 0x11, yec); ++ ++ /* libdlo hardcodes vsync start to 0 */ ++ wrptr = udl_set_register_lfsr16(wrptr, 0x13, 0); ++ ++ /* vsync end is width of vsync pulse */ ++ wrptr = udl_set_register_lfsr16(wrptr, 0x15, mode->crtc_vsync_end - mode->crtc_vsync_start); ++ ++ /* vpixels is active pixels */ ++ wrptr = udl_set_register_16(wrptr, 0x17, mode->crtc_vdisplay); ++ ++ wrptr = udl_set_register_16be(wrptr, 0x1B, ++ mode->clock / 5); ++ ++ return wrptr; ++} ++ ++static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct udl_device *udl = dev->dev_private; ++ struct urb *urb; ++ char *buf; ++ int retval; ++ ++ urb = udl_get_urb(dev); ++ if (!urb) ++ return -ENOMEM; ++ ++ buf = (char *)urb->transfer_buffer; ++ ++ memcpy(buf, udl->mode_buf, udl->mode_buf_len); ++ retval = udl_submit_urb(dev, urb, udl->mode_buf_len); ++ DRM_INFO("write mode info %d\n", udl->mode_buf_len); ++ return retval; ++} ++ ++ ++static void udl_crtc_dpms(struct drm_crtc *crtc, int mode) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct udl_device *udl = dev->dev_private; ++ int retval; ++ ++ if (mode == DRM_MODE_DPMS_OFF) { ++ char *buf; ++ struct urb *urb; ++ urb = udl_get_urb(dev); ++ if (!urb) ++ return; ++ ++ buf = (char *)urb->transfer_buffer; ++ buf = udl_vidreg_lock(buf); ++ buf = udl_enable_hvsync(buf, false); ++ buf = udl_vidreg_unlock(buf); ++ ++ retval = udl_submit_urb(dev, urb, buf - (char *) ++ urb->transfer_buffer); ++ } else { ++ if (udl->mode_buf_len == 0) { ++ DRM_ERROR("Trying to enable DPMS with no mode\n"); ++ return; ++ } ++ udl_crtc_write_mode_to_hw(crtc); ++ } ++ ++} ++ ++static bool udl_crtc_mode_fixup(struct drm_crtc *crtc, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++ ++{ ++ return true; ++} ++ ++#if 0 ++static int ++udl_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, ++ int x, int y, enum mode_set_atomic state) ++{ ++ return 0; ++} ++ ++static int ++udl_pipe_set_base(struct drm_crtc *crtc, int x, int y, ++ struct drm_framebuffer *old_fb) ++{ ++ return 0; ++} ++#endif ++ ++static int udl_crtc_mode_set(struct drm_crtc *crtc, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode, ++ int x, int y, ++ struct drm_framebuffer *old_fb) ++ ++{ ++ struct drm_device *dev = crtc->dev; ++ struct udl_framebuffer *ufb = to_udl_fb(crtc->fb); ++ struct udl_device *udl = dev->dev_private; ++ char *buf; ++ char *wrptr; ++ int color_depth = 0; ++ ++ buf = (char *)udl->mode_buf; ++ ++ /* for now we just clip 24 -> 16 - if we fix that fix this */ ++ /*if (crtc->fb->bits_per_pixel != 16) ++ color_depth = 1; */ ++ ++ /* This first section has to do with setting the base address on the ++ * controller * associated with the display. There are 2 base ++ * pointers, currently, we only * use the 16 bpp segment. ++ */ ++ wrptr = udl_vidreg_lock(buf); ++ wrptr = udl_set_color_depth(wrptr, color_depth); ++ /* set base for 16bpp segment to 0 */ ++ wrptr = udl_set_base16bpp(wrptr, 0); ++ /* set base for 8bpp segment to end of fb */ ++ wrptr = udl_set_base8bpp(wrptr, 2 * mode->vdisplay * mode->hdisplay); ++ ++ wrptr = udl_set_vid_cmds(wrptr, adjusted_mode); ++ wrptr = udl_enable_hvsync(wrptr, true); ++ wrptr = udl_vidreg_unlock(wrptr); ++ ++ ufb->active_16 = true; ++ if (old_fb) { ++ struct udl_framebuffer *uold_fb = to_udl_fb(old_fb); ++ uold_fb->active_16 = false; ++ } ++ udl->mode_buf_len = wrptr - buf; ++ ++ /* damage all of it */ ++ udl_handle_damage(ufb, 0, 0, ufb->base.width, ufb->base.height); ++ return 0; ++} ++ ++ ++static void udl_crtc_disable(struct drm_crtc *crtc) ++{ ++ ++ ++} ++ ++static void udl_crtc_destroy(struct drm_crtc *crtc) ++{ ++ drm_crtc_cleanup(crtc); ++ kfree(crtc); ++} ++ ++static void udl_load_lut(struct drm_crtc *crtc) ++{ ++} ++ ++static void udl_crtc_prepare(struct drm_crtc *crtc) ++{ ++} ++ ++static void udl_crtc_commit(struct drm_crtc *crtc) ++{ ++ udl_crtc_dpms(crtc, DRM_MODE_DPMS_ON); ++} ++ ++static struct drm_crtc_helper_funcs udl_helper_funcs = { ++ .dpms = udl_crtc_dpms, ++ .mode_fixup = udl_crtc_mode_fixup, ++ .mode_set = udl_crtc_mode_set, ++ .prepare = udl_crtc_prepare, ++ .commit = udl_crtc_commit, ++ .disable = udl_crtc_disable, ++ .load_lut = udl_load_lut, ++}; ++ ++static const struct drm_crtc_funcs udl_crtc_funcs = { ++ .set_config = drm_crtc_helper_set_config, ++ .destroy = udl_crtc_destroy, ++}; ++ ++int udl_crtc_init(struct drm_device *dev) ++{ ++ struct drm_crtc *crtc; ++ ++ crtc = kzalloc(sizeof(struct drm_crtc) + sizeof(struct drm_connector *), GFP_KERNEL); ++ if (crtc == NULL) ++ return -ENOMEM; ++ ++ drm_crtc_init(dev, crtc, &udl_crtc_funcs); ++ drm_crtc_helper_add(crtc, &udl_helper_funcs); ++ ++ return 0; ++} ++ ++static const struct drm_mode_config_funcs udl_mode_funcs = { ++ .fb_create = udl_fb_user_fb_create, ++ .output_poll_changed = NULL, ++}; ++ ++int udl_modeset_init(struct drm_device *dev) ++{ ++ struct drm_encoder *encoder; ++ drm_mode_config_init(dev); ++ ++ dev->mode_config.min_width = 640; ++ dev->mode_config.min_height = 480; ++ ++ dev->mode_config.max_width = 2048; ++ dev->mode_config.max_height = 2048; ++ ++ dev->mode_config.prefer_shadow = 0; ++ dev->mode_config.preferred_depth = 24; ++ ++ dev->mode_config.funcs = (void *)&udl_mode_funcs; ++ ++ drm_mode_create_dirty_info_property(dev); ++ ++ udl_crtc_init(dev); ++ ++ encoder = udl_encoder_init(dev); ++ ++ udl_connector_init(dev, encoder); ++ ++ return 0; ++} ++ ++void udl_modeset_cleanup(struct drm_device *dev) ++{ ++ drm_mode_config_cleanup(dev); ++} +diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c +new file mode 100644 +index 0000000..fc11344 +--- /dev/null ++++ b/drivers/gpu/drm/udl/udl_transfer.c +@@ -0,0 +1,254 @@ ++/* ++ * Copyright (C) 2012 Red Hat ++ * based in parts on udlfb.c: ++ * Copyright (C) 2009 Roberto De Ioris ++ * Copyright (C) 2009 Jaya Kumar ++ * Copyright (C) 2009 Bernie Thompson ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License v2. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "drmP.h" ++#include "udl_drv.h" ++ ++#define MAX_CMD_PIXELS 255 ++ ++#define RLX_HEADER_BYTES 7 ++#define MIN_RLX_PIX_BYTES 4 ++#define MIN_RLX_CMD_BYTES (RLX_HEADER_BYTES + MIN_RLX_PIX_BYTES) ++ ++#define RLE_HEADER_BYTES 6 ++#define MIN_RLE_PIX_BYTES 3 ++#define MIN_RLE_CMD_BYTES (RLE_HEADER_BYTES + MIN_RLE_PIX_BYTES) ++ ++#define RAW_HEADER_BYTES 6 ++#define MIN_RAW_PIX_BYTES 2 ++#define MIN_RAW_CMD_BYTES (RAW_HEADER_BYTES + MIN_RAW_PIX_BYTES) ++ ++/* ++ * Trims identical data from front and back of line ++ * Sets new front buffer address and width ++ * And returns byte count of identical pixels ++ * Assumes CPU natural alignment (unsigned long) ++ * for back and front buffer ptrs and width ++ */ ++#if 0 ++static int udl_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes) ++{ ++ int j, k; ++ const unsigned long *back = (const unsigned long *) bback; ++ const unsigned long *front = (const unsigned long *) *bfront; ++ const int width = *width_bytes / sizeof(unsigned long); ++ int identical = width; ++ int start = width; ++ int end = width; ++ ++ prefetch((void *) front); ++ prefetch((void *) back); ++ ++ for (j = 0; j < width; j++) { ++ if (back[j] != front[j]) { ++ start = j; ++ break; ++ } ++ } ++ ++ for (k = width - 1; k > j; k--) { ++ if (back[k] != front[k]) { ++ end = k+1; ++ break; ++ } ++ } ++ ++ identical = start + (width - end); ++ *bfront = (u8 *) &front[start]; ++ *width_bytes = (end - start) * sizeof(unsigned long); ++ ++ return identical * sizeof(unsigned long); ++} ++#endif ++ ++static inline u16 pixel32_to_be16p(const uint8_t *pixel) ++{ ++ uint32_t pix = *(uint32_t *)pixel; ++ u16 retval; ++ ++ retval = (((pix >> 3) & 0x001f) | ++ ((pix >> 5) & 0x07e0) | ++ ((pix >> 8) & 0xf800)); ++ return retval; ++} ++ ++/* ++ * Render a command stream for an encoded horizontal line segment of pixels. ++ * ++ * A command buffer holds several commands. ++ * It always begins with a fresh command header ++ * (the protocol doesn't require this, but we enforce it to allow ++ * multiple buffers to be potentially encoded and sent in parallel). ++ * A single command encodes one contiguous horizontal line of pixels ++ * ++ * The function relies on the client to do all allocation, so that ++ * rendering can be done directly to output buffers (e.g. USB URBs). ++ * The function fills the supplied command buffer, providing information ++ * on where it left off, so the client may call in again with additional ++ * buffers if the line will take several buffers to complete. ++ * ++ * A single command can transmit a maximum of 256 pixels, ++ * regardless of the compression ratio (protocol design limit). ++ * To the hardware, 0 for a size byte means 256 ++ * ++ * Rather than 256 pixel commands which are either rl or raw encoded, ++ * the rlx command simply assumes alternating raw and rl spans within one cmd. ++ * This has a slightly larger header overhead, but produces more even results. ++ * It also processes all data (read and write) in a single pass. ++ * Performance benchmarks of common cases show it having just slightly better ++ * compression than 256 pixel raw or rle commands, with similar CPU consumpion. ++ * But for very rl friendly data, will compress not quite as well. ++ */ ++static void udl_compress_hline16( ++ const u8 **pixel_start_ptr, ++ const u8 *const pixel_end, ++ uint32_t *device_address_ptr, ++ uint8_t **command_buffer_ptr, ++ const uint8_t *const cmd_buffer_end, int bpp) ++{ ++ const u8 *pixel = *pixel_start_ptr; ++ uint32_t dev_addr = *device_address_ptr; ++ uint8_t *cmd = *command_buffer_ptr; ++ ++ while ((pixel_end > pixel) && ++ (cmd_buffer_end - MIN_RLX_CMD_BYTES > cmd)) { ++ uint8_t *raw_pixels_count_byte = 0; ++ uint8_t *cmd_pixels_count_byte = 0; ++ const u8 *raw_pixel_start = 0; ++ const u8 *cmd_pixel_start, *cmd_pixel_end = 0; ++ ++ prefetchw((void *) cmd); /* pull in one cache line at least */ ++ ++ *cmd++ = 0xaf; ++ *cmd++ = 0x6b; ++ *cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF); ++ *cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF); ++ *cmd++ = (uint8_t) ((dev_addr) & 0xFF); ++ ++ cmd_pixels_count_byte = cmd++; /* we'll know this later */ ++ cmd_pixel_start = pixel; ++ ++ raw_pixels_count_byte = cmd++; /* we'll know this later */ ++ raw_pixel_start = pixel; ++ ++ cmd_pixel_end = pixel + (min(MAX_CMD_PIXELS + 1, ++ min((int)(pixel_end - pixel) / bpp, ++ (int)(cmd_buffer_end - cmd) / 2))) * bpp; ++ ++ prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp); ++ ++ while (pixel < cmd_pixel_end) { ++ const u8 * const repeating_pixel = pixel; ++ ++ if (bpp == 2) ++ *(uint16_t *)cmd = cpu_to_be16p((uint16_t *)pixel); ++ else if (bpp == 4) ++ *(uint16_t *)cmd = cpu_to_be16(pixel32_to_be16p(pixel)); ++ ++ cmd += 2; ++ pixel += bpp; ++ ++ if (unlikely((pixel < cmd_pixel_end) && ++ (!memcmp(pixel, repeating_pixel, bpp)))) { ++ /* go back and fill in raw pixel count */ ++ *raw_pixels_count_byte = (((repeating_pixel - ++ raw_pixel_start) / bpp) + 1) & 0xFF; ++ ++ while ((pixel < cmd_pixel_end) ++ && (!memcmp(pixel, repeating_pixel, bpp))) { ++ pixel += bpp; ++ } ++ ++ /* immediately after raw data is repeat byte */ ++ *cmd++ = (((pixel - repeating_pixel) / bpp) - 1) & 0xFF; ++ ++ /* Then start another raw pixel span */ ++ raw_pixel_start = pixel; ++ raw_pixels_count_byte = cmd++; ++ } ++ } ++ ++ if (pixel > raw_pixel_start) { ++ /* finalize last RAW span */ ++ *raw_pixels_count_byte = ((pixel-raw_pixel_start) / bpp) & 0xFF; ++ } ++ ++ *cmd_pixels_count_byte = ((pixel - cmd_pixel_start) / bpp) & 0xFF; ++ dev_addr += ((pixel - cmd_pixel_start) / bpp) * 2; ++ } ++ ++ if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) { ++ /* Fill leftover bytes with no-ops */ ++ if (cmd_buffer_end > cmd) ++ memset(cmd, 0xAF, cmd_buffer_end - cmd); ++ cmd = (uint8_t *) cmd_buffer_end; ++ } ++ ++ *command_buffer_ptr = cmd; ++ *pixel_start_ptr = pixel; ++ *device_address_ptr = dev_addr; ++ ++ return; ++} ++ ++/* ++ * There are 3 copies of every pixel: The front buffer that the fbdev ++ * client renders to, the actual framebuffer across the USB bus in hardware ++ * (that we can only write to, slowly, and can never read), and (optionally) ++ * our shadow copy that tracks what's been sent to that hardware buffer. ++ */ ++int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, ++ const char *front, char **urb_buf_ptr, ++ u32 byte_offset, u32 device_byte_offset, ++ u32 byte_width, ++ int *ident_ptr, int *sent_ptr) ++{ ++ const u8 *line_start, *line_end, *next_pixel; ++ u32 base16 = 0 + (device_byte_offset / bpp) * 2; ++ struct urb *urb = *urb_ptr; ++ u8 *cmd = *urb_buf_ptr; ++ u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; ++ ++ line_start = (u8 *) (front + byte_offset); ++ next_pixel = line_start; ++ line_end = next_pixel + byte_width; ++ ++ while (next_pixel < line_end) { ++ ++ udl_compress_hline16(&next_pixel, ++ line_end, &base16, ++ (u8 **) &cmd, (u8 *) cmd_end, bpp); ++ ++ if (cmd >= cmd_end) { ++ int len = cmd - (u8 *) urb->transfer_buffer; ++ if (udl_submit_urb(dev, urb, len)) ++ return 1; /* lost pixels is set */ ++ *sent_ptr += len; ++ urb = udl_get_urb(dev); ++ if (!urb) ++ return 1; /* lost_pixels is set */ ++ *urb_ptr = urb; ++ cmd = urb->transfer_buffer; ++ cmd_end = &cmd[urb->transfer_buffer_length]; ++ } ++ } ++ ++ *urb_buf_ptr = cmd; ++ ++ return 0; ++} ++ +diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c +index a83e86d..02661f3 100644 +--- a/drivers/gpu/drm/via/via_drv.c ++++ b/drivers/gpu/drm/via/via_drv.c +@@ -30,16 +30,52 @@ + + #include "drm_pciids.h" + ++static int via_driver_open(struct drm_device *dev, struct drm_file *file) ++{ ++ struct via_file_private *file_priv; ++ ++ DRM_DEBUG_DRIVER("\n"); ++ file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL); ++ if (!file_priv) ++ return -ENOMEM; ++ ++ file->driver_priv = file_priv; ++ ++ INIT_LIST_HEAD(&file_priv->obj_list); ++ ++ return 0; ++} ++ ++void via_driver_postclose(struct drm_device *dev, struct drm_file *file) ++{ ++ struct via_file_private *file_priv = file->driver_priv; ++ ++ kfree(file_priv); ++} ++ + static struct pci_device_id pciidlist[] = { + viadrv_PCI_IDS + }; + ++static const struct file_operations via_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .mmap = drm_mmap, ++ .poll = drm_poll, ++ .fasync = drm_fasync, ++ .llseek = noop_llseek, ++}; ++ + static struct drm_driver driver = { + .driver_features = + DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | + DRIVER_IRQ_SHARED, + .load = via_driver_load, + .unload = via_driver_unload, ++ .open = via_driver_open, ++ .postclose = via_driver_postclose, + .context_dtor = via_final_context, + .get_vblank_counter = via_get_vblank_counter, + .enable_vblank = via_enable_vblank, +@@ -54,17 +90,7 @@ static struct drm_driver driver = { + .reclaim_buffers_idlelocked = via_reclaim_buffers_locked, + .lastclose = via_lastclose, + .ioctls = via_ioctls, +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = drm_ioctl, +- .mmap = drm_mmap, +- .poll = drm_poll, +- .fasync = drm_fasync, +- .llseek = noop_llseek, +- }, +- ++ .fops = &via_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, +diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h +index 9cf87d9..88edacc 100644 +--- a/drivers/gpu/drm/via/via_drv.h ++++ b/drivers/gpu/drm/via/via_drv.h +@@ -24,7 +24,7 @@ + #ifndef _VIA_DRV_H_ + #define _VIA_DRV_H_ + +-#include "drm_sman.h" ++#include "drm_mm.h" + #define DRIVER_AUTHOR "Various" + + #define DRIVER_NAME "via" +@@ -88,9 +88,12 @@ typedef struct drm_via_private { + uint32_t irq_pending_mask; + int *irq_map; + unsigned int idle_fault; +- struct drm_sman sman; + int vram_initialized; ++ struct drm_mm vram_mm; + int agp_initialized; ++ struct drm_mm agp_mm; ++ /** Mapping of userspace keys to mm objects */ ++ struct idr object_idr; + unsigned long vram_offset; + unsigned long agp_offset; + drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; +diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c +index 6cca9a7..c126182 100644 +--- a/drivers/gpu/drm/via/via_map.c ++++ b/drivers/gpu/drm/via/via_map.c +@@ -100,19 +100,15 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset) + if (dev_priv == NULL) + return -ENOMEM; + ++ idr_init(&dev_priv->object_idr); + dev->dev_private = (void *)dev_priv; + + dev_priv->chipset = chipset; + +- ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); +- if (ret) { +- kfree(dev_priv); +- return ret; +- } ++ pci_set_master(dev->pdev); + + ret = drm_vblank_init(dev, 1); + if (ret) { +- drm_sman_takedown(&dev_priv->sman); + kfree(dev_priv); + return ret; + } +@@ -124,7 +120,8 @@ int via_driver_unload(struct drm_device *dev) + { + drm_via_private_t *dev_priv = dev->dev_private; + +- drm_sman_takedown(&dev_priv->sman); ++ idr_remove_all(&dev_priv->object_idr); ++ idr_destroy(&dev_priv->object_idr); + + kfree(dev_priv); + +diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c +index 6cc2dad..a3574d0 100644 +--- a/drivers/gpu/drm/via/via_mm.c ++++ b/drivers/gpu/drm/via/via_mm.c +@@ -28,26 +28,22 @@ + #include "drmP.h" + #include "via_drm.h" + #include "via_drv.h" +-#include "drm_sman.h" + + #define VIA_MM_ALIGN_SHIFT 4 + #define VIA_MM_ALIGN_MASK ((1 << VIA_MM_ALIGN_SHIFT) - 1) + ++struct via_memblock { ++ struct drm_mm_node mm_node; ++ struct list_head owner_list; ++}; ++ + int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) + { + drm_via_agp_t *agp = data; + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; +- int ret; + + mutex_lock(&dev->struct_mutex); +- ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0, +- agp->size >> VIA_MM_ALIGN_SHIFT); +- +- if (ret) { +- DRM_ERROR("AGP memory manager initialisation error\n"); +- mutex_unlock(&dev->struct_mutex); +- return ret; +- } ++ drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> VIA_MM_ALIGN_SHIFT); + + dev_priv->agp_initialized = 1; + dev_priv->agp_offset = agp->offset; +@@ -61,17 +57,9 @@ int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv) + { + drm_via_fb_t *fb = data; + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; +- int ret; + + mutex_lock(&dev->struct_mutex); +- ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0, +- fb->size >> VIA_MM_ALIGN_SHIFT); +- +- if (ret) { +- DRM_ERROR("VRAM memory manager initialisation error\n"); +- mutex_unlock(&dev->struct_mutex); +- return ret; +- } ++ drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> VIA_MM_ALIGN_SHIFT); + + dev_priv->vram_initialized = 1; + dev_priv->vram_offset = fb->offset; +@@ -108,19 +96,25 @@ void via_lastclose(struct drm_device *dev) + return; + + mutex_lock(&dev->struct_mutex); +- drm_sman_cleanup(&dev_priv->sman); +- dev_priv->vram_initialized = 0; +- dev_priv->agp_initialized = 0; ++ if (dev_priv->vram_initialized) { ++ drm_mm_takedown(&dev_priv->vram_mm); ++ dev_priv->vram_initialized = 0; ++ } ++ if (dev_priv->agp_initialized) { ++ drm_mm_takedown(&dev_priv->agp_mm); ++ dev_priv->agp_initialized = 0; ++ } + mutex_unlock(&dev->struct_mutex); + } + + int via_mem_alloc(struct drm_device *dev, void *data, +- struct drm_file *file_priv) ++ struct drm_file *file) + { + drm_via_mem_t *mem = data; +- int retval = 0; +- struct drm_memblock_item *item; ++ int retval = 0, user_key; ++ struct via_memblock *item; + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; ++ struct via_file_private *file_priv = file->driver_priv; + unsigned long tmpSize; + + if (mem->type > VIA_MEM_AGP) { +@@ -136,24 +130,57 @@ int via_mem_alloc(struct drm_device *dev, void *data, + return -EINVAL; + } + ++ item = kzalloc(sizeof(*item), GFP_KERNEL); ++ if (!item) { ++ retval = -ENOMEM; ++ goto fail_alloc; ++ } ++ + tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; +- item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0, +- (unsigned long)file_priv); +- mutex_unlock(&dev->struct_mutex); +- if (item) { +- mem->offset = ((mem->type == VIA_MEM_VIDEO) ? +- dev_priv->vram_offset : dev_priv->agp_offset) + +- (item->mm-> +- offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT); +- mem->index = item->user_hash.key; +- } else { +- mem->offset = 0; +- mem->size = 0; +- mem->index = 0; +- DRM_DEBUG("Video memory allocation failed\n"); ++ if (mem->type == VIA_MEM_AGP) ++ retval = drm_mm_insert_node(&dev_priv->agp_mm, ++ &item->mm_node, ++ tmpSize, 0); ++ else ++ retval = drm_mm_insert_node(&dev_priv->vram_mm, ++ &item->mm_node, ++ tmpSize, 0); ++ if (retval) ++ goto fail_alloc; ++ ++again: ++ if (idr_pre_get(&dev_priv->object_idr, GFP_KERNEL) == 0) { + retval = -ENOMEM; ++ goto fail_idr; + } + ++ retval = idr_get_new_above(&dev_priv->object_idr, item, 1, &user_key); ++ if (retval == -EAGAIN) ++ goto again; ++ if (retval) ++ goto fail_idr; ++ ++ list_add(&item->owner_list, &file_priv->obj_list); ++ mutex_unlock(&dev->struct_mutex); ++ ++ mem->offset = ((mem->type == VIA_MEM_VIDEO) ? ++ dev_priv->vram_offset : dev_priv->agp_offset) + ++ ((item->mm_node.start) << VIA_MM_ALIGN_SHIFT); ++ mem->index = user_key; ++ ++ return 0; ++ ++fail_idr: ++ drm_mm_remove_node(&item->mm_node); ++fail_alloc: ++ kfree(item); ++ mutex_unlock(&dev->struct_mutex); ++ ++ mem->offset = 0; ++ mem->size = 0; ++ mem->index = 0; ++ DRM_DEBUG("Video memory allocation failed\n"); ++ + return retval; + } + +@@ -161,24 +188,35 @@ int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) + { + drm_via_private_t *dev_priv = dev->dev_private; + drm_via_mem_t *mem = data; +- int ret; ++ struct via_memblock *obj; + + mutex_lock(&dev->struct_mutex); +- ret = drm_sman_free_key(&dev_priv->sman, mem->index); ++ obj = idr_find(&dev_priv->object_idr, mem->index); ++ if (obj == NULL) { ++ mutex_unlock(&dev->struct_mutex); ++ return -EINVAL; ++ } ++ ++ idr_remove(&dev_priv->object_idr, mem->index); ++ list_del(&obj->owner_list); ++ drm_mm_remove_node(&obj->mm_node); ++ kfree(obj); + mutex_unlock(&dev->struct_mutex); ++ + DRM_DEBUG("free = 0x%lx\n", mem->index); + +- return ret; ++ return 0; + } + + + void via_reclaim_buffers_locked(struct drm_device *dev, +- struct drm_file *file_priv) ++ struct drm_file *file) + { +- drm_via_private_t *dev_priv = dev->dev_private; ++ struct via_file_private *file_priv = file->driver_priv; ++ struct via_memblock *entry, *next; + + mutex_lock(&dev->struct_mutex); +- if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) { ++ if (list_empty(&file_priv->obj_list)) { + mutex_unlock(&dev->struct_mutex); + return; + } +@@ -186,7 +224,12 @@ void via_reclaim_buffers_locked(struct drm_device *dev, + if (dev->driver->dma_quiescent) + dev->driver->dma_quiescent(dev); + +- drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv); ++ list_for_each_entry_safe(entry, next, &file_priv->obj_list, ++ owner_list) { ++ list_del(&entry->owner_list); ++ drm_mm_remove_node(&entry->mm_node); ++ kfree(entry); ++ } + mutex_unlock(&dev->struct_mutex); + return; + } +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +index 5a72ed9..1e2c0fb 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +@@ -28,6 +28,7 @@ + #include "vmwgfx_drv.h" + #include "ttm/ttm_bo_driver.h" + #include "ttm/ttm_placement.h" ++#include "ttm/ttm_page_alloc.h" + + static uint32_t vram_placement_flags = TTM_PL_FLAG_VRAM | + TTM_PL_FLAG_CACHED; +@@ -139,85 +140,63 @@ struct ttm_placement vmw_srf_placement = { + .busy_placement = gmr_vram_placement_flags + }; + +-struct vmw_ttm_backend { +- struct ttm_backend backend; +- struct page **pages; +- unsigned long num_pages; ++struct vmw_ttm_tt { ++ struct ttm_tt ttm; + struct vmw_private *dev_priv; + int gmr_id; + }; + +-static int vmw_ttm_populate(struct ttm_backend *backend, +- unsigned long num_pages, struct page **pages, +- struct page *dummy_read_page, +- dma_addr_t *dma_addrs) ++static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) + { +- struct vmw_ttm_backend *vmw_be = +- container_of(backend, struct vmw_ttm_backend, backend); +- +- vmw_be->pages = pages; +- vmw_be->num_pages = num_pages; +- +- return 0; +-} +- +-static int vmw_ttm_bind(struct ttm_backend *backend, struct ttm_mem_reg *bo_mem) +-{ +- struct vmw_ttm_backend *vmw_be = +- container_of(backend, struct vmw_ttm_backend, backend); ++ struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, ttm); + + vmw_be->gmr_id = bo_mem->start; + +- return vmw_gmr_bind(vmw_be->dev_priv, vmw_be->pages, +- vmw_be->num_pages, vmw_be->gmr_id); ++ return vmw_gmr_bind(vmw_be->dev_priv, ttm->pages, ++ ttm->num_pages, vmw_be->gmr_id); + } + +-static int vmw_ttm_unbind(struct ttm_backend *backend) ++static int vmw_ttm_unbind(struct ttm_tt *ttm) + { +- struct vmw_ttm_backend *vmw_be = +- container_of(backend, struct vmw_ttm_backend, backend); ++ struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, ttm); + + vmw_gmr_unbind(vmw_be->dev_priv, vmw_be->gmr_id); + return 0; + } + +-static void vmw_ttm_clear(struct ttm_backend *backend) ++static void vmw_ttm_destroy(struct ttm_tt *ttm) + { +- struct vmw_ttm_backend *vmw_be = +- container_of(backend, struct vmw_ttm_backend, backend); +- +- vmw_be->pages = NULL; +- vmw_be->num_pages = 0; +-} +- +-static void vmw_ttm_destroy(struct ttm_backend *backend) +-{ +- struct vmw_ttm_backend *vmw_be = +- container_of(backend, struct vmw_ttm_backend, backend); ++ struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, ttm); + ++ ttm_tt_fini(ttm); + kfree(vmw_be); + } + + static struct ttm_backend_func vmw_ttm_func = { +- .populate = vmw_ttm_populate, +- .clear = vmw_ttm_clear, + .bind = vmw_ttm_bind, + .unbind = vmw_ttm_unbind, + .destroy = vmw_ttm_destroy, + }; + +-struct ttm_backend *vmw_ttm_backend_init(struct ttm_bo_device *bdev) ++struct ttm_tt *vmw_ttm_tt_create(struct ttm_bo_device *bdev, ++ unsigned long size, uint32_t page_flags, ++ struct page *dummy_read_page) + { +- struct vmw_ttm_backend *vmw_be; ++ struct vmw_ttm_tt *vmw_be; + + vmw_be = kmalloc(sizeof(*vmw_be), GFP_KERNEL); + if (!vmw_be) + return NULL; + +- vmw_be->backend.func = &vmw_ttm_func; ++ vmw_be->ttm.func = &vmw_ttm_func; + vmw_be->dev_priv = container_of(bdev, struct vmw_private, bdev); + +- return &vmw_be->backend; ++ if (ttm_tt_init(&vmw_be->ttm, bdev, size, page_flags, dummy_read_page)) { ++ kfree(vmw_be); ++ return NULL; ++ } ++ ++ return &vmw_be->ttm; + } + + int vmw_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags) +@@ -357,7 +336,9 @@ static int vmw_sync_obj_wait(void *sync_obj, void *sync_arg, + } + + struct ttm_bo_driver vmw_bo_driver = { +- .create_ttm_backend_entry = vmw_ttm_backend_init, ++ .ttm_tt_create = &vmw_ttm_tt_create, ++ .ttm_tt_populate = &ttm_pool_populate, ++ .ttm_tt_unpopulate = &ttm_pool_unpopulate, + .invalidate_caches = vmw_invalidate_caches, + .init_mem_type = vmw_init_mem_type, + .evict_flags = vmw_evict_flags, +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +index f739fcf..1a35795 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +@@ -38,6 +38,10 @@ + #define VMWGFX_CHIP_SVGAII 0 + #define VMW_FB_RESERVATION 0 + ++#define VMW_MIN_INITIAL_WIDTH 800 ++#define VMW_MIN_INITIAL_HEIGHT 600 ++ ++ + /** + * Fully encoded drm commands. Might move to vmw_drm.h + */ +@@ -388,6 +392,41 @@ void vmw_3d_resource_dec(struct vmw_private *dev_priv, + BUG_ON(n3d < 0); + } + ++/** ++ * Sets the initial_[width|height] fields on the given vmw_private. ++ * ++ * It does so by reading SVGA_REG_[WIDTH|HEIGHT] regs and then ++ * clamping the value to fb_max_[width|height] fields and the ++ * VMW_MIN_INITIAL_[WIDTH|HEIGHT]. ++ * If the values appear to be invalid, set them to ++ * VMW_MIN_INITIAL_[WIDTH|HEIGHT]. ++ */ ++static void vmw_get_initial_size(struct vmw_private *dev_priv) ++{ ++ uint32_t width; ++ uint32_t height; ++ ++ width = vmw_read(dev_priv, SVGA_REG_WIDTH); ++ height = vmw_read(dev_priv, SVGA_REG_HEIGHT); ++ ++ width = max_t(uint32_t, width, VMW_MIN_INITIAL_WIDTH); ++ height = max_t(uint32_t, height, VMW_MIN_INITIAL_HEIGHT); ++ ++ if (width > dev_priv->fb_max_width || ++ height > dev_priv->fb_max_height) { ++ ++ /* ++ * This is a host error and shouldn't occur. ++ */ ++ ++ width = VMW_MIN_INITIAL_WIDTH; ++ height = VMW_MIN_INITIAL_HEIGHT; ++ } ++ ++ dev_priv->initial_width = width; ++ dev_priv->initial_height = height; ++} ++ + static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) + { + struct vmw_private *dev_priv; +@@ -401,6 +440,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) + } + memset(dev_priv, 0, sizeof(*dev_priv)); + ++ pci_set_master(dev->pdev); ++ + dev_priv->dev = dev; + dev_priv->vmw_chipset = chipset; + dev_priv->last_read_seqno = (uint32_t) -100; +@@ -431,7 +472,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) + svga_id = vmw_read(dev_priv, SVGA_REG_ID); + if (svga_id != SVGA_ID_2) { + ret = -ENOSYS; +- DRM_ERROR("Unsuported SVGA ID 0x%x\n", svga_id); ++ DRM_ERROR("Unsupported SVGA ID 0x%x\n", svga_id); + mutex_unlock(&dev_priv->hw_mutex); + goto out_err0; + } +@@ -442,6 +483,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) + dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE); + dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH); + dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT); ++ ++ vmw_get_initial_size(dev_priv); ++ + if (dev_priv->capabilities & SVGA_CAP_GMR) { + dev_priv->max_gmr_descriptors = + vmw_read(dev_priv, +@@ -692,6 +736,15 @@ static int vmw_driver_unload(struct drm_device *dev) + return 0; + } + ++static void vmw_preclose(struct drm_device *dev, ++ struct drm_file *file_priv) ++{ ++ struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); ++ struct vmw_private *dev_priv = vmw_priv(dev); ++ ++ vmw_event_fence_fpriv_gone(dev_priv->fman, &vmw_fp->fence_events); ++} ++ + static void vmw_postclose(struct drm_device *dev, + struct drm_file *file_priv) + { +@@ -714,6 +767,7 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv) + if (unlikely(vmw_fp == NULL)) + return ret; + ++ INIT_LIST_HEAD(&vmw_fp->fence_events); + vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev, 10); + if (unlikely(vmw_fp->tfile == NULL)) + goto out_no_tfile; +@@ -1073,6 +1127,21 @@ static const struct dev_pm_ops vmw_pm_ops = { + .resume = vmw_pm_resume, + }; + ++static const struct file_operations vmwgfx_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = vmw_unlocked_ioctl, ++ .mmap = vmw_mmap, ++ .poll = vmw_fops_poll, ++ .read = vmw_fops_read, ++ .fasync = drm_fasync, ++#if defined(CONFIG_COMPAT) ++ .compat_ioctl = drm_compat_ioctl, ++#endif ++ .llseek = noop_llseek, ++}; ++ + static struct drm_driver driver = { + .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | + DRIVER_MODESET, +@@ -1096,26 +1165,14 @@ static struct drm_driver driver = { + .master_set = vmw_master_set, + .master_drop = vmw_master_drop, + .open = vmw_driver_open, ++ .preclose = vmw_preclose, + .postclose = vmw_postclose, + + .dumb_create = vmw_dumb_create, + .dumb_map_offset = vmw_dumb_map_offset, + .dumb_destroy = vmw_dumb_destroy, + +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = vmw_unlocked_ioctl, +- .mmap = vmw_mmap, +- .poll = vmw_fops_poll, +- .read = vmw_fops_read, +- .fasync = drm_fasync, +-#if defined(CONFIG_COMPAT) +- .compat_ioctl = drm_compat_ioctl, +-#endif +- .llseek = noop_llseek, +- }, ++ .fops = &vmwgfx_driver_fops, + .name = VMWGFX_DRIVER_NAME, + .desc = VMWGFX_DRIVER_DESC, + .date = VMWGFX_DRIVER_DATE, +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +index 0e3fa7d..29c984f 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +@@ -40,9 +40,9 @@ + #include "ttm/ttm_module.h" + #include "vmwgfx_fence.h" + +-#define VMWGFX_DRIVER_DATE "20111025" ++#define VMWGFX_DRIVER_DATE "20120209" + #define VMWGFX_DRIVER_MAJOR 2 +-#define VMWGFX_DRIVER_MINOR 3 ++#define VMWGFX_DRIVER_MINOR 4 + #define VMWGFX_DRIVER_PATCHLEVEL 0 + #define VMWGFX_FILE_PAGE_OFFSET 0x00100000 + #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) +@@ -62,6 +62,7 @@ + struct vmw_fpriv { + struct drm_master *locked_master; + struct ttm_object_file *tfile; ++ struct list_head fence_events; + }; + + struct vmw_dma_buffer { +@@ -202,6 +203,8 @@ struct vmw_private { + uint32_t mmio_size; + uint32_t fb_max_width; + uint32_t fb_max_height; ++ uint32_t initial_width; ++ uint32_t initial_height; + __le32 __iomem *mmio_virt; + int mmio_mtrr; + uint32_t capabilities; +@@ -533,7 +536,8 @@ extern int vmw_execbuf_process(struct drm_file *file_priv, + uint32_t command_size, + uint64_t throttle_us, + struct drm_vmw_fence_rep __user +- *user_fence_rep); ++ *user_fence_rep, ++ struct vmw_fence_obj **out_fence); + + extern void + vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +index 84ba033..4acced4 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +@@ -558,36 +558,14 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, + } *cmd; + int ret; + struct vmw_resource *res; +- SVGA3dCmdSurfaceDMASuffix *suffix; +- uint32_t bo_size; + + cmd = container_of(header, struct vmw_dma_cmd, header); +- suffix = (SVGA3dCmdSurfaceDMASuffix *)((unsigned long) &cmd->dma + +- header->size - sizeof(*suffix)); +- +- /* Make sure device and verifier stays in sync. */ +- if (unlikely(suffix->suffixSize != sizeof(*suffix))) { +- DRM_ERROR("Invalid DMA suffix size.\n"); +- return -EINVAL; +- } +- + ret = vmw_translate_guest_ptr(dev_priv, sw_context, + &cmd->dma.guest.ptr, + &vmw_bo); + if (unlikely(ret != 0)) + return ret; + +- /* Make sure DMA doesn't cross BO boundaries. */ +- bo_size = vmw_bo->base.num_pages * PAGE_SIZE; +- if (unlikely(cmd->dma.guest.ptr.offset > bo_size)) { +- DRM_ERROR("Invalid DMA offset.\n"); +- return -EINVAL; +- } +- +- bo_size -= cmd->dma.guest.ptr.offset; +- if (unlikely(suffix->maximumOffset > bo_size)) +- suffix->maximumOffset = bo_size; +- + bo = &vmw_bo->base; + ret = vmw_user_surface_lookup_handle(dev_priv, sw_context->tfile, + cmd->dma.host.sid, &srf); +@@ -1131,10 +1109,11 @@ int vmw_execbuf_process(struct drm_file *file_priv, + void *kernel_commands, + uint32_t command_size, + uint64_t throttle_us, +- struct drm_vmw_fence_rep __user *user_fence_rep) ++ struct drm_vmw_fence_rep __user *user_fence_rep, ++ struct vmw_fence_obj **out_fence) + { + struct vmw_sw_context *sw_context = &dev_priv->ctx; +- struct vmw_fence_obj *fence; ++ struct vmw_fence_obj *fence = NULL; + uint32_t handle; + void *cmd; + int ret; +@@ -1230,8 +1209,13 @@ int vmw_execbuf_process(struct drm_file *file_priv, + vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, + user_fence_rep, fence, handle); + +- if (likely(fence != NULL)) ++ /* Don't unreference when handing fence out */ ++ if (unlikely(out_fence != NULL)) { ++ *out_fence = fence; ++ fence = NULL; ++ } else if (likely(fence != NULL)) { + vmw_fence_obj_unreference(&fence); ++ } + + mutex_unlock(&dev_priv->cmdbuf_mutex); + return 0; +@@ -1384,7 +1368,8 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data, + ret = vmw_execbuf_process(file_priv, dev_priv, + (void __user *)(unsigned long)arg->commands, + NULL, arg->command_size, arg->throttle_us, +- (void __user *)(unsigned long)arg->fence_rep); ++ (void __user *)(unsigned long)arg->fence_rep, ++ NULL); + + if (unlikely(ret != 0)) + goto out_unlock; +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +index 7f16ff2..7fc3dc7 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +@@ -416,10 +416,6 @@ int vmw_fb_init(struct vmw_private *vmw_priv) + unsigned fb_bpp, fb_depth, fb_offset, fb_pitch, fb_size; + int ret; + +- /* XXX These shouldn't be hardcoded. */ +- initial_width = 800; +- initial_height = 600; +- + fb_bpp = 32; + fb_depth = 24; + +@@ -427,8 +423,8 @@ int vmw_fb_init(struct vmw_private *vmw_priv) + fb_width = min(vmw_priv->fb_max_width, (unsigned)2048); + fb_height = min(vmw_priv->fb_max_height, (unsigned)2048); + +- initial_width = min(fb_width, initial_width); +- initial_height = min(fb_height, initial_height); ++ initial_width = min(vmw_priv->initial_width, fb_width); ++ initial_height = min(vmw_priv->initial_height, fb_height); + + fb_pitch = fb_width * fb_bpp / 8; + fb_size = fb_pitch * fb_height; +@@ -517,19 +513,7 @@ int vmw_fb_init(struct vmw_private *vmw_priv) + info->var.xres = initial_width; + info->var.yres = initial_height; + +-#if 0 +- info->pixmap.size = 64*1024; +- info->pixmap.buf_align = 8; +- info->pixmap.access_align = 32; +- info->pixmap.flags = FB_PIXMAP_SYSTEM; +- info->pixmap.scan_align = 1; +-#else +- info->pixmap.size = 0; +- info->pixmap.buf_align = 8; +- info->pixmap.access_align = 32; +- info->pixmap.flags = FB_PIXMAP_SYSTEM; +- info->pixmap.scan_align = 1; +-#endif ++ /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ + + info->apertures = alloc_apertures(1); + if (!info->apertures) { +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +index 1ed5a1c..7e07433 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +@@ -69,12 +69,13 @@ struct vmw_user_fence { + * be assigned the current time tv_usec val when the fence signals. + */ + struct vmw_event_fence_action { +- struct drm_pending_event e; + struct vmw_fence_action action; ++ struct list_head fpriv_head; ++ ++ struct drm_pending_event *event; + struct vmw_fence_obj *fence; + struct drm_device *dev; +- struct kref kref; +- uint32_t size; ++ + uint32_t *tv_sec; + uint32_t *tv_usec; + }; +@@ -484,7 +485,14 @@ void vmw_fence_obj_flush(struct vmw_fence_obj *fence) + + static void vmw_fence_destroy(struct vmw_fence_obj *fence) + { ++ struct vmw_fence_manager *fman = fence->fman; ++ + kfree(fence); ++ /* ++ * Free kernel space accounting. ++ */ ++ ttm_mem_global_free(vmw_mem_glob(fman->dev_priv), ++ fman->fence_size); + } + + int vmw_fence_create(struct vmw_fence_manager *fman, +@@ -492,12 +500,20 @@ int vmw_fence_create(struct vmw_fence_manager *fman, + uint32_t mask, + struct vmw_fence_obj **p_fence) + { ++ struct ttm_mem_global *mem_glob = vmw_mem_glob(fman->dev_priv); + struct vmw_fence_obj *fence; + int ret; + ++ ret = ttm_mem_global_alloc(mem_glob, fman->fence_size, ++ false, false); ++ if (unlikely(ret != 0)) ++ return ret; ++ + fence = kzalloc(sizeof(*fence), GFP_KERNEL); +- if (unlikely(fence == NULL)) +- return -ENOMEM; ++ if (unlikely(fence == NULL)) { ++ ret = -ENOMEM; ++ goto out_no_object; ++ } + + ret = vmw_fence_obj_init(fman, fence, seqno, mask, + vmw_fence_destroy); +@@ -509,6 +525,8 @@ int vmw_fence_create(struct vmw_fence_manager *fman, + + out_err_init: + kfree(fence); ++out_no_object: ++ ttm_mem_global_free(mem_glob, fman->fence_size); + return ret; + } + +@@ -767,46 +785,40 @@ int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data, + } + + /** +- * vmw_event_fence_action_destroy +- * +- * @kref: The struct kref embedded in a struct vmw_event_fence_action. +- * +- * The vmw_event_fence_action destructor that may be called either after +- * the fence action cleanup, or when the event is delivered. +- * It frees both the vmw_event_fence_action struct and the actual +- * event structure copied to user-space. +- */ +-static void vmw_event_fence_action_destroy(struct kref *kref) +-{ +- struct vmw_event_fence_action *eaction = +- container_of(kref, struct vmw_event_fence_action, kref); +- struct ttm_mem_global *mem_glob = +- vmw_mem_glob(vmw_priv(eaction->dev)); +- uint32_t size = eaction->size; +- +- kfree(eaction->e.event); +- kfree(eaction); +- ttm_mem_global_free(mem_glob, size); +-} +- +- +-/** +- * vmw_event_fence_action_delivered ++ * vmw_event_fence_fpriv_gone - Remove references to struct drm_file objects + * +- * @e: The struct drm_pending_event embedded in a struct +- * vmw_event_fence_action. ++ * @fman: Pointer to a struct vmw_fence_manager ++ * @event_list: Pointer to linked list of struct vmw_event_fence_action objects ++ * with pointers to a struct drm_file object about to be closed. + * +- * The struct drm_pending_event destructor that is called by drm +- * once the event is delivered. Since we don't know whether this function +- * will be called before or after the fence action destructor, we +- * free a refcount and destroy if it becomes zero. ++ * This function removes all pending fence events with references to a ++ * specific struct drm_file object about to be closed. The caller is required ++ * to pass a list of all struct vmw_event_fence_action objects with such ++ * events attached. This function is typically called before the ++ * struct drm_file object's event management is taken down. + */ +-static void vmw_event_fence_action_delivered(struct drm_pending_event *e) ++void vmw_event_fence_fpriv_gone(struct vmw_fence_manager *fman, ++ struct list_head *event_list) + { +- struct vmw_event_fence_action *eaction = +- container_of(e, struct vmw_event_fence_action, e); ++ struct vmw_event_fence_action *eaction; ++ struct drm_pending_event *event; ++ unsigned long irq_flags; + +- kref_put(&eaction->kref, vmw_event_fence_action_destroy); ++ while (1) { ++ spin_lock_irqsave(&fman->lock, irq_flags); ++ if (list_empty(event_list)) ++ goto out_unlock; ++ eaction = list_first_entry(event_list, ++ struct vmw_event_fence_action, ++ fpriv_head); ++ list_del_init(&eaction->fpriv_head); ++ event = eaction->event; ++ eaction->event = NULL; ++ spin_unlock_irqrestore(&fman->lock, irq_flags); ++ event->destroy(event); ++ } ++out_unlock: ++ spin_unlock_irqrestore(&fman->lock, irq_flags); + } + + +@@ -819,18 +831,21 @@ static void vmw_event_fence_action_delivered(struct drm_pending_event *e) + * This function is called when the seqno of the fence where @action is + * attached has passed. It queues the event on the submitter's event list. + * This function is always called from atomic context, and may be called +- * from irq context. It ups a refcount reflecting that we now have two +- * destructors. ++ * from irq context. + */ + static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) + { + struct vmw_event_fence_action *eaction = + container_of(action, struct vmw_event_fence_action, action); + struct drm_device *dev = eaction->dev; +- struct drm_file *file_priv = eaction->e.file_priv; ++ struct drm_pending_event *event = eaction->event; ++ struct drm_file *file_priv; + unsigned long irq_flags; + +- kref_get(&eaction->kref); ++ if (unlikely(event == NULL)) ++ return; ++ ++ file_priv = event->file_priv; + spin_lock_irqsave(&dev->event_lock, irq_flags); + + if (likely(eaction->tv_sec != NULL)) { +@@ -841,7 +856,9 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) + *eaction->tv_usec = tv.tv_usec; + } + +- list_add_tail(&eaction->e.link, &file_priv->event_list); ++ list_del_init(&eaction->fpriv_head); ++ list_add_tail(&eaction->event->link, &file_priv->event_list); ++ eaction->event = NULL; + wake_up_all(&file_priv->event_wait); + spin_unlock_irqrestore(&dev->event_lock, irq_flags); + } +@@ -859,9 +876,15 @@ static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action) + { + struct vmw_event_fence_action *eaction = + container_of(action, struct vmw_event_fence_action, action); ++ struct vmw_fence_manager *fman = eaction->fence->fman; ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&fman->lock, irq_flags); ++ list_del(&eaction->fpriv_head); ++ spin_unlock_irqrestore(&fman->lock, irq_flags); + + vmw_fence_obj_unreference(&eaction->fence); +- kref_put(&eaction->kref, vmw_event_fence_action_destroy); ++ kfree(eaction); + } + + +@@ -929,39 +952,23 @@ void vmw_fence_obj_add_action(struct vmw_fence_obj *fence, + * an error code, the caller needs to free that object. + */ + +-int vmw_event_fence_action_create(struct drm_file *file_priv, +- struct vmw_fence_obj *fence, +- struct drm_event *event, +- uint32_t *tv_sec, +- uint32_t *tv_usec, +- bool interruptible) ++int vmw_event_fence_action_queue(struct drm_file *file_priv, ++ struct vmw_fence_obj *fence, ++ struct drm_pending_event *event, ++ uint32_t *tv_sec, ++ uint32_t *tv_usec, ++ bool interruptible) + { + struct vmw_event_fence_action *eaction; +- struct ttm_mem_global *mem_glob = +- vmw_mem_glob(fence->fman->dev_priv); + struct vmw_fence_manager *fman = fence->fman; +- uint32_t size = fman->event_fence_action_size + +- ttm_round_pot(event->length); +- int ret; +- +- /* +- * Account for internal structure size as well as the +- * event size itself. +- */ +- +- ret = ttm_mem_global_alloc(mem_glob, size, false, interruptible); +- if (unlikely(ret != 0)) +- return ret; ++ struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); ++ unsigned long irq_flags; + + eaction = kzalloc(sizeof(*eaction), GFP_KERNEL); +- if (unlikely(eaction == NULL)) { +- ttm_mem_global_free(mem_glob, size); ++ if (unlikely(eaction == NULL)) + return -ENOMEM; +- } + +- eaction->e.event = event; +- eaction->e.file_priv = file_priv; +- eaction->e.destroy = vmw_event_fence_action_delivered; ++ eaction->event = event; + + eaction->action.seq_passed = vmw_event_fence_action_seq_passed; + eaction->action.cleanup = vmw_event_fence_action_cleanup; +@@ -969,16 +976,89 @@ int vmw_event_fence_action_create(struct drm_file *file_priv, + + eaction->fence = vmw_fence_obj_reference(fence); + eaction->dev = fman->dev_priv->dev; +- eaction->size = size; + eaction->tv_sec = tv_sec; + eaction->tv_usec = tv_usec; + +- kref_init(&eaction->kref); ++ spin_lock_irqsave(&fman->lock, irq_flags); ++ list_add_tail(&eaction->fpriv_head, &vmw_fp->fence_events); ++ spin_unlock_irqrestore(&fman->lock, irq_flags); ++ + vmw_fence_obj_add_action(fence, &eaction->action); + + return 0; + } + ++struct vmw_event_fence_pending { ++ struct drm_pending_event base; ++ struct drm_vmw_event_fence event; ++}; ++ ++int vmw_event_fence_action_create(struct drm_file *file_priv, ++ struct vmw_fence_obj *fence, ++ uint32_t flags, ++ uint64_t user_data, ++ bool interruptible) ++{ ++ struct vmw_event_fence_pending *event; ++ struct drm_device *dev = fence->fman->dev_priv->dev; ++ unsigned long irq_flags; ++ int ret; ++ ++ spin_lock_irqsave(&dev->event_lock, irq_flags); ++ ++ ret = (file_priv->event_space < sizeof(event->event)) ? -EBUSY : 0; ++ if (likely(ret == 0)) ++ file_priv->event_space -= sizeof(event->event); ++ ++ spin_unlock_irqrestore(&dev->event_lock, irq_flags); ++ ++ if (unlikely(ret != 0)) { ++ DRM_ERROR("Failed to allocate event space for this file.\n"); ++ goto out_no_space; ++ } ++ ++ ++ event = kzalloc(sizeof(*event), GFP_KERNEL); ++ if (unlikely(event == NULL)) { ++ DRM_ERROR("Failed to allocate an event.\n"); ++ ret = -ENOMEM; ++ goto out_no_event; ++ } ++ ++ event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED; ++ event->event.base.length = sizeof(*event); ++ event->event.user_data = user_data; ++ ++ event->base.event = &event->event.base; ++ event->base.file_priv = file_priv; ++ event->base.destroy = (void (*) (struct drm_pending_event *)) kfree; ++ ++ ++ if (flags & DRM_VMW_FE_FLAG_REQ_TIME) ++ ret = vmw_event_fence_action_queue(file_priv, fence, ++ &event->base, ++ &event->event.tv_sec, ++ &event->event.tv_usec, ++ interruptible); ++ else ++ ret = vmw_event_fence_action_queue(file_priv, fence, ++ &event->base, ++ NULL, ++ NULL, ++ interruptible); ++ if (ret != 0) ++ goto out_no_queue; ++ ++out_no_queue: ++ event->base.destroy(&event->base); ++out_no_event: ++ spin_lock_irqsave(&dev->event_lock, irq_flags); ++ file_priv->event_space += sizeof(*event); ++ spin_unlock_irqrestore(&dev->event_lock, irq_flags); ++out_no_space: ++ return ret; ++} ++ + int vmw_fence_event_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) + { +@@ -991,8 +1071,6 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, + (struct drm_vmw_fence_rep __user *)(unsigned long) + arg->fence_rep; + uint32_t handle; +- unsigned long irq_flags; +- struct drm_vmw_event_fence *event; + int ret; + + /* +@@ -1045,59 +1123,28 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, + + BUG_ON(fence == NULL); + +- spin_lock_irqsave(&dev->event_lock, irq_flags); +- +- ret = (file_priv->event_space < sizeof(*event)) ? -EBUSY : 0; +- if (likely(ret == 0)) +- file_priv->event_space -= sizeof(*event); +- +- spin_unlock_irqrestore(&dev->event_lock, irq_flags); +- +- if (unlikely(ret != 0)) { +- DRM_ERROR("Failed to allocate event space for this file.\n"); +- goto out_no_event_space; +- } +- +- event = kzalloc(sizeof(*event), GFP_KERNEL); +- if (unlikely(event == NULL)) { +- DRM_ERROR("Failed to allocate an event.\n"); +- goto out_no_event; +- } +- +- event->base.type = DRM_VMW_EVENT_FENCE_SIGNALED; +- event->base.length = sizeof(*event); +- event->user_data = arg->user_data; +- + if (arg->flags & DRM_VMW_FE_FLAG_REQ_TIME) + ret = vmw_event_fence_action_create(file_priv, fence, +- &event->base, +- &event->tv_sec, +- &event->tv_usec, ++ arg->flags, ++ arg->user_data, + true); + else + ret = vmw_event_fence_action_create(file_priv, fence, +- &event->base, +- NULL, +- NULL, ++ arg->flags, ++ arg->user_data, + true); + + if (unlikely(ret != 0)) { + if (ret != -ERESTARTSYS) + DRM_ERROR("Failed to attach event to fence.\n"); +- goto out_no_attach; ++ goto out_no_create; + } + + vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence, + handle); + vmw_fence_obj_unreference(&fence); + return 0; +-out_no_attach: +- kfree(event); +-out_no_event: +- spin_lock_irqsave(&dev->event_lock, irq_flags); +- file_priv->event_space += sizeof(*event); +- spin_unlock_irqrestore(&dev->event_lock, irq_flags); +-out_no_event_space: ++out_no_create: + if (user_fence_rep != NULL) + ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, + handle, TTM_REF_USAGE); +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h +index 0854a20..faf2e78 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h +@@ -109,5 +109,12 @@ extern int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + extern int vmw_fence_event_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +- ++extern void vmw_event_fence_fpriv_gone(struct vmw_fence_manager *fman, ++ struct list_head *event_list); ++extern int vmw_event_fence_action_queue(struct drm_file *filee_priv, ++ struct vmw_fence_obj *fence, ++ struct drm_pending_event *event, ++ uint32_t *tv_sec, ++ uint32_t *tv_usec, ++ bool interruptible); + #endif /* _VMWGFX_FENCE_H_ */ +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c +index 2952249..e1978a2 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c +@@ -156,10 +156,10 @@ static int vmw_gmr_build_descriptors(struct list_head *desc_pages, + + if (likely(page_virtual != NULL)) { + desc_virtual->ppn = page_to_pfn(page); +- kunmap_atomic(page_virtual, KM_USER0); ++ kunmap_atomic(page_virtual); + } + +- page_virtual = kmap_atomic(page, KM_USER0); ++ page_virtual = kmap_atomic(page); + desc_virtual = page_virtual - 1; + prev_pfn = ~(0UL); + +@@ -189,7 +189,7 @@ static int vmw_gmr_build_descriptors(struct list_head *desc_pages, + } + + if (likely(page_virtual != NULL)) +- kunmap_atomic(page_virtual, KM_USER0); ++ kunmap_atomic(page_virtual); + + return 0; + out_err: +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +index eb9735e..7ca1d47 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +@@ -422,7 +422,8 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, + struct vmw_framebuffer *framebuffer, + unsigned flags, unsigned color, + struct drm_clip_rect *clips, +- unsigned num_clips, int inc) ++ unsigned num_clips, int inc, ++ struct vmw_fence_obj **out_fence) + { + struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; + struct drm_clip_rect *clips_ptr; +@@ -542,12 +543,15 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, + if (num == 0) + continue; + ++ /* only return the last fence */ ++ if (out_fence && *out_fence) ++ vmw_fence_obj_unreference(out_fence); + + /* recalculate package length */ + fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num; + cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); + ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, +- fifo_size, 0, NULL); ++ fifo_size, 0, NULL, out_fence); + + if (unlikely(ret != 0)) + break; +@@ -598,7 +602,7 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, + + ret = do_surface_dirty_sou(dev_priv, file_priv, &vfbs->base, + flags, color, +- clips, num_clips, inc); ++ clips, num_clips, inc, NULL); + + ttm_read_unlock(&vmaster->lock); + return 0; +@@ -690,7 +694,7 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, + + /* XXX get the first 3 from the surface info */ + vfbs->base.base.bits_per_pixel = mode_cmd->bpp; +- vfbs->base.base.pitch = mode_cmd->pitch; ++ vfbs->base.base.pitches[0] = mode_cmd->pitch; + vfbs->base.base.depth = mode_cmd->depth; + vfbs->base.base.width = mode_cmd->width; + vfbs->base.base.height = mode_cmd->height; +@@ -804,12 +808,12 @@ static int do_dmabuf_define_gmrfb(struct drm_file *file_priv, + cmd->body.format.bitsPerPixel = framebuffer->base.bits_per_pixel; + cmd->body.format.colorDepth = depth; + cmd->body.format.reserved = 0; +- cmd->body.bytesPerLine = framebuffer->base.pitch; ++ cmd->body.bytesPerLine = framebuffer->base.pitches[0]; + cmd->body.ptr.gmrId = framebuffer->user_handle; + cmd->body.ptr.offset = 0; + + ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, +- fifo_size, 0, NULL); ++ fifo_size, 0, NULL, NULL); + + kfree(cmd); + +@@ -821,7 +825,8 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv, + struct vmw_framebuffer *framebuffer, + unsigned flags, unsigned color, + struct drm_clip_rect *clips, +- unsigned num_clips, int increment) ++ unsigned num_clips, int increment, ++ struct vmw_fence_obj **out_fence) + { + struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; + struct drm_clip_rect *clips_ptr; +@@ -894,9 +899,13 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv, + if (hit_num == 0) + continue; + ++ /* only return the last fence */ ++ if (out_fence && *out_fence) ++ vmw_fence_obj_unreference(out_fence); ++ + fifo_size = sizeof(*blits) * hit_num; + ret = vmw_execbuf_process(file_priv, dev_priv, NULL, blits, +- fifo_size, 0, NULL); ++ fifo_size, 0, NULL, out_fence); + + if (unlikely(ret != 0)) + break; +@@ -942,7 +951,7 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, + } else { + ret = do_dmabuf_dirty_sou(file_priv, dev_priv, &vfbd->base, + flags, color, +- clips, num_clips, increment); ++ clips, num_clips, increment, NULL); + } + + ttm_read_unlock(&vmaster->lock); +@@ -1056,7 +1065,7 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, + } + + vfbd->base.base.bits_per_pixel = mode_cmd->bpp; +- vfbd->base.base.pitch = mode_cmd->pitch; ++ vfbd->base.base.pitches[0] = mode_cmd->pitch; + vfbd->base.base.depth = mode_cmd->depth; + vfbd->base.base.width = mode_cmd->width; + vfbd->base.base.height = mode_cmd->height; +@@ -1085,7 +1094,7 @@ out_err1: + + static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, + struct drm_file *file_priv, +- struct drm_mode_fb_cmd *mode_cmd) ++ struct drm_mode_fb_cmd2 *mode_cmd2) + { + struct vmw_private *dev_priv = vmw_priv(dev); + struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; +@@ -1093,8 +1102,16 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, + struct vmw_surface *surface = NULL; + struct vmw_dma_buffer *bo = NULL; + struct ttm_base_object *user_obj; ++ struct drm_mode_fb_cmd mode_cmd; + int ret; + ++ mode_cmd.width = mode_cmd2->width; ++ mode_cmd.height = mode_cmd2->height; ++ mode_cmd.pitch = mode_cmd2->pitches[0]; ++ mode_cmd.handle = mode_cmd2->handles[0]; ++ drm_fb_get_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth, ++ &mode_cmd.bpp); ++ + /** + * This code should be conditioned on Screen Objects not being used. + * If screen objects are used, we can allocate a GMR to hold the +@@ -1102,8 +1119,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, + */ + + if (!vmw_kms_validate_mode_vram(dev_priv, +- mode_cmd->pitch, +- mode_cmd->height)) { ++ mode_cmd.pitch, ++ mode_cmd.height)) { + DRM_ERROR("VRAM size is too small for requested mode.\n"); + return ERR_PTR(-ENOMEM); + } +@@ -1117,15 +1134,19 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, + * command stream using user-space handles. + */ + +- user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle); ++ user_obj = ttm_base_object_lookup(tfile, mode_cmd.handle); + if (unlikely(user_obj == NULL)) { + DRM_ERROR("Could not locate requested kms frame buffer.\n"); + return ERR_PTR(-ENOENT); + } + ++ /** ++ * End conditioned code. ++ */ ++ + /* returns either a dmabuf or surface */ + ret = vmw_user_lookup_handle(dev_priv, tfile, +- mode_cmd->handle, ++ mode_cmd.handle, + &surface, &bo); + if (ret) + goto err_out; +@@ -1133,10 +1154,10 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, + /* Create the new framebuffer depending one what we got back */ + if (bo) + ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb, +- mode_cmd); ++ &mode_cmd); + else if (surface) + ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, +- surface, &vfb, mode_cmd); ++ surface, &vfb, &mode_cmd); + else + BUG(); + +@@ -1284,7 +1305,7 @@ int vmw_kms_present(struct vmw_private *dev_priv, + fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num; + cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); + ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, +- fifo_size, 0, NULL); ++ fifo_size, 0, NULL, NULL); + + if (unlikely(ret != 0)) + break; +@@ -1344,7 +1365,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv, + cmd->body.format.bitsPerPixel = vfb->base.bits_per_pixel; + cmd->body.format.colorDepth = vfb->base.depth; + cmd->body.format.reserved = 0; +- cmd->body.bytesPerLine = vfb->base.pitch; ++ cmd->body.bytesPerLine = vfb->base.pitches[0]; + cmd->body.ptr.gmrId = vfb->user_handle; + cmd->body.ptr.offset = 0; + +@@ -1397,7 +1418,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv, + fifo_size = sizeof(*cmd) + sizeof(*blits) * blits_pos; + + ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, fifo_size, +- 0, user_fence_rep); ++ 0, user_fence_rep, NULL); + + kfree(cmd); + +@@ -1660,6 +1681,74 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num, + return 0; + } + ++int vmw_du_page_flip(struct drm_crtc *crtc, ++ struct drm_framebuffer *fb, ++ struct drm_pending_vblank_event *event) ++{ ++ struct vmw_private *dev_priv = vmw_priv(crtc->dev); ++ struct drm_framebuffer *old_fb = crtc->fb; ++ struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); ++ struct drm_file *file_priv ; ++ struct vmw_fence_obj *fence = NULL; ++ struct drm_clip_rect clips; ++ int ret; ++ ++ if (event == NULL) ++ return -EINVAL; ++ ++ /* require ScreenObject support for page flipping */ ++ if (!dev_priv->sou_priv) ++ return -ENOSYS; ++ ++ file_priv = event->base.file_priv; ++ if (!vmw_kms_screen_object_flippable(dev_priv, crtc)) ++ return -EINVAL; ++ ++ crtc->fb = fb; ++ ++ /* do a full screen dirty update */ ++ clips.x1 = clips.y1 = 0; ++ clips.x2 = fb->width; ++ clips.y2 = fb->height; ++ ++ if (vfb->dmabuf) ++ ret = do_dmabuf_dirty_sou(file_priv, dev_priv, vfb, ++ 0, 0, &clips, 1, 1, &fence); ++ else ++ ret = do_surface_dirty_sou(dev_priv, file_priv, vfb, ++ 0, 0, &clips, 1, 1, &fence); ++ ++ ++ if (ret != 0) ++ goto out_no_fence; ++ if (!fence) { ++ ret = -EINVAL; ++ goto out_no_fence; ++ } ++ ++ ret = vmw_event_fence_action_queue(file_priv, fence, ++ &event->base, ++ &event->event.tv_sec, ++ &event->event.tv_usec, ++ true); ++ ++ /* ++ * No need to hold on to this now. The only cleanup ++ * we need to do if we fail is unref the fence. ++ */ ++ vmw_fence_obj_unreference(&fence); ++ ++ if (vmw_crtc_to_du(crtc)->is_implicit) ++ vmw_kms_screen_object_update_implicit_fb(dev_priv, crtc); ++ ++ return ret; ++ ++out_no_fence: ++ crtc->fb = old_fb; ++ return ret; ++} ++ ++ + void vmw_du_crtc_save(struct drm_crtc *crtc) + { + } +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +index e1cb855..8184bc5 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +@@ -29,6 +29,7 @@ + #define VMWGFX_KMS_H_ + + #include "drmP.h" ++#include "drm_crtc_helper.h" + #include "vmwgfx_drv.h" + + #define VMWGFX_NUM_DISPLAY_UNITS 8 +@@ -120,6 +121,9 @@ struct vmw_display_unit { + * Shared display unit functions - vmwgfx_kms.c + */ + void vmw_display_unit_cleanup(struct vmw_display_unit *du); ++int vmw_du_page_flip(struct drm_crtc *crtc, ++ struct drm_framebuffer *fb, ++ struct drm_pending_vblank_event *event); + void vmw_du_crtc_save(struct drm_crtc *crtc); + void vmw_du_crtc_restore(struct drm_crtc *crtc); + void vmw_du_crtc_gamma_set(struct drm_crtc *crtc, +@@ -153,5 +157,10 @@ int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv); + int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv); + int vmw_kms_sou_update_layout(struct vmw_private *dev_priv, unsigned num, + struct drm_vmw_rect *rects); ++bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv, ++ struct drm_crtc *crtc); ++void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv, ++ struct drm_crtc *crtc); ++ + + #endif +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +index 8f8dbd4..070fb23 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +@@ -95,7 +95,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) + return 0; + fb = entry->base.crtc.fb; + +- return vmw_kms_write_svga(dev_priv, w, h, fb->pitch, ++ return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0], + fb->bits_per_pixel, fb->depth); + } + +@@ -103,7 +103,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) + entry = list_entry(lds->active.next, typeof(*entry), active); + fb = entry->base.crtc.fb; + +- vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitch, ++ vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0], + fb->bits_per_pixel, fb->depth); + } + +@@ -354,8 +354,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) + INIT_LIST_HEAD(&ldu->active); + + ldu->base.pref_active = (unit == 0); +- ldu->base.pref_width = 800; +- ldu->base.pref_height = 600; ++ ldu->base.pref_width = dev_priv->initial_width; ++ ldu->base.pref_height = dev_priv->initial_height; + ldu->base.pref_mode = NULL; + ldu->base.is_implicit = true; + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +index 0795d17..059b32c 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +@@ -1540,29 +1540,10 @@ out_bad_surface: + /** + * Buffer management. + */ +- +-static size_t vmw_dmabuf_acc_size(struct ttm_bo_global *glob, +- unsigned long num_pages) +-{ +- static size_t bo_user_size = ~0; +- +- size_t page_array_size = +- (num_pages * sizeof(void *) + PAGE_SIZE - 1) & PAGE_MASK; +- +- if (unlikely(bo_user_size == ~0)) { +- bo_user_size = glob->ttm_bo_extra_size + +- ttm_round_pot(sizeof(struct vmw_dma_buffer)); +- } +- +- return bo_user_size + page_array_size; +-} +- + void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) + { + struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); +- struct ttm_bo_global *glob = bo->glob; + +- ttm_mem_global_free(glob->mem_glob, bo->acc_size); + kfree(vmw_bo); + } + +@@ -1573,24 +1554,12 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv, + void (*bo_free) (struct ttm_buffer_object *bo)) + { + struct ttm_bo_device *bdev = &dev_priv->bdev; +- struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; + size_t acc_size; + int ret; + + BUG_ON(!bo_free); + +- acc_size = +- vmw_dmabuf_acc_size(bdev->glob, +- (size + PAGE_SIZE - 1) >> PAGE_SHIFT); +- +- ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); +- if (unlikely(ret != 0)) { +- /* we must free the bo here as +- * ttm_buffer_object_init does so as well */ +- bo_free(&vmw_bo->base); +- return ret; +- } +- ++ acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct vmw_dma_buffer)); + memset(vmw_bo, 0, sizeof(*vmw_bo)); + + INIT_LIST_HEAD(&vmw_bo->validate_list); +@@ -1605,9 +1574,7 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv, + static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo) + { + struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo); +- struct ttm_bo_global *glob = bo->glob; + +- ttm_mem_global_free(glob->mem_glob, bo->acc_size); + kfree(vmw_user_bo); + } + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +index 4defdcf..6deaf2f 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +@@ -394,6 +394,7 @@ static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { + .gamma_set = vmw_du_crtc_gamma_set, + .destroy = vmw_sou_crtc_destroy, + .set_config = vmw_sou_crtc_set_config, ++ .page_flip = vmw_du_page_flip, + }; + + /* +@@ -448,8 +449,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) + sou->active_implicit = false; + + sou->base.pref_active = (unit == 0); +- sou->base.pref_width = 800; +- sou->base.pref_height = 600; ++ sou->base.pref_width = dev_priv->initial_width; ++ sou->base.pref_height = dev_priv->initial_height; + sou->base.pref_mode = NULL; + sou->base.is_implicit = true; + +@@ -535,3 +536,36 @@ int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv) + + return 0; + } ++ ++/** ++ * Returns if this unit can be page flipped. ++ * Must be called with the mode_config mutex held. ++ */ ++bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv, ++ struct drm_crtc *crtc) ++{ ++ struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc); ++ ++ if (!sou->base.is_implicit) ++ return true; ++ ++ if (dev_priv->sou_priv->num_implicit != 1) ++ return false; ++ ++ return true; ++} ++ ++/** ++ * Update the implicit fb to the current fb of this crtc. ++ * Must be called with the mode_config mutex held. ++ */ ++void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv, ++ struct drm_crtc *crtc) ++{ ++ struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc); ++ ++ BUG_ON(!sou->base.is_implicit); ++ ++ dev_priv->sou_priv->implicit_fb = ++ vmw_framebuffer_to_vfb(sou->base.crtc.fb); ++} +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index b5cc078..84bc8d1 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -647,6 +647,12 @@ config HID_ZYDACRON + ---help--- + Support for Zydacron remote control. + ++config HYPERV_MOUSE ++ tristate "Microsoft Hyper-V mouse driver" ++ depends on HYPERV ++ ---help--- ++ Select this option to enable the Hyper-V mouse driver. ++ + endmenu + + endif # HID_SUPPORT +diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile +index 1e0d2a6..fbb1ee6 100644 +--- a/drivers/hid/Makefile ++++ b/drivers/hid/Makefile +@@ -78,6 +78,7 @@ obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o + obj-$(CONFIG_HID_WACOM) += hid-wacom.o + obj-$(CONFIG_HID_WALTOP) += hid-waltop.o + obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o ++obj-$(CONFIG_HYPERV_MOUSE) += hid-hyperv.o + + obj-$(CONFIG_USB_HID) += usbhid/ + obj-$(CONFIG_USB_MOUSE) += usbhid/ +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 64d79d2..665335c 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -2001,6 +2001,16 @@ static const struct hid_device_id hid_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) }, ++#if defined(CONFIG_MOUSE_SYNAPTICS_USB) || defined(CONFIG_MOUSE_SYNAPTICS_USB_MODULE) ++ { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_INT_TP) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_CPAD) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_STICK) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_WP) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_COMP_TP) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_WTP) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DPAD) }, ++#endif + { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, +diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c +new file mode 100644 +index 0000000..4066324 +--- /dev/null ++++ b/drivers/hid/hid-hyperv.c +@@ -0,0 +1,587 @@ ++/* ++ * Copyright (c) 2009, Citrix Systems, Inc. ++ * Copyright (c) 2010, Microsoft Corporation. ++ * Copyright (c) 2011, Novell Inc. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * 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 ++ ++ ++struct hv_input_dev_info { ++ unsigned int size; ++ unsigned short vendor; ++ unsigned short product; ++ unsigned short version; ++ unsigned short reserved[11]; ++}; ++ ++/* The maximum size of a synthetic input message. */ ++#define SYNTHHID_MAX_INPUT_REPORT_SIZE 16 ++ ++/* ++ * Current version ++ * ++ * History: ++ * Beta, RC < 2008/1/22 1,0 ++ * RC > 2008/1/22 2,0 ++ */ ++#define SYNTHHID_INPUT_VERSION_MAJOR 2 ++#define SYNTHHID_INPUT_VERSION_MINOR 0 ++#define SYNTHHID_INPUT_VERSION (SYNTHHID_INPUT_VERSION_MINOR | \ ++ (SYNTHHID_INPUT_VERSION_MAJOR << 16)) ++ ++ ++#pragma pack(push, 1) ++/* ++ * Message types in the synthetic input protocol ++ */ ++enum synthhid_msg_type { ++ SYNTH_HID_PROTOCOL_REQUEST, ++ SYNTH_HID_PROTOCOL_RESPONSE, ++ SYNTH_HID_INITIAL_DEVICE_INFO, ++ SYNTH_HID_INITIAL_DEVICE_INFO_ACK, ++ SYNTH_HID_INPUT_REPORT, ++ SYNTH_HID_MAX ++}; ++ ++/* ++ * Basic message structures. ++ */ ++struct synthhid_msg_hdr { ++ enum synthhid_msg_type type; ++ u32 size; ++}; ++ ++struct synthhid_msg { ++ struct synthhid_msg_hdr header; ++ char data[1]; /* Enclosed message */ ++}; ++ ++union synthhid_version { ++ struct { ++ u16 minor_version; ++ u16 major_version; ++ }; ++ u32 version; ++}; ++ ++/* ++ * Protocol messages ++ */ ++struct synthhid_protocol_request { ++ struct synthhid_msg_hdr header; ++ union synthhid_version version_requested; ++}; ++ ++struct synthhid_protocol_response { ++ struct synthhid_msg_hdr header; ++ union synthhid_version version_requested; ++ unsigned char approved; ++}; ++ ++struct synthhid_device_info { ++ struct synthhid_msg_hdr header; ++ struct hv_input_dev_info hid_dev_info; ++ struct hid_descriptor hid_descriptor; ++}; ++ ++struct synthhid_device_info_ack { ++ struct synthhid_msg_hdr header; ++ unsigned char reserved; ++}; ++ ++struct synthhid_input_report { ++ struct synthhid_msg_hdr header; ++ char buffer[1]; ++}; ++ ++#pragma pack(pop) ++ ++#define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE) ++#define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE) ++ ++ ++enum pipe_prot_msg_type { ++ PIPE_MESSAGE_INVALID, ++ PIPE_MESSAGE_DATA, ++ PIPE_MESSAGE_MAXIMUM ++}; ++ ++ ++struct pipe_prt_msg { ++ enum pipe_prot_msg_type type; ++ u32 size; ++ char data[1]; ++}; ++ ++struct mousevsc_prt_msg { ++ enum pipe_prot_msg_type type; ++ u32 size; ++ union { ++ struct synthhid_protocol_request request; ++ struct synthhid_protocol_response response; ++ struct synthhid_device_info_ack ack; ++ }; ++}; ++ ++/* ++ * Represents an mousevsc device ++ */ ++struct mousevsc_dev { ++ struct hv_device *device; ++ bool init_complete; ++ bool connected; ++ struct mousevsc_prt_msg protocol_req; ++ struct mousevsc_prt_msg protocol_resp; ++ /* Synchronize the request/response if needed */ ++ struct completion wait_event; ++ int dev_info_status; ++ ++ struct hid_descriptor *hid_desc; ++ unsigned char *report_desc; ++ u32 report_desc_size; ++ struct hv_input_dev_info hid_dev_info; ++ struct hid_device *hid_device; ++}; ++ ++ ++static struct mousevsc_dev *mousevsc_alloc_device(struct hv_device *device) ++{ ++ struct mousevsc_dev *input_dev; ++ ++ input_dev = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL); ++ ++ if (!input_dev) ++ return NULL; ++ ++ input_dev->device = device; ++ hv_set_drvdata(device, input_dev); ++ init_completion(&input_dev->wait_event); ++ input_dev->init_complete = false; ++ ++ return input_dev; ++} ++ ++static void mousevsc_free_device(struct mousevsc_dev *device) ++{ ++ kfree(device->hid_desc); ++ kfree(device->report_desc); ++ hv_set_drvdata(device->device, NULL); ++ kfree(device); ++} ++ ++static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, ++ struct synthhid_device_info *device_info) ++{ ++ int ret = 0; ++ struct hid_descriptor *desc; ++ struct mousevsc_prt_msg ack; ++ ++ input_device->dev_info_status = -ENOMEM; ++ ++ input_device->hid_dev_info = device_info->hid_dev_info; ++ desc = &device_info->hid_descriptor; ++ if (desc->bLength == 0) ++ goto cleanup; ++ ++ input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC); ++ ++ if (!input_device->hid_desc) ++ goto cleanup; ++ ++ memcpy(input_device->hid_desc, desc, desc->bLength); ++ ++ input_device->report_desc_size = desc->desc[0].wDescriptorLength; ++ if (input_device->report_desc_size == 0) { ++ input_device->dev_info_status = -EINVAL; ++ goto cleanup; ++ } ++ ++ input_device->report_desc = kzalloc(input_device->report_desc_size, ++ GFP_ATOMIC); ++ ++ if (!input_device->report_desc) { ++ input_device->dev_info_status = -ENOMEM; ++ goto cleanup; ++ } ++ ++ memcpy(input_device->report_desc, ++ ((unsigned char *)desc) + desc->bLength, ++ desc->desc[0].wDescriptorLength); ++ ++ /* Send the ack */ ++ memset(&ack, 0, sizeof(struct mousevsc_prt_msg)); ++ ++ ack.type = PIPE_MESSAGE_DATA; ++ ack.size = sizeof(struct synthhid_device_info_ack); ++ ++ ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK; ++ ack.ack.header.size = 1; ++ ack.ack.reserved = 0; ++ ++ ret = vmbus_sendpacket(input_device->device->channel, ++ &ack, ++ sizeof(struct pipe_prt_msg) - sizeof(unsigned char) + ++ sizeof(struct synthhid_device_info_ack), ++ (unsigned long)&ack, ++ VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ ++ if (!ret) ++ input_device->dev_info_status = 0; ++ ++cleanup: ++ complete(&input_device->wait_event); ++ ++ return; ++} ++ ++static void mousevsc_on_receive(struct hv_device *device, ++ struct vmpacket_descriptor *packet) ++{ ++ struct pipe_prt_msg *pipe_msg; ++ struct synthhid_msg *hid_msg; ++ struct mousevsc_dev *input_dev = hv_get_drvdata(device); ++ struct synthhid_input_report *input_report; ++ ++ pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet + ++ (packet->offset8 << 3)); ++ ++ if (pipe_msg->type != PIPE_MESSAGE_DATA) ++ return; ++ ++ hid_msg = (struct synthhid_msg *)pipe_msg->data; ++ ++ switch (hid_msg->header.type) { ++ case SYNTH_HID_PROTOCOL_RESPONSE: ++ /* ++ * While it will be impossible for us to protect against ++ * malicious/buggy hypervisor/host, add a check here to ++ * ensure we don't corrupt memory. ++ */ ++ if ((pipe_msg->size + sizeof(struct pipe_prt_msg) ++ - sizeof(unsigned char)) ++ > sizeof(struct mousevsc_prt_msg)) { ++ WARN_ON(1); ++ break; ++ } ++ ++ memcpy(&input_dev->protocol_resp, pipe_msg, ++ pipe_msg->size + sizeof(struct pipe_prt_msg) - ++ sizeof(unsigned char)); ++ complete(&input_dev->wait_event); ++ break; ++ ++ case SYNTH_HID_INITIAL_DEVICE_INFO: ++ WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info)); ++ ++ /* ++ * Parse out the device info into device attr, ++ * hid desc and report desc ++ */ ++ mousevsc_on_receive_device_info(input_dev, ++ (struct synthhid_device_info *)pipe_msg->data); ++ break; ++ case SYNTH_HID_INPUT_REPORT: ++ input_report = ++ (struct synthhid_input_report *)pipe_msg->data; ++ if (!input_dev->init_complete) ++ break; ++ hid_input_report(input_dev->hid_device, ++ HID_INPUT_REPORT, input_report->buffer, ++ input_report->header.size, 1); ++ break; ++ default: ++ pr_err("unsupported hid msg type - type %d len %d", ++ hid_msg->header.type, hid_msg->header.size); ++ break; ++ } ++ ++} ++ ++static void mousevsc_on_channel_callback(void *context) ++{ ++ const int packet_size = 0x100; ++ int ret; ++ struct hv_device *device = context; ++ u32 bytes_recvd; ++ u64 req_id; ++ struct vmpacket_descriptor *desc; ++ unsigned char *buffer; ++ int bufferlen = packet_size; ++ ++ buffer = kmalloc(bufferlen, GFP_ATOMIC); ++ if (!buffer) ++ return; ++ ++ do { ++ ret = vmbus_recvpacket_raw(device->channel, buffer, ++ bufferlen, &bytes_recvd, &req_id); ++ ++ switch (ret) { ++ case 0: ++ if (bytes_recvd <= 0) { ++ kfree(buffer); ++ return; ++ } ++ desc = (struct vmpacket_descriptor *)buffer; ++ ++ switch (desc->type) { ++ case VM_PKT_COMP: ++ break; ++ ++ case VM_PKT_DATA_INBAND: ++ mousevsc_on_receive(device, desc); ++ break; ++ ++ default: ++ pr_err("unhandled packet type %d, tid %llx len %d\n", ++ desc->type, req_id, bytes_recvd); ++ break; ++ } ++ ++ break; ++ ++ case -ENOBUFS: ++ kfree(buffer); ++ /* Handle large packet */ ++ bufferlen = bytes_recvd; ++ buffer = kmalloc(bytes_recvd, GFP_ATOMIC); ++ ++ if (!buffer) ++ return; ++ ++ break; ++ } ++ } while (1); ++ ++} ++ ++static int mousevsc_connect_to_vsp(struct hv_device *device) ++{ ++ int ret = 0; ++ int t; ++ struct mousevsc_dev *input_dev = hv_get_drvdata(device); ++ struct mousevsc_prt_msg *request; ++ struct mousevsc_prt_msg *response; ++ ++ request = &input_dev->protocol_req; ++ memset(request, 0, sizeof(struct mousevsc_prt_msg)); ++ ++ request->type = PIPE_MESSAGE_DATA; ++ request->size = sizeof(struct synthhid_protocol_request); ++ request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST; ++ request->request.header.size = sizeof(unsigned int); ++ request->request.version_requested.version = SYNTHHID_INPUT_VERSION; ++ ++ ret = vmbus_sendpacket(device->channel, request, ++ sizeof(struct pipe_prt_msg) - ++ sizeof(unsigned char) + ++ sizeof(struct synthhid_protocol_request), ++ (unsigned long)request, ++ VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ if (ret) ++ goto cleanup; ++ ++ t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); ++ if (!t) { ++ ret = -ETIMEDOUT; ++ goto cleanup; ++ } ++ ++ response = &input_dev->protocol_resp; ++ ++ if (!response->response.approved) { ++ pr_err("synthhid protocol request failed (version %d)\n", ++ SYNTHHID_INPUT_VERSION); ++ ret = -ENODEV; ++ goto cleanup; ++ } ++ ++ t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); ++ if (!t) { ++ ret = -ETIMEDOUT; ++ goto cleanup; ++ } ++ ++ /* ++ * We should have gotten the device attr, hid desc and report ++ * desc at this point ++ */ ++ ret = input_dev->dev_info_status; ++ ++cleanup: ++ return ret; ++} ++ ++static int mousevsc_hid_open(struct hid_device *hid) ++{ ++ return 0; ++} ++ ++static int mousevsc_hid_start(struct hid_device *hid) ++{ ++ return 0; ++} ++ ++static void mousevsc_hid_close(struct hid_device *hid) ++{ ++} ++ ++static void mousevsc_hid_stop(struct hid_device *hid) ++{ ++} ++ ++static struct hid_ll_driver mousevsc_ll_driver = { ++ .open = mousevsc_hid_open, ++ .close = mousevsc_hid_close, ++ .start = mousevsc_hid_start, ++ .stop = mousevsc_hid_stop, ++}; ++ ++static struct hid_driver mousevsc_hid_driver; ++ ++static int mousevsc_probe(struct hv_device *device, ++ const struct hv_vmbus_device_id *dev_id) ++{ ++ int ret; ++ struct mousevsc_dev *input_dev; ++ struct hid_device *hid_dev; ++ ++ input_dev = mousevsc_alloc_device(device); ++ ++ if (!input_dev) ++ return -ENOMEM; ++ ++ ret = vmbus_open(device->channel, ++ INPUTVSC_SEND_RING_BUFFER_SIZE, ++ INPUTVSC_RECV_RING_BUFFER_SIZE, ++ NULL, ++ 0, ++ mousevsc_on_channel_callback, ++ device ++ ); ++ ++ if (ret) ++ goto probe_err0; ++ ++ ret = mousevsc_connect_to_vsp(device); ++ ++ if (ret) ++ goto probe_err1; ++ ++ /* workaround SA-167 */ ++ if (input_dev->report_desc[14] == 0x25) ++ input_dev->report_desc[14] = 0x29; ++ ++ hid_dev = hid_allocate_device(); ++ if (IS_ERR(hid_dev)) { ++ ret = PTR_ERR(hid_dev); ++ goto probe_err1; ++ } ++ ++ hid_dev->ll_driver = &mousevsc_ll_driver; ++ hid_dev->driver = &mousevsc_hid_driver; ++ hid_dev->bus = BUS_VIRTUAL; ++ hid_dev->vendor = input_dev->hid_dev_info.vendor; ++ hid_dev->product = input_dev->hid_dev_info.product; ++ hid_dev->version = input_dev->hid_dev_info.version; ++ input_dev->hid_device = hid_dev; ++ ++ sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse"); ++ ++ ret = hid_add_device(hid_dev); ++ if (ret) ++ goto probe_err1; ++ ++ ret = hid_parse_report(hid_dev, input_dev->report_desc, ++ input_dev->report_desc_size); ++ ++ if (ret) { ++ hid_err(hid_dev, "parse failed\n"); ++ goto probe_err2; ++ } ++ ++ ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV); ++ ++ if (ret) { ++ hid_err(hid_dev, "hw start failed\n"); ++ goto probe_err2; ++ } ++ ++ input_dev->connected = true; ++ input_dev->init_complete = true; ++ ++ return ret; ++ ++probe_err2: ++ hid_destroy_device(hid_dev); ++ ++probe_err1: ++ vmbus_close(device->channel); ++ ++probe_err0: ++ mousevsc_free_device(input_dev); ++ ++ return ret; ++} ++ ++ ++static int mousevsc_remove(struct hv_device *dev) ++{ ++ struct mousevsc_dev *input_dev = hv_get_drvdata(dev); ++ ++ vmbus_close(dev->channel); ++ hid_hw_stop(input_dev->hid_device); ++ hid_destroy_device(input_dev->hid_device); ++ mousevsc_free_device(input_dev); ++ ++ return 0; ++} ++ ++static const struct hv_vmbus_device_id id_table[] = { ++ /* Mouse guid */ ++ { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, ++ 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A) }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(vmbus, id_table); ++ ++static struct hv_driver mousevsc_drv = { ++ .name = KBUILD_MODNAME, ++ .id_table = id_table, ++ .probe = mousevsc_probe, ++ .remove = mousevsc_remove, ++}; ++ ++static int __init mousevsc_init(void) ++{ ++ return vmbus_driver_register(&mousevsc_drv); ++} ++ ++static void __exit mousevsc_exit(void) ++{ ++ vmbus_driver_unregister(&mousevsc_drv); ++} ++ ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(HV_DRV_VERSION); ++module_init(mousevsc_init); ++module_exit(mousevsc_exit); +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index ccc89b0..057aeb0 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -685,6 +685,17 @@ + #define USB_DEVICE_ID_SYNAPTICS_QUAD_HD 0x1ac3 + #define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710 + ++#define USB_VENDOR_ID_SYNAPTICS 0x06cb ++#define USB_DEVICE_ID_SYNAPTICS_TP 0x0001 ++#define USB_DEVICE_ID_SYNAPTICS_INT_TP 0x0002 ++#define USB_DEVICE_ID_SYNAPTICS_CPAD 0x0003 ++#define USB_DEVICE_ID_SYNAPTICS_TS 0x0006 ++#define USB_DEVICE_ID_SYNAPTICS_STICK 0x0007 ++#define USB_DEVICE_ID_SYNAPTICS_WP 0x0008 ++#define USB_DEVICE_ID_SYNAPTICS_COMP_TP 0x0009 ++#define USB_DEVICE_ID_SYNAPTICS_WTP 0x0010 ++#define USB_DEVICE_ID_SYNAPTICS_DPAD 0x0013 ++ + #define USB_VENDOR_ID_THRUSTMASTER 0x044f + + #define USB_VENDOR_ID_TOPSEED 0x0766 +diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig +index 9fa09ac..70f5dde 100644 +--- a/drivers/hv/Kconfig ++++ b/drivers/hv/Kconfig +@@ -1,3 +1,5 @@ ++menu "Microsoft Hyper-V guest support" ++ + config HYPERV + tristate "Microsoft Hyper-V client drivers" + depends on X86 && ACPI && PCI +@@ -11,4 +13,4 @@ config HYPERV_UTILS + help + Select this option to enable the Hyper-V Utilities. + +- ++endmenu +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 7f963328b..bcf67af 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -37,81 +37,6 @@ struct vmbus_channel_message_table_entry { + void (*message_handler)(struct vmbus_channel_message_header *msg); + }; + +-#define MAX_MSG_TYPES 4 +-#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8 +- +-static const uuid_le +- supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = { +- /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */ +- /* Storage - SCSI */ +- { +- .b = { +- 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, +- 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f +- } +- }, +- +- /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ +- /* Network */ +- { +- .b = { +- 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, +- 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E +- } +- }, +- +- /* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */ +- /* Input */ +- { +- .b = { +- 0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, +- 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A +- } +- }, +- +- /* {32412632-86cb-44a2-9b5c-50d1417354f5} */ +- /* IDE */ +- { +- .b = { +- 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, +- 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 +- } +- }, +- /* 0E0B6031-5213-4934-818B-38D90CED39DB */ +- /* Shutdown */ +- { +- .b = { +- 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, +- 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB +- } +- }, +- /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */ +- /* TimeSync */ +- { +- .b = { +- 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, +- 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf +- } +- }, +- /* {57164f39-9115-4e78-ab55-382f3bd5422d} */ +- /* Heartbeat */ +- { +- .b = { +- 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, +- 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d +- } +- }, +- /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */ +- /* KVP */ +- { +- .b = { +- 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, +- 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 +- } +- }, +- +-}; +- + + /** + * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message +@@ -223,6 +148,17 @@ static void vmbus_process_rescind_offer(struct work_struct *work) + vmbus_device_unregister(channel->device_obj); + } + ++void vmbus_free_channels(void) ++{ ++ struct vmbus_channel *channel; ++ ++ list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { ++ vmbus_device_unregister(channel->device_obj); ++ kfree(channel->device_obj); ++ free_channel(channel); ++ } ++} ++ + /* + * vmbus_process_offer - Process the offer by creating a channel/device + * associated with this offer +@@ -287,6 +223,7 @@ static void vmbus_process_offer(struct work_struct *work) + spin_lock_irqsave(&vmbus_connection.channel_lock, flags); + list_del(&newchannel->listentry); + spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); ++ kfree(newchannel->device_obj); + + free_channel(newchannel); + } else { +@@ -309,20 +246,8 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) + struct vmbus_channel *newchannel; + uuid_le *guidtype; + uuid_le *guidinstance; +- int i; +- int fsupported = 0; + + offer = (struct vmbus_channel_offer_channel *)hdr; +- for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) { +- if (!uuid_le_cmp(offer->offer.if_type, +- supported_device_classes[i])) { +- fsupported = 1; +- break; +- } +- } +- +- if (!fsupported) +- return; + + guidtype = &offer->offer.if_type; + guidinstance = &offer->offer.if_instance; +diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c +index 17ed6fb..4583c49 100644 +--- a/drivers/hv/hv.c ++++ b/drivers/hv/hv.c +@@ -155,22 +155,17 @@ int hv_init(void) + union hv_x64_msr_hypercall_contents hypercall_msr; + void *virtaddr = NULL; + +- memset(hv_context.synic_event_page, 0, sizeof(void *) * MAX_NUM_CPUS); ++ memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS); + memset(hv_context.synic_message_page, 0, +- sizeof(void *) * MAX_NUM_CPUS); ++ sizeof(void *) * NR_CPUS); + memset(hv_context.post_msg_page, 0, +- sizeof(void *) * MAX_NUM_CPUS); ++ sizeof(void *) * NR_CPUS); + + if (!query_hypervisor_presence()) + goto cleanup; + + max_leaf = query_hypervisor_info(); + +- rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid); +- +- if (hv_context.guestid != 0) +- goto cleanup; +- + /* Write our OS info */ + wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID); + hv_context.guestid = HV_LINUX_GUEST_ID; +@@ -239,6 +234,9 @@ void hv_cleanup(void) + { + union hv_x64_msr_hypercall_contents hypercall_msr; + ++ /* Reset our OS id */ ++ wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); ++ + kfree(hv_context.signal_event_buffer); + hv_context.signal_event_buffer = NULL; + hv_context.signal_event_param = NULL; +diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c +index 0e8343f..6186025 100644 +--- a/drivers/hv/hv_kvp.c ++++ b/drivers/hv/hv_kvp.c +@@ -28,8 +28,6 @@ + #include + #include + +-#include "hv_kvp.h" +- + + + /* +@@ -44,9 +42,10 @@ + static struct { + bool active; /* transaction status - active or not */ + int recv_len; /* number of bytes received. */ +- int index; /* current index */ ++ struct hv_kvp_msg *kvp_msg; /* current message */ + struct vmbus_channel *recv_channel; /* chn we got the request */ + u64 recv_req_id; /* request ID. */ ++ void *kvp_context; /* for the channel callback */ + } kvp_transaction; + + static void kvp_send_key(struct work_struct *dummy); +@@ -73,15 +72,20 @@ kvp_register(void) + { + + struct cn_msg *msg; ++ struct hv_kvp_msg *kvp_msg; ++ char *version; + +- msg = kzalloc(sizeof(*msg) + strlen(HV_DRV_VERSION) + 1 , GFP_ATOMIC); ++ msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg), GFP_ATOMIC); + + if (msg) { ++ kvp_msg = (struct hv_kvp_msg *)msg->data; ++ version = kvp_msg->body.kvp_register.version; + msg->id.idx = CN_KVP_IDX; + msg->id.val = CN_KVP_VAL; +- msg->seq = KVP_REGISTER; +- strcpy(msg->data, HV_DRV_VERSION); +- msg->len = strlen(HV_DRV_VERSION) + 1; ++ ++ kvp_msg->kvp_hdr.operation = KVP_OP_REGISTER; ++ strcpy(version, HV_DRV_VERSION); ++ msg->len = sizeof(struct hv_kvp_msg); + cn_netlink_send(msg, 0, GFP_ATOMIC); + kfree(msg); + } +@@ -103,23 +107,28 @@ kvp_work_func(struct work_struct *dummy) + static void + kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) + { +- struct hv_ku_msg *message; ++ struct hv_kvp_msg *message; ++ struct hv_kvp_msg_enumerate *data; + +- message = (struct hv_ku_msg *)msg->data; +- if (msg->seq == KVP_REGISTER) { ++ message = (struct hv_kvp_msg *)msg->data; ++ switch (message->kvp_hdr.operation) { ++ case KVP_OP_REGISTER: + pr_info("KVP: user-mode registering done.\n"); + kvp_register(); +- } ++ kvp_transaction.active = false; ++ hv_kvp_onchannelcallback(kvp_transaction.kvp_context); ++ break; + +- if (msg->seq == KVP_USER_SET) { ++ default: ++ data = &message->body.kvp_enum_data; + /* + * Complete the transaction by forwarding the key value + * to the host. But first, cancel the timeout. + */ + if (cancel_delayed_work_sync(&kvp_work)) +- kvp_respond_to_host(message->kvp_key, +- message->kvp_value, +- !strlen(message->kvp_key)); ++ kvp_respond_to_host(data->data.key, ++ data->data.value, ++ !strlen(data->data.key)); + } + } + +@@ -127,19 +136,105 @@ static void + kvp_send_key(struct work_struct *dummy) + { + struct cn_msg *msg; +- int index = kvp_transaction.index; ++ struct hv_kvp_msg *message; ++ struct hv_kvp_msg *in_msg; ++ __u8 operation = kvp_transaction.kvp_msg->kvp_hdr.operation; ++ __u8 pool = kvp_transaction.kvp_msg->kvp_hdr.pool; ++ __u32 val32; ++ __u64 val64; + + msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC); ++ if (!msg) ++ return; + +- if (msg) { +- msg->id.idx = CN_KVP_IDX; +- msg->id.val = CN_KVP_VAL; +- msg->seq = KVP_KERNEL_GET; +- ((struct hv_ku_msg *)msg->data)->kvp_index = index; +- msg->len = sizeof(struct hv_ku_msg); +- cn_netlink_send(msg, 0, GFP_ATOMIC); +- kfree(msg); ++ msg->id.idx = CN_KVP_IDX; ++ msg->id.val = CN_KVP_VAL; ++ ++ message = (struct hv_kvp_msg *)msg->data; ++ message->kvp_hdr.operation = operation; ++ message->kvp_hdr.pool = pool; ++ in_msg = kvp_transaction.kvp_msg; ++ ++ /* ++ * The key/value strings sent from the host are encoded in ++ * in utf16; convert it to utf8 strings. ++ * The host assures us that the utf16 strings will not exceed ++ * the max lengths specified. We will however, reserve room ++ * for the string terminating character - in the utf16s_utf8s() ++ * function we limit the size of the buffer where the converted ++ * string is placed to HV_KVP_EXCHANGE_MAX_*_SIZE -1 to gaurantee ++ * that the strings can be properly terminated! ++ */ ++ ++ switch (message->kvp_hdr.operation) { ++ case KVP_OP_SET: ++ switch (in_msg->body.kvp_set.data.value_type) { ++ case REG_SZ: ++ /* ++ * The value is a string - utf16 encoding. ++ */ ++ message->body.kvp_set.data.value_size = ++ utf16s_to_utf8s( ++ (wchar_t *)in_msg->body.kvp_set.data.value, ++ in_msg->body.kvp_set.data.value_size, ++ UTF16_LITTLE_ENDIAN, ++ message->body.kvp_set.data.value, ++ HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1) + 1; ++ break; ++ ++ case REG_U32: ++ /* ++ * The value is a 32 bit scalar. ++ * We save this as a utf8 string. ++ */ ++ val32 = in_msg->body.kvp_set.data.value_u32; ++ message->body.kvp_set.data.value_size = ++ sprintf(message->body.kvp_set.data.value, ++ "%d", val32) + 1; ++ break; ++ ++ case REG_U64: ++ /* ++ * The value is a 64 bit scalar. ++ * We save this as a utf8 string. ++ */ ++ val64 = in_msg->body.kvp_set.data.value_u64; ++ message->body.kvp_set.data.value_size = ++ sprintf(message->body.kvp_set.data.value, ++ "%llu", val64) + 1; ++ break; ++ ++ } ++ case KVP_OP_GET: ++ message->body.kvp_set.data.key_size = ++ utf16s_to_utf8s( ++ (wchar_t *)in_msg->body.kvp_set.data.key, ++ in_msg->body.kvp_set.data.key_size, ++ UTF16_LITTLE_ENDIAN, ++ message->body.kvp_set.data.key, ++ HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1; ++ break; ++ ++ case KVP_OP_DELETE: ++ message->body.kvp_delete.key_size = ++ utf16s_to_utf8s( ++ (wchar_t *)in_msg->body.kvp_delete.key, ++ in_msg->body.kvp_delete.key_size, ++ UTF16_LITTLE_ENDIAN, ++ message->body.kvp_delete.key, ++ HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1; ++ break; ++ ++ case KVP_OP_ENUMERATE: ++ message->body.kvp_enum_data.index = ++ in_msg->body.kvp_enum_data.index; ++ break; + } ++ ++ msg->len = sizeof(struct hv_kvp_msg); ++ cn_netlink_send(msg, 0, GFP_ATOMIC); ++ kfree(msg); ++ + return; + } + +@@ -151,10 +246,11 @@ static void + kvp_respond_to_host(char *key, char *value, int error) + { + struct hv_kvp_msg *kvp_msg; +- struct hv_kvp_msg_enumerate *kvp_data; ++ struct hv_kvp_exchg_msg_value *kvp_data; + char *key_name; + struct icmsg_hdr *icmsghdrp; +- int keylen, valuelen; ++ int keylen = 0; ++ int valuelen = 0; + u32 buf_len; + struct vmbus_channel *channel; + u64 req_id; +@@ -181,6 +277,9 @@ kvp_respond_to_host(char *key, char *value, int error) + + kvp_transaction.active = false; + ++ icmsghdrp = (struct icmsg_hdr *) ++ &recv_buffer[sizeof(struct vmbuspipe_hdr)]; ++ + if (channel->onchannel_callback == NULL) + /* + * We have raced with util driver being unloaded; +@@ -188,41 +287,67 @@ kvp_respond_to_host(char *key, char *value, int error) + */ + return; + +- icmsghdrp = (struct icmsg_hdr *) +- &recv_buffer[sizeof(struct vmbuspipe_hdr)]; +- kvp_msg = (struct hv_kvp_msg *) +- &recv_buffer[sizeof(struct vmbuspipe_hdr) + +- sizeof(struct icmsg_hdr)]; +- kvp_data = &kvp_msg->kvp_data; +- key_name = key; + + /* +- * If the error parameter is set, terminate the host's enumeration. ++ * If the error parameter is set, terminate the host's enumeration ++ * on this pool. + */ + if (error) { + /* +- * We don't support this index or the we have timedout; +- * terminate the host-side iteration by returning an error. ++ * Something failed or the we have timedout; ++ * terminate the current host-side iteration. + */ +- icmsghdrp->status = HV_E_FAIL; ++ icmsghdrp->status = HV_S_CONT; + goto response_done; + } + ++ icmsghdrp->status = HV_S_OK; ++ ++ kvp_msg = (struct hv_kvp_msg *) ++ &recv_buffer[sizeof(struct vmbuspipe_hdr) + ++ sizeof(struct icmsg_hdr)]; ++ ++ switch (kvp_transaction.kvp_msg->kvp_hdr.operation) { ++ case KVP_OP_GET: ++ kvp_data = &kvp_msg->body.kvp_get.data; ++ goto copy_value; ++ ++ case KVP_OP_SET: ++ case KVP_OP_DELETE: ++ goto response_done; ++ ++ default: ++ break; ++ } ++ ++ kvp_data = &kvp_msg->body.kvp_enum_data.data; ++ key_name = key; ++ + /* + * The windows host expects the key/value pair to be encoded +- * in utf16. ++ * in utf16. Ensure that the key/value size reported to the host ++ * will be less than or equal to the MAX size (including the ++ * terminating character). + */ + keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN, +- (wchar_t *) kvp_data->data.key, +- HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2); +- kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */ ++ (wchar_t *) kvp_data->key, ++ (HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2) - 2); ++ kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */ ++ ++copy_value: + valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN, +- (wchar_t *) kvp_data->data.value, +- HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2); +- kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */ ++ (wchar_t *) kvp_data->value, ++ (HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2); ++ kvp_data->value_size = 2*(valuelen + 1); /* utf16 encoding */ + +- kvp_data->data.value_type = REG_SZ; /* all our values are strings */ +- icmsghdrp->status = HV_S_OK; ++ /* ++ * If the utf8s to utf16s conversion failed; notify host ++ * of the error. ++ */ ++ if ((keylen < 0) || (valuelen < 0)) ++ icmsghdrp->status = HV_E_FAIL; ++ ++ kvp_data->value_type = REG_SZ; /* all our values are strings */ + + response_done: + icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; +@@ -249,11 +374,18 @@ void hv_kvp_onchannelcallback(void *context) + u64 requestid; + + struct hv_kvp_msg *kvp_msg; +- struct hv_kvp_msg_enumerate *kvp_data; + + struct icmsg_hdr *icmsghdrp; + struct icmsg_negotiate *negop = NULL; + ++ if (kvp_transaction.active) { ++ /* ++ * We will defer processing this callback once ++ * the current transaction is complete. ++ */ ++ kvp_transaction.kvp_context = context; ++ return; ++ } + + vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid); + +@@ -268,29 +400,16 @@ void hv_kvp_onchannelcallback(void *context) + sizeof(struct vmbuspipe_hdr) + + sizeof(struct icmsg_hdr)]; + +- kvp_data = &kvp_msg->kvp_data; +- +- /* +- * We only support the "get" operation on +- * "KVP_POOL_AUTO" pool. +- */ +- +- if ((kvp_msg->kvp_hdr.pool != KVP_POOL_AUTO) || +- (kvp_msg->kvp_hdr.operation != +- KVP_OP_ENUMERATE)) { +- icmsghdrp->status = HV_E_FAIL; +- goto callback_done; +- } +- + /* + * Stash away this global state for completing the + * transaction; note transactions are serialized. + */ ++ + kvp_transaction.recv_len = recvlen; + kvp_transaction.recv_channel = channel; + kvp_transaction.recv_req_id = requestid; + kvp_transaction.active = true; +- kvp_transaction.index = kvp_data->index; ++ kvp_transaction.kvp_msg = kvp_msg; + + /* + * Get the information from the +@@ -308,8 +427,6 @@ void hv_kvp_onchannelcallback(void *context) + + } + +-callback_done: +- + icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION + | ICMSGHDRFLAG_RESPONSE; + +@@ -330,6 +447,14 @@ hv_kvp_init(struct hv_util_service *srv) + return err; + recv_buffer = srv->recv_buffer; + ++ /* ++ * When this driver loads, the user level daemon that ++ * processes the host requests may not yet be running. ++ * Defer processing channel callbacks until the daemon ++ * has registered. ++ */ ++ kvp_transaction.active = true; ++ + return 0; + } + +diff --git a/drivers/hv/hv_kvp.h b/drivers/hv/hv_kvp.h +deleted file mode 100644 +index 9b765d7..0000000 +--- a/drivers/hv/hv_kvp.h ++++ /dev/null +@@ -1,184 +0,0 @@ +-/* +- * An implementation of HyperV key value pair (KVP) functionality for Linux. +- * +- * +- * Copyright (C) 2010, Novell, Inc. +- * Author : K. Y. Srinivasan +- * +- * 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, GOOD TITLE or +- * NON INFRINGEMENT. See the GNU General Public License for more +- * details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- */ +-#ifndef _KVP_H +-#define _KVP_H_ +- +-/* +- * Maximum value size - used for both key names and value data, and includes +- * any applicable NULL terminators. +- * +- * Note: This limit is somewhat arbitrary, but falls easily within what is +- * supported for all native guests (back to Win 2000) and what is reasonable +- * for the IC KVP exchange functionality. Note that Windows Me/98/95 are +- * limited to 255 character key names. +- * +- * MSDN recommends not storing data values larger than 2048 bytes in the +- * registry. +- * +- * Note: This value is used in defining the KVP exchange message - this value +- * cannot be modified without affecting the message size and compatibility. +- */ +- +-/* +- * bytes, including any null terminators +- */ +-#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048) +- +- +-/* +- * Maximum key size - the registry limit for the length of an entry name +- * is 256 characters, including the null terminator +- */ +- +-#define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512) +- +-/* +- * In Linux, we implement the KVP functionality in two components: +- * 1) The kernel component which is packaged as part of the hv_utils driver +- * is responsible for communicating with the host and responsible for +- * implementing the host/guest protocol. 2) A user level daemon that is +- * responsible for data gathering. +- * +- * Host/Guest Protocol: The host iterates over an index and expects the guest +- * to assign a key name to the index and also return the value corresponding to +- * the key. The host will have atmost one KVP transaction outstanding at any +- * given point in time. The host side iteration stops when the guest returns +- * an error. Microsoft has specified the following mapping of key names to +- * host specified index: +- * +- * Index Key Name +- * 0 FullyQualifiedDomainName +- * 1 IntegrationServicesVersion +- * 2 NetworkAddressIPv4 +- * 3 NetworkAddressIPv6 +- * 4 OSBuildNumber +- * 5 OSName +- * 6 OSMajorVersion +- * 7 OSMinorVersion +- * 8 OSVersion +- * 9 ProcessorArchitecture +- * +- * The Windows host expects the Key Name and Key Value to be encoded in utf16. +- * +- * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the +- * data gathering functionality in a user mode daemon. The user level daemon +- * is also responsible for binding the key name to the index as well. The +- * kernel and user-level daemon communicate using a connector channel. +- * +- * The user mode component first registers with the +- * the kernel component. Subsequently, the kernel component requests, data +- * for the specified keys. In response to this message the user mode component +- * fills in the value corresponding to the specified key. We overload the +- * sequence field in the cn_msg header to define our KVP message types. +- * +- * +- * The kernel component simply acts as a conduit for communication between the +- * Windows host and the user-level daemon. The kernel component passes up the +- * index received from the Host to the user-level daemon. If the index is +- * valid (supported), the corresponding key as well as its +- * value (both are strings) is returned. If the index is invalid +- * (not supported), a NULL key string is returned. +- */ +- +-/* +- * +- * The following definitions are shared with the user-mode component; do not +- * change any of this without making the corresponding changes in +- * the KVP user-mode component. +- */ +- +-#define CN_KVP_VAL 0x1 /* This supports queries from the kernel */ +-#define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */ +- +-enum hv_ku_op { +- KVP_REGISTER = 0, /* Register the user mode component */ +- KVP_KERNEL_GET, /* Kernel is requesting the value */ +- KVP_KERNEL_SET, /* Kernel is providing the value */ +- KVP_USER_GET, /* User is requesting the value */ +- KVP_USER_SET /* User is providing the value */ +-}; +- +-struct hv_ku_msg { +- __u32 kvp_index; /* Key index */ +- __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */ +- __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */ +-}; +- +- +- +- +-#ifdef __KERNEL__ +- +-/* +- * Registry value types. +- */ +- +-#define REG_SZ 1 +- +-enum hv_kvp_exchg_op { +- KVP_OP_GET = 0, +- KVP_OP_SET, +- KVP_OP_DELETE, +- KVP_OP_ENUMERATE, +- KVP_OP_COUNT /* Number of operations, must be last. */ +-}; +- +-enum hv_kvp_exchg_pool { +- KVP_POOL_EXTERNAL = 0, +- KVP_POOL_GUEST, +- KVP_POOL_AUTO, +- KVP_POOL_AUTO_EXTERNAL, +- KVP_POOL_AUTO_INTERNAL, +- KVP_POOL_COUNT /* Number of pools, must be last. */ +-}; +- +-struct hv_kvp_hdr { +- u8 operation; +- u8 pool; +-}; +- +-struct hv_kvp_exchg_msg_value { +- u32 value_type; +- u32 key_size; +- u32 value_size; +- u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; +- u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; +-}; +- +-struct hv_kvp_msg_enumerate { +- u32 index; +- struct hv_kvp_exchg_msg_value data; +-}; +- +-struct hv_kvp_msg { +- struct hv_kvp_hdr kvp_hdr; +- struct hv_kvp_msg_enumerate kvp_data; +-}; +- +-int hv_kvp_init(struct hv_util_service *); +-void hv_kvp_deinit(void); +-void hv_kvp_onchannelcallback(void *); +- +-#endif /* __KERNEL__ */ +-#endif /* _KVP_H */ +- +diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c +index 55d58f2..dbb8b8e 100644 +--- a/drivers/hv/hv_util.c ++++ b/drivers/hv/hv_util.c +@@ -28,9 +28,6 @@ + #include + #include + +-#include "hv_kvp.h" +- +- + static void shutdown_onchannelcallback(void *context); + static struct hv_util_service util_shutdown = { + .util_cb = shutdown_onchannelcallback, +diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h +index be2f3af..b2a1fad 100644 +--- a/drivers/hv/hyperv_vmbus.h ++++ b/drivers/hv/hyperv_vmbus.h +@@ -457,7 +457,6 @@ static const uuid_le VMBUS_SERVICE_ID = { + }, + }; + +-#define MAX_NUM_CPUS 32 + + + struct hv_input_signal_event_buffer { +@@ -483,12 +482,12 @@ struct hv_context { + /* 8-bytes aligned of the buffer above */ + struct hv_input_signal_event *signal_event_param; + +- void *synic_message_page[MAX_NUM_CPUS]; +- void *synic_event_page[MAX_NUM_CPUS]; ++ void *synic_message_page[NR_CPUS]; ++ void *synic_event_page[NR_CPUS]; + /* + * buffer to post messages to the host. + */ +- void *post_msg_page[MAX_NUM_CPUS]; ++ void *post_msg_page[NR_CPUS]; + }; + + extern struct hv_context hv_context; +@@ -615,6 +614,7 @@ void vmbus_device_unregister(struct hv_device *device_obj); + + struct vmbus_channel *relid2channel(u32 relid); + ++void vmbus_free_channels(void); + + /* Connection interface */ + +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index f58067f..1ec309d 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -792,8 +792,19 @@ cleanup: + return ret; + } + ++static void __exit vmbus_exit(void) ++{ ++ ++ free_irq(irq, hv_acpi_dev); ++ vmbus_free_channels(); ++ bus_unregister(&hv_bus); ++ hv_cleanup(); ++ acpi_bus_unregister_driver(&vmbus_acpi_driver); ++} ++ + + MODULE_LICENSE("GPL"); + MODULE_VERSION(HV_DRV_VERSION); + +-module_init(hv_acpi_init); ++subsys_initcall(hv_acpi_init); ++module_exit(vmbus_exit); +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index 83e3e9d..5c984a6 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -293,6 +293,26 @@ config SENSORS_ATXP1 + This driver can also be built as a module. If so, the module + will be called atxp1. + ++config SENSORS_CY8CXX ++ tristate "Cypress Semiconductor CY8Cxx" ++ depends on I2C ++ help ++ If you say yes here you get support for Cypress Semiconductor ++ CY8C series sensor chips. ++ ++ This driver can also be built as a module. If so, the module ++ will be called cy8cxx. ++ ++config SENSORS_CY8C3245R1 ++ tristate "Cypress Semiconductor CY8C3245R1" ++ depends on I2C ++ help ++ If you say yes here you get support for Cypress Semiconductor ++ CY8C3245 first revision sensor chips. ++ ++ This driver can also be built as a module. If so, the module ++ will be called cy8c3245r1. ++ + config SENSORS_DS620 + tristate "Dallas Semiconductor DS620" + depends on I2C +@@ -474,8 +494,8 @@ config SENSORS_IT87 + select HWMON_VID + help + If you say yes here you get support for ITE IT8705F, IT8712F, +- IT8716F, IT8718F, IT8720F, IT8721F, IT8726F and IT8758E sensor +- chips, and the SiS960 clone. ++ IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F and IT8758E ++ sensor chips, and the SiS960 clone. + + This driver can also be built as a module. If so, the module + will be called it87. +@@ -812,6 +832,27 @@ config SENSORS_MAX6650 + This driver can also be built as a module. If so, the module + will be called max6650. + ++config SENSORS_MAX6620 ++ tristate "Maxim MAX6620 sensor chip" ++ depends on I2C && EXPERIMENTAL ++ help ++ If you say yes here you get support for the MAX6620 ++ sensor chips. ++ ++ This driver can also be built as a module. If so, the module ++ will be called max6620. ++ ++config SENSORS_MAX6697 ++ tristate "Maxim MAX6697 and compatibles" ++ depends on I2C ++ help ++ If you say yes here you get support for MAX6581, MAX6602, MAX6622, ++ MAX6636, MAX6689, MAX6693, MAX6694, MAX6697, MAX6698, and MAX6699 ++ temperature sensor chips. ++ ++ This driver can also be built as a module. If so, the module ++ will be called max6697. ++ + config SENSORS_NTC_THERMISTOR + tristate "NTC thermistor support" + depends on EXPERIMENTAL +@@ -964,6 +1005,16 @@ config SENSORS_EMC2103 + This driver can also be built as a module. If so, the module + will be called emc2103. + ++config SENSORS_EMC2305 ++ tristate "SMSC EMC2305" ++ depends on I2C ++ help ++ If you say yes here you get support for the SMSC EMC2305/EMC2303 ++ fan controller chips. ++ ++ This driver can also be built as a module. If so, the module ++ will be called emc2305. ++ + config SENSORS_EMC6W201 + tristate "SMSC EMC6W201" + depends on I2C +diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +index 8251ce8..ff3a18e 100644 +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -42,11 +42,14 @@ obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o + obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o + obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o + obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o ++obj-$(CONFIG_SENSORS_CY8CXX) += cy8cxx.o ++obj-$(CONFIG_SENSORS_CY8C3245R1) += cy8c3245r1.o + obj-$(CONFIG_SENSORS_DME1737) += dme1737.o + obj-$(CONFIG_SENSORS_DS620) += ds620.o + obj-$(CONFIG_SENSORS_DS1621) += ds1621.o + obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o + obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o ++obj-$(CONFIG_SENSORS_EMC2305) += emc2305.o + obj-$(CONFIG_SENSORS_EMC6W201) += emc6w201.o + obj-$(CONFIG_SENSORS_EXYNOS4_TMU) += exynos4_tmu.o + obj-$(CONFIG_SENSORS_F71805F) += f71805f.o +@@ -94,6 +97,8 @@ obj-$(CONFIG_SENSORS_MAX1668) += max1668.o + obj-$(CONFIG_SENSORS_MAX6639) += max6639.o + obj-$(CONFIG_SENSORS_MAX6642) += max6642.o + obj-$(CONFIG_SENSORS_MAX6650) += max6650.o ++obj-$(CONFIG_SENSORS_MAX6620) += max6620.o ++obj-$(CONFIG_SENSORS_MAX6697) += max6697.o + obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o + obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o + obj-$(CONFIG_SENSORS_PC87360) += pc87360.o +diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c +index 3a15fd6..e84af9c 100644 +--- a/drivers/hwmon/adt7470.c ++++ b/drivers/hwmon/adt7470.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + /* Addresses to scan */ + static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; +@@ -48,6 +49,7 @@ static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; + #define ADT7470_REG_PWM_MAX_MAX_ADDR 0x3B + #define ADT7470_REG_CFG 0x40 + #define ADT7470_FSPD_MASK 0x04 ++#define ADT7470_TODIS_MASK 0x08 + #define ADT7470_REG_ALARM1 0x41 + #define ADT7470_R1T_ALARM 0x01 + #define ADT7470_R2T_ALARM 0x02 +@@ -225,6 +227,14 @@ static void adt7470_init_client(struct i2c_client *client) + if (reg < 0) { + dev_err(&client->dev, "cannot read configuration register\n"); + } else { ++ struct property *pp; ++ pp = of_find_property(client->dev.of_node, ++ "disable-smbus-timeout", NULL); ++ if (pp) ++ reg |= ADT7470_TODIS_MASK; ++ else ++ reg &= ~ADT7470_TODIS_MASK; ++ + /* start monitoring (and do a self-test) */ + i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg | 3); + } +diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c +index b5fcd87..d460f4e 100644 +--- a/drivers/hwmon/adt7475.c ++++ b/drivers/hwmon/adt7475.c +@@ -671,6 +671,21 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, + return count; + } + ++ /* Clear PWM invert bit, i.e. force normal sense of ++ * duty cycle. See ADT7473 data sheet for description ++ * of register 0x5C, bit 4: ++ * ++ * This bit inverts the PWM output. The default is ++ * 0, which corresponds to a logic high output for ++ * 100% duty cycle. Setting this bit to 1 inverts ++ * the PWM output, so 100% duty cycle corresponds to ++ * a logic low output. ++ * ++ */ ++ data->pwm[CONTROL][sattr->index] &= ~(1 << 4); ++ i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(sattr->index), ++ data->pwm[CONTROL][sattr->index]); ++ + reg = PWM_REG(sattr->index); + break; + +diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c +index e6ec920..ce9d21f 100644 +--- a/drivers/hwmon/coretemp.c ++++ b/drivers/hwmon/coretemp.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + #define DRVNAME "coretemp" + +@@ -791,13 +792,23 @@ static struct notifier_block coretemp_cpu_notifier __refdata = { + .notifier_call = coretemp_cpu_callback, + }; + ++static const struct x86_cpu_id coretemp_ids[] = { ++ { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM }, ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, coretemp_ids); ++ + static int __init coretemp_init(void) + { + int i, err = -ENODEV; + +- /* quick check if we run Intel */ +- if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL) +- goto exit; ++ /* ++ * CPUID.06H.EAX[0] indicates whether the CPU has thermal ++ * sensors. We check this bit only, all the early CPUs ++ * without thermal sensors will be filtered out. ++ */ ++ if (!x86_match_cpu(coretemp_ids)) ++ return -ENODEV; + + err = platform_driver_register(&coretemp_driver); + if (err) +diff --git a/drivers/hwmon/cy8c3245r1.c b/drivers/hwmon/cy8c3245r1.c +new file mode 100644 +index 0000000..3cf12d5 +--- /dev/null ++++ b/drivers/hwmon/cy8c3245r1.c +@@ -0,0 +1,1081 @@ ++/* ++ * A hwmon driver for the Cypress Semiconductor C3245 ++ * Copyright (C) 2014 Cumulus Networks ++ * ++ * Author: Shrijeet Mukherjee ++ * Author: Vidya Ravipati ++ * ++ * Based on the adt7470 driver ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* cy8c3245r1 registers */ ++#define CY8C3245R1_REG_BASE_ADDR 0x00 ++#define CY8C3245R1_REG_DEV_ID 0x09 ++#define CY8C3245R1_REG_COMPANY_ID 0x05 ++#define CY8C3245R1_REG_FW_REV_MAJ 0x06 ++#define CY8C3245R1_REG_FW_REV_MIN 0x07 ++#define CY8C3245R1_REG_RESET 0x08 ++ ++/* ++ * Fan PWM / RPM Profile control registers ++ * ++ * These registers consist of two-bytes each ++ */ ++#define CY8C3245R1_REG_FAN_PROFILE_BASE_ADDR 0x10 ++#define CY8C3245R1_REG_FAN_PROFILE(x) (CY8C3245R1_REG_FAN_PROFILE_BASE_ADDR + ((x) * 2)) ++enum { ++ CY8C3245R1_FAN_PROFILE_LOW_DUTY = 0, ++ CY8C3245R1_FAN_PROFILE_LOW_RPM, ++ CY8C3245R1_FAN_PROFILE_HIGH_DUTY, ++ CY8C3245R1_FAN_PROFILE_HIGH_RPM, ++ CY8C3245R1_FAN_PROFILE_SPEED_0_DUTY, ++ CY8C3245R1_FAN_PROFILE_SPEED_100_DUTY, ++ CY8C3245R1_FAN_PROFILE_MAX ++}; ++ ++/* skipping over regs to set */ ++ ++#define CY8C3245R1_REG_TEMP_BASE_ADDR 0x20 ++ ++#define CY8C3245R1_REG_FAN_BASE_ADDR 0x40 ++#define CY8C3245R1_REG_FAN_TARGET_BASE_ADDR 0x3E ++ ++#define CY8C3245R1_REG_PWM_BASE_ADDR 0x3C ++ ++#define CY8C3245R1_REG_TEMP_LIMITS_BASE_ADDR 0x20 ++#define CY8C3245R1_REG_TEMP_LIMITS_MAX_ADDR 0x28 ++ ++#define CY8C3245R1_REG_FAN_MAX_BASE_ADDR 0x16 ++ ++#define CY8C3245R1_REG_PWM_CFG_BASE_ADDR 0x33 ++ ++#define CY8C3245R1_TEMP_COUNT 8 ++#define CY8C3245R1_TEMP_REG(x) (CY8C3245R1_REG_TEMP_BASE_ADDR + (x)) ++#define CY8C3245R1_TEMP_MAX_REG(x) (CY8C3245R1_REG_TEMP_LIMITS_MAX_ADDR + (x)) ++ ++#define CY8C3245R1_FAN_COUNT 8 ++#define CY8C3245R1_REG_FAN(x) (CY8C3245R1_REG_FAN_BASE_ADDR + ((x) * 2)) ++ ++#define CY8C3245R1_REG_FAN_MIN(x) (CY8C3245R1_REG_FAN_MIN_BASE_ADDR + ((x) * 2)) ++#define CY8C3245R1_REG_FAN_MAX(x) (CY8C3245R1_REG_FAN_MAX_BASE_ADDR) ++#define CY8C3245R1_REG_FAN_TARGET (CY8C3245R1_REG_FAN_TARGET_BASE_ADDR) ++ ++#define CY8C3245R1_PWM_COUNT 1 ++#define CY8C3245R1_REG_PWM (CY8C3245R1_REG_PWM_BASE_ADDR) ++ ++#define CY8C3245R1_COMPANY_ID 0xCC ++#define CY8C3245R1_DEV_ID 0x09 ++#define CY8C3245R1_FW_REV_MAJ 0x02 ++#define CY8C3245R1_FW_REV_MIN 0x03 ++ ++/* "all temps" according to hwmon sysfs interface spec */ ++#define CY8C3245R1_PWM_ALL_TEMPS 0x3FF ++ ++/* How often do we reread sensors values? (In jiffies) */ ++#define SENSOR_REFRESH_INTERVAL (5 * HZ) ++ ++/* How often do we reread sensor limit values? (In jiffies) */ ++#define LIMIT_REFRESH_INTERVAL (60 * HZ) ++ ++/* Wait at least 200ms per sensor for 10 sensors */ ++#define TEMP_COLLECTION_TIME 2000 ++ ++/* auto update thing won't fire more than every 2s */ ++#define AUTO_UPDATE_INTERVAL 2000 ++ ++/* datasheet says to divide this number by the fan reading to get fan rpm */ ++#define FAN_PERIOD_INVALID 65535 ++#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) ++ ++struct cy8c3245r1_data { ++ struct device *hwmon_dev; ++ struct attribute_group attrs; ++ struct mutex lock; ++ char sensors_valid; ++ char limits_valid; ++ unsigned long sensors_last_updated; /* In jiffies */ ++ unsigned long limits_last_updated; /* In jiffies */ ++ ++ int num_temp_sensors; /* -1 = probe */ ++ int temperatures_probed; ++ ++ s8 temp[CY8C3245R1_TEMP_COUNT]; ++ s8 temp_max[CY8C3245R1_TEMP_COUNT]; ++ u16 fan[CY8C3245R1_FAN_COUNT]; ++ u16 fan_max[CY8C3245R1_FAN_COUNT]; ++ u16 fan_min[CY8C3245R1_FAN_COUNT]; ++ u16 fan_tgt; ++ u16 fan_profile[CY8C3245R1_FAN_PROFILE_MAX]; ++ u8 fan_alarm; ++ u8 temp_alarm; ++ u8 force_pwm_max; ++ u8 pwm; ++ u8 pwm_automatic; ++ struct task_struct *auto_update; ++ struct completion auto_update_stop; ++ unsigned int auto_update_interval; ++}; ++ ++static int cy8c3245r1_probe(struct i2c_client *client, ++ const struct i2c_device_id *id); ++static int cy8c3245r1_remove(struct i2c_client *client); ++ ++static const struct i2c_device_id cy8c3245r1_id[] = { ++ { "CY8C3245R1", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, cy8c3245r1_id); ++ ++static struct i2c_driver cy8c3245r1_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "cy8c3245r1", ++ }, ++ .probe = cy8c3245r1_probe, ++ .remove = cy8c3245r1_remove, ++ .id_table = cy8c3245r1_id, ++}; ++ ++/* ++ * 16-bit registers on the CY8C3245R1 are high-byte first. ++ */ ++static inline int cy8c3245r1_read_word_data(struct i2c_client *client, u8 reg) ++{ ++ s32 rc; ++ u16 val; ++ ++ /* read high byte */ ++ rc = i2c_smbus_read_byte_data(client, reg); ++ if (rc < 0) { ++ dev_warn(&client->dev, "i2c read failed: 0x%02x, errno %d\n", ++ reg, -rc); ++ return rc; ++ } ++ val = ((u16)rc & 0xFF) << 8; ++ ++ /* read low byte */ ++ rc = i2c_smbus_read_byte_data(client, reg + 1); ++ if (rc < 0) { ++ dev_warn(&client->dev, "i2c read failed: 0x%02x, errno %d\n", ++ reg + 1, -rc); ++ return rc; ++ } ++ val |= (u16)rc & 0xFF; ++ ++ return val; ++} ++ ++static inline int cy8c3245r1_write_word_data(struct i2c_client *client, ++ u8 reg, ++ u16 value) ++{ ++ s32 rc; ++ ++ /* write high byte */ ++ rc = i2c_smbus_write_byte_data(client, reg, value >> 8); ++ if (rc < 0) { ++ dev_warn(&client->dev, ++ "i2c write failed: 0x%02x: 0x%02x, errno %d\n", ++ reg, value >> 8, -rc); ++ return rc; ++ } ++ ++ /* write low byte */ ++ rc = i2c_smbus_write_byte_data(client, reg + 1, value & 0xFF); ++ if (rc < 0) { ++ dev_warn(&client->dev, ++ "i2c write failed: 0x%02x: 0x%02x, errno %d\n", ++ reg + 1, value & 0xFF, -rc); ++ return rc; ++ } ++ ++ return rc; ++} ++ ++static void cy8c3245r1_init_client(struct i2c_client *client) ++{ ++ int reg = i2c_smbus_read_byte_data(client, CY8C3245R1_REG_PWM_CFG_BASE_ADDR); ++ ++ if (reg < 0) { ++ dev_err(&client->dev, "cannot read configuration register\n"); ++ } else { ++ i2c_smbus_write_byte_data(client, CY8C3245R1_REG_PWM_CFG_BASE_ADDR, 0); ++ } ++} ++ ++/* Probe for temperature sensors. Assumes lock is held */ ++static int cy8c3245r1_read_temperatures(struct i2c_client *client, ++ struct cy8c3245r1_data *data) ++{ ++ int i; ++ ++ /* Only count fans if we have to */ ++ if (data->num_temp_sensors >= 0) ++ return 0; ++ ++ for (i = 0; i < CY8C3245R1_TEMP_COUNT; i++) { ++ data->temp[i] = i2c_smbus_read_byte_data(client, ++ CY8C3245R1_TEMP_REG(i)); ++ if (data->temp[i]) ++ data->num_temp_sensors = i + 1; ++ } ++ data->temperatures_probed = 1; ++ return 0; ++} ++ ++static int cy8c3245r1_update_thread(void *p) ++{ ++ struct i2c_client *client = p; ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ ++ while (!kthread_should_stop()) { ++ mutex_lock(&data->lock); ++ cy8c3245r1_read_temperatures(client, data); ++ mutex_unlock(&data->lock); ++ if (kthread_should_stop()) ++ break; ++ msleep_interruptible(data->auto_update_interval); ++ } ++ ++ complete_all(&data->auto_update_stop); ++ return 0; ++} ++ ++static struct cy8c3245r1_data *cy8c3245r1_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ unsigned long local_jiffies = jiffies; ++ int i; ++ int need_sensors = 1; ++ int need_limits = 1; ++ ++ /* ++ * Figure out if we need to update the shadow registers. ++ * Lockless means that we may occasionally report out of ++ * date data. ++ */ ++ if (time_before(local_jiffies, data->sensors_last_updated + ++ SENSOR_REFRESH_INTERVAL) && ++ data->sensors_valid) ++ need_sensors = 0; ++ ++ if (time_before(local_jiffies, data->limits_last_updated + ++ LIMIT_REFRESH_INTERVAL) && ++ data->limits_valid) ++ need_limits = 0; ++ ++ if (!need_sensors && !need_limits) ++ return data; ++ ++ mutex_lock(&data->lock); ++ if (!need_sensors) ++ goto no_sensor_update; ++ ++ if (!data->temperatures_probed) ++ cy8c3245r1_read_temperatures(client, data); ++ else ++ for (i = 0; i < CY8C3245R1_TEMP_COUNT; i++) ++ data->temp[i] = i2c_smbus_read_byte_data(client, ++ CY8C3245R1_TEMP_REG(i)); ++ ++ for (i = 0; i < CY8C3245R1_FAN_COUNT; i++) { ++ data->fan[i] = cy8c3245r1_read_word_data(client, ++ CY8C3245R1_REG_FAN(i)); ++ } ++ ++ data->pwm = i2c_smbus_read_byte_data(client, ++ CY8C3245R1_REG_PWM); ++ ++ data->sensors_last_updated = local_jiffies; ++ data->sensors_valid = 1; ++ ++no_sensor_update: ++ if (!need_limits) ++ goto out; ++ ++ for (i = 0; i < CY8C3245R1_TEMP_COUNT; i++) { ++ data->temp_max[i] = i2c_smbus_read_byte_data(client, ++ CY8C3245R1_TEMP_MAX_REG(i)); ++ } ++ ++ for (i = 0; i < CY8C3245R1_FAN_COUNT; i++) { ++ data->fan_max[i] = cy8c3245r1_read_word_data(client, ++ CY8C3245R1_REG_FAN_MAX(i)); ++ } ++ data->fan_tgt = cy8c3245r1_read_word_data(client, ++ CY8C3245R1_REG_FAN_TARGET); ++ ++ for (i = 0; i < CY8C3245R1_FAN_PROFILE_MAX; i++) { ++ data->fan_profile[i] = cy8c3245r1_read_word_data(client, ++ CY8C3245R1_REG_FAN_PROFILE(i)); ++ } ++ ++ data->limits_last_updated = local_jiffies; ++ data->limits_valid = 1; ++ ++out: ++ mutex_unlock(&data->lock); ++ return data; ++} ++ ++static ssize_t show_auto_update_interval(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ return sprintf(buf, "%d\n", data->auto_update_interval); ++} ++ ++static ssize_t set_auto_update_interval(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = SENSORS_LIMIT(temp, 0, 60000); ++ ++ mutex_lock(&data->lock); ++ data->auto_update_interval = temp; ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_num_temp_sensors(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ return sprintf(buf, "%d\n", data->num_temp_sensors); ++} ++ ++static ssize_t set_num_temp_sensors(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = SENSORS_LIMIT(temp, -1, 10); ++ ++ mutex_lock(&data->lock); ++ data->num_temp_sensors = temp; ++ if (temp < 0) ++ data->temperatures_probed = 0; ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_temp_max(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ return sprintf(buf, "%d\n", 1000 * data->temp_max[attr->index]); ++} ++ ++static ssize_t set_temp_max(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = DIV_ROUND_CLOSEST(temp, 1000); ++ temp = SENSORS_LIMIT(temp, -128, 127); ++ ++ mutex_lock(&data->lock); ++ data->temp_max[attr->index] = temp; ++ i2c_smbus_write_byte_data(client, CY8C3245R1_TEMP_MAX_REG(attr->index), ++ temp); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ return sprintf(buf, "%d\n", 1000 * data->temp[attr->index]); ++} ++ ++static ssize_t show_fan_max(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ if (FAN_DATA_VALID(data->fan_max[attr->index])) ++ return sprintf(buf, "%d\n", ++ data->fan_max[attr->index]); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t set_fan_max(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long rpm; ++ ++ if (strict_strtol(buf, 10, &rpm) || !rpm) ++ return -EINVAL; ++ ++ rpm = SENSORS_LIMIT(rpm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_max[attr->index] = rpm; ++ cy8c3245r1_write_word_data(client, CY8C3245R1_REG_FAN_MAX(attr->index), rpm); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++/* ++ * fan_min is a pure software concept, not implemented by hardware. ++ * It is used to compute the alarm status. ++ */ ++static ssize_t show_fan_min(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ return sprintf(buf, "%d\n", data->fan_min[attr->index]); ++} ++ ++static ssize_t set_fan_min(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long rpm; ++ ++ if (strict_strtol(buf, 10, &rpm) || !rpm) ++ return -EINVAL; ++ ++ rpm = SENSORS_LIMIT(rpm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_min[attr->index] = rpm; ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_fan_target(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ if (FAN_DATA_VALID(data->fan_tgt)) ++ return sprintf(buf, "%d\n", ++ data->fan_tgt); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t set_fan_target(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long rpm; ++ ++ if (strict_strtol(buf, 10, &rpm) || !rpm) ++ return -EINVAL; ++ ++ rpm = SENSORS_LIMIT(rpm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_tgt = rpm; ++ cy8c3245r1_write_word_data(client, CY8C3245R1_REG_FAN_TARGET, rpm); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++/* ++ * Show Fan Profile Settings ++ */ ++static ssize_t show_fan_profile(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ return sprintf(buf, "%u\n", ++ data->fan_profile[attr->index]); ++} ++ ++/* ++ * Set Fan Profile Settings ++ */ ++static ssize_t set_fan_profile(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long parm; ++ ++ if (strict_strtoul(buf, 10, &parm)) ++ return -EINVAL; ++ ++ parm = SENSORS_LIMIT(parm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_profile[attr->index] = parm; ++ cy8c3245r1_write_word_data(client, CY8C3245R1_REG_FAN_PROFILE(attr->index), parm); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ if (FAN_DATA_VALID(data->fan[attr->index])) ++ return sprintf(buf, "%d\n", data->fan[attr->index]); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ return sprintf(buf, "%d\n", data->pwm); ++} ++ ++static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = SENSORS_LIMIT(temp, 0, 255); ++ ++ mutex_lock(&data->lock); ++ data->pwm = temp; ++ i2c_smbus_write_byte_data(client, CY8C3245R1_REG_PWM, temp); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_fan_alarm_mask(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ int i; ++ u32 alarm_mask = 0; ++ ++ for (i = 0; i < CY8C3245R1_FAN_COUNT; i++) ++ if ((data->fan[i] < data->fan_min[i]) || ++ (data->fan[i] >= data->fan_max[i])) ++ alarm_mask |= 0x1 << i; ++ ++ return sprintf(buf, "%x\n", alarm_mask); ++} ++ ++static ssize_t show_temp_alarm_mask(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ int i; ++ u32 alarm_mask = 0; ++ ++ for (i = 0; i < CY8C3245R1_TEMP_COUNT; i++) ++ if (data->temp[i] >= data->temp_max[i]) ++ alarm_mask |= 0x1 << i; ++ ++ return sprintf(buf, "%x\n", alarm_mask); ++} ++ ++static ssize_t show_fan_alarm(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ if ((data->fan[attr->index] < data->fan_min[attr->index]) || ++ (data->fan[attr->index] >= data->fan_max[attr->index])) ++ return sprintf(buf, "1\n"); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t show_temp_alarm(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ if (data->temp[attr->index] >= data->temp_max[attr->index]) ++ return sprintf(buf, "1\n"); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t set_pwm_auto(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ if (!(temp >= 0 && temp <= 3)) ++ return -EINVAL; ++ ++ return count; ++} ++ ++static ssize_t show_pwm_auto(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ return sprintf(buf, "%d\n", data->pwm_automatic); ++} ++ ++#define CY8C3245R1_REG_MIN 0x00 ++#define CY8C3245R1_REG_MAX 0xe0 ++ ++static ssize_t show_debug(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ int len = 0, i, j; ++ u8 val; ++ for (i = 0; i < (CY8C3245R1_REG_MAX - CY8C3245R1_REG_MIN) / 16; i++) { ++ len += sprintf(buf+len, "0x%02x: ", CY8C3245R1_REG_MIN + (i * 16)); ++ for (j = 0; j < 16; j++) { ++ val = i2c_smbus_read_byte_data(client, CY8C3245R1_REG_MIN + (i * 16) + j); ++ len += sprintf(buf+len, "%02x ", val); ++ } ++ len += sprintf(buf+len, "\n"); ++ } ++ return len; ++} ++ ++static DEVICE_ATTR(fan_alarm_mask, S_IRUGO, show_fan_alarm_mask, NULL); ++static DEVICE_ATTR(temp_alarm_mask, S_IRUGO, show_temp_alarm_mask, NULL); ++static DEVICE_ATTR(num_temp_sensors, S_IWUSR | S_IRUGO, show_num_temp_sensors, ++ set_num_temp_sensors); ++static DEVICE_ATTR(auto_update_interval, S_IWUSR | S_IRUGO, ++ show_auto_update_interval, set_auto_update_interval); ++ ++static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 0); ++static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 1); ++static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 2); ++static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 3); ++static SENSOR_DEVICE_ATTR(temp5_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 4); ++static SENSOR_DEVICE_ATTR(temp6_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 5); ++static SENSOR_DEVICE_ATTR(temp7_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 6); ++static SENSOR_DEVICE_ATTR(temp8_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 7); ++ ++static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); ++static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); ++static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); ++static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); ++static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4); ++static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5); ++static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6); ++static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7); ++ ++static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0); ++static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1); ++static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2); ++static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_temp_alarm, NULL, 3); ++static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO, show_temp_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(temp6_alarm, S_IRUGO, show_temp_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(temp7_alarm, S_IRUGO, show_temp_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(temp8_alarm, S_IRUGO, show_temp_alarm, NULL, 4); ++ ++static SENSOR_DEVICE_ATTR(fan1_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 0); ++static SENSOR_DEVICE_ATTR(fan2_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 1); ++static SENSOR_DEVICE_ATTR(fan3_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 2); ++static SENSOR_DEVICE_ATTR(fan4_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 3); ++static SENSOR_DEVICE_ATTR(fan5_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 4); ++static SENSOR_DEVICE_ATTR(fan6_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 5); ++static SENSOR_DEVICE_ATTR(fan7_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 6); ++static SENSOR_DEVICE_ATTR(fan8_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 7); ++ ++static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 0); ++static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 1); ++static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 2); ++static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 3); ++static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 4); ++static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 5); ++static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 6); ++static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 7); ++ ++static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 0); ++static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 1); ++static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 2); ++static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 3); ++static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 4); ++static SENSOR_DEVICE_ATTR(fan6_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 5); ++static SENSOR_DEVICE_ATTR(fan7_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 6); ++static SENSOR_DEVICE_ATTR(fan8_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 7); ++ ++#define FAN_PROFILE_ATTR(_name, _index) \ ++ SENSOR_DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \ ++ show_fan_profile, set_fan_profile, _index) ++ ++static FAN_PROFILE_ATTR(fan_low_duty, CY8C3245R1_FAN_PROFILE_LOW_DUTY); ++static FAN_PROFILE_ATTR(fan_low_rpm, CY8C3245R1_FAN_PROFILE_LOW_RPM); ++static FAN_PROFILE_ATTR(fan_high_duty, CY8C3245R1_FAN_PROFILE_HIGH_DUTY); ++static FAN_PROFILE_ATTR(fan_high_rpm, CY8C3245R1_FAN_PROFILE_HIGH_RPM); ++static FAN_PROFILE_ATTR(fan_speed_0_duty, CY8C3245R1_FAN_PROFILE_SPEED_0_DUTY); ++static FAN_PROFILE_ATTR(fan_speed_100_duty,CY8C3245R1_FAN_PROFILE_SPEED_100_DUTY); ++ ++static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); ++static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); ++static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); ++static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); ++static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4); ++static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5); ++static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6); ++static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7); ++ ++static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0); ++static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1); ++static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2); ++static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3); ++static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5); ++static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6); ++static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7); ++ ++static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); ++static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); ++static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); ++static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); ++static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 4); ++static SENSOR_DEVICE_ATTR(pwm6, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 5); ++static SENSOR_DEVICE_ATTR(pwm7, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 6); ++static SENSOR_DEVICE_ATTR(pwm8, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 7); ++ ++static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm6_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm7_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm8_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++ ++static SENSOR_DEVICE_ATTR(debug, S_IRUGO, show_debug, NULL, 0); ++ ++static struct attribute *cy8c3245r1_attr[] = ++{ ++ &dev_attr_fan_alarm_mask.attr, ++ &dev_attr_temp_alarm_mask.attr, ++ &dev_attr_num_temp_sensors.attr, ++ &dev_attr_auto_update_interval.attr, ++ &sensor_dev_attr_temp1_max.dev_attr.attr, ++ &sensor_dev_attr_temp2_max.dev_attr.attr, ++ &sensor_dev_attr_temp3_max.dev_attr.attr, ++ &sensor_dev_attr_temp4_max.dev_attr.attr, ++ &sensor_dev_attr_temp5_max.dev_attr.attr, ++ &sensor_dev_attr_temp6_max.dev_attr.attr, ++ &sensor_dev_attr_temp7_max.dev_attr.attr, ++ &sensor_dev_attr_temp8_max.dev_attr.attr, ++ &sensor_dev_attr_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_temp2_input.dev_attr.attr, ++ &sensor_dev_attr_temp3_input.dev_attr.attr, ++ &sensor_dev_attr_temp4_input.dev_attr.attr, ++ &sensor_dev_attr_temp5_input.dev_attr.attr, ++ &sensor_dev_attr_temp6_input.dev_attr.attr, ++ &sensor_dev_attr_temp7_input.dev_attr.attr, ++ &sensor_dev_attr_temp8_input.dev_attr.attr, ++ &sensor_dev_attr_temp1_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp2_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp3_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp4_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp5_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp6_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp7_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp8_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan1_max.dev_attr.attr, ++ &sensor_dev_attr_fan2_max.dev_attr.attr, ++ &sensor_dev_attr_fan3_max.dev_attr.attr, ++ &sensor_dev_attr_fan4_max.dev_attr.attr, ++ &sensor_dev_attr_fan5_max.dev_attr.attr, ++ &sensor_dev_attr_fan6_max.dev_attr.attr, ++ &sensor_dev_attr_fan7_max.dev_attr.attr, ++ &sensor_dev_attr_fan8_max.dev_attr.attr, ++ &sensor_dev_attr_fan1_min.dev_attr.attr, ++ &sensor_dev_attr_fan2_min.dev_attr.attr, ++ &sensor_dev_attr_fan3_min.dev_attr.attr, ++ &sensor_dev_attr_fan4_min.dev_attr.attr, ++ &sensor_dev_attr_fan5_min.dev_attr.attr, ++ &sensor_dev_attr_fan6_min.dev_attr.attr, ++ &sensor_dev_attr_fan7_min.dev_attr.attr, ++ &sensor_dev_attr_fan8_min.dev_attr.attr, ++ &sensor_dev_attr_fan1_target.dev_attr.attr, ++ &sensor_dev_attr_fan2_target.dev_attr.attr, ++ &sensor_dev_attr_fan3_target.dev_attr.attr, ++ &sensor_dev_attr_fan4_target.dev_attr.attr, ++ &sensor_dev_attr_fan5_target.dev_attr.attr, ++ &sensor_dev_attr_fan6_target.dev_attr.attr, ++ &sensor_dev_attr_fan7_target.dev_attr.attr, ++ &sensor_dev_attr_fan8_target.dev_attr.attr, ++ &sensor_dev_attr_fan1_input.dev_attr.attr, ++ &sensor_dev_attr_fan2_input.dev_attr.attr, ++ &sensor_dev_attr_fan3_input.dev_attr.attr, ++ &sensor_dev_attr_fan4_input.dev_attr.attr, ++ &sensor_dev_attr_fan5_input.dev_attr.attr, ++ &sensor_dev_attr_fan6_input.dev_attr.attr, ++ &sensor_dev_attr_fan7_input.dev_attr.attr, ++ &sensor_dev_attr_fan8_input.dev_attr.attr, ++ &sensor_dev_attr_fan1_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan2_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan3_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan4_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan5_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan6_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan7_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan8_alarm.dev_attr.attr, ++ &sensor_dev_attr_pwm1.dev_attr.attr, ++ &sensor_dev_attr_pwm2.dev_attr.attr, ++ &sensor_dev_attr_pwm3.dev_attr.attr, ++ &sensor_dev_attr_pwm4.dev_attr.attr, ++ &sensor_dev_attr_pwm5.dev_attr.attr, ++ &sensor_dev_attr_pwm6.dev_attr.attr, ++ &sensor_dev_attr_pwm7.dev_attr.attr, ++ &sensor_dev_attr_pwm8.dev_attr.attr, ++ &sensor_dev_attr_pwm1_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm2_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm3_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm4_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm5_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm6_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm7_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm8_enable.dev_attr.attr, ++ &sensor_dev_attr_fan_low_duty.dev_attr.attr, ++ &sensor_dev_attr_fan_low_rpm.dev_attr.attr, ++ &sensor_dev_attr_fan_high_duty.dev_attr.attr, ++ &sensor_dev_attr_fan_high_rpm.dev_attr.attr, ++ &sensor_dev_attr_fan_speed_0_duty.dev_attr.attr, ++ &sensor_dev_attr_fan_speed_100_duty.dev_attr.attr, ++ &sensor_dev_attr_debug.dev_attr.attr, ++ NULL ++}; ++ ++static int cy8c3245r1_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct cy8c3245r1_data *data; ++ int err; ++ int minor_revision, major_revision; ++ ++ data = kzalloc(sizeof(struct cy8c3245r1_data), GFP_KERNEL); ++ if (!data) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ data->num_temp_sensors = -1; ++ data->auto_update_interval = AUTO_UPDATE_INTERVAL; ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->lock); ++ ++ dev_info(&client->dev, "%s chip found\n", client->name); ++ ++ /* Initialize the CY8C3245R1 chip */ ++ cy8c3245r1_init_client(client); ++ ++ minor_revision = i2c_smbus_read_byte_data(client, CY8C3245R1_REG_FW_REV_MIN); ++ major_revision = i2c_smbus_read_byte_data(client, CY8C3245R1_REG_FW_REV_MAJ); ++ if ((minor_revision < CY8C3245R1_FW_REV_MIN) || ++ (major_revision != CY8C3245R1_FW_REV_MAJ)) { ++ dev_err(&client->dev, ++ "PSoC Supported Version >= %u.%u, Current version %u.%u\n", ++ CY8C3245R1_FW_REV_MAJ, CY8C3245R1_FW_REV_MIN, major_revision, ++ minor_revision); ++ err = -ENODEV; ++ goto exit_free; ++ } ++ ++ /* Register sysfs hooks */ ++ data->attrs.attrs = cy8c3245r1_attr; ++ if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) ++ goto exit_free; ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ err = PTR_ERR(data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ init_completion(&data->auto_update_stop); ++ data->auto_update = kthread_run(cy8c3245r1_update_thread, client, ++ dev_name(data->hwmon_dev)); ++ if (IS_ERR(data->auto_update)) { ++ err = PTR_ERR(data->auto_update); ++ goto exit_unregister; ++ } ++ ++ return 0; ++ ++exit_unregister: ++ hwmon_device_unregister(data->hwmon_dev); ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &data->attrs); ++exit_free: ++ kfree(data); ++exit: ++ return err; ++} ++ ++static int cy8c3245r1_remove(struct i2c_client *client) ++{ ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ ++ kthread_stop(data->auto_update); ++ wait_for_completion(&data->auto_update_stop); ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &data->attrs); ++ kfree(data); ++ return 0; ++} ++ ++static int __init cy8c3245r1_init(void) ++{ ++ return i2c_add_driver(&cy8c3245r1_driver); ++} ++ ++static void __exit cy8c3245r1_exit(void) ++{ ++ i2c_del_driver(&cy8c3245r1_driver); ++} ++ ++MODULE_AUTHOR("Shrijeet Mukherjee "); ++MODULE_AUTHOR("Vidya Ravipati "); ++MODULE_DESCRIPTION("CY8C3245R1 driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(cy8c3245r1_init); ++module_exit(cy8c3245r1_exit); +diff --git a/drivers/hwmon/cy8cxx.c b/drivers/hwmon/cy8cxx.c +new file mode 100644 +index 0000000..3edfbe7 +--- /dev/null ++++ b/drivers/hwmon/cy8cxx.c +@@ -0,0 +1,1084 @@ ++/* ++ * A hwmon driver for the Cypress Semiconductor C3245 ++ * Copyright (C) 2013 Cumulus Networks ++ * ++ * Author: Shrijeet Mukherjee ++ * ++ * Based on the adt7470 driver ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Addresses to scan */ ++static const unsigned short normal_i2c[] = { 0x2E, I2C_CLIENT_END }; ++ ++/* CY8C3XX registers */ ++#define CY8C3XX_REG_BASE_ADDR 0x00 ++#define CY8C3XX_REG_DEV_ID 0x04 ++#define CY8C3XX_REG_COMPANY_ID 0x05 ++#define CY8C3XX_REG_FW_REV_MAJ 0x06 ++#define CY8C3XX_REG_FW_REV_MIN 0x07 ++#define CY8C3XX_REG_RESET 0x08 ++ ++/* ++ * Fan PWM / RPM Profile control registers ++ * ++ * These registers consist of two-bytes each ++ */ ++#define CY8C3XX_REG_FAN_PROFILE_BASE_ADDR 0x10 ++#define CY8C3XX_REG_FAN_PROFILE(x) (CY8C3XX_REG_FAN_PROFILE_BASE_ADDR + ((x) * 2)) ++enum { ++ CY8C3XX_FAN_PROFILE_LOW_DUTY = 0, ++ CY8C3XX_FAN_PROFILE_LOW_RPM, ++ CY8C3XX_FAN_PROFILE_HIGH_DUTY, ++ CY8C3XX_FAN_PROFILE_HIGH_RPM, ++ CY8C3XX_FAN_PROFILE_SPEED_0_DUTY, ++ CY8C3XX_FAN_PROFILE_SPEED_100_DUTY, ++ CY8C3XX_FAN_PROFILE_MAX ++}; ++ ++/* skipping over regs to set */ ++ ++#define CY8C3XX_REG_TEMP_BASE_ADDR 0x30 ++ ++#define CY8C3XX_REG_FAN_BASE_ADDR 0x80 ++#define CY8C3XX_REG_FAN_TARGET_BASE_ADDR 0xA0 ++ ++#define CY8C3XX_REG_PWM_BASE_ADDR 0x60 ++ ++#define CY8C3XX_REG_PWM_MAX_BASE_ADDR 0x38 ++ ++#define CY8C3XX_REG_TEMP_LIMITS_BASE_ADDR 0x30 ++#define CY8C3XX_REG_TEMP_LIMITS_MAX_ADDR 0x40 ++ ++#define CY8C3XX_REG_FAN_MAX_BASE_ADDR 0x16 ++ ++#define CY8C3XX_REG_PWM_CFG_BASE_ADDR 0x55 ++ ++#define CY8C3XX_TEMP_COUNT 5 ++#define CY8C3XX_TEMP_REG(x) (CY8C3XX_REG_TEMP_BASE_ADDR + (x)) ++#define CY8C3XX_TEMP_MAX_REG(x) (CY8C3XX_REG_TEMP_LIMITS_MAX_ADDR + (x)) ++ ++#define CY8C3XX_FAN_COUNT 8 ++#define CY8C3XX_REG_FAN(x) (CY8C3XX_REG_FAN_BASE_ADDR + ((x) * 2)) ++ ++#define CY8C3XX_REG_FAN_MIN(x) (CY8C3XX_REG_FAN_MIN_BASE_ADDR + ((x) * 2)) ++#define CY8C3XX_REG_FAN_MAX(x) (CY8C3XX_REG_FAN_MAX_BASE_ADDR) ++#define CY8C3XX_REG_FAN_TARGET(x) (CY8C3XX_REG_FAN_TARGET_BASE_ADDR + \ ++ ((x) * 2)) ++ ++#define CY8C3XX_PWM_COUNT 8 ++#define CY8C3XX_REG_PWM(x) (CY8C3XX_REG_PWM_BASE_ADDR + ((x) * 2)) ++ ++#define CY8C3XX_COMPANY_ID 0xCC ++#define CY8C3XX_DEV_ID 0x02 ++#define CY8C3XX_FW_REV_MAJ 0x01 ++ ++/* "all temps" according to hwmon sysfs interface spec */ ++#define CY8C3XX_PWM_ALL_TEMPS 0x3FF ++ ++/* How often do we reread sensors values? (In jiffies) */ ++#define SENSOR_REFRESH_INTERVAL (5 * HZ) ++ ++/* How often do we reread sensor limit values? (In jiffies) */ ++#define LIMIT_REFRESH_INTERVAL (60 * HZ) ++ ++/* Wait at least 200ms per sensor for 10 sensors */ ++#define TEMP_COLLECTION_TIME 2000 ++ ++/* auto update thing won't fire more than every 2s */ ++#define AUTO_UPDATE_INTERVAL 2000 ++ ++/* datasheet says to divide this number by the fan reading to get fan rpm */ ++#define FAN_PERIOD_INVALID 65535 ++#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) ++ ++struct cy8c3xx_data { ++ struct device *hwmon_dev; ++ struct attribute_group attrs; ++ struct mutex lock; ++ char sensors_valid; ++ char limits_valid; ++ unsigned long sensors_last_updated; /* In jiffies */ ++ unsigned long limits_last_updated; /* In jiffies */ ++ ++ int num_temp_sensors; /* -1 = probe */ ++ int temperatures_probed; ++ ++ s8 temp[CY8C3XX_TEMP_COUNT]; ++ s8 temp_max[CY8C3XX_TEMP_COUNT]; ++ u16 fan[CY8C3XX_FAN_COUNT]; ++ u16 fan_max[CY8C3XX_FAN_COUNT]; ++ u16 fan_min[CY8C3XX_FAN_COUNT]; ++ u16 fan_tgt[CY8C3XX_FAN_COUNT]; ++ u16 fan_profile[CY8C3XX_FAN_PROFILE_MAX]; ++ u8 fan_alarm; ++ u8 temp_alarm; ++ u8 force_pwm_max; ++ u8 pwm[CY8C3XX_PWM_COUNT]; ++ u8 pwm_automatic; ++ struct task_struct *auto_update; ++ struct completion auto_update_stop; ++ unsigned int auto_update_interval; ++}; ++ ++static int cy8c3xx_probe(struct i2c_client *client, ++ const struct i2c_device_id *id); ++static int cy8c3xx_detect(struct i2c_client *client, ++ struct i2c_board_info *info); ++static int cy8c3xx_remove(struct i2c_client *client); ++ ++static const struct i2c_device_id cy8c3xx_id[] = { ++ { "CY8C3245", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, cy8c3xx_id); ++ ++static struct i2c_driver cy8c3xx_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "cy8c3xx", ++ }, ++ .probe = cy8c3xx_probe, ++ .remove = cy8c3xx_remove, ++ .id_table = cy8c3xx_id, ++ .detect = cy8c3xx_detect, ++ .address_list = normal_i2c, ++}; ++ ++/* ++ * 16-bit registers on the CY8C3XX are high-byte first. ++ */ ++static inline int cy8c3xx_read_word_data(struct i2c_client *client, u8 reg) ++{ ++ s32 rc; ++ u16 val; ++ ++ /* read high byte */ ++ rc = i2c_smbus_read_byte_data(client, reg); ++ if (rc < 0) { ++ dev_warn(&client->dev, "i2c read failed: 0x%02x, errno %d\n", ++ reg, -rc); ++ return rc; ++ } ++ val = ((u16)rc & 0xFF) << 8; ++ ++ /* read low byte */ ++ rc = i2c_smbus_read_byte_data(client, reg + 1); ++ if (rc < 0) { ++ dev_warn(&client->dev, "i2c read failed: 0x%02x, errno %d\n", ++ reg + 1, -rc); ++ return rc; ++ } ++ val |= (u16)rc & 0xFF; ++ ++ return val; ++} ++ ++static inline int cy8c3xx_write_word_data(struct i2c_client *client, ++ u8 reg, ++ u16 value) ++{ ++ s32 rc; ++ ++ /* write high byte */ ++ rc = i2c_smbus_write_byte_data(client, reg, value >> 8); ++ if (rc < 0) { ++ dev_warn(&client->dev, ++ "i2c write failed: 0x%02x: 0x%02x, errno %d\n", ++ reg, value >> 8, -rc); ++ return rc; ++ } ++ ++ /* write low byte */ ++ rc = i2c_smbus_write_byte_data(client, reg + 1, value & 0xFF); ++ if (rc < 0) { ++ dev_warn(&client->dev, ++ "i2c write failed: 0x%02x: 0x%02x, errno %d\n", ++ reg + 1, value & 0xFF, -rc); ++ return rc; ++ } ++ ++ return rc; ++} ++ ++/* Probe for temperature sensors. Assumes lock is held */ ++static int cy8c3xx_read_temperatures(struct i2c_client *client, ++ struct cy8c3xx_data *data) ++{ ++ int i; ++ ++ /* Only count fans if we have to */ ++ if (data->num_temp_sensors >= 0) ++ return 0; ++ ++ for (i = 0; i < CY8C3XX_TEMP_COUNT; i++) { ++ data->temp[i] = i2c_smbus_read_byte_data(client, ++ CY8C3XX_TEMP_REG(i)); ++ if (data->temp[i]) ++ data->num_temp_sensors = i + 1; ++ } ++ data->temperatures_probed = 1; ++ return 0; ++} ++ ++static int cy8c3xx_update_thread(void *p) ++{ ++ struct i2c_client *client = p; ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ ++ while (!kthread_should_stop()) { ++ mutex_lock(&data->lock); ++ cy8c3xx_read_temperatures(client, data); ++ mutex_unlock(&data->lock); ++ if (kthread_should_stop()) ++ break; ++ msleep_interruptible(data->auto_update_interval); ++ } ++ ++ complete_all(&data->auto_update_stop); ++ return 0; ++} ++ ++static struct cy8c3xx_data *cy8c3xx_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ unsigned long local_jiffies = jiffies; ++ int i; ++ int need_sensors = 1; ++ int need_limits = 1; ++ ++ /* ++ * Figure out if we need to update the shadow registers. ++ * Lockless means that we may occasionally report out of ++ * date data. ++ */ ++ if (time_before(local_jiffies, data->sensors_last_updated + ++ SENSOR_REFRESH_INTERVAL) && ++ data->sensors_valid) ++ need_sensors = 0; ++ ++ if (time_before(local_jiffies, data->limits_last_updated + ++ LIMIT_REFRESH_INTERVAL) && ++ data->limits_valid) ++ need_limits = 0; ++ ++ if (!need_sensors && !need_limits) ++ return data; ++ ++ mutex_lock(&data->lock); ++ if (!need_sensors) ++ goto no_sensor_update; ++ ++ if (!data->temperatures_probed) ++ cy8c3xx_read_temperatures(client, data); ++ else ++ for (i = 0; i < CY8C3XX_TEMP_COUNT; i++) ++ data->temp[i] = i2c_smbus_read_byte_data(client, ++ CY8C3XX_TEMP_REG(i)); ++ ++ for (i = 0; i < CY8C3XX_FAN_COUNT; i++) { ++ data->fan[i] = cy8c3xx_read_word_data(client, ++ CY8C3XX_REG_FAN(i)); ++ } ++ ++ for (i = 0; i < CY8C3XX_PWM_COUNT; i++) { ++ data->pwm[i] = i2c_smbus_read_byte_data(client, ++ CY8C3XX_REG_PWM(i)); ++ } ++ ++ data->sensors_last_updated = local_jiffies; ++ data->sensors_valid = 1; ++ ++no_sensor_update: ++ if (!need_limits) ++ goto out; ++ ++ for (i = 0; i < CY8C3XX_TEMP_COUNT; i++) { ++ data->temp_max[i] = i2c_smbus_read_byte_data(client, ++ CY8C3XX_TEMP_MAX_REG(i)); ++ } ++ ++ for (i = 0; i < CY8C3XX_FAN_COUNT; i++) { ++ data->fan_max[i] = cy8c3xx_read_word_data(client, ++ CY8C3XX_REG_FAN_MAX(i)); ++ data->fan_tgt[i] = cy8c3xx_read_word_data(client, ++ CY8C3XX_REG_FAN_TARGET(i)); ++ } ++ ++ for (i = 0; i < CY8C3XX_FAN_PROFILE_MAX; i++) { ++ data->fan_profile[i] = cy8c3xx_read_word_data(client, ++ CY8C3XX_REG_FAN_PROFILE(i)); ++ } ++ ++ data->limits_last_updated = local_jiffies; ++ data->limits_valid = 1; ++ ++out: ++ mutex_unlock(&data->lock); ++ return data; ++} ++ ++static ssize_t show_auto_update_interval(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ return sprintf(buf, "%d\n", data->auto_update_interval); ++} ++ ++static ssize_t set_auto_update_interval(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = SENSORS_LIMIT(temp, 0, 60000); ++ ++ mutex_lock(&data->lock); ++ data->auto_update_interval = temp; ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_num_temp_sensors(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ return sprintf(buf, "%d\n", data->num_temp_sensors); ++} ++ ++static ssize_t set_num_temp_sensors(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = SENSORS_LIMIT(temp, -1, 10); ++ ++ mutex_lock(&data->lock); ++ data->num_temp_sensors = temp; ++ if (temp < 0) ++ data->temperatures_probed = 0; ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_temp_max(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ return sprintf(buf, "%d\n", 1000 * data->temp_max[attr->index]); ++} ++ ++static ssize_t set_temp_max(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = DIV_ROUND_CLOSEST(temp, 1000); ++ temp = SENSORS_LIMIT(temp, -128, 127); ++ ++ mutex_lock(&data->lock); ++ data->temp_max[attr->index] = temp; ++ i2c_smbus_write_byte_data(client, CY8C3XX_TEMP_MAX_REG(attr->index), ++ temp); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ return sprintf(buf, "%d\n", 1000 * data->temp[attr->index]); ++} ++ ++static ssize_t show_fan_max(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ if (FAN_DATA_VALID(data->fan_max[attr->index])) ++ return sprintf(buf, "%d\n", ++ data->fan_max[attr->index]); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t set_fan_max(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long rpm; ++ ++ if (strict_strtol(buf, 10, &rpm) || !rpm) ++ return -EINVAL; ++ ++ rpm = SENSORS_LIMIT(rpm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_max[attr->index] = rpm; ++ cy8c3xx_write_word_data(client, CY8C3XX_REG_FAN_MAX(attr->index), rpm); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++/* ++ * fan_min is a pure software concept, not implemented by hardware. ++ * It is used to compute the alarm status. ++ */ ++static ssize_t show_fan_min(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ return sprintf(buf, "%d\n", data->fan_min[attr->index]); ++} ++ ++static ssize_t set_fan_min(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long rpm; ++ ++ if (strict_strtol(buf, 10, &rpm) || !rpm) ++ return -EINVAL; ++ ++ rpm = SENSORS_LIMIT(rpm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_min[attr->index] = rpm; ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_fan_target(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ if (FAN_DATA_VALID(data->fan_tgt[attr->index])) ++ return sprintf(buf, "%d\n", ++ data->fan_tgt[attr->index]); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t set_fan_target(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long rpm; ++ ++ if (strict_strtol(buf, 10, &rpm) || !rpm) ++ return -EINVAL; ++ ++ rpm = SENSORS_LIMIT(rpm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_tgt[attr->index] = rpm; ++ cy8c3xx_write_word_data(client, CY8C3XX_REG_FAN_TARGET(attr->index), rpm); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++/* ++ * Show Fan Profile Settings ++ */ ++static ssize_t show_fan_profile(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ return sprintf(buf, "%u\n", ++ data->fan_profile[attr->index]); ++} ++ ++/* ++ * Set Fan Profile Settings ++ */ ++static ssize_t set_fan_profile(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long parm; ++ ++ if (strict_strtoul(buf, 10, &parm)) ++ return -EINVAL; ++ ++ parm = SENSORS_LIMIT(parm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_profile[attr->index] = parm; ++ cy8c3xx_write_word_data(client, CY8C3XX_REG_FAN_PROFILE(attr->index), parm); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ if (FAN_DATA_VALID(data->fan[attr->index])) ++ return sprintf(buf, "%d\n", data->fan[attr->index]); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ return sprintf(buf, "%d\n", data->pwm[attr->index]); ++} ++ ++static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = SENSORS_LIMIT(temp, 0, 255); ++ ++ mutex_lock(&data->lock); ++ data->pwm[attr->index] = temp; ++ i2c_smbus_write_byte_data(client, CY8C3XX_REG_PWM(attr->index), temp); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_fan_alarm_mask(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ int i; ++ u32 alarm_mask = 0; ++ ++ for (i = 0; i < CY8C3XX_FAN_COUNT; i++) ++ if ((data->fan[i] < data->fan_min[i]) || ++ (data->fan[i] >= data->fan_max[i])) ++ alarm_mask |= 0x1 << i; ++ ++ return sprintf(buf, "%x\n", alarm_mask); ++} ++ ++static ssize_t show_temp_alarm_mask(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ int i; ++ u32 alarm_mask = 0; ++ ++ for (i = 0; i < CY8C3XX_TEMP_COUNT; i++) ++ if (data->temp[i] >= data->temp_max[i]) ++ alarm_mask |= 0x1 << i; ++ ++ return sprintf(buf, "%x\n", alarm_mask); ++} ++ ++static ssize_t show_fan_alarm(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ if ((data->fan[attr->index] < data->fan_min[attr->index]) || ++ (data->fan[attr->index] >= data->fan_max[attr->index])) ++ return sprintf(buf, "1\n"); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t show_temp_alarm(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ if (data->temp[attr->index] >= data->temp_max[attr->index]) ++ return sprintf(buf, "1\n"); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t set_pwm_auto(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ if (!(temp > 0 && temp < 3)) ++ return -EINVAL; ++ ++ mutex_lock(&data->lock); ++ data->pwm_automatic = temp; ++ i2c_smbus_write_byte_data(client, CY8C3XX_REG_PWM_CFG_BASE_ADDR, temp); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_pwm_auto(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ return sprintf(buf, "%d\n", data->pwm_automatic); ++} ++ ++#define CY8C3XX_REG_MIN 0x00 ++#define CY8C3XX_REG_MAX 0xe0 ++ ++static ssize_t show_debug(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ int len = 0, i, j; ++ u8 val; ++ for (i = 0; i < (CY8C3XX_REG_MAX - CY8C3XX_REG_MIN) / 16; i++) { ++ len += sprintf(buf+len, "0x%02x: ", CY8C3XX_REG_MIN + (i * 16)); ++ for (j = 0; j < 16; j++) { ++ val = i2c_smbus_read_byte_data(client, CY8C3XX_REG_MIN + (i * 16) + j); ++ len += sprintf(buf+len, "%02x ", val); ++ } ++ len += sprintf(buf+len, "\n"); ++ } ++ return len; ++} ++ ++static DEVICE_ATTR(fan_alarm_mask, S_IRUGO, show_fan_alarm_mask, NULL); ++static DEVICE_ATTR(temp_alarm_mask, S_IRUGO, show_temp_alarm_mask, NULL); ++static DEVICE_ATTR(num_temp_sensors, S_IWUSR | S_IRUGO, show_num_temp_sensors, ++ set_num_temp_sensors); ++static DEVICE_ATTR(auto_update_interval, S_IWUSR | S_IRUGO, ++ show_auto_update_interval, set_auto_update_interval); ++ ++static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 0); ++static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 1); ++static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 2); ++static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 3); ++static SENSOR_DEVICE_ATTR(temp5_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 4); ++ ++static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); ++static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); ++static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); ++static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); ++static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4); ++ ++static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0); ++static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1); ++static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2); ++static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_temp_alarm, NULL, 3); ++static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO, show_temp_alarm, NULL, 4); ++ ++static SENSOR_DEVICE_ATTR(fan1_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 0); ++static SENSOR_DEVICE_ATTR(fan2_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 1); ++static SENSOR_DEVICE_ATTR(fan3_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 2); ++static SENSOR_DEVICE_ATTR(fan4_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 3); ++static SENSOR_DEVICE_ATTR(fan5_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 4); ++static SENSOR_DEVICE_ATTR(fan6_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 5); ++static SENSOR_DEVICE_ATTR(fan7_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 6); ++static SENSOR_DEVICE_ATTR(fan8_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 7); ++ ++static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 0); ++static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 1); ++static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 2); ++static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 3); ++static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 4); ++static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 5); ++static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 6); ++static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 7); ++ ++static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 0); ++static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 1); ++static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 2); ++static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 3); ++static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 4); ++static SENSOR_DEVICE_ATTR(fan6_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 5); ++static SENSOR_DEVICE_ATTR(fan7_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 6); ++static SENSOR_DEVICE_ATTR(fan8_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 7); ++ ++#define FAN_PROFILE_ATTR(_name, _index) \ ++ SENSOR_DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \ ++ show_fan_profile, set_fan_profile, _index) ++ ++static FAN_PROFILE_ATTR(fan_low_duty, CY8C3XX_FAN_PROFILE_LOW_DUTY); ++static FAN_PROFILE_ATTR(fan_low_rpm, CY8C3XX_FAN_PROFILE_LOW_RPM); ++static FAN_PROFILE_ATTR(fan_high_duty, CY8C3XX_FAN_PROFILE_HIGH_DUTY); ++static FAN_PROFILE_ATTR(fan_high_rpm, CY8C3XX_FAN_PROFILE_HIGH_RPM); ++static FAN_PROFILE_ATTR(fan_speed_0_duty, CY8C3XX_FAN_PROFILE_SPEED_0_DUTY); ++static FAN_PROFILE_ATTR(fan_speed_100_duty,CY8C3XX_FAN_PROFILE_SPEED_100_DUTY); ++ ++static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); ++static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); ++static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); ++static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); ++static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4); ++static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5); ++static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6); ++static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7); ++ ++static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0); ++static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1); ++static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2); ++static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3); ++static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5); ++static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6); ++static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7); ++ ++static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); ++static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); ++static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); ++static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); ++static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 4); ++static SENSOR_DEVICE_ATTR(pwm6, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 5); ++static SENSOR_DEVICE_ATTR(pwm7, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 6); ++static SENSOR_DEVICE_ATTR(pwm8, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 7); ++ ++static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm6_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm7_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm8_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++ ++static SENSOR_DEVICE_ATTR(debug, S_IRUGO, show_debug, NULL, 0); ++ ++static struct attribute *cy8c3xx_attr[] = ++{ ++ &dev_attr_fan_alarm_mask.attr, ++ &dev_attr_temp_alarm_mask.attr, ++ &dev_attr_num_temp_sensors.attr, ++ &dev_attr_auto_update_interval.attr, ++ &sensor_dev_attr_temp1_max.dev_attr.attr, ++ &sensor_dev_attr_temp2_max.dev_attr.attr, ++ &sensor_dev_attr_temp3_max.dev_attr.attr, ++ &sensor_dev_attr_temp4_max.dev_attr.attr, ++ &sensor_dev_attr_temp5_max.dev_attr.attr, ++ &sensor_dev_attr_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_temp2_input.dev_attr.attr, ++ &sensor_dev_attr_temp3_input.dev_attr.attr, ++ &sensor_dev_attr_temp4_input.dev_attr.attr, ++ &sensor_dev_attr_temp5_input.dev_attr.attr, ++ &sensor_dev_attr_temp1_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp2_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp3_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp4_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp5_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan1_max.dev_attr.attr, ++ &sensor_dev_attr_fan2_max.dev_attr.attr, ++ &sensor_dev_attr_fan3_max.dev_attr.attr, ++ &sensor_dev_attr_fan4_max.dev_attr.attr, ++ &sensor_dev_attr_fan5_max.dev_attr.attr, ++ &sensor_dev_attr_fan6_max.dev_attr.attr, ++ &sensor_dev_attr_fan7_max.dev_attr.attr, ++ &sensor_dev_attr_fan8_max.dev_attr.attr, ++ &sensor_dev_attr_fan1_min.dev_attr.attr, ++ &sensor_dev_attr_fan2_min.dev_attr.attr, ++ &sensor_dev_attr_fan3_min.dev_attr.attr, ++ &sensor_dev_attr_fan4_min.dev_attr.attr, ++ &sensor_dev_attr_fan5_min.dev_attr.attr, ++ &sensor_dev_attr_fan6_min.dev_attr.attr, ++ &sensor_dev_attr_fan7_min.dev_attr.attr, ++ &sensor_dev_attr_fan8_min.dev_attr.attr, ++ &sensor_dev_attr_fan1_target.dev_attr.attr, ++ &sensor_dev_attr_fan2_target.dev_attr.attr, ++ &sensor_dev_attr_fan3_target.dev_attr.attr, ++ &sensor_dev_attr_fan4_target.dev_attr.attr, ++ &sensor_dev_attr_fan5_target.dev_attr.attr, ++ &sensor_dev_attr_fan6_target.dev_attr.attr, ++ &sensor_dev_attr_fan7_target.dev_attr.attr, ++ &sensor_dev_attr_fan8_target.dev_attr.attr, ++ &sensor_dev_attr_fan1_input.dev_attr.attr, ++ &sensor_dev_attr_fan2_input.dev_attr.attr, ++ &sensor_dev_attr_fan3_input.dev_attr.attr, ++ &sensor_dev_attr_fan4_input.dev_attr.attr, ++ &sensor_dev_attr_fan5_input.dev_attr.attr, ++ &sensor_dev_attr_fan6_input.dev_attr.attr, ++ &sensor_dev_attr_fan7_input.dev_attr.attr, ++ &sensor_dev_attr_fan8_input.dev_attr.attr, ++ &sensor_dev_attr_fan1_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan2_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan3_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan4_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan5_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan6_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan7_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan8_alarm.dev_attr.attr, ++ &sensor_dev_attr_pwm1.dev_attr.attr, ++ &sensor_dev_attr_pwm2.dev_attr.attr, ++ &sensor_dev_attr_pwm3.dev_attr.attr, ++ &sensor_dev_attr_pwm4.dev_attr.attr, ++ &sensor_dev_attr_pwm5.dev_attr.attr, ++ &sensor_dev_attr_pwm6.dev_attr.attr, ++ &sensor_dev_attr_pwm7.dev_attr.attr, ++ &sensor_dev_attr_pwm8.dev_attr.attr, ++ &sensor_dev_attr_pwm1_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm2_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm3_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm4_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm5_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm6_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm7_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm8_enable.dev_attr.attr, ++ &sensor_dev_attr_fan_low_duty.dev_attr.attr, ++ &sensor_dev_attr_fan_low_rpm.dev_attr.attr, ++ &sensor_dev_attr_fan_high_duty.dev_attr.attr, ++ &sensor_dev_attr_fan_high_rpm.dev_attr.attr, ++ &sensor_dev_attr_fan_speed_0_duty.dev_attr.attr, ++ &sensor_dev_attr_fan_speed_100_duty.dev_attr.attr, ++ &sensor_dev_attr_debug.dev_attr.attr, ++ NULL ++}; ++ ++/* Return 0 if detection is successful, -ENODEV otherwise */ ++static int cy8c3xx_detect(struct i2c_client *client, ++ struct i2c_board_info *info) ++{ ++ struct i2c_adapter *adapter = client->adapter; ++ int vendor, device, revision; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) ++ return -ENODEV; ++ ++ vendor = i2c_smbus_read_byte_data(client, CY8C3XX_REG_COMPANY_ID); ++ printk(KERN_INFO "vendor = %u\n", vendor); ++ if (vendor != CY8C3XX_COMPANY_ID) ++ return -ENODEV; ++ ++ device = i2c_smbus_read_byte_data(client, CY8C3XX_REG_DEV_ID); ++ printk(KERN_INFO "device = %u\n", device); ++ if (device != CY8C3XX_DEV_ID) ++ return -ENODEV; ++ ++ revision = i2c_smbus_read_byte_data(client, CY8C3XX_REG_FW_REV_MAJ); ++ printk(KERN_INFO "rev = %u\n", revision); ++ if (revision != CY8C3XX_FW_REV_MAJ) ++ return -ENODEV; ++ ++ strlcpy(info->type, "cy8c3xx", I2C_NAME_SIZE); ++ ++ printk(KERN_INFO "cy8c3xx detected\n"); ++ return 0; ++} ++ ++static int cy8c3xx_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct cy8c3xx_data *data; ++ int err; ++ ++ data = kzalloc(sizeof(struct cy8c3xx_data), GFP_KERNEL); ++ if (!data) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ data->num_temp_sensors = -1; ++ data->auto_update_interval = AUTO_UPDATE_INTERVAL; ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->lock); ++ ++ dev_info(&client->dev, "%s chip found\n", client->name); ++ ++ /* Register sysfs hooks */ ++ data->attrs.attrs = cy8c3xx_attr; ++ if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) ++ goto exit_free; ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ err = PTR_ERR(data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ init_completion(&data->auto_update_stop); ++ data->auto_update = kthread_run(cy8c3xx_update_thread, client, ++ dev_name(data->hwmon_dev)); ++ if (IS_ERR(data->auto_update)) { ++ err = PTR_ERR(data->auto_update); ++ goto exit_unregister; ++ } ++ ++ return 0; ++ ++exit_unregister: ++ hwmon_device_unregister(data->hwmon_dev); ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &data->attrs); ++exit_free: ++ kfree(data); ++exit: ++ return err; ++} ++ ++static int cy8c3xx_remove(struct i2c_client *client) ++{ ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ ++ kthread_stop(data->auto_update); ++ wait_for_completion(&data->auto_update_stop); ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &data->attrs); ++ kfree(data); ++ return 0; ++} ++ ++static int __init cy8c3xx_init(void) ++{ ++ return i2c_add_driver(&cy8c3xx_driver); ++} ++ ++static void __exit cy8c3xx_exit(void) ++{ ++ i2c_del_driver(&cy8c3xx_driver); ++} ++ ++MODULE_AUTHOR("Shrijeet Mukherjee "); ++MODULE_DESCRIPTION("CY8C3XX driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(cy8c3xx_init); ++module_exit(cy8c3xx_exit); +diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c +new file mode 100644 +index 0000000..62f88e0 +--- /dev/null ++++ b/drivers/hwmon/emc2305.c +@@ -0,0 +1,875 @@ ++/* ++ * emc2305.c - hwmon driver for SMSC EMC2305 fan controller ++ * (C) Copyright 2013 ++ * Reinhard Pfau, Guntermann & Drunck GmbH ++ * ++ * Based on emc2103 driver by SMSC. ++ * ++ * Datasheet available at: ++ * http://www.smsc.com/Downloads/SMSC/Downloads_Public/Data_Sheets/2305.pdf ++ * ++ * Also supports the EMC2303 fan controller which has the same functionality ++ * and register layout as EMC2305, but supports only up to 3 fans instead of 5. ++ * ++ * Also supports EMC2302 (up to 2 fans) and EMC2301 (1 fan) fan controller. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++/* ++ * TODO / IDEAS: ++ * - expose more of the configuration and features ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * Addresses scanned. ++ * Listed in the same order as they appear in the EMC2305, EMC2303 data sheets. ++ * ++ * Note: these are the I2C adresses which are possible for EMC2305 and EMC2303 ++ * chips. ++ * The EMC2302 supports only 0x2e (EMC2302-1) and 0x2f (EMC2302-2). ++ * The EMC2301 supports only 0x2f. ++ */ ++static const unsigned short i2c_adresses[] = { ++ 0x2E, ++ 0x2F, ++ 0x2C, ++ 0x2D, ++ 0x4C, ++ 0x4D, ++ I2C_CLIENT_END ++}; ++ ++/* ++ * global registers ++ */ ++enum { ++ REG_CONFIGURATION = 0x20, ++ REG_FAN_STATUS = 0x24, ++ REG_FAN_STALL_STATUS = 0x25, ++ REG_FAN_SPIN_STATUS = 0x26, ++ REG_DRIVE_FAIL_STATUS = 0x27, ++ REG_FAN_INTERRUPT_ENABLE = 0x29, ++ REG_PWM_POLARITY_CONFIG = 0x2a, ++ REG_PWM_OUTPUT_CONFIG = 0x2b, ++ REG_PWM_BASE_FREQ_1 = 0x2c, ++ REG_PWM_BASE_FREQ_2 = 0x2d, ++ REG_SOFTWARE_LOCK = 0xef, ++ REG_PRODUCT_FEATURES = 0xfc, ++ REG_PRODUCT_ID = 0xfd, ++ REG_MANUFACTURER_ID = 0xfe, ++ REG_REVISION = 0xff ++}; ++ ++/* ++ * fan specific registers ++ */ ++enum { ++ REG_FAN_SETTING = 0x30, ++ REG_PWM_DIVIDE = 0x31, ++ REG_FAN_CONFIGURATION_1 = 0x32, ++ REG_FAN_CONFIGURATION_2 = 0x33, ++ REG_GAIN = 0x35, ++ REG_FAN_SPIN_UP_CONFIG = 0x36, ++ REG_FAN_MAX_STEP = 0x37, ++ REG_FAN_MINIMUM_DRIVE = 0x38, ++ REG_FAN_VALID_TACH_COUNT = 0x39, ++ REG_FAN_DRIVE_FAIL_BAND_LOW = 0x3a, ++ REG_FAN_DRIVE_FAIL_BAND_HIGH = 0x3b, ++ REG_TACH_TARGET_LOW = 0x3c, ++ REG_TACH_TARGET_HIGH = 0x3d, ++ REG_TACH_READ_HIGH = 0x3e, ++ REG_TACH_READ_LOW = 0x3f, ++}; ++ ++#define SEL_FAN(fan, reg) (reg + fan * 0x10) ++ ++/* ++ * Factor by equations [2] and [3] from data sheet; valid for fans where the ++ * number of edges equals (poles * 2 + 1). ++ */ ++#define FAN_RPM_FACTOR 3932160 ++ ++ ++struct emc2305_fan_data { ++ bool enabled; ++ bool valid; ++ unsigned long last_updated; ++ bool rpm_control; ++ u8 multiplier; ++ u8 poles; ++ u16 target; ++ u16 tach; ++ u16 rpm_factor; ++ u8 pwm; ++}; ++ ++struct emc2305_data { ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ int fans; ++ struct emc2305_fan_data fan[5]; ++}; ++ ++static int read_u8_from_i2c(struct i2c_client *client, u8 i2c_reg, u8 *output) ++{ ++ int status = i2c_smbus_read_byte_data(client, i2c_reg); ++ if (status < 0) { ++ dev_warn(&client->dev, "reg 0x%02x, err %d\n", ++ i2c_reg, status); ++ } else { ++ *output = status; ++ } ++ return status; ++} ++ ++static void read_fan_from_i2c(struct i2c_client *client, u16 *output, ++ u8 hi_addr, u8 lo_addr) ++{ ++ u8 high_byte, lo_byte; ++ ++ if (read_u8_from_i2c(client, hi_addr, &high_byte) < 0) ++ return; ++ ++ if (read_u8_from_i2c(client, lo_addr, &lo_byte) < 0) ++ return; ++ ++ *output = ((u16)high_byte << 5) | (lo_byte >> 3); ++} ++ ++static void write_fan_target_to_i2c(struct i2c_client *client, int fan, ++ u16 new_target) ++{ ++ const u8 lo_reg = SEL_FAN(fan, REG_TACH_TARGET_LOW); ++ const u8 hi_reg = SEL_FAN(fan, REG_TACH_TARGET_HIGH); ++ u8 high_byte = (new_target & 0x1fe0) >> 5; ++ u8 low_byte = (new_target & 0x001f) << 3; ++ i2c_smbus_write_byte_data(client, lo_reg, low_byte); ++ i2c_smbus_write_byte_data(client, hi_reg, high_byte); ++} ++ ++static void read_fan_config_from_i2c(struct i2c_client *client, int fan) ++ ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ u8 conf1; ++ ++ if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_CONFIGURATION_1), ++ &conf1) < 0) ++ return; ++ ++ data->fan[fan].rpm_control = (conf1 & 0x80) != 0; ++ data->fan[fan].multiplier = 1 << ((conf1 & 0x60) >> 5); ++ data->fan[fan].poles = ((conf1 & 0x18) >> 3) + 1; ++} ++ ++static void read_fan_setting(struct i2c_client *client, int fan) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ u8 setting; ++ ++ if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_SETTING), ++ &setting) < 0) ++ return; ++ ++ data->fan[fan].pwm = setting; ++} ++ ++static void read_fan_data(struct i2c_client *client, int fan_idx) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ ++ read_fan_from_i2c(client, &data->fan[fan_idx].target, ++ SEL_FAN(fan_idx, REG_TACH_TARGET_HIGH), ++ SEL_FAN(fan_idx, REG_TACH_TARGET_LOW)); ++ read_fan_from_i2c(client, &data->fan[fan_idx].tach, ++ SEL_FAN(fan_idx, REG_TACH_READ_HIGH), ++ SEL_FAN(fan_idx, REG_TACH_READ_LOW)); ++} ++ ++static struct emc2305_fan_data * ++emc2305_update_fan(struct i2c_client *client, int fan_idx) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ struct emc2305_fan_data *fan_data = &data->fan[fan_idx]; ++ ++ mutex_lock(&data->update_lock); ++ ++ if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) ++ || !fan_data->valid) { ++ read_fan_config_from_i2c(client, fan_idx); ++ read_fan_data(client, fan_idx); ++ read_fan_setting(client, fan_idx); ++ fan_data->valid = true; ++ fan_data->last_updated = jiffies; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return fan_data; ++} ++ ++static struct emc2305_fan_data * ++emc2305_update_device_fan(struct device *dev, struct device_attribute *da) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int fan_idx = to_sensor_dev_attr(da)->index; ++ ++ return emc2305_update_fan(client, fan_idx); ++} ++ ++/* ++ * set/ config functions ++ */ ++ ++/* ++ * Note: we also update the fan target here, because its value is ++ * determined in part by the fan clock divider. This follows the principle ++ * of least surprise; the user doesn't expect the fan target to change just ++ * because the divider changed. ++ */ ++static int ++emc2305_set_fan_div(struct i2c_client *client, int fan_idx, long new_div) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); ++ const u8 reg_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); ++ int new_range_bits, old_div = 8 / fan->multiplier; ++ int status = 0; ++ ++ if (new_div == old_div) /* No change */ ++ return 0; ++ ++ switch (new_div) { ++ case 1: ++ new_range_bits = 3; ++ break; ++ case 2: ++ new_range_bits = 2; ++ break; ++ case 4: ++ new_range_bits = 1; ++ break; ++ case 8: ++ new_range_bits = 0; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ mutex_lock(&data->update_lock); ++ ++ status = i2c_smbus_read_byte_data(client, reg_conf1); ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg 0x%02x, err %d\n", ++ reg_conf1, status); ++ status = -EIO; ++ goto exit_unlock; ++ } ++ status &= 0x9F; ++ status |= (new_range_bits << 5); ++ status = i2c_smbus_write_byte_data(client, reg_conf1, status); ++ if (status < 0) { ++ status = -EIO; ++ goto exit_invalidate; ++ } ++ ++ fan->multiplier = 8 / new_div; ++ ++ /* update fan target if high byte is not disabled */ ++ if ((fan->target & 0x1fe0) != 0x1fe0) { ++ u16 new_target = (fan->target * old_div) / new_div; ++ fan->target = min_t(u16, new_target, 0x1fff); ++ write_fan_target_to_i2c(client, fan_idx, fan->target); ++ } ++ ++exit_invalidate: ++ /* invalidate fan data to force re-read from hardware */ ++ fan->valid = false; ++exit_unlock: ++ mutex_unlock(&data->update_lock); ++ return status; ++} ++ ++static int ++emc2305_set_fan_target(struct i2c_client *client, int fan_idx, long rpm_target) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); ++ ++ /* ++ * Datasheet states 16000 as maximum RPM target ++ * (table 2.2 and section 4.3) ++ */ ++ if ((rpm_target < 0) || (rpm_target > 16000)) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ ++ if (rpm_target == 0) ++ fan->target = 0x1fff; ++ else ++ fan->target = clamp_val( ++ (FAN_RPM_FACTOR * fan->multiplier) / rpm_target, ++ 0, 0x1fff); ++ ++ write_fan_target_to_i2c(client, fan_idx, fan->target); ++ ++ mutex_unlock(&data->update_lock); ++ return 0; ++} ++ ++static int ++emc2305_set_pwm_enable(struct i2c_client *client, int fan_idx, long enable) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); ++ const u8 reg_fan_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); ++ int status = 0; ++ u8 conf_reg; ++ ++ mutex_lock(&data->update_lock); ++ switch (enable) { ++ case 0: ++ fan->rpm_control = false; ++ break; ++ case 3: ++ fan->rpm_control = true; ++ break; ++ default: ++ status = -EINVAL; ++ goto exit_unlock; ++ } ++ ++ status = read_u8_from_i2c(client, reg_fan_conf1, &conf_reg); ++ if (status < 0) { ++ status = -EIO; ++ goto exit_unlock; ++ } ++ ++ if (fan->rpm_control) ++ conf_reg |= 0x80; ++ else ++ conf_reg &= ~0x80; ++ ++ status = i2c_smbus_write_byte_data(client, reg_fan_conf1, conf_reg); ++ if (status < 0) ++ status = -EIO; ++ ++exit_unlock: ++ mutex_unlock(&data->update_lock); ++ return status; ++} ++ ++static int ++emc2305_set_pwm(struct i2c_client *client, int fan_idx, long pwm) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); ++ const u8 reg_fan_setting = SEL_FAN(fan_idx, REG_FAN_SETTING); ++ int status = 0; ++ ++ /* ++ * Datasheet states 255 as maximum PWM ++ * (section 5.7) ++ */ ++ if ((pwm < 0) || (pwm > 255)) ++ return -EINVAL; ++ ++ fan->pwm = pwm; ++ ++ mutex_lock(&data->update_lock); ++ ++ status = i2c_smbus_write_byte_data(client, reg_fan_setting, fan->pwm); ++ ++ mutex_unlock(&data->update_lock); ++ return status; ++} ++/* ++ * sysfs callback functions ++ * ++ * Note: ++ * Naming of the funcs is modelled after the naming scheme described in ++ * Documentation/hwmon/sysfs-interface: ++ * ++ * For a sysfs file _ the functions are named like this: ++ * the show function: show__ ++ * the store function: set__ ++ * For read only (RO) attributes of course only the show func is required. ++ * ++ * This convention allows us to define the sysfs attributes by using macros. ++ */ ++ ++static ssize_t ++show_fan_input(struct device *dev, struct device_attribute *da, char *buf) ++{ ++ struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); ++ int rpm = 0; ++ if (fan->tach != 0) ++ rpm = (FAN_RPM_FACTOR * fan->multiplier) / fan->tach; ++ return sprintf(buf, "%d\n", rpm); ++} ++ ++static ssize_t ++show_fan_fault(struct device *dev, struct device_attribute *da, char *buf) ++{ ++ struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); ++ bool fault = ((fan->tach & 0x1fe0) == 0x1fe0); ++ return sprintf(buf, "%d\n", fault ? 1 : 0); ++} ++ ++static ssize_t ++show_fan_div(struct device *dev, struct device_attribute *da, char *buf) ++{ ++ struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); ++ int fan_div = 8 / fan->multiplier; ++ return sprintf(buf, "%d\n", fan_div); ++} ++ ++static ssize_t ++set_fan_div(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int fan_idx = to_sensor_dev_attr(da)->index; ++ long new_div; ++ int status; ++ ++ status = kstrtol(buf, 10, &new_div); ++ if (status < 0) ++ return -EINVAL; ++ ++ status = emc2305_set_fan_div(client, fan_idx, new_div); ++ if (status < 0) ++ return status; ++ ++ return count; ++} ++ ++static ssize_t ++show_fan_target(struct device *dev, struct device_attribute *da, char *buf) ++{ ++ struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); ++ int rpm = 0; ++ ++ /* high byte of 0xff indicates disabled so return 0 */ ++ if ((fan->target != 0) && ((fan->target & 0x1fe0) != 0x1fe0)) ++ rpm = (FAN_RPM_FACTOR * fan->multiplier) ++ / fan->target; ++ ++ return sprintf(buf, "%d\n", rpm); ++} ++ ++static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int fan_idx = to_sensor_dev_attr(da)->index; ++ long rpm_target; ++ int status; ++ ++ status = kstrtol(buf, 10, &rpm_target); ++ if (status < 0) ++ return -EINVAL; ++ ++ status = emc2305_set_fan_target(client, fan_idx, rpm_target); ++ if (status < 0) ++ return status; ++ ++ return count; ++} ++ ++static ssize_t ++show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf) ++{ ++ struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); ++ return sprintf(buf, "%d\n", fan->rpm_control ? 3 : 0); ++} ++ ++static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int fan_idx = to_sensor_dev_attr(da)->index; ++ long new_value; ++ int status; ++ ++ status = kstrtol(buf, 10, &new_value); ++ if (status < 0) ++ return -EINVAL; ++ status = emc2305_set_pwm_enable(client, fan_idx, new_value); ++ return count; ++} ++ ++static ssize_t show_pwm(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); ++ return sprintf(buf, "%d\n", fan->pwm); ++} ++ ++static ssize_t set_pwm(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int fan_idx = to_sensor_dev_attr(da)->index; ++ unsigned long val; ++ int ret; ++ int status; ++ ++ ret = kstrtoul(buf, 10, &val); ++ if (ret) ++ return ret; ++ if (val > 255) ++ return -EINVAL; ++ ++ status = emc2305_set_pwm(client, fan_idx, val); ++ return count; ++} ++ ++/* define a read only attribute */ ++#define EMC2305_ATTR_RO(_type, _item, _num) \ ++ SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO, \ ++ show_## _type ## _ ## _item, NULL, _num - 1) ++ ++/* define a read/write attribute */ ++#define EMC2305_ATTR_RW(_type, _item, _num) \ ++ SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO | S_IWUSR, \ ++ show_## _type ##_ ## _item, \ ++ set_## _type ## _ ## _item, _num - 1) ++ ++/* ++ * TODO: Ugly hack, but temporary as this whole logic needs ++ * to be rewritten as per standard HWMON sysfs registration ++ */ ++ ++/* define a read/write attribute */ ++#define EMC2305_ATTR_RW2(_type, _num) \ ++ SENSOR_ATTR(_type ## _num, S_IRUGO | S_IWUSR, \ ++ show_## _type, set_## _type, _num - 1) ++ ++/* defines the attributes for a single fan */ ++#define EMC2305_DEFINE_FAN_ATTRS(_num) \ ++ static const \ ++ struct sensor_device_attribute emc2305_attr_fan ## _num[] = { \ ++ EMC2305_ATTR_RO(fan, input, _num), \ ++ EMC2305_ATTR_RO(fan, fault, _num), \ ++ EMC2305_ATTR_RW(fan, div, _num), \ ++ EMC2305_ATTR_RW(fan, target, _num), \ ++ EMC2305_ATTR_RW(pwm, enable, _num), \ ++ EMC2305_ATTR_RW2(pwm, _num) \ ++ } ++ ++#define EMC2305_NUM_FAN_ATTRS ARRAY_SIZE(emc2305_attr_fan1) ++ ++/* common attributes for EMC2303 and EMC2305 */ ++static const struct sensor_device_attribute emc2305_attr_common[] = { ++}; ++ ++/* fan attributes for the single fans */ ++EMC2305_DEFINE_FAN_ATTRS(1); ++EMC2305_DEFINE_FAN_ATTRS(2); ++EMC2305_DEFINE_FAN_ATTRS(3); ++EMC2305_DEFINE_FAN_ATTRS(4); ++EMC2305_DEFINE_FAN_ATTRS(5); ++EMC2305_DEFINE_FAN_ATTRS(6); ++ ++/* fan attributes */ ++static const struct sensor_device_attribute *emc2305_fan_attrs[] = { ++ emc2305_attr_fan1, ++ emc2305_attr_fan2, ++ emc2305_attr_fan3, ++ emc2305_attr_fan4, ++ emc2305_attr_fan5, ++}; ++ ++/* ++ * driver interface ++ */ ++ ++static int emc2305_remove(struct i2c_client *client) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ int fan_idx, i; ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ ++ for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) ++ for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) ++ device_remove_file( ++ &client->dev, ++ &emc2305_fan_attrs[fan_idx][i].dev_attr); ++ ++ for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) ++ device_remove_file(&client->dev, ++ &emc2305_attr_common[i].dev_attr); ++ ++ kfree(data); ++ return 0; ++} ++ ++ ++#ifdef CONFIG_OF ++/* ++ * device tree support ++ */ ++ ++struct of_fan_attribute { ++ const char *name; ++ int (*set)(struct i2c_client*, int, long); ++}; ++ ++struct of_fan_attribute of_fan_attributes[] = { ++ {"fan-div", emc2305_set_fan_div}, ++ {"fan-target", emc2305_set_fan_target}, ++ {"pwm-enable", emc2305_set_pwm_enable}, ++ {NULL, NULL} ++}; ++ ++static int emc2305_config_of(struct i2c_client *client) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ struct device_node *node; ++ unsigned int fan_idx; ++ ++ if (!client->dev.of_node) ++ return -EINVAL; ++ if (!of_get_next_child(client->dev.of_node, NULL)) ++ return 0; ++ ++ for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) ++ data->fan[fan_idx].enabled = false; ++ ++ for_each_child_of_node(client->dev.of_node, node) { ++ const __be32 *property; ++ int len; ++ struct of_fan_attribute *attr; ++ ++ property = of_get_property(node, "reg", &len); ++ if (!property || len != sizeof(int)) { ++ dev_err(&client->dev, "invalid reg on %s\n", ++ node->full_name); ++ continue; ++ } ++ ++ fan_idx = be32_to_cpup(property); ++ if (fan_idx >= data->fans) { ++ dev_err(&client->dev, ++ "invalid fan index %d on %s\n", ++ fan_idx, node->full_name); ++ continue; ++ } ++ ++ data->fan[fan_idx].enabled = true; ++ ++ for (attr = of_fan_attributes; attr->name; ++attr) { ++ int status = 0; ++ long value; ++ property = of_get_property(node, attr->name, &len); ++ if (!property) ++ continue; ++ if (len != sizeof(int)) { ++ dev_err(&client->dev, "invalid %s on %s\n", ++ attr->name, node->full_name); ++ continue; ++ } ++ value = be32_to_cpup(property); ++ status = attr->set(client, fan_idx, value); ++ if (status == -EINVAL) { ++ dev_err(&client->dev, ++ "invalid value for %s on %s\n", ++ attr->name, node->full_name); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++#endif ++ ++static void emc2305_get_config(struct i2c_client *client) ++{ ++ int i; ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ ++ for (i = 0; i < data->fans; ++i) { ++ data->fan[i].enabled = true; ++ emc2305_update_fan(client, i); ++ } ++ ++#ifdef CONFIG_OF ++ emc2305_config_of(client); ++#endif ++ ++} ++ ++static int ++emc2305_probe(struct i2c_client *client, const struct i2c_device_id *id) ++{ ++ struct emc2305_data *data; ++ int status; ++ int i; ++ int fan_idx; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) ++ return -EIO; ++ ++ data = kzalloc(sizeof(struct emc2305_data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->update_lock); ++ ++ status = i2c_smbus_read_byte_data(client, REG_PRODUCT_ID); ++ switch (status) { ++ case 0x34: /* EMC2305 */ ++ data->fans = 5; ++ break; ++ case 0x35: /* EMC2303 */ ++ data->fans = 3; ++ break; ++ case 0x36: /* EMC2302 */ ++ data->fans = 2; ++ break; ++ case 0x37: /* EMC2301 */ ++ data->fans = 1; ++ break; ++ default: ++ if (status >= 0) ++ status = -EINVAL; ++ goto exit_free; ++ } ++ ++ emc2305_get_config(client); ++ ++ for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) { ++ status = device_create_file(&client->dev, ++ &emc2305_attr_common[i].dev_attr); ++ if (status) ++ goto exit_remove; ++ } ++ for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) ++ for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) { ++ if (!data->fan[fan_idx].enabled) ++ continue; ++ status = device_create_file( ++ &client->dev, ++ &emc2305_fan_attrs[fan_idx][i].dev_attr); ++ if (status) ++ goto exit_remove_fans; ++ } ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ status = PTR_ERR(data->hwmon_dev); ++ goto exit_remove_fans; ++ } ++ ++ dev_info(&client->dev, "%s: sensor '%s'\n", ++ dev_name(data->hwmon_dev), client->name); ++ ++ return 0; ++ ++exit_remove_fans: ++ for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) ++ for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) ++ device_remove_file( ++ &client->dev, ++ &emc2305_fan_attrs[fan_idx][i].dev_attr); ++ ++exit_remove: ++ for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) ++ device_remove_file(&client->dev, ++ &emc2305_attr_common[i].dev_attr); ++exit_free: ++ kfree(data); ++ return status; ++} ++ ++static const struct i2c_device_id emc2305_id[] = { ++ { "emc2305", 0 }, ++ { "emc2303", 0 }, ++ { "emc2302", 0 }, ++ { "emc2301", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, emc2305_id); ++ ++/* Return 0 if detection is successful, -ENODEV otherwise */ ++static int ++emc2305_detect(struct i2c_client *new_client, struct i2c_board_info *info) ++{ ++ struct i2c_adapter *adapter = new_client->adapter; ++ int manufacturer, product; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) ++ return -ENODEV; ++ ++ manufacturer = ++ i2c_smbus_read_byte_data(new_client, REG_MANUFACTURER_ID); ++ if (manufacturer != 0x5D) ++ return -ENODEV; ++ ++ product = i2c_smbus_read_byte_data(new_client, REG_PRODUCT_ID); ++ ++ switch (product) { ++ case 0x34: ++ strlcpy(info->type, "emc2305", I2C_NAME_SIZE); ++ break; ++ case 0x35: ++ strlcpy(info->type, "emc2303", I2C_NAME_SIZE); ++ break; ++ case 0x36: ++ strlcpy(info->type, "emc2302", I2C_NAME_SIZE); ++ break; ++ case 0x37: ++ strlcpy(info->type, "emc2301", I2C_NAME_SIZE); ++ break; ++ default: ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static struct i2c_driver emc2305_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "emc2305", ++ }, ++ .probe = emc2305_probe, ++ .remove = emc2305_remove, ++ .id_table = emc2305_id, ++ .detect = emc2305_detect, ++ .address_list = i2c_adresses, ++}; ++ ++module_i2c_driver(emc2305_driver); ++ ++MODULE_AUTHOR("Reinhard Pfau "); ++MODULE_DESCRIPTION("SMSC EMC2305 hwmon driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c +index 1ba7af2..3d7ee59 100644 +--- a/drivers/hwmon/it87.c ++++ b/drivers/hwmon/it87.c +@@ -17,6 +17,7 @@ + * IT8720F Super I/O chip w/LPC interface + * IT8721F Super I/O chip w/LPC interface + * IT8726F Super I/O chip w/LPC interface ++ * IT8728F Super I/O chip w/LPC interface + * IT8758E Super I/O chip w/LPC interface + * Sis950 A clone of the IT8705F + * +@@ -58,7 +59,7 @@ + + #define DRVNAME "it87" + +-enum chips { it87, it8712, it8716, it8718, it8720, it8721 }; ++enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728 }; + + static unsigned short force_id; + module_param(force_id, ushort, 0); +@@ -135,6 +136,7 @@ static inline void superio_exit(void) + #define IT8720F_DEVID 0x8720 + #define IT8721F_DEVID 0x8721 + #define IT8726F_DEVID 0x8726 ++#define IT8728F_DEVID 0x8728 + #define IT87_ACT_REG 0x30 + #define IT87_BASE_REG 0x60 + +@@ -274,11 +276,31 @@ struct it87_data { + s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ + }; + ++static inline int has_12mv_adc(const struct it87_data *data) ++{ ++ /* ++ * IT8721F and later have a 12 mV ADC, also with internal scaling ++ * on selected inputs. ++ */ ++ return data->type == it8721 ++ || data->type == it8728; ++} ++ ++static inline int has_newer_autopwm(const struct it87_data *data) ++{ ++ /* ++ * IT8721F and later have separate registers for the temperature ++ * mapping and the manual duty cycle. ++ */ ++ return data->type == it8721 ++ || data->type == it8728; ++} ++ + static u8 in_to_reg(const struct it87_data *data, int nr, long val) + { + long lsb; + +- if (data->type == it8721) { ++ if (has_12mv_adc(data)) { + if (data->in_scaled & (1 << nr)) + lsb = 24; + else +@@ -292,7 +314,7 @@ static u8 in_to_reg(const struct it87_data *data, int nr, long val) + + static int in_from_reg(const struct it87_data *data, int nr, int val) + { +- if (data->type == it8721) { ++ if (has_12mv_adc(data)) { + if (data->in_scaled & (1 << nr)) + return val * 24; + else +@@ -329,7 +351,7 @@ static inline u16 FAN16_TO_REG(long rpm) + + static u8 pwm_to_reg(const struct it87_data *data, long val) + { +- if (data->type == it8721) ++ if (has_newer_autopwm(data)) + return val; + else + return val >> 1; +@@ -337,7 +359,7 @@ static u8 pwm_to_reg(const struct it87_data *data, long val) + + static int pwm_from_reg(const struct it87_data *data, u8 reg) + { +- if (data->type == it8721) ++ if (has_newer_autopwm(data)) + return reg; + else + return (reg & 0x7f) << 1; +@@ -374,7 +396,8 @@ static inline int has_16bit_fans(const struct it87_data *data) + || data->type == it8716 + || data->type == it8718 + || data->type == it8720 +- || data->type == it8721; ++ || data->type == it8721 ++ || data->type == it8728; + } + + static inline int has_old_autopwm(const struct it87_data *data) +@@ -842,7 +865,7 @@ static ssize_t set_pwm_enable(struct device *dev, + data->fan_main_ctrl); + } else { + if (val == 1) /* Manual mode */ +- data->pwm_ctrl[nr] = data->type == it8721 ? ++ data->pwm_ctrl[nr] = has_newer_autopwm(data) ? + data->pwm_temp_map[nr] : + data->pwm_duty[nr]; + else /* Automatic mode */ +@@ -870,7 +893,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, + return -EINVAL; + + mutex_lock(&data->update_lock); +- if (data->type == it8721) { ++ if (has_newer_autopwm(data)) { + /* If we are in automatic mode, the PWM duty cycle register + * is read-only so we can't write the value */ + if (data->pwm_ctrl[nr] & 0x80) { +@@ -1311,8 +1334,8 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr, + struct it87_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(attr)->index; + +- return sprintf(buf, "%s\n", data->type == it8721 ? labels_it8721[nr] +- : labels[nr]); ++ return sprintf(buf, "%s\n", has_12mv_adc(data) ? labels_it8721[nr] ++ : labels[nr]); + } + static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0); + static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1); +@@ -1605,6 +1628,9 @@ static int __init it87_find(unsigned short *address, + case IT8721F_DEVID: + sio_data->type = it8721; + break; ++ case IT8728F_DEVID: ++ sio_data->type = it8728; ++ break; + case 0xffff: /* No device at all */ + goto exit; + default: +@@ -1646,8 +1672,11 @@ static int __init it87_find(unsigned short *address, + superio_select(GPIO); + + reg = superio_inb(IT87_SIO_GPIO3_REG); +- if (sio_data->type == it8721) { +- /* The IT8721F/IT8758E doesn't have VID pins at all */ ++ if (sio_data->type == it8721 || sio_data->type == it8728) { ++ /* ++ * The IT8721F/IT8758E doesn't have VID pins at all, ++ * not sure about the IT8728F. ++ */ + sio_data->skip_vid = 1; + } else { + /* We need at least 4 VID pins */ +@@ -1692,7 +1721,8 @@ static int __init it87_find(unsigned short *address, + } + if (reg & (1 << 0)) + sio_data->internal |= (1 << 0); +- if ((reg & (1 << 1)) || sio_data->type == it8721) ++ if ((reg & (1 << 1)) || sio_data->type == it8721 || ++ sio_data->type == it8728) + sio_data->internal |= (1 << 1); + + sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; +@@ -1770,6 +1800,7 @@ static int __devinit it87_probe(struct platform_device *pdev) + "it8718", + "it8720", + "it8721", ++ "it8728", + }; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); +@@ -1807,7 +1838,7 @@ static int __devinit it87_probe(struct platform_device *pdev) + enable_pwm_interface = it87_check_pwm(dev); + + /* Starting with IT8721F, we handle scaling of internal voltages */ +- if (data->type == it8721) { ++ if (has_12mv_adc(data)) { + if (sio_data->internal & (1 << 0)) + data->in_scaled |= (1 << 3); /* in3 is AVCC */ + if (sio_data->internal & (1 << 1)) +@@ -2093,7 +2124,7 @@ static void __devinit it87_init_device(struct platform_device *pdev) + static void it87_update_pwm_ctrl(struct it87_data *data, int nr) + { + data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr)); +- if (data->type == it8721) { ++ if (has_newer_autopwm(data)) { + data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; + data->pwm_duty[nr] = it87_read_value(data, + IT87_REG_PWM_DUTY(nr)); +diff --git a/drivers/hwmon/max6620.c b/drivers/hwmon/max6620.c +new file mode 100644 +index 0000000..525d12f +--- /dev/null ++++ b/drivers/hwmon/max6620.c +@@ -0,0 +1,661 @@ ++/* ++ * max6620.c - Linux Kernel module for hardware monitoring. ++ * ++ * (C) 2012 by L. Grunenberg ++ * ++ * based on code written by : ++ * 2007 by Hans J. Koch ++ * John Morris ++ * Copyright (c) 2003 Spirent Communications ++ * and Claus Gindhart ++ * ++ * This module has only been tested with the MAX6620 chip. ++ * ++ * The datasheet was last seen at: ++ * ++ * http://pdfserv.maxim-ic.com/en/ds/MAX6620.pdf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * Insmod parameters ++ */ ++ ++ ++/* clock: The clock frequency of the chip the driver should assume */ ++static int clock = 8192; ++static u32 sr = 2; ++static u32 np = 2; ++ ++module_param(clock, int, S_IRUGO); ++ ++static const unsigned short normal_i2c[] = {0x0a, 0x1a, 0x2a, I2C_CLIENT_END}; ++ ++/* ++ * MAX 6620 registers ++ */ ++ ++#define MAX6620_REG_CONFIG 0x00 ++#define MAX6620_REG_FAULT 0x01 ++#define MAX6620_REG_CONF_FAN0 0x02 ++#define MAX6620_REG_CONF_FAN1 0x03 ++#define MAX6620_REG_CONF_FAN2 0x04 ++#define MAX6620_REG_CONF_FAN3 0x05 ++#define MAX6620_REG_DYN_FAN0 0x06 ++#define MAX6620_REG_DYN_FAN1 0x07 ++#define MAX6620_REG_DYN_FAN2 0x08 ++#define MAX6620_REG_DYN_FAN3 0x09 ++#define MAX6620_REG_TACH0 0x10 ++#define MAX6620_REG_TACH1 0x12 ++#define MAX6620_REG_TACH2 0x14 ++#define MAX6620_REG_TACH3 0x16 ++#define MAX6620_REG_VOLT0 0x18 ++#define MAX6620_REG_VOLT1 0x1A ++#define MAX6620_REG_VOLT2 0x1C ++#define MAX6620_REG_VOLT3 0x1E ++#define MAX6620_REG_TAR0 0x20 ++#define MAX6620_REG_TAR1 0x22 ++#define MAX6620_REG_TAR2 0x24 ++#define MAX6620_REG_TAR3 0x26 ++#define MAX6620_REG_DAC0 0x28 ++#define MAX6620_REG_DAC1 0x2A ++#define MAX6620_REG_DAC2 0x2C ++#define MAX6620_REG_DAC3 0x2E ++ ++/* ++ * Config register bits ++ */ ++ ++#define MAX6620_CFG_RUN 0x80 ++#define MAX6620_CFG_POR 0x40 ++#define MAX6620_CFG_TIMEOUT 0x20 ++#define MAX6620_CFG_FULLFAN 0x10 ++#define MAX6620_CFG_OSC 0x08 ++#define MAX6620_CFG_WD_MASK 0x06 ++#define MAX6620_CFG_WD_2 0x02 ++#define MAX6620_CFG_WD_6 0x04 ++#define MAX6620_CFG_WD10 0x06 ++#define MAX6620_CFG_WD 0x01 ++ ++ ++/* ++ * Failure status register bits ++ */ ++ ++#define MAX6620_FAIL_TACH0 0x10 ++#define MAX6620_FAIL_TACH1 0x20 ++#define MAX6620_FAIL_TACH2 0x40 ++#define MAX6620_FAIL_TACH3 0x80 ++#define MAX6620_FAIL_MASK0 0x01 ++#define MAX6620_FAIL_MASK1 0x02 ++#define MAX6620_FAIL_MASK2 0x04 ++#define MAX6620_FAIL_MASK3 0x08 ++ ++ ++/* Minimum and maximum values of the FAN-RPM */ ++#define FAN_RPM_MIN 240 ++#define FAN_RPM_MAX 30000 ++ ++#define DIV_FROM_REG(reg) (1 << ((reg & 0xE0) >> 5)) ++ ++static int max6620_probe(struct i2c_client *client, const struct i2c_device_id *id); ++static int max6620_init_client(struct i2c_client *client); ++static int max6620_remove(struct i2c_client *client); ++static struct max6620_data *max6620_update_device(struct device *dev); ++ ++static const u8 config_reg[] = { ++ MAX6620_REG_CONF_FAN0, ++ MAX6620_REG_CONF_FAN1, ++ MAX6620_REG_CONF_FAN2, ++ MAX6620_REG_CONF_FAN3, ++}; ++ ++static const u8 dyn_reg[] = { ++ MAX6620_REG_DYN_FAN0, ++ MAX6620_REG_DYN_FAN1, ++ MAX6620_REG_DYN_FAN2, ++ MAX6620_REG_DYN_FAN3, ++}; ++ ++static const u8 tach_reg[] = { ++ MAX6620_REG_TACH0, ++ MAX6620_REG_TACH1, ++ MAX6620_REG_TACH2, ++ MAX6620_REG_TACH3, ++}; ++ ++static const u8 volt_reg[] = { ++ MAX6620_REG_VOLT0, ++ MAX6620_REG_VOLT1, ++ MAX6620_REG_VOLT2, ++ MAX6620_REG_VOLT3, ++}; ++ ++static const u8 target_reg[] = { ++ MAX6620_REG_TAR0, ++ MAX6620_REG_TAR1, ++ MAX6620_REG_TAR2, ++ MAX6620_REG_TAR3, ++}; ++ ++static const u8 dac_reg[] = { ++ MAX6620_REG_DAC0, ++ MAX6620_REG_DAC1, ++ MAX6620_REG_DAC2, ++ MAX6620_REG_DAC3, ++}; ++ ++/* ++ * Driver data (common to all clients) ++ */ ++ ++static const struct i2c_device_id max6620_id[] = { ++ { "max6620", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, max6620_id); ++ ++static struct i2c_driver max6620_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "max6620", ++ }, ++ .probe = max6620_probe, ++ .remove = __devexit_p(max6620_remove), ++ .id_table = max6620_id, ++ .address_list = normal_i2c, ++}; ++ ++/* ++ * Client data (each client gets its own) ++ */ ++ ++struct max6620_data { ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ int nr_fans; ++ char valid; /* zero until following fields are valid */ ++ unsigned long last_updated; /* in jiffies */ ++ ++ /* register values */ ++ u8 speed[4]; ++ u8 config; ++ u8 fancfg[4]; ++ u8 fandyn[4]; ++ u8 tach[4]; ++ u8 volt[4]; ++ u8 target[4]; ++ u8 dac[4]; ++ u8 fault; ++}; ++ ++static ssize_t get_fan(struct device *dev, struct device_attribute *devattr, char *buf) { ++ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ u32 rpm = 0; ++ u32 tach = 0; ++ u32 tach1 = 0; ++ u32 tach2 = 0; ++ ++ tach1 = i2c_smbus_read_byte_data(client, tach_reg[attr->index]); ++ tach1 = (tach1 << 3) & 0x7f8; ++ tach2 = i2c_smbus_read_byte_data(client, tach_reg[attr->index] + 1); ++ tach2 = (tach2 >> 5) & 0x7; ++ tach = tach1 | tach2; ++ if (tach == 0) { ++ rpm = 0; ++ } else { ++ rpm = (60 * sr * clock)/(tach * np); ++ } ++ return sprintf(buf, "%d\n", rpm); ++} ++ ++static ssize_t get_target(struct device *dev, struct device_attribute *devattr, char *buf) { ++ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ u32 rpm; ++ u32 target; ++ u32 target1; ++ u32 target2; ++ ++ target1 = i2c_smbus_read_byte_data(client, target_reg[attr->index]); ++ target1 = (target1 << 3) & 0x7f8; ++ target2 = i2c_smbus_read_byte_data(client, target_reg[attr->index] + 1); ++ target2 = (target2 >> 5) & 0x7; ++ target = target1 | target2; ++ if (target == 0) { ++ rpm = 0; ++ } else { ++ rpm = (60 * sr * clock)/(target * np); ++ } ++ return sprintf(buf, "%d\n", rpm); ++} ++ ++static ssize_t set_target(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { ++ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct max6620_data *data = i2c_get_clientdata(client); ++ u32 rpm; ++ int err; ++ u32 target; ++ u32 target1; ++ u32 target2; ++ ++ err = kstrtouint(buf, 10, &rpm); ++ if (err) ++ return err; ++ ++ rpm = SENSORS_LIMIT(rpm, FAN_RPM_MIN, FAN_RPM_MAX); ++ ++ mutex_lock(&data->update_lock); ++ ++ target = (60 * sr * 8192)/(rpm * np); ++ target1 = (target >> 3) & 0xff; ++ target2 = (target << 5) & 0xe0; ++ i2c_smbus_write_byte_data(client, target_reg[attr->index], target1); ++ i2c_smbus_write_byte_data(client, target_reg[attr->index] + 1, target2); ++ ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++/* ++ * Get/set the fan speed in open loop mode using pwm1 sysfs file. ++ * Speed is given as a relative value from 0 to 255, where 255 is maximum ++ * speed. Note that this is done by writing directly to the chip's DAC, ++ * it won't change the closed loop speed set by fan1_target. ++ * Also note that due to rounding errors it is possible that you don't read ++ * back exactly the value you have set. ++ */ ++ ++static ssize_t get_pwm(struct device *dev, struct device_attribute *devattr, char *buf) { ++ ++ int pwm; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct max6620_data *data = max6620_update_device(dev); ++ ++ /* ++ * Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans. ++ * Lower DAC values mean higher speeds. ++ */ ++ pwm = ((int)data->volt[attr->index]); ++ ++ if (pwm < 0) ++ pwm = 0; ++ ++ return sprintf(buf, "%d\n", pwm); ++} ++ ++static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { ++ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct max6620_data *data = i2c_get_clientdata(client); ++ unsigned long pwm; ++ int err; ++ ++ err = kstrtoul(buf, 10, &pwm); ++ if (err) ++ return err; ++ ++ pwm = SENSORS_LIMIT(pwm, 0, 255); ++ ++ mutex_lock(&data->update_lock); ++ ++ data->dac[attr->index] = pwm; ++ ++ ++ i2c_smbus_write_byte_data(client, dac_reg[attr->index], data->dac[attr->index]); ++ i2c_smbus_write_byte_data(client, dac_reg[attr->index]+1, 0x00); ++ ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++/* ++ * Get/Set controller mode: ++ * Possible values: ++ * 0 = Fan always on ++ * 1 = Open loop, Voltage is set according to speed, not regulated. ++ * 2 = Closed loop, RPM for all fans regulated by fan1 tachometer ++ */ ++ ++static ssize_t get_enable(struct device *dev, struct device_attribute *devattr, char *buf) { ++ ++ struct max6620_data *data = max6620_update_device(dev); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ int mode = (data->fancfg[attr->index] & 0x80 ) >> 7; ++ int sysfs_modes[2] = {1, 2}; ++ ++ return sprintf(buf, "%d\n", sysfs_modes[mode]); ++} ++ ++static ssize_t set_enable(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { ++ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6620_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ int max6620_modes[3] = {0, 1, 0}; ++ unsigned long mode; ++ int err; ++ ++ err = kstrtoul(buf, 10, &mode); ++ if (err) ++ return err; ++ ++ if (mode > 2) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ ++ data->fancfg[attr->index] = i2c_smbus_read_byte_data(client, config_reg[attr->index]); ++ data->fancfg[attr->index] = (data->fancfg[attr->index] & ~0x80) ++ | (max6620_modes[mode] << 7); ++ ++ i2c_smbus_write_byte_data(client, config_reg[attr->index], data->fancfg[attr->index]); ++ ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++/* ++ * Read/write functions for fan1_div sysfs file. The MAX6620 has no such ++ * divider. We handle this by converting between divider and counttime: ++ * ++ * (counttime == k) <==> (divider == 2^k), k = 0, 1, 2, 3, 4 or 5 ++ * ++ * Lower values of k allow to connect a faster fan without the risk of ++ * counter overflow. The price is lower resolution. You can also set counttime ++ * using the module parameter. Note that the module parameter "prescaler" also ++ * influences the behaviour. Unfortunately, there's no sysfs attribute ++ * defined for that. See the data sheet for details. ++ */ ++ ++static ssize_t get_div(struct device *dev, struct device_attribute *devattr, char *buf) { ++ ++ struct max6620_data *data = max6620_update_device(dev); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ ++ return sprintf(buf, "%d\n", DIV_FROM_REG(data->fandyn[attr->index])); ++} ++ ++static ssize_t set_div(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { ++ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6620_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ unsigned long div; ++ int err; ++ u8 div_bin; ++ ++ err = kstrtoul(buf, 10, &div); ++ if (err) ++ return err; ++ ++ mutex_lock(&data->update_lock); ++ switch (div) { ++ case 1: ++ div_bin = 0; ++ break; ++ case 2: ++ div_bin = 1; ++ break; ++ case 4: ++ div_bin = 2; ++ break; ++ case 8: ++ div_bin = 3; ++ break; ++ case 16: ++ div_bin = 4; ++ break; ++ case 32: ++ div_bin = 5; ++ break; ++ default: ++ mutex_unlock(&data->update_lock); ++ return -EINVAL; ++ } ++ data->fandyn[attr->index] &= 0x1F; ++ data->fandyn[attr->index] |= div_bin << 5; ++ i2c_smbus_write_byte_data(client, dyn_reg[attr->index], data->fandyn[attr->index]); ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, 0); ++static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan, NULL, 1); ++static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, get_fan, NULL, 2); ++static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, get_fan, NULL, 3); ++static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, get_target, set_target, 0); ++static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, get_div, set_div, 0); ++static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, 0); ++static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 0); ++static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, get_target, set_target, 1); ++static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO, get_div, set_div, 1); ++static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, 1); ++static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 1); ++static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO, get_target, set_target, 2); ++static SENSOR_DEVICE_ATTR(fan3_div, S_IWUSR | S_IRUGO, get_div, set_div, 2); ++static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, 2); ++static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 2); ++static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO, get_target, set_target, 3); ++static SENSOR_DEVICE_ATTR(fan4_div, S_IWUSR | S_IRUGO, get_div, set_div, 3); ++static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, 3); ++static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 3); ++ ++static struct attribute *max6620_attrs[] = { ++ &sensor_dev_attr_fan1_input.dev_attr.attr, ++ &sensor_dev_attr_fan2_input.dev_attr.attr, ++ &sensor_dev_attr_fan3_input.dev_attr.attr, ++ &sensor_dev_attr_fan4_input.dev_attr.attr, ++ &sensor_dev_attr_fan1_target.dev_attr.attr, ++ &sensor_dev_attr_fan1_div.dev_attr.attr, ++ &sensor_dev_attr_pwm1_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm1.dev_attr.attr, ++ &sensor_dev_attr_fan2_target.dev_attr.attr, ++ &sensor_dev_attr_fan2_div.dev_attr.attr, ++ &sensor_dev_attr_pwm2_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm2.dev_attr.attr, ++ &sensor_dev_attr_fan3_target.dev_attr.attr, ++ &sensor_dev_attr_fan3_div.dev_attr.attr, ++ &sensor_dev_attr_pwm3_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm3.dev_attr.attr, ++ &sensor_dev_attr_fan4_target.dev_attr.attr, ++ &sensor_dev_attr_fan4_div.dev_attr.attr, ++ &sensor_dev_attr_pwm4_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm4.dev_attr.attr, ++ NULL ++}; ++ ++static struct attribute_group max6620_attr_grp = { ++ .attrs = max6620_attrs, ++}; ++ ++ ++/* ++ * Real code ++ */ ++ ++static int __devinit max6620_probe(struct i2c_client *client, const struct i2c_device_id *id) { ++ ++ struct max6620_data *data; ++ int err; ++ ++ data = devm_kzalloc(&client->dev, sizeof(struct max6620_data), GFP_KERNEL); ++ if (!data) { ++ dev_err(&client->dev, "out of memory.\n"); ++ return -ENOMEM; ++ } ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->update_lock); ++ data->nr_fans = id->driver_data; ++ ++ /* ++ * Initialize the max6620 chip ++ */ ++ dev_info(&client->dev, "About to initialize module\n"); ++ ++ err = max6620_init_client(client); ++ if (err) ++ return err; ++ dev_info(&client->dev, "Module initialized\n"); ++ ++ err = sysfs_create_group(&client->dev.kobj, &max6620_attr_grp); ++ if (err) ++ return err; ++dev_info(&client->dev, "Sysfs entries created\n"); ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (!IS_ERR(data->hwmon_dev)) ++ return 0; ++ ++ err = PTR_ERR(data->hwmon_dev); ++ dev_err(&client->dev, "error registering hwmon device.\n"); ++ ++ sysfs_remove_group(&client->dev.kobj, &max6620_attr_grp); ++ return err; ++} ++ ++static int __devexit max6620_remove(struct i2c_client *client) { ++ ++ struct max6620_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ ++ sysfs_remove_group(&client->dev.kobj, &max6620_attr_grp); ++ return 0; ++} ++ ++static int max6620_init_client(struct i2c_client *client) { ++ ++ struct max6620_data *data = i2c_get_clientdata(client); ++ int config; ++ int err = -EIO; ++ int i; ++ ++ config = i2c_smbus_read_byte_data(client, MAX6620_REG_CONFIG); ++ ++ if (config < 0) { ++ dev_err(&client->dev, "Error reading config, aborting.\n"); ++ return err; ++ } ++ ++ ++ /* ++ * Set bit 4, disable other fans from going full speed on a fail ++ * failure. ++ */ ++ if (i2c_smbus_write_byte_data(client, MAX6620_REG_CONFIG, config | 0x10)) { ++ dev_err(&client->dev, "Config write error, aborting.\n"); ++ return err; ++ } ++ ++ data->config = config; ++ for (i = 0; i < 4; i++) { ++ data->fancfg[i] = i2c_smbus_read_byte_data(client, config_reg[i]); ++ data->fancfg[i] |= 0xa8; // enable TACH monitoring ++ i2c_smbus_write_byte_data(client, config_reg[i], data->fancfg[i]); ++ data->fandyn[i] = i2c_smbus_read_byte_data(client, dyn_reg[i]); ++ /* 2 counts (001) and Rate change 100 (0.125 secs) */ ++ data-> fandyn[i] = 0x30; ++ i2c_smbus_write_byte_data(client, dyn_reg[i], data->fandyn[i]); ++ data->tach[i] = i2c_smbus_read_byte_data(client, tach_reg[i]); ++ data->volt[i] = i2c_smbus_read_byte_data(client, volt_reg[i]); ++ data->target[i] = i2c_smbus_read_byte_data(client, target_reg[i]); ++ data->dac[i] = i2c_smbus_read_byte_data(client, dac_reg[i]); ++ ++ } ++ return 0; ++} ++ ++static struct max6620_data *max6620_update_device(struct device *dev) ++{ ++ int i; ++ u8 fault_reg; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6620_data *data = i2c_get_clientdata(client); ++ ++ mutex_lock(&data->update_lock); ++ ++ if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { ++ ++ for (i = 0; i < 4; i++) { ++ data->fancfg[i] = i2c_smbus_read_byte_data(client, config_reg[i]); ++ data->fandyn[i] = i2c_smbus_read_byte_data(client, dyn_reg[i]); ++ data->tach[i] = i2c_smbus_read_byte_data(client, tach_reg[i]); ++ data->volt[i] = i2c_smbus_read_byte_data(client, volt_reg[i]); ++ data->target[i] = i2c_smbus_read_byte_data(client, target_reg[i]); ++ data->dac[i] = i2c_smbus_read_byte_data(client, dac_reg[i]); ++ } ++ ++ ++ /* ++ * Alarms are cleared on read in case the condition that ++ * caused the alarm is removed. Keep the value latched here ++ * for providing the register through different alarm files. ++ */ ++ fault_reg = i2c_smbus_read_byte_data(client, MAX6620_REG_FAULT); ++ data->fault |= (fault_reg >> 4) & (fault_reg & 0x0F); ++ ++ data->last_updated = jiffies; ++ data->valid = 1; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ ++ return data; ++} ++ ++// module_i2c_driver(max6620_driver); ++ ++static int __init max6620_init(void) ++{ ++ return i2c_add_driver(&max6620_driver); ++} ++module_init(max6620_init); ++ ++/** ++ * sht21_init() - clean up driver ++ * ++ * Called when module is removed. ++ */ ++static void __exit max6620_exit(void) ++{ ++ i2c_del_driver(&max6620_driver); ++} ++module_exit(max6620_exit); ++ ++MODULE_AUTHOR("Lucas Grunenberg"); ++MODULE_DESCRIPTION("MAX6620 sensor driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c +index 8c3df04..5e78a33 100644 +--- a/drivers/hwmon/max6639.c ++++ b/drivers/hwmon/max6639.c +@@ -66,9 +66,62 @@ static unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END }; + #define MAX6639_GCONFIG_CH2_LOCAL 0x10 + #define MAX6639_GCONFIG_PWM_FREQ_HI 0x08 + +-#define MAX6639_FAN_CONFIG1_PWM 0x80 ++#define MAX6639_GCONFIG_STANDBY_OFFSET 7 ++#define MAX6639_GCONFIG_POR_OFFSET 6 ++#define MAX6639_GCONFIG_DISABLE_TIMEOUT_OFFSET 5 ++#define MAX6639_GCONFIG_CH2_LOCAL_OFFSET 4 ++#define MAX6639_GCONFIG_PWM_FREQ_HI_OFFSET 3 ++ ++#define MAX6639_OUTMASK_CH1_ALERT_DISABLE 7 ++#define MAX6639_OUTMASK_CH2_ALERT_DISABLE 6 ++#define MAX6639_OUTMASK_CH1_OT_DISABLE 5 ++#define MAX6639_OUTMASK_CH2_OT_DISABLE 4 ++#define MAX6639_OUTMASK_CH1_THERM_DISABLE 3 ++#define MAX6639_OUTMASK_CH2_THERM_DISABLE 2 ++#define MAX6639_OUTMASK_FAN1_FAULT_ENABLE 1 ++#define MAX6639_OUTMASK_FAN2_FAULT_ENABLE 0 ++ ++#define MAX6639_FAN_CONFIG1_PWM 0x80 ++#define MAX6639_FAN_CONFIG1_PWM_MODE 0x80 ++#define MAX6639_FAN_CONFIG1_PWM_MODE_OFFSET 7 ++#define MAX6639_FAN_CONFIG1_DUTY 0x70 ++#define MAX6639_FAN_CONFIG1_DUTY_OFFSET 4 ++#define MAX6639_FAN_CONFIG1_TEMP_CH 0x0c ++#define MAX6639_FAN_CONFIG1_TEMP_CH_OFFSET 2 ++#define MAX6639_FAN_CONFIG1_RPM_RANGE 0x03 ++#define MAX6639_FAN_CONFIG1_RPM_RANGE_OFFSET 0 ++ ++#define MAX6639_FAN_CONFIG2a_RPM_STEPA 0xf0 ++#define MAX6639_FAN_CONFIG2a_RPM_STEPA_OFFSET 4 ++#define MAX6639_FAN_CONFIG2a_TEMP_STEPA 0x0f ++#define MAX6639_FAN_CONFIG2a_TEMP_STEPA_OFFSET 0 ++ ++#define MAX6639_FAN_CONFIG2b_RPM_STEPB 0xf0 ++#define MAX6639_FAN_CONFIG2b_RPM_STEPB_OFFSET 4 ++#define MAX6639_FAN_CONFIG2b_START_STEPB 0x0f ++#define MAX6639_FAN_CONFIG2b_START_STEPB_OFFSET 0 ++ ++ ++#define MAX6639_FAN_CONFIG3_SPINUP_DISABLE 0x80 ++#define MAX6639_FAN_CONFIG3_SPINUP_DISABLE_OFFSET 7 ++#define MAX6639_FAN_CONFIG3_THERM_FULL_SPEED 0x40 ++#define MAX6639_FAN_CONFIG3_THERM_FULL_SPEED_OFFSET 6 ++#define MAX6639_FAN_CONFIG3_PULSE_STR_DISABLE 0x20 ++#define MAX6639_FAN_CONFIG3_PULSE_STR_DISABLE_OFFSET 5 ++#define MAX6639_FAN_CONFIG3_PWM_FREQ 0x3 ++#define MAX6639_FAN_CONFIG3_PWM_FREQ_OFFSET 0 ++ ++#define MAX6639_FAN_PPR_COUNT 0xc0 ++#define MAX6639_FAN_PPR_COUNT_OFFSET 6 ++#define MAX6639_FAN_PPR_TACH_MIN 0x3f ++#define MAX6639_FAN_PPR_TACH_MIN_OFFSET 0 ++ ++#define MAX6639_FAN_TARGET_CNT 0xff ++#define MAX6639_FAN_TARGET_CNT_OFFSET 0 ++ ++#define MAX6639_FAN_CNT 0xff ++#define MAX6639_FAN_CNT_OFFSET 0 + +-#define MAX6639_FAN_CONFIG3_THERM_FULL_SPEED 0x40 + + static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 }; + +@@ -162,6 +215,299 @@ abort: + return ret; + } + ++ ++/* Puneet start */ ++static ssize_t show_fan_target(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6639_data *data = i2c_get_clientdata(client); ++ int conf, tach_count, range; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); ++ ++ mutex_lock(&data->update_lock); ++ conf = i2c_smbus_read_byte_data(client, MAX6639_REG_FAN_CONFIG1(attr->index)); ++ tach_count = i2c_smbus_read_byte_data(client, MAX6639_REG_TARGET_CNT(attr->index)); ++ mutex_unlock(&data->update_lock); ++ if (conf < 0) ++ return conf; ++ if (tach_count < 0) ++ return tach_count; ++ ++ range = (conf & MAX6639_FAN_CONFIG1_RPM_RANGE) >> MAX6639_FAN_CONFIG1_RPM_RANGE_OFFSET; ++ return sprintf(buf, "%d\n", FAN_FROM_REG(tach_count, range)); ++} ++ ++static ssize_t set_fan_target(struct device *dev, ++ struct device_attribute *dev_attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6639_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); ++ int conf, range, tach_count, target_speed; ++ int res; ++ ++ res = strict_strtoul(buf, 10, &target_speed); ++ if (res < 0) ++ return res; ++ ++ mutex_lock(&data->update_lock); ++ conf = i2c_smbus_read_byte_data(client, MAX6639_REG_FAN_CONFIG1(attr->index)); ++ mutex_unlock(&data->update_lock); ++ if (conf < 0) ++ return conf; ++ ++ range = (conf & MAX6639_FAN_CONFIG1_RPM_RANGE) >> MAX6639_FAN_CONFIG1_RPM_RANGE_OFFSET; ++ tach_count = FAN_FROM_REG(target_speed, range); ++ ++ mutex_lock(&data->update_lock); ++ res= i2c_smbus_write_byte_data(client, ++ MAX6639_REG_TARGET_CNT(attr->index), tach_count); ++ mutex_unlock(&data->update_lock); ++ if (res < 0) ++ return res; ++ return count; ++} ++ ++static ssize_t show_pwm_enable(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6639_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); ++ int conf; ++ int pwm_mode; ++ int temp_ch; ++ int mode = 0; ++ /*Modes 0: Auto Control, 1: Manual PWM Control, 2: Manual RPM Control */ ++ ++ mutex_lock(&data->update_lock); ++ conf = i2c_smbus_read_byte_data(client, MAX6639_REG_FAN_CONFIG1(attr->index)); ++ mutex_unlock(&data->update_lock); ++ if (conf < 0) ++ return conf; ++ ++ pwm_mode = (conf & MAX6639_FAN_CONFIG1_PWM_MODE) >> MAX6639_FAN_CONFIG1_PWM_MODE_OFFSET; ++ temp_ch = (conf & MAX6639_FAN_CONFIG1_TEMP_CH) >> MAX6639_FAN_CONFIG1_TEMP_CH_OFFSET; ++ ++ if (pwm_mode == 1) ++ mode = 1; ++ else if (temp_ch == 0) ++ mode = 2; ++ return sprintf(buf, "%d\n",mode); ++} ++ ++static ssize_t set_pwm_enable(struct device *dev, ++ struct device_attribute *dev_attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6639_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); ++ int mode, pwm_mode, temp_ch; ++ int res; ++ int val = 0; ++ /*Modes 0: Auto Control, 1: Manual PWM Control, 2: Manual RPM Control */ ++ res = strict_strtoul(buf, 10, &mode); ++ if (res < 0) ++ return res; ++ ++ if (mode == 0) { ++ pwm_mode = 0; ++ temp_ch = 3; ++ } else if (mode == 1){ ++ pwm_mode = 1; ++ temp_ch = 3; ++ } else { ++ pwm_mode = 0; ++ temp_ch = 0; ++ } ++ val |= ((pwm_mode << MAX6639_FAN_CONFIG1_PWM_MODE_OFFSET) & ++ MAX6639_FAN_CONFIG1_PWM_MODE); ++ val |= ((temp_ch << MAX6639_FAN_CONFIG1_TEMP_CH_OFFSET) & ++ MAX6639_FAN_CONFIG1_TEMP_CH); ++ ++ mutex_lock(&data->update_lock); ++ res = i2c_smbus_write_byte_data(client, ++ MAX6639_REG_FAN_CONFIG1(attr->index), val); ++ mutex_unlock(&data->update_lock); ++ if (res < 0) ++ return res; ++ return count; ++} ++ ++static ssize_t show_value(struct device *dev, char *buf, ++ u8 reg, u8 mask, u8 offset) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6639_data *data = i2c_get_clientdata(client); ++ int reg_val; ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ mutex_lock(&data->update_lock); ++ reg_val = i2c_smbus_read_byte_data(client, reg); ++ mutex_unlock(&data->update_lock); ++ if (reg_val < 0) ++ return reg_val; ++ ++ reg_val = (reg_val & mask) >> offset; ++ return sprintf(buf, "%d\n", reg_val); ++} ++ ++static ssize_t set_value(struct device *dev, const char *buf, size_t count, ++ u8 reg, u8 mask, u8 offset) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6639_data *data = i2c_get_clientdata(client); ++ unsigned long val; ++ int res; ++ int reg_val; ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ res = strict_strtoul(buf, 10, &val); ++ if (res) ++ return res; ++ mutex_lock(&data->update_lock); ++ reg_val = i2c_smbus_read_byte_data(client, reg); ++ mutex_unlock(&data->update_lock); ++ if (reg_val < 0) ++ return reg_val; ++ ++ reg_val &= ~mask; ++ val = (val << offset) & mask; ++ reg_val |= val; ++ ++ mutex_lock(&data->update_lock); ++ res = i2c_smbus_write_byte_data(client, reg, val); ++ mutex_unlock(&data->update_lock); ++ if (res < 0) ++ return res; ++ return count; ++} ++ ++#define max6639_attr(type, reg, mask, off) \ ++static ssize_t show_##type(struct device *dev, \ ++ struct device_attribute *dev_attr, char *buf) \ ++{ \ ++ return show_value(dev, buf, reg, mask, off); \ ++} \ ++static ssize_t set_##type(struct device *dev, \ ++ struct device_attribute *dev_attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ return set_value(dev, buf, count, reg, mask, off); \ ++} \ ++static SENSOR_DEVICE_ATTR(type, S_IWUSR | S_IRUGO, show_##type, set_##type, 0); \ ++ ++static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable, set_pwm_enable, 0); ++static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable, set_pwm_enable, 1); ++static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, show_fan_target, set_fan_target, 0); ++static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, show_fan_target, set_fan_target, 1); ++ ++max6639_attr(standby, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_STANDBY, ++ MAX6639_GCONFIG_STANDBY_OFFSET) ++max6639_attr(por, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_POR, ++ MAX6639_GCONFIG_POR_OFFSET) ++max6639_attr(disable_smbus_timeout, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_DISABLE_TIMEOUT, ++ MAX6639_GCONFIG_DISABLE_TIMEOUT_OFFSET) ++max6639_attr(ch2_local, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_CH2_LOCAL, ++ MAX6639_GCONFIG_CH2_LOCAL_OFFSET) ++max6639_attr(pwm_freq_hi, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_PWM_FREQ_HI, ++ MAX6639_GCONFIG_PWM_FREQ_HI_OFFSET) ++ ++max6639_attr(ch1_alert_disable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_CH1_ALERT_DISABLE, ++ MAX6639_OUTMASK_CH1_ALERT_DISABLE) ++max6639_attr(ch2_alert_disable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_CH2_ALERT_DISABLE, ++ MAX6639_OUTMASK_CH2_ALERT_DISABLE) ++max6639_attr(ch1_ot_disable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_CH1_OT_DISABLE, ++ MAX6639_OUTMASK_CH1_OT_DISABLE) ++max6639_attr(ch2_ot_disable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_CH2_OT_DISABLE, ++ MAX6639_OUTMASK_CH2_OT_DISABLE) ++max6639_attr(ch1_therm_disable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_CH1_THERM_DISABLE, ++ MAX6639_OUTMASK_CH1_THERM_DISABLE) ++max6639_attr(ch2_therm_disable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_CH2_THERM_DISABLE, ++ MAX6639_OUTMASK_CH2_THERM_DISABLE) ++max6639_attr(fan1_fault_enable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_FAN1_FAULT_ENABLE, ++ MAX6639_OUTMASK_FAN1_FAULT_ENABLE) ++max6639_attr(fan2_fault_enable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_FAN2_FAULT_ENABLE, ++ MAX6639_OUTMASK_FAN2_FAULT_ENABLE) ++ ++ ++max6639_attr(fan1_pwm_mode, MAX6639_REG_FAN_CONFIG1(0), MAX6639_FAN_CONFIG1_PWM_MODE, ++ MAX6639_FAN_CONFIG1_PWM_MODE_OFFSET) ++max6639_attr(fan2_pwm_mode, MAX6639_REG_FAN_CONFIG1(1), MAX6639_FAN_CONFIG1_PWM_MODE, ++ MAX6639_FAN_CONFIG1_PWM_MODE_OFFSET) ++max6639_attr(fan1_duty, MAX6639_REG_FAN_CONFIG1(0), MAX6639_FAN_CONFIG1_DUTY, ++ MAX6639_FAN_CONFIG1_DUTY_OFFSET) ++max6639_attr(fan2_duty, MAX6639_REG_FAN_CONFIG1(1), MAX6639_FAN_CONFIG1_DUTY, ++ MAX6639_FAN_CONFIG1_DUTY_OFFSET) ++max6639_attr(fan1_temp_ch, MAX6639_REG_FAN_CONFIG1(0), MAX6639_FAN_CONFIG1_TEMP_CH, ++ MAX6639_FAN_CONFIG1_TEMP_CH_OFFSET) ++max6639_attr(fan2_temp_ch, MAX6639_REG_FAN_CONFIG1(1), MAX6639_FAN_CONFIG1_TEMP_CH, ++ MAX6639_FAN_CONFIG1_TEMP_CH_OFFSET) ++max6639_attr(fan1_rpm_range, MAX6639_REG_FAN_CONFIG1(0), MAX6639_FAN_CONFIG1_RPM_RANGE, ++ MAX6639_FAN_CONFIG1_RPM_RANGE_OFFSET) ++max6639_attr(fan2_rpm_range, MAX6639_REG_FAN_CONFIG1(1), MAX6639_FAN_CONFIG1_RPM_RANGE, ++ MAX6639_FAN_CONFIG1_RPM_RANGE_OFFSET) ++ ++max6639_attr(fan1_rpm_step_size_a, MAX6639_REG_FAN_CONFIG2a(0), MAX6639_FAN_CONFIG2a_RPM_STEPA, ++ MAX6639_FAN_CONFIG2a_RPM_STEPA_OFFSET) ++max6639_attr(fan2_rpm_step_size_a, MAX6639_REG_FAN_CONFIG2a(1), MAX6639_FAN_CONFIG2a_RPM_STEPA, ++ MAX6639_FAN_CONFIG2a_RPM_STEPA_OFFSET) ++max6639_attr(fan1_temp_step_size, MAX6639_REG_FAN_CONFIG2a(0), MAX6639_FAN_CONFIG2a_TEMP_STEPA, ++ MAX6639_FAN_CONFIG2a_RPM_STEPA_OFFSET) ++max6639_attr(fan2_temp_step_size, MAX6639_REG_FAN_CONFIG2a(1), MAX6639_FAN_CONFIG2a_TEMP_STEPA, ++ MAX6639_FAN_CONFIG2a_TEMP_STEPA_OFFSET) ++ ++max6639_attr(fan1_rpm_step_size_b, MAX6639_REG_FAN_CONFIG2b(0), MAX6639_FAN_CONFIG2b_RPM_STEPB, ++ MAX6639_FAN_CONFIG2b_RPM_STEPB_OFFSET) ++max6639_attr(fan2_rpm_step_size_b, MAX6639_REG_FAN_CONFIG2b(1), MAX6639_FAN_CONFIG2b_RPM_STEPB, ++ MAX6639_FAN_CONFIG2b_RPM_STEPB_OFFSET) ++max6639_attr(fan1_rpm_start_step_b, MAX6639_REG_FAN_CONFIG2b(0), MAX6639_FAN_CONFIG2b_START_STEPB, ++ MAX6639_FAN_CONFIG2b_START_STEPB_OFFSET) ++max6639_attr(fan2_rpm_start_step_b, MAX6639_REG_FAN_CONFIG2b(1), MAX6639_FAN_CONFIG2b_RPM_STEPB, ++ MAX6639_FAN_CONFIG2b_START_STEPB_OFFSET) ++ ++max6639_attr(fan1_spinup_disable, MAX6639_REG_FAN_CONFIG3(0), MAX6639_FAN_CONFIG3_SPINUP_DISABLE, ++ MAX6639_FAN_CONFIG3_SPINUP_DISABLE_OFFSET) ++max6639_attr(fan2_spinup_disable, MAX6639_REG_FAN_CONFIG3(1), MAX6639_FAN_CONFIG3_SPINUP_DISABLE, ++ MAX6639_FAN_CONFIG3_SPINUP_DISABLE_OFFSET) ++max6639_attr(fan1_therm_full_speed_enable, MAX6639_REG_FAN_CONFIG3(0), MAX6639_FAN_CONFIG3_THERM_FULL_SPEED, ++ MAX6639_FAN_CONFIG3_THERM_FULL_SPEED_OFFSET) ++max6639_attr(fan2_therm_full_speed_enable, MAX6639_REG_FAN_CONFIG3(1), MAX6639_FAN_CONFIG3_THERM_FULL_SPEED, ++ MAX6639_FAN_CONFIG3_THERM_FULL_SPEED_OFFSET) ++max6639_attr(fan1_pulse_stretch_disable, MAX6639_REG_FAN_CONFIG3(0), MAX6639_FAN_CONFIG3_PULSE_STR_DISABLE, ++ MAX6639_FAN_CONFIG3_PULSE_STR_DISABLE_OFFSET) ++max6639_attr(fan2_pulse_stretch_disable, MAX6639_REG_FAN_CONFIG3(1), MAX6639_FAN_CONFIG3_PULSE_STR_DISABLE, ++ MAX6639_FAN_CONFIG3_PULSE_STR_DISABLE_OFFSET) ++max6639_attr(fan1_pwm_freq, MAX6639_REG_FAN_CONFIG3(0), MAX6639_FAN_CONFIG3_PWM_FREQ, ++ MAX6639_FAN_CONFIG3_PWM_FREQ_OFFSET) ++max6639_attr(fan2_pwm_freq, MAX6639_REG_FAN_CONFIG3(1), MAX6639_FAN_CONFIG3_PWM_FREQ, ++ MAX6639_FAN_CONFIG3_PWM_FREQ_OFFSET) ++ ++max6639_attr(fan1_ppr_count, MAX6639_REG_FAN_PPR(0), MAX6639_FAN_PPR_COUNT, ++ MAX6639_FAN_PPR_COUNT_OFFSET) ++max6639_attr(fan2_ppr_count, MAX6639_REG_FAN_PPR(1), MAX6639_FAN_PPR_COUNT, ++ MAX6639_FAN_PPR_COUNT_OFFSET) ++max6639_attr(fan1_tach_min, MAX6639_REG_FAN_PPR(0), MAX6639_FAN_PPR_TACH_MIN, ++ MAX6639_FAN_PPR_TACH_MIN_OFFSET) ++max6639_attr(fan2_tach_min, MAX6639_REG_FAN_PPR(1), MAX6639_FAN_PPR_TACH_MIN, ++ MAX6639_FAN_PPR_TACH_MIN_OFFSET) ++ ++max6639_attr(fan1_cnt_target, MAX6639_REG_TARGET_CNT(0), MAX6639_FAN_TARGET_CNT, ++ MAX6639_FAN_TARGET_CNT_OFFSET) ++max6639_attr(fan2_cnt_target, MAX6639_REG_TARGET_CNT(1), MAX6639_FAN_TARGET_CNT, ++ MAX6639_FAN_TARGET_CNT_OFFSET) ++ ++max6639_attr(fan1_cnt, MAX6639_REG_FAN_CNT(0), MAX6639_FAN_CNT, ++ MAX6639_FAN_CNT_OFFSET) ++max6639_attr(fan2_cnt, MAX6639_REG_FAN_CNT(1), MAX6639_FAN_CNT, ++ MAX6639_FAN_CNT_OFFSET) ++ ++/*Puneet end */ + static ssize_t show_temp_input(struct device *dev, + struct device_attribute *dev_attr, char *buf) + { +@@ -326,14 +672,27 @@ static ssize_t set_pwm(struct device *dev, + static ssize_t show_fan_input(struct device *dev, + struct device_attribute *dev_attr, char *buf) + { ++ struct i2c_client *client = to_i2c_client(dev); + struct max6639_data *data = max6639_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); ++ int conf, range, input; + + if (IS_ERR(data)) + return PTR_ERR(data); ++ mutex_lock(&data->update_lock); ++ conf = i2c_smbus_read_byte_data(client, MAX6639_REG_FAN_CONFIG1(attr->index)); ++ input = i2c_smbus_read_byte_data(client, MAX6639_REG_FAN_CNT(attr->index)); ++ mutex_unlock(&data->update_lock); ++ if (conf < 0) ++ return conf; ++ ++ if (input < 0) ++ return input; ++ ++ range = (conf & MAX6639_FAN_CONFIG1_RPM_RANGE) >> ++ MAX6639_FAN_CONFIG1_RPM_RANGE_OFFSET; + +- return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index], +- data->rpm_range)); ++ return sprintf(buf, "%d\n", FAN_FROM_REG(input, range)); + } + + static ssize_t show_alarm(struct device *dev, +@@ -401,6 +760,55 @@ static struct attribute *max6639_attributes[] = { + &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_emergency_alarm.dev_attr.attr, ++ &sensor_dev_attr_standby.dev_attr.attr, ++ &sensor_dev_attr_por.dev_attr.attr, ++ &sensor_dev_attr_disable_smbus_timeout.dev_attr.attr, ++ &sensor_dev_attr_ch2_local.dev_attr.attr, ++ &sensor_dev_attr_pwm_freq_hi.dev_attr.attr, ++ &sensor_dev_attr_ch1_alert_disable.dev_attr.attr, ++ &sensor_dev_attr_ch2_alert_disable.dev_attr.attr, ++ &sensor_dev_attr_ch1_ot_disable.dev_attr.attr, ++ &sensor_dev_attr_ch2_ot_disable.dev_attr.attr, ++ &sensor_dev_attr_ch1_therm_disable.dev_attr.attr, ++ &sensor_dev_attr_ch2_therm_disable.dev_attr.attr, ++ &sensor_dev_attr_fan1_fault_enable.dev_attr.attr, ++ &sensor_dev_attr_fan2_fault_enable.dev_attr.attr, ++ &sensor_dev_attr_fan1_pwm_mode.dev_attr.attr, ++ &sensor_dev_attr_fan2_pwm_mode.dev_attr.attr, ++ &sensor_dev_attr_fan1_duty.dev_attr.attr, ++ &sensor_dev_attr_fan2_duty.dev_attr.attr, ++ &sensor_dev_attr_fan1_temp_ch.dev_attr.attr, ++ &sensor_dev_attr_fan2_temp_ch.dev_attr.attr, ++ &sensor_dev_attr_fan1_rpm_range.dev_attr.attr, ++ &sensor_dev_attr_fan2_rpm_range.dev_attr.attr, ++ &sensor_dev_attr_fan1_rpm_step_size_a.dev_attr.attr, ++ &sensor_dev_attr_fan2_rpm_step_size_a.dev_attr.attr, ++ &sensor_dev_attr_fan1_rpm_step_size_b.dev_attr.attr, ++ &sensor_dev_attr_fan2_rpm_step_size_b.dev_attr.attr, ++ &sensor_dev_attr_fan1_temp_step_size.dev_attr.attr, ++ &sensor_dev_attr_fan2_temp_step_size.dev_attr.attr, ++ &sensor_dev_attr_fan1_rpm_start_step_b.dev_attr.attr, ++ &sensor_dev_attr_fan2_rpm_start_step_b.dev_attr.attr, ++ &sensor_dev_attr_fan1_spinup_disable.dev_attr.attr, ++ &sensor_dev_attr_fan2_spinup_disable.dev_attr.attr, ++ &sensor_dev_attr_fan1_therm_full_speed_enable.dev_attr.attr, ++ &sensor_dev_attr_fan2_therm_full_speed_enable.dev_attr.attr, ++ &sensor_dev_attr_fan1_pulse_stretch_disable.dev_attr.attr, ++ &sensor_dev_attr_fan2_pulse_stretch_disable.dev_attr.attr, ++ &sensor_dev_attr_fan1_pwm_freq.dev_attr.attr, ++ &sensor_dev_attr_fan2_pwm_freq.dev_attr.attr, ++ &sensor_dev_attr_fan1_ppr_count.dev_attr.attr, ++ &sensor_dev_attr_fan2_ppr_count.dev_attr.attr, ++ &sensor_dev_attr_fan1_tach_min.dev_attr.attr, ++ &sensor_dev_attr_fan2_tach_min.dev_attr.attr, ++ &sensor_dev_attr_fan1_cnt_target.dev_attr.attr, ++ &sensor_dev_attr_fan2_cnt_target.dev_attr.attr, ++ &sensor_dev_attr_fan1_cnt.dev_attr.attr, ++ &sensor_dev_attr_fan2_cnt.dev_attr.attr, ++ &sensor_dev_attr_pwm1_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm2_enable.dev_attr.attr, ++ &sensor_dev_attr_fan1_target.dev_attr.attr, ++ &sensor_dev_attr_fan2_target.dev_attr.attr, + NULL + }; + +diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c +new file mode 100644 +index 0000000..b567828 +--- /dev/null ++++ b/drivers/hwmon/max6697.c +@@ -0,0 +1,702 @@ ++/* ++ * Copyright (c) 2012 Guenter Roeck ++ * ++ * based on max1668.c ++ * Copyright (c) 2011 David George ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU 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 ++ ++enum chips { max6581, max6602, max6622, max6636, max6689, max6693, max6694, ++ max6697, max6698, max6699 }; ++ ++/* Report local sensor as temp1 */ ++ ++static const u8 MAX6697_REG_TEMP[] = { ++ 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08 }; ++static const u8 MAX6697_REG_TEMP_EXT[] = { ++ 0x57, 0x09, 0x52, 0x53, 0x54, 0x55, 0x56, 0 }; ++static const u8 MAX6697_REG_MAX[] = { ++ 0x17, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x18 }; ++static const u8 MAX6697_REG_CRIT[] = { ++ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27 }; ++ ++/* ++ * Map device tree / platform data register bit map to chip bit map. ++ * Applies to alert register and over-temperature register. ++ */ ++#define MAX6697_MAP_BITS(reg) ((((reg) & 0x7e) >> 1) | \ ++ (((reg) & 0x01) << 6) | ((reg) & 0x80)) ++ ++#define MAX6697_REG_STAT(n) (0x44 + (n)) ++ ++#define MAX6697_REG_CONFIG 0x41 ++#define MAX6581_CONF_EXTENDED (1 << 1) ++#define MAX6693_CONF_BETA (1 << 2) ++#define MAX6697_CONF_RESISTANCE (1 << 3) ++#define MAX6697_CONF_TIMEOUT (1 << 5) ++#define MAX6697_REG_ALERT_MASK 0x42 ++#define MAX6697_REG_OVERT_MASK 0x43 ++ ++#define MAX6581_REG_RESISTANCE 0x4a ++#define MAX6581_REG_IDEALITY 0x4b ++#define MAX6581_REG_IDEALITY_SELECT 0x4c ++#define MAX6581_REG_OFFSET 0x4d ++#define MAX6581_REG_OFFSET_SELECT 0x4e ++ ++#define MAX6697_CONV_TIME 156 /* ms per channel, worst case */ ++ ++struct max6697_chip_data { ++ int channels; ++ u32 have_ext; ++ u32 have_crit; ++ u32 have_fault; ++ u8 valid_conf; ++ const u8 *alarm_map; ++}; ++ ++struct max6697_data { ++ struct device *hwmon_dev; ++ ++ enum chips type; ++ const struct max6697_chip_data *chip; ++ ++ int update_interval; /* in milli-seconds */ ++ int temp_offset; /* in degrees C */ ++ ++ struct mutex update_lock; ++ unsigned long last_updated; /* In jiffies */ ++ bool valid; /* true if following fields are valid */ ++ ++ /* 1x local and up to 7x remote */ ++ u8 temp[8][4]; /* [nr][0]=temp [1]=ext [2]=max [3]=crit */ ++#define MAX6697_TEMP_INPUT 0 ++#define MAX6697_TEMP_EXT 1 ++#define MAX6697_TEMP_MAX 2 ++#define MAX6697_TEMP_CRIT 3 ++ u32 alarms; ++}; ++ ++/* Diode fault status bits on MAX6581 are right shifted by one bit */ ++static const u8 max6581_alarm_map[] = { ++ 0, 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, ++ 16, 17, 18, 19, 20, 21, 22, 23 }; ++ ++static const struct max6697_chip_data max6697_chip_data[] = { ++ [max6581] = { ++ .channels = 8, ++ .have_crit = 0xff, ++ .have_ext = 0x7f, ++ .have_fault = 0xfe, ++ .valid_conf = MAX6581_CONF_EXTENDED | MAX6697_CONF_TIMEOUT, ++ .alarm_map = max6581_alarm_map, ++ }, ++ [max6602] = { ++ .channels = 5, ++ .have_crit = 0x12, ++ .have_ext = 0x02, ++ .have_fault = 0x1e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++ [max6622] = { ++ .channels = 5, ++ .have_crit = 0x12, ++ .have_ext = 0x02, ++ .have_fault = 0x1e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++ [max6636] = { ++ .channels = 7, ++ .have_crit = 0x72, ++ .have_ext = 0x02, ++ .have_fault = 0x7e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++ [max6689] = { ++ .channels = 7, ++ .have_crit = 0x72, ++ .have_ext = 0x02, ++ .have_fault = 0x7e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++ [max6693] = { ++ .channels = 7, ++ .have_crit = 0x72, ++ .have_ext = 0x02, ++ .have_fault = 0x7e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6693_CONF_BETA | ++ MAX6697_CONF_TIMEOUT, ++ }, ++ [max6694] = { ++ .channels = 5, ++ .have_crit = 0x12, ++ .have_ext = 0x02, ++ .have_fault = 0x1e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6693_CONF_BETA | ++ MAX6697_CONF_TIMEOUT, ++ }, ++ [max6697] = { ++ .channels = 7, ++ .have_crit = 0x72, ++ .have_ext = 0x02, ++ .have_fault = 0x7e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++ [max6698] = { ++ .channels = 7, ++ .have_crit = 0x72, ++ .have_ext = 0x02, ++ .have_fault = 0x0e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++ [max6699] = { ++ .channels = 5, ++ .have_crit = 0x12, ++ .have_ext = 0x02, ++ .have_fault = 0x1e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++}; ++ ++static struct max6697_data *max6697_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6697_data *data = i2c_get_clientdata(client); ++ struct max6697_data *ret = data; ++ int val; ++ int i; ++ u32 alarms; ++ ++ mutex_lock(&data->update_lock); ++ ++ if (data->valid && ++ !time_after(jiffies, data->last_updated ++ + msecs_to_jiffies(data->update_interval))) ++ goto abort; ++ ++ for (i = 0; i < data->chip->channels; i++) { ++ if (data->chip->have_ext & (1 << i)) { ++ val = i2c_smbus_read_byte_data(client, ++ MAX6697_REG_TEMP_EXT[i]); ++ if (unlikely(val < 0)) { ++ ret = ERR_PTR(val); ++ goto abort; ++ } ++ data->temp[i][MAX6697_TEMP_EXT] = val; ++ } ++ ++ val = i2c_smbus_read_byte_data(client, MAX6697_REG_TEMP[i]); ++ if (unlikely(val < 0)) { ++ ret = ERR_PTR(val); ++ goto abort; ++ } ++ data->temp[i][MAX6697_TEMP_INPUT] = val; ++ ++ val = i2c_smbus_read_byte_data(client, MAX6697_REG_MAX[i]); ++ if (unlikely(val < 0)) { ++ ret = ERR_PTR(val); ++ goto abort; ++ } ++ data->temp[i][MAX6697_TEMP_MAX] = val; ++ ++ if (data->chip->have_crit & (1 << i)) { ++ val = i2c_smbus_read_byte_data(client, ++ MAX6697_REG_CRIT[i]); ++ if (unlikely(val < 0)) { ++ ret = ERR_PTR(val); ++ goto abort; ++ } ++ data->temp[i][MAX6697_TEMP_CRIT] = val; ++ } ++ } ++ ++ alarms = 0; ++ for (i = 0; i < 3; i++) { ++ val = i2c_smbus_read_byte_data(client, MAX6697_REG_STAT(i)); ++ if (unlikely(val < 0)) { ++ ret = ERR_PTR(val); ++ goto abort; ++ } ++ alarms = (alarms << 8) | val; ++ } ++ data->alarms = alarms; ++ data->last_updated = jiffies; ++ data->valid = true; ++abort: ++ mutex_unlock(&data->update_lock); ++ ++ return ret; ++} ++ ++static ssize_t show_temp_input(struct device *dev, ++ struct device_attribute *devattr, char *buf) ++{ ++ int index = to_sensor_dev_attr(devattr)->index; ++ struct max6697_data *data = max6697_update_device(dev); ++ int temp; ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ ++ temp = (data->temp[index][MAX6697_TEMP_INPUT] - data->temp_offset) << 3; ++ temp |= data->temp[index][MAX6697_TEMP_EXT] >> 5; ++ ++ return sprintf(buf, "%d\n", temp * 125); ++} ++ ++static ssize_t show_temp(struct device *dev, ++ struct device_attribute *devattr, char *buf) ++{ ++ int nr = to_sensor_dev_attr_2(devattr)->nr; ++ int index = to_sensor_dev_attr_2(devattr)->index; ++ struct max6697_data *data = max6697_update_device(dev); ++ int temp; ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ ++ temp = data->temp[nr][index]; ++ temp -= data->temp_offset; ++ ++ return sprintf(buf, "%d\n", temp * 1000); ++} ++ ++static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ int index = to_sensor_dev_attr(attr)->index; ++ struct max6697_data *data = max6697_update_device(dev); ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ ++ if (data->chip->alarm_map) ++ index = data->chip->alarm_map[index]; ++ ++ return sprintf(buf, "%u\n", (data->alarms >> index) & 0x1); ++} ++ ++static ssize_t set_temp(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ int nr = to_sensor_dev_attr_2(devattr)->nr; ++ int index = to_sensor_dev_attr_2(devattr)->index; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6697_data *data = i2c_get_clientdata(client); ++ long temp; ++ int ret; ++ ++ ret = kstrtol(buf, 10, &temp); ++ if (ret < 0) ++ return ret; ++ ++ mutex_lock(&data->update_lock); ++ temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset; ++ temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127); ++ data->temp[nr][index] = temp; ++ ret = i2c_smbus_write_byte_data(client, ++ index == 2 ? MAX6697_REG_MAX[nr] ++ : MAX6697_REG_CRIT[nr], ++ temp); ++ mutex_unlock(&data->update_lock); ++ ++ return ret < 0 ? ret : count; ++} ++ ++static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); ++static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 0, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 0, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1); ++static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 1, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 1, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2); ++static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 2, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 2, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3); ++static SENSOR_DEVICE_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 3, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 3, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4); ++static SENSOR_DEVICE_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 4, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 4, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5); ++static SENSOR_DEVICE_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 5, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 5, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp_input, NULL, 6); ++static SENSOR_DEVICE_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 6, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 6, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp_input, NULL, 7); ++static SENSOR_DEVICE_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 7, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 7, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 22); ++static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 16); ++static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 17); ++static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 18); ++static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL, 19); ++static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO, show_alarm, NULL, 20); ++static SENSOR_DEVICE_ATTR(temp7_max_alarm, S_IRUGO, show_alarm, NULL, 21); ++static SENSOR_DEVICE_ATTR(temp8_max_alarm, S_IRUGO, show_alarm, NULL, 23); ++ ++static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); ++static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8); ++static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 9); ++static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 10); ++static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, show_alarm, NULL, 11); ++static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO, show_alarm, NULL, 12); ++static SENSOR_DEVICE_ATTR(temp7_crit_alarm, S_IRUGO, show_alarm, NULL, 13); ++static SENSOR_DEVICE_ATTR(temp8_crit_alarm, S_IRUGO, show_alarm, NULL, 15); ++ ++static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 1); ++static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2); ++static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 3); ++static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_alarm, NULL, 5); ++static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_alarm, NULL, 6); ++static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_alarm, NULL, 7); ++ ++static DEVICE_ATTR(dummy, 0, NULL, NULL); ++ ++static mode_t max6697_is_visible(struct kobject *kobj, struct attribute *attr, ++ int index) ++{ ++ struct device *dev = container_of(kobj, struct device, kobj); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6697_data *data = i2c_get_clientdata(client); ++ const struct max6697_chip_data *chip = data->chip; ++ int channel = index / 6; /* channel number */ ++ int nr = index % 6; /* attribute index within channel */ ++ ++ if (channel >= chip->channels) ++ return 0; ++ ++ if ((nr == 3 || nr == 4) && !(chip->have_crit & (1 << channel))) ++ return 0; ++ if (nr == 5 && !(chip->have_fault & (1 << channel))) ++ return 0; ++ ++ return attr->mode; ++} ++ ++/* ++ * max6697_is_visible uses the index into the following array to determine ++ * if attributes should be created or not. Any change in order or content ++ * must be matched in max6697_is_visible. ++ */ ++static struct attribute *max6697_attributes[] = { ++ &sensor_dev_attr_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_temp1_max.dev_attr.attr, ++ &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp1_crit.dev_attr.attr, ++ &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, ++ &dev_attr_dummy.attr, ++ ++ &sensor_dev_attr_temp2_input.dev_attr.attr, ++ &sensor_dev_attr_temp2_max.dev_attr.attr, ++ &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp2_crit.dev_attr.attr, ++ &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp2_fault.dev_attr.attr, ++ ++ &sensor_dev_attr_temp3_input.dev_attr.attr, ++ &sensor_dev_attr_temp3_max.dev_attr.attr, ++ &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp3_crit.dev_attr.attr, ++ &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp3_fault.dev_attr.attr, ++ ++ &sensor_dev_attr_temp4_input.dev_attr.attr, ++ &sensor_dev_attr_temp4_max.dev_attr.attr, ++ &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp4_crit.dev_attr.attr, ++ &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp4_fault.dev_attr.attr, ++ ++ &sensor_dev_attr_temp5_input.dev_attr.attr, ++ &sensor_dev_attr_temp5_max.dev_attr.attr, ++ &sensor_dev_attr_temp5_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp5_crit.dev_attr.attr, ++ &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp5_fault.dev_attr.attr, ++ ++ &sensor_dev_attr_temp6_input.dev_attr.attr, ++ &sensor_dev_attr_temp6_max.dev_attr.attr, ++ &sensor_dev_attr_temp6_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp6_crit.dev_attr.attr, ++ &sensor_dev_attr_temp6_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp6_fault.dev_attr.attr, ++ ++ &sensor_dev_attr_temp7_input.dev_attr.attr, ++ &sensor_dev_attr_temp7_max.dev_attr.attr, ++ &sensor_dev_attr_temp7_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp7_crit.dev_attr.attr, ++ &sensor_dev_attr_temp7_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp7_fault.dev_attr.attr, ++ ++ &sensor_dev_attr_temp8_input.dev_attr.attr, ++ &sensor_dev_attr_temp8_max.dev_attr.attr, ++ &sensor_dev_attr_temp8_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp8_crit.dev_attr.attr, ++ &sensor_dev_attr_temp8_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp8_fault.dev_attr.attr, ++ NULL ++}; ++ ++static const struct attribute_group max6697_group = { ++ .attrs = max6697_attributes, .is_visible = max6697_is_visible, ++}; ++ ++static void max6697_get_config_of(struct device_node *node, ++ struct max6697_platform_data *pdata) ++{ ++ int len; ++ const __be32 *prop; ++ ++ prop = of_get_property(node, "smbus-timeout-disable", &len); ++ if (prop) ++ pdata->smbus_timeout_disable = true; ++ prop = of_get_property(node, "extended-range-enable", &len); ++ if (prop) ++ pdata->extended_range_enable = true; ++ prop = of_get_property(node, "beta-compensation-enable", &len); ++ if (prop) ++ pdata->beta_compensation = true; ++ prop = of_get_property(node, "alert-mask", &len); ++ if (prop && len == sizeof(u32)) ++ pdata->alert_mask = be32_to_cpu(prop[0]); ++ prop = of_get_property(node, "over-temperature-mask", &len); ++ if (prop && len == sizeof(u32)) ++ pdata->over_temperature_mask = be32_to_cpu(prop[0]); ++ prop = of_get_property(node, "resistance-cancellation", &len); ++ if (prop) { ++ if (len == sizeof(u32)) ++ pdata->resistance_cancellation = be32_to_cpu(prop[0]); ++ else ++ pdata->resistance_cancellation = 0xfe; ++ } ++ prop = of_get_property(node, "transistor-ideality", &len); ++ if (prop && len == 2 * sizeof(u32)) { ++ pdata->ideality_mask = be32_to_cpu(prop[0]); ++ pdata->ideality_value = be32_to_cpu(prop[1]); ++ } ++} ++ ++static int max6697_init_chip(struct i2c_client *client) ++{ ++ struct max6697_data *data = i2c_get_clientdata(client); ++ struct max6697_platform_data *pdata = dev_get_platdata(&client->dev); ++ struct max6697_platform_data p; ++ const struct max6697_chip_data *chip = data->chip; ++ int factor = chip->channels; ++ int ret, reg; ++ ++ /* ++ * Don't touch configuration if neither platform data nor OF ++ * configuration was specified. If that is the case, use the ++ * current chip configuration. ++ */ ++ if (!pdata && !client->dev.of_node) { ++ reg = i2c_smbus_read_byte_data(client, MAX6697_REG_CONFIG); ++ if (reg < 0) ++ return reg; ++ if (data->type == max6581) { ++ if (reg & MAX6581_CONF_EXTENDED) ++ data->temp_offset = 64; ++ reg = i2c_smbus_read_byte_data(client, ++ MAX6581_REG_RESISTANCE); ++ if (reg < 0) ++ return reg; ++ factor += hweight8(reg); ++ } else { ++ if (reg & MAX6697_CONF_RESISTANCE) ++ factor++; ++ } ++ goto done; ++ } ++ ++ if (client->dev.of_node) { ++ memset(&p, 0, sizeof(p)); ++ max6697_get_config_of(client->dev.of_node, &p); ++ pdata = &p; ++ } ++ ++ reg = 0; ++ if (pdata->smbus_timeout_disable && ++ (chip->valid_conf & MAX6697_CONF_TIMEOUT)) { ++ reg |= MAX6697_CONF_TIMEOUT; ++ } ++ if (pdata->extended_range_enable && ++ (chip->valid_conf & MAX6581_CONF_EXTENDED)) { ++ reg |= MAX6581_CONF_EXTENDED; ++ data->temp_offset = 64; ++ } ++ if (pdata->resistance_cancellation && ++ (chip->valid_conf & MAX6697_CONF_RESISTANCE)) { ++ reg |= MAX6697_CONF_RESISTANCE; ++ factor++; ++ } ++ if (pdata->beta_compensation && ++ (chip->valid_conf & MAX6693_CONF_BETA)) { ++ reg |= MAX6693_CONF_BETA; ++ } ++ ++ ret = i2c_smbus_write_byte_data(client, MAX6697_REG_CONFIG, reg); ++ if (ret < 0) ++ return ret; ++ ++ ret = i2c_smbus_write_byte_data(client, MAX6697_REG_ALERT_MASK, ++ MAX6697_MAP_BITS(pdata->alert_mask)); ++ if (ret < 0) ++ return ret; ++ ++ ret = i2c_smbus_write_byte_data(client, MAX6697_REG_OVERT_MASK, ++ MAX6697_MAP_BITS(pdata->over_temperature_mask)); ++ if (ret < 0) ++ return ret; ++ ++ if (data->type == max6581) { ++ factor += hweight8(pdata->resistance_cancellation >> 1); ++ ret = i2c_smbus_write_byte_data(client, MAX6581_REG_RESISTANCE, ++ pdata->resistance_cancellation >> 1); ++ if (ret < 0) ++ return ret; ++ ret = i2c_smbus_write_byte_data(client, MAX6581_REG_IDEALITY, ++ pdata->ideality_value); ++ if (ret < 0) ++ return ret; ++ ret = i2c_smbus_write_byte_data(client, ++ MAX6581_REG_IDEALITY_SELECT, ++ pdata->ideality_mask >> 1); ++ if (ret < 0) ++ return ret; ++ } ++done: ++ data->update_interval = factor * MAX6697_CONV_TIME; ++ return 0; ++} ++ ++static int max6697_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct i2c_adapter *adapter = client->adapter; ++ struct device *dev = &client->dev; ++ struct max6697_data *data; ++ int err; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) ++ return -ENODEV; ++ ++ data = devm_kzalloc(dev, sizeof(struct max6697_data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ data->type = id->driver_data; ++ data->chip = &max6697_chip_data[data->type]; ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->update_lock); ++ ++ err = max6697_init_chip(client); ++ if (err) ++ return err; ++ ++ err = sysfs_create_group(&client->dev.kobj, &max6697_group); ++ if (err) ++ return err; ++ ++ data->hwmon_dev = hwmon_device_register(dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ err = PTR_ERR(data->hwmon_dev); ++ goto error; ++ } ++ ++ return 0; ++ ++error: ++ sysfs_remove_group(&client->dev.kobj, &max6697_group); ++ return err; ++} ++ ++static int max6697_remove(struct i2c_client *client) ++{ ++ struct max6697_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &max6697_group); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id max6697_id[] = { ++ { "max6581", max6581 }, ++ { "max6602", max6602 }, ++ { "max6622", max6622 }, ++ { "max6636", max6636 }, ++ { "max6689", max6689 }, ++ { "max6693", max6693 }, ++ { "max6694", max6694 }, ++ { "max6697", max6697 }, ++ { "max6698", max6698 }, ++ { "max6699", max6699 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, max6697_id); ++ ++static struct i2c_driver max6697_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "max6697", ++ }, ++ .probe = max6697_probe, ++ .remove = max6697_remove, ++ .id_table = max6697_id, ++}; ++ ++module_i2c_driver(max6697_driver); ++ ++MODULE_AUTHOR("Guenter Roeck "); ++MODULE_DESCRIPTION("MAX6697 temperature sensor driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig +index 4b26f51..e549b09 100644 +--- a/drivers/hwmon/pmbus/Kconfig ++++ b/drivers/hwmon/pmbus/Kconfig +@@ -119,4 +119,34 @@ config SENSORS_ZL6100 + This driver can also be built as a module. If so, the module will + be called zl6100. + ++config SENSORS_DPS460 ++ tristate "Delta DPS460" ++ default n ++ help ++ If you say yes here you get hardware monitoring support for Delta ++ DPSXXX Power Supply. ++ ++ This driver can also be built as a module. If so, the module will ++ be called dps460. ++ ++config SENSORS_PS2471 ++ tristate "Lite-ON PS2471" ++ default n ++ help ++ If you say yes here you get hardware monitoring support for Lite ++ -ON PS2471. ++ ++ This driver can also be built as a module. If so, the module will ++ be called ps2471. ++ ++config SENSORS_CPR4011 ++ tristate "Compuware CPR4011 4M11/21" ++ default n ++ help ++ If you say yes here you get hardware monitoring support for Compuware ++ CPR4011 4M11/21 ++ ++ This driver can also be built as a module. If so, the module will ++ be called cpr4011. ++ + endif # PMBUS +diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile +index 789376c..85aeddf 100644 +--- a/drivers/hwmon/pmbus/Makefile ++++ b/drivers/hwmon/pmbus/Makefile +@@ -13,3 +13,6 @@ obj-$(CONFIG_SENSORS_MAX8688) += max8688.o + obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o + obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o + obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o ++obj-$(CONFIG_SENSORS_DPS460) += dps460.o ++obj-$(CONFIG_SENSORS_PS2471) += ps2471.o ++obj-$(CONFIG_SENSORS_CPR4011) += cpr4011.o +diff --git a/drivers/hwmon/pmbus/cpr4011.c b/drivers/hwmon/pmbus/cpr4011.c +new file mode 100644 +index 0000000..4cd976a +--- /dev/null ++++ b/drivers/hwmon/pmbus/cpr4011.c +@@ -0,0 +1,83 @@ ++/* ++ * Hardware monitoring driver for Compuware CPR-4011-4M11/21 ++ * ++ * Copyright (C) 2015 Cumulus Networks, LLC ++ * Author: Puneet Shenoy ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pmbus.h" ++ ++enum chips { cpr4011 }; ++ ++static int cpr4011_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct pmbus_driver_info *info; ++ int ret; ++ ++ if (!i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA)) { ++ pr_err("i2c check functionality failed\n"); ++ return -ENODEV; ++ } ++ info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ info->pages = 1; ++ info->func[0] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 | ++ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; ++ info->format[PSC_PWM] = linear; ++ ++ ret = pmbus_do_probe(client, id, info); ++ if (ret < 0) ++ kfree(info); ++ return ret; ++} ++ ++static int cpr4011_remove(struct i2c_client *client) ++{ ++ pmbus_do_remove(client); ++ return 0; ++} ++ ++static const struct i2c_device_id cpr4011_id[] = { ++ {"cpr4011", cpr4011}, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, cpr4011_id); ++ ++static struct i2c_driver cpr4011_driver = { ++ .driver = { .name = "cpr4011",}, ++ .probe = cpr4011_probe, ++ .remove = cpr4011_remove, ++ .id_table = cpr4011_id, ++}; ++ ++module_i2c_driver(cpr4011_driver); ++ ++MODULE_AUTHOR("Puneet Shenoy"); ++MODULE_DESCRIPTION("PMBus driver for Compuware CPR4011 4M11/21 Power Supply"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/pmbus/dps460.c b/drivers/hwmon/pmbus/dps460.c +new file mode 100644 +index 0000000..47a8ee6 +--- /dev/null ++++ b/drivers/hwmon/pmbus/dps460.c +@@ -0,0 +1,101 @@ ++/* ++ * Hardware monitoring driver for Delta DPSXXX Power Supplies ++ * ++ * Copyright (C) 2015 Cumulus Networks, LLC ++ * Author: Puneet Shenoy ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pmbus.h" ++ ++enum chips { dps460, dps200 }; ++ ++static int dps460_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct pmbus_driver_info *info; ++ int ret; ++ ++ if (!i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA | ++ I2C_FUNC_SMBUS_PEC)) ++ return -ENODEV; ++ ++ info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ /* Use only 1 page with 1 Fan, 2 Temps. */ ++ info->pages = 1; ++ info->func[0] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 | ++ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; ++ info->format[PSC_PWM] = linear; ++ ++ if ((i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) || ++ (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_BLOCK_DATA))) ++ info->func[0] |= PMBUS_HAVE_MFR_INFO; ++ ++ if (id->driver_data == dps200) { ++ info->format[PSC_VOLTAGE_OUT] = direct; ++ info->format[PSC_FAN] = linear; ++ } else if (id->driver_data == dps460) { ++ /* Needs PEC(PACKET ERROR CODE) for writes */ ++ client->flags = I2C_CLIENT_PEC; ++ } ++ ++ ret = pmbus_do_probe(client, id, info); ++ if (ret < 0) ++ kfree(info); ++ return ret; ++} ++ ++static int dps460_remove(struct i2c_client *client) ++{ ++ pmbus_do_remove(client); ++ return 0; ++} ++ ++static const struct i2c_device_id dps460_id[] = { ++ {"dps460", dps460}, ++ {"dps200", dps200}, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, dps460_id); ++ ++static struct i2c_driver dps460_driver = { ++ .driver = { ++ .name = "dps460", ++ }, ++ .probe = dps460_probe, ++ .remove = dps460_remove, ++ .id_table = dps460_id, ++}; ++ ++module_i2c_driver(dps460_driver); ++ ++MODULE_AUTHOR("Puneet Shenoy"); ++MODULE_DESCRIPTION("PMBus driver for Delta DPSXXX"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h +index 5d31d1c..48eb99c 100644 +--- a/drivers/hwmon/pmbus/pmbus.h ++++ b/drivers/hwmon/pmbus/pmbus.h +@@ -288,6 +288,7 @@ enum pmbus_sensor_classes { + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, ++ PSC_PWM, + PSC_NUM_CLASSES /* Number of power sensor classes */ + }; + +@@ -312,6 +313,7 @@ enum pmbus_sensor_classes { + #define PMBUS_HAVE_STATUS_TEMP (1 << 15) + #define PMBUS_HAVE_STATUS_FAN12 (1 << 16) + #define PMBUS_HAVE_STATUS_FAN34 (1 << 17) ++#define PMBUS_HAVE_MFR_INFO (1 << 18) + + enum pmbus_data_format { linear = 0, direct, vid }; + +diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c +index d89b339..60c846c 100644 +--- a/drivers/hwmon/pmbus/pmbus_core.c ++++ b/drivers/hwmon/pmbus/pmbus_core.c +@@ -62,6 +62,8 @@ + + #define PMBUS_MAX_INPUT_LABELS 4 /* vin, vcap, iin, pin */ + ++#define PMBUS_MFR_INFO_COUNT 6 /* Manufacturer info fields */ ++ + /* + * status, status_vout, status_iout, status_fans, status_fan34, and status_temp + * are paged. status_input is unpaged. +@@ -103,6 +105,11 @@ struct pmbus_label { + char label[PMBUS_NAME_SIZE]; /* label */ + }; + ++struct pmbus_mfr { ++ char name[PMBUS_NAME_SIZE]; /* sysfs mfr name */ ++ struct sensor_device_attribute attribute; ++}; ++ + struct pmbus_data { + struct device *hwmon_dev; + +@@ -138,6 +145,13 @@ struct pmbus_data { + int num_labels; + struct pmbus_label *labels; + ++ /* ++ * Manufacturer Info ++ */ ++ int max_mfrs; ++ int num_mfrs; ++ struct pmbus_mfr *mfrs; ++ + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ +@@ -445,6 +459,10 @@ static long pmbus_reg2data_linear(struct pmbus_data *data, + if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */ + exponent = data->exponent; + mantissa = (u16) sensor->data; ++ } else if (sensor->class == PSC_PWM) { ++ /* PWM has a duty cycle value from 0 to 100 */ ++ mantissa = (u16) sensor->data; ++ exponent = 0; + } else { /* LINEAR11 */ + exponent = ((s16)sensor->data) >> 11; + mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5; +@@ -452,6 +470,13 @@ static long pmbus_reg2data_linear(struct pmbus_data *data, + + val = mantissa; + ++ /* Map duty cycle 0 -> 100 to PWM range 0 -> 255 */ ++ if (sensor->class == PSC_PWM) { ++ val = (val * 255)/100; ++ val = SENSORS_LIMIT(val, 0, 255); ++ return val; ++ } ++ + /* scale result to milli-units for all sensors except fans */ + if (sensor->class != PSC_FAN) + val = val * 1000L; +@@ -558,6 +583,13 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data, + if (val == 0) + return 0; + ++ /* Map PWM range 0 -> 255 to duty cycle 0 -> 100 */ ++ if (class == PSC_PWM) { ++ val = (val * 100)/255; ++ SENSORS_LIMIT(val, 0, 100); ++ return val; ++ } ++ + if (class == PSC_VOLTAGE_OUT) { + /* LINEAR16 does not support negative voltages */ + if (val < 0) +@@ -769,6 +801,31 @@ static ssize_t pmbus_show_sensor(struct device *dev, + return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor)); + } + ++static ssize_t pmbus_show_mfr(struct device *dev, ++ struct device_attribute *da, ++ char *buf) { ++ struct i2c_client *client = to_i2c_client(dev); ++ int cmd = to_sensor_dev_attr(da)->index; ++ u8 b_buf[I2C_SMBUS_BLOCK_MAX + 1]; ++ int ret; ++ ++ if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_BLOCK_DATA)) ++ ret = i2c_smbus_read_block_data(client, cmd, b_buf); ++ else if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) ++ ret = i2c_smbus_read_i2c_block_data(client, cmd, ++ I2C_SMBUS_BLOCK_MAX, b_buf); ++ else ++ ret = -EIO; ++ ++ if (ret < 0) ++ return ret; ++ ++ b_buf[ret] = '\0'; ++ return sprintf(buf, "%s\n", b_buf); ++}; ++ + static ssize_t pmbus_set_sensor(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +@@ -846,6 +903,20 @@ static void pmbus_add_boolean(struct pmbus_data *data, + data->num_booleans++; + } + ++static void pmbus_add_mfr(struct pmbus_data *data, const char *name, ++ int idx) ++{ ++ struct pmbus_mfr *mfr; ++ ++ BUG_ON(data->num_mfrs >= data->max_mfrs); ++ ++ mfr = &data->mfrs[data->num_mfrs]; ++ ++ snprintf(mfr->name, sizeof(mfr->name), "%s", name); ++ PMBUS_ADD_GET_ATTR(data, mfr->name, mfr, idx); ++ data->num_mfrs++; ++} ++ + static void pmbus_add_boolean_reg(struct pmbus_data *data, + const char *name, const char *type, + int seq, int reg, int bit) +@@ -871,8 +942,12 @@ static void pmbus_add_sensor(struct pmbus_data *data, + BUG_ON(data->num_sensors >= data->max_sensors); + + sensor = &data->sensors[data->num_sensors]; +- snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s", +- name, seq, type); ++ if (!(strcmp("pwm", name))) ++ snprintf(sensor->name, sizeof(sensor->name), "%s%d", ++ name, seq); ++ else ++ snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s", ++ name, seq, type); + sensor->page = page; + sensor->reg = reg; + sensor->class = class; +@@ -914,11 +989,12 @@ static void pmbus_find_max_attr(struct i2c_client *client, + struct pmbus_data *data) + { + const struct pmbus_driver_info *info = data->info; +- int page, max_sensors, max_booleans, max_labels; ++ int page, max_sensors, max_booleans, max_labels, max_mfrs; + + max_sensors = PMBUS_MAX_INPUT_SENSORS; + max_booleans = PMBUS_MAX_INPUT_BOOLEANS; + max_labels = PMBUS_MAX_INPUT_LABELS; ++ max_mfrs = 0; + + for (page = 0; page < info->pages; page++) { + if (info->func[page] & PMBUS_HAVE_VOUT) { +@@ -957,10 +1033,15 @@ static void pmbus_find_max_attr(struct i2c_client *client, + max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP; + } + } ++ if (info->func[0] & PMBUS_HAVE_MFR_INFO) ++ max_mfrs = PMBUS_MFR_INFO_COUNT; ++ + data->max_sensors = max_sensors; + data->max_booleans = max_booleans; + data->max_labels = max_labels; +- data->max_attributes = max_sensors + max_booleans + max_labels; ++ data->max_mfrs = max_mfrs; ++ data->max_attributes = max_sensors + max_booleans + \ ++ max_labels + max_mfrs; + } + + /* +@@ -1512,6 +1593,13 @@ static const int pmbus_fan_config_registers[] = { + PMBUS_FAN_CONFIG_34 + }; + ++static const int pmbus_fan_cmd_registers[] = { ++ PMBUS_FAN_COMMAND_1, ++ PMBUS_FAN_COMMAND_2, ++ PMBUS_FAN_COMMAND_3, ++ PMBUS_FAN_COMMAND_4, ++}; ++ + static const int pmbus_fan_status_registers[] = { + PMBUS_STATUS_FAN_12, + PMBUS_STATUS_FAN_12, +@@ -1568,6 +1656,9 @@ static void pmbus_add_fan_attributes(struct i2c_client *client, + pmbus_add_sensor(data, "fan", "input", index, page, + pmbus_fan_registers[f], PSC_FAN, true, + true); ++ pmbus_add_sensor(data, "pwm", "", index, page, ++ pmbus_fan_cmd_registers[f], PSC_PWM, ++ true, false); + + /* + * Each fan status register covers multiple fans, +@@ -1594,6 +1685,23 @@ static void pmbus_add_fan_attributes(struct i2c_client *client, + } + } + ++/* Manufacturer Info */ ++static void pmbus_add_mfr_attributes(struct i2c_client *client, ++ struct pmbus_data *data) ++{ ++ const struct pmbus_driver_info *info = data->info; ++ ++ /* Only Read Page 0 mfr info */ ++ if (info->func[0] & PMBUS_HAVE_MFR_INFO) { ++ pmbus_add_mfr(data, "mfr_id", PMBUS_MFR_ID); ++ pmbus_add_mfr(data, "mfr_model", PMBUS_MFR_MODEL); ++ pmbus_add_mfr(data, "mfr_revision", PMBUS_MFR_REVISION); ++ pmbus_add_mfr(data, "mfr_location", PMBUS_MFR_LOCATION); ++ pmbus_add_mfr(data, "mfr_date", PMBUS_MFR_DATE); ++ pmbus_add_mfr(data, "mfr_serial", PMBUS_MFR_SERIAL); ++ } ++} ++ + static void pmbus_find_attributes(struct i2c_client *client, + struct pmbus_data *data) + { +@@ -1615,6 +1723,9 @@ static void pmbus_find_attributes(struct i2c_client *client, + + /* Fans */ + pmbus_add_fan_attributes(client, data); ++ ++ /* Manufacturer Info */ ++ pmbus_add_mfr_attributes(client, data); + } + + /* +@@ -1741,6 +1852,13 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + goto out_booleans; + } + ++ data->mfrs = kzalloc(sizeof(struct pmbus_mfr) * data->max_mfrs, ++ GFP_KERNEL); ++ if (!data->mfrs) { ++ dev_err(&client->dev, "No memory to allocate mfr data\n"); ++ goto out_mfrs; ++ } ++ + data->attributes = kzalloc(sizeof(struct attribute *) + * data->max_attributes, GFP_KERNEL); + if (!data->attributes) { +@@ -1779,6 +1897,8 @@ out_hwmon_device_register: + sysfs_remove_group(&client->dev.kobj, &data->group); + out_attributes: + kfree(data->attributes); ++out_mfrs: ++ kfree(data->mfrs); + out_labels: + kfree(data->labels); + out_booleans: +@@ -1797,6 +1917,7 @@ void pmbus_do_remove(struct i2c_client *client) + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->group); + kfree(data->attributes); ++ kfree(data->mfrs); + kfree(data->labels); + kfree(data->booleans); + kfree(data->sensors); +diff --git a/drivers/hwmon/pmbus/ps2471.c b/drivers/hwmon/pmbus/ps2471.c +new file mode 100644 +index 0000000..a1ce238 +--- /dev/null ++++ b/drivers/hwmon/pmbus/ps2471.c +@@ -0,0 +1,89 @@ ++/* ++ * Hardware monitoring driver for Lite-ON PS2471 Power Supply ++ * ++ * Copyright (C) 2015 Cumulus Networks, LLC ++ * Author: Puneet Shenoy ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pmbus.h" ++ ++enum chips { ps2471 }; ++ ++static int ps2471_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct pmbus_driver_info *info; ++ int ret; ++ ++ if (!i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA)) { ++ pr_err("i2c check functionality failed\n"); ++ return -ENODEV; ++ } ++ info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ info->pages = 1; ++ info->func[0] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 | ++ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; ++ info->format[PSC_PWM] = linear; ++ ++ if ((i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) || ++ (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_BLOCK_DATA))) ++ info->func[0] |= PMBUS_HAVE_MFR_INFO; ++ ++ ret = pmbus_do_probe(client, id, info); ++ if (ret < 0) ++ kfree(info); ++ return ret; ++} ++ ++static int ps2471_remove(struct i2c_client *client) ++{ ++ pmbus_do_remove(client); ++ return 0; ++} ++ ++static const struct i2c_device_id ps2471_id[] = { ++ {"ps2471", ps2471}, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, ps2471_id); ++ ++static struct i2c_driver ps2471_driver = { ++ .driver = { .name = "ps2471",}, ++ .probe = ps2471_probe, ++ .remove = ps2471_remove, ++ .id_table = ps2471_id, ++}; ++ ++module_i2c_driver(ps2471_driver); ++ ++MODULE_AUTHOR("Puneet Shenoy"); ++MODULE_DESCRIPTION("PMBus driver for Lite-ON PS2471 Power Supply"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c +index 8eac67d..8689664 100644 +--- a/drivers/hwmon/via-cputemp.c ++++ b/drivers/hwmon/via-cputemp.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + + #define DRVNAME "via_cputemp" + +@@ -308,15 +309,20 @@ static struct notifier_block via_cputemp_cpu_notifier __refdata = { + .notifier_call = via_cputemp_cpu_callback, + }; + ++static const struct x86_cpu_id cputemp_ids[] = { ++ { X86_VENDOR_CENTAUR, 6, 0xa, }, /* C7 A */ ++ { X86_VENDOR_CENTAUR, 6, 0xd, }, /* C7 D */ ++ { X86_VENDOR_CENTAUR, 6, 0xf, }, /* Nano */ ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, cputemp_ids); ++ + static int __init via_cputemp_init(void) + { + int i, err; + +- if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) { +- printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n"); +- err = -ENODEV; +- goto exit; +- } ++ if (!x86_match_cpu(cputemp_ids)) ++ return -ENODEV; + + err = platform_driver_register(&via_cputemp_driver); + if (err) +diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c +index 24f94f4..acba1c6 100644 +--- a/drivers/i2c/algos/i2c-algo-bit.c ++++ b/drivers/i2c/algos/i2c-algo-bit.c +@@ -616,10 +616,11 @@ static u32 bit_func(struct i2c_adapter *adap) + + /* -----exported algorithm data: ------------------------------------- */ + +-static const struct i2c_algorithm i2c_bit_algo = { ++const struct i2c_algorithm i2c_bit_algo = { + .master_xfer = bit_xfer, + .functionality = bit_func, + }; ++EXPORT_SYMBOL(i2c_bit_algo); + + /* + * registering functions to load algorithms at runtime +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index 949ea64..36756f8 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -120,6 +120,16 @@ config I2C_ISCH + This driver can also be built as a module. If so, the module + will be called i2c-isch. + ++config I2C_ISMT ++ tristate "Intel iSMT SMBus Controller" ++ depends on PCI && X86 ++ help ++ If you say yes to this option, support will be included for the Intel ++ iSMT SMBus host controller interface. ++ ++ This driver can also be built as a module. If so, the module will be ++ called i2c-ismt. ++ + config I2C_PIIX4 + tristate "Intel PIIX4 and compatible (ATI/AMD/Serverworks/Broadcom/SMSC)" + depends on PCI +@@ -330,6 +340,17 @@ config I2C_BLACKFIN_TWI_CLK_KHZ + help + The unit of the TWI clock is kHz. + ++config I2C_CEL_CPLD ++ tristate "Celestica CPLD I2C Driver" ++ depends on CEL_REDSTONE ++ help ++ If you say yes to this option, support will be included for ++ the Celestica CPLD I2C interface. This interface is for ++ interacting with SFP+ and QSFP modules. ++ ++ This driver can also be built as a module. If so, the module ++ will be called i2c-cel-cpld. ++ + config I2C_CPM + tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)" + depends on (CPM1 || CPM2) && OF_I2C +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index d6b8779..b3f56c8 100644 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -14,6 +14,7 @@ obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o + obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o + obj-$(CONFIG_I2C_I801) += i2c-i801.o + obj-$(CONFIG_I2C_ISCH) += i2c-isch.o ++obj-$(CONFIG_I2C_ISMT) += i2c-ismt.o + obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o + obj-$(CONFIG_I2C_NFORCE2_S4985) += i2c-nforce2-s4985.o + obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o +@@ -31,6 +32,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o + obj-$(CONFIG_I2C_AT91) += i2c-at91.o + obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o + obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o ++obj-$(CONFIG_I2C_CEL_CPLD) += i2c-cel-cpld.o + obj-$(CONFIG_I2C_CPM) += i2c-cpm.o + obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o + obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o +diff --git a/drivers/i2c/busses/i2c-cel-cpld.c b/drivers/i2c/busses/i2c-cel-cpld.c +new file mode 100644 +index 0000000..c46bc21 +--- /dev/null ++++ b/drivers/i2c/busses/i2c-cel-cpld.c +@@ -0,0 +1,657 @@ ++/* ++ * Copyright (C) 2013 Cumulus Networks, Inc. ++ * Author: Curt Brune ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define BUS_DRV_NAME "cel-cpld-i2c-bus" ++#define BUS_MUX_DRV_VERSION "1.1" ++ ++/* ++ * The CEL_CPLD_I2C_XXX offsets are relative to the start of the "I2C ++ * block" within each CPLD: ++ * ++ * CPLD2 -- 0x10 ++ * CPLD3 -- 0x40 ++ * CPLD4 -- 0x80 ++ * ++ */ ++#define CEL_CPLD_I2C_PORT_ID 0x00 ++#define CEL_CPLD_I2C_OPCODE 0x02 ++#define CEL_CPLD_I2C_DEV_ADDR 0x04 ++#define CEL_CPLD_I2C_CMD_BYTE0 0x08 ++#define CEL_CPLD_I2C_CMD_BYTE1 0x0A ++#define CEL_CPLD_I2C_CMD_BYTE2 0x0C ++#define CEL_CPLD_I2C_CSR 0x0E ++#define CEL_CPLD_I2C_WRITE_DATA 0x10 ++#define WRITE_DATA(x) (CEL_CPLD_I2C_WRITE_DATA + (2*x)) ++#define CEL_CPLD_I2C_READ_DATA 0x20 ++#define READ_DATA(x) (CEL_CPLD_I2C_READ_DATA + (2*x)) ++ ++#define CEL_CPLD_I2C_CLK_50KHZ 0x00 ++#define CEL_CPLD_I2C_CLK_100KHZ 0x40 ++ ++#define CSR_MASTER_ERROR 0x80 ++#define CSR_BUSY 0x40 ++#define CSR_MASTER_RESET_L 0x01 ++ ++#define OPCODE_DATA_LENGTH_SHIFT 4 ++#define OPCODE_CMD_LENGTH 1 ++ ++#define DEV_ADDR_READ_OP 0x1 ++#define DEV_ADDR_WRITE_OP 0x0 ++ ++struct cel_cpld_i2c { ++ struct device *m_dev; ++ void __iomem *m_base; ++ struct i2c_adapter m_adap; ++ u8 m_clk_freq; ++}; ++ ++static inline void cel_cpld_set_mux_reg(struct cel_cpld_i2c *i2c, int channel) ++{ ++ writeb(i2c->m_clk_freq | (channel & 0x3F), ++ i2c->m_base + CEL_CPLD_I2C_PORT_ID); ++} ++ ++/* ++ * Wait up to 1 second for the controller to be come non-busy. ++ * ++ * Returns: ++ * - success: 0 ++ * - failure: negative status code ++ */ ++static int cel_cpld_wait(struct cel_cpld_i2c *i2c) ++{ ++ unsigned long orig_jiffies = jiffies; ++ int rc = 0; ++ u8 csr; ++ ++ /* Allow bus up to 1s to become not busy */ ++ while ((csr = readb(i2c->m_base + CEL_CPLD_I2C_CSR)) & CSR_BUSY) { ++ if (signal_pending(current)) { ++ return -EINTR; ++ } ++ if (time_after(jiffies, orig_jiffies + HZ)) { ++ dev_warn(i2c->m_dev, "Bus busy timeout\n"); ++ rc = -ETIMEDOUT; ++ break; ++ } ++ schedule(); ++ } ++ ++ if (csr & CSR_MASTER_ERROR) { ++ /* Typically this means the SFP+ device is not present. */ ++ /* Clear master error with the master reset. */ ++ writeb(~CSR_MASTER_RESET_L, ++ i2c->m_base + CEL_CPLD_I2C_CSR); ++ udelay(3000); ++ writeb(CSR_MASTER_RESET_L, ++ i2c->m_base + CEL_CPLD_I2C_CSR); ++ rc = rc ? rc : -EIO; ++ } ++ ++ return rc; ++} ++ ++static int cel_cpld_i2c_write(struct cel_cpld_i2c *i2c, int target, ++ u8 offset, const u8 *data, int length) ++{ ++ u8 tmp, xfer_len, i; ++ int ret, total_xfer = 0; ++ ++ /* The CEL-CPLD I2C master writes in units of 8 bytes */ ++ while (length > 0) { ++ ++ /* Configure byte offset within device */ ++ writeb(offset + total_xfer, ++ i2c->m_base + CEL_CPLD_I2C_CMD_BYTE0); ++ ++ /* Configure transfer length - max of 8 bytes */ ++ xfer_len = (length > 8) ? 8 : length; ++ tmp = (xfer_len << OPCODE_DATA_LENGTH_SHIFT); ++ tmp |= OPCODE_CMD_LENGTH; ++ writeb(tmp, i2c->m_base + CEL_CPLD_I2C_OPCODE); ++ ++ /* Load the transmit data into the send buffer */ ++ for (i = 0; i < xfer_len; i++) ++ writeb(data[total_xfer + i], i2c->m_base + WRITE_DATA(i)); ++ ++ /* Initiate write transaction */ ++ tmp = (target << 1) | DEV_ADDR_WRITE_OP; ++ writeb(tmp, i2c->m_base + CEL_CPLD_I2C_DEV_ADDR); ++ ++ /* Wait for transfer completion */ ++ ret = cel_cpld_wait(i2c); ++ if (ret) ++ return ret; ++ ++ total_xfer += xfer_len; ++ length -= xfer_len; ++ } ++ ++ return 0; ++} ++ ++static int cel_cpld_i2c_read(struct cel_cpld_i2c *i2c, int target, ++ u8 offset, u8 *data, int length) ++{ ++ u8 tmp, xfer_len, i; ++ int ret, total_xfer = 0; ++ ++ /* The CEL-CPLD I2C master reads in units of 8 bytes */ ++ while (length > 0) { ++ ++ /* Configure byte offset within device */ ++ writeb(offset + total_xfer, ++ i2c->m_base + CEL_CPLD_I2C_CMD_BYTE0); ++ ++ /* Configure transfer length - max of 8 bytes */ ++ xfer_len = (length > 8) ? 8 : length; ++ tmp = (xfer_len << OPCODE_DATA_LENGTH_SHIFT); ++ tmp |= OPCODE_CMD_LENGTH; ++ writeb(tmp, i2c->m_base + CEL_CPLD_I2C_OPCODE); ++ ++ /* Initiate read transaction */ ++ tmp = (target << 1) | DEV_ADDR_READ_OP; ++ writeb(tmp, i2c->m_base + CEL_CPLD_I2C_DEV_ADDR); ++ ++ /* Wait for transfer completion */ ++ ret = cel_cpld_wait(i2c); ++ if (ret) ++ return ret; ++ ++ /* Gather up the results */ ++ for (i = 0; i < xfer_len; i++) ++ data[total_xfer + i] = readb(i2c->m_base + READ_DATA(i)); ++ ++ total_xfer += xfer_len; ++ length -= xfer_len; ++ } ++ ++ return 0; ++} ++ ++static int cel_cpld_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ++{ ++ struct i2c_msg *pmsg; ++ int ret = 0; ++ struct cel_cpld_i2c *i2c = i2c_get_adapdata(adap); ++ u8 offset; ++ ++ /* Allow bus to become not busy */ ++ ret = cel_cpld_wait(i2c); ++ if (ret) ++ return ret; ++ ++ /* ++ * This is somewhat gimpy. ++ * ++ * The CEL-CPLD I2C master is special built to read/write SFP+ ++ * EEPROMs only. It is *not* a general purpose I2C master. ++ * The clients of this master are *always* expected to be ++ * "at,24c04" or "sff-8436 based qsfp" compatible EEPROMs. ++ * ++ * As such we have the following expectations for READ operation: ++ * ++ * - number of messages is "2" ++ * - msg[0] contains info about the offset within the 512-byte EEPROM ++ * - msg[0].len = 1 ++ * - msg[0].buf[0] contains the offset ++ * - msg[1] contains info about the read payload ++ * ++ * As such we have the following expectations for WRITE operation: ++ * ++ * - number of messages is "1" ++ * - msg[0] contains info about the offset within the 512-byte EEPROM ++ * - msg[0].buf[0] contains the offset ++ * - msg[0] also contains info about the write payload ++ */ ++ ++ /* ++ * The offset within the EEPROM is stored in msg[0].buf[0]. ++ */ ++ offset = msgs[0].buf[0]; ++ ++ if (num == 1) { ++ pmsg = &msgs[0]; ++ } else { ++ pmsg = &msgs[1]; ++ } ++ ++ if ((offset + pmsg->len) > 0x200) ++ return -EINVAL; ++ ++ if (pmsg->flags & I2C_M_RD) { ++ if (num != 2) { ++ dev_warn(i2c->m_dev, "Expecting 2 i2c messages. Got %d\n", num); ++ return -EINVAL; ++ } ++ ++ if (msgs[0].len != 1) { ++ dev_warn(i2c->m_dev, "Expecting mgs[0].len == 1. Got %d\n", ++ msgs[0].len); ++ return -EINVAL; ++ } ++ ++ ret = cel_cpld_i2c_read(i2c, pmsg->addr, offset, pmsg->buf, pmsg->len); ++ } else { ++ ret = cel_cpld_i2c_write(i2c, pmsg->addr, offset, &(pmsg->buf[1]), (pmsg->len - 1)); ++ } ++ ++ return (ret < 0) ? ret : num; ++} ++ ++static u32 cel_cpld_functionality(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm cel_cpld_algo = { ++ .master_xfer = cel_cpld_xfer, ++ .functionality = cel_cpld_functionality, ++}; ++ ++static struct i2c_adapter cel_cpld_ops = { ++ .owner = THIS_MODULE, ++ .name = "CEL_CPLD adapter", ++ .algo = &cel_cpld_algo, ++ .timeout = HZ, ++}; ++ ++static void __devinit cel_cpld_i2c_bus_setup(struct device_node *node, ++ struct cel_cpld_i2c *i2c, ++ u32 clock) ++{ ++ u8 clk_freq = CEL_CPLD_I2C_CLK_50KHZ; ++ ++ if (clock == 100000) ++ clk_freq = CEL_CPLD_I2C_CLK_100KHZ; ++ ++ i2c->m_clk_freq = clk_freq; ++ writeb(clk_freq, i2c->m_base + CEL_CPLD_I2C_PORT_ID); ++ ++ /* Reset the I2C master logic */ ++ writeb(~CSR_MASTER_RESET_L, i2c->m_base + CEL_CPLD_I2C_CSR); ++ udelay(3000); ++ writeb(CSR_MASTER_RESET_L, i2c->m_base + CEL_CPLD_I2C_CSR); ++ ++} ++ ++static const struct of_device_id cel_cpld_i2c_bus_of_match[]; ++static int __devinit cel_cpld_i2c_bus_probe(struct platform_device *op) ++{ ++ const struct of_device_id *match; ++ struct cel_cpld_i2c *i2c; ++ const u32 *prop; ++ u32 clock = 100000; ++ int result = 0; ++ int plen; ++ ++ match = of_match_device(cel_cpld_i2c_bus_of_match, &op->dev); ++ if (!match) ++ return -EINVAL; ++ ++ i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); ++ if (!i2c) ++ return -ENOMEM; ++ ++ i2c->m_dev = &op->dev; /* for debug and error output */ ++ ++ i2c->m_base = of_iomap(op->dev.of_node, 0); ++ if (!i2c->m_base) { ++ dev_err(i2c->m_dev, "failed to map controller\n"); ++ result = -ENOMEM; ++ goto fail_map; ++ } ++ ++ prop = of_get_property(op->dev.of_node, "clock-frequency", &plen); ++ if (prop && plen == sizeof(u32)) { ++ /* ++ * The hardware only supports two clock frequencies: ++ * 50kHz and 100kHz. ++ * ++ */ ++ if ((*prop != 50000) && (*prop != 100000)) { ++ dev_err(i2c->m_dev, "clock-frequency %u is not valid.\n", ++ *prop); ++ result = -EINVAL; ++ goto fail_property; ++ } else { ++ clock = *prop; ++ dev_info(i2c->m_dev, "clock-frequency %u\n", clock); ++ } ++ } ++ ++ cel_cpld_i2c_bus_setup(op->dev.of_node, i2c, clock); ++ ++ prop = of_get_property(op->dev.of_node, "cel_cpld,timeout", &plen); ++ if (prop && plen == sizeof(u32)) { ++ cel_cpld_ops.timeout = *prop * HZ / 1000000; ++ if (cel_cpld_ops.timeout < 5) ++ cel_cpld_ops.timeout = 5; ++ } ++ dev_info(i2c->m_dev, "timeout %u us\n", cel_cpld_ops.timeout * 1000000 / HZ); ++ ++ dev_set_drvdata(&op->dev, i2c); ++ ++ i2c->m_adap = cel_cpld_ops; ++ i2c_set_adapdata(&i2c->m_adap, i2c); ++ i2c->m_adap.dev.parent = &op->dev; ++ i2c->m_adap.dev.of_node = of_node_get(op->dev.of_node); ++ ++ result = i2c_add_adapter(&i2c->m_adap); ++ if (result < 0) { ++ dev_err(i2c->m_dev, "failed to add adapter\n"); ++ goto fail_add; ++ } ++ of_i2c_register_devices(&i2c->m_adap); ++ ++ return result; ++ ++ fail_add: ++ dev_set_drvdata(&op->dev, NULL); ++ fail_property: ++ iounmap(i2c->m_base); ++ fail_map: ++ kfree(i2c); ++ return result; ++}; ++ ++static int __devexit cel_cpld_i2c_bus_remove(struct platform_device *op) ++{ ++ struct cel_cpld_i2c *i2c = dev_get_drvdata(&op->dev); ++ ++ i2c_del_adapter(&i2c->m_adap); ++ dev_set_drvdata(&op->dev, NULL); ++ ++ iounmap(i2c->m_base); ++ kfree(i2c); ++ return 0; ++}; ++ ++static const struct of_device_id cel_cpld_i2c_bus_of_match[] = { ++ {.compatible = "cel,cpld-i2c-bus", }, ++ { /* end of list */ }, ++}; ++MODULE_DEVICE_TABLE(of, cel_cpld_i2c_bus_of_match); ++ ++/* Structure for a device driver */ ++static struct platform_driver cel_cpld_i2c_bus_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = BUS_DRV_NAME, ++ .of_match_table = cel_cpld_i2c_bus_of_match, ++ }, ++ .probe = cel_cpld_i2c_bus_probe, ++ .remove = __devexit_p(cel_cpld_i2c_bus_remove), ++}; ++ ++/* ++ * MUX Driver starts here ++ */ ++ ++#define MUX_DRV_NAME "cel-cpld-i2c-mux" ++ ++#define INVALID_CHANNEL (0xFF) ++ ++struct cel_cpld_vadapter { ++ struct i2c_adapter *m_adapter; /* virtual i2c adapter struct */ ++ u32 m_channel; /* MUX channel */ ++ struct llist_node m_llnode; ++}; ++ ++struct cel_cpld_i2c_mux { ++ struct device *m_dev; /* for debug and error output */ ++ struct llist_head m_vadapter_list; /* list of virtual i2c adapters */ ++ struct cel_cpld_i2c *m_i2c_bus; /* parent I2C master device */ ++ u8 m_last_channel; /* last channel selected */ ++ u32 m_mux_id; /* mux ID */ ++}; ++ ++static int cel_cpld_i2c_mux_select_chan(struct i2c_adapter *adap, ++ void *client, u32 channel) ++{ ++ struct cel_cpld_i2c_mux *mux = i2c_get_clientdata(client); ++ ++ if (channel != mux->m_last_channel) { ++ cel_cpld_set_mux_reg(mux->m_i2c_bus, channel); ++ mux->m_last_channel = channel; ++ } ++ ++ return 0; ++} ++ ++/* ++ * I2C init/probing/exit functions ++ */ ++ ++static int __devinit cel_cpld_i2c_mux_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); ++ struct cel_cpld_i2c *i2c = i2c_get_adapdata(adap); ++ struct cel_cpld_i2c_mux *mux; ++ const void* prop; ++ struct device_node *mux_of_child; ++ struct cel_cpld_vadapter *entry; ++ struct llist_node *llnode; ++ int plen = 0; ++ u32 mux_id, cnt = 0; ++ int rc = -ENODEV; ++ ++ /* ++ * Use the parent adapter for our register access. ++ */ ++ if (i2c->m_base == NULL) { ++ dev_err(&client->dev, ++ "Cannot find valid register iomap for CPLD mux.\n"); ++ rc = -ENODEV; ++ goto err; ++ } ++ ++ prop = of_get_property(client->dev.of_node, "reg", &plen); ++ if (prop && plen == sizeof(u32)) { ++ mux_id = *((u32*)prop); ++ } else { ++ dev_err(&client->dev, ++ "Cannot find valid mux_id for CPLD mux.\n"); ++ rc = -ENODEV; ++ goto err; ++ } ++ ++ mux = kmalloc(sizeof(struct cel_cpld_i2c_mux), GFP_KERNEL); ++ if (!mux) { ++ rc = -ENOMEM; ++ goto err; ++ } ++ ++ i2c_set_clientdata(client, mux); ++ ++ mux->m_dev = &client->dev; /* for debug and error output */ ++ mux->m_i2c_bus = i2c; ++ mux->m_mux_id = mux_id; ++ mux->m_last_channel = INVALID_CHANNEL; ++ init_llist_head(&mux->m_vadapter_list); ++ ++ /* Create a virtual adapter for each child channel of this mux */ ++ for_each_child_of_node(client->dev.of_node, mux_of_child) { ++ u32 channel; ++ ++ prop = of_get_property(mux_of_child, "reg", &plen); ++ if (prop && plen == sizeof(u32)) { ++ channel = *((u32*)prop); ++ } else { ++ dev_err(&client->dev, ++ "Cannot find channel for CPLD mux.\n"); ++ rc = -EINVAL; ++ of_node_put(mux_of_child); ++ goto virt_reg_failed; ++ } ++ of_node_put(mux_of_child); ++ ++ /* Check for duplicates */ ++ llist_for_each_entry(entry, ++ mux->m_vadapter_list.first, ++ m_llnode) { ++ if (entry->m_channel == channel) { ++ dev_err(&client->dev, ++ "Duplicate MUX channel: %u\n", channel); ++ rc = -EINVAL; ++ goto virt_reg_failed; ++ } ++ } ++ ++ entry = kmalloc(sizeof(struct cel_cpld_vadapter), GFP_KERNEL); ++ if (!entry) { ++ rc = -ENOMEM; ++ goto virt_reg_failed; ++ } ++ ++ entry->m_channel = channel; ++ entry->m_adapter = ++ i2c_add_mux_adapter(adap, &client->dev, client, ++ 0, channel, ++ cel_cpld_i2c_mux_select_chan, ++ NULL); ++ ++ if (entry->m_adapter == NULL) { ++ rc = -ENODEV; ++ dev_err(&client->dev, ++ "failed to register multiplexed adapter %u\n", ++ channel); ++ kfree(entry); ++ goto virt_reg_failed; ++ } ++ ++ llist_add(&entry->m_llnode, &mux->m_vadapter_list); ++ cnt++; ++ } ++ ++ dev_info(&client->dev, ++ "registered %u multiplexed buses for mux_id %u\n", ++ cnt, mux_id); ++ ++ return 0; ++ ++virt_reg_failed: ++ while ((llnode = llist_del_first(&mux->m_vadapter_list)) != NULL) { ++ entry = llist_entry(llnode, struct cel_cpld_vadapter, m_llnode); ++ if (entry->m_adapter) ++ (void)i2c_del_mux_adapter(entry->m_adapter); ++ kfree(entry); ++ } ++ ++ kfree(mux); ++err: ++ return rc; ++} ++ ++static int __devexit cel_cpld_i2c_mux_remove(struct i2c_client *client) ++{ ++ struct cel_cpld_i2c_mux *mux = i2c_get_clientdata(client); ++ struct llist_node *llnode; ++ struct cel_cpld_vadapter *entry; ++ ++ while ((llnode = llist_del_first(&mux->m_vadapter_list)) != NULL) { ++ entry = llist_entry(llnode, struct cel_cpld_vadapter, m_llnode); ++ if (entry->m_adapter) ++ (void)i2c_del_mux_adapter(entry->m_adapter); ++ kfree(entry); ++ } ++ ++ kfree(mux); ++ return 0; ++} ++ ++static const struct i2c_device_id cel_cpld_i2c_mux_ids[] = { ++ { "cpld-i2c-mux", 0 }, ++ { /* end of list */ }, ++}; ++MODULE_DEVICE_TABLE(i2c, cel_cpld_i2c_mux_ids); ++ ++static struct i2c_driver cel_cpld_i2c_mux_driver = { ++ .driver = { ++ .name = MUX_DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = cel_cpld_i2c_mux_probe, ++ .remove = __devexit_p(cel_cpld_i2c_mux_remove), ++ .id_table = cel_cpld_i2c_mux_ids, ++}; ++ ++/* ++ * Module init/exit methods begin here. The init and exit methods ++ * register/de-register two devices: ++ * ++ * - The i2c bus adapter device ++ * - The i2c mux device ++ * ++ */ ++static int __init cel_cpld_i2c_init(void) ++{ ++ int rc; ++ ++ /* First register the i2c adapter */ ++ rc = platform_driver_register(&cel_cpld_i2c_bus_driver); ++ if (rc) { ++ printk(KERN_ERR"%s(): platform_driver_register() failed: %d\n", ++ __func__, rc); ++ return rc; ++ } ++ ++ /* Next register the i2c mux */ ++ rc = i2c_add_driver(&cel_cpld_i2c_mux_driver); ++ if (rc) { ++ printk(KERN_ERR"%s(): i2c_add_driver() failed: %d\n", ++ __func__, rc); ++ platform_driver_unregister(&cel_cpld_i2c_bus_driver); ++ } ++ ++ return rc; ++} ++ ++static void __exit cel_cpld_i2c_exit(void) ++{ ++ /* First remove the i2c mux driver */ ++ i2c_del_driver( &cel_cpld_i2c_mux_driver); ++ ++ /* Next remove the i2c adapter */ ++ platform_driver_unregister(&cel_cpld_i2c_bus_driver); ++} ++ ++module_init(cel_cpld_i2c_init); ++module_exit(cel_cpld_i2c_exit); ++ ++MODULE_AUTHOR("Curt Brune "); ++MODULE_DESCRIPTION("I2C Adapter/Mux Driver for Celestica CPLD"); ++MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(BUS_MUX_DRV_VERSION); +diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c +index aadb398..7515735 100644 +--- a/drivers/i2c/busses/i2c-designware-core.c ++++ b/drivers/i2c/busses/i2c-designware-core.c +@@ -66,8 +66,11 @@ + #define DW_IC_STATUS 0x70 + #define DW_IC_TXFLR 0x74 + #define DW_IC_RXFLR 0x78 ++#define DW_IC_SDA_HOLD 0x7c + #define DW_IC_TX_ABRT_SOURCE 0x80 + #define DW_IC_COMP_PARAM_1 0xf4 ++#define DW_IC_COMP_VERSION 0xf8 ++#define DW_IC_SDA_HOLD_MIN_VERS 0x3131312A + #define DW_IC_COMP_TYPE 0xfc + #define DW_IC_COMP_TYPE_VALUE 0x44570140 + +@@ -280,6 +283,13 @@ int i2c_dw_init(struct dw_i2c_dev *dev) + 47, /* tLOW = 4.7 us */ + 3, /* tf = 0.3 us */ + 0); /* No offset */ ++ ++ /* Allow platforms to specify the ideal HCNT and LCNT values */ ++ if (dev->ss_hcnt && dev->ss_lcnt) { ++ hcnt = dev->ss_hcnt; ++ lcnt = dev->ss_lcnt; ++ } ++ + dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT); + dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT); + dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); +@@ -294,10 +304,25 @@ int i2c_dw_init(struct dw_i2c_dev *dev) + 13, /* tLOW = 1.3 us */ + 3, /* tf = 0.3 us */ + 0); /* No offset */ ++ ++ if (dev->fs_hcnt && dev->fs_lcnt) { ++ hcnt = dev->fs_hcnt; ++ lcnt = dev->fs_lcnt; ++ } + dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT); + dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT); + dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); + ++ /* Configure SDA Hold Time if required */ ++ if (dev->sda_hold_time) { ++ reg = dw_readl(dev, DW_IC_COMP_VERSION); ++ if (reg >= DW_IC_SDA_HOLD_MIN_VERS) ++ dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD); ++ else ++ dev_warn(dev->dev, ++ "Hardware too old to adjust SDA hold time."); ++ } ++ + /* Configure Tx/Rx FIFO threshold levels */ + dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL); + dw_writel(dev, 0, DW_IC_RX_TL); +@@ -406,8 +431,12 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) + + while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { + if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { ++ /* avoid rx buffer overrun */ ++ if (rx_limit - dev->rx_outstanding <= 0) ++ break; + dw_writel(dev, 0x100, DW_IC_DATA_CMD); + rx_limit--; ++ dev->rx_outstanding++; + } else + dw_writel(dev, *buf++, DW_IC_DATA_CMD); + tx_limit--; buf_len--; +@@ -460,9 +489,10 @@ i2c_dw_read(struct dw_i2c_dev *dev) + + rx_valid = dw_readl(dev, DW_IC_RXFLR); + +- for (; len > 0 && rx_valid > 0; len--, rx_valid--) ++ for (; len > 0 && rx_valid > 0; len--, rx_valid--) { + *buf++ = dw_readl(dev, DW_IC_DATA_CMD); +- ++ dev->rx_outstanding--; ++ } + if (len > 0) { + dev->status |= STATUS_READ_IN_PROGRESS; + dev->rx_buf_len = len; +@@ -519,6 +549,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) + dev->msg_err = 0; + dev->status = STATUS_IDLE; + dev->abort_source = 0; ++ dev->rx_outstanding = 0; + + ret = i2c_dw_wait_bus_not_busy(dev); + if (ret < 0) +diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h +index 02d1a2d..af8f8c6 100644 +--- a/drivers/i2c/busses/i2c-designware-core.h ++++ b/drivers/i2c/busses/i2c-designware-core.h +@@ -60,6 +60,16 @@ + * @adapter: i2c subsystem adapter node + * @tx_fifo_depth: depth of the hardware tx fifo + * @rx_fifo_depth: depth of the hardware rx fifo ++ * @rx_outstanding: current master-rx elements in tx fifo ++ * @ss_hcnt: standard speed HCNT value ++ * @ss_lcnt: standard speed LCNT value ++ * @fs_hcnt: fast speed HCNT value ++ * @fs_lcnt: fast speed LCNT value ++ * ++ * HCNT and LCNT parameters can be used if the platform knows more accurate ++ * values than the one computed based only on the input clock frequency. ++ * Leave them to be %0 if not used. ++ * + */ + struct dw_i2c_dev { + struct device *dev; +@@ -88,6 +98,12 @@ struct dw_i2c_dev { + u32 master_cfg; + unsigned int tx_fifo_depth; + unsigned int rx_fifo_depth; ++ int rx_outstanding; ++ u32 sda_hold_time; ++ u16 ss_hcnt; ++ u16 ss_lcnt; ++ u16 fs_hcnt; ++ u16 fs_lcnt; + }; + + extern u32 dw_readl(struct dw_i2c_dev *dev, int offset); +diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c +index 9e89e73..3a2901e 100644 +--- a/drivers/i2c/busses/i2c-designware-pcidrv.c ++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c +@@ -54,6 +54,16 @@ enum dw_pci_ctl_id_t { + medfield_3, + medfield_4, + medfield_5, ++ ++ baytrail, ++}; ++ ++struct dw_scl_sda_cfg { ++ u32 ss_hcnt; ++ u32 fs_hcnt; ++ u32 ss_lcnt; ++ u32 fs_lcnt; ++ u32 sda_hold; + }; + + struct dw_pci_controller { +@@ -62,12 +72,29 @@ struct dw_pci_controller { + u32 tx_fifo_depth; + u32 rx_fifo_depth; + u32 clk_khz; ++ u32 functionality; ++ struct dw_scl_sda_cfg *scl_sda_cfg; + }; + + #define INTEL_MID_STD_CFG (DW_IC_CON_MASTER | \ + DW_IC_CON_SLAVE_DISABLE | \ + DW_IC_CON_RESTART_EN) + ++#define DW_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \ ++ I2C_FUNC_SMBUS_BYTE | \ ++ I2C_FUNC_SMBUS_BYTE_DATA | \ ++ I2C_FUNC_SMBUS_WORD_DATA | \ ++ I2C_FUNC_SMBUS_I2C_BLOCK) ++ ++/* BayTrail HCNT/LCNT/SDA hold time */ ++static struct dw_scl_sda_cfg byt_config = { ++ .ss_hcnt = 0x200, ++ .fs_hcnt = 0x55, ++ .ss_lcnt = 0x200, ++ .fs_lcnt = 0x99, ++ .sda_hold = 0x6, ++}; ++ + static struct dw_pci_controller dw_pci_controllers[] = { + [moorestown_0] = { + .bus_num = 0, +@@ -132,6 +159,15 @@ static struct dw_pci_controller dw_pci_controllers[] = { + .rx_fifo_depth = 32, + .clk_khz = 25000, + }, ++ [baytrail] = { ++ .bus_num = -1, ++ .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, ++ .tx_fifo_depth = 32, ++ .rx_fifo_depth = 32, ++ .clk_khz = 100000, ++ .functionality = I2C_FUNC_10BIT_ADDR, ++ .scl_sda_cfg = &byt_config, ++ } + }; + static struct i2c_algorithm i2c_dw_algo = { + .master_xfer = i2c_dw_xfer, +@@ -217,6 +253,7 @@ const struct pci_device_id *id) + void __iomem *base; + int r; + struct dw_pci_controller *controller; ++ struct dw_scl_sda_cfg *cfg; + + if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) { + printk(KERN_ERR "dw_i2c_pci_probe: invalid driver data %ld\n", +@@ -271,13 +308,17 @@ const struct pci_device_id *id) + dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; + dev->base = base; + dev->dev = get_device(&pdev->dev); +- dev->functionality = +- I2C_FUNC_I2C | +- I2C_FUNC_SMBUS_BYTE | +- I2C_FUNC_SMBUS_BYTE_DATA | +- I2C_FUNC_SMBUS_WORD_DATA | +- I2C_FUNC_SMBUS_I2C_BLOCK; ++ dev->functionality = controller->functionality | ++ DW_DEFAULT_FUNCTIONALITY; + dev->master_cfg = controller->bus_cfg; ++ if (controller->scl_sda_cfg) { ++ cfg = controller->scl_sda_cfg; ++ dev->ss_hcnt = cfg->ss_hcnt; ++ dev->fs_hcnt = cfg->fs_hcnt; ++ dev->ss_lcnt = cfg->ss_lcnt; ++ dev->fs_lcnt = cfg->fs_lcnt; ++ dev->sda_hold_time = cfg->sda_hold; ++ } + + pci_set_drvdata(pdev, dev); + +@@ -294,8 +335,7 @@ const struct pci_device_id *id) + adap->algo = &i2c_dw_algo; + adap->dev.parent = &pdev->dev; + adap->nr = controller->bus_num; +- snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci-%d", +- adap->nr); ++ snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci"); + + r = request_irq(pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev); + if (r) { +@@ -361,6 +401,15 @@ DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = { + { PCI_VDEVICE(INTEL, 0x082C), medfield_0 }, + { PCI_VDEVICE(INTEL, 0x082D), medfield_1 }, + { PCI_VDEVICE(INTEL, 0x082E), medfield_2 }, ++ /* Baytrail */ ++ { PCI_VDEVICE(INTEL, 0x0F41), baytrail }, ++ { PCI_VDEVICE(INTEL, 0x0F42), baytrail }, ++ { PCI_VDEVICE(INTEL, 0x0F43), baytrail }, ++ { PCI_VDEVICE(INTEL, 0x0F44), baytrail }, ++ { PCI_VDEVICE(INTEL, 0x0F45), baytrail }, ++ { PCI_VDEVICE(INTEL, 0x0F46), baytrail }, ++ { PCI_VDEVICE(INTEL, 0x0F47), baytrail }, ++ + { 0,} + }; + MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids); +diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c +index 817d025..8bc003c 100644 +--- a/drivers/i2c/busses/i2c-i801.c ++++ b/drivers/i2c/busses/i2c-i801.c +@@ -2,7 +2,7 @@ + Copyright (c) 1998 - 2002 Frodo Looijaard , + Philip Edelbrock , and Mark D. Studebaker + +- Copyright (C) 2007, 2008 Jean Delvare ++ Copyright (C) 2007 - 2012 Jean Delvare + Copyright (C) 2010 Intel Corporation, + David Woodhouse + +@@ -53,6 +53,14 @@ + Panther Point (PCH) 0x1e22 32 hard yes yes yes + Lynx Point (PCH) 0x8c22 32 hard yes yes yes + Lynx Point-LP (PCH) 0x9c22 32 hard yes yes yes ++ Avoton (SOC) 0x1f3c 32 hard yes yes yes ++ Wellsburg (PCH) 0x8d22 32 hard yes yes yes ++ Wellsburg (PCH) MS 0x8d7d 32 hard yes yes yes ++ Wellsburg (PCH) MS 0x8d7e 32 hard yes yes yes ++ Wellsburg (PCH) MS 0x8d7f 32 hard yes yes yes ++ Coleto Creek (PCH) 0x23b0 32 hard yes yes yes ++ Wildcat Point-LP (PCH) 0x9ca2 32 hard yes yes yes ++ BayTrail (SOC) 0x0f12 32 hard yes yes yes + + Features supported by this driver: + Software PEC no +@@ -61,10 +69,12 @@ + Block process call transaction no + I2C block read transaction yes (doesn't use the block buffer) + Slave mode no ++ Interrupt processing yes + + See the file Documentation/i2c/busses/i2c-i801 for details. + */ + ++#include + #include + #include + #include +@@ -77,6 +87,15 @@ + #include + #include + #include ++#include ++#include ++ ++#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ ++ defined CONFIG_DMI ++#include ++#include ++#include ++#endif + + /* I801 SMBus address offsets */ + #define SMBHSTSTS(p) (0 + (p)->smba) +@@ -92,8 +111,12 @@ + + /* PCI Address Constants */ + #define SMBBAR 4 ++#define SMBPCISTS 0x006 + #define SMBHSTCFG 0x040 + ++/* Host status bits for SMBPCISTS */ ++#define SMBPCISTS_INTS 0x08 ++ + /* Host configuration bits for SMBHSTCFG */ + #define SMBHSTCFG_HST_EN 1 + #define SMBHSTCFG_SMB_SMI_EN 2 +@@ -103,12 +126,12 @@ + #define SMBAUXCTL_CRC 1 + #define SMBAUXCTL_E32B 2 + +-/* kill bit for SMBHSTCNT */ +-#define SMBHSTCNT_KILL 2 ++/* Auxiliary status register bits, ICH4+ only */ ++#define SMBAUXSTS_CRCE 1 ++#define SMBAUXSTS_STCO 2 + + /* Other settings */ +-#define MAX_TIMEOUT 100 +-#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ ++#define MAX_RETRIES 400 + + /* I801 command constants */ + #define I801_QUICK 0x00 +@@ -118,10 +141,13 @@ + #define I801_PROC_CALL 0x10 /* unimplemented */ + #define I801_BLOCK_DATA 0x14 + #define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */ +-#define I801_BLOCK_LAST 0x34 +-#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */ +-#define I801_START 0x40 +-#define I801_PEC_EN 0x80 /* ICH3 and later */ ++ ++/* I801 Host Control register bits */ ++#define SMBHSTCNT_INTREN 0x01 ++#define SMBHSTCNT_KILL 0x02 ++#define SMBHSTCNT_LAST_BYTE 0x20 ++#define SMBHSTCNT_START 0x40 ++#define SMBHSTCNT_PEC_EN 0x80 /* ICH3 and later */ + + /* I801 Hosts Status register bits */ + #define SMBHSTSTS_BYTE_DONE 0x80 +@@ -133,11 +159,16 @@ + #define SMBHSTSTS_INTR 0x02 + #define SMBHSTSTS_HOST_BUSY 0x01 + +-#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \ +- SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \ +- SMBHSTSTS_INTR) ++#define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | \ ++ SMBHSTSTS_DEV_ERR) ++ ++#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | \ ++ STATUS_ERROR_FLAGS) ++ ++#define AUXSTS_ERROR_FLAGS SMBAUXSTS_CRCE + + /* Older devices have their ID defined in */ ++#define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12 + #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 + #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 + /* Patsburg also has three 'Integrated Device Function' SMBus controllers */ +@@ -145,10 +176,26 @@ + #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71 + #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72 + #define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22 ++#define PCI_DEVICE_ID_INTEL_AVOTON_SMBUS 0x1f3c + #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 ++#define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS 0x23b0 + #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 + #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 ++#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS 0x8d22 ++#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0 0x8d7d ++#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1 0x8d7e ++#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2 0x8d7f + #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 ++#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS 0x9ca2 ++ ++struct i801_mux_config { ++ char *gpio_chip; ++ unsigned values[3]; ++ int n_values; ++ unsigned classes[3]; ++ unsigned gpios[2]; /* Relative to gpio_chip->base */ ++ int n_gpios; ++}; + + struct i801_priv { + struct i2c_adapter adapter; +@@ -156,6 +203,23 @@ struct i801_priv { + unsigned char original_hstcfg; + struct pci_dev *pci_dev; + unsigned int features; ++ ++ /* isr processing */ ++ wait_queue_head_t waitq; ++ u8 status; ++ ++ /* Command state used by isr for byte-by-byte block transactions */ ++ u8 cmd; ++ bool is_read; ++ int count; ++ int len; ++ u8 *data; ++ ++#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ ++ defined CONFIG_DMI ++ const struct i801_mux_config *mux_drvdata; ++ struct platform_device *mux_pdev; ++#endif + }; + + static struct pci_driver i801_driver; +@@ -164,6 +228,7 @@ static struct pci_driver i801_driver; + #define FEATURE_BLOCK_BUFFER (1 << 1) + #define FEATURE_BLOCK_PROC (1 << 2) + #define FEATURE_I2C_BLOCK_READ (1 << 3) ++#define FEATURE_IRQ (1 << 4) + /* Not really a feature, but it's convenient to handle it as such */ + #define FEATURE_IDF (1 << 15) + +@@ -172,11 +237,16 @@ static const char *i801_feature_names[] = { + "Block buffer", + "Block process call", + "I2C block read", ++ "Interrupt", + }; + + static unsigned int disable_features; + module_param(disable_features, uint, S_IRUGO | S_IWUSR); +-MODULE_PARM_DESC(disable_features, "Disable selected driver features"); ++MODULE_PARM_DESC(disable_features, "Disable selected driver features:\n" ++ "\t\t 0x01 disable SMBus PEC\n" ++ "\t\t 0x02 disable the block buffer\n" ++ "\t\t 0x08 disable the I2C block read functionality\n" ++ "\t\t 0x10 don't use interrupts "); + + /* Make sure the SMBus host is ready to start transmitting. + Return 0 if it is, -EBUSY if it is not. */ +@@ -207,19 +277,28 @@ static int i801_check_pre(struct i801_priv *priv) + return 0; + } + +-/* Convert the status register to an error code, and clear it. */ +-static int i801_check_post(struct i801_priv *priv, int status, int timeout) ++/* ++ * Convert the status register to an error code, and clear it. ++ * Note that status only contains the bits we want to clear, not the ++ * actual register value. ++ */ ++static int i801_check_post(struct i801_priv *priv, int status) + { + int result = 0; + +- /* If the SMBus is still busy, we give up */ +- if (timeout) { ++ /* ++ * If the SMBus is still busy, we give up ++ * Note: This timeout condition only happens when using polling ++ * transactions. For interrupt operation, NAK/timeout is indicated by ++ * DEV_ERR. ++ */ ++ if (unlikely(status < 0)) { + dev_err(&priv->pci_dev->dev, "Transaction timeout\n"); + /* try to stop the current command */ + dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n"); + outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL, + SMBHSTCNT(priv)); +- msleep(1); ++ usleep_range(1000, 2000); + outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL), + SMBHSTCNT(priv)); + +@@ -246,64 +325,76 @@ static int i801_check_post(struct i801_priv *priv, int status, int timeout) + dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n"); + } + +- if (result) { +- /* Clear error flags */ +- outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv)); +- status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; +- if (status) { +- dev_warn(&priv->pci_dev->dev, "Failed clearing status " +- "flags at end of transaction (%02x)\n", +- status); +- } +- } ++ /* Clear status flags except BYTE_DONE, to be cleared by caller */ ++ outb_p(status, SMBHSTSTS(priv)); + + return result; + } + +-static int i801_transaction(struct i801_priv *priv, int xact) ++/* Wait for BUSY being cleared and either INTR or an error flag being set */ ++static int i801_wait_intr(struct i801_priv *priv) + { +- int status; +- int result; + int timeout = 0; +- +- result = i801_check_pre(priv); +- if (result < 0) +- return result; +- +- /* the current contents of SMBHSTCNT can be overwritten, since PEC, +- * INTREN, SMBSCMD are passed in xact */ +- outb_p(xact | I801_START, SMBHSTCNT(priv)); ++ int status; + + /* We will always wait for a fraction of a second! */ + do { +- msleep(1); ++ usleep_range(250, 500); + status = inb_p(SMBHSTSTS(priv)); +- } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT)); +- +- result = i801_check_post(priv, status, timeout > MAX_TIMEOUT); +- if (result < 0) +- return result; ++ } while (((status & SMBHSTSTS_HOST_BUSY) || ++ !(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR))) && ++ (timeout++ < MAX_RETRIES)); + +- outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv)); +- return 0; ++ if (timeout > MAX_RETRIES) { ++ dev_dbg(&priv->pci_dev->dev, "INTR Timeout!\n"); ++ return -ETIMEDOUT; ++ } ++ return status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR); + } + +-/* wait for INTR bit as advised by Intel */ +-static void i801_wait_hwpec(struct i801_priv *priv) ++/* Wait for either BYTE_DONE or an error flag being set */ ++static int i801_wait_byte_done(struct i801_priv *priv) + { + int timeout = 0; + int status; + ++ /* We will always wait for a fraction of a second! */ + do { +- msleep(1); ++ usleep_range(250, 500); + status = inb_p(SMBHSTSTS(priv)); +- } while ((!(status & SMBHSTSTS_INTR)) +- && (timeout++ < MAX_TIMEOUT)); ++ } while (!(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) && ++ (timeout++ < MAX_RETRIES)); + +- if (timeout > MAX_TIMEOUT) +- dev_dbg(&priv->pci_dev->dev, "PEC Timeout!\n"); ++ if (timeout > MAX_RETRIES) { ++ dev_dbg(&priv->pci_dev->dev, "BYTE_DONE Timeout!\n"); ++ return -ETIMEDOUT; ++ } ++ return status & STATUS_ERROR_FLAGS; ++} + +- outb_p(status, SMBHSTSTS(priv)); ++static int i801_transaction(struct i801_priv *priv, int xact) ++{ ++ int status; ++ int result; ++ ++ result = i801_check_pre(priv); ++ if (result < 0) ++ return result; ++ ++ if (priv->features & FEATURE_IRQ) { ++ outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START, ++ SMBHSTCNT(priv)); ++ wait_event(priv->waitq, (status = priv->status)); ++ priv->status = 0; ++ return i801_check_post(priv, status); ++ } ++ ++ /* the current contents of SMBHSTCNT can be overwritten, since PEC, ++ * SMBSCMD are passed in xact */ ++ outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv)); ++ ++ status = i801_wait_intr(priv); ++ return i801_check_post(priv, status); + } + + static int i801_block_transaction_by_block(struct i801_priv *priv, +@@ -323,8 +414,8 @@ static int i801_block_transaction_by_block(struct i801_priv *priv, + outb_p(data->block[i+1], SMBBLKDAT(priv)); + } + +- status = i801_transaction(priv, I801_BLOCK_DATA | ENABLE_INT9 | +- I801_PEC_EN * hwpec); ++ status = i801_transaction(priv, I801_BLOCK_DATA | ++ (hwpec ? SMBHSTCNT_PEC_EN : 0)); + if (status) + return status; + +@@ -340,6 +431,110 @@ static int i801_block_transaction_by_block(struct i801_priv *priv, + return 0; + } + ++static void i801_isr_byte_done(struct i801_priv *priv) ++{ ++ if (priv->is_read) { ++ /* For SMBus block reads, length is received with first byte */ ++ if (((priv->cmd & 0x1c) == I801_BLOCK_DATA) && ++ (priv->count == 0)) { ++ priv->len = inb_p(SMBHSTDAT0(priv)); ++ if (priv->len < 1 || priv->len > I2C_SMBUS_BLOCK_MAX) { ++ dev_err(&priv->pci_dev->dev, ++ "Illegal SMBus block read size %d\n", ++ priv->len); ++ /* FIXME: Recover */ ++ priv->len = I2C_SMBUS_BLOCK_MAX; ++ } else { ++ dev_dbg(&priv->pci_dev->dev, ++ "SMBus block read size is %d\n", ++ priv->len); ++ } ++ priv->data[-1] = priv->len; ++ } ++ ++ /* Read next byte */ ++ if (priv->count < priv->len) ++ priv->data[priv->count++] = inb(SMBBLKDAT(priv)); ++ else ++ dev_dbg(&priv->pci_dev->dev, ++ "Discarding extra byte on block read\n"); ++ ++ /* Set LAST_BYTE for last byte of read transaction */ ++ if (priv->count == priv->len - 1) ++ outb_p(priv->cmd | SMBHSTCNT_LAST_BYTE, ++ SMBHSTCNT(priv)); ++ } else if (priv->count < priv->len - 1) { ++ /* Write next byte, except for IRQ after last byte */ ++ outb_p(priv->data[++priv->count], SMBBLKDAT(priv)); ++ } ++ ++ /* Clear BYTE_DONE to continue with next byte */ ++ outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv)); ++} ++ ++/* ++ * There are two kinds of interrupts: ++ * ++ * 1) i801 signals transaction completion with one of these interrupts: ++ * INTR - Success ++ * DEV_ERR - Invalid command, NAK or communication timeout ++ * BUS_ERR - SMI# transaction collision ++ * FAILED - transaction was canceled due to a KILL request ++ * When any of these occur, update ->status and wake up the waitq. ++ * ->status must be cleared before kicking off the next transaction. ++ * ++ * 2) For byte-by-byte (I2C read/write) transactions, one BYTE_DONE interrupt ++ * occurs for each byte of a byte-by-byte to prepare the next byte. ++ */ ++static irqreturn_t i801_isr(int irq, void *dev_id) ++{ ++ struct i801_priv *priv = dev_id; ++ u16 pcists; ++ u8 status; ++ u8 auxsts; ++ ++ /* Confirm this is our interrupt */ ++ pci_read_config_word(priv->pci_dev, SMBPCISTS, &pcists); ++ if (!(pcists & SMBPCISTS_INTS)) ++ return IRQ_NONE; ++ ++ status = inb_p(SMBHSTSTS(priv)); ++ if (status != 0x42) ++ dev_dbg(&priv->pci_dev->dev, "irq: status = %02x\n", status); ++ ++ if (status & SMBHSTSTS_BYTE_DONE) ++ i801_isr_byte_done(priv); ++ ++ /* ++ * Clear error condition in aux status that may have come from ++ * a PEC error. The main status register also should be showing ++ * an error. That should be sufficient for reporting purposes. ++ */ ++ if (priv->features & FEATURE_SMBUS_PEC && ++ (auxsts = inb_p(SMBAUXSTS(priv))) & AUXSTS_ERROR_FLAGS) { ++ dev_dbg(&priv->pci_dev->dev, "irq: auxsts = %02x\n", auxsts); ++ outb_p(auxsts & AUXSTS_ERROR_FLAGS, SMBAUXSTS(priv)); ++ } ++ ++ /* ++ * Clear irq sources and report transaction result. ++ * ->status must be cleared before the next transaction is started. ++ */ ++ status &= SMBHSTSTS_INTR | STATUS_ERROR_FLAGS; ++ if (status) { ++ outb_p(status, SMBHSTSTS(priv)); ++ priv->status |= status; ++ wake_up(&priv->waitq); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * For "byte-by-byte" block transactions: ++ * I2C write uses cmd=I801_BLOCK_DATA, I2C_EN=1 ++ * I2C read uses cmd=I801_I2C_BLOCK_DATA ++ */ + static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, + union i2c_smbus_data *data, + char read_write, int command, +@@ -349,7 +544,6 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, + int smbcmd; + int status; + int result; +- int timeout; + + result = i801_check_pre(priv); + if (result < 0) +@@ -362,36 +556,39 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, + outb_p(data->block[1], SMBBLKDAT(priv)); + } + ++ if (command == I2C_SMBUS_I2C_BLOCK_DATA && ++ read_write == I2C_SMBUS_READ) ++ smbcmd = I801_I2C_BLOCK_DATA; ++ else ++ smbcmd = I801_BLOCK_DATA; ++ ++ if (priv->features & FEATURE_IRQ) { ++ priv->is_read = (read_write == I2C_SMBUS_READ); ++ if (len == 1 && priv->is_read) ++ smbcmd |= SMBHSTCNT_LAST_BYTE; ++ priv->cmd = smbcmd | SMBHSTCNT_INTREN; ++ priv->len = len; ++ priv->count = 0; ++ priv->data = &data->block[1]; ++ ++ outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv)); ++ wait_event(priv->waitq, (status = priv->status)); ++ priv->status = 0; ++ return i801_check_post(priv, status); ++ } ++ + for (i = 1; i <= len; i++) { +- if (i == len && read_write == I2C_SMBUS_READ) { +- if (command == I2C_SMBUS_I2C_BLOCK_DATA) +- smbcmd = I801_I2C_BLOCK_LAST; +- else +- smbcmd = I801_BLOCK_LAST; +- } else { +- if (command == I2C_SMBUS_I2C_BLOCK_DATA +- && read_write == I2C_SMBUS_READ) +- smbcmd = I801_I2C_BLOCK_DATA; +- else +- smbcmd = I801_BLOCK_DATA; +- } +- outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv)); ++ if (i == len && read_write == I2C_SMBUS_READ) ++ smbcmd |= SMBHSTCNT_LAST_BYTE; ++ outb_p(smbcmd, SMBHSTCNT(priv)); + + if (i == 1) +- outb_p(inb(SMBHSTCNT(priv)) | I801_START, ++ outb_p(inb(SMBHSTCNT(priv)) | SMBHSTCNT_START, + SMBHSTCNT(priv)); + +- /* We will always wait for a fraction of a second! */ +- timeout = 0; +- do { +- msleep(1); +- status = inb_p(SMBHSTSTS(priv)); +- } while ((!(status & SMBHSTSTS_BYTE_DONE)) +- && (timeout++ < MAX_TIMEOUT)); +- +- result = i801_check_post(priv, status, timeout > MAX_TIMEOUT); +- if (result < 0) +- return result; ++ status = i801_wait_byte_done(priv); ++ if (status) ++ goto exit; + + if (i == 1 && read_write == I2C_SMBUS_READ + && command != I2C_SMBUS_I2C_BLOCK_DATA) { +@@ -418,10 +615,12 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, + outb_p(data->block[i+1], SMBBLKDAT(priv)); + + /* signals SMBBLKDAT ready */ +- outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv)); ++ outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv)); + } + +- return 0; ++ status = i801_wait_intr(priv); ++exit: ++ return i801_check_post(priv, status); + } + + static int i801_set_block_buffer_mode(struct i801_priv *priv) +@@ -476,9 +675,6 @@ static int i801_block_transaction(struct i801_priv *priv, + read_write, + command, hwpec); + +- if (result == 0 && hwpec) +- i801_wait_hwpec(priv); +- + if (command == I2C_SMBUS_I2C_BLOCK_DATA + && read_write == I2C_SMBUS_WRITE) { + /* restore saved configuration register value */ +@@ -566,7 +762,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, + ret = i801_block_transaction(priv, data, read_write, size, + hwpec); + else +- ret = i801_transaction(priv, xact | ENABLE_INT9); ++ ret = i801_transaction(priv, xact); + + /* Some BIOSes don't like it when PEC is enabled at reboot or resume + time, so we forcibly disable it after every transaction. Turn off +@@ -639,6 +835,14 @@ static const struct pci_device_id i801_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMBUS) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS) }, + { 0, } + }; + +@@ -682,14 +886,14 @@ struct dmi_onboard_device_info { + const char *i2c_type; + }; + +-static struct dmi_onboard_device_info __devinitdata dmi_devices[] = { ++static const struct dmi_onboard_device_info dmi_devices[] = { + { "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" }, + { "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" }, + { "Hades", DMI_DEV_TYPE_OTHER, 0x73, "fschds" }, + }; + +-static void __devinit dmi_check_onboard_device(u8 type, const char *name, +- struct i2c_adapter *adap) ++static void dmi_check_onboard_device(u8 type, const char *name, ++ struct i2c_adapter *adap) + { + int i; + struct i2c_board_info info; +@@ -712,8 +916,7 @@ static void __devinit dmi_check_onboard_device(u8 type, const char *name, + /* We use our own function to check for onboard devices instead of + dmi_find_device() as some buggy BIOS's have the devices we are interested + in marked as disabled */ +-static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm, +- void *adap) ++static void dmi_check_onboard_devices(const struct dmi_header *dm, void *adap) + { + int i, count; + +@@ -742,7 +945,7 @@ static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm, + } + + /* Register optional slaves */ +-static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) ++static void i801_probe_optional_slaves(struct i801_priv *priv) + { + /* Only register slaves on main SMBus channel */ + if (priv->features & FEATURE_IDF) +@@ -762,11 +965,170 @@ static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) + } + #else + static void __init input_apanel_init(void) {} +-static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {} ++static void i801_probe_optional_slaves(struct i801_priv *priv) {} + #endif /* CONFIG_X86 && CONFIG_DMI */ + +-static int __devinit i801_probe(struct pci_dev *dev, +- const struct pci_device_id *id) ++#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ ++ defined CONFIG_DMI ++static struct i801_mux_config i801_mux_config_asus_z8_d12 = { ++ .gpio_chip = "gpio_ich", ++ .values = { 0x02, 0x03 }, ++ .n_values = 2, ++ .classes = { I2C_CLASS_SPD, I2C_CLASS_SPD }, ++ .gpios = { 52, 53 }, ++ .n_gpios = 2, ++}; ++ ++static struct i801_mux_config i801_mux_config_asus_z8_d18 = { ++ .gpio_chip = "gpio_ich", ++ .values = { 0x02, 0x03, 0x01 }, ++ .n_values = 3, ++ .classes = { I2C_CLASS_SPD, I2C_CLASS_SPD, I2C_CLASS_SPD }, ++ .gpios = { 52, 53 }, ++ .n_gpios = 2, ++}; ++ ++static const struct dmi_system_id mux_dmi_table[] = { ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "Z8NA-D6(C)"), ++ }, ++ .driver_data = &i801_mux_config_asus_z8_d12, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "Z8P(N)E-D12(X)"), ++ }, ++ .driver_data = &i801_mux_config_asus_z8_d12, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "Z8NH-D12"), ++ }, ++ .driver_data = &i801_mux_config_asus_z8_d12, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "Z8PH-D12/IFB"), ++ }, ++ .driver_data = &i801_mux_config_asus_z8_d12, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "Z8NR-D12"), ++ }, ++ .driver_data = &i801_mux_config_asus_z8_d12, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "Z8P(N)H-D12"), ++ }, ++ .driver_data = &i801_mux_config_asus_z8_d12, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "Z8PG-D18"), ++ }, ++ .driver_data = &i801_mux_config_asus_z8_d18, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "Z8PE-D18"), ++ }, ++ .driver_data = &i801_mux_config_asus_z8_d18, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "Z8PS-D12"), ++ }, ++ .driver_data = &i801_mux_config_asus_z8_d12, ++ }, ++ { } ++}; ++ ++/* Setup multiplexing if needed */ ++static int i801_add_mux(struct i801_priv *priv) ++{ ++ struct device *dev = &priv->adapter.dev; ++ const struct i801_mux_config *mux_config; ++ struct i2c_mux_gpio_platform_data gpio_data; ++ int err; ++ ++ if (!priv->mux_drvdata) ++ return 0; ++ mux_config = priv->mux_drvdata; ++ ++ /* Prepare the platform data */ ++ memset(&gpio_data, 0, sizeof(struct i2c_mux_gpio_platform_data)); ++ gpio_data.parent = priv->adapter.nr; ++ gpio_data.values = mux_config->values; ++ gpio_data.n_values = mux_config->n_values; ++ gpio_data.classes = mux_config->classes; ++ gpio_data.gpio_chip = mux_config->gpio_chip; ++ gpio_data.gpios = mux_config->gpios; ++ gpio_data.n_gpios = mux_config->n_gpios; ++ gpio_data.idle = I2C_MUX_GPIO_NO_IDLE; ++ ++ /* Register the mux device */ ++ priv->mux_pdev = platform_device_register_data(dev, "i2c-mux-gpio", ++ PLATFORM_DEVID_AUTO, &gpio_data, ++ sizeof(struct i2c_mux_gpio_platform_data)); ++ if (IS_ERR(priv->mux_pdev)) { ++ err = PTR_ERR(priv->mux_pdev); ++ priv->mux_pdev = NULL; ++ dev_err(dev, "Failed to register i2c-mux-gpio device\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static void i801_del_mux(struct i801_priv *priv) ++{ ++ if (priv->mux_pdev) ++ platform_device_unregister(priv->mux_pdev); ++} ++ ++static unsigned int i801_get_adapter_class(struct i801_priv *priv) ++{ ++ const struct dmi_system_id *id; ++ const struct i801_mux_config *mux_config; ++ unsigned int class = I2C_CLASS_HWMON | I2C_CLASS_SPD; ++ int i; ++ ++ id = dmi_first_match(mux_dmi_table); ++ if (id) { ++ /* Remove branch classes from trunk */ ++ mux_config = id->driver_data; ++ for (i = 0; i < mux_config->n_values; i++) ++ class &= ~mux_config->classes[i]; ++ ++ /* Remember for later */ ++ priv->mux_drvdata = mux_config; ++ } ++ ++ return class; ++} ++#else ++static inline int i801_add_mux(struct i801_priv *priv) { return 0; } ++static inline void i801_del_mux(struct i801_priv *priv) { } ++ ++static inline unsigned int i801_get_adapter_class(struct i801_priv *priv) ++{ ++ return I2C_CLASS_HWMON | I2C_CLASS_SPD; ++} ++#endif ++ ++static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) + { + unsigned char temp; + int err, i; +@@ -778,7 +1140,7 @@ static int __devinit i801_probe(struct pci_dev *dev, + + i2c_set_adapdata(&priv->adapter, priv); + priv->adapter.owner = THIS_MODULE; +- priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; ++ priv->adapter.class = i801_get_adapter_class(priv); + priv->adapter.algo = &smbus_algorithm; + + priv->pci_dev = dev; +@@ -786,10 +1148,14 @@ static int __devinit i801_probe(struct pci_dev *dev, + case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0: + case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1: + case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2: ++ case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0: ++ case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1: ++ case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2: + priv->features |= FEATURE_IDF; + /* fall through */ + default: + priv->features |= FEATURE_I2C_BLOCK_READ; ++ priv->features |= FEATURE_IRQ; + /* fall through */ + case PCI_DEVICE_ID_INTEL_82801DB_3: + priv->features |= FEATURE_SMBUS_PEC; +@@ -826,11 +1192,13 @@ static int __devinit i801_probe(struct pci_dev *dev, + goto exit; + } + ++#if 0 + err = acpi_check_resource_conflict(&dev->resource[SMBBAR]); + if (err) { + err = -ENODEV; + goto exit; + } ++#endif + + err = pci_request_region(dev, SMBBAR, i801_driver.name); + if (err) { +@@ -849,16 +1217,30 @@ static int __devinit i801_probe(struct pci_dev *dev, + } + pci_write_config_byte(priv->pci_dev, SMBHSTCFG, temp); + +- if (temp & SMBHSTCFG_SMB_SMI_EN) ++ if (temp & SMBHSTCFG_SMB_SMI_EN) { + dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n"); +- else +- dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n"); ++ /* Disable SMBus interrupt feature if SMBus using SMI# */ ++ priv->features &= ~FEATURE_IRQ; ++ } + + /* Clear special mode bits */ + if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER)) + outb_p(inb_p(SMBAUXCTL(priv)) & + ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); + ++ if (priv->features & FEATURE_IRQ) { ++ init_waitqueue_head(&priv->waitq); ++ ++ err = request_irq(dev->irq, i801_isr, IRQF_SHARED, ++ i801_driver.name, priv); ++ if (err) { ++ dev_err(&dev->dev, "Failed to allocate irq %d: %d\n", ++ dev->irq, err); ++ goto exit_release; ++ } ++ dev_info(&dev->dev, "SMBus using PCI Interrupt\n"); ++ } ++ + /* set up the sysfs linkage to our parent device */ + priv->adapter.dev.parent = &dev->dev; + +@@ -870,14 +1252,20 @@ static int __devinit i801_probe(struct pci_dev *dev, + err = i2c_add_adapter(&priv->adapter); + if (err) { + dev_err(&dev->dev, "Failed to add SMBus adapter\n"); +- goto exit_release; ++ goto exit_free_irq; + } + + i801_probe_optional_slaves(priv); ++ /* We ignore errors - multiplexing is optional */ ++ i801_add_mux(priv); + + pci_set_drvdata(dev, priv); ++ + return 0; + ++exit_free_irq: ++ if (priv->features & FEATURE_IRQ) ++ free_irq(dev->irq, priv); + exit_release: + pci_release_region(dev, SMBBAR); + exit: +@@ -885,14 +1273,18 @@ exit: + return err; + } + +-static void __devexit i801_remove(struct pci_dev *dev) ++static void i801_remove(struct pci_dev *dev) + { + struct i801_priv *priv = pci_get_drvdata(dev); + ++ i801_del_mux(priv); + i2c_del_adapter(&priv->adapter); + pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); ++ ++ if (priv->features & FEATURE_IRQ) ++ free_irq(dev->irq, priv); + pci_release_region(dev, SMBBAR); +- pci_set_drvdata(dev, NULL); ++ + kfree(priv); + /* + * do not call pci_disable_device(dev) since it can cause hard hangs on +@@ -926,7 +1318,7 @@ static struct pci_driver i801_driver = { + .name = "i801_smbus", + .id_table = i801_ids, + .probe = i801_probe, +- .remove = __devexit_p(i801_remove), ++ .remove = i801_remove, + .suspend = i801_suspend, + .resume = i801_resume, + }; +@@ -943,8 +1335,7 @@ static void __exit i2c_i801_exit(void) + pci_unregister_driver(&i801_driver); + } + +-MODULE_AUTHOR("Mark D. Studebaker , " +- "Jean Delvare "); ++MODULE_AUTHOR("Mark D. Studebaker , Jean Delvare "); + MODULE_DESCRIPTION("I801 SMBus driver"); + MODULE_LICENSE("GPL"); + +diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c +new file mode 100644 +index 0000000..9058fc6 +--- /dev/null ++++ b/drivers/i2c/busses/i2c-ismt.c +@@ -0,0 +1,993 @@ ++/* ++ * This file is provided under a dual BSD/GPLv2 license. When using or ++ * redistributing this file, you may do so under either license. ++ * ++ * Copyright(c) 2012 Intel Corporation. All rights reserved. ++ * ++ * GPL LICENSE SUMMARY ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of version 2 of the GNU General Public License 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * The full GNU General Public License is included in this distribution ++ * in the file called LICENSE.GPL. ++ * ++ * BSD LICENSE ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Intel Corporation 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 COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER 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. ++ */ ++ ++/* ++ * Supports the SMBus Message Transport (SMT) in the Intel Atom Processor ++ * S12xx Product Family. ++ * ++ * Features supported by this driver: ++ * Hardware PEC yes ++ * Block buffer yes ++ * Block process call transaction no ++ * Slave mode no ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* PCI Address Constants */ ++#define SMBBAR 0 ++ ++/* PCI DIDs for the Intel SMBus Message Transport (SMT) Devices */ ++#define PCI_DEVICE_ID_INTEL_S1200_SMT0 0x0c59 ++#define PCI_DEVICE_ID_INTEL_S1200_SMT1 0x0c5a ++#define PCI_DEVICE_ID_INTEL_AVOTON_SMT 0x1f15 ++ ++#define ISMT_DESC_ENTRIES 32 /* number of descriptor entries */ ++#define ISMT_MAX_RETRIES 3 /* number of SMBus retries to attempt */ ++ ++/* Hardware Descriptor Constants - Control Field */ ++#define ISMT_DESC_CWRL 0x01 /* Command/Write Length */ ++#define ISMT_DESC_BLK 0X04 /* Perform Block Transaction */ ++#define ISMT_DESC_FAIR 0x08 /* Set fairness flag upon successful arbit. */ ++#define ISMT_DESC_PEC 0x10 /* Packet Error Code */ ++#define ISMT_DESC_I2C 0x20 /* I2C Enable */ ++#define ISMT_DESC_INT 0x40 /* Interrupt */ ++#define ISMT_DESC_SOE 0x80 /* Stop On Error */ ++ ++/* Hardware Descriptor Constants - Status Field */ ++#define ISMT_DESC_SCS 0x01 /* Success */ ++#define ISMT_DESC_DLTO 0x04 /* Data Low Time Out */ ++#define ISMT_DESC_NAK 0x08 /* NAK Received */ ++#define ISMT_DESC_CRC 0x10 /* CRC Error */ ++#define ISMT_DESC_CLTO 0x20 /* Clock Low Time Out */ ++#define ISMT_DESC_COL 0x40 /* Collisions */ ++#define ISMT_DESC_LPR 0x80 /* Large Packet Received */ ++ ++/* Macros */ ++#define ISMT_DESC_ADDR_RW(addr, rw) (((addr) << 1) | (rw)) ++ ++/* iSMT General Register address offsets (SMBBAR + ) */ ++#define ISMT_GR_GCTRL 0x000 /* General Control */ ++#define ISMT_GR_SMTICL 0x008 /* SMT Interrupt Cause Location */ ++#define ISMT_GR_ERRINTMSK 0x010 /* Error Interrupt Mask */ ++#define ISMT_GR_ERRAERMSK 0x014 /* Error AER Mask */ ++#define ISMT_GR_ERRSTS 0x018 /* Error Status */ ++#define ISMT_GR_ERRINFO 0x01c /* Error Information */ ++ ++/* iSMT Master Registers */ ++#define ISMT_MSTR_MDBA 0x100 /* Master Descriptor Base Address */ ++#define ISMT_MSTR_MCTRL 0x108 /* Master Control */ ++#define ISMT_MSTR_MSTS 0x10c /* Master Status */ ++#define ISMT_MSTR_MDS 0x110 /* Master Descriptor Size */ ++#define ISMT_MSTR_RPOLICY 0x114 /* Retry Policy */ ++ ++/* iSMT Miscellaneous Registers */ ++#define ISMT_SPGT 0x300 /* SMBus PHY Global Timing */ ++ ++/* General Control Register (GCTRL) bit definitions */ ++#define ISMT_GCTRL_TRST 0x04 /* Target Reset */ ++#define ISMT_GCTRL_KILL 0x08 /* Kill */ ++#define ISMT_GCTRL_SRST 0x40 /* Soft Reset */ ++ ++/* Master Control Register (MCTRL) bit definitions */ ++#define ISMT_MCTRL_SS 0x01 /* Start/Stop */ ++#define ISMT_MCTRL_MEIE 0x10 /* Master Error Interrupt Enable */ ++#define ISMT_MCTRL_FMHP 0x00ff0000 /* Firmware Master Head Ptr (FMHP) */ ++ ++/* Master Status Register (MSTS) bit definitions */ ++#define ISMT_MSTS_HMTP 0xff0000 /* HW Master Tail Pointer (HMTP) */ ++#define ISMT_MSTS_MIS 0x20 /* Master Interrupt Status (MIS) */ ++#define ISMT_MSTS_MEIS 0x10 /* Master Error Int Status (MEIS) */ ++#define ISMT_MSTS_IP 0x01 /* In Progress */ ++ ++/* Master Descriptor Size (MDS) bit definitions */ ++#define ISMT_MDS_MASK 0xff /* Master Descriptor Size mask (MDS) */ ++ ++/* SMBus PHY Global Timing Register (SPGT) bit definitions */ ++#define ISMT_SPGT_SPD_MASK 0xc0000000 /* SMBus Speed mask */ ++#define ISMT_SPGT_SPD_80K 0x00 /* 80 kHz */ ++#define ISMT_SPGT_SPD_100K (0x1 << 30) /* 100 kHz */ ++#define ISMT_SPGT_SPD_400K (0x2 << 30) /* 400 kHz */ ++#define ISMT_SPGT_SPD_1M (0x3 << 30) /* 1 MHz */ ++ ++/* MSI Control Register (MSICTL) bit definitions */ ++#define ISMT_MSICTL_MSIE 0x01 /* MSI Enable */ ++ ++/** ++ * ismt_ids - PCI device IDs supported by this driver ++ */ ++static DEFINE_PCI_DEVICE_TABLE(ismt_ids) = { ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT0) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT1) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMT) }, ++ { 0, } ++}; ++ ++MODULE_DEVICE_TABLE(pci, ismt_ids); ++ ++/* Bus speed control bits for slow debuggers - refer to the docs for usage */ ++static unsigned int bus_speed = 100; ++static unsigned int delay = 1000; ++module_param(bus_speed, uint, S_IRUGO); ++MODULE_PARM_DESC(bus_speed, "Bus Speed in kHz (1000 by default)"); ++module_param(delay, uint, S_IRUGO); ++MODULE_PARM_DESC(delay, "Delay in microsecs before access (1000 by default)"); ++ ++/** ++ * __ismt_desc_dump() - dump the contents of a specific descriptor ++ */ ++static void __ismt_desc_dump(struct device *dev, const struct ismt_desc *desc) ++{ ++ ++ dev_dbg(dev, "Descriptor struct: %p\n", desc); ++ dev_dbg(dev, "\ttgtaddr_rw=0x%02X\n", desc->tgtaddr_rw); ++ dev_dbg(dev, "\twr_len_cmd=0x%02X\n", desc->wr_len_cmd); ++ dev_dbg(dev, "\trd_len= 0x%02X\n", desc->rd_len); ++ dev_dbg(dev, "\tcontrol= 0x%02X\n", desc->control); ++ dev_dbg(dev, "\tstatus= 0x%02X\n", desc->status); ++ dev_dbg(dev, "\tretry= 0x%02X\n", desc->retry); ++ dev_dbg(dev, "\trxbytes= 0x%02X\n", desc->rxbytes); ++ dev_dbg(dev, "\ttxbytes= 0x%02X\n", desc->txbytes); ++ dev_dbg(dev, "\tdptr_low= 0x%08X\n", desc->dptr_low); ++ dev_dbg(dev, "\tdptr_high= 0x%08X\n", desc->dptr_high); ++} ++/** ++ * ismt_desc_dump() - dump the contents of a descriptor for debug purposes ++ * @priv: iSMT private data ++ */ ++static void ismt_desc_dump(struct ismt_priv *priv) ++{ ++ struct device *dev = &priv->pci_dev->dev; ++ struct ismt_desc *desc = &priv->hw[priv->head]; ++ ++ dev_dbg(dev, "Dump of the descriptor struct: 0x%X\n", priv->head); ++ __ismt_desc_dump(dev, desc); ++} ++ ++/** ++ * ismt_gen_reg_dump() - dump the iSMT General Registers ++ * @priv: iSMT private data ++ */ ++static void ismt_gen_reg_dump(struct ismt_priv *priv) ++{ ++ struct device *dev = &priv->pci_dev->dev; ++ ++ dev_dbg(dev, "Dump of the iSMT General Registers\n"); ++ dev_dbg(dev, " GCTRL.... : (0x%p)=0x%X\n", ++ priv->smba + ISMT_GR_GCTRL, ++ readl(priv->smba + ISMT_GR_GCTRL)); ++ dev_dbg(dev, " SMTICL... : (0x%p)=0x%016llX\n", ++ priv->smba + ISMT_GR_SMTICL, ++ (long long unsigned int)readq(priv->smba + ISMT_GR_SMTICL)); ++ dev_dbg(dev, " ERRINTMSK : (0x%p)=0x%X\n", ++ priv->smba + ISMT_GR_ERRINTMSK, ++ readl(priv->smba + ISMT_GR_ERRINTMSK)); ++ dev_dbg(dev, " ERRAERMSK : (0x%p)=0x%X\n", ++ priv->smba + ISMT_GR_ERRAERMSK, ++ readl(priv->smba + ISMT_GR_ERRAERMSK)); ++ dev_dbg(dev, " ERRSTS... : (0x%p)=0x%X\n", ++ priv->smba + ISMT_GR_ERRSTS, ++ readl(priv->smba + ISMT_GR_ERRSTS)); ++ dev_dbg(dev, " ERRINFO.. : (0x%p)=0x%X\n", ++ priv->smba + ISMT_GR_ERRINFO, ++ readl(priv->smba + ISMT_GR_ERRINFO)); ++} ++ ++/** ++ * ismt_mstr_reg_dump() - dump the iSMT Master Registers ++ * @priv: iSMT private data ++ */ ++static void ismt_mstr_reg_dump(struct ismt_priv *priv) ++{ ++ struct device *dev = &priv->pci_dev->dev; ++ ++ dev_dbg(dev, "Dump of the iSMT Master Registers\n"); ++ dev_dbg(dev, " MDBA..... : (0x%p)=0x%016llX\n", ++ priv->smba + ISMT_MSTR_MDBA, ++ (long long unsigned int)readq(priv->smba + ISMT_MSTR_MDBA)); ++ dev_dbg(dev, " MCTRL.... : (0x%p)=0x%X\n", ++ priv->smba + ISMT_MSTR_MCTRL, ++ readl(priv->smba + ISMT_MSTR_MCTRL)); ++ dev_dbg(dev, " MSTS..... : (0x%p)=0x%X\n", ++ priv->smba + ISMT_MSTR_MSTS, ++ readl(priv->smba + ISMT_MSTR_MSTS)); ++ dev_dbg(dev, " MDS...... : (0x%p)=0x%X\n", ++ priv->smba + ISMT_MSTR_MDS, ++ readl(priv->smba + ISMT_MSTR_MDS)); ++ dev_dbg(dev, " RPOLICY.. : (0x%p)=0x%X\n", ++ priv->smba + ISMT_MSTR_RPOLICY, ++ readl(priv->smba + ISMT_MSTR_RPOLICY)); ++ dev_dbg(dev, " SPGT..... : (0x%p)=0x%X\n", ++ priv->smba + ISMT_SPGT, ++ readl(priv->smba + ISMT_SPGT)); ++} ++ ++/** ++ * ismt_submit_desc() - add a descriptor to the ring ++ * @priv: iSMT private data ++ */ ++static void ismt_submit_desc(struct ismt_priv *priv) ++{ ++ uint fmhp; ++ uint val; ++ ++ ismt_desc_dump(priv); ++ ismt_gen_reg_dump(priv); ++ ismt_mstr_reg_dump(priv); ++ ++ /* Set the FMHP (Firmware Master Head Pointer)*/ ++ fmhp = ((priv->head + 1) % ISMT_DESC_ENTRIES) << 16; ++ val = readl(priv->smba + ISMT_MSTR_MCTRL); ++ writel((val & ~ISMT_MCTRL_FMHP) | fmhp, ++ priv->smba + ISMT_MSTR_MCTRL); ++ ++ /* Set the start bit */ ++ val = readl(priv->smba + ISMT_MSTR_MCTRL); ++ writel(val | ISMT_MCTRL_SS, ++ priv->smba + ISMT_MSTR_MCTRL); ++} ++ ++/** ++ * ismt_process_desc() - handle the completion of the descriptor ++ * @desc: the iSMT hardware descriptor ++ * @data: data buffer from the upper layer ++ * @priv: ismt_priv struct holding our dma buffer ++ * @size: SMBus transaction type ++ * @read_write: flag to indicate if this is a read or write ++ */ ++static int ismt_process_desc(const struct ismt_desc *desc, ++ union i2c_smbus_data *data, ++ struct ismt_priv *priv, int size, ++ char read_write) ++{ ++ u8 *dma_buffer = priv->dma_buffer; ++ ++ dev_dbg(&priv->pci_dev->dev, "Processing completed descriptor\n"); ++ __ismt_desc_dump(&priv->pci_dev->dev, desc); ++ ++ if (desc->status & ISMT_DESC_SCS) { ++ if (read_write == I2C_SMBUS_WRITE && ++ size != I2C_SMBUS_PROC_CALL) ++ return 0; ++ ++ switch (size) { ++ case I2C_SMBUS_BYTE: ++ case I2C_SMBUS_BYTE_DATA: ++ data->byte = dma_buffer[0]; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ case I2C_SMBUS_PROC_CALL: ++ data->word = dma_buffer[0] | (dma_buffer[1] << 8); ++ break; ++ case I2C_SMBUS_BLOCK_DATA: ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ memcpy(&data->block[1], dma_buffer, desc->rxbytes); ++ data->block[0] = desc->rxbytes; ++ break; ++ } ++ return 0; ++ } ++ ++ if (likely(desc->status & ISMT_DESC_NAK)) ++ return -ENXIO; ++ ++ if (desc->status & ISMT_DESC_CRC) ++ return -EBADMSG; ++ ++ if (desc->status & ISMT_DESC_COL) ++ return -EAGAIN; ++ ++ if (desc->status & ISMT_DESC_LPR) ++ return -EPROTO; ++ ++ if (desc->status & (ISMT_DESC_DLTO | ISMT_DESC_CLTO)) ++ return -ETIMEDOUT; ++ ++ return -EIO; ++} ++ ++/** ++ * ismt_access() - process an SMBus command ++ * @adap: the i2c host adapter ++ * @addr: address of the i2c/SMBus target ++ * @flags: command options ++ * @read_write: read from or write to device ++ * @command: the i2c/SMBus command to issue ++ * @size: SMBus transaction type ++ * @data: read/write data buffer ++ */ ++static int ismt_access(struct i2c_adapter *adap, u16 addr, ++ unsigned short flags, char read_write, u8 command, ++ int size, union i2c_smbus_data *data) ++{ ++ int ret; ++ dma_addr_t dma_addr = 0; /* address of the data buffer */ ++ u8 dma_size = 0; ++ enum dma_data_direction dma_direction = 0; ++ struct ismt_desc *desc; ++ struct ismt_priv *priv = i2c_get_adapdata(adap); ++ struct device *dev = &priv->pci_dev->dev; ++ ++ if (delay > 0) ++ udelay(delay); ++ ++ desc = &priv->hw[priv->head]; ++ ++ /* Initialize the DMA buffer */ ++ memset(priv->dma_buffer, 0, sizeof(priv->dma_buffer)); ++ ++ /* Initialize the descriptor */ ++ memset(desc, 0, sizeof(struct ismt_desc)); ++ desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write); ++ ++ /* Initialize common control bits */ ++ if (likely(priv->using_msi)) ++ desc->control = ISMT_DESC_INT | ISMT_DESC_FAIR; ++ else ++ desc->control = ISMT_DESC_FAIR; ++ ++ if ((flags & I2C_CLIENT_PEC) && (size != I2C_SMBUS_QUICK) ++ && (size != I2C_SMBUS_I2C_BLOCK_DATA)) ++ desc->control |= ISMT_DESC_PEC; ++ ++ switch (size) { ++ case I2C_SMBUS_QUICK: ++ dev_dbg(dev, "I2C_SMBUS_QUICK\n"); ++ break; ++ ++ case I2C_SMBUS_BYTE: ++ if (read_write == I2C_SMBUS_WRITE) { ++ /* ++ * Send Byte ++ * The command field contains the write data ++ */ ++ dev_dbg(dev, "I2C_SMBUS_BYTE: WRITE\n"); ++ desc->control |= ISMT_DESC_CWRL; ++ desc->wr_len_cmd = command; ++ } else { ++ /* Receive Byte */ ++ dev_dbg(dev, "I2C_SMBUS_BYTE: READ\n"); ++ dma_size = 1; ++ dma_direction = DMA_FROM_DEVICE; ++ desc->rd_len = 1; ++ } ++ break; ++ ++ case I2C_SMBUS_BYTE_DATA: ++ if (read_write == I2C_SMBUS_WRITE) { ++ /* ++ * Write Byte ++ * Command plus 1 data byte ++ */ ++ dev_dbg(dev, "I2C_SMBUS_BYTE_DATA: WRITE\n"); ++ desc->wr_len_cmd = 2; ++ dma_size = 2; ++ dma_direction = DMA_TO_DEVICE; ++ priv->dma_buffer[0] = command; ++ priv->dma_buffer[1] = data->byte; ++ } else { ++ /* Read Byte */ ++ dev_dbg(dev, "I2C_SMBUS_BYTE_DATA: READ\n"); ++ desc->control |= ISMT_DESC_CWRL; ++ desc->wr_len_cmd = command; ++ desc->rd_len = 1; ++ dma_size = 1; ++ dma_direction = DMA_FROM_DEVICE; ++ } ++ break; ++ ++ case I2C_SMBUS_WORD_DATA: ++ if (read_write == I2C_SMBUS_WRITE) { ++ /* Write Word */ ++ dev_dbg(dev, "I2C_SMBUS_WORD_DATA: WRITE\n"); ++ desc->wr_len_cmd = 3; ++ dma_size = 3; ++ dma_direction = DMA_TO_DEVICE; ++ priv->dma_buffer[0] = command; ++ priv->dma_buffer[1] = data->word & 0xff; ++ priv->dma_buffer[2] = data->word >> 8; ++ } else { ++ /* Read Word */ ++ dev_dbg(dev, "I2C_SMBUS_WORD_DATA: READ\n"); ++ desc->wr_len_cmd = command; ++ desc->control |= ISMT_DESC_CWRL; ++ desc->rd_len = 2; ++ dma_size = 2; ++ dma_direction = DMA_FROM_DEVICE; ++ } ++ break; ++ ++ case I2C_SMBUS_PROC_CALL: ++ dev_dbg(dev, "I2C_SMBUS_PROC_CALL\n"); ++ desc->wr_len_cmd = 3; ++ desc->rd_len = 2; ++ dma_size = 3; ++ dma_direction = DMA_BIDIRECTIONAL; ++ priv->dma_buffer[0] = command; ++ priv->dma_buffer[1] = data->word & 0xff; ++ priv->dma_buffer[2] = data->word >> 8; ++ break; ++ ++ case I2C_SMBUS_BLOCK_DATA: ++ if (read_write == I2C_SMBUS_WRITE) { ++ /* Block Write */ ++ dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: WRITE\n"); ++ dma_size = data->block[0] + 1; ++ dma_direction = DMA_TO_DEVICE; ++ desc->wr_len_cmd = dma_size; ++ desc->control |= ISMT_DESC_BLK; ++ priv->dma_buffer[0] = command; ++ memcpy(&priv->dma_buffer[1], &data->block[1], dma_size); ++ } else { ++ /* Block Read */ ++ dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: READ\n"); ++ dma_size = I2C_SMBUS_BLOCK_MAX; ++ dma_direction = DMA_FROM_DEVICE; ++ desc->rd_len = dma_size; ++ desc->wr_len_cmd = command; ++ desc->control |= (ISMT_DESC_BLK | ISMT_DESC_CWRL); ++ } ++ break; ++ ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ /* Make sure the length is valid */ ++ if (data->block[0] < 1) ++ data->block[0] = 1; ++ ++ if (data->block[0] > I2C_SMBUS_BLOCK_MAX) ++ data->block[0] = I2C_SMBUS_BLOCK_MAX; ++ ++ if (read_write == I2C_SMBUS_WRITE) { ++ /* i2c Block Write */ ++ dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: WRITE\n"); ++ dma_size = data->block[0] + 1; ++ dma_direction = DMA_TO_DEVICE; ++ desc->wr_len_cmd = dma_size; ++ desc->control |= ISMT_DESC_I2C; ++ priv->dma_buffer[0] = command; ++ memcpy(&priv->dma_buffer[1], &data->block[1], dma_size); ++ } else { ++ /* i2c Block Read */ ++ dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: READ\n"); ++ dma_size = data->block[0]; ++ dma_direction = DMA_FROM_DEVICE; ++ desc->rd_len = dma_size; ++ desc->wr_len_cmd = command; ++ desc->control |= (ISMT_DESC_I2C | ISMT_DESC_CWRL); ++ /* ++ * Per the "Table 15-15. I2C Commands", ++ * in the External Design Specification (EDS), ++ * (Document Number: 508084, Revision: 2.0), ++ * the _rw bit must be 0 ++ */ ++ desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, 0); ++ } ++ break; ++ ++ default: ++ dev_err(dev, "Unsupported transaction %d\n", ++ size); ++ return -EOPNOTSUPP; ++ } ++ ++ /* map the data buffer */ ++ if (dma_size != 0) { ++ dev_dbg(dev, " dev=%p\n", dev); ++ dev_dbg(dev, " data=%p\n", data); ++ dev_dbg(dev, " dma_buffer=%p\n", priv->dma_buffer); ++ dev_dbg(dev, " dma_size=%d\n", dma_size); ++ dev_dbg(dev, " dma_direction=%d\n", dma_direction); ++ ++ dma_addr = dma_map_single(dev, ++ priv->dma_buffer, ++ dma_size, ++ dma_direction); ++ ++ if (dma_mapping_error(dev, dma_addr)) { ++ dev_err(dev, "Error in mapping dma buffer %p\n", ++ priv->dma_buffer); ++ return -EIO; ++ } ++ ++ dev_dbg(dev, " dma_addr = 0x%016llX\n", ++ (unsigned long long)dma_addr); ++ ++ desc->dptr_low = lower_32_bits(dma_addr); ++ desc->dptr_high = upper_32_bits(dma_addr); ++ } ++ ++ INIT_COMPLETION(priv->cmp); ++ ++ /* Add the descriptor */ ++ ismt_submit_desc(priv); ++ ++ /* Now we wait for interrupt completion, 1s */ ++ ret = wait_for_completion_timeout(&priv->cmp, HZ*1); ++ ++ /* unmap the data buffer */ ++ if (dma_size != 0) ++ dma_unmap_single(&adap->dev, dma_addr, dma_size, dma_direction); ++ ++ if (unlikely(!ret)) { ++ dev_err(dev, "completion wait timed out\n"); ++ ret = -ETIMEDOUT; ++ goto out; ++ } ++ ++ /* do any post processing of the descriptor here */ ++ ret = ismt_process_desc(desc, data, priv, size, read_write); ++ ++out: ++ /* Update the ring pointer */ ++ priv->head++; ++ priv->head %= ISMT_DESC_ENTRIES; ++ ++ return ret; ++} ++ ++/** ++ * ismt_func() - report which i2c commands are supported by this adapter ++ * @adap: the i2c host adapter ++ */ ++static u32 ismt_func(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_SMBUS_QUICK | ++ I2C_FUNC_SMBUS_BYTE | ++ I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA | ++ I2C_FUNC_SMBUS_PROC_CALL | ++ I2C_FUNC_SMBUS_BLOCK_DATA | ++ I2C_FUNC_SMBUS_I2C_BLOCK | ++ I2C_FUNC_SMBUS_PEC; ++} ++ ++/** ++ * smbus_algorithm - the adapter algorithm and supported functionality ++ * @smbus_xfer: the adapter algorithm ++ * @functionality: functionality supported by the adapter ++ */ ++static const struct i2c_algorithm smbus_algorithm = { ++ .smbus_xfer = ismt_access, ++ .functionality = ismt_func, ++}; ++ ++/** ++ * ismt_handle_isr() - interrupt handler bottom half ++ * @priv: iSMT private data ++ */ ++static irqreturn_t ismt_handle_isr(struct ismt_priv *priv) ++{ ++ complete(&priv->cmp); ++ ++ return IRQ_HANDLED; ++} ++ ++ ++/** ++ * ismt_do_interrupt() - IRQ interrupt handler ++ * @vec: interrupt vector ++ * @data: iSMT private data ++ */ ++static irqreturn_t ismt_do_interrupt(int vec, void *data) ++{ ++ u32 val; ++ struct ismt_priv *priv = data; ++ ++ /* ++ * check to see it's our interrupt, return IRQ_NONE if not ours ++ * since we are sharing interrupt ++ */ ++ val = readl(priv->smba + ISMT_MSTR_MSTS); ++ ++ if (!(val & (ISMT_MSTS_MIS | ISMT_MSTS_MEIS))) ++ return IRQ_NONE; ++ else ++ writel(val | ISMT_MSTS_MIS | ISMT_MSTS_MEIS, ++ priv->smba + ISMT_MSTR_MSTS); ++ ++ return ismt_handle_isr(priv); ++} ++ ++/** ++ * ismt_do_msi_interrupt() - MSI interrupt handler ++ * @vec: interrupt vector ++ * @data: iSMT private data ++ */ ++static irqreturn_t ismt_do_msi_interrupt(int vec, void *data) ++{ ++ return ismt_handle_isr(data); ++} ++ ++/** ++ * ismt_hw_init() - initialize the iSMT hardware ++ * @priv: iSMT private data ++ */ ++static void ismt_hw_init(struct ismt_priv *priv) ++{ ++ u32 val; ++ struct device *dev = &priv->pci_dev->dev; ++ ++ /* initialize the Master Descriptor Base Address (MDBA) */ ++ writeq(priv->io_rng_dma, priv->smba + ISMT_MSTR_MDBA); ++ ++ /* initialize the Master Control Register (MCTRL) */ ++ writel(ISMT_MCTRL_MEIE, priv->smba + ISMT_MSTR_MCTRL); ++ ++ /* initialize the Master Status Register (MSTS) */ ++ writel(0, priv->smba + ISMT_MSTR_MSTS); ++ ++ /* initialize the Master Descriptor Size (MDS) */ ++ val = readl(priv->smba + ISMT_MSTR_MDS); ++ writel((val & ~ISMT_MDS_MASK) | (ISMT_DESC_ENTRIES - 1), ++ priv->smba + ISMT_MSTR_MDS); ++ ++ /* ++ * Set the SMBus speed (could use this for slow HW debuggers) ++ */ ++ ++ val = readl(priv->smba + ISMT_SPGT); ++ ++ switch (bus_speed) { ++ case 0: ++ break; ++ ++ case 80: ++ dev_dbg(dev, "Setting SMBus clock to 80 kHz\n"); ++ writel(((val & ~ISMT_SPGT_SPD_MASK) | ISMT_SPGT_SPD_80K), ++ priv->smba + ISMT_SPGT); ++ break; ++ ++ case 100: ++ dev_dbg(dev, "Setting SMBus clock to 100 kHz\n"); ++ writel(((val & ~ISMT_SPGT_SPD_MASK) | ISMT_SPGT_SPD_100K), ++ priv->smba + ISMT_SPGT); ++ break; ++ ++ case 400: ++ dev_dbg(dev, "Setting SMBus clock to 400 kHz\n"); ++ writel(((val & ~ISMT_SPGT_SPD_MASK) | ISMT_SPGT_SPD_400K), ++ priv->smba + ISMT_SPGT); ++ break; ++ ++ case 1000: ++ dev_dbg(dev, "Setting SMBus clock to 1000 kHz\n"); ++ writel(((val & ~ISMT_SPGT_SPD_MASK) | ISMT_SPGT_SPD_1M), ++ priv->smba + ISMT_SPGT); ++ break; ++ ++ default: ++ dev_warn(dev, "Invalid SMBus clock speed, only 0, 80, 100, 400, and 1000 are valid\n"); ++ break; ++ } ++ ++ val = readl(priv->smba + ISMT_SPGT); ++ ++ switch (val & ISMT_SPGT_SPD_MASK) { ++ case ISMT_SPGT_SPD_80K: ++ bus_speed = 80; ++ break; ++ case ISMT_SPGT_SPD_100K: ++ bus_speed = 100; ++ break; ++ case ISMT_SPGT_SPD_400K: ++ bus_speed = 400; ++ break; ++ case ISMT_SPGT_SPD_1M: ++ bus_speed = 1000; ++ break; ++ } ++ dev_info(dev, "SMBus clock is running at %d kHz with delay %d us\n", bus_speed, delay); ++} ++ ++/** ++ * ismt_dev_init() - initialize the iSMT data structures ++ * @priv: iSMT private data ++ */ ++static int ismt_dev_init(struct ismt_priv *priv) ++{ ++ /* allocate memory for the descriptor */ ++ priv->hw = dmam_alloc_coherent(&priv->pci_dev->dev, ++ (ISMT_DESC_ENTRIES ++ * sizeof(struct ismt_desc)), ++ &priv->io_rng_dma, ++ GFP_KERNEL); ++ if (!priv->hw) ++ return -ENOMEM; ++ ++ memset(priv->hw, 0, (ISMT_DESC_ENTRIES * sizeof(struct ismt_desc))); ++ ++ priv->head = 0; ++ init_completion(&priv->cmp); ++ ++ return 0; ++} ++ ++/** ++ * ismt_int_init() - initialize interrupts ++ * @priv: iSMT private data ++ */ ++static int ismt_int_init(struct ismt_priv *priv) ++{ ++ int err; ++ ++ /* Try using MSI interrupts */ ++ err = pci_enable_msi(priv->pci_dev); ++ if (err) { ++ dev_warn(&priv->pci_dev->dev, ++ "Unable to use MSI interrupts, falling back to legacy\n"); ++ goto intx; ++ } ++ ++ err = devm_request_irq(&priv->pci_dev->dev, ++ priv->pci_dev->irq, ++ ismt_do_msi_interrupt, ++ 0, ++ "ismt-msi", ++ priv); ++ if (err) { ++ pci_disable_msi(priv->pci_dev); ++ goto intx; ++ } ++ ++ priv->using_msi = true; ++ goto done; ++ ++ /* Try using legacy interrupts */ ++intx: ++ err = devm_request_irq(&priv->pci_dev->dev, ++ priv->pci_dev->irq, ++ ismt_do_interrupt, ++ IRQF_SHARED, ++ "ismt-intx", ++ priv); ++ if (err) { ++ dev_err(&priv->pci_dev->dev, "no usable interrupts\n"); ++ return -ENODEV; ++ } ++ ++ priv->using_msi = false; ++ ++done: ++ return 0; ++} ++ ++static struct pci_driver ismt_driver; ++ ++/** ++ * ismt_probe() - probe for iSMT devices ++ * @pdev: PCI-Express device ++ * @id: PCI-Express device ID ++ */ ++static int ++ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id) ++{ ++ int err; ++ struct ismt_priv *priv; ++ unsigned long start, len; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ pci_set_drvdata(pdev, priv); ++ i2c_set_adapdata(&priv->adapter, priv); ++ priv->adapter.owner = THIS_MODULE; ++ ++ priv->adapter.class = I2C_CLASS_HWMON; ++ ++ priv->adapter.algo = &smbus_algorithm; ++ ++ /* set up the sysfs linkage to our parent device */ ++ priv->adapter.dev.parent = &pdev->dev; ++ ++ /* number of retries on lost arbitration */ ++ priv->adapter.retries = ISMT_MAX_RETRIES; ++ ++ priv->pci_dev = pdev; ++ ++ err = pcim_enable_device(pdev); ++ if (err) { ++ dev_err(&pdev->dev, "Failed to enable SMBus PCI device (%d)\n", ++ err); ++ return err; ++ } ++ ++ /* enable bus mastering */ ++ pci_set_master(pdev); ++ ++ /* Determine the address of the SMBus area */ ++ start = pci_resource_start(pdev, SMBBAR); ++ len = pci_resource_len(pdev, SMBBAR); ++ if (!start || !len) { ++ dev_err(&pdev->dev, ++ "SMBus base address uninitialized, upgrade BIOS\n"); ++ return -ENODEV; ++ } ++ ++ snprintf(priv->adapter.name, sizeof(priv->adapter.name), ++ "SMBus iSMT adapter at %lx", start); ++ ++ dev_dbg(&priv->pci_dev->dev, " start=0x%lX\n", start); ++ dev_dbg(&priv->pci_dev->dev, " len=0x%lX\n", len); ++ ++ err = acpi_check_resource_conflict(&pdev->resource[SMBBAR]); ++ if (err) { ++ dev_err(&pdev->dev, "ACPI resource conflict!\n"); ++ return err; ++ } ++ ++ err = pci_request_region(pdev, SMBBAR, ismt_driver.name); ++ if (err) { ++ dev_err(&pdev->dev, ++ "Failed to request SMBus region 0x%lx-0x%lx\n", ++ start, start + len); ++ return err; ++ } ++ ++ priv->smba = pcim_iomap(pdev, SMBBAR, len); ++ if (!priv->smba) { ++ dev_err(&pdev->dev, "Unable to ioremap SMBus BAR\n"); ++ err = -ENODEV; ++ goto fail; ++ } ++ ++ if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) || ++ (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)) { ++ if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) || ++ (pci_set_consistent_dma_mask(pdev, ++ DMA_BIT_MASK(32)) != 0)) { ++ dev_err(&pdev->dev, "pci_set_dma_mask fail %p\n", ++ pdev); ++ err = -ENODEV; ++ goto fail; ++ } ++ } ++ ++ err = ismt_dev_init(priv); ++ if (err) ++ goto fail; ++ ++ ismt_hw_init(priv); ++ ++ err = ismt_int_init(priv); ++ if (err) ++ goto fail; ++ ++ err = i2c_add_adapter(&priv->adapter); ++ if (err) { ++ dev_err(&pdev->dev, "Failed to add SMBus iSMT adapter\n"); ++ err = -ENODEV; ++ goto fail; ++ } ++ return 0; ++ ++fail: ++ pci_release_region(pdev, SMBBAR); ++ return err; ++} ++ ++/** ++ * ismt_remove() - release driver resources ++ * @pdev: PCI-Express device ++ */ ++static void ismt_remove(struct pci_dev *pdev) ++{ ++ struct ismt_priv *priv = pci_get_drvdata(pdev); ++ ++ i2c_del_adapter(&priv->adapter); ++ pci_release_region(pdev, SMBBAR); ++} ++ ++/** ++ * ismt_suspend() - place the device in suspend ++ * @pdev: PCI-Express device ++ * @mesg: PM message ++ */ ++#ifdef CONFIG_PM ++static int ismt_suspend(struct pci_dev *pdev, pm_message_t mesg) ++{ ++ pci_save_state(pdev); ++ pci_set_power_state(pdev, pci_choose_state(pdev, mesg)); ++ return 0; ++} ++ ++/** ++ * ismt_resume() - PCI resume code ++ * @pdev: PCI-Express device ++ */ ++static int ismt_resume(struct pci_dev *pdev) ++{ ++ pci_set_power_state(pdev, PCI_D0); ++ pci_restore_state(pdev); ++ return pci_enable_device(pdev); ++} ++ ++#else ++ ++#define ismt_suspend NULL ++#define ismt_resume NULL ++ ++#endif ++ ++static struct pci_driver ismt_driver = { ++ .name = "ismt_smbus", ++ .id_table = ismt_ids, ++ .probe = ismt_probe, ++ .remove = ismt_remove, ++ .suspend = ismt_suspend, ++ .resume = ismt_resume, ++}; ++ ++static int __init i2c_ismt_init(void) ++{ ++ return pci_register_driver(&ismt_driver); ++} ++ ++static void __exit i2c_ismt_exit(void) ++{ ++ pci_unregister_driver(&ismt_driver); ++} ++ ++module_init(i2c_ismt_init); ++module_exit(i2c_ismt_exit); ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_AUTHOR("Bill E. Brown "); ++MODULE_DESCRIPTION("Intel SMBus Message Transport (iSMT) driver"); +diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c +index a9941c6..5eda5a2 100644 +--- a/drivers/i2c/busses/i2c-mv64xxx.c ++++ b/drivers/i2c/busses/i2c-mv64xxx.c +@@ -81,6 +81,8 @@ enum { + }; + + struct mv64xxx_i2c_data { ++ struct i2c_msg *msgs; ++ int num_msgs; + int irq; + u32 state; + u32 action; +@@ -104,6 +106,32 @@ struct mv64xxx_i2c_data { + struct i2c_adapter adapter; + }; + ++static void ++mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, ++ struct i2c_msg *msg) ++{ ++ u32 dir = 0; ++ ++ drv_data->msg = msg; ++ drv_data->byte_posn = 0; ++ drv_data->bytes_left = msg->len; ++ drv_data->aborting = 0; ++ drv_data->rc = 0; ++ drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK | ++ MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN; ++ ++ if (msg->flags & I2C_M_RD) ++ dir = 1; ++ ++ if (msg->flags & I2C_M_TEN) { ++ drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir; ++ drv_data->addr2 = (u32)msg->addr & 0xff; ++ } else { ++ drv_data->addr1 = ((u32)msg->addr & 0x7f) << 1 | dir; ++ drv_data->addr2 = 0; ++ } ++} ++ + /* + ***************************************************************************** + * +@@ -162,7 +190,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) + if ((drv_data->bytes_left == 0) + || (drv_data->aborting + && (drv_data->byte_posn != 0))) { +- if (drv_data->send_stop) { ++ if (drv_data->send_stop || drv_data->aborting) { + drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; + drv_data->state = MV64XXX_I2C_STATE_IDLE; + } else { +@@ -239,12 +267,25 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) + { + switch(drv_data->action) { + case MV64XXX_I2C_ACTION_SEND_RESTART: ++ /* We should only get here if we have further messages */ ++ BUG_ON(drv_data->num_msgs == 0); ++ + drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START; +- drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; + writel(drv_data->cntl_bits, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); +- drv_data->block = 0; +- wake_up_interruptible(&drv_data->waitq); ++ ++ drv_data->msgs++; ++ drv_data->num_msgs--; ++ ++ /* Setup for the next message */ ++ mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs); ++ ++ /* ++ * We're never at the start of the message here, and by this ++ * time it's already too late to do any protocol mangling. ++ * Thankfully, do not advertise support for that feature. ++ */ ++ drv_data->send_stop = drv_data->num_msgs == 1; + break; + + case MV64XXX_I2C_ACTION_CONTINUE: +@@ -292,7 +333,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) + writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + drv_data->block = 0; +- wake_up_interruptible(&drv_data->waitq); ++ wake_up(&drv_data->waitq); + break; + + case MV64XXX_I2C_ACTION_INVALID: +@@ -307,7 +348,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) + writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + drv_data->block = 0; +- wake_up_interruptible(&drv_data->waitq); ++ wake_up(&drv_data->waitq); + break; + } + } +@@ -341,39 +382,13 @@ mv64xxx_i2c_intr(int irq, void *dev_id) + ***************************************************************************** + */ + static void +-mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, +- struct i2c_msg *msg) +-{ +- u32 dir = 0; +- +- drv_data->msg = msg; +- drv_data->byte_posn = 0; +- drv_data->bytes_left = msg->len; +- drv_data->aborting = 0; +- drv_data->rc = 0; +- drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK | +- MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN; +- +- if (msg->flags & I2C_M_RD) +- dir = 1; +- +- if (msg->flags & I2C_M_TEN) { +- drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir; +- drv_data->addr2 = (u32)msg->addr & 0xff; +- } else { +- drv_data->addr1 = ((u32)msg->addr & 0x7f) << 1 | dir; +- drv_data->addr2 = 0; +- } +-} +- +-static void + mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) + { + long time_left; + unsigned long flags; + char abort = 0; + +- time_left = wait_event_interruptible_timeout(drv_data->waitq, ++ time_left = wait_event_timeout(drv_data->waitq, + !drv_data->block, drv_data->adapter.timeout); + + spin_lock_irqsave(&drv_data->lock, flags); +@@ -406,36 +421,15 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) + + static int + mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, +- int is_first, int is_last) ++ int is_last) + { + unsigned long flags; + + spin_lock_irqsave(&drv_data->lock, flags); + mv64xxx_i2c_prepare_for_io(drv_data, msg); + +- if (unlikely(msg->flags & I2C_M_NOSTART)) { /* Skip start/addr phases */ +- if (drv_data->msg->flags & I2C_M_RD) { +- /* No action to do, wait for slave to send a byte */ +- drv_data->action = MV64XXX_I2C_ACTION_CONTINUE; +- drv_data->state = +- MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA; +- } else { +- drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; +- drv_data->state = +- MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK; +- drv_data->bytes_left--; +- } +- } else { +- if (is_first) { +- drv_data->action = MV64XXX_I2C_ACTION_SEND_START; +- drv_data->state = +- MV64XXX_I2C_STATE_WAITING_FOR_START_COND; +- } else { +- drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1; +- drv_data->state = +- MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK; +- } +- } ++ drv_data->action = MV64XXX_I2C_ACTION_SEND_START; ++ drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; + + drv_data->send_stop = is_last; + drv_data->block = 1; +@@ -463,16 +457,20 @@ static int + mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) + { + struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); +- int i, rc; ++ int rc, ret = num; + +- for (i = 0; i < num; i++) { +- rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i], +- i == 0, i + 1 == num); +- if (rc < 0) +- return rc; +- } ++ BUG_ON(drv_data->msgs != NULL); ++ drv_data->msgs = msgs; ++ drv_data->num_msgs = num; ++ ++ rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[0], num == 1); ++ if (rc < 0) ++ ret = rc; ++ ++ drv_data->num_msgs = 0; ++ drv_data->msgs = NULL; + +- return num; ++ return ret; + } + + static const struct i2c_algorithm mv64xxx_i2c_algo = { +diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c +index d7a4833..609794b 100644 +--- a/drivers/i2c/i2c-mux.c ++++ b/drivers/i2c/i2c-mux.c +@@ -24,6 +24,8 @@ + #include + #include + #include ++#include ++#include + + /* multiplexer per channel data */ + struct i2c_mux_priv { +@@ -31,11 +33,11 @@ struct i2c_mux_priv { + struct i2c_algorithm algo; + + struct i2c_adapter *parent; +- void *mux_dev; /* the mux chip/device */ ++ void *mux_priv; /* the mux chip/device */ + u32 chan_id; /* the channel id */ + +- int (*select)(struct i2c_adapter *, void *mux_dev, u32 chan_id); +- int (*deselect)(struct i2c_adapter *, void *mux_dev, u32 chan_id); ++ int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id); ++ int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id); + }; + + static int i2c_mux_master_xfer(struct i2c_adapter *adap, +@@ -47,11 +49,11 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap, + + /* Switch to the right mux port and perform the transfer. */ + +- ret = priv->select(parent, priv->mux_dev, priv->chan_id); ++ ret = priv->select(parent, priv->mux_priv, priv->chan_id); + if (ret >= 0) + ret = parent->algo->master_xfer(parent, msgs, num); + if (priv->deselect) +- priv->deselect(parent, priv->mux_dev, priv->chan_id); ++ priv->deselect(parent, priv->mux_priv, priv->chan_id); + + return ret; + } +@@ -67,12 +69,12 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, + + /* Select the right mux port and perform the transfer. */ + +- ret = priv->select(parent, priv->mux_dev, priv->chan_id); ++ ret = priv->select(parent, priv->mux_priv, priv->chan_id); + if (ret >= 0) + ret = parent->algo->smbus_xfer(parent, addr, flags, + read_write, command, size, data); + if (priv->deselect) +- priv->deselect(parent, priv->mux_dev, priv->chan_id); ++ priv->deselect(parent, priv->mux_priv, priv->chan_id); + + return ret; + } +@@ -87,7 +89,8 @@ static u32 i2c_mux_functionality(struct i2c_adapter *adap) + } + + struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, +- void *mux_dev, u32 force_nr, u32 chan_id, ++ struct device *mux_dev, ++ void *mux_priv, u32 force_nr, u32 chan_id, + int (*select) (struct i2c_adapter *, + void *, u32), + int (*deselect) (struct i2c_adapter *, +@@ -102,7 +105,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, + + /* Set up private adapter data */ + priv->parent = parent; +- priv->mux_dev = mux_dev; ++ priv->mux_priv = mux_priv; + priv->chan_id = chan_id; + priv->select = select; + priv->deselect = deselect; +@@ -124,6 +127,26 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, + priv->adap.algo_data = priv; + priv->adap.dev.parent = &parent->dev; + ++ /* ++ * Try to get populate the mux adapter's of_node, expands to ++ * nothing if !CONFIG_OF. ++ */ ++ if (mux_dev->of_node) { ++ struct device_node *child; ++ u32 reg; ++ int ret; ++ ++ for_each_child_of_node(mux_dev->of_node, child) { ++ ret = of_property_read_u32(child, "reg", ®); ++ if (ret) ++ continue; ++ if (chan_id == reg) { ++ priv->adap.dev.of_node = child; ++ break; ++ } ++ } ++ } ++ + if (force_nr) { + priv->adap.nr = force_nr; + ret = i2c_add_numbered_adapter(&priv->adap); +@@ -141,6 +164,8 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, + dev_info(&parent->dev, "Added multiplexed i2c bus %d\n", + i2c_adapter_id(&priv->adap)); + ++ of_i2c_register_devices(&priv->adap); ++ + return &priv->adap; + } + EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); +diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig +index 90b7a01..73ed997 100644 +--- a/drivers/i2c/muxes/Kconfig ++++ b/drivers/i2c/muxes/Kconfig +@@ -37,4 +37,16 @@ config I2C_MUX_PCA954x + This driver can also be built as a module. If so, the module + will be called pca954x. + ++config I2C_MUX_DNI_6448 ++ tristate "Delta Networks 6448 I2C Mux" ++ depends on EXPERIMENTAL ++ help ++ If you say yes here you get support for the DNI 6448 I2C Mux devices ++ ++config I2C_MUX_QUANTA ++ tristate "CumulusNetworks QUANTA I2C Mux" ++ depends on EXPERIMENTAL ++ help ++ If you say yes here you get support for the QUANTA I2C Mux devices ++ + endmenu +diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile +index 4640436..7fbdd2f 100644 +--- a/drivers/i2c/muxes/Makefile ++++ b/drivers/i2c/muxes/Makefile +@@ -4,5 +4,7 @@ + obj-$(CONFIG_I2C_MUX_GPIO) += gpio-i2cmux.o + obj-$(CONFIG_I2C_MUX_PCA9541) += pca9541.o + obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o ++obj-$(CONFIG_I2C_MUX_DNI_6448) += dni_6448_i2c_mux.o ++obj-$(CONFIG_I2C_MUX_QUANTA) += quanta-i2cmux.o + + ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG +diff --git a/drivers/i2c/muxes/dni_6448_i2c_mux.c b/drivers/i2c/muxes/dni_6448_i2c_mux.c +new file mode 100644 +index 0000000..ecbbd1d +--- /dev/null ++++ b/drivers/i2c/muxes/dni_6448_i2c_mux.c +@@ -0,0 +1,312 @@ ++/* ++ * DNI 6448 CPLD I2C multiplexer ++ * ++ * Copyright (C) 2012 Cumulus Networks, Inc. ++ * Author: Curt Brune ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * The DNI 6448 CPLD resides on the MPC8536 local bus and controls a a ++ * dual 1-of-4 high-speed FET multiplexer/demultiplexer. The details ++ * of the multiplexer are shielded from us as we only touch CPLD ++ * registers. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define CPLD_REG_PRODUCT_ID (0x07000) ++ ++#define CPLD_REG_I2C_1_CTRL (0x0e000) ++# define CPLD_I2C_1_EN_L (4) ++# define CPLD_I2C_1_SELECT_MSK (0x3) ++ ++#define CPLD_REG_I2C_2_CTRL (0x0f000) ++# define CPLD_I2C_2_SELECT_MSK (0x7) ++ ++// Expected product ID ++#define DNI_6448_PRODUCT_ID1 (0xa0) // single fixed power supply ++#define DNI_6448_PRODUCT_ID2 (0x80) // dual hot-swap power supplies ++#define DNI_6448_PRODUCT_ID3 (0xc0) // dual hot-swap power supplies ?? ++#define DNI_6448_PRODUCT_ID4 (0x20) // POE ++ ++static const char driver_name[] = "dni_6448_i2c_mux"; ++#define DRIVER_VERSION "1.1" ++ ++#undef DEBUG ++// #define DEBUG ++ ++#ifdef DEBUG ++#define LOG_DBG(fmt, args...) \ ++ do { \ ++ printk(KERN_ERR "%s:%s(): " fmt, \ ++ driver_name, __func__, ## args); \ ++ } while (0) ++#else ++#define LOG_DBG(fmt, args...) ++#endif ++ ++#define LOG_INFO(fmt, args...) \ ++ do { \ ++ printk(KERN_INFO "%s: " fmt, \ ++ driver_name, ## args); \ ++ } while (0) ++ ++#define LOG_ERR(fmt, args...) \ ++ do { \ ++ printk(KERN_ERR "%s:%s():ERROR: " fmt, \ ++ driver_name, __func__, ## args); \ ++ } while (0) ++ ++#define DNI_6448_MUX_NCHANS (8) ++ ++struct dni_6448_mux { ++ struct i2c_adapter* m_virt_adaps[DNI_6448_MUX_NCHANS]; ++ u8 __iomem* m_cpld_regs; /* Mem mapped CPLD */ ++ u8 m_last_chan; /* last register value */ ++ u32 m_mux_id; /* mux ID */ ++}; ++ ++static u16 dni_6448_num_channels[] = { ++ 0, ++ 4, // mux_id 1 has 4 channels ++ 8, // mux_id 2 has 8 channels ++}; ++ ++static int dni_6448_mux_select_chan(struct i2c_adapter *adap, ++ void *client, u32 chan) ++{ ++ struct dni_6448_mux* dev = i2c_get_clientdata(client); ++ u32 ctrl_reg; ++ u8 val, chan_mask; ++ ++ LOG_DBG("Setting mux %d to channel %d", dev->m_mux_id, chan); ++ ++ if (dev->m_mux_id == 1) { ++ ctrl_reg = CPLD_REG_I2C_1_CTRL; ++ chan_mask = CPLD_I2C_1_SELECT_MSK; ++ } ++ else { ++ ctrl_reg = CPLD_REG_I2C_2_CTRL; ++ chan_mask = CPLD_I2C_2_SELECT_MSK; ++ } ++ ++ if (chan & ~chan_mask) { ++ // bad channel ++ LOG_ERR("mux_id: %d -- trying to set non-existent channel %d", ++ dev->m_mux_id, chan); ++ return -EINVAL; ++ } ++ ++ if ( dev->m_last_chan != chan) { ++ ++ val = readb( dev->m_cpld_regs + ctrl_reg); ++ val &= ~chan_mask; ++ val |= chan; ++ writeb( val, dev->m_cpld_regs + ctrl_reg); ++ ++ dev->m_last_chan = chan; ++ } ++ ++ return 0; ++ ++} ++ ++/* ++ * I2C init/probing/exit functions ++ */ ++static int dni_6448_mux_probe(struct i2c_client* client, ++ const struct i2c_device_id* id) ++{ ++ struct i2c_adapter* adap = to_i2c_adapter(client->dev.parent); ++ int num; ++ struct dni_6448_mux* dev; ++ struct device_node* cpld; ++ u8 __iomem* cpld_regs; ++ u8 val; ++ int prop_len; ++ const void* prop; ++ u32 mux_id; ++ ++ int ret = -ENODEV; ++ ++ LOG_DBG("Entry"); ++ ++ if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) ++ goto err; ++ ++ cpld = of_find_compatible_node(NULL, NULL, "dni,6448-cpld"); ++ if (!cpld) { ++ LOG_ERR("Can not find 6448-cpld node in device tree\n"); ++ ret = -ENODEV; ++ goto err; ++ } ++ else { ++ cpld_regs = of_iomap(cpld, 0); ++ of_node_put(cpld); ++ } ++ ++ prop_len = 0; ++ prop = of_get_property( client->dev.of_node, "reg", &prop_len); ++ if ( (prop == NULL) || (prop_len != 4)) { ++ LOG_ERR("Can not find property for mux in device tree\n"); ++ LOG_ERR("prop is %sNULL. prop_len: %d\n", ++ (prop == NULL) ? "" : "not ", ++ prop_len); ++ ret = -ENODEV; ++ goto err; ++ } ++ else { ++ mux_id = *((u32*)prop); ++ LOG_DBG("mux_id: %d", mux_id); ++ } ++ ++ // Try to read a register and make sure we're good ++ val = readb( cpld_regs + CPLD_REG_PRODUCT_ID); ++ if ( (val != DNI_6448_PRODUCT_ID1) && ++ (val != DNI_6448_PRODUCT_ID2) && ++ (val != DNI_6448_PRODUCT_ID3) && ++ (val != DNI_6448_PRODUCT_ID4)) { ++ LOG_ERR("Can not verify dni-6448 product ID 0x%02x\n",val); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ dev = kzalloc(sizeof(struct dni_6448_mux), GFP_KERNEL); ++ if (!dev) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ i2c_set_clientdata(client, dev); ++ ++ dev->m_cpld_regs = cpld_regs; ++ dev->m_mux_id = mux_id; ++ ++ // Default to channel-0 and enable controller ++ if (mux_id == 1) { ++ val = readb( dev->m_cpld_regs + CPLD_REG_I2C_1_CTRL); ++ val &= ~CPLD_I2C_1_SELECT_MSK; ++ // also clear output enable, active low ++ val &= ~(1 << CPLD_I2C_1_EN_L); ++ writeb( val, dev->m_cpld_regs + CPLD_REG_I2C_1_CTRL); ++ } ++ else { ++ val = readb( dev->m_cpld_regs + CPLD_REG_I2C_2_CTRL); ++ val &= ~CPLD_I2C_2_SELECT_MSK; ++ writeb( val, dev->m_cpld_regs + CPLD_REG_I2C_2_CTRL); ++ } ++ dev->m_last_chan = 0; ++ ++ /* Now create an adapter for each channel */ ++ for (num = 0; num < dni_6448_num_channels[dev->m_mux_id]; num++) { ++ dev->m_virt_adaps[num] = ++ i2c_add_mux_adapter(adap, &client->dev, client, ++ 0, num, ++ dni_6448_mux_select_chan, ++ NULL); ++ ++ if (dev->m_virt_adaps[num] == NULL) { ++ ret = -ENODEV; ++ dev_err(&client->dev, ++ "failed to register multiplexed adapter %d\n", ++ num); ++ goto virt_reg_failed; ++ } ++ } ++ ++ dev_info(&client->dev, ++ "registered %d multiplexed buses for %s, mux_id %d\n", ++ num, driver_name, mux_id); ++ ++ LOG_DBG("Exit"); ++ return 0; ++ ++virt_reg_failed: ++ for (num--; num >= 0; num--) ++ i2c_del_mux_adapter(dev->m_virt_adaps[num]); ++ ++ kfree(dev); ++err: ++ LOG_DBG("Error Exit"); ++ return ret; ++} ++ ++static int dni_6448_mux_remove(struct i2c_client* client) ++{ ++ struct dni_6448_mux* dev = i2c_get_clientdata(client); ++ int i, err; ++ ++ LOG_DBG("Entry"); ++ for (i = 0; i < dni_6448_num_channels[dev->m_mux_id]; ++i) ++ if (dev->m_virt_adaps[i]) { ++ err = i2c_del_mux_adapter(dev->m_virt_adaps[i]); ++ if (err) ++ return err; ++ dev->m_virt_adaps[i] = NULL; ++ } ++ ++ kfree(dev); ++ LOG_DBG("Exit"); ++ return 0; ++} ++ ++static const struct i2c_device_id dni_6448_mux_ids[] = { ++ { "6448-i2c-mux", 0 }, ++ { /* end of list */ }, ++}; ++ ++static struct i2c_driver dni_6448_mux_driver = { ++ .driver = { ++ .name = driver_name, ++ .owner = THIS_MODULE, ++ }, ++ .probe = dni_6448_mux_probe, ++ .remove = dni_6448_mux_remove, ++ .id_table = dni_6448_mux_ids, ++}; ++ ++static int __init dni_6448_mux_init(void) ++{ ++ int rc; ++ ++ LOG_DBG("Loading %s", driver_name); ++ rc = i2c_add_driver( &dni_6448_mux_driver); ++ if ( rc) { ++ LOG_ERR("i2c_add_driver() failed"); ++ } ++ return rc; ++} ++ ++static void __exit dni_6448_mux_exit(void) ++{ ++ LOG_DBG("Entry"); ++ i2c_del_driver( &dni_6448_mux_driver); ++ LOG_DBG("Exit"); ++} ++ ++module_init(dni_6448_mux_init); ++module_exit(dni_6448_mux_exit); ++ ++MODULE_AUTHOR("Curt Brune "); ++MODULE_DESCRIPTION("I2C Mux Driver for Delta Networks Inc. ET6448"); ++MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(DRIVER_VERSION); +diff --git a/drivers/i2c/muxes/gpio-i2cmux.c b/drivers/i2c/muxes/gpio-i2cmux.c +index 7b6ce62..cd238c7 100644 +--- a/drivers/i2c/muxes/gpio-i2cmux.c ++++ b/drivers/i2c/muxes/gpio-i2cmux.c +@@ -105,7 +105,8 @@ static int __devinit gpiomux_probe(struct platform_device *pdev) + for (i = 0; i < pdata->n_values; i++) { + u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0; + +- mux->adap[i] = i2c_add_mux_adapter(parent, mux, nr, i, ++ mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, ++ nr, i, + gpiomux_select, deselect); + if (!mux->adap[i]) { + ret = -ENODEV; +diff --git a/drivers/i2c/muxes/pca9541.c b/drivers/i2c/muxes/pca9541.c +index ed699c5..e9e07ba 100644 +--- a/drivers/i2c/muxes/pca9541.c ++++ b/drivers/i2c/muxes/pca9541.c +@@ -353,7 +353,8 @@ static int pca9541_probe(struct i2c_client *client, + force = 0; + if (pdata) + force = pdata->modes[0].adap_id; +- data->mux_adap = i2c_add_mux_adapter(adap, client, force, 0, ++ data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client, ++ force, 0, + pca9541_select_chan, + pca9541_release_chan); + +diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c +index 6f89536..c9db544 100644 +--- a/drivers/i2c/muxes/pca954x.c ++++ b/drivers/i2c/muxes/pca954x.c +@@ -188,6 +188,7 @@ static int pca954x_probe(struct i2c_client *client, + struct pca954x_platform_data *pdata = client->dev.platform_data; + int num, force; + struct pca954x *data; ++ int deselect_on_exit = 0; + int ret = -ENODEV; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) +@@ -210,6 +211,17 @@ static int pca954x_probe(struct i2c_client *client, + goto exit_free; + } + ++ /* ++ * Check whether we want to deselect the mux after the ++ * transaction. This can be specified in one of two ways: ++ * ++ * 1. using platform data: pdata->modes[num].deselect_on_exit ++ * 2. using the device tree property deselect_on_exit ++ */ ++ if (of_find_property(client->dev.of_node, "deselect-on-exit", NULL)) { ++ deselect_on_exit = 1; ++ } ++ + data->type = id->driver_data; + data->last_chan = 0; /* force the first selection */ + +@@ -226,10 +238,10 @@ static int pca954x_probe(struct i2c_client *client, + } + + data->virt_adaps[num] = +- i2c_add_mux_adapter(adap, client, ++ i2c_add_mux_adapter(adap, &client->dev, client, + force, num, pca954x_select_chan, +- (pdata && pdata->modes[num].deselect_on_exit) +- ? pca954x_deselect_mux : NULL); ++ (pdata && pdata->modes[num].deselect_on_exit) || deselect_on_exit ++ ? pca954x_deselect_mux : NULL); + + if (data->virt_adaps[num] == NULL) { + ret = -ENODEV; +diff --git a/drivers/i2c/muxes/quanta-i2cmux.c b/drivers/i2c/muxes/quanta-i2cmux.c +new file mode 100644 +index 0000000..498f6e7 +--- /dev/null ++++ b/drivers/i2c/muxes/quanta-i2cmux.c +@@ -0,0 +1,238 @@ ++/* ++ * I2C multiplexer for the quanta CPLD chips ++ * ++ * ++ * Copyright 2014 Cumulus Networks, inc all rights reserved ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define QUANTA_I2CMUX_MAX_NCHANS 32 ++ ++static const unsigned short quanta_sfp_address_list[] = { ++ 0x50, 0x51, I2C_CLIENT_END }; ++ ++enum quanta_i2cmux_type { ++ quanta_i2cmux_16, ++ quanta_i2cmux_32, ++}; ++ ++struct quanta_i2cmux { ++ enum quanta_i2cmux_type type; ++ struct i2c_adapter *virt_adaps[QUANTA_I2CMUX_MAX_NCHANS]; ++ u8 last_chan; /* last register value */ ++}; ++ ++/* Struct to hold private data for muxes */ ++struct chip_desc { ++ u8 nchans; ++}; ++ ++static const struct chip_desc chips[] = { ++ [quanta_i2cmux_16] = { ++ .nchans = 16, ++ }, ++ [quanta_i2cmux_32] = { ++ .nchans = 32, ++ }, ++}; ++ ++static const struct i2c_device_id quanta_i2cmux_id[] = { ++ { "quanta-i2cmux-16", quanta_i2cmux_16 }, ++ { "quanta-i2cmux-32", quanta_i2cmux_32 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, quanta_i2cmux_id); ++ ++static int quanta_i2cmux_reg_write(struct i2c_adapter *adap, ++ struct i2c_client *client, u8 command, u8 val) ++{ ++ int ret = -ENODEV; ++ ++ if (adap->algo->master_xfer) { ++ struct i2c_msg msg; ++ char buf[2]; ++ ++ msg.addr = client->addr; ++ msg.flags = 0; ++ msg.len = 2; ++ buf[0] = command; ++ buf[1] = val; ++ msg.buf = buf; ++ ret = adap->algo->master_xfer(adap, &msg, 1); ++ ++ } else { ++ union i2c_smbus_data data; ++ ++ data.byte = val; ++ ret = adap->algo->smbus_xfer(adap, client->addr, ++ client->flags, ++ I2C_SMBUS_WRITE, ++ command, I2C_SMBUS_BYTE_DATA, &data); ++ } ++ ++ return ret; ++} ++ ++static int quanta_i2cmux_select_chan(struct i2c_adapter *adap, ++ void *client, u32 chan) ++{ ++ struct quanta_i2cmux *data = i2c_get_clientdata(client); ++ const struct chip_desc *chip = &chips[data->type]; ++ u8 regval; ++ int ret = 0; ++ ++ /** ++ * The channel select register is 1-based, but our API to the ++ * world is 0-based. ++ */ ++ regval = chan + 1; ++ ++ /* Only select the channel if its different from the last channel */ ++ if (data->last_chan != regval) { ++ ret = quanta_i2cmux_reg_write(adap, client, ++ QUANTA_I2CMUX_CHANNEL_SELECT, regval); ++ data->last_chan = regval; ++ } ++ ++ return ret; ++} ++ ++static int quanta_i2cmux_deselect_mux(struct i2c_adapter *adap, ++ void *client, u32 chan) ++{ ++ struct quanta_i2cmux *data = i2c_get_clientdata(client); ++ ++ /* Deselect active channel */ ++ data->last_chan = 0; ++ return quanta_i2cmux_reg_write(adap, client, QUANTA_I2CMUX_CHANNEL_SELECT, ++ data->last_chan); ++} ++ ++static int quanta_i2cmux_client_detect(struct i2c_client *client, ++ struct i2c_board_info *info) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct i2c_board_info tmp_info = { ++ I2C_BOARD_INFO("24c08", 0x50), ++ }; ++ union i2c_smbus_data dummy; ++ int err; ++ ++ err = i2c_smbus_xfer(adap, client->addr, 0, I2C_SMBUS_READ, 0, ++ I2C_SMBUS_BYTE, &dummy); ++ ++ memcpy(info->type, tmp_info.type, I2C_NAME_SIZE); ++ ++ return err; ++} ++ ++static int quanta_i2cmux_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); ++ struct quanta_i2cmux *data; ++ int num; ++ int ret = -ENODEV; ++ ++ if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) ++ goto err; ++ ++ data = kzalloc(sizeof(struct quanta_i2cmux), GFP_KERNEL); ++ if (!data) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ i2c_set_clientdata(client, data); ++ ++ if (i2c_smbus_write_byte(client, 0) < 0) { ++ dev_warn(&client->dev, "probe failed\n"); ++ goto exit_free; ++ } ++ ++ data->type = id->driver_data; ++ data->last_chan = 0; /* force the first selection */ ++ ++ /* Now create an adapter for each channel */ ++ for (num = 0; num < chips[data->type].nchans; num++) { ++ data->virt_adaps[num] = ++ i2c_add_mux_adapter(adap, &client->dev, client, ++ 0, num, ++ quanta_i2cmux_select_chan, ++ quanta_i2cmux_deselect_mux); ++ ++ if (data->virt_adaps[num] == NULL) { ++ ret = -ENODEV; ++ dev_err(&client->dev, ++ "failed to register multiplexed adapter" ++ " %d\n", num); ++ goto virt_reg_failed; ++ } ++ } ++ ++ dev_info(&client->dev, ++ "registered %d multiplexed busses for I2C mux %s\n", ++ num, client->name); ++ ++ return 0; ++ ++virt_reg_failed: ++ for (num--; num >= 0; num--) ++ i2c_del_mux_adapter(data->virt_adaps[num]); ++exit_free: ++ kfree(data); ++err: ++ return ret; ++} ++ ++static int quanta_i2cmux_remove(struct i2c_client *client) ++{ ++ struct quanta_i2cmux *data = i2c_get_clientdata(client); ++ int i, err; ++ ++ for (i = 0; i < chips[data->type].nchans; ++i) ++ if (data->virt_adaps[i]) { ++ err = i2c_del_mux_adapter(data->virt_adaps[i]); ++ if (err) ++ return err; ++ data->virt_adaps[i] = NULL; ++ } ++ ++ kfree(data); ++ return 0; ++} ++ ++static struct i2c_driver quanta_i2cmux_driver = { ++ .driver = { ++ .name = "quanta-i2cmux", ++ .owner = THIS_MODULE, ++ }, ++ .probe = quanta_i2cmux_probe, ++ .remove = quanta_i2cmux_remove, ++ .id_table = quanta_i2cmux_id, ++ .address_list = quanta_sfp_address_list, ++ .detect = quanta_i2cmux_client_detect, ++}; ++ ++static int __init quanta_i2cmux_init(void) ++{ ++ return i2c_add_driver(&quanta_i2cmux_driver); ++} ++ ++static void __exit quanta_i2cmux_exit(void) ++{ ++ i2c_del_driver(&quanta_i2cmux_driver); ++} ++ ++module_init(quanta_i2cmux_init); ++module_exit(quanta_i2cmux_exit); ++ ++MODULE_AUTHOR("Roopa Prabhu "); ++MODULE_DESCRIPTION("quanta I2C mux driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c +index 44fde43..145a33e 100644 +--- a/drivers/idle/intel_idle.c ++++ b/drivers/idle/intel_idle.c +@@ -62,6 +62,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -81,6 +82,17 @@ static unsigned int mwait_substates; + /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ + static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */ + ++struct idle_cpu { ++ struct cpuidle_state *state_table; ++ ++ /* ++ * Hardware C-state auto-demotion may not always be optimal. ++ * Indicate which enable bits to clear here. ++ */ ++ unsigned long auto_demotion_disable_flags; ++}; ++ ++static const struct idle_cpu *icpu; + static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; + static int intel_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index); +@@ -88,12 +100,6 @@ static int intel_idle(struct cpuidle_device *dev, + static struct cpuidle_state *cpuidle_state_table; + + /* +- * Hardware C-state auto-demotion may not always be optimal. +- * Indicate which enable bits to clear here. +- */ +-static unsigned long long auto_demotion_disable_flags; +- +-/* + * Set this flag for states where the HW flushes the TLB for us + * and so we don't need cross-calls to keep it consistent. + * If this flag is set, SW flushes the TLB, so even if the +@@ -352,27 +358,74 @@ static void auto_demotion_disable(void *dummy) + unsigned long long msr_bits; + + rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); +- msr_bits &= ~auto_demotion_disable_flags; ++ msr_bits &= ~(icpu->auto_demotion_disable_flags); + wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); + } + ++static const struct idle_cpu idle_cpu_nehalem = { ++ .state_table = nehalem_cstates, ++ .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, ++}; ++ ++static const struct idle_cpu idle_cpu_atom = { ++ .state_table = atom_cstates, ++}; ++ ++static const struct idle_cpu idle_cpu_lincroft = { ++ .state_table = atom_cstates, ++ .auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE, ++}; ++ ++static const struct idle_cpu idle_cpu_snb = { ++ .state_table = snb_cstates, ++}; ++ ++static const struct idle_cpu idle_cpu_ivb = { ++ .state_table = ivb_cstates, ++}; ++ ++#define ICPU(model, cpu) \ ++ { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } ++ ++static const struct x86_cpu_id intel_idle_ids[] = { ++ ICPU(0x1a, idle_cpu_nehalem), ++ ICPU(0x1e, idle_cpu_nehalem), ++ ICPU(0x1f, idle_cpu_nehalem), ++ ICPU(0x25, idle_cpu_nehalem), ++ ICPU(0x2c, idle_cpu_nehalem), ++ ICPU(0x2e, idle_cpu_nehalem), ++ ICPU(0x1c, idle_cpu_atom), ++ ICPU(0x26, idle_cpu_lincroft), ++ ICPU(0x2f, idle_cpu_nehalem), ++ ICPU(0x2a, idle_cpu_snb), ++ ICPU(0x2d, idle_cpu_snb), ++ ICPU(0x3a, idle_cpu_ivb), ++ ICPU(0x3e, idle_cpu_ivb), ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); ++ + /* + * intel_idle_probe() + */ + static int intel_idle_probe(void) + { + unsigned int eax, ebx, ecx; ++ const struct x86_cpu_id *id; + + if (max_cstate == 0) { + pr_debug(PREFIX "disabled\n"); + return -EPERM; + } + +- if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) +- return -ENODEV; +- +- if (!boot_cpu_has(X86_FEATURE_MWAIT)) ++ id = x86_match_cpu(intel_idle_ids); ++ if (!id) { ++ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && ++ boot_cpu_data.x86 == 6) ++ pr_debug(PREFIX "does not run on family %d model %d\n", ++ boot_cpu_data.x86, boot_cpu_data.x86_model); + return -ENODEV; ++ } + + if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) + return -ENODEV; +@@ -386,48 +439,8 @@ static int intel_idle_probe(void) + + pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates); + +- +- if (boot_cpu_data.x86 != 6) /* family 6 */ +- return -ENODEV; +- +- switch (boot_cpu_data.x86_model) { +- +- case 0x1A: /* Core i7, Xeon 5500 series */ +- case 0x1E: /* Core i7 and i5 Processor - Lynnfield Jasper Forest */ +- case 0x1F: /* Core i7 and i5 Processor - Nehalem */ +- case 0x2E: /* Nehalem-EX Xeon */ +- case 0x2F: /* Westmere-EX Xeon */ +- case 0x25: /* Westmere */ +- case 0x2C: /* Westmere */ +- cpuidle_state_table = nehalem_cstates; +- auto_demotion_disable_flags = +- (NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE); +- break; +- +- case 0x1C: /* 28 - Atom Processor */ +- cpuidle_state_table = atom_cstates; +- break; +- +- case 0x26: /* 38 - Lincroft Atom Processor */ +- cpuidle_state_table = atom_cstates; +- auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE; +- break; +- +- case 0x2A: /* SNB */ +- case 0x2D: /* SNB Xeon */ +- cpuidle_state_table = snb_cstates; +- break; +- +- case 0x3A: /* IVB */ +- case 0x3E: /* IVB Xeon */ +- cpuidle_state_table = ivb_cstates; +- break; +- +- default: +- pr_debug(PREFIX "does not run on family %d model %d\n", +- boot_cpu_data.x86, boot_cpu_data.x86_model); +- return -ENODEV; +- } ++ icpu = (const struct idle_cpu *)id->driver_data; ++ cpuidle_state_table = icpu->state_table; + + if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ + lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE; +@@ -506,7 +519,7 @@ static int intel_idle_cpuidle_driver_init(void) + drv->state_count += 1; + } + +- if (auto_demotion_disable_flags) ++ if (icpu->auto_demotion_disable_flags) + on_each_cpu(auto_demotion_disable, NULL, 1); + + return 0; +diff --git a/drivers/infiniband/hw/qib/qib_sd7220.c b/drivers/infiniband/hw/qib/qib_sd7220.c +index de1a4b2..b338cb8 100644 +--- a/drivers/infiniband/hw/qib/qib_sd7220.c ++++ b/drivers/infiniband/hw/qib/qib_sd7220.c +@@ -403,10 +403,8 @@ int qib_sd7220_init(struct qib_devdata *dd) + } + + ret = request_firmware(&fw, SD7220_FW_NAME, &dd->pcidev->dev); +- if (ret) { +- qib_dev_err(dd, "Failed to load IB SERDES image\n"); ++ if (ret) + goto done; +- } + + /* Substitute our deduced value for was_reset */ + ret = qib_ibsd_ucode_loaded(dd->pport, fw); +diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c +index f658086..8129f1f 100644 +--- a/drivers/input/input-mt.c ++++ b/drivers/input/input-mt.c +@@ -14,6 +14,17 @@ + + #define TRKID_SGN ((TRKID_MAX + 1) >> 1) + ++#define input_dev_to_mt(dev) \ ++ ((dev)->mt ? container_of((dev)->mt, struct input_mt, slots[0]) : NULL) ++ ++static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src) ++{ ++ if (dev->absinfo && test_bit(src, dev->absbit)) { ++ dev->absinfo[dst] = dev->absinfo[src]; ++ dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst); ++ } ++} ++ + /** + * input_mt_init_slots() - initialize MT input slots + * @dev: input device supporting MT events and finger tracking +@@ -25,8 +36,10 @@ + * May be called repeatedly. Returns -EINVAL if attempting to + * reinitialize with a different number of slots. + */ +-int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) ++int input_mt_init_slots_flags(struct input_dev *dev, unsigned int num_slots, ++ unsigned int flags) + { ++ struct input_mt *mt; + int i; + + if (!num_slots) +@@ -34,20 +47,62 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) + if (dev->mt) + return dev->mtsize != num_slots ? -EINVAL : 0; + +- dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL); +- if (!dev->mt) +- return -ENOMEM; ++ mt = kzalloc(sizeof(*mt) + num_slots * sizeof(*mt->slots) + ++ num_slots * sizeof(*mt->slot_frame), GFP_KERNEL); ++ if (!mt) ++ goto err_mem; + + dev->mtsize = num_slots; ++ mt->num_slots = num_slots; ++ mt->flags = flags; ++ mt->slot_frame = (unsigned int *)&mt->slots[num_slots]; + input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); + input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0); + input_set_events_per_packet(dev, 6 * num_slots); + ++ if (flags & (INPUT_MT_POINTER | INPUT_MT_DIRECT)) { ++ __set_bit(EV_KEY, dev->evbit); ++ __set_bit(BTN_TOUCH, dev->keybit); ++ ++ copy_abs(dev, ABS_X, ABS_MT_POSITION_X); ++ copy_abs(dev, ABS_Y, ABS_MT_POSITION_Y); ++ copy_abs(dev, ABS_PRESSURE, ABS_MT_PRESSURE); ++ } ++ if (flags & INPUT_MT_POINTER) { ++ __set_bit(BTN_TOOL_FINGER, dev->keybit); ++ __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); ++ if (num_slots >= 3) ++ __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); ++ if (num_slots >= 4) ++ __set_bit(BTN_TOOL_QUADTAP, dev->keybit); ++ if (num_slots >= 5) ++ __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); ++ __set_bit(INPUT_PROP_POINTER, dev->propbit); ++ } ++ if (flags & INPUT_MT_DIRECT) ++ __set_bit(INPUT_PROP_DIRECT, dev->propbit); ++ if (flags & INPUT_MT_TRACK) { ++ unsigned int n2 = num_slots * num_slots; ++ mt->red = kcalloc(n2, sizeof(*mt->red), GFP_KERNEL); ++ if (!mt->red) ++ goto err_mem; ++ } ++ + /* Mark slots as 'unused' */ + for (i = 0; i < num_slots; i++) +- input_mt_set_value(&dev->mt[i], ABS_MT_TRACKING_ID, -1); ++ input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1); + ++ dev->mt = &mt->slots[0]; + return 0; ++err_mem: ++ kfree(mt); ++ return -ENOMEM; ++} ++EXPORT_SYMBOL(input_mt_init_slots_flags); ++ ++int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) ++{ ++ return input_mt_init_slots_flags(dev, num_slots, 0); + } + EXPORT_SYMBOL(input_mt_init_slots); + +@@ -60,7 +115,11 @@ EXPORT_SYMBOL(input_mt_init_slots); + */ + void input_mt_destroy_slots(struct input_dev *dev) + { +- kfree(dev->mt); ++ if (dev->mt) { ++ struct input_mt *mt = input_dev_to_mt(dev); ++ kfree(mt->red); ++ kfree(mt); ++ } + dev->mt = NULL; + dev->mtsize = 0; + dev->slot = 0; +@@ -83,17 +142,23 @@ EXPORT_SYMBOL(input_mt_destroy_slots); + void input_mt_report_slot_state(struct input_dev *dev, + unsigned int tool_type, bool active) + { +- struct input_mt_slot *mt; ++ struct input_mt *mt = input_dev_to_mt(dev); ++ struct input_mt_slot *slot; + int id; + +- if (!dev->mt || !active) { ++ if (!mt) ++ return; ++ ++ slot = &mt->slots[dev->slot]; ++ mt->slot_frame[dev->slot] = mt->frame; ++ ++ if (!active) { + input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); + return; + } + +- mt = &dev->mt[dev->slot]; +- id = input_mt_get_value(mt, ABS_MT_TRACKING_ID); +- if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type) ++ id = input_mt_get_value(slot, ABS_MT_TRACKING_ID); ++ if (id < 0 || input_mt_get_value(slot, ABS_MT_TOOL_TYPE) != tool_type) + id = input_mt_new_trkid(dev); + + input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id); +@@ -170,3 +235,162 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) + } + } + EXPORT_SYMBOL(input_mt_report_pointer_emulation); ++ ++/** ++ * input_mt_sync_frame() - synchronize mt frame ++ * @dev: input device with allocated MT slots ++ * ++ * Close the frame and prepare the internal state for a new one. ++ * Depending on the flags, marks unused slots as inactive and performs ++ * pointer emulation. ++ */ ++void input_mt_sync_frame(struct input_dev *dev) ++{ ++ struct input_mt *mt = input_dev_to_mt(dev); ++ unsigned int i; ++ ++ if (!mt) ++ return; ++ ++ if (mt->flags & INPUT_MT_DROP_UNUSED) { ++ for (i = 0; i < mt->num_slots; i++) { ++ if (mt->slot_frame[i] == mt->frame) ++ continue; ++ input_mt_slot(dev, i); ++ input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); ++ } ++ } ++ ++ input_mt_report_pointer_emulation(dev, (mt->flags & INPUT_MT_POINTER)); ++ ++ mt->frame++; ++} ++EXPORT_SYMBOL(input_mt_sync_frame); ++ ++static int adjust_dual(int *begin, int step, int *end, int eq) ++{ ++ int f, *p, s, c; ++ ++ if (begin == end) ++ return 0; ++ ++ f = *begin; ++ p = begin + step; ++ s = p == end ? f + 1 : *p; ++ ++ for (; p != end; p += step) ++ if (*p < f) ++ s = f, f = *p; ++ else if (*p < s) ++ s = *p; ++ ++ c = (f + s + 1) / 2; ++ if (c == 0 || (c > 0 && !eq)) ++ return 0; ++ if (s < 0) ++ c *= 2; ++ ++ for (p = begin; p != end; p += step) ++ *p -= c; ++ ++ return (c < s && s <= 0) || (f >= 0 && f < c); ++} ++ ++static void find_reduced_matrix(int *w, int nr, int nc, int nrc) ++{ ++ int i, k, sum; ++ ++ for (k = 0; k < nrc; k++) { ++ for (i = 0; i < nr; i++) ++ adjust_dual(w + i, nr, w + i + nrc, nr <= nc); ++ sum = 0; ++ for (i = 0; i < nrc; i += nr) ++ sum += adjust_dual(w + i, 1, w + i + nr, nc <= nr); ++ if (!sum) ++ break; ++ } ++} ++ ++static int input_mt_set_matrix(struct input_mt *mt, ++ const struct input_mt_pos *pos, int num_pos) ++{ ++ const struct input_mt_pos *p; ++ struct input_mt_slot *s; ++ int *w = mt->red; ++ int x, y; ++ ++ for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { ++ if (!input_mt_is_active(s)) ++ continue; ++ x = input_mt_get_value(s, ABS_MT_POSITION_X); ++ y = input_mt_get_value(s, ABS_MT_POSITION_Y); ++ for (p = pos; p != pos + num_pos; p++) { ++ int dx = x - p->x, dy = y - p->y; ++ *w++ = dx * dx + dy * dy; ++ } ++ } ++ ++ return w - mt->red; ++} ++ ++static void input_mt_set_slots(struct input_mt *mt, ++ int *slots, int num_pos) ++{ ++ struct input_mt_slot *s; ++ int *w = mt->red, *p; ++ ++ for (p = slots; p != slots + num_pos; p++) ++ *p = -1; ++ ++ for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { ++ if (!input_mt_is_active(s)) ++ continue; ++ for (p = slots; p != slots + num_pos; p++) ++ if (*w++ < 0) ++ *p = s - mt->slots; ++ } ++ ++ for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { ++ if (input_mt_is_active(s)) ++ continue; ++ for (p = slots; p != slots + num_pos; p++) ++ if (*p < 0) { ++ *p = s - mt->slots; ++ break; ++ } ++ } ++} ++ ++/** ++ * input_mt_assign_slots() - perform a best-match assignment ++ * @dev: input device with allocated MT slots ++ * @slots: the slot assignment to be filled ++ * @pos: the position array to match ++ * @num_pos: number of positions ++ * ++ * Performs a best match against the current contacts and returns ++ * the slot assignment list. New contacts are assigned to unused ++ * slots. ++ * ++ * Returns zero on success, or negative error in case of failure. ++ */ ++int input_mt_assign_slots(struct input_dev *dev, int *slots, ++ const struct input_mt_pos *pos, int num_pos) ++{ ++ struct input_mt *mt = input_dev_to_mt(dev); ++ int nrc; ++ ++ if (!mt || !mt->red) ++ return -ENXIO; ++ if (num_pos > mt->num_slots) ++ return -EINVAL; ++ if (num_pos < 1) ++ return 0; ++ ++ nrc = input_mt_set_matrix(mt, pos, num_pos); ++ find_reduced_matrix(mt->red, num_pos, nrc / num_pos, nrc); ++ input_mt_set_slots(mt, slots, num_pos); ++ ++ return 0; ++} ++EXPORT_SYMBOL(input_mt_assign_slots); +diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig +index 9c1e6ee..be0ff64 100644 +--- a/drivers/input/mouse/Kconfig ++++ b/drivers/input/mouse/Kconfig +@@ -68,6 +68,16 @@ config MOUSE_PS2_SYNAPTICS + + If unsure, say Y. + ++config MOUSE_PS2_CYPRESS ++ bool "Cypress PS/2 mouse protocol extension" if EXPERT ++ default y ++ depends on MOUSE_PS2 ++ help ++ Say Y here if you have a Cypress PS/2 Trackpad connected to ++ your system. ++ ++ If unsure, say Y. ++ + config MOUSE_PS2_LIFEBOOK + bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT + default y +@@ -322,4 +332,21 @@ config MOUSE_SYNAPTICS_I2C + To compile this driver as a module, choose M here: the + module will be called synaptics_i2c. + ++config MOUSE_SYNAPTICS_USB ++ tristate "Synaptics USB device support" ++ depends on USB_ARCH_HAS_HCD ++ select USB ++ help ++ Say Y here if you want to use a Synaptics USB touchpad or pointing ++ stick. ++ ++ While these devices emulate an USB mouse by default and can be used ++ with standard usbhid driver, this driver, together with its X.Org ++ counterpart, allows you to fully utilize capabilities of the device. ++ More information can be found at: ++ ++ ++ To compile this driver as a module, choose M here: the ++ module will be called synaptics_usb. ++ + endif +diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile +index 570c84a4..789f92c 100644 +--- a/drivers/input/mouse/Makefile ++++ b/drivers/input/mouse/Makefile +@@ -18,6 +18,7 @@ obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o + obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o + obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o + obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o ++obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o + obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o + + psmouse-objs := psmouse-base.o synaptics.o +@@ -30,3 +31,4 @@ psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o + psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o + psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o + psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o ++psmouse-$(CONFIG_MOUSE_PS2_CYPRESS) += cypress_ps2.o +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 64ce6d9..9854a1f 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -17,13 +17,63 @@ + + #include + #include ++#include + #include + #include + + #include "psmouse.h" + #include "alps.h" + +-#define ALPS_OLDPROTO 0x01 /* old style input */ ++/* ++ * Definitions for ALPS version 3 and 4 command mode protocol ++ */ ++#define ALPS_V3_X_MAX 2000 ++#define ALPS_V3_Y_MAX 1400 ++ ++#define ALPS_BITMAP_X_BITS 15 ++#define ALPS_BITMAP_Y_BITS 11 ++ ++#define ALPS_CMD_NIBBLE_10 0x01f2 ++ ++static const struct alps_nibble_commands alps_v3_nibble_commands[] = { ++ { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ ++ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ ++ { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ ++ { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ ++ { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ ++ { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ ++ { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ ++ { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ ++ { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ ++ { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ ++ { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ ++ { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ ++ { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ ++ { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ ++ { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ ++ { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ ++}; ++ ++static const struct alps_nibble_commands alps_v4_nibble_commands[] = { ++ { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */ ++ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ ++ { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ ++ { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ ++ { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ ++ { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ ++ { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ ++ { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ ++ { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ ++ { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ ++ { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ ++ { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ ++ { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ ++ { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ ++ { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ ++ { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ ++}; ++ ++ + #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ + #define ALPS_PASS 0x04 /* device has a pass-through port */ + +@@ -35,30 +85,33 @@ + 6-byte ALPS packet */ + + static const struct alps_model_info alps_model_data[] = { +- { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ +- { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ +- { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, +- { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, +- { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */ +- { { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ +- { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ +- { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ +- { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ +- { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ +- { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, +- { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ +- { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ +- { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, +- { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ ++ { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ ++ { { 0x33, 0x02, 0x0a }, 0x00, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ ++ { { 0x53, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x53, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x60, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ ++ { { 0x63, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x02, 0x28 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ ++ { { 0x63, 0x02, 0x3c }, 0x00, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ ++ { { 0x63, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ ++ { { 0x63, 0x02, 0x64 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ ++ { { 0x73, 0x00, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ ++ { { 0x73, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x73, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ ++ { { 0x20, 0x02, 0x0e }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ ++ { { 0x22, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, ++ { { 0x22, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ + /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ +- { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ++ { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, +- { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ +- { { 0x52, 0x01, 0x14 }, 0xff, 0xff, +- ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ ++ { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ ++ { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ++ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ ++ { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, ++ { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, ++ { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, + }; + + /* +@@ -67,42 +120,7 @@ static const struct alps_model_info alps_model_data[] = { + * isn't valid per PS/2 spec. + */ + +-/* +- * PS/2 packet format +- * +- * byte 0: 0 0 YSGN XSGN 1 M R L +- * byte 1: X7 X6 X5 X4 X3 X2 X1 X0 +- * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 +- * +- * Note that the device never signals overflow condition. +- * +- * ALPS absolute Mode - new format +- * +- * byte 0: 1 ? ? ? 1 ? ? ? +- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 +- * byte 2: 0 x10 x9 x8 x7 ? fin ges +- * byte 3: 0 y9 y8 y7 1 M R L +- * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 +- * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 +- * +- * Dualpoint device -- interleaved packet format +- * +- * byte 0: 1 1 0 0 1 1 1 1 +- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 +- * byte 2: 0 x10 x9 x8 x7 0 fin ges +- * byte 3: 0 0 YSGN XSGN 1 1 1 1 +- * byte 4: X7 X6 X5 X4 X3 X2 X1 X0 +- * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 +- * byte 6: 0 y9 y8 y7 1 m r l +- * byte 7: 0 y6 y5 y4 y3 y2 y1 y0 +- * byte 8: 0 z6 z5 z4 z3 z2 z1 z0 +- * +- * CAPITALS = stick, miniscules = touchpad +- * +- * ?'s can have different meanings on different models, +- * such as wheel rotation, extra buttons, stick buttons +- * on a dualpoint, etc. +- */ ++/* Packet formats are described in Documentation/input/alps.txt */ + + static bool alps_is_valid_first_byte(const struct alps_model_info *model, + unsigned char data) +@@ -137,7 +155,7 @@ static void alps_report_buttons(struct psmouse *psmouse, + input_sync(dev2); + } + +-static void alps_process_packet(struct psmouse *psmouse) ++static void alps_process_packet_v1_v2(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; + const struct alps_model_info *model = priv->i; +@@ -147,7 +165,7 @@ static void alps_process_packet(struct psmouse *psmouse) + int x, y, z, ges, fin, left, right, middle; + int back = 0, forward = 0; + +- if (model->flags & ALPS_OLDPROTO) { ++ if (model->proto_version == ALPS_PROTO_V1) { + left = packet[2] & 0x10; + right = packet[2] & 0x08; + middle = 0; +@@ -239,6 +257,403 @@ static void alps_process_packet(struct psmouse *psmouse) + input_sync(dev); + } + ++/* ++ * Process bitmap data from v3 and v4 protocols. Returns the number of ++ * fingers detected. A return value of 0 means at least one of the ++ * bitmaps was empty. ++ * ++ * The bitmaps don't have enough data to track fingers, so this function ++ * only generates points representing a bounding box of all contacts. ++ * These points are returned in x1, y1, x2, and y2 when the return value ++ * is greater than 0. ++ */ ++static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, ++ int *x1, int *y1, int *x2, int *y2) ++{ ++ struct alps_bitmap_point { ++ int start_bit; ++ int num_bits; ++ }; ++ ++ int fingers_x = 0, fingers_y = 0, fingers; ++ int i, bit, prev_bit; ++ struct alps_bitmap_point x_low = {0,}, x_high = {0,}; ++ struct alps_bitmap_point y_low = {0,}, y_high = {0,}; ++ struct alps_bitmap_point *point; ++ ++ if (!x_map || !y_map) ++ return 0; ++ ++ *x1 = *y1 = *x2 = *y2 = 0; ++ ++ prev_bit = 0; ++ point = &x_low; ++ for (i = 0; x_map != 0; i++, x_map >>= 1) { ++ bit = x_map & 1; ++ if (bit) { ++ if (!prev_bit) { ++ point->start_bit = i; ++ fingers_x++; ++ } ++ point->num_bits++; ++ } else { ++ if (prev_bit) ++ point = &x_high; ++ else ++ point->num_bits = 0; ++ } ++ prev_bit = bit; ++ } ++ ++ /* ++ * y bitmap is reversed for what we need (lower positions are in ++ * higher bits), so we process from the top end. ++ */ ++ y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); ++ prev_bit = 0; ++ point = &y_low; ++ for (i = 0; y_map != 0; i++, y_map <<= 1) { ++ bit = y_map & (1 << (sizeof(y_map) * BITS_PER_BYTE - 1)); ++ if (bit) { ++ if (!prev_bit) { ++ point->start_bit = i; ++ fingers_y++; ++ } ++ point->num_bits++; ++ } else { ++ if (prev_bit) ++ point = &y_high; ++ else ++ point->num_bits = 0; ++ } ++ prev_bit = bit; ++ } ++ ++ /* ++ * Fingers can overlap, so we use the maximum count of fingers ++ * on either axis as the finger count. ++ */ ++ fingers = max(fingers_x, fingers_y); ++ ++ /* ++ * If total fingers is > 1 but either axis reports only a single ++ * contact, we have overlapping or adjacent fingers. For the ++ * purposes of creating a bounding box, divide the single contact ++ * (roughly) equally between the two points. ++ */ ++ if (fingers > 1) { ++ if (fingers_x == 1) { ++ i = x_low.num_bits / 2; ++ x_low.num_bits = x_low.num_bits - i; ++ x_high.start_bit = x_low.start_bit + i; ++ x_high.num_bits = max(i, 1); ++ } else if (fingers_y == 1) { ++ i = y_low.num_bits / 2; ++ y_low.num_bits = y_low.num_bits - i; ++ y_high.start_bit = y_low.start_bit + i; ++ y_high.num_bits = max(i, 1); ++ } ++ } ++ ++ *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / ++ (2 * (ALPS_BITMAP_X_BITS - 1)); ++ *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / ++ (2 * (ALPS_BITMAP_Y_BITS - 1)); ++ ++ if (fingers > 1) { ++ *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / ++ (2 * (ALPS_BITMAP_X_BITS - 1)); ++ *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / ++ (2 * (ALPS_BITMAP_Y_BITS - 1)); ++ } ++ ++ return fingers; ++} ++ ++static void alps_set_slot(struct input_dev *dev, int slot, bool active, ++ int x, int y) ++{ ++ input_mt_slot(dev, slot); ++ input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); ++ if (active) { ++ input_report_abs(dev, ABS_MT_POSITION_X, x); ++ input_report_abs(dev, ABS_MT_POSITION_Y, y); ++ } ++} ++ ++static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers, ++ int x1, int y1, int x2, int y2) ++{ ++ alps_set_slot(dev, 0, num_fingers != 0, x1, y1); ++ alps_set_slot(dev, 1, num_fingers == 2, x2, y2); ++} ++ ++static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ struct input_dev *dev = priv->dev2; ++ int x, y, z, left, right, middle; ++ ++ /* Sanity check packet */ ++ if (!(packet[0] & 0x40)) { ++ psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); ++ return; ++ } ++ ++ /* ++ * There's a special packet that seems to indicate the end ++ * of a stream of trackstick data. Filter these out. ++ */ ++ if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f) ++ return; ++ ++ x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f)); ++ y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f)); ++ z = (packet[4] & 0x7c) >> 2; ++ ++ /* ++ * The x and y values tend to be quite large, and when used ++ * alone the trackstick is difficult to use. Scale them down ++ * to compensate. ++ */ ++ x /= 8; ++ y /= 8; ++ ++ input_report_rel(dev, REL_X, x); ++ input_report_rel(dev, REL_Y, -y); ++ ++ /* ++ * Most ALPS models report the trackstick buttons in the touchpad ++ * packets, but a few report them here. No reliable way has been ++ * found to differentiate between the models upfront, so we enable ++ * the quirk in response to seeing a button press in the trackstick ++ * packet. ++ */ ++ left = packet[3] & 0x01; ++ right = packet[3] & 0x02; ++ middle = packet[3] & 0x04; ++ ++ if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) && ++ (left || right || middle)) ++ priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS; ++ ++ if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) { ++ input_report_key(dev, BTN_LEFT, left); ++ input_report_key(dev, BTN_RIGHT, right); ++ input_report_key(dev, BTN_MIDDLE, middle); ++ } ++ ++ input_sync(dev); ++ return; ++} ++ ++static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ struct input_dev *dev = psmouse->dev; ++ struct input_dev *dev2 = priv->dev2; ++ int x, y, z; ++ int left, right, middle; ++ int x1 = 0, y1 = 0, x2 = 0, y2 = 0; ++ int fingers = 0, bmap_fingers; ++ unsigned int x_bitmap, y_bitmap; ++ ++ /* ++ * There's no single feature of touchpad position and bitmap packets ++ * that can be used to distinguish between them. We rely on the fact ++ * that a bitmap packet should always follow a position packet with ++ * bit 6 of packet[4] set. ++ */ ++ if (priv->multi_packet) { ++ /* ++ * Sometimes a position packet will indicate a multi-packet ++ * sequence, but then what follows is another position ++ * packet. Check for this, and when it happens process the ++ * position packet as usual. ++ */ ++ if (packet[0] & 0x40) { ++ fingers = (packet[5] & 0x3) + 1; ++ x_bitmap = ((packet[4] & 0x7e) << 8) | ++ ((packet[1] & 0x7f) << 2) | ++ ((packet[0] & 0x30) >> 4); ++ y_bitmap = ((packet[3] & 0x70) << 4) | ++ ((packet[2] & 0x7f) << 1) | ++ (packet[4] & 0x01); ++ ++ bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, ++ &x1, &y1, &x2, &y2); ++ ++ /* ++ * We shouldn't report more than one finger if ++ * we don't have two coordinates. ++ */ ++ if (fingers > 1 && bmap_fingers < 2) ++ fingers = bmap_fingers; ++ ++ /* Now process position packet */ ++ packet = priv->multi_data; ++ } else { ++ priv->multi_packet = 0; ++ } ++ } ++ ++ /* ++ * Bit 6 of byte 0 is not usually set in position packets. The only ++ * times it seems to be set is in situations where the data is ++ * suspect anyway, e.g. a palm resting flat on the touchpad. Given ++ * this combined with the fact that this bit is useful for filtering ++ * out misidentified bitmap packets, we reject anything with this ++ * bit set. ++ */ ++ if (packet[0] & 0x40) ++ return; ++ ++ if (!priv->multi_packet && (packet[4] & 0x40)) { ++ priv->multi_packet = 1; ++ memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); ++ return; ++ } ++ ++ priv->multi_packet = 0; ++ ++ left = packet[3] & 0x01; ++ right = packet[3] & 0x02; ++ middle = packet[3] & 0x04; ++ ++ x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | ++ ((packet[0] & 0x30) >> 4); ++ y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); ++ z = packet[5] & 0x7f; ++ ++ /* ++ * Sometimes the hardware sends a single packet with z = 0 ++ * in the middle of a stream. Real releases generate packets ++ * with x, y, and z all zero, so these seem to be flukes. ++ * Ignore them. ++ */ ++ if (x && y && !z) ++ return; ++ ++ /* ++ * If we don't have MT data or the bitmaps were empty, we have ++ * to rely on ST data. ++ */ ++ if (!fingers) { ++ x1 = x; ++ y1 = y; ++ fingers = z > 0 ? 1 : 0; ++ } ++ ++ if (z >= 64) ++ input_report_key(dev, BTN_TOUCH, 1); ++ else ++ input_report_key(dev, BTN_TOUCH, 0); ++ ++ alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); ++ ++ input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); ++ input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); ++ input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); ++ input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); ++ ++ input_report_key(dev, BTN_LEFT, left); ++ input_report_key(dev, BTN_RIGHT, right); ++ input_report_key(dev, BTN_MIDDLE, middle); ++ ++ if (z > 0) { ++ input_report_abs(dev, ABS_X, x); ++ input_report_abs(dev, ABS_Y, y); ++ } ++ input_report_abs(dev, ABS_PRESSURE, z); ++ ++ input_sync(dev); ++ ++ if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { ++ left = packet[3] & 0x10; ++ right = packet[3] & 0x20; ++ middle = packet[3] & 0x40; ++ ++ input_report_key(dev2, BTN_LEFT, left); ++ input_report_key(dev2, BTN_RIGHT, right); ++ input_report_key(dev2, BTN_MIDDLE, middle); ++ input_sync(dev2); ++ } ++} ++ ++static void alps_process_packet_v3(struct psmouse *psmouse) ++{ ++ unsigned char *packet = psmouse->packet; ++ ++ /* ++ * v3 protocol packets come in three types, two representing ++ * touchpad data and one representing trackstick data. ++ * Trackstick packets seem to be distinguished by always ++ * having 0x3f in the last byte. This value has never been ++ * observed in the last byte of either of the other types ++ * of packets. ++ */ ++ if (packet[5] == 0x3f) { ++ alps_process_trackstick_packet_v3(psmouse); ++ return; ++ } ++ ++ alps_process_touchpad_packet_v3(psmouse); ++} ++ ++static void alps_process_packet_v4(struct psmouse *psmouse) ++{ ++ unsigned char *packet = psmouse->packet; ++ struct input_dev *dev = psmouse->dev; ++ int x, y, z; ++ int left, right; ++ ++ left = packet[4] & 0x01; ++ right = packet[4] & 0x02; ++ ++ x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | ++ ((packet[0] & 0x30) >> 4); ++ y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); ++ z = packet[5] & 0x7f; ++ ++ if (z >= 64) ++ input_report_key(dev, BTN_TOUCH, 1); ++ else ++ input_report_key(dev, BTN_TOUCH, 0); ++ ++ if (z > 0) { ++ input_report_abs(dev, ABS_X, x); ++ input_report_abs(dev, ABS_Y, y); ++ } ++ input_report_abs(dev, ABS_PRESSURE, z); ++ ++ input_report_key(dev, BTN_TOOL_FINGER, z > 0); ++ input_report_key(dev, BTN_LEFT, left); ++ input_report_key(dev, BTN_RIGHT, right); ++ ++ input_sync(dev); ++} ++ ++static void alps_process_packet(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ const struct alps_model_info *model = priv->i; ++ ++ switch (model->proto_version) { ++ case ALPS_PROTO_V1: ++ case ALPS_PROTO_V2: ++ alps_process_packet_v1_v2(psmouse); ++ break; ++ case ALPS_PROTO_V3: ++ alps_process_packet_v3(psmouse); ++ break; ++ case ALPS_PROTO_V4: ++ alps_process_packet_v4(psmouse); ++ break; ++ } ++} ++ + static void alps_report_bare_ps2_packet(struct psmouse *psmouse, + unsigned char packet[], + bool report_buttons) +@@ -344,7 +759,7 @@ static void alps_flush_packet(unsigned long data) + + serio_pause_rx(psmouse->ps2dev.serio); + +- if (psmouse->pktcnt == 6) { ++ if (psmouse->pktcnt == psmouse->pktsize) { + + /* + * We did not any more data in reasonable amount of time. +@@ -401,8 +816,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + return PSMOUSE_BAD_DATA; + } + +- /* Bytes 2 - 6 should have 0 in the highest bit */ +- if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && ++ /* Bytes 2 - pktsize should have 0 in the highest bit */ ++ if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && + (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { + psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", + psmouse->pktcnt - 1, +@@ -410,7 +825,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + return PSMOUSE_BAD_DATA; + } + +- if (psmouse->pktcnt == 6) { ++ if (psmouse->pktcnt == psmouse->pktsize) { + alps_process_packet(psmouse); + return PSMOUSE_FULL_PACKET; + } +@@ -418,11 +833,127 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + return PSMOUSE_GOOD_DATA; + } + ++static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ struct alps_data *priv = psmouse->private; ++ int command; ++ unsigned char *param; ++ unsigned char dummy[4]; ++ ++ BUG_ON(nibble > 0xf); ++ ++ command = priv->nibble_commands[nibble].command; ++ param = (command & 0x0f00) ? ++ dummy : (unsigned char *)&priv->nibble_commands[nibble].data; ++ ++ if (ps2_command(ps2dev, param, command)) ++ return -1; ++ ++ return 0; ++} ++ ++static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ struct alps_data *priv = psmouse->private; ++ int i, nibble; ++ ++ if (ps2_command(ps2dev, NULL, priv->addr_command)) ++ return -1; ++ ++ for (i = 12; i >= 0; i -= 4) { ++ nibble = (addr >> i) & 0xf; ++ if (alps_command_mode_send_nibble(psmouse, nibble)) ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ unsigned char param[4]; ++ ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ return -1; ++ ++ /* ++ * The address being read is returned in the first two bytes ++ * of the result. Check that this address matches the expected ++ * address. ++ */ ++ if (addr != ((param[0] << 8) | param[1])) ++ return -1; ++ ++ return param[2]; ++} ++ ++static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr) ++{ ++ if (alps_command_mode_set_addr(psmouse, addr)) ++ return -1; ++ return __alps_command_mode_read_reg(psmouse, addr); ++} ++ ++static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value) ++{ ++ if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf)) ++ return -1; ++ if (alps_command_mode_send_nibble(psmouse, value & 0xf)) ++ return -1; ++ return 0; ++} ++ ++static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, ++ u8 value) ++{ ++ if (alps_command_mode_set_addr(psmouse, addr)) ++ return -1; ++ return __alps_command_mode_write_reg(psmouse, value); ++} ++ ++static int alps_enter_command_mode(struct psmouse *psmouse, ++ unsigned char *resp) ++{ ++ unsigned char param[4]; ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || ++ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { ++ psmouse_err(psmouse, "failed to enter command mode\n"); ++ return -1; ++ } ++ ++ if (param[0] != 0x88 && param[1] != 0x07) { ++ psmouse_dbg(psmouse, ++ "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", ++ param[0], param[1], param[2]); ++ return -1; ++ } ++ ++ if (resp) ++ *resp = param[2]; ++ return 0; ++} ++ ++static inline int alps_exit_command_mode(struct psmouse *psmouse) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) ++ return -1; ++ return 0; ++} ++ + static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) + { + struct ps2dev *ps2dev = &psmouse->ps2dev; + static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; + unsigned char param[4]; ++ const struct alps_model_info *model = NULL; + int i; + + /* +@@ -473,12 +1004,41 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + *version = (param[0] << 8) | (param[1] << 4) | i; + } + +- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { + if (!memcmp(param, alps_model_data[i].signature, +- sizeof(alps_model_data[i].signature))) +- return alps_model_data + i; ++ sizeof(alps_model_data[i].signature))) { ++ model = alps_model_data + i; ++ break; ++ } ++ } + +- return NULL; ++ if (model && model->proto_version > ALPS_PROTO_V2) { ++ /* ++ * Need to check command mode response to identify ++ * model ++ */ ++ model = NULL; ++ if (alps_enter_command_mode(psmouse, param)) { ++ psmouse_warn(psmouse, ++ "touchpad failed to enter command mode\n"); ++ } else { ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { ++ if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && ++ alps_model_data[i].command_mode_resp == param[0]) { ++ model = alps_model_data + i; ++ break; ++ } ++ } ++ alps_exit_command_mode(psmouse); ++ ++ if (!model) ++ psmouse_dbg(psmouse, ++ "Unknown command mode response %2.2x\n", ++ param[0]); ++ } ++ } ++ ++ return model; + } + + /* +@@ -486,7 +1046,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + * subsequent commands. It looks like glidepad is behind stickpointer, + * I'd thought it would be other way around... + */ +-static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) ++static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable) + { + struct ps2dev *ps2dev = &psmouse->ps2dev; + int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; +@@ -503,7 +1063,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) + return 0; + } + +-static int alps_absolute_mode(struct psmouse *psmouse) ++static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) + { + struct ps2dev *ps2dev = &psmouse->ps2dev; + +@@ -574,17 +1134,17 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) + static int alps_poll(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +- unsigned char buf[6]; ++ unsigned char buf[sizeof(psmouse->packet)]; + bool poll_failed; + + if (priv->i->flags & ALPS_PASS) +- alps_passthrough_mode(psmouse, true); ++ alps_passthrough_mode_v2(psmouse, true); + + poll_failed = ps2_command(&psmouse->ps2dev, buf, + PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; + + if (priv->i->flags & ALPS_PASS) +- alps_passthrough_mode(psmouse, false); ++ alps_passthrough_mode_v2(psmouse, false); + + if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) + return -1; +@@ -601,13 +1161,13 @@ static int alps_poll(struct psmouse *psmouse) + return 0; + } + +-static int alps_hw_init(struct psmouse *psmouse) ++static int alps_hw_init_v1_v2(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; + const struct alps_model_info *model = priv->i; + + if ((model->flags & ALPS_PASS) && +- alps_passthrough_mode(psmouse, true)) { ++ alps_passthrough_mode_v2(psmouse, true)) { + return -1; + } + +@@ -616,13 +1176,13 @@ static int alps_hw_init(struct psmouse *psmouse) + return -1; + } + +- if (alps_absolute_mode(psmouse)) { ++ if (alps_absolute_mode_v1_v2(psmouse)) { + psmouse_err(psmouse, "Failed to enable absolute mode\n"); + return -1; + } + + if ((model->flags & ALPS_PASS) && +- alps_passthrough_mode(psmouse, false)) { ++ alps_passthrough_mode_v2(psmouse, false)) { + return -1; + } + +@@ -635,6 +1195,297 @@ static int alps_hw_init(struct psmouse *psmouse) + return 0; + } + ++/* ++ * Enable or disable passthrough mode to the trackstick. Must be in ++ * command mode when calling this function. ++ */ ++static int alps_passthrough_mode_v3(struct psmouse *psmouse, bool enable) ++{ ++ int reg_val; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0008); ++ if (reg_val == -1) ++ return -1; ++ ++ if (enable) ++ reg_val |= 0x01; ++ else ++ reg_val &= ~0x01; ++ ++ if (__alps_command_mode_write_reg(psmouse, reg_val)) ++ return -1; ++ ++ return 0; ++} ++ ++/* Must be in command mode when calling this function */ ++static int alps_absolute_mode_v3(struct psmouse *psmouse) ++{ ++ int reg_val; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0004); ++ if (reg_val == -1) ++ return -1; ++ ++ reg_val |= 0x06; ++ if (__alps_command_mode_write_reg(psmouse, reg_val)) ++ return -1; ++ ++ return 0; ++} ++ ++static int alps_hw_init_v3(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ int reg_val; ++ unsigned char param[4]; ++ ++ priv->nibble_commands = alps_v3_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; ++ ++ if (alps_enter_command_mode(psmouse, NULL)) ++ goto error; ++ ++ /* Check for trackstick */ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0008); ++ if (reg_val == -1) ++ goto error; ++ if (reg_val & 0x80) { ++ if (alps_passthrough_mode_v3(psmouse, true)) ++ goto error; ++ if (alps_exit_command_mode(psmouse)) ++ goto error; ++ ++ /* ++ * E7 report for the trackstick ++ * ++ * There have been reports of failures to seem to trace back ++ * to the above trackstick check failing. When these occur ++ * this E7 report fails, so when that happens we continue ++ * with the assumption that there isn't a trackstick after ++ * all. ++ */ ++ param[0] = 0x64; ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { ++ psmouse_warn(psmouse, "trackstick E7 report failed\n"); ++ } else { ++ psmouse_dbg(psmouse, ++ "trackstick E7 report: %2.2x %2.2x %2.2x\n", ++ param[0], param[1], param[2]); ++ ++ /* ++ * Not sure what this does, but it is absolutely ++ * essential. Without it, the touchpad does not ++ * work at all and the trackstick just emits normal ++ * PS/2 packets. ++ */ ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ alps_command_mode_send_nibble(psmouse, 0x9) || ++ alps_command_mode_send_nibble(psmouse, 0x4)) { ++ psmouse_err(psmouse, ++ "Error sending magic E6 sequence\n"); ++ goto error_passthrough; ++ } ++ } ++ ++ if (alps_enter_command_mode(psmouse, NULL)) ++ goto error_passthrough; ++ if (alps_passthrough_mode_v3(psmouse, false)) ++ goto error; ++ } ++ ++ if (alps_absolute_mode_v3(psmouse)) { ++ psmouse_err(psmouse, "Failed to enter absolute mode\n"); ++ goto error; ++ } ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0006); ++ if (reg_val == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) ++ goto error; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0007); ++ if (reg_val == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) ++ goto error; ++ ++ if (alps_command_mode_read_reg(psmouse, 0x0144) == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, 0x04)) ++ goto error; ++ ++ if (alps_command_mode_read_reg(psmouse, 0x0159) == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_read_reg(psmouse, 0x0163) == -1) ++ goto error; ++ if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_read_reg(psmouse, 0x0162) == -1) ++ goto error; ++ if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) ++ goto error; ++ ++ /* ++ * This ensures the trackstick packets are in the format ++ * supported by this driver. If bit 1 isn't set the packet ++ * format is different. ++ */ ++ if (alps_command_mode_write_reg(psmouse, 0x0008, 0x82)) ++ goto error; ++ ++ alps_exit_command_mode(psmouse); ++ ++ /* Set rate and enable data reporting */ ++ param[0] = 0x64; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { ++ psmouse_err(psmouse, "Failed to enable data reporting\n"); ++ return -1; ++ } ++ ++ return 0; ++ ++error_passthrough: ++ /* Something failed while in passthrough mode, so try to get out */ ++ if (!alps_enter_command_mode(psmouse, NULL)) ++ alps_passthrough_mode_v3(psmouse, false); ++error: ++ /* ++ * Leaving the touchpad in command mode will essentially render ++ * it unusable until the machine reboots, so exit it here just ++ * to be safe ++ */ ++ alps_exit_command_mode(psmouse); ++ return -1; ++} ++ ++/* Must be in command mode when calling this function */ ++static int alps_absolute_mode_v4(struct psmouse *psmouse) ++{ ++ int reg_val; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0004); ++ if (reg_val == -1) ++ return -1; ++ ++ reg_val |= 0x02; ++ if (__alps_command_mode_write_reg(psmouse, reg_val)) ++ return -1; ++ ++ return 0; ++} ++ ++static int alps_hw_init_v4(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ unsigned char param[4]; ++ ++ priv->nibble_commands = alps_v4_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_DISABLE; ++ ++ if (alps_enter_command_mode(psmouse, NULL)) ++ goto error; ++ ++ if (alps_absolute_mode_v4(psmouse)) { ++ psmouse_err(psmouse, "Failed to enter absolute mode\n"); ++ goto error; ++ } ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03)) ++ goto error; ++ ++ alps_exit_command_mode(psmouse); ++ ++ /* ++ * This sequence changes the output from a 9-byte to an ++ * 8-byte format. All the same data seems to be present, ++ * just in a more compact format. ++ */ ++ param[0] = 0xc8; ++ param[1] = 0x64; ++ param[2] = 0x50; ++ if (ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, ¶m[2], PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, param, PSMOUSE_CMD_GETID)) ++ return -1; ++ ++ /* Set rate and enable data reporting */ ++ param[0] = 0x64; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { ++ psmouse_err(psmouse, "Failed to enable data reporting\n"); ++ return -1; ++ } ++ ++ return 0; ++ ++error: ++ /* ++ * Leaving the touchpad in command mode will essentially render ++ * it unusable until the machine reboots, so exit it here just ++ * to be safe ++ */ ++ alps_exit_command_mode(psmouse); ++ return -1; ++} ++ ++static int alps_hw_init(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ const struct alps_model_info *model = priv->i; ++ int ret = -1; ++ ++ switch (model->proto_version) { ++ case ALPS_PROTO_V1: ++ case ALPS_PROTO_V2: ++ ret = alps_hw_init_v1_v2(psmouse); ++ break; ++ case ALPS_PROTO_V3: ++ ret = alps_hw_init_v3(psmouse); ++ break; ++ case ALPS_PROTO_V4: ++ ret = alps_hw_init_v4(psmouse); ++ break; ++ } ++ ++ return ret; ++} ++ + static int alps_reconnect(struct psmouse *psmouse) + { + const struct alps_model_info *model; +@@ -675,6 +1526,8 @@ int alps_init(struct psmouse *psmouse) + + psmouse->private = priv; + ++ psmouse_reset(psmouse); ++ + model = alps_get_model(psmouse, &version); + if (!model) + goto init_fail; +@@ -702,8 +1555,29 @@ int alps_init(struct psmouse *psmouse) + BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); + + dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); +- input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); ++ ++ switch (model->proto_version) { ++ case ALPS_PROTO_V1: ++ case ALPS_PROTO_V2: ++ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); ++ break; ++ case ALPS_PROTO_V3: ++ set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); ++ input_mt_init_slots(dev1, 2); ++ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); ++ ++ set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); ++ set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); ++ set_bit(BTN_TOOL_QUADTAP, dev1->keybit); ++ /* fall through */ ++ case ALPS_PROTO_V4: ++ input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); ++ break; ++ } ++ + input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); + + if (model->flags & ALPS_WHEEL) { +@@ -746,7 +1620,7 @@ int alps_init(struct psmouse *psmouse) + psmouse->poll = alps_poll; + psmouse->disconnect = alps_disconnect; + psmouse->reconnect = alps_reconnect; +- psmouse->pktsize = 6; ++ psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; + + /* We are having trouble resyncing ALPS touchpads so disable it for now */ + psmouse->resync_time = 0; +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 904ed8b..a00a4ab 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -12,20 +12,39 @@ + #ifndef _ALPS_H + #define _ALPS_H + ++#define ALPS_PROTO_V1 0 ++#define ALPS_PROTO_V2 1 ++#define ALPS_PROTO_V3 2 ++#define ALPS_PROTO_V4 3 ++ + struct alps_model_info { + unsigned char signature[3]; ++ unsigned char command_mode_resp; /* v3/v4 only */ ++ unsigned char proto_version; + unsigned char byte0, mask0; + unsigned char flags; + }; + ++struct alps_nibble_commands { ++ int command; ++ unsigned char data; ++}; ++ + struct alps_data { + struct input_dev *dev2; /* Relative device */ + char phys[32]; /* Phys */ + const struct alps_model_info *i;/* Info */ ++ const struct alps_nibble_commands *nibble_commands; ++ int addr_command; /* Command to set register address */ + int prev_fin; /* Finger bit from previous packet */ ++ int multi_packet; /* Multi-packet data in progress */ ++ unsigned char multi_data[6]; /* Saved multi-packet data */ ++ u8 quirks; + struct timer_list timer; + }; + ++#define ALPS_QUIRK_TRACKSTICK_BUTTONS 1 /* trakcstick buttons in trackstick packet */ ++ + #ifdef CONFIG_MOUSE_PS2_ALPS + int alps_detect(struct psmouse *psmouse, bool set_properties); + int alps_init(struct psmouse *psmouse); +diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c +new file mode 100644 +index 0000000..4e366b9 +--- /dev/null ++++ b/drivers/input/mouse/cypress_ps2.c +@@ -0,0 +1,732 @@ ++/* ++ * Cypress Trackpad PS/2 mouse driver ++ * ++ * Copyright (c) 2012 Cypress Semiconductor Corporation. ++ * ++ * Author: ++ * Dudley Du ++ * ++ * Additional contributors include: ++ * Kamal Mostafa ++ * Kyle Fazzari ++ * ++ * 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 "cypress_ps2.h" ++ ++#undef CYTP_DEBUG_VERBOSE /* define this and DEBUG for more verbose dump */ ++ ++static void cypress_set_packet_size(struct psmouse *psmouse, unsigned int n) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ cytp->pkt_size = n; ++} ++ ++static const unsigned char cytp_rate[] = {10, 20, 40, 60, 100, 200}; ++static const unsigned char cytp_resolution[] = {0x00, 0x01, 0x02, 0x03}; ++ ++static int cypress_ps2_sendbyte(struct psmouse *psmouse, int value) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ ++ if (ps2_sendbyte(ps2dev, value & 0xff, CYTP_CMD_TIMEOUT) < 0) { ++ psmouse_dbg(psmouse, ++ "sending command 0x%02x failed, resp 0x%02x\n", ++ value & 0xff, ps2dev->nak); ++ if (ps2dev->nak == CYTP_PS2_RETRY) ++ return CYTP_PS2_RETRY; ++ else ++ return CYTP_PS2_ERROR; ++ } ++ ++#ifdef CYTP_DEBUG_VERBOSE ++ psmouse_dbg(psmouse, "sending command 0x%02x succeeded, resp 0xfa\n", ++ value & 0xff); ++#endif ++ ++ return 0; ++} ++ ++static int cypress_ps2_ext_cmd(struct psmouse *psmouse, unsigned short cmd, ++ unsigned char data) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ int tries = CYTP_PS2_CMD_TRIES; ++ int rc; ++ ++ ps2_begin_command(ps2dev); ++ ++ do { ++ /* ++ * Send extension command byte (0xE8 or 0xF3). ++ * If sending the command fails, send recovery command ++ * to make the device return to the ready state. ++ */ ++ rc = cypress_ps2_sendbyte(psmouse, cmd & 0xff); ++ if (rc == CYTP_PS2_RETRY) { ++ rc = cypress_ps2_sendbyte(psmouse, 0x00); ++ if (rc == CYTP_PS2_RETRY) ++ rc = cypress_ps2_sendbyte(psmouse, 0x0a); ++ } ++ if (rc == CYTP_PS2_ERROR) ++ continue; ++ ++ rc = cypress_ps2_sendbyte(psmouse, data); ++ if (rc == CYTP_PS2_RETRY) ++ rc = cypress_ps2_sendbyte(psmouse, data); ++ if (rc == CYTP_PS2_ERROR) ++ continue; ++ else ++ break; ++ } while (--tries > 0); ++ ++ ps2_end_command(ps2dev); ++ ++ return rc; ++} ++ ++static int cypress_ps2_read_cmd_status(struct psmouse *psmouse, ++ unsigned char cmd, ++ unsigned char *param) ++{ ++ int rc; ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ enum psmouse_state old_state; ++ int pktsize; ++ ++ ps2_begin_command(&psmouse->ps2dev); ++ ++ old_state = psmouse->state; ++ psmouse->state = PSMOUSE_CMD_MODE; ++ psmouse->pktcnt = 0; ++ ++ pktsize = (cmd == CYTP_CMD_READ_TP_METRICS) ? 8 : 3; ++ memset(param, 0, pktsize); ++ ++ rc = cypress_ps2_sendbyte(psmouse, 0xe9); ++ if (rc < 0) ++ goto out; ++ ++ wait_event_timeout(ps2dev->wait, ++ (psmouse->pktcnt >= pktsize), ++ msecs_to_jiffies(CYTP_CMD_TIMEOUT)); ++ ++ memcpy(param, psmouse->packet, pktsize); ++ ++ psmouse_dbg(psmouse, "Command 0x%02x response data (0x): %*ph\n", ++ cmd, pktsize, param); ++ ++out: ++ psmouse->state = old_state; ++ psmouse->pktcnt = 0; ++ ++ ps2_end_command(&psmouse->ps2dev); ++ ++ return rc; ++} ++ ++static bool cypress_verify_cmd_state(struct psmouse *psmouse, ++ unsigned char cmd, unsigned char *param) ++{ ++ bool rate_match = false; ++ bool resolution_match = false; ++ int i; ++ ++ /* callers will do further checking. */ ++ if (cmd == CYTP_CMD_READ_CYPRESS_ID || ++ cmd == CYTP_CMD_STANDARD_MODE || ++ cmd == CYTP_CMD_READ_TP_METRICS) ++ return true; ++ ++ if ((~param[0] & DFLT_RESP_BITS_VALID) == DFLT_RESP_BITS_VALID && ++ (param[0] & DFLT_RESP_BIT_MODE) == DFLT_RESP_STREAM_MODE) { ++ for (i = 0; i < sizeof(cytp_resolution); i++) ++ if (cytp_resolution[i] == param[1]) ++ resolution_match = true; ++ ++ for (i = 0; i < sizeof(cytp_rate); i++) ++ if (cytp_rate[i] == param[2]) ++ rate_match = true; ++ ++ if (resolution_match && rate_match) ++ return true; ++ } ++ ++ psmouse_dbg(psmouse, "verify cmd state failed.\n"); ++ return false; ++} ++ ++static int cypress_send_ext_cmd(struct psmouse *psmouse, unsigned char cmd, ++ unsigned char *param) ++{ ++ int tries = CYTP_PS2_CMD_TRIES; ++ int rc; ++ ++ psmouse_dbg(psmouse, "send extension cmd 0x%02x, [%d %d %d %d]\n", ++ cmd, DECODE_CMD_AA(cmd), DECODE_CMD_BB(cmd), ++ DECODE_CMD_CC(cmd), DECODE_CMD_DD(cmd)); ++ ++ do { ++ cypress_ps2_ext_cmd(psmouse, ++ PSMOUSE_CMD_SETRES, DECODE_CMD_DD(cmd)); ++ cypress_ps2_ext_cmd(psmouse, ++ PSMOUSE_CMD_SETRES, DECODE_CMD_CC(cmd)); ++ cypress_ps2_ext_cmd(psmouse, ++ PSMOUSE_CMD_SETRES, DECODE_CMD_BB(cmd)); ++ cypress_ps2_ext_cmd(psmouse, ++ PSMOUSE_CMD_SETRES, DECODE_CMD_AA(cmd)); ++ ++ rc = cypress_ps2_read_cmd_status(psmouse, cmd, param); ++ if (rc) ++ continue; ++ ++ if (cypress_verify_cmd_state(psmouse, cmd, param)) ++ return 0; ++ ++ } while (--tries > 0); ++ ++ return -EIO; ++} ++ ++int cypress_detect(struct psmouse *psmouse, bool set_properties) ++{ ++ unsigned char param[3]; ++ ++ if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_CYPRESS_ID, param)) ++ return -ENODEV; ++ ++ /* Check for Cypress Trackpad signature bytes: 0x33 0xCC */ ++ if (param[0] != 0x33 || param[1] != 0xCC) ++ return -ENODEV; ++ ++ if (set_properties) { ++ psmouse->vendor = "Cypress"; ++ psmouse->name = "Trackpad"; ++ } ++ ++ return 0; ++} ++ ++static int cypress_read_fw_version(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ unsigned char param[3]; ++ ++ if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_CYPRESS_ID, param)) ++ return -ENODEV; ++ ++ /* Check for Cypress Trackpad signature bytes: 0x33 0xCC */ ++ if (param[0] != 0x33 || param[1] != 0xCC) ++ return -ENODEV; ++ ++ cytp->fw_version = param[2] & FW_VERSION_MASX; ++ cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0; ++ ++ /* ++ * Trackpad fw_version 11 (in Dell XPS12) yields a bogus response to ++ * CYTP_CMD_READ_TP_METRICS so do not try to use it. LP: #1103594. ++ */ ++ if (cytp->fw_version >= 11) ++ cytp->tp_metrics_supported = 0; ++ ++ psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version); ++ psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n", ++ cytp->tp_metrics_supported); ++ ++ return 0; ++} ++ ++static int cypress_read_tp_metrics(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ unsigned char param[8]; ++ ++ /* set default values for tp metrics. */ ++ cytp->tp_width = CYTP_DEFAULT_WIDTH; ++ cytp->tp_high = CYTP_DEFAULT_HIGH; ++ cytp->tp_max_abs_x = CYTP_ABS_MAX_X; ++ cytp->tp_max_abs_y = CYTP_ABS_MAX_Y; ++ cytp->tp_min_pressure = CYTP_MIN_PRESSURE; ++ cytp->tp_max_pressure = CYTP_MAX_PRESSURE; ++ cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; ++ cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; ++ ++ if (!cytp->tp_metrics_supported) ++ return 0; ++ ++ memset(param, 0, sizeof(param)); ++ if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) { ++ /* Update trackpad parameters. */ ++ cytp->tp_max_abs_x = (param[1] << 8) | param[0]; ++ cytp->tp_max_abs_y = (param[3] << 8) | param[2]; ++ cytp->tp_min_pressure = param[4]; ++ cytp->tp_max_pressure = param[5]; ++ } ++ ++ if (!cytp->tp_max_pressure || ++ cytp->tp_max_pressure < cytp->tp_min_pressure || ++ !cytp->tp_width || !cytp->tp_high || ++ !cytp->tp_max_abs_x || ++ cytp->tp_max_abs_x < cytp->tp_width || ++ !cytp->tp_max_abs_y || ++ cytp->tp_max_abs_y < cytp->tp_high) ++ return -EINVAL; ++ ++ cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; ++ cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; ++ ++#ifdef CYTP_DEBUG_VERBOSE ++ psmouse_dbg(psmouse, "Dump trackpad hardware configuration as below:\n"); ++ psmouse_dbg(psmouse, "cytp->tp_width = %d\n", cytp->tp_width); ++ psmouse_dbg(psmouse, "cytp->tp_high = %d\n", cytp->tp_high); ++ psmouse_dbg(psmouse, "cytp->tp_max_abs_x = %d\n", cytp->tp_max_abs_x); ++ psmouse_dbg(psmouse, "cytp->tp_max_abs_y = %d\n", cytp->tp_max_abs_y); ++ psmouse_dbg(psmouse, "cytp->tp_min_pressure = %d\n", cytp->tp_min_pressure); ++ psmouse_dbg(psmouse, "cytp->tp_max_pressure = %d\n", cytp->tp_max_pressure); ++ psmouse_dbg(psmouse, "cytp->tp_res_x = %d\n", cytp->tp_res_x); ++ psmouse_dbg(psmouse, "cytp->tp_res_y = %d\n", cytp->tp_res_y); ++ ++ psmouse_dbg(psmouse, "tp_type_APA = %d\n", ++ (param[6] & TP_METRICS_BIT_APA) ? 1 : 0); ++ psmouse_dbg(psmouse, "tp_type_MTG = %d\n", ++ (param[6] & TP_METRICS_BIT_MTG) ? 1 : 0); ++ psmouse_dbg(psmouse, "tp_palm = %d\n", ++ (param[6] & TP_METRICS_BIT_PALM) ? 1 : 0); ++ psmouse_dbg(psmouse, "tp_stubborn = %d\n", ++ (param[6] & TP_METRICS_BIT_STUBBORN) ? 1 : 0); ++ psmouse_dbg(psmouse, "tp_1f_jitter = %d\n", ++ (param[6] & TP_METRICS_BIT_1F_JITTER) >> 2); ++ psmouse_dbg(psmouse, "tp_2f_jitter = %d\n", ++ (param[6] & TP_METRICS_BIT_2F_JITTER) >> 4); ++ psmouse_dbg(psmouse, "tp_1f_spike = %d\n", ++ param[7] & TP_METRICS_BIT_1F_SPIKE); ++ psmouse_dbg(psmouse, "tp_2f_spike = %d\n", ++ (param[7] & TP_METRICS_BIT_2F_SPIKE) >> 2); ++ psmouse_dbg(psmouse, "tp_abs_packet_format_set = %d\n", ++ (param[7] & TP_METRICS_BIT_ABS_PKT_FORMAT_SET) >> 4); ++#endif ++ ++ return 0; ++} ++ ++static int cypress_query_hardware(struct psmouse *psmouse) ++{ ++ int ret; ++ ++ ret = cypress_read_fw_version(psmouse); ++ if (ret) ++ return ret; ++ ++ ret = cypress_read_tp_metrics(psmouse); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int cypress_set_absolute_mode(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ unsigned char param[3]; ++ ++ if (cypress_send_ext_cmd(psmouse, CYTP_CMD_ABS_WITH_PRESSURE_MODE, param) < 0) ++ return -1; ++ ++ cytp->mode = (cytp->mode & ~CYTP_BIT_ABS_REL_MASK) ++ | CYTP_BIT_ABS_PRESSURE; ++ cypress_set_packet_size(psmouse, 5); ++ ++ return 0; ++} ++ ++/* ++ * Reset trackpad device. ++ * This is also the default mode when trackpad powered on. ++ */ ++static void cypress_reset(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ ++ cytp->mode = 0; ++ ++ psmouse_reset(psmouse); ++} ++ ++static int cypress_set_input_params(struct input_dev *input, ++ struct cytp_data *cytp) ++{ ++ int ret; ++ ++ if (!cytp->tp_res_x || !cytp->tp_res_y) ++ return -EINVAL; ++ ++ __set_bit(EV_ABS, input->evbit); ++ input_set_abs_params(input, ABS_X, 0, cytp->tp_max_abs_x, 0, 0); ++ input_set_abs_params(input, ABS_Y, 0, cytp->tp_max_abs_y, 0, 0); ++ input_set_abs_params(input, ABS_PRESSURE, ++ cytp->tp_min_pressure, cytp->tp_max_pressure, 0, 0); ++ input_set_abs_params(input, ABS_TOOL_WIDTH, 0, 255, 0, 0); ++ ++ /* finger position */ ++ input_set_abs_params(input, ABS_MT_POSITION_X, 0, cytp->tp_max_abs_x, 0, 0); ++ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, cytp->tp_max_abs_y, 0, 0); ++ input_set_abs_params(input, ABS_MT_PRESSURE, 0, 255, 0, 0); ++ ++ ret = input_mt_init_slots_flags(input, CYTP_MAX_MT_SLOTS, ++ INPUT_MT_DROP_UNUSED|INPUT_MT_TRACK); ++ if (ret < 0) ++ return ret; ++ ++ __set_bit(INPUT_PROP_SEMI_MT, input->propbit); ++ ++ input_abs_set_res(input, ABS_X, cytp->tp_res_x); ++ input_abs_set_res(input, ABS_Y, cytp->tp_res_y); ++ ++ input_abs_set_res(input, ABS_MT_POSITION_X, cytp->tp_res_x); ++ input_abs_set_res(input, ABS_MT_POSITION_Y, cytp->tp_res_y); ++ ++ __set_bit(BTN_TOUCH, input->keybit); ++ __set_bit(BTN_TOOL_FINGER, input->keybit); ++ __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); ++ __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); ++ __set_bit(BTN_TOOL_QUADTAP, input->keybit); ++ __set_bit(BTN_TOOL_QUINTTAP, input->keybit); ++ ++ __clear_bit(EV_REL, input->evbit); ++ __clear_bit(REL_X, input->relbit); ++ __clear_bit(REL_Y, input->relbit); ++ ++ __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); ++ __set_bit(EV_KEY, input->evbit); ++ __set_bit(BTN_LEFT, input->keybit); ++ __set_bit(BTN_RIGHT, input->keybit); ++ __set_bit(BTN_MIDDLE, input->keybit); ++ ++ input_set_drvdata(input, cytp); ++ ++ return 0; ++} ++ ++static int cypress_get_finger_count(unsigned char header_byte) ++{ ++ unsigned char bits6_7; ++ int finger_count; ++ ++ bits6_7 = header_byte >> 6; ++ finger_count = bits6_7 & 0x03; ++ ++ if (finger_count == 1) ++ return 1; ++ ++ if (header_byte & ABS_HSCROLL_BIT) { ++ /* HSCROLL gets added on to 0 finger count. */ ++ switch (finger_count) { ++ case 0: return 4; ++ case 2: return 5; ++ default: ++ /* Invalid contact (e.g. palm). Ignore it. */ ++ return -1; ++ } ++ } ++ ++ return finger_count; ++} ++ ++ ++static int cypress_parse_packet(struct psmouse *psmouse, ++ struct cytp_data *cytp, struct cytp_report_data *report_data) ++{ ++ unsigned char *packet = psmouse->packet; ++ unsigned char header_byte = packet[0]; ++ int contact_cnt; ++ ++ memset(report_data, 0, sizeof(struct cytp_report_data)); ++ ++ contact_cnt = cypress_get_finger_count(header_byte); ++ ++ if (contact_cnt < 0) /* e.g. palm detect */ ++ return -EINVAL; ++ ++ report_data->contact_cnt = contact_cnt; ++ ++ report_data->tap = (header_byte & ABS_MULTIFINGER_TAP) ? 1 : 0; ++ ++ if (report_data->contact_cnt == 1) { ++ report_data->contacts[0].x = ++ ((packet[1] & 0x70) << 4) | packet[2]; ++ report_data->contacts[0].y = ++ ((packet[1] & 0x07) << 8) | packet[3]; ++ if (cytp->mode & CYTP_BIT_ABS_PRESSURE) ++ report_data->contacts[0].z = packet[4]; ++ ++ } else if (report_data->contact_cnt >= 2) { ++ report_data->contacts[0].x = ++ ((packet[1] & 0x70) << 4) | packet[2]; ++ report_data->contacts[0].y = ++ ((packet[1] & 0x07) << 8) | packet[3]; ++ if (cytp->mode & CYTP_BIT_ABS_PRESSURE) ++ report_data->contacts[0].z = packet[4]; ++ ++ report_data->contacts[1].x = ++ ((packet[5] & 0xf0) << 4) | packet[6]; ++ report_data->contacts[1].y = ++ ((packet[5] & 0x0f) << 8) | packet[7]; ++ if (cytp->mode & CYTP_BIT_ABS_PRESSURE) ++ report_data->contacts[1].z = report_data->contacts[0].z; ++ } ++ ++ report_data->left = (header_byte & BTN_LEFT_BIT) ? 1 : 0; ++ report_data->right = (header_byte & BTN_RIGHT_BIT) ? 1 : 0; ++ ++ /* ++ * This is only true if one of the mouse buttons were tapped. Make ++ * sure it doesn't turn into a click. The regular tap-to-click ++ * functionality will handle that on its own. If we don't do this, ++ * disabling tap-to-click won't affect the mouse button zones. ++ */ ++ if (report_data->tap) ++ report_data->left = 0; ++ ++#ifdef CYTP_DEBUG_VERBOSE ++ { ++ int i; ++ int n = report_data->contact_cnt; ++ psmouse_dbg(psmouse, "Dump parsed report data as below:\n"); ++ psmouse_dbg(psmouse, "contact_cnt = %d\n", ++ report_data->contact_cnt); ++ if (n > CYTP_MAX_MT_SLOTS) ++ n = CYTP_MAX_MT_SLOTS; ++ for (i = 0; i < n; i++) ++ psmouse_dbg(psmouse, "contacts[%d] = {%d, %d, %d}\n", i, ++ report_data->contacts[i].x, ++ report_data->contacts[i].y, ++ report_data->contacts[i].z); ++ psmouse_dbg(psmouse, "left = %d\n", report_data->left); ++ psmouse_dbg(psmouse, "right = %d\n", report_data->right); ++ psmouse_dbg(psmouse, "middle = %d\n", report_data->middle); ++ } ++#endif ++ ++ return 0; ++} ++ ++static void cypress_process_packet(struct psmouse *psmouse, bool zero_pkt) ++{ ++ int i; ++ struct input_dev *input = psmouse->dev; ++ struct cytp_data *cytp = psmouse->private; ++ struct cytp_report_data report_data; ++ struct cytp_contact *contact; ++ struct input_mt_pos pos[CYTP_MAX_MT_SLOTS]; ++ int slots[CYTP_MAX_MT_SLOTS]; ++ int n; ++ ++ if (cypress_parse_packet(psmouse, cytp, &report_data)) ++ return; ++ ++ n = report_data.contact_cnt; ++ ++ if (n > CYTP_MAX_MT_SLOTS) ++ n = CYTP_MAX_MT_SLOTS; ++ ++ for (i = 0; i < n; i++) { ++ contact = &report_data.contacts[i]; ++ pos[i].x = contact->x; ++ pos[i].y = contact->y; ++ } ++ ++ input_mt_assign_slots(input, slots, pos, n); ++ ++ for (i = 0; i < n; i++) { ++ contact = &report_data.contacts[i]; ++ input_mt_slot(input, slots[i]); ++ input_mt_report_slot_state(input, MT_TOOL_FINGER, true); ++ input_report_abs(input, ABS_MT_POSITION_X, contact->x); ++ input_report_abs(input, ABS_MT_POSITION_Y, contact->y); ++ input_report_abs(input, ABS_MT_PRESSURE, contact->z); ++ } ++ ++ input_mt_sync_frame(input); ++ ++ input_mt_report_finger_count(input, report_data.contact_cnt); ++ ++ input_report_key(input, BTN_LEFT, report_data.left); ++ input_report_key(input, BTN_RIGHT, report_data.right); ++ input_report_key(input, BTN_MIDDLE, report_data.middle); ++ ++ input_sync(input); ++} ++ ++static psmouse_ret_t cypress_validate_byte(struct psmouse *psmouse) ++{ ++ int contact_cnt; ++ int index = psmouse->pktcnt - 1; ++ unsigned char *packet = psmouse->packet; ++ struct cytp_data *cytp = psmouse->private; ++ ++ if (index < 0 || index > cytp->pkt_size) ++ return PSMOUSE_BAD_DATA; ++ ++ if (index == 0 && (packet[0] & 0xfc) == 0) { ++ /* call packet process for reporting finger leave. */ ++ cypress_process_packet(psmouse, 1); ++ return PSMOUSE_FULL_PACKET; ++ } ++ ++ /* ++ * Perform validation (and adjust packet size) based only on the ++ * first byte; allow all further bytes through. ++ */ ++ if (index != 0) ++ return PSMOUSE_GOOD_DATA; ++ ++ /* ++ * If absolute/relative mode bit has not been set yet, just pass ++ * the byte through. ++ */ ++ if ((cytp->mode & CYTP_BIT_ABS_REL_MASK) == 0) ++ return PSMOUSE_GOOD_DATA; ++ ++ if ((packet[0] & 0x08) == 0x08) ++ return PSMOUSE_BAD_DATA; ++ ++ contact_cnt = cypress_get_finger_count(packet[0]); ++ ++ if (contact_cnt < 0) ++ return PSMOUSE_BAD_DATA; ++ ++ if (cytp->mode & CYTP_BIT_ABS_NO_PRESSURE) ++ cypress_set_packet_size(psmouse, contact_cnt == 2 ? 7 : 4); ++ else ++ cypress_set_packet_size(psmouse, contact_cnt == 2 ? 8 : 5); ++ ++ return PSMOUSE_GOOD_DATA; ++} ++ ++static psmouse_ret_t cypress_protocol_handler(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ ++ if (psmouse->pktcnt >= cytp->pkt_size) { ++ cypress_process_packet(psmouse, 0); ++ return PSMOUSE_FULL_PACKET; ++ } ++ ++ return cypress_validate_byte(psmouse); ++} ++ ++static void cypress_set_rate(struct psmouse *psmouse, unsigned int rate) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ ++ if (rate >= 80) { ++ psmouse->rate = 80; ++ cytp->mode |= CYTP_BIT_HIGH_RATE; ++ } else { ++ psmouse->rate = 40; ++ cytp->mode &= ~CYTP_BIT_HIGH_RATE; ++ } ++ ++ ps2_command(&psmouse->ps2dev, (unsigned char *)&psmouse->rate, ++ PSMOUSE_CMD_SETRATE); ++} ++ ++static void cypress_disconnect(struct psmouse *psmouse) ++{ ++ cypress_reset(psmouse); ++ kfree(psmouse->private); ++ psmouse->private = NULL; ++} ++ ++static int cypress_reconnect(struct psmouse *psmouse) ++{ ++ int tries = CYTP_PS2_CMD_TRIES; ++ int rc; ++ ++ do { ++ cypress_reset(psmouse); ++ rc = cypress_detect(psmouse, false); ++ } while (rc && (--tries > 0)); ++ ++ if (rc) { ++ psmouse_err(psmouse, "Reconnect: unable to detect trackpad.\n"); ++ return -1; ++ } ++ ++ if (cypress_set_absolute_mode(psmouse)) { ++ psmouse_err(psmouse, "Reconnect: Unable to initialize Cypress absolute mode.\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int cypress_init(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp; ++ ++ cytp = (struct cytp_data *)kzalloc(sizeof(struct cytp_data), GFP_KERNEL); ++ psmouse->private = (void *)cytp; ++ if (cytp == NULL) ++ return -ENOMEM; ++ ++ cypress_reset(psmouse); ++ ++ psmouse->pktsize = 8; ++ ++ if (cypress_query_hardware(psmouse)) { ++ psmouse_err(psmouse, "Unable to query Trackpad hardware.\n"); ++ goto err_exit; ++ } ++ ++ if (cypress_set_absolute_mode(psmouse)) { ++ psmouse_err(psmouse, "init: Unable to initialize Cypress absolute mode.\n"); ++ goto err_exit; ++ } ++ ++ if (cypress_set_input_params(psmouse->dev, cytp) < 0) { ++ psmouse_err(psmouse, "init: Unable to set input params.\n"); ++ goto err_exit; ++ } ++ ++ psmouse->model = 1; ++ psmouse->protocol_handler = cypress_protocol_handler; ++ psmouse->set_rate = cypress_set_rate; ++ psmouse->disconnect = cypress_disconnect; ++ psmouse->reconnect = cypress_reconnect; ++ psmouse->cleanup = cypress_reset; ++ psmouse->resync_time = 0; ++ ++ return 0; ++ ++err_exit: ++ /* ++ * Reset Cypress Trackpad as a standard mouse. Then ++ * let psmouse driver commmunicating with it as default PS2 mouse. ++ */ ++ cypress_reset(psmouse); ++ ++ psmouse->private = NULL; ++ kfree(cytp); ++ ++ return -1; ++} ++ ++bool cypress_supported(void) ++{ ++ return true; ++} +diff --git a/drivers/input/mouse/cypress_ps2.h b/drivers/input/mouse/cypress_ps2.h +new file mode 100644 +index 0000000..4720f21 +--- /dev/null ++++ b/drivers/input/mouse/cypress_ps2.h +@@ -0,0 +1,191 @@ ++#ifndef _CYPRESS_PS2_H ++#define _CYPRESS_PS2_H ++ ++#include "psmouse.h" ++ ++#define CMD_BITS_MASK 0x03 ++#define COMPOSIT(x, s) (((x) & CMD_BITS_MASK) << (s)) ++ ++#define ENCODE_CMD(aa, bb, cc, dd) \ ++ (COMPOSIT((aa), 6) | COMPOSIT((bb), 4) | COMPOSIT((cc), 2) | COMPOSIT((dd), 0)) ++#define CYTP_CMD_ABS_NO_PRESSURE_MODE ENCODE_CMD(0, 1, 0, 0) ++#define CYTP_CMD_ABS_WITH_PRESSURE_MODE ENCODE_CMD(0, 1, 0, 1) ++#define CYTP_CMD_SMBUS_MODE ENCODE_CMD(0, 1, 1, 0) ++#define CYTP_CMD_STANDARD_MODE ENCODE_CMD(0, 2, 0, 0) /* not implemented yet. */ ++#define CYTP_CMD_CYPRESS_REL_MODE ENCODE_CMD(1, 1, 1, 1) /* not implemented yet. */ ++#define CYTP_CMD_READ_CYPRESS_ID ENCODE_CMD(0, 0, 0, 0) ++#define CYTP_CMD_READ_TP_METRICS ENCODE_CMD(0, 0, 0, 1) ++#define CYTP_CMD_SET_HSCROLL_WIDTH(w) ENCODE_CMD(1, 1, 0, (w)) ++#define CYTP_CMD_SET_HSCROLL_MASK ENCODE_CMD(1, 1, 0, 0) ++#define CYTP_CMD_SET_VSCROLL_WIDTH(w) ENCODE_CMD(1, 2, 0, (w)) ++#define CYTP_CMD_SET_VSCROLL_MASK ENCODE_CMD(1, 2, 0, 0) ++#define CYTP_CMD_SET_PALM_GEOMETRY(e) ENCODE_CMD(1, 2, 1, (e)) ++#define CYTP_CMD_PALM_GEMMETRY_MASK ENCODE_CMD(1, 2, 1, 0) ++#define CYTP_CMD_SET_PALM_SENSITIVITY(s) ENCODE_CMD(1, 2, 2, (s)) ++#define CYTP_CMD_PALM_SENSITIVITY_MASK ENCODE_CMD(1, 2, 2, 0) ++#define CYTP_CMD_SET_MOUSE_SENSITIVITY(s) ENCODE_CMD(1, 3, ((s) >> 2), (s)) ++#define CYTP_CMD_MOUSE_SENSITIVITY_MASK ENCODE_CMD(1, 3, 0, 0) ++#define CYTP_CMD_REQUEST_BASELINE_STATUS ENCODE_CMD(2, 0, 0, 1) ++#define CYTP_CMD_REQUEST_RECALIBRATION ENCODE_CMD(2, 0, 0, 3) ++ ++#define DECODE_CMD_AA(x) (((x) >> 6) & CMD_BITS_MASK) ++#define DECODE_CMD_BB(x) (((x) >> 4) & CMD_BITS_MASK) ++#define DECODE_CMD_CC(x) (((x) >> 2) & CMD_BITS_MASK) ++#define DECODE_CMD_DD(x) ((x) & CMD_BITS_MASK) ++ ++/* Cypress trackpad working mode. */ ++#define CYTP_BIT_ABS_PRESSURE (1 << 3) ++#define CYTP_BIT_ABS_NO_PRESSURE (1 << 2) ++#define CYTP_BIT_CYPRESS_REL (1 << 1) ++#define CYTP_BIT_STANDARD_REL (1 << 0) ++#define CYTP_BIT_REL_MASK (CYTP_BIT_CYPRESS_REL | CYTP_BIT_STANDARD_REL) ++#define CYTP_BIT_ABS_MASK (CYTP_BIT_ABS_PRESSURE | CYTP_BIT_ABS_NO_PRESSURE) ++#define CYTP_BIT_ABS_REL_MASK (CYTP_BIT_ABS_MASK | CYTP_BIT_REL_MASK) ++ ++#define CYTP_BIT_HIGH_RATE (1 << 4) ++/* ++ * report mode bit is set, firmware working in Remote Mode. ++ * report mode bit is cleared, firmware working in Stream Mode. ++ */ ++#define CYTP_BIT_REPORT_MODE (1 << 5) ++ ++/* scrolling width values for set HSCROLL and VSCROLL width command. */ ++#define SCROLL_WIDTH_NARROW 1 ++#define SCROLL_WIDTH_NORMAL 2 ++#define SCROLL_WIDTH_WIDE 3 ++ ++#define PALM_GEOMETRY_ENABLE 1 ++#define PALM_GEOMETRY_DISABLE 0 ++ ++#define TP_METRICS_MASK 0x80 ++#define FW_VERSION_MASX 0x7f ++#define FW_VER_HIGH_MASK 0x70 ++#define FW_VER_LOW_MASK 0x0f ++ ++/* Times to retry a ps2_command and millisecond delay between tries. */ ++#define CYTP_PS2_CMD_TRIES 3 ++#define CYTP_PS2_CMD_DELAY 500 ++ ++/* time out for PS/2 command only in milliseconds. */ ++#define CYTP_CMD_TIMEOUT 200 ++#define CYTP_DATA_TIMEOUT 30 ++ ++#define CYTP_EXT_CMD 0xe8 ++#define CYTP_PS2_RETRY 0xfe ++#define CYTP_PS2_ERROR 0xfc ++ ++#define CYTP_RESP_RETRY 0x01 ++#define CYTP_RESP_ERROR 0xfe ++ ++ ++#define CYTP_105001_WIDTH 97 /* Dell XPS 13 */ ++#define CYTP_105001_HIGH 59 ++#define CYTP_DEFAULT_WIDTH (CYTP_105001_WIDTH) ++#define CYTP_DEFAULT_HIGH (CYTP_105001_HIGH) ++ ++#define CYTP_ABS_MAX_X 1600 ++#define CYTP_ABS_MAX_Y 900 ++#define CYTP_MAX_PRESSURE 255 ++#define CYTP_MIN_PRESSURE 0 ++ ++/* header byte bits of relative package. */ ++#define BTN_LEFT_BIT 0x01 ++#define BTN_RIGHT_BIT 0x02 ++#define BTN_MIDDLE_BIT 0x04 ++#define REL_X_SIGN_BIT 0x10 ++#define REL_Y_SIGN_BIT 0x20 ++ ++/* header byte bits of absolute package. */ ++#define ABS_VSCROLL_BIT 0x10 ++#define ABS_HSCROLL_BIT 0x20 ++#define ABS_MULTIFINGER_TAP 0x04 ++#define ABS_EDGE_MOTION_MASK 0x80 ++ ++#define DFLT_RESP_BITS_VALID 0x88 /* SMBus bit should not be set. */ ++#define DFLT_RESP_SMBUS_BIT 0x80 ++#define DFLT_SMBUS_MODE 0x80 ++#define DFLT_PS2_MODE 0x00 ++#define DFLT_RESP_BIT_MODE 0x40 ++#define DFLT_RESP_REMOTE_MODE 0x40 ++#define DFLT_RESP_STREAM_MODE 0x00 ++#define DFLT_RESP_BIT_REPORTING 0x20 ++#define DFLT_RESP_BIT_SCALING 0x10 ++ ++#define TP_METRICS_BIT_PALM 0x80 ++#define TP_METRICS_BIT_STUBBORN 0x40 ++#define TP_METRICS_BIT_2F_JITTER 0x30 ++#define TP_METRICS_BIT_1F_JITTER 0x0c ++#define TP_METRICS_BIT_APA 0x02 ++#define TP_METRICS_BIT_MTG 0x01 ++#define TP_METRICS_BIT_ABS_PKT_FORMAT_SET 0xf0 ++#define TP_METRICS_BIT_2F_SPIKE 0x0c ++#define TP_METRICS_BIT_1F_SPIKE 0x03 ++ ++/* bits of first byte response of E9h-Status Request command. */ ++#define RESP_BTN_RIGHT_BIT 0x01 ++#define RESP_BTN_MIDDLE_BIT 0x02 ++#define RESP_BTN_LEFT_BIT 0x04 ++#define RESP_SCALING_BIT 0x10 ++#define RESP_ENABLE_BIT 0x20 ++#define RESP_REMOTE_BIT 0x40 ++#define RESP_SMBUS_BIT 0x80 ++ ++#define CYTP_MAX_MT_SLOTS 2 ++ ++struct cytp_contact { ++ int x; ++ int y; ++ int z; /* also named as touch pressure. */ ++}; ++ ++/* The structure of Cypress Trackpad event data. */ ++struct cytp_report_data { ++ int contact_cnt; ++ struct cytp_contact contacts[CYTP_MAX_MT_SLOTS]; ++ unsigned int left:1; ++ unsigned int right:1; ++ unsigned int middle:1; ++ unsigned int tap:1; /* multi-finger tap detected. */ ++}; ++ ++/* The structure of Cypress Trackpad device private data. */ ++struct cytp_data { ++ int fw_version; ++ ++ int pkt_size; ++ int mode; ++ ++ int tp_min_pressure; ++ int tp_max_pressure; ++ int tp_width; /* X direction physical size in mm. */ ++ int tp_high; /* Y direction physical size in mm. */ ++ int tp_max_abs_x; /* Max X absolute units that can be reported. */ ++ int tp_max_abs_y; /* Max Y absolute units that can be reported. */ ++ ++ int tp_res_x; /* X resolution in units/mm. */ ++ int tp_res_y; /* Y resolution in units/mm. */ ++ ++ int tp_metrics_supported; ++}; ++ ++ ++#ifdef CONFIG_MOUSE_PS2_CYPRESS ++int cypress_detect(struct psmouse *psmouse, bool set_properties); ++int cypress_init(struct psmouse *psmouse); ++bool cypress_supported(void); ++#else ++inline int cypress_detect(struct psmouse *psmouse, bool set_properties) ++{ ++ return -ENOSYS; ++} ++inline int cypress_init(struct psmouse *psmouse) ++{ ++ return -ENOSYS; ++} ++inline bool cypress_supported(void) ++{ ++ return 0; ++} ++#endif /* CONFIG_MOUSE_PS2_CYPRESS */ ++ ++#endif /* _CYPRESS_PS2_H */ +diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c +index 9f352fb..b139e2c 100644 +--- a/drivers/input/mouse/psmouse-base.c ++++ b/drivers/input/mouse/psmouse-base.c +@@ -34,6 +34,7 @@ + #include "touchkit_ps2.h" + #include "elantech.h" + #include "sentelic.h" ++#include "cypress_ps2.h" + + #define DRIVER_DESC "PS/2 mouse driver" + +@@ -663,6 +664,28 @@ static int psmouse_extensions(struct psmouse *psmouse, + } + + /* ++ * Try Cypress Trackpad. ++ * Must try it before Finger Sensing Pad because Finger Sensing Pad probe ++ * upsets some modules of Cypress Trackpads. ++ */ ++ if (max_proto > PSMOUSE_IMEX && ++ cypress_detect(psmouse, set_properties) == 0) { ++ if (cypress_supported()) { ++ if (cypress_init(psmouse) == 0) ++ return PSMOUSE_CYPRESS; ++ ++ /* ++ * Finger Sensing Pad probe upsets some modules of ++ * Cypress Trackpad, must avoid Finger Sensing Pad ++ * probe if Cypress Trackpad device detected. ++ */ ++ return PSMOUSE_PS2; ++ } ++ ++ max_proto = PSMOUSE_IMEX; ++ } ++ ++/* + * Try ALPS TouchPad + */ + if (max_proto > PSMOUSE_IMEX) { +@@ -789,6 +812,15 @@ static const struct psmouse_protocol psmouse_protocols[] = { + .alias = "thinkps", + .detect = thinking_detect, + }, ++#ifdef CONFIG_MOUSE_PS2_CYPRESS ++ { ++ .type = PSMOUSE_CYPRESS, ++ .name = "CyPS/2", ++ .alias = "cypress", ++ .detect = cypress_detect, ++ .init = cypress_init, ++ }, ++#endif + { + .type = PSMOUSE_GENPS, + .name = "GenPS/2", +diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h +index 9b84b0c..03b2312 100644 +--- a/drivers/input/mouse/psmouse.h ++++ b/drivers/input/mouse/psmouse.h +@@ -8,6 +8,7 @@ + #define PSMOUSE_CMD_SETSTREAM 0x00ea + #define PSMOUSE_CMD_SETPOLL 0x00f0 + #define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */ ++#define PSMOUSE_CMD_RESET_WRAP 0x00ec + #define PSMOUSE_CMD_GETID 0x02f2 + #define PSMOUSE_CMD_SETRATE 0x10f3 + #define PSMOUSE_CMD_ENABLE 0x00f4 +@@ -93,6 +94,7 @@ enum psmouse_type { + PSMOUSE_HGPK, + PSMOUSE_ELANTECH, + PSMOUSE_FSP, ++ PSMOUSE_CYPRESS, + PSMOUSE_AUTO /* This one should always be last */ + }; + +diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c +new file mode 100644 +index 0000000..e559a94 +--- /dev/null ++++ b/drivers/input/mouse/synaptics_usb.c +@@ -0,0 +1,568 @@ ++/* ++ * USB Synaptics device driver ++ * ++ * Copyright (c) 2002 Rob Miller (rob@inpharmatica . co . uk) ++ * Copyright (c) 2003 Ron Lee (ron@debian.org) ++ * cPad driver for kernel 2.4 ++ * ++ * Copyright (c) 2004 Jan Steinhoff (cpad@jan-steinhoff . de) ++ * Copyright (c) 2004 Ron Lee (ron@debian.org) ++ * rewritten for kernel 2.6 ++ * ++ * cPad display character device part is not included. It can be found at ++ * http://jan-steinhoff.de/linux/synaptics-usb.html ++ * ++ * Bases on: usb_skeleton.c v2.2 by Greg Kroah-Hartman ++ * drivers/hid/usbhid/usbmouse.c by Vojtech Pavlik ++ * drivers/input/mouse/synaptics.c by Peter Osterlund ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the Free ++ * Software Foundation; either version 2 of the License, or (at your option) ++ * any later version. ++ * ++ * Trademarks are the property of their respective owners. ++ */ ++ ++/* ++ * There are three different types of Synaptics USB devices: Touchpads, ++ * touchsticks (or trackpoints), and touchscreens. Touchpads are well supported ++ * by this driver, touchstick support has not been tested much yet, and ++ * touchscreens have not been tested at all. ++ * ++ * Up to three alternate settings are possible: ++ * setting 0: one int endpoint for relative movement (used by usbhid.ko) ++ * setting 1: one int endpoint for absolute finger position ++ * setting 2 (cPad only): one int endpoint for absolute finger position and ++ * two bulk endpoints for the display (in/out) ++ * This driver uses setting 1. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define USB_VENDOR_ID_SYNAPTICS 0x06cb ++#define USB_DEVICE_ID_SYNAPTICS_TP 0x0001 /* Synaptics USB TouchPad */ ++#define USB_DEVICE_ID_SYNAPTICS_INT_TP 0x0002 /* Integrated USB TouchPad */ ++#define USB_DEVICE_ID_SYNAPTICS_CPAD 0x0003 /* Synaptics cPad */ ++#define USB_DEVICE_ID_SYNAPTICS_TS 0x0006 /* Synaptics TouchScreen */ ++#define USB_DEVICE_ID_SYNAPTICS_STICK 0x0007 /* Synaptics USB Styk */ ++#define USB_DEVICE_ID_SYNAPTICS_WP 0x0008 /* Synaptics USB WheelPad */ ++#define USB_DEVICE_ID_SYNAPTICS_COMP_TP 0x0009 /* Composite USB TouchPad */ ++#define USB_DEVICE_ID_SYNAPTICS_WTP 0x0010 /* Wireless TouchPad */ ++#define USB_DEVICE_ID_SYNAPTICS_DPAD 0x0013 /* DisplayPad */ ++ ++#define SYNUSB_TOUCHPAD (1 << 0) ++#define SYNUSB_STICK (1 << 1) ++#define SYNUSB_TOUCHSCREEN (1 << 2) ++#define SYNUSB_AUXDISPLAY (1 << 3) /* For cPad */ ++#define SYNUSB_COMBO (1 << 4) /* Composite device (TP + stick) */ ++#define SYNUSB_IO_ALWAYS (1 << 5) ++ ++#define USB_DEVICE_SYNAPTICS(prod, kind) \ ++ USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, \ ++ USB_DEVICE_ID_SYNAPTICS_##prod), \ ++ .driver_info = (kind), ++ ++#define SYNUSB_RECV_SIZE 8 ++ ++#define XMIN_NOMINAL 1472 ++#define XMAX_NOMINAL 5472 ++#define YMIN_NOMINAL 1408 ++#define YMAX_NOMINAL 4448 ++ ++struct synusb { ++ struct usb_device *udev; ++ struct usb_interface *intf; ++ struct urb *urb; ++ unsigned char *data; ++ ++ /* input device related data structures */ ++ struct input_dev *input; ++ char name[128]; ++ char phys[64]; ++ ++ /* characteristics of the device */ ++ unsigned long flags; ++}; ++ ++static void synusb_report_buttons(struct synusb *synusb) ++{ ++ struct input_dev *input_dev = synusb->input; ++ ++ input_report_key(input_dev, BTN_LEFT, synusb->data[1] & 0x04); ++ input_report_key(input_dev, BTN_RIGHT, synusb->data[1] & 0x01); ++ input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x02); ++} ++ ++static void synusb_report_stick(struct synusb *synusb) ++{ ++ struct input_dev *input_dev = synusb->input; ++ int x, y; ++ unsigned int pressure; ++ ++ pressure = synusb->data[6]; ++ x = (s16)(be16_to_cpup((__be16 *)&synusb->data[2]) << 3) >> 7; ++ y = (s16)(be16_to_cpup((__be16 *)&synusb->data[4]) << 3) >> 7; ++ ++ if (pressure > 0) { ++ input_report_rel(input_dev, REL_X, x); ++ input_report_rel(input_dev, REL_Y, -y); ++ } ++ ++ input_report_abs(input_dev, ABS_PRESSURE, pressure); ++ ++ synusb_report_buttons(synusb); ++ ++ input_sync(input_dev); ++} ++ ++static void synusb_report_touchpad(struct synusb *synusb) ++{ ++ struct input_dev *input_dev = synusb->input; ++ unsigned int num_fingers, tool_width; ++ unsigned int x, y; ++ unsigned int pressure, w; ++ ++ pressure = synusb->data[6]; ++ x = be16_to_cpup((__be16 *)&synusb->data[2]); ++ y = be16_to_cpup((__be16 *)&synusb->data[4]); ++ w = synusb->data[0] & 0x0f; ++ ++ if (pressure > 0) { ++ num_fingers = 1; ++ tool_width = 5; ++ switch (w) { ++ case 0 ... 1: ++ num_fingers = 2 + w; ++ break; ++ ++ case 2: /* pen, pretend its a finger */ ++ break; ++ ++ case 4 ... 15: ++ tool_width = w; ++ break; ++ } ++ } else { ++ num_fingers = 0; ++ tool_width = 0; ++ } ++ ++ /* ++ * Post events ++ * BTN_TOUCH has to be first as mousedev relies on it when doing ++ * absolute -> relative conversion ++ */ ++ ++ if (pressure > 30) ++ input_report_key(input_dev, BTN_TOUCH, 1); ++ if (pressure < 25) ++ input_report_key(input_dev, BTN_TOUCH, 0); ++ ++ if (num_fingers > 0) { ++ input_report_abs(input_dev, ABS_X, x); ++ input_report_abs(input_dev, ABS_Y, ++ YMAX_NOMINAL + YMIN_NOMINAL - y); ++ } ++ ++ input_report_abs(input_dev, ABS_PRESSURE, pressure); ++ input_report_abs(input_dev, ABS_TOOL_WIDTH, tool_width); ++ ++ input_report_key(input_dev, BTN_TOOL_FINGER, num_fingers == 1); ++ input_report_key(input_dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); ++ input_report_key(input_dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); ++ ++ synusb_report_buttons(synusb); ++ if (synusb->flags & SYNUSB_AUXDISPLAY) ++ input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x08); ++ ++ input_sync(input_dev); ++} ++ ++static void synusb_irq(struct urb *urb) ++{ ++ struct synusb *synusb = urb->context; ++ int error; ++ ++ /* Check our status in case we need to bail out early. */ ++ switch (urb->status) { ++ case 0: ++ usb_mark_last_busy(synusb->udev); ++ break; ++ ++ /* Device went away so don't keep trying to read from it. */ ++ case -ECONNRESET: ++ case -ENOENT: ++ case -ESHUTDOWN: ++ return; ++ ++ default: ++ goto resubmit; ++ break; ++ } ++ ++ if (synusb->flags & SYNUSB_STICK) ++ synusb_report_stick(synusb); ++ else ++ synusb_report_touchpad(synusb); ++ ++resubmit: ++ error = usb_submit_urb(urb, GFP_ATOMIC); ++ if (error && error != -EPERM) ++ dev_err(&synusb->intf->dev, ++ "%s - usb_submit_urb failed with result: %d", ++ __func__, error); ++} ++ ++static struct usb_endpoint_descriptor * ++synusb_get_in_endpoint(struct usb_host_interface *iface) ++{ ++ ++ struct usb_endpoint_descriptor *endpoint; ++ int i; ++ ++ for (i = 0; i < iface->desc.bNumEndpoints; ++i) { ++ endpoint = &iface->endpoint[i].desc; ++ ++ if (usb_endpoint_is_int_in(endpoint)) { ++ /* we found our interrupt in endpoint */ ++ return endpoint; ++ } ++ } ++ ++ return NULL; ++} ++ ++static int synusb_open(struct input_dev *dev) ++{ ++ struct synusb *synusb = input_get_drvdata(dev); ++ int retval; ++ ++ retval = usb_autopm_get_interface(synusb->intf); ++ if (retval) { ++ dev_err(&synusb->intf->dev, ++ "%s - usb_autopm_get_interface failed, error: %d\n", ++ __func__, retval); ++ return retval; ++ } ++ ++ retval = usb_submit_urb(synusb->urb, GFP_KERNEL); ++ if (retval) { ++ dev_err(&synusb->intf->dev, ++ "%s - usb_submit_urb failed, error: %d\n", ++ __func__, retval); ++ retval = -EIO; ++ goto out; ++ } ++ ++ synusb->intf->needs_remote_wakeup = 1; ++ ++out: ++ usb_autopm_put_interface(synusb->intf); ++ return retval; ++} ++ ++static void synusb_close(struct input_dev *dev) ++{ ++ struct synusb *synusb = input_get_drvdata(dev); ++ int autopm_error; ++ ++ autopm_error = usb_autopm_get_interface(synusb->intf); ++ ++ usb_kill_urb(synusb->urb); ++ synusb->intf->needs_remote_wakeup = 0; ++ ++ if (!autopm_error) ++ usb_autopm_put_interface(synusb->intf); ++} ++ ++static int synusb_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ struct usb_device *udev = interface_to_usbdev(intf); ++ struct usb_endpoint_descriptor *ep; ++ struct synusb *synusb; ++ struct input_dev *input_dev; ++ unsigned int intf_num = intf->cur_altsetting->desc.bInterfaceNumber; ++ unsigned int altsetting = min(intf->num_altsetting, 1U); ++ int error; ++ ++ error = usb_set_interface(udev, intf_num, altsetting); ++ if (error) { ++ dev_err(&udev->dev, ++ "Can not set alternate setting to %i, error: %i", ++ altsetting, error); ++ return error; ++ } ++ ++ ep = synusb_get_in_endpoint(intf->cur_altsetting); ++ if (!ep) ++ return -ENODEV; ++ ++ synusb = kzalloc(sizeof(*synusb), GFP_KERNEL); ++ input_dev = input_allocate_device(); ++ if (!synusb || !input_dev) { ++ error = -ENOMEM; ++ goto err_free_mem; ++ } ++ ++ synusb->udev = udev; ++ synusb->intf = intf; ++ synusb->input = input_dev; ++ ++ synusb->flags = id->driver_info; ++ if (synusb->flags & SYNUSB_COMBO) { ++ /* ++ * This is a combo device, we need to set proper ++ * capability, depending on the interface. ++ */ ++ synusb->flags |= intf_num == 1 ? ++ SYNUSB_STICK : SYNUSB_TOUCHPAD; ++ } ++ ++ synusb->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!synusb->urb) { ++ error = -ENOMEM; ++ goto err_free_mem; ++ } ++ ++ synusb->data = usb_alloc_coherent(udev, SYNUSB_RECV_SIZE, GFP_KERNEL, ++ &synusb->urb->transfer_dma); ++ if (!synusb->data) { ++ error = -ENOMEM; ++ goto err_free_urb; ++ } ++ ++ usb_fill_int_urb(synusb->urb, udev, ++ usb_rcvintpipe(udev, ep->bEndpointAddress), ++ synusb->data, SYNUSB_RECV_SIZE, ++ synusb_irq, synusb, ++ ep->bInterval); ++ synusb->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; ++ ++ if (udev->manufacturer) ++ strlcpy(synusb->name, udev->manufacturer, ++ sizeof(synusb->name)); ++ ++ if (udev->product) { ++ if (udev->manufacturer) ++ strlcat(synusb->name, " ", sizeof(synusb->name)); ++ strlcat(synusb->name, udev->product, sizeof(synusb->name)); ++ } ++ ++ if (!strlen(synusb->name)) ++ snprintf(synusb->name, sizeof(synusb->name), ++ "USB Synaptics Device %04x:%04x", ++ le16_to_cpu(udev->descriptor.idVendor), ++ le16_to_cpu(udev->descriptor.idProduct)); ++ ++ if (synusb->flags & SYNUSB_STICK) ++ strlcat(synusb->name, " (Stick) ", sizeof(synusb->name)); ++ ++ usb_make_path(udev, synusb->phys, sizeof(synusb->phys)); ++ strlcat(synusb->phys, "/input0", sizeof(synusb->phys)); ++ ++ input_dev->name = synusb->name; ++ input_dev->phys = synusb->phys; ++ usb_to_input_id(udev, &input_dev->id); ++ input_dev->dev.parent = &synusb->intf->dev; ++ ++ if (!(synusb->flags & SYNUSB_IO_ALWAYS)) { ++ input_dev->open = synusb_open; ++ input_dev->close = synusb_close; ++ } ++ ++ input_set_drvdata(input_dev, synusb); ++ ++ __set_bit(EV_ABS, input_dev->evbit); ++ __set_bit(EV_KEY, input_dev->evbit); ++ ++ if (synusb->flags & SYNUSB_STICK) { ++ __set_bit(EV_REL, input_dev->evbit); ++ __set_bit(REL_X, input_dev->relbit); ++ __set_bit(REL_Y, input_dev->relbit); ++ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0); ++ } else { ++ input_set_abs_params(input_dev, ABS_X, ++ XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); ++ input_set_abs_params(input_dev, ABS_Y, ++ YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); ++ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); ++ input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); ++ __set_bit(BTN_TOUCH, input_dev->keybit); ++ __set_bit(BTN_TOOL_FINGER, input_dev->keybit); ++ __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); ++ __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); ++ } ++ ++ __set_bit(BTN_LEFT, input_dev->keybit); ++ __set_bit(BTN_RIGHT, input_dev->keybit); ++ __set_bit(BTN_MIDDLE, input_dev->keybit); ++ ++ usb_set_intfdata(intf, synusb); ++ ++ if (synusb->flags & SYNUSB_IO_ALWAYS) { ++ error = synusb_open(input_dev); ++ if (error) ++ goto err_free_dma; ++ } ++ ++ error = input_register_device(input_dev); ++ if (error) { ++ dev_err(&udev->dev, ++ "Failed to register input device, error %d\n", ++ error); ++ goto err_stop_io; ++ } ++ ++ return 0; ++ ++err_stop_io: ++ if (synusb->flags & SYNUSB_IO_ALWAYS) ++ synusb_close(synusb->input); ++err_free_dma: ++ usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data, ++ synusb->urb->transfer_dma); ++err_free_urb: ++ usb_free_urb(synusb->urb); ++err_free_mem: ++ input_free_device(input_dev); ++ kfree(synusb); ++ usb_set_intfdata(intf, NULL); ++ ++ return error; ++} ++ ++static void synusb_disconnect(struct usb_interface *intf) ++{ ++ struct synusb *synusb = usb_get_intfdata(intf); ++ struct usb_device *udev = interface_to_usbdev(intf); ++ ++ if (synusb->flags & SYNUSB_IO_ALWAYS) ++ synusb_close(synusb->input); ++ ++ input_unregister_device(synusb->input); ++ ++ usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data, ++ synusb->urb->transfer_dma); ++ usb_free_urb(synusb->urb); ++ kfree(synusb); ++ ++ usb_set_intfdata(intf, NULL); ++} ++ ++static int synusb_suspend(struct usb_interface *intf, pm_message_t message) ++{ ++ struct synusb *synusb = usb_get_intfdata(intf); ++ struct input_dev *input_dev = synusb->input; ++ ++ mutex_lock(&input_dev->mutex); ++ usb_kill_urb(synusb->urb); ++ mutex_unlock(&input_dev->mutex); ++ ++ return 0; ++} ++ ++static int synusb_resume(struct usb_interface *intf) ++{ ++ struct synusb *synusb = usb_get_intfdata(intf); ++ struct input_dev *input_dev = synusb->input; ++ int retval = 0; ++ ++ mutex_lock(&input_dev->mutex); ++ ++ if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) && ++ usb_submit_urb(synusb->urb, GFP_NOIO) < 0) { ++ retval = -EIO; ++ } ++ ++ mutex_unlock(&input_dev->mutex); ++ ++ return retval; ++} ++ ++static int synusb_pre_reset(struct usb_interface *intf) ++{ ++ struct synusb *synusb = usb_get_intfdata(intf); ++ struct input_dev *input_dev = synusb->input; ++ ++ mutex_lock(&input_dev->mutex); ++ usb_kill_urb(synusb->urb); ++ ++ return 0; ++} ++ ++static int synusb_post_reset(struct usb_interface *intf) ++{ ++ struct synusb *synusb = usb_get_intfdata(intf); ++ struct input_dev *input_dev = synusb->input; ++ int retval = 0; ++ ++ if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) && ++ usb_submit_urb(synusb->urb, GFP_NOIO) < 0) { ++ retval = -EIO; ++ } ++ ++ mutex_unlock(&input_dev->mutex); ++ ++ return retval; ++} ++ ++static int synusb_reset_resume(struct usb_interface *intf) ++{ ++ return synusb_resume(intf); ++} ++ ++static struct usb_device_id synusb_idtable[] = { ++ { USB_DEVICE_SYNAPTICS(TP, SYNUSB_TOUCHPAD) }, ++ { USB_DEVICE_SYNAPTICS(INT_TP, SYNUSB_TOUCHPAD) }, ++ { USB_DEVICE_SYNAPTICS(CPAD, ++ SYNUSB_TOUCHPAD | SYNUSB_AUXDISPLAY | SYNUSB_IO_ALWAYS) }, ++ { USB_DEVICE_SYNAPTICS(TS, SYNUSB_TOUCHSCREEN) }, ++ { USB_DEVICE_SYNAPTICS(STICK, SYNUSB_STICK) }, ++ { USB_DEVICE_SYNAPTICS(WP, SYNUSB_TOUCHPAD) }, ++ { USB_DEVICE_SYNAPTICS(COMP_TP, SYNUSB_COMBO) }, ++ { USB_DEVICE_SYNAPTICS(WTP, SYNUSB_TOUCHPAD) }, ++ { USB_DEVICE_SYNAPTICS(DPAD, SYNUSB_TOUCHPAD) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(usb, synusb_idtable); ++ ++static struct usb_driver synusb_driver = { ++ .name = "synaptics_usb", ++ .probe = synusb_probe, ++ .disconnect = synusb_disconnect, ++ .id_table = synusb_idtable, ++ .suspend = synusb_suspend, ++ .resume = synusb_resume, ++ .pre_reset = synusb_pre_reset, ++ .post_reset = synusb_post_reset, ++ .reset_resume = synusb_reset_resume, ++ .supports_autosuspend = 1, ++}; ++ ++static int __init synusb_init(void) ++{ ++ return usb_register(&synusb_driver); ++} ++ ++static void __exit synusb_exit(void) ++{ ++ usb_deregister(&synusb_driver); ++} ++ ++module_init(synusb_init); ++module_exit(synusb_exit); ++ ++MODULE_AUTHOR("Rob Miller , " ++ "Ron Lee , " ++ "Jan Steinhoff "); ++MODULE_DESCRIPTION("Synaptics USB device driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig +index 58a8775..bed7cbf 100644 +--- a/drivers/input/tablet/Kconfig ++++ b/drivers/input/tablet/Kconfig +@@ -76,7 +76,10 @@ config TABLET_USB_KBTAB + config TABLET_USB_WACOM + tristate "Wacom Intuos/Graphire tablet support (USB)" + depends on USB_ARCH_HAS_HCD ++ select POWER_SUPPLY + select USB ++ select NEW_LEDS ++ select LEDS_CLASS + help + Say Y here if you want to use the USB version of the Wacom Intuos + or Graphire tablet. Make sure to say Y to "Mouse support" +diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h +index 0783864..b79d451 100644 +--- a/drivers/input/tablet/wacom.h ++++ b/drivers/input/tablet/wacom.h +@@ -88,6 +88,7 @@ + #include + #include + #include ++#include + #include + + /* +@@ -112,6 +113,7 @@ struct wacom { + struct urb *irq; + struct wacom_wac wacom_wac; + struct mutex lock; ++ struct work_struct work; + bool open; + char phys[32]; + struct wacom_led { +@@ -120,12 +122,19 @@ struct wacom { + u8 hlv; /* status led brightness button pressed (1..127) */ + u8 img_lum; /* OLED matrix display brightness */ + } led; ++ struct power_supply battery; + }; + ++static inline void wacom_schedule_work(struct wacom_wac *wacom_wac) ++{ ++ struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); ++ schedule_work(&wacom->work); ++} ++ + extern const struct usb_device_id wacom_ids[]; + + void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); + void wacom_setup_device_quirks(struct wacom_features *features); +-void wacom_setup_input_capabilities(struct input_dev *input_dev, +- struct wacom_wac *wacom_wac); ++int wacom_setup_input_capabilities(struct input_dev *input_dev, ++ struct wacom_wac *wacom_wac); + #endif +diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c +index 1c1b7b4..d709e47 100644 +--- a/drivers/input/tablet/wacom_sys.c ++++ b/drivers/input/tablet/wacom_sys.c +@@ -28,7 +28,10 @@ + #define HID_USAGE_Y_TILT 0x3e + #define HID_USAGE_FINGER 0x22 + #define HID_USAGE_STYLUS 0x20 +-#define HID_COLLECTION 0xc0 ++#define HID_USAGE_CONTACTMAX 0x55 ++#define HID_COLLECTION 0xa1 ++#define HID_COLLECTION_LOGICAL 0x02 ++#define HID_COLLECTION_END 0xc0 + + enum { + WCM_UNDEFINED = 0, +@@ -66,7 +69,8 @@ static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id, + do { + retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_REPORT, +- USB_TYPE_CLASS | USB_RECIP_INTERFACE, ++ USB_DIR_IN | USB_TYPE_CLASS | ++ USB_RECIP_INTERFACE, + (type << 8) + id, + intf->altsetting[0].desc.bInterfaceNumber, + buf, size, 100); +@@ -164,7 +168,99 @@ static void wacom_close(struct input_dev *dev) + usb_autopm_put_interface(wacom->intf); + } + +-static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, ++/* ++ * Static values for max X/Y and resolution of Pen interface is stored in ++ * features. This mean physical size of active area can be computed. ++ * This is useful to do when Pen and Touch have same active area of tablet. ++ * This means for Touch device, we only need to find max X/Y value and we ++ * have enough information to compute resolution of touch. ++ */ ++static void wacom_set_phy_from_res(struct wacom_features *features) ++{ ++ features->x_phy = (features->x_max * 100) / features->x_resolution; ++ features->y_phy = (features->y_max * 100) / features->y_resolution; ++} ++ ++static int wacom_parse_logical_collection(unsigned char *report, ++ struct wacom_features *features) ++{ ++ int length = 0; ++ ++ if (features->type == BAMBOO_PT) { ++ ++ /* Logical collection is only used by 3rd gen Bamboo Touch */ ++ features->pktlen = WACOM_PKGLEN_BBTOUCH3; ++ features->device_type = BTN_TOOL_FINGER; ++ ++ wacom_set_phy_from_res(features); ++ ++ features->x_max = features->y_max = ++ get_unaligned_le16(&report[10]); ++ ++ length = 11; ++ } ++ return length; ++} ++ ++static void wacom_retrieve_report_data(struct usb_interface *intf, ++ struct wacom_features *features) ++{ ++ int result = 0; ++ unsigned char *rep_data; ++ ++ rep_data = kmalloc(2, GFP_KERNEL); ++ if (rep_data) { ++ ++ rep_data[0] = 12; ++ result = wacom_get_report(intf, WAC_HID_FEATURE_REPORT, ++ rep_data[0], rep_data, 2, ++ WAC_MSG_RETRIES); ++ ++ if (result >= 0 && rep_data[1] > 2) ++ features->touch_max = rep_data[1]; ++ ++ kfree(rep_data); ++ } ++} ++ ++/* ++ * Interface Descriptor of wacom devices can be incomplete and ++ * inconsistent so wacom_features table is used to store stylus ++ * device's packet lengths, various maximum values, and tablet ++ * resolution based on product ID's. ++ * ++ * For devices that contain 2 interfaces, wacom_features table is ++ * inaccurate for the touch interface. Since the Interface Descriptor ++ * for touch interfaces has pretty complete data, this function exists ++ * to query tablet for this missing information instead of hard coding in ++ * an additional table. ++ * ++ * A typical Interface Descriptor for a stylus will contain a ++ * boot mouse application collection that is not of interest and this ++ * function will ignore it. ++ * ++ * It also contains a digitizer application collection that also is not ++ * of interest since any information it contains would be duplicate ++ * of what is in wacom_features. Usually it defines a report of an array ++ * of bytes that could be used as max length of the stylus packet returned. ++ * If it happens to define a Digitizer-Stylus Physical Collection then ++ * the X and Y logical values contain valid data but it is ignored. ++ * ++ * A typical Interface Descriptor for a touch interface will contain a ++ * Digitizer-Finger Physical Collection which will define both logical ++ * X/Y maximum as well as the physical size of tablet. Since touch ++ * interfaces haven't supported pressure or distance, this is enough ++ * information to override invalid values in the wacom_features table. ++ * ++ * 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical ++ * Collection. Instead they define a Logical Collection with a single ++ * Logical Maximum for both X and Y. ++ * ++ * Intuos5 touch interface does not contain useful data. We deal with ++ * this after returning from this function. ++ */ ++static int wacom_parse_hid(struct usb_interface *intf, ++ struct hid_descriptor *hid_desc, + struct wacom_features *features) + { + struct usb_device *dev = interface_to_usbdev(intf); +@@ -220,12 +316,14 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi + if (features->type == TABLETPC2FG) { + /* need to reset back */ + features->pktlen = WACOM_PKGLEN_TPC2FG; +- features->device_type = BTN_TOOL_DOUBLETAP; + } ++ ++ if (features->type == MTSCREEN) ++ features->pktlen = WACOM_PKGLEN_MTOUCH; ++ + if (features->type == BAMBOO_PT) { + /* need to reset back */ + features->pktlen = WACOM_PKGLEN_BBTOUCH; +- features->device_type = BTN_TOOL_DOUBLETAP; + features->x_phy = + get_unaligned_le16(&report[i + 5]); + features->x_max = +@@ -244,8 +342,6 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi + /* penabled only accepts exact bytes of data */ + if (features->type == TABLETPC2FG) + features->pktlen = WACOM_PKGLEN_GRAPHIRE; +- if (features->type == BAMBOO_PT) +- features->pktlen = WACOM_PKGLEN_BBFUN; + features->device_type = BTN_TOOL_PEN; + features->x_max = + get_unaligned_le16(&report[i + 3]); +@@ -257,20 +353,15 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi + case HID_USAGE_Y: + if (usage == WCM_DESKTOP) { + if (finger) { +- features->device_type = BTN_TOOL_FINGER; +- if (features->type == TABLETPC2FG) { +- /* need to reset back */ +- features->pktlen = WACOM_PKGLEN_TPC2FG; +- features->device_type = BTN_TOOL_DOUBLETAP; ++ int type = features->type; ++ ++ if (type == TABLETPC2FG || type == MTSCREEN) { + features->y_max = + get_unaligned_le16(&report[i + 3]); + features->y_phy = + get_unaligned_le16(&report[i + 6]); + i += 7; +- } else if (features->type == BAMBOO_PT) { +- /* need to reset back */ +- features->pktlen = WACOM_PKGLEN_BBTOUCH; +- features->device_type = BTN_TOOL_DOUBLETAP; ++ } else if (type == BAMBOO_PT) { + features->y_phy = + get_unaligned_le16(&report[i + 3]); + features->y_max = +@@ -284,12 +375,6 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi + i += 4; + } + } else if (pen) { +- /* penabled only accepts exact bytes of data */ +- if (features->type == TABLETPC2FG) +- features->pktlen = WACOM_PKGLEN_GRAPHIRE; +- if (features->type == BAMBOO_PT) +- features->pktlen = WACOM_PKGLEN_BBFUN; +- features->device_type = BTN_TOOL_PEN; + features->y_max = + get_unaligned_le16(&report[i + 3]); + i += 4; +@@ -302,17 +387,39 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi + i++; + break; + ++ /* ++ * Requiring Stylus Usage will ignore boot mouse ++ * X/Y values and some cases of invalid Digitizer X/Y ++ * values commonly reported. ++ */ + case HID_USAGE_STYLUS: + pen = 1; + i++; + break; ++ ++ case HID_USAGE_CONTACTMAX: ++ /* leave touch_max as is if predefined */ ++ if (!features->touch_max) ++ wacom_retrieve_report_data(intf, features); ++ i++; ++ break; + } + break; + +- case HID_COLLECTION: ++ case HID_COLLECTION_END: + /* reset UsagePage and Finger */ + finger = usage = 0; + break; ++ ++ case HID_COLLECTION: ++ i++; ++ switch (report[i]) { ++ case HID_COLLECTION_LOGICAL: ++ i += wacom_parse_logical_collection(&report[i], ++ features); ++ break; ++ } ++ break; + } + } + +@@ -332,23 +439,33 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat + if (!rep_data) + return error; + +- /* ask to report tablet data if it is MT Tablet PC or +- * not a Tablet PC */ +- if (features->type == TABLETPC2FG) { +- do { +- rep_data[0] = 3; +- rep_data[1] = 4; +- rep_data[2] = 0; +- rep_data[3] = 0; +- report_id = 3; +- error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, +- report_id, rep_data, 4, 1); +- if (error >= 0) +- error = wacom_get_report(intf, +- WAC_HID_FEATURE_REPORT, +- report_id, rep_data, 4, 1); +- } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); +- } else if (features->type != TABLETPC) { ++ /* ask to report Wacom data */ ++ if (features->device_type == BTN_TOOL_FINGER) { ++ /* if it is an MT Tablet PC touch */ ++ if (features->type == TABLETPC2FG || ++ features->type == MTSCREEN) { ++ do { ++ rep_data[0] = 3; ++ rep_data[1] = 4; ++ rep_data[2] = 0; ++ rep_data[3] = 0; ++ report_id = 3; ++ error = wacom_set_report(intf, ++ WAC_HID_FEATURE_REPORT, ++ report_id, ++ rep_data, 4, 1); ++ if (error >= 0) ++ error = wacom_get_report(intf, ++ WAC_HID_FEATURE_REPORT, ++ report_id, ++ rep_data, 4, 1); ++ } while ((error < 0 || rep_data[1] != 4) && ++ limit++ < WAC_MSG_RETRIES); ++ } ++ } else if (features->type != TABLETPC && ++ features->type != WIRELESS && ++ features->type != TABLETPC2FG && ++ features->device_type == BTN_TOOL_PEN) { + do { + rep_data[0] = 2; + rep_data[1] = 2; +@@ -367,7 +484,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat + } + + static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, +- struct wacom_features *features) ++ struct wacom_features *features) + { + int error = 0; + struct usb_host_interface *interface = intf->cur_altsetting; +@@ -380,16 +497,35 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, + features->pressure_fuzz = 0; + features->distance_fuzz = 0; + +- /* only Tablet PCs and Bamboo P&T need to retrieve the info */ +- if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && +- (features->type != BAMBOO_PT)) ++ /* ++ * The wireless device HID is basic and layout conflicts with ++ * other tablets (monitor and touch interface can look like pen). ++ * Skip the query for this type and modify defaults based on ++ * interface number. ++ */ ++ if (features->type == WIRELESS) { ++ if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { ++ features->device_type = 0; ++ } else if (intf->cur_altsetting->desc.bInterfaceNumber == 2) { ++ features->device_type = BTN_TOOL_DOUBLETAP; ++ features->pktlen = WACOM_PKGLEN_BBTOUCH3; ++ } ++ } ++ ++ /* only devices that support touch need to retrieve the info */ ++ if (features->type != TABLETPC && ++ features->type != TABLETPC2FG && ++ features->type != BAMBOO_PT && ++ features->type != MTSCREEN) { + goto out; ++ } + +- if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { +- if (usb_get_extra_descriptor(&interface->endpoint[0], +- HID_DEVICET_REPORT, &hid_desc)) { +- printk("wacom: can not retrieve extra class descriptor\n"); +- error = 1; ++ error = usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc); ++ if (error) { ++ error = usb_get_extra_descriptor(&interface->endpoint[0], ++ HID_DEVICET_REPORT, &hid_desc); ++ if (error) { ++ printk(KERN_ERR "wacom: can not retrieve extra class descriptor\n"); + goto out; + } + } +@@ -479,22 +615,39 @@ static void wacom_remove_shared_data(struct wacom_wac *wacom) + static int wacom_led_control(struct wacom *wacom) + { + unsigned char *buf; +- int retval, led = 0; ++ int retval; + + buf = kzalloc(9, GFP_KERNEL); + if (!buf) + return -ENOMEM; + +- if (wacom->wacom_wac.features.type == WACOM_21UX2) +- led = (wacom->led.select[1] << 4) | 0x40; +- +- led |= wacom->led.select[0] | 0x4; +- +- buf[0] = WAC_CMD_LED_CONTROL; +- buf[1] = led; +- buf[2] = wacom->led.llv; +- buf[3] = wacom->led.hlv; +- buf[4] = wacom->led.img_lum; ++ if (wacom->wacom_wac.features.type >= INTUOS5S && ++ wacom->wacom_wac.features.type <= INTUOS5L) { ++ /* ++ * Touch Ring and crop mark LED luminance may take on ++ * one of four values: ++ * 0 = Low; 1 = Medium; 2 = High; 3 = Off ++ */ ++ int ring_led = wacom->led.select[0] & 0x03; ++ int ring_lum = (((wacom->led.llv & 0x60) >> 5) - 1) & 0x03; ++ int crop_lum = 0; ++ ++ buf[0] = WAC_CMD_LED_CONTROL; ++ buf[1] = (crop_lum << 4) | (ring_lum << 2) | (ring_led); ++ } ++ else { ++ int led = wacom->led.select[0] | 0x4; ++ ++ if (wacom->wacom_wac.features.type == WACOM_21UX2 || ++ wacom->wacom_wac.features.type == WACOM_24HD) ++ led |= (wacom->led.select[1] << 4) | 0x40; ++ ++ buf[0] = WAC_CMD_LED_CONTROL; ++ buf[1] = led; ++ buf[2] = wacom->led.llv; ++ buf[3] = wacom->led.hlv; ++ buf[4] = wacom->led.img_lum; ++ } + + retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL, + buf, 9, WAC_CMD_RETRIES); +@@ -687,6 +840,17 @@ static struct attribute_group intuos4_led_attr_group = { + .attrs = intuos4_led_attrs, + }; + ++static struct attribute *intuos5_led_attrs[] = { ++ &dev_attr_status0_luminance.attr, ++ &dev_attr_status_led0_select.attr, ++ NULL ++}; ++ ++static struct attribute_group intuos5_led_attr_group = { ++ .name = "wacom_led", ++ .attrs = intuos5_led_attrs, ++}; ++ + static int wacom_initialize_leds(struct wacom *wacom) + { + int error; +@@ -704,6 +868,7 @@ static int wacom_initialize_leds(struct wacom *wacom) + &intuos4_led_attr_group); + break; + ++ case WACOM_24HD: + case WACOM_21UX2: + wacom->led.select[0] = 0; + wacom->led.select[1] = 0; +@@ -715,6 +880,19 @@ static int wacom_initialize_leds(struct wacom *wacom) + &cintiq_led_attr_group); + break; + ++ case INTUOS5S: ++ case INTUOS5: ++ case INTUOS5L: ++ wacom->led.select[0] = 0; ++ wacom->led.select[1] = 0; ++ wacom->led.llv = 32; ++ wacom->led.hlv = 0; ++ wacom->led.img_lum = 0; ++ ++ error = sysfs_create_group(&wacom->intf->dev.kobj, ++ &intuos5_led_attr_group); ++ break; ++ + default: + return 0; + } +@@ -738,10 +916,172 @@ static void wacom_destroy_leds(struct wacom *wacom) + &intuos4_led_attr_group); + break; + ++ case WACOM_24HD: + case WACOM_21UX2: + sysfs_remove_group(&wacom->intf->dev.kobj, + &cintiq_led_attr_group); + break; ++ ++ case INTUOS5S: ++ case INTUOS5: ++ case INTUOS5L: ++ sysfs_remove_group(&wacom->intf->dev.kobj, ++ &intuos5_led_attr_group); ++ break; ++ } ++} ++ ++static enum power_supply_property wacom_battery_props[] = { ++ POWER_SUPPLY_PROP_CAPACITY ++}; ++ ++static int wacom_battery_get_property(struct power_supply *psy, ++ enum power_supply_property psp, ++ union power_supply_propval *val) ++{ ++ struct wacom *wacom = container_of(psy, struct wacom, battery); ++ int ret = 0; ++ ++ switch (psp) { ++ case POWER_SUPPLY_PROP_CAPACITY: ++ val->intval = ++ wacom->wacom_wac.battery_capacity * 100 / 31; ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++static int wacom_initialize_battery(struct wacom *wacom) ++{ ++ int error = 0; ++ ++ if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) { ++ wacom->battery.properties = wacom_battery_props; ++ wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props); ++ wacom->battery.get_property = wacom_battery_get_property; ++ wacom->battery.name = "wacom_battery"; ++ wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY; ++ wacom->battery.use_for_apm = 0; ++ ++ error = power_supply_register(&wacom->usbdev->dev, ++ &wacom->battery); ++ } ++ ++ return error; ++} ++ ++static void wacom_destroy_battery(struct wacom *wacom) ++{ ++ if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) ++ power_supply_unregister(&wacom->battery); ++} ++ ++static int wacom_register_input(struct wacom *wacom) ++{ ++ struct input_dev *input_dev; ++ struct usb_interface *intf = wacom->intf; ++ struct usb_device *dev = interface_to_usbdev(intf); ++ struct wacom_wac *wacom_wac = &(wacom->wacom_wac); ++ int error; ++ ++ input_dev = input_allocate_device(); ++ if (!input_dev) { ++ error = -ENOMEM; ++ goto fail1; ++ } ++ ++ input_dev->name = wacom_wac->name; ++ input_dev->dev.parent = &intf->dev; ++ input_dev->open = wacom_open; ++ input_dev->close = wacom_close; ++ usb_to_input_id(dev, &input_dev->id); ++ input_set_drvdata(input_dev, wacom); ++ ++ wacom_wac->input = input_dev; ++ error = wacom_setup_input_capabilities(input_dev, wacom_wac); ++ if (error) ++ goto fail1; ++ ++ error = input_register_device(input_dev); ++ if (error) ++ goto fail2; ++ ++ return 0; ++ ++fail2: ++ input_free_device(input_dev); ++ wacom_wac->input = NULL; ++fail1: ++ return error; ++} ++ ++static void wacom_wireless_work(struct work_struct *work) ++{ ++ struct wacom *wacom = container_of(work, struct wacom, work); ++ struct usb_device *usbdev = wacom->usbdev; ++ struct wacom_wac *wacom_wac = &wacom->wacom_wac; ++ ++ /* ++ * Regardless if this is a disconnect or a new tablet, ++ * remove any existing input devices. ++ */ ++ ++ /* Stylus interface */ ++ wacom = usb_get_intfdata(usbdev->config->interface[1]); ++ if (wacom->wacom_wac.input) ++ input_unregister_device(wacom->wacom_wac.input); ++ wacom->wacom_wac.input = 0; ++ ++ /* Touch interface */ ++ wacom = usb_get_intfdata(usbdev->config->interface[2]); ++ if (wacom->wacom_wac.input) ++ input_unregister_device(wacom->wacom_wac.input); ++ wacom->wacom_wac.input = 0; ++ ++ if (wacom_wac->pid == 0) { ++ printk(KERN_INFO "wacom: wireless tablet disconnected\n"); ++ } else { ++ const struct usb_device_id *id = wacom_ids; ++ ++ printk(KERN_INFO ++ "wacom: wireless tablet connected with PID %x\n", ++ wacom_wac->pid); ++ ++ while (id->match_flags) { ++ if (id->idVendor == USB_VENDOR_ID_WACOM && ++ id->idProduct == wacom_wac->pid) ++ break; ++ id++; ++ } ++ ++ if (!id->match_flags) { ++ printk(KERN_INFO ++ "wacom: ignorning unknown PID.\n"); ++ return; ++ } ++ ++ /* Stylus interface */ ++ wacom = usb_get_intfdata(usbdev->config->interface[1]); ++ wacom_wac = &wacom->wacom_wac; ++ wacom_wac->features = ++ *((struct wacom_features *)id->driver_info); ++ wacom_wac->features.device_type = BTN_TOOL_PEN; ++ wacom_register_input(wacom); ++ ++ /* Touch interface */ ++ wacom = usb_get_intfdata(usbdev->config->interface[2]); ++ wacom_wac = &wacom->wacom_wac; ++ wacom_wac->features = ++ *((struct wacom_features *)id->driver_info); ++ wacom_wac->features.pktlen = WACOM_PKGLEN_BBTOUCH3; ++ wacom_wac->features.device_type = BTN_TOOL_FINGER; ++ wacom_set_phy_from_res(&wacom_wac->features); ++ wacom_wac->features.x_max = wacom_wac->features.y_max = 4096; ++ wacom_register_input(wacom); + } + } + +@@ -752,18 +1092,14 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i + struct wacom *wacom; + struct wacom_wac *wacom_wac; + struct wacom_features *features; +- struct input_dev *input_dev; + int error; + + if (!id->driver_info) + return -EINVAL; + + wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); +- input_dev = input_allocate_device(); +- if (!wacom || !input_dev) { +- error = -ENOMEM; +- goto fail1; +- } ++ if (!wacom) ++ return -ENOMEM; + + wacom_wac = &wacom->wacom_wac; + wacom_wac->features = *((struct wacom_features *)id->driver_info); +@@ -789,18 +1125,39 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i + wacom->usbdev = dev; + wacom->intf = intf; + mutex_init(&wacom->lock); ++ INIT_WORK(&wacom->work, wacom_wireless_work); + usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); + strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); + +- wacom_wac->input = input_dev; +- + endpoint = &intf->cur_altsetting->endpoint[0].desc; + +- /* Retrieve the physical and logical size for OEM devices */ ++ /* Retrieve the physical and logical size for touch devices */ + error = wacom_retrieve_hid_descriptor(intf, features); + if (error) + goto fail3; + ++ /* ++ * Intuos5 has no useful data about its touch interface in its ++ * HID descriptor. If this is the touch interface (wMaxPacketSize ++ * of WACOM_PKGLEN_BBTOUCH3), override the table values. ++ */ ++ if (features->type >= INTUOS5S && features->type <= INTUOS5L) { ++ if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) { ++ features->device_type = BTN_TOOL_FINGER; ++ features->pktlen = WACOM_PKGLEN_BBTOUCH3; ++ ++ features->x_phy = ++ (features->x_max * 100) / features->x_resolution; ++ features->y_phy = ++ (features->y_max * 100) / features->y_resolution; ++ ++ features->x_max = 4096; ++ features->y_max = 4096; ++ } else { ++ features->device_type = BTN_TOOL_PEN; ++ } ++ } ++ + wacom_setup_device_quirks(features); + + strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); +@@ -817,15 +1174,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i + goto fail3; + } + +- input_dev->name = wacom_wac->name; +- input_dev->dev.parent = &intf->dev; +- input_dev->open = wacom_open; +- input_dev->close = wacom_close; +- usb_to_input_id(dev, &input_dev->id); +- input_set_drvdata(input_dev, wacom); +- +- wacom_setup_input_capabilities(input_dev, wacom_wac); +- + usb_fill_int_urb(wacom->irq, dev, + usb_rcvintpipe(dev, endpoint->bEndpointAddress), + wacom_wac->data, features->pktlen, +@@ -837,22 +1185,34 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i + if (error) + goto fail4; + +- error = input_register_device(input_dev); ++ error = wacom_initialize_battery(wacom); + if (error) + goto fail5; + ++ if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { ++ error = wacom_register_input(wacom); ++ if (error) ++ goto fail6; ++ } ++ + /* Note that if query fails it is not a hard failure */ + wacom_query_tablet_data(intf, features); + + usb_set_intfdata(intf, wacom); ++ ++ if (features->quirks & WACOM_QUIRK_MONITOR) { ++ if (usb_submit_urb(wacom->irq, GFP_KERNEL)) ++ goto fail5; ++ } ++ + return 0; + ++ fail6: wacom_destroy_battery(wacom); + fail5: wacom_destroy_leds(wacom); + fail4: wacom_remove_shared_data(wacom_wac); + fail3: usb_free_urb(wacom->irq); + fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); +- fail1: input_free_device(input_dev); +- kfree(wacom); ++ fail1: kfree(wacom); + return error; + } + +@@ -863,7 +1223,10 @@ static void wacom_disconnect(struct usb_interface *intf) + usb_set_intfdata(intf, NULL); + + usb_kill_urb(wacom->irq); +- input_unregister_device(wacom->wacom_wac.input); ++ cancel_work_sync(&wacom->work); ++ if (wacom->wacom_wac.input) ++ input_unregister_device(wacom->wacom_wac.input); ++ wacom_destroy_battery(wacom); + wacom_destroy_leds(wacom); + usb_free_urb(wacom->irq); + usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, +@@ -895,7 +1258,8 @@ static int wacom_resume(struct usb_interface *intf) + wacom_query_tablet_data(intf, features); + wacom_led_control(wacom); + +- if (wacom->open && usb_submit_urb(wacom->irq, GFP_NOIO) < 0) ++ if ((wacom->open || features->quirks & WACOM_QUIRK_MONITOR) ++ && usb_submit_urb(wacom->irq, GFP_NOIO) < 0) + rv = -EIO; + + mutex_unlock(&wacom->lock); +diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c +index f00c70e..be3316f 100644 +--- a/drivers/input/tablet/wacom_wac.c ++++ b/drivers/input/tablet/wacom_wac.c +@@ -321,6 +321,9 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) + + /* Enter report */ + if ((data[1] & 0xfc) == 0xc0) { ++ if (features->type >= INTUOS5S && features->type <= INTUOS5L) ++ wacom->shared->stylus_in_proximity = true; ++ + /* serial number of the tool */ + wacom->serial[idx] = ((data[3] & 0x0f) << 28) + + (data[4] << 20) + (data[5] << 12) + +@@ -406,6 +409,9 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) + + /* Exit report */ + if ((data[1] & 0xfe) == 0x80) { ++ if (features->type >= INTUOS5S && features->type <= INTUOS5L) ++ wacom->shared->stylus_in_proximity = false; ++ + /* + * Reset all states otherwise we lose the initial states + * when in-prox next time +@@ -452,7 +458,8 @@ static void wacom_intuos_general(struct wacom_wac *wacom) + if ((data[1] & 0xb8) == 0xa0) { + t = (data[6] << 2) | ((data[7] >> 6) & 3); + if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || +- features->type == WACOM_21UX2) { ++ (features->type >= INTUOS5S && features->type <= INTUOS5L) || ++ features->type == WACOM_21UX2 || features->type == WACOM_24HD) { + t = (t << 1) | (data[1] & 1); + } + input_report_abs(input, ABS_PRESSURE, t); +@@ -483,7 +490,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) + int idx = 0, result; + + if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_INTUOSREAD +- && data[0] != WACOM_REPORT_INTUOSWRITE && data[0] != WACOM_REPORT_INTUOSPAD) { ++ && data[0] != WACOM_REPORT_INTUOSWRITE && data[0] != WACOM_REPORT_INTUOSPAD ++ && data[0] != WACOM_REPORT_INTUOS5PAD) { + dbg("wacom_intuos_irq: received unknown report #%d", data[0]); + return 0; + } +@@ -493,7 +501,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) + idx = data[1] & 0x01; + + /* pad packets. Works as a second tool and is always in prox */ +- if (data[0] == WACOM_REPORT_INTUOSPAD) { ++ if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) { + if (features->type >= INTUOS4S && features->type <= INTUOS4L) { + input_report_key(input, BTN_0, (data[2] & 0x01)); + input_report_key(input, BTN_1, (data[3] & 0x01)); +@@ -519,6 +527,84 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) + input_report_key(input, wacom->tool[1], 0); + input_report_abs(input, ABS_MISC, 0); + } ++ } else if (features->type == WACOM_24HD) { ++ input_report_key(input, BTN_0, (data[6] & 0x01)); ++ input_report_key(input, BTN_1, (data[6] & 0x02)); ++ input_report_key(input, BTN_2, (data[6] & 0x04)); ++ input_report_key(input, BTN_3, (data[6] & 0x08)); ++ input_report_key(input, BTN_4, (data[6] & 0x10)); ++ input_report_key(input, BTN_5, (data[6] & 0x20)); ++ input_report_key(input, BTN_6, (data[6] & 0x40)); ++ input_report_key(input, BTN_7, (data[6] & 0x80)); ++ input_report_key(input, BTN_8, (data[8] & 0x01)); ++ input_report_key(input, BTN_9, (data[8] & 0x02)); ++ input_report_key(input, BTN_A, (data[8] & 0x04)); ++ input_report_key(input, BTN_B, (data[8] & 0x08)); ++ input_report_key(input, BTN_C, (data[8] & 0x10)); ++ input_report_key(input, BTN_X, (data[8] & 0x20)); ++ input_report_key(input, BTN_Y, (data[8] & 0x40)); ++ input_report_key(input, BTN_Z, (data[8] & 0x80)); ++ ++ /* ++ * Three "buttons" are available on the 24HD which are ++ * physically implemented as a touchstrip. Each button ++ * is approximately 3 bits wide with a 2 bit spacing. ++ * The raw touchstrip bits are stored at: ++ * ((data[3] & 0x1f) << 8) | data[4]) ++ */ ++ input_report_key(input, KEY_PROG1, data[4] & 0x07); ++ input_report_key(input, KEY_PROG2, data[4] & 0xE0); ++ input_report_key(input, KEY_PROG3, data[3] & 0x1C); ++ ++ if (data[1] & 0x80) { ++ input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f)); ++ } else { ++ /* Out of proximity, clear wheel value. */ ++ input_report_abs(input, ABS_WHEEL, 0); ++ } ++ ++ if (data[2] & 0x80) { ++ input_report_abs(input, ABS_THROTTLE, (data[2] & 0x7f)); ++ } else { ++ /* Out of proximity, clear second wheel value. */ ++ input_report_abs(input, ABS_THROTTLE, 0); ++ } ++ ++ if (data[1] | data[2] | (data[3] & 0x1f) | data[4] | data[6] | data[8]) { ++ input_report_key(input, wacom->tool[1], 1); ++ input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); ++ } else { ++ input_report_key(input, wacom->tool[1], 0); ++ input_report_abs(input, ABS_MISC, 0); ++ } ++ } else if (features->type >= INTUOS5S && features->type <= INTUOS5L) { ++ int i; ++ ++ /* Touch ring mode switch has no capacitive sensor */ ++ input_report_key(input, BTN_0, (data[3] & 0x01)); ++ ++ /* ++ * ExpressKeys on Intuos5 have a capacitive sensor in ++ * addition to the mechanical switch. Switch data is ++ * stored in data[4], capacitive data in data[5]. ++ */ ++ for (i = 0; i < 8; i++) ++ input_report_key(input, BTN_1 + i, data[4] & (1 << i)); ++ ++ if (data[2] & 0x80) { ++ input_report_abs(input, ABS_WHEEL, (data[2] & 0x7f)); ++ } else { ++ /* Out of proximity, clear wheel value. */ ++ input_report_abs(input, ABS_WHEEL, 0); ++ } ++ ++ if (data[2] | (data[3] & 0x01) | data[4]) { ++ input_report_key(input, wacom->tool[1], 1); ++ input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); ++ } else { ++ input_report_key(input, wacom->tool[1], 0); ++ input_report_abs(input, ABS_MISC, 0); ++ } + } else { + if (features->type == WACOM_21UX2) { + input_report_key(input, BTN_0, (data[5] & 0x01)); +@@ -582,7 +668,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) + (features->type == INTUOS3 || + features->type == INTUOS3S || + features->type == INTUOS4 || +- features->type == INTUOS4S)) { ++ features->type == INTUOS4S || ++ features->type == INTUOS5 || ++ features->type == INTUOS5S)) { + + return 0; + } +@@ -635,7 +723,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) + + } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { + /* I4 mouse */ +- if (features->type >= INTUOS4S && features->type <= INTUOS4L) { ++ if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || ++ (features->type >= INTUOS5S && features->type <= INTUOS5L)) { + input_report_key(input, BTN_LEFT, data[6] & 0x01); + input_report_key(input, BTN_MIDDLE, data[6] & 0x02); + input_report_key(input, BTN_RIGHT, data[6] & 0x04); +@@ -662,7 +751,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) + } + } + } else if ((features->type < INTUOS3S || features->type == INTUOS3L || +- features->type == INTUOS4L) && ++ features->type == INTUOS4L || features->type == INTUOS5L) && + wacom->tool[idx] == BTN_TOOL_LENS) { + /* Lens cursor packets */ + input_report_key(input, BTN_LEFT, data[8] & 0x01); +@@ -679,6 +768,72 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) + return 1; + } + ++static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid) ++{ ++ int touch_max = wacom->features.touch_max; ++ int i; ++ ++ if (!wacom->slots) ++ return -1; ++ ++ for (i = 0; i < touch_max; ++i) { ++ if (wacom->slots[i] == contactid) ++ return i; ++ } ++ for (i = 0; i < touch_max; ++i) { ++ if (wacom->slots[i] == -1) ++ return i; ++ } ++ return -1; ++} ++ ++static int wacom_mt_touch(struct wacom_wac *wacom) ++{ ++ struct input_dev *input = wacom->input; ++ char *data = wacom->data; ++ int i; ++ int current_num_contacts = data[2]; ++ int contacts_to_send = 0; ++ ++ /* ++ * First packet resets the counter since only the first ++ * packet in series will have non-zero current_num_contacts. ++ */ ++ if (current_num_contacts) ++ wacom->num_contacts_left = current_num_contacts; ++ ++ /* There are at most 5 contacts per packet */ ++ contacts_to_send = min(5, wacom->num_contacts_left); ++ ++ for (i = 0; i < contacts_to_send; i++) { ++ int offset = (WACOM_BYTES_PER_MT_PACKET * i) + 3; ++ bool touch = data[offset] & 0x1; ++ int id = le16_to_cpup((__le16 *)&data[offset + 1]); ++ int slot = find_slot_from_contactid(wacom, id); ++ ++ if (slot < 0) ++ continue; ++ ++ input_mt_slot(input, slot); ++ input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); ++ if (touch) { ++ int x = le16_to_cpup((__le16 *)&data[offset + 7]); ++ int y = le16_to_cpup((__le16 *)&data[offset + 9]); ++ input_report_abs(input, ABS_MT_POSITION_X, x); ++ input_report_abs(input, ABS_MT_POSITION_Y, y); ++ } ++ wacom->slots[slot] = touch ? id : -1; ++ } ++ ++ input_mt_report_pointer_emulation(input, true); ++ ++ wacom->num_contacts_left -= contacts_to_send; ++ if (wacom->num_contacts_left < 0) ++ wacom->num_contacts_left = 0; ++ ++ return 1; ++} ++ + static int wacom_tpc_mt_touch(struct wacom_wac *wacom) + { + struct input_dev *input = wacom->input; +@@ -717,6 +872,9 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) + bool prox; + int x = 0, y = 0; + ++ if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG) ++ return 0; ++ + if (!wacom->shared->stylus_in_proximity) { + if (len == WACOM_PKGLEN_TPC1FG) { + prox = data[0] & 0x01; +@@ -782,12 +940,27 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) + + dbg("wacom_tpc_irq: received report #%d", data[0]); + +- if (len == WACOM_PKGLEN_TPC1FG || data[0] == WACOM_REPORT_TPC1FG) ++ switch (len) { ++ case WACOM_PKGLEN_TPC1FG: + return wacom_tpc_single_touch(wacom, len); +- else if (data[0] == WACOM_REPORT_TPC2FG) ++ ++ case WACOM_PKGLEN_TPC2FG: + return wacom_tpc_mt_touch(wacom); +- else if (data[0] == WACOM_REPORT_PENABLED) +- return wacom_tpc_pen(wacom); ++ ++ default: ++ switch (data[0]) { ++ case WACOM_REPORT_TPC1FG: ++ case WACOM_REPORT_TPCHID: ++ case WACOM_REPORT_TPCST: ++ return wacom_tpc_single_touch(wacom, len); ++ ++ case WACOM_REPORT_TPCMT: ++ return wacom_mt_touch(wacom); ++ ++ case WACOM_REPORT_PENABLED: ++ return wacom_tpc_pen(wacom); ++ } ++ } + + return 0; + } +@@ -799,6 +972,9 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) + unsigned char *data = wacom->data; + int i; + ++ if (data[0] != 0x02) ++ return 0; ++ + for (i = 0; i < 2; i++) { + int offset = (data[1] & 0x80) ? (8 * i) : (9 * i); + bool touch = data[offset + 3] & 0x80; +@@ -837,12 +1013,76 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) + return 0; + } + ++static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) ++{ ++ struct input_dev *input = wacom->input; ++ int slot_id = data[0] - 2; /* data[0] is between 2 and 17 */ ++ bool touch = data[1] & 0x80; ++ ++ touch = touch && !wacom->shared->stylus_in_proximity; ++ ++ input_mt_slot(input, slot_id); ++ input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); ++ ++ if (touch) { ++ int x = (data[2] << 4) | (data[4] >> 4); ++ int y = (data[3] << 4) | (data[4] & 0x0f); ++ int w = data[6]; ++ ++ input_report_abs(input, ABS_MT_POSITION_X, x); ++ input_report_abs(input, ABS_MT_POSITION_Y, y); ++ input_report_abs(input, ABS_MT_TOUCH_MAJOR, w); ++ } ++} ++ ++static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data) ++{ ++ struct input_dev *input = wacom->input; ++ ++ input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); ++ input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0); ++ input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0); ++ input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0); ++} ++ ++static int wacom_bpt3_touch(struct wacom_wac *wacom) ++{ ++ struct input_dev *input = wacom->input; ++ unsigned char *data = wacom->data; ++ int count = data[1] & 0x07; ++ int i; ++ ++ if (data[0] != 0x02) ++ return 0; ++ ++ /* data has up to 7 fixed sized 8-byte messages starting at data[2] */ ++ for (i = 0; i < count; i++) { ++ int offset = (8 * i) + 2; ++ int msg_id = data[offset]; ++ ++ if (msg_id >= 2 && msg_id <= 17) ++ wacom_bpt3_touch_msg(wacom, data + offset); ++ else if (msg_id == 128) ++ wacom_bpt3_button_msg(wacom, data + offset); ++ ++ } ++ ++ input_mt_report_pointer_emulation(input, true); ++ ++ input_sync(input); ++ ++ return 0; ++} ++ + static int wacom_bpt_pen(struct wacom_wac *wacom) + { + struct input_dev *input = wacom->input; + unsigned char *data = wacom->data; + int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0; + ++ if (data[0] != 0x02) ++ return 0; ++ + prox = (data[1] & 0x20) == 0x20; + + /* +@@ -907,12 +1147,43 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len) + { + if (len == WACOM_PKGLEN_BBTOUCH) + return wacom_bpt_touch(wacom); +- else if (len == WACOM_PKGLEN_BBFUN) ++ else if (len == WACOM_PKGLEN_BBTOUCH3) ++ return wacom_bpt3_touch(wacom); ++ else if (len == WACOM_PKGLEN_BBFUN || len == WACOM_PKGLEN_BBPEN) + return wacom_bpt_pen(wacom); + + return 0; + } + ++static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) ++{ ++ unsigned char *data = wacom->data; ++ int connected; ++ ++ if (len != WACOM_PKGLEN_WIRELESS || data[0] != 0x80) ++ return 0; ++ ++ connected = data[1] & 0x01; ++ if (connected) { ++ int pid, battery; ++ ++ pid = get_unaligned_be16(&data[6]); ++ battery = data[5] & 0x3f; ++ if (wacom->pid != pid) { ++ wacom->pid = pid; ++ wacom_schedule_work(wacom); ++ } ++ wacom->battery_capacity = battery; ++ } else if (wacom->pid != 0) { ++ /* disconnected while previously connected */ ++ wacom->pid = 0; ++ wacom_schedule_work(wacom); ++ wacom->battery_capacity = 0; ++ } ++ ++ return 0; ++} ++ + void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) + { + bool sync; +@@ -950,11 +1221,22 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) + case CINTIQ: + case WACOM_BEE: + case WACOM_21UX2: ++ case WACOM_24HD: + sync = wacom_intuos_irq(wacom_wac); + break; + ++ case INTUOS5S: ++ case INTUOS5: ++ case INTUOS5L: ++ if (len == WACOM_PKGLEN_BBTOUCH3) ++ sync = wacom_bpt3_touch(wacom_wac); ++ else ++ sync = wacom_intuos_irq(wacom_wac); ++ break; ++ + case TABLETPC: + case TABLETPC2FG: ++ case MTSCREEN: + sync = wacom_tpc_irq(wacom_wac, len); + break; + +@@ -962,6 +1244,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) + sync = wacom_bpt_irq(wacom_wac, len); + break; + ++ case WIRELESS: ++ sync = wacom_wireless_irq(wacom_wac, len); ++ break; ++ + default: + sync = false; + break; +@@ -1023,18 +1309,30 @@ void wacom_setup_device_quirks(struct wacom_features *features) + + /* these device have multiple inputs */ + if (features->type == TABLETPC || features->type == TABLETPC2FG || +- features->type == BAMBOO_PT) ++ features->type == BAMBOO_PT || features->type == WIRELESS || ++ (features->type >= INTUOS5S && features->type <= INTUOS5L) || ++ features->type == MTSCREEN) + features->quirks |= WACOM_QUIRK_MULTI_INPUT; + +- /* quirks for bamboo touch */ ++ /* quirk for bamboo touch with 2 low res touches */ + if (features->type == BAMBOO_PT && +- features->device_type == BTN_TOOL_DOUBLETAP) { ++ features->pktlen == WACOM_PKGLEN_BBTOUCH) { + features->x_max <<= 5; + features->y_max <<= 5; + features->x_fuzz <<= 5; + features->y_fuzz <<= 5; + features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES; + } ++ ++ if (features->type == WIRELESS) { ++ ++ /* monitor never has input and pen/touch have delayed create */ ++ features->quirks |= WACOM_QUIRK_NO_INPUT; ++ ++ /* must be monitor interface if no device_type set */ ++ if (!features->device_type) ++ features->quirks |= WACOM_QUIRK_MONITOR; ++ } + } + + static unsigned int wacom_calculate_touch_res(unsigned int logical_max, +@@ -1044,8 +1342,8 @@ static unsigned int wacom_calculate_touch_res(unsigned int logical_max, + return (logical_max * 100) / physical_max; + } + +-void wacom_setup_input_capabilities(struct input_dev *input_dev, +- struct wacom_wac *wacom_wac) ++int wacom_setup_input_capabilities(struct input_dev *input_dev, ++ struct wacom_wac *wacom_wac) + { + struct wacom_features *features = &wacom_wac->features; + int i; +@@ -1105,6 +1403,26 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); + break; + ++ case WACOM_24HD: ++ __set_bit(BTN_A, input_dev->keybit); ++ __set_bit(BTN_B, input_dev->keybit); ++ __set_bit(BTN_C, input_dev->keybit); ++ __set_bit(BTN_X, input_dev->keybit); ++ __set_bit(BTN_Y, input_dev->keybit); ++ __set_bit(BTN_Z, input_dev->keybit); ++ ++ for (i = 0; i < 10; i++) ++ __set_bit(BTN_0 + i, input_dev->keybit); ++ ++ __set_bit(KEY_PROG1, input_dev->keybit); ++ __set_bit(KEY_PROG2, input_dev->keybit); ++ __set_bit(KEY_PROG3, input_dev->keybit); ++ ++ input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); ++ input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); ++ wacom_setup_cintiq(wacom_wac); ++ break; ++ + case WACOM_21UX2: + __set_bit(BTN_A, input_dev->keybit); + __set_bit(BTN_B, input_dev->keybit); +@@ -1160,6 +1478,50 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, + wacom_setup_intuos(wacom_wac); + break; + ++ case INTUOS5: ++ case INTUOS5L: ++ if (features->device_type == BTN_TOOL_PEN) { ++ __set_bit(BTN_7, input_dev->keybit); ++ __set_bit(BTN_8, input_dev->keybit); ++ } ++ /* fall through */ ++ ++ case INTUOS5S: ++ __set_bit(INPUT_PROP_POINTER, input_dev->propbit); ++ ++ if (features->device_type == BTN_TOOL_PEN) { ++ for (i = 0; i < 7; i++) ++ __set_bit(BTN_0 + i, input_dev->keybit); ++ ++ input_set_abs_params(input_dev, ABS_DISTANCE, 0, ++ features->distance_max, ++ 0, 0); ++ ++ input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); ++ ++ wacom_setup_intuos(wacom_wac); ++ } else if (features->device_type == BTN_TOOL_FINGER) { ++ __clear_bit(ABS_MISC, input_dev->absbit); ++ ++ __set_bit(BTN_TOOL_FINGER, input_dev->keybit); ++ __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); ++ __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); ++ __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); ++ ++ input_mt_init_slots(input_dev, features->touch_max); ++ ++ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, ++ 0, 255, 0, 0); ++ ++ input_set_abs_params(input_dev, ABS_MT_POSITION_X, ++ 0, features->x_max, ++ features->x_fuzz, 0); ++ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, ++ 0, features->y_max, ++ features->y_fuzz, 0); ++ } ++ break; ++ + case INTUOS4: + case INTUOS4L: + __set_bit(BTN_7, input_dev->keybit); +@@ -1176,10 +1538,24 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); + break; + ++ case MTSCREEN: ++ if (features->device_type == BTN_TOOL_FINGER) { ++ ++ wacom_wac->slots = kmalloc(features->touch_max * ++ sizeof(int), ++ GFP_KERNEL); ++ if (!wacom_wac->slots) ++ return -ENOMEM; ++ ++ for (i = 0; i < features->touch_max; i++) ++ wacom_wac->slots[i] = -1; ++ } ++ /* fall through */ ++ + case TABLETPC2FG: +- if (features->device_type == BTN_TOOL_DOUBLETAP) { ++ if (features->device_type == BTN_TOOL_FINGER) { + +- input_mt_init_slots(input_dev, 2); ++ input_mt_init_slots(input_dev, features->touch_max); + input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, + 0, MT_TOOL_MAX, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_X, +@@ -1226,7 +1602,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, + + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); + +- if (features->device_type == BTN_TOOL_DOUBLETAP) { ++ if (features->device_type == BTN_TOOL_FINGER) { + __set_bit(BTN_LEFT, input_dev->keybit); + __set_bit(BTN_FORWARD, input_dev->keybit); + __set_bit(BTN_BACK, input_dev->keybit); +@@ -1234,8 +1610,19 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, + + __set_bit(BTN_TOOL_FINGER, input_dev->keybit); + __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); ++ input_mt_init_slots(input_dev, features->touch_max); ++ ++ if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { ++ __set_bit(BTN_TOOL_TRIPLETAP, ++ input_dev->keybit); ++ __set_bit(BTN_TOOL_QUADTAP, ++ input_dev->keybit); ++ ++ input_set_abs_params(input_dev, ++ ABS_MT_TOUCH_MAJOR, ++ 0, 255, 0, 0); ++ } + +- input_mt_init_slots(input_dev, 2); + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + 0, features->x_max, + features->x_fuzz, 0); +@@ -1253,6 +1640,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, + } + break; + } ++ return 0; + } + + static const struct wacom_features wacom_features_0x00 = +@@ -1420,6 +1808,27 @@ static const struct wacom_features wacom_features_0xBB = + static const struct wacom_features wacom_features_0xBC = + { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 25400, 2047, + 63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; ++static const struct wacom_features wacom_features_0x26 = ++ { "Wacom Intuos5 touch S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, ++ 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, ++ .touch_max = 16 }; ++static const struct wacom_features wacom_features_0x27 = ++ { "Wacom Intuos5 touch M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, ++ 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, ++ .touch_max = 16 }; ++static const struct wacom_features wacom_features_0x28 = ++ { "Wacom Intuos5 touch L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, ++ 63, INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, ++ .touch_max = 16 }; ++static const struct wacom_features wacom_features_0x29 = ++ { "Wacom Intuos5 S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, ++ 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; ++static const struct wacom_features wacom_features_0x2A = ++ { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, ++ 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; ++static const struct wacom_features wacom_features_0xF4 = ++ { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, ++ 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + static const struct wacom_features wacom_features_0x3F = + { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, + 63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; +@@ -1458,31 +1867,44 @@ static const struct wacom_features wacom_features_0x9F = + 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + static const struct wacom_features wacom_features_0xE2 = + { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, +- 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++ 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 2 }; + static const struct wacom_features wacom_features_0xE3 = + { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, +- 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++ 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 2 }; ++static const struct wacom_features wacom_features_0xE5 = ++ { "Wacom ISDv4 E5", WACOM_PKGLEN_MTOUCH, 26202, 16325, 255, ++ 0, MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + static const struct wacom_features wacom_features_0xE6 = + { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255, +- 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++ 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 2 }; + static const struct wacom_features wacom_features_0xEC = + { "Wacom ISDv4 EC", WACOM_PKGLEN_GRAPHIRE, 25710, 14500, 255, + 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + static const struct wacom_features wacom_features_0x47 = + { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, + 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++static const struct wacom_features wacom_features_0x84 = ++ { "Wacom Wireless Receiver", WACOM_PKGLEN_WIRELESS, 0, 0, 0, ++ 0, WIRELESS, 0, 0, .touch_max = 16 }; + static const struct wacom_features wacom_features_0xD0 = + { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, +- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 2 }; + static const struct wacom_features wacom_features_0xD1 = + { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, +- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 2 }; + static const struct wacom_features wacom_features_0xD2 = + { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, +- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 2 }; + static const struct wacom_features wacom_features_0xD3 = + { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, +- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 2 }; + static const struct wacom_features wacom_features_0xD4 = + { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, + 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +@@ -1491,19 +1913,35 @@ static const struct wacom_features wacom_features_0xD5 = + 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + static const struct wacom_features wacom_features_0xD6 = + { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, +- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 2 }; + static const struct wacom_features wacom_features_0xD7 = + { "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, +- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 2 }; + static const struct wacom_features wacom_features_0xD8 = + { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, +- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 2 }; + static const struct wacom_features wacom_features_0xDA = + { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, +- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 2 }; + static struct wacom_features wacom_features_0xDB = + { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, +- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 2 }; ++static const struct wacom_features wacom_features_0xDD = ++ { "Wacom Bamboo Connect", WACOM_PKGLEN_BBPEN, 14720, 9200, 1023, ++ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; ++static const struct wacom_features wacom_features_0xDE = ++ { "Wacom Bamboo 16FG 4x5", WACOM_PKGLEN_BBPEN, 14720, 9200, 1023, ++ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 16 }; ++static const struct wacom_features wacom_features_0xDF = ++ { "Wacom Bamboo 16FG 6x8", WACOM_PKGLEN_BBPEN, 21648, 13700, 1023, ++ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, ++ .touch_max = 16 }; + static const struct wacom_features wacom_features_0x6004 = + { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, + 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +@@ -1577,6 +2015,11 @@ const struct usb_device_id wacom_ids[] = { + { USB_DEVICE_WACOM(0xBA) }, + { USB_DEVICE_WACOM(0xBB) }, + { USB_DEVICE_WACOM(0xBC) }, ++ { USB_DEVICE_WACOM(0x26) }, ++ { USB_DEVICE_WACOM(0x27) }, ++ { USB_DEVICE_WACOM(0x28) }, ++ { USB_DEVICE_WACOM(0x29) }, ++ { USB_DEVICE_WACOM(0x2A) }, + { USB_DEVICE_WACOM(0x3F) }, + { USB_DEVICE_WACOM(0xC5) }, + { USB_DEVICE_WACOM(0xC6) }, +@@ -1588,6 +2031,7 @@ const struct usb_device_id wacom_ids[] = { + { USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID, + USB_INTERFACE_SUBCLASS_BOOT, + USB_INTERFACE_PROTOCOL_MOUSE) }, ++ { USB_DEVICE_WACOM(0x84) }, + { USB_DEVICE_WACOM(0xD0) }, + { USB_DEVICE_WACOM(0xD1) }, + { USB_DEVICE_WACOM(0xD2) }, +@@ -1599,6 +2043,9 @@ const struct usb_device_id wacom_ids[] = { + { USB_DEVICE_WACOM(0xD8) }, + { USB_DEVICE_WACOM(0xDA) }, + { USB_DEVICE_WACOM(0xDB) }, ++ { USB_DEVICE_WACOM(0xDD) }, ++ { USB_DEVICE_WACOM(0xDE) }, ++ { USB_DEVICE_WACOM(0xDF) }, + { USB_DEVICE_WACOM(0xF0) }, + { USB_DEVICE_WACOM(0xCC) }, + { USB_DEVICE_WACOM(0x90) }, +@@ -1608,9 +2055,11 @@ const struct usb_device_id wacom_ids[] = { + { USB_DEVICE_WACOM(0x9F) }, + { USB_DEVICE_WACOM(0xE2) }, + { USB_DEVICE_WACOM(0xE3) }, ++ { USB_DEVICE_WACOM(0xE5) }, + { USB_DEVICE_WACOM(0xE6) }, + { USB_DEVICE_WACOM(0xEC) }, + { USB_DEVICE_WACOM(0x47) }, ++ { USB_DEVICE_WACOM(0xF4) }, + { USB_DEVICE_LENOVO(0x6004) }, + { } + }; +diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h +index 53eb71b..78fbd3f 100644 +--- a/drivers/input/tablet/wacom_wac.h ++++ b/drivers/input/tablet/wacom_wac.h +@@ -12,7 +12,7 @@ + #include + + /* maximum packet length for USB devices */ +-#define WACOM_PKGLEN_MAX 32 ++#define WACOM_PKGLEN_MAX 64 + + /* packet length for individual models */ + #define WACOM_PKGLEN_PENPRTN 7 +@@ -22,6 +22,13 @@ + #define WACOM_PKGLEN_TPC1FG 5 + #define WACOM_PKGLEN_TPC2FG 14 + #define WACOM_PKGLEN_BBTOUCH 20 ++#define WACOM_PKGLEN_BBTOUCH3 64 ++#define WACOM_PKGLEN_BBPEN 10 ++#define WACOM_PKGLEN_WIRELESS 32 ++#define WACOM_PKGLEN_MTOUCH 62 ++ ++/* wacom data size per MT contact */ ++#define WACOM_BYTES_PER_MT_PACKET 11 + + /* device IDs */ + #define STYLUS_DEVICE_ID 0x02 +@@ -35,12 +42,18 @@ + #define WACOM_REPORT_INTUOSREAD 5 + #define WACOM_REPORT_INTUOSWRITE 6 + #define WACOM_REPORT_INTUOSPAD 12 ++#define WACOM_REPORT_INTUOS5PAD 3 + #define WACOM_REPORT_TPC1FG 6 + #define WACOM_REPORT_TPC2FG 13 ++#define WACOM_REPORT_TPCMT 13 ++#define WACOM_REPORT_TPCHID 15 ++#define WACOM_REPORT_TPCST 16 + + /* device quirks */ + #define WACOM_QUIRK_MULTI_INPUT 0x0001 + #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002 ++#define WACOM_QUIRK_NO_INPUT 0x0004 ++#define WACOM_QUIRK_MONITOR 0x0008 + + enum { + PENPARTNER = 0, +@@ -50,6 +63,7 @@ enum { + PL, + DTU, + BAMBOO_PT, ++ WIRELESS, + INTUOS, + INTUOS3S, + INTUOS3, +@@ -57,12 +71,17 @@ enum { + INTUOS4S, + INTUOS4, + INTUOS4L, ++ INTUOS5S, ++ INTUOS5, ++ INTUOS5L, ++ WACOM_24HD, + WACOM_21UX2, + CINTIQ, + WACOM_BEE, + WACOM_MO, + TABLETPC, + TABLETPC2FG, ++ MTSCREEN, + MAX_TYPE + }; + +@@ -86,6 +105,7 @@ struct wacom_features { + int pressure_fuzz; + int distance_fuzz; + unsigned quirks; ++ unsigned touch_max; + }; + + struct wacom_shared { +@@ -102,6 +122,10 @@ struct wacom_wac { + struct wacom_features features; + struct wacom_shared *shared; + struct input_dev *input; ++ int pid; ++ int battery_capacity; ++ int num_contacts_left; ++ int *slots; + }; + + #endif +diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c +index a596c27..d84de37 100644 +--- a/drivers/input/touchscreen/atmel_mxt_ts.c ++++ b/drivers/input/touchscreen/atmel_mxt_ts.c +@@ -954,10 +954,8 @@ static int mxt_load_fw(struct device *dev, const char *fn) + int ret; + + ret = request_firmware(&fw, fn, dev); +- if (ret) { +- dev_err(dev, "Unable to open firmware %s\n", fn); ++ if (ret) + return ret; +- } + + /* Change to the bootloader mode */ + mxt_write_object(data, MXT_GEN_COMMAND_T6, +diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c +index 4d0d41e..ad7db7d 100644 +--- a/drivers/isdn/hardware/mISDN/speedfax.c ++++ b/drivers/isdn/hardware/mISDN/speedfax.c +@@ -389,11 +389,8 @@ setup_instance(struct sfax_hw *card) + card->isar.owner = THIS_MODULE; + + err = request_firmware(&firmware, "isdn/ISAR.BIN", &card->pdev->dev); +- if (err < 0) { +- pr_info("%s: firmware request failed %d\n", +- card->name, err); ++ if (err) + goto error_fw; +- } + if (debug & DEBUG_HW) + pr_notice("%s: got firmware %zu bytes\n", + card->name, firmware->size); +diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c +index 4878d91..501d139 100644 +--- a/drivers/md/dm-crypt.c ++++ b/drivers/md/dm-crypt.c +@@ -1737,7 +1737,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, + return DM_MAPIO_SUBMITTED; + } + +-static void crypt_status(struct dm_target *ti, status_type_t type, ++static int crypt_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) + { + struct crypt_config *cc = ti->private; +@@ -1765,6 +1765,7 @@ static void crypt_status(struct dm_target *ti, status_type_t type, + + break; + } ++ return 0; + } + + static void crypt_postsuspend(struct dm_target *ti) +diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c +index 3f123f1..9237003 100644 +--- a/drivers/md/dm-delay.c ++++ b/drivers/md/dm-delay.c +@@ -301,7 +301,7 @@ static int delay_map(struct dm_target *ti, struct bio *bio, + return delay_bio(dc, dc->read_delay, bio); + } + +-static void delay_status(struct dm_target *ti, status_type_t type, ++static int delay_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) + { + struct delay_c *dc = ti->private; +@@ -322,6 +322,8 @@ static void delay_status(struct dm_target *ti, status_type_t type, + dc->write_delay); + break; + } ++ ++ return 0; + } + + static int delay_iterate_devices(struct dm_target *ti, +diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c +index 746b5e8..5dd8e9c 100644 +--- a/drivers/md/dm-flakey.c ++++ b/drivers/md/dm-flakey.c +@@ -331,7 +331,7 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, + return error; + } + +-static void flakey_status(struct dm_target *ti, status_type_t type, ++static int flakey_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) + { + unsigned sz = 0; +@@ -362,6 +362,7 @@ static void flakey_status(struct dm_target *ti, status_type_t type, + + break; + } ++ return 0; + } + + static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) +diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c +index c55d8e4..827e575 100644 +--- a/drivers/md/dm-linear.c ++++ b/drivers/md/dm-linear.c +@@ -94,7 +94,7 @@ static int linear_map(struct dm_target *ti, struct bio *bio, + return DM_MAPIO_REMAPPED; + } + +-static void linear_status(struct dm_target *ti, status_type_t type, ++static int linear_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) + { + struct linear_c *lc = (struct linear_c *) ti->private; +@@ -109,6 +109,7 @@ static void linear_status(struct dm_target *ti, status_type_t type, + (unsigned long long)lc->start); + break; + } ++ return 0; + } + + static int linear_ioctl(struct dm_target *ti, unsigned int cmd, +diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c +index 84ad530..d989d67 100644 +--- a/drivers/md/dm-mpath.c ++++ b/drivers/md/dm-mpath.c +@@ -1335,7 +1335,7 @@ static void multipath_resume(struct dm_target *ti) + * [priority selector-name num_ps_args [ps_args]* + * num_paths num_selector_args [path_dev [selector_args]* ]+ ]+ + */ +-static void multipath_status(struct dm_target *ti, status_type_t type, ++static int multipath_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) + { + int sz = 0; +@@ -1439,6 +1439,8 @@ static void multipath_status(struct dm_target *ti, status_type_t type, + } + + spin_unlock_irqrestore(&m->lock, flags); ++ ++ return 0; + } + + static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) +diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c +index 8158f63..f98ea5d 100644 +--- a/drivers/md/dm-raid.c ++++ b/drivers/md/dm-raid.c +@@ -1020,7 +1020,7 @@ static int raid_map(struct dm_target *ti, struct bio *bio, union map_info *map_c + return DM_MAPIO_SUBMITTED; + } + +-static void raid_status(struct dm_target *ti, status_type_t type, ++static int raid_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) + { + struct raid_set *rs = ti->private; +@@ -1156,6 +1156,8 @@ static void raid_status(struct dm_target *ti, status_type_t type, + DMEMIT(" -"); + } + } ++ ++ return 0; + } + + static int raid_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) +diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c +index b4361eb..8d4200c 100644 +--- a/drivers/md/dm-raid1.c ++++ b/drivers/md/dm-raid1.c +@@ -1367,7 +1367,7 @@ static char device_status_char(struct mirror *m) + } + + +-static void mirror_status(struct dm_target *ti, status_type_t type, ++static int mirror_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) + { + unsigned int m, sz = 0; +@@ -1403,6 +1403,8 @@ static void mirror_status(struct dm_target *ti, status_type_t type, + if (ms->features & DM_RAID1_HANDLE_ERRORS) + DMEMIT(" 1 handle_errors"); + } ++ ++ return 0; + } + + static int mirror_iterate_devices(struct dm_target *ti, +diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c +index 6b94c3c..6a6c91e 100644 +--- a/drivers/md/dm-snap.c ++++ b/drivers/md/dm-snap.c +@@ -1902,7 +1902,7 @@ static void snapshot_merge_resume(struct dm_target *ti) + start_merge(s); + } + +-static void snapshot_status(struct dm_target *ti, status_type_t type, ++static int snapshot_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) + { + unsigned sz = 0; +@@ -1949,6 +1949,8 @@ static void snapshot_status(struct dm_target *ti, status_type_t type, + maxlen - sz); + break; + } ++ ++ return 0; + } + + static int snapshot_iterate_devices(struct dm_target *ti, +@@ -2203,7 +2205,7 @@ static void origin_resume(struct dm_target *ti) + ti->split_io = get_origin_minimum_chunksize(dev->bdev); + } + +-static void origin_status(struct dm_target *ti, status_type_t type, ++static int origin_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) + { + struct dm_dev *dev = ti->private; +@@ -2217,6 +2219,8 @@ static void origin_status(struct dm_target *ti, status_type_t type, + snprintf(result, maxlen, "%s", dev->name); + break; + } ++ ++ return 0; + } + + static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm, +diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c +index cbd41d2..e30a5cd 100644 +--- a/drivers/md/dm-stripe.c ++++ b/drivers/md/dm-stripe.c +@@ -301,7 +301,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio, + * + */ + +-static void stripe_status(struct dm_target *ti, status_type_t type, ++static int stripe_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) + { + struct stripe_c *sc = (struct stripe_c *) ti->private; +@@ -329,6 +329,7 @@ static void stripe_status(struct dm_target *ti, status_type_t type, + (unsigned long long)sc->stripe[i].physical_start); + break; + } ++ return 0; + } + + static int stripe_end_io(struct dm_target *ti, struct bio *bio, +diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c +index 5c52582..bf7299f 100644 +--- a/drivers/md/dm-table.c ++++ b/drivers/md/dm-table.c +@@ -543,13 +543,15 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev, + (unsigned long long) start << SECTOR_SHIFT); + + /* +- * Check if merge fn is supported. +- * If not we'll force DM to use PAGE_SIZE or +- * smaller I/O, just to be safe. ++ * If we don't call merge_bvec_fn, we must never risk ++ * violating it, so limit max_phys_segments to 1 lying within ++ * a single page. + */ +- if (dm_queue_merge_is_compulsory(q) && !ti->type->merge) +- blk_limits_max_hw_sectors(limits, +- (unsigned int) (PAGE_SIZE >> 9)); ++ if (dm_queue_merge_is_compulsory(q) && !ti->type->merge) { ++ limits->max_segments = 1; ++ limits->seg_boundary_mask = PAGE_CACHE_SIZE - 1; ++ } ++ + return 0; + } + EXPORT_SYMBOL_GPL(dm_set_device_limits); +diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c +index d9f23a4..7f4649f 100644 +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -2096,7 +2096,7 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv) + * / + * / + */ +-static void pool_status(struct dm_target *ti, status_type_t type, ++static int pool_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) + { + int r; +@@ -2177,10 +2177,11 @@ static void pool_status(struct dm_target *ti, status_type_t type, + DMEMIT("skip_block_zeroing "); + break; + } +- return; ++ return 0; + + err: + DMEMIT("Error"); ++ return 0; + } + + static int pool_iterate_devices(struct dm_target *ti, +@@ -2356,7 +2357,7 @@ static void thin_postsuspend(struct dm_target *ti) + /* + * + */ +-static void thin_status(struct dm_target *ti, status_type_t type, ++static int thin_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) + { + int r; +@@ -2398,10 +2399,11 @@ static void thin_status(struct dm_target *ti, status_type_t type, + } + } + +- return; ++ return 0; + + err: + DMEMIT("Error"); ++ return 0; + } + + static int thin_iterate_devices(struct dm_target *ti, +diff --git a/drivers/md/md.c b/drivers/md/md.c +index ea8a181..d7e9242 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -5384,9 +5384,9 @@ static int get_bitmap_file(struct mddev * mddev, void __user * arg) + int err = -ENOMEM; + + if (md_allow_write(mddev)) +- file = kmalloc(sizeof(*file), GFP_NOIO); ++ file = kzalloc(sizeof(*file), GFP_NOIO); + else +- file = kmalloc(sizeof(*file), GFP_KERNEL); ++ file = kzalloc(sizeof(*file), GFP_KERNEL); + + if (!file) + goto out; +diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c +index 3acbaa0..6c18194 100644 +--- a/drivers/media/common/tuners/tuner-xc2028.c ++++ b/drivers/media/common/tuners/tuner-xc2028.c +@@ -278,16 +278,8 @@ static int load_all_firmwares(struct dvb_frontend *fe) + + tuner_dbg("Reading firmware %s\n", fname); + rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent); +- if (rc < 0) { +- if (rc == -ENOENT) +- tuner_err("Error: firmware %s not found.\n", +- fname); +- else +- tuner_err("Error %d while requesting firmware %s \n", +- rc, fname); +- ++ if (rc) + return rc; +- } + p = fw->data; + endp = p + fw->size; + +diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig +index 5825716..fd60900 100644 +--- a/drivers/media/dvb/dvb-usb/Kconfig ++++ b/drivers/media/dvb/dvb-usb/Kconfig +@@ -247,6 +247,7 @@ config DVB_USB_AF9005 + depends on DVB_USB && EXPERIMENTAL + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE ++ select FW_LOADER + help + Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver + and the TerraTec Cinergy T USB XE (Rev.1) +diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c +index 3263e97..7b30bd2 100644 +--- a/drivers/media/dvb/dvb-usb/af9005-fe.c ++++ b/drivers/media/dvb/dvb-usb/af9005-fe.c +@@ -22,10 +22,26 @@ + * see Documentation/dvb/README.dvb-usb for more information + */ + #include "af9005.h" +-#include "af9005-script.h" + #include "mt2060.h" + #include "qt1010.h" + #include ++#include ++ ++/* Register initialisation script to be extracted from the Windows driver */ ++ ++typedef struct { ++ __le16 reg; ++ u8 pos; ++ u8 len; ++ u8 val; ++ u8 pad; ++} __packed RegDesc; ++ ++#define WIN_DRV_NAME "AF05BDA.sys" ++#define WIN_DRV_VERSION "6.3.2.1" ++#define WIN_DRV_SIZE 133504 ++#define WIN_DRV_SCRIPT_OFFSET 88316 ++#define WIN_DRV_SCRIPT_SIZE 1110 + + struct af9005_fe_state { + struct dvb_usb_device *d; +@@ -816,6 +832,8 @@ static int af9005_fe_init(struct dvb_frontend *fe) + { + struct af9005_fe_state *state = fe->demodulator_priv; + struct dvb_usb_adapter *adap = fe->dvb->priv; ++ const struct firmware *fw; ++ const RegDesc *script; + int ret, i, scriptlen; + u8 temp, temp0 = 0, temp1 = 0, temp2 = 0; + u8 buf[2]; +@@ -967,37 +985,55 @@ static int af9005_fe_init(struct dvb_frontend *fe) + if ((ret = af9005_write_ofdm_register(state->d, 0xaefb, 0x01))) + return ret; + +- /* load init script */ +- deb_info("load init script\n"); +- scriptlen = sizeof(script) / sizeof(RegDesc); ++ /* load and validate init script */ ++ deb_info("load init script from Windows driver\n"); ++ ret = request_firmware(&fw, WIN_DRV_NAME, &state->d->udev->dev); ++ if (ret) ++ return ret; ++ BUILD_BUG_ON(sizeof(RegDesc) != 6); ++ if (fw->size != WIN_DRV_SIZE || ++ memcmp(fw->data + WIN_DRV_SCRIPT_OFFSET, ++ "\x80\xa1\x00\x08\x0a\x00", 6) || ++ memcmp(fw->data + WIN_DRV_SCRIPT_OFFSET + WIN_DRV_SCRIPT_SIZE - 6, ++ "\x49\xa3\x00\x06\x02\x00", 6)) { ++ err("%s is invalid - should be version %s, size %u bytes\n", ++ WIN_DRV_NAME, WIN_DRV_VERSION, WIN_DRV_SIZE); ++ ret = -EINVAL; ++ goto fail_release; ++ } ++ ++ script = (const RegDesc *)(fw->data + WIN_DRV_SCRIPT_OFFSET); ++ scriptlen = WIN_DRV_SCRIPT_SIZE / sizeof(RegDesc); + for (i = 0; i < scriptlen; i++) { ++ u16 reg = le16_to_cpu(script[i].reg); + if ((ret = +- af9005_write_register_bits(state->d, script[i].reg, ++ af9005_write_register_bits(state->d, reg, + script[i].pos, + script[i].len, script[i].val))) +- return ret; ++ goto fail_release; + /* save 3 bytes of original fcw */ +- if (script[i].reg == 0xae18) ++ if (reg == 0xae18) + temp2 = script[i].val; +- if (script[i].reg == 0xae19) ++ if (reg == 0xae19) + temp1 = script[i].val; +- if (script[i].reg == 0xae1a) ++ if (reg == 0xae1a) + temp0 = script[i].val; + + /* save original unplug threshold */ +- if (script[i].reg == xd_p_reg_unplug_th) ++ if (reg == xd_p_reg_unplug_th) + state->original_if_unplug_th = script[i].val; +- if (script[i].reg == xd_p_reg_unplug_rf_gain_th) ++ if (reg == xd_p_reg_unplug_rf_gain_th) + state->original_rf_unplug_th = script[i].val; +- if (script[i].reg == xd_p_reg_unplug_dtop_if_gain_th) ++ if (reg == xd_p_reg_unplug_dtop_if_gain_th) + state->original_dtop_if_unplug_th = script[i].val; +- if (script[i].reg == xd_p_reg_unplug_dtop_rf_gain_th) ++ if (reg == xd_p_reg_unplug_dtop_rf_gain_th) + state->original_dtop_rf_unplug_th = script[i].val; + + } + state->original_fcw = + ((u32) temp2 << 16) + ((u32) temp1 << 8) + (u32) temp0; + ++ release_firmware(fw); + + /* save original TOPs */ + deb_info("save original TOPs\n"); +@@ -1077,6 +1113,10 @@ static int af9005_fe_init(struct dvb_frontend *fe) + + deb_info("profit!\n"); + return 0; ++ ++fail_release: ++ release_firmware(fw); ++ return ret; + } + + static int af9005_fe_sleep(struct dvb_frontend *fe) +diff --git a/drivers/media/dvb/dvb-usb/af9005-script.h b/drivers/media/dvb/dvb-usb/af9005-script.h +deleted file mode 100644 +index 4d69045..0000000 +--- a/drivers/media/dvb/dvb-usb/af9005-script.h ++++ /dev/null +@@ -1,203 +0,0 @@ +-/* +-File automatically generated by createinit.py using data +-extracted from AF05BDA.sys (windows driver): +- +-dd if=AF05BDA.sys of=initsequence bs=1 skip=88316 count=1110 +-python createinit.py > af9005-script.h +- +-*/ +- +-typedef struct { +- u16 reg; +- u8 pos; +- u8 len; +- u8 val; +-} RegDesc; +- +-static RegDesc script[] = { +- {0xa180, 0x0, 0x8, 0xa}, +- {0xa181, 0x0, 0x8, 0xd7}, +- {0xa182, 0x0, 0x8, 0xa3}, +- {0xa0a0, 0x0, 0x8, 0x0}, +- {0xa0a1, 0x0, 0x5, 0x0}, +- {0xa0a1, 0x5, 0x1, 0x1}, +- {0xa0c0, 0x0, 0x4, 0x1}, +- {0xa20e, 0x4, 0x4, 0xa}, +- {0xa20f, 0x0, 0x8, 0x40}, +- {0xa210, 0x0, 0x8, 0x8}, +- {0xa32a, 0x0, 0x4, 0xa}, +- {0xa32c, 0x0, 0x8, 0x20}, +- {0xa32b, 0x0, 0x8, 0x15}, +- {0xa1a0, 0x1, 0x1, 0x1}, +- {0xa000, 0x0, 0x1, 0x1}, +- {0xa000, 0x1, 0x1, 0x0}, +- {0xa001, 0x1, 0x1, 0x1}, +- {0xa001, 0x0, 0x1, 0x0}, +- {0xa001, 0x5, 0x1, 0x0}, +- {0xa00e, 0x0, 0x5, 0x10}, +- {0xa00f, 0x0, 0x3, 0x4}, +- {0xa00f, 0x3, 0x3, 0x5}, +- {0xa010, 0x0, 0x3, 0x4}, +- {0xa010, 0x3, 0x3, 0x5}, +- {0xa016, 0x4, 0x4, 0x3}, +- {0xa01f, 0x0, 0x6, 0xa}, +- {0xa020, 0x0, 0x6, 0xa}, +- {0xa2bc, 0x0, 0x1, 0x1}, +- {0xa2bc, 0x5, 0x1, 0x1}, +- {0xa015, 0x0, 0x8, 0x50}, +- {0xa016, 0x0, 0x1, 0x0}, +- {0xa02a, 0x0, 0x8, 0x50}, +- {0xa029, 0x0, 0x8, 0x4b}, +- {0xa614, 0x0, 0x8, 0x46}, +- {0xa002, 0x0, 0x5, 0x19}, +- {0xa003, 0x0, 0x5, 0x1a}, +- {0xa004, 0x0, 0x5, 0x19}, +- {0xa005, 0x0, 0x5, 0x1a}, +- {0xa008, 0x0, 0x8, 0x69}, +- {0xa009, 0x0, 0x2, 0x2}, +- {0xae1b, 0x0, 0x8, 0x69}, +- {0xae1c, 0x0, 0x8, 0x2}, +- {0xae1d, 0x0, 0x8, 0x2a}, +- {0xa022, 0x0, 0x8, 0xaa}, +- {0xa006, 0x0, 0x8, 0xc8}, +- {0xa007, 0x0, 0x2, 0x0}, +- {0xa00c, 0x0, 0x8, 0xba}, +- {0xa00d, 0x0, 0x2, 0x2}, +- {0xa608, 0x0, 0x8, 0xba}, +- {0xa60e, 0x0, 0x2, 0x2}, +- {0xa609, 0x0, 0x8, 0x80}, +- {0xa60e, 0x2, 0x2, 0x3}, +- {0xa00a, 0x0, 0x8, 0xb6}, +- {0xa00b, 0x0, 0x2, 0x0}, +- {0xa011, 0x0, 0x8, 0xb9}, +- {0xa012, 0x0, 0x2, 0x0}, +- {0xa013, 0x0, 0x8, 0xbd}, +- {0xa014, 0x0, 0x2, 0x2}, +- {0xa366, 0x0, 0x1, 0x1}, +- {0xa2bc, 0x3, 0x1, 0x0}, +- {0xa2bd, 0x0, 0x8, 0xa}, +- {0xa2be, 0x0, 0x8, 0x14}, +- {0xa2bf, 0x0, 0x8, 0x8}, +- {0xa60a, 0x0, 0x8, 0xbd}, +- {0xa60e, 0x4, 0x2, 0x2}, +- {0xa60b, 0x0, 0x8, 0x86}, +- {0xa60e, 0x6, 0x2, 0x3}, +- {0xa001, 0x2, 0x2, 0x1}, +- {0xa1c7, 0x0, 0x8, 0xf5}, +- {0xa03d, 0x0, 0x8, 0xb1}, +- {0xa616, 0x0, 0x8, 0xff}, +- {0xa617, 0x0, 0x8, 0xad}, +- {0xa618, 0x0, 0x8, 0xad}, +- {0xa61e, 0x3, 0x1, 0x1}, +- {0xae1a, 0x0, 0x8, 0x0}, +- {0xae19, 0x0, 0x8, 0xc8}, +- {0xae18, 0x0, 0x8, 0x61}, +- {0xa140, 0x0, 0x8, 0x0}, +- {0xa141, 0x0, 0x8, 0xc8}, +- {0xa142, 0x0, 0x7, 0x61}, +- {0xa023, 0x0, 0x8, 0xff}, +- {0xa021, 0x0, 0x8, 0xad}, +- {0xa026, 0x0, 0x1, 0x0}, +- {0xa024, 0x0, 0x8, 0xff}, +- {0xa025, 0x0, 0x8, 0xff}, +- {0xa1c8, 0x0, 0x8, 0xf}, +- {0xa2bc, 0x1, 0x1, 0x0}, +- {0xa60c, 0x0, 0x4, 0x5}, +- {0xa60c, 0x4, 0x4, 0x6}, +- {0xa60d, 0x0, 0x8, 0xa}, +- {0xa371, 0x0, 0x1, 0x1}, +- {0xa366, 0x1, 0x3, 0x7}, +- {0xa338, 0x0, 0x8, 0x10}, +- {0xa339, 0x0, 0x6, 0x7}, +- {0xa33a, 0x0, 0x6, 0x1f}, +- {0xa33b, 0x0, 0x8, 0xf6}, +- {0xa33c, 0x3, 0x5, 0x4}, +- {0xa33d, 0x4, 0x4, 0x0}, +- {0xa33d, 0x1, 0x1, 0x1}, +- {0xa33d, 0x2, 0x1, 0x1}, +- {0xa33d, 0x3, 0x1, 0x1}, +- {0xa16d, 0x0, 0x4, 0xf}, +- {0xa161, 0x0, 0x5, 0x5}, +- {0xa162, 0x0, 0x4, 0x5}, +- {0xa165, 0x0, 0x8, 0xff}, +- {0xa166, 0x0, 0x8, 0x9c}, +- {0xa2c3, 0x0, 0x4, 0x5}, +- {0xa61a, 0x0, 0x6, 0xf}, +- {0xb200, 0x0, 0x8, 0xa1}, +- {0xb201, 0x0, 0x8, 0x7}, +- {0xa093, 0x0, 0x1, 0x0}, +- {0xa093, 0x1, 0x5, 0xf}, +- {0xa094, 0x0, 0x8, 0xff}, +- {0xa095, 0x0, 0x8, 0xf}, +- {0xa080, 0x2, 0x5, 0x3}, +- {0xa081, 0x0, 0x4, 0x0}, +- {0xa081, 0x4, 0x4, 0x9}, +- {0xa082, 0x0, 0x5, 0x1f}, +- {0xa08d, 0x0, 0x8, 0x1}, +- {0xa083, 0x0, 0x8, 0x32}, +- {0xa084, 0x0, 0x1, 0x0}, +- {0xa08e, 0x0, 0x8, 0x3}, +- {0xa085, 0x0, 0x8, 0x32}, +- {0xa086, 0x0, 0x3, 0x0}, +- {0xa087, 0x0, 0x8, 0x6e}, +- {0xa088, 0x0, 0x5, 0x15}, +- {0xa089, 0x0, 0x8, 0x0}, +- {0xa08a, 0x0, 0x5, 0x19}, +- {0xa08b, 0x0, 0x8, 0x92}, +- {0xa08c, 0x0, 0x5, 0x1c}, +- {0xa120, 0x0, 0x8, 0x0}, +- {0xa121, 0x0, 0x5, 0x10}, +- {0xa122, 0x0, 0x8, 0x0}, +- {0xa123, 0x0, 0x7, 0x40}, +- {0xa123, 0x7, 0x1, 0x0}, +- {0xa124, 0x0, 0x8, 0x13}, +- {0xa125, 0x0, 0x7, 0x10}, +- {0xa1c0, 0x0, 0x8, 0x0}, +- {0xa1c1, 0x0, 0x5, 0x4}, +- {0xa1c2, 0x0, 0x8, 0x0}, +- {0xa1c3, 0x0, 0x5, 0x10}, +- {0xa1c3, 0x5, 0x3, 0x0}, +- {0xa1c4, 0x0, 0x6, 0x0}, +- {0xa1c5, 0x0, 0x7, 0x10}, +- {0xa100, 0x0, 0x8, 0x0}, +- {0xa101, 0x0, 0x5, 0x10}, +- {0xa102, 0x0, 0x8, 0x0}, +- {0xa103, 0x0, 0x7, 0x40}, +- {0xa103, 0x7, 0x1, 0x0}, +- {0xa104, 0x0, 0x8, 0x18}, +- {0xa105, 0x0, 0x7, 0xa}, +- {0xa106, 0x0, 0x8, 0x20}, +- {0xa107, 0x0, 0x8, 0x40}, +- {0xa108, 0x0, 0x4, 0x0}, +- {0xa38c, 0x0, 0x8, 0xfc}, +- {0xa38d, 0x0, 0x8, 0x0}, +- {0xa38e, 0x0, 0x8, 0x7e}, +- {0xa38f, 0x0, 0x8, 0x0}, +- {0xa390, 0x0, 0x8, 0x2f}, +- {0xa60f, 0x5, 0x1, 0x1}, +- {0xa170, 0x0, 0x8, 0xdc}, +- {0xa171, 0x0, 0x2, 0x0}, +- {0xa2ae, 0x0, 0x1, 0x1}, +- {0xa2ae, 0x1, 0x1, 0x1}, +- {0xa392, 0x0, 0x1, 0x1}, +- {0xa391, 0x2, 0x1, 0x0}, +- {0xabc1, 0x0, 0x8, 0xff}, +- {0xabc2, 0x0, 0x8, 0x0}, +- {0xabc8, 0x0, 0x8, 0x8}, +- {0xabca, 0x0, 0x8, 0x10}, +- {0xabcb, 0x0, 0x1, 0x0}, +- {0xabc3, 0x5, 0x3, 0x7}, +- {0xabc0, 0x6, 0x1, 0x0}, +- {0xabc0, 0x4, 0x2, 0x0}, +- {0xa344, 0x4, 0x4, 0x1}, +- {0xabc0, 0x7, 0x1, 0x1}, +- {0xabc0, 0x2, 0x1, 0x1}, +- {0xa345, 0x0, 0x8, 0x66}, +- {0xa346, 0x0, 0x8, 0x66}, +- {0xa347, 0x0, 0x4, 0x0}, +- {0xa343, 0x0, 0x4, 0xa}, +- {0xa347, 0x4, 0x4, 0x2}, +- {0xa348, 0x0, 0x4, 0xc}, +- {0xa348, 0x4, 0x4, 0x7}, +- {0xa349, 0x0, 0x6, 0x2}, +-}; +diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c +index f313182..55695f5 100644 +--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c ++++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c +@@ -1852,12 +1852,9 @@ static int stk9090m_frontend_attach(struct dvb_usb_adapter *adap) + + dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80); + +- if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev)) { +- deb_info("%s: Upload failed. (file not found?)\n", __func__); ++ if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev)) + return -ENODEV; +- } else { +- deb_info("%s: firmware read %Zu bytes.\n", __func__, state->frontend_firmware->size); +- } ++ deb_info("%s: firmware read %Zu bytes.\n", __func__, state->frontend_firmware->size); + stk9090m_config.microcode_B_fe_size = state->frontend_firmware->size; + stk9090m_config.microcode_B_fe_buffer = state->frontend_firmware->data; + +@@ -1918,12 +1915,9 @@ static int nim9090md_frontend_attach(struct dvb_usb_adapter *adap) + msleep(20); + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); + +- if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev)) { +- deb_info("%s: Upload failed. (file not found?)\n", __func__); ++ if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev)) + return -EIO; +- } else { +- deb_info("%s: firmware read %Zu bytes.\n", __func__, state->frontend_firmware->size); +- } ++ deb_info("%s: firmware read %Zu bytes.\n", __func__, state->frontend_firmware->size); + nim9090md_config[0].microcode_B_fe_size = state->frontend_firmware->size; + nim9090md_config[0].microcode_B_fe_buffer = state->frontend_firmware->data; + nim9090md_config[1].microcode_B_fe_size = state->frontend_firmware->size; +diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c +index 733a7ff..a4e18ec 100644 +--- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c ++++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c +@@ -80,14 +80,9 @@ int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_device_pro + int ret; + const struct firmware *fw = NULL; + +- if ((ret = request_firmware(&fw, props->firmware, &udev->dev)) != 0) { +- err("did not find the firmware file. (%s) " +- "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)", +- props->firmware,ret); ++ ret = request_firmware(&fw, props->firmware, &udev->dev); ++ if (ret) + return ret; +- } +- +- info("downloading firmware from file '%s'",props->firmware); + + switch (props->usb_ctrl) { + case CYPRESS_AN2135: +diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c +index 5f71284..1dc0eb7 100644 +--- a/drivers/media/dvb/dvb-usb/gp8psk.c ++++ b/drivers/media/dvb/dvb-usb/gp8psk.c +@@ -116,20 +116,14 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) + const u8 *ptr; + u8 *buf; + if ((ret = request_firmware(&fw, bcm4500_firmware, +- &d->udev->dev)) != 0) { +- err("did not find the bcm4500 firmware file. (%s) " +- "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)", +- bcm4500_firmware,ret); ++ &d->udev->dev)) != 0) + return ret; +- } + + ret = -EINVAL; + + if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0)) + goto out_rel_fw; + +- info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware); +- + ptr = fw->data; + buf = kmalloc(64, GFP_KERNEL | GFP_DMA); + if (!buf) { +diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c +index 98fd9a6..e511482 100644 +--- a/drivers/media/dvb/dvb-usb/opera1.c ++++ b/drivers/media/dvb/dvb-usb/opera1.c +@@ -452,9 +452,6 @@ static int opera1_xilinx_load_firmware(struct usb_device *dev, + info("start downloading fpga firmware %s",filename); + + if ((ret = request_firmware(&fw, filename, &dev->dev)) != 0) { +- err("did not find the firmware file. (%s) " +- "Please see linux/Documentation/dvb/ for more details on firmware-problems.", +- filename); + return ret; + } else { + p = kmalloc(fw->size, GFP_KERNEL); +diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c +index 345311c..395ab72 100644 +--- a/drivers/media/dvb/frontends/af9013.c ++++ b/drivers/media/dvb/frontends/af9013.c +@@ -1346,15 +1346,8 @@ static int af9013_download_firmware(struct af9013_state *state) + + /* request the firmware, this will block and timeout */ + ret = request_firmware(&fw, fw_file, state->i2c->dev.parent); +- if (ret) { +- err("did not find the firmware file. (%s) " +- "Please see linux/Documentation/dvb/ for more details" \ +- " on firmware-problems. (%d)", +- fw_file, ret); ++ if (ret) + goto error; +- } +- +- info("downloading firmware from file '%s'", fw_file); + + /* calc checksum */ + for (i = 0; i < fw->size; i++) +diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c +index 8aff586..190eda5 100644 +--- a/drivers/media/dvb/frontends/bcm3510.c ++++ b/drivers/media/dvb/frontends/bcm3510.c +@@ -619,10 +619,9 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe) + int ret,i; + + deb_info("requesting firmware\n"); +- if ((ret = st->config->request_firmware(fe, &fw, BCM3510_DEFAULT_FIRMWARE)) < 0) { +- err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret); ++ ret = st->config->request_firmware(fe, &fw, BCM3510_DEFAULT_FIRMWARE); ++ if (ret) + return ret; +- } + deb_info("got firmware: %zd\n",fw->size); + + b = fw->data; +diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c +index 4ff6d15..3131d3f 100644 +--- a/drivers/media/dvb/frontends/cx24116.c ++++ b/drivers/media/dvb/frontends/cx24116.c +@@ -493,13 +493,8 @@ static int cx24116_firmware_ondemand(struct dvb_frontend *fe) + __func__, CX24116_DEFAULT_FIRMWARE); + ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, + state->i2c->dev.parent); +- printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", +- __func__); +- if (ret) { +- printk(KERN_ERR "%s: No firmware uploaded " +- "(timeout or file not found?)\n", __func__); ++ if (ret) + return ret; +- } + + /* Make sure we don't recurse back through here + * during loading */ +diff --git a/drivers/media/dvb/frontends/drxd_hard.c b/drivers/media/dvb/frontends/drxd_hard.c +index 88e46f4..fa86a2e 100644 +--- a/drivers/media/dvb/frontends/drxd_hard.c ++++ b/drivers/media/dvb/frontends/drxd_hard.c +@@ -909,10 +909,8 @@ static int load_firmware(struct drxd_state *state, const char *fw_name) + { + const struct firmware *fw; + +- if (request_firmware(&fw, fw_name, state->dev) < 0) { +- printk(KERN_ERR "drxd: firmware load failure [%s]\n", fw_name); ++ if (request_firmware(&fw, fw_name, state->dev)) + return -EIO; +- } + + state->microcode = kmalloc(fw->size, GFP_KERNEL); + if (state->microcode == NULL) { +diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c +index a1f5e3d..584835e 100644 +--- a/drivers/media/dvb/frontends/drxk_hard.c ++++ b/drivers/media/dvb/frontends/drxk_hard.c +@@ -5968,13 +5968,8 @@ static int load_microcode(struct drxk_state *state, const char *mc_name) + dprintk(1, "\n"); + + err = request_firmware(&fw, mc_name, state->i2c->dev.parent); +- if (err < 0) { +- printk(KERN_ERR +- "drxk: Could not load firmware file %s.\n", mc_name); +- printk(KERN_INFO +- "drxk: Copy %s to your hotplug directory!\n", mc_name); ++ if (err) + return err; +- } + err = DownloadMicrocode(state, fw->data, fw->size); + release_firmware(fw); + return err; +diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c +index 2151c99..40bef90 100644 +--- a/drivers/media/dvb/frontends/ds3000.c ++++ b/drivers/media/dvb/frontends/ds3000.c +@@ -403,12 +403,8 @@ static int ds3000_firmware_ondemand(struct dvb_frontend *fe) + DS3000_DEFAULT_FIRMWARE); + ret = request_firmware(&fw, DS3000_DEFAULT_FIRMWARE, + state->i2c->dev.parent); +- printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__); +- if (ret) { +- printk(KERN_ERR "%s: No firmware uploaded (timeout or file not " +- "found?)\n", __func__); ++ if (ret) + return ret; +- } + + /* Make sure we don't recurse back through here during loading */ + state->skip_fw_load = 1; +diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c +index eac2065..2be6209 100644 +--- a/drivers/media/dvb/frontends/nxt200x.c ++++ b/drivers/media/dvb/frontends/nxt200x.c +@@ -881,11 +881,8 @@ static int nxt2002_init(struct dvb_frontend* fe) + printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE); + ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE, + state->i2c->dev.parent); +- printk("nxt2002: Waiting for firmware upload(2)...\n"); +- if (ret) { +- printk("nxt2002: No firmware uploaded (timeout or file not found?)\n"); ++ if (ret) + return ret; +- } + + ret = nxt2002_load_firmware(fe, fw); + release_firmware(fw); +@@ -946,11 +943,8 @@ static int nxt2004_init(struct dvb_frontend* fe) + printk("nxt2004: Waiting for firmware upload (%s)...\n", NXT2004_DEFAULT_FIRMWARE); + ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE, + state->i2c->dev.parent); +- printk("nxt2004: Waiting for firmware upload(2)...\n"); +- if (ret) { +- printk("nxt2004: No firmware uploaded (timeout or file not found?)\n"); ++ if (ret) + return ret; +- } + + ret = nxt2004_load_firmware(fe, fw); + release_firmware(fw); +diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c +index 38e67ac..c16c504 100644 +--- a/drivers/media/dvb/frontends/or51132.c ++++ b/drivers/media/dvb/frontends/or51132.c +@@ -341,11 +341,8 @@ static int or51132_set_parameters(struct dvb_frontend* fe, + printk("or51132: Waiting for firmware upload(%s)...\n", + fwname); + ret = request_firmware(&fw, fwname, state->i2c->dev.parent); +- if (ret) { +- printk(KERN_WARNING "or51132: No firmware up" +- "loaded(timeout or file not found?)\n"); ++ if (ret) + return ret; +- } + ret = or51132_load_firmware(fe, fw); + release_firmware(fw); + if (ret) { +diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c +index c709ce6..b4d9a02 100644 +--- a/drivers/media/dvb/frontends/or51211.c ++++ b/drivers/media/dvb/frontends/or51211.c +@@ -379,12 +379,8 @@ static int or51211_init(struct dvb_frontend* fe) + "(%s)...\n", OR51211_DEFAULT_FIRMWARE); + ret = config->request_firmware(fe, &fw, + OR51211_DEFAULT_FIRMWARE); +- printk(KERN_INFO "or51211:Got Hotplug firmware\n"); +- if (ret) { +- printk(KERN_WARNING "or51211: No firmware uploaded " +- "(timeout or file not found?)\n"); ++ if (ret) + return ret; +- } + + ret = or51211_load_firmware(fe, fw); + release_firmware(fw); +diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c +index b85eb60..2d7482b 100644 +--- a/drivers/media/dvb/frontends/sp8870.c ++++ b/drivers/media/dvb/frontends/sp8870.c +@@ -315,10 +315,8 @@ static int sp8870_init (struct dvb_frontend* fe) + + /* request the firmware, this will block until someone uploads it */ + printk("sp8870: waiting for firmware upload (%s)...\n", SP8870_DEFAULT_FIRMWARE); +- if (state->config->request_firmware(fe, &fw, SP8870_DEFAULT_FIRMWARE)) { +- printk("sp8870: no firmware upload (timeout or file not found?)\n"); ++ if (state->config->request_firmware(fe, &fw, SP8870_DEFAULT_FIRMWARE)) + return -EIO; +- } + + if (sp8870_firmware_upload(state, fw)) { + printk("sp8870: writing firmware to device failed\n"); +diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c +index 4a7c3d8..cb9c4fc 100644 +--- a/drivers/media/dvb/frontends/sp887x.c ++++ b/drivers/media/dvb/frontends/sp887x.c +@@ -514,10 +514,8 @@ static int sp887x_init(struct dvb_frontend* fe) + /* request the firmware, this will block until someone uploads it */ + printk("sp887x: waiting for firmware upload (%s)...\n", SP887X_DEFAULT_FIRMWARE); + ret = state->config->request_firmware(fe, &fw, SP887X_DEFAULT_FIRMWARE); +- if (ret) { +- printk("sp887x: no firmware upload (timeout or file not found?)\n"); ++ if (ret) + return ret; +- } + + ret = sp887x_initial_setup(fe, fw); + release_firmware(fw); +diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c +index 7f10594..a246b75 100644 +--- a/drivers/media/dvb/frontends/tda10048.c ++++ b/drivers/media/dvb/frontends/tda10048.c +@@ -509,8 +509,6 @@ static int tda10048_firmware_upload(struct dvb_frontend *fe) + ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE, + state->i2c->dev.parent); + if (ret) { +- printk(KERN_ERR "%s: Upload failed. (file not found?)\n", +- __func__); + return -EIO; + } else { + printk(KERN_INFO "%s: firmware read %Zu bytes.\n", +diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c +index ea485d9..5127d96 100644 +--- a/drivers/media/dvb/frontends/tda1004x.c ++++ b/drivers/media/dvb/frontends/tda1004x.c +@@ -397,10 +397,8 @@ static int tda10045_fwupload(struct dvb_frontend* fe) + /* request the firmware, this will block until someone uploads it */ + printk(KERN_INFO "tda1004x: waiting for firmware upload (%s)...\n", TDA10045_DEFAULT_FIRMWARE); + ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE); +- if (ret) { +- printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n"); ++ if (ret) + return ret; +- } + + /* reset chip */ + tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0); +@@ -541,7 +539,6 @@ static int tda10046_fwupload(struct dvb_frontend* fe) + /* remain compatible to old bug: try to load with tda10045 image name */ + ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE); + if (ret) { +- printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n"); + return ret; + } else { + printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n", +diff --git a/drivers/media/dvb/frontends/tda10071.c b/drivers/media/dvb/frontends/tda10071.c +index ba79284..daa1b7c 100644 +--- a/drivers/media/dvb/frontends/tda10071.c ++++ b/drivers/media/dvb/frontends/tda10071.c +@@ -934,13 +934,8 @@ static int tda10071_init(struct dvb_frontend *fe) + + /* request the firmware, this will block and timeout */ + ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent); +- if (ret) { +- err("did not find the firmware file. (%s) " +- "Please see linux/Documentation/dvb/ for more" \ +- " details on firmware-problems. (%d)", +- fw_file, ret); ++ if (ret) + goto error; +- } + + /* init */ + for (i = 0; i < ARRAY_SIZE(tab2); i++) { +diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c +index f129a93..5d4cbcd 100644 +--- a/drivers/media/dvb/ngene/ngene-core.c ++++ b/drivers/media/dvb/ngene/ngene-core.c +@@ -1272,13 +1272,8 @@ static int ngene_load_firm(struct ngene *dev) + break; + } + +- if (request_firmware(&fw, fw_name, &dev->pci_dev->dev) < 0) { +- printk(KERN_ERR DEVICE_NAME +- ": Could not load firmware file %s.\n", fw_name); +- printk(KERN_INFO DEVICE_NAME +- ": Copy %s to your hotplug directory!\n", fw_name); ++ if (request_firmware(&fw, fw_name, &dev->pci_dev->dev)) + return -1; +- } + if (size == 0) + size = fw->size; + if (size != fw->size) { +@@ -1286,8 +1281,6 @@ static int ngene_load_firm(struct ngene *dev) + ": Firmware %s has invalid size!", fw_name); + err = -1; + } else { +- printk(KERN_INFO DEVICE_NAME +- ": Loading firmware file %s.\n", fw_name); + ngene_fw = (u8 *) fw->data; + err = ngene_command_load_firmware(dev, ngene_fw, size); + } +diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c +index 7331e84..e1a83db 100644 +--- a/drivers/media/dvb/siano/smscoreapi.c ++++ b/drivers/media/dvb/siano/smscoreapi.c +@@ -642,10 +642,8 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, + return -EINVAL; + + rc = request_firmware(&fw, filename, coredev->device); +- if (rc < 0) { +- sms_info("failed to open \"%s\"", filename); ++ if (rc) + return rc; +- } + sms_info("read FW %s, size=%zd", filename, fw->size); + fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT), + GFP_KERNEL | GFP_DMA); +diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c +index 3d20719..ebe4d20 100644 +--- a/drivers/media/dvb/ttpci/av7110.c ++++ b/drivers/media/dvb/ttpci/av7110.c +@@ -1532,16 +1532,9 @@ static int get_firmware(struct av7110* av7110) + /* request the av7110 firmware, this will block until someone uploads it */ + ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev); + if (ret) { +- if (ret == -ENOENT) { +- printk(KERN_ERR "dvb-ttpci: could not load firmware," +- " file not found: dvb-ttpci-01.fw\n"); +- printk(KERN_ERR "dvb-ttpci: usually this should be in " +- "/usr/lib/hotplug/firmware or /lib/firmware\n"); +- printk(KERN_ERR "dvb-ttpci: and can be downloaded from" ++ if (ret == -ENOENT) ++ printk(KERN_ERR "dvb-ttpci: firmware can be downloaded from" + " http://www.linuxtv.org/download/dvb/firmware/\n"); +- } else +- printk(KERN_ERR "dvb-ttpci: cannot request firmware" +- " (error %i)\n", ret); + return -EINVAL; + } + +diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c +index f1cbfe5..203f568 100644 +--- a/drivers/media/dvb/ttpci/av7110_hw.c ++++ b/drivers/media/dvb/ttpci/av7110_hw.c +@@ -243,11 +243,8 @@ int av7110_bootarm(struct av7110 *av7110) + //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT); + + ret = request_firmware(&fw, fw_name, &dev->pci->dev); +- if (ret) { +- printk(KERN_ERR "dvb-ttpci: Failed to load firmware \"%s\"\n", +- fw_name); ++ if (ret) + return ret; +- } + + mwdebi(av7110, DEBISWAB, DPRAM_BASE, fw->data, fw->size); + release_firmware(fw); +diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +index 420bb42..3082fb5 100644 +--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c ++++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +@@ -296,10 +296,8 @@ static int ttusb_boot_dsp(struct ttusb *ttusb) + + err = request_firmware(&fw, "ttusb-budget/dspbootcode.bin", + &ttusb->dev->dev); +- if (err) { +- printk(KERN_ERR "ttusb-budget: failed to request firmware\n"); ++ if (err) + return err; +- } + + /* BootBlock */ + b[0] = 0xaa; +diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c +index f893bff..3afee49 100644 +--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c ++++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c +@@ -1293,11 +1293,8 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) + + dprintk("%s\n", __func__); + +- if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) { +- printk(KERN_ERR "%s: Firmware (%s) unavailable.\n", +- __func__, dec->firmware_name); ++ if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) + return 1; +- } + + firmware = fw_entry->data; + firmware_size = fw_entry->size; +diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c +index 8aa4968..016911a 100644 +--- a/drivers/media/radio/radio-wl1273.c ++++ b/drivers/media/radio/radio-wl1273.c +@@ -512,11 +512,8 @@ static int wl1273_fm_upload_firmware_patch(struct wl1273_device *radio) + * Uploading the firmware patch is not always necessary, + * so we only print an info message. + */ +- if (request_firmware(&fw_p, fw_name, dev)) { +- dev_info(dev, "%s - %s not found\n", __func__, fw_name); +- ++ if (request_firmware(&fw_p, fw_name, dev)) + return 0; +- } + + ptr = (__u8 *) fw_p->data; + packet_num = ptr[0]; +diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c +index 5991ab6..03b578e 100644 +--- a/drivers/media/radio/wl128x/fmdrv_common.c ++++ b/drivers/media/radio/wl128x/fmdrv_common.c +@@ -1248,10 +1248,8 @@ static u32 fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name) + + ret = request_firmware(&fw_entry, fw_name, + &fmdev->radio_dev->dev); +- if (ret < 0) { +- fmerr("Unable to read firmware(%s) content\n", fw_name); ++ if (ret) + return ret; +- } + fmdbg("Firmware(%s) length : %d bytes\n", fw_name, fw_entry->size); + + fw_data = (void *)fw_entry->data; +diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig +index aeb7f43..8fe0285 100644 +--- a/drivers/media/rc/Kconfig ++++ b/drivers/media/rc/Kconfig +@@ -243,6 +243,21 @@ config IR_WINBOND_CIR + To compile this driver as a module, choose M here: the module will + be called winbond_cir. + ++config IR_IGUANA ++ tristate "IguanaWorks USB IR Transceiver" ++ depends on RC_CORE ++ select USB ++ ---help--- ++ Say Y here if you want to use the IguanaWorks USB IR Transceiver. ++ Both infrared receive and send are supported. If you want to ++ change the ID or the pin config, use the user space driver from ++ IguanaWorks. ++ ++ Only firmware 0x0205 and later is supported. ++ ++ To compile this driver as a module, choose M here: the module will ++ be called iguanair. ++ + config RC_LOOPBACK + tristate "Remote Control Loopback Driver" + depends on RC_CORE +diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile +index 2156e78..f94771f 100644 +--- a/drivers/media/rc/Makefile ++++ b/drivers/media/rc/Makefile +@@ -25,3 +25,4 @@ obj-$(CONFIG_IR_REDRAT3) += redrat3.o + obj-$(CONFIG_IR_STREAMZAP) += streamzap.o + obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o + obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o ++obj-$(CONFIG_IR_IGUANA) += iguanair.o +diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c +new file mode 100644 +index 0000000..51d7057 +--- /dev/null ++++ b/drivers/media/rc/iguanair.c +@@ -0,0 +1,621 @@ ++/* ++ * IguanaWorks USB IR Transceiver support ++ * ++ * Copyright (C) 2012 Sean Young ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "iguanair" ++#define BUF_SIZE 152 ++ ++struct iguanair { ++ struct rc_dev *rc; ++ ++ struct device *dev; ++ struct usb_device *udev; ++ ++ uint16_t version; ++ uint8_t bufsize; ++ uint8_t cycle_overhead; ++ ++ struct mutex lock; ++ ++ /* receiver support */ ++ bool receiver_on; ++ dma_addr_t dma_in, dma_out; ++ uint8_t *buf_in; ++ struct urb *urb_in, *urb_out; ++ struct completion completion; ++ ++ /* transmit support */ ++ bool tx_overflow; ++ uint32_t carrier; ++ struct send_packet *packet; ++ ++ char name[64]; ++ char phys[64]; ++}; ++ ++#define CMD_GET_VERSION 0x01 ++#define CMD_GET_BUFSIZE 0x11 ++#define CMD_GET_FEATURES 0x10 ++#define CMD_SEND 0x15 ++#define CMD_EXECUTE 0x1f ++#define CMD_RX_OVERFLOW 0x31 ++#define CMD_TX_OVERFLOW 0x32 ++#define CMD_RECEIVER_ON 0x12 ++#define CMD_RECEIVER_OFF 0x14 ++ ++#define DIR_IN 0xdc ++#define DIR_OUT 0xcd ++ ++#define MAX_IN_PACKET 8u ++#define MAX_OUT_PACKET (sizeof(struct send_packet) + BUF_SIZE) ++#define TIMEOUT 1000 ++#define RX_RESOLUTION 21333 ++ ++struct packet { ++ uint16_t start; ++ uint8_t direction; ++ uint8_t cmd; ++}; ++ ++struct send_packet { ++ struct packet header; ++ uint8_t length; ++ uint8_t channels; ++ uint8_t busy7; ++ uint8_t busy4; ++ uint8_t payload[0]; ++}; ++ ++static void process_ir_data(struct iguanair *ir, unsigned len) ++{ ++ if (len >= 4 && ir->buf_in[0] == 0 && ir->buf_in[1] == 0) { ++ switch (ir->buf_in[3]) { ++ case CMD_GET_VERSION: ++ if (len == 6) { ++ ir->version = (ir->buf_in[5] << 8) | ++ ir->buf_in[4]; ++ complete(&ir->completion); ++ } ++ break; ++ case CMD_GET_BUFSIZE: ++ if (len >= 5) { ++ ir->bufsize = ir->buf_in[4]; ++ complete(&ir->completion); ++ } ++ break; ++ case CMD_GET_FEATURES: ++ if (len > 5) { ++ ir->cycle_overhead = ir->buf_in[5]; ++ complete(&ir->completion); ++ } ++ break; ++ case CMD_TX_OVERFLOW: ++ ir->tx_overflow = true; ++ case CMD_RECEIVER_OFF: ++ case CMD_RECEIVER_ON: ++ case CMD_SEND: ++ complete(&ir->completion); ++ break; ++ case CMD_RX_OVERFLOW: ++ dev_warn(ir->dev, "receive overflow\n"); ++ ir_raw_event_reset(ir->rc); ++ break; ++ default: ++ dev_warn(ir->dev, "control code %02x received\n", ++ ir->buf_in[3]); ++ break; ++ } ++ } else if (len >= 7) { ++ DEFINE_IR_RAW_EVENT(rawir); ++ unsigned i; ++ bool event = false; ++ ++ init_ir_raw_event(&rawir); ++ ++ for (i = 0; i < 7; i++) { ++ if (ir->buf_in[i] == 0x80) { ++ rawir.pulse = false; ++ rawir.duration = US_TO_NS(21845); ++ } else { ++ rawir.pulse = (ir->buf_in[i] & 0x80) == 0; ++ rawir.duration = ((ir->buf_in[i] & 0x7f) + 1) * ++ RX_RESOLUTION; ++ } ++ ++ if (ir_raw_event_store_with_filter(ir->rc, &rawir)) ++ event = true; ++ } ++ ++ if (event) ++ ir_raw_event_handle(ir->rc); ++ } ++} ++ ++static void iguanair_rx(struct urb *urb) ++{ ++ struct iguanair *ir; ++ int rc; ++ ++ if (!urb) ++ return; ++ ++ ir = urb->context; ++ if (!ir) { ++ usb_unlink_urb(urb); ++ return; ++ } ++ ++ switch (urb->status) { ++ case 0: ++ process_ir_data(ir, urb->actual_length); ++ break; ++ case -ECONNRESET: ++ case -ENOENT: ++ case -ESHUTDOWN: ++ usb_unlink_urb(urb); ++ return; ++ case -EPIPE: ++ default: ++ dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status); ++ break; ++ } ++ ++ rc = usb_submit_urb(urb, GFP_ATOMIC); ++ if (rc && rc != -ENODEV) ++ dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc); ++} ++ ++static void iguanair_irq_out(struct urb *urb) ++{ ++ struct iguanair *ir = urb->context; ++ ++ if (urb->status) ++ dev_dbg(ir->dev, "Error: out urb status = %d\n", urb->status); ++} ++ ++static int iguanair_send(struct iguanair *ir, unsigned size) ++{ ++ int rc; ++ ++ INIT_COMPLETION(ir->completion); ++ ++ ir->urb_out->transfer_buffer_length = size; ++ rc = usb_submit_urb(ir->urb_out, GFP_KERNEL); ++ if (rc) ++ return rc; ++ ++ if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0) ++ return -ETIMEDOUT; ++ ++ return rc; ++} ++ ++static int iguanair_get_features(struct iguanair *ir) ++{ ++ int rc; ++ ++ ir->packet->header.start = 0; ++ ir->packet->header.direction = DIR_OUT; ++ ir->packet->header.cmd = CMD_GET_VERSION; ++ ++ rc = iguanair_send(ir, sizeof(ir->packet->header)); ++ if (rc) { ++ dev_info(ir->dev, "failed to get version\n"); ++ goto out; ++ } ++ ++ if (ir->version < 0x205) { ++ dev_err(ir->dev, "firmware 0x%04x is too old\n", ir->version); ++ rc = -ENODEV; ++ goto out; ++ } ++ ++ ir->bufsize = 150; ++ ir->cycle_overhead = 65; ++ ++ ir->packet->header.cmd = CMD_GET_BUFSIZE; ++ ++ rc = iguanair_send(ir, sizeof(ir->packet->header)); ++ if (rc) { ++ dev_info(ir->dev, "failed to get buffer size\n"); ++ goto out; ++ } ++ ++ if (ir->bufsize > BUF_SIZE) { ++ dev_info(ir->dev, "buffer size %u larger than expected\n", ++ ir->bufsize); ++ ir->bufsize = BUF_SIZE; ++ } ++ ++ ir->packet->header.cmd = CMD_GET_FEATURES; ++ ++ rc = iguanair_send(ir, sizeof(ir->packet->header)); ++ if (rc) { ++ dev_info(ir->dev, "failed to get features\n"); ++ goto out; ++ } ++ ++out: ++ return rc; ++} ++ ++static int iguanair_receiver(struct iguanair *ir, bool enable) ++{ ++ int rc; ++ ++ ir->packet->header.start = 0; ++ ir->packet->header.direction = DIR_OUT; ++ ir->packet->header.cmd = enable ? CMD_RECEIVER_ON : CMD_RECEIVER_OFF; ++ ++ if (enable) ++ ir_raw_event_reset(ir->rc); ++ ++ rc = iguanair_send(ir, sizeof(ir->packet->header)); ++ ++ return rc; ++} ++ ++/* ++ * The iguana ir creates the carrier by busy spinning after each pulse or ++ * space. This is counted in CPU cycles, with the CPU running at 24MHz. It is ++ * broken down into 7-cycles and 4-cyles delays, with a preference for ++ * 4-cycle delays. ++ */ ++static int iguanair_set_tx_carrier(struct rc_dev *dev, uint32_t carrier) ++{ ++ struct iguanair *ir = dev->priv; ++ ++ if (carrier < 25000 || carrier > 150000) ++ return -EINVAL; ++ ++ mutex_lock(&ir->lock); ++ ++ if (carrier != ir->carrier) { ++ uint32_t cycles, fours, sevens; ++ ++ ir->carrier = carrier; ++ ++ cycles = DIV_ROUND_CLOSEST(24000000, carrier * 2) - ++ ir->cycle_overhead; ++ ++ /* make up the the remainer of 4-cycle blocks */ ++ switch (cycles & 3) { ++ case 0: ++ sevens = 0; ++ break; ++ case 1: ++ sevens = 3; ++ break; ++ case 2: ++ sevens = 2; ++ break; ++ case 3: ++ sevens = 1; ++ break; ++ } ++ ++ fours = (cycles - sevens * 7) / 4; ++ ++ /* magic happens here */ ++ ir->packet->busy7 = (4 - sevens) * 2; ++ ir->packet->busy4 = 110 - fours; ++ } ++ ++ mutex_unlock(&ir->lock); ++ ++ return carrier; ++} ++ ++static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask) ++{ ++ struct iguanair *ir = dev->priv; ++ ++ if (mask > 15) ++ return 4; ++ ++ mutex_lock(&ir->lock); ++ ir->packet->channels = mask << 4; ++ mutex_unlock(&ir->lock); ++ ++ return 0; ++} ++ ++static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) ++{ ++ struct iguanair *ir = dev->priv; ++ uint8_t space; ++ unsigned i, size, periods, bytes; ++ int rc; ++ ++ mutex_lock(&ir->lock); ++ ++ /* convert from us to carrier periods */ ++ for (i = space = size = 0; i < count; i++) { ++ periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); ++ bytes = DIV_ROUND_UP(periods, 127); ++ if (size + bytes > ir->bufsize) { ++ count = i; ++ break; ++ } ++ while (periods > 127) { ++ ir->packet->payload[size++] = 127 | space; ++ periods -= 127; ++ } ++ ++ ir->packet->payload[size++] = periods | space; ++ space ^= 0x80; ++ } ++ ++ if (count == 0) { ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ ir->packet->header.start = 0; ++ ir->packet->header.direction = DIR_OUT; ++ ir->packet->header.cmd = CMD_SEND; ++ ir->packet->length = size; ++ ++ ir->tx_overflow = false; ++ ++ rc = iguanair_send(ir, sizeof(*ir->packet) + size); ++ ++ if (rc == 0 && ir->tx_overflow) ++ rc = -EOVERFLOW; ++ ++out: ++ mutex_unlock(&ir->lock); ++ ++ return rc ? rc : count; ++} ++ ++static int iguanair_open(struct rc_dev *rdev) ++{ ++ struct iguanair *ir = rdev->priv; ++ int rc; ++ ++ mutex_lock(&ir->lock); ++ ++ rc = iguanair_receiver(ir, true); ++ if (rc == 0) ++ ir->receiver_on = true; ++ ++ mutex_unlock(&ir->lock); ++ ++ return rc; ++} ++ ++static void iguanair_close(struct rc_dev *rdev) ++{ ++ struct iguanair *ir = rdev->priv; ++ int rc; ++ ++ mutex_lock(&ir->lock); ++ ++ rc = iguanair_receiver(ir, false); ++ ir->receiver_on = false; ++ if (rc && rc != -ENODEV) ++ dev_warn(ir->dev, "failed to disable receiver: %d\n", rc); ++ ++ mutex_unlock(&ir->lock); ++} ++ ++static int __devinit iguanair_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ struct usb_device *udev = interface_to_usbdev(intf); ++ struct iguanair *ir; ++ struct rc_dev *rc; ++ int ret, pipein, pipeout; ++ struct usb_host_interface *idesc; ++ ++ ir = kzalloc(sizeof(*ir), GFP_KERNEL); ++ rc = rc_allocate_device(); ++ if (!ir || !rc) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ir->buf_in = usb_alloc_coherent(udev, MAX_IN_PACKET, GFP_KERNEL, ++ &ir->dma_in); ++ ir->packet = usb_alloc_coherent(udev, MAX_OUT_PACKET, GFP_KERNEL, ++ &ir->dma_out); ++ ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); ++ ir->urb_out = usb_alloc_urb(0, GFP_KERNEL); ++ ++ if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ idesc = intf->altsetting; ++ ++ if (idesc->desc.bNumEndpoints < 2) { ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ ir->rc = rc; ++ ir->dev = &intf->dev; ++ ir->udev = udev; ++ mutex_init(&ir->lock); ++ ++ init_completion(&ir->completion); ++ pipeout = usb_sndintpipe(udev, ++ idesc->endpoint[1].desc.bEndpointAddress); ++ usb_fill_int_urb(ir->urb_out, udev, pipeout, ir->packet, MAX_OUT_PACKET, ++ iguanair_irq_out, ir, 1); ++ ir->urb_out->transfer_dma = ir->dma_out; ++ ir->urb_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; ++ ++ pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress); ++ usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_IN_PACKET, ++ iguanair_rx, ir, 1); ++ ir->urb_in->transfer_dma = ir->dma_in; ++ ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; ++ ++ ret = usb_submit_urb(ir->urb_in, GFP_KERNEL); ++ if (ret) { ++ dev_warn(&intf->dev, "failed to submit urb: %d\n", ret); ++ goto out; ++ } ++ ++ ret = iguanair_get_features(ir); ++ if (ret) ++ goto out2; ++ ++ snprintf(ir->name, sizeof(ir->name), ++ "IguanaWorks USB IR Transceiver version 0x%04x", ir->version); ++ ++ usb_make_path(ir->udev, ir->phys, sizeof(ir->phys)); ++ ++ rc->input_name = ir->name; ++ rc->input_phys = ir->phys; ++ usb_to_input_id(ir->udev, &rc->input_id); ++ rc->dev.parent = &intf->dev; ++ rc->driver_type = RC_DRIVER_IR_RAW; ++ rc->allowed_protos = RC_TYPE_ALL; ++ rc->priv = ir; ++ rc->open = iguanair_open; ++ rc->close = iguanair_close; ++ rc->s_tx_mask = iguanair_set_tx_mask; ++ rc->s_tx_carrier = iguanair_set_tx_carrier; ++ rc->tx_ir = iguanair_tx; ++ rc->driver_name = DRIVER_NAME; ++ rc->map_name = RC_MAP_RC6_MCE; ++ rc->timeout = MS_TO_NS(100); ++ rc->rx_resolution = RX_RESOLUTION; ++ ++ iguanair_set_tx_carrier(rc, 38000); ++ ++ ret = rc_register_device(rc); ++ if (ret < 0) { ++ dev_err(&intf->dev, "failed to register rc device %d", ret); ++ goto out2; ++ } ++ ++ usb_set_intfdata(intf, ir); ++ ++ return 0; ++out2: ++ usb_kill_urb(ir->urb_in); ++ usb_kill_urb(ir->urb_out); ++out: ++ if (ir) { ++ usb_free_urb(ir->urb_in); ++ usb_free_urb(ir->urb_out); ++ usb_free_coherent(udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in); ++ usb_free_coherent(udev, MAX_OUT_PACKET, ir->packet, ++ ir->dma_out); ++ } ++ rc_free_device(rc); ++ kfree(ir); ++ return ret; ++} ++ ++static void __devexit iguanair_disconnect(struct usb_interface *intf) ++{ ++ struct iguanair *ir = usb_get_intfdata(intf); ++ ++ rc_unregister_device(ir->rc); ++ usb_set_intfdata(intf, NULL); ++ usb_kill_urb(ir->urb_in); ++ usb_kill_urb(ir->urb_out); ++ usb_free_urb(ir->urb_in); ++ usb_free_urb(ir->urb_out); ++ usb_free_coherent(ir->udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in); ++ usb_free_coherent(ir->udev, MAX_OUT_PACKET, ir->packet, ir->dma_out); ++ kfree(ir); ++} ++ ++static int iguanair_suspend(struct usb_interface *intf, pm_message_t message) ++{ ++ struct iguanair *ir = usb_get_intfdata(intf); ++ int rc = 0; ++ ++ mutex_lock(&ir->lock); ++ ++ if (ir->receiver_on) { ++ rc = iguanair_receiver(ir, false); ++ if (rc) ++ dev_warn(ir->dev, "failed to disable receiver for suspend\n"); ++ } ++ ++ usb_kill_urb(ir->urb_in); ++ usb_kill_urb(ir->urb_out); ++ ++ mutex_unlock(&ir->lock); ++ ++ return rc; ++} ++ ++static int iguanair_resume(struct usb_interface *intf) ++{ ++ struct iguanair *ir = usb_get_intfdata(intf); ++ int rc = 0; ++ ++ mutex_lock(&ir->lock); ++ ++ rc = usb_submit_urb(ir->urb_in, GFP_KERNEL); ++ if (rc) ++ dev_warn(&intf->dev, "failed to submit urb: %d\n", rc); ++ ++ if (ir->receiver_on) { ++ rc = iguanair_receiver(ir, true); ++ if (rc) ++ dev_warn(ir->dev, "failed to enable receiver after resume\n"); ++ } ++ ++ mutex_unlock(&ir->lock); ++ ++ return rc; ++} ++ ++static const struct usb_device_id iguanair_table[] = { ++ { USB_DEVICE(0x1781, 0x0938) }, ++ { } ++}; ++ ++static struct usb_driver iguanair_driver = { ++ .name = DRIVER_NAME, ++ .probe = iguanair_probe, ++ .disconnect = __devexit_p(iguanair_disconnect), ++ .suspend = iguanair_suspend, ++ .resume = iguanair_resume, ++ .reset_resume = iguanair_resume, ++ .id_table = iguanair_table, ++ .soft_unbind = 1 /* we want to disable receiver on unbind */ ++}; ++ ++module_usb_driver(iguanair_driver); ++ ++MODULE_DESCRIPTION("IguanaWorks USB IR Transceiver"); ++MODULE_AUTHOR("Sean Young "); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(usb, iguanair_table); ++ +diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c +index 5939021..1a69a24 100644 +--- a/drivers/media/video/bt8xx/bttv-cards.c ++++ b/drivers/media/video/bt8xx/bttv-cards.c +@@ -3766,10 +3766,8 @@ static int __devinit pvr_boot(struct bttv *btv) + int rc; + + rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev); +- if (rc != 0) { +- pr_warn("%d: no altera firmware [via hotplug]\n", btv->c.nr); ++ if (rc != 0) + return rc; +- } + rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size); + pr_info("%d: altera firmware upload %s\n", + btv->c.nr, (rc < 0) ? "failed" : "ok"); +diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c +index ee91e295..ce897e1 100644 +--- a/drivers/media/video/cpia2/cpia2_core.c ++++ b/drivers/media/video/cpia2/cpia2_core.c +@@ -905,11 +905,8 @@ static int apply_vp_patch(struct camera_data *cam) + struct cpia2_command cmd; + + ret = request_firmware(&fw, fw_name, &cam->dev->dev); +- if (ret) { +- printk(KERN_ERR "cpia2: failed to load VP patch \"%s\"\n", +- fw_name); ++ if (ret) + return ret; +- } + + cmd.req_mode = CAMERAACCESS_TYPE_REPEAT | CAMERAACCESS_VP; + cmd.direction = TRANSFER_WRITE; +diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c +index 280aa4d..d30f06e 100644 +--- a/drivers/media/video/cx18/cx18-av-firmware.c ++++ b/drivers/media/video/cx18/cx18-av-firmware.c +@@ -85,10 +85,8 @@ int cx18_av_loadfw(struct cx18 *cx) + int i; + int retries1 = 0; + +- if (request_firmware(&fw, FWFILE, &cx->pci_dev->dev) != 0) { +- CX18_ERR_DEV(sd, "unable to open firmware %s\n", FWFILE); ++ if (request_firmware(&fw, FWFILE, &cx->pci_dev->dev) != 0) + return -EINVAL; +- } + + /* The firmware load often has byte errors, so allow for several + retries, both at byte level and at the firmware load level. */ +diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c +index f41922b..4684be4 100644 +--- a/drivers/media/video/cx18/cx18-dvb.c ++++ b/drivers/media/video/cx18/cx18-dvb.c +@@ -139,9 +139,7 @@ static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream, + int ret; + + ret = request_firmware(fw, fn, &cx->pci_dev->dev); +- if (ret) +- CX18_ERR("Unable to open firmware file %s\n", fn); +- else { ++ if (!ret) { + size_t sz = (*fw)->size; + if (sz < 2 || sz > 64 || (sz % 2) != 0) { + CX18_ERR("Firmware %s has a bad size: %lu bytes\n", +@@ -154,7 +152,7 @@ static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream, + + if (ret) { + CX18_ERR("The MPC718 board variant with the MT352 DVB-T" +- "demodualtor will not work without it\n"); ++ "demodulator will not work without firmware\n"); + CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware " + "mpc718' if you need the firmware\n"); + } +diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c +index 1b3fb50..5eccf1f 100644 +--- a/drivers/media/video/cx18/cx18-firmware.c ++++ b/drivers/media/video/cx18/cx18-firmware.c +@@ -106,11 +106,8 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx) + u32 __iomem *dst = (u32 __iomem *)mem; + const u32 *src; + +- if (request_firmware(&fw, fn, &cx->pci_dev->dev)) { +- CX18_ERR("Unable to open firmware %s\n", fn); +- CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n"); ++ if (request_firmware(&fw, fn, &cx->pci_dev->dev)) + return -ENOMEM; +- } + + src = (const u32 *)fw->data; + +@@ -151,8 +148,6 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx, + int sz; + + if (request_firmware(&fw, fn, &cx->pci_dev->dev)) { +- CX18_ERR("unable to open firmware %s\n", fn); +- CX18_ERR("did you put the firmware in the hotplug firmware directory?\n"); + cx18_setup_page(cx, 0); + return -ENOMEM; + } +diff --git a/drivers/media/video/cx231xx/cx231xx-417.c b/drivers/media/video/cx231xx/cx231xx-417.c +index f8f0e59..6ded90b 100644 +--- a/drivers/media/video/cx231xx/cx231xx-417.c ++++ b/drivers/media/video/cx231xx/cx231xx-417.c +@@ -979,14 +979,8 @@ static int cx231xx_load_firmware(struct cx231xx *dev) + retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME, + &dev->udev->dev); + +- if (retval != 0) { +- printk(KERN_ERR +- "ERROR: Hotplug firmware request failed (%s).\n", +- CX231xx_FIRM_IMAGE_NAME); +- printk(KERN_ERR "Please fix your hotplug setup, the board will " +- "not work without firmware loaded!\n"); ++ if (retval != 0) + return -1; +- } + + if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) { + printk(KERN_ERR "ERROR: Firmware size mismatch " +diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c +index 67c4a59..630b55e 100644 +--- a/drivers/media/video/cx23885/cx23885-417.c ++++ b/drivers/media/video/cx23885/cx23885-417.c +@@ -929,14 +929,8 @@ static int cx23885_load_firmware(struct cx23885_dev *dev) + retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME, + &dev->pci->dev); + +- if (retval != 0) { +- printk(KERN_ERR +- "ERROR: Hotplug firmware request failed (%s).\n", +- CX23885_FIRM_IMAGE_NAME); +- printk(KERN_ERR "Please fix your hotplug setup, the board will " +- "not work without firmware loaded!\n"); ++ if (retval != 0) + return -1; +- } + + if (firmware->size != CX23885_FIRM_IMAGE_SIZE) { + printk(KERN_ERR "ERROR: Firmware size mismatch " +diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c +index c3cf089..78f197d 100644 +--- a/drivers/media/video/cx23885/cx23885-cards.c ++++ b/drivers/media/video/cx23885/cx23885-cards.c +@@ -1513,11 +1513,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) + cinfo.rev, filename); + + ret = request_firmware(&fw, filename, &dev->pci->dev); +- if (ret != 0) +- printk(KERN_ERR "did not find the firmware file. (%s) " +- "Please see linux/Documentation/dvb/ for more details " +- "on firmware-problems.", filename); +- else ++ if (ret == 0) + altera_init(&netup_config, fw); + + release_firmware(fw); +diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c +index 8150200..ebb6a68 100644 +--- a/drivers/media/video/cx25840/cx25840-firmware.c ++++ b/drivers/media/video/cx25840/cx25840-firmware.c +@@ -123,10 +123,8 @@ int cx25840_loadfw(struct i2c_client *client) + MAX_BUF_SIZE = 16; /* cx231xx cannot accept more than 16 bytes at a time */ + } + +- if (request_firmware(&fw, fwname, FWDEV(client)) != 0) { +- v4l_err(client, "unable to open firmware %s\n", fwname); ++ if (request_firmware(&fw, fwname, FWDEV(client)) != 0) + return -EINVAL; +- } + + start_fw_load(client); + +diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c +index e46446a..1acb2f2 100644 +--- a/drivers/media/video/cx88/cx88-blackbird.c ++++ b/drivers/media/video/cx88/cx88-blackbird.c +@@ -446,13 +446,8 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) + &dev->pci->dev); + + +- if (retval != 0) { +- dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n", +- CX2341X_FIRM_ENC_FILENAME); +- dprintk(0, "Please fix your hotplug setup, the board will " +- "not work without firmware loaded!\n"); ++ if (retval != 0) + return -1; +- } + + if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) { + dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n", +diff --git a/drivers/media/video/gspca/vicam.c b/drivers/media/video/gspca/vicam.c +index 81dd4c9..c430106 100644 +--- a/drivers/media/video/gspca/vicam.c ++++ b/drivers/media/video/gspca/vicam.c +@@ -270,10 +270,8 @@ static int sd_init(struct gspca_dev *gspca_dev) + + ret = request_ihex_firmware(&fw, "vicam/firmware.fw", + &gspca_dev->dev->dev); +- if (ret) { +- pr_err("Failed to load \"vicam/firmware.fw\": %d\n", ret); ++ if (ret) + return ret; +- } + + firmware_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!firmware_buf) { +diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c +index 02c5ade..279879b 100644 +--- a/drivers/media/video/ivtv/ivtv-firmware.c ++++ b/drivers/media/video/ivtv/ivtv-firmware.c +@@ -80,8 +80,6 @@ retry: + release_firmware(fw); + return size; + } +- IVTV_ERR("Unable to open firmware %s (must be %ld bytes)\n", fn, size); +- IVTV_ERR("Did you put the firmware in the hotplug firmware directory?\n"); + return -ENOMEM; + } + +diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c +index 122b457..a6bc93e 100644 +--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c ++++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c +@@ -1415,29 +1415,6 @@ static int pvr2_locate_firmware(struct pvr2_hdw *hdw, + "request_firmware fatal error with code=%d",ret); + return ret; + } +- pvr2_trace(PVR2_TRACE_ERROR_LEGS, +- "***WARNING***" +- " Device %s firmware" +- " seems to be missing.", +- fwtypename); +- pvr2_trace(PVR2_TRACE_ERROR_LEGS, +- "Did you install the pvrusb2 firmware files" +- " in their proper location?"); +- if (fwcount == 1) { +- pvr2_trace(PVR2_TRACE_ERROR_LEGS, +- "request_firmware unable to locate %s file %s", +- fwtypename,fwnames[0]); +- } else { +- pvr2_trace(PVR2_TRACE_ERROR_LEGS, +- "request_firmware unable to locate" +- " one of the following %s files:", +- fwtypename); +- for (idx = 0; idx < fwcount; idx++) { +- pvr2_trace(PVR2_TRACE_ERROR_LEGS, +- "request_firmware: Failed to find %s", +- fwnames[idx]); +- } +- } + return ret; + } + +diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c +index 803c9c8..3086022 100644 +--- a/drivers/media/video/s2255drv.c ++++ b/drivers/media/video/s2255drv.c +@@ -2588,10 +2588,8 @@ static int s2255_probe(struct usb_interface *interface, + } + /* load the first chunk */ + if (request_firmware(&dev->fw_data->fw, +- FIRMWARE_FILE_NAME, &dev->udev->dev)) { +- printk(KERN_ERR "sensoray 2255 failed to get firmware\n"); ++ FIRMWARE_FILE_NAME, &dev->udev->dev)) + goto errorREQFW; +- } + /* check the firmware is valid */ + fw_size = dev->fw_data->fw->size; + pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8]; +diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c +index f2481a8..e7d1ce7 100644 +--- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c ++++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c +@@ -39,10 +39,8 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) + mfc_debug_enter(); + err = request_firmware((const struct firmware **)&fw_blob, + "s5p-mfc.fw", dev->v4l2_dev.dev); +- if (err != 0) { +- mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); ++ if (err != 0) + return -EINVAL; +- } + dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN); + if (s5p_mfc_bitproc_buf) { + mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n"); +@@ -117,10 +115,8 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev) + mfc_debug_enter(); + err = request_firmware((const struct firmware **)&fw_blob, + "s5p-mfc.fw", dev->v4l2_dev.dev); +- if (err != 0) { +- mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); ++ if (err != 0) + return -EINVAL; +- } + if (fw_blob->size > dev->fw_size) { + mfc_err("MFC firmware is too big to be loaded\n"); + release_firmware(fw_blob); +diff --git a/drivers/media/video/saa7164/saa7164-fw.c b/drivers/media/video/saa7164/saa7164-fw.c +index a266bf0..8d56779 100644 +--- a/drivers/media/video/saa7164/saa7164-fw.c ++++ b/drivers/media/video/saa7164/saa7164-fw.c +@@ -420,11 +420,8 @@ int saa7164_downloadfirmware(struct saa7164_dev *dev) + __func__, fwname); + + ret = request_firmware(&fw, fwname, &dev->pci->dev); +- if (ret) { +- printk(KERN_ERR "%s() Upload failed. " +- "(file not found?)\n", __func__); ++ if (ret) + return -ENOMEM; +- } + + printk(KERN_INFO "%s() firmware read %Zu bytes.\n", + __func__, fw->size); +diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c +index 129f135..ed3ed9b 100644 +--- a/drivers/media/video/tlg2300/pd-main.c ++++ b/drivers/media/video/tlg2300/pd-main.c +@@ -219,10 +219,8 @@ static int firmware_download(struct usb_device *udev) + size_t max_packet_size; + + ret = request_firmware(&fw, firmware_name, &udev->dev); +- if (ret) { +- log("download err : %d", ret); ++ if (ret) + return ret; +- } + + fwlength = fw->size; + +diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c +index ea1169b..753d6ef 100644 +--- a/drivers/mfd/lpc_sch.c ++++ b/drivers/mfd/lpc_sch.c +@@ -36,6 +36,7 @@ + + #define GPIOBASE 0x44 + #define GPIO_IO_SIZE 64 ++#define GPIO_IO_SIZE_CENTERTON 128 + + #define WDTBASE 0x84 + #define WDT_IO_SIZE 64 +@@ -44,39 +45,41 @@ static struct resource smbus_sch_resource = { + .flags = IORESOURCE_IO, + }; + +- + static struct resource gpio_sch_resource = { + .flags = IORESOURCE_IO, + }; + +-static struct mfd_cell lpc_sch_cells[] = { +- { +- .name = "isch_smbus", +- .num_resources = 1, +- .resources = &smbus_sch_resource, +- }, +- { +- .name = "sch_gpio", +- .num_resources = 1, +- .resources = &gpio_sch_resource, +- }, +-}; +- + static struct resource wdt_sch_resource = { + .flags = IORESOURCE_IO, + }; + +-static struct mfd_cell tunnelcreek_cells[] = { +- { +- .name = "tunnelcreek_wdt", +- .num_resources = 1, +- .resources = &wdt_sch_resource, +- }, ++static struct mfd_cell lpc_sch_cells[3]; ++ ++static struct mfd_cell isch_smbus_cell = { ++ .name = "isch_smbus", ++ .num_resources = 1, ++ .resources = &smbus_sch_resource, ++ .ignore_resource_conflicts = true, + }; + +-static struct pci_device_id lpc_sch_ids[] = { ++static struct mfd_cell sch_gpio_cell = { ++ .name = "sch_gpio", ++ .num_resources = 1, ++ .resources = &gpio_sch_resource, ++ .ignore_resource_conflicts = true, ++}; ++ ++static struct mfd_cell wdt_sch_cell = { ++ .name = "ie6xx_wdt", ++ .num_resources = 1, ++ .resources = &wdt_sch_resource, ++ .ignore_resource_conflicts = true, ++}; ++ ++static const struct pci_device_id lpc_sch_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CENTERTON_ILB) }, + { 0, } + }; + MODULE_DEVICE_TABLE(pci, lpc_sch_ids); +@@ -86,72 +89,76 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, + { + unsigned int base_addr_cfg; + unsigned short base_addr; +- int i; ++ int i, cells = 0; + int ret; + + pci_read_config_dword(dev, SMBASE, &base_addr_cfg); +- if (!(base_addr_cfg & (1 << 31))) { +- dev_err(&dev->dev, "Decode of the SMBus I/O range disabled\n"); +- return -ENODEV; ++ base_addr = 0; ++ if (!(base_addr_cfg & (1 << 31))) ++ dev_warn(&dev->dev, "Decode of the SMBus I/O range disabled\n"); ++ else ++ base_addr = (unsigned short)base_addr_cfg; ++ ++ if (base_addr == 0) { ++ dev_warn(&dev->dev, "I/O space for SMBus uninitialized\n"); ++ } else { ++ lpc_sch_cells[cells++] = isch_smbus_cell; ++ smbus_sch_resource.start = base_addr; ++ smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1; + } +- base_addr = (unsigned short)base_addr_cfg; ++ ++ pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg); ++ base_addr = 0; ++ if (!(base_addr_cfg & (1 << 31))) ++ dev_warn(&dev->dev, "Decode of the GPIO I/O range disabled\n"); ++ else ++ base_addr = (unsigned short)base_addr_cfg; ++ + if (base_addr == 0) { +- dev_err(&dev->dev, "I/O space for SMBus uninitialized\n"); +- return -ENODEV; ++ dev_warn(&dev->dev, "I/O space for GPIO uninitialized\n"); ++ } else { ++ lpc_sch_cells[cells++] = sch_gpio_cell; ++ gpio_sch_resource.start = base_addr; ++ if (id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) ++ gpio_sch_resource.end = base_addr + GPIO_IO_SIZE_CENTERTON - 1; ++ else ++ gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1; + } + +- smbus_sch_resource.start = base_addr; +- smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1; ++ if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC ++ || id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) { ++ pci_read_config_dword(dev, WDTBASE, &base_addr_cfg); ++ base_addr = 0; ++ if (!(base_addr_cfg & (1 << 31))) ++ dev_warn(&dev->dev, "Decode of the WDT I/O range disabled\n"); ++ else ++ base_addr = (unsigned short)base_addr_cfg; ++ if (base_addr == 0) ++ dev_warn(&dev->dev, "I/O space for WDT uninitialized\n"); ++ else { ++ lpc_sch_cells[cells++] = wdt_sch_cell; ++ wdt_sch_resource.start = base_addr; ++ wdt_sch_resource.end = base_addr + WDT_IO_SIZE - 1; ++ } ++ } + +- pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg); +- if (!(base_addr_cfg & (1 << 31))) { +- dev_err(&dev->dev, "Decode of the GPIO I/O range disabled\n"); ++ if (WARN_ON(cells > ARRAY_SIZE(lpc_sch_cells))) { ++ dev_err(&dev->dev, "Cell count exceeds array size"); + return -ENODEV; + } +- base_addr = (unsigned short)base_addr_cfg; +- if (base_addr == 0) { +- dev_err(&dev->dev, "I/O space for GPIO uninitialized\n"); ++ ++ if (cells == 0) { ++ dev_err(&dev->dev, "All decode registers disabled.\n"); + return -ENODEV; + } + +- gpio_sch_resource.start = base_addr; +- gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1; +- +- for (i=0; i < ARRAY_SIZE(lpc_sch_cells); i++) ++ for (i = 0; i < cells; i++) + lpc_sch_cells[i].id = id->device; + +- ret = mfd_add_devices(&dev->dev, 0, +- lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0); ++ ret = mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0); + if (ret) +- goto out_dev; ++ mfd_remove_devices(&dev->dev); + +- if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC) { +- pci_read_config_dword(dev, WDTBASE, &base_addr_cfg); +- if (!(base_addr_cfg & (1 << 31))) { +- dev_err(&dev->dev, "Decode of the WDT I/O range disabled\n"); +- ret = -ENODEV; +- goto out_dev; +- } +- base_addr = (unsigned short)base_addr_cfg; +- if (base_addr == 0) { +- dev_err(&dev->dev, "I/O space for WDT uninitialized\n"); +- ret = -ENODEV; +- goto out_dev; +- } +- +- wdt_sch_resource.start = base_addr; +- wdt_sch_resource.end = base_addr + WDT_IO_SIZE - 1; +- +- for (i = 0; i < ARRAY_SIZE(tunnelcreek_cells); i++) +- tunnelcreek_cells[i].id = id->device; +- +- ret = mfd_add_devices(&dev->dev, 0, tunnelcreek_cells, +- ARRAY_SIZE(tunnelcreek_cells), NULL, 0); +- } +- +- return ret; +-out_dev: +- mfd_remove_devices(&dev->dev); + return ret; + } + +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 5664696..92525a2 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -500,6 +500,55 @@ config USB_SWITCH_FSA9480 + stereo and mono audio, video, microphone and UART data to use + a common connector port. + ++config EARLY_DMA_ALLOC ++ bool "Early DMA Memory Allocator" ++ depends on HAS_DMA ++ ++ ---help--- ++ This driver locks down a region of DMA accessible memory ++ early in the boot process. This memory can be used by other ++ drivers that might rmmod/insmod, insuring the memory region ++ does not become fragmented. ++ ++config EDA_DEF_SIZE ++ hex "EDA Default Region Size" ++ depends on EARLY_DMA_ALLOC ++ default 0x04000000 ++ help ++ Default size of the reserved memory pool, if not altered by the ++ open firmware interface or kernel boot parameter. This memory ++ will not be accessable to the rest of the system. Default is ++ 64MB. ++ ++config EDA_DEF_ALIGN ++ hex "EDA Default Alignment" ++ depends on EARLY_DMA_ALLOC ++ default 0x00100000 ++ help ++ Default alignment of the memory region. Default is 1MB. ++ ++config RETIMER_CLASS ++ tristate "Retimer Class support" ++ depends on SYSFS ++ depends on OF ++ default y ++ help ++ Creates a hardware class in sysfs called "retimer_dev", ++ providing a common place to register RETIMER devices. ++ ++ This support can also be built as a module. If so, the module ++ will be called retimer_class. ++ ++config DS100DF410 ++ tristate "DS100DF410 Low Power 10GbE Quad Channel Retimer" ++ depends on I2C && SYSFS ++ help ++ If you say yes here you get support for the DS100DF410 ++ Low Power 10GbE Quad Channel Retimer. ++ ++ This driver can also be built as a module. If so, the module ++ will be called ds100df410. ++ + source "drivers/misc/c2port/Kconfig" + source "drivers/misc/eeprom/Kconfig" + source "drivers/misc/cb710/Kconfig" +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index b26495a..ad70876 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -48,3 +48,6 @@ obj-y += lis3lv02d/ + obj-y += carma/ + obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o + obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ ++obj-$(CONFIG_EARLY_DMA_ALLOC) += early_dma_alloc.o ++obj-$(CONFIG_RETIMER_CLASS) += retimer_class.o ++obj-$(CONFIG_DS100DF410) += ds100df410.o +diff --git a/drivers/misc/ds100df410.c b/drivers/misc/ds100df410.c +new file mode 100644 +index 0000000..d46d107 +--- /dev/null ++++ b/drivers/misc/ds100df410.c +@@ -0,0 +1,326 @@ ++/* ++ * ds100df410.c - I2c client driver to manage DS100DF410 ++ * DS100DF410 Low Power 10GbE Quad Channel Retimer ++ * ++ * Copyright (C) 2014 Cumulus Networks, Inc. ++ * Author: Puneet Shenoy ++ * ++ * Ideas and structure regarding introducing the class device graciously borrowed ++ * from the eeprom sysfs/class support by: ++ * Copyright (C) 2013 CumulusNetworks, Inc. ++ * Author: Curt Brune ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_RETIMER_CLASS ++#include ++#endif ++ ++#define DS100DF410_DRV_NAME "ds100df410" ++#define DRIVER_VERSION "1.0" ++ ++#define DS100DF410_RESET_REG 0x00 ++#define DS100DF410_OVERRIDE_REG 0x09 ++#define DS100DF410_CDR_RST_REG 0x0a ++#define DS100DF410_TAP_DEM_REG 0x15 ++#define DS100DF410_PFD_PRBS_DFE_REG 0x1e ++#define DS100DF410_DRV_SEL_VOD_REG 0x2d ++#define DS100DF410_ADAPT_EQ_SM_REG 0x31 ++#define DS100DF410_VEO_CLK_CDR_CAP_REG 0x36 ++#define DS100DF410_CHANNELS_REG 0xff ++ ++struct ds100df410_data { ++ struct i2c_client *client; ++ ++#ifdef CONFIG_RETIMER_CLASS ++ struct device *retimer_dev; ++#endif ++ struct mutex lock; ++}; ++ ++static u32 ds100df410_read(struct device *dev, u8 reg, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ u32 ret = i2c_smbus_read_byte_data(client, reg); ++ ++ return sprintf(buf, "%d\n", ret); ++} ++ ++static u32 ds100df410_write(struct device *dev, u8 reg, const char *buf, ++ size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ unsigned long val; ++ int ret; ++ ++ if (strict_strtoul(buf, 0, &val) < 0) ++ return -EINVAL; ++ ++ ret = i2c_smbus_write_byte_data(client, reg, (u8)val); ++ if (ret < 0) ++ return ret; ++ ++ return count; ++} ++ ++static ssize_t ds100df410_show_cdr_rst(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_CDR_RST_REG, buf); ++} ++ ++static ssize_t ds100df410_store_cdr_rst(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_CDR_RST_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_tap_dem(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_TAP_DEM_REG, buf); ++} ++ ++static ssize_t ds100df410_store_tap_dem(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_TAP_DEM_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_pfd_prbs_dfe(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_PFD_PRBS_DFE_REG, buf); ++} ++ ++static ssize_t ds100df410_store_pfd_prbs_dfe(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_PFD_PRBS_DFE_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_drv_sel_vod(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_DRV_SEL_VOD_REG, buf); ++} ++ ++static ssize_t ds100df410_store_drv_sel_vod(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_DRV_SEL_VOD_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_adapt_eq_sm(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_ADAPT_EQ_SM_REG, buf); ++} ++ ++static ssize_t ds100df410_store_adapt_eq_sm(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_ADAPT_EQ_SM_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_veo_clk_cdr_cap(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_VEO_CLK_CDR_CAP_REG, buf); ++} ++ ++static ssize_t ds100df410_store_veo_clk_cdr_cap(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_VEO_CLK_CDR_CAP_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_channels(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_CHANNELS_REG, buf); ++} ++ ++static ssize_t ds100df410_store_channels(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_CHANNELS_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_override(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_OVERRIDE_REG, buf); ++} ++ ++static ssize_t ds100df410_store_override(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_OVERRIDE_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_reset(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_RESET_REG, buf); ++} ++ ++static ssize_t ds100df410_store_reset(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_RESET_REG, buf, count); ++} ++ ++static DEVICE_ATTR(cdr_rst, S_IWUSR | S_IRUGO, ++ ds100df410_show_cdr_rst, ds100df410_store_cdr_rst); ++static DEVICE_ATTR(tap_dem, S_IWUSR | S_IRUGO, ++ ds100df410_show_tap_dem, ds100df410_store_tap_dem); ++static DEVICE_ATTR(pfd_prbs_dfe, S_IWUSR | S_IRUGO, ++ ds100df410_show_pfd_prbs_dfe, ds100df410_store_pfd_prbs_dfe); ++static DEVICE_ATTR(drv_sel_vod, S_IWUSR | S_IRUGO, ++ ds100df410_show_drv_sel_vod, ds100df410_store_drv_sel_vod); ++static DEVICE_ATTR(adapt_eq_sm, S_IWUSR | S_IRUGO, ++ ds100df410_show_adapt_eq_sm, ds100df410_store_adapt_eq_sm); ++static DEVICE_ATTR(veo_clk_cdr_cap, S_IWUSR | S_IRUGO, ++ ds100df410_show_veo_clk_cdr_cap, ++ ds100df410_store_veo_clk_cdr_cap); ++static DEVICE_ATTR(channels, S_IWUSR | S_IRUGO, ++ ds100df410_show_channels, ds100df410_store_channels); ++static DEVICE_ATTR(override, S_IWUSR | S_IRUGO, ++ ds100df410_show_override, ds100df410_store_override); ++static DEVICE_ATTR(reset, S_IWUSR | S_IRUGO, ++ ds100df410_show_reset, ds100df410_store_reset); ++ ++static struct attribute *ds100df410_attributes[] = { ++ &dev_attr_cdr_rst.attr, ++ &dev_attr_tap_dem.attr, ++ &dev_attr_pfd_prbs_dfe.attr, ++ &dev_attr_drv_sel_vod.attr, ++ &dev_attr_adapt_eq_sm.attr, ++ &dev_attr_veo_clk_cdr_cap.attr, ++ &dev_attr_channels.attr, ++ &dev_attr_override.attr, ++ &dev_attr_reset.attr, ++ NULL ++}; ++ ++static const struct attribute_group ds100df410_attr_group = { ++ .attrs = ds100df410_attributes, ++}; ++ ++static int __devinit ds100df410_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); ++ struct ds100df410_data *data; ++ int err = 0; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) { ++ return -EIO; ++ } ++ ++ data = kzalloc(sizeof(struct ds100df410_data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ data->client = client; ++ mutex_init(&data->lock); ++ ++ /* register sysfs hooks */ ++ err = sysfs_create_group(&client->dev.kobj, &ds100df410_attr_group); ++ if (err) ++ goto exit_kfree; ++ ++ ++#ifdef CONFIG_RETIMER_CLASS ++ data->retimer_dev = retimer_device_register(&client->dev); ++ if (IS_ERR(data->retimer_dev)) { ++ dev_err(&client->dev, "error registering retimer device.\n"); ++ err = PTR_ERR(data->retimer_dev); ++ goto exit_kfree; ++ } ++#endif ++ ++ i2c_set_clientdata(client, data); ++ return 0; ++exit_kfree: ++ kfree(data); ++ return err; ++} ++ ++static int __devexit ds100df410_remove(struct i2c_client *client) ++{ ++ struct ds100df410_data *data; ++ ++ data = i2c_get_clientdata(client); ++ sysfs_remove_group(&client->dev.kobj, &ds100df410_attr_group); ++ ++#ifdef CONFIG_RETIMER_CLASS ++ retimer_device_unregister(data->retimer_dev); ++#endif ++ ++ kfree(data); ++ return 0; ++} ++ ++static const struct i2c_device_id ds100df410_id[] = { ++ { "ds100df410", 0 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, ds100df410_id); ++ ++static struct i2c_driver ds100df410_driver = { ++ .driver = { ++ .name = DS100DF410_DRV_NAME, ++ }, ++ .probe = ds100df410_probe, ++ .remove = __devexit_p(ds100df410_remove), ++ .id_table = ds100df410_id, ++}; ++ ++module_i2c_driver(ds100df410_driver); ++MODULE_AUTHOR("Puneet Shenoy "); ++MODULE_DESCRIPTION("I2C client for DS100DF410 10GE Quad Core Retimer"); ++MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(DRIVER_VERSION); +diff --git a/drivers/misc/early_dma_alloc.c b/drivers/misc/early_dma_alloc.c +new file mode 100644 +index 0000000..609a858 +--- /dev/null ++++ b/drivers/misc/early_dma_alloc.c +@@ -0,0 +1,223 @@ ++/* ++ * Early DMA Memory Allocator ++ * ++ * Copyright © 2013,2014 Cumulus Networks, Inc. ++ * ++ * Author: Curt Brune ++ * Modified: Jonathan Toppins ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++/* ++ * This driver allocates a region of DMA accessible memory, making it ++ * available to one other device driver. ++ * ++ * The client device driver may be unloaded and reloaded over time. ++ * This driver keeps the DMA region from becoming fragmented across ++ * module reloads. ++ * ++ * Memory Region Restrictions ++ * -------------------------- ++ * The memory region allocated by EDA MUST exist below a 4GB limit. This ++ * is because EDA's primary (only at time of writing) user is the ++ * Broadcom BDE driver wich assumes a 32-bit physical address space and ++ * assumes paddr is no more than 32-bits wide. Furthermore, before porting ++ * the BDE driver to use EDA the BDE driver specifically checked if the ++ * memory region provided by highmem was less than 4GB. We assume Broadcom ++ * knew what they were doing and there is a specific reason why this 4GB ++ * limit is needed, so we enforce this limit by checking the physical address ++ * after allocation. ++ * ++ * Memory Region Size and Alignment ++ * -------------------------------- ++ * This driver allows three ways for the user to define the DMA memory ++ * that will be created, listed in order of preference. ++ * 1. The user may specify on the kernel command line in the boot loader ++ * the "eda_mem" option, this option has the format "size@alignment", ++ * example: eda_mem=0x04000000@0x00100000 ++ * 2. This driver looks for a device tree node compatible with ++ * "early-dma-alloc". The "region_size" property of the node contains ++ * the size, in bytes, of the desired DMA memory region. The ++ * "alignment" property contains the desired memory alignment of the ++ * region. ++ * 3. Finally if neither of the above are provided the Kbuild changable, ++ * compiled in default size and alignment will be used. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if (!defined CONFIG_EDA_DEF_SIZE) || \ ++ (!defined CONFIG_EDA_DEF_ALIGN) ++#error incorrect kernel config - fix it ++#endif ++ ++// #define DEBUG ++#if (defined DEBUG) ++#define eda_debug(fmt, ... ) \ ++ printk(KERN_ERR "eda-debug:%s(): " fmt "\n", __func__ , \ ++ ##__VA_ARGS__) ++#else ++#define eda_debug(fmt, ... ) ++#endif ++ ++#define eda_info(fmt, ... ) \ ++ printk(KERN_INFO "eda: " fmt "\n", ##__VA_ARGS__) ++ ++static uint32_t dma_size; ++static void *dma_vaddr; ++static u32 dma_align __initdata; ++static bool eda_cmdline __initdata; ++ ++static int __init setup_eda_mem(char *str) ++{ ++ char *endp; ++ ++ dma_size = memparse(str, &endp) & PAGE_MASK; ++ if (*endp == '@') ++ dma_align = memparse(endp + 1, NULL) & PAGE_MASK; ++ eda_cmdline = true; ++ return 0; ++} ++early_param("eda_mem", setup_eda_mem); ++ ++static int __init of_eda_init(uint32_t *size, u32 *align) ++#ifdef CONFIG_OF_FLATTREE ++{ ++ int rc = -ENODEV; ++ struct device_node *np = NULL; ++ const u32 *region_sz_p = NULL; ++ const u32 *align_p = NULL; ++ u32 prop_sz = 0; ++ ++ eda_debug("entry"); ++ ++ /* is a programming error make it really painful so it gets fixed */ ++ BUG_ON(NULL == size || NULL == align); ++ ++ np = of_find_compatible_node(NULL, NULL, "early-dma-alloc"); ++ if (!np) { ++ printk(KERN_WARNING "WARN: Can not find `early-dma-alloc'" ++ " device tree node.\n"); ++ goto cleanup; ++ } ++ ++ region_sz_p = of_get_property(np, "region_size", &prop_sz); ++ if (!region_sz_p || (prop_sz != sizeof(*region_sz_p))) { ++ printk(KERN_ERR "ERROR: Can not find `region_size' property" ++ " in early-dma-alloc device tree node.\n"); ++ goto cleanup; ++ } ++ *size = *region_sz_p; ++ ++ align_p = of_get_property(np, "alignment", &prop_sz); ++ if (!align_p || (prop_sz != sizeof(*align_p))) { ++ printk(KERN_ERR "ERROR: Can not find `alignment' property in" ++ "early-dma-alloc device tree node.\n"); ++ goto cleanup; ++ } ++ *align = *align_p; ++ rc = 0; ++ ++ eda_debug("cleanup"); ++ ++cleanup: ++ of_node_put(np); ++ return rc; ++ ++} ++#else ++{ ++ return -ENODEV; ++} ++#endif ++ ++int eda_dma_info_get(void **vaddr, uint32_t *paddr, uint32_t *size) ++{ ++ eda_debug("entry"); ++ ++ if (!dma_vaddr) ++ return -ENOMEM; ++ ++ if (!vaddr || !paddr || !size) ++ return -EINVAL; ++ ++ *vaddr = dma_vaddr; ++ *paddr = (uint32_t) virt_to_phys(dma_vaddr); ++ *size = dma_size; ++ ++ eda_debug("returning -- dma_vaddr: 0x%pK, dma_paddr: 0x%08x," ++ " size: 0x%08x", *vaddr, *paddr, *size); ++ ++ return 0; ++} ++EXPORT_SYMBOL(eda_dma_info_get); ++ ++int __init eda_init(void) ++{ ++ int rc = 0; ++ ++ if (eda_cmdline) { ++ if (!dma_align) ++ dma_align = CONFIG_EDA_DEF_ALIGN; ++ if (!dma_size) ++ dma_size = CONFIG_EDA_DEF_SIZE; ++ eda_debug("size & alignment came from: kernel cmdline"); ++ } else if (!of_eda_init(&dma_size, &dma_align)) { ++ eda_debug("size & alignment came from: open firmware entry"); ++ } else { ++ dma_align = CONFIG_EDA_DEF_ALIGN; ++ dma_size = CONFIG_EDA_DEF_SIZE; ++ eda_debug("size & alignment came from: compiled in defaults"); ++ } ++ ++ dma_vaddr = __alloc_bootmem_low(dma_size, dma_align, 0); ++ /* ++ * enforce EDA's requirement to allocate the memory region below a ++ * 32-bit limit. ++ */ ++ if (virt_to_phys(dma_vaddr) > 0xFFFFFFFFULL) { ++ rc = -ENOMEM; ++ printk(KERN_ERR "ERROR: DMA memory beyond 32-bit address" ++ " space not supported.\n"); ++ goto cleanup; ++ } ++ ++ eda_info("dma_vaddr: 0x%pK, dma_paddr: 0x%016llx, size: 0x%08x," ++ " alignment: 0x%08x", ++ dma_vaddr, (unsigned long long) virt_to_phys(dma_vaddr), ++ dma_size, dma_align); ++cleanup: ++ if (rc && dma_vaddr) { ++ free_bootmem((unsigned long) dma_vaddr, dma_size); ++ } ++ if (rc) { ++ dma_vaddr = NULL; ++ dma_size = 0; ++ } ++ return rc; ++} ++EXPORT_SYMBOL(eda_init); +diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig +index 701edf6..7c7b208 100644 +--- a/drivers/misc/eeprom/Kconfig ++++ b/drivers/misc/eeprom/Kconfig +@@ -1,5 +1,16 @@ + menu "EEPROM support" + ++config EEPROM_CLASS ++ tristate "EEPROM Hardware Class support" ++ depends on SYSFS ++ default y ++ help ++ Creates a hardware class in sysfs called "eeprom_dev", ++ providing a common place to register EEPROM devices. ++ ++ This support can also be built as a module. If so, the module ++ will be called eeprom_class. ++ + config EEPROM_AT24 + tristate "I2C EEPROMs from most vendors" + depends on I2C && SYSFS +@@ -95,4 +106,16 @@ config EEPROM_DIGSY_MTC_CFG + + If unsure, say N. + ++config EEPROM_SFF_8436 ++ tristate "SFF-8436 QSFP EEPROMs support" ++ depends on I2C && SYSFS ++ help ++ If you say yes here you get read-only support for the EEPROM of ++ the QSFPs which are implemented as per SFF-8436. ++ ++ All other features of this chip should be accessed via i2c-dev. ++ ++ This driver can also be built as a module. If so, the module ++ will be called sff_8436. ++ + endmenu +diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile +index fc1e81d..9edd559 100644 +--- a/drivers/misc/eeprom/Makefile ++++ b/drivers/misc/eeprom/Makefile +@@ -1,3 +1,4 @@ ++obj-$(CONFIG_EEPROM_CLASS) += eeprom_class.o + obj-$(CONFIG_EEPROM_AT24) += at24.o + obj-$(CONFIG_EEPROM_AT25) += at25.o + obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o +@@ -5,3 +6,4 @@ obj-$(CONFIG_EEPROM_MAX6875) += max6875.o + obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o + obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o + obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o ++obj-$(CONFIG_EEPROM_SFF_8436) += sff_8436_eeprom.o +diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c +index ab1ad41..67f4e6f 100644 +--- a/drivers/misc/eeprom/at24.c ++++ b/drivers/misc/eeprom/at24.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + /* + * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. +@@ -68,6 +69,8 @@ struct at24_data { + unsigned write_max; + unsigned num_addresses; + ++ struct eeprom_device *eeprom_dev; ++ + /* + * Some chips tie up multiple I2C addresses; dummy devices reserve + * them for us, and we'll use them with SMBus calls. +@@ -192,7 +195,8 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: +- count = 2; ++ /* Check for odd length transaction */ ++ count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; +@@ -237,12 +241,20 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, + status = i2c_smbus_read_word_data(client, offset); + if (status >= 0) { + buf[0] = status & 0xff; +- buf[1] = status >> 8; ++ if (count == 2) ++ buf[1] = status >> 8; + status = count; + } + break; + case I2C_SMBUS_BYTE_DATA: +- status = i2c_smbus_read_byte_data(client, offset); ++ if (at24->chip.flags & AT24_FLAG_ADDR16) { ++ status = i2c_smbus_write_byte_data(client, (offset >> 8) & 0xff, offset & 0xff); ++ if (status >= 0) { ++ status = i2c_smbus_read_byte(client); ++ } ++ } else { ++ status = i2c_smbus_read_byte_data(client, offset); ++ } + if (status >= 0) { + buf[0] = status; + status = count; +@@ -327,6 +339,7 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page; ++ int i = 0; + + /* Get corresponding I2C address and adjust offset */ + client = at24_translate_offset(at24, &offset); +@@ -340,10 +353,22 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + if (offset + count > next_page) + count = next_page - offset; + +- /* If we'll use I2C calls for I/O, set up the message */ +- if (!at24->use_smbus) { +- int i = 0; + ++ switch (at24->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ /* Smaller eeproms can work given some SMBus extension calls */ ++ if (count > I2C_SMBUS_BLOCK_MAX) ++ count = I2C_SMBUS_BLOCK_MAX; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ /* Check for odd length transaction */ ++ count = (count == 1) ? 1 : 2; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ count = 1; ++ break; ++ default: ++ /* If we'll use I2C calls for I/O, set up the message */ + msg.addr = client->addr; + msg.flags = 0; + +@@ -355,6 +380,7 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; ++ break; + } + + /* +@@ -365,15 +391,40 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; +- if (at24->use_smbus) { ++ switch (at24->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; +- } else { ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ if (count == 2) { ++ status = i2c_smbus_write_word_data( ++ client,offset,(u16)((buf[0]) | ++ (buf[1] << 8))); ++ } else { ++ /* count = 1 */ ++ status = i2c_smbus_write_byte_data( ++ client, offset, buf[0]); ++ } ++ if (status == 0) ++ status = count; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ if (at24->chip.flags & AT24_FLAG_ADDR16) { ++ status = i2c_smbus_write_word_data(client, (offset >> 8) & 0xff, buf[0] << 8 | (offset & 0xff)); ++ } else { ++ status = i2c_smbus_write_byte_data(client, offset, buf[0]); ++ } ++ if (status == 0) ++ status = count; ++ break; ++ default: + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; ++ break; + } + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", + count, offset, status, jiffies); +@@ -512,6 +563,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) + + chip.setup = NULL; + chip.context = NULL; ++ chip.eeprom_data = NULL; + } + + if (!is_power_of_2(chip.byte_len)) +@@ -529,11 +581,10 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (chip.flags & AT24_FLAG_ADDR16) { +- err = -EPFNOSUPPORT; +- goto err_out; +- } +- if (i2c_check_functionality(client->adapter, +- I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { ++ use_smbus = I2C_SMBUS_BYTE_DATA; ++ } else if (!(chip.flags & AT24_FLAG_DISABLE_I2CBLOCK) && ++ (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_I2C_BLOCK))) { + use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) { +@@ -579,9 +630,14 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) + + writable = !(chip.flags & AT24_FLAG_READONLY); + if (writable) { +- if (!use_smbus || i2c_check_functionality(client->adapter, +- I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { +- ++ if (!use_smbus || ++ (!(chip.flags & AT24_FLAG_DISABLE_I2CBLOCK) && ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_WORD_DATA) || ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + unsigned write_max = chip.page_size; + + at24->macc.write = at24_macc_write; +@@ -625,6 +681,13 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) + if (err) + goto err_clients; + ++ at24->eeprom_dev = eeprom_device_register(&client->dev, chip.eeprom_data); ++ if (IS_ERR(at24->eeprom_dev)) { ++ dev_err(&client->dev, "error registering eeprom device.\n"); ++ err = PTR_ERR(at24->eeprom_dev); ++ goto err_clients; ++ } ++ + i2c_set_clientdata(client, at24); + + dev_info(&client->dev, "%zu byte %s EEPROM, %s, %u bytes/write\n", +@@ -667,6 +730,8 @@ static int __devexit at24_remove(struct i2c_client *client) + for (i = 1; i < at24->num_addresses; i++) + i2c_unregister_device(at24->client[i]); + ++ eeprom_device_unregister(at24->eeprom_dev); ++ + kfree(at24->writebuf); + kfree(at24); + return 0; +diff --git a/drivers/misc/eeprom/eeprom_class.c b/drivers/misc/eeprom/eeprom_class.c +new file mode 100644 +index 0000000..e01a81a +--- /dev/null ++++ b/drivers/misc/eeprom/eeprom_class.c +@@ -0,0 +1,194 @@ ++/* ++ * eeprom_class.c ++ * ++ * This file defines the sysfs class "eeprom", for use by EEPROM ++ * drivers. ++ * ++ * Copyright (C) 2013 Cumulus Networks, Inc. ++ * Author: Curt Brune ++ * ++ * Ideas and structure graciously borrowed from the hwmon class: ++ * Copyright (C) 2005 Mark M. Hoffman ++ * ++ * This program is free software; 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Root eeprom "class" object (corresponds to '//class/eeprom_dev/') */ ++static struct class *eeprom_class; ++ ++#define EEPROM_CLASS_NAME "eeprom_dev" ++#define EEPROM_ID_PREFIX "eeprom" ++#define EEPROM_ID_FORMAT EEPROM_ID_PREFIX "%d" ++ ++static DEFINE_IDA(eeprom_ida); ++ ++/** ++ * eeprom_device_register - register w/ eeprom class ++ * @dev: the device to register ++ * @data: platform data to use for the device ++ * ++ * eeprom_device_unregister() must be called when the device is no ++ * longer needed. ++ * ++ * Creates a new eeprom class device that is a child of @dev. Also ++ * creates a symlink in //class/eeprom_dev/eeprom[N] pointing ++ * to the new device. ++ * ++ * Returns the pointer to the new device. ++ */ ++struct eeprom_device *eeprom_device_register(struct device *dev, struct eeprom_platform_data *data) ++{ ++ struct eeprom_device *eeprom_dev; ++ int id; ++ int ret; ++ ++ id = ida_simple_get(&eeprom_ida, 0, 0, GFP_KERNEL); ++ if (id < 0) ++ return ERR_PTR(id); ++ ++ eeprom_dev = kzalloc(sizeof(struct eeprom_device), GFP_KERNEL); ++ if (!eeprom_dev) { ++ ret = -ENOMEM; ++ goto err_ida; ++ } ++ ++ eeprom_dev->dev = device_create(eeprom_class, dev, MKDEV(0, 0), ++ eeprom_dev, EEPROM_ID_FORMAT, id); ++ if (IS_ERR(eeprom_dev->dev)) { ++ ret = PTR_ERR(eeprom_dev->dev); ++ goto err_eeprom_dev_free; ++ } ++ ++ eeprom_dev->data = data; ++ ++ return eeprom_dev; ++ ++err_eeprom_dev_free: ++ kfree(eeprom_dev); ++ ++err_ida: ++ ida_simple_remove(&eeprom_ida, id); ++ return ERR_PTR(ret); ++} ++ ++/** ++ * eeprom_device_unregister - removes the previously registered class device ++ * ++ * @eeprom: the eeprom class device to destroy ++ */ ++void eeprom_device_unregister(struct eeprom_device *eeprom_dev) ++{ ++ int id; ++ ++ if (likely(sscanf(dev_name(eeprom_dev->dev), EEPROM_ID_FORMAT, &id) == 1)) { ++ device_unregister(eeprom_dev->dev); ++ kfree(eeprom_dev); ++ ida_simple_remove(&eeprom_ida, id); ++ } else ++ dev_dbg(eeprom_dev->dev->parent, ++ "eeprom_device_unregister() failed: bad class ID!\n"); ++} ++ ++/** ++ * Each member of the eeprom class exports a sysfs file called ++ * "label", containing the label property from the corresponding ++ * device tree node. ++ * ++ * Userspace can use the label to identify what the EEPROM is for. ++ */ ++static ssize_t label_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct eeprom_device *eeprom_dev = (struct eeprom_device *)dev_get_drvdata(dev); ++ const char* cp = NULL; ++ int len = 0; ++ ++ /* Check if the eeprom device has an explicit label: ++ * - explicitly passed in to eeprom_device_register() ++ * - explicitly passed via the device tree node ++ * ++ * Otherwise use "unknown". ++ */ ++ if (eeprom_dev->data && eeprom_dev->data->label) { ++ cp = eeprom_dev->data->label; ++ len = strlen(cp) + 1; ++ } else { ++ /* ++ * Check for a device tree property. ++ * ++ * The class device is a child of the original device, ++ * i.e. dev->parent points to the original device. ++ */ ++ if (dev->parent && dev->parent->of_node) ++ cp = of_get_property(dev->parent->of_node, "label", &len); ++ } ++ ++ if ((cp == NULL) || (len == 0)) { ++ cp = "unknown"; ++ len = strlen(cp) + 1; ++ } ++ ++ strncpy(buf, cp, len - 1); ++ buf[len - 1] = '\n'; ++ buf[len] = '\0'; ++ ++ return len; ++} ++ ++struct device_attribute eeprom_class_dev_attrs[] = { ++ __ATTR_RO(label), ++ __ATTR_NULL, ++}; ++ ++static int __init eeprom_init(void) ++{ ++ eeprom_class = class_create(THIS_MODULE, EEPROM_CLASS_NAME); ++ if (IS_ERR(eeprom_class)) { ++ pr_err("couldn't create sysfs class\n"); ++ return PTR_ERR(eeprom_class); ++ } ++ ++ eeprom_class->dev_attrs = eeprom_class_dev_attrs; ++ ++ return 0; ++} ++ ++static void __exit eeprom_exit(void) ++{ ++ class_destroy(eeprom_class); ++} ++ ++subsys_initcall(eeprom_init); ++module_exit(eeprom_exit); ++ ++EXPORT_SYMBOL_GPL(eeprom_device_register); ++EXPORT_SYMBOL_GPL(eeprom_device_unregister); ++ ++MODULE_AUTHOR("Curt Brune "); ++MODULE_DESCRIPTION("eeprom sysfs/class support"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/misc/eeprom/sff_8436_eeprom.c b/drivers/misc/eeprom/sff_8436_eeprom.c +new file mode 100644 +index 0000000..f6cc6e2 +--- /dev/null ++++ b/drivers/misc/eeprom/sff_8436_eeprom.c +@@ -0,0 +1,1226 @@ ++/* ++ * sff_8436_eeprom.c - handle most SFF-8436 based QSFP EEPROMs ++ * ++ * Copyright (C) 2014 Cumulus networks 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 Freeoftware Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++/* ++ * Description: ++ * a) SFF 8436 based qsfp read/write transactions are just like the at24 eeproms ++ * b) The register/memory layout is up to 5 128 byte pages defined by a "pages valid" ++ * register and switched via a "page select" register as explained in below diagram. ++ * c) 256 bytes are mapped at a time. page 0 is always mapped to the first 128 bytes and ++ * the other 4 pages are selectively mapped to the second 128 bytes ++ * ++ * SFF 8436 based QSFP Memory Map ++ * ++ * 2-Wire Serial Address: 1010000x ++ * ++ * Lower Page 00h (128 bytes) ++ * ===================== ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * |Page Select Byte(127)| ++ * ===================== ++ * | ++ * | ++ * | ++ * | ++ * V ++ * ----------------------------------------------------------------- ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * V V V V ++ * ------------- ---------------- ----------------- -------------- ++ * | | | | | | | | ++ * | Upper | | Upper | | Upper | | Upper | ++ * | Page 00h | | Page 01h | | Page 02h | | Page 03h | ++ * | | | (Optional) | | (Optional) | | (Optional | ++ * | | | | | | | for Cable | ++ * | | | | | | | Assemblies) | ++ * | ID | | AST | | User | | | ++ * | Fields | | Table | | EEPROM Data | | | ++ * | | | | | | | | ++ * | | | | | | | | ++ * | | | | | | | | ++ * ------------- ---------------- ----------------- -------------- ++ * ++ * ++ **/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define SFF_8436_EEPROM_SIZE (5*128) ++#define SFF_8436_MAX_PAGE_COUNT 5 ++#define SFF_8436_MMAP_SIZE 256 ++#define SFF_8436_PAGE_SELECT_REG 0x7F ++ ++#define SFF_8436_OPTION_4_OFFSET 0xC3 ++#define SFF_8436_PAGE_02_PRESENT (1 << 7) /* Memory Page 02 present */ ++#define SFF_8436_PAGE_01_PRESENT (1 << 6) /* Memory Page 01 present */ ++#define SFF_8436_STATUS_2_OFFSET 0x02 ++#define SFF_8436_STATUS_PAGE_03_PRESENT_L (1 << 2) /* Flat Memory:0- Paging, 1- Page 0 only */ ++ ++#define SFF_ID_OFFSET 0x00 ++#define SFF_ID_LEN 1 ++#define SFF_ID_SFP 0x03 ++#define SFF_ID_QSFP_PLUS 0x0d ++#define SFF_ID_QSFP28 0x11 ++#define SFF_8472_EEPROM_SIZE (4*128) ++ ++struct sff_8436_data { ++ struct sff_8436_platform_data chip; ++ struct memory_accessor macc; ++ int use_smbus; ++ ++ /* ++ * Lock protects against activities from other Linux tasks, ++ * but not from changes by other I2C masters. ++ */ ++ struct mutex lock; ++ struct bin_attribute bin; ++ struct attribute_group attr_group; ++ ++ u8 *writebuf; ++ unsigned write_max; ++ ++ unsigned num_addresses; ++ ++ u8 data[SFF_8436_EEPROM_SIZE]; ++ struct eeprom_device *eeprom_dev; ++ ++ /* Config variable to support SFF-8472/SFP+ standard */ ++ int sfp_compat; ++ ++ struct i2c_client *client[]; ++}; ++ ++typedef enum qsfp_opcode { ++ QSFP_READ_OP = 0, ++ QSFP_WRITE_OP = 1 ++} qsfp_opcode_e; ++ ++/* ++ * This parameter is to help this driver avoid blocking other drivers out ++ * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C ++ * clock, one 256 byte read takes about 1/43 second which is excessive; ++ * but the 1/170 second it takes at 400 kHz may be quite reasonable; and ++ * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. ++ * ++ * This value is forced to be a power of two so that writes align on pages. ++ */ ++static unsigned io_limit = 128; ++ ++/* ++ *pecs often allow 5 msec for a page write, sometimes 20 msec; ++ * it's important to recover from write timeouts. ++ */ ++static unsigned write_timeout = 25; ++ ++#define SFF_8436_PAGE_SIZE 128 ++#define SFF_8436_SIZE_BYTELEN 5 ++#define SFF_8436_SIZE_FLAGS 8 ++ ++#define SFF_8436_BITMASK(x) (BIT(x) - 1) ++ ++ ++/* create non-zero magic value for given eeprom parameters */ ++#define SFF_8436_DEVICE_MAGIC(_len, _flags) \ ++ ((1 << SFF_8436_SIZE_FLAGS | (_flags)) \ ++ << SFF_8436_SIZE_BYTELEN | ilog2(_len)) ++ ++static const struct i2c_device_id sff8436_ids[] = { ++ { "sff8436",SFF_8436_DEVICE_MAGIC(2048 / 8, 0) }, ++ { /* END OF LIST */ } ++}; ++MODULE_DEVICE_TABLE(i2c, sff8436_ids); ++ ++/*-------------------------------------------------------------------------*/ ++/* ++ * This routine computes the addressing information to be used for a given r/w request. ++ * Assumes that sanity checks for offset happened at sysfs-layer. ++ * Offset within Lower Page 00h and Upper Page 00h are not recomputed ++ */ ++static uint8_t sff_8436_translate_offset(struct sff_8436_data *sff_8436, ++ loff_t *offset) ++{ ++ unsigned page = 0; ++ ++ if (*offset < SFF_8436_MMAP_SIZE) { ++ return 0; ++ } ++ ++ page = (*offset >> 7)-1; ++ ++ if (page > 0 ) { ++ *offset = 0x80 + (*offset & 0x7f); ++ } else { ++ *offset &= 0xff; ++ } ++ ++ return page; ++} ++ ++static int sff_8436_read_reg(struct sff_8436_data *sff_8436, ++ uint8_t reg, uint8_t *val) ++{ ++ int count = 1, i = 0; ++ struct i2c_client *client = sff_8436->client[0]; ++ struct i2c_msg msg[2]; ++ u8 msgbuf[2]; ++ ssize_t status; ++ unsigned long timeout, read_time; ++ ++ memset(msg, 0, sizeof(msg)); ++ ++ /* ++ * Writes fail if the previous one didn't complete yet. We may ++ * loop a few times until this one succeeds, waiting at least ++ * long enough for one entire page write to work. ++ */ ++ timeout = jiffies + msecs_to_jiffies(write_timeout); ++ do { ++ read_time = jiffies; ++ switch (sff_8436->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ status = i2c_smbus_read_i2c_block_data(client, ++ reg, count, val); ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ status = i2c_smbus_read_word_data(client, reg); ++ ++ if (status >= 0) { ++ *val = status & 0xff; ++ status = count; ++ } ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ status = i2c_smbus_read_byte_data(client, reg); ++ ++ if (status >= 0) { ++ *val = status; ++ status = count; ++ } ++ break; ++ ++ default: ++ i = 0; ++ msgbuf[i++] = reg; ++ ++ msg[0].addr = client->addr; ++ msg[0].buf = msgbuf; ++ msg[0].len = i; ++ ++ msg[1].addr = client->addr; ++ msg[1].flags = I2C_M_RD; ++ msg[1].buf = val; ++ msg[1].len = count; ++ ++ status = i2c_transfer(client->adapter, msg, 2); ++ if (status == 2) ++ status = count; ++ break; ++ } ++ dev_dbg(&client->dev, "read (using smbus %d) %d@%d --> %zd (%ld)\n", ++ sff_8436->use_smbus, count, reg, status, jiffies); ++ ++ if (status == count) ++ return count; ++ ++ /* REVISIT: at HZ=100, this is sloooow */ ++ msleep(1); ++ } while (time_before(read_time, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static int sff_8436_write_reg(struct sff_8436_data *sff_8436, ++ uint8_t reg, uint8_t val) ++{ ++ uint8_t data[2] = { reg, val }; ++ int count = 1; ++ struct i2c_client *client = sff_8436->client[0]; ++ struct i2c_msg msg; ++ ssize_t status; ++ unsigned long timeout, write_time; ++ ++ /* ++ * Writes fail if the previous one didn't complete yet. We may ++ * loop a few times until this one succeeds, waiting at least ++ * long enough for one entire page write to work. ++ */ ++ timeout = jiffies + msecs_to_jiffies(write_timeout); ++ do { ++ write_time = jiffies; ++ switch (sff_8436->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ status = i2c_smbus_write_i2c_block_data(client, ++ reg, count, &val); ++ if (status == 0) ++ status = count; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ case I2C_SMBUS_BYTE_DATA: ++ status = i2c_smbus_write_byte_data(client, reg, val); ++ ++ if (status == 0) ++ status = count; ++ break; ++ default: ++ msg.addr = client->addr; ++ msg.flags = 0; ++ msg.len = sizeof(data); ++ msg.buf = (char *) data; ++ ++ status = i2c_transfer(client->adapter, &msg, 1); ++ if (status == 1) ++ status = count; ++ break; ++ } ++ dev_dbg(&client->dev, "write (using smbus %d) %d@%d --> %zd (%ld)\n", ++ sff_8436->use_smbus, count, reg, status, jiffies); ++ ++ if (status == count) ++ return count; ++ ++ /* REVISIT: at HZ=100, this is sloooow */ ++ msleep(1); ++ } while (time_before(write_time, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static int sff_8436_write_page_reg(struct sff_8436_data *sff_8436, ++ uint8_t val) ++{ ++ return sff_8436_write_reg(sff_8436, SFF_8436_PAGE_SELECT_REG, val); ++} ++ ++static ssize_t sff_8436_eeprom_read(struct sff_8436_data *sff_8436, ++ struct i2c_client *client, char *buf, ++ unsigned offset, size_t count) ++{ ++ struct i2c_msg msg[2]; ++ u8 msgbuf[2]; ++ unsigned long timeout, read_time; ++ int status, i; ++ ++ memset(msg, 0, sizeof(msg)); ++ ++ switch (sff_8436->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ /*smaller eeproms can work given some SMBus extension calls */ ++ if (count > I2C_SMBUS_BLOCK_MAX) ++ count = I2C_SMBUS_BLOCK_MAX; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ /* Check for odd length transaction */ ++ count = (count == 1) ? 1 : 2; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ count = 1; ++ break; ++ default: ++ /* ++ * When we have a better choice than SMBus calls, use a ++ * combined I2C message. Write address; then read up to ++ * io_limit data bytes. Note that read page rollover helps us ++ * here (unlike writes). msgbuf is u8 and will cast to our ++ * needs. ++ */ ++ i = 0; ++ msgbuf[i++] = offset; ++ ++ msg[0].addr = client->addr; ++ msg[0].buf = msgbuf; ++ msg[0].len = i; ++ ++ msg[1].addr = client->addr; ++ msg[1].flags = I2C_M_RD; ++ msg[1].buf = buf; ++ msg[1].len = count; ++ } ++ ++ /* ++ * Reads fail if the previous write didn't complete yet. We may ++ * loop a few times until this one succeeds, waiting at least ++ * long enough for one entire page write to work. ++ */ ++ timeout = jiffies + msecs_to_jiffies(write_timeout); ++ do { ++ read_time = jiffies; ++ ++ switch (sff_8436->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ status = i2c_smbus_read_i2c_block_data(client, offset, ++ count, buf); ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ status = i2c_smbus_read_word_data(client, offset); ++ if (status >= 0) { ++ buf[0] = status & 0xff; ++ if (count == 2) ++ buf[1] = status >> 8; ++ status = count; ++ } ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ status = i2c_smbus_read_byte_data(client, offset); ++ if (status >= 0) { ++ buf[0] = status; ++ status = count; ++ } ++ break; ++ default: ++ status = i2c_transfer(client->adapter, msg, 2); ++ if (status == 2) ++ status = count; ++ } ++ ++ dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", ++ count, offset, status, jiffies); ++ ++ if (status == count) ++ return count; ++ ++ /* REVISIT: at HZ=100, this is sloooow */ ++ msleep(1); ++ } while (time_before(read_time, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static ssize_t sff_8436_eeprom_write(struct sff_8436_data *sff_8436, ++ struct i2c_client *client, const char *buf, ++ unsigned offset, size_t count) ++{ ++ struct i2c_msg msg; ++ ssize_t status; ++ unsigned long timeout, write_time; ++ unsigned next_page; ++ int i = 0; ++ ++ /* write max is at most a page */ ++ if (count > sff_8436->write_max) ++ count = sff_8436->write_max; ++ ++ /* Never roll over backwards, to the start of this page */ ++ next_page = roundup(offset + 1, SFF_8436_PAGE_SIZE); ++ if (offset + count > next_page) ++ count = next_page - offset; ++ ++ switch (sff_8436->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ /*smaller eeproms can work given some SMBus extension calls */ ++ if (count > I2C_SMBUS_BLOCK_MAX) ++ count = I2C_SMBUS_BLOCK_MAX; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ /* Check for odd length transaction */ ++ count = (count == 1) ? 1 : 2; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ count = 1; ++ break; ++ default: ++ /* If we'll use I2C calls for I/O, set up the message */ ++ msg.addr = client->addr; ++ msg.flags = 0; ++ ++ /* msg.buf is u8 and casts will mask the values */ ++ msg.buf = sff_8436->writebuf; ++ ++ msg.buf[i++] = offset; ++ memcpy(&msg.buf[i], buf, count); ++ msg.len = i + count; ++ break; ++ } ++ ++ /* ++ * Reads fail if the previous write didn't complete yet. We may ++ * loop a few times until this one succeeds, waiting at least ++ * long enough for one entire page write to work. ++ */ ++ timeout = jiffies + msecs_to_jiffies(write_timeout); ++ do { ++ write_time = jiffies; ++ ++ switch (sff_8436->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ status = i2c_smbus_write_i2c_block_data(client, ++ offset, count, buf); ++ if (status == 0) ++ status = count; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ if (count == 2) { ++ status = i2c_smbus_write_word_data( ++ client,offset,(u16)((buf[0]) | ++ (buf[1] << 8))); ++ } else { ++ /* count = 1 */ ++ status = i2c_smbus_write_byte_data( ++ client, offset, buf[0]); ++ } ++ if (status == 0) ++ status = count; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ status = i2c_smbus_write_byte_data(client, offset, buf[0]); ++ if (status == 0) ++ status = count; ++ break; ++ default: ++ status = i2c_transfer(client->adapter, &msg, 1); ++ if (status == 1) ++ status = count; ++ break; ++ } ++ ++ dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", ++ count, offset, (long int) status, jiffies); ++ ++ if (status == count) ++ return count; ++ ++ /* REVISIT: at HZ=100, this is sloooow */ ++ msleep(1); ++ } while (time_before(write_time, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static ssize_t sff_8436_eeprom_update_client(struct sff_8436_data *sff_8436, ++ loff_t off, size_t count, qsfp_opcode_e opcode) ++{ ++ struct i2c_client *client = sff_8436->client[0]; ++ ssize_t retval = 0; ++ u8 page = 0; ++ loff_t phy_offset = off; ++ int ret = 0; ++ ++ page = sff_8436_translate_offset(sff_8436, &phy_offset); ++ ++ dev_dbg(&client->dev, ++ "sff_8436_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", ++ off, page, phy_offset, (long int) count, opcode); ++ if (page > 0) { ++ ret = sff_8436_write_page_reg(sff_8436, page); ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "sff_8436_write_page_reg for page %d failed ret:%d!\n", ++ page, ret); ++ return ret; ++ } ++ } ++ ++ while (count) { ++ ssize_t status; ++ ++ if (opcode == QSFP_READ_OP) { ++ status = sff_8436_eeprom_read(sff_8436, client, ++ (char *)(&sff_8436->data[off]), phy_offset, count); ++ } else { ++ status = sff_8436_eeprom_write(sff_8436, client, ++ (char *)(&sff_8436->data[off]), phy_offset, count); ++ } ++ if (status <= 0) { ++ if (retval == 0) ++ retval = status; ++ break; ++ } ++ phy_offset += status; ++ off += status; ++ count -= status; ++ retval += status; ++ } ++ ++ ++ if (page > 0) { ++ ret = sff_8436_write_page_reg(sff_8436, 0); ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "sff_8436_write_page_reg for page 0 failed ret:%d!\n", ret); ++ return ret; ++ } ++ } ++ return retval; ++} ++ ++/* ++ * API to return whether pluggable module is SFP+ or QSFP ++ */ ++int get_module_id (struct sff_8436_data *sff_8436) ++{ ++ struct i2c_client *client = sff_8436->client[0]; ++ int ret; ++ u8 mod_id = 0; ++ ++ mutex_lock(&sff_8436->lock); ++ ++ ret = sff_8436_read_reg(sff_8436, SFF_ID_OFFSET, &mod_id); ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "sff_8436_read_reg for page 00h status failed %d!\n", ret); ++ mod_id = -1; ++ } ++ ++ mutex_unlock(&sff_8436->lock); ++ ++ return mod_id; ++} ++ ++/* ++ * Mechanism to handle addresses greater than 256 by 8 bit addressing mode is ++ * by registering addresses 256-512 as another chip ++ * ++ * This routine supports chips which consume multiple I2C addresses. It ++ * computes the addressing information to be used for a given r/w request. ++ * Assumes that sanity checks for offset happened at sysfs-layer. ++ * ++ */ ++static struct i2c_client *sff_8472_translate_offset(struct sff_8436_data *sff_8436, ++ loff_t offset, loff_t *phy_offset) ++{ ++ unsigned i; ++ ++ i = offset >> 8; ++ *phy_offset = offset & 0xff; ++ ++ return sff_8436->client[i]; ++} ++ ++/* ++ * Assumption: ++ * Buffer provided and returned by this driver is ++ * of size 5x128 (QSFP eeprom size) even though ++ * SFP+ eeprom size is 4x128. ++ * ++ * Read operation: ++ * Last page -513 to 640 will be 0xff ++ * ++ * Write operation: ++ * Last page : 513 to 640 will be ignored ++ * ++ */ ++ ++static ssize_t sff_8472_read_write(struct sff_8436_data *sff_8436, ++ loff_t off, size_t count, qsfp_opcode_e opcode) ++{ ++ struct i2c_client *client; ++ ssize_t retval = 0; ++ ++ if (unlikely(!count)) ++ return count; ++ ++ /* ++ * Read data from chip, protecting against concurrent updates ++ * from this host, but not from other I2C masters. ++ */ ++ mutex_lock(&sff_8436->lock); ++ ++ while (count) { ++ ssize_t status; ++ loff_t phy_offset = 0; ++ ++ client = sff_8472_translate_offset(sff_8436, off, &phy_offset); ++ dev_dbg(&client->dev, ++ "sff_8472_read_write off %lld offset:%lld, count:%ld, phy_offset:%lld\n", ++ off, off, (long int) count, phy_offset); ++ ++ if (opcode == QSFP_READ_OP) { ++ status = sff_8436_eeprom_read(sff_8436, client, ++ (char *)(&sff_8436->data[off]), phy_offset, count); ++ } else { ++ status = sff_8436_eeprom_write(sff_8436, client, ++ (char *)(&sff_8436->data[off]), phy_offset, count); ++ } ++ ++ if (status <= 0) { ++ if (retval == 0) ++ retval = status; ++ break; ++ } ++ off += status; ++ phy_offset += status; ++ count -= status; ++ retval += status; ++ } ++ ++ mutex_unlock(&sff_8436->lock); ++ ++ ++ return retval; ++} ++ ++static ssize_t sff_8436_read_write(struct sff_8436_data *sff_8436, ++ char *buf, loff_t off, size_t len, qsfp_opcode_e opcode) ++{ ++ struct i2c_client *client = sff_8436->client[0]; ++ u8 page; ++ u8 refresh_page = 0; ++ int ret = 0; ++ u8 val = 0; ++ u8 mod_id = 0; ++ int err_timeout = 0; ++ size_t pending_len = 0, page_len = 0; ++ loff_t page_offset = 0, page_start_offset = 0; ++ size_t max_eeprom_size = SFF_8436_EEPROM_SIZE; ++ ++ if (unlikely(!len)) ++ return len; ++ ++ ++ if (sff_8436->sfp_compat) { ++ mod_id = get_module_id(sff_8436); ++ ++ if (mod_id == SFF_ID_SFP) { ++ max_eeprom_size = SFF_8472_EEPROM_SIZE; ++ } ++ } ++ ++ if (off > max_eeprom_size) ++ return 0; ++ ++ if (off + len > max_eeprom_size) ++ len = max_eeprom_size - off; ++ ++ memset(sff_8436->data, 0xff, SFF_8436_EEPROM_SIZE); ++ ++ if (opcode == QSFP_WRITE_OP) { ++ memcpy(&sff_8436->data[off], buf, len); ++ } ++ ++ if (sff_8436->sfp_compat) { ++ ++ dev_dbg(&client->dev, ++ "Module ID: %d, offset:%lld , len:%ld!\n", mod_id, off, len); ++ ++ if (mod_id == SFF_ID_SFP) { ++ ret = sff_8472_read_write(sff_8436, off, len, opcode); ++ ++ if (opcode == QSFP_READ_OP) { ++ memcpy(buf, &sff_8436->data[off], len); ++ } ++ return (ret); ++ } ++ } ++ /* ++ * Read data from chip, protecting against concurrent updates ++ * from this host, but not from other I2C masters. ++ */ ++ mutex_lock(&sff_8436->lock); ++ ++ /* ++ * Refresh pages which covers the requested data ++ * from offset to off + len ++ * Only refresh pages which contain requested bytes ++ * ++ */ ++ ++ pending_len = len; ++ ++ for (page = off >> 7; page <= (off + len - 1) >> 7; page++) { ++ refresh_page = 0; ++ switch (page) { ++ case 0: ++ /* Lower page 00h */ ++ refresh_page = 1; ++ err_timeout = 1; ++ break; ++ case 1: ++ /* Upper page 00h */ ++ refresh_page = 1; ++ err_timeout = 1; ++ break; ++ case 2: ++ /* Upper page 01h */ ++ ret = sff_8436_read_reg(sff_8436, SFF_8436_OPTION_4_OFFSET, &val); ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "sff_8436_read_reg for page 01h status failed %d!\n", ret); ++ goto err; ++ } ++ if (val & SFF_8436_PAGE_01_PRESENT) { ++ refresh_page = 1; ++ } ++ break; ++ case 3: ++ /* Upper page 02h */ ++ ret = sff_8436_read_reg(sff_8436, SFF_8436_OPTION_4_OFFSET, &val); ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "sff_8436_read_reg for page 02h status failed %d!\n", ret); ++ goto err; ++ } ++ if (val & SFF_8436_PAGE_02_PRESENT) { ++ refresh_page = 1; ++ } ++ break; ++ case 4: ++ /* Upper page 03h */ ++ ret = sff_8436_read_reg(sff_8436, SFF_8436_STATUS_2_OFFSET, &val); ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "sff_8436_read_reg for page 03h status failed %d!\n", ret); ++ goto err; ++ } ++ if (!(val & SFF_8436_STATUS_PAGE_03_PRESENT_L)) { ++ refresh_page = 1; ++ } ++ break; ++ default: ++ /* Invalid page index */ ++ dev_err(&client->dev, "Invalid page %d!\n", page); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ if (!refresh_page) { ++ /* if page is not valid or already refreshed */ ++ continue; ++ } ++ ++ /* ++ * Compute the offset and number of bytes to be read/write ++ * w.r.t requested page ++ * ++ * 1. start at offset 0 (within the page), and read/write the entire page ++ * 2. start at offset 0 (within the page) and read/write less than entire page ++ * 3. start at an offset not equal to 0 and read/write the rest of the page ++ * 4. start at an offset not equal to 0 and read/write less than (end of page - offset) ++ * ++ */ ++ page_start_offset = page * SFF_8436_PAGE_SIZE; ++ ++ if (page_start_offset < off) { ++ page_offset = off; ++ if (off + pending_len < page_start_offset + SFF_8436_PAGE_SIZE) { ++ page_len = pending_len; ++ } else { ++ page_len = SFF_8436_PAGE_SIZE - off; ++ } ++ } else { ++ page_offset = page_start_offset; ++ if (pending_len > SFF_8436_PAGE_SIZE) { ++ page_len = SFF_8436_PAGE_SIZE; ++ } else { ++ page_len = pending_len; ++ } ++ } ++ ++ pending_len = pending_len - page_len; ++ ++ dev_dbg(&client->dev, ++ "sff_read off %lld len %ld page_start_offset %lld page_offset %lld page_len %ld pending_len %ld\n", ++ off, (long int) len, page_start_offset, page_offset, (long int) page_len, (long int) pending_len); ++ ++ /* Refresh the data from offset for specified len */ ++ ret = sff_8436_eeprom_update_client(sff_8436, page_offset, page_len, opcode); ++ if (ret != page_len) { ++ if (err_timeout) { ++ dev_dbg(&client->dev, "sff_8436_update_client for %s page %d page_offset %lld page_len %ld failed %d!\n", ++ (page ? "Upper" : "Lower"), (page ? (page-1) : page), page_offset, (long int) page_len, ret); ++ goto err; ++ } else { ++ dev_err(&client->dev, "sff_8436_update_client for %s page %d page_offset %lld page_len %ld failed %d!\n", ++ (page ? "Upper" : "Lower"), (page ? (page-1) : page), page_offset, (long int) page_len, ret); ++ } ++ } ++ } ++ mutex_unlock(&sff_8436->lock); ++ ++ if (opcode == QSFP_READ_OP) { ++ memcpy(buf, &sff_8436->data[off], len); ++ } ++ return len; ++ ++err: ++ mutex_unlock(&sff_8436->lock); ++ ++ return ret; ++} ++ ++static ssize_t sff_8436_bin_read(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, ++ char *buf, loff_t off, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); ++ struct sff_8436_data *sff_8436 = i2c_get_clientdata(client); ++ ++ return sff_8436_read_write(sff_8436, buf, off, count, QSFP_READ_OP); ++} ++ ++ ++static ssize_t sff_8436_bin_write(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, ++ char *buf, loff_t off, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); ++ struct sff_8436_data *sff_8436 = i2c_get_clientdata(client); ++ ++ return sff_8436_read_write(sff_8436, buf, off, count, QSFP_WRITE_OP); ++} ++/*-------------------------------------------------------------------------*/ ++ ++/* ++ * This lets other kernel code access the eeprom data. For example, it ++ * might hold a board's Ethernet address, or board-specific calibration ++ * data generated on the manufacturing floor. ++ */ ++ ++static ssize_t sff_8436_macc_read(struct memory_accessor *macc, char *buf, ++ off_t offset, size_t count) ++{ ++ struct sff_8436_data *sff_8436 = container_of(macc, struct sff_8436_data, macc); ++ ++ return sff_8436_read_write(sff_8436, buf, offset, count, QSFP_READ_OP); ++} ++ ++static ssize_t sff_8436_macc_write(struct memory_accessor *macc, const char *buf, ++ off_t offset, size_t count) ++{ ++ struct sff_8436_data *sff_8436 = container_of(macc, struct sff_8436_data, macc); ++ ++ return sff_8436_read_write(sff_8436, (char *) buf, offset, count, QSFP_WRITE_OP); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int __devexit sff_8436_remove(struct i2c_client *client) ++{ ++ struct sff_8436_data *sff_8436; ++ int i; ++ ++ sff_8436 = i2c_get_clientdata(client); ++ sysfs_remove_group(&client->dev.kobj, &sff_8436->attr_group); ++ sysfs_remove_bin_file(&client->dev.kobj, &sff_8436->bin); ++ ++ for (i = 1; i < sff_8436->num_addresses; i++) ++ i2c_unregister_device(sff_8436->client[i]); ++ ++ eeprom_device_unregister(sff_8436->eeprom_dev); ++ ++ kfree(sff_8436->writebuf); ++ kfree(sff_8436); ++ return 0; ++} ++ ++static ssize_t show_sfp_compat(struct device *dev, ++ struct device_attribute *dattr, ++ char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sff_8436_data *sff_8436 = i2c_get_clientdata(client); ++ ssize_t count; ++ ++ mutex_lock(&sff_8436->lock); ++ count = sprintf(buf, "%d\n", sff_8436->sfp_compat); ++ mutex_unlock(&sff_8436->lock); ++ ++ return count; ++} ++ ++static ssize_t set_sfp_compat(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sff_8436_data *sff_8436 = i2c_get_clientdata(client); ++ int sfp_compat; ++ ++ if (sscanf(buf, "%d", &sfp_compat) != 1 || ++ sfp_compat < 0 || sfp_compat > 1) ++ return -EINVAL; ++ ++ mutex_lock(&sff_8436->lock); ++ sff_8436->sfp_compat = sfp_compat; ++ mutex_unlock(&sff_8436->lock); ++ ++ return count; ++} ++ ++static DEVICE_ATTR(sfp_compatible, S_IRUGO | S_IWUSR, show_sfp_compat, set_sfp_compat); ++ ++static struct attribute *sff_8436_attrs[] = { ++ &dev_attr_sfp_compatible.attr, ++ NULL, ++}; ++ ++static struct attribute_group sff_8436_attr_group = { ++ .attrs = sff_8436_attrs, ++}; ++ ++static int sff_8436_eeprom_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ int err; ++ int use_smbus = 0; ++ struct sff_8436_platform_data chip; ++ struct sff_8436_data *sff_8436; ++ kernel_ulong_t magic; ++ int num_addresses = 0; ++ int i = 0; ++ ++ if (client->dev.platform_data) { ++ chip = *(struct sff_8436_platform_data *)client->dev.platform_data; ++ } else { ++ /* ++ * SFF-8436 MMAP is 256 bytes long ++ */ ++ magic = SFF_8436_DEVICE_MAGIC(2048 / 8, 0); ++ chip.byte_len = BIT(magic & SFF_8436_BITMASK(SFF_8436_SIZE_BYTELEN)); ++ magic >>= SFF_8436_SIZE_BYTELEN; ++ chip.flags = magic & SFF_8436_BITMASK(SFF_8436_SIZE_FLAGS); ++ /* ++ * This is slow, but we can't know all eeproms, so we better ++ * play safe.pecifying custom eeprom-types via platform_data ++ * is recommended anyhow. ++ */ ++ chip.page_size = 1; ++ ++ chip.setup = NULL; ++ chip.context = NULL; ++ chip.eeprom_data = NULL; ++ } ++ ++ if (!is_power_of_2(chip.byte_len)) ++ dev_warn(&client->dev, ++ "byte_len looks suspicious (no power of 2)!\n"); ++ ++ if (!chip.page_size) { ++ dev_err(&client->dev, "page_size must not be 0!\n"); ++ err = -EINVAL; ++ goto exit; ++ } ++ if (!is_power_of_2(chip.page_size)) ++ dev_warn(&client->dev, ++ "page_size looks suspicious (no power of 2)!\n"); ++ ++ /* Use I2C operations unless we're stuck with SMBus extensions. */ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { ++ if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { ++ use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; ++ } else if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_WORD_DATA)) { ++ use_smbus = I2C_SMBUS_WORD_DATA; ++ } else if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_BYTE_DATA)) { ++ use_smbus = I2C_SMBUS_BYTE_DATA; ++ } else { ++ err = -EPFNOSUPPORT; ++ goto exit; ++ } ++ } ++ ++ /* Mechanism to handle addresses greater than 256 by 8 bit addressing mode is ++ * by registering addresses 256-512 as another chip ++ */ ++ num_addresses = 2; ++ ++ if (!(sff_8436 = kzalloc(sizeof(struct sff_8436_data) + ++ num_addresses * sizeof(struct i2c_client *), GFP_KERNEL))) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ mutex_init(&sff_8436->lock); ++ sff_8436->use_smbus = use_smbus; ++ sff_8436->chip = chip; ++ sff_8436->num_addresses = num_addresses; ++ ++ /* ++ * Export the EEPROM bytes through sysfs, since that's convenient. ++ * By default, only root should see the data (maybe passwords etc) ++ */ ++ sysfs_bin_attr_init(&sff_8436->bin); ++ sff_8436->bin.attr.name = "eeprom"; ++ sff_8436->bin.attr.mode = SFF_8436_FLAG_IRUGO; ++ sff_8436->bin.read = sff_8436_bin_read; ++ sff_8436->bin.size = SFF_8436_EEPROM_SIZE; ++ ++ sff_8436->macc.read = sff_8436_macc_read; ++ ++ if (!use_smbus || ++ (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_WORD_DATA) || ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { ++ //unsigned write_max = chip.page_size; ++ /* ++ * NOTE: AN-2079 ++ * Finisar recommends that the host implement 1 byte writes only, ++ * since this module only supports 32 byte page boundaries. ++ * 2 byte writes are acceptable for PE and Vout changes per ++ * Application Note AN-2071. ++ */ ++ unsigned write_max = 1; ++ ++ sff_8436->macc.write = sff_8436_macc_write; ++ ++ sff_8436->bin.write = sff_8436_bin_write; ++ sff_8436->bin.attr.mode |= S_IWUSR; ++ ++ if (write_max > io_limit) ++ write_max = io_limit; ++ if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) ++ write_max = I2C_SMBUS_BLOCK_MAX; ++ sff_8436->write_max = write_max; ++ ++ /* buffer (data + address at the beginning) */ ++ sff_8436->writebuf = kmalloc(write_max + 2, GFP_KERNEL); ++ if (!sff_8436->writebuf) { ++ err = -ENOMEM; ++ goto exit_kfree; ++ } ++ } else { ++ dev_warn(&client->dev, ++ "cannot write due to controller restrictions."); ++ } ++ ++ memset(sff_8436->data, 0xff, SFF_8436_EEPROM_SIZE); ++ ++ sff_8436->client[0] = client; ++ ++ /* use dummy devices for multiple-address chips */ ++ for (i = 1; i < num_addresses; i++) { ++ sff_8436->client[i] = i2c_new_dummy(client->adapter, ++ client->addr + i); ++ if (!sff_8436->client[i]) { ++ dev_err(&client->dev, "address 0x%02x unavailable\n", ++ client->addr + i); ++ err = -EADDRINUSE; ++ goto err_struct; ++ } ++ } ++ ++ /* create the sysfs eeprom file */ ++ err = sysfs_create_bin_file(&client->dev.kobj, &sff_8436->bin); ++ if (err) ++ goto err_struct; ++ ++ sff_8436->attr_group = sff_8436_attr_group; ++ sff_8436->sfp_compat = 0; ++ ++ err = sysfs_create_group(&client->dev.kobj, &sff_8436->attr_group); ++ if (err) { ++ dev_err(&client->dev, "failed to create sysfs attribute group.\n"); ++ goto err_struct; ++ } ++ sff_8436->eeprom_dev = eeprom_device_register(&client->dev, chip.eeprom_data); ++ if (IS_ERR(sff_8436->eeprom_dev)) { ++ dev_err(&client->dev, "error registering eeprom device.\n"); ++ err = PTR_ERR(sff_8436->eeprom_dev); ++ goto err_sysfs_cleanup; ++ } ++ ++ i2c_set_clientdata(client, sff_8436); ++ ++ dev_info(&client->dev, "%zu byte %s EEPROM, %s\n", ++ sff_8436->bin.size, client->name, ++ "read-only"); ++ ++ if (use_smbus == I2C_SMBUS_WORD_DATA || ++ use_smbus == I2C_SMBUS_BYTE_DATA) { ++ dev_notice(&client->dev, "Falling back to %s reads, " ++ "performance will suffer\n", use_smbus == ++ I2C_SMBUS_WORD_DATA ? "word" : "byte"); ++ } ++ ++ if (chip.setup) ++ chip.setup(&sff_8436->macc, chip.context); ++ ++ return 0; ++ ++err_sysfs_cleanup: ++ sysfs_remove_group(&client->dev.kobj, &sff_8436->attr_group); ++ sysfs_remove_bin_file(&client->dev.kobj, &sff_8436->bin); ++ ++err_struct: ++ for (i = 1; i < num_addresses; i++) { ++ if (sff_8436->client[i]) ++ i2c_unregister_device(sff_8436->client[i]); ++ } ++ ++ kfree(sff_8436->writebuf); ++exit_kfree: ++ kfree(sff_8436); ++exit: ++ dev_dbg(&client->dev, "probe error %d\n", err); ++ ++ return err; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static struct i2c_driver sff_8436_driver = { ++ .driver = { ++ .name = "sff8436", ++ .owner = THIS_MODULE, ++ }, ++ .probe = sff_8436_eeprom_probe, ++ .remove = __devexit_p(sff_8436_remove), ++ .id_table = sff8436_ids, ++}; ++ ++static int __init sff_8436_init(void) ++{ ++ if (!io_limit) { ++ pr_err("sff_8436: io_limit must not be 0!\n"); ++ return -EINVAL; ++ } ++ ++ io_limit = rounddown_pow_of_two(io_limit); ++ return i2c_add_driver(&sff_8436_driver); ++} ++module_init(sff_8436_init); ++ ++static void __exit sff_8436_exit(void) ++{ ++ i2c_del_driver(&sff_8436_driver); ++} ++module_exit(sff_8436_exit); ++ ++MODULE_DESCRIPTION("Driver for SFF-8436 based QSFP EEPROMs"); ++MODULE_AUTHOR("VIDYA RAVIPATI "); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/misc/iwmc3200top/fw-download.c b/drivers/misc/iwmc3200top/fw-download.c +index e27afde..407c5ef 100644 +--- a/drivers/misc/iwmc3200top/fw-download.c ++++ b/drivers/misc/iwmc3200top/fw-download.c +@@ -311,11 +311,8 @@ int iwmct_fw_load(struct iwmct_priv *priv) + + /* get the firmware */ + ret = request_firmware(&raw, fw_name, &priv->func->dev); +- if (ret < 0) { +- LOG_ERROR(priv, FW_DOWNLOAD, "%s request_firmware failed %d\n", +- fw_name, ret); ++ if (ret) + goto exit; +- } + + if (raw->size < sizeof(struct iwmct_fw_sec_hdr)) { + LOG_ERROR(priv, FW_DOWNLOAD, "%s smaller then (%zd) (%zd)\n", +diff --git a/drivers/misc/retimer_class.c b/drivers/misc/retimer_class.c +new file mode 100644 +index 0000000..0e59ccf +--- /dev/null ++++ b/drivers/misc/retimer_class.c +@@ -0,0 +1,160 @@ ++/* ++ * retimer_class.c ++ * ++ * This file defines the sysfs class "retimer", for use by RETIMER ++ * drivers. ++ * ++ * Copyright (C) 2014 Cumulus Networks, Inc. ++ * Author: Puneet Shenoy ++ * ++ * Ideas and structure graciously borrowed from the eeprom_class class: ++ * Copyright (C) 2013 Curt Brune ++ * ++ * This program is free software; 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Root retimer "class" object (corresponds to '//class/retimer_dev/') */ ++static struct class *retimer_class; ++ ++#define RETIMER_CLASS_NAME "retimer_dev" ++#define RETIMER_ID_PREFIX "retimer" ++#define RETIMER_ID_FORMAT RETIMER_ID_PREFIX "%d" ++ ++static DEFINE_IDA(retimer_ida); ++ ++/** ++ * retimer_device_register - register w/ retimer class ++ * @dev: the device to register ++ * ++ * retimer_device_unregister() must be called when the device is no ++ * longer needed. ++ * ++ * Creates a new retimer class device that is a child of @dev. Also ++ * creates a symlink in //class/retimer_dev/retimer[N] pointing ++ * to the new device. ++ * ++ * Returns the pointer to the new device. ++ */ ++struct device *retimer_device_register(struct device *dev) ++{ ++ struct device *retimer_dev; ++ int id; ++ ++ id = ida_simple_get(&retimer_ida, 0, 0, GFP_KERNEL); ++ if (id < 0) ++ return ERR_PTR(id); ++ ++ retimer_dev = device_create(retimer_class, dev, MKDEV(0, 0), NULL, ++ RETIMER_ID_FORMAT, id); ++ ++ if (IS_ERR(retimer_dev)) ++ ida_simple_remove(&retimer_ida, id); ++ ++ return retimer_dev; ++} ++ ++/** ++ * retimer_device_unregister - removes the previously registered class device ++ * ++ * @dev: the class device to destroy ++ */ ++void retimer_device_unregister(struct device *dev) ++{ ++ int id; ++ ++ if (likely(sscanf(dev_name(dev), RETIMER_ID_FORMAT, &id) == 1)) { ++ device_unregister(dev); ++ ida_simple_remove(&retimer_ida, id); ++ } else ++ dev_dbg(dev->parent, ++ "retimer_device_unregister() failed: bad class ID!\n"); ++} ++ ++/** ++ * Each member of the retimer class exports a sysfs file called ++ * "label", containing the label property from the corresponding ++ * device tree node. ++ * ++ * Userspace can use the label to identify what the RETIMER is for. ++ */ ++static ssize_t label_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ const char* cp = NULL; ++ int len = 0; ++ ++ /* ++ * The class device is a child of the original device, ++ * i.e. dev->parent points to the original device. ++ */ ++ if (dev->parent && dev->parent->of_node) ++ cp = of_get_property(dev->parent->of_node, "label", &len); ++ ++ if ((cp == NULL) || (len == 0)) { ++ cp = "unknown"; ++ len = strlen(cp) + 1; ++ } ++ ++ strncpy(buf, cp, len - 1); ++ buf[len - 1] = '\n'; ++ buf[len] = '\0'; ++ ++ return len; ++} ++ ++struct device_attribute retimer_class_dev_attrs[] = { ++ __ATTR_RO(label), ++ __ATTR_NULL, ++}; ++ ++static int __init retimer_init(void) ++{ ++ retimer_class = class_create(THIS_MODULE, RETIMER_CLASS_NAME); ++ if (IS_ERR(retimer_class)) { ++ pr_err("couldn't create sysfs class\n"); ++ return PTR_ERR(retimer_class); ++ } ++ ++ retimer_class->dev_attrs = retimer_class_dev_attrs; ++ ++ return 0; ++} ++ ++static void __exit retimer_exit(void) ++{ ++ class_destroy(retimer_class); ++} ++ ++subsys_initcall(retimer_init); ++module_exit(retimer_exit); ++ ++EXPORT_SYMBOL_GPL(retimer_device_register); ++EXPORT_SYMBOL_GPL(retimer_device_unregister); ++ ++MODULE_AUTHOR("Puneet Shenoy "); ++MODULE_DESCRIPTION("retimer sysfs/class support"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c +index 43ef8d1..5e4fe09 100644 +--- a/drivers/misc/ti-st/st_kim.c ++++ b/drivers/misc/ti-st/st_kim.c +@@ -281,11 +281,8 @@ static long download_firmware(struct kim_data_s *kim_gdata) + request_firmware(&kim_gdata->fw_entry, bts_scr_name, + &kim_gdata->kim_pdev->dev); + if (unlikely((err != 0) || (kim_gdata->fw_entry->data == NULL) || +- (kim_gdata->fw_entry->size == 0))) { +- pr_err(" request_firmware failed(errno %ld) for %s", err, +- bts_scr_name); ++ (kim_gdata->fw_entry->size == 0))) + return -EINVAL; +- } + ptr = (void *)kim_gdata->fw_entry->data; + len = kim_gdata->fw_entry->size; + /* bts_header to remove out magic number and +diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile +index 12eef39..400756e 100644 +--- a/drivers/mmc/Makefile ++++ b/drivers/mmc/Makefile +@@ -6,5 +6,4 @@ subdir-ccflags-$(CONFIG_MMC_DEBUG) := -DDEBUG + + obj-$(CONFIG_MMC) += core/ + obj-$(CONFIG_MMC) += card/ +-obj-$(CONFIG_MMC) += host/ +- ++obj-$(subst m,y,$(CONFIG_MMC)) += host/ +diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig +index 3b1f783..5562308 100644 +--- a/drivers/mmc/card/Kconfig ++++ b/drivers/mmc/card/Kconfig +@@ -52,6 +52,7 @@ config MMC_BLOCK_BOUNCE + + config SDIO_UART + tristate "SDIO UART/GPS class support" ++ depends on TTY + help + SDIO function driver for SDIO cards that implements the UART + class, as well as the GPS class which appears like a UART. +diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c +index f53d5c8..1b0ffea 100644 +--- a/drivers/mmc/card/block.c ++++ b/drivers/mmc/card/block.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -41,7 +42,6 @@ + #include + #include + +-#include + #include + + #include "queue.h" +@@ -58,6 +58,15 @@ MODULE_ALIAS("mmc:block"); + #define INAND_CMD38_ARG_SECERASE 0x80 + #define INAND_CMD38_ARG_SECTRIM1 0x81 + #define INAND_CMD38_ARG_SECTRIM2 0x88 ++#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ ++#define MMC_SANITIZE_REQ_TIMEOUT 240000 ++#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16) ++ ++#define mmc_req_rel_wr(req) (((req->cmd_flags & REQ_FUA) || \ ++ (req->cmd_flags & REQ_META)) && \ ++ (rq_data_dir(req) == WRITE)) ++#define PACKED_CMD_VER 0x01 ++#define PACKED_CMD_WR 0x02 + + static DEFINE_MUTEX(block_mutex); + +@@ -89,6 +98,7 @@ struct mmc_blk_data { + unsigned int flags; + #define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */ + #define MMC_BLK_REL_WR (1 << 1) /* MMC Reliable write support */ ++#define MMC_BLK_PACKED_CMD (1 << 2) /* MMC packed command support */ + + unsigned int usage; + unsigned int read_only; +@@ -107,23 +117,38 @@ struct mmc_blk_data { + */ + unsigned int part_curr; + struct device_attribute force_ro; ++ struct device_attribute power_ro_lock; ++ int area_type; + }; + + static DEFINE_MUTEX(open_lock); + +-enum mmc_blk_status { +- MMC_BLK_SUCCESS = 0, +- MMC_BLK_PARTIAL, +- MMC_BLK_CMD_ERR, +- MMC_BLK_RETRY, +- MMC_BLK_ABORT, +- MMC_BLK_DATA_ERR, +- MMC_BLK_ECC_ERR, ++enum { ++ MMC_PACKED_NR_IDX = -1, ++ MMC_PACKED_NR_ZERO, ++ MMC_PACKED_NR_SINGLE, + }; + + module_param(perdev_minors, int, 0444); + MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); + ++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); ++ ++static inline void mmc_blk_clear_packed(struct mmc_queue_req *mqrq) ++{ ++ struct mmc_packed *packed = mqrq->packed; ++ ++ BUG_ON(!packed); ++ ++ mqrq->cmd_type = MMC_PACKED_NONE; ++ packed->nr_entries = MMC_PACKED_NR_ZERO; ++ packed->idx_failure = MMC_PACKED_NR_IDX; ++ packed->retries = 0; ++ packed->blocks = 0; ++} ++ + static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) + { + struct mmc_blk_data *md; +@@ -165,6 +190,70 @@ static void mmc_blk_put(struct mmc_blk_data *md) + mutex_unlock(&open_lock); + } + ++static ssize_t power_ro_lock_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int ret; ++ struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); ++ struct mmc_card *card = md->queue.card; ++ int locked = 0; ++ ++ if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PERM_WP_EN) ++ locked = 2; ++ else if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_EN) ++ locked = 1; ++ ++ ret = snprintf(buf, PAGE_SIZE, "%d\n", locked); ++ ++ return ret; ++} ++ ++static ssize_t power_ro_lock_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ int ret; ++ struct mmc_blk_data *md, *part_md; ++ struct mmc_card *card; ++ unsigned long set; ++ ++ if (kstrtoul(buf, 0, &set)) ++ return -EINVAL; ++ ++ if (set != 1) ++ return count; ++ ++ md = mmc_blk_get(dev_to_disk(dev)); ++ card = md->queue.card; ++ ++ mmc_get_card(card); ++ ++ ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, ++ card->ext_csd.boot_ro_lock | ++ EXT_CSD_BOOT_WP_B_PWR_WP_EN, ++ card->ext_csd.part_time); ++ if (ret) ++ pr_err("%s: Locking boot partition ro until next power on failed: %d\n", md->disk->disk_name, ret); ++ else ++ card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN; ++ ++ mmc_put_card(card); ++ ++ if (!ret) { ++ pr_info("%s: Locking boot partition ro until next power on\n", ++ md->disk->disk_name); ++ set_disk_ro(md->disk, 1); ++ ++ list_for_each_entry(part_md, &md->part, part) ++ if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) { ++ pr_info("%s: Locking boot partition ro until next power on\n", part_md->disk->disk_name); ++ set_disk_ro(part_md->disk, 1); ++ } ++ } ++ ++ mmc_blk_put(md); ++ return count; ++} ++ + static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr, + char *buf) + { +@@ -291,6 +380,66 @@ out: + return ERR_PTR(err); + } + ++static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status, ++ u32 retries_max) ++{ ++ int err; ++ u32 retry_count = 0; ++ ++ if (!status || !retries_max) ++ return -EINVAL; ++ ++ do { ++ err = get_card_status(card, status, 5); ++ if (err) ++ break; ++ ++ if (!R1_STATUS(*status) && ++ (R1_CURRENT_STATE(*status) != R1_STATE_PRG)) ++ break; /* RPMB programming operation complete */ ++ ++ /* ++ * Rechedule to give the MMC device a chance to continue ++ * processing the previous command without being polled too ++ * frequently. ++ */ ++ usleep_range(1000, 5000); ++ } while (++retry_count < retries_max); ++ ++ if (retry_count == retries_max) ++ err = -EPERM; ++ ++ return err; ++} ++ ++static int ioctl_do_sanitize(struct mmc_card *card) ++{ ++ int err; ++ ++ if (!mmc_can_sanitize(card)) { ++ pr_warn("%s: %s - SANITIZE is not supported\n", ++ mmc_hostname(card->host), __func__); ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ pr_debug("%s: %s - SANITIZE IN PROGRESS...\n", ++ mmc_hostname(card->host), __func__); ++ ++ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, ++ EXT_CSD_SANITIZE_START, 1, ++ MMC_SANITIZE_REQ_TIMEOUT); ++ ++ if (err) ++ pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n", ++ mmc_hostname(card->host), __func__, err); ++ ++ pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host), ++ __func__); ++out: ++ return err; ++} ++ + static int mmc_blk_ioctl_cmd(struct block_device *bdev, + struct mmc_ioc_cmd __user *ic_ptr) + { +@@ -302,6 +451,8 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, + struct mmc_request mrq = {NULL}; + struct scatterlist sg; + int err; ++ int is_rpmb = false; ++ u32 status = 0; + + /* + * The caller must have CAP_SYS_RAWIO, and must be calling this on the +@@ -318,9 +469,12 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, + md = mmc_blk_get(bdev->bd_disk); + if (!md) { + err = -EINVAL; +- goto cmd_done; ++ goto cmd_err; + } + ++ if (md->area_type & MMC_BLK_DATA_AREA_RPMB) ++ is_rpmb = true; ++ + card = md->queue.card; + if (IS_ERR(card)) { + err = PTR_ERR(card); +@@ -369,7 +523,11 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, + + mrq.cmd = &cmd; + +- mmc_claim_host(card->host); ++ mmc_get_card(card); ++ ++ err = mmc_blk_part_switch(card, md); ++ if (err) ++ goto cmd_rel_host; + + if (idata->ic.is_acmd) { + err = mmc_app_cmd(card->host, card); +@@ -377,6 +535,24 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, + goto cmd_rel_host; + } + ++ if (is_rpmb) { ++ err = mmc_set_blockcount(card, data.blocks, ++ idata->ic.write_flag & (1 << 31)); ++ if (err) ++ goto cmd_rel_host; ++ } ++ ++ if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) && ++ (cmd.opcode == MMC_SWITCH)) { ++ err = ioctl_do_sanitize(card); ++ ++ if (err) ++ pr_err("%s: ioctl_do_sanitize() failed. err = %d", ++ __func__, err); ++ ++ goto cmd_rel_host; ++ } ++ + mmc_wait_for_req(card->host, &mrq); + + if (cmd.error) { +@@ -412,11 +588,24 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, + } + } + ++ if (is_rpmb) { ++ /* ++ * Ensure RPMB command has completed by polling CMD13 ++ * "Send Status". ++ */ ++ err = ioctl_rpmb_card_status_poll(card, &status, 5); ++ if (err) ++ dev_err(mmc_dev(card->host), ++ "%s: Card Status=0x%08X, error %d\n", ++ __func__, status, err); ++ } ++ + cmd_rel_host: +- mmc_release_host(card->host); ++ mmc_put_card(card); + + cmd_done: + mmc_blk_put(md); ++cmd_err: + kfree(idata->buf); + kfree(idata); + return err; +@@ -487,7 +676,6 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card) + struct mmc_request mrq = {NULL}; + struct mmc_command cmd = {0}; + struct mmc_data data = {0}; +- unsigned int timeout_us; + + struct scatterlist sg; + +@@ -507,23 +695,12 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card) + cmd.arg = 0; + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + +- data.timeout_ns = card->csd.tacc_ns * 100; +- data.timeout_clks = card->csd.tacc_clks * 100; +- +- timeout_us = data.timeout_ns / 1000; +- timeout_us += data.timeout_clks * 1000 / +- (card->host->ios.clock / 1000); +- +- if (timeout_us > 100000) { +- data.timeout_ns = 100000000; +- data.timeout_clks = 0; +- } +- + data.blksz = 4; + data.blocks = 1; + data.flags = MMC_DATA_READ; + data.sg = &sg; + data.sg_len = 1; ++ mmc_set_data_timeout(&data, card); + + mrq.cmd = &cmd; + mrq.data = &data; +@@ -545,19 +722,6 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card) + return result; + } + +-static int send_stop(struct mmc_card *card, u32 *status) +-{ +- 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(card->host, &cmd, 5); +- if (err == 0) +- *status = cmd.resp[0]; +- return err; +-} +- + static int get_card_status(struct mmc_card *card, u32 *status, int retries) + { + struct mmc_command cmd = {0}; +@@ -573,6 +737,100 @@ static int get_card_status(struct mmc_card *card, u32 *status, int retries) + return err; + } + ++static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms, ++ bool hw_busy_detect, struct request *req, int *gen_err) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); ++ int err = 0; ++ u32 status; ++ ++ do { ++ err = get_card_status(card, &status, 5); ++ if (err) { ++ pr_err("%s: error %d requesting status\n", ++ req->rq_disk->disk_name, err); ++ return err; ++ } ++ ++ if (status & R1_ERROR) { ++ pr_err("%s: %s: error sending status cmd, status %#x\n", ++ req->rq_disk->disk_name, __func__, status); ++ *gen_err = 1; ++ } ++ ++ /* We may rely on the host hw to handle busy detection.*/ ++ if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && ++ hw_busy_detect) ++ break; ++ ++ /* ++ * Timeout if the device never becomes ready for data and never ++ * leaves the program state. ++ */ ++ if (time_after(jiffies, timeout)) { ++ pr_err("%s: Card stuck in programming state! %s %s\n", ++ mmc_hostname(card->host), ++ req->rq_disk->disk_name, __func__); ++ return -ETIMEDOUT; ++ } ++ ++ /* ++ * Some cards mishandle the status bits, ++ * so make sure to check both the busy ++ * indication and the card state. ++ */ ++ } while (!(status & R1_READY_FOR_DATA) || ++ (R1_CURRENT_STATE(status) == R1_STATE_PRG)); ++ ++ return err; ++} ++ ++static int send_stop(struct mmc_card *card, unsigned int timeout_ms, ++ struct request *req, int *gen_err, u32 *stop_status) ++{ ++ struct mmc_host *host = card->host; ++ struct mmc_command cmd = {0}; ++ int err; ++ bool use_r1b_resp = rq_data_dir(req) == WRITE; ++ ++ /* ++ * Normally we use R1B responses for WRITE, but in cases where the host ++ * has specified a max_busy_timeout we need to validate it. A failure ++ * means we need to prevent the host from doing hw busy detection, which ++ * is done by converting to a R1 response instead. ++ */ ++ if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) ++ use_r1b_resp = false; ++ ++ cmd.opcode = MMC_STOP_TRANSMISSION; ++ if (use_r1b_resp) { ++ cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; ++ cmd.busy_timeout = timeout_ms; ++ } else { ++ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; ++ } ++ ++ err = mmc_wait_for_cmd(host, &cmd, 5); ++ if (err) ++ return err; ++ ++ *stop_status = cmd.resp[0]; ++ ++ /* No need to check card status in case of READ. */ ++ if (rq_data_dir(req) == READ) ++ return 0; ++ ++ if (!mmc_host_is_spi(host) && ++ (*stop_status & R1_ERROR)) { ++ pr_err("%s: %s: general error sending stop command, resp %#x\n", ++ req->rq_disk->disk_name, __func__, *stop_status); ++ *gen_err = 1; ++ } ++ ++ return card_busy_detect(card, timeout_ms, use_r1b_resp, req, gen_err); ++} ++ ++#define ERR_NOMEDIUM 3 + #define ERR_RETRY 2 + #define ERR_ABORT 1 + #define ERR_CONTINUE 0 +@@ -640,6 +898,9 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, + u32 status, stop_status = 0; + int err, retry; + ++ if (mmc_card_removed(card)) ++ return ERR_NOMEDIUM; ++ + /* + * Try to get card status which indicates both the card state + * and why there was no response. If the first attempt fails, +@@ -656,8 +917,12 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, + } + + /* We couldn't get a response from the card. Give up. */ +- if (err) ++ if (err) { ++ /* Check if the card is removed */ ++ if (mmc_detect_card_removed(card->host)) ++ return ERR_NOMEDIUM; + return ERR_ABORT; ++ } + + /* Flag ECC errors */ + if ((status & R1_CARD_ECC_FAILED) || +@@ -681,26 +946,21 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, + */ + if (R1_CURRENT_STATE(status) == R1_STATE_DATA || + R1_CURRENT_STATE(status) == R1_STATE_RCV) { +- err = send_stop(card, &stop_status); +- if (err) ++ err = send_stop(card, ++ DIV_ROUND_UP(brq->data.timeout_ns, 1000000), ++ req, gen_err, &stop_status); ++ if (err) { + pr_err("%s: error %d sending stop command\n", + req->rq_disk->disk_name, err); +- +- /* +- * If the stop cmd also timed out, the card is probably +- * not present, so abort. Other errors are bad news too. +- */ +- if (err) ++ /* ++ * If the stop cmd also timed out, the card is probably ++ * not present, so abort. Other errors are bad news too. ++ */ + return ERR_ABORT; ++ } ++ + if (stop_status & R1_CARD_ECC_FAILED) + *ecc_err = 1; +- if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) +- if (stop_status & R1_ERROR) { +- pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n", +- req->rq_disk->disk_name, __func__, +- stop_status); +- *gen_err = 1; +- } + } + + /* Check for set block count errors */ +@@ -804,9 +1064,7 @@ out: + goto retry; + if (!err) + mmc_blk_reset_success(md, type); +- spin_lock_irq(&md->lock); +- __blk_end_request(req, err, blk_rq_bytes(req)); +- spin_unlock_irq(&md->lock); ++ blk_end_request(req, err, blk_rq_bytes(req)); + + return err ? 0 : 1; + } +@@ -816,10 +1074,10 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, + { + struct mmc_blk_data *md = mq->data; + struct mmc_card *card = md->queue.card; +- unsigned int from, nr, arg, trim_arg, erase_arg; ++ unsigned int from, nr, arg; + int err = 0, type = MMC_BLK_SECDISCARD; + +- if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) { ++ if (!(mmc_can_secure_erase_trim(card))) { + err = -EOPNOTSUPP; + goto out; + } +@@ -827,23 +1085,11 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, + from = blk_rq_pos(req); + nr = blk_rq_sectors(req); + +- /* The sanitize operation is supported at v4.5 only */ +- if (mmc_can_sanitize(card)) { +- erase_arg = MMC_ERASE_ARG; +- trim_arg = MMC_TRIM_ARG; +- } else { +- erase_arg = MMC_SECURE_ERASE_ARG; +- trim_arg = MMC_SECURE_TRIM1_ARG; +- } ++ if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr)) ++ arg = MMC_SECURE_TRIM1_ARG; ++ else ++ arg = MMC_SECURE_ERASE_ARG; + +- if (mmc_erase_group_aligned(card, from, nr)) +- arg = erase_arg; +- else if (mmc_can_trim(card)) +- arg = trim_arg; +- else { +- err = -EINVAL; +- goto out; +- } + retry: + if (card->quirks & MMC_QUIRK_INAND_CMD38) { + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +@@ -879,18 +1125,13 @@ retry: + goto out; + } + +- if (mmc_can_sanitize(card)) +- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +- EXT_CSD_SANITIZE_START, 1, 0); + out_retry: + if (err && !mmc_blk_reset(md, card->host, type)) + goto retry; + if (!err) + mmc_blk_reset_success(md, type); + out: +- spin_lock_irq(&md->lock); +- __blk_end_request(req, err, blk_rq_bytes(req)); +- spin_unlock_irq(&md->lock); ++ blk_end_request(req, err, blk_rq_bytes(req)); + + return err ? 0 : 1; + } +@@ -905,9 +1146,7 @@ static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req) + if (ret) + ret = -EIO; + +- spin_lock_irq(&md->lock); +- __blk_end_request_all(req, ret); +- spin_unlock_irq(&md->lock); ++ blk_end_request_all(req, ret); + + return ret ? 0 : 1; + } +@@ -969,6 +1208,8 @@ static int mmc_blk_err_check(struct mmc_card *card, + return MMC_BLK_RETRY; + case ERR_ABORT: + return MMC_BLK_ABORT; ++ case ERR_NOMEDIUM: ++ return MMC_BLK_NOMEDIUM; + case ERR_CONTINUE: + break; + } +@@ -991,7 +1232,7 @@ static int mmc_blk_err_check(struct mmc_card *card, + * program mode, which we have to wait for it to complete. + */ + if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) { +- u32 status; ++ int err; + + /* Check stop command response */ + if (brq->stop.resp[0] & R1_ERROR) { +@@ -1001,33 +1242,15 @@ static int mmc_blk_err_check(struct mmc_card *card, + gen_err = 1; + } + +- do { +- int err = get_card_status(card, &status, 5); +- if (err) { +- pr_err("%s: error %d requesting status\n", +- req->rq_disk->disk_name, err); +- return MMC_BLK_CMD_ERR; +- } +- +- if (status & R1_ERROR) { +- pr_err("%s: %s: general error sending status command, card status %#x\n", +- req->rq_disk->disk_name, __func__, +- status); +- gen_err = 1; +- } +- +- /* +- * Some cards mishandle the status bits, +- * so make sure to check both the busy +- * indication and the card state. +- */ +- } while (!(status & R1_READY_FOR_DATA) || +- (R1_CURRENT_STATE(status) == R1_STATE_PRG)); ++ err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, false, req, ++ &gen_err); ++ if (err) ++ return MMC_BLK_CMD_ERR; + } + + /* if general error occurs, retry the write operation. */ + if (gen_err) { +- pr_warning("%s: retrying write for general error\n", ++ pr_warn("%s: retrying write for general error\n", + req->rq_disk->disk_name); + return MMC_BLK_RETRY; + } +@@ -1051,12 +1274,78 @@ 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; + } + ++static int mmc_blk_packed_err_check(struct mmc_card *card, ++ struct mmc_async_req *areq) ++{ ++ struct mmc_queue_req *mq_rq = container_of(areq, struct mmc_queue_req, ++ mmc_active); ++ struct request *req = mq_rq->req; ++ struct mmc_packed *packed = mq_rq->packed; ++ int err, check, status; ++ u8 *ext_csd; ++ ++ BUG_ON(!packed); ++ ++ packed->retries--; ++ check = mmc_blk_err_check(card, areq); ++ err = get_card_status(card, &status, 0); ++ if (err) { ++ pr_err("%s: error %d sending status command\n", ++ req->rq_disk->disk_name, err); ++ return MMC_BLK_ABORT; ++ } ++ ++ if (status & R1_EXCEPTION_EVENT) { ++ ext_csd = kzalloc(512, GFP_KERNEL); ++ if (!ext_csd) { ++ pr_err("%s: unable to allocate buffer for ext_csd\n", ++ req->rq_disk->disk_name); ++ return -ENOMEM; ++ } ++ ++ err = mmc_send_ext_csd(card, ext_csd); ++ if (err) { ++ pr_err("%s: error %d sending ext_csd\n", ++ req->rq_disk->disk_name, err); ++ check = MMC_BLK_ABORT; ++ goto free; ++ } ++ ++ if ((ext_csd[EXT_CSD_EXP_EVENTS_STATUS] & ++ EXT_CSD_PACKED_FAILURE) && ++ (ext_csd[EXT_CSD_PACKED_CMD_STATUS] & ++ EXT_CSD_PACKED_GENERIC_ERROR)) { ++ if (ext_csd[EXT_CSD_PACKED_CMD_STATUS] & ++ EXT_CSD_PACKED_INDEXED_ERROR) { ++ packed->idx_failure = ++ ext_csd[EXT_CSD_PACKED_FAILURE_INDEX] - 1; ++ check = MMC_BLK_PARTIAL; ++ } ++ pr_err("%s: packed cmd failed, nr %u, sectors %u, " ++ "failure index: %d\n", ++ req->rq_disk->disk_name, packed->nr_entries, ++ packed->blocks, packed->idx_failure); ++ } ++free: ++ kfree(ext_csd); ++ } ++ ++ return check; ++} ++ + static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + struct mmc_card *card, + int disable_multi, +@@ -1066,6 +1355,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + struct mmc_blk_request *brq = &mqrq->brq; + struct request *req = mqrq->req; + struct mmc_blk_data *md = mq->data; ++ bool do_data_tag; + + /* + * Reliable writes are used to implement Forced Unit Access and +@@ -1090,7 +1380,6 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + brq->data.blksz = 512; + brq->stop.opcode = MMC_STOP_TRANSMISSION; + brq->stop.arg = 0; +- brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + brq->data.blocks = blk_rq_sectors(req); + + /* +@@ -1133,15 +1422,31 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + 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); + + /* ++ * 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, +@@ -1159,13 +1464,13 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + * 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))) { ++ 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_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; + } +@@ -1200,10 +1505,221 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + mmc_queue_bounce_pre(mqrq); + } + ++static inline u8 mmc_calc_packed_hdr_segs(struct request_queue *q, ++ struct mmc_card *card) ++{ ++ unsigned int hdr_sz = mmc_large_sector(card) ? 4096 : 512; ++ unsigned int max_seg_sz = queue_max_segment_size(q); ++ unsigned int len, nr_segs = 0; ++ ++ do { ++ len = min(hdr_sz, max_seg_sz); ++ hdr_sz -= len; ++ nr_segs++; ++ } while (hdr_sz); ++ ++ return nr_segs; ++} ++ ++static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req) ++{ ++ struct request_queue *q = mq->queue; ++ struct mmc_card *card = mq->card; ++ struct request *cur = req, *next = NULL; ++ struct mmc_blk_data *md = mq->data; ++ struct mmc_queue_req *mqrq = mq->mqrq_cur; ++ bool en_rel_wr = card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN; ++ unsigned int req_sectors = 0, phys_segments = 0; ++ unsigned int max_blk_count, max_phys_segs; ++ bool put_back = true; ++ u8 max_packed_rw = 0; ++ u8 reqs = 0; ++ ++ if (!(md->flags & MMC_BLK_PACKED_CMD)) ++ goto no_packed; ++ ++ if ((rq_data_dir(cur) == WRITE) && ++ mmc_host_packed_wr(card->host)) ++ max_packed_rw = card->ext_csd.max_packed_writes; ++ ++ if (max_packed_rw == 0) ++ goto no_packed; ++ ++ if (mmc_req_rel_wr(cur) && ++ (md->flags & MMC_BLK_REL_WR) && !en_rel_wr) ++ goto no_packed; ++ ++ if (mmc_large_sector(card) && ++ !IS_ALIGNED(blk_rq_sectors(cur), 8)) ++ goto no_packed; ++ ++ mmc_blk_clear_packed(mqrq); ++ ++ max_blk_count = min(card->host->max_blk_count, ++ card->host->max_req_size >> 9); ++ if (unlikely(max_blk_count > 0xffff)) ++ max_blk_count = 0xffff; ++ ++ max_phys_segs = queue_max_segments(q); ++ req_sectors += blk_rq_sectors(cur); ++ phys_segments += cur->nr_phys_segments; ++ ++ if (rq_data_dir(cur) == WRITE) { ++ req_sectors += mmc_large_sector(card) ? 8 : 1; ++ phys_segments += mmc_calc_packed_hdr_segs(q, card); ++ } ++ ++ do { ++ if (reqs >= max_packed_rw - 1) { ++ put_back = false; ++ break; ++ } ++ ++ spin_lock_irq(q->queue_lock); ++ next = blk_fetch_request(q); ++ spin_unlock_irq(q->queue_lock); ++ if (!next) { ++ put_back = false; ++ break; ++ } ++ ++ if (mmc_large_sector(card) && ++ !IS_ALIGNED(blk_rq_sectors(next), 8)) ++ break; ++ ++ if (next->cmd_flags & REQ_DISCARD || ++ next->cmd_flags & REQ_FLUSH) ++ break; ++ ++ if (rq_data_dir(cur) != rq_data_dir(next)) ++ break; ++ ++ if (mmc_req_rel_wr(next) && ++ (md->flags & MMC_BLK_REL_WR) && !en_rel_wr) ++ break; ++ ++ req_sectors += blk_rq_sectors(next); ++ if (req_sectors > max_blk_count) ++ break; ++ ++ phys_segments += next->nr_phys_segments; ++ if (phys_segments > max_phys_segs) ++ break; ++ ++ list_add_tail(&next->queuelist, &mqrq->packed->list); ++ cur = next; ++ reqs++; ++ } while (1); ++ ++ if (put_back) { ++ spin_lock_irq(q->queue_lock); ++ blk_requeue_request(q, next); ++ spin_unlock_irq(q->queue_lock); ++ } ++ ++ if (reqs > 0) { ++ list_add(&req->queuelist, &mqrq->packed->list); ++ mqrq->packed->nr_entries = ++reqs; ++ mqrq->packed->retries = reqs; ++ return reqs; ++ } ++ ++no_packed: ++ mqrq->cmd_type = MMC_PACKED_NONE; ++ return 0; ++} ++ ++static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq, ++ struct mmc_card *card, ++ struct mmc_queue *mq) ++{ ++ struct mmc_blk_request *brq = &mqrq->brq; ++ struct request *req = mqrq->req; ++ struct request *prq; ++ struct mmc_blk_data *md = mq->data; ++ struct mmc_packed *packed = mqrq->packed; ++ bool do_rel_wr, do_data_tag; ++ u32 *packed_cmd_hdr; ++ u8 hdr_blocks; ++ u8 i = 1; ++ ++ BUG_ON(!packed); ++ ++ mqrq->cmd_type = MMC_PACKED_WRITE; ++ packed->blocks = 0; ++ packed->idx_failure = MMC_PACKED_NR_IDX; ++ ++ packed_cmd_hdr = packed->cmd_hdr; ++ memset(packed_cmd_hdr, 0, sizeof(packed->cmd_hdr)); ++ packed_cmd_hdr[0] = (packed->nr_entries << 16) | ++ (PACKED_CMD_WR << 8) | PACKED_CMD_VER; ++ hdr_blocks = mmc_large_sector(card) ? 8 : 1; ++ ++ /* ++ * Argument for each entry of packed group ++ */ ++ list_for_each_entry(prq, &packed->list, queuelist) { ++ do_rel_wr = mmc_req_rel_wr(prq) && (md->flags & MMC_BLK_REL_WR); ++ do_data_tag = (card->ext_csd.data_tag_unit_size) && ++ (prq->cmd_flags & REQ_META) && ++ (rq_data_dir(prq) == WRITE) && ++ ((brq->data.blocks * brq->data.blksz) >= ++ card->ext_csd.data_tag_unit_size); ++ /* Argument of CMD23 */ ++ packed_cmd_hdr[(i * 2)] = ++ (do_rel_wr ? MMC_CMD23_ARG_REL_WR : 0) | ++ (do_data_tag ? MMC_CMD23_ARG_TAG_REQ : 0) | ++ blk_rq_sectors(prq); ++ /* Argument of CMD18 or CMD25 */ ++ packed_cmd_hdr[((i * 2)) + 1] = ++ mmc_card_blockaddr(card) ? ++ blk_rq_pos(prq) : blk_rq_pos(prq) << 9; ++ packed->blocks += blk_rq_sectors(prq); ++ i++; ++ } ++ ++ memset(brq, 0, sizeof(struct mmc_blk_request)); ++ brq->mrq.cmd = &brq->cmd; ++ brq->mrq.data = &brq->data; ++ brq->mrq.sbc = &brq->sbc; ++ brq->mrq.stop = &brq->stop; ++ ++ brq->sbc.opcode = MMC_SET_BLOCK_COUNT; ++ brq->sbc.arg = MMC_CMD23_ARG_PACKED | (packed->blocks + hdr_blocks); ++ brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC; ++ ++ brq->cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK; ++ 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->data.blksz = 512; ++ brq->data.blocks = packed->blocks + hdr_blocks; ++ brq->data.flags |= MMC_DATA_WRITE; ++ ++ brq->stop.opcode = MMC_STOP_TRANSMISSION; ++ brq->stop.arg = 0; ++ brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; ++ ++ mmc_set_data_timeout(&brq->data, card); ++ ++ brq->data.sg = mqrq->sg; ++ brq->data.sg_len = mmc_queue_map_sg(mq, mqrq); ++ ++ mqrq->mmc_active.mrq = &brq->mrq; ++ mqrq->mmc_active.err_check = mmc_blk_packed_err_check; ++ ++ mmc_queue_bounce_pre(mqrq); ++} ++ + static int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card, + struct mmc_blk_request *brq, struct request *req, + int ret) + { ++ struct mmc_queue_req *mq_rq; ++ mq_rq = container_of(brq, struct mmc_queue_req, brq); ++ + /* + * If this is an SD card and we're writing, we can first + * mark the known good sectors as ok. +@@ -1217,18 +1733,87 @@ static int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card, + + blocks = mmc_sd_num_wr_blocks(card); + if (blocks != (u32)-1) { +- spin_lock_irq(&md->lock); +- ret = __blk_end_request(req, 0, blocks << 9); +- spin_unlock_irq(&md->lock); ++ ret = blk_end_request(req, 0, blocks << 9); + } + } else { +- spin_lock_irq(&md->lock); +- ret = __blk_end_request(req, 0, brq->data.bytes_xfered); +- spin_unlock_irq(&md->lock); ++ if (!mmc_packed_cmd(mq_rq->cmd_type)) ++ ret = blk_end_request(req, 0, brq->data.bytes_xfered); ++ } ++ return ret; ++} ++ ++static int mmc_blk_end_packed_req(struct mmc_queue_req *mq_rq) ++{ ++ struct request *prq; ++ struct mmc_packed *packed = mq_rq->packed; ++ int idx = packed->idx_failure, i = 0; ++ int ret = 0; ++ ++ BUG_ON(!packed); ++ ++ while (!list_empty(&packed->list)) { ++ prq = list_entry_rq(packed->list.next); ++ if (idx == i) { ++ /* retry from error index */ ++ packed->nr_entries -= idx; ++ mq_rq->req = prq; ++ ret = 1; ++ ++ if (packed->nr_entries == MMC_PACKED_NR_SINGLE) { ++ list_del_init(&prq->queuelist); ++ mmc_blk_clear_packed(mq_rq); ++ } ++ return ret; ++ } ++ list_del_init(&prq->queuelist); ++ blk_end_request(prq, 0, blk_rq_bytes(prq)); ++ i++; + } ++ ++ mmc_blk_clear_packed(mq_rq); + return ret; + } + ++static void mmc_blk_abort_packed_req(struct mmc_queue_req *mq_rq) ++{ ++ struct request *prq; ++ struct mmc_packed *packed = mq_rq->packed; ++ ++ BUG_ON(!packed); ++ ++ while (!list_empty(&packed->list)) { ++ prq = list_entry_rq(packed->list.next); ++ list_del_init(&prq->queuelist); ++ blk_end_request(prq, -EIO, blk_rq_bytes(prq)); ++ } ++ ++ mmc_blk_clear_packed(mq_rq); ++} ++ ++static void mmc_blk_revert_packed_req(struct mmc_queue *mq, ++ struct mmc_queue_req *mq_rq) ++{ ++ struct request *prq; ++ struct request_queue *q = mq->queue; ++ struct mmc_packed *packed = mq_rq->packed; ++ ++ BUG_ON(!packed); ++ ++ while (!list_empty(&packed->list)) { ++ prq = list_entry_rq(packed->list.prev); ++ if (prq->queuelist.prev != &packed->list) { ++ list_del_init(&prq->queuelist); ++ spin_lock_irq(q->queue_lock); ++ blk_requeue_request(mq->queue, prq); ++ spin_unlock_irq(q->queue_lock); ++ } else { ++ list_del_init(&prq->queuelist); ++ } ++ } ++ ++ mmc_blk_clear_packed(mq_rq); ++} ++ + static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) + { + struct mmc_blk_data *md = mq->data; +@@ -1237,21 +1822,45 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) + int ret = 1, disable_multi = 0, retry = 0, type; + enum mmc_blk_status status; + struct mmc_queue_req *mq_rq; +- struct request *req; ++ struct request *req = rqc; + struct mmc_async_req *areq; ++ const u8 packed_nr = 2; ++ u8 reqs = 0; + + if (!rqc && !mq->mqrq_prev->req) + return 0; + ++ if (rqc) ++ reqs = mmc_blk_prep_packed_list(mq, rqc); ++ + do { + if (rqc) { +- mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq); ++ /* ++ * 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); ++ mq_rq = mq->mqrq_cur; ++ goto cmd_abort; ++ } ++ ++ if (reqs >= packed_nr) ++ mmc_blk_packed_hdr_wrq_prep(mq->mqrq_cur, ++ card, mq); ++ else ++ mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq); + areq = &mq->mqrq_cur->mmc_active; + } else + areq = NULL; + areq = mmc_start_req(card->host, areq, (int *) &status); +- if (!areq) ++ if (!areq) { ++ if (status == MMC_BLK_NEW_REQUEST) ++ mq->flags |= MMC_QUEUE_NEW_REQUEST; + return 0; ++ } + + mq_rq = container_of(areq, struct mmc_queue_req, mmc_active); + brq = &mq_rq->brq; +@@ -1266,10 +1875,15 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) + * A block was successfully transferred. + */ + mmc_blk_reset_success(md, type); +- spin_lock_irq(&md->lock); +- ret = __blk_end_request(req, 0, ++ ++ if (mmc_packed_cmd(mq_rq->cmd_type)) { ++ ret = mmc_blk_end_packed_req(mq_rq); ++ break; ++ } else { ++ ret = blk_end_request(req, 0, + brq->data.bytes_xfered); +- spin_unlock_irq(&md->lock); ++ } ++ + /* + * If the blk_end_request function returns non-zero even + * though all data has been transferred and no errors +@@ -1304,7 +1918,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) + err = mmc_blk_reset(md, card->host, type); + if (!err) + break; +- if (err == -ENODEV) ++ if (err == -ENODEV || ++ mmc_packed_cmd(mq_rq->cmd_type)) + goto cmd_abort; + /* Fall through */ + } +@@ -1321,37 +1936,69 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) + * time, so we only reach here after trying to + * read a single sector. + */ +- spin_lock_irq(&md->lock); +- ret = __blk_end_request(req, -EIO, ++ ret = blk_end_request(req, -EIO, + brq->data.blksz); +- spin_unlock_irq(&md->lock); + if (!ret) + goto start_new_req; + break; ++ case MMC_BLK_NOMEDIUM: ++ goto cmd_abort; ++ default: ++ pr_err("%s: Unhandled return value (%d)", ++ req->rq_disk->disk_name, status); ++ goto cmd_abort; + } + + if (ret) { +- /* +- * In case of a incomplete request +- * prepare it again and resend. +- */ +- mmc_blk_rw_rq_prep(mq_rq, card, disable_multi, mq); +- mmc_start_req(card->host, &mq_rq->mmc_active, NULL); ++ if (mmc_packed_cmd(mq_rq->cmd_type)) { ++ if (!mq_rq->packed->retries) ++ goto cmd_abort; ++ mmc_blk_packed_hdr_wrq_prep(mq_rq, card, mq); ++ mmc_start_req(card->host, ++ &mq_rq->mmc_active, NULL); ++ } else { ++ ++ /* ++ * In case of a incomplete request ++ * prepare it again and resend. ++ */ ++ mmc_blk_rw_rq_prep(mq_rq, card, ++ disable_multi, mq); ++ mmc_start_req(card->host, ++ &mq_rq->mmc_active, NULL); ++ } + } + } while (ret); + + return 1; + + cmd_abort: +- spin_lock_irq(&md->lock); +- while (ret) +- ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req)); +- spin_unlock_irq(&md->lock); ++ if (mmc_packed_cmd(mq_rq->cmd_type)) { ++ mmc_blk_abort_packed_req(mq_rq); ++ } else { ++ if (mmc_card_removed(card)) ++ req->cmd_flags |= REQ_QUIET; ++ while (ret) ++ ret = blk_end_request(req, -EIO, ++ blk_rq_cur_bytes(req)); ++ } + + start_new_req: + if (rqc) { +- mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq); +- mmc_start_req(card->host, &mq->mqrq_cur->mmc_active, NULL); ++ if (mmc_card_removed(card)) { ++ rqc->cmd_flags |= REQ_QUIET; ++ blk_end_request_all(rqc, -EIO); ++ } else { ++ /* ++ * If current request is packed, it needs to put back. ++ */ ++ if (mmc_packed_cmd(mq->mqrq_cur->cmd_type)) ++ mmc_blk_revert_packed_req(mq, mq->mqrq_cur); ++ ++ mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq); ++ mmc_start_req(card->host, ++ &mq->mqrq_cur->mmc_active, NULL); ++ } + } + + return 0; +@@ -1362,23 +2009,25 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) + int ret; + 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; + + if (req && !mq->mqrq_prev->req) + /* claim host only for the first request */ +- mmc_claim_host(card->host); ++ mmc_get_card(card); + + ret = mmc_blk_part_switch(card, md); + if (ret) { + if (req) { +- spin_lock_irq(&md->lock); +- __blk_end_request_all(req, -EIO); +- spin_unlock_irq(&md->lock); ++ blk_end_request_all(req, -EIO); + } + ret = 0; + goto out; + } + +- if (req && req->cmd_flags & REQ_DISCARD) { ++ 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); +@@ -1387,19 +2036,30 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) + ret = mmc_blk_issue_secdiscard_rq(mq, req); + else + ret = mmc_blk_issue_discard_rq(mq, req); +- } else if (req && req->cmd_flags & REQ_FLUSH) { ++ } 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); + } + + out: +- if (!req) +- /* release host only when there are no more requests */ +- mmc_release_host(card->host); ++ 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'. ++ */ ++ mmc_put_card(card); + return ret; + } + +@@ -1413,7 +2073,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, + struct device *parent, + sector_t size, + bool default_ro, +- const char *subname) ++ const char *subname, ++ int area_type) + { + struct mmc_blk_data *md; + int devidx, ret; +@@ -1438,11 +2099,12 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, + if (!subname) { + md->name_idx = find_first_zero_bit(name_use, max_devices); + __set_bit(md->name_idx, name_use); +- } +- else ++ } else + md->name_idx = ((struct mmc_blk_data *) + dev_to_disk(parent)->private_data)->name_idx; + ++ md->area_type = area_type; ++ + /* + * Set the read-only status based on the supported commands + * and the write protect switch. +@@ -1473,6 +2135,8 @@ 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); ++ if (area_type & MMC_BLK_DATA_AREA_RPMB) ++ md->disk->flags |= GENHD_FL_NO_PART_SCAN; + + /* + * As discussed on lkml, GENHD_FL_REMOVABLE should: +@@ -1489,7 +2153,12 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, + snprintf(md->disk->disk_name, sizeof(md->disk->disk_name), + "mmcblk%d%s", md->name_idx, subname ? subname : ""); + +- blk_queue_logical_block_size(md->queue.queue, 512); ++ if (mmc_card_mmc(card)) ++ blk_queue_logical_block_size(md->queue.queue, ++ card->ext_csd.data_sector_size); ++ else ++ blk_queue_logical_block_size(md->queue.queue, 512); ++ + set_capacity(md->disk, size); + + if (mmc_host_cmd23(card->host)) { +@@ -1507,6 +2176,14 @@ 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: +@@ -1536,7 +2213,8 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) + size = card->csd.capacity << (card->csd.read_blkbits - 9); + } + +- md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL); ++ md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL, ++ MMC_BLK_DATA_AREA_MAIN); + return md; + } + +@@ -1545,13 +2223,14 @@ static int mmc_blk_alloc_part(struct mmc_card *card, + unsigned int part_type, + sector_t size, + bool default_ro, +- const char *subname) ++ const char *subname, ++ int area_type) + { + char cap_str[10]; + struct mmc_blk_data *part_md; + + part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro, +- subname); ++ subname, area_type); + if (IS_ERR(part_md)) + return PTR_ERR(part_md); + part_md->part_type = part_type; +@@ -1584,7 +2263,8 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) + card->part[idx].part_cfg, + card->part[idx].size >> 9, + card->part[idx].force_ro, +- card->part[idx].name); ++ card->part[idx].name, ++ card->part[idx].area_type); + if (ret) + return ret; + } +@@ -1593,36 +2273,29 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) + return ret; + } + +-static int +-mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) +-{ +- int err; +- +- mmc_claim_host(card->host); +- err = mmc_set_blocklen(card, 512); +- mmc_release_host(card->host); +- +- if (err) { +- pr_err("%s: unable to set block size to 512: %d\n", +- md->disk->disk_name, err); +- return -EINVAL; +- } +- +- return 0; +-} +- + static void mmc_blk_remove_req(struct mmc_blk_data *md) + { ++ struct mmc_card *card; ++ + if (md) { ++ /* ++ * Flush remaining requests and free queues. It ++ * is freeing the queue that stops new requests ++ * from being accepted. ++ */ ++ 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) && ++ card->ext_csd.boot_ro_lockable) ++ device_remove_file(disk_to_dev(md->disk), ++ &md->power_ro_lock); + +- /* Stop new requests from getting into the queue */ + del_gendisk(md->disk); + } +- +- /* Then flush out any already in there */ +- mmc_cleanup_queue(&md->queue); + mmc_blk_put(md); + } + } +@@ -1644,6 +2317,7 @@ static void mmc_blk_remove_parts(struct mmc_card *card, + static int mmc_add_disk(struct mmc_blk_data *md) + { + int ret; ++ struct mmc_card *card = md->queue.card; + + add_disk(md->disk); + md->force_ro.show = force_ro_show; +@@ -1653,20 +2327,55 @@ static int mmc_add_disk(struct mmc_blk_data *md) + md->force_ro.attr.mode = S_IRUGO | S_IWUSR; + ret = device_create_file(disk_to_dev(md->disk), &md->force_ro); + if (ret) +- del_gendisk(md->disk); ++ goto force_ro_fail; ++ ++ if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) && ++ card->ext_csd.boot_ro_lockable) { ++ umode_t mode; ++ ++ if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS) ++ mode = S_IRUGO; ++ else ++ mode = S_IRUGO | S_IWUSR; ++ ++ md->power_ro_lock.show = power_ro_lock_show; ++ md->power_ro_lock.store = power_ro_lock_store; ++ sysfs_attr_init(&md->power_ro_lock.attr); ++ md->power_ro_lock.attr.mode = mode; ++ md->power_ro_lock.attr.name = ++ "ro_lock_until_next_power_on"; ++ ret = device_create_file(disk_to_dev(md->disk), ++ &md->power_ro_lock); ++ if (ret) ++ goto power_ro_lock_fail; ++ } ++ return ret; ++ ++power_ro_lock_fail: ++ device_remove_file(disk_to_dev(md->disk), &md->force_ro); ++force_ro_fail: ++ del_gendisk(md->disk); + + return ret; + } + ++#define CID_MANFID_SANDISK 0x2 ++#define CID_MANFID_TOSHIBA 0x11 ++#define CID_MANFID_MICRON 0x13 + #define CID_MANFID_SAMSUNG 0x15 + + static const struct mmc_fixup blk_fixups[] = + { +- MMC_FIXUP("SEM02G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), +- MMC_FIXUP("SEM04G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), +- MMC_FIXUP("SEM08G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), +- MMC_FIXUP("SEM16G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), +- MMC_FIXUP("SEM32G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), ++ MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk, ++ MMC_QUIRK_INAND_CMD38), ++ MMC_FIXUP("SEM04G", CID_MANFID_SANDISK, 0x100, add_quirk, ++ MMC_QUIRK_INAND_CMD38), ++ MMC_FIXUP("SEM08G", CID_MANFID_SANDISK, 0x100, add_quirk, ++ MMC_QUIRK_INAND_CMD38), ++ MMC_FIXUP("SEM16G", CID_MANFID_SANDISK, 0x100, add_quirk, ++ MMC_QUIRK_INAND_CMD38), ++ MMC_FIXUP("SEM32G", CID_MANFID_SANDISK, 0x100, add_quirk, ++ MMC_QUIRK_INAND_CMD38), + + /* + * Some MMC cards experience performance degradation with CMD23 +@@ -1676,18 +2385,18 @@ static const struct mmc_fixup blk_fixups[] = + * + * N.B. This doesn't affect SD cards. + */ +- MMC_FIXUP("MMC08G", 0x11, CID_OEMID_ANY, add_quirk_mmc, ++ MMC_FIXUP("MMC08G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_BLK_NO_CMD23), +- MMC_FIXUP("MMC16G", 0x11, CID_OEMID_ANY, add_quirk_mmc, ++ MMC_FIXUP("MMC16G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_BLK_NO_CMD23), +- MMC_FIXUP("MMC32G", 0x11, CID_OEMID_ANY, add_quirk_mmc, ++ MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_BLK_NO_CMD23), + + /* + * Some Micron MMC cards needs longer data read timeout than + * indicated in CSD. + */ +- MMC_FIXUP(CID_NAME_ANY, 0x13, 0x200, add_quirk_mmc, ++ MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc, + MMC_QUIRK_LONG_READ_TIME), + + /* +@@ -1718,7 +2427,6 @@ static const struct mmc_fixup blk_fixups[] = + static int mmc_blk_probe(struct mmc_card *card) + { + struct mmc_blk_data *md, *part_md; +- int err; + char cap_str[10]; + + /* +@@ -1731,10 +2439,6 @@ static int mmc_blk_probe(struct mmc_card *card) + if (IS_ERR(md)) + return PTR_ERR(md); + +- err = mmc_blk_set_blksize(md, card); +- if (err) +- goto out; +- + string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2, + cap_str, sizeof(cap_str)); + pr_info("%s: %s %s %s %s\n", +@@ -1754,12 +2458,25 @@ static int mmc_blk_probe(struct mmc_card *card) + if (mmc_add_disk(part_md)) + goto out; + } ++ ++ pm_runtime_set_autosuspend_delay(&card->dev, 3000); ++ pm_runtime_use_autosuspend(&card->dev); ++ ++ /* ++ * Don't enable runtime PM for SD-combo cards here. Leave that ++ * decision to be taken during the SDIO init sequence instead. ++ */ ++ if (card->type != MMC_TYPE_SD_COMBO) { ++ pm_runtime_set_active(&card->dev); ++ pm_runtime_enable(&card->dev); ++ } ++ + return 0; + + out: + mmc_blk_remove_parts(card, md); + mmc_blk_remove_req(md); +- return err; ++ return 0; + } + + static void mmc_blk_remove(struct mmc_card *card) +@@ -1767,15 +2484,18 @@ static void mmc_blk_remove(struct mmc_card *card) + struct mmc_blk_data *md = mmc_get_drvdata(card); + + mmc_blk_remove_parts(card, md); ++ pm_runtime_get_sync(&card->dev); + mmc_claim_host(card->host); + mmc_blk_part_switch(card, md); + mmc_release_host(card->host); ++ if (card->type != MMC_TYPE_SD_COMBO) ++ pm_runtime_disable(&card->dev); ++ pm_runtime_put_noidle(&card->dev); + mmc_blk_remove_req(md); + mmc_set_drvdata(card, NULL); + } + +-#ifdef CONFIG_PM +-static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state) ++static int _mmc_blk_suspend(struct mmc_card *card) + { + struct mmc_blk_data *part_md; + struct mmc_blk_data *md = mmc_get_drvdata(card); +@@ -1789,14 +2509,23 @@ static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state) + return 0; + } + ++static void mmc_blk_shutdown(struct mmc_card *card) ++{ ++ _mmc_blk_suspend(card); ++} ++ ++#ifdef CONFIG_PM ++static int mmc_blk_suspend(struct mmc_card *card) ++{ ++ return _mmc_blk_suspend(card); ++} ++ + static int mmc_blk_resume(struct mmc_card *card) + { + struct mmc_blk_data *part_md; + struct mmc_blk_data *md = mmc_get_drvdata(card); + + if (md) { +- mmc_blk_set_blksize(md, card); +- + /* + * Resume involves the card going into idle state, + * so current partition is always the main one. +@@ -1822,6 +2551,7 @@ static struct mmc_driver mmc_driver = { + .remove = mmc_blk_remove, + .suspend = mmc_blk_suspend, + .resume = mmc_blk_resume, ++ .shutdown = mmc_blk_shutdown, + }; + + static int __init mmc_blk_init(void) +diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c +index b038c4a..0c0fc52 100644 +--- a/drivers/mmc/card/mmc_test.c ++++ b/drivers/mmc/card/mmc_test.c +@@ -1581,6 +1581,7 @@ static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill) + + t->max_segs = test->card->host->max_segs; + t->max_seg_sz = test->card->host->max_seg_size; ++ t->max_seg_sz -= t->max_seg_sz % 512; + + t->max_tfr = t->max_sz; + if (t->max_tfr >> 9 > test->card->host->max_blk_count) +@@ -2848,18 +2849,12 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf, + struct seq_file *sf = (struct seq_file *)file->private_data; + struct mmc_card *card = (struct mmc_card *)sf->private; + struct mmc_test_card *test; +- char lbuf[12]; + long testcase; ++ int ret; + +- if (count >= sizeof(lbuf)) +- return -EINVAL; +- +- if (copy_from_user(lbuf, buf, count)) +- return -EFAULT; +- lbuf[count] = '\0'; +- +- if (strict_strtol(lbuf, 10, &testcase)) +- return -EINVAL; ++ ret = kstrtol_from_user(buf, count, 10, &testcase); ++ if (ret) ++ return ret; + + test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL); + if (!test) +@@ -2949,7 +2944,7 @@ static void mmc_test_free_dbgfs_file(struct mmc_card *card) + } + + static int __mmc_test_register_dbgfs_file(struct mmc_card *card, +- const char *name, mode_t mode, const struct file_operations *fops) ++ const char *name, umode_t mode, const struct file_operations *fops) + { + struct dentry *file = NULL; + struct mmc_test_dbgfs_file *df; +@@ -3024,12 +3019,17 @@ static void mmc_test_remove(struct mmc_card *card) + mmc_test_free_dbgfs_file(card); + } + ++static void mmc_test_shutdown(struct mmc_card *card) ++{ ++} ++ + static struct mmc_driver mmc_driver = { + .drv = { + .name = "mmc_test", + }, + .probe = mmc_test_probe, + .remove = mmc_test_remove, ++ .shutdown = mmc_test_shutdown, + }; + + static int __init mmc_test_init(void) +diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c +index 78690f2..2b8992f 100644 +--- a/drivers/mmc/card/queue.c ++++ b/drivers/mmc/card/queue.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -22,13 +23,13 @@ + + #define MMC_QUEUE_BOUNCESZ 65536 + +-#define MMC_QUEUE_SUSPENDED (1 << 0) +- + /* + * Prepare a MMC request. This just filters out odd stuff. + */ + static int mmc_prep_request(struct request_queue *q, struct request *req) + { ++ struct mmc_queue *mq = q->queuedata; ++ + /* + * We only like normal block requests and discards. + */ +@@ -37,6 +38,9 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) + return BLKPREP_KILL; + } + ++ if (mq && mmc_card_removed(mq->card)) ++ return BLKPREP_KILL; ++ + req->cmd_flags |= REQ_DONTPREP; + + return BLKPREP_OK; +@@ -53,6 +57,7 @@ static int mmc_queue_thread(void *d) + 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); +@@ -62,7 +67,28 @@ static int mmc_queue_thread(void *d) + + if (req || mq->mqrq_prev->req) { + set_current_state(TASK_RUNNING); ++ cmd_flags = req ? req->cmd_flags : 0; + 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); +@@ -72,13 +98,6 @@ static int mmc_queue_thread(void *d) + schedule(); + down(&mq->thread_sem); + } +- +- /* Current request becomes previous request and vice versa. */ +- 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; + } while (1); + up(&mq->thread_sem); + +@@ -91,10 +110,12 @@ static int mmc_queue_thread(void *d) + * on any queue on this host, and attempt to issue it. This may + * not be the queue we were asked to process. + */ +-static void mmc_request(struct request_queue *q) ++static void mmc_request_fn(struct request_queue *q) + { + struct mmc_queue *mq = q->queuedata; + struct request *req; ++ unsigned long flags; ++ struct mmc_context_info *cntx; + + if (!mq) { + while ((req = blk_fetch_request(q)) != NULL) { +@@ -104,7 +125,20 @@ static void mmc_request(struct request_queue *q) + return; + } + +- if (!mq->mqrq_cur->req && !mq->mqrq_prev->req) ++ cntx = &mq->card->host->context_info; ++ if (!mq->mqrq_cur->req && mq->mqrq_prev->req) { ++ /* ++ * New MMC request arrived when MMC thread may be ++ * blocked on the previous request to be complete ++ * with no current request fetched ++ */ ++ spin_lock_irqsave(&cntx->lock, flags); ++ if (cntx->is_waiting_last_req) { ++ cntx->is_new_req = true; ++ wake_up_interruptible(&cntx->wait); ++ } ++ spin_unlock_irqrestore(&cntx->lock, flags); ++ } else if (!mq->mqrq_cur->req && !mq->mqrq_prev->req) + wake_up_process(mq->thread); + } + +@@ -140,7 +174,7 @@ static void mmc_queue_setup_discard(struct request_queue *q, + /* granularity must not be greater than max. discard */ + if (card->pref_erase > max_discard) + q->limits.discard_granularity = 0; +- if (mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card)) ++ if (mmc_can_secure_erase_trim(card)) + queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q); + } + +@@ -164,14 +198,13 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, + + if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) + limit = *mmc_dev(host)->dma_mask; ++ // limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; + + mq->card = card; +- mq->queue = blk_init_queue(mmc_request, lock); ++ mq->queue = blk_init_queue(mmc_request_fn, lock); + if (!mq->queue) + return -ENOMEM; + +- memset(&mq->mqrq_cur, 0, sizeof(mq->mqrq_cur)); +- memset(&mq->mqrq_prev, 0, sizeof(mq->mqrq_prev)); + mq->mqrq_cur = mqrq_cur; + mq->mqrq_prev = mqrq_prev; + mq->queue->queuedata = mq; +@@ -328,6 +361,49 @@ void mmc_cleanup_queue(struct mmc_queue *mq) + } + EXPORT_SYMBOL(mmc_cleanup_queue); + ++int mmc_packed_init(struct mmc_queue *mq, struct mmc_card *card) ++{ ++ struct mmc_queue_req *mqrq_cur = &mq->mqrq[0]; ++ struct mmc_queue_req *mqrq_prev = &mq->mqrq[1]; ++ int ret = 0; ++ ++ ++ mqrq_cur->packed = kzalloc(sizeof(struct mmc_packed), GFP_KERNEL); ++ if (!mqrq_cur->packed) { ++ pr_warn("%s: unable to allocate packed cmd for mqrq_cur\n", ++ mmc_card_name(card)); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ mqrq_prev->packed = kzalloc(sizeof(struct mmc_packed), GFP_KERNEL); ++ if (!mqrq_prev->packed) { ++ pr_warn("%s: unable to allocate packed cmd for mqrq_prev\n", ++ mmc_card_name(card)); ++ kfree(mqrq_cur->packed); ++ mqrq_cur->packed = NULL; ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ INIT_LIST_HEAD(&mqrq_cur->packed->list); ++ INIT_LIST_HEAD(&mqrq_prev->packed->list); ++ ++out: ++ return ret; ++} ++ ++void mmc_packed_clean(struct mmc_queue *mq) ++{ ++ struct mmc_queue_req *mqrq_cur = &mq->mqrq[0]; ++ struct mmc_queue_req *mqrq_prev = &mq->mqrq[1]; ++ ++ kfree(mqrq_cur->packed); ++ mqrq_cur->packed = NULL; ++ kfree(mqrq_prev->packed); ++ mqrq_prev->packed = NULL; ++} ++ + /** + * mmc_queue_suspend - suspend a MMC request queue + * @mq: MMC queue to suspend +@@ -372,6 +448,41 @@ void mmc_queue_resume(struct mmc_queue *mq) + } + } + ++static unsigned int mmc_queue_packed_map_sg(struct mmc_queue *mq, ++ struct mmc_packed *packed, ++ struct scatterlist *sg, ++ enum mmc_packed_type cmd_type) ++{ ++ struct scatterlist *__sg = sg; ++ unsigned int sg_len = 0; ++ struct request *req; ++ ++ if (mmc_packed_wr(cmd_type)) { ++ unsigned int hdr_sz = mmc_large_sector(mq->card) ? 4096 : 512; ++ unsigned int max_seg_sz = queue_max_segment_size(mq->queue); ++ unsigned int len, remain, offset = 0; ++ u8 *buf = (u8 *)packed->cmd_hdr; ++ ++ remain = hdr_sz; ++ do { ++ len = min(remain, max_seg_sz); ++ sg_set_buf(__sg, buf + offset, len); ++ offset += len; ++ remain -= len; ++ (__sg++)->page_link &= ~0x02; ++ sg_len++; ++ } while (remain); ++ } ++ ++ list_for_each_entry(req, &packed->list, queuelist) { ++ sg_len += blk_rq_map_sg(mq->queue, req, __sg); ++ __sg = sg + (sg_len - 1); ++ (__sg++)->page_link &= ~0x02; ++ } ++ sg_mark_end(sg + (sg_len - 1)); ++ return sg_len; ++} ++ + /* + * Prepare the sg list(s) to be handed of to the host driver + */ +@@ -380,14 +491,26 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq) + unsigned int sg_len; + size_t buflen; + struct scatterlist *sg; ++ enum mmc_packed_type cmd_type; + int i; + +- if (!mqrq->bounce_buf) +- return blk_rq_map_sg(mq->queue, mqrq->req, mqrq->sg); ++ 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); + +- sg_len = blk_rq_map_sg(mq->queue, mqrq->req, 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); + + mqrq->bounce_sg_len = sg_len; + +diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h +index d2a1eb4..5752d50 100644 +--- a/drivers/mmc/card/queue.h ++++ b/drivers/mmc/card/queue.h +@@ -1,6 +1,8 @@ + #ifndef MMC_QUEUE_H + #define MMC_QUEUE_H + ++#define MMC_REQ_SPECIAL_MASK (REQ_DISCARD | REQ_FLUSH) ++ + struct request; + struct task_struct; + +@@ -12,6 +14,23 @@ struct mmc_blk_request { + struct mmc_data data; + }; + ++enum mmc_packed_type { ++ MMC_PACKED_NONE = 0, ++ MMC_PACKED_WRITE, ++}; ++ ++#define mmc_packed_cmd(type) ((type) != MMC_PACKED_NONE) ++#define mmc_packed_wr(type) ((type) == MMC_PACKED_WRITE) ++ ++struct mmc_packed { ++ struct list_head list; ++ u32 cmd_hdr[1024]; ++ unsigned int blocks; ++ u8 nr_entries; ++ u8 retries; ++ s16 idx_failure; ++}; ++ + struct mmc_queue_req { + struct request *req; + struct mmc_blk_request brq; +@@ -20,6 +39,8 @@ struct mmc_queue_req { + struct scatterlist *bounce_sg; + unsigned int bounce_sg_len; + struct mmc_async_req mmc_active; ++ enum mmc_packed_type cmd_type; ++ struct mmc_packed *packed; + }; + + struct mmc_queue { +@@ -27,6 +48,9 @@ struct mmc_queue { + struct task_struct *thread; + struct semaphore thread_sem; + unsigned int flags; ++#define MMC_QUEUE_SUSPENDED (1 << 0) ++#define MMC_QUEUE_NEW_REQUEST (1 << 1) ++ + int (*issue_fn)(struct mmc_queue *, struct request *); + void *data; + struct request_queue *queue; +@@ -46,4 +70,7 @@ extern unsigned int mmc_queue_map_sg(struct mmc_queue *, + extern void mmc_queue_bounce_pre(struct mmc_queue_req *); + extern void mmc_queue_bounce_post(struct mmc_queue_req *); + ++extern int mmc_packed_init(struct mmc_queue *, struct mmc_card *); ++extern void mmc_packed_clean(struct mmc_queue *); ++ + #endif +diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c +index 2c151e1..f093cea 100644 +--- a/drivers/mmc/card/sdio_uart.c ++++ b/drivers/mmc/card/sdio_uart.c +@@ -66,8 +66,6 @@ struct uart_icount { + + struct sdio_uart_port { + struct tty_port port; +- struct kref kref; +- struct tty_struct *tty; + unsigned int index; + struct sdio_func *func; + struct mutex func_lock; +@@ -93,7 +91,6 @@ static int sdio_uart_add_port(struct sdio_uart_port *port) + { + int index, ret = -EBUSY; + +- kref_init(&port->kref); + mutex_init(&port->func_lock); + spin_lock_init(&port->write_lock); + if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE, GFP_KERNEL)) +@@ -123,29 +120,20 @@ static struct sdio_uart_port *sdio_uart_port_get(unsigned index) + spin_lock(&sdio_uart_table_lock); + port = sdio_uart_table[index]; + if (port) +- kref_get(&port->kref); ++ tty_port_get(&port->port); + spin_unlock(&sdio_uart_table_lock); + + return port; + } + +-static void sdio_uart_port_destroy(struct kref *kref) +-{ +- struct sdio_uart_port *port = +- container_of(kref, struct sdio_uart_port, kref); +- kfifo_free(&port->xmit_fifo); +- kfree(port); +-} +- + static void sdio_uart_port_put(struct sdio_uart_port *port) + { +- kref_put(&port->kref, sdio_uart_port_destroy); ++ tty_port_put(&port->port); + } + + static void sdio_uart_port_remove(struct sdio_uart_port *port) + { + struct sdio_func *func; +- struct tty_struct *tty; + + BUG_ON(sdio_uart_table[port->index] != port); + +@@ -166,12 +154,8 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port) + sdio_claim_host(func); + port->func = NULL; + mutex_unlock(&port->func_lock); +- tty = tty_port_tty_get(&port->port); + /* tty_hangup is async so is this safe as is ?? */ +- if (tty) { +- tty_hangup(tty); +- tty_kref_put(tty); +- } ++ tty_port_tty_hangup(&port->port, false); + mutex_unlock(&port->port.mutex); + sdio_release_irq(func); + sdio_disable_func(func); +@@ -392,7 +376,6 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port) + static void sdio_uart_receive_chars(struct sdio_uart_port *port, + unsigned int *status) + { +- struct tty_struct *tty = tty_port_tty_get(&port->port); + unsigned int ch, flag; + int max_count = 256; + +@@ -429,23 +412,19 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port, + } + + if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0) +- if (tty) +- tty_insert_flip_char(tty, ch, flag); ++ tty_insert_flip_char(&port->port, ch, flag); + + /* + * Overrun is special. Since it's reported immediately, + * it doesn't affect the current character. + */ + if (*status & ~port->ignore_status_mask & UART_LSR_OE) +- if (tty) +- tty_insert_flip_char(tty, 0, TTY_OVERRUN); ++ tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); + + *status = sdio_in(port, UART_LSR); + } while ((*status & UART_LSR_DR) && (max_count-- > 0)); +- if (tty) { +- tty_flip_buffer_push(tty); +- tty_kref_put(tty); +- } ++ ++ tty_flip_buffer_push(&port->port); + } + + static void sdio_uart_transmit_chars(struct sdio_uart_port *port) +@@ -508,17 +487,13 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) + wake_up_interruptible(&port->port.open_wait); + else { + /* DCD drop - hang up if tty attached */ +- tty = tty_port_tty_get(&port->port); +- if (tty) { +- tty_hangup(tty); +- tty_kref_put(tty); +- } ++ tty_port_tty_hangup(&port->port, false); + } + } + if (status & UART_MSR_DCTS) { + port->icount.cts++; + tty = tty_port_tty_get(&port->port); +- if (tty && (tty->termios->c_cflag & CRTSCTS)) { ++ if (tty && (tty->termios.c_cflag & CRTSCTS)) { + int cts = (status & UART_MSR_CTS); + if (tty->hw_stopped) { + if (cts) { +@@ -671,12 +646,12 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) + port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE; + port->mctrl = TIOCM_OUT2; + +- sdio_uart_change_speed(port, tty->termios, NULL); ++ sdio_uart_change_speed(port, &tty->termios, NULL); + +- if (tty->termios->c_cflag & CBAUD) ++ if (tty->termios.c_cflag & CBAUD) + sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); + +- if (tty->termios->c_cflag & CRTSCTS) ++ if (tty->termios.c_cflag & CRTSCTS) + if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) + tty->hw_stopped = 1; + +@@ -737,6 +712,14 @@ static void sdio_uart_shutdown(struct tty_port *tport) + sdio_uart_release_func(port); + } + ++static void sdio_uart_port_destroy(struct tty_port *tport) ++{ ++ struct sdio_uart_port *port = ++ container_of(tport, struct sdio_uart_port, port); ++ kfifo_free(&port->xmit_fifo); ++ kfree(port); ++} ++ + /** + * sdio_uart_install - install method + * @driver: the driver in use (sdio_uart in our case) +@@ -750,15 +733,12 @@ static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty) + { + int idx = tty->index; + struct sdio_uart_port *port = sdio_uart_port_get(idx); +- int ret = tty_init_termios(tty); ++ int ret = tty_standard_install(driver, tty); + +- if (ret == 0) { +- tty_driver_kref_get(driver); +- tty->count++; ++ if (ret == 0) + /* This is the ref sdio_uart_port get provided */ + tty->driver_data = port; +- driver->ttys[idx] = tty; +- } else ++ else + sdio_uart_port_put(port); + return ret; + } +@@ -853,7 +833,7 @@ static void sdio_uart_throttle(struct tty_struct *tty) + { + struct sdio_uart_port *port = tty->driver_data; + +- if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS)) ++ if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS)) + return; + + if (sdio_uart_claim_func(port) != 0) +@@ -864,7 +844,7 @@ static void sdio_uart_throttle(struct tty_struct *tty) + sdio_uart_start_tx(port); + } + +- if (tty->termios->c_cflag & CRTSCTS) ++ if (tty->termios.c_cflag & CRTSCTS) + sdio_uart_clear_mctrl(port, TIOCM_RTS); + + sdio_uart_irq(port->func); +@@ -875,7 +855,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) + { + struct sdio_uart_port *port = tty->driver_data; + +- if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS)) ++ if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS)) + return; + + if (sdio_uart_claim_func(port) != 0) +@@ -890,7 +870,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) + } + } + +- if (tty->termios->c_cflag & CRTSCTS) ++ if (tty->termios.c_cflag & CRTSCTS) + sdio_uart_set_mctrl(port, TIOCM_RTS); + + sdio_uart_irq(port->func); +@@ -901,12 +881,12 @@ static void sdio_uart_set_termios(struct tty_struct *tty, + struct ktermios *old_termios) + { + struct sdio_uart_port *port = tty->driver_data; +- unsigned int cflag = tty->termios->c_cflag; ++ unsigned int cflag = tty->termios.c_cflag; + + if (sdio_uart_claim_func(port) != 0) + return; + +- sdio_uart_change_speed(port, tty->termios, old_termios); ++ sdio_uart_change_speed(port, &tty->termios, old_termios); + + /* Handle transition to B0 status */ + if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) +@@ -1048,6 +1028,7 @@ static const struct tty_port_operations sdio_uart_port_ops = { + .carrier_raised = uart_carrier_raised, + .shutdown = sdio_uart_shutdown, + .activate = sdio_uart_activate, ++ .destruct = sdio_uart_port_destroy, + }; + + static const struct tty_operations sdio_uart_ops = { +@@ -1135,8 +1116,8 @@ static int sdio_uart_probe(struct sdio_func *func, + kfree(port); + } else { + struct device *dev; +- dev = tty_register_device(sdio_uart_tty_driver, +- port->index, &func->dev); ++ dev = tty_port_register_device(&port->port, ++ sdio_uart_tty_driver, port->index, &func->dev); + if (IS_ERR(dev)) { + sdio_uart_port_remove(port); + ret = PTR_ERR(dev); +@@ -1178,7 +1159,6 @@ static int __init sdio_uart_init(void) + if (!tty_drv) + return -ENOMEM; + +- tty_drv->owner = THIS_MODULE; + tty_drv->driver_name = "sdio_uart"; + tty_drv->name = "ttySDIO"; + tty_drv->major = 0; /* dynamically allocated */ +diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig +index ef10387..9ebee72 100644 +--- a/drivers/mmc/core/Kconfig ++++ b/drivers/mmc/core/Kconfig +@@ -2,24 +2,8 @@ + # MMC core configuration + # + +-config MMC_UNSAFE_RESUME +- bool "Assume MMC/SD cards are non-removable (DANGEROUS)" +- help +- If you say Y here, the MMC layer will assume that all cards +- stayed in their respective slots during the suspend. The +- normal behaviour is to remove them at suspend and +- redetecting them at resume. Breaking this assumption will +- in most cases result in data corruption. +- +- This option is usually just for embedded systems which use +- a MMC/SD card for rootfs. Most people should say N here. +- +- This option sets a default which can be overridden by the +- module parameter "removable=0" or "removable=1". +- + config MMC_CLKGATE +- bool "MMC host clock gating (EXPERIMENTAL)" +- depends on EXPERIMENTAL ++ bool "MMC host clock gating" + help + This will attempt to aggressively gate the clock to the MMC card. + This is done to save power due to gating off the logic and bus +diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile +index 6395019..38ed210 100644 +--- a/drivers/mmc/core/Makefile ++++ b/drivers/mmc/core/Makefile +@@ -7,6 +7,6 @@ mmc_core-y := core.o bus.o host.o \ + mmc.o mmc_ops.o sd.o sd_ops.o \ + sdio.o sdio_ops.o sdio_bus.o \ + sdio_cis.o sdio_io.o sdio_irq.o \ +- quirks.o ++ quirks.o slot-gpio.o + + mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o +diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c +index 6be4924..84763c0 100644 +--- a/drivers/mmc/core/bus.c ++++ b/drivers/mmc/core/bus.c +@@ -122,14 +122,39 @@ static int mmc_bus_remove(struct device *dev) + return 0; + } + +-static int mmc_bus_suspend(struct device *dev, pm_message_t state) ++static void mmc_bus_shutdown(struct device *dev) + { + struct mmc_driver *drv = to_mmc_driver(dev->driver); + struct mmc_card *card = mmc_dev_to_card(dev); +- int ret = 0; ++ struct mmc_host *host = card->host; ++ int ret; ++ ++ if (dev->driver && drv->shutdown) ++ drv->shutdown(card); ++ ++ if (host->bus_ops->shutdown) { ++ ret = host->bus_ops->shutdown(host); ++ if (ret) ++ pr_warn("%s: error %d during shutdown\n", ++ mmc_hostname(host), ret); ++ } ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int mmc_bus_suspend(struct device *dev) ++{ ++ struct mmc_driver *drv = to_mmc_driver(dev->driver); ++ struct mmc_card *card = mmc_dev_to_card(dev); ++ struct mmc_host *host = card->host; ++ int ret; + +- if (dev->driver && drv->suspend) +- ret = drv->suspend(card, state); ++ if (dev->driver && drv->suspend) { ++ ret = drv->suspend(card); ++ if (ret) ++ return ret; ++ } ++ ++ ret = host->bus_ops->suspend(host); + return ret; + } + +@@ -137,48 +162,52 @@ static int mmc_bus_resume(struct device *dev) + { + struct mmc_driver *drv = to_mmc_driver(dev->driver); + struct mmc_card *card = mmc_dev_to_card(dev); +- int ret = 0; ++ struct mmc_host *host = card->host; ++ int ret; ++ ++ ret = host->bus_ops->resume(host); ++ if (ret) ++ pr_warn("%s: error %d during resume (card was removed?)\n", ++ mmc_hostname(host), ret); + + if (dev->driver && drv->resume) + ret = drv->resume(card); ++ + return ret; + } ++#endif + + #ifdef CONFIG_PM_RUNTIME + + static int mmc_runtime_suspend(struct device *dev) + { + struct mmc_card *card = mmc_dev_to_card(dev); ++ struct mmc_host *host = card->host; + +- return mmc_power_save_host(card->host); ++ return host->bus_ops->runtime_suspend(host); + } + + static int mmc_runtime_resume(struct device *dev) + { + struct mmc_card *card = mmc_dev_to_card(dev); ++ struct mmc_host *host = card->host; + +- return mmc_power_restore_host(card->host); ++ return host->bus_ops->runtime_resume(host); + } + + static int mmc_runtime_idle(struct device *dev) + { +- return pm_runtime_suspend(dev); ++ return 0; + } + ++#endif /* !CONFIG_PM_RUNTIME */ ++ + static const struct dev_pm_ops mmc_bus_pm_ops = { +- .runtime_suspend = mmc_runtime_suspend, +- .runtime_resume = mmc_runtime_resume, +- .runtime_idle = mmc_runtime_idle, ++ SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume, ++ mmc_runtime_idle) ++ SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume) + }; + +-#define MMC_PM_OPS_PTR (&mmc_bus_pm_ops) +- +-#else /* !CONFIG_PM_RUNTIME */ +- +-#define MMC_PM_OPS_PTR NULL +- +-#endif /* !CONFIG_PM_RUNTIME */ +- + static struct bus_type mmc_bus_type = { + .name = "mmc", + .dev_attrs = mmc_dev_attrs, +@@ -186,9 +215,8 @@ static struct bus_type mmc_bus_type = { + .uevent = mmc_bus_uevent, + .probe = mmc_bus_probe, + .remove = mmc_bus_remove, +- .suspend = mmc_bus_suspend, +- .resume = mmc_bus_resume, +- .pm = MMC_PM_OPS_PTR, ++ .shutdown = mmc_bus_shutdown, ++ .pm = &mmc_bus_pm_ops, + }; + + int mmc_register_bus(void) +@@ -231,8 +259,7 @@ static void mmc_release_card(struct device *dev) + + sdio_free_common_cis(card); + +- if (card->info) +- kfree(card->info); ++ kfree(card->info); + + kfree(card); + } +@@ -267,6 +294,15 @@ int mmc_add_card(struct mmc_card *card) + { + int ret; + const char *type; ++ 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 ", ++ }; ++ + + dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); + +@@ -296,24 +332,31 @@ int mmc_add_card(struct mmc_card *card) + break; + } + ++ if (mmc_card_uhs(card) && ++ (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) ++ uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; ++ + if (mmc_host_is_spi(card->host)) { + pr_info("%s: new %s%s%s card on SPI\n", + mmc_hostname(card->host), +- mmc_card_highspeed(card) ? "high speed " : "", +- mmc_card_ddr_mode(card) ? "DDR " : "", ++ mmc_card_hs(card) ? "high speed " : "", ++ mmc_card_ddr52(card) ? "DDR " : "", + type); + } else { +- printk(KERN_INFO "%s: new %s%s%s card at address %04x\n", ++ pr_info("%s: new %s%s%s%s%s card at address %04x\n", + mmc_hostname(card->host), +- mmc_sd_card_uhs(card) ? "ultra high speed " : +- (mmc_card_highspeed(card) ? "high speed " : ""), +- mmc_card_ddr_mode(card) ? "DDR " : "", +- type, card->rca); ++ mmc_card_uhs(card) ? "ultra high speed " : ++ (mmc_card_hs(card) ? "high speed " : ""), ++ mmc_card_hs400(card) ? "HS400 " : ++ (mmc_card_hs200(card) ? "HS200 " : ""), ++ mmc_card_ddr52(card) ? "DDR " : "", ++ uhs_bus_speed_mode, type, card->rca); + } + + #ifdef CONFIG_DEBUG_FS + mmc_add_card_debugfs(card); + #endif ++ mmc_init_context_info(card->host); + + ret = device_add(&card->dev); + if (ret) +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index fc7386e..748e332 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -23,9 +23,12 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include ++#include + + #include + #include +@@ -41,34 +44,27 @@ + #include "sd_ops.h" + #include "sdio_ops.h" + ++/* If the device is not responding */ ++#define MMC_CORE_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ ++ ++/* ++ * Background operations can take a long time, depending on the housekeeping ++ * operations the card has to perform. ++ */ ++#define MMC_BKOPS_MAX_TIMEOUT (4 * 60 * 1000) /* max time to wait in ms */ ++ + static struct workqueue_struct *workqueue; ++static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; + + /* + * Enabling software CRCs on the data blocks can be a significant (30%) + * performance cost, and for other reasons may not always be desired. + * So we allow it it to be disabled. + */ +-int use_spi_crc = 1; ++bool use_spi_crc = 1; + module_param(use_spi_crc, bool, 0); + + /* +- * We normally treat cards as removed during suspend if they are not +- * known to be on a non-removable bus, to avoid the risk of writing +- * back data to a different card after resume. Allow this to be +- * overridden if necessary. +- */ +-#ifdef CONFIG_MMC_UNSAFE_RESUME +-int mmc_assume_removable; +-#else +-int mmc_assume_removable = 1; +-#endif +-EXPORT_SYMBOL(mmc_assume_removable); +-module_param_named(removable, mmc_assume_removable, bool, 0644); +-MODULE_PARM_DESC( +- removable, +- "MMC/SD cards are removable and may be removed during suspend"); +- +-/* + * Internal function. Schedule delayed work in the MMC work queue. + */ + static int mmc_schedule_delayed_work(struct delayed_work *work, +@@ -109,8 +105,8 @@ static void mmc_should_fail_request(struct mmc_host *host, + !should_fail(&host->fail_mmc_request, data->blksz * data->blocks)) + return; + +- data->error = data_errors[random32() % ARRAY_SIZE(data_errors)]; +- data->bytes_xfered = (random32() % (data->bytes_xfered >> 9)) << 9; ++ data->error = data_errors[prandom_u32() % ARRAY_SIZE(data_errors)]; ++ data->bytes_xfered = (prandom_u32() % (data->bytes_xfered >> 9)) << 9; + } + + #else /* CONFIG_FAIL_MMC_REQUEST */ +@@ -140,7 +136,7 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) + cmd->retries = 0; + } + +- if (err && cmd->retries) { ++ if (err && cmd->retries && !mmc_card_removed(host->card)) { + /* + * Request starter must handle retries - see + * mmc_wait_for_req_done(). +@@ -188,6 +184,12 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) + struct scatterlist *sg; + #endif + ++ if (mrq->sbc) { ++ pr_debug("<%s: starting CMD%u arg %08x flags %08x>\n", ++ mmc_hostname(host), mrq->sbc->opcode, ++ mrq->sbc->arg, mrq->sbc->flags); ++ } ++ + pr_debug("%s: starting CMD%u arg %08x flags %08x\n", + mmc_hostname(host), mrq->cmd->opcode, + mrq->cmd->arg, mrq->cmd->flags); +@@ -238,16 +240,178 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) + host->ops->request(host, mrq); + } + ++/** ++ * mmc_start_bkops - start BKOPS for supported cards ++ * @card: MMC card to start BKOPS ++ * @form_exception: A flag to indicate if this function was ++ * called due to an exception raised by the card ++ * ++ * Start background operations whenever requested. ++ * When the urgent BKOPS bit is set in a R1 command response ++ * then background operations should be started immediately. ++*/ ++void mmc_start_bkops(struct mmc_card *card, bool from_exception) ++{ ++ int err; ++ int timeout; ++ bool use_busy_signal; ++ ++ BUG_ON(!card); ++ ++ if (!card->ext_csd.bkops_en || mmc_card_doing_bkops(card)) ++ return; ++ ++ err = mmc_read_bkops_status(card); ++ if (err) { ++ pr_err("%s: Failed to read bkops status: %d\n", ++ mmc_hostname(card->host), err); ++ return; ++ } ++ ++ if (!card->ext_csd.raw_bkops_status) ++ return; ++ ++ if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 && ++ from_exception) ++ return; ++ ++ mmc_claim_host(card->host); ++ if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) { ++ timeout = MMC_BKOPS_MAX_TIMEOUT; ++ use_busy_signal = true; ++ } else { ++ timeout = 0; ++ use_busy_signal = false; ++ } ++ ++ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, ++ EXT_CSD_BKOPS_START, 1, timeout, ++ use_busy_signal, true, false); ++ if (err) { ++ pr_warn("%s: Error %d starting bkops\n", ++ mmc_hostname(card->host), err); ++ goto out; ++ } ++ ++ /* ++ * For urgent bkops status (LEVEL_2 and more) ++ * bkops executed synchronously, otherwise ++ * the operation is in progress ++ */ ++ if (!use_busy_signal) ++ mmc_card_set_doing_bkops(card); ++out: ++ mmc_release_host(card->host); ++} ++EXPORT_SYMBOL(mmc_start_bkops); ++ ++/* ++ * mmc_wait_data_done() - done callback for data request ++ * @mrq: done data request ++ * ++ * Wakes up mmc context, passed as a callback to host controller driver ++ */ ++static void mmc_wait_data_done(struct mmc_request *mrq) ++{ ++ mrq->host->context_info.is_done_rcv = true; ++ wake_up_interruptible(&mrq->host->context_info.wait); ++} ++ + static void mmc_wait_done(struct mmc_request *mrq) + { + complete(&mrq->completion); + } + +-static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) ++/* ++ *__mmc_start_data_req() - starts data request ++ * @host: MMC host to start the request ++ * @mrq: data request to start ++ * ++ * 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) ++{ ++ mrq->done = mmc_wait_data_done; ++ mrq->host = host; ++ if (mmc_card_removed(host->card)) { ++ mrq->cmd->error = -ENOMEDIUM; ++ mmc_wait_data_done(mrq); ++ return -ENOMEDIUM; ++ } ++ mmc_start_request(host, mrq); ++ ++ return 0; ++} ++ ++static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) + { + init_completion(&mrq->completion); + mrq->done = mmc_wait_done; ++ if (mmc_card_removed(host->card)) { ++ mrq->cmd->error = -ENOMEDIUM; ++ complete(&mrq->completion); ++ return -ENOMEDIUM; ++ } + mmc_start_request(host, mrq); ++ return 0; ++} ++ ++/* ++ * mmc_wait_for_data_req_done() - wait for request completed ++ * @host: MMC host to prepare the command. ++ * @mrq: MMC request to wait for ++ * ++ * 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 after checking errors. ++ */ ++static int mmc_wait_for_data_req_done(struct mmc_host *host, ++ struct mmc_request *mrq, ++ struct mmc_async_req *next_req) ++{ ++ struct mmc_command *cmd; ++ struct mmc_context_info *context_info = &host->context_info; ++ int err; ++ unsigned long flags; ++ ++ while (1) { ++ wait_event_interruptible(context_info->wait, ++ (context_info->is_done_rcv || ++ context_info->is_new_req)); ++ spin_lock_irqsave(&context_info->lock, flags); ++ context_info->is_waiting_last_req = false; ++ spin_unlock_irqrestore(&context_info->lock, flags); ++ if (context_info->is_done_rcv) { ++ context_info->is_done_rcv = false; ++ context_info->is_new_req = false; ++ cmd = mrq->cmd; ++ ++ if (!cmd->error || !cmd->retries || ++ mmc_card_removed(host->card)) { ++ err = host->areq->err_check(host->card, ++ host->areq); ++ break; /* return err */ ++ } else { ++ pr_info("%s: req failed (CMD%u): %d, retrying...\n", ++ mmc_hostname(host), ++ cmd->opcode, cmd->error); ++ cmd->retries--; ++ cmd->error = 0; ++ host->ops->request(host, mrq); ++ continue; /* wait for done/new event again */ ++ } ++ } else if (context_info->is_new_req) { ++ context_info->is_new_req = false; ++ if (!next_req) { ++ err = MMC_BLK_NEW_REQUEST; ++ break; /* return err */ ++ } ++ } ++ } ++ return err; + } + + static void mmc_wait_for_req_done(struct mmc_host *host, +@@ -259,7 +423,26 @@ static void mmc_wait_for_req_done(struct mmc_host *host, + wait_for_completion(&mrq->completion); + + cmd = mrq->cmd; +- if (!cmd->error || !cmd->retries) ++ ++ /* ++ * If host has timed out waiting for the sanitize ++ * to complete, card might be still in programming state ++ * so let's try to bring the card out of programming ++ * state. ++ */ ++ if (cmd->sanitize_busy && cmd->error == -ETIMEDOUT) { ++ if (!mmc_interrupt_hpi(host->card)) { ++ pr_warning("%s: %s: Interrupted sanitize\n", ++ mmc_hostname(host), __func__); ++ cmd->error = 0; ++ break; ++ } else { ++ pr_err("%s: %s: Failed to interrupt sanitize\n", ++ mmc_hostname(host), __func__); ++ } ++ } ++ if (!cmd->error || !cmd->retries || ++ mmc_card_removed(host->card)) + break; + + pr_debug("%s: req failed (CMD%u): %d, retrying...\n", +@@ -284,8 +467,11 @@ static void mmc_wait_for_req_done(struct mmc_host *host, + static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, + bool is_first_req) + { +- if (host->ops->pre_req) ++ if (host->ops->pre_req) { ++ mmc_host_clk_hold(host); + host->ops->pre_req(host, mrq, is_first_req); ++ mmc_host_clk_release(host); ++ } + } + + /** +@@ -300,8 +486,11 @@ static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, + static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, + int err) + { +- if (host->ops->post_req) ++ if (host->ops->post_req) { ++ mmc_host_clk_hold(host); + host->ops->post_req(host, mrq, err); ++ mmc_host_clk_release(host); ++ } + } + + /** +@@ -324,6 +513,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host, + struct mmc_async_req *areq, int *error) + { + int err = 0; ++ int start_err = 0; + struct mmc_async_req *data = host->areq; + + /* Prepare a new request */ +@@ -331,32 +521,41 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host, + mmc_pre_req(host, areq->mrq, !host->areq); + + if (host->areq) { +- mmc_wait_for_req_done(host, host->areq->mrq); +- err = host->areq->err_check(host->card, host->areq); +- if (err) { +- /* post process the completed failed request */ +- mmc_post_req(host, host->areq->mrq, 0); +- if (areq) +- /* +- * Cancel the new prepared request, because +- * it can't run until the failed +- * request has been properly handled. +- */ +- mmc_post_req(host, areq->mrq, -EINVAL); +- +- host->areq = NULL; +- goto out; ++ err = mmc_wait_for_data_req_done(host, host->areq->mrq, areq); ++ if (err == MMC_BLK_NEW_REQUEST) { ++ if (error) ++ *error = err; ++ /* ++ * The previous request was not completed, ++ * nothing to return ++ */ ++ return NULL; + } ++ /* ++ * Check BKOPS urgency for each R1 response ++ */ ++ if (host->card && mmc_card_mmc(host->card) && ++ ((mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1) || ++ (mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1B)) && ++ (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT)) ++ mmc_start_bkops(host->card, true); + } + +- if (areq) +- __mmc_start_req(host, areq->mrq); ++ if (!err && areq) ++ start_err = __mmc_start_data_req(host, areq->mrq); + + if (host->areq) + mmc_post_req(host, host->areq->mrq, 0); + +- host->areq = areq; +- out: ++ /* Cancel a prepared request if it was not started. */ ++ if ((err || start_err) && areq) ++ mmc_post_req(host, areq->mrq, -EINVAL); ++ ++ if (err) ++ host->areq = NULL; ++ else ++ host->areq = areq; ++ + if (error) + *error = err; + return data; +@@ -384,12 +583,13 @@ EXPORT_SYMBOL(mmc_wait_for_req); + * @card: the MMC card associated with the HPI transfer + * + * Issued High Priority Interrupt, and check for card status +- * util out-of prg-state. ++ * until out-of prg-state. + */ + int mmc_interrupt_hpi(struct mmc_card *card) + { + int err; + u32 status; ++ unsigned long prg_wait; + + BUG_ON(!card); + +@@ -405,30 +605,39 @@ int mmc_interrupt_hpi(struct mmc_card *card) + goto out; + } + +- /* +- * If the card status is in PRG-state, we can send the HPI command. +- */ +- if (R1_CURRENT_STATE(status) == R1_STATE_PRG) { +- do { +- /* +- * We don't know when the HPI command will finish +- * processing, so we need to resend HPI until out +- * of prg-state, and keep checking the card status +- * with SEND_STATUS. If a timeout error occurs when +- * sending the HPI command, we are already out of +- * prg-state. +- */ +- err = mmc_send_hpi_cmd(card, &status); +- if (err) +- pr_debug("%s: abort HPI (%d error)\n", +- mmc_hostname(card->host), err); ++ switch (R1_CURRENT_STATE(status)) { ++ case R1_STATE_IDLE: ++ case R1_STATE_READY: ++ case R1_STATE_STBY: ++ case R1_STATE_TRAN: ++ /* ++ * In idle and transfer states, HPI is not needed and the caller ++ * can issue the next intended command immediately ++ */ ++ goto out; ++ case R1_STATE_PRG: ++ break; ++ default: ++ /* In all other states, it's illegal to issue HPI */ ++ pr_debug("%s: HPI cannot be sent. Card state=%d\n", ++ mmc_hostname(card->host), R1_CURRENT_STATE(status)); ++ err = -EINVAL; ++ goto out; ++ } + +- err = mmc_send_status(card, &status); +- if (err) +- break; +- } while (R1_CURRENT_STATE(status) == R1_STATE_PRG); +- } else +- pr_debug("%s: Left prg-state\n", mmc_hostname(card->host)); ++ err = mmc_send_hpi_cmd(card, &status); ++ if (err) ++ goto out; ++ ++ prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time); ++ do { ++ err = mmc_send_status(card, &status); ++ ++ if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN) ++ break; ++ if (time_after(jiffies, prg_wait)) ++ err = -ETIMEDOUT; ++ } while (!err); + + out: + mmc_release_host(card->host); +@@ -466,6 +675,64 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries + EXPORT_SYMBOL(mmc_wait_for_cmd); + + /** ++ * mmc_stop_bkops - stop ongoing BKOPS ++ * @card: MMC card to check BKOPS ++ * ++ * Send HPI command to stop ongoing background operations to ++ * allow rapid servicing of foreground operations, e.g. read/ ++ * writes. Wait until the card comes out of the programming state ++ * to avoid errors in servicing read/write requests. ++ */ ++int mmc_stop_bkops(struct mmc_card *card) ++{ ++ int err = 0; ++ ++ BUG_ON(!card); ++ err = mmc_interrupt_hpi(card); ++ ++ /* ++ * If err is EINVAL, we can't issue an HPI. ++ * It should complete the BKOPS. ++ */ ++ if (!err || (err == -EINVAL)) { ++ mmc_card_clr_doing_bkops(card); ++ err = 0; ++ } ++ ++ return err; ++} ++EXPORT_SYMBOL(mmc_stop_bkops); ++ ++int mmc_read_bkops_status(struct mmc_card *card) ++{ ++ int err; ++ u8 *ext_csd; ++ ++ /* ++ * In future work, we should consider storing the entire ext_csd. ++ */ ++ ext_csd = kmalloc(512, GFP_KERNEL); ++ if (!ext_csd) { ++ pr_err("%s: could not allocate buffer to receive the ext_csd.\n", ++ mmc_hostname(card->host)); ++ return -ENOMEM; ++ } ++ ++ mmc_claim_host(card->host); ++ err = mmc_send_ext_csd(card, ext_csd); ++ mmc_release_host(card->host); ++ if (err) ++ goto out; ++ ++ card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS]; ++ card->ext_csd.raw_exception_status = ext_csd[EXT_CSD_EXP_EVENTS_STATUS]; ++out: ++ kfree(ext_csd); ++ return err; ++} ++EXPORT_SYMBOL(mmc_read_bkops_status); ++ ++/** + * mmc_set_data_timeout - set the timeout for a data command + * @data: data phase for command + * @card: the MMC card associated with the data transfer +@@ -514,10 +781,14 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) + + if (data->flags & MMC_DATA_WRITE) + /* +- * The limit is really 250 ms, but that is +- * insufficient for some crappy cards. ++ * The MMC spec "It is strongly recommended ++ * for hosts to implement more than 500ms ++ * timeout value even if the card indicates ++ * the 250ms maximum busy length." Even the ++ * previous value of 300ms is known to be ++ * insufficient for some cards. + */ +- limit_us = 300000; ++ limit_us = 3000000; + else + limit_us = 100000; + +@@ -528,6 +799,10 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) + data->timeout_ns = limit_us * 1000; + data->timeout_clks = 0; + } ++ ++ /* assign limit value if invalid */ ++ if (timeout_us == 0) ++ data->timeout_ns = limit_us * 1000; + } + + /* +@@ -587,101 +862,6 @@ unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz) + EXPORT_SYMBOL(mmc_align_data_size); + + /** +- * mmc_host_enable - enable a host. +- * @host: mmc host to enable +- * +- * Hosts that support power saving can use the 'enable' and 'disable' +- * methods to exit and enter power saving states. For more information +- * see comments for struct mmc_host_ops. +- */ +-int mmc_host_enable(struct mmc_host *host) +-{ +- if (!(host->caps & MMC_CAP_DISABLE)) +- return 0; +- +- if (host->en_dis_recurs) +- return 0; +- +- if (host->nesting_cnt++) +- return 0; +- +- cancel_delayed_work_sync(&host->disable); +- +- if (host->enabled) +- return 0; +- +- if (host->ops->enable) { +- int err; +- +- host->en_dis_recurs = 1; +- err = host->ops->enable(host); +- host->en_dis_recurs = 0; +- +- if (err) { +- pr_debug("%s: enable error %d\n", +- mmc_hostname(host), err); +- return err; +- } +- } +- host->enabled = 1; +- return 0; +-} +-EXPORT_SYMBOL(mmc_host_enable); +- +-static int mmc_host_do_disable(struct mmc_host *host, int lazy) +-{ +- if (host->ops->disable) { +- int err; +- +- host->en_dis_recurs = 1; +- err = host->ops->disable(host, lazy); +- host->en_dis_recurs = 0; +- +- if (err < 0) { +- pr_debug("%s: disable error %d\n", +- mmc_hostname(host), err); +- return err; +- } +- if (err > 0) { +- unsigned long delay = msecs_to_jiffies(err); +- +- mmc_schedule_delayed_work(&host->disable, delay); +- } +- } +- host->enabled = 0; +- return 0; +-} +- +-/** +- * mmc_host_disable - disable a host. +- * @host: mmc host to disable +- * +- * Hosts that support power saving can use the 'enable' and 'disable' +- * methods to exit and enter power saving states. For more information +- * see comments for struct mmc_host_ops. +- */ +-int mmc_host_disable(struct mmc_host *host) +-{ +- int err; +- +- if (!(host->caps & MMC_CAP_DISABLE)) +- return 0; +- +- if (host->en_dis_recurs) +- return 0; +- +- if (--host->nesting_cnt) +- return 0; +- +- if (!host->enabled) +- return 0; +- +- err = mmc_host_do_disable(host, 0); +- return err; +-} +-EXPORT_SYMBOL(mmc_host_disable); +- +-/** + * __mmc_claim_host - exclusively claim a host + * @host: mmc host to claim + * @abort: whether or not the operation should be aborted +@@ -719,46 +899,28 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) + wake_up(&host->wq); + spin_unlock_irqrestore(&host->lock, flags); + remove_wait_queue(&host->wq, &wait); +- if (!stop) +- mmc_host_enable(host); ++ if (host->ops->enable && !stop && host->claim_cnt == 1) ++ host->ops->enable(host); + return stop; + } + + EXPORT_SYMBOL(__mmc_claim_host); + + /** +- * mmc_try_claim_host - try exclusively to claim a host +- * @host: mmc host to claim ++ * mmc_release_host - release a host ++ * @host: mmc host to release + * +- * Returns %1 if the host is claimed, %0 otherwise. ++ * Release a MMC host, allowing others to claim the host ++ * for their operations. + */ +-int mmc_try_claim_host(struct mmc_host *host) ++void mmc_release_host(struct mmc_host *host) + { +- int claimed_host = 0; + unsigned long flags; + +- spin_lock_irqsave(&host->lock, flags); +- if (!host->claimed || host->claimer == current) { +- host->claimed = 1; +- host->claimer = current; +- host->claim_cnt += 1; +- claimed_host = 1; +- } +- spin_unlock_irqrestore(&host->lock, flags); +- return claimed_host; +-} +-EXPORT_SYMBOL(mmc_try_claim_host); ++ WARN_ON(!host->claimed); + +-/** +- * mmc_do_release_host - release a claimed host +- * @host: mmc host to release +- * +- * If you successfully claimed a host, this function will +- * release it again. +- */ +-void mmc_do_release_host(struct mmc_host *host) +-{ +- unsigned long flags; ++ if (host->ops->disable && host->claim_cnt == 1) ++ host->ops->disable(host); + + spin_lock_irqsave(&host->lock, flags); + if (--host->claim_cnt) { +@@ -771,68 +933,30 @@ void mmc_do_release_host(struct mmc_host *host) + wake_up(&host->wq); + } + } +-EXPORT_SYMBOL(mmc_do_release_host); +- +-void mmc_host_deeper_disable(struct work_struct *work) +-{ +- struct mmc_host *host = +- container_of(work, struct mmc_host, disable.work); +- +- /* If the host is claimed then we do not want to disable it anymore */ +- if (!mmc_try_claim_host(host)) +- return; +- mmc_host_do_disable(host, 1); +- mmc_do_release_host(host); +-} ++EXPORT_SYMBOL(mmc_release_host); + +-/** +- * mmc_host_lazy_disable - lazily disable a host. +- * @host: mmc host to disable +- * +- * Hosts that support power saving can use the 'enable' and 'disable' +- * methods to exit and enter power saving states. For more information +- * see comments for struct mmc_host_ops. ++/* ++ * This is a helper function, which fetches a runtime pm reference for the ++ * card device and also claims the host. + */ +-int mmc_host_lazy_disable(struct mmc_host *host) ++void mmc_get_card(struct mmc_card *card) + { +- if (!(host->caps & MMC_CAP_DISABLE)) +- return 0; +- +- if (host->en_dis_recurs) +- return 0; +- +- if (--host->nesting_cnt) +- return 0; +- +- if (!host->enabled) +- return 0; +- +- if (host->disable_delay) { +- mmc_schedule_delayed_work(&host->disable, +- msecs_to_jiffies(host->disable_delay)); +- return 0; +- } else +- return mmc_host_do_disable(host, 1); ++ pm_runtime_get_sync(&card->dev); ++ mmc_claim_host(card->host); + } +-EXPORT_SYMBOL(mmc_host_lazy_disable); ++EXPORT_SYMBOL(mmc_get_card); + +-/** +- * mmc_release_host - release a host +- * @host: mmc host to release +- * +- * Release a MMC host, allowing others to claim the host +- * for their operations. ++/* ++ * This is a helper function, which releases the host and drops the runtime ++ * pm reference for the card device. + */ +-void mmc_release_host(struct mmc_host *host) ++void mmc_put_card(struct mmc_card *card) + { +- WARN_ON(!host->claimed); +- +- mmc_host_lazy_disable(host); +- +- mmc_do_release_host(host); ++ mmc_release_host(card->host); ++ pm_runtime_mark_last_busy(&card->dev); ++ pm_runtime_put_autosuspend(&card->dev); + } +- +-EXPORT_SYMBOL(mmc_release_host); ++EXPORT_SYMBOL(mmc_put_card); + + /* + * Internal function that does the actual ios call to the host driver, +@@ -1037,6 +1161,49 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max) + } + EXPORT_SYMBOL(mmc_vddrange_to_ocrmask); + ++#ifdef CONFIG_OF ++ ++/** ++ * mmc_of_parse_voltage - return mask of supported voltages ++ * @np: The device node need to be parsed. ++ * @mask: mask of voltages available for MMC/SD/SDIO ++ * ++ * 1. Return zero on success. ++ * 2. Return negative errno: voltage-range is invalid. ++ */ ++int mmc_of_parse_voltage(struct device_node *np, u32 *mask) ++{ ++ const u32 *voltage_ranges; ++ int num_ranges, i; ++ ++ voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges); ++ num_ranges = num_ranges / sizeof(*voltage_ranges) / 2; ++ if (!voltage_ranges || !num_ranges) { ++ pr_info("%s: voltage-ranges unspecified\n", np->full_name); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < num_ranges; i++) { ++ const int j = i * 2; ++ u32 ocr_mask; ++ ++ ocr_mask = mmc_vddrange_to_ocrmask( ++ be32_to_cpu(voltage_ranges[j]), ++ be32_to_cpu(voltage_ranges[j + 1])); ++ if (!ocr_mask) { ++ pr_err("%s: voltage-range #%d is invalid\n", ++ np->full_name, i); ++ return -EINVAL; ++ } ++ *mask |= ocr_mask; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(mmc_of_parse_voltage); ++ ++#endif /* CONFIG_OF */ ++ + #ifdef CONFIG_REGULATOR + + /** +@@ -1072,7 +1239,7 @@ int mmc_regulator_get_ocrmask(struct regulator *supply) + + return result; + } +-EXPORT_SYMBOL(mmc_regulator_get_ocrmask); ++EXPORT_SYMBOL_GPL(mmc_regulator_get_ocrmask); + + /** + * mmc_regulator_set_ocr - set regulator to match host->ios voltage +@@ -1097,7 +1264,8 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, + int tmp; + int voltage; + +- /* REVISIT mmc_vddrange_to_ocrmask() may have set some ++ /* ++ * REVISIT mmc_vddrange_to_ocrmask() may have set some + * bits this regulator doesn't quite support ... don't + * be too picky, most cards and regulators are OK with + * a 0.1V range goof (it's a small error percentage). +@@ -1111,10 +1279,15 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, + max_uV = min_uV + 100 * 1000; + } + +- /* avoid needless changes to this voltage; the regulator +- * might not allow this operation ++ /* ++ * If we're using a fixed/static regulator, don't call ++ * regulator_set_voltage; it would fail. + */ + voltage = regulator_get_voltage(supply); ++ ++ if (!regulator_can_change_voltage(supply)) ++ min_uV = max_uV = voltage; ++ + if (voltage < 0) + result = voltage; + else if (voltage < min_uV || voltage > max_uV) +@@ -1138,7 +1311,37 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, + "could not set regulator OCR (%d)\n", result); + return result; + } +-EXPORT_SYMBOL(mmc_regulator_set_ocr); ++EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr); ++ ++int mmc_regulator_get_supply(struct mmc_host *mmc) ++{ ++ struct device *dev = mmc_dev(mmc); ++ int ret; ++ ++ mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc"); ++ mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc"); ++ ++ if (IS_ERR(mmc->supply.vmmc)) { ++ if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ dev_info(dev, "No vmmc regulator found\n"); ++ } else { ++ ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc); ++ if (ret > 0) ++ mmc->ocr_avail = ret; ++ else ++ dev_warn(dev, "Failed getting OCR mask: %d\n", ret); ++ } ++ ++ if (IS_ERR(mmc->supply.vqmmc)) { ++ if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ dev_info(dev, "No vqmmc regulator found\n"); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(mmc_regulator_get_supply); + + #endif /* CONFIG_REGULATOR */ + +@@ -1150,55 +1353,141 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) + { + int bit; + +- ocr &= host->ocr_avail; ++ /* ++ * Sanity check the voltages that the card claims to ++ * support. ++ */ ++ if (ocr & 0x7F) { ++ dev_warn(mmc_dev(host), ++ "card claims to support voltages below defined range\n"); ++ ocr &= ~0x7F; ++ } + +- bit = ffs(ocr); +- if (bit) { +- bit -= 1; ++ ocr &= host->ocr_avail; ++ if (!ocr) { ++ dev_warn(mmc_dev(host), "no support for card's volts\n"); ++ return 0; ++ } + ++ if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) { ++ bit = ffs(ocr) - 1; ++ ocr &= 3 << bit; ++ mmc_power_cycle(host, ocr); ++ } else { ++ bit = fls(ocr) - 1; + ocr &= 3 << bit; ++ if (bit != host->ios.vdd) ++ dev_warn(mmc_dev(host), "exceeding card's volts\n"); ++ } ++ ++ return ocr; ++} ++ ++int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) ++{ ++ int err = 0; ++ int old_signal_voltage = host->ios.signal_voltage; ++ ++ host->ios.signal_voltage = signal_voltage; ++ if (host->ops->start_signal_voltage_switch) { ++ mmc_host_clk_hold(host); ++ err = host->ops->start_signal_voltage_switch(host, &host->ios); ++ mmc_host_clk_release(host); ++ } ++ ++ if (err) ++ host->ios.signal_voltage = old_signal_voltage; ++ ++ return err; ++ ++} ++ ++int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) ++{ ++ struct mmc_command cmd = {0}; ++ int err = 0; ++ u32 clock; ++ ++ BUG_ON(!host); ++ ++ /* ++ * Send CMD11 only if the request is to switch the card to ++ * 1.8V signalling. ++ */ ++ if (signal_voltage == MMC_SIGNAL_VOLTAGE_330) ++ return __mmc_set_signal_voltage(host, signal_voltage); ++ ++ /* ++ * If we cannot switch voltages, return failure so the caller ++ * can continue without UHS mode ++ */ ++ if (!host->ops->start_signal_voltage_switch) ++ return -EPERM; ++ if (!host->ops->card_busy) ++ pr_warning("%s: cannot verify signal voltage switch\n", ++ mmc_hostname(host)); ++ ++ cmd.opcode = SD_SWITCH_VOLTAGE; ++ cmd.arg = 0; ++ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; ++ ++ err = mmc_wait_for_cmd(host, &cmd, 0); ++ if (err) ++ return err; ++ ++ if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) ++ return -EIO; + +- mmc_host_clk_hold(host); +- host->ios.vdd = bit; +- mmc_set_ios(host); +- mmc_host_clk_release(host); +- } else { +- pr_warning("%s: host doesn't support card's voltages\n", +- mmc_hostname(host)); +- ocr = 0; ++ mmc_host_clk_hold(host); ++ /* ++ * The card should drive cmd and dat[0:3] low immediately ++ * after the response of cmd11, but wait 1 ms to be sure ++ */ ++ mmc_delay(1); ++ if (host->ops->card_busy && !host->ops->card_busy(host)) { ++ err = -EAGAIN; ++ goto power_cycle; + } ++ /* ++ * During a signal voltage level switch, the clock must be gated ++ * for 5 ms according to the SD spec ++ */ ++ clock = host->ios.clock; ++ host->ios.clock = 0; ++ mmc_set_ios(host); + +- return ocr; +-} ++ if (__mmc_set_signal_voltage(host, signal_voltage)) { ++ /* ++ * Voltages may not have been switched, but we've already ++ * sent CMD11, so a power cycle is required anyway ++ */ ++ err = -EAGAIN; ++ goto power_cycle; ++ } + +-int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11) +-{ +- struct mmc_command cmd = {0}; +- int err = 0; ++ /* Keep clock gated for at least 5 ms */ ++ mmc_delay(5); ++ host->ios.clock = clock; ++ mmc_set_ios(host); + +- BUG_ON(!host); ++ /* Wait for at least 1 ms according to spec */ ++ mmc_delay(1); + + /* +- * Send CMD11 only if the request is to switch the card to +- * 1.8V signalling. ++ * Failure to switch is indicated by the card holding ++ * dat[0:3] low + */ +- if ((signal_voltage != MMC_SIGNAL_VOLTAGE_330) && cmd11) { +- cmd.opcode = SD_SWITCH_VOLTAGE; +- cmd.arg = 0; +- cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; +- +- err = mmc_wait_for_cmd(host, &cmd, 0); +- if (err) +- return err; ++ if (host->ops->card_busy && host->ops->card_busy(host)) ++ err = -EAGAIN; + +- if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) +- return -EIO; ++power_cycle: ++ if (err) { ++ pr_debug("%s: Signal voltage switch failed, " ++ "power cycling card\n", mmc_hostname(host)); ++ mmc_power_cycle(host, ocr); + } + +- host->ios.signal_voltage = signal_voltage; +- +- if (host->ops->start_signal_voltage_switch) +- err = host->ops->start_signal_voltage_switch(host, &host->ios); ++ mmc_host_clk_release(host); + + return err; + } +@@ -1225,46 +1514,6 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type) + mmc_host_clk_release(host); + } + +-static void mmc_poweroff_notify(struct mmc_host *host) +-{ +- struct mmc_card *card; +- unsigned int timeout; +- unsigned int notify_type = EXT_CSD_NO_POWER_NOTIFICATION; +- int err = 0; +- +- card = host->card; +- +- /* +- * Send power notify command only if card +- * is mmc and notify state is powered ON +- */ +- if (card && mmc_card_mmc(card) && +- (card->poweroff_notify_state == MMC_POWERED_ON)) { +- +- if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) { +- notify_type = EXT_CSD_POWER_OFF_SHORT; +- timeout = card->ext_csd.generic_cmd6_time; +- card->poweroff_notify_state = MMC_POWEROFF_SHORT; +- } else { +- notify_type = EXT_CSD_POWER_OFF_LONG; +- timeout = card->ext_csd.power_off_longtime; +- card->poweroff_notify_state = MMC_POWEROFF_LONG; +- } +- +- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +- EXT_CSD_POWER_OFF_NOTIFICATION, +- notify_type, timeout); +- +- if (err && err != -EBADMSG) +- pr_err("Device failed to respond within %d poweroff " +- "time. Forcefully powering down the device\n", +- timeout); +- +- /* Set the card state to no notification after the poweroff */ +- card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION; +- } +-} +- + /* + * Apply power to the MMC stack. This is a two-stage process. + * First, we enable power to the card without the clock running. +@@ -1276,19 +1525,14 @@ static void mmc_poweroff_notify(struct mmc_host *host) + * If a host does all the power sequencing itself, ignore the + * initial MMC_POWER_UP stage. + */ +-static void mmc_power_up(struct mmc_host *host) ++void mmc_power_up(struct mmc_host *host, u32 ocr) + { +- int bit; ++ if (host->ios.power_mode == MMC_POWER_ON) ++ return; + + mmc_host_clk_hold(host); + +- /* If ocr is set, we use it */ +- if (host->ocr) +- bit = ffs(host->ocr) - 1; +- else +- bit = fls(host->ocr_avail) - 1; +- +- host->ios.vdd = bit; ++ host->ios.vdd = fls(ocr) - 1; + if (mmc_host_is_spi(host)) + host->ios.chip_select = MMC_CS_HIGH; + else +@@ -1299,6 +1543,14 @@ static void mmc_power_up(struct mmc_host *host) + host->ios.timing = MMC_TIMING_LEGACY; + mmc_set_ios(host); + ++ /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */ ++ if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330) == 0) ++ dev_dbg(mmc_dev(host), "Initial signal voltage of 3.3v\n"); ++ else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180) == 0) ++ dev_dbg(mmc_dev(host), "Initial signal voltage of 1.8v\n"); ++ else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120) == 0) ++ dev_dbg(mmc_dev(host), "Initial signal voltage of 1.2v\n"); ++ + /* + * This delay should be sufficient to allow the power supply + * to reach the minimum voltage. +@@ -1321,19 +1573,14 @@ static void mmc_power_up(struct mmc_host *host) + + void mmc_power_off(struct mmc_host *host) + { ++ if (host->ios.power_mode == MMC_POWER_OFF) ++ return; ++ + mmc_host_clk_hold(host); + + host->ios.clock = 0; + host->ios.vdd = 0; + +- mmc_poweroff_notify(host); +- +- /* +- * Reset ocr mask to be the highest possible voltage supported for +- * this mmc host. This value will be used at next power up. +- */ +- host->ocr = 1 << (fls(host->ocr_avail) - 1); +- + if (!mmc_host_is_spi(host)) { + host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; + host->ios.chip_select = MMC_CS_DONTCARE; +@@ -1353,6 +1600,14 @@ void mmc_power_off(struct mmc_host *host) + mmc_host_clk_release(host); + } + ++void mmc_power_cycle(struct mmc_host *host, u32 ocr) ++{ ++ mmc_power_off(host); ++ /* Wait at least 1 ms according to SD spec */ ++ mmc_delay(1); ++ mmc_power_up(host, ocr); ++} ++ + /* + * Cleanup when the last reference to the bus operator is dropped. + */ +@@ -1438,6 +1693,28 @@ void mmc_detach_bus(struct mmc_host *host) + mmc_bus_put(host); + } + ++static void _mmc_detect_change(struct mmc_host *host, unsigned long delay, ++ bool cd_irq) ++{ ++#ifdef CONFIG_MMC_DEBUG ++ unsigned long flags; ++ spin_lock_irqsave(&host->lock, flags); ++ WARN_ON(host->removed); ++ spin_unlock_irqrestore(&host->lock, flags); ++#endif ++ ++ /* ++ * If the device is configured as wakeup, we prevent a new sleep for ++ * 5 s to give provision for user space to consume the event. ++ */ ++ if (cd_irq && !(host->caps & MMC_CAP_NEEDS_POLL) && ++ device_can_wakeup(mmc_dev(host))) ++ pm_wakeup_event(mmc_dev(host), 5000); ++ ++ host->detect_change = 1; ++ mmc_schedule_delayed_work(&host->detect, delay); ++} ++ + /** + * mmc_detect_change - process change of state on a MMC socket + * @host: host which changed state. +@@ -1450,16 +1727,8 @@ void mmc_detach_bus(struct mmc_host *host) + */ + void mmc_detect_change(struct mmc_host *host, unsigned long delay) + { +-#ifdef CONFIG_MMC_DEBUG +- unsigned long flags; +- spin_lock_irqsave(&host->lock, flags); +- WARN_ON(host->removed); +- spin_unlock_irqrestore(&host->lock, flags); +-#endif +- +- mmc_schedule_delayed_work(&host->detect, delay); ++ _mmc_detect_change(host, delay, true); + } +- + EXPORT_SYMBOL(mmc_detect_change); + + void mmc_init_erase(struct mmc_card *card) +@@ -1615,6 +1884,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, + { + struct mmc_command cmd = {0}; + unsigned int qty = 0; ++ unsigned long timeout; + int err; + + /* +@@ -1680,7 +1950,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, + cmd.opcode = MMC_ERASE; + cmd.arg = arg; + cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; +- cmd.cmd_timeout_ms = mmc_erase_timeout(card, arg, qty); ++ cmd.busy_timeout = mmc_erase_timeout(card, arg, qty); + err = mmc_wait_for_cmd(card->host, &cmd, 0); + if (err) { + pr_err("mmc_erase: erase error %d, status %#x\n", +@@ -1692,6 +1962,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, + if (mmc_host_is_spi(card->host)) + goto out; + ++ timeout = jiffies + msecs_to_jiffies(MMC_CORE_TIMEOUT_MS); + do { + memset(&cmd, 0, sizeof(struct mmc_command)); + cmd.opcode = MMC_SEND_STATUS; +@@ -1705,8 +1976,19 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, + err = -EIO; + goto out; + } ++ ++ /* Timeout if the device never becomes ready for data and ++ * never leaves the program state. ++ */ ++ if (time_after(jiffies, timeout)) { ++ pr_err("%s: Card stuck in programming state! %s\n", ++ mmc_hostname(card->host), __func__); ++ err = -EIO; ++ goto out; ++ } ++ + } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || +- R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG); ++ (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG)); + out: + return err; + } +@@ -1855,7 +2137,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, + y = 0; + for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) { + timeout = mmc_erase_timeout(card, arg, qty + x); +- if (timeout > host->max_discard_to) ++ if (timeout > host->max_busy_timeout) + break; + if (timeout < last_timeout) + break; +@@ -1887,7 +2169,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) + struct mmc_host *host = card->host; + unsigned int max_discard, max_trim; + +- if (!host->max_discard_to) ++ if (!host->max_busy_timeout) + return UINT_MAX; + + /* +@@ -1907,7 +2189,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) + max_discard = 0; + } + pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n", +- mmc_hostname(host), max_discard, host->max_discard_to); ++ mmc_hostname(host), max_discard, host->max_busy_timeout); + return max_discard; + } + EXPORT_SYMBOL(mmc_calc_max_discard); +@@ -1916,7 +2198,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) + { + struct mmc_command cmd = {0}; + +- if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card)) ++ if (mmc_card_blockaddr(card) || mmc_card_ddr52(card)) + return 0; + + cmd.opcode = MMC_SET_BLOCKLEN; +@@ -1926,6 +2208,20 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) + } + EXPORT_SYMBOL(mmc_set_blocklen); + ++int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount, ++ bool is_rel_write) ++{ ++ struct mmc_command cmd = {0}; ++ ++ cmd.opcode = MMC_SET_BLOCK_COUNT; ++ cmd.arg = blockcount & 0x0000FFFF; ++ if (is_rel_write) ++ cmd.arg |= 1 << 31; ++ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; ++ return mmc_wait_for_cmd(card->host, &cmd, 5); ++} ++EXPORT_SYMBOL(mmc_set_blockcount); ++ + static void mmc_hw_reset_for_init(struct mmc_host *host) + { + if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) +@@ -1952,9 +2248,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check) + { + struct mmc_card *card = host->card; + +- if (!host->bus_ops->power_restore) +- return -EOPNOTSUPP; +- + if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) + return -EOPNOTSUPP; + +@@ -1985,7 +2278,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check) + } + } + +- host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR); + if (mmc_host_is_spi(host)) { + host->ios.chip_select = MMC_CS_HIGH; + host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; +@@ -2022,7 +2314,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) + pr_info("%s: %s: trying to init card at %u Hz\n", + mmc_hostname(host), __func__, host->f_init); + #endif +- mmc_power_up(host); ++ mmc_power_up(host, host->ocr_avail); + + /* + * Some eMMCs (with VCCQ always on) may not be reset after power up, so +@@ -2052,26 +2344,104 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) + return -EIO; + } + ++int _mmc_detect_card_removed(struct mmc_host *host) ++{ ++ int ret; ++ ++ if (host->caps & MMC_CAP_NONREMOVABLE) ++ return 0; ++ ++ if (!host->card || mmc_card_removed(host->card)) ++ return 1; ++ ++ ret = host->bus_ops->alive(host); ++ ++ /* ++ * Card detect status and alive check may be out of sync if card is ++ * removed slowly, when card detect switch changes while card/slot ++ * pads are still contacted in hardware (refer to "SD Card Mechanical ++ * Addendum, Appendix C: Card Detection Switch"). So reschedule a ++ * detect work 200ms later for this case. ++ */ ++ if (!ret && host->ops->get_cd && !host->ops->get_cd(host)) { ++ mmc_detect_change(host, msecs_to_jiffies(200)); ++ pr_debug("%s: card removed too slowly\n", mmc_hostname(host)); ++ } ++ ++ if (ret) { ++ mmc_card_set_removed(host->card); ++ pr_debug("%s: card remove detected\n", mmc_hostname(host)); ++ } ++ ++ return ret; ++} ++ ++int mmc_detect_card_removed(struct mmc_host *host) ++{ ++ struct mmc_card *card = host->card; ++ int ret; ++ ++ WARN_ON(!host->claimed); ++ ++ if (!card) ++ return 1; ++ ++ ret = mmc_card_removed(card); ++ /* ++ * The card will be considered unchanged unless we have been asked to ++ * detect a change or host requires polling to provide card detection. ++ */ ++ if (!host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL)) ++ return ret; ++ ++ host->detect_change = 0; ++ if (!ret) { ++ ret = _mmc_detect_card_removed(host); ++ if (ret && (host->caps & MMC_CAP_NEEDS_POLL)) { ++ /* ++ * Schedule a detect work as soon as possible to let a ++ * rescan handle the card removal. ++ */ ++ cancel_delayed_work(&host->detect); ++ _mmc_detect_change(host, 0, false); ++ } ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(mmc_detect_card_removed); ++ + void mmc_rescan(struct work_struct *work) + { +- static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; + struct mmc_host *host = + container_of(work, struct mmc_host, detect.work); + int i; + ++ if (host->trigger_card_event && host->ops->card_event) { ++ host->ops->card_event(host); ++ host->trigger_card_event = false; ++ } ++ + if (host->rescan_disable) + return; + ++ /* If there is a non-removable card registered, only scan once */ ++ if ((host->caps & MMC_CAP_NONREMOVABLE) && host->rescan_entered) ++ return; ++ host->rescan_entered = 1; ++ + mmc_bus_get(host); + + /* + * if there is a _removable_ card registered, check whether it is + * still present + */ +- if (host->bus_ops && host->bus_ops->detect && !host->bus_dead ++ if (host->bus_ops && !host->bus_dead + && !(host->caps & MMC_CAP_NONREMOVABLE)) + host->bus_ops->detect(host); + ++ host->detect_change = 0; ++ + /* + * Let mmc_bus_put() free the bus/bus_ops if we've found that + * the card is no longer present. +@@ -2091,8 +2461,13 @@ void mmc_rescan(struct work_struct *work) + */ + mmc_bus_put(host); + +- if (host->ops->get_cd && host->ops->get_cd(host) == 0) ++ if (!(host->caps & MMC_CAP_NONREMOVABLE) && host->ops->get_cd && ++ host->ops->get_cd(host) == 0) { ++ mmc_claim_host(host); ++ mmc_power_off(host); ++ mmc_release_host(host); + goto out; ++ } + + mmc_claim_host(host); + for (i = 0; i < ARRAY_SIZE(freqs); i++) { +@@ -2110,8 +2485,13 @@ void mmc_rescan(struct work_struct *work) + + void mmc_start_host(struct mmc_host *host) + { +- mmc_power_off(host); +- mmc_detect_change(host, 0); ++ host->f_init = max(freqs[0], host->f_min); ++ host->rescan_disable = 0; ++ if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP) ++ mmc_power_off(host); ++ else ++ mmc_power_up(host, host->ocr_avail); ++ _mmc_detect_change(host, 0, false); + } + + void mmc_stop_host(struct mmc_host *host) +@@ -2123,8 +2503,7 @@ void mmc_stop_host(struct mmc_host *host) + spin_unlock_irqrestore(&host->lock, flags); + #endif + +- if (host->caps & MMC_CAP_DISABLE) +- cancel_delayed_work(&host->disable); ++ host->rescan_disable = 1; + cancel_delayed_work_sync(&host->detect); + mmc_flush_scheduled_work(); + +@@ -2133,9 +2512,8 @@ void mmc_stop_host(struct mmc_host *host) + + mmc_bus_get(host); + if (host->bus_ops && !host->bus_dead) { +- if (host->bus_ops->remove) +- host->bus_ops->remove(host); +- ++ /* Calling bus_ops->remove() with a claimed host can deadlock */ ++ host->bus_ops->remove(host); + mmc_claim_host(host); + mmc_detach_bus(host); + mmc_power_off(host); +@@ -2160,7 +2538,7 @@ int mmc_power_save_host(struct mmc_host *host) + + mmc_bus_get(host); + +- if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { ++ if (!host->bus_ops || host->bus_dead) { + mmc_bus_put(host); + return -EINVAL; + } +@@ -2186,12 +2564,12 @@ int mmc_power_restore_host(struct mmc_host *host) + + mmc_bus_get(host); + +- if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { ++ if (!host->bus_ops || host->bus_dead) { + mmc_bus_put(host); + return -EINVAL; + } + +- mmc_power_up(host); ++ mmc_power_up(host, host->card->ocr); + ret = host->bus_ops->power_restore(host); + + mmc_bus_put(host); +@@ -2200,57 +2578,13 @@ int mmc_power_restore_host(struct mmc_host *host) + } + EXPORT_SYMBOL(mmc_power_restore_host); + +-int mmc_card_awake(struct mmc_host *host) +-{ +- int err = -ENOSYS; +- +- mmc_bus_get(host); +- +- if (host->bus_ops && !host->bus_dead && host->bus_ops->awake) +- err = host->bus_ops->awake(host); +- +- mmc_bus_put(host); +- +- return err; +-} +-EXPORT_SYMBOL(mmc_card_awake); +- +-int mmc_card_sleep(struct mmc_host *host) +-{ +- int err = -ENOSYS; +- +- mmc_bus_get(host); +- +- if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep) +- err = host->bus_ops->sleep(host); +- +- mmc_bus_put(host); +- +- return err; +-} +-EXPORT_SYMBOL(mmc_card_sleep); +- +-int mmc_card_can_sleep(struct mmc_host *host) +-{ +- struct mmc_card *card = host->card; +- +- if (card && mmc_card_mmc(card) && card->ext_csd.rev >= 3) +- return 1; +- return 0; +-} +-EXPORT_SYMBOL(mmc_card_can_sleep); +- + /* + * Flush the cache to the non-volatile storage. + */ + int mmc_flush_cache(struct mmc_card *card) + { +- struct mmc_host *host = card->host; + int err = 0; + +- if (!(host->caps2 & MMC_CAP2_CACHE_CTRL)) +- return err; +- + if (mmc_card_mmc(card) && + (card->ext_csd.cache_size > 0) && + (card->ext_csd.cache_ctrl & 1)) { +@@ -2265,150 +2599,8 @@ int mmc_flush_cache(struct mmc_card *card) + } + EXPORT_SYMBOL(mmc_flush_cache); + +-/* +- * Turn the cache ON/OFF. +- * Turning the cache OFF shall trigger flushing of the data +- * to the non-volatile storage. +- */ +-int mmc_cache_ctrl(struct mmc_host *host, u8 enable) +-{ +- struct mmc_card *card = host->card; +- int err = 0; +- +- if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) || +- mmc_card_is_removable(host)) +- return err; +- +- if (card && mmc_card_mmc(card) && +- (card->ext_csd.cache_size > 0)) { +- enable = !!enable; +- +- if (card->ext_csd.cache_ctrl ^ enable) +- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +- EXT_CSD_CACHE_CTRL, enable, 0); +- if (err) +- pr_err("%s: cache %s error %d\n", +- mmc_hostname(card->host), +- enable ? "on" : "off", +- err); +- else +- card->ext_csd.cache_ctrl = enable; +- } +- +- return err; +-} +-EXPORT_SYMBOL(mmc_cache_ctrl); +- + #ifdef CONFIG_PM + +-/** +- * mmc_suspend_host - suspend a host +- * @host: mmc host +- */ +-int mmc_suspend_host(struct mmc_host *host) +-{ +- int err = 0; +- +- if (host->caps & MMC_CAP_DISABLE) +- cancel_delayed_work(&host->disable); +- cancel_delayed_work(&host->detect); +- mmc_flush_scheduled_work(); +- err = mmc_cache_ctrl(host, 0); +- if (err) +- goto out; +- +- mmc_bus_get(host); +- if (host->bus_ops && !host->bus_dead) { +- +- /* +- * A long response time is not acceptable for device drivers +- * when doing suspend. Prevent mmc_claim_host in the suspend +- * sequence, to potentially wait "forever" by trying to +- * pre-claim the host. +- */ +- if (mmc_try_claim_host(host)) { +- if (host->bus_ops->suspend) { +- /* +- * For eMMC 4.5 device send notify command +- * before sleep, because in sleep state eMMC 4.5 +- * devices respond to only RESET and AWAKE cmd +- */ +- mmc_poweroff_notify(host); +- err = host->bus_ops->suspend(host); +- } +- mmc_do_release_host(host); +- +- if (err == -ENOSYS || !host->bus_ops->resume) { +- /* +- * We simply "remove" the card in this case. +- * It will be redetected on resume. +- */ +- if (host->bus_ops->remove) +- host->bus_ops->remove(host); +- mmc_claim_host(host); +- mmc_detach_bus(host); +- mmc_power_off(host); +- mmc_release_host(host); +- host->pm_flags = 0; +- err = 0; +- } +- } else { +- err = -EBUSY; +- } +- } +- mmc_bus_put(host); +- +- if (!err && !mmc_card_keep_power(host)) +- mmc_power_off(host); +- +-out: +- return err; +-} +- +-EXPORT_SYMBOL(mmc_suspend_host); +- +-/** +- * mmc_resume_host - resume a previously suspended host +- * @host: mmc host +- */ +-int mmc_resume_host(struct mmc_host *host) +-{ +- int err = 0; +- +- mmc_bus_get(host); +- if (host->bus_ops && !host->bus_dead) { +- if (!mmc_card_keep_power(host)) { +- mmc_power_up(host); +- mmc_select_voltage(host, host->ocr); +- /* +- * Tell runtime PM core we just powered up the card, +- * since it still believes the card is powered off. +- * Note that currently runtime PM is only enabled +- * for SDIO cards that are MMC_CAP_POWER_OFF_CARD +- */ +- if (mmc_card_sdio(host->card) && +- (host->caps & MMC_CAP_POWER_OFF_CARD)) { +- pm_runtime_disable(&host->card->dev); +- pm_runtime_set_active(&host->card->dev); +- pm_runtime_enable(&host->card->dev); +- } +- } +- BUG_ON(!host->bus_ops->resume); +- err = host->bus_ops->resume(host); +- if (err) { +- pr_warning("%s: error %d during resume " +- "(card was removed?)\n", +- mmc_hostname(host), err); +- err = 0; +- } +- } +- host->pm_flags &= ~MMC_PM_KEEP_POWER; +- mmc_bus_put(host); +- +- return err; +-} +-EXPORT_SYMBOL(mmc_resume_host); +- + /* Do the card removal on suspend if card is assumed removeable + * Do that in pm notifier while userspace isn't yet frozen, so we will be able + to sync the card. +@@ -2419,7 +2611,7 @@ int mmc_pm_notify(struct notifier_block *notify_block, + struct mmc_host *host = container_of( + notify_block, struct mmc_host, pm_notify); + unsigned long flags; +- ++ int err = 0; + + switch (mode) { + case PM_HIBERNATION_PREPARE: +@@ -2428,18 +2620,21 @@ int mmc_pm_notify(struct notifier_block *notify_block, + + spin_lock_irqsave(&host->lock, flags); + host->rescan_disable = 1; +- host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT; + spin_unlock_irqrestore(&host->lock, flags); + cancel_delayed_work_sync(&host->detect); + +- if (!host->bus_ops || host->bus_ops->suspend) ++ if (!host->bus_ops) + break; + +- mmc_claim_host(host); +- +- if (host->bus_ops->remove) +- host->bus_ops->remove(host); ++ /* Validate prerequisites for suspend */ ++ if (host->bus_ops->pre_suspend) ++ err = host->bus_ops->pre_suspend(host); ++ if (!err) ++ break; + ++ /* Calling bus_ops->remove() with a claimed host can deadlock */ ++ host->bus_ops->remove(host); ++ mmc_claim_host(host); + mmc_detach_bus(host); + mmc_power_off(host); + mmc_release_host(host); +@@ -2452,9 +2647,8 @@ int mmc_pm_notify(struct notifier_block *notify_block, + + spin_lock_irqsave(&host->lock, flags); + host->rescan_disable = 0; +- host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG; + spin_unlock_irqrestore(&host->lock, flags); +- mmc_detect_change(host, 0); ++ _mmc_detect_change(host, 0, false); + + } + +@@ -2462,6 +2656,23 @@ int mmc_pm_notify(struct notifier_block *notify_block, + } + #endif + ++/** ++ * mmc_init_context_info() - init synchronization context ++ * @host: mmc host ++ * ++ * Init struct context_info needed to implement asynchronous ++ * request mechanism, used by mmc core, host driver and mmc requests ++ * supplier. ++ */ ++void mmc_init_context_info(struct mmc_host *host) ++{ ++ spin_lock_init(&host->context_info.lock); ++ host->context_info.is_new_req = false; ++ host->context_info.is_done_rcv = false; ++ host->context_info.is_waiting_last_req = false; ++ init_waitqueue_head(&host->context_info.wait); ++} ++ + static int __init mmc_init(void) + { + int ret; +diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h +index 14664f1..443a584 100644 +--- a/drivers/mmc/core/core.h ++++ b/drivers/mmc/core/core.h +@@ -16,14 +16,17 @@ + #define MMC_CMD_RETRIES 3 + + struct mmc_bus_ops { +- int (*awake)(struct mmc_host *); +- int (*sleep)(struct mmc_host *); + void (*remove)(struct mmc_host *); + void (*detect)(struct mmc_host *); ++ int (*pre_suspend)(struct mmc_host *); + int (*suspend)(struct mmc_host *); + int (*resume)(struct mmc_host *); ++ int (*runtime_suspend)(struct mmc_host *); ++ int (*runtime_resume)(struct mmc_host *); + int (*power_save)(struct mmc_host *); + int (*power_restore)(struct mmc_host *); ++ int (*alive)(struct mmc_host *); ++ int (*shutdown)(struct mmc_host *); + }; + + void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); +@@ -39,11 +42,13 @@ void mmc_set_ungated(struct mmc_host *host); + void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); + void mmc_set_bus_width(struct mmc_host *host, unsigned int width); + u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); +-int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, +- bool cmd11); ++int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr); ++int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); + void mmc_set_timing(struct mmc_host *host, unsigned int timing); + void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); ++void mmc_power_up(struct mmc_host *host, u32 ocr); + void mmc_power_off(struct mmc_host *host); ++void mmc_power_cycle(struct mmc_host *host, u32 ocr); + + static inline void mmc_delay(unsigned int ms) + { +@@ -59,12 +64,14 @@ void mmc_rescan(struct work_struct *work); + void mmc_start_host(struct mmc_host *host); + void mmc_stop_host(struct mmc_host *host); + ++int _mmc_detect_card_removed(struct mmc_host *host); ++ + int mmc_attach_mmc(struct mmc_host *host); + int mmc_attach_sd(struct mmc_host *host); + int mmc_attach_sdio(struct mmc_host *host); + + /* Module parameters */ +-extern int use_spi_crc; ++extern bool use_spi_crc; + + /* Debugfs information for hosts and cards */ + void mmc_add_host_debugfs(struct mmc_host *host); +@@ -73,5 +80,6 @@ void mmc_remove_host_debugfs(struct mmc_host *host); + void mmc_add_card_debugfs(struct mmc_card *card); + void mmc_remove_card_debugfs(struct mmc_card *card); + ++void mmc_init_context_info(struct mmc_host *host); + #endif + +diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c +index 3923880..91eb162 100644 +--- a/drivers/mmc/core/debugfs.c ++++ b/drivers/mmc/core/debugfs.c +@@ -57,6 +57,8 @@ static int mmc_ios_show(struct seq_file *s, void *data) + const char *str; + + seq_printf(s, "clock:\t\t%u Hz\n", ios->clock); ++ if (host->actual_clock) ++ seq_printf(s, "actual clock:\t%u Hz\n", host->actual_clock); + seq_printf(s, "vdd:\t\t%u ", ios->vdd); + if ((1 << ios->vdd) & MMC_VDD_165_195) + seq_printf(s, "(1.65 - 1.95 V)\n"); +@@ -133,12 +135,37 @@ static int mmc_ios_show(struct seq_file *s, void *data) + case MMC_TIMING_UHS_DDR50: + str = "sd uhs DDR50"; + break; ++ case MMC_TIMING_MMC_DDR52: ++ str = "mmc DDR52"; ++ break; ++ case MMC_TIMING_MMC_HS200: ++ str = "mmc HS200"; ++ break; ++ case MMC_TIMING_MMC_HS400: ++ str = "mmc HS400"; ++ break; + default: + str = "invalid"; + break; + } + seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str); + ++ switch (ios->signal_voltage) { ++ case MMC_SIGNAL_VOLTAGE_330: ++ str = "3.30 V"; ++ break; ++ case MMC_SIGNAL_VOLTAGE_180: ++ str = "1.80 V"; ++ break; ++ case MMC_SIGNAL_VOLTAGE_120: ++ str = "1.20 V"; ++ break; ++ default: ++ str = "invalid"; ++ break; ++ } ++ seq_printf(s, "signal voltage:\t%u (%s)\n", ios->chip_select, str); ++ + return 0; + } + +@@ -237,13 +264,13 @@ static int mmc_dbg_card_status_get(void *data, u64 *val) + u32 status; + int ret; + +- mmc_claim_host(card->host); ++ mmc_get_card(card); + + ret = mmc_send_status(data, &status); + if (!ret) + *val = status; + +- mmc_release_host(card->host); ++ mmc_put_card(card); + + return ret; + } +@@ -270,13 +297,13 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp) + goto out_free; + } + +- mmc_claim_host(card->host); ++ mmc_get_card(card); + err = mmc_send_ext_csd(card, ext_csd); +- mmc_release_host(card->host); ++ mmc_put_card(card); + if (err) + goto out_free; + +- for (i = 511; i >= 0; i--) ++ for (i = 0; i < 512; i++) + n += sprintf(buf + n, "%02x", ext_csd[i]); + n += sprintf(buf + n, "\n"); + BUG_ON(n != EXT_CSD_STR_LEN); +diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c +index d31c78b..03c71dd 100644 +--- a/drivers/mmc/core/host.c ++++ b/drivers/mmc/core/host.c +@@ -15,6 +15,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -23,6 +25,7 @@ + + #include + #include ++#include + + #include "core.h" + #include "host.h" +@@ -32,6 +35,7 @@ + static void mmc_host_classdev_release(struct device *dev) + { + struct mmc_host *host = cls_dev_to_mmc_host(dev); ++ mutex_destroy(&host->slot.lock); + kfree(host); + } + +@@ -54,6 +58,27 @@ static DEFINE_IDR(mmc_host_idr); + static DEFINE_SPINLOCK(mmc_host_lock); + + #ifdef CONFIG_MMC_CLKGATE ++static ssize_t clkgate_delay_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct mmc_host *host = cls_dev_to_mmc_host(dev); ++ return snprintf(buf, PAGE_SIZE, "%lu\n", host->clkgate_delay); ++} ++ ++static ssize_t clkgate_delay_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct mmc_host *host = cls_dev_to_mmc_host(dev); ++ unsigned long flags, value; ++ ++ if (kstrtoul(buf, 0, &value)) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&host->clk_lock, flags); ++ host->clkgate_delay = value; ++ spin_unlock_irqrestore(&host->clk_lock, flags); ++ return count; ++} + + /* + * Enabling clock gating will make the core call out to the host +@@ -114,7 +139,7 @@ static void mmc_host_clk_gate_delayed(struct mmc_host *host) + static void mmc_host_clk_gate_work(struct work_struct *work) + { + struct mmc_host *host = container_of(work, struct mmc_host, +- clk_gate_work); ++ clk_gate_work.work); + + mmc_host_clk_gate_delayed(host); + } +@@ -131,6 +156,8 @@ void mmc_host_clk_hold(struct mmc_host *host) + { + unsigned long flags; + ++ /* cancel any clock gating work scheduled by mmc_host_clk_release() */ ++ cancel_delayed_work_sync(&host->clk_gate_work); + mutex_lock(&host->clk_gate_mutex); + spin_lock_irqsave(&host->clk_lock, flags); + if (host->clk_gated) { +@@ -180,7 +207,8 @@ void mmc_host_clk_release(struct mmc_host *host) + host->clk_requests--; + if (mmc_host_may_gate_card(host->card) && + !host->clk_requests) +- queue_work(system_nrt_wq, &host->clk_gate_work); ++ schedule_delayed_work(&host->clk_gate_work, ++ msecs_to_jiffies(host->clkgate_delay)); + spin_unlock_irqrestore(&host->clk_lock, flags); + } + +@@ -213,8 +241,13 @@ static inline void mmc_host_clk_init(struct mmc_host *host) + host->clk_requests = 0; + /* Hold MCI clock for 8 cycles by default */ + host->clk_delay = 8; ++ /* ++ * Default clock gating delay is 0ms to avoid wasting power. ++ * This value can be tuned by writing into sysfs entry. ++ */ ++ host->clkgate_delay = 0; + host->clk_gated = false; +- INIT_WORK(&host->clk_gate_work, mmc_host_clk_gate_work); ++ INIT_DELAYED_WORK(&host->clk_gate_work, mmc_host_clk_gate_work); + spin_lock_init(&host->clk_lock); + mutex_init(&host->clk_gate_mutex); + } +@@ -229,7 +262,7 @@ static inline void mmc_host_clk_exit(struct mmc_host *host) + * Wait for any outstanding gate and then make sure we're + * ungated before exiting. + */ +- if (cancel_work_sync(&host->clk_gate_work)) ++ if (cancel_delayed_work_sync(&host->clk_gate_work)) + mmc_host_clk_gate_delayed(host); + if (host->clk_gated) + mmc_host_clk_hold(host); +@@ -237,6 +270,17 @@ static inline void mmc_host_clk_exit(struct mmc_host *host) + WARN_ON(host->clk_requests > 1); + } + ++static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) ++{ ++ host->clkgate_delay_attr.show = clkgate_delay_show; ++ host->clkgate_delay_attr.store = clkgate_delay_store; ++ sysfs_attr_init(&host->clkgate_delay_attr.attr); ++ host->clkgate_delay_attr.attr.name = "clkgate_delay"; ++ host->clkgate_delay_attr.attr.mode = S_IRUGO | S_IWUSR; ++ if (device_create_file(&host->class_dev, &host->clkgate_delay_attr)) ++ pr_err("%s: Failed to create clkgate_delay sysfs entry\n", ++ mmc_hostname(host)); ++} + #else + + static inline void mmc_host_clk_init(struct mmc_host *host) +@@ -247,9 +291,171 @@ static inline void mmc_host_clk_exit(struct mmc_host *host) + { + } + ++static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) ++{ ++} ++ + #endif + + /** ++ * mmc_of_parse() - parse host's device-tree node ++ * @host: host whose node should be parsed. ++ * ++ * To keep the rest of the MMC subsystem unaware of whether DT has been ++ * used to to instantiate and configure this host instance or not, we ++ * parse the properties and set respective generic mmc-host flags and ++ * parameters. ++ */ ++int mmc_of_parse(struct mmc_host *host) ++{ ++ struct device_node *np; ++ u32 bus_width; ++ bool explicit_inv_wp, gpio_inv_wp = false; ++ enum of_gpio_flags flags; ++ int len, ret, gpio; ++ ++ if (!host->parent || !host->parent->of_node) ++ return 0; ++ ++ np = host->parent->of_node; ++ ++ /* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */ ++ if (of_property_read_u32(np, "bus-width", &bus_width) < 0) { ++ dev_dbg(host->parent, ++ "\"bus-width\" property is missing, assuming 1 bit.\n"); ++ bus_width = 1; ++ } ++ ++ switch (bus_width) { ++ case 8: ++ host->caps |= MMC_CAP_8_BIT_DATA; ++ /* Hosts capable of 8-bit transfers can also do 4 bits */ ++ case 4: ++ host->caps |= MMC_CAP_4_BIT_DATA; ++ break; ++ case 1: ++ break; ++ default: ++ dev_err(host->parent, ++ "Invalid \"bus-width\" value %u!\n", bus_width); ++ return -EINVAL; ++ } ++ ++ /* f_max is obtained from the optional "max-frequency" property */ ++ of_property_read_u32(np, "max-frequency", &host->f_max); ++ ++ /* ++ * Configure CD and WP pins. They are both by default active low to ++ * match the SDHCI spec. If GPIOs are provided for CD and / or WP, the ++ * mmc-gpio helpers are used to attach, configure and use them. If ++ * polarity inversion is specified in DT, one of MMC_CAP2_CD_ACTIVE_HIGH ++ * and MMC_CAP2_RO_ACTIVE_HIGH capability-2 flags is set. If the ++ * "broken-cd" property is provided, the MMC_CAP_NEEDS_POLL capability ++ * is set. If the "non-removable" property is found, the ++ * MMC_CAP_NONREMOVABLE capability is set and no card-detection ++ * configuration is performed. ++ */ ++ ++ /* Parse Card Detection */ ++ if (of_find_property(np, "non-removable", &len)) { ++ host->caps |= MMC_CAP_NONREMOVABLE; ++ } else { ++ bool explicit_inv_cd, gpio_inv_cd = false; ++ ++ explicit_inv_cd = of_property_read_bool(np, "cd-inverted"); ++ ++ if (of_find_property(np, "broken-cd", &len)) ++ host->caps |= MMC_CAP_NEEDS_POLL; ++ ++ gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &flags); ++ if (gpio_is_valid(gpio)) { ++ if (!(flags & OF_GPIO_ACTIVE_LOW)) ++ gpio_inv_cd = true; ++ ++ ret = mmc_gpio_request_cd(host, gpio); ++ if (ret < 0) { ++ dev_err(host->parent, ++ "Failed to request CD GPIO #%d: %d!\n", ++ gpio, ret); ++ return ret; ++ } else { ++ dev_info(host->parent, "Got CD GPIO #%d.\n", ++ gpio); ++ } ++ } ++ ++ if (explicit_inv_cd ^ gpio_inv_cd) ++ host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; ++ } ++ ++ /* Parse Write Protection */ ++ explicit_inv_wp = of_property_read_bool(np, "wp-inverted"); ++ ++ gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags); ++ if (gpio_is_valid(gpio)) { ++ if (!(flags & OF_GPIO_ACTIVE_LOW)) ++ gpio_inv_wp = true; ++ ++ ret = mmc_gpio_request_ro(host, gpio); ++ if (ret < 0) { ++ dev_err(host->parent, ++ "Failed to request WP GPIO: %d!\n", ret); ++ goto out; ++ } else { ++ dev_info(host->parent, "Got WP GPIO #%d.\n", ++ gpio); ++ } ++ } ++ if (explicit_inv_wp ^ gpio_inv_wp) ++ host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; ++ ++ if (of_find_property(np, "cap-sd-highspeed", &len)) ++ host->caps |= MMC_CAP_SD_HIGHSPEED; ++ if (of_find_property(np, "cap-mmc-highspeed", &len)) ++ host->caps |= MMC_CAP_MMC_HIGHSPEED; ++ if (of_find_property(np, "sd-uhs-sdr12", &len)) ++ host->caps |= MMC_CAP_UHS_SDR12; ++ if (of_find_property(np, "sd-uhs-sdr25", &len)) ++ host->caps |= MMC_CAP_UHS_SDR25; ++ if (of_find_property(np, "sd-uhs-sdr50", &len)) ++ host->caps |= MMC_CAP_UHS_SDR50; ++ if (of_find_property(np, "sd-uhs-sdr104", &len)) ++ host->caps |= MMC_CAP_UHS_SDR104; ++ if (of_find_property(np, "sd-uhs-ddr50", &len)) ++ host->caps |= MMC_CAP_UHS_DDR50; ++ if (of_find_property(np, "cap-power-off-card", &len)) ++ host->caps |= MMC_CAP_POWER_OFF_CARD; ++ if (of_find_property(np, "cap-sdio-irq", &len)) ++ host->caps |= MMC_CAP_SDIO_IRQ; ++ if (of_find_property(np, "full-pwr-cycle", &len)) ++ host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE; ++ if (of_find_property(np, "keep-power-in-suspend", &len)) ++ host->pm_caps |= MMC_PM_KEEP_POWER; ++ if (of_find_property(np, "enable-sdio-wakeup", &len)) ++ host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; ++ if (of_find_property(np, "mmc-ddr-1_8v", &len)) ++ host->caps |= MMC_CAP_1_8V_DDR; ++ if (of_find_property(np, "mmc-ddr-1_2v", &len)) ++ host->caps |= MMC_CAP_1_2V_DDR; ++ if (of_find_property(np, "mmc-hs200-1_8v", &len)) ++ host->caps2 |= MMC_CAP2_HS200_1_8V_SDR; ++ if (of_find_property(np, "mmc-hs200-1_2v", &len)) ++ host->caps2 |= MMC_CAP2_HS200_1_2V_SDR; ++ if (of_find_property(np, "mmc-hs400-1_8v", &len)) ++ host->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR; ++ if (of_find_property(np, "mmc-hs400-1_2v", &len)) ++ host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR; ++ ++ return 0; ++ ++out: ++ mmc_gpio_free_cd(host); ++ return ret; ++} ++ ++EXPORT_SYMBOL(mmc_of_parse); ++ ++/** + * mmc_alloc_host - initialise the per-host structure. + * @extra: sizeof private data structure + * @dev: pointer to host device model structure +@@ -268,6 +474,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) + if (!host) + return NULL; + ++ /* scanning will be enabled when we're ready */ ++ host->rescan_disable = 1; + spin_lock(&mmc_host_lock); + err = idr_get_new(&mmc_host_idr, host, &host->index); + spin_unlock(&mmc_host_lock); +@@ -283,10 +491,12 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) + + mmc_host_clk_init(host); + ++ mutex_init(&host->slot.lock); ++ host->slot.cd_irq = -EINVAL; ++ + spin_lock_init(&host->lock); + init_waitqueue_head(&host->wq); + INIT_DELAYED_WORK(&host->detect, mmc_rescan); +- INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable); + #ifdef CONFIG_PM + host->pm_notify.notifier_call = mmc_pm_notify; + #endif +@@ -335,6 +545,7 @@ int mmc_add_host(struct mmc_host *host) + #ifdef CONFIG_DEBUG_FS + mmc_add_host_debugfs(host); + #endif ++ mmc_host_clk_sysfs_init(host); + + mmc_start_host(host); + register_pm_notifier(&host->pm_notify); +diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h +index fb8a5cd..f2ab9e5 100644 +--- a/drivers/mmc/core/host.h ++++ b/drivers/mmc/core/host.h +@@ -15,27 +15,5 @@ + int mmc_register_host_class(void); + void mmc_unregister_host_class(void); + +-#ifdef CONFIG_MMC_CLKGATE +-void mmc_host_clk_hold(struct mmc_host *host); +-void mmc_host_clk_release(struct mmc_host *host); +-unsigned int mmc_host_clk_rate(struct mmc_host *host); +- +-#else +-static inline void mmc_host_clk_hold(struct mmc_host *host) +-{ +-} +- +-static inline void mmc_host_clk_release(struct mmc_host *host) +-{ +-} +- +-static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) +-{ +- return host->ios.clock; +-} +-#endif +- +-void mmc_host_deeper_disable(struct work_struct *work); +- + #endif + +diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c +index c1aec06..c12e247 100644 +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -96,6 +97,7 @@ static int mmc_decode_cid(struct mmc_card *card) + card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); + card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); + card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); ++ card->cid.prv = UNSTUFF_BITS(resp, 48, 8); + card->cid.serial = UNSTUFF_BITS(resp, 16, 32); + card->cid.month = UNSTUFF_BITS(resp, 12, 4); + card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; +@@ -235,6 +237,67 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) + return err; + } + ++static void mmc_select_card_type(struct mmc_card *card) ++{ ++ struct mmc_host *host = card->host; ++ u8 card_type = card->ext_csd.raw_card_type; ++ u32 caps = host->caps, caps2 = host->caps2; ++ unsigned int hs_max_dtr = 0, hs200_max_dtr = 0; ++ unsigned int avail_type = 0; ++ ++ if (caps & MMC_CAP_MMC_HIGHSPEED && ++ card_type & EXT_CSD_CARD_TYPE_HS_26) { ++ hs_max_dtr = MMC_HIGH_26_MAX_DTR; ++ avail_type |= EXT_CSD_CARD_TYPE_HS_26; ++ } ++ ++ if (caps & MMC_CAP_MMC_HIGHSPEED && ++ card_type & EXT_CSD_CARD_TYPE_HS_52) { ++ hs_max_dtr = MMC_HIGH_52_MAX_DTR; ++ avail_type |= EXT_CSD_CARD_TYPE_HS_52; ++ } ++ ++ if (caps & MMC_CAP_1_8V_DDR && ++ card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) { ++ hs_max_dtr = MMC_HIGH_DDR_MAX_DTR; ++ avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V; ++ } ++ ++ if (caps & MMC_CAP_1_2V_DDR && ++ card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) { ++ hs_max_dtr = MMC_HIGH_DDR_MAX_DTR; ++ avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V; ++ } ++ ++ if (caps2 & MMC_CAP2_HS200_1_8V_SDR && ++ card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) { ++ hs200_max_dtr = MMC_HS200_MAX_DTR; ++ avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V; ++ } ++ ++ if (caps2 & MMC_CAP2_HS200_1_2V_SDR && ++ card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) { ++ hs200_max_dtr = MMC_HS200_MAX_DTR; ++ avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V; ++ } ++ ++ if (caps2 & MMC_CAP2_HS400_1_8V && ++ card_type & EXT_CSD_CARD_TYPE_HS400_1_8V) { ++ hs200_max_dtr = MMC_HS200_MAX_DTR; ++ avail_type |= EXT_CSD_CARD_TYPE_HS400_1_8V; ++ } ++ ++ if (caps2 & MMC_CAP2_HS400_1_2V && ++ card_type & EXT_CSD_CARD_TYPE_HS400_1_2V) { ++ hs200_max_dtr = MMC_HS200_MAX_DTR; ++ avail_type |= EXT_CSD_CARD_TYPE_HS400_1_2V; ++ } ++ ++ card->ext_csd.hs_max_dtr = hs_max_dtr; ++ card->ext_csd.hs200_max_dtr = hs200_max_dtr; ++ card->mmc_avail_type = avail_type; ++} ++ + /* + * Decode extended CSD. + */ +@@ -262,7 +325,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) + } + + card->ext_csd.rev = ext_csd[EXT_CSD_REV]; +- if (card->ext_csd.rev > 6) { ++ if (card->ext_csd.rev > 7) { + pr_err("%s: unrecognised EXT_CSD revision %d\n", + mmc_hostname(card->host), card->ext_csd.rev); + err = -EINVAL; +@@ -284,35 +347,9 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) + if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512) + mmc_card_set_blockaddr(card); + } ++ + card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; +- switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { +- case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | +- EXT_CSD_CARD_TYPE_26: +- card->ext_csd.hs_max_dtr = 52000000; +- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; +- break; +- case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | +- EXT_CSD_CARD_TYPE_26: +- card->ext_csd.hs_max_dtr = 52000000; +- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; +- break; +- case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | +- EXT_CSD_CARD_TYPE_26: +- card->ext_csd.hs_max_dtr = 52000000; +- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; +- break; +- case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: +- card->ext_csd.hs_max_dtr = 52000000; +- break; +- case EXT_CSD_CARD_TYPE_26: +- card->ext_csd.hs_max_dtr = 26000000; +- break; +- default: +- /* MMC v4 spec says this cannot happen */ +- pr_warning("%s: card is mmc v4 but doesn't " +- "support any high-speed modes.\n", +- mmc_hostname(card->host)); +- } ++ mmc_select_card_type(card); + + card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT]; + card->ext_csd.raw_erase_timeout_mult = +@@ -348,13 +385,14 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) + part_size = ext_csd[EXT_CSD_BOOT_MULT] << 17; + mmc_part_add(card, part_size, + EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx, +- "boot%d", idx, true); ++ "boot%d", idx, true, ++ MMC_BLK_DATA_AREA_BOOT); + } + } + } + + card->ext_csd.raw_hc_erase_gap_size = +- ext_csd[EXT_CSD_PARTITION_ATTRIBUTE]; ++ ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; + card->ext_csd.raw_sec_trim_mult = + ext_csd[EXT_CSD_SEC_TRIM_MULT]; + card->ext_csd.raw_sec_erase_mult = +@@ -435,7 +473,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) + hc_wp_grp_sz); + mmc_part_add(card, part_size << 19, + EXT_CSD_PART_CONFIG_ACC_GP0 + idx, +- "gp%d", idx, false); ++ "gp%d", idx, false, ++ MMC_BLK_DATA_AREA_GP); + } + } + card->ext_csd.sec_trim_mult = +@@ -446,9 +485,52 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) + ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; + card->ext_csd.trim_timeout = 300 * + ext_csd[EXT_CSD_TRIM_MULT]; ++ ++ /* ++ * Note that the call to mmc_part_add above defaults to read ++ * only. If this default assumption is changed, the call must ++ * take into account the value of boot_locked below. ++ */ ++ card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP]; ++ card->ext_csd.boot_ro_lockable = true; ++ ++ /* Save power class values */ ++ card->ext_csd.raw_pwr_cl_52_195 = ++ ext_csd[EXT_CSD_PWR_CL_52_195]; ++ card->ext_csd.raw_pwr_cl_26_195 = ++ ext_csd[EXT_CSD_PWR_CL_26_195]; ++ card->ext_csd.raw_pwr_cl_52_360 = ++ ext_csd[EXT_CSD_PWR_CL_52_360]; ++ card->ext_csd.raw_pwr_cl_26_360 = ++ ext_csd[EXT_CSD_PWR_CL_26_360]; ++ card->ext_csd.raw_pwr_cl_200_195 = ++ ext_csd[EXT_CSD_PWR_CL_200_195]; ++ card->ext_csd.raw_pwr_cl_200_360 = ++ ext_csd[EXT_CSD_PWR_CL_200_360]; ++ card->ext_csd.raw_pwr_cl_ddr_52_195 = ++ ext_csd[EXT_CSD_PWR_CL_DDR_52_195]; ++ card->ext_csd.raw_pwr_cl_ddr_52_360 = ++ ext_csd[EXT_CSD_PWR_CL_DDR_52_360]; ++ card->ext_csd.raw_pwr_cl_ddr_200_360 = ++ ext_csd[EXT_CSD_PWR_CL_DDR_200_360]; + } + + if (card->ext_csd.rev >= 5) { ++ /* Adjust production date as per JEDEC JESD84-B451 */ ++ if (card->cid.year < 2010) ++ card->cid.year += 16; ++ ++ /* check whether the eMMC card supports BKOPS */ ++ if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { ++ card->ext_csd.bkops = 1; ++ card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN]; ++ card->ext_csd.raw_bkops_status = ++ ext_csd[EXT_CSD_BKOPS_STATUS]; ++ if (!card->ext_csd.bkops_en) ++ pr_info("%s: BKOPS_EN bit is not set\n", ++ mmc_hostname(card->host)); ++ } ++ + /* check whether the eMMC card supports HPI */ + if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) { + card->ext_csd.hpi = 1; +@@ -466,6 +548,17 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) + + card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM]; + card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION]; ++ ++ /* ++ * RPMB regions are defined in multiples of 128K. ++ */ ++ card->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT]; ++ if (ext_csd[EXT_CSD_RPMB_MULT] && mmc_host_cmd23(card->host)) { ++ mmc_part_add(card, ext_csd[EXT_CSD_RPMB_MULT] << 17, ++ EXT_CSD_PART_CONFIG_ACC_RPMB, ++ "rpmb", 0, false, ++ MMC_BLK_DATA_AREA_RPMB); ++ } + } + + card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT]; +@@ -488,6 +581,27 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) + ext_csd[EXT_CSD_CACHE_SIZE + 1] << 8 | + ext_csd[EXT_CSD_CACHE_SIZE + 2] << 16 | + ext_csd[EXT_CSD_CACHE_SIZE + 3] << 24; ++ ++ if (ext_csd[EXT_CSD_DATA_SECTOR_SIZE] == 1) ++ card->ext_csd.data_sector_size = 4096; ++ else ++ card->ext_csd.data_sector_size = 512; ++ ++ if ((ext_csd[EXT_CSD_DATA_TAG_SUPPORT] & 1) && ++ (ext_csd[EXT_CSD_TAG_UNIT_SIZE] <= 8)) { ++ card->ext_csd.data_tag_unit_size = ++ ((unsigned int) 1 << ext_csd[EXT_CSD_TAG_UNIT_SIZE]) * ++ (card->ext_csd.data_sector_size); ++ } else { ++ card->ext_csd.data_tag_unit_size = 0; ++ } ++ ++ card->ext_csd.max_packed_writes = ++ ext_csd[EXT_CSD_MAX_PACKED_WRITES]; ++ card->ext_csd.max_packed_reads = ++ ext_csd[EXT_CSD_MAX_PACKED_READS]; ++ } else { ++ card->ext_csd.data_sector_size = 512; + } + + out: +@@ -511,16 +625,12 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width) + err = mmc_get_ext_csd(card, &bw_ext_csd); + + if (err || bw_ext_csd == NULL) { +- if (bus_width != MMC_BUS_WIDTH_1) +- err = -EINVAL; ++ err = -EINVAL; + goto out; + } + +- if (bus_width == MMC_BUS_WIDTH_1) +- goto out; +- + /* only compare read only fields */ +- err = (!(card->ext_csd.raw_partition_support == ++ err = !((card->ext_csd.raw_partition_support == + bw_ext_csd[EXT_CSD_PARTITION_SUPPORT]) && + (card->ext_csd.raw_erased_mem_count == + bw_ext_csd[EXT_CSD_ERASED_MEM_CONT]) && +@@ -553,7 +663,26 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width) + (card->ext_csd.raw_sectors[2] == + bw_ext_csd[EXT_CSD_SEC_CNT + 2]) && + (card->ext_csd.raw_sectors[3] == +- bw_ext_csd[EXT_CSD_SEC_CNT + 3])); ++ bw_ext_csd[EXT_CSD_SEC_CNT + 3]) && ++ (card->ext_csd.raw_pwr_cl_52_195 == ++ bw_ext_csd[EXT_CSD_PWR_CL_52_195]) && ++ (card->ext_csd.raw_pwr_cl_26_195 == ++ bw_ext_csd[EXT_CSD_PWR_CL_26_195]) && ++ (card->ext_csd.raw_pwr_cl_52_360 == ++ bw_ext_csd[EXT_CSD_PWR_CL_52_360]) && ++ (card->ext_csd.raw_pwr_cl_26_360 == ++ bw_ext_csd[EXT_CSD_PWR_CL_26_360]) && ++ (card->ext_csd.raw_pwr_cl_200_195 == ++ bw_ext_csd[EXT_CSD_PWR_CL_200_195]) && ++ (card->ext_csd.raw_pwr_cl_200_360 == ++ bw_ext_csd[EXT_CSD_PWR_CL_200_360]) && ++ (card->ext_csd.raw_pwr_cl_ddr_52_195 == ++ bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) && ++ (card->ext_csd.raw_pwr_cl_ddr_52_360 == ++ bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]) && ++ (card->ext_csd.raw_pwr_cl_ddr_200_360 == ++ bw_ext_csd[EXT_CSD_PWR_CL_DDR_200_360])); ++ + if (err) + err = -EINVAL; + +@@ -574,10 +703,13 @@ MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); + MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); + MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); + MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); ++MMC_DEV_ATTR(prv, "0x%x\n", card->cid.prv); + MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); + MMC_DEV_ATTR(enhanced_area_offset, "%llu\n", + card->ext_csd.enhanced_area_offset); + MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size); ++MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult); ++MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors); + + static struct attribute *mmc_std_attrs[] = { + &dev_attr_cid.attr, +@@ -590,9 +722,12 @@ static struct attribute *mmc_std_attrs[] = { + &dev_attr_manfid.attr, + &dev_attr_name.attr, + &dev_attr_oemid.attr, ++ &dev_attr_prv.attr, + &dev_attr_serial.attr, + &dev_attr_enhanced_area_offset.attr, + &dev_attr_enhanced_area_size.attr, ++ &dev_attr_raw_rpmb_size_mult.attr, ++ &dev_attr_rel_sectors.attr, + NULL, + }; + +@@ -615,21 +750,13 @@ static struct device_type mmc_type = { + * extended CSD register, select it by executing the + * mmc_switch command. + */ +-static int mmc_select_powerclass(struct mmc_card *card, +- unsigned int bus_width, u8 *ext_csd) ++static int __mmc_select_powerclass(struct mmc_card *card, ++ unsigned int bus_width) + { ++ struct mmc_host *host = card->host; ++ struct mmc_ext_csd *ext_csd = &card->ext_csd; ++ unsigned int pwrclass_val = 0; + int err = 0; +- unsigned int pwrclass_val; +- unsigned int index = 0; +- struct mmc_host *host; +- +- BUG_ON(!card); +- +- host = card->host; +- BUG_ON(!host); +- +- if (ext_csd == NULL) +- return 0; + + /* Power class selection is supported for versions >= 4.0 */ + if (card->csd.mmca_vsn < CSD_SPEC_VER_4) +@@ -641,27 +768,34 @@ static int mmc_select_powerclass(struct mmc_card *card, + + switch (1 << host->ios.vdd) { + case MMC_VDD_165_195: +- if (host->ios.clock <= 26000000) +- index = EXT_CSD_PWR_CL_26_195; +- else if (host->ios.clock <= 52000000) +- index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? +- EXT_CSD_PWR_CL_52_195 : +- EXT_CSD_PWR_CL_DDR_52_195; +- else if (host->ios.clock <= 200000000) +- index = EXT_CSD_PWR_CL_200_195; ++ if (host->ios.clock <= MMC_HIGH_26_MAX_DTR) ++ pwrclass_val = ext_csd->raw_pwr_cl_26_195; ++ else if (host->ios.clock <= MMC_HIGH_52_MAX_DTR) ++ pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? ++ ext_csd->raw_pwr_cl_52_195 : ++ ext_csd->raw_pwr_cl_ddr_52_195; ++ else if (host->ios.clock <= MMC_HS200_MAX_DTR) ++ pwrclass_val = ext_csd->raw_pwr_cl_200_195; + break; ++ case MMC_VDD_27_28: ++ case MMC_VDD_28_29: ++ case MMC_VDD_29_30: ++ case MMC_VDD_30_31: ++ case MMC_VDD_31_32: + case MMC_VDD_32_33: + case MMC_VDD_33_34: + case MMC_VDD_34_35: + case MMC_VDD_35_36: +- if (host->ios.clock <= 26000000) +- index = EXT_CSD_PWR_CL_26_360; +- else if (host->ios.clock <= 52000000) +- index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? +- EXT_CSD_PWR_CL_52_360 : +- EXT_CSD_PWR_CL_DDR_52_360; +- else if (host->ios.clock <= 200000000) +- index = EXT_CSD_PWR_CL_200_360; ++ if (host->ios.clock <= MMC_HIGH_26_MAX_DTR) ++ pwrclass_val = ext_csd->raw_pwr_cl_26_360; ++ else if (host->ios.clock <= MMC_HIGH_52_MAX_DTR) ++ pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? ++ ext_csd->raw_pwr_cl_52_360 : ++ ext_csd->raw_pwr_cl_ddr_52_360; ++ else if (host->ios.clock <= MMC_HS200_MAX_DTR) ++ pwrclass_val = (bus_width == EXT_CSD_DDR_BUS_WIDTH_8) ? ++ ext_csd->raw_pwr_cl_ddr_200_360 : ++ ext_csd->raw_pwr_cl_200_360; + break; + default: + pr_warning("%s: Voltage range not supported " +@@ -669,8 +803,6 @@ static int mmc_select_powerclass(struct mmc_card *card, + return -EINVAL; + } + +- pwrclass_val = ext_csd[index]; +- + if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8)) + pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >> + EXT_CSD_PWR_CL_8BIT_SHIFT; +@@ -689,6 +821,360 @@ static int mmc_select_powerclass(struct mmc_card *card, + return err; + } + ++static int mmc_select_powerclass(struct mmc_card *card) ++{ ++ struct mmc_host *host = card->host; ++ u32 bus_width, ext_csd_bits; ++ int err, ddr; ++ ++ /* Power class selection is supported for versions >= 4.0 */ ++ if (card->csd.mmca_vsn < CSD_SPEC_VER_4) ++ return 0; ++ ++ bus_width = host->ios.bus_width; ++ /* Power class values are defined only for 4/8 bit bus */ ++ if (bus_width == MMC_BUS_WIDTH_1) ++ return 0; ++ ++ ddr = card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52; ++ if (ddr) ++ ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? ++ EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4; ++ else ++ ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? ++ EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; ++ ++ err = __mmc_select_powerclass(card, ext_csd_bits); ++ if (err) ++ pr_warn("%s: power class selection to bus width %d ddr %d failed\n", ++ mmc_hostname(host), 1 << bus_width, ddr); ++ ++ return err; ++} ++ ++/* ++ * Set the bus speed for the selected speed mode. ++ */ ++static void mmc_set_bus_speed(struct mmc_card *card) ++{ ++ unsigned int max_dtr = (unsigned int)-1; ++ ++ if ((mmc_card_hs200(card) || mmc_card_hs400(card)) && ++ max_dtr > card->ext_csd.hs200_max_dtr) ++ max_dtr = card->ext_csd.hs200_max_dtr; ++ else if (mmc_card_hs(card) && max_dtr > card->ext_csd.hs_max_dtr) ++ max_dtr = card->ext_csd.hs_max_dtr; ++ else if (max_dtr > card->csd.max_dtr) ++ max_dtr = card->csd.max_dtr; ++ ++ mmc_set_clock(card->host, max_dtr); ++} ++ ++/* ++ * Select the bus width amoung 4-bit and 8-bit(SDR). ++ * If the bus width is changed successfully, return the selected width value. ++ * Zero is returned instead of error value if the wide width is not supported. ++ */ ++static int mmc_select_bus_width(struct mmc_card *card) ++{ ++ static unsigned ext_csd_bits[] = { ++ EXT_CSD_BUS_WIDTH_8, ++ EXT_CSD_BUS_WIDTH_4, ++ }; ++ static unsigned bus_widths[] = { ++ MMC_BUS_WIDTH_8, ++ MMC_BUS_WIDTH_4, ++ }; ++ struct mmc_host *host = card->host; ++ unsigned idx, bus_width = 0; ++ int err = 0; ++ ++ if ((card->csd.mmca_vsn < CSD_SPEC_VER_4) && ++ !(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) ++ return 0; ++ ++ idx = (host->caps & MMC_CAP_8_BIT_DATA) ? 0 : 1; ++ ++ /* ++ * Unlike SD, MMC cards dont have a configuration register to notify ++ * supported bus width. So bus test command should be run to identify ++ * the supported bus width or compare the ext csd values of current ++ * bus width and ext csd values of 1 bit mode read earlier. ++ */ ++ for (; idx < ARRAY_SIZE(bus_widths); idx++) { ++ /* ++ * Host is capable of 8bit transfer, then switch ++ * the device to work in 8bit transfer mode. If the ++ * mmc switch command returns error then switch to ++ * 4bit transfer mode. On success set the corresponding ++ * bus width on the host. ++ */ ++ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, ++ EXT_CSD_BUS_WIDTH, ++ ext_csd_bits[idx], ++ card->ext_csd.generic_cmd6_time); ++ if (err) ++ continue; ++ ++ bus_width = bus_widths[idx]; ++ mmc_set_bus_width(host, bus_width); ++ ++ /* ++ * If controller can't handle bus width test, ++ * compare ext_csd previously read in 1 bit mode ++ * against ext_csd at new bus width ++ */ ++ if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST)) ++ err = mmc_compare_ext_csds(card, bus_width); ++ else ++ err = mmc_bus_test(card, bus_width); ++ ++ if (!err) { ++ err = bus_width; ++ break; ++ } else { ++ pr_warn("%s: switch to bus width %d failed\n", ++ mmc_hostname(host), ext_csd_bits[idx]); ++ } ++ } ++ ++ return err; ++} ++ ++/* ++ * Switch to the high-speed mode ++ */ ++static int mmc_select_hs(struct mmc_card *card) ++{ ++ int err; ++ ++ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, ++ EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, ++ card->ext_csd.generic_cmd6_time, ++ true, true, true); ++ if (!err) ++ mmc_set_timing(card->host, MMC_TIMING_MMC_HS); ++ ++ return err; ++} ++ ++/* ++ * Activate wide bus and DDR if supported. ++ */ ++static int mmc_select_hs_ddr(struct mmc_card *card) ++{ ++ struct mmc_host *host = card->host; ++ u32 bus_width, ext_csd_bits; ++ int err = 0; ++ ++ if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52)) ++ return 0; ++ ++ bus_width = host->ios.bus_width; ++ if (bus_width == MMC_BUS_WIDTH_1) ++ return 0; ++ ++ ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? ++ EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4; ++ ++ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, ++ EXT_CSD_BUS_WIDTH, ++ ext_csd_bits, ++ card->ext_csd.generic_cmd6_time); ++ if (err) { ++ pr_warn("%s: switch to bus width %d ddr failed\n", ++ mmc_hostname(host), 1 << bus_width); ++ return err; ++ } ++ ++ /* ++ * eMMC cards can support 3.3V to 1.2V i/o (vccq) ++ * signaling. ++ * ++ * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq. ++ * ++ * 1.8V vccq at 3.3V core voltage (vcc) is not required ++ * in the JEDEC spec for DDR. ++ * ++ * Do not force change in vccq since we are obviously ++ * working and no change to vccq is needed. ++ * ++ * WARNING: eMMC rules are NOT the same as SD DDR ++ */ ++ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_1_2V) { ++ err = __mmc_set_signal_voltage(host, ++ MMC_SIGNAL_VOLTAGE_120); ++ if (err) ++ return err; ++ } ++ ++ mmc_set_timing(host, MMC_TIMING_MMC_DDR52); ++ ++ return err; ++} ++ ++static int mmc_select_hs400(struct mmc_card *card) ++{ ++ struct mmc_host *host = card->host; ++ int err = 0; ++ ++ /* ++ * HS400 mode requires 8-bit bus width ++ */ ++ if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && ++ host->ios.bus_width == MMC_BUS_WIDTH_8)) ++ return 0; ++ ++ /* ++ * Before switching to dual data rate operation for HS400, ++ * it is required to convert from HS200 mode to HS mode. ++ */ ++ mmc_set_timing(card->host, MMC_TIMING_MMC_HS); ++ mmc_set_bus_speed(card); ++ ++ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, ++ EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, ++ card->ext_csd.generic_cmd6_time, ++ true, true, true); ++ if (err) { ++ pr_warn("%s: switch to high-speed from hs200 failed, err:%d\n", ++ mmc_hostname(host), err); ++ return err; ++ } ++ ++ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, ++ EXT_CSD_BUS_WIDTH, ++ EXT_CSD_DDR_BUS_WIDTH_8, ++ card->ext_csd.generic_cmd6_time); ++ if (err) { ++ pr_warn("%s: switch to bus width for hs400 failed, err:%d\n", ++ mmc_hostname(host), err); ++ return err; ++ } ++ ++ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, ++ EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400, ++ card->ext_csd.generic_cmd6_time, ++ true, true, true); ++ if (err) { ++ pr_warn("%s: switch to hs400 failed, err:%d\n", ++ mmc_hostname(host), err); ++ return err; ++ } ++ ++ mmc_set_timing(host, MMC_TIMING_MMC_HS400); ++ mmc_set_bus_speed(card); ++ ++ return 0; ++} ++ ++/* ++ * For device supporting HS200 mode, the following sequence ++ * should be done before executing the tuning process. ++ * 1. set the desired bus width(4-bit or 8-bit, 1-bit is not supported) ++ * 2. switch to HS200 mode ++ * 3. set the clock to > 52Mhz and <=200MHz ++ */ ++static int mmc_select_hs200(struct mmc_card *card) ++{ ++ struct mmc_host *host = card->host; ++ int err = -EINVAL; ++ ++ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V) ++ err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); ++ ++ if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V) ++ err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); ++ ++ /* If fails try again during next card power cycle */ ++ if (err) ++ goto err; ++ ++ /* ++ * Set the bus width(4 or 8) with host's support and ++ * switch to HS200 mode if bus width is set successfully. ++ */ ++ err = mmc_select_bus_width(card); ++ if (!IS_ERR_VALUE(err)) { ++ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, ++ EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200, ++ card->ext_csd.generic_cmd6_time, ++ true, true, true); ++ if (!err) ++ mmc_set_timing(host, MMC_TIMING_MMC_HS200); ++ } ++err: ++ return err; ++} ++ ++/* ++ * Activate High Speed or HS200 mode if supported. ++ */ ++static int mmc_select_timing(struct mmc_card *card) ++{ ++ int err = 0; ++ ++ if ((card->csd.mmca_vsn < CSD_SPEC_VER_4 && ++ card->ext_csd.hs_max_dtr == 0)) ++ goto bus_speed; ++ ++ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200) ++ err = mmc_select_hs200(card); ++ else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) ++ err = mmc_select_hs(card); ++ ++ if (err && err != -EBADMSG) ++ return err; ++ ++ if (err) { ++ pr_warn("%s: switch to %s failed\n", ++ mmc_card_hs(card) ? "high-speed" : ++ (mmc_card_hs200(card) ? "hs200" : ""), ++ mmc_hostname(card->host)); ++ err = 0; ++ } ++ ++bus_speed: ++ /* ++ * Set the bus speed to the selected bus timing. ++ * If timing is not selected, backward compatible is the default. ++ */ ++ mmc_set_bus_speed(card); ++ return err; ++} ++ ++/* ++ * Execute tuning sequence to seek the proper bus operating ++ * conditions for HS200 and HS400, which sends CMD21 to the device. ++ */ ++static int mmc_hs200_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_TUNING_BLOCK_HS200); ++ 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. + * +@@ -699,9 +1185,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, + struct mmc_card *oldcard) + { + struct mmc_card *card; +- int err, ddr = 0; ++ int err; + u32 cid[4]; +- unsigned int max_dtr; + u32 rocr; + u8 *ext_csd = NULL; + +@@ -762,6 +1247,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, + goto err; + } + ++ card->ocr = ocr; + card->type = MMC_TYPE_MMC; + card->rca = 1; + memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); +@@ -831,7 +1317,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, + * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF + * bit. This bit will be lost every time after a reset or power off. + */ +- if (card->ext_csd.enhanced_area_en) { ++ if (card->ext_csd.enhanced_area_en || ++ (card->ext_csd.rev >= 3 && (host->caps2 & MMC_CAP2_HC_ERASE_SZ))) { + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_ERASE_GROUP_DEF, 1, + card->ext_csd.generic_cmd6_time); +@@ -872,11 +1359,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, + } + + /* +- * If the host supports the power_off_notify capability then +- * set the notification byte in the ext_csd register of device ++ * Enable power_off_notification byte in the ext_csd register + */ +- if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) && +- (card->ext_csd.rev >= 6)) { ++ if (card->ext_csd.rev >= 6) { + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_POWER_OFF_NOTIFICATION, + EXT_CSD_POWER_ON, +@@ -889,36 +1374,46 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, + * so check for success and update the flag + */ + if (!err) +- card->poweroff_notify_state = MMC_POWERED_ON; ++ card->ext_csd.power_off_notification = EXT_CSD_POWER_ON; + } + + /* +- * Activate high speed (if supported) ++ * Select timing interface + */ +- if ((card->ext_csd.hs_max_dtr != 0) && +- (host->caps & MMC_CAP_MMC_HIGHSPEED)) { +- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +- EXT_CSD_HS_TIMING, 1, +- card->ext_csd.generic_cmd6_time); +- if (err && err != -EBADMSG) +- goto free_card; ++ err = mmc_select_timing(card); ++ if (err) ++ goto free_card; + +- if (err) { +- pr_warning("%s: switch to highspeed failed\n", +- mmc_hostname(card->host)); +- err = 0; +- } else { +- mmc_card_set_highspeed(card); +- mmc_set_timing(card->host, MMC_TIMING_MMC_HS); ++ if (mmc_card_hs200(card)) { ++ err = mmc_hs200_tuning(card); ++ if (err) ++ goto err; ++ ++ err = mmc_select_hs400(card); ++ if (err) ++ goto err; ++ } else if (mmc_card_hs(card)) { ++ /* Select the desired bus width optionally */ ++ err = mmc_select_bus_width(card); ++ if (!IS_ERR_VALUE(err)) { ++ err = mmc_select_hs_ddr(card); ++ if (err) ++ goto err; + } + } + + /* ++ * Choose the power class with selected bus interface ++ */ ++ mmc_select_powerclass(card); ++ ++ /* + * Enable HPI feature (if supported) + */ + if (card->ext_csd.hpi) { + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +- EXT_CSD_HPI_MGMT, 1, 0); ++ EXT_CSD_HPI_MGMT, 1, ++ card->ext_csd.generic_cmd6_time); + if (err && err != -EBADMSG) + goto free_card; + if (err) { +@@ -930,151 +1425,51 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, + } + + /* +- * Compute bus speed. +- */ +- max_dtr = (unsigned int)-1; +- +- if (mmc_card_highspeed(card)) { +- if (max_dtr > card->ext_csd.hs_max_dtr) +- max_dtr = card->ext_csd.hs_max_dtr; +- } else if (max_dtr > card->csd.max_dtr) { +- max_dtr = card->csd.max_dtr; +- } +- +- mmc_set_clock(host, max_dtr); +- +- /* +- * Indicate DDR mode (if supported). +- */ +- if (mmc_card_highspeed(card)) { +- if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) +- && ((host->caps & (MMC_CAP_1_8V_DDR | +- MMC_CAP_UHS_DDR50)) +- == (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50))) +- ddr = MMC_1_8V_DDR_MODE; +- else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) +- && ((host->caps & (MMC_CAP_1_2V_DDR | +- MMC_CAP_UHS_DDR50)) +- == (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50))) +- ddr = MMC_1_2V_DDR_MODE; +- } +- +- /* +- * Activate wide bus and DDR (if supported). ++ * If cache size is higher than 0, this indicates ++ * the existence of cache and it can be turned on. + */ +- if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && +- (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { +- static unsigned ext_csd_bits[][2] = { +- { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 }, +- { EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 }, +- { EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 }, +- }; +- static unsigned bus_widths[] = { +- MMC_BUS_WIDTH_8, +- MMC_BUS_WIDTH_4, +- MMC_BUS_WIDTH_1 +- }; +- unsigned idx, bus_width = 0; +- +- if (host->caps & MMC_CAP_8_BIT_DATA) +- idx = 0; +- else +- idx = 1; +- for (; idx < ARRAY_SIZE(bus_widths); idx++) { +- bus_width = bus_widths[idx]; +- if (bus_width == MMC_BUS_WIDTH_1) +- ddr = 0; /* no DDR for 1-bit width */ +- err = mmc_select_powerclass(card, ext_csd_bits[idx][0], +- ext_csd); +- if (err) +- pr_err("%s: power class selection to " +- "bus width %d failed\n", +- mmc_hostname(card->host), +- 1 << bus_width); +- +- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +- EXT_CSD_BUS_WIDTH, +- ext_csd_bits[idx][0], +- card->ext_csd.generic_cmd6_time); +- if (!err) { +- mmc_set_bus_width(card->host, bus_width); +- +- /* +- * If controller can't handle bus width test, +- * compare ext_csd previously read in 1 bit mode +- * against ext_csd at new bus width +- */ +- if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST)) +- err = mmc_compare_ext_csds(card, +- bus_width); +- else +- err = mmc_bus_test(card, bus_width); +- if (!err) +- break; +- } +- } ++ if (card->ext_csd.cache_size > 0) { ++ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, ++ EXT_CSD_CACHE_CTRL, 1, ++ card->ext_csd.generic_cmd6_time); ++ if (err && err != -EBADMSG) ++ goto free_card; + +- if (!err && ddr) { +- err = mmc_select_powerclass(card, ext_csd_bits[idx][1], +- ext_csd); +- if (err) +- pr_err("%s: power class selection to " +- "bus width %d ddr %d failed\n", +- mmc_hostname(card->host), +- 1 << bus_width, ddr); +- +- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +- EXT_CSD_BUS_WIDTH, +- ext_csd_bits[idx][1], +- card->ext_csd.generic_cmd6_time); +- } ++ /* ++ * Only if no error, cache is turned on successfully. ++ */ + if (err) { +- pr_warning("%s: switch to bus width %d ddr %d " +- "failed\n", mmc_hostname(card->host), +- 1 << bus_width, ddr); +- goto free_card; +- } else if (ddr) { +- /* +- * eMMC cards can support 3.3V to 1.2V i/o (vccq) +- * signaling. +- * +- * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq. +- * +- * 1.8V vccq at 3.3V core voltage (vcc) is not required +- * in the JEDEC spec for DDR. +- * +- * Do not force change in vccq since we are obviously +- * working and no change to vccq is needed. +- * +- * WARNING: eMMC rules are NOT the same as SD DDR +- */ +- if (ddr == MMC_1_2V_DDR_MODE) { +- err = mmc_set_signal_voltage(host, +- MMC_SIGNAL_VOLTAGE_120, 0); +- if (err) +- goto err; +- } +- mmc_card_set_ddr_mode(card); +- mmc_set_timing(card->host, MMC_TIMING_UHS_DDR50); +- mmc_set_bus_width(card->host, bus_width); ++ pr_warning("%s: Cache is supported, " ++ "but failed to turn on (%d)\n", ++ mmc_hostname(card->host), err); ++ card->ext_csd.cache_ctrl = 0; ++ err = 0; ++ } else { ++ card->ext_csd.cache_ctrl = 1; + } + } + + /* +- * If cache size is higher than 0, this indicates +- * the existence of cache and it can be turned on. ++ * The mandatory minimum values are defined for packed command. ++ * read: 5, write: 3 + */ +- if ((host->caps2 & MMC_CAP2_CACHE_CTRL) && +- card->ext_csd.cache_size > 0) { ++ if (card->ext_csd.max_packed_writes >= 3 && ++ card->ext_csd.max_packed_reads >= 5 && ++ host->caps2 & MMC_CAP2_PACKED_CMD) { + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, +- EXT_CSD_CACHE_CTRL, 1, 0); ++ EXT_CSD_EXP_EVENTS_CTRL, ++ EXT_CSD_PACKED_EVENT_EN, ++ card->ext_csd.generic_cmd6_time); + if (err && err != -EBADMSG) + goto free_card; +- +- /* +- * Only if no error, cache is turned on successfully. +- */ +- card->ext_csd.cache_ctrl = err ? 0 : 1; ++ if (err) { ++ pr_warn("%s: Enabling packed event failed\n", ++ mmc_hostname(card->host)); ++ card->ext_csd.packed_event_en = 0; ++ err = 0; ++ } else { ++ card->ext_csd.packed_event_en = 1; ++ } + } + + if (!oldcard) +@@ -1092,6 +1487,84 @@ err: + return err; + } + ++static int mmc_can_sleep(struct mmc_card *card) ++{ ++ return (card && card->ext_csd.rev >= 3); ++} ++ ++static int mmc_sleep(struct mmc_host *host) ++{ ++ struct mmc_command cmd = {0}; ++ struct mmc_card *card = host->card; ++ unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000); ++ int err; ++ ++ err = mmc_deselect_cards(host); ++ if (err) ++ return err; ++ ++ cmd.opcode = MMC_SLEEP_AWAKE; ++ cmd.arg = card->rca << 16; ++ cmd.arg |= 1 << 15; ++ ++ /* ++ * If the max_busy_timeout of the host is specified, validate it against ++ * the sleep cmd timeout. A failure means we need to prevent the host ++ * from doing hw busy detection, which is done by converting to a R1 ++ * response instead of a R1B. ++ */ ++ if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) { ++ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; ++ } else { ++ cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; ++ cmd.busy_timeout = timeout_ms; ++ } ++ ++ err = mmc_wait_for_cmd(host, &cmd, 0); ++ if (err) ++ return err; ++ ++ /* ++ * If the host does not wait while the card signals busy, then we will ++ * will have to wait the sleep/awake timeout. Note, we cannot use the ++ * SEND_STATUS command to poll the status because that command (and most ++ * others) is invalid while the card sleeps. ++ */ ++ if (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) ++ mmc_delay(timeout_ms); ++ ++ return err; ++} ++ ++static int mmc_can_poweroff_notify(const struct mmc_card *card) ++{ ++ return card && ++ mmc_card_mmc(card) && ++ (card->ext_csd.power_off_notification == EXT_CSD_POWER_ON); ++} ++ ++static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type) ++{ ++ unsigned int timeout = card->ext_csd.generic_cmd6_time; ++ int err; ++ ++ /* Use EXT_CSD_POWER_OFF_SHORT as default notification type. */ ++ if (notify_type == EXT_CSD_POWER_OFF_LONG) ++ timeout = card->ext_csd.power_off_longtime; ++ ++ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, ++ EXT_CSD_POWER_OFF_NOTIFICATION, ++ notify_type, timeout, true, false, false); ++ if (err) ++ pr_err("%s: Power Off Notification timed out, %u\n", ++ mmc_hostname(card->host), timeout); ++ ++ /* Disable the power off notification after the switch operation. */ ++ card->ext_csd.power_off_notification = EXT_CSD_NO_POWER_NOTIFICATION; ++ ++ return err; ++} ++ + /* + * Host is being removed. Free up the current card. + */ +@@ -1105,6 +1578,14 @@ static void mmc_remove(struct mmc_host *host) + } + + /* ++ * Card detection - card is alive. ++ */ ++static int mmc_alive(struct mmc_host *host) ++{ ++ return mmc_send_status(host->card, NULL); ++} ++ ++/* + * Card detection callback from host. + */ + static void mmc_detect(struct mmc_host *host) +@@ -1114,14 +1595,14 @@ static void mmc_detect(struct mmc_host *host) + BUG_ON(!host); + BUG_ON(!host->card); + +- mmc_claim_host(host); ++ mmc_get_card(host->card); + + /* + * Just check if our card has been removed. + */ +- err = mmc_send_status(host->card, NULL); ++ err = _mmc_detect_card_removed(host); + +- mmc_release_host(host); ++ mmc_put_card(host->card); + + if (err) { + mmc_remove(host); +@@ -1133,127 +1614,192 @@ static void mmc_detect(struct mmc_host *host) + } + } + +-/* +- * Suspend callback from host. +- */ +-static int mmc_suspend(struct mmc_host *host) ++static int _mmc_suspend(struct mmc_host *host, bool is_suspend) + { + int err = 0; ++ unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT : ++ EXT_CSD_POWER_OFF_LONG; + + BUG_ON(!host); + BUG_ON(!host->card); + + mmc_claim_host(host); +- if (mmc_card_can_sleep(host)) +- err = mmc_card_sleep(host); ++ ++ if (mmc_card_suspended(host->card)) ++ goto out; ++ ++ if (mmc_card_doing_bkops(host->card)) { ++ err = mmc_stop_bkops(host->card); ++ if (err) ++ goto out; ++ } ++ ++ err = mmc_flush_cache(host->card); ++ if (err) ++ goto out; ++ ++ if (mmc_can_poweroff_notify(host->card) && ++ ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend)) ++ err = mmc_poweroff_notify(host->card, notify_type); ++ else if (mmc_can_sleep(host->card)) ++ err = mmc_sleep(host); + else if (!mmc_host_is_spi(host)) +- mmc_deselect_cards(host); +- host->card->state &= ~MMC_STATE_HIGHSPEED; ++ err = mmc_deselect_cards(host); ++ ++ if (!err) { ++ mmc_power_off(host); ++ mmc_card_set_suspended(host->card); ++ } ++out: + mmc_release_host(host); ++ return err; ++} ++ ++/* ++ * Suspend callback ++ */ ++static int mmc_suspend(struct mmc_host *host) ++{ ++ int err; ++ ++ err = _mmc_suspend(host, true); ++ if (!err) { ++ pm_runtime_disable(&host->card->dev); ++ pm_runtime_set_suspended(&host->card->dev); ++ } + + return err; + } + + /* +- * Resume callback from host. +- * + * This function tries to determine if the same card is still present + * and, if so, restore all state to it. + */ +-static int mmc_resume(struct mmc_host *host) ++static int _mmc_resume(struct mmc_host *host) + { +- int err; ++ int err = 0; + + BUG_ON(!host); + BUG_ON(!host->card); + + mmc_claim_host(host); +- err = mmc_init_card(host, host->ocr, host->card); +- mmc_release_host(host); + ++ if (!mmc_card_suspended(host->card)) ++ goto out; ++ ++ mmc_power_up(host, host->card->ocr); ++ err = mmc_init_card(host, host->card->ocr, host->card); ++ mmc_card_clr_suspended(host->card); ++ ++out: ++ mmc_release_host(host); + return err; + } + +-static int mmc_power_restore(struct mmc_host *host) ++/* ++ * Shutdown callback ++ */ ++static int mmc_shutdown(struct mmc_host *host) + { +- int ret; ++ int err = 0; + +- host->card->state &= ~MMC_STATE_HIGHSPEED; +- mmc_claim_host(host); +- ret = mmc_init_card(host, host->ocr, host->card); +- mmc_release_host(host); ++ /* ++ * In a specific case for poweroff notify, we need to resume the card ++ * before we can shutdown it properly. ++ */ ++ if (mmc_can_poweroff_notify(host->card) && ++ !(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE)) ++ err = _mmc_resume(host); + +- return ret; ++ if (!err) ++ err = _mmc_suspend(host, false); ++ ++ return err; + } + +-static int mmc_sleep(struct mmc_host *host) ++/* ++ * Callback for resume. ++ */ ++static int mmc_resume(struct mmc_host *host) + { +- struct mmc_card *card = host->card; +- int err = -ENOSYS; ++ int err = 0; + +- if (card && card->ext_csd.rev >= 3) { +- err = mmc_card_sleepawake(host, 1); +- if (err < 0) +- pr_debug("%s: Error %d while putting card into sleep", +- mmc_hostname(host), err); ++ if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) { ++ err = _mmc_resume(host); ++ pm_runtime_set_active(&host->card->dev); ++ pm_runtime_mark_last_busy(&host->card->dev); + } ++ pm_runtime_enable(&host->card->dev); + + return err; + } + +-static int mmc_awake(struct mmc_host *host) ++/* ++ * Callback for runtime_suspend. ++ */ ++static int mmc_runtime_suspend(struct mmc_host *host) + { +- struct mmc_card *card = host->card; +- int err = -ENOSYS; ++ int err; + +- if (card && card->ext_csd.rev >= 3) { +- err = mmc_card_sleepawake(host, 0); +- if (err < 0) +- pr_debug("%s: Error %d while awaking sleeping card", +- mmc_hostname(host), err); +- } ++ if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) ++ return 0; ++ ++ err = _mmc_suspend(host, true); ++ if (err) ++ pr_err("%s: error %d doing aggessive suspend\n", ++ mmc_hostname(host), err); + + return err; + } + +-static const struct mmc_bus_ops mmc_ops = { +- .awake = mmc_awake, +- .sleep = mmc_sleep, +- .remove = mmc_remove, +- .detect = mmc_detect, +- .suspend = NULL, +- .resume = NULL, +- .power_restore = mmc_power_restore, +-}; ++/* ++ * Callback for runtime_resume. ++ */ ++static int mmc_runtime_resume(struct mmc_host *host) ++{ ++ int err; + +-static const struct mmc_bus_ops mmc_ops_unsafe = { +- .awake = mmc_awake, +- .sleep = mmc_sleep, ++ if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME))) ++ return 0; ++ ++ err = _mmc_resume(host); ++ if (err) ++ pr_err("%s: error %d doing aggessive resume\n", ++ mmc_hostname(host), err); ++ ++ return 0; ++} ++ ++static int mmc_power_restore(struct mmc_host *host) ++{ ++ int ret; ++ ++ mmc_claim_host(host); ++ ret = mmc_init_card(host, host->card->ocr, host->card); ++ mmc_release_host(host); ++ ++ return ret; ++} ++ ++static const struct mmc_bus_ops mmc_ops = { + .remove = mmc_remove, + .detect = mmc_detect, + .suspend = mmc_suspend, + .resume = mmc_resume, ++ .runtime_suspend = mmc_runtime_suspend, ++ .runtime_resume = mmc_runtime_resume, + .power_restore = mmc_power_restore, ++ .alive = mmc_alive, ++ .shutdown = mmc_shutdown, + }; + +-static void mmc_attach_bus_ops(struct mmc_host *host) +-{ +- const struct mmc_bus_ops *bus_ops; +- +- if (!mmc_card_is_removable(host)) +- bus_ops = &mmc_ops_unsafe; +- else +- bus_ops = &mmc_ops; +- mmc_attach_bus(host, bus_ops); +-} +- + /* + * Starting point for MMC card init. + */ + int mmc_attach_mmc(struct mmc_host *host) + { + int err; +- u32 ocr; ++ u32 ocr, rocr; + + BUG_ON(!host); + WARN_ON(!host->claimed); +@@ -1266,7 +1812,7 @@ int mmc_attach_mmc(struct mmc_host *host) + if (err) + return err; + +- mmc_attach_bus_ops(host); ++ mmc_attach_bus(host, &mmc_ops); + if (host->ocr_avail_mmc) + host->ocr_avail = host->ocr_avail_mmc; + +@@ -1279,23 +1825,12 @@ int mmc_attach_mmc(struct mmc_host *host) + goto err; + } + +- /* +- * Sanity check the voltages that the card claims to +- * support. +- */ +- if (ocr & 0x7F) { +- pr_warning("%s: card claims to support voltages " +- "below the defined range. These will be ignored.\n", +- mmc_hostname(host)); +- ocr &= ~0x7F; +- } +- +- host->ocr = mmc_select_voltage(host, ocr); ++ rocr = mmc_select_voltage(host, ocr); + + /* + * Can we support the voltage of the card? + */ +- if (!host->ocr) { ++ if (!rocr) { + err = -EINVAL; + goto err; + } +@@ -1303,7 +1838,7 @@ int mmc_attach_mmc(struct mmc_host *host) + /* + * Detect and init the card. + */ +- err = mmc_init_card(host, host->ocr, NULL); ++ err = mmc_init_card(host, rocr, NULL); + if (err) + goto err; + +diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c +index 4d41fa9..f51b5ba 100644 +--- a/drivers/mmc/core/mmc_ops.c ++++ b/drivers/mmc/core/mmc_ops.c +@@ -21,6 +21,42 @@ + #include "core.h" + #include "mmc_ops.h" + ++#define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ ++ ++static inline int __mmc_send_status(struct mmc_card *card, u32 *status, ++ bool ignore_crc) ++{ ++ int err; ++ struct mmc_command cmd = {0}; ++ ++ BUG_ON(!card); ++ BUG_ON(!card->host); ++ ++ cmd.opcode = MMC_SEND_STATUS; ++ if (!mmc_host_is_spi(card->host)) ++ cmd.arg = card->rca << 16; ++ cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; ++ if (ignore_crc) ++ cmd.flags &= ~MMC_RSP_CRC; ++ ++ err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); ++ if (err) ++ return err; ++ ++ /* NOTE: callers are required to understand the difference ++ * between "native" and SPI format status words! ++ */ ++ if (status) ++ *status = cmd.resp[0]; ++ ++ return 0; ++} ++ ++int mmc_send_status(struct mmc_card *card, u32 *status) ++{ ++ return __mmc_send_status(card, status, false); ++} ++ + static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card) + { + int err; +@@ -57,40 +93,6 @@ int mmc_deselect_cards(struct mmc_host *host) + return _mmc_select_card(host, NULL); + } + +-int mmc_card_sleepawake(struct mmc_host *host, int sleep) +-{ +- struct mmc_command cmd = {0}; +- struct mmc_card *card = host->card; +- int err; +- +- if (sleep) +- mmc_deselect_cards(host); +- +- cmd.opcode = MMC_SLEEP_AWAKE; +- cmd.arg = card->rca << 16; +- if (sleep) +- cmd.arg |= 1 << 15; +- +- cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; +- err = mmc_wait_for_cmd(host, &cmd, 0); +- if (err) +- return err; +- +- /* +- * If the host does not wait while the card signals busy, then we will +- * will have to wait the sleep/awake timeout. Note, we cannot use the +- * SEND_STATUS command to poll the status because that command (and most +- * others) is invalid while the card sleeps. +- */ +- if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) +- mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000)); +- +- if (!sleep) +- err = mmc_select_card(card); +- +- return err; +-} +- + int mmc_go_idle(struct mmc_host *host) + { + int err; +@@ -230,6 +232,10 @@ mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode) + return 0; + } + ++/* ++ * NOTE: void *buf, caller for the buf is required to use DMA-capable ++ * buffer or on-stack buffer (with some overhead in callee). ++ */ + static int + mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, + u32 opcode, void *buf, unsigned len) +@@ -239,13 +245,19 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, + struct mmc_data data = {0}; + struct scatterlist sg; + void *data_buf; ++ int is_on_stack; + +- /* dma onto stack is unsafe/nonportable, but callers to this +- * routine normally provide temporary on-stack buffers ... +- */ +- data_buf = kmalloc(len, GFP_KERNEL); +- if (data_buf == NULL) +- return -ENOMEM; ++ is_on_stack = object_is_on_stack(buf); ++ if (is_on_stack) { ++ /* ++ * dma onto stack is unsafe/nonportable, but callers to this ++ * routine normally provide temporary on-stack buffers ... ++ */ ++ data_buf = kmalloc(len, GFP_KERNEL); ++ if (!data_buf) ++ return -ENOMEM; ++ } else ++ data_buf = buf; + + mrq.cmd = &cmd; + mrq.data = &data; +@@ -280,8 +292,10 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, + + mmc_wait_for_req(host, &mrq); + +- memcpy(buf, data_buf, len); +- kfree(data_buf); ++ if (is_on_stack) { ++ memcpy(buf, data_buf, len); ++ kfree(data_buf); ++ } + + if (cmd.error) + return cmd.error; +@@ -294,24 +308,32 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, + int mmc_send_csd(struct mmc_card *card, u32 *csd) + { + int ret, i; ++ u32 *csd_tmp; + + if (!mmc_host_is_spi(card->host)) + return mmc_send_cxd_native(card->host, card->rca << 16, + csd, MMC_SEND_CSD); + +- ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16); ++ csd_tmp = kmalloc(16, GFP_KERNEL); ++ if (!csd_tmp) ++ return -ENOMEM; ++ ++ ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd_tmp, 16); + if (ret) +- return ret; ++ goto err; + + for (i = 0;i < 4;i++) +- csd[i] = be32_to_cpu(csd[i]); ++ csd[i] = be32_to_cpu(csd_tmp[i]); + +- return 0; ++err: ++ kfree(csd_tmp); ++ return ret; + } + + int mmc_send_cid(struct mmc_host *host, u32 *cid) + { + int ret, i; ++ u32 *cid_tmp; + + if (!mmc_host_is_spi(host)) { + if (!host->card) +@@ -320,14 +342,20 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid) + cid, MMC_SEND_CID); + } + +- ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16); ++ cid_tmp = kmalloc(16, GFP_KERNEL); ++ if (!cid_tmp) ++ return -ENOMEM; ++ ++ ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid_tmp, 16); + if (ret) +- return ret; ++ goto err; + + for (i = 0;i < 4;i++) +- cid[i] = be32_to_cpu(cid[i]); ++ cid[i] = be32_to_cpu(cid_tmp[i]); + +- return 0; ++err: ++ kfree(cid_tmp); ++ return ret; + } + + int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) +@@ -335,6 +363,7 @@ int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) + return mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, + ext_csd, 512); + } ++EXPORT_SYMBOL_GPL(mmc_send_ext_csd); + + int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp) + { +@@ -367,89 +396,132 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc) + } + + /** +- * mmc_switch - modify EXT_CSD register ++ * __mmc_switch - modify EXT_CSD register + * @card: the MMC card associated with the data transfer + * @set: cmd set values + * @index: EXT_CSD register index + * @value: value to program into EXT_CSD register + * @timeout_ms: timeout (ms) for operation performed by register write, + * timeout of zero implies maximum possible timeout ++ * @use_busy_signal: use the busy signal as response type ++ * @send_status: send status cmd to poll for busy ++ * @ignore_crc: ignore CRC errors when sending status cmd to poll for busy + * + * Modifies the EXT_CSD register for selected card. + */ +-int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, +- unsigned int timeout_ms) ++int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, ++ unsigned int timeout_ms, bool use_busy_signal, bool send_status, ++ bool ignore_crc) + { ++ struct mmc_host *host = card->host; + int err; + struct mmc_command cmd = {0}; +- u32 status; ++ unsigned long timeout; ++ u32 status = 0; ++ bool use_r1b_resp = use_busy_signal; + +- BUG_ON(!card); +- BUG_ON(!card->host); ++ /* ++ * If the cmd timeout and the max_busy_timeout of the host are both ++ * specified, let's validate them. A failure means we need to prevent ++ * the host from doing hw busy detection, which is done by converting ++ * to a R1 response instead of a R1B. ++ */ ++ if (timeout_ms && host->max_busy_timeout && ++ (timeout_ms > host->max_busy_timeout)) ++ use_r1b_resp = false; + + cmd.opcode = MMC_SWITCH; + cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (index << 16) | + (value << 8) | + set; +- cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; +- cmd.cmd_timeout_ms = timeout_ms; ++ cmd.flags = MMC_CMD_AC; ++ if (use_r1b_resp) { ++ cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; ++ /* ++ * A busy_timeout of zero means the host can decide to use ++ * whatever value it finds suitable. ++ */ ++ cmd.busy_timeout = timeout_ms; ++ } else { ++ cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; ++ } + +- err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); ++ if (index == EXT_CSD_SANITIZE_START) ++ cmd.sanitize_busy = true; ++ ++ err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); + if (err) + return err; + +- /* Must check status to be sure of no errors */ ++ /* No need to check card status in case of unblocking command */ ++ if (!use_busy_signal) ++ return 0; ++ ++ /* ++ * CRC errors shall only be ignored in cases were CMD13 is used to poll ++ * to detect busy completion. ++ */ ++ if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) ++ ignore_crc = false; ++ ++ /* We have an unspecified cmd timeout, use the fallback value. */ ++ if (!timeout_ms) ++ timeout_ms = MMC_OPS_TIMEOUT_MS; ++ ++ /* Must check status to be sure of no errors. */ ++ timeout = jiffies + msecs_to_jiffies(timeout_ms); + do { +- err = mmc_send_status(card, &status); +- if (err) +- return err; +- if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) ++ if (send_status) { ++ err = __mmc_send_status(card, &status, ignore_crc); ++ if (err) ++ return err; ++ } ++ if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) + break; +- if (mmc_host_is_spi(card->host)) ++ if (mmc_host_is_spi(host)) + break; ++ ++ /* ++ * We are not allowed to issue a status command and the host ++ * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only ++ * rely on waiting for the stated timeout to be sufficient. ++ */ ++ if (!send_status) { ++ mmc_delay(timeout_ms); ++ return 0; ++ } ++ ++ /* Timeout if the device never leaves the program state. */ ++ if (time_after(jiffies, timeout)) { ++ pr_err("%s: Card stuck in programming state! %s\n", ++ mmc_hostname(host), __func__); ++ return -ETIMEDOUT; ++ } + } while (R1_CURRENT_STATE(status) == R1_STATE_PRG); + +- if (mmc_host_is_spi(card->host)) { ++ if (mmc_host_is_spi(host)) { + if (status & R1_SPI_ILLEGAL_COMMAND) + return -EBADMSG; + } else { + if (status & 0xFDFFA000) +- pr_warning("%s: unexpected status %#x after " +- "switch", mmc_hostname(card->host), status); ++ pr_warn("%s: unexpected status %#x after switch\n", ++ mmc_hostname(host), status); + if (status & R1_SWITCH_ERROR) + return -EBADMSG; + } + + return 0; + } +-EXPORT_SYMBOL_GPL(mmc_switch); ++EXPORT_SYMBOL_GPL(__mmc_switch); + +-int mmc_send_status(struct mmc_card *card, u32 *status) ++int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, ++ unsigned int timeout_ms) + { +- int err; +- struct mmc_command cmd = {0}; +- +- BUG_ON(!card); +- BUG_ON(!card->host); +- +- cmd.opcode = MMC_SEND_STATUS; +- if (!mmc_host_is_spi(card->host)) +- cmd.arg = card->rca << 16; +- cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; +- +- err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); +- if (err) +- return err; +- +- /* NOTE: callers are required to understand the difference +- * between "native" and SPI format status words! +- */ +- if (status) +- *status = cmd.resp[0]; +- +- return 0; ++ return __mmc_switch(card, set, index, value, timeout_ms, true, true, ++ false); + } ++EXPORT_SYMBOL_GPL(mmc_switch); + + static int + mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, +@@ -507,6 +579,7 @@ mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, + + data.sg = &sg; + data.sg_len = 1; ++ mmc_set_data_timeout(&data, card); + sg_init_one(&sg, data_buf, len); + mmc_wait_for_req(host, &mrq); + err = 0; +@@ -553,19 +626,22 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) + { + struct mmc_command cmd = {0}; + unsigned int opcode; +- unsigned int flags; + int err; + ++ if (!card->ext_csd.hpi) { ++ pr_warning("%s: Card didn't support HPI command\n", ++ mmc_hostname(card->host)); ++ return -EINVAL; ++ } ++ + opcode = card->ext_csd.hpi_cmd; + if (opcode == MMC_STOP_TRANSMISSION) +- flags = MMC_RSP_R1 | MMC_CMD_AC; ++ cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; + else if (opcode == MMC_SEND_STATUS) +- flags = MMC_RSP_R1 | MMC_CMD_AC; ++ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; + + cmd.opcode = opcode; + cmd.arg = card->rca << 16 | 1; +- cmd.flags = flags; +- cmd.cmd_timeout_ms = card->ext_csd.out_of_int_time; + + err = mmc_wait_for_cmd(card->host, &cmd, 0); + if (err) { +diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h +index 3dd8941..80ae9f4 100644 +--- a/drivers/mmc/core/mmc_ops.h ++++ b/drivers/mmc/core/mmc_ops.h +@@ -24,7 +24,6 @@ int mmc_send_status(struct mmc_card *card, u32 *status); + int mmc_send_cid(struct mmc_host *host, u32 *cid); + int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); + int mmc_spi_set_crc(struct mmc_host *host, int use_crc); +-int mmc_card_sleepawake(struct mmc_host *host, int sleep); + int mmc_bus_test(struct mmc_card *card, u8 bus_width); + int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status); + +diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c +index 06ee1ae..6c36fcc 100644 +--- a/drivers/mmc/core/quirks.c ++++ b/drivers/mmc/core/quirks.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + #ifndef SDIO_VENDOR_ID_TI + #define SDIO_VENDOR_ID_TI 0x0097 +@@ -30,6 +31,10 @@ + #define SDIO_DEVICE_ID_STE_CW1200 0x2280 + #endif + ++#ifndef SDIO_DEVICE_ID_MARVELL_8797_F0 ++#define SDIO_DEVICE_ID_MARVELL_8797_F0 0x9128 ++#endif ++ + /* + * This hook just adds a quirk for all sdio devices + */ +@@ -58,6 +63,9 @@ static const struct mmc_fixup mmc_fixup_methods[] = { + SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200, + add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512), + ++ SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797_F0, ++ add_quirk, MMC_QUIRK_BROKEN_IRQ_POLLING), ++ + END_FIXUP + }; + +diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c +index f2a05ea..ac56732 100644 +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -13,12 +13,16 @@ + #include + #include + #include ++#include + + #include + #include + #include + #include + ++ ++#include ++ + #include "core.h" + #include "bus.h" + #include "mmc_ops.h" +@@ -44,6 +48,13 @@ static const unsigned int tacc_mant[] = { + 35, 40, 45, 50, 55, 60, 70, 80, + }; + ++static const unsigned int sd_au_size[] = { ++ 0, SZ_16K / 512, SZ_32K / 512, SZ_64K / 512, ++ SZ_128K / 512, SZ_256K / 512, SZ_512K / 512, SZ_1M / 512, ++ SZ_2M / 512, SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512, ++ SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, SZ_64M / 512, ++}; ++ + #define UNSTUFF_BITS(resp,start,size) \ + ({ \ + const int __size = size; \ +@@ -244,18 +255,20 @@ static int mmc_read_ssr(struct mmc_card *card) + * bitfield positions accordingly. + */ + au = UNSTUFF_BITS(ssr, 428 - 384, 4); +- if (au > 0 || au <= 9) { +- card->ssr.au = 1 << (au + 4); +- es = UNSTUFF_BITS(ssr, 408 - 384, 16); +- et = UNSTUFF_BITS(ssr, 402 - 384, 6); +- eo = UNSTUFF_BITS(ssr, 400 - 384, 2); +- if (es && et) { +- card->ssr.erase_timeout = (et * 1000) / es; +- card->ssr.erase_offset = eo * 1000; ++ if (au) { ++ if (au <= 9 || card->scr.sda_spec3) { ++ card->ssr.au = sd_au_size[au]; ++ es = UNSTUFF_BITS(ssr, 408 - 384, 16); ++ et = UNSTUFF_BITS(ssr, 402 - 384, 6); ++ if (es && et) { ++ eo = UNSTUFF_BITS(ssr, 400 - 384, 2); ++ card->ssr.erase_timeout = (et * 1000) / es; ++ card->ssr.erase_offset = eo * 1000; ++ } ++ } else { ++ pr_warning("%s: SD Status: Invalid Allocation Unit size.\n", ++ mmc_hostname(card->host)); + } +- } else { +- pr_warning("%s: SD Status: Invalid Allocation Unit " +- "size.\n", mmc_hostname(card->host)); + } + out: + kfree(ssr); +@@ -290,8 +303,12 @@ static int mmc_read_switch(struct mmc_card *card) + return -ENOMEM; + } + +- /* Find out the supported Bus Speed Modes. */ +- err = mmc_sd_switch(card, 0, 0, 1, status); ++ /* ++ * Find out the card's support bits with a mode 0 operation. ++ * The argument does not matter, as the support bits do not ++ * change with the arguments. ++ */ ++ err = mmc_sd_switch(card, 0, 0, 0, status); + if (err) { + /* + * If the host or the card can't do the switch, +@@ -307,51 +324,13 @@ static int mmc_read_switch(struct mmc_card *card) + goto out; + } + +- if (status[13] & UHS_SDR50_BUS_SPEED) +- card->sw_caps.hs_max_dtr = 50000000; ++ if (status[13] & SD_MODE_HIGH_SPEED) ++ card->sw_caps.hs_max_dtr = HIGH_SPEED_MAX_DTR; + + if (card->scr.sda_spec3) { + card->sw_caps.sd3_bus_mode = status[13]; +- +- /* Find out Driver Strengths supported by the card */ +- err = mmc_sd_switch(card, 0, 2, 1, status); +- if (err) { +- /* +- * If the host or the card can't do the switch, +- * fail more gracefully. +- */ +- if (err != -EINVAL && err != -ENOSYS && err != -EFAULT) +- goto out; +- +- pr_warning("%s: problem reading " +- "Driver Strength.\n", +- mmc_hostname(card->host)); +- err = 0; +- +- goto out; +- } +- ++ /* Driver Strengths supported by the card */ + card->sw_caps.sd3_drv_type = status[9]; +- +- /* Find out Current Limits supported by the card */ +- err = mmc_sd_switch(card, 0, 3, 1, status); +- if (err) { +- /* +- * If the host or the card can't do the switch, +- * fail more gracefully. +- */ +- if (err != -EINVAL && err != -ENOSYS && err != -EFAULT) +- goto out; +- +- pr_warning("%s: problem reading " +- "Current Limit.\n", +- mmc_hostname(card->host)); +- err = 0; +- +- goto out; +- } +- +- card->sw_caps.sd3_curr_limit = status[7]; + } + + out: +@@ -451,9 +430,11 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status) + * information and let the hardware specific code + * return what is possible given the options + */ ++ mmc_host_clk_hold(card->host); + drive_strength = card->host->ops->select_drive_strength( + card->sw_caps.uhs_max_dtr, + host_drv_type, card_drv_type); ++ mmc_host_clk_release(card->host); + + err = mmc_sd_switch(card, 1, 2, drive_strength, status); + if (err) +@@ -476,8 +457,7 @@ static void sd_update_bus_speed_mode(struct mmc_card *card) + * If the host doesn't support any of the UHS-I modes, fallback on + * default speed. + */ +- if (!(card->host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | +- MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))) { ++ if (!mmc_host_uhs(card->host)) { + card->sd_bus_speed = 0; + return; + } +@@ -549,60 +529,80 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status) + return 0; + } + ++/* Get host's max current setting at its current voltage */ ++static u32 sd_get_host_max_current(struct mmc_host *host) ++{ ++ u32 voltage, max_current; ++ ++ voltage = 1 << host->ios.vdd; ++ switch (voltage) { ++ case MMC_VDD_165_195: ++ max_current = host->max_current_180; ++ break; ++ case MMC_VDD_29_30: ++ case MMC_VDD_30_31: ++ max_current = host->max_current_300; ++ break; ++ case MMC_VDD_32_33: ++ case MMC_VDD_33_34: ++ max_current = host->max_current_330; ++ break; ++ default: ++ max_current = 0; ++ } ++ ++ return max_current; ++} ++ + static int sd_set_current_limit(struct mmc_card *card, u8 *status) + { +- int current_limit = 0; ++ int current_limit = SD_SET_CURRENT_NO_CHANGE; + int err; ++ u32 max_current; + + /* + * Current limit switch is only defined for SDR50, SDR104, and DDR50 +- * bus speed modes. For other bus speed modes, we set the default +- * current limit of 200mA. ++ * bus speed modes. For other bus speed modes, we do not change the ++ * current limit. + */ +- if ((card->sd_bus_speed == UHS_SDR50_BUS_SPEED) || +- (card->sd_bus_speed == UHS_SDR104_BUS_SPEED) || +- (card->sd_bus_speed == UHS_DDR50_BUS_SPEED)) { +- if (card->host->caps & MMC_CAP_MAX_CURRENT_800) { +- if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_800) +- current_limit = SD_SET_CURRENT_LIMIT_800; +- else if (card->sw_caps.sd3_curr_limit & +- SD_MAX_CURRENT_600) +- current_limit = SD_SET_CURRENT_LIMIT_600; +- else if (card->sw_caps.sd3_curr_limit & +- SD_MAX_CURRENT_400) +- current_limit = SD_SET_CURRENT_LIMIT_400; +- else if (card->sw_caps.sd3_curr_limit & +- SD_MAX_CURRENT_200) +- current_limit = SD_SET_CURRENT_LIMIT_200; +- } else if (card->host->caps & MMC_CAP_MAX_CURRENT_600) { +- if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_600) +- current_limit = SD_SET_CURRENT_LIMIT_600; +- else if (card->sw_caps.sd3_curr_limit & +- SD_MAX_CURRENT_400) +- current_limit = SD_SET_CURRENT_LIMIT_400; +- else if (card->sw_caps.sd3_curr_limit & +- SD_MAX_CURRENT_200) +- current_limit = SD_SET_CURRENT_LIMIT_200; +- } else if (card->host->caps & MMC_CAP_MAX_CURRENT_400) { +- if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_400) +- current_limit = SD_SET_CURRENT_LIMIT_400; +- else if (card->sw_caps.sd3_curr_limit & +- SD_MAX_CURRENT_200) +- current_limit = SD_SET_CURRENT_LIMIT_200; +- } else if (card->host->caps & MMC_CAP_MAX_CURRENT_200) { +- if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_200) +- current_limit = SD_SET_CURRENT_LIMIT_200; +- } +- } else ++ if ((card->sd_bus_speed != UHS_SDR50_BUS_SPEED) && ++ (card->sd_bus_speed != UHS_SDR104_BUS_SPEED) && ++ (card->sd_bus_speed != UHS_DDR50_BUS_SPEED)) ++ return 0; ++ ++ /* ++ * Host has different current capabilities when operating at ++ * different voltages, so find out its max current first. ++ */ ++ max_current = sd_get_host_max_current(card->host); ++ ++ /* ++ * We only check host's capability here, if we set a limit that is ++ * higher than the card's maximum current, the card will be using its ++ * maximum current, e.g. if the card's maximum current is 300ma, and ++ * when we set current limit to 200ma, the card will draw 200ma, and ++ * when we set current limit to 400/600/800ma, the card will draw its ++ * maximum 300ma from the host. ++ */ ++ if (max_current >= 800) ++ current_limit = SD_SET_CURRENT_LIMIT_800; ++ else if (max_current >= 600) ++ current_limit = SD_SET_CURRENT_LIMIT_600; ++ else if (max_current >= 400) ++ current_limit = SD_SET_CURRENT_LIMIT_400; ++ else if (max_current >= 200) + current_limit = SD_SET_CURRENT_LIMIT_200; + +- err = mmc_sd_switch(card, 1, 3, current_limit, status); +- if (err) +- return err; ++ if (current_limit != SD_SET_CURRENT_NO_CHANGE) { ++ err = mmc_sd_switch(card, 1, 3, current_limit, status); ++ if (err) ++ return err; + +- if (((status[15] >> 4) & 0x0F) != current_limit) +- pr_warning("%s: Problem setting current limit!\n", +- mmc_hostname(card->host)); ++ if (((status[15] >> 4) & 0x0F) != current_limit) ++ pr_warning("%s: Problem setting current limit!\n", ++ mmc_hostname(card->host)); ++ ++ } + + return 0; + } +@@ -659,9 +659,18 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) + if (err) + goto out; + +- /* SPI mode doesn't define CMD19 */ +- if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) +- err = card->host->ops->execute_tuning(card->host); ++ /* ++ * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and ++ * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. ++ */ ++ if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning && ++ (card->sd_bus_speed == UHS_SDR50_BUS_SPEED || ++ card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) { ++ mmc_host_clk_hold(card->host); ++ err = card->host->ops->execute_tuning(card->host, ++ MMC_SEND_TUNING_BLOCK); ++ mmc_host_clk_release(card->host); ++ } + + out: + kfree(status); +@@ -720,6 +729,16 @@ struct device_type sd_type = { + int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr) + { + int err; ++ u32 max_current; ++ int retries = 10; ++ u32 pocr = ocr; ++ ++try_again: ++ if (!retries) { ++ ocr &= ~SD_OCR_S18R; ++ pr_warning("%s: Skipping voltage switch\n", ++ mmc_hostname(host)); ++ } + + /* + * Since we're changing the OCR value, we seem to +@@ -741,18 +760,20 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr) + + /* + * If the host supports one of UHS-I modes, request the card +- * to switch to 1.8V signaling level. ++ * to switch to 1.8V signaling level. If the card has failed ++ * repeatedly to switch however, skip this. + */ +- if (host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | +- MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50)) ++ if (retries && mmc_host_uhs(host)) + ocr |= SD_OCR_S18R; + +- /* If the host can supply more than 150mA, XPC should be set to 1. */ +- if (host->caps & (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 | +- MMC_CAP_SET_XPC_180)) ++ /* ++ * If the host can supply more than 150mA at current voltage, ++ * XPC should be set to 1. ++ */ ++ max_current = sd_get_host_max_current(host); ++ if (max_current > 150) + ocr |= SD_OCR_XPC; + +-try_again: + err = mmc_send_app_op_cond(host, ocr, rocr); + if (err) + return err; +@@ -763,9 +784,13 @@ try_again: + */ + if (!mmc_host_is_spi(host) && rocr && + ((*rocr & 0x41000000) == 0x41000000)) { +- err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, true); +- if (err) { +- ocr &= ~SD_OCR_S18R; ++ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, ++ pocr); ++ if (err == -EAGAIN) { ++ retries--; ++ goto try_again; ++ } else if (err) { ++ retries = 0; + goto try_again; + } + } +@@ -849,8 +874,11 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, + if (!reinit) { + int ro = -1; + +- if (host->ops->get_ro) ++ if (host->ops->get_ro) { ++ mmc_host_clk_hold(card->host); + ro = host->ops->get_ro(host); ++ mmc_host_clk_release(card->host); ++ } + + if (ro < 0) { + pr_warning("%s: host does not " +@@ -869,7 +897,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card) + { + unsigned max_dtr = (unsigned int)-1; + +- if (mmc_card_highspeed(card)) { ++ if (mmc_card_hs(card)) { + if (max_dtr > card->sw_caps.hs_max_dtr) + max_dtr = card->sw_caps.hs_max_dtr; + } else if (max_dtr > card->csd.max_dtr) { +@@ -879,12 +907,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card) + return max_dtr; + } + +-void mmc_sd_go_highspeed(struct mmc_card *card) +-{ +- mmc_card_set_highspeed(card); +- mmc_set_timing(card->host, MMC_TIMING_SD_HS); +-} +- + /* + * Handle the detection and initialisation of a card. + * +@@ -919,6 +941,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, + if (IS_ERR(card)) + return PTR_ERR(card); + ++ card->ocr = ocr; + card->type = MMC_TYPE_SD; + memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); + } +@@ -929,13 +952,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, + if (!mmc_host_is_spi(host)) { + err = mmc_send_relative_addr(host, &card->rca); + if (err) +- return err; ++ goto free_card; + } + + if (!oldcard) { + err = mmc_sd_get_csd(host, card); + if (err) +- return err; ++ goto free_card; + + mmc_decode_cid(card); + } +@@ -946,7 +969,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, + if (!mmc_host_is_spi(host)) { + err = mmc_select_card(card); + if (err) +- return err; ++ goto free_card; + } + + err = mmc_sd_setup_card(host, card, oldcard != NULL); +@@ -958,23 +981,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, + err = mmc_sd_init_uhs_card(card); + if (err) + goto free_card; +- +- /* Card is an ultra-high-speed card */ +- mmc_sd_card_set_uhs(card); +- +- /* +- * Since initialization is now complete, enable preset +- * value registers for UHS-I cards. +- */ +- if (host->ops->enable_preset_value) +- host->ops->enable_preset_value(host, true); + } else { + /* + * Attempt to change to high-speed (if supported) + */ + err = mmc_sd_switch_hs(card); + if (err > 0) +- mmc_sd_go_highspeed(card); ++ mmc_set_timing(card->host, MMC_TIMING_SD_HS); + else if (err) + goto free_card; + +@@ -1019,6 +1032,14 @@ static void mmc_sd_remove(struct mmc_host *host) + } + + /* ++ * Card detection - card is alive. ++ */ ++static int mmc_sd_alive(struct mmc_host *host) ++{ ++ return mmc_send_status(host->card, NULL); ++} ++ ++/* + * Card detection callback from host. + */ + static void mmc_sd_detect(struct mmc_host *host) +@@ -1028,14 +1049,14 @@ static void mmc_sd_detect(struct mmc_host *host) + BUG_ON(!host); + BUG_ON(!host->card); + +- mmc_claim_host(host); ++ mmc_get_card(host->card); + + /* + * Just check if our card has been removed. + */ +- err = mmc_send_status(host->card, NULL); ++ err = _mmc_detect_card_removed(host); + +- mmc_release_host(host); ++ mmc_put_card(host->card); + + if (err) { + mmc_sd_remove(host); +@@ -1047,50 +1068,131 @@ static void mmc_sd_detect(struct mmc_host *host) + } + } + +-/* +- * Suspend callback from host. +- */ +-static int mmc_sd_suspend(struct mmc_host *host) ++static int _mmc_sd_suspend(struct mmc_host *host) + { ++ int err = 0; ++ + BUG_ON(!host); + BUG_ON(!host->card); + + mmc_claim_host(host); ++ ++ if (mmc_card_suspended(host->card)) ++ goto out; ++ + if (!mmc_host_is_spi(host)) +- mmc_deselect_cards(host); +- host->card->state &= ~MMC_STATE_HIGHSPEED; ++ err = mmc_deselect_cards(host); ++ ++ if (!err) { ++ mmc_power_off(host); ++ mmc_card_set_suspended(host->card); ++ } ++ ++out: + mmc_release_host(host); ++ return err; ++} + +- return 0; ++/* ++ * Callback for suspend ++ */ ++static int mmc_sd_suspend(struct mmc_host *host) ++{ ++ int err; ++ ++ err = _mmc_sd_suspend(host); ++ if (!err) { ++ pm_runtime_disable(&host->card->dev); ++ pm_runtime_set_suspended(&host->card->dev); ++ } ++ ++ return err; + } + + /* +- * Resume callback from host. +- * + * This function tries to determine if the same card is still present + * and, if so, restore all state to it. + */ +-static int mmc_sd_resume(struct mmc_host *host) ++static int _mmc_sd_resume(struct mmc_host *host) + { +- int err; ++ int err = 0; + + BUG_ON(!host); + BUG_ON(!host->card); + + mmc_claim_host(host); +- err = mmc_sd_init_card(host, host->ocr, host->card); ++ ++ if (!mmc_card_suspended(host->card)) ++ goto out; ++ ++ mmc_power_up(host, host->card->ocr); ++ err = mmc_sd_init_card(host, host->card->ocr, host->card); ++ mmc_card_clr_suspended(host->card); ++ ++out: + mmc_release_host(host); ++ return err; ++} ++ ++/* ++ * Callback for resume ++ */ ++static int mmc_sd_resume(struct mmc_host *host) ++{ ++ int err = 0; ++ ++ if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) { ++ err = _mmc_sd_resume(host); ++ pm_runtime_set_active(&host->card->dev); ++ pm_runtime_mark_last_busy(&host->card->dev); ++ } ++ pm_runtime_enable(&host->card->dev); ++ ++ return err; ++} ++ ++/* ++ * Callback for runtime_suspend. ++ */ ++static int mmc_sd_runtime_suspend(struct mmc_host *host) ++{ ++ int err; ++ ++ if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) ++ return 0; ++ ++ err = _mmc_sd_suspend(host); ++ if (err) ++ pr_err("%s: error %d doing aggessive suspend\n", ++ mmc_hostname(host), err); + + return err; + } + ++/* ++ * Callback for runtime_resume. ++ */ ++static int mmc_sd_runtime_resume(struct mmc_host *host) ++{ ++ int err; ++ ++ if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME))) ++ return 0; ++ ++ err = _mmc_sd_resume(host); ++ if (err) ++ pr_err("%s: error %d doing aggessive resume\n", ++ mmc_hostname(host), err); ++ ++ return 0; ++} ++ + static int mmc_sd_power_restore(struct mmc_host *host) + { + int ret; + +- host->card->state &= ~MMC_STATE_HIGHSPEED; + mmc_claim_host(host); +- ret = mmc_sd_init_card(host, host->ocr, host->card); ++ ret = mmc_sd_init_card(host, host->card->ocr, host->card); + mmc_release_host(host); + + return ret; +@@ -1099,55 +1201,31 @@ static int mmc_sd_power_restore(struct mmc_host *host) + static const struct mmc_bus_ops mmc_sd_ops = { + .remove = mmc_sd_remove, + .detect = mmc_sd_detect, +- .suspend = NULL, +- .resume = NULL, +- .power_restore = mmc_sd_power_restore, +-}; +- +-static const struct mmc_bus_ops mmc_sd_ops_unsafe = { +- .remove = mmc_sd_remove, +- .detect = mmc_sd_detect, ++ .runtime_suspend = mmc_sd_runtime_suspend, ++ .runtime_resume = mmc_sd_runtime_resume, + .suspend = mmc_sd_suspend, + .resume = mmc_sd_resume, + .power_restore = mmc_sd_power_restore, ++ .alive = mmc_sd_alive, ++ .shutdown = mmc_sd_suspend, + }; + +-static void mmc_sd_attach_bus_ops(struct mmc_host *host) +-{ +- const struct mmc_bus_ops *bus_ops; +- +- if (!mmc_card_is_removable(host)) +- bus_ops = &mmc_sd_ops_unsafe; +- else +- bus_ops = &mmc_sd_ops; +- mmc_attach_bus(host, bus_ops); +-} +- + /* + * Starting point for SD card init. + */ + int mmc_attach_sd(struct mmc_host *host) + { + int err; +- u32 ocr; ++ u32 ocr, rocr; + + BUG_ON(!host); + WARN_ON(!host->claimed); + +- /* Make sure we are at 3.3V signalling voltage */ +- err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, false); +- if (err) +- return err; +- +- /* Disable preset value enable if already set since last time */ +- if (host->ops->enable_preset_value) +- host->ops->enable_preset_value(host, false); +- + err = mmc_send_app_op_cond(host, 0, &ocr); + if (err) + return err; + +- mmc_sd_attach_bus_ops(host); ++ mmc_attach_bus(host, &mmc_sd_ops); + if (host->ocr_avail_sd) + host->ocr_avail = host->ocr_avail_sd; + +@@ -1162,31 +1240,12 @@ int mmc_attach_sd(struct mmc_host *host) + goto err; + } + +- /* +- * Sanity check the voltages that the card claims to +- * support. +- */ +- if (ocr & 0x7F) { +- pr_warning("%s: card claims to support voltages " +- "below the defined range. These will be ignored.\n", +- mmc_hostname(host)); +- ocr &= ~0x7F; +- } +- +- if ((ocr & MMC_VDD_165_195) && +- !(host->ocr_avail_sd & MMC_VDD_165_195)) { +- pr_warning("%s: SD card claims to support the " +- "incompletely defined 'low voltage range'. This " +- "will be ignored.\n", mmc_hostname(host)); +- ocr &= ~MMC_VDD_165_195; +- } +- +- host->ocr = mmc_select_voltage(host, ocr); ++ rocr = mmc_select_voltage(host, ocr); + + /* + * Can we support the voltage(s) of the card(s)? + */ +- if (!host->ocr) { ++ if (!rocr) { + err = -EINVAL; + goto err; + } +@@ -1194,7 +1253,7 @@ int mmc_attach_sd(struct mmc_host *host) + /* + * Detect and init the card. + */ +- err = mmc_sd_init_card(host, host->ocr, NULL); ++ err = mmc_sd_init_card(host, rocr, NULL); + if (err) + goto err; + +diff --git a/drivers/mmc/core/sd.h b/drivers/mmc/core/sd.h +index 4b34b24..aab824a 100644 +--- a/drivers/mmc/core/sd.h ++++ b/drivers/mmc/core/sd.h +@@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, + bool reinit); + unsigned mmc_sd_get_max_clock(struct mmc_card *card); + int mmc_sd_switch_hs(struct mmc_card *card); +-void mmc_sd_go_highspeed(struct mmc_card *card); + + #endif +diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c +index 558a495..e636d9e 100644 +--- a/drivers/mmc/core/sdio.c ++++ b/drivers/mmc/core/sdio.c +@@ -14,6 +14,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -97,11 +98,13 @@ fail: + return ret; + } + +-static int sdio_read_cccr(struct mmc_card *card) ++static int sdio_read_cccr(struct mmc_card *card, u32 ocr) + { + int ret; + int cccr_vsn; ++ int uhs = ocr & R4_18V_PRESENT; + unsigned char data; ++ unsigned char speed; + + memset(&card->cccr, 0, sizeof(struct sdio_cccr)); + +@@ -140,12 +143,57 @@ static int sdio_read_cccr(struct mmc_card *card) + } + + if (cccr_vsn >= SDIO_CCCR_REV_1_20) { +- ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &data); ++ ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); + if (ret) + goto out; + +- if (data & SDIO_SPEED_SHS) +- card->cccr.high_speed = 1; ++ card->scr.sda_spec3 = 0; ++ card->sw_caps.sd3_bus_mode = 0; ++ card->sw_caps.sd3_drv_type = 0; ++ if (cccr_vsn >= SDIO_CCCR_REV_3_00 && uhs) { ++ card->scr.sda_spec3 = 1; ++ ret = mmc_io_rw_direct(card, 0, 0, ++ SDIO_CCCR_UHS, 0, &data); ++ if (ret) ++ goto out; ++ ++ if (mmc_host_uhs(card->host)) { ++ if (data & SDIO_UHS_DDR50) ++ card->sw_caps.sd3_bus_mode ++ |= SD_MODE_UHS_DDR50; ++ ++ if (data & SDIO_UHS_SDR50) ++ card->sw_caps.sd3_bus_mode ++ |= SD_MODE_UHS_SDR50; ++ ++ if (data & SDIO_UHS_SDR104) ++ card->sw_caps.sd3_bus_mode ++ |= SD_MODE_UHS_SDR104; ++ } ++ ++ ret = mmc_io_rw_direct(card, 0, 0, ++ SDIO_CCCR_DRIVE_STRENGTH, 0, &data); ++ if (ret) ++ goto out; ++ ++ if (data & SDIO_DRIVE_SDTA) ++ card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_A; ++ if (data & SDIO_DRIVE_SDTC) ++ card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_C; ++ if (data & SDIO_DRIVE_SDTD) ++ card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_D; ++ } ++ ++ /* if no uhs mode ensure we check for high speed */ ++ if (!card->sw_caps.sd3_bus_mode) { ++ if (speed & SDIO_SPEED_SHS) { ++ card->cccr.high_speed = 1; ++ card->sw_caps.hs_max_dtr = 50000000; ++ } else { ++ card->cccr.high_speed = 0; ++ card->sw_caps.hs_max_dtr = 25000000; ++ } ++ } + } + + out: +@@ -167,6 +215,12 @@ static int sdio_enable_wide(struct mmc_card *card) + if (ret) + return ret; + ++ if ((ctrl & SDIO_BUS_WIDTH_MASK) == SDIO_BUS_WIDTH_RESERVED) ++ pr_warning("%s: SDIO_CCCR_IF is invalid: 0x%02x\n", ++ mmc_hostname(card->host), ctrl); ++ ++ /* set as 4-bit bus width */ ++ ctrl &= ~SDIO_BUS_WIDTH_MASK; + ctrl |= SDIO_BUS_WIDTH_4BIT; + + ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL); +@@ -309,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card) + { + unsigned max_dtr; + +- if (mmc_card_highspeed(card)) { ++ if (mmc_card_hs(card)) { + /* + * The SDIO specification doesn't mention how + * the CIS transfer speed register relates to +@@ -327,6 +381,206 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card) + return max_dtr; + } + ++static unsigned char host_drive_to_sdio_drive(int host_strength) ++{ ++ switch (host_strength) { ++ case MMC_SET_DRIVER_TYPE_A: ++ return SDIO_DTSx_SET_TYPE_A; ++ case MMC_SET_DRIVER_TYPE_B: ++ return SDIO_DTSx_SET_TYPE_B; ++ case MMC_SET_DRIVER_TYPE_C: ++ return SDIO_DTSx_SET_TYPE_C; ++ case MMC_SET_DRIVER_TYPE_D: ++ return SDIO_DTSx_SET_TYPE_D; ++ default: ++ return SDIO_DTSx_SET_TYPE_B; ++ } ++} ++ ++static void sdio_select_driver_type(struct mmc_card *card) ++{ ++ int host_drv_type = SD_DRIVER_TYPE_B; ++ int card_drv_type = SD_DRIVER_TYPE_B; ++ int drive_strength; ++ unsigned char card_strength; ++ int err; ++ ++ /* ++ * If the host doesn't support any of the Driver Types A,C or D, ++ * or there is no board specific handler then default Driver ++ * Type B is used. ++ */ ++ if (!(card->host->caps & ++ (MMC_CAP_DRIVER_TYPE_A | ++ MMC_CAP_DRIVER_TYPE_C | ++ MMC_CAP_DRIVER_TYPE_D))) ++ return; ++ ++ if (!card->host->ops->select_drive_strength) ++ return; ++ ++ if (card->host->caps & MMC_CAP_DRIVER_TYPE_A) ++ host_drv_type |= SD_DRIVER_TYPE_A; ++ ++ if (card->host->caps & MMC_CAP_DRIVER_TYPE_C) ++ host_drv_type |= SD_DRIVER_TYPE_C; ++ ++ if (card->host->caps & MMC_CAP_DRIVER_TYPE_D) ++ host_drv_type |= SD_DRIVER_TYPE_D; ++ ++ if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A) ++ card_drv_type |= SD_DRIVER_TYPE_A; ++ ++ if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C) ++ card_drv_type |= SD_DRIVER_TYPE_C; ++ ++ if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_D) ++ card_drv_type |= SD_DRIVER_TYPE_D; ++ ++ /* ++ * The drive strength that the hardware can support ++ * depends on the board design. Pass the appropriate ++ * information and let the hardware specific code ++ * return what is possible given the options ++ */ ++ drive_strength = card->host->ops->select_drive_strength( ++ card->sw_caps.uhs_max_dtr, ++ host_drv_type, card_drv_type); ++ ++ /* if error just use default for drive strength B */ ++ err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_DRIVE_STRENGTH, 0, ++ &card_strength); ++ if (err) ++ return; ++ ++ card_strength &= ~(SDIO_DRIVE_DTSx_MASK<host, drive_strength); ++} ++ ++ ++static int sdio_set_bus_speed_mode(struct mmc_card *card) ++{ ++ unsigned int bus_speed, timing; ++ int err; ++ unsigned char speed; ++ ++ /* ++ * If the host doesn't support any of the UHS-I modes, fallback on ++ * default speed. ++ */ ++ if (!mmc_host_uhs(card->host)) ++ return 0; ++ ++ bus_speed = SDIO_SPEED_SDR12; ++ timing = MMC_TIMING_UHS_SDR12; ++ if ((card->host->caps & MMC_CAP_UHS_SDR104) && ++ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) { ++ bus_speed = SDIO_SPEED_SDR104; ++ timing = MMC_TIMING_UHS_SDR104; ++ card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR; ++ card->sd_bus_speed = UHS_SDR104_BUS_SPEED; ++ } else if ((card->host->caps & MMC_CAP_UHS_DDR50) && ++ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) { ++ bus_speed = SDIO_SPEED_DDR50; ++ timing = MMC_TIMING_UHS_DDR50; ++ card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR; ++ card->sd_bus_speed = UHS_DDR50_BUS_SPEED; ++ } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | ++ MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode & ++ SD_MODE_UHS_SDR50)) { ++ bus_speed = SDIO_SPEED_SDR50; ++ timing = MMC_TIMING_UHS_SDR50; ++ card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR; ++ card->sd_bus_speed = UHS_SDR50_BUS_SPEED; ++ } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | ++ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) && ++ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) { ++ bus_speed = SDIO_SPEED_SDR25; ++ timing = MMC_TIMING_UHS_SDR25; ++ card->sw_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR; ++ card->sd_bus_speed = UHS_SDR25_BUS_SPEED; ++ } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | ++ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 | ++ MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode & ++ SD_MODE_UHS_SDR12)) { ++ bus_speed = SDIO_SPEED_SDR12; ++ timing = MMC_TIMING_UHS_SDR12; ++ card->sw_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR; ++ card->sd_bus_speed = UHS_SDR12_BUS_SPEED; ++ } ++ ++ err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); ++ if (err) ++ return err; ++ ++ speed &= ~SDIO_SPEED_BSS_MASK; ++ speed |= bus_speed; ++ err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); ++ if (err) ++ return err; ++ ++ if (bus_speed) { ++ mmc_set_timing(card->host, timing); ++ mmc_set_clock(card->host, card->sw_caps.uhs_max_dtr); ++ } ++ ++ return 0; ++} ++ ++/* ++ * UHS-I specific initialization procedure ++ */ ++static int mmc_sdio_init_uhs_card(struct mmc_card *card) ++{ ++ int err; ++ ++ if (!card->scr.sda_spec3) ++ return 0; ++ ++ /* ++ * Switch to wider bus (if supported). ++ */ ++ if (card->host->caps & MMC_CAP_4_BIT_DATA) { ++ err = sdio_enable_4bit_bus(card); ++ if (err > 0) { ++ mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); ++ err = 0; ++ } ++ } ++ ++ /* Set the driver strength for the card */ ++ sdio_select_driver_type(card); ++ ++ /* Set bus speed mode of the card */ ++ err = sdio_set_bus_speed_mode(card); ++ if (err) ++ goto out; ++ ++ /* ++ * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and ++ * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. ++ */ ++ if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning && ++ ((card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50) || ++ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104))) { ++ mmc_host_clk_hold(card->host); ++ err = card->host->ops->execute_tuning(card->host, ++ MMC_SEND_TUNING_BLOCK); ++ mmc_host_clk_release(card->host); ++ } ++ ++out: ++ ++ return err; ++} ++ + /* + * Handle the detection and initialisation of a card. + * +@@ -338,15 +592,29 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, + { + struct mmc_card *card; + int err; ++ int retries = 10; ++ u32 rocr = 0; ++ u32 ocr_card = ocr; + + BUG_ON(!host); + WARN_ON(!host->claimed); + ++ /* to query card if 1.8V signalling is supported */ ++ if (mmc_host_uhs(host)) ++ ocr |= R4_18V_PRESENT; ++ ++try_again: ++ if (!retries) { ++ pr_warning("%s: Skipping voltage switch\n", ++ mmc_hostname(host)); ++ ocr &= ~R4_18V_PRESENT; ++ } ++ + /* + * Inform the card of the voltage + */ + if (!powered_resume) { +- err = mmc_send_io_op_cond(host, host->ocr, &ocr); ++ err = mmc_send_io_op_cond(host, ocr, &rocr); + if (err) + goto err; + } +@@ -369,8 +637,8 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, + goto err; + } + +- if ((ocr & R4_MEMORY_PRESENT) && +- mmc_sd_get_cid(host, host->ocr & ocr, card->raw_cid, NULL) == 0) { ++ if ((rocr & R4_MEMORY_PRESENT) && ++ mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) { + card->type = MMC_TYPE_SD_COMBO; + + if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO || +@@ -394,6 +662,31 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, + host->ops->init_card(host, card); + + /* ++ * If the host and card support UHS-I mode request the card ++ * to switch to 1.8V signaling level. No 1.8v signalling if ++ * UHS mode is not enabled to maintain compatibility and some ++ * systems that claim 1.8v signalling in fact do not support ++ * it. ++ */ ++ if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) { ++ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, ++ ocr); ++ if (err == -EAGAIN) { ++ sdio_reset(host); ++ mmc_go_idle(host); ++ mmc_send_if_cond(host, host->ocr_avail); ++ mmc_remove_card(card); ++ retries--; ++ goto try_again; ++ } else if (err) { ++ ocr &= ~R4_18V_PRESENT; ++ } ++ err = 0; ++ } else { ++ ocr &= ~R4_18V_PRESENT; ++ } ++ ++ /* + * For native busses: set card RCA and quit open drain mode. + */ + if (!powered_resume && !mmc_host_is_spi(host)) { +@@ -440,7 +733,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, + mmc_set_clock(host, card->cis.max_dtr); + + if (card->cccr.high_speed) { +- mmc_card_set_highspeed(card); + mmc_set_timing(card->host, MMC_TIMING_SD_HS); + } + +@@ -450,7 +742,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, + /* + * Read the common registers. + */ +- err = sdio_read_cccr(card); ++ err = sdio_read_cccr(card, ocr); + if (err) + goto remove; + +@@ -470,6 +762,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, + + card = oldcard; + } ++ card->ocr = ocr_card; + mmc_fixup_device(card, NULL); + + if (card->type == MMC_TYPE_SD_COMBO) { +@@ -492,29 +785,36 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, + if (err) + goto remove; + +- /* +- * Switch to high-speed (if supported). +- */ +- err = sdio_enable_hs(card); +- if (err > 0) +- mmc_sd_go_highspeed(card); +- else if (err) +- goto remove; +- +- /* +- * Change to the card's maximum speed. +- */ +- mmc_set_clock(host, mmc_sdio_get_max_clock(card)); ++ /* Initialization sequence for UHS-I cards */ ++ /* Only if card supports 1.8v and UHS signaling */ ++ if ((ocr & R4_18V_PRESENT) && card->sw_caps.sd3_bus_mode) { ++ err = mmc_sdio_init_uhs_card(card); ++ if (err) ++ goto remove; ++ } else { ++ /* ++ * Switch to high-speed (if supported). ++ */ ++ err = sdio_enable_hs(card); ++ if (err > 0) ++ mmc_set_timing(card->host, MMC_TIMING_SD_HS); ++ else if (err) ++ goto remove; + +- /* +- * Switch to wider bus (if supported). +- */ +- err = sdio_enable_4bit_bus(card); +- if (err > 0) +- mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); +- else if (err) +- goto remove; ++ /* ++ * Change to the card's maximum speed. ++ */ ++ mmc_set_clock(host, mmc_sdio_get_max_clock(card)); + ++ /* ++ * Switch to wider bus (if supported). ++ */ ++ err = sdio_enable_4bit_bus(card); ++ if (err > 0) ++ mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); ++ else if (err) ++ goto remove; ++ } + finish: + if (!oldcard) + host->card = card; +@@ -550,6 +850,14 @@ static void mmc_sdio_remove(struct mmc_host *host) + } + + /* ++ * Card detection - card is alive. ++ */ ++static int mmc_sdio_alive(struct mmc_host *host) ++{ ++ return mmc_select_card(host->card); ++} ++ ++/* + * Card detection callback from host. + */ + static void mmc_sdio_detect(struct mmc_host *host) +@@ -562,8 +870,10 @@ static void mmc_sdio_detect(struct mmc_host *host) + /* Make sure card is powered before detecting it */ + if (host->caps & MMC_CAP_POWER_OFF_CARD) { + err = pm_runtime_get_sync(&host->card->dev); +- if (err < 0) ++ if (err < 0) { ++ pm_runtime_put_noidle(&host->card->dev); + goto out; ++ } + } + + mmc_claim_host(host); +@@ -571,7 +881,7 @@ static void mmc_sdio_detect(struct mmc_host *host) + /* + * Just check if our card has been removed. + */ +- err = mmc_select_card(host->card); ++ err = _mmc_detect_card_removed(host); + + mmc_release_host(host); + +@@ -601,11 +911,11 @@ out: + } + + /* +- * SDIO suspend. We need to suspend all functions separately. ++ * SDIO pre_suspend. We need to suspend all functions separately. + * Therefore all registered functions must have drivers with suspend + * and resume methods. Failing that we simply remove the whole card. + */ +-static int mmc_sdio_suspend(struct mmc_host *host) ++static int mmc_sdio_pre_suspend(struct mmc_host *host) + { + int i, err = 0; + +@@ -616,32 +926,34 @@ static int mmc_sdio_suspend(struct mmc_host *host) + if (!pmops || !pmops->suspend || !pmops->resume) { + /* force removal of entire card in that case */ + err = -ENOSYS; +- } else +- err = pmops->suspend(&func->dev); +- if (err) + break; ++ } + } + } +- while (err && --i >= 0) { +- struct sdio_func *func = host->card->sdio_func[i]; +- if (func && sdio_func_present(func) && func->dev.driver) { +- const struct dev_pm_ops *pmops = func->dev.driver->pm; +- pmops->resume(&func->dev); +- } +- } + +- if (!err && mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { ++ return err; ++} ++ ++/* ++ * SDIO suspend. Suspend all functions separately. ++ */ ++static int mmc_sdio_suspend(struct mmc_host *host) ++{ ++ if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { + mmc_claim_host(host); + sdio_disable_wide(host->card); + mmc_release_host(host); + } + +- return err; ++ if (!mmc_card_keep_power(host)) ++ mmc_power_off(host); ++ ++ return 0; + } + + static int mmc_sdio_resume(struct mmc_host *host) + { +- int i, err = 0; ++ int err = 0; + + BUG_ON(!host); + BUG_ON(!host->card); +@@ -649,11 +961,29 @@ static int mmc_sdio_resume(struct mmc_host *host) + /* Basic card reinitialization. */ + mmc_claim_host(host); + ++ /* Restore power if needed */ ++ if (!mmc_card_keep_power(host)) { ++ mmc_power_up(host, host->card->ocr); ++ /* ++ * Tell runtime PM core we just powered up the card, ++ * since it still believes the card is powered off. ++ * Note that currently runtime PM is only enabled ++ * for SDIO cards that are MMC_CAP_POWER_OFF_CARD ++ */ ++ if (host->caps & MMC_CAP_POWER_OFF_CARD) { ++ pm_runtime_disable(&host->card->dev); ++ pm_runtime_set_active(&host->card->dev); ++ pm_runtime_enable(&host->card->dev); ++ } ++ } ++ + /* No need to reinitialize powered-resumed nonremovable cards */ +- if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) +- err = mmc_sdio_init_card(host, host->ocr, host->card, ++ if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) { ++ sdio_reset(host); ++ mmc_go_idle(host); ++ err = mmc_sdio_init_card(host, host->card->ocr, host->card, + mmc_card_keep_power(host)); +- else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { ++ } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { + /* We may have switched to 1-bit mode during suspend */ + err = sdio_enable_4bit_bus(host->card); + if (err > 0) { +@@ -666,31 +996,13 @@ static int mmc_sdio_resume(struct mmc_host *host) + wake_up_process(host->sdio_irq_thread); + mmc_release_host(host); + +- /* +- * If the card looked to be the same as before suspending, then +- * we proceed to resume all card functions. If one of them returns +- * an error then we simply return that error to the core and the +- * card will be redetected as new. It is the responsibility of +- * the function driver to perform further tests with the extra +- * knowledge it has of the card to confirm the card is indeed the +- * same as before suspending (same MAC address for network cards, +- * etc.) and return an error otherwise. +- */ +- for (i = 0; !err && i < host->card->sdio_funcs; i++) { +- struct sdio_func *func = host->card->sdio_func[i]; +- if (func && sdio_func_present(func) && func->dev.driver) { +- const struct dev_pm_ops *pmops = func->dev.driver->pm; +- err = pmops->resume(&func->dev); +- } +- } +- ++ host->pm_flags &= ~MMC_PM_KEEP_POWER; + return err; + } + + static int mmc_sdio_power_restore(struct mmc_host *host) + { + int ret; +- u32 ocr; + + BUG_ON(!host); + BUG_ON(!host->card); +@@ -712,27 +1024,17 @@ static int mmc_sdio_power_restore(struct mmc_host *host) + * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and + * harmless in other situations. + * +- * With these steps taken, mmc_select_voltage() is also required to +- * restore the correct voltage setting of the card. + */ ++ + sdio_reset(host); + mmc_go_idle(host); + mmc_send_if_cond(host, host->ocr_avail); + +- ret = mmc_send_io_op_cond(host, 0, &ocr); ++ ret = mmc_send_io_op_cond(host, 0, NULL); + if (ret) + goto out; + +- if (host->ocr_avail_sdio) +- host->ocr_avail = host->ocr_avail_sdio; +- +- host->ocr = mmc_select_voltage(host, ocr & ~0x7F); +- if (!host->ocr) { +- ret = -EINVAL; +- goto out; +- } +- +- ret = mmc_sdio_init_card(host, host->ocr, host->card, ++ ret = mmc_sdio_init_card(host, host->card->ocr, host->card, + mmc_card_keep_power(host)); + if (!ret && host->sdio_irqs) + mmc_signal_sdio_irq(host); +@@ -743,12 +1045,30 @@ out: + return ret; + } + ++static int mmc_sdio_runtime_suspend(struct mmc_host *host) ++{ ++ /* No references to the card, cut the power to it. */ ++ mmc_power_off(host); ++ return 0; ++} ++ ++static int mmc_sdio_runtime_resume(struct mmc_host *host) ++{ ++ /* Restore power and re-initialize. */ ++ mmc_power_up(host, host->card->ocr); ++ return mmc_sdio_power_restore(host); ++} ++ + static const struct mmc_bus_ops mmc_sdio_ops = { + .remove = mmc_sdio_remove, + .detect = mmc_sdio_detect, ++ .pre_suspend = mmc_sdio_pre_suspend, + .suspend = mmc_sdio_suspend, + .resume = mmc_sdio_resume, ++ .runtime_suspend = mmc_sdio_runtime_suspend, ++ .runtime_resume = mmc_sdio_runtime_resume, + .power_restore = mmc_sdio_power_restore, ++ .alive = mmc_sdio_alive, + }; + + +@@ -758,7 +1078,7 @@ static const struct mmc_bus_ops mmc_sdio_ops = { + int mmc_attach_sdio(struct mmc_host *host) + { + int err, i, funcs; +- u32 ocr; ++ u32 ocr, rocr; + struct mmc_card *card; + + BUG_ON(!host); +@@ -772,23 +1092,13 @@ int mmc_attach_sdio(struct mmc_host *host) + if (host->ocr_avail_sdio) + host->ocr_avail = host->ocr_avail_sdio; + +- /* +- * Sanity check the voltages that the card claims to +- * support. +- */ +- if (ocr & 0x7F) { +- pr_warning("%s: card claims to support voltages " +- "below the defined range. These will be ignored.\n", +- mmc_hostname(host)); +- ocr &= ~0x7F; +- } + +- host->ocr = mmc_select_voltage(host, ocr); ++ rocr = mmc_select_voltage(host, ocr); + + /* + * Can we support the voltage(s) of the card(s)? + */ +- if (!host->ocr) { ++ if (!rocr) { + err = -EINVAL; + goto err; + } +@@ -796,9 +1106,10 @@ int mmc_attach_sdio(struct mmc_host *host) + /* + * Detect and init the card. + */ +- err = mmc_sdio_init_card(host, host->ocr, NULL, 0); ++ err = mmc_sdio_init_card(host, rocr, NULL, 0); + if (err) + goto err; ++ + card = host->card; + + /* +diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c +index 40989e6..a8d12ec 100644 +--- a/drivers/mmc/core/sdio_bus.c ++++ b/drivers/mmc/core/sdio_bus.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -137,7 +138,7 @@ static int sdio_bus_probe(struct device *dev) + if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) { + ret = pm_runtime_get_sync(dev); + if (ret < 0) +- goto out; ++ goto disable_runtimepm; + } + + /* Set the default block size so the driver is sure it's something +@@ -157,7 +158,6 @@ static int sdio_bus_probe(struct device *dev) + disable_runtimepm: + if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) + pm_runtime_put_noidle(dev); +-out: + return ret; + } + +@@ -192,23 +192,24 @@ static int sdio_bus_remove(struct device *dev) + return ret; + } + +-#ifdef CONFIG_PM_RUNTIME ++#ifdef CONFIG_PM + + static const struct dev_pm_ops sdio_bus_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume) + SET_RUNTIME_PM_OPS( + pm_generic_runtime_suspend, + pm_generic_runtime_resume, +- pm_generic_runtime_idle ++ NULL + ) + }; + + #define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops) + +-#else /* !CONFIG_PM_RUNTIME */ ++#else /* !CONFIG_PM */ + + #define SDIO_PM_OPS_PTR NULL + +-#endif /* !CONFIG_PM_RUNTIME */ ++#endif /* !CONFIG_PM */ + + static struct bus_type sdio_bus_type = { + .name = "sdio", +@@ -259,8 +260,7 @@ static void sdio_release_func(struct device *dev) + + sdio_free_func_cis(func); + +- if (func->info) +- kfree(func->info); ++ kfree(func->info); + + kfree(func); + } +@@ -287,6 +287,12 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card) + return func; + } + ++#ifdef CONFIG_ACPI ++static void sdio_acpi_set_handle(struct sdio_func *func) {} ++#else ++static inline void sdio_acpi_set_handle(struct sdio_func *func) {} ++#endif ++ + /* + * Register a new SDIO function with the driver model. + */ +@@ -296,9 +302,12 @@ int sdio_add_func(struct sdio_func *func) + + dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num); + ++ // sdio_acpi_set_handle(func); + ret = device_add(&func->dev); +- if (ret == 0) ++ if (ret == 0) { + sdio_func_set_present(func); ++ // acpi_dev_pm_attach(&func->dev, false); ++ } + + return ret; + } +@@ -314,6 +323,7 @@ void sdio_remove_func(struct sdio_func *func) + if (!sdio_func_present(func)) + return; + ++ // acpi_dev_pm_detach(&func->dev, false); + device_del(&func->dev); + put_device(&func->dev); + } +diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c +index b1f3168..78cb4d5 100644 +--- a/drivers/mmc/core/sdio_io.c ++++ b/drivers/mmc/core/sdio_io.c +@@ -188,14 +188,16 @@ EXPORT_SYMBOL_GPL(sdio_set_block_size); + */ + static inline unsigned int sdio_max_byte_size(struct sdio_func *func) + { +- unsigned mval = min(func->card->host->max_seg_size, +- func->card->host->max_blk_size); ++ unsigned mval = func->card->host->max_blk_size; + + if (mmc_blksz_for_byte_mode(func->card)) + mval = min(mval, func->cur_blksize); + else + mval = min(mval, func->max_blksize); + ++ if (mmc_card_broken_byte_mode_512(func->card)) ++ return min(mval, 511u); ++ + return min(mval, 512u); /* maximum size for byte mode */ + } + +@@ -308,13 +310,10 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write, + /* Do the bulk of the transfer using block mode (if supported). */ + if (func->card->cccr.multi_block && (size > sdio_max_byte_size(func))) { + /* Blocks per command is limited by host count, host transfer +- * size (we only use a single sg entry) and the maximum for +- * IO_RW_EXTENDED of 511 blocks. */ +- max_blocks = min(func->card->host->max_blk_count, +- func->card->host->max_seg_size / func->cur_blksize); +- max_blocks = min(max_blocks, 511u); ++ * size and the maximum for IO_RW_EXTENDED of 511 blocks. */ ++ max_blocks = min(func->card->host->max_blk_count, 511u); + +- while (remainder > func->cur_blksize) { ++ while (remainder >= func->cur_blksize) { + unsigned blocks; + + blocks = remainder / func->cur_blksize; +@@ -339,8 +338,9 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write, + while (remainder > 0) { + size = min(remainder, sdio_max_byte_size(func)); + ++ /* Indicate byte mode by setting "blocks" = 0 */ + ret = mmc_io_rw_extended(func->card, write, func->num, addr, +- incr_addr, buf, 1, size); ++ incr_addr, buf, 0, size); + if (ret) + return ret; + +diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c +index 9dd0462..5cc13c8 100644 +--- a/drivers/mmc/core/sdio_irq.c ++++ b/drivers/mmc/core/sdio_irq.c +@@ -53,6 +53,17 @@ static int process_sdio_pending_irqs(struct mmc_host *host) + return ret; + } + ++ if (pending && mmc_card_broken_irq_polling(card) && ++ !(host->caps & MMC_CAP_SDIO_IRQ)) { ++ unsigned char dummy; ++ ++ /* A fake interrupt could be created when we poll SDIO_CCCR_INTx ++ * register with a Marvell SD8797 card. A dummy CMD52 read to ++ * function 0 register 0xff can avoid this. ++ */ ++ mmc_io_rw_direct(card, 0, 0, 0xff, 0, &dummy); ++ } ++ + count = 0; + for (i = 1; i <= 7; i++) { + if (pending & (1 << i)) { +@@ -79,6 +90,15 @@ static int process_sdio_pending_irqs(struct mmc_host *host) + return ret; + } + ++void sdio_run_irqs(struct mmc_host *host) ++{ ++ mmc_claim_host(host); ++ host->sdio_irq_pending = true; ++ process_sdio_pending_irqs(host); ++ mmc_release_host(host); ++} ++EXPORT_SYMBOL_GPL(sdio_run_irqs); ++ + static int sdio_irq_thread(void *_host) + { + struct mmc_host *host = _host; +@@ -149,15 +169,21 @@ static int sdio_irq_thread(void *_host) + } + + set_current_state(TASK_INTERRUPTIBLE); +- if (host->caps & MMC_CAP_SDIO_IRQ) ++ if (host->caps & MMC_CAP_SDIO_IRQ) { ++ mmc_host_clk_hold(host); + host->ops->enable_sdio_irq(host, 1); ++ mmc_host_clk_release(host); ++ } + if (!kthread_should_stop()) + schedule_timeout(period); + set_current_state(TASK_RUNNING); + } while (!kthread_should_stop()); + +- if (host->caps & MMC_CAP_SDIO_IRQ) ++ if (host->caps & MMC_CAP_SDIO_IRQ) { ++ mmc_host_clk_hold(host); + host->ops->enable_sdio_irq(host, 0); ++ mmc_host_clk_release(host); ++ } + + pr_debug("%s: IRQ thread exiting with code %d\n", + mmc_hostname(host), ret); +@@ -172,14 +198,20 @@ static int sdio_card_irq_get(struct mmc_card *card) + WARN_ON(!host->claimed); + + if (!host->sdio_irqs++) { +- atomic_set(&host->sdio_irq_thread_abort, 0); +- host->sdio_irq_thread = +- kthread_run(sdio_irq_thread, host, "ksdioirqd/%s", +- mmc_hostname(host)); +- if (IS_ERR(host->sdio_irq_thread)) { +- int err = PTR_ERR(host->sdio_irq_thread); +- host->sdio_irqs--; +- return err; ++ if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) { ++ atomic_set(&host->sdio_irq_thread_abort, 0); ++ host->sdio_irq_thread = ++ kthread_run(sdio_irq_thread, host, ++ "ksdioirqd/%s", mmc_hostname(host)); ++ if (IS_ERR(host->sdio_irq_thread)) { ++ int err = PTR_ERR(host->sdio_irq_thread); ++ host->sdio_irqs--; ++ return err; ++ } ++ } else { ++ mmc_host_clk_hold(host); ++ host->ops->enable_sdio_irq(host, 1); ++ mmc_host_clk_release(host); + } + } + +@@ -194,8 +226,14 @@ static int sdio_card_irq_put(struct mmc_card *card) + BUG_ON(host->sdio_irqs < 1); + + if (!--host->sdio_irqs) { +- atomic_set(&host->sdio_irq_thread_abort, 1); +- kthread_stop(host->sdio_irq_thread); ++ if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) { ++ atomic_set(&host->sdio_irq_thread_abort, 1); ++ kthread_stop(host->sdio_irq_thread); ++ } else { ++ mmc_host_clk_hold(host); ++ host->ops->enable_sdio_irq(host, 0); ++ mmc_host_clk_release(host); ++ } + } + + return 0; +diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c +index b0517cc..62508b4 100644 +--- a/drivers/mmc/core/sdio_ops.c ++++ b/drivers/mmc/core/sdio_ops.c +@@ -124,12 +124,13 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, + struct mmc_request mrq = {NULL}; + struct mmc_command cmd = {0}; + struct mmc_data data = {0}; +- struct scatterlist sg; ++ struct scatterlist sg, *sg_ptr; ++ struct sg_table sgtable; ++ unsigned int nents, left_size, i; ++ unsigned int seg_size = card->host->max_seg_size; + + BUG_ON(!card); + BUG_ON(fn > 7); +- BUG_ON(blocks == 1 && blksz > 512); +- WARN_ON(blocks == 0); + WARN_ON(blksz == 0); + + /* sanity check */ +@@ -144,27 +145,46 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, + cmd.arg |= fn << 28; + cmd.arg |= incr_addr ? 0x04000000 : 0x00000000; + cmd.arg |= addr << 9; +- if (blocks == 1 && blksz < 512) +- cmd.arg |= blksz; /* byte mode */ +- else if (blocks == 1 && blksz == 512 && +- !(mmc_card_broken_byte_mode_512(card))) +- cmd.arg |= 0; /* byte mode, 0==512 */ ++ if (blocks == 0) ++ cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */ + else + cmd.arg |= 0x08000000 | blocks; /* block mode */ + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + + data.blksz = blksz; +- data.blocks = blocks; ++ /* Code in host drivers/fwk assumes that "blocks" always is >=1 */ ++ data.blocks = blocks ? blocks : 1; + data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; +- data.sg = &sg; +- data.sg_len = 1; + +- sg_init_one(&sg, buf, blksz * blocks); ++ left_size = data.blksz * data.blocks; ++ nents = (left_size - 1) / seg_size + 1; ++ if (nents > 1) { ++ if (sg_alloc_table(&sgtable, nents, GFP_KERNEL)) ++ return -ENOMEM; ++ ++ data.sg = sgtable.sgl; ++ data.sg_len = nents; ++ ++ for_each_sg(data.sg, sg_ptr, data.sg_len, i) { ++ sg_set_page(sg_ptr, virt_to_page(buf + (i * seg_size)), ++ min(seg_size, left_size), ++ offset_in_page(buf + (i * seg_size))); ++ left_size = left_size - seg_size; ++ } ++ } else { ++ data.sg = &sg; ++ data.sg_len = 1; ++ ++ sg_init_one(&sg, buf, left_size); ++ } + + mmc_set_data_timeout(&data, card); + + mmc_wait_for_req(card->host, &mrq); + ++ if (nents > 1) ++ sg_free_table(&sgtable); ++ + if (cmd.error) + return cmd.error; + if (data.error) +diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c +new file mode 100644 +index 0000000..16a1c0b +--- /dev/null ++++ b/drivers/mmc/core/slot-gpio.c +@@ -0,0 +1,200 @@ ++/* ++ * Generic GPIO card-detect helper ++ * ++ * Copyright (C) 2011, Guennadi Liakhovetski ++ * ++ * 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 ++ ++struct mmc_gpio { ++ int ro_gpio; ++ int cd_gpio; ++ char *ro_label; ++ char cd_label[0]; ++}; ++ ++static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) ++{ ++ /* Schedule a card detection after a debounce timeout */ ++ struct mmc_host *host = dev_id; ++ ++ if (host->ops->card_event) ++ host->ops->card_event(host); ++ ++ mmc_detect_change(host, msecs_to_jiffies(200)); ++ ++ return IRQ_HANDLED; ++} ++ ++static int mmc_gpio_alloc(struct mmc_host *host) ++{ ++ size_t len = strlen(dev_name(host->parent)) + 4; ++ struct mmc_gpio *ctx; ++ ++ mutex_lock(&host->slot.lock); ++ ++ ctx = host->slot.handler_priv; ++ if (!ctx) { ++ /* ++ * devm_kzalloc() can be called after device_initialize(), even ++ * before device_add(), i.e., between mmc_alloc_host() and ++ * mmc_add_host() ++ */ ++ ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len, ++ GFP_KERNEL); ++ if (ctx) { ++ ctx->ro_label = ctx->cd_label + len; ++ snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); ++ snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent)); ++ ctx->cd_gpio = -EINVAL; ++ ctx->ro_gpio = -EINVAL; ++ host->slot.handler_priv = ctx; ++ } ++ } ++ ++ mutex_unlock(&host->slot.lock); ++ ++ return ctx ? 0 : -ENOMEM; ++} ++ ++int mmc_gpio_get_ro(struct mmc_host *host) ++{ ++ struct mmc_gpio *ctx = host->slot.handler_priv; ++ ++ if (!ctx || !gpio_is_valid(ctx->ro_gpio)) ++ return -ENOSYS; ++ ++ return !gpio_get_value_cansleep(ctx->ro_gpio) ^ ++ !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH); ++} ++EXPORT_SYMBOL(mmc_gpio_get_ro); ++ ++int mmc_gpio_get_cd(struct mmc_host *host) ++{ ++ struct mmc_gpio *ctx = host->slot.handler_priv; ++ ++ if (!ctx || !gpio_is_valid(ctx->cd_gpio)) ++ return -ENOSYS; ++ ++ return !gpio_get_value_cansleep(ctx->cd_gpio) ^ ++ !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH); ++} ++EXPORT_SYMBOL(mmc_gpio_get_cd); ++ ++int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) ++{ ++ struct mmc_gpio *ctx; ++ int ret; ++ ++ if (!gpio_is_valid(gpio)) ++ return -EINVAL; ++ ++ ret = mmc_gpio_alloc(host); ++ if (ret < 0) ++ return ret; ++ ++ ctx = host->slot.handler_priv; ++ ++ ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label); ++ if (ret < 0) ++ return ret; ++ ++ ctx->ro_gpio = gpio; ++ ++ return 0; ++} ++EXPORT_SYMBOL(mmc_gpio_request_ro); ++ ++int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) ++{ ++ struct mmc_gpio *ctx; ++ int irq = gpio_to_irq(gpio); ++ int ret; ++ ++ ret = mmc_gpio_alloc(host); ++ if (ret < 0) ++ return ret; ++ ++ ctx = host->slot.handler_priv; ++ ++ ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label); ++ if (ret < 0) ++ /* ++ * don't bother freeing memory. It might still get used by other ++ * slot functions, in any case it will be freed, when the device ++ * is destroyed. ++ */ ++ return ret; ++ ++ /* ++ * Even if gpio_to_irq() returns a valid IRQ number, the platform might ++ * still prefer to poll, e.g., because that IRQ number is already used ++ * by another unit and cannot be shared. ++ */ ++ if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL) ++ irq = -EINVAL; ++ ++ if (irq >= 0) { ++ ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt, ++ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ++ ctx->cd_label, host); ++ if (ret < 0) ++ irq = ret; ++ } ++ ++ host->slot.cd_irq = irq; ++ ++ if (irq < 0) ++ host->caps |= MMC_CAP_NEEDS_POLL; ++ ++ ctx->cd_gpio = gpio; ++ ++ return 0; ++} ++EXPORT_SYMBOL(mmc_gpio_request_cd); ++ ++void mmc_gpio_free_ro(struct mmc_host *host) ++{ ++ struct mmc_gpio *ctx = host->slot.handler_priv; ++ int gpio; ++ ++ if (!ctx || !gpio_is_valid(ctx->ro_gpio)) ++ return; ++ ++ gpio = ctx->ro_gpio; ++ ctx->ro_gpio = -EINVAL; ++ ++ gpio_free(gpio); ++} ++EXPORT_SYMBOL(mmc_gpio_free_ro); ++ ++void mmc_gpio_free_cd(struct mmc_host *host) ++{ ++ struct mmc_gpio *ctx = host->slot.handler_priv; ++ int gpio; ++ ++ if (!ctx || !gpio_is_valid(ctx->cd_gpio)) ++ return; ++ ++ if (host->slot.cd_irq >= 0) { ++ free_irq(host->slot.cd_irq, host); ++ host->slot.cd_irq = -EINVAL; ++ } ++ ++ gpio = ctx->cd_gpio; ++ ctx->cd_gpio = -EINVAL; ++ ++ gpio_free(gpio); ++} ++EXPORT_SYMBOL(mmc_gpio_free_cd); +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 90233ad..3a8d690 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -69,7 +69,7 @@ config MMC_SDHCI_PCI + If unsure, say N. + + config MMC_RICOH_MMC +- bool "Ricoh MMC Controller Disabler (EXPERIMENTAL)" ++ bool "Ricoh MMC Controller Disabler" + depends on MMC_SDHCI_PCI + help + This adds a pci quirk to disable Ricoh MMC Controller. This +@@ -81,10 +81,22 @@ config MMC_RICOH_MMC + + If unsure, say Y. + ++config MMC_SDHCI_ACPI ++ tristate "SDHCI support for ACPI enumerated SDHCI controllers" ++ depends on MMC_SDHCI && ACPI ++ help ++ This selects support for ACPI enumerated SDHCI controllers, ++ identified by ACPI Compatibility ID PNP0D40 or specific ++ ACPI Hardware IDs. ++ ++ If you have a controller with this interface, say Y or M here. ++ ++ If unsure, say N. ++ + config MMC_SDHCI_PLTFM + tristate "SDHCI platform and OF driver helper" + depends on MMC_SDHCI +- help ++ help + This selects the common helper functions support for Secure Digital + Host Controller Interface based platform and OF drivers. + +@@ -92,6 +104,18 @@ config MMC_SDHCI_PLTFM + + If unsure, say N. + ++config MMC_SDHCI_OF_ARASAN ++ tristate "SDHCI OF support for the Arasan SDHCI controllers" ++ depends on MMC_SDHCI_PLTFM ++ depends on OF ++ help ++ This selects the Arasan Secure Digital Host Controller Interface ++ (SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC. ++ ++ If you have a controller with this interface, say Y or M here. ++ ++ If unsure, say N. ++ + config MMC_SDHCI_OF_ESDHC + tristate "SDHCI OF support for the Freescale eSDHC controller" + depends on MMC_SDHCI_PLTFM +@@ -144,7 +168,7 @@ config MMC_SDHCI_ESDHC_IMX + + config MMC_SDHCI_DOVE + tristate "SDHCI support on Marvell's Dove SoC" +- depends on ARCH_DOVE ++ depends on ARCH_DOVE || MACH_DOVE + depends on MMC_SDHCI_PLTFM + select MMC_SDHCI_IO_ACCESSORS + help +@@ -174,8 +198,16 @@ config MMC_SDHCI_S3C + often referrered to as the HSMMC block in some of the Samsung S3C + range of SoC. + +- Note, due to the problems with DMA, the DMA support is only +- available with CONFIG_EXPERIMENTAL is selected. ++ If you have a controller with this interface, say Y or M here. ++ ++ If unsure, say N. ++ ++config MMC_SDHCI_SIRF ++ tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs" ++ depends on ARCH_SIRF ++ depends on MMC_SDHCI_PLTFM ++ help ++ This selects the SDHCI support for SiRF System-on-Chip devices. + + If you have a controller with this interface, say Y or M here. + +@@ -184,8 +216,7 @@ config MMC_SDHCI_S3C + config MMC_SDHCI_PXAV3 + tristate "Marvell MMP2 SD Host Controller support (PXAV3)" + depends on CLKDEV_LOOKUP +- select MMC_SDHCI +- select MMC_SDHCI_PLTFM ++ depends on MMC_SDHCI_PLTFM + default CPU_MMP2 + help + This selects the Marvell(R) PXAV3 SD Host Controller. +@@ -197,8 +228,7 @@ config MMC_SDHCI_PXAV3 + config MMC_SDHCI_PXAV2 + tristate "Marvell PXA9XX SD Host Controller support (PXAV2)" + depends on CLKDEV_LOOKUP +- select MMC_SDHCI +- select MMC_SDHCI_PLTFM ++ depends on MMC_SDHCI_PLTFM + default CPU_PXA910 + help + This selects the Marvell(R) PXAV2 SD Host Controller. +@@ -221,7 +251,7 @@ config MMC_SDHCI_SPEAR + + config MMC_SDHCI_S3C_DMA + bool "DMA support on S3C SDHCI" +- depends on MMC_SDHCI_S3C && EXPERIMENTAL ++ depends on MMC_SDHCI_S3C + help + Enable DMA support on the Samsung S3C SDHCI glue. The DMA + has proved to be problematic if the controller encounters +@@ -229,10 +259,41 @@ config MMC_SDHCI_S3C_DMA + + YMMV. + ++config MMC_SDHCI_BCM_KONA ++ tristate "SDHCI support on Broadcom KONA platform" ++ depends on ARCH_BCM_MOBILE ++ depends on MMC_SDHCI_PLTFM ++ help ++ This selects the Broadcom Kona Secure Digital Host Controller ++ Interface(SDHCI) support. ++ This is used in Broadcom mobile SoCs. ++ ++ If you have a controller with this interface, say Y or M here. ++ ++config MMC_SDHCI_BCM2835 ++ tristate "SDHCI platform support for the BCM2835 SD/MMC Controller" ++ depends on ARCH_BCM2835 ++ depends on MMC_SDHCI_PLTFM ++ select MMC_SDHCI_IO_ACCESSORS ++ help ++ This selects the BCM2835 SD/MMC controller. If you have a BCM2835 ++ platform with SD or MMC devices, say Y or M here. ++ ++ If unsure, say N. ++ ++config MMC_MOXART ++ tristate "MOXART SD/MMC Host Controller support" ++ depends on ARCH_MOXART && MMC ++ help ++ This selects support for the MOXART SD/MMC Host Controller. ++ MOXA provides one multi-functional card reader which can ++ be found on some embedded hardware such as UC-7112-LX. ++ If you have a controller with this interface, say Y here. ++ + config MMC_OMAP + tristate "TI OMAP Multimedia Card Interface support" + depends on ARCH_OMAP +- select TPS65010 if MACH_OMAP_H2 ++ depends on TPS65010 || !MACH_OMAP_H2 + help + This selects the TI OMAP Multimedia card Interface. + If you have an OMAP board with a Multimedia Card slot, +@@ -242,11 +303,11 @@ config MMC_OMAP + + config MMC_OMAP_HS + tristate "TI OMAP High Speed Multimedia Card Interface support" +- depends on SOC_OMAP2430 || ARCH_OMAP3 || ARCH_OMAP4 ++ depends on ARCH_OMAP2PLUS || COMPILE_TEST + help + This selects the TI OMAP High Speed Multimedia card Interface. +- If you have an OMAP2430 or OMAP3 board or OMAP4 board with a +- Multimedia Card slot, say Y or M here. ++ If you have an omap2plus board with a Multimedia Card slot, ++ say Y or M here. + + If unsure, say N. + +@@ -270,23 +331,8 @@ config MMC_AU1X + + If unsure, say N. + +-choice +- prompt "Atmel SD/MMC Driver" +- depends on AVR32 || ARCH_AT91 +- default MMC_ATMELMCI if AVR32 +- help +- Choose which driver to use for the Atmel MCI Silicon +- +-config MMC_AT91 +- tristate "AT91 SD/MMC Card Interface support" +- depends on ARCH_AT91 +- help +- This selects the AT91 MCI controller. +- +- If unsure, say N. +- + config MMC_ATMELMCI +- tristate "Atmel Multimedia Card Interface support" ++ tristate "Atmel SD/MMC Driver (Multimedia Card Interface)" + depends on AVR32 || ARCH_AT91 + help + This selects the Atmel Multimedia Card Interface driver. If +@@ -295,33 +341,34 @@ config MMC_ATMELMCI + + If unsure, say N. + +-endchoice +- +-config MMC_IMX +- tristate "Motorola i.MX Multimedia Card Interface support" +- depends on ARCH_MX1 ++config MMC_SDHCI_MSM ++ tristate "Qualcomm SDHCI Controller Support" ++ depends on ARCH_QCOM ++ depends on MMC_SDHCI_PLTFM + help +- This selects the Motorola i.MX Multimedia card Interface. +- If you have a i.MX platform with a Multimedia Card slot, +- say Y or M here. ++ This selects the Secure Digital Host Controller Interface (SDHCI) ++ support present in Qualcomm SOCs. The controller supports ++ SD/MMC/SDIO devices. ++ ++ If you have a controller with this interface, say Y or M here. + + If unsure, say N. + + config MMC_MSM + tristate "Qualcomm SDCC Controller Support" +- depends on MMC && ARCH_MSM ++ depends on MMC && (ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50) + help + This provides support for the SD/MMC cell found in the + MSM and QSD SOCs from Qualcomm. The controller also has + support for SDIO devices. + + config MMC_MXC +- tristate "Freescale i.MX21/27/31 Multimedia Card Interface support" +- depends on ARCH_MXC ++ tristate "Freescale i.MX21/27/31 or MPC512x Multimedia Card support" ++ depends on ARCH_MXC || PPC_MPC512x + help +- This selects the Freescale i.MX21, i.MX27 and i.MX31 Multimedia card +- Interface. If you have a i.MX platform with a Multimedia Card slot, +- say Y or M here. ++ This selects the Freescale i.MX21, i.MX27, i.MX31 or MPC512x ++ Multimedia Card Interface. If you have an i.MX or MPC512x platform ++ with a Multimedia Card slot, say Y or M here. + + If unsure, say N. + +@@ -335,8 +382,8 @@ config MMC_MXS + If unsure, say N. + + config MMC_TIFM_SD +- tristate "TI Flash Media MMC/SD Interface support (EXPERIMENTAL)" +- depends on EXPERIMENTAL && PCI ++ tristate "TI Flash Media MMC/SD Interface support" ++ depends on PCI + select TIFM_CORE + help + Say Y here if you want to be able to access MMC/SD cards with +@@ -369,6 +416,13 @@ config MMC_DAVINCI + If you have an DAVINCI board with a Multimedia Card slot, + say Y or M here. If unsure, say N. + ++config MMC_GOLDFISH ++ tristate "goldfish qemu Multimedia Card Interface support" ++ depends on GOLDFISH ++ help ++ This selects the Goldfish Multimedia card Interface emulation ++ found on the Goldfish Android virtual device emulation. ++ + config MMC_SPI + tristate "MMC/SD/SDIO over SPI" + depends on SPI_MASTER && !HIGHMEM && HAS_DMA +@@ -385,7 +439,7 @@ config MMC_SPI + + config MMC_S3C + tristate "Samsung S3C SD/MMC Card Interface support" +- depends on ARCH_S3C2410 ++ depends on ARCH_S3C24XX + help + This selects a driver for the MCI interface found in + Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs. +@@ -415,8 +469,7 @@ config MMC_S3C_PIO + the S3C MCI driver. + + config MMC_S3C_DMA +- bool "Use DMA transfers only (EXPERIMENTAL)" +- depends on EXPERIMENTAL ++ bool "Use DMA transfers only" + help + Use DMA to transfer data between memory and the hardare. + +@@ -425,7 +478,7 @@ config MMC_S3C_DMA + option is useful. + + config MMC_S3C_PIODMA +- bool "Support for both PIO and DMA (EXPERIMENTAL)" ++ bool "Support for both PIO and DMA" + help + Compile both the PIO and DMA transfer routines into the + driver and let the platform select at run-time which one +@@ -436,8 +489,8 @@ config MMC_S3C_PIODMA + endchoice + + config MMC_SDRICOH_CS +- tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)" +- depends on EXPERIMENTAL && PCI && PCMCIA ++ tristate "MMC/SD driver for Ricoh Bay1Controllers" ++ depends on PCI && PCMCIA + help + Say Y here if your Notebook reports a Ricoh Bay1Controller PCMCIA + card whenever you insert a MMC or SD card into the card slot. +@@ -458,7 +511,8 @@ config MMC_TMIO + + config MMC_SDHI + tristate "SH-Mobile SDHI SD/SDIO controller support" +- depends on SUPERH || ARCH_SHMOBILE ++ depends on SUPERH || ARM ++ depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST + select MMC_TMIO_CORE + help + This provides support for the SDHI SD/SDIO controller found in +@@ -467,7 +521,6 @@ config MMC_SDHI + config MMC_CB710 + tristate "ENE CB710 MMC/SD Interface support" + depends on PCI +- select MISC_DEVICES + select CB710_CORE + help + This option enables support for MMC/SD part of ENE CB710/720 Flash +@@ -510,7 +563,7 @@ config SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND + + config MMC_DW + tristate "Synopsys DesignWare Memory Card Interface" +- depends on ARM ++ depends on ARC || ARM + help + This selects support for the Synopsys DesignWare Mobile Storage IP + block, this provides host support for SD and MMC interfaces, in both +@@ -524,9 +577,54 @@ config MMC_DW_IDMAC + Designware Mobile Storage IP block. This disables the external DMA + interface. + ++config MMC_DW_PLTFM ++ tristate "Synopsys Designware MCI Support as platform device" ++ depends on MMC_DW ++ default y ++ help ++ This selects the common helper functions support for Host Controller ++ Interface based platform driver. Please select this option if the IP ++ is present as a platform device. This is the common interface for the ++ Synopsys Designware IP. ++ ++ If you have a controller with this interface, say Y or M here. ++ ++ If unsure, say Y. ++ ++config MMC_DW_EXYNOS ++ tristate "Exynos specific extensions for Synopsys DW Memory Card Interface" ++ depends on MMC_DW ++ select MMC_DW_PLTFM ++ help ++ This selects support for Samsung Exynos SoC specific extensions to the ++ Synopsys DesignWare Memory Card Interface driver. Select this option ++ for platforms based on Exynos4 and Exynos5 SoC's. ++ ++config MMC_DW_K3 ++ tristate "K3 specific extensions for Synopsys DW Memory Card Interface" ++ depends on MMC_DW ++ select MMC_DW_PLTFM ++ select MMC_DW_IDMAC ++ help ++ This selects support for Hisilicon K3 SoC specific extensions to the ++ Synopsys DesignWare Memory Card Interface driver. Select this option ++ for platforms based on Hisilicon K3 SoC's. ++ ++config MMC_DW_PCI ++ tristate "Synopsys Designware MCI support on PCI bus" ++ depends on MMC_DW && PCI ++ help ++ This selects the PCI bus for the Synopsys Designware Mobile Storage IP. ++ Select this option if the IP is present on PCI platform. ++ ++ If you have a controller with this interface, say Y or M here. ++ ++ If unsure, say N. ++ + config MMC_SH_MMCIF + tristate "SuperH Internal MMCIF support" +- depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE) ++ depends on MMC_BLOCK ++ depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST + help + This selects the MMC Host Interface controller (MMCIF). + +@@ -585,3 +683,35 @@ config MMC_USHC + + Note: These controllers only support SDIO cards and do not + support MMC or SD memory cards. ++ ++config MMC_WMT ++ tristate "Wondermedia SD/MMC Host Controller support" ++ depends on ARCH_VT8500 ++ default y ++ help ++ This selects support for the SD/MMC Host Controller on ++ Wondermedia WM8505/WM8650 based SoCs. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called wmt-sdmmc. ++ ++config MMC_REALTEK_PCI ++ tristate "Realtek PCI-E SD/MMC Card Interface Driver" ++ depends on MFD_RTSX_PCI ++ help ++ Say Y here to include driver code to support SD/MMC card interface ++ of Realtek PCI-E card reader ++ ++config MMC_REALTEK_USB ++ tristate "Realtek USB SD/MMC Card Interface Driver" ++ depends on MFD_RTSX_USB ++ help ++ Say Y here to include driver code to support SD/MMC card interface ++ of Realtek RTS5129/39 series card reader ++ ++config MMC_SUNXI ++ tristate "Allwinner sunxi SD/MMC Host Controller support" ++ depends on ARCH_SUNXI ++ help ++ This selects support for the SD/MMC Host Controller on ++ Allwinner sunxi SoCs. +diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +index b4b83f3..4d7797a 100644 +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -4,25 +4,28 @@ + + obj-$(CONFIG_MMC_ARMMMCI) += mmci.o + obj-$(CONFIG_MMC_PXA) += pxamci.o +-obj-$(CONFIG_MMC_IMX) += imxmmc.o + obj-$(CONFIG_MMC_MXC) += mxcmmc.o + obj-$(CONFIG_MMC_MXS) += mxs-mmc.o + obj-$(CONFIG_MMC_SDHCI) += sdhci.o + obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o ++obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o ++obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-o2micro.o ++obj-$(CONFIG_MMC_SDHCI_ACPI) += sdhci-acpi.o + obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o + obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o + obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o ++obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o + obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o + obj-$(CONFIG_MMC_WBSD) += wbsd.o + obj-$(CONFIG_MMC_AU1X) += au1xmmc.o + obj-$(CONFIG_MMC_OMAP) += omap.o + obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o +-obj-$(CONFIG_MMC_AT91) += at91_mci.o + obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o + obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o + obj-$(CONFIG_MMC_MSM) += msm_sdcc.o + obj-$(CONFIG_MMC_MVSDIO) += mvsdio.o + obj-$(CONFIG_MMC_DAVINCI) += davinci_mmc.o ++obj-$(CONFIG_MMC_GOLDFISH) += android-goldfish.o + obj-$(CONFIG_MMC_SPI) += mmc_spi.o + ifeq ($(CONFIG_OF),y) + obj-$(CONFIG_MMC_SPI) += of_mmc_spi.o +@@ -38,18 +41,32 @@ obj-$(CONFIG_MMC_CB710) += cb710-mmc.o + obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o + obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o + obj-$(CONFIG_MMC_DW) += dw_mmc.o ++obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o ++obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o ++obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o ++obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o + obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o + obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o + obj-$(CONFIG_MMC_VUB300) += vub300.o + obj-$(CONFIG_MMC_USHC) += ushc.o ++obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o ++obj-$(CONFIG_MMC_MOXART) += moxart-mmc.o ++obj-$(CONFIG_MMC_SUNXI) += sunxi-mmc.o ++ ++obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o ++obj-$(CONFIG_MMC_REALTEK_USB) += rtsx_usb_sdmmc.o + + obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o + obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o + obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o + obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o + obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o ++obj-$(CONFIG_MMC_SDHCI_OF_ARASAN) += sdhci-of-arasan.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_BCM_KONA) += sdhci-bcm-kona.o ++obj-$(CONFIG_MMC_SDHCI_BCM2835) += sdhci-bcm2835.o ++obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o + + ifeq ($(CONFIG_CB710_DEBUG),y) + CFLAGS-cb710-mmc += -DDEBUG +diff --git a/drivers/mmc/host/android-goldfish.c b/drivers/mmc/host/android-goldfish.c +new file mode 100644 +index 0000000..8b4e20a +--- /dev/null ++++ b/drivers/mmc/host/android-goldfish.c +@@ -0,0 +1,568 @@ ++/* ++ * Copyright 2007, Google Inc. ++ * Copyright 2012, Intel Inc. ++ * ++ * based on omap.c driver, which was ++ * Copyright (C) 2004 Nokia Corporation ++ * Written by Tuukka Tikkanen and Juha Yrjölä ++ * Misc hacks here and there by Tony Lindgren ++ * Other hacks (DMA, SD, etc) by David Brownell ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define DRIVER_NAME "goldfish_mmc" ++ ++#define BUFFER_SIZE 16384 ++ ++#define GOLDFISH_MMC_READ(host, addr) (readl(host->reg_base + addr)) ++#define GOLDFISH_MMC_WRITE(host, addr, x) (writel(x, host->reg_base + addr)) ++ ++enum { ++ /* status register */ ++ MMC_INT_STATUS = 0x00, ++ /* set this to enable IRQ */ ++ MMC_INT_ENABLE = 0x04, ++ /* set this to specify buffer address */ ++ MMC_SET_BUFFER = 0x08, ++ ++ /* MMC command number */ ++ MMC_CMD = 0x0C, ++ ++ /* MMC argument */ ++ MMC_ARG = 0x10, ++ ++ /* MMC response (or R2 bits 0 - 31) */ ++ MMC_RESP_0 = 0x14, ++ ++ /* MMC R2 response bits 32 - 63 */ ++ MMC_RESP_1 = 0x18, ++ ++ /* MMC R2 response bits 64 - 95 */ ++ MMC_RESP_2 = 0x1C, ++ ++ /* MMC R2 response bits 96 - 127 */ ++ MMC_RESP_3 = 0x20, ++ ++ MMC_BLOCK_LENGTH = 0x24, ++ MMC_BLOCK_COUNT = 0x28, ++ ++ /* MMC state flags */ ++ MMC_STATE = 0x2C, ++ ++ /* MMC_INT_STATUS bits */ ++ ++ MMC_STAT_END_OF_CMD = 1U << 0, ++ MMC_STAT_END_OF_DATA = 1U << 1, ++ MMC_STAT_STATE_CHANGE = 1U << 2, ++ MMC_STAT_CMD_TIMEOUT = 1U << 3, ++ ++ /* MMC_STATE bits */ ++ MMC_STATE_INSERTED = 1U << 0, ++ MMC_STATE_READ_ONLY = 1U << 1, ++}; ++ ++/* ++ * Command types ++ */ ++#define OMAP_MMC_CMDTYPE_BC 0 ++#define OMAP_MMC_CMDTYPE_BCR 1 ++#define OMAP_MMC_CMDTYPE_AC 2 ++#define OMAP_MMC_CMDTYPE_ADTC 3 ++ ++ ++struct goldfish_mmc_host { ++ struct mmc_request *mrq; ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ struct mmc_host *mmc; ++ struct device *dev; ++ unsigned char id; /* 16xx chips have 2 MMC blocks */ ++ void __iomem *virt_base; ++ unsigned int phys_base; ++ int irq; ++ unsigned char bus_mode; ++ unsigned char hw_bus_mode; ++ ++ unsigned int sg_len; ++ unsigned dma_done:1; ++ unsigned dma_in_use:1; ++ ++ void __iomem *reg_base; ++}; ++ ++static inline int ++goldfish_mmc_cover_is_open(struct goldfish_mmc_host *host) ++{ ++ return 0; ++} ++ ++static ssize_t ++goldfish_mmc_show_cover_switch(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct goldfish_mmc_host *host = dev_get_drvdata(dev); ++ ++ return sprintf(buf, "%s\n", goldfish_mmc_cover_is_open(host) ? "open" : ++ "closed"); ++} ++ ++static DEVICE_ATTR(cover_switch, S_IRUGO, goldfish_mmc_show_cover_switch, NULL); ++ ++static void ++goldfish_mmc_start_command(struct goldfish_mmc_host *host, struct mmc_command *cmd) ++{ ++ u32 cmdreg; ++ u32 resptype; ++ u32 cmdtype; ++ ++ host->cmd = cmd; ++ ++ resptype = 0; ++ cmdtype = 0; ++ ++ /* Our hardware needs to know exact type */ ++ switch (mmc_resp_type(cmd)) { ++ case MMC_RSP_NONE: ++ break; ++ case MMC_RSP_R1: ++ case MMC_RSP_R1B: ++ /* resp 1, 1b, 6, 7 */ ++ resptype = 1; ++ break; ++ case MMC_RSP_R2: ++ resptype = 2; ++ break; ++ case MMC_RSP_R3: ++ resptype = 3; ++ break; ++ default: ++ dev_err(mmc_dev(host->mmc), ++ "Invalid response type: %04x\n", mmc_resp_type(cmd)); ++ break; ++ } ++ ++ if (mmc_cmd_type(cmd) == MMC_CMD_ADTC) ++ cmdtype = OMAP_MMC_CMDTYPE_ADTC; ++ else if (mmc_cmd_type(cmd) == MMC_CMD_BC) ++ cmdtype = OMAP_MMC_CMDTYPE_BC; ++ else if (mmc_cmd_type(cmd) == MMC_CMD_BCR) ++ cmdtype = OMAP_MMC_CMDTYPE_BCR; ++ else ++ cmdtype = OMAP_MMC_CMDTYPE_AC; ++ ++ cmdreg = cmd->opcode | (resptype << 8) | (cmdtype << 12); ++ ++ if (host->bus_mode == MMC_BUSMODE_OPENDRAIN) ++ cmdreg |= 1 << 6; ++ ++ if (cmd->flags & MMC_RSP_BUSY) ++ cmdreg |= 1 << 11; ++ ++ if (host->data && !(host->data->flags & MMC_DATA_WRITE)) ++ cmdreg |= 1 << 15; ++ ++ GOLDFISH_MMC_WRITE(host, MMC_ARG, cmd->arg); ++ GOLDFISH_MMC_WRITE(host, MMC_CMD, cmdreg); ++} ++ ++static void goldfish_mmc_xfer_done(struct goldfish_mmc_host *host, ++ struct mmc_data *data) ++{ ++ if (host->dma_in_use) { ++ enum dma_data_direction dma_data_dir; ++ ++ if (data->flags & MMC_DATA_WRITE) ++ dma_data_dir = DMA_TO_DEVICE; ++ else ++ dma_data_dir = DMA_FROM_DEVICE; ++ ++ if (dma_data_dir == DMA_FROM_DEVICE) { ++ /* ++ * We don't really have DMA, so we need ++ * to copy from our platform driver buffer ++ */ ++ uint8_t *dest = (uint8_t *)sg_virt(data->sg); ++ memcpy(dest, host->virt_base, data->sg->length); ++ } ++ host->data->bytes_xfered += data->sg->length; ++ dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len, ++ dma_data_dir); ++ } ++ ++ host->data = NULL; ++ host->sg_len = 0; ++ ++ /* ++ * NOTE: MMC layer will sometimes poll-wait CMD13 next, issuing ++ * dozens of requests until the card finishes writing data. ++ * It'd be cheaper to just wait till an EOFB interrupt arrives... ++ */ ++ ++ if (!data->stop) { ++ host->mrq = NULL; ++ mmc_request_done(host->mmc, data->mrq); ++ return; ++ } ++ ++ goldfish_mmc_start_command(host, data->stop); ++} ++ ++static void goldfish_mmc_end_of_data(struct goldfish_mmc_host *host, ++ struct mmc_data *data) ++{ ++ if (!host->dma_in_use) { ++ goldfish_mmc_xfer_done(host, data); ++ return; ++ } ++ if (host->dma_done) ++ goldfish_mmc_xfer_done(host, data); ++} ++ ++static void goldfish_mmc_cmd_done(struct goldfish_mmc_host *host, ++ struct mmc_command *cmd) ++{ ++ host->cmd = NULL; ++ if (cmd->flags & MMC_RSP_PRESENT) { ++ if (cmd->flags & MMC_RSP_136) { ++ /* response type 2 */ ++ cmd->resp[3] = ++ GOLDFISH_MMC_READ(host, MMC_RESP_0); ++ cmd->resp[2] = ++ GOLDFISH_MMC_READ(host, MMC_RESP_1); ++ cmd->resp[1] = ++ GOLDFISH_MMC_READ(host, MMC_RESP_2); ++ cmd->resp[0] = ++ GOLDFISH_MMC_READ(host, MMC_RESP_3); ++ } else { ++ /* response types 1, 1b, 3, 4, 5, 6 */ ++ cmd->resp[0] = ++ GOLDFISH_MMC_READ(host, MMC_RESP_0); ++ } ++ } ++ ++ if (host->data == NULL || cmd->error) { ++ host->mrq = NULL; ++ mmc_request_done(host->mmc, cmd->mrq); ++ } ++} ++ ++static irqreturn_t goldfish_mmc_irq(int irq, void *dev_id) ++{ ++ struct goldfish_mmc_host *host = (struct goldfish_mmc_host *)dev_id; ++ u16 status; ++ int end_command = 0; ++ int end_transfer = 0; ++ int transfer_error = 0; ++ int state_changed = 0; ++ int cmd_timeout = 0; ++ ++ while ((status = GOLDFISH_MMC_READ(host, MMC_INT_STATUS)) != 0) { ++ GOLDFISH_MMC_WRITE(host, MMC_INT_STATUS, status); ++ ++ if (status & MMC_STAT_END_OF_CMD) ++ end_command = 1; ++ ++ if (status & MMC_STAT_END_OF_DATA) ++ end_transfer = 1; ++ ++ if (status & MMC_STAT_STATE_CHANGE) ++ state_changed = 1; ++ ++ if (status & MMC_STAT_CMD_TIMEOUT) { ++ end_command = 0; ++ cmd_timeout = 1; ++ } ++ } ++ ++ if (cmd_timeout) { ++ struct mmc_request *mrq = host->mrq; ++ mrq->cmd->error = -ETIMEDOUT; ++ host->mrq = NULL; ++ mmc_request_done(host->mmc, mrq); ++ } ++ ++ if (end_command) ++ goldfish_mmc_cmd_done(host, host->cmd); ++ ++ if (transfer_error) ++ goldfish_mmc_xfer_done(host, host->data); ++ else if (end_transfer) { ++ host->dma_done = 1; ++ goldfish_mmc_end_of_data(host, host->data); ++ } else if (host->data != NULL) { ++ /* ++ * WORKAROUND -- after porting this driver from 2.6 to 3.4, ++ * during device initialization, cases where host->data is ++ * non-null but end_transfer is false would occur. Doing ++ * nothing in such cases results in no further interrupts, ++ * and initialization failure. ++ * TODO -- find the real cause. ++ */ ++ host->dma_done = 1; ++ goldfish_mmc_end_of_data(host, host->data); ++ } ++ ++ if (state_changed) { ++ u32 state = GOLDFISH_MMC_READ(host, MMC_STATE); ++ pr_info("%s: Card detect now %d\n", __func__, ++ (state & MMC_STATE_INSERTED)); ++ mmc_detect_change(host->mmc, 0); ++ } ++ ++ if (!end_command && !end_transfer && ++ !transfer_error && !state_changed && !cmd_timeout) { ++ status = GOLDFISH_MMC_READ(host, MMC_INT_STATUS); ++ dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status); ++ if (status != 0) { ++ GOLDFISH_MMC_WRITE(host, MMC_INT_STATUS, status); ++ GOLDFISH_MMC_WRITE(host, MMC_INT_ENABLE, 0); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void goldfish_mmc_prepare_data(struct goldfish_mmc_host *host, ++ struct mmc_request *req) ++{ ++ struct mmc_data *data = req->data; ++ int block_size; ++ unsigned sg_len; ++ enum dma_data_direction dma_data_dir; ++ ++ host->data = data; ++ if (data == NULL) { ++ GOLDFISH_MMC_WRITE(host, MMC_BLOCK_LENGTH, 0); ++ GOLDFISH_MMC_WRITE(host, MMC_BLOCK_COUNT, 0); ++ host->dma_in_use = 0; ++ return; ++ } ++ ++ block_size = data->blksz; ++ ++ GOLDFISH_MMC_WRITE(host, MMC_BLOCK_COUNT, data->blocks - 1); ++ GOLDFISH_MMC_WRITE(host, MMC_BLOCK_LENGTH, block_size - 1); ++ ++ /* ++ * Cope with calling layer confusion; it issues "single ++ * block" writes using multi-block scatterlists. ++ */ ++ sg_len = (data->blocks == 1) ? 1 : data->sg_len; ++ ++ if (data->flags & MMC_DATA_WRITE) ++ dma_data_dir = DMA_TO_DEVICE; ++ else ++ dma_data_dir = DMA_FROM_DEVICE; ++ ++ host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, ++ sg_len, dma_data_dir); ++ host->dma_done = 0; ++ host->dma_in_use = 1; ++ ++ if (dma_data_dir == DMA_TO_DEVICE) { ++ /* ++ * We don't really have DMA, so we need to copy to our ++ * platform driver buffer ++ */ ++ const uint8_t *src = (uint8_t *)sg_virt(data->sg); ++ memcpy(host->virt_base, src, data->sg->length); ++ } ++} ++ ++static void goldfish_mmc_request(struct mmc_host *mmc, struct mmc_request *req) ++{ ++ struct goldfish_mmc_host *host = mmc_priv(mmc); ++ ++ WARN_ON(host->mrq != NULL); ++ ++ host->mrq = req; ++ goldfish_mmc_prepare_data(host, req); ++ goldfish_mmc_start_command(host, req->cmd); ++ ++ /* ++ * This is to avoid accidentally being detected as an SDIO card ++ * in mmc_attach_sdio(). ++ */ ++ if (req->cmd->opcode == SD_IO_SEND_OP_COND && ++ req->cmd->flags == (MMC_RSP_SPI_R4 | MMC_RSP_R4 | MMC_CMD_BCR)) ++ req->cmd->error = -EINVAL; ++} ++ ++static void goldfish_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct goldfish_mmc_host *host = mmc_priv(mmc); ++ ++ host->bus_mode = ios->bus_mode; ++ host->hw_bus_mode = host->bus_mode; ++} ++ ++static int goldfish_mmc_get_ro(struct mmc_host *mmc) ++{ ++ uint32_t state; ++ struct goldfish_mmc_host *host = mmc_priv(mmc); ++ ++ state = GOLDFISH_MMC_READ(host, MMC_STATE); ++ return ((state & MMC_STATE_READ_ONLY) != 0); ++} ++ ++static const struct mmc_host_ops goldfish_mmc_ops = { ++ .request = goldfish_mmc_request, ++ .set_ios = goldfish_mmc_set_ios, ++ .get_ro = goldfish_mmc_get_ro, ++}; ++ ++static int goldfish_mmc_probe(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc; ++ struct goldfish_mmc_host *host = NULL; ++ struct resource *res; ++ int ret = 0; ++ int irq; ++ dma_addr_t buf_addr; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ irq = platform_get_irq(pdev, 0); ++ if (res == NULL || irq < 0) ++ return -ENXIO; ++ ++ mmc = mmc_alloc_host(sizeof(struct goldfish_mmc_host), &pdev->dev); ++ if (mmc == NULL) { ++ ret = -ENOMEM; ++ goto err_alloc_host_failed; ++ } ++ ++ host = mmc_priv(mmc); ++ host->mmc = mmc; ++ ++ pr_err("mmc: Mapping %lX to %lX\n", (long)res->start, (long)res->end); ++ host->reg_base = ioremap(res->start, resource_size(res)); ++ if (host->reg_base == NULL) { ++ ret = -ENOMEM; ++ goto ioremap_failed; ++ } ++ host->virt_base = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE, ++ &buf_addr, GFP_KERNEL); ++ ++ if (host->virt_base == 0) { ++ ret = -ENOMEM; ++ goto dma_alloc_failed; ++ } ++ host->phys_base = buf_addr; ++ ++ host->id = pdev->id; ++ host->irq = irq; ++ ++ mmc->ops = &goldfish_mmc_ops; ++ mmc->f_min = 400000; ++ mmc->f_max = 24000000; ++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; ++ mmc->caps = MMC_CAP_4_BIT_DATA; ++ ++ /* Use scatterlist DMA to reduce per-transfer costs. ++ * NOTE max_seg_size assumption that small blocks aren't ++ * normally used (except e.g. for reading SD registers). ++ */ ++ mmc->max_segs = 32; ++ mmc->max_blk_size = 2048; /* MMC_BLOCK_LENGTH is 11 bits (+1) */ ++ mmc->max_blk_count = 2048; /* MMC_BLOCK_COUNT is 11 bits (+1) */ ++ mmc->max_req_size = BUFFER_SIZE; ++ mmc->max_seg_size = mmc->max_req_size; ++ ++ ret = request_irq(host->irq, goldfish_mmc_irq, 0, DRIVER_NAME, host); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed IRQ Adding goldfish MMC\n"); ++ goto err_request_irq_failed; ++ } ++ ++ host->dev = &pdev->dev; ++ platform_set_drvdata(pdev, host); ++ ++ ret = device_create_file(&pdev->dev, &dev_attr_cover_switch); ++ if (ret) ++ dev_warn(mmc_dev(host->mmc), ++ "Unable to create sysfs attributes\n"); ++ ++ GOLDFISH_MMC_WRITE(host, MMC_SET_BUFFER, host->phys_base); ++ GOLDFISH_MMC_WRITE(host, MMC_INT_ENABLE, ++ MMC_STAT_END_OF_CMD | MMC_STAT_END_OF_DATA | ++ MMC_STAT_STATE_CHANGE | MMC_STAT_CMD_TIMEOUT); ++ ++ mmc_add_host(mmc); ++ return 0; ++ ++err_request_irq_failed: ++ dma_free_coherent(&pdev->dev, BUFFER_SIZE, host->virt_base, ++ host->phys_base); ++dma_alloc_failed: ++ iounmap(host->reg_base); ++ioremap_failed: ++ mmc_free_host(host->mmc); ++err_alloc_host_failed: ++ return ret; ++} ++ ++static int goldfish_mmc_remove(struct platform_device *pdev) ++{ ++ struct goldfish_mmc_host *host = platform_get_drvdata(pdev); ++ ++ BUG_ON(host == NULL); ++ ++ mmc_remove_host(host->mmc); ++ free_irq(host->irq, host); ++ dma_free_coherent(&pdev->dev, BUFFER_SIZE, host->virt_base, host->phys_base); ++ iounmap(host->reg_base); ++ mmc_free_host(host->mmc); ++ return 0; ++} ++ ++static struct platform_driver goldfish_mmc_driver = { ++ .probe = goldfish_mmc_probe, ++ .remove = goldfish_mmc_remove, ++ .driver = { ++ .name = DRIVER_NAME, ++ }, ++}; ++ ++module_platform_driver(goldfish_mmc_driver); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h +index 000b3ad..c97001e 100644 +--- a/drivers/mmc/host/atmel-mci-regs.h ++++ b/drivers/mmc/host/atmel-mci-regs.h +@@ -31,6 +31,7 @@ + # define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */ + # define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */ + # define ATMCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */ ++# define ATMCI_MR_CLKODD(x) ((x) << 16) /* LSB of Clock Divider */ + #define ATMCI_DTOR 0x0008 /* Data Timeout */ + # define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */ + # define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */ +@@ -139,4 +140,25 @@ + #define atmci_writel(port,reg,value) \ + __raw_writel((value), (port)->regs + reg) + ++/* On AVR chips the Peripheral DMA Controller is not connected to MCI. */ ++#ifdef CONFIG_AVR32 ++# define ATMCI_PDC_CONNECTED 0 ++#else ++# define ATMCI_PDC_CONNECTED 1 ++#endif ++ ++/* ++ * Fix sconfig's burst size according to atmel MCI. We need to convert them as: ++ * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. ++ * ++ * This can be done by finding most significant bit set. ++ */ ++static inline unsigned int atmci_convert_chksize(unsigned int maxburst) ++{ ++ if (maxburst > 1) ++ return fls(maxburst) - 2; ++ else ++ return 0; ++} ++ + #endif /* __DRIVERS_MMC_ATMEL_MCI_H__ */ +diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c +index fd61f63..bb585d9 100644 +--- a/drivers/mmc/host/atmel-mci.c ++++ b/drivers/mmc/host/atmel-mci.c +@@ -19,11 +19,16 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + #include + #include + #include ++#include ++#include + + #include + #include +@@ -32,31 +37,29 @@ + #include + #include + ++#include + #include + #include + +-#include +-#include +- + #include "atmel-mci-regs.h" + + #define ATMCI_DATA_ERROR_FLAGS (ATMCI_DCRCE | ATMCI_DTOE | ATMCI_OVRE | ATMCI_UNRE) + #define ATMCI_DMA_THRESHOLD 16 + + enum { +- EVENT_CMD_COMPLETE = 0, ++ EVENT_CMD_RDY = 0, + EVENT_XFER_COMPLETE, +- EVENT_DATA_COMPLETE, ++ EVENT_NOTBUSY, + EVENT_DATA_ERROR, + }; + + enum atmel_mci_state { + STATE_IDLE = 0, + STATE_SENDING_CMD, +- STATE_SENDING_DATA, +- STATE_DATA_BUSY, ++ STATE_DATA_XFER, ++ STATE_WAITING_NOTBUSY, + STATE_SENDING_STOP, +- STATE_DATA_ERROR, ++ STATE_END_REQUEST, + }; + + enum atmci_xfer_dir { +@@ -70,12 +73,17 @@ enum atmci_pdc_buf { + }; + + struct atmel_mci_caps { +- bool has_dma; ++ bool has_dma_conf_reg; + bool has_pdc; + bool has_cfg_reg; + bool has_cstor_reg; + bool has_highspeed; + bool has_rwproof; ++ bool has_odd_clk_div; ++ bool has_bad_data_ordering; ++ bool need_reset_after_xfer; ++ bool need_blksz_mul_4; ++ bool need_notbusy_for_read_ops; + }; + + struct atmel_mci_dma { +@@ -89,6 +97,11 @@ struct atmel_mci_dma { + * @regs: Pointer to MMIO registers. + * @sg: Scatterlist entry currently being processed by PIO or PDC code. + * @pio_offset: Offset into the current scatterlist entry. ++ * @buffer: Buffer used if we don't have the r/w proof capability. We ++ * don't have the time to switch pdc buffers so we have to use only ++ * one buffer for the full transaction. ++ * @buf_size: size of the buffer. ++ * @phys_buf_addr: buffer address needed for pdc. + * @cur_slot: The slot which is currently using the controller. + * @mrq: The request currently being processed on @cur_slot, + * or NULL if the controller is idle. +@@ -114,6 +127,7 @@ struct atmel_mci_dma { + * @queue: List of slots waiting for access to the controller. + * @need_clock_update: Update the clock rate before the next request. + * @need_reset: Reset controller before next request. ++ * @timer: Timer to balance the data timeout error flag which cannot rise. + * @mode_reg: Value of the MR register. + * @cfg_reg: Value of the CFG register. + * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus +@@ -165,6 +179,9 @@ struct atmel_mci { + struct scatterlist *sg; + unsigned int sg_len; + unsigned int pio_offset; ++ unsigned int *buffer; ++ unsigned int buf_size; ++ dma_addr_t buf_phys_addr; + + struct atmel_mci_slot *cur_slot; + struct mmc_request *mrq; +@@ -174,6 +191,7 @@ struct atmel_mci { + + struct atmel_mci_dma dma; + struct dma_chan *data_chan; ++ struct dma_slave_config dma_conf; + + u32 cmd_status; + u32 data_status; +@@ -187,6 +205,7 @@ struct atmel_mci { + + bool need_clock_update; + bool need_reset; ++ struct timer_list timer; + u32 mode_reg; + u32 cfg_reg; + unsigned long bus_hz; +@@ -237,7 +256,6 @@ struct atmel_mci_slot { + #define ATMCI_CARD_PRESENT 0 + #define ATMCI_CARD_NEED_INIT 1 + #define ATMCI_SHUTDOWN 2 +-#define ATMCI_SUSPENDED 3 + + int detect_pin; + int wp_pin; +@@ -360,6 +378,8 @@ static int atmci_regs_show(struct seq_file *s, void *v) + { + struct atmel_mci *host = s->private; + u32 *buf; ++ int ret = 0; ++ + + buf = kmalloc(ATMCI_REGS_SIZE, GFP_KERNEL); + if (!buf) +@@ -370,17 +390,27 @@ static int atmci_regs_show(struct seq_file *s, void *v) + * not disabling interrupts, so IMR and SR may not be + * consistent. + */ ++ ret = clk_prepare_enable(host->mck); ++ if (ret) ++ goto out; ++ + spin_lock_bh(&host->lock); +- clk_enable(host->mck); + memcpy_fromio(buf, host->regs, ATMCI_REGS_SIZE); +- clk_disable(host->mck); + spin_unlock_bh(&host->lock); + +- seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n", ++ clk_disable_unprepare(host->mck); ++ ++ seq_printf(s, "MR:\t0x%08x%s%s ", + buf[ATMCI_MR / 4], + buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "", +- buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : "", +- buf[ATMCI_MR / 4] & 0xff); ++ buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : ""); ++ if (host->caps.has_odd_clk_div) ++ seq_printf(s, "{CLKDIV,CLKODD}=%u\n", ++ ((buf[ATMCI_MR / 4] & 0xff) << 1) ++ | ((buf[ATMCI_MR / 4] >> 16) & 1)); ++ else ++ seq_printf(s, "CLKDIV=%u\n", ++ (buf[ATMCI_MR / 4] & 0xff)); + seq_printf(s, "DTOR:\t0x%08x\n", buf[ATMCI_DTOR / 4]); + seq_printf(s, "SDCR:\t0x%08x\n", buf[ATMCI_SDCR / 4]); + seq_printf(s, "ARGR:\t0x%08x\n", buf[ATMCI_ARGR / 4]); +@@ -396,7 +426,7 @@ static int atmci_regs_show(struct seq_file *s, void *v) + atmci_show_status_reg(s, "SR", buf[ATMCI_SR / 4]); + atmci_show_status_reg(s, "IMR", buf[ATMCI_IMR / 4]); + +- if (host->caps.has_dma) { ++ if (host->caps.has_dma_conf_reg) { + u32 val; + + val = buf[ATMCI_DMA / 4]; +@@ -418,9 +448,10 @@ static int atmci_regs_show(struct seq_file *s, void *v) + val & ATMCI_CFG_LSYNC ? " LSYNC" : ""); + } + ++out: + kfree(buf); + +- return 0; ++ return ret; + } + + static int atmci_regs_open(struct inode *inode, struct file *file) +@@ -478,6 +509,103 @@ err: + dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); + } + ++#if defined(CONFIG_OF) ++static const struct of_device_id atmci_dt_ids[] = { ++ { .compatible = "atmel,hsmci" }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, atmci_dt_ids); ++ ++static struct mci_platform_data* ++atmci_of_init(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *cnp; ++ struct mci_platform_data *pdata; ++ u32 slot_id; ++ ++ if (!np) { ++ dev_err(&pdev->dev, "device node not found\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) { ++ dev_err(&pdev->dev, "could not allocate memory for pdata\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ for_each_child_of_node(np, cnp) { ++ if (of_property_read_u32(cnp, "reg", &slot_id)) { ++ dev_warn(&pdev->dev, "reg property is missing for %s\n", ++ cnp->full_name); ++ continue; ++ } ++ ++ if (slot_id >= ATMCI_MAX_NR_SLOTS) { ++ dev_warn(&pdev->dev, "can't have more than %d slots\n", ++ ATMCI_MAX_NR_SLOTS); ++ break; ++ } ++ ++ if (of_property_read_u32(cnp, "bus-width", ++ &pdata->slot[slot_id].bus_width)) ++ pdata->slot[slot_id].bus_width = 1; ++ ++ pdata->slot[slot_id].detect_pin = ++ of_get_named_gpio(cnp, "cd-gpios", 0); ++ ++ pdata->slot[slot_id].detect_is_active_high = ++ of_property_read_bool(cnp, "cd-inverted"); ++ ++ pdata->slot[slot_id].wp_pin = ++ of_get_named_gpio(cnp, "wp-gpios", 0); ++ } ++ ++ return pdata; ++} ++#else /* CONFIG_OF */ ++static inline struct mci_platform_data* ++atmci_of_init(struct platform_device *dev) ++{ ++ return ERR_PTR(-EINVAL); ++} ++#endif ++ ++static inline unsigned int atmci_get_version(struct atmel_mci *host) ++{ ++ return atmci_readl(host, ATMCI_VERSION) & 0x00000fff; ++} ++ ++static void atmci_timeout_timer(unsigned long data) ++{ ++ struct atmel_mci *host; ++ ++ host = (struct atmel_mci *)data; ++ ++ dev_dbg(&host->pdev->dev, "software timeout\n"); ++ ++ if (host->mrq->cmd->data) { ++ host->mrq->cmd->data->error = -ETIMEDOUT; ++ host->data = NULL; ++ /* ++ * With some SDIO modules, sometimes DMA transfer hangs. If ++ * stop_transfer() is not called then the DMA request is not ++ * removed, following ones are queued and never computed. ++ */ ++ if (host->state == STATE_DATA_XFER) ++ host->stop_transfer(host); ++ } else { ++ host->mrq->cmd->error = -ETIMEDOUT; ++ host->cmd = NULL; ++ } ++ host->need_reset = 1; ++ host->state = STATE_END_REQUEST; ++ smp_wmb(); ++ tasklet_schedule(&host->tasklet); ++} ++ + static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host, + unsigned int ns) + { +@@ -589,6 +717,7 @@ static void atmci_send_command(struct atmel_mci *host, + + static void atmci_send_stop_cmd(struct atmel_mci *host, struct mmc_data *data) + { ++ dev_dbg(&host->pdev->dev, "send stop command\n"); + atmci_send_command(host, data->stop, host->stop_cmdr); + atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY); + } +@@ -601,6 +730,7 @@ static void atmci_pdc_set_single_buf(struct atmel_mci *host, + enum atmci_xfer_dir dir, enum atmci_pdc_buf buf_nb) + { + u32 pointer_reg, counter_reg; ++ unsigned int buf_size; + + if (dir == XFER_RECEIVE) { + pointer_reg = ATMEL_PDC_RPR; +@@ -615,8 +745,15 @@ static void atmci_pdc_set_single_buf(struct atmel_mci *host, + counter_reg += ATMEL_PDC_SCND_BUF_OFF; + } + +- atmci_writel(host, pointer_reg, sg_dma_address(host->sg)); +- if (host->data_size <= sg_dma_len(host->sg)) { ++ if (!host->caps.has_rwproof) { ++ buf_size = host->buf_size; ++ atmci_writel(host, pointer_reg, host->buf_phys_addr); ++ } else { ++ buf_size = sg_dma_len(host->sg); ++ atmci_writel(host, pointer_reg, sg_dma_address(host->sg)); ++ } ++ ++ if (host->data_size <= buf_size) { + if (host->data_size & 0x3) { + /* If size is different from modulo 4, transfer bytes */ + atmci_writel(host, counter_reg, host->data_size); +@@ -668,18 +805,25 @@ static void atmci_pdc_cleanup(struct atmel_mci *host) + */ + static void atmci_pdc_complete(struct atmel_mci *host) + { ++ int transfer_size = host->data->blocks * host->data->blksz; ++ int i; ++ + atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); +- atmci_pdc_cleanup(host); + +- /* +- * If the card was removed, data will be NULL. No point trying +- * to send the stop command or waiting for NBUSY in this case. +- */ +- if (host->data) { +- atmci_set_pending(host, EVENT_XFER_COMPLETE); +- tasklet_schedule(&host->tasklet); +- atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); ++ if ((!host->caps.has_rwproof) ++ && (host->data->flags & MMC_DATA_READ)) { ++ if (host->caps.has_bad_data_ordering) ++ for (i = 0; i < transfer_size; i++) ++ host->buffer[i] = swab32(host->buffer[i]); ++ sg_copy_from_buffer(host->data->sg, host->data->sg_len, ++ host->buffer, transfer_size); + } ++ ++ atmci_pdc_cleanup(host); ++ ++ dev_dbg(&host->pdev->dev, "(%s) set pending xfer complete\n", __func__); ++ atmci_set_pending(host, EVENT_XFER_COMPLETE); ++ tasklet_schedule(&host->tasklet); + } + + static void atmci_dma_cleanup(struct atmel_mci *host) +@@ -703,7 +847,7 @@ static void atmci_dma_complete(void *arg) + + dev_vdbg(&host->pdev->dev, "DMA complete\n"); + +- if (host->caps.has_dma) ++ if (host->caps.has_dma_conf_reg) + /* Disable DMA hardware handshaking on MCI */ + atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN); + +@@ -714,6 +858,8 @@ static void atmci_dma_complete(void *arg) + * to send the stop command or waiting for NBUSY in this case. + */ + if (data) { ++ dev_dbg(&host->pdev->dev, ++ "(%s) set pending xfer complete\n", __func__); + atmci_set_pending(host, EVENT_XFER_COMPLETE); + tasklet_schedule(&host->tasklet); + +@@ -790,6 +936,7 @@ atmci_prepare_data_pdc(struct atmel_mci *host, struct mmc_data *data) + u32 iflags, tmp; + unsigned int sg_len; + enum dma_data_direction dir; ++ int i; + + data->error = -EINPROGRESS; + +@@ -805,7 +952,7 @@ atmci_prepare_data_pdc(struct atmel_mci *host, struct mmc_data *data) + iflags |= ATMCI_ENDRX | ATMCI_RXBUFF; + } else { + dir = DMA_TO_DEVICE; +- iflags |= ATMCI_ENDTX | ATMCI_TXBUFE; ++ iflags |= ATMCI_ENDTX | ATMCI_TXBUFE | ATMCI_BLKE; + } + + /* Set BLKLEN */ +@@ -817,6 +964,16 @@ atmci_prepare_data_pdc(struct atmel_mci *host, struct mmc_data *data) + /* Configure PDC */ + host->data_size = data->blocks * data->blksz; + sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir); ++ ++ if ((!host->caps.has_rwproof) ++ && (host->data->flags & MMC_DATA_WRITE)) { ++ sg_copy_to_buffer(host->data->sg, host->data->sg_len, ++ host->buffer, host->data_size); ++ if (host->caps.has_bad_data_ordering) ++ for (i = 0; i < host->data_size; i++) ++ host->buffer[i] = swab32(host->buffer[i]); ++ } ++ + if (host->data_size) + atmci_pdc_set_both_buf(host, + ((dir == DMA_FROM_DEVICE) ? XFER_RECEIVE : XFER_TRANSMIT)); +@@ -832,7 +989,9 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) + struct scatterlist *sg; + unsigned int i; + enum dma_data_direction direction; ++ enum dma_transfer_direction slave_dirn; + unsigned int sglen; ++ u32 maxburst; + u32 iflags; + + data->error = -EINPROGRESS; +@@ -866,19 +1025,26 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) + if (!chan) + return -ENODEV; + +- if (host->caps.has_dma) +- atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(3) | ATMCI_DMAEN); +- +- if (data->flags & MMC_DATA_READ) ++ if (data->flags & MMC_DATA_READ) { + direction = DMA_FROM_DEVICE; +- else ++ host->dma_conf.direction = slave_dirn = DMA_DEV_TO_MEM; ++ maxburst = atmci_convert_chksize(host->dma_conf.src_maxburst); ++ } else { + direction = DMA_TO_DEVICE; ++ host->dma_conf.direction = slave_dirn = DMA_MEM_TO_DEV; ++ maxburst = atmci_convert_chksize(host->dma_conf.dst_maxburst); ++ } ++ ++ if (host->caps.has_dma_conf_reg) ++ atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(maxburst) | ++ ATMCI_DMAEN); + + sglen = dma_map_sg(chan->device->dev, data->sg, + data->sg_len, direction); + +- desc = chan->device->device_prep_slave_sg(chan, +- data->sg, sglen, direction, ++ dmaengine_slave_config(chan, &host->dma_conf); ++ desc = dmaengine_prep_slave_sg(chan, ++ data->sg, sglen, slave_dirn, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc) + goto unmap_exit; +@@ -925,17 +1091,18 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) + + static void atmci_stop_transfer(struct atmel_mci *host) + { ++ dev_dbg(&host->pdev->dev, ++ "(%s) set pending xfer complete\n", __func__); + atmci_set_pending(host, EVENT_XFER_COMPLETE); + atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); + } + + /* +- * Stop data transfer because error(s) occured. ++ * Stop data transfer because error(s) occurred. + */ + static void atmci_stop_transfer_pdc(struct atmel_mci *host) + { +- atmci_set_pending(host, EVENT_XFER_COMPLETE); +- atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); ++ atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); + } + + static void atmci_stop_transfer_dma(struct atmel_mci *host) +@@ -947,6 +1114,8 @@ static void atmci_stop_transfer_dma(struct atmel_mci *host) + atmci_dma_cleanup(host); + } else { + /* Data transfer was stopped by the interrupt handler */ ++ dev_dbg(&host->pdev->dev, ++ "(%s) set pending xfer complete\n", __func__); + atmci_set_pending(host, EVENT_XFER_COMPLETE); + atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); + } +@@ -971,9 +1140,12 @@ static void atmci_start_request(struct atmel_mci *host, + + host->pending_events = 0; + host->completed_events = 0; ++ host->cmd_status = 0; + host->data_status = 0; + +- if (host->need_reset) { ++ dev_dbg(&host->pdev->dev, "start request: cmd %u\n", mrq->cmd->opcode); ++ ++ if (host->need_reset || host->caps.need_reset_after_xfer) { + iflags = atmci_readl(host, ATMCI_IMR); + iflags &= (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB); + atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); +@@ -988,7 +1160,7 @@ static void atmci_start_request(struct atmel_mci *host, + + iflags = atmci_readl(host, ATMCI_IMR); + if (iflags & ~(ATMCI_SDIOIRQA | ATMCI_SDIOIRQB)) +- dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n", ++ dev_dbg(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n", + iflags); + + if (unlikely(test_and_clear_bit(ATMCI_CARD_NEED_INIT, &slot->flags))) { +@@ -1048,6 +1220,8 @@ static void atmci_start_request(struct atmel_mci *host, + * prepared yet.) + */ + atmci_writel(host, ATMCI_IER, iflags); ++ ++ mod_timer(&host->timer, jiffies + msecs_to_jiffies(2000)); + } + + static void atmci_queue_request(struct atmel_mci *host, +@@ -1062,6 +1236,7 @@ static void atmci_queue_request(struct atmel_mci *host, + host->state = STATE_SENDING_CMD; + atmci_start_request(host, slot); + } else { ++ dev_dbg(&host->pdev->dev, "queue request\n"); + list_add_tail(&slot->queue_node, &host->queue); + } + spin_unlock_bh(&host->lock); +@@ -1074,6 +1249,7 @@ static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq) + struct mmc_data *data; + + WARN_ON(slot->mrq); ++ dev_dbg(&host->pdev->dev, "MRQ: cmd %u\n", mrq->cmd->opcode); + + /* + * We may "know" the card is gone even though there's still an +@@ -1104,6 +1280,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + struct atmel_mci_slot *slot = mmc_priv(mmc); + struct atmel_mci *host = slot->host; + unsigned int i; ++ bool unprepare_clk; + + slot->sdc_reg &= ~ATMCI_SDCBUS_MASK; + switch (ios->bus_width) { +@@ -1119,9 +1296,13 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + unsigned int clock_min = ~0U; + u32 clkdiv; + ++ clk_prepare(host->mck); ++ unprepare_clk = true; ++ + spin_lock_bh(&host->lock); + if (!host->mode_reg) { + clk_enable(host->mck); ++ unprepare_clk = false; + atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); + atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); + if (host->caps.has_cfg_reg) +@@ -1140,16 +1321,27 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + } + + /* Calculate clock divider */ +- clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1; +- if (clkdiv > 255) { +- dev_warn(&mmc->class_dev, +- "clock %u too slow; using %lu\n", +- clock_min, host->bus_hz / (2 * 256)); +- clkdiv = 255; ++ if (host->caps.has_odd_clk_div) { ++ clkdiv = DIV_ROUND_UP(host->bus_hz, clock_min) - 2; ++ if (clkdiv > 511) { ++ dev_warn(&mmc->class_dev, ++ "clock %u too slow; using %lu\n", ++ clock_min, host->bus_hz / (511 + 2)); ++ clkdiv = 511; ++ } ++ host->mode_reg = ATMCI_MR_CLKDIV(clkdiv >> 1) ++ | ATMCI_MR_CLKODD(clkdiv & 1); ++ } else { ++ clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1; ++ if (clkdiv > 255) { ++ dev_warn(&mmc->class_dev, ++ "clock %u too slow; using %lu\n", ++ clock_min, host->bus_hz / (2 * 256)); ++ clkdiv = 255; ++ } ++ host->mode_reg = ATMCI_MR_CLKDIV(clkdiv); + } + +- host->mode_reg = ATMCI_MR_CLKDIV(clkdiv); +- + /* + * WRPROOF and RDPROOF prevent overruns/underruns by + * stopping the clock when the FIFO is full/empty. +@@ -1178,6 +1370,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + } else { + bool any_slot_active = false; + ++ unprepare_clk = false; ++ + spin_lock_bh(&host->lock); + slot->clock = 0; + for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { +@@ -1191,15 +1385,25 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + if (host->mode_reg) { + atmci_readl(host, ATMCI_MR); + clk_disable(host->mck); ++ unprepare_clk = true; + } + host->mode_reg = 0; + } + spin_unlock_bh(&host->lock); + } + ++ if (unprepare_clk) ++ clk_unprepare(host->mck); ++ + switch (ios->power_mode) { ++ case MMC_POWER_OFF: ++ if (!IS_ERR(mmc->supply.vmmc)) ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); ++ break; + case MMC_POWER_UP: + set_bit(ATMCI_CARD_NEED_INIT, &slot->flags); ++ if (!IS_ERR(mmc->supply.vmmc)) ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); + break; + default: + /* +@@ -1302,6 +1506,8 @@ static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq) + host->state = STATE_IDLE; + } + ++ del_timer(&host->timer); ++ + spin_unlock(&host->lock); + mmc_request_done(prev_mmc, mrq); + spin_lock(&host->lock); +@@ -1324,21 +1530,13 @@ static void atmci_command_complete(struct atmel_mci *host, + cmd->error = -EILSEQ; + else if (status & (ATMCI_RINDE | ATMCI_RDIRE | ATMCI_RENDE)) + cmd->error = -EIO; +- else +- cmd->error = 0; +- +- if (cmd->error) { +- dev_dbg(&host->pdev->dev, +- "command error: status=0x%08x\n", status); +- +- if (cmd->data) { +- host->stop_transfer(host); +- host->data = NULL; +- atmci_writel(host, ATMCI_IDR, ATMCI_NOTBUSY +- | ATMCI_TXRDY | ATMCI_RXRDY +- | ATMCI_DATA_ERROR_FLAGS); ++ else if (host->mrq->data && (host->mrq->data->blksz & 3)) { ++ if (host->caps.need_blksz_mul_4) { ++ cmd->error = -EINVAL; ++ host->need_reset = 1; + } +- } ++ } else ++ cmd->error = 0; + } + + static void atmci_detect_change(unsigned long data) +@@ -1401,23 +1599,21 @@ static void atmci_detect_change(unsigned long data) + break; + case STATE_SENDING_CMD: + mrq->cmd->error = -ENOMEDIUM; +- if (!mrq->data) +- break; +- /* fall through */ +- case STATE_SENDING_DATA: ++ if (mrq->data) ++ host->stop_transfer(host); ++ break; ++ case STATE_DATA_XFER: + mrq->data->error = -ENOMEDIUM; + host->stop_transfer(host); + break; +- case STATE_DATA_BUSY: +- case STATE_DATA_ERROR: +- if (mrq->data->error == -EINPROGRESS) +- mrq->data->error = -ENOMEDIUM; +- if (!mrq->stop) +- break; +- /* fall through */ ++ case STATE_WAITING_NOTBUSY: ++ mrq->data->error = -ENOMEDIUM; ++ break; + case STATE_SENDING_STOP: + mrq->stop->error = -ENOMEDIUM; + break; ++ case STATE_END_REQUEST: ++ break; + } + + atmci_request_end(host, mrq); +@@ -1445,7 +1641,6 @@ static void atmci_tasklet_func(unsigned long priv) + struct atmel_mci *host = (struct atmel_mci *)priv; + struct mmc_request *mrq = host->mrq; + struct mmc_data *data = host->data; +- struct mmc_command *cmd = host->cmd; + enum atmel_mci_state state = host->state; + enum atmel_mci_state prev_state; + u32 status; +@@ -1461,107 +1656,189 @@ static void atmci_tasklet_func(unsigned long priv) + + do { + prev_state = state; ++ dev_dbg(&host->pdev->dev, "FSM: state=%d\n", state); + + switch (state) { + case STATE_IDLE: + break; + + case STATE_SENDING_CMD: ++ /* ++ * Command has been sent, we are waiting for command ++ * ready. Then we have three next states possible: ++ * END_REQUEST by default, WAITING_NOTBUSY if it's a ++ * command needing it or DATA_XFER if there is data. ++ */ ++ dev_dbg(&host->pdev->dev, "FSM: cmd ready?\n"); + if (!atmci_test_and_clear_pending(host, +- EVENT_CMD_COMPLETE)) ++ EVENT_CMD_RDY)) + break; + ++ dev_dbg(&host->pdev->dev, "set completed cmd ready\n"); + host->cmd = NULL; +- atmci_set_completed(host, EVENT_CMD_COMPLETE); ++ atmci_set_completed(host, EVENT_CMD_RDY); + atmci_command_complete(host, mrq->cmd); +- if (!mrq->data || cmd->error) { +- atmci_request_end(host, host->mrq); +- goto unlock; +- } ++ if (mrq->data) { ++ dev_dbg(&host->pdev->dev, ++ "command with data transfer"); ++ /* ++ * If there is a command error don't start ++ * data transfer. ++ */ ++ if (mrq->cmd->error) { ++ host->stop_transfer(host); ++ host->data = NULL; ++ atmci_writel(host, ATMCI_IDR, ++ ATMCI_TXRDY | ATMCI_RXRDY ++ | ATMCI_DATA_ERROR_FLAGS); ++ state = STATE_END_REQUEST; ++ } else ++ state = STATE_DATA_XFER; ++ } else if ((!mrq->data) && (mrq->cmd->flags & MMC_RSP_BUSY)) { ++ dev_dbg(&host->pdev->dev, ++ "command response need waiting notbusy"); ++ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); ++ state = STATE_WAITING_NOTBUSY; ++ } else ++ state = STATE_END_REQUEST; + +- prev_state = state = STATE_SENDING_DATA; +- /* fall through */ ++ break; + +- case STATE_SENDING_DATA: ++ case STATE_DATA_XFER: + if (atmci_test_and_clear_pending(host, + EVENT_DATA_ERROR)) { +- host->stop_transfer(host); +- if (data->stop) +- atmci_send_stop_cmd(host, data); +- state = STATE_DATA_ERROR; ++ dev_dbg(&host->pdev->dev, "set completed data error\n"); ++ atmci_set_completed(host, EVENT_DATA_ERROR); ++ state = STATE_END_REQUEST; + break; + } + ++ /* ++ * A data transfer is in progress. The event expected ++ * to move to the next state depends of data transfer ++ * type (PDC or DMA). Once transfer done we can move ++ * to the next step which is WAITING_NOTBUSY in write ++ * case and directly SENDING_STOP in read case. ++ */ ++ dev_dbg(&host->pdev->dev, "FSM: xfer complete?\n"); + if (!atmci_test_and_clear_pending(host, + EVENT_XFER_COMPLETE)) + break; + ++ dev_dbg(&host->pdev->dev, ++ "(%s) set completed xfer complete\n", ++ __func__); + atmci_set_completed(host, EVENT_XFER_COMPLETE); +- prev_state = state = STATE_DATA_BUSY; +- /* fall through */ +- +- case STATE_DATA_BUSY: +- if (!atmci_test_and_clear_pending(host, +- EVENT_DATA_COMPLETE)) +- break; + +- host->data = NULL; +- atmci_set_completed(host, EVENT_DATA_COMPLETE); +- status = host->data_status; +- if (unlikely(status & ATMCI_DATA_ERROR_FLAGS)) { +- if (status & ATMCI_DTOE) { +- dev_dbg(&host->pdev->dev, +- "data timeout error\n"); +- data->error = -ETIMEDOUT; +- } else if (status & ATMCI_DCRCE) { +- dev_dbg(&host->pdev->dev, +- "data CRC error\n"); +- data->error = -EILSEQ; +- } else { +- dev_dbg(&host->pdev->dev, +- "data FIFO error (status=%08x)\n", +- status); +- data->error = -EIO; +- } ++ if (host->caps.need_notbusy_for_read_ops || ++ (host->data->flags & MMC_DATA_WRITE)) { ++ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); ++ state = STATE_WAITING_NOTBUSY; ++ } else if (host->mrq->stop) { ++ atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY); ++ atmci_send_stop_cmd(host, data); ++ state = STATE_SENDING_STOP; + } else { ++ host->data = NULL; + data->bytes_xfered = data->blocks * data->blksz; + data->error = 0; +- atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS); ++ state = STATE_END_REQUEST; + } ++ break; + +- if (!data->stop) { +- atmci_request_end(host, host->mrq); +- goto unlock; +- } ++ case STATE_WAITING_NOTBUSY: ++ /* ++ * We can be in the state for two reasons: a command ++ * requiring waiting not busy signal (stop command ++ * included) or a write operation. In the latest case, ++ * we need to send a stop command. ++ */ ++ dev_dbg(&host->pdev->dev, "FSM: not busy?\n"); ++ if (!atmci_test_and_clear_pending(host, ++ EVENT_NOTBUSY)) ++ break; + +- prev_state = state = STATE_SENDING_STOP; +- if (!data->error) +- atmci_send_stop_cmd(host, data); +- /* fall through */ ++ dev_dbg(&host->pdev->dev, "set completed not busy\n"); ++ atmci_set_completed(host, EVENT_NOTBUSY); ++ ++ if (host->data) { ++ /* ++ * For some commands such as CMD53, even if ++ * there is data transfer, there is no stop ++ * command to send. ++ */ ++ if (host->mrq->stop) { ++ atmci_writel(host, ATMCI_IER, ++ ATMCI_CMDRDY); ++ atmci_send_stop_cmd(host, data); ++ state = STATE_SENDING_STOP; ++ } else { ++ host->data = NULL; ++ data->bytes_xfered = data->blocks ++ * data->blksz; ++ data->error = 0; ++ state = STATE_END_REQUEST; ++ } ++ } else ++ state = STATE_END_REQUEST; ++ break; + + case STATE_SENDING_STOP: ++ /* ++ * In this state, it is important to set host->data to ++ * NULL (which is tested in the waiting notbusy state) ++ * in order to go to the end request state instead of ++ * sending stop again. ++ */ ++ dev_dbg(&host->pdev->dev, "FSM: cmd ready?\n"); + if (!atmci_test_and_clear_pending(host, +- EVENT_CMD_COMPLETE)) ++ EVENT_CMD_RDY)) + break; + ++ dev_dbg(&host->pdev->dev, "FSM: cmd ready\n"); + host->cmd = NULL; ++ data->bytes_xfered = data->blocks * data->blksz; ++ data->error = 0; + atmci_command_complete(host, mrq->stop); +- atmci_request_end(host, host->mrq); +- goto unlock; ++ if (mrq->stop->error) { ++ host->stop_transfer(host); ++ atmci_writel(host, ATMCI_IDR, ++ ATMCI_TXRDY | ATMCI_RXRDY ++ | ATMCI_DATA_ERROR_FLAGS); ++ state = STATE_END_REQUEST; ++ } else { ++ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); ++ state = STATE_WAITING_NOTBUSY; ++ } ++ host->data = NULL; ++ break; + +- case STATE_DATA_ERROR: +- if (!atmci_test_and_clear_pending(host, +- EVENT_XFER_COMPLETE)) +- break; ++ case STATE_END_REQUEST: ++ atmci_writel(host, ATMCI_IDR, ATMCI_TXRDY | ATMCI_RXRDY ++ | ATMCI_DATA_ERROR_FLAGS); ++ status = host->data_status; ++ if (unlikely(status)) { ++ host->stop_transfer(host); ++ host->data = NULL; ++ if (data) { ++ if (status & ATMCI_DTOE) { ++ data->error = -ETIMEDOUT; ++ } else if (status & ATMCI_DCRCE) { ++ data->error = -EILSEQ; ++ } else { ++ data->error = -EIO; ++ } ++ } ++ } + +- state = STATE_DATA_BUSY; ++ atmci_request_end(host, host->mrq); ++ state = STATE_IDLE; + break; + } + } while (state != prev_state); + + host->state = state; + +-unlock: + spin_unlock(&host->lock); + } + +@@ -1616,9 +1893,6 @@ static void atmci_read_data_pio(struct atmel_mci *host) + | ATMCI_DATA_ERROR_FLAGS)); + host->data_status = status; + data->bytes_xfered += nbytes; +- smp_wmb(); +- atmci_set_pending(host, EVENT_DATA_ERROR); +- tasklet_schedule(&host->tasklet); + return; + } + } while (status & ATMCI_RXRDY); +@@ -1689,9 +1963,6 @@ static void atmci_write_data_pio(struct atmel_mci *host) + | ATMCI_DATA_ERROR_FLAGS)); + host->data_status = status; + data->bytes_xfered += nbytes; +- smp_wmb(); +- atmci_set_pending(host, EVENT_DATA_ERROR); +- tasklet_schedule(&host->tasklet); + return; + } + } while (status & ATMCI_TXRDY); +@@ -1709,16 +1980,6 @@ done: + atmci_set_pending(host, EVENT_XFER_COMPLETE); + } + +-static void atmci_cmd_interrupt(struct atmel_mci *host, u32 status) +-{ +- atmci_writel(host, ATMCI_IDR, ATMCI_CMDRDY); +- +- host->cmd_status = status; +- smp_wmb(); +- atmci_set_pending(host, EVENT_CMD_COMPLETE); +- tasklet_schedule(&host->tasklet); +-} +- + static void atmci_sdio_interrupt(struct atmel_mci *host, u32 status) + { + int i; +@@ -1746,17 +2007,21 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) + break; + + if (pending & ATMCI_DATA_ERROR_FLAGS) { ++ dev_dbg(&host->pdev->dev, "IRQ: data error\n"); + atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS +- | ATMCI_RXRDY | ATMCI_TXRDY); +- pending &= atmci_readl(host, ATMCI_IMR); ++ | ATMCI_RXRDY | ATMCI_TXRDY ++ | ATMCI_ENDRX | ATMCI_ENDTX ++ | ATMCI_RXBUFF | ATMCI_TXBUFE); + + host->data_status = status; ++ dev_dbg(&host->pdev->dev, "set pending data error\n"); + smp_wmb(); + atmci_set_pending(host, EVENT_DATA_ERROR); + tasklet_schedule(&host->tasklet); + } + + if (pending & ATMCI_TXBUFE) { ++ dev_dbg(&host->pdev->dev, "IRQ: tx buffer empty\n"); + atmci_writel(host, ATMCI_IDR, ATMCI_TXBUFE); + atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX); + /* +@@ -1772,6 +2037,7 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) + atmci_pdc_complete(host); + } + } else if (pending & ATMCI_ENDTX) { ++ dev_dbg(&host->pdev->dev, "IRQ: end of tx buffer\n"); + atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX); + + if (host->data_size) { +@@ -1782,6 +2048,7 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) + } + + if (pending & ATMCI_RXBUFF) { ++ dev_dbg(&host->pdev->dev, "IRQ: rx buffer full\n"); + atmci_writel(host, ATMCI_IDR, ATMCI_RXBUFF); + atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX); + /* +@@ -1797,6 +2064,7 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) + atmci_pdc_complete(host); + } + } else if (pending & ATMCI_ENDRX) { ++ dev_dbg(&host->pdev->dev, "IRQ: end of rx buffer\n"); + atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX); + + if (host->data_size) { +@@ -1806,23 +2074,44 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) + } + } + ++ /* ++ * First mci IPs, so mainly the ones having pdc, have some ++ * issues with the notbusy signal. You can't get it after ++ * data transmission if you have not sent a stop command. ++ * The appropriate workaround is to use the BLKE signal. ++ */ ++ if (pending & ATMCI_BLKE) { ++ dev_dbg(&host->pdev->dev, "IRQ: blke\n"); ++ atmci_writel(host, ATMCI_IDR, ATMCI_BLKE); ++ smp_wmb(); ++ dev_dbg(&host->pdev->dev, "set pending notbusy\n"); ++ atmci_set_pending(host, EVENT_NOTBUSY); ++ tasklet_schedule(&host->tasklet); ++ } + + if (pending & ATMCI_NOTBUSY) { +- atmci_writel(host, ATMCI_IDR, +- ATMCI_DATA_ERROR_FLAGS | ATMCI_NOTBUSY); +- if (!host->data_status) +- host->data_status = status; ++ dev_dbg(&host->pdev->dev, "IRQ: not_busy\n"); ++ atmci_writel(host, ATMCI_IDR, ATMCI_NOTBUSY); + smp_wmb(); +- atmci_set_pending(host, EVENT_DATA_COMPLETE); ++ dev_dbg(&host->pdev->dev, "set pending notbusy\n"); ++ atmci_set_pending(host, EVENT_NOTBUSY); + tasklet_schedule(&host->tasklet); + } ++ + if (pending & ATMCI_RXRDY) + atmci_read_data_pio(host); + if (pending & ATMCI_TXRDY) + atmci_write_data_pio(host); + +- if (pending & ATMCI_CMDRDY) +- atmci_cmd_interrupt(host, status); ++ if (pending & ATMCI_CMDRDY) { ++ dev_dbg(&host->pdev->dev, "IRQ: cmd ready\n"); ++ atmci_writel(host, ATMCI_IDR, ATMCI_CMDRDY); ++ host->cmd_status = status; ++ smp_wmb(); ++ dev_dbg(&host->pdev->dev, "set pending cmd rdy\n"); ++ atmci_set_pending(host, EVENT_CMD_RDY); ++ tasklet_schedule(&host->tasklet); ++ } + + if (pending & (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB)) + atmci_sdio_interrupt(host, status); +@@ -1867,6 +2156,13 @@ static int __init atmci_init_slot(struct atmel_mci *host, + slot->sdc_reg = sdc_reg; + slot->sdio_irq = sdio_irq; + ++ dev_dbg(&mmc->class_dev, ++ "slot[%u]: bus_width=%u, detect_pin=%d, " ++ "detect_is_active_high=%s, wp_pin=%d\n", ++ id, slot_data->bus_width, slot_data->detect_pin, ++ slot_data->detect_is_active_high ? "true" : "false", ++ slot_data->wp_pin); ++ + mmc->ops = &atmci_ops; + mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); + mmc->f_max = host->bus_hz / 2; +@@ -1875,13 +2171,26 @@ static int __init atmci_init_slot(struct atmel_mci *host, + mmc->caps |= MMC_CAP_SDIO_IRQ; + if (host->caps.has_highspeed) + mmc->caps |= MMC_CAP_SD_HIGHSPEED; +- if (slot_data->bus_width >= 4) ++ /* ++ * Without the read/write proof capability, it is strongly suggested to ++ * use only one bit for data to prevent fifo underruns and overruns ++ * which will corrupt data. ++ */ ++ if ((slot_data->bus_width >= 4) && host->caps.has_rwproof) + mmc->caps |= MMC_CAP_4_BIT_DATA; + +- mmc->max_segs = 64; +- mmc->max_req_size = 32768 * 512; +- mmc->max_blk_size = 32768; +- mmc->max_blk_count = 512; ++ if (atmci_get_version(host) < 0x200) { ++ mmc->max_segs = 256; ++ mmc->max_blk_size = 4095; ++ mmc->max_blk_count = 256; ++ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; ++ mmc->max_seg_size = mmc->max_blk_size * mmc->max_segs; ++ } else { ++ mmc->max_segs = 64; ++ mmc->max_req_size = 32768 * 512; ++ mmc->max_blk_size = 32768; ++ mmc->max_blk_count = 512; ++ } + + /* Assume card is present initially */ + set_bit(ATMCI_CARD_PRESENT, &slot->flags); +@@ -1906,6 +2215,7 @@ static int __init atmci_init_slot(struct atmel_mci *host, + } + + host->slot[id] = slot; ++ mmc_regulator_get_supply(mmc); + mmc_add_host(mmc); + + if (gpio_is_valid(slot->detect_pin)) { +@@ -1956,10 +2266,15 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot, + mmc_free_host(slot->mmc); + } + +-static bool atmci_filter(struct dma_chan *chan, void *slave) ++static bool atmci_filter(struct dma_chan *chan, void *pdata) + { +- struct mci_dma_data *sl = slave; ++ struct mci_platform_data *sl_pdata = pdata; ++ struct mci_dma_data *sl; + ++ if (!sl_pdata) ++ return false; ++ ++ sl = sl_pdata->dma_slave; + if (sl && find_slave_dev(sl) == chan->device->dev) { + chan->private = slave_data_ptr(sl); + return true; +@@ -1971,41 +2286,37 @@ static bool atmci_filter(struct dma_chan *chan, void *slave) + static bool atmci_configure_dma(struct atmel_mci *host) + { + struct mci_platform_data *pdata; ++ dma_cap_mask_t mask; + + if (host == NULL) + return false; + + pdata = host->pdev->dev.platform_data; + +- if (pdata && find_slave_dev(pdata->dma_slave)) { +- dma_cap_mask_t mask; +- +- setup_dma_addr(pdata->dma_slave, +- host->mapbase + ATMCI_TDR, +- host->mapbase + ATMCI_RDR); ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); + +- /* Try to grab a DMA channel */ +- dma_cap_zero(mask); +- dma_cap_set(DMA_SLAVE, mask); +- host->dma.chan = +- dma_request_channel(mask, atmci_filter, pdata->dma_slave); +- } ++ host->dma.chan = dma_request_slave_channel_compat(mask, atmci_filter, pdata, ++ &host->pdev->dev, "rxtx"); + if (!host->dma.chan) { + dev_warn(&host->pdev->dev, "no DMA channel available\n"); + return false; + } else { + dev_info(&host->pdev->dev, +- "Using %s for DMA transfers\n", ++ "using %s for DMA transfers\n", + dma_chan_name(host->dma.chan)); ++ ++ host->dma_conf.src_addr = host->mapbase + ATMCI_RDR; ++ host->dma_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ host->dma_conf.src_maxburst = 1; ++ host->dma_conf.dst_addr = host->mapbase + ATMCI_TDR; ++ host->dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ host->dma_conf.dst_maxburst = 1; ++ host->dma_conf.device_fc = false; + return true; + } + } + +-static inline unsigned int atmci_get_version(struct atmel_mci *host) +-{ +- return atmci_readl(host, ATMCI_VERSION) & 0x00000fff; +-} +- + /* + * HSMCI (High Speed MCI) module is not fully compatible with MCI module. + * HSMCI provides DMA support and a new config register but no more supports +@@ -2019,36 +2330,40 @@ static void __init atmci_get_cap(struct atmel_mci *host) + dev_info(&host->pdev->dev, + "version: 0x%x\n", version); + +- host->caps.has_dma = 0; +- host->caps.has_pdc = 0; ++ host->caps.has_dma_conf_reg = 0; ++ host->caps.has_pdc = ATMCI_PDC_CONNECTED; + host->caps.has_cfg_reg = 0; + host->caps.has_cstor_reg = 0; + host->caps.has_highspeed = 0; + host->caps.has_rwproof = 0; ++ host->caps.has_odd_clk_div = 0; ++ host->caps.has_bad_data_ordering = 1; ++ host->caps.need_reset_after_xfer = 1; ++ host->caps.need_blksz_mul_4 = 1; ++ host->caps.need_notbusy_for_read_ops = 0; + + /* keep only major version number */ + switch (version & 0xf00) { +- case 0x100: +- case 0x200: +- host->caps.has_pdc = 1; +- host->caps.has_rwproof = 1; +- break; +- case 0x300: +- case 0x400: + case 0x500: +-#ifdef CONFIG_AT_HDMAC +- host->caps.has_dma = 1; +-#else +- host->caps.has_dma = 0; +- dev_info(&host->pdev->dev, +- "has dma capability but dma engine is not selected, then use pio\n"); +-#endif ++ host->caps.has_odd_clk_div = 1; ++ case 0x400: ++ case 0x300: ++ host->caps.has_dma_conf_reg = 1; ++ host->caps.has_pdc = 0; + host->caps.has_cfg_reg = 1; + host->caps.has_cstor_reg = 1; + host->caps.has_highspeed = 1; ++ case 0x200: + host->caps.has_rwproof = 1; ++ host->caps.need_blksz_mul_4 = 0; ++ host->caps.need_notbusy_for_read_ops = 1; ++ case 0x100: ++ host->caps.has_bad_data_ordering = 0; ++ host->caps.need_reset_after_xfer = 0; ++ case 0x0: + break; + default: ++ host->caps.has_pdc = 0; + dev_warn(&host->pdev->dev, + "Unmanaged mci version, set minimum capabilities\n"); + break; +@@ -2068,8 +2383,14 @@ static int __init atmci_probe(struct platform_device *pdev) + if (!regs) + return -ENXIO; + pdata = pdev->dev.platform_data; +- if (!pdata) +- return -ENXIO; ++ if (!pdata) { ++ pdata = atmci_of_init(pdev); ++ if (IS_ERR(pdata)) { ++ dev_err(&pdev->dev, "platform data not available\n"); ++ return PTR_ERR(pdata); ++ } ++ } ++ + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; +@@ -2093,10 +2414,12 @@ static int __init atmci_probe(struct platform_device *pdev) + if (!host->regs) + goto err_ioremap; + +- clk_enable(host->mck); ++ ret = clk_prepare_enable(host->mck); ++ if (ret) ++ goto err_request_irq; + atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); + host->bus_hz = clk_get_rate(host->mck); +- clk_disable(host->mck); ++ clk_disable_unprepare(host->mck); + + host->mapbase = regs->start; + +@@ -2108,7 +2431,7 @@ static int __init atmci_probe(struct platform_device *pdev) + + /* Get MCI capabilities and set operations according to it */ + atmci_get_cap(host); +- if (host->caps.has_dma && atmci_configure_dma(host)) { ++ if (atmci_configure_dma(host)) { + host->prepare_data = &atmci_prepare_data_dma; + host->submit_data = &atmci_submit_data_dma; + host->stop_transfer = &atmci_stop_transfer_dma; +@@ -2126,20 +2449,28 @@ static int __init atmci_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, host); + ++ setup_timer(&host->timer, atmci_timeout_timer, (unsigned long)host); ++ + /* We need at least one slot to succeed */ + nr_slots = 0; + ret = -ENODEV; + if (pdata->slot[0].bus_width) { + ret = atmci_init_slot(host, &pdata->slot[0], + 0, ATMCI_SDCSEL_SLOT_A, ATMCI_SDIOIRQA); +- if (!ret) ++ if (!ret) { + nr_slots++; ++ host->buf_size = host->slot[0]->mmc->max_req_size; ++ } + } + if (pdata->slot[1].bus_width) { + ret = atmci_init_slot(host, &pdata->slot[1], + 1, ATMCI_SDCSEL_SLOT_B, ATMCI_SDIOIRQB); +- if (!ret) ++ if (!ret) { + nr_slots++; ++ if (host->slot[1]->mmc->max_req_size > host->buf_size) ++ host->buf_size = ++ host->slot[1]->mmc->max_req_size; ++ } + } + + if (!nr_slots) { +@@ -2147,6 +2478,17 @@ static int __init atmci_probe(struct platform_device *pdev) + goto err_init_slot; + } + ++ if (!host->caps.has_rwproof) { ++ host->buffer = dma_alloc_coherent(&pdev->dev, host->buf_size, ++ &host->buf_phys_addr, ++ GFP_KERNEL); ++ if (!host->buffer) { ++ ret = -ENOMEM; ++ dev_err(&pdev->dev, "buffer allocation failed\n"); ++ goto err_init_slot; ++ } ++ } ++ + dev_info(&pdev->dev, + "Atmel MCI controller at 0x%08lx irq %d, %u slots\n", + host->mapbase, irq, nr_slots); +@@ -2171,18 +2513,20 @@ static int __exit atmci_remove(struct platform_device *pdev) + struct atmel_mci *host = platform_get_drvdata(pdev); + unsigned int i; + +- platform_set_drvdata(pdev, NULL); ++ if (host->buffer) ++ dma_free_coherent(&pdev->dev, host->buf_size, ++ host->buffer, host->buf_phys_addr); + + for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { + if (host->slot[i]) + atmci_cleanup_slot(host->slot[i], i); + } + +- clk_enable(host->mck); ++ clk_prepare_enable(host->mck); + atmci_writel(host, ATMCI_IDR, ~0UL); + atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS); + atmci_readl(host, ATMCI_SR); +- clk_disable(host->mck); ++ clk_disable_unprepare(host->mck); + + if (host->dma.chan) + dma_release_channel(host->dma.chan); +@@ -2196,72 +2540,11 @@ static int __exit atmci_remove(struct platform_device *pdev) + return 0; + } + +-#ifdef CONFIG_PM +-static int atmci_suspend(struct device *dev) +-{ +- struct atmel_mci *host = dev_get_drvdata(dev); +- int i; +- +- for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { +- struct atmel_mci_slot *slot = host->slot[i]; +- int ret; +- +- if (!slot) +- continue; +- ret = mmc_suspend_host(slot->mmc); +- if (ret < 0) { +- while (--i >= 0) { +- slot = host->slot[i]; +- if (slot +- && test_bit(ATMCI_SUSPENDED, &slot->flags)) { +- mmc_resume_host(host->slot[i]->mmc); +- clear_bit(ATMCI_SUSPENDED, &slot->flags); +- } +- } +- return ret; +- } else { +- set_bit(ATMCI_SUSPENDED, &slot->flags); +- } +- } +- +- return 0; +-} +- +-static int atmci_resume(struct device *dev) +-{ +- struct atmel_mci *host = dev_get_drvdata(dev); +- int i; +- int ret = 0; +- +- for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { +- struct atmel_mci_slot *slot = host->slot[i]; +- int err; +- +- slot = host->slot[i]; +- if (!slot) +- continue; +- if (!test_bit(ATMCI_SUSPENDED, &slot->flags)) +- continue; +- err = mmc_resume_host(slot->mmc); +- if (err < 0) +- ret = err; +- else +- clear_bit(ATMCI_SUSPENDED, &slot->flags); +- } +- +- return ret; +-} +-static SIMPLE_DEV_PM_OPS(atmci_pm, atmci_suspend, atmci_resume); +-#define ATMCI_PM_OPS (&atmci_pm) +-#else +-#define ATMCI_PM_OPS NULL +-#endif +- + static struct platform_driver atmci_driver = { + .remove = __exit_p(atmci_remove), + .driver = { + .name = "atmel_mci", +- .pm = ATMCI_PM_OPS, ++ .of_match_table = of_match_ptr(atmci_dt_ids), + }, + }; + +diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c +index 5d3b9ae..f5443a6 100644 +--- a/drivers/mmc/host/au1xmmc.c ++++ b/drivers/mmc/host/au1xmmc.c +@@ -153,6 +153,7 @@ static inline int has_dbdma(void) + { + switch (alchemy_get_cputype()) { + case ALCHEMY_CPU_AU1200: ++ case ALCHEMY_CPU_AU1300: + return 1; + default: + return 0; +@@ -768,11 +769,15 @@ static void au1xmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + + config2 = au_readl(HOST_CONFIG2(host)); + switch (ios->bus_width) { ++ case MMC_BUS_WIDTH_8: ++ config2 |= SD_CONFIG2_BB; ++ break; + case MMC_BUS_WIDTH_4: ++ config2 &= ~SD_CONFIG2_BB; + config2 |= SD_CONFIG2_WB; + break; + case MMC_BUS_WIDTH_1: +- config2 &= ~SD_CONFIG2_WB; ++ config2 &= ~(SD_CONFIG2_WB | SD_CONFIG2_BB); + break; + } + au_writel(config2, HOST_CONFIG2(host)); +@@ -938,12 +943,12 @@ static const struct mmc_host_ops au1xmmc_ops = { + .enable_sdio_irq = au1xmmc_enable_sdio_irq, + }; + +-static int __devinit au1xmmc_probe(struct platform_device *pdev) ++static int au1xmmc_probe(struct platform_device *pdev) + { + struct mmc_host *mmc; + struct au1xmmc_host *host; + struct resource *r; +- int ret; ++ int ret, iflag; + + mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev); + if (!mmc) { +@@ -982,37 +987,43 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "no IRQ defined\n"); + goto out3; + } +- + host->irq = r->start; +- /* IRQ is shared among both SD controllers */ +- ret = request_irq(host->irq, au1xmmc_irq, IRQF_SHARED, +- DRIVER_NAME, host); +- if (ret) { +- dev_err(&pdev->dev, "cannot grab IRQ\n"); +- goto out3; +- } + + mmc->ops = &au1xmmc_ops; + + mmc->f_min = 450000; + mmc->f_max = 24000000; + ++ mmc->max_blk_size = 2048; ++ mmc->max_blk_count = 512; ++ ++ mmc->ocr_avail = AU1XMMC_OCR; ++ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; ++ mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT; ++ ++ iflag = IRQF_SHARED; /* Au1100/Au1200: one int for both ctrls */ ++ + switch (alchemy_get_cputype()) { + case ALCHEMY_CPU_AU1100: + mmc->max_seg_size = AU1100_MMC_DESCRIPTOR_SIZE; +- mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT; + break; + case ALCHEMY_CPU_AU1200: + mmc->max_seg_size = AU1200_MMC_DESCRIPTOR_SIZE; +- mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT; ++ break; ++ case ALCHEMY_CPU_AU1300: ++ iflag = 0; /* nothing is shared */ ++ mmc->max_seg_size = AU1200_MMC_DESCRIPTOR_SIZE; ++ mmc->f_max = 52000000; ++ if (host->ioarea->start == AU1100_SD0_PHYS_ADDR) ++ mmc->caps |= MMC_CAP_8_BIT_DATA; + break; + } + +- mmc->max_blk_size = 2048; +- mmc->max_blk_count = 512; +- +- mmc->ocr_avail = AU1XMMC_OCR; +- mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; ++ ret = request_irq(host->irq, au1xmmc_irq, iflag, DRIVER_NAME, host); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot grab IRQ\n"); ++ goto out3; ++ } + + host->status = HOST_S_IDLE; + +@@ -1103,7 +1114,7 @@ out0: + return ret; + } + +-static int __devexit au1xmmc_remove(struct platform_device *pdev) ++static int au1xmmc_remove(struct platform_device *pdev) + { + struct au1xmmc_host *host = platform_get_drvdata(pdev); + +@@ -1138,7 +1149,6 @@ static int __devexit au1xmmc_remove(struct platform_device *pdev) + kfree(host->ioarea); + + mmc_free_host(host->mmc); +- platform_set_drvdata(pdev, NULL); + } + return 0; + } +@@ -1147,11 +1157,6 @@ static int __devexit au1xmmc_remove(struct platform_device *pdev) + static int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state) + { + struct au1xmmc_host *host = platform_get_drvdata(pdev); +- int ret; +- +- ret = mmc_suspend_host(host->mmc); +- if (ret) +- return ret; + + au_writel(0, HOST_CONFIG2(host)); + au_writel(0, HOST_CONFIG(host)); +@@ -1168,7 +1173,7 @@ static int au1xmmc_resume(struct platform_device *pdev) + + au1xmmc_reset_controller(host); + +- return mmc_resume_host(host->mmc); ++ return 0; + } + #else + #define au1xmmc_suspend NULL +diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c +index 0371bf5..2b7f37e 100644 +--- a/drivers/mmc/host/bfin_sdh.c ++++ b/drivers/mmc/host/bfin_sdh.c +@@ -24,9 +24,7 @@ + #include + #include + +-#if defined(CONFIG_BF51x) +-#define bfin_read_SDH_PWR_CTL bfin_read_RSI_PWR_CTL +-#define bfin_write_SDH_PWR_CTL bfin_write_RSI_PWR_CTL ++#if defined(CONFIG_BF51x) || defined(__ADSPBF60x__) + #define bfin_read_SDH_CLK_CTL bfin_read_RSI_CLK_CTL + #define bfin_write_SDH_CLK_CTL bfin_write_RSI_CLK_CTL + #define bfin_write_SDH_ARGUMENT bfin_write_RSI_ARGUMENT +@@ -45,17 +43,18 @@ + #define bfin_write_SDH_E_STATUS bfin_write_RSI_E_STATUS + #define bfin_read_SDH_STATUS bfin_read_RSI_STATUS + #define bfin_write_SDH_MASK0 bfin_write_RSI_MASK0 ++#define bfin_write_SDH_E_MASK bfin_write_RSI_E_MASK + #define bfin_read_SDH_CFG bfin_read_RSI_CFG + #define bfin_write_SDH_CFG bfin_write_RSI_CFG ++# if defined(__ADSPBF60x__) ++# define bfin_read_SDH_BLK_SIZE bfin_read_RSI_BLKSZ ++# define bfin_write_SDH_BLK_SIZE bfin_write_RSI_BLKSZ ++# else ++# define bfin_read_SDH_PWR_CTL bfin_read_RSI_PWR_CTL ++# define bfin_write_SDH_PWR_CTL bfin_write_RSI_PWR_CTL ++# endif + #endif + +-struct dma_desc_array { +- unsigned long start_addr; +- unsigned short cfg; +- unsigned short x_count; +- short x_modify; +-} __packed; +- + struct sdh_host { + struct mmc_host *mmc; + spinlock_t lock; +@@ -69,6 +68,7 @@ struct sdh_host { + dma_addr_t sg_dma; + int dma_len; + ++ unsigned long sclk; + unsigned int imask; + unsigned int power_mode; + unsigned int clk_div; +@@ -134,11 +134,15 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) + /* Only supports power-of-2 block size */ + if (data->blksz & (data->blksz - 1)) + return -EINVAL; ++#ifndef RSI_BLKSZ + data_ctl |= ((ffs(data->blksz) - 1) << 4); ++#else ++ bfin_write_SDH_BLK_SIZE(data->blksz); ++#endif + + bfin_write_SDH_DATA_CTL(data_ctl); + /* the time of a host clock period in ns */ +- cycle_ns = 1000000000 / (get_sclk() / (2 * (host->clk_div + 1))); ++ cycle_ns = 1000000000 / (host->sclk / (2 * (host->clk_div + 1))); + timeout = data->timeout_ns / cycle_ns; + timeout += data->timeout_clks; + bfin_write_SDH_DATA_TIMER(timeout); +@@ -152,8 +156,13 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) + + sdh_enable_stat_irq(host, (DAT_CRC_FAIL | DAT_TIME_OUT | DAT_END)); + host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir); +-#if defined(CONFIG_BF54x) +- dma_cfg |= DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_32 | DMAEN; ++#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) ++ dma_cfg |= DMAFLOW_ARRAY | RESTART | WDSIZE_32 | DMAEN; ++# ifdef RSI_BLKSZ ++ dma_cfg |= PSIZE_32 | NDSIZE_3; ++# else ++ dma_cfg |= NDSIZE_5; ++# endif + { + struct scatterlist *sg; + int i; +@@ -163,7 +172,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) + host->sg_cpu[i].x_count = sg_dma_len(sg) / 4; + host->sg_cpu[i].x_modify = 4; + dev_dbg(mmc_dev(host->mmc), "%d: start_addr:0x%lx, " +- "cfg:0x%x, x_count:0x%x, x_modify:0x%x\n", ++ "cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n", + i, host->sg_cpu[i].start_addr, + host->sg_cpu[i].cfg, host->sg_cpu[i].x_count, + host->sg_cpu[i].x_modify); +@@ -179,6 +188,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) + set_dma_curr_desc_addr(host->dma_ch, (unsigned long *)host->sg_dma); + set_dma_x_count(host->dma_ch, 0); + set_dma_x_modify(host->dma_ch, 0); ++ SSYNC(); + set_dma_config(host->dma_ch, dma_cfg); + #elif defined(CONFIG_BF51x) + /* RSI DMA doesn't work in array mode */ +@@ -186,6 +196,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) + set_dma_start_addr(host->dma_ch, sg_dma_address(&data->sg[0])); + set_dma_x_count(host->dma_ch, length / 4); + set_dma_x_modify(host->dma_ch, 4); ++ SSYNC(); + set_dma_config(host->dma_ch, dma_cfg); + #endif + bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E); +@@ -303,7 +314,6 @@ static int sdh_data_done(struct sdh_host *host, unsigned int stat) + else + data->bytes_xfered = 0; + +- sdh_disable_stat_irq(host, DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN); + bfin_write_SDH_STATUS_CLR(DAT_END_STAT | DAT_TIMEOUT_STAT | \ + DAT_CRC_FAIL_STAT | DAT_BLK_END_STAT | RX_OVERRUN | TX_UNDERRUN); + bfin_write_SDH_DATA_CTL(0); +@@ -328,74 +338,114 @@ static void sdh_request(struct mmc_host *mmc, struct mmc_request *mrq) + dev_dbg(mmc_dev(host->mmc), "%s enter, mrp:%p, cmd:%p\n", __func__, mrq, mrq->cmd); + WARN_ON(host->mrq != NULL); + ++ spin_lock(&host->lock); + host->mrq = mrq; + host->data = mrq->data; + + if (mrq->data && mrq->data->flags & MMC_DATA_READ) { + ret = sdh_setup_data(host, mrq->data); + if (ret) +- return; ++ goto data_err; + } + + sdh_start_cmd(host, mrq->cmd); ++data_err: ++ spin_unlock(&host->lock); + } + + static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct sdh_host *host; +- unsigned long flags; + u16 clk_ctl = 0; ++#ifndef RSI_BLKSZ + u16 pwr_ctl = 0; ++#endif + u16 cfg; + host = mmc_priv(mmc); + +- spin_lock_irqsave(&host->lock, flags); +- if (ios->clock) { +- unsigned long sys_clk, ios_clk; +- unsigned char clk_div; +- ios_clk = 2 * ios->clock; +- sys_clk = get_sclk(); +- clk_div = sys_clk / ios_clk; +- if (sys_clk % ios_clk == 0) +- clk_div -= 1; +- clk_div = min_t(unsigned char, clk_div, 0xFF); +- clk_ctl |= clk_div; +- clk_ctl |= CLK_E; +- host->clk_div = clk_div; +- } else +- sdh_stop_clock(host); +- +- if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) +-#ifdef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND +- pwr_ctl |= ROD_CTL; +-#else +- pwr_ctl |= SD_CMD_OD | ROD_CTL; +-#endif ++ spin_lock(&host->lock); + +- if (ios->bus_width == MMC_BUS_WIDTH_4) { +- cfg = bfin_read_SDH_CFG(); ++ cfg = bfin_read_SDH_CFG(); ++ cfg |= MWE; ++ switch (ios->bus_width) { ++ case MMC_BUS_WIDTH_4: ++#ifndef RSI_BLKSZ + cfg &= ~PD_SDDAT3; ++#endif + cfg |= PUP_SDDAT3; + /* Enable 4 bit SDIO */ +- cfg |= (SD4E | MWE); +- bfin_write_SDH_CFG(cfg); +- clk_ctl |= WIDE_BUS; +- } else { +- cfg = bfin_read_SDH_CFG(); +- cfg |= MWE; +- bfin_write_SDH_CFG(cfg); ++ cfg |= SD4E; ++ clk_ctl |= WIDE_BUS_4; ++ break; ++ case MMC_BUS_WIDTH_8: ++#ifndef RSI_BLKSZ ++ cfg &= ~PD_SDDAT3; ++#endif ++ cfg |= PUP_SDDAT3; ++ /* Disable 4 bit SDIO */ ++ cfg &= ~SD4E; ++ clk_ctl |= BYTE_BUS_8; ++ break; ++ default: ++ cfg &= ~PUP_SDDAT3; ++ /* Disable 4 bit SDIO */ ++ cfg &= ~SD4E; + } +- +- bfin_write_SDH_CLK_CTL(clk_ctl); ++ bfin_write_SDH_CFG(cfg); + + host->power_mode = ios->power_mode; +- if (ios->power_mode == MMC_POWER_ON) ++#ifndef RSI_BLKSZ ++ if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) { ++ pwr_ctl |= ROD_CTL; ++# ifndef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND ++ pwr_ctl |= SD_CMD_OD; ++# endif ++ } ++ ++ if (ios->power_mode != MMC_POWER_OFF) + pwr_ctl |= PWR_ON; ++ else ++ pwr_ctl &= ~PWR_ON; + + bfin_write_SDH_PWR_CTL(pwr_ctl); ++#else ++# ifndef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND ++ if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) ++ cfg |= SD_CMD_OD; ++ else ++ cfg &= ~SD_CMD_OD; ++# endif ++ ++ if (ios->power_mode != MMC_POWER_OFF) ++ cfg |= PWR_ON; ++ else ++ cfg &= ~PWR_ON; ++ ++ bfin_write_SDH_CFG(cfg); ++#endif + SSYNC(); + +- spin_unlock_irqrestore(&host->lock, flags); ++ if (ios->power_mode == MMC_POWER_ON && ios->clock) { ++ unsigned char clk_div; ++ clk_div = (get_sclk() / ios->clock - 1) / 2; ++ clk_div = min_t(unsigned char, clk_div, 0xFF); ++ clk_ctl |= clk_div; ++ clk_ctl |= CLK_E; ++ host->clk_div = clk_div; ++ bfin_write_SDH_CLK_CTL(clk_ctl); ++ } else ++ sdh_stop_clock(host); ++ ++ /* set up sdh interrupt mask*/ ++ if (ios->power_mode == MMC_POWER_ON) ++ bfin_write_SDH_MASK0(DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | ++ RX_OVERRUN | TX_UNDERRUN | CMD_SENT | CMD_RESP_END | ++ CMD_TIME_OUT | CMD_CRC_FAIL); ++ else ++ bfin_write_SDH_MASK0(0); ++ SSYNC(); ++ ++ spin_unlock(&host->lock); + + dev_dbg(mmc_dev(host->mmc), "SDH: clk_div = 0x%x actual clock:%ld expected clock:%d\n", + host->clk_div, +@@ -412,7 +462,7 @@ static irqreturn_t sdh_dma_irq(int irq, void *devid) + { + struct sdh_host *host = devid; + +- dev_dbg(mmc_dev(host->mmc), "%s enter, irq_stat: 0x%04x\n", __func__, ++ dev_dbg(mmc_dev(host->mmc), "%s enter, irq_stat: 0x%04lx\n", __func__, + get_dma_curr_irqstat(host->dma_ch)); + clear_dma_irqstat(host->dma_ch); + SSYNC(); +@@ -427,6 +477,9 @@ static irqreturn_t sdh_stat_irq(int irq, void *devid) + int handled = 0; + + dev_dbg(mmc_dev(host->mmc), "%s enter\n", __func__); ++ ++ spin_lock(&host->lock); ++ + status = bfin_read_SDH_E_STATUS(); + if (status & SD_CARD_DET) { + mmc_detect_change(host->mmc, 0); +@@ -444,12 +497,31 @@ static irqreturn_t sdh_stat_irq(int irq, void *devid) + if (status & (DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN)) + handled |= sdh_data_done(host, status); + ++ spin_unlock(&host->lock); ++ + dev_dbg(mmc_dev(host->mmc), "%s exit\n\n", __func__); + + return IRQ_RETVAL(handled); + } + +-static int __devinit sdh_probe(struct platform_device *pdev) ++static void sdh_reset(void) ++{ ++#if defined(CONFIG_BF54x) ++ /* Secure Digital Host shares DMA with Nand controller */ ++ bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); ++#endif ++ ++ bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); ++ SSYNC(); ++ ++ /* Disable card inserting detection pin. set MMC_CAP_NEEDS_POLL, and ++ * mmc stack will do the detection. ++ */ ++ bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3)); ++ SSYNC(); ++} ++ ++static int sdh_probe(struct platform_device *pdev) + { + struct mmc_host *mmc; + struct sdh_host *host; +@@ -469,8 +541,16 @@ static int __devinit sdh_probe(struct platform_device *pdev) + } + + mmc->ops = &sdh_ops; +- mmc->max_segs = 32; ++#if defined(CONFIG_BF51x) ++ mmc->max_segs = 1; ++#else ++ mmc->max_segs = PAGE_SIZE / sizeof(struct dma_desc_array); ++#endif ++#ifdef RSI_BLKSZ ++ mmc->max_seg_size = -1; ++#else + mmc->max_seg_size = 1 << 16; ++#endif + mmc->max_blk_size = 1 << 11; + mmc->max_blk_count = 1 << 11; + mmc->max_req_size = PAGE_SIZE; +@@ -480,6 +560,7 @@ static int __devinit sdh_probe(struct platform_device *pdev) + mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL; + host = mmc_priv(mmc); + host->mmc = mmc; ++ host->sclk = get_sclk(); + + spin_lock_init(&host->lock); + host->irq = drv_data->irq_int0; +@@ -504,7 +585,6 @@ static int __devinit sdh_probe(struct platform_device *pdev) + } + + platform_set_drvdata(pdev, mmc); +- mmc_add_host(mmc); + + ret = request_irq(host->irq, sdh_stat_irq, 0, "SDH Status IRQ", host); + if (ret) { +@@ -517,20 +597,10 @@ static int __devinit sdh_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "unable to request peripheral pins\n"); + goto out4; + } +-#if defined(CONFIG_BF54x) +- /* Secure Digital Host shares DMA with Nand controller */ +- bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); +-#endif + +- bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); +- SSYNC(); +- +- /* Disable card inserting detection pin. set MMC_CAP_NEES_POLL, and +- * mmc stack will do the detection. +- */ +- bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3)); +- SSYNC(); ++ sdh_reset(); + ++ mmc_add_host(mmc); + return 0; + + out4: +@@ -546,12 +616,10 @@ out1: + return ret; + } + +-static int __devexit sdh_remove(struct platform_device *pdev) ++static int sdh_remove(struct platform_device *pdev) + { + struct mmc_host *mmc = platform_get_drvdata(pdev); + +- platform_set_drvdata(pdev, NULL); +- + if (mmc) { + struct sdh_host *host = mmc_priv(mmc); + +@@ -571,22 +639,15 @@ static int __devexit sdh_remove(struct platform_device *pdev) + #ifdef CONFIG_PM + static int sdh_suspend(struct platform_device *dev, pm_message_t state) + { +- struct mmc_host *mmc = platform_get_drvdata(dev); + struct bfin_sd_host *drv_data = get_sdh_data(dev); +- int ret = 0; +- +- if (mmc) +- ret = mmc_suspend_host(mmc); + +- bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() & ~PWR_ON); + peripheral_free_list(drv_data->pin_req); + +- return ret; ++ return 0; + } + + static int sdh_resume(struct platform_device *dev) + { +- struct mmc_host *mmc = platform_get_drvdata(dev); + struct bfin_sd_host *drv_data = get_sdh_data(dev); + int ret = 0; + +@@ -596,20 +657,7 @@ static int sdh_resume(struct platform_device *dev) + return ret; + } + +- bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() | PWR_ON); +-#if defined(CONFIG_BF54x) +- /* Secure Digital Host shares DMA with Nand controller */ +- bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); +-#endif +- bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); +- SSYNC(); +- +- bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3)); +- SSYNC(); +- +- if (mmc) +- ret = mmc_resume_host(mmc); +- ++ sdh_reset(); + return ret; + } + #else +@@ -619,7 +667,7 @@ static int sdh_resume(struct platform_device *dev) + + static struct platform_driver sdh_driver = { + .probe = sdh_probe, +- .remove = __devexit_p(sdh_remove), ++ .remove = sdh_remove, + .suspend = sdh_suspend, + .resume = sdh_resume, + .driver = { +@@ -627,17 +675,7 @@ static struct platform_driver sdh_driver = { + }, + }; + +-static int __init sdh_init(void) +-{ +- return platform_driver_register(&sdh_driver); +-} +-module_init(sdh_init); +- +-static void __exit sdh_exit(void) +-{ +- platform_driver_unregister(&sdh_driver); +-} +-module_exit(sdh_exit); ++module_platform_driver(sdh_driver); + + MODULE_DESCRIPTION("Blackfin Secure Digital Host Driver"); + MODULE_AUTHOR("Cliff Cai, Roy Huang"); +diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c +index ce2a47b..1087b4c 100644 +--- a/drivers/mmc/host/cb710-mmc.c ++++ b/drivers/mmc/host/cb710-mmc.c +@@ -667,12 +667,6 @@ static const struct mmc_host_ops cb710_mmc_host = { + static int cb710_mmc_suspend(struct platform_device *pdev, pm_message_t state) + { + struct cb710_slot *slot = cb710_pdev_to_slot(pdev); +- struct mmc_host *mmc = cb710_slot_to_mmc(slot); +- int err; +- +- err = mmc_suspend_host(mmc); +- if (err) +- return err; + + cb710_mmc_enable_irq(slot, 0, ~0); + return 0; +@@ -681,16 +675,14 @@ static int cb710_mmc_suspend(struct platform_device *pdev, pm_message_t state) + static int cb710_mmc_resume(struct platform_device *pdev) + { + struct cb710_slot *slot = cb710_pdev_to_slot(pdev); +- struct mmc_host *mmc = cb710_slot_to_mmc(slot); + + cb710_mmc_enable_irq(slot, 0, ~0); +- +- return mmc_resume_host(mmc); ++ return 0; + } + + #endif /* CONFIG_PM */ + +-static int __devinit cb710_mmc_init(struct platform_device *pdev) ++static int cb710_mmc_init(struct platform_device *pdev) + { + struct cb710_slot *slot = cb710_pdev_to_slot(pdev); + struct cb710_chip *chip = cb710_slot_to_chip(slot); +@@ -703,7 +695,7 @@ static int __devinit cb710_mmc_init(struct platform_device *pdev) + if (!mmc) + return -ENOMEM; + +- dev_set_drvdata(&pdev->dev, mmc); ++ platform_set_drvdata(pdev, mmc); + + /* harmless (maybe) magic */ + pci_read_config_dword(chip->pdev, 0x48, &val); +@@ -746,7 +738,7 @@ err_free_mmc: + return err; + } + +-static int __devexit cb710_mmc_exit(struct platform_device *pdev) ++static int cb710_mmc_exit(struct platform_device *pdev) + { + struct cb710_slot *slot = cb710_pdev_to_slot(pdev); + struct mmc_host *mmc = cb710_slot_to_mmc(slot); +@@ -773,25 +765,14 @@ static int __devexit cb710_mmc_exit(struct platform_device *pdev) + static struct platform_driver cb710_mmc_driver = { + .driver.name = "cb710-mmc", + .probe = cb710_mmc_init, +- .remove = __devexit_p(cb710_mmc_exit), ++ .remove = cb710_mmc_exit, + #ifdef CONFIG_PM + .suspend = cb710_mmc_suspend, + .resume = cb710_mmc_resume, + #endif + }; + +-static int __init cb710_mmc_init_module(void) +-{ +- return platform_driver_register(&cb710_mmc_driver); +-} +- +-static void __exit cb710_mmc_cleanup_module(void) +-{ +- platform_driver_unregister(&cb710_mmc_driver); +-} +- +-module_init(cb710_mmc_init_module); +-module_exit(cb710_mmc_cleanup_module); ++module_platform_driver(cb710_mmc_driver); + + MODULE_AUTHOR("MichaÅ‚ MirosÅ‚aw "); + MODULE_DESCRIPTION("ENE CB710 memory card reader driver - MMC/SD part"); +diff --git a/drivers/mmc/host/cb710-mmc.h b/drivers/mmc/host/cb710-mmc.h +index e845c77..8984ec8 100644 +--- a/drivers/mmc/host/cb710-mmc.h ++++ b/drivers/mmc/host/cb710-mmc.h +@@ -24,7 +24,7 @@ struct cb710_mmc_reader { + + static inline struct mmc_host *cb710_slot_to_mmc(struct cb710_slot *slot) + { +- return dev_get_drvdata(&slot->pdev.dev); ++ return platform_get_drvdata(&slot->pdev); + } + + static inline struct cb710_slot *cb710_mmc_to_slot(struct mmc_host *mmc) +diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c +index 64a8325..5d4c5e0 100644 +--- a/drivers/mmc/host/davinci_mmc.c ++++ b/drivers/mmc/host/davinci_mmc.c +@@ -30,11 +30,15 @@ + #include + #include + #include ++#include + #include ++#include + #include ++#include ++#include + +-#include +-#include ++#include ++#include + + /* + * Register Definitions +@@ -160,6 +164,16 @@ module_param(rw_threshold, uint, S_IRUGO); + MODULE_PARM_DESC(rw_threshold, + "Read/Write threshold. Default = 32"); + ++static unsigned poll_threshold = 128; ++module_param(poll_threshold, uint, S_IRUGO); ++MODULE_PARM_DESC(poll_threshold, ++ "Polling transaction size threshold. Default = 128"); ++ ++static unsigned poll_loopcount = 32; ++module_param(poll_loopcount, uint, S_IRUGO); ++MODULE_PARM_DESC(poll_loopcount, ++ "Maximum polling loop count. Default = 32"); ++ + static unsigned __initdata use_dma = 1; + module_param(use_dma, uint, 0); + MODULE_PARM_DESC(use_dma, "Whether to use DMA or not. Default = 1"); +@@ -179,7 +193,6 @@ struct mmc_davinci_host { + #define DAVINCI_MMC_DATADIR_READ 1 + #define DAVINCI_MMC_DATADIR_WRITE 2 + unsigned char data_dir; +- unsigned char suspended; + + /* buffer is used during PIO of one scatterlist segment, and + * is updated along with buffer_bytes_left. bytes_left applies +@@ -190,19 +203,12 @@ struct mmc_davinci_host { + u32 bytes_left; + + u32 rxdma, txdma; ++ struct dma_chan *dma_tx; ++ struct dma_chan *dma_rx; + bool use_dma; + bool do_dma; + bool sdio_int; +- +- /* Scatterlist DMA uses one or more parameter RAM entries: +- * the main one (associated with rxdma or txdma) plus zero or +- * more links. The entries for a given transfer differ only +- * by memory buffer (address, length) and link field. +- */ +- struct edmacc_param tx_template; +- struct edmacc_param rx_template; +- unsigned n_link; +- u32 links[MAX_NR_SG - 1]; ++ bool active_request; + + /* For PIO we walk scatterlists one segment at a time. */ + unsigned int sg_len; +@@ -219,6 +225,7 @@ struct mmc_davinci_host { + #endif + }; + ++static irqreturn_t mmc_davinci_irq(int irq, void *dev_id); + + /* PIO only */ + static void mmc_davinci_sg_to_buf(struct mmc_davinci_host *host) +@@ -376,7 +383,20 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host, + + writel(cmd->arg, host->base + DAVINCI_MMCARGHL); + writel(cmd_reg, host->base + DAVINCI_MMCCMD); +- writel(im_val, host->base + DAVINCI_MMCIM); ++ ++ host->active_request = true; ++ ++ if (!host->do_dma && host->bytes_left <= poll_threshold) { ++ u32 count = poll_loopcount; ++ ++ while (host->active_request && count--) { ++ mmc_davinci_irq(0, host); ++ cpu_relax(); ++ } ++ } ++ ++ if (host->active_request) ++ writel(im_val, host->base + DAVINCI_MMCIM); + } + + /*----------------------------------------------------------------------*/ +@@ -385,153 +405,74 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host, + + static void davinci_abort_dma(struct mmc_davinci_host *host) + { +- int sync_dev; ++ struct dma_chan *sync_dev; + + if (host->data_dir == DAVINCI_MMC_DATADIR_READ) +- sync_dev = host->rxdma; ++ sync_dev = host->dma_rx; + else +- sync_dev = host->txdma; +- +- edma_stop(sync_dev); +- edma_clean_channel(sync_dev); +-} +- +-static void +-mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data *data); +- +-static void mmc_davinci_dma_cb(unsigned channel, u16 ch_status, void *data) +-{ +- if (DMA_COMPLETE != ch_status) { +- struct mmc_davinci_host *host = data; +- +- /* Currently means: DMA Event Missed, or "null" transfer +- * request was seen. In the future, TC errors (like bad +- * addresses) might be presented too. +- */ +- dev_warn(mmc_dev(host->mmc), "DMA %s error\n", +- (host->data->flags & MMC_DATA_WRITE) +- ? "write" : "read"); +- host->data->error = -EIO; +- mmc_davinci_xfer_done(host, host->data); +- } +-} +- +-/* Set up tx or rx template, to be modified and updated later */ +-static void __init mmc_davinci_dma_setup(struct mmc_davinci_host *host, +- bool tx, struct edmacc_param *template) +-{ +- unsigned sync_dev; +- const u16 acnt = 4; +- const u16 bcnt = rw_threshold >> 2; +- const u16 ccnt = 0; +- u32 src_port = 0; +- u32 dst_port = 0; +- s16 src_bidx, dst_bidx; +- s16 src_cidx, dst_cidx; +- +- /* +- * A-B Sync transfer: each DMA request is for one "frame" of +- * rw_threshold bytes, broken into "acnt"-size chunks repeated +- * "bcnt" times. Each segment needs "ccnt" such frames; since +- * we tell the block layer our mmc->max_seg_size limit, we can +- * trust (later) that it's within bounds. +- * +- * The FIFOs are read/written in 4-byte chunks (acnt == 4) and +- * EDMA will optimize memory operations to use larger bursts. +- */ +- if (tx) { +- sync_dev = host->txdma; +- +- /* src_prt, ccnt, and link to be set up later */ +- src_bidx = acnt; +- src_cidx = acnt * bcnt; ++ sync_dev = host->dma_tx; + +- dst_port = host->mem_res->start + DAVINCI_MMCDXR; +- dst_bidx = 0; +- dst_cidx = 0; +- } else { +- sync_dev = host->rxdma; +- +- src_port = host->mem_res->start + DAVINCI_MMCDRR; +- src_bidx = 0; +- src_cidx = 0; +- +- /* dst_prt, ccnt, and link to be set up later */ +- dst_bidx = acnt; +- dst_cidx = acnt * bcnt; +- } +- +- /* +- * We can't use FIFO mode for the FIFOs because MMC FIFO addresses +- * are not 256-bit (32-byte) aligned. So we use INCR, and the W8BIT +- * parameter is ignored. +- */ +- edma_set_src(sync_dev, src_port, INCR, W8BIT); +- edma_set_dest(sync_dev, dst_port, INCR, W8BIT); +- +- edma_set_src_index(sync_dev, src_bidx, src_cidx); +- edma_set_dest_index(sync_dev, dst_bidx, dst_cidx); +- +- edma_set_transfer_params(sync_dev, acnt, bcnt, ccnt, 8, ABSYNC); +- +- edma_read_slot(sync_dev, template); +- +- /* don't bother with irqs or chaining */ +- template->opt |= EDMA_CHAN_SLOT(sync_dev) << 12; ++ dmaengine_terminate_all(sync_dev); + } + +-static void mmc_davinci_send_dma_request(struct mmc_davinci_host *host, ++static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host, + struct mmc_data *data) + { +- struct edmacc_param *template; +- int channel, slot; +- unsigned link; +- struct scatterlist *sg; +- unsigned sg_len; +- unsigned bytes_left = host->bytes_left; +- const unsigned shift = ffs(rw_threshold) - 1; ++ struct dma_chan *chan; ++ struct dma_async_tx_descriptor *desc; ++ int ret = 0; + + if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) { +- template = &host->tx_template; +- channel = host->txdma; ++ struct dma_slave_config dma_tx_conf = { ++ .direction = DMA_MEM_TO_DEV, ++ .dst_addr = host->mem_res->start + DAVINCI_MMCDXR, ++ .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, ++ .dst_maxburst = ++ rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES, ++ }; ++ chan = host->dma_tx; ++ dmaengine_slave_config(host->dma_tx, &dma_tx_conf); ++ ++ desc = dmaengine_prep_slave_sg(host->dma_tx, ++ data->sg, ++ host->sg_len, ++ DMA_MEM_TO_DEV, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!desc) { ++ dev_dbg(mmc_dev(host->mmc), ++ "failed to allocate DMA TX descriptor"); ++ ret = -1; ++ goto out; ++ } + } else { +- template = &host->rx_template; +- channel = host->rxdma; +- } +- +- /* We know sg_len and ccnt will never be out of range because +- * we told the mmc layer which in turn tells the block layer +- * to ensure that it only hands us one scatterlist segment +- * per EDMA PARAM entry. Update the PARAM +- * entries needed for each segment of this scatterlist. +- */ +- for (slot = channel, link = 0, sg = data->sg, sg_len = host->sg_len; +- sg_len-- != 0 && bytes_left; +- sg = sg_next(sg), slot = host->links[link++]) { +- u32 buf = sg_dma_address(sg); +- unsigned count = sg_dma_len(sg); +- +- template->link_bcntrld = sg_len +- ? (EDMA_CHAN_SLOT(host->links[link]) << 5) +- : 0xffff; +- +- if (count > bytes_left) +- count = bytes_left; +- bytes_left -= count; +- +- if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) +- template->src = buf; +- else +- template->dst = buf; +- template->ccnt = count >> shift; +- +- edma_write_slot(slot, template); ++ struct dma_slave_config dma_rx_conf = { ++ .direction = DMA_DEV_TO_MEM, ++ .src_addr = host->mem_res->start + DAVINCI_MMCDRR, ++ .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, ++ .src_maxburst = ++ rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES, ++ }; ++ chan = host->dma_rx; ++ dmaengine_slave_config(host->dma_rx, &dma_rx_conf); ++ ++ desc = dmaengine_prep_slave_sg(host->dma_rx, ++ data->sg, ++ host->sg_len, ++ DMA_DEV_TO_MEM, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!desc) { ++ dev_dbg(mmc_dev(host->mmc), ++ "failed to allocate DMA RX descriptor"); ++ ret = -1; ++ goto out; ++ } + } + +- if (host->version == MMC_CTLR_VERSION_2) +- edma_clear_event(channel); ++ dmaengine_submit(desc); ++ dma_async_issue_pending(chan); + +- edma_start(channel); ++out: ++ return ret; + } + + static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, +@@ -539,6 +480,7 @@ static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, + { + int i; + int mask = rw_threshold - 1; ++ int ret = 0; + + host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + ((data->flags & MMC_DATA_WRITE) +@@ -558,70 +500,50 @@ static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, + } + + host->do_dma = 1; +- mmc_davinci_send_dma_request(host, data); ++ ret = mmc_davinci_send_dma_request(host, data); + +- return 0; ++ return ret; + } + + static void __init_or_module + davinci_release_dma_channels(struct mmc_davinci_host *host) + { +- unsigned i; +- + if (!host->use_dma) + return; + +- for (i = 0; i < host->n_link; i++) +- edma_free_slot(host->links[i]); +- +- edma_free_channel(host->txdma); +- edma_free_channel(host->rxdma); ++ dma_release_channel(host->dma_tx); ++ dma_release_channel(host->dma_rx); + } + + static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host) + { +- u32 link_size; +- int r, i; +- +- /* Acquire master DMA write channel */ +- r = edma_alloc_channel(host->txdma, mmc_davinci_dma_cb, host, +- EVENTQ_DEFAULT); +- if (r < 0) { +- dev_warn(mmc_dev(host->mmc), "alloc %s channel err %d\n", +- "tx", r); +- return r; +- } +- mmc_davinci_dma_setup(host, true, &host->tx_template); +- +- /* Acquire master DMA read channel */ +- r = edma_alloc_channel(host->rxdma, mmc_davinci_dma_cb, host, +- EVENTQ_DEFAULT); +- if (r < 0) { +- dev_warn(mmc_dev(host->mmc), "alloc %s channel err %d\n", +- "rx", r); +- goto free_master_write; ++ int r; ++ dma_cap_mask_t mask; ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ ++ host->dma_tx = ++ dma_request_slave_channel_compat(mask, edma_filter_fn, ++ &host->txdma, mmc_dev(host->mmc), "tx"); ++ if (!host->dma_tx) { ++ dev_err(mmc_dev(host->mmc), "Can't get dma_tx channel\n"); ++ return -ENODEV; + } +- mmc_davinci_dma_setup(host, false, &host->rx_template); + +- /* Allocate parameter RAM slots, which will later be bound to a +- * channel as needed to handle a scatterlist. +- */ +- link_size = min_t(unsigned, host->nr_sg, ARRAY_SIZE(host->links)); +- for (i = 0; i < link_size; i++) { +- r = edma_alloc_slot(EDMA_CTLR(host->txdma), EDMA_SLOT_ANY); +- if (r < 0) { +- dev_dbg(mmc_dev(host->mmc), "dma PaRAM alloc --> %d\n", +- r); +- break; +- } +- host->links[i] = r; ++ host->dma_rx = ++ dma_request_slave_channel_compat(mask, edma_filter_fn, ++ &host->rxdma, mmc_dev(host->mmc), "rx"); ++ if (!host->dma_rx) { ++ dev_err(mmc_dev(host->mmc), "Can't get dma_rx channel\n"); ++ r = -ENODEV; ++ goto free_master_write; + } +- host->n_link = i; + + return 0; + + free_master_write: +- edma_free_channel(host->txdma); ++ dma_release_channel(host->dma_tx); + + return r; + } +@@ -915,6 +837,7 @@ mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data *data) + if (!data->stop || (host->cmd && host->cmd->error)) { + mmc_request_done(host->mmc, data->mrq); + writel(0, host->base + DAVINCI_MMCIM); ++ host->active_request = false; + } else + mmc_davinci_start_command(host, data->stop); + } +@@ -942,6 +865,7 @@ static void mmc_davinci_cmd_done(struct mmc_davinci_host *host, + cmd->mrq->cmd->retries = 0; + mmc_request_done(host->mmc, cmd->mrq); + writel(0, host->base + DAVINCI_MMCIM); ++ host->active_request = false; + } + } + +@@ -1009,12 +933,33 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) + * by read. So, it is not unbouned loop even in the case of + * non-dma. + */ +- while (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) { +- davinci_fifo_data_trans(host, rw_threshold); +- status = readl(host->base + DAVINCI_MMCST0); +- if (!status) +- break; +- qstatus |= status; ++ if (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) { ++ unsigned long im_val; ++ ++ /* ++ * If interrupts fire during the following loop, they will be ++ * handled by the handler, but the PIC will still buffer these. ++ * As a result, the handler will be called again to serve these ++ * needlessly. In order to avoid these spurious interrupts, ++ * keep interrupts masked during the loop. ++ */ ++ im_val = readl(host->base + DAVINCI_MMCIM); ++ writel(0, host->base + DAVINCI_MMCIM); ++ ++ do { ++ davinci_fifo_data_trans(host, rw_threshold); ++ status = readl(host->base + DAVINCI_MMCST0); ++ qstatus |= status; ++ } while (host->bytes_left && ++ (status & (MMCST0_DXRDY | MMCST0_DRRDY))); ++ ++ /* ++ * If an interrupt is pending, it is assumed it will fire when ++ * it is unmasked. This assumption is also taken when the MMCIM ++ * is first set. Otherwise, writing to MMCIM after reading the ++ * status is race-prone. ++ */ ++ writel(im_val, host->base + DAVINCI_MMCIM); + } + + if (qstatus & MMCST0_DATDNE) { +@@ -1216,16 +1161,86 @@ static void __init init_mmcsd_host(struct mmc_davinci_host *host) + mmc_davinci_reset_ctrl(host, 0); + } + +-static int __init davinci_mmcsd_probe(struct platform_device *pdev) ++static struct platform_device_id davinci_mmc_devtype[] = { ++ { ++ .name = "dm6441-mmc", ++ .driver_data = MMC_CTLR_VERSION_1, ++ }, { ++ .name = "da830-mmc", ++ .driver_data = MMC_CTLR_VERSION_2, ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(platform, davinci_mmc_devtype); ++ ++static const struct of_device_id davinci_mmc_dt_ids[] = { ++ { ++ .compatible = "ti,dm6441-mmc", ++ .data = &davinci_mmc_devtype[MMC_CTLR_VERSION_1], ++ }, ++ { ++ .compatible = "ti,da830-mmc", ++ .data = &davinci_mmc_devtype[MMC_CTLR_VERSION_2], ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, davinci_mmc_dt_ids); ++ ++static struct davinci_mmc_config ++ *mmc_parse_pdata(struct platform_device *pdev) + { ++ struct device_node *np; + struct davinci_mmc_config *pdata = pdev->dev.platform_data; ++ const struct of_device_id *match = ++ of_match_device(davinci_mmc_dt_ids, &pdev->dev); ++ u32 data; ++ ++ np = pdev->dev.of_node; ++ if (!np) ++ return pdata; ++ ++ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) { ++ dev_err(&pdev->dev, "Failed to allocate memory for struct davinci_mmc_config\n"); ++ goto nodata; ++ } ++ ++ if (match) ++ pdev->id_entry = match->data; ++ ++ if (of_property_read_u32(np, "max-frequency", &pdata->max_freq)) ++ dev_info(&pdev->dev, "'max-frequency' property not specified, defaulting to 25MHz\n"); ++ ++ of_property_read_u32(np, "bus-width", &data); ++ switch (data) { ++ case 1: ++ case 4: ++ case 8: ++ pdata->wires = data; ++ break; ++ default: ++ pdata->wires = 1; ++ dev_info(&pdev->dev, "Unsupported buswidth, defaulting to 1 bit\n"); ++ } ++nodata: ++ return pdata; ++} ++ ++static int __init davinci_mmcsd_probe(struct platform_device *pdev) ++{ ++ struct davinci_mmc_config *pdata = NULL; + struct mmc_davinci_host *host = NULL; + struct mmc_host *mmc = NULL; + struct resource *r, *mem = NULL; + int ret = 0, irq = 0; + size_t mem_size; ++ const struct platform_device_id *id_entry; + +- /* REVISIT: when we're fully converted, fail if pdata is NULL */ ++ pdata = mmc_parse_pdata(pdev); ++ if (pdata == NULL) { ++ dev_err(&pdev->dev, "Couldn't get platform data\n"); ++ return -ENOENT; ++ } + + ret = -ENODEV; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -1249,13 +1264,15 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) + + r = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (!r) +- goto out; +- host->rxdma = r->start; ++ dev_warn(&pdev->dev, "RX DMA resource not specified\n"); ++ else ++ host->rxdma = r->start; + + r = platform_get_resource(pdev, IORESOURCE_DMA, 1); + if (!r) +- goto out; +- host->txdma = r->start; ++ dev_warn(&pdev->dev, "TX DMA resource not specified\n"); ++ else ++ host->txdma = r->start; + + host->mem_res = mem; + host->base = ioremap(mem->start, mem_size); +@@ -1296,7 +1313,9 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) + if (pdata && (pdata->wires == 8)) + mmc->caps |= (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA); + +- host->version = pdata->version; ++ id_entry = platform_get_device_id(pdev); ++ if (id_entry) ++ host->version = id_entry->driver_data; + + mmc->ops = &mmc_davinci_ops; + mmc->f_min = 312500; +@@ -1311,7 +1330,7 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) + * Each hw_seg uses one EDMA parameter RAM slot, always one + * channel and then usually some linked slots. + */ +- mmc->max_segs = 1 + host->n_link; ++ mmc->max_segs = MAX_NR_SG; + + /* EDMA limit per hw segment (one or two MBytes) */ + mmc->max_seg_size = MAX_CCNT * rw_threshold; +@@ -1387,7 +1406,6 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev) + { + struct mmc_davinci_host *host = platform_get_drvdata(pdev); + +- platform_set_drvdata(pdev, NULL); + if (host) { + mmc_davinci_cpufreq_deregister(host); + +@@ -1416,42 +1434,23 @@ static int davinci_mmcsd_suspend(struct device *dev) + { + struct platform_device *pdev = to_platform_device(dev); + struct mmc_davinci_host *host = platform_get_drvdata(pdev); +- int ret; + +- mmc_host_enable(host->mmc); +- ret = mmc_suspend_host(host->mmc); +- if (!ret) { +- writel(0, host->base + DAVINCI_MMCIM); +- mmc_davinci_reset_ctrl(host, 1); +- mmc_host_disable(host->mmc); +- clk_disable(host->clk); +- host->suspended = 1; +- } else { +- host->suspended = 0; +- mmc_host_disable(host->mmc); +- } ++ writel(0, host->base + DAVINCI_MMCIM); ++ mmc_davinci_reset_ctrl(host, 1); ++ clk_disable(host->clk); + +- return ret; ++ return 0; + } + + static int davinci_mmcsd_resume(struct device *dev) + { + struct platform_device *pdev = to_platform_device(dev); + struct mmc_davinci_host *host = platform_get_drvdata(pdev); +- int ret; +- +- if (!host->suspended) +- return 0; + + clk_enable(host->clk); +- mmc_host_enable(host->mmc); +- + mmc_davinci_reset_ctrl(host, 0); +- ret = mmc_resume_host(host->mmc); +- if (!ret) +- host->suspended = 0; + +- return ret; ++ return 0; + } + + static const struct dev_pm_ops davinci_mmcsd_pm = { +@@ -1469,24 +1468,16 @@ static struct platform_driver davinci_mmcsd_driver = { + .name = "davinci_mmc", + .owner = THIS_MODULE, + .pm = davinci_mmcsd_pm_ops, ++ .of_match_table = davinci_mmc_dt_ids, + }, + .remove = __exit_p(davinci_mmcsd_remove), ++ .id_table = davinci_mmc_devtype, + }; + +-static int __init davinci_mmcsd_init(void) +-{ +- return platform_driver_probe(&davinci_mmcsd_driver, +- davinci_mmcsd_probe); +-} +-module_init(davinci_mmcsd_init); +- +-static void __exit davinci_mmcsd_exit(void) +-{ +- platform_driver_unregister(&davinci_mmcsd_driver); +-} +-module_exit(davinci_mmcsd_exit); ++module_platform_driver_probe(davinci_mmcsd_driver, davinci_mmcsd_probe); + + MODULE_AUTHOR("Texas Instruments India"); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("MMC/SD driver for Davinci MMC controller"); ++MODULE_ALIAS("platform:davinci_mmc"); + +diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c +new file mode 100644 +index 0000000..0fbc53a +--- /dev/null ++++ b/drivers/mmc/host/dw_mmc-exynos.c +@@ -0,0 +1,450 @@ ++/* ++ * Exynos Specific Extensions for Synopsys DW Multimedia Card Interface driver ++ * ++ * Copyright (C) 2012, Samsung Electronics 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 "dw_mmc.h" ++#include "dw_mmc-pltfm.h" ++ ++#define NUM_PINS(x) (x + 2) ++ ++#define SDMMC_CLKSEL 0x09C ++#define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0) ++#define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16) ++#define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24) ++#define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7) ++#define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ ++ SDMMC_CLKSEL_CCLK_DRIVE(y) | \ ++ SDMMC_CLKSEL_CCLK_DIVIDER(z)) ++#define SDMMC_CLKSEL_WAKEUP_INT BIT(11) ++ ++#define EXYNOS4210_FIXED_CIU_CLK_DIV 2 ++#define EXYNOS4412_FIXED_CIU_CLK_DIV 4 ++ ++/* Block number in eMMC */ ++#define DWMCI_BLOCK_NUM 0xFFFFFFFF ++ ++#define SDMMC_EMMCP_BASE 0x1000 ++#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) ++#define SDMMC_MPSBEGIN0 (SDMMC_EMMCP_BASE + 0x0200) ++#define SDMMC_MPSEND0 (SDMMC_EMMCP_BASE + 0x0204) ++#define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C) ++ ++/* SMU control bits */ ++#define DWMCI_MPSCTRL_SECURE_READ_BIT BIT(7) ++#define DWMCI_MPSCTRL_SECURE_WRITE_BIT BIT(6) ++#define DWMCI_MPSCTRL_NON_SECURE_READ_BIT BIT(5) ++#define DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4) ++#define DWMCI_MPSCTRL_USE_FUSE_KEY BIT(3) ++#define DWMCI_MPSCTRL_ECB_MODE BIT(2) ++#define DWMCI_MPSCTRL_ENCRYPTION BIT(1) ++#define DWMCI_MPSCTRL_VALID BIT(0) ++ ++#define EXYNOS_CCLKIN_MIN 50000000 /* unit: HZ */ ++ ++/* Variations in Exynos specific dw-mshc controller */ ++enum dw_mci_exynos_type { ++ DW_MCI_TYPE_EXYNOS4210, ++ DW_MCI_TYPE_EXYNOS4412, ++ DW_MCI_TYPE_EXYNOS5250, ++ DW_MCI_TYPE_EXYNOS5420, ++ DW_MCI_TYPE_EXYNOS5420_SMU, ++}; ++ ++/* Exynos implementation specific driver private data */ ++struct dw_mci_exynos_priv_data { ++ enum dw_mci_exynos_type ctrl_type; ++ u8 ciu_div; ++ u32 sdr_timing; ++ u32 ddr_timing; ++ u32 cur_speed; ++}; ++ ++static struct dw_mci_exynos_compatible { ++ char *compatible; ++ enum dw_mci_exynos_type ctrl_type; ++} exynos_compat[] = { ++ { ++ .compatible = "samsung,exynos4210-dw-mshc", ++ .ctrl_type = DW_MCI_TYPE_EXYNOS4210, ++ }, { ++ .compatible = "samsung,exynos4412-dw-mshc", ++ .ctrl_type = DW_MCI_TYPE_EXYNOS4412, ++ }, { ++ .compatible = "samsung,exynos5250-dw-mshc", ++ .ctrl_type = DW_MCI_TYPE_EXYNOS5250, ++ }, { ++ .compatible = "samsung,exynos5420-dw-mshc", ++ .ctrl_type = DW_MCI_TYPE_EXYNOS5420, ++ }, { ++ .compatible = "samsung,exynos5420-dw-mshc-smu", ++ .ctrl_type = DW_MCI_TYPE_EXYNOS5420_SMU, ++ }, ++}; ++ ++static int dw_mci_exynos_priv_init(struct dw_mci *host) ++{ ++ struct dw_mci_exynos_priv_data *priv = host->priv; ++ ++ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU) { ++ mci_writel(host, MPSBEGIN0, 0); ++ mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM); ++ mci_writel(host, MPSCTRL0, DWMCI_MPSCTRL_SECURE_WRITE_BIT | ++ DWMCI_MPSCTRL_NON_SECURE_READ_BIT | ++ DWMCI_MPSCTRL_VALID | ++ DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT); ++ } ++ ++ return 0; ++} ++ ++static int dw_mci_exynos_setup_clock(struct dw_mci *host) ++{ ++ struct dw_mci_exynos_priv_data *priv = host->priv; ++ unsigned long rate = clk_get_rate(host->ciu_clk); ++ ++ host->bus_hz = rate / (priv->ciu_div + 1); ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int dw_mci_exynos_suspend(struct device *dev) ++{ ++ struct dw_mci *host = dev_get_drvdata(dev); ++ ++ return dw_mci_suspend(host); ++} ++ ++static int dw_mci_exynos_resume(struct device *dev) ++{ ++ struct dw_mci *host = dev_get_drvdata(dev); ++ ++ dw_mci_exynos_priv_init(host); ++ return dw_mci_resume(host); ++} ++ ++/** ++ * dw_mci_exynos_resume_noirq - Exynos-specific resume code ++ * ++ * On exynos5420 there is a silicon errata that will sometimes leave the ++ * WAKEUP_INT bit in the CLKSEL register asserted. This bit is 1 to indicate ++ * that it fired and we can clear it by writing a 1 back. Clear it to prevent ++ * interrupts from going off constantly. ++ * ++ * We run this code on all exynos variants because it doesn't hurt. ++ */ ++ ++static int dw_mci_exynos_resume_noirq(struct device *dev) ++{ ++ struct dw_mci *host = dev_get_drvdata(dev); ++ u32 clksel; ++ ++ clksel = mci_readl(host, CLKSEL); ++ if (clksel & SDMMC_CLKSEL_WAKEUP_INT) ++ mci_writel(host, CLKSEL, clksel); ++ ++ return 0; ++} ++#else ++#define dw_mci_exynos_suspend NULL ++#define dw_mci_exynos_resume NULL ++#define dw_mci_exynos_resume_noirq NULL ++#endif /* CONFIG_PM_SLEEP */ ++ ++static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) ++{ ++ /* ++ * Exynos4412 and Exynos5250 extends the use of CMD register with the ++ * use of bit 29 (which is reserved on standard MSHC controllers) for ++ * optionally bypassing the HOLD register for command and data. The ++ * HOLD register should be bypassed in case there is no phase shift ++ * applied on CMD/DATA that is sent to the card. ++ */ ++ if (SDMMC_CLKSEL_GET_DRV_WD3(mci_readl(host, CLKSEL))) ++ *cmdr |= SDMMC_CMD_USE_HOLD_REG; ++} ++ ++static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) ++{ ++ struct dw_mci_exynos_priv_data *priv = host->priv; ++ unsigned int wanted = ios->clock; ++ unsigned long actual; ++ u8 div = priv->ciu_div + 1; ++ ++ if (ios->timing == MMC_TIMING_MMC_DDR52) { ++ mci_writel(host, CLKSEL, priv->ddr_timing); ++ /* Should be double rate for DDR mode */ ++ if (ios->bus_width == MMC_BUS_WIDTH_8) ++ wanted <<= 1; ++ } else { ++ mci_writel(host, CLKSEL, priv->sdr_timing); ++ } ++ ++ /* Don't care if wanted clock is zero */ ++ if (!wanted) ++ return; ++ ++ /* Guaranteed minimum frequency for cclkin */ ++ if (wanted < EXYNOS_CCLKIN_MIN) ++ wanted = EXYNOS_CCLKIN_MIN; ++ ++ if (wanted != priv->cur_speed) { ++ int ret = clk_set_rate(host->ciu_clk, wanted * div); ++ if (ret) ++ dev_warn(host->dev, ++ "failed to set clk-rate %u error: %d\n", ++ wanted * div, ret); ++ actual = clk_get_rate(host->ciu_clk); ++ host->bus_hz = actual / div; ++ priv->cur_speed = wanted; ++ host->current_speed = 0; ++ } ++} ++ ++static int dw_mci_exynos_parse_dt(struct dw_mci *host) ++{ ++ struct dw_mci_exynos_priv_data *priv; ++ struct device_node *np = host->dev->of_node; ++ u32 timing[2]; ++ u32 div = 0; ++ int idx; ++ int ret; ++ ++ priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) { ++ dev_err(host->dev, "mem alloc failed for private data\n"); ++ return -ENOMEM; ++ } ++ ++ for (idx = 0; idx < ARRAY_SIZE(exynos_compat); idx++) { ++ if (of_device_is_compatible(np, exynos_compat[idx].compatible)) ++ priv->ctrl_type = exynos_compat[idx].ctrl_type; ++ } ++ ++ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412) ++ priv->ciu_div = EXYNOS4412_FIXED_CIU_CLK_DIV - 1; ++ else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210) ++ priv->ciu_div = EXYNOS4210_FIXED_CIU_CLK_DIV - 1; ++ else { ++ of_property_read_u32(np, "samsung,dw-mshc-ciu-div", &div); ++ priv->ciu_div = div; ++ } ++ ++ ret = of_property_read_u32_array(np, ++ "samsung,dw-mshc-sdr-timing", timing, 2); ++ if (ret) ++ return ret; ++ ++ priv->sdr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); ++ ++ ret = of_property_read_u32_array(np, ++ "samsung,dw-mshc-ddr-timing", timing, 2); ++ if (ret) ++ return ret; ++ ++ priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); ++ host->priv = priv; ++ return 0; ++} ++ ++static inline u8 dw_mci_exynos_get_clksmpl(struct dw_mci *host) ++{ ++ return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL)); ++} ++ ++static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample) ++{ ++ u32 clksel; ++ clksel = mci_readl(host, CLKSEL); ++ clksel = (clksel & ~0x7) | SDMMC_CLKSEL_CCLK_SAMPLE(sample); ++ mci_writel(host, CLKSEL, clksel); ++} ++ ++static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host) ++{ ++ u32 clksel; ++ u8 sample; ++ ++ clksel = mci_readl(host, CLKSEL); ++ sample = (clksel + 1) & 0x7; ++ clksel = (clksel & ~0x7) | sample; ++ mci_writel(host, CLKSEL, clksel); ++ return sample; ++} ++ ++static s8 dw_mci_exynos_get_best_clksmpl(u8 candiates) ++{ ++ const u8 iter = 8; ++ u8 __c; ++ s8 i, loc = -1; ++ ++ for (i = 0; i < iter; i++) { ++ __c = ror8(candiates, i); ++ if ((__c & 0xc7) == 0xc7) { ++ loc = i; ++ goto out; ++ } ++ } ++ ++ for (i = 0; i < iter; i++) { ++ __c = ror8(candiates, i); ++ if ((__c & 0x83) == 0x83) { ++ loc = i; ++ goto out; ++ } ++ } ++ ++out: ++ return loc; ++} ++ ++static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot, u32 opcode, ++ struct dw_mci_tuning_data *tuning_data) ++{ ++ struct dw_mci *host = slot->host; ++ struct mmc_host *mmc = slot->mmc; ++ const u8 *blk_pattern = tuning_data->blk_pattern; ++ u8 *blk_test; ++ unsigned int blksz = tuning_data->blksz; ++ u8 start_smpl, smpl, candiates = 0; ++ s8 found = -1; ++ int ret = 0; ++ ++ blk_test = kmalloc(blksz, GFP_KERNEL); ++ if (!blk_test) ++ return -ENOMEM; ++ ++ start_smpl = dw_mci_exynos_get_clksmpl(host); ++ ++ do { ++ struct mmc_request mrq = {NULL}; ++ struct mmc_command cmd = {0}; ++ struct mmc_command stop = {0}; ++ struct mmc_data data = {0}; ++ struct scatterlist sg; ++ ++ cmd.opcode = opcode; ++ cmd.arg = 0; ++ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; ++ ++ stop.opcode = MMC_STOP_TRANSMISSION; ++ stop.arg = 0; ++ stop.flags = MMC_RSP_R1B | MMC_CMD_AC; ++ ++ data.blksz = blksz; ++ data.blocks = 1; ++ data.flags = MMC_DATA_READ; ++ data.sg = &sg; ++ data.sg_len = 1; ++ ++ sg_init_one(&sg, blk_test, blksz); ++ mrq.cmd = &cmd; ++ mrq.stop = &stop; ++ mrq.data = &data; ++ host->mrq = &mrq; ++ ++ mci_writel(host, TMOUT, ~0); ++ smpl = dw_mci_exynos_move_next_clksmpl(host); ++ ++ mmc_wait_for_req(mmc, &mrq); ++ ++ if (!cmd.error && !data.error) { ++ if (!memcmp(blk_pattern, blk_test, blksz)) ++ candiates |= (1 << smpl); ++ } else { ++ dev_dbg(host->dev, ++ "Tuning error: cmd.error:%d, data.error:%d\n", ++ cmd.error, data.error); ++ } ++ } while (start_smpl != smpl); ++ ++ found = dw_mci_exynos_get_best_clksmpl(candiates); ++ if (found >= 0) ++ dw_mci_exynos_set_clksmpl(host, found); ++ else ++ ret = -EIO; ++ ++ kfree(blk_test); ++ return ret; ++} ++ ++/* Common capabilities of Exynos4/Exynos5 SoC */ ++static unsigned long exynos_dwmmc_caps[4] = { ++ MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, ++ MMC_CAP_CMD23, ++ MMC_CAP_CMD23, ++ MMC_CAP_CMD23, ++}; ++ ++static const struct dw_mci_drv_data exynos_drv_data = { ++ .caps = exynos_dwmmc_caps, ++ .init = dw_mci_exynos_priv_init, ++ .setup_clock = dw_mci_exynos_setup_clock, ++ .prepare_command = dw_mci_exynos_prepare_command, ++ .set_ios = dw_mci_exynos_set_ios, ++ .parse_dt = dw_mci_exynos_parse_dt, ++ .execute_tuning = dw_mci_exynos_execute_tuning, ++}; ++ ++static const struct of_device_id dw_mci_exynos_match[] = { ++ { .compatible = "samsung,exynos4412-dw-mshc", ++ .data = &exynos_drv_data, }, ++ { .compatible = "samsung,exynos5250-dw-mshc", ++ .data = &exynos_drv_data, }, ++ { .compatible = "samsung,exynos5420-dw-mshc", ++ .data = &exynos_drv_data, }, ++ { .compatible = "samsung,exynos5420-dw-mshc-smu", ++ .data = &exynos_drv_data, }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, dw_mci_exynos_match); ++ ++static int dw_mci_exynos_probe(struct platform_device *pdev) ++{ ++ const struct dw_mci_drv_data *drv_data; ++ const struct of_device_id *match; ++ ++ match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node); ++ drv_data = match->data; ++ return dw_mci_pltfm_register(pdev, drv_data); ++} ++ ++static const struct dev_pm_ops dw_mci_exynos_pmops = { ++ SET_SYSTEM_SLEEP_PM_OPS(dw_mci_exynos_suspend, dw_mci_exynos_resume) ++ .resume_noirq = dw_mci_exynos_resume_noirq, ++ .thaw_noirq = dw_mci_exynos_resume_noirq, ++ .restore_noirq = dw_mci_exynos_resume_noirq, ++}; ++ ++static struct platform_driver dw_mci_exynos_pltfm_driver = { ++ .probe = dw_mci_exynos_probe, ++ .remove = __exit_p(dw_mci_pltfm_remove), ++ .driver = { ++ .name = "dwmmc_exynos", ++ .of_match_table = dw_mci_exynos_match, ++ .pm = &dw_mci_exynos_pmops, ++ }, ++}; ++ ++module_platform_driver(dw_mci_exynos_pltfm_driver); ++ ++MODULE_DESCRIPTION("Samsung Specific DW-MSHC Driver Extension"); ++MODULE_AUTHOR("Thomas Abraham ++#include ++#include ++#include ++#include ++#include ++ ++#include "dw_mmc.h" ++#include "dw_mmc-pltfm.h" ++ ++static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios) ++{ ++ int ret; ++ ++ ret = clk_set_rate(host->ciu_clk, ios->clock); ++ if (ret) ++ dev_warn(host->dev, "failed to set rate %uHz\n", ios->clock); ++ ++ host->bus_hz = clk_get_rate(host->ciu_clk); ++} ++ ++static const struct dw_mci_drv_data k3_drv_data = { ++ .set_ios = dw_mci_k3_set_ios, ++}; ++ ++static const struct of_device_id dw_mci_k3_match[] = { ++ { .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, dw_mci_k3_match); ++ ++static int dw_mci_k3_probe(struct platform_device *pdev) ++{ ++ const struct dw_mci_drv_data *drv_data; ++ const struct of_device_id *match; ++ ++ match = of_match_node(dw_mci_k3_match, pdev->dev.of_node); ++ drv_data = match->data; ++ ++ return dw_mci_pltfm_register(pdev, drv_data); ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int dw_mci_k3_suspend(struct device *dev) ++{ ++ struct dw_mci *host = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = dw_mci_suspend(host); ++ if (!ret) ++ clk_disable_unprepare(host->ciu_clk); ++ ++ return ret; ++} ++ ++static int dw_mci_k3_resume(struct device *dev) ++{ ++ struct dw_mci *host = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = clk_prepare_enable(host->ciu_clk); ++ if (ret) { ++ dev_err(host->dev, "failed to enable ciu clock\n"); ++ return ret; ++ } ++ ++ return dw_mci_resume(host); ++} ++#endif /* CONFIG_PM_SLEEP */ ++ ++static SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume); ++ ++static struct platform_driver dw_mci_k3_pltfm_driver = { ++ .probe = dw_mci_k3_probe, ++ .remove = dw_mci_pltfm_remove, ++ .driver = { ++ .name = "dwmmc_k3", ++ .of_match_table = dw_mci_k3_match, ++ .pm = &dw_mci_k3_pmops, ++ }, ++}; ++ ++module_platform_driver(dw_mci_k3_pltfm_driver); ++ ++MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:dwmmc-k3"); +diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c +new file mode 100644 +index 0000000..f70546a +--- /dev/null ++++ b/drivers/mmc/host/dw_mmc-pci.c +@@ -0,0 +1,125 @@ ++/* ++ * Synopsys DesignWare Multimedia Card PCI Interface driver ++ * ++ * Copyright (C) 2012 Vayavya Labs Pvt. 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 "dw_mmc.h" ++ ++#define PCI_BAR_NO 2 ++#define SYNOPSYS_DW_MCI_VENDOR_ID 0x700 ++#define SYNOPSYS_DW_MCI_DEVICE_ID 0x1107 ++/* Defining the Capabilities */ ++#define DW_MCI_CAPABILITIES (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED |\ ++ MMC_CAP_SD_HIGHSPEED | MMC_CAP_8_BIT_DATA |\ ++ MMC_CAP_SDIO_IRQ) ++ ++static struct dw_mci_board pci_board_data = { ++ .num_slots = 1, ++ .caps = DW_MCI_CAPABILITIES, ++ .bus_hz = 33 * 1000 * 1000, ++ .detect_delay_ms = 200, ++ .fifo_depth = 32, ++}; ++ ++static int dw_mci_pci_probe(struct pci_dev *pdev, ++ const struct pci_device_id *entries) ++{ ++ struct dw_mci *host; ++ int ret; ++ ++ ret = pcim_enable_device(pdev); ++ if (ret) ++ return ret; ++ ++ host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL); ++ if (!host) ++ return -ENOMEM; ++ ++ host->irq = pdev->irq; ++ host->irq_flags = IRQF_SHARED; ++ host->dev = &pdev->dev; ++ host->pdata = &pci_board_data; ++ ++ ret = pcim_iomap_regions(pdev, 1 << PCI_BAR_NO, pci_name(pdev)); ++ if (ret) ++ return ret; ++ ++ host->regs = pcim_iomap_table(pdev)[PCI_BAR_NO]; ++ ++ pci_set_master(pdev); ++ ++ ret = dw_mci_probe(host); ++ if (ret) ++ return ret; ++ ++ pci_set_drvdata(pdev, host); ++ ++ return 0; ++} ++ ++static void dw_mci_pci_remove(struct pci_dev *pdev) ++{ ++ struct dw_mci *host = pci_get_drvdata(pdev); ++ ++ dw_mci_remove(host); ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int dw_mci_pci_suspend(struct device *dev) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ struct dw_mci *host = pci_get_drvdata(pdev); ++ ++ return dw_mci_suspend(host); ++} ++ ++static int dw_mci_pci_resume(struct device *dev) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ struct dw_mci *host = pci_get_drvdata(pdev); ++ ++ return dw_mci_resume(host); ++} ++#else ++#define dw_mci_pci_suspend NULL ++#define dw_mci_pci_resume NULL ++#endif /* CONFIG_PM_SLEEP */ ++ ++static SIMPLE_DEV_PM_OPS(dw_mci_pci_pmops, dw_mci_pci_suspend, dw_mci_pci_resume); ++ ++static DEFINE_PCI_DEVICE_TABLE(dw_mci_pci_id) = { ++ { PCI_DEVICE(SYNOPSYS_DW_MCI_VENDOR_ID, SYNOPSYS_DW_MCI_DEVICE_ID) }, ++ {} ++}; ++MODULE_DEVICE_TABLE(pci, dw_mci_pci_id); ++ ++static struct pci_driver dw_mci_pci_driver = { ++ .name = "dw_mmc_pci", ++ .id_table = dw_mci_pci_id, ++ .probe = dw_mci_pci_probe, ++ .remove = dw_mci_pci_remove, ++ .driver = { ++ .pm = &dw_mci_pci_pmops ++ }, ++}; ++ ++module_pci_driver(dw_mci_pci_driver); ++ ++MODULE_DESCRIPTION("DW Multimedia Card PCI Interface driver"); ++MODULE_AUTHOR("Shashidhar Hiremath "); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c +new file mode 100644 +index 0000000..d4a47a9 +--- /dev/null ++++ b/drivers/mmc/host/dw_mmc-pltfm.c +@@ -0,0 +1,142 @@ ++/* ++ * Synopsys DesignWare Multimedia Card Interface driver ++ * ++ * Copyright (C) 2009 NXP Semiconductors ++ * Copyright (C) 2009, 2010 Imagination Technologies 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 "dw_mmc.h" ++#include "dw_mmc-pltfm.h" ++ ++static void dw_mci_pltfm_prepare_command(struct dw_mci *host, u32 *cmdr) ++{ ++ *cmdr |= SDMMC_CMD_USE_HOLD_REG; ++} ++ ++static const struct dw_mci_drv_data rockchip_drv_data = { ++ .prepare_command = dw_mci_pltfm_prepare_command, ++}; ++ ++static const struct dw_mci_drv_data socfpga_drv_data = { ++ .prepare_command = dw_mci_pltfm_prepare_command, ++}; ++ ++int dw_mci_pltfm_register(struct platform_device *pdev, ++ const struct dw_mci_drv_data *drv_data) ++{ ++ struct dw_mci *host; ++ struct resource *regs; ++ ++ host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL); ++ if (!host) ++ return -ENOMEM; ++ ++ host->irq = platform_get_irq(pdev, 0); ++ if (host->irq < 0) ++ return host->irq; ++ ++ host->drv_data = drv_data; ++ host->dev = &pdev->dev; ++ host->irq_flags = 0; ++ host->pdata = pdev->dev.platform_data; ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ host->regs = devm_ioremap_resource(&pdev->dev, regs); ++ if (IS_ERR(host->regs)) ++ return PTR_ERR(host->regs); ++ ++ platform_set_drvdata(pdev, host); ++ return dw_mci_probe(host); ++} ++EXPORT_SYMBOL_GPL(dw_mci_pltfm_register); ++ ++#ifdef CONFIG_PM_SLEEP ++/* ++ * TODO: we should probably disable the clock to the card in the suspend path. ++ */ ++static int dw_mci_pltfm_suspend(struct device *dev) ++{ ++ struct dw_mci *host = dev_get_drvdata(dev); ++ ++ return dw_mci_suspend(host); ++} ++ ++static int dw_mci_pltfm_resume(struct device *dev) ++{ ++ struct dw_mci *host = dev_get_drvdata(dev); ++ ++ return dw_mci_resume(host); ++} ++#else ++#define dw_mci_pltfm_suspend NULL ++#define dw_mci_pltfm_resume NULL ++#endif /* CONFIG_PM_SLEEP */ ++ ++SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume); ++EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops); ++ ++static const struct of_device_id dw_mci_pltfm_match[] = { ++ { .compatible = "snps,dw-mshc", }, ++ { .compatible = "rockchip,rk2928-dw-mshc", ++ .data = &rockchip_drv_data }, ++ { .compatible = "altr,socfpga-dw-mshc", ++ .data = &socfpga_drv_data }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); ++ ++static int dw_mci_pltfm_probe(struct platform_device *pdev) ++{ ++ const struct dw_mci_drv_data *drv_data = NULL; ++ const struct of_device_id *match; ++ ++ if (pdev->dev.of_node) { ++ match = of_match_node(dw_mci_pltfm_match, pdev->dev.of_node); ++ drv_data = match->data; ++ } ++ ++ return dw_mci_pltfm_register(pdev, drv_data); ++} ++ ++int dw_mci_pltfm_remove(struct platform_device *pdev) ++{ ++ struct dw_mci *host = platform_get_drvdata(pdev); ++ ++ dw_mci_remove(host); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove); ++ ++static struct platform_driver dw_mci_pltfm_driver = { ++ .probe = dw_mci_pltfm_probe, ++ .remove = dw_mci_pltfm_remove, ++ .driver = { ++ .name = "dw_mmc", ++ .of_match_table = dw_mci_pltfm_match, ++ .pm = &dw_mci_pltfm_pmops, ++ }, ++}; ++ ++module_platform_driver(dw_mci_pltfm_driver); ++ ++MODULE_DESCRIPTION("DW Multimedia Card Interface driver"); ++MODULE_AUTHOR("NXP Semiconductor VietNam"); ++MODULE_AUTHOR("Imagination Technologies Ltd"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h +new file mode 100644 +index 0000000..68e7fd2 +--- /dev/null ++++ b/drivers/mmc/host/dw_mmc-pltfm.h +@@ -0,0 +1,20 @@ ++/* ++ * Synopsys DesignWare Multimedia Card Interface Platform driver ++ * ++ * Copyright (C) 2012, Samsung Electronics 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. ++ */ ++ ++#ifndef _DW_MMC_PLTFM_H_ ++#define _DW_MMC_PLTFM_H_ ++ ++extern int dw_mci_pltfm_register(struct platform_device *pdev, ++ const struct dw_mci_drv_data *drv_data); ++extern int dw_mci_pltfm_remove(struct platform_device *pdev); ++extern const struct dev_pm_ops dw_mci_pltfm_pmops; ++ ++#endif /* _DW_MMC_PLTFM_H_ */ +diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c +index baf3d42..1ac227c 100644 +--- a/drivers/mmc/host/dw_mmc.c ++++ b/drivers/mmc/host/dw_mmc.c +@@ -29,15 +29,19 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include ++#include ++#include + + #include "dw_mmc.h" + + /* Common flag combinations */ +-#define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DTO | SDMMC_INT_DCRC | \ ++#define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DRTO | SDMMC_INT_DCRC | \ + SDMMC_INT_HTO | SDMMC_INT_SBE | \ + SDMMC_INT_EBE) + #define DW_MCI_CMD_ERROR_FLAGS (SDMMC_INT_RTO | SDMMC_INT_RCRC | \ +@@ -48,7 +52,15 @@ + #define DW_MCI_RECV_STATUS 2 + #define DW_MCI_DMA_THRESHOLD 16 + ++#define DW_MCI_FREQ_MAX 200000000 /* unit: HZ */ ++#define DW_MCI_FREQ_MIN 400000 /* unit: HZ */ ++ + #ifdef CONFIG_MMC_DW_IDMAC ++#define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \ ++ SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \ ++ SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \ ++ SDMMC_IDMAC_INT_TI) ++ + struct idmac_desc { + u32 des0; /* Control Descriptor */ + #define IDMAC_DES0_DIC BIT(1) +@@ -69,38 +81,38 @@ struct idmac_desc { + }; + #endif /* CONFIG_MMC_DW_IDMAC */ + +-/** +- * struct dw_mci_slot - MMC slot state +- * @mmc: The mmc_host representing this slot. +- * @host: The MMC controller this slot is using. +- * @ctype: Card type for this slot. +- * @mrq: mmc_request currently being processed or waiting to be +- * processed, or NULL when the slot is idle. +- * @queue_node: List node for placing this node in the @queue list of +- * &struct dw_mci. +- * @clock: Clock rate configured by set_ios(). Protected by host->lock. +- * @flags: Random state bits associated with the slot. +- * @id: Number of this slot. +- * @last_detect_state: Most recently observed card detect state. +- */ +-struct dw_mci_slot { +- struct mmc_host *mmc; +- struct dw_mci *host; +- +- u32 ctype; +- +- struct mmc_request *mrq; +- struct list_head queue_node; ++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, ++}; + +- unsigned int clock; +- unsigned long flags; +-#define DW_MMC_CARD_PRESENT 0 +-#define DW_MMC_CARD_NEED_INIT 1 +- int id; +- int last_detect_state; ++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 struct workqueue_struct *dw_mci_card_workqueue; ++static inline bool dw_mci_fifo_reset(struct dw_mci *host); ++static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host); + + #if defined(CONFIG_DEBUG_FS) + static int dw_mci_req_show(struct seq_file *s, void *v) +@@ -223,23 +235,23 @@ err: + } + #endif /* defined(CONFIG_DEBUG_FS) */ + +-static void dw_mci_set_timeout(struct dw_mci *host) +-{ +- /* timeout (maximum) */ +- mci_writel(host, TMOUT, 0xffffffff); +-} +- + static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) + { + struct mmc_data *data; ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ const struct dw_mci_drv_data *drv_data = slot->host->drv_data; + u32 cmdr; + cmd->error = -EINPROGRESS; + + cmdr = cmd->opcode; + +- if (cmdr == MMC_STOP_TRANSMISSION) ++ if (cmd->opcode == MMC_STOP_TRANSMISSION || ++ cmd->opcode == MMC_GO_IDLE_STATE || ++ cmd->opcode == MMC_GO_INACTIVE_STATE || ++ (cmd->opcode == SD_IO_RW_DIRECT && ++ ((cmd->arg >> 9) & 0x1FFFF) == SDIO_CCCR_ABORT)) + cmdr |= SDMMC_CMD_STOP; +- else ++ else if (cmd->opcode != MMC_SEND_STATUS && cmd->data) + cmdr |= SDMMC_CMD_PRV_DAT_WAIT; + + if (cmd->flags & MMC_RSP_PRESENT) { +@@ -261,6 +273,43 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) + cmdr |= SDMMC_CMD_DAT_WR; + } + ++ if (drv_data && drv_data->prepare_command) ++ drv_data->prepare_command(slot->host, &cmdr); ++ ++ return cmdr; ++} ++ ++static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd) ++{ ++ struct mmc_command *stop; ++ u32 cmdr; ++ ++ if (!cmd->data) ++ return 0; ++ ++ stop = &host->stop_abort; ++ cmdr = cmd->opcode; ++ memset(stop, 0, sizeof(struct mmc_command)); ++ ++ if (cmdr == MMC_READ_SINGLE_BLOCK || ++ cmdr == MMC_READ_MULTIPLE_BLOCK || ++ cmdr == MMC_WRITE_BLOCK || ++ cmdr == MMC_WRITE_MULTIPLE_BLOCK) { ++ stop->opcode = MMC_STOP_TRANSMISSION; ++ stop->arg = 0; ++ stop->flags = MMC_RSP_R1B | MMC_CMD_AC; ++ } else if (cmdr == SD_IO_RW_EXTENDED) { ++ stop->opcode = SD_IO_RW_DIRECT; ++ stop->arg |= (1 << 31) | (0 << 28) | (SDIO_CCCR_ABORT << 9) | ++ ((cmd->arg >> 28) & 0x7); ++ stop->flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; ++ } else { ++ return 0; ++ } ++ ++ cmdr = stop->opcode | SDMMC_CMD_STOP | ++ SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_EXP; ++ + return cmdr; + } + +@@ -268,7 +317,7 @@ static void dw_mci_start_command(struct dw_mci *host, + struct mmc_command *cmd, u32 cmd_flags) + { + host->cmd = cmd; +- dev_vdbg(&host->pdev->dev, ++ dev_vdbg(host->dev, + "start command: ARGR=0x%08x CMDR=0x%08x\n", + cmd->arg, cmd_flags); + +@@ -278,9 +327,10 @@ static void dw_mci_start_command(struct dw_mci *host, + mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START); + } + +-static void send_stop_cmd(struct dw_mci *host, struct mmc_data *data) ++static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data) + { +- dw_mci_start_command(host, data->stop, host->stop_cmdr); ++ struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort; ++ dw_mci_start_command(host, stop, host->stop_cmdr); + } + + /* DMA interface functions */ +@@ -289,10 +339,18 @@ static void dw_mci_stop_dma(struct dw_mci *host) + if (host->using_dma) { + host->dma_ops->stop(host); + host->dma_ops->cleanup(host); +- } else { +- /* Data transfer was stopped by the interrupt handler */ +- set_bit(EVENT_XFER_COMPLETE, &host->pending_events); + } ++ ++ /* Data transfer was stopped by the interrupt handler */ ++ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); ++} ++ ++static int dw_mci_get_dma_dir(struct mmc_data *data) ++{ ++ if (data->flags & MMC_DATA_WRITE) ++ return DMA_TO_DEVICE; ++ else ++ return DMA_FROM_DEVICE; + } + + #ifdef CONFIG_MMC_DW_IDMAC +@@ -301,9 +359,19 @@ static void dw_mci_dma_cleanup(struct dw_mci *host) + struct mmc_data *data = host->data; + + if (data) +- dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, +- ((data->flags & MMC_DATA_WRITE) +- ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); ++ if (!data->host_cookie) ++ dma_unmap_sg(host->dev, ++ data->sg, ++ data->sg_len, ++ dw_mci_get_dma_dir(data)); ++} ++ ++static void dw_mci_idmac_reset(struct dw_mci *host) ++{ ++ u32 bmod = mci_readl(host, BMOD); ++ /* Software reset of DMA */ ++ bmod |= SDMMC_IDMAC_SWRESET; ++ mci_writel(host, BMOD, bmod); + } + + static void dw_mci_idmac_stop_dma(struct dw_mci *host) +@@ -319,6 +387,7 @@ static void dw_mci_idmac_stop_dma(struct dw_mci *host) + /* Stop the IDMAC running */ + temp = mci_readl(host, BMOD); + temp &= ~(SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB); ++ temp |= SDMMC_IDMAC_SWRESET; + mci_writel(host, BMOD, temp); + } + +@@ -326,7 +395,7 @@ static void dw_mci_idmac_complete_dma(struct dw_mci *host) + { + struct mmc_data *data = host->data; + +- dev_vdbg(&host->pdev->dev, "DMA complete\n"); ++ dev_vdbg(host->dev, "DMA complete\n"); + + host->dma_ops->cleanup(host); + +@@ -410,7 +479,10 @@ static int dw_mci_idmac_init(struct dw_mci *host) + p->des3 = host->sg_dma; + p->des0 = IDMAC_DES0_ER; + ++ dw_mci_idmac_reset(host); ++ + /* Mask out interrupts - get Tx & Rx complete only */ ++ mci_writel(host, IDSTS, IDMAC_INT_CLR); + mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI | + SDMMC_IDMAC_INT_TI); + +@@ -419,7 +491,7 @@ static int dw_mci_idmac_init(struct dw_mci *host) + return 0; + } + +-static struct dw_mci_dma_ops dw_mci_idmac_ops = { ++static const struct dw_mci_dma_ops dw_mci_idmac_ops = { + .init = dw_mci_idmac_init, + .start = dw_mci_idmac_start_dma, + .stop = dw_mci_idmac_stop_dma, +@@ -428,17 +500,15 @@ static struct dw_mci_dma_ops dw_mci_idmac_ops = { + }; + #endif /* CONFIG_MMC_DW_IDMAC */ + +-static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) ++static int dw_mci_pre_dma_transfer(struct dw_mci *host, ++ struct mmc_data *data, ++ bool next) + { + struct scatterlist *sg; +- unsigned int i, direction, sg_len; +- u32 temp; +- +- host->using_dma = 0; ++ unsigned int i, sg_len; + +- /* If we don't have a channel, we can't do DMA */ +- if (!host->use_dma) +- return -ENODEV; ++ if (!next && data->host_cookie) ++ return data->host_cookie; + + /* + * We don't do DMA on "complex" transfers, i.e. with +@@ -447,6 +517,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) + */ + if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD) + return -EINVAL; ++ + if (data->blksz & 3) + return -EINVAL; + +@@ -455,21 +526,160 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) + return -EINVAL; + } + +- host->using_dma = 1; ++ sg_len = dma_map_sg(host->dev, ++ data->sg, ++ data->sg_len, ++ dw_mci_get_dma_dir(data)); ++ if (sg_len == 0) ++ return -EINVAL; + +- if (data->flags & MMC_DATA_READ) +- direction = DMA_FROM_DEVICE; +- else +- direction = DMA_TO_DEVICE; ++ if (next) ++ data->host_cookie = sg_len; ++ ++ return sg_len; ++} ++ ++static void dw_mci_pre_req(struct mmc_host *mmc, ++ struct mmc_request *mrq, ++ bool is_first_req) ++{ ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ struct mmc_data *data = mrq->data; ++ ++ if (!slot->host->use_dma || !data) ++ return; ++ ++ if (data->host_cookie) { ++ data->host_cookie = 0; ++ return; ++ } ++ ++ if (dw_mci_pre_dma_transfer(slot->host, mrq->data, 1) < 0) ++ data->host_cookie = 0; ++} ++ ++static void dw_mci_post_req(struct mmc_host *mmc, ++ struct mmc_request *mrq, ++ int err) ++{ ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ struct mmc_data *data = mrq->data; + +- sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, +- direction); ++ if (!slot->host->use_dma || !data) ++ return; ++ ++ if (data->host_cookie) ++ dma_unmap_sg(slot->host->dev, ++ data->sg, ++ data->sg_len, ++ dw_mci_get_dma_dir(data)); ++ data->host_cookie = 0; ++} ++ ++static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data) ++{ ++#ifdef CONFIG_MMC_DW_IDMAC ++ unsigned int blksz = data->blksz; ++ const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256}; ++ u32 fifo_width = 1 << host->data_shift; ++ u32 blksz_depth = blksz / fifo_width, fifoth_val; ++ u32 msize = 0, rx_wmark = 1, tx_wmark, tx_wmark_invers; ++ int idx = (sizeof(mszs) / sizeof(mszs[0])) - 1; ++ ++ tx_wmark = (host->fifo_depth) / 2; ++ tx_wmark_invers = host->fifo_depth - tx_wmark; ++ ++ /* ++ * MSIZE is '1', ++ * if blksz is not a multiple of the FIFO width ++ */ ++ if (blksz % fifo_width) { ++ msize = 0; ++ rx_wmark = 1; ++ goto done; ++ } ++ ++ do { ++ if (!((blksz_depth % mszs[idx]) || ++ (tx_wmark_invers % mszs[idx]))) { ++ msize = idx; ++ rx_wmark = mszs[idx] - 1; ++ break; ++ } ++ } while (--idx > 0); ++ /* ++ * If idx is '0', it won't be tried ++ * Thus, initial values are uesed ++ */ ++done: ++ fifoth_val = SDMMC_SET_FIFOTH(msize, rx_wmark, tx_wmark); ++ mci_writel(host, FIFOTH, fifoth_val); ++#endif ++} ++ ++static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data) ++{ ++ unsigned int blksz = data->blksz; ++ u32 blksz_depth, fifo_depth; ++ u16 thld_size; ++ ++ WARN_ON(!(data->flags & MMC_DATA_READ)); ++ ++ if (host->timing != MMC_TIMING_MMC_HS200 && ++ host->timing != MMC_TIMING_UHS_SDR104) ++ goto disable; ++ ++ blksz_depth = blksz / (1 << host->data_shift); ++ fifo_depth = host->fifo_depth; ++ ++ if (blksz_depth > fifo_depth) ++ goto disable; ++ ++ /* ++ * If (blksz_depth) >= (fifo_depth >> 1), should be 'thld_size <= blksz' ++ * If (blksz_depth) < (fifo_depth >> 1), should be thld_size = blksz ++ * Currently just choose blksz. ++ */ ++ thld_size = blksz; ++ mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(thld_size, 1)); ++ return; ++ ++disable: ++ mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(0, 0)); ++} + +- dev_vdbg(&host->pdev->dev, ++static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) ++{ ++ int sg_len; ++ u32 temp; ++ ++ host->using_dma = 0; ++ ++ /* If we don't have a channel, we can't do DMA */ ++ if (!host->use_dma) ++ return -ENODEV; ++ ++ sg_len = dw_mci_pre_dma_transfer(host, data, 0); ++ if (sg_len < 0) { ++ host->dma_ops->stop(host); ++ return sg_len; ++ } ++ ++ host->using_dma = 1; ++ ++ dev_vdbg(host->dev, + "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n", + (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, + sg_len); + ++ /* ++ * Decide the MSIZE and RX/TX Watermark. ++ * If current block size is same with previous size, ++ * no need to update fifoth. ++ */ ++ if (host->prev_blksz != data->blksz) ++ dw_mci_adjust_fifoth(host, data); ++ + /* Enable the DMA interface */ + temp = mci_readl(host, CTRL); + temp |= SDMMC_CTRL_DMA_ENABLE; +@@ -495,10 +705,12 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) + host->sg = NULL; + host->data = data; + +- if (data->flags & MMC_DATA_READ) ++ if (data->flags & MMC_DATA_READ) { + host->dir_status = DW_MCI_RECV_STATUS; +- else ++ dw_mci_ctrl_rd_thld(host, data); ++ } else { + host->dir_status = DW_MCI_SEND_STATUS; ++ } + + if (dw_mci_submit_data_dma(host, data)) { + int flags = SG_MITER_ATOMIC; +@@ -520,6 +732,21 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) + temp = mci_readl(host, CTRL); + temp &= ~SDMMC_CTRL_DMA_ENABLE; + mci_writel(host, CTRL, temp); ++ ++ /* ++ * Use the initial fifoth_val for PIO mode. ++ * If next issued data may be transfered by DMA mode, ++ * prev_blksz should be invalidated. ++ */ ++ mci_writel(host, FIFOTH, host->fifoth_val); ++ host->prev_blksz = 0; ++ } else { ++ /* ++ * Keep the current block size. ++ * It will be used to decide whether to update ++ * fifoth register next time. ++ */ ++ host->prev_blksz = data->blksz; + } + } + +@@ -543,25 +770,34 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) + cmd, arg, cmd_status); + } + +-static void dw_mci_setup_bus(struct dw_mci_slot *slot) ++static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) + { + struct dw_mci *host = slot->host; ++ unsigned int clock = slot->clock; + u32 div; ++ u32 clk_en_a; + +- if (slot->clock != host->current_speed) { +- if (host->bus_hz % slot->clock) ++ if (!clock) { ++ mci_writel(host, CLKENA, 0); ++ mci_send_cmd(slot, ++ SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); ++ } else if (clock != host->current_speed || force_clkinit) { ++ div = host->bus_hz / clock; ++ if (host->bus_hz % clock && host->bus_hz > clock) + /* + * move the + 1 after the divide to prevent + * over-clocking the card. + */ +- div = ((host->bus_hz / slot->clock) >> 1) + 1; +- else +- div = (host->bus_hz / slot->clock) >> 1; ++ div += 1; + +- dev_info(&slot->mmc->class_dev, +- "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ" +- " div = %d)\n", slot->id, host->bus_hz, slot->clock, +- div ? ((host->bus_hz / div) >> 1) : host->bus_hz, div); ++ div = (host->bus_hz != clock) ? DIV_ROUND_UP(div, 2) : 0; ++ ++ if ((clock << div) != slot->__clk_old || force_clkinit) ++ dev_info(&slot->mmc->class_dev, ++ "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ div = %d)\n", ++ slot->id, host->bus_hz, clock, ++ div ? ((host->bus_hz / div) >> 1) : ++ host->bus_hz, div); + + /* disable clock */ + mci_writel(host, CLKENA, 0); +@@ -578,51 +814,52 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) + mci_send_cmd(slot, + SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); + +- /* enable clock */ +- mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE | +- SDMMC_CLKEN_LOW_PWR); ++ /* enable clock; only low power if no SDIO */ ++ clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; ++ if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id))) ++ clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; ++ mci_writel(host, CLKENA, clk_en_a); + + /* inform CIU */ + mci_send_cmd(slot, + SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); + +- host->current_speed = slot->clock; ++ /* keep the clock with reflecting clock dividor */ ++ slot->__clk_old = clock << div; + } + ++ host->current_speed = clock; ++ + /* Set the current slot bus width */ + mci_writel(host, CTYPE, (slot->ctype << slot->id)); + } + +-static void dw_mci_start_request(struct dw_mci *host, +- struct dw_mci_slot *slot) ++static void __dw_mci_start_request(struct dw_mci *host, ++ struct dw_mci_slot *slot, ++ struct mmc_command *cmd) + { + struct mmc_request *mrq; +- struct mmc_command *cmd; + struct mmc_data *data; + u32 cmdflags; + + mrq = slot->mrq; +- if (host->pdata->select_slot) +- host->pdata->select_slot(slot->id); +- +- /* Slot specific timing and width adjustment */ +- dw_mci_setup_bus(slot); + + host->cur_slot = slot; + host->mrq = mrq; + + host->pending_events = 0; + host->completed_events = 0; ++ host->cmd_status = 0; + host->data_status = 0; ++ host->dir_status = 0; + +- data = mrq->data; ++ data = cmd->data; + if (data) { +- dw_mci_set_timeout(host); ++ mci_writel(host, TMOUT, 0xFFFFFFFF); + mci_writel(host, BYTCNT, data->blksz*data->blocks); + mci_writel(host, BLKSIZ, data->blksz); + } + +- cmd = mrq->cmd; + cmdflags = dw_mci_prepare_command(slot->mmc, cmd); + + /* this is the first command, send the initialization clock */ +@@ -638,6 +875,18 @@ static void dw_mci_start_request(struct dw_mci *host, + + if (mrq->stop) + host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); ++ else ++ host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd); ++} ++ ++static void dw_mci_start_request(struct dw_mci *host, ++ struct dw_mci_slot *slot) ++{ ++ struct mmc_request *mrq = slot->mrq; ++ struct mmc_command *cmd; ++ ++ cmd = mrq->sbc ? mrq->sbc : mrq->cmd; ++ __dw_mci_start_request(host, slot, cmd); + } + + /* must be called with host->lock held */ +@@ -686,41 +935,55 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) + static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct dw_mci_slot *slot = mmc_priv(mmc); ++ const struct dw_mci_drv_data *drv_data = slot->host->drv_data; + u32 regs; + +- /* set default 1 bit mode */ +- slot->ctype = SDMMC_CTYPE_1BIT; +- + switch (ios->bus_width) { +- case MMC_BUS_WIDTH_1: +- slot->ctype = SDMMC_CTYPE_1BIT; +- break; + case MMC_BUS_WIDTH_4: + slot->ctype = SDMMC_CTYPE_4BIT; + break; + case MMC_BUS_WIDTH_8: + slot->ctype = SDMMC_CTYPE_8BIT; + break; ++ default: ++ /* set default 1 bit mode */ ++ slot->ctype = SDMMC_CTYPE_1BIT; + } + ++ regs = mci_readl(slot->host, UHS_REG); ++ + /* DDR mode set */ +- if (ios->timing == MMC_TIMING_UHS_DDR50) { +- regs = mci_readl(slot->host, UHS_REG); +- regs |= (0x1 << slot->id) << 16; +- mci_writel(slot->host, UHS_REG, regs); +- } ++ if (ios->timing == MMC_TIMING_MMC_DDR52) ++ regs |= ((0x1 << slot->id) << 16); ++ else ++ regs &= ~((0x1 << slot->id) << 16); + +- if (ios->clock) { +- /* +- * Use mirror of ios->clock to prevent race with mmc +- * core ios update when finding the minimum. +- */ +- slot->clock = ios->clock; +- } ++ mci_writel(slot->host, UHS_REG, regs); ++ slot->host->timing = ios->timing; ++ ++ /* ++ * Use mirror of ios->clock to prevent race with mmc ++ * core ios update when finding the minimum. ++ */ ++ slot->clock = ios->clock; ++ ++ if (drv_data && drv_data->set_ios) ++ drv_data->set_ios(slot->host, ios); ++ ++ /* Slot specific timing and width adjustment */ ++ dw_mci_setup_bus(slot, false); + + switch (ios->power_mode) { + case MMC_POWER_UP: + set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); ++ regs = mci_readl(slot->host, PWREN); ++ regs |= (1 << slot->id); ++ mci_writel(slot->host, PWREN, regs); ++ break; ++ case MMC_POWER_OFF: ++ regs = mci_readl(slot->host, PWREN); ++ regs &= ~(1 << slot->id); ++ mci_writel(slot->host, PWREN, regs); + break; + default: + break; +@@ -731,11 +994,13 @@ static int dw_mci_get_ro(struct mmc_host *mmc) + { + int read_only; + struct dw_mci_slot *slot = mmc_priv(mmc); +- struct dw_mci_board *brd = slot->host->pdata; ++ int gpio_ro = mmc_gpio_get_ro(mmc); + + /* Use platform get_ro function, else try on board write protect */ +- if (brd->get_ro) +- read_only = brd->get_ro(slot->id); ++ if (slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT) ++ read_only = 0; ++ else if (!IS_ERR_VALUE(gpio_ro)) ++ read_only = gpio_ro; + else + read_only = + mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0; +@@ -751,24 +1016,55 @@ static int dw_mci_get_cd(struct mmc_host *mmc) + int present; + struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci_board *brd = slot->host->pdata; ++ struct dw_mci *host = slot->host; ++ int gpio_cd = mmc_gpio_get_cd(mmc); + + /* Use platform get_cd function, else try onboard card detect */ + if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) + present = 1; +- else if (brd->get_cd) +- present = !brd->get_cd(slot->id); ++ else if (!IS_ERR_VALUE(gpio_cd)) ++ present = gpio_cd; + else + present = (mci_readl(slot->host, CDETECT) & (1 << slot->id)) + == 0 ? 1 : 0; + +- if (present) ++ spin_lock_bh(&host->lock); ++ if (present) { ++ set_bit(DW_MMC_CARD_PRESENT, &slot->flags); + dev_dbg(&mmc->class_dev, "card is present\n"); +- else ++ } else { ++ clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); + dev_dbg(&mmc->class_dev, "card is not present\n"); ++ } ++ spin_unlock_bh(&host->lock); + + return present; + } + ++/* ++ * Disable lower power mode. ++ * ++ * Low power mode will stop the card clock when idle. According to the ++ * description of the CLKENA register we should disable low power mode ++ * for SDIO cards if we need SDIO interrupts to work. ++ * ++ * This function is fast if low power mode is already disabled. ++ */ ++static void dw_mci_disable_low_power(struct dw_mci_slot *slot) ++{ ++ struct dw_mci *host = slot->host; ++ u32 clk_en_a; ++ const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id; ++ ++ clk_en_a = mci_readl(host, CLKENA); ++ ++ if (clk_en_a & clken_low_pwr) { ++ mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr); ++ mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | ++ SDMMC_CMD_PRV_DAT_WAIT, 0); ++ } ++} ++ + static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) + { + struct dw_mci_slot *slot = mmc_priv(mmc); +@@ -778,20 +1074,63 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) + /* Enable/disable Slot Specific SDIO interrupt */ + int_mask = mci_readl(host, INTMASK); + if (enb) { ++ /* ++ * Turn off low power mode if it was enabled. This is a bit of ++ * a heavy operation and we disable / enable IRQs a lot, so ++ * we'll leave low power mode disabled and it will get ++ * re-enabled again in dw_mci_setup_bus(). ++ */ ++ dw_mci_disable_low_power(slot); ++ + mci_writel(host, INTMASK, +- (int_mask | (1 << SDMMC_INT_SDIO(slot->id)))); ++ (int_mask | SDMMC_INT_SDIO(slot->id))); + } else { + mci_writel(host, INTMASK, +- (int_mask & ~(1 << SDMMC_INT_SDIO(slot->id)))); ++ (int_mask & ~SDMMC_INT_SDIO(slot->id))); ++ } ++} ++ ++static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode) ++{ ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ struct dw_mci *host = slot->host; ++ const struct dw_mci_drv_data *drv_data = host->drv_data; ++ struct dw_mci_tuning_data tuning_data; ++ int err = -ENOSYS; ++ ++ if (opcode == MMC_SEND_TUNING_BLOCK_HS200) { ++ if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) { ++ tuning_data.blk_pattern = tuning_blk_pattern_8bit; ++ tuning_data.blksz = sizeof(tuning_blk_pattern_8bit); ++ } else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) { ++ tuning_data.blk_pattern = tuning_blk_pattern_4bit; ++ tuning_data.blksz = sizeof(tuning_blk_pattern_4bit); ++ } else { ++ return -EINVAL; ++ } ++ } else if (opcode == MMC_SEND_TUNING_BLOCK) { ++ tuning_data.blk_pattern = tuning_blk_pattern_4bit; ++ tuning_data.blksz = sizeof(tuning_blk_pattern_4bit); ++ } else { ++ dev_err(host->dev, ++ "Undefined command(%d) for tuning\n", opcode); ++ return -EINVAL; + } ++ ++ if (drv_data && drv_data->execute_tuning) ++ err = drv_data->execute_tuning(slot, opcode, &tuning_data); ++ return err; + } + + static const struct mmc_host_ops dw_mci_ops = { + .request = dw_mci_request, ++ .pre_req = dw_mci_pre_req, ++ .post_req = dw_mci_post_req, + .set_ios = dw_mci_set_ios, + .get_ro = dw_mci_get_ro, + .get_cd = dw_mci_get_cd, + .enable_sdio_irq = dw_mci_enable_sdio_irq, ++ .execute_tuning = dw_mci_execute_tuning, + }; + + static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) +@@ -809,12 +1148,12 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) + slot = list_entry(host->queue.next, + struct dw_mci_slot, queue_node); + list_del(&slot->queue_node); +- dev_vdbg(&host->pdev->dev, "list not empty: %s is next\n", ++ dev_vdbg(host->dev, "list not empty: %s is next\n", + mmc_hostname(slot->mmc)); + host->state = STATE_SENDING_CMD; + dw_mci_start_request(host, slot); + } else { +- dev_vdbg(&host->pdev->dev, "list empty\n"); ++ dev_vdbg(host->dev, "list empty\n"); + host->state = STATE_IDLE; + } + +@@ -823,7 +1162,7 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) + spin_lock(&host->lock); + } + +-static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd) ++static int dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd) + { + u32 status = host->cmd_status; + +@@ -857,12 +1196,52 @@ static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd + /* newer ip versions need a delay between retries */ + if (host->quirks & DW_MCI_QUIRK_RETRY_DELAY) + mdelay(20); ++ } + +- if (cmd->data) { +- host->data = NULL; +- dw_mci_stop_dma(host); ++ return cmd->error; ++} ++ ++static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data) ++{ ++ u32 status = host->data_status; ++ ++ if (status & DW_MCI_DATA_ERROR_FLAGS) { ++ if (status & SDMMC_INT_DRTO) { ++ data->error = -ETIMEDOUT; ++ } else if (status & SDMMC_INT_DCRC) { ++ data->error = -EILSEQ; ++ } else if (status & SDMMC_INT_EBE) { ++ if (host->dir_status == ++ DW_MCI_SEND_STATUS) { ++ /* ++ * No data CRC status was returned. ++ * The number of bytes transferred ++ * will be exaggerated in PIO mode. ++ */ ++ data->bytes_xfered = 0; ++ data->error = -ETIMEDOUT; ++ } else if (host->dir_status == ++ DW_MCI_RECV_STATUS) { ++ data->error = -EIO; ++ } ++ } else { ++ /* SDMMC_INT_SBE is included */ ++ data->error = -EIO; + } ++ ++ dev_dbg(host->dev, "data error, status 0x%08x\n", status); ++ ++ /* ++ * After an error, there may be data lingering ++ * in the FIFO ++ */ ++ dw_mci_fifo_reset(host); ++ } else { ++ data->bytes_xfered = data->blocks * data->blksz; ++ data->error = 0; + } ++ ++ return data->error; + } + + static void dw_mci_tasklet_func(unsigned long priv) +@@ -870,14 +1249,16 @@ static void dw_mci_tasklet_func(unsigned long priv) + struct dw_mci *host = (struct dw_mci *)priv; + struct mmc_data *data; + struct mmc_command *cmd; ++ struct mmc_request *mrq; + enum dw_mci_state state; + enum dw_mci_state prev_state; +- u32 status, ctrl; ++ unsigned int err; + + spin_lock(&host->lock); + + state = host->state; + data = host->data; ++ mrq = host->mrq; + + do { + prev_state = state; +@@ -894,9 +1275,23 @@ static void dw_mci_tasklet_func(unsigned long priv) + cmd = host->cmd; + host->cmd = NULL; + set_bit(EVENT_CMD_COMPLETE, &host->completed_events); +- dw_mci_command_complete(host, host->mrq->cmd); +- if (!host->mrq->data || cmd->error) { +- dw_mci_request_end(host, host->mrq); ++ err = dw_mci_command_complete(host, cmd); ++ if (cmd == mrq->sbc && !err) { ++ prev_state = state = STATE_SENDING_CMD; ++ __dw_mci_start_request(host, host->cur_slot, ++ mrq->cmd); ++ goto unlock; ++ } ++ ++ if (cmd->data && err) { ++ dw_mci_stop_dma(host); ++ send_stop_abort(host, data); ++ state = STATE_SENDING_STOP; ++ break; ++ } ++ ++ if (!cmd->data || err) { ++ dw_mci_request_end(host, mrq); + goto unlock; + } + +@@ -907,8 +1302,7 @@ static void dw_mci_tasklet_func(unsigned long priv) + if (test_and_clear_bit(EVENT_DATA_ERROR, + &host->pending_events)) { + dw_mci_stop_dma(host); +- if (data->stop) +- send_stop_cmd(host, data); ++ send_stop_abort(host, data); + state = STATE_DATA_ERROR; + break; + } +@@ -928,54 +1322,27 @@ static void dw_mci_tasklet_func(unsigned long priv) + + host->data = NULL; + set_bit(EVENT_DATA_COMPLETE, &host->completed_events); +- status = host->data_status; +- +- if (status & DW_MCI_DATA_ERROR_FLAGS) { +- if (status & SDMMC_INT_DTO) { +- data->error = -ETIMEDOUT; +- } else if (status & SDMMC_INT_DCRC) { +- data->error = -EILSEQ; +- } else if (status & SDMMC_INT_EBE && +- host->dir_status == +- DW_MCI_SEND_STATUS) { +- /* +- * No data CRC status was returned. +- * The number of bytes transferred will +- * be exaggerated in PIO mode. +- */ +- data->bytes_xfered = 0; +- data->error = -ETIMEDOUT; +- } else { +- dev_err(&host->pdev->dev, +- "data FIFO error " +- "(status=%08x)\n", +- status); +- data->error = -EIO; ++ err = dw_mci_data_complete(host, data); ++ ++ if (!err) { ++ if (!data->stop || mrq->sbc) { ++ if (mrq->sbc && data->stop) ++ data->stop->error = 0; ++ dw_mci_request_end(host, mrq); ++ goto unlock; + } +- /* +- * After an error, there may be data lingering +- * in the FIFO, so reset it - doing so +- * generates a block interrupt, hence setting +- * the scatter-gather pointer to NULL. +- */ +- sg_miter_stop(&host->sg_miter); +- host->sg = NULL; +- ctrl = mci_readl(host, CTRL); +- ctrl |= SDMMC_CTRL_FIFO_RESET; +- mci_writel(host, CTRL, ctrl); +- } else { +- data->bytes_xfered = data->blocks * data->blksz; +- data->error = 0; +- } + +- if (!data->stop) { +- dw_mci_request_end(host, host->mrq); +- goto unlock; ++ /* stop command for open-ended transfer*/ ++ if (data->stop) ++ send_stop_abort(host, data); + } + ++ /* ++ * If err has non-zero, ++ * stop-abort command has been already issued. ++ */ + prev_state = state = STATE_SENDING_STOP; +- if (!data->error) +- send_stop_cmd(host, data); ++ + /* fall through */ + + case STATE_SENDING_STOP: +@@ -983,9 +1350,19 @@ static void dw_mci_tasklet_func(unsigned long priv) + &host->pending_events)) + break; + ++ /* CMD error in data command */ ++ if (mrq->cmd->error && mrq->data) ++ dw_mci_fifo_reset(host); ++ + host->cmd = NULL; +- dw_mci_command_complete(host, host->mrq->stop); +- dw_mci_request_end(host, host->mrq); ++ host->data = NULL; ++ ++ if (mrq->stop) ++ dw_mci_command_complete(host, mrq->stop); ++ else ++ host->cmd_status = 0; ++ ++ dw_mci_request_end(host, mrq); + goto unlock; + + case STATE_DATA_ERROR: +@@ -1043,12 +1420,15 @@ static void dw_mci_pull_final_bytes(struct dw_mci *host, void *buf, int cnt) + + static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) + { ++ struct mmc_data *data = host->data; ++ int init_cnt = cnt; ++ + /* try and push anything in the part_buf */ + if (unlikely(host->part_buf_count)) { + int len = dw_mci_push_part_bytes(host, buf, cnt); + buf += len; + cnt -= len; +- if (!sg_next(host->sg) || host->part_buf_count == 2) { ++ if (host->part_buf_count == 2) { + mci_writew(host, DATA(host->data_offset), + host->part_buf16); + host->part_buf_count = 0; +@@ -1081,9 +1461,11 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) + /* put anything remaining in the part_buf */ + if (cnt) { + dw_mci_set_part_bytes(host, buf, cnt); +- if (!sg_next(host->sg)) ++ /* Push data if we have reached the expected data length */ ++ if ((data->bytes_xfered + init_cnt) == ++ (data->blksz * data->blocks)) + mci_writew(host, DATA(host->data_offset), +- host->part_buf16); ++ host->part_buf16); + } + } + +@@ -1121,12 +1503,15 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt) + + static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) + { ++ struct mmc_data *data = host->data; ++ int init_cnt = cnt; ++ + /* try and push anything in the part_buf */ + if (unlikely(host->part_buf_count)) { + int len = dw_mci_push_part_bytes(host, buf, cnt); + buf += len; + cnt -= len; +- if (!sg_next(host->sg) || host->part_buf_count == 4) { ++ if (host->part_buf_count == 4) { + mci_writel(host, DATA(host->data_offset), + host->part_buf32); + host->part_buf_count = 0; +@@ -1159,9 +1544,11 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) + /* put anything remaining in the part_buf */ + if (cnt) { + dw_mci_set_part_bytes(host, buf, cnt); +- if (!sg_next(host->sg)) ++ /* Push data if we have reached the expected data length */ ++ if ((data->bytes_xfered + init_cnt) == ++ (data->blksz * data->blocks)) + mci_writel(host, DATA(host->data_offset), +- host->part_buf32); ++ host->part_buf32); + } + } + +@@ -1199,13 +1586,17 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt) + + static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) + { ++ struct mmc_data *data = host->data; ++ int init_cnt = cnt; ++ + /* try and push anything in the part_buf */ + if (unlikely(host->part_buf_count)) { + int len = dw_mci_push_part_bytes(host, buf, cnt); + buf += len; + cnt -= len; +- if (!sg_next(host->sg) || host->part_buf_count == 8) { +- mci_writew(host, DATA(host->data_offset), ++ ++ if (host->part_buf_count == 8) { ++ mci_writeq(host, DATA(host->data_offset), + host->part_buf); + host->part_buf_count = 0; + } +@@ -1237,9 +1628,11 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) + /* put anything remaining in the part_buf */ + if (cnt) { + dw_mci_set_part_bytes(host, buf, cnt); +- if (!sg_next(host->sg)) ++ /* Push data if we have reached the expected data length */ ++ if ((data->bytes_xfered + init_cnt) == ++ (data->blksz * data->blocks)) + mci_writeq(host, DATA(host->data_offset), +- host->part_buf); ++ host->part_buf); + } + } + +@@ -1290,7 +1683,7 @@ static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt) + host->pull_data(host, buf, cnt); + } + +-static void dw_mci_read_data_pio(struct dw_mci *host) ++static void dw_mci_read_data_pio(struct dw_mci *host, bool dto) + { + struct sg_mapping_iter *sg_miter = &host->sg_miter; + void *buf; +@@ -1298,14 +1691,14 @@ static void dw_mci_read_data_pio(struct dw_mci *host) + struct mmc_data *data = host->data; + int shift = host->data_shift; + u32 status; +- unsigned int nbytes = 0, len; ++ unsigned int len; + unsigned int remain, fcnt; + + do { + if (!sg_miter_next(sg_miter)) + goto done; + +- host->sg = sg_miter->__sg; ++ host->sg = sg_miter->piter.sg; + buf = sg_miter->addr; + remain = sg_miter->length; + offset = 0; +@@ -1317,28 +1710,17 @@ static void dw_mci_read_data_pio(struct dw_mci *host) + if (!len) + break; + dw_mci_pull_data(host, (void *)(buf + offset), len); ++ data->bytes_xfered += len; + offset += len; +- nbytes += len; + remain -= len; + } while (remain); +- sg_miter->consumed = offset; + ++ sg_miter->consumed = offset; + status = mci_readl(host, MINTSTS); + mci_writel(host, RINTSTS, SDMMC_INT_RXDR); +- if (status & DW_MCI_DATA_ERROR_FLAGS) { +- host->data_status = status; +- data->bytes_xfered += nbytes; +- sg_miter_stop(sg_miter); +- host->sg = NULL; +- smp_wmb(); +- +- set_bit(EVENT_DATA_ERROR, &host->pending_events); +- +- tasklet_schedule(&host->tasklet); +- return; +- } +- } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ +- data->bytes_xfered += nbytes; ++ /* if the RXDR is ready read again */ ++ } while ((status & SDMMC_INT_RXDR) || ++ (dto && SDMMC_GET_FCNT(mci_readl(host, STATUS)))); + + if (!remain) { + if (!sg_miter_next(sg_miter)) +@@ -1349,7 +1731,6 @@ static void dw_mci_read_data_pio(struct dw_mci *host) + return; + + done: +- data->bytes_xfered += nbytes; + sg_miter_stop(sg_miter); + host->sg = NULL; + smp_wmb(); +@@ -1364,7 +1745,7 @@ static void dw_mci_write_data_pio(struct dw_mci *host) + struct mmc_data *data = host->data; + int shift = host->data_shift; + u32 status; +- unsigned int nbytes = 0, len; ++ unsigned int len; + unsigned int fifo_depth = host->fifo_depth; + unsigned int remain, fcnt; + +@@ -1372,7 +1753,7 @@ static void dw_mci_write_data_pio(struct dw_mci *host) + if (!sg_miter_next(sg_miter)) + goto done; + +- host->sg = sg_miter->__sg; ++ host->sg = sg_miter->piter.sg; + buf = sg_miter->addr; + remain = sg_miter->length; + offset = 0; +@@ -1385,29 +1766,15 @@ static void dw_mci_write_data_pio(struct dw_mci *host) + if (!len) + break; + host->push_data(host, (void *)(buf + offset), len); ++ data->bytes_xfered += len; + offset += len; +- nbytes += len; + remain -= len; + } while (remain); +- sg_miter->consumed = offset; + ++ sg_miter->consumed = offset; + status = mci_readl(host, MINTSTS); + mci_writel(host, RINTSTS, SDMMC_INT_TXDR); +- if (status & DW_MCI_DATA_ERROR_FLAGS) { +- host->data_status = status; +- data->bytes_xfered += nbytes; +- sg_miter_stop(sg_miter); +- host->sg = NULL; +- +- smp_wmb(); +- +- set_bit(EVENT_DATA_ERROR, &host->pending_events); +- +- tasklet_schedule(&host->tasklet); +- return; +- } + } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ +- data->bytes_xfered += nbytes; + + if (!remain) { + if (!sg_miter_next(sg_miter)) +@@ -1418,7 +1785,6 @@ static void dw_mci_write_data_pio(struct dw_mci *host) + return; + + done: +- data->bytes_xfered += nbytes; + sg_miter_stop(sg_miter); + host->sg = NULL; + smp_wmb(); +@@ -1439,30 +1805,25 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status) + static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) + { + struct dw_mci *host = dev_id; +- u32 status, pending; +- unsigned int pass_count = 0; ++ u32 pending; + int i; + +- do { +- status = mci_readl(host, RINTSTS); +- pending = mci_readl(host, MINTSTS); /* read-only mask reg */ +- +- /* +- * DTO fix - version 2.10a and below, and only if internal DMA +- * is configured. +- */ +- if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) { +- if (!pending && +- ((mci_readl(host, STATUS) >> 17) & 0x1fff)) +- pending |= SDMMC_INT_DATA_OVER; +- } ++ pending = mci_readl(host, MINTSTS); /* read-only mask reg */ + +- if (!pending) +- break; ++ /* ++ * DTO fix - version 2.10a and below, and only if internal DMA ++ * is configured. ++ */ ++ if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) { ++ if (!pending && ++ ((mci_readl(host, STATUS) >> 17) & 0x1fff)) ++ pending |= SDMMC_INT_DATA_OVER; ++ } + ++ if (pending) { + if (pending & DW_MCI_CMD_ERROR_FLAGS) { + mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); +- host->cmd_status = status; ++ host->cmd_status = pending; + smp_wmb(); + set_bit(EVENT_CMD_COMPLETE, &host->pending_events); + } +@@ -1470,22 +1831,20 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) + if (pending & DW_MCI_DATA_ERROR_FLAGS) { + /* if there is an error report DATA_ERROR */ + mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); +- host->data_status = status; ++ host->data_status = pending; + smp_wmb(); + set_bit(EVENT_DATA_ERROR, &host->pending_events); +- if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC | +- SDMMC_INT_SBE | SDMMC_INT_EBE))) +- tasklet_schedule(&host->tasklet); ++ tasklet_schedule(&host->tasklet); + } + + if (pending & SDMMC_INT_DATA_OVER) { + mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER); + if (!host->data_status) +- host->data_status = status; ++ host->data_status = pending; + smp_wmb(); + if (host->dir_status == DW_MCI_RECV_STATUS) { + if (host->sg != NULL) +- dw_mci_read_data_pio(host); ++ dw_mci_read_data_pio(host, true); + } + set_bit(EVENT_DATA_COMPLETE, &host->pending_events); + tasklet_schedule(&host->tasklet); +@@ -1494,7 +1853,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) + if (pending & SDMMC_INT_RXDR) { + mci_writel(host, RINTSTS, SDMMC_INT_RXDR); + if (host->dir_status == DW_MCI_RECV_STATUS && host->sg) +- dw_mci_read_data_pio(host); ++ dw_mci_read_data_pio(host, false); + } + + if (pending & SDMMC_INT_TXDR) { +@@ -1505,12 +1864,12 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) + + if (pending & SDMMC_INT_CMD_DONE) { + mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); +- dw_mci_cmd_interrupt(host, status); ++ dw_mci_cmd_interrupt(host, pending); + } + + if (pending & SDMMC_INT_CD) { + mci_writel(host, RINTSTS, SDMMC_INT_CD); +- queue_work(dw_mci_card_workqueue, &host->card_work); ++ queue_work(host->card_workqueue, &host->card_work); + } + + /* Handle SDIO Interrupts */ +@@ -1522,7 +1881,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) + } + } + +- } while (pass_count++ < 5); ++ } + + #ifdef CONFIG_MMC_DW_IDMAC + /* Handle DMA interrupts */ +@@ -1530,7 +1889,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) + if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) { + mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI); + mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI); +- set_bit(EVENT_DATA_COMPLETE, &host->pending_events); + host->dma_ops->complete(host); + } + #endif +@@ -1548,26 +1906,17 @@ static void dw_mci_work_routine_card(struct work_struct *work) + struct mmc_host *mmc = slot->mmc; + struct mmc_request *mrq; + int present; +- u32 ctrl; + + present = dw_mci_get_cd(mmc); + while (present != slot->last_detect_state) { + dev_dbg(&slot->mmc->class_dev, "card %s\n", + present ? "inserted" : "removed"); + +- /* Power up slot (before spin_lock, may sleep) */ +- if (present != 0 && host->pdata->setpower) +- host->pdata->setpower(slot->id, mmc->ocr_avail); +- + spin_lock_bh(&host->lock); + + /* Card change detected */ + slot->last_detect_state = present; + +- /* Mark card as present if applicable */ +- if (present != 0) +- set_bit(DW_MMC_CARD_PRESENT, &slot->flags); +- + /* Clean up queue if present */ + mrq = slot->mrq; + if (mrq) { +@@ -1591,11 +1940,10 @@ static void dw_mci_work_routine_card(struct work_struct *work) + case STATE_DATA_ERROR: + if (mrq->data->error == -EINPROGRESS) + mrq->data->error = -ENOMEDIUM; +- if (!mrq->stop) +- break; + /* fall through */ + case STATE_SENDING_STOP: +- mrq->stop->error = -ENOMEDIUM; ++ if (mrq->stop) ++ mrq->stop->error = -ENOMEDIUM; + break; + } + +@@ -1616,34 +1964,16 @@ static void dw_mci_work_routine_card(struct work_struct *work) + + /* Power down slot */ + if (present == 0) { +- clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); +- +- /* +- * Clear down the FIFO - doing so generates a +- * block interrupt, hence setting the +- * scatter-gather pointer to NULL. +- */ +- sg_miter_stop(&host->sg_miter); +- host->sg = NULL; +- +- ctrl = mci_readl(host, CTRL); +- ctrl |= SDMMC_CTRL_FIFO_RESET; +- mci_writel(host, CTRL, ctrl); +- ++ /* Clear down the FIFO */ ++ dw_mci_fifo_reset(host); + #ifdef CONFIG_MMC_DW_IDMAC +- ctrl = mci_readl(host, BMOD); +- ctrl |= 0x01; /* Software reset of DMA */ +- mci_writel(host, BMOD, ctrl); ++ dw_mci_idmac_reset(host); + #endif + + } + + spin_unlock_bh(&host->lock); + +- /* Power down slot (after spin_unlock, may sleep) */ +- if (present == 0 && host->pdata->setpower) +- host->pdata->setpower(slot->id, 0); +- + present = dw_mci_get_cd(mmc); + } + +@@ -1652,12 +1982,70 @@ static void dw_mci_work_routine_card(struct work_struct *work) + } + } + +-static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) ++#ifdef CONFIG_OF ++/* given a slot id, find out the device node representing that slot */ ++static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) ++{ ++ struct device_node *np; ++ const __be32 *addr; ++ int len; ++ ++ if (!dev || !dev->of_node) ++ return NULL; ++ ++ for_each_child_of_node(dev->of_node, np) { ++ addr = of_get_property(np, "reg", &len); ++ if (!addr || (len < sizeof(int))) ++ continue; ++ if (be32_to_cpup(addr) == slot) ++ return np; ++ } ++ return NULL; ++} ++ ++static struct dw_mci_of_slot_quirks { ++ char *quirk; ++ int id; ++} of_slot_quirks[] = { ++ { ++ .quirk = "disable-wp", ++ .id = DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT, ++ }, ++}; ++ ++static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) ++{ ++ struct device_node *np = dw_mci_of_find_slot_node(dev, slot); ++ int quirks = 0; ++ int idx; ++ ++ /* get quirks */ ++ for (idx = 0; idx < ARRAY_SIZE(of_slot_quirks); idx++) ++ if (of_get_property(np, of_slot_quirks[idx].quirk, NULL)) ++ quirks |= of_slot_quirks[idx].id; ++ ++ return quirks; ++} ++#else /* CONFIG_OF */ ++static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) ++{ ++ return 0; ++} ++static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) ++{ ++ return NULL; ++} ++#endif /* CONFIG_OF */ ++ ++static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) + { + struct mmc_host *mmc; + struct dw_mci_slot *slot; ++ const struct dw_mci_drv_data *drv_data = host->drv_data; ++ int ctrl_id, ret; ++ u32 freq[2]; + +- mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), &host->pdev->dev); ++ mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); + if (!mmc) + return -ENOMEM; + +@@ -1665,42 +2053,43 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) + slot->id = id; + slot->mmc = mmc; + slot->host = host; ++ host->slot[id] = slot; + +- mmc->ops = &dw_mci_ops; +- mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510); +- mmc->f_max = host->bus_hz; ++ slot->quirks = dw_mci_of_get_slot_quirks(host->dev, slot->id); + +- if (host->pdata->get_ocr) +- mmc->ocr_avail = host->pdata->get_ocr(id); +- else +- mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; ++ mmc->ops = &dw_mci_ops; ++ if (of_property_read_u32_array(host->dev->of_node, ++ "clock-freq-min-max", freq, 2)) { ++ mmc->f_min = DW_MCI_FREQ_MIN; ++ mmc->f_max = DW_MCI_FREQ_MAX; ++ } else { ++ mmc->f_min = freq[0]; ++ mmc->f_max = freq[1]; ++ } + +- /* +- * Start with slot power disabled, it will be enabled when a card +- * is detected. +- */ +- if (host->pdata->setpower) +- host->pdata->setpower(id, 0); ++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + + if (host->pdata->caps) + mmc->caps = host->pdata->caps; +- else +- mmc->caps = 0; + +- if (host->pdata->get_bus_wd) +- if (host->pdata->get_bus_wd(slot->id) >= 4) +- mmc->caps |= MMC_CAP_4_BIT_DATA; ++ if (host->pdata->pm_caps) ++ mmc->pm_caps = host->pdata->pm_caps; ++ ++ if (host->dev->of_node) { ++ ctrl_id = of_alias_get_id(host->dev->of_node, "mshc"); ++ if (ctrl_id < 0) ++ ctrl_id = 0; ++ } else { ++ ctrl_id = to_platform_device(host->dev)->id; ++ } ++ if (drv_data && drv_data->caps) ++ mmc->caps |= drv_data->caps[ctrl_id]; ++ ++ if (host->pdata->caps2) ++ mmc->caps2 = host->pdata->caps2; + +- if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED) +- mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; ++ mmc_of_parse(mmc); + +-#ifdef CONFIG_MMC_DW_IDMAC +- mmc->max_segs = host->ring_size; +- mmc->max_blk_size = 65536; +- mmc->max_blk_count = host->ring_size; +- mmc->max_seg_size = 0x1000; +- mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count; +-#else + if (host->pdata->blk_settings) { + mmc->max_segs = host->pdata->blk_settings->max_segs; + mmc->max_blk_size = host->pdata->blk_settings->max_blk_size; +@@ -1709,28 +2098,29 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) + mmc->max_seg_size = host->pdata->blk_settings->max_seg_size; + } else { + /* Useful defaults if platform data is unset. */ ++#ifdef CONFIG_MMC_DW_IDMAC ++ mmc->max_segs = host->ring_size; ++ mmc->max_blk_size = 65536; ++ mmc->max_blk_count = host->ring_size; ++ mmc->max_seg_size = 0x1000; ++ mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count; ++#else + mmc->max_segs = 64; + mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */ + mmc->max_blk_count = 512; + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + mmc->max_seg_size = mmc->max_req_size; +- } + #endif /* CONFIG_MMC_DW_IDMAC */ +- +- host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); +- if (IS_ERR(host->vmmc)) { +- pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); +- host->vmmc = NULL; +- } else +- regulator_enable(host->vmmc); ++ } + + if (dw_mci_get_cd(mmc)) + set_bit(DW_MMC_CARD_PRESENT, &slot->flags); + else + clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); + +- host->slot[id] = slot; +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto err_setup_bus; + + #if defined(CONFIG_DEBUG_FS) + dw_mci_init_debugfs(slot); +@@ -1739,21 +2129,15 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) + /* Card initially undetected */ + slot->last_detect_state = 0; + +- /* +- * Card may have been plugged in prior to boot so we +- * need to run the detect tasklet +- */ +- queue_work(dw_mci_card_workqueue, &host->card_work); +- + return 0; ++ ++err_setup_bus: ++ mmc_free_host(mmc); ++ return -EINVAL; + } + + static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) + { +- /* Shutdown detect IRQ */ +- if (slot->host->pdata->exit) +- slot->host->pdata->exit(id); +- + /* Debugfs stuff is cleaned up by mmc core */ + mmc_remove_host(slot->mmc); + slot->host->slot[id] = NULL; +@@ -1763,10 +2147,10 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) + static void dw_mci_init_dma(struct dw_mci *host) + { + /* Alloc memory for sg translation */ +- host->sg_cpu = dma_alloc_coherent(&host->pdev->dev, PAGE_SIZE, ++ host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE, + &host->sg_dma, GFP_KERNEL); + if (!host->sg_cpu) { +- dev_err(&host->pdev->dev, "%s: could not alloc DMA memory\n", ++ dev_err(host->dev, "%s: could not alloc DMA memory\n", + __func__); + goto no_dma; + } +@@ -1774,20 +2158,21 @@ static void dw_mci_init_dma(struct dw_mci *host) + /* Determine which DMA interface to use */ + #ifdef CONFIG_MMC_DW_IDMAC + host->dma_ops = &dw_mci_idmac_ops; +- dev_info(&host->pdev->dev, "Using internal DMA controller.\n"); ++ dev_info(host->dev, "Using internal DMA controller.\n"); + #endif + + if (!host->dma_ops) + goto no_dma; + +- if (host->dma_ops->init) { ++ if (host->dma_ops->init && host->dma_ops->start && ++ host->dma_ops->stop && host->dma_ops->cleanup) { + if (host->dma_ops->init(host)) { +- dev_err(&host->pdev->dev, "%s: Unable to initialize " ++ dev_err(host->dev, "%s: Unable to initialize " + "DMA Controller.\n", __func__); + goto no_dma; + } + } else { +- dev_err(&host->pdev->dev, "DMA initialization not found.\n"); ++ dev_err(host->dev, "DMA initialization not found.\n"); + goto no_dma; + } + +@@ -1795,88 +2180,223 @@ static void dw_mci_init_dma(struct dw_mci *host) + return; + + no_dma: +- dev_info(&host->pdev->dev, "Using PIO mode.\n"); ++ dev_info(host->dev, "Using PIO mode.\n"); + host->use_dma = 0; + return; + } + +-static bool mci_wait_reset(struct device *dev, struct dw_mci *host) ++static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset) + { + unsigned long timeout = jiffies + msecs_to_jiffies(500); +- unsigned int ctrl; ++ u32 ctrl; + +- mci_writel(host, CTRL, (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | +- SDMMC_CTRL_DMA_RESET)); ++ ctrl = mci_readl(host, CTRL); ++ ctrl |= reset; ++ mci_writel(host, CTRL, ctrl); + + /* wait till resets clear */ + do { + ctrl = mci_readl(host, CTRL); +- if (!(ctrl & (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | +- SDMMC_CTRL_DMA_RESET))) ++ if (!(ctrl & reset)) + return true; + } while (time_before(jiffies, timeout)); + +- dev_err(dev, "Timeout resetting block (ctrl %#x)\n", ctrl); ++ dev_err(host->dev, ++ "Timeout resetting block (ctrl reset %#x)\n", ++ ctrl & reset); + + return false; + } + +-static int dw_mci_probe(struct platform_device *pdev) ++static inline bool dw_mci_fifo_reset(struct dw_mci *host) ++{ ++ /* ++ * Reseting generates a block interrupt, hence setting ++ * the scatter-gather pointer to NULL. ++ */ ++ if (host->sg) { ++ sg_miter_stop(&host->sg_miter); ++ host->sg = NULL; ++ } ++ ++ return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET); ++} ++ ++static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host) ++{ ++ return dw_mci_ctrl_reset(host, ++ SDMMC_CTRL_FIFO_RESET | ++ SDMMC_CTRL_RESET | ++ SDMMC_CTRL_DMA_RESET); ++} ++ ++#ifdef CONFIG_OF ++static struct dw_mci_of_quirks { ++ char *quirk; ++ int id; ++} of_quirks[] = { ++ { ++ .quirk = "broken-cd", ++ .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, ++ }, ++}; ++ ++static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) + { +- struct dw_mci *host; +- struct resource *regs; + struct dw_mci_board *pdata; +- int irq, ret, i, width; +- u32 fifo_size; ++ struct device *dev = host->dev; ++ struct device_node *np = dev->of_node; ++ const struct dw_mci_drv_data *drv_data = host->drv_data; ++ int idx, ret; ++ u32 clock_frequency; ++ ++ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) { ++ dev_err(dev, "could not allocate memory for pdata\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ /* find out number of slots supported */ ++ if (of_property_read_u32(dev->of_node, "num-slots", ++ &pdata->num_slots)) { ++ dev_info(dev, "num-slots property not found, " ++ "assuming 1 slot is available\n"); ++ pdata->num_slots = 1; ++ } + +- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!regs) +- return -ENXIO; ++ /* get quirks */ ++ for (idx = 0; idx < ARRAY_SIZE(of_quirks); idx++) ++ if (of_get_property(np, of_quirks[idx].quirk, NULL)) ++ pdata->quirks |= of_quirks[idx].id; + +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) +- return irq; ++ if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth)) ++ dev_info(dev, "fifo-depth property not found, using " ++ "value of FIFOTH register as default\n"); + +- host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL); +- if (!host) +- return -ENOMEM; ++ of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); + +- host->pdev = pdev; +- host->pdata = pdata = pdev->dev.platform_data; +- if (!pdata || !pdata->init) { +- dev_err(&pdev->dev, +- "Platform data must supply init function\n"); +- ret = -ENODEV; +- goto err_freehost; ++ if (!of_property_read_u32(np, "clock-frequency", &clock_frequency)) ++ pdata->bus_hz = clock_frequency; ++ ++ if (drv_data && drv_data->parse_dt) { ++ ret = drv_data->parse_dt(host); ++ if (ret) ++ return ERR_PTR(ret); + } + +- if (!pdata->select_slot && pdata->num_slots > 1) { +- dev_err(&pdev->dev, +- "Platform data must supply select_slot function\n"); +- ret = -ENODEV; +- goto err_freehost; ++ if (of_find_property(np, "supports-highspeed", NULL)) ++ pdata->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; ++ ++ return pdata; ++} ++ ++#else /* CONFIG_OF */ ++static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) ++{ ++ return ERR_PTR(-EINVAL); ++} ++#endif /* CONFIG_OF */ ++ ++int dw_mci_probe(struct dw_mci *host) ++{ ++ const struct dw_mci_drv_data *drv_data = host->drv_data; ++ int width, i, ret = 0; ++ u32 fifo_size; ++ int init_slots = 0; ++ ++ if (!host->pdata) { ++ host->pdata = dw_mci_parse_dt(host); ++ if (IS_ERR(host->pdata)) { ++ dev_err(host->dev, "platform data not available\n"); ++ return -EINVAL; ++ } ++ } ++ ++ if (host->pdata->num_slots > 1) { ++ dev_err(host->dev, ++ "Platform data must supply num_slots.\n"); ++ return -ENODEV; ++ } ++ ++ host->biu_clk = devm_clk_get(host->dev, "biu"); ++ if (IS_ERR(host->biu_clk)) { ++ dev_dbg(host->dev, "biu clock not available\n"); ++ } else { ++ ret = clk_prepare_enable(host->biu_clk); ++ if (ret) { ++ dev_err(host->dev, "failed to enable biu clock\n"); ++ return ret; ++ } ++ } ++ ++ host->ciu_clk = devm_clk_get(host->dev, "ciu"); ++ if (IS_ERR(host->ciu_clk)) { ++ dev_dbg(host->dev, "ciu clock not available\n"); ++ host->bus_hz = host->pdata->bus_hz; ++ } else { ++ ret = clk_prepare_enable(host->ciu_clk); ++ if (ret) { ++ dev_err(host->dev, "failed to enable ciu clock\n"); ++ goto err_clk_biu; ++ } ++ ++ if (host->pdata->bus_hz) { ++ ret = clk_set_rate(host->ciu_clk, host->pdata->bus_hz); ++ if (ret) ++ dev_warn(host->dev, ++ "Unable to set bus rate to %uHz\n", ++ host->pdata->bus_hz); ++ } ++ host->bus_hz = clk_get_rate(host->ciu_clk); + } + +- if (!pdata->bus_hz) { +- dev_err(&pdev->dev, ++ if (!host->bus_hz) { ++ dev_err(host->dev, + "Platform data must supply bus speed\n"); + ret = -ENODEV; +- goto err_freehost; ++ goto err_clk_ciu; + } + +- host->bus_hz = pdata->bus_hz; +- host->quirks = pdata->quirks; ++ if (drv_data && drv_data->init) { ++ ret = drv_data->init(host); ++ if (ret) { ++ dev_err(host->dev, ++ "implementation specific init failed\n"); ++ goto err_clk_ciu; ++ } ++ } + +- spin_lock_init(&host->lock); +- INIT_LIST_HEAD(&host->queue); ++ if (drv_data && drv_data->setup_clock) { ++ ret = drv_data->setup_clock(host); ++ if (ret) { ++ dev_err(host->dev, ++ "implementation specific clock setup failed\n"); ++ goto err_clk_ciu; ++ } ++ } + +- ret = -ENOMEM; +- host->regs = ioremap(regs->start, resource_size(regs)); +- if (!host->regs) +- goto err_freehost; ++ host->vmmc = devm_regulator_get_optional(host->dev, "vmmc"); ++ if (IS_ERR(host->vmmc)) { ++ ret = PTR_ERR(host->vmmc); ++ if (ret == -EPROBE_DEFER) ++ goto err_clk_ciu; + +- host->dma_ops = pdata->dma_ops; +- dw_mci_init_dma(host); ++ dev_info(host->dev, "no vmmc regulator found: %d\n", ret); ++ host->vmmc = NULL; ++ } else { ++ ret = regulator_enable(host->vmmc); ++ if (ret) { ++ if (ret != -EPROBE_DEFER) ++ dev_err(host->dev, ++ "regulator_enable fail: %d\n", ret); ++ goto err_clk_ciu; ++ } ++ } ++ ++ host->quirks = host->pdata->quirks; ++ ++ spin_lock_init(&host->lock); ++ INIT_LIST_HEAD(&host->queue); + + /* + * Get the host data width - this assumes that HCON has been set with +@@ -1905,10 +2425,11 @@ static int dw_mci_probe(struct platform_device *pdev) + } + + /* Reset all blocks */ +- if (!mci_wait_reset(&pdev->dev, host)) { +- ret = -ENODEV; +- goto err_dmaunmap; +- } ++ if (!dw_mci_ctrl_all_reset(host)) ++ return -ENODEV; ++ ++ host->dma_ops = host->pdata->dma_ops; ++ dw_mci_init_dma(host); + + /* Clear the interrupts for the host controller */ + mci_writel(host, RINTSTS, 0xFFFFFFFF); +@@ -1929,58 +2450,49 @@ static int dw_mci_probe(struct platform_device *pdev) + * should put it in the platform data. + */ + fifo_size = mci_readl(host, FIFOTH); +- fifo_size = 1 + ((fifo_size >> 16) & 0x7ff); ++ fifo_size = 1 + ((fifo_size >> 16) & 0xfff); + } else { + fifo_size = host->pdata->fifo_depth; + } + host->fifo_depth = fifo_size; +- host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) | +- ((fifo_size/2) << 0)); ++ host->fifoth_val = ++ SDMMC_SET_FIFOTH(0x2, fifo_size / 2 - 1, fifo_size / 2); + mci_writel(host, FIFOTH, host->fifoth_val); + + /* disable clock to CIU */ + mci_writel(host, CLKENA, 0); + mci_writel(host, CLKSRC, 0); + +- tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); +- dw_mci_card_workqueue = alloc_workqueue("dw-mci-card", +- WQ_MEM_RECLAIM | WQ_NON_REENTRANT, 1); +- if (!dw_mci_card_workqueue) +- goto err_dmaunmap; +- INIT_WORK(&host->card_work, dw_mci_work_routine_card); +- +- ret = request_irq(irq, dw_mci_interrupt, 0, "dw-mci", host); +- if (ret) +- goto err_workqueue; +- +- platform_set_drvdata(pdev, host); +- +- if (host->pdata->num_slots) +- host->num_slots = host->pdata->num_slots; +- else +- host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; +- +- /* We need at least one slot to succeed */ +- for (i = 0; i < host->num_slots; i++) { +- ret = dw_mci_init_slot(host, i); +- if (ret) { +- ret = -ENODEV; +- goto err_init_slot; +- } +- } +- + /* + * In 2.40a spec, Data offset is changed. + * Need to check the version-id and set data-offset for DATA register. + */ + host->verid = SDMMC_GET_VERID(mci_readl(host, VERID)); +- dev_info(&pdev->dev, "Version ID is %04x\n", host->verid); ++ dev_info(host->dev, "Version ID is %04x\n", host->verid); + + if (host->verid < DW_MMC_240A) + host->data_offset = DATA_OFFSET; + else + host->data_offset = DATA_240A_OFFSET; + ++ tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); ++ host->card_workqueue = alloc_workqueue("dw-mci-card", ++ WQ_MEM_RECLAIM, 1); ++ if (!host->card_workqueue) { ++ ret = -ENOMEM; ++ goto err_dmaunmap; ++ } ++ INIT_WORK(&host->card_work, dw_mci_work_routine_card); ++ ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, ++ host->irq_flags, "dw-mci", host); ++ if (ret) ++ goto err_workqueue; ++ ++ if (host->pdata->num_slots) ++ host->num_slots = host->pdata->num_slots; ++ else ++ host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; ++ + /* + * Enable interrupts for command done, data over, data empty, card det, + * receive ready and error such as transmit, receive timeout, crc error +@@ -1991,57 +2503,63 @@ static int dw_mci_probe(struct platform_device *pdev) + DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); + mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ + +- dev_info(&pdev->dev, "DW MMC controller at irq %d, " ++ dev_info(host->dev, "DW MMC controller at irq %d, " + "%d bit host data width, " + "%u deep fifo\n", +- irq, width, fifo_size); +- if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) +- dev_info(&pdev->dev, "Internal DMAC interrupt fix enabled.\n"); ++ host->irq, width, fifo_size); + +- return 0; ++ /* We need at least one slot to succeed */ ++ for (i = 0; i < host->num_slots; i++) { ++ ret = dw_mci_init_slot(host, i); ++ if (ret) ++ dev_dbg(host->dev, "slot %d init failed\n", i); ++ else ++ init_slots++; ++ } + +-err_init_slot: +- /* De-init any initialized slots */ +- while (i > 0) { +- if (host->slot[i]) +- dw_mci_cleanup_slot(host->slot[i], i); +- i--; ++ if (init_slots) { ++ dev_info(host->dev, "%d slots initialized\n", init_slots); ++ } else { ++ dev_dbg(host->dev, "attempted to initialize %d slots, " ++ "but failed on all\n", host->num_slots); ++ goto err_workqueue; + } +- free_irq(irq, host); ++ ++ if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) ++ dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); ++ ++ return 0; + + err_workqueue: +- destroy_workqueue(dw_mci_card_workqueue); ++ destroy_workqueue(host->card_workqueue); + + err_dmaunmap: + if (host->use_dma && host->dma_ops->exit) + host->dma_ops->exit(host); +- dma_free_coherent(&host->pdev->dev, PAGE_SIZE, +- host->sg_cpu, host->sg_dma); +- iounmap(host->regs); +- +- if (host->vmmc) { ++ if (host->vmmc) + regulator_disable(host->vmmc); +- regulator_put(host->vmmc); +- } + ++err_clk_ciu: ++ if (!IS_ERR(host->ciu_clk)) ++ clk_disable_unprepare(host->ciu_clk); ++ ++err_clk_biu: ++ if (!IS_ERR(host->biu_clk)) ++ clk_disable_unprepare(host->biu_clk); + +-err_freehost: +- kfree(host); + return ret; + } ++EXPORT_SYMBOL(dw_mci_probe); + +-static int __exit dw_mci_remove(struct platform_device *pdev) ++void dw_mci_remove(struct dw_mci *host) + { +- struct dw_mci *host = platform_get_drvdata(pdev); + int i; + + mci_writel(host, RINTSTS, 0xFFFFFFFF); + mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ + +- platform_set_drvdata(pdev, NULL); +- + for (i = 0; i < host->num_slots; i++) { +- dev_dbg(&pdev->dev, "remove slot %d\n", i); ++ dev_dbg(host->dev, "remove slot %d\n", i); + if (host->slot[i]) + dw_mci_cleanup_slot(host->slot[i], i); + } +@@ -2050,72 +2568,67 @@ static int __exit dw_mci_remove(struct platform_device *pdev) + mci_writel(host, CLKENA, 0); + mci_writel(host, CLKSRC, 0); + +- free_irq(platform_get_irq(pdev, 0), host); +- destroy_workqueue(dw_mci_card_workqueue); +- dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); ++ destroy_workqueue(host->card_workqueue); + + if (host->use_dma && host->dma_ops->exit) + host->dma_ops->exit(host); + +- if (host->vmmc) { ++ if (host->vmmc) + regulator_disable(host->vmmc); +- regulator_put(host->vmmc); +- } + +- iounmap(host->regs); ++ if (!IS_ERR(host->ciu_clk)) ++ clk_disable_unprepare(host->ciu_clk); + +- kfree(host); +- return 0; ++ if (!IS_ERR(host->biu_clk)) ++ clk_disable_unprepare(host->biu_clk); + } ++EXPORT_SYMBOL(dw_mci_remove); + +-#ifdef CONFIG_PM ++ ++ ++#ifdef CONFIG_PM_SLEEP + /* + * TODO: we should probably disable the clock to the card in the suspend path. + */ +-static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg) ++int dw_mci_suspend(struct dw_mci *host) + { +- int i, ret; +- struct dw_mci *host = platform_get_drvdata(pdev); +- +- for (i = 0; i < host->num_slots; i++) { +- struct dw_mci_slot *slot = host->slot[i]; +- if (!slot) +- continue; +- ret = mmc_suspend_host(slot->mmc); +- if (ret < 0) { +- while (--i >= 0) { +- slot = host->slot[i]; +- if (slot) +- mmc_resume_host(host->slot[i]->mmc); +- } +- return ret; +- } +- } +- + if (host->vmmc) + regulator_disable(host->vmmc); + + return 0; + } ++EXPORT_SYMBOL(dw_mci_suspend); + +-static int dw_mci_resume(struct platform_device *pdev) ++int dw_mci_resume(struct dw_mci *host) + { + int i, ret; +- struct dw_mci *host = platform_get_drvdata(pdev); +- +- if (host->vmmc) +- regulator_enable(host->vmmc); + +- if (host->dma_ops->init) +- host->dma_ops->init(host); ++ if (host->vmmc) { ++ ret = regulator_enable(host->vmmc); ++ if (ret) { ++ dev_err(host->dev, ++ "failed to enable regulator: %d\n", ret); ++ return ret; ++ } ++ } + +- if (!mci_wait_reset(&pdev->dev, host)) { ++ if (!dw_mci_ctrl_all_reset(host)) { + ret = -ENODEV; + return ret; + } + +- /* Restore the old value at FIFOTH register */ ++ if (host->use_dma && host->dma_ops->init) ++ host->dma_ops->init(host); ++ ++ /* ++ * Restore the initial value at FIFOTH register ++ * And Invalidate the prev_blksz with zero ++ */ + mci_writel(host, FIFOTH, host->fifoth_val); ++ host->prev_blksz = 0; ++ ++ /* Put in max timeout */ ++ mci_writel(host, TMOUT, 0xFFFFFFFF); + + mci_writel(host, RINTSTS, 0xFFFFFFFF); + mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | +@@ -2127,35 +2640,24 @@ static int dw_mci_resume(struct platform_device *pdev) + struct dw_mci_slot *slot = host->slot[i]; + if (!slot) + continue; +- ret = mmc_resume_host(host->slot[i]->mmc); +- if (ret < 0) +- return ret; ++ if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) { ++ dw_mci_set_ios(slot->mmc, &slot->mmc->ios); ++ dw_mci_setup_bus(slot, true); ++ } + } +- + return 0; + } +-#else +-#define dw_mci_suspend NULL +-#define dw_mci_resume NULL +-#endif /* CONFIG_PM */ +- +-static struct platform_driver dw_mci_driver = { +- .remove = __exit_p(dw_mci_remove), +- .suspend = dw_mci_suspend, +- .resume = dw_mci_resume, +- .driver = { +- .name = "dw_mmc", +- }, +-}; ++EXPORT_SYMBOL(dw_mci_resume); ++#endif /* CONFIG_PM_SLEEP */ + + static int __init dw_mci_init(void) + { +- return platform_driver_probe(&dw_mci_driver, dw_mci_probe); ++ pr_info("Synopsys Designware Multimedia Card Interface Driver\n"); ++ return 0; + } + + static void __exit dw_mci_exit(void) + { +- platform_driver_unregister(&dw_mci_driver); + } + + module_init(dw_mci_init); +diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h +index 72c071f..738fa24 100644 +--- a/drivers/mmc/host/dw_mmc.h ++++ b/drivers/mmc/host/dw_mmc.h +@@ -53,6 +53,7 @@ + #define SDMMC_IDINTEN 0x090 + #define SDMMC_DSCADDR 0x094 + #define SDMMC_BUFADDR 0x098 ++#define SDMMC_CDTHRCTL 0x100 + #define SDMMC_DATA(x) (x) + + /* +@@ -98,7 +99,7 @@ + #define SDMMC_INT_HLE BIT(12) + #define SDMMC_INT_FRUN BIT(11) + #define SDMMC_INT_HTO BIT(10) +-#define SDMMC_INT_DTO BIT(9) ++#define SDMMC_INT_DRTO BIT(9) + #define SDMMC_INT_RTO BIT(8) + #define SDMMC_INT_DCRC BIT(7) + #define SDMMC_INT_RCRC BIT(6) +@@ -111,6 +112,7 @@ + #define SDMMC_INT_ERROR 0xbfc2 + /* Command register defines */ + #define SDMMC_CMD_START BIT(31) ++#define SDMMC_CMD_USE_HOLD_REG BIT(29) + #define SDMMC_CMD_CCS_EXP BIT(23) + #define SDMMC_CMD_CEATA_RD BIT(22) + #define SDMMC_CMD_UPD_CLK BIT(21) +@@ -126,7 +128,11 @@ + #define SDMMC_CMD_RESP_EXP BIT(6) + #define SDMMC_CMD_INDX(n) ((n) & 0x1F) + /* Status register defines */ +-#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FF) ++#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF) ++/* FIFOTH register defines */ ++#define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \ ++ ((r) & 0xFFF) << 16 | \ ++ ((t) & 0xFFF)) + /* Internal DMAC interrupt defines */ + #define SDMMC_IDMAC_INT_AI BIT(9) + #define SDMMC_IDMAC_INT_NI BIT(8) +@@ -141,6 +147,8 @@ + #define SDMMC_IDMAC_SWRESET BIT(0) + /* Version ID register define */ + #define SDMMC_GET_VERID(x) ((x) & 0xFFFF) ++/* Card read threshold */ ++#define SDMMC_SET_RD_THLD(v, x) (((v) & 0x1FFF) << 16 | (x)) + + /* Register access macros */ + #define mci_readl(dev, reg) \ +@@ -175,4 +183,79 @@ + (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg) = (value)) + #endif + ++extern int dw_mci_probe(struct dw_mci *host); ++extern void dw_mci_remove(struct dw_mci *host); ++#ifdef CONFIG_PM_SLEEP ++extern int dw_mci_suspend(struct dw_mci *host); ++extern int dw_mci_resume(struct dw_mci *host); ++#endif ++ ++/** ++ * struct dw_mci_slot - MMC slot state ++ * @mmc: The mmc_host representing this slot. ++ * @host: The MMC controller this slot is using. ++ * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX) ++ * @ctype: Card type for this slot. ++ * @mrq: mmc_request currently being processed or waiting to be ++ * processed, or NULL when the slot is idle. ++ * @queue_node: List node for placing this node in the @queue list of ++ * &struct dw_mci. ++ * @clock: Clock rate configured by set_ios(). Protected by host->lock. ++ * @__clk_old: The last updated clock with reflecting clock divider. ++ * Keeping track of this helps us to avoid spamming the console ++ * with CONFIG_MMC_CLKGATE. ++ * @flags: Random state bits associated with the slot. ++ * @id: Number of this slot. ++ * @last_detect_state: Most recently observed card detect state. ++ */ ++struct dw_mci_slot { ++ struct mmc_host *mmc; ++ struct dw_mci *host; ++ ++ int quirks; ++ ++ u32 ctype; ++ ++ struct mmc_request *mrq; ++ struct list_head queue_node; ++ ++ unsigned int clock; ++ unsigned int __clk_old; ++ ++ unsigned long flags; ++#define DW_MMC_CARD_PRESENT 0 ++#define DW_MMC_CARD_NEED_INIT 1 ++ int id; ++ int last_detect_state; ++}; ++ ++struct dw_mci_tuning_data { ++ const u8 *blk_pattern; ++ unsigned int blksz; ++}; ++ ++/** ++ * dw_mci driver data - dw-mshc implementation specific driver data. ++ * @caps: mmc subsystem specified capabilities of the controller(s). ++ * @init: early implementation specific initialization. ++ * @setup_clock: implementation specific clock configuration. ++ * @prepare_command: handle CMD register extensions. ++ * @set_ios: handle bus specific extensions. ++ * @parse_dt: parse implementation specific device tree properties. ++ * @execute_tuning: implementation specific tuning procedure. ++ * ++ * Provide controller implementation specific extensions. The usage of this ++ * data structure is fully optional and usage of each member in this structure ++ * is optional as well. ++ */ ++struct dw_mci_drv_data { ++ unsigned long *caps; ++ int (*init)(struct dw_mci *host); ++ int (*setup_clock)(struct dw_mci *host); ++ void (*prepare_command)(struct dw_mci *host, u32 *cmdr); ++ void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); ++ int (*parse_dt)(struct dw_mci *host); ++ int (*execute_tuning)(struct dw_mci_slot *slot, u32 opcode, ++ struct dw_mci_tuning_data *tuning_data); ++}; + #endif /* _DW_MMC_H_ */ +diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c +index 74218ad..537d6c7 100644 +--- a/drivers/mmc/host/jz4740_mmc.c ++++ b/drivers/mmc/host/jz4740_mmc.c +@@ -14,6 +14,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -120,7 +121,6 @@ struct jz4740_mmc_host { + int irq; + int card_detect_irq; + +- struct resource *mem; + void __iomem *base; + struct mmc_request *req; + struct mmc_command *cmd; +@@ -231,6 +231,14 @@ static void jz4740_mmc_transfer_check_state(struct jz4740_mmc_host *host, + host->req->cmd->error = -EIO; + data->error = -EIO; + } ++ } else if (status & JZ_MMC_STATUS_READ_ERROR_MASK) { ++ if (status & (JZ_MMC_STATUS_TIMEOUT_READ)) { ++ host->req->cmd->error = -ETIMEDOUT; ++ data->error = -ETIMEDOUT; ++ } else { ++ host->req->cmd->error = -EIO; ++ data->error = -EIO; ++ } + } + } + +@@ -507,10 +515,13 @@ static irqreturn_t jz_mmc_irq_worker(int irq, void *devid) + + jz4740_mmc_send_command(host, req->stop); + +- timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_PRG_DONE); +- if (timeout) { +- host->state = JZ4740_MMC_STATE_DONE; +- break; ++ if (mmc_resp_type(req->stop) & MMC_RSP_BUSY) { ++ timeout = jz4740_mmc_poll_irq(host, ++ JZ_MMC_IRQ_PRG_DONE); ++ if (timeout) { ++ host->state = JZ4740_MMC_STATE_DONE; ++ break; ++ } + } + case JZ4740_MMC_STATE_DONE: + break; +@@ -560,11 +571,6 @@ static irqreturn_t jz_mmc_irq(int irq, void *devid) + if (cmd->data) + cmd->data->error = -EIO; + cmd->error = -EIO; +- } else if (status & (JZ_MMC_STATUS_CRC_READ_ERROR | +- JZ_MMC_STATUS_CRC_WRITE_ERROR)) { +- if (cmd->data) +- cmd->data->error = -EIO; +- cmd->error = -EIO; + } + + jz4740_mmc_set_irq_enabled(host, irq_reg, false); +@@ -626,7 +632,7 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + gpio_set_value(host->pdata->gpio_power, + !host->pdata->power_active_low); + host->cmdat |= JZ_MMC_CMDAT_INIT; +- clk_enable(host->clk); ++ clk_prepare_enable(host->clk); + break; + case MMC_POWER_ON: + break; +@@ -634,7 +640,7 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + if (gpio_is_valid(host->pdata->gpio_power)) + gpio_set_value(host->pdata->gpio_power, + host->pdata->power_active_low); +- clk_disable(host->clk); ++ clk_disable_unprepare(host->clk); + break; + } + +@@ -650,35 +656,6 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + } + } + +-static int jz4740_mmc_get_ro(struct mmc_host *mmc) +-{ +- struct jz4740_mmc_host *host = mmc_priv(mmc); +- if (!gpio_is_valid(host->pdata->gpio_read_only)) +- return -ENOSYS; +- +- return gpio_get_value(host->pdata->gpio_read_only) ^ +- host->pdata->read_only_active_low; +-} +- +-static int jz4740_mmc_get_cd(struct mmc_host *mmc) +-{ +- struct jz4740_mmc_host *host = mmc_priv(mmc); +- if (!gpio_is_valid(host->pdata->gpio_card_detect)) +- return -ENOSYS; +- +- return gpio_get_value(host->pdata->gpio_card_detect) ^ +- host->pdata->card_detect_active_low; +-} +- +-static irqreturn_t jz4740_mmc_card_detect_irq(int irq, void *devid) +-{ +- struct jz4740_mmc_host *host = devid; +- +- mmc_detect_change(host->mmc, HZ / 2); +- +- return IRQ_HANDLED; +-} +- + static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) + { + struct jz4740_mmc_host *host = mmc_priv(mmc); +@@ -688,8 +665,8 @@ static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) + static const struct mmc_host_ops jz4740_mmc_ops = { + .request = jz4740_mmc_request, + .set_ios = jz4740_mmc_set_ios, +- .get_ro = jz4740_mmc_get_ro, +- .get_cd = jz4740_mmc_get_cd, ++ .get_ro = mmc_gpio_get_ro, ++ .get_cd = mmc_gpio_get_cd, + .enable_sdio_irq = jz4740_mmc_enable_sdio_irq, + }; + +@@ -702,7 +679,7 @@ static const struct jz_gpio_bulk_request jz4740_mmc_pins[] = { + JZ_GPIO_BULK_PIN(MSC_DATA3), + }; + +-static int __devinit jz4740_mmc_request_gpio(struct device *dev, int gpio, ++static int jz4740_mmc_request_gpio(struct device *dev, int gpio, + const char *name, bool output, int value) + { + int ret; +@@ -724,58 +701,34 @@ static int __devinit jz4740_mmc_request_gpio(struct device *dev, int gpio, + return 0; + } + +-static int __devinit jz4740_mmc_request_gpios(struct platform_device *pdev) ++static int jz4740_mmc_request_gpios(struct mmc_host *mmc, ++ struct platform_device *pdev) + { +- int ret; + struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; ++ int ret = 0; + + if (!pdata) + return 0; + +- ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_card_detect, +- "MMC detect change", false, 0); +- if (ret) +- goto err; +- +- ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_read_only, +- "MMC read only", false, 0); +- if (ret) +- goto err_free_gpio_card_detect; +- +- ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power, +- "MMC read only", true, pdata->power_active_low); +- if (ret) +- goto err_free_gpio_read_only; +- +- return 0; +- +-err_free_gpio_read_only: +- if (gpio_is_valid(pdata->gpio_read_only)) +- gpio_free(pdata->gpio_read_only); +-err_free_gpio_card_detect: +- if (gpio_is_valid(pdata->gpio_card_detect)) +- gpio_free(pdata->gpio_card_detect); +-err: +- return ret; +-} +- +-static int __devinit jz4740_mmc_request_cd_irq(struct platform_device *pdev, +- struct jz4740_mmc_host *host) +-{ +- struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; ++ if (!pdata->card_detect_active_low) ++ mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; ++ if (!pdata->read_only_active_low) ++ mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; + +- if (!gpio_is_valid(pdata->gpio_card_detect)) +- return 0; ++ if (gpio_is_valid(pdata->gpio_card_detect)) { ++ ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect, 0); ++ if (ret) ++ return ret; ++ } + +- host->card_detect_irq = gpio_to_irq(pdata->gpio_card_detect); +- if (host->card_detect_irq < 0) { +- dev_warn(&pdev->dev, "Failed to get card detect irq\n"); +- return 0; ++ if (gpio_is_valid(pdata->gpio_read_only)) { ++ ret = mmc_gpio_request_ro(mmc, pdata->gpio_read_only); ++ if (ret) ++ return ret; + } + +- return request_irq(host->card_detect_irq, jz4740_mmc_card_detect_irq, +- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, +- "MMC card detect", host); ++ return jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power, ++ "MMC read only", true, pdata->power_active_low); + } + + static void jz4740_mmc_free_gpios(struct platform_device *pdev) +@@ -787,10 +740,6 @@ static void jz4740_mmc_free_gpios(struct platform_device *pdev) + + if (gpio_is_valid(pdata->gpio_power)) + gpio_free(pdata->gpio_power); +- if (gpio_is_valid(pdata->gpio_read_only)) +- gpio_free(pdata->gpio_read_only); +- if (gpio_is_valid(pdata->gpio_card_detect)) +- gpio_free(pdata->gpio_card_detect); + } + + static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host) +@@ -802,12 +751,13 @@ static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host) + return num_pins; + } + +-static int __devinit jz4740_mmc_probe(struct platform_device* pdev) ++static int jz4740_mmc_probe(struct platform_device* pdev) + { + int ret; + struct mmc_host *mmc; + struct jz4740_mmc_host *host; + struct jz4740_mmc_platform_data *pdata; ++ struct resource *res; + + pdata = pdev->dev.platform_data; + +@@ -827,42 +777,27 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev) + goto err_free_host; + } + +- host->clk = clk_get(&pdev->dev, "mmc"); ++ host->clk = devm_clk_get(&pdev->dev, "mmc"); + if (IS_ERR(host->clk)) { + ret = PTR_ERR(host->clk); + dev_err(&pdev->dev, "Failed to get mmc clock\n"); + goto err_free_host; + } + +- host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!host->mem) { +- ret = -ENOENT; +- dev_err(&pdev->dev, "Failed to get base platform memory\n"); +- goto err_clk_put; +- } +- +- host->mem = request_mem_region(host->mem->start, +- resource_size(host->mem), pdev->name); +- if (!host->mem) { +- ret = -EBUSY; +- dev_err(&pdev->dev, "Failed to request base memory region\n"); +- goto err_clk_put; +- } +- +- host->base = ioremap_nocache(host->mem->start, resource_size(host->mem)); +- if (!host->base) { +- ret = -EBUSY; +- dev_err(&pdev->dev, "Failed to ioremap base memory\n"); +- goto err_release_mem_region; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ host->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(host->base)) { ++ ret = PTR_ERR(host->base); ++ goto err_free_host; + } + + ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); + if (ret) { + dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret); +- goto err_iounmap; ++ goto err_free_host; + } + +- ret = jz4740_mmc_request_gpios(pdev); ++ ret = jz4740_mmc_request_gpios(mmc, pdev); + if (ret) + goto err_gpio_bulk_free; + +@@ -885,17 +820,11 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev) + spin_lock_init(&host->lock); + host->irq_mask = 0xffff; + +- ret = jz4740_mmc_request_cd_irq(pdev, host); +- if (ret) { +- dev_err(&pdev->dev, "Failed to request card detect irq\n"); +- goto err_free_gpios; +- } +- + ret = request_threaded_irq(host->irq, jz_mmc_irq, jz_mmc_irq_worker, 0, + dev_name(&pdev->dev), host); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); +- goto err_free_card_detect_irq; ++ goto err_free_gpios; + } + + jz4740_mmc_reset(host); +@@ -918,27 +847,17 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev) + + err_free_irq: + free_irq(host->irq, host); +-err_free_card_detect_irq: +- if (host->card_detect_irq >= 0) +- free_irq(host->card_detect_irq, host); + err_free_gpios: + jz4740_mmc_free_gpios(pdev); + err_gpio_bulk_free: + jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); +-err_iounmap: +- iounmap(host->base); +-err_release_mem_region: +- release_mem_region(host->mem->start, resource_size(host->mem)); +-err_clk_put: +- clk_put(host->clk); + err_free_host: +- platform_set_drvdata(pdev, NULL); + mmc_free_host(mmc); + + return ret; + } + +-static int __devexit jz4740_mmc_remove(struct platform_device *pdev) ++static int jz4740_mmc_remove(struct platform_device *pdev) + { + struct jz4740_mmc_host *host = platform_get_drvdata(pdev); + +@@ -949,31 +868,21 @@ static int __devexit jz4740_mmc_remove(struct platform_device *pdev) + mmc_remove_host(host->mmc); + + free_irq(host->irq, host); +- if (host->card_detect_irq >= 0) +- free_irq(host->card_detect_irq, host); + + jz4740_mmc_free_gpios(pdev); + jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); + +- iounmap(host->base); +- release_mem_region(host->mem->start, resource_size(host->mem)); +- +- clk_put(host->clk); +- +- platform_set_drvdata(pdev, NULL); + mmc_free_host(host->mmc); + + return 0; + } + +-#ifdef CONFIG_PM ++#ifdef CONFIG_PM_SLEEP + + static int jz4740_mmc_suspend(struct device *dev) + { + struct jz4740_mmc_host *host = dev_get_drvdata(dev); + +- mmc_suspend_host(host->mmc); +- + jz_gpio_bulk_suspend(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); + + return 0; +@@ -985,18 +894,11 @@ static int jz4740_mmc_resume(struct device *dev) + + jz_gpio_bulk_resume(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); + +- mmc_resume_host(host->mmc); +- + return 0; + } + +-const struct dev_pm_ops jz4740_mmc_pm_ops = { +- .suspend = jz4740_mmc_suspend, +- .resume = jz4740_mmc_resume, +- .poweroff = jz4740_mmc_suspend, +- .restore = jz4740_mmc_resume, +-}; +- ++static SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend, ++ jz4740_mmc_resume); + #define JZ4740_MMC_PM_OPS (&jz4740_mmc_pm_ops) + #else + #define JZ4740_MMC_PM_OPS NULL +@@ -1004,7 +906,7 @@ const struct dev_pm_ops jz4740_mmc_pm_ops = { + + static struct platform_driver jz4740_mmc_driver = { + .probe = jz4740_mmc_probe, +- .remove = __devexit_p(jz4740_mmc_remove), ++ .remove = jz4740_mmc_remove, + .driver = { + .name = "jz4740-mmc", + .owner = THIS_MODULE, +@@ -1012,17 +914,7 @@ static struct platform_driver jz4740_mmc_driver = { + }, + }; + +-static int __init jz4740_mmc_init(void) +-{ +- return platform_driver_register(&jz4740_mmc_driver); +-} +-module_init(jz4740_mmc_init); +- +-static void __exit jz4740_mmc_exit(void) +-{ +- platform_driver_unregister(&jz4740_mmc_driver); +-} +-module_exit(jz4740_mmc_exit); ++module_platform_driver(jz4740_mmc_driver); + + MODULE_DESCRIPTION("JZ4740 SD/MMC controller driver"); + MODULE_LICENSE("GPL"); +diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c +index 92946b8..cc8d4a6 100644 +--- a/drivers/mmc/host/mmc_spi.c ++++ b/drivers/mmc/host/mmc_spi.c +@@ -36,6 +36,7 @@ + + #include + #include /* for R1_SPI_* bit values */ ++#include + + #include + #include +@@ -447,7 +448,6 @@ mmc_spi_command_send(struct mmc_spi_host *host, + { + struct scratch *data = host->data; + u8 *cp = data->status; +- u32 arg = cmd->arg; + int status; + struct spi_transfer *t; + +@@ -464,14 +464,12 @@ mmc_spi_command_send(struct mmc_spi_host *host, + * We init the whole buffer to all-ones, which is what we need + * to write while we're reading (later) response data. + */ +- memset(cp++, 0xff, sizeof(data->status)); ++ memset(cp, 0xff, sizeof(data->status)); + +- *cp++ = 0x40 | cmd->opcode; +- *cp++ = (u8)(arg >> 24); +- *cp++ = (u8)(arg >> 16); +- *cp++ = (u8)(arg >> 8); +- *cp++ = (u8)arg; +- *cp++ = (crc7(0, &data->status[1], 5) << 1) | 0x01; ++ cp[1] = 0x40 | cmd->opcode; ++ put_unaligned_be32(cmd->arg, cp+2); ++ cp[6] = crc7_be(0, cp+1, 5) | 0x01; ++ cp += 7; + + /* Then, read up to 13 bytes (while writing all-ones): + * - N(CR) (== 1..8) bytes of all-ones +@@ -710,10 +708,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, + * so we have to cope with this situation and check the response + * bit-by-bit. Arggh!!! + */ +- pattern = scratch->status[0] << 24; +- pattern |= scratch->status[1] << 16; +- pattern |= scratch->status[2] << 8; +- pattern |= scratch->status[3]; ++ pattern = get_unaligned_be32(scratch->status); + + /* First 3 bit of pattern are undefined */ + pattern |= 0xE0000000; +@@ -1272,33 +1267,11 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + } + } + +-static int mmc_spi_get_ro(struct mmc_host *mmc) +-{ +- struct mmc_spi_host *host = mmc_priv(mmc); +- +- if (host->pdata && host->pdata->get_ro) +- return !!host->pdata->get_ro(mmc->parent); +- /* +- * Board doesn't support read only detection; let the mmc core +- * decide what to do. +- */ +- return -ENOSYS; +-} +- +-static int mmc_spi_get_cd(struct mmc_host *mmc) +-{ +- struct mmc_spi_host *host = mmc_priv(mmc); +- +- if (host->pdata && host->pdata->get_cd) +- return !!host->pdata->get_cd(mmc->parent); +- return -ENOSYS; +-} +- + static const struct mmc_host_ops mmc_spi_ops = { + .request = mmc_spi_request, + .set_ios = mmc_spi_set_ios, +- .get_ro = mmc_spi_get_ro, +- .get_cd = mmc_spi_get_cd, ++ .get_ro = mmc_gpio_get_ro, ++ .get_cd = mmc_gpio_get_cd, + }; + + +@@ -1324,6 +1297,7 @@ static int mmc_spi_probe(struct spi_device *spi) + struct mmc_host *mmc; + struct mmc_spi_host *host; + int status; ++ bool has_ro = false; + + /* We rely on full duplex transfers, mostly to reduce + * per-transfer overheads (by making fewer transfers). +@@ -1448,18 +1422,33 @@ static int mmc_spi_probe(struct spi_device *spi) + } + + /* pass platform capabilities, if any */ +- if (host->pdata) ++ if (host->pdata) { + mmc->caps |= host->pdata->caps; ++ mmc->caps2 |= host->pdata->caps2; ++ } + + status = mmc_add_host(mmc); + if (status != 0) + goto fail_add_host; + ++ if (host->pdata && host->pdata->flags & MMC_SPI_USE_CD_GPIO) { ++ status = mmc_gpio_request_cd(mmc, host->pdata->cd_gpio, ++ host->pdata->cd_debounce); ++ if (status != 0) ++ goto fail_add_host; ++ } ++ ++ if (host->pdata && host->pdata->flags & MMC_SPI_USE_RO_GPIO) { ++ has_ro = true; ++ status = mmc_gpio_request_ro(mmc, host->pdata->ro_gpio); ++ if (status != 0) ++ goto fail_add_host; ++ } ++ + dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n", + dev_name(&mmc->class_dev), + host->dma_dev ? "" : ", no DMA", +- (host->pdata && host->pdata->get_ro) +- ? "" : ", no WP", ++ has_ro ? "" : ", no WP", + (host->pdata && host->pdata->setpower) + ? "" : ", no poweroff", + (mmc->caps & MMC_CAP_NEEDS_POLL) +@@ -1485,7 +1474,7 @@ nomem: + } + + +-static int __devexit mmc_spi_remove(struct spi_device *spi) ++static int mmc_spi_remove(struct spi_device *spi) + { + struct mmc_host *mmc = dev_get_drvdata(&spi->dev); + struct mmc_spi_host *host; +@@ -1517,7 +1506,7 @@ static int __devexit mmc_spi_remove(struct spi_device *spi) + return 0; + } + +-static struct of_device_id mmc_spi_of_match_table[] __devinitdata = { ++static struct of_device_id mmc_spi_of_match_table[] = { + { .compatible = "mmc-spi-slot", }, + {}, + }; +@@ -1525,28 +1514,14 @@ static struct of_device_id mmc_spi_of_match_table[] __devinitdata = { + static struct spi_driver mmc_spi_driver = { + .driver = { + .name = "mmc_spi", +- .bus = &spi_bus_type, + .owner = THIS_MODULE, + .of_match_table = mmc_spi_of_match_table, + }, + .probe = mmc_spi_probe, +- .remove = __devexit_p(mmc_spi_remove), ++ .remove = mmc_spi_remove, + }; + +- +-static int __init mmc_spi_init(void) +-{ +- return spi_register_driver(&mmc_spi_driver); +-} +-module_init(mmc_spi_init); +- +- +-static void __exit mmc_spi_exit(void) +-{ +- spi_unregister_driver(&mmc_spi_driver); +-} +-module_exit(mmc_spi_exit); +- ++module_spi_driver(mmc_spi_driver); + + MODULE_AUTHOR("Mike Lavender, David Brownell, " + "Hans-Peter Nilsson, Jan Nikitenko"); +diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c +index 0726e59..4964894 100644 +--- a/drivers/mmc/host/mmci.c ++++ b/drivers/mmc/host/mmci.c +@@ -13,23 +13,30 @@ + #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 +@@ -53,6 +60,11 @@ static unsigned int fmax = 515633; + * @sdio: variant supports SDIO + * @st_clkdiv: true if using a ST-specific clock divider algorithm + * @blksz_datactrl16: true if Block size is at b16..b30 position in datactrl register ++ * @pwrreg_powerup: power up value for MMCIPOWER register ++ * @signal_direction: input/out direction of bus signals can be indicated ++ * @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock ++ * @busy_detect: true if busy detection on dat0 is supported ++ * @pwrreg_nopower: bits in MMCIPOWER don't controls ext. power supply + */ + struct variant_data { + unsigned int clkreg; +@@ -63,18 +75,33 @@ struct variant_data { + bool sdio; + bool st_clkdiv; + bool blksz_datactrl16; ++ u32 pwrreg_powerup; ++ bool signal_direction; ++ bool pwrreg_clkgate; ++ bool busy_detect; ++ bool pwrreg_nopower; + }; + + static struct variant_data variant_arm = { + .fifosize = 16 * 4, + .fifohalfsize = 8 * 4, + .datalength_bits = 16, ++ .pwrreg_powerup = MCI_PWR_UP, + }; + + static struct variant_data variant_arm_extended_fifo = { + .fifosize = 128 * 4, + .fifohalfsize = 64 * 4, + .datalength_bits = 16, ++ .pwrreg_powerup = MCI_PWR_UP, ++}; ++ ++static struct variant_data variant_arm_extended_fifo_hwfc = { ++ .fifosize = 128 * 4, ++ .fifohalfsize = 64 * 4, ++ .clkreg_enable = MCI_ARM_HWFCEN, ++ .datalength_bits = 16, ++ .pwrreg_powerup = MCI_PWR_UP, + }; + + static struct variant_data variant_u300 = { +@@ -83,6 +110,23 @@ static struct variant_data variant_u300 = { + .clkreg_enable = MCI_ST_U300_HWFCEN, + .datalength_bits = 16, + .sdio = true, ++ .pwrreg_powerup = MCI_PWR_ON, ++ .signal_direction = true, ++ .pwrreg_clkgate = true, ++ .pwrreg_nopower = true, ++}; ++ ++static struct variant_data variant_nomadik = { ++ .fifosize = 16 * 4, ++ .fifohalfsize = 8 * 4, ++ .clkreg = MCI_CLK_ENABLE, ++ .datalength_bits = 24, ++ .sdio = true, ++ .st_clkdiv = true, ++ .pwrreg_powerup = MCI_PWR_ON, ++ .signal_direction = true, ++ .pwrreg_clkgate = true, ++ .pwrreg_nopower = true, + }; + + static struct variant_data variant_ux500 = { +@@ -93,6 +137,11 @@ static struct variant_data variant_ux500 = { + .datalength_bits = 24, + .sdio = true, + .st_clkdiv = true, ++ .pwrreg_powerup = MCI_PWR_ON, ++ .signal_direction = true, ++ .pwrreg_clkgate = true, ++ .busy_detect = true, ++ .pwrreg_nopower = true, + }; + + static struct variant_data variant_ux500v2 = { +@@ -104,8 +153,101 @@ static struct variant_data variant_ux500v2 = { + .sdio = true, + .st_clkdiv = true, + .blksz_datactrl16 = true, ++ .pwrreg_powerup = MCI_PWR_ON, ++ .signal_direction = true, ++ .pwrreg_clkgate = true, ++ .busy_detect = true, ++ .pwrreg_nopower = true, + }; + ++static int mmci_card_busy(struct mmc_host *mmc) ++{ ++ struct mmci_host *host = mmc_priv(mmc); ++ unsigned long flags; ++ int busy = 0; ++ ++ pm_runtime_get_sync(mmc_dev(mmc)); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ if (readl(host->base + MMCISTATUS) & MCI_ST_CARDBUSY) ++ busy = 1; ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ pm_runtime_mark_last_busy(mmc_dev(mmc)); ++ pm_runtime_put_autosuspend(mmc_dev(mmc)); ++ ++ return busy; ++} ++ ++/* ++ * Validate mmc prerequisites ++ */ ++static int mmci_validate_data(struct mmci_host *host, ++ struct mmc_data *data) ++{ ++ if (!data) ++ return 0; ++ ++ if (!is_power_of_2(data->blksz)) { ++ dev_err(mmc_dev(host->mmc), ++ "unsupported block size (%d bytes)\n", data->blksz); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static void mmci_reg_delay(struct mmci_host *host) ++{ ++ /* ++ * According to the spec, at least three feedback clock cycles ++ * of max 52 MHz must pass between two writes to the MMCICLOCK reg. ++ * Three MCLK clock cycles must pass between two MMCIPOWER reg writes. ++ * Worst delay time during card init is at 100 kHz => 30 us. ++ * Worst delay time when up and running is at 25 MHz => 120 ns. ++ */ ++ if (host->cclk < 25000000) ++ udelay(30); ++ else ++ ndelay(120); ++} ++ ++/* ++ * This must be called with host->lock held ++ */ ++static void mmci_write_clkreg(struct mmci_host *host, u32 clk) ++{ ++ if (host->clk_reg != clk) { ++ host->clk_reg = clk; ++ writel(clk, host->base + MMCICLOCK); ++ } ++} ++ ++/* ++ * This must be called with host->lock held ++ */ ++static void mmci_write_pwrreg(struct mmci_host *host, u32 pwr) ++{ ++ if (host->pwr_reg != pwr) { ++ host->pwr_reg = pwr; ++ writel(pwr, host->base + MMCIPOWER); ++ } ++} ++ ++/* ++ * This must be called with host->lock held ++ */ ++static void mmci_write_datactrlreg(struct mmci_host *host, u32 datactrl) ++{ ++ /* Keep ST Micro busy mode if enabled */ ++ datactrl |= host->datactrl_reg & MCI_ST_DPSM_BUSYMODE; ++ ++ if (host->datactrl_reg != datactrl) { ++ host->datactrl_reg = datactrl; ++ writel(datactrl, host->base + MMCIDATACTRL); ++ } ++} ++ + /* + * This must be called with host->lock held + */ +@@ -114,6 +256,9 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) + struct variant_data *variant = host->variant; + u32 clk = variant->clkreg; + ++ /* Make sure cclk reflects the current calculated clock */ ++ host->cclk = 0; ++ + if (desired) { + if (desired >= host->mclk) { + clk = MCI_CLK_BYPASS; +@@ -148,12 +293,19 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) + /* clk |= MCI_CLK_PWRSAVE; */ + } + ++ /* Set actual clock for debug */ ++ host->mmc->actual_clock = host->cclk; ++ + if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) + clk |= MCI_4BIT_BUS; + if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8) + clk |= MCI_ST_8BIT_BUS; + +- writel(clk, host->base + MMCICLOCK); ++ if (host->mmc->ios.timing == MMC_TIMING_UHS_DDR50 || ++ host->mmc->ios.timing == MMC_TIMING_MMC_DDR52) ++ clk |= MCI_ST_UX500_NEG_EDGE; ++ ++ mmci_write_clkreg(host, clk); + } + + static void +@@ -166,14 +318,10 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) + host->mrq = NULL; + host->cmd = NULL; + +- /* +- * Need to drop the host lock here; mmc_request_done may call +- * back into the driver... +- */ +- spin_unlock(&host->lock); +- pm_runtime_put(mmc_dev(host->mmc)); + mmc_request_done(host->mmc, mrq); +- spin_lock(&host->lock); ++ ++ pm_runtime_mark_last_busy(mmc_dev(host->mmc)); ++ pm_runtime_put_autosuspend(mmc_dev(host->mmc)); + } + + static void mmci_set_mask1(struct mmci_host *host, unsigned int mask) +@@ -194,7 +342,7 @@ static void mmci_set_mask1(struct mmci_host *host, unsigned int mask) + + static void mmci_stop_data(struct mmci_host *host) + { +- writel(0, host->base + MMCIDATACTRL); ++ mmci_write_datactrlreg(host, 0); + mmci_set_mask1(host, 0); + host->data = NULL; + } +@@ -217,7 +365,7 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) + * no custom DMA interfaces are supported. + */ + #ifdef CONFIG_DMA_ENGINE +-static void __devinit mmci_dma_setup(struct mmci_host *host) ++static void mmci_dma_setup(struct mmci_host *host) + { + struct mmci_platform_data *plat = host->plat; + const char *rxname, *txname; +@@ -242,8 +390,8 @@ static void __devinit mmci_dma_setup(struct mmci_host *host) + */ + if (plat->dma_rx_param) { + host->dma_rx_channel = dma_request_channel(mask, +- plat->dma_filter, +- plat->dma_rx_param); ++ plat->dma_filter, ++ plat->dma_rx_param); + /* E.g if no DMA hardware is present */ + if (!host->dma_rx_channel) + dev_err(mmc_dev(host->mmc), "no RX DMA channel\n"); +@@ -251,8 +399,8 @@ static void __devinit mmci_dma_setup(struct mmci_host *host) + + if (plat->dma_tx_param) { + host->dma_tx_channel = dma_request_channel(mask, +- plat->dma_filter, +- plat->dma_tx_param); ++ plat->dma_filter, ++ plat->dma_tx_param); + if (!host->dma_tx_channel) + dev_warn(mmc_dev(host->mmc), "no TX DMA channel\n"); + } else { +@@ -293,24 +441,45 @@ static void __devinit mmci_dma_setup(struct mmci_host *host) + } + + /* +- * This is used in __devinit or __devexit so inline it ++ * This is used in or so inline it + * so it can be discarded. + */ + static inline void mmci_dma_release(struct mmci_host *host) + { +- struct mmci_platform_data *plat = host->plat; +- + if (host->dma_rx_channel) + dma_release_channel(host->dma_rx_channel); +- if (host->dma_tx_channel && plat->dma_tx_param) ++ if (host->dma_tx_channel) + dma_release_channel(host->dma_tx_channel); + host->dma_rx_channel = host->dma_tx_channel = NULL; + } + ++static void mmci_dma_data_error(struct mmci_host *host) ++{ ++ dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n"); ++ dmaengine_terminate_all(host->dma_current); ++ host->dma_current = NULL; ++ host->dma_desc_current = NULL; ++ host->data->host_cookie = 0; ++} ++ + static void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data) + { +- struct dma_chan *chan = host->dma_current; ++ struct dma_chan *chan; + enum dma_data_direction dir; ++ ++ if (data->flags & MMC_DATA_READ) { ++ dir = DMA_FROM_DEVICE; ++ chan = host->dma_rx_channel; ++ } else { ++ dir = DMA_TO_DEVICE; ++ chan = host->dma_tx_channel; ++ } ++ ++ dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir); ++} ++ ++static void mmci_dma_finalize(struct mmci_host *host, struct mmc_data *data) ++{ + u32 status; + int i; + +@@ -329,19 +498,13 @@ static void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data) + * contiguous buffers. On TX, we'll get a FIFO underrun error. + */ + if (status & MCI_RXDATAAVLBLMASK) { +- dmaengine_terminate_all(chan); ++ mmci_dma_data_error(host); + if (!data->error) + data->error = -EIO; + } + +- if (data->flags & MMC_DATA_WRITE) { +- dir = DMA_TO_DEVICE; +- } else { +- dir = DMA_FROM_DEVICE; +- } +- + if (!data->host_cookie) +- dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir); ++ mmci_dma_unmap(host, data); + + /* + * Use of DMA with scatter-gather is impossible. +@@ -351,16 +514,15 @@ static void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data) + dev_err(mmc_dev(host->mmc), "buggy DMA detected. Taking evasive action.\n"); + mmci_dma_release(host); + } +-} + +-static void mmci_dma_data_error(struct mmci_host *host) +-{ +- dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n"); +- dmaengine_terminate_all(host->dma_current); ++ host->dma_current = NULL; ++ host->dma_desc_current = NULL; + } + +-static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, +- struct mmci_host_next *next) ++/* prepares DMA channel and DMA descriptor, returns non-zero on failure */ ++static int __mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, ++ struct dma_chan **dma_chan, ++ struct dma_async_tx_descriptor **dma_desc) + { + struct variant_data *variant = host->variant; + struct dma_slave_config conf = { +@@ -370,27 +532,21 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, + .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, + .src_maxburst = variant->fifohalfsize >> 2, /* # of words */ + .dst_maxburst = variant->fifohalfsize >> 2, /* # of words */ ++ .device_fc = false, + }; + struct dma_chan *chan; + struct dma_device *device; + struct dma_async_tx_descriptor *desc; ++ enum dma_data_direction buffer_dirn; + int nr_sg; + +- /* Check if next job is already prepared */ +- if (data->host_cookie && !next && +- host->dma_current && host->dma_desc_current) +- return 0; +- +- if (!next) { +- host->dma_current = NULL; +- host->dma_desc_current = NULL; +- } +- + if (data->flags & MMC_DATA_READ) { +- conf.direction = DMA_FROM_DEVICE; ++ conf.direction = DMA_DEV_TO_MEM; ++ buffer_dirn = DMA_FROM_DEVICE; + chan = host->dma_rx_channel; + } else { +- conf.direction = DMA_TO_DEVICE; ++ conf.direction = DMA_MEM_TO_DEV; ++ buffer_dirn = DMA_TO_DEVICE; + chan = host->dma_tx_channel; + } + +@@ -403,39 +559,51 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, + return -EINVAL; + + device = chan->device; +- nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, conf.direction); ++ nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, buffer_dirn); + if (nr_sg == 0) + return -EINVAL; + + dmaengine_slave_config(chan, &conf); +- desc = device->device_prep_slave_sg(chan, data->sg, nr_sg, ++ desc = dmaengine_prep_slave_sg(chan, data->sg, nr_sg, + conf.direction, DMA_CTRL_ACK); + if (!desc) + goto unmap_exit; + +- if (next) { +- next->dma_chan = chan; +- next->dma_desc = desc; +- } else { +- host->dma_current = chan; +- host->dma_desc_current = desc; +- } ++ *dma_chan = chan; ++ *dma_desc = desc; + + return 0; + + unmap_exit: +- if (!next) +- dmaengine_terminate_all(chan); +- dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction); ++ dma_unmap_sg(device->dev, data->sg, data->sg_len, buffer_dirn); + return -ENOMEM; + } + ++static inline int mmci_dma_prep_data(struct mmci_host *host, ++ struct mmc_data *data) ++{ ++ /* Check if next job is already prepared. */ ++ if (host->dma_current && host->dma_desc_current) ++ return 0; ++ ++ /* No job were prepared thus do it now. */ ++ return __mmci_dma_prep_data(host, data, &host->dma_current, ++ &host->dma_desc_current); ++} ++ ++static inline int mmci_dma_prep_next(struct mmci_host *host, ++ struct mmc_data *data) ++{ ++ struct mmci_host_next *nd = &host->next_data; ++ return __mmci_dma_prep_data(host, data, &nd->dma_chan, &nd->dma_desc); ++} ++ + static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) + { + int ret; + struct mmc_data *data = host->data; + +- ret = mmci_dma_prep_data(host, host->data, NULL); ++ ret = mmci_dma_prep_data(host, host->data); + if (ret) + return ret; + +@@ -449,7 +617,7 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) + datactrl |= MCI_DPSM_DMAENABLE; + + /* Trigger the DMA transfer */ +- writel(datactrl, host->base + MMCIDATACTRL); ++ mmci_write_datactrlreg(host, datactrl); + + /* + * Let the MMCI say when the data is ended and it's time +@@ -465,19 +633,11 @@ static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data) + { + struct mmci_host_next *next = &host->next_data; + +- if (data->host_cookie && data->host_cookie != next->cookie) { +- pr_warning("[%s] invalid cookie: data->host_cookie %d" +- " host->next_data.cookie %d\n", +- __func__, data->host_cookie, host->next_data.cookie); +- data->host_cookie = 0; +- } +- +- if (!data->host_cookie) +- return; ++ WARN_ON(data->host_cookie && data->host_cookie != next->cookie); ++ WARN_ON(!data->host_cookie && (next->dma_desc || next->dma_chan)); + + host->dma_desc_current = next->dma_desc; + host->dma_current = next->dma_chan; +- + next->dma_desc = NULL; + next->dma_chan = NULL; + } +@@ -492,19 +652,13 @@ static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq, + if (!data) + return; + +- if (data->host_cookie) { +- data->host_cookie = 0; ++ BUG_ON(data->host_cookie); ++ ++ if (mmci_validate_data(host, data)) + return; +- } + +- /* if config for dma */ +- if (((data->flags & MMC_DATA_WRITE) && host->dma_tx_channel) || +- ((data->flags & MMC_DATA_READ) && host->dma_rx_channel)) { +- if (mmci_dma_prep_data(host, data, nd)) +- data->host_cookie = 0; +- else +- data->host_cookie = ++nd->cookie < 0 ? 1 : nd->cookie; +- } ++ if (!mmci_dma_prep_next(host, data)) ++ data->host_cookie = ++nd->cookie < 0 ? 1 : nd->cookie; + } + + static void mmci_post_request(struct mmc_host *mmc, struct mmc_request *mrq, +@@ -512,29 +666,23 @@ static void mmci_post_request(struct mmc_host *mmc, struct mmc_request *mrq, + { + struct mmci_host *host = mmc_priv(mmc); + struct mmc_data *data = mrq->data; +- struct dma_chan *chan; +- enum dma_data_direction dir; + +- if (!data) ++ if (!data || !data->host_cookie) + return; + +- if (data->flags & MMC_DATA_READ) { +- dir = DMA_FROM_DEVICE; +- chan = host->dma_rx_channel; +- } else { +- dir = DMA_TO_DEVICE; +- chan = host->dma_tx_channel; +- } ++ mmci_dma_unmap(host, data); + ++ if (err) { ++ struct mmci_host_next *next = &host->next_data; ++ struct dma_chan *chan; ++ if (data->flags & MMC_DATA_READ) ++ chan = host->dma_rx_channel; ++ else ++ chan = host->dma_tx_channel; ++ dmaengine_terminate_all(chan); + +- /* if config for dma */ +- if (chan) { +- if (err) +- dmaengine_terminate_all(chan); +- if (data->host_cookie) +- dma_unmap_sg(mmc_dev(host->mmc), data->sg, +- data->sg_len, dir); +- mrq->data->host_cookie = 0; ++ next->dma_desc = NULL; ++ next->dma_chan = NULL; + } + } + +@@ -555,6 +703,11 @@ static inline void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data) + { + } + ++static inline void mmci_dma_finalize(struct mmci_host *host, ++ struct mmc_data *data) ++{ ++} ++ + static inline void mmci_dma_data_error(struct mmci_host *host) + { + } +@@ -604,6 +757,37 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) + if (data->flags & MMC_DATA_READ) + datactrl |= MCI_DPSM_DIRECTION; + ++ /* The ST Micro variants has a special bit to enable SDIO */ ++ if (variant->sdio && host->mmc->card) ++ if (mmc_card_sdio(host->mmc->card)) { ++ /* ++ * The ST Micro variants has a special bit ++ * to enable SDIO. ++ */ ++ u32 clk; ++ ++ datactrl |= MCI_ST_DPSM_SDIOEN; ++ ++ /* ++ * The ST Micro variant for SDIO small write transfers ++ * needs to have clock H/W flow control disabled, ++ * otherwise the transfer will not start. The threshold ++ * depends on the rate of MCLK. ++ */ ++ if (data->flags & MMC_DATA_WRITE && ++ (host->size < 8 || ++ (host->size <= 8 && host->mclk > 50000000))) ++ clk = host->clk_reg & ~variant->clkreg_enable; ++ else ++ clk = host->clk_reg | variant->clkreg_enable; ++ ++ mmci_write_clkreg(host, clk); ++ } ++ ++ if (host->mmc->ios.timing == MMC_TIMING_UHS_DDR50 || ++ host->mmc->ios.timing == MMC_TIMING_MMC_DDR52) ++ datactrl |= MCI_ST_DPSM_DDRMODE; ++ + /* + * Attempt to use DMA operation mode, if this + * should fail, fall back to PIO mode +@@ -632,12 +816,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) + irqmask = MCI_TXFIFOHALFEMPTYMASK; + } + +- /* The ST Micro variants has a special bit to enable SDIO */ +- if (variant->sdio && host->mmc->card) +- if (mmc_card_sdio(host->mmc->card)) +- datactrl |= MCI_ST_DPSM_SDIOEN; +- +- writel(datactrl, base + MMCIDATACTRL); ++ mmci_write_datactrlreg(host, datactrl); + writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); + mmci_set_mask1(host, irqmask); + } +@@ -680,8 +859,10 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, + u32 remain, success; + + /* Terminate the DMA transfer */ +- if (dma_inprogress(host)) ++ if (dma_inprogress(host)) { + mmci_dma_data_error(host); ++ mmci_dma_unmap(host, data); ++ } + + /* + * Calculate how far we are into the transfer. Note that +@@ -720,14 +901,14 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, + + if (status & MCI_DATAEND || data->error) { + if (dma_inprogress(host)) +- mmci_dma_unmap(host, data); ++ mmci_dma_finalize(host, data); + mmci_stop_data(host); + + if (!data->error) + /* The error clause is handled above, success! */ + data->bytes_xfered = data->blksz * data->blocks; + +- if (!data->stop) { ++ if (!data->stop || host->mrq->sbc) { + mmci_request_end(host, data->mrq); + } else { + mmci_start_command(host, data->stop, 0); +@@ -740,6 +921,30 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, + unsigned int status) + { + void __iomem *base = host->base; ++ bool sbc = (cmd == host->mrq->sbc); ++ bool busy_resp = host->variant->busy_detect && ++ (cmd->flags & MMC_RSP_BUSY); ++ ++ /* Check if we need to wait for busy completion. */ ++ if (host->busy_status && (status & MCI_ST_CARDBUSY)) ++ return; ++ ++ /* Enable busy completion if needed and supported. */ ++ if (!host->busy_status && busy_resp && ++ !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) && ++ (readl(base + MMCISTATUS) & MCI_ST_CARDBUSY)) { ++ writel(readl(base + MMCIMASK0) | MCI_ST_BUSYEND, ++ base + MMCIMASK0); ++ host->busy_status = status & (MCI_CMDSENT|MCI_CMDRESPEND); ++ return; ++ } ++ ++ /* At busy completion, mask the IRQ and complete the request. */ ++ if (host->busy_status) { ++ writel(readl(base + MMCIMASK0) & ~MCI_ST_BUSYEND, ++ base + MMCIMASK0); ++ host->busy_status = 0; ++ } + + host->cmd = NULL; + +@@ -754,14 +959,18 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, + cmd->resp[3] = readl(base + MMCIRESPONSE3); + } + +- if (!cmd->data || cmd->error) { ++ if ((!sbc && !cmd->data) || cmd->error) { + if (host->data) { + /* Terminate the DMA transfer */ +- if (dma_inprogress(host)) ++ if (dma_inprogress(host)) { + mmci_dma_data_error(host); ++ mmci_dma_unmap(host, host->data); ++ } + mmci_stop_data(host); + } +- mmci_request_end(host, cmd->mrq); ++ mmci_request_end(host, host->mrq); ++ } else if (sbc) { ++ mmci_start_command(host, host->mrq->cmd, 0); + } else if (!(cmd->data->flags & MMC_DATA_READ)) { + mmci_start_data(host, cmd->data); + } +@@ -783,7 +992,24 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema + if (count <= 0) + break; + +- readsl(base + MMCIFIFO, ptr, count >> 2); ++ /* ++ * SDIO especially may want to send something that is ++ * not divisible by 4 (as opposed to card sectors ++ * etc). Therefore make sure to always read the last bytes ++ * while only doing full 32-bit reads towards the FIFO. ++ */ ++ if (unlikely(count & 0x3)) { ++ if (count < 4) { ++ unsigned char buf[4]; ++ ioread32_rep(base + MMCIFIFO, buf, 1); ++ memcpy(ptr, buf, count); ++ } else { ++ ioread32_rep(base + MMCIFIFO, ptr, count >> 2); ++ count &= ~0x3; ++ } ++ } else { ++ ioread32_rep(base + MMCIFIFO, ptr, count >> 2); ++ } + + ptr += count; + remain -= count; +@@ -812,23 +1038,6 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem + count = min(remain, maxcnt); + + /* +- * The ST Micro variant for SDIO transfer sizes +- * less then 8 bytes should have clock H/W flow +- * control disabled. +- */ +- if (variant->sdio && +- mmc_card_sdio(host->mmc->card)) { +- if (count < 8) +- writel(readl(host->base + MMCICLOCK) & +- ~variant->clkreg_enable, +- host->base + MMCICLOCK); +- else +- writel(readl(host->base + MMCICLOCK) | +- variant->clkreg_enable, +- host->base + MMCICLOCK); +- } +- +- /* + * SDIO especially may want to send something that is + * not divisible by 4 (as opposed to card sectors + * etc), and the FIFO only accept full 32-bit writes. +@@ -836,7 +1045,7 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem + * byte become a 32bit write, 7 bytes will be two + * 32bit writes etc. + */ +- writesl(base + MMCIFIFO, ptr, (count + 3) >> 2); ++ iowrite32_rep(base + MMCIFIFO, ptr, (count + 3) >> 2); + + ptr += count; + remain -= count; +@@ -954,20 +1163,30 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) + status &= ~MCI_IRQ1MASK; + } + ++ /* ++ * We intentionally clear the MCI_ST_CARDBUSY IRQ here (if it's ++ * enabled) since the HW seems to be triggering the IRQ on both ++ * edges while monitoring DAT0 for busy completion. ++ */ + status &= readl(host->base + MMCIMASK0); + writel(status, host->base + MMCICLEAR); + + dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); + ++ cmd = host->cmd; ++ if ((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT| ++ MCI_CMDSENT|MCI_CMDRESPEND) && cmd) ++ mmci_cmd_irq(host, cmd, status); ++ + data = host->data; + if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR| + MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND| + MCI_DATABLOCKEND) && data) + mmci_data_irq(host, data, status); + +- cmd = host->cmd; +- if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd) +- mmci_cmd_irq(host, cmd, status); ++ /* Don't poll for busy completion in irq context. */ ++ if (host->busy_status) ++ status &= ~MCI_ST_CARDBUSY; + + ret = 1; + } while (status); +@@ -984,10 +1203,8 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) + + WARN_ON(host->mrq != NULL); + +- if (mrq->data && !is_power_of_2(mrq->data->blksz)) { +- dev_err(mmc_dev(mmc), "unsupported block size (%d bytes)\n", +- mrq->data->blksz); +- mrq->cmd->error = -EINVAL; ++ mrq->cmd->error = mmci_validate_data(host, mrq->data); ++ if (mrq->cmd->error) { + mmc_request_done(mmc, mrq); + return; + } +@@ -1004,7 +1221,10 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) + if (mrq->data && mrq->data->flags & MMC_DATA_READ) + mmci_start_data(host, mrq->data); + +- mmci_start_command(host, mrq->cmd, 0); ++ if (mrq->sbc) ++ mmci_start_command(host, mrq->sbc, 0); ++ else ++ mmci_start_command(host, mrq->cmd, 0); + + spin_unlock_irqrestore(&host->lock, flags); + } +@@ -1012,42 +1232,70 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) + static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct mmci_host *host = mmc_priv(mmc); ++ struct variant_data *variant = host->variant; + u32 pwr = 0; + unsigned long flags; + int ret; + ++ pm_runtime_get_sync(mmc_dev(mmc)); ++ ++ if (host->plat->ios_handler && ++ host->plat->ios_handler(mmc_dev(mmc), ios)) ++ dev_err(mmc_dev(mmc), "platform ios_handler failed\n"); ++ + switch (ios->power_mode) { + case MMC_POWER_OFF: +- if (host->vcc) +- ret = mmc_regulator_set_ocr(mmc, host->vcc, 0); ++ if (!IS_ERR(mmc->supply.vmmc)) ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); ++ ++ if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) { ++ regulator_disable(mmc->supply.vqmmc); ++ host->vqmmc_enabled = false; ++ } ++ + break; + case MMC_POWER_UP: +- if (host->vcc) { +- ret = mmc_regulator_set_ocr(mmc, host->vcc, ios->vdd); +- if (ret) { +- dev_err(mmc_dev(mmc), "unable to set OCR\n"); +- /* +- * The .set_ios() function in the mmc_host_ops +- * struct return void, and failing to set the +- * power should be rare so we print an error +- * and return here. +- */ +- return; +- } +- } +- if (host->plat->vdd_handler) +- pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd, +- ios->power_mode); +- /* The ST version does not have this, fall through to POWER_ON */ +- if (host->hw_designer != AMBA_VENDOR_ST) { +- pwr |= MCI_PWR_UP; +- break; +- } ++ if (!IS_ERR(mmc->supply.vmmc)) ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); ++ ++ /* ++ * The ST Micro variant doesn't have the PL180s MCI_PWR_UP ++ * and instead uses MCI_PWR_ON so apply whatever value is ++ * configured in the variant data. ++ */ ++ pwr |= variant->pwrreg_powerup; ++ ++ break; + case MMC_POWER_ON: ++ if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) { ++ ret = regulator_enable(mmc->supply.vqmmc); ++ if (ret < 0) ++ dev_err(mmc_dev(mmc), ++ "failed to enable vqmmc regulator\n"); ++ else ++ host->vqmmc_enabled = true; ++ } ++ + pwr |= MCI_PWR_ON; + break; + } + ++ if (variant->signal_direction && ios->power_mode != MMC_POWER_OFF) { ++ /* ++ * The ST Micro variant has some additional bits ++ * indicating signal direction for the signals in ++ * the SD/MMC bus and feedback-clock usage. ++ */ ++ pwr |= host->pwr_reg_add; ++ ++ if (ios->bus_width == MMC_BUS_WIDTH_4) ++ pwr &= ~MCI_ST_DATA74DIREN; ++ else if (ios->bus_width == MMC_BUS_WIDTH_1) ++ pwr &= (~MCI_ST_DATA74DIREN & ++ ~MCI_ST_DATA31DIREN & ++ ~MCI_ST_DATA2DIREN); ++ } ++ + if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) { + if (host->hw_designer != AMBA_VENDOR_ST) + pwr |= MCI_ROD; +@@ -1060,119 +1308,159 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + } + } + ++ /* ++ * If clock = 0 and the variant requires the MMCIPOWER to be used for ++ * gating the clock, the MCI_PWR_ON bit is cleared. ++ */ ++ if (!ios->clock && variant->pwrreg_clkgate) ++ pwr &= ~MCI_PWR_ON; ++ + spin_lock_irqsave(&host->lock, flags); + + mmci_set_clkreg(host, ios->clock); +- +- if (host->pwr != pwr) { +- host->pwr = pwr; +- writel(pwr, host->base + MMCIPOWER); +- } ++ mmci_write_pwrreg(host, pwr); ++ mmci_reg_delay(host); + + spin_unlock_irqrestore(&host->lock, flags); +-} + +-static int mmci_get_ro(struct mmc_host *mmc) +-{ +- struct mmci_host *host = mmc_priv(mmc); +- +- if (host->gpio_wp == -ENOSYS) +- return -ENOSYS; +- +- return gpio_get_value_cansleep(host->gpio_wp); ++ pm_runtime_mark_last_busy(mmc_dev(mmc)); ++ pm_runtime_put_autosuspend(mmc_dev(mmc)); + } + + static int mmci_get_cd(struct mmc_host *mmc) + { + struct mmci_host *host = mmc_priv(mmc); + struct mmci_platform_data *plat = host->plat; +- unsigned int status; ++ unsigned int status = mmc_gpio_get_cd(mmc); + +- if (host->gpio_cd == -ENOSYS) { ++ if (status == -ENOSYS) { + if (!plat->status) + return 1; /* Assume always present */ + + status = plat->status(mmc_dev(host->mmc)); +- } else +- status = !!gpio_get_value_cansleep(host->gpio_cd) +- ^ plat->cd_invert; +- +- /* +- * Use positive logic throughout - status is zero for no card, +- * non-zero for card inserted. +- */ ++ } + return status; + } + +-static irqreturn_t mmci_cd_irq(int irq, void *dev_id) ++static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios) + { +- struct mmci_host *host = dev_id; ++ int ret = 0; + +- mmc_detect_change(host->mmc, msecs_to_jiffies(500)); ++ if (!IS_ERR(mmc->supply.vqmmc)) { + +- return IRQ_HANDLED; ++ pm_runtime_get_sync(mmc_dev(mmc)); ++ ++ switch (ios->signal_voltage) { ++ case MMC_SIGNAL_VOLTAGE_330: ++ ret = regulator_set_voltage(mmc->supply.vqmmc, ++ 2700000, 3600000); ++ break; ++ case MMC_SIGNAL_VOLTAGE_180: ++ ret = regulator_set_voltage(mmc->supply.vqmmc, ++ 1700000, 1950000); ++ break; ++ case MMC_SIGNAL_VOLTAGE_120: ++ ret = regulator_set_voltage(mmc->supply.vqmmc, ++ 1100000, 1300000); ++ break; ++ } ++ ++ if (ret) ++ dev_warn(mmc_dev(mmc), "Voltage switch failed\n"); ++ ++ pm_runtime_mark_last_busy(mmc_dev(mmc)); ++ pm_runtime_put_autosuspend(mmc_dev(mmc)); ++ } ++ ++ return ret; + } + +-static const struct mmc_host_ops mmci_ops = { ++static struct mmc_host_ops mmci_ops = { + .request = mmci_request, + .pre_req = mmci_pre_request, + .post_req = mmci_post_request, + .set_ios = mmci_set_ios, +- .get_ro = mmci_get_ro, ++ .get_ro = mmc_gpio_get_ro, + .get_cd = mmci_get_cd, ++ .start_signal_voltage_switch = mmci_sig_volt_switch, + }; + +-static int __devinit mmci_probe(struct amba_device *dev, ++static int mmci_of_parse(struct device_node *np, struct mmc_host *mmc) ++{ ++ struct mmci_host *host = mmc_priv(mmc); ++ int ret = mmc_of_parse(mmc); ++ ++ if (ret) ++ return ret; ++ ++ if (of_get_property(np, "st,sig-dir-dat0", NULL)) ++ host->pwr_reg_add |= MCI_ST_DATA0DIREN; ++ if (of_get_property(np, "st,sig-dir-dat2", NULL)) ++ host->pwr_reg_add |= MCI_ST_DATA2DIREN; ++ if (of_get_property(np, "st,sig-dir-dat31", NULL)) ++ host->pwr_reg_add |= MCI_ST_DATA31DIREN; ++ if (of_get_property(np, "st,sig-dir-dat74", NULL)) ++ host->pwr_reg_add |= MCI_ST_DATA74DIREN; ++ if (of_get_property(np, "st,sig-dir-cmd", NULL)) ++ host->pwr_reg_add |= MCI_ST_CMDDIREN; ++ if (of_get_property(np, "st,sig-pin-fbclk", NULL)) ++ host->pwr_reg_add |= MCI_ST_FBCLKEN; ++ ++ if (of_get_property(np, "mmc-cap-mmc-highspeed", NULL)) ++ mmc->caps |= MMC_CAP_MMC_HIGHSPEED; ++ if (of_get_property(np, "mmc-cap-sd-highspeed", NULL)) ++ mmc->caps |= MMC_CAP_SD_HIGHSPEED; ++ ++ return 0; ++} ++ ++static int mmci_probe(struct amba_device *dev, + const struct amba_id *id) + { + struct mmci_platform_data *plat = dev->dev.platform_data; ++ struct device_node *np = dev->dev.of_node; + struct variant_data *variant = id->data; + struct mmci_host *host; + struct mmc_host *mmc; + int ret; + +- /* must have platform data */ +- if (!plat) { +- ret = -EINVAL; +- goto out; ++ /* Must have platform data or Device Tree. */ ++ if (!plat && !np) { ++ dev_err(&dev->dev, "No plat data or DT found\n"); ++ return -EINVAL; + } + +- ret = amba_request_regions(dev, DRIVER_NAME); +- if (ret) +- goto out; ++ if (!plat) { ++ plat = devm_kzalloc(&dev->dev, sizeof(*plat), GFP_KERNEL); ++ if (!plat) ++ return -ENOMEM; ++ } + + mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev); +- if (!mmc) { +- ret = -ENOMEM; +- goto rel_regions; +- } ++ if (!mmc) ++ return -ENOMEM; ++ ++ ret = mmci_of_parse(np, mmc); ++ if (ret) ++ goto host_free; + + host = mmc_priv(mmc); + host->mmc = mmc; + +- host->gpio_wp = -ENOSYS; +- host->gpio_cd = -ENOSYS; +- host->gpio_cd_irq = -1; +- + host->hw_designer = amba_manf(dev); + host->hw_revision = amba_rev(dev); + dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer); + dev_dbg(mmc_dev(mmc), "revision = 0x%01x\n", host->hw_revision); + +- host->clk = clk_get(&dev->dev, NULL); ++ host->clk = devm_clk_get(&dev->dev, NULL); + if (IS_ERR(host->clk)) { + ret = PTR_ERR(host->clk); +- host->clk = NULL; + goto host_free; + } + +- ret = clk_prepare(host->clk); +- if (ret) +- goto clk_free; +- +- ret = clk_enable(host->clk); ++ ret = clk_prepare_enable(host->clk); + if (ret) +- goto clk_unprep; ++ goto host_free; + + host->plat = plat; + host->variant = variant; +@@ -1190,14 +1478,14 @@ static int __devinit mmci_probe(struct amba_device *dev, + dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n", + host->mclk); + } ++ + host->phybase = dev->res.start; +- host->base = ioremap(dev->res.start, resource_size(&dev->res)); +- if (!host->base) { +- ret = -ENOMEM; ++ host->base = devm_ioremap_resource(&dev->dev, &dev->res); ++ if (IS_ERR(host->base)) { ++ ret = PTR_ERR(host->base); + goto clk_disable; + } + +- mmc->ops = &mmci_ops; + /* + * The ARM and ST versions of the block have slightly different + * clock divider equations which means that the minimum divider +@@ -1208,43 +1496,45 @@ static int __devinit mmci_probe(struct amba_device *dev, + else + mmc->f_min = DIV_ROUND_UP(host->mclk, 512); + /* +- * If the platform data supplies a maximum operating +- * frequency, this takes precedence. Else, we fall back +- * to using the module parameter, which has a (low) +- * default value in case it is not specified. Either +- * value must not exceed the clock rate into the block, +- * of course. ++ * If no maximum operating frequency is supplied, fall back to use ++ * the module parameter, which has a (low) default value in case it ++ * is not specified. Either value must not exceed the clock rate into ++ * the block, of course. + */ +- if (plat->f_max) +- mmc->f_max = min(host->mclk, plat->f_max); ++ if (mmc->f_max) ++ mmc->f_max = min(host->mclk, mmc->f_max); + else + mmc->f_max = min(host->mclk, fmax); + dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); + +-#ifdef CONFIG_REGULATOR +- /* If we're using the regulator framework, try to fetch a regulator */ +- host->vcc = regulator_get(&dev->dev, "vmmc"); +- if (IS_ERR(host->vcc)) +- host->vcc = NULL; +- else { +- int mask = mmc_regulator_get_ocrmask(host->vcc); ++ /* Get regulators and the supported OCR mask */ ++ mmc_regulator_get_supply(mmc); ++ if (!mmc->ocr_avail) ++ mmc->ocr_avail = plat->ocr_mask; ++ else if (plat->ocr_mask) ++ dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n"); ++ ++ /* DT takes precedence over platform data. */ ++ if (!np) { ++ if (!plat->cd_invert) ++ mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; ++ mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; ++ } + +- if (mask < 0) +- dev_err(&dev->dev, "error getting OCR mask (%d)\n", +- mask); +- else { +- host->mmc->ocr_avail = (u32) mask; +- if (plat->ocr_mask) +- dev_warn(&dev->dev, +- "Provided ocr_mask/setpower will not be used " +- "(using regulator instead)\n"); +- } ++ /* We support these capabilities. */ ++ mmc->caps |= MMC_CAP_CMD23; ++ ++ if (variant->busy_detect) { ++ mmci_ops.card_busy = mmci_card_busy; ++ mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE); ++ mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; ++ mmc->max_busy_timeout = 0; + } +-#endif +- /* Fall back to platform data if no regulator is found */ +- if (host->vcc == NULL) +- mmc->ocr_avail = plat->ocr_mask; +- mmc->caps = plat->capabilities; ++ ++ mmc->ops = &mmci_ops; ++ ++ /* We support these PM capabilities. */ ++ mmc->pm_caps |= MMC_PM_KEEP_POWER; + + /* + * We can do SGIO +@@ -1267,12 +1557,13 @@ static int __devinit mmci_probe(struct amba_device *dev, + /* + * Block size can be up to 2048 bytes, but must be a power of two. + */ +- mmc->max_blk_size = 2048; ++ mmc->max_blk_size = 1 << 11; + + /* +- * No limit on the number of blocks transferred. ++ * Limit the number of blocks transferred so that we don't overflow ++ * the maximum request size. + */ +- mmc->max_blk_count = mmc->max_req_size; ++ mmc->max_blk_count = mmc->max_req_size >> 11; + + spin_lock_init(&host->lock); + +@@ -1280,54 +1571,30 @@ static int __devinit mmci_probe(struct amba_device *dev, + writel(0, host->base + MMCIMASK1); + writel(0xfff, host->base + MMCICLEAR); + +- if (gpio_is_valid(plat->gpio_cd)) { +- ret = gpio_request(plat->gpio_cd, DRIVER_NAME " (cd)"); +- if (ret == 0) +- ret = gpio_direction_input(plat->gpio_cd); +- if (ret == 0) +- host->gpio_cd = plat->gpio_cd; +- else if (ret != -ENOSYS) +- goto err_gpio_cd; +- +- /* +- * A gpio pin that will detect cards when inserted and removed +- * will most likely want to trigger on the edges if it is +- * 0 when ejected and 1 when inserted (or mutatis mutandis +- * for the inverted case) so we request triggers on both +- * edges. +- */ +- ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd), +- mmci_cd_irq, +- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, +- DRIVER_NAME " (cd)", host); +- if (ret >= 0) +- host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd); ++ /* If DT, cd/wp gpios must be supplied through it. */ ++ if (!np && gpio_is_valid(plat->gpio_cd)) { ++ ret = mmc_gpio_request_cd(mmc, plat->gpio_cd, 0); ++ if (ret) ++ goto clk_disable; + } +- if (gpio_is_valid(plat->gpio_wp)) { +- ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)"); +- if (ret == 0) +- ret = gpio_direction_input(plat->gpio_wp); +- if (ret == 0) +- host->gpio_wp = plat->gpio_wp; +- else if (ret != -ENOSYS) +- goto err_gpio_wp; ++ if (!np && gpio_is_valid(plat->gpio_wp)) { ++ ret = mmc_gpio_request_ro(mmc, plat->gpio_wp); ++ if (ret) ++ goto clk_disable; + } + +- if ((host->plat->status || host->gpio_cd != -ENOSYS) +- && host->gpio_cd_irq < 0) +- mmc->caps |= MMC_CAP_NEEDS_POLL; +- +- ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host); ++ ret = devm_request_irq(&dev->dev, dev->irq[0], mmci_irq, IRQF_SHARED, ++ DRIVER_NAME " (cmd)", host); + if (ret) +- goto unmap; ++ goto clk_disable; + +- if (dev->irq[1] == NO_IRQ) ++ if (!dev->irq[1]) + host->singleirq = true; + else { +- ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, +- DRIVER_NAME " (pio)", host); ++ ret = devm_request_irq(&dev->dev, dev->irq[1], mmci_pio_irq, ++ IRQF_SHARED, DRIVER_NAME " (pio)", host); + if (ret) +- goto irq0_free; ++ goto clk_disable; + } + + writel(MCI_IRQENABLE, host->base + MMCIMASK0); +@@ -1341,44 +1608,25 @@ static int __devinit mmci_probe(struct amba_device *dev, + + mmci_dma_setup(host); + ++ pm_runtime_set_autosuspend_delay(&dev->dev, 50); ++ pm_runtime_use_autosuspend(&dev->dev); + pm_runtime_put(&dev->dev); + + mmc_add_host(mmc); + + return 0; + +- irq0_free: +- free_irq(dev->irq[0], host); +- unmap: +- if (host->gpio_wp != -ENOSYS) +- gpio_free(host->gpio_wp); +- err_gpio_wp: +- if (host->gpio_cd_irq >= 0) +- free_irq(host->gpio_cd_irq, host); +- if (host->gpio_cd != -ENOSYS) +- gpio_free(host->gpio_cd); +- err_gpio_cd: +- iounmap(host->base); + clk_disable: +- clk_disable(host->clk); +- clk_unprep: +- clk_unprepare(host->clk); +- clk_free: +- clk_put(host->clk); ++ clk_disable_unprepare(host->clk); + host_free: + mmc_free_host(mmc); +- rel_regions: +- amba_release_regions(dev); +- out: + return ret; + } + +-static int __devexit mmci_remove(struct amba_device *dev) ++static int mmci_remove(struct amba_device *dev) + { + struct mmc_host *mmc = amba_get_drvdata(dev); + +- amba_set_drvdata(dev, NULL); +- + if (mmc) { + struct mmci_host *host = mmc_priv(mmc); + +@@ -1397,71 +1645,85 @@ static int __devexit mmci_remove(struct amba_device *dev) + writel(0, host->base + MMCIDATACTRL); + + mmci_dma_release(host); +- free_irq(dev->irq[0], host); +- if (!host->singleirq) +- free_irq(dev->irq[1], host); +- +- if (host->gpio_wp != -ENOSYS) +- gpio_free(host->gpio_wp); +- if (host->gpio_cd_irq >= 0) +- free_irq(host->gpio_cd_irq, host); +- if (host->gpio_cd != -ENOSYS) +- gpio_free(host->gpio_cd); +- +- iounmap(host->base); +- clk_disable(host->clk); +- clk_unprepare(host->clk); +- clk_put(host->clk); +- +- if (host->vcc) +- mmc_regulator_set_ocr(mmc, host->vcc, 0); +- regulator_put(host->vcc); +- ++ clk_disable_unprepare(host->clk); + mmc_free_host(mmc); +- +- amba_release_regions(dev); + } + + return 0; + } + + #ifdef CONFIG_PM +-static int mmci_suspend(struct amba_device *dev, pm_message_t state) ++static void mmci_save(struct mmci_host *host) + { +- struct mmc_host *mmc = amba_get_drvdata(dev); +- int ret = 0; ++ unsigned long flags; + +- if (mmc) { +- struct mmci_host *host = mmc_priv(mmc); ++ spin_lock_irqsave(&host->lock, flags); + +- ret = mmc_suspend_host(mmc); +- if (ret == 0) +- writel(0, host->base + MMCIMASK0); ++ writel(0, host->base + MMCIMASK0); ++ if (host->variant->pwrreg_nopower) { ++ writel(0, host->base + MMCIDATACTRL); ++ writel(0, host->base + MMCIPOWER); ++ writel(0, host->base + MMCICLOCK); + } ++ mmci_reg_delay(host); + +- return ret; ++ spin_unlock_irqrestore(&host->lock, flags); + } + +-static int mmci_resume(struct amba_device *dev) ++static void mmci_restore(struct mmci_host *host) + { +- struct mmc_host *mmc = amba_get_drvdata(dev); +- int ret = 0; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ if (host->variant->pwrreg_nopower) { ++ writel(host->clk_reg, host->base + MMCICLOCK); ++ writel(host->datactrl_reg, host->base + MMCIDATACTRL); ++ writel(host->pwr_reg, host->base + MMCIPOWER); ++ } ++ writel(MCI_IRQENABLE, host->base + MMCIMASK0); ++ mmci_reg_delay(host); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++static int mmci_runtime_suspend(struct device *dev) ++{ ++ struct amba_device *adev = to_amba_device(dev); ++ struct mmc_host *mmc = amba_get_drvdata(adev); + + if (mmc) { + struct mmci_host *host = mmc_priv(mmc); ++ pinctrl_pm_select_sleep_state(dev); ++ mmci_save(host); ++ clk_disable_unprepare(host->clk); ++ } + +- writel(MCI_IRQENABLE, host->base + MMCIMASK0); ++ return 0; ++} + +- ret = mmc_resume_host(mmc); ++static int mmci_runtime_resume(struct device *dev) ++{ ++ struct amba_device *adev = to_amba_device(dev); ++ struct mmc_host *mmc = amba_get_drvdata(adev); ++ ++ if (mmc) { ++ struct mmci_host *host = mmc_priv(mmc); ++ clk_prepare_enable(host->clk); ++ mmci_restore(host); ++ pinctrl_pm_select_default_state(dev); + } + +- return ret; ++ return 0; + } +-#else +-#define mmci_suspend NULL +-#define mmci_resume NULL + #endif + ++static const struct dev_pm_ops mmci_dev_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, ++ pm_runtime_force_resume) ++ SET_PM_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL) ++}; ++ + static struct amba_id mmci_ids[] = { + { + .id = 0x00041180, +@@ -1474,6 +1736,11 @@ static struct amba_id mmci_ids[] = { + .data = &variant_arm_extended_fifo, + }, + { ++ .id = 0x02041180, ++ .mask = 0xff0fffff, ++ .data = &variant_arm_extended_fifo_hwfc, ++ }, ++ { + .id = 0x00041181, + .mask = 0x000fffff, + .data = &variant_arm, +@@ -1485,6 +1752,11 @@ static struct amba_id mmci_ids[] = { + .data = &variant_u300, + }, + { ++ .id = 0x10180180, ++ .mask = 0xf0ffffff, ++ .data = &variant_nomadik, ++ }, ++ { + .id = 0x00280180, + .mask = 0x00ffffff, + .data = &variant_u300, +@@ -1502,29 +1774,20 @@ static struct amba_id mmci_ids[] = { + { 0, 0 }, + }; + ++MODULE_DEVICE_TABLE(amba, mmci_ids); ++ + static struct amba_driver mmci_driver = { + .drv = { + .name = DRIVER_NAME, ++ .pm = &mmci_dev_pm_ops, + }, + .probe = mmci_probe, +- .remove = __devexit_p(mmci_remove), +- .suspend = mmci_suspend, +- .resume = mmci_resume, ++ .remove = mmci_remove, + .id_table = mmci_ids, + }; + +-static int __init mmci_init(void) +-{ +- return amba_driver_register(&mmci_driver); +-} +- +-static void __exit mmci_exit(void) +-{ +- amba_driver_unregister(&mmci_driver); +-} ++module_amba_driver(mmci_driver); + +-module_init(mmci_init); +-module_exit(mmci_exit); + module_param(fmax, uint, 0444); + + MODULE_DESCRIPTION("ARM PrimeCell PL180/181 Multimedia Card Interface driver"); +diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h +index 79e4143..347d942 100644 +--- a/drivers/mmc/host/mmci.h ++++ b/drivers/mmc/host/mmci.h +@@ -14,8 +14,8 @@ + #define MCI_OD (1 << 6) + #define MCI_ROD (1 << 7) + /* +- * The ST Micro version does not have ROD and reuse the voltage registers +- * for direction settings ++ * The ST Micro version does not have ROD and reuse the voltage registers for ++ * direction settings. + */ + #define MCI_ST_DATA2DIREN (1 << 2) + #define MCI_ST_CMDDIREN (1 << 3) +@@ -38,6 +38,8 @@ + #define MCI_ST_UX500_NEG_EDGE (1 << 13) + #define MCI_ST_UX500_HWFCEN (1 << 14) + #define MCI_ST_UX500_CLK_INV (1 << 15) ++/* Modified PL180 on Versatile Express platform */ ++#define MCI_ARM_HWFCEN (1 << 12) + + #define MMCIARGUMENT 0x008 + #define MMCICOMMAND 0x00c +@@ -46,10 +48,11 @@ + #define MCI_CPSM_INTERRUPT (1 << 8) + #define MCI_CPSM_PENDING (1 << 9) + #define MCI_CPSM_ENABLE (1 << 10) +-#define MCI_SDIO_SUSP (1 << 11) +-#define MCI_ENCMD_COMPL (1 << 12) +-#define MCI_NIEN (1 << 13) +-#define MCI_CE_ATACMD (1 << 14) ++/* Argument flag extenstions in the ST Micro versions */ ++#define MCI_ST_SDIO_SUSP (1 << 11) ++#define MCI_ST_ENCMD_COMPL (1 << 12) ++#define MCI_ST_NIEN (1 << 13) ++#define MCI_ST_CE_ATACMD (1 << 14) + + #define MMCIRESPCMD 0x010 + #define MMCIRESPONSE0 0x014 +@@ -102,6 +105,7 @@ + /* Extended status bits for the ST Micro variants */ + #define MCI_ST_SDIOIT (1 << 22) + #define MCI_ST_CEATAEND (1 << 23) ++#define MCI_ST_CARDBUSY (1 << 24) + + #define MMCICLEAR 0x038 + #define MCI_CMDCRCFAILCLR (1 << 0) +@@ -118,6 +122,7 @@ + /* Extended status bits for the ST Micro variants */ + #define MCI_ST_SDIOITC (1 << 22) + #define MCI_ST_CEATAENDC (1 << 23) ++#define MCI_ST_BUSYENDC (1 << 24) + + #define MMCIMASK0 0x03c + #define MCI_CMDCRCFAILMASK (1 << 0) +@@ -145,6 +150,7 @@ + /* Extended status bits for the ST Micro variants */ + #define MCI_ST_SDIOITMASK (1 << 22) + #define MCI_ST_CEATAENDMASK (1 << 23) ++#define MCI_ST_BUSYEND (1 << 24) + + #define MMCIMASK1 0x040 + #define MMCIFIFOCNT 0x048 +@@ -160,7 +166,7 @@ + (MCI_RXFIFOHALFFULLMASK | MCI_RXDATAAVLBLMASK | \ + MCI_TXFIFOHALFEMPTYMASK) + +-#define NR_SG 16 ++#define NR_SG 128 + + struct clk; + struct variant_data; +@@ -180,16 +186,18 @@ struct mmci_host { + struct mmc_data *data; + struct mmc_host *mmc; + struct clk *clk; +- int gpio_cd; +- int gpio_wp; +- int gpio_cd_irq; + bool singleirq; + + spinlock_t lock; + + unsigned int mclk; + unsigned int cclk; +- u32 pwr; ++ u32 pwr_reg; ++ u32 pwr_reg_add; ++ u32 clk_reg; ++ u32 datactrl_reg; ++ u32 busy_status; ++ bool vqmmc_enabled; + struct mmci_platform_data *plat; + struct variant_data *variant; + +@@ -202,7 +210,6 @@ struct mmci_host { + /* pio stuff */ + struct sg_mapping_iter sg_miter; + unsigned int size; +- struct regulator *vcc; + + #ifdef CONFIG_DMA_ENGINE + /* DMA stuff */ +diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c +new file mode 100644 +index 0000000..74924a0 +--- /dev/null ++++ b/drivers/mmc/host/moxart-mmc.c +@@ -0,0 +1,730 @@ ++/* ++ * MOXA ART MMC host driver. ++ * ++ * Copyright (C) 2014 Jonas Jensen ++ * ++ * Jonas Jensen ++ * ++ * Based on code from ++ * Moxa Technologies Co., Ltd. ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define REG_COMMAND 0 ++#define REG_ARGUMENT 4 ++#define REG_RESPONSE0 8 ++#define REG_RESPONSE1 12 ++#define REG_RESPONSE2 16 ++#define REG_RESPONSE3 20 ++#define REG_RESPONSE_COMMAND 24 ++#define REG_DATA_CONTROL 28 ++#define REG_DATA_TIMER 32 ++#define REG_DATA_LENGTH 36 ++#define REG_STATUS 40 ++#define REG_CLEAR 44 ++#define REG_INTERRUPT_MASK 48 ++#define REG_POWER_CONTROL 52 ++#define REG_CLOCK_CONTROL 56 ++#define REG_BUS_WIDTH 60 ++#define REG_DATA_WINDOW 64 ++#define REG_FEATURE 68 ++#define REG_REVISION 72 ++ ++/* REG_COMMAND */ ++#define CMD_SDC_RESET BIT(10) ++#define CMD_EN BIT(9) ++#define CMD_APP_CMD BIT(8) ++#define CMD_LONG_RSP BIT(7) ++#define CMD_NEED_RSP BIT(6) ++#define CMD_IDX_MASK 0x3f ++ ++/* REG_RESPONSE_COMMAND */ ++#define RSP_CMD_APP BIT(6) ++#define RSP_CMD_IDX_MASK 0x3f ++ ++/* REG_DATA_CONTROL */ ++#define DCR_DATA_FIFO_RESET BIT(8) ++#define DCR_DATA_THRES BIT(7) ++#define DCR_DATA_EN BIT(6) ++#define DCR_DMA_EN BIT(5) ++#define DCR_DATA_WRITE BIT(4) ++#define DCR_BLK_SIZE 0x0f ++ ++/* REG_DATA_LENGTH */ ++#define DATA_LEN_MASK 0xffffff ++ ++/* REG_STATUS */ ++#define WRITE_PROT BIT(12) ++#define CARD_DETECT BIT(11) ++/* 1-10 below can be sent to either registers, interrupt or clear. */ ++#define CARD_CHANGE BIT(10) ++#define FIFO_ORUN BIT(9) ++#define FIFO_URUN BIT(8) ++#define DATA_END BIT(7) ++#define CMD_SENT BIT(6) ++#define DATA_CRC_OK BIT(5) ++#define RSP_CRC_OK BIT(4) ++#define DATA_TIMEOUT BIT(3) ++#define RSP_TIMEOUT BIT(2) ++#define DATA_CRC_FAIL BIT(1) ++#define RSP_CRC_FAIL BIT(0) ++ ++#define MASK_RSP (RSP_TIMEOUT | RSP_CRC_FAIL | \ ++ RSP_CRC_OK | CARD_DETECT | CMD_SENT) ++ ++#define MASK_DATA (DATA_CRC_OK | DATA_END | \ ++ DATA_CRC_FAIL | DATA_TIMEOUT) ++ ++#define MASK_INTR_PIO (FIFO_URUN | FIFO_ORUN | CARD_CHANGE) ++ ++/* REG_POWER_CONTROL */ ++#define SD_POWER_ON BIT(4) ++#define SD_POWER_MASK 0x0f ++ ++/* REG_CLOCK_CONTROL */ ++#define CLK_HISPD BIT(9) ++#define CLK_OFF BIT(8) ++#define CLK_SD BIT(7) ++#define CLK_DIV_MASK 0x7f ++ ++/* REG_BUS_WIDTH */ ++#define BUS_WIDTH_8 BIT(2) ++#define BUS_WIDTH_4 BIT(1) ++#define BUS_WIDTH_1 BIT(0) ++ ++#define MMC_VDD_360 23 ++#define MIN_POWER (MMC_VDD_360 - SD_POWER_MASK) ++#define MAX_RETRIES 500000 ++ ++struct moxart_host { ++ spinlock_t lock; ++ ++ void __iomem *base; ++ ++ phys_addr_t reg_phys; ++ ++ struct dma_chan *dma_chan_tx; ++ struct dma_chan *dma_chan_rx; ++ struct dma_async_tx_descriptor *tx_desc; ++ struct mmc_host *mmc; ++ struct mmc_request *mrq; ++ struct scatterlist *cur_sg; ++ struct completion dma_complete; ++ struct completion pio_complete; ++ ++ u32 num_sg; ++ u32 data_remain; ++ u32 data_len; ++ u32 fifo_width; ++ u32 timeout; ++ u32 rate; ++ ++ long sysclk; ++ ++ bool have_dma; ++ bool is_removed; ++}; ++ ++static inline void moxart_init_sg(struct moxart_host *host, ++ struct mmc_data *data) ++{ ++ host->cur_sg = data->sg; ++ host->num_sg = data->sg_len; ++ host->data_remain = host->cur_sg->length; ++ ++ if (host->data_remain > host->data_len) ++ host->data_remain = host->data_len; ++} ++ ++static inline int moxart_next_sg(struct moxart_host *host) ++{ ++ int remain; ++ struct mmc_data *data = host->mrq->cmd->data; ++ ++ host->cur_sg++; ++ host->num_sg--; ++ ++ if (host->num_sg > 0) { ++ host->data_remain = host->cur_sg->length; ++ remain = host->data_len - data->bytes_xfered; ++ if (remain > 0 && remain < host->data_remain) ++ host->data_remain = remain; ++ } ++ ++ return host->num_sg; ++} ++ ++static int moxart_wait_for_status(struct moxart_host *host, ++ u32 mask, u32 *status) ++{ ++ int ret = -ETIMEDOUT; ++ u32 i; ++ ++ for (i = 0; i < MAX_RETRIES; i++) { ++ *status = readl(host->base + REG_STATUS); ++ if (!(*status & mask)) { ++ udelay(5); ++ continue; ++ } ++ writel(*status & mask, host->base + REG_CLEAR); ++ ret = 0; ++ break; ++ } ++ ++ if (ret) ++ dev_err(mmc_dev(host->mmc), "timed out waiting for status\n"); ++ ++ return ret; ++} ++ ++ ++static void moxart_send_command(struct moxart_host *host, ++ struct mmc_command *cmd) ++{ ++ u32 status, cmdctrl; ++ ++ writel(RSP_TIMEOUT | RSP_CRC_OK | ++ RSP_CRC_FAIL | CMD_SENT, host->base + REG_CLEAR); ++ writel(cmd->arg, host->base + REG_ARGUMENT); ++ ++ cmdctrl = cmd->opcode & CMD_IDX_MASK; ++ if (cmdctrl == SD_APP_SET_BUS_WIDTH || cmdctrl == SD_APP_OP_COND || ++ cmdctrl == SD_APP_SEND_SCR || cmdctrl == SD_APP_SD_STATUS || ++ cmdctrl == SD_APP_SEND_NUM_WR_BLKS) ++ cmdctrl |= CMD_APP_CMD; ++ ++ if (cmd->flags & MMC_RSP_PRESENT) ++ cmdctrl |= CMD_NEED_RSP; ++ ++ if (cmd->flags & MMC_RSP_136) ++ cmdctrl |= CMD_LONG_RSP; ++ ++ writel(cmdctrl | CMD_EN, host->base + REG_COMMAND); ++ ++ if (moxart_wait_for_status(host, MASK_RSP, &status) == -ETIMEDOUT) ++ cmd->error = -ETIMEDOUT; ++ ++ if (status & RSP_TIMEOUT) { ++ cmd->error = -ETIMEDOUT; ++ return; ++ } ++ if (status & RSP_CRC_FAIL) { ++ cmd->error = -EIO; ++ return; ++ } ++ if (status & RSP_CRC_OK) { ++ if (cmd->flags & MMC_RSP_136) { ++ cmd->resp[3] = readl(host->base + REG_RESPONSE0); ++ cmd->resp[2] = readl(host->base + REG_RESPONSE1); ++ cmd->resp[1] = readl(host->base + REG_RESPONSE2); ++ cmd->resp[0] = readl(host->base + REG_RESPONSE3); ++ } else { ++ cmd->resp[0] = readl(host->base + REG_RESPONSE0); ++ } ++ } ++} ++ ++static void moxart_dma_complete(void *param) ++{ ++ struct moxart_host *host = param; ++ ++ complete(&host->dma_complete); ++} ++ ++static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host) ++{ ++ u32 len, dir_data, dir_slave; ++ unsigned long dma_time; ++ struct dma_async_tx_descriptor *desc = NULL; ++ struct dma_chan *dma_chan; ++ ++ if (host->data_len == data->bytes_xfered) ++ return; ++ ++ if (data->flags & MMC_DATA_WRITE) { ++ dma_chan = host->dma_chan_tx; ++ dir_data = DMA_TO_DEVICE; ++ dir_slave = DMA_MEM_TO_DEV; ++ } else { ++ dma_chan = host->dma_chan_rx; ++ dir_data = DMA_FROM_DEVICE; ++ dir_slave = DMA_DEV_TO_MEM; ++ } ++ ++ len = dma_map_sg(dma_chan->device->dev, data->sg, ++ data->sg_len, dir_data); ++ ++ if (len > 0) { ++ desc = dmaengine_prep_slave_sg(dma_chan, data->sg, ++ len, dir_slave, ++ DMA_PREP_INTERRUPT | ++ DMA_CTRL_ACK); ++ } else { ++ dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n"); ++ } ++ ++ if (desc) { ++ host->tx_desc = desc; ++ desc->callback = moxart_dma_complete; ++ desc->callback_param = host; ++ dmaengine_submit(desc); ++ dma_async_issue_pending(dma_chan); ++ } ++ ++ data->bytes_xfered += host->data_remain; ++ ++ dma_time = wait_for_completion_interruptible_timeout( ++ &host->dma_complete, host->timeout); ++ ++ dma_unmap_sg(dma_chan->device->dev, ++ data->sg, data->sg_len, ++ dir_data); ++} ++ ++ ++static void moxart_transfer_pio(struct moxart_host *host) ++{ ++ struct mmc_data *data = host->mrq->cmd->data; ++ u32 *sgp, len = 0, remain, status; ++ ++ if (host->data_len == data->bytes_xfered) ++ return; ++ ++ sgp = sg_virt(host->cur_sg); ++ remain = host->data_remain; ++ ++ if (data->flags & MMC_DATA_WRITE) { ++ while (remain > 0) { ++ if (moxart_wait_for_status(host, FIFO_URUN, &status) ++ == -ETIMEDOUT) { ++ data->error = -ETIMEDOUT; ++ complete(&host->pio_complete); ++ return; ++ } ++ for (len = 0; len < remain && len < host->fifo_width;) { ++ iowrite32(*sgp, host->base + REG_DATA_WINDOW); ++ sgp++; ++ len += 4; ++ } ++ remain -= len; ++ } ++ ++ } else { ++ while (remain > 0) { ++ if (moxart_wait_for_status(host, FIFO_ORUN, &status) ++ == -ETIMEDOUT) { ++ data->error = -ETIMEDOUT; ++ complete(&host->pio_complete); ++ return; ++ } ++ for (len = 0; len < remain && len < host->fifo_width;) { ++ /* SCR data must be read in big endian. */ ++ if (data->mrq->cmd->opcode == SD_APP_SEND_SCR) ++ *sgp = ioread32be(host->base + ++ REG_DATA_WINDOW); ++ else ++ *sgp = ioread32(host->base + ++ REG_DATA_WINDOW); ++ sgp++; ++ len += 4; ++ } ++ remain -= len; ++ } ++ } ++ ++ data->bytes_xfered += host->data_remain - remain; ++ host->data_remain = remain; ++ ++ if (host->data_len != data->bytes_xfered) ++ moxart_next_sg(host); ++ else ++ complete(&host->pio_complete); ++} ++ ++static void moxart_prepare_data(struct moxart_host *host) ++{ ++ struct mmc_data *data = host->mrq->cmd->data; ++ u32 datactrl; ++ int blksz_bits; ++ ++ if (!data) ++ return; ++ ++ host->data_len = data->blocks * data->blksz; ++ blksz_bits = ffs(data->blksz) - 1; ++ BUG_ON(1 << blksz_bits != data->blksz); ++ ++ moxart_init_sg(host, data); ++ ++ datactrl = DCR_DATA_EN | (blksz_bits & DCR_BLK_SIZE); ++ ++ if (data->flags & MMC_DATA_WRITE) ++ datactrl |= DCR_DATA_WRITE; ++ ++ if ((host->data_len > host->fifo_width) && host->have_dma) ++ datactrl |= DCR_DMA_EN; ++ ++ writel(DCR_DATA_FIFO_RESET, host->base + REG_DATA_CONTROL); ++ writel(MASK_DATA | FIFO_URUN | FIFO_ORUN, host->base + REG_CLEAR); ++ writel(host->rate, host->base + REG_DATA_TIMER); ++ writel(host->data_len, host->base + REG_DATA_LENGTH); ++ writel(datactrl, host->base + REG_DATA_CONTROL); ++} ++ ++static void moxart_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct moxart_host *host = mmc_priv(mmc); ++ unsigned long pio_time, flags; ++ u32 status; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ init_completion(&host->dma_complete); ++ init_completion(&host->pio_complete); ++ ++ host->mrq = mrq; ++ ++ if (readl(host->base + REG_STATUS) & CARD_DETECT) { ++ mrq->cmd->error = -ETIMEDOUT; ++ goto request_done; ++ } ++ ++ moxart_prepare_data(host); ++ moxart_send_command(host, host->mrq->cmd); ++ ++ if (mrq->cmd->data) { ++ if ((host->data_len > host->fifo_width) && host->have_dma) { ++ ++ writel(CARD_CHANGE, host->base + REG_INTERRUPT_MASK); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ moxart_transfer_dma(mrq->cmd->data, host); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ } else { ++ ++ writel(MASK_INTR_PIO, host->base + REG_INTERRUPT_MASK); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ /* PIO transfers start from interrupt. */ ++ pio_time = wait_for_completion_interruptible_timeout( ++ &host->pio_complete, host->timeout); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ } ++ ++ if (host->is_removed) { ++ dev_err(mmc_dev(host->mmc), "card removed\n"); ++ mrq->cmd->error = -ETIMEDOUT; ++ goto request_done; ++ } ++ ++ if (moxart_wait_for_status(host, MASK_DATA, &status) ++ == -ETIMEDOUT) { ++ mrq->cmd->data->error = -ETIMEDOUT; ++ goto request_done; ++ } ++ ++ if (status & DATA_CRC_FAIL) ++ mrq->cmd->data->error = -ETIMEDOUT; ++ ++ if (mrq->cmd->data->stop) ++ moxart_send_command(host, mrq->cmd->data->stop); ++ } ++ ++request_done: ++ spin_unlock_irqrestore(&host->lock, flags); ++ mmc_request_done(host->mmc, mrq); ++} ++ ++static irqreturn_t moxart_irq(int irq, void *devid) ++{ ++ struct moxart_host *host = (struct moxart_host *)devid; ++ u32 status; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ status = readl(host->base + REG_STATUS); ++ if (status & CARD_CHANGE) { ++ host->is_removed = status & CARD_DETECT; ++ if (host->is_removed && host->have_dma) { ++ dmaengine_terminate_all(host->dma_chan_tx); ++ dmaengine_terminate_all(host->dma_chan_rx); ++ } ++ host->mrq = NULL; ++ writel(MASK_INTR_PIO, host->base + REG_CLEAR); ++ writel(CARD_CHANGE, host->base + REG_INTERRUPT_MASK); ++ mmc_detect_change(host->mmc, 0); ++ } ++ if (status & (FIFO_ORUN | FIFO_URUN) && host->mrq) ++ moxart_transfer_pio(host); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ return IRQ_HANDLED; ++} ++ ++static void moxart_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct moxart_host *host = mmc_priv(mmc); ++ unsigned long flags; ++ u8 power, div; ++ u32 ctrl; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ if (ios->clock) { ++ for (div = 0; div < CLK_DIV_MASK; ++div) { ++ if (ios->clock >= host->sysclk / (2 * (div + 1))) ++ break; ++ } ++ ctrl = CLK_SD | div; ++ host->rate = host->sysclk / (2 * (div + 1)); ++ if (host->rate > host->sysclk) ++ ctrl |= CLK_HISPD; ++ writel(ctrl, host->base + REG_CLOCK_CONTROL); ++ } ++ ++ if (ios->power_mode == MMC_POWER_OFF) { ++ writel(readl(host->base + REG_POWER_CONTROL) & ~SD_POWER_ON, ++ host->base + REG_POWER_CONTROL); ++ } else { ++ if (ios->vdd < MIN_POWER) ++ power = 0; ++ else ++ power = ios->vdd - MIN_POWER; ++ ++ writel(SD_POWER_ON | (u32) power, ++ host->base + REG_POWER_CONTROL); ++ } ++ ++ switch (ios->bus_width) { ++ case MMC_BUS_WIDTH_4: ++ writel(BUS_WIDTH_4, host->base + REG_BUS_WIDTH); ++ break; ++ case MMC_BUS_WIDTH_8: ++ writel(BUS_WIDTH_8, host->base + REG_BUS_WIDTH); ++ break; ++ default: ++ writel(BUS_WIDTH_1, host->base + REG_BUS_WIDTH); ++ break; ++ } ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++ ++static int moxart_get_ro(struct mmc_host *mmc) ++{ ++ struct moxart_host *host = mmc_priv(mmc); ++ ++ return !!(readl(host->base + REG_STATUS) & WRITE_PROT); ++} ++ ++static struct mmc_host_ops moxart_ops = { ++ .request = moxart_request, ++ .set_ios = moxart_set_ios, ++ .get_ro = moxart_get_ro, ++}; ++ ++static int moxart_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *node = dev->of_node; ++ struct resource res_mmc; ++ struct mmc_host *mmc; ++ struct moxart_host *host = NULL; ++ struct dma_slave_config cfg; ++ struct clk *clk; ++ void __iomem *reg_mmc; ++ dma_cap_mask_t mask; ++ int irq, ret; ++ u32 i; ++ ++ mmc = mmc_alloc_host(sizeof(struct moxart_host), dev); ++ if (!mmc) { ++ dev_err(dev, "mmc_alloc_host failed\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ret = of_address_to_resource(node, 0, &res_mmc); ++ if (ret) { ++ dev_err(dev, "of_address_to_resource failed\n"); ++ goto out; ++ } ++ ++ irq = irq_of_parse_and_map(node, 0); ++ if (irq <= 0) { ++ dev_err(dev, "irq_of_parse_and_map failed\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ clk = of_clk_get(node, 0); ++ if (IS_ERR(clk)) { ++ dev_err(dev, "of_clk_get failed\n"); ++ ret = PTR_ERR(clk); ++ goto out; ++ } ++ ++ reg_mmc = devm_ioremap_resource(dev, &res_mmc); ++ if (IS_ERR(reg_mmc)) { ++ ret = PTR_ERR(reg_mmc); ++ goto out; ++ } ++ ++ mmc_of_parse(mmc); ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ ++ host = mmc_priv(mmc); ++ host->mmc = mmc; ++ host->base = reg_mmc; ++ host->reg_phys = res_mmc.start; ++ host->timeout = msecs_to_jiffies(1000); ++ host->sysclk = clk_get_rate(clk); ++ host->fifo_width = readl(host->base + REG_FEATURE) << 2; ++ host->dma_chan_tx = of_dma_request_slave_channel(node, "tx"); ++ host->dma_chan_rx = of_dma_request_slave_channel(node, "rx"); ++ ++ spin_lock_init(&host->lock); ++ ++ mmc->ops = &moxart_ops; ++ mmc->f_max = DIV_ROUND_CLOSEST(host->sysclk, 2); ++ mmc->f_min = DIV_ROUND_CLOSEST(host->sysclk, CLK_DIV_MASK * 2); ++ mmc->ocr_avail = 0xffff00; /* Support 2.0v - 3.6v power. */ ++ ++ if (IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) { ++ dev_dbg(dev, "PIO mode transfer enabled\n"); ++ host->have_dma = false; ++ } else { ++ dev_dbg(dev, "DMA channels found (%p,%p)\n", ++ host->dma_chan_tx, host->dma_chan_rx); ++ host->have_dma = true; ++ ++ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ ++ cfg.direction = DMA_MEM_TO_DEV; ++ cfg.src_addr = 0; ++ cfg.dst_addr = host->reg_phys + REG_DATA_WINDOW; ++ dmaengine_slave_config(host->dma_chan_tx, &cfg); ++ ++ cfg.direction = DMA_DEV_TO_MEM; ++ cfg.src_addr = host->reg_phys + REG_DATA_WINDOW; ++ cfg.dst_addr = 0; ++ dmaengine_slave_config(host->dma_chan_rx, &cfg); ++ } ++ ++ switch ((readl(host->base + REG_BUS_WIDTH) >> 3) & 3) { ++ case 1: ++ mmc->caps |= MMC_CAP_4_BIT_DATA; ++ break; ++ case 2: ++ mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; ++ break; ++ default: ++ break; ++ } ++ ++ writel(0, host->base + REG_INTERRUPT_MASK); ++ ++ writel(CMD_SDC_RESET, host->base + REG_COMMAND); ++ for (i = 0; i < MAX_RETRIES; i++) { ++ if (!(readl(host->base + REG_COMMAND) & CMD_SDC_RESET)) ++ break; ++ udelay(5); ++ } ++ ++ ret = devm_request_irq(dev, irq, moxart_irq, 0, "moxart-mmc", host); ++ if (ret) ++ goto out; ++ ++ dev_set_drvdata(dev, mmc); ++ mmc_add_host(mmc); ++ ++ dev_dbg(dev, "IRQ=%d, FIFO is %d bytes\n", irq, host->fifo_width); ++ ++ return 0; ++ ++out: ++ if (mmc) ++ mmc_free_host(mmc); ++ return ret; ++} ++ ++static int moxart_remove(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc = dev_get_drvdata(&pdev->dev); ++ struct moxart_host *host = mmc_priv(mmc); ++ ++ dev_set_drvdata(&pdev->dev, NULL); ++ ++ if (mmc) { ++ if (!IS_ERR(host->dma_chan_tx)) ++ dma_release_channel(host->dma_chan_tx); ++ if (!IS_ERR(host->dma_chan_rx)) ++ dma_release_channel(host->dma_chan_rx); ++ mmc_remove_host(mmc); ++ mmc_free_host(mmc); ++ ++ writel(0, host->base + REG_INTERRUPT_MASK); ++ writel(0, host->base + REG_POWER_CONTROL); ++ writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF, ++ host->base + REG_CLOCK_CONTROL); ++ } ++ ++ kfree(host); ++ ++ return 0; ++} ++ ++static const struct of_device_id moxart_mmc_match[] = { ++ { .compatible = "moxa,moxart-mmc" }, ++ { .compatible = "faraday,ftsdc010" }, ++ { } ++}; ++ ++static struct platform_driver moxart_mmc_driver = { ++ .probe = moxart_probe, ++ .remove = moxart_remove, ++ .driver = { ++ .name = "mmc-moxart", ++ .owner = THIS_MODULE, ++ .of_match_table = moxart_mmc_match, ++ }, ++}; ++module_platform_driver(moxart_mmc_driver); ++ ++MODULE_ALIAS("platform:mmc-moxart"); ++MODULE_DESCRIPTION("MOXA ART MMC driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Jonas Jensen "); +diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c +index 80d8eb1..9405ecd 100644 +--- a/drivers/mmc/host/msm_sdcc.c ++++ b/drivers/mmc/host/msm_sdcc.c +@@ -42,8 +42,7 @@ + #include + #include + +-#include +-#include ++#include + #include + #include + +@@ -689,8 +688,8 @@ msmsdcc_pio_irq(int irq, void *dev_id) + + /* Map the current scatter buffer */ + local_irq_save(flags); +- buffer = kmap_atomic(sg_page(host->pio.sg), +- KM_BIO_SRC_IRQ) + host->pio.sg->offset; ++ buffer = kmap_atomic(sg_page(host->pio.sg)) ++ + host->pio.sg->offset; + buffer += host->pio.sg_off; + remain = host->pio.sg->length - host->pio.sg_off; + len = 0; +@@ -700,7 +699,7 @@ msmsdcc_pio_irq(int irq, void *dev_id) + len = msmsdcc_pio_write(host, buffer, remain, status); + + /* Unmap the buffer */ +- kunmap_atomic(buffer, KM_BIO_SRC_IRQ); ++ kunmap_atomic(buffer); + local_irq_restore(flags); + + host->pio.sg_off += len; +@@ -1269,10 +1268,18 @@ msmsdcc_probe(struct platform_device *pdev) + goto clk_put; + } + ++ ret = clk_prepare(host->pclk); ++ if (ret) ++ goto clk_put; ++ ++ ret = clk_prepare(host->clk); ++ if (ret) ++ goto clk_unprepare_p; ++ + /* Enable clocks */ + ret = msmsdcc_enable_clocks(host); + if (ret) +- goto clk_put; ++ goto clk_unprepare; + + host->pclk_rate = clk_get_rate(host->pclk); + host->clk_rate = clk_get_rate(host->clk); +@@ -1387,6 +1394,10 @@ msmsdcc_probe(struct platform_device *pdev) + free_irq(host->stat_irq, host); + clk_disable: + msmsdcc_disable_clocks(host, 0); ++ clk_unprepare: ++ clk_unprepare(host->clk); ++ clk_unprepare_p: ++ clk_unprepare(host->pclk); + clk_put: + clk_put(host->clk); + pclk_put: +@@ -1405,28 +1416,10 @@ ioremap_free: + } + + #ifdef CONFIG_PM +-#ifdef CONFIG_MMC_MSM7X00A_RESUME_IN_WQ +-static void +-do_resume_work(struct work_struct *work) +-{ +- struct msmsdcc_host *host = +- container_of(work, struct msmsdcc_host, resume_task); +- struct mmc_host *mmc = host->mmc; +- +- if (mmc) { +- mmc_resume_host(mmc); +- if (host->stat_irq) +- enable_irq(host->stat_irq); +- } +-} +-#endif +- +- + static int + msmsdcc_suspend(struct platform_device *dev, pm_message_t state) + { + struct mmc_host *mmc = mmc_get_drvdata(dev); +- int rc = 0; + + if (mmc) { + struct msmsdcc_host *host = mmc_priv(mmc); +@@ -1434,14 +1427,11 @@ msmsdcc_suspend(struct platform_device *dev, pm_message_t state) + if (host->stat_irq) + disable_irq(host->stat_irq); + +- if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) +- rc = mmc_suspend_host(mmc); +- if (!rc) +- msmsdcc_writel(host, 0, MMCIMASK0); ++ msmsdcc_writel(host, 0, MMCIMASK0); + if (host->clks_on) + msmsdcc_disable_clocks(host, 0); + } +- return rc; ++ return 0; + } + + static int +@@ -1456,8 +1446,6 @@ msmsdcc_resume(struct platform_device *dev) + + msmsdcc_writel(host, host->saved_irq0mask, MMCIMASK0); + +- if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) +- mmc_resume_host(mmc); + if (host->stat_irq) + enable_irq(host->stat_irq); + #if BUSCLK_PWRSAVE +@@ -1480,18 +1468,7 @@ static struct platform_driver msmsdcc_driver = { + }, + }; + +-static int __init msmsdcc_init(void) +-{ +- return platform_driver_register(&msmsdcc_driver); +-} +- +-static void __exit msmsdcc_exit(void) +-{ +- platform_driver_unregister(&msmsdcc_driver); +-} +- +-module_init(msmsdcc_init); +-module_exit(msmsdcc_exit); ++module_platform_driver(msmsdcc_driver); + + MODULE_DESCRIPTION("Qualcomm MSM 7X00A Multimedia Card Interface driver"); + MODULE_LICENSE("GPL"); +diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c +index 211a495..6b4c5ad 100644 +--- a/drivers/mmc/host/mvsdio.c ++++ b/drivers/mmc/host/mvsdio.c +@@ -19,18 +19,23 @@ + #include + #include + #include ++#include + #include ++#include ++#include + #include ++#include ++#include + + #include + #include +-#include ++#include + + #include "mvsdio.h" + + #define DRIVER_NAME "mvsdio" + +-static int maxfreq = MVSD_CLOCKRATE_MAX; ++static int maxfreq; + static int nodma; + + struct mvsd_host { +@@ -49,10 +54,7 @@ struct mvsd_host { + struct timer_list timer; + struct mmc_host *mmc; + struct device *dev; +- struct resource *res; +- int irq; +- int gpio_card_detect; +- int gpio_write_protect; ++ struct clk *clk; + }; + + #define mvsd_write(offs, val) writel(val, iobase + (offs)) +@@ -77,11 +79,11 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data) + unsigned long t = jiffies + HZ; + unsigned int hw_state, count = 0; + do { ++ hw_state = mvsd_read(MVSD_HW_STATE); + if (time_after(jiffies, t)) { + dev_warn(host->dev, "FIFO_EMPTY bit missing\n"); + break; + } +- hw_state = mvsd_read(MVSD_HW_STATE); + count++; + } while (!(hw_state & (1 << 13))); + dev_dbg(host->dev, "*** wait for FIFO_EMPTY bit " +@@ -117,10 +119,8 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data) + host->pio_size = data->blocks * data->blksz; + host->pio_ptr = sg_virt(data->sg); + if (!nodma) +- pr_debug("%s: fallback to PIO for data " +- "at 0x%p size %d\n", +- mmc_hostname(host->mmc), +- host->pio_ptr, host->pio_size); ++ dev_dbg(host->dev, "fallback to PIO for data at 0x%p size %d\n", ++ host->pio_ptr, host->pio_size); + return 1; + } else { + dma_addr_t phys_addr; +@@ -354,6 +354,20 @@ static irqreturn_t mvsd_irq(int irq, void *dev) + intr_status, mvsd_read(MVSD_NOR_INTR_EN), + mvsd_read(MVSD_HW_STATE)); + ++ /* ++ * It looks like, SDIO IP can issue one late, spurious irq ++ * although all irqs should be disabled. To work around this, ++ * bail out early, if we didn't expect any irqs to occur. ++ */ ++ if (!mvsd_read(MVSD_NOR_INTR_EN) && !mvsd_read(MVSD_ERR_INTR_EN)) { ++ dev_dbg(host->dev, "spurious irq detected intr 0x%04x intr_en 0x%04x erri 0x%04x erri_en 0x%04x\n", ++ mvsd_read(MVSD_NOR_INTR_STATUS), ++ mvsd_read(MVSD_NOR_INTR_EN), ++ mvsd_read(MVSD_ERR_INTR_STATUS), ++ mvsd_read(MVSD_ERR_INTR_EN)); ++ return IRQ_HANDLED; ++ } ++ + spin_lock(&host->lock); + + /* PIO handling, if needed. Messy business... */ +@@ -471,8 +485,8 @@ static irqreturn_t mvsd_irq(int irq, void *dev) + if (mrq->data) + err_status = mvsd_finish_data(host, mrq->data, err_status); + if (err_status) { +- pr_err("%s: unhandled error status %#04x\n", +- mmc_hostname(host->mmc), err_status); ++ dev_err(host->dev, "unhandled error status %#04x\n", ++ err_status); + cmd->error = -ENOMSG; + } + +@@ -489,9 +503,8 @@ static irqreturn_t mvsd_irq(int irq, void *dev) + if (irq_handled) + return IRQ_HANDLED; + +- pr_err("%s: unhandled interrupt status=0x%04x en=0x%04x " +- "pio=%d\n", mmc_hostname(host->mmc), intr_status, +- host->intr_en, host->pio_size); ++ dev_err(host->dev, "unhandled interrupt status=0x%04x en=0x%04x pio=%d\n", ++ intr_status, host->intr_en, host->pio_size); + return IRQ_NONE; + } + +@@ -505,13 +518,11 @@ static void mvsd_timeout_timer(unsigned long data) + spin_lock_irqsave(&host->lock, flags); + mrq = host->mrq; + if (mrq) { +- pr_err("%s: Timeout waiting for hardware interrupt.\n", +- mmc_hostname(host->mmc)); +- pr_err("%s: hw_state=0x%04x, intr_status=0x%04x " +- "intr_en=0x%04x\n", mmc_hostname(host->mmc), +- mvsd_read(MVSD_HW_STATE), +- mvsd_read(MVSD_NOR_INTR_STATUS), +- mvsd_read(MVSD_NOR_INTR_EN)); ++ dev_err(host->dev, "Timeout waiting for hardware interrupt.\n"); ++ dev_err(host->dev, "hw_state=0x%04x, intr_status=0x%04x intr_en=0x%04x\n", ++ mvsd_read(MVSD_HW_STATE), ++ mvsd_read(MVSD_NOR_INTR_STATUS), ++ mvsd_read(MVSD_NOR_INTR_EN)); + + host->mrq = NULL; + +@@ -538,13 +549,6 @@ static void mvsd_timeout_timer(unsigned long data) + mmc_request_done(host->mmc, mrq); + } + +-static irqreturn_t mvsd_card_detect_irq(int irq, void *dev) +-{ +- struct mvsd_host *host = dev; +- mmc_detect_change(host->mmc, msecs_to_jiffies(100)); +- return IRQ_HANDLED; +-} +- + static void mvsd_enable_sdio_irq(struct mmc_host *mmc, int enable) + { + struct mvsd_host *host = mmc_priv(mmc); +@@ -564,20 +568,6 @@ static void mvsd_enable_sdio_irq(struct mmc_host *mmc, int enable) + spin_unlock_irqrestore(&host->lock, flags); + } + +-static int mvsd_get_ro(struct mmc_host *mmc) +-{ +- struct mvsd_host *host = mmc_priv(mmc); +- +- if (host->gpio_write_protect) +- return gpio_get_value(host->gpio_write_protect); +- +- /* +- * Board doesn't support read only detection; let the mmc core +- * decide what to do. +- */ +- return -ENOSYS; +-} +- + static void mvsd_power_up(struct mvsd_host *host) + { + void __iomem *iobase = host->base; +@@ -674,13 +664,14 @@ static void mvsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + + static const struct mmc_host_ops mvsd_ops = { + .request = mvsd_request, +- .get_ro = mvsd_get_ro, ++ .get_ro = mmc_gpio_get_ro, + .set_ios = mvsd_set_ios, + .enable_sdio_irq = mvsd_enable_sdio_irq, + }; + +-static void __init mv_conf_mbus_windows(struct mvsd_host *host, +- struct mbus_dram_target_info *dram) ++static void ++mv_conf_mbus_windows(struct mvsd_host *host, ++ const struct mbus_dram_target_info *dram) + { + void __iomem *iobase = host->base; + int i; +@@ -691,7 +682,7 @@ static void __init mv_conf_mbus_windows(struct mvsd_host *host, + } + + for (i = 0; i < dram->num_cs; i++) { +- struct mbus_dram_window *cs = dram->cs + i; ++ const struct mbus_dram_window *cs = dram->cs + i; + writel(((cs->size - 1) & 0xffff0000) | + (cs->mbus_attr << 8) | + (dram->mbus_dram_target_id << 4) | 1, +@@ -700,24 +691,21 @@ static void __init mv_conf_mbus_windows(struct mvsd_host *host, + } + } + +-static int __init mvsd_probe(struct platform_device *pdev) ++static int mvsd_probe(struct platform_device *pdev) + { ++ struct device_node *np = pdev->dev.of_node; + struct mmc_host *mmc = NULL; + struct mvsd_host *host = NULL; +- const struct mvsdio_platform_data *mvsd_data; ++ const struct mbus_dram_target_info *dram; + struct resource *r; + int ret, irq; ++ struct pinctrl *pinctrl; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); +- mvsd_data = pdev->dev.platform_data; +- if (!r || irq < 0 || !mvsd_data) ++ if (!r || irq < 0) + return -ENXIO; + +- r = request_mem_region(r->start, SZ_1K, DRIVER_NAME); +- if (!r) +- return -EBUSY; +- + mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); + if (!mmc) { + ret = -ENOMEM; +@@ -727,17 +715,28 @@ static int __init mvsd_probe(struct platform_device *pdev) + host = mmc_priv(mmc); + host->mmc = mmc; + host->dev = &pdev->dev; +- host->res = r; +- host->base_clock = mvsd_data->clock / 2; ++ ++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev); ++ if (IS_ERR(pinctrl)) ++ dev_warn(&pdev->dev, "no pins associated\n"); ++ ++ /* ++ * Some non-DT platforms do not pass a clock, and the clock ++ * frequency is passed through platform_data. On DT platforms, ++ * a clock must always be passed, even if there is no gatable ++ * clock associated to the SDIO interface (it can simply be a ++ * fixed rate clock). ++ */ ++ host->clk = devm_clk_get(&pdev->dev, NULL); ++ if (!IS_ERR(host->clk)) ++ clk_prepare_enable(host->clk); + + mmc->ops = &mvsd_ops; + + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; +- mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ | +- MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; + + mmc->f_min = DIV_ROUND_UP(host->base_clock, MVSD_BASE_DIV_MAX); +- mmc->f_max = maxfreq; ++ mmc->f_max = MVSD_CLOCKRATE_MAX; + + mmc->max_blk_size = 2048; + mmc->max_blk_count = 65535; +@@ -746,54 +745,67 @@ static int __init mvsd_probe(struct platform_device *pdev) + mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count; + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + ++ if (np) { ++ if (IS_ERR(host->clk)) { ++ dev_err(&pdev->dev, "DT platforms must have a clock associated\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ host->base_clock = clk_get_rate(host->clk) / 2; ++ ret = mmc_of_parse(mmc); ++ if (ret < 0) ++ goto out; ++ } else { ++ const struct mvsdio_platform_data *mvsd_data; ++ ++ mvsd_data = pdev->dev.platform_data; ++ if (!mvsd_data) { ++ ret = -ENXIO; ++ goto out; ++ } ++ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ | ++ MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; ++ host->base_clock = mvsd_data->clock / 2; ++ /* GPIO 0 regarded as invalid for backward compatibility */ ++ if (mvsd_data->gpio_card_detect && ++ gpio_is_valid(mvsd_data->gpio_card_detect)) { ++ ret = mmc_gpio_request_cd(mmc, ++ mvsd_data->gpio_card_detect, ++ 0); ++ if (ret) ++ goto out; ++ } else { ++ mmc->caps |= MMC_CAP_NEEDS_POLL; ++ } ++ ++ if (mvsd_data->gpio_write_protect && ++ gpio_is_valid(mvsd_data->gpio_write_protect)) ++ mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect); ++ } ++ ++ if (maxfreq) ++ mmc->f_max = maxfreq; ++ + spin_lock_init(&host->lock); + +- host->base = ioremap(r->start, SZ_4K); +- if (!host->base) { +- ret = -ENOMEM; ++ host->base = devm_ioremap_resource(&pdev->dev, r); ++ if (IS_ERR(host->base)) { ++ ret = PTR_ERR(host->base); + goto out; + } + + /* (Re-)program MBUS remapping windows if we are asked to. */ +- if (mvsd_data->dram != NULL) +- mv_conf_mbus_windows(host, mvsd_data->dram); ++ dram = mv_mbus_dram_info(); ++ if (dram) ++ mv_conf_mbus_windows(host, dram); + + mvsd_power_down(host); + +- ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host); ++ ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host); + if (ret) { +- pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq); ++ dev_err(&pdev->dev, "cannot assign irq %d\n", irq); + goto out; +- } else +- host->irq = irq; +- +- if (mvsd_data->gpio_card_detect) { +- ret = gpio_request(mvsd_data->gpio_card_detect, +- DRIVER_NAME " cd"); +- if (ret == 0) { +- gpio_direction_input(mvsd_data->gpio_card_detect); +- irq = gpio_to_irq(mvsd_data->gpio_card_detect); +- ret = request_irq(irq, mvsd_card_detect_irq, +- IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING, +- DRIVER_NAME " cd", host); +- if (ret == 0) +- host->gpio_card_detect = +- mvsd_data->gpio_card_detect; +- else +- gpio_free(mvsd_data->gpio_card_detect); +- } +- } +- if (!host->gpio_card_detect) +- mmc->caps |= MMC_CAP_NEEDS_POLL; +- +- if (mvsd_data->gpio_write_protect) { +- ret = gpio_request(mvsd_data->gpio_write_protect, +- DRIVER_NAME " wp"); +- if (ret == 0) { +- gpio_direction_input(mvsd_data->gpio_write_protect); +- host->gpio_write_protect = +- mvsd_data->gpio_write_protect; +- } + } + + setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host); +@@ -802,109 +814,60 @@ static int __init mvsd_probe(struct platform_device *pdev) + if (ret) + goto out; + +- pr_notice("%s: %s driver initialized, ", +- mmc_hostname(mmc), DRIVER_NAME); +- if (host->gpio_card_detect) +- printk("using GPIO %d for card detection\n", +- host->gpio_card_detect); ++ if (!(mmc->caps & MMC_CAP_NEEDS_POLL)) ++ dev_dbg(&pdev->dev, "using GPIO for card detection\n"); + else +- printk("lacking card detect (fall back to polling)\n"); ++ dev_dbg(&pdev->dev, "lacking card detect (fall back to polling)\n"); ++ + return 0; + + out: +- if (host) { +- if (host->irq) +- free_irq(host->irq, host); +- if (host->gpio_card_detect) { +- free_irq(gpio_to_irq(host->gpio_card_detect), host); +- gpio_free(host->gpio_card_detect); +- } +- if (host->gpio_write_protect) +- gpio_free(host->gpio_write_protect); +- if (host->base) +- iounmap(host->base); +- } +- if (r) +- release_resource(r); +- if (mmc) ++ if (mmc) { ++ mmc_gpio_free_cd(mmc); ++ mmc_gpio_free_ro(mmc); ++ if (!IS_ERR(host->clk)) ++ clk_disable_unprepare(host->clk); + mmc_free_host(mmc); ++ } + + return ret; + } + +-static int __exit mvsd_remove(struct platform_device *pdev) ++static int mvsd_remove(struct platform_device *pdev) + { + struct mmc_host *mmc = platform_get_drvdata(pdev); + +- if (mmc) { +- struct mvsd_host *host = mmc_priv(mmc); +- +- if (host->gpio_card_detect) { +- free_irq(gpio_to_irq(host->gpio_card_detect), host); +- gpio_free(host->gpio_card_detect); +- } +- mmc_remove_host(mmc); +- free_irq(host->irq, host); +- if (host->gpio_write_protect) +- gpio_free(host->gpio_write_protect); +- del_timer_sync(&host->timer); +- mvsd_power_down(host); +- iounmap(host->base); +- release_resource(host->res); +- mmc_free_host(mmc); +- } +- platform_set_drvdata(pdev, NULL); +- return 0; +-} ++ struct mvsd_host *host = mmc_priv(mmc); + +-#ifdef CONFIG_PM +-static int mvsd_suspend(struct platform_device *dev, pm_message_t state) +-{ +- struct mmc_host *mmc = platform_get_drvdata(dev); +- int ret = 0; ++ mmc_gpio_free_cd(mmc); ++ mmc_gpio_free_ro(mmc); ++ mmc_remove_host(mmc); ++ del_timer_sync(&host->timer); ++ mvsd_power_down(host); + +- if (mmc) +- ret = mmc_suspend_host(mmc); ++ if (!IS_ERR(host->clk)) ++ clk_disable_unprepare(host->clk); ++ mmc_free_host(mmc); + +- return ret; ++ return 0; + } + +-static int mvsd_resume(struct platform_device *dev) +-{ +- struct mmc_host *mmc = platform_get_drvdata(dev); +- int ret = 0; +- +- if (mmc) +- ret = mmc_resume_host(mmc); +- +- return ret; +-} +-#else +-#define mvsd_suspend NULL +-#define mvsd_resume NULL +-#endif ++static const struct of_device_id mvsdio_dt_ids[] = { ++ { .compatible = "marvell,orion-sdio" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, mvsdio_dt_ids); + + static struct platform_driver mvsd_driver = { +- .remove = __exit_p(mvsd_remove), +- .suspend = mvsd_suspend, +- .resume = mvsd_resume, ++ .probe = mvsd_probe, ++ .remove = mvsd_remove, + .driver = { + .name = DRIVER_NAME, ++ .of_match_table = mvsdio_dt_ids, + }, + }; + +-static int __init mvsd_init(void) +-{ +- return platform_driver_probe(&mvsd_driver, mvsd_probe); +-} +- +-static void __exit mvsd_exit(void) +-{ +- platform_driver_unregister(&mvsd_driver); +-} +- +-module_init(mvsd_init); +-module_exit(mvsd_exit); ++module_platform_driver(mvsd_driver); + + /* maximum card clock frequency (default 50MHz) */ + module_param(maxfreq, int, 0); +diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c +index 8e0fbe9..ed1cb93 100644 +--- a/drivers/mmc/host/mxcmmc.c ++++ b/drivers/mmc/host/mxcmmc.c +@@ -33,16 +33,21 @@ + #include + #include + #include ++#include ++#include ++#include ++#include ++#include ++#include + + #include + #include +-#include +-#include ++#include + +-#include +-#include ++#include + + #define DRIVER_NAME "mxc-mmc" ++#define MXCMCI_TIMEOUT_MS 10000 + + #define MMC_REG_STR_STP_CLK 0x00 + #define MMC_REG_STATUS 0x04 +@@ -111,11 +116,16 @@ + #define INT_WRITE_OP_DONE_EN (1 << 1) + #define INT_READ_OP_EN (1 << 0) + ++enum mxcmci_type { ++ IMX21_MMC, ++ IMX31_MMC, ++ MPC512X_MMC, ++}; ++ + struct mxcmci_host { + struct mmc_host *mmc; +- struct resource *res; + void __iomem *base; +- int irq; ++ dma_addr_t phys_base; + int detect_irq; + struct dma_chan *dma; + struct dma_async_tx_descriptor *desc; +@@ -135,54 +145,108 @@ struct mxcmci_host { + u16 rev_no; + unsigned int cmdat; + +- struct clk *clk; ++ struct clk *clk_ipg; ++ struct clk *clk_per; + + int clock; + + struct work_struct datawork; + spinlock_t lock; + +- struct regulator *vcc; +- + int burstlen; + int dmareq; + struct dma_slave_config dma_slave_config; + struct imx_dma_data dma_data; ++ ++ struct timer_list watchdog; ++ enum mxcmci_type devtype; + }; + +-static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); ++static const struct platform_device_id mxcmci_devtype[] = { ++ { ++ .name = "imx21-mmc", ++ .driver_data = IMX21_MMC, ++ }, { ++ .name = "imx31-mmc", ++ .driver_data = IMX31_MMC, ++ }, { ++ .name = "mpc512x-sdhc", ++ .driver_data = MPC512X_MMC, ++ }, { ++ /* sentinel */ ++ } ++}; ++MODULE_DEVICE_TABLE(platform, mxcmci_devtype); ++ ++static const struct of_device_id mxcmci_of_match[] = { ++ { ++ .compatible = "fsl,imx21-mmc", ++ .data = &mxcmci_devtype[IMX21_MMC], ++ }, { ++ .compatible = "fsl,imx31-mmc", ++ .data = &mxcmci_devtype[IMX31_MMC], ++ }, { ++ .compatible = "fsl,mpc5121-sdhc", ++ .data = &mxcmci_devtype[MPC512X_MMC], ++ }, { ++ /* sentinel */ ++ } ++}; ++MODULE_DEVICE_TABLE(of, mxcmci_of_match); + +-static inline void mxcmci_init_ocr(struct mxcmci_host *host) ++static inline int is_imx31_mmc(struct mxcmci_host *host) + { +- host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc"); ++ return host->devtype == IMX31_MMC; ++} + +- if (IS_ERR(host->vcc)) { +- host->vcc = NULL; +- } else { +- host->mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vcc); +- if (host->pdata && host->pdata->ocr_avail) +- dev_warn(mmc_dev(host->mmc), +- "pdata->ocr_avail will not be used\n"); +- } ++static inline int is_mpc512x_mmc(struct mxcmci_host *host) ++{ ++ return host->devtype == MPC512X_MMC; ++} + +- if (host->vcc == NULL) { +- /* fall-back to platform data */ +- if (host->pdata && host->pdata->ocr_avail) +- host->mmc->ocr_avail = host->pdata->ocr_avail; +- else +- host->mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; +- } ++static inline u32 mxcmci_readl(struct mxcmci_host *host, int reg) ++{ ++ if (IS_ENABLED(CONFIG_PPC_MPC512x)) ++ return ioread32be(host->base + reg); ++ else ++ return readl(host->base + reg); + } + +-static inline void mxcmci_set_power(struct mxcmci_host *host, +- unsigned char power_mode, +- unsigned int vdd) ++static inline void mxcmci_writel(struct mxcmci_host *host, u32 val, int reg) + { +- if (host->vcc) { +- if (power_mode == MMC_POWER_UP) +- mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); +- else if (power_mode == MMC_POWER_OFF) +- mmc_regulator_set_ocr(host->mmc, host->vcc, 0); ++ if (IS_ENABLED(CONFIG_PPC_MPC512x)) ++ iowrite32be(val, host->base + reg); ++ else ++ writel(val, host->base + reg); ++} ++ ++static inline u16 mxcmci_readw(struct mxcmci_host *host, int reg) ++{ ++ if (IS_ENABLED(CONFIG_PPC_MPC512x)) ++ return ioread32be(host->base + reg); ++ else ++ return readw(host->base + reg); ++} ++ ++static inline void mxcmci_writew(struct mxcmci_host *host, u16 val, int reg) ++{ ++ if (IS_ENABLED(CONFIG_PPC_MPC512x)) ++ iowrite32be(val, host->base + reg); ++ else ++ writew(val, host->base + reg); ++} ++ ++static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); ++ ++static void mxcmci_set_power(struct mxcmci_host *host, unsigned int vdd) ++{ ++ if (!IS_ERR(host->mmc->supply.vmmc)) { ++ if (host->power_mode == MMC_POWER_UP) ++ mmc_regulator_set_ocr(host->mmc, ++ host->mmc->supply.vmmc, vdd); ++ else if (host->power_mode == MMC_POWER_OFF) ++ mmc_regulator_set_ocr(host->mmc, ++ host->mmc->supply.vmmc, 0); + } + + if (host->pdata && host->pdata->setpower) +@@ -201,16 +265,38 @@ static void mxcmci_softreset(struct mxcmci_host *host) + dev_dbg(mmc_dev(host->mmc), "mxcmci_softreset\n"); + + /* reset sequence */ +- writew(STR_STP_CLK_RESET, host->base + MMC_REG_STR_STP_CLK); +- writew(STR_STP_CLK_RESET | STR_STP_CLK_START_CLK, +- host->base + MMC_REG_STR_STP_CLK); ++ mxcmci_writew(host, STR_STP_CLK_RESET, MMC_REG_STR_STP_CLK); ++ mxcmci_writew(host, STR_STP_CLK_RESET | STR_STP_CLK_START_CLK, ++ MMC_REG_STR_STP_CLK); + + for (i = 0; i < 8; i++) +- writew(STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK); ++ mxcmci_writew(host, STR_STP_CLK_START_CLK, MMC_REG_STR_STP_CLK); ++ ++ mxcmci_writew(host, 0xff, MMC_REG_RES_TO); ++} ++ ++#if IS_ENABLED(CONFIG_PPC_MPC512x) ++static inline void buffer_swap32(u32 *buf, int len) ++{ ++ int i; + +- writew(0xff, host->base + MMC_REG_RES_TO); ++ for (i = 0; i < ((len + 3) / 4); i++) { ++ st_le32(buf, *buf); ++ buf++; ++ } ++} ++ ++static void mxcmci_swap_buffers(struct mmc_data *data) ++{ ++ struct scatterlist *sg; ++ int i; ++ ++ for_each_sg(data->sg, sg, data->sg_len, i) ++ buffer_swap32(sg_virt(sg), sg->length); + } +-static int mxcmci_setup_dma(struct mmc_host *mmc); ++#else ++static inline void mxcmci_swap_buffers(struct mmc_data *data) {} ++#endif + + static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) + { +@@ -218,6 +304,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) + unsigned int blksz = data->blksz; + unsigned int datasize = nob * blksz; + struct scatterlist *sg; ++ enum dma_transfer_direction slave_dirn; + int i, nents; + + if (data->flags & MMC_DATA_STREAM) +@@ -226,32 +313,37 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) + host->data = data; + data->bytes_xfered = 0; + +- writew(nob, host->base + MMC_REG_NOB); +- writew(blksz, host->base + MMC_REG_BLK_LEN); ++ mxcmci_writew(host, nob, MMC_REG_NOB); ++ mxcmci_writew(host, blksz, MMC_REG_BLK_LEN); + host->datasize = datasize; + + if (!mxcmci_use_dma(host)) + return 0; + + for_each_sg(data->sg, sg, data->sg_len, i) { +- if (sg->offset & 3 || sg->length & 3) { ++ if (sg->offset & 3 || sg->length & 3 || sg->length < 512) { + host->do_dma = 0; + return 0; + } + } + +- if (data->flags & MMC_DATA_READ) ++ if (data->flags & MMC_DATA_READ) { + host->dma_dir = DMA_FROM_DEVICE; +- else ++ slave_dirn = DMA_DEV_TO_MEM; ++ } else { + host->dma_dir = DMA_TO_DEVICE; ++ slave_dirn = DMA_MEM_TO_DEV; ++ ++ mxcmci_swap_buffers(data); ++ } + + nents = dma_map_sg(host->dma->device->dev, data->sg, + data->sg_len, host->dma_dir); + if (nents != data->sg_len) + return -EINVAL; + +- host->desc = host->dma->device->device_prep_slave_sg(host->dma, +- data->sg, data->sg_len, host->dma_dir, ++ host->desc = dmaengine_prep_slave_sg(host->dma, ++ data->sg, data->sg_len, slave_dirn, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + + if (!host->desc) { +@@ -263,10 +355,34 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) + wmb(); + + dmaengine_submit(host->desc); ++ dma_async_issue_pending(host->dma); ++ ++ mod_timer(&host->watchdog, jiffies + msecs_to_jiffies(MXCMCI_TIMEOUT_MS)); + + return 0; + } + ++static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat); ++static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat); ++ ++static void mxcmci_dma_callback(void *data) ++{ ++ struct mxcmci_host *host = data; ++ u32 stat; ++ ++ del_timer(&host->watchdog); ++ ++ stat = mxcmci_readl(host, MMC_REG_STATUS); ++ mxcmci_writel(host, stat & ~STATUS_DATA_TRANS_DONE, MMC_REG_STATUS); ++ ++ dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); ++ ++ if (stat & STATUS_READ_OP_DONE) ++ mxcmci_writel(host, STATUS_READ_OP_DONE, MMC_REG_STATUS); ++ ++ mxcmci_data_done(host, stat); ++} ++ + static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, + unsigned int cmdat) + { +@@ -298,18 +414,24 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, + + int_cntr = INT_END_CMD_RES_EN; + +- if (mxcmci_use_dma(host)) +- int_cntr |= INT_READ_OP_EN | INT_WRITE_OP_DONE_EN; ++ if (mxcmci_use_dma(host)) { ++ if (host->dma_dir == DMA_FROM_DEVICE) { ++ host->desc->callback = mxcmci_dma_callback; ++ host->desc->callback_param = host; ++ } else { ++ int_cntr |= INT_WRITE_OP_DONE_EN; ++ } ++ } + + spin_lock_irqsave(&host->lock, flags); + if (host->use_sdio) + int_cntr |= INT_SDIO_IRQ_EN; +- writel(int_cntr, host->base + MMC_REG_INT_CNTR); ++ mxcmci_writel(host, int_cntr, MMC_REG_INT_CNTR); + spin_unlock_irqrestore(&host->lock, flags); + +- writew(cmd->opcode, host->base + MMC_REG_CMD); +- writel(cmd->arg, host->base + MMC_REG_ARG); +- writew(cmdat, host->base + MMC_REG_CMD_DAT_CONT); ++ mxcmci_writew(host, cmd->opcode, MMC_REG_CMD); ++ mxcmci_writel(host, cmd->arg, MMC_REG_ARG); ++ mxcmci_writew(host, cmdat, MMC_REG_CMD_DAT_CONT); + + return 0; + } +@@ -323,7 +445,7 @@ static void mxcmci_finish_request(struct mxcmci_host *host, + spin_lock_irqsave(&host->lock, flags); + if (host->use_sdio) + int_cntr |= INT_SDIO_IRQ_EN; +- writel(int_cntr, host->base + MMC_REG_INT_CNTR); ++ mxcmci_writel(host, int_cntr, MMC_REG_INT_CNTR); + spin_unlock_irqrestore(&host->lock, flags); + + host->req = NULL; +@@ -339,9 +461,9 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat) + int data_error; + + if (mxcmci_use_dma(host)) { +- dmaengine_terminate_all(host->dma); + dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, + host->dma_dir); ++ mxcmci_swap_buffers(data); + } + + if (stat & STATUS_ERR_MASK) { +@@ -400,14 +522,14 @@ static void mxcmci_read_response(struct mxcmci_host *host, unsigned int stat) + if (cmd->flags & MMC_RSP_PRESENT) { + if (cmd->flags & MMC_RSP_136) { + for (i = 0; i < 4; i++) { +- a = readw(host->base + MMC_REG_RES_FIFO); +- b = readw(host->base + MMC_REG_RES_FIFO); ++ a = mxcmci_readw(host, MMC_REG_RES_FIFO); ++ b = mxcmci_readw(host, MMC_REG_RES_FIFO); + cmd->resp[i] = a << 16 | b; + } + } else { +- a = readw(host->base + MMC_REG_RES_FIFO); +- b = readw(host->base + MMC_REG_RES_FIFO); +- c = readw(host->base + MMC_REG_RES_FIFO); ++ a = mxcmci_readw(host, MMC_REG_RES_FIFO); ++ b = mxcmci_readw(host, MMC_REG_RES_FIFO); ++ c = mxcmci_readw(host, MMC_REG_RES_FIFO); + cmd->resp[0] = a << 24 | b << 8 | c >> 8; + } + } +@@ -419,7 +541,7 @@ static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask) + unsigned long timeout = jiffies + HZ; + + do { +- stat = readl(host->base + MMC_REG_STATUS); ++ stat = mxcmci_readl(host, MMC_REG_STATUS); + if (stat & STATUS_ERR_MASK) + return stat; + if (time_after(jiffies, timeout)) { +@@ -443,7 +565,7 @@ static int mxcmci_pull(struct mxcmci_host *host, void *_buf, int bytes) + STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE); + if (stat) + return stat; +- *buf++ = readl(host->base + MMC_REG_BUFFER_ACCESS); ++ *buf++ = cpu_to_le32(mxcmci_readl(host, MMC_REG_BUFFER_ACCESS)); + bytes -= 4; + } + +@@ -455,7 +577,7 @@ static int mxcmci_pull(struct mxcmci_host *host, void *_buf, int bytes) + STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE); + if (stat) + return stat; +- tmp = readl(host->base + MMC_REG_BUFFER_ACCESS); ++ tmp = cpu_to_le32(mxcmci_readl(host, MMC_REG_BUFFER_ACCESS)); + memcpy(b, &tmp, bytes); + } + +@@ -471,7 +593,7 @@ static int mxcmci_push(struct mxcmci_host *host, void *_buf, int bytes) + stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); + if (stat) + return stat; +- writel(*buf++, host->base + MMC_REG_BUFFER_ACCESS); ++ mxcmci_writel(host, cpu_to_le32(*buf++), MMC_REG_BUFFER_ACCESS); + bytes -= 4; + } + +@@ -484,7 +606,7 @@ static int mxcmci_push(struct mxcmci_host *host, void *_buf, int bytes) + return stat; + + memcpy(&tmp, b, bytes); +- writel(tmp, host->base + MMC_REG_BUFFER_ACCESS); ++ mxcmci_writel(host, cpu_to_le32(tmp), MMC_REG_BUFFER_ACCESS); + } + + stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); +@@ -530,8 +652,8 @@ static void mxcmci_datawork(struct work_struct *work) + datawork); + int datastat = mxcmci_transfer_data(host); + +- writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, +- host->base + MMC_REG_STATUS); ++ mxcmci_writel(host, STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, ++ MMC_REG_STATUS); + mxcmci_finish_data(host, datastat); + + if (host->req->stop) { +@@ -546,24 +668,40 @@ static void mxcmci_datawork(struct work_struct *work) + + static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat) + { +- struct mmc_data *data = host->data; ++ struct mmc_request *req; + int data_error; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ if (!host->data) { ++ spin_unlock_irqrestore(&host->lock, flags); ++ return; ++ } + +- if (!data) ++ if (!host->req) { ++ spin_unlock_irqrestore(&host->lock, flags); + return; ++ } ++ ++ req = host->req; ++ if (!req->stop) ++ host->req = NULL; /* we will handle finish req below */ + + data_error = mxcmci_finish_data(host, stat); + ++ spin_unlock_irqrestore(&host->lock, flags); ++ + mxcmci_read_response(host, stat); + host->cmd = NULL; + +- if (host->req->stop) { +- if (mxcmci_start_cmd(host, host->req->stop, 0)) { +- mxcmci_finish_request(host, host->req); ++ if (req->stop) { ++ if (mxcmci_start_cmd(host, req->stop, 0)) { ++ mxcmci_finish_request(host, req); + return; + } + } else { +- mxcmci_finish_request(host, host->req); ++ mxcmci_finish_request(host, req); + } + } + +@@ -593,9 +731,11 @@ static irqreturn_t mxcmci_irq(int irq, void *devid) + bool sdio_irq; + u32 stat; + +- stat = readl(host->base + MMC_REG_STATUS); +- writel(stat & ~(STATUS_SDIO_INT_ACTIVE | STATUS_DATA_TRANS_DONE | +- STATUS_WRITE_OP_DONE), host->base + MMC_REG_STATUS); ++ stat = mxcmci_readl(host, MMC_REG_STATUS); ++ mxcmci_writel(host, ++ stat & ~(STATUS_SDIO_INT_ACTIVE | STATUS_DATA_TRANS_DONE | ++ STATUS_WRITE_OP_DONE), ++ MMC_REG_STATUS); + + dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); + +@@ -605,11 +745,11 @@ static irqreturn_t mxcmci_irq(int irq, void *devid) + + if (mxcmci_use_dma(host) && + (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE))) +- writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, +- host->base + MMC_REG_STATUS); ++ mxcmci_writel(host, STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, ++ MMC_REG_STATUS); + + if (sdio_irq) { +- writel(STATUS_SDIO_INT_ACTIVE, host->base + MMC_REG_STATUS); ++ mxcmci_writel(host, STATUS_SDIO_INT_ACTIVE, MMC_REG_STATUS); + mmc_signal_sdio_irq(host->mmc); + } + +@@ -617,8 +757,10 @@ static irqreturn_t mxcmci_irq(int irq, void *devid) + mxcmci_cmd_done(host, stat); + + if (mxcmci_use_dma(host) && +- (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) ++ (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) { ++ del_timer(&host->watchdog); + mxcmci_data_done(host, stat); ++ } + + if (host->default_irq_mask && + (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL))) +@@ -666,7 +808,7 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios) + { + unsigned int divider; + int prescaler = 0; +- unsigned int clk_in = clk_get_rate(host->clk); ++ unsigned int clk_in = clk_get_rate(host->clk_per); + + while (prescaler <= 0x800) { + for (divider = 1; divider <= 0xF; divider++) { +@@ -689,7 +831,7 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios) + prescaler <<= 1; + } + +- writew((prescaler << 4) | divider, host->base + MMC_REG_CLK_RATE); ++ mxcmci_writew(host, (prescaler << 4) | divider, MMC_REG_CLK_RATE); + + dev_dbg(mmc_dev(host->mmc), "scaler: %d divider: %d in: %d out: %d\n", + prescaler, divider, clk_in, clk_ios); +@@ -700,12 +842,13 @@ static int mxcmci_setup_dma(struct mmc_host *mmc) + struct mxcmci_host *host = mmc_priv(mmc); + struct dma_slave_config *config = &host->dma_slave_config; + +- config->dst_addr = host->res->start + MMC_REG_BUFFER_ACCESS; +- config->src_addr = host->res->start + MMC_REG_BUFFER_ACCESS; ++ config->dst_addr = host->phys_base + MMC_REG_BUFFER_ACCESS; ++ config->src_addr = host->phys_base + MMC_REG_BUFFER_ACCESS; + config->dst_addr_width = 4; + config->src_addr_width = 4; + config->dst_maxburst = host->burstlen; + config->src_maxburst = host->burstlen; ++ config->device_fc = false; + + return dmaengine_slave_config(host->dma, config); + } +@@ -742,8 +885,8 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4; + + if (host->power_mode != ios->power_mode) { +- mxcmci_set_power(host, ios->power_mode, ios->vdd); + host->power_mode = ios->power_mode; ++ mxcmci_set_power(host, ios->vdd); + + if (ios->power_mode == MMC_POWER_ON) + host->cmdat |= CMD_DAT_CONT_INIT; +@@ -751,9 +894,9 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + + if (ios->clock) { + mxcmci_set_clk_rate(host, ios->clock); +- writew(STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK); ++ mxcmci_writew(host, STR_STP_CLK_START_CLK, MMC_REG_STR_STP_CLK); + } else { +- writew(STR_STP_CLK_STOP_CLK, host->base + MMC_REG_STR_STP_CLK); ++ mxcmci_writew(host, STR_STP_CLK_STOP_CLK, MMC_REG_STR_STP_CLK); + } + + host->clock = ios->clock; +@@ -776,10 +919,11 @@ static int mxcmci_get_ro(struct mmc_host *mmc) + if (host->pdata && host->pdata->get_ro) + return !!host->pdata->get_ro(mmc_dev(mmc)); + /* +- * Board doesn't support read only detection; let the mmc core +- * decide what to do. ++ * If board doesn't support read only detection (no mmc_gpio ++ * context or gpio is invalid), then let the mmc core decide ++ * what to do. + */ +- return -ENOSYS; ++ return mmc_gpio_get_ro(mmc); + } + + static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable) +@@ -790,19 +934,21 @@ static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable) + + spin_lock_irqsave(&host->lock, flags); + host->use_sdio = enable; +- int_cntr = readl(host->base + MMC_REG_INT_CNTR); ++ int_cntr = mxcmci_readl(host, MMC_REG_INT_CNTR); + + if (enable) + int_cntr |= INT_SDIO_IRQ_EN; + else + int_cntr &= ~INT_SDIO_IRQ_EN; + +- writel(int_cntr, host->base + MMC_REG_INT_CNTR); ++ mxcmci_writel(host, int_cntr, MMC_REG_INT_CNTR); + spin_unlock_irqrestore(&host->lock, flags); + } + + static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card) + { ++ struct mxcmci_host *mxcmci = mmc_priv(host); ++ + /* + * MX3 SoCs have a silicon bug which corrupts CRC calculation of + * multi-block transfers when connected SDIO peripheral doesn't +@@ -810,7 +956,7 @@ static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card) + * One way to prevent this is to only allow 1-bit transfers. + */ + +- if (cpu_is_mx3() && card->type == MMC_TYPE_SDIO) ++ if (is_imx31_mmc(mxcmci) && card->type == MMC_TYPE_SDIO) + host->caps &= ~MMC_CAP_4_BIT_DATA; + else + host->caps |= MMC_CAP_4_BIT_DATA; +@@ -828,6 +974,35 @@ static bool filter(struct dma_chan *chan, void *param) + return true; + } + ++static void mxcmci_watchdog(unsigned long data) ++{ ++ struct mmc_host *mmc = (struct mmc_host *)data; ++ struct mxcmci_host *host = mmc_priv(mmc); ++ struct mmc_request *req = host->req; ++ unsigned int stat = mxcmci_readl(host, MMC_REG_STATUS); ++ ++ if (host->dma_dir == DMA_FROM_DEVICE) { ++ dmaengine_terminate_all(host->dma); ++ dev_err(mmc_dev(host->mmc), ++ "%s: read time out (status = 0x%08x)\n", ++ __func__, stat); ++ } else { ++ dev_err(mmc_dev(host->mmc), ++ "%s: write time out (status = 0x%08x)\n", ++ __func__, stat); ++ mxcmci_softreset(host); ++ } ++ ++ /* Mark transfer as erroneus and inform the upper layers */ ++ ++ if (host->data) ++ host->data->error = -ETIMEDOUT; ++ host->req = NULL; ++ host->cmd = NULL; ++ host->data = NULL; ++ mmc_request_done(host->mmc, req); ++} ++ + static const struct mmc_host_ops mxcmci_ops = { + .request = mxcmci_request, + .set_ios = mxcmci_set_ios, +@@ -839,70 +1014,108 @@ static const struct mmc_host_ops mxcmci_ops = { + static int mxcmci_probe(struct platform_device *pdev) + { + struct mmc_host *mmc; +- struct mxcmci_host *host = NULL; +- struct resource *iores, *r; ++ struct mxcmci_host *host; ++ struct resource *res; + int ret = 0, irq; ++ bool dat3_card_detect = false; + dma_cap_mask_t mask; ++ const struct of_device_id *of_id; ++ struct imxmmc_platform_data *pdata = pdev->dev.platform_data; ++ ++ pr_info("i.MX/MPC512x SDHC driver\n"); + +- pr_info("i.MX SDHC driver\n"); ++ of_id = of_match_device(mxcmci_of_match, &pdev->dev); + +- iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); +- if (!iores || irq < 0) ++ if (irq < 0) + return -EINVAL; + +- r = request_mem_region(iores->start, resource_size(iores), pdev->name); +- if (!r) +- return -EBUSY; ++ mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); ++ if (!mmc) ++ return -ENOMEM; ++ ++ host = mmc_priv(mmc); + +- mmc = mmc_alloc_host(sizeof(struct mxcmci_host), &pdev->dev); +- if (!mmc) { +- ret = -ENOMEM; +- goto out_release_mem; ++ host->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(host->base)) { ++ ret = PTR_ERR(host->base); ++ goto out_free; + } + ++ host->phys_base = res->start; ++ ++ ret = mmc_of_parse(mmc); ++ if (ret) ++ goto out_free; + mmc->ops = &mxcmci_ops; +- mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; ++ ++ /* For devicetree parsing, the bus width is read from devicetree */ ++ if (pdata) ++ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; ++ else ++ mmc->caps |= MMC_CAP_SDIO_IRQ; + + /* MMC core transfer sizes tunable parameters */ +- mmc->max_segs = 64; + mmc->max_blk_size = 2048; + mmc->max_blk_count = 65535; + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + mmc->max_seg_size = mmc->max_req_size; + +- host = mmc_priv(mmc); +- host->base = ioremap(r->start, resource_size(r)); +- if (!host->base) { +- ret = -ENOMEM; +- goto out_free; ++ if (of_id) { ++ const struct platform_device_id *id_entry = of_id->data; ++ host->devtype = id_entry->driver_data; ++ } else { ++ host->devtype = pdev->id_entry->driver_data; + } + ++ /* adjust max_segs after devtype detection */ ++ if (!is_mpc512x_mmc(host)) ++ mmc->max_segs = 64; ++ + host->mmc = mmc; +- host->pdata = pdev->dev.platform_data; ++ host->pdata = pdata; + spin_lock_init(&host->lock); + +- mxcmci_init_ocr(host); ++ if (pdata) ++ dat3_card_detect = pdata->dat3_card_detect; ++ else if (!(mmc->caps & MMC_CAP_NONREMOVABLE) ++ && !of_property_read_bool(pdev->dev.of_node, "cd-gpios")) ++ dat3_card_detect = true; ++ ++ ret = mmc_regulator_get_supply(mmc); ++ if (ret) { ++ if (pdata && ret != -EPROBE_DEFER) ++ mmc->ocr_avail = pdata->ocr_avail ? : ++ MMC_VDD_32_33 | MMC_VDD_33_34; ++ else ++ goto out_free; ++ } + +- if (host->pdata && host->pdata->dat3_card_detect) ++ if (dat3_card_detect) + host->default_irq_mask = + INT_CARD_INSERTION_EN | INT_CARD_REMOVAL_EN; + else + host->default_irq_mask = 0; + +- host->res = r; +- host->irq = irq; ++ host->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); ++ if (IS_ERR(host->clk_ipg)) { ++ ret = PTR_ERR(host->clk_ipg); ++ goto out_free; ++ } + +- host->clk = clk_get(&pdev->dev, NULL); +- if (IS_ERR(host->clk)) { +- ret = PTR_ERR(host->clk); +- goto out_iounmap; ++ host->clk_per = devm_clk_get(&pdev->dev, "per"); ++ if (IS_ERR(host->clk_per)) { ++ ret = PTR_ERR(host->clk_per); ++ goto out_free; + } +- clk_enable(host->clk); ++ ++ clk_prepare_enable(host->clk_per); ++ clk_prepare_enable(host->clk_ipg); + + mxcmci_softreset(host); + +- host->rev_no = readw(host->base + MMC_REG_REV_NO); ++ host->rev_no = mxcmci_readw(host, MMC_REG_REV_NO); + if (host->rev_no != 0x400) { + ret = -ENODEV; + dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n", +@@ -910,34 +1123,38 @@ static int mxcmci_probe(struct platform_device *pdev) + goto out_clk_put; + } + +- mmc->f_min = clk_get_rate(host->clk) >> 16; +- mmc->f_max = clk_get_rate(host->clk) >> 1; ++ mmc->f_min = clk_get_rate(host->clk_per) >> 16; ++ mmc->f_max = clk_get_rate(host->clk_per) >> 1; + + /* recommended in data sheet */ +- writew(0x2db4, host->base + MMC_REG_READ_TO); +- +- writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR); +- +- r = platform_get_resource(pdev, IORESOURCE_DMA, 0); +- if (r) { +- host->dmareq = r->start; +- host->dma_data.peripheral_type = IMX_DMATYPE_SDHC; +- host->dma_data.priority = DMA_PRIO_LOW; +- host->dma_data.dma_request = host->dmareq; +- dma_cap_zero(mask); +- dma_cap_set(DMA_SLAVE, mask); +- host->dma = dma_request_channel(mask, filter, host); +- if (host->dma) +- mmc->max_seg_size = dma_get_max_seg_size( +- host->dma->device->dev); +- } ++ mxcmci_writew(host, 0x2db4, MMC_REG_READ_TO); + +- if (!host->dma) ++ mxcmci_writel(host, host->default_irq_mask, MMC_REG_INT_CNTR); ++ ++ if (!host->pdata) { ++ host->dma = dma_request_slave_channel(&pdev->dev, "rx-tx"); ++ } else { ++ res = platform_get_resource(pdev, IORESOURCE_DMA, 0); ++ if (res) { ++ host->dmareq = res->start; ++ host->dma_data.peripheral_type = IMX_DMATYPE_SDHC; ++ host->dma_data.priority = DMA_PRIO_LOW; ++ host->dma_data.dma_request = host->dmareq; ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ host->dma = dma_request_channel(mask, filter, host); ++ } ++ } ++ if (host->dma) ++ mmc->max_seg_size = dma_get_max_seg_size( ++ host->dma->device->dev); ++ else + dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n"); + + INIT_WORK(&host->datawork, mxcmci_datawork); + +- ret = request_irq(host->irq, mxcmci_irq, 0, DRIVER_NAME, host); ++ ret = devm_request_irq(&pdev->dev, irq, mxcmci_irq, 0, ++ dev_name(&pdev->dev), host); + if (ret) + goto out_free_dma; + +@@ -947,27 +1164,28 @@ static int mxcmci_probe(struct platform_device *pdev) + ret = host->pdata->init(&pdev->dev, mxcmci_detect_irq, + host->mmc); + if (ret) +- goto out_free_irq; ++ goto out_free_dma; + } + ++ init_timer(&host->watchdog); ++ host->watchdog.function = &mxcmci_watchdog; ++ host->watchdog.data = (unsigned long)mmc; ++ + mmc_add_host(mmc); + + return 0; + +-out_free_irq: +- free_irq(host->irq, host); + out_free_dma: + if (host->dma) + dma_release_channel(host->dma); ++ + out_clk_put: +- clk_disable(host->clk); +- clk_put(host->clk); +-out_iounmap: +- iounmap(host->base); ++ clk_disable_unprepare(host->clk_per); ++ clk_disable_unprepare(host->clk_ipg); ++ + out_free: + mmc_free_host(mmc); +-out_release_mem: +- release_mem_region(iores->start, resource_size(iores)); ++ + return ret; + } + +@@ -976,91 +1194,59 @@ static int mxcmci_remove(struct platform_device *pdev) + struct mmc_host *mmc = platform_get_drvdata(pdev); + struct mxcmci_host *host = mmc_priv(mmc); + +- platform_set_drvdata(pdev, NULL); +- + mmc_remove_host(mmc); + +- if (host->vcc) +- regulator_put(host->vcc); +- + if (host->pdata && host->pdata->exit) + host->pdata->exit(&pdev->dev, mmc); + +- free_irq(host->irq, host); +- iounmap(host->base); +- + if (host->dma) + dma_release_channel(host->dma); + +- clk_disable(host->clk); +- clk_put(host->clk); +- +- release_mem_region(host->res->start, resource_size(host->res)); ++ clk_disable_unprepare(host->clk_per); ++ clk_disable_unprepare(host->clk_ipg); + + mmc_free_host(mmc); + + return 0; + } + +-#ifdef CONFIG_PM +-static int mxcmci_suspend(struct device *dev) ++static int __maybe_unused mxcmci_suspend(struct device *dev) + { + struct mmc_host *mmc = dev_get_drvdata(dev); + struct mxcmci_host *host = mmc_priv(mmc); +- int ret = 0; + +- if (mmc) +- ret = mmc_suspend_host(mmc); +- clk_disable(host->clk); +- +- return ret; ++ clk_disable_unprepare(host->clk_per); ++ clk_disable_unprepare(host->clk_ipg); ++ return 0; + } + +-static int mxcmci_resume(struct device *dev) ++static int __maybe_unused mxcmci_resume(struct device *dev) + { + struct mmc_host *mmc = dev_get_drvdata(dev); + struct mxcmci_host *host = mmc_priv(mmc); +- int ret = 0; +- +- clk_enable(host->clk); +- if (mmc) +- ret = mmc_resume_host(mmc); + +- return ret; ++ clk_prepare_enable(host->clk_per); ++ clk_prepare_enable(host->clk_ipg); ++ return 0; + } + +-static const struct dev_pm_ops mxcmci_pm_ops = { +- .suspend = mxcmci_suspend, +- .resume = mxcmci_resume, +-}; +-#endif ++static SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume); + + static struct platform_driver mxcmci_driver = { + .probe = mxcmci_probe, + .remove = mxcmci_remove, ++ .id_table = mxcmci_devtype, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, +-#ifdef CONFIG_PM + .pm = &mxcmci_pm_ops, +-#endif ++ .of_match_table = mxcmci_of_match, + } + }; + +-static int __init mxcmci_init(void) +-{ +- return platform_driver_register(&mxcmci_driver); +-} +- +-static void __exit mxcmci_exit(void) +-{ +- platform_driver_unregister(&mxcmci_driver); +-} +- +-module_init(mxcmci_init); +-module_exit(mxcmci_exit); ++module_platform_driver(mxcmci_driver); + + MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver"); + MODULE_AUTHOR("Sascha Hauer, Pengutronix"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("platform:imx-mmc"); ++MODULE_ALIAS("platform:mxc-mmc"); +diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c +index f201bed..babfea0 100644 +--- a/drivers/mmc/host/mxs-mmc.c ++++ b/drivers/mmc/host/mxs-mmc.c +@@ -23,6 +23,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + #include +@@ -35,98 +38,15 @@ + #include + #include + #include ++#include + #include + #include + #include +- +-#include +-#include +-#include +-#include ++#include ++#include + + #define DRIVER_NAME "mxs-mmc" + +-/* card detect polling timeout */ +-#define MXS_MMC_DETECT_TIMEOUT (HZ/2) +- +-#define SSP_VERSION_LATEST 4 +-#define ssp_is_old() (host->version < SSP_VERSION_LATEST) +- +-/* SSP registers */ +-#define HW_SSP_CTRL0 0x000 +-#define BM_SSP_CTRL0_RUN (1 << 29) +-#define BM_SSP_CTRL0_SDIO_IRQ_CHECK (1 << 28) +-#define BM_SSP_CTRL0_IGNORE_CRC (1 << 26) +-#define BM_SSP_CTRL0_READ (1 << 25) +-#define BM_SSP_CTRL0_DATA_XFER (1 << 24) +-#define BP_SSP_CTRL0_BUS_WIDTH (22) +-#define BM_SSP_CTRL0_BUS_WIDTH (0x3 << 22) +-#define BM_SSP_CTRL0_WAIT_FOR_IRQ (1 << 21) +-#define BM_SSP_CTRL0_LONG_RESP (1 << 19) +-#define BM_SSP_CTRL0_GET_RESP (1 << 17) +-#define BM_SSP_CTRL0_ENABLE (1 << 16) +-#define BP_SSP_CTRL0_XFER_COUNT (0) +-#define BM_SSP_CTRL0_XFER_COUNT (0xffff) +-#define HW_SSP_CMD0 0x010 +-#define BM_SSP_CMD0_DBL_DATA_RATE_EN (1 << 25) +-#define BM_SSP_CMD0_SLOW_CLKING_EN (1 << 22) +-#define BM_SSP_CMD0_CONT_CLKING_EN (1 << 21) +-#define BM_SSP_CMD0_APPEND_8CYC (1 << 20) +-#define BP_SSP_CMD0_BLOCK_SIZE (16) +-#define BM_SSP_CMD0_BLOCK_SIZE (0xf << 16) +-#define BP_SSP_CMD0_BLOCK_COUNT (8) +-#define BM_SSP_CMD0_BLOCK_COUNT (0xff << 8) +-#define BP_SSP_CMD0_CMD (0) +-#define BM_SSP_CMD0_CMD (0xff) +-#define HW_SSP_CMD1 0x020 +-#define HW_SSP_XFER_SIZE 0x030 +-#define HW_SSP_BLOCK_SIZE 0x040 +-#define BP_SSP_BLOCK_SIZE_BLOCK_COUNT (4) +-#define BM_SSP_BLOCK_SIZE_BLOCK_COUNT (0xffffff << 4) +-#define BP_SSP_BLOCK_SIZE_BLOCK_SIZE (0) +-#define BM_SSP_BLOCK_SIZE_BLOCK_SIZE (0xf) +-#define HW_SSP_TIMING (ssp_is_old() ? 0x050 : 0x070) +-#define BP_SSP_TIMING_TIMEOUT (16) +-#define BM_SSP_TIMING_TIMEOUT (0xffff << 16) +-#define BP_SSP_TIMING_CLOCK_DIVIDE (8) +-#define BM_SSP_TIMING_CLOCK_DIVIDE (0xff << 8) +-#define BP_SSP_TIMING_CLOCK_RATE (0) +-#define BM_SSP_TIMING_CLOCK_RATE (0xff) +-#define HW_SSP_CTRL1 (ssp_is_old() ? 0x060 : 0x080) +-#define BM_SSP_CTRL1_SDIO_IRQ (1 << 31) +-#define BM_SSP_CTRL1_SDIO_IRQ_EN (1 << 30) +-#define BM_SSP_CTRL1_RESP_ERR_IRQ (1 << 29) +-#define BM_SSP_CTRL1_RESP_ERR_IRQ_EN (1 << 28) +-#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ (1 << 27) +-#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN (1 << 26) +-#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ (1 << 25) +-#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN (1 << 24) +-#define BM_SSP_CTRL1_DATA_CRC_IRQ (1 << 23) +-#define BM_SSP_CTRL1_DATA_CRC_IRQ_EN (1 << 22) +-#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ (1 << 21) +-#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ_EN (1 << 20) +-#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ (1 << 17) +-#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN (1 << 16) +-#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ (1 << 15) +-#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN (1 << 14) +-#define BM_SSP_CTRL1_DMA_ENABLE (1 << 13) +-#define BM_SSP_CTRL1_POLARITY (1 << 9) +-#define BP_SSP_CTRL1_WORD_LENGTH (4) +-#define BM_SSP_CTRL1_WORD_LENGTH (0xf << 4) +-#define BP_SSP_CTRL1_SSP_MODE (0) +-#define BM_SSP_CTRL1_SSP_MODE (0xf) +-#define HW_SSP_SDRESP0 (ssp_is_old() ? 0x080 : 0x0a0) +-#define HW_SSP_SDRESP1 (ssp_is_old() ? 0x090 : 0x0b0) +-#define HW_SSP_SDRESP2 (ssp_is_old() ? 0x0a0 : 0x0c0) +-#define HW_SSP_SDRESP3 (ssp_is_old() ? 0x0b0 : 0x0d0) +-#define HW_SSP_STATUS (ssp_is_old() ? 0x0c0 : 0x100) +-#define BM_SSP_STATUS_CARD_DETECT (1 << 28) +-#define BM_SSP_STATUS_SDIO_IRQ (1 << 17) +-#define HW_SSP_VERSION (cpu_is_mx23() ? 0x110 : 0x130) +-#define BP_SSP_VERSION_MAJOR (24) +- +-#define BF_SSP(value, field) (((value) << BP_SSP_##field) & BM_SSP_##field) +- + #define MXS_MMC_IRQ_BITS (BM_SSP_CTRL1_SDIO_IRQ | \ + BM_SSP_CTRL1_RESP_ERR_IRQ | \ + BM_SSP_CTRL1_RESP_TIMEOUT_IRQ | \ +@@ -136,60 +56,54 @@ + BM_SSP_CTRL1_RECV_TIMEOUT_IRQ | \ + BM_SSP_CTRL1_FIFO_OVERRUN_IRQ) + +-#define SSP_PIO_NUM 3 ++/* card detect polling timeout */ ++#define MXS_MMC_DETECT_TIMEOUT (HZ/2) + + struct mxs_mmc_host { ++ struct mxs_ssp ssp; ++ + struct mmc_host *mmc; + struct mmc_request *mrq; + struct mmc_command *cmd; + struct mmc_data *data; + +- void __iomem *base; +- int irq; +- struct resource *res; +- struct resource *dma_res; +- struct clk *clk; +- unsigned int clk_rate; +- +- struct dma_chan *dmach; +- struct mxs_dma_data dma_data; +- unsigned int dma_dir; +- u32 ssp_pio_words[SSP_PIO_NUM]; +- +- unsigned int version; + unsigned char bus_width; + spinlock_t lock; + int sdio_irq_en; ++ bool broken_cd; + }; + +-static int mxs_mmc_get_ro(struct mmc_host *mmc) ++static int mxs_mmc_get_cd(struct mmc_host *mmc) + { + struct mxs_mmc_host *host = mmc_priv(mmc); +- struct mxs_mmc_platform_data *pdata = +- mmc_dev(host->mmc)->platform_data; ++ struct mxs_ssp *ssp = &host->ssp; ++ int present, ret; + +- if (!pdata) +- return -EFAULT; ++ if (host->broken_cd) ++ return -ENOSYS; + +- if (!gpio_is_valid(pdata->wp_gpio)) +- return -EINVAL; ++ ret = mmc_gpio_get_cd(mmc); ++ if (ret >= 0) ++ return ret; + +- return gpio_get_value(pdata->wp_gpio); +-} ++ present = !(readl(ssp->base + HW_SSP_STATUS(ssp)) & ++ BM_SSP_STATUS_CARD_DETECT); + +-static int mxs_mmc_get_cd(struct mmc_host *mmc) +-{ +- struct mxs_mmc_host *host = mmc_priv(mmc); ++ if (mmc->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) ++ present = !present; + +- return !(readl(host->base + HW_SSP_STATUS) & +- BM_SSP_STATUS_CARD_DETECT); ++ return present; + } + +-static void mxs_mmc_reset(struct mxs_mmc_host *host) ++static int mxs_mmc_reset(struct mxs_mmc_host *host) + { ++ struct mxs_ssp *ssp = &host->ssp; + u32 ctrl0, ctrl1; ++ int ret; + +- mxs_reset_block(host->base); ++ ret = stmp_reset_block(ssp->base); ++ if (ret) ++ return ret; + + ctrl0 = BM_SSP_CTRL0_IGNORE_CRC; + ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) | +@@ -205,15 +119,16 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host) + writel(BF_SSP(0xffff, TIMING_TIMEOUT) | + BF_SSP(2, TIMING_CLOCK_DIVIDE) | + BF_SSP(0, TIMING_CLOCK_RATE), +- host->base + HW_SSP_TIMING); ++ ssp->base + HW_SSP_TIMING(ssp)); + + if (host->sdio_irq_en) { + ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK; + ctrl1 |= BM_SSP_CTRL1_SDIO_IRQ_EN; + } + +- writel(ctrl0, host->base + HW_SSP_CTRL0); +- writel(ctrl1, host->base + HW_SSP_CTRL1); ++ writel(ctrl0, ssp->base + HW_SSP_CTRL0); ++ writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp)); ++ return 0; + } + + static void mxs_mmc_start_cmd(struct mxs_mmc_host *host, +@@ -224,21 +139,22 @@ static void mxs_mmc_request_done(struct mxs_mmc_host *host) + struct mmc_command *cmd = host->cmd; + struct mmc_data *data = host->data; + struct mmc_request *mrq = host->mrq; ++ struct mxs_ssp *ssp = &host->ssp; + + if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) { + if (mmc_resp_type(cmd) & MMC_RSP_136) { +- cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0); +- cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1); +- cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2); +- cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3); ++ cmd->resp[3] = readl(ssp->base + HW_SSP_SDRESP0(ssp)); ++ cmd->resp[2] = readl(ssp->base + HW_SSP_SDRESP1(ssp)); ++ cmd->resp[1] = readl(ssp->base + HW_SSP_SDRESP2(ssp)); ++ cmd->resp[0] = readl(ssp->base + HW_SSP_SDRESP3(ssp)); + } else { +- cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0); ++ cmd->resp[0] = readl(ssp->base + HW_SSP_SDRESP0(ssp)); + } + } + + if (data) { + dma_unmap_sg(mmc_dev(host->mmc), data->sg, +- data->sg_len, host->dma_dir); ++ data->sg_len, ssp->dma_dir); + /* + * If there was an error on any block, we mark all + * data blocks as being in error. +@@ -271,13 +187,14 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id) + struct mxs_mmc_host *host = dev_id; + struct mmc_command *cmd = host->cmd; + struct mmc_data *data = host->data; ++ struct mxs_ssp *ssp = &host->ssp; + u32 stat; + + spin_lock(&host->lock); + +- stat = readl(host->base + HW_SSP_CTRL1); ++ stat = readl(ssp->base + HW_SSP_CTRL1(ssp)); + writel(stat & MXS_MMC_IRQ_BITS, +- host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR); ++ ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR); + + spin_unlock(&host->lock); + +@@ -304,8 +221,9 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id) + } + + static struct dma_async_tx_descriptor *mxs_mmc_prep_dma( +- struct mxs_mmc_host *host, unsigned int append) ++ struct mxs_mmc_host *host, unsigned long flags) + { ++ struct mxs_ssp *ssp = &host->ssp; + struct dma_async_tx_descriptor *desc; + struct mmc_data *data = host->data; + struct scatterlist * sgl; +@@ -314,24 +232,24 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma( + if (data) { + /* data */ + dma_map_sg(mmc_dev(host->mmc), data->sg, +- data->sg_len, host->dma_dir); ++ data->sg_len, ssp->dma_dir); + sgl = data->sg; + sg_len = data->sg_len; + } else { + /* pio */ +- sgl = (struct scatterlist *) host->ssp_pio_words; ++ sgl = (struct scatterlist *) ssp->ssp_pio_words; + sg_len = SSP_PIO_NUM; + } + +- desc = host->dmach->device->device_prep_slave_sg(host->dmach, +- sgl, sg_len, host->dma_dir, append); ++ desc = dmaengine_prep_slave_sg(ssp->dmach, ++ sgl, sg_len, ssp->slave_dirn, flags); + if (desc) { + desc->callback = mxs_mmc_dma_irq_callback; + desc->callback_param = host; + } else { + if (data) + dma_unmap_sg(mmc_dev(host->mmc), data->sg, +- data->sg_len, host->dma_dir); ++ data->sg_len, ssp->dma_dir); + } + + return desc; +@@ -339,6 +257,7 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma( + + static void mxs_mmc_bc(struct mxs_mmc_host *host) + { ++ struct mxs_ssp *ssp = &host->ssp; + struct mmc_command *cmd = host->cmd; + struct dma_async_tx_descriptor *desc; + u32 ctrl0, cmd0, cmd1; +@@ -352,15 +271,17 @@ static void mxs_mmc_bc(struct mxs_mmc_host *host) + cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN; + } + +- host->ssp_pio_words[0] = ctrl0; +- host->ssp_pio_words[1] = cmd0; +- host->ssp_pio_words[2] = cmd1; +- host->dma_dir = DMA_NONE; +- desc = mxs_mmc_prep_dma(host, 0); ++ ssp->ssp_pio_words[0] = ctrl0; ++ ssp->ssp_pio_words[1] = cmd0; ++ ssp->ssp_pio_words[2] = cmd1; ++ ssp->dma_dir = DMA_NONE; ++ ssp->slave_dirn = DMA_TRANS_NONE; ++ desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK); + if (!desc) + goto out; + + dmaengine_submit(desc); ++ dma_async_issue_pending(ssp->dmach); + return; + + out: +@@ -370,6 +291,7 @@ out: + + static void mxs_mmc_ac(struct mxs_mmc_host *host) + { ++ struct mxs_ssp *ssp = &host->ssp; + struct mmc_command *cmd = host->cmd; + struct dma_async_tx_descriptor *desc; + u32 ignore_crc, get_resp, long_resp; +@@ -391,15 +313,17 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host) + cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN; + } + +- host->ssp_pio_words[0] = ctrl0; +- host->ssp_pio_words[1] = cmd0; +- host->ssp_pio_words[2] = cmd1; +- host->dma_dir = DMA_NONE; +- desc = mxs_mmc_prep_dma(host, 0); ++ ssp->ssp_pio_words[0] = ctrl0; ++ ssp->ssp_pio_words[1] = cmd0; ++ ssp->ssp_pio_words[2] = cmd1; ++ ssp->dma_dir = DMA_NONE; ++ ssp->slave_dirn = DMA_TRANS_NONE; ++ desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK); + if (!desc) + goto out; + + dmaengine_submit(desc); ++ dma_async_issue_pending(ssp->dmach); + return; + + out: +@@ -430,12 +354,15 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) + struct dma_async_tx_descriptor *desc; + struct scatterlist *sgl = data->sg, *sg; + unsigned int sg_len = data->sg_len; +- int i; ++ unsigned int i; + + unsigned short dma_data_dir, timeout; ++ enum dma_transfer_direction slave_dirn; + unsigned int data_size = 0, log2_blksz; + unsigned int blocks = data->blocks; + ++ struct mxs_ssp *ssp = &host->ssp; ++ + u32 ignore_crc, get_resp, long_resp, read; + u32 ctrl0, cmd0, cmd1, val; + +@@ -448,9 +375,11 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) + + if (data->flags & MMC_DATA_WRITE) { + dma_data_dir = DMA_TO_DEVICE; ++ slave_dirn = DMA_MEM_TO_DEV; + read = 0; + } else { + dma_data_dir = DMA_FROM_DEVICE; ++ slave_dirn = DMA_DEV_TO_MEM; + read = BM_SSP_CTRL0_READ; + } + +@@ -476,15 +405,15 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) + blocks = 1; + + /* xfer count, block size and count need to be set differently */ +- if (ssp_is_old()) { ++ if (ssp_is_old(ssp)) { + ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT); + cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) | + BF_SSP(blocks - 1, CMD0_BLOCK_COUNT); + } else { +- writel(data_size, host->base + HW_SSP_XFER_SIZE); ++ writel(data_size, ssp->base + HW_SSP_XFER_SIZE); + writel(BF_SSP(log2_blksz, BLOCK_SIZE_BLOCK_SIZE) | + BF_SSP(blocks - 1, BLOCK_SIZE_BLOCK_COUNT), +- host->base + HW_SSP_BLOCK_SIZE); ++ ssp->base + HW_SSP_BLOCK_SIZE); + } + + if ((cmd->opcode == MMC_STOP_TRANSMISSION) || +@@ -499,17 +428,18 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) + } + + /* set the timeout count */ +- timeout = mxs_ns_to_ssp_ticks(host->clk_rate, data->timeout_ns); +- val = readl(host->base + HW_SSP_TIMING); ++ timeout = mxs_ns_to_ssp_ticks(ssp->clk_rate, data->timeout_ns); ++ val = readl(ssp->base + HW_SSP_TIMING(ssp)); + val &= ~(BM_SSP_TIMING_TIMEOUT); + val |= BF_SSP(timeout, TIMING_TIMEOUT); +- writel(val, host->base + HW_SSP_TIMING); ++ writel(val, ssp->base + HW_SSP_TIMING(ssp)); + + /* pio */ +- host->ssp_pio_words[0] = ctrl0; +- host->ssp_pio_words[1] = cmd0; +- host->ssp_pio_words[2] = cmd1; +- host->dma_dir = DMA_NONE; ++ ssp->ssp_pio_words[0] = ctrl0; ++ ssp->ssp_pio_words[1] = cmd0; ++ ssp->ssp_pio_words[2] = cmd1; ++ ssp->dma_dir = DMA_NONE; ++ ssp->slave_dirn = DMA_TRANS_NONE; + desc = mxs_mmc_prep_dma(host, 0); + if (!desc) + goto out; +@@ -517,12 +447,14 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) + /* append data sg */ + WARN_ON(host->data != NULL); + host->data = data; +- host->dma_dir = dma_data_dir; +- desc = mxs_mmc_prep_dma(host, 1); ++ ssp->dma_dir = dma_data_dir; ++ ssp->slave_dirn = slave_dirn; ++ desc = mxs_mmc_prep_dma(host, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc) + goto out; + + dmaengine_submit(desc); ++ dma_async_issue_pending(ssp->dmach); + return; + out: + dev_warn(mmc_dev(host->mmc), +@@ -563,42 +495,6 @@ static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) + mxs_mmc_start_cmd(host, mrq->cmd); + } + +-static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate) +-{ +- unsigned int ssp_clk, ssp_sck; +- u32 clock_divide, clock_rate; +- u32 val; +- +- ssp_clk = clk_get_rate(host->clk); +- +- for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) { +- clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide); +- clock_rate = (clock_rate > 0) ? clock_rate - 1 : 0; +- if (clock_rate <= 255) +- break; +- } +- +- if (clock_divide > 254) { +- dev_err(mmc_dev(host->mmc), +- "%s: cannot set clock to %d\n", __func__, rate); +- return; +- } +- +- ssp_sck = ssp_clk / clock_divide / (1 + clock_rate); +- +- val = readl(host->base + HW_SSP_TIMING); +- val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE); +- val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE); +- val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE); +- writel(val, host->base + HW_SSP_TIMING); +- +- host->clk_rate = ssp_sck; +- +- dev_dbg(mmc_dev(host->mmc), +- "%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n", +- __func__, clock_divide, clock_rate, ssp_clk, ssp_sck, rate); +-} +- + static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct mxs_mmc_host *host = mmc_priv(mmc); +@@ -611,12 +507,13 @@ static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + host->bus_width = 0; + + if (ios->clock) +- mxs_mmc_set_clk_rate(host, ios->clock); ++ mxs_ssp_set_clk_rate(&host->ssp, ios->clock); + } + + static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) + { + struct mxs_mmc_host *host = mmc_priv(mmc); ++ struct mxs_ssp *ssp = &host->ssp; + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); +@@ -625,106 +522,116 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) + + if (enable) { + writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, +- host->base + HW_SSP_CTRL0 + MXS_SET_ADDR); ++ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); + writel(BM_SSP_CTRL1_SDIO_IRQ_EN, +- host->base + HW_SSP_CTRL1 + MXS_SET_ADDR); ++ ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_SET); + } else { + writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, +- host->base + HW_SSP_CTRL0 + MXS_CLR_ADDR); ++ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); + writel(BM_SSP_CTRL1_SDIO_IRQ_EN, +- host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR); ++ ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR); + } + + spin_unlock_irqrestore(&host->lock, flags); + +- if (enable && readl(host->base + HW_SSP_STATUS) & BM_SSP_STATUS_SDIO_IRQ) ++ if (enable && readl(ssp->base + HW_SSP_STATUS(ssp)) & ++ BM_SSP_STATUS_SDIO_IRQ) + mmc_signal_sdio_irq(host->mmc); + + } + + static const struct mmc_host_ops mxs_mmc_ops = { + .request = mxs_mmc_request, +- .get_ro = mxs_mmc_get_ro, ++ .get_ro = mmc_gpio_get_ro, + .get_cd = mxs_mmc_get_cd, + .set_ios = mxs_mmc_set_ios, + .enable_sdio_irq = mxs_mmc_enable_sdio_irq, + }; + +-static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param) +-{ +- struct mxs_mmc_host *host = param; +- +- if (!mxs_dma_is_apbh(chan)) +- return false; +- +- if (chan->chan_id != host->dma_res->start) +- return false; +- +- chan->private = &host->dma_data; ++static struct platform_device_id mxs_ssp_ids[] = { ++ { ++ .name = "imx23-mmc", ++ .driver_data = IMX23_SSP, ++ }, { ++ .name = "imx28-mmc", ++ .driver_data = IMX28_SSP, ++ }, { ++ /* sentinel */ ++ } ++}; ++MODULE_DEVICE_TABLE(platform, mxs_ssp_ids); + +- return true; +-} ++static const struct of_device_id mxs_mmc_dt_ids[] = { ++ { .compatible = "fsl,imx23-mmc", .data = (void *) IMX23_SSP, }, ++ { .compatible = "fsl,imx28-mmc", .data = (void *) IMX28_SSP, }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, mxs_mmc_dt_ids); + + static int mxs_mmc_probe(struct platform_device *pdev) + { ++ const struct of_device_id *of_id = ++ of_match_device(mxs_mmc_dt_ids, &pdev->dev); ++ struct device_node *np = pdev->dev.of_node; + struct mxs_mmc_host *host; + struct mmc_host *mmc; +- struct resource *iores, *dmares, *r; +- struct mxs_mmc_platform_data *pdata; +- int ret = 0, irq_err, irq_dma; +- dma_cap_mask_t mask; ++ struct resource *iores; ++ int ret = 0, irq_err; ++ struct regulator *reg_vmmc; ++ struct mxs_ssp *ssp; + + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); + irq_err = platform_get_irq(pdev, 0); +- irq_dma = platform_get_irq(pdev, 1); +- if (!iores || !dmares || irq_err < 0 || irq_dma < 0) ++ if (!iores || irq_err < 0) + return -EINVAL; + +- r = request_mem_region(iores->start, resource_size(iores), pdev->name); +- if (!r) +- return -EBUSY; +- + mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev); +- if (!mmc) { +- ret = -ENOMEM; +- goto out_release_mem; +- } ++ if (!mmc) ++ return -ENOMEM; + + host = mmc_priv(mmc); +- host->base = ioremap(r->start, resource_size(r)); +- if (!host->base) { +- ret = -ENOMEM; ++ ssp = &host->ssp; ++ ssp->dev = &pdev->dev; ++ ssp->base = devm_ioremap_resource(&pdev->dev, iores); ++ if (IS_ERR(ssp->base)) { ++ ret = PTR_ERR(ssp->base); + goto out_mmc_free; + } + +- /* only major verion does matter */ +- host->version = readl(host->base + HW_SSP_VERSION) >> +- BP_SSP_VERSION_MAJOR; ++ ssp->devid = (enum mxs_ssp_id) of_id->data; + + host->mmc = mmc; +- host->res = r; +- host->dma_res = dmares; +- host->irq = irq_err; + host->sdio_irq_en = 0; + +- host->clk = clk_get(&pdev->dev, NULL); +- if (IS_ERR(host->clk)) { +- ret = PTR_ERR(host->clk); +- goto out_iounmap; ++ reg_vmmc = devm_regulator_get(&pdev->dev, "vmmc"); ++ if (!IS_ERR(reg_vmmc)) { ++ ret = regulator_enable(reg_vmmc); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "Failed to enable vmmc regulator: %d\n", ret); ++ goto out_mmc_free; ++ } ++ } ++ ++ ssp->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(ssp->clk)) { ++ ret = PTR_ERR(ssp->clk); ++ goto out_mmc_free; + } +- clk_enable(host->clk); ++ clk_prepare_enable(ssp->clk); + +- mxs_mmc_reset(host); ++ ret = mxs_mmc_reset(host); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to reset mmc: %d\n", ret); ++ goto out_clk_disable; ++ } + +- dma_cap_zero(mask); +- dma_cap_set(DMA_SLAVE, mask); +- host->dma_data.chan_irq = irq_dma; +- host->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host); +- if (!host->dmach) { ++ ssp->dmach = dma_request_slave_channel(&pdev->dev, "rx-tx"); ++ if (!ssp->dmach) { + dev_err(mmc_dev(host->mmc), + "%s: failed to request dma\n", __func__); +- goto out_clk_put; ++ ret = -ENODEV; ++ goto out_clk_disable; + } + + /* set mmc core parameters */ +@@ -732,27 +639,27 @@ static int mxs_mmc_probe(struct platform_device *pdev) + mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | + MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL; + +- pdata = mmc_dev(host->mmc)->platform_data; +- if (pdata) { +- if (pdata->flags & SLOTF_8_BIT_CAPABLE) +- mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; +- if (pdata->flags & SLOTF_4_BIT_CAPABLE) +- mmc->caps |= MMC_CAP_4_BIT_DATA; +- } ++ host->broken_cd = of_property_read_bool(np, "broken-cd"); + + mmc->f_min = 400000; + mmc->f_max = 288000000; ++ ++ ret = mmc_of_parse(mmc); ++ if (ret) ++ goto out_clk_disable; ++ + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + + mmc->max_segs = 52; + mmc->max_blk_size = 1 << 0xf; +- mmc->max_blk_count = (ssp_is_old()) ? 0xff : 0xffffff; +- mmc->max_req_size = (ssp_is_old()) ? 0xffff : 0xffffffff; +- mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev); ++ mmc->max_blk_count = (ssp_is_old(ssp)) ? 0xff : 0xffffff; ++ mmc->max_req_size = (ssp_is_old(ssp)) ? 0xffff : 0xffffffff; ++ mmc->max_seg_size = dma_get_max_seg_size(ssp->dmach->device->dev); + + platform_set_drvdata(pdev, mmc); + +- ret = request_irq(host->irq, mxs_mmc_irq_handler, 0, DRIVER_NAME, host); ++ ret = devm_request_irq(&pdev->dev, irq_err, mxs_mmc_irq_handler, 0, ++ DRIVER_NAME, host); + if (ret) + goto out_free_dma; + +@@ -760,26 +667,19 @@ static int mxs_mmc_probe(struct platform_device *pdev) + + ret = mmc_add_host(mmc); + if (ret) +- goto out_free_irq; ++ goto out_free_dma; + + dev_info(mmc_dev(host->mmc), "initialized\n"); + + return 0; + +-out_free_irq: +- free_irq(host->irq, host); + out_free_dma: +- if (host->dmach) +- dma_release_channel(host->dmach); +-out_clk_put: +- clk_disable(host->clk); +- clk_put(host->clk); +-out_iounmap: +- iounmap(host->base); ++ if (ssp->dmach) ++ dma_release_channel(ssp->dmach); ++out_clk_disable: ++ clk_disable_unprepare(ssp->clk); + out_mmc_free: + mmc_free_host(mmc); +-out_release_mem: +- release_mem_region(iores->start, resource_size(iores)); + return ret; + } + +@@ -787,26 +687,17 @@ static int mxs_mmc_remove(struct platform_device *pdev) + { + struct mmc_host *mmc = platform_get_drvdata(pdev); + struct mxs_mmc_host *host = mmc_priv(mmc); +- struct resource *res = host->res; ++ struct mxs_ssp *ssp = &host->ssp; + + mmc_remove_host(mmc); + +- free_irq(host->irq, host); ++ if (ssp->dmach) ++ dma_release_channel(ssp->dmach); + +- platform_set_drvdata(pdev, NULL); +- +- if (host->dmach) +- dma_release_channel(host->dmach); +- +- clk_disable(host->clk); +- clk_put(host->clk); +- +- iounmap(host->base); ++ clk_disable_unprepare(ssp->clk); + + mmc_free_host(mmc); + +- release_mem_region(res->start, resource_size(res)); +- + return 0; + } + +@@ -815,26 +706,20 @@ static int mxs_mmc_suspend(struct device *dev) + { + struct mmc_host *mmc = dev_get_drvdata(dev); + struct mxs_mmc_host *host = mmc_priv(mmc); +- int ret = 0; +- +- ret = mmc_suspend_host(mmc); ++ struct mxs_ssp *ssp = &host->ssp; + +- clk_disable(host->clk); +- +- return ret; ++ clk_disable_unprepare(ssp->clk); ++ return 0; + } + + static int mxs_mmc_resume(struct device *dev) + { + struct mmc_host *mmc = dev_get_drvdata(dev); + struct mxs_mmc_host *host = mmc_priv(mmc); +- int ret = 0; +- +- clk_enable(host->clk); ++ struct mxs_ssp *ssp = &host->ssp; + +- ret = mmc_resume_host(mmc); +- +- return ret; ++ clk_prepare_enable(ssp->clk); ++ return 0; + } + + static const struct dev_pm_ops mxs_mmc_pm_ops = { +@@ -846,28 +731,20 @@ static const struct dev_pm_ops mxs_mmc_pm_ops = { + static struct platform_driver mxs_mmc_driver = { + .probe = mxs_mmc_probe, + .remove = mxs_mmc_remove, ++ .id_table = mxs_ssp_ids, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + #ifdef CONFIG_PM + .pm = &mxs_mmc_pm_ops, + #endif ++ .of_match_table = mxs_mmc_dt_ids, + }, + }; + +-static int __init mxs_mmc_init(void) +-{ +- return platform_driver_register(&mxs_mmc_driver); +-} +- +-static void __exit mxs_mmc_exit(void) +-{ +- platform_driver_unregister(&mxs_mmc_driver); +-} +- +-module_init(mxs_mmc_init); +-module_exit(mxs_mmc_exit); ++module_platform_driver(mxs_mmc_driver); + + MODULE_DESCRIPTION("FREESCALE MXS MMC peripheral"); + MODULE_AUTHOR("Freescale Semiconductor"); + MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:" DRIVER_NAME); +diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c +index ab66f24..6e218fb 100644 +--- a/drivers/mmc/host/of_mmc_spi.c ++++ b/drivers/mmc/host/of_mmc_spi.c +@@ -50,25 +50,6 @@ static struct of_mmc_spi *to_of_mmc_spi(struct device *dev) + return container_of(dev->platform_data, struct of_mmc_spi, pdata); + } + +-static int of_mmc_spi_read_gpio(struct device *dev, int gpio_num) +-{ +- struct of_mmc_spi *oms = to_of_mmc_spi(dev); +- bool active_low = oms->alow_gpios[gpio_num]; +- bool value = gpio_get_value(oms->gpios[gpio_num]); +- +- return active_low ^ value; +-} +- +-static int of_mmc_spi_get_cd(struct device *dev) +-{ +- return of_mmc_spi_read_gpio(dev, CD_GPIO); +-} +- +-static int of_mmc_spi_get_ro(struct device *dev) +-{ +- return of_mmc_spi_read_gpio(dev, WP_GPIO); +-} +- + static int of_mmc_spi_init(struct device *dev, + irqreturn_t (*irqhandler)(int, void *), void *mmc) + { +@@ -113,8 +94,8 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) + const int j = i * 2; + u32 mask; + +- mask = mmc_vddrange_to_ocrmask(voltage_ranges[j], +- voltage_ranges[j + 1]); ++ mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]), ++ be32_to_cpu(voltage_ranges[j + 1])); + if (!mask) { + ret = -EINVAL; + dev_err(dev, "OF: voltage-range #%d is invalid\n", i); +@@ -130,23 +111,25 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) + if (!gpio_is_valid(oms->gpios[i])) + continue; + +- ret = gpio_request(oms->gpios[i], dev_name(dev)); +- if (ret < 0) { +- oms->gpios[i] = -EINVAL; +- continue; +- } +- + if (gpio_flags & OF_GPIO_ACTIVE_LOW) + oms->alow_gpios[i] = true; + } + +- if (gpio_is_valid(oms->gpios[CD_GPIO])) +- oms->pdata.get_cd = of_mmc_spi_get_cd; +- if (gpio_is_valid(oms->gpios[WP_GPIO])) +- oms->pdata.get_ro = of_mmc_spi_get_ro; ++ if (gpio_is_valid(oms->gpios[CD_GPIO])) { ++ oms->pdata.cd_gpio = oms->gpios[CD_GPIO]; ++ oms->pdata.flags |= MMC_SPI_USE_CD_GPIO; ++ if (!oms->alow_gpios[CD_GPIO]) ++ oms->pdata.caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; ++ } ++ if (gpio_is_valid(oms->gpios[WP_GPIO])) { ++ oms->pdata.ro_gpio = oms->gpios[WP_GPIO]; ++ oms->pdata.flags |= MMC_SPI_USE_RO_GPIO; ++ if (!oms->alow_gpios[WP_GPIO]) ++ oms->pdata.caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; ++ } + + oms->detect_irq = irq_of_parse_and_map(np, 0); +- if (oms->detect_irq != NO_IRQ) { ++ if (oms->detect_irq != 0) { + oms->pdata.init = of_mmc_spi_init; + oms->pdata.exit = of_mmc_spi_exit; + } else { +@@ -166,15 +149,10 @@ void mmc_spi_put_pdata(struct spi_device *spi) + struct device *dev = &spi->dev; + struct device_node *np = dev->of_node; + struct of_mmc_spi *oms = to_of_mmc_spi(dev); +- int i; + + if (!dev->platform_data || !np) + return; + +- for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) { +- if (gpio_is_valid(oms->gpios[i])) +- gpio_free(oms->gpios[i]); +- } + kfree(oms); + dev->platform_data = NULL; + } +diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c +index 2dba999..81974ec 100644 +--- a/drivers/mmc/host/omap.c ++++ b/drivers/mmc/host/omap.c +@@ -2,7 +2,7 @@ + * linux/drivers/mmc/host/omap.c + * + * Copyright (C) 2004 Nokia Corporation +- * Written by Tuukka Tikkanen and Juha Yrjölä ++ * Written by Tuukka Tikkanen and Juha Yrjölä + * Misc hacks here and there by Tony Lindgren + * Other hacks (DMA, SD, etc) by David Brownell + * +@@ -17,26 +17,21 @@ + #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 + + #define OMAP_MMC_REG_CMD 0x00 + #define OMAP_MMC_REG_ARGL 0x01 +@@ -78,6 +73,13 @@ + #define OMAP_MMC_STAT_CARD_BUSY (1 << 2) + #define OMAP_MMC_STAT_END_OF_CMD (1 << 0) + ++#define mmc_omap7xx() (host->features & MMC_OMAP7XX) ++#define mmc_omap15xx() (host->features & MMC_OMAP15XX) ++#define mmc_omap16xx() (host->features & MMC_OMAP16XX) ++#define MMC_OMAP1_MASK (MMC_OMAP7XX | MMC_OMAP15XX | MMC_OMAP16XX) ++#define mmc_omap1() (host->features & MMC_OMAP1_MASK) ++#define mmc_omap2() (!mmc_omap1()) ++ + #define OMAP_MMC_REG(host, reg) (OMAP_MMC_REG_##reg << (host)->reg_shift) + #define OMAP_MMC_READ(host, reg) __raw_readw((host)->virt_base + OMAP_MMC_REG(host, reg)) + #define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG(host, reg)) +@@ -90,7 +92,6 @@ + #define OMAP_MMC_CMDTYPE_AC 2 + #define OMAP_MMC_CMDTYPE_ADTC 3 + +- + #define DRIVER_NAME "mmci-omap" + + /* Specifies how often in millisecs to poll for card status changes +@@ -105,7 +106,6 @@ struct mmc_omap_slot { + u16 saved_con; + u16 bus_mode; + unsigned int fclk_freq; +- unsigned powered:1; + + struct tasklet_struct cover_tasklet; + struct timer_list cover_timer; +@@ -119,7 +119,6 @@ struct mmc_omap_slot { + + struct mmc_omap_host { + int initialized; +- int suspended; + struct mmc_request * mrq; + struct mmc_command * cmd; + struct mmc_data * data; +@@ -128,12 +127,14 @@ struct mmc_omap_host { + unsigned char id; /* 16xx chips have 2 MMC blocks */ + struct clk * iclk; + struct clk * fclk; +- struct resource *mem_res; ++ struct dma_chan *dma_rx; ++ u32 dma_rx_burst; ++ struct dma_chan *dma_tx; ++ u32 dma_tx_burst; + void __iomem *virt_base; + unsigned int phys_base; + int irq; + unsigned char bus_mode; +- unsigned char hw_bus_mode; + unsigned int reg_shift; + + struct work_struct cmd_abort_work; +@@ -151,14 +152,10 @@ struct mmc_omap_host { + u32 buffer_bytes_left; + u32 total_bytes_left; + +- unsigned use_dma:1; ++ unsigned features; + unsigned brs_received:1, dma_done:1; +- unsigned dma_is_read:1; + unsigned dma_in_use:1; +- int dma_ch; + spinlock_t dma_lock; +- struct timer_list dma_timer; +- unsigned dma_len; + + struct mmc_omap_slot *slots[OMAP_MMC_MAX_SLOTS]; + struct mmc_omap_slot *current_slot; +@@ -169,18 +166,18 @@ struct mmc_omap_host { + struct timer_list clk_timer; + spinlock_t clk_lock; /* for changing enabled state */ + unsigned int fclk_enabled:1; ++ struct workqueue_struct *mmc_omap_wq; + + struct omap_mmc_platform_data *pdata; + }; + +-static struct workqueue_struct *mmc_omap_wq; + + static void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot) + { + unsigned long tick_ns; + + if (slot != NULL && slot->host->fclk_enabled && slot->fclk_freq > 0) { +- tick_ns = (1000000000 + slot->fclk_freq - 1) / slot->fclk_freq; ++ tick_ns = DIV_ROUND_UP(NSEC_PER_SEC, slot->fclk_freq); + ndelay(8 * tick_ns); + } + } +@@ -291,7 +288,7 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled) + host->next_slot = new_slot; + host->mmc = new_slot->mmc; + spin_unlock_irqrestore(&host->slot_lock, flags); +- queue_work(mmc_omap_wq, &host->slot_release_work); ++ queue_work(host->mmc_omap_wq, &host->slot_release_work); + return; + } + +@@ -340,6 +337,7 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd) + u32 cmdreg; + u32 resptype; + u32 cmdtype; ++ u16 irq_mask; + + host->cmd = cmd; + +@@ -392,12 +390,14 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd) + OMAP_MMC_WRITE(host, CTO, 200); + OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff); + OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16); +- OMAP_MMC_WRITE(host, IE, +- OMAP_MMC_STAT_A_EMPTY | OMAP_MMC_STAT_A_FULL | +- OMAP_MMC_STAT_CMD_CRC | OMAP_MMC_STAT_CMD_TOUT | +- OMAP_MMC_STAT_DATA_CRC | OMAP_MMC_STAT_DATA_TOUT | +- OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR | +- OMAP_MMC_STAT_END_OF_DATA); ++ irq_mask = OMAP_MMC_STAT_A_EMPTY | OMAP_MMC_STAT_A_FULL | ++ OMAP_MMC_STAT_CMD_CRC | OMAP_MMC_STAT_CMD_TOUT | ++ OMAP_MMC_STAT_DATA_CRC | OMAP_MMC_STAT_DATA_TOUT | ++ OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR | ++ OMAP_MMC_STAT_END_OF_DATA; ++ if (cmd->opcode == MMC_ERASE) ++ irq_mask &= ~OMAP_MMC_STAT_DATA_TOUT; ++ OMAP_MMC_WRITE(host, IE, irq_mask); + OMAP_MMC_WRITE(host, CMD, cmdreg); + } + +@@ -406,18 +406,25 @@ mmc_omap_release_dma(struct mmc_omap_host *host, struct mmc_data *data, + int abort) + { + enum dma_data_direction dma_data_dir; ++ struct device *dev = mmc_dev(host->mmc); ++ struct dma_chan *c; + +- BUG_ON(host->dma_ch < 0); +- if (data->error) +- omap_stop_dma(host->dma_ch); +- /* Release DMA channel lazily */ +- mod_timer(&host->dma_timer, jiffies + HZ); +- if (data->flags & MMC_DATA_WRITE) ++ if (data->flags & MMC_DATA_WRITE) { + dma_data_dir = DMA_TO_DEVICE; +- else ++ c = host->dma_tx; ++ } else { + dma_data_dir = DMA_FROM_DEVICE; +- dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len, +- dma_data_dir); ++ c = host->dma_rx; ++ } ++ if (c) { ++ if (data->error) { ++ dmaengine_terminate_all(c); ++ /* Claim nothing transferred on error... */ ++ data->bytes_xfered = 0; ++ } ++ dev = c->device->dev; ++ } ++ dma_unmap_sg(dev, data->sg, host->sg_len, dma_data_dir); + } + + static void mmc_omap_send_stop_work(struct work_struct *work) +@@ -428,7 +435,7 @@ static void mmc_omap_send_stop_work(struct work_struct *work) + struct mmc_data *data = host->stop_data; + unsigned long tick_ns; + +- tick_ns = (1000000000 + slot->fclk_freq - 1)/slot->fclk_freq; ++ tick_ns = DIV_ROUND_UP(NSEC_PER_SEC, slot->fclk_freq); + ndelay(8*tick_ns); + + mmc_omap_start_command(host, data->stop); +@@ -459,7 +466,7 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) + } + + host->stop_data = data; +- queue_work(mmc_omap_wq, &host->send_stop_work); ++ queue_work(host->mmc_omap_wq, &host->send_stop_work); + } + + static void +@@ -470,7 +477,7 @@ mmc_omap_send_abort(struct mmc_omap_host *host, int maxloops) + u16 stat = 0; + + /* Sending abort takes 80 clocks. Have some extra and round up */ +- timeout = (120*1000000 + slot->fclk_freq - 1)/slot->fclk_freq; ++ timeout = DIV_ROUND_UP(120 * USEC_PER_SEC, slot->fclk_freq); + restarts = 0; + while (restarts < maxloops) { + OMAP_MMC_WRITE(host, STAT, 0xFFFF); +@@ -525,16 +532,6 @@ mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data) + } + + static void +-mmc_omap_dma_timer(unsigned long data) +-{ +- struct mmc_omap_host *host = (struct mmc_omap_host *) data; +- +- BUG_ON(host->dma_ch < 0); +- omap_free_dma(host->dma_ch); +- host->dma_ch = -1; +-} +- +-static void + mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data) + { + unsigned long flags; +@@ -639,7 +636,7 @@ mmc_omap_cmd_timer(unsigned long data) + OMAP_MMC_WRITE(host, IE, 0); + disable_irq(host->irq); + host->abort = 1; +- queue_work(mmc_omap_wq, &host->cmd_abort_work); ++ queue_work(host->mmc_omap_wq, &host->cmd_abort_work); + } + spin_unlock_irqrestore(&host->slot_lock, flags); + } +@@ -669,7 +666,7 @@ mmc_omap_clk_timer(unsigned long data) + static void + mmc_omap_xfer_data(struct mmc_omap_host *host, int write) + { +- int n; ++ int n, nwords; + + if (host->buffer_bytes_left == 0) { + host->sg_idx++; +@@ -679,33 +676,48 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write) + n = 64; + if (n > host->buffer_bytes_left) + n = host->buffer_bytes_left; ++ ++ /* Round up to handle odd number of bytes to transfer */ ++ nwords = DIV_ROUND_UP(n, 2); ++ + host->buffer_bytes_left -= n; + host->total_bytes_left -= n; + host->data->bytes_xfered += n; + + if (write) { +- __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); ++ __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), ++ host->buffer, nwords); + } else { +- __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); ++ __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), ++ host->buffer, nwords); + } ++ ++ host->buffer += nwords; + } + +-static inline void mmc_omap_report_irq(u16 status) ++#ifdef CONFIG_MMC_DEBUG ++static void mmc_omap_report_irq(struct mmc_omap_host *host, u16 status) + { + static const char *mmc_omap_status_bits[] = { + "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO", + "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR" + }; +- int i, c = 0; ++ int i; ++ char res[64], *buf = res; ++ ++ buf += sprintf(buf, "MMC IRQ 0x%x:", status); + + for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++) +- if (status & (1 << i)) { +- if (c) +- printk(" "); +- printk("%s", mmc_omap_status_bits[i]); +- c++; +- } ++ if (status & (1 << i)) ++ buf += sprintf(buf, " %s", mmc_omap_status_bits[i]); ++ dev_vdbg(mmc_dev(host->mmc), "%s\n", res); + } ++#else ++static void mmc_omap_report_irq(struct mmc_omap_host *host, u16 status) ++{ ++} ++#endif ++ + + static irqreturn_t mmc_omap_irq(int irq, void *dev_id) + { +@@ -739,12 +751,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) + cmd = host->cmd->opcode; + else + cmd = -1; +-#ifdef CONFIG_MMC_DEBUG + dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ", + status, cmd); +- mmc_omap_report_irq(status); +- printk("\n"); +-#endif ++ mmc_omap_report_irq(host, status); ++ + if (host->total_bytes_left) { + if ((status & OMAP_MMC_STAT_A_FULL) || + (status & OMAP_MMC_STAT_END_OF_DATA)) +@@ -828,7 +838,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) + host->abort = 1; + OMAP_MMC_WRITE(host, IE, 0); + disable_irq_nosync(host->irq); +- queue_work(mmc_omap_wq, &host->cmd_abort_work); ++ queue_work(host->mmc_omap_wq, &host->cmd_abort_work); + return IRQ_HANDLED; + } + +@@ -891,159 +901,15 @@ static void mmc_omap_cover_handler(unsigned long param) + jiffies + msecs_to_jiffies(OMAP_MMC_COVER_POLL_DELAY)); + } + +-/* Prepare to transfer the next segment of a scatterlist */ +-static void +-mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) +-{ +- int dma_ch = host->dma_ch; +- unsigned long data_addr; +- u16 buf, frame; +- u32 count; +- struct scatterlist *sg = &data->sg[host->sg_idx]; +- int src_port = 0; +- int dst_port = 0; +- int sync_dev = 0; +- +- data_addr = host->phys_base + OMAP_MMC_REG(host, DATA); +- frame = data->blksz; +- count = sg_dma_len(sg); +- +- if ((data->blocks == 1) && (count > data->blksz)) +- count = frame; +- +- host->dma_len = count; +- +- /* FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx and 24xx. +- * Use 16 or 32 word frames when the blocksize is at least that large. +- * Blocksize is usually 512 bytes; but not for some SD reads. +- */ +- if (cpu_is_omap15xx() && frame > 32) +- frame = 32; +- else if (frame > 64) +- frame = 64; +- count /= frame; +- frame >>= 1; +- +- if (!(data->flags & MMC_DATA_WRITE)) { +- buf = 0x800f | ((frame - 1) << 8); +- +- if (cpu_class_is_omap1()) { +- src_port = OMAP_DMA_PORT_TIPB; +- dst_port = OMAP_DMA_PORT_EMIFF; +- } +- if (cpu_is_omap24xx()) +- sync_dev = OMAP24XX_DMA_MMC1_RX; +- +- omap_set_dma_src_params(dma_ch, src_port, +- OMAP_DMA_AMODE_CONSTANT, +- data_addr, 0, 0); +- omap_set_dma_dest_params(dma_ch, dst_port, +- OMAP_DMA_AMODE_POST_INC, +- sg_dma_address(sg), 0, 0); +- omap_set_dma_dest_data_pack(dma_ch, 1); +- omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); +- } else { +- buf = 0x0f80 | ((frame - 1) << 0); +- +- if (cpu_class_is_omap1()) { +- src_port = OMAP_DMA_PORT_EMIFF; +- dst_port = OMAP_DMA_PORT_TIPB; +- } +- if (cpu_is_omap24xx()) +- sync_dev = OMAP24XX_DMA_MMC1_TX; +- +- omap_set_dma_dest_params(dma_ch, dst_port, +- OMAP_DMA_AMODE_CONSTANT, +- data_addr, 0, 0); +- omap_set_dma_src_params(dma_ch, src_port, +- OMAP_DMA_AMODE_POST_INC, +- sg_dma_address(sg), 0, 0); +- omap_set_dma_src_data_pack(dma_ch, 1); +- omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); +- } +- +- /* Max limit for DMA frame count is 0xffff */ +- BUG_ON(count > 0xffff); +- +- OMAP_MMC_WRITE(host, BUF, buf); +- omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16, +- frame, count, OMAP_DMA_SYNC_FRAME, +- sync_dev, 0); +-} +- +-/* A scatterlist segment completed */ +-static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data) +-{ +- struct mmc_omap_host *host = (struct mmc_omap_host *) data; +- struct mmc_data *mmcdat = host->data; +- +- if (unlikely(host->dma_ch < 0)) { +- dev_err(mmc_dev(host->mmc), +- "DMA callback while DMA not enabled\n"); +- return; +- } +- /* FIXME: We really should do something to _handle_ the errors */ +- if (ch_status & OMAP1_DMA_TOUT_IRQ) { +- dev_err(mmc_dev(host->mmc),"DMA timeout\n"); +- return; +- } +- if (ch_status & OMAP_DMA_DROP_IRQ) { +- dev_err(mmc_dev(host->mmc), "DMA sync error\n"); +- return; +- } +- if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) { +- return; +- } +- mmcdat->bytes_xfered += host->dma_len; +- host->sg_idx++; +- if (host->sg_idx < host->sg_len) { +- mmc_omap_prepare_dma(host, host->data); +- omap_start_dma(host->dma_ch); +- } else +- mmc_omap_dma_done(host, host->data); +-} +- +-static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data *data) ++static void mmc_omap_dma_callback(void *priv) + { +- const char *dma_dev_name; +- int sync_dev, dma_ch, is_read, r; +- +- is_read = !(data->flags & MMC_DATA_WRITE); +- del_timer_sync(&host->dma_timer); +- if (host->dma_ch >= 0) { +- if (is_read == host->dma_is_read) +- return 0; +- omap_free_dma(host->dma_ch); +- host->dma_ch = -1; +- } ++ struct mmc_omap_host *host = priv; ++ struct mmc_data *data = host->data; + +- if (is_read) { +- if (host->id == 0) { +- sync_dev = OMAP_DMA_MMC_RX; +- dma_dev_name = "MMC1 read"; +- } else { +- sync_dev = OMAP_DMA_MMC2_RX; +- dma_dev_name = "MMC2 read"; +- } +- } else { +- if (host->id == 0) { +- sync_dev = OMAP_DMA_MMC_TX; +- dma_dev_name = "MMC1 write"; +- } else { +- sync_dev = OMAP_DMA_MMC2_TX; +- dma_dev_name = "MMC2 write"; +- } +- } +- r = omap_request_dma(sync_dev, dma_dev_name, mmc_omap_dma_cb, +- host, &dma_ch); +- if (r != 0) { +- dev_dbg(mmc_dev(host->mmc), "omap_request_dma() failed with %d\n", r); +- return r; +- } +- host->dma_ch = dma_ch; +- host->dma_is_read = is_read; ++ /* If we got to the end of DMA, assume everything went well */ ++ data->bytes_xfered += data->blocks * data->blksz; + +- return 0; ++ mmc_omap_dma_done(host, data); + } + + static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req) +@@ -1081,7 +947,7 @@ static void + mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) + { + struct mmc_data *data = req->data; +- int i, use_dma, block_size; ++ int i, use_dma = 1, block_size; + unsigned sg_len; + + host->data = data; +@@ -1106,45 +972,94 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) + sg_len = (data->blocks == 1) ? 1 : data->sg_len; + + /* Only do DMA for entire blocks */ +- use_dma = host->use_dma; +- if (use_dma) { +- for (i = 0; i < sg_len; i++) { +- if ((data->sg[i].length % block_size) != 0) { +- use_dma = 0; +- break; +- } ++ for (i = 0; i < sg_len; i++) { ++ if ((data->sg[i].length % block_size) != 0) { ++ use_dma = 0; ++ break; + } + } + + host->sg_idx = 0; + if (use_dma) { +- if (mmc_omap_get_dma_channel(host, data) == 0) { +- enum dma_data_direction dma_data_dir; +- +- if (data->flags & MMC_DATA_WRITE) +- dma_data_dir = DMA_TO_DEVICE; +- else +- dma_data_dir = DMA_FROM_DEVICE; +- +- host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, +- sg_len, dma_data_dir); +- host->total_bytes_left = 0; +- mmc_omap_prepare_dma(host, req->data); +- host->brs_received = 0; +- host->dma_done = 0; +- host->dma_in_use = 1; +- } else +- use_dma = 0; ++ enum dma_data_direction dma_data_dir; ++ struct dma_async_tx_descriptor *tx; ++ struct dma_chan *c; ++ u32 burst, *bp; ++ u16 buf; ++ ++ /* ++ * FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx ++ * and 24xx. Use 16 or 32 word frames when the ++ * blocksize is at least that large. Blocksize is ++ * usually 512 bytes; but not for some SD reads. ++ */ ++ burst = mmc_omap15xx() ? 32 : 64; ++ if (burst > data->blksz) ++ burst = data->blksz; ++ ++ burst >>= 1; ++ ++ if (data->flags & MMC_DATA_WRITE) { ++ c = host->dma_tx; ++ bp = &host->dma_tx_burst; ++ buf = 0x0f80 | (burst - 1) << 0; ++ dma_data_dir = DMA_TO_DEVICE; ++ } else { ++ c = host->dma_rx; ++ bp = &host->dma_rx_burst; ++ buf = 0x800f | (burst - 1) << 8; ++ dma_data_dir = DMA_FROM_DEVICE; ++ } ++ ++ if (!c) ++ goto use_pio; ++ ++ /* Only reconfigure if we have a different burst size */ ++ if (*bp != burst) { ++ struct dma_slave_config cfg; ++ ++ cfg.src_addr = host->phys_base + OMAP_MMC_REG(host, DATA); ++ cfg.dst_addr = host->phys_base + OMAP_MMC_REG(host, DATA); ++ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; ++ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; ++ cfg.src_maxburst = burst; ++ cfg.dst_maxburst = burst; ++ ++ if (dmaengine_slave_config(c, &cfg)) ++ goto use_pio; ++ ++ *bp = burst; ++ } ++ ++ host->sg_len = dma_map_sg(c->device->dev, data->sg, sg_len, ++ dma_data_dir); ++ if (host->sg_len == 0) ++ goto use_pio; ++ ++ tx = dmaengine_prep_slave_sg(c, data->sg, host->sg_len, ++ data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!tx) ++ goto use_pio; ++ ++ OMAP_MMC_WRITE(host, BUF, buf); ++ ++ tx->callback = mmc_omap_dma_callback; ++ tx->callback_param = host; ++ dmaengine_submit(tx); ++ host->brs_received = 0; ++ host->dma_done = 0; ++ host->dma_in_use = 1; ++ return; + } ++ use_pio: + + /* Revert to PIO? */ +- if (!use_dma) { +- OMAP_MMC_WRITE(host, BUF, 0x1f1f); +- host->total_bytes_left = data->blocks * block_size; +- host->sg_len = sg_len; +- mmc_omap_sg_to_buf(host); +- host->dma_in_use = 0; +- } ++ OMAP_MMC_WRITE(host, BUF, 0x1f1f); ++ host->total_bytes_left = data->blocks * block_size; ++ host->sg_len = sg_len; ++ mmc_omap_sg_to_buf(host); ++ host->dma_in_use = 0; + } + + static void mmc_omap_start_request(struct mmc_omap_host *host, +@@ -1157,8 +1072,12 @@ static void mmc_omap_start_request(struct mmc_omap_host *host, + /* only touch fifo AFTER the controller readies it */ + mmc_omap_prepare_data(host, req); + mmc_omap_start_command(host, req->cmd); +- if (host->dma_in_use) +- omap_start_dma(host->dma_ch); ++ if (host->dma_in_use) { ++ struct dma_chan *c = host->data->flags & MMC_DATA_WRITE ? ++ host->dma_tx : host->dma_rx; ++ ++ dma_async_issue_pending(c); ++ } + } + + static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req) +@@ -1190,8 +1109,7 @@ static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on, + if (slot->pdata->set_power != NULL) + slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on, + vdd); +- +- if (cpu_is_omap24xx()) { ++ if (mmc_omap2()) { + u16 w; + + if (power_on) { +@@ -1300,7 +1218,7 @@ static const struct mmc_host_ops mmc_omap_ops = { + .set_ios = mmc_omap_set_ios, + }; + +-static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id) ++static int mmc_omap_new_slot(struct mmc_omap_host *host, int id) + { + struct mmc_omap_slot *slot = NULL; + struct mmc_host *mmc; +@@ -1320,12 +1238,12 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id) + + mmc->caps = 0; + if (host->pdata->slots[id].wires >= 4) +- mmc->caps |= MMC_CAP_4_BIT_DATA; ++ mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_ERASE; + + mmc->ops = &mmc_omap_ops; + mmc->f_min = 400000; + +- if (cpu_class_is_omap2()) ++ if (mmc_omap2()) + mmc->f_max = 48000000; + else + mmc->f_max = 24000000; +@@ -1343,6 +1261,13 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id) + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + mmc->max_seg_size = mmc->max_req_size; + ++ if (slot->pdata->get_cover_state != NULL) { ++ setup_timer(&slot->cover_timer, mmc_omap_cover_timer, ++ (unsigned long)slot); ++ tasklet_init(&slot->cover_tasklet, mmc_omap_cover_handler, ++ (unsigned long)slot); ++ } ++ + r = mmc_add_host(mmc); + if (r < 0) + goto err_remove_host; +@@ -1359,11 +1284,6 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id) + &dev_attr_cover_switch); + if (r < 0) + goto err_remove_slot_name; +- +- setup_timer(&slot->cover_timer, mmc_omap_cover_timer, +- (unsigned long)slot); +- tasklet_init(&slot->cover_tasklet, mmc_omap_cover_handler, +- (unsigned long)slot); + tasklet_schedule(&slot->cover_tasklet); + } + +@@ -1389,17 +1309,19 @@ static void mmc_omap_remove_slot(struct mmc_omap_slot *slot) + + tasklet_kill(&slot->cover_tasklet); + del_timer_sync(&slot->cover_timer); +- flush_workqueue(mmc_omap_wq); ++ flush_workqueue(slot->host->mmc_omap_wq); + + mmc_remove_host(mmc); + mmc_free_host(mmc); + } + +-static int __init mmc_omap_probe(struct platform_device *pdev) ++static int mmc_omap_probe(struct platform_device *pdev) + { + struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; + struct mmc_omap_host *host = NULL; + struct resource *res; ++ dma_cap_mask_t mask; ++ unsigned sig = 0; + int i, ret = 0; + int irq; + +@@ -1409,24 +1331,22 @@ static int __init mmc_omap_probe(struct platform_device *pdev) + } + if (pdata->nr_slots == 0) { + dev_err(&pdev->dev, "no slots\n"); +- return -ENXIO; ++ return -EPROBE_DEFER; + } + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ host = devm_kzalloc(&pdev->dev, sizeof(struct mmc_omap_host), ++ GFP_KERNEL); ++ if (host == NULL) ++ return -ENOMEM; ++ + irq = platform_get_irq(pdev, 0); +- if (res == NULL || irq < 0) ++ if (irq < 0) + return -ENXIO; + +- res = request_mem_region(res->start, resource_size(res), +- pdev->name); +- if (res == NULL) +- return -EBUSY; +- +- host = kzalloc(sizeof(struct mmc_omap_host), GFP_KERNEL); +- if (host == NULL) { +- ret = -ENOMEM; +- goto err_free_mem_region; +- } ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ host->virt_base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(host->virt_base)) ++ return PTR_ERR(host->virt_base); + + INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work); + INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work); +@@ -1439,33 +1359,20 @@ static int __init mmc_omap_probe(struct platform_device *pdev) + setup_timer(&host->clk_timer, mmc_omap_clk_timer, (unsigned long) host); + + spin_lock_init(&host->dma_lock); +- setup_timer(&host->dma_timer, mmc_omap_dma_timer, (unsigned long) host); + spin_lock_init(&host->slot_lock); + init_waitqueue_head(&host->slot_wq); + + host->pdata = pdata; ++ host->features = host->pdata->slots[0].features; + host->dev = &pdev->dev; + platform_set_drvdata(pdev, host); + + host->id = pdev->id; +- host->mem_res = res; +- host->irq = irq; +- +- host->use_dma = 1; +- host->dev->dma_mask = &pdata->dma_mask; +- host->dma_ch = -1; +- + host->irq = irq; +- host->phys_base = host->mem_res->start; +- host->virt_base = ioremap(res->start, resource_size(res)); +- if (!host->virt_base) +- goto err_ioremap; +- ++ host->phys_base = res->start; + host->iclk = clk_get(&pdev->dev, "ick"); +- if (IS_ERR(host->iclk)) { +- ret = PTR_ERR(host->iclk); +- goto err_free_mmc_host; +- } ++ if (IS_ERR(host->iclk)) ++ return PTR_ERR(host->iclk); + clk_enable(host->iclk); + + host->fclk = clk_get(&pdev->dev, "fck"); +@@ -1474,9 +1381,33 @@ static int __init mmc_omap_probe(struct platform_device *pdev) + goto err_free_iclk; + } + ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ ++ host->dma_tx_burst = -1; ++ host->dma_rx_burst = -1; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); ++ if (res) ++ sig = res->start; ++ host->dma_tx = dma_request_slave_channel_compat(mask, ++ omap_dma_filter_fn, &sig, &pdev->dev, "tx"); ++ if (!host->dma_tx) ++ dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n", ++ sig); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); ++ if (res) ++ sig = res->start; ++ host->dma_rx = dma_request_slave_channel_compat(mask, ++ omap_dma_filter_fn, &sig, &pdev->dev, "rx"); ++ if (!host->dma_rx) ++ dev_warn(host->dev, "unable to obtain RX DMA engine channel %u\n", ++ sig); ++ + ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host); + if (ret) +- goto err_free_fclk; ++ goto err_free_dma; + + if (pdata->init != NULL) { + ret = pdata->init(&pdev->dev); +@@ -1485,36 +1416,40 @@ static int __init mmc_omap_probe(struct platform_device *pdev) + } + + host->nr_slots = pdata->nr_slots; ++ host->reg_shift = (mmc_omap7xx() ? 1 : 2); ++ ++ host->mmc_omap_wq = alloc_workqueue("mmc_omap", 0, 0); ++ if (!host->mmc_omap_wq) ++ goto err_plat_cleanup; ++ + for (i = 0; i < pdata->nr_slots; i++) { + ret = mmc_omap_new_slot(host, i); + if (ret < 0) { + while (--i >= 0) + mmc_omap_remove_slot(host->slots[i]); + +- goto err_plat_cleanup; ++ goto err_destroy_wq; + } + } + +- host->reg_shift = (cpu_is_omap7xx() ? 1 : 2); +- + return 0; + ++err_destroy_wq: ++ destroy_workqueue(host->mmc_omap_wq); + err_plat_cleanup: + if (pdata->cleanup) + pdata->cleanup(&pdev->dev); + err_free_irq: + free_irq(host->irq, host); +-err_free_fclk: ++err_free_dma: ++ if (host->dma_tx) ++ dma_release_channel(host->dma_tx); ++ if (host->dma_rx) ++ dma_release_channel(host->dma_rx); + clk_put(host->fclk); + err_free_iclk: + clk_disable(host->iclk); + clk_put(host->iclk); +-err_free_mmc_host: +- iounmap(host->virt_base); +-err_ioremap: +- kfree(host); +-err_free_mem_region: +- release_mem_region(res->start, resource_size(res)); + return ret; + } + +@@ -1523,8 +1458,6 @@ static int mmc_omap_remove(struct platform_device *pdev) + struct mmc_omap_host *host = platform_get_drvdata(pdev); + int i; + +- platform_set_drvdata(pdev, NULL); +- + BUG_ON(host == NULL); + + for (i = 0; i < host->nr_slots; i++) +@@ -1539,99 +1472,35 @@ static int mmc_omap_remove(struct platform_device *pdev) + clk_disable(host->iclk); + clk_put(host->iclk); + +- iounmap(host->virt_base); +- release_mem_region(pdev->resource[0].start, +- pdev->resource[0].end - pdev->resource[0].start + 1); +- +- kfree(host); ++ if (host->dma_tx) ++ dma_release_channel(host->dma_tx); ++ if (host->dma_rx) ++ dma_release_channel(host->dma_rx); + +- return 0; +-} +- +-#ifdef CONFIG_PM +-static int mmc_omap_suspend(struct platform_device *pdev, pm_message_t mesg) +-{ +- int i, ret = 0; +- struct mmc_omap_host *host = platform_get_drvdata(pdev); +- +- if (host == NULL || host->suspended) +- return 0; +- +- for (i = 0; i < host->nr_slots; i++) { +- struct mmc_omap_slot *slot; ++ destroy_workqueue(host->mmc_omap_wq); + +- slot = host->slots[i]; +- ret = mmc_suspend_host(slot->mmc); +- if (ret < 0) { +- while (--i >= 0) { +- slot = host->slots[i]; +- mmc_resume_host(slot->mmc); +- } +- return ret; +- } +- } +- host->suspended = 1; + return 0; + } + +-static int mmc_omap_resume(struct platform_device *pdev) +-{ +- int i, ret = 0; +- struct mmc_omap_host *host = platform_get_drvdata(pdev); +- +- if (host == NULL || !host->suspended) +- return 0; +- +- for (i = 0; i < host->nr_slots; i++) { +- struct mmc_omap_slot *slot; +- slot = host->slots[i]; +- ret = mmc_resume_host(slot->mmc); +- if (ret < 0) +- return ret; +- +- host->suspended = 0; +- } +- return 0; +-} +-#else +-#define mmc_omap_suspend NULL +-#define mmc_omap_resume NULL ++#if IS_BUILTIN(CONFIG_OF) ++static const struct of_device_id mmc_omap_match[] = { ++ { .compatible = "ti,omap2420-mmc", }, ++ { }, ++}; + #endif + + static struct platform_driver mmc_omap_driver = { ++ .probe = mmc_omap_probe, + .remove = mmc_omap_remove, +- .suspend = mmc_omap_suspend, +- .resume = mmc_omap_resume, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(mmc_omap_match), + }, + }; + +-static int __init mmc_omap_init(void) +-{ +- int ret; +- +- mmc_omap_wq = alloc_workqueue("mmc_omap", 0, 0); +- if (!mmc_omap_wq) +- return -ENOMEM; +- +- ret = platform_driver_probe(&mmc_omap_driver, mmc_omap_probe); +- if (ret) +- destroy_workqueue(mmc_omap_wq); +- return ret; +-} +- +-static void __exit mmc_omap_exit(void) +-{ +- platform_driver_unregister(&mmc_omap_driver); +- destroy_workqueue(mmc_omap_wq); +-} +- +-module_init(mmc_omap_init); +-module_exit(mmc_omap_exit); +- ++module_platform_driver(mmc_omap_driver); + MODULE_DESCRIPTION("OMAP Multimedia Card driver"); + MODULE_LICENSE("GPL"); + MODULE_ALIAS("platform:" DRIVER_NAME); +-MODULE_AUTHOR("Juha Yrjölä"); ++MODULE_AUTHOR("Juha Yrjölä"); +diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c +index bc27065..6b7b755 100644 +--- a/drivers/mmc/host/omap_hsmmc.c ++++ b/drivers/mmc/host/omap_hsmmc.c +@@ -19,32 +19,33 @@ + #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 + + /* OMAP HSMMC Host Controller Registers */ +-#define OMAP_HSMMC_SYSCONFIG 0x0010 + #define OMAP_HSMMC_SYSSTATUS 0x0014 + #define OMAP_HSMMC_CON 0x002C ++#define OMAP_HSMMC_SDMASA 0x0100 + #define OMAP_HSMMC_BLK 0x0104 + #define OMAP_HSMMC_ARG 0x0108 + #define OMAP_HSMMC_CMD 0x010C +@@ -58,10 +59,12 @@ + #define OMAP_HSMMC_STAT 0x0130 + #define OMAP_HSMMC_IE 0x0134 + #define OMAP_HSMMC_ISE 0x0138 ++#define OMAP_HSMMC_AC12 0x013C + #define OMAP_HSMMC_CAPA 0x0140 + + #define VS18 (1 << 26) + #define VS30 (1 << 25) ++#define HSS (1 << 21) + #define SDVS18 (0x5 << 9) + #define SDVS30 (0x6 << 9) + #define SDVS33 (0x7 << 9) +@@ -74,57 +77,70 @@ + #define ICE 0x1 + #define ICS 0x2 + #define CEN (1 << 2) ++#define CLKD_MAX 0x3FF /* max clock divisor: 1023 */ + #define CLKD_MASK 0x0000FFC0 + #define CLKD_SHIFT 6 + #define DTO_MASK 0x000F0000 + #define DTO_SHIFT 16 +-#define INT_EN_MASK 0x307F0033 +-#define BWR_ENABLE (1 << 4) +-#define BRR_ENABLE (1 << 5) +-#define DTO_ENABLE (1 << 20) + #define INIT_STREAM (1 << 1) ++#define ACEN_ACMD23 (2 << 2) + #define DP_SELECT (1 << 21) + #define DDIR (1 << 4) +-#define DMA_EN 0x1 ++#define DMAE 0x1 + #define MSBS (1 << 5) + #define BCE (1 << 1) + #define FOUR_BIT (1 << 1) ++#define HSPE (1 << 2) ++#define DDR (1 << 19) + #define DW8 (1 << 5) +-#define CC 0x1 +-#define TC 0x02 + #define OD 0x1 +-#define ERR (1 << 15) +-#define CMD_TIMEOUT (1 << 16) +-#define DATA_TIMEOUT (1 << 20) +-#define CMD_CRC (1 << 17) +-#define DATA_CRC (1 << 21) +-#define CARD_ERR (1 << 28) + #define STAT_CLEAR 0xFFFFFFFF + #define INIT_STREAM_CMD 0x00000000 + #define DUAL_VOLT_OCR_BIT 7 + #define SRC (1 << 25) + #define SRD (1 << 26) + #define SOFTRESET (1 << 1) +-#define RESETDONE (1 << 0) + +-/* +- * FIXME: Most likely all the data using these _DEVID defines should come +- * from the platform_data, or implemented in controller and slot specific +- * functions. +- */ +-#define OMAP_MMC1_DEVID 0 +-#define OMAP_MMC2_DEVID 1 +-#define OMAP_MMC3_DEVID 2 +-#define OMAP_MMC4_DEVID 3 +-#define OMAP_MMC5_DEVID 4 ++/* Interrupt masks for IE and ISE register */ ++#define CC_EN (1 << 0) ++#define TC_EN (1 << 1) ++#define BWR_EN (1 << 4) ++#define BRR_EN (1 << 5) ++#define ERR_EN (1 << 15) ++#define CTO_EN (1 << 16) ++#define CCRC_EN (1 << 17) ++#define CEB_EN (1 << 18) ++#define CIE_EN (1 << 19) ++#define DTO_EN (1 << 20) ++#define DCRC_EN (1 << 21) ++#define DEB_EN (1 << 22) ++#define ACE_EN (1 << 24) ++#define CERR_EN (1 << 28) ++#define BADA_EN (1 << 29) ++ ++#define INT_EN_MASK (BADA_EN | CERR_EN | ACE_EN | DEB_EN | DCRC_EN |\ ++ DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \ ++ BRR_EN | BWR_EN | TC_EN | CC_EN) ++ ++#define CNI (1 << 7) ++#define ACIE (1 << 4) ++#define ACEB (1 << 3) ++#define ACCE (1 << 2) ++#define ACTO (1 << 1) ++#define ACNE (1 << 0) + + #define MMC_AUTOSUSPEND_DELAY 100 +-#define MMC_TIMEOUT_MS 20 +-#define OMAP_MMC_MASTER_CLOCK 96000000 ++#define MMC_TIMEOUT_MS 20 /* 20 mSec */ ++#define MMC_TIMEOUT_US 20000 /* 20000 micro Sec */ + #define OMAP_MMC_MIN_CLOCK 400000 + #define OMAP_MMC_MAX_CLOCK 52000000 + #define DRIVER_NAME "omap_hsmmc" + ++#define VDD_1V8 1800000 /* 180000 uV */ ++#define VDD_3V0 3000000 /* 300000 uV */ ++#define VDD_165_195 (ffs(MMC_VDD_165_195) - 1) ++ ++#define AUTO_CMD23 (1 << 1) /* Auto CMD23 support */ + /* + * One controller can have multiple slots, like on some omap boards using + * omap.c controller driver. Luckily this is not currently done on any known +@@ -163,39 +179,48 @@ struct omap_hsmmc_host { + */ + struct regulator *vcc; + struct regulator *vcc_aux; +- struct work_struct mmc_carddetect_work; ++ struct regulator *pbias; ++ bool pbias_enabled; + void __iomem *base; + resource_size_t mapbase; + spinlock_t irq_lock; /* Prevent races with irq handler */ +- unsigned int id; + unsigned int dma_len; + unsigned int dma_sg_idx; + unsigned char bus_mode; + unsigned char power_mode; +- u32 *buffer; +- u32 bytesleft; + int suspended; ++ u32 con; ++ u32 hctl; ++ u32 sysctl; ++ u32 capa; + int irq; + int use_dma, dma_ch; +- int dma_line_tx, dma_line_rx; ++ struct dma_chan *tx_chan; ++ struct dma_chan *rx_chan; + int slot_id; +- int got_dbclk; + int response_busy; + int context_loss; +- int dpm_state; +- int vdd; + int protect_card; + int reqs_blocked; + int use_reg; + int req_in_progress; ++ unsigned long clk_rate; ++ unsigned int flags; + struct omap_hsmmc_next next_data; +- + struct omap_mmc_platform_data *pdata; + }; + ++struct omap_mmc_of_data { ++ u32 reg_offset; ++ u8 controller_flags; ++}; ++ ++static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host); ++ + static int omap_hsmmc_card_detect(struct device *dev, int slot) + { +- struct omap_mmc_platform_data *mmc = dev->platform_data; ++ struct omap_hsmmc_host *host = dev_get_drvdata(dev); ++ struct omap_mmc_platform_data *mmc = host->pdata; + + /* NOTE: assumes card detect signal is active-low */ + return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); +@@ -203,7 +228,8 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot) + + static int omap_hsmmc_get_wp(struct device *dev, int slot) + { +- struct omap_mmc_platform_data *mmc = dev->platform_data; ++ struct omap_hsmmc_host *host = dev_get_drvdata(dev); ++ struct omap_mmc_platform_data *mmc = host->pdata; + + /* NOTE: assumes write protect signal is active-high */ + return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); +@@ -211,7 +237,8 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot) + + static int omap_hsmmc_get_cover_state(struct device *dev, int slot) + { +- struct omap_mmc_platform_data *mmc = dev->platform_data; ++ struct omap_hsmmc_host *host = dev_get_drvdata(dev); ++ struct omap_mmc_platform_data *mmc = host->pdata; + + /* NOTE: assumes card detect signal is active-low */ + return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); +@@ -221,7 +248,8 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot) + + static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) + { +- struct omap_mmc_platform_data *mmc = dev->platform_data; ++ struct omap_hsmmc_host *host = dev_get_drvdata(dev); ++ struct omap_mmc_platform_data *mmc = host->pdata; + + disable_irq(mmc->slots[0].card_detect_irq); + return 0; +@@ -229,7 +257,8 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) + + static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) + { +- struct omap_mmc_platform_data *mmc = dev->platform_data; ++ struct omap_hsmmc_host *host = dev_get_drvdata(dev); ++ struct omap_mmc_platform_data *mmc = host->pdata; + + enable_irq(mmc->slots[0].card_detect_irq); + return 0; +@@ -244,28 +273,7 @@ static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) + + #ifdef CONFIG_REGULATOR + +-static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on, +- int vdd) +-{ +- struct omap_hsmmc_host *host = +- platform_get_drvdata(to_platform_device(dev)); +- int ret; +- +- if (mmc_slot(host).before_set_reg) +- mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); +- +- if (power_on) +- ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); +- else +- ret = mmc_regulator_set_ocr(host->mmc, host->vcc, 0); +- +- if (mmc_slot(host).after_set_reg) +- mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); +- +- return ret; +-} +- +-static int omap_hsmmc_235_set_power(struct device *dev, int slot, int power_on, ++static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on, + int vdd) + { + struct omap_hsmmc_host *host = +@@ -282,6 +290,15 @@ static int omap_hsmmc_235_set_power(struct device *dev, int slot, int power_on, + if (mmc_slot(host).before_set_reg) + mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); + ++ if (host->pbias) { ++ if (host->pbias_enabled == 1) { ++ ret = regulator_disable(host->pbias); ++ if (!ret) ++ host->pbias_enabled = 0; ++ } ++ regulator_set_voltage(host->pbias, VDD_3V0, VDD_3V0); ++ } ++ + /* + * Assume Vcc regulator is used only to power the card ... OMAP + * VDDS is used to power the pins, optionally with a transceiver to +@@ -296,11 +313,12 @@ static int omap_hsmmc_235_set_power(struct device *dev, int slot, int power_on, + * chips/cards need an interface voltage rail too. + */ + if (power_on) { +- ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); ++ if (host->vcc) ++ ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); + /* Enable interface voltage rail, if needed */ + if (ret == 0 && host->vcc_aux) { + ret = regulator_enable(host->vcc_aux); +- if (ret < 0) ++ if (ret < 0 && host->vcc) + ret = mmc_regulator_set_ocr(host->mmc, + host->vcc, 0); + } +@@ -308,119 +326,47 @@ static int omap_hsmmc_235_set_power(struct device *dev, int slot, int power_on, + /* Shut down the rail */ + if (host->vcc_aux) + ret = regulator_disable(host->vcc_aux); +- if (!ret) { ++ if (host->vcc) { + /* Then proceed to shut down the local regulator */ + ret = mmc_regulator_set_ocr(host->mmc, + host->vcc, 0); + } + } + +- if (mmc_slot(host).after_set_reg) +- mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); +- +- return ret; +-} +- +-static int omap_hsmmc_4_set_power(struct device *dev, int slot, int power_on, +- int vdd) +-{ +- return 0; +-} +- +-static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep, +- int vdd, int cardsleep) +-{ +- struct omap_hsmmc_host *host = +- platform_get_drvdata(to_platform_device(dev)); +- int mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; +- +- return regulator_set_mode(host->vcc, mode); +-} +- +-static int omap_hsmmc_235_set_sleep(struct device *dev, int slot, int sleep, +- int vdd, int cardsleep) +-{ +- struct omap_hsmmc_host *host = +- platform_get_drvdata(to_platform_device(dev)); +- int err, mode; +- +- /* +- * If we don't see a Vcc regulator, assume it's a fixed +- * voltage always-on regulator. +- */ +- if (!host->vcc) +- return 0; +- +- mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; +- +- if (!host->vcc_aux) +- return regulator_set_mode(host->vcc, mode); +- +- if (cardsleep) { +- /* VCC can be turned off if card is asleep */ +- if (sleep) +- err = mmc_regulator_set_ocr(host->mmc, host->vcc, 0); ++ if (host->pbias) { ++ if (vdd <= VDD_165_195) ++ ret = regulator_set_voltage(host->pbias, VDD_1V8, ++ VDD_1V8); + else +- err = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); +- } else +- err = regulator_set_mode(host->vcc, mode); +- if (err) +- return err; ++ ret = regulator_set_voltage(host->pbias, VDD_3V0, ++ VDD_3V0); ++ if (ret < 0) ++ goto error_set_power; + +- if (!mmc_slot(host).vcc_aux_disable_is_sleep) +- return regulator_set_mode(host->vcc_aux, mode); ++ if (host->pbias_enabled == 0) { ++ ret = regulator_enable(host->pbias); ++ if (!ret) ++ host->pbias_enabled = 1; ++ } ++ } + +- if (sleep) +- return regulator_disable(host->vcc_aux); +- else +- return regulator_enable(host->vcc_aux); +-} ++ if (mmc_slot(host).after_set_reg) ++ mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); + +-static int omap_hsmmc_4_set_sleep(struct device *dev, int slot, int sleep, +- int vdd, int cardsleep) +-{ +- return 0; ++error_set_power: ++ return ret; + } + + static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) + { + struct regulator *reg; +- int ret = 0; + int ocr_value = 0; + +- switch (host->id) { +- case OMAP_MMC1_DEVID: +- /* On-chip level shifting via PBIAS0/PBIAS1 */ +- mmc_slot(host).set_power = omap_hsmmc_1_set_power; +- mmc_slot(host).set_sleep = omap_hsmmc_1_set_sleep; +- break; +- case OMAP_MMC2_DEVID: +- case OMAP_MMC3_DEVID: +- case OMAP_MMC5_DEVID: +- /* Off-chip level shifting, or none */ +- mmc_slot(host).set_power = omap_hsmmc_235_set_power; +- mmc_slot(host).set_sleep = omap_hsmmc_235_set_sleep; +- break; +- case OMAP_MMC4_DEVID: +- mmc_slot(host).set_power = omap_hsmmc_4_set_power; +- mmc_slot(host).set_sleep = omap_hsmmc_4_set_sleep; +- default: +- pr_err("MMC%d configuration not supported!\n", host->id); +- return -EINVAL; +- } +- +- reg = regulator_get(host->dev, "vmmc"); ++ reg = devm_regulator_get(host->dev, "vmmc"); + if (IS_ERR(reg)) { +- dev_dbg(host->dev, "vmmc regulator missing\n"); +- /* +- * HACK: until fixed.c regulator is usable, +- * we don't require a main regulator +- * for MMC2 or MMC3 +- */ +- if (host->id == OMAP_MMC1_DEVID) { +- ret = PTR_ERR(reg); +- goto err; +- } ++ dev_err(host->dev, "unable to get vmmc regulator %ld\n", ++ PTR_ERR(reg)); ++ return PTR_ERR(reg); + } else { + host->vcc = reg; + ocr_value = mmc_regulator_get_ocrmask(reg); +@@ -428,53 +374,43 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) + mmc_slot(host).ocr_mask = ocr_value; + } else { + if (!(mmc_slot(host).ocr_mask & ocr_value)) { +- pr_err("MMC%d ocrmask %x is not supported\n", +- host->id, mmc_slot(host).ocr_mask); ++ dev_err(host->dev, "ocrmask %x is not supported\n", ++ mmc_slot(host).ocr_mask); + mmc_slot(host).ocr_mask = 0; + return -EINVAL; + } + } ++ } ++ mmc_slot(host).set_power = omap_hsmmc_set_power; + +- /* Allow an aux regulator */ +- reg = regulator_get(host->dev, "vmmc_aux"); +- host->vcc_aux = IS_ERR(reg) ? NULL : reg; ++ /* Allow an aux regulator */ ++ reg = devm_regulator_get_optional(host->dev, "vmmc_aux"); ++ host->vcc_aux = IS_ERR(reg) ? NULL : reg; + +- /* For eMMC do not power off when not in sleep state */ +- if (mmc_slot(host).no_regulator_off_init) +- return 0; +- /* +- * UGLY HACK: workaround regulator framework bugs. +- * When the bootloader leaves a supply active, it's +- * initialized with zero usecount ... and we can't +- * disable it without first enabling it. Until the +- * framework is fixed, we need a workaround like this +- * (which is safe for MMC, but not in general). +- */ +- if (regulator_is_enabled(host->vcc) > 0 || +- (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) { +- int vdd = ffs(mmc_slot(host).ocr_mask) - 1; ++ reg = devm_regulator_get_optional(host->dev, "pbias"); ++ host->pbias = IS_ERR(reg) ? NULL : reg; + +- mmc_slot(host).set_power(host->dev, host->slot_id, +- 1, vdd); +- mmc_slot(host).set_power(host->dev, host->slot_id, +- 0, 0); +- } ++ /* For eMMC do not power off when not in sleep state */ ++ if (mmc_slot(host).no_regulator_off_init) ++ return 0; ++ /* ++ * To disable boot_on regulator, enable regulator ++ * to increase usecount and then disable it. ++ */ ++ if ((host->vcc && regulator_is_enabled(host->vcc) > 0) || ++ (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) { ++ int vdd = ffs(mmc_slot(host).ocr_mask) - 1; ++ ++ mmc_slot(host).set_power(host->dev, host->slot_id, 1, vdd); ++ mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); + } + + return 0; +- +-err: +- mmc_slot(host).set_power = NULL; +- mmc_slot(host).set_sleep = NULL; +- return ret; + } + + static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) + { +- regulator_put(host->vcc); +- regulator_put(host->vcc_aux); + mmc_slot(host).set_power = NULL; +- mmc_slot(host).set_sleep = NULL; + } + + static inline int omap_hsmmc_have_reg(void) +@@ -568,7 +504,7 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) + OMAP_HSMMC_WRITE(host->base, SYSCTL, + OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN); + if ((OMAP_HSMMC_READ(host->base, SYSCTL) & CEN) != 0x0) +- dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n"); ++ dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stopped\n"); + } + + static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host, +@@ -577,13 +513,13 @@ static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host, + unsigned int irq_mask; + + if (host->use_dma) +- irq_mask = INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE); ++ irq_mask = INT_EN_MASK & ~(BRR_EN | BWR_EN); + else + irq_mask = INT_EN_MASK; + + /* Disable timeout for erases */ + if (cmd->opcode == MMC_ERASE) +- irq_mask &= ~DTO_ENABLE; ++ irq_mask &= ~DTO_EN; + + OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); + OMAP_HSMMC_WRITE(host->base, ISE, irq_mask); +@@ -598,14 +534,14 @@ static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host) + } + + /* Calculate divisor for the given clock frequency */ +-static u16 calc_divisor(struct mmc_ios *ios) ++static u16 calc_divisor(struct omap_hsmmc_host *host, struct mmc_ios *ios) + { + u16 dsor = 0; + + if (ios->clock) { +- dsor = DIV_ROUND_UP(OMAP_MMC_MASTER_CLOCK, ios->clock); +- if (dsor > 250) +- dsor = 250; ++ dsor = DIV_ROUND_UP(clk_get_rate(host->fclk), ios->clock); ++ if (dsor > CLKD_MAX) ++ dsor = CLKD_MAX; + } + + return dsor; +@@ -616,14 +552,16 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host) + struct mmc_ios *ios = &host->mmc->ios; + unsigned long regval; + unsigned long timeout; ++ unsigned long clkdiv; + +- dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock); ++ dev_vdbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock); + + omap_hsmmc_stop_clock(host); + + regval = OMAP_HSMMC_READ(host->base, SYSCTL); + regval = regval & ~(CLKD_MASK | DTO_MASK); +- regval = regval | (calc_divisor(ios) << 6) | (DTO << 16); ++ clkdiv = calc_divisor(host, ios); ++ regval = regval | (clkdiv << 6) | (DTO << 16); + OMAP_HSMMC_WRITE(host->base, SYSCTL, regval); + OMAP_HSMMC_WRITE(host->base, SYSCTL, + OMAP_HSMMC_READ(host->base, SYSCTL) | ICE); +@@ -634,6 +572,27 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host) + && time_before(jiffies, timeout)) + cpu_relax(); + ++ /* ++ * Enable High-Speed Support ++ * Pre-Requisites ++ * - Controller should support High-Speed-Enable Bit ++ * - Controller should not be using DDR Mode ++ * - Controller should advertise that it supports High Speed ++ * in capabilities register ++ * - MMC/SD clock coming out of controller > 25MHz ++ */ ++ if ((mmc_slot(host).features & HSMMC_HAS_HSPE_SUPPORT) && ++ (ios->timing != MMC_TIMING_MMC_DDR52) && ++ ((OMAP_HSMMC_READ(host->base, CAPA) & HSS) == HSS)) { ++ regval = OMAP_HSMMC_READ(host->base, HCTL); ++ if (clkdiv && (clk_get_rate(host->fclk)/clkdiv) > 25000000) ++ regval |= HSPE; ++ else ++ regval &= ~HSPE; ++ ++ OMAP_HSMMC_WRITE(host->base, HCTL, regval); ++ } ++ + omap_hsmmc_start_clock(host); + } + +@@ -643,6 +602,10 @@ static void omap_hsmmc_set_bus_width(struct omap_hsmmc_host *host) + u32 con; + + con = OMAP_HSMMC_READ(host->base, CON); ++ if (ios->timing == MMC_TIMING_MMC_DDR52) ++ con |= DDR; /* configure in DDR mode */ ++ else ++ con &= ~DDR; + switch (ios->bus_width) { + case MMC_BUS_WIDTH_8: + OMAP_HSMMC_WRITE(host->base, CON, con | DW8); +@@ -681,39 +644,18 @@ static void omap_hsmmc_set_bus_mode(struct omap_hsmmc_host *host) + static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) + { + struct mmc_ios *ios = &host->mmc->ios; +- struct omap_mmc_platform_data *pdata = host->pdata; +- int context_loss = 0; + u32 hctl, capa; + unsigned long timeout; + +- if (pdata->get_context_loss_count) { +- context_loss = pdata->get_context_loss_count(host->dev); +- if (context_loss < 0) +- return 1; +- } +- +- dev_dbg(mmc_dev(host->mmc), "context was %slost\n", +- context_loss == host->context_loss ? "not " : ""); +- if (host->context_loss == context_loss) +- return 1; +- +- /* Wait for hardware reset */ +- timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); +- while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE +- && time_before(jiffies, timeout)) +- ; +- +- /* Do software reset */ +- OMAP_HSMMC_WRITE(host->base, SYSCONFIG, SOFTRESET); +- timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); +- while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE +- && time_before(jiffies, timeout)) +- ; ++ if (host->con == OMAP_HSMMC_READ(host->base, CON) && ++ host->hctl == OMAP_HSMMC_READ(host->base, HCTL) && ++ host->sysctl == OMAP_HSMMC_READ(host->base, SYSCTL) && ++ host->capa == OMAP_HSMMC_READ(host->base, CAPA)) ++ return 0; + +- OMAP_HSMMC_WRITE(host->base, SYSCONFIG, +- OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE); ++ host->context_loss++; + +- if (host->id == OMAP_MMC1_DEVID) { ++ if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { + if (host->power_mode != MMC_POWER_OFF && + (1 << ios->vdd) <= MMC_VDD_23_24) + hctl = SDVS18; +@@ -752,9 +694,8 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) + omap_hsmmc_set_bus_mode(host); + + out: +- host->context_loss = context_loss; +- +- dev_dbg(mmc_dev(host->mmc), "context is restored\n"); ++ dev_dbg(mmc_dev(host->mmc), "context is restored: restore count %d\n", ++ host->context_loss); + return 0; + } + +@@ -763,15 +704,10 @@ out: + */ + static void omap_hsmmc_context_save(struct omap_hsmmc_host *host) + { +- struct omap_mmc_platform_data *pdata = host->pdata; +- int context_loss; +- +- if (pdata->get_context_loss_count) { +- context_loss = pdata->get_context_loss_count(host->dev); +- if (context_loss < 0) +- return; +- host->context_loss = context_loss; +- } ++ host->con = OMAP_HSMMC_READ(host->base, CON); ++ host->hctl = OMAP_HSMMC_READ(host->base, HCTL); ++ host->sysctl = OMAP_HSMMC_READ(host->base, SYSCTL); ++ host->capa = OMAP_HSMMC_READ(host->base, CAPA); + } + + #else +@@ -807,8 +743,8 @@ static void send_init_stream(struct omap_hsmmc_host *host) + OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD); + + timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); +- while ((reg != CC) && time_before(jiffies, timeout)) +- reg = OMAP_HSMMC_READ(host->base, STAT) & CC; ++ while ((reg != CC_EN) && time_before(jiffies, timeout)) ++ reg = OMAP_HSMMC_READ(host->base, STAT) & CC_EN; + + OMAP_HSMMC_WRITE(host->base, CON, + OMAP_HSMMC_READ(host->base, CON) & ~INIT_STREAM); +@@ -863,7 +799,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, + { + int cmdreg = 0, resptype = 0, cmdtype = 0; + +- dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n", ++ dev_vdbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n", + mmc_hostname(host->mmc), cmd->opcode, cmd->arg); + host->cmd = cmd; + +@@ -890,6 +826,11 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, + + cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22); + ++ if ((host->flags & AUTO_CMD23) && mmc_op_multi(cmd->opcode) && ++ host->mrq->sbc) { ++ cmdreg |= ACEN_ACMD23; ++ OMAP_HSMMC_WRITE(host->base, SDMASA, host->mrq->sbc->arg); ++ } + if (data) { + cmdreg |= DP_SELECT | MSBS | BCE; + if (data->flags & MMC_DATA_READ) +@@ -899,7 +840,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, + } + + if (host->use_dma) +- cmdreg |= DMA_EN; ++ cmdreg |= DMAE; + + host->req_in_progress = 1; + +@@ -916,14 +857,21 @@ omap_hsmmc_get_dma_dir(struct omap_hsmmc_host *host, struct mmc_data *data) + return DMA_FROM_DEVICE; + } + ++static struct dma_chan *omap_hsmmc_get_dma_chan(struct omap_hsmmc_host *host, ++ struct mmc_data *data) ++{ ++ return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan; ++} ++ + static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_request *mrq) + { + int dma_ch; ++ unsigned long flags; + +- spin_lock(&host->irq_lock); ++ spin_lock_irqsave(&host->irq_lock, flags); + host->req_in_progress = 0; + dma_ch = host->dma_ch; +- spin_unlock(&host->irq_lock); ++ spin_unlock_irqrestore(&host->irq_lock, flags); + + omap_hsmmc_disable_irq(host); + /* Do not complete the request if DMA is still in progress */ +@@ -960,11 +908,10 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) + else + data->bytes_xfered = 0; + +- if (!data->stop) { ++ if (data->stop && (data->error || !host->mrq->sbc)) ++ omap_hsmmc_start_command(host, data->stop, NULL); ++ else + omap_hsmmc_request_done(host, data->mrq); +- return; +- } +- omap_hsmmc_start_command(host, data->stop, NULL); + } + + /* +@@ -973,6 +920,15 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) + static void + omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) + { ++ if (host->mrq->sbc && (host->cmd == host->mrq->sbc) && ++ !host->mrq->sbc->error && !(host->flags & AUTO_CMD23)) { ++ host->cmd = NULL; ++ omap_hsmmc_start_dma_transfer(host); ++ omap_hsmmc_start_command(host, host->mrq->cmd, ++ host->mrq->data); ++ return; ++ } ++ + host->cmd = NULL; + + if (cmd->flags & MMC_RSP_PRESENT) { +@@ -988,7 +944,7 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) + } + } + if ((host->data == NULL && !host->response_busy) || cmd->error) +- omap_hsmmc_request_done(host, cmd->mrq); ++ omap_hsmmc_request_done(host, host->mrq); + } + + /* +@@ -997,19 +953,23 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) + static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) + { + int dma_ch; ++ unsigned long flags; + + host->data->error = errno; + +- spin_lock(&host->irq_lock); ++ spin_lock_irqsave(&host->irq_lock, flags); + dma_ch = host->dma_ch; + host->dma_ch = -1; +- spin_unlock(&host->irq_lock); ++ spin_unlock_irqrestore(&host->irq_lock, flags); + + if (host->use_dma && dma_ch != -1) { +- dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, +- host->data->sg_len, ++ struct dma_chan *chan = omap_hsmmc_get_dma_chan(host, host->data); ++ ++ dmaengine_terminate_all(chan); ++ dma_unmap_sg(chan->device->dev, ++ host->data->sg, host->data->sg_len, + omap_hsmmc_get_dma_dir(host, host->data)); +- omap_free_dma(dma_ch); ++ + host->data->host_cookie = 0; + } + host->data = NULL; +@@ -1041,7 +1001,7 @@ static void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, u32 status) + buf += len; + } + +- dev_dbg(mmc_dev(host->mmc), "%s\n", res); ++ dev_vdbg(mmc_dev(host->mmc), "%s\n", res); + } + #else + static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, +@@ -1061,8 +1021,7 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, + unsigned long bit) + { + unsigned long i = 0; +- unsigned long limit = (loops_per_jiffy * +- msecs_to_jiffies(MMC_TIMEOUT_MS)); ++ unsigned long limit = MMC_TIMEOUT_US; + + OMAP_HSMMC_WRITE(host->base, SYSCTL, + OMAP_HSMMC_READ(host->base, SYSCTL) | bit); +@@ -1074,13 +1033,13 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, + if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) { + while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) + && (i++ < limit)) +- cpu_relax(); ++ udelay(1); + } + i = 0; + + while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) && + (i++ < limit)) +- cpu_relax(); ++ udelay(1); + + if (OMAP_HSMMC_READ(host->base, SYSCTL) & bit) + dev_err(mmc_dev(host->mmc), +@@ -1088,75 +1047,65 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, + __func__); + } + ++static void hsmmc_command_incomplete(struct omap_hsmmc_host *host, ++ int err, int end_cmd) ++{ ++ if (end_cmd) { ++ omap_hsmmc_reset_controller_fsm(host, SRC); ++ if (host->cmd) ++ host->cmd->error = err; ++ } ++ ++ if (host->data) { ++ omap_hsmmc_reset_controller_fsm(host, SRD); ++ omap_hsmmc_dma_cleanup(host, err); ++ } else if (host->mrq && host->mrq->cmd) ++ host->mrq->cmd->error = err; ++} ++ + static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) + { + struct mmc_data *data; + int end_cmd = 0, end_trans = 0; +- +- if (!host->req_in_progress) { +- do { +- OMAP_HSMMC_WRITE(host->base, STAT, status); +- /* Flush posted write */ +- status = OMAP_HSMMC_READ(host->base, STAT); +- } while (status & INT_EN_MASK); +- return; +- } ++ int error = 0; + + data = host->data; +- dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); ++ dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); + +- if (status & ERR) { ++ if (status & ERR_EN) { + omap_hsmmc_dbg_report_irq(host, status); +- if ((status & CMD_TIMEOUT) || +- (status & CMD_CRC)) { +- if (host->cmd) { +- if (status & CMD_TIMEOUT) { +- omap_hsmmc_reset_controller_fsm(host, +- SRC); +- host->cmd->error = -ETIMEDOUT; +- } else { +- host->cmd->error = -EILSEQ; +- } ++ ++ if (status & (CTO_EN | CCRC_EN)) ++ end_cmd = 1; ++ if (status & (CTO_EN | DTO_EN)) ++ hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd); ++ else if (status & (CCRC_EN | DCRC_EN)) ++ hsmmc_command_incomplete(host, -EILSEQ, end_cmd); ++ ++ if (status & ACE_EN) { ++ u32 ac12; ++ ac12 = OMAP_HSMMC_READ(host->base, AC12); ++ if (!(ac12 & ACNE) && host->mrq->sbc) { + end_cmd = 1; ++ if (ac12 & ACTO) ++ error = -ETIMEDOUT; ++ else if (ac12 & (ACCE | ACEB | ACIE)) ++ error = -EILSEQ; ++ host->mrq->sbc->error = error; ++ hsmmc_command_incomplete(host, error, end_cmd); + } +- if (host->data || host->response_busy) { +- if (host->data) +- omap_hsmmc_dma_cleanup(host, +- -ETIMEDOUT); +- host->response_busy = 0; +- omap_hsmmc_reset_controller_fsm(host, SRD); +- } +- } +- if ((status & DATA_TIMEOUT) || +- (status & DATA_CRC)) { +- if (host->data || host->response_busy) { +- int err = (status & DATA_TIMEOUT) ? +- -ETIMEDOUT : -EILSEQ; +- +- if (host->data) +- omap_hsmmc_dma_cleanup(host, err); +- else +- host->mrq->cmd->error = err; +- host->response_busy = 0; +- omap_hsmmc_reset_controller_fsm(host, SRD); +- end_trans = 1; +- } ++ dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12); + } +- if (status & CARD_ERR) { +- dev_dbg(mmc_dev(host->mmc), +- "Ignoring card err CMD%d\n", host->cmd->opcode); +- if (host->cmd) +- end_cmd = 1; +- if (host->data) +- end_trans = 1; ++ if (host->data || host->response_busy) { ++ end_trans = !end_cmd; ++ host->response_busy = 0; + } + } + + OMAP_HSMMC_WRITE(host->base, STAT, status); +- +- if (end_cmd || ((status & CC) && host->cmd)) ++ if (end_cmd || ((status & CC_EN) && host->cmd)) + omap_hsmmc_cmd_done(host, host->cmd); +- if ((end_trans || (status & TC)) && host->mrq) ++ if ((end_trans || (status & TC_EN)) && host->mrq) + omap_hsmmc_xfer_done(host, data); + } + +@@ -1169,11 +1118,12 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) + int status; + + status = OMAP_HSMMC_READ(host->base, STAT); +- do { ++ while (status & INT_EN_MASK && host->req_in_progress) { + omap_hsmmc_do_irq(host, status); ++ + /* Flush posted write */ + status = OMAP_HSMMC_READ(host->base, STAT); +- } while (status & INT_EN_MASK); ++ } + + return IRQ_HANDLED; + } +@@ -1205,8 +1155,8 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) + + /* Disable the clocks */ + pm_runtime_put_sync(host->dev); +- if (host->got_dbclk) +- clk_disable(host->dbclk); ++ if (host->dbclk) ++ clk_disable_unprepare(host->dbclk); + + /* Turn the power off */ + ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); +@@ -1216,8 +1166,8 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) + ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1, + vdd); + pm_runtime_get_sync(host->dev); +- if (host->got_dbclk) +- clk_enable(host->dbclk); ++ if (host->dbclk) ++ clk_prepare_enable(host->dbclk); + + if (ret != 0) + goto err; +@@ -1251,7 +1201,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) + + return 0; + err: +- dev_dbg(mmc_dev(host->mmc), "Unable to switch operating voltage\n"); ++ dev_err(mmc_dev(host->mmc), "Unable to switch operating voltage\n"); + return ret; + } + +@@ -1264,14 +1214,14 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) + host->reqs_blocked = 0; + if (mmc_slot(host).get_cover_state(host->dev, host->slot_id)) { + if (host->protect_card) { +- pr_info("%s: cover is closed, " ++ dev_info(host->dev, "%s: cover is closed, " + "card is now accessible\n", + mmc_hostname(host->mmc)); + host->protect_card = 0; + } + } else { + if (!host->protect_card) { +- pr_info("%s: cover is open, " ++ dev_info(host->dev, "%s: cover is open, " + "card is now inaccessible\n", + mmc_hostname(host->mmc)); + host->protect_card = 1; +@@ -1280,18 +1230,14 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) + } + + /* +- * Work Item to notify the core about card insertion/removal ++ * irq handler to notify the core about card insertion/removal + */ +-static void omap_hsmmc_detect(struct work_struct *work) ++static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) + { +- struct omap_hsmmc_host *host = +- container_of(work, struct omap_hsmmc_host, mmc_carddetect_work); ++ struct omap_hsmmc_host *host = dev_id; + struct omap_mmc_slot_data *slot = &mmc_slot(host); + int carddetect; + +- if (host->suspended) +- return; +- + sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); + + if (slot->card_detect) +@@ -1305,105 +1251,32 @@ static void omap_hsmmc_detect(struct work_struct *work) + mmc_detect_change(host->mmc, (HZ * 200) / 1000); + else + mmc_detect_change(host->mmc, (HZ * 50) / 1000); +-} +- +-/* +- * ISR for handling card insertion and removal +- */ +-static irqreturn_t omap_hsmmc_cd_handler(int irq, void *dev_id) +-{ +- struct omap_hsmmc_host *host = (struct omap_hsmmc_host *)dev_id; +- +- if (host->suspended) +- return IRQ_HANDLED; +- schedule_work(&host->mmc_carddetect_work); +- + return IRQ_HANDLED; + } + +-static int omap_hsmmc_get_dma_sync_dev(struct omap_hsmmc_host *host, +- struct mmc_data *data) ++static void omap_hsmmc_dma_callback(void *param) + { +- int sync_dev; +- +- if (data->flags & MMC_DATA_WRITE) +- sync_dev = host->dma_line_tx; +- else +- sync_dev = host->dma_line_rx; +- return sync_dev; +-} +- +-static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host, +- struct mmc_data *data, +- struct scatterlist *sgl) +-{ +- int blksz, nblk, dma_ch; +- +- dma_ch = host->dma_ch; +- if (data->flags & MMC_DATA_WRITE) { +- omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, +- (host->mapbase + OMAP_HSMMC_DATA), 0, 0); +- omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC, +- sg_dma_address(sgl), 0, 0); +- } else { +- omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, +- (host->mapbase + OMAP_HSMMC_DATA), 0, 0); +- omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC, +- sg_dma_address(sgl), 0, 0); +- } +- +- blksz = host->data->blksz; +- nblk = sg_dma_len(sgl) / blksz; +- +- omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, +- blksz / 4, nblk, OMAP_DMA_SYNC_FRAME, +- omap_hsmmc_get_dma_sync_dev(host, data), +- !(data->flags & MMC_DATA_WRITE)); +- +- omap_start_dma(dma_ch); +-} +- +-/* +- * DMA call back function +- */ +-static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) +-{ +- struct omap_hsmmc_host *host = cb_data; ++ struct omap_hsmmc_host *host = param; ++ struct dma_chan *chan; + struct mmc_data *data; +- int dma_ch, req_in_progress; ++ int req_in_progress; + +- if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) { +- dev_warn(mmc_dev(host->mmc), "unexpected dma status %x\n", +- ch_status); +- return; +- } +- +- spin_lock(&host->irq_lock); ++ spin_lock_irq(&host->irq_lock); + if (host->dma_ch < 0) { +- spin_unlock(&host->irq_lock); ++ spin_unlock_irq(&host->irq_lock); + return; + } + + data = host->mrq->data; +- host->dma_sg_idx++; +- if (host->dma_sg_idx < host->dma_len) { +- /* Fire up the next transfer. */ +- omap_hsmmc_config_dma_params(host, data, +- data->sg + host->dma_sg_idx); +- spin_unlock(&host->irq_lock); +- return; +- } +- ++ chan = omap_hsmmc_get_dma_chan(host, data); + if (!data->host_cookie) +- dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, ++ dma_unmap_sg(chan->device->dev, ++ data->sg, data->sg_len, + omap_hsmmc_get_dma_dir(host, data)); + + req_in_progress = host->req_in_progress; +- dma_ch = host->dma_ch; + host->dma_ch = -1; +- spin_unlock(&host->irq_lock); +- +- omap_free_dma(dma_ch); ++ spin_unlock_irq(&host->irq_lock); + + /* If DMA has finished after TC, complete the request */ + if (!req_in_progress) { +@@ -1416,23 +1289,22 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) + + static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host, + struct mmc_data *data, +- struct omap_hsmmc_next *next) ++ struct omap_hsmmc_next *next, ++ struct dma_chan *chan) + { + int dma_len; + + if (!next && data->host_cookie && + data->host_cookie != host->next_data.cookie) { +- pr_warning("[%s] invalid cookie: data->host_cookie %d" ++ dev_warn(host->dev, "[%s] invalid cookie: data->host_cookie %d" + " host->next_data.cookie %d\n", + __func__, data->host_cookie, host->next_data.cookie); + data->host_cookie = 0; + } + + /* Check if next job is already prepared */ +- if (next || +- (!next && data->host_cookie != host->next_data.cookie)) { +- dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, +- data->sg_len, ++ if (next || data->host_cookie != host->next_data.cookie) { ++ dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len, + omap_hsmmc_get_dma_dir(host, data)); + + } else { +@@ -1456,11 +1328,14 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host, + /* + * Routine to configure and start DMA for the MMC card + */ +-static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, ++static int omap_hsmmc_setup_dma_transfer(struct omap_hsmmc_host *host, + struct mmc_request *req) + { +- int dma_ch = 0, ret = 0, i; ++ struct dma_slave_config cfg; ++ struct dma_async_tx_descriptor *tx; ++ int ret = 0, i; + struct mmc_data *data = req->data; ++ struct dma_chan *chan; + + /* Sanity check: all the SG entries must be aligned by block size. */ + for (i = 0; i < data->sg_len; i++) { +@@ -1478,22 +1353,39 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, + + BUG_ON(host->dma_ch != -1); + +- ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data), +- "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch); +- if (ret != 0) { +- dev_err(mmc_dev(host->mmc), +- "%s: omap_request_dma() failed with %d\n", +- mmc_hostname(host->mmc), ret); ++ chan = omap_hsmmc_get_dma_chan(host, data); ++ ++ cfg.src_addr = host->mapbase + OMAP_HSMMC_DATA; ++ cfg.dst_addr = host->mapbase + OMAP_HSMMC_DATA; ++ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ cfg.src_maxburst = data->blksz / 4; ++ cfg.dst_maxburst = data->blksz / 4; ++ ++ ret = dmaengine_slave_config(chan, &cfg); ++ if (ret) + return ret; +- } +- ret = omap_hsmmc_pre_dma_transfer(host, data, NULL); ++ ++ ret = omap_hsmmc_pre_dma_transfer(host, data, NULL, chan); + if (ret) + return ret; + +- host->dma_ch = dma_ch; +- host->dma_sg_idx = 0; ++ tx = dmaengine_prep_slave_sg(chan, data->sg, data->sg_len, ++ data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!tx) { ++ dev_err(mmc_dev(host->mmc), "prep_slave_sg() failed\n"); ++ /* FIXME: cleanup */ ++ return -1; ++ } ++ ++ tx->callback = omap_hsmmc_dma_callback; ++ tx->callback_param = host; ++ ++ /* Does not fail */ ++ dmaengine_submit(tx); + +- omap_hsmmc_config_dma_params(host, data, data->sg); ++ host->dma_ch = 1; + + return 0; + } +@@ -1510,7 +1402,7 @@ static void set_data_timeout(struct omap_hsmmc_host *host, + if (clkd == 0) + clkd = 1; + +- cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd); ++ cycle_ns = 1000000000 / (host->clk_rate / clkd); + timeout = timeout_ns / cycle_ns; + timeout += timeout_clks; + if (timeout) { +@@ -1535,6 +1427,21 @@ static void set_data_timeout(struct omap_hsmmc_host *host, + OMAP_HSMMC_WRITE(host->base, SYSCTL, reg); + } + ++static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host) ++{ ++ struct mmc_request *req = host->mrq; ++ struct dma_chan *chan; ++ ++ if (!req->data) ++ return; ++ OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz) ++ | (req->data->blocks << 16)); ++ set_data_timeout(host, req->data->timeout_ns, ++ req->data->timeout_clks); ++ chan = omap_hsmmc_get_dma_chan(host, req->data); ++ dma_async_issue_pending(chan); ++} ++ + /* + * Configure block length for MMC/SD cards and initiate the transfer. + */ +@@ -1555,14 +1462,10 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req) + return 0; + } + +- OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz) +- | (req->data->blocks << 16)); +- set_data_timeout(host, req->data->timeout_ns, req->data->timeout_clks); +- + if (host->use_dma) { +- ret = omap_hsmmc_start_dma_transfer(host, req); ++ ret = omap_hsmmc_setup_dma_transfer(host, req); + if (ret != 0) { +- dev_dbg(mmc_dev(host->mmc), "MMC start dma failure\n"); ++ dev_err(mmc_dev(host->mmc), "MMC start dma failure\n"); + return ret; + } + } +@@ -1575,11 +1478,11 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, + struct omap_hsmmc_host *host = mmc_priv(mmc); + struct mmc_data *data = mrq->data; + +- if (host->use_dma) { +- if (data->host_cookie) +- dma_unmap_sg(mmc_dev(host->mmc), data->sg, +- data->sg_len, +- omap_hsmmc_get_dma_dir(host, data)); ++ if (host->use_dma && data->host_cookie) { ++ struct dma_chan *c = omap_hsmmc_get_dma_chan(host, data); ++ ++ dma_unmap_sg(c->device->dev, data->sg, data->sg_len, ++ omap_hsmmc_get_dma_dir(host, data)); + data->host_cookie = 0; + } + } +@@ -1594,10 +1497,13 @@ static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, + return ; + } + +- if (host->use_dma) ++ if (host->use_dma) { ++ struct dma_chan *c = omap_hsmmc_get_dma_chan(host, mrq->data); ++ + if (omap_hsmmc_pre_dma_transfer(host, mrq->data, +- &host->next_data)) ++ &host->next_data, c)) + mrq->data->host_cookie = 0; ++ } + } + + /* +@@ -1631,6 +1537,7 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) + host->reqs_blocked = 0; + WARN_ON(host->mrq != NULL); + host->mrq = req; ++ host->clk_rate = clk_get_rate(host->fclk); + err = omap_hsmmc_prepare_data(host, req); + if (err) { + req->cmd->error = err; +@@ -1640,7 +1547,12 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) + mmc_request_done(mmc, req); + return; + } ++ if (req->sbc && !(host->flags & AUTO_CMD23)) { ++ omap_hsmmc_start_command(host, req->sbc, NULL); ++ return; ++ } + ++ omap_hsmmc_start_dma_transfer(host); + omap_hsmmc_start_command(host, req->cmd, req->data); + } + +@@ -1657,12 +1569,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + case MMC_POWER_OFF: + mmc_slot(host).set_power(host->dev, host->slot_id, + 0, 0); +- host->vdd = 0; + break; + case MMC_POWER_UP: + mmc_slot(host).set_power(host->dev, host->slot_id, + 1, ios->vdd); +- host->vdd = ios->vdd; + break; + case MMC_POWER_ON: + do_send_init_stream = 1; +@@ -1748,10 +1658,6 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) + value = OMAP_HSMMC_READ(host->base, CAPA); + OMAP_HSMMC_WRITE(host->base, CAPA, value | capa); + +- /* Set the controller to AUTO IDLE mode */ +- value = OMAP_HSMMC_READ(host->base, SYSCONFIG); +- OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE); +- + /* Set SD bus power bit */ + set_sd_bus_power(host); + } +@@ -1765,7 +1671,7 @@ static int omap_hsmmc_enable_fclk(struct mmc_host *mmc) + return 0; + } + +-static int omap_hsmmc_disable_fclk(struct mmc_host *mmc, int lazy) ++static int omap_hsmmc_disable_fclk(struct mmc_host *mmc) + { + struct omap_hsmmc_host *host = mmc_priv(mmc); + +@@ -1794,30 +1700,12 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data) + { + struct mmc_host *mmc = s->private; + struct omap_hsmmc_host *host = mmc_priv(mmc); +- int context_loss = 0; +- +- if (host->pdata->get_context_loss_count) +- context_loss = host->pdata->get_context_loss_count(host->dev); +- +- seq_printf(s, "mmc%d:\n" +- " enabled:\t%d\n" +- " dpm_state:\t%d\n" +- " nesting_cnt:\t%d\n" +- " ctx_loss:\t%d:%d\n" +- "\nregs:\n", +- mmc->index, mmc->enabled ? 1 : 0, +- host->dpm_state, mmc->nesting_cnt, +- host->context_loss, context_loss); +- +- if (host->suspended) { +- seq_printf(s, "host suspended, can't read registers\n"); +- return 0; +- } ++ ++ seq_printf(s, "mmc%d:\n ctx_loss:\t%d\n\nregs:\n", ++ mmc->index, host->context_loss); + + pm_runtime_get_sync(host->dev); + +- seq_printf(s, "SYSCONFIG:\t0x%08x\n", +- OMAP_HSMMC_READ(host->base, SYSCONFIG)); + seq_printf(s, "CON:\t\t0x%08x\n", + OMAP_HSMMC_READ(host->base, CON)); + seq_printf(s, "HCTL:\t\t0x%08x\n", +@@ -1864,13 +1752,121 @@ static void omap_hsmmc_debugfs(struct mmc_host *mmc) + + #endif + +-static int __init omap_hsmmc_probe(struct platform_device *pdev) ++#ifdef CONFIG_OF ++static const struct omap_mmc_of_data omap3_pre_es3_mmc_of_data = { ++ /* See 35xx errata 2.1.1.128 in SPRZ278F */ ++ .controller_flags = OMAP_HSMMC_BROKEN_MULTIBLOCK_READ, ++}; ++ ++static const struct omap_mmc_of_data omap4_mmc_of_data = { ++ .reg_offset = 0x100, ++}; ++ ++static const struct of_device_id omap_mmc_of_match[] = { ++ { ++ .compatible = "ti,omap2-hsmmc", ++ }, ++ { ++ .compatible = "ti,omap3-pre-es3-hsmmc", ++ .data = &omap3_pre_es3_mmc_of_data, ++ }, ++ { ++ .compatible = "ti,omap3-hsmmc", ++ }, ++ { ++ .compatible = "ti,omap4-hsmmc", ++ .data = &omap4_mmc_of_data, ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, omap_mmc_of_match); ++ ++static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) ++{ ++ struct omap_mmc_platform_data *pdata; ++ struct device_node *np = dev->of_node; ++ u32 bus_width, max_freq; ++ int cd_gpio, wp_gpio; ++ ++ cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); ++ wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); ++ if (cd_gpio == -EPROBE_DEFER || wp_gpio == -EPROBE_DEFER) ++ return ERR_PTR(-EPROBE_DEFER); ++ ++ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return ERR_PTR(-ENOMEM); /* out of memory */ ++ ++ if (of_find_property(np, "ti,dual-volt", NULL)) ++ pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT; ++ ++ /* This driver only supports 1 slot */ ++ pdata->nr_slots = 1; ++ pdata->slots[0].switch_pin = cd_gpio; ++ pdata->slots[0].gpio_wp = wp_gpio; ++ ++ if (of_find_property(np, "ti,non-removable", NULL)) { ++ pdata->slots[0].nonremovable = true; ++ pdata->slots[0].no_regulator_off_init = true; ++ } ++ of_property_read_u32(np, "bus-width", &bus_width); ++ if (bus_width == 4) ++ pdata->slots[0].caps |= MMC_CAP_4_BIT_DATA; ++ else if (bus_width == 8) ++ pdata->slots[0].caps |= MMC_CAP_8_BIT_DATA; ++ ++ if (of_find_property(np, "ti,needs-special-reset", NULL)) ++ pdata->slots[0].features |= HSMMC_HAS_UPDATED_RESET; ++ ++ if (!of_property_read_u32(np, "max-frequency", &max_freq)) ++ pdata->max_freq = max_freq; ++ ++ if (of_find_property(np, "ti,needs-special-hs-handling", NULL)) ++ pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT; ++ ++ if (of_find_property(np, "keep-power-in-suspend", NULL)) ++ pdata->slots[0].pm_caps |= MMC_PM_KEEP_POWER; ++ ++ if (of_find_property(np, "enable-sdio-wakeup", NULL)) ++ pdata->slots[0].pm_caps |= MMC_PM_WAKE_SDIO_IRQ; ++ ++ return pdata; ++} ++#else ++static inline struct omap_mmc_platform_data ++ *of_get_hsmmc_pdata(struct device *dev) ++{ ++ return ERR_PTR(-EINVAL); ++} ++#endif ++ ++static int omap_hsmmc_probe(struct platform_device *pdev) + { + struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; + struct mmc_host *mmc; + struct omap_hsmmc_host *host = NULL; + struct resource *res; + int ret, irq; ++ const struct of_device_id *match; ++ dma_cap_mask_t mask; ++ unsigned tx_req, rx_req; ++ struct pinctrl *pinctrl; ++ const struct omap_mmc_of_data *data; ++ void __iomem *base; ++ ++ match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev); ++ if (match) { ++ pdata = of_get_hsmmc_pdata(&pdev->dev); ++ ++ if (IS_ERR(pdata)) ++ return PTR_ERR(pdata); ++ ++ if (match->data) { ++ data = match->data; ++ pdata->reg_offset = data->reg_offset; ++ pdata->controller_flags |= data->controller_flags; ++ } ++ } + + if (pdata == NULL) { + dev_err(&pdev->dev, "Platform Data is missing\n"); +@@ -1887,11 +1883,9 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) + if (res == NULL || irq < 0) + return -ENXIO; + +- res->start += pdata->reg_offset; +- res->end += pdata->reg_offset; +- res = request_mem_region(res->start, resource_size(res), pdev->name); +- if (res == NULL) +- return -EBUSY; ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); + + ret = omap_hsmmc_gpio_init(pdata); + if (ret) +@@ -1908,43 +1902,35 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) + host->pdata = pdata; + host->dev = &pdev->dev; + host->use_dma = 1; +- host->dev->dma_mask = &pdata->dma_mask; + host->dma_ch = -1; + host->irq = irq; +- host->id = pdev->id; + host->slot_id = 0; +- host->mapbase = res->start; +- host->base = ioremap(host->mapbase, SZ_4K); ++ host->mapbase = res->start + pdata->reg_offset; ++ host->base = base + pdata->reg_offset; + host->power_mode = MMC_POWER_OFF; + host->next_data.cookie = 1; ++ host->pbias_enabled = 0; + + platform_set_drvdata(pdev, host); +- INIT_WORK(&host->mmc_carddetect_work, omap_hsmmc_detect); + + mmc->ops = &omap_hsmmc_ops; + +- /* +- * If regulator_disable can only put vcc_aux to sleep then there is +- * no off state. +- */ +- if (mmc_slot(host).vcc_aux_disable_is_sleep) +- mmc_slot(host).no_off = 1; ++ mmc->f_min = OMAP_MMC_MIN_CLOCK; + +- mmc->f_min = OMAP_MMC_MIN_CLOCK; +- mmc->f_max = OMAP_MMC_MAX_CLOCK; ++ if (pdata->max_freq > 0) ++ mmc->f_max = pdata->max_freq; ++ else ++ mmc->f_max = OMAP_MMC_MAX_CLOCK; + + spin_lock_init(&host->irq_lock); + +- host->fclk = clk_get(&pdev->dev, "fck"); ++ host->fclk = devm_clk_get(&pdev->dev, "fck"); + if (IS_ERR(host->fclk)) { + ret = PTR_ERR(host->fclk); + host->fclk = NULL; + goto err1; + } + +- omap_hsmmc_context_save(host); +- +- mmc->caps |= MMC_CAP_DISABLE; + if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) { + dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n"); + mmc->caps2 |= MMC_CAP2_NO_MULTI_READ; +@@ -1955,21 +1941,17 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) + pm_runtime_set_autosuspend_delay(host->dev, MMC_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(host->dev); + +- if (cpu_is_omap2430()) { +- host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); +- /* +- * MMC can still work without debounce clock. +- */ +- if (IS_ERR(host->dbclk)) +- dev_warn(mmc_dev(host->mmc), +- "Failed to get debounce clock\n"); +- else +- host->got_dbclk = 1; ++ omap_hsmmc_context_save(host); + +- if (host->got_dbclk) +- if (clk_enable(host->dbclk) != 0) +- dev_dbg(mmc_dev(host->mmc), "Enabling debounce" +- " clk failed\n"); ++ host->dbclk = devm_clk_get(&pdev->dev, "mmchsdb_fck"); ++ /* ++ * MMC can still work without debounce clock. ++ */ ++ if (IS_ERR(host->dbclk)) { ++ host->dbclk = NULL; ++ } else if (clk_prepare_enable(host->dbclk) != 0) { ++ dev_warn(mmc_dev(host->mmc), "Failed to enable debounce clk\n"); ++ host->dbclk = NULL; + } + + /* Since we do only SG emulation, we can have as many segs +@@ -1991,48 +1973,64 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) + if (mmc_slot(host).nonremovable) + mmc->caps |= MMC_CAP_NONREMOVABLE; + ++ mmc->pm_caps = mmc_slot(host).pm_caps; ++ + omap_hsmmc_conf_bus_power(host); + +- /* Select DMA lines */ +- switch (host->id) { +- case OMAP_MMC1_DEVID: +- host->dma_line_tx = OMAP24XX_DMA_MMC1_TX; +- host->dma_line_rx = OMAP24XX_DMA_MMC1_RX; +- break; +- case OMAP_MMC2_DEVID: +- host->dma_line_tx = OMAP24XX_DMA_MMC2_TX; +- host->dma_line_rx = OMAP24XX_DMA_MMC2_RX; +- break; +- case OMAP_MMC3_DEVID: +- host->dma_line_tx = OMAP34XX_DMA_MMC3_TX; +- host->dma_line_rx = OMAP34XX_DMA_MMC3_RX; +- break; +- case OMAP_MMC4_DEVID: +- host->dma_line_tx = OMAP44XX_DMA_MMC4_TX; +- host->dma_line_rx = OMAP44XX_DMA_MMC4_RX; +- break; +- case OMAP_MMC5_DEVID: +- host->dma_line_tx = OMAP44XX_DMA_MMC5_TX; +- host->dma_line_rx = OMAP44XX_DMA_MMC5_RX; +- break; +- default: +- dev_err(mmc_dev(host->mmc), "Invalid MMC id\n"); ++ if (!pdev->dev.of_node) { ++ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); ++ if (!res) { ++ dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n"); ++ ret = -ENXIO; ++ goto err_irq; ++ } ++ tx_req = res->start; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); ++ if (!res) { ++ dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n"); ++ ret = -ENXIO; ++ goto err_irq; ++ } ++ rx_req = res->start; ++ } ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ ++ host->rx_chan = ++ dma_request_slave_channel_compat(mask, omap_dma_filter_fn, ++ &rx_req, &pdev->dev, "rx"); ++ ++ if (!host->rx_chan) { ++ dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", rx_req); ++ ret = -ENXIO; ++ goto err_irq; ++ } ++ ++ host->tx_chan = ++ dma_request_slave_channel_compat(mask, omap_dma_filter_fn, ++ &tx_req, &pdev->dev, "tx"); ++ ++ if (!host->tx_chan) { ++ dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", tx_req); ++ ret = -ENXIO; + goto err_irq; + } + + /* Request IRQ for MMC operations */ +- ret = request_irq(host->irq, omap_hsmmc_irq, 0, ++ ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0, + mmc_hostname(mmc), host); + if (ret) { +- dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n"); ++ dev_err(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n"); + goto err_irq; + } + + if (pdata->init != NULL) { + if (pdata->init(&pdev->dev) != 0) { +- dev_dbg(mmc_dev(host->mmc), ++ dev_err(mmc_dev(host->mmc), + "Unable to configure MMC IRQs\n"); +- goto err_irq_cd_init; ++ goto err_irq; + } + } + +@@ -2047,12 +2045,13 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) + + /* Request IRQ for card detect */ + if ((mmc_slot(host).card_detect_irq)) { +- ret = request_irq(mmc_slot(host).card_detect_irq, +- omap_hsmmc_cd_handler, +- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, +- mmc_hostname(mmc), host); ++ ret = devm_request_threaded_irq(&pdev->dev, ++ mmc_slot(host).card_detect_irq, ++ NULL, omap_hsmmc_detect, ++ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ++ mmc_hostname(mmc), host); + if (ret) { +- dev_dbg(mmc_dev(host->mmc), ++ dev_err(mmc_dev(host->mmc), + "Unable to grab MMC CD IRQ\n"); + goto err_irq_cd; + } +@@ -2062,6 +2061,11 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) + + omap_hsmmc_disable_irq(host); + ++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev); ++ if (IS_ERR(pinctrl)) ++ dev_warn(&pdev->dev, ++ "pins are not configured from the driver\n"); ++ + omap_hsmmc_protect_card(host); + + mmc_add_host(mmc); +@@ -2086,161 +2090,126 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) + + err_slot_name: + mmc_remove_host(mmc); +- free_irq(mmc_slot(host).card_detect_irq, host); + err_irq_cd: + if (host->use_reg) + omap_hsmmc_reg_put(host); + err_reg: + if (host->pdata->cleanup) + host->pdata->cleanup(&pdev->dev); +-err_irq_cd_init: +- free_irq(host->irq, host); + err_irq: +- pm_runtime_mark_last_busy(host->dev); +- pm_runtime_put_autosuspend(host->dev); +- clk_put(host->fclk); +- if (host->got_dbclk) { +- clk_disable(host->dbclk); +- clk_put(host->dbclk); +- } ++ if (host->tx_chan) ++ dma_release_channel(host->tx_chan); ++ if (host->rx_chan) ++ dma_release_channel(host->rx_chan); ++ pm_runtime_put_sync(host->dev); ++ pm_runtime_disable(host->dev); ++ if (host->dbclk) ++ clk_disable_unprepare(host->dbclk); + err1: +- iounmap(host->base); +- platform_set_drvdata(pdev, NULL); + mmc_free_host(mmc); + err_alloc: + omap_hsmmc_gpio_free(pdata); + err: +- release_mem_region(res->start, resource_size(res)); + return ret; + } + + static int omap_hsmmc_remove(struct platform_device *pdev) + { + struct omap_hsmmc_host *host = platform_get_drvdata(pdev); +- struct resource *res; + +- if (host) { +- pm_runtime_get_sync(host->dev); +- mmc_remove_host(host->mmc); +- if (host->use_reg) +- omap_hsmmc_reg_put(host); +- if (host->pdata->cleanup) +- host->pdata->cleanup(&pdev->dev); +- free_irq(host->irq, host); +- if (mmc_slot(host).card_detect_irq) +- free_irq(mmc_slot(host).card_detect_irq, host); +- flush_work_sync(&host->mmc_carddetect_work); +- +- pm_runtime_put_sync(host->dev); +- pm_runtime_disable(host->dev); +- clk_put(host->fclk); +- if (host->got_dbclk) { +- clk_disable(host->dbclk); +- clk_put(host->dbclk); +- } ++ pm_runtime_get_sync(host->dev); ++ mmc_remove_host(host->mmc); ++ if (host->use_reg) ++ omap_hsmmc_reg_put(host); ++ if (host->pdata->cleanup) ++ host->pdata->cleanup(&pdev->dev); + +- mmc_free_host(host->mmc); +- iounmap(host->base); +- omap_hsmmc_gpio_free(pdev->dev.platform_data); +- } ++ if (host->tx_chan) ++ dma_release_channel(host->tx_chan); ++ if (host->rx_chan) ++ dma_release_channel(host->rx_chan); + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (res) +- release_mem_region(res->start, resource_size(res)); +- platform_set_drvdata(pdev, NULL); ++ pm_runtime_put_sync(host->dev); ++ pm_runtime_disable(host->dev); ++ if (host->dbclk) ++ clk_disable_unprepare(host->dbclk); ++ ++ omap_hsmmc_gpio_free(host->pdata); ++ mmc_free_host(host->mmc); + + return 0; + } + + #ifdef CONFIG_PM ++static int omap_hsmmc_prepare(struct device *dev) ++{ ++ struct omap_hsmmc_host *host = dev_get_drvdata(dev); ++ ++ if (host->pdata->suspend) ++ return host->pdata->suspend(dev, host->slot_id); ++ ++ return 0; ++} ++ ++static void omap_hsmmc_complete(struct device *dev) ++{ ++ struct omap_hsmmc_host *host = dev_get_drvdata(dev); ++ ++ if (host->pdata->resume) ++ host->pdata->resume(dev, host->slot_id); ++ ++} ++ + static int omap_hsmmc_suspend(struct device *dev) + { +- int ret = 0; +- struct platform_device *pdev = to_platform_device(dev); +- struct omap_hsmmc_host *host = platform_get_drvdata(pdev); ++ struct omap_hsmmc_host *host = dev_get_drvdata(dev); + +- if (host && host->suspended) ++ if (!host) + return 0; + +- if (host) { +- pm_runtime_get_sync(host->dev); +- host->suspended = 1; +- if (host->pdata->suspend) { +- ret = host->pdata->suspend(&pdev->dev, +- host->slot_id); +- if (ret) { +- dev_dbg(mmc_dev(host->mmc), +- "Unable to handle MMC board" +- " level suspend\n"); +- host->suspended = 0; +- return ret; +- } +- } +- cancel_work_sync(&host->mmc_carddetect_work); +- ret = mmc_suspend_host(host->mmc); ++ pm_runtime_get_sync(host->dev); + +- if (ret == 0) { +- omap_hsmmc_disable_irq(host); +- OMAP_HSMMC_WRITE(host->base, HCTL, ++ if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) { ++ omap_hsmmc_disable_irq(host); ++ OMAP_HSMMC_WRITE(host->base, HCTL, + OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); +- if (host->got_dbclk) +- clk_disable(host->dbclk); +- } else { +- host->suspended = 0; +- if (host->pdata->resume) { +- if (host->pdata->resume(&pdev->dev, host->slot_id)) +- dev_dbg(mmc_dev(host->mmc), +- "Unmask interrupt failed\n"); +- } +- } +- pm_runtime_put_sync(host->dev); + } +- return ret; ++ ++ if (host->dbclk) ++ clk_disable_unprepare(host->dbclk); ++ ++ pm_runtime_put_sync(host->dev); ++ return 0; + } + + /* Routine to resume the MMC device */ + static int omap_hsmmc_resume(struct device *dev) + { +- int ret = 0; +- struct platform_device *pdev = to_platform_device(dev); +- struct omap_hsmmc_host *host = platform_get_drvdata(pdev); ++ struct omap_hsmmc_host *host = dev_get_drvdata(dev); + +- if (host && !host->suspended) ++ if (!host) + return 0; + +- if (host) { +- pm_runtime_get_sync(host->dev); ++ pm_runtime_get_sync(host->dev); + +- if (host->got_dbclk) +- clk_enable(host->dbclk); ++ if (host->dbclk) ++ clk_prepare_enable(host->dbclk); + ++ if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) + omap_hsmmc_conf_bus_power(host); + +- if (host->pdata->resume) { +- ret = host->pdata->resume(&pdev->dev, host->slot_id); +- if (ret) +- dev_dbg(mmc_dev(host->mmc), +- "Unmask interrupt failed\n"); +- } +- +- omap_hsmmc_protect_card(host); +- +- /* Notify the core to resume the host */ +- ret = mmc_resume_host(host->mmc); +- if (ret == 0) +- host->suspended = 0; +- +- pm_runtime_mark_last_busy(host->dev); +- pm_runtime_put_autosuspend(host->dev); +- } +- +- return ret; ++ omap_hsmmc_protect_card(host); + ++ pm_runtime_mark_last_busy(host->dev); ++ pm_runtime_put_autosuspend(host->dev); ++ return 0; + } + + #else ++#define omap_hsmmc_prepare NULL ++#define omap_hsmmc_complete NULL + #define omap_hsmmc_suspend NULL +-#define omap_hsmmc_resume NULL ++#define omap_hsmmc_resume NULL + #endif + + static int omap_hsmmc_runtime_suspend(struct device *dev) +@@ -2249,7 +2218,7 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) + + host = platform_get_drvdata(to_platform_device(dev)); + omap_hsmmc_context_save(host); +- dev_dbg(mmc_dev(host->mmc), "disabled\n"); ++ dev_dbg(dev, "disabled\n"); + + return 0; + } +@@ -2260,7 +2229,7 @@ static int omap_hsmmc_runtime_resume(struct device *dev) + + host = platform_get_drvdata(to_platform_device(dev)); + omap_hsmmc_context_restore(host); +- dev_dbg(mmc_dev(host->mmc), "enabled\n"); ++ dev_dbg(dev, "enabled\n"); + + return 0; + } +@@ -2268,34 +2237,24 @@ static int omap_hsmmc_runtime_resume(struct device *dev) + static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { + .suspend = omap_hsmmc_suspend, + .resume = omap_hsmmc_resume, ++ .prepare = omap_hsmmc_prepare, ++ .complete = omap_hsmmc_complete, + .runtime_suspend = omap_hsmmc_runtime_suspend, + .runtime_resume = omap_hsmmc_runtime_resume, + }; + + static struct platform_driver omap_hsmmc_driver = { ++ .probe = omap_hsmmc_probe, + .remove = omap_hsmmc_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .pm = &omap_hsmmc_dev_pm_ops, ++ .of_match_table = of_match_ptr(omap_mmc_of_match), + }, + }; + +-static int __init omap_hsmmc_init(void) +-{ +- /* Register the MMC driver */ +- return platform_driver_probe(&omap_hsmmc_driver, omap_hsmmc_probe); +-} +- +-static void __exit omap_hsmmc_cleanup(void) +-{ +- /* Unregister MMC driver */ +- platform_driver_unregister(&omap_hsmmc_driver); +-} +- +-module_init(omap_hsmmc_init); +-module_exit(omap_hsmmc_cleanup); +- ++module_platform_driver(omap_hsmmc_driver); + MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver"); + MODULE_LICENSE("GPL"); + MODULE_ALIAS("platform:" DRIVER_NAME); +diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c +index fc4356e..32fe113 100644 +--- a/drivers/mmc/host/pxamci.c ++++ b/drivers/mmc/host/pxamci.c +@@ -30,12 +30,15 @@ + #include + #include + #include ++#include ++#include ++#include + + #include + + #include + #include +-#include ++#include + + #include "pxamci.h" + +@@ -80,7 +83,7 @@ struct pxamci_host { + static inline void pxamci_init_ocr(struct pxamci_host *host) + { + #ifdef CONFIG_REGULATOR +- host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc"); ++ host->vcc = regulator_get_optional(mmc_dev(host->mmc), "vmmc"); + + if (IS_ERR(host->vcc)) + host->vcc = NULL; +@@ -125,7 +128,7 @@ static inline int pxamci_set_power(struct pxamci_host *host, + !!on ^ host->pdata->gpio_power_invert); + } + if (!host->vcc && host->pdata && host->pdata->setpower) +- host->pdata->setpower(mmc_dev(host->mmc), vdd); ++ return host->pdata->setpower(mmc_dev(host->mmc), vdd); + + return 0; + } +@@ -573,6 +576,50 @@ static irqreturn_t pxamci_detect_irq(int irq, void *devid) + return IRQ_HANDLED; + } + ++#ifdef CONFIG_OF ++static const struct of_device_id pxa_mmc_dt_ids[] = { ++ { .compatible = "marvell,pxa-mmc" }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(of, pxa_mmc_dt_ids); ++ ++static int pxamci_of_init(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct pxamci_platform_data *pdata; ++ u32 tmp; ++ ++ if (!np) ++ return 0; ++ ++ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return -ENOMEM; ++ ++ pdata->gpio_card_detect = ++ of_get_named_gpio(np, "cd-gpios", 0); ++ pdata->gpio_card_ro = ++ of_get_named_gpio(np, "wp-gpios", 0); ++ ++ /* pxa-mmc specific */ ++ pdata->gpio_power = ++ of_get_named_gpio(np, "pxa-mmc,gpio-power", 0); ++ ++ if (of_property_read_u32(np, "pxa-mmc,detect-delay-ms", &tmp) == 0) ++ pdata->detect_delay_ms = tmp; ++ ++ pdev->dev.platform_data = pdata; ++ ++ return 0; ++} ++#else ++static int pxamci_of_init(struct platform_device *pdev) ++{ ++ return 0; ++} ++#endif ++ + static int pxamci_probe(struct platform_device *pdev) + { + struct mmc_host *mmc; +@@ -580,6 +627,10 @@ static int pxamci_probe(struct platform_device *pdev) + struct resource *r, *dmarx, *dmatx; + int ret, irq, gpio_cd = -1, gpio_ro = -1, gpio_power = -1; + ++ ret = pxamci_of_init(pdev); ++ if (ret) ++ return ret; ++ + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!r || irq < 0) +@@ -783,8 +834,6 @@ static int pxamci_remove(struct platform_device *pdev) + struct mmc_host *mmc = platform_get_drvdata(pdev); + int gpio_cd = -1, gpio_ro = -1, gpio_power = -1; + +- platform_set_drvdata(pdev, NULL); +- + if (mmc) { + struct pxamci_host *host = mmc_priv(mmc); + +@@ -831,59 +880,17 @@ static int pxamci_remove(struct platform_device *pdev) + return 0; + } + +-#ifdef CONFIG_PM +-static int pxamci_suspend(struct device *dev) +-{ +- struct mmc_host *mmc = dev_get_drvdata(dev); +- int ret = 0; +- +- if (mmc) +- ret = mmc_suspend_host(mmc); +- +- return ret; +-} +- +-static int pxamci_resume(struct device *dev) +-{ +- struct mmc_host *mmc = dev_get_drvdata(dev); +- int ret = 0; +- +- if (mmc) +- ret = mmc_resume_host(mmc); +- +- return ret; +-} +- +-static const struct dev_pm_ops pxamci_pm_ops = { +- .suspend = pxamci_suspend, +- .resume = pxamci_resume, +-}; +-#endif +- + static struct platform_driver pxamci_driver = { + .probe = pxamci_probe, + .remove = pxamci_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, +-#ifdef CONFIG_PM +- .pm = &pxamci_pm_ops, +-#endif ++ .of_match_table = of_match_ptr(pxa_mmc_dt_ids), + }, + }; + +-static int __init pxamci_init(void) +-{ +- return platform_driver_register(&pxamci_driver); +-} +- +-static void __exit pxamci_exit(void) +-{ +- platform_driver_unregister(&pxamci_driver); +-} +- +-module_init(pxamci_init); +-module_exit(pxamci_exit); ++module_platform_driver(pxamci_driver); + + MODULE_DESCRIPTION("PXA Multimedia Card Interface Driver"); + MODULE_LICENSE("GPL"); +diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c +new file mode 100644 +index 0000000..0d51964 +--- /dev/null ++++ b/drivers/mmc/host/rtsx_pci_sdmmc.c +@@ -0,0 +1,1306 @@ ++/* Realtek PCI-Express SD/MMC Card Interface driver ++ * ++ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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 as published by the ++ * Free Software Foundation; either version 2, 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 . ++ * ++ * Author: ++ * Wei WANG ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct realtek_pci_sdmmc { ++ struct platform_device *pdev; ++ struct rtsx_pcr *pcr; ++ struct mmc_host *mmc; ++ struct mmc_request *mrq; ++ ++ struct mutex host_mutex; ++ ++ u8 ssc_depth; ++ unsigned int clock; ++ bool vpclk; ++ bool double_clk; ++ bool eject; ++ bool initial_mode; ++ int power_state; ++#define SDMMC_POWER_ON 1 ++#define SDMMC_POWER_OFF 0 ++}; ++ ++static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) ++{ ++ return &(host->pdev->dev); ++} ++ ++static inline void sd_clear_error(struct realtek_pci_sdmmc *host) ++{ ++ rtsx_pci_write_register(host->pcr, CARD_STOP, ++ SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR); ++} ++ ++#ifdef DEBUG ++static void sd_print_debug_regs(struct realtek_pci_sdmmc *host) ++{ ++ struct rtsx_pcr *pcr = host->pcr; ++ u16 i; ++ u8 *ptr; ++ ++ /* Print SD host internal registers */ ++ rtsx_pci_init_cmd(pcr); ++ for (i = 0xFDA0; i <= 0xFDAE; i++) ++ rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0); ++ for (i = 0xFD52; i <= 0xFD69; i++) ++ rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0); ++ rtsx_pci_send_cmd(pcr, 100); ++ ++ ptr = rtsx_pci_get_cmd_data(pcr); ++ for (i = 0xFDA0; i <= 0xFDAE; i++) ++ dev_dbg(sdmmc_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++)); ++ for (i = 0xFD52; i <= 0xFD69; i++) ++ dev_dbg(sdmmc_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++)); ++} ++#else ++#define sd_print_debug_regs(host) ++#endif /* DEBUG */ ++ ++static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, ++ u8 *buf, int buf_len, int timeout) ++{ ++ struct rtsx_pcr *pcr = host->pcr; ++ int err, i; ++ u8 trans_mode; ++ ++ dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__, cmd[0] - 0x40); ++ ++ if (!buf) ++ buf_len = 0; ++ ++ if ((cmd[0] & 0x3F) == MMC_SEND_TUNING_BLOCK) ++ trans_mode = SD_TM_AUTO_TUNING; ++ else ++ trans_mode = SD_TM_NORMAL_READ; ++ ++ rtsx_pci_init_cmd(pcr); ++ ++ for (i = 0; i < 5; i++) ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0 + i, 0xFF, cmd[i]); ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, ++ 0xFF, (u8)(byte_cnt >> 8)); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, ++ SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | ++ SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); ++ if (trans_mode != SD_TM_AUTO_TUNING) ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ++ CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, ++ 0xFF, trans_mode | SD_TRANSFER_START); ++ rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, ++ SD_TRANSFER_END, SD_TRANSFER_END); ++ ++ err = rtsx_pci_send_cmd(pcr, timeout); ++ if (err < 0) { ++ sd_print_debug_regs(host); ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_pci_send_cmd fail (err = %d)\n", err); ++ return err; ++ } ++ ++ if (buf && buf_len) { ++ err = rtsx_pci_read_ppbuf(pcr, buf, buf_len); ++ if (err < 0) { ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_pci_read_ppbuf fail (err = %d)\n", err); ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, ++ u8 *buf, int buf_len, int timeout) ++{ ++ struct rtsx_pcr *pcr = host->pcr; ++ int err, i; ++ u8 trans_mode; ++ ++ if (!buf) ++ buf_len = 0; ++ ++ if (buf && buf_len) { ++ err = rtsx_pci_write_ppbuf(pcr, buf, buf_len); ++ if (err < 0) { ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_pci_write_ppbuf fail (err = %d)\n", err); ++ return err; ++ } ++ } ++ ++ trans_mode = cmd ? SD_TM_AUTO_WRITE_2 : SD_TM_AUTO_WRITE_3; ++ rtsx_pci_init_cmd(pcr); ++ ++ if (cmd) { ++ dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d\n", __func__, ++ cmd[0] - 0x40); ++ ++ for (i = 0; i < 5; i++) ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ++ SD_CMD0 + i, 0xFF, cmd[i]); ++ } ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, ++ 0xFF, (u8)(byte_cnt >> 8)); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, ++ SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | ++ SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, ++ trans_mode | SD_TRANSFER_START); ++ rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, ++ SD_TRANSFER_END, SD_TRANSFER_END); ++ ++ err = rtsx_pci_send_cmd(pcr, timeout); ++ if (err < 0) { ++ sd_print_debug_regs(host); ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_pci_send_cmd fail (err = %d)\n", err); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, ++ struct mmc_command *cmd) ++{ ++ struct rtsx_pcr *pcr = host->pcr; ++ u8 cmd_idx = (u8)cmd->opcode; ++ u32 arg = cmd->arg; ++ int err = 0; ++ int timeout = 100; ++ int i; ++ u8 *ptr; ++ int stat_idx = 0; ++ u8 rsp_type; ++ int rsp_len = 5; ++ bool clock_toggled = false; ++ ++ dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", ++ __func__, cmd_idx, arg); ++ ++ /* Response type: ++ * R0 ++ * R1, R5, R6, R7 ++ * R1b ++ * R2 ++ * R3, R4 ++ */ ++ switch (mmc_resp_type(cmd)) { ++ case MMC_RSP_NONE: ++ rsp_type = SD_RSP_TYPE_R0; ++ rsp_len = 0; ++ break; ++ case MMC_RSP_R1: ++ rsp_type = SD_RSP_TYPE_R1; ++ break; ++ case MMC_RSP_R1 & ~MMC_RSP_CRC: ++ rsp_type = SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7; ++ break; ++ case MMC_RSP_R1B: ++ rsp_type = SD_RSP_TYPE_R1b; ++ break; ++ case MMC_RSP_R2: ++ rsp_type = SD_RSP_TYPE_R2; ++ rsp_len = 16; ++ break; ++ case MMC_RSP_R3: ++ rsp_type = SD_RSP_TYPE_R3; ++ break; ++ default: ++ dev_dbg(sdmmc_dev(host), "cmd->flag is not valid\n"); ++ err = -EINVAL; ++ goto out; ++ } ++ ++ if (rsp_type == SD_RSP_TYPE_R1b) ++ timeout = 3000; ++ ++ if (cmd->opcode == SD_SWITCH_VOLTAGE) { ++ err = rtsx_pci_write_register(pcr, SD_BUS_STAT, ++ 0xFF, SD_CLK_TOGGLE_EN); ++ if (err < 0) ++ goto out; ++ ++ clock_toggled = true; ++ } ++ ++ rtsx_pci_init_cmd(pcr); ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8)(arg >> 24)); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8)(arg >> 16)); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8)(arg >> 8)); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8)arg); ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, ++ 0x01, PINGPONG_BUFFER); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, ++ 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); ++ rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, ++ SD_TRANSFER_END | SD_STAT_IDLE, ++ SD_TRANSFER_END | SD_STAT_IDLE); ++ ++ if (rsp_type == SD_RSP_TYPE_R2) { ++ /* Read data from ping-pong buffer */ ++ for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) ++ rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); ++ stat_idx = 16; ++ } else if (rsp_type != SD_RSP_TYPE_R0) { ++ /* Read data from SD_CMDx registers */ ++ for (i = SD_CMD0; i <= SD_CMD4; i++) ++ rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); ++ stat_idx = 5; ++ } ++ ++ rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0); ++ ++ err = rtsx_pci_send_cmd(pcr, timeout); ++ if (err < 0) { ++ sd_print_debug_regs(host); ++ sd_clear_error(host); ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_pci_send_cmd error (err = %d)\n", err); ++ goto out; ++ } ++ ++ if (rsp_type == SD_RSP_TYPE_R0) { ++ err = 0; ++ goto out; ++ } ++ ++ /* Eliminate returned value of CHECK_REG_CMD */ ++ ptr = rtsx_pci_get_cmd_data(pcr) + 1; ++ ++ /* Check (Start,Transmission) bit of Response */ ++ if ((ptr[0] & 0xC0) != 0) { ++ err = -EILSEQ; ++ dev_dbg(sdmmc_dev(host), "Invalid response bit\n"); ++ goto out; ++ } ++ ++ /* Check CRC7 */ ++ if (!(rsp_type & SD_NO_CHECK_CRC7)) { ++ if (ptr[stat_idx] & SD_CRC7_ERR) { ++ err = -EILSEQ; ++ dev_dbg(sdmmc_dev(host), "CRC7 error\n"); ++ goto out; ++ } ++ } ++ ++ if (rsp_type == SD_RSP_TYPE_R2) { ++ for (i = 0; i < 4; i++) { ++ cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4); ++ dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n", ++ i, cmd->resp[i]); ++ } ++ } else { ++ cmd->resp[0] = get_unaligned_be32(ptr + 1); ++ dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", ++ cmd->resp[0]); ++ } ++ ++out: ++ cmd->error = err; ++ ++ if (err && clock_toggled) ++ rtsx_pci_write_register(pcr, SD_BUS_STAT, ++ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); ++} ++ ++static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) ++{ ++ struct rtsx_pcr *pcr = host->pcr; ++ struct mmc_host *mmc = host->mmc; ++ struct mmc_card *card = mmc->card; ++ struct mmc_data *data = mrq->data; ++ int uhs = mmc_card_uhs(card); ++ int read = (data->flags & MMC_DATA_READ) ? 1 : 0; ++ u8 cfg2, trans_mode; ++ int err; ++ size_t data_len = data->blksz * data->blocks; ++ ++ if (read) { ++ cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | ++ SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; ++ trans_mode = SD_TM_AUTO_READ_3; ++ } else { ++ cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | ++ SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; ++ trans_mode = SD_TM_AUTO_WRITE_3; ++ } ++ ++ if (!uhs) ++ cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; ++ ++ rtsx_pci_init_cmd(pcr); ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, ++ 0xFF, (u8)data->blocks); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, ++ 0xFF, (u8)(data->blocks >> 8)); ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0, ++ DMA_DONE_INT, DMA_DONE_INT); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, ++ 0xFF, (u8)(data_len >> 24)); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, ++ 0xFF, (u8)(data_len >> 16)); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, ++ 0xFF, (u8)(data_len >> 8)); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)data_len); ++ if (read) { ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, ++ 0x03 | DMA_PACK_SIZE_MASK, ++ DMA_DIR_FROM_CARD | DMA_EN | DMA_512); ++ } else { ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, ++ 0x03 | DMA_PACK_SIZE_MASK, ++ DMA_DIR_TO_CARD | DMA_EN | DMA_512); ++ } ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, ++ 0x01, RING_BUFFER); ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, ++ trans_mode | SD_TRANSFER_START); ++ rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, ++ SD_TRANSFER_END, SD_TRANSFER_END); ++ ++ rtsx_pci_send_cmd_no_wait(pcr); ++ ++ err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000); ++ if (err < 0) { ++ sd_clear_error(host); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host) ++{ ++ rtsx_pci_write_register(host->pcr, SD_CFG1, ++ SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128); ++} ++ ++static inline void sd_disable_initial_mode(struct realtek_pci_sdmmc *host) ++{ ++ rtsx_pci_write_register(host->pcr, SD_CFG1, ++ SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0); ++} ++ ++static void sd_normal_rw(struct realtek_pci_sdmmc *host, ++ struct mmc_request *mrq) ++{ ++ struct mmc_command *cmd = mrq->cmd; ++ struct mmc_data *data = mrq->data; ++ u8 _cmd[5], *buf; ++ ++ _cmd[0] = 0x40 | (u8)cmd->opcode; ++ put_unaligned_be32(cmd->arg, (u32 *)(&_cmd[1])); ++ ++ buf = kzalloc(data->blksz, GFP_NOIO); ++ if (!buf) { ++ cmd->error = -ENOMEM; ++ return; ++ } ++ ++ if (data->flags & MMC_DATA_READ) { ++ if (host->initial_mode) ++ sd_disable_initial_mode(host); ++ ++ cmd->error = sd_read_data(host, _cmd, (u16)data->blksz, buf, ++ data->blksz, 200); ++ ++ if (host->initial_mode) ++ sd_enable_initial_mode(host); ++ ++ sg_copy_from_buffer(data->sg, data->sg_len, buf, data->blksz); ++ } else { ++ sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz); ++ ++ cmd->error = sd_write_data(host, _cmd, (u16)data->blksz, buf, ++ data->blksz, 200); ++ } ++ ++ kfree(buf); ++} ++ ++static int sd_change_phase(struct realtek_pci_sdmmc *host, ++ u8 sample_point, bool rx) ++{ ++ struct rtsx_pcr *pcr = host->pcr; ++ int err; ++ ++ dev_dbg(sdmmc_dev(host), "%s(%s): sample_point = %d\n", ++ __func__, rx ? "RX" : "TX", sample_point); ++ ++ rtsx_pci_init_cmd(pcr); ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, CHANGE_CLK); ++ if (rx) ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ++ SD_VPRX_CTL, 0x1F, sample_point); ++ else ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ++ SD_VPTX_CTL, 0x1F, sample_point); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, ++ PHASE_NOT_RESET, PHASE_NOT_RESET); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, 0); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0); ++ ++ err = rtsx_pci_send_cmd(pcr, 100); ++ if (err < 0) ++ return err; ++ ++ return 0; ++} ++ ++static inline u32 test_phase_bit(u32 phase_map, unsigned int bit) ++{ ++ bit %= RTSX_PHASE_MAX; ++ return phase_map & (1 << bit); ++} ++ ++static int sd_get_phase_len(u32 phase_map, unsigned int start_bit) ++{ ++ int i; ++ ++ for (i = 0; i < RTSX_PHASE_MAX; i++) { ++ if (test_phase_bit(phase_map, start_bit + i) == 0) ++ return i; ++ } ++ return RTSX_PHASE_MAX; ++} ++ ++static u8 sd_search_final_phase(struct realtek_pci_sdmmc *host, u32 phase_map) ++{ ++ int start = 0, len = 0; ++ int start_final = 0, len_final = 0; ++ u8 final_phase = 0xFF; ++ ++ if (phase_map == 0) { ++ dev_err(sdmmc_dev(host), "phase error: [map:%x]\n", phase_map); ++ return final_phase; ++ } ++ ++ while (start < RTSX_PHASE_MAX) { ++ len = sd_get_phase_len(phase_map, start); ++ if (len_final < len) { ++ start_final = start; ++ len_final = len; ++ } ++ start += len ? len : 1; ++ } ++ ++ final_phase = (start_final + len_final / 2) % RTSX_PHASE_MAX; ++ dev_dbg(sdmmc_dev(host), "phase: [map:%x] [maxlen:%d] [final:%d]\n", ++ phase_map, len_final, final_phase); ++ ++ return final_phase; ++} ++ ++static void sd_wait_data_idle(struct realtek_pci_sdmmc *host) ++{ ++ int err, i; ++ u8 val = 0; ++ ++ for (i = 0; i < 100; i++) { ++ err = rtsx_pci_read_register(host->pcr, SD_DATA_STATE, &val); ++ if (val & SD_DATA_IDLE) ++ return; ++ ++ udelay(100); ++ } ++} ++ ++static int sd_tuning_rx_cmd(struct realtek_pci_sdmmc *host, ++ u8 opcode, u8 sample_point) ++{ ++ int err; ++ u8 cmd[5] = {0}; ++ ++ err = sd_change_phase(host, sample_point, true); ++ if (err < 0) ++ return err; ++ ++ cmd[0] = 0x40 | opcode; ++ err = sd_read_data(host, cmd, 0x40, NULL, 0, 100); ++ if (err < 0) { ++ /* Wait till SD DATA IDLE */ ++ sd_wait_data_idle(host); ++ sd_clear_error(host); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int sd_tuning_phase(struct realtek_pci_sdmmc *host, ++ u8 opcode, u32 *phase_map) ++{ ++ int err, i; ++ u32 raw_phase_map = 0; ++ ++ for (i = 0; i < RTSX_PHASE_MAX; i++) { ++ err = sd_tuning_rx_cmd(host, opcode, (u8)i); ++ if (err == 0) ++ raw_phase_map |= 1 << i; ++ } ++ ++ if (phase_map) ++ *phase_map = raw_phase_map; ++ ++ return 0; ++} ++ ++static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode) ++{ ++ int err, i; ++ u32 raw_phase_map[RX_TUNING_CNT] = {0}, phase_map; ++ u8 final_phase; ++ ++ for (i = 0; i < RX_TUNING_CNT; i++) { ++ err = sd_tuning_phase(host, opcode, &(raw_phase_map[i])); ++ if (err < 0) ++ return err; ++ ++ if (raw_phase_map[i] == 0) ++ break; ++ } ++ ++ phase_map = 0xFFFFFFFF; ++ for (i = 0; i < RX_TUNING_CNT; i++) { ++ dev_dbg(sdmmc_dev(host), "RX raw_phase_map[%d] = 0x%08x\n", ++ i, raw_phase_map[i]); ++ phase_map &= raw_phase_map[i]; ++ } ++ dev_dbg(sdmmc_dev(host), "RX phase_map = 0x%08x\n", phase_map); ++ ++ if (phase_map) { ++ final_phase = sd_search_final_phase(host, phase_map); ++ if (final_phase == 0xFF) ++ return -EINVAL; ++ ++ err = sd_change_phase(host, final_phase, true); ++ if (err < 0) ++ return err; ++ } else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct realtek_pci_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_pcr *pcr = host->pcr; ++ struct mmc_command *cmd = mrq->cmd; ++ struct mmc_data *data = mrq->data; ++ unsigned int data_size = 0; ++ int err; ++ ++ if (host->eject) { ++ cmd->error = -ENOMEDIUM; ++ goto finish; ++ } ++ ++ err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); ++ if (err) { ++ cmd->error = err; ++ goto finish; ++ } ++ ++ mutex_lock(&pcr->pcr_mutex); ++ ++ rtsx_pci_start_run(pcr); ++ ++ rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth, ++ host->initial_mode, host->double_clk, host->vpclk); ++ rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, SD_MOD_SEL); ++ rtsx_pci_write_register(pcr, CARD_SHARE_MODE, ++ CARD_SHARE_MASK, CARD_SHARE_48_SD); ++ ++ mutex_lock(&host->host_mutex); ++ host->mrq = mrq; ++ mutex_unlock(&host->host_mutex); ++ ++ if (mrq->data) ++ data_size = data->blocks * data->blksz; ++ ++ if (!data_size || mmc_op_multi(cmd->opcode) || ++ (cmd->opcode == MMC_READ_SINGLE_BLOCK) || ++ (cmd->opcode == MMC_WRITE_BLOCK)) { ++ sd_send_cmd_get_rsp(host, cmd); ++ ++ if (!cmd->error && data_size) { ++ sd_rw_multi(host, mrq); ++ ++ if (mmc_op_multi(cmd->opcode) && mrq->stop) ++ sd_send_cmd_get_rsp(host, mrq->stop); ++ } ++ } else { ++ sd_normal_rw(host, mrq); ++ } ++ ++ if (mrq->data) { ++ if (cmd->error || data->error) ++ data->bytes_xfered = 0; ++ else ++ data->bytes_xfered = data->blocks * data->blksz; ++ } ++ ++ mutex_unlock(&pcr->pcr_mutex); ++ ++finish: ++ if (cmd->error) ++ dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); ++ ++ mutex_lock(&host->host_mutex); ++ host->mrq = NULL; ++ mutex_unlock(&host->host_mutex); ++ ++ mmc_request_done(mmc, mrq); ++} ++ ++static int sd_set_bus_width(struct realtek_pci_sdmmc *host, ++ unsigned char bus_width) ++{ ++ int err = 0; ++ u8 width[] = { ++ [MMC_BUS_WIDTH_1] = SD_BUS_WIDTH_1BIT, ++ [MMC_BUS_WIDTH_4] = SD_BUS_WIDTH_4BIT, ++ [MMC_BUS_WIDTH_8] = SD_BUS_WIDTH_8BIT, ++ }; ++ ++ if (bus_width <= MMC_BUS_WIDTH_8) ++ err = rtsx_pci_write_register(host->pcr, SD_CFG1, ++ 0x03, width[bus_width]); ++ ++ return err; ++} ++ ++static int sd_power_on(struct realtek_pci_sdmmc *host) ++{ ++ struct rtsx_pcr *pcr = host->pcr; ++ int err; ++ ++ if (host->power_state == SDMMC_POWER_ON) ++ return 0; ++ ++ rtsx_pci_init_cmd(pcr); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE, ++ CARD_SHARE_MASK, CARD_SHARE_48_SD); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, ++ SD_CLK_EN, SD_CLK_EN); ++ err = rtsx_pci_send_cmd(pcr, 100); ++ if (err < 0) ++ return err; ++ ++ err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_SD_CARD); ++ if (err < 0) ++ return err; ++ ++ err = rtsx_pci_card_power_on(pcr, RTSX_SD_CARD); ++ if (err < 0) ++ return err; ++ ++ err = rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN); ++ if (err < 0) ++ return err; ++ ++ host->power_state = SDMMC_POWER_ON; ++ return 0; ++} ++ ++static int sd_power_off(struct realtek_pci_sdmmc *host) ++{ ++ struct rtsx_pcr *pcr = host->pcr; ++ int err; ++ ++ host->power_state = SDMMC_POWER_OFF; ++ ++ rtsx_pci_init_cmd(pcr); ++ ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0); ++ ++ err = rtsx_pci_send_cmd(pcr, 100); ++ if (err < 0) ++ return err; ++ ++ err = rtsx_pci_card_power_off(pcr, RTSX_SD_CARD); ++ if (err < 0) ++ return err; ++ ++ return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_SD_CARD); ++} ++ ++static int sd_set_power_mode(struct realtek_pci_sdmmc *host, ++ unsigned char power_mode) ++{ ++ int err; ++ ++ if (power_mode == MMC_POWER_OFF) ++ err = sd_power_off(host); ++ else ++ err = sd_power_on(host); ++ ++ return err; ++} ++ ++static int sd_set_timing(struct realtek_pci_sdmmc *host, unsigned char timing) ++{ ++ struct rtsx_pcr *pcr = host->pcr; ++ int err = 0; ++ ++ rtsx_pci_init_cmd(pcr); ++ ++ switch (timing) { ++ case MMC_TIMING_UHS_SDR104: ++ case MMC_TIMING_UHS_SDR50: ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, ++ 0x0C | SD_ASYNC_FIFO_NOT_RST, ++ SD_30_MODE | SD_ASYNC_FIFO_NOT_RST); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, ++ CLK_LOW_FREQ, CLK_LOW_FREQ); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, ++ CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0); ++ break; ++ ++ case MMC_TIMING_MMC_DDR52: ++ case MMC_TIMING_UHS_DDR50: ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, ++ 0x0C | SD_ASYNC_FIFO_NOT_RST, ++ SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, ++ CLK_LOW_FREQ, CLK_LOW_FREQ); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, ++ CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_PUSH_POINT_CTL, ++ DDR_VAR_TX_CMD_DAT, DDR_VAR_TX_CMD_DAT); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, ++ DDR_VAR_RX_DAT | DDR_VAR_RX_CMD, ++ DDR_VAR_RX_DAT | DDR_VAR_RX_CMD); ++ break; ++ ++ case MMC_TIMING_MMC_HS: ++ case MMC_TIMING_SD_HS: ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, ++ 0x0C, SD_20_MODE); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, ++ CLK_LOW_FREQ, CLK_LOW_FREQ); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, ++ CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_PUSH_POINT_CTL, ++ SD20_TX_SEL_MASK, SD20_TX_14_AHEAD); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, ++ SD20_RX_SEL_MASK, SD20_RX_14_DELAY); ++ break; ++ ++ default: ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ++ SD_CFG1, 0x0C, SD_20_MODE); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, ++ CLK_LOW_FREQ, CLK_LOW_FREQ); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, ++ CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ++ SD_PUSH_POINT_CTL, 0xFF, 0); ++ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, ++ SD20_RX_SEL_MASK, SD20_RX_POS_EDGE); ++ break; ++ } ++ ++ err = rtsx_pci_send_cmd(pcr, 100); ++ ++ return err; ++} ++ ++static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct realtek_pci_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_pcr *pcr = host->pcr; ++ ++ if (host->eject) ++ return; ++ ++ if (rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD)) ++ return; ++ ++ mutex_lock(&pcr->pcr_mutex); ++ ++ rtsx_pci_start_run(pcr); ++ ++ sd_set_bus_width(host, ios->bus_width); ++ sd_set_power_mode(host, ios->power_mode); ++ sd_set_timing(host, ios->timing); ++ ++ host->vpclk = false; ++ host->double_clk = true; ++ ++ switch (ios->timing) { ++ case MMC_TIMING_UHS_SDR104: ++ case MMC_TIMING_UHS_SDR50: ++ host->ssc_depth = RTSX_SSC_DEPTH_2M; ++ host->vpclk = true; ++ host->double_clk = false; ++ break; ++ case MMC_TIMING_MMC_DDR52: ++ case MMC_TIMING_UHS_DDR50: ++ case MMC_TIMING_UHS_SDR25: ++ host->ssc_depth = RTSX_SSC_DEPTH_1M; ++ break; ++ default: ++ host->ssc_depth = RTSX_SSC_DEPTH_500K; ++ break; ++ } ++ ++ host->initial_mode = (ios->clock <= 1000000) ? true : false; ++ ++ host->clock = ios->clock; ++ rtsx_pci_switch_clock(pcr, ios->clock, host->ssc_depth, ++ host->initial_mode, host->double_clk, host->vpclk); ++ ++ mutex_unlock(&pcr->pcr_mutex); ++} ++ ++static int sdmmc_get_ro(struct mmc_host *mmc) ++{ ++ struct realtek_pci_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_pcr *pcr = host->pcr; ++ int ro = 0; ++ u32 val; ++ ++ if (host->eject) ++ return -ENOMEDIUM; ++ ++ mutex_lock(&pcr->pcr_mutex); ++ ++ rtsx_pci_start_run(pcr); ++ ++ /* Check SD mechanical write-protect switch */ ++ val = rtsx_pci_readl(pcr, RTSX_BIPR); ++ dev_dbg(sdmmc_dev(host), "%s: RTSX_BIPR = 0x%08x\n", __func__, val); ++ if (val & SD_WRITE_PROTECT) ++ ro = 1; ++ ++ mutex_unlock(&pcr->pcr_mutex); ++ ++ return ro; ++} ++ ++static int sdmmc_get_cd(struct mmc_host *mmc) ++{ ++ struct realtek_pci_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_pcr *pcr = host->pcr; ++ int cd = 0; ++ u32 val; ++ ++ if (host->eject) ++ return -ENOMEDIUM; ++ ++ mutex_lock(&pcr->pcr_mutex); ++ ++ rtsx_pci_start_run(pcr); ++ ++ /* Check SD card detect */ ++ val = rtsx_pci_card_exist(pcr); ++ dev_dbg(sdmmc_dev(host), "%s: RTSX_BIPR = 0x%08x\n", __func__, val); ++ if (val & SD_EXIST) ++ cd = 1; ++ ++ mutex_unlock(&pcr->pcr_mutex); ++ ++ return cd; ++} ++ ++static int sd_wait_voltage_stable_1(struct realtek_pci_sdmmc *host) ++{ ++ struct rtsx_pcr *pcr = host->pcr; ++ int err; ++ u8 stat; ++ ++ /* Reference to Signal Voltage Switch Sequence in SD spec. ++ * Wait for a period of time so that the card can drive SD_CMD and ++ * SD_DAT[3:0] to low after sending back CMD11 response. ++ */ ++ mdelay(1); ++ ++ /* SD_CMD, SD_DAT[3:0] should be driven to low by card; ++ * If either one of SD_CMD,SD_DAT[3:0] is not low, ++ * abort the voltage switch sequence; ++ */ ++ err = rtsx_pci_read_register(pcr, SD_BUS_STAT, &stat); ++ if (err < 0) ++ return err; ++ ++ if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | ++ SD_DAT1_STATUS | SD_DAT0_STATUS)) ++ return -EINVAL; ++ ++ /* Stop toggle SD clock */ ++ err = rtsx_pci_write_register(pcr, SD_BUS_STAT, ++ 0xFF, SD_CLK_FORCE_STOP); ++ if (err < 0) ++ return err; ++ ++ return 0; ++} ++ ++static int sd_wait_voltage_stable_2(struct realtek_pci_sdmmc *host) ++{ ++ struct rtsx_pcr *pcr = host->pcr; ++ int err; ++ u8 stat, mask, val; ++ ++ /* Wait 1.8V output of voltage regulator in card stable */ ++ msleep(50); ++ ++ /* Toggle SD clock again */ ++ err = rtsx_pci_write_register(pcr, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN); ++ if (err < 0) ++ return err; ++ ++ /* Wait for a period of time so that the card can drive ++ * SD_DAT[3:0] to high at 1.8V ++ */ ++ msleep(20); ++ ++ /* SD_CMD, SD_DAT[3:0] should be pulled high by host */ ++ err = rtsx_pci_read_register(pcr, SD_BUS_STAT, &stat); ++ if (err < 0) ++ return err; ++ ++ mask = SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | ++ SD_DAT1_STATUS | SD_DAT0_STATUS; ++ val = SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | ++ SD_DAT1_STATUS | SD_DAT0_STATUS; ++ if ((stat & mask) != val) { ++ dev_dbg(sdmmc_dev(host), ++ "%s: SD_BUS_STAT = 0x%x\n", __func__, stat); ++ rtsx_pci_write_register(pcr, SD_BUS_STAT, ++ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); ++ rtsx_pci_write_register(pcr, CARD_CLK_EN, 0xFF, 0); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct realtek_pci_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_pcr *pcr = host->pcr; ++ int err = 0; ++ u8 voltage; ++ ++ dev_dbg(sdmmc_dev(host), "%s: signal_voltage = %d\n", ++ __func__, ios->signal_voltage); ++ ++ if (host->eject) ++ return -ENOMEDIUM; ++ ++ err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); ++ if (err) ++ return err; ++ ++ mutex_lock(&pcr->pcr_mutex); ++ ++ rtsx_pci_start_run(pcr); ++ ++ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) ++ voltage = OUTPUT_3V3; ++ else ++ voltage = OUTPUT_1V8; ++ ++ if (voltage == OUTPUT_1V8) { ++ err = sd_wait_voltage_stable_1(host); ++ if (err < 0) ++ goto out; ++ } ++ ++ err = rtsx_pci_switch_output_voltage(pcr, voltage); ++ if (err < 0) ++ goto out; ++ ++ if (voltage == OUTPUT_1V8) { ++ err = sd_wait_voltage_stable_2(host); ++ if (err < 0) ++ goto out; ++ } ++ ++out: ++ /* Stop toggle SD clock in idle */ ++ err = rtsx_pci_write_register(pcr, SD_BUS_STAT, ++ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); ++ ++ mutex_unlock(&pcr->pcr_mutex); ++ ++ return err; ++} ++ ++static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) ++{ ++ struct realtek_pci_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_pcr *pcr = host->pcr; ++ int err = 0; ++ ++ if (host->eject) ++ return -ENOMEDIUM; ++ ++ err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); ++ if (err) ++ return err; ++ ++ mutex_lock(&pcr->pcr_mutex); ++ ++ rtsx_pci_start_run(pcr); ++ ++ /* Set initial TX phase */ ++ switch (mmc->ios.timing) { ++ case MMC_TIMING_UHS_SDR104: ++ err = sd_change_phase(host, SDR104_TX_PHASE(pcr), false); ++ break; ++ ++ case MMC_TIMING_UHS_SDR50: ++ err = sd_change_phase(host, SDR50_TX_PHASE(pcr), false); ++ break; ++ ++ case MMC_TIMING_UHS_DDR50: ++ err = sd_change_phase(host, DDR50_TX_PHASE(pcr), false); ++ break; ++ ++ default: ++ err = 0; ++ } ++ ++ if (err) ++ goto out; ++ ++ /* Tuning RX phase */ ++ if ((mmc->ios.timing == MMC_TIMING_UHS_SDR104) || ++ (mmc->ios.timing == MMC_TIMING_UHS_SDR50)) ++ err = sd_tuning_rx(host, opcode); ++ else if (mmc->ios.timing == MMC_TIMING_UHS_DDR50) ++ err = sd_change_phase(host, DDR50_RX_PHASE(pcr), true); ++ ++out: ++ mutex_unlock(&pcr->pcr_mutex); ++ ++ return err; ++} ++ ++static const struct mmc_host_ops realtek_pci_sdmmc_ops = { ++ .request = sdmmc_request, ++ .set_ios = sdmmc_set_ios, ++ .get_ro = sdmmc_get_ro, ++ .get_cd = sdmmc_get_cd, ++ .start_signal_voltage_switch = sdmmc_switch_voltage, ++ .execute_tuning = sdmmc_execute_tuning, ++}; ++ ++static void init_extra_caps(struct realtek_pci_sdmmc *host) ++{ ++ struct mmc_host *mmc = host->mmc; ++ struct rtsx_pcr *pcr = host->pcr; ++ ++ dev_dbg(sdmmc_dev(host), "pcr->extra_caps = 0x%x\n", pcr->extra_caps); ++ ++ if (pcr->extra_caps & EXTRA_CAPS_SD_SDR50) ++ mmc->caps |= MMC_CAP_UHS_SDR50; ++ if (pcr->extra_caps & EXTRA_CAPS_SD_SDR104) ++ mmc->caps |= MMC_CAP_UHS_SDR104; ++ if (pcr->extra_caps & EXTRA_CAPS_SD_DDR50) ++ mmc->caps |= MMC_CAP_UHS_DDR50; ++ if (pcr->extra_caps & EXTRA_CAPS_MMC_HSDDR) ++ mmc->caps |= MMC_CAP_1_8V_DDR; ++ if (pcr->extra_caps & EXTRA_CAPS_MMC_8BIT) ++ mmc->caps |= MMC_CAP_8_BIT_DATA; ++} ++ ++static void realtek_init_host(struct realtek_pci_sdmmc *host) ++{ ++ struct mmc_host *mmc = host->mmc; ++ ++ mmc->f_min = 250000; ++ mmc->f_max = 208000000; ++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; ++ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED | ++ MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST | ++ MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; ++ mmc->max_current_330 = 400; ++ mmc->max_current_180 = 800; ++ mmc->ops = &realtek_pci_sdmmc_ops; ++ ++ init_extra_caps(host); ++ ++ mmc->max_segs = 256; ++ mmc->max_seg_size = 65536; ++ mmc->max_blk_size = 512; ++ mmc->max_blk_count = 65535; ++ mmc->max_req_size = 524288; ++} ++ ++static void rtsx_pci_sdmmc_card_event(struct platform_device *pdev) ++{ ++ struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); ++ ++ mmc_detect_change(host->mmc, 0); ++} ++ ++static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc; ++ struct realtek_pci_sdmmc *host; ++ struct rtsx_pcr *pcr; ++ struct pcr_handle *handle = pdev->dev.platform_data; ++ ++ if (!handle) ++ return -ENXIO; ++ ++ pcr = handle->pcr; ++ if (!pcr) ++ return -ENXIO; ++ ++ dev_dbg(&(pdev->dev), ": Realtek PCI-E SDMMC controller found\n"); ++ ++ mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); ++ if (!mmc) ++ return -ENOMEM; ++ ++ host = mmc_priv(mmc); ++ host->pcr = pcr; ++ host->mmc = mmc; ++ host->pdev = pdev; ++ host->power_state = SDMMC_POWER_OFF; ++ platform_set_drvdata(pdev, host); ++ pcr->slots[RTSX_SD_CARD].p_dev = pdev; ++ pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event; ++ ++ mutex_init(&host->host_mutex); ++ ++ realtek_init_host(host); ++ ++ mmc_add_host(mmc); ++ ++ return 0; ++} ++ ++static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) ++{ ++ struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); ++ struct rtsx_pcr *pcr; ++ struct mmc_host *mmc; ++ ++ if (!host) ++ return 0; ++ ++ pcr = host->pcr; ++ pcr->slots[RTSX_SD_CARD].p_dev = NULL; ++ pcr->slots[RTSX_SD_CARD].card_event = NULL; ++ mmc = host->mmc; ++ ++ mutex_lock(&host->host_mutex); ++ if (host->mrq) { ++ dev_dbg(&(pdev->dev), ++ "%s: Controller removed during transfer\n", ++ mmc_hostname(mmc)); ++ ++ rtsx_pci_complete_unfinished_transfer(pcr); ++ ++ host->mrq->cmd->error = -ENOMEDIUM; ++ if (host->mrq->stop) ++ host->mrq->stop->error = -ENOMEDIUM; ++ mmc_request_done(mmc, host->mrq); ++ } ++ mutex_unlock(&host->host_mutex); ++ ++ mmc_remove_host(mmc); ++ host->eject = true; ++ ++ mmc_free_host(mmc); ++ ++ dev_dbg(&(pdev->dev), ++ ": Realtek PCI-E SDMMC controller has been removed\n"); ++ ++ return 0; ++} ++ ++static struct platform_device_id rtsx_pci_sdmmc_ids[] = { ++ { ++ .name = DRV_NAME_RTSX_PCI_SDMMC, ++ }, { ++ /* sentinel */ ++ } ++}; ++MODULE_DEVICE_TABLE(platform, rtsx_pci_sdmmc_ids); ++ ++static struct platform_driver rtsx_pci_sdmmc_driver = { ++ .probe = rtsx_pci_sdmmc_drv_probe, ++ .remove = rtsx_pci_sdmmc_drv_remove, ++ .id_table = rtsx_pci_sdmmc_ids, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = DRV_NAME_RTSX_PCI_SDMMC, ++ }, ++}; ++module_platform_driver(rtsx_pci_sdmmc_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Wei WANG "); ++MODULE_DESCRIPTION("Realtek PCI-E SD/MMC Card Host Driver"); +diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c +new file mode 100644 +index 0000000..5d3766e +--- /dev/null ++++ b/drivers/mmc/host/rtsx_usb_sdmmc.c +@@ -0,0 +1,1456 @@ ++/* Realtek USB SD/MMC Card Interface driver ++ * ++ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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 ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ * ++ * Author: ++ * Roger Tseng ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \ ++ defined(CONFIG_MMC_REALTEK_USB_MODULE)) ++#include ++#include ++#define RTSX_USB_USE_LEDS_CLASS ++#endif ++ ++struct rtsx_usb_sdmmc { ++ struct platform_device *pdev; ++ struct rtsx_ucr *ucr; ++ struct mmc_host *mmc; ++ struct mmc_request *mrq; ++ ++ struct mutex host_mutex; ++ ++ u8 ssc_depth; ++ unsigned int clock; ++ bool vpclk; ++ bool double_clk; ++ bool host_removal; ++ bool card_exist; ++ bool initial_mode; ++ bool ddr_mode; ++ ++ unsigned char power_mode; ++ ++#ifdef RTSX_USB_USE_LEDS_CLASS ++ struct led_classdev led; ++ char led_name[32]; ++ struct work_struct led_work; ++#endif ++}; ++ ++static inline struct device *sdmmc_dev(struct rtsx_usb_sdmmc *host) ++{ ++ return &(host->pdev->dev); ++} ++ ++static inline void sd_clear_error(struct rtsx_usb_sdmmc *host) ++{ ++ struct rtsx_ucr *ucr = host->ucr; ++ rtsx_usb_ep0_write_register(ucr, CARD_STOP, ++ SD_STOP | SD_CLR_ERR, ++ SD_STOP | SD_CLR_ERR); ++ ++ rtsx_usb_clear_dma_err(ucr); ++ rtsx_usb_clear_fsm_err(ucr); ++} ++ ++#ifdef DEBUG ++static void sd_print_debug_regs(struct rtsx_usb_sdmmc *host) ++{ ++ struct rtsx_ucr *ucr = host->ucr; ++ u8 val = 0; ++ ++ rtsx_usb_ep0_read_register(ucr, SD_STAT1, &val); ++ dev_dbg(sdmmc_dev(host), "SD_STAT1: 0x%x\n", val); ++ rtsx_usb_ep0_read_register(ucr, SD_STAT2, &val); ++ dev_dbg(sdmmc_dev(host), "SD_STAT2: 0x%x\n", val); ++ rtsx_usb_ep0_read_register(ucr, SD_BUS_STAT, &val); ++ dev_dbg(sdmmc_dev(host), "SD_BUS_STAT: 0x%x\n", val); ++} ++#else ++#define sd_print_debug_regs(host) ++#endif /* DEBUG */ ++ ++static int sd_read_data(struct rtsx_usb_sdmmc *host, struct mmc_command *cmd, ++ u16 byte_cnt, u8 *buf, int buf_len, int timeout) ++{ ++ struct rtsx_ucr *ucr = host->ucr; ++ int err; ++ u8 trans_mode; ++ ++ if (!buf) ++ buf_len = 0; ++ ++ rtsx_usb_init_cmd(ucr); ++ if (cmd != NULL) { ++ dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__ ++ , cmd->opcode); ++ if (cmd->opcode == MMC_SEND_TUNING_BLOCK) ++ trans_mode = SD_TM_AUTO_TUNING; ++ else ++ trans_mode = SD_TM_NORMAL_READ; ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ SD_CMD0, 0xFF, (u8)(cmd->opcode) | 0x40); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ SD_CMD1, 0xFF, (u8)(cmd->arg >> 24)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ SD_CMD2, 0xFF, (u8)(cmd->arg >> 16)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ SD_CMD3, 0xFF, (u8)(cmd->arg >> 8)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ SD_CMD4, 0xFF, (u8)cmd->arg); ++ } else { ++ trans_mode = SD_TM_AUTO_READ_3; ++ } ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H, ++ 0xFF, (u8)(byte_cnt >> 8)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, ++ SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | ++ SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); ++ if (trans_mode != SD_TM_AUTO_TUNING) ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, ++ 0xFF, trans_mode | SD_TRANSFER_START); ++ rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, ++ SD_TRANSFER_END, SD_TRANSFER_END); ++ ++ if (cmd != NULL) { ++ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD1, 0, 0); ++ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD2, 0, 0); ++ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD3, 0, 0); ++ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD4, 0, 0); ++ } ++ ++ err = rtsx_usb_send_cmd(ucr, MODE_CR, timeout); ++ if (err) { ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_usb_send_cmd failed (err = %d)\n", err); ++ return err; ++ } ++ ++ err = rtsx_usb_get_rsp(ucr, !cmd ? 1 : 5, timeout); ++ if (err || (ucr->rsp_buf[0] & SD_TRANSFER_ERR)) { ++ sd_print_debug_regs(host); ++ ++ if (!err) { ++ dev_dbg(sdmmc_dev(host), ++ "Transfer failed (SD_TRANSFER = %02x)\n", ++ ucr->rsp_buf[0]); ++ err = -EIO; ++ } else { ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_usb_get_rsp failed (err = %d)\n", err); ++ } ++ ++ return err; ++ } ++ ++ if (cmd != NULL) { ++ cmd->resp[0] = get_unaligned_be32(ucr->rsp_buf + 1); ++ dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", ++ cmd->resp[0]); ++ } ++ ++ if (buf && buf_len) { ++ /* 2-byte aligned part */ ++ err = rtsx_usb_read_ppbuf(ucr, buf, byte_cnt - (byte_cnt % 2)); ++ if (err) { ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_usb_read_ppbuf failed (err = %d)\n", err); ++ return err; ++ } ++ ++ /* unaligned byte */ ++ if (byte_cnt % 2) ++ return rtsx_usb_read_register(ucr, ++ PPBUF_BASE2 + byte_cnt, ++ buf + byte_cnt - 1); ++ } ++ ++ return 0; ++} ++ ++static int sd_write_data(struct rtsx_usb_sdmmc *host, struct mmc_command *cmd, ++ u16 byte_cnt, u8 *buf, int buf_len, int timeout) ++{ ++ struct rtsx_ucr *ucr = host->ucr; ++ int err; ++ u8 trans_mode; ++ ++ if (!buf) ++ buf_len = 0; ++ ++ if (buf && buf_len) { ++ err = rtsx_usb_write_ppbuf(ucr, buf, buf_len); ++ if (err) { ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_usb_write_ppbuf failed (err = %d)\n", ++ err); ++ return err; ++ } ++ } ++ ++ trans_mode = (cmd != NULL) ? SD_TM_AUTO_WRITE_2 : SD_TM_AUTO_WRITE_3; ++ rtsx_usb_init_cmd(ucr); ++ ++ if (cmd != NULL) { ++ dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__, ++ cmd->opcode); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ SD_CMD0, 0xFF, (u8)(cmd->opcode) | 0x40); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ SD_CMD1, 0xFF, (u8)(cmd->arg >> 24)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ SD_CMD2, 0xFF, (u8)(cmd->arg >> 16)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ SD_CMD3, 0xFF, (u8)(cmd->arg >> 8)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ SD_CMD4, 0xFF, (u8)cmd->arg); ++ } ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H, ++ 0xFF, (u8)(byte_cnt >> 8)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, ++ SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | ++ SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, ++ trans_mode | SD_TRANSFER_START); ++ rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, ++ SD_TRANSFER_END, SD_TRANSFER_END); ++ ++ if (cmd != NULL) { ++ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD1, 0, 0); ++ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD2, 0, 0); ++ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD3, 0, 0); ++ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD4, 0, 0); ++ } ++ ++ err = rtsx_usb_send_cmd(ucr, MODE_CR, timeout); ++ if (err) { ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_usb_send_cmd failed (err = %d)\n", err); ++ return err; ++ } ++ ++ err = rtsx_usb_get_rsp(ucr, !cmd ? 1 : 5, timeout); ++ if (err) { ++ sd_print_debug_regs(host); ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_usb_get_rsp failed (err = %d)\n", err); ++ return err; ++ } ++ ++ if (cmd != NULL) { ++ cmd->resp[0] = get_unaligned_be32(ucr->rsp_buf + 1); ++ dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", ++ cmd->resp[0]); ++ } ++ ++ return 0; ++} ++ ++static void sd_send_cmd_get_rsp(struct rtsx_usb_sdmmc *host, ++ struct mmc_command *cmd) ++{ ++ struct rtsx_ucr *ucr = host->ucr; ++ u8 cmd_idx = (u8)cmd->opcode; ++ u32 arg = cmd->arg; ++ int err = 0; ++ int timeout = 100; ++ int i; ++ u8 *ptr; ++ int stat_idx = 0; ++ int len = 2; ++ u8 rsp_type; ++ ++ dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", ++ __func__, cmd_idx, arg); ++ ++ /* Response type: ++ * R0 ++ * R1, R5, R6, R7 ++ * R1b ++ * R2 ++ * R3, R4 ++ */ ++ switch (mmc_resp_type(cmd)) { ++ case MMC_RSP_NONE: ++ rsp_type = SD_RSP_TYPE_R0; ++ break; ++ case MMC_RSP_R1: ++ rsp_type = SD_RSP_TYPE_R1; ++ break; ++ case MMC_RSP_R1 & ~MMC_RSP_CRC: ++ rsp_type = SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7; ++ break; ++ case MMC_RSP_R1B: ++ rsp_type = SD_RSP_TYPE_R1b; ++ break; ++ case MMC_RSP_R2: ++ rsp_type = SD_RSP_TYPE_R2; ++ break; ++ case MMC_RSP_R3: ++ rsp_type = SD_RSP_TYPE_R3; ++ break; ++ default: ++ dev_dbg(sdmmc_dev(host), "cmd->flag is not valid\n"); ++ err = -EINVAL; ++ goto out; ++ } ++ ++ if (rsp_type == SD_RSP_TYPE_R1b) ++ timeout = 3000; ++ ++ if (cmd->opcode == SD_SWITCH_VOLTAGE) { ++ err = rtsx_usb_write_register(ucr, SD_BUS_STAT, ++ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, ++ SD_CLK_TOGGLE_EN); ++ if (err) ++ goto out; ++ } ++ ++ rtsx_usb_init_cmd(ucr); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8)(arg >> 24)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8)(arg >> 16)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8)(arg >> 8)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8)arg); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE, ++ 0x01, PINGPONG_BUFFER); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, ++ 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); ++ rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, ++ SD_TRANSFER_END | SD_STAT_IDLE, ++ SD_TRANSFER_END | SD_STAT_IDLE); ++ ++ if (rsp_type == SD_RSP_TYPE_R2) { ++ /* Read data from ping-pong buffer */ ++ for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) ++ rtsx_usb_add_cmd(ucr, READ_REG_CMD, (u16)i, 0, 0); ++ stat_idx = 16; ++ } else if (rsp_type != SD_RSP_TYPE_R0) { ++ /* Read data from SD_CMDx registers */ ++ for (i = SD_CMD0; i <= SD_CMD4; i++) ++ rtsx_usb_add_cmd(ucr, READ_REG_CMD, (u16)i, 0, 0); ++ stat_idx = 5; ++ } ++ len += stat_idx; ++ ++ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_STAT1, 0, 0); ++ ++ err = rtsx_usb_send_cmd(ucr, MODE_CR, 100); ++ if (err) { ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_usb_send_cmd error (err = %d)\n", err); ++ goto out; ++ } ++ ++ err = rtsx_usb_get_rsp(ucr, len, timeout); ++ if (err || (ucr->rsp_buf[0] & SD_TRANSFER_ERR)) { ++ sd_print_debug_regs(host); ++ sd_clear_error(host); ++ ++ if (!err) { ++ dev_dbg(sdmmc_dev(host), ++ "Transfer failed (SD_TRANSFER = %02x)\n", ++ ucr->rsp_buf[0]); ++ err = -EIO; ++ } else { ++ dev_dbg(sdmmc_dev(host), ++ "rtsx_usb_get_rsp failed (err = %d)\n", err); ++ } ++ ++ goto out; ++ } ++ ++ if (rsp_type == SD_RSP_TYPE_R0) { ++ err = 0; ++ goto out; ++ } ++ ++ /* Skip result of CHECK_REG_CMD */ ++ ptr = ucr->rsp_buf + 1; ++ ++ /* Check (Start,Transmission) bit of Response */ ++ if ((ptr[0] & 0xC0) != 0) { ++ err = -EILSEQ; ++ dev_dbg(sdmmc_dev(host), "Invalid response bit\n"); ++ goto out; ++ } ++ ++ /* Check CRC7 */ ++ if (!(rsp_type & SD_NO_CHECK_CRC7)) { ++ if (ptr[stat_idx] & SD_CRC7_ERR) { ++ err = -EILSEQ; ++ dev_dbg(sdmmc_dev(host), "CRC7 error\n"); ++ goto out; ++ } ++ } ++ ++ if (rsp_type == SD_RSP_TYPE_R2) { ++ for (i = 0; i < 4; i++) { ++ cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4); ++ dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n", ++ i, cmd->resp[i]); ++ } ++ } else { ++ cmd->resp[0] = get_unaligned_be32(ptr + 1); ++ dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n", ++ cmd->resp[0]); ++ } ++ ++out: ++ cmd->error = err; ++} ++ ++static int sd_rw_multi(struct rtsx_usb_sdmmc *host, struct mmc_request *mrq) ++{ ++ struct rtsx_ucr *ucr = host->ucr; ++ struct mmc_data *data = mrq->data; ++ int read = (data->flags & MMC_DATA_READ) ? 1 : 0; ++ u8 cfg2, trans_mode; ++ int err; ++ u8 flag; ++ size_t data_len = data->blksz * data->blocks; ++ unsigned int pipe; ++ ++ if (read) { ++ dev_dbg(sdmmc_dev(host), "%s: read %zu bytes\n", ++ __func__, data_len); ++ cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | ++ SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; ++ trans_mode = SD_TM_AUTO_READ_3; ++ } else { ++ dev_dbg(sdmmc_dev(host), "%s: write %zu bytes\n", ++ __func__, data_len); ++ cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | ++ SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; ++ trans_mode = SD_TM_AUTO_WRITE_3; ++ } ++ ++ rtsx_usb_init_cmd(ucr); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L, ++ 0xFF, (u8)data->blocks); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H, ++ 0xFF, (u8)(data->blocks >> 8)); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE, ++ 0x01, RING_BUFFER); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC3, ++ 0xFF, (u8)(data_len >> 24)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC2, ++ 0xFF, (u8)(data_len >> 16)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC1, ++ 0xFF, (u8)(data_len >> 8)); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC0, ++ 0xFF, (u8)data_len); ++ if (read) { ++ flag = MODE_CDIR; ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL, ++ 0x03 | DMA_PACK_SIZE_MASK, ++ DMA_DIR_FROM_CARD | DMA_EN | DMA_512); ++ } else { ++ flag = MODE_CDOR; ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL, ++ 0x03 | DMA_PACK_SIZE_MASK, ++ DMA_DIR_TO_CARD | DMA_EN | DMA_512); ++ } ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, ++ trans_mode | SD_TRANSFER_START); ++ rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER, ++ SD_TRANSFER_END, SD_TRANSFER_END); ++ ++ err = rtsx_usb_send_cmd(ucr, flag, 100); ++ if (err) ++ return err; ++ ++ if (read) ++ pipe = usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN); ++ else ++ pipe = usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT); ++ ++ err = rtsx_usb_transfer_data(ucr, pipe, data->sg, data_len, ++ data->sg_len, NULL, 10000); ++ if (err) { ++ dev_dbg(sdmmc_dev(host), "rtsx_usb_transfer_data error %d\n" ++ , err); ++ sd_clear_error(host); ++ return err; ++ } ++ ++ return rtsx_usb_get_rsp(ucr, 1, 2000); ++} ++ ++static inline void sd_enable_initial_mode(struct rtsx_usb_sdmmc *host) ++{ ++ rtsx_usb_write_register(host->ucr, SD_CFG1, ++ SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128); ++} ++ ++static inline void sd_disable_initial_mode(struct rtsx_usb_sdmmc *host) ++{ ++ rtsx_usb_write_register(host->ucr, SD_CFG1, ++ SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0); ++} ++ ++static void sd_normal_rw(struct rtsx_usb_sdmmc *host, ++ struct mmc_request *mrq) ++{ ++ struct mmc_command *cmd = mrq->cmd; ++ struct mmc_data *data = mrq->data; ++ u8 *buf; ++ ++ buf = kzalloc(data->blksz, GFP_NOIO); ++ if (!buf) { ++ cmd->error = -ENOMEM; ++ return; ++ } ++ ++ if (data->flags & MMC_DATA_READ) { ++ if (host->initial_mode) ++ sd_disable_initial_mode(host); ++ ++ cmd->error = sd_read_data(host, cmd, (u16)data->blksz, buf, ++ data->blksz, 200); ++ ++ if (host->initial_mode) ++ sd_enable_initial_mode(host); ++ ++ sg_copy_from_buffer(data->sg, data->sg_len, buf, data->blksz); ++ } else { ++ sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz); ++ ++ cmd->error = sd_write_data(host, cmd, (u16)data->blksz, buf, ++ data->blksz, 200); ++ } ++ ++ kfree(buf); ++} ++ ++static int sd_change_phase(struct rtsx_usb_sdmmc *host, u8 sample_point, int tx) ++{ ++ struct rtsx_ucr *ucr = host->ucr; ++ int err; ++ ++ dev_dbg(sdmmc_dev(host), "%s: %s sample_point = %d\n", ++ __func__, tx ? "TX" : "RX", sample_point); ++ ++ rtsx_usb_init_cmd(ucr); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, CLK_CHANGE); ++ ++ if (tx) ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, ++ 0x0F, sample_point); ++ else ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK1_CTL, ++ 0x0F, sample_point); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, ++ PHASE_NOT_RESET, PHASE_NOT_RESET); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, 0); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, SD_ASYNC_FIFO_RST, 0); ++ ++ err = rtsx_usb_send_cmd(ucr, MODE_C, 100); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++static inline u32 get_phase_point(u32 phase_map, unsigned int idx) ++{ ++ idx &= MAX_PHASE; ++ return phase_map & (1 << idx); ++} ++ ++static int get_phase_len(u32 phase_map, unsigned int idx) ++{ ++ int i; ++ ++ for (i = 0; i < MAX_PHASE + 1; i++) { ++ if (get_phase_point(phase_map, idx + i) == 0) ++ return i; ++ } ++ return MAX_PHASE + 1; ++} ++ ++static u8 sd_search_final_phase(struct rtsx_usb_sdmmc *host, u32 phase_map) ++{ ++ int start = 0, len = 0; ++ int start_final = 0, len_final = 0; ++ u8 final_phase = 0xFF; ++ ++ if (phase_map == 0) { ++ dev_dbg(sdmmc_dev(host), "Phase: [map:%x]\n", phase_map); ++ return final_phase; ++ } ++ ++ while (start < MAX_PHASE + 1) { ++ len = get_phase_len(phase_map, start); ++ if (len_final < len) { ++ start_final = start; ++ len_final = len; ++ } ++ start += len ? len : 1; ++ } ++ ++ final_phase = (start_final + len_final / 2) & MAX_PHASE; ++ dev_dbg(sdmmc_dev(host), "Phase: [map:%x] [maxlen:%d] [final:%d]\n", ++ phase_map, len_final, final_phase); ++ ++ return final_phase; ++} ++ ++static void sd_wait_data_idle(struct rtsx_usb_sdmmc *host) ++{ ++ int err, i; ++ u8 val = 0; ++ ++ for (i = 0; i < 100; i++) { ++ err = rtsx_usb_ep0_read_register(host->ucr, ++ SD_DATA_STATE, &val); ++ if (val & SD_DATA_IDLE) ++ return; ++ ++ usleep_range(100, 1000); ++ } ++} ++ ++static int sd_tuning_rx_cmd(struct rtsx_usb_sdmmc *host, ++ u8 opcode, u8 sample_point) ++{ ++ int err; ++ struct mmc_command cmd = {0}; ++ ++ err = sd_change_phase(host, sample_point, 0); ++ if (err) ++ return err; ++ ++ cmd.opcode = MMC_SEND_TUNING_BLOCK; ++ err = sd_read_data(host, &cmd, 0x40, NULL, 0, 100); ++ if (err) { ++ /* Wait till SD DATA IDLE */ ++ sd_wait_data_idle(host); ++ sd_clear_error(host); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static void sd_tuning_phase(struct rtsx_usb_sdmmc *host, ++ u8 opcode, u16 *phase_map) ++{ ++ int err, i; ++ u16 raw_phase_map = 0; ++ ++ for (i = MAX_PHASE; i >= 0; i--) { ++ err = sd_tuning_rx_cmd(host, opcode, (u8)i); ++ if (!err) ++ raw_phase_map |= 1 << i; ++ } ++ ++ if (phase_map) ++ *phase_map = raw_phase_map; ++} ++ ++static int sd_tuning_rx(struct rtsx_usb_sdmmc *host, u8 opcode) ++{ ++ int err, i; ++ u16 raw_phase_map[RX_TUNING_CNT] = {0}, phase_map; ++ u8 final_phase; ++ ++ /* setting fixed default TX phase */ ++ err = sd_change_phase(host, 0x01, 1); ++ if (err) { ++ dev_dbg(sdmmc_dev(host), "TX phase setting failed\n"); ++ return err; ++ } ++ ++ /* tuning RX phase */ ++ for (i = 0; i < RX_TUNING_CNT; i++) { ++ sd_tuning_phase(host, opcode, &(raw_phase_map[i])); ++ ++ if (raw_phase_map[i] == 0) ++ break; ++ } ++ ++ phase_map = 0xFFFF; ++ for (i = 0; i < RX_TUNING_CNT; i++) { ++ dev_dbg(sdmmc_dev(host), "RX raw_phase_map[%d] = 0x%04x\n", ++ i, raw_phase_map[i]); ++ phase_map &= raw_phase_map[i]; ++ } ++ dev_dbg(sdmmc_dev(host), "RX phase_map = 0x%04x\n", phase_map); ++ ++ if (phase_map) { ++ final_phase = sd_search_final_phase(host, phase_map); ++ if (final_phase == 0xFF) ++ return -EINVAL; ++ ++ err = sd_change_phase(host, final_phase, 0); ++ if (err) ++ return err; ++ } else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int sdmmc_get_ro(struct mmc_host *mmc) ++{ ++ struct rtsx_usb_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_ucr *ucr = host->ucr; ++ int err; ++ u16 val; ++ ++ if (host->host_removal) ++ return -ENOMEDIUM; ++ ++ mutex_lock(&ucr->dev_mutex); ++ ++ /* Check SD card detect */ ++ err = rtsx_usb_get_card_status(ucr, &val); ++ ++ mutex_unlock(&ucr->dev_mutex); ++ ++ ++ /* Treat failed detection as non-ro */ ++ if (err) ++ return 0; ++ ++ if (val & SD_WP) ++ return 1; ++ ++ return 0; ++} ++ ++static int sdmmc_get_cd(struct mmc_host *mmc) ++{ ++ struct rtsx_usb_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_ucr *ucr = host->ucr; ++ int err; ++ u16 val; ++ ++ if (host->host_removal) ++ return -ENOMEDIUM; ++ ++ mutex_lock(&ucr->dev_mutex); ++ ++ /* Check SD card detect */ ++ err = rtsx_usb_get_card_status(ucr, &val); ++ ++ mutex_unlock(&ucr->dev_mutex); ++ ++ /* Treat failed detection as non-exist */ ++ if (err) ++ goto no_card; ++ ++ if (val & SD_CD) { ++ host->card_exist = true; ++ return 1; ++ } ++ ++no_card: ++ host->card_exist = false; ++ return 0; ++} ++ ++static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct rtsx_usb_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_ucr *ucr = host->ucr; ++ struct mmc_command *cmd = mrq->cmd; ++ struct mmc_data *data = mrq->data; ++ unsigned int data_size = 0; ++ ++ dev_dbg(sdmmc_dev(host), "%s\n", __func__); ++ ++ if (host->host_removal) { ++ cmd->error = -ENOMEDIUM; ++ goto finish; ++ } ++ ++ if ((!host->card_exist)) { ++ cmd->error = -ENOMEDIUM; ++ goto finish_detect_card; ++ } ++ ++ /* ++ * Reject SDIO CMDs to speed up card identification ++ * since unsupported ++ */ ++ if (cmd->opcode == SD_IO_SEND_OP_COND || ++ cmd->opcode == SD_IO_RW_DIRECT || ++ cmd->opcode == SD_IO_RW_EXTENDED) { ++ cmd->error = -EINVAL; ++ goto finish; ++ } ++ ++ mutex_lock(&ucr->dev_mutex); ++ ++ mutex_lock(&host->host_mutex); ++ host->mrq = mrq; ++ mutex_unlock(&host->host_mutex); ++ ++ if (mrq->data) ++ data_size = data->blocks * data->blksz; ++ ++ if (!data_size) { ++ sd_send_cmd_get_rsp(host, cmd); ++ } else if ((!(data_size % 512) && cmd->opcode != MMC_SEND_EXT_CSD) || ++ mmc_op_multi(cmd->opcode)) { ++ sd_send_cmd_get_rsp(host, cmd); ++ ++ if (!cmd->error) { ++ sd_rw_multi(host, mrq); ++ ++ if (mmc_op_multi(cmd->opcode) && mrq->stop) { ++ sd_send_cmd_get_rsp(host, mrq->stop); ++ rtsx_usb_write_register(ucr, MC_FIFO_CTL, ++ FIFO_FLUSH, FIFO_FLUSH); ++ } ++ } ++ } else { ++ sd_normal_rw(host, mrq); ++ } ++ ++ if (mrq->data) { ++ if (cmd->error || data->error) ++ data->bytes_xfered = 0; ++ else ++ data->bytes_xfered = data->blocks * data->blksz; ++ } ++ ++ mutex_unlock(&ucr->dev_mutex); ++ ++finish_detect_card: ++ if (cmd->error) { ++ /* ++ * detect card when fail to update card existence state and ++ * speed up card removal when retry ++ */ ++ sdmmc_get_cd(mmc); ++ dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); ++ } ++ ++finish: ++ mutex_lock(&host->host_mutex); ++ host->mrq = NULL; ++ mutex_unlock(&host->host_mutex); ++ ++ mmc_request_done(mmc, mrq); ++} ++ ++static int sd_set_bus_width(struct rtsx_usb_sdmmc *host, ++ unsigned char bus_width) ++{ ++ int err = 0; ++ u8 width[] = { ++ [MMC_BUS_WIDTH_1] = SD_BUS_WIDTH_1BIT, ++ [MMC_BUS_WIDTH_4] = SD_BUS_WIDTH_4BIT, ++ [MMC_BUS_WIDTH_8] = SD_BUS_WIDTH_8BIT, ++ }; ++ ++ if (bus_width <= MMC_BUS_WIDTH_8) ++ err = rtsx_usb_write_register(host->ucr, SD_CFG1, ++ 0x03, width[bus_width]); ++ ++ return err; ++} ++ ++static int sd_pull_ctl_disable_lqfp48(struct rtsx_ucr *ucr) ++{ ++ rtsx_usb_init_cmd(ucr); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); ++ ++ return rtsx_usb_send_cmd(ucr, MODE_C, 100); ++} ++ ++static int sd_pull_ctl_disable_qfn24(struct rtsx_ucr *ucr) ++{ ++ rtsx_usb_init_cmd(ucr); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); ++ ++ return rtsx_usb_send_cmd(ucr, MODE_C, 100); ++} ++ ++static int sd_pull_ctl_enable_lqfp48(struct rtsx_ucr *ucr) ++{ ++ rtsx_usb_init_cmd(ucr); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0xAA); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xA9); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); ++ ++ return rtsx_usb_send_cmd(ucr, MODE_C, 100); ++} ++ ++static int sd_pull_ctl_enable_qfn24(struct rtsx_ucr *ucr) ++{ ++ rtsx_usb_init_cmd(ucr); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA5); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x9A); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xA5); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x9A); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x65); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x5A); ++ ++ return rtsx_usb_send_cmd(ucr, MODE_C, 100); ++} ++ ++static int sd_power_on(struct rtsx_usb_sdmmc *host) ++{ ++ struct rtsx_ucr *ucr = host->ucr; ++ int err; ++ ++ dev_dbg(sdmmc_dev(host), "%s\n", __func__); ++ rtsx_usb_init_cmd(ucr); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SHARE_MODE, ++ CARD_SHARE_MASK, CARD_SHARE_SD); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, ++ SD_CLK_EN, SD_CLK_EN); ++ err = rtsx_usb_send_cmd(ucr, MODE_C, 100); ++ if (err) ++ return err; ++ ++ if (CHECK_PKG(ucr, LQFP48)) ++ err = sd_pull_ctl_enable_lqfp48(ucr); ++ else ++ err = sd_pull_ctl_enable_qfn24(ucr); ++ if (err) ++ return err; ++ ++ err = rtsx_usb_write_register(ucr, CARD_PWR_CTL, ++ POWER_MASK, PARTIAL_POWER_ON); ++ if (err) ++ return err; ++ ++ usleep_range(800, 1000); ++ ++ rtsx_usb_init_cmd(ucr); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, ++ POWER_MASK|LDO3318_PWR_MASK, POWER_ON|LDO_ON); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, ++ SD_OUTPUT_EN, SD_OUTPUT_EN); ++ ++ return rtsx_usb_send_cmd(ucr, MODE_C, 100); ++} ++ ++static int sd_power_off(struct rtsx_usb_sdmmc *host) ++{ ++ struct rtsx_ucr *ucr = host->ucr; ++ int err; ++ ++ dev_dbg(sdmmc_dev(host), "%s\n", __func__); ++ rtsx_usb_init_cmd(ucr); ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, ++ POWER_MASK, POWER_OFF); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, ++ POWER_MASK|LDO3318_PWR_MASK, POWER_OFF|LDO_SUSPEND); ++ ++ err = rtsx_usb_send_cmd(ucr, MODE_C, 100); ++ if (err) ++ return err; ++ ++ if (CHECK_PKG(ucr, LQFP48)) ++ return sd_pull_ctl_disable_lqfp48(ucr); ++ return sd_pull_ctl_disable_qfn24(ucr); ++} ++ ++static int sd_set_power_mode(struct rtsx_usb_sdmmc *host, ++ unsigned char power_mode) ++{ ++ int err; ++ ++ if (power_mode != MMC_POWER_OFF) ++ power_mode = MMC_POWER_ON; ++ ++ if (power_mode == host->power_mode) ++ return 0; ++ ++ if (power_mode == MMC_POWER_OFF) { ++ err = sd_power_off(host); ++ pm_runtime_put(sdmmc_dev(host)); ++ } else { ++ pm_runtime_get_sync(sdmmc_dev(host)); ++ err = sd_power_on(host); ++ } ++ ++ if (!err) ++ host->power_mode = power_mode; ++ ++ return err; ++} ++ ++static int sd_set_timing(struct rtsx_usb_sdmmc *host, ++ unsigned char timing, bool *ddr_mode) ++{ ++ struct rtsx_ucr *ucr = host->ucr; ++ int err; ++ ++ *ddr_mode = false; ++ ++ rtsx_usb_init_cmd(ucr); ++ ++ switch (timing) { ++ case MMC_TIMING_UHS_SDR104: ++ case MMC_TIMING_UHS_SDR50: ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, ++ 0x0C | SD_ASYNC_FIFO_RST, ++ SD_30_MODE | SD_ASYNC_FIFO_RST); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, ++ CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); ++ break; ++ ++ case MMC_TIMING_UHS_DDR50: ++ *ddr_mode = true; ++ ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, ++ 0x0C | SD_ASYNC_FIFO_RST, ++ SD_DDR_MODE | SD_ASYNC_FIFO_RST); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, ++ CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PUSH_POINT_CTL, ++ DDR_VAR_TX_CMD_DAT, DDR_VAR_TX_CMD_DAT); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, ++ DDR_VAR_RX_DAT | DDR_VAR_RX_CMD, ++ DDR_VAR_RX_DAT | DDR_VAR_RX_CMD); ++ break; ++ ++ case MMC_TIMING_MMC_HS: ++ case MMC_TIMING_SD_HS: ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, ++ 0x0C, SD_20_MODE); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, ++ CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PUSH_POINT_CTL, ++ SD20_TX_SEL_MASK, SD20_TX_14_AHEAD); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, ++ SD20_RX_SEL_MASK, SD20_RX_14_DELAY); ++ break; ++ ++ default: ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ SD_CFG1, 0x0C, SD_20_MODE); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, ++ CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, ++ SD_PUSH_POINT_CTL, 0xFF, 0); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, ++ SD20_RX_SEL_MASK, SD20_RX_POS_EDGE); ++ break; ++ } ++ ++ err = rtsx_usb_send_cmd(ucr, MODE_C, 100); ++ ++ return err; ++} ++ ++static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct rtsx_usb_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_ucr *ucr = host->ucr; ++ ++ dev_dbg(sdmmc_dev(host), "%s\n", __func__); ++ mutex_lock(&ucr->dev_mutex); ++ ++ if (rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD)) { ++ mutex_unlock(&ucr->dev_mutex); ++ return; ++ } ++ ++ sd_set_power_mode(host, ios->power_mode); ++ sd_set_bus_width(host, ios->bus_width); ++ sd_set_timing(host, ios->timing, &host->ddr_mode); ++ ++ host->vpclk = false; ++ host->double_clk = true; ++ ++ switch (ios->timing) { ++ case MMC_TIMING_UHS_SDR104: ++ case MMC_TIMING_UHS_SDR50: ++ host->ssc_depth = SSC_DEPTH_2M; ++ host->vpclk = true; ++ host->double_clk = false; ++ break; ++ case MMC_TIMING_UHS_DDR50: ++ case MMC_TIMING_UHS_SDR25: ++ host->ssc_depth = SSC_DEPTH_1M; ++ break; ++ default: ++ host->ssc_depth = SSC_DEPTH_512K; ++ break; ++ } ++ ++ host->initial_mode = (ios->clock <= 1000000) ? true : false; ++ host->clock = ios->clock; ++ ++ rtsx_usb_switch_clock(host->ucr, host->clock, host->ssc_depth, ++ host->initial_mode, host->double_clk, host->vpclk); ++ ++ mutex_unlock(&ucr->dev_mutex); ++ dev_dbg(sdmmc_dev(host), "%s end\n", __func__); ++} ++ ++static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct rtsx_usb_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_ucr *ucr = host->ucr; ++ int err = 0; ++ ++ dev_dbg(sdmmc_dev(host), "%s: signal_voltage = %d\n", ++ __func__, ios->signal_voltage); ++ ++ if (host->host_removal) ++ return -ENOMEDIUM; ++ ++ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_120) ++ return -EPERM; ++ ++ mutex_lock(&ucr->dev_mutex); ++ ++ err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD); ++ if (err) { ++ mutex_unlock(&ucr->dev_mutex); ++ return err; ++ } ++ ++ /* Let mmc core do the busy checking, simply stop the forced-toggle ++ * clock(while issuing CMD11) and switch voltage. ++ */ ++ rtsx_usb_init_cmd(ucr); ++ ++ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PAD_CTL, ++ SD_IO_USING_1V8, SD_IO_USING_3V3); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, ++ TUNE_SD18_MASK, TUNE_SD18_3V3); ++ } else { ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BUS_STAT, ++ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, ++ SD_CLK_FORCE_STOP); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PAD_CTL, ++ SD_IO_USING_1V8, SD_IO_USING_1V8); ++ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, ++ TUNE_SD18_MASK, TUNE_SD18_1V8); ++ } ++ ++ err = rtsx_usb_send_cmd(ucr, MODE_C, 100); ++ mutex_unlock(&ucr->dev_mutex); ++ ++ return err; ++} ++ ++static int sdmmc_card_busy(struct mmc_host *mmc) ++{ ++ struct rtsx_usb_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_ucr *ucr = host->ucr; ++ int err; ++ u8 stat; ++ u8 mask = SD_DAT3_STATUS | SD_DAT2_STATUS | SD_DAT1_STATUS ++ | SD_DAT0_STATUS; ++ ++ dev_dbg(sdmmc_dev(host), "%s\n", __func__); ++ ++ mutex_lock(&ucr->dev_mutex); ++ ++ err = rtsx_usb_write_register(ucr, SD_BUS_STAT, ++ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, ++ SD_CLK_TOGGLE_EN); ++ if (err) ++ goto out; ++ ++ mdelay(1); ++ ++ err = rtsx_usb_read_register(ucr, SD_BUS_STAT, &stat); ++ if (err) ++ goto out; ++ ++ err = rtsx_usb_write_register(ucr, SD_BUS_STAT, ++ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); ++out: ++ mutex_unlock(&ucr->dev_mutex); ++ ++ if (err) ++ return err; ++ ++ /* check if any pin between dat[0:3] is low */ ++ if ((stat & mask) != mask) ++ return 1; ++ else ++ return 0; ++} ++ ++static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) ++{ ++ struct rtsx_usb_sdmmc *host = mmc_priv(mmc); ++ struct rtsx_ucr *ucr = host->ucr; ++ int err = 0; ++ ++ if (host->host_removal) ++ return -ENOMEDIUM; ++ ++ mutex_lock(&ucr->dev_mutex); ++ ++ if (!host->ddr_mode) ++ err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK); ++ ++ mutex_unlock(&ucr->dev_mutex); ++ ++ return err; ++} ++ ++static const struct mmc_host_ops rtsx_usb_sdmmc_ops = { ++ .request = sdmmc_request, ++ .set_ios = sdmmc_set_ios, ++ .get_ro = sdmmc_get_ro, ++ .get_cd = sdmmc_get_cd, ++ .start_signal_voltage_switch = sdmmc_switch_voltage, ++ .card_busy = sdmmc_card_busy, ++ .execute_tuning = sdmmc_execute_tuning, ++}; ++ ++#ifdef RTSX_USB_USE_LEDS_CLASS ++static void rtsx_usb_led_control(struct led_classdev *led, ++ enum led_brightness brightness) ++{ ++ struct rtsx_usb_sdmmc *host = container_of(led, ++ struct rtsx_usb_sdmmc, led); ++ ++ if (host->host_removal) ++ return; ++ ++ host->led.brightness = brightness; ++ schedule_work(&host->led_work); ++} ++ ++static void rtsx_usb_update_led(struct work_struct *work) ++{ ++ struct rtsx_usb_sdmmc *host = ++ container_of(work, struct rtsx_usb_sdmmc, led_work); ++ struct rtsx_ucr *ucr = host->ucr; ++ ++ mutex_lock(&ucr->dev_mutex); ++ ++ if (host->led.brightness == LED_OFF) ++ rtsx_usb_turn_off_led(ucr); ++ else ++ rtsx_usb_turn_on_led(ucr); ++ ++ mutex_unlock(&ucr->dev_mutex); ++} ++#endif ++ ++static void rtsx_usb_init_host(struct rtsx_usb_sdmmc *host) ++{ ++ struct mmc_host *mmc = host->mmc; ++ ++ mmc->f_min = 250000; ++ mmc->f_max = 208000000; ++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; ++ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED | ++ MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST | ++ MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | ++ MMC_CAP_NEEDS_POLL; ++ ++ mmc->max_current_330 = 400; ++ mmc->max_current_180 = 800; ++ mmc->ops = &rtsx_usb_sdmmc_ops; ++ mmc->max_segs = 256; ++ mmc->max_seg_size = 65536; ++ mmc->max_blk_size = 512; ++ mmc->max_blk_count = 65535; ++ mmc->max_req_size = 524288; ++ ++ host->power_mode = MMC_POWER_OFF; ++} ++ ++static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc; ++ struct rtsx_usb_sdmmc *host; ++ struct rtsx_ucr *ucr; ++#ifdef RTSX_USB_USE_LEDS_CLASS ++ int err; ++#endif ++ ++ ucr = usb_get_intfdata(to_usb_interface(pdev->dev.parent)); ++ if (!ucr) ++ return -ENXIO; ++ ++ dev_dbg(&(pdev->dev), ": Realtek USB SD/MMC controller found\n"); ++ ++ mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); ++ if (!mmc) ++ return -ENOMEM; ++ ++ host = mmc_priv(mmc); ++ host->ucr = ucr; ++ host->mmc = mmc; ++ host->pdev = pdev; ++ platform_set_drvdata(pdev, host); ++ ++ mutex_init(&host->host_mutex); ++ rtsx_usb_init_host(host); ++ pm_runtime_enable(&pdev->dev); ++ ++#ifdef RTSX_USB_USE_LEDS_CLASS ++ snprintf(host->led_name, sizeof(host->led_name), ++ "%s::", mmc_hostname(mmc)); ++ host->led.name = host->led_name; ++ host->led.brightness = LED_OFF; ++ host->led.default_trigger = mmc_hostname(mmc); ++ host->led.brightness_set = rtsx_usb_led_control; ++ ++ err = led_classdev_register(mmc_dev(mmc), &host->led); ++ if (err) ++ dev_err(&(pdev->dev), ++ "Failed to register LED device: %d\n", err); ++ INIT_WORK(&host->led_work, rtsx_usb_update_led); ++ ++#endif ++ mmc_add_host(mmc); ++ ++ return 0; ++} ++ ++static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev) ++{ ++ struct rtsx_usb_sdmmc *host = platform_get_drvdata(pdev); ++ struct mmc_host *mmc; ++ ++ if (!host) ++ return 0; ++ ++ mmc = host->mmc; ++ host->host_removal = true; ++ ++ mutex_lock(&host->host_mutex); ++ if (host->mrq) { ++ dev_dbg(&(pdev->dev), ++ "%s: Controller removed during transfer\n", ++ mmc_hostname(mmc)); ++ host->mrq->cmd->error = -ENOMEDIUM; ++ if (host->mrq->stop) ++ host->mrq->stop->error = -ENOMEDIUM; ++ mmc_request_done(mmc, host->mrq); ++ } ++ mutex_unlock(&host->host_mutex); ++ ++ mmc_remove_host(mmc); ++ ++#ifdef RTSX_USB_USE_LEDS_CLASS ++ cancel_work_sync(&host->led_work); ++ led_classdev_unregister(&host->led); ++#endif ++ ++ mmc_free_host(mmc); ++ pm_runtime_disable(&pdev->dev); ++ platform_set_drvdata(pdev, NULL); ++ ++ dev_dbg(&(pdev->dev), ++ ": Realtek USB SD/MMC module has been removed\n"); ++ ++ return 0; ++} ++ ++static struct platform_device_id rtsx_usb_sdmmc_ids[] = { ++ { ++ .name = "rtsx_usb_sdmmc", ++ }, { ++ /* sentinel */ ++ } ++}; ++MODULE_DEVICE_TABLE(platform, rtsx_usb_sdmmc_ids); ++ ++static struct platform_driver rtsx_usb_sdmmc_driver = { ++ .probe = rtsx_usb_sdmmc_drv_probe, ++ .remove = rtsx_usb_sdmmc_drv_remove, ++ .id_table = rtsx_usb_sdmmc_ids, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "rtsx_usb_sdmmc", ++ }, ++}; ++module_platform_driver(rtsx_usb_sdmmc_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Roger Tseng "); ++MODULE_DESCRIPTION("Realtek USB SD/MMC Card Host Driver"); +diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c +index 720f993..f237826 100644 +--- a/drivers/mmc/host/s3cmci.c ++++ b/drivers/mmc/host/s3cmci.c +@@ -23,17 +23,97 @@ + #include + #include + ++#include + #include ++#include + +-#include +-#include +- +-#include ++#include + + #include "s3cmci.h" + + #define DRIVER_NAME "s3c-mci" + ++#define S3C2410_SDICON (0x00) ++#define S3C2410_SDIPRE (0x04) ++#define S3C2410_SDICMDARG (0x08) ++#define S3C2410_SDICMDCON (0x0C) ++#define S3C2410_SDICMDSTAT (0x10) ++#define S3C2410_SDIRSP0 (0x14) ++#define S3C2410_SDIRSP1 (0x18) ++#define S3C2410_SDIRSP2 (0x1C) ++#define S3C2410_SDIRSP3 (0x20) ++#define S3C2410_SDITIMER (0x24) ++#define S3C2410_SDIBSIZE (0x28) ++#define S3C2410_SDIDCON (0x2C) ++#define S3C2410_SDIDCNT (0x30) ++#define S3C2410_SDIDSTA (0x34) ++#define S3C2410_SDIFSTA (0x38) ++ ++#define S3C2410_SDIDATA (0x3C) ++#define S3C2410_SDIIMSK (0x40) ++ ++#define S3C2440_SDIDATA (0x40) ++#define S3C2440_SDIIMSK (0x3C) ++ ++#define S3C2440_SDICON_SDRESET (1 << 8) ++#define S3C2410_SDICON_SDIOIRQ (1 << 3) ++#define S3C2410_SDICON_FIFORESET (1 << 1) ++#define S3C2410_SDICON_CLOCKTYPE (1 << 0) ++ ++#define S3C2410_SDICMDCON_LONGRSP (1 << 10) ++#define S3C2410_SDICMDCON_WAITRSP (1 << 9) ++#define S3C2410_SDICMDCON_CMDSTART (1 << 8) ++#define S3C2410_SDICMDCON_SENDERHOST (1 << 6) ++#define S3C2410_SDICMDCON_INDEX (0x3f) ++ ++#define S3C2410_SDICMDSTAT_CRCFAIL (1 << 12) ++#define S3C2410_SDICMDSTAT_CMDSENT (1 << 11) ++#define S3C2410_SDICMDSTAT_CMDTIMEOUT (1 << 10) ++#define S3C2410_SDICMDSTAT_RSPFIN (1 << 9) ++ ++#define S3C2440_SDIDCON_DS_WORD (2 << 22) ++#define S3C2410_SDIDCON_TXAFTERRESP (1 << 20) ++#define S3C2410_SDIDCON_RXAFTERCMD (1 << 19) ++#define S3C2410_SDIDCON_BLOCKMODE (1 << 17) ++#define S3C2410_SDIDCON_WIDEBUS (1 << 16) ++#define S3C2410_SDIDCON_DMAEN (1 << 15) ++#define S3C2410_SDIDCON_STOP (1 << 14) ++#define S3C2440_SDIDCON_DATSTART (1 << 14) ++ ++#define S3C2410_SDIDCON_XFER_RXSTART (2 << 12) ++#define S3C2410_SDIDCON_XFER_TXSTART (3 << 12) ++ ++#define S3C2410_SDIDCON_BLKNUM_MASK (0xFFF) ++ ++#define S3C2410_SDIDSTA_SDIOIRQDETECT (1 << 9) ++#define S3C2410_SDIDSTA_FIFOFAIL (1 << 8) ++#define S3C2410_SDIDSTA_CRCFAIL (1 << 7) ++#define S3C2410_SDIDSTA_RXCRCFAIL (1 << 6) ++#define S3C2410_SDIDSTA_DATATIMEOUT (1 << 5) ++#define S3C2410_SDIDSTA_XFERFINISH (1 << 4) ++#define S3C2410_SDIDSTA_TXDATAON (1 << 1) ++#define S3C2410_SDIDSTA_RXDATAON (1 << 0) ++ ++#define S3C2440_SDIFSTA_FIFORESET (1 << 16) ++#define S3C2440_SDIFSTA_FIFOFAIL (3 << 14) ++#define S3C2410_SDIFSTA_TFDET (1 << 13) ++#define S3C2410_SDIFSTA_RFDET (1 << 12) ++#define S3C2410_SDIFSTA_COUNTMASK (0x7f) ++ ++#define S3C2410_SDIIMSK_RESPONSECRC (1 << 17) ++#define S3C2410_SDIIMSK_CMDSENT (1 << 16) ++#define S3C2410_SDIIMSK_CMDTIMEOUT (1 << 15) ++#define S3C2410_SDIIMSK_RESPONSEND (1 << 14) ++#define S3C2410_SDIIMSK_SDIOIRQ (1 << 12) ++#define S3C2410_SDIIMSK_FIFOFAIL (1 << 11) ++#define S3C2410_SDIIMSK_CRCSTATUS (1 << 10) ++#define S3C2410_SDIIMSK_DATACRC (1 << 9) ++#define S3C2410_SDIIMSK_DATATIMEOUT (1 << 8) ++#define S3C2410_SDIIMSK_DATAFINISH (1 << 7) ++#define S3C2410_SDIIMSK_TXFIFOHALF (1 << 4) ++#define S3C2410_SDIIMSK_RXFIFOLAST (1 << 2) ++#define S3C2410_SDIIMSK_RXFIFOHALF (1 << 0) ++ + enum dbg_channels { + dbg_err = (1 << 0), + dbg_debug = (1 << 1), +@@ -1237,12 +1317,9 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + switch (ios->power_mode) { + case MMC_POWER_ON: + case MMC_POWER_UP: +- s3c2410_gpio_cfgpin(S3C2410_GPE(5), S3C2410_GPE5_SDCLK); +- s3c2410_gpio_cfgpin(S3C2410_GPE(6), S3C2410_GPE6_SDCMD); +- s3c2410_gpio_cfgpin(S3C2410_GPE(7), S3C2410_GPE7_SDDAT0); +- s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1); +- s3c2410_gpio_cfgpin(S3C2410_GPE(9), S3C2410_GPE9_SDDAT2); +- s3c2410_gpio_cfgpin(S3C2410_GPE(10), S3C2410_GPE10_SDDAT3); ++ /* Configure GPE5...GPE10 pins in SD mode */ ++ s3c_gpio_cfgall_range(S3C2410_GPE(5), 6, S3C_GPIO_SFN(2), ++ S3C_GPIO_PULL_NONE); + + if (host->pdata->set_power) + host->pdata->set_power(ios->power_mode, ios->vdd); +@@ -1544,7 +1621,7 @@ static inline void s3cmci_debugfs_remove(struct s3cmci_host *host) { } + + #endif /* CONFIG_DEBUG_FS */ + +-static int __devinit s3cmci_probe(struct platform_device *pdev) ++static int s3cmci_probe(struct platform_device *pdev) + { + struct s3cmci_host *host; + struct mmc_host *mmc; +@@ -1606,7 +1683,7 @@ static int __devinit s3cmci_probe(struct platform_device *pdev) + host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!host->mem) { + dev_err(&pdev->dev, +- "failed to get io memory region resouce.\n"); ++ "failed to get io memory region resource.\n"); + + ret = -ENOENT; + goto probe_free_gpio; +@@ -1630,7 +1707,7 @@ static int __devinit s3cmci_probe(struct platform_device *pdev) + + host->irq = platform_get_irq(pdev, 0); + if (host->irq == 0) { +- dev_err(&pdev->dev, "failed to get interrupt resouce.\n"); ++ dev_err(&pdev->dev, "failed to get interrupt resource.\n"); + ret = -EINVAL; + goto probe_iounmap; + } +@@ -1823,7 +1900,7 @@ static void s3cmci_shutdown(struct platform_device *pdev) + clk_disable(host->clk); + } + +-static int __devexit s3cmci_remove(struct platform_device *pdev) ++static int s3cmci_remove(struct platform_device *pdev) + { + struct mmc_host *mmc = platform_get_drvdata(pdev); + struct s3cmci_host *host = mmc_priv(mmc); +@@ -1874,58 +1951,18 @@ static struct platform_device_id s3cmci_driver_ids[] = { + + MODULE_DEVICE_TABLE(platform, s3cmci_driver_ids); + +- +-#ifdef CONFIG_PM +- +-static int s3cmci_suspend(struct device *dev) +-{ +- struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev)); +- +- return mmc_suspend_host(mmc); +-} +- +-static int s3cmci_resume(struct device *dev) +-{ +- struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev)); +- +- return mmc_resume_host(mmc); +-} +- +-static const struct dev_pm_ops s3cmci_pm = { +- .suspend = s3cmci_suspend, +- .resume = s3cmci_resume, +-}; +- +-#define s3cmci_pm_ops &s3cmci_pm +-#else /* CONFIG_PM */ +-#define s3cmci_pm_ops NULL +-#endif /* CONFIG_PM */ +- +- + static struct platform_driver s3cmci_driver = { + .driver = { + .name = "s3c-sdi", + .owner = THIS_MODULE, +- .pm = s3cmci_pm_ops, + }, + .id_table = s3cmci_driver_ids, + .probe = s3cmci_probe, +- .remove = __devexit_p(s3cmci_remove), ++ .remove = s3cmci_remove, + .shutdown = s3cmci_shutdown, + }; + +-static int __init s3cmci_init(void) +-{ +- return platform_driver_register(&s3cmci_driver); +-} +- +-static void __exit s3cmci_exit(void) +-{ +- platform_driver_unregister(&s3cmci_driver); +-} +- +-module_init(s3cmci_init); +-module_exit(s3cmci_exit); ++module_platform_driver(s3cmci_driver); + + MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver"); + MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c +new file mode 100644 +index 0000000..8ce3c28 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-acpi.c +@@ -0,0 +1,417 @@ ++/* ++ * Secure Digital Host Controller Interface ACPI driver. ++ * ++ * Copyright (c) 2012, Intel Corporation. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "sdhci.h" ++ ++enum { ++ SDHCI_ACPI_SD_CD = BIT(0), ++ SDHCI_ACPI_RUNTIME_PM = BIT(1), ++ SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL = BIT(2), ++}; ++ ++struct sdhci_acpi_chip { ++ const struct sdhci_ops *ops; ++ unsigned int quirks; ++ unsigned int quirks2; ++ unsigned long caps; ++ unsigned int caps2; ++ mmc_pm_flag_t pm_caps; ++}; ++ ++struct sdhci_acpi_slot { ++ const struct sdhci_acpi_chip *chip; ++ unsigned int quirks; ++ unsigned int quirks2; ++ unsigned long caps; ++ unsigned int caps2; ++ mmc_pm_flag_t pm_caps; ++ unsigned int flags; ++}; ++ ++struct sdhci_acpi_host { ++ struct sdhci_host *host; ++ const struct sdhci_acpi_slot *slot; ++ struct platform_device *pdev; ++ bool use_runtime_pm; ++}; ++ ++static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag) ++{ ++ return c->slot && (c->slot->flags & flag); ++} ++ ++static int sdhci_acpi_enable_dma(struct sdhci_host *host) ++{ ++ return 0; ++} ++ ++static void sdhci_acpi_int_hw_reset(struct sdhci_host *host) ++{ ++ u8 reg; ++ ++ reg = sdhci_readb(host, SDHCI_POWER_CONTROL); ++ reg |= 0x10; ++ sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); ++ /* For eMMC, minimum is 1us but give it 9us for good measure */ ++ udelay(9); ++ reg &= ~0x10; ++ sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); ++ /* For eMMC, minimum is 200us but give it 300us for good measure */ ++ usleep_range(300, 1000); ++} ++ ++static const struct sdhci_ops sdhci_acpi_ops_dflt = { ++ .set_clock = sdhci_set_clock, ++ .enable_dma = sdhci_acpi_enable_dma, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++}; ++ ++static const struct sdhci_ops sdhci_acpi_ops_int = { ++ .set_clock = sdhci_set_clock, ++ .enable_dma = sdhci_acpi_enable_dma, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++ .hw_reset = sdhci_acpi_int_hw_reset, ++}; ++ ++static const struct sdhci_acpi_chip sdhci_acpi_chip_int = { ++ .ops = &sdhci_acpi_ops_int, ++}; ++ ++static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = { ++ .chip = &sdhci_acpi_chip_int, ++ .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | MMC_CAP_HW_RESET, ++ .caps2 = MMC_CAP2_HC_ERASE_SZ, ++ .flags = SDHCI_ACPI_RUNTIME_PM, ++}; ++ ++static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { ++ .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION, ++ .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON, ++ .caps = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD, ++ .flags = SDHCI_ACPI_RUNTIME_PM, ++ .pm_caps = MMC_PM_KEEP_POWER, ++}; ++ ++static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { ++ .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL | ++ SDHCI_ACPI_RUNTIME_PM, ++ .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, ++}; ++ ++struct sdhci_acpi_uid_slot { ++ const char *hid; ++ const char *uid; ++ const struct sdhci_acpi_slot *slot; ++}; ++ ++static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = { ++ { "80860F14" , "1" , &sdhci_acpi_slot_int_emmc }, ++ { "80860F14" , "3" , &sdhci_acpi_slot_int_sd }, ++ { "80860F16" , NULL, &sdhci_acpi_slot_int_sd }, ++ { "INT33BB" , "2" , &sdhci_acpi_slot_int_sdio }, ++ { "INT33C6" , NULL, &sdhci_acpi_slot_int_sdio }, ++ { "INT3436" , NULL, &sdhci_acpi_slot_int_sdio }, ++ { "PNP0D40" }, ++ { }, ++}; ++ ++static const struct acpi_device_id sdhci_acpi_ids[] = { ++ { "80860F14" }, ++ { "80860F16" }, ++ { "INT33BB" }, ++ { "INT33C6" }, ++ { "INT3436" }, ++ { "PNP0D40" }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids); ++ ++static const struct sdhci_acpi_slot *sdhci_acpi_get_slot_by_ids(const char *hid, ++ const char *uid) ++{ ++ const struct sdhci_acpi_uid_slot *u; ++ ++ for (u = sdhci_acpi_uids; u->hid; u++) { ++ if (strcmp(u->hid, hid)) ++ continue; ++ if (!u->uid) ++ return u->slot; ++ if (uid && !strcmp(u->uid, uid)) ++ return u->slot; ++ } ++ return NULL; ++} ++ ++static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(acpi_handle handle, ++ const char *hid) ++{ ++ const struct sdhci_acpi_slot *slot; ++ struct acpi_device_info *info; ++ const char *uid = NULL; ++ acpi_status status; ++ ++ status = acpi_get_object_info(handle, &info); ++ if (!ACPI_FAILURE(status) && (info->valid & ACPI_VALID_UID)) ++ uid = info->unique_id.string; ++ ++ slot = sdhci_acpi_get_slot_by_ids(hid, uid); ++ ++ kfree(info); ++ return slot; ++} ++ ++static int sdhci_acpi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ acpi_handle handle = ACPI_HANDLE(dev); ++ struct acpi_device *device; ++ struct sdhci_acpi_host *c; ++ struct sdhci_host *host; ++ struct resource *iomem; ++ resource_size_t len; ++ const char *hid; ++ int err; ++ ++ if (acpi_bus_get_device(handle, &device)) ++ return -ENODEV; ++ ++ if (acpi_bus_get_status(device) || !device->status.present) ++ return -ENODEV; ++ ++ hid = acpi_device_hid(device); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!iomem) ++ return -ENOMEM; ++ ++ len = resource_size(iomem); ++ if (len < 0x100) ++ dev_err(dev, "Invalid iomem size!\n"); ++ ++ if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev))) ++ return -ENOMEM; ++ ++ host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host)); ++ if (IS_ERR(host)) ++ return PTR_ERR(host); ++ ++ c = sdhci_priv(host); ++ c->host = host; ++ c->slot = sdhci_acpi_get_slot(handle, hid); ++ c->pdev = pdev; ++ c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM); ++ ++ platform_set_drvdata(pdev, c); ++ ++ host->hw_name = "ACPI"; ++ host->ops = &sdhci_acpi_ops_dflt; ++ host->irq = platform_get_irq(pdev, 0); ++ ++ host->ioaddr = devm_ioremap_nocache(dev, iomem->start, ++ resource_size(iomem)); ++ if (host->ioaddr == NULL) { ++ err = -ENOMEM; ++ goto err_free; ++ } ++ ++ if (!dev->dma_mask) { ++ u64 dma_mask; ++ ++ if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT) { ++ /* 64-bit DMA is not supported at present */ ++ dma_mask = DMA_BIT_MASK(32); ++ } else { ++ dma_mask = DMA_BIT_MASK(32); ++ } ++ ++ err = dma_coerce_mask_and_coherent(dev, dma_mask); ++ if (err) ++ goto err_free; ++ } ++ ++ if (c->slot) { ++ if (c->slot->chip) { ++ host->ops = c->slot->chip->ops; ++ host->quirks |= c->slot->chip->quirks; ++ host->quirks2 |= c->slot->chip->quirks2; ++ host->mmc->caps |= c->slot->chip->caps; ++ host->mmc->caps2 |= c->slot->chip->caps2; ++ host->mmc->pm_caps |= c->slot->chip->pm_caps; ++ } ++ host->quirks |= c->slot->quirks; ++ host->quirks2 |= c->slot->quirks2; ++ host->mmc->caps |= c->slot->caps; ++ host->mmc->caps2 |= c->slot->caps2; ++ host->mmc->pm_caps |= c->slot->pm_caps; ++ } ++ ++ host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; ++ ++ if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) { ++ bool v = sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL); ++ ++ if (mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0)) { ++ dev_warn(dev, "failed to setup card detect gpio\n"); ++ c->use_runtime_pm = false; ++ } ++ } ++ ++ err = sdhci_add_host(host); ++ if (err) ++ goto err_free; ++ ++ if (c->use_runtime_pm) { ++ pm_runtime_set_active(dev); ++ pm_suspend_ignore_children(dev, 1); ++ pm_runtime_set_autosuspend_delay(dev, 50); ++ pm_runtime_use_autosuspend(dev); ++ pm_runtime_enable(dev); ++ } ++ ++ return 0; ++ ++err_free: ++ sdhci_free_host(c->host); ++ return err; ++} ++ ++static int sdhci_acpi_remove(struct platform_device *pdev) ++{ ++ struct sdhci_acpi_host *c = platform_get_drvdata(pdev); ++ struct device *dev = &pdev->dev; ++ int dead; ++ ++ if (c->use_runtime_pm) { ++ pm_runtime_get_sync(dev); ++ pm_runtime_disable(dev); ++ pm_runtime_put_noidle(dev); ++ } ++ ++ dead = (sdhci_readl(c->host, SDHCI_INT_STATUS) == ~0); ++ sdhci_remove_host(c->host, dead); ++ sdhci_free_host(c->host); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++ ++static int sdhci_acpi_suspend(struct device *dev) ++{ ++ struct sdhci_acpi_host *c = dev_get_drvdata(dev); ++ ++ return sdhci_suspend_host(c->host); ++} ++ ++static int sdhci_acpi_resume(struct device *dev) ++{ ++ struct sdhci_acpi_host *c = dev_get_drvdata(dev); ++ ++ return sdhci_resume_host(c->host); ++} ++ ++#else ++ ++#define sdhci_acpi_suspend NULL ++#define sdhci_acpi_resume NULL ++ ++#endif ++ ++#ifdef CONFIG_PM_RUNTIME ++ ++static int sdhci_acpi_runtime_suspend(struct device *dev) ++{ ++ struct sdhci_acpi_host *c = dev_get_drvdata(dev); ++ ++ return sdhci_runtime_suspend_host(c->host); ++} ++ ++static int sdhci_acpi_runtime_resume(struct device *dev) ++{ ++ struct sdhci_acpi_host *c = dev_get_drvdata(dev); ++ ++ return sdhci_runtime_resume_host(c->host); ++} ++ ++static int sdhci_acpi_runtime_idle(struct device *dev) ++{ ++ return 0; ++} ++ ++#else ++ ++#define sdhci_acpi_runtime_suspend NULL ++#define sdhci_acpi_runtime_resume NULL ++#define sdhci_acpi_runtime_idle NULL ++ ++#endif ++ ++static const struct dev_pm_ops sdhci_acpi_pm_ops = { ++ .suspend = sdhci_acpi_suspend, ++ .resume = sdhci_acpi_resume, ++ .runtime_suspend = sdhci_acpi_runtime_suspend, ++ .runtime_resume = sdhci_acpi_runtime_resume, ++ .runtime_idle = sdhci_acpi_runtime_idle, ++}; ++ ++static struct platform_driver sdhci_acpi_driver = { ++ .driver = { ++ .name = "sdhci-acpi", ++ .owner = THIS_MODULE, ++ .acpi_match_table = sdhci_acpi_ids, ++ .pm = &sdhci_acpi_pm_ops, ++ }, ++ .probe = sdhci_acpi_probe, ++ .remove = sdhci_acpi_remove, ++}; ++ ++module_platform_driver(sdhci_acpi_driver); ++ ++MODULE_DESCRIPTION("Secure Digital Host Controller Interface ACPI driver"); ++MODULE_AUTHOR("Adrian Hunter"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c +new file mode 100644 +index 0000000..dd780c3 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-bcm-kona.c +@@ -0,0 +1,373 @@ ++/* ++ * Copyright (C) 2013 Broadcom 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "sdhci-pltfm.h" ++#include "sdhci.h" ++ ++#define SDHCI_SOFT_RESET 0x01000000 ++#define KONA_SDHOST_CORECTRL 0x8000 ++#define KONA_SDHOST_CD_PINCTRL 0x00000008 ++#define KONA_SDHOST_STOP_HCLK 0x00000004 ++#define KONA_SDHOST_RESET 0x00000002 ++#define KONA_SDHOST_EN 0x00000001 ++ ++#define KONA_SDHOST_CORESTAT 0x8004 ++#define KONA_SDHOST_WP 0x00000002 ++#define KONA_SDHOST_CD_SW 0x00000001 ++ ++#define KONA_SDHOST_COREIMR 0x8008 ++#define KONA_SDHOST_IP 0x00000001 ++ ++#define KONA_SDHOST_COREISR 0x800C ++#define KONA_SDHOST_COREIMSR 0x8010 ++#define KONA_SDHOST_COREDBG1 0x8014 ++#define KONA_SDHOST_COREGPO_MASK 0x8018 ++ ++#define SD_DETECT_GPIO_DEBOUNCE_128MS 128 ++ ++#define KONA_MMC_AUTOSUSPEND_DELAY (50) ++ ++struct sdhci_bcm_kona_dev { ++ struct mutex write_lock; /* protect back to back writes */ ++ struct clk *external_clk; ++}; ++ ++ ++static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host) ++{ ++ unsigned int val; ++ unsigned long timeout; ++ ++ /* This timeout should be sufficent for core to reset */ ++ timeout = jiffies + msecs_to_jiffies(100); ++ ++ /* reset the host using the top level reset */ ++ val = sdhci_readl(host, KONA_SDHOST_CORECTRL); ++ val |= KONA_SDHOST_RESET; ++ sdhci_writel(host, val, KONA_SDHOST_CORECTRL); ++ ++ while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) { ++ if (time_is_before_jiffies(timeout)) { ++ pr_err("Error: sd host is stuck in reset!!!\n"); ++ return -EFAULT; ++ } ++ } ++ ++ /* bring the host out of reset */ ++ val = sdhci_readl(host, KONA_SDHOST_CORECTRL); ++ val &= ~KONA_SDHOST_RESET; ++ ++ /* ++ * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS) ++ * Back-to-Back writes to same register needs delay when SD bus clock ++ * is very low w.r.t AHB clock, mainly during boot-time and during card ++ * insert-removal. ++ */ ++ usleep_range(1000, 5000); ++ sdhci_writel(host, val, KONA_SDHOST_CORECTRL); ++ ++ return 0; ++} ++ ++static void sdhci_bcm_kona_sd_init(struct sdhci_host *host) ++{ ++ unsigned int val; ++ ++ /* enable the interrupt from the IP core */ ++ val = sdhci_readl(host, KONA_SDHOST_COREIMR); ++ val |= KONA_SDHOST_IP; ++ sdhci_writel(host, val, KONA_SDHOST_COREIMR); ++ ++ /* Enable the AHB clock gating module to the host */ ++ val = sdhci_readl(host, KONA_SDHOST_CORECTRL); ++ val |= KONA_SDHOST_EN; ++ ++ /* ++ * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS) ++ * Back-to-Back writes to same register needs delay when SD bus clock ++ * is very low w.r.t AHB clock, mainly during boot-time and during card ++ * insert-removal. ++ */ ++ usleep_range(1000, 5000); ++ sdhci_writel(host, val, KONA_SDHOST_CORECTRL); ++} ++ ++/* ++ * Software emulation of the SD card insertion/removal. Set insert=1 for insert ++ * and insert=0 for removal. The card detection is done by GPIO. For Broadcom ++ * IP to function properly the bit 0 of CORESTAT register needs to be set/reset ++ * to generate the CD IRQ handled in sdhci.c which schedules card_tasklet. ++ */ ++static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert) ++{ ++ struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); ++ struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv); ++ u32 val; ++ ++ /* ++ * Back-to-Back register write needs a delay of min 10uS. ++ * Back-to-Back writes to same register needs delay when SD bus clock ++ * is very low w.r.t AHB clock, mainly during boot-time and during card ++ * insert-removal. ++ * We keep 20uS ++ */ ++ mutex_lock(&kona_dev->write_lock); ++ udelay(20); ++ val = sdhci_readl(host, KONA_SDHOST_CORESTAT); ++ ++ if (insert) { ++ int ret; ++ ++ ret = mmc_gpio_get_ro(host->mmc); ++ if (ret >= 0) ++ val = (val & ~KONA_SDHOST_WP) | ++ ((ret) ? KONA_SDHOST_WP : 0); ++ ++ val |= KONA_SDHOST_CD_SW; ++ sdhci_writel(host, val, KONA_SDHOST_CORESTAT); ++ } else { ++ val &= ~KONA_SDHOST_CD_SW; ++ sdhci_writel(host, val, KONA_SDHOST_CORESTAT); ++ } ++ mutex_unlock(&kona_dev->write_lock); ++ ++ return 0; ++} ++ ++/* ++ * SD card interrupt event callback ++ */ ++static void sdhci_bcm_kona_card_event(struct sdhci_host *host) ++{ ++ if (mmc_gpio_get_cd(host->mmc) > 0) { ++ dev_dbg(mmc_dev(host->mmc), ++ "card inserted\n"); ++ sdhci_bcm_kona_sd_card_emulate(host, 1); ++ } else { ++ dev_dbg(mmc_dev(host->mmc), ++ "card removed\n"); ++ sdhci_bcm_kona_sd_card_emulate(host, 0); ++ } ++} ++ ++/* ++ * Get the base clock. Use central clock source for now. Not sure if different ++ * clock speed to each dev is allowed ++ */ ++static unsigned int sdhci_bcm_kona_get_max_clk(struct sdhci_host *host) ++{ ++ struct sdhci_bcm_kona_dev *kona_dev; ++ struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); ++ kona_dev = sdhci_pltfm_priv(pltfm_priv); ++ ++ return host->mmc->f_max; ++} ++ ++static unsigned int sdhci_bcm_kona_get_timeout_clock(struct sdhci_host *host) ++{ ++ return sdhci_bcm_kona_get_max_clk(host); ++} ++ ++static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host, ++ u8 power_mode) ++{ ++ /* ++ * JEDEC and SD spec specify supplying 74 continuous clocks to ++ * device after power up. With minimum bus (100KHz) that ++ * that translates to 740us ++ */ ++ if (power_mode != MMC_POWER_OFF) ++ udelay(740); ++} ++ ++static struct sdhci_ops sdhci_bcm_kona_ops = { ++ .set_clock = sdhci_set_clock, ++ .get_max_clock = sdhci_bcm_kona_get_max_clk, ++ .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock, ++ .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++ .card_event = sdhci_bcm_kona_card_event, ++}; ++ ++static struct sdhci_pltfm_data sdhci_pltfm_data_kona = { ++ .ops = &sdhci_bcm_kona_ops, ++ .quirks = SDHCI_QUIRK_NO_CARD_NO_RESET | ++ SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_32BIT_DMA_ADDR | ++ SDHCI_QUIRK_32BIT_DMA_SIZE | SDHCI_QUIRK_32BIT_ADMA_SIZE | ++ SDHCI_QUIRK_FORCE_BLK_SZ_2048 | ++ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, ++}; ++ ++static struct __initconst of_device_id sdhci_bcm_kona_of_match[] = { ++ { .compatible = "brcm,kona-sdhci"}, ++ { .compatible = "bcm,kona-sdhci"}, /* deprecated name */ ++ {} ++}; ++MODULE_DEVICE_TABLE(of, sdhci_bcm_kona_of_match); ++ ++static int sdhci_bcm_kona_probe(struct platform_device *pdev) ++{ ++ struct sdhci_bcm_kona_dev *kona_dev = NULL; ++ struct sdhci_pltfm_host *pltfm_priv; ++ struct device *dev = &pdev->dev; ++ struct sdhci_host *host; ++ int ret; ++ ++ ret = 0; ++ ++ host = sdhci_pltfm_init(pdev, &sdhci_pltfm_data_kona, ++ sizeof(*kona_dev)); ++ if (IS_ERR(host)) ++ return PTR_ERR(host); ++ ++ dev_dbg(dev, "%s: inited. IOADDR=%p\n", __func__, host->ioaddr); ++ ++ pltfm_priv = sdhci_priv(host); ++ ++ kona_dev = sdhci_pltfm_priv(pltfm_priv); ++ mutex_init(&kona_dev->write_lock); ++ ++ mmc_of_parse(host->mmc); ++ ++ if (!host->mmc->f_max) { ++ dev_err(&pdev->dev, "Missing max-freq for SDHCI cfg\n"); ++ ret = -ENXIO; ++ goto err_pltfm_free; ++ } ++ ++ /* Get and enable the external clock */ ++ kona_dev->external_clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(kona_dev->external_clk)) { ++ dev_err(dev, "Failed to get external clock\n"); ++ ret = PTR_ERR(kona_dev->external_clk); ++ goto err_pltfm_free; ++ } ++ ++ if (clk_set_rate(kona_dev->external_clk, host->mmc->f_max) != 0) { ++ dev_err(dev, "Failed to set rate external clock\n"); ++ goto err_pltfm_free; ++ } ++ ++ if (clk_prepare_enable(kona_dev->external_clk) != 0) { ++ dev_err(dev, "Failed to enable external clock\n"); ++ goto err_pltfm_free; ++ } ++ ++ dev_dbg(dev, "non-removable=%c\n", ++ (host->mmc->caps & MMC_CAP_NONREMOVABLE) ? 'Y' : 'N'); ++ dev_dbg(dev, "cd_gpio %c, wp_gpio %c\n", ++ (mmc_gpio_get_cd(host->mmc) != -ENOSYS) ? 'Y' : 'N', ++ (mmc_gpio_get_ro(host->mmc) != -ENOSYS) ? 'Y' : 'N'); ++ ++ if (host->mmc->caps & MMC_CAP_NONREMOVABLE) ++ host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; ++ ++ dev_dbg(dev, "is_8bit=%c\n", ++ (host->mmc->caps | MMC_CAP_8_BIT_DATA) ? 'Y' : 'N'); ++ ++ ret = sdhci_bcm_kona_sd_reset(host); ++ if (ret) ++ goto err_clk_disable; ++ ++ sdhci_bcm_kona_sd_init(host); ++ ++ ret = sdhci_add_host(host); ++ if (ret) { ++ dev_err(dev, "Failed sdhci_add_host\n"); ++ goto err_reset; ++ } ++ ++ /* if device is eMMC, emulate card insert right here */ ++ if (host->mmc->caps & MMC_CAP_NONREMOVABLE) { ++ ret = sdhci_bcm_kona_sd_card_emulate(host, 1); ++ if (ret) { ++ dev_err(dev, ++ "unable to emulate card insertion\n"); ++ goto err_remove_host; ++ } ++ } ++ /* ++ * Since the card detection GPIO interrupt is configured to be ++ * edge sensitive, check the initial GPIO value here, emulate ++ * only if the card is present ++ */ ++ if (mmc_gpio_get_cd(host->mmc) > 0) ++ sdhci_bcm_kona_sd_card_emulate(host, 1); ++ ++ dev_dbg(dev, "initialized properly\n"); ++ return 0; ++ ++err_remove_host: ++ sdhci_remove_host(host, 0); ++ ++err_reset: ++ sdhci_bcm_kona_sd_reset(host); ++ ++err_clk_disable: ++ clk_disable_unprepare(kona_dev->external_clk); ++ ++err_pltfm_free: ++ sdhci_pltfm_free(pdev); ++ ++ dev_err(dev, "Probing of sdhci-pltfm failed: %d\n", ret); ++ return ret; ++} ++ ++static int sdhci_bcm_kona_remove(struct platform_device *pdev) ++{ ++ struct sdhci_host *host = platform_get_drvdata(pdev); ++ struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); ++ struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv); ++ int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); ++ ++ sdhci_remove_host(host, dead); ++ ++ clk_disable_unprepare(kona_dev->external_clk); ++ ++ sdhci_pltfm_free(pdev); ++ ++ return 0; ++} ++ ++static struct platform_driver sdhci_bcm_kona_driver = { ++ .driver = { ++ .name = "sdhci-kona", ++ .owner = THIS_MODULE, ++ .pm = SDHCI_PLTFM_PMOPS, ++ .of_match_table = sdhci_bcm_kona_of_match, ++ }, ++ .probe = sdhci_bcm_kona_probe, ++ .remove = sdhci_bcm_kona_remove, ++}; ++module_platform_driver(sdhci_bcm_kona_driver); ++ ++MODULE_DESCRIPTION("SDHCI driver for Broadcom Kona platform"); ++MODULE_AUTHOR("Broadcom"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c +new file mode 100644 +index 0000000..46af9a4 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-bcm2835.c +@@ -0,0 +1,208 @@ ++/* ++ * BCM2835 SDHCI ++ * Copyright (C) 2012 Stephen Warren ++ * Based on U-Boot's MMC driver for the BCM2835 by Oleksandr Tymoshenko & me ++ * Portions of the code there were obviously based on the Linux kernel at: ++ * git://github.com/raspberrypi/linux.git rpi-3.6.y ++ * commit f5b930b "Main bcm2708 linux port" signed-off-by Dom Cobley. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * 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 "sdhci-pltfm.h" ++ ++/* ++ * 400KHz is max freq for card ID etc. Use that as min card clock. We need to ++ * know the min to enable static calculation of max BCM2835_SDHCI_WRITE_DELAY. ++ */ ++#define MIN_FREQ 400000 ++ ++/* ++ * The Arasan has a bugette whereby it may lose the content of successive ++ * writes to registers that are within two SD-card clock cycles of each other ++ * (a clock domain crossing problem). It seems, however, that the data ++ * register does not have this problem, which is just as well - otherwise we'd ++ * have to nobble the DMA engine too. ++ * ++ * This should probably be dynamically calculated based on the actual card ++ * frequency. However, this is the longest we'll have to wait, and doesn't ++ * seem to slow access down too much, so the added complexity doesn't seem ++ * worth it for now. ++ * ++ * 1/MIN_FREQ is (max) time per tick of eMMC clock. ++ * 2/MIN_FREQ is time for two ticks. ++ * Multiply by 1000000 to get uS per two ticks. ++ * *1000000 for uSecs. ++ * +1 for hack rounding. ++ */ ++#define BCM2835_SDHCI_WRITE_DELAY (((2 * 1000000) / MIN_FREQ) + 1) ++ ++struct bcm2835_sdhci { ++ u32 shadow; ++}; ++ ++static void bcm2835_sdhci_writel(struct sdhci_host *host, u32 val, int reg) ++{ ++ writel(val, host->ioaddr + reg); ++ ++ udelay(BCM2835_SDHCI_WRITE_DELAY); ++} ++ ++static inline u32 bcm2835_sdhci_readl(struct sdhci_host *host, int reg) ++{ ++ u32 val = readl(host->ioaddr + reg); ++ ++ if (reg == SDHCI_CAPABILITIES) ++ val |= SDHCI_CAN_VDD_330; ++ ++ return val; ++} ++ ++static void bcm2835_sdhci_writew(struct sdhci_host *host, u16 val, int reg) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct bcm2835_sdhci *bcm2835_host = pltfm_host->priv; ++ u32 oldval = (reg == SDHCI_COMMAND) ? bcm2835_host->shadow : ++ bcm2835_sdhci_readl(host, reg & ~3); ++ u32 word_num = (reg >> 1) & 1; ++ u32 word_shift = word_num * 16; ++ u32 mask = 0xffff << word_shift; ++ u32 newval = (oldval & ~mask) | (val << word_shift); ++ ++ if (reg == SDHCI_TRANSFER_MODE) ++ bcm2835_host->shadow = newval; ++ else ++ bcm2835_sdhci_writel(host, newval, reg & ~3); ++} ++ ++static u16 bcm2835_sdhci_readw(struct sdhci_host *host, int reg) ++{ ++ u32 val = bcm2835_sdhci_readl(host, (reg & ~3)); ++ u32 word_num = (reg >> 1) & 1; ++ u32 word_shift = word_num * 16; ++ u32 word = (val >> word_shift) & 0xffff; ++ ++ return word; ++} ++ ++static void bcm2835_sdhci_writeb(struct sdhci_host *host, u8 val, int reg) ++{ ++ u32 oldval = bcm2835_sdhci_readl(host, reg & ~3); ++ u32 byte_num = reg & 3; ++ u32 byte_shift = byte_num * 8; ++ u32 mask = 0xff << byte_shift; ++ u32 newval = (oldval & ~mask) | (val << byte_shift); ++ ++ bcm2835_sdhci_writel(host, newval, reg & ~3); ++} ++ ++static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg) ++{ ++ u32 val = bcm2835_sdhci_readl(host, (reg & ~3)); ++ u32 byte_num = reg & 3; ++ u32 byte_shift = byte_num * 8; ++ u32 byte = (val >> byte_shift) & 0xff; ++ ++ return byte; ++} ++ ++static unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host) ++{ ++ return MIN_FREQ; ++} ++ ++static const struct sdhci_ops bcm2835_sdhci_ops = { ++ .write_l = bcm2835_sdhci_writel, ++ .write_w = bcm2835_sdhci_writew, ++ .write_b = bcm2835_sdhci_writeb, ++ .read_l = bcm2835_sdhci_readl, ++ .read_w = bcm2835_sdhci_readw, ++ .read_b = bcm2835_sdhci_readb, ++ .set_clock = sdhci_set_clock, ++ .get_max_clock = sdhci_pltfm_clk_get_max_clock, ++ .get_min_clock = bcm2835_sdhci_get_min_clock, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++}; ++ ++static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = { ++ .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | ++ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK, ++ .ops = &bcm2835_sdhci_ops, ++}; ++ ++static int bcm2835_sdhci_probe(struct platform_device *pdev) ++{ ++ struct sdhci_host *host; ++ struct bcm2835_sdhci *bcm2835_host; ++ struct sdhci_pltfm_host *pltfm_host; ++ int ret; ++ ++ host = sdhci_pltfm_init(pdev, &bcm2835_sdhci_pdata, 0); ++ if (IS_ERR(host)) ++ return PTR_ERR(host); ++ ++ bcm2835_host = devm_kzalloc(&pdev->dev, sizeof(*bcm2835_host), ++ GFP_KERNEL); ++ if (!bcm2835_host) { ++ dev_err(mmc_dev(host->mmc), ++ "failed to allocate bcm2835_sdhci\n"); ++ return -ENOMEM; ++ } ++ ++ pltfm_host = sdhci_priv(host); ++ pltfm_host->priv = bcm2835_host; ++ ++ pltfm_host->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(pltfm_host->clk)) { ++ ret = PTR_ERR(pltfm_host->clk); ++ goto err; ++ } ++ ++ return sdhci_add_host(host); ++ ++err: ++ sdhci_pltfm_free(pdev); ++ return ret; ++} ++ ++static int bcm2835_sdhci_remove(struct platform_device *pdev) ++{ ++ return sdhci_pltfm_unregister(pdev); ++} ++ ++static const struct of_device_id bcm2835_sdhci_of_match[] = { ++ { .compatible = "brcm,bcm2835-sdhci" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, bcm2835_sdhci_of_match); ++ ++static struct platform_driver bcm2835_sdhci_driver = { ++ .driver = { ++ .name = "sdhci-bcm2835", ++ .owner = THIS_MODULE, ++ .of_match_table = bcm2835_sdhci_of_match, ++ .pm = SDHCI_PLTFM_PMOPS, ++ }, ++ .probe = bcm2835_sdhci_probe, ++ .remove = bcm2835_sdhci_remove, ++}; ++module_platform_driver(bcm2835_sdhci_driver); ++ ++MODULE_DESCRIPTION("BCM2835 SDHCI driver"); ++MODULE_AUTHOR("Stephen Warren"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c +index b4257e7..14b7407 100644 +--- a/drivers/mmc/host/sdhci-cns3xxx.c ++++ b/drivers/mmc/host/sdhci-cns3xxx.c +@@ -16,7 +16,6 @@ + #include + #include + #include +-#include + #include "sdhci-pltfm.h" + + static unsigned int sdhci_cns3xxx_get_max_clk(struct sdhci_host *host) +@@ -31,13 +30,12 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock) + u16 clk; + unsigned long timeout; + +- if (clock == host->clock) +- return; ++ host->mmc->actual_clock = 0; + + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + + if (clock == 0) +- goto out; ++ return; + + while (host->max_clk / div > clock) { + /* +@@ -76,31 +74,31 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock) + + clk |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); +-out: +- host->clock = clock; + } + +-static struct sdhci_ops sdhci_cns3xxx_ops = { ++static const struct sdhci_ops sdhci_cns3xxx_ops = { + .get_max_clock = sdhci_cns3xxx_get_max_clk, + .set_clock = sdhci_cns3xxx_set_clock, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, + }; + +-static struct sdhci_pltfm_data sdhci_cns3xxx_pdata = { ++static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = { + .ops = &sdhci_cns3xxx_ops, + .quirks = SDHCI_QUIRK_BROKEN_DMA | + SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | + SDHCI_QUIRK_INVERTED_WRITE_PROTECT | + SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | +- SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | +- SDHCI_QUIRK_NONSTANDARD_CLOCK, ++ SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, + }; + +-static int __devinit sdhci_cns3xxx_probe(struct platform_device *pdev) ++static int sdhci_cns3xxx_probe(struct platform_device *pdev) + { +- return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata); ++ return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata, 0); + } + +-static int __devexit sdhci_cns3xxx_remove(struct platform_device *pdev) ++static int sdhci_cns3xxx_remove(struct platform_device *pdev) + { + return sdhci_pltfm_unregister(pdev); + } +@@ -112,20 +110,10 @@ static struct platform_driver sdhci_cns3xxx_driver = { + .pm = SDHCI_PLTFM_PMOPS, + }, + .probe = sdhci_cns3xxx_probe, +- .remove = __devexit_p(sdhci_cns3xxx_remove), ++ .remove = sdhci_cns3xxx_remove, + }; + +-static int __init sdhci_cns3xxx_init(void) +-{ +- return platform_driver_register(&sdhci_cns3xxx_driver); +-} +-module_init(sdhci_cns3xxx_init); +- +-static void __exit sdhci_cns3xxx_exit(void) +-{ +- platform_driver_unregister(&sdhci_cns3xxx_driver); +-} +-module_exit(sdhci_cns3xxx_exit); ++module_platform_driver(sdhci_cns3xxx_driver); + + MODULE_DESCRIPTION("SDHCI driver for CNS3xxx"); + MODULE_AUTHOR("Scott Shu, " +diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c +index 31acb70..e6278ec 100644 +--- a/drivers/mmc/host/sdhci-dove.c ++++ b/drivers/mmc/host/sdhci-dove.c +@@ -19,12 +19,19 @@ + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + ++#include ++#include + #include +-#include + #include ++#include ++#include + + #include "sdhci-pltfm.h" + ++struct sdhci_dove_priv { ++ struct clk *clk; ++}; ++ + static u16 sdhci_dove_readw(struct sdhci_host *host, int reg) + { + u16 ret; +@@ -44,62 +51,110 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg) + { + u32 ret; + ++ ret = readl(host->ioaddr + reg); ++ + switch (reg) { + case SDHCI_CAPABILITIES: +- ret = readl(host->ioaddr + reg); + /* Mask the support for 3.0V */ + ret &= ~SDHCI_CAN_VDD_300; + break; +- default: +- ret = readl(host->ioaddr + reg); + } + return ret; + } + +-static struct sdhci_ops sdhci_dove_ops = { ++static const struct sdhci_ops sdhci_dove_ops = { + .read_w = sdhci_dove_readw, + .read_l = sdhci_dove_readl, ++ .set_clock = sdhci_set_clock, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, + }; + +-static struct sdhci_pltfm_data sdhci_dove_pdata = { ++static const struct sdhci_pltfm_data sdhci_dove_pdata = { + .ops = &sdhci_dove_ops, + .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | + SDHCI_QUIRK_NO_BUSY_IRQ | + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | +- SDHCI_QUIRK_FORCE_DMA, ++ SDHCI_QUIRK_FORCE_DMA | ++ SDHCI_QUIRK_NO_HISPD_BIT, + }; + +-static int __devinit sdhci_dove_probe(struct platform_device *pdev) ++static int sdhci_dove_probe(struct platform_device *pdev) + { +- return sdhci_pltfm_register(pdev, &sdhci_dove_pdata); ++ struct sdhci_host *host; ++ struct sdhci_pltfm_host *pltfm_host; ++ struct sdhci_dove_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv), ++ GFP_KERNEL); ++ if (!priv) { ++ dev_err(&pdev->dev, "unable to allocate private data"); ++ return -ENOMEM; ++ } ++ ++ priv->clk = devm_clk_get(&pdev->dev, NULL); ++ ++ host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0); ++ if (IS_ERR(host)) ++ return PTR_ERR(host); ++ ++ pltfm_host = sdhci_priv(host); ++ pltfm_host->priv = priv; ++ ++ if (!IS_ERR(priv->clk)) ++ clk_prepare_enable(priv->clk); ++ ++ ret = mmc_of_parse(host->mmc); ++ if (ret) ++ goto err_sdhci_add; ++ ++ ret = sdhci_add_host(host); ++ if (ret) ++ goto err_sdhci_add; ++ ++ return 0; ++ ++err_sdhci_add: ++ if (!IS_ERR(priv->clk)) ++ clk_disable_unprepare(priv->clk); ++ sdhci_pltfm_free(pdev); ++ return ret; + } + +-static int __devexit sdhci_dove_remove(struct platform_device *pdev) ++static int sdhci_dove_remove(struct platform_device *pdev) + { +- return sdhci_pltfm_unregister(pdev); ++ struct sdhci_host *host = platform_get_drvdata(pdev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_dove_priv *priv = pltfm_host->priv; ++ ++ sdhci_pltfm_unregister(pdev); ++ ++ if (!IS_ERR(priv->clk)) ++ clk_disable_unprepare(priv->clk); ++ ++ return 0; + } + ++static const struct of_device_id sdhci_dove_of_match_table[] = { ++ { .compatible = "marvell,dove-sdhci", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, sdhci_dove_of_match_table); ++ + static struct platform_driver sdhci_dove_driver = { + .driver = { + .name = "sdhci-dove", + .owner = THIS_MODULE, + .pm = SDHCI_PLTFM_PMOPS, ++ .of_match_table = sdhci_dove_of_match_table, + }, + .probe = sdhci_dove_probe, +- .remove = __devexit_p(sdhci_dove_remove), ++ .remove = sdhci_dove_remove, + }; + +-static int __init sdhci_dove_init(void) +-{ +- return platform_driver_register(&sdhci_dove_driver); +-} +-module_init(sdhci_dove_init); +- +-static void __exit sdhci_dove_exit(void) +-{ +- platform_driver_unregister(&sdhci_dove_driver); +-} +-module_exit(sdhci_dove_exit); ++module_platform_driver(sdhci_dove_driver); + + MODULE_DESCRIPTION("SDHCI driver for Dove"); + MODULE_AUTHOR("Saeed Bishara , " +diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c +index 85a074f..ccec0e3 100644 +--- a/drivers/mmc/host/sdhci-esdhc-imx.c ++++ b/drivers/mmc/host/sdhci-esdhc-imx.c +@@ -21,19 +21,62 @@ + #include + #include + #include ++#include + #include + #include + #include +-#include ++#include ++#include ++#include + #include "sdhci-pltfm.h" + #include "sdhci-esdhc.h" + +-#define SDHCI_CTRL_D3CD 0x08 ++#define ESDHC_CTRL_D3CD 0x08 + /* VENDOR SPEC register */ +-#define SDHCI_VENDOR_SPEC 0xC0 +-#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002 +-#define SDHCI_WTMK_LVL 0x44 +-#define SDHCI_MIX_CTRL 0x48 ++#define ESDHC_VENDOR_SPEC 0xc0 ++#define ESDHC_VENDOR_SPEC_SDIO_QUIRK (1 << 1) ++#define ESDHC_VENDOR_SPEC_VSELECT (1 << 1) ++#define ESDHC_VENDOR_SPEC_FRC_SDCLK_ON (1 << 8) ++#define ESDHC_WTMK_LVL 0x44 ++#define ESDHC_MIX_CTRL 0x48 ++#define ESDHC_MIX_CTRL_DDREN (1 << 3) ++#define ESDHC_MIX_CTRL_AC23EN (1 << 7) ++#define ESDHC_MIX_CTRL_EXE_TUNE (1 << 22) ++#define ESDHC_MIX_CTRL_SMPCLK_SEL (1 << 23) ++#define ESDHC_MIX_CTRL_FBCLK_SEL (1 << 25) ++/* Bits 3 and 6 are not SDHCI standard definitions */ ++#define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7 ++/* Tuning bits */ ++#define ESDHC_MIX_CTRL_TUNING_MASK 0x03c00000 ++ ++/* dll control register */ ++#define ESDHC_DLL_CTRL 0x60 ++#define ESDHC_DLL_OVERRIDE_VAL_SHIFT 9 ++#define ESDHC_DLL_OVERRIDE_EN_SHIFT 8 ++ ++/* tune control register */ ++#define ESDHC_TUNE_CTRL_STATUS 0x68 ++#define ESDHC_TUNE_CTRL_STEP 1 ++#define ESDHC_TUNE_CTRL_MIN 0 ++#define ESDHC_TUNE_CTRL_MAX ((1 << 7) - 1) ++ ++#define ESDHC_TUNING_CTRL 0xcc ++#define ESDHC_STD_TUNING_EN (1 << 24) ++/* NOTE: the minimum valid tuning start tap for mx6sl is 1 */ ++#define ESDHC_TUNING_START_TAP 0x1 ++ ++#define ESDHC_TUNING_BLOCK_PATTERN_LEN 64 ++ ++/* pinctrl state */ ++#define ESDHC_PINCTRL_STATE_100MHZ "state_100mhz" ++#define ESDHC_PINCTRL_STATE_200MHZ "state_200mhz" ++ ++/* ++ * Our interpretation of the SDHCI_HOST_CONTROL register ++ */ ++#define ESDHC_CTRL_4BITBUS (0x1 << 1) ++#define ESDHC_CTRL_8BITBUS (0x2 << 1) ++#define ESDHC_CTRL_BUSWIDTH_MASK (0x3 << 1) + + /* + * There is an INT DMA ERR mis-match between eSDHC and STD SDHC SPEC: +@@ -41,7 +84,7 @@ + * but bit28 is used as the INT DMA ERR in fsl eSDHC design. + * Define this macro DMA error INT for fsl eSDHC + */ +-#define SDHCI_INT_VENDOR_SPEC_DMA_ERR 0x10000000 ++#define ESDHC_INT_VENDOR_SPEC_DMA_ERR (1 << 28) + + /* + * The CMDTYPE of the CMD register (offset 0xE) should be set to +@@ -54,39 +97,82 @@ + * As a result, the TC flag is not asserted and SW received timeout + * exeception. Bit1 of Vendor Spec registor is used to fix it. + */ +-#define ESDHC_FLAG_MULTIBLK_NO_INT (1 << 1) +- +-enum imx_esdhc_type { +- IMX25_ESDHC, +- IMX35_ESDHC, +- IMX51_ESDHC, +- IMX53_ESDHC, +- IMX6Q_USDHC, ++#define ESDHC_FLAG_MULTIBLK_NO_INT BIT(1) ++/* ++ * The flag enables the workaround for ESDHC errata ENGcm07207 which ++ * affects i.MX25 and i.MX35. ++ */ ++#define ESDHC_FLAG_ENGCM07207 BIT(2) ++/* ++ * The flag tells that the ESDHC controller is an USDHC block that is ++ * integrated on the i.MX6 series. ++ */ ++#define ESDHC_FLAG_USDHC BIT(3) ++/* The IP supports manual tuning process */ ++#define ESDHC_FLAG_MAN_TUNING BIT(4) ++/* The IP supports standard tuning process */ ++#define ESDHC_FLAG_STD_TUNING BIT(5) ++/* The IP has SDHCI_CAPABILITIES_1 register */ ++#define ESDHC_FLAG_HAVE_CAP1 BIT(6) ++ ++struct esdhc_soc_data { ++ u32 flags; ++}; ++ ++static struct esdhc_soc_data esdhc_imx25_data = { ++ .flags = ESDHC_FLAG_ENGCM07207, ++}; ++ ++static struct esdhc_soc_data esdhc_imx35_data = { ++ .flags = ESDHC_FLAG_ENGCM07207, ++}; ++ ++static struct esdhc_soc_data esdhc_imx51_data = { ++ .flags = 0, ++}; ++ ++static struct esdhc_soc_data esdhc_imx53_data = { ++ .flags = ESDHC_FLAG_MULTIBLK_NO_INT, ++}; ++ ++static struct esdhc_soc_data usdhc_imx6q_data = { ++ .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING, ++}; ++ ++static struct esdhc_soc_data usdhc_imx6sl_data = { ++ .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING ++ | ESDHC_FLAG_HAVE_CAP1, + }; + + struct pltfm_imx_data { +- int flags; + u32 scratchpad; +- enum imx_esdhc_type devtype; ++ struct pinctrl *pinctrl; ++ struct pinctrl_state *pins_default; ++ struct pinctrl_state *pins_100mhz; ++ struct pinctrl_state *pins_200mhz; ++ const struct esdhc_soc_data *socdata; + struct esdhc_platform_data boarddata; ++ struct clk *clk_ipg; ++ struct clk *clk_ahb; ++ struct clk *clk_per; ++ enum { ++ NO_CMD_PENDING, /* no multiblock command pending*/ ++ MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */ ++ WAIT_FOR_INT, /* sent CMD12, waiting for response INT */ ++ } multiblock_status; ++ u32 is_ddr; + }; + + static struct platform_device_id imx_esdhc_devtype[] = { + { + .name = "sdhci-esdhc-imx25", +- .driver_data = IMX25_ESDHC, ++ .driver_data = (kernel_ulong_t) &esdhc_imx25_data, + }, { + .name = "sdhci-esdhc-imx35", +- .driver_data = IMX35_ESDHC, ++ .driver_data = (kernel_ulong_t) &esdhc_imx35_data, + }, { + .name = "sdhci-esdhc-imx51", +- .driver_data = IMX51_ESDHC, +- }, { +- .name = "sdhci-esdhc-imx53", +- .driver_data = IMX53_ESDHC, +- }, { +- .name = "sdhci-usdhc-imx6q", +- .driver_data = IMX6Q_USDHC, ++ .driver_data = (kernel_ulong_t) &esdhc_imx51_data, + }, { + /* sentinel */ + } +@@ -94,38 +180,34 @@ static struct platform_device_id imx_esdhc_devtype[] = { + MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype); + + static const struct of_device_id imx_esdhc_dt_ids[] = { +- { .compatible = "fsl,imx25-esdhc", .data = &imx_esdhc_devtype[IMX25_ESDHC], }, +- { .compatible = "fsl,imx35-esdhc", .data = &imx_esdhc_devtype[IMX35_ESDHC], }, +- { .compatible = "fsl,imx51-esdhc", .data = &imx_esdhc_devtype[IMX51_ESDHC], }, +- { .compatible = "fsl,imx53-esdhc", .data = &imx_esdhc_devtype[IMX53_ESDHC], }, +- { .compatible = "fsl,imx6q-usdhc", .data = &imx_esdhc_devtype[IMX6Q_USDHC], }, ++ { .compatible = "fsl,imx25-esdhc", .data = &esdhc_imx25_data, }, ++ { .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, }, ++ { .compatible = "fsl,imx51-esdhc", .data = &esdhc_imx51_data, }, ++ { .compatible = "fsl,imx53-esdhc", .data = &esdhc_imx53_data, }, ++ { .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, }, ++ { .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids); + + static inline int is_imx25_esdhc(struct pltfm_imx_data *data) + { +- return data->devtype == IMX25_ESDHC; +-} +- +-static inline int is_imx35_esdhc(struct pltfm_imx_data *data) +-{ +- return data->devtype == IMX35_ESDHC; ++ return data->socdata == &esdhc_imx25_data; + } + +-static inline int is_imx51_esdhc(struct pltfm_imx_data *data) ++static inline int is_imx53_esdhc(struct pltfm_imx_data *data) + { +- return data->devtype == IMX51_ESDHC; ++ return data->socdata == &esdhc_imx53_data; + } + +-static inline int is_imx53_esdhc(struct pltfm_imx_data *data) ++static inline int is_imx6q_usdhc(struct pltfm_imx_data *data) + { +- return data->devtype == IMX53_ESDHC; ++ return data->socdata == &usdhc_imx6q_data; + } + +-static inline int is_imx6q_usdhc(struct pltfm_imx_data *data) ++static inline int esdhc_is_usdhc(struct pltfm_imx_data *data) + { +- return data->devtype == IMX6Q_USDHC; ++ return !!(data->socdata->flags & ESDHC_FLAG_USDHC); + } + + static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg) +@@ -140,22 +222,23 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) + { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host->priv; +- struct esdhc_platform_data *boarddata = &imx_data->boarddata; +- +- /* fake CARD_PRESENT flag */ + u32 val = readl(host->ioaddr + reg); + +- if (unlikely((reg == SDHCI_PRESENT_STATE) +- && gpio_is_valid(boarddata->cd_gpio))) { +- if (gpio_get_value(boarddata->cd_gpio)) +- /* no card, if a valid gpio says so... */ +- val &= ~SDHCI_CARD_PRESENT; +- else +- /* ... in all other cases assume card is present */ +- val |= SDHCI_CARD_PRESENT; ++ if (unlikely(reg == SDHCI_PRESENT_STATE)) { ++ u32 fsl_prss = val; ++ /* save the least 20 bits */ ++ val = fsl_prss & 0x000FFFFF; ++ /* move dat[0-3] bits */ ++ val |= (fsl_prss & 0x0F000000) >> 4; ++ /* move cmd line bit */ ++ val |= (fsl_prss & 0x00800000) << 1; + } + + if (unlikely(reg == SDHCI_CAPABILITIES)) { ++ /* ignore bit[0-15] as it stores cap_1 register val for mx6sl */ ++ if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1) ++ val &= 0xffff0000; ++ + /* In FSL esdhc IC module, only bit20 is used to indicate the + * ADMA2 capability of esdhc, but this bit is messed up on + * some SOCs (e.g. on MX25, MX35 this bit is set, but they +@@ -169,11 +252,42 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) + } + } + ++ if (unlikely(reg == SDHCI_CAPABILITIES_1)) { ++ if (esdhc_is_usdhc(imx_data)) { ++ if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1) ++ val = readl(host->ioaddr + SDHCI_CAPABILITIES) & 0xFFFF; ++ else ++ /* imx6q/dl does not have cap_1 register, fake one */ ++ val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104 ++ | SDHCI_SUPPORT_SDR50 ++ | SDHCI_USE_SDR50_TUNING; ++ } ++ } ++ ++ if (unlikely(reg == SDHCI_MAX_CURRENT) && esdhc_is_usdhc(imx_data)) { ++ val = 0; ++ val |= 0xFF << SDHCI_MAX_CURRENT_330_SHIFT; ++ val |= 0xFF << SDHCI_MAX_CURRENT_300_SHIFT; ++ val |= 0xFF << SDHCI_MAX_CURRENT_180_SHIFT; ++ } ++ + if (unlikely(reg == SDHCI_INT_STATUS)) { +- if (val & SDHCI_INT_VENDOR_SPEC_DMA_ERR) { +- val &= ~SDHCI_INT_VENDOR_SPEC_DMA_ERR; ++ if (val & ESDHC_INT_VENDOR_SPEC_DMA_ERR) { ++ val &= ~ESDHC_INT_VENDOR_SPEC_DMA_ERR; + val |= SDHCI_INT_ADMA_ERROR; + } ++ ++ /* ++ * mask off the interrupt we get in response to the manually ++ * sent CMD12 ++ */ ++ if ((imx_data->multiblock_status == WAIT_FOR_INT) && ++ ((val & SDHCI_INT_RESPONSE) == SDHCI_INT_RESPONSE)) { ++ val &= ~SDHCI_INT_RESPONSE; ++ writel(SDHCI_INT_RESPONSE, host->ioaddr + ++ SDHCI_INT_STATUS); ++ imx_data->multiblock_status = NO_CMD_PENDING; ++ } + } + + return val; +@@ -183,17 +297,9 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) + { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host->priv; +- struct esdhc_platform_data *boarddata = &imx_data->boarddata; + u32 data; + + if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) { +- if (boarddata->cd_type == ESDHC_CD_GPIO) +- /* +- * These interrupts won't work with a custom +- * card_detect gpio (only applied to mx25/35) +- */ +- val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); +- + if (val & SDHCI_INT_CARD_INT) { + /* + * Clear and then set D3CD bit to avoid missing the +@@ -204,26 +310,35 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) + * re-sample it by the following steps. + */ + data = readl(host->ioaddr + SDHCI_HOST_CONTROL); +- data &= ~SDHCI_CTRL_D3CD; ++ data &= ~ESDHC_CTRL_D3CD; + writel(data, host->ioaddr + SDHCI_HOST_CONTROL); +- data |= SDHCI_CTRL_D3CD; ++ data |= ESDHC_CTRL_D3CD; + writel(data, host->ioaddr + SDHCI_HOST_CONTROL); + } + } + +- if (unlikely((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT) ++ if (unlikely((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) + && (reg == SDHCI_INT_STATUS) + && (val & SDHCI_INT_DATA_END))) { + u32 v; +- v = readl(host->ioaddr + SDHCI_VENDOR_SPEC); +- v &= ~SDHCI_VENDOR_SPEC_SDIO_QUIRK; +- writel(v, host->ioaddr + SDHCI_VENDOR_SPEC); ++ v = readl(host->ioaddr + ESDHC_VENDOR_SPEC); ++ v &= ~ESDHC_VENDOR_SPEC_SDIO_QUIRK; ++ writel(v, host->ioaddr + ESDHC_VENDOR_SPEC); ++ ++ if (imx_data->multiblock_status == MULTIBLK_IN_PROCESS) ++ { ++ /* send a manual CMD12 with RESPTYP=none */ ++ data = MMC_STOP_TRANSMISSION << 24 | ++ SDHCI_CMD_ABORTCMD << 16; ++ writel(data, host->ioaddr + SDHCI_TRANSFER_MODE); ++ imx_data->multiblock_status = WAIT_FOR_INT; ++ } + } + + if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) { + if (val & SDHCI_INT_ADMA_ERROR) { + val &= ~SDHCI_INT_ADMA_ERROR; +- val |= SDHCI_INT_VENDOR_SPEC_DMA_ERR; ++ val |= ESDHC_INT_VENDOR_SPEC_DMA_ERR; + } + } + +@@ -234,10 +349,12 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg) + { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host->priv; ++ u16 ret = 0; ++ u32 val; + + if (unlikely(reg == SDHCI_HOST_VERSION)) { + reg ^= 2; +- if (is_imx6q_usdhc(imx_data)) { ++ if (esdhc_is_usdhc(imx_data)) { + /* + * The usdhc register returns a wrong host version. + * Correct it here. +@@ -246,6 +363,45 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg) + } + } + ++ if (unlikely(reg == SDHCI_HOST_CONTROL2)) { ++ val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); ++ if (val & ESDHC_VENDOR_SPEC_VSELECT) ++ ret |= SDHCI_CTRL_VDD_180; ++ ++ if (esdhc_is_usdhc(imx_data)) { ++ if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) ++ val = readl(host->ioaddr + ESDHC_MIX_CTRL); ++ else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) ++ /* the std tuning bits is in ACMD12_ERR for imx6sl */ ++ val = readl(host->ioaddr + SDHCI_ACMD12_ERR); ++ } ++ ++ if (val & ESDHC_MIX_CTRL_EXE_TUNE) ++ ret |= SDHCI_CTRL_EXEC_TUNING; ++ if (val & ESDHC_MIX_CTRL_SMPCLK_SEL) ++ ret |= SDHCI_CTRL_TUNED_CLK; ++ ++ ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; ++ ++ return ret; ++ } ++ ++ if (unlikely(reg == SDHCI_TRANSFER_MODE)) { ++ if (esdhc_is_usdhc(imx_data)) { ++ u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); ++ ret = m & ESDHC_MIX_CTRL_SDHCI_MASK; ++ /* Swap AC23 bit */ ++ if (m & ESDHC_MIX_CTRL_AC23EN) { ++ ret &= ~ESDHC_MIX_CTRL_AC23EN; ++ ret |= SDHCI_TRNS_AUTO_CMD23; ++ } ++ } else { ++ ret = readw(host->ioaddr + SDHCI_TRANSFER_MODE); ++ } ++ ++ return ret; ++ } ++ + return readw(host->ioaddr + reg); + } + +@@ -253,40 +409,94 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) + { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host->priv; ++ u32 new_val = 0; + + switch (reg) { ++ case SDHCI_CLOCK_CONTROL: ++ new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); ++ if (val & SDHCI_CLOCK_CARD_EN) ++ new_val |= ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; ++ else ++ new_val &= ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; ++ writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); ++ return; ++ case SDHCI_HOST_CONTROL2: ++ new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); ++ if (val & SDHCI_CTRL_VDD_180) ++ new_val |= ESDHC_VENDOR_SPEC_VSELECT; ++ else ++ new_val &= ~ESDHC_VENDOR_SPEC_VSELECT; ++ writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); ++ if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { ++ new_val = readl(host->ioaddr + ESDHC_MIX_CTRL); ++ if (val & SDHCI_CTRL_TUNED_CLK) ++ new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL; ++ else ++ new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; ++ writel(new_val , host->ioaddr + ESDHC_MIX_CTRL); ++ } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { ++ u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR); ++ u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); ++ if (val & SDHCI_CTRL_TUNED_CLK) { ++ v |= ESDHC_MIX_CTRL_SMPCLK_SEL; ++ } else { ++ v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; ++ m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; ++ } ++ ++ if (val & SDHCI_CTRL_EXEC_TUNING) { ++ v |= ESDHC_MIX_CTRL_EXE_TUNE; ++ m |= ESDHC_MIX_CTRL_FBCLK_SEL; ++ } else { ++ v &= ~ESDHC_MIX_CTRL_EXE_TUNE; ++ } ++ ++ writel(v, host->ioaddr + SDHCI_ACMD12_ERR); ++ writel(m, host->ioaddr + ESDHC_MIX_CTRL); ++ } ++ return; + case SDHCI_TRANSFER_MODE: +- /* +- * Postpone this write, we must do it together with a +- * command write that is down below. +- */ +- if ((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT) ++ if ((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) + && (host->cmd->opcode == SD_IO_RW_EXTENDED) + && (host->cmd->data->blocks > 1) + && (host->cmd->data->flags & MMC_DATA_READ)) { + u32 v; +- v = readl(host->ioaddr + SDHCI_VENDOR_SPEC); +- v |= SDHCI_VENDOR_SPEC_SDIO_QUIRK; +- writel(v, host->ioaddr + SDHCI_VENDOR_SPEC); ++ v = readl(host->ioaddr + ESDHC_VENDOR_SPEC); ++ v |= ESDHC_VENDOR_SPEC_SDIO_QUIRK; ++ writel(v, host->ioaddr + ESDHC_VENDOR_SPEC); ++ } ++ ++ if (esdhc_is_usdhc(imx_data)) { ++ u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); ++ /* Swap AC23 bit */ ++ if (val & SDHCI_TRNS_AUTO_CMD23) { ++ val &= ~SDHCI_TRNS_AUTO_CMD23; ++ val |= ESDHC_MIX_CTRL_AC23EN; ++ } ++ m = val | (m & ~ESDHC_MIX_CTRL_SDHCI_MASK); ++ writel(m, host->ioaddr + ESDHC_MIX_CTRL); ++ } else { ++ /* ++ * Postpone this write, we must do it together with a ++ * command write that is down below. ++ */ ++ imx_data->scratchpad = val; + } +- imx_data->scratchpad = val; + return; + case SDHCI_COMMAND: +- if ((host->cmd->opcode == MMC_STOP_TRANSMISSION || +- host->cmd->opcode == MMC_SET_BLOCK_COUNT) && +- (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)) ++ if (host->cmd->opcode == MMC_STOP_TRANSMISSION) + val |= SDHCI_CMD_ABORTCMD; + +- if (is_imx6q_usdhc(imx_data)) { +- u32 m = readl(host->ioaddr + SDHCI_MIX_CTRL); +- m = imx_data->scratchpad | (m & 0xffff0000); +- writel(m, host->ioaddr + SDHCI_MIX_CTRL); ++ if ((host->cmd->opcode == MMC_SET_BLOCK_COUNT) && ++ (imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT)) ++ imx_data->multiblock_status = MULTIBLK_IN_PROCESS; ++ ++ if (esdhc_is_usdhc(imx_data)) + writel(val << 16, + host->ioaddr + SDHCI_TRANSFER_MODE); +- } else { ++ else + writel(val << 16 | imx_data->scratchpad, + host->ioaddr + SDHCI_TRANSFER_MODE); +- } + return; + case SDHCI_BLOCK_SIZE: + val &= ~SDHCI_MAKE_BLKSZ(0x7, 0); +@@ -297,7 +507,10 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) + + static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) + { ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct pltfm_imx_data *imx_data = pltfm_host->priv; + u32 new_val; ++ u32 mask; + + switch (reg) { + case SDHCI_POWER_CONTROL: +@@ -307,16 +520,25 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) + */ + return; + case SDHCI_HOST_CONTROL: +- /* FSL messed up here, so we can just keep those three */ +- new_val = val & (SDHCI_CTRL_LED | \ +- SDHCI_CTRL_4BITBUS | \ +- SDHCI_CTRL_D3CD); +- /* ensure the endianess */ ++ /* FSL messed up here, so we need to manually compose it. */ ++ new_val = val & SDHCI_CTRL_LED; ++ /* ensure the endianness */ + new_val |= ESDHC_HOST_CONTROL_LE; +- /* DMA mode bits are shifted */ +- new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5; ++ /* bits 8&9 are reserved on mx25 */ ++ if (!is_imx25_esdhc(imx_data)) { ++ /* DMA mode bits are shifted */ ++ new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5; ++ } ++ ++ /* ++ * Do not touch buswidth bits here. This is done in ++ * esdhc_pltfm_bus_width. ++ * Do not touch the D3CD bit either which is used for the ++ * SDIO interrupt errata workaround. ++ */ ++ mask = 0xffff & ~(ESDHC_CTRL_BUSWIDTH_MASK | ESDHC_CTRL_D3CD); + +- esdhc_clrset_le(host, 0xffff, new_val, reg); ++ esdhc_clrset_le(host, mask, new_val, reg); + return; + } + esdhc_clrset_le(host, 0xff, val, reg); +@@ -329,22 +551,99 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) + * circuit relies on. To work around it, we turn the clocks on back + * to keep card detection circuit functional. + */ +- if ((reg == SDHCI_SOFTWARE_RESET) && (val & 1)) ++ if ((reg == SDHCI_SOFTWARE_RESET) && (val & 1)) { + esdhc_clrset_le(host, 0x7, 0x7, ESDHC_SYSTEM_CONTROL); ++ /* ++ * The reset on usdhc fails to clear MIX_CTRL register. ++ * Do it manually here. ++ */ ++ if (esdhc_is_usdhc(imx_data)) { ++ /* the tuning bits should be kept during reset */ ++ new_val = readl(host->ioaddr + ESDHC_MIX_CTRL); ++ writel(new_val & ESDHC_MIX_CTRL_TUNING_MASK, ++ host->ioaddr + ESDHC_MIX_CTRL); ++ imx_data->is_ddr = 0; ++ } ++ } + } + + static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) + { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct pltfm_imx_data *imx_data = pltfm_host->priv; ++ struct esdhc_platform_data *boarddata = &imx_data->boarddata; + +- return clk_get_rate(pltfm_host->clk); ++ if (boarddata->f_max && (boarddata->f_max < pltfm_host->clock)) ++ return boarddata->f_max; ++ else ++ return pltfm_host->clock; + } + + static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) + { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + +- return clk_get_rate(pltfm_host->clk) / 256 / 16; ++ return pltfm_host->clock / 256 / 16; ++} ++ ++static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, ++ unsigned int clock) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct pltfm_imx_data *imx_data = pltfm_host->priv; ++ unsigned int host_clock = pltfm_host->clock; ++ int pre_div = 2; ++ int div = 1; ++ u32 temp, val; ++ ++ if (clock == 0) { ++ host->mmc->actual_clock = 0; ++ ++ if (esdhc_is_usdhc(imx_data)) { ++ val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); ++ writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, ++ host->ioaddr + ESDHC_VENDOR_SPEC); ++ } ++ return; ++ } ++ ++ if (esdhc_is_usdhc(imx_data) && !imx_data->is_ddr) ++ pre_div = 1; ++ ++ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); ++ temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN ++ | ESDHC_CLOCK_MASK); ++ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); ++ ++ while (host_clock / pre_div / 16 > clock && pre_div < 256) ++ pre_div *= 2; ++ ++ while (host_clock / pre_div / div > clock && div < 16) ++ div++; ++ ++ host->mmc->actual_clock = host_clock / pre_div / div; ++ dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", ++ clock, host->mmc->actual_clock); ++ ++ if (imx_data->is_ddr) ++ pre_div >>= 2; ++ else ++ pre_div >>= 1; ++ div--; ++ ++ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); ++ temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN ++ | (div << ESDHC_DIVIDER_SHIFT) ++ | (pre_div << ESDHC_PREDIV_SHIFT)); ++ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); ++ ++ if (esdhc_is_usdhc(imx_data)) { ++ val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); ++ writel(val | ESDHC_VENDOR_SPEC_FRC_SDCLK_ON, ++ host->ioaddr + ESDHC_VENDOR_SPEC); ++ } ++ ++ mdelay(1); + } + + static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) +@@ -355,8 +654,7 @@ static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) + + switch (boarddata->wp_type) { + case ESDHC_WP_GPIO: +- if (gpio_is_valid(boarddata->wp_gpio)) +- return gpio_get_value(boarddata->wp_gpio); ++ return mmc_gpio_get_ro(host->mmc); + case ESDHC_WP_CONTROLLER: + return !(readl(host->ioaddr + SDHCI_PRESENT_STATE) & + SDHCI_WRITE_PROTECT); +@@ -367,19 +665,237 @@ static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) + return -ENOSYS; + } + ++static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) ++{ ++ u32 ctrl; ++ ++ switch (width) { ++ case MMC_BUS_WIDTH_8: ++ ctrl = ESDHC_CTRL_8BITBUS; ++ break; ++ case MMC_BUS_WIDTH_4: ++ ctrl = ESDHC_CTRL_4BITBUS; ++ break; ++ default: ++ ctrl = 0; ++ break; ++ } ++ ++ esdhc_clrset_le(host, ESDHC_CTRL_BUSWIDTH_MASK, ctrl, ++ SDHCI_HOST_CONTROL); ++} ++ ++static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) ++{ ++ u32 reg; ++ ++ /* FIXME: delay a bit for card to be ready for next tuning due to errors */ ++ mdelay(1); ++ ++ /* This is balanced by the runtime put in sdhci_tasklet_finish */ ++ pm_runtime_get_sync(host->mmc->parent); ++ reg = readl(host->ioaddr + ESDHC_MIX_CTRL); ++ reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | ++ ESDHC_MIX_CTRL_FBCLK_SEL; ++ writel(reg, host->ioaddr + ESDHC_MIX_CTRL); ++ writel(val << 8, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); ++ dev_dbg(mmc_dev(host->mmc), ++ "tunning with delay 0x%x ESDHC_TUNE_CTRL_STATUS 0x%x\n", ++ val, readl(host->ioaddr + ESDHC_TUNE_CTRL_STATUS)); ++} ++ ++static void esdhc_request_done(struct mmc_request *mrq) ++{ ++ complete(&mrq->completion); ++} ++ ++static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode, ++ struct scatterlist *sg) ++{ ++ struct mmc_command cmd = {0}; ++ struct mmc_request mrq = {NULL}; ++ struct mmc_data data = {0}; ++ ++ cmd.opcode = opcode; ++ cmd.arg = 0; ++ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; ++ ++ data.blksz = ESDHC_TUNING_BLOCK_PATTERN_LEN; ++ data.blocks = 1; ++ data.flags = MMC_DATA_READ; ++ data.sg = sg; ++ data.sg_len = 1; ++ ++ mrq.cmd = &cmd; ++ mrq.cmd->mrq = &mrq; ++ mrq.data = &data; ++ mrq.data->mrq = &mrq; ++ mrq.cmd->data = mrq.data; ++ ++ mrq.done = esdhc_request_done; ++ init_completion(&(mrq.completion)); ++ ++ spin_lock_irq(&host->lock); ++ host->mrq = &mrq; ++ ++ sdhci_send_command(host, mrq.cmd); ++ ++ spin_unlock_irq(&host->lock); ++ ++ wait_for_completion(&mrq.completion); ++ ++ if (cmd.error) ++ return cmd.error; ++ if (data.error) ++ return data.error; ++ ++ return 0; ++} ++ ++static void esdhc_post_tuning(struct sdhci_host *host) ++{ ++ u32 reg; ++ ++ reg = readl(host->ioaddr + ESDHC_MIX_CTRL); ++ reg &= ~ESDHC_MIX_CTRL_EXE_TUNE; ++ writel(reg, host->ioaddr + ESDHC_MIX_CTRL); ++} ++ ++static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode) ++{ ++ struct scatterlist sg; ++ char *tuning_pattern; ++ int min, max, avg, ret; ++ ++ tuning_pattern = kmalloc(ESDHC_TUNING_BLOCK_PATTERN_LEN, GFP_KERNEL); ++ if (!tuning_pattern) ++ return -ENOMEM; ++ ++ sg_init_one(&sg, tuning_pattern, ESDHC_TUNING_BLOCK_PATTERN_LEN); ++ ++ /* find the mininum delay first which can pass tuning */ ++ min = ESDHC_TUNE_CTRL_MIN; ++ while (min < ESDHC_TUNE_CTRL_MAX) { ++ esdhc_prepare_tuning(host, min); ++ if (!esdhc_send_tuning_cmd(host, opcode, &sg)) ++ break; ++ min += ESDHC_TUNE_CTRL_STEP; ++ } ++ ++ /* find the maxinum delay which can not pass tuning */ ++ max = min + ESDHC_TUNE_CTRL_STEP; ++ while (max < ESDHC_TUNE_CTRL_MAX) { ++ esdhc_prepare_tuning(host, max); ++ if (esdhc_send_tuning_cmd(host, opcode, &sg)) { ++ max -= ESDHC_TUNE_CTRL_STEP; ++ break; ++ } ++ max += ESDHC_TUNE_CTRL_STEP; ++ } ++ ++ /* use average delay to get the best timing */ ++ avg = (min + max) / 2; ++ esdhc_prepare_tuning(host, avg); ++ ret = esdhc_send_tuning_cmd(host, opcode, &sg); ++ esdhc_post_tuning(host); ++ ++ kfree(tuning_pattern); ++ ++ dev_dbg(mmc_dev(host->mmc), "tunning %s at 0x%x ret %d\n", ++ ret ? "failed" : "passed", avg, ret); ++ ++ return ret; ++} ++ ++static int esdhc_change_pinstate(struct sdhci_host *host, ++ unsigned int uhs) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct pltfm_imx_data *imx_data = pltfm_host->priv; ++ struct pinctrl_state *pinctrl; ++ ++ dev_dbg(mmc_dev(host->mmc), "change pinctrl state for uhs %d\n", uhs); ++ ++ if (IS_ERR(imx_data->pinctrl) || ++ IS_ERR(imx_data->pins_default) || ++ IS_ERR(imx_data->pins_100mhz) || ++ IS_ERR(imx_data->pins_200mhz)) ++ return -EINVAL; ++ ++ switch (uhs) { ++ case MMC_TIMING_UHS_SDR50: ++ pinctrl = imx_data->pins_100mhz; ++ break; ++ case MMC_TIMING_UHS_SDR104: ++ case MMC_TIMING_MMC_HS200: ++ pinctrl = imx_data->pins_200mhz; ++ break; ++ default: ++ /* back to default state for other legacy timing */ ++ pinctrl = imx_data->pins_default; ++ } ++ ++ return pinctrl_select_state(imx_data->pinctrl, pinctrl); ++} ++ ++static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct pltfm_imx_data *imx_data = pltfm_host->priv; ++ struct esdhc_platform_data *boarddata = &imx_data->boarddata; ++ ++ switch (timing) { ++ case MMC_TIMING_UHS_SDR12: ++ case MMC_TIMING_UHS_SDR25: ++ case MMC_TIMING_UHS_SDR50: ++ case MMC_TIMING_UHS_SDR104: ++ case MMC_TIMING_MMC_HS200: ++ break; ++ case MMC_TIMING_UHS_DDR50: ++ case MMC_TIMING_MMC_DDR52: ++ writel(readl(host->ioaddr + ESDHC_MIX_CTRL) | ++ ESDHC_MIX_CTRL_DDREN, ++ host->ioaddr + ESDHC_MIX_CTRL); ++ imx_data->is_ddr = 1; ++ if (boarddata->delay_line) { ++ u32 v; ++ v = boarddata->delay_line << ++ ESDHC_DLL_OVERRIDE_VAL_SHIFT | ++ (1 << ESDHC_DLL_OVERRIDE_EN_SHIFT); ++ if (is_imx53_esdhc(imx_data)) ++ v <<= 1; ++ writel(v, host->ioaddr + ESDHC_DLL_CTRL); ++ } ++ break; ++ } ++ ++ esdhc_change_pinstate(host, timing); ++} ++ ++static void esdhc_reset(struct sdhci_host *host, u8 mask) ++{ ++ sdhci_reset(host, mask); ++ ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++} ++ + static struct sdhci_ops sdhci_esdhc_ops = { + .read_l = esdhc_readl_le, + .read_w = esdhc_readw_le, + .write_l = esdhc_writel_le, + .write_w = esdhc_writew_le, + .write_b = esdhc_writeb_le, +- .set_clock = esdhc_set_clock, ++ .set_clock = esdhc_pltfm_set_clock, + .get_max_clock = esdhc_pltfm_get_max_clock, + .get_min_clock = esdhc_pltfm_get_min_clock, + .get_ro = esdhc_pltfm_get_ro, ++ .set_bus_width = esdhc_pltfm_set_bus_width, ++ .set_uhs_signaling = esdhc_set_uhs_signaling, ++ .reset = esdhc_reset, + }; + +-static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { ++static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { + .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_HISPD_BIT + | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC + | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC +@@ -387,16 +903,8 @@ static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { + .ops = &sdhci_esdhc_ops, + }; + +-static irqreturn_t cd_irq(int irq, void *data) +-{ +- struct sdhci_host *sdhost = (struct sdhci_host *)data; +- +- tasklet_schedule(&sdhost->card_tasklet); +- return IRQ_HANDLED; +-}; +- + #ifdef CONFIG_OF +-static int __devinit ++static int + sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, + struct esdhc_platform_data *boarddata) + { +@@ -405,7 +913,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, + if (!np) + return -ENODEV; + +- if (of_get_property(np, "fsl,card-wired", NULL)) ++ if (of_get_property(np, "non-removable", NULL)) + boarddata->cd_type = ESDHC_CD_PERMANENT; + + if (of_get_property(np, "fsl,cd-controller", NULL)) +@@ -422,6 +930,18 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, + if (gpio_is_valid(boarddata->wp_gpio)) + boarddata->wp_type = ESDHC_WP_GPIO; + ++ of_property_read_u32(np, "bus-width", &boarddata->max_bus_width); ++ ++ of_property_read_u32(np, "max-frequency", &boarddata->f_max); ++ ++ if (of_find_property(np, "no-1-8-v", NULL)) ++ boarddata->support_vsel = false; ++ else ++ boarddata->support_vsel = true; ++ ++ if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line)) ++ boarddata->delay_line = 0; ++ + return 0; + } + #else +@@ -433,66 +953,102 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, + } + #endif + +-static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) ++static int sdhci_esdhc_imx_probe(struct platform_device *pdev) + { + const struct of_device_id *of_id = + of_match_device(imx_esdhc_dt_ids, &pdev->dev); + struct sdhci_pltfm_host *pltfm_host; + struct sdhci_host *host; + struct esdhc_platform_data *boarddata; +- struct clk *clk; + int err; + struct pltfm_imx_data *imx_data; + +- host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata); ++ host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata, 0); + if (IS_ERR(host)) + return PTR_ERR(host); + + pltfm_host = sdhci_priv(host); + +- imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL); ++ imx_data = devm_kzalloc(&pdev->dev, sizeof(*imx_data), GFP_KERNEL); + if (!imx_data) { + err = -ENOMEM; +- goto err_imx_data; ++ goto free_sdhci; + } + +- if (of_id) +- pdev->id_entry = of_id->data; +- imx_data->devtype = pdev->id_entry->driver_data; ++ imx_data->socdata = of_id ? of_id->data : (struct esdhc_soc_data *) ++ pdev->id_entry->driver_data; + pltfm_host->priv = imx_data; + +- clk = clk_get(mmc_dev(host->mmc), NULL); +- if (IS_ERR(clk)) { +- dev_err(mmc_dev(host->mmc), "clk err\n"); +- err = PTR_ERR(clk); +- goto err_clk_get; ++ imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); ++ if (IS_ERR(imx_data->clk_ipg)) { ++ err = PTR_ERR(imx_data->clk_ipg); ++ goto free_sdhci; ++ } ++ ++ imx_data->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); ++ if (IS_ERR(imx_data->clk_ahb)) { ++ err = PTR_ERR(imx_data->clk_ahb); ++ goto free_sdhci; ++ } ++ ++ imx_data->clk_per = devm_clk_get(&pdev->dev, "per"); ++ if (IS_ERR(imx_data->clk_per)) { ++ err = PTR_ERR(imx_data->clk_per); ++ goto free_sdhci; ++ } ++ ++ pltfm_host->clk = imx_data->clk_per; ++ pltfm_host->clock = clk_get_rate(pltfm_host->clk); ++ clk_prepare_enable(imx_data->clk_per); ++ clk_prepare_enable(imx_data->clk_ipg); ++ clk_prepare_enable(imx_data->clk_ahb); ++ ++ imx_data->pinctrl = devm_pinctrl_get(&pdev->dev); ++ if (IS_ERR(imx_data->pinctrl)) { ++ err = PTR_ERR(imx_data->pinctrl); ++ goto disable_clk; ++ } ++ ++ imx_data->pins_default = pinctrl_lookup_state(imx_data->pinctrl, ++ PINCTRL_STATE_DEFAULT); ++ if (IS_ERR(imx_data->pins_default)) { ++ err = PTR_ERR(imx_data->pins_default); ++ dev_err(mmc_dev(host->mmc), "could not get default state\n"); ++ goto disable_clk; + } +- clk_enable(clk); +- pltfm_host->clk = clk; + + host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; + +- if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data)) ++ if (imx_data->socdata->flags & ESDHC_FLAG_ENGCM07207) + /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */ + host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK + | SDHCI_QUIRK_BROKEN_ADMA; + +- if (is_imx53_esdhc(imx_data)) +- imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT; +- + /* + * The imx6q ROM code will change the default watermark level setting + * to something insane. Change it back here. + */ +- if (is_imx6q_usdhc(imx_data)) +- writel(0x08100810, host->ioaddr + SDHCI_WTMK_LVL); ++ if (esdhc_is_usdhc(imx_data)) { ++ writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL); ++ host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; ++ host->mmc->caps |= MMC_CAP_1_8V_DDR; ++ } ++ ++ if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) ++ sdhci_esdhc_ops.platform_execute_tuning = ++ esdhc_executing_tuning; ++ ++ if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) ++ writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) | ++ ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP, ++ host->ioaddr + ESDHC_TUNING_CTRL); + + boarddata = &imx_data->boarddata; + if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { + if (!host->mmc->parent->platform_data) { + dev_err(mmc_dev(host->mmc), "no board data!\n"); + err = -EINVAL; +- goto no_board_data; ++ goto disable_clk; + } + imx_data->boarddata = *((struct esdhc_platform_data *) + host->mmc->parent->platform_data); +@@ -500,35 +1056,23 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) + + /* write_protect */ + if (boarddata->wp_type == ESDHC_WP_GPIO) { +- err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP"); ++ err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio); + if (err) { +- dev_warn(mmc_dev(host->mmc), +- "no write-protect pin available!\n"); +- boarddata->wp_gpio = -EINVAL; ++ dev_err(mmc_dev(host->mmc), ++ "failed to request write-protect gpio!\n"); ++ goto disable_clk; + } +- } else { +- boarddata->wp_gpio = -EINVAL; ++ host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; + } + + /* card_detect */ +- if (boarddata->cd_type != ESDHC_CD_GPIO) +- boarddata->cd_gpio = -EINVAL; +- + switch (boarddata->cd_type) { + case ESDHC_CD_GPIO: +- err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD"); ++ err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0); + if (err) { + dev_err(mmc_dev(host->mmc), +- "no card-detect pin available!\n"); +- goto no_card_detect_pin; +- } +- +- err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq, +- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, +- mmc_hostname(host->mmc), host); +- if (err) { +- dev_err(mmc_dev(host->mmc), "request irq error\n"); +- goto no_card_detect_irq; ++ "failed to request card-detect gpio!\n"); ++ goto disable_clk; + } + /* fall through */ + +@@ -538,88 +1082,141 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) + break; + + case ESDHC_CD_PERMANENT: +- host->mmc->caps = MMC_CAP_NONREMOVABLE; ++ host->mmc->caps |= MMC_CAP_NONREMOVABLE; + break; + + case ESDHC_CD_NONE: + break; + } + ++ switch (boarddata->max_bus_width) { ++ case 8: ++ host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA; ++ break; ++ case 4: ++ host->mmc->caps |= MMC_CAP_4_BIT_DATA; ++ break; ++ case 1: ++ default: ++ host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; ++ break; ++ } ++ ++ /* sdr50 and sdr104 needs work on 1.8v signal voltage */ ++ if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data)) { ++ imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, ++ ESDHC_PINCTRL_STATE_100MHZ); ++ imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, ++ ESDHC_PINCTRL_STATE_200MHZ); ++ if (IS_ERR(imx_data->pins_100mhz) || ++ IS_ERR(imx_data->pins_200mhz)) { ++ dev_warn(mmc_dev(host->mmc), ++ "could not get ultra high speed state, work on normal mode\n"); ++ /* fall back to not support uhs by specify no 1.8v quirk */ ++ host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; ++ } ++ } else { ++ host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; ++ } ++ + err = sdhci_add_host(host); + if (err) +- goto err_add_host; ++ goto disable_clk; ++ ++ pm_runtime_set_active(&pdev->dev); ++ pm_runtime_enable(&pdev->dev); ++ pm_runtime_set_autosuspend_delay(&pdev->dev, 50); ++ pm_runtime_use_autosuspend(&pdev->dev); ++ pm_suspend_ignore_children(&pdev->dev, 1); + + return 0; + +-err_add_host: +- if (gpio_is_valid(boarddata->cd_gpio)) +- free_irq(gpio_to_irq(boarddata->cd_gpio), host); +-no_card_detect_irq: +- if (gpio_is_valid(boarddata->cd_gpio)) +- gpio_free(boarddata->cd_gpio); +- if (gpio_is_valid(boarddata->wp_gpio)) +- gpio_free(boarddata->wp_gpio); +-no_card_detect_pin: +-no_board_data: +- clk_disable(pltfm_host->clk); +- clk_put(pltfm_host->clk); +-err_clk_get: +- kfree(imx_data); +-err_imx_data: ++disable_clk: ++ clk_disable_unprepare(imx_data->clk_per); ++ clk_disable_unprepare(imx_data->clk_ipg); ++ clk_disable_unprepare(imx_data->clk_ahb); ++free_sdhci: + sdhci_pltfm_free(pdev); + return err; + } + +-static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev) ++static int sdhci_esdhc_imx_remove(struct platform_device *pdev) + { + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host->priv; +- struct esdhc_platform_data *boarddata = &imx_data->boarddata; + int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); + + sdhci_remove_host(host, dead); + +- if (gpio_is_valid(boarddata->wp_gpio)) +- gpio_free(boarddata->wp_gpio); ++ pm_runtime_dont_use_autosuspend(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); + +- if (gpio_is_valid(boarddata->cd_gpio)) { +- free_irq(gpio_to_irq(boarddata->cd_gpio), host); +- gpio_free(boarddata->cd_gpio); ++ if (!IS_ENABLED(CONFIG_PM_RUNTIME)) { ++ clk_disable_unprepare(imx_data->clk_per); ++ clk_disable_unprepare(imx_data->clk_ipg); ++ clk_disable_unprepare(imx_data->clk_ahb); + } + +- clk_disable(pltfm_host->clk); +- clk_put(pltfm_host->clk); +- kfree(imx_data); +- + sdhci_pltfm_free(pdev); + + return 0; + } + ++#ifdef CONFIG_PM_RUNTIME ++static int sdhci_esdhc_runtime_suspend(struct device *dev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct pltfm_imx_data *imx_data = pltfm_host->priv; ++ int ret; ++ ++ ret = sdhci_runtime_suspend_host(host); ++ ++ if (!sdhci_sdio_irq_enabled(host)) { ++ clk_disable_unprepare(imx_data->clk_per); ++ clk_disable_unprepare(imx_data->clk_ipg); ++ } ++ clk_disable_unprepare(imx_data->clk_ahb); ++ ++ return ret; ++} ++ ++static int sdhci_esdhc_runtime_resume(struct device *dev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct pltfm_imx_data *imx_data = pltfm_host->priv; ++ ++ if (!sdhci_sdio_irq_enabled(host)) { ++ clk_prepare_enable(imx_data->clk_per); ++ clk_prepare_enable(imx_data->clk_ipg); ++ } ++ clk_prepare_enable(imx_data->clk_ahb); ++ ++ return sdhci_runtime_resume_host(host); ++} ++#endif ++ ++static const struct dev_pm_ops sdhci_esdhc_pmops = { ++ SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume) ++ SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend, ++ sdhci_esdhc_runtime_resume, NULL) ++}; ++ + static struct platform_driver sdhci_esdhc_imx_driver = { + .driver = { + .name = "sdhci-esdhc-imx", + .owner = THIS_MODULE, + .of_match_table = imx_esdhc_dt_ids, +- .pm = SDHCI_PLTFM_PMOPS, ++ .pm = &sdhci_esdhc_pmops, + }, + .id_table = imx_esdhc_devtype, + .probe = sdhci_esdhc_imx_probe, +- .remove = __devexit_p(sdhci_esdhc_imx_remove), ++ .remove = sdhci_esdhc_imx_remove, + }; + +-static int __init sdhci_esdhc_imx_init(void) +-{ +- return platform_driver_register(&sdhci_esdhc_imx_driver); +-} +-module_init(sdhci_esdhc_imx_init); +- +-static void __exit sdhci_esdhc_imx_exit(void) +-{ +- platform_driver_unregister(&sdhci_esdhc_imx_driver); +-} +-module_exit(sdhci_esdhc_imx_exit); ++module_platform_driver(sdhci_esdhc_imx_driver); + + MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC"); + MODULE_AUTHOR("Wolfram Sang "); +diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h +index 62ca03a..3497cfa 100644 +--- a/drivers/mmc/host/sdhci-esdhc.h ++++ b/drivers/mmc/host/sdhci-esdhc.h +@@ -20,10 +20,8 @@ + + #define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \ + SDHCI_QUIRK_NO_BUSY_IRQ | \ +- SDHCI_QUIRK_NONSTANDARD_CLOCK | \ + SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \ +- SDHCI_QUIRK_PIO_NEEDS_DELAY | \ +- SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) ++ SDHCI_QUIRK_PIO_NEEDS_DELAY) + + #define ESDHC_SYSTEM_CONTROL 0x2c + #define ESDHC_CLOCK_MASK 0x0000fff0 +@@ -36,46 +34,17 @@ + /* pltfm-specific */ + #define ESDHC_HOST_CONTROL_LE 0x20 + ++/* ++ * P2020 interpretation of the SDHCI_HOST_CONTROL register ++ */ ++#define ESDHC_CTRL_4BITBUS (0x1 << 1) ++#define ESDHC_CTRL_8BITBUS (0x2 << 1) ++#define ESDHC_CTRL_BUSWIDTH_MASK (0x3 << 1) ++ + /* OF-specific */ + #define ESDHC_DMA_SYSCTL 0x40c + #define ESDHC_DMA_SNOOP 0x00000040 + + #define ESDHC_HOST_CONTROL_RES 0x05 + +-static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) +-{ +- int pre_div = 2; +- int div = 1; +- u32 temp; +- +- if (clock == 0) +- goto out; +- +- temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); +- temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN +- | ESDHC_CLOCK_MASK); +- sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); +- +- while (host->max_clk / pre_div / 16 > clock && pre_div < 256) +- pre_div *= 2; +- +- while (host->max_clk / pre_div / div > clock && div < 16) +- div++; +- +- dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", +- clock, host->max_clk / pre_div / div); +- +- pre_div >>= 1; +- div--; +- +- temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); +- temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN +- | (div << ESDHC_DIVIDER_SHIFT) +- | (pre_div << ESDHC_PREDIV_SHIFT)); +- sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); +- mdelay(100); +-out: +- host->clock = clock; +-} +- + #endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */ +diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c +new file mode 100644 +index 0000000..40573a5 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-msm.c +@@ -0,0 +1,622 @@ ++/* ++ * drivers/mmc/host/sdhci-msm.c - Qualcomm SDHCI Platform driver ++ * ++ * Copyright (c) 2013-2014, 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 "sdhci-pltfm.h" ++ ++#define CORE_HC_MODE 0x78 ++#define HC_MODE_EN 0x1 ++#define CORE_POWER 0x0 ++#define CORE_SW_RST BIT(7) ++ ++#define MAX_PHASES 16 ++#define CORE_DLL_LOCK BIT(7) ++#define CORE_DLL_EN BIT(16) ++#define CORE_CDR_EN BIT(17) ++#define CORE_CK_OUT_EN BIT(18) ++#define CORE_CDR_EXT_EN BIT(19) ++#define CORE_DLL_PDN BIT(29) ++#define CORE_DLL_RST BIT(30) ++#define CORE_DLL_CONFIG 0x100 ++#define CORE_DLL_STATUS 0x108 ++ ++#define CORE_VENDOR_SPEC 0x10c ++#define CORE_CLK_PWRSAVE BIT(1) ++ ++#define CDR_SELEXT_SHIFT 20 ++#define CDR_SELEXT_MASK (0xf << CDR_SELEXT_SHIFT) ++#define CMUX_SHIFT_PHASE_SHIFT 24 ++#define CMUX_SHIFT_PHASE_MASK (7 << CMUX_SHIFT_PHASE_SHIFT) ++ ++static const u32 tuning_block_64[] = { ++ 0x00ff0fff, 0xccc3ccff, 0xffcc3cc3, 0xeffefffe, ++ 0xddffdfff, 0xfbfffbff, 0xff7fffbf, 0xefbdf777, ++ 0xf0fff0ff, 0x3cccfc0f, 0xcfcc33cc, 0xeeffefff, ++ 0xfdfffdff, 0xffbfffdf, 0xfff7ffbb, 0xde7b7ff7 ++}; ++ ++static const u32 tuning_block_128[] = { ++ 0xff00ffff, 0x0000ffff, 0xccccffff, 0xcccc33cc, ++ 0xcc3333cc, 0xffffcccc, 0xffffeeff, 0xffeeeeff, ++ 0xffddffff, 0xddddffff, 0xbbffffff, 0xbbffffff, ++ 0xffffffbb, 0xffffff77, 0x77ff7777, 0xffeeddbb, ++ 0x00ffffff, 0x00ffffff, 0xccffff00, 0xcc33cccc, ++ 0x3333cccc, 0xffcccccc, 0xffeeffff, 0xeeeeffff, ++ 0xddffffff, 0xddffffff, 0xffffffdd, 0xffffffbb, ++ 0xffffbbbb, 0xffff77ff, 0xff7777ff, 0xeeddbb77 ++}; ++ ++struct sdhci_msm_host { ++ struct platform_device *pdev; ++ void __iomem *core_mem; /* MSM SDCC mapped address */ ++ struct clk *clk; /* main SD/MMC bus clock */ ++ struct clk *pclk; /* SDHC peripheral bus clock */ ++ struct clk *bus_clk; /* SDHC bus voter clock */ ++ struct mmc_host *mmc; ++ struct sdhci_pltfm_data sdhci_msm_pdata; ++}; ++ ++/* Platform specific tuning */ ++static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll) ++{ ++ u32 wait_cnt = 50; ++ u8 ck_out_en; ++ struct mmc_host *mmc = host->mmc; ++ ++ /* Poll for CK_OUT_EN bit. max. poll time = 50us */ ++ ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) & ++ CORE_CK_OUT_EN); ++ ++ while (ck_out_en != poll) { ++ if (--wait_cnt == 0) { ++ dev_err(mmc_dev(mmc), "%s: CK_OUT_EN bit is not %d\n", ++ mmc_hostname(mmc), poll); ++ return -ETIMEDOUT; ++ } ++ udelay(1); ++ ++ ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) & ++ CORE_CK_OUT_EN); ++ } ++ ++ return 0; ++} ++ ++static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase) ++{ ++ int rc; ++ static const u8 grey_coded_phase_table[] = { ++ 0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4, ++ 0xc, 0xd, 0xf, 0xe, 0xa, 0xb, 0x9, 0x8 ++ }; ++ unsigned long flags; ++ u32 config; ++ struct mmc_host *mmc = host->mmc; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); ++ config &= ~(CORE_CDR_EN | CORE_CK_OUT_EN); ++ config |= (CORE_CDR_EXT_EN | CORE_DLL_EN); ++ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); ++ ++ /* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '0' */ ++ rc = msm_dll_poll_ck_out_en(host, 0); ++ if (rc) ++ goto err_out; ++ ++ /* ++ * Write the selected DLL clock output phase (0 ... 15) ++ * to CDR_SELEXT bit field of DLL_CONFIG register. ++ */ ++ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); ++ config &= ~CDR_SELEXT_MASK; ++ config |= grey_coded_phase_table[phase] << CDR_SELEXT_SHIFT; ++ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); ++ ++ /* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */ ++ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) ++ | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG); ++ ++ /* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */ ++ rc = msm_dll_poll_ck_out_en(host, 1); ++ if (rc) ++ goto err_out; ++ ++ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); ++ config |= CORE_CDR_EN; ++ config &= ~CORE_CDR_EXT_EN; ++ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); ++ goto out; ++ ++err_out: ++ dev_err(mmc_dev(mmc), "%s: Failed to set DLL phase: %d\n", ++ mmc_hostname(mmc), phase); ++out: ++ spin_unlock_irqrestore(&host->lock, flags); ++ return rc; ++} ++ ++/* ++ * Find out the greatest range of consecuitive selected ++ * DLL clock output phases that can be used as sampling ++ * setting for SD3.0 UHS-I card read operation (in SDR104 ++ * timing mode) or for eMMC4.5 card read operation (in HS200 ++ * timing mode). ++ * Select the 3/4 of the range and configure the DLL with the ++ * selected DLL clock output phase. ++ */ ++ ++static int msm_find_most_appropriate_phase(struct sdhci_host *host, ++ u8 *phase_table, u8 total_phases) ++{ ++ int ret; ++ u8 ranges[MAX_PHASES][MAX_PHASES] = { {0}, {0} }; ++ u8 phases_per_row[MAX_PHASES] = { 0 }; ++ int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0; ++ int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0; ++ bool phase_0_found = false, phase_15_found = false; ++ struct mmc_host *mmc = host->mmc; ++ ++ if (!total_phases || (total_phases > MAX_PHASES)) { ++ dev_err(mmc_dev(mmc), "%s: Invalid argument: total_phases=%d\n", ++ mmc_hostname(mmc), total_phases); ++ return -EINVAL; ++ } ++ ++ for (cnt = 0; cnt < total_phases; cnt++) { ++ ranges[row_index][col_index] = phase_table[cnt]; ++ phases_per_row[row_index] += 1; ++ col_index++; ++ ++ if ((cnt + 1) == total_phases) { ++ continue; ++ /* check if next phase in phase_table is consecutive or not */ ++ } else if ((phase_table[cnt] + 1) != phase_table[cnt + 1]) { ++ row_index++; ++ col_index = 0; ++ } ++ } ++ ++ if (row_index >= MAX_PHASES) ++ return -EINVAL; ++ ++ /* Check if phase-0 is present in first valid window? */ ++ if (!ranges[0][0]) { ++ phase_0_found = true; ++ phase_0_raw_index = 0; ++ /* Check if cycle exist between 2 valid windows */ ++ for (cnt = 1; cnt <= row_index; cnt++) { ++ if (phases_per_row[cnt]) { ++ for (i = 0; i < phases_per_row[cnt]; i++) { ++ if (ranges[cnt][i] == 15) { ++ phase_15_found = true; ++ phase_15_raw_index = cnt; ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ /* If 2 valid windows form cycle then merge them as single window */ ++ if (phase_0_found && phase_15_found) { ++ /* number of phases in raw where phase 0 is present */ ++ u8 phases_0 = phases_per_row[phase_0_raw_index]; ++ /* number of phases in raw where phase 15 is present */ ++ u8 phases_15 = phases_per_row[phase_15_raw_index]; ++ ++ if (phases_0 + phases_15 >= MAX_PHASES) ++ /* ++ * If there are more than 1 phase windows then total ++ * number of phases in both the windows should not be ++ * more than or equal to MAX_PHASES. ++ */ ++ return -EINVAL; ++ ++ /* Merge 2 cyclic windows */ ++ i = phases_15; ++ for (cnt = 0; cnt < phases_0; cnt++) { ++ ranges[phase_15_raw_index][i] = ++ ranges[phase_0_raw_index][cnt]; ++ if (++i >= MAX_PHASES) ++ break; ++ } ++ ++ phases_per_row[phase_0_raw_index] = 0; ++ phases_per_row[phase_15_raw_index] = phases_15 + phases_0; ++ } ++ ++ for (cnt = 0; cnt <= row_index; cnt++) { ++ if (phases_per_row[cnt] > curr_max) { ++ curr_max = phases_per_row[cnt]; ++ selected_row_index = cnt; ++ } ++ } ++ ++ i = (curr_max * 3) / 4; ++ if (i) ++ i--; ++ ++ ret = ranges[selected_row_index][i]; ++ ++ if (ret >= MAX_PHASES) { ++ ret = -EINVAL; ++ dev_err(mmc_dev(mmc), "%s: Invalid phase selected=%d\n", ++ mmc_hostname(mmc), ret); ++ } ++ ++ return ret; ++} ++ ++static inline void msm_cm_dll_set_freq(struct sdhci_host *host) ++{ ++ u32 mclk_freq = 0, config; ++ ++ /* Program the MCLK value to MCLK_FREQ bit field */ ++ if (host->clock <= 112000000) ++ mclk_freq = 0; ++ else if (host->clock <= 125000000) ++ mclk_freq = 1; ++ else if (host->clock <= 137000000) ++ mclk_freq = 2; ++ else if (host->clock <= 150000000) ++ mclk_freq = 3; ++ else if (host->clock <= 162000000) ++ mclk_freq = 4; ++ else if (host->clock <= 175000000) ++ mclk_freq = 5; ++ else if (host->clock <= 187000000) ++ mclk_freq = 6; ++ else if (host->clock <= 200000000) ++ mclk_freq = 7; ++ ++ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); ++ config &= ~CMUX_SHIFT_PHASE_MASK; ++ config |= mclk_freq << CMUX_SHIFT_PHASE_SHIFT; ++ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); ++} ++ ++/* Initialize the DLL (Programmable Delay Line) */ ++static int msm_init_cm_dll(struct sdhci_host *host) ++{ ++ struct mmc_host *mmc = host->mmc; ++ int wait_cnt = 50; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ /* ++ * Make sure that clock is always enabled when DLL ++ * tuning is in progress. Keeping PWRSAVE ON may ++ * turn off the clock. ++ */ ++ writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) ++ & ~CORE_CLK_PWRSAVE), host->ioaddr + CORE_VENDOR_SPEC); ++ ++ /* Write 1 to DLL_RST bit of DLL_CONFIG register */ ++ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) ++ | CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG); ++ ++ /* Write 1 to DLL_PDN bit of DLL_CONFIG register */ ++ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) ++ | CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG); ++ msm_cm_dll_set_freq(host); ++ ++ /* Write 0 to DLL_RST bit of DLL_CONFIG register */ ++ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) ++ & ~CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG); ++ ++ /* Write 0 to DLL_PDN bit of DLL_CONFIG register */ ++ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) ++ & ~CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG); ++ ++ /* Set DLL_EN bit to 1. */ ++ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) ++ | CORE_DLL_EN), host->ioaddr + CORE_DLL_CONFIG); ++ ++ /* Set CK_OUT_EN bit to 1. */ ++ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) ++ | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG); ++ ++ /* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */ ++ while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) & ++ CORE_DLL_LOCK)) { ++ /* max. wait for 50us sec for LOCK bit to be set */ ++ if (--wait_cnt == 0) { ++ dev_err(mmc_dev(mmc), "%s: DLL failed to LOCK\n", ++ mmc_hostname(mmc)); ++ spin_unlock_irqrestore(&host->lock, flags); ++ return -ETIMEDOUT; ++ } ++ udelay(1); ++ } ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++ return 0; ++} ++ ++static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode) ++{ ++ int tuning_seq_cnt = 3; ++ u8 phase, *data_buf, tuned_phases[16], tuned_phase_cnt = 0; ++ const u32 *tuning_block_pattern = tuning_block_64; ++ int size = sizeof(tuning_block_64); /* Pattern size in bytes */ ++ int rc; ++ struct mmc_host *mmc = host->mmc; ++ struct mmc_ios ios = host->mmc->ios; ++ ++ /* ++ * Tuning is required for SDR104, HS200 and HS400 cards and ++ * if clock frequency is greater than 100MHz in these modes. ++ */ ++ if (host->clock <= 100 * 1000 * 1000 || ++ !((ios.timing == MMC_TIMING_MMC_HS200) || ++ (ios.timing == MMC_TIMING_UHS_SDR104))) ++ return 0; ++ ++ if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) && ++ (mmc->ios.bus_width == MMC_BUS_WIDTH_8)) { ++ tuning_block_pattern = tuning_block_128; ++ size = sizeof(tuning_block_128); ++ } ++ ++ data_buf = kmalloc(size, GFP_KERNEL); ++ if (!data_buf) ++ return -ENOMEM; ++ ++retry: ++ /* First of all reset the tuning block */ ++ rc = msm_init_cm_dll(host); ++ if (rc) ++ goto out; ++ ++ phase = 0; ++ do { ++ struct mmc_command cmd = { 0 }; ++ struct mmc_data data = { 0 }; ++ struct mmc_request mrq = { ++ .cmd = &cmd, ++ .data = &data ++ }; ++ struct scatterlist sg; ++ ++ /* Set the phase in delay line hw block */ ++ rc = msm_config_cm_dll_phase(host, phase); ++ if (rc) ++ goto out; ++ ++ cmd.opcode = opcode; ++ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; ++ ++ data.blksz = size; ++ data.blocks = 1; ++ data.flags = MMC_DATA_READ; ++ data.timeout_ns = NSEC_PER_SEC; /* 1 second */ ++ ++ data.sg = &sg; ++ data.sg_len = 1; ++ sg_init_one(&sg, data_buf, size); ++ memset(data_buf, 0, size); ++ mmc_wait_for_req(mmc, &mrq); ++ ++ if (!cmd.error && !data.error && ++ !memcmp(data_buf, tuning_block_pattern, size)) { ++ /* Tuning is successful at this tuning point */ ++ tuned_phases[tuned_phase_cnt++] = phase; ++ dev_dbg(mmc_dev(mmc), "%s: Found good phase = %d\n", ++ mmc_hostname(mmc), phase); ++ } ++ } while (++phase < ARRAY_SIZE(tuned_phases)); ++ ++ if (tuned_phase_cnt) { ++ rc = msm_find_most_appropriate_phase(host, tuned_phases, ++ tuned_phase_cnt); ++ if (rc < 0) ++ goto out; ++ else ++ phase = rc; ++ ++ /* ++ * Finally set the selected phase in delay ++ * line hw block. ++ */ ++ rc = msm_config_cm_dll_phase(host, phase); ++ if (rc) ++ goto out; ++ dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n", ++ mmc_hostname(mmc), phase); ++ } else { ++ if (--tuning_seq_cnt) ++ goto retry; ++ /* Tuning failed */ ++ dev_dbg(mmc_dev(mmc), "%s: No tuning point found\n", ++ mmc_hostname(mmc)); ++ rc = -EIO; ++ } ++ ++out: ++ kfree(data_buf); ++ return rc; ++} ++ ++static const struct of_device_id sdhci_msm_dt_match[] = { ++ { .compatible = "qcom,sdhci-msm-v4" }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match); ++ ++static struct sdhci_ops sdhci_msm_ops = { ++ .platform_execute_tuning = sdhci_msm_execute_tuning, ++ .reset = sdhci_reset, ++ .set_clock = sdhci_set_clock, ++ .set_bus_width = sdhci_set_bus_width, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++}; ++ ++static int sdhci_msm_probe(struct platform_device *pdev) ++{ ++ struct sdhci_host *host; ++ struct sdhci_pltfm_host *pltfm_host; ++ struct sdhci_msm_host *msm_host; ++ struct resource *core_memres; ++ int ret; ++ u16 host_version; ++ ++ msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL); ++ if (!msm_host) ++ return -ENOMEM; ++ ++ msm_host->sdhci_msm_pdata.ops = &sdhci_msm_ops; ++ host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata, 0); ++ if (IS_ERR(host)) ++ return PTR_ERR(host); ++ ++ pltfm_host = sdhci_priv(host); ++ pltfm_host->priv = msm_host; ++ msm_host->mmc = host->mmc; ++ msm_host->pdev = pdev; ++ ++ ret = mmc_of_parse(host->mmc); ++ if (ret) ++ goto pltfm_free; ++ ++ sdhci_get_of_property(pdev); ++ ++ /* Setup SDCC bus voter clock. */ ++ msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus"); ++ if (!IS_ERR(msm_host->bus_clk)) { ++ /* Vote for max. clk rate for max. performance */ ++ ret = clk_set_rate(msm_host->bus_clk, INT_MAX); ++ if (ret) ++ goto pltfm_free; ++ ret = clk_prepare_enable(msm_host->bus_clk); ++ if (ret) ++ goto pltfm_free; ++ } ++ ++ /* Setup main peripheral bus clock */ ++ msm_host->pclk = devm_clk_get(&pdev->dev, "iface"); ++ if (IS_ERR(msm_host->pclk)) { ++ ret = PTR_ERR(msm_host->pclk); ++ dev_err(&pdev->dev, "Perpheral clk setup failed (%d)\n", ret); ++ goto bus_clk_disable; ++ } ++ ++ ret = clk_prepare_enable(msm_host->pclk); ++ if (ret) ++ goto bus_clk_disable; ++ ++ /* Setup SDC MMC clock */ ++ msm_host->clk = devm_clk_get(&pdev->dev, "core"); ++ if (IS_ERR(msm_host->clk)) { ++ ret = PTR_ERR(msm_host->clk); ++ dev_err(&pdev->dev, "SDC MMC clk setup failed (%d)\n", ret); ++ goto pclk_disable; ++ } ++ ++ ret = clk_prepare_enable(msm_host->clk); ++ if (ret) ++ goto pclk_disable; ++ ++ core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ msm_host->core_mem = devm_ioremap_resource(&pdev->dev, core_memres); ++ ++ if (IS_ERR(msm_host->core_mem)) { ++ dev_err(&pdev->dev, "Failed to remap registers\n"); ++ ret = PTR_ERR(msm_host->core_mem); ++ goto clk_disable; ++ } ++ ++ /* Reset the core and Enable SDHC mode */ ++ writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) | ++ CORE_SW_RST, msm_host->core_mem + CORE_POWER); ++ ++ /* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */ ++ usleep_range(1000, 5000); ++ if (readl(msm_host->core_mem + CORE_POWER) & CORE_SW_RST) { ++ dev_err(&pdev->dev, "Stuck in reset\n"); ++ ret = -ETIMEDOUT; ++ goto clk_disable; ++ } ++ ++ /* Set HC_MODE_EN bit in HC_MODE register */ ++ writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE)); ++ ++ host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; ++ host->quirks |= SDHCI_QUIRK_SINGLE_POWER_WRITE; ++ ++ host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION)); ++ dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n", ++ host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >> ++ SDHCI_VENDOR_VER_SHIFT)); ++ ++ ret = sdhci_add_host(host); ++ if (ret) ++ goto clk_disable; ++ ++ return 0; ++ ++clk_disable: ++ clk_disable_unprepare(msm_host->clk); ++pclk_disable: ++ clk_disable_unprepare(msm_host->pclk); ++bus_clk_disable: ++ if (!IS_ERR(msm_host->bus_clk)) ++ clk_disable_unprepare(msm_host->bus_clk); ++pltfm_free: ++ sdhci_pltfm_free(pdev); ++ return ret; ++} ++ ++static int sdhci_msm_remove(struct platform_device *pdev) ++{ ++ struct sdhci_host *host = platform_get_drvdata(pdev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_msm_host *msm_host = pltfm_host->priv; ++ int dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) == ++ 0xffffffff); ++ ++ sdhci_remove_host(host, dead); ++ sdhci_pltfm_free(pdev); ++ clk_disable_unprepare(msm_host->clk); ++ clk_disable_unprepare(msm_host->pclk); ++ if (!IS_ERR(msm_host->bus_clk)) ++ clk_disable_unprepare(msm_host->bus_clk); ++ return 0; ++} ++ ++static struct platform_driver sdhci_msm_driver = { ++ .probe = sdhci_msm_probe, ++ .remove = sdhci_msm_remove, ++ .driver = { ++ .name = "sdhci_msm", ++ .owner = THIS_MODULE, ++ .of_match_table = sdhci_msm_dt_match, ++ }, ++}; ++ ++module_platform_driver(sdhci_msm_driver); ++ ++MODULE_DESCRIPTION("Qualcomm Secure Digital Host Controller Interface driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c +new file mode 100644 +index 0000000..5bd1092 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-of-arasan.c +@@ -0,0 +1,228 @@ ++/* ++ * Arasan Secure Digital Host Controller Interface. ++ * Copyright (C) 2011 - 2012 Michal Simek ++ * Copyright (c) 2012 Wind River Systems, Inc. ++ * Copyright (C) 2013 Pengutronix e.K. ++ * Copyright (C) 2013 Xilinx Inc. ++ * ++ * Based on sdhci-of-esdhc.c ++ * ++ * Copyright (c) 2007 Freescale Semiconductor, Inc. ++ * Copyright (c) 2009 MontaVista Software, Inc. ++ * ++ * Authors: Xiaobo Xie ++ * Anton Vorontsov ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the 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 "sdhci-pltfm.h" ++ ++#define SDHCI_ARASAN_CLK_CTRL_OFFSET 0x2c ++ ++#define CLK_CTRL_TIMEOUT_SHIFT 16 ++#define CLK_CTRL_TIMEOUT_MASK (0xf << CLK_CTRL_TIMEOUT_SHIFT) ++#define CLK_CTRL_TIMEOUT_MIN_EXP 13 ++ ++/** ++ * struct sdhci_arasan_data ++ * @clk_ahb: Pointer to the AHB clock ++ */ ++struct sdhci_arasan_data { ++ struct clk *clk_ahb; ++}; ++ ++static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host) ++{ ++ u32 div; ++ unsigned long freq; ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ ++ div = readl(host->ioaddr + SDHCI_ARASAN_CLK_CTRL_OFFSET); ++ div = (div & CLK_CTRL_TIMEOUT_MASK) >> CLK_CTRL_TIMEOUT_SHIFT; ++ ++ freq = clk_get_rate(pltfm_host->clk); ++ freq /= 1 << (CLK_CTRL_TIMEOUT_MIN_EXP + div); ++ ++ return freq; ++} ++ ++static struct sdhci_ops sdhci_arasan_ops = { ++ .set_clock = sdhci_set_clock, ++ .get_max_clock = sdhci_pltfm_clk_get_max_clock, ++ .get_timeout_clock = sdhci_arasan_get_timeout_clock, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++}; ++ ++static struct sdhci_pltfm_data sdhci_arasan_pdata = { ++ .ops = &sdhci_arasan_ops, ++}; ++ ++#ifdef CONFIG_PM_SLEEP ++/** ++ * sdhci_arasan_suspend - Suspend method for the driver ++ * @dev: Address of the device structure ++ * Returns 0 on success and error value on error ++ * ++ * Put the device in a low power state. ++ */ ++static int sdhci_arasan_suspend(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct sdhci_host *host = platform_get_drvdata(pdev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv; ++ int ret; ++ ++ ret = sdhci_suspend_host(host); ++ if (ret) ++ return ret; ++ ++ clk_disable(pltfm_host->clk); ++ clk_disable(sdhci_arasan->clk_ahb); ++ ++ return 0; ++} ++ ++/** ++ * sdhci_arasan_resume - Resume method for the driver ++ * @dev: Address of the device structure ++ * Returns 0 on success and error value on error ++ * ++ * Resume operation after suspend ++ */ ++static int sdhci_arasan_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct sdhci_host *host = platform_get_drvdata(pdev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv; ++ int ret; ++ ++ ret = clk_enable(sdhci_arasan->clk_ahb); ++ if (ret) { ++ dev_err(dev, "Cannot enable AHB clock.\n"); ++ return ret; ++ } ++ ++ ret = clk_enable(pltfm_host->clk); ++ if (ret) { ++ dev_err(dev, "Cannot enable SD clock.\n"); ++ clk_disable(sdhci_arasan->clk_ahb); ++ return ret; ++ } ++ ++ return sdhci_resume_host(host); ++} ++#endif /* ! CONFIG_PM_SLEEP */ ++ ++static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend, ++ sdhci_arasan_resume); ++ ++static int sdhci_arasan_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct clk *clk_xin; ++ struct sdhci_host *host; ++ struct sdhci_pltfm_host *pltfm_host; ++ struct sdhci_arasan_data *sdhci_arasan; ++ ++ sdhci_arasan = devm_kzalloc(&pdev->dev, sizeof(*sdhci_arasan), ++ GFP_KERNEL); ++ if (!sdhci_arasan) ++ return -ENOMEM; ++ ++ sdhci_arasan->clk_ahb = devm_clk_get(&pdev->dev, "clk_ahb"); ++ if (IS_ERR(sdhci_arasan->clk_ahb)) { ++ dev_err(&pdev->dev, "clk_ahb clock not found.\n"); ++ return PTR_ERR(sdhci_arasan->clk_ahb); ++ } ++ ++ clk_xin = devm_clk_get(&pdev->dev, "clk_xin"); ++ if (IS_ERR(clk_xin)) { ++ dev_err(&pdev->dev, "clk_xin clock not found.\n"); ++ return PTR_ERR(clk_xin); ++ } ++ ++ ret = clk_prepare_enable(sdhci_arasan->clk_ahb); ++ if (ret) { ++ dev_err(&pdev->dev, "Unable to enable AHB clock.\n"); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(clk_xin); ++ if (ret) { ++ dev_err(&pdev->dev, "Unable to enable SD clock.\n"); ++ goto clk_dis_ahb; ++ } ++ ++ host = sdhci_pltfm_init(pdev, &sdhci_arasan_pdata, 0); ++ if (IS_ERR(host)) { ++ ret = PTR_ERR(host); ++ dev_err(&pdev->dev, "platform init failed (%u)\n", ret); ++ goto clk_disable_all; ++ } ++ ++ sdhci_get_of_property(pdev); ++ pltfm_host = sdhci_priv(host); ++ pltfm_host->priv = sdhci_arasan; ++ pltfm_host->clk = clk_xin; ++ ++ ret = sdhci_add_host(host); ++ if (ret) { ++ dev_err(&pdev->dev, "platform register failed (%u)\n", ret); ++ goto err_pltfm_free; ++ } ++ ++ return 0; ++ ++err_pltfm_free: ++ sdhci_pltfm_free(pdev); ++clk_disable_all: ++ clk_disable_unprepare(clk_xin); ++clk_dis_ahb: ++ clk_disable_unprepare(sdhci_arasan->clk_ahb); ++ ++ return ret; ++} ++ ++static int sdhci_arasan_remove(struct platform_device *pdev) ++{ ++ struct sdhci_host *host = platform_get_drvdata(pdev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv; ++ ++ clk_disable_unprepare(pltfm_host->clk); ++ clk_disable_unprepare(sdhci_arasan->clk_ahb); ++ ++ return sdhci_pltfm_unregister(pdev); ++} ++ ++static const struct of_device_id sdhci_arasan_of_match[] = { ++ { .compatible = "arasan,sdhci-8.9a" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, sdhci_arasan_of_match); ++ ++static struct platform_driver sdhci_arasan_driver = { ++ .driver = { ++ .name = "sdhci-arasan", ++ .owner = THIS_MODULE, ++ .of_match_table = sdhci_arasan_of_match, ++ .pm = &sdhci_arasan_dev_pm_ops, ++ }, ++ .probe = sdhci_arasan_probe, ++ .remove = sdhci_arasan_remove, ++}; ++ ++module_platform_driver(sdhci_arasan_driver); ++ ++MODULE_DESCRIPTION("Driver for the Arasan SDHCI Controller"); ++MODULE_AUTHOR("Soeren Brinkmann "); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c +new file mode 100644 +index 0000000..74de0b5 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-of-core.c +@@ -0,0 +1,274 @@ ++/* ++ * OpenFirmware bindings for Secure Digital Host Controller Interface. ++ * ++ * Copyright (c) 2007, 2011 Freescale Semiconductor, Inc. ++ * Copyright (c) 2009 MontaVista Software, Inc. ++ * ++ * Authors: Xiaobo Xie ++ * Anton Vorontsov ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the 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 ++#ifdef CONFIG_PPC ++#include ++#endif ++#include "sdhci-of.h" ++#include "sdhci.h" ++ ++#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER ++ ++/* ++ * These accessors are designed for big endian hosts doing I/O to ++ * little endian controllers incorporating a 32-bit hardware byte swapper. ++ */ ++ ++u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg) ++{ ++ return in_be32(host->ioaddr + reg); ++} ++ ++u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg) ++{ ++ return in_be16(host->ioaddr + (reg ^ 0x2)); ++} ++ ++u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg) ++{ ++ return in_8(host->ioaddr + (reg ^ 0x3)); ++} ++ ++void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg) ++{ ++ out_be32(host->ioaddr + reg, val); ++} ++ ++void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg) ++{ ++ struct sdhci_of_host *of_host = sdhci_priv(host); ++ int base = reg & ~0x3; ++ int shift = (reg & 0x2) * 8; ++ ++ switch (reg) { ++ case SDHCI_TRANSFER_MODE: ++ /* ++ * Postpone this write, we must do it together with a ++ * command write that is down below. ++ */ ++ of_host->xfer_mode_shadow = val; ++ return; ++ case SDHCI_COMMAND: ++ sdhci_be32bs_writel(host, val << 16 | of_host->xfer_mode_shadow, ++ SDHCI_TRANSFER_MODE); ++ return; ++ } ++ clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift); ++} ++ ++void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg) ++{ ++ int base = reg & ~0x3; ++ int shift = (reg & 0x3) * 8; ++ ++ clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift); ++} ++#endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */ ++ ++#ifdef CONFIG_PM ++ ++static int sdhci_of_suspend(struct platform_device *ofdev, pm_message_t state) ++{ ++ struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); ++ ++ return mmc_suspend_host(host->mmc); ++} ++ ++static int sdhci_of_resume(struct platform_device *ofdev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); ++ ++ return mmc_resume_host(host->mmc); ++} ++ ++#else ++ ++#define sdhci_of_suspend NULL ++#define sdhci_of_resume NULL ++ ++#endif ++ ++static bool __devinit sdhci_of_wp_inverted(struct device_node *np) ++{ ++ if (of_get_property(np, "sdhci,wp-inverted", NULL)) ++ return true; ++ ++ /* Old device trees don't have the wp-inverted property. */ ++#ifdef CONFIG_PPC ++ return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds); ++#else ++ return false; ++#endif ++} ++ ++static const struct of_device_id sdhci_of_match[]; ++static int __devinit sdhci_of_probe(struct platform_device *ofdev) ++{ ++ const struct of_device_id *match; ++ struct device_node *np = ofdev->dev.of_node; ++ struct sdhci_of_data *sdhci_of_data; ++ struct sdhci_host *host; ++ struct sdhci_of_host *of_host; ++ const __be32 *clk; ++ int size; ++ int ret; ++ ++ match = of_match_device(sdhci_of_match, &ofdev->dev); ++ if (!match) ++ return -EINVAL; ++ sdhci_of_data = match->data; ++ ++ if (!of_device_is_available(np)) ++ return -ENODEV; ++ ++ host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host)); ++ if (IS_ERR(host)) ++ return -ENOMEM; ++ ++ of_host = sdhci_priv(host); ++ dev_set_drvdata(&ofdev->dev, host); ++ ++ host->ioaddr = of_iomap(np, 0); ++ if (!host->ioaddr) { ++ ret = -ENOMEM; ++ goto err_addr_map; ++ } ++ ++ host->irq = irq_of_parse_and_map(np, 0); ++ if (!host->irq) { ++ ret = -EINVAL; ++ goto err_no_irq; ++ } ++ ++ host->hw_name = dev_name(&ofdev->dev); ++ if (sdhci_of_data) { ++ host->quirks = sdhci_of_data->quirks; ++ host->ops = &sdhci_of_data->ops; ++ } ++ ++ if (of_get_property(np, "sdhci,auto-cmd12", NULL)) ++ host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; ++ ++ ++ if (of_get_property(np, "sdhci,1-bit-only", NULL)) ++ host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; ++ ++ if (sdhci_of_wp_inverted(np)) ++ host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; ++ ++ if (of_device_is_compatible(np, "fsl,esdhc")) ++ host->quirks |= SDHCI_QUIRK_QORIQ_PROCTL_WEIRD; ++ ++ if (of_device_is_compatible(np, "fsl,p4080-esdhc")) ++ host->quirks |= SDHCI_QUIRK_QORIQ_HOSTCAPBLT_ONLY_VS33; ++ ++ if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc")) ++ host->quirks |= SDHCI_QUIRK_BROKEN_DMA; ++ ++ if (of_device_is_compatible(np, "fsl,p2020-esdhc") || ++ of_device_is_compatible(np, "fsl,p1010-esdhc") || ++ of_device_is_compatible(np, "fsl,t4240-esdhc") || ++ of_device_is_compatible(np, "fsl,mpc8536-esdhc")) ++ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; ++ ++ if (of_device_is_compatible(np, "fsl,t4240-esdhc")) { ++ host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; ++ host->quirks |= SDHCI_QUIRK_QORIQ_CIRCUIT_SUPPORT_VS33; ++ host->quirks |= SDHCI_QUIRK_LONG_TIME_CMD_COMPLETE_IRQ; ++ } ++ ++ clk = of_get_property(np, "clock-frequency", &size); ++ if (clk && size == sizeof(*clk) && *clk) ++ of_host->clock = be32_to_cpup(clk); ++ ++ ret = sdhci_add_host(host); ++ if (ret) ++ goto err_add_host; ++ ++ return 0; ++ ++err_add_host: ++ irq_dispose_mapping(host->irq); ++err_no_irq: ++ iounmap(host->ioaddr); ++err_addr_map: ++ sdhci_free_host(host); ++ return ret; ++} ++ ++static int __devexit sdhci_of_remove(struct platform_device *ofdev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); ++ ++ sdhci_remove_host(host, 0); ++ sdhci_free_host(host); ++ irq_dispose_mapping(host->irq); ++ iounmap(host->ioaddr); ++ return 0; ++} ++ ++static const struct of_device_id sdhci_of_match[] = { ++#ifdef CONFIG_MMC_SDHCI_OF_ESDHC ++ { .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc, }, ++ { .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc, }, ++ { .compatible = "fsl,esdhc", .data = &sdhci_esdhc, }, ++#endif ++#ifdef CONFIG_MMC_SDHCI_OF_HLWD ++ { .compatible = "nintendo,hollywood-sdhci", .data = &sdhci_hlwd, }, ++#endif ++ { .compatible = "generic-sdhci", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, sdhci_of_match); ++ ++static struct platform_driver sdhci_of_driver = { ++ .driver = { ++ .name = "sdhci-of", ++ .owner = THIS_MODULE, ++ .of_match_table = sdhci_of_match, ++ }, ++ .probe = sdhci_of_probe, ++ .remove = __devexit_p(sdhci_of_remove), ++ .suspend = sdhci_of_suspend, ++ .resume = sdhci_of_resume, ++}; ++ ++static int __init sdhci_of_init(void) ++{ ++ return platform_driver_register(&sdhci_of_driver); ++} ++module_init(sdhci_of_init); ++ ++static void __exit sdhci_of_exit(void) ++{ ++ platform_driver_unregister(&sdhci_of_driver); ++} ++module_exit(sdhci_of_exit); ++ ++MODULE_DESCRIPTION("Secure Digital Host Controller Interface OF driver"); ++MODULE_AUTHOR("Xiaobo Xie , " ++ "Anton Vorontsov "); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c +index 01e5f62..fdc2732 100644 +--- a/drivers/mmc/host/sdhci-of-esdhc.c ++++ b/drivers/mmc/host/sdhci-of-esdhc.c +@@ -1,7 +1,7 @@ + /* + * Freescale eSDHC controller driver. + * +- * Copyright (c) 2007, 2010 Freescale Semiconductor, Inc. ++ * Copyright (c) 2007, 2010, 2012 Freescale Semiconductor, Inc. + * Copyright (c) 2009 MontaVista Software, Inc. + * + * Authors: Xiaobo Xie +@@ -13,13 +13,42 @@ + * your option) any later version. + */ + ++#include + #include ++#include + #include + #include + #include + #include "sdhci-pltfm.h" + #include "sdhci-esdhc.h" + ++#define VENDOR_V_22 0x12 ++#define VENDOR_V_23 0x13 ++static u32 esdhc_readl(struct sdhci_host *host, int reg) ++{ ++ u32 ret; ++ ++ ret = in_be32(host->ioaddr + reg); ++ /* ++ * The bit of ADMA flag in eSDHC is not compatible with standard ++ * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is ++ * supported by eSDHC. ++ * And for many FSL eSDHC controller, the reset value of field ++ * SDHCI_CAN_DO_ADMA1 is one, but some of them can't support ADMA, ++ * only these vendor version is greater than 2.2/0x12 support ADMA. ++ * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the ++ * the verdor version number, oxFE is SDHCI_HOST_VERSION. ++ */ ++ if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) { ++ u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); ++ tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; ++ if (tmp > VENDOR_V_22) ++ ret |= SDHCI_CAN_DO_ADMA2; ++ } ++ ++ return ret; ++} ++ + static u16 esdhc_readw(struct sdhci_host *host, int reg) + { + u16 ret; +@@ -38,9 +67,38 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg) + int base = reg & ~0x3; + int shift = (reg & 0x3) * 8; + u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff; ++ ++ /* ++ * "DMA select" locates at offset 0x28 in SD specification, but on ++ * P5020 or P3041, it locates at 0x29. ++ */ ++ if (reg == SDHCI_HOST_CONTROL) { ++ u32 dma_bits; ++ ++ dma_bits = in_be32(host->ioaddr + reg); ++ /* DMA select is 22,23 bits in Protocol Control Register */ ++ dma_bits = (dma_bits >> 5) & SDHCI_CTRL_DMA_MASK; ++ ++ /* fixup the result */ ++ ret &= ~SDHCI_CTRL_DMA_MASK; ++ ret |= dma_bits; ++ } ++ + return ret; + } + ++static void esdhc_writel(struct sdhci_host *host, u32 val, int reg) ++{ ++ /* ++ * Enable IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE] ++ * when SYSCTL[RSTD]) is set for some special operations. ++ * No any impact other operation. ++ */ ++ if (reg == SDHCI_INT_ENABLE) ++ val |= SDHCI_INT_BLK_GAP; ++ sdhci_be32bs_writel(host, val, reg); ++} ++ + static void esdhc_writew(struct sdhci_host *host, u16 val, int reg) + { + if (reg == SDHCI_BLOCK_SIZE) { +@@ -56,12 +114,69 @@ static void esdhc_writew(struct sdhci_host *host, u16 val, int reg) + + static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) + { ++ /* ++ * "DMA select" location is offset 0x28 in SD specification, but on ++ * P5020 or P3041, it's located at 0x29. ++ */ ++ if (reg == SDHCI_HOST_CONTROL) { ++ u32 dma_bits; ++ ++ /* ++ * If host control register is not standard, exit ++ * this function ++ */ ++ if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) ++ return; ++ ++ /* DMA select is 22,23 bits in Protocol Control Register */ ++ dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5; ++ clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5, ++ dma_bits); ++ val &= ~SDHCI_CTRL_DMA_MASK; ++ val |= in_be32(host->ioaddr + reg) & SDHCI_CTRL_DMA_MASK; ++ } ++ + /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */ + if (reg == SDHCI_HOST_CONTROL) + val &= ~ESDHC_HOST_CONTROL_RES; + sdhci_be32bs_writeb(host, val, reg); + } + ++/* ++ * For Abort or Suspend after Stop at Block Gap, ignore the ADMA ++ * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC]) ++ * and Block Gap Event(IRQSTAT[BGE]) are also set. ++ * For Continue, apply soft reset for data(SYSCTL[RSTD]); ++ * and re-issue the entire read transaction from beginning. ++ */ ++static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask) ++{ ++ u32 tmp; ++ bool applicable; ++ dma_addr_t dmastart; ++ dma_addr_t dmanow; ++ ++ tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); ++ tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; ++ ++ applicable = (intmask & SDHCI_INT_DATA_END) && ++ (intmask & SDHCI_INT_BLK_GAP) && ++ (tmp == VENDOR_V_23); ++ if (!applicable) ++ return; ++ ++ host->data->error = 0; ++ dmastart = sg_dma_address(host->data->sg); ++ dmanow = dmastart + host->data->bytes_xfered; ++ /* ++ * Force update to the next DMA block boundary. ++ */ ++ dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + ++ SDHCI_DEFAULT_BOUNDARY_SIZE; ++ host->data->bytes_xfered = dmanow - dmastart; ++ sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); ++} ++ + static int esdhc_of_enable_dma(struct sdhci_host *host) + { + setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP); +@@ -82,32 +197,190 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host) + return pltfm_host->clock / 256 / 16; + } + +-static struct sdhci_ops sdhci_esdhc_ops = { +- .read_l = sdhci_be32bs_readl, ++static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) ++{ ++ int pre_div = 2; ++ int div = 1; ++ u32 temp; ++ ++ host->mmc->actual_clock = 0; ++ ++ if (clock == 0) ++ return; ++ ++ /* Workaround to reduce the clock frequency for p1010 esdhc */ ++ if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) { ++ if (clock > 20000000) ++ clock -= 5000000; ++ if (clock > 40000000) ++ clock -= 5000000; ++ } ++ ++ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); ++ temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN ++ | ESDHC_CLOCK_MASK); ++ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); ++ ++ while (host->max_clk / pre_div / 16 > clock && pre_div < 256) ++ pre_div *= 2; ++ ++ while (host->max_clk / pre_div / div > clock && div < 16) ++ div++; ++ ++ dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", ++ clock, host->max_clk / pre_div / div); ++ ++ pre_div >>= 1; ++ div--; ++ ++ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); ++ temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN ++ | (div << ESDHC_DIVIDER_SHIFT) ++ | (pre_div << ESDHC_PREDIV_SHIFT)); ++ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); ++ mdelay(1); ++} ++ ++static void esdhc_of_platform_init(struct sdhci_host *host) ++{ ++ u32 vvn; ++ ++ vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); ++ vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; ++ if (vvn == VENDOR_V_22) ++ host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; ++ ++ if (vvn > VENDOR_V_22) ++ host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; ++} ++ ++static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) ++{ ++ u32 ctrl; ++ ++ switch (width) { ++ case MMC_BUS_WIDTH_8: ++ ctrl = ESDHC_CTRL_8BITBUS; ++ break; ++ ++ case MMC_BUS_WIDTH_4: ++ ctrl = ESDHC_CTRL_4BITBUS; ++ break; ++ ++ default: ++ ctrl = 0; ++ break; ++ } ++ ++ clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL, ++ ESDHC_CTRL_BUSWIDTH_MASK, ctrl); ++} ++ ++static void esdhc_reset(struct sdhci_host *host, u8 mask) ++{ ++ sdhci_reset(host, mask); ++ ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++} ++ ++static const struct sdhci_ops sdhci_esdhc_ops = { ++ .read_l = esdhc_readl, + .read_w = esdhc_readw, + .read_b = esdhc_readb, +- .write_l = sdhci_be32bs_writel, ++ .write_l = esdhc_writel, + .write_w = esdhc_writew, + .write_b = esdhc_writeb, +- .set_clock = esdhc_set_clock, ++ .set_clock = esdhc_of_set_clock, + .enable_dma = esdhc_of_enable_dma, + .get_max_clock = esdhc_of_get_max_clock, + .get_min_clock = esdhc_of_get_min_clock, ++ .platform_init = esdhc_of_platform_init, ++ .adma_workaround = esdhci_of_adma_workaround, ++ .set_bus_width = esdhc_pltfm_set_bus_width, ++ .reset = esdhc_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++}; ++ ++#ifdef CONFIG_PM ++ ++static u32 esdhc_proctl; ++static int esdhc_of_suspend(struct device *dev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ ++ esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL); ++ ++ return sdhci_suspend_host(host); ++} ++ ++static int esdhc_of_resume(struct device *dev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ int ret = sdhci_resume_host(host); ++ ++ if (ret == 0) { ++ /* Isn't this already done by sdhci_resume_host() ? --rmk */ ++ esdhc_of_enable_dma(host); ++ sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL); ++ } ++ ++ return ret; ++} ++ ++static const struct dev_pm_ops esdhc_pmops = { ++ .suspend = esdhc_of_suspend, ++ .resume = esdhc_of_resume, + }; ++#define ESDHC_PMOPS (&esdhc_pmops) ++#else ++#define ESDHC_PMOPS NULL ++#endif + +-static struct sdhci_pltfm_data sdhci_esdhc_pdata = { +- /* card detection could be handled via GPIO */ ++static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { ++ /* ++ * card detection could be handled via GPIO ++ * eSDHC cannot support End Attribute in NOP ADMA descriptor ++ */ + .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION +- | SDHCI_QUIRK_NO_CARD_NO_RESET, ++ | SDHCI_QUIRK_NO_CARD_NO_RESET ++ | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, + .ops = &sdhci_esdhc_ops, + }; + +-static int __devinit sdhci_esdhc_probe(struct platform_device *pdev) ++static int sdhci_esdhc_probe(struct platform_device *pdev) + { +- return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata); ++ struct sdhci_host *host; ++ struct device_node *np; ++ int ret; ++ ++ host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0); ++ if (IS_ERR(host)) ++ return PTR_ERR(host); ++ ++ sdhci_get_of_property(pdev); ++ ++ np = pdev->dev.of_node; ++ if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { ++ /* ++ * Freescale messed up with P2020 as it has a non-standard ++ * host control register ++ */ ++ host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; ++ } ++ ++ /* call to generic mmc_of_parse to support additional capabilities */ ++ mmc_of_parse(host->mmc); ++ mmc_of_parse_voltage(np, &host->ocr_mask); ++ ++ ret = sdhci_add_host(host); ++ if (ret) ++ sdhci_pltfm_free(pdev); ++ ++ return ret; + } + +-static int __devexit sdhci_esdhc_remove(struct platform_device *pdev) ++static int sdhci_esdhc_remove(struct platform_device *pdev) + { + return sdhci_pltfm_unregister(pdev); + } +@@ -125,23 +398,13 @@ static struct platform_driver sdhci_esdhc_driver = { + .name = "sdhci-esdhc", + .owner = THIS_MODULE, + .of_match_table = sdhci_esdhc_of_match, +- .pm = SDHCI_PLTFM_PMOPS, ++ .pm = ESDHC_PMOPS, + }, + .probe = sdhci_esdhc_probe, +- .remove = __devexit_p(sdhci_esdhc_remove), ++ .remove = sdhci_esdhc_remove, + }; + +-static int __init sdhci_esdhc_init(void) +-{ +- return platform_driver_register(&sdhci_esdhc_driver); +-} +-module_init(sdhci_esdhc_init); +- +-static void __exit sdhci_esdhc_exit(void) +-{ +- platform_driver_unregister(&sdhci_esdhc_driver); +-} +-module_exit(sdhci_esdhc_exit); ++module_platform_driver(sdhci_esdhc_driver); + + MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC"); + MODULE_AUTHOR("Xiaobo Xie , " +diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c +index 3619adc..b341661 100644 +--- a/drivers/mmc/host/sdhci-of-hlwd.c ++++ b/drivers/mmc/host/sdhci-of-hlwd.c +@@ -51,27 +51,31 @@ static void sdhci_hlwd_writeb(struct sdhci_host *host, u8 val, int reg) + udelay(SDHCI_HLWD_WRITE_DELAY); + } + +-static struct sdhci_ops sdhci_hlwd_ops = { ++static const struct sdhci_ops sdhci_hlwd_ops = { + .read_l = sdhci_be32bs_readl, + .read_w = sdhci_be32bs_readw, + .read_b = sdhci_be32bs_readb, + .write_l = sdhci_hlwd_writel, + .write_w = sdhci_hlwd_writew, + .write_b = sdhci_hlwd_writeb, ++ .set_clock = sdhci_set_clock, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, + }; + +-static struct sdhci_pltfm_data sdhci_hlwd_pdata = { ++static const struct sdhci_pltfm_data sdhci_hlwd_pdata = { + .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR | + SDHCI_QUIRK_32BIT_DMA_SIZE, + .ops = &sdhci_hlwd_ops, + }; + +-static int __devinit sdhci_hlwd_probe(struct platform_device *pdev) ++static int sdhci_hlwd_probe(struct platform_device *pdev) + { +- return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata); ++ return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata, 0); + } + +-static int __devexit sdhci_hlwd_remove(struct platform_device *pdev) ++static int sdhci_hlwd_remove(struct platform_device *pdev) + { + return sdhci_pltfm_unregister(pdev); + } +@@ -90,20 +94,10 @@ static struct platform_driver sdhci_hlwd_driver = { + .pm = SDHCI_PLTFM_PMOPS, + }, + .probe = sdhci_hlwd_probe, +- .remove = __devexit_p(sdhci_hlwd_remove), ++ .remove = sdhci_hlwd_remove, + }; + +-static int __init sdhci_hlwd_init(void) +-{ +- return platform_driver_register(&sdhci_hlwd_driver); +-} +-module_init(sdhci_hlwd_init); +- +-static void __exit sdhci_hlwd_exit(void) +-{ +- platform_driver_unregister(&sdhci_hlwd_driver); +-} +-module_exit(sdhci_hlwd_exit); ++module_platform_driver(sdhci_hlwd_driver); + + MODULE_DESCRIPTION("Nintendo Wii SDHCI OF driver"); + MODULE_AUTHOR("The GameCube Linux Team, Albert Herranz"); +diff --git a/drivers/mmc/host/sdhci-pci-data.c b/drivers/mmc/host/sdhci-pci-data.c +new file mode 100644 +index 0000000..a611217 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-pci-data.c +@@ -0,0 +1,5 @@ ++#include ++#include ++ ++struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno); ++EXPORT_SYMBOL_GPL(sdhci_pci_get_data); +diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c +new file mode 100644 +index 0000000..5670e38 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-pci-o2micro.c +@@ -0,0 +1,397 @@ ++/* ++ * Copyright (C) 2013 BayHub Technology Ltd. ++ * ++ * Authors: Peter Guo ++ * Adam Lee ++ * ++ * 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 "sdhci.h" ++#include "sdhci-pci.h" ++#include "sdhci-pci-o2micro.h" ++ ++static void o2_pci_set_baseclk(struct sdhci_pci_chip *chip, u32 value) ++{ ++ u32 scratch_32; ++ pci_read_config_dword(chip->pdev, ++ O2_SD_PLL_SETTING, &scratch_32); ++ ++ scratch_32 &= 0x0000FFFF; ++ scratch_32 |= value; ++ ++ pci_write_config_dword(chip->pdev, ++ O2_SD_PLL_SETTING, scratch_32); ++} ++ ++static void o2_pci_led_enable(struct sdhci_pci_chip *chip) ++{ ++ int ret; ++ u32 scratch_32; ++ ++ /* Set led of SD host function enable */ ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_FUNC_REG0, &scratch_32); ++ if (ret) ++ return; ++ ++ scratch_32 &= ~O2_SD_FREG0_LEDOFF; ++ pci_write_config_dword(chip->pdev, ++ O2_SD_FUNC_REG0, scratch_32); ++ ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_TEST_REG, &scratch_32); ++ if (ret) ++ return; ++ ++ scratch_32 |= O2_SD_LED_ENABLE; ++ pci_write_config_dword(chip->pdev, ++ O2_SD_TEST_REG, scratch_32); ++ ++} ++ ++void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip) ++{ ++ u32 scratch_32; ++ int ret; ++ /* Improve write performance for SD3.0 */ ++ ret = pci_read_config_dword(chip->pdev, O2_SD_DEV_CTRL, &scratch_32); ++ if (ret) ++ return; ++ scratch_32 &= ~((1 << 12) | (1 << 13) | (1 << 14)); ++ pci_write_config_dword(chip->pdev, O2_SD_DEV_CTRL, scratch_32); ++ ++ /* Enable Link abnormal reset generating Reset */ ++ ret = pci_read_config_dword(chip->pdev, O2_SD_MISC_REG5, &scratch_32); ++ if (ret) ++ return; ++ scratch_32 &= ~((1 << 19) | (1 << 11)); ++ scratch_32 |= (1 << 10); ++ pci_write_config_dword(chip->pdev, O2_SD_MISC_REG5, scratch_32); ++ ++ /* set card power over current protection */ ++ ret = pci_read_config_dword(chip->pdev, O2_SD_TEST_REG, &scratch_32); ++ if (ret) ++ return; ++ scratch_32 |= (1 << 4); ++ pci_write_config_dword(chip->pdev, O2_SD_TEST_REG, scratch_32); ++ ++ /* adjust the output delay for SD mode */ ++ pci_write_config_dword(chip->pdev, O2_SD_DELAY_CTRL, 0x00002492); ++ ++ /* Set the output voltage setting of Aux 1.2v LDO */ ++ ret = pci_read_config_dword(chip->pdev, O2_SD_LD0_CTRL, &scratch_32); ++ if (ret) ++ return; ++ scratch_32 &= ~(3 << 12); ++ pci_write_config_dword(chip->pdev, O2_SD_LD0_CTRL, scratch_32); ++ ++ /* Set Max power supply capability of SD host */ ++ ret = pci_read_config_dword(chip->pdev, O2_SD_CAP_REG0, &scratch_32); ++ if (ret) ++ return; ++ scratch_32 &= ~(0x01FE); ++ scratch_32 |= 0x00CC; ++ pci_write_config_dword(chip->pdev, O2_SD_CAP_REG0, scratch_32); ++ /* Set DLL Tuning Window */ ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_TUNING_CTRL, &scratch_32); ++ if (ret) ++ return; ++ scratch_32 &= ~(0x000000FF); ++ scratch_32 |= 0x00000066; ++ pci_write_config_dword(chip->pdev, O2_SD_TUNING_CTRL, scratch_32); ++ ++ /* Set UHS2 T_EIDLE */ ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_UHS2_L1_CTRL, &scratch_32); ++ if (ret) ++ return; ++ scratch_32 &= ~(0x000000FC); ++ scratch_32 |= 0x00000084; ++ pci_write_config_dword(chip->pdev, O2_SD_UHS2_L1_CTRL, scratch_32); ++ ++ /* Set UHS2 Termination */ ++ ret = pci_read_config_dword(chip->pdev, O2_SD_FUNC_REG3, &scratch_32); ++ if (ret) ++ return; ++ scratch_32 &= ~((1 << 21) | (1 << 30)); ++ ++ /* Set RTD3 function disabled */ ++ scratch_32 |= ((1 << 29) | (1 << 28)); ++ pci_write_config_dword(chip->pdev, O2_SD_FUNC_REG3, scratch_32); ++ ++ /* Set L1 Entrance Timer */ ++ ret = pci_read_config_dword(chip->pdev, O2_SD_CAPS, &scratch_32); ++ if (ret) ++ return; ++ scratch_32 &= ~(0xf0000000); ++ scratch_32 |= 0x30000000; ++ pci_write_config_dword(chip->pdev, O2_SD_CAPS, scratch_32); ++ ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_MISC_CTRL4, &scratch_32); ++ if (ret) ++ return; ++ scratch_32 &= ~(0x000f0000); ++ scratch_32 |= 0x00080000; ++ pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL4, scratch_32); ++} ++EXPORT_SYMBOL_GPL(sdhci_pci_o2_fujin2_pci_init); ++ ++int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) ++{ ++ struct sdhci_pci_chip *chip; ++ struct sdhci_host *host; ++ u32 reg; ++ ++ chip = slot->chip; ++ host = slot->host; ++ switch (chip->pdev->device) { ++ case PCI_DEVICE_ID_O2_SDS0: ++ case PCI_DEVICE_ID_O2_SEABIRD0: ++ case PCI_DEVICE_ID_O2_SEABIRD1: ++ case PCI_DEVICE_ID_O2_SDS1: ++ case PCI_DEVICE_ID_O2_FUJIN2: ++ reg = sdhci_readl(host, O2_SD_VENDOR_SETTING); ++ if (reg & 0x1) ++ host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; ++ ++ if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2) ++ break; ++ /* set dll watch dog timer */ ++ reg = sdhci_readl(host, O2_SD_VENDOR_SETTING2); ++ reg |= (1 << 12); ++ sdhci_writel(host, reg, O2_SD_VENDOR_SETTING2); ++ ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(sdhci_pci_o2_probe_slot); ++ ++int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) ++{ ++ int ret; ++ u8 scratch; ++ u32 scratch_32; ++ ++ switch (chip->pdev->device) { ++ case PCI_DEVICE_ID_O2_8220: ++ case PCI_DEVICE_ID_O2_8221: ++ case PCI_DEVICE_ID_O2_8320: ++ case PCI_DEVICE_ID_O2_8321: ++ /* This extra setup is required due to broken ADMA. */ ++ ret = pci_read_config_byte(chip->pdev, ++ O2_SD_LOCK_WP, &scratch); ++ if (ret) ++ return ret; ++ scratch &= 0x7f; ++ pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); ++ ++ /* Set Multi 3 to VCC3V# */ ++ pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08); ++ ++ /* Disable CLK_REQ# support after media DET */ ++ ret = pci_read_config_byte(chip->pdev, ++ O2_SD_CLKREQ, &scratch); ++ if (ret) ++ return ret; ++ scratch |= 0x20; ++ pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch); ++ ++ /* Choose capabilities, enable SDMA. We have to write 0x01 ++ * to the capabilities register first to unlock it. ++ */ ++ ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch); ++ if (ret) ++ return ret; ++ scratch |= 0x01; ++ pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch); ++ pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73); ++ ++ /* Disable ADMA1/2 */ ++ pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39); ++ pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08); ++ ++ /* Disable the infinite transfer mode */ ++ ret = pci_read_config_byte(chip->pdev, ++ O2_SD_INF_MOD, &scratch); ++ if (ret) ++ return ret; ++ scratch |= 0x08; ++ pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch); ++ ++ /* Lock WP */ ++ ret = pci_read_config_byte(chip->pdev, ++ O2_SD_LOCK_WP, &scratch); ++ if (ret) ++ return ret; ++ scratch |= 0x80; ++ pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); ++ break; ++ case PCI_DEVICE_ID_O2_SDS0: ++ case PCI_DEVICE_ID_O2_SDS1: ++ case PCI_DEVICE_ID_O2_FUJIN2: ++ /* UnLock WP */ ++ ret = pci_read_config_byte(chip->pdev, ++ O2_SD_LOCK_WP, &scratch); ++ if (ret) ++ return ret; ++ ++ scratch &= 0x7f; ++ pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); ++ ++ /* DevId=8520 subId= 0x11 or 0x12 Type Chip support */ ++ if (chip->pdev->device == PCI_DEVICE_ID_O2_FUJIN2) { ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_FUNC_REG0, ++ &scratch_32); ++ scratch_32 = ((scratch_32 & 0xFF000000) >> 24); ++ ++ /* Check Whether subId is 0x11 or 0x12 */ ++ if ((scratch_32 == 0x11) || (scratch_32 == 0x12)) { ++ scratch_32 = 0x2c280000; ++ ++ /* Set Base Clock to 208MZ */ ++ o2_pci_set_baseclk(chip, scratch_32); ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_FUNC_REG4, ++ &scratch_32); ++ ++ /* Enable Base Clk setting change */ ++ scratch_32 |= O2_SD_FREG4_ENABLE_CLK_SET; ++ pci_write_config_dword(chip->pdev, ++ O2_SD_FUNC_REG4, ++ scratch_32); ++ ++ /* Set Tuning Window to 4 */ ++ pci_write_config_byte(chip->pdev, ++ O2_SD_TUNING_CTRL, 0x44); ++ ++ break; ++ } ++ } ++ ++ /* Enable 8520 led function */ ++ o2_pci_led_enable(chip); ++ ++ /* Set timeout CLK */ ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_CLK_SETTING, &scratch_32); ++ if (ret) ++ return ret; ++ ++ scratch_32 &= ~(0xFF00); ++ scratch_32 |= 0x07E0C800; ++ pci_write_config_dword(chip->pdev, ++ O2_SD_CLK_SETTING, scratch_32); ++ ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_CLKREQ, &scratch_32); ++ if (ret) ++ return ret; ++ scratch_32 |= 0x3; ++ pci_write_config_dword(chip->pdev, O2_SD_CLKREQ, scratch_32); ++ ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_PLL_SETTING, &scratch_32); ++ if (ret) ++ return ret; ++ ++ scratch_32 &= ~(0x1F3F070E); ++ scratch_32 |= 0x18270106; ++ pci_write_config_dword(chip->pdev, ++ O2_SD_PLL_SETTING, scratch_32); ++ ++ /* Disable UHS1 funciton */ ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_CAP_REG2, &scratch_32); ++ if (ret) ++ return ret; ++ scratch_32 &= ~(0xE0); ++ pci_write_config_dword(chip->pdev, ++ O2_SD_CAP_REG2, scratch_32); ++ ++ if (chip->pdev->device == PCI_DEVICE_ID_O2_FUJIN2) ++ sdhci_pci_o2_fujin2_pci_init(chip); ++ ++ /* Lock WP */ ++ ret = pci_read_config_byte(chip->pdev, ++ O2_SD_LOCK_WP, &scratch); ++ if (ret) ++ return ret; ++ scratch |= 0x80; ++ pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); ++ break; ++ case PCI_DEVICE_ID_O2_SEABIRD0: ++ case PCI_DEVICE_ID_O2_SEABIRD1: ++ /* UnLock WP */ ++ ret = pci_read_config_byte(chip->pdev, ++ O2_SD_LOCK_WP, &scratch); ++ if (ret) ++ return ret; ++ ++ scratch &= 0x7f; ++ pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); ++ ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_PLL_SETTING, &scratch_32); ++ ++ if ((scratch_32 & 0xff000000) == 0x01000000) { ++ scratch_32 &= 0x0000FFFF; ++ scratch_32 |= 0x1F340000; ++ ++ pci_write_config_dword(chip->pdev, ++ O2_SD_PLL_SETTING, scratch_32); ++ } else { ++ scratch_32 &= 0x0000FFFF; ++ scratch_32 |= 0x2c280000; ++ ++ pci_write_config_dword(chip->pdev, ++ O2_SD_PLL_SETTING, scratch_32); ++ ++ ret = pci_read_config_dword(chip->pdev, ++ O2_SD_FUNC_REG4, ++ &scratch_32); ++ scratch_32 |= (1 << 22); ++ pci_write_config_dword(chip->pdev, ++ O2_SD_FUNC_REG4, scratch_32); ++ } ++ ++ /* Set Tuning Windows to 5 */ ++ pci_write_config_byte(chip->pdev, ++ O2_SD_TUNING_CTRL, 0x55); ++ /* Lock WP */ ++ ret = pci_read_config_byte(chip->pdev, ++ O2_SD_LOCK_WP, &scratch); ++ if (ret) ++ return ret; ++ scratch |= 0x80; ++ pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); ++ break; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(sdhci_pci_o2_probe); ++ ++int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip) ++{ ++ sdhci_pci_o2_probe(chip); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(sdhci_pci_o2_resume); +diff --git a/drivers/mmc/host/sdhci-pci-o2micro.h b/drivers/mmc/host/sdhci-pci-o2micro.h +new file mode 100644 +index 0000000..f7ffc90 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-pci-o2micro.h +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (C) 2013 BayHub Technology Ltd. ++ * ++ * Authors: Peter Guo ++ * Adam Lee ++ * ++ * 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 __SDHCI_PCI_O2MICRO_H ++#define __SDHCI_PCI_O2MICRO_H ++ ++#include "sdhci-pci.h" ++ ++/* ++ * O2Micro device IDs ++ */ ++ ++#define PCI_DEVICE_ID_O2_SDS0 0x8420 ++#define PCI_DEVICE_ID_O2_SDS1 0x8421 ++#define PCI_DEVICE_ID_O2_FUJIN2 0x8520 ++#define PCI_DEVICE_ID_O2_SEABIRD0 0x8620 ++#define PCI_DEVICE_ID_O2_SEABIRD1 0x8621 ++ ++/* ++ * O2Micro device registers ++ */ ++ ++#define O2_SD_MISC_REG5 0x64 ++#define O2_SD_LD0_CTRL 0x68 ++#define O2_SD_DEV_CTRL 0x88 ++#define O2_SD_LOCK_WP 0xD3 ++#define O2_SD_TEST_REG 0xD4 ++#define O2_SD_FUNC_REG0 0xDC ++#define O2_SD_MULTI_VCC3V 0xEE ++#define O2_SD_CLKREQ 0xEC ++#define O2_SD_CAPS 0xE0 ++#define O2_SD_ADMA1 0xE2 ++#define O2_SD_ADMA2 0xE7 ++#define O2_SD_INF_MOD 0xF1 ++#define O2_SD_MISC_CTRL4 0xFC ++#define O2_SD_TUNING_CTRL 0x300 ++#define O2_SD_PLL_SETTING 0x304 ++#define O2_SD_CLK_SETTING 0x328 ++#define O2_SD_CAP_REG2 0x330 ++#define O2_SD_CAP_REG0 0x334 ++#define O2_SD_UHS1_CAP_SETTING 0x33C ++#define O2_SD_DELAY_CTRL 0x350 ++#define O2_SD_UHS2_L1_CTRL 0x35C ++#define O2_SD_FUNC_REG3 0x3E0 ++#define O2_SD_FUNC_REG4 0x3E4 ++#define O2_SD_LED_ENABLE BIT(6) ++#define O2_SD_FREG0_LEDOFF BIT(13) ++#define O2_SD_FREG4_ENABLE_CLK_SET BIT(22) ++ ++#define O2_SD_VENDOR_SETTING 0x110 ++#define O2_SD_VENDOR_SETTING2 0x1C8 ++ ++extern void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip); ++ ++extern int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot); ++ ++extern int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip); ++ ++extern int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip); ++ ++#endif /* __SDHCI_PCI_O2MICRO_H */ +diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c +index 83b51b5..52c42fc 100644 +--- a/drivers/mmc/host/sdhci-pci.c ++++ b/drivers/mmc/host/sdhci-pci.c +@@ -23,62 +23,12 @@ + #include + #include + #include +-#include + #include ++#include + + #include "sdhci.h" +- +-/* +- * PCI registers +- */ +- +-#define PCI_SDHCI_IFPIO 0x00 +-#define PCI_SDHCI_IFDMA 0x01 +-#define PCI_SDHCI_IFVENDOR 0x02 +- +-#define PCI_SLOT_INFO 0x40 /* 8 bits */ +-#define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) +-#define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 +- +-#define MAX_SLOTS 8 +- +-struct sdhci_pci_chip; +-struct sdhci_pci_slot; +- +-struct sdhci_pci_fixes { +- unsigned int quirks; +- bool allow_runtime_pm; +- +- int (*probe) (struct sdhci_pci_chip *); +- +- int (*probe_slot) (struct sdhci_pci_slot *); +- void (*remove_slot) (struct sdhci_pci_slot *, int); +- +- int (*suspend) (struct sdhci_pci_chip *); +- int (*resume) (struct sdhci_pci_chip *); +-}; +- +-struct sdhci_pci_slot { +- struct sdhci_pci_chip *chip; +- struct sdhci_host *host; +- +- int pci_bar; +- int rst_n_gpio; +- int cd_gpio; +- int cd_irq; +-}; +- +-struct sdhci_pci_chip { +- struct pci_dev *pdev; +- +- unsigned int quirks; +- bool allow_runtime_pm; +- const struct sdhci_pci_fixes *fixes; +- +- int num_slots; /* Slots on controller */ +- struct sdhci_pci_slot *slots[MAX_SLOTS]; /* Pointers to host slots */ +-}; +- ++#include "sdhci-pci.h" ++#include "sdhci-pci-o2micro.h" + + /*****************************************************************************\ + * * +@@ -105,6 +55,7 @@ static int ricoh_mmc_probe_slot(struct sdhci_pci_slot *slot) + + SDHCI_TIMEOUT_CLK_UNIT | + SDHCI_CAN_VDD_330 | ++ SDHCI_CAN_DO_HISPD | + SDHCI_CAN_DO_SDMA; + return 0; + } +@@ -172,32 +123,15 @@ static int mrst_hc_probe(struct sdhci_pci_chip *chip) + return 0; + } + +-/* Medfield eMMC hardware reset GPIOs */ +-static int mfd_emmc0_rst_gpio = -EINVAL; +-static int mfd_emmc1_rst_gpio = -EINVAL; +- +-static int mfd_emmc_gpio_parse(struct sfi_table_header *table) ++static int pch_hc_probe_slot(struct sdhci_pci_slot *slot) + { +- struct sfi_table_simple *sb = (struct sfi_table_simple *)table; +- struct sfi_gpio_table_entry *entry; +- int i, num; +- +- num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry); +- entry = (struct sfi_gpio_table_entry *)sb->pentry; +- +- for (i = 0; i < num; i++, entry++) { +- if (!strncmp(entry->pin_name, "emmc0_rst", SFI_NAME_LEN)) +- mfd_emmc0_rst_gpio = entry->pin_no; +- else if (!strncmp(entry->pin_name, "emmc1_rst", SFI_NAME_LEN)) +- mfd_emmc1_rst_gpio = entry->pin_no; +- } +- ++ slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA; + return 0; + } + + #ifdef CONFIG_PM_RUNTIME + +-static irqreturn_t mfd_sd_cd(int irq, void *dev_id) ++static irqreturn_t sdhci_pci_sd_cd(int irq, void *dev_id) + { + struct sdhci_pci_slot *slot = dev_id; + struct sdhci_host *host = slot->host; +@@ -206,15 +140,16 @@ static irqreturn_t mfd_sd_cd(int irq, void *dev_id) + return IRQ_HANDLED; + } + +-#define MFLD_SD_CD_PIN 69 +- +-static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot) ++static void sdhci_pci_add_own_cd(struct sdhci_pci_slot *slot) + { +- int err, irq, gpio = MFLD_SD_CD_PIN; ++ int err, irq, gpio = slot->cd_gpio; + + slot->cd_gpio = -EINVAL; + slot->cd_irq = -EINVAL; + ++ if (!gpio_is_valid(gpio)) ++ return; ++ + err = gpio_request(gpio, "sd_cd"); + if (err < 0) + goto out; +@@ -227,72 +162,54 @@ static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot) + if (irq < 0) + goto out_free; + +- err = request_irq(irq, mfd_sd_cd, IRQF_TRIGGER_RISING | ++ err = request_irq(irq, sdhci_pci_sd_cd, IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, "sd_cd", slot); + if (err) + goto out_free; + + slot->cd_gpio = gpio; + slot->cd_irq = irq; +- slot->host->quirks2 |= SDHCI_QUIRK2_OWN_CARD_DETECTION; + +- return 0; ++ return; + + out_free: + gpio_free(gpio); + out: + dev_warn(&slot->chip->pdev->dev, "failed to setup card detect wake up\n"); +- return 0; + } + +-static void mfd_sd_remove_slot(struct sdhci_pci_slot *slot, int dead) ++static void sdhci_pci_remove_own_cd(struct sdhci_pci_slot *slot) + { + if (slot->cd_irq >= 0) + free_irq(slot->cd_irq, slot); +- gpio_free(slot->cd_gpio); ++ if (gpio_is_valid(slot->cd_gpio)) ++ gpio_free(slot->cd_gpio); + } + + #else + +-#define mfd_sd_probe_slot NULL +-#define mfd_sd_remove_slot NULL ++static inline void sdhci_pci_add_own_cd(struct sdhci_pci_slot *slot) ++{ ++} ++ ++static inline void sdhci_pci_remove_own_cd(struct sdhci_pci_slot *slot) ++{ ++} + + #endif + + static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot) + { +- const char *name = NULL; +- int gpio = -EINVAL; +- +- sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, mfd_emmc_gpio_parse); +- +- switch (slot->chip->pdev->device) { +- case PCI_DEVICE_ID_INTEL_MFD_EMMC0: +- gpio = mfd_emmc0_rst_gpio; +- name = "eMMC0_reset"; +- break; +- case PCI_DEVICE_ID_INTEL_MFD_EMMC1: +- gpio = mfd_emmc1_rst_gpio; +- name = "eMMC1_reset"; +- break; +- } +- +- if (!gpio_request(gpio, name)) { +- gpio_direction_output(gpio, 1); +- slot->rst_n_gpio = gpio; +- slot->host->mmc->caps |= MMC_CAP_HW_RESET; +- } +- + slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE; +- +- slot->host->mmc->caps2 = MMC_CAP2_BOOTPART_NOACC; +- ++ slot->host->mmc->caps2 |= MMC_CAP2_BOOTPART_NOACC | ++ MMC_CAP2_HC_ERASE_SZ; + return 0; + } + +-static void mfd_emmc_remove_slot(struct sdhci_pci_slot *slot, int dead) ++static int mfd_sdio_probe_slot(struct sdhci_pci_slot *slot) + { +- gpio_free(slot->rst_n_gpio); ++ slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE; ++ return 0; + } + + static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = { +@@ -308,90 +225,106 @@ static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = { + static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = { + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, + .allow_runtime_pm = true, +- .probe_slot = mfd_sd_probe_slot, +- .remove_slot = mfd_sd_remove_slot, ++ .own_cd_for_runtime_pm = true, + }; + + static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = { + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, ++ .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON, + .allow_runtime_pm = true, ++ .probe_slot = mfd_sdio_probe_slot, + }; + + static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = { + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, + .allow_runtime_pm = true, + .probe_slot = mfd_emmc_probe_slot, +- .remove_slot = mfd_emmc_remove_slot, + }; + +-/* O2Micro extra registers */ +-#define O2_SD_LOCK_WP 0xD3 +-#define O2_SD_MULTI_VCC3V 0xEE +-#define O2_SD_CLKREQ 0xEC +-#define O2_SD_CAPS 0xE0 +-#define O2_SD_ADMA1 0xE2 +-#define O2_SD_ADMA2 0xE7 +-#define O2_SD_INF_MOD 0xF1 ++static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = { ++ .quirks = SDHCI_QUIRK_BROKEN_ADMA, ++ .probe_slot = pch_hc_probe_slot, ++}; + +-static int o2_probe(struct sdhci_pci_chip *chip) ++static void sdhci_pci_int_hw_reset(struct sdhci_host *host) + { +- int ret; +- u8 scratch; ++ u8 reg; ++ ++ reg = sdhci_readb(host, SDHCI_POWER_CONTROL); ++ reg |= 0x10; ++ sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); ++ /* For eMMC, minimum is 1us but give it 9us for good measure */ ++ udelay(9); ++ reg &= ~0x10; ++ sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); ++ /* For eMMC, minimum is 200us but give it 300us for good measure */ ++ usleep_range(300, 1000); ++} + +- switch (chip->pdev->device) { +- case PCI_DEVICE_ID_O2_8220: +- case PCI_DEVICE_ID_O2_8221: +- case PCI_DEVICE_ID_O2_8320: +- case PCI_DEVICE_ID_O2_8321: +- /* This extra setup is required due to broken ADMA. */ +- ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); +- if (ret) +- return ret; +- scratch &= 0x7f; +- pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); ++static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) ++{ ++ slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | ++ MMC_CAP_HW_RESET; ++ slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ; ++ slot->hw_reset = sdhci_pci_int_hw_reset; ++ return 0; ++} + +- /* Set Multi 3 to VCC3V# */ +- pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08); ++static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot) ++{ ++ slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE; ++ return 0; ++} + +- /* Disable CLK_REQ# support after media DET */ +- ret = pci_read_config_byte(chip->pdev, O2_SD_CLKREQ, &scratch); +- if (ret) +- return ret; +- scratch |= 0x20; +- pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch); ++static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { ++ .allow_runtime_pm = true, ++ .probe_slot = byt_emmc_probe_slot, ++}; + +- /* Choose capabilities, enable SDMA. We have to write 0x01 +- * to the capabilities register first to unlock it. +- */ +- ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch); +- if (ret) +- return ret; +- scratch |= 0x01; +- pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch); +- pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73); ++static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { ++ .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON, ++ .allow_runtime_pm = true, ++ .probe_slot = byt_sdio_probe_slot, ++}; ++ ++static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { ++ .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, ++ .allow_runtime_pm = true, ++ .own_cd_for_runtime_pm = true, ++}; + +- /* Disable ADMA1/2 */ +- pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39); +- pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08); ++/* Define Host controllers for Intel Merrifield platform */ ++#define INTEL_MRFL_EMMC_0 0 ++#define INTEL_MRFL_EMMC_1 1 + +- /* Disable the infinite transfer mode */ +- ret = pci_read_config_byte(chip->pdev, O2_SD_INF_MOD, &scratch); +- if (ret) +- return ret; +- scratch |= 0x08; +- pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch); ++static int intel_mrfl_mmc_probe_slot(struct sdhci_pci_slot *slot) ++{ ++ if ((PCI_FUNC(slot->chip->pdev->devfn) != INTEL_MRFL_EMMC_0) && ++ (PCI_FUNC(slot->chip->pdev->devfn) != INTEL_MRFL_EMMC_1)) ++ /* SD support is not ready yet */ ++ return -ENODEV; + +- /* Lock WP */ +- ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); +- if (ret) +- return ret; +- scratch |= 0x80; +- pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); +- } ++ slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | ++ MMC_CAP_1_8V_DDR; + + return 0; + } + ++static const struct sdhci_pci_fixes sdhci_intel_mrfl_mmc = { ++ .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, ++ .quirks2 = SDHCI_QUIRK2_BROKEN_HS200, ++ .probe_slot = intel_mrfl_mmc_probe_slot, ++}; ++ ++/* O2Micro extra registers */ ++#define O2_SD_LOCK_WP 0xD3 ++#define O2_SD_MULTI_VCC3V 0xEE ++#define O2_SD_CLKREQ 0xEC ++#define O2_SD_CAPS 0xE0 ++#define O2_SD_ADMA1 0xE2 ++#define O2_SD_ADMA2 0xE7 ++#define O2_SD_INF_MOD 0xF1 ++ + static int jmicron_pmos(struct sdhci_pci_chip *chip, int on) + { + u8 scratch; +@@ -582,7 +515,10 @@ static int jmicron_resume(struct sdhci_pci_chip *chip) + } + + static const struct sdhci_pci_fixes sdhci_o2 = { +- .probe = o2_probe, ++ .probe = sdhci_pci_o2_probe, ++ .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, ++ .probe_slot = sdhci_pci_o2_probe_slot, ++ .resume = sdhci_pci_o2_resume, + }; + + static const struct sdhci_pci_fixes sdhci_jmicron = { +@@ -674,7 +610,19 @@ static const struct sdhci_pci_fixes sdhci_via = { + .probe = via_probe, + }; + +-static const struct pci_device_id pci_ids[] __devinitdata = { ++static int rtsx_probe_slot(struct sdhci_pci_slot *slot) ++{ ++ slot->host->mmc->caps2 |= MMC_CAP2_HS200; ++ return 0; ++} ++ ++static const struct sdhci_pci_fixes sdhci_rtsx = { ++ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | ++ SDHCI_QUIRK2_BROKEN_DDR50, ++ .probe_slot = rtsx_probe_slot, ++}; ++ ++static const struct pci_device_id pci_ids[] = { + { + .vendor = PCI_VENDOR_ID_RICOH, + .device = PCI_DEVICE_ID_RICOH_R5C822, +@@ -796,6 +744,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = { + }, + + { ++ .vendor = PCI_VENDOR_ID_REALTEK, ++ .device = 0x5250, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_rtsx, ++ }, ++ ++ { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_MRST_SD0, + .subvendor = PCI_ANY_ID, +@@ -860,6 +816,102 @@ static const struct pci_device_id pci_ids[] __devinitdata = { + }, + + { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_PCH_SDIO0, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_pch_sdio, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_PCH_SDIO1, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_pch_sdio, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_BYT_EMMC, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_emmc, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_BYT_SDIO, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_sdio, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_BYT_SD, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_sd, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_BYT_EMMC2, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_emmc, ++ }, ++ ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_CLV_SDIO0, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_sd, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_CLV_SDIO1, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_sdio, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_CLV_SDIO2, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_sdio, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_CLV_EMMC0, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_CLV_EMMC1, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_MRFL_MMC, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_mrfl_mmc, ++ }, ++ { + .vendor = PCI_VENDOR_ID_O2, + .device = PCI_DEVICE_ID_O2_8120, + .subvendor = PCI_ANY_ID, +@@ -899,6 +951,46 @@ static const struct pci_device_id pci_ids[] __devinitdata = { + .driver_data = (kernel_ulong_t)&sdhci_o2, + }, + ++ { ++ .vendor = PCI_VENDOR_ID_O2, ++ .device = PCI_DEVICE_ID_O2_FUJIN2, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_o2, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_O2, ++ .device = PCI_DEVICE_ID_O2_SDS0, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_o2, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_O2, ++ .device = PCI_DEVICE_ID_O2_SDS1, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_o2, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_O2, ++ .device = PCI_DEVICE_ID_O2_SEABIRD0, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_o2, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_O2, ++ .device = PCI_DEVICE_ID_O2_SEABIRD1, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_o2, ++ }, ++ + { /* Generic SD host controller */ + PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) + }, +@@ -939,7 +1031,7 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host) + return 0; + } + +-static int sdhci_pci_8bit_width(struct sdhci_host *host, int width) ++static void sdhci_pci_set_bus_width(struct sdhci_host *host, int width) + { + u8 ctrl; + +@@ -960,11 +1052,9 @@ static int sdhci_pci_8bit_width(struct sdhci_host *host, int width) + } + + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); +- +- return 0; + } + +-static void sdhci_pci_hw_reset(struct sdhci_host *host) ++static void sdhci_pci_gpio_hw_reset(struct sdhci_host *host) + { + struct sdhci_pci_slot *slot = sdhci_priv(host); + int rst_n_gpio = slot->rst_n_gpio; +@@ -979,9 +1069,20 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host) + usleep_range(300, 1000); + } + +-static struct sdhci_ops sdhci_pci_ops = { ++static void sdhci_pci_hw_reset(struct sdhci_host *host) ++{ ++ struct sdhci_pci_slot *slot = sdhci_priv(host); ++ ++ if (slot->hw_reset) ++ slot->hw_reset(host); ++} ++ ++static const struct sdhci_ops sdhci_pci_ops = { ++ .set_clock = sdhci_set_clock, + .enable_dma = sdhci_pci_enable_dma, +- .platform_8bit_width = sdhci_pci_8bit_width, ++ .set_bus_width = sdhci_pci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, + .hw_reset = sdhci_pci_hw_reset, + }; + +@@ -1013,11 +1114,8 @@ static int sdhci_pci_suspend(struct device *dev) + + ret = sdhci_suspend_host(slot->host); + +- if (ret) { +- for (i--; i >= 0; i--) +- sdhci_resume_host(chip->slots[i]->host); +- return ret; +- } ++ if (ret) ++ goto err_pci_suspend; + + slot_pm_flags = slot->host->mmc->pm_flags; + if (slot_pm_flags & MMC_PM_WAKE_SDIO_IRQ) +@@ -1028,11 +1126,8 @@ static int sdhci_pci_suspend(struct device *dev) + + if (chip->fixes && chip->fixes->suspend) { + ret = chip->fixes->suspend(chip); +- if (ret) { +- for (i = chip->num_slots - 1; i >= 0; i--) +- sdhci_resume_host(chip->slots[i]->host); +- return ret; +- } ++ if (ret) ++ goto err_pci_suspend; + } + + pci_save_state(pdev); +@@ -1049,6 +1144,11 @@ static int sdhci_pci_suspend(struct device *dev) + } + + return 0; ++ ++err_pci_suspend: ++ while (--i >= 0) ++ sdhci_resume_host(chip->slots[i]->host); ++ return ret; + } + + static int sdhci_pci_resume(struct device *dev) +@@ -1114,23 +1214,22 @@ static int sdhci_pci_runtime_suspend(struct device *dev) + + ret = sdhci_runtime_suspend_host(slot->host); + +- if (ret) { +- for (i--; i >= 0; i--) +- sdhci_runtime_resume_host(chip->slots[i]->host); +- return ret; +- } ++ if (ret) ++ goto err_pci_runtime_suspend; + } + + if (chip->fixes && chip->fixes->suspend) { + ret = chip->fixes->suspend(chip); +- if (ret) { +- for (i = chip->num_slots - 1; i >= 0; i--) +- sdhci_runtime_resume_host(chip->slots[i]->host); +- return ret; +- } ++ if (ret) ++ goto err_pci_runtime_suspend; + } + + return 0; ++ ++err_pci_runtime_suspend: ++ while (--i >= 0) ++ sdhci_runtime_resume_host(chip->slots[i]->host); ++ return ret; + } + + static int sdhci_pci_runtime_resume(struct device *dev) +@@ -1190,19 +1289,20 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = { + * * + \*****************************************************************************/ + +-static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( +- struct pci_dev *pdev, struct sdhci_pci_chip *chip, int bar) ++static struct sdhci_pci_slot *sdhci_pci_probe_slot( ++ struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar, ++ int slotno) + { + struct sdhci_pci_slot *slot; + struct sdhci_host *host; +- int ret; ++ int ret, bar = first_bar + slotno; + + if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) { + dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar); + return ERR_PTR(-ENODEV); + } + +- if (pci_resource_len(pdev, bar) != 0x100) { ++ if (pci_resource_len(pdev, bar) < 0x100) { + dev_err(&pdev->dev, "Invalid iomem size. You may " + "experience problems.\n"); + } +@@ -1229,17 +1329,35 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( + slot->host = host; + slot->pci_bar = bar; + slot->rst_n_gpio = -EINVAL; ++ slot->cd_gpio = -EINVAL; ++ ++ /* Retrieve platform data if there is any */ ++ if (*sdhci_pci_get_data) ++ slot->data = sdhci_pci_get_data(pdev, slotno); ++ ++ if (slot->data) { ++ if (slot->data->setup) { ++ ret = slot->data->setup(slot->data); ++ if (ret) { ++ dev_err(&pdev->dev, "platform setup failed\n"); ++ goto free; ++ } ++ } ++ slot->rst_n_gpio = slot->data->rst_n_gpio; ++ slot->cd_gpio = slot->data->cd_gpio; ++ } + + host->hw_name = "PCI"; + host->ops = &sdhci_pci_ops; + host->quirks = chip->quirks; ++ host->quirks2 = chip->quirks2; + + host->irq = pdev->irq; + + ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc)); + if (ret) { + dev_err(&pdev->dev, "cannot request region\n"); +- goto free; ++ goto cleanup; + } + + host->ioaddr = pci_ioremap_bar(pdev, bar); +@@ -1255,15 +1373,42 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( + goto unmap; + } + ++ if (gpio_is_valid(slot->rst_n_gpio)) { ++ if (!gpio_request(slot->rst_n_gpio, "eMMC_reset")) { ++ gpio_direction_output(slot->rst_n_gpio, 1); ++ slot->host->mmc->caps |= MMC_CAP_HW_RESET; ++ slot->hw_reset = sdhci_pci_gpio_hw_reset; ++ } else { ++ dev_warn(&pdev->dev, "failed to request rst_n_gpio\n"); ++ slot->rst_n_gpio = -EINVAL; ++ } ++ } ++ + host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ; ++ host->mmc->slotno = slotno; ++ host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; + + ret = sdhci_add_host(host); + if (ret) + goto remove; + ++ sdhci_pci_add_own_cd(slot); ++ ++ /* ++ * Check if the chip needs a separate GPIO for card detect to wake up ++ * from runtime suspend. If it is not there, don't allow runtime PM. ++ * Note sdhci_pci_add_own_cd() sets slot->cd_gpio to -EINVAL on failure. ++ */ ++ if (chip->fixes && chip->fixes->own_cd_for_runtime_pm && ++ !gpio_is_valid(slot->cd_gpio)) ++ chip->allow_runtime_pm = false; ++ + return slot; + + remove: ++ if (gpio_is_valid(slot->rst_n_gpio)) ++ gpio_free(slot->rst_n_gpio); ++ + if (chip->fixes && chip->fixes->remove_slot) + chip->fixes->remove_slot(slot, 0); + +@@ -1273,6 +1418,10 @@ unmap: + release: + pci_release_region(pdev, bar); + ++cleanup: ++ if (slot->data && slot->data->cleanup) ++ slot->data->cleanup(slot->data); ++ + free: + sdhci_free_host(host); + +@@ -1284,6 +1433,8 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) + int dead; + u32 scratch; + ++ sdhci_pci_remove_own_cd(slot); ++ + dead = 0; + scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS); + if (scratch == (u32)-1) +@@ -1291,15 +1442,21 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) + + sdhci_remove_host(slot->host, dead); + ++ if (gpio_is_valid(slot->rst_n_gpio)) ++ gpio_free(slot->rst_n_gpio); ++ + if (slot->chip->fixes && slot->chip->fixes->remove_slot) + slot->chip->fixes->remove_slot(slot, dead); + ++ if (slot->data && slot->data->cleanup) ++ slot->data->cleanup(slot->data); ++ + pci_release_region(slot->chip->pdev, slot->pci_bar); + + sdhci_free_host(slot->host); + } + +-static void __devinit sdhci_pci_runtime_pm_allow(struct device *dev) ++static void sdhci_pci_runtime_pm_allow(struct device *dev) + { + pm_runtime_put_noidle(dev); + pm_runtime_allow(dev); +@@ -1308,13 +1465,13 @@ static void __devinit sdhci_pci_runtime_pm_allow(struct device *dev) + pm_suspend_ignore_children(dev, 1); + } + +-static void __devexit sdhci_pci_runtime_pm_forbid(struct device *dev) ++static void sdhci_pci_runtime_pm_forbid(struct device *dev) + { + pm_runtime_forbid(dev); + pm_runtime_get_noresume(dev); + } + +-static int __devinit sdhci_pci_probe(struct pci_dev *pdev, ++static int sdhci_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) + { + struct sdhci_pci_chip *chip; +@@ -1365,6 +1522,7 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, + chip->fixes = (const struct sdhci_pci_fixes *)ent->driver_data; + if (chip->fixes) { + chip->quirks = chip->fixes->quirks; ++ chip->quirks2 = chip->fixes->quirks2; + chip->allow_runtime_pm = chip->fixes->allow_runtime_pm; + } + chip->num_slots = slots; +@@ -1380,7 +1538,7 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, + slots = chip->num_slots; /* Quirk may have changed this */ + + for (i = 0; i < slots; i++) { +- slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i); ++ slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i); + if (IS_ERR(slot)) { + for (i--; i >= 0; i--) + sdhci_pci_remove_slot(chip->slots[i]); +@@ -1405,7 +1563,7 @@ err: + return ret; + } + +-static void __devexit sdhci_pci_remove(struct pci_dev *pdev) ++static void sdhci_pci_remove(struct pci_dev *pdev) + { + int i; + struct sdhci_pci_chip *chip; +@@ -1430,30 +1588,13 @@ static struct pci_driver sdhci_driver = { + .name = "sdhci-pci", + .id_table = pci_ids, + .probe = sdhci_pci_probe, +- .remove = __devexit_p(sdhci_pci_remove), ++ .remove = sdhci_pci_remove, + .driver = { + .pm = &sdhci_pci_pm_ops + }, + }; + +-/*****************************************************************************\ +- * * +- * Driver init/exit * +- * * +-\*****************************************************************************/ +- +-static int __init sdhci_drv_init(void) +-{ +- return pci_register_driver(&sdhci_driver); +-} +- +-static void __exit sdhci_drv_exit(void) +-{ +- pci_unregister_driver(&sdhci_driver); +-} +- +-module_init(sdhci_drv_init); +-module_exit(sdhci_drv_exit); ++module_pci_driver(sdhci_driver); + + MODULE_AUTHOR("Pierre Ossman "); + MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver"); +diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h +new file mode 100644 +index 0000000..6d71871 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-pci.h +@@ -0,0 +1,78 @@ ++#ifndef __SDHCI_PCI_H ++#define __SDHCI_PCI_H ++ ++/* ++ * PCI device IDs ++ */ ++ ++#define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809 ++#define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a ++#define PCI_DEVICE_ID_INTEL_BYT_EMMC 0x0f14 ++#define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15 ++#define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16 ++#define PCI_DEVICE_ID_INTEL_BYT_EMMC2 0x0f50 ++#define PCI_DEVICE_ID_INTEL_MRFL_MMC 0x1190 ++#define PCI_DEVICE_ID_INTEL_CLV_SDIO0 0x08f9 ++#define PCI_DEVICE_ID_INTEL_CLV_SDIO1 0x08fa ++#define PCI_DEVICE_ID_INTEL_CLV_SDIO2 0x08fb ++#define PCI_DEVICE_ID_INTEL_CLV_EMMC0 0x08e5 ++#define PCI_DEVICE_ID_INTEL_CLV_EMMC1 0x08e6 ++ ++/* ++ * PCI registers ++ */ ++ ++#define PCI_SDHCI_IFPIO 0x00 ++#define PCI_SDHCI_IFDMA 0x01 ++#define PCI_SDHCI_IFVENDOR 0x02 ++ ++#define PCI_SLOT_INFO 0x40 /* 8 bits */ ++#define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) ++#define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 ++ ++#define MAX_SLOTS 8 ++ ++struct sdhci_pci_chip; ++struct sdhci_pci_slot; ++ ++struct sdhci_pci_fixes { ++ unsigned int quirks; ++ unsigned int quirks2; ++ bool allow_runtime_pm; ++ bool own_cd_for_runtime_pm; ++ ++ int (*probe) (struct sdhci_pci_chip *); ++ ++ int (*probe_slot) (struct sdhci_pci_slot *); ++ void (*remove_slot) (struct sdhci_pci_slot *, int); ++ ++ int (*suspend) (struct sdhci_pci_chip *); ++ int (*resume) (struct sdhci_pci_chip *); ++}; ++ ++struct sdhci_pci_slot { ++ struct sdhci_pci_chip *chip; ++ struct sdhci_host *host; ++ struct sdhci_pci_data *data; ++ ++ int pci_bar; ++ int rst_n_gpio; ++ int cd_gpio; ++ int cd_irq; ++ ++ void (*hw_reset)(struct sdhci_host *host); ++}; ++ ++struct sdhci_pci_chip { ++ struct pci_dev *pdev; ++ ++ unsigned int quirks; ++ unsigned int quirks2; ++ bool allow_runtime_pm; ++ const struct sdhci_pci_fixes *fixes; ++ ++ int num_slots; /* Slots on controller */ ++ struct sdhci_pci_slot *slots[MAX_SLOTS]; /* Pointers to host slots */ ++}; ++ ++#endif /* __SDHCI_PCI_H */ +diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c +index 03970bc..7e834fb 100644 +--- a/drivers/mmc/host/sdhci-pltfm.c ++++ b/drivers/mmc/host/sdhci-pltfm.c +@@ -2,7 +2,7 @@ + * sdhci-pltfm.c Support for SDHCI platform devices + * Copyright (c) 2009 Intel Corporation + * +- * Copyright (c) 2007 Freescale Semiconductor, Inc. ++ * Copyright (c) 2007, 2011 Freescale Semiconductor, Inc. + * Copyright (c) 2009 MontaVista Software, Inc. + * + * Authors: Xiaobo Xie +@@ -36,13 +36,26 @@ + #endif + #include "sdhci-pltfm.h" + +-static struct sdhci_ops sdhci_pltfm_ops = { ++unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ ++ return clk_get_rate(pltfm_host->clk); ++} ++EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock); ++ ++static const struct sdhci_ops sdhci_pltfm_ops = { ++ .set_clock = sdhci_set_clock, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, + }; + + #ifdef CONFIG_OF + static bool sdhci_of_wp_inverted(struct device_node *np) + { +- if (of_get_property(np, "sdhci,wp-inverted", NULL)) ++ if (of_get_property(np, "sdhci,wp-inverted", NULL) || ++ of_get_property(np, "wp-inverted", NULL)) + return true; + + /* Old device trees don't have the wp-inverted property. */ +@@ -59,21 +72,45 @@ void sdhci_get_of_property(struct platform_device *pdev) + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + const __be32 *clk; ++ u32 bus_width; + int size; + + if (of_device_is_available(np)) { + if (of_get_property(np, "sdhci,auto-cmd12", NULL)) + host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; + +- if (of_get_property(np, "sdhci,1-bit-only", NULL)) ++ if (of_get_property(np, "sdhci,1-bit-only", NULL) || ++ (of_property_read_u32(np, "bus-width", &bus_width) == 0 && ++ bus_width == 1)) + host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; + + if (sdhci_of_wp_inverted(np)) + host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; + ++ if (of_get_property(np, "broken-cd", NULL)) ++ host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; ++ ++ if (of_get_property(np, "no-1-8-v", NULL)) ++ host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; ++ ++ if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc")) ++ host->quirks |= SDHCI_QUIRK_BROKEN_DMA; ++ ++ if (of_device_is_compatible(np, "fsl,p2020-esdhc") || ++ of_device_is_compatible(np, "fsl,p1010-esdhc") || ++ of_device_is_compatible(np, "fsl,t4240-esdhc") || ++ of_device_is_compatible(np, "fsl,mpc8536-esdhc")) ++ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; ++ + clk = of_get_property(np, "clock-frequency", &size); + if (clk && size == sizeof(*clk) && *clk) + pltfm_host->clock = be32_to_cpup(clk); ++ ++ if (of_find_property(np, "keep-power-in-suspend", NULL)) ++ host->mmc->pm_caps |= MMC_PM_KEEP_POWER; ++ ++ if (of_find_property(np, "enable-sdio-wakeup", NULL)) ++ host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; + } + } + #else +@@ -82,10 +119,10 @@ void sdhci_get_of_property(struct platform_device *pdev) {} + EXPORT_SYMBOL_GPL(sdhci_get_of_property); + + struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, +- struct sdhci_pltfm_data *pdata) ++ const struct sdhci_pltfm_data *pdata, ++ size_t priv_size) + { + struct sdhci_host *host; +- struct sdhci_pltfm_host *pltfm_host; + struct device_node *np = pdev->dev.of_node; + struct resource *iomem; + int ret; +@@ -101,24 +138,27 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, + + /* Some PCI-based MFD need the parent here */ + if (pdev->dev.parent != &platform_bus && !np) +- host = sdhci_alloc_host(pdev->dev.parent, sizeof(*pltfm_host)); ++ host = sdhci_alloc_host(pdev->dev.parent, ++ sizeof(struct sdhci_pltfm_host) + priv_size); + else +- host = sdhci_alloc_host(&pdev->dev, sizeof(*pltfm_host)); ++ host = sdhci_alloc_host(&pdev->dev, ++ sizeof(struct sdhci_pltfm_host) + priv_size); + + if (IS_ERR(host)) { + ret = PTR_ERR(host); + goto err; + } + +- pltfm_host = sdhci_priv(host); +- + host->hw_name = dev_name(&pdev->dev); + if (pdata && pdata->ops) + host->ops = pdata->ops; + else + host->ops = &sdhci_pltfm_ops; +- if (pdata) ++ if (pdata) { + host->quirks = pdata->quirks; ++ host->quirks2 = pdata->quirks2; ++ } ++ + host->irq = platform_get_irq(pdev, 0); + + if (!request_mem_region(iomem->start, resource_size(iomem), +@@ -135,6 +175,13 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, + goto err_remap; + } + ++ /* ++ * Some platforms need to probe the controller to be able to ++ * determine which caps should be used. ++ */ ++ if (host->ops && host->ops->platform_init) ++ host->ops->platform_init(host); ++ + platform_set_drvdata(pdev, host); + + return host; +@@ -157,17 +204,17 @@ void sdhci_pltfm_free(struct platform_device *pdev) + iounmap(host->ioaddr); + release_mem_region(iomem->start, resource_size(iomem)); + sdhci_free_host(host); +- platform_set_drvdata(pdev, NULL); + } + EXPORT_SYMBOL_GPL(sdhci_pltfm_free); + + int sdhci_pltfm_register(struct platform_device *pdev, +- struct sdhci_pltfm_data *pdata) ++ const struct sdhci_pltfm_data *pdata, ++ size_t priv_size) + { + struct sdhci_host *host; + int ret = 0; + +- host = sdhci_pltfm_init(pdev, pdata); ++ host = sdhci_pltfm_init(pdev, pdata, priv_size); + if (IS_ERR(host)) + return PTR_ERR(host); + +@@ -194,19 +241,21 @@ int sdhci_pltfm_unregister(struct platform_device *pdev) + EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister); + + #ifdef CONFIG_PM +-static int sdhci_pltfm_suspend(struct device *dev) ++int sdhci_pltfm_suspend(struct device *dev) + { + struct sdhci_host *host = dev_get_drvdata(dev); + + return sdhci_suspend_host(host); + } ++EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend); + +-static int sdhci_pltfm_resume(struct device *dev) ++int sdhci_pltfm_resume(struct device *dev) + { + struct sdhci_host *host = dev_get_drvdata(dev); + + return sdhci_resume_host(host); + } ++EXPORT_SYMBOL_GPL(sdhci_pltfm_resume); + + const struct dev_pm_ops sdhci_pltfm_pmops = { + .suspend = sdhci_pltfm_suspend, +diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h +index 37e0e18..04bc248 100644 +--- a/drivers/mmc/host/sdhci-pltfm.h ++++ b/drivers/mmc/host/sdhci-pltfm.h +@@ -16,8 +16,9 @@ + #include "sdhci.h" + + struct sdhci_pltfm_data { +- struct sdhci_ops *ops; ++ const struct sdhci_ops *ops; + unsigned int quirks; ++ unsigned int quirks2; + }; + + struct sdhci_pltfm_host { +@@ -27,6 +28,8 @@ struct sdhci_pltfm_host { + /* migrate from sdhci_of_host */ + unsigned int clock; + u16 xfer_mode_shadow; ++ ++ unsigned long private[0] ____cacheline_aligned; + }; + + #ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER +@@ -91,14 +94,25 @@ static inline void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg) + extern void sdhci_get_of_property(struct platform_device *pdev); + + extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, +- struct sdhci_pltfm_data *pdata); ++ const struct sdhci_pltfm_data *pdata, ++ size_t priv_size); + extern void sdhci_pltfm_free(struct platform_device *pdev); + + extern int sdhci_pltfm_register(struct platform_device *pdev, +- struct sdhci_pltfm_data *pdata); ++ const struct sdhci_pltfm_data *pdata, ++ size_t priv_size); + extern int sdhci_pltfm_unregister(struct platform_device *pdev); + ++extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host); ++ ++static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host) ++{ ++ return (void *)host->private; ++} ++ + #ifdef CONFIG_PM ++extern int sdhci_pltfm_suspend(struct device *dev); ++extern int sdhci_pltfm_resume(struct device *dev); + extern const struct dev_pm_ops sdhci_pltfm_pmops; + #define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops) + #else +diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c +index 7a039c3..3c0f3c0 100644 +--- a/drivers/mmc/host/sdhci-pxav2.c ++++ b/drivers/mmc/host/sdhci-pxav2.c +@@ -28,6 +28,9 @@ + #include + #include + #include ++#include ++#include ++ + #include "sdhci.h" + #include "sdhci-pltfm.h" + +@@ -48,11 +51,13 @@ + #define MMC_CARD 0x1000 + #define MMC_WIDTH 0x0100 + +-static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask) ++static void pxav2_reset(struct sdhci_host *host, u8 mask) + { + struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; + ++ sdhci_reset(host, mask); ++ + if (mask == SDHCI_RESET_ALL) { + u16 tmp = 0; + +@@ -85,7 +90,7 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask) + } + } + +-static int pxav2_mmc_set_width(struct sdhci_host *host, int width) ++static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width) + { + u8 ctrl; + u16 tmp; +@@ -104,30 +109,67 @@ static int pxav2_mmc_set_width(struct sdhci_host *host, int width) + } + writew(tmp, host->ioaddr + SD_CE_ATA_2); + writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); +- +- return 0; + } + +-static u32 pxav2_get_max_clock(struct sdhci_host *host) ++static const struct sdhci_ops pxav2_sdhci_ops = { ++ .set_clock = sdhci_set_clock, ++ .get_max_clock = sdhci_pltfm_clk_get_max_clock, ++ .set_bus_width = pxav2_mmc_set_bus_width, ++ .reset = pxav2_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++}; ++ ++#ifdef CONFIG_OF ++static const struct of_device_id sdhci_pxav2_of_match[] = { ++ { ++ .compatible = "mrvl,pxav2-mmc", ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, sdhci_pxav2_of_match); ++ ++static struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev) + { +- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_pxa_platdata *pdata; ++ struct device_node *np = dev->of_node; ++ u32 bus_width; ++ u32 clk_delay_cycles; ++ ++ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return NULL; ++ ++ if (of_find_property(np, "non-removable", NULL)) ++ pdata->flags |= PXA_FLAG_CARD_PERMANENT; ++ ++ of_property_read_u32(np, "bus-width", &bus_width); ++ if (bus_width == 8) ++ pdata->flags |= PXA_FLAG_SD_8_BIT_CAPABLE_SLOT; ++ ++ of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles); ++ if (clk_delay_cycles > 0) { ++ pdata->clk_delay_sel = 1; ++ pdata->clk_delay_cycles = clk_delay_cycles; ++ } + +- return clk_get_rate(pltfm_host->clk); ++ return pdata; + } ++#else ++static inline struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev) ++{ ++ return NULL; ++} ++#endif + +-static struct sdhci_ops pxav2_sdhci_ops = { +- .get_max_clock = pxav2_get_max_clock, +- .platform_reset_exit = pxav2_set_private_registers, +- .platform_8bit_width = pxav2_mmc_set_width, +-}; +- +-static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) ++static int sdhci_pxav2_probe(struct platform_device *pdev) + { + struct sdhci_pltfm_host *pltfm_host; + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct sdhci_host *host = NULL; + struct sdhci_pxa *pxa = NULL; ++ const struct of_device_id *match; ++ + int ret; + struct clk *clk; + +@@ -135,7 +177,7 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) + if (!pxa) + return -ENOMEM; + +- host = sdhci_pltfm_init(pdev, NULL); ++ host = sdhci_pltfm_init(pdev, NULL, 0); + if (IS_ERR(host)) { + kfree(pxa); + return PTR_ERR(host); +@@ -150,12 +192,16 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) + goto err_clk_get; + } + pltfm_host->clk = clk; +- clk_enable(clk); ++ clk_prepare_enable(clk); + + host->quirks = SDHCI_QUIRK_BROKEN_ADMA + | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL + | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN; + ++ match = of_match_device(of_match_ptr(sdhci_pxav2_of_match), &pdev->dev); ++ if (match) { ++ pdata = pxav2_get_mmc_pdata(dev); ++ } + if (pdata) { + if (pdata->flags & PXA_FLAG_CARD_PERMANENT) { + /* on-chip device */ +@@ -188,7 +234,7 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) + return 0; + + err_add_host: +- clk_disable(clk); ++ clk_disable_unprepare(clk); + clk_put(clk); + err_clk_get: + sdhci_pltfm_free(pdev); +@@ -196,7 +242,7 @@ err_clk_get: + return ret; + } + +-static int __devexit sdhci_pxav2_remove(struct platform_device *pdev) ++static int sdhci_pxav2_remove(struct platform_device *pdev) + { + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +@@ -204,13 +250,11 @@ static int __devexit sdhci_pxav2_remove(struct platform_device *pdev) + + sdhci_remove_host(host, 1); + +- clk_disable(pltfm_host->clk); ++ clk_disable_unprepare(pltfm_host->clk); + clk_put(pltfm_host->clk); + sdhci_pltfm_free(pdev); + kfree(pxa); + +- platform_set_drvdata(pdev, NULL); +- + return 0; + } + +@@ -218,23 +262,16 @@ static struct platform_driver sdhci_pxav2_driver = { + .driver = { + .name = "sdhci-pxav2", + .owner = THIS_MODULE, ++#ifdef CONFIG_OF ++ .of_match_table = sdhci_pxav2_of_match, ++#endif + .pm = SDHCI_PLTFM_PMOPS, + }, + .probe = sdhci_pxav2_probe, +- .remove = __devexit_p(sdhci_pxav2_remove), ++ .remove = sdhci_pxav2_remove, + }; +-static int __init sdhci_pxav2_init(void) +-{ +- return platform_driver_register(&sdhci_pxav2_driver); +-} +- +-static void __exit sdhci_pxav2_exit(void) +-{ +- platform_driver_unregister(&sdhci_pxav2_driver); +-} + +-module_init(sdhci_pxav2_init); +-module_exit(sdhci_pxav2_exit); ++module_platform_driver(sdhci_pxav2_driver); + + MODULE_DESCRIPTION("SDHCI driver for pxav2"); + MODULE_AUTHOR("Marvell International Ltd."); +diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c +index 15673a7..f4f1289 100644 +--- a/drivers/mmc/host/sdhci-pxav3.c ++++ b/drivers/mmc/host/sdhci-pxav3.c +@@ -24,13 +24,23 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include ++#include ++#include ++#include ++#include ++#include ++ + #include "sdhci.h" + #include "sdhci-pltfm.h" + ++#define PXAV3_RPM_DELAY_MS 50 ++ + #define SD_CLOCK_BURST_SIZE_SETUP 0x10A + #define SDCLK_SEL 0x100 + #define SDCLK_DELAY_SHIFT 9 +@@ -48,11 +58,67 @@ + #define SDCE_MISC_INT (1<<2) + #define SDCE_MISC_INT_EN (1<<1) + +-static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask) ++/* ++ * These registers are relative to the second register region, for the ++ * MBus bridge. ++ */ ++#define SDHCI_WINDOW_CTRL(i) (0x80 + ((i) << 3)) ++#define SDHCI_WINDOW_BASE(i) (0x84 + ((i) << 3)) ++#define SDHCI_MAX_WIN_NUM 8 ++ ++static int mv_conf_mbus_windows(struct platform_device *pdev, ++ const struct mbus_dram_target_info *dram) ++{ ++ int i; ++ void __iomem *regs; ++ struct resource *res; ++ ++ if (!dram) { ++ dev_err(&pdev->dev, "no mbus dram info\n"); ++ return -EINVAL; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!res) { ++ dev_err(&pdev->dev, "cannot get mbus registers\n"); ++ return -EINVAL; ++ } ++ ++ regs = ioremap(res->start, resource_size(res)); ++ if (!regs) { ++ dev_err(&pdev->dev, "cannot map mbus registers\n"); ++ return -ENOMEM; ++ } ++ ++ for (i = 0; i < SDHCI_MAX_WIN_NUM; i++) { ++ writel(0, regs + SDHCI_WINDOW_CTRL(i)); ++ writel(0, regs + SDHCI_WINDOW_BASE(i)); ++ } ++ ++ for (i = 0; i < dram->num_cs; i++) { ++ const struct mbus_dram_window *cs = dram->cs + i; ++ ++ /* Write size, attributes and target id to control register */ ++ writel(((cs->size - 1) & 0xffff0000) | ++ (cs->mbus_attr << 8) | ++ (dram->mbus_dram_target_id << 4) | 1, ++ regs + SDHCI_WINDOW_CTRL(i)); ++ /* Write base address to base register */ ++ writel(cs->base, regs + SDHCI_WINDOW_BASE(i)); ++ } ++ ++ iounmap(regs); ++ ++ return 0; ++} ++ ++static void pxav3_reset(struct sdhci_host *host, u8 mask) + { + struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; + ++ sdhci_reset(host, mask); ++ + if (mask == SDHCI_RESET_ALL) { + /* + * tune timing of read data/command when crc error happen +@@ -120,7 +186,7 @@ static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode) + pxa->power_mode = power_mode; + } + +-static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) ++static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) + { + u16 ctrl_2; + +@@ -154,23 +220,71 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) + dev_dbg(mmc_dev(host->mmc), + "%s uhs = %d, ctrl_2 = %04X\n", + __func__, uhs, ctrl_2); +- +- return 0; + } + +-static struct sdhci_ops pxav3_sdhci_ops = { +- .platform_reset_exit = pxav3_set_private_registers, ++static const struct sdhci_ops pxav3_sdhci_ops = { ++ .set_clock = sdhci_set_clock, + .set_uhs_signaling = pxav3_set_uhs_signaling, + .platform_send_init_74_clocks = pxav3_gen_init_74_clocks, ++ .get_max_clock = sdhci_pltfm_clk_get_max_clock, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = pxav3_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++}; ++ ++static struct sdhci_pltfm_data sdhci_pxav3_pdata = { ++ .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK ++ | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC ++ | SDHCI_QUIRK_32BIT_ADMA_SIZE ++ | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, ++ .ops = &pxav3_sdhci_ops, ++}; ++ ++#ifdef CONFIG_OF ++static const struct of_device_id sdhci_pxav3_of_match[] = { ++ { ++ .compatible = "mrvl,pxav3-mmc", ++ }, ++ { ++ .compatible = "marvell,armada-380-sdhci", ++ }, ++ {}, + }; ++MODULE_DEVICE_TABLE(of, sdhci_pxav3_of_match); ++ ++static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) ++{ ++ struct sdhci_pxa_platdata *pdata; ++ struct device_node *np = dev->of_node; ++ u32 clk_delay_cycles; ++ ++ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return NULL; + +-static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) ++ of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles); ++ if (clk_delay_cycles > 0) ++ pdata->clk_delay_cycles = clk_delay_cycles; ++ ++ return pdata; ++} ++#else ++static inline struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) ++{ ++ return NULL; ++} ++#endif ++ ++static int sdhci_pxav3_probe(struct platform_device *pdev) + { + struct sdhci_pltfm_host *pltfm_host; + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; ++ struct device_node *np = pdev->dev.of_node; + struct sdhci_host *host = NULL; + struct sdhci_pxa *pxa = NULL; ++ const struct of_device_id *match; ++ + int ret; + struct clk *clk; + +@@ -178,36 +292,45 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) + if (!pxa) + return -ENOMEM; + +- host = sdhci_pltfm_init(pdev, NULL); ++ host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata, 0); + if (IS_ERR(host)) { + kfree(pxa); + return PTR_ERR(host); + } ++ ++ if (of_device_is_compatible(np, "marvell,armada-380-sdhci")) { ++ ret = mv_conf_mbus_windows(pdev, mv_mbus_dram_info()); ++ if (ret < 0) ++ goto err_mbus_win; ++ } ++ ++ + pltfm_host = sdhci_priv(host); + pltfm_host->priv = pxa; + +- clk = clk_get(dev, "PXA-SDHCLK"); ++ clk = clk_get(dev, NULL); + if (IS_ERR(clk)) { + dev_err(dev, "failed to get io clock\n"); + ret = PTR_ERR(clk); + goto err_clk_get; + } + pltfm_host->clk = clk; +- clk_enable(clk); +- +- host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL +- | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC +- | SDHCI_QUIRK_32BIT_ADMA_SIZE; ++ clk_prepare_enable(clk); + + /* enable 1/8V DDR capable */ + host->mmc->caps |= MMC_CAP_1_8V_DDR; + +- if (pdata) { +- if (pdata->flags & PXA_FLAG_CARD_PERMANENT) { +- /* on-chip device */ +- host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; ++ match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev); ++ if (match) { ++ ret = mmc_of_parse(host->mmc); ++ if (ret) ++ goto err_of_parse; ++ sdhci_get_of_property(pdev); ++ pdata = pxav3_get_mmc_pdata(dev); ++ } else if (pdata) { ++ /* on-chip device */ ++ if (pdata->flags & PXA_FLAG_CARD_PERMANENT) + host->mmc->caps |= MMC_CAP_NONREMOVABLE; +- } + + /* If slot design supports 8 bit data, indicate this to MMC. */ + if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT) +@@ -215,13 +338,31 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) + + if (pdata->quirks) + host->quirks |= pdata->quirks; ++ if (pdata->quirks2) ++ host->quirks2 |= pdata->quirks2; + if (pdata->host_caps) + host->mmc->caps |= pdata->host_caps; ++ if (pdata->host_caps2) ++ host->mmc->caps2 |= pdata->host_caps2; + if (pdata->pm_caps) + host->mmc->pm_caps |= pdata->pm_caps; ++ ++ if (gpio_is_valid(pdata->ext_cd_gpio)) { ++ ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio, ++ 0); ++ if (ret) { ++ dev_err(mmc_dev(host->mmc), ++ "failed to allocate card detect gpio\n"); ++ goto err_cd_req; ++ } ++ } + } + +- host->ops = &pxav3_sdhci_ops; ++ pm_runtime_enable(&pdev->dev); ++ pm_runtime_get_sync(&pdev->dev); ++ pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS); ++ pm_runtime_use_autosuspend(&pdev->dev); ++ pm_suspend_ignore_children(&pdev->dev, 1); + + ret = sdhci_add_host(host); + if (ret) { +@@ -231,56 +372,141 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, host); + ++ if (host->mmc->pm_caps & MMC_PM_KEEP_POWER) { ++ device_init_wakeup(&pdev->dev, 1); ++ host->mmc->pm_flags |= MMC_PM_WAKE_SDIO_IRQ; ++ } else { ++ device_init_wakeup(&pdev->dev, 0); ++ } ++ ++ pm_runtime_put_autosuspend(&pdev->dev); ++ + return 0; + ++err_of_parse: ++err_cd_req: + err_add_host: +- clk_disable(clk); ++ pm_runtime_put_sync(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ clk_disable_unprepare(clk); + clk_put(clk); + err_clk_get: ++err_mbus_win: + sdhci_pltfm_free(pdev); + kfree(pxa); + return ret; + } + +-static int __devexit sdhci_pxav3_remove(struct platform_device *pdev) ++static int sdhci_pxav3_remove(struct platform_device *pdev) + { + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_pxa *pxa = pltfm_host->priv; + ++ pm_runtime_get_sync(&pdev->dev); + sdhci_remove_host(host, 1); ++ pm_runtime_disable(&pdev->dev); + +- clk_disable(pltfm_host->clk); ++ clk_disable_unprepare(pltfm_host->clk); + clk_put(pltfm_host->clk); ++ + sdhci_pltfm_free(pdev); + kfree(pxa); + +- platform_set_drvdata(pdev, NULL); ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int sdhci_pxav3_suspend(struct device *dev) ++{ ++ int ret; ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ ++ pm_runtime_get_sync(dev); ++ ret = sdhci_suspend_host(host); ++ pm_runtime_mark_last_busy(dev); ++ pm_runtime_put_autosuspend(dev); ++ ++ return ret; ++} ++ ++static int sdhci_pxav3_resume(struct device *dev) ++{ ++ int ret; ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ ++ pm_runtime_get_sync(dev); ++ ret = sdhci_resume_host(host); ++ pm_runtime_mark_last_busy(dev); ++ pm_runtime_put_autosuspend(dev); ++ ++ return ret; ++} ++#endif ++ ++#ifdef CONFIG_PM_RUNTIME ++static int sdhci_pxav3_runtime_suspend(struct device *dev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ unsigned long flags; ++ ++ if (pltfm_host->clk) { ++ spin_lock_irqsave(&host->lock, flags); ++ host->runtime_suspended = true; ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ clk_disable_unprepare(pltfm_host->clk); ++ } + + return 0; + } + ++static int sdhci_pxav3_runtime_resume(struct device *dev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ unsigned long flags; ++ ++ if (pltfm_host->clk) { ++ clk_prepare_enable(pltfm_host->clk); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ host->runtime_suspended = false; ++ spin_unlock_irqrestore(&host->lock, flags); ++ } ++ ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_PM ++static const struct dev_pm_ops sdhci_pxav3_pmops = { ++ SET_SYSTEM_SLEEP_PM_OPS(sdhci_pxav3_suspend, sdhci_pxav3_resume) ++ SET_RUNTIME_PM_OPS(sdhci_pxav3_runtime_suspend, ++ sdhci_pxav3_runtime_resume, NULL) ++}; ++ ++#define SDHCI_PXAV3_PMOPS (&sdhci_pxav3_pmops) ++ ++#else ++#define SDHCI_PXAV3_PMOPS NULL ++#endif ++ + static struct platform_driver sdhci_pxav3_driver = { + .driver = { + .name = "sdhci-pxav3", ++#ifdef CONFIG_OF ++ .of_match_table = sdhci_pxav3_of_match, ++#endif + .owner = THIS_MODULE, +- .pm = SDHCI_PLTFM_PMOPS, ++ .pm = SDHCI_PXAV3_PMOPS, + }, + .probe = sdhci_pxav3_probe, +- .remove = __devexit_p(sdhci_pxav3_remove), ++ .remove = sdhci_pxav3_remove, + }; +-static int __init sdhci_pxav3_init(void) +-{ +- return platform_driver_register(&sdhci_pxav3_driver); +-} +- +-static void __exit sdhci_pxav3_exit(void) +-{ +- platform_driver_unregister(&sdhci_pxav3_driver); +-} + +-module_init(sdhci_pxav3_init); +-module_exit(sdhci_pxav3_exit); ++module_platform_driver(sdhci_pxav3_driver); + + MODULE_DESCRIPTION("SDHCI driver for pxav3"); + MODULE_AUTHOR("Marvell International Ltd."); +diff --git a/drivers/mmc/host/sdhci-s3c-regs.h b/drivers/mmc/host/sdhci-s3c-regs.h +new file mode 100644 +index 0000000..e34049a +--- /dev/null ++++ b/drivers/mmc/host/sdhci-s3c-regs.h +@@ -0,0 +1,87 @@ ++/* linux/arch/arm/plat-s3c/include/plat/regs-sdhci.h ++ * ++ * Copyright 2008 Openmoko, Inc. ++ * Copyright 2008 Simtec Electronics ++ * http://armlinux.simtec.co.uk/ ++ * Ben Dooks ++ * ++ * S3C Platform - SDHCI (HSMMC) register definitions ++ * ++ * 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 __PLAT_S3C_SDHCI_REGS_H ++#define __PLAT_S3C_SDHCI_REGS_H __FILE__ ++ ++#define S3C_SDHCI_CONTROL2 (0x80) ++#define S3C_SDHCI_CONTROL3 (0x84) ++#define S3C64XX_SDHCI_CONTROL4 (0x8C) ++ ++#define S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR (1 << 31) ++#define S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK (1 << 30) ++#define S3C_SDHCI_CTRL2_CDINVRXD3 (1 << 29) ++#define S3C_SDHCI_CTRL2_SLCARDOUT (1 << 28) ++ ++#define S3C_SDHCI_CTRL2_FLTCLKSEL_MASK (0xf << 24) ++#define S3C_SDHCI_CTRL2_FLTCLKSEL_SHIFT (24) ++#define S3C_SDHCI_CTRL2_FLTCLKSEL(_x) ((_x) << 24) ++ ++#define S3C_SDHCI_CTRL2_LVLDAT_MASK (0xff << 16) ++#define S3C_SDHCI_CTRL2_LVLDAT_SHIFT (16) ++#define S3C_SDHCI_CTRL2_LVLDAT(_x) ((_x) << 16) ++ ++#define S3C_SDHCI_CTRL2_ENFBCLKTX (1 << 15) ++#define S3C_SDHCI_CTRL2_ENFBCLKRX (1 << 14) ++#define S3C_SDHCI_CTRL2_SDCDSEL (1 << 13) ++#define S3C_SDHCI_CTRL2_SDSIGPC (1 << 12) ++#define S3C_SDHCI_CTRL2_ENBUSYCHKTXSTART (1 << 11) ++ ++#define S3C_SDHCI_CTRL2_DFCNT_MASK (0x3 << 9) ++#define S3C_SDHCI_CTRL2_DFCNT_SHIFT (9) ++#define S3C_SDHCI_CTRL2_DFCNT_NONE (0x0 << 9) ++#define S3C_SDHCI_CTRL2_DFCNT_4SDCLK (0x1 << 9) ++#define S3C_SDHCI_CTRL2_DFCNT_16SDCLK (0x2 << 9) ++#define S3C_SDHCI_CTRL2_DFCNT_64SDCLK (0x3 << 9) ++ ++#define S3C_SDHCI_CTRL2_ENCLKOUTHOLD (1 << 8) ++#define S3C_SDHCI_CTRL2_RWAITMODE (1 << 7) ++#define S3C_SDHCI_CTRL2_DISBUFRD (1 << 6) ++#define S3C_SDHCI_CTRL2_SELBASECLK_MASK (0x3 << 4) ++#define S3C_SDHCI_CTRL2_SELBASECLK_SHIFT (4) ++#define S3C_SDHCI_CTRL2_PWRSYNC (1 << 3) ++#define S3C_SDHCI_CTRL2_ENCLKOUTMSKCON (1 << 1) ++#define S3C_SDHCI_CTRL2_HWINITFIN (1 << 0) ++ ++#define S3C_SDHCI_CTRL3_FCSEL3 (1 << 31) ++#define S3C_SDHCI_CTRL3_FCSEL2 (1 << 23) ++#define S3C_SDHCI_CTRL3_FCSEL1 (1 << 15) ++#define S3C_SDHCI_CTRL3_FCSEL0 (1 << 7) ++ ++#define S3C_SDHCI_CTRL3_FIA3_MASK (0x7f << 24) ++#define S3C_SDHCI_CTRL3_FIA3_SHIFT (24) ++#define S3C_SDHCI_CTRL3_FIA3(_x) ((_x) << 24) ++ ++#define S3C_SDHCI_CTRL3_FIA2_MASK (0x7f << 16) ++#define S3C_SDHCI_CTRL3_FIA2_SHIFT (16) ++#define S3C_SDHCI_CTRL3_FIA2(_x) ((_x) << 16) ++ ++#define S3C_SDHCI_CTRL3_FIA1_MASK (0x7f << 8) ++#define S3C_SDHCI_CTRL3_FIA1_SHIFT (8) ++#define S3C_SDHCI_CTRL3_FIA1(_x) ((_x) << 8) ++ ++#define S3C_SDHCI_CTRL3_FIA0_MASK (0x7f << 0) ++#define S3C_SDHCI_CTRL3_FIA0_SHIFT (0) ++#define S3C_SDHCI_CTRL3_FIA0(_x) ((_x) << 0) ++ ++#define S3C64XX_SDHCI_CONTROL4_DRIVE_MASK (0x3 << 16) ++#define S3C64XX_SDHCI_CONTROL4_DRIVE_SHIFT (16) ++#define S3C64XX_SDHCI_CONTROL4_DRIVE_2mA (0x0 << 16) ++#define S3C64XX_SDHCI_CONTROL4_DRIVE_4mA (0x1 << 16) ++#define S3C64XX_SDHCI_CONTROL4_DRIVE_7mA (0x2 << 16) ++#define S3C64XX_SDHCI_CONTROL4_DRIVE_9mA (0x3 << 16) ++ ++#define S3C64XX_SDHCI_CONTROL4_BUSY (1) ++ ++#endif /* __PLAT_S3C_SDHCI_REGS_H */ +diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c +index 06af9e4..fa5954a 100644 +--- a/drivers/mmc/host/sdhci-s3c.c ++++ b/drivers/mmc/host/sdhci-s3c.c +@@ -15,17 +15,20 @@ + #include + #include + #include ++#include + #include + #include + #include + #include + #include ++#include ++#include ++#include ++#include + + #include + +-#include +-#include +- ++#include "sdhci-s3c-regs.h" + #include "sdhci.h" + + #define MAX_BUS_CLK (4) +@@ -45,43 +48,33 @@ struct sdhci_s3c { + struct platform_device *pdev; + struct resource *ioarea; + struct s3c_sdhci_platdata *pdata; +- unsigned int cur_clk; ++ int cur_clk; + int ext_cd_irq; + int ext_cd_gpio; + + struct clk *clk_io; + struct clk *clk_bus[MAX_BUS_CLK]; +-}; ++ unsigned long clk_rates[MAX_BUS_CLK]; + +-static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host) +-{ +- return sdhci_priv(host); +-} ++ bool no_divider; ++}; + + /** +- * get_curclk - convert ctrl2 register to clock source number +- * @ctrl2: Control2 register value. ++ * struct sdhci_s3c_driver_data - S3C SDHCI platform specific driver data ++ * @sdhci_quirks: sdhci host specific quirks. ++ * ++ * Specifies platform specific configuration of sdhci controller. ++ * Note: A structure for driver specific platform data is used for future ++ * expansion of its usage. + */ +-static u32 get_curclk(u32 ctrl2) +-{ +- ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK; +- ctrl2 >>= S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; +- +- return ctrl2; +-} ++struct sdhci_s3c_drv_data { ++ unsigned int sdhci_quirks; ++ bool no_divider; ++}; + +-static void sdhci_s3c_check_sclk(struct sdhci_host *host) ++static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host) + { +- struct sdhci_s3c *ourhost = to_s3c(host); +- u32 tmp = readl(host->ioaddr + S3C_SDHCI_CONTROL2); +- +- if (get_curclk(tmp) != ourhost->cur_clk) { +- dev_dbg(&ourhost->pdev->dev, "restored ctrl2 clock setting\n"); +- +- tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; +- tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; +- writel(tmp, host->ioaddr + 0x80); +- } ++ return sdhci_priv(host); + } + + /** +@@ -93,20 +86,11 @@ static void sdhci_s3c_check_sclk(struct sdhci_host *host) + static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host) + { + struct sdhci_s3c *ourhost = to_s3c(host); +- struct clk *busclk; +- unsigned int rate, max; +- int clk; +- +- /* note, a reset will reset the clock source */ +- +- sdhci_s3c_check_sclk(host); +- +- for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) { +- busclk = ourhost->clk_bus[clk]; +- if (!busclk) +- continue; ++ unsigned long rate, max = 0; ++ int src; + +- rate = clk_get_rate(busclk); ++ for (src = 0; src < MAX_BUS_CLK; src++) { ++ rate = ourhost->clk_rates[src]; + if (rate > max) + max = rate; + } +@@ -126,31 +110,38 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, + { + unsigned long rate; + struct clk *clksrc = ourhost->clk_bus[src]; +- int div; ++ int shift; + +- if (!clksrc) ++ if (IS_ERR(clksrc)) + return UINT_MAX; + + /* +- * Clock divider's step is different as 1 from that of host controller +- * when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL. ++ * If controller uses a non-standard clock division, find the best clock ++ * speed possible with selected clock source and skip the division. + */ +- if (ourhost->pdata->clk_type) { ++ if (ourhost->no_divider) { + rate = clk_round_rate(clksrc, wanted); + return wanted - rate; + } + +- rate = clk_get_rate(clksrc); ++ rate = ourhost->clk_rates[src]; + +- for (div = 1; div < 256; div *= 2) { +- if ((rate / div) <= wanted) ++ for (shift = 0; shift <= 8; ++shift) { ++ if ((rate >> shift) <= wanted) + break; + } + ++ if (shift > 8) { ++ dev_dbg(&ourhost->pdev->dev, ++ "clk %d: rate %ld, min rate %lu > wanted %u\n", ++ src, rate, rate / 256, wanted); ++ return UINT_MAX; ++ } ++ + dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n", +- src, rate, wanted, rate / div); ++ src, rate, wanted, rate >> shift); + +- return (wanted - (rate / div)); ++ return wanted - (rate >> shift); + } + + /** +@@ -170,9 +161,13 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) + int src; + u32 ctrl; + ++ host->mmc->actual_clock = 0; ++ + /* don't bother if the clock is going off. */ +- if (clock == 0) ++ if (clock == 0) { ++ sdhci_set_clock(host, clock); + return; ++ } + + for (src = 0; src < MAX_BUS_CLK; src++) { + delta = sdhci_s3c_consider_clock(ourhost, src, clock); +@@ -187,22 +182,26 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) + best_src, clock, best); + + /* select the new clock source */ +- + if (ourhost->cur_clk != best_src) { + struct clk *clk = ourhost->clk_bus[best_src]; + +- /* turn clock off to card before changing clock source */ +- writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); ++ clk_prepare_enable(clk); ++ if (ourhost->cur_clk >= 0) ++ clk_disable_unprepare( ++ ourhost->clk_bus[ourhost->cur_clk]); + + ourhost->cur_clk = best_src; +- host->max_clk = clk_get_rate(clk); +- +- ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2); +- ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; +- ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; +- writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2); ++ host->max_clk = ourhost->clk_rates[best_src]; + } + ++ /* turn clock off to card before changing clock source */ ++ writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); ++ ++ ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2); ++ ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; ++ ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; ++ writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2); ++ + /* reprogram default hardware configuration */ + writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, + host->ioaddr + S3C64XX_SDHCI_CONTROL4); +@@ -220,6 +219,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) + if (clock < 25 * 1000000) + ctrl |= (S3C_SDHCI_CTRL3_FCSEL3 | S3C_SDHCI_CTRL3_FCSEL2); + writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL3); ++ ++ sdhci_set_clock(host, clock); + } + + /** +@@ -234,17 +235,17 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) + static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host) + { + struct sdhci_s3c *ourhost = to_s3c(host); +- unsigned int delta, min = UINT_MAX; ++ unsigned long rate, min = ULONG_MAX; + int src; + + for (src = 0; src < MAX_BUS_CLK; src++) { +- delta = sdhci_s3c_consider_clock(ourhost, src, 0); +- if (delta == UINT_MAX) ++ rate = ourhost->clk_rates[src] / 256; ++ if (!rate) + continue; +- /* delta is a negative value in this case */ +- if (-delta < min) +- min = -delta; ++ if (rate < min) ++ min = rate; + } ++ + return min; + } + +@@ -252,47 +253,95 @@ static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host) + static unsigned int sdhci_cmu_get_max_clock(struct sdhci_host *host) + { + struct sdhci_s3c *ourhost = to_s3c(host); ++ unsigned long rate, max = 0; ++ int src; ++ ++ for (src = 0; src < MAX_BUS_CLK; src++) { ++ struct clk *clk; ++ ++ clk = ourhost->clk_bus[src]; ++ if (IS_ERR(clk)) ++ continue; ++ ++ rate = clk_round_rate(clk, ULONG_MAX); ++ if (rate > max) ++ max = rate; ++ } + +- return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], UINT_MAX); ++ return max; + } + + /* sdhci_cmu_get_min_clock - callback to get minimal supported clock value. */ + static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host) + { + struct sdhci_s3c *ourhost = to_s3c(host); ++ unsigned long rate, min = ULONG_MAX; ++ int src; + +- /* +- * initial clock can be in the frequency range of +- * 100KHz-400KHz, so we set it as max value. +- */ +- return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], 400000); ++ for (src = 0; src < MAX_BUS_CLK; src++) { ++ struct clk *clk; ++ ++ clk = ourhost->clk_bus[src]; ++ if (IS_ERR(clk)) ++ continue; ++ ++ rate = clk_round_rate(clk, 0); ++ if (rate < min) ++ min = rate; ++ } ++ ++ return min; + } + + /* sdhci_cmu_set_clock - callback on clock change.*/ + static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) + { + struct sdhci_s3c *ourhost = to_s3c(host); ++ struct device *dev = &ourhost->pdev->dev; ++ unsigned long timeout; ++ u16 clk = 0; ++ ++ host->mmc->actual_clock = 0; + +- /* don't bother if the clock is going off */ +- if (clock == 0) ++ /* If the clock is going off, set to 0 at clock control register */ ++ if (clock == 0) { ++ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + return; ++ } + + sdhci_s3c_set_clock(host, clock); + + clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock); + +- host->clock = clock; ++ clk = SDHCI_CLOCK_INT_EN; ++ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); ++ ++ /* Wait max 20 ms */ ++ timeout = 20; ++ while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) ++ & SDHCI_CLOCK_INT_STABLE)) { ++ if (timeout == 0) { ++ dev_err(dev, "%s: Internal clock never stabilised.\n", ++ mmc_hostname(host->mmc)); ++ return; ++ } ++ timeout--; ++ mdelay(1); ++ } ++ ++ clk |= SDHCI_CLOCK_CARD_EN; ++ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + } + + /** +- * sdhci_s3c_platform_8bit_width - support 8bit buswidth ++ * sdhci_s3c_set_bus_width - support 8bit buswidth + * @host: The SDHCI host being queried + * @width: MMC_BUS_WIDTH_ macro for the bus width being requested + * + * We have 8-bit width support but is not a v3 controller. +- * So we add platform_8bit_width() and support 8bit width. ++ * So we add platform_bus_width() and support 8bit width. + */ +-static int sdhci_s3c_platform_8bit_width(struct sdhci_host *host, int width) ++static void sdhci_s3c_set_bus_width(struct sdhci_host *host, int width) + { + u8 ctrl; + +@@ -314,84 +363,82 @@ static int sdhci_s3c_platform_8bit_width(struct sdhci_host *host, int width) + } + + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); +- +- return 0; + } + + static struct sdhci_ops sdhci_s3c_ops = { + .get_max_clock = sdhci_s3c_get_max_clk, + .set_clock = sdhci_s3c_set_clock, + .get_min_clock = sdhci_s3c_get_min_clock, +- .platform_8bit_width = sdhci_s3c_platform_8bit_width, ++ .set_bus_width = sdhci_s3c_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, + }; + +-static void sdhci_s3c_notify_change(struct platform_device *dev, int state) ++#ifdef CONFIG_OF ++static int sdhci_s3c_parse_dt(struct device *dev, ++ struct sdhci_host *host, struct s3c_sdhci_platdata *pdata) + { +- struct sdhci_host *host = platform_get_drvdata(dev); +- unsigned long flags; +- +- if (host) { +- spin_lock_irqsave(&host->lock, flags); +- if (state) { +- dev_dbg(&dev->dev, "card inserted.\n"); +- host->flags &= ~SDHCI_DEVICE_DEAD; +- host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; +- } else { +- dev_dbg(&dev->dev, "card removed.\n"); +- host->flags |= SDHCI_DEVICE_DEAD; +- host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; +- } +- tasklet_schedule(&host->card_tasklet); +- spin_unlock_irqrestore(&host->lock, flags); ++ struct device_node *node = dev->of_node; ++ u32 max_width; ++ ++ /* if the bus-width property is not specified, assume width as 1 */ ++ if (of_property_read_u32(node, "bus-width", &max_width)) ++ max_width = 1; ++ pdata->max_width = max_width; ++ ++ /* get the card detection method */ ++ if (of_get_property(node, "broken-cd", NULL)) { ++ pdata->cd_type = S3C_SDHCI_CD_NONE; ++ return 0; ++ } ++ ++ if (of_get_property(node, "non-removable", NULL)) { ++ pdata->cd_type = S3C_SDHCI_CD_PERMANENT; ++ return 0; + } +-} + +-static irqreturn_t sdhci_s3c_gpio_card_detect_thread(int irq, void *dev_id) ++ if (of_get_named_gpio(node, "cd-gpios", 0)) ++ return 0; ++ ++ /* assuming internal card detect that will be configured by pinctrl */ ++ pdata->cd_type = S3C_SDHCI_CD_INTERNAL; ++ return 0; ++} ++#else ++static int sdhci_s3c_parse_dt(struct device *dev, ++ struct sdhci_host *host, struct s3c_sdhci_platdata *pdata) + { +- struct sdhci_s3c *sc = dev_id; +- int status = gpio_get_value(sc->ext_cd_gpio); +- if (sc->pdata->ext_cd_gpio_invert) +- status = !status; +- sdhci_s3c_notify_change(sc->pdev, status); +- return IRQ_HANDLED; ++ return -EINVAL; + } ++#endif + +-static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc) ++static const struct of_device_id sdhci_s3c_dt_match[]; ++ ++static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data( ++ struct platform_device *pdev) + { +- struct s3c_sdhci_platdata *pdata = sc->pdata; +- struct device *dev = &sc->pdev->dev; +- +- if (gpio_request(pdata->ext_cd_gpio, "SDHCI EXT CD") == 0) { +- sc->ext_cd_gpio = pdata->ext_cd_gpio; +- sc->ext_cd_irq = gpio_to_irq(pdata->ext_cd_gpio); +- if (sc->ext_cd_irq && +- request_threaded_irq(sc->ext_cd_irq, NULL, +- sdhci_s3c_gpio_card_detect_thread, +- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, +- dev_name(dev), sc) == 0) { +- int status = gpio_get_value(sc->ext_cd_gpio); +- if (pdata->ext_cd_gpio_invert) +- status = !status; +- sdhci_s3c_notify_change(sc->pdev, status); +- } else { +- dev_warn(dev, "cannot request irq for card detect\n"); +- sc->ext_cd_irq = 0; +- } +- } else { +- dev_err(dev, "cannot request gpio for card detect\n"); ++#ifdef CONFIG_OF ++ if (pdev->dev.of_node) { ++ const struct of_device_id *match; ++ match = of_match_node(sdhci_s3c_dt_match, pdev->dev.of_node); ++ return (struct sdhci_s3c_drv_data *)match->data; + } ++#endif ++ return (struct sdhci_s3c_drv_data *) ++ platform_get_device_id(pdev)->driver_data; + } + +-static int __devinit sdhci_s3c_probe(struct platform_device *pdev) ++static int sdhci_s3c_probe(struct platform_device *pdev) + { +- struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; ++ struct s3c_sdhci_platdata *pdata; ++ struct sdhci_s3c_drv_data *drv_data; + struct device *dev = &pdev->dev; + struct sdhci_host *host; + struct sdhci_s3c *sc; + struct resource *res; + int ret, irq, ptr, clks; + +- if (!pdata) { ++ if (!pdev->dev.platform_data && !pdev->dev.of_node) { + dev_err(dev, "no device data specified\n"); + return -ENOENT; + } +@@ -402,63 +449,60 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) + return irq; + } + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!res) { +- dev_err(dev, "no memory specified\n"); +- return -ENOENT; +- } +- + host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); + if (IS_ERR(host)) { + dev_err(dev, "sdhci_alloc_host() failed\n"); + return PTR_ERR(host); + } +- + sc = sdhci_priv(host); + ++ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) { ++ ret = -ENOMEM; ++ goto err_pdata_io_clk; ++ } ++ ++ if (pdev->dev.of_node) { ++ ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata); ++ if (ret) ++ goto err_pdata_io_clk; ++ } else { ++ memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); ++ sc->ext_cd_gpio = -1; /* invalid gpio number */ ++ } ++ ++ drv_data = sdhci_s3c_get_driver_data(pdev); ++ + sc->host = host; + sc->pdev = pdev; + sc->pdata = pdata; +- sc->ext_cd_gpio = -1; /* invalid gpio number */ ++ sc->cur_clk = -1; + + platform_set_drvdata(pdev, host); + +- sc->clk_io = clk_get(dev, "hsmmc"); ++ sc->clk_io = devm_clk_get(dev, "hsmmc"); + if (IS_ERR(sc->clk_io)) { + dev_err(dev, "failed to get io clock\n"); + ret = PTR_ERR(sc->clk_io); +- goto err_io_clk; ++ goto err_pdata_io_clk; + } + + /* enable the local io clock and keep it running for the moment. */ +- clk_enable(sc->clk_io); ++ clk_prepare_enable(sc->clk_io); + + for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { +- struct clk *clk; +- char *name = pdata->clocks[ptr]; +- +- if (name == NULL) +- continue; ++ char name[14]; + +- clk = clk_get(dev, name); +- if (IS_ERR(clk)) { +- dev_err(dev, "failed to get clock %s\n", name); ++ snprintf(name, 14, "mmc_busclk.%d", ptr); ++ sc->clk_bus[ptr] = devm_clk_get(dev, name); ++ if (IS_ERR(sc->clk_bus[ptr])) + continue; +- } + + clks++; +- sc->clk_bus[ptr] = clk; +- +- /* +- * save current clock index to know which clock bus +- * is used later in overriding functions. +- */ +- sc->cur_clk = ptr; +- +- clk_enable(clk); ++ sc->clk_rates[ptr] = clk_get_rate(sc->clk_bus[ptr]); + + dev_info(dev, "clock source %d: %s (%ld Hz)\n", +- ptr, name, clk_get_rate(clk)); ++ ptr, name, sc->clk_rates[ptr]); + } + + if (clks == 0) { +@@ -467,18 +511,10 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) + goto err_no_busclks; + } + +- sc->ioarea = request_mem_region(res->start, resource_size(res), +- mmc_hostname(host->mmc)); +- if (!sc->ioarea) { +- dev_err(dev, "failed to reserve register area\n"); +- ret = -ENXIO; +- goto err_req_regs; +- } +- +- host->ioaddr = ioremap_nocache(res->start, resource_size(res)); +- if (!host->ioaddr) { +- dev_err(dev, "failed to map registers\n"); +- ret = -ENXIO; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ host->ioaddr = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(host->ioaddr)) { ++ ret = PTR_ERR(host->ioaddr); + goto err_req_regs; + } + +@@ -489,11 +525,16 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) + host->hw_name = "samsung-hsmmc"; + host->ops = &sdhci_s3c_ops; + host->quirks = 0; ++ host->quirks2 = 0; + host->irq = irq; + + /* Setup quirks for the controller */ + host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; + host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; ++ if (drv_data) { ++ host->quirks |= drv_data->sdhci_quirks; ++ sc->no_divider = drv_data->no_divider; ++ } + + #ifndef CONFIG_MMC_SDHCI_S3C_DMA + +@@ -521,8 +562,16 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) + if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) + host->mmc->caps = MMC_CAP_NONREMOVABLE; + +- if (pdata->host_caps) +- host->mmc->caps |= pdata->host_caps; ++ switch (pdata->max_width) { ++ case 8: ++ host->mmc->caps |= MMC_CAP_8_BIT_DATA; ++ case 4: ++ host->mmc->caps |= MMC_CAP_4_BIT_DATA; ++ break; ++ } ++ ++ if (pdata->pm_caps) ++ host->mmc->pm_caps |= pdata->pm_caps; + + host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | + SDHCI_QUIRK_32BIT_DMA_SIZE); +@@ -534,7 +583,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) + * If controller does not have internal clock divider, + * we can use overriding functions instead of default. + */ +- if (pdata->clk_type) { ++ if (sc->no_divider) { + sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; + sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; + sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock; +@@ -544,84 +593,65 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) + if (pdata->host_caps) + host->mmc->caps |= pdata->host_caps; + ++ if (pdata->host_caps2) ++ host->mmc->caps2 |= pdata->host_caps2; ++ ++ pm_runtime_enable(&pdev->dev); ++ pm_runtime_set_autosuspend_delay(&pdev->dev, 50); ++ pm_runtime_use_autosuspend(&pdev->dev); ++ pm_suspend_ignore_children(&pdev->dev, 1); ++ ++ mmc_of_parse(host->mmc); ++ + ret = sdhci_add_host(host); + if (ret) { + dev_err(dev, "sdhci_add_host() failed\n"); +- goto err_add_host; ++ pm_runtime_forbid(&pdev->dev); ++ pm_runtime_get_noresume(&pdev->dev); ++ goto err_req_regs; + } + +- /* The following two methods of card detection might call +- sdhci_s3c_notify_change() immediately, so they can be called +- only after sdhci_add_host(). Setup errors are ignored. */ +- if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_init) +- pdata->ext_cd_init(&sdhci_s3c_notify_change); +- if (pdata->cd_type == S3C_SDHCI_CD_GPIO && +- gpio_is_valid(pdata->ext_cd_gpio)) +- sdhci_s3c_setup_card_detect_gpio(sc); +- ++#ifdef CONFIG_PM_RUNTIME ++ if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) ++ clk_disable_unprepare(sc->clk_io); ++#endif + return 0; + +- err_add_host: +- release_resource(sc->ioarea); +- kfree(sc->ioarea); +- + err_req_regs: +- for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { +- if (sc->clk_bus[ptr]) { +- clk_disable(sc->clk_bus[ptr]); +- clk_put(sc->clk_bus[ptr]); +- } +- } +- + err_no_busclks: +- clk_disable(sc->clk_io); +- clk_put(sc->clk_io); ++ clk_disable_unprepare(sc->clk_io); + +- err_io_clk: ++ err_pdata_io_clk: + sdhci_free_host(host); + + return ret; + } + +-static int __devexit sdhci_s3c_remove(struct platform_device *pdev) ++static int sdhci_s3c_remove(struct platform_device *pdev) + { +- struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_s3c *sc = sdhci_priv(host); +- int ptr; +- +- if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup) +- pdata->ext_cd_cleanup(&sdhci_s3c_notify_change); + + if (sc->ext_cd_irq) + free_irq(sc->ext_cd_irq, sc); + +- if (gpio_is_valid(sc->ext_cd_gpio)) +- gpio_free(sc->ext_cd_gpio); +- ++#ifdef CONFIG_PM_RUNTIME ++ if (sc->pdata->cd_type != S3C_SDHCI_CD_INTERNAL) ++ clk_prepare_enable(sc->clk_io); ++#endif + sdhci_remove_host(host, 1); + +- for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { +- if (sc->clk_bus[ptr]) { +- clk_disable(sc->clk_bus[ptr]); +- clk_put(sc->clk_bus[ptr]); +- } +- } +- clk_disable(sc->clk_io); +- clk_put(sc->clk_io); ++ pm_runtime_dont_use_autosuspend(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); + +- iounmap(host->ioaddr); +- release_resource(sc->ioarea); +- kfree(sc->ioarea); ++ clk_disable_unprepare(sc->clk_io); + + sdhci_free_host(host); +- platform_set_drvdata(pdev, NULL); + + return 0; + } + +-#ifdef CONFIG_PM +- ++#ifdef CONFIG_PM_SLEEP + static int sdhci_s3c_suspend(struct device *dev) + { + struct sdhci_host *host = dev_get_drvdata(dev); +@@ -635,10 +665,44 @@ static int sdhci_s3c_resume(struct device *dev) + + return sdhci_resume_host(host); + } ++#endif ++ ++#ifdef CONFIG_PM_RUNTIME ++static int sdhci_s3c_runtime_suspend(struct device *dev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ struct sdhci_s3c *ourhost = to_s3c(host); ++ struct clk *busclk = ourhost->clk_io; ++ int ret; ++ ++ ret = sdhci_runtime_suspend_host(host); ++ ++ if (ourhost->cur_clk >= 0) ++ clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]); ++ clk_disable_unprepare(busclk); ++ return ret; ++} + ++static int sdhci_s3c_runtime_resume(struct device *dev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ struct sdhci_s3c *ourhost = to_s3c(host); ++ struct clk *busclk = ourhost->clk_io; ++ int ret; ++ ++ clk_prepare_enable(busclk); ++ if (ourhost->cur_clk >= 0) ++ clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]); ++ ret = sdhci_runtime_resume_host(host); ++ return ret; ++} ++#endif ++ ++#ifdef CONFIG_PM + static const struct dev_pm_ops sdhci_s3c_pmops = { +- .suspend = sdhci_s3c_suspend, +- .resume = sdhci_s3c_resume, ++ SET_SYSTEM_SLEEP_PM_OPS(sdhci_s3c_suspend, sdhci_s3c_resume) ++ SET_RUNTIME_PM_OPS(sdhci_s3c_runtime_suspend, sdhci_s3c_runtime_resume, ++ NULL) + }; + + #define SDHCI_S3C_PMOPS (&sdhci_s3c_pmops) +@@ -647,28 +711,50 @@ static const struct dev_pm_ops sdhci_s3c_pmops = { + #define SDHCI_S3C_PMOPS NULL + #endif + ++#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212) ++static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = { ++ .no_divider = true, ++}; ++#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data) ++#else ++#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)NULL) ++#endif ++ ++static struct platform_device_id sdhci_s3c_driver_ids[] = { ++ { ++ .name = "s3c-sdhci", ++ .driver_data = (kernel_ulong_t)NULL, ++ }, { ++ .name = "exynos4-sdhci", ++ .driver_data = EXYNOS4_SDHCI_DRV_DATA, ++ }, ++ { } ++}; ++MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids); ++ ++#ifdef CONFIG_OF ++static const struct of_device_id sdhci_s3c_dt_match[] = { ++ { .compatible = "samsung,s3c6410-sdhci", }, ++ { .compatible = "samsung,exynos4210-sdhci", ++ .data = (void *)EXYNOS4_SDHCI_DRV_DATA }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match); ++#endif ++ + static struct platform_driver sdhci_s3c_driver = { + .probe = sdhci_s3c_probe, +- .remove = __devexit_p(sdhci_s3c_remove), ++ .remove = sdhci_s3c_remove, ++ .id_table = sdhci_s3c_driver_ids, + .driver = { + .owner = THIS_MODULE, + .name = "s3c-sdhci", ++ .of_match_table = of_match_ptr(sdhci_s3c_dt_match), + .pm = SDHCI_S3C_PMOPS, + }, + }; + +-static int __init sdhci_s3c_init(void) +-{ +- return platform_driver_register(&sdhci_s3c_driver); +-} +- +-static void __exit sdhci_s3c_exit(void) +-{ +- platform_driver_unregister(&sdhci_s3c_driver); +-} +- +-module_init(sdhci_s3c_init); +-module_exit(sdhci_s3c_exit); ++module_platform_driver(sdhci_s3c_driver); + + MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue"); + MODULE_AUTHOR("Ben Dooks, "); +diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c +new file mode 100644 +index 0000000..1700453 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-sirf.c +@@ -0,0 +1,184 @@ ++/* ++ * SDHCI support for SiRF primaII and marco SoCs ++ * ++ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. ++ * ++ * Licensed under GPLv2 or later. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "sdhci-pltfm.h" ++ ++struct sdhci_sirf_priv { ++ struct clk *clk; ++ int gpio_cd; ++}; ++ ++static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); ++ return clk_get_rate(priv->clk); ++} ++ ++static struct sdhci_ops sdhci_sirf_ops = { ++ .set_clock = sdhci_set_clock, ++ .get_max_clock = sdhci_sirf_get_max_clk, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++}; ++ ++static struct sdhci_pltfm_data sdhci_sirf_pdata = { ++ .ops = &sdhci_sirf_ops, ++ .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | ++ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | ++ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | ++ SDHCI_QUIRK_INVERTED_WRITE_PROTECT | ++ SDHCI_QUIRK_DELAY_AFTER_POWER, ++}; ++ ++static int sdhci_sirf_probe(struct platform_device *pdev) ++{ ++ struct sdhci_host *host; ++ struct sdhci_pltfm_host *pltfm_host; ++ struct sdhci_sirf_priv *priv; ++ struct clk *clk; ++ int gpio_cd; ++ int ret; ++ ++ clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "unable to get clock"); ++ return PTR_ERR(clk); ++ } ++ ++ if (pdev->dev.of_node) ++ gpio_cd = of_get_named_gpio(pdev->dev.of_node, "cd-gpios", 0); ++ else ++ gpio_cd = -EINVAL; ++ ++ host = sdhci_pltfm_init(pdev, &sdhci_sirf_pdata, sizeof(struct sdhci_sirf_priv)); ++ if (IS_ERR(host)) ++ return PTR_ERR(host); ++ ++ pltfm_host = sdhci_priv(host); ++ priv = sdhci_pltfm_priv(pltfm_host); ++ priv->clk = clk; ++ priv->gpio_cd = gpio_cd; ++ ++ sdhci_get_of_property(pdev); ++ ++ ret = clk_prepare_enable(priv->clk); ++ if (ret) ++ goto err_clk_prepare; ++ ++ ret = sdhci_add_host(host); ++ if (ret) ++ goto err_sdhci_add; ++ ++ /* ++ * We must request the IRQ after sdhci_add_host(), as the tasklet only ++ * gets setup in sdhci_add_host() and we oops. ++ */ ++ if (gpio_is_valid(priv->gpio_cd)) { ++ ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd, 0); ++ if (ret) { ++ dev_err(&pdev->dev, "card detect irq request failed: %d\n", ++ ret); ++ goto err_request_cd; ++ } ++ } ++ ++ return 0; ++ ++err_request_cd: ++ sdhci_remove_host(host, 0); ++err_sdhci_add: ++ clk_disable_unprepare(priv->clk); ++err_clk_prepare: ++ sdhci_pltfm_free(pdev); ++ return ret; ++} ++ ++static int sdhci_sirf_remove(struct platform_device *pdev) ++{ ++ struct sdhci_host *host = platform_get_drvdata(pdev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); ++ ++ sdhci_pltfm_unregister(pdev); ++ ++ if (gpio_is_valid(priv->gpio_cd)) ++ mmc_gpio_free_cd(host->mmc); ++ ++ clk_disable_unprepare(priv->clk); ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int sdhci_sirf_suspend(struct device *dev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); ++ int ret; ++ ++ ret = sdhci_suspend_host(host); ++ if (ret) ++ return ret; ++ ++ clk_disable(priv->clk); ++ ++ return 0; ++} ++ ++static int sdhci_sirf_resume(struct device *dev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); ++ int ret; ++ ++ ret = clk_enable(priv->clk); ++ if (ret) { ++ dev_dbg(dev, "Resume: Error enabling clock\n"); ++ return ret; ++ } ++ ++ return sdhci_resume_host(host); ++} ++ ++static SIMPLE_DEV_PM_OPS(sdhci_sirf_pm_ops, sdhci_sirf_suspend, sdhci_sirf_resume); ++#endif ++ ++static const struct of_device_id sdhci_sirf_of_match[] = { ++ { .compatible = "sirf,prima2-sdhc" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, sdhci_sirf_of_match); ++ ++static struct platform_driver sdhci_sirf_driver = { ++ .driver = { ++ .name = "sdhci-sirf", ++ .owner = THIS_MODULE, ++ .of_match_table = sdhci_sirf_of_match, ++#ifdef CONFIG_PM_SLEEP ++ .pm = &sdhci_sirf_pm_ops, ++#endif ++ }, ++ .probe = sdhci_sirf_probe, ++ .remove = sdhci_sirf_remove, ++}; ++ ++module_platform_driver(sdhci_sirf_driver); ++ ++MODULE_DESCRIPTION("SDHCI driver for SiRFprimaII/SiRFmarco"); ++MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c +index 63cc8b6..9d535c7 100644 +--- a/drivers/mmc/host/sdhci-spear.c ++++ b/drivers/mmc/host/sdhci-spear.c +@@ -4,7 +4,7 @@ + * Support of SDHCI platform devices for spear soc family + * + * Copyright (C) 2010 ST Microelectronics +- * Viresh Kumar ++ * Viresh Kumar + * + * Inspired by sdhci-pltfm.c + * +@@ -20,10 +20,14 @@ + #include + #include + #include ++#include ++#include + #include ++#include + #include + #include + #include ++#include + #include + #include "sdhci.h" + +@@ -33,265 +37,209 @@ struct spear_sdhci { + }; + + /* sdhci ops */ +-static struct sdhci_ops sdhci_pltfm_ops = { +- /* Nothing to do for now. */ ++static const struct sdhci_ops sdhci_pltfm_ops = { ++ .set_clock = sdhci_set_clock, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, + }; + +-/* gpio card detection interrupt handler */ +-static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id) ++#ifdef CONFIG_OF ++static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev) + { +- struct platform_device *pdev = dev_id; +- struct sdhci_host *host = platform_get_drvdata(pdev); +- struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev); +- unsigned long gpio_irq_type; +- int val; +- +- val = gpio_get_value(sdhci->data->card_int_gpio); +- +- /* val == 1 -> card removed, val == 0 -> card inserted */ +- /* if card removed - set irq for low level, else vice versa */ +- gpio_irq_type = val ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH; +- irq_set_irq_type(irq, gpio_irq_type); +- +- if (sdhci->data->card_power_gpio >= 0) { +- if (!sdhci->data->power_always_enb) { +- /* if card inserted, give power, otherwise remove it */ +- val = sdhci->data->power_active_high ? !val : val ; +- gpio_set_value(sdhci->data->card_power_gpio, val); +- } ++ struct device_node *np = pdev->dev.of_node; ++ struct sdhci_plat_data *pdata = NULL; ++ int cd_gpio; ++ ++ cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); ++ if (!gpio_is_valid(cd_gpio)) ++ cd_gpio = -1; ++ ++ /* If pdata is required */ ++ if (cd_gpio != -1) { ++ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ dev_err(&pdev->dev, "DT: kzalloc failed\n"); ++ else ++ pdata->card_int_gpio = cd_gpio; + } + +- /* inform sdhci driver about card insertion/removal */ +- tasklet_schedule(&host->card_tasklet); +- +- return IRQ_HANDLED; ++ return pdata; ++} ++#else ++static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev) ++{ ++ return ERR_PTR(-ENOSYS); + } ++#endif + +-static int __devinit sdhci_probe(struct platform_device *pdev) ++static int sdhci_probe(struct platform_device *pdev) + { ++ struct device_node *np = pdev->dev.of_node; + struct sdhci_host *host; + struct resource *iomem; + struct spear_sdhci *sdhci; ++ struct device *dev; + int ret; + +- BUG_ON(pdev == NULL); +- +- iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!iomem) { +- ret = -ENOMEM; +- dev_dbg(&pdev->dev, "memory resource not defined\n"); ++ dev = pdev->dev.parent ? pdev->dev.parent : &pdev->dev; ++ host = sdhci_alloc_host(dev, sizeof(*sdhci)); ++ if (IS_ERR(host)) { ++ ret = PTR_ERR(host); ++ dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n"); + goto err; + } + +- if (!request_mem_region(iomem->start, resource_size(iomem), +- "spear-sdhci")) { +- ret = -EBUSY; +- dev_dbg(&pdev->dev, "cannot request region\n"); +- goto err; ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ host->ioaddr = devm_ioremap_resource(&pdev->dev, iomem); ++ if (IS_ERR(host->ioaddr)) { ++ ret = PTR_ERR(host->ioaddr); ++ dev_dbg(&pdev->dev, "unable to map iomem: %d\n", ret); ++ goto err_host; + } + +- sdhci = kzalloc(sizeof(*sdhci), GFP_KERNEL); +- if (!sdhci) { +- ret = -ENOMEM; +- dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n"); +- goto err_kzalloc; +- } ++ host->hw_name = "sdhci"; ++ host->ops = &sdhci_pltfm_ops; ++ host->irq = platform_get_irq(pdev, 0); ++ host->quirks = SDHCI_QUIRK_BROKEN_ADMA; ++ ++ sdhci = sdhci_priv(host); + + /* clk enable */ +- sdhci->clk = clk_get(&pdev->dev, NULL); ++ sdhci->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(sdhci->clk)) { + ret = PTR_ERR(sdhci->clk); + dev_dbg(&pdev->dev, "Error getting clock\n"); +- goto err_clk_get; ++ goto err_host; + } + +- ret = clk_enable(sdhci->clk); ++ ret = clk_prepare_enable(sdhci->clk); + if (ret) { + dev_dbg(&pdev->dev, "Error enabling clock\n"); +- goto err_clk_enb; ++ goto err_host; + } + +- /* overwrite platform_data */ +- sdhci->data = dev_get_platdata(&pdev->dev); +- pdev->dev.platform_data = sdhci; ++ ret = clk_set_rate(sdhci->clk, 50000000); ++ if (ret) ++ dev_dbg(&pdev->dev, "Error setting desired clk, clk=%lu\n", ++ clk_get_rate(sdhci->clk)); + +- if (pdev->dev.parent) +- host = sdhci_alloc_host(pdev->dev.parent, 0); +- else +- host = sdhci_alloc_host(&pdev->dev, 0); +- +- if (IS_ERR(host)) { +- ret = PTR_ERR(host); +- dev_dbg(&pdev->dev, "error allocating host\n"); +- goto err_alloc_host; ++ if (np) { ++ sdhci->data = sdhci_probe_config_dt(pdev); ++ if (IS_ERR(sdhci->data)) { ++ dev_err(&pdev->dev, "DT: Failed to get pdata\n"); ++ goto disable_clk; ++ } ++ } else { ++ sdhci->data = dev_get_platdata(&pdev->dev); + } + +- host->hw_name = "sdhci"; +- host->ops = &sdhci_pltfm_ops; +- host->irq = platform_get_irq(pdev, 0); +- host->quirks = SDHCI_QUIRK_BROKEN_ADMA; +- +- host->ioaddr = ioremap(iomem->start, resource_size(iomem)); +- if (!host->ioaddr) { +- ret = -ENOMEM; +- dev_dbg(&pdev->dev, "failed to remap registers\n"); +- goto err_ioremap; ++ /* ++ * It is optional to use GPIOs for sdhci card detection. If ++ * sdhci->data is NULL, then use original sdhci lines otherwise ++ * GPIO lines. We use the built-in GPIO support for this. ++ */ ++ if (sdhci->data && sdhci->data->card_int_gpio >= 0) { ++ ret = mmc_gpio_request_cd(host->mmc, ++ sdhci->data->card_int_gpio, 0); ++ if (ret < 0) { ++ dev_dbg(&pdev->dev, ++ "failed to request card-detect gpio%d\n", ++ sdhci->data->card_int_gpio); ++ goto disable_clk; ++ } + } + + ret = sdhci_add_host(host); + if (ret) { + dev_dbg(&pdev->dev, "error adding host\n"); +- goto err_add_host; ++ goto disable_clk; + } + + platform_set_drvdata(pdev, host); + +- /* +- * It is optional to use GPIOs for sdhci Power control & sdhci card +- * interrupt detection. If sdhci->data is NULL, then use original sdhci +- * lines otherwise GPIO lines. +- * If GPIO is selected for power control, then power should be disabled +- * after card removal and should be enabled when card insertion +- * interrupt occurs +- */ +- if (!sdhci->data) +- return 0; +- +- if (sdhci->data->card_power_gpio >= 0) { +- int val = 0; +- +- ret = gpio_request(sdhci->data->card_power_gpio, "sdhci"); +- if (ret < 0) { +- dev_dbg(&pdev->dev, "gpio request fail: %d\n", +- sdhci->data->card_power_gpio); +- goto err_pgpio_request; +- } +- +- if (sdhci->data->power_always_enb) +- val = sdhci->data->power_active_high; +- else +- val = !sdhci->data->power_active_high; +- +- ret = gpio_direction_output(sdhci->data->card_power_gpio, val); +- if (ret) { +- dev_dbg(&pdev->dev, "gpio set direction fail: %d\n", +- sdhci->data->card_power_gpio); +- goto err_pgpio_direction; +- } +- } +- +- if (sdhci->data->card_int_gpio >= 0) { +- ret = gpio_request(sdhci->data->card_int_gpio, "sdhci"); +- if (ret < 0) { +- dev_dbg(&pdev->dev, "gpio request fail: %d\n", +- sdhci->data->card_int_gpio); +- goto err_igpio_request; +- } +- +- ret = gpio_direction_input(sdhci->data->card_int_gpio); +- if (ret) { +- dev_dbg(&pdev->dev, "gpio set direction fail: %d\n", +- sdhci->data->card_int_gpio); +- goto err_igpio_direction; +- } +- ret = request_irq(gpio_to_irq(sdhci->data->card_int_gpio), +- sdhci_gpio_irq, IRQF_TRIGGER_LOW, +- mmc_hostname(host->mmc), pdev); +- if (ret) { +- dev_dbg(&pdev->dev, "gpio request irq fail: %d\n", +- sdhci->data->card_int_gpio); +- goto err_igpio_request_irq; +- } +- +- } +- + return 0; + +-err_igpio_request_irq: +-err_igpio_direction: +- if (sdhci->data->card_int_gpio >= 0) +- gpio_free(sdhci->data->card_int_gpio); +-err_igpio_request: +-err_pgpio_direction: +- if (sdhci->data->card_power_gpio >= 0) +- gpio_free(sdhci->data->card_power_gpio); +-err_pgpio_request: +- platform_set_drvdata(pdev, NULL); +- sdhci_remove_host(host, 1); +-err_add_host: +- iounmap(host->ioaddr); +-err_ioremap: ++disable_clk: ++ clk_disable_unprepare(sdhci->clk); ++err_host: + sdhci_free_host(host); +-err_alloc_host: +- clk_disable(sdhci->clk); +-err_clk_enb: +- clk_put(sdhci->clk); +-err_clk_get: +- kfree(sdhci); +-err_kzalloc: +- release_mem_region(iomem->start, resource_size(iomem)); + err: + dev_err(&pdev->dev, "spear-sdhci probe failed: %d\n", ret); + return ret; + } + +-static int __devexit sdhci_remove(struct platform_device *pdev) ++static int sdhci_remove(struct platform_device *pdev) + { + struct sdhci_host *host = platform_get_drvdata(pdev); +- struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev); +- int dead; ++ struct spear_sdhci *sdhci = sdhci_priv(host); ++ int dead = 0; + u32 scratch; + +- if (sdhci->data) { +- if (sdhci->data->card_int_gpio >= 0) { +- free_irq(gpio_to_irq(sdhci->data->card_int_gpio), pdev); +- gpio_free(sdhci->data->card_int_gpio); +- } +- +- if (sdhci->data->card_power_gpio >= 0) +- gpio_free(sdhci->data->card_power_gpio); +- } +- +- platform_set_drvdata(pdev, NULL); +- dead = 0; + scratch = readl(host->ioaddr + SDHCI_INT_STATUS); + if (scratch == (u32)-1) + dead = 1; + + sdhci_remove_host(host, dead); +- iounmap(host->ioaddr); ++ clk_disable_unprepare(sdhci->clk); + sdhci_free_host(host); +- clk_disable(sdhci->clk); +- clk_put(sdhci->clk); +- kfree(sdhci); +- if (iomem) +- release_mem_region(iomem->start, resource_size(iomem)); + + return 0; + } + ++#ifdef CONFIG_PM_SLEEP ++static int sdhci_suspend(struct device *dev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ struct spear_sdhci *sdhci = sdhci_priv(host); ++ int ret; ++ ++ ret = sdhci_suspend_host(host); ++ if (!ret) ++ clk_disable(sdhci->clk); ++ ++ return ret; ++} ++ ++static int sdhci_resume(struct device *dev) ++{ ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ struct spear_sdhci *sdhci = sdhci_priv(host); ++ int ret; ++ ++ ret = clk_enable(sdhci->clk); ++ if (ret) { ++ dev_dbg(dev, "Resume: Error enabling clock\n"); ++ return ret; ++ } ++ ++ return sdhci_resume_host(host); ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(sdhci_pm_ops, sdhci_suspend, sdhci_resume); ++ ++#ifdef CONFIG_OF ++static const struct of_device_id sdhci_spear_id_table[] = { ++ { .compatible = "st,spear300-sdhci" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, sdhci_spear_id_table); ++#endif ++ + static struct platform_driver sdhci_driver = { + .driver = { + .name = "sdhci", + .owner = THIS_MODULE, ++ .pm = &sdhci_pm_ops, ++ .of_match_table = of_match_ptr(sdhci_spear_id_table), + }, + .probe = sdhci_probe, +- .remove = __devexit_p(sdhci_remove), ++ .remove = sdhci_remove, + }; + +-static int __init sdhci_init(void) +-{ +- return platform_driver_register(&sdhci_driver); +-} +-module_init(sdhci_init); +- +-static void __exit sdhci_exit(void) +-{ +- platform_driver_unregister(&sdhci_driver); +-} +-module_exit(sdhci_exit); ++module_platform_driver(sdhci_driver); + + MODULE_DESCRIPTION("SPEAr Secure Digital Host Controller Interface driver"); +-MODULE_AUTHOR("Viresh Kumar "); ++MODULE_AUTHOR("Viresh Kumar "); + MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c +index e2e18d3..d93a063 100644 +--- a/drivers/mmc/host/sdhci-tegra.c ++++ b/drivers/mmc/host/sdhci-tegra.c +@@ -19,35 +19,49 @@ + #include + #include + #include ++#include + #include + #include + #include + #include +-#include ++#include + + #include + +-#include +-#include +- + #include "sdhci-pltfm.h" + +-static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg) +-{ +- u32 val; +- +- if (unlikely(reg == SDHCI_PRESENT_STATE)) { +- /* Use wp_gpio here instead? */ +- val = readl(host->ioaddr + reg); +- return val | SDHCI_WRITE_PROTECT; +- } ++/* Tegra SDHOST controller vendor register definitions */ ++#define SDHCI_TEGRA_VENDOR_MISC_CTRL 0x120 ++#define SDHCI_MISC_CTRL_ENABLE_SDR104 0x8 ++#define SDHCI_MISC_CTRL_ENABLE_SDR50 0x10 ++#define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20 ++#define SDHCI_MISC_CTRL_ENABLE_DDR50 0x200 ++ ++#define NVQUIRK_FORCE_SDHCI_SPEC_200 BIT(0) ++#define NVQUIRK_ENABLE_BLOCK_GAP_DET BIT(1) ++#define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2) ++#define NVQUIRK_DISABLE_SDR50 BIT(3) ++#define NVQUIRK_DISABLE_SDR104 BIT(4) ++#define NVQUIRK_DISABLE_DDR50 BIT(5) ++ ++struct sdhci_tegra_soc_data { ++ const struct sdhci_pltfm_data *pdata; ++ u32 nvquirks; ++}; + +- return readl(host->ioaddr + reg); +-} ++struct sdhci_tegra { ++ const struct sdhci_tegra_soc_data *soc_data; ++ int power_gpio; ++}; + + static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) + { +- if (unlikely(reg == SDHCI_HOST_VERSION)) { ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_tegra *tegra_host = pltfm_host->priv; ++ const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; ++ ++ if (unlikely((soc_data->nvquirks & NVQUIRK_FORCE_SDHCI_SPEC_200) && ++ (reg == SDHCI_HOST_VERSION))) { + /* Erratum: Version register is invalid in HW. */ + return SDHCI_SPEC_200; + } +@@ -57,6 +71,10 @@ static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) + + static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) + { ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_tegra *tegra_host = pltfm_host->priv; ++ const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; ++ + /* Seems like we're getting spurious timeout and crc errors, so + * disable signalling of them. In case of real errors software + * timers should take care of eventually detecting them. +@@ -66,7 +84,8 @@ static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) + + writel(val, host->ioaddr + reg); + +- if (unlikely(reg == SDHCI_INT_ENABLE)) { ++ if (unlikely((soc_data->nvquirks & NVQUIRK_ENABLE_BLOCK_GAP_DET) && ++ (reg == SDHCI_INT_ENABLE))) { + /* Erratum: Must enable block gap interrupt detection */ + u8 gap_ctrl = readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL); + if (val & SDHCI_INT_CARD_INT) +@@ -77,33 +96,44 @@ static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) + } + } + +-static unsigned int tegra_sdhci_get_ro(struct sdhci_host *sdhci) ++static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host) + { +- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci); +- struct tegra_sdhci_platform_data *plat = pltfm_host->priv; +- +- if (!gpio_is_valid(plat->wp_gpio)) +- return -1; +- +- return gpio_get_value(plat->wp_gpio); ++ return mmc_gpio_get_ro(host->mmc); + } + +-static irqreturn_t carddetect_irq(int irq, void *data) ++static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask) + { +- struct sdhci_host *sdhost = (struct sdhci_host *)data; +- +- tasklet_schedule(&sdhost->card_tasklet); +- return IRQ_HANDLED; +-}; ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_tegra *tegra_host = pltfm_host->priv; ++ const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; ++ u32 misc_ctrl; ++ ++ sdhci_reset(host, mask); ++ ++ if (!(mask & SDHCI_RESET_ALL)) ++ return; ++ ++ misc_ctrl = sdhci_readw(host, SDHCI_TEGRA_VENDOR_MISC_CTRL); ++ /* Erratum: Enable SDHCI spec v3.00 support */ ++ if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300) ++ misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300; ++ /* Don't advertise UHS modes which aren't supported yet */ ++ if (soc_data->nvquirks & NVQUIRK_DISABLE_SDR50) ++ misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR50; ++ if (soc_data->nvquirks & NVQUIRK_DISABLE_DDR50) ++ misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_DDR50; ++ if (soc_data->nvquirks & NVQUIRK_DISABLE_SDR104) ++ misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR104; ++ sdhci_writew(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL); ++} + +-static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width) ++static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width) + { +- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +- struct tegra_sdhci_platform_data *plat = pltfm_host->priv; + u32 ctrl; + + ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); +- if (plat->is_8bit && bus_width == MMC_BUS_WIDTH_8) { ++ if ((host->mmc->caps & MMC_CAP_8_BIT_DATA) && ++ (bus_width == MMC_BUS_WIDTH_8)) { + ctrl &= ~SDHCI_CTRL_4BITBUS; + ctrl |= SDHCI_CTRL_8BITBUS; + } else { +@@ -114,123 +144,129 @@ static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width) + ctrl &= ~SDHCI_CTRL_4BITBUS; + } + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); +- return 0; + } + +-static struct sdhci_ops tegra_sdhci_ops = { ++static const struct sdhci_ops tegra_sdhci_ops = { + .get_ro = tegra_sdhci_get_ro, +- .read_l = tegra_sdhci_readl, + .read_w = tegra_sdhci_readw, + .write_l = tegra_sdhci_writel, +- .platform_8bit_width = tegra_sdhci_8bit, ++ .set_clock = sdhci_set_clock, ++ .set_bus_width = tegra_sdhci_set_bus_width, ++ .reset = tegra_sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++ .get_max_clock = sdhci_pltfm_clk_get_max_clock, + }; + +-static struct sdhci_pltfm_data sdhci_tegra_pdata = { ++static const struct sdhci_pltfm_data sdhci_tegra20_pdata = { + .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | + SDHCI_QUIRK_SINGLE_POWER_WRITE | + SDHCI_QUIRK_NO_HISPD_BIT | +- SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC, ++ SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | ++ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, + .ops = &tegra_sdhci_ops, + }; + +-static const struct of_device_id sdhci_tegra_dt_match[] __devinitdata = { +- { .compatible = "nvidia,tegra20-sdhci", }, +- {} ++static struct sdhci_tegra_soc_data soc_data_tegra20 = { ++ .pdata = &sdhci_tegra20_pdata, ++ .nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 | ++ NVQUIRK_ENABLE_BLOCK_GAP_DET, + }; +-MODULE_DEVICE_TABLE(of, sdhci_dt_ids); + +-static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata( +- struct platform_device *pdev) +-{ +- struct tegra_sdhci_platform_data *plat; +- struct device_node *np = pdev->dev.of_node; ++static const struct sdhci_pltfm_data sdhci_tegra30_pdata = { ++ .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | ++ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | ++ SDHCI_QUIRK_SINGLE_POWER_WRITE | ++ SDHCI_QUIRK_NO_HISPD_BIT | ++ SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | ++ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, ++ .ops = &tegra_sdhci_ops, ++}; + +- if (!np) +- return NULL; ++static struct sdhci_tegra_soc_data soc_data_tegra30 = { ++ .pdata = &sdhci_tegra30_pdata, ++ .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 | ++ NVQUIRK_DISABLE_SDR50 | ++ NVQUIRK_DISABLE_SDR104, ++}; + +- plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); +- if (!plat) { +- dev_err(&pdev->dev, "Can't allocate platform data\n"); +- return NULL; +- } ++static const struct sdhci_pltfm_data sdhci_tegra114_pdata = { ++ .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | ++ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | ++ SDHCI_QUIRK_SINGLE_POWER_WRITE | ++ SDHCI_QUIRK_NO_HISPD_BIT | ++ SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | ++ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, ++ .ops = &tegra_sdhci_ops, ++}; + +- plat->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); +- plat->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); +- plat->power_gpio = of_get_named_gpio(np, "power-gpios", 0); +- if (of_find_property(np, "support-8bit", NULL)) +- plat->is_8bit = 1; ++static struct sdhci_tegra_soc_data soc_data_tegra114 = { ++ .pdata = &sdhci_tegra114_pdata, ++ .nvquirks = NVQUIRK_DISABLE_SDR50 | ++ NVQUIRK_DISABLE_DDR50 | ++ NVQUIRK_DISABLE_SDR104, ++}; + +- return plat; ++static const struct of_device_id sdhci_tegra_dt_match[] = { ++ { .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra114 }, ++ { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 }, ++ { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 }, ++ { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); ++ ++static int sdhci_tegra_parse_dt(struct device *dev) ++{ ++ struct device_node *np = dev->of_node; ++ struct sdhci_host *host = dev_get_drvdata(dev); ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_tegra *tegra_host = pltfm_host->priv; ++ ++ tegra_host->power_gpio = of_get_named_gpio(np, "power-gpios", 0); ++ return mmc_of_parse(host->mmc); + } + +-static int __devinit sdhci_tegra_probe(struct platform_device *pdev) ++static int sdhci_tegra_probe(struct platform_device *pdev) + { +- struct sdhci_pltfm_host *pltfm_host; +- struct tegra_sdhci_platform_data *plat; ++ const struct of_device_id *match; ++ const struct sdhci_tegra_soc_data *soc_data; + struct sdhci_host *host; ++ struct sdhci_pltfm_host *pltfm_host; ++ struct sdhci_tegra *tegra_host; + struct clk *clk; + int rc; + +- host = sdhci_pltfm_init(pdev, &sdhci_tegra_pdata); ++ match = of_match_device(sdhci_tegra_dt_match, &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ soc_data = match->data; ++ ++ host = sdhci_pltfm_init(pdev, soc_data->pdata, 0); + if (IS_ERR(host)) + return PTR_ERR(host); +- + pltfm_host = sdhci_priv(host); + +- plat = pdev->dev.platform_data; +- +- if (plat == NULL) +- plat = sdhci_tegra_dt_parse_pdata(pdev); +- +- if (plat == NULL) { +- dev_err(mmc_dev(host->mmc), "missing platform data\n"); +- rc = -ENXIO; +- goto err_no_plat; ++ tegra_host = devm_kzalloc(&pdev->dev, sizeof(*tegra_host), GFP_KERNEL); ++ if (!tegra_host) { ++ dev_err(mmc_dev(host->mmc), "failed to allocate tegra_host\n"); ++ rc = -ENOMEM; ++ goto err_alloc_tegra_host; + } ++ tegra_host->soc_data = soc_data; ++ pltfm_host->priv = tegra_host; + +- pltfm_host->priv = plat; ++ rc = sdhci_tegra_parse_dt(&pdev->dev); ++ if (rc) ++ goto err_parse_dt; + +- if (gpio_is_valid(plat->power_gpio)) { +- rc = gpio_request(plat->power_gpio, "sdhci_power"); ++ if (gpio_is_valid(tegra_host->power_gpio)) { ++ rc = gpio_request(tegra_host->power_gpio, "sdhci_power"); + if (rc) { + dev_err(mmc_dev(host->mmc), + "failed to allocate power gpio\n"); + goto err_power_req; + } +- tegra_gpio_enable(plat->power_gpio); +- gpio_direction_output(plat->power_gpio, 1); +- } +- +- if (gpio_is_valid(plat->cd_gpio)) { +- rc = gpio_request(plat->cd_gpio, "sdhci_cd"); +- if (rc) { +- dev_err(mmc_dev(host->mmc), +- "failed to allocate cd gpio\n"); +- goto err_cd_req; +- } +- tegra_gpio_enable(plat->cd_gpio); +- gpio_direction_input(plat->cd_gpio); +- +- rc = request_irq(gpio_to_irq(plat->cd_gpio), carddetect_irq, +- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, +- mmc_hostname(host->mmc), host); +- +- if (rc) { +- dev_err(mmc_dev(host->mmc), "request irq error\n"); +- goto err_cd_irq_req; +- } +- +- } +- +- if (gpio_is_valid(plat->wp_gpio)) { +- rc = gpio_request(plat->wp_gpio, "sdhci_wp"); +- if (rc) { +- dev_err(mmc_dev(host->mmc), +- "failed to allocate wp gpio\n"); +- goto err_wp_req; +- } +- tegra_gpio_enable(plat->wp_gpio); +- gpio_direction_input(plat->wp_gpio); ++ gpio_direction_output(tegra_host->power_gpio, 1); + } + + clk = clk_get(mmc_dev(host->mmc), NULL); +@@ -239,14 +275,9 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev) + rc = PTR_ERR(clk); + goto err_clk_get; + } +- clk_enable(clk); ++ clk_prepare_enable(clk); + pltfm_host->clk = clk; + +- host->mmc->pm_caps = plat->pm_flags; +- +- if (plat->is_8bit) +- host->mmc->caps |= MMC_CAP_8_BIT_DATA; +- + rc = sdhci_add_host(host); + if (rc) + goto err_add_host; +@@ -254,58 +285,31 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev) + return 0; + + err_add_host: +- clk_disable(pltfm_host->clk); ++ clk_disable_unprepare(pltfm_host->clk); + clk_put(pltfm_host->clk); + err_clk_get: +- if (gpio_is_valid(plat->wp_gpio)) { +- tegra_gpio_disable(plat->wp_gpio); +- gpio_free(plat->wp_gpio); +- } +-err_wp_req: +- if (gpio_is_valid(plat->cd_gpio)) +- free_irq(gpio_to_irq(plat->cd_gpio), host); +-err_cd_irq_req: +- if (gpio_is_valid(plat->cd_gpio)) { +- tegra_gpio_disable(plat->cd_gpio); +- gpio_free(plat->cd_gpio); +- } +-err_cd_req: +- if (gpio_is_valid(plat->power_gpio)) { +- tegra_gpio_disable(plat->power_gpio); +- gpio_free(plat->power_gpio); +- } ++ if (gpio_is_valid(tegra_host->power_gpio)) ++ gpio_free(tegra_host->power_gpio); + err_power_req: +-err_no_plat: ++err_parse_dt: ++err_alloc_tegra_host: + sdhci_pltfm_free(pdev); + return rc; + } + +-static int __devexit sdhci_tegra_remove(struct platform_device *pdev) ++static int sdhci_tegra_remove(struct platform_device *pdev) + { + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +- struct tegra_sdhci_platform_data *plat = pltfm_host->priv; ++ struct sdhci_tegra *tegra_host = pltfm_host->priv; + int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); + + sdhci_remove_host(host, dead); + +- if (gpio_is_valid(plat->wp_gpio)) { +- tegra_gpio_disable(plat->wp_gpio); +- gpio_free(plat->wp_gpio); +- } ++ if (gpio_is_valid(tegra_host->power_gpio)) ++ gpio_free(tegra_host->power_gpio); + +- if (gpio_is_valid(plat->cd_gpio)) { +- free_irq(gpio_to_irq(plat->cd_gpio), host); +- tegra_gpio_disable(plat->cd_gpio); +- gpio_free(plat->cd_gpio); +- } +- +- if (gpio_is_valid(plat->power_gpio)) { +- tegra_gpio_disable(plat->power_gpio); +- gpio_free(plat->power_gpio); +- } +- +- clk_disable(pltfm_host->clk); ++ clk_disable_unprepare(pltfm_host->clk); + clk_put(pltfm_host->clk); + + sdhci_pltfm_free(pdev); +@@ -321,21 +325,11 @@ static struct platform_driver sdhci_tegra_driver = { + .pm = SDHCI_PLTFM_PMOPS, + }, + .probe = sdhci_tegra_probe, +- .remove = __devexit_p(sdhci_tegra_remove), ++ .remove = sdhci_tegra_remove, + }; + +-static int __init sdhci_tegra_init(void) +-{ +- return platform_driver_register(&sdhci_tegra_driver); +-} +-module_init(sdhci_tegra_init); +- +-static void __exit sdhci_tegra_exit(void) +-{ +- platform_driver_unregister(&sdhci_tegra_driver); +-} +-module_exit(sdhci_tegra_exit); ++module_platform_driver(sdhci_tegra_driver); + + MODULE_DESCRIPTION("SDHCI driver for Tegra"); +-MODULE_AUTHOR(" Google, Inc."); ++MODULE_AUTHOR("Google, Inc."); + MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c +index 9f68b82..07eb5f5 100644 +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -27,6 +27,8 @@ + + #include + #include ++#include ++#include + + #include "sdhci.h" + +@@ -42,19 +44,23 @@ + + #define MAX_TUNING_LOOP 40 + ++#define ADMA_SIZE ((128 * 2 + 1) * 4) ++ + static unsigned int debug_quirks = 0; + static unsigned int debug_quirks2; + + static void sdhci_finish_data(struct sdhci_host *); + +-static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); + static void sdhci_finish_command(struct sdhci_host *); +-static int sdhci_execute_tuning(struct mmc_host *mmc); ++static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); + static void sdhci_tuning_timer(unsigned long data); ++static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); + + #ifdef CONFIG_PM_RUNTIME + static int sdhci_runtime_pm_get(struct sdhci_host *host); + static int sdhci_runtime_pm_put(struct sdhci_host *host); ++static void sdhci_runtime_pm_bus_on(struct sdhci_host *host); ++static void sdhci_runtime_pm_bus_off(struct sdhci_host *host); + #else + static inline int sdhci_runtime_pm_get(struct sdhci_host *host) + { +@@ -64,6 +70,12 @@ static inline int sdhci_runtime_pm_put(struct sdhci_host *host) + { + return 0; + } ++static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) ++{ ++} ++static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) ++{ ++} + #endif + + static void sdhci_dumpregs(struct sdhci_host *host) +@@ -121,45 +133,26 @@ static void sdhci_dumpregs(struct sdhci_host *host) + * * + \*****************************************************************************/ + +-static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) +-{ +- u32 ier; +- +- ier = sdhci_readl(host, SDHCI_INT_ENABLE); +- ier &= ~clear; +- ier |= set; +- sdhci_writel(host, ier, SDHCI_INT_ENABLE); +- sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); +-} +- +-static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs) +-{ +- sdhci_clear_set_irqs(host, 0, irqs); +-} +- +-static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs) +-{ +- sdhci_clear_set_irqs(host, irqs, 0); +-} +- + static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) + { +- u32 present, irqs; ++ u32 present; + +- if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ++ if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || ++ (host->mmc->caps & MMC_CAP_NONREMOVABLE)) + return; + +- if (host->quirks2 & SDHCI_QUIRK2_OWN_CARD_DETECTION) +- return; ++ if (enable) { ++ present = sdhci_readl(host, SDHCI_PRESENT_STATE) & ++ SDHCI_CARD_PRESENT; + +- present = sdhci_readl(host, SDHCI_PRESENT_STATE) & +- SDHCI_CARD_PRESENT; +- irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT; ++ host->ier |= present ? SDHCI_INT_CARD_REMOVE : ++ SDHCI_INT_CARD_INSERT; ++ } else { ++ host->ier &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); ++ } + +- if (enable) +- sdhci_unmask_irqs(host, irqs); +- else +- sdhci_mask_irqs(host, irqs); ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + } + + static void sdhci_enable_card_detection(struct sdhci_host *host) +@@ -172,27 +165,18 @@ static void sdhci_disable_card_detection(struct sdhci_host *host) + sdhci_set_card_detection(host, false); + } + +-static void sdhci_reset(struct sdhci_host *host, u8 mask) ++void sdhci_reset(struct sdhci_host *host, u8 mask) + { + unsigned long timeout; +- u32 uninitialized_var(ier); +- +- if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { +- if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & +- SDHCI_CARD_PRESENT)) +- return; +- } +- +- if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) +- ier = sdhci_readl(host, SDHCI_INT_ENABLE); +- +- if (host->ops->platform_reset_enter) +- host->ops->platform_reset_enter(host, mask); + + sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); + +- if (mask & SDHCI_RESET_ALL) ++ if (mask & SDHCI_RESET_ALL) { + host->clock = 0; ++ /* Reset-all turns off SD Bus Power */ ++ if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) ++ sdhci_runtime_pm_bus_off(host); ++ } + + /* Wait max 100 ms */ + timeout = 100; +@@ -208,12 +192,28 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) + timeout--; + mdelay(1); + } ++} ++EXPORT_SYMBOL_GPL(sdhci_reset); + +- if (host->ops->platform_reset_exit) +- host->ops->platform_reset_exit(host, mask); ++static void sdhci_do_reset(struct sdhci_host *host, u8 mask) ++{ ++ if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { ++ if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & ++ SDHCI_CARD_PRESENT)) ++ return; ++ } ++ ++ host->ops->reset(host, mask); ++ ++ if (mask & SDHCI_RESET_ALL) { ++ if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { ++ if (host->ops->enable_dma) ++ host->ops->enable_dma(host); ++ } + +- if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) +- sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); ++ /* Resetting the controller clears many */ ++ host->preset_enabled = false; ++ } + } + + static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); +@@ -221,15 +221,18 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); + static void sdhci_init(struct sdhci_host *host, int soft) + { + if (soft) +- sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); ++ sdhci_do_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); + else +- sdhci_reset(host, SDHCI_RESET_ALL); ++ sdhci_do_reset(host, SDHCI_RESET_ALL); + +- sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, +- SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | +- 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); ++ host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | ++ 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_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + + if (soft) { + /* force clock reconfiguration */ +@@ -241,6 +244,19 @@ static void sdhci_init(struct sdhci_host *host, int soft) + static void sdhci_reinit(struct sdhci_host *host) + { + sdhci_init(host, 0); ++ /* ++ * Retuning stuffs are affected by different cards inserted and only ++ * applicable to UHS-I cards. So reset these fields to their initial ++ * value when card is removed. ++ */ ++ if (host->flags & SDHCI_USING_RETUNING_TIMER) { ++ host->flags &= ~SDHCI_USING_RETUNING_TIMER; ++ ++ del_timer_sync(&host->tuning_timer); ++ host->flags &= ~SDHCI_NEEDS_RETUNING; ++ host->mmc->max_blk_count = ++ (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; ++ } + sdhci_enable_card_detection(host); + } + +@@ -423,12 +439,12 @@ static void sdhci_transfer_pio(struct sdhci_host *host) + static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) + { + local_irq_save(*flags); +- return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; ++ return kmap_atomic(sg_page(sg)) + sg->offset; + } + + static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) + { +- kunmap_atomic(buffer, KM_BIO_SRC_IRQ); ++ kunmap_atomic(buffer); + local_irq_restore(*flags); + } + +@@ -472,11 +488,6 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, + else + direction = DMA_TO_DEVICE; + +- /* +- * The ADMA descriptor table is mapped further down as we +- * need to fill it with data first. +- */ +- + host->align_addr = dma_map_single(mmc_dev(host->mmc), + host->align_buffer, 128 * 4, direction); + if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) +@@ -537,7 +548,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, + * If this triggers then we have a calculation bug + * somewhere. :/ + */ +- WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4); ++ WARN_ON((desc - host->adma_desc) > ADMA_SIZE); + } + + if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { +@@ -565,17 +576,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, + host->align_addr, 128 * 4, direction); + } + +- host->adma_addr = dma_map_single(mmc_dev(host->mmc), +- host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); +- if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr)) +- goto unmap_entries; +- BUG_ON(host->adma_addr & 0x3); +- + return 0; + +-unmap_entries: +- dma_unmap_sg(mmc_dev(host->mmc), data->sg, +- data->sg_len, direction); + unmap_align: + dma_unmap_single(mmc_dev(host->mmc), host->align_addr, + 128 * 4, direction); +@@ -593,19 +595,25 @@ static void sdhci_adma_table_post(struct sdhci_host *host, + u8 *align; + char *buffer; + unsigned long flags; ++ bool has_unaligned; + + if (data->flags & MMC_DATA_READ) + direction = DMA_FROM_DEVICE; + else + direction = DMA_TO_DEVICE; + +- dma_unmap_single(mmc_dev(host->mmc), host->adma_addr, +- (128 * 2 + 1) * 4, DMA_TO_DEVICE); +- + dma_unmap_single(mmc_dev(host->mmc), host->align_addr, + 128 * 4, direction); + +- if (data->flags & MMC_DATA_READ) { ++ /* Do a quick scan of the SG list for any unaligned mappings */ ++ has_unaligned = false; ++ for_each_sg(data->sg, sg, host->sg_count, i) ++ if (sg_dma_address(sg) & 3) { ++ has_unaligned = true; ++ break; ++ } ++ ++ if (has_unaligned && data->flags & MMC_DATA_READ) { + dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, + data->sg_len, direction); + +@@ -645,12 +653,12 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) + return 0xE; + + /* Unspecified timeout, assume max */ +- if (!data && !cmd->cmd_timeout_ms) ++ if (!data && !cmd->busy_timeout) + return 0xE; + + /* timeout in us */ + if (!data) +- target_timeout = cmd->cmd_timeout_ms * 1000; ++ target_timeout = cmd->busy_timeout * 1000; + else { + target_timeout = data->timeout_ns / 1000; + if (host->clock) +@@ -677,8 +685,8 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) + } + + if (count >= 0xF) { +- pr_warning("%s: Too large timeout requested for CMD%d!\n", +- mmc_hostname(host->mmc), cmd->opcode); ++ DBG("%s: Too large timeout 0x%x requested for CMD%d!\n", ++ mmc_hostname(host->mmc), count, cmd->opcode); + count = 0xE; + } + +@@ -691,9 +699,12 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) + u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; + + if (host->flags & SDHCI_REQ_USE_DMA) +- sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); ++ host->ier = (host->ier & ~pio_irqs) | dma_irqs; + else +- sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); ++ host->ier = (host->ier & ~dma_irqs) | pio_irqs; ++ ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + } + + static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) +@@ -868,8 +879,13 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, + u16 mode; + struct mmc_data *data = cmd->data; + +- if (data == NULL) ++ if (data == NULL) { ++ /* clear Auto CMD settings for no data CMDs */ ++ mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); ++ sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | ++ SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE); + return; ++ } + + WARN_ON(!host->data); + +@@ -941,8 +957,8 @@ static void sdhci_finish_data(struct sdhci_host *host) + * upon error conditions. + */ + if (data->error) { +- sdhci_reset(host, SDHCI_RESET_CMD); +- sdhci_reset(host, SDHCI_RESET_DATA); ++ sdhci_do_reset(host, SDHCI_RESET_CMD); ++ sdhci_do_reset(host, SDHCI_RESET_DATA); + } + + sdhci_send_command(host, data->stop); +@@ -950,7 +966,7 @@ static void sdhci_finish_data(struct sdhci_host *host) + tasklet_schedule(&host->finish_tasklet); + } + +-static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) ++void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) + { + int flags; + u32 mask; +@@ -983,7 +999,12 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) + mdelay(1); + } + +- mod_timer(&host->timer, jiffies + 10 * HZ); ++ timeout = jiffies; ++ if (!cmd->data && cmd->busy_timeout > 9000) ++ timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; ++ else ++ timeout += 10 * HZ; ++ mod_timer(&host->timer, timeout); + + host->cmd = cmd; + +@@ -1016,11 +1037,13 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) + flags |= SDHCI_CMD_INDEX; + + /* CMD19 is special in that the Data Present Select should be set */ +- if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK)) ++ if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK || ++ cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) + flags |= SDHCI_CMD_DATA; + + sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); + } ++EXPORT_SYMBOL_GPL(sdhci_send_command); + + static void sdhci_finish_command(struct sdhci_host *host) + { +@@ -1063,54 +1086,87 @@ static void sdhci_finish_command(struct sdhci_host *host) + } + } + +-static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) ++static u16 sdhci_get_preset_value(struct sdhci_host *host) ++{ ++ u16 preset = 0; ++ ++ switch (host->timing) { ++ case MMC_TIMING_UHS_SDR12: ++ preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); ++ break; ++ case MMC_TIMING_UHS_SDR25: ++ preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25); ++ break; ++ case MMC_TIMING_UHS_SDR50: ++ preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50); ++ break; ++ case MMC_TIMING_UHS_SDR104: ++ case MMC_TIMING_MMC_HS200: ++ preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104); ++ break; ++ case MMC_TIMING_UHS_DDR50: ++ preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50); ++ break; ++ default: ++ pr_warn("%s: Invalid UHS-I mode selected\n", ++ mmc_hostname(host->mmc)); ++ preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); ++ break; ++ } ++ return preset; ++} ++ ++void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) + { + int div = 0; /* Initialized for compiler warning */ ++ int real_div = div, clk_mul = 1; + u16 clk = 0; + unsigned long timeout; + +- if (clock == host->clock) +- return; +- +- if (host->ops->set_clock) { +- host->ops->set_clock(host, clock); +- if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) +- return; +- } ++ host->mmc->actual_clock = 0; + + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + + if (clock == 0) +- goto out; ++ return; + + if (host->version >= SDHCI_SPEC_300) { ++ if (host->preset_enabled) { ++ u16 pre_val; ++ ++ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); ++ pre_val = sdhci_get_preset_value(host); ++ div = (pre_val & SDHCI_PRESET_SDCLK_FREQ_MASK) ++ >> SDHCI_PRESET_SDCLK_FREQ_SHIFT; ++ if (host->clk_mul && ++ (pre_val & SDHCI_PRESET_CLKGEN_SEL_MASK)) { ++ clk = SDHCI_PROG_CLOCK_MODE; ++ real_div = div + 1; ++ clk_mul = host->clk_mul; ++ } else { ++ real_div = max_t(int, 1, div << 1); ++ } ++ goto clock_set; ++ } ++ + /* + * Check if the Host Controller supports Programmable Clock + * Mode. + */ + if (host->clk_mul) { +- u16 ctrl; +- ++ for (div = 1; div <= 1024; div++) { ++ if ((host->max_clk * host->clk_mul / div) ++ <= clock) ++ break; ++ } + /* +- * We need to figure out whether the Host Driver needs +- * to select Programmable Clock Mode, or the value can +- * be set automatically by the Host Controller based on +- * the Preset Value registers. ++ * Set Programmable Clock Mode in the Clock ++ * Control register. + */ +- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); +- if (!(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) { +- for (div = 1; div <= 1024; div++) { +- if (((host->max_clk * host->clk_mul) / +- div) <= clock) +- break; +- } +- /* +- * Set Programmable Clock Mode in the Clock +- * Control register. +- */ +- clk = SDHCI_PROG_CLOCK_MODE; +- div--; +- } ++ clk = SDHCI_PROG_CLOCK_MODE; ++ real_div = div; ++ clk_mul = host->clk_mul; ++ div--; + } else { + /* Version 3.00 divisors must be a multiple of 2. */ + if (host->max_clk <= clock) +@@ -1122,6 +1178,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) + break; + } + } ++ real_div = div; + div >>= 1; + } + } else { +@@ -1130,9 +1187,14 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) + if ((host->max_clk / div) <= clock) + break; + } ++ real_div = div; + div >>= 1; + } + ++clock_set: ++ if (real_div) ++ host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div; ++ + clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; + clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) + << SDHCI_DIVIDER_HI_SHIFT; +@@ -1155,17 +1217,16 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) + + clk |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); +- +-out: +- host->clock = clock; + } ++EXPORT_SYMBOL_GPL(sdhci_set_clock); + +-static void sdhci_set_power(struct sdhci_host *host, unsigned short power) ++static void sdhci_set_power(struct sdhci_host *host, unsigned char mode, ++ unsigned short vdd) + { + u8 pwr = 0; + +- if (power != (unsigned short)-1) { +- switch (1 << power) { ++ if (mode != MMC_POWER_OFF) { ++ switch (1 << vdd) { + case MMC_VDD_165_195: + pwr = SDHCI_POWER_180; + break; +@@ -1189,33 +1250,45 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) + + if (pwr == 0) { + sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); +- return; +- } ++ if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) ++ sdhci_runtime_pm_bus_off(host); ++ vdd = 0; ++ } else { ++ /* ++ * Spec says that we should clear the power reg before setting ++ * a new value. Some controllers don't seem to like this though. ++ */ ++ if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) ++ sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); + +- /* +- * Spec says that we should clear the power reg before setting +- * a new value. Some controllers don't seem to like this though. +- */ +- if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) +- sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); ++ /* ++ * At least the Marvell CaFe chip gets confused if we set the ++ * voltage and set turn on power at the same time, so set the ++ * voltage first. ++ */ ++ if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) ++ sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); ++ ++ pwr |= SDHCI_POWER_ON; + +- /* +- * At least the Marvell CaFe chip gets confused if we set the voltage +- * and set turn on power at the same time, so set the voltage first. +- */ +- if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) + sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); + +- pwr |= SDHCI_POWER_ON; ++ if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) ++ sdhci_runtime_pm_bus_on(host); + +- sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); ++ /* ++ * Some controllers need an extra 10ms delay of 10ms before ++ * they can apply clock after applying power ++ */ ++ if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) ++ mdelay(10); ++ } + +- /* +- * Some controllers need an extra 10ms delay of 10ms before they +- * can apply clock after applying power +- */ +- if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) +- mdelay(10); ++ if (host->vmmc) { ++ spin_unlock_irq(&host->lock); ++ mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd); ++ spin_lock_irq(&host->lock); ++ } + } + + /*****************************************************************************\ +@@ -1227,8 +1300,9 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) + static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) + { + struct sdhci_host *host; +- bool present; ++ int present; + unsigned long flags; ++ u32 tuning_opcode; + + host = mmc_priv(mmc); + +@@ -1255,12 +1329,22 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) + + host->mrq = mrq; + +- /* If polling, assume that the card is always present. */ +- if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) +- present = true; +- else +- present = sdhci_readl(host, SDHCI_PRESENT_STATE) & +- SDHCI_CARD_PRESENT; ++ /* ++ * Firstly check card presence from cd-gpio. The return could ++ * be one of the following possibilities: ++ * negative: cd-gpio is not available ++ * zero: cd-gpio is used, and card is removed ++ * one: cd-gpio is used, and card is present ++ */ ++ present = mmc_gpio_get_cd(host->mmc); ++ if (present < 0) { ++ /* If polling, assume that the card is always present. */ ++ if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ++ present = 1; ++ else ++ present = sdhci_readl(host, SDHCI_PRESENT_STATE) & ++ SDHCI_CARD_PRESENT; ++ } + + if (!present || host->flags & SDHCI_DEVICE_DEAD) { + host->mrq->cmd->error = -ENOMEDIUM; +@@ -1276,12 +1360,26 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) + */ + if ((host->flags & SDHCI_NEEDS_RETUNING) && + !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { +- spin_unlock_irqrestore(&host->lock, flags); +- sdhci_execute_tuning(mmc); +- spin_lock_irqsave(&host->lock, flags); ++ if (mmc->card) { ++ /* eMMC uses cmd21 but sd and sdio use cmd19 */ ++ tuning_opcode = ++ mmc->card->type == MMC_TYPE_MMC ? ++ MMC_SEND_TUNING_BLOCK_HS200 : ++ MMC_SEND_TUNING_BLOCK; ++ ++ /* Here we need to set the host->mrq to NULL, ++ * in case the pending finish_tasklet ++ * finishes it incorrectly. ++ */ ++ host->mrq = NULL; ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_execute_tuning(mmc, tuning_opcode); ++ spin_lock_irqsave(&host->lock, flags); + +- /* Restore original mmc_request structure */ +- host->mrq = mrq; ++ /* Restore original mmc_request structure */ ++ host->mrq = mrq; ++ } + } + + if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) +@@ -1294,6 +1392,50 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) + spin_unlock_irqrestore(&host->lock, flags); + } + ++void sdhci_set_bus_width(struct sdhci_host *host, int width) ++{ ++ u8 ctrl; ++ ++ ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); ++ if (width == MMC_BUS_WIDTH_8) { ++ ctrl &= ~SDHCI_CTRL_4BITBUS; ++ if (host->version >= SDHCI_SPEC_300) ++ ctrl |= SDHCI_CTRL_8BITBUS; ++ } else { ++ if (host->version >= SDHCI_SPEC_300) ++ ctrl &= ~SDHCI_CTRL_8BITBUS; ++ if (width == MMC_BUS_WIDTH_4) ++ ctrl |= SDHCI_CTRL_4BITBUS; ++ else ++ ctrl &= ~SDHCI_CTRL_4BITBUS; ++ } ++ sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); ++} ++EXPORT_SYMBOL_GPL(sdhci_set_bus_width); ++ ++void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) ++{ ++ u16 ctrl_2; ++ ++ ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); ++ /* Select Bus Speed Mode for host */ ++ ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; ++ if ((timing == MMC_TIMING_MMC_HS200) || ++ (timing == MMC_TIMING_UHS_SDR104)) ++ ctrl_2 |= SDHCI_CTRL_UHS_SDR104; ++ else if (timing == MMC_TIMING_UHS_SDR12) ++ ctrl_2 |= SDHCI_CTRL_UHS_SDR12; ++ else if (timing == MMC_TIMING_UHS_SDR25) ++ ctrl_2 |= SDHCI_CTRL_UHS_SDR25; ++ else if (timing == MMC_TIMING_UHS_SDR50) ++ ctrl_2 |= SDHCI_CTRL_UHS_SDR50; ++ else if ((timing == MMC_TIMING_UHS_DDR50) || ++ (timing == MMC_TIMING_MMC_DDR52)) ++ ctrl_2 |= SDHCI_CTRL_UHS_DDR50; ++ sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); ++} ++EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling); ++ + static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) + { + unsigned long flags; +@@ -1301,8 +1443,12 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) + + spin_lock_irqsave(&host->lock, flags); + +- if (host->flags & SDHCI_DEVICE_DEAD) +- goto out; ++ if (host->flags & SDHCI_DEVICE_DEAD) { ++ spin_unlock_irqrestore(&host->lock, flags); ++ if (host->vmmc && ios->power_mode == MMC_POWER_OFF) ++ mmc_regulator_set_ocr(host->mmc, host->vmmc, 0); ++ return; ++ } + + /* + * Reset the chip on each power off. +@@ -1313,39 +1459,22 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) + sdhci_reinit(host); + } + +- sdhci_set_clock(host, ios->clock); ++ if (host->version >= SDHCI_SPEC_300 && ++ (ios->power_mode == MMC_POWER_UP) && ++ !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) ++ sdhci_enable_preset_value(host, false); + +- if (ios->power_mode == MMC_POWER_OFF) +- sdhci_set_power(host, -1); +- else +- sdhci_set_power(host, ios->vdd); ++ if (!ios->clock || ios->clock != host->clock) { ++ host->ops->set_clock(host, ios->clock); ++ host->clock = ios->clock; ++ } ++ ++ sdhci_set_power(host, ios->power_mode, ios->vdd); + + if (host->ops->platform_send_init_74_clocks) + host->ops->platform_send_init_74_clocks(host, ios->power_mode); + +- /* +- * If your platform has 8-bit width support but is not a v3 controller, +- * or if it requires special setup code, you should implement that in +- * platform_8bit_width(). +- */ +- if (host->ops->platform_8bit_width) +- host->ops->platform_8bit_width(host, ios->bus_width); +- else { +- ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); +- if (ios->bus_width == MMC_BUS_WIDTH_8) { +- ctrl &= ~SDHCI_CTRL_4BITBUS; +- if (host->version >= SDHCI_SPEC_300) +- ctrl |= SDHCI_CTRL_8BITBUS; +- } else { +- if (host->version >= SDHCI_SPEC_300) +- ctrl &= ~SDHCI_CTRL_8BITBUS; +- if (ios->bus_width == MMC_BUS_WIDTH_4) +- ctrl |= SDHCI_CTRL_4BITBUS; +- else +- ctrl &= ~SDHCI_CTRL_4BITBUS; +- } +- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); +- } ++ host->ops->set_bus_width(host, ios->bus_width); + + ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); + +@@ -1358,22 +1487,23 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) + + if (host->version >= SDHCI_SPEC_300) { + u16 clk, ctrl_2; +- unsigned int clock; + + /* In case of UHS-I modes, set High Speed Enable */ +- if ((ios->timing == MMC_TIMING_UHS_SDR50) || ++ if ((ios->timing == MMC_TIMING_MMC_HS200) || ++ (ios->timing == MMC_TIMING_MMC_DDR52) || ++ (ios->timing == MMC_TIMING_UHS_SDR50) || + (ios->timing == MMC_TIMING_UHS_SDR104) || + (ios->timing == MMC_TIMING_UHS_DDR50) || + (ios->timing == MMC_TIMING_UHS_SDR25)) + ctrl |= SDHCI_CTRL_HISPD; + +- ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); +- if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) { ++ if (!host->preset_enabled) { + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); + /* + * We only need to set Driver Strength if the + * preset value enable is not set. + */ ++ ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); + ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK; + if (ios->drv_type == MMC_SET_DRIVER_TYPE_A) + ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A; +@@ -1397,9 +1527,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); + + /* Re-enable SD Clock */ +- clock = host->clock; +- host->clock = 0; +- sdhci_set_clock(host, clock); ++ host->ops->set_clock(host, host->clock); + } + + +@@ -1408,29 +1536,25 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) + clk &= ~SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + +- if (host->ops->set_uhs_signaling) +- host->ops->set_uhs_signaling(host, ios->timing); +- else { +- ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); +- /* Select Bus Speed Mode for host */ +- ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; +- if (ios->timing == MMC_TIMING_UHS_SDR12) +- ctrl_2 |= SDHCI_CTRL_UHS_SDR12; +- else if (ios->timing == MMC_TIMING_UHS_SDR25) +- ctrl_2 |= SDHCI_CTRL_UHS_SDR25; +- else if (ios->timing == MMC_TIMING_UHS_SDR50) +- ctrl_2 |= SDHCI_CTRL_UHS_SDR50; +- else if (ios->timing == MMC_TIMING_UHS_SDR104) +- ctrl_2 |= SDHCI_CTRL_UHS_SDR104; +- else if (ios->timing == MMC_TIMING_UHS_DDR50) +- ctrl_2 |= SDHCI_CTRL_UHS_DDR50; +- sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); ++ host->ops->set_uhs_signaling(host, ios->timing); ++ host->timing = ios->timing; ++ ++ if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && ++ ((ios->timing == MMC_TIMING_UHS_SDR12) || ++ (ios->timing == MMC_TIMING_UHS_SDR25) || ++ (ios->timing == MMC_TIMING_UHS_SDR50) || ++ (ios->timing == MMC_TIMING_UHS_SDR104) || ++ (ios->timing == MMC_TIMING_UHS_DDR50))) { ++ u16 preset; ++ ++ sdhci_enable_preset_value(host, true); ++ preset = sdhci_get_preset_value(host); ++ ios->drv_type = (preset & SDHCI_PRESET_DRV_MASK) ++ >> SDHCI_PRESET_DRV_SHIFT; + } + + /* Re-enable SD Clock */ +- clock = host->clock; +- host->clock = 0; +- sdhci_set_clock(host, clock); ++ host->ops->set_clock(host, host->clock); + } else + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); + +@@ -1440,9 +1564,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) + * it on each ios seems to solve the problem. + */ + if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) +- sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); ++ sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + +-out: + mmiowb(); + spin_unlock_irqrestore(&host->lock, flags); + } +@@ -1456,6 +1579,37 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + sdhci_runtime_pm_put(host); + } + ++static int sdhci_do_get_cd(struct sdhci_host *host) ++{ ++ int gpio_cd = mmc_gpio_get_cd(host->mmc); ++ ++ if (host->flags & SDHCI_DEVICE_DEAD) ++ return 0; ++ ++ /* If polling/nonremovable, assume that the card is always present. */ ++ if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || ++ (host->mmc->caps & MMC_CAP_NONREMOVABLE)) ++ return 1; ++ ++ /* Try slot gpio detect */ ++ if (!IS_ERR_VALUE(gpio_cd)) ++ return !!gpio_cd; ++ ++ /* Host native card detect */ ++ return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); ++} ++ ++static int sdhci_get_cd(struct mmc_host *mmc) ++{ ++ struct sdhci_host *host = mmc_priv(mmc); ++ int ret; ++ ++ sdhci_runtime_pm_get(host); ++ ret = sdhci_do_get_cd(host); ++ sdhci_runtime_pm_put(host); ++ return ret; ++} ++ + static int sdhci_check_ro(struct sdhci_host *host) + { + unsigned long flags; +@@ -1519,24 +1673,16 @@ static int sdhci_get_ro(struct mmc_host *mmc) + + static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable) + { +- if (host->flags & SDHCI_DEVICE_DEAD) +- goto out; +- +- if (enable) +- host->flags |= SDHCI_SDIO_IRQ_ENABLED; +- else +- host->flags &= ~SDHCI_SDIO_IRQ_ENABLED; +- +- /* SDIO IRQ will be enabled as appropriate in runtime resume */ +- if (host->runtime_suspended) +- goto out; ++ if (!(host->flags & SDHCI_DEVICE_DEAD)) { ++ if (enable) ++ host->ier |= SDHCI_INT_CARD_INT; ++ else ++ host->ier &= ~SDHCI_INT_CARD_INT; + +- if (enable) +- sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT); +- else +- sdhci_mask_irqs(host, SDHCI_INT_CARD_INT); +-out: +- mmiowb(); ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ mmiowb(); ++ } + } + + static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) +@@ -1544,17 +1690,25 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) + struct sdhci_host *host = mmc_priv(mmc); + unsigned long flags; + ++ sdhci_runtime_pm_get(host); ++ + spin_lock_irqsave(&host->lock, flags); ++ if (enable) ++ host->flags |= SDHCI_SDIO_IRQ_ENABLED; ++ else ++ host->flags &= ~SDHCI_SDIO_IRQ_ENABLED; ++ + sdhci_enable_sdio_irq_nolock(host, enable); + spin_unlock_irqrestore(&host->lock, flags); ++ ++ sdhci_runtime_pm_put(host); + } + + static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, + struct mmc_ios *ios) + { +- u8 pwr; +- u16 clk, ctrl; +- u32 present_state; ++ u16 ctrl; ++ int ret; + + /* + * Signal Voltage Switching is only applicable for Host Controllers +@@ -1563,16 +1717,22 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, + if (host->version < SDHCI_SPEC_300) + return 0; + +- /* +- * 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 = sdhci_readw(host, SDHCI_HOST_CONTROL2); +- if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { ++ ++ switch (ios->signal_voltage) { ++ case MMC_SIGNAL_VOLTAGE_330: + /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ + ctrl &= ~SDHCI_CTRL_VDD_180; + sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); + ++ if (host->vqmmc) { ++ ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000); ++ if (ret) { ++ pr_warning("%s: Switching to 3.3V signalling voltage " ++ " failed\n", mmc_hostname(host->mmc)); ++ return -EIO; ++ } ++ } + /* Wait for 5ms */ + usleep_range(5000, 5500); + +@@ -1580,72 +1740,55 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); + if (!(ctrl & SDHCI_CTRL_VDD_180)) + return 0; +- else { +- pr_info(DRIVER_NAME ": Switching to 3.3V " +- "signalling voltage failed\n"); +- return -EIO; +- } +- } else if (!(ctrl & SDHCI_CTRL_VDD_180) && +- (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) { +- /* Stop SDCLK */ +- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); +- clk &= ~SDHCI_CLOCK_CARD_EN; +- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); +- +- /* Check whether DAT[3:0] is 0000 */ +- present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); +- if (!((present_state & SDHCI_DATA_LVL_MASK) >> +- SDHCI_DATA_LVL_SHIFT)) { +- /* +- * Enable 1.8V Signal Enable in the Host Control2 +- * register +- */ +- ctrl |= SDHCI_CTRL_VDD_180; +- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); + +- /* Wait for 5ms */ +- usleep_range(5000, 5500); +- +- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); +- if (ctrl & SDHCI_CTRL_VDD_180) { +- /* Provide SDCLK again and wait for 1ms*/ +- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); +- clk |= SDHCI_CLOCK_CARD_EN; +- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); +- usleep_range(1000, 1500); ++ pr_warning("%s: 3.3V regulator output did not became stable\n", ++ mmc_hostname(host->mmc)); + +- /* +- * If DAT[3:0] level is 1111b, then the card +- * was successfully switched to 1.8V signaling. +- */ +- present_state = sdhci_readl(host, +- SDHCI_PRESENT_STATE); +- if ((present_state & SDHCI_DATA_LVL_MASK) == +- SDHCI_DATA_LVL_MASK) +- return 0; ++ return -EAGAIN; ++ case MMC_SIGNAL_VOLTAGE_180: ++ if (host->vqmmc) { ++ ret = regulator_set_voltage(host->vqmmc, ++ 1700000, 1950000); ++ if (ret) { ++ pr_warning("%s: Switching to 1.8V signalling voltage " ++ " failed\n", mmc_hostname(host->mmc)); ++ return -EIO; + } + } + + /* +- * 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. ++ * Enable 1.8V Signal Enable in the Host Control2 ++ * register + */ +- pwr = sdhci_readb(host, SDHCI_POWER_CONTROL); +- pwr &= ~SDHCI_POWER_ON; +- sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); ++ ctrl |= SDHCI_CTRL_VDD_180; ++ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); + +- /* Wait for 1ms as per the spec */ +- usleep_range(1000, 1500); +- pwr |= SDHCI_POWER_ON; +- sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); ++ /* Wait for 5ms */ ++ usleep_range(5000, 5500); ++ ++ /* 1.8V regulator output should be stable within 5 ms */ ++ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); ++ if (ctrl & SDHCI_CTRL_VDD_180) ++ return 0; ++ ++ pr_warning("%s: 1.8V regulator output did not became stable\n", ++ mmc_hostname(host->mmc)); + +- pr_info(DRIVER_NAME ": Switching to 1.8V signalling " +- "voltage failed, retrying with S18R set to 0\n"); + return -EAGAIN; +- } else ++ case MMC_SIGNAL_VOLTAGE_120: ++ if (host->vqmmc) { ++ ret = regulator_set_voltage(host->vqmmc, 1100000, 1300000); ++ if (ret) { ++ pr_warning("%s: Switching to 1.2V signalling voltage " ++ " failed\n", mmc_hostname(host->mmc)); ++ return -EIO; ++ } ++ } ++ return 0; ++ default: + /* No signal voltage switch required */ + return 0; ++ } + } + + static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, +@@ -1662,38 +1805,63 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, + return err; + } + +-static int sdhci_execute_tuning(struct mmc_host *mmc) ++static int sdhci_card_busy(struct mmc_host *mmc) + { +- struct sdhci_host *host; ++ struct sdhci_host *host = mmc_priv(mmc); ++ u32 present_state; ++ ++ sdhci_runtime_pm_get(host); ++ /* Check whether DAT[3:0] is 0000 */ ++ present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); ++ sdhci_runtime_pm_put(host); ++ ++ return !(present_state & SDHCI_DATA_LVL_MASK); ++} ++ ++static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) ++{ ++ struct sdhci_host *host = mmc_priv(mmc); + u16 ctrl; +- u32 ier; + int tuning_loop_counter = MAX_TUNING_LOOP; +- unsigned long timeout; + int err = 0; + unsigned long flags; + +- host = mmc_priv(mmc); +- + sdhci_runtime_pm_get(host); + spin_lock_irqsave(&host->lock, flags); + +- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); +- + /* +- * Host Controller needs tuning only in case of SDR104 mode +- * and for SDR50 mode when Use Tuning for SDR50 is set in ++ * The Host Controller needs tuning only in case of SDR104 mode ++ * and for SDR50 mode when Use Tuning for SDR50 is set in the + * Capabilities register. ++ * If the Host Controller supports the HS200 mode then the ++ * tuning function has to be executed. + */ +- if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || +- (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && +- (host->flags & SDHCI_SDR50_NEEDS_TUNING))) +- ctrl |= SDHCI_CTRL_EXEC_TUNING; +- else { ++ switch (host->timing) { ++ case MMC_TIMING_MMC_HS200: ++ case MMC_TIMING_UHS_SDR104: ++ break; ++ ++ case MMC_TIMING_UHS_SDR50: ++ if (host->flags & SDHCI_SDR50_NEEDS_TUNING || ++ host->flags & SDHCI_SDR104_NEEDS_TUNING) ++ break; ++ /* FALLTHROUGH */ ++ ++ default: + spin_unlock_irqrestore(&host->lock, flags); + sdhci_runtime_pm_put(host); + return 0; + } + ++ if (host->ops->platform_execute_tuning) { ++ spin_unlock_irqrestore(&host->lock, flags); ++ err = host->ops->platform_execute_tuning(host, opcode); ++ sdhci_runtime_pm_put(host); ++ return err; ++ } ++ ++ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); ++ ctrl |= SDHCI_CTRL_EXEC_TUNING; + sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); + + /* +@@ -1706,28 +1874,27 @@ static int sdhci_execute_tuning(struct mmc_host *mmc) + * to make sure we don't hit a controller bug, we _only_ + * enable Buffer Read Ready interrupt here. + */ +- ier = sdhci_readl(host, SDHCI_INT_ENABLE); +- sdhci_clear_set_irqs(host, ier, SDHCI_INT_DATA_AVAIL); ++ sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); ++ sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); + + /* + * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number + * of loops reaches 40 times or a timeout of 150ms occurs. + */ +- timeout = 150; + do { + struct mmc_command cmd = {0}; + struct mmc_request mrq = {NULL}; + +- if (!tuning_loop_counter && !timeout) +- break; +- +- cmd.opcode = MMC_SEND_TUNING_BLOCK; ++ cmd.opcode = opcode; + cmd.arg = 0; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + cmd.retries = 0; + cmd.data = NULL; + cmd.error = 0; + ++ if (tuning_loop_counter-- == 0) ++ break; ++ + mrq.cmd = &cmd; + host->mrq = &mrq; + +@@ -1736,7 +1903,17 @@ static int sdhci_execute_tuning(struct mmc_host *mmc) + * block to the Host Controller. So we set the block size + * to 64 here. + */ +- sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE); ++ if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200) { ++ if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) ++ sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128), ++ SDHCI_BLOCK_SIZE); ++ else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) ++ sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), ++ SDHCI_BLOCK_SIZE); ++ } else { ++ sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), ++ SDHCI_BLOCK_SIZE); ++ } + + /* + * The tuning block is sent by the card to the host controller. +@@ -1775,25 +1952,25 @@ static int sdhci_execute_tuning(struct mmc_host *mmc) + host->tuning_done = 0; + + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); +- tuning_loop_counter--; +- timeout--; +- mdelay(1); ++ ++ /* eMMC spec does not require a delay between tuning cycles */ ++ if (opcode == MMC_SEND_TUNING_BLOCK) ++ mdelay(1); + } while (ctrl & SDHCI_CTRL_EXEC_TUNING); + + /* + * The Host Driver has exhausted the maximum number of loops allowed, + * so use fixed sampling frequency. + */ +- if (!tuning_loop_counter || !timeout) { ++ if (tuning_loop_counter < 0) { + ctrl &= ~SDHCI_CTRL_TUNED_CLK; + sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); +- } else { +- if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { +- pr_info(DRIVER_NAME ": Tuning procedure" +- " failed, falling back to fixed sampling" +- " clock\n"); +- err = -EIO; +- } ++ } ++ if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { ++ pr_info(DRIVER_NAME ": Tuning procedure" ++ " failed, falling back to fixed sampling" ++ " clock\n"); ++ err = -EIO; + } + + out: +@@ -1805,16 +1982,16 @@ out: + */ + if (!(host->flags & SDHCI_NEEDS_RETUNING) && host->tuning_count && + (host->tuning_mode == SDHCI_TUNING_MODE_1)) { ++ host->flags |= SDHCI_USING_RETUNING_TIMER; + mod_timer(&host->tuning_timer, jiffies + + host->tuning_count * HZ); + /* Tuning mode 1 limits the maximum data length to 4MB */ + mmc->max_blk_count = (4 * 1024 * 1024) / mmc->max_blk_size; +- } else { ++ } else if (host->flags & SDHCI_USING_RETUNING_TIMER) { + host->flags &= ~SDHCI_NEEDS_RETUNING; + /* Reload the new initial value for timer */ +- if (host->tuning_mode == SDHCI_TUNING_MODE_1) +- mod_timer(&host->tuning_timer, jiffies + +- host->tuning_count * HZ); ++ mod_timer(&host->tuning_timer, jiffies + ++ host->tuning_count * HZ); + } + + /* +@@ -1822,104 +1999,97 @@ out: + * try tuning again at a later time, when the re-tuning timer expires. + * So for these controllers, we return 0. Since there might be other + * controllers who do not have this capability, we return error for +- * them. ++ * them. SDHCI_USING_RETUNING_TIMER means the host is currently using ++ * a retuning timer to do the retuning for the card. + */ +- if (err && host->tuning_count && +- host->tuning_mode == SDHCI_TUNING_MODE_1) ++ if (err && (host->flags & SDHCI_USING_RETUNING_TIMER)) + err = 0; + +- sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier); ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + spin_unlock_irqrestore(&host->lock, flags); + sdhci_runtime_pm_put(host); + + return err; + } + +-static void sdhci_do_enable_preset_value(struct sdhci_host *host, bool enable) +-{ +- u16 ctrl; +- unsigned long flags; + ++static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) ++{ + /* Host Controller v3.00 defines preset value registers */ + if (host->version < SDHCI_SPEC_300) + return; + +- spin_lock_irqsave(&host->lock, flags); +- +- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); +- + /* + * We only enable or disable Preset Value if they are not already + * enabled or disabled respectively. Otherwise, we bail out. + */ +- if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) { +- ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; +- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); +- host->flags |= SDHCI_PV_ENABLED; +- } else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) { +- ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; +- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); +- host->flags &= ~SDHCI_PV_ENABLED; +- } ++ if (host->preset_enabled != enable) { ++ u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); + +- spin_unlock_irqrestore(&host->lock, flags); +-} +- +-static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable) +-{ +- struct sdhci_host *host = mmc_priv(mmc); ++ if (enable) ++ ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; ++ else ++ ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; + +- sdhci_runtime_pm_get(host); +- sdhci_do_enable_preset_value(host, enable); +- sdhci_runtime_pm_put(host); +-} ++ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); + +-static const struct mmc_host_ops sdhci_ops = { +- .request = sdhci_request, +- .set_ios = sdhci_set_ios, +- .get_ro = sdhci_get_ro, +- .hw_reset = sdhci_hw_reset, +- .enable_sdio_irq = sdhci_enable_sdio_irq, +- .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, +- .execute_tuning = sdhci_execute_tuning, +- .enable_preset_value = sdhci_enable_preset_value, +-}; ++ if (enable) ++ host->flags |= SDHCI_PV_ENABLED; ++ else ++ host->flags &= ~SDHCI_PV_ENABLED; + +-/*****************************************************************************\ +- * * +- * Tasklets * +- * * +-\*****************************************************************************/ ++ host->preset_enabled = enable; ++ } ++} + +-static void sdhci_tasklet_card(unsigned long param) ++static void sdhci_card_event(struct mmc_host *mmc) + { +- struct sdhci_host *host; ++ struct sdhci_host *host = mmc_priv(mmc); + unsigned long flags; + +- host = (struct sdhci_host*)param; ++ /* First check if client has provided their own card event */ ++ if (host->ops->card_event) ++ host->ops->card_event(host); + + spin_lock_irqsave(&host->lock, flags); + + /* Check host->mrq first in case we are runtime suspended */ +- if (host->mrq && +- !(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { ++ if (host->mrq && !sdhci_do_get_cd(host)) { + pr_err("%s: Card removed during transfer!\n", + mmc_hostname(host->mmc)); + pr_err("%s: Resetting controller.\n", + mmc_hostname(host->mmc)); + +- sdhci_reset(host, SDHCI_RESET_CMD); +- sdhci_reset(host, SDHCI_RESET_DATA); ++ sdhci_do_reset(host, SDHCI_RESET_CMD); ++ sdhci_do_reset(host, SDHCI_RESET_DATA); + + host->mrq->cmd->error = -ENOMEDIUM; + tasklet_schedule(&host->finish_tasklet); + } + + spin_unlock_irqrestore(&host->lock, flags); +- +- mmc_detect_change(host->mmc, msecs_to_jiffies(200)); + } + ++static const struct mmc_host_ops sdhci_ops = { ++ .request = sdhci_request, ++ .set_ios = sdhci_set_ios, ++ .get_cd = sdhci_get_cd, ++ .get_ro = sdhci_get_ro, ++ .hw_reset = sdhci_hw_reset, ++ .enable_sdio_irq = sdhci_enable_sdio_irq, ++ .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, ++ .execute_tuning = sdhci_execute_tuning, ++ .card_event = sdhci_card_event, ++ .card_busy = sdhci_card_busy, ++}; ++ ++/*****************************************************************************\ ++ * * ++ * Tasklets * ++ * * ++\*****************************************************************************/ ++ + static void sdhci_tasklet_finish(unsigned long param) + { + struct sdhci_host *host; +@@ -1954,19 +2124,14 @@ static void sdhci_tasklet_finish(unsigned long param) + (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { + + /* Some controllers need this kick or reset won't work here */ +- if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { +- unsigned int clock; +- ++ if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) + /* This is to force an update */ +- clock = host->clock; +- host->clock = 0; +- sdhci_set_clock(host, clock); +- } ++ host->ops->set_clock(host, host->clock); + + /* Spec says we should do both at the same time, but Ricoh + controllers do not like that. */ +- sdhci_reset(host, SDHCI_RESET_CMD); +- sdhci_reset(host, SDHCI_RESET_DATA); ++ sdhci_do_reset(host, SDHCI_RESET_CMD); ++ sdhci_do_reset(host, SDHCI_RESET_DATA); + } + + host->mrq = NULL; +@@ -2115,12 +2280,14 @@ static void sdhci_show_adma_error(struct sdhci_host *host) { } + + static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) + { ++ u32 command; + BUG_ON(intmask == 0); + + /* CMD19 generates _only_ Buffer Read Ready interrupt */ + if (intmask & SDHCI_INT_DATA_AVAIL) { +- if (SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) == +- MMC_SEND_TUNING_BLOCK) { ++ command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)); ++ if (command == MMC_SEND_TUNING_BLOCK || ++ command == MMC_SEND_TUNING_BLOCK_HS200) { + host->tuning_done = 1; + wake_up(&host->buf_ready_int); + return; +@@ -2160,6 +2327,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) + pr_err("%s: ADMA error\n", mmc_hostname(host->mmc)); + sdhci_show_adma_error(host); + host->data->error = -EIO; ++ if (host->ops->adma_workaround) ++ host->ops->adma_workaround(host, intmask); + } + + if (host->data->error) +@@ -2212,105 +2381,132 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) + + static irqreturn_t sdhci_irq(int irq, void *dev_id) + { +- irqreturn_t result; ++ irqreturn_t result = IRQ_NONE; + struct sdhci_host *host = dev_id; +- u32 intmask; +- int cardint = 0; ++ u32 intmask, mask, unexpected = 0; ++ int max_loops = 16; + + spin_lock(&host->lock); + +- if (host->runtime_suspended) { ++ if (host->runtime_suspended && !sdhci_sdio_irq_enabled(host)) { + spin_unlock(&host->lock); +- pr_warning("%s: got irq while runtime suspended\n", +- mmc_hostname(host->mmc)); +- return IRQ_HANDLED; ++ return IRQ_NONE; + } + + intmask = sdhci_readl(host, SDHCI_INT_STATUS); +- + if (!intmask || intmask == 0xffffffff) { + result = IRQ_NONE; + goto out; + } + +- DBG("*** %s got interrupt: 0x%08x\n", +- mmc_hostname(host->mmc), intmask); ++ do { ++ /* Clear selected interrupts. */ ++ mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | ++ SDHCI_INT_BUS_POWER); ++ sdhci_writel(host, mask, SDHCI_INT_STATUS); + +- if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { +- u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) & +- SDHCI_CARD_PRESENT; ++ DBG("*** %s got interrupt: 0x%08x\n", ++ mmc_hostname(host->mmc), intmask); + +- /* +- * There is a observation on i.mx esdhc. INSERT bit will be +- * immediately set again when it gets cleared, if a card is +- * inserted. We have to mask the irq to prevent interrupt +- * storm which will freeze the system. And the REMOVE gets +- * the same situation. +- * +- * More testing are needed here to ensure it works for other +- * platforms though. +- */ +- sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT : +- SDHCI_INT_CARD_REMOVE); +- sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE : +- SDHCI_INT_CARD_INSERT); ++ if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { ++ u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) & ++ SDHCI_CARD_PRESENT; + +- sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | +- SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); +- intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); +- tasklet_schedule(&host->card_tasklet); +- } ++ /* ++ * There is a observation on i.mx esdhc. INSERT ++ * bit will be immediately set again when it gets ++ * cleared, if a card is inserted. We have to mask ++ * the irq to prevent interrupt storm which will ++ * freeze the system. And the REMOVE gets the ++ * same situation. ++ * ++ * More testing are needed here to ensure it works ++ * for other platforms though. ++ */ ++ host->ier &= ~(SDHCI_INT_CARD_INSERT | ++ SDHCI_INT_CARD_REMOVE); ++ host->ier |= present ? SDHCI_INT_CARD_REMOVE : ++ SDHCI_INT_CARD_INSERT; ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ ++ sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | ++ SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); ++ ++ host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT | ++ SDHCI_INT_CARD_REMOVE); ++ result = IRQ_WAKE_THREAD; ++ } + +- if (intmask & SDHCI_INT_CMD_MASK) { +- sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, +- SDHCI_INT_STATUS); +- sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); +- } ++ if (intmask & SDHCI_INT_CMD_MASK) ++ sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); + +- if (intmask & SDHCI_INT_DATA_MASK) { +- sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK, +- SDHCI_INT_STATUS); +- sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); +- } ++ if (intmask & SDHCI_INT_DATA_MASK) ++ sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); + +- intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); ++ if (intmask & SDHCI_INT_BUS_POWER) ++ pr_err("%s: Card is consuming too much power!\n", ++ mmc_hostname(host->mmc)); + +- intmask &= ~SDHCI_INT_ERROR; ++ if (intmask & SDHCI_INT_CARD_INT) { ++ sdhci_enable_sdio_irq_nolock(host, false); ++ host->thread_isr |= SDHCI_INT_CARD_INT; ++ result = IRQ_WAKE_THREAD; ++ } + +- if (intmask & SDHCI_INT_BUS_POWER) { +- pr_err("%s: Card is consuming too much power!\n", +- mmc_hostname(host->mmc)); +- sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS); +- } ++ intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | ++ SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | ++ SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | ++ SDHCI_INT_CARD_INT); + +- intmask &= ~SDHCI_INT_BUS_POWER; ++ if (intmask) { ++ unexpected |= intmask; ++ sdhci_writel(host, intmask, SDHCI_INT_STATUS); ++ } + +- if (intmask & SDHCI_INT_CARD_INT) +- cardint = 1; ++ if (result == IRQ_NONE) ++ result = IRQ_HANDLED; + +- intmask &= ~SDHCI_INT_CARD_INT; ++ intmask = sdhci_readl(host, SDHCI_INT_STATUS); ++ } while (intmask && --max_loops); ++out: ++ spin_unlock(&host->lock); + +- if (intmask) { ++ if (unexpected) { + pr_err("%s: Unexpected interrupt 0x%08x.\n", +- mmc_hostname(host->mmc), intmask); ++ mmc_hostname(host->mmc), unexpected); + sdhci_dumpregs(host); +- +- sdhci_writel(host, intmask, SDHCI_INT_STATUS); + } + +- result = IRQ_HANDLED; ++ return result; ++} + +- mmiowb(); +-out: +- spin_unlock(&host->lock); ++static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) ++{ ++ struct sdhci_host *host = dev_id; ++ unsigned long flags; ++ u32 isr; + +- /* +- * We have to delay this as it calls back into the driver. +- */ +- if (cardint) +- mmc_signal_sdio_irq(host->mmc); ++ spin_lock_irqsave(&host->lock, flags); ++ isr = host->thread_isr; ++ host->thread_isr = 0; ++ spin_unlock_irqrestore(&host->lock, flags); + +- return result; ++ if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { ++ sdhci_card_event(host->mmc); ++ mmc_detect_change(host->mmc, msecs_to_jiffies(200)); ++ } ++ ++ if (isr & SDHCI_INT_CARD_INT) { ++ sdio_run_irqs(host->mmc); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ if (host->flags & SDHCI_SDIO_IRQ_ENABLED) ++ sdhci_enable_sdio_irq_nolock(host, true); ++ spin_unlock_irqrestore(&host->lock, flags); ++ } ++ ++ return isr ? IRQ_HANDLED : IRQ_NONE; + } + + /*****************************************************************************\ +@@ -2320,80 +2516,99 @@ out: + \*****************************************************************************/ + + #ifdef CONFIG_PM ++void sdhci_enable_irq_wakeups(struct sdhci_host *host) ++{ ++ u8 val; ++ u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE ++ | SDHCI_WAKE_ON_INT; + +-int sdhci_suspend_host(struct sdhci_host *host) ++ val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); ++ val |= mask ; ++ /* Avoid fake wake up */ ++ if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ++ val &= ~(SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE); ++ sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); ++} ++EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups); ++ ++void sdhci_disable_irq_wakeups(struct sdhci_host *host) + { +- int ret; ++ u8 val; ++ u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE ++ | SDHCI_WAKE_ON_INT; + ++ val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); ++ val &= ~mask; ++ sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); ++} ++EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups); ++ ++int sdhci_suspend_host(struct sdhci_host *host) ++{ + sdhci_disable_card_detection(host); + + /* Disable tuning since we are suspending */ +- if (host->version >= SDHCI_SPEC_300 && host->tuning_count && +- host->tuning_mode == SDHCI_TUNING_MODE_1) { ++ if (host->flags & SDHCI_USING_RETUNING_TIMER) { + del_timer_sync(&host->tuning_timer); + host->flags &= ~SDHCI_NEEDS_RETUNING; + } + +- ret = mmc_suspend_host(host->mmc); +- if (ret) +- return ret; +- +- free_irq(host->irq, host); +- +- if (host->vmmc) +- ret = regulator_disable(host->vmmc); +- +- return ret; ++ if (!device_may_wakeup(mmc_dev(host->mmc))) { ++ host->ier = 0; ++ sdhci_writel(host, 0, SDHCI_INT_ENABLE); ++ sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); ++ free_irq(host->irq, host); ++ } else { ++ sdhci_enable_irq_wakeups(host); ++ enable_irq_wake(host->irq); ++ } ++ return 0; + } + + EXPORT_SYMBOL_GPL(sdhci_suspend_host); + + int sdhci_resume_host(struct sdhci_host *host) + { +- int ret; +- +- if (host->vmmc) { +- int ret = regulator_enable(host->vmmc); +- if (ret) +- return ret; +- } ++ int ret = 0; + + if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { + if (host->ops->enable_dma) + host->ops->enable_dma(host); + } + +- ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, +- mmc_hostname(host->mmc), host); +- if (ret) +- return ret; ++ if (!device_may_wakeup(mmc_dev(host->mmc))) { ++ ret = request_threaded_irq(host->irq, sdhci_irq, ++ sdhci_thread_irq, IRQF_SHARED, ++ mmc_hostname(host->mmc), host); ++ if (ret) ++ return ret; ++ } else { ++ sdhci_disable_irq_wakeups(host); ++ disable_irq_wake(host->irq); ++ } + +- sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); +- mmiowb(); ++ if ((host->mmc->pm_flags & MMC_PM_KEEP_POWER) && ++ (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) { ++ /* Card keeps power but host controller does not */ ++ sdhci_init(host, 0); ++ host->pwr = 0; ++ host->clock = 0; ++ sdhci_do_set_ios(host, &host->mmc->ios); ++ } else { ++ sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); ++ mmiowb(); ++ } + +- ret = mmc_resume_host(host->mmc); + sdhci_enable_card_detection(host); + + /* Set the re-tuning expiration flag */ +- if ((host->version >= SDHCI_SPEC_300) && host->tuning_count && +- (host->tuning_mode == SDHCI_TUNING_MODE_1)) ++ if (host->flags & SDHCI_USING_RETUNING_TIMER) + host->flags |= SDHCI_NEEDS_RETUNING; + + return ret; + } + + EXPORT_SYMBOL_GPL(sdhci_resume_host); +- +-void sdhci_enable_irq_wakeups(struct sdhci_host *host) +-{ +- u8 val; +- val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); +- val |= SDHCI_WAKE_ON_INT; +- sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); +-} +- +-EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups); +- + #endif /* CONFIG_PM */ + + #ifdef CONFIG_PM_RUNTIME +@@ -2409,23 +2624,40 @@ static int sdhci_runtime_pm_put(struct sdhci_host *host) + return pm_runtime_put_autosuspend(host->mmc->parent); + } + ++static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) ++{ ++ if (host->runtime_suspended || host->bus_on) ++ return; ++ host->bus_on = true; ++ pm_runtime_get_noresume(host->mmc->parent); ++} ++ ++static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) ++{ ++ if (host->runtime_suspended || !host->bus_on) ++ return; ++ host->bus_on = false; ++ pm_runtime_put_noidle(host->mmc->parent); ++} ++ + int sdhci_runtime_suspend_host(struct sdhci_host *host) + { + unsigned long flags; + int ret = 0; + + /* Disable tuning since we are suspending */ +- if (host->version >= SDHCI_SPEC_300 && +- host->tuning_mode == SDHCI_TUNING_MODE_1) { ++ if (host->flags & SDHCI_USING_RETUNING_TIMER) { + del_timer_sync(&host->tuning_timer); + host->flags &= ~SDHCI_NEEDS_RETUNING; + } + + spin_lock_irqsave(&host->lock, flags); +- sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); ++ host->ier &= SDHCI_INT_CARD_INT; ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + spin_unlock_irqrestore(&host->lock, flags); + +- synchronize_irq(host->irq); ++ synchronize_hardirq(host->irq); + + spin_lock_irqsave(&host->lock, flags); + host->runtime_suspended = true; +@@ -2453,12 +2685,15 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) + sdhci_do_set_ios(host, &host->mmc->ios); + + sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios); +- if (host_flags & SDHCI_PV_ENABLED) +- sdhci_do_enable_preset_value(host, true); ++ if ((host_flags & SDHCI_PV_ENABLED) && ++ !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) { ++ spin_lock_irqsave(&host->lock, flags); ++ sdhci_enable_preset_value(host, true); ++ spin_unlock_irqrestore(&host->lock, flags); ++ } + + /* Set the re-tuning expiration flag */ +- if ((host->version >= SDHCI_SPEC_300) && host->tuning_count && +- (host->tuning_mode == SDHCI_TUNING_MODE_1)) ++ if (host->flags & SDHCI_USING_RETUNING_TIMER) + host->flags |= SDHCI_NEEDS_RETUNING; + + spin_lock_irqsave(&host->lock, flags); +@@ -2466,7 +2701,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) + host->runtime_suspended = false; + + /* Enable SDIO IRQ */ +- if ((host->flags & SDHCI_SDIO_IRQ_ENABLED)) ++ if (host->flags & SDHCI_SDIO_IRQ_ENABLED) + sdhci_enable_sdio_irq_nolock(host, true); + + /* Enable Card Detection */ +@@ -2509,7 +2744,7 @@ EXPORT_SYMBOL_GPL(sdhci_alloc_host); + int sdhci_add_host(struct sdhci_host *host) + { + struct mmc_host *mmc; +- u32 caps[2]; ++ u32 caps[2] = {0, 0}; + u32 max_current_caps; + unsigned int ocr_avail; + int ret; +@@ -2525,7 +2760,7 @@ int sdhci_add_host(struct sdhci_host *host) + if (debug_quirks2) + host->quirks2 = debug_quirks2; + +- sdhci_reset(host, SDHCI_RESET_ALL); ++ sdhci_do_reset(host, SDHCI_RESET_ALL); + + host->version = sdhci_readw(host, SDHCI_HOST_VERSION); + host->version = (host->version & SDHCI_SPEC_VER_MASK) +@@ -2539,8 +2774,10 @@ int sdhci_add_host(struct sdhci_host *host) + caps[0] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps : + sdhci_readl(host, SDHCI_CAPABILITIES); + +- caps[1] = (host->version >= SDHCI_SPEC_300) ? +- sdhci_readl(host, SDHCI_CAPABILITIES_1) : 0; ++ if (host->version >= SDHCI_SPEC_300) ++ caps[1] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? ++ host->caps1 : ++ sdhci_readl(host, SDHCI_CAPABILITIES_1); + + if (host->quirks & SDHCI_QUIRK_FORCE_DMA) + host->flags |= SDHCI_USE_SDMA; +@@ -2583,15 +2820,29 @@ int sdhci_add_host(struct sdhci_host *host) + * (128) and potentially one alignment transfer for + * each of those entries. + */ +- host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL); ++ host->adma_desc = dma_alloc_coherent(mmc_dev(host->mmc), ++ ADMA_SIZE, &host->adma_addr, ++ GFP_KERNEL); + host->align_buffer = kmalloc(128 * 4, GFP_KERNEL); + if (!host->adma_desc || !host->align_buffer) { +- kfree(host->adma_desc); ++ dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE, ++ host->adma_desc, host->adma_addr); + kfree(host->align_buffer); + pr_warning("%s: Unable to allocate ADMA " + "buffers. Falling back to standard DMA.\n", + mmc_hostname(mmc)); + host->flags &= ~SDHCI_USE_ADMA; ++ host->adma_desc = NULL; ++ host->align_buffer = NULL; ++ } else if (host->adma_addr & 3) { ++ pr_warning("%s: unable to allocate aligned ADMA descriptor\n", ++ mmc_hostname(mmc)); ++ host->flags &= ~SDHCI_USE_ADMA; ++ dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE, ++ host->adma_desc, host->adma_addr); ++ kfree(host->align_buffer); ++ host->adma_desc = NULL; ++ host->align_buffer = NULL; + } + } + +@@ -2673,9 +2924,10 @@ int sdhci_add_host(struct sdhci_host *host) + if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) + host->timeout_clk = mmc->f_max / 1000; + +- mmc->max_discard_to = (1 << 27) / host->timeout_clk; ++ mmc->max_busy_timeout = (1 << 27) / host->timeout_clk; + + mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; ++ mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; + + if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) + host->flags |= SDHCI_AUTO_CMD12; +@@ -2700,31 +2952,70 @@ int sdhci_add_host(struct sdhci_host *host) + if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) + mmc->caps |= MMC_CAP_4_BIT_DATA; + ++ if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) ++ mmc->caps &= ~MMC_CAP_CMD23; ++ + if (caps[0] & SDHCI_CAN_DO_HISPD) + mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; + + if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && +- mmc_card_is_removable(mmc)) ++ !(host->mmc->caps & MMC_CAP_NONREMOVABLE)) + mmc->caps |= MMC_CAP_NEEDS_POLL; + ++ /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ ++ host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc"); ++ if (IS_ERR_OR_NULL(host->vqmmc)) { ++ if (PTR_ERR(host->vqmmc) < 0) { ++ pr_info("%s: no vqmmc regulator found\n", ++ mmc_hostname(mmc)); ++ host->vqmmc = NULL; ++ } ++ } else { ++ ret = regulator_enable(host->vqmmc); ++ if (!regulator_is_supported_voltage(host->vqmmc, 1700000, ++ 1950000)) ++ caps[1] &= ~(SDHCI_SUPPORT_SDR104 | ++ SDHCI_SUPPORT_SDR50 | ++ SDHCI_SUPPORT_DDR50); ++ if (ret) { ++ pr_warn("%s: Failed to enable vqmmc regulator: %d\n", ++ mmc_hostname(mmc), ret); ++ host->vqmmc = NULL; ++ } ++ } ++ ++ if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) ++ caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | ++ SDHCI_SUPPORT_DDR50); ++ + /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ + if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | + SDHCI_SUPPORT_DDR50)) + mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; + + /* SDR104 supports also implies SDR50 support */ +- if (caps[1] & SDHCI_SUPPORT_SDR104) ++ if (caps[1] & SDHCI_SUPPORT_SDR104) { + mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; +- else if (caps[1] & SDHCI_SUPPORT_SDR50) ++ /* SD3.0: SDR104 is supported so (for eMMC) the caps2 ++ * field can be promoted to support HS200. ++ */ ++ if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) ++ mmc->caps2 |= MMC_CAP2_HS200; ++ } else if (caps[1] & SDHCI_SUPPORT_SDR50) + mmc->caps |= MMC_CAP_UHS_SDR50; + +- if (caps[1] & SDHCI_SUPPORT_DDR50) ++ if ((caps[1] & SDHCI_SUPPORT_DDR50) && ++ !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) + mmc->caps |= MMC_CAP_UHS_DDR50; + +- /* Does the host needs tuning for SDR50? */ ++ /* Does the host need tuning for SDR50? */ + if (caps[1] & SDHCI_USE_SDR50_TUNING) + host->flags |= SDHCI_SDR50_NEEDS_TUNING; + ++ /* Does the host need tuning for SDR104 / HS200? */ ++ if (mmc->caps2 & MMC_CAP2_HS200) ++ host->flags |= SDHCI_SDR104_NEEDS_TUNING; ++ + /* Driver Type(s) (A, C, D) supported by the host */ + if (caps[1] & SDHCI_DRIVER_TYPE_A) + mmc->caps |= MMC_CAP_DRIVER_TYPE_A; +@@ -2733,15 +3024,6 @@ int sdhci_add_host(struct sdhci_host *host) + if (caps[1] & SDHCI_DRIVER_TYPE_D) + mmc->caps |= MMC_CAP_DRIVER_TYPE_D; + +- /* +- * If Power Off Notify capability is enabled by the host, +- * set notify to short power off notify timeout value. +- */ +- if (mmc->caps2 & MMC_CAP2_POWEROFF_NOTIFY) +- mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT; +- else +- mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE; +- + /* Initial value for re-tuning timer count */ + host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >> + SDHCI_RETUNING_TIMER_COUNT_SHIFT; +@@ -2758,6 +3040,35 @@ int sdhci_add_host(struct sdhci_host *host) + SDHCI_RETUNING_MODE_SHIFT; + + ocr_avail = 0; ++ ++ host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); ++ if (IS_ERR_OR_NULL(host->vmmc)) { ++ if (PTR_ERR(host->vmmc) < 0) { ++ pr_info("%s: no vmmc regulator found\n", ++ mmc_hostname(mmc)); ++ host->vmmc = NULL; ++ } ++ } ++ ++#ifdef CONFIG_REGULATOR ++ /* ++ * Voltage range check makes sense only if regulator reports ++ * any voltage value. ++ */ ++ if (host->vmmc && regulator_get_voltage(host->vmmc) > 0) { ++ ret = regulator_is_supported_voltage(host->vmmc, 2700000, ++ 3600000); ++ if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_330))) ++ caps[0] &= ~SDHCI_CAN_VDD_330; ++ if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_300))) ++ caps[0] &= ~SDHCI_CAN_VDD_300; ++ ret = regulator_is_supported_voltage(host->vmmc, 1700000, ++ 1950000); ++ if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_180))) ++ caps[0] &= ~SDHCI_CAN_VDD_180; ++ } ++#endif /* CONFIG_REGULATOR */ ++ + /* + * According to SD Host Controller spec v3.00, if the Host System + * can afford more than 150mA, Host Driver should set XPC to 1. Also +@@ -2766,57 +3077,50 @@ int sdhci_add_host(struct sdhci_host *host) + * value. + */ + max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT); ++ if (!max_current_caps && host->vmmc) { ++ u32 curr = regulator_get_current_limit(host->vmmc); ++ if (curr > 0) { ++ ++ /* convert to SDHCI_MAX_CURRENT format */ ++ curr = curr/1000; /* convert to mA */ ++ curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER; ++ ++ curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT); ++ max_current_caps = ++ (curr << SDHCI_MAX_CURRENT_330_SHIFT) | ++ (curr << SDHCI_MAX_CURRENT_300_SHIFT) | ++ (curr << SDHCI_MAX_CURRENT_180_SHIFT); ++ } ++ } + + if (caps[0] & SDHCI_CAN_VDD_330) { +- int max_current_330; +- + ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34; + +- max_current_330 = ((max_current_caps & ++ mmc->max_current_330 = ((max_current_caps & + SDHCI_MAX_CURRENT_330_MASK) >> + SDHCI_MAX_CURRENT_330_SHIFT) * + SDHCI_MAX_CURRENT_MULTIPLIER; +- +- if (max_current_330 > 150) +- mmc->caps |= MMC_CAP_SET_XPC_330; + } + if (caps[0] & SDHCI_CAN_VDD_300) { +- int max_current_300; +- + ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31; + +- max_current_300 = ((max_current_caps & ++ mmc->max_current_300 = ((max_current_caps & + SDHCI_MAX_CURRENT_300_MASK) >> + SDHCI_MAX_CURRENT_300_SHIFT) * + SDHCI_MAX_CURRENT_MULTIPLIER; +- +- if (max_current_300 > 150) +- mmc->caps |= MMC_CAP_SET_XPC_300; + } + if (caps[0] & SDHCI_CAN_VDD_180) { +- int max_current_180; +- + ocr_avail |= MMC_VDD_165_195; + +- max_current_180 = ((max_current_caps & ++ mmc->max_current_180 = ((max_current_caps & + SDHCI_MAX_CURRENT_180_MASK) >> + SDHCI_MAX_CURRENT_180_SHIFT) * + SDHCI_MAX_CURRENT_MULTIPLIER; +- +- if (max_current_180 > 150) +- mmc->caps |= MMC_CAP_SET_XPC_180; +- +- /* Maximum current capabilities of the host at 1.8V */ +- if (max_current_180 >= 800) +- mmc->caps |= MMC_CAP_MAX_CURRENT_800; +- else if (max_current_180 >= 600) +- mmc->caps |= MMC_CAP_MAX_CURRENT_600; +- else if (max_current_180 >= 400) +- mmc->caps |= MMC_CAP_MAX_CURRENT_400; +- else +- mmc->caps |= MMC_CAP_MAX_CURRENT_200; + } + ++ if (host->ocr_mask) ++ ocr_avail = host->ocr_mask; ++ + mmc->ocr_avail = ocr_avail; + mmc->ocr_avail_sdio = ocr_avail; + if (host->ocr_avail_sdio) +@@ -2895,8 +3199,6 @@ int sdhci_add_host(struct sdhci_host *host) + /* + * Init tasklets. + */ +- tasklet_init(&host->card_tasklet, +- sdhci_tasklet_card, (unsigned long)host); + tasklet_init(&host->finish_tasklet, + sdhci_tasklet_finish, (unsigned long)host); + +@@ -2911,21 +3213,16 @@ int sdhci_add_host(struct sdhci_host *host) + host->tuning_timer.function = sdhci_tuning_timer; + } + +- ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, +- mmc_hostname(mmc), host); +- if (ret) +- goto untasklet; ++ sdhci_init(host, 0); + +- host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); +- if (IS_ERR(host->vmmc)) { +- pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); +- host->vmmc = NULL; +- } else { +- regulator_enable(host->vmmc); ++ ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, ++ IRQF_SHARED, mmc_hostname(mmc), host); ++ if (ret) { ++ pr_err("%s: Failed to request IRQ %d: %d\n", ++ mmc_hostname(mmc), host->irq, ret); ++ goto untasklet; + } + +- sdhci_init(host, 0); +- + #ifdef CONFIG_MMC_DEBUG + sdhci_dumpregs(host); + #endif +@@ -2939,8 +3236,11 @@ int sdhci_add_host(struct sdhci_host *host) + host->led.brightness_set = sdhci_led_control; + + ret = led_classdev_register(mmc_dev(mmc), &host->led); +- if (ret) ++ if (ret) { ++ pr_err("%s: Failed to register LED device: %d\n", ++ mmc_hostname(mmc), ret); + goto reset; ++ } + #endif + + mmiowb(); +@@ -2958,11 +3258,12 @@ int sdhci_add_host(struct sdhci_host *host) + + #ifdef SDHCI_USE_LEDS_CLASS + reset: +- sdhci_reset(host, SDHCI_RESET_ALL); ++ sdhci_do_reset(host, SDHCI_RESET_ALL); ++ sdhci_writel(host, 0, SDHCI_INT_ENABLE); ++ sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); + free_irq(host->irq, host); + #endif + untasklet: +- tasklet_kill(&host->card_tasklet); + tasklet_kill(&host->finish_tasklet); + + return ret; +@@ -2999,15 +3300,14 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) + #endif + + if (!dead) +- sdhci_reset(host, SDHCI_RESET_ALL); ++ sdhci_do_reset(host, SDHCI_RESET_ALL); + ++ sdhci_writel(host, 0, SDHCI_INT_ENABLE); ++ sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); + free_irq(host->irq, host); + + del_timer_sync(&host->timer); +- if (host->version >= SDHCI_SPEC_300) +- del_timer_sync(&host->tuning_timer); + +- tasklet_kill(&host->card_tasklet); + tasklet_kill(&host->finish_tasklet); + + if (host->vmmc) { +@@ -3015,7 +3315,14 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) + regulator_put(host->vmmc); + } + +- kfree(host->adma_desc); ++ if (host->vqmmc) { ++ regulator_disable(host->vqmmc); ++ regulator_put(host->vqmmc); ++ } ++ ++ if (host->adma_desc) ++ dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE, ++ host->adma_desc, host->adma_addr); + kfree(host->align_buffer); + + host->adma_desc = NULL; +diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h +index a04d4d0..4a5cd5e 100644 +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -120,6 +120,7 @@ + #define SDHCI_SIGNAL_ENABLE 0x38 + #define SDHCI_INT_RESPONSE 0x00000001 + #define SDHCI_INT_DATA_END 0x00000002 ++#define SDHCI_INT_BLK_GAP 0x00000004 + #define SDHCI_INT_DMA_END 0x00000008 + #define SDHCI_INT_SPACE_AVAIL 0x00000010 + #define SDHCI_INT_DATA_AVAIL 0x00000020 +@@ -146,7 +147,8 @@ + #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 | \ +- SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR) ++ SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | \ ++ SDHCI_INT_BLK_GAP) + #define SDHCI_INT_ALL_MASK ((unsigned int)-1) + + #define SDHCI_ACMD12_ERR 0x3C +@@ -158,6 +160,7 @@ + #define SDHCI_CTRL_UHS_SDR50 0x0002 + #define SDHCI_CTRL_UHS_SDR104 0x0003 + #define SDHCI_CTRL_UHS_DDR50 0x0004 ++#define SDHCI_CTRL_HS_SDR200 0x0005 /* reserved value in SDIO spec */ + #define SDHCI_CTRL_VDD_180 0x0008 + #define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 + #define SDHCI_CTRL_DRV_TYPE_B 0x0000 +@@ -204,6 +207,7 @@ + #define SDHCI_CAPABILITIES_1 0x44 + + #define SDHCI_MAX_CURRENT 0x48 ++#define SDHCI_MAX_CURRENT_LIMIT 0xFF + #define SDHCI_MAX_CURRENT_330_MASK 0x0000FF + #define SDHCI_MAX_CURRENT_330_SHIFT 0 + #define SDHCI_MAX_CURRENT_300_MASK 0x00FF00 +@@ -225,6 +229,18 @@ + + /* 60-FB reserved */ + ++#define SDHCI_PRESET_FOR_SDR12 0x66 ++#define SDHCI_PRESET_FOR_SDR25 0x68 ++#define SDHCI_PRESET_FOR_SDR50 0x6A ++#define SDHCI_PRESET_FOR_SDR104 0x6C ++#define SDHCI_PRESET_FOR_DDR50 0x6E ++#define SDHCI_PRESET_DRV_MASK 0xC000 ++#define SDHCI_PRESET_DRV_SHIFT 14 ++#define SDHCI_PRESET_CLKGEN_SEL_MASK 0x400 ++#define SDHCI_PRESET_CLKGEN_SEL_SHIFT 10 ++#define SDHCI_PRESET_SDCLK_FREQ_MASK 0x3FF ++#define SDHCI_PRESET_SDCLK_FREQ_SHIFT 0 ++ + #define SDHCI_SLOT_INT_STATUS 0xFC + + #define SDHCI_HOST_VERSION 0xFE +@@ -265,15 +281,17 @@ struct sdhci_ops { + unsigned int (*get_max_clock)(struct sdhci_host *host); + unsigned int (*get_min_clock)(struct sdhci_host *host); + unsigned int (*get_timeout_clock)(struct sdhci_host *host); +- int (*platform_8bit_width)(struct sdhci_host *host, +- int width); ++ void (*set_bus_width)(struct sdhci_host *host, int width); + void (*platform_send_init_74_clocks)(struct sdhci_host *host, + u8 power_mode); + unsigned int (*get_ro)(struct sdhci_host *host); +- void (*platform_reset_enter)(struct sdhci_host *host, u8 mask); +- void (*platform_reset_exit)(struct sdhci_host *host, u8 mask); +- int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); ++ void (*reset)(struct sdhci_host *host, u8 mask); ++ int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode); ++ void (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); + void (*hw_reset)(struct sdhci_host *host); ++ void (*adma_workaround)(struct sdhci_host *host, u32 intmask); ++ void (*platform_init)(struct sdhci_host *host); ++ void (*card_event)(struct sdhci_host *host); + }; + + #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS +@@ -372,6 +390,18 @@ static inline void *sdhci_priv(struct sdhci_host *host) + extern void sdhci_card_detect(struct sdhci_host *host); + extern int sdhci_add_host(struct sdhci_host *host); + extern void sdhci_remove_host(struct sdhci_host *host, int dead); ++extern void sdhci_send_command(struct sdhci_host *host, ++ struct mmc_command *cmd); ++ ++static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host) ++{ ++ return !!(host->flags & SDHCI_SDIO_IRQ_ENABLED); ++} ++ ++void sdhci_set_clock(struct sdhci_host *host, unsigned int clock); ++void sdhci_set_bus_width(struct sdhci_host *host, int width); ++void sdhci_reset(struct sdhci_host *host, u8 mask); ++void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing); + + #ifdef CONFIG_PM + extern int sdhci_suspend_host(struct sdhci_host *host); +diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c +index 7009f17..b7e3057 100644 +--- a/drivers/mmc/host/sdricoh_cs.c ++++ b/drivers/mmc/host/sdricoh_cs.c +@@ -516,9 +516,7 @@ static void sdricoh_pcmcia_detach(struct pcmcia_device *link) + #ifdef CONFIG_PM + static int sdricoh_pcmcia_suspend(struct pcmcia_device *link) + { +- struct mmc_host *mmc = link->priv; + dev_dbg(&link->dev, "suspend\n"); +- mmc_suspend_host(mmc); + return 0; + } + +@@ -527,7 +525,6 @@ static int sdricoh_pcmcia_resume(struct pcmcia_device *link) + struct mmc_host *mmc = link->priv; + dev_dbg(&link->dev, "resume\n"); + sdricoh_reset(mmc_priv(mmc)); +- mmc_resume_host(mmc); + return 0; + } + #else +@@ -543,25 +540,7 @@ static struct pcmcia_driver sdricoh_driver = { + .suspend = sdricoh_pcmcia_suspend, + .resume = sdricoh_pcmcia_resume, + }; +- +-/*****************************************************************************\ +- * * +- * Driver init/exit * +- * * +-\*****************************************************************************/ +- +-static int __init sdricoh_drv_init(void) +-{ +- return pcmcia_register_driver(&sdricoh_driver); +-} +- +-static void __exit sdricoh_drv_exit(void) +-{ +- pcmcia_unregister_driver(&sdricoh_driver); +-} +- +-module_init(sdricoh_drv_init); +-module_exit(sdricoh_drv_exit); ++module_pcmcia_driver(sdricoh_driver); + + module_param(switchlocked, uint, 0444); + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index d5505f3..656fbba 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -16,6 +16,33 @@ + * + */ + ++/* ++ * The MMCIF driver is now processing MMC requests asynchronously, according ++ * to the Linux MMC API requirement. ++ * ++ * The MMCIF driver processes MMC requests in up to 3 stages: command, optional ++ * data, and optional stop. To achieve asynchronous processing each of these ++ * stages is split into two halves: a top and a bottom half. The top half ++ * initialises the hardware, installs a timeout handler to handle completion ++ * timeouts, and returns. In case of the command stage this immediately returns ++ * control to the caller, leaving all further processing to run asynchronously. ++ * All further request processing is performed by the bottom halves. ++ * ++ * The bottom half further consists of a "hard" IRQ handler, an IRQ handler ++ * thread, a DMA completion callback, if DMA is used, a timeout work, and ++ * request- and stage-specific handler methods. ++ * ++ * Each bottom half run begins with either a hardware interrupt, a DMA callback ++ * invocation, or a timeout work run. In case of an error or a successful ++ * processing completion, the MMC core is informed and the request processing is ++ * finished. In case processing has to continue, i.e., if data has to be read ++ * from or written to the card, or if a stop command has to be sent, the next ++ * top half is called, which performs the necessary hardware handling and ++ * reschedules the timeout work. This returns the driver state machine into the ++ * bottom half waiting state. ++ */ ++ ++#include + #include + #include + #include +@@ -27,9 +54,14 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include ++#include + #include ++#include + #include + #include + +@@ -58,6 +90,7 @@ + #define CMD_SET_TBIT (1 << 7) /* 1: tran mission bit "Low" */ + #define CMD_SET_OPDM (1 << 6) /* 1: open/drain */ + #define CMD_SET_CCSH (1 << 5) ++#define CMD_SET_DARS (1 << 2) /* Dual Data Rate */ + #define CMD_SET_DATW_1 ((0 << 1) | (0 << 0)) /* 1bit */ + #define CMD_SET_DATW_4 ((0 << 1) | (1 << 0)) /* 4bit */ + #define CMD_SET_DATW_8 ((1 << 1) | (0 << 0)) /* 8bit */ +@@ -97,6 +130,12 @@ + INT_CCSTO | INT_CRCSTO | INT_WDATTO | \ + INT_RDATTO | INT_RBSYTO | INT_RSPTO) + ++#define INT_ALL (INT_RBSYE | INT_CRSPE | INT_BUFREN | \ ++ INT_BUFWEN | INT_CMD12DRE | INT_BUFRE | \ ++ INT_DTRANE | INT_CMD12RBE | INT_CMD12CRE) ++ ++#define INT_CCS (INT_CCSTO | INT_CCSRCV | INT_CCSDE) ++ + /* CE_INT_MASK */ + #define MASK_ALL 0x00000000 + #define MASK_MCCSDE (1 << 29) +@@ -123,6 +162,16 @@ + #define MASK_MRBSYTO (1 << 1) + #define MASK_MRSPTO (1 << 0) + ++#define MASK_START_CMD (MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \ ++ MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \ ++ MASK_MCRCSTO | MASK_MWDATTO | \ ++ MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO) ++ ++#define MASK_CLEAN (INT_ERR_STS | MASK_MRBSYE | MASK_MCRSPE | \ ++ MASK_MBUFREN | MASK_MBUFWEN | \ ++ MASK_MCMD12DRE | MASK_MBUFRE | MASK_MDTRANE | \ ++ MASK_MCMD12RBE | MASK_MCMD12CRE) ++ + /* CE_HOST_STS1 */ + #define STS1_CMDSEQ (1 << 31) + +@@ -160,25 +209,46 @@ enum mmcif_state { + STATE_IDLE, + STATE_REQUEST, + STATE_IOS, ++ STATE_TIMEOUT, ++}; ++ ++enum mmcif_wait_for { ++ MMCIF_WAIT_FOR_REQUEST, ++ MMCIF_WAIT_FOR_CMD, ++ MMCIF_WAIT_FOR_MREAD, ++ MMCIF_WAIT_FOR_MWRITE, ++ MMCIF_WAIT_FOR_READ, ++ MMCIF_WAIT_FOR_WRITE, ++ MMCIF_WAIT_FOR_READ_END, ++ MMCIF_WAIT_FOR_WRITE_END, ++ MMCIF_WAIT_FOR_STOP, + }; + + struct sh_mmcif_host { + struct mmc_host *mmc; +- struct mmc_data *data; ++ struct mmc_request *mrq; + struct platform_device *pd; +- struct sh_dmae_slave dma_slave_tx; +- struct sh_dmae_slave dma_slave_rx; + struct clk *hclk; + unsigned int clk; + int bus_width; ++ unsigned char timing; + bool sd_error; ++ bool dying; + long timeout; + void __iomem *addr; +- struct completion intr_wait; ++ u32 *pio_ptr; ++ spinlock_t lock; /* protect sh_mmcif_host::state */ + enum mmcif_state state; +- spinlock_t lock; ++ enum mmcif_wait_for wait_for; ++ struct delayed_work timeout_work; ++ size_t blocksize; ++ int sg_idx; ++ int sg_blkidx; + bool power; + bool card_present; ++ bool ccs_enable; /* Command Completion Signal support */ ++ bool clk_ctrl2_enable; ++ struct mutex thread_lock; + + /* DMA support */ + struct dma_chan *chan_rx; +@@ -202,38 +272,32 @@ static inline void sh_mmcif_bitclr(struct sh_mmcif_host *host, + static void mmcif_dma_complete(void *arg) + { + struct sh_mmcif_host *host = arg; ++ struct mmc_request *mrq = host->mrq; ++ + dev_dbg(&host->pd->dev, "Command completed\n"); + +- if (WARN(!host->data, "%s: NULL data in DMA completion!\n", ++ if (WARN(!mrq || !mrq->data, "%s: NULL data in DMA completion!\n", + dev_name(&host->pd->dev))) + return; + +- if (host->data->flags & MMC_DATA_READ) +- dma_unmap_sg(host->chan_rx->device->dev, +- host->data->sg, host->data->sg_len, +- DMA_FROM_DEVICE); +- else +- dma_unmap_sg(host->chan_tx->device->dev, +- host->data->sg, host->data->sg_len, +- DMA_TO_DEVICE); +- + complete(&host->dma_complete); + } + + static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) + { +- struct scatterlist *sg = host->data->sg; ++ struct mmc_data *data = host->mrq->data; ++ struct scatterlist *sg = data->sg; + struct dma_async_tx_descriptor *desc = NULL; + struct dma_chan *chan = host->chan_rx; + dma_cookie_t cookie = -EINVAL; + int ret; + +- ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len, ++ ret = dma_map_sg(chan->device->dev, sg, data->sg_len, + DMA_FROM_DEVICE); + if (ret > 0) { + host->dma_active = true; +- desc = chan->device->device_prep_slave_sg(chan, sg, ret, +- DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ desc = dmaengine_prep_slave_sg(chan, sg, ret, ++ DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + } + + if (desc) { +@@ -244,7 +308,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) + dma_async_issue_pending(chan); + } + dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n", +- __func__, host->data->sg_len, ret, cookie); ++ __func__, data->sg_len, ret, cookie); + + if (!desc) { + /* DMA failed, fall back to PIO */ +@@ -265,23 +329,24 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) + } + + dev_dbg(&host->pd->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__, +- desc, cookie, host->data->sg_len); ++ desc, cookie, data->sg_len); + } + + static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) + { +- struct scatterlist *sg = host->data->sg; ++ struct mmc_data *data = host->mrq->data; ++ struct scatterlist *sg = data->sg; + struct dma_async_tx_descriptor *desc = NULL; + struct dma_chan *chan = host->chan_tx; + dma_cookie_t cookie = -EINVAL; + int ret; + +- ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len, ++ ret = dma_map_sg(chan->device->dev, sg, data->sg_len, + DMA_TO_DEVICE); + if (ret > 0) { + host->dma_active = true; +- desc = chan->device->device_prep_slave_sg(chan, sg, ret, +- DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ desc = dmaengine_prep_slave_sg(chan, sg, ret, ++ DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + } + + if (desc) { +@@ -292,7 +357,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) + dma_async_issue_pending(chan); + } + dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n", +- __func__, host->data->sg_len, ret, cookie); ++ __func__, data->sg_len, ret, cookie); + + if (!desc) { + /* DMA failed, fall back to PIO */ +@@ -316,55 +381,74 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) + desc, cookie); + } + +-static bool sh_mmcif_filter(struct dma_chan *chan, void *arg) ++static struct dma_chan * ++sh_mmcif_request_dma_one(struct sh_mmcif_host *host, ++ struct sh_mmcif_plat_data *pdata, ++ enum dma_transfer_direction direction) + { +- dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg); +- chan->private = arg; +- return true; ++ struct dma_slave_config cfg; ++ struct dma_chan *chan; ++ unsigned int slave_id; ++ struct resource *res; ++ dma_cap_mask_t mask; ++ int ret; ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ ++ if (pdata) ++ slave_id = direction == DMA_MEM_TO_DEV ++ ? pdata->slave_id_tx : pdata->slave_id_rx; ++ else ++ slave_id = 0; ++ ++ chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, ++ (void *)(unsigned long)slave_id, &host->pd->dev, ++ direction == DMA_MEM_TO_DEV ? "tx" : "rx"); ++ ++ dev_dbg(&host->pd->dev, "%s: %s: got channel %p\n", __func__, ++ direction == DMA_MEM_TO_DEV ? "TX" : "RX", chan); ++ ++ if (!chan) ++ return NULL; ++ ++ res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); ++ ++ /* In the OF case the driver will get the slave ID from the DT */ ++ cfg.slave_id = slave_id; ++ cfg.direction = direction; ++ cfg.dst_addr = res->start + MMCIF_CE_DATA; ++ cfg.src_addr = 0; ++ ret = dmaengine_slave_config(chan, &cfg); ++ if (ret < 0) { ++ dma_release_channel(chan); ++ return NULL; ++ } ++ ++ return chan; + } + + static void sh_mmcif_request_dma(struct sh_mmcif_host *host, + struct sh_mmcif_plat_data *pdata) + { +- struct sh_dmae_slave *tx, *rx; + host->dma_active = false; + +- /* We can only either use DMA for both Tx and Rx or not use it at all */ +- if (pdata->dma) { +- dev_warn(&host->pd->dev, +- "Update your platform to use embedded DMA slave IDs\n"); +- tx = &pdata->dma->chan_priv_tx; +- rx = &pdata->dma->chan_priv_rx; +- } else { +- tx = &host->dma_slave_tx; +- tx->slave_id = pdata->slave_id_tx; +- rx = &host->dma_slave_rx; +- rx->slave_id = pdata->slave_id_rx; +- } +- if (tx->slave_id > 0 && rx->slave_id > 0) { +- dma_cap_mask_t mask; +- +- dma_cap_zero(mask); +- dma_cap_set(DMA_SLAVE, mask); +- +- host->chan_tx = dma_request_channel(mask, sh_mmcif_filter, tx); +- dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__, +- host->chan_tx); +- +- if (!host->chan_tx) ++ if (pdata) { ++ if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) + return; ++ } else if (!host->pd->dev.of_node) { ++ return; ++ } + +- host->chan_rx = dma_request_channel(mask, sh_mmcif_filter, rx); +- dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__, +- host->chan_rx); +- +- if (!host->chan_rx) { +- dma_release_channel(host->chan_tx); +- host->chan_tx = NULL; +- return; +- } ++ /* We can only either use DMA for both Tx and Rx or not use it at all */ ++ host->chan_tx = sh_mmcif_request_dma_one(host, pdata, DMA_MEM_TO_DEV); ++ if (!host->chan_tx) ++ return; + +- init_completion(&host->dma_complete); ++ host->chan_rx = sh_mmcif_request_dma_one(host, pdata, DMA_DEV_TO_MEM); ++ if (!host->chan_rx) { ++ dma_release_channel(host->chan_tx); ++ host->chan_tx = NULL; + } + } + +@@ -389,17 +473,19 @@ static void sh_mmcif_release_dma(struct sh_mmcif_host *host) + static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk) + { + struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; ++ bool sup_pclk = p ? p->sup_pclk : false; + + sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE); + sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR); + + if (!clk) + return; +- if (p->sup_pclk && clk == host->clk) ++ if (sup_pclk && clk == host->clk) + sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK); + else + sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR & +- (ilog2(__rounddown_pow_of_two(host->clk / clk)) << 16)); ++ ((fls(DIV_ROUND_UP(host->clk, ++ clk) - 1) - 1) << 16)); + + sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE); + } +@@ -412,8 +498,12 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host) + + sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_ON); + sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_OFF); ++ if (host->ccs_enable) ++ tmp |= SCCSTO_29; ++ if (host->clk_ctrl2_enable) ++ sh_mmcif_writel(host->addr, MMCIF_CE_CLK_CTRL2, 0x0F0F0000); + sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, tmp | +- SRSPTO_256 | SRBSYTO_29 | SRWDTO_29 | SCCSTO_29); ++ SRSPTO_256 | SRBSYTO_29 | SRWDTO_29); + /* byte swap on */ + sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP); + } +@@ -421,7 +511,7 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host) + static int sh_mmcif_error_manage(struct sh_mmcif_host *host) + { + u32 state1, state2; +- int ret, timeout = 10000000; ++ int ret, timeout; + + host->sd_error = false; + +@@ -433,155 +523,212 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host) + if (state1 & STS1_CMDSEQ) { + sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK); + sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, ~CMD_CTRL_BREAK); +- while (1) { +- timeout--; +- if (timeout < 0) { +- dev_err(&host->pd->dev, +- "Forceed end of command sequence timeout err\n"); +- return -EIO; +- } ++ for (timeout = 10000000; timeout; timeout--) { + if (!(sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1) +- & STS1_CMDSEQ)) ++ & STS1_CMDSEQ)) + break; + mdelay(1); + } ++ if (!timeout) { ++ dev_err(&host->pd->dev, ++ "Forced end of command sequence timeout err\n"); ++ return -EIO; ++ } + sh_mmcif_sync_reset(host); + dev_dbg(&host->pd->dev, "Forced end of command sequence\n"); + return -EIO; + } + + if (state2 & STS2_CRC_ERR) { +- dev_dbg(&host->pd->dev, ": Happened CRC error\n"); ++ dev_err(&host->pd->dev, " CRC error: state %u, wait %u\n", ++ host->state, host->wait_for); + ret = -EIO; + } else if (state2 & STS2_TIMEOUT_ERR) { +- dev_dbg(&host->pd->dev, ": Happened Timeout error\n"); ++ dev_err(&host->pd->dev, " Timeout: state %u, wait %u\n", ++ host->state, host->wait_for); + ret = -ETIMEDOUT; + } else { +- dev_dbg(&host->pd->dev, ": Happened End/Index error\n"); ++ dev_dbg(&host->pd->dev, " End/Index error: state %u, wait %u\n", ++ host->state, host->wait_for); + ret = -EIO; + } + return ret; + } + +-static int sh_mmcif_single_read(struct sh_mmcif_host *host, +- struct mmc_request *mrq) ++static bool sh_mmcif_next_block(struct sh_mmcif_host *host, u32 *p) + { +- struct mmc_data *data = mrq->data; +- long time; +- u32 blocksize, i, *p = sg_virt(data->sg); ++ struct mmc_data *data = host->mrq->data; ++ ++ host->sg_blkidx += host->blocksize; ++ ++ /* data->sg->length must be a multiple of host->blocksize? */ ++ BUG_ON(host->sg_blkidx > data->sg->length); ++ ++ if (host->sg_blkidx == data->sg->length) { ++ host->sg_blkidx = 0; ++ if (++host->sg_idx < data->sg_len) ++ host->pio_ptr = sg_virt(++data->sg); ++ } else { ++ host->pio_ptr = p; ++ } ++ ++ return host->sg_idx != data->sg_len; ++} ++ ++static void sh_mmcif_single_read(struct sh_mmcif_host *host, ++ struct mmc_request *mrq) ++{ ++ host->blocksize = (sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) & ++ BLOCK_SIZE_MASK) + 3; ++ ++ host->wait_for = MMCIF_WAIT_FOR_READ; + + /* buf read enable */ + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- if (time <= 0 || host->sd_error) +- return sh_mmcif_error_manage(host); +- +- blocksize = (BLOCK_SIZE_MASK & +- sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3; +- for (i = 0; i < blocksize / 4; i++) ++} ++ ++static bool sh_mmcif_read_block(struct sh_mmcif_host *host) ++{ ++ struct mmc_data *data = host->mrq->data; ++ u32 *p = sg_virt(data->sg); ++ int i; ++ ++ if (host->sd_error) { ++ data->error = sh_mmcif_error_manage(host); ++ dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, data->error); ++ return false; ++ } ++ ++ for (i = 0; i < host->blocksize / 4; i++) + *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA); + + /* buffer read end */ + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- if (time <= 0 || host->sd_error) +- return sh_mmcif_error_manage(host); ++ host->wait_for = MMCIF_WAIT_FOR_READ_END; + +- return 0; ++ return true; + } + +-static int sh_mmcif_multi_read(struct sh_mmcif_host *host, +- struct mmc_request *mrq) ++static void sh_mmcif_multi_read(struct sh_mmcif_host *host, ++ struct mmc_request *mrq) + { + struct mmc_data *data = mrq->data; +- long time; +- u32 blocksize, i, j, sec, *p; +- +- blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr, +- MMCIF_CE_BLOCK_SET); +- for (j = 0; j < data->sg_len; j++) { +- p = sg_virt(data->sg); +- for (sec = 0; sec < data->sg->length / blocksize; sec++) { +- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); +- /* buf read enable */ +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- +- if (time <= 0 || host->sd_error) +- return sh_mmcif_error_manage(host); +- +- for (i = 0; i < blocksize / 4; i++) +- *p++ = sh_mmcif_readl(host->addr, +- MMCIF_CE_DATA); +- } +- if (j < data->sg_len - 1) +- data->sg++; ++ ++ if (!data->sg_len || !data->sg->length) ++ return; ++ ++ host->blocksize = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) & ++ BLOCK_SIZE_MASK; ++ ++ host->wait_for = MMCIF_WAIT_FOR_MREAD; ++ host->sg_idx = 0; ++ host->sg_blkidx = 0; ++ host->pio_ptr = sg_virt(data->sg); ++ ++ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); ++} ++ ++static bool sh_mmcif_mread_block(struct sh_mmcif_host *host) ++{ ++ struct mmc_data *data = host->mrq->data; ++ u32 *p = host->pio_ptr; ++ int i; ++ ++ if (host->sd_error) { ++ data->error = sh_mmcif_error_manage(host); ++ dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, data->error); ++ return false; + } +- return 0; ++ ++ BUG_ON(!data->sg->length); ++ ++ for (i = 0; i < host->blocksize / 4; i++) ++ *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA); ++ ++ if (!sh_mmcif_next_block(host, p)) ++ return false; ++ ++ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); ++ ++ return true; + } + +-static int sh_mmcif_single_write(struct sh_mmcif_host *host, ++static void sh_mmcif_single_write(struct sh_mmcif_host *host, + struct mmc_request *mrq) + { +- struct mmc_data *data = mrq->data; +- long time; +- u32 blocksize, i, *p = sg_virt(data->sg); ++ host->blocksize = (sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) & ++ BLOCK_SIZE_MASK) + 3; + +- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); ++ host->wait_for = MMCIF_WAIT_FOR_WRITE; + + /* buf write enable */ +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- if (time <= 0 || host->sd_error) +- return sh_mmcif_error_manage(host); +- +- blocksize = (BLOCK_SIZE_MASK & +- sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3; +- for (i = 0; i < blocksize / 4; i++) ++ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); ++} ++ ++static bool sh_mmcif_write_block(struct sh_mmcif_host *host) ++{ ++ struct mmc_data *data = host->mrq->data; ++ u32 *p = sg_virt(data->sg); ++ int i; ++ ++ if (host->sd_error) { ++ data->error = sh_mmcif_error_manage(host); ++ dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, data->error); ++ return false; ++ } ++ ++ for (i = 0; i < host->blocksize / 4; i++) + sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++); + + /* buffer write end */ + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); ++ host->wait_for = MMCIF_WAIT_FOR_WRITE_END; + +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- if (time <= 0 || host->sd_error) +- return sh_mmcif_error_manage(host); +- +- return 0; ++ return true; + } + +-static int sh_mmcif_multi_write(struct sh_mmcif_host *host, +- struct mmc_request *mrq) ++static void sh_mmcif_multi_write(struct sh_mmcif_host *host, ++ struct mmc_request *mrq) + { + struct mmc_data *data = mrq->data; +- long time; +- u32 i, sec, j, blocksize, *p; + +- blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr, +- MMCIF_CE_BLOCK_SET); ++ if (!data->sg_len || !data->sg->length) ++ return; + +- for (j = 0; j < data->sg_len; j++) { +- p = sg_virt(data->sg); +- for (sec = 0; sec < data->sg->length / blocksize; sec++) { +- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); +- /* buf write enable*/ +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); ++ host->blocksize = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) & ++ BLOCK_SIZE_MASK; + +- if (time <= 0 || host->sd_error) +- return sh_mmcif_error_manage(host); ++ host->wait_for = MMCIF_WAIT_FOR_MWRITE; ++ host->sg_idx = 0; ++ host->sg_blkidx = 0; ++ host->pio_ptr = sg_virt(data->sg); + +- for (i = 0; i < blocksize / 4; i++) +- sh_mmcif_writel(host->addr, +- MMCIF_CE_DATA, *p++); +- } +- if (j < data->sg_len - 1) +- data->sg++; ++ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); ++} ++ ++static bool sh_mmcif_mwrite_block(struct sh_mmcif_host *host) ++{ ++ struct mmc_data *data = host->mrq->data; ++ u32 *p = host->pio_ptr; ++ int i; ++ ++ if (host->sd_error) { ++ data->error = sh_mmcif_error_manage(host); ++ dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, data->error); ++ return false; + } +- return 0; ++ ++ BUG_ON(!data->sg->length); ++ ++ for (i = 0; i < host->blocksize / 4; i++) ++ sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++); ++ ++ if (!sh_mmcif_next_block(host, p)) ++ return false; ++ ++ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); ++ ++ return true; + } + + static void sh_mmcif_get_response(struct sh_mmcif_host *host, +@@ -603,8 +750,11 @@ static void sh_mmcif_get_cmd12response(struct sh_mmcif_host *host, + } + + static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, +- struct mmc_request *mrq, struct mmc_command *cmd, u32 opc) ++ struct mmc_request *mrq) + { ++ struct mmc_data *data = mrq->data; ++ struct mmc_command *cmd = mrq->cmd; ++ u32 opc = cmd->opcode; + u32 tmp = 0; + + /* Response Type check */ +@@ -626,17 +776,17 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, + } + switch (opc) { + /* RBSY */ ++ case MMC_SLEEP_AWAKE: + case MMC_SWITCH: + case MMC_STOP_TRANSMISSION: + case MMC_SET_WRITE_PROT: + case MMC_CLR_WRITE_PROT: + case MMC_ERASE: +- case MMC_GEN_CMD: + tmp |= CMD_SET_RBSY; + break; + } + /* WDAT / DATW */ +- if (host->data) { ++ if (data) { + tmp |= CMD_SET_WDAT; + switch (host->bus_width) { + case MMC_BUS_WIDTH_1: +@@ -652,6 +802,18 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, + dev_err(&host->pd->dev, "Unsupported bus width.\n"); + break; + } ++ switch (host->timing) { ++ case MMC_TIMING_MMC_DDR52: ++ /* ++ * MMC core will only set this timing, if the host ++ * advertises the MMC_CAP_1_8V_DDR/MMC_CAP_1_2V_DDR ++ * capability. MMCIF implementations with this ++ * capability, e.g. sh73a0, will have to set it ++ * in their platform data. ++ */ ++ tmp |= CMD_SET_DARS; ++ break; ++ } + } + /* DWEN */ + if (opc == MMC_WRITE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) +@@ -660,7 +822,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, + if (opc == MMC_READ_MULTIPLE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) { + tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN; + sh_mmcif_bitset(host, MMCIF_CE_BLOCK_SET, +- mrq->data->blocks << 16); ++ data->blocks << 16); + } + /* RIDXC[1:0] check bits */ + if (opc == MMC_SEND_OP_COND || opc == MMC_ALL_SEND_CID || +@@ -674,150 +836,95 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, + opc == MMC_SEND_CSD || opc == MMC_SEND_CID) + tmp |= CMD_SET_CRC7C_INTERNAL; + +- return opc = ((opc << 24) | tmp); ++ return (opc << 24) | tmp; + } + + static int sh_mmcif_data_trans(struct sh_mmcif_host *host, +- struct mmc_request *mrq, u32 opc) ++ struct mmc_request *mrq, u32 opc) + { +- int ret; +- + switch (opc) { + case MMC_READ_MULTIPLE_BLOCK: +- ret = sh_mmcif_multi_read(host, mrq); +- break; ++ sh_mmcif_multi_read(host, mrq); ++ return 0; + case MMC_WRITE_MULTIPLE_BLOCK: +- ret = sh_mmcif_multi_write(host, mrq); +- break; ++ sh_mmcif_multi_write(host, mrq); ++ return 0; + case MMC_WRITE_BLOCK: +- ret = sh_mmcif_single_write(host, mrq); +- break; ++ sh_mmcif_single_write(host, mrq); ++ return 0; + case MMC_READ_SINGLE_BLOCK: + case MMC_SEND_EXT_CSD: +- ret = sh_mmcif_single_read(host, mrq); +- break; ++ sh_mmcif_single_read(host, mrq); ++ return 0; + default: +- dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc); +- ret = -EINVAL; +- break; ++ dev_err(&host->pd->dev, "Unsupported CMD%d\n", opc); ++ return -EINVAL; + } +- return ret; + } + + static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, +- struct mmc_request *mrq, struct mmc_command *cmd) ++ struct mmc_request *mrq) + { +- long time; +- int ret = 0, mask = 0; ++ struct mmc_command *cmd = mrq->cmd; + u32 opc = cmd->opcode; ++ u32 mask; + + switch (opc) { +- /* respons busy check */ ++ /* response busy check */ ++ case MMC_SLEEP_AWAKE: + case MMC_SWITCH: + case MMC_STOP_TRANSMISSION: + case MMC_SET_WRITE_PROT: + case MMC_CLR_WRITE_PROT: + case MMC_ERASE: +- case MMC_GEN_CMD: +- mask = MASK_MRBSYE; ++ mask = MASK_START_CMD | MASK_MRBSYE; + break; + default: +- mask = MASK_MCRSPE; ++ mask = MASK_START_CMD | MASK_MCRSPE; + break; + } +- mask |= MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | +- MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | +- MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | +- MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO; + +- if (host->data) { ++ if (host->ccs_enable) ++ mask |= MASK_MCCSTO; ++ ++ if (mrq->data) { + sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0); + sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, + mrq->data->blksz); + } +- opc = sh_mmcif_set_cmd(host, mrq, cmd, opc); ++ opc = sh_mmcif_set_cmd(host, mrq); + +- sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0); ++ if (host->ccs_enable) ++ sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0); ++ else ++ sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0 | INT_CCS); + sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask); + /* set arg */ + sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg); + /* set cmd */ + sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc); + +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- if (time <= 0) { +- cmd->error = sh_mmcif_error_manage(host); +- return; +- } +- if (host->sd_error) { +- switch (cmd->opcode) { +- case MMC_ALL_SEND_CID: +- case MMC_SELECT_CARD: +- case MMC_APP_CMD: +- cmd->error = -ETIMEDOUT; +- break; +- default: +- dev_dbg(&host->pd->dev, "Cmd(d'%d) err\n", +- cmd->opcode); +- cmd->error = sh_mmcif_error_manage(host); +- break; +- } +- host->sd_error = false; +- return; +- } +- if (!(cmd->flags & MMC_RSP_PRESENT)) { +- cmd->error = 0; +- return; +- } +- sh_mmcif_get_response(host, cmd); +- if (host->data) { +- if (!host->dma_active) { +- ret = sh_mmcif_data_trans(host, mrq, cmd->opcode); +- } else { +- long time = +- wait_for_completion_interruptible_timeout(&host->dma_complete, +- host->timeout); +- if (!time) +- ret = -ETIMEDOUT; +- else if (time < 0) +- ret = time; +- sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, +- BUF_ACC_DMAREN | BUF_ACC_DMAWEN); +- host->dma_active = false; +- } +- if (ret < 0) +- mrq->data->bytes_xfered = 0; +- else +- mrq->data->bytes_xfered = +- mrq->data->blocks * mrq->data->blksz; +- } +- cmd->error = ret; ++ host->wait_for = MMCIF_WAIT_FOR_CMD; ++ schedule_delayed_work(&host->timeout_work, host->timeout); + } + + static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, +- struct mmc_request *mrq, struct mmc_command *cmd) ++ struct mmc_request *mrq) + { +- long time; +- +- if (mrq->cmd->opcode == MMC_READ_MULTIPLE_BLOCK) ++ switch (mrq->cmd->opcode) { ++ case MMC_READ_MULTIPLE_BLOCK: + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE); +- else if (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) ++ break; ++ case MMC_WRITE_MULTIPLE_BLOCK: + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE); +- else { ++ break; ++ default: + dev_err(&host->pd->dev, "unsupported stop cmd\n"); +- cmd->error = sh_mmcif_error_manage(host); ++ mrq->stop->error = sh_mmcif_error_manage(host); + return; + } + +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- if (time <= 0 || host->sd_error) { +- cmd->error = sh_mmcif_error_manage(host); +- return; +- } +- sh_mmcif_get_cmd12response(host, cmd); +- cmd->error = 0; ++ host->wait_for = MMCIF_WAIT_FOR_STOP; + } + + static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) +@@ -827,6 +934,7 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) + + spin_lock_irqsave(&host->lock, flags); + if (host->state != STATE_IDLE) { ++ dev_dbg(&host->pd->dev, "%s() rejected, state %u\n", __func__, host->state); + spin_unlock_irqrestore(&host->lock, flags); + mrq->cmd->error = -EAGAIN; + mmc_request_done(mmc, mrq); +@@ -838,51 +946,56 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) + + switch (mrq->cmd->opcode) { + /* MMCIF does not support SD/SDIO command */ +- case SD_IO_SEND_OP_COND: ++ case MMC_SLEEP_AWAKE: /* = SD_IO_SEND_OP_COND (5) */ ++ case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */ ++ if ((mrq->cmd->flags & MMC_CMD_MASK) != MMC_CMD_BCR) ++ break; + case MMC_APP_CMD: ++ case SD_IO_RW_DIRECT: + host->state = STATE_IDLE; + mrq->cmd->error = -ETIMEDOUT; + mmc_request_done(mmc, mrq); + return; +- case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */ +- if (!mrq->data) { +- /* send_if_cond cmd (not support) */ +- host->state = STATE_IDLE; +- mrq->cmd->error = -ETIMEDOUT; +- mmc_request_done(mmc, mrq); +- return; +- } +- break; + default: + break; + } +- host->data = mrq->data; +- if (mrq->data) { +- if (mrq->data->flags & MMC_DATA_READ) { +- if (host->chan_rx) +- sh_mmcif_start_dma_rx(host); +- } else { +- if (host->chan_tx) +- sh_mmcif_start_dma_tx(host); +- } ++ ++ host->mrq = mrq; ++ ++ sh_mmcif_start_cmd(host, mrq); ++} ++ ++static int sh_mmcif_clk_update(struct sh_mmcif_host *host) ++{ ++ int ret = clk_prepare_enable(host->hclk); ++ ++ if (!ret) { ++ host->clk = clk_get_rate(host->hclk); ++ host->mmc->f_max = host->clk / 2; ++ host->mmc->f_min = host->clk / 512; + } +- sh_mmcif_start_cmd(host, mrq, mrq->cmd); +- host->data = NULL; + +- if (!mrq->cmd->error && mrq->stop) +- sh_mmcif_stop_cmd(host, mrq, mrq->stop); +- host->state = STATE_IDLE; +- mmc_request_done(mmc, mrq); ++ return ret; ++} ++ ++static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios) ++{ ++ struct mmc_host *mmc = host->mmc; ++ ++ if (!IS_ERR(mmc->supply.vmmc)) ++ /* Errors ignored... */ ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ++ ios->power_mode ? ios->vdd : 0); + } + + static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct sh_mmcif_host *host = mmc_priv(mmc); +- struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + if (host->state != STATE_IDLE) { ++ dev_dbg(&host->pd->dev, "%s() rejected, state %u\n", __func__, host->state); + spin_unlock_irqrestore(&host->lock, flags); + return; + } +@@ -896,6 +1009,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + sh_mmcif_request_dma(host, host->pd->dev.platform_data); + host->card_present = true; + } ++ sh_mmcif_set_power(host, ios); + } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) { + /* clock stop */ + sh_mmcif_clock_control(host, 0); +@@ -906,10 +1020,11 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + } + } + if (host->power) { +- pm_runtime_put(&host->pd->dev); ++ pm_runtime_put_sync(&host->pd->dev); ++ clk_disable_unprepare(host->hclk); + host->power = false; +- if (p->down_pwr && ios->power_mode == MMC_POWER_OFF) +- p->down_pwr(host->pd); ++ if (ios->power_mode == MMC_POWER_OFF) ++ sh_mmcif_set_power(host, ios); + } + host->state = STATE_IDLE; + return; +@@ -917,8 +1032,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + + if (ios->clock) { + if (!host->power) { +- if (p->set_pwr) +- p->set_pwr(host->pd, ios->power_mode); ++ sh_mmcif_clk_update(host); + pm_runtime_get_sync(&host->pd->dev); + host->power = true; + sh_mmcif_sync_reset(host); +@@ -926,6 +1040,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + sh_mmcif_clock_control(host, ios->clock); + } + ++ host->timing = ios->timing; + host->bus_width = ios->bus_width; + host->state = STATE_IDLE; + } +@@ -934,8 +1049,12 @@ static int sh_mmcif_get_cd(struct mmc_host *mmc) + { + struct sh_mmcif_host *host = mmc_priv(mmc); + struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; ++ int ret = mmc_gpio_get_cd(mmc); ++ ++ if (ret >= 0) ++ return ret; + +- if (!p->get_cd) ++ if (!p || !p->get_cd) + return -ENOSYS; + else + return p->get_cd(host->pd); +@@ -947,83 +1066,315 @@ static struct mmc_host_ops sh_mmcif_ops = { + .get_cd = sh_mmcif_get_cd, + }; + +-static void sh_mmcif_detect(struct mmc_host *mmc) ++static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) + { +- mmc_detect_change(mmc, 0); ++ struct mmc_command *cmd = host->mrq->cmd; ++ struct mmc_data *data = host->mrq->data; ++ long time; ++ ++ if (host->sd_error) { ++ switch (cmd->opcode) { ++ case MMC_ALL_SEND_CID: ++ case MMC_SELECT_CARD: ++ case MMC_APP_CMD: ++ cmd->error = -ETIMEDOUT; ++ break; ++ default: ++ cmd->error = sh_mmcif_error_manage(host); ++ break; ++ } ++ dev_dbg(&host->pd->dev, "CMD%d error %d\n", ++ cmd->opcode, cmd->error); ++ host->sd_error = false; ++ return false; ++ } ++ if (!(cmd->flags & MMC_RSP_PRESENT)) { ++ cmd->error = 0; ++ return false; ++ } ++ ++ sh_mmcif_get_response(host, cmd); ++ ++ if (!data) ++ return false; ++ ++ /* ++ * Completion can be signalled from DMA callback and error, so, have to ++ * reset here, before setting .dma_active ++ */ ++ init_completion(&host->dma_complete); ++ ++ if (data->flags & MMC_DATA_READ) { ++ if (host->chan_rx) ++ sh_mmcif_start_dma_rx(host); ++ } else { ++ if (host->chan_tx) ++ sh_mmcif_start_dma_tx(host); ++ } ++ ++ if (!host->dma_active) { ++ data->error = sh_mmcif_data_trans(host, host->mrq, cmd->opcode); ++ return !data->error; ++ } ++ ++ /* Running in the IRQ thread, can sleep */ ++ time = wait_for_completion_interruptible_timeout(&host->dma_complete, ++ host->timeout); ++ ++ if (data->flags & MMC_DATA_READ) ++ dma_unmap_sg(host->chan_rx->device->dev, ++ data->sg, data->sg_len, ++ DMA_FROM_DEVICE); ++ else ++ dma_unmap_sg(host->chan_tx->device->dev, ++ data->sg, data->sg_len, ++ DMA_TO_DEVICE); ++ ++ if (host->sd_error) { ++ dev_err(host->mmc->parent, ++ "Error IRQ while waiting for DMA completion!\n"); ++ /* Woken up by an error IRQ: abort DMA */ ++ data->error = sh_mmcif_error_manage(host); ++ } else if (!time) { ++ dev_err(host->mmc->parent, "DMA timeout!\n"); ++ data->error = -ETIMEDOUT; ++ } else if (time < 0) { ++ dev_err(host->mmc->parent, ++ "wait_for_completion_...() error %ld!\n", time); ++ data->error = time; ++ } ++ sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, ++ BUF_ACC_DMAREN | BUF_ACC_DMAWEN); ++ host->dma_active = false; ++ ++ if (data->error) { ++ data->bytes_xfered = 0; ++ /* Abort DMA */ ++ if (data->flags & MMC_DATA_READ) ++ dmaengine_terminate_all(host->chan_rx); ++ else ++ dmaengine_terminate_all(host->chan_tx); ++ } ++ ++ return false; ++} ++ ++static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) ++{ ++ struct sh_mmcif_host *host = dev_id; ++ struct mmc_request *mrq; ++ bool wait = false; ++ ++ cancel_delayed_work_sync(&host->timeout_work); ++ ++ mutex_lock(&host->thread_lock); ++ ++ mrq = host->mrq; ++ if (!mrq) { ++ dev_dbg(&host->pd->dev, "IRQ thread state %u, wait %u: NULL mrq!\n", ++ host->state, host->wait_for); ++ mutex_unlock(&host->thread_lock); ++ return IRQ_HANDLED; ++ } ++ ++ /* ++ * All handlers return true, if processing continues, and false, if the ++ * request has to be completed - successfully or not ++ */ ++ switch (host->wait_for) { ++ case MMCIF_WAIT_FOR_REQUEST: ++ /* We're too late, the timeout has already kicked in */ ++ mutex_unlock(&host->thread_lock); ++ return IRQ_HANDLED; ++ case MMCIF_WAIT_FOR_CMD: ++ /* Wait for data? */ ++ wait = sh_mmcif_end_cmd(host); ++ break; ++ case MMCIF_WAIT_FOR_MREAD: ++ /* Wait for more data? */ ++ wait = sh_mmcif_mread_block(host); ++ break; ++ case MMCIF_WAIT_FOR_READ: ++ /* Wait for data end? */ ++ wait = sh_mmcif_read_block(host); ++ break; ++ case MMCIF_WAIT_FOR_MWRITE: ++ /* Wait data to write? */ ++ wait = sh_mmcif_mwrite_block(host); ++ break; ++ case MMCIF_WAIT_FOR_WRITE: ++ /* Wait for data end? */ ++ wait = sh_mmcif_write_block(host); ++ break; ++ case MMCIF_WAIT_FOR_STOP: ++ if (host->sd_error) { ++ mrq->stop->error = sh_mmcif_error_manage(host); ++ dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, mrq->stop->error); ++ break; ++ } ++ sh_mmcif_get_cmd12response(host, mrq->stop); ++ mrq->stop->error = 0; ++ break; ++ case MMCIF_WAIT_FOR_READ_END: ++ case MMCIF_WAIT_FOR_WRITE_END: ++ if (host->sd_error) { ++ mrq->data->error = sh_mmcif_error_manage(host); ++ dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, mrq->data->error); ++ } ++ break; ++ default: ++ BUG(); ++ } ++ ++ if (wait) { ++ schedule_delayed_work(&host->timeout_work, host->timeout); ++ /* Wait for more data */ ++ mutex_unlock(&host->thread_lock); ++ return IRQ_HANDLED; ++ } ++ ++ if (host->wait_for != MMCIF_WAIT_FOR_STOP) { ++ struct mmc_data *data = mrq->data; ++ if (!mrq->cmd->error && data && !data->error) ++ data->bytes_xfered = ++ data->blocks * data->blksz; ++ ++ if (mrq->stop && !mrq->cmd->error && (!data || !data->error)) { ++ sh_mmcif_stop_cmd(host, mrq); ++ if (!mrq->stop->error) { ++ schedule_delayed_work(&host->timeout_work, host->timeout); ++ mutex_unlock(&host->thread_lock); ++ return IRQ_HANDLED; ++ } ++ } ++ } ++ ++ host->wait_for = MMCIF_WAIT_FOR_REQUEST; ++ host->state = STATE_IDLE; ++ host->mrq = NULL; ++ mmc_request_done(host->mmc, mrq); ++ ++ mutex_unlock(&host->thread_lock); ++ ++ return IRQ_HANDLED; + } + + static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) + { + struct sh_mmcif_host *host = dev_id; +- u32 state; +- int err = 0; ++ u32 state, mask; + + state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); ++ mask = sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK); ++ if (host->ccs_enable) ++ sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~(state & mask)); ++ else ++ sh_mmcif_writel(host->addr, MMCIF_CE_INT, INT_CCS | ~(state & mask)); ++ sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN); + +- if (state & INT_RBSYE) { +- sh_mmcif_writel(host->addr, MMCIF_CE_INT, +- ~(INT_RBSYE | INT_CRSPE)); +- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MRBSYE); +- } else if (state & INT_CRSPE) { +- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_CRSPE); +- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCRSPE); +- } else if (state & INT_BUFREN) { +- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFREN); +- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); +- } else if (state & INT_BUFWEN) { +- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFWEN); +- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); +- } else if (state & INT_CMD12DRE) { +- sh_mmcif_writel(host->addr, MMCIF_CE_INT, +- ~(INT_CMD12DRE | INT_CMD12RBE | +- INT_CMD12CRE | INT_BUFRE)); +- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE); +- } else if (state & INT_BUFRE) { +- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFRE); +- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); +- } else if (state & INT_DTRANE) { +- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_DTRANE); +- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); +- } else if (state & INT_CMD12RBE) { +- sh_mmcif_writel(host->addr, MMCIF_CE_INT, +- ~(INT_CMD12RBE | INT_CMD12CRE)); +- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE); +- } else if (state & INT_ERR_STS) { +- /* err interrupts */ +- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); +- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state); +- err = 1; +- } else { +- dev_dbg(&host->pd->dev, "Unsupported interrupt: 0x%x\n", state); +- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); +- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state); +- err = 1; +- } +- if (err) { ++ if (state & ~MASK_CLEAN) ++ dev_dbg(&host->pd->dev, "IRQ state = 0x%08x incompletely cleared\n", ++ state); ++ ++ if (state & INT_ERR_STS || state & ~INT_ALL) { + host->sd_error = true; +- dev_dbg(&host->pd->dev, "int err state = %08x\n", state); ++ dev_dbg(&host->pd->dev, "int err state = 0x%08x\n", state); + } +- if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) +- complete(&host->intr_wait); +- else ++ if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) { ++ if (!host->mrq) ++ dev_dbg(&host->pd->dev, "NULL IRQ state = 0x%08x\n", state); ++ if (!host->dma_active) ++ return IRQ_WAKE_THREAD; ++ else if (host->sd_error) ++ mmcif_dma_complete(host); ++ } else { + dev_dbg(&host->pd->dev, "Unexpected IRQ 0x%x\n", state); ++ } + + return IRQ_HANDLED; + } + +-static int __devinit sh_mmcif_probe(struct platform_device *pdev) ++static void mmcif_timeout_work(struct work_struct *work) ++{ ++ struct delayed_work *d = container_of(work, struct delayed_work, work); ++ struct sh_mmcif_host *host = container_of(d, struct sh_mmcif_host, timeout_work); ++ struct mmc_request *mrq = host->mrq; ++ unsigned long flags; ++ ++ if (host->dying) ++ /* Don't run after mmc_remove_host() */ ++ return; ++ ++ dev_err(&host->pd->dev, "Timeout waiting for %u on CMD%u\n", ++ host->wait_for, mrq->cmd->opcode); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ if (host->state == STATE_IDLE) { ++ spin_unlock_irqrestore(&host->lock, flags); ++ return; ++ } ++ ++ host->state = STATE_TIMEOUT; ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ /* ++ * Handle races with cancel_delayed_work(), unless ++ * cancel_delayed_work_sync() is used ++ */ ++ switch (host->wait_for) { ++ case MMCIF_WAIT_FOR_CMD: ++ mrq->cmd->error = sh_mmcif_error_manage(host); ++ break; ++ case MMCIF_WAIT_FOR_STOP: ++ mrq->stop->error = sh_mmcif_error_manage(host); ++ break; ++ case MMCIF_WAIT_FOR_MREAD: ++ case MMCIF_WAIT_FOR_MWRITE: ++ case MMCIF_WAIT_FOR_READ: ++ case MMCIF_WAIT_FOR_WRITE: ++ case MMCIF_WAIT_FOR_READ_END: ++ case MMCIF_WAIT_FOR_WRITE_END: ++ mrq->data->error = sh_mmcif_error_manage(host); ++ break; ++ default: ++ BUG(); ++ } ++ ++ host->state = STATE_IDLE; ++ host->wait_for = MMCIF_WAIT_FOR_REQUEST; ++ host->mrq = NULL; ++ mmc_request_done(host->mmc, mrq); ++} ++ ++static void sh_mmcif_init_ocr(struct sh_mmcif_host *host) ++{ ++ struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data; ++ struct mmc_host *mmc = host->mmc; ++ ++ mmc_regulator_get_supply(mmc); ++ ++ if (!pd) ++ return; ++ ++ if (!mmc->ocr_avail) ++ mmc->ocr_avail = pd->ocr; ++ else if (pd->ocr) ++ dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n"); ++} ++ ++static int sh_mmcif_probe(struct platform_device *pdev) + { + int ret = 0, irq[2]; + struct mmc_host *mmc; + struct sh_mmcif_host *host; +- struct sh_mmcif_plat_data *pd; ++ struct sh_mmcif_plat_data *pd = pdev->dev.platform_data; + struct resource *res; + void __iomem *reg; +- char clk_name[8]; ++ const char *name; + + irq[0] = platform_get_irq(pdev, 0); + irq[1] = platform_get_irq(pdev, 1); +- if (irq[0] < 0 || irq[1] < 0) { ++ if (irq[0] < 0) { + dev_err(&pdev->dev, "Get irq error\n"); + return -ENXIO; + } +@@ -1037,49 +1388,33 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "ioremap error.\n"); + return -ENOMEM; + } +- pd = pdev->dev.platform_data; +- if (!pd) { +- dev_err(&pdev->dev, "sh_mmcif plat data error.\n"); +- ret = -ENXIO; +- goto clean_up; +- } ++ + mmc = mmc_alloc_host(sizeof(struct sh_mmcif_host), &pdev->dev); + if (!mmc) { + ret = -ENOMEM; +- goto clean_up; ++ goto ealloch; + } ++ ++ ret = mmc_of_parse(mmc); ++ if (ret < 0) ++ goto eofparse; ++ + host = mmc_priv(mmc); + host->mmc = mmc; + host->addr = reg; +- host->timeout = 1000; ++ host->timeout = msecs_to_jiffies(1000); ++ host->ccs_enable = !pd || !pd->ccs_unsupported; ++ host->clk_ctrl2_enable = pd && pd->clk_ctrl2_present; + +- snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id); +- host->hclk = clk_get(&pdev->dev, clk_name); +- if (IS_ERR(host->hclk)) { +- dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); +- ret = PTR_ERR(host->hclk); +- goto clean_up1; +- } +- clk_enable(host->hclk); +- host->clk = clk_get_rate(host->hclk); + host->pd = pdev; + +- init_completion(&host->intr_wait); + spin_lock_init(&host->lock); + + mmc->ops = &sh_mmcif_ops; +- mmc->f_max = host->clk; +- /* close to 400KHz */ +- if (mmc->f_max < 51200000) +- mmc->f_min = mmc->f_max / 128; +- else if (mmc->f_max < 102400000) +- mmc->f_min = mmc->f_max / 256; +- else +- mmc->f_min = mmc->f_max / 512; +- if (pd->ocr) +- mmc->ocr_avail = pd->ocr; +- mmc->caps = MMC_CAP_MMC_HIGHSPEED; +- if (pd->caps) ++ sh_mmcif_init_ocr(host); ++ ++ mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_WAIT_WHILE_BUSY; ++ if (pd && pd->caps) + mmc->caps |= pd->caps; + mmc->max_segs = 32; + mmc->max_blk_size = 512; +@@ -1087,63 +1422,107 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) + mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size; + mmc->max_seg_size = mmc->max_req_size; + +- sh_mmcif_sync_reset(host); + platform_set_drvdata(pdev, host); + + pm_runtime_enable(&pdev->dev); + host->power = false; + ++ host->hclk = clk_get(&pdev->dev, NULL); ++ if (IS_ERR(host->hclk)) { ++ ret = PTR_ERR(host->hclk); ++ dev_err(&pdev->dev, "cannot get clock: %d\n", ret); ++ goto eclkget; ++ } ++ ret = sh_mmcif_clk_update(host); ++ if (ret < 0) ++ goto eclkupdate; ++ + ret = pm_runtime_resume(&pdev->dev); + if (ret < 0) +- goto clean_up2; ++ goto eresume; + +- mmc_add_host(mmc); ++ INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); + ++ sh_mmcif_sync_reset(host); + sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); + +- ret = request_irq(irq[0], sh_mmcif_intr, 0, "sh_mmc:error", host); ++ name = irq[1] < 0 ? dev_name(&pdev->dev) : "sh_mmc:error"; ++ ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, name, host); + if (ret) { +- dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n"); +- goto clean_up3; ++ dev_err(&pdev->dev, "request_irq error (%s)\n", name); ++ goto ereqirq0; + } +- ret = request_irq(irq[1], sh_mmcif_intr, 0, "sh_mmc:int", host); +- if (ret) { +- free_irq(irq[0], host); +- dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); +- goto clean_up3; ++ if (irq[1] >= 0) { ++ ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, ++ 0, "sh_mmc:int", host); ++ if (ret) { ++ dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); ++ goto ereqirq1; ++ } + } + +- sh_mmcif_detect(host->mmc); ++ if (pd && pd->use_cd_gpio) { ++ ret = mmc_gpio_request_cd(mmc, pd->cd_gpio, 0); ++ if (ret < 0) ++ goto erqcd; ++ } ++ ++ mutex_init(&host->thread_lock); ++ ++ clk_disable_unprepare(host->hclk); ++ ret = mmc_add_host(mmc); ++ if (ret < 0) ++ goto emmcaddh; ++ ++ dev_pm_qos_expose_latency_limit(&pdev->dev, 100); + + dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION); + dev_dbg(&pdev->dev, "chip ver H'%04x\n", + sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff); + return ret; + +-clean_up3: +- mmc_remove_host(mmc); ++emmcaddh: ++erqcd: ++ if (irq[1] >= 0) ++ free_irq(irq[1], host); ++ereqirq1: ++ free_irq(irq[0], host); ++ereqirq0: + pm_runtime_suspend(&pdev->dev); +-clean_up2: ++eresume: ++ clk_disable_unprepare(host->hclk); ++eclkupdate: ++ clk_put(host->hclk); ++eclkget: + pm_runtime_disable(&pdev->dev); +- clk_disable(host->hclk); +-clean_up1: ++eofparse: + mmc_free_host(mmc); +-clean_up: +- if (reg) +- iounmap(reg); ++ealloch: ++ iounmap(reg); + return ret; + } + +-static int __devexit sh_mmcif_remove(struct platform_device *pdev) ++static int sh_mmcif_remove(struct platform_device *pdev) + { + struct sh_mmcif_host *host = platform_get_drvdata(pdev); + int irq[2]; + ++ host->dying = true; ++ clk_prepare_enable(host->hclk); + pm_runtime_get_sync(&pdev->dev); + ++ dev_pm_qos_hide_latency_limit(&pdev->dev); ++ + mmc_remove_host(host->mmc); + sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); + ++ /* ++ * FIXME: cancel_delayed_work(_sync)() and free_irq() race with the ++ * mmc_remove_host() call above. But swapping order doesn't help either ++ * (a query on the linux-mmc mailing list didn't bring any replies). ++ */ ++ cancel_delayed_work_sync(&host->timeout_work); ++ + if (host->addr) + iounmap(host->addr); + +@@ -1151,11 +1530,10 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev) + irq[1] = platform_get_irq(pdev, 1); + + free_irq(irq[0], host); +- free_irq(irq[1], host); +- +- platform_set_drvdata(pdev, NULL); ++ if (irq[1] >= 0) ++ free_irq(irq[1], host); + +- clk_disable(host->hclk); ++ clk_disable_unprepare(host->hclk); + mmc_free_host(host->mmc); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); +@@ -1163,38 +1541,30 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev) + return 0; + } + +-#ifdef CONFIG_PM ++#ifdef CONFIG_PM_SLEEP + static int sh_mmcif_suspend(struct device *dev) + { +- struct platform_device *pdev = to_platform_device(dev); +- struct sh_mmcif_host *host = platform_get_drvdata(pdev); +- int ret = mmc_suspend_host(host->mmc); ++ struct sh_mmcif_host *host = dev_get_drvdata(dev); + +- if (!ret) { +- sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); +- clk_disable(host->hclk); +- } ++ sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); + +- return ret; ++ return 0; + } + + static int sh_mmcif_resume(struct device *dev) + { +- struct platform_device *pdev = to_platform_device(dev); +- struct sh_mmcif_host *host = platform_get_drvdata(pdev); +- +- clk_enable(host->hclk); +- +- return mmc_resume_host(host->mmc); ++ return 0; + } +-#else +-#define sh_mmcif_suspend NULL +-#define sh_mmcif_resume NULL +-#endif /* CONFIG_PM */ ++#endif ++ ++static const struct of_device_id mmcif_of_match[] = { ++ { .compatible = "renesas,sh-mmcif" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, mmcif_of_match); + + static const struct dev_pm_ops sh_mmcif_dev_pm_ops = { +- .suspend = sh_mmcif_suspend, +- .resume = sh_mmcif_resume, ++ SET_SYSTEM_SLEEP_PM_OPS(sh_mmcif_suspend, sh_mmcif_resume) + }; + + static struct platform_driver sh_mmcif_driver = { +@@ -1203,22 +1573,12 @@ static struct platform_driver sh_mmcif_driver = { + .driver = { + .name = DRIVER_NAME, + .pm = &sh_mmcif_dev_pm_ops, ++ .owner = THIS_MODULE, ++ .of_match_table = mmcif_of_match, + }, + }; + +-static int __init sh_mmcif_init(void) +-{ +- return platform_driver_register(&sh_mmcif_driver); +-} +- +-static void __exit sh_mmcif_exit(void) +-{ +- platform_driver_unregister(&sh_mmcif_driver); +-} +- +-module_init(sh_mmcif_init); +-module_exit(sh_mmcif_exit); +- ++module_platform_driver(sh_mmcif_driver); + + MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver"); + MODULE_LICENSE("GPL"); +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 41ae646..91058da 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -21,7 +21,9 @@ + #include + #include + #include ++#include + #include ++#include + #include + #include + #include +@@ -31,30 +33,70 @@ + + #include "tmio_mmc.h" + ++#define EXT_ACC 0xe4 ++ ++struct sh_mobile_sdhi_of_data { ++ unsigned long tmio_flags; ++ unsigned long capabilities; ++ unsigned long capabilities2; ++}; ++ ++static const struct sh_mobile_sdhi_of_data sh_mobile_sdhi_of_cfg[] = { ++ { ++ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, ++ }, ++}; ++ ++static const struct sh_mobile_sdhi_of_data of_rcar_gen1_compatible = { ++ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE, ++ .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, ++}; ++ ++static const struct sh_mobile_sdhi_of_data of_rcar_gen2_compatible = { ++ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE, ++ .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, ++ .capabilities2 = MMC_CAP2_NO_MULTI_READ, ++}; ++ ++static const struct of_device_id sh_mobile_sdhi_of_match[] = { ++ { .compatible = "renesas,sdhi-shmobile" }, ++ { .compatible = "renesas,sdhi-sh7372" }, ++ { .compatible = "renesas,sdhi-sh73a0", .data = &sh_mobile_sdhi_of_cfg[0], }, ++ { .compatible = "renesas,sdhi-r8a73a4", .data = &sh_mobile_sdhi_of_cfg[0], }, ++ { .compatible = "renesas,sdhi-r8a7740", .data = &sh_mobile_sdhi_of_cfg[0], }, ++ { .compatible = "renesas,sdhi-r8a7778", .data = &of_rcar_gen1_compatible, }, ++ { .compatible = "renesas,sdhi-r8a7779", .data = &of_rcar_gen1_compatible, }, ++ { .compatible = "renesas,sdhi-r8a7790", .data = &of_rcar_gen2_compatible, }, ++ { .compatible = "renesas,sdhi-r8a7791", .data = &of_rcar_gen2_compatible, }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match); ++ + struct sh_mobile_sdhi { + struct clk *clk; + struct tmio_mmc_data mmc_data; +- struct sh_dmae_slave param_tx; +- struct sh_dmae_slave param_rx; + struct tmio_mmc_dma dma_priv; + }; + +-static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state) ++static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f) + { +- struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ struct tmio_mmc_host *host = mmc_priv(mmc); ++ struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); ++ int ret = clk_prepare_enable(priv->clk); ++ if (ret < 0) ++ return ret; + +- if (p && p->set_pwr) +- p->set_pwr(pdev, state); ++ *f = clk_get_rate(priv->clk); ++ return 0; + } + +-static int sh_mobile_sdhi_get_cd(struct platform_device *pdev) ++static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev) + { +- struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; +- +- if (p && p->get_cd) +- return p->get_cd(pdev); +- else +- return -ENOSYS; ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ struct tmio_mmc_host *host = mmc_priv(mmc); ++ struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); ++ clk_disable_unprepare(priv->clk); + } + + static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host) +@@ -90,56 +132,86 @@ static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr) + return 0; + } + +-static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) ++static void sh_mobile_sdhi_cd_wakeup(const struct platform_device *pdev) ++{ ++ mmc_detect_change(platform_get_drvdata(pdev), msecs_to_jiffies(100)); ++} ++ ++static const struct sh_mobile_sdhi_ops sdhi_ops = { ++ .cd_wakeup = sh_mobile_sdhi_cd_wakeup, ++}; ++ ++static int sh_mobile_sdhi_probe(struct platform_device *pdev) + { ++ const struct of_device_id *of_id = ++ of_match_device(sh_mobile_sdhi_of_match, &pdev->dev); + struct sh_mobile_sdhi *priv; + struct tmio_mmc_data *mmc_data; + struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; + struct tmio_mmc_host *host; +- char clk_name[8]; ++ struct resource *res; + int irq, ret, i = 0; + bool multiplexed_isr = true; ++ struct tmio_mmc_dma *dma_priv; ++ u16 ver; + +- priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL); ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -EINVAL; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_mobile_sdhi), GFP_KERNEL); + if (priv == NULL) { + dev_err(&pdev->dev, "kzalloc failed\n"); + return -ENOMEM; + } + + mmc_data = &priv->mmc_data; +- p->pdata = mmc_data; ++ dma_priv = &priv->dma_priv; ++ ++ if (p) { ++ if (p->init) { ++ ret = p->init(pdev, &sdhi_ops); ++ if (ret) ++ return ret; ++ } ++ } + +- snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id); +- priv->clk = clk_get(&pdev->dev, clk_name); ++ priv->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(priv->clk)) { +- dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); + ret = PTR_ERR(priv->clk); ++ dev_err(&pdev->dev, "cannot get clock: %d\n", ret); + goto eclkget; + } + +- clk_enable(priv->clk); +- +- mmc_data->hclk = clk_get_rate(priv->clk); +- mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; +- mmc_data->get_cd = sh_mobile_sdhi_get_cd; ++ mmc_data->clk_enable = sh_mobile_sdhi_clk_enable; ++ mmc_data->clk_disable = sh_mobile_sdhi_clk_disable; + mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED; ++ mmc_data->write16_hook = sh_mobile_sdhi_write16_hook; + if (p) { + mmc_data->flags = p->tmio_flags; +- if (mmc_data->flags & TMIO_MMC_HAS_IDLE_WAIT) +- mmc_data->write16_hook = sh_mobile_sdhi_write16_hook; + mmc_data->ocr_mask = p->tmio_ocr_mask; + mmc_data->capabilities |= p->tmio_caps; ++ mmc_data->capabilities2 |= p->tmio_caps2; ++ mmc_data->cd_gpio = p->cd_gpio; + + if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) { +- priv->param_tx.slave_id = p->dma_slave_tx; +- priv->param_rx.slave_id = p->dma_slave_rx; +- priv->dma_priv.chan_priv_tx = &priv->param_tx; +- priv->dma_priv.chan_priv_rx = &priv->param_rx; +- priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */ +- mmc_data->dma = &priv->dma_priv; ++ /* ++ * Yes, we have to provide slave IDs twice to TMIO: ++ * once as a filter parameter and once for channel ++ * configuration as an explicit slave ID ++ */ ++ dma_priv->chan_priv_tx = (void *)p->dma_slave_tx; ++ dma_priv->chan_priv_rx = (void *)p->dma_slave_rx; ++ dma_priv->slave_id_tx = p->dma_slave_tx; ++ dma_priv->slave_id_rx = p->dma_slave_rx; + } + } + ++ dma_priv->alignment_shift = 1; /* 2-byte alignment */ ++ dma_priv->filter = shdma_chan_filter; ++ ++ mmc_data->dma = dma_priv; ++ + /* + * All SDHI blocks support 2-byte and larger block sizes in 4-bit + * bus width mode. +@@ -151,11 +223,29 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + */ + mmc_data->flags |= TMIO_MMC_SDIO_IRQ; + ++ if (of_id && of_id->data) { ++ const struct sh_mobile_sdhi_of_data *of_data = of_id->data; ++ mmc_data->flags |= of_data->tmio_flags; ++ mmc_data->capabilities |= of_data->capabilities; ++ mmc_data->capabilities2 |= of_data->capabilities2; ++ } ++ ++ /* SD control register space size is 0x100, 0x200 for bus_shift=1 */ ++ mmc_data->bus_shift = resource_size(res) >> 9; ++ + ret = tmio_mmc_host_probe(&host, pdev, mmc_data); + if (ret < 0) + goto eprobe; + + /* ++ * FIXME: ++ * this Workaround can be more clever method ++ */ ++ ver = sd_ctrl_read16(host, CTL_VERSION); ++ if (ver == 0xCB0D) ++ sd_ctrl_write16(host, EXT_ACC, 1); ++ ++ /* + * Allow one or more specific (named) ISRs or + * one or more multiplexed (un-named) ISRs. + */ +@@ -163,33 +253,33 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT); + if (irq >= 0) { + multiplexed_isr = false; +- ret = request_irq(irq, tmio_mmc_card_detect_irq, 0, ++ ret = devm_request_irq(&pdev->dev, irq, tmio_mmc_card_detect_irq, 0, + dev_name(&pdev->dev), host); + if (ret) +- goto eirq_card_detect; ++ goto eirq; + } + + irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO); + if (irq >= 0) { + multiplexed_isr = false; +- ret = request_irq(irq, tmio_mmc_sdio_irq, 0, ++ ret = devm_request_irq(&pdev->dev, irq, tmio_mmc_sdio_irq, 0, + dev_name(&pdev->dev), host); + if (ret) +- goto eirq_sdio; ++ goto eirq; + } + + irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDCARD); + if (irq >= 0) { + multiplexed_isr = false; +- ret = request_irq(irq, tmio_mmc_sdcard_irq, 0, ++ ret = devm_request_irq(&pdev->dev, irq, tmio_mmc_sdcard_irq, 0, + dev_name(&pdev->dev), host); + if (ret) +- goto eirq_sdcard; ++ goto eirq; + } else if (!multiplexed_isr) { + dev_err(&pdev->dev, + "Principal SD-card IRQ is missing among named interrupts\n"); + ret = irq; +- goto eirq_sdcard; ++ goto eirq; + } + + if (multiplexed_isr) { +@@ -198,44 +288,32 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + if (irq < 0) + break; + i++; +- ret = request_irq(irq, tmio_mmc_irq, 0, ++ ret = devm_request_irq(&pdev->dev, irq, tmio_mmc_irq, 0, + dev_name(&pdev->dev), host); + if (ret) +- goto eirq_multiplexed; ++ goto eirq; + } + + /* There must be at least one IRQ source */ +- if (!i) +- goto eirq_multiplexed; ++ if (!i) { ++ ret = irq; ++ goto eirq; ++ } + } + + dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n", + mmc_hostname(host->mmc), (unsigned long) +- (platform_get_resource(pdev,IORESOURCE_MEM, 0)->start), +- mmc_data->hclk / 1000000); ++ (platform_get_resource(pdev, IORESOURCE_MEM, 0)->start), ++ host->mmc->f_max / 1000000); + + return ret; + +-eirq_multiplexed: +- while (i--) { +- irq = platform_get_irq(pdev, i); +- free_irq(irq, host); +- } +-eirq_sdcard: +- irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO); +- if (irq >= 0) +- free_irq(irq, host); +-eirq_sdio: +- irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT); +- if (irq >= 0) +- free_irq(irq, host); +-eirq_card_detect: ++eirq: + tmio_mmc_host_remove(host); + eprobe: +- clk_disable(priv->clk); +- clk_put(priv->clk); + eclkget: +- kfree(priv); ++ if (p && p->cleanup) ++ p->cleanup(pdev); + return ret; + } + +@@ -243,33 +321,21 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev) + { + struct mmc_host *mmc = platform_get_drvdata(pdev); + struct tmio_mmc_host *host = mmc_priv(mmc); +- struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); + struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; +- int i = 0, irq; +- +- p->pdata = NULL; + + tmio_mmc_host_remove(host); + +- while (1) { +- irq = platform_get_irq(pdev, i++); +- if (irq < 0) +- break; +- free_irq(irq, host); +- } +- +- clk_disable(priv->clk); +- clk_put(priv->clk); +- kfree(priv); ++ if (p && p->cleanup) ++ p->cleanup(pdev); + + return 0; + } + + static const struct dev_pm_ops tmio_mmc_dev_pm_ops = { +- .suspend = tmio_mmc_host_suspend, +- .resume = tmio_mmc_host_resume, +- .runtime_suspend = tmio_mmc_host_runtime_suspend, +- .runtime_resume = tmio_mmc_host_runtime_resume, ++ SET_SYSTEM_SLEEP_PM_OPS(tmio_mmc_host_suspend, tmio_mmc_host_resume) ++ SET_RUNTIME_PM_OPS(tmio_mmc_host_runtime_suspend, ++ tmio_mmc_host_runtime_resume, ++ NULL) + }; + + static struct platform_driver sh_mobile_sdhi_driver = { +@@ -277,23 +343,13 @@ static struct platform_driver sh_mobile_sdhi_driver = { + .name = "sh_mobile_sdhi", + .owner = THIS_MODULE, + .pm = &tmio_mmc_dev_pm_ops, ++ .of_match_table = sh_mobile_sdhi_of_match, + }, + .probe = sh_mobile_sdhi_probe, +- .remove = __devexit_p(sh_mobile_sdhi_remove), ++ .remove = sh_mobile_sdhi_remove, + }; + +-static int __init sh_mobile_sdhi_init(void) +-{ +- return platform_driver_register(&sh_mobile_sdhi_driver); +-} +- +-static void __exit sh_mobile_sdhi_exit(void) +-{ +- platform_driver_unregister(&sh_mobile_sdhi_driver); +-} +- +-module_init(sh_mobile_sdhi_init); +-module_exit(sh_mobile_sdhi_exit); ++module_platform_driver(sh_mobile_sdhi_driver); + + MODULE_DESCRIPTION("SuperH Mobile SDHI driver"); + MODULE_AUTHOR("Magnus Damm"); +diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c +new file mode 100644 +index 0000000..024f67c +--- /dev/null ++++ b/drivers/mmc/host/sunxi-mmc.c +@@ -0,0 +1,1049 @@ ++/* ++ * Driver for sunxi SD/MMC host controllers ++ * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd. ++ * (C) Copyright 2007-2011 Aaron Maoye ++ * (C) Copyright 2013-2014 O2S GmbH ++ * (C) Copyright 2013-2014 David Lanzend�rfer ++ * (C) Copyright 2013-2014 Hans de Goede ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the 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 ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* register offset definitions */ ++#define SDXC_REG_GCTRL (0x00) /* SMC Global Control Register */ ++#define SDXC_REG_CLKCR (0x04) /* SMC Clock Control Register */ ++#define SDXC_REG_TMOUT (0x08) /* SMC Time Out Register */ ++#define SDXC_REG_WIDTH (0x0C) /* SMC Bus Width Register */ ++#define SDXC_REG_BLKSZ (0x10) /* SMC Block Size Register */ ++#define SDXC_REG_BCNTR (0x14) /* SMC Byte Count Register */ ++#define SDXC_REG_CMDR (0x18) /* SMC Command Register */ ++#define SDXC_REG_CARG (0x1C) /* SMC Argument Register */ ++#define SDXC_REG_RESP0 (0x20) /* SMC Response Register 0 */ ++#define SDXC_REG_RESP1 (0x24) /* SMC Response Register 1 */ ++#define SDXC_REG_RESP2 (0x28) /* SMC Response Register 2 */ ++#define SDXC_REG_RESP3 (0x2C) /* SMC Response Register 3 */ ++#define SDXC_REG_IMASK (0x30) /* SMC Interrupt Mask Register */ ++#define SDXC_REG_MISTA (0x34) /* SMC Masked Interrupt Status Register */ ++#define SDXC_REG_RINTR (0x38) /* SMC Raw Interrupt Status Register */ ++#define SDXC_REG_STAS (0x3C) /* SMC Status Register */ ++#define SDXC_REG_FTRGL (0x40) /* SMC FIFO Threshold Watermark Registe */ ++#define SDXC_REG_FUNS (0x44) /* SMC Function Select Register */ ++#define SDXC_REG_CBCR (0x48) /* SMC CIU Byte Count Register */ ++#define SDXC_REG_BBCR (0x4C) /* SMC BIU Byte Count Register */ ++#define SDXC_REG_DBGC (0x50) /* SMC Debug Enable Register */ ++#define SDXC_REG_HWRST (0x78) /* SMC Card Hardware Reset for Register */ ++#define SDXC_REG_DMAC (0x80) /* SMC IDMAC Control Register */ ++#define SDXC_REG_DLBA (0x84) /* SMC IDMAC Descriptor List Base Addre */ ++#define SDXC_REG_IDST (0x88) /* SMC IDMAC Status Register */ ++#define SDXC_REG_IDIE (0x8C) /* SMC IDMAC Interrupt Enable Register */ ++#define SDXC_REG_CHDA (0x90) ++#define SDXC_REG_CBDA (0x94) ++ ++#define mmc_readl(host, reg) \ ++ readl((host)->reg_base + SDXC_##reg) ++#define mmc_writel(host, reg, value) \ ++ writel((value), (host)->reg_base + SDXC_##reg) ++ ++/* global control register bits */ ++#define SDXC_SOFT_RESET BIT(0) ++#define SDXC_FIFO_RESET BIT(1) ++#define SDXC_DMA_RESET BIT(2) ++#define SDXC_INTERRUPT_ENABLE_BIT BIT(4) ++#define SDXC_DMA_ENABLE_BIT BIT(5) ++#define SDXC_DEBOUNCE_ENABLE_BIT BIT(8) ++#define SDXC_POSEDGE_LATCH_DATA BIT(9) ++#define SDXC_DDR_MODE BIT(10) ++#define SDXC_MEMORY_ACCESS_DONE BIT(29) ++#define SDXC_ACCESS_DONE_DIRECT BIT(30) ++#define SDXC_ACCESS_BY_AHB BIT(31) ++#define SDXC_ACCESS_BY_DMA (0 << 31) ++#define SDXC_HARDWARE_RESET \ ++ (SDXC_SOFT_RESET | SDXC_FIFO_RESET | SDXC_DMA_RESET) ++ ++/* clock control bits */ ++#define SDXC_CARD_CLOCK_ON BIT(16) ++#define SDXC_LOW_POWER_ON BIT(17) ++ ++/* bus width */ ++#define SDXC_WIDTH1 0 ++#define SDXC_WIDTH4 1 ++#define SDXC_WIDTH8 2 ++ ++/* smc command bits */ ++#define SDXC_RESP_EXPIRE BIT(6) ++#define SDXC_LONG_RESPONSE BIT(7) ++#define SDXC_CHECK_RESPONSE_CRC BIT(8) ++#define SDXC_DATA_EXPIRE BIT(9) ++#define SDXC_WRITE BIT(10) ++#define SDXC_SEQUENCE_MODE BIT(11) ++#define SDXC_SEND_AUTO_STOP BIT(12) ++#define SDXC_WAIT_PRE_OVER BIT(13) ++#define SDXC_STOP_ABORT_CMD BIT(14) ++#define SDXC_SEND_INIT_SEQUENCE BIT(15) ++#define SDXC_UPCLK_ONLY BIT(21) ++#define SDXC_READ_CEATA_DEV BIT(22) ++#define SDXC_CCS_EXPIRE BIT(23) ++#define SDXC_ENABLE_BIT_BOOT BIT(24) ++#define SDXC_ALT_BOOT_OPTIONS BIT(25) ++#define SDXC_BOOT_ACK_EXPIRE BIT(26) ++#define SDXC_BOOT_ABORT BIT(27) ++#define SDXC_VOLTAGE_SWITCH BIT(28) ++#define SDXC_USE_HOLD_REGISTER BIT(29) ++#define SDXC_START BIT(31) ++ ++/* interrupt bits */ ++#define SDXC_RESP_ERROR BIT(1) ++#define SDXC_COMMAND_DONE BIT(2) ++#define SDXC_DATA_OVER BIT(3) ++#define SDXC_TX_DATA_REQUEST BIT(4) ++#define SDXC_RX_DATA_REQUEST BIT(5) ++#define SDXC_RESP_CRC_ERROR BIT(6) ++#define SDXC_DATA_CRC_ERROR BIT(7) ++#define SDXC_RESP_TIMEOUT BIT(8) ++#define SDXC_DATA_TIMEOUT BIT(9) ++#define SDXC_VOLTAGE_CHANGE_DONE BIT(10) ++#define SDXC_FIFO_RUN_ERROR BIT(11) ++#define SDXC_HARD_WARE_LOCKED BIT(12) ++#define SDXC_START_BIT_ERROR BIT(13) ++#define SDXC_AUTO_COMMAND_DONE BIT(14) ++#define SDXC_END_BIT_ERROR BIT(15) ++#define SDXC_SDIO_INTERRUPT BIT(16) ++#define SDXC_CARD_INSERT BIT(30) ++#define SDXC_CARD_REMOVE BIT(31) ++#define SDXC_INTERRUPT_ERROR_BIT \ ++ (SDXC_RESP_ERROR | SDXC_RESP_CRC_ERROR | SDXC_DATA_CRC_ERROR | \ ++ SDXC_RESP_TIMEOUT | SDXC_DATA_TIMEOUT | SDXC_FIFO_RUN_ERROR | \ ++ SDXC_HARD_WARE_LOCKED | SDXC_START_BIT_ERROR | SDXC_END_BIT_ERROR) ++#define SDXC_INTERRUPT_DONE_BIT \ ++ (SDXC_AUTO_COMMAND_DONE | SDXC_DATA_OVER | \ ++ SDXC_COMMAND_DONE | SDXC_VOLTAGE_CHANGE_DONE) ++ ++/* status */ ++#define SDXC_RXWL_FLAG BIT(0) ++#define SDXC_TXWL_FLAG BIT(1) ++#define SDXC_FIFO_EMPTY BIT(2) ++#define SDXC_FIFO_FULL BIT(3) ++#define SDXC_CARD_PRESENT BIT(8) ++#define SDXC_CARD_DATA_BUSY BIT(9) ++#define SDXC_DATA_FSM_BUSY BIT(10) ++#define SDXC_DMA_REQUEST BIT(31) ++#define SDXC_FIFO_SIZE 16 ++ ++/* Function select */ ++#define SDXC_CEATA_ON (0xceaa << 16) ++#define SDXC_SEND_IRQ_RESPONSE BIT(0) ++#define SDXC_SDIO_READ_WAIT BIT(1) ++#define SDXC_ABORT_READ_DATA BIT(2) ++#define SDXC_SEND_CCSD BIT(8) ++#define SDXC_SEND_AUTO_STOPCCSD BIT(9) ++#define SDXC_CEATA_DEV_IRQ_ENABLE BIT(10) ++ ++/* IDMA controller bus mod bit field */ ++#define SDXC_IDMAC_SOFT_RESET BIT(0) ++#define SDXC_IDMAC_FIX_BURST BIT(1) ++#define SDXC_IDMAC_IDMA_ON BIT(7) ++#define SDXC_IDMAC_REFETCH_DES BIT(31) ++ ++/* IDMA status bit field */ ++#define SDXC_IDMAC_TRANSMIT_INTERRUPT BIT(0) ++#define SDXC_IDMAC_RECEIVE_INTERRUPT BIT(1) ++#define SDXC_IDMAC_FATAL_BUS_ERROR BIT(2) ++#define SDXC_IDMAC_DESTINATION_INVALID BIT(4) ++#define SDXC_IDMAC_CARD_ERROR_SUM BIT(5) ++#define SDXC_IDMAC_NORMAL_INTERRUPT_SUM BIT(8) ++#define SDXC_IDMAC_ABNORMAL_INTERRUPT_SUM BIT(9) ++#define SDXC_IDMAC_HOST_ABORT_INTERRUPT BIT(10) ++#define SDXC_IDMAC_IDLE (0 << 13) ++#define SDXC_IDMAC_SUSPEND (1 << 13) ++#define SDXC_IDMAC_DESC_READ (2 << 13) ++#define SDXC_IDMAC_DESC_CHECK (3 << 13) ++#define SDXC_IDMAC_READ_REQUEST_WAIT (4 << 13) ++#define SDXC_IDMAC_WRITE_REQUEST_WAIT (5 << 13) ++#define SDXC_IDMAC_READ (6 << 13) ++#define SDXC_IDMAC_WRITE (7 << 13) ++#define SDXC_IDMAC_DESC_CLOSE (8 << 13) ++ ++/* ++* If the idma-des-size-bits of property is ie 13, bufsize bits are: ++* Bits 0-12: buf1 size ++* Bits 13-25: buf2 size ++* Bits 26-31: not used ++* Since we only ever set buf1 size, we can simply store it directly. ++*/ ++#define SDXC_IDMAC_DES0_DIC BIT(1) /* disable interrupt on completion */ ++#define SDXC_IDMAC_DES0_LD BIT(2) /* last descriptor */ ++#define SDXC_IDMAC_DES0_FD BIT(3) /* first descriptor */ ++#define SDXC_IDMAC_DES0_CH BIT(4) /* chain mode */ ++#define SDXC_IDMAC_DES0_ER BIT(5) /* end of ring */ ++#define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */ ++#define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */ ++ ++struct sunxi_idma_des { ++ u32 config; ++ u32 buf_size; ++ u32 buf_addr_ptr1; ++ u32 buf_addr_ptr2; ++}; ++ ++struct sunxi_mmc_host { ++ struct mmc_host *mmc; ++ struct reset_control *reset; ++ ++ /* IO mapping base */ ++ void __iomem *reg_base; ++ ++ /* clock management */ ++ struct clk *clk_ahb; ++ struct clk *clk_mmc; ++ ++ /* irq */ ++ spinlock_t lock; ++ int irq; ++ u32 int_sum; ++ u32 sdio_imask; ++ ++ /* dma */ ++ u32 idma_des_size_bits; ++ dma_addr_t sg_dma; ++ void *sg_cpu; ++ bool wait_dma; ++ ++ struct mmc_request *mrq; ++ struct mmc_request *manual_stop_mrq; ++ int ferror; ++}; ++ ++static int sunxi_mmc_reset_host(struct sunxi_mmc_host *host) ++{ ++ unsigned long expire = jiffies + msecs_to_jiffies(250); ++ u32 rval; ++ ++ mmc_writel(host, REG_CMDR, SDXC_HARDWARE_RESET); ++ do { ++ rval = mmc_readl(host, REG_GCTRL); ++ } while (time_before(jiffies, expire) && (rval & SDXC_HARDWARE_RESET)); ++ ++ if (rval & SDXC_HARDWARE_RESET) { ++ dev_err(mmc_dev(host->mmc), "fatal err reset timeout\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int sunxi_mmc_init_host(struct mmc_host *mmc) ++{ ++ u32 rval; ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ ++ if (sunxi_mmc_reset_host(host)) ++ return -EIO; ++ ++ mmc_writel(host, REG_FTRGL, 0x20070008); ++ mmc_writel(host, REG_TMOUT, 0xffffffff); ++ mmc_writel(host, REG_IMASK, host->sdio_imask); ++ mmc_writel(host, REG_RINTR, 0xffffffff); ++ mmc_writel(host, REG_DBGC, 0xdeb); ++ mmc_writel(host, REG_FUNS, SDXC_CEATA_ON); ++ mmc_writel(host, REG_DLBA, host->sg_dma); ++ ++ rval = mmc_readl(host, REG_GCTRL); ++ rval |= SDXC_INTERRUPT_ENABLE_BIT; ++ rval &= ~SDXC_ACCESS_DONE_DIRECT; ++ mmc_writel(host, REG_GCTRL, rval); ++ ++ return 0; ++} ++ ++static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, ++ struct mmc_data *data) ++{ ++ struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu; ++ struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma; ++ int i, max_len = (1 << host->idma_des_size_bits); ++ ++ for (i = 0; i < data->sg_len; i++) { ++ pdes[i].config = SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN | ++ SDXC_IDMAC_DES0_DIC; ++ ++ if (data->sg[i].length == max_len) ++ pdes[i].buf_size = 0; /* 0 == max_len */ ++ else ++ pdes[i].buf_size = data->sg[i].length; ++ ++ pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]); ++ pdes[i].buf_addr_ptr2 = (u32)&pdes_pa[i + 1]; ++ } ++ ++ pdes[0].config |= SDXC_IDMAC_DES0_FD; ++ pdes[i - 1].config = SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_LD; ++ ++ /* ++ * Avoid the io-store starting the idmac hitting io-mem before the ++ * descriptors hit the main-mem. ++ */ ++ wmb(); ++} ++ ++static enum dma_data_direction sunxi_mmc_get_dma_dir(struct mmc_data *data) ++{ ++ if (data->flags & MMC_DATA_WRITE) ++ return DMA_TO_DEVICE; ++ else ++ return DMA_FROM_DEVICE; ++} ++ ++static int sunxi_mmc_map_dma(struct sunxi_mmc_host *host, ++ struct mmc_data *data) ++{ ++ u32 i, dma_len; ++ struct scatterlist *sg; ++ ++ dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, ++ sunxi_mmc_get_dma_dir(data)); ++ if (dma_len == 0) { ++ dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n"); ++ return -ENOMEM; ++ } ++ ++ for_each_sg(data->sg, sg, data->sg_len, i) { ++ if (sg->offset & 3 || sg->length & 3) { ++ dev_err(mmc_dev(host->mmc), ++ "unaligned scatterlist: os %x length %d\n", ++ sg->offset, sg->length); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++static void sunxi_mmc_start_dma(struct sunxi_mmc_host *host, ++ struct mmc_data *data) ++{ ++ u32 rval; ++ ++ sunxi_mmc_init_idma_des(host, data); ++ ++ rval = mmc_readl(host, REG_GCTRL); ++ rval |= SDXC_DMA_ENABLE_BIT; ++ mmc_writel(host, REG_GCTRL, rval); ++ rval |= SDXC_DMA_RESET; ++ mmc_writel(host, REG_GCTRL, rval); ++ ++ mmc_writel(host, REG_DMAC, SDXC_IDMAC_SOFT_RESET); ++ ++ if (!(data->flags & MMC_DATA_WRITE)) ++ mmc_writel(host, REG_IDIE, SDXC_IDMAC_RECEIVE_INTERRUPT); ++ ++ mmc_writel(host, REG_DMAC, ++ SDXC_IDMAC_FIX_BURST | SDXC_IDMAC_IDMA_ON); ++} ++ ++static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host, ++ struct mmc_request *req) ++{ ++ u32 arg, cmd_val, ri; ++ unsigned long expire = jiffies + msecs_to_jiffies(1000); ++ ++ cmd_val = SDXC_START | SDXC_RESP_EXPIRE | ++ SDXC_STOP_ABORT_CMD | SDXC_CHECK_RESPONSE_CRC; ++ ++ if (req->cmd->opcode == SD_IO_RW_EXTENDED) { ++ cmd_val |= SD_IO_RW_DIRECT; ++ arg = (1 << 31) | (0 << 28) | (SDIO_CCCR_ABORT << 9) | ++ ((req->cmd->arg >> 28) & 0x7); ++ } else { ++ cmd_val |= MMC_STOP_TRANSMISSION; ++ arg = 0; ++ } ++ ++ mmc_writel(host, REG_CARG, arg); ++ mmc_writel(host, REG_CMDR, cmd_val); ++ ++ do { ++ ri = mmc_readl(host, REG_RINTR); ++ } while (!(ri & (SDXC_COMMAND_DONE | SDXC_INTERRUPT_ERROR_BIT)) && ++ time_before(jiffies, expire)); ++ ++ if (!(ri & SDXC_COMMAND_DONE) || (ri & SDXC_INTERRUPT_ERROR_BIT)) { ++ dev_err(mmc_dev(host->mmc), "send stop command failed\n"); ++ if (req->stop) ++ req->stop->resp[0] = -ETIMEDOUT; ++ } else { ++ if (req->stop) ++ req->stop->resp[0] = mmc_readl(host, REG_RESP0); ++ } ++ ++ mmc_writel(host, REG_RINTR, 0xffff); ++} ++ ++static void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *host) ++{ ++ struct mmc_command *cmd = host->mrq->cmd; ++ struct mmc_data *data = host->mrq->data; ++ ++ /* For some cmds timeout is normal with sd/mmc cards */ ++ if ((host->int_sum & SDXC_INTERRUPT_ERROR_BIT) == ++ SDXC_RESP_TIMEOUT && (cmd->opcode == SD_IO_SEND_OP_COND || ++ cmd->opcode == SD_IO_RW_DIRECT)) ++ return; ++ ++ dev_err(mmc_dev(host->mmc), ++ "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n", ++ host->mmc->index, cmd->opcode, ++ data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "", ++ host->int_sum & SDXC_RESP_ERROR ? " RE" : "", ++ host->int_sum & SDXC_RESP_CRC_ERROR ? " RCE" : "", ++ host->int_sum & SDXC_DATA_CRC_ERROR ? " DCE" : "", ++ host->int_sum & SDXC_RESP_TIMEOUT ? " RTO" : "", ++ host->int_sum & SDXC_DATA_TIMEOUT ? " DTO" : "", ++ host->int_sum & SDXC_FIFO_RUN_ERROR ? " FE" : "", ++ host->int_sum & SDXC_HARD_WARE_LOCKED ? " HL" : "", ++ host->int_sum & SDXC_START_BIT_ERROR ? " SBE" : "", ++ host->int_sum & SDXC_END_BIT_ERROR ? " EBE" : "" ++ ); ++} ++ ++/* Called in interrupt context! */ ++static irqreturn_t sunxi_mmc_finalize_request(struct sunxi_mmc_host *host) ++{ ++ struct mmc_request *mrq = host->mrq; ++ struct mmc_data *data = mrq->data; ++ u32 rval; ++ ++ mmc_writel(host, REG_IMASK, host->sdio_imask); ++ mmc_writel(host, REG_IDIE, 0); ++ ++ if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT) { ++ sunxi_mmc_dump_errinfo(host); ++ mrq->cmd->error = -ETIMEDOUT; ++ ++ if (data) { ++ data->error = -ETIMEDOUT; ++ host->manual_stop_mrq = mrq; ++ } ++ ++ if (mrq->stop) ++ mrq->stop->error = -ETIMEDOUT; ++ } else { ++ if (mrq->cmd->flags & MMC_RSP_136) { ++ mrq->cmd->resp[0] = mmc_readl(host, REG_RESP3); ++ mrq->cmd->resp[1] = mmc_readl(host, REG_RESP2); ++ mrq->cmd->resp[2] = mmc_readl(host, REG_RESP1); ++ mrq->cmd->resp[3] = mmc_readl(host, REG_RESP0); ++ } else { ++ mrq->cmd->resp[0] = mmc_readl(host, REG_RESP0); ++ } ++ ++ if (data) ++ data->bytes_xfered = data->blocks * data->blksz; ++ } ++ ++ if (data) { ++ mmc_writel(host, REG_IDST, 0x337); ++ mmc_writel(host, REG_DMAC, 0); ++ rval = mmc_readl(host, REG_GCTRL); ++ rval |= SDXC_DMA_RESET; ++ mmc_writel(host, REG_GCTRL, rval); ++ rval &= ~SDXC_DMA_ENABLE_BIT; ++ mmc_writel(host, REG_GCTRL, rval); ++ rval |= SDXC_FIFO_RESET; ++ mmc_writel(host, REG_GCTRL, rval); ++ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, ++ sunxi_mmc_get_dma_dir(data)); ++ } ++ ++ mmc_writel(host, REG_RINTR, 0xffff); ++ ++ host->mrq = NULL; ++ host->int_sum = 0; ++ host->wait_dma = false; ++ ++ return host->manual_stop_mrq ? IRQ_WAKE_THREAD : IRQ_HANDLED; ++} ++ ++static irqreturn_t sunxi_mmc_irq(int irq, void *dev_id) ++{ ++ struct sunxi_mmc_host *host = dev_id; ++ struct mmc_request *mrq; ++ u32 msk_int, idma_int; ++ bool finalize = false; ++ bool sdio_int = false; ++ irqreturn_t ret = IRQ_HANDLED; ++ ++ spin_lock(&host->lock); ++ ++ idma_int = mmc_readl(host, REG_IDST); ++ msk_int = mmc_readl(host, REG_MISTA); ++ ++ dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n", ++ host->mrq, msk_int, idma_int); ++ ++ mrq = host->mrq; ++ if (mrq) { ++ if (idma_int & SDXC_IDMAC_RECEIVE_INTERRUPT) ++ host->wait_dma = false; ++ ++ host->int_sum |= msk_int; ++ ++ /* Wait for COMMAND_DONE on RESPONSE_TIMEOUT before finalize */ ++ if ((host->int_sum & SDXC_RESP_TIMEOUT) && ++ !(host->int_sum & SDXC_COMMAND_DONE)) ++ mmc_writel(host, REG_IMASK, ++ host->sdio_imask | SDXC_COMMAND_DONE); ++ /* Don't wait for dma on error */ ++ else if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT) ++ finalize = true; ++ else if ((host->int_sum & SDXC_INTERRUPT_DONE_BIT) && ++ !host->wait_dma) ++ finalize = true; ++ } ++ ++ if (msk_int & SDXC_SDIO_INTERRUPT) ++ sdio_int = true; ++ ++ mmc_writel(host, REG_RINTR, msk_int); ++ mmc_writel(host, REG_IDST, idma_int); ++ ++ if (finalize) ++ ret = sunxi_mmc_finalize_request(host); ++ ++ spin_unlock(&host->lock); ++ ++ if (finalize && ret == IRQ_HANDLED) ++ mmc_request_done(host->mmc, mrq); ++ ++ if (sdio_int) ++ mmc_signal_sdio_irq(host->mmc); ++ ++ return ret; ++} ++ ++static irqreturn_t sunxi_mmc_handle_manual_stop(int irq, void *dev_id) ++{ ++ struct sunxi_mmc_host *host = dev_id; ++ struct mmc_request *mrq; ++ unsigned long iflags; ++ ++ spin_lock_irqsave(&host->lock, iflags); ++ mrq = host->manual_stop_mrq; ++ spin_unlock_irqrestore(&host->lock, iflags); ++ ++ if (!mrq) { ++ dev_err(mmc_dev(host->mmc), "no request for manual stop\n"); ++ return IRQ_HANDLED; ++ } ++ ++ dev_err(mmc_dev(host->mmc), "data error, sending stop command\n"); ++ sunxi_mmc_send_manual_stop(host, mrq); ++ ++ spin_lock_irqsave(&host->lock, iflags); ++ host->manual_stop_mrq = NULL; ++ spin_unlock_irqrestore(&host->lock, iflags); ++ ++ mmc_request_done(host->mmc, mrq); ++ ++ return IRQ_HANDLED; ++} ++ ++static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en) ++{ ++ unsigned long expire = jiffies + msecs_to_jiffies(250); ++ u32 rval; ++ ++ rval = mmc_readl(host, REG_CLKCR); ++ rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON); ++ ++ if (oclk_en) ++ rval |= SDXC_CARD_CLOCK_ON; ++ ++ mmc_writel(host, REG_CLKCR, rval); ++ ++ rval = SDXC_START | SDXC_UPCLK_ONLY | SDXC_WAIT_PRE_OVER; ++ mmc_writel(host, REG_CMDR, rval); ++ ++ do { ++ rval = mmc_readl(host, REG_CMDR); ++ } while (time_before(jiffies, expire) && (rval & SDXC_START)); ++ ++ /* clear irq status bits set by the command */ ++ mmc_writel(host, REG_RINTR, ++ mmc_readl(host, REG_RINTR) & ~SDXC_SDIO_INTERRUPT); ++ ++ if (rval & SDXC_START) { ++ dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, ++ struct mmc_ios *ios) ++{ ++ u32 rate, oclk_dly, rval, sclk_dly, src_clk; ++ int ret; ++ ++ rate = clk_round_rate(host->clk_mmc, ios->clock); ++ dev_dbg(mmc_dev(host->mmc), "setting clk to %d, rounded %d\n", ++ ios->clock, rate); ++ ++ /* setting clock rate */ ++ ret = clk_set_rate(host->clk_mmc, rate); ++ if (ret) { ++ dev_err(mmc_dev(host->mmc), "error setting clk to %d: %d\n", ++ rate, ret); ++ return ret; ++ } ++ ++ ret = sunxi_mmc_oclk_onoff(host, 0); ++ if (ret) ++ return ret; ++ ++ /* clear internal divider */ ++ rval = mmc_readl(host, REG_CLKCR); ++ rval &= ~0xff; ++ mmc_writel(host, REG_CLKCR, rval); ++ ++ /* determine delays */ ++ if (rate <= 400000) { ++ oclk_dly = 0; ++ sclk_dly = 7; ++ } else if (rate <= 25000000) { ++ oclk_dly = 0; ++ sclk_dly = 5; ++ } else if (rate <= 50000000) { ++ if (ios->timing == MMC_TIMING_UHS_DDR50) { ++ oclk_dly = 2; ++ sclk_dly = 4; ++ } else { ++ oclk_dly = 3; ++ sclk_dly = 5; ++ } ++ } else { ++ /* rate > 50000000 */ ++ oclk_dly = 2; ++ sclk_dly = 4; ++ } ++ ++ src_clk = clk_get_rate(clk_get_parent(host->clk_mmc)); ++ if (src_clk >= 300000000 && src_clk <= 400000000) { ++ if (oclk_dly) ++ oclk_dly--; ++ if (sclk_dly) ++ sclk_dly--; ++ } ++ ++ clk_sunxi_mmc_phase_control(host->clk_mmc, sclk_dly, oclk_dly); ++ ++ return sunxi_mmc_oclk_onoff(host, 1); ++} ++ ++static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ u32 rval; ++ ++ /* Set the power state */ ++ switch (ios->power_mode) { ++ case MMC_POWER_ON: ++ break; ++ ++ case MMC_POWER_UP: ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); ++ ++ host->ferror = sunxi_mmc_init_host(mmc); ++ if (host->ferror) ++ return; ++ ++ dev_dbg(mmc_dev(mmc), "power on!\n"); ++ break; ++ ++ case MMC_POWER_OFF: ++ dev_dbg(mmc_dev(mmc), "power off!\n"); ++ sunxi_mmc_reset_host(host); ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); ++ break; ++ } ++ ++ /* set bus width */ ++ switch (ios->bus_width) { ++ case MMC_BUS_WIDTH_1: ++ mmc_writel(host, REG_WIDTH, SDXC_WIDTH1); ++ break; ++ case MMC_BUS_WIDTH_4: ++ mmc_writel(host, REG_WIDTH, SDXC_WIDTH4); ++ break; ++ case MMC_BUS_WIDTH_8: ++ mmc_writel(host, REG_WIDTH, SDXC_WIDTH8); ++ break; ++ } ++ ++ /* set ddr mode */ ++ rval = mmc_readl(host, REG_GCTRL); ++ if (ios->timing == MMC_TIMING_UHS_DDR50) ++ rval |= SDXC_DDR_MODE; ++ else ++ rval &= ~SDXC_DDR_MODE; ++ mmc_writel(host, REG_GCTRL, rval); ++ ++ /* set up clock */ ++ if (ios->clock && ios->power_mode) { ++ host->ferror = sunxi_mmc_clk_set_rate(host, ios); ++ /* Android code had a usleep_range(50000, 55000); here */ ++ } ++} ++ ++static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) ++{ ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ unsigned long flags; ++ u32 imask; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ imask = mmc_readl(host, REG_IMASK); ++ if (enable) { ++ host->sdio_imask = SDXC_SDIO_INTERRUPT; ++ imask |= SDXC_SDIO_INTERRUPT; ++ } else { ++ host->sdio_imask = 0; ++ imask &= ~SDXC_SDIO_INTERRUPT; ++ } ++ mmc_writel(host, REG_IMASK, imask); ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++static void sunxi_mmc_hw_reset(struct mmc_host *mmc) ++{ ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ mmc_writel(host, REG_HWRST, 0); ++ udelay(10); ++ mmc_writel(host, REG_HWRST, 1); ++ udelay(300); ++} ++ ++static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ struct mmc_command *cmd = mrq->cmd; ++ struct mmc_data *data = mrq->data; ++ unsigned long iflags; ++ u32 imask = SDXC_INTERRUPT_ERROR_BIT; ++ u32 cmd_val = SDXC_START | (cmd->opcode & 0x3f); ++ int ret; ++ ++ /* Check for set_ios errors (should never happen) */ ++ if (host->ferror) { ++ mrq->cmd->error = host->ferror; ++ mmc_request_done(mmc, mrq); ++ return; ++ } ++ ++ if (data) { ++ ret = sunxi_mmc_map_dma(host, data); ++ if (ret < 0) { ++ dev_err(mmc_dev(mmc), "map DMA failed\n"); ++ cmd->error = ret; ++ data->error = ret; ++ mmc_request_done(mmc, mrq); ++ return; ++ } ++ } ++ ++ if (cmd->opcode == MMC_GO_IDLE_STATE) { ++ cmd_val |= SDXC_SEND_INIT_SEQUENCE; ++ imask |= SDXC_COMMAND_DONE; ++ } ++ ++ if (cmd->flags & MMC_RSP_PRESENT) { ++ cmd_val |= SDXC_RESP_EXPIRE; ++ if (cmd->flags & MMC_RSP_136) ++ cmd_val |= SDXC_LONG_RESPONSE; ++ if (cmd->flags & MMC_RSP_CRC) ++ cmd_val |= SDXC_CHECK_RESPONSE_CRC; ++ ++ if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) { ++ cmd_val |= SDXC_DATA_EXPIRE | SDXC_WAIT_PRE_OVER; ++ if (cmd->data->flags & MMC_DATA_STREAM) { ++ imask |= SDXC_AUTO_COMMAND_DONE; ++ cmd_val |= SDXC_SEQUENCE_MODE | ++ SDXC_SEND_AUTO_STOP; ++ } ++ ++ if (cmd->data->stop) { ++ imask |= SDXC_AUTO_COMMAND_DONE; ++ cmd_val |= SDXC_SEND_AUTO_STOP; ++ } else { ++ imask |= SDXC_DATA_OVER; ++ } ++ ++ if (cmd->data->flags & MMC_DATA_WRITE) ++ cmd_val |= SDXC_WRITE; ++ else ++ host->wait_dma = true; ++ } else { ++ imask |= SDXC_COMMAND_DONE; ++ } ++ } else { ++ imask |= SDXC_COMMAND_DONE; ++ } ++ ++ dev_dbg(mmc_dev(mmc), "cmd %d(%08x) arg %x ie 0x%08x len %d\n", ++ cmd_val & 0x3f, cmd_val, cmd->arg, imask, ++ mrq->data ? mrq->data->blksz * mrq->data->blocks : 0); ++ ++ spin_lock_irqsave(&host->lock, iflags); ++ ++ if (host->mrq || host->manual_stop_mrq) { ++ spin_unlock_irqrestore(&host->lock, iflags); ++ ++ if (data) ++ dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, ++ sunxi_mmc_get_dma_dir(data)); ++ ++ dev_err(mmc_dev(mmc), "request already pending\n"); ++ mrq->cmd->error = -EBUSY; ++ mmc_request_done(mmc, mrq); ++ return; ++ } ++ ++ if (data) { ++ mmc_writel(host, REG_BLKSZ, data->blksz); ++ mmc_writel(host, REG_BCNTR, data->blksz * data->blocks); ++ sunxi_mmc_start_dma(host, data); ++ } ++ ++ host->mrq = mrq; ++ mmc_writel(host, REG_IMASK, host->sdio_imask | imask); ++ mmc_writel(host, REG_CARG, cmd->arg); ++ mmc_writel(host, REG_CMDR, cmd_val); ++ ++ spin_unlock_irqrestore(&host->lock, iflags); ++} ++ ++static const struct of_device_id sunxi_mmc_of_match[] = { ++ { .compatible = "allwinner,sun4i-a10-mmc", }, ++ { .compatible = "allwinner,sun5i-a13-mmc", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); ++ ++static struct mmc_host_ops sunxi_mmc_ops = { ++ .request = sunxi_mmc_request, ++ .set_ios = sunxi_mmc_set_ios, ++ .get_ro = mmc_gpio_get_ro, ++ .get_cd = mmc_gpio_get_cd, ++ .enable_sdio_irq = sunxi_mmc_enable_sdio_irq, ++ .hw_reset = sunxi_mmc_hw_reset, ++}; ++ ++static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, ++ struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ int ret; ++ ++ if (of_device_is_compatible(np, "allwinner,sun4i-a10-mmc")) ++ host->idma_des_size_bits = 13; ++ else ++ host->idma_des_size_bits = 16; ++ ++ ret = mmc_regulator_get_supply(host->mmc); ++ if (ret) { ++ if (ret != -EPROBE_DEFER) ++ dev_err(&pdev->dev, "Could not get vmmc supply\n"); ++ return ret; ++ } ++ ++ host->reg_base = devm_ioremap_resource(&pdev->dev, ++ platform_get_resource(pdev, IORESOURCE_MEM, 0)); ++ if (IS_ERR(host->reg_base)) ++ return PTR_ERR(host->reg_base); ++ ++ host->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); ++ if (IS_ERR(host->clk_ahb)) { ++ dev_err(&pdev->dev, "Could not get ahb clock\n"); ++ return PTR_ERR(host->clk_ahb); ++ } ++ ++ host->clk_mmc = devm_clk_get(&pdev->dev, "mmc"); ++ if (IS_ERR(host->clk_mmc)) { ++ dev_err(&pdev->dev, "Could not get mmc clock\n"); ++ return PTR_ERR(host->clk_mmc); ++ } ++ ++ host->reset = devm_reset_control_get(&pdev->dev, "ahb"); ++ ++ ret = clk_prepare_enable(host->clk_ahb); ++ if (ret) { ++ dev_err(&pdev->dev, "Enable ahb clk err %d\n", ret); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(host->clk_mmc); ++ if (ret) { ++ dev_err(&pdev->dev, "Enable mmc clk err %d\n", ret); ++ goto error_disable_clk_ahb; ++ } ++ ++ if (!IS_ERR(host->reset)) { ++ ret = reset_control_deassert(host->reset); ++ if (ret) { ++ dev_err(&pdev->dev, "reset err %d\n", ret); ++ goto error_disable_clk_mmc; ++ } ++ } ++ ++ /* ++ * Sometimes the controller asserts the irq on boot for some reason, ++ * make sure the controller is in a sane state before enabling irqs. ++ */ ++ ret = sunxi_mmc_reset_host(host); ++ if (ret) ++ goto error_assert_reset; ++ ++ host->irq = platform_get_irq(pdev, 0); ++ return devm_request_threaded_irq(&pdev->dev, host->irq, sunxi_mmc_irq, ++ sunxi_mmc_handle_manual_stop, 0, "sunxi-mmc", host); ++ ++error_assert_reset: ++ if (!IS_ERR(host->reset)) ++ reset_control_assert(host->reset); ++error_disable_clk_mmc: ++ clk_disable_unprepare(host->clk_mmc); ++error_disable_clk_ahb: ++ clk_disable_unprepare(host->clk_ahb); ++ return ret; ++} ++ ++static int sunxi_mmc_probe(struct platform_device *pdev) ++{ ++ struct sunxi_mmc_host *host; ++ struct mmc_host *mmc; ++ int ret; ++ ++ mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev); ++ if (!mmc) { ++ dev_err(&pdev->dev, "mmc alloc host failed\n"); ++ return -ENOMEM; ++ } ++ ++ host = mmc_priv(mmc); ++ host->mmc = mmc; ++ spin_lock_init(&host->lock); ++ ++ ret = sunxi_mmc_resource_request(host, pdev); ++ if (ret) ++ goto error_free_host; ++ ++ host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, ++ &host->sg_dma, GFP_KERNEL); ++ if (!host->sg_cpu) { ++ dev_err(&pdev->dev, "Failed to allocate DMA descriptor mem\n"); ++ ret = -ENOMEM; ++ goto error_free_host; ++ } ++ ++ mmc->ops = &sunxi_mmc_ops; ++ mmc->max_blk_count = 8192; ++ mmc->max_blk_size = 4096; ++ mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des); ++ mmc->max_seg_size = (1 << host->idma_des_size_bits); ++ mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; ++ /* 400kHz ~ 50MHz */ ++ mmc->f_min = 400000; ++ mmc->f_max = 50000000; ++ mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; ++ ++ ret = mmc_of_parse(mmc); ++ if (ret) ++ goto error_free_dma; ++ ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto error_free_dma; ++ ++ dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq); ++ platform_set_drvdata(pdev, mmc); ++ return 0; ++ ++error_free_dma: ++ dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); ++error_free_host: ++ mmc_free_host(mmc); ++ return ret; ++} ++ ++static int sunxi_mmc_remove(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ ++ mmc_remove_host(mmc); ++ disable_irq(host->irq); ++ sunxi_mmc_reset_host(host); ++ ++ if (!IS_ERR(host->reset)) ++ reset_control_assert(host->reset); ++ ++ clk_disable_unprepare(host->clk_mmc); ++ clk_disable_unprepare(host->clk_ahb); ++ ++ dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); ++ mmc_free_host(mmc); ++ ++ return 0; ++} ++ ++static struct platform_driver sunxi_mmc_driver = { ++ .driver = { ++ .name = "sunxi-mmc", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(sunxi_mmc_of_match), ++ }, ++ .probe = sunxi_mmc_probe, ++ .remove = sunxi_mmc_remove, ++}; ++module_platform_driver(sunxi_mmc_driver); ++ ++MODULE_DESCRIPTION("Allwinner's SD/MMC Card Controller Driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("David Lanzend�rfer "); ++MODULE_ALIAS("platform:sunxi-mmc"); +diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c +index f70d046..d1760eb 100644 +--- a/drivers/mmc/host/tifm_sd.c ++++ b/drivers/mmc/host/tifm_sd.c +@@ -22,8 +22,8 @@ + #define DRIVER_NAME "tifm_sd" + #define DRIVER_VERSION "0.8" + +-static int no_dma = 0; +-static int fixed_timeout = 0; ++static bool no_dma = 0; ++static bool fixed_timeout = 0; + module_param(no_dma, bool, 0644); + module_param(fixed_timeout, bool, 0644); + +@@ -118,7 +118,7 @@ static void tifm_sd_read_fifo(struct tifm_sd *host, struct page *pg, + unsigned char *buf; + unsigned int pos = 0, val; + +- buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + off; ++ buf = kmap_atomic(pg) + off; + if (host->cmd_flags & DATA_CARRY) { + buf[pos++] = host->bounce_buf_data[0]; + host->cmd_flags &= ~DATA_CARRY; +@@ -134,7 +134,7 @@ static void tifm_sd_read_fifo(struct tifm_sd *host, struct page *pg, + } + buf[pos++] = (val >> 8) & 0xff; + } +- kunmap_atomic(buf - off, KM_BIO_DST_IRQ); ++ kunmap_atomic(buf - off); + } + + static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg, +@@ -144,7 +144,7 @@ static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg, + unsigned char *buf; + unsigned int pos = 0, val; + +- buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + off; ++ buf = kmap_atomic(pg) + off; + if (host->cmd_flags & DATA_CARRY) { + val = host->bounce_buf_data[0] | ((buf[pos++] << 8) & 0xff00); + writel(val, sock->addr + SOCK_MMCSD_DATA); +@@ -161,7 +161,7 @@ static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg, + val |= (buf[pos++] << 8) & 0xff00; + writel(val, sock->addr + SOCK_MMCSD_DATA); + } +- kunmap_atomic(buf - off, KM_BIO_SRC_IRQ); ++ kunmap_atomic(buf - off); + } + + static void tifm_sd_transfer_data(struct tifm_sd *host) +@@ -212,13 +212,13 @@ static void tifm_sd_copy_page(struct page *dst, unsigned int dst_off, + struct page *src, unsigned int src_off, + unsigned int count) + { +- unsigned char *src_buf = kmap_atomic(src, KM_BIO_SRC_IRQ) + src_off; +- unsigned char *dst_buf = kmap_atomic(dst, KM_BIO_DST_IRQ) + dst_off; ++ unsigned char *src_buf = kmap_atomic(src) + src_off; ++ unsigned char *dst_buf = kmap_atomic(dst) + dst_off; + + memcpy(dst_buf, src_buf, count); + +- kunmap_atomic(dst_buf - dst_off, KM_BIO_DST_IRQ); +- kunmap_atomic(src_buf - src_off, KM_BIO_SRC_IRQ); ++ kunmap_atomic(dst_buf - dst_off); ++ kunmap_atomic(src_buf - src_off); + } + + static void tifm_sd_bounce_block(struct tifm_sd *host, struct mmc_data *r_data) +@@ -1030,7 +1030,7 @@ static void tifm_sd_remove(struct tifm_dev *sock) + + static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) + { +- return mmc_suspend_host(tifm_get_drvdata(sock)); ++ return 0; + } + + static int tifm_sd_resume(struct tifm_dev *sock) +@@ -1044,8 +1044,6 @@ static int tifm_sd_resume(struct tifm_dev *sock) + + if (rc) + host->eject = 1; +- else +- rc = mmc_resume_host(mmc); + + return rc; + } +diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c +index a4ea102..cfad844 100644 +--- a/drivers/mmc/host/tmio_mmc.c ++++ b/drivers/mmc/host/tmio_mmc.c +@@ -23,45 +23,45 @@ + + #include "tmio_mmc.h" + +-#ifdef CONFIG_PM +-static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) ++#ifdef CONFIG_PM_SLEEP ++static int tmio_mmc_suspend(struct device *dev) + { +- const struct mfd_cell *cell = mfd_get_cell(dev); ++ struct platform_device *pdev = to_platform_device(dev); ++ const struct mfd_cell *cell = mfd_get_cell(pdev); + int ret; + +- ret = tmio_mmc_host_suspend(&dev->dev); ++ ret = tmio_mmc_host_suspend(dev); + + /* Tell MFD core it can disable us now.*/ + if (!ret && cell->disable) +- cell->disable(dev); ++ cell->disable(pdev); + + return ret; + } + +-static int tmio_mmc_resume(struct platform_device *dev) ++static int tmio_mmc_resume(struct device *dev) + { +- const struct mfd_cell *cell = mfd_get_cell(dev); ++ struct platform_device *pdev = to_platform_device(dev); ++ const struct mfd_cell *cell = mfd_get_cell(pdev); + int ret = 0; + + /* Tell the MFD core we are ready to be enabled */ + if (cell->resume) +- ret = cell->resume(dev); ++ ret = cell->resume(pdev); + + if (!ret) +- ret = tmio_mmc_host_resume(&dev->dev); ++ ret = tmio_mmc_host_resume(dev); + + return ret; + } +-#else +-#define tmio_mmc_suspend NULL +-#define tmio_mmc_resume NULL + #endif + +-static int __devinit tmio_mmc_probe(struct platform_device *pdev) ++static int tmio_mmc_probe(struct platform_device *pdev) + { + const struct mfd_cell *cell = mfd_get_cell(pdev); + struct tmio_mmc_data *pdata; + struct tmio_mmc_host *host; ++ struct resource *res; + int ret = -EINVAL, irq; + + if (pdev->num_resources != 2) +@@ -84,6 +84,14 @@ static int __devinit tmio_mmc_probe(struct platform_device *pdev) + goto out; + } + ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -EINVAL; ++ ++ /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ ++ pdata->bus_shift = resource_size(res) >> 10; ++ pdata->flags |= TMIO_MMC_HAVE_HIGH_REG; ++ + ret = tmio_mmc_host_probe(&host, pdev, pdata); + if (ret) + goto cell_disable; +@@ -107,13 +115,11 @@ out: + return ret; + } + +-static int __devexit tmio_mmc_remove(struct platform_device *pdev) ++static int tmio_mmc_remove(struct platform_device *pdev) + { + const struct mfd_cell *cell = mfd_get_cell(pdev); + struct mmc_host *mmc = platform_get_drvdata(pdev); + +- platform_set_drvdata(pdev, NULL); +- + if (mmc) { + struct tmio_mmc_host *host = mmc_priv(mmc); + free_irq(platform_get_irq(pdev, 0), host); +@@ -127,30 +133,21 @@ static int __devexit tmio_mmc_remove(struct platform_device *pdev) + + /* ------------------- device registration ----------------------- */ + ++static const struct dev_pm_ops tmio_mmc_dev_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(tmio_mmc_suspend, tmio_mmc_resume) ++}; ++ + static struct platform_driver tmio_mmc_driver = { + .driver = { + .name = "tmio-mmc", + .owner = THIS_MODULE, ++ .pm = &tmio_mmc_dev_pm_ops, + }, + .probe = tmio_mmc_probe, +- .remove = __devexit_p(tmio_mmc_remove), +- .suspend = tmio_mmc_suspend, +- .resume = tmio_mmc_resume, ++ .remove = tmio_mmc_remove, + }; + +- +-static int __init tmio_mmc_init(void) +-{ +- return platform_driver_register(&tmio_mmc_driver); +-} +- +-static void __exit tmio_mmc_exit(void) +-{ +- platform_driver_unregister(&tmio_mmc_driver); +-} +- +-module_init(tmio_mmc_init); +-module_exit(tmio_mmc_exit); ++module_platform_driver(tmio_mmc_driver); + + MODULE_DESCRIPTION("Toshiba TMIO SD/MMC driver"); + MODULE_AUTHOR("Ian Molton "); +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index 3020f98..100ffe0 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -20,8 +20,8 @@ + #include + #include + #include +-#include + #include ++#include + + /* Definitions for values the CTRL_SDIO_STATUS register can take. */ + #define TMIO_SDIO_STAT_IOIRQ 0x0001 +@@ -40,23 +40,36 @@ + + struct tmio_mmc_data; + ++/* ++ * We differentiate between the following 3 power states: ++ * 1. card slot powered off, controller stopped. This is used, when either there ++ * is no card in the slot, or the card really has to be powered down. ++ * 2. card slot powered on, controller stopped. This is used, when a card is in ++ * the slot, but no activity is currently taking place. This is a power- ++ * saving mode with card-state preserved. This state can be entered, e.g. ++ * when MMC clock-gating is used. ++ * 3. card slot powered on, controller running. This is the actual active state. ++ */ ++enum tmio_mmc_power { ++ TMIO_MMC_OFF_STOP, /* card power off, controller stopped */ ++ TMIO_MMC_ON_STOP, /* card power on, controller stopped */ ++ TMIO_MMC_ON_RUN, /* card power on, controller running */ ++}; ++ + struct tmio_mmc_host { + void __iomem *ctl; +- unsigned long bus_shift; + struct mmc_command *cmd; + struct mmc_request *mrq; + struct mmc_data *data; + struct mmc_host *mmc; +- unsigned int sdio_irq_enabled; ++ ++ /* Controller and card power state */ ++ enum tmio_mmc_power power; + + /* Callbacks for clock / power control */ + void (*set_pwr)(struct platform_device *host, int state); + void (*set_clk_div)(struct platform_device *host, int state); + +- int pm_error; +- /* recognise system-wide suspend in runtime PM methods */ +- bool pm_global; +- + /* pio related stuff */ + struct scatterlist *sg_ptr; + struct scatterlist *sg_orig; +@@ -86,6 +99,8 @@ struct tmio_mmc_host { + spinlock_t lock; /* protect host private data */ + unsigned long last_req_ts; + struct mutex ios_lock; /* protect set_ios() context */ ++ bool native_hotplug; ++ bool resuming; + }; + + int tmio_mmc_host_probe(struct tmio_mmc_host **host, +@@ -105,13 +120,13 @@ static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, + unsigned long *flags) + { + local_irq_save(*flags); +- return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; ++ return kmap_atomic(sg_page(sg)) + sg->offset; + } + + static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg, + unsigned long *flags, void *virt) + { +- kunmap_atomic(virt - sg->offset, KM_BIO_SRC_IRQ); ++ kunmap_atomic(virt - sg->offset); + local_irq_restore(*flags); + } + +@@ -120,6 +135,7 @@ void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data); + void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable); + void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); + void tmio_mmc_release_dma(struct tmio_mmc_host *host); ++void tmio_mmc_abort_dma(struct tmio_mmc_host *host); + #else + static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host, + struct mmc_data *data) +@@ -140,34 +156,37 @@ static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host, + static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host) + { + } ++ ++static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host) ++{ ++} + #endif + +-#ifdef CONFIG_PM ++#ifdef CONFIG_PM_SLEEP + int tmio_mmc_host_suspend(struct device *dev); + int tmio_mmc_host_resume(struct device *dev); +-#else +-#define tmio_mmc_host_suspend NULL +-#define tmio_mmc_host_resume NULL + #endif + ++#ifdef CONFIG_PM_RUNTIME + int tmio_mmc_host_runtime_suspend(struct device *dev); + int tmio_mmc_host_runtime_resume(struct device *dev); ++#endif + + static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) + { +- return readw(host->ctl + (addr << host->bus_shift)); ++ return readw(host->ctl + (addr << host->pdata->bus_shift)); + } + + static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr, + u16 *buf, int count) + { +- readsw(host->ctl + (addr << host->bus_shift), buf, count); ++ readsw(host->ctl + (addr << host->pdata->bus_shift), buf, count); + } + + static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) + { +- return readw(host->ctl + (addr << host->bus_shift)) | +- readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16; ++ return readw(host->ctl + (addr << host->pdata->bus_shift)) | ++ readw(host->ctl + ((addr + 2) << host->pdata->bus_shift)) << 16; + } + + static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val) +@@ -177,19 +196,19 @@ static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val + */ + if (host->pdata->write16_hook && host->pdata->write16_hook(host, addr)) + return; +- writew(val, host->ctl + (addr << host->bus_shift)); ++ writew(val, host->ctl + (addr << host->pdata->bus_shift)); + } + + static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr, + u16 *buf, int count) + { +- writesw(host->ctl + (addr << host->bus_shift), buf, count); ++ writesw(host->ctl + (addr << host->pdata->bus_shift), buf, count); + } + + static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val) + { +- writew(val, host->ctl + (addr << host->bus_shift)); +- writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); ++ writew(val, host->ctl + (addr << host->pdata->bus_shift)); ++ writew(val >> 16, host->ctl + ((addr + 2) << host->pdata->bus_shift)); + } + + +diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c +index be9e74d..03e7b28 100644 +--- a/drivers/mmc/host/tmio_mmc_dma.c ++++ b/drivers/mmc/host/tmio_mmc_dma.c +@@ -34,6 +34,18 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) + #endif + } + ++void tmio_mmc_abort_dma(struct tmio_mmc_host *host) ++{ ++ tmio_mmc_enable_dma(host, false); ++ ++ if (host->chan_rx) ++ dmaengine_terminate_all(host->chan_rx); ++ if (host->chan_tx) ++ dmaengine_terminate_all(host->chan_tx); ++ ++ tmio_mmc_enable_dma(host, true); ++} ++ + static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) + { + struct scatterlist *sg = host->sg_ptr, *sg_tmp; +@@ -76,8 +88,8 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) + + ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE); + if (ret > 0) +- desc = chan->device->device_prep_slave_sg(chan, sg, ret, +- DMA_FROM_DEVICE, DMA_CTRL_ACK); ++ desc = dmaengine_prep_slave_sg(chan, sg, ret, ++ DMA_DEV_TO_MEM, DMA_CTRL_ACK); + + if (desc) { + cookie = dmaengine_submit(desc); +@@ -157,8 +169,8 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) + + ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE); + if (ret > 0) +- desc = chan->device->device_prep_slave_sg(chan, sg, ret, +- DMA_TO_DEVICE, DMA_CTRL_ACK); ++ desc = dmaengine_prep_slave_sg(chan, sg, ret, ++ DMA_MEM_TO_DEV, DMA_CTRL_ACK); + + if (desc) { + cookie = dmaengine_submit(desc); +@@ -249,42 +261,62 @@ out: + spin_unlock_irq(&host->lock); + } + +-/* It might be necessary to make filter MFD specific */ +-static bool tmio_mmc_filter(struct dma_chan *chan, void *arg) +-{ +- dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg); +- chan->private = arg; +- return true; +-} +- + void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata) + { + /* We can only either use DMA for both Tx and Rx or not use it at all */ +- if (!pdata->dma) ++ if (!pdata->dma || (!host->pdev->dev.of_node && ++ (!pdata->dma->chan_priv_tx || !pdata->dma->chan_priv_rx))) + return; + + if (!host->chan_tx && !host->chan_rx) { ++ struct resource *res = platform_get_resource(host->pdev, ++ IORESOURCE_MEM, 0); ++ struct dma_slave_config cfg = {}; + dma_cap_mask_t mask; ++ int ret; ++ ++ if (!res) ++ return; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + +- host->chan_tx = dma_request_channel(mask, tmio_mmc_filter, +- pdata->dma->chan_priv_tx); ++ host->chan_tx = dma_request_slave_channel_compat(mask, ++ pdata->dma->filter, pdata->dma->chan_priv_tx, ++ &host->pdev->dev, "tx"); + dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__, + host->chan_tx); + + if (!host->chan_tx) + return; + +- host->chan_rx = dma_request_channel(mask, tmio_mmc_filter, +- pdata->dma->chan_priv_rx); ++ if (pdata->dma->chan_priv_tx) ++ cfg.slave_id = pdata->dma->slave_id_tx; ++ cfg.direction = DMA_MEM_TO_DEV; ++ cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->pdata->bus_shift); ++ cfg.src_addr = 0; ++ ret = dmaengine_slave_config(host->chan_tx, &cfg); ++ if (ret < 0) ++ goto ecfgtx; ++ ++ host->chan_rx = dma_request_slave_channel_compat(mask, ++ pdata->dma->filter, pdata->dma->chan_priv_rx, ++ &host->pdev->dev, "rx"); + dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__, + host->chan_rx); + + if (!host->chan_rx) + goto ereqrx; + ++ if (pdata->dma->chan_priv_rx) ++ cfg.slave_id = pdata->dma->slave_id_rx; ++ cfg.direction = DMA_DEV_TO_MEM; ++ cfg.src_addr = cfg.dst_addr; ++ cfg.dst_addr = 0; ++ ret = dmaengine_slave_config(host->chan_rx, &cfg); ++ if (ret < 0) ++ goto ecfgrx; ++ + host->bounce_buf = (u8 *)__get_free_page(GFP_KERNEL | GFP_DMA); + if (!host->bounce_buf) + goto ebouncebuf; +@@ -298,9 +330,11 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat + return; + + ebouncebuf: ++ecfgrx: + dma_release_channel(host->chan_rx); + host->chan_rx = NULL; + ereqrx: ++ecfgtx: + dma_release_channel(host->chan_tx); + host->chan_tx = NULL; + } +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 4208b39..faf0924 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -35,14 +35,18 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include + #include ++#include + #include ++#include + #include +-#include + #include ++#include + + #include "tmio_mmc.h" + +@@ -126,7 +130,6 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) + struct tmio_mmc_host *host = mmc_priv(mmc); + + if (enable) { +- host->sdio_irq_enabled = 1; + host->sdio_irq_mask = TMIO_SDIO_MASK_ALL & + ~TMIO_SDIO_STAT_IOIRQ; + sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001); +@@ -135,7 +138,6 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) + host->sdio_irq_mask = TMIO_SDIO_MASK_ALL; + sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask); + sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000); +- host->sdio_irq_enabled = 0; + } + } + +@@ -154,14 +156,13 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) + host->set_clk_div(host->pdev, (clk>>22) & 1); + + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff); ++ msleep(10); + } + + static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) + { +- struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); +- + /* implicit BUG_ON(!res) */ +- if (resource_size(res) > 0x100) { ++ if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) { + sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000); + msleep(10); + } +@@ -173,14 +174,12 @@ static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) + + static void tmio_mmc_clk_start(struct tmio_mmc_host *host) + { +- struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); +- + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 | + sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); + msleep(10); + + /* implicit BUG_ON(!res) */ +- if (resource_size(res) > 0x100) { ++ if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) { + sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100); + msleep(10); + } +@@ -188,16 +187,14 @@ static void tmio_mmc_clk_start(struct tmio_mmc_host *host) + + static void tmio_mmc_reset(struct tmio_mmc_host *host) + { +- struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); +- + /* FIXME - should we set stop clock reg here */ + sd_ctrl_write16(host, CTL_RESET_SD, 0x0000); + /* implicit BUG_ON(!res) */ +- if (resource_size(res) > 0x100) ++ if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) + sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000); + msleep(10); + sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); +- if (resource_size(res) > 0x100) ++ if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) + sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001); + msleep(10); + } +@@ -246,6 +243,7 @@ static void tmio_mmc_reset_work(struct work_struct *work) + /* Ready for new calls */ + host->mrq = NULL; + ++ tmio_mmc_abort_dma(host); + mmc_request_done(host->mmc, mrq); + } + +@@ -272,6 +270,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host) + host->mrq = NULL; + spin_unlock_irqrestore(&host->lock, flags); + ++ if (mrq->cmd->error || (mrq->data && mrq->data->error)) ++ tmio_mmc_abort_dma(host); ++ + mmc_request_done(host->mmc, mrq); + } + +@@ -299,9 +300,10 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command + { + struct mmc_data *data = host->data; + int c = cmd->opcode; ++ u32 irq_mask = TMIO_MASK_CMD; + +- /* Command 12 is handled by hardware */ +- if (cmd->opcode == 12 && !cmd->arg) { ++ /* CMD12 is handled by hardware */ ++ if (cmd->opcode == MMC_STOP_TRANSMISSION && !cmd->arg) { + sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001); + return 0; + } +@@ -334,7 +336,9 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command + c |= TRANSFER_READ; + } + +- tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_CMD); ++ if (!host->native_hotplug) ++ irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); ++ tmio_mmc_enable_mmc_irqs(host, irq_mask); + + /* Fire off the command */ + sd_ctrl_write32(host, CTL_ARG_REG, cmd->arg); +@@ -442,7 +446,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host) + } + + if (stop) { +- if (stop->opcode == 12 && !stop->arg) ++ if (stop->opcode == MMC_STOP_TRANSMISSION && !stop->arg) + sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000); + else + BUG(); +@@ -744,6 +748,70 @@ fail: + mmc_request_done(mmc, mrq); + } + ++static int tmio_mmc_clk_update(struct mmc_host *mmc) ++{ ++ struct tmio_mmc_host *host = mmc_priv(mmc); ++ struct tmio_mmc_data *pdata = host->pdata; ++ int ret; ++ ++ if (!pdata->clk_enable) ++ return -ENOTSUPP; ++ ++ ret = pdata->clk_enable(host->pdev, &mmc->f_max); ++ if (!ret) ++ mmc->f_min = mmc->f_max / 512; ++ ++ return ret; ++} ++ ++static void tmio_mmc_power_on(struct tmio_mmc_host *host, unsigned short vdd) ++{ ++ struct mmc_host *mmc = host->mmc; ++ int ret = 0; ++ ++ /* .set_ios() is returning void, so, no chance to report an error */ ++ ++ if (host->set_pwr) ++ host->set_pwr(host->pdev, 1); ++ ++ if (!IS_ERR(mmc->supply.vmmc)) { ++ ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); ++ /* ++ * Attention: empiric value. With a b43 WiFi SDIO card this ++ * delay proved necessary for reliable card-insertion probing. ++ * 100us were not enough. Is this the same 140us delay, as in ++ * tmio_mmc_set_ios()? ++ */ ++ udelay(200); ++ } ++ /* ++ * It seems, VccQ should be switched on after Vcc, this is also what the ++ * omap_hsmmc.c driver does. ++ */ ++ if (!IS_ERR(mmc->supply.vqmmc) && !ret) { ++ ret = regulator_enable(mmc->supply.vqmmc); ++ udelay(200); ++ } ++ ++ if (ret < 0) ++ dev_dbg(&host->pdev->dev, "Regulators failed to power up: %d\n", ++ ret); ++} ++ ++static void tmio_mmc_power_off(struct tmio_mmc_host *host) ++{ ++ struct mmc_host *mmc = host->mmc; ++ ++ if (!IS_ERR(mmc->supply.vqmmc)) ++ regulator_disable(mmc->supply.vqmmc); ++ ++ if (!IS_ERR(mmc->supply.vmmc)) ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); ++ ++ if (host->set_pwr) ++ host->set_pwr(host->pdev, 0); ++} ++ + /* Set MMC clock / power. + * Note: This controller uses a simple divider scheme therefore it cannot + * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as +@@ -753,7 +821,7 @@ fail: + static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct tmio_mmc_host *host = mmc_priv(mmc); +- struct tmio_mmc_data *pdata = host->pdata; ++ struct device *dev = &host->pdev->dev; + unsigned long flags; + + mutex_lock(&host->ios_lock); +@@ -761,13 +829,13 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + spin_lock_irqsave(&host->lock, flags); + if (host->mrq) { + if (IS_ERR(host->mrq)) { +- dev_dbg(&host->pdev->dev, ++ dev_dbg(dev, + "%s.%d: concurrent .set_ios(), clk %u, mode %u\n", + current->comm, task_pid_nr(current), + ios->clock, ios->power_mode); + host->mrq = ERR_PTR(-EINTR); + } else { +- dev_dbg(&host->pdev->dev, ++ dev_dbg(dev, + "%s.%d: CMD%u active since %lu, now %lu!\n", + current->comm, task_pid_nr(current), + host->mrq->cmd->opcode, host->last_req_ts, jiffies); +@@ -783,38 +851,59 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + spin_unlock_irqrestore(&host->lock, flags); + + /* +- * pdata->power == false only if COLD_CD is available, otherwise only +- * in short time intervals during probing or resuming ++ * host->power toggles between false and true in both cases - either ++ * or not the controller can be runtime-suspended during inactivity. ++ * But if the controller has to be kept on, the runtime-pm usage_count ++ * is kept positive, so no suspending actually takes place. + */ + if (ios->power_mode == MMC_POWER_ON && ios->clock) { +- if (!pdata->power) { +- pm_runtime_get_sync(&host->pdev->dev); +- pdata->power = true; ++ if (host->power != TMIO_MMC_ON_RUN) { ++ tmio_mmc_clk_update(mmc); ++ pm_runtime_get_sync(dev); ++ if (host->resuming) { ++ tmio_mmc_reset(host); ++ host->resuming = false; ++ } + } ++ if (host->power == TMIO_MMC_OFF_STOP) ++ tmio_mmc_reset(host); + tmio_mmc_set_clock(host, ios->clock); +- /* power up SD bus */ +- if (host->set_pwr) +- host->set_pwr(host->pdev, 1); ++ if (host->power == TMIO_MMC_OFF_STOP) ++ /* power up SD card and the bus */ ++ tmio_mmc_power_on(host, ios->vdd); ++ host->power = TMIO_MMC_ON_RUN; + /* start bus clock */ + tmio_mmc_clk_start(host); + } else if (ios->power_mode != MMC_POWER_UP) { +- if (host->set_pwr && ios->power_mode == MMC_POWER_OFF) +- host->set_pwr(host->pdev, 0); +- if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && +- pdata->power) { +- pdata->power = false; +- pm_runtime_put(&host->pdev->dev); ++ struct tmio_mmc_data *pdata = host->pdata; ++ unsigned int old_power = host->power; ++ ++ if (old_power != TMIO_MMC_OFF_STOP) { ++ if (ios->power_mode == MMC_POWER_OFF) { ++ tmio_mmc_power_off(host); ++ host->power = TMIO_MMC_OFF_STOP; ++ } else { ++ host->power = TMIO_MMC_ON_STOP; ++ } ++ } ++ ++ if (old_power == TMIO_MMC_ON_RUN) { ++ tmio_mmc_clk_stop(host); ++ pm_runtime_put(dev); ++ if (pdata->clk_disable) ++ pdata->clk_disable(host->pdev); + } +- tmio_mmc_clk_stop(host); + } + +- switch (ios->bus_width) { +- case MMC_BUS_WIDTH_1: +- sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0); +- break; +- case MMC_BUS_WIDTH_4: +- sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0); +- break; ++ if (host->power != TMIO_MMC_OFF_STOP) { ++ switch (ios->bus_width) { ++ case MMC_BUS_WIDTH_1: ++ sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0); ++ break; ++ case MMC_BUS_WIDTH_4: ++ sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0); ++ break; ++ } + } + + /* Let things settle. delay taken from winCE driver */ +@@ -833,31 +922,55 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc) + { + struct tmio_mmc_host *host = mmc_priv(mmc); + struct tmio_mmc_data *pdata = host->pdata; ++ int ret = mmc_gpio_get_ro(mmc); ++ if (ret >= 0) ++ return ret; + + return !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) || + (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)); + } + +-static int tmio_mmc_get_cd(struct mmc_host *mmc) +-{ +- struct tmio_mmc_host *host = mmc_priv(mmc); +- struct tmio_mmc_data *pdata = host->pdata; +- +- if (!pdata->get_cd) +- return -ENOSYS; +- else +- return pdata->get_cd(host->pdev); +-} +- + static const struct mmc_host_ops tmio_mmc_ops = { + .request = tmio_mmc_request, + .set_ios = tmio_mmc_set_ios, + .get_ro = tmio_mmc_get_ro, +- .get_cd = tmio_mmc_get_cd, ++ .get_cd = mmc_gpio_get_cd, + .enable_sdio_irq = tmio_mmc_enable_sdio_irq, + }; + +-int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, ++static int tmio_mmc_init_ocr(struct tmio_mmc_host *host) ++{ ++ struct tmio_mmc_data *pdata = host->pdata; ++ struct mmc_host *mmc = host->mmc; ++ ++ mmc_regulator_get_supply(mmc); ++ ++ /* use ocr_mask if no regulator */ ++ if (!mmc->ocr_avail) ++ mmc->ocr_avail = pdata->ocr_mask; ++ ++ /* ++ * try again. ++ * There is possibility that regulator has not been probed ++ */ ++ if (!mmc->ocr_avail) ++ return -EPROBE_DEFER; ++ ++ return 0; ++} ++ ++static void tmio_mmc_of_parse(struct platform_device *pdev, ++ struct tmio_mmc_data *pdata) ++{ ++ const struct device_node *np = pdev->dev.of_node; ++ if (!np) ++ return; ++ ++ if (of_get_property(np, "toshiba,mmc-wrprotect-disable", NULL)) ++ pdata->flags |= TMIO_MMC_WRPROTECT_DISABLE; ++} ++ ++int tmio_mmc_host_probe(struct tmio_mmc_host **host, + struct platform_device *pdev, + struct tmio_mmc_data *pdata) + { +@@ -867,6 +980,11 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + int ret; + u32 irq_mask = TMIO_MASK_CMD; + ++ tmio_mmc_of_parse(pdev, pdata); ++ ++ if (!(pdata->flags & TMIO_MMC_HAS_IDLE_WAIT)) ++ pdata->write16_hook = NULL; ++ + res_ctl = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res_ctl) + return -EINVAL; +@@ -875,6 +993,10 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + if (!mmc) + return -ENOMEM; + ++ ret = mmc_of_parse(mmc); ++ if (ret < 0) ++ goto host_free; ++ + pdata->dev = &pdev->dev; + _host = mmc_priv(mmc); + _host->pdata = pdata; +@@ -885,8 +1007,9 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + _host->set_pwr = pdata->set_pwr; + _host->set_clk_div = pdata->set_clk_div; + +- /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ +- _host->bus_shift = resource_size(res_ctl) >> 10; ++ ret = tmio_mmc_init_ocr(_host); ++ if (ret < 0) ++ goto host_free; + + _host->ctl = ioremap(res_ctl->start, resource_size(res_ctl)); + if (!_host->ctl) { +@@ -895,31 +1018,62 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + } + + mmc->ops = &tmio_mmc_ops; +- mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities; +- mmc->f_max = pdata->hclk; +- mmc->f_min = mmc->f_max / 512; ++ mmc->caps |= MMC_CAP_4_BIT_DATA | pdata->capabilities; ++ mmc->caps2 |= pdata->capabilities2; + mmc->max_segs = 32; + mmc->max_blk_size = 512; + mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) * + mmc->max_segs; + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + mmc->max_seg_size = mmc->max_req_size; +- if (pdata->ocr_mask) +- mmc->ocr_avail = pdata->ocr_mask; +- else +- mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + +- pdata->power = false; ++ _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD || ++ mmc->caps & MMC_CAP_NEEDS_POLL || ++ mmc->caps & MMC_CAP_NONREMOVABLE || ++ mmc->slot.cd_irq >= 0); ++ ++ _host->power = TMIO_MMC_OFF_STOP; + pm_runtime_enable(&pdev->dev); + ret = pm_runtime_resume(&pdev->dev); + if (ret < 0) + goto pm_disable; + ++ if (tmio_mmc_clk_update(mmc) < 0) { ++ mmc->f_max = pdata->hclk; ++ mmc->f_min = mmc->f_max / 512; ++ } ++ ++ /* ++ * There are 4 different scenarios for the card detection: ++ * 1) an external gpio irq handles the cd (best for power savings) ++ * 2) internal sdhi irq handles the cd ++ * 3) a worker thread polls the sdhi - indicated by MMC_CAP_NEEDS_POLL ++ * 4) the medium is non-removable - indicated by MMC_CAP_NONREMOVABLE ++ * ++ * While we increment the runtime PM counter for all scenarios when ++ * the mmc core activates us by calling an appropriate set_ios(), we ++ * must additionally ensure that in case 2) the tmio mmc hardware stays ++ * powered on during runtime for the card detection to work. ++ */ ++ if (_host->native_hotplug) ++ pm_runtime_get_noresume(&pdev->dev); ++ + tmio_mmc_clk_stop(_host); + tmio_mmc_reset(_host); + + _host->sdcard_irq_mask = sd_ctrl_read32(_host, CTL_IRQ_MASK); + tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); ++ ++ /* Unmask the IRQs we want to know about */ ++ if (!_host->chan_rx) ++ irq_mask |= TMIO_MASK_READOP; ++ if (!_host->chan_tx) ++ irq_mask |= TMIO_MASK_WRITEOP; ++ if (!_host->native_hotplug) ++ irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); ++ ++ _host->sdcard_irq_mask &= ~irq_mask; ++ + if (pdata->flags & TMIO_MMC_SDIO_IRQ) + tmio_mmc_enable_sdio_irq(mmc, 0); + +@@ -933,21 +1087,23 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + /* See if we also get DMA */ + tmio_mmc_request_dma(_host, pdata); + +- /* We have to keep the device powered for its card detection to work */ +- if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD)) { +- pdata->power = true; +- pm_runtime_get_noresume(&pdev->dev); ++ ret = mmc_add_host(mmc); ++ if (pdata->clk_disable) ++ pdata->clk_disable(pdev); ++ if (ret < 0) { ++ tmio_mmc_host_remove(_host); ++ return ret; + } + +- mmc_add_host(mmc); +- +- /* Unmask the IRQs we want to know about */ +- if (!_host->chan_rx) +- irq_mask |= TMIO_MASK_READOP; +- if (!_host->chan_tx) +- irq_mask |= TMIO_MASK_WRITEOP; ++ dev_pm_qos_expose_latency_limit(&pdev->dev, 100); + +- tmio_mmc_enable_mmc_irqs(_host, irq_mask); ++ if (pdata->flags & TMIO_MMC_USE_GPIO_CD) { ++ ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio, 0); ++ if (ret < 0) { ++ tmio_mmc_host_remove(_host); ++ return ret; ++ } ++ } + + *host = _host; + +@@ -966,18 +1122,14 @@ EXPORT_SYMBOL(tmio_mmc_host_probe); + void tmio_mmc_host_remove(struct tmio_mmc_host *host) + { + struct platform_device *pdev = host->pdev; ++ struct mmc_host *mmc = host->mmc; + +- /* +- * We don't have to manipulate pdata->power here: if there is a card in +- * the slot, the runtime PM is active and our .runtime_resume() will not +- * be run. If there is no card in the slot and the platform can suspend +- * the controller, the runtime PM is suspended and pdata->power == false, +- * so, our .runtime_resume() will not try to detect a card in the slot. +- */ +- if (host->pdata->flags & TMIO_MMC_HAS_COLD_CD) ++ if (!host->native_hotplug) + pm_runtime_get_sync(&pdev->dev); + +- mmc_remove_host(host->mmc); ++ dev_pm_qos_hide_latency_limit(&pdev->dev); ++ ++ mmc_remove_host(mmc); + cancel_work_sync(&host->done); + cancel_delayed_work_sync(&host->delayed_reset_work); + tmio_mmc_release_dma(host); +@@ -986,23 +1138,18 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) + pm_runtime_disable(&pdev->dev); + + iounmap(host->ctl); +- mmc_free_host(host->mmc); ++ mmc_free_host(mmc); + } + EXPORT_SYMBOL(tmio_mmc_host_remove); + +-#ifdef CONFIG_PM ++#ifdef CONFIG_PM_SLEEP + int tmio_mmc_host_suspend(struct device *dev) + { + struct mmc_host *mmc = dev_get_drvdata(dev); + struct tmio_mmc_host *host = mmc_priv(mmc); +- int ret = mmc_suspend_host(mmc); + +- if (!ret) +- tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL); +- +- host->pm_error = pm_runtime_put_sync(dev); +- +- return ret; ++ tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL); ++ return 0; + } + EXPORT_SYMBOL(tmio_mmc_host_suspend); + +@@ -1011,26 +1158,16 @@ int tmio_mmc_host_resume(struct device *dev) + struct mmc_host *mmc = dev_get_drvdata(dev); + struct tmio_mmc_host *host = mmc_priv(mmc); + +- /* The MMC core will perform the complete set up */ +- host->pdata->power = false; +- +- host->pm_global = true; +- if (!host->pm_error) +- pm_runtime_get_sync(dev); +- +- if (host->pm_global) { +- /* Runtime PM resume callback didn't run */ +- tmio_mmc_reset(host); +- tmio_mmc_enable_dma(host, true); +- host->pm_global = false; +- } ++ tmio_mmc_enable_dma(host, true); + +- return mmc_resume_host(mmc); ++ /* The MMC core will perform the complete set up */ ++ host->resuming = true; ++ return 0; + } + EXPORT_SYMBOL(tmio_mmc_host_resume); ++#endif + +-#endif /* CONFIG_PM */ +- ++#ifdef CONFIG_PM_RUNTIME + int tmio_mmc_host_runtime_suspend(struct device *dev) + { + return 0; +@@ -1041,21 +1178,12 @@ int tmio_mmc_host_runtime_resume(struct device *dev) + { + struct mmc_host *mmc = dev_get_drvdata(dev); + struct tmio_mmc_host *host = mmc_priv(mmc); +- struct tmio_mmc_data *pdata = host->pdata; + +- tmio_mmc_reset(host); + tmio_mmc_enable_dma(host, true); + +- if (pdata->power) { +- /* Only entered after a card-insert interrupt */ +- if (!mmc->card) +- tmio_mmc_set_ios(mmc, &mmc->ios); +- mmc_detect_change(mmc, msecs_to_jiffies(100)); +- } +- host->pm_global = false; +- + return 0; + } + EXPORT_SYMBOL(tmio_mmc_host_runtime_resume); ++#endif + + MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/ushc.c b/drivers/mmc/host/ushc.c +index f08f944..d2c386f 100644 +--- a/drivers/mmc/host/ushc.c ++++ b/drivers/mmc/host/ushc.c +@@ -504,7 +504,7 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id + ret = -ENOMEM; + goto err; + } +- ushc->csw = kzalloc(sizeof(struct ushc_cbw), GFP_KERNEL); ++ ushc->csw = kzalloc(sizeof(struct ushc_csw), GFP_KERNEL); + if (ushc->csw == NULL) { + ret = -ENOMEM; + goto err; +@@ -562,17 +562,7 @@ static struct usb_driver ushc_driver = { + .disconnect = ushc_disconnect, + }; + +-static int __init ushc_init(void) +-{ +- return usb_register(&ushc_driver); +-} +-module_init(ushc_init); +- +-static void __exit ushc_exit(void) +-{ +- usb_deregister(&ushc_driver); +-} +-module_exit(ushc_exit); ++module_usb_driver(ushc_driver); + + MODULE_DESCRIPTION("USB SD Host Controller driver"); + MODULE_AUTHOR("David Vrabel "); +diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c +index 4b83c43..63fac78 100644 +--- a/drivers/mmc/host/via-sdmmc.c ++++ b/drivers/mmc/host/via-sdmmc.c +@@ -1082,7 +1082,7 @@ static void via_init_mmc_host(struct via_crdr_mmc_host *host) + msleep(1); + } + +-static int __devinit via_sd_probe(struct pci_dev *pcidev, ++static int via_sd_probe(struct pci_dev *pcidev, + const struct pci_device_id *id) + { + struct mmc_host *mmc; +@@ -1176,7 +1176,7 @@ disable: + return ret; + } + +-static void __devexit via_sd_remove(struct pci_dev *pcidev) ++static void via_sd_remove(struct pci_dev *pcidev) + { + struct via_crdr_mmc_host *sdhost = pci_get_drvdata(pcidev); + unsigned long flags; +@@ -1269,21 +1269,18 @@ static void via_init_sdc_pm(struct via_crdr_mmc_host *host) + static int via_sd_suspend(struct pci_dev *pcidev, pm_message_t state) + { + struct via_crdr_mmc_host *host; +- int ret = 0; + + host = pci_get_drvdata(pcidev); + + via_save_pcictrlreg(host); + via_save_sdcreg(host); + +- ret = mmc_suspend_host(host->mmc); +- + pci_save_state(pcidev); + pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0); + pci_disable_device(pcidev); + pci_set_power_state(pcidev, pci_choose_state(pcidev, state)); + +- return ret; ++ return 0; + } + + static int via_sd_resume(struct pci_dev *pcidev) +@@ -1316,8 +1313,6 @@ static int via_sd_resume(struct pci_dev *pcidev) + via_restore_pcictrlreg(sdhost); + via_init_sdc_pm(sdhost); + +- ret = mmc_resume_host(sdhost->mmc); +- + return ret; + } + +@@ -1332,26 +1327,12 @@ static struct pci_driver via_sd_driver = { + .name = DRV_NAME, + .id_table = via_ids, + .probe = via_sd_probe, +- .remove = __devexit_p(via_sd_remove), ++ .remove = via_sd_remove, + .suspend = via_sd_suspend, + .resume = via_sd_resume, + }; + +-static int __init via_sd_drv_init(void) +-{ +- pr_info(DRV_NAME ": VIA SD/MMC Card Reader driver " +- "(C) 2008 VIA Technologies, Inc.\n"); +- +- return pci_register_driver(&via_sd_driver); +-} +- +-static void __exit via_sd_drv_exit(void) +-{ +- pci_unregister_driver(&via_sd_driver); +-} +- +-module_init(via_sd_drv_init); +-module_exit(via_sd_drv_exit); ++module_pci_driver(via_sd_driver); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("VIA Technologies Inc."); +diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c +index 2ec978b..4262296 100644 +--- a/drivers/mmc/host/vub300.c ++++ b/drivers/mmc/host/vub300.c +@@ -223,25 +223,25 @@ enum SD_RESPONSE_TYPE { + #define FUN(c) (0x000007 & (c->arg>>28)) + #define REG(c) (0x01FFFF & (c->arg>>9)) + +-static int limit_speed_to_24_MHz; ++static bool limit_speed_to_24_MHz; + module_param(limit_speed_to_24_MHz, bool, 0644); + MODULE_PARM_DESC(limit_speed_to_24_MHz, "Limit Max SDIO Clock Speed to 24 MHz"); + +-static int pad_input_to_usb_pkt; ++static bool pad_input_to_usb_pkt; + module_param(pad_input_to_usb_pkt, bool, 0644); + MODULE_PARM_DESC(pad_input_to_usb_pkt, + "Pad USB data input transfers to whole USB Packet"); + +-static int disable_offload_processing; ++static bool disable_offload_processing; + module_param(disable_offload_processing, bool, 0644); + MODULE_PARM_DESC(disable_offload_processing, "Disable Offload Processing"); + +-static int force_1_bit_data_xfers; ++static bool force_1_bit_data_xfers; + module_param(force_1_bit_data_xfers, bool, 0644); + MODULE_PARM_DESC(force_1_bit_data_xfers, + "Force SDIO Data Transfers to 1-bit Mode"); + +-static int force_polling_for_irqs; ++static bool force_polling_for_irqs; + module_param(force_polling_for_irqs, bool, 0644); + MODULE_PARM_DESC(force_polling_for_irqs, "Force Polling for SDIO interrupts"); + +@@ -806,7 +806,7 @@ static void command_res_completed(struct urb *urb) + * we suspect a buggy USB host controller + */ + } else if (!vub300->data) { +- /* this means that the command (typically CMD52) suceeded */ ++ /* this means that the command (typically CMD52) succeeded */ + } else if (vub300->resp.common.header_type != 0x02) { + /* + * this is an error response from the VUB300 chip +@@ -2079,7 +2079,7 @@ static void vub300_enable_sdio_irq(struct mmc_host *mmc, int enable) + kref_put(&vub300->kref, vub300_delete); + } + +-void vub300_init_card(struct mmc_host *mmc, struct mmc_card *card) ++static void vub300_init_card(struct mmc_host *mmc, struct mmc_card *card) + { /* NOT irq */ + struct vub300_mmc_host *vub300 = mmc_priv(mmc); + dev_info(&vub300->udev->dev, "NO host QUIRKS for this card\n"); +@@ -2358,10 +2358,11 @@ error5: + * which is contained at the end of struct mmc + */ + error4: +- usb_free_urb(command_out_urb); +-error1: + usb_free_urb(command_res_urb); ++error1: ++ usb_free_urb(command_out_urb); + error0: ++ usb_put_dev(udev); + return retval; + } + +@@ -2391,26 +2392,12 @@ static void vub300_disconnect(struct usb_interface *interface) + #ifdef CONFIG_PM + static int vub300_suspend(struct usb_interface *intf, pm_message_t message) + { +- struct vub300_mmc_host *vub300 = usb_get_intfdata(intf); +- if (!vub300 || !vub300->mmc) { +- return 0; +- } else { +- struct mmc_host *mmc = vub300->mmc; +- mmc_suspend_host(mmc); +- return 0; +- } ++ return 0; + } + + static int vub300_resume(struct usb_interface *intf) + { +- struct vub300_mmc_host *vub300 = usb_get_intfdata(intf); +- if (!vub300 || !vub300->mmc) { +- return 0; +- } else { +- struct mmc_host *mmc = vub300->mmc; +- mmc_resume_host(mmc); +- return 0; +- } ++ return 0; + } + #else + #define vub300_suspend NULL +diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c +index 64acd9c..1defd5e 100644 +--- a/drivers/mmc/host/wbsd.c ++++ b/drivers/mmc/host/wbsd.c +@@ -1196,7 +1196,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id) + * Allocate/free MMC structure. + */ + +-static int __devinit wbsd_alloc_mmc(struct device *dev) ++static int wbsd_alloc_mmc(struct device *dev) + { + struct mmc_host *mmc; + struct wbsd_host *host; +@@ -1288,7 +1288,7 @@ static void wbsd_free_mmc(struct device *dev) + * Scan for known chip id:s + */ + +-static int __devinit wbsd_scan(struct wbsd_host *host) ++static int wbsd_scan(struct wbsd_host *host) + { + int i, j, k; + int id; +@@ -1344,7 +1344,7 @@ static int __devinit wbsd_scan(struct wbsd_host *host) + * Allocate/free io port ranges + */ + +-static int __devinit wbsd_request_region(struct wbsd_host *host, int base) ++static int wbsd_request_region(struct wbsd_host *host, int base) + { + if (base & 0x7) + return -EINVAL; +@@ -1374,7 +1374,7 @@ static void wbsd_release_regions(struct wbsd_host *host) + * Allocate/free DMA port and buffer + */ + +-static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma) ++static void wbsd_request_dma(struct wbsd_host *host, int dma) + { + if (dma < 0) + return; +@@ -1452,7 +1452,7 @@ static void wbsd_release_dma(struct wbsd_host *host) + * Allocate/free IRQ. + */ + +-static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq) ++static int wbsd_request_irq(struct wbsd_host *host, int irq) + { + int ret; + +@@ -1502,7 +1502,7 @@ static void wbsd_release_irq(struct wbsd_host *host) + * Allocate all resources for the host. + */ + +-static int __devinit wbsd_request_resources(struct wbsd_host *host, ++static int wbsd_request_resources(struct wbsd_host *host, + int base, int irq, int dma) + { + int ret; +@@ -1644,7 +1644,7 @@ static void wbsd_chip_poweroff(struct wbsd_host *host) + * * + \*****************************************************************************/ + +-static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma, ++static int wbsd_init(struct device *dev, int base, int irq, int dma, + int pnp) + { + struct wbsd_host *host = NULL; +@@ -1735,7 +1735,7 @@ static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma, + return 0; + } + +-static void __devexit wbsd_shutdown(struct device *dev, int pnp) ++static void wbsd_shutdown(struct device *dev, int pnp) + { + struct mmc_host *mmc = dev_get_drvdata(dev); + struct wbsd_host *host; +@@ -1762,13 +1762,13 @@ static void __devexit wbsd_shutdown(struct device *dev, int pnp) + * Non-PnP + */ + +-static int __devinit wbsd_probe(struct platform_device *dev) ++static int wbsd_probe(struct platform_device *dev) + { + /* Use the module parameters for resources */ + return wbsd_init(&dev->dev, param_io, param_irq, param_dma, 0); + } + +-static int __devexit wbsd_remove(struct platform_device *dev) ++static int wbsd_remove(struct platform_device *dev) + { + wbsd_shutdown(&dev->dev, 0); + +@@ -1781,7 +1781,7 @@ static int __devexit wbsd_remove(struct platform_device *dev) + + #ifdef CONFIG_PNP + +-static int __devinit ++static int + wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id) + { + int io, irq, dma; +@@ -1801,7 +1801,7 @@ wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id) + return wbsd_init(&pnpdev->dev, io, irq, dma, 1); + } + +-static void __devexit wbsd_pnp_remove(struct pnp_dev *dev) ++static void wbsd_pnp_remove(struct pnp_dev *dev) + { + wbsd_shutdown(&dev->dev, 1); + } +@@ -1814,28 +1814,11 @@ static void __devexit wbsd_pnp_remove(struct pnp_dev *dev) + + #ifdef CONFIG_PM + +-static int wbsd_suspend(struct wbsd_host *host, pm_message_t state) +-{ +- BUG_ON(host == NULL); +- +- return mmc_suspend_host(host->mmc); +-} +- +-static int wbsd_resume(struct wbsd_host *host) +-{ +- BUG_ON(host == NULL); +- +- wbsd_init_device(host); +- +- return mmc_resume_host(host->mmc); +-} +- + static int wbsd_platform_suspend(struct platform_device *dev, + pm_message_t state) + { + struct mmc_host *mmc = platform_get_drvdata(dev); + struct wbsd_host *host; +- int ret; + + if (mmc == NULL) + return 0; +@@ -1844,12 +1827,7 @@ static int wbsd_platform_suspend(struct platform_device *dev, + + host = mmc_priv(mmc); + +- ret = wbsd_suspend(host, state); +- if (ret) +- return ret; +- + wbsd_chip_poweroff(host); +- + return 0; + } + +@@ -1872,7 +1850,8 @@ static int wbsd_platform_resume(struct platform_device *dev) + */ + mdelay(5); + +- return wbsd_resume(host); ++ wbsd_init_device(host); ++ return 0; + } + + #ifdef CONFIG_PNP +@@ -1880,16 +1859,12 @@ static int wbsd_platform_resume(struct platform_device *dev) + static int wbsd_pnp_suspend(struct pnp_dev *pnp_dev, pm_message_t state) + { + struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev); +- struct wbsd_host *host; + + if (mmc == NULL) + return 0; + + DBGF("Suspending...\n"); +- +- host = mmc_priv(mmc); +- +- return wbsd_suspend(host, state); ++ return 0; + } + + static int wbsd_pnp_resume(struct pnp_dev *pnp_dev) +@@ -1922,7 +1897,8 @@ static int wbsd_pnp_resume(struct pnp_dev *pnp_dev) + */ + mdelay(5); + +- return wbsd_resume(host); ++ wbsd_init_device(host); ++ return 0; + } + + #endif /* CONFIG_PNP */ +@@ -1941,7 +1917,7 @@ static struct platform_device *wbsd_device; + + static struct platform_driver wbsd_driver = { + .probe = wbsd_probe, +- .remove = __devexit_p(wbsd_remove), ++ .remove = wbsd_remove, + + .suspend = wbsd_platform_suspend, + .resume = wbsd_platform_resume, +@@ -1957,7 +1933,7 @@ static struct pnp_driver wbsd_pnp_driver = { + .name = DRIVER_NAME, + .id_table = pnp_dev_table, + .probe = wbsd_pnp_probe, +- .remove = __devexit_p(wbsd_pnp_remove), ++ .remove = wbsd_pnp_remove, + + .suspend = wbsd_pnp_suspend, + .resume = wbsd_pnp_resume, +diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c +new file mode 100644 +index 0000000..282891a +--- /dev/null ++++ b/drivers/mmc/host/wmt-sdmmc.c +@@ -0,0 +1,1006 @@ ++/* ++ * WM8505/WM8650 SD/MMC Host Controller ++ * ++ * Copyright (C) 2010 Tony Prisk ++ * Copyright (C) 2008 WonderMedia Technologies, Inc. ++ * ++ * 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 ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++ ++#define DRIVER_NAME "wmt-sdhc" ++ ++ ++/* MMC/SD controller registers */ ++#define SDMMC_CTLR 0x00 ++#define SDMMC_CMD 0x01 ++#define SDMMC_RSPTYPE 0x02 ++#define SDMMC_ARG 0x04 ++#define SDMMC_BUSMODE 0x08 ++#define SDMMC_BLKLEN 0x0C ++#define SDMMC_BLKCNT 0x0E ++#define SDMMC_RSP 0x10 ++#define SDMMC_CBCR 0x20 ++#define SDMMC_INTMASK0 0x24 ++#define SDMMC_INTMASK1 0x25 ++#define SDMMC_STS0 0x28 ++#define SDMMC_STS1 0x29 ++#define SDMMC_STS2 0x2A ++#define SDMMC_STS3 0x2B ++#define SDMMC_RSPTIMEOUT 0x2C ++#define SDMMC_CLK 0x30 /* VT8500 only */ ++#define SDMMC_EXTCTRL 0x34 ++#define SDMMC_SBLKLEN 0x38 ++#define SDMMC_DMATIMEOUT 0x3C ++ ++ ++/* SDMMC_CTLR bit fields */ ++#define CTLR_CMD_START 0x01 ++#define CTLR_CMD_WRITE 0x04 ++#define CTLR_FIFO_RESET 0x08 ++ ++/* SDMMC_BUSMODE bit fields */ ++#define BM_SPI_MODE 0x01 ++#define BM_FOURBIT_MODE 0x02 ++#define BM_EIGHTBIT_MODE 0x04 ++#define BM_SD_OFF 0x10 ++#define BM_SPI_CS 0x20 ++#define BM_SD_POWER 0x40 ++#define BM_SOFT_RESET 0x80 ++#define BM_ONEBIT_MASK 0xFD ++ ++/* SDMMC_BLKLEN bit fields */ ++#define BLKL_CRCERR_ABORT 0x0800 ++#define BLKL_CD_POL_HIGH 0x1000 ++#define BLKL_GPI_CD 0x2000 ++#define BLKL_DATA3_CD 0x4000 ++#define BLKL_INT_ENABLE 0x8000 ++ ++/* SDMMC_INTMASK0 bit fields */ ++#define INT0_MBLK_TRAN_DONE_INT_EN 0x10 ++#define INT0_BLK_TRAN_DONE_INT_EN 0x20 ++#define INT0_CD_INT_EN 0x40 ++#define INT0_DI_INT_EN 0x80 ++ ++/* SDMMC_INTMASK1 bit fields */ ++#define INT1_CMD_RES_TRAN_DONE_INT_EN 0x02 ++#define INT1_CMD_RES_TOUT_INT_EN 0x04 ++#define INT1_MBLK_AUTO_STOP_INT_EN 0x08 ++#define INT1_DATA_TOUT_INT_EN 0x10 ++#define INT1_RESCRC_ERR_INT_EN 0x20 ++#define INT1_RCRC_ERR_INT_EN 0x40 ++#define INT1_WCRC_ERR_INT_EN 0x80 ++ ++/* SDMMC_STS0 bit fields */ ++#define STS0_WRITE_PROTECT 0x02 ++#define STS0_CD_DATA3 0x04 ++#define STS0_CD_GPI 0x08 ++#define STS0_MBLK_DONE 0x10 ++#define STS0_BLK_DONE 0x20 ++#define STS0_CARD_DETECT 0x40 ++#define STS0_DEVICE_INS 0x80 ++ ++/* SDMMC_STS1 bit fields */ ++#define STS1_SDIO_INT 0x01 ++#define STS1_CMDRSP_DONE 0x02 ++#define STS1_RSP_TIMEOUT 0x04 ++#define STS1_AUTOSTOP_DONE 0x08 ++#define STS1_DATA_TIMEOUT 0x10 ++#define STS1_RSP_CRC_ERR 0x20 ++#define STS1_RCRC_ERR 0x40 ++#define STS1_WCRC_ERR 0x80 ++ ++/* SDMMC_STS2 bit fields */ ++#define STS2_CMD_RES_BUSY 0x10 ++#define STS2_DATARSP_BUSY 0x20 ++#define STS2_DIS_FORCECLK 0x80 ++ ++ ++/* MMC/SD DMA Controller Registers */ ++#define SDDMA_GCR 0x100 ++#define SDDMA_IER 0x104 ++#define SDDMA_ISR 0x108 ++#define SDDMA_DESPR 0x10C ++#define SDDMA_RBR 0x110 ++#define SDDMA_DAR 0x114 ++#define SDDMA_BAR 0x118 ++#define SDDMA_CPR 0x11C ++#define SDDMA_CCR 0x120 ++ ++ ++/* SDDMA_GCR bit fields */ ++#define DMA_GCR_DMA_EN 0x00000001 ++#define DMA_GCR_SOFT_RESET 0x00000100 ++ ++/* SDDMA_IER bit fields */ ++#define DMA_IER_INT_EN 0x00000001 ++ ++/* SDDMA_ISR bit fields */ ++#define DMA_ISR_INT_STS 0x00000001 ++ ++/* SDDMA_RBR bit fields */ ++#define DMA_RBR_FORMAT 0x40000000 ++#define DMA_RBR_END 0x80000000 ++ ++/* SDDMA_CCR bit fields */ ++#define DMA_CCR_RUN 0x00000080 ++#define DMA_CCR_IF_TO_PERIPHERAL 0x00000000 ++#define DMA_CCR_PERIPHERAL_TO_IF 0x00400000 ++ ++/* SDDMA_CCR event status */ ++#define DMA_CCR_EVT_NO_STATUS 0x00000000 ++#define DMA_CCR_EVT_UNDERRUN 0x00000001 ++#define DMA_CCR_EVT_OVERRUN 0x00000002 ++#define DMA_CCR_EVT_DESP_READ 0x00000003 ++#define DMA_CCR_EVT_DATA_RW 0x00000004 ++#define DMA_CCR_EVT_EARLY_END 0x00000005 ++#define DMA_CCR_EVT_SUCCESS 0x0000000F ++ ++#define PDMA_READ 0x00 ++#define PDMA_WRITE 0x01 ++ ++#define WMT_SD_POWER_OFF 0 ++#define WMT_SD_POWER_ON 1 ++ ++struct wmt_dma_descriptor { ++ u32 flags; ++ u32 data_buffer_addr; ++ u32 branch_addr; ++ u32 reserved1; ++}; ++ ++struct wmt_mci_caps { ++ unsigned int f_min; ++ unsigned int f_max; ++ u32 ocr_avail; ++ u32 caps; ++ u32 max_seg_size; ++ u32 max_segs; ++ u32 max_blk_size; ++}; ++ ++struct wmt_mci_priv { ++ struct mmc_host *mmc; ++ void __iomem *sdmmc_base; ++ ++ int irq_regular; ++ int irq_dma; ++ ++ void *dma_desc_buffer; ++ dma_addr_t dma_desc_device_addr; ++ ++ struct completion cmdcomp; ++ struct completion datacomp; ++ ++ struct completion *comp_cmd; ++ struct completion *comp_dma; ++ ++ struct mmc_request *req; ++ struct mmc_command *cmd; ++ ++ struct clk *clk_sdmmc; ++ struct device *dev; ++ ++ u8 power_inverted; ++ u8 cd_inverted; ++}; ++ ++static void wmt_set_sd_power(struct wmt_mci_priv *priv, int enable) ++{ ++ u32 reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); ++ ++ if (enable ^ priv->power_inverted) ++ reg_tmp &= ~BM_SD_OFF; ++ else ++ reg_tmp |= BM_SD_OFF; ++ ++ writeb(reg_tmp, priv->sdmmc_base + SDMMC_BUSMODE); ++} ++ ++static void wmt_mci_read_response(struct mmc_host *mmc) ++{ ++ struct wmt_mci_priv *priv; ++ int idx1, idx2; ++ u8 tmp_resp; ++ u32 response; ++ ++ priv = mmc_priv(mmc); ++ ++ for (idx1 = 0; idx1 < 4; idx1++) { ++ response = 0; ++ for (idx2 = 0; idx2 < 4; idx2++) { ++ if ((idx1 == 3) && (idx2 == 3)) ++ tmp_resp = readb(priv->sdmmc_base + SDMMC_RSP); ++ else ++ tmp_resp = readb(priv->sdmmc_base + SDMMC_RSP + ++ (idx1*4) + idx2 + 1); ++ response |= (tmp_resp << (idx2 * 8)); ++ } ++ priv->cmd->resp[idx1] = cpu_to_be32(response); ++ } ++} ++ ++static void wmt_mci_start_command(struct wmt_mci_priv *priv) ++{ ++ u32 reg_tmp; ++ ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR); ++ writeb(reg_tmp | CTLR_CMD_START, priv->sdmmc_base + SDMMC_CTLR); ++} ++ ++static int wmt_mci_send_command(struct mmc_host *mmc, u8 command, u8 cmdtype, ++ u32 arg, u8 rsptype) ++{ ++ struct wmt_mci_priv *priv; ++ u32 reg_tmp; ++ ++ priv = mmc_priv(mmc); ++ ++ /* write command, arg, resptype registers */ ++ writeb(command, priv->sdmmc_base + SDMMC_CMD); ++ writel(arg, priv->sdmmc_base + SDMMC_ARG); ++ writeb(rsptype, priv->sdmmc_base + SDMMC_RSPTYPE); ++ ++ /* reset response FIFO */ ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR); ++ writeb(reg_tmp | CTLR_FIFO_RESET, priv->sdmmc_base + SDMMC_CTLR); ++ ++ /* ensure clock enabled - VT3465 */ ++ wmt_set_sd_power(priv, WMT_SD_POWER_ON); ++ ++ /* clear status bits */ ++ writeb(0xFF, priv->sdmmc_base + SDMMC_STS0); ++ writeb(0xFF, priv->sdmmc_base + SDMMC_STS1); ++ writeb(0xFF, priv->sdmmc_base + SDMMC_STS2); ++ writeb(0xFF, priv->sdmmc_base + SDMMC_STS3); ++ ++ /* set command type */ ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR); ++ writeb((reg_tmp & 0x0F) | (cmdtype << 4), ++ priv->sdmmc_base + SDMMC_CTLR); ++ ++ return 0; ++} ++ ++static void wmt_mci_disable_dma(struct wmt_mci_priv *priv) ++{ ++ writel(DMA_ISR_INT_STS, priv->sdmmc_base + SDDMA_ISR); ++ writel(0, priv->sdmmc_base + SDDMA_IER); ++} ++ ++static void wmt_complete_data_request(struct wmt_mci_priv *priv) ++{ ++ struct mmc_request *req; ++ req = priv->req; ++ ++ req->data->bytes_xfered = req->data->blksz * req->data->blocks; ++ ++ /* unmap the DMA pages used for write data */ ++ if (req->data->flags & MMC_DATA_WRITE) ++ dma_unmap_sg(mmc_dev(priv->mmc), req->data->sg, ++ req->data->sg_len, DMA_TO_DEVICE); ++ else ++ dma_unmap_sg(mmc_dev(priv->mmc), req->data->sg, ++ req->data->sg_len, DMA_FROM_DEVICE); ++ ++ /* Check if the DMA ISR returned a data error */ ++ if ((req->cmd->error) || (req->data->error)) ++ mmc_request_done(priv->mmc, req); ++ else { ++ wmt_mci_read_response(priv->mmc); ++ if (!req->data->stop) { ++ /* single-block read/write requests end here */ ++ mmc_request_done(priv->mmc, req); ++ } else { ++ /* ++ * we change the priv->cmd variable so the response is ++ * stored in the stop struct rather than the original ++ * calling command struct ++ */ ++ priv->comp_cmd = &priv->cmdcomp; ++ init_completion(priv->comp_cmd); ++ priv->cmd = req->data->stop; ++ wmt_mci_send_command(priv->mmc, req->data->stop->opcode, ++ 7, req->data->stop->arg, 9); ++ wmt_mci_start_command(priv); ++ } ++ } ++} ++ ++static irqreturn_t wmt_mci_dma_isr(int irq_num, void *data) ++{ ++ struct wmt_mci_priv *priv; ++ ++ int status; ++ ++ priv = (struct wmt_mci_priv *)data; ++ ++ status = readl(priv->sdmmc_base + SDDMA_CCR) & 0x0F; ++ ++ if (status != DMA_CCR_EVT_SUCCESS) { ++ dev_err(priv->dev, "DMA Error: Status = %d\n", status); ++ priv->req->data->error = -ETIMEDOUT; ++ complete(priv->comp_dma); ++ return IRQ_HANDLED; ++ } ++ ++ priv->req->data->error = 0; ++ ++ wmt_mci_disable_dma(priv); ++ ++ complete(priv->comp_dma); ++ ++ if (priv->comp_cmd) { ++ if (completion_done(priv->comp_cmd)) { ++ /* ++ * if the command (regular) interrupt has already ++ * completed, finish off the request otherwise we wait ++ * for the command interrupt and finish from there. ++ */ ++ wmt_complete_data_request(priv); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t wmt_mci_regular_isr(int irq_num, void *data) ++{ ++ struct wmt_mci_priv *priv; ++ u32 status0; ++ u32 status1; ++ u32 status2; ++ u32 reg_tmp; ++ int cmd_done; ++ ++ priv = (struct wmt_mci_priv *)data; ++ cmd_done = 0; ++ status0 = readb(priv->sdmmc_base + SDMMC_STS0); ++ status1 = readb(priv->sdmmc_base + SDMMC_STS1); ++ status2 = readb(priv->sdmmc_base + SDMMC_STS2); ++ ++ /* Check for card insertion */ ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_INTMASK0); ++ if ((reg_tmp & INT0_DI_INT_EN) && (status0 & STS0_DEVICE_INS)) { ++ mmc_detect_change(priv->mmc, 0); ++ if (priv->cmd) ++ priv->cmd->error = -ETIMEDOUT; ++ if (priv->comp_cmd) ++ complete(priv->comp_cmd); ++ if (priv->comp_dma) { ++ wmt_mci_disable_dma(priv); ++ complete(priv->comp_dma); ++ } ++ writeb(STS0_DEVICE_INS, priv->sdmmc_base + SDMMC_STS0); ++ return IRQ_HANDLED; ++ } ++ ++ if ((!priv->req->data) || ++ ((priv->req->data->stop) && (priv->cmd == priv->req->data->stop))) { ++ /* handle non-data & stop_transmission requests */ ++ if (status1 & STS1_CMDRSP_DONE) { ++ priv->cmd->error = 0; ++ cmd_done = 1; ++ } else if ((status1 & STS1_RSP_TIMEOUT) || ++ (status1 & STS1_DATA_TIMEOUT)) { ++ priv->cmd->error = -ETIMEDOUT; ++ cmd_done = 1; ++ } ++ ++ if (cmd_done) { ++ priv->comp_cmd = NULL; ++ ++ if (!priv->cmd->error) ++ wmt_mci_read_response(priv->mmc); ++ ++ priv->cmd = NULL; ++ ++ mmc_request_done(priv->mmc, priv->req); ++ } ++ } else { ++ /* handle data requests */ ++ if (status1 & STS1_CMDRSP_DONE) { ++ if (priv->cmd) ++ priv->cmd->error = 0; ++ if (priv->comp_cmd) ++ complete(priv->comp_cmd); ++ } ++ ++ if ((status1 & STS1_RSP_TIMEOUT) || ++ (status1 & STS1_DATA_TIMEOUT)) { ++ if (priv->cmd) ++ priv->cmd->error = -ETIMEDOUT; ++ if (priv->comp_cmd) ++ complete(priv->comp_cmd); ++ if (priv->comp_dma) { ++ wmt_mci_disable_dma(priv); ++ complete(priv->comp_dma); ++ } ++ } ++ ++ if (priv->comp_dma) { ++ /* ++ * If the dma interrupt has already completed, finish ++ * off the request; otherwise we wait for the DMA ++ * interrupt and finish from there. ++ */ ++ if (completion_done(priv->comp_dma)) ++ wmt_complete_data_request(priv); ++ } ++ } ++ ++ writeb(status0, priv->sdmmc_base + SDMMC_STS0); ++ writeb(status1, priv->sdmmc_base + SDMMC_STS1); ++ writeb(status2, priv->sdmmc_base + SDMMC_STS2); ++ ++ return IRQ_HANDLED; ++} ++ ++static void wmt_reset_hardware(struct mmc_host *mmc) ++{ ++ struct wmt_mci_priv *priv; ++ u32 reg_tmp; ++ ++ priv = mmc_priv(mmc); ++ ++ /* reset controller */ ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); ++ writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base + SDMMC_BUSMODE); ++ ++ /* reset response FIFO */ ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR); ++ writeb(reg_tmp | CTLR_FIFO_RESET, priv->sdmmc_base + SDMMC_CTLR); ++ ++ /* enable GPI pin to detect card */ ++ writew(BLKL_INT_ENABLE | BLKL_GPI_CD, priv->sdmmc_base + SDMMC_BLKLEN); ++ ++ /* clear interrupt status */ ++ writeb(0xFF, priv->sdmmc_base + SDMMC_STS0); ++ writeb(0xFF, priv->sdmmc_base + SDMMC_STS1); ++ ++ /* setup interrupts */ ++ writeb(INT0_CD_INT_EN | INT0_DI_INT_EN, priv->sdmmc_base + ++ SDMMC_INTMASK0); ++ writeb(INT1_DATA_TOUT_INT_EN | INT1_CMD_RES_TRAN_DONE_INT_EN | ++ INT1_CMD_RES_TOUT_INT_EN, priv->sdmmc_base + SDMMC_INTMASK1); ++ ++ /* set the DMA timeout */ ++ writew(8191, priv->sdmmc_base + SDMMC_DMATIMEOUT); ++ ++ /* auto clock freezing enable */ ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_STS2); ++ writeb(reg_tmp | STS2_DIS_FORCECLK, priv->sdmmc_base + SDMMC_STS2); ++ ++ /* set a default clock speed of 400Khz */ ++ clk_set_rate(priv->clk_sdmmc, 400000); ++} ++ ++static int wmt_dma_init(struct mmc_host *mmc) ++{ ++ struct wmt_mci_priv *priv; ++ ++ priv = mmc_priv(mmc); ++ ++ writel(DMA_GCR_SOFT_RESET, priv->sdmmc_base + SDDMA_GCR); ++ writel(DMA_GCR_DMA_EN, priv->sdmmc_base + SDDMA_GCR); ++ if ((readl(priv->sdmmc_base + SDDMA_GCR) & DMA_GCR_DMA_EN) != 0) ++ return 0; ++ else ++ return 1; ++} ++ ++static void wmt_dma_init_descriptor(struct wmt_dma_descriptor *desc, ++ u16 req_count, u32 buffer_addr, u32 branch_addr, int end) ++{ ++ desc->flags = 0x40000000 | req_count; ++ if (end) ++ desc->flags |= 0x80000000; ++ desc->data_buffer_addr = buffer_addr; ++ desc->branch_addr = branch_addr; ++} ++ ++static void wmt_dma_config(struct mmc_host *mmc, u32 descaddr, u8 dir) ++{ ++ struct wmt_mci_priv *priv; ++ u32 reg_tmp; ++ ++ priv = mmc_priv(mmc); ++ ++ /* Enable DMA Interrupts */ ++ writel(DMA_IER_INT_EN, priv->sdmmc_base + SDDMA_IER); ++ ++ /* Write DMA Descriptor Pointer Register */ ++ writel(descaddr, priv->sdmmc_base + SDDMA_DESPR); ++ ++ writel(0x00, priv->sdmmc_base + SDDMA_CCR); ++ ++ if (dir == PDMA_WRITE) { ++ reg_tmp = readl(priv->sdmmc_base + SDDMA_CCR); ++ writel(reg_tmp & DMA_CCR_IF_TO_PERIPHERAL, priv->sdmmc_base + ++ SDDMA_CCR); ++ } else { ++ reg_tmp = readl(priv->sdmmc_base + SDDMA_CCR); ++ writel(reg_tmp | DMA_CCR_PERIPHERAL_TO_IF, priv->sdmmc_base + ++ SDDMA_CCR); ++ } ++} ++ ++static void wmt_dma_start(struct wmt_mci_priv *priv) ++{ ++ u32 reg_tmp; ++ ++ reg_tmp = readl(priv->sdmmc_base + SDDMA_CCR); ++ writel(reg_tmp | DMA_CCR_RUN, priv->sdmmc_base + SDDMA_CCR); ++} ++ ++static void wmt_mci_request(struct mmc_host *mmc, struct mmc_request *req) ++{ ++ struct wmt_mci_priv *priv; ++ struct wmt_dma_descriptor *desc; ++ u8 command; ++ u8 cmdtype; ++ u32 arg; ++ u8 rsptype; ++ u32 reg_tmp; ++ ++ struct scatterlist *sg; ++ int i; ++ int sg_cnt; ++ int offset; ++ u32 dma_address; ++ int desc_cnt; ++ ++ priv = mmc_priv(mmc); ++ priv->req = req; ++ ++ /* ++ * Use the cmd variable to pass a pointer to the resp[] structure ++ * This is required on multi-block requests to pass the pointer to the ++ * stop command ++ */ ++ priv->cmd = req->cmd; ++ ++ command = req->cmd->opcode; ++ arg = req->cmd->arg; ++ rsptype = mmc_resp_type(req->cmd); ++ cmdtype = 0; ++ ++ /* rsptype=7 only valid for SPI commands - should be =2 for SD */ ++ if (rsptype == 7) ++ rsptype = 2; ++ /* rsptype=21 is R1B, convert for controller */ ++ if (rsptype == 21) ++ rsptype = 9; ++ ++ if (!req->data) { ++ wmt_mci_send_command(mmc, command, cmdtype, arg, rsptype); ++ wmt_mci_start_command(priv); ++ /* completion is now handled in the regular_isr() */ ++ } ++ if (req->data) { ++ priv->comp_cmd = &priv->cmdcomp; ++ init_completion(priv->comp_cmd); ++ ++ wmt_dma_init(mmc); ++ ++ /* set controller data length */ ++ reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN); ++ writew((reg_tmp & 0xF800) | (req->data->blksz - 1), ++ priv->sdmmc_base + SDMMC_BLKLEN); ++ ++ /* set controller block count */ ++ writew(req->data->blocks, priv->sdmmc_base + SDMMC_BLKCNT); ++ ++ desc = (struct wmt_dma_descriptor *)priv->dma_desc_buffer; ++ ++ if (req->data->flags & MMC_DATA_WRITE) { ++ sg_cnt = dma_map_sg(mmc_dev(mmc), req->data->sg, ++ req->data->sg_len, DMA_TO_DEVICE); ++ cmdtype = 1; ++ if (req->data->blocks > 1) ++ cmdtype = 3; ++ } else { ++ sg_cnt = dma_map_sg(mmc_dev(mmc), req->data->sg, ++ req->data->sg_len, DMA_FROM_DEVICE); ++ cmdtype = 2; ++ if (req->data->blocks > 1) ++ cmdtype = 4; ++ } ++ ++ dma_address = priv->dma_desc_device_addr + 16; ++ desc_cnt = 0; ++ ++ for_each_sg(req->data->sg, sg, sg_cnt, i) { ++ offset = 0; ++ while (offset < sg_dma_len(sg)) { ++ wmt_dma_init_descriptor(desc, req->data->blksz, ++ sg_dma_address(sg)+offset, ++ dma_address, 0); ++ desc++; ++ desc_cnt++; ++ offset += req->data->blksz; ++ dma_address += 16; ++ if (desc_cnt == req->data->blocks) ++ break; ++ } ++ } ++ desc--; ++ desc->flags |= 0x80000000; ++ ++ if (req->data->flags & MMC_DATA_WRITE) ++ wmt_dma_config(mmc, priv->dma_desc_device_addr, ++ PDMA_WRITE); ++ else ++ wmt_dma_config(mmc, priv->dma_desc_device_addr, ++ PDMA_READ); ++ ++ wmt_mci_send_command(mmc, command, cmdtype, arg, rsptype); ++ ++ priv->comp_dma = &priv->datacomp; ++ init_completion(priv->comp_dma); ++ ++ wmt_dma_start(priv); ++ wmt_mci_start_command(priv); ++ } ++} ++ ++static void wmt_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct wmt_mci_priv *priv; ++ u32 reg_tmp; ++ ++ priv = mmc_priv(mmc); ++ ++ if (ios->power_mode == MMC_POWER_UP) { ++ wmt_reset_hardware(mmc); ++ ++ wmt_set_sd_power(priv, WMT_SD_POWER_ON); ++ } ++ if (ios->power_mode == MMC_POWER_OFF) ++ wmt_set_sd_power(priv, WMT_SD_POWER_OFF); ++ ++ if (ios->clock != 0) ++ clk_set_rate(priv->clk_sdmmc, ios->clock); ++ ++ switch (ios->bus_width) { ++ case MMC_BUS_WIDTH_8: ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL); ++ writeb(reg_tmp | 0x04, priv->sdmmc_base + SDMMC_EXTCTRL); ++ break; ++ case MMC_BUS_WIDTH_4: ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); ++ writeb(reg_tmp | BM_FOURBIT_MODE, priv->sdmmc_base + ++ SDMMC_BUSMODE); ++ ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL); ++ writeb(reg_tmp & 0xFB, priv->sdmmc_base + SDMMC_EXTCTRL); ++ break; ++ case MMC_BUS_WIDTH_1: ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); ++ writeb(reg_tmp & BM_ONEBIT_MASK, priv->sdmmc_base + ++ SDMMC_BUSMODE); ++ ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL); ++ writeb(reg_tmp & 0xFB, priv->sdmmc_base + SDMMC_EXTCTRL); ++ break; ++ } ++} ++ ++static int wmt_mci_get_ro(struct mmc_host *mmc) ++{ ++ struct wmt_mci_priv *priv = mmc_priv(mmc); ++ ++ return !(readb(priv->sdmmc_base + SDMMC_STS0) & STS0_WRITE_PROTECT); ++} ++ ++static int wmt_mci_get_cd(struct mmc_host *mmc) ++{ ++ struct wmt_mci_priv *priv = mmc_priv(mmc); ++ u32 cd = (readb(priv->sdmmc_base + SDMMC_STS0) & STS0_CD_GPI) >> 3; ++ ++ return !(cd ^ priv->cd_inverted); ++} ++ ++static struct mmc_host_ops wmt_mci_ops = { ++ .request = wmt_mci_request, ++ .set_ios = wmt_mci_set_ios, ++ .get_ro = wmt_mci_get_ro, ++ .get_cd = wmt_mci_get_cd, ++}; ++ ++/* Controller capabilities */ ++static struct wmt_mci_caps wm8505_caps = { ++ .f_min = 390425, ++ .f_max = 50000000, ++ .ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34, ++ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | ++ MMC_CAP_SD_HIGHSPEED, ++ .max_seg_size = 65024, ++ .max_segs = 128, ++ .max_blk_size = 2048, ++}; ++ ++static struct of_device_id wmt_mci_dt_ids[] = { ++ { .compatible = "wm,wm8505-sdhc", .data = &wm8505_caps }, ++ { /* Sentinel */ }, ++}; ++ ++static int wmt_mci_probe(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc; ++ struct wmt_mci_priv *priv; ++ struct device_node *np = pdev->dev.of_node; ++ const struct of_device_id *of_id = ++ of_match_device(wmt_mci_dt_ids, &pdev->dev); ++ const struct wmt_mci_caps *wmt_caps; ++ int ret; ++ int regular_irq, dma_irq; ++ ++ if (!of_id || !of_id->data) { ++ dev_err(&pdev->dev, "Controller capabilities data missing\n"); ++ return -EFAULT; ++ } ++ ++ wmt_caps = of_id->data; ++ ++ if (!np) { ++ dev_err(&pdev->dev, "Missing SDMMC description in devicetree\n"); ++ return -EFAULT; ++ } ++ ++ regular_irq = irq_of_parse_and_map(np, 0); ++ dma_irq = irq_of_parse_and_map(np, 1); ++ ++ if (!regular_irq || !dma_irq) { ++ dev_err(&pdev->dev, "Getting IRQs failed!\n"); ++ ret = -ENXIO; ++ goto fail1; ++ } ++ ++ mmc = mmc_alloc_host(sizeof(struct wmt_mci_priv), &pdev->dev); ++ if (!mmc) { ++ dev_err(&pdev->dev, "Failed to allocate mmc_host\n"); ++ ret = -ENOMEM; ++ goto fail1; ++ } ++ ++ mmc->ops = &wmt_mci_ops; ++ mmc->f_min = wmt_caps->f_min; ++ mmc->f_max = wmt_caps->f_max; ++ mmc->ocr_avail = wmt_caps->ocr_avail; ++ mmc->caps = wmt_caps->caps; ++ ++ mmc->max_seg_size = wmt_caps->max_seg_size; ++ mmc->max_segs = wmt_caps->max_segs; ++ mmc->max_blk_size = wmt_caps->max_blk_size; ++ ++ mmc->max_req_size = (16*512*mmc->max_segs); ++ mmc->max_blk_count = mmc->max_req_size / 512; ++ ++ priv = mmc_priv(mmc); ++ priv->mmc = mmc; ++ priv->dev = &pdev->dev; ++ ++ priv->power_inverted = 0; ++ priv->cd_inverted = 0; ++ ++ if (of_get_property(np, "sdon-inverted", NULL)) ++ priv->power_inverted = 1; ++ if (of_get_property(np, "cd-inverted", NULL)) ++ priv->cd_inverted = 1; ++ ++ priv->sdmmc_base = of_iomap(np, 0); ++ if (!priv->sdmmc_base) { ++ dev_err(&pdev->dev, "Failed to map IO space\n"); ++ ret = -ENOMEM; ++ goto fail2; ++ } ++ ++ priv->irq_regular = regular_irq; ++ priv->irq_dma = dma_irq; ++ ++ ret = request_irq(regular_irq, wmt_mci_regular_isr, 0, "sdmmc", priv); ++ if (ret) { ++ dev_err(&pdev->dev, "Register regular IRQ fail\n"); ++ goto fail3; ++ } ++ ++ ret = request_irq(dma_irq, wmt_mci_dma_isr, 32, "sdmmc", priv); ++ if (ret) { ++ dev_err(&pdev->dev, "Register DMA IRQ fail\n"); ++ goto fail4; ++ } ++ ++ /* alloc some DMA buffers for descriptors/transfers */ ++ priv->dma_desc_buffer = dma_alloc_coherent(&pdev->dev, ++ mmc->max_blk_count * 16, ++ &priv->dma_desc_device_addr, ++ GFP_KERNEL); ++ if (!priv->dma_desc_buffer) { ++ dev_err(&pdev->dev, "DMA alloc fail\n"); ++ ret = -EPERM; ++ goto fail5; ++ } ++ ++ platform_set_drvdata(pdev, mmc); ++ ++ priv->clk_sdmmc = of_clk_get(np, 0); ++ if (IS_ERR(priv->clk_sdmmc)) { ++ dev_err(&pdev->dev, "Error getting clock\n"); ++ ret = PTR_ERR(priv->clk_sdmmc); ++ goto fail5; ++ } ++ ++ clk_prepare_enable(priv->clk_sdmmc); ++ ++ /* configure the controller to a known 'ready' state */ ++ wmt_reset_hardware(mmc); ++ ++ mmc_add_host(mmc); ++ ++ dev_info(&pdev->dev, "WMT SDHC Controller initialized\n"); ++ ++ return 0; ++fail5: ++ free_irq(dma_irq, priv); ++fail4: ++ free_irq(regular_irq, priv); ++fail3: ++ iounmap(priv->sdmmc_base); ++fail2: ++ mmc_free_host(mmc); ++fail1: ++ return ret; ++} ++ ++static int wmt_mci_remove(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc; ++ struct wmt_mci_priv *priv; ++ struct resource *res; ++ u32 reg_tmp; ++ ++ mmc = platform_get_drvdata(pdev); ++ priv = mmc_priv(mmc); ++ ++ /* reset SD controller */ ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); ++ writel(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base + SDMMC_BUSMODE); ++ reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN); ++ writew(reg_tmp & ~(0xA000), priv->sdmmc_base + SDMMC_BLKLEN); ++ writeb(0xFF, priv->sdmmc_base + SDMMC_STS0); ++ writeb(0xFF, priv->sdmmc_base + SDMMC_STS1); ++ ++ /* release the dma buffers */ ++ dma_free_coherent(&pdev->dev, priv->mmc->max_blk_count * 16, ++ priv->dma_desc_buffer, priv->dma_desc_device_addr); ++ ++ mmc_remove_host(mmc); ++ ++ free_irq(priv->irq_regular, priv); ++ free_irq(priv->irq_dma, priv); ++ ++ iounmap(priv->sdmmc_base); ++ ++ clk_disable_unprepare(priv->clk_sdmmc); ++ clk_put(priv->clk_sdmmc); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(res->start, resource_size(res)); ++ ++ mmc_free_host(mmc); ++ ++ dev_info(&pdev->dev, "WMT MCI device removed\n"); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int wmt_mci_suspend(struct device *dev) ++{ ++ u32 reg_tmp; ++ struct platform_device *pdev = to_platform_device(dev); ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ struct wmt_mci_priv *priv; ++ ++ if (!mmc) ++ return 0; ++ ++ priv = mmc_priv(mmc); ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); ++ writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base + ++ SDMMC_BUSMODE); ++ ++ reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN); ++ writew(reg_tmp & 0x5FFF, priv->sdmmc_base + SDMMC_BLKLEN); ++ ++ writeb(0xFF, priv->sdmmc_base + SDMMC_STS0); ++ writeb(0xFF, priv->sdmmc_base + SDMMC_STS1); ++ ++ clk_disable(priv->clk_sdmmc); ++ return 0; ++} ++ ++static int wmt_mci_resume(struct device *dev) ++{ ++ u32 reg_tmp; ++ struct platform_device *pdev = to_platform_device(dev); ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ struct wmt_mci_priv *priv; ++ ++ if (mmc) { ++ priv = mmc_priv(mmc); ++ clk_enable(priv->clk_sdmmc); ++ ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE); ++ writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base + ++ SDMMC_BUSMODE); ++ ++ reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN); ++ writew(reg_tmp | (BLKL_GPI_CD | BLKL_INT_ENABLE), ++ priv->sdmmc_base + SDMMC_BLKLEN); ++ ++ reg_tmp = readb(priv->sdmmc_base + SDMMC_INTMASK0); ++ writeb(reg_tmp | INT0_DI_INT_EN, priv->sdmmc_base + ++ SDMMC_INTMASK0); ++ ++ } ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops wmt_mci_pm = { ++ .suspend = wmt_mci_suspend, ++ .resume = wmt_mci_resume, ++}; ++ ++#define wmt_mci_pm_ops (&wmt_mci_pm) ++ ++#else /* !CONFIG_PM */ ++ ++#define wmt_mci_pm_ops NULL ++ ++#endif ++ ++static struct platform_driver wmt_mci_driver = { ++ .probe = wmt_mci_probe, ++ .remove = wmt_mci_remove, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .pm = wmt_mci_pm_ops, ++ .of_match_table = wmt_mci_dt_ids, ++ }, ++}; ++ ++module_platform_driver(wmt_mci_driver); ++ ++MODULE_DESCRIPTION("Wondermedia MMC/SD Driver"); ++MODULE_AUTHOR("Tony Prisk"); ++MODULE_LICENSE("GPL v2"); ++MODULE_DEVICE_TABLE(of, wmt_mci_dt_ids); +diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig +index b1e3c26..c7ae3f5 100644 +--- a/drivers/mtd/chips/Kconfig ++++ b/drivers/mtd/chips/Kconfig +@@ -52,8 +52,8 @@ config MTD_CFI_NOSWAP + 'NO', which is the default when CONFIG_MTD_CFI_ADV_OPTIONS isn't + enabled, means that the CPU will not do any swapping; the chips + are expected to be wired to the CPU in 'host-endian' form. +- Specific arrangements are possible with the BIG_ENDIAN_BYTE and +- LITTLE_ENDIAN_BYTE, if the bytes are reversed. ++ Specific arrangements are possible with the BIG_ENDIAN_BYTE, ++ LITTLE_ENDIAN_BYTE, and OF_BYTE_SWAP if the bytes are reversed. + + If you have a LART, on which the data (and address) lines were + connected in a fashion which ensured that the nets were as short +@@ -68,6 +68,9 @@ config MTD_CFI_BE_BYTE_SWAP + config MTD_CFI_LE_BYTE_SWAP + bool "LITTLE_ENDIAN_BYTE" + ++config MTD_CFI_OF_BYTE_SWAP ++ bool "OF_BYTESWAP_PROPERTY" ++ + endchoice + + config MTD_CFI_GEOMETRY +diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c +index 179814a..aa272a3 100644 +--- a/drivers/mtd/chips/cfi_cmdset_0020.c ++++ b/drivers/mtd/chips/cfi_cmdset_0020.c +@@ -139,8 +139,8 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary) + } + + /* Do some byteswapping if necessary */ +- extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport); +- extp->BlkStatusRegMask = cfi32_to_cpu(extp->BlkStatusRegMask); ++ extp->FeatureSupport = cfi32_to_cpu(map, extp->FeatureSupport); ++ extp->BlkStatusRegMask = cfi32_to_cpu(map, extp->BlkStatusRegMask); + + #ifdef DEBUG_CFI_FEATURES + /* Tell the user about it in lots of lovely detail */ +diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig +index 283d887..95cc3ad 100644 +--- a/drivers/mtd/devices/Kconfig ++++ b/drivers/mtd/devices/Kconfig +@@ -102,6 +102,15 @@ config M25PXX_USE_FAST_READ + help + This option enables FAST_READ access supported by ST M25Pxx. + ++config M25PXX_STAY_IN_3BYTE_MODE ++ bool "Stay in 3-byte address mode when idle" ++ depends on MTD_M25P80 ++ default n ++ help ++ This option forces the flash to stay in 3-byte address mode when idle ++ (even for flashes that require 4-byte address). This is work around the ++ reset problem if the controller cannot issue 4-byte OPCODE when booting. ++ + config MTD_SST25L + tristate "Support SST25L (non JEDEC) SPI Flash chips" + depends on SPI_MASTER +diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c +index 3d6beb7..9145658 100644 +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -47,6 +47,7 @@ + #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ + #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ + #define OPCODE_RDID 0x9f /* Read JEDEC ID */ ++#define OPCODE_RDFSR 0x70 /* Read Flag Status Register */ + + /* Used for SST flashes only. */ + #define OPCODE_BP 0x02 /* Byte program */ +@@ -69,6 +70,9 @@ + #define SR_BP2 0x10 /* Block protect 2 */ + #define SR_SRWD 0x80 /* SR write protect */ + ++/* Flag Status Register bits. */ ++#define FSR_RDY 0x80 /* Ready/Busy program erase controller */ ++ + /* 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 MAX_CMD_SIZE 6 +@@ -91,6 +95,7 @@ struct m25p { + struct mtd_info mtd; + u16 page_size; + u16 addr_width; ++ bool check_fsr; + u8 erase_opcode; + u8 *command; + }; +@@ -107,6 +112,28 @@ static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) + */ + + /* ++ * Read the Flag Status Register (required for some Micron chips). ++ * Return the Flag Status Register value. ++ * Returns negative if error occurred. ++ */ ++static int read_fsr(struct m25p *flash) ++{ ++ ssize_t retval; ++ u8 code = OPCODE_RDFSR; ++ u8 val; ++ ++ retval = spi_write_then_read(flash->spi, &code, 1, &val, 1); ++ ++ if (retval < 0) { ++ dev_err(&flash->spi->dev, "error %d reading FSR\n", ++ (int) retval); ++ return retval; ++ } ++ ++ return val; ++} ++ ++/* + * Read the status register, returning its value in the location + * Return the status register value. + * Returns negative if error occurred. +@@ -166,10 +193,18 @@ static inline int write_disable(struct m25p *flash) + */ + static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable) + { ++ int status; ++ + switch (JEDEC_MFR(jedec_id)) { + case CFI_MFR_MACRONIX: + flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; + return spi_write(flash->spi, flash->command, 1); ++ case CFI_MFR_ST: ++ flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; ++ write_enable(flash); ++ status = spi_write(flash->spi, flash->command, 1); ++ write_disable(flash); ++ return status; + default: + /* Spansion style */ + flash->command[0] = OPCODE_BRWR; +@@ -185,15 +220,21 @@ static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable) + static int wait_till_ready(struct m25p *flash) + { + unsigned long deadline; +- int sr; ++ int sr, fsr; + + deadline = jiffies + MAX_READY_WAIT_JIFFIES; + + do { + if ((sr = read_sr(flash)) < 0) + break; +- else if (!(sr & SR_WIP)) ++ else if (!(sr & SR_WIP)) { ++ if (flash->check_fsr) { ++ fsr = read_fsr(flash); ++ if (!(fsr & FSR_RDY)) ++ return 1; ++ } + return 0; ++ } + + cond_resched(); + +@@ -625,6 +666,7 @@ struct flash_info { + u16 flags; + #define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ + #define M25P_NO_ERASE 0x02 /* No erase command needed */ ++#define E_FSR 0x08 /* Flag SR exists for flash */ + }; + + #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ +@@ -686,6 +728,10 @@ static const struct spi_device_id m25p_ids[] = { + { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, + { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, + ++ /* Micron */ ++ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, ++ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, ++ + /* Spansion -- single (large) sector size only, at least + * for the chips listed here (without boot sectors). + */ +@@ -727,6 +773,11 @@ static const struct spi_device_id m25p_ids[] = { + { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, + { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, + ++ { "n25q64", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, ++ { "n25q128", INFO(0x20ba18, 0, 64 * 1024, 256, E_FSR) }, ++ { "n25q256", INFO(0x20ba19, 0, 64 * 1024, 512, E_FSR | SECT_4K) }, ++ { "n25q512", INFO(0x20ba20, 0, 64 * 1024, 1024, E_FSR | SECT_4K) }, ++ + { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, + { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, + { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) }, +@@ -928,6 +979,9 @@ static int __devinit m25p_probe(struct spi_device *spi) + if (info->flags & M25P_NO_ERASE) + flash->mtd.flags |= MTD_NO_ERASE; + ++ if (info->flags & E_FSR) ++ flash->check_fsr = 1; ++ + ppdata.of_node = spi->dev.of_node; + flash->mtd.dev.parent = &spi->dev; + flash->page_size = info->page_size; +diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c +index 7d65f9d..7f32f30 100644 +--- a/drivers/mtd/maps/physmap_of.c ++++ b/drivers/mtd/maps/physmap_of.c +@@ -161,6 +161,9 @@ static int __devinit of_flash_probe(struct platform_device *dev) + struct of_flash *info; + const char *probe_type; + const __be32 *width; ++#ifdef CONFIG_MTD_CFI_OF_BYTE_SWAP ++ struct property * byteswap_prop; ++#endif + int err; + int i; + int count; +@@ -236,6 +239,16 @@ static int __devinit of_flash_probe(struct platform_device *dev) + info->list[i].map.size = res_size; + info->list[i].map.bankwidth = be32_to_cpup(width); + ++#ifdef CONFIG_MTD_CFI_OF_BYTE_SWAP ++ byteswap_prop = of_find_property(dp, "byteswap", NULL); ++ if (byteswap_prop == NULL) { ++ info->list[i].map.byteswap = 0; ++ } else { ++ info->list[i].map.byteswap = 1; ++ dev_info(&dev->dev, "byteswapping configured in OF\n"); ++ } ++#endif ++ + err = -ENOMEM; + info->list[i].map.virt = ioremap(info->list[i].map.phys, + info->list[i].map.size); +diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c +index f3cdce9..b7883e5 100644 +--- a/drivers/mtd/mtdoops.c ++++ b/drivers/mtd/mtdoops.c +@@ -311,8 +311,7 @@ static void mtdoops_do_dump(struct kmsg_dumper *dumper, + char *dst; + + if (reason != KMSG_DUMP_OOPS && +- reason != KMSG_DUMP_PANIC && +- reason != KMSG_DUMP_KEXEC) ++ reason != KMSG_DUMP_PANIC) + return; + + /* Only dump oopses if dump_oops is set */ +diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c +index 1f9c363..bc431fb 100644 +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -1286,7 +1286,7 @@ out: + ubi_err("UBI error: cannot initialize UBI, error %d", err); + return err; + } +-module_init(ubi_init); ++late_initcall(ubi_init); + + static void __exit ubi_exit(void) + { +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index 61d3d1f..05ac9bc 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -153,6 +153,20 @@ config MACVTAP + To compile this driver as a module, choose M here: the module + will be called macvtap. + ++config VXLAN ++ tristate "Virtual eXtensible Local Area Network (VXLAN)" ++ depends on EXPERIMENTAL ++ ---help--- ++ This allows one to create vxlan virtual interfaces that provide ++ Layer 2 Networks over Layer 3 Networks. VXLAN is often used ++ to tunnel virtual network infrastructure in virtualized environments. ++ For more information see: ++ http://tools.ietf.org/html/draft-mahalingam-dutt-dcops-vx... ++ ++ To compile this driver as a module, choose M here: the module ++ will be called vxlan. ++ ++ + config NETCONSOLE + tristate "Network console logging support" + ---help--- +@@ -340,4 +354,101 @@ config VMXNET3 + To compile this driver as a module, choose M here: the + module will be called vmxnet3. + ++source "drivers/net/hyperv/Kconfig" ++ ++config DPA ++ bool "Freescale Data Path Frame Manager Ethernet" ++ depends on FSL_SOC && FSL_BMAN && FSL_QMAN && FSL_FMAN && LIBFCOE=n ++ select PHYLIB ++ ++config DPA_OFFLINE_PORTS ++ bool "Offline Ports support" ++ depends on DPA ++ default y ++ help ++ The Offline Parsing / Host Command ports (short: OH ports, of Offline ports) provide ++ most of the functionality of the regular, online ports, except they receive their ++ frames from a core or an accelerator on the SoC, via QMan frame queues, ++ rather than directly from the network. ++ Offline ports are configured via PCD (Parse-Classify-Distribute) schemes, just like ++ any online FMan port. They deliver the processed frames to frame queues, according ++ to the applied PCD configurations. ++ ++ Choosing this feature will not impact the functionality and/or performance of the system, ++ so it is safe to have it. ++ ++config DPAA_ETH_SG_SUPPORT ++ bool ++ ++choice DPAA_ETH_OPTIMIZE ++ prompt "Optimization choices for the DPAA Ethernet driver" ++ depends on DPA ++ default DPAA_ETH_OPTIMIZE_FOR_IPFWD ++ ++ ---help--- ++ Compile-time switch between driver optimizations for forwarding use-cases and ++ termination scenarios. ++ ++ config DPAA_ETH_OPTIMIZE_FOR_IPFWD ++ bool "Optimize for forwarding" ++ select DPA_TX_RECYCLE if FMAN_T4240 ++ help ++ Optimize the DPAA-Ethernet driver for IP/IPSec forwarding use-cases. ++ ++ config DPAA_ETH_OPTIMIZE_FOR_TERM ++ bool "Optimize for termination" ++ select DPAA_ETH_SG_SUPPORT ++ help ++ Optimize the DPAA-Ethernet driver for termination (TCP, UDP) use-cases. ++ In particular, this choice enables Scatter-Gather (SG) support ++ in the driver, which is momentarily not accessible otherwise. ++ ++endchoice ++ ++config DPA_TX_RECYCLE ++ bool ++ depends on FMAN_T4240 ++ ++config FSL_DPA_1588 ++ tristate "IEEE 1588-compliant timestamping" ++ depends on DPA ++ default n ++ ++choice DPA_ETH_WQ_ASSIGN ++ prompt "WorkQueue assignment scheme for FrameQueues" ++ depends on DPA ++ default DPA_ETH_WQ_MULTI ++ help ++ Selects the FrameQueue to WorkQueue assignment scheme. ++ ++ config DPA_ETH_WQ_LEGACY ++ bool "Legacy WQ assignment" ++ help ++ Statically-defined FQIDs are round-robin assigned to all WQs (0..7). PCD queues are always ++ in this category. Other frame queues may be those used for "MAC-less" or "shared MAC" configurations ++ of the driver. ++ Dynamically-defined FQIDs all go to WQ7. ++ config DPA_ETH_WQ_MULTI ++ bool "Multi-WQ assignment" ++ help ++ Tx Confirmation FQs go to WQ1. ++ Rx Default, Tx and PCD FQs go to WQ3. ++ Rx Error and Tx Error FQs go to WQ2. ++endchoice ++ ++config DPAA_ETH_USE_NDO_SELECT_QUEUE ++ bool "Use driver's Tx queue selection mechanism" ++ default y ++ ---help--- ++ The DPAA-Ethernet driver defines a ndo_select_queue() callback for optimal selection ++ of the egress FQ. That will override the XPS support for this netdevice. ++ If for whatever reason you want to be in control of the egress FQ-to-CPU selection and mapping, ++ or simply don't want to use the driver's ndo_select_queue() callback, then unselect this ++ and use the standard XPS support instead. ++ ++config DPAA_ETH_UNIT_TESTS ++ bool "Run Unit Tests for DPAA Ethernet" ++ depends on DPA ++ default y ++ + endif # NETDEVICES +diff --git a/drivers/net/Makefile b/drivers/net/Makefile +index fa877cd..3e78eeb 100644 +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -20,6 +20,7 @@ obj-$(CONFIG_RIONET) += rionet.o + obj-$(CONFIG_TUN) += tun.o + obj-$(CONFIG_VETH) += veth.o + obj-$(CONFIG_VIRTIO_NET) += virtio_net.o ++obj-$(CONFIG_VXLAN) += vxlan.o + + # + # Networking Drivers +@@ -57,6 +58,8 @@ obj-$(CONFIG_VMXNET3) += vmxnet3/ + obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o + obj-$(CONFIG_XEN_NETDEV_BACKEND) += xen-netback/ + ++obj-$(if $(CONFIG_DPA),y) += dpa/ ++ + obj-$(CONFIG_USB_CATC) += usb/ + obj-$(CONFIG_USB_KAWETH) += usb/ + obj-$(CONFIG_USB_PEGASUS) += usb/ +@@ -66,3 +69,5 @@ obj-$(CONFIG_USB_USBNET) += usb/ + obj-$(CONFIG_USB_ZD1201) += usb/ + obj-$(CONFIG_USB_IPHETH) += usb/ + obj-$(CONFIG_USB_CDC_PHONET) += usb/ ++ ++obj-$(CONFIG_HYPERV_NET) += hyperv/ +diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig +index f5a8916..1dd0719 100644 +--- a/drivers/net/appletalk/Kconfig ++++ b/drivers/net/appletalk/Kconfig +@@ -49,32 +49,6 @@ config LTPC + This driver is experimental, which means that it may not work. + See the file . + +-config COPS +- tristate "COPS LocalTalk PC support" +- depends on DEV_APPLETALK && (ISA || EISA) +- help +- This allows you to use COPS AppleTalk cards to connect to LocalTalk +- networks. You also need version 1.3.3 or later of the netatalk +- package. This driver is experimental, which means that it may not +- work. This driver will only work if you choose "AppleTalk DDP" +- networking support, above. +- Please read the file . +- +-config COPS_DAYNA +- bool "Dayna firmware support" +- depends on COPS +- help +- Support COPS compatible cards with Dayna style firmware (Dayna +- DL2000/ Daynatalk/PC (half length), COPS LT-95, Farallon PhoneNET PC +- III, Farallon PhoneNET PC II). +- +-config COPS_TANGENT +- bool "Tangent firmware support" +- depends on COPS +- help +- Support COPS compatible cards with Tangent style firmware (Tangent +- ATB_II, Novell NL-1000, Daystar Digital LT-200. +- + config IPDDP + tristate "Appletalk-IP driver support" + depends on DEV_APPLETALK && ATALK +diff --git a/drivers/net/appletalk/Makefile b/drivers/net/appletalk/Makefile +index 6cfc705..e61e736 100644 +--- a/drivers/net/appletalk/Makefile ++++ b/drivers/net/appletalk/Makefile +@@ -3,5 +3,4 @@ + # + + obj-$(CONFIG_IPDDP) += ipddp.o +-obj-$(CONFIG_COPS) += cops.o + obj-$(CONFIG_LTPC) += ltpc.o +diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c +deleted file mode 100644 +index 9abd4eb..0000000 +--- a/drivers/net/appletalk/cops.c ++++ /dev/null +@@ -1,1013 +0,0 @@ +-/* cops.c: LocalTalk driver for Linux. +- * +- * Authors: +- * - Jay Schulist +- * +- * With more than a little help from; +- * - Alan Cox +- * +- * Derived from: +- * - skeleton.c: A network driver outline for linux. +- * Written 1993-94 by Donald Becker. +- * - ltpc.c: A driver for the LocalTalk PC card. +- * Written by Bradford W. Johnson. +- * +- * Copyright 1993 United States Government as represented by the +- * Director, National Security Agency. +- * +- * This software may be used and distributed according to the terms +- * of the GNU General Public License, incorporated herein by reference. +- * +- * Changes: +- * 19970608 Alan Cox Allowed dual card type support +- * Can set board type in insmod +- * Hooks for cops_setup routine +- * (not yet implemented). +- * 19971101 Jay Schulist Fixes for multiple lt* devices. +- * 19980607 Steven Hirsch Fixed the badly broken support +- * for Tangent type cards. Only +- * tested on Daystar LT200. Some +- * cleanup of formatting and program +- * logic. Added emacs 'local-vars' +- * setup for Jay's brace style. +- * 20000211 Alan Cox Cleaned up for softnet +- */ +- +-static const char *version = +-"cops.c:v0.04 6/7/98 Jay Schulist \n"; +-/* +- * Sources: +- * COPS Localtalk SDK. This provides almost all of the information +- * needed. +- */ +- +-/* +- * insmod/modprobe configurable stuff. +- * - IO Port, choose one your card supports or 0 if you dare. +- * - IRQ, also choose one your card supports or nothing and let +- * the driver figure it out. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include /* For udelay() */ +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include "cops.h" /* Our Stuff */ +-#include "cops_ltdrv.h" /* Firmware code for Tangent type cards. */ +-#include "cops_ffdrv.h" /* Firmware code for Dayna type cards. */ +- +-/* +- * The name of the card. Is used for messages and in the requests for +- * io regions, irqs and dma channels +- */ +- +-static const char *cardname = "cops"; +- +-#ifdef CONFIG_COPS_DAYNA +-static int board_type = DAYNA; /* Module exported */ +-#else +-static int board_type = TANGENT; +-#endif +- +-static int io = 0x240; /* Default IO for Dayna */ +-static int irq = 5; /* Default IRQ */ +- +-/* +- * COPS Autoprobe information. +- * Right now if port address is right but IRQ is not 5 this will +- * return a 5 no matter what since we will still get a status response. +- * Need one more additional check to narrow down after we have gotten +- * the ioaddr. But since only other possible IRQs is 3 and 4 so no real +- * hurry on this. I *STRONGLY* recommend using IRQ 5 for your card with +- * this driver. +- * +- * This driver has 2 modes and they are: Dayna mode and Tangent mode. +- * Each mode corresponds with the type of card. It has been found +- * that there are 2 main types of cards and all other cards are +- * the same and just have different names or only have minor differences +- * such as more IO ports. As this driver is tested it will +- * become more clear on exactly what cards are supported. The driver +- * defaults to using Dayna mode. To change the drivers mode, simply +- * select Dayna or Tangent mode when configuring the kernel. +- * +- * This driver should support: +- * TANGENT driver mode: +- * Tangent ATB-II, Novell NL-1000, Daystar Digital LT-200, +- * COPS LT-1 +- * DAYNA driver mode: +- * Dayna DL2000/DaynaTalk PC (Half Length), COPS LT-95, +- * Farallon PhoneNET PC III, Farallon PhoneNET PC II +- * Other cards possibly supported mode unknown though: +- * Dayna DL2000 (Full length), COPS LT/M (Micro-Channel) +- * +- * Cards NOT supported by this driver but supported by the ltpc.c +- * driver written by Bradford W. Johnson +- * Farallon PhoneNET PC +- * Original Apple LocalTalk PC card +- * +- * N.B. +- * +- * The Daystar Digital LT200 boards do not support interrupt-driven +- * IO. You must specify 'irq=0xff' as a module parameter to invoke +- * polled mode. I also believe that the port probing logic is quite +- * dangerous at best and certainly hopeless for a polled card. Best to +- * specify both. - Steve H. +- * +- */ +- +-/* +- * Zero terminated list of IO ports to probe. +- */ +- +-static unsigned int ports[] = { +- 0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260, +- 0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360, +- 0 +-}; +- +-/* +- * Zero terminated list of IRQ ports to probe. +- */ +- +-static int cops_irqlist[] = { +- 5, 4, 3, 0 +-}; +- +-static struct timer_list cops_timer; +- +-/* use 0 for production, 1 for verification, 2 for debug, 3 for verbose debug */ +-#ifndef COPS_DEBUG +-#define COPS_DEBUG 1 +-#endif +-static unsigned int cops_debug = COPS_DEBUG; +- +-/* The number of low I/O ports used by the card. */ +-#define COPS_IO_EXTENT 8 +- +-/* Information that needs to be kept for each board. */ +- +-struct cops_local +-{ +- int board; /* Holds what board type is. */ +- int nodeid; /* Set to 1 once have nodeid. */ +- unsigned char node_acquire; /* Node ID when acquired. */ +- struct atalk_addr node_addr; /* Full node address */ +- spinlock_t lock; /* RX/TX lock */ +-}; +- +-/* Index to functions, as function prototypes. */ +-static int cops_probe1 (struct net_device *dev, int ioaddr); +-static int cops_irq (int ioaddr, int board); +- +-static int cops_open (struct net_device *dev); +-static int cops_jumpstart (struct net_device *dev); +-static void cops_reset (struct net_device *dev, int sleep); +-static void cops_load (struct net_device *dev); +-static int cops_nodeid (struct net_device *dev, int nodeid); +- +-static irqreturn_t cops_interrupt (int irq, void *dev_id); +-static void cops_poll (unsigned long ltdev); +-static void cops_timeout(struct net_device *dev); +-static void cops_rx (struct net_device *dev); +-static netdev_tx_t cops_send_packet (struct sk_buff *skb, +- struct net_device *dev); +-static void set_multicast_list (struct net_device *dev); +-static int cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); +-static int cops_close (struct net_device *dev); +- +-static void cleanup_card(struct net_device *dev) +-{ +- if (dev->irq) +- free_irq(dev->irq, dev); +- release_region(dev->base_addr, COPS_IO_EXTENT); +-} +- +-/* +- * Check for a network adaptor of this type, and return '0' iff one exists. +- * If dev->base_addr == 0, probe all likely locations. +- * If dev->base_addr in [1..0x1ff], always return failure. +- * otherwise go with what we pass in. +- */ +-struct net_device * __init cops_probe(int unit) +-{ +- struct net_device *dev; +- unsigned *port; +- int base_addr; +- int err = 0; +- +- dev = alloc_ltalkdev(sizeof(struct cops_local)); +- if (!dev) +- return ERR_PTR(-ENOMEM); +- +- if (unit >= 0) { +- sprintf(dev->name, "lt%d", unit); +- netdev_boot_setup_check(dev); +- irq = dev->irq; +- base_addr = dev->base_addr; +- } else { +- base_addr = dev->base_addr = io; +- } +- +- if (base_addr > 0x1ff) { /* Check a single specified location. */ +- err = cops_probe1(dev, base_addr); +- } else if (base_addr != 0) { /* Don't probe at all. */ +- err = -ENXIO; +- } else { +- /* FIXME Does this really work for cards which generate irq? +- * It's definitely N.G. for polled Tangent. sh +- * Dayna cards don't autoprobe well at all, but if your card is +- * at IRQ 5 & IO 0x240 we find it every time. ;) JS +- */ +- for (port = ports; *port && cops_probe1(dev, *port) < 0; port++) +- ; +- if (!*port) +- err = -ENODEV; +- } +- if (err) +- goto out; +- err = register_netdev(dev); +- if (err) +- goto out1; +- return dev; +-out1: +- cleanup_card(dev); +-out: +- free_netdev(dev); +- return ERR_PTR(err); +-} +- +-static const struct net_device_ops cops_netdev_ops = { +- .ndo_open = cops_open, +- .ndo_stop = cops_close, +- .ndo_start_xmit = cops_send_packet, +- .ndo_tx_timeout = cops_timeout, +- .ndo_do_ioctl = cops_ioctl, +- .ndo_set_rx_mode = set_multicast_list, +-}; +- +-/* +- * This is the real probe routine. Linux has a history of friendly device +- * probes on the ISA bus. A good device probes avoids doing writes, and +- * verifies that the correct device exists and functions. +- */ +-static int __init cops_probe1(struct net_device *dev, int ioaddr) +-{ +- struct cops_local *lp; +- static unsigned version_printed; +- int board = board_type; +- int retval; +- +- if(cops_debug && version_printed++ == 0) +- printk("%s", version); +- +- /* Grab the region so no one else tries to probe our ioports. */ +- if (!request_region(ioaddr, COPS_IO_EXTENT, dev->name)) +- return -EBUSY; +- +- /* +- * Since this board has jumpered interrupts, allocate the interrupt +- * vector now. There is no point in waiting since no other device +- * can use the interrupt, and this marks the irq as busy. Jumpered +- * interrupts are typically not reported by the boards, and we must +- * used AutoIRQ to find them. +- */ +- dev->irq = irq; +- switch (dev->irq) +- { +- case 0: +- /* COPS AutoIRQ routine */ +- dev->irq = cops_irq(ioaddr, board); +- if (dev->irq) +- break; +- /* No IRQ found on this port, fallthrough */ +- case 1: +- retval = -EINVAL; +- goto err_out; +- +- /* Fixup for users that don't know that IRQ 2 is really +- * IRQ 9, or don't know which one to set. +- */ +- case 2: +- dev->irq = 9; +- break; +- +- /* Polled operation requested. Although irq of zero passed as +- * a parameter tells the init routines to probe, we'll +- * overload it to denote polled operation at runtime. +- */ +- case 0xff: +- dev->irq = 0; +- break; +- +- default: +- break; +- } +- +- /* Reserve any actual interrupt. */ +- if (dev->irq) { +- retval = request_irq(dev->irq, cops_interrupt, 0, dev->name, dev); +- if (retval) +- goto err_out; +- } +- +- dev->base_addr = ioaddr; +- +- lp = netdev_priv(dev); +- spin_lock_init(&lp->lock); +- +- /* Copy local board variable to lp struct. */ +- lp->board = board; +- +- dev->netdev_ops = &cops_netdev_ops; +- dev->watchdog_timeo = HZ * 2; +- +- +- /* Tell the user where the card is and what mode we're in. */ +- if(board==DAYNA) +- printk("%s: %s at %#3x, using IRQ %d, in Dayna mode.\n", +- dev->name, cardname, ioaddr, dev->irq); +- if(board==TANGENT) { +- if(dev->irq) +- printk("%s: %s at %#3x, IRQ %d, in Tangent mode\n", +- dev->name, cardname, ioaddr, dev->irq); +- else +- printk("%s: %s at %#3x, using polled IO, in Tangent mode.\n", +- dev->name, cardname, ioaddr); +- +- } +- return 0; +- +-err_out: +- release_region(ioaddr, COPS_IO_EXTENT); +- return retval; +-} +- +-static int __init cops_irq (int ioaddr, int board) +-{ /* +- * This does not use the IRQ to determine where the IRQ is. We just +- * assume that when we get a correct status response that it's the IRQ. +- * This really just verifies the IO port but since we only have access +- * to such a small number of IRQs (5, 4, 3) this is not bad. +- * This will probably not work for more than one card. +- */ +- int irqaddr=0; +- int i, x, status; +- +- if(board==DAYNA) +- { +- outb(0, ioaddr+DAYNA_RESET); +- inb(ioaddr+DAYNA_RESET); +- mdelay(333); +- } +- if(board==TANGENT) +- { +- inb(ioaddr); +- outb(0, ioaddr); +- outb(0, ioaddr+TANG_RESET); +- } +- +- for(i=0; cops_irqlist[i] !=0; i++) +- { +- irqaddr = cops_irqlist[i]; +- for(x = 0xFFFF; x>0; x --) /* wait for response */ +- { +- if(board==DAYNA) +- { +- status = (inb(ioaddr+DAYNA_CARD_STATUS)&3); +- if(status == 1) +- return irqaddr; +- } +- if(board==TANGENT) +- { +- if((inb(ioaddr+TANG_CARD_STATUS)& TANG_TX_READY) !=0) +- return irqaddr; +- } +- } +- } +- return 0; /* no IRQ found */ +-} +- +-/* +- * Open/initialize the board. This is called (in the current kernel) +- * sometime after booting when the 'ifconfig' program is run. +- */ +-static int cops_open(struct net_device *dev) +-{ +- struct cops_local *lp = netdev_priv(dev); +- +- if(dev->irq==0) +- { +- /* +- * I don't know if the Dayna-style boards support polled +- * operation. For now, only allow it for Tangent. +- */ +- if(lp->board==TANGENT) /* Poll 20 times per second */ +- { +- init_timer(&cops_timer); +- cops_timer.function = cops_poll; +- cops_timer.data = (unsigned long)dev; +- cops_timer.expires = jiffies + HZ/20; +- add_timer(&cops_timer); +- } +- else +- { +- printk(KERN_WARNING "%s: No irq line set\n", dev->name); +- return -EAGAIN; +- } +- } +- +- cops_jumpstart(dev); /* Start the card up. */ +- +- netif_start_queue(dev); +- return 0; +-} +- +-/* +- * This allows for a dynamic start/restart of the entire card. +- */ +-static int cops_jumpstart(struct net_device *dev) +-{ +- struct cops_local *lp = netdev_priv(dev); +- +- /* +- * Once the card has the firmware loaded and has acquired +- * the nodeid, if it is reset it will lose it all. +- */ +- cops_reset(dev,1); /* Need to reset card before load firmware. */ +- cops_load(dev); /* Load the firmware. */ +- +- /* +- * If atalkd already gave us a nodeid we will use that +- * one again, else we wait for atalkd to give us a nodeid +- * in cops_ioctl. This may cause a problem if someone steals +- * our nodeid while we are resetting. +- */ +- if(lp->nodeid == 1) +- cops_nodeid(dev,lp->node_acquire); +- +- return 0; +-} +- +-static void tangent_wait_reset(int ioaddr) +-{ +- int timeout=0; +- +- while(timeout++ < 5 && (inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) +- mdelay(1); /* Wait 1 second */ +-} +- +-/* +- * Reset the LocalTalk board. +- */ +-static void cops_reset(struct net_device *dev, int sleep) +-{ +- struct cops_local *lp = netdev_priv(dev); +- int ioaddr=dev->base_addr; +- +- if(lp->board==TANGENT) +- { +- inb(ioaddr); /* Clear request latch. */ +- outb(0,ioaddr); /* Clear the TANG_TX_READY flop. */ +- outb(0, ioaddr+TANG_RESET); /* Reset the adapter. */ +- +- tangent_wait_reset(ioaddr); +- outb(0, ioaddr+TANG_CLEAR_INT); +- } +- if(lp->board==DAYNA) +- { +- outb(0, ioaddr+DAYNA_RESET); /* Assert the reset port */ +- inb(ioaddr+DAYNA_RESET); /* Clear the reset */ +- if (sleep) +- msleep(333); +- else +- mdelay(333); +- } +- +- netif_wake_queue(dev); +-} +- +-static void cops_load (struct net_device *dev) +-{ +- struct ifreq ifr; +- struct ltfirmware *ltf= (struct ltfirmware *)&ifr.ifr_ifru; +- struct cops_local *lp = netdev_priv(dev); +- int ioaddr=dev->base_addr; +- int length, i = 0; +- +- strcpy(ifr.ifr_name,"lt0"); +- +- /* Get card's firmware code and do some checks on it. */ +-#ifdef CONFIG_COPS_DAYNA +- if(lp->board==DAYNA) +- { +- ltf->length=sizeof(ffdrv_code); +- ltf->data=ffdrv_code; +- } +- else +-#endif +-#ifdef CONFIG_COPS_TANGENT +- if(lp->board==TANGENT) +- { +- ltf->length=sizeof(ltdrv_code); +- ltf->data=ltdrv_code; +- } +- else +-#endif +- { +- printk(KERN_INFO "%s; unsupported board type.\n", dev->name); +- return; +- } +- +- /* Check to make sure firmware is correct length. */ +- if(lp->board==DAYNA && ltf->length!=5983) +- { +- printk(KERN_WARNING "%s: Firmware is not length of FFDRV.BIN.\n", dev->name); +- return; +- } +- if(lp->board==TANGENT && ltf->length!=2501) +- { +- printk(KERN_WARNING "%s: Firmware is not length of DRVCODE.BIN.\n", dev->name); +- return; +- } +- +- if(lp->board==DAYNA) +- { +- /* +- * We must wait for a status response +- * with the DAYNA board. +- */ +- while(++i<65536) +- { +- if((inb(ioaddr+DAYNA_CARD_STATUS)&3)==1) +- break; +- } +- +- if(i==65536) +- return; +- } +- +- /* +- * Upload the firmware and kick. Byte-by-byte works nicely here. +- */ +- i=0; +- length = ltf->length; +- while(length--) +- { +- outb(ltf->data[i], ioaddr); +- i++; +- } +- +- if(cops_debug > 1) +- printk("%s: Uploaded firmware - %d bytes of %d bytes.\n", +- dev->name, i, ltf->length); +- +- if(lp->board==DAYNA) /* Tell Dayna to run the firmware code. */ +- outb(1, ioaddr+DAYNA_INT_CARD); +- else /* Tell Tang to run the firmware code. */ +- inb(ioaddr); +- +- if(lp->board==TANGENT) +- { +- tangent_wait_reset(ioaddr); +- inb(ioaddr); /* Clear initial ready signal. */ +- } +-} +- +-/* +- * Get the LocalTalk Nodeid from the card. We can suggest +- * any nodeid 1-254. The card will try and get that exact +- * address else we can specify 0 as the nodeid and the card +- * will autoprobe for a nodeid. +- */ +-static int cops_nodeid (struct net_device *dev, int nodeid) +-{ +- struct cops_local *lp = netdev_priv(dev); +- int ioaddr = dev->base_addr; +- +- if(lp->board == DAYNA) +- { +- /* Empty any pending adapter responses. */ +- while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0) +- { +- outb(0, ioaddr+COPS_CLEAR_INT); /* Clear interrupts. */ +- if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST) +- cops_rx(dev); /* Kick any packets waiting. */ +- schedule(); +- } +- +- outb(2, ioaddr); /* Output command packet length as 2. */ +- outb(0, ioaddr); +- outb(LAP_INIT, ioaddr); /* Send LAP_INIT command byte. */ +- outb(nodeid, ioaddr); /* Suggest node address. */ +- } +- +- if(lp->board == TANGENT) +- { +- /* Empty any pending adapter responses. */ +- while(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY) +- { +- outb(0, ioaddr+COPS_CLEAR_INT); /* Clear interrupt. */ +- cops_rx(dev); /* Kick out packets waiting. */ +- schedule(); +- } +- +- /* Not sure what Tangent does if nodeid picked is used. */ +- if(nodeid == 0) /* Seed. */ +- nodeid = jiffies&0xFF; /* Get a random try */ +- outb(2, ioaddr); /* Command length LSB */ +- outb(0, ioaddr); /* Command length MSB */ +- outb(LAP_INIT, ioaddr); /* Send LAP_INIT byte */ +- outb(nodeid, ioaddr); /* LAP address hint. */ +- outb(0xFF, ioaddr); /* Int. level to use */ +- } +- +- lp->node_acquire=0; /* Set nodeid holder to 0. */ +- while(lp->node_acquire==0) /* Get *True* nodeid finally. */ +- { +- outb(0, ioaddr+COPS_CLEAR_INT); /* Clear any interrupt. */ +- +- if(lp->board == DAYNA) +- { +- if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST) +- cops_rx(dev); /* Grab the nodeid put in lp->node_acquire. */ +- } +- if(lp->board == TANGENT) +- { +- if(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY) +- cops_rx(dev); /* Grab the nodeid put in lp->node_acquire. */ +- } +- schedule(); +- } +- +- if(cops_debug > 1) +- printk(KERN_DEBUG "%s: Node ID %d has been acquired.\n", +- dev->name, lp->node_acquire); +- +- lp->nodeid=1; /* Set got nodeid to 1. */ +- +- return 0; +-} +- +-/* +- * Poll the Tangent type cards to see if we have work. +- */ +- +-static void cops_poll(unsigned long ltdev) +-{ +- int ioaddr, status; +- int boguscount = 0; +- +- struct net_device *dev = (struct net_device *)ltdev; +- +- del_timer(&cops_timer); +- +- if(dev == NULL) +- return; /* We've been downed */ +- +- ioaddr = dev->base_addr; +- do { +- status=inb(ioaddr+TANG_CARD_STATUS); +- if(status & TANG_RX_READY) +- cops_rx(dev); +- if(status & TANG_TX_READY) +- netif_wake_queue(dev); +- status = inb(ioaddr+TANG_CARD_STATUS); +- } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY))); +- +- /* poll 20 times per second */ +- cops_timer.expires = jiffies + HZ/20; +- add_timer(&cops_timer); +-} +- +-/* +- * The typical workload of the driver: +- * Handle the network interface interrupts. +- */ +-static irqreturn_t cops_interrupt(int irq, void *dev_id) +-{ +- struct net_device *dev = dev_id; +- struct cops_local *lp; +- int ioaddr, status; +- int boguscount = 0; +- +- ioaddr = dev->base_addr; +- lp = netdev_priv(dev); +- +- if(lp->board==DAYNA) +- { +- do { +- outb(0, ioaddr + COPS_CLEAR_INT); +- status=inb(ioaddr+DAYNA_CARD_STATUS); +- if((status&0x03)==DAYNA_RX_REQUEST) +- cops_rx(dev); +- netif_wake_queue(dev); +- } while(++boguscount < 20); +- } +- else +- { +- do { +- status=inb(ioaddr+TANG_CARD_STATUS); +- if(status & TANG_RX_READY) +- cops_rx(dev); +- if(status & TANG_TX_READY) +- netif_wake_queue(dev); +- status=inb(ioaddr+TANG_CARD_STATUS); +- } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY))); +- } +- +- return IRQ_HANDLED; +-} +- +-/* +- * We have a good packet(s), get it/them out of the buffers. +- */ +-static void cops_rx(struct net_device *dev) +-{ +- int pkt_len = 0; +- int rsp_type = 0; +- struct sk_buff *skb = NULL; +- struct cops_local *lp = netdev_priv(dev); +- int ioaddr = dev->base_addr; +- int boguscount = 0; +- unsigned long flags; +- +- +- spin_lock_irqsave(&lp->lock, flags); +- +- if(lp->board==DAYNA) +- { +- outb(0, ioaddr); /* Send out Zero length. */ +- outb(0, ioaddr); +- outb(DATA_READ, ioaddr); /* Send read command out. */ +- +- /* Wait for DMA to turn around. */ +- while(++boguscount<1000000) +- { +- barrier(); +- if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_READY) +- break; +- } +- +- if(boguscount==1000000) +- { +- printk(KERN_WARNING "%s: DMA timed out.\n",dev->name); +- spin_unlock_irqrestore(&lp->lock, flags); +- return; +- } +- } +- +- /* Get response length. */ +- if(lp->board==DAYNA) +- pkt_len = inb(ioaddr) & 0xFF; +- else +- pkt_len = inb(ioaddr) & 0x00FF; +- pkt_len |= (inb(ioaddr) << 8); +- /* Input IO code. */ +- rsp_type=inb(ioaddr); +- +- /* Malloc up new buffer. */ +- skb = dev_alloc_skb(pkt_len); +- if(skb == NULL) +- { +- printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", +- dev->name); +- dev->stats.rx_dropped++; +- while(pkt_len--) /* Discard packet */ +- inb(ioaddr); +- spin_unlock_irqrestore(&lp->lock, flags); +- return; +- } +- skb->dev = dev; +- skb_put(skb, pkt_len); +- skb->protocol = htons(ETH_P_LOCALTALK); +- +- insb(ioaddr, skb->data, pkt_len); /* Eat the Data */ +- +- if(lp->board==DAYNA) +- outb(1, ioaddr+DAYNA_INT_CARD); /* Interrupt the card */ +- +- spin_unlock_irqrestore(&lp->lock, flags); /* Restore interrupts. */ +- +- /* Check for bad response length */ +- if(pkt_len < 0 || pkt_len > MAX_LLAP_SIZE) +- { +- printk(KERN_WARNING "%s: Bad packet length of %d bytes.\n", +- dev->name, pkt_len); +- dev->stats.tx_errors++; +- dev_kfree_skb_any(skb); +- return; +- } +- +- /* Set nodeid and then get out. */ +- if(rsp_type == LAP_INIT_RSP) +- { /* Nodeid taken from received packet. */ +- lp->node_acquire = skb->data[0]; +- dev_kfree_skb_any(skb); +- return; +- } +- +- /* One last check to make sure we have a good packet. */ +- if(rsp_type != LAP_RESPONSE) +- { +- printk(KERN_WARNING "%s: Bad packet type %d.\n", dev->name, rsp_type); +- dev->stats.tx_errors++; +- dev_kfree_skb_any(skb); +- return; +- } +- +- skb_reset_mac_header(skb); /* Point to entire packet. */ +- skb_pull(skb,3); +- skb_reset_transport_header(skb); /* Point to data (Skip header). */ +- +- /* Update the counters. */ +- dev->stats.rx_packets++; +- dev->stats.rx_bytes += skb->len; +- +- /* Send packet to a higher place. */ +- netif_rx(skb); +-} +- +-static void cops_timeout(struct net_device *dev) +-{ +- struct cops_local *lp = netdev_priv(dev); +- int ioaddr = dev->base_addr; +- +- dev->stats.tx_errors++; +- if(lp->board==TANGENT) +- { +- if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) +- printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name); +- } +- printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name); +- cops_jumpstart(dev); /* Restart the card. */ +- dev->trans_start = jiffies; /* prevent tx timeout */ +- netif_wake_queue(dev); +-} +- +- +-/* +- * Make the card transmit a LocalTalk packet. +- */ +- +-static netdev_tx_t cops_send_packet(struct sk_buff *skb, +- struct net_device *dev) +-{ +- struct cops_local *lp = netdev_priv(dev); +- int ioaddr = dev->base_addr; +- unsigned long flags; +- +- /* +- * Block a timer-based transmit from overlapping. +- */ +- +- netif_stop_queue(dev); +- +- spin_lock_irqsave(&lp->lock, flags); +- if(lp->board == DAYNA) /* Wait for adapter transmit buffer. */ +- while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0) +- cpu_relax(); +- if(lp->board == TANGENT) /* Wait for adapter transmit buffer. */ +- while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) +- cpu_relax(); +- +- /* Output IO length. */ +- outb(skb->len, ioaddr); +- if(lp->board == DAYNA) +- outb(skb->len >> 8, ioaddr); +- else +- outb((skb->len >> 8)&0x0FF, ioaddr); +- +- /* Output IO code. */ +- outb(LAP_WRITE, ioaddr); +- +- if(lp->board == DAYNA) /* Check the transmit buffer again. */ +- while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0); +- +- outsb(ioaddr, skb->data, skb->len); /* Send out the data. */ +- +- if(lp->board==DAYNA) /* Dayna requires you kick the card */ +- outb(1, ioaddr+DAYNA_INT_CARD); +- +- spin_unlock_irqrestore(&lp->lock, flags); /* Restore interrupts. */ +- +- /* Done sending packet, update counters and cleanup. */ +- dev->stats.tx_packets++; +- dev->stats.tx_bytes += skb->len; +- dev_kfree_skb (skb); +- return NETDEV_TX_OK; +-} +- +-/* +- * Dummy function to keep the Appletalk layer happy. +- */ +- +-static void set_multicast_list(struct net_device *dev) +-{ +- if(cops_debug >= 3) +- printk("%s: set_multicast_list executed\n", dev->name); +-} +- +-/* +- * System ioctls for the COPS LocalTalk card. +- */ +- +-static int cops_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +-{ +- struct cops_local *lp = netdev_priv(dev); +- struct sockaddr_at *sa = (struct sockaddr_at *)&ifr->ifr_addr; +- struct atalk_addr *aa = (struct atalk_addr *)&lp->node_addr; +- +- switch(cmd) +- { +- case SIOCSIFADDR: +- /* Get and set the nodeid and network # atalkd wants. */ +- cops_nodeid(dev, sa->sat_addr.s_node); +- aa->s_net = sa->sat_addr.s_net; +- aa->s_node = lp->node_acquire; +- +- /* Set broardcast address. */ +- dev->broadcast[0] = 0xFF; +- +- /* Set hardware address. */ +- dev->dev_addr[0] = aa->s_node; +- dev->addr_len = 1; +- return 0; +- +- case SIOCGIFADDR: +- sa->sat_addr.s_net = aa->s_net; +- sa->sat_addr.s_node = aa->s_node; +- return 0; +- +- default: +- return -EOPNOTSUPP; +- } +-} +- +-/* +- * The inverse routine to cops_open(). +- */ +- +-static int cops_close(struct net_device *dev) +-{ +- struct cops_local *lp = netdev_priv(dev); +- +- /* If we were running polled, yank the timer. +- */ +- if(lp->board==TANGENT && dev->irq==0) +- del_timer(&cops_timer); +- +- netif_stop_queue(dev); +- return 0; +-} +- +- +-#ifdef MODULE +-static struct net_device *cops_dev; +- +-MODULE_LICENSE("GPL"); +-module_param(io, int, 0); +-module_param(irq, int, 0); +-module_param(board_type, int, 0); +- +-static int __init cops_module_init(void) +-{ +- if (io == 0) +- printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n", +- cardname); +- cops_dev = cops_probe(-1); +- if (IS_ERR(cops_dev)) +- return PTR_ERR(cops_dev); +- return 0; +-} +- +-static void __exit cops_module_exit(void) +-{ +- unregister_netdev(cops_dev); +- cleanup_card(cops_dev); +- free_netdev(cops_dev); +-} +-module_init(cops_module_init); +-module_exit(cops_module_exit); +-#endif /* MODULE */ +diff --git a/drivers/net/appletalk/cops.h b/drivers/net/appletalk/cops.h +deleted file mode 100644 +index fd2750b..0000000 +--- a/drivers/net/appletalk/cops.h ++++ /dev/null +@@ -1,60 +0,0 @@ +-/* cops.h: LocalTalk driver for Linux. +- * +- * Authors: +- * - Jay Schulist +- */ +- +-#ifndef __LINUX_COPSLTALK_H +-#define __LINUX_COPSLTALK_H +- +-#ifdef __KERNEL__ +- +-/* Max LLAP size we will accept. */ +-#define MAX_LLAP_SIZE 603 +- +-/* Tangent */ +-#define TANG_CARD_STATUS 1 +-#define TANG_CLEAR_INT 1 +-#define TANG_RESET 3 +- +-#define TANG_TX_READY 1 +-#define TANG_RX_READY 2 +- +-/* Dayna */ +-#define DAYNA_CMD_DATA 0 +-#define DAYNA_CLEAR_INT 1 +-#define DAYNA_CARD_STATUS 2 +-#define DAYNA_INT_CARD 3 +-#define DAYNA_RESET 4 +- +-#define DAYNA_RX_READY 0 +-#define DAYNA_TX_READY 1 +-#define DAYNA_RX_REQUEST 3 +- +-/* Same on both card types */ +-#define COPS_CLEAR_INT 1 +- +-/* LAP response codes received from the cards. */ +-#define LAP_INIT 1 /* Init cmd */ +-#define LAP_INIT_RSP 2 /* Init response */ +-#define LAP_WRITE 3 /* Write cmd */ +-#define DATA_READ 4 /* Data read */ +-#define LAP_RESPONSE 4 /* Received ALAP frame response */ +-#define LAP_GETSTAT 5 /* Get LAP and HW status */ +-#define LAP_RSPSTAT 6 /* Status response */ +- +-#endif +- +-/* +- * Structure to hold the firmware information. +- */ +-struct ltfirmware +-{ +- unsigned int length; +- const unsigned char *data; +-}; +- +-#define DAYNA 1 +-#define TANGENT 2 +- +-#endif +diff --git a/drivers/net/appletalk/cops_ffdrv.h b/drivers/net/appletalk/cops_ffdrv.h +deleted file mode 100644 +index b020050..0000000 +--- a/drivers/net/appletalk/cops_ffdrv.h ++++ /dev/null +@@ -1,532 +0,0 @@ +- +-/* +- * The firmware this driver downloads into the Localtalk card is a +- * separate program and is not GPL'd source code, even though the Linux +- * side driver and the routine that loads this data into the card are. +- * +- * It is taken from the COPS SDK and is under the following license +- * +- * This material is licensed to you strictly for use in conjunction with +- * the use of COPS LocalTalk adapters. +- * There is no charge for this SDK. And no waranty express or implied +- * about its fitness for any purpose. However, we will cheerefully +- * refund every penny you paid for this SDK... +- * Regards, +- * +- * Thomas F. Divine +- * Chief Scientist +- */ +- +- +-/* cops_ffdrv.h: LocalTalk driver firmware dump for Linux. +- * +- * Authors: +- * - Jay Schulist +- */ +- +- +-#ifdef CONFIG_COPS_DAYNA +- +-static const unsigned char ffdrv_code[] = { +- 58,3,0,50,228,149,33,255,255,34,226,149, +- 249,17,40,152,33,202,154,183,237,82,77,68, +- 11,107,98,19,54,0,237,176,175,50,80,0, +- 62,128,237,71,62,32,237,57,51,62,12,237, +- 57,50,237,57,54,62,6,237,57,52,62,12, +- 237,57,49,33,107,137,34,32,128,33,83,130, +- 34,40,128,33,86,130,34,42,128,33,112,130, +- 34,36,128,33,211,130,34,38,128,62,0,237, +- 57,16,33,63,148,34,34,128,237,94,205,15, +- 130,251,205,168,145,24,141,67,111,112,121,114, +- 105,103,104,116,32,40,67,41,32,49,57,56, +- 56,32,45,32,68,97,121,110,97,32,67,111, +- 109,109,117,110,105,99,97,116,105,111,110,115, +- 32,32,32,65,108,108,32,114,105,103,104,116, +- 115,32,114,101,115,101,114,118,101,100,46,32, +- 32,40,68,40,68,7,16,8,34,7,22,6, +- 16,5,12,4,8,3,6,140,0,16,39,128, +- 0,4,96,10,224,6,0,7,126,2,64,11, +- 118,12,6,13,0,14,193,15,0,5,96,3, +- 192,1,64,9,8,62,9,211,66,62,192,211, +- 66,62,100,61,32,253,6,28,33,205,129,14, +- 66,237,163,194,253,129,6,28,33,205,129,14, +- 64,237,163,194,9,130,201,62,47,50,71,152, +- 62,47,211,68,58,203,129,237,57,20,58,204, +- 129,237,57,21,33,77,152,54,132,205,233,129, +- 58,228,149,254,209,40,6,56,4,62,0,24, +- 2,219,96,33,233,149,119,230,62,33,232,149, +- 119,213,33,8,152,17,7,0,25,119,19,25, +- 119,209,201,251,237,77,245,197,213,229,221,229, +- 205,233,129,62,1,50,106,137,205,158,139,221, +- 225,225,209,193,241,251,237,77,245,197,213,219, +- 72,237,56,16,230,46,237,57,16,237,56,12, +- 58,72,152,183,32,26,6,20,17,128,2,237, +- 56,46,187,32,35,237,56,47,186,32,29,219, +- 72,230,1,32,3,5,32,232,175,50,72,152, +- 229,221,229,62,1,50,106,137,205,158,139,221, +- 225,225,24,25,62,1,50,72,152,58,201,129, +- 237,57,12,58,202,129,237,57,13,237,56,16, +- 246,17,237,57,16,209,193,241,251,237,77,245, +- 197,229,213,221,229,237,56,16,230,17,237,57, +- 16,237,56,20,58,34,152,246,16,246,8,211, +- 68,62,6,61,32,253,58,34,152,246,8,211, +- 68,58,203,129,237,57,20,58,204,129,237,57, +- 21,237,56,16,246,34,237,57,16,221,225,209, +- 225,193,241,251,237,77,33,2,0,57,126,230, +- 3,237,100,1,40,2,246,128,230,130,245,62, +- 5,211,64,241,211,64,201,229,213,243,237,56, +- 16,230,46,237,57,16,237,56,12,251,70,35, +- 35,126,254,175,202,77,133,254,129,202,15,133, +- 230,128,194,191,132,43,58,44,152,119,33,76, +- 152,119,35,62,132,119,120,254,255,40,4,58, +- 49,152,119,219,72,43,43,112,17,3,0,237, +- 56,52,230,248,237,57,52,219,72,230,1,194, +- 141,131,209,225,237,56,52,246,6,237,57,52, +- 62,1,55,251,201,62,3,211,66,62,192,211, +- 66,62,48,211,66,0,0,219,66,230,1,40, +- 4,219,67,24,240,205,203,135,58,75,152,254, +- 255,202,128,132,58,49,152,254,161,250,207,131, +- 58,34,152,211,68,62,10,211,66,62,128,211, +- 66,62,11,211,66,62,6,211,66,24,0,62, +- 14,211,66,62,33,211,66,62,1,211,66,62, +- 64,211,66,62,3,211,66,62,209,211,66,62, +- 100,71,219,66,230,1,32,6,5,32,247,195, +- 248,132,219,67,71,58,44,152,184,194,248,132, +- 62,100,71,219,66,230,1,32,6,5,32,247, +- 195,248,132,219,67,62,100,71,219,66,230,1, +- 32,6,5,32,247,195,248,132,219,67,254,133, +- 32,7,62,0,50,74,152,24,17,254,173,32, +- 7,62,1,50,74,152,24,6,254,141,194,248, +- 132,71,209,225,58,49,152,254,132,32,10,62, +- 50,205,2,134,205,144,135,24,27,254,140,32, +- 15,62,110,205,2,134,62,141,184,32,5,205, +- 144,135,24,8,62,10,205,2,134,205,8,134, +- 62,1,50,106,137,205,158,139,237,56,52,246, +- 6,237,57,52,175,183,251,201,62,20,135,237, +- 57,20,175,237,57,21,237,56,16,246,2,237, +- 57,16,237,56,20,95,237,56,21,123,254,10, +- 48,244,237,56,16,230,17,237,57,16,209,225, +- 205,144,135,62,1,50,106,137,205,158,139,237, +- 56,52,246,6,237,57,52,175,183,251,201,209, +- 225,243,219,72,230,1,40,13,62,10,211,66, +- 0,0,219,66,230,192,202,226,132,237,56,52, +- 246,6,237,57,52,62,1,55,251,201,205,203, +- 135,62,1,50,106,137,205,158,139,237,56,52, +- 246,6,237,57,52,183,251,201,209,225,62,1, +- 50,106,137,205,158,139,237,56,52,246,6,237, +- 57,52,62,2,55,251,201,209,225,243,219,72, +- 230,1,202,213,132,62,10,211,66,0,0,219, +- 66,230,192,194,213,132,229,62,1,50,106,137, +- 42,40,152,205,65,143,225,17,3,0,205,111, +- 136,62,6,211,66,58,44,152,211,66,237,56, +- 52,246,6,237,57,52,183,251,201,209,197,237, +- 56,52,230,248,237,57,52,219,72,230,1,32, +- 15,193,225,237,56,52,246,6,237,57,52,62, +- 1,55,251,201,14,23,58,37,152,254,0,40, +- 14,14,2,254,1,32,5,62,140,119,24,3, +- 62,132,119,43,43,197,205,203,135,193,62,1, +- 211,66,62,64,211,66,62,3,211,66,62,193, +- 211,66,62,100,203,39,71,219,66,230,1,32, +- 6,5,32,247,195,229,133,33,238,151,219,67, +- 71,58,44,152,184,194,229,133,119,62,100,71, +- 219,66,230,1,32,6,5,32,247,195,229,133, +- 219,67,35,119,13,32,234,193,225,62,1,50, +- 106,137,205,158,139,237,56,52,246,6,237,57, +- 52,175,183,251,201,33,234,151,35,35,62,255, +- 119,193,225,62,1,50,106,137,205,158,139,237, +- 56,52,246,6,237,57,52,175,251,201,243,61, +- 32,253,251,201,62,3,211,66,62,192,211,66, +- 58,49,152,254,140,32,19,197,229,213,17,181, +- 129,33,185,129,1,2,0,237,176,209,225,193, +- 24,27,229,213,33,187,129,58,49,152,230,15, +- 87,30,2,237,92,25,17,181,129,126,18,19, +- 35,126,18,209,225,58,34,152,246,8,211,68, +- 58,49,152,254,165,40,14,254,164,40,10,62, +- 10,211,66,62,224,211,66,24,25,58,74,152, +- 254,0,40,10,62,10,211,66,62,160,211,66, +- 24,8,62,10,211,66,62,128,211,66,62,11, +- 211,66,62,6,211,66,205,147,143,62,5,211, +- 66,62,224,211,66,62,5,211,66,62,96,211, +- 66,62,5,61,32,253,62,5,211,66,62,224, +- 211,66,62,14,61,32,253,62,5,211,66,62, +- 233,211,66,62,128,211,66,58,181,129,61,32, +- 253,62,1,211,66,62,192,211,66,1,254,19, +- 237,56,46,187,32,6,13,32,247,195,226,134, +- 62,192,211,66,0,0,219,66,203,119,40,250, +- 219,66,203,87,40,250,243,237,56,16,230,17, +- 237,57,16,237,56,20,251,62,5,211,66,62, +- 224,211,66,58,182,129,61,32,253,229,33,181, +- 129,58,183,129,203,63,119,35,58,184,129,119, +- 225,62,10,211,66,62,224,211,66,62,11,211, +- 66,62,118,211,66,62,47,211,68,62,5,211, +- 66,62,233,211,66,58,181,129,61,32,253,62, +- 5,211,66,62,224,211,66,58,182,129,61,32, +- 253,62,5,211,66,62,96,211,66,201,229,213, +- 58,50,152,230,15,87,30,2,237,92,33,187, +- 129,25,17,181,129,126,18,35,19,126,18,209, +- 225,58,71,152,246,8,211,68,58,50,152,254, +- 165,40,14,254,164,40,10,62,10,211,66,62, +- 224,211,66,24,8,62,10,211,66,62,128,211, +- 66,62,11,211,66,62,6,211,66,195,248,135, +- 62,3,211,66,62,192,211,66,197,229,213,17, +- 181,129,33,183,129,1,2,0,237,176,209,225, +- 193,62,47,211,68,62,10,211,66,62,224,211, +- 66,62,11,211,66,62,118,211,66,62,1,211, +- 66,62,0,211,66,205,147,143,195,16,136,62, +- 3,211,66,62,192,211,66,197,229,213,17,181, +- 129,33,183,129,1,2,0,237,176,209,225,193, +- 62,47,211,68,62,10,211,66,62,224,211,66, +- 62,11,211,66,62,118,211,66,205,147,143,62, +- 5,211,66,62,224,211,66,62,5,211,66,62, +- 96,211,66,62,5,61,32,253,62,5,211,66, +- 62,224,211,66,62,14,61,32,253,62,5,211, +- 66,62,233,211,66,62,128,211,66,58,181,129, +- 61,32,253,62,1,211,66,62,192,211,66,1, +- 254,19,237,56,46,187,32,6,13,32,247,195, +- 88,136,62,192,211,66,0,0,219,66,203,119, +- 40,250,219,66,203,87,40,250,62,5,211,66, +- 62,224,211,66,58,182,129,61,32,253,62,5, +- 211,66,62,96,211,66,201,197,14,67,6,0, +- 62,3,211,66,62,192,211,66,62,48,211,66, +- 0,0,219,66,230,1,40,4,219,67,24,240, +- 62,5,211,66,62,233,211,66,62,128,211,66, +- 58,181,129,61,32,253,237,163,29,62,192,211, +- 66,219,66,230,4,40,250,237,163,29,32,245, +- 219,66,230,4,40,250,62,255,71,219,66,230, +- 4,40,3,5,32,247,219,66,230,4,40,250, +- 62,5,211,66,62,224,211,66,58,182,129,61, +- 32,253,62,5,211,66,62,96,211,66,58,71, +- 152,254,1,202,18,137,62,16,211,66,62,56, +- 211,66,62,14,211,66,62,33,211,66,62,1, +- 211,66,62,248,211,66,237,56,48,246,153,230, +- 207,237,57,48,62,3,211,66,62,221,211,66, +- 193,201,58,71,152,211,68,62,10,211,66,62, +- 128,211,66,62,11,211,66,62,6,211,66,62, +- 6,211,66,58,44,152,211,66,62,16,211,66, +- 62,56,211,66,62,48,211,66,0,0,62,14, +- 211,66,62,33,211,66,62,1,211,66,62,248, +- 211,66,237,56,48,246,145,246,8,230,207,237, +- 57,48,62,3,211,66,62,221,211,66,193,201, +- 44,3,1,0,70,69,1,245,197,213,229,175, +- 50,72,152,237,56,16,230,46,237,57,16,237, +- 56,12,62,1,211,66,0,0,219,66,95,230, +- 160,32,3,195,20,139,123,230,96,194,72,139, +- 62,48,211,66,62,1,211,66,62,64,211,66, +- 237,91,40,152,205,207,143,25,43,55,237,82, +- 218,70,139,34,42,152,98,107,58,44,152,190, +- 194,210,138,35,35,62,130,190,194,200,137,62, +- 1,50,48,152,62,175,190,202,82,139,62,132, +- 190,32,44,50,50,152,62,47,50,71,152,229, +- 175,50,106,137,42,40,152,205,65,143,225,54, +- 133,43,70,58,44,152,119,43,112,17,3,0, +- 62,10,205,2,134,205,111,136,195,158,138,62, +- 140,190,32,19,50,50,152,58,233,149,230,4, +- 202,222,138,62,1,50,71,152,195,219,137,126, +- 254,160,250,185,138,254,166,242,185,138,50,50, +- 152,43,126,35,229,213,33,234,149,95,22,0, +- 25,126,254,132,40,18,254,140,40,14,58,50, +- 152,230,15,87,126,31,21,242,65,138,56,2, +- 175,119,58,50,152,230,15,87,58,233,149,230, +- 62,31,21,242,85,138,218,98,138,209,225,195, +- 20,139,58,50,152,33,100,137,230,15,95,22, +- 0,25,126,50,71,152,209,225,58,50,152,254, +- 164,250,135,138,58,73,152,254,0,40,4,54, +- 173,24,2,54,133,43,70,58,44,152,119,43, +- 112,17,3,0,205,70,135,175,50,106,137,205, +- 208,139,58,199,129,237,57,12,58,200,129,237, +- 57,13,237,56,16,246,17,237,57,16,225,209, +- 193,241,251,237,77,62,129,190,194,227,138,54, +- 130,43,70,58,44,152,119,43,112,17,3,0, +- 205,144,135,195,20,139,35,35,126,254,132,194, +- 227,138,175,50,106,137,205,158,139,24,42,58, +- 201,154,254,1,40,7,62,1,50,106,137,24, +- 237,58,106,137,254,1,202,222,138,62,128,166, +- 194,222,138,221,229,221,33,67,152,205,127,142, +- 205,109,144,221,225,225,209,193,241,251,237,77, +- 58,106,137,254,1,202,44,139,58,50,152,254, +- 164,250,44,139,58,73,152,238,1,50,73,152, +- 221,229,221,33,51,152,205,127,142,221,225,62, +- 1,50,106,137,205,158,139,195,13,139,24,208, +- 24,206,24,204,230,64,40,3,195,20,139,195, +- 20,139,43,126,33,8,152,119,35,58,44,152, +- 119,43,237,91,35,152,205,203,135,205,158,139, +- 195,13,139,175,50,78,152,62,3,211,66,62, +- 192,211,66,201,197,33,4,0,57,126,35,102, +- 111,62,1,50,106,137,219,72,205,141,139,193, +- 201,62,1,50,78,152,34,40,152,54,0,35, +- 35,54,0,195,163,139,58,78,152,183,200,229, +- 33,181,129,58,183,129,119,35,58,184,129,119, +- 225,62,47,211,68,62,14,211,66,62,193,211, +- 66,62,10,211,66,62,224,211,66,62,11,211, +- 66,62,118,211,66,195,3,140,58,78,152,183, +- 200,58,71,152,211,68,254,69,40,4,254,70, +- 32,17,58,73,152,254,0,40,10,62,10,211, +- 66,62,160,211,66,24,8,62,10,211,66,62, +- 128,211,66,62,11,211,66,62,6,211,66,62, +- 6,211,66,58,44,152,211,66,62,16,211,66, +- 62,56,211,66,62,48,211,66,0,0,219,66, +- 230,1,40,4,219,67,24,240,62,14,211,66, +- 62,33,211,66,42,40,152,205,65,143,62,1, +- 211,66,62,248,211,66,237,56,48,246,145,246, +- 8,230,207,237,57,48,62,3,211,66,62,221, +- 211,66,201,62,16,211,66,62,56,211,66,62, +- 48,211,66,0,0,219,66,230,1,40,4,219, +- 67,24,240,62,14,211,66,62,33,211,66,62, +- 1,211,66,62,248,211,66,237,56,48,246,153, +- 230,207,237,57,48,62,3,211,66,62,221,211, +- 66,201,229,213,33,234,149,95,22,0,25,126, +- 254,132,40,4,254,140,32,2,175,119,123,209, +- 225,201,6,8,14,0,31,48,1,12,16,250, +- 121,201,33,4,0,57,94,35,86,33,2,0, +- 57,126,35,102,111,221,229,34,89,152,237,83, +- 91,152,221,33,63,152,205,127,142,58,81,152, +- 50,82,152,58,80,152,135,50,80,152,205,162, +- 140,254,3,56,16,58,81,152,135,60,230,15, +- 50,81,152,175,50,80,152,24,23,58,79,152, +- 205,162,140,254,3,48,13,58,81,152,203,63, +- 50,81,152,62,255,50,79,152,58,81,152,50, +- 82,152,58,79,152,135,50,79,152,62,32,50, +- 83,152,50,84,152,237,56,16,230,17,237,57, +- 16,219,72,62,192,50,93,152,62,93,50,94, +- 152,58,93,152,61,50,93,152,32,9,58,94, +- 152,61,50,94,152,40,44,62,170,237,57,20, +- 175,237,57,21,237,56,16,246,2,237,57,16, +- 219,72,230,1,202,29,141,237,56,20,71,237, +- 56,21,120,254,10,48,237,237,56,16,230,17, +- 237,57,16,243,62,14,211,66,62,65,211,66, +- 251,58,39,152,23,23,60,50,39,152,71,58, +- 82,152,160,230,15,40,22,71,14,10,219,66, +- 230,16,202,186,141,219,72,230,1,202,186,141, +- 13,32,239,16,235,42,89,152,237,91,91,152, +- 205,47,131,48,7,61,202,186,141,195,227,141, +- 221,225,33,0,0,201,221,33,55,152,205,127, +- 142,58,84,152,61,50,84,152,40,19,58,82, +- 152,246,1,50,82,152,58,79,152,246,1,50, +- 79,152,195,29,141,221,225,33,1,0,201,221, +- 33,59,152,205,127,142,58,80,152,246,1,50, +- 80,152,58,82,152,135,246,1,50,82,152,58, +- 83,152,61,50,83,152,194,29,141,221,225,33, +- 2,0,201,221,229,33,0,0,57,17,4,0, +- 25,126,50,44,152,230,128,50,85,152,58,85, +- 152,183,40,6,221,33,88,2,24,4,221,33, +- 150,0,58,44,152,183,40,53,60,40,50,60, +- 40,47,61,61,33,86,152,119,35,119,35,54, +- 129,175,50,48,152,221,43,221,229,225,124,181, +- 40,42,33,86,152,17,3,0,205,189,140,17, +- 232,3,27,123,178,32,251,58,48,152,183,40, +- 224,58,44,152,71,62,7,128,230,127,71,58, +- 85,152,176,50,44,152,24,162,221,225,201,183, +- 221,52,0,192,221,52,1,192,221,52,2,192, +- 221,52,3,192,55,201,245,62,1,211,100,241, +- 201,245,62,1,211,96,241,201,33,2,0,57, +- 126,35,102,111,237,56,48,230,175,237,57,48, +- 62,48,237,57,49,125,237,57,32,124,237,57, +- 33,62,0,237,57,34,62,88,237,57,35,62, +- 0,237,57,36,237,57,37,33,128,2,125,237, +- 57,38,124,237,57,39,237,56,48,246,97,230, +- 207,237,57,48,62,0,237,57,0,62,0,211, +- 96,211,100,201,33,2,0,57,126,35,102,111, +- 237,56,48,230,175,237,57,48,62,12,237,57, +- 49,62,76,237,57,32,62,0,237,57,33,237, +- 57,34,125,237,57,35,124,237,57,36,62,0, +- 237,57,37,33,128,2,125,237,57,38,124,237, +- 57,39,237,56,48,246,97,230,207,237,57,48, +- 62,1,211,96,201,33,2,0,57,126,35,102, +- 111,229,237,56,48,230,87,237,57,48,125,237, +- 57,40,124,237,57,41,62,0,237,57,42,62, +- 67,237,57,43,62,0,237,57,44,58,106,137, +- 254,1,32,5,33,6,0,24,3,33,128,2, +- 125,237,57,46,124,237,57,47,237,56,50,230, +- 252,246,2,237,57,50,225,201,33,4,0,57, +- 94,35,86,33,2,0,57,126,35,102,111,237, +- 56,48,230,87,237,57,48,125,237,57,40,124, +- 237,57,41,62,0,237,57,42,62,67,237,57, +- 43,62,0,237,57,44,123,237,57,46,122,237, +- 57,47,237,56,50,230,244,246,0,237,57,50, +- 237,56,48,246,145,230,207,237,57,48,201,213, +- 237,56,46,95,237,56,47,87,237,56,46,111, +- 237,56,47,103,183,237,82,32,235,33,128,2, +- 183,237,82,209,201,213,237,56,38,95,237,56, +- 39,87,237,56,38,111,237,56,39,103,183,237, +- 82,32,235,33,128,2,183,237,82,209,201,245, +- 197,1,52,0,237,120,230,253,237,121,193,241, +- 201,245,197,1,52,0,237,120,246,2,237,121, +- 193,241,201,33,2,0,57,126,35,102,111,126, +- 35,110,103,201,33,0,0,34,102,152,34,96, +- 152,34,98,152,33,202,154,34,104,152,237,91, +- 104,152,42,226,149,183,237,82,17,0,255,25, +- 34,100,152,203,124,40,6,33,0,125,34,100, +- 152,42,104,152,35,35,35,229,205,120,139,193, +- 201,205,186,149,229,42,40,152,35,35,35,229, +- 205,39,144,193,124,230,3,103,221,117,254,221, +- 116,255,237,91,42,152,35,35,35,183,237,82, +- 32,12,17,5,0,42,42,152,205,171,149,242, +- 169,144,42,40,152,229,205,120,139,193,195,198, +- 149,237,91,42,152,42,98,152,25,34,98,152, +- 19,19,19,42,102,152,25,34,102,152,237,91, +- 100,152,33,158,253,25,237,91,102,152,205,171, +- 149,242,214,144,33,0,0,34,102,152,62,1, +- 50,95,152,205,225,144,195,198,149,58,95,152, +- 183,200,237,91,96,152,42,102,152,205,171,149, +- 242,5,145,237,91,102,152,33,98,2,25,237, +- 91,96,152,205,171,149,250,37,145,237,91,96, +- 152,42,102,152,183,237,82,32,7,42,98,152, +- 125,180,40,13,237,91,102,152,42,96,152,205, +- 171,149,242,58,145,237,91,104,152,42,102,152, +- 25,35,35,35,229,205,120,139,193,175,50,95, +- 152,201,195,107,139,205,206,149,250,255,243,205, +- 225,144,251,58,230,149,183,194,198,149,17,1, +- 0,42,98,152,205,171,149,250,198,149,62,1, +- 50,230,149,237,91,96,152,42,104,152,25,221, +- 117,252,221,116,253,237,91,104,152,42,96,152, +- 25,35,35,35,221,117,254,221,116,255,35,35, +- 35,229,205,39,144,124,230,3,103,35,35,35, +- 221,117,250,221,116,251,235,221,110,252,221,102, +- 253,115,35,114,35,54,4,62,1,211,100,211, +- 84,195,198,149,33,0,0,34,102,152,34,96, +- 152,34,98,152,33,202,154,34,104,152,237,91, +- 104,152,42,226,149,183,237,82,17,0,255,25, +- 34,100,152,33,109,152,54,0,33,107,152,229, +- 205,240,142,193,62,47,50,34,152,62,132,50, +- 49,152,205,241,145,205,61,145,58,39,152,60, +- 50,39,152,24,241,205,206,149,251,255,33,109, +- 152,126,183,202,198,149,110,221,117,251,33,109, +- 152,54,0,221,126,251,254,1,40,28,254,3, +- 40,101,254,4,202,190,147,254,5,202,147,147, +- 254,8,40,87,33,107,152,229,205,240,142,195, +- 198,149,58,201,154,183,32,21,33,111,152,126, +- 50,229,149,205,52,144,33,110,152,110,38,0, +- 229,205,11,142,193,237,91,96,152,42,104,152, +- 25,221,117,254,221,116,255,35,35,54,2,17, +- 2,0,43,43,115,35,114,58,44,152,35,35, +- 119,58,228,149,35,119,62,1,211,100,211,84, +- 62,1,50,201,154,24,169,205,153,142,58,231, +- 149,183,40,250,175,50,231,149,33,110,152,126, +- 254,255,40,91,58,233,149,230,63,183,40,83, +- 94,22,0,33,234,149,25,126,183,40,13,33, +- 110,152,94,33,234,150,25,126,254,3,32,36, +- 205,81,148,125,180,33,110,152,94,22,0,40, +- 17,33,234,149,25,54,0,33,107,152,229,205, +- 240,142,193,195,198,149,33,234,150,25,54,0, +- 33,110,152,94,22,0,33,234,149,25,126,50, +- 49,152,254,132,32,37,62,47,50,34,152,42, +- 107,152,229,33,110,152,229,205,174,140,193,193, +- 125,180,33,110,152,94,22,0,33,234,150,202, +- 117,147,25,52,195,120,147,58,49,152,254,140, +- 32,7,62,1,50,34,152,24,210,62,32,50, +- 106,152,24,19,58,49,152,95,58,106,152,163, +- 183,58,106,152,32,11,203,63,50,106,152,58, +- 106,152,183,32,231,254,2,40,51,254,4,40, +- 38,254,8,40,26,254,16,40,13,254,32,32, +- 158,62,165,50,49,152,62,69,24,190,62,164, +- 50,49,152,62,70,24,181,62,163,50,49,152, +- 175,24,173,62,162,50,49,152,62,1,24,164, +- 62,161,50,49,152,62,3,24,155,25,54,0, +- 221,126,251,254,8,40,7,58,230,149,183,202, +- 32,146,33,107,152,229,205,240,142,193,211,84, +- 195,198,149,237,91,96,152,42,104,152,25,221, +- 117,254,221,116,255,35,35,54,6,17,2,0, +- 43,43,115,35,114,58,228,149,35,35,119,58, +- 233,149,35,119,205,146,142,195,32,146,237,91, +- 96,152,42,104,152,25,229,205,160,142,193,58, +- 231,149,183,40,250,175,50,231,149,243,237,91, +- 96,152,42,104,152,25,221,117,254,221,116,255, +- 78,35,70,221,113,252,221,112,253,89,80,42, +- 98,152,183,237,82,34,98,152,203,124,40,19, +- 33,0,0,34,98,152,34,102,152,34,96,152, +- 62,1,50,95,152,24,40,221,94,252,221,86, +- 253,19,19,19,42,96,152,25,34,96,152,237, +- 91,100,152,33,158,253,25,237,91,96,152,205, +- 171,149,242,55,148,33,0,0,34,96,152,175, +- 50,230,149,251,195,32,146,245,62,1,50,231, +- 149,62,16,237,57,0,211,80,241,251,237,77, +- 201,205,186,149,229,229,33,0,0,34,37,152, +- 33,110,152,126,50,234,151,58,44,152,33,235, +- 151,119,221,54,253,0,221,54,254,0,195,230, +- 148,33,236,151,54,175,33,3,0,229,33,234, +- 151,229,205,174,140,193,193,33,236,151,126,254, +- 255,40,74,33,245,151,110,221,117,255,33,249, +- 151,126,221,166,255,221,119,255,33,253,151,126, +- 221,166,255,221,119,255,58,232,149,95,221,126, +- 255,163,221,119,255,183,40,15,230,191,33,110, +- 152,94,22,0,33,234,149,25,119,24,12,33, +- 110,152,94,22,0,33,234,149,25,54,132,33, +- 0,0,195,198,149,221,110,253,221,102,254,35, +- 221,117,253,221,116,254,17,32,0,221,110,253, +- 221,102,254,205,171,149,250,117,148,58,233,149, +- 203,87,40,84,33,1,0,34,37,152,221,54, +- 253,0,221,54,254,0,24,53,33,236,151,54, +- 175,33,3,0,229,33,234,151,229,205,174,140, +- 193,193,33,236,151,126,254,255,40,14,33,110, +- 152,94,22,0,33,234,149,25,54,140,24,159, +- 221,110,253,221,102,254,35,221,117,253,221,116, +- 254,17,32,0,221,110,253,221,102,254,205,171, +- 149,250,12,149,33,2,0,34,37,152,221,54, +- 253,0,221,54,254,0,24,54,33,236,151,54, +- 175,33,3,0,229,33,234,151,229,205,174,140, +- 193,193,33,236,151,126,254,255,40,15,33,110, +- 152,94,22,0,33,234,149,25,54,132,195,211, +- 148,221,110,253,221,102,254,35,221,117,253,221, +- 116,254,17,32,0,221,110,253,221,102,254,205, +- 171,149,250,96,149,33,1,0,195,198,149,124, +- 170,250,179,149,237,82,201,124,230,128,237,82, +- 60,201,225,253,229,221,229,221,33,0,0,221, +- 57,233,221,249,221,225,253,225,201,233,225,253, +- 229,221,229,221,33,0,0,221,57,94,35,86, +- 35,235,57,249,235,233,0,0,0,0,0,0, +- 62,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 175,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,133,1,0,0,0,63, +- 255,255,255,255,0,0,0,63,0,0,0,0, +- 0,0,0,0,0,0,0,24,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0 +- } ; +- +-#endif +diff --git a/drivers/net/appletalk/cops_ltdrv.h b/drivers/net/appletalk/cops_ltdrv.h +deleted file mode 100644 +index c699b1a..0000000 +--- a/drivers/net/appletalk/cops_ltdrv.h ++++ /dev/null +@@ -1,241 +0,0 @@ +-/* +- * The firmware this driver downloads into the Localtalk card is a +- * separate program and is not GPL'd source code, even though the Linux +- * side driver and the routine that loads this data into the card are. +- * +- * It is taken from the COPS SDK and is under the following license +- * +- * This material is licensed to you strictly for use in conjunction with +- * the use of COPS LocalTalk adapters. +- * There is no charge for this SDK. And no waranty express or implied +- * about its fitness for any purpose. However, we will cheerefully +- * refund every penny you paid for this SDK... +- * Regards, +- * +- * Thomas F. Divine +- * Chief Scientist +- */ +- +- +-/* cops_ltdrv.h: LocalTalk driver firmware dump for Linux. +- * +- * Authors: +- * - Jay Schulist +- */ +- +- +-#ifdef CONFIG_COPS_TANGENT +- +-static const unsigned char ltdrv_code[] = { +- 58,3,0,50,148,10,33,143,15,62,85,119, +- 190,32,9,62,170,119,190,32,3,35,24,241, +- 34,146,10,249,17,150,10,33,143,15,183,237, +- 82,77,68,11,107,98,19,54,0,237,176,62, +- 16,237,57,51,62,0,237,57,50,237,57,54, +- 62,12,237,57,49,62,195,33,39,2,50,56, +- 0,34,57,0,237,86,205,30,2,251,205,60, +- 10,24,169,67,111,112,121,114,105,103,104,116, +- 32,40,99,41,32,49,57,56,56,45,49,57, +- 57,50,44,32,80,114,105,110,116,105,110,103, +- 32,67,111,109,109,117,110,105,99,97,116,105, +- 111,110,115,32,65,115,115,111,99,105,97,116, +- 101,115,44,32,73,110,99,46,65,108,108,32, +- 114,105,103,104,116,115,32,114,101,115,101,114, +- 118,101,100,46,32,32,4,4,22,40,255,60, +- 4,96,10,224,6,0,7,126,2,64,11,246, +- 12,6,13,0,14,193,15,0,5,96,3,192, +- 1,0,9,8,62,3,211,82,62,192,211,82, +- 201,62,3,211,82,62,213,211,82,201,62,5, +- 211,82,62,224,211,82,201,62,5,211,82,62, +- 224,211,82,201,62,5,211,82,62,96,211,82, +- 201,6,28,33,180,1,14,82,237,163,194,4, +- 2,33,39,2,34,64,0,58,3,0,230,1, +- 192,62,11,237,121,62,118,237,121,201,33,182, +- 10,54,132,205,253,1,201,245,197,213,229,42, +- 150,10,14,83,17,98,2,67,20,237,162,58, +- 179,1,95,219,82,230,1,32,6,29,32,247, +- 195,17,3,62,1,211,82,219,82,95,230,160, +- 32,10,237,162,32,225,21,32,222,195,15,3, +- 237,162,123,230,96,194,21,3,62,48,211,82, +- 62,1,211,82,175,211,82,237,91,150,10,43, +- 55,237,82,218,19,3,34,152,10,98,107,58, +- 154,10,190,32,81,62,1,50,158,10,35,35, +- 62,132,190,32,44,54,133,43,70,58,154,10, +- 119,43,112,17,3,0,205,137,3,62,16,211, +- 82,62,56,211,82,205,217,1,42,150,10,14, +- 83,17,98,2,67,20,58,178,1,95,195,59, +- 2,62,129,190,194,227,2,54,130,43,70,58, +- 154,10,119,43,112,17,3,0,205,137,3,195, +- 254,2,35,35,126,254,132,194,227,2,205,61, +- 3,24,20,62,128,166,194,222,2,221,229,221, +- 33,175,10,205,93,6,205,144,7,221,225,225, +- 209,193,241,251,237,77,221,229,221,33,159,10, +- 205,93,6,221,225,205,61,3,195,247,2,24, +- 237,24,235,24,233,230,64,40,2,24,227,24, +- 225,175,50,179,10,205,208,1,201,197,33,4, +- 0,57,126,35,102,111,205,51,3,193,201,62, +- 1,50,179,10,34,150,10,54,0,58,179,10, +- 183,200,62,14,211,82,62,193,211,82,62,10, +- 211,82,62,224,211,82,62,6,211,82,58,154, +- 10,211,82,62,16,211,82,62,56,211,82,62, +- 48,211,82,219,82,230,1,40,4,219,83,24, +- 242,62,14,211,82,62,33,211,82,62,1,211, +- 82,62,9,211,82,62,32,211,82,205,217,1, +- 201,14,83,205,208,1,24,23,14,83,205,208, +- 1,205,226,1,58,174,1,61,32,253,205,244, +- 1,58,174,1,61,32,253,205,226,1,58,175, +- 1,61,32,253,62,5,211,82,62,233,211,82, +- 62,128,211,82,58,176,1,61,32,253,237,163, +- 27,62,192,211,82,219,82,230,4,40,250,237, +- 163,27,122,179,32,243,219,82,230,4,40,250, +- 58,178,1,71,219,82,230,4,40,3,5,32, +- 247,219,82,230,4,40,250,205,235,1,58,177, +- 1,61,32,253,205,244,1,201,229,213,35,35, +- 126,230,128,194,145,4,43,58,154,10,119,43, +- 70,33,181,10,119,43,112,17,3,0,243,62, +- 10,211,82,219,82,230,128,202,41,4,209,225, +- 62,1,55,251,201,205,144,3,58,180,10,254, +- 255,202,127,4,205,217,1,58,178,1,71,219, +- 82,230,1,32,6,5,32,247,195,173,4,219, +- 83,71,58,154,10,184,194,173,4,58,178,1, +- 71,219,82,230,1,32,6,5,32,247,195,173, +- 4,219,83,58,178,1,71,219,82,230,1,32, +- 6,5,32,247,195,173,4,219,83,254,133,194, +- 173,4,58,179,1,24,4,58,179,1,135,61, +- 32,253,209,225,205,137,3,205,61,3,183,251, +- 201,209,225,243,62,10,211,82,219,82,230,128, +- 202,164,4,62,1,55,251,201,205,144,3,205, +- 61,3,183,251,201,209,225,62,2,55,251,201, +- 243,62,14,211,82,62,33,211,82,251,201,33, +- 4,0,57,94,35,86,33,2,0,57,126,35, +- 102,111,221,229,34,193,10,237,83,195,10,221, +- 33,171,10,205,93,6,58,185,10,50,186,10, +- 58,184,10,135,50,184,10,205,112,6,254,3, +- 56,16,58,185,10,135,60,230,15,50,185,10, +- 175,50,184,10,24,23,58,183,10,205,112,6, +- 254,3,48,13,58,185,10,203,63,50,185,10, +- 62,255,50,183,10,58,185,10,50,186,10,58, +- 183,10,135,50,183,10,62,32,50,187,10,50, +- 188,10,6,255,219,82,230,16,32,3,5,32, +- 247,205,180,4,6,40,219,82,230,16,40,3, +- 5,32,247,62,10,211,82,219,82,230,128,194, +- 46,5,219,82,230,16,40,214,237,95,71,58, +- 186,10,160,230,15,40,32,71,14,10,62,10, +- 211,82,219,82,230,128,202,119,5,205,180,4, +- 195,156,5,219,82,230,16,202,156,5,13,32, +- 229,16,225,42,193,10,237,91,195,10,205,252, +- 3,48,7,61,202,156,5,195,197,5,221,225, +- 33,0,0,201,221,33,163,10,205,93,6,58, +- 188,10,61,50,188,10,40,19,58,186,10,246, +- 1,50,186,10,58,183,10,246,1,50,183,10, +- 195,46,5,221,225,33,1,0,201,221,33,167, +- 10,205,93,6,58,184,10,246,1,50,184,10, +- 58,186,10,135,246,1,50,186,10,58,187,10, +- 61,50,187,10,194,46,5,221,225,33,2,0, +- 201,221,229,33,0,0,57,17,4,0,25,126, +- 50,154,10,230,128,50,189,10,58,189,10,183, +- 40,6,221,33,88,2,24,4,221,33,150,0, +- 58,154,10,183,40,49,60,40,46,61,33,190, +- 10,119,35,119,35,54,129,175,50,158,10,221, +- 43,221,229,225,124,181,40,42,33,190,10,17, +- 3,0,205,206,4,17,232,3,27,123,178,32, +- 251,58,158,10,183,40,224,58,154,10,71,62, +- 7,128,230,127,71,58,189,10,176,50,154,10, +- 24,166,221,225,201,183,221,52,0,192,221,52, +- 1,192,221,52,2,192,221,52,3,192,55,201, +- 6,8,14,0,31,48,1,12,16,250,121,201, +- 33,2,0,57,94,35,86,35,78,35,70,35, +- 126,35,102,105,79,120,68,103,237,176,201,33, +- 2,0,57,126,35,102,111,62,17,237,57,48, +- 125,237,57,40,124,237,57,41,62,0,237,57, +- 42,62,64,237,57,43,62,0,237,57,44,33, +- 128,2,125,237,57,46,124,237,57,47,62,145, +- 237,57,48,211,68,58,149,10,211,66,201,33, +- 2,0,57,126,35,102,111,62,33,237,57,48, +- 62,64,237,57,32,62,0,237,57,33,237,57, +- 34,125,237,57,35,124,237,57,36,62,0,237, +- 57,37,33,128,2,125,237,57,38,124,237,57, +- 39,62,97,237,57,48,211,67,58,149,10,211, +- 66,201,237,56,46,95,237,56,47,87,237,56, +- 46,111,237,56,47,103,183,237,82,32,235,33, +- 128,2,183,237,82,201,237,56,38,95,237,56, +- 39,87,237,56,38,111,237,56,39,103,183,237, +- 82,32,235,33,128,2,183,237,82,201,205,106, +- 10,221,110,6,221,102,7,126,35,110,103,195, +- 118,10,205,106,10,33,0,0,34,205,10,34, +- 198,10,34,200,10,33,143,15,34,207,10,237, +- 91,207,10,42,146,10,183,237,82,17,0,255, +- 25,34,203,10,203,124,40,6,33,0,125,34, +- 203,10,42,207,10,229,205,37,3,195,118,10, +- 205,106,10,229,42,150,10,35,35,35,229,205, +- 70,7,193,124,230,3,103,221,117,254,221,116, +- 255,237,91,152,10,35,35,35,183,237,82,32, +- 12,17,5,0,42,152,10,205,91,10,242,203, +- 7,42,150,10,229,205,37,3,195,118,10,237, +- 91,152,10,42,200,10,25,34,200,10,42,205, +- 10,25,34,205,10,237,91,203,10,33,158,253, +- 25,237,91,205,10,205,91,10,242,245,7,33, +- 0,0,34,205,10,62,1,50,197,10,205,5, +- 8,33,0,0,57,249,195,118,10,205,106,10, +- 58,197,10,183,202,118,10,237,91,198,10,42, +- 205,10,205,91,10,242,46,8,237,91,205,10, +- 33,98,2,25,237,91,198,10,205,91,10,250, +- 78,8,237,91,198,10,42,205,10,183,237,82, +- 32,7,42,200,10,125,180,40,13,237,91,205, +- 10,42,198,10,205,91,10,242,97,8,237,91, +- 207,10,42,205,10,25,229,205,37,3,175,50, +- 197,10,195,118,10,205,29,3,33,0,0,57, +- 249,195,118,10,205,106,10,58,202,10,183,40, +- 22,205,14,7,237,91,209,10,19,19,19,205, +- 91,10,242,139,8,33,1,0,195,118,10,33, +- 0,0,195,118,10,205,126,10,252,255,205,108, +- 8,125,180,194,118,10,237,91,200,10,33,0, +- 0,205,91,10,242,118,10,237,91,207,10,42, +- 198,10,25,221,117,254,221,116,255,35,35,35, +- 229,205,70,7,193,124,230,3,103,35,35,35, +- 221,117,252,221,116,253,229,221,110,254,221,102, +- 255,229,33,212,10,229,205,124,6,193,193,221, +- 110,252,221,102,253,34,209,10,33,211,10,54, +- 4,33,209,10,227,205,147,6,193,62,1,50, +- 202,10,243,221,94,252,221,86,253,42,200,10, +- 183,237,82,34,200,10,203,124,40,17,33,0, +- 0,34,200,10,34,205,10,34,198,10,50,197, +- 10,24,37,221,94,252,221,86,253,42,198,10, +- 25,34,198,10,237,91,203,10,33,158,253,25, +- 237,91,198,10,205,91,10,242,68,9,33,0, +- 0,34,198,10,205,5,8,33,0,0,57,249, +- 251,195,118,10,205,106,10,33,49,13,126,183, +- 40,16,205,42,7,237,91,47,13,19,19,19, +- 205,91,10,242,117,9,58,142,15,198,1,50, +- 142,15,195,118,10,33,49,13,126,254,1,40, +- 25,254,3,202,7,10,254,5,202,21,10,33, +- 49,13,54,0,33,47,13,229,205,207,6,195, +- 118,10,58,141,15,183,32,72,33,51,13,126, +- 50,149,10,205,86,7,33,50,13,126,230,127, +- 183,32,40,58,142,15,230,127,50,142,15,183, +- 32,5,198,1,50,142,15,33,50,13,126,111, +- 23,159,103,203,125,58,142,15,40,5,198,128, +- 50,142,15,33,50,13,119,33,50,13,126,111, +- 23,159,103,229,205,237,5,193,33,211,10,54, +- 2,33,2,0,34,209,10,58,154,10,33,212, +- 10,119,58,148,10,33,213,10,119,33,209,10, +- 229,205,147,6,193,24,128,42,47,13,229,33, +- 50,13,229,205,191,4,193,24,239,33,211,10, +- 54,6,33,3,0,34,209,10,58,154,10,33, +- 212,10,119,58,148,10,33,213,10,119,33,214, +- 10,54,5,33,209,10,229,205,147,6,24,200, +- 205,106,10,33,49,13,54,0,33,47,13,229, +- 205,207,6,33,209,10,227,205,147,6,193,205, +- 80,9,205,145,8,24,248,124,170,250,99,10, +- 237,82,201,124,230,128,237,82,60,201,225,253, +- 229,221,229,221,33,0,0,221,57,233,221,249, +- 221,225,253,225,201,233,225,253,229,221,229,221, +- 33,0,0,221,57,94,35,86,35,235,57,249, +- 235,233,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0,0,0,0,0,0,0,0, +- 0,0,0,0,0 +- } ; +- +-#endif +diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c +index aaa7999..c9f951c 100644 +--- a/drivers/net/bonding/bond_3ad.c ++++ b/drivers/net/bonding/bond_3ad.c +@@ -70,6 +70,7 @@ + #define AD_PORT_STANDBY 0x80 + #define AD_PORT_SELECTED 0x100 + #define AD_PORT_MOVED 0x200 ++#define AD_PORT_BYPASS 0x400 + + // Port Key definitions + // key is determined according to the link speed, duplex and +@@ -223,7 +224,9 @@ static inline int __agg_has_partner(struct aggregator *agg) + */ + static inline void __disable_port(struct port *port) + { ++ pr_debug("Disable port %s\n", port->slave->dev->name); + bond_set_slave_inactive_flags(port->slave); ++ bond_3ad_set_carrier(port->slave->bond); + } + + /** +@@ -235,8 +238,11 @@ static inline void __enable_port(struct port *port) + { + struct slave *slave = port->slave; + +- if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev)) ++ if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev)) { ++ pr_debug("Enable port %s, individual %d\n", slave->dev->name, slave->individual); + bond_set_slave_active_flags(slave); ++ bond_3ad_set_carrier(slave->bond); ++ } + } + + /** +@@ -388,6 +394,130 @@ static u8 __get_duplex(struct port *port) + } + + /** ++ * is_lacp_bypass_eligible - is bond eligible to go into lacp bypass mode ++ * @bond: the bond we're looking at ++ * ++ * Return true if it is, false otherwise ++ */ ++static bool is_lacp_bypass_eligible(struct bonding *bond) ++{ ++ return (bond->params.lacp_bypass_allow && ++ (bond->params.lacp_bypass_active || ++ bond->params.lacp_bypass_all_active)); ++} ++ ++/** ++ * is_better_bypass_slave - compare between two slaves of the same bond ++ * and see which one is better for lacp bypass ++ * @slave1 ++ * @slave2 ++ * ++ * Return: true if slave1 is better, false otherwise ++ */ ++static bool is_better_bypass_slave(struct slave *slave1, struct slave *slave2) ++{ ++ if (!slave1) ++ return false; ++ ++ if (!slave2) ++ return true; ++ ++ if (slave1->bond != slave2->bond) ++ return false; ++ ++ if (slave1->lacp_bypass_priority > slave2->lacp_bypass_priority) ++ return true; ++ ++ if (slave2->lacp_bypass_priority > slave1->lacp_bypass_priority) ++ return false; ++ ++ return (strcmp(slave1->dev->name, slave2->dev->name) <= 0); ++} ++ ++/** ++ * __get_best_bypass_slave_in_bond - get the best slave when bond is in bypass mode ++ * @bond: the bond we're looking at ++ * Return the slave in the bond which is best for lacp bypass ++ */ ++static struct slave *__get_best_bypass_slave_in_bond(struct bonding *bond) ++{ ++ struct slave *slave, *best_slave = NULL; ++ int i; ++ ++ if (!is_lacp_bypass_eligible(bond)) ++ return NULL; ++ ++ bond_for_each_slave(bond, slave, i) { ++ if (IS_UP(slave->dev)) { ++ if (!best_slave) ++ best_slave = slave; ++ else if (is_better_bypass_slave(slave, best_slave)) ++ best_slave = slave; ++ } ++ } ++ return best_slave; ++} ++ ++static struct slave *__get_best_bypass_slave_in_agg(struct aggregator *agg) ++{ ++ struct slave *best_slave = NULL; ++ struct port *port; ++ ++ if (!is_lacp_bypass_eligible(agg->slave->bond)) ++ return NULL; ++ ++ for (port = agg->lag_ports; ++ port; ++ port = port->next_port_in_aggregator) { ++ ++ if (IS_UP(port->slave->dev)) { ++ if (!best_slave) ++ best_slave = port->slave; ++ else if (is_better_bypass_slave(port->slave, best_slave)) ++ best_slave = port->slave; ++ } ++ } ++ return best_slave; ++} ++ ++/** ++ * is_best_bypass_slave - is the given slave the best for lacp bypass ++ * @slave: the slave we're looking at ++ * Return true if it is, false otherwise ++ */ ++static bool is_best_bypass_slave(struct slave *slave) ++{ ++ return (slave == __get_best_bypass_slave_in_bond(slave->bond)); ++} ++ ++static bool is_agg_in_bypass(struct aggregator *agg) ++{ ++ struct slave *slave; ++ ++ if (!agg) ++ return false; ++ ++ slave = __get_best_bypass_slave_in_agg(agg); ++ return (slave && (SLAVE_AD_INFO(slave).port.sm_vars & AD_PORT_BYPASS)); ++} ++ ++bool bond_3ad_in_bypass_state(struct net_device *dev) ++{ ++ int i; ++ struct slave *slave; ++ struct bonding *bond = netdev_priv(dev); ++ if (!bond) ++ return false; ++ ++ bond_for_each_slave(bond, slave, i) { ++ if (SLAVE_AD_INFO(slave).port.sm_vars & AD_PORT_BYPASS) ++ return true; ++ } ++ ++ return false; ++} ++ ++/** + * __initialize_port_locks - initialize a port's STATE machine spinlock + * @port: the port we're looking at + * +@@ -511,10 +641,14 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port) + + // set the partner sync. to on if the partner is sync. and the port is matched + if ((port->sm_vars & AD_PORT_MATCHED) +- && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) ++ && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) { + partner->port_state |= AD_STATE_SYNCHRONIZATION; +- else ++ pr_debug("%s partner sync=1\n", port->slave->dev->name); ++ } ++ else { + partner->port_state &= ~AD_STATE_SYNCHRONIZATION; ++ pr_debug("%s partner sync=0\n", port->slave->dev->name); ++ } + } + } + +@@ -783,6 +917,8 @@ static inline void __update_lacpdu_from_port(struct port *port) + lacpdu->actor_port_priority = htons(port->actor_port_priority); + lacpdu->actor_port = htons(port->actor_port_number); + lacpdu->actor_state = port->actor_oper_port_state; ++ pr_debug("update lacpdu: %s, actor port state %x\n", ++ port->slave->dev->name, port->actor_oper_port_state); + + /* lacpdu->reserved_3_1 initialized + * lacpdu->tlv_type_partner_info initialized +@@ -941,18 +1077,21 @@ static void ad_mux_machine(struct port *port) + case AD_MUX_ATTACHED: + // check also if agg_select_timer expired(so the edable port will take place only after this timer) + if ((port->sm_vars & AD_PORT_SELECTED) && (port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) && !__check_agg_selection_timer(port)) { +- port->sm_mux_state = AD_MUX_COLLECTING_DISTRIBUTING;// next state ++ if (port->aggregator->is_active) ++ port->sm_mux_state = AD_MUX_COLLECTING_DISTRIBUTING;// next state + } else if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY)) { // if UNSELECTED or STANDBY + port->sm_vars &= ~AD_PORT_READY_N; + // in order to withhold the selection logic to check all ports READY_N value + // every callback cycle to update ready variable, we check READY_N and update READY here + __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator)); + port->sm_mux_state = AD_MUX_DETACHED;// next state +- } ++ } else if (port->aggregator->is_active) ++ port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION; + break; + case AD_MUX_COLLECTING_DISTRIBUTING: + if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY) || +- !(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) ++ !(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) || ++ !(port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION) + ) { + port->sm_mux_state = AD_MUX_ATTACHED;// next state + +@@ -975,8 +1114,8 @@ static void ad_mux_machine(struct port *port) + + // check if the state machine was changed + if (port->sm_mux_state != last_state) { +- pr_debug("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n", +- port->actor_port_number, last_state, ++ pr_debug("Mux Machine: Port=%d (%s), Last State=%d, Curr State=%d\n", ++ port->actor_port_number, port->slave->dev->name, last_state, + port->sm_mux_state); + switch (port->sm_mux_state) { + case AD_MUX_DETACHED: +@@ -992,7 +1131,10 @@ static void ad_mux_machine(struct port *port) + break; + case AD_MUX_ATTACHED: + __attach_bond_to_agg(port); +- port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION; ++ if (port->aggregator->is_active) ++ port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION; ++ else ++ port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION; + port->actor_oper_port_state &= ~AD_STATE_COLLECTING; + port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING; + ad_disable_collecting_distributing(port); +@@ -1001,6 +1143,7 @@ static void ad_mux_machine(struct port *port) + case AD_MUX_COLLECTING_DISTRIBUTING: + port->actor_oper_port_state |= AD_STATE_COLLECTING; + port->actor_oper_port_state |= AD_STATE_DISTRIBUTING; ++ port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION; + ad_enable_collecting_distributing(port); + port->ntt = true; + break; +@@ -1010,6 +1153,21 @@ static void ad_mux_machine(struct port *port) + } + } + ++static void cancel_bypass_on_all_slaves(struct bonding *bond) ++{ ++ struct port *port; ++ ++ if (!bond) ++ return; ++ ++ for (port = __get_first_port(bond); port; port = __get_next_port(port)) { ++ if (port->sm_vars & AD_PORT_BYPASS) ++ pr_info("%s: disabling lacp bypass\n", port->slave->dev->name); ++ port->sm_vars &= ~AD_PORT_BYPASS; ++ port->slave->individual = 0; ++ } ++} ++ + /** + * ad_rx_machine - handle a port's rx State Machine + * @lacpdu: the lacpdu we've received +@@ -1037,15 +1195,52 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) + /* next state */ + port->sm_rx_state = AD_RX_PORT_DISABLED; + // check if new lacpdu arrived +- else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) || (port->sm_rx_state == AD_RX_DEFAULTED) || (port->sm_rx_state == AD_RX_CURRENT))) { ++ else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) || (port->sm_rx_state == AD_RX_DEFAULTED) || (port->sm_rx_state == AD_RX_CURRENT) || (port->sm_rx_state == AD_RX_BYPASS_EXPIRED))) { + port->sm_rx_timer_counter = 0; // zero timer + port->sm_rx_state = AD_RX_CURRENT; ++ } else if (port->sm_rx_state == AD_RX_BYPASS) { ++ if (lacpdu) { ++ pr_info("%s: lacpdu received, disabling lacp bypass\n", ++ port->slave->dev->name); ++ ++ port->sm_rx_bypass_timer_counter = 0; ++ port->sm_rx_state = AD_RX_CURRENT; ++ __disable_port(port); // bring down the bond, let lacp runs its course ++ } else if ((!is_best_bypass_slave(port->slave) || ++ !(port->sm_vars & AD_PORT_BYPASS)) && ++ !port->slave->bond->params.lacp_bypass_all_active) { ++ pr_debug("(%s) bypass allow %d active %d or no longer best\n", ++ port->slave->dev->name, ++ port->slave->bond->params.lacp_bypass_allow, ++ port->slave->bond->params.lacp_bypass_active); ++ port->sm_rx_bypass_timer_counter = 0; ++ //if (is_lacp_bypass_eligible(port->slave->bond)) ++ // port->sm_rx_state = AD_RX_BYPASS_EXPIRED; ++ // else ++ port->sm_rx_state = AD_RX_DEFAULTED; ++ __disable_port(port); ++ } else if (port->sm_rx_bypass_timer_counter && ++ !(--port->sm_rx_bypass_timer_counter)) { ++ pr_info("%s: lacp bypass grace period expired\n", ++ port->slave->dev->name); ++ ++ port->sm_rx_state = AD_RX_BYPASS_EXPIRED; // next state ++ __disable_port(port); ++ } else if ((port->sm_vars & AD_PORT_BYPASS) != AD_PORT_BYPASS) { ++ pr_debug("%s: lacp bypass has been cancelled\n", port->slave->dev->name); ++ port->sm_rx_bypass_timer_counter = 0; ++ port->sm_rx_state = AD_RX_DEFAULTED; ++ __disable_port(port); ++ } + } else { + // if timer is on, and if it is expired + if (port->sm_rx_timer_counter && !(--port->sm_rx_timer_counter)) { + switch (port->sm_rx_state) { + case AD_RX_EXPIRED: +- port->sm_rx_state = AD_RX_DEFAULTED; // next state ++ if (is_best_bypass_slave(port->slave)) ++ port->sm_rx_state = AD_RX_BYPASS; // next state ++ else ++ port->sm_rx_state = AD_RX_DEFAULTED; // next state + break; + case AD_RX_CURRENT: + port->sm_rx_state = AD_RX_EXPIRED; // next state +@@ -1054,7 +1249,11 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) + break; + } + } else { ++ struct aggregator *agg; ++ struct bonding *bond; ++ + // if no lacpdu arrived and no timer is on ++ //pr_debug("rx_machine: state %d\n", port->sm_rx_state); + switch (port->sm_rx_state) { + case AD_RX_PORT_DISABLED: + if (port->sm_vars & AD_PORT_MOVED) +@@ -1068,6 +1267,17 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) + & AD_PORT_LACP_ENABLED) == 0)) + port->sm_rx_state = AD_RX_LACP_DISABLED; // next state + break; ++ case AD_RX_DEFAULTED: ++ bond = __get_bond_by_port(port); ++ if (bond && is_lacp_bypass_eligible(bond) && ++ bond->params.lacp_bypass_all_active) { ++ agg = bond_3ad_get_active_agg(bond); ++ if (!agg || is_agg_in_bypass(agg) || ++ (agg == port->aggregator)) ++ port->sm_rx_state = AD_RX_BYPASS; ++ } else if (is_best_bypass_slave(port->slave)) ++ port->sm_rx_state = AD_RX_BYPASS; // next state ++ break; + default: //to silence the compiler + break; + +@@ -1075,10 +1285,13 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) + } + } + ++ if (lacpdu) ++ cancel_bypass_on_all_slaves(__get_bond_by_port(port)); ++ + // check if the State machine was changed or new lacpdu arrived + if ((port->sm_rx_state != last_state) || (lacpdu)) { +- pr_debug("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n", +- port->actor_port_number, last_state, ++ pr_debug("Rx Machine: Port=%d (%s), Last State=%d, Curr State=%d\n", ++ port->actor_port_number, port->slave->dev->name, last_state, + port->sm_rx_state); + switch (port->sm_rx_state) { + case AD_RX_INITIALIZE: +@@ -1096,13 +1309,19 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) + + case AD_RX_PORT_DISABLED: + port->sm_vars &= ~AD_PORT_MATCHED; ++ port->sm_vars &= ~AD_PORT_BYPASS; ++ port->sm_rx_bypass_timer_counter = 0; ++ port->slave->individual = 0; + break; + case AD_RX_LACP_DISABLED: + port->sm_vars &= ~AD_PORT_SELECTED; ++ port->sm_vars &= ~AD_PORT_BYPASS; ++ port->sm_rx_bypass_timer_counter = 0; + __record_default(port); + port->partner_oper.port_state &= ~AD_STATE_AGGREGATION; + port->sm_vars |= AD_PORT_MATCHED; + port->actor_oper_port_state &= ~AD_STATE_EXPIRED; ++ port->slave->individual = 0; + break; + case AD_RX_EXPIRED: + //Reset of the Synchronization flag. (Standard 43.4.12) +@@ -1110,16 +1329,22 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) + //mux machine in case of EXPIRED even if LINK_DOWN didn't arrive for the port. + port->partner_oper.port_state &= ~AD_STATE_SYNCHRONIZATION; + port->sm_vars &= ~AD_PORT_MATCHED; ++ port->sm_vars &= ~AD_PORT_BYPASS; ++ port->sm_rx_bypass_timer_counter = 0; + port->partner_oper.port_state |= + AD_STATE_LACP_ACTIVITY; + port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT)); + port->actor_oper_port_state |= AD_STATE_EXPIRED; ++ port->slave->individual = 0; + break; + case AD_RX_DEFAULTED: + __update_default_selected(port); + __record_default(port); + port->sm_vars |= AD_PORT_MATCHED; ++ port->sm_vars &= ~AD_PORT_BYPASS; ++ port->sm_rx_bypass_timer_counter = 0; + port->actor_oper_port_state &= ~AD_STATE_EXPIRED; ++ port->slave->individual = 0; + break; + case AD_RX_CURRENT: + // detect loopback situation +@@ -1135,6 +1360,26 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) + __record_pdu(lacpdu, port); + port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT)); + port->actor_oper_port_state &= ~AD_STATE_EXPIRED; ++ port->sm_vars &= ~AD_PORT_BYPASS; ++ port->slave->individual = 0; ++ break; ++ case AD_RX_BYPASS: ++ pr_info("%s: in lacp bypass state\n", port->slave->dev->name); ++ ++ port->sm_rx_bypass_timer_counter = ++ port->slave->bond->params.lacp_bypass_period * ++ ad_ticks_per_sec; ++ port->sm_vars &= ~AD_PORT_SELECTED; ++ port->sm_vars |= AD_PORT_BYPASS; ++ if (port->slave->bond->params.lacp_bypass_all_active) { ++ port->slave->individual = 1; ++ __enable_port(port); ++ } ++ break; ++ case AD_RX_BYPASS_EXPIRED: ++ port->sm_vars &= ~AD_PORT_BYPASS; ++ port->slave->individual = 0; ++ port->sm_rx_bypass_timer_counter = 0; + break; + default: //to silence the compiler + break; +@@ -1149,6 +1394,9 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) + */ + static void ad_tx_machine(struct port *port) + { ++ struct bonding *bond = __get_bond_by_port(port); ++ struct slave *slave = port->slave; ++ + // check if tx timer expired, to verify that we do not send more than 3 packets per second + if (port->sm_tx_timer_counter && !(--port->sm_tx_timer_counter)) { + // check if there is something to send +@@ -1156,8 +1404,9 @@ static void ad_tx_machine(struct port *port) + __update_lacpdu_from_port(port); + + if (ad_lacpdu_send(port) >= 0) { +- pr_debug("Sent LACPDU on port %d\n", +- port->actor_port_number); ++ pr_debug("Sent LACPDU on port %d, bond %s slave %s (actor port state %x)\n", ++ port->actor_port_number, bond ? bond->dev->name:"", ++ slave ? slave->dev->name:"", port->actor_oper_port_state); + + /* mark ntt as false, so it will not be sent again until + demanded */ +@@ -1272,7 +1521,7 @@ static void ad_port_selection_logic(struct port *port) + // if the port is already Selected, do nothing + if (port->sm_vars & AD_PORT_SELECTED) + return; +- ++ pr_debug("Running port selection (%s)\n", port->slave->dev->name); + // if the port is connected to other aggregator, detach it + if (port->aggregator) { + // detach the port from its former aggregator +@@ -1294,6 +1543,7 @@ static void ad_port_selection_logic(struct port *port) + port->aggregator = NULL; + port->next_port_in_aggregator = NULL; + port->actor_port_aggregator_identifier = 0; ++ __disable_port(port); + + pr_debug("Port %d left LAG %d\n", + port->actor_port_number, +@@ -1396,6 +1646,12 @@ static void ad_port_selection_logic(struct port *port) + + aggregator = __get_first_agg(port); + ad_agg_selection_logic(aggregator); ++ ++ if (!port->aggregator->is_active) ++ port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION; ++ ++ if (port->slave->individual) ++ __enable_port(port); + } + + /* +@@ -1423,13 +1679,25 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best, + * did reply, keep best. + * + * 4. Therefore, current and best both have partner replies or +- * both do not, so perform selection policy: ++ * both do not, so: ++ * ++ * 4a. If both have no partner and bond is bypass eligible and if ++ * current agg is a better bypass slave, select current. ++ * ++ * 4b. If both have no partner and bond is bypass eligible and if ++ * best agg is a better bypass, keep best. ++ * ++ * 5. Therefore, current and best both have partner replies or ++ * both do not and bond is not bypass eligible, perform ++ * selection policy: + * + * BOND_AD_COUNT: Select by count of ports. If count is equal, + * select by bandwidth. + * + * BOND_AD_STABLE, BOND_AD_BANDWIDTH: Select by bandwidth. + */ ++ struct slave *s1, *s2; ++ + if (!best) + return curr; + +@@ -1445,6 +1713,19 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best, + if (!__agg_has_partner(curr) && __agg_has_partner(best)) + return best; + ++ if (is_lacp_bypass_eligible(curr->slave->bond) && ++ !__agg_has_partner(curr) && !__agg_has_partner(best)) { ++ ++ s1 = __get_best_bypass_slave_in_agg(curr); ++ s2 = __get_best_bypass_slave_in_agg(best); ++ ++ if (is_better_bypass_slave(s1, s2)) ++ return curr; ++ ++ if (is_better_bypass_slave(s2, s1)) ++ return best; ++ } ++ + switch (__get_agg_selection_mode(curr->lag_ports)) { + case BOND_AD_COUNT: + if (curr->num_of_ports > best->num_of_ports) +@@ -1509,6 +1790,7 @@ static void ad_agg_selection_logic(struct aggregator *agg) + { + struct aggregator *best, *active, *origin; + struct port *port; ++ bool best_is_in_bypass = false; + + origin = agg; + active = __get_active_agg(agg); +@@ -1522,7 +1804,9 @@ static void ad_agg_selection_logic(struct aggregator *agg) + + } while ((agg = __get_next_agg(agg))); + +- if (best && ++ best_is_in_bypass = is_agg_in_bypass(best); ++ ++ if (best && !best_is_in_bypass && + __get_agg_selection_mode(best->lag_ports) == BOND_AD_STABLE) { + /* + * For the STABLE policy, don't replace the old active +@@ -1587,7 +1871,11 @@ static void ad_agg_selection_logic(struct aggregator *agg) + if (active) { + for (port = active->lag_ports; port; + port = port->next_port_in_aggregator) { +- __disable_port(port); ++ if (!port->slave->individual) { ++ __disable_port(port); ++ port->sm_vars &= ~AD_PORT_BYPASS; ++ port->slave->individual = 0; ++ } + } + } + } +@@ -1599,12 +1887,15 @@ static void ad_agg_selection_logic(struct aggregator *agg) + active = __get_active_agg(origin); + + if (active) { +- if (!__agg_has_partner(active)) { ++// if (!__agg_has_partner(active)) { + for (port = active->lag_ports; port; + port = port->next_port_in_aggregator) { +- __enable_port(port); ++ if (is_best_bypass_slave(port->slave)) { ++ pr_debug("(%s) agg active and no partner\n", port->slave->dev->name); ++ __enable_port(port); ++ } + } +- } ++// } + } + + if (origin->slave) { +@@ -1717,6 +2008,9 @@ static void ad_initialize_port(struct port *port, int lacp_fast) + port->next_port_in_aggregator = NULL; + port->transaction_id = 0; + ++ // bypass ++ port->sm_rx_bypass_timer_counter = 0; ++ + memcpy(&port->lacpdu, &lacpdu, sizeof(lacpdu)); + } + } +@@ -1863,14 +2157,19 @@ void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout) + */ + void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution) + { ++ // If user configured a sys_mac, use it ++ struct mac_addr *sys_mac = (struct mac_addr *)bond->dev->dev_addr; ++ if (MAC_ADDRESS_COMPARE(&(bond->params.sys_mac_addr), &(null_mac_addr))) ++ sys_mac = (struct mac_addr *)&(bond->params.sys_mac_addr); ++ + // check that the bond is not initialized yet + if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), +- bond->dev->dev_addr)) { ++ sys_mac)) { + + BOND_AD_INFO(bond).aggregator_identifier = 0; + +- BOND_AD_INFO(bond).system.sys_priority = 0xFFFF; +- BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr); ++ BOND_AD_INFO(bond).system.sys_priority = bond->params.sys_priority; ++ BOND_AD_INFO(bond).system.sys_mac_addr = *sys_mac; + + // initialize how many times this module is called in one second(should be about every 100ms) + ad_ticks_per_sec = tick_resolution; +@@ -2174,6 +2473,7 @@ re_arm: + static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length) + { + struct port *port; ++ struct bonding *bond; + + if (length >= sizeof(struct lacpdu)) { + +@@ -2184,11 +2484,13 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u + slave->dev->name, slave->dev->master->name); + return; + } ++ bond = __get_bond_by_port(port); + + switch (lacpdu->subtype) { + case AD_TYPE_LACPDU: +- pr_debug("Received LACPDU on port %d\n", +- port->actor_port_number); ++ pr_debug("Received LACPDU on port %d bond %s slave %s\n", ++ port->actor_port_number, (bond && bond->dev) ? bond->dev->name:"", ++ (port->slave && port->slave->dev) ? port->slave->dev->name:""); + /* Protect against concurrent state machines */ + __get_state_machine_lock(port); + ad_rx_machine(lacpdu, port); +@@ -2256,8 +2558,10 @@ void bond_3ad_adapter_speed_changed(struct slave *slave) + void bond_3ad_adapter_duplex_changed(struct slave *slave) + { + struct port *port; ++ struct bonding *bond; + + port = &(SLAVE_AD_INFO(slave).port); ++ bond = __get_bond_by_port(port); + + // if slave is null, the whole port is not initialized + if (!port->slave) { +@@ -2269,7 +2573,11 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave) + port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS; + port->actor_oper_port_key = port->actor_admin_port_key |= + __get_duplex(port); +- pr_debug("Port %d changed duplex\n", port->actor_port_number); ++ pr_debug("Port %d bond %s slave %s changed duplex\n", port->actor_port_number, ++ (bond && bond->dev) ? bond->dev->name:"", ++ (port->slave && port->slave->dev) ? port->slave->dev->name:""); ++ if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS) ++ port->sm_vars |= AD_PORT_LACP_ENABLED; + // there is no need to reselect a new aggregator, just signal the + // state machines to reinitialize + port->sm_vars |= AD_PORT_BEGIN; +@@ -2331,17 +2639,30 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) + int bond_3ad_set_carrier(struct bonding *bond) + { + struct aggregator *active; ++ struct slave *slave; ++ int active_slaves = 0, i; ++ bool bypass = false; ++ ++ bond_for_each_slave(bond, slave, i) ++ if (bond_is_active_slave(slave)) ++ active_slaves++; + + active = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator)); +- if (active) { ++ bypass = is_agg_in_bypass(active); ++ pr_debug("%s %s active id: %d #actives: %d bypass: %d\n", __FUNCTION__, ++ bond->dev->name, active ? active->aggregator_identifier : 0, ++ active_slaves, bypass); ++ if (active && (bypass || __agg_has_partner(active))) { + /* are enough slaves available to consider link up? */ +- if (active->num_of_ports < bond->params.min_links) { ++ if (active_slaves < bond->params.min_links) { + if (netif_carrier_ok(bond->dev)) { + netif_carrier_off(bond->dev); ++ pr_debug("Setting bond %s off\n", bond->dev->name); + return 1; + } + } else if (!netif_carrier_ok(bond->dev)) { + netif_carrier_on(bond->dev); ++ pr_debug("Setting bond %s on\n", bond->dev->name); + return 1; + } + return 0; +@@ -2354,15 +2675,7 @@ int bond_3ad_set_carrier(struct bonding *bond) + return 0; + } + +-/** +- * bond_3ad_get_active_agg_info - get information of the active aggregator +- * @bond: bonding struct to work on +- * @ad_info: ad_info struct to fill with the bond's info +- * +- * Returns: 0 on success +- * < 0 on error +- */ +-int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info) ++struct aggregator * bond_3ad_get_active_agg(struct bonding *bond) + { + struct aggregator *aggregator = NULL; + struct port *port; +@@ -2374,6 +2687,21 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info) + } + } + ++ return aggregator; ++} ++ ++/** ++ * bond_3ad_get_active_agg_info - get information of the active aggregator ++ * @bond: bonding struct to work on ++ * @ad_info: ad_info struct to fill with the bond's info ++ * ++ * Returns: 0 on success ++ * < 0 on error ++ */ ++int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info) ++{ ++ struct aggregator *aggregator = bond_3ad_get_active_agg(bond); ++ + if (aggregator) { + ad_info->aggregator_id = aggregator->aggregator_identifier; + ad_info->ports = aggregator->num_of_ports; +@@ -2483,11 +2811,13 @@ void bond_3ad_update_lacp_rate(struct bonding *bond) + struct port *port = NULL; + int lacp_fast; + +- read_lock(&bond->lock); ++ write_lock_bh(&bond->lock); + lacp_fast = bond->params.lacp_fast; + + bond_for_each_slave(bond, slave, i) { + port = &(SLAVE_AD_INFO(slave).port); ++ if (port->slave == NULL) ++ continue; + __get_state_machine_lock(port); + if (lacp_fast) + port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT; +@@ -2496,5 +2826,72 @@ void bond_3ad_update_lacp_rate(struct bonding *bond) + __release_state_machine_lock(port); + } + +- read_unlock(&bond->lock); ++ write_unlock_bh(&bond->lock); ++} ++ ++/* ++ * When modify sys_priority parameter via sysfs, ++ * update the bond's sys_priority and the ++ * actor_system_priority of each port. ++ * ++ * Hold slave->state_machine_lock, ++ * so we can modify port->actor_system_priority ++ * no matter bond is up or down. ++ */ ++void bond_3ad_update_sys_priority(struct bonding *bond) ++{ ++ int i; ++ struct slave *slave; ++ struct port *port = NULL; ++ u16 sys_priority; ++ ++ write_lock_bh(&bond->lock); ++ sys_priority = bond->params.sys_priority; ++ BOND_AD_INFO(bond).system.sys_priority = sys_priority; ++ ++ bond_for_each_slave(bond, slave, i) { ++ port = &(SLAVE_AD_INFO(slave).port); ++ if (port->slave == NULL) ++ continue; ++ __get_state_machine_lock(port); ++ port->actor_system_priority = sys_priority; ++ __release_state_machine_lock(port); ++ } ++ ++ write_unlock_bh(&bond->lock); ++} ++ ++/* ++ * When modify sys_mac_addr parameter via sysfs, ++ * update the bond's sys_mac_addr and the ++ * actor_system of each port. ++ * ++ * Hold slave->state_machine_lock, ++ * so we can modify port->actor_system ++ * no matter bond is up or down. ++ */ ++void bond_3ad_update_sys_mac_addr(struct bonding *bond) ++{ ++ int i; ++ struct slave *slave; ++ struct port *port = NULL; ++ struct mac_addr sys_mac; ++ ++ write_lock_bh(&bond->lock); ++ sys_mac = *((struct mac_addr *)&(bond->params.sys_mac_addr)); ++ if (!MAC_ADDRESS_COMPARE(&(sys_mac), &(null_mac_addr))){ ++ sys_mac = *((struct mac_addr *)bond->dev->dev_addr); ++ } ++ BOND_AD_INFO(bond).system.sys_mac_addr = sys_mac; ++ ++ bond_for_each_slave(bond, slave, i) { ++ port = &(SLAVE_AD_INFO(slave).port); ++ if (port->slave == NULL) ++ continue; ++ __get_state_machine_lock(port); ++ port->actor_system = sys_mac; ++ __release_state_machine_lock(port); ++ } ++ ++ write_unlock_bh(&bond->lock); + } +diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h +index 20d9c78..6e30f94 100644 +--- a/drivers/net/bonding/bond_3ad.h ++++ b/drivers/net/bonding/bond_3ad.h +@@ -55,7 +55,9 @@ typedef enum { + AD_RX_LACP_DISABLED, // rx Machine + AD_RX_EXPIRED, // rx Machine + AD_RX_DEFAULTED, // rx Machine +- AD_RX_CURRENT // rx Machine ++ AD_RX_CURRENT, // rx Machine ++ AD_RX_BYPASS, // rx Machine ++ AD_RX_BYPASS_EXPIRED // rx Machine + } rx_states_t; + + // periodic machine states(43.4.12 in the 802.3ad standard) +@@ -100,7 +102,8 @@ typedef enum { + AD_ACTOR_CHURN_TIMER, + AD_PERIODIC_TIMER, + AD_PARTNER_CHURN_TIMER, +- AD_WAIT_WHILE_TIMER ++ AD_WAIT_WHILE_TIMER, ++ AD_BYPASS_TIMER, + } ad_timers_t; + + #pragma pack(1) +@@ -223,6 +226,7 @@ typedef struct port { + u16 sm_vars; // all state machines variables for this port + rx_states_t sm_rx_state; // state machine rx state + u16 sm_rx_timer_counter; // state machine rx timer counter ++ u16 sm_rx_bypass_timer_counter; // state machine rx bypass timer counter + periodic_states_t sm_periodic_state;// state machine periodic state + u16 sm_periodic_timer_counter; // state machine periodic timer counter + mux_states_t sm_mux_state; // state machine mux state +@@ -273,11 +277,15 @@ void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout); + void bond_3ad_adapter_speed_changed(struct slave *slave); + void bond_3ad_adapter_duplex_changed(struct slave *slave); + void bond_3ad_handle_link_change(struct slave *slave, char link); ++struct aggregator *bond_3ad_get_active_agg(struct bonding *bond); + int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info); + int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev); + void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond, + struct slave *slave); + int bond_3ad_set_carrier(struct bonding *bond); + void bond_3ad_update_lacp_rate(struct bonding *bond); ++void bond_3ad_update_sys_priority(struct bonding *bond); ++void bond_3ad_update_sys_mac_addr(struct bonding *bond); ++bool bond_3ad_in_bypass_state(struct net_device *dev); + #endif //__BOND_3AD_H__ + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 5af2a8f..d3413e6 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -78,6 +78,8 @@ + #include + #include + #include ++#include ++#include + #include "bonding.h" + #include "bond_3ad.h" + #include "bond_alb.h" +@@ -87,6 +89,9 @@ + /* monitor all links that often (in milliseconds). <=0 disables monitoring */ + #define BOND_LINK_MON_INTERV 0 + #define BOND_LINK_ARP_INTERV 0 ++#define BOND_LACP_BYPASS_PERIOD 0 ++#define BOND_LACP_BYPASS_ACTIVE_DEFAULT 1 ++#define BOND_LACP_BYPASS_ALL_ACTIVE_DEFAULT 1 + + static int max_bonds = BOND_DEFAULT_MAX_BONDS; + static int tx_queues = BOND_DEFAULT_TX_QUEUES; +@@ -250,6 +255,10 @@ struct bond_parm_tbl ad_select_tbl[] = { + + static int bond_init(struct net_device *bond_dev); + static void bond_uninit(struct net_device *bond_dev); ++static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev, ++ struct rtnl_link_stats64 *stats); ++static struct rtnl_link_stats64 *__bond_get_stats(struct net_device *bond_dev, ++ struct rtnl_link_stats64 *stats); + + /*---------------------------- General routines -----------------------------*/ + +@@ -271,6 +280,166 @@ const char *bond_mode_name(int mode) + return names[mode]; + } + ++/*---------------------------- genl/bond -----------------------------*/ ++ ++enum { ++ BOND_GENL_ATTR_UNSPEC, ++ BOND_GENL_ATTR_BOND, ++ BOND_GENL_ATTR_SLAVE, ++ BOND_GENL_ATTR_INDIVIDUAL, ++ __BOND_GENL_ATTR_MAX, ++}; ++#define BOND_GENL_ATTR_MAX (__BOND_GENL_ATTR_MAX - 1) ++ ++enum { ++ BOND_GENL_CMD_UNSPEC, ++ BOND_GENL_CMD_GET, ++ BOND_GENL_CMD_ACTIVATE_EVENT, ++ BOND_GENL_CMD_DEACTIVATE_EVENT, ++ __BOND_GENL_CMD_MAX, ++}; ++ ++static struct genl_family bond_event_genl_family = { ++ .id = GENL_ID_GENERATE, ++ .name = "bond_event", ++ .version = 1, ++ .maxattr = BOND_GENL_ATTR_MAX, ++}; ++ ++static int fill_genlmsg(struct sk_buff *skb, u32 pid, u32 seq, ++ int flags, u8 cmd, struct bonding *bond, struct slave *slave) ++{ ++ void *hdr; ++ ++ hdr = genlmsg_put(skb, pid, seq, &bond_event_genl_family, ++ flags, cmd); ++ if (hdr == NULL) ++ return -EMSGSIZE; ++ ++ if (bond) ++ NLA_PUT_U32(skb, BOND_GENL_ATTR_BOND, bond->dev->ifindex); ++ else ++ NLA_PUT_U32(skb, BOND_GENL_ATTR_BOND, 0); ++ NLA_PUT_U32(skb, BOND_GENL_ATTR_SLAVE, slave->dev->ifindex); ++ ++ if (slave->individual) ++ NLA_PUT_U32(skb, BOND_GENL_ATTR_INDIVIDUAL, 1); ++ else ++ NLA_PUT_U32(skb, BOND_GENL_ATTR_INDIVIDUAL, 0); ++ ++ return genlmsg_end(skb, hdr); ++ ++nla_put_failure: ++ genlmsg_cancel(skb, hdr); ++ return -EMSGSIZE; ++} ++ ++static int bond_event_genl_dump(struct sk_buff *skb, ++ struct netlink_callback *cb) ++{ ++ struct bond_net *bn = net_generic(&init_net, bond_net_id); ++ struct slave *slave; ++ struct bonding *bond; ++ u32 pid = NETLINK_CB(cb->skb).pid; ++ u32 seq = cb->nlh->nlmsg_seq; ++ int bond_idx = 0, bond_start_idx = cb->args[0]; ++ int slave_idx = 0, slave_start_idx = cb->args[1]; ++ int i; ++ ++ rtnl_lock(); ++ ++ list_for_each_entry(bond, &bn->dev_list, bond_list) { ++ ++ if (bond_idx > bond_start_idx) ++ slave_start_idx = 0; ++ if (bond_idx++ < bond_start_idx) ++ continue; ++ ++ slave_idx = 0; ++ ++ read_lock(&bond->lock); ++ bond_for_each_slave(bond, slave, i) { ++ u8 cmd = bond_is_active_slave(slave) ? ++ BOND_GENL_CMD_ACTIVATE_EVENT : ++ BOND_GENL_CMD_DEACTIVATE_EVENT; ++ if (slave_idx++ < slave_start_idx) ++ continue; ++ if (fill_genlmsg(skb, pid, seq, NLM_F_MULTI, ++ cmd, bond, slave) < 0) { ++ read_unlock(&bond->lock); ++ goto out; ++ } ++ } ++ read_unlock(&bond->lock); ++ } ++ ++out: ++ rtnl_unlock(); ++ ++ cb->args[0] = bond_idx; ++ cb->args[1] = slave_idx; ++ ++ return skb->len; ++} ++ ++static struct genl_ops bond_event_get_ops = { ++ .cmd = BOND_GENL_CMD_GET, ++ .dumpit = bond_event_genl_dump, ++}; ++ ++static struct genl_multicast_group bond_event_mcgrp = { ++ .name = "bond_event_mc", ++}; ++ ++static int bond_netlink_event(struct bonding *bond, ++ struct slave *slave, ++ u8 cmd) ++{ ++ static atomic_t seq; ++ struct sk_buff *skb; ++ int msg_size = 3 * nla_total_size(sizeof(u32)); ++ ++ skb = genlmsg_new(msg_size, GFP_ATOMIC); ++ if (!skb) ++ return -ENOMEM; ++ ++ if (fill_genlmsg(skb, 0, atomic_add_return(1, &seq), ++ 0, cmd, bond, slave) < 0) ++ goto err_out; ++ ++ genlmsg_multicast(skb, 0, bond_event_mcgrp.id, GFP_ATOMIC); ++ ++ return 0; ++ ++err_out: ++ nlmsg_free(skb); ++ return -ENOMEM; ++} ++ ++static int bond_genl_init(void) ++{ ++ int res; ++ ++ res = genl_register_family(&bond_event_genl_family); ++ if (res) ++ return res; ++ ++ res = genl_register_ops(&bond_event_genl_family, ++ &bond_event_get_ops); ++ if (res) ++ goto err; ++ ++ res = genl_register_mc_group(&bond_event_genl_family, ++ &bond_event_mcgrp); ++ if (res) ++ goto err; ++ ++ return res; ++err: ++ genl_unregister_family(&bond_event_genl_family); ++ return res; ++} ++ + /*---------------------------------- VLAN -----------------------------------*/ + + /** +@@ -1008,13 +1177,13 @@ static bool bond_should_notify_peers(struct bonding *bond) + { + struct slave *slave = bond->curr_active_slave; + +- pr_debug("bond_should_notify_peers: bond %s slave %s\n", +- bond->dev->name, slave ? slave->dev->name : "NULL"); +- + if (!slave || !bond->send_peer_notif || + test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state)) + return false; + ++ pr_debug("bond_should_notify_peers: bond %s slave %s\n", ++ bond->dev->name, slave ? slave->dev->name : "NULL"); ++ + bond->send_peer_notif--; + return true; + } +@@ -1341,7 +1510,11 @@ static u32 bond_fix_features(struct net_device *dev, u32 features) + goto out; + } + +- mask = features; ++ /* If any slave has the offload feature flag set, ++ * set the offload flag on the bond. ++ */ ++ mask = features | NETIF_F_HW_SWITCH_OFFLOAD; ++ + features &= ~NETIF_F_ONE_FOR_ALL; + features |= NETIF_F_ALL_FOR_ALL; + +@@ -1358,7 +1531,8 @@ out: + + #define BOND_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \ + NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \ +- NETIF_F_HIGHDMA | NETIF_F_LRO) ++ NETIF_F_HIGHDMA | NETIF_F_LRO | \ ++ NETIF_F_HW_SWITCH_OFFLOAD) + + static void bond_compute_features(struct bonding *bond) + { +@@ -1648,7 +1822,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) + goto err_restore_mac; + } + +- /* open the slave since the application closed it */ ++ /* If the bond is multi-chassis LAG enabled the slave is placed in a ++ * proto_down state. This has to be done before device is opened and ++ * is needed to prevent the slaves from becoming active independent of ++ * the mc-lag control protocol run by the app. */ ++ if (bond->params.clag_enable) ++ dev_change_proto_down(slave_dev, true); ++ + res = dev_open(slave_dev); + if (res) { + pr_debug("Opening slave %s failed\n", slave_dev->name); +@@ -1658,6 +1838,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) + new_slave->bond = bond; + new_slave->dev = slave_dev; + slave_dev->priv_flags |= IFF_BONDING; ++ /* initialize slave stats */ ++ dev_get_stats(new_slave->dev, &new_slave->slave_stats); + + if (bond_is_lb(bond)) { + /* bond_alb_init_slave() must be called before all other stages since +@@ -1848,6 +2030,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) + goto err_dest_symlinks; + } + ++ res = bond_sysfs_slave_add(new_slave); ++ if (res) { ++ pr_debug("Error %d calling bond_sysfs_slave_add\n", res); ++ goto err_unregister; ++ } ++ + pr_info("%s: enslaving %s as a%s interface with a%s link.\n", + bond_dev->name, slave_dev->name, + bond_is_active_slave(new_slave) ? "n active" : " backup", +@@ -1857,6 +2045,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) + return 0; + + /* Undo stages on error */ ++err_unregister: ++ netdev_rx_handler_unregister(slave_dev); ++ + err_dest_symlinks: + bond_destroy_slave_symlinks(bond_dev, slave_dev); + +@@ -1870,6 +2061,8 @@ err_close: + dev_close(slave_dev); + + err_unset_master: ++ if (bond->params.clag_enable) ++ dev_change_proto_down(slave_dev, false); + netdev_set_bond_master(slave_dev, NULL); + + err_restore_mac: +@@ -1937,10 +2130,14 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) + } + + write_unlock_bh(&bond->lock); ++ ++ bond_sysfs_slave_del(slave); ++ + /* unregister rx_handler early so bond_handle_frame wouldn't be called + * for this slave anymore. + */ + netdev_rx_handler_unregister(slave_dev); ++ + write_lock_bh(&bond->lock); + + if (!bond->params.fail_over_mac) { +@@ -1969,7 +2166,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) + + bond->current_arp_slave = NULL; + +- /* release the slave from its bond */ ++ /* recompute stats just before removing the slave */ ++ __bond_get_stats(bond->dev, &bond->bond_stats); ++ + bond_detach_slave(bond, slave); + + if (bond->primary_slave == slave) +@@ -2069,6 +2268,10 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) + /* close slave before restoring its mac address */ + dev_close(slave_dev); + ++ /* Clear MLAG proto_down state */ ++ if (bond->params.clag_enable) ++ dev_change_proto_down(slave_dev, false); ++ + if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) { + /* restore original ("permanent") mac address */ + memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); +@@ -2080,6 +2283,11 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) + + slave_dev->priv_flags &= ~IFF_BONDING; + ++ /* deactivate slave in bond cache. bond ifindex for cache ++ * entry will be 0 (slave no longer in bond). ++ */ ++ bond_netlink_event(NULL, slave, BOND_GENL_CMD_DEACTIVATE_EVENT); ++ + kfree(slave); + + return 0; /* deletion OK */ +@@ -2155,6 +2363,7 @@ static int bond_release_all(struct net_device *bond_dev) + bond_alb_deinit_slave(bond, slave); + } + ++ bond_sysfs_slave_del(slave); + bond_destroy_slave_symlinks(bond_dev, slave_dev); + bond_del_vlans_from_slave(bond, slave_dev); + +@@ -2184,6 +2393,10 @@ static int bond_release_all(struct net_device *bond_dev) + /* close slave before restoring its mac address */ + dev_close(slave_dev); + ++ /* Clear MLAG proto_down state */ ++ if (bond->params.clag_enable) ++ dev_change_proto_down(slave_dev, false); ++ + if (!bond->params.fail_over_mac) { + /* restore original ("permanent") mac address*/ + memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); +@@ -2422,6 +2635,7 @@ static int bond_miimon_inspect(struct bonding *bond) + static void bond_miimon_commit(struct bonding *bond) + { + struct slave *slave; ++ struct ethtool_cmd ecmd; + int i; + + bond_for_each_slave(bond, slave, i) { +@@ -2439,14 +2653,17 @@ static void bond_miimon_commit(struct bonding *bond) + } else if (bond->params.mode != BOND_MODE_ACTIVEBACKUP) { + /* make it immediately active */ + bond_set_active_slave(slave); ++ bond_set_slave_active_flags(slave); + } else if (slave != bond->primary_slave) { + /* prevent it from being the active one */ + bond_set_backup_slave(slave); + } + ++ __ethtool_get_settings(slave->dev, &ecmd); + pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n", + bond->dev->name, slave->dev->name, +- slave->speed, slave->duplex ? "full" : "half"); ++ ethtool_cmd_speed(&ecmd), ++ ecmd.duplex == DUPLEX_FULL ? "full" : "half"); + + /* notify ad that the link status has changed */ + if (bond->params.mode == BOND_MODE_8023AD) +@@ -2469,6 +2686,7 @@ static void bond_miimon_commit(struct bonding *bond) + slave->link = BOND_LINK_DOWN; + + if (bond->params.mode == BOND_MODE_ACTIVEBACKUP || ++ bond->params.mode == BOND_MODE_XOR || + bond->params.mode == BOND_MODE_8023AD) + bond_set_slave_inactive_flags(slave); + +@@ -3465,7 +3683,7 @@ static int bond_open(struct net_device *bond_dev) + if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) + && (slave != bond->curr_active_slave)) { + bond_set_slave_inactive_flags(slave); +- } else { ++ } else if (bond->params.mode != BOND_MODE_8023AD) { + bond_set_slave_active_flags(slave); + } + } +@@ -3527,46 +3745,68 @@ static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev, + struct rtnl_link_stats64 *stats) + { + struct bonding *bond = netdev_priv(bond_dev); ++ ++ read_lock_bh(&bond->lock); ++ ++ stats = __bond_get_stats(bond_dev, stats); ++ ++ read_unlock_bh(&bond->lock); ++ ++ return stats; ++} ++ ++/* Port stats can be cleared, so if new port stats are less than old ++ * total do not perform the subraction and just presume the new port ++ * stats are the net difference since last time. ++ */ ++#define STATS_DIFF(x) \ ++ (pstats->x > sstats->x ? sstats->x : sstats->x - pstats->x) ++ ++static struct rtnl_link_stats64 *__bond_get_stats(struct net_device *bond_dev, ++ struct rtnl_link_stats64 *stats) ++{ ++ struct bonding *bond = netdev_priv(bond_dev); + struct rtnl_link_stats64 temp; + struct slave *slave; + int i; + +- memset(stats, 0, sizeof(*stats)); +- +- read_lock_bh(&bond->lock); ++ memcpy(stats, &bond->bond_stats, sizeof(*stats)); + + bond_for_each_slave(bond, slave, i) { + const struct rtnl_link_stats64 *sstats = + dev_get_stats(slave->dev, &temp); ++ struct rtnl_link_stats64 *pstats = &slave->slave_stats; + +- stats->rx_packets += sstats->rx_packets; +- stats->rx_bytes += sstats->rx_bytes; +- stats->rx_errors += sstats->rx_errors; +- stats->rx_dropped += sstats->rx_dropped; ++ stats->rx_packets += STATS_DIFF(rx_packets); ++ stats->rx_bytes += STATS_DIFF(rx_bytes); ++ stats->rx_errors += STATS_DIFF(rx_errors); ++ stats->rx_dropped += STATS_DIFF(rx_dropped); + +- stats->tx_packets += sstats->tx_packets; +- stats->tx_bytes += sstats->tx_bytes; +- stats->tx_errors += sstats->tx_errors; +- stats->tx_dropped += sstats->tx_dropped; ++ stats->tx_packets += STATS_DIFF(tx_packets); ++ stats->tx_bytes += STATS_DIFF(tx_bytes); ++ stats->tx_errors += STATS_DIFF(tx_errors); ++ stats->tx_dropped += STATS_DIFF(tx_dropped); + +- stats->multicast += sstats->multicast; +- stats->collisions += sstats->collisions; ++ stats->multicast += STATS_DIFF(multicast); ++ stats->collisions += STATS_DIFF(collisions); + +- stats->rx_length_errors += sstats->rx_length_errors; +- stats->rx_over_errors += sstats->rx_over_errors; +- stats->rx_crc_errors += sstats->rx_crc_errors; +- stats->rx_frame_errors += sstats->rx_frame_errors; +- stats->rx_fifo_errors += sstats->rx_fifo_errors; +- stats->rx_missed_errors += sstats->rx_missed_errors; ++ stats->rx_length_errors += STATS_DIFF(rx_length_errors); ++ stats->rx_over_errors += STATS_DIFF(rx_over_errors); ++ stats->rx_crc_errors += STATS_DIFF(rx_crc_errors); ++ stats->rx_frame_errors += STATS_DIFF(rx_frame_errors); ++ stats->rx_fifo_errors += STATS_DIFF(rx_fifo_errors); ++ stats->rx_missed_errors += STATS_DIFF(rx_missed_errors); + +- stats->tx_aborted_errors += sstats->tx_aborted_errors; +- stats->tx_carrier_errors += sstats->tx_carrier_errors; +- stats->tx_fifo_errors += sstats->tx_fifo_errors; +- stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors; +- stats->tx_window_errors += sstats->tx_window_errors; +- } ++ stats->tx_aborted_errors += STATS_DIFF(tx_aborted_errors); ++ stats->tx_carrier_errors += STATS_DIFF(tx_carrier_errors); ++ stats->tx_fifo_errors += STATS_DIFF(tx_fifo_errors); ++ stats->tx_heartbeat_errors += STATS_DIFF(tx_heartbeat_errors); ++ stats->tx_window_errors += STATS_DIFF(tx_window_errors); + +- read_unlock_bh(&bond->lock); ++ /* save off the slave stats for the next run */ ++ memcpy(pstats, sstats, sizeof(*sstats)); ++ } ++ memcpy(&bond->bond_stats, stats, sizeof(*stats)); + + return stats; + } +@@ -4052,7 +4292,10 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) + int res = 1; + + read_lock(&bond->curr_slave_lock); +- start_at = bond->curr_active_slave; ++ if (bond->curr_active_slave) ++ start_at = bond->curr_active_slave; ++ else ++ start_at = bond->first_slave; + read_unlock(&bond->curr_slave_lock); + + if (!start_at) +@@ -4183,7 +4426,11 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev + case BOND_MODE_BROADCAST: + return bond_xmit_broadcast(skb, dev); + case BOND_MODE_8023AD: +- return bond_3ad_xmit_xor(skb, dev); ++ /* check if bond is in bypass state, if so, use broadcast */ ++ if (bond_3ad_in_bypass_state(dev)) ++ return bond_xmit_broadcast(skb, dev); ++ else ++ return bond_3ad_xmit_xor(skb, dev); + case BOND_MODE_ALB: + case BOND_MODE_TLB: + return bond_alb_xmit(skb, dev); +@@ -4253,6 +4500,33 @@ void bond_set_mode_ops(struct bonding *bond, int mode) + } + } + ++static int bond_get_settings(struct net_device *dev, ++ struct ethtool_cmd *ecmd) ++{ ++ struct bonding *bond = netdev_priv(dev); ++ u32 speed_mbps = SPEED_UNKNOWN; ++ ++ if (bond->first_slave) ++ speed_mbps = bond->first_slave->speed; ++ ++ switch(speed_mbps) { ++ case SPEED_10: ++ case SPEED_100: ++ case SPEED_1000: ++ case SPEED_10000: ++ speed_mbps = speed_mbps * bond->slave_cnt; ++ break; ++ default: ++ speed_mbps = SPEED_UNKNOWN; ++ break; ++ } ++ ++ ethtool_cmd_speed_set(ecmd, speed_mbps); ++ ecmd->duplex = DUPLEX_FULL; ++ ++ return 0; ++} ++ + static void bond_ethtool_get_drvinfo(struct net_device *bond_dev, + struct ethtool_drvinfo *drvinfo) + { +@@ -4262,6 +4536,7 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev, + } + + static const struct ethtool_ops bond_ethtool_ops = { ++ .get_settings = bond_get_settings, + .get_drvinfo = bond_ethtool_get_drvinfo, + .get_link = ethtool_op_get_link, + }; +@@ -4712,6 +4987,8 @@ static int bond_check_params(struct bond_params *params) + params->downdelay = downdelay; + params->use_carrier = use_carrier; + params->lacp_fast = lacp_fast; ++ params->sys_priority = 0xFFFF; ++ memset(¶ms->sys_mac_addr, 0, sizeof(params->sys_mac_addr)); + params->primary[0] = 0; + params->primary_reselect = primary_reselect_value; + params->fail_over_mac = fail_over_mac_value; +@@ -4719,6 +4996,9 @@ static int bond_check_params(struct bond_params *params) + params->all_slaves_active = all_slaves_active; + params->resend_igmp = resend_igmp; + params->min_links = min_links; ++ params->lacp_bypass_period = BOND_LACP_BYPASS_PERIOD; ++ params->lacp_bypass_active = BOND_LACP_BYPASS_ACTIVE_DEFAULT; ++ params->lacp_bypass_all_active = BOND_LACP_BYPASS_ALL_ACTIVE_DEFAULT; + + if (primary) { + strncpy(params->primary, primary, IFNAMSIZ); +@@ -4803,12 +5083,289 @@ static int bond_get_tx_queues(struct net *net, struct nlattr *tb[], + return 0; + } + ++static size_t bond_get_size(const struct net_device *bond_dev) ++{ ++ return nla_total_size(sizeof(u8)) + /* IFLA_BOND_MODE */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_ACTIVE_SLAVE */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIIMON */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_UPDELAY */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_DOWNDELAY */ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_USE_CARRIER */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_INTERVAL */ ++ /* IFLA_BOND_ARP_IP_TARGET */ ++ nla_total_size(sizeof(struct nlattr)) + ++ nla_total_size(sizeof(u32)) * BOND_MAX_ARP_TARGETS + ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_VALIDATE */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_ALL_TARGETS */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_PRIMARY */ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_PRIMARY_RESELECT */ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_FAIL_OVER_MAC */ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_XMIT_HASH_POLICY */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_RESEND_IGMP */ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_NUM_PEER_NOTIF */ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_ALL_SLAVES_ACTIVE */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIN_LINKS */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_LP_INTERVAL */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_PACKETS_PER_SLAVE */ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_AD_LACP_RATE */ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_AD_SELECT */ ++ nla_total_size(sizeof(struct nlattr)) + /* IFLA_BOND_AD_INFO */ ++ nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_AGGREGATOR */ ++ nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_NUM_PORTS */ ++ nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_ACTOR_KEY */ ++ nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_PARTNER_KEY*/ ++ nla_total_size(ETH_ALEN) + /* IFLA_BOND_AD_INFO_PARTNER_MAC*/ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_CL_LACP_BYPASS_ALLOW */ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_CL_LACP_BYPASS_ACTIVE */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_CL_LACP_BYPASS_PERIOD */ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_CL_LACP_BYPASS_ALL_ACTIVE */ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_CL_CLAG_ENABLE */ ++ 0; ++} ++ ++static struct net_device *__bond_option_active_slave_get(struct bonding *bond, ++ struct slave *slave) ++{ ++ return bond_uses_primary(bond) && slave ? slave->dev : NULL; ++} ++ ++static int bond_option_active_slave_get_ifindex(struct bonding *bond) ++{ ++ const struct net_device *slave; ++ int ifindex; ++ ++ read_lock(&bond->lock); ++ read_lock(&bond->curr_slave_lock); ++ slave = __bond_option_active_slave_get(bond, bond->curr_active_slave); ++ ifindex = slave ? slave->ifindex : 0; ++ read_unlock(&bond->curr_slave_lock); ++ read_unlock(&bond->lock); ++ return ifindex; ++} ++ ++ ++static int bond_fill_info(struct sk_buff *skb, ++ const struct net_device *bond_dev) ++{ ++ struct bonding *bond = netdev_priv(bond_dev); ++ int ifindex, i, targets_added; ++ struct nlattr *targets; ++ struct slave *primary; ++ ++ if (nla_put_u8(skb, IFLA_BOND_MODE, BOND_MODE(bond))) ++ goto nla_put_failure; ++ ++ ifindex = bond_option_active_slave_get_ifindex(bond); ++ if (ifindex && nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, ifindex)) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon)) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(skb, IFLA_BOND_UPDELAY, ++ bond->params.updelay * bond->params.miimon)) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(skb, IFLA_BOND_DOWNDELAY, ++ bond->params.downdelay * bond->params.miimon)) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_BOND_USE_CARRIER, bond->params.use_carrier)) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(skb, IFLA_BOND_ARP_INTERVAL, bond->params.arp_interval)) ++ goto nla_put_failure; ++ ++ targets = nla_nest_start(skb, IFLA_BOND_ARP_IP_TARGET); ++ if (!targets) ++ goto nla_put_failure; ++ ++ targets_added = 0; ++ for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) { ++ if (bond->params.arp_targets[i]) { ++ nla_put_be32(skb, i, bond->params.arp_targets[i]); ++ targets_added = 1; ++ } ++ } ++ ++ if (targets_added) ++ nla_nest_end(skb, targets); ++ else ++ nla_nest_cancel(skb, targets); ++ ++ if (nla_put_u32(skb, IFLA_BOND_ARP_VALIDATE, bond->params.arp_validate)) ++ goto nla_put_failure; ++ ++ primary = bond->primary_slave; ++ if (primary && ++ nla_put_u32(skb, IFLA_BOND_PRIMARY, primary->dev->ifindex)) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_BOND_PRIMARY_RESELECT, ++ bond->params.primary_reselect)) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_BOND_FAIL_OVER_MAC, ++ bond->params.fail_over_mac)) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_BOND_XMIT_HASH_POLICY, ++ bond->params.xmit_policy)) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(skb, IFLA_BOND_RESEND_IGMP, ++ bond->params.resend_igmp)) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_BOND_NUM_PEER_NOTIF, ++ bond->params.num_peer_notif)) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_BOND_ALL_SLAVES_ACTIVE, ++ bond->params.all_slaves_active)) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(skb, IFLA_BOND_MIN_LINKS, ++ bond->params.min_links)) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_BOND_AD_LACP_RATE, ++ bond->params.lacp_fast)) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_BOND_AD_SELECT, ++ bond->params.ad_select)) ++ goto nla_put_failure; ++ ++ if (BOND_MODE(bond) == BOND_MODE_8023AD) { ++ struct ad_info info; ++ ++ if (!bond_3ad_get_active_agg_info(bond, &info)) { ++ struct nlattr *nest; ++ ++ nest = nla_nest_start(skb, IFLA_BOND_AD_INFO); ++ if (!nest) ++ goto nla_put_failure; ++ ++ if (nla_put_u16(skb, IFLA_BOND_AD_INFO_AGGREGATOR, ++ info.aggregator_id)) ++ goto nla_put_failure; ++ if (nla_put_u16(skb, IFLA_BOND_AD_INFO_NUM_PORTS, ++ info.ports)) ++ goto nla_put_failure; ++ if (nla_put_u16(skb, IFLA_BOND_AD_INFO_ACTOR_KEY, ++ info.actor_key)) ++ goto nla_put_failure; ++ if (nla_put_u16(skb, IFLA_BOND_AD_INFO_PARTNER_KEY, ++ info.partner_key)) ++ goto nla_put_failure; ++ if (nla_put(skb, IFLA_BOND_AD_INFO_PARTNER_MAC, ++ sizeof(info.partner_system), ++ &info.partner_system)) ++ goto nla_put_failure; ++ ++ nla_nest_end(skb, nest); ++ } ++ ++ if (nla_put_u8(skb, IFLA_BOND_CL_LACP_BYPASS_ALLOW, ++ bond->params.lacp_bypass_allow)) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_BOND_CL_LACP_BYPASS_ACTIVE, ++ bond->params.lacp_bypass_active)) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(skb, IFLA_BOND_CL_LACP_BYPASS_PERIOD, ++ bond->params.lacp_bypass_period)) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_BOND_CL_LACP_BYPASS_ALL_ACTIVE, ++ bond->params.lacp_bypass_all_active)) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_BOND_CL_CLAG_ENABLE, ++ bond->params.clag_enable)) ++ goto nla_put_failure; ++ } ++ ++ return 0; ++ ++nla_put_failure: ++ return -EMSGSIZE; ++} ++ ++static size_t bond_get_slave_size(const struct net_device *bond_dev, ++ const struct net_device *slave_dev) ++{ ++ return nla_total_size(sizeof(u8)) + /* IFLA_BOND_SLAVE_STATE */ ++ nla_total_size(sizeof(u8)) + /* IFLA_BOND_SLAVE_MII_STATUS */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_SLAVE_LINK_FAILURE_COUNT */ ++ nla_total_size(MAX_ADDR_LEN) + /* IFLA_BOND_SLAVE_PERM_HWADDR */ ++ nla_total_size(sizeof(u16)) + /* IFLA_BOND_SLAVE_QUEUE_ID */ ++ nla_total_size(sizeof(u16)) + /* IFLA_BOND_SLAVE_AD_AGGREGATOR_ID */ ++ nla_total_size(sizeof(u32)) + /* IFLA_BOND_SLAVE_CL_LACP_BYPASS_PRIO */ ++ 0; ++} ++ ++static int bond_fill_slave_info(struct sk_buff *skb, ++ const struct net_device *bond_dev, ++ const struct net_device *slave_dev) ++{ ++ struct slave *slave = bond_slave_get_rtnl(slave_dev); ++ ++ if (!slave) ++ return 0; ++ ++ if (nla_put_u8(skb, IFLA_BOND_SLAVE_STATE, bond_slave_state(slave))) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_BOND_SLAVE_MII_STATUS, slave->link)) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(skb, IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, ++ slave->link_failure_count)) ++ goto nla_put_failure; ++ ++ if (nla_put(skb, IFLA_BOND_SLAVE_PERM_HWADDR, ++ slave_dev->addr_len, slave->perm_hwaddr)) ++ goto nla_put_failure; ++ ++ if (nla_put_u16(skb, IFLA_BOND_SLAVE_QUEUE_ID, slave->queue_id)) ++ goto nla_put_failure; ++ ++ if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) { ++ const struct aggregator *agg; ++ ++ agg = SLAVE_AD_INFO(slave).port.aggregator; ++ if (agg) ++ if (nla_put_u16(skb, IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, ++ agg->aggregator_identifier)) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(skb, IFLA_BOND_SLAVE_CL_LACP_BYPASS_PRIO, ++ slave->lacp_bypass_priority)) ++ goto nla_put_failure; ++ } ++ ++ return 0; ++ ++nla_put_failure: ++ return -EMSGSIZE; ++} ++ ++ + static struct rtnl_link_ops bond_link_ops __read_mostly = { + .kind = "bond", + .priv_size = sizeof(struct bonding), + .setup = bond_setup, ++ .maxtype = IFLA_BOND_MAX, + .validate = bond_validate, ++ .get_size = bond_get_size, ++ .fill_info = bond_fill_info, + .get_tx_queues = bond_get_tx_queues, ++ .slave_maxtype = IFLA_BOND_SLAVE_MAX, ++ .get_slave_size = bond_get_slave_size, ++ .fill_slave_info= bond_fill_slave_info, + }; + + /* Create a new bond based on the specified name and bonding parameters. +@@ -4882,6 +5439,53 @@ static struct pernet_operations bond_net_ops = { + .size = sizeof(struct bond_net), + }; + ++void bond_set_active_slave(struct slave *slave) ++{ ++ slave->backup = 0; ++ bond_netlink_event(slave->bond, slave, BOND_GENL_CMD_ACTIVATE_EVENT); ++} ++ ++void bond_set_backup_slave(struct slave *slave) ++{ ++ slave->backup = 1; ++ bond_netlink_event(slave->bond, slave, BOND_GENL_CMD_DEACTIVATE_EVENT); ++} ++ ++static void bond_set_clag_proto_down(struct bonding *bond, ++ bool proto_down) ++{ ++ struct slave *slave; ++ struct net_device *slave_dev; ++ int i; ++ ++ read_lock(&bond->lock); ++ bond_for_each_slave(bond, slave, i) { ++ slave_dev = slave->dev; ++ dev_change_proto_down(slave_dev, proto_down); ++ } ++ read_unlock(&bond->lock); ++} ++ ++/* Enable/disable multi-chassis LAG on a bond. Once mc-lag is enabled on a bond ++ * the slaves are place in a proto_down state as the slaves' state will now be ++ * controlled by a mc-lag application. On mc-lag disable the bonding driver ++ * takes back slave state control and clears proto_down on slaves that may have ++ * been shutdown by the application */ ++void bond_set_clag_enable(struct bonding *bond, u8 clag_enable) ++{ ++ if (bond->params.clag_enable == clag_enable) ++ return; ++ ++ bond->params.clag_enable = clag_enable; ++ ++ if (clag_enable) ++ /* proto_down the bond and its slaves - they are now in ++ * MC-LAG app's control */ ++ bond_set_clag_proto_down(bond, true); ++ else ++ bond_set_clag_proto_down(bond, false); ++} ++ + static int __init bonding_init(void) + { + int i; +@@ -4901,6 +5505,10 @@ static int __init bonding_init(void) + if (res) + goto err_link; + ++ res = bond_genl_init(); ++ if (res) ++ goto err_genl; ++ + bond_create_debugfs(); + + for (i = 0; i < max_bonds; i++) { +@@ -4914,6 +5522,8 @@ static int __init bonding_init(void) + out: + return res; + err: ++ genl_unregister_family(&bond_event_genl_family); ++err_genl: + bond_destroy_debugfs(); + rtnl_link_unregister(&bond_link_ops); + err_link: +@@ -4929,6 +5539,7 @@ static void __exit bonding_exit(void) + + bond_destroy_debugfs(); + ++ genl_unregister_family(&bond_event_genl_family); + rtnl_link_unregister(&bond_link_ops); + unregister_pernet_subsys(&bond_net_ops); + +diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c +index ad284ba..c1e3faf 100644 +--- a/drivers/net/bonding/bond_procfs.c ++++ b/drivers/net/bonding/bond_procfs.c +@@ -129,6 +129,9 @@ static void bond_info_show_master(struct seq_file *seq) + seq_printf(seq, "Min links: %d\n", bond->params.min_links); + seq_printf(seq, "Aggregator selection policy (ad_select): %s\n", + ad_select_tbl[bond->params.ad_select].modename); ++ seq_printf(seq, "System Identification: %d %pM\n", ++ BOND_AD_INFO(bond).system.sys_priority, ++ &(BOND_AD_INFO(bond).system.sys_mac_addr)); + + if (bond_3ad_get_active_agg_info(bond, &ad_info)) { + seq_printf(seq, "bond %s has no active aggregator\n", +@@ -147,6 +150,14 @@ static void bond_info_show_master(struct seq_file *seq) + seq_printf(seq, "\tPartner Mac Address: %pM\n", + ad_info.partner_system); + } ++ ++ seq_printf(seq, "LACP Bypass Info:\n"); ++ seq_printf(seq, "\tAllowed: %d\n", ++ bond->params.lacp_bypass_allow); ++ seq_printf(seq, "\tTimeout: %d\n", ++ bond->params.lacp_bypass_period); ++ seq_printf(seq, "\tAll-active: %d\n", ++ bond->params.lacp_bypass_all_active); + } + } + +@@ -182,6 +193,12 @@ static void bond_info_show_slave(struct seq_file *seq, + agg->aggregator_identifier); + else + seq_puts(seq, "Aggregator ID: N/A\n"); ++ seq_printf(seq, "LACP bypass priority: %d\n", ++ slave->lacp_bypass_priority); ++ if (SLAVE_AD_INFO(slave).port.sm_rx_state == AD_RX_BYPASS) ++ seq_printf(seq, "LACP bypass: on\n"); ++ if (SLAVE_AD_INFO(slave).port.sm_rx_state == AD_RX_BYPASS_EXPIRED) ++ seq_printf(seq, "LACP bypass: expired\n"); + } + seq_printf(seq, "Slave queue ID: %d\n", slave->queue_id); + } +diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c +index cf95bd8..7bdb979 100644 +--- a/drivers/net/bonding/bond_sysfs.c ++++ b/drivers/net/bonding/bond_sysfs.c +@@ -47,6 +47,79 @@ + #define to_dev(obj) container_of(obj, struct device, kobj) + #define to_bond(cd) ((struct bonding *)(netdev_priv(to_net_dev(cd)))) + ++struct slave_attribute { ++ struct attribute attr; ++ ssize_t (*show)(struct slave *, char *); ++ int (*store)(struct slave *, unsigned long); ++}; ++ ++static ssize_t show_lacp_bypass_priority(struct slave *slave, char *buf) ++{ ++ return sprintf(buf, "%d\n", slave->lacp_bypass_priority); ++} ++ ++static int store_lacp_bypass_priority(struct slave *slave, unsigned long val) ++{ ++ slave->lacp_bypass_priority = val; ++ return 0; ++} ++ ++static const struct slave_attribute slave_lacp_bypass_priority = { ++ .attr = { ++ .name = "lacp_bypass_priority", ++ .mode = S_IWUSR | S_IRUGO, ++ }, ++ .show = show_lacp_bypass_priority, ++ .store = store_lacp_bypass_priority, ++}; ++ ++static const struct slave_attribute *slave_attrs[] = { ++ &slave_lacp_bypass_priority, ++ NULL ++}; ++ ++#define to_slave_attr(_at) container_of(_at, struct slave_attribute, attr) ++#define to_slave(obj) container_of(obj, struct slave, kobj) ++ ++static ssize_t slave_show(struct kobject *kobj, ++ struct attribute *attr, char *buf) ++{ ++ struct slave_attribute *slave_attr = to_slave_attr(attr); ++ struct slave *slave = to_slave(kobj); ++ ++ return slave_attr->show(slave, buf); ++} ++ ++static ssize_t slave_store(struct kobject *kobj, ++ struct attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct slave_attribute *slave_attr = to_slave_attr(attr); ++ struct slave *slave = to_slave(kobj); ++ ssize_t ret = -EINVAL; ++ char *endp; ++ unsigned long val; ++ ++ val = simple_strtoul(buf, &endp, 0); ++ if (endp != buf) { ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ ++ ret = slave_attr->store(slave, val); ++ if (ret == 0) ++ ret = count; ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, slave->bond->dev); ++ ++ rtnl_unlock(); ++ } ++ return ret; ++} ++ ++const struct sysfs_ops slave_sysfs_ops = { ++ .show = slave_show, ++ .store = slave_store, ++}; ++ + /* + * "show" function for the bond_masters attribute. + * The class parameter is ignored. +@@ -347,11 +420,15 @@ static ssize_t bonding_store_mode(struct device *d, + goto out; + } + ++ if (!rtnl_trylock()) ++ return restart_syscall(); + bond->params.mode = new_value; + bond_set_mode_ops(bond, bond->params.mode); + pr_info("%s: setting mode to %s (%d).\n", + bond->dev->name, bond_mode_tbl[new_value].modename, + new_value); ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); + out: + return ret; + } +@@ -394,13 +471,17 @@ static ssize_t bonding_store_xmit_hash(struct device *d, + (int)strlen(buf) - 1, buf); + ret = -EINVAL; + goto out; +- } else { +- bond->params.xmit_policy = new_value; +- bond_set_mode_ops(bond, bond->params.mode); +- pr_info("%s: setting xmit hash policy to %s (%d).\n", ++ } ++ ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ bond->params.xmit_policy = new_value; ++ bond_set_mode_ops(bond, bond->params.mode); ++ pr_info("%s: setting xmit hash policy to %s (%d).\n", + bond->dev->name, + xmit_hashtype_tbl[new_value].modename, new_value); +- } ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); + out: + return ret; + } +@@ -443,7 +524,11 @@ static ssize_t bonding_store_arp_validate(struct device *d, + bond->dev->name, arp_validate_tbl[new_value].modename, + new_value); + ++ if (!rtnl_trylock()) ++ return restart_syscall(); + bond->params.arp_validate = new_value; ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); + + return count; + } +@@ -486,10 +571,14 @@ static ssize_t bonding_store_fail_over_mac(struct device *d, + return -EINVAL; + } + ++ if (!rtnl_trylock()) ++ return restart_syscall(); + bond->params.fail_over_mac = new_value; + pr_info("%s: Setting fail_over_mac to %s (%d).\n", + bond->dev->name, fail_over_mac_tbl[new_value].modename, + new_value); ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); + + return count; + } +@@ -567,6 +656,7 @@ static ssize_t bonding_store_arp_interval(struct device *d, + queue_delayed_work(bond->wq, &bond->arp_work, 0); + } + } ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); + out: + rtnl_unlock(); + return ret; +@@ -603,6 +693,8 @@ static ssize_t bonding_store_arp_targets(struct device *d, + struct bonding *bond = to_bond(d); + __be32 *targets; + ++ if (!rtnl_trylock()) ++ return restart_syscall(); + targets = bond->params.arp_targets; + newtarget = in_aton(buf + 1); + /* look for adds */ +@@ -667,8 +759,10 @@ static ssize_t bonding_store_arp_targets(struct device *d, + ret = -EPERM; + goto out; + } ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); + + out: ++ rtnl_unlock(); + return ret; + } + static DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets); +@@ -727,6 +821,7 @@ static ssize_t bonding_store_downdelay(struct device *d, + bond->params.downdelay * bond->params.miimon); + + } ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); + + out: + rtnl_unlock(); +@@ -785,6 +880,7 @@ static ssize_t bonding_store_updelay(struct device *d, + bond->dev->name, + bond->params.updelay * bond->params.miimon); + } ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); + + out: + rtnl_unlock(); +@@ -832,11 +928,15 @@ static ssize_t bonding_store_lacp(struct device *d, + new_value = bond_parse_parm(buf, bond_lacp_tbl); + + if ((new_value == 1) || (new_value == 0)) { ++ if (!rtnl_trylock()) ++ return restart_syscall(); + bond->params.lacp_fast = new_value; + bond_3ad_update_lacp_rate(bond); + pr_info("%s: Setting LACP rate to %s (%d).\n", + bond->dev->name, bond_lacp_tbl[new_value].modename, + new_value); ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); + } else { + pr_err("%s: Ignoring invalid LACP rate value %.*s.\n", + bond->dev->name, (int)strlen(buf) - 1, buf); +@@ -872,14 +972,229 @@ static ssize_t bonding_store_min_links(struct device *d, + return ret; + } + ++ if (!rtnl_trylock()) ++ return restart_syscall(); + pr_info("%s: Setting min links value to %u\n", + bond->dev->name, new_value); + bond->params.min_links = new_value; ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); + return count; + } + static DEVICE_ATTR(min_links, S_IRUGO | S_IWUSR, + bonding_show_min_links, bonding_store_min_links); + ++static ssize_t bonding_show_clag_enable(struct device *d, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct bonding *bond = to_bond(d); ++ ++ return sprintf(buf, "%d\n", bond->params.clag_enable); ++} ++ ++static ssize_t bonding_store_clag_enable(struct device *d, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct bonding *bond = to_bond(d); ++ int ret; ++ u8 new_value; ++ ++ ret = kstrtou8(buf, 10, &new_value); ++ if (ret < 0) { ++ pr_err("%s: Ignoring invalid clag enable value %s.\n", ++ bond->dev->name, buf); ++ return ret; ++ } ++ ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ pr_debug("%s: Setting clag enable to %u\n", ++ bond->dev->name, new_value); ++ bond_set_clag_enable(bond, new_value); ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); ++ return count; ++} ++static DEVICE_ATTR(clag_enable, S_IRUGO | S_IWUSR, ++ bonding_show_clag_enable, bonding_store_clag_enable); ++ ++static ssize_t bonding_show_lacp_bypass_allow(struct device *d, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct bonding *bond = to_bond(d); ++ ++ return sprintf(buf, "%d\n", bond->params.lacp_bypass_allow); ++} ++ ++static ssize_t bonding_store_lacp_bypass_allow(struct device *d, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct bonding *bond = to_bond(d); ++ int ret; ++ unsigned int new_value; ++ ++ if (bond->params.mode != BOND_MODE_8023AD) { ++ pr_err("%s: Unable to update lacp_bypass_allow because bond is not " ++ "in 802.3ad mode.\n", bond->dev->name); ++ ret = -EPERM; ++ return ret; ++ } ++ ++ ret = kstrtouint(buf, 0, &new_value); ++ if (ret < 0) { ++ pr_err("%s: Ignoring invalid lacp_bypass_allow value %s.\n", ++ bond->dev->name, buf); ++ return ret; ++ } ++ ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ pr_debug("%s: Setting lacp_bypass_allow to %u\n", ++ bond->dev->name, new_value); ++ bond->params.lacp_bypass_allow = new_value; ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); ++ return count; ++} ++static DEVICE_ATTR(lacp_bypass_allow, S_IRUGO | S_IWUSR, ++ bonding_show_lacp_bypass_allow, bonding_store_lacp_bypass_allow); ++ ++static ssize_t bonding_show_lacp_bypass_period(struct device *d, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct bonding *bond = to_bond(d); ++ ++ return sprintf(buf, "%d\n", bond->params.lacp_bypass_period); ++} ++ ++static ssize_t bonding_store_lacp_bypass_period(struct device *d, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct bonding *bond = to_bond(d); ++ int ret; ++ unsigned int new_value; ++ ++ if (bond->params.mode != BOND_MODE_8023AD) { ++ pr_err("%s: Unable to update lacp_bypass_period because bond is not " ++ "in 802.3ad mode.\n", bond->dev->name); ++ ret = -EPERM; ++ return ret; ++ } ++ ++ ret = kstrtouint(buf, 0, &new_value); ++ if (ret < 0) { ++ pr_err("%s: Ignoring invalid lacp_bypass_period value %s.\n", ++ bond->dev->name, buf); ++ return ret; ++ } ++ ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ pr_debug("%s: Setting lacp_bypass period to %u\n", ++ bond->dev->name, new_value); ++ bond->params.lacp_bypass_period = new_value; ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); ++ return count; ++} ++static DEVICE_ATTR(lacp_bypass_period, S_IRUGO | S_IWUSR, ++ bonding_show_lacp_bypass_period, ++ bonding_store_lacp_bypass_period); ++ ++static ssize_t bonding_show_lacp_bypass_active(struct device *d, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct bonding *bond = to_bond(d); ++ ++ return sprintf(buf, "%d\n", bond->params.lacp_bypass_active); ++} ++ ++static ssize_t bonding_store_lacp_bypass_active(struct device *d, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct bonding *bond = to_bond(d); ++ int ret; ++ unsigned int new_value; ++ ++ if (bond->params.mode != BOND_MODE_8023AD) { ++ pr_err("%s: Unable to update lacp_bypass_active because bond is not " ++ "in 802.3ad mode.\n", bond->dev->name); ++ ret = -EPERM; ++ return ret; ++ } ++ ++ ret = kstrtouint(buf, 0, &new_value); ++ if (ret < 0) { ++ pr_err("%s: Ignoring invalid lacp_bypass_active value %s.\n", ++ bond->dev->name, buf); ++ return ret; ++ } ++ ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ pr_debug("%s: Setting lacp_bypass active to %u\n", ++ bond->dev->name, new_value); ++ bond->params.lacp_bypass_active = new_value; ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); ++ return count; ++} ++static DEVICE_ATTR(lacp_bypass_active, S_IRUGO | S_IWUSR, ++ bonding_show_lacp_bypass_active, ++ bonding_store_lacp_bypass_active); ++ ++static ssize_t bonding_show_lacp_bypass_all_active(struct device *d, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct bonding *bond = to_bond(d); ++ ++ return sprintf(buf, "%d\n", bond->params.lacp_bypass_all_active); ++} ++ ++static ssize_t bonding_store_lacp_bypass_all_active(struct device *d, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct bonding *bond = to_bond(d); ++ int ret; ++ unsigned int new_value; ++ ++ if (bond->params.mode != BOND_MODE_8023AD) { ++ pr_err("%s: Unable to update lacp_bypass_all_active because bond is not " ++ "in 802.3ad mode.\n", bond->dev->name); ++ ret = -EPERM; ++ return ret; ++ } ++ ++ ret = kstrtouint(buf, 0, &new_value); ++ if (ret < 0) { ++ pr_err("%s: Ignoring invalid lacp_bypass_all_active value %s.\n", ++ bond->dev->name, buf); ++ return ret; ++ } ++ ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ pr_debug("%s: Setting lacp_bypass use priority to %u\n", ++ bond->dev->name, new_value); ++ bond->params.lacp_bypass_all_active = new_value; ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); ++ return count; ++} ++static DEVICE_ATTR(lacp_bypass_all_active, S_IRUGO | S_IWUSR, ++ bonding_show_lacp_bypass_all_active, ++ bonding_store_lacp_bypass_all_active); ++ + static ssize_t bonding_show_ad_select(struct device *d, + struct device_attribute *attr, + char *buf) +@@ -909,10 +1224,14 @@ static ssize_t bonding_store_ad_select(struct device *d, + new_value = bond_parse_parm(buf, ad_select_tbl); + + if (new_value != -1) { ++ if (!rtnl_trylock()) ++ return restart_syscall(); + bond->params.ad_select = new_value; + pr_info("%s: Setting ad_select to %s (%d).\n", + bond->dev->name, ad_select_tbl[new_value].modename, + new_value); ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); + } else { + pr_err("%s: Ignoring invalid ad_select value %.*s.\n", + bond->dev->name, (int)strlen(buf) - 1, buf); +@@ -940,8 +1259,19 @@ static ssize_t bonding_store_num_peer_notif(struct device *d, + const char *buf, size_t count) + { + struct bonding *bond = to_bond(d); +- int err = kstrtou8(buf, 10, &bond->params.num_peer_notif); +- return err ? err : count; ++ int err; ++ ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ ++ err = kstrtou8(buf, 10, &bond->params.num_peer_notif); ++ if (err) ++ goto out; ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ err = count; ++out: ++ rtnl_unlock(); ++ return err; + } + static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, + bonding_show_num_peer_notif, bonding_store_num_peer_notif); +@@ -1015,6 +1345,7 @@ static ssize_t bonding_store_miimon(struct device *d, + queue_delayed_work(bond->wq, &bond->mii_work, 0); + } + } ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); + out: + rtnl_unlock(); + return ret; +@@ -1091,6 +1422,7 @@ out: + write_unlock_bh(&bond->curr_slave_lock); + read_unlock(&bond->lock); + unblock_netpoll_tx(); ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); + rtnl_unlock(); + + return count; +@@ -1143,6 +1475,7 @@ static ssize_t bonding_store_primary_reselect(struct device *d, + write_unlock_bh(&bond->curr_slave_lock); + read_unlock(&bond->lock); + unblock_netpoll_tx(); ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); + out: + rtnl_unlock(); + return ret; +@@ -1178,9 +1511,13 @@ static ssize_t bonding_store_carrier(struct device *d, + goto out; + } + if ((new_value == 0) || (new_value == 1)) { ++ if (!rtnl_trylock()) ++ return restart_syscall(); + bond->params.use_carrier = new_value; + pr_info("%s: Setting use_carrier to %d.\n", + bond->dev->name, new_value); ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); + } else { + pr_info("%s: Ignoring invalid use_carrier value %d.\n", + bond->dev->name, new_value); +@@ -1290,7 +1627,7 @@ static ssize_t bonding_store_active_slave(struct device *d, + write_unlock_bh(&bond->curr_slave_lock); + read_unlock(&bond->lock); + unblock_netpoll_tx(); +- ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); + rtnl_unlock(); + + return count; +@@ -1428,6 +1765,160 @@ static ssize_t bonding_show_ad_partner_mac(struct device *d, + static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL); + + /* ++ * Show the current 802.3ad active slaves. ++ */ ++static ssize_t bonding_show_ad_active_slaves(struct device *d, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct slave *slave; ++ int i, count = 0; ++ struct bonding *bond = to_bond(d); ++ ++ if (bond->params.mode != BOND_MODE_8023AD) ++ return count; ++ ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ ++ read_lock(&bond->lock); ++ bond_for_each_slave(bond, slave, i) { ++ int active; ++ if (count > (PAGE_SIZE - IFNAMSIZ - 6)) { ++ /* not enough space for another interface_name:status pair */ ++ if ((PAGE_SIZE - count) > 10) ++ count = PAGE_SIZE - 10; ++ count += sprintf(buf + count, "++more++ "); ++ break; ++ } ++ active = bond_is_active_slave(slave) ? 1 : 0; ++ count += sprintf(buf + count, "%s:%d ", ++ slave->dev->name, active); ++ } ++ read_unlock(&bond->lock); ++ if (count) ++ buf[count-1] = '\n'; /* eat the leftover space */ ++ rtnl_unlock(); ++ ++ return count; ++} ++static DEVICE_ATTR(ad_active_slaves, S_IRUGO, bonding_show_ad_active_slaves, NULL); ++ ++/* ++ * Show and set 802.3ad system priority. ++ */ ++static ssize_t bonding_show_ad_sys_priority(struct device *d, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct bonding *bond = to_bond(d); ++ int count = 0; ++ ++ if (bond->params.mode == BOND_MODE_8023AD) { ++ count = sprintf(buf, "%d\n", bond->params.sys_priority); ++ } ++ ++ return count; ++} ++ ++static ssize_t bonding_store_ad_sys_priority(struct device *d, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ u16 new_value; ++ int ret; ++ struct bonding *bond = to_bond(d); ++ ++ if (bond->params.mode != BOND_MODE_8023AD) { ++ pr_err("%s: Unable to update sys priority because bond is not in 802.3ad mode.\n", ++ bond->dev->name); ++ ret = -EPERM; ++ goto out; ++ } ++ ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ ++ ret = kstrtou16(buf, 0, &new_value); ++ if (ret < 0) { ++ pr_err("%s: Ignoring invalid sys priority value %s.\n", ++ bond->dev->name, buf); ++ goto out_unlock; ++ } ++ ret = count; ++ ++ pr_info("%s: Setting sys priority value to %u\n", ++ bond->dev->name, new_value); ++ bond->params.sys_priority = new_value; ++ bond_3ad_update_sys_priority(bond); ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ ++out_unlock: ++ rtnl_unlock(); ++out: ++ return ret; ++} ++static DEVICE_ATTR(ad_sys_priority, S_IRUGO | S_IWUSR, ++ bonding_show_ad_sys_priority, bonding_store_ad_sys_priority); ++ ++ ++/* ++ * Show and set 802.3ad system mac address. ++ */ ++static ssize_t bonding_show_ad_sys_mac_addr(struct device *d, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct bonding *bond = to_bond(d); ++ int count = 0; ++ ++ if (bond->params.mode == BOND_MODE_8023AD) ++ count = sprintf(buf, "%pM\n", bond->params.sys_mac_addr); ++ ++ return count; ++} ++ ++static ssize_t bonding_store_ad_sys_mac_addr(struct device *d, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int ret = count; ++ struct bonding *bond = to_bond(d); ++ u8 new_mac[ETH_ALEN]; ++ ++ if (bond->params.mode != BOND_MODE_8023AD) { ++ pr_err("%s: Unable to update sys mac because bond is not in 802.3ad mode.\n", ++ bond->dev->name); ++ ret = -EPERM; ++ goto out; ++ } ++ ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ ++ if (!mac_pton(buf, new_mac)) { ++ pr_err("%s: Ignoring invalid sys mac value %s.\n", ++ bond->dev->name, buf); ++ ret = -EINVAL; ++ goto out_unlock; ++ } ++ ++ pr_info("%s: Setting sys mac value to %pM\n", ++ bond->dev->name, new_mac); ++ memcpy(&(bond->params.sys_mac_addr), new_mac, ETH_ALEN); ++ bond_3ad_update_sys_mac_addr(bond); ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ ++out_unlock: ++ rtnl_unlock(); ++out: ++ return ret; ++} ++static DEVICE_ATTR(ad_sys_mac_addr, S_IRUGO | S_IWUSR, ++ bonding_show_ad_sys_mac_addr, bonding_store_ad_sys_mac_addr); ++ ++ ++/* + * Show the queue_ids of the slaves in the current bond. + */ + static ssize_t bonding_show_queue_id(struct device *d, +@@ -1523,8 +2014,8 @@ static ssize_t bonding_store_queue_id(struct device *d, + + /* Actually set the qids for the slave */ + update_slave->queue_id = qid; +- + read_unlock(&bond->lock); ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); + out: + rtnl_unlock(); + return ret; +@@ -1562,6 +2053,9 @@ static ssize_t bonding_store_slaves_active(struct device *d, + struct bonding *bond = to_bond(d); + struct slave *slave; + ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ + if (sscanf(buf, "%d", &new_value) != 1) { + pr_err("%s: no all_slaves_active value specified.\n", + bond->dev->name); +@@ -1591,7 +2085,9 @@ static ssize_t bonding_store_slaves_active(struct device *d, + } + } + read_unlock(&bond->lock); ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); + out: ++ rtnl_unlock(); + return ret; + } + static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR, +@@ -1630,9 +2126,13 @@ static ssize_t bonding_store_resend_igmp(struct device *d, + goto out; + } + ++ if (!rtnl_trylock()) ++ return restart_syscall(); + pr_info("%s: Setting resend_igmp to %d.\n", + bond->dev->name, new_value); + bond->params.resend_igmp = new_value; ++ call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev); ++ rtnl_unlock(); + out: + return ret; + } +@@ -1665,10 +2165,18 @@ static struct attribute *per_bond_attrs[] = { + &dev_attr_ad_actor_key.attr, + &dev_attr_ad_partner_key.attr, + &dev_attr_ad_partner_mac.attr, ++ &dev_attr_ad_active_slaves.attr, ++ &dev_attr_ad_sys_priority.attr, ++ &dev_attr_ad_sys_mac_addr.attr, + &dev_attr_queue_id.attr, + &dev_attr_all_slaves_active.attr, + &dev_attr_resend_igmp.attr, + &dev_attr_min_links.attr, ++ &dev_attr_lacp_bypass_allow.attr, ++ &dev_attr_lacp_bypass_active.attr, ++ &dev_attr_lacp_bypass_period.attr, ++ &dev_attr_lacp_bypass_all_active.attr, ++ &dev_attr_clag_enable.attr, + NULL, + }; + +@@ -1730,3 +2238,39 @@ void bond_prepare_sysfs_group(struct bonding *bond) + bond->dev->sysfs_groups[0] = &bonding_group; + } + ++static struct kobj_type slave_ktype = { ++#ifdef CONFIG_SYSFS ++ .sysfs_ops = &slave_sysfs_ops, ++#endif ++}; ++ ++int bond_sysfs_slave_add(struct slave *slave) ++{ ++ const struct slave_attribute **a; ++ int err; ++ ++ err = kobject_init_and_add(&slave->kobj, &slave_ktype, ++ &(slave->dev->dev.kobj), "bonding_slave"); ++ if (err) ++ return err; ++ ++ for (a = slave_attrs; *a; ++a) { ++ err = sysfs_create_file(&slave->kobj, &((*a)->attr)); ++ if (err) { ++ kobject_del(&slave->kobj); ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++void bond_sysfs_slave_del(struct slave *slave) ++{ ++ const struct slave_attribute **a; ++ ++ for (a = slave_attrs; *a; ++a) ++ sysfs_remove_file(&slave->kobj, &((*a)->attr)); ++ ++ kobject_del(&slave->kobj); ++} +diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h +index 1aecc37..a4a984f 100644 +--- a/drivers/net/bonding/bonding.h ++++ b/drivers/net/bonding/bonding.h +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include "bond_3ad.h" + #include "bond_alb.h" + +@@ -69,6 +70,8 @@ + set_fs(fs); \ + res; }) + ++#define BOND_MODE(bond) ((bond)->params.mode) ++ + /** + * bond_for_each_slave_from - iterate the slaves list from a starting point + * @bond: the bond holding this list. +@@ -149,12 +152,19 @@ struct bond_params { + int lacp_fast; + unsigned int min_links; + int ad_select; ++ u16 sys_priority; ++ u8 sys_mac_addr[ETH_ALEN]; + char primary[IFNAMSIZ]; + int primary_reselect; + __be32 arp_targets[BOND_MAX_ARP_TARGETS]; + int tx_queues; + int all_slaves_active; + int resend_igmp; ++ int lacp_bypass_allow; ++ int lacp_bypass_active; ++ u32 lacp_bypass_period; ++ int lacp_bypass_all_active; ++ u8 clag_enable; + }; + + struct bond_parm_tbl { +@@ -182,18 +192,22 @@ struct slave { + s8 new_link; + u8 backup:1, /* indicates backup slave. Value corresponds with + BOND_STATE_ACTIVE and BOND_STATE_BACKUP */ +- inactive:1; /* indicates inactive slave */ ++ inactive:1, /* indicates inactive slave */ ++ individual:1; + u8 duplex; + u32 original_mtu; + u32 link_failure_count; + u32 speed; + u16 queue_id; + u8 perm_hwaddr[ETH_ALEN]; ++ int lacp_bypass_priority; + struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */ + struct tlb_slave_info tlb_info; + #ifdef CONFIG_NET_POLL_CONTROLLER + struct netpoll *np; + #endif ++ struct kobject kobj; ++ struct rtnl_link_stats64 slave_stats; + }; + + /* +@@ -248,6 +262,7 @@ struct bonding { + /* debugging suport via debugfs */ + struct dentry *debug_dir; + #endif /* CONFIG_DEBUG_FS */ ++ struct rtnl_link_stats64 bond_stats; + }; + + static inline bool bond_vlan_used(struct bonding *bond) +@@ -258,6 +273,9 @@ static inline bool bond_vlan_used(struct bonding *bond) + #define bond_slave_get_rcu(dev) \ + ((struct slave *) rcu_dereference(dev->rx_handler_data)) + ++#define bond_slave_get_rtnl(dev) \ ++ ((struct slave *) rtnl_dereference(dev->rx_handler_data)) ++ + /** + * Returns NULL if the net_device does not belong to any of the bond's slaves + * +@@ -293,16 +311,20 @@ static inline bool bond_is_lb(const struct bonding *bond) + bond->params.mode == BOND_MODE_ALB); + } + +-static inline void bond_set_active_slave(struct slave *slave) ++static inline bool bond_mode_uses_primary(int mode) + { +- slave->backup = 0; ++ return mode == BOND_MODE_ACTIVEBACKUP || mode == BOND_MODE_TLB || ++ mode == BOND_MODE_ALB; + } + +-static inline void bond_set_backup_slave(struct slave *slave) ++static inline bool bond_uses_primary(struct bonding *bond) + { +- slave->backup = 1; ++ return bond_mode_uses_primary(BOND_MODE(bond)); + } + ++void bond_set_active_slave(struct slave *slave); ++void bond_set_backup_slave(struct slave *slave); ++ + static inline int bond_slave_state(struct slave *slave) + { + return slave->backup; +@@ -386,6 +408,8 @@ int bond_create(struct net *net, const char *name); + int bond_create_sysfs(struct bond_net *net); + void bond_destroy_sysfs(struct bond_net *net); + void bond_prepare_sysfs_group(struct bonding *bond); ++int bond_sysfs_slave_add(struct slave *slave); ++void bond_sysfs_slave_del(struct slave *slave); + int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave); + void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave); + int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev); +@@ -403,6 +427,7 @@ void bond_debug_register(struct bonding *bond); + void bond_debug_unregister(struct bonding *bond); + void bond_debug_reregister(struct bonding *bond); + const char *bond_mode_name(int mode); ++void bond_set_clag_enable(struct bonding *bond, u8 clag_enable); + + struct bond_net { + struct net * net; /* Associated network namespace */ +diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c +index 3105961..e560bcb 100644 +--- a/drivers/net/can/softing/softing_fw.c ++++ b/drivers/net/can/softing/softing_fw.c +@@ -237,11 +237,8 @@ int softing_load_app_fw(const char *file, struct softing *card) + int8_t type_end = 0, type_entrypoint = 0; + + ret = request_firmware(&fw, file, &card->pdev->dev); +- if (ret) { +- dev_alert(&card->pdev->dev, "request_firmware(%s) got %i\n", +- file, ret); ++ if (ret) + return ret; +- } + dev_dbg(&card->pdev->dev, "firmware(%s) got %lu bytes\n", + file, (unsigned long)fw->size); + /* parse the firmware */ +diff --git a/drivers/net/dpa/Makefile b/drivers/net/dpa/Makefile +new file mode 100644 +index 0000000..0e59076 +--- /dev/null ++++ b/drivers/net/dpa/Makefile +@@ -0,0 +1,21 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++ ++EXTRA_CFLAGS += -I$(NET_DPA) ++ ++#Netcomm SW tree ++obj-$(CONFIG_FSL_FMAN) += NetCommSw/ ++obj-$(CONFIG_FSL_DPA_1588) += dpaa_1588.o ++obj-$(CONFIG_DPAA_ETH_SG_SUPPORT) += fsl-dpa-sg.o ++obj-$(CONFIG_DPA) += fsl-mac.o fsl-dpa.o ++obj-$(CONFIG_DPA_OFFLINE_PORTS) += fsl-oh.o ++ ++fsl-dpa-objs := dpa-ethtool.o dpaa_eth.o dpaa_eth_sysfs.o xgmac_mdio.o memac_mdio.o ++fsl-dpa-sg-objs := dpaa_eth_sg.o ++fsl-mac-objs := mac.o mac-api.o ++fsl-oh-objs := offline_port.o +diff --git a/drivers/net/dpa/NetCommSw/Kconfig b/drivers/net/dpa/NetCommSw/Kconfig +new file mode 100644 +index 0000000..e640465 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Kconfig +@@ -0,0 +1,112 @@ ++menu "Frame Manager support" ++ ++menuconfig FSL_FMAN ++ bool "Freescale Frame Manager (datapath) support" ++ # depends on PPC_E500MC ++ default y ++ ---help--- ++ If unsure, say Y. ++ ++if FSL_FMAN ++ ++config FSL_FMAN_TEST ++ bool "FMan test module" ++ default n ++ ---help--- ++ This option compiles test code for FMan. ++ ++menu "FMAN Processor support" ++choice ++ depends on FSL_FMAN ++ prompt "Processor Type" ++ ++config FMAN_P3040_P4080_P5020 ++ bool "P3040 P4080 5020" ++ ++config FMAN_P1023 ++ bool "P1023" ++ ++config FMAN_T4240 ++ bool "T4240" ++ ++endchoice ++endmenu ++ ++config FMAN_RESOURCE_ALLOCATION_ALGORITHM ++ bool "Enable FMan dynamic resource allocation algorithm" ++ default n ++ ---help--- ++ Enables algorithm for dynamic resource allocation ++ ++config FMAN_DISABLE_OH_TO_REUSE_RESOURCES ++ depends on FMAN_RESOURCE_ALLOCATION_ALGORITHM ++ bool "Disable offline parsing ports to reuse resources" ++ default n ++ ---help--- ++ Redistributes FMan OH's resources to all other ports, ++ thus enabling other configurations. ++ ++config FMAN_MIB_CNT_OVF_IRQ_EN ++ bool "Enable the dTSEC MIB counters overflow interrupt" ++ default n ++ ---help--- ++ Enable the dTSEC MIB counters overflow interrupt to get ++ accurate MIB counters values. Enabled it compensates ++ for the counters overflow but reduces performance and ++ triggers error messages in HV setups. ++ ++ ++config FSL_FM_MAX_FRAME_SIZE ++ int "Maximum L2 frame size" ++ depends on FSL_FMAN ++ range 64 9600 ++ default "1522" ++ help ++ Configure this in relation to the maximum possible MTU of your ++ network configuration. In particular, one would need to ++ increase this value in order to use jumbo frames. ++ FSL_FM_MAX_FRAME_SIZE must accomodate the Ethernet FCS (4 bytes) ++ and one ETH+VLAN header (18 bytes), to a total of 22 bytes in ++ excess of the desired L3 MTU. ++ ++ Note that having too large a FSL_FM_MAX_FRAME_SIZE (much larger ++ than the actual MTU) may lead to buffer exhaustion, especially ++ in the case of badly fragmented datagrams on the Rx path. ++ Conversely, having a FSL_FM_MAX_FRAME_SIZE smaller than the actual ++ MTU will lead to frames being dropped. ++ ++ This can be overridden by specifying "fsl_fm_max_frm" in ++ the kernel bootargs: ++ * in Hypervisor-based scenarios, by adding a "chosen" node ++ with the "bootargs" property specifying ++ "fsl_fm_max_frm="; ++ * in non-Hypervisor-based scenarios, via u-boot's env, by ++ modifying the "bootargs" env variable. ++ ++config FSL_FM_RX_EXTRA_HEADROOM ++ int "Add extra headroom at beginning of data buffers" ++ depends on FSL_FMAN ++ range 0 384 ++ default "64" ++ help ++ Configure this to tell the Frame Manager to reserve some extra ++ space at the beginning of a data buffer on the receive path, ++ before Internal Context fields are copied. This is in addition ++ to the private data area already reserved for driver internal ++ use. The option does not affect in any way the layout of ++ transmitted buffers. You may be required to enable the config ++ option FMAN_RESOURCE_ALLOCATION_ALGORITHM and also ++ FMAN_DISABLE_OH_TO_REUSE_RESOURCES to have enough resources ++ when using this option and also supporting jumbo frames. ++ ++ This setting can be overridden by specifying ++ "fsl_fm_rx_extra_headroom" in the kernel bootargs: ++ * in Hypervisor-based scenarios, by adding a "chosen" node ++ with the "bootargs" property specifying ++ "fsl_fm_rx_extra_headroom="; ++ * in non-Hypervisor-based scenarios, via u-boot's env, by ++ modifying the "bootargs" env variable. ++ ++endif # FSL_FMAN ++ ++endmenu +diff --git a/drivers/net/dpa/NetCommSw/Makefile b/drivers/net/dpa/NetCommSw/Makefile +new file mode 100644 +index 0000000..c21d5a5 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Makefile +@@ -0,0 +1,11 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++# ++obj-y += etc/ ++obj-y += Peripherals/FM/ ++obj-y += src/ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/HC/Makefile b/drivers/net/dpa/NetCommSw/Peripherals/FM/HC/Makefile +new file mode 100644 +index 0000000..3ec3824 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/HC/Makefile +@@ -0,0 +1,15 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/dpa/NetCommSw/Peripherals/FM/inc ++ ++EXTRA_CFLAGS += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-Hc.o ++ ++fsl-ncsw-Hc-objs := hc.o +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/HC/hc.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/HC/hc.c +new file mode 100644 +index 0000000..dca9478 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/HC/hc.c +@@ -0,0 +1,1191 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "std_ext.h" ++#include "error_ext.h" ++#include "sprint_ext.h" ++#include "string_ext.h" ++ ++#include "fm_common.h" ++#include "fm_hc.h" ++ ++ ++/**************************************************************************//** ++ @Description defaults ++*//***************************************************************************/ ++#define DEFAULT_dataMemId 0 ++ ++#define HC_HCOR_OPCODE_PLCR_PRFL 0x0 ++#define HC_HCOR_OPCODE_KG_SCM 0x1 ++#define HC_HCOR_OPCODE_SYNC 0x2 ++#define HC_HCOR_OPCODE_CC 0x3 ++#define HC_HCOR_OPCODE_CC_CAPWAP_REASSM_TIMEOUT 0x5 ++#define HC_HCOR_OPCODE_CC_IP_REASSM_TIMEOUT 0x10 ++#define HC_HCOR_OPCODE_CC_IP_FRAG_INITIALIZATION 0x11 ++#define HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_ACTIVE_SHIFT 24 ++#define HC_HCOR_EXTRA_REG_IP_REASSM_TIMEOUT_TSBS_SHIFT 24 ++#define HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_RES_SHIFT 16 ++#define HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_RES_MASK 0xF ++#define HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_CMD_SHIFT 24 ++#define HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_BPID 16 ++ ++#define HC_HCOR_GBL 0x20000000 ++ ++#define HC_HCOR_KG_SCHEME_COUNTER 0x00000400 ++ ++#if (DPAA_VERSION == 10) ++#define HC_HCOR_KG_SCHEME_REGS_MASK 0xFFFFF800 ++#else ++#define HC_HCOR_KG_SCHEME_REGS_MASK 0xFFFFFE00 ++#endif /* (DPAA_VERSION == 10) */ ++ ++#define SIZE_OF_HC_FRAME_PORT_REGS (sizeof(t_HcFrame)-sizeof(struct fman_kg_scheme_regs)+sizeof(t_FmPcdKgPortRegs)) ++#define SIZE_OF_HC_FRAME_SCHEME_REGS sizeof(t_HcFrame) ++#define SIZE_OF_HC_FRAME_PROFILES_REGS (sizeof(t_HcFrame)-sizeof(struct fman_kg_scheme_regs)+sizeof(t_FmPcdPlcrProfileRegs)) ++#define SIZE_OF_HC_FRAME_PROFILE_CNT (sizeof(t_HcFrame)-sizeof(t_FmPcdPlcrProfileRegs)+sizeof(uint32_t)) ++#define SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC 16 ++ ++#define HC_CMD_POOL_SIZE (INTG_MAX_NUM_OF_CORES) ++ ++#define BUILD_FD(len) \ ++do { \ ++ memset(&fmFd, 0, sizeof(t_DpaaFD)); \ ++ DPAA_FD_SET_ADDR(&fmFd, p_HcFrame); \ ++ DPAA_FD_SET_OFFSET(&fmFd, 0); \ ++ DPAA_FD_SET_LENGTH(&fmFd, len); \ ++} while (0) ++ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++typedef _Packed struct t_FmPcdKgPortRegs { ++ volatile uint32_t spReg; ++ volatile uint32_t cppReg; ++} _PackedType t_FmPcdKgPortRegs; ++ ++typedef _Packed struct t_HcFrame { ++ volatile uint32_t opcode; ++ volatile uint32_t actionReg; ++ volatile uint32_t extraReg; ++ volatile uint32_t commandSequence; ++ union { ++ struct fman_kg_scheme_regs schemeRegs; ++ struct fman_kg_scheme_regs schemeRegsWithoutCounter; ++ t_FmPcdPlcrProfileRegs profileRegs; ++ volatile uint32_t singleRegForWrite; /* for writing SP, CPP, profile counter */ ++ t_FmPcdKgPortRegs portRegsForRead; ++ volatile uint32_t clsPlanEntries[CLS_PLAN_NUM_PER_GRP]; ++ t_FmPcdCcCapwapReassmTimeoutParams ccCapwapReassmTimeout; ++ t_FmPcdCcIpReassmTimeoutParams ccIpReassmTimeout; ++ } hcSpecificData; ++} _PackedType t_HcFrame; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++typedef struct t_FmHc { ++ t_Handle h_FmPcd; ++ t_Handle h_HcPortDev; ++ t_FmPcdQmEnqueueCallback *f_QmEnqueue; /**< A callback for enqueuing frames to the QM */ ++ t_Handle h_QmArg; /**< A handle to the QM module */ ++ uint8_t dataMemId; /**< Memory partition ID for data buffers */ ++ ++ uint32_t seqNum[HC_CMD_POOL_SIZE]; /* FIFO of seqNum to use when ++ taking buffer */ ++ uint32_t nextSeqNumLocation; /* seqNum location in seqNum[] for next buffer */ ++ volatile bool enqueued[HC_CMD_POOL_SIZE]; /* HC is active - frame is enqueued ++ and not confirmed yet */ ++ t_HcFrame *p_Frm[HC_CMD_POOL_SIZE]; ++} t_FmHc; ++ ++ ++static t_Error FillBufPool(t_FmHc *p_FmHc) ++{ ++ uint32_t i; ++ ++ ASSERT_COND(p_FmHc); ++ ++ for (i = 0; i < HC_CMD_POOL_SIZE; i++) ++ { ++#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ++ p_FmHc->p_Frm[i] = (t_HcFrame *)XX_MallocSmart((sizeof(t_HcFrame) + (16 - (sizeof(t_FmHc) % 16))), ++ p_FmHc->dataMemId, ++ 16); ++#else ++ p_FmHc->p_Frm[i] = (t_HcFrame *)XX_MallocSmart(sizeof(t_HcFrame), ++ p_FmHc->dataMemId, ++ 16); ++#endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */ ++ if (!p_FmHc->p_Frm[i]) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM HC frames!")); ++ } ++ ++ /* Initialize FIFO of seqNum to use during GetBuf */ ++ for (i = 0; i < HC_CMD_POOL_SIZE; i++) ++ { ++ p_FmHc->seqNum[i] = i; ++ } ++ p_FmHc->nextSeqNumLocation = 0; ++ ++ return E_OK; ++} ++ ++static __inline__ t_HcFrame * GetBuf(t_FmHc *p_FmHc, uint32_t *p_SeqNum) ++{ ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_FmHc); ++ ++ intFlags = FmPcdLock(p_FmHc->h_FmPcd); ++ ++ if (p_FmHc->nextSeqNumLocation == HC_CMD_POOL_SIZE) ++ { ++ /* No more buffers */ ++ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags); ++ return NULL; ++ } ++ ++ *p_SeqNum = p_FmHc->seqNum[p_FmHc->nextSeqNumLocation]; ++ p_FmHc->nextSeqNumLocation++; ++ ++ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags); ++ return p_FmHc->p_Frm[*p_SeqNum]; ++} ++ ++static __inline__ void PutBuf(t_FmHc *p_FmHc, t_HcFrame *p_Buf, uint32_t seqNum) ++{ ++ uint32_t intFlags; ++ ++ UNUSED(p_Buf); ++ ++ intFlags = FmPcdLock(p_FmHc->h_FmPcd); ++ ASSERT_COND(p_FmHc->nextSeqNumLocation); ++ p_FmHc->nextSeqNumLocation--; ++ p_FmHc->seqNum[p_FmHc->nextSeqNumLocation] = seqNum; ++ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags); ++} ++ ++static __inline__ t_Error EnQFrm(t_FmHc *p_FmHc, t_DpaaFD *p_FmFd, uint32_t seqNum) ++{ ++ t_Error err = E_OK; ++ uint32_t intFlags; ++ uint32_t timeout=100; ++ ++ intFlags = FmPcdLock(p_FmHc->h_FmPcd); ++ ASSERT_COND(!p_FmHc->enqueued[seqNum]); ++ p_FmHc->enqueued[seqNum] = TRUE; ++ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags); ++ DBG(TRACE, ("Send Hc, SeqNum %d, buff@0x%x, fd offset 0x%x", ++ seqNum, ++ DPAA_FD_GET_ADDR(p_FmFd), ++ DPAA_FD_GET_OFFSET(p_FmFd))); ++ err = p_FmHc->f_QmEnqueue(p_FmHc->h_QmArg, (void *)p_FmFd); ++ if (err) ++ RETURN_ERROR(MINOR, err, ("HC enqueue failed")); ++ ++ while (p_FmHc->enqueued[seqNum] && --timeout) ++ XX_UDelay(100); ++ ++ if (!timeout) ++ RETURN_ERROR(MINOR, E_TIMEOUT, ("HC Callback, timeout exceeded")); ++ ++ return err; ++} ++ ++ ++t_Handle FmHcConfigAndInit(t_FmHcParams *p_FmHcParams) ++{ ++ t_FmHc *p_FmHc; ++ t_FmPortParams fmPortParam; ++ t_Error err; ++ ++ p_FmHc = (t_FmHc *)XX_Malloc(sizeof(t_FmHc)); ++ if (!p_FmHc) ++ { ++ REPORT_ERROR(MINOR, E_NO_MEMORY, ("HC obj")); ++ return NULL; ++ } ++ memset(p_FmHc,0,sizeof(t_FmHc)); ++ ++ p_FmHc->h_FmPcd = p_FmHcParams->h_FmPcd; ++ p_FmHc->f_QmEnqueue = p_FmHcParams->params.f_QmEnqueue; ++ p_FmHc->h_QmArg = p_FmHcParams->params.h_QmArg; ++ p_FmHc->dataMemId = DEFAULT_dataMemId; ++ ++ err = FillBufPool(p_FmHc); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ FmHcFree(p_FmHc); ++ return NULL; ++ } ++ ++ if (!FmIsMaster(p_FmHcParams->h_Fm)) ++ return (t_Handle)p_FmHc; ++ ++ memset(&fmPortParam, 0, sizeof(fmPortParam)); ++ fmPortParam.baseAddr = p_FmHcParams->params.portBaseAddr; ++ fmPortParam.portType = e_FM_PORT_TYPE_OH_HOST_COMMAND; ++ fmPortParam.portId = p_FmHcParams->params.portId; ++ fmPortParam.liodnBase = p_FmHcParams->params.liodnBase; ++ fmPortParam.h_Fm = p_FmHcParams->h_Fm; ++ ++ fmPortParam.specificParams.nonRxParams.errFqid = p_FmHcParams->params.errFqid; ++ fmPortParam.specificParams.nonRxParams.dfltFqid = p_FmHcParams->params.confFqid; ++ fmPortParam.specificParams.nonRxParams.qmChannel = p_FmHcParams->params.qmChannel; ++ ++ p_FmHc->h_HcPortDev = FM_PORT_Config(&fmPortParam); ++ if (!p_FmHc->h_HcPortDev) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("FM HC port!")); ++ XX_Free(p_FmHc); ++ return NULL; ++ } ++ ++ /* final init */ ++ err = FM_PORT_Init(p_FmHc->h_HcPortDev); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MAJOR, err, ("FM HC port init!")); ++ FmHcFree(p_FmHc); ++ return NULL; ++ } ++ ++ err = FM_PORT_Enable(p_FmHc->h_HcPortDev); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MAJOR, err, ("FM HC port enable!")); ++ FmHcFree(p_FmHc); ++ return NULL; ++ } ++ ++ return (t_Handle)p_FmHc; ++} ++ ++t_Handle FmGcGetHcPortDevH(t_Handle h_FmHc) ++{ ++ t_FmHc *p_FmHc = (t_FmHc *)h_FmHc; ++ ++ return (p_FmHc) ? p_FmHc->h_HcPortDev : NULL; ++} ++ ++void FmHcFree(t_Handle h_FmHc) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ int i; ++ ++ if (!p_FmHc) ++ return; ++ ++ for (i=0; ip_Frm[i]) ++ XX_FreeSmart(p_FmHc->p_Frm[i]); ++ else ++ break; ++ ++ if (p_FmHc->h_HcPortDev) ++ FM_PORT_Free(p_FmHc->h_HcPortDev); ++ ++ XX_Free(p_FmHc); ++} ++ ++/*****************************************************************************/ ++t_Error FmHcSetFramesDataMemory(t_Handle h_FmHc, ++ uint8_t memId) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ int i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmHc, E_INVALID_HANDLE); ++ ++ p_FmHc->dataMemId = memId; ++ ++ for (i=0; ip_Frm[i]) ++ XX_FreeSmart(p_FmHc->p_Frm[i]); ++ ++ return FillBufPool(p_FmHc); ++} ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++t_Error FmHcDumpRegs(t_Handle h_FmHc) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmHc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmHc->h_HcPortDev, E_INVALID_HANDLE); ++ ++ return FM_PORT_DumpRegs(p_FmHc->h_HcPortDev); ++ ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++void FmHcTxConf(t_Handle h_FmHc, t_DpaaFD *p_Fd) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_FmHc); ++ ++ intFlags = FmPcdLock(p_FmHc->h_FmPcd); ++ p_HcFrame = (t_HcFrame *)PTR_MOVE(DPAA_FD_GET_ADDR(p_Fd), DPAA_FD_GET_OFFSET(p_Fd)); ++ ++ DBG(TRACE, ("Hc Conf, SeqNum %d, FD@0x%x, fd offset 0x%x", ++ p_HcFrame->commandSequence, DPAA_FD_GET_ADDR(p_Fd), DPAA_FD_GET_OFFSET(p_Fd))); ++ ++ if (!(p_FmHc->enqueued[p_HcFrame->commandSequence])) ++ REPORT_ERROR(MINOR, E_INVALID_FRAME, ("Not an Host-Command frame received!")); ++ else ++ p_FmHc->enqueued[p_HcFrame->commandSequence] = FALSE; ++ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags); ++} ++ ++t_Error FmHcPcdKgSetScheme(t_Handle h_FmHc, ++ t_Handle h_Scheme, ++ struct fman_kg_scheme_regs *p_SchemeRegs, ++ bool updateCounter) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_Error err = E_OK; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint8_t physicalSchemeId; ++ uint32_t seqNum; ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme); ++ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, updateCounter); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ memcpy(&p_HcFrame->hcSpecificData.schemeRegs, p_SchemeRegs, sizeof(struct fman_kg_scheme_regs)); ++ if (!updateCounter) ++ { ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_dv0 = p_SchemeRegs->kgse_dv0; ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_dv1 = p_SchemeRegs->kgse_dv1; ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_ccbs = p_SchemeRegs->kgse_ccbs; ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_mv = p_SchemeRegs->kgse_mv; ++ } ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdKgDeleteScheme(t_Handle h_FmHc, t_Handle h_Scheme) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_Error err = E_OK; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint8_t physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme); ++ uint32_t seqNum; ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ memset(&p_HcFrame->hcSpecificData.schemeRegs, 0, sizeof(struct fman_kg_scheme_regs)); ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdKgCcGetSetParams(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_Error err = E_OK; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint8_t relativeSchemeId; ++ uint8_t physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme); ++ uint32_t tmpReg32 = 0; ++ uint32_t seqNum; ++ ++ /* Scheme is locked by calling routine */ ++ /* WARNING - this lock will not be efficient if other HC routine will attempt to change ++ * "kgse_mode" or "kgse_om" without locking scheme ! ++ */ ++ ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmHc->h_FmPcd, physicalSchemeId); ++ if ( relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ ++ if (!FmPcdKgGetPointedOwners(p_FmHc->h_FmPcd, relativeSchemeId) || ++ !(FmPcdKgGetRequiredAction(p_FmHc->h_FmPcd, relativeSchemeId) & requiredAction)) ++ { ++ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && ++ (FmPcdKgGetNextEngine(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_PLCR)) ++ { ++ if ((FmPcdKgIsDirectPlcr(p_FmHc->h_FmPcd, relativeSchemeId) == FALSE) || ++ (FmPcdKgIsDistrOnPlcrProfile(p_FmHc->h_FmPcd, relativeSchemeId) == TRUE)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this situation PP can not be with distribution and has to be shared")); ++ err = FmPcdPlcrCcGetSetParams(p_FmHc->h_FmPcd, FmPcdKgGetRelativeProfileId(p_FmHc->h_FmPcd, relativeSchemeId), requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ else /* From here we deal with KG-Schemes only */ ++ { ++ /* Pre change general code */ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ p_HcFrame->commandSequence = seqNum; ++ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC); ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ /* specific change */ ++ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && ++ ((FmPcdKgGetNextEngine(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_DONE) && ++ (FmPcdKgGetDoneAction(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_ENQ_FRAME))) ++ { ++ tmpReg32 = p_HcFrame->hcSpecificData.schemeRegs.kgse_mode; ++ ASSERT_COND(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_mode = tmpReg32 | NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ } ++ ++ if ((requiredAction & UPDATE_KG_NIA_CC_WA) && ++ (FmPcdKgGetNextEngine(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_CC)) ++ { ++ tmpReg32 = p_HcFrame->hcSpecificData.schemeRegs.kgse_mode; ++ ASSERT_COND(tmpReg32 & (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC)); ++ tmpReg32 &= ~NIA_FM_CTL_AC_CC; ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_mode = tmpReg32 | NIA_FM_CTL_AC_PRE_CC; ++ } ++ ++ if (requiredAction & UPDATE_KG_OPT_MODE) ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_om = value; ++ ++ if (requiredAction & UPDATE_KG_NIA) ++ { ++ tmpReg32 = p_HcFrame->hcSpecificData.schemeRegs.kgse_mode; ++ tmpReg32 &= ~(NIA_ENG_MASK | NIA_AC_MASK); ++ tmpReg32 |= value; ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_mode = tmpReg32; ++ } ++ ++ /* Post change general code */ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ } ++ ++ return E_OK; ++} ++ ++uint32_t FmHcPcdKgGetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_Error err; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint32_t retVal; ++ uint8_t relativeSchemeId; ++ uint8_t physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme); ++ uint32_t seqNum; ++ ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmHc->h_FmPcd, physicalSchemeId); ++ if ( relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ return 0; ++ } ++ ++ /* first read scheme and check that it is valid */ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ { ++ REPORT_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ return 0; ++ } ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ if (err != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return 0; ++ } ++ ++ if (!FmPcdKgHwSchemeIsValid(p_HcFrame->hcSpecificData.schemeRegs.kgse_mode)) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is invalid")); ++ return 0; ++ } ++ ++ retVal = p_HcFrame->hcSpecificData.schemeRegs.kgse_spc; ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ return retVal; ++} ++ ++t_Error FmHcPcdKgSetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t value) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_Error err = E_OK; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint8_t relativeSchemeId, physicalSchemeId; ++ uint32_t seqNum; ++ ++ physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme); ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmHc->h_FmPcd, physicalSchemeId); ++ if ( relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ ++ /* first read scheme and check that it is valid */ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_COUNTER; ++ /* write counter */ ++ p_HcFrame->hcSpecificData.singleRegForWrite = value; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ return err; ++} ++ ++t_Error FmHcPcdKgSetClsPlan(t_Handle h_FmHc, t_FmPcdKgInterModuleClsPlanSet *p_Set) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint32_t i; ++ uint32_t seqNum; ++ t_Error err = E_OK; ++ ++ ASSERT_COND(p_FmHc); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ for (i = p_Set->baseEntry; i < (p_Set->baseEntry+p_Set->numOfClsPlanEntries); i+=8) ++ { ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildWriteClsPlanBlockActionReg((uint8_t)(i / CLS_PLAN_NUM_PER_GRP)); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ memcpy((void*)&p_HcFrame->hcSpecificData.clsPlanEntries, (void *)&p_Set->vectors[i-p_Set->baseEntry], CLS_PLAN_NUM_PER_GRP*sizeof(uint32_t)); ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ } ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ return err; ++} ++ ++t_Error FmHcPcdKgDeleteClsPlan(t_Handle h_FmHc, uint8_t grpId) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet; ++ ++ p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet)); ++ if (!p_ClsPlanSet) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set")); ++ ++ memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet)); ++ ++ p_ClsPlanSet->baseEntry = FmPcdKgGetClsPlanGrpBase(p_FmHc->h_FmPcd, grpId); ++ p_ClsPlanSet->numOfClsPlanEntries = FmPcdKgGetClsPlanGrpSize(p_FmHc->h_FmPcd, grpId); ++ ASSERT_COND(p_ClsPlanSet->numOfClsPlanEntries <= FM_PCD_MAX_NUM_OF_CLS_PLANS); ++ ++ if (FmHcPcdKgSetClsPlan(p_FmHc, p_ClsPlanSet) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ XX_Free(p_ClsPlanSet); ++ ++ FmPcdKgDestroyClsPlanGrp(p_FmHc->h_FmPcd, grpId); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdCcCapwapTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcCapwapReassmTimeoutParams *p_CcCapwapReassmTimeoutParams ) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err; ++ uint32_t seqNum; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC_CAPWAP_REASSM_TIMEOUT); ++ memcpy(&p_HcFrame->hcSpecificData.ccCapwapReassmTimeout, p_CcCapwapReassmTimeoutParams, sizeof(t_FmPcdCcCapwapReassmTimeoutParams)); ++ p_HcFrame->commandSequence = seqNum; ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ return err; ++} ++ ++t_Error FmHcPcdCcIpFragScratchPollCmd(t_Handle h_FmHc, bool fill, t_FmPcdCcFragScratchPoolCmdParams *p_FmPcdCcFragScratchPoolCmdParams) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err; ++ uint32_t seqNum; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC_IP_FRAG_INITIALIZATION); ++ p_HcFrame->actionReg = (uint32_t)(((fill == TRUE) ? 0 : 1) << HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_CMD_SHIFT); ++ p_HcFrame->actionReg |= p_FmPcdCcFragScratchPoolCmdParams->bufferPoolId << HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_BPID; ++ if (fill == TRUE) ++ { ++ p_HcFrame->extraReg = p_FmPcdCcFragScratchPoolCmdParams->numOfBuffers; ++ } ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ p_FmPcdCcFragScratchPoolCmdParams->numOfBuffers = p_HcFrame->extraReg; ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ return E_OK; ++} ++ ++t_Error FmHcPcdCcIpTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcIpReassmTimeoutParams *p_CcIpReassmTimeoutParams, uint8_t *p_Result) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err; ++ uint32_t seqNum; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC_IP_REASSM_TIMEOUT); ++ p_HcFrame->actionReg = (uint32_t)((p_CcIpReassmTimeoutParams->activate ? 0 : 1) << HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_ACTIVE_SHIFT); ++ p_HcFrame->extraReg = (p_CcIpReassmTimeoutParams->tsbs << HC_HCOR_EXTRA_REG_IP_REASSM_TIMEOUT_TSBS_SHIFT) | p_CcIpReassmTimeoutParams->iprcpt; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ *p_Result = (uint8_t) ++ ((p_HcFrame->actionReg >> HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_RES_SHIFT) & HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_RES_MASK); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ return E_OK; ++} ++ ++t_Error FmHcPcdPlcrCcGetSetParams(t_Handle h_FmHc,uint16_t absoluteProfileId, uint32_t requiredAction) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err; ++ uint32_t tmpReg32 = 0; ++ uint32_t requiredActionTmp, pointedOwnersTmp; ++ uint32_t seqNum; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0); ++ ++ /* Profile is locked by calling routine */ ++ /* WARNING - this lock will not be efficient if other HC routine will attempt to change ++ * "fmpl_pegnia" "fmpl_peynia" or "fmpl_pernia" without locking Profile ! ++ */ ++ ++ requiredActionTmp = FmPcdPlcrGetRequiredAction(p_FmHc->h_FmPcd, absoluteProfileId); ++ pointedOwnersTmp = FmPcdPlcrGetPointedOwners(p_FmHc->h_FmPcd, absoluteProfileId); ++ ++ if (!pointedOwnersTmp || !(requiredActionTmp & requiredAction)) ++ { ++ if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) ++ { ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ /* first read scheme and check that it is valid */ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildReadPlcrActionReg(absoluteProfileId); ++ p_HcFrame->extraReg = 0x00008000; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC); ++ ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ tmpReg32 = p_HcFrame->hcSpecificData.profileRegs.fmpl_pegnia; ++ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); ++ } ++ ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId); ++ p_HcFrame->actionReg |= FmPcdPlcrBuildNiaProfileReg(TRUE, FALSE, FALSE); ++ p_HcFrame->extraReg = 0x00008000; ++ p_HcFrame->hcSpecificData.singleRegForWrite = tmpReg32; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT); ++ ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ tmpReg32 = p_HcFrame->hcSpecificData.profileRegs.fmpl_peynia; ++ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); ++ } ++ ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId); ++ p_HcFrame->actionReg |= FmPcdPlcrBuildNiaProfileReg(FALSE, TRUE, FALSE); ++ p_HcFrame->extraReg = 0x00008000; ++ p_HcFrame->hcSpecificData.singleRegForWrite = tmpReg32; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT); ++ ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ tmpReg32 = p_HcFrame->hcSpecificData.profileRegs.fmpl_pernia; ++ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); ++ } ++ ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId); ++ p_HcFrame->actionReg |= FmPcdPlcrBuildNiaProfileReg(FALSE, FALSE, TRUE); ++ p_HcFrame->extraReg = 0x00008000; ++ p_HcFrame->hcSpecificData.singleRegForWrite = tmpReg32; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT); ++ ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ } ++ } ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdPlcrSetProfile(t_Handle h_FmHc, t_Handle h_Profile, t_FmPcdPlcrProfileRegs *p_PlcrRegs) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_Error err = E_OK; ++ uint16_t profileIndx; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint32_t seqNum; ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ profileIndx = FmPcdPlcrProfileGetAbsoluteId(h_Profile); ++ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionRegs(profileIndx); ++ p_HcFrame->extraReg = 0x00008000; ++ memcpy(&p_HcFrame->hcSpecificData.profileRegs, p_PlcrRegs, sizeof(t_FmPcdPlcrProfileRegs)); ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdPlcrDeleteProfile(t_Handle h_FmHc, t_Handle h_Profile) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile); ++ t_Error err = E_OK; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint32_t seqNum; ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId); ++ p_HcFrame->actionReg |= 0x00008000; ++ p_HcFrame->extraReg = 0x00008000; ++ memset(&p_HcFrame->hcSpecificData.profileRegs, 0, sizeof(t_FmPcdPlcrProfileRegs)); ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdPlcrSetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value) ++{ ++ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile); ++ t_Error err = E_OK; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint32_t seqNum; ++ ++ /* first read scheme and check that it is valid */ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId); ++ p_HcFrame->actionReg |= FmPcdPlcrBuildCounterProfileReg(counter); ++ p_HcFrame->extraReg = 0x00008000; ++ p_HcFrame->hcSpecificData.singleRegForWrite = value; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++uint32_t FmHcPcdPlcrGetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile); ++ t_Error err; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint32_t retVal = 0; ++ uint32_t seqNum; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0); ++ ++ /* first read scheme and check that it is valid */ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ { ++ REPORT_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ return 0; ++ } ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildReadPlcrActionReg(absoluteProfileId); ++ p_HcFrame->extraReg = 0x00008000; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ if (err != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return 0; ++ } ++ ++ switch (counter) ++ { ++ case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER: ++ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_pegpc; ++ break; ++ case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER: ++ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_peypc; ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER: ++ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_perpc; ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER: ++ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_perypc; ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER: ++ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_perrpc; ++ break; ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ return retVal; ++} ++ ++t_Error FmHcKgWriteSp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t spReg, bool add) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err = E_OK; ++ uint32_t seqNum; ++ ++ ASSERT_COND(p_FmHc); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ /* first read SP register */ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildReadPortSchemeBindActionReg(hardwarePortId); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_PORT_REGS); ++ ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ /* spReg is the first reg, so we can use it both for read and for write */ ++ if (add) ++ p_HcFrame->hcSpecificData.portRegsForRead.spReg |= spReg; ++ else ++ p_HcFrame->hcSpecificData.portRegsForRead.spReg &= ~spReg; ++ ++ p_HcFrame->actionReg = FmPcdKgBuildWritePortSchemeBindActionReg(hardwarePortId); ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcKgWriteCpp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t cppReg) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err = E_OK; ++ uint32_t seqNum; ++ ++ ASSERT_COND(p_FmHc); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ /* first read SP register */ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildWritePortClsPlanBindActionReg(hardwarePortId); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ p_HcFrame->hcSpecificData.singleRegForWrite = cppReg; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdCcDoDynamicChange(t_Handle h_FmHc, uint32_t oldAdAddrOffset, uint32_t newAdAddrOffset) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err = E_OK; ++ uint32_t seqNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmHc, E_INVALID_HANDLE); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC); ++ p_HcFrame->actionReg = newAdAddrOffset; ++ p_HcFrame->actionReg |= 0xc0000000; ++ p_HcFrame->extraReg = oldAdAddrOffset; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/Makefile b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/Makefile +new file mode 100644 +index 0000000..629949c +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/Makefile +@@ -0,0 +1,20 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++NCSW_FM_INC = $(srctree)/drivers/net/dpa/NetCommSw/Peripherals/FM/inc ++ ++EXTRA_CFLAGS += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-MAC.o ++ ++fsl-ncsw-MAC-objs := dtsec.o dtsec_mii_acc.o fm_mac.o tgec.o tgec_mii_acc.o \ ++ fman_dtsec.o fman_dtsec_mii_acc.o fman_memac.o \ ++ fman_tgec.o fman_crc32.o ++ ++ifeq ($(CONFIG_FMAN_T4240),y) ++fsl-ncsw-MAC-objs += memac.o memac_mii_acc.o ++endif +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/dtsec.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/dtsec.c +new file mode 100644 +index 0000000..e4cb509 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/dtsec.c +@@ -0,0 +1,1513 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 dtsec.c ++ ++ @Description FM dTSEC ... ++*//***************************************************************************/ ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "xx_ext.h" ++#include "endian_ext.h" ++#include "debug_ext.h" ++#include "crc_mac_addr_ext.h" ++ ++#include "fm_common.h" ++#include "dtsec.h" ++#include "fsl_fman_dtsec.h" ++ ++ ++/*****************************************************************************/ ++/* Internal routines */ ++/*****************************************************************************/ ++ ++static t_Error CheckInitParameters(t_Dtsec *p_Dtsec) ++{ ++ if (ENET_SPEED_FROM_MODE(p_Dtsec->enetMode) >= e_ENET_SPEED_10000) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 1G MAC driver only supports 1G or lower speeds")); ++ if (p_Dtsec->macId >= FM_MAX_NUM_OF_1G_MACS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("macId can not be greater than the number of 1G MACs")); ++ if (p_Dtsec->addr == 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC Must have a valid MAC Address")); ++ if ((ENET_SPEED_FROM_MODE(p_Dtsec->enetMode) >= e_ENET_SPEED_1000) && ++ p_Dtsec->p_DtsecDriverParam->halfdup_on) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC 1G can't work in half duplex")); ++ if (p_Dtsec->p_DtsecDriverParam->halfdup_on && (p_Dtsec->p_DtsecDriverParam)->loopback) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("LoopBack is not supported in halfDuplex mode")); ++#ifdef FM_RX_PREAM_4_ERRATA_DTSEC_A001 ++ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev <= 6) /* fixed for rev3 */ ++ if (p_Dtsec->p_DtsecDriverParam->rx_preamble) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("preambleRxEn")); ++#endif /* FM_RX_PREAM_4_ERRATA_DTSEC_A001 */ ++ if (((p_Dtsec->p_DtsecDriverParam)->tx_preamble || (p_Dtsec->p_DtsecDriverParam)->rx_preamble) &&( (p_Dtsec->p_DtsecDriverParam)->preamble_len != 0x7)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Preamble length should be 0x7 bytes")); ++ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_on && ++ (p_Dtsec->p_DtsecDriverParam->tx_time_stamp_en || p_Dtsec->p_DtsecDriverParam->rx_time_stamp_en)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dTSEC in half duplex mode has to be with 1588 timeStamping diable")); ++ if ((p_Dtsec->p_DtsecDriverParam)->rx_flow && (p_Dtsec->p_DtsecDriverParam)->rx_ctrl_acc ) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Receive control frame are not passed to the system memory so it can not be accept ")); ++ if ((p_Dtsec->p_DtsecDriverParam)->rx_prepend > MAX_PACKET_ALIGNMENT) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("packetAlignmentPadding can't be greater than %d ",MAX_PACKET_ALIGNMENT )); ++ if (((p_Dtsec->p_DtsecDriverParam)->non_back_to_back_ipg1 > MAX_INTER_PACKET_GAP) || ++ ((p_Dtsec->p_DtsecDriverParam)->non_back_to_back_ipg2 > MAX_INTER_PACKET_GAP) || ++ ((p_Dtsec->p_DtsecDriverParam)->back_to_back_ipg > MAX_INTER_PACKET_GAP)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inter packet gap can't be greater than %d ",MAX_INTER_PACKET_GAP )); ++ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_alt_backoff_val > MAX_INTER_PALTERNATE_BEB) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("alternateBackoffVal can't be greater than %d ",MAX_INTER_PALTERNATE_BEB )); ++ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_retransmit > MAX_RETRANSMISSION) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("maxRetransmission can't be greater than %d ",MAX_RETRANSMISSION )); ++ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_coll_window > MAX_COLLISION_WINDOW) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("collisionWindow can't be greater than %d ",MAX_COLLISION_WINDOW )); ++ ++ /* If Auto negotiation process is disabled, need to */ ++ /* Set up the PHY using the MII Management Interface */ ++ if (p_Dtsec->p_DtsecDriverParam->tbipa > MAX_PHYS) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("PHY address (should be 0-%d)", MAX_PHYS)); ++ if (!p_Dtsec->f_Exception) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("uninitialized f_Exception")); ++ if (!p_Dtsec->f_Event) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("uninitialized f_Event")); ++ ++#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002 ++ if (p_Dtsec->p_DtsecDriverParam->rx_len_check) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!")); ++#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */ ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static uint32_t GetMacAddrHashCode(uint64_t ethAddr) ++{ ++ uint32_t crc; ++ ++ /* CRC calculation */ ++ GET_MAC_ADDR_CRC(ethAddr, crc); ++ ++ crc = GetMirror32(crc); ++ ++ return crc; ++} ++ ++/* ......................................................................... */ ++ ++static void UpdateStatistics(t_Dtsec *p_Dtsec) ++{ ++ uint32_t car1, car2; ++ ++ dtsec_get_clear_carry_regs(p_Dtsec->p_MemMap, &car1, &car2); ++ ++ if (car1) ++ { ++ if (car1 & CAR1_TR64) ++ p_Dtsec->internalStatistics.tr64 += VAL22BIT; ++ if (car1 & CAR1_TR127) ++ p_Dtsec->internalStatistics.tr127 += VAL22BIT; ++ if (car1 & CAR1_TR255) ++ p_Dtsec->internalStatistics.tr255 += VAL22BIT; ++ if (car1 & CAR1_TR511) ++ p_Dtsec->internalStatistics.tr511 += VAL22BIT; ++ if (car1 & CAR1_TRK1) ++ p_Dtsec->internalStatistics.tr1k += VAL22BIT; ++ if (car1 & CAR1_TRMAX) ++ p_Dtsec->internalStatistics.trmax += VAL22BIT; ++ if (car1 & CAR1_TRMGV) ++ p_Dtsec->internalStatistics.trmgv += VAL22BIT; ++ if (car1 & CAR1_RBYT) ++ p_Dtsec->internalStatistics.rbyt += (uint64_t)VAL32BIT; ++ if (car1 & CAR1_RPKT) ++ p_Dtsec->internalStatistics.rpkt += VAL22BIT; ++ if (car1 & CAR1_RMCA) ++ p_Dtsec->internalStatistics.rmca += VAL22BIT; ++ if (car1 & CAR1_RBCA) ++ p_Dtsec->internalStatistics.rbca += VAL22BIT; ++ if (car1 & CAR1_RXPF) ++ p_Dtsec->internalStatistics.rxpf += VAL16BIT; ++ if (car1 & CAR1_RALN) ++ p_Dtsec->internalStatistics.raln += VAL16BIT; ++ if (car1 & CAR1_RFLR) ++ p_Dtsec->internalStatistics.rflr += VAL16BIT; ++ if (car1 & CAR1_RCDE) ++ p_Dtsec->internalStatistics.rcde += VAL16BIT; ++ if (car1 & CAR1_RCSE) ++ p_Dtsec->internalStatistics.rcse += VAL16BIT; ++ if (car1 & CAR1_RUND) ++ p_Dtsec->internalStatistics.rund += VAL16BIT; ++ if (car1 & CAR1_ROVR) ++ p_Dtsec->internalStatistics.rovr += VAL16BIT; ++ if (car1 & CAR1_RFRG) ++ p_Dtsec->internalStatistics.rfrg += VAL16BIT; ++ if (car1 & CAR1_RJBR) ++ p_Dtsec->internalStatistics.rjbr += VAL16BIT; ++ if (car1 & CAR1_RDRP) ++ p_Dtsec->internalStatistics.rdrp += VAL16BIT; ++ } ++ if (car2) ++ { ++ if (car2 & CAR2_TFCS) ++ p_Dtsec->internalStatistics.tfcs += VAL12BIT; ++ if (car2 & CAR2_TBYT) ++ p_Dtsec->internalStatistics.tbyt += (uint64_t)VAL32BIT; ++ if (car2 & CAR2_TPKT) ++ p_Dtsec->internalStatistics.tpkt += VAL22BIT; ++ if (car2 & CAR2_TMCA) ++ p_Dtsec->internalStatistics.tmca += VAL22BIT; ++ if (car2 & CAR2_TBCA) ++ p_Dtsec->internalStatistics.tbca += VAL22BIT; ++ if (car2 & CAR2_TXPF) ++ p_Dtsec->internalStatistics.txpf += VAL16BIT; ++ if (car2 & CAR2_TDRP) ++ p_Dtsec->internalStatistics.tdrp += VAL16BIT; ++ } ++} ++ ++/* .............................................................................. */ ++ ++static uint16_t DtsecGetMaxFrameLength(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Dtsec, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE, 0); ++ ++ return dtsec_get_max_frame_len(p_Dtsec->p_MemMap); ++} ++ ++/* .............................................................................. */ ++ ++static void DtsecIsr(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ uint32_t event; ++ struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap; ++ ++ /* do not handle MDIO events */ ++ event = dtsec_get_event(p_DtsecMemMap, (uint32_t)(~(DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN))); ++ ++ event &= dtsec_get_interrupt_mask(p_DtsecMemMap); ++ ++ dtsec_ack_event(p_DtsecMemMap, event); ++ ++ if (event & DTSEC_IMASK_BREN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_BAB_RX); ++ if (event & DTSEC_IMASK_RXCEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_RX_CTL); ++ if (event & DTSEC_IMASK_MSROEN) ++ UpdateStatistics(p_Dtsec); ++ if (event & DTSEC_IMASK_GTSCEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET); ++ if (event & DTSEC_IMASK_BTEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_BAB_TX); ++ if (event & DTSEC_IMASK_TXCEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_CTL); ++ if (event & DTSEC_IMASK_TXEEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_ERR); ++ if (event & DTSEC_IMASK_LCEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_LATE_COL); ++ if (event & DTSEC_IMASK_CRLEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_COL_RET_LMT); ++ if (event & DTSEC_IMASK_XFUNEN) ++ { ++#ifdef FM_TX_LOCKUP_ERRATA_DTSEC6 ++ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2) ++ { ++ uint32_t tpkt1, tmpReg1, tpkt2, tmpReg2, i; ++ /* a. Write 0x00E0_0C00 to DTSEC_ID */ ++ /* This is a read only regidter */ ++ ++ /* b. Read and save the value of TPKT */ ++ tpkt1 = GET_UINT32(p_DtsecMemMap->tpkt); ++ ++ /* c. Read the register at dTSEC address offset 0x32C */ ++ tmpReg1 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c)); ++ ++ /* d. Compare bits [9:15] to bits [25:31] of the register at address offset 0x32C. */ ++ if ((tmpReg1 & 0x007F0000) != (tmpReg1 & 0x0000007F)) ++ { ++ /* If they are not equal, save the value of this register and wait for at least ++ * MAXFRM*16 ns */ ++ XX_UDelay((uint32_t)(MIN(DtsecGetMaxFrameLength(p_Dtsec)*16/1000, 1))); ++ } ++ ++ /* e. Read and save TPKT again and read the register at dTSEC address offset ++ 0x32C again*/ ++ tpkt2 = GET_UINT32(p_DtsecMemMap->tpkt); ++ tmpReg2 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c)); ++ ++ /* f. Compare the value of TPKT saved in step b to value read in step e. Also ++ compare bits [9:15] of the register at offset 0x32C saved in step d to the value ++ of bits [9:15] saved in step e. If the two registers values are unchanged, then ++ the transmit portion of the dTSEC controller is locked up and the user should ++ proceed to the recover sequence. */ ++ if ((tpkt1 == tpkt2) && ((tmpReg1 & 0x007F0000) == (tmpReg2 & 0x007F0000))) ++ { ++ /* recover sequence */ ++ ++ /* a.Write a 1 to RCTRL[GRS]*/ ++ ++ WRITE_UINT32(p_DtsecMemMap->rctrl, GET_UINT32(p_DtsecMemMap->rctrl) | RCTRL_GRS); ++ ++ /* b.Wait until IEVENT[GRSC]=1, or at least 100 us has elapsed. */ ++ for (i = 0 ; i < 100 ; i++ ) ++ { ++ if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN) ++ break; ++ XX_UDelay(1); ++ } ++ if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN) ++ WRITE_UINT32(p_DtsecMemMap->ievent, DTSEC_IMASK_GRSCEN); ++ else ++ DBG(INFO,("Rx lockup due to dTSEC Tx lockup")); ++ ++ /* c.Write a 1 to bit n of FM_RSTC (offset 0x0CC of FPM)*/ ++ FmResetMac(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MAC_1G, p_Dtsec->fmMacControllerDriver.macId); ++ ++ /* d.Wait 4 Tx clocks (32 ns) */ ++ XX_UDelay(1); ++ ++ /* e.Write a 0 to bit n of FM_RSTC. */ ++ /* cleared by FMAN */ ++ } ++ } ++#endif /* FM_TX_LOCKUP_ERRATA_DTSEC6 */ ++ ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_FIFO_UNDRN); ++ } ++ if (event & DTSEC_IMASK_MAGEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_MAG_PCKT); ++ if (event & DTSEC_IMASK_GRSCEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET); ++ if (event & DTSEC_IMASK_TDPEEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_DATA_ERR); ++ if (event & DTSEC_IMASK_RDPEEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_RX_DATA_ERR); ++ ++ /* - masked interrupts */ ++ ASSERT_COND(!(event & DTSEC_IMASK_ABRTEN)); ++ ASSERT_COND(!(event & DTSEC_IMASK_IFERREN)); ++} ++ ++static void DtsecMdioIsr(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ uint32_t event; ++ struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap; ++ ++ event = GET_UINT32(p_DtsecMemMap->ievent); ++ /* handle only MDIO events */ ++ event &= (DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN); ++ if (event) ++ { ++ event &= GET_UINT32(p_DtsecMemMap->imask); ++ ++ WRITE_UINT32(p_DtsecMemMap->ievent, event); ++ ++ if (event & DTSEC_IMASK_MMRDEN) ++ p_Dtsec->f_Event(p_Dtsec->h_App, e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET); ++ if (event & DTSEC_IMASK_MMWREN) ++ p_Dtsec->f_Event(p_Dtsec->h_App, e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET); ++ } ++} ++ ++static void Dtsec1588Isr(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ uint32_t event; ++ struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap; ++ ++ if (p_Dtsec->ptpTsuEnabled) ++ { ++ event = dtsec_check_and_clear_tmr_event(p_DtsecMemMap); ++ ++ if (event) ++ { ++ ASSERT_COND(event & TMR_PEVENT_TSRE); ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_1588_TS_RX_ERR); ++ } ++ } ++} ++ ++/* ........................................................................... */ ++ ++static void FreeInitResources(t_Dtsec *p_Dtsec) ++{ ++ /*TODO - need to ask why with mdioIrq != 0*/ ++ if ((p_Dtsec->mdioIrq != 0) && (p_Dtsec->mdioIrq != NO_IRQ)) ++ { ++ XX_DisableIntr(p_Dtsec->mdioIrq); ++ XX_FreeIntr(p_Dtsec->mdioIrq); ++ } ++ FmUnregisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Dtsec->macId, e_FM_INTR_TYPE_ERR); ++ FmUnregisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Dtsec->macId, e_FM_INTR_TYPE_NORMAL); ++ ++ /* release the driver's group hash table */ ++ FreeHashTable(p_Dtsec->p_MulticastAddrHash); ++ p_Dtsec->p_MulticastAddrHash = NULL; ++ ++ /* release the driver's individual hash table */ ++ FreeHashTable(p_Dtsec->p_UnicastAddrHash); ++ p_Dtsec->p_UnicastAddrHash = NULL; ++} ++ ++/* ........................................................................... */ ++ ++static t_Error GracefulStop(t_Dtsec *p_Dtsec, e_CommMode mode) ++{ ++ struct dtsec_regs *p_MemMap; ++ ++ ASSERT_COND(p_Dtsec); ++ ++ p_MemMap = p_Dtsec->p_MemMap; ++ ASSERT_COND(p_MemMap); ++ ++ /* Assert the graceful transmit stop bit */ ++ if (mode & e_COMM_MODE_RX) ++ { ++ dtsec_stop_rx(p_MemMap); ++ ++#ifdef FM_GRS_ERRATA_DTSEC_A002 ++ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2) ++ XX_UDelay(100); ++#else /* FM_GRS_ERRATA_DTSEC_A002 */ ++#ifdef FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 ++ XX_UDelay(10); ++#endif /* FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 */ ++#endif /* FM_GRS_ERRATA_DTSEC_A002 */ ++ } ++ ++ if (mode & e_COMM_MODE_TX) ++#if defined(FM_GTS_ERRATA_DTSEC_A004) || defined(FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012) ++ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2) ++ DBG(INFO, ("GTS not supported due to DTSEC_A004 errata.")); ++#else /* not defined(FM_GTS_ERRATA_DTSEC_A004) ||... */ ++#ifdef FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 ++ DBG(INFO, ("GTS not supported due to DTSEC_A0014 errata.")); ++#else /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */ ++ dtsec_stop_tx(p_MemMap); ++#endif /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */ ++#endif /* defined(FM_GTS_ERRATA_DTSEC_A004) ||... */ ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error GracefulRestart(t_Dtsec *p_Dtsec, e_CommMode mode) ++{ ++ struct dtsec_regs *p_MemMap; ++ ++ ASSERT_COND(p_Dtsec); ++ p_MemMap = p_Dtsec->p_MemMap; ++ ASSERT_COND(p_MemMap); ++ ++ /* clear the graceful receive stop bit */ ++ if (mode & e_COMM_MODE_TX) ++ dtsec_start_tx(p_MemMap); ++ ++ if (mode & e_COMM_MODE_RX) ++ dtsec_start_rx(p_MemMap); ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* dTSEC Configs modification functions */ ++/*****************************************************************************/ ++ ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigLoopback(t_Handle h_Dtsec, bool newVal) ++{ ++ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->p_DtsecDriverParam->loopback = newVal; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigMaxFrameLength(t_Handle h_Dtsec, uint16_t newVal) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->p_DtsecDriverParam->maximum_frame = newVal; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigPadAndCrc(t_Handle h_Dtsec, bool newVal) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->p_DtsecDriverParam->tx_pad_crc = newVal; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigHalfDuplex(t_Handle h_Dtsec, bool newVal) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->p_DtsecDriverParam->halfdup_on = newVal; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigTbiPhyAddr(t_Handle h_Dtsec, uint8_t newVal) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->p_DtsecDriverParam->tbi_phy_addr = newVal; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigLengthCheck(t_Handle h_Dtsec, bool newVal) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->p_DtsecDriverParam->rx_len_check = newVal; ++ ++ return E_OK; ++} ++ ++static t_Error DtsecConfigException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR) ++ { ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Dtsec->exceptions |= bitMask; ++ else ++ p_Dtsec->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ } ++ else ++ { ++ if (!p_Dtsec->ptpTsuEnabled) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only")); ++ switch (exception){ ++ case (e_FM_MAC_EX_1G_1588_TS_RX_ERR): ++ if (enable) ++ p_Dtsec->enTsuErrExeption = TRUE; ++ else ++ p_Dtsec->enTsuErrExeption = FALSE; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ } ++ } ++ return E_OK; ++} ++/*****************************************************************************/ ++/* dTSEC Run Time API functions */ ++/*****************************************************************************/ ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecEnable(t_Handle h_Dtsec, e_CommMode mode) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ dtsec_enable(p_Dtsec->p_MemMap, ++ (bool)!!(mode & e_COMM_MODE_RX), ++ (bool)!!(mode & e_COMM_MODE_TX)); ++ ++ GracefulRestart(p_Dtsec, mode); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecDisable (t_Handle h_Dtsec, e_CommMode mode) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ GracefulStop(p_Dtsec, mode); ++ ++ dtsec_disable(p_Dtsec->p_MemMap, ++ (bool)!!(mode & e_COMM_MODE_RX), ++ (bool)!!(mode & e_COMM_MODE_TX)); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecSetTxPauseFrames(t_Handle h_Dtsec, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ UNUSED(priority);UNUSED(threshTime); ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++#ifdef FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 ++ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2) ++ if (pauseTime <= 320) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ++ ("This pause-time value of %d is illegal due to errata dTSEC-A003!" ++ " value should be greater than 320.")); ++#endif /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 */ ++ ++ dtsec_set_tx_pause_time(p_Dtsec->p_MemMap, pauseTime); ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++/* backward compatibility. will be removed in the future. */ ++static t_Error DtsecTxMacPause(t_Handle h_Dtsec, uint16_t pauseTime) ++{ ++ return DtsecSetTxPauseFrames(h_Dtsec, 0, pauseTime, 0); ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecRxIgnoreMacPause(t_Handle h_Dtsec, bool en) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ bool accept_pause = !en; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ dtsec_handle_rx_pause(p_Dtsec->p_MemMap, accept_pause); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecEnable1588TimeStamp(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->ptpTsuEnabled = TRUE; ++ dtsec_set_ts(p_Dtsec->p_MemMap, TRUE); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecDisable1588TimeStamp(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->ptpTsuEnabled = FALSE; ++ dtsec_set_ts(p_Dtsec->p_MemMap, FALSE); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecGetStatistics(t_Handle h_Dtsec, t_FmMacStatistics *p_Statistics) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ struct dtsec_regs *p_DtsecMemMap; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER); ++ ++ p_DtsecMemMap = p_Dtsec->p_MemMap; ++ ++ if (p_Dtsec->statisticsLevel == e_FM_MAC_NONE_STATISTICS) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Statistics disabled")); ++ ++ memset(p_Statistics, 0xff, sizeof(t_FmMacStatistics)); ++ ++ if (p_Dtsec->statisticsLevel == e_FM_MAC_FULL_STATISTICS) ++ { ++ p_Statistics->eStatPkts64 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR64) ++ + p_Dtsec->internalStatistics.tr64; ++ p_Statistics->eStatPkts65to127 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR127) ++ + p_Dtsec->internalStatistics.tr127; ++ p_Statistics->eStatPkts128to255 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR255) ++ + p_Dtsec->internalStatistics.tr255; ++ p_Statistics->eStatPkts256to511 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR511) ++ + p_Dtsec->internalStatistics.tr511; ++ p_Statistics->eStatPkts512to1023 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR1K) ++ + p_Dtsec->internalStatistics.tr1k; ++ p_Statistics->eStatPkts1024to1518 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TRMAX) ++ + p_Dtsec->internalStatistics.trmax; ++ p_Statistics->eStatPkts1519to1522 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TRMGV) ++ + p_Dtsec->internalStatistics.trmgv; ++ ++ /* MIB II */ ++ p_Statistics->ifInOctets = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RBYT) ++ + p_Dtsec->internalStatistics.rbyt; ++ p_Statistics->ifInPkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RPKT) ++ + p_Dtsec->internalStatistics.rpkt; ++ p_Statistics->ifInUcastPkts = 0; ++ p_Statistics->ifInMcastPkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RMCA) ++ + p_Dtsec->internalStatistics.rmca; ++ p_Statistics->ifInBcastPkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RBCA) ++ + p_Dtsec->internalStatistics.rbca; ++ p_Statistics->ifOutOctets = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TBYT) ++ + p_Dtsec->internalStatistics.tbyt; ++ p_Statistics->ifOutPkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TPKT) ++ + p_Dtsec->internalStatistics.tpkt; ++ p_Statistics->ifOutUcastPkts = 0; ++ p_Statistics->ifOutMcastPkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TMCA) ++ + p_Dtsec->internalStatistics.tmca; ++ p_Statistics->ifOutBcastPkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TBCA) ++ + p_Dtsec->internalStatistics.tbca; ++ } ++ ++ p_Statistics->eStatFragments = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RFRG) ++ + p_Dtsec->internalStatistics.rfrg; ++ p_Statistics->eStatJabbers = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RJBR) ++ + p_Dtsec->internalStatistics.rjbr; ++ p_Statistics->eStatsDropEvents = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RDRP) ++ + p_Dtsec->internalStatistics.rdrp; ++ p_Statistics->eStatCRCAlignErrors = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RALN) ++ + p_Dtsec->internalStatistics.raln; ++ p_Statistics->eStatUndersizePkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RUND) ++ + p_Dtsec->internalStatistics.rund; ++ p_Statistics->eStatOversizePkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_ROVR) ++ + p_Dtsec->internalStatistics.rovr; ++ p_Statistics->reStatPause = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RXPF) ++ + p_Dtsec->internalStatistics.rxpf; ++ p_Statistics->teStatPause = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TXPF) ++ + p_Dtsec->internalStatistics.txpf; ++ p_Statistics->ifInDiscards = p_Statistics->eStatsDropEvents; ++ p_Statistics->ifInErrors = p_Statistics->eStatsDropEvents + p_Statistics->eStatCRCAlignErrors ++ + dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RFLR) + p_Dtsec->internalStatistics.rflr ++ + dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RCDE) + p_Dtsec->internalStatistics.rcde ++ + dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RCSE) + p_Dtsec->internalStatistics.rcse; ++ ++ p_Statistics->ifOutDiscards = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TDRP) ++ + p_Dtsec->internalStatistics.tdrp; ++ p_Statistics->ifOutErrors = p_Statistics->ifOutDiscards /**< Number of frames transmitted with error: */ ++ + dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_TFCS) ++ + p_Dtsec->internalStatistics.tfcs; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecModifyMacAddress (t_Handle h_Dtsec, t_EnetAddr *p_EnetAddr) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ /* Initialize MAC Station Address registers (1 & 2) */ ++ /* Station address have to be swapped (big endian to little endian */ ++ p_Dtsec->addr = ENET_ADDR_TO_UINT64(*p_EnetAddr); ++ dtsec_set_mac_address(p_Dtsec->p_MemMap, (uint8_t *)(*p_EnetAddr)); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecResetCounters (t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ /* clear HW counters */ ++ dtsec_reset_stat(p_Dtsec->p_MemMap); ++ ++ /* clear SW counters holding carries */ ++ memset(&p_Dtsec->internalStatistics, 0, sizeof(t_InternalStatistics)); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecAddExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *) h_Dtsec; ++ uint64_t ethAddr; ++ uint8_t paddrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ if (ethAddr & GROUP_ADDRESS) ++ /* Multicast address has no effect in PADDR */ ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address")); ++ ++ /* Make sure no PADDR contains this address */ ++ for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++) ++ if (p_Dtsec->indAddrRegUsed[paddrNum]) ++ if (p_Dtsec->paddr[paddrNum] == ethAddr) ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG); ++ ++ /* Find first unused PADDR */ ++ for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++) ++ if (!(p_Dtsec->indAddrRegUsed[paddrNum])) ++ { ++ /* mark this PADDR as used */ ++ p_Dtsec->indAddrRegUsed[paddrNum] = TRUE; ++ /* store address */ ++ p_Dtsec->paddr[paddrNum] = ethAddr; ++ ++ /* put in hardware */ ++ dtsec_add_addr_in_paddr(p_Dtsec->p_MemMap, (uint64_t)PTR_TO_UINT(ðAddr), paddrNum); ++ p_Dtsec->numOfIndAddrInRegs++; ++ ++ return E_OK; ++ } ++ ++ /* No free PADDR */ ++ RETURN_ERROR(MAJOR, E_FULL, NO_MSG); ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecDelExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *) h_Dtsec; ++ uint64_t ethAddr; ++ uint8_t paddrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ /* Find used PADDR containing this address */ ++ for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++) ++ { ++ if ((p_Dtsec->indAddrRegUsed[paddrNum]) && ++ (p_Dtsec->paddr[paddrNum] == ethAddr)) ++ { ++ /* mark this PADDR as not used */ ++ p_Dtsec->indAddrRegUsed[paddrNum] = FALSE; ++ /* clear in hardware */ ++ dtsec_clear_addr_in_paddr(p_Dtsec->p_MemMap, paddrNum); ++ p_Dtsec->numOfIndAddrInRegs--; ++ ++ return E_OK; ++ } ++ } ++ ++ RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG); ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecAddHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ t_EthHashEntry *p_HashEntry; ++ uint64_t ethAddr; ++ int32_t bucket; ++ uint32_t crc; ++ bool mcast, ghtx; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ ghtx = (bool)((dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE); ++ mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE); ++ ++ if (ghtx && !mcast) /* Cannot handle unicast mac addr when GHTX is on */ ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Could not compute hash bucket")); ++ ++ crc = GetMacAddrHashCode(ethAddr); ++ ++ /* considering the 9 highest order bits in crc H[8:0]: ++ * if ghtx = 0 H[8:6] (highest order 3 bits) identify the hash register ++ * and H[5:1] (next 5 bits) identify the hash bit ++ * if ghts = 1 H[8:5] (highest order 4 bits) identify the hash register ++ * and H[4:0] (next 5 bits) identify the hash bit. ++ * ++ * In bucket index output the low 5 bits identify the hash register bit, ++ * while the higher 4 bits identify the hash register ++ */ ++ ++ if (ghtx) ++ bucket = (int32_t)((crc >> 23) & 0x1ff); ++ else { ++ bucket = (int32_t)((crc >> 24) & 0xff); ++ /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */ ++ if (mcast) ++ bucket += 0x100; ++ } ++ ++ dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, TRUE); ++ ++ /* Create element to be added to the driver hash table */ ++ p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry)); ++ p_HashEntry->addr = ethAddr; ++ INIT_LIST(&p_HashEntry->node); ++ ++ if (ethAddr & MAC_GROUP_ADDRESS) ++ /* Group Address */ ++ LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket])); ++ else ++ LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket])); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecDelHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ t_List *p_Pos; ++ t_EthHashEntry *p_HashEntry = NULL; ++ uint64_t ethAddr; ++ int32_t bucket; ++ uint32_t crc; ++ bool mcast, ghtx; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ ghtx = (bool)((dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE); ++ mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE); ++ ++ if (ghtx && !mcast) /* Cannot handle unicast mac addr when GHTX is on */ ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Could not compute hash bucket")); ++ ++ crc = GetMacAddrHashCode(ethAddr); ++ ++ if (ghtx) ++ bucket = (int32_t)((crc >> 23) & 0x1ff); ++ else { ++ bucket = (int32_t)((crc >> 24) & 0xff); ++ /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */ ++ if (mcast) ++ bucket += 0x100; ++ } ++ ++ if (ethAddr & MAC_GROUP_ADDRESS) ++ { ++ /* Group Address */ ++ LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket])) ++ { ++ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos); ++ if (p_HashEntry->addr == ethAddr) ++ { ++ LIST_DelAndInit(&p_HashEntry->node); ++ XX_Free(p_HashEntry); ++ break; ++ } ++ } ++ if (LIST_IsEmpty(&p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket])) ++ dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE); ++ } ++ else ++ { ++ /* Individual Address */ ++ LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket])) ++ { ++ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos); ++ if (p_HashEntry->addr == ethAddr) ++ { ++ LIST_DelAndInit(&p_HashEntry->node); ++ XX_Free(p_HashEntry); ++ break; ++ } ++ } ++ if (LIST_IsEmpty(&p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket])) ++ dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE); ++ } ++ ++ /* address does not exist */ ++ ASSERT_COND(p_HashEntry != NULL); ++ ++ return E_OK; ++} ++ ++void DtsecRestartTbiAN(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ if (!p_Dtsec) ++ return; ++ ++ DTSEC_MII_WritePhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, ++ PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1); ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecSetPromiscuous(t_Handle h_Dtsec, bool newVal) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ dtsec_set_uc_promisc(p_Dtsec->p_MemMap, newVal); ++ dtsec_set_mc_promisc(p_Dtsec->p_MemMap, newVal); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecSetStatistics(t_Handle h_Dtsec, e_FmMacStatisticsLevel statisticsLevel) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->statisticsLevel = statisticsLevel; ++ ++ err = (t_Error)dtsec_set_stat_level(p_Dtsec->p_MemMap, ++ (enum mac_stat_level)statisticsLevel); ++ if (err != E_OK) ++ return err; ++ ++ switch (statisticsLevel) ++ { ++ case (e_FM_MAC_NONE_STATISTICS): ++ p_Dtsec->exceptions &= ~DTSEC_IMASK_MSROEN; ++ break; ++ case (e_FM_MAC_PARTIAL_STATISTICS): ++ p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN; ++ break; ++ case (e_FM_MAC_FULL_STATISTICS): ++ p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecAdjustLink(t_Handle h_Dtsec, e_EnetSpeed speed, bool fullDuplex) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ t_Error err; ++ enum enet_interface enet_interface; ++ enum enet_speed enet_speed; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode), speed); ++ enet_interface = (enum enet_interface) ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode); ++ enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Dtsec->enetMode); ++ p_Dtsec->halfDuplex = !fullDuplex; ++ ++ err = (t_Error)dtsec_adjust_link(p_Dtsec->p_MemMap, enet_interface, enet_speed, fullDuplex); ++ ++ if (err == E_CONFLICT) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ("Ethernet interface does not support Half Duplex mode")); ++ ++ return err; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecRestartAutoneg(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ uint16_t tmpReg16; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ DTSEC_MII_ReadPhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, &tmpReg16); ++ tmpReg16 |= (PHY_CR_RESET_AN); ++ DTSEC_MII_WritePhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, tmpReg16); ++ ++ return E_OK; ++} ++ ++/*************************************************************************************/ ++/* .............................................................................. */ ++ ++static t_Error DtsecGetId(t_Handle h_Dtsec, uint32_t *macId) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ *macId = p_Dtsec->macId; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecGetVersion(t_Handle h_Dtsec, uint32_t *macVersion) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ *macVersion = dtsec_get_revision(p_Dtsec->p_MemMap); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecSetException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR) ++ { ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Dtsec->exceptions |= bitMask; ++ else ++ p_Dtsec->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ if (enable) ++ dtsec_enable_interrupt(p_Dtsec->p_MemMap, bitMask); ++ else ++ dtsec_disable_interrupt(p_Dtsec->p_MemMap, bitMask); ++ } ++ else ++ { ++ if (!p_Dtsec->ptpTsuEnabled) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only")); ++ switch (exception) ++ { ++ case (e_FM_MAC_EX_1G_1588_TS_RX_ERR): ++ if (enable) ++ { ++ p_Dtsec->enTsuErrExeption = TRUE; ++ dtsec_enable_tmr_interrupt(p_Dtsec->p_MemMap); ++ } else { ++ p_Dtsec->enTsuErrExeption = FALSE; ++ dtsec_disable_tmr_interrupt(p_Dtsec->p_MemMap); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ } ++ } ++ ++ return E_OK; ++} ++ ++ ++ ++/* ........................................................................... */ ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++static t_Error DtsecDumpRegs(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ int i = 0; ++ ++ DECLARE_DUMP; ++ ++ if (p_Dtsec->p_MemMap) ++ { ++ ++ DUMP_TITLE(p_Dtsec->p_MemMap, ("dTSEC %d: ", p_Dtsec->macId)); ++ DUMP_VAR(p_Dtsec->p_MemMap, tsec_id); ++ DUMP_VAR(p_Dtsec->p_MemMap, tsec_id2); ++ DUMP_VAR(p_Dtsec->p_MemMap, ievent); ++ DUMP_VAR(p_Dtsec->p_MemMap, imask); ++ DUMP_VAR(p_Dtsec->p_MemMap, ecntrl); ++ DUMP_VAR(p_Dtsec->p_MemMap, ptv); ++ DUMP_VAR(p_Dtsec->p_MemMap, tmr_ctrl); ++ DUMP_VAR(p_Dtsec->p_MemMap, tmr_pevent); ++ DUMP_VAR(p_Dtsec->p_MemMap, tmr_pemask); ++ DUMP_VAR(p_Dtsec->p_MemMap, tctrl); ++ DUMP_VAR(p_Dtsec->p_MemMap, rctrl); ++ DUMP_VAR(p_Dtsec->p_MemMap, maccfg1); ++ DUMP_VAR(p_Dtsec->p_MemMap, maccfg2); ++ DUMP_VAR(p_Dtsec->p_MemMap, ipgifg); ++ DUMP_VAR(p_Dtsec->p_MemMap, hafdup); ++ DUMP_VAR(p_Dtsec->p_MemMap, maxfrm); ++ ++ DUMP_VAR(p_Dtsec->p_MemMap, macstnaddr1); ++ DUMP_VAR(p_Dtsec->p_MemMap, macstnaddr2); ++ ++ DUMP_SUBSTRUCT_ARRAY(i, 8) ++ { ++ DUMP_VAR(p_Dtsec->p_MemMap, macaddr[i].exact_match1); ++ DUMP_VAR(p_Dtsec->p_MemMap, macaddr[i].exact_match2); ++ } ++ DUMP_VAR(p_Dtsec->p_MemMap, car1); ++ DUMP_VAR(p_Dtsec->p_MemMap, car2); ++ } ++ ++ return E_OK; ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ ++/*****************************************************************************/ ++/* dTSEC Init & Free API */ ++/*****************************************************************************/ ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecInit(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ struct dtsec_cfg *p_DtsecDriverParam; ++ t_Error err; ++ uint16_t maxFrmLn; ++ enum enet_interface enet_interface; ++ enum enet_speed enet_speed; ++ t_EnetAddr ethAddr; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE); ++ ++ FM_GetRevision(p_Dtsec->fmMacControllerDriver.h_Fm, &p_Dtsec->fmMacControllerDriver.fmRevInfo); ++ CHECK_INIT_PARAMETERS(p_Dtsec, CheckInitParameters); ++ ++ p_DtsecDriverParam = p_Dtsec->p_DtsecDriverParam; ++ p_Dtsec->halfDuplex = p_DtsecDriverParam->halfdup_on; ++ ++ enet_interface = (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode); ++ enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_Dtsec->enetMode); ++ MAKE_ENET_ADDR_FROM_UINT64(p_Dtsec->addr, ethAddr); ++ ++ err = (t_Error)dtsec_init(p_Dtsec->p_MemMap, ++ p_DtsecDriverParam, ++ enet_interface, ++ enet_speed, ++ (uint8_t*)ethAddr, ++ p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev, ++ p_Dtsec->fmMacControllerDriver.fmRevInfo.minorRev, ++ p_Dtsec->exceptions); ++ if (err) ++ { ++ FreeInitResources(p_Dtsec); ++ RETURN_ERROR(MAJOR, err, ("This DTSEC version does not support the required i/f mode")); ++ } ++ ++ DTSEC_MII_Init(h_Dtsec); ++ ++ if (ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode) == e_ENET_IF_SGMII) ++ { ++ uint16_t tmpReg16; ++ ++ /* Configure the TBI PHY Control Register */ ++ tmpReg16 = PHY_TBICON_CLK_SEL | PHY_TBICON_SRESET; ++ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16); ++ ++ tmpReg16 = PHY_TBICON_CLK_SEL; ++ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16); ++ ++ tmpReg16 = (PHY_CR_PHY_RESET | PHY_CR_ANE | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1); ++ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16); ++ ++ if (p_Dtsec->enetMode & ENET_IF_SGMII_BASEX) ++ tmpReg16 = PHY_TBIANA_1000X; ++ else ++ tmpReg16 = PHY_TBIANA_SGMII; ++ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 4, tmpReg16); ++ ++ tmpReg16 = (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1); ++ ++ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16); ++ } ++ ++ /* Max Frame Length */ ++ maxFrmLn = dtsec_get_max_frame_len(p_Dtsec->p_MemMap); ++ err = FmSetMacMaxFrame(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MAC_1G, ++ p_Dtsec->fmMacControllerDriver.macId, maxFrmLn); ++ ++ p_Dtsec->p_MulticastAddrHash = AllocHashTable(EXTENDED_HASH_TABLE_SIZE); ++ if (!p_Dtsec->p_MulticastAddrHash) { ++ FreeInitResources(p_Dtsec); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MC hash table is FAILED")); ++ } ++ ++ p_Dtsec->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE); ++ if (!p_Dtsec->p_UnicastAddrHash) ++ { ++ FreeInitResources(p_Dtsec); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("UC hash table is FAILED")); ++ } ++ ++ /* register err intr handler for dtsec to FPM (err)*/ ++ FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, ++ e_FM_MOD_1G_MAC, ++ p_Dtsec->macId, ++ e_FM_INTR_TYPE_ERR, ++ DtsecIsr, ++ p_Dtsec); ++ /* register 1588 intr handler for TMR to FPM (normal)*/ ++ FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, ++ e_FM_MOD_1G_MAC, ++ p_Dtsec->macId, ++ e_FM_INTR_TYPE_NORMAL, ++ Dtsec1588Isr, ++ p_Dtsec); ++ /* register normal intr handler for dtsec to main interrupt controller. */ ++ if (p_Dtsec->mdioIrq != NO_IRQ) ++ { ++ XX_SetIntr(p_Dtsec->mdioIrq, DtsecMdioIsr, p_Dtsec); ++ XX_EnableIntr(p_Dtsec->mdioIrq); ++ } ++ ++ XX_Free(p_DtsecDriverParam); ++ p_Dtsec->p_DtsecDriverParam = NULL; ++ ++ err = DtsecSetStatistics(h_Dtsec, e_FM_MAC_FULL_STATISTICS); ++ if (err) ++ { ++ FreeInitResources(p_Dtsec); ++ RETURN_ERROR(MAJOR, err, ("Undefined statistics level")); ++ } ++ ++ return E_OK; ++} ++ ++/* ........................................................................... */ ++ ++static t_Error DtsecFree(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ ++ FreeInitResources(p_Dtsec); ++ ++ if (p_Dtsec->p_DtsecDriverParam) ++ { ++ XX_Free(p_Dtsec->p_DtsecDriverParam); ++ p_Dtsec->p_DtsecDriverParam = NULL; ++ } ++ XX_Free (h_Dtsec); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver) ++{ ++ p_FmMacControllerDriver->f_FM_MAC_Init = DtsecInit; ++ p_FmMacControllerDriver->f_FM_MAC_Free = DtsecFree; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetStatistics = DtsecSetStatistics; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = DtsecConfigLoopback; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = DtsecConfigMaxFrameLength; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigWan = NULL; /* Not supported on dTSEC */ ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = DtsecConfigPadAndCrc; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = DtsecConfigHalfDuplex; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = DtsecConfigLengthCheck; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr = DtsecConfigTbiPhyAddr; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigException = DtsecConfigException; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = NULL; ++ ++ p_FmMacControllerDriver->f_FM_MAC_Enable = DtsecEnable; ++ p_FmMacControllerDriver->f_FM_MAC_Disable = DtsecDisable; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetException = DtsecSetException; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = DtsecSetPromiscuous; ++ p_FmMacControllerDriver->f_FM_MAC_AdjustLink = DtsecAdjustLink; ++ p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = DtsecRestartAutoneg; ++ ++ p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = DtsecEnable1588TimeStamp; ++ p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = DtsecDisable1588TimeStamp; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = DtsecTxMacPause; ++ p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = DtsecSetTxPauseFrames; ++ p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = DtsecRxIgnoreMacPause; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ResetCounters = DtsecResetCounters; ++ p_FmMacControllerDriver->f_FM_MAC_GetStatistics = DtsecGetStatistics; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = DtsecModifyMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = DtsecAddHashMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = DtsecDelHashMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = DtsecAddExactMatchMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = DtsecDelExactMatchMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_GetId = DtsecGetId; ++ p_FmMacControllerDriver->f_FM_MAC_GetVersion = DtsecGetVersion; ++ p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = DtsecGetMaxFrameLength; ++ ++ p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = DTSEC_MII_WritePhyReg; ++ p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = DTSEC_MII_ReadPhyReg; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ p_FmMacControllerDriver->f_FM_MAC_DumpRegs = DtsecDumpRegs; ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++} ++ ++ ++/*****************************************************************************/ ++/* dTSEC Config Main Entry */ ++/*****************************************************************************/ ++ ++/* .............................................................................. */ ++ ++t_Handle DTSEC_Config(t_FmMacParams *p_FmMacParam) ++{ ++ t_Dtsec *p_Dtsec; ++ struct dtsec_cfg *p_DtsecDriverParam; ++ uintptr_t baseAddr; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL); ++ ++ baseAddr = p_FmMacParam->baseAddr; ++ ++ /* allocate memory for the UCC GETH data structure. */ ++ p_Dtsec = (t_Dtsec *)XX_Malloc(sizeof(t_Dtsec)); ++ if (!p_Dtsec) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver structure")); ++ return NULL; ++ } ++ memset(p_Dtsec, 0, sizeof(t_Dtsec)); ++ InitFmMacControllerDriver(&p_Dtsec->fmMacControllerDriver); ++ ++ /* allocate memory for the dTSEC driver parameters data structure. */ ++ p_DtsecDriverParam = (struct dtsec_cfg *) XX_Malloc(sizeof(struct dtsec_cfg)); ++ if (!p_DtsecDriverParam) ++ { ++ XX_Free(p_Dtsec); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver parameters")); ++ return NULL; ++ } ++ memset(p_DtsecDriverParam, 0, sizeof(struct dtsec_cfg)); ++ ++ /* Plant parameter structure pointer */ ++ p_Dtsec->p_DtsecDriverParam = p_DtsecDriverParam; ++ ++ dtsec_defconfig(p_DtsecDriverParam); ++ ++ p_Dtsec->p_MemMap = (struct dtsec_regs *)UINT_TO_PTR(baseAddr); ++ p_Dtsec->p_MiiMemMap = (struct dtsec_mii_reg *)UINT_TO_PTR(baseAddr + DTSEC_TO_MII_OFFSET); ++ p_Dtsec->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr); ++ p_Dtsec->enetMode = p_FmMacParam->enetMode; ++ p_Dtsec->macId = p_FmMacParam->macId; ++ p_Dtsec->exceptions = DEFAULT_exceptions; ++ p_Dtsec->mdioIrq = p_FmMacParam->mdioIrq; ++ p_Dtsec->f_Exception = p_FmMacParam->f_Exception; ++ p_Dtsec->f_Event = p_FmMacParam->f_Event; ++ p_Dtsec->h_App = p_FmMacParam->h_App; ++ p_Dtsec->ptpTsuEnabled = p_Dtsec->p_DtsecDriverParam->ptp_tsu_en; ++ p_Dtsec->enTsuErrExeption = p_Dtsec->p_DtsecDriverParam->ptp_exception_en; ++ p_Dtsec->tbi_phy_addr = p_Dtsec->p_DtsecDriverParam->tbi_phy_addr; ++ ++ return p_Dtsec; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/dtsec.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/dtsec.h +new file mode 100644 +index 0000000..01296dd +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/dtsec.h +@@ -0,0 +1,245 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 dtsec.h ++ ++ @Description FM dTSEC ... ++*//***************************************************************************/ ++#ifndef __DTSEC_H ++#define __DTSEC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++#include "enet_ext.h" ++ ++#include "dtsec_mii_acc.h" ++#include "fm_mac.h" ++ ++ ++#define DEFAULT_exceptions \ ++ ((uint32_t)(DTSEC_IMASK_BREN | \ ++ DTSEC_IMASK_RXCEN | \ ++ DTSEC_IMASK_BTEN | \ ++ DTSEC_IMASK_TXCEN | \ ++ DTSEC_IMASK_TXEEN | \ ++ DTSEC_IMASK_ABRTEN | \ ++ DTSEC_IMASK_LCEN | \ ++ DTSEC_IMASK_CRLEN | \ ++ DTSEC_IMASK_XFUNEN | \ ++ DTSEC_IMASK_IFERREN | \ ++ DTSEC_IMASK_MAGEN | \ ++ DTSEC_IMASK_TDPEEN | \ ++ DTSEC_IMASK_RDPEEN)) ++ ++#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \ ++ case e_FM_MAC_EX_1G_BAB_RX: \ ++ bitMask = DTSEC_IMASK_BREN; break; \ ++ case e_FM_MAC_EX_1G_RX_CTL: \ ++ bitMask = DTSEC_IMASK_RXCEN; break; \ ++ case e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET: \ ++ bitMask = DTSEC_IMASK_GTSCEN ; break; \ ++ case e_FM_MAC_EX_1G_BAB_TX: \ ++ bitMask = DTSEC_IMASK_BTEN ; break; \ ++ case e_FM_MAC_EX_1G_TX_CTL: \ ++ bitMask = DTSEC_IMASK_TXCEN ; break; \ ++ case e_FM_MAC_EX_1G_TX_ERR: \ ++ bitMask = DTSEC_IMASK_TXEEN ; break; \ ++ case e_FM_MAC_EX_1G_LATE_COL: \ ++ bitMask = DTSEC_IMASK_LCEN ; break; \ ++ case e_FM_MAC_EX_1G_COL_RET_LMT: \ ++ bitMask = DTSEC_IMASK_CRLEN ; break; \ ++ case e_FM_MAC_EX_1G_TX_FIFO_UNDRN: \ ++ bitMask = DTSEC_IMASK_XFUNEN ; break; \ ++ case e_FM_MAC_EX_1G_MAG_PCKT: \ ++ bitMask = DTSEC_IMASK_MAGEN ; break; \ ++ case e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET: \ ++ bitMask = DTSEC_IMASK_MMRDEN; break; \ ++ case e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET: \ ++ bitMask = DTSEC_IMASK_MMWREN ; break; \ ++ case e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET: \ ++ bitMask = DTSEC_IMASK_GRSCEN; break; \ ++ case e_FM_MAC_EX_1G_TX_DATA_ERR: \ ++ bitMask = DTSEC_IMASK_TDPEEN; break; \ ++ case e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL: \ ++ bitMask = DTSEC_IMASK_MSROEN ; break; \ ++ default: bitMask = 0;break;} ++ ++ ++#define MAX_PACKET_ALIGNMENT 31 ++#define MAX_INTER_PACKET_GAP 0x7f ++#define MAX_INTER_PALTERNATE_BEB 0x0f ++#define MAX_RETRANSMISSION 0x0f ++#define MAX_COLLISION_WINDOW 0x03ff ++ ++ ++/********************* From mac ext ******************************************/ ++typedef uint32_t t_ErrorDisable; ++ ++#define ERROR_DISABLE_TRANSMIT 0x00400000 ++#define ERROR_DISABLE_LATE_COLLISION 0x00040000 ++#define ERROR_DISABLE_COLLISION_RETRY_LIMIT 0x00020000 ++#define ERROR_DISABLE_TxFIFO_UNDERRUN 0x00010000 ++#define ERROR_DISABLE_TxABORT 0x00008000 ++#define ERROR_DISABLE_INTERFACE 0x00004000 ++#define ERROR_DISABLE_TxDATA_PARITY 0x00000002 ++#define ERROR_DISABLE_RxDATA_PARITY 0x00000001 ++ ++/*****************************************************************************/ ++#define DTSEC_NUM_OF_PADDRS 15 /* number of pattern match registers (entries) */ ++ ++#define GROUP_ADDRESS 0x0000010000000000LL /* Group address bit indication */ ++ ++#define HASH_TABLE_SIZE 256 /* Hash table size (= 32 bits * 8 regs) */ ++ ++#define HASH_TABLE_SIZE 256 /* Hash table size (32 bits * 8 regs) */ ++#define EXTENDED_HASH_TABLE_SIZE 512 /* Extended Hash table size (32 bits * 16 regs) */ ++ ++#define DTSEC_TO_MII_OFFSET 0x1000 /* number of pattern match registers (entries) */ ++ ++#define MAX_PHYS 32 /* maximum number of phys */ ++ ++#define VAL32BIT 0x100000000LL ++#define VAL22BIT 0x00400000 ++#define VAL16BIT 0x00010000 ++#define VAL12BIT 0x00001000 ++ ++/* PHY Control Register */ ++#define PHY_CR_PHY_RESET 0x8000 ++#define PHY_CR_LOOPBACK 0x4000 ++#define PHY_CR_SPEED0 0x2000 ++#define PHY_CR_ANE 0x1000 ++#define PHY_CR_RESET_AN 0x0200 ++#define PHY_CR_FULLDUPLEX 0x0100 ++#define PHY_CR_SPEED1 0x0040 ++ ++#define PHY_TBICON_SRESET 0x8000 ++#define PHY_TBICON_CLK_SEL 0x0020 ++ ++#define PHY_TBIANA_SGMII 0x4001 ++#define PHY_TBIANA_1000X 0x01a0 ++ ++ ++/* CAR1/2 bits */ ++#define CAR1_TR64 0x80000000 ++#define CAR1_TR127 0x40000000 ++#define CAR1_TR255 0x20000000 ++#define CAR1_TR511 0x10000000 ++#define CAR1_TRK1 0x08000000 ++#define CAR1_TRMAX 0x04000000 ++#define CAR1_TRMGV 0x02000000 ++ ++#define CAR1_RBYT 0x00010000 ++#define CAR1_RPKT 0x00008000 ++#define CAR1_RMCA 0x00002000 ++#define CAR1_RBCA 0x00001000 ++#define CAR1_RXPF 0x00000400 ++#define CAR1_RALN 0x00000100 ++#define CAR1_RFLR 0x00000080 ++#define CAR1_RCDE 0x00000040 ++#define CAR1_RCSE 0x00000020 ++#define CAR1_RUND 0x00000010 ++#define CAR1_ROVR 0x00000008 ++#define CAR1_RFRG 0x00000004 ++#define CAR1_RJBR 0x00000002 ++#define CAR1_RDRP 0x00000001 ++ ++#define CAR2_TFCS 0x00040000 ++#define CAR2_TBYT 0x00002000 ++#define CAR2_TPKT 0x00001000 ++#define CAR2_TMCA 0x00000800 ++#define CAR2_TBCA 0x00000400 ++#define CAR2_TXPF 0x00000200 ++#define CAR2_TDRP 0x00000001 ++ ++typedef struct t_InternalStatistics ++{ ++ uint64_t tr64; ++ uint64_t tr127; ++ uint64_t tr255; ++ uint64_t tr511; ++ uint64_t tr1k; ++ uint64_t trmax; ++ uint64_t trmgv; ++ uint64_t rfrg; ++ uint64_t rjbr; ++ uint64_t rdrp; ++ uint64_t raln; ++ uint64_t rund; ++ uint64_t rovr; ++ uint64_t rxpf; ++ uint64_t txpf; ++ uint64_t rbyt; ++ uint64_t rpkt; ++ uint64_t rmca; ++ uint64_t rbca; ++ uint64_t rflr; ++ uint64_t rcde; ++ uint64_t rcse; ++ uint64_t tbyt; ++ uint64_t tpkt; ++ uint64_t tmca; ++ uint64_t tbca; ++ uint64_t tdrp; ++ uint64_t tfcs; ++} t_InternalStatistics; ++ ++typedef struct { ++ t_FmMacControllerDriver fmMacControllerDriver; ++ t_Handle h_App; /**< Handle to the upper layer application */ ++ struct dtsec_regs *p_MemMap; /**< pointer to dTSEC memory mapped registers. */ ++ struct dtsec_mii_reg *p_MiiMemMap; /**< pointer to dTSEC MII memory mapped registers. */ ++ uint64_t addr; /**< MAC address of device; */ ++ e_EnetMode enetMode; /**< Ethernet physical interface */ ++ t_FmMacExceptionCallback *f_Exception; ++ int mdioIrq; ++ t_FmMacExceptionCallback *f_Event; ++ bool indAddrRegUsed[DTSEC_NUM_OF_PADDRS]; /**< Whether a particular individual address recognition register is being used */ ++ uint64_t paddr[DTSEC_NUM_OF_PADDRS]; /**< MAC address for particular individual address recognition register */ ++ uint8_t numOfIndAddrInRegs; /**< Number of individual addresses in registers for this station. */ ++ bool halfDuplex; ++ t_InternalStatistics internalStatistics; ++ t_EthHash *p_MulticastAddrHash; /* pointer to driver's global address hash table */ ++ t_EthHash *p_UnicastAddrHash; /* pointer to driver's individual address hash table */ ++ uint8_t macId; ++ uint8_t tbi_phy_addr; ++ uint32_t exceptions; ++ bool ptpTsuEnabled; ++ bool enTsuErrExeption; ++ e_FmMacStatisticsLevel statisticsLevel; ++ struct dtsec_cfg *p_DtsecDriverParam; ++} t_Dtsec; ++ ++ ++#endif /* __DTSEC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/dtsec_mii_acc.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/dtsec_mii_acc.c +new file mode 100644 +index 0000000..371e1f9 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/dtsec_mii_acc.c +@@ -0,0 +1,109 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 dtsec_mii_acc.c ++ ++ @Description FM dtsec MII register access MAC ... ++*//***************************************************************************/ ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "fm_mac.h" ++#include "dtsec.h" ++#include "fsl_fman_dtsec_mii_acc.h" ++ ++ ++/*****************************************************************************/ ++t_Error DTSEC_MII_WritePhyReg(t_Handle h_Dtsec, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t data) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ struct dtsec_mii_reg *miiregs; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ miiregs = p_Dtsec->p_MiiMemMap; ++ ++ err = (t_Error)dtsec_mii_write_reg(miiregs, phyAddr, reg, data); ++ ++ return err; ++} ++ ++/*****************************************************************************/ ++t_Error DTSEC_MII_ReadPhyReg(t_Handle h_Dtsec, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t *p_Data) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ struct dtsec_mii_reg *miiregs; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ miiregs = p_Dtsec->p_MiiMemMap; ++ ++ err = (t_Error)dtsec_mii_read_reg(miiregs, phyAddr, reg, p_Data); ++ ++ if (*p_Data == 0xffff) ++ RETURN_ERROR(MINOR, E_NO_DEVICE, ++ ("Read wrong data (0xffff): phyAddr 0x%x, reg 0x%x", ++ phyAddr, reg)); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return err; ++} ++ ++t_Error DTSEC_MII_Init(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ struct dtsec_mii_reg *miiregs; ++ uint16_t dtsec_freq; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ miiregs = p_Dtsec->p_MiiMemMap; ++ dtsec_freq = (uint16_t)(p_Dtsec->fmMacControllerDriver.clkFreq >> 1); ++ ++ dtsec_mii_init(miiregs, dtsec_freq); ++ ++ return E_OK; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/dtsec_mii_acc.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/dtsec_mii_acc.h +new file mode 100644 +index 0000000..d5dd39a +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/dtsec_mii_acc.h +@@ -0,0 +1,45 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __DTSEC_MII_ACC_H ++#define __DTSEC_MII_ACC_H ++ ++#include "std_ext.h" ++ ++ ++t_Error DTSEC_MII_WritePhyReg(t_Handle h_Dtsec, uint8_t phyAddr, uint8_t reg, uint16_t data); ++t_Error DTSEC_MII_ReadPhyReg(t_Handle h_Dtsec, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data); ++t_Error DTSEC_MII_Init(t_Handle h_Dtsec); ++ ++ ++#endif /* __DTSEC_MII_ACC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fm_mac.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fm_mac.c +new file mode 100644 +index 0000000..e2deaa2 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fm_mac.c +@@ -0,0 +1,628 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_mac.c ++ ++ @Description FM MAC ... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "string_ext.h" ++#include "sprint_ext.h" ++#include "error_ext.h" ++#include "fm_ext.h" ++ ++#include "fm_common.h" ++#include "fm_mac.h" ++ ++ ++/* ......................................................................... */ ++ ++t_Handle FM_MAC_Config (t_FmMacParams *p_FmMacParam) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_INVALID_HANDLE, NULL); ++ ++#if (DPAA_VERSION == 10) ++ if (ENET_SPEED_FROM_MODE(p_FmMacParam->enetMode) < e_ENET_SPEED_10000) ++ p_FmMacControllerDriver = (t_FmMacControllerDriver *)DTSEC_Config(p_FmMacParam); ++ else ++#if FM_MAX_NUM_OF_10G_MACS > 0 ++ p_FmMacControllerDriver = (t_FmMacControllerDriver *)TGEC_Config(p_FmMacParam); ++#else ++ p_FmMacControllerDriver = NULL; ++#endif /* FM_MAX_NUM_OF_10G_MACS > 0 */ ++#else ++ p_FmMacControllerDriver = (t_FmMacControllerDriver *)MEMAC_Config(p_FmMacParam); ++#endif /* (DPAA_VERSION == 10) */ ++ ++ if (!p_FmMacControllerDriver) ++ return NULL; ++ ++ p_FmMacControllerDriver->h_Fm = p_FmMacParam->h_Fm; ++ p_FmMacControllerDriver->enetMode = p_FmMacParam->enetMode; ++ p_FmMacControllerDriver->macId = p_FmMacParam->macId; ++ p_FmMacControllerDriver->resetOnInit = DEFAULT_resetOnInit; ++ ++ if ((p_FmMacControllerDriver->clkFreq = FmGetClockFreq(p_FmMacControllerDriver->h_Fm)) == 0) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Can't get clock for MAC!")); ++ return NULL; ++ } ++ ++ return (t_Handle)p_FmMacControllerDriver; ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_Init (t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->resetOnInit && ++ !p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit && ++ (FmResetMac(p_FmMacControllerDriver->h_Fm, ++ ((ENET_INTERFACE_FROM_MODE(p_FmMacControllerDriver->enetMode) == e_ENET_IF_XGMII) ? ++ e_FM_MAC_10G : e_FM_MAC_1G), ++ p_FmMacControllerDriver->macId) != E_OK)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't reset MAC!")); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_Init) ++ return p_FmMacControllerDriver->f_FM_MAC_Init(h_FmMac); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_Free (t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_Free) ++ return p_FmMacControllerDriver->f_FM_MAC_Free(h_FmMac); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigResetOnInit (t_Handle h_FmMac, bool enable) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit(h_FmMac, enable); ++ ++ p_FmMacControllerDriver->resetOnInit = enable; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigLoopback (t_Handle h_FmMac, bool newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback(h_FmMac, newVal); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigMaxFrameLength (t_Handle h_FmMac, uint16_t newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength(h_FmMac, newVal); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigWan (t_Handle h_FmMac, bool flag) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigWan) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigWan(h_FmMac, flag); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigPadAndCrc (t_Handle h_FmMac, bool newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc(h_FmMac, newVal); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigHalfDuplex (t_Handle h_FmMac, bool newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex(h_FmMac,newVal); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigTbiPhyAddr (t_Handle h_FmMac, uint8_t newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr(h_FmMac,newVal); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigLengthCheck (t_Handle h_FmMac, bool newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck(h_FmMac,newVal); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigException (t_Handle h_FmMac, e_FmMacExceptions ex, bool enable) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigException) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigException(h_FmMac, ex, enable); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigSkipFman11Workaround (t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigSkipFman11Workaround) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigSkipFman11Workaround(h_FmMac); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++ ++/*****************************************************************************/ ++/* Run Time Control */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_Enable (t_Handle h_FmMac, e_CommMode mode) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_Enable) ++ return p_FmMacControllerDriver->f_FM_MAC_Enable(h_FmMac, mode); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_Disable (t_Handle h_FmMac, e_CommMode mode) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_Disable) ++ return p_FmMacControllerDriver->f_FM_MAC_Disable(h_FmMac, mode); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_Enable1588TimeStamp (t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp) ++ return p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp(h_FmMac); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_Disable1588TimeStamp (t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp) ++ return p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp(h_FmMac); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetTxAutoPauseFrames(t_Handle h_FmMac, ++ uint16_t pauseTime) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames) ++ return p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames(h_FmMac, ++ pauseTime); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetTxPauseFrames(t_Handle h_FmMac, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames) ++ return p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames(h_FmMac, ++ priority, ++ pauseTime, ++ threshTime); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetRxIgnorePauseFrames (t_Handle h_FmMac, bool en) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames) ++ return p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames(h_FmMac, en); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ResetCounters (t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ResetCounters) ++ return p_FmMacControllerDriver->f_FM_MAC_ResetCounters(h_FmMac); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetException(t_Handle h_FmMac, e_FmMacExceptions ex, bool enable) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetException) ++ return p_FmMacControllerDriver->f_FM_MAC_SetException(h_FmMac, ex, enable); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetStatistics (t_Handle h_FmMac, e_FmMacStatisticsLevel statisticsLevel) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetStatistics) ++ return p_FmMacControllerDriver->f_FM_MAC_SetStatistics(h_FmMac, statisticsLevel); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_GetStatistics (t_Handle h_FmMac, t_FmMacStatistics *p_Statistics) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_GetStatistics) ++ return p_FmMacControllerDriver->f_FM_MAC_GetStatistics(h_FmMac, p_Statistics); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ModifyMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr) ++ return p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr(h_FmMac, p_EnetAddr); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_AddHashMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr) ++ return p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr(h_FmMac, p_EnetAddr); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_RemoveHashMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr) ++ return p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr(h_FmMac, p_EnetAddr); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_AddExactMatchMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr) ++ return p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr(h_FmMac, p_EnetAddr); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_RemovelExactMatchMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr) ++ return p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr(h_FmMac, p_EnetAddr); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_GetVesrion (t_Handle h_FmMac, uint32_t *macVresion) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_GetVersion) ++ return p_FmMacControllerDriver->f_FM_MAC_GetVersion(h_FmMac, macVresion); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_GetId (t_Handle h_FmMac, uint32_t *macId) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_GetId) ++ return p_FmMacControllerDriver->f_FM_MAC_GetId(h_FmMac, macId); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetPromiscuous (t_Handle h_FmMac, bool newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous) ++ return p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous(h_FmMac, newVal); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_AdjustLink(t_Handle h_FmMac, e_EnetSpeed speed, bool fullDuplex) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_AdjustLink) ++ return p_FmMacControllerDriver->f_FM_MAC_AdjustLink(h_FmMac, speed, fullDuplex); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_RestartAutoneg(t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg) ++ return p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg(h_FmMac); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_MII_WritePhyReg (t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t data) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg) ++ return p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg(h_FmMac, phyAddr, reg, data); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_MII_ReadPhyReg(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg) ++ return p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg(h_FmMac, phyAddr, reg, p_Data); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++uint16_t FM_MAC_GetMaxFrameLength(t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmMacControllerDriver, E_INVALID_HANDLE, 0); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength) ++ return p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength(h_FmMac); ++ ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ return 0; ++} ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/*****************************************************************************/ ++t_Error FM_MAC_DumpRegs(t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_DumpRegs) ++ return p_FmMacControllerDriver->f_FM_MAC_DumpRegs(h_FmMac); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fm_mac.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fm_mac.h +new file mode 100644 +index 0000000..94f7b09 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fm_mac.h +@@ -0,0 +1,222 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_mac.h ++ ++ @Description FM MAC ... ++*//***************************************************************************/ ++#ifndef __FM_MAC_H ++#define __FM_MAC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++#include "fm_mac_ext.h" ++#include "fm_common.h" ++ ++ ++#define __ERR_MODULE__ MODULE_FM_MAC ++ ++/**************************************************************************//** ++ @Description defaults ++*//***************************************************************************/ ++ ++ ++#define DEFAULT_halfDuplex FALSE ++#define DEFAULT_padAndCrcEnable TRUE ++#define DEFAULT_resetOnInit FALSE ++ ++ ++typedef struct { ++ uint64_t addr; /* Ethernet Address */ ++ t_List node; ++} t_EthHashEntry; ++#define ETH_HASH_ENTRY_OBJ(ptr) LIST_OBJECT(ptr, t_EthHashEntry, node) ++ ++typedef struct { ++ uint16_t size; ++ t_List *p_Lsts; ++} t_EthHash; ++ ++typedef struct { ++ t_Error (*f_FM_MAC_Init) (t_Handle h_FmMac); ++ t_Error (*f_FM_MAC_Free) (t_Handle h_FmMac); ++ ++ t_Error (*f_FM_MAC_SetStatistics) (t_Handle h_FmMac, e_FmMacStatisticsLevel statisticsLevel); ++ t_Error (*f_FM_MAC_ConfigLoopback) (t_Handle h_FmMac, bool newVal); ++ t_Error (*f_FM_MAC_ConfigMaxFrameLength) (t_Handle h_FmMac, uint16_t newVal); ++ t_Error (*f_FM_MAC_ConfigWan) (t_Handle h_FmMac, bool flag); ++ t_Error (*f_FM_MAC_ConfigPadAndCrc) (t_Handle h_FmMac, bool newVal); ++ t_Error (*f_FM_MAC_ConfigHalfDuplex) (t_Handle h_FmMac, bool newVal); ++ t_Error (*f_FM_MAC_ConfigLengthCheck) (t_Handle h_FmMac, bool newVal); ++ t_Error (*f_FM_MAC_ConfigTbiPhyAddr) (t_Handle h_FmMac, uint8_t newVal); ++ t_Error (*f_FM_MAC_ConfigException) (t_Handle h_FmMac, e_FmMacExceptions, bool enable); ++ t_Error (*f_FM_MAC_ConfigResetOnInit) (t_Handle h_FmMac, bool enable); ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++ t_Error (*f_FM_MAC_ConfigSkipFman11Workaround) (t_Handle h_FmMac); ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++ t_Error (*f_FM_MAC_SetException) (t_Handle h_FmMac, e_FmMacExceptions ex, bool enable); ++ ++ t_Error (*f_FM_MAC_Enable) (t_Handle h_FmMac, e_CommMode mode); ++ t_Error (*f_FM_MAC_Disable) (t_Handle h_FmMac, e_CommMode mode); ++ t_Error (*f_FM_MAC_Enable1588TimeStamp) (t_Handle h_FmMac); ++ t_Error (*f_FM_MAC_Disable1588TimeStamp) (t_Handle h_FmMac); ++ t_Error (*f_FM_MAC_Reset) (t_Handle h_FmMac, bool wait); ++ ++ t_Error (*f_FM_MAC_SetTxAutoPauseFrames) (t_Handle h_FmMac, ++ uint16_t pauseTime); ++ t_Error (*f_FM_MAC_SetTxPauseFrames) (t_Handle h_FmMac, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime); ++ t_Error (*f_FM_MAC_SetRxIgnorePauseFrames) (t_Handle h_FmMac, bool en); ++ ++ t_Error (*f_FM_MAC_ResetCounters) (t_Handle h_FmMac); ++ t_Error (*f_FM_MAC_GetStatistics) (t_Handle h_FmMac, t_FmMacStatistics *p_Statistics); ++ ++ t_Error (*f_FM_MAC_ModifyMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ t_Error (*f_FM_MAC_AddHashMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ t_Error (*f_FM_MAC_RemoveHashMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ t_Error (*f_FM_MAC_AddExactMatchMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ t_Error (*f_FM_MAC_RemovelExactMatchMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ ++ t_Error (*f_FM_MAC_SetPromiscuous) (t_Handle h_FmMac, bool newVal); ++ t_Error (*f_FM_MAC_AdjustLink) (t_Handle h_FmMac, e_EnetSpeed speed, bool fullDuplex); ++ t_Error (*f_FM_MAC_RestartAutoneg) (t_Handle h_FmMac); ++ ++ t_Error (*f_FM_MAC_GetId) (t_Handle h_FmMac, uint32_t *macId); ++ ++ t_Error (*f_FM_MAC_GetVersion) (t_Handle h_FmMac, uint32_t *macVersion); ++ ++ uint16_t (*f_FM_MAC_GetMaxFrameLength) (t_Handle h_FmMac); ++ ++ t_Error (*f_FM_MAC_MII_WritePhyReg)(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t data); ++ t_Error (*f_FM_MAC_MII_ReadPhyReg)(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data); ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_Error (*f_FM_MAC_DumpRegs) (t_Handle h_FmMac); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ t_Handle h_Fm; ++ t_FmRevisionInfo fmRevInfo; ++ e_EnetMode enetMode; ++ uint8_t macId; ++ bool resetOnInit; ++ uint16_t clkFreq; ++} t_FmMacControllerDriver; ++ ++ ++#if (DPAA_VERSION == 10) ++t_Handle DTSEC_Config(t_FmMacParams *p_FmMacParam); ++t_Handle TGEC_Config(t_FmMacParams *p_FmMacParams); ++#else ++t_Handle MEMAC_Config(t_FmMacParams *p_FmMacParam); ++#endif /* (DPAA_VERSION == 10) */ ++uint16_t FM_MAC_GetMaxFrameLength(t_Handle FmMac); ++ ++ ++/* ........................................................................... */ ++ ++static __inline__ t_EthHashEntry *DequeueAddrFromHashEntry(t_List *p_AddrLst) ++{ ++ t_EthHashEntry *p_HashEntry = NULL; ++ if (!LIST_IsEmpty(p_AddrLst)) ++ { ++ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_AddrLst->p_Next); ++ LIST_DelAndInit(&p_HashEntry->node); ++ } ++ return p_HashEntry; ++} ++ ++/* ........................................................................... */ ++ ++static __inline__ void FreeHashTable(t_EthHash *p_Hash) ++{ ++ t_EthHashEntry *p_HashEntry; ++ int i = 0; ++ ++ if (p_Hash) ++ { ++ if (p_Hash->p_Lsts) ++ { ++ for (i=0; isize; i++) ++ { ++ p_HashEntry = DequeueAddrFromHashEntry(&p_Hash->p_Lsts[i]); ++ while (p_HashEntry) ++ { ++ XX_Free(p_HashEntry); ++ p_HashEntry = DequeueAddrFromHashEntry(&p_Hash->p_Lsts[i]); ++ } ++ } ++ ++ XX_Free(p_Hash->p_Lsts); ++ } ++ ++ XX_Free(p_Hash); ++ } ++} ++ ++/* ........................................................................... */ ++ ++static __inline__ t_EthHash * AllocHashTable(uint16_t size) ++{ ++ uint32_t i; ++ t_EthHash *p_Hash; ++ ++ /* Allocate address hash table */ ++ p_Hash = (t_EthHash *)XX_Malloc(size*sizeof(t_EthHash *)); ++ if (!p_Hash) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Address hash table")); ++ return NULL; ++ } ++ p_Hash->size = size; ++ ++ p_Hash->p_Lsts = (t_List *)XX_Malloc(p_Hash->size*sizeof(t_List)); ++ if (!p_Hash->p_Lsts) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Address hash table")); ++ XX_Free(p_Hash); ++ return NULL; ++ } ++ ++ for (i=0 ; isize; i++) ++ INIT_LIST(&p_Hash->p_Lsts[i]); ++ ++ return p_Hash; ++} ++ ++ ++#endif /* __FM_MAC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_crc32.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_crc32.c +new file mode 100644 +index 0000000..b6a4ca2 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_crc32.c +@@ -0,0 +1,119 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "fman_crc32.h" ++#include "common/general.h" ++ ++ ++/* precomputed CRC values for address hashing */ ++static const uint32_t crc_tbl[256] = { ++ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, ++ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, ++ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, ++ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, ++ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, ++ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, ++ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, ++ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, ++ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, ++ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, ++ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, ++ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, ++ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, ++ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, ++ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, ++ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, ++ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, ++ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, ++ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, ++ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, ++ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, ++ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, ++ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, ++ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, ++ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, ++ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, ++ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, ++ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, ++ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, ++ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, ++ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, ++ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, ++ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, ++ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, ++ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, ++ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, ++ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, ++ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, ++ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, ++ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, ++ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, ++ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, ++ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d ++}; ++ ++/* Get the mirrored value of a byte size number. (0x11010011 --> 0x11001011) */ ++static inline uint8_t get_mirror8(uint8_t n) ++{ ++ uint8_t mirror[16] = { ++ 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, ++ 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f ++ }; ++ return (uint8_t)(((mirror[n & 0x0f] << 4) | (mirror[n >> 4]))); ++} ++ ++static inline uint32_t get_mirror32(uint32_t n) ++{ ++ return ((uint32_t)get_mirror8((uint8_t)(n))<<24) | ++ ((uint32_t)get_mirror8((uint8_t)(n>>8))<<16) | ++ ((uint32_t)get_mirror8((uint8_t)(n>>16))<<8) | ++ ((uint32_t)get_mirror8((uint8_t)(n>>24))); ++} ++ ++uint32_t get_mac_addr_crc(uint64_t _addr) ++{ ++ uint32_t i; ++ uint8_t data; ++ uint32_t crc; ++ ++ /* CRC calculation */ ++ crc = 0xffffffff; ++ for (i = 0; i < 6; i++) { ++ data = (uint8_t)(_addr >> ((5-i)*8)); ++ crc = crc ^ data; ++ crc = crc_tbl[crc&0xff] ^ (crc>>8); ++ } ++ ++ crc = get_mirror32(crc); ++ return crc; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_crc32.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_crc32.h +new file mode 100644 +index 0000000..6e32fdc +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_crc32.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __FMAN_CRC32_H ++#define __FMAN_CRC32_H ++ ++#include "common/general.h" ++ ++ ++uint32_t get_mac_addr_crc(uint64_t _addr); ++ ++ ++#endif /* __FMAN_CRC32_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_dtsec.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_dtsec.c +new file mode 100644 +index 0000000..2ba8554 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_dtsec.c +@@ -0,0 +1,818 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "fsl_fman_dtsec.h" ++ ++ ++void dtsec_stop_rx(struct dtsec_regs *regs) ++{ ++ /* Assert the graceful stop bit */ ++ iowrite32be(ioread32be(®s->rctrl) | RCTRL_GRS, ®s->rctrl); ++} ++ ++void dtsec_stop_tx(struct dtsec_regs *regs) ++{ ++ /* Assert the graceful stop bit */ ++ iowrite32be(ioread32be(®s->tctrl) | DTSEC_TCTRL_GTS, ®s->tctrl); ++} ++ ++void dtsec_start_tx(struct dtsec_regs *regs) ++{ ++ /* clear the graceful stop bit */ ++ iowrite32be(ioread32be(®s->tctrl) & ~DTSEC_TCTRL_GTS, ®s->tctrl); ++} ++ ++void dtsec_start_rx(struct dtsec_regs *regs) ++{ ++ /* clear the graceful stop bit */ ++ iowrite32be(ioread32be(®s->rctrl) & ~RCTRL_GRS, ®s->rctrl); ++} ++ ++void dtsec_defconfig(struct dtsec_cfg *cfg) ++{ ++ cfg->halfdup_on = DEFAULT_HALFDUP_ON; ++ cfg->halfdup_retransmit = DEFAULT_HALFDUP_RETRANSMIT; ++ cfg->halfdup_coll_window = DEFAULT_HALFDUP_COLL_WINDOW; ++ cfg->halfdup_excess_defer = DEFAULT_HALFDUP_EXCESS_DEFER; ++ cfg->halfdup_no_backoff = DEFAULT_HALFDUP_NO_BACKOFF; ++ cfg->halfdup_bp_no_backoff = DEFAULT_HALFDUP_BP_NO_BACKOFF; ++ cfg->halfdup_alt_backoff_val = DEFAULT_HALFDUP_ALT_BACKOFF_VAL; ++ cfg->halfdup_alt_backoff_en = DEFAULT_HALFDUP_ALT_BACKOFF_EN; ++ cfg->rx_drop_bcast = DEFAULT_RX_DROP_BCAST; ++ cfg->rx_short_frm = DEFAULT_RX_SHORT_FRM; ++ cfg->rx_len_check = DEFAULT_RX_LEN_CHECK; ++ cfg->tx_pad_crc = DEFAULT_TX_PAD_CRC; ++ cfg->tx_crc = DEFAULT_TX_CRC; ++ cfg->rx_ctrl_acc = DEFAULT_RX_CTRL_ACC; ++ cfg->tx_pause_time = DEFAULT_TX_PAUSE_TIME; ++ cfg->tbipa = DEFAULT_TBIPA; /* PHY address 0 is reserved (DPAA RM)*/ ++ cfg->rx_prepend = DEFAULT_RX_PREPEND; ++ cfg->ptp_tsu_en = DEFAULT_PTP_TSU_EN; ++ cfg->ptp_exception_en = DEFAULT_PTP_EXCEPTION_EN; ++ cfg->preamble_len = DEFAULT_PREAMBLE_LEN; ++ cfg->rx_preamble = DEFAULT_RX_PREAMBLE; ++ cfg->tx_preamble = DEFAULT_TX_PREAMBLE; ++ cfg->loopback = DEFAULT_LOOPBACK; ++ cfg->rx_time_stamp_en = DEFAULT_RX_TIME_STAMP_EN; ++ cfg->tx_time_stamp_en = DEFAULT_TX_TIME_STAMP_EN; ++ cfg->rx_flow = DEFAULT_RX_FLOW; ++ cfg->tx_flow = DEFAULT_TX_FLOW; ++ cfg->rx_group_hash_exd = DEFAULT_RX_GROUP_HASH_EXD; ++ cfg->tx_pause_time_extd = DEFAULT_TX_PAUSE_TIME_EXTD; ++ cfg->rx_promisc = DEFAULT_RX_PROMISC; ++ cfg->non_back_to_back_ipg1 = DEFAULT_NON_BACK_TO_BACK_IPG1; ++ cfg->non_back_to_back_ipg2 = DEFAULT_NON_BACK_TO_BACK_IPG2; ++ cfg->min_ifg_enforcement = DEFAULT_MIN_IFG_ENFORCEMENT; ++ cfg->back_to_back_ipg = DEFAULT_BACK_TO_BACK_IPG; ++ cfg->maximum_frame = DEFAULT_MAXIMUM_FRAME; ++ cfg->tbi_phy_addr = DEFAULT_TBI_PHY_ADDR; ++} ++ ++int dtsec_init(struct dtsec_regs *regs, struct dtsec_cfg *cfg, ++ enum enet_interface iface_mode, ++ enum enet_speed iface_speed, ++ uint8_t *macaddr, ++ uint8_t fm_rev_maj, ++ uint8_t fm_rev_min, ++ uint32_t exception_mask) ++{ ++ bool is_rgmii = FALSE; ++ bool is_sgmii = FALSE; ++ bool is_qsgmii = FALSE; ++ int i; ++ uint32_t tmp; ++ ++UNUSED(fm_rev_maj);UNUSED(fm_rev_min); ++ ++ /* let's start with a soft reset */ ++ iowrite32be(MACCFG1_SOFT_RESET, ®s->maccfg1); ++ iowrite32be(0, ®s->maccfg1); ++ ++ /*************dtsec_id2******************/ ++ tmp = ioread32be(®s->tsec_id2); ++ ++ /* check RGMII support */ ++ if (iface_mode == E_ENET_IF_RGMII || ++ iface_mode == E_ENET_IF_RMII) ++ if (tmp & DTSEC_ID2_INT_REDUCED_OFF) ++ return -EINVAL; ++ ++ if (iface_mode == E_ENET_IF_SGMII || ++ iface_mode == E_ENET_IF_MII) ++ if (tmp & DTSEC_ID2_INT_REDUCED_OFF) ++ return -EINVAL; ++ ++ /***************ECNTRL************************/ ++ ++ is_rgmii = (bool)((iface_mode == E_ENET_IF_RGMII) ? TRUE : FALSE); ++ is_sgmii = (bool)((iface_mode == E_ENET_IF_SGMII) ? TRUE : FALSE); ++ is_qsgmii = (bool)((iface_mode == E_ENET_IF_QSGMII) ? TRUE : FALSE); ++ ++ tmp = 0; ++ if (is_rgmii || iface_mode == E_ENET_IF_GMII) ++ tmp |= DTSEC_ECNTRL_GMIIM; ++ if (is_sgmii) ++ tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM); ++ if (is_qsgmii) ++ tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM | ++ DTSEC_ECNTRL_QSGMIIM); ++ if (is_rgmii) ++ tmp |= DTSEC_ECNTRL_RPM; ++ if (iface_speed == E_ENET_SPEED_100) ++ tmp |= DTSEC_ECNTRL_R100M; ++ ++ iowrite32be(tmp, ®s->ecntrl); ++ /***************ECNTRL************************/ ++ ++ /***************TCTRL************************/ ++ tmp = 0; ++ if (cfg->halfdup_on) ++ tmp |= DTSEC_TCTRL_THDF; ++ if (cfg->tx_time_stamp_en) ++ tmp |= DTSEC_TCTRL_TTSE; ++ ++ iowrite32be(tmp, ®s->tctrl); ++ ++ /***************TCTRL************************/ ++ ++ /***************PTV************************/ ++ tmp = 0; ++ ++#ifdef FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1 ++ if ((fm_rev_maj == 1) && (fm_rev_min == 0)) ++ cfg->tx_pause_time += 2; ++#endif /* FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1 */ ++ ++ if (cfg->tx_pause_time) ++ tmp |= cfg->tx_pause_time; ++ if (cfg->tx_pause_time_extd) ++ tmp |= cfg->tx_pause_time_extd << PTV_PTE_OFST; ++ iowrite32be(tmp, ®s->ptv); ++ ++ /***************RCTRL************************/ ++ tmp = 0; ++ tmp |= ((uint32_t)(cfg->rx_prepend & 0x0000001f)) << 16; ++ if (cfg->rx_ctrl_acc) ++ tmp |= RCTRL_CFA; ++ if (cfg->rx_group_hash_exd) ++ tmp |= RCTRL_GHTX; ++ if (cfg->rx_time_stamp_en) ++ tmp |= RCTRL_RTSE; ++ if (cfg->rx_drop_bcast) ++ tmp |= RCTRL_BC_REJ; ++ if (cfg->rx_short_frm) ++ tmp |= RCTRL_RSF; ++ if (cfg->rx_promisc) ++ tmp |= RCTRL_PROM; ++ ++ iowrite32be(tmp, ®s->rctrl); ++ /***************RCTRL************************/ ++ ++ /* ++ * Assign a Phy Address to the TBI (TBIPA). ++ * Done also in cases where TBI is not selected to avoid conflict with ++ * the external PHY's Physical address ++ */ ++ iowrite32be(cfg->tbipa, ®s->tbipa); ++ ++ /***************TMR_CTL************************/ ++ iowrite32be(0, ®s->tmr_ctrl); ++ ++ if (cfg->ptp_tsu_en) { ++ tmp = 0; ++ tmp |= TMR_PEVENT_TSRE; ++ iowrite32be(tmp, ®s->tmr_pevent); ++ ++ if (cfg->ptp_exception_en) { ++ tmp = 0; ++ tmp |= TMR_PEMASK_TSREEN; ++ iowrite32be(tmp, ®s->tmr_pemask); ++ } ++ } ++ ++ /***************MACCFG1***********************/ ++ tmp = 0; ++ if (cfg->loopback) ++ tmp |= MACCFG1_LOOPBACK; ++ if (cfg->rx_flow) ++ tmp |= MACCFG1_RX_FLOW; ++ if (cfg->tx_flow) ++ tmp |= MACCFG1_TX_FLOW; ++ iowrite32be(tmp, ®s->maccfg1); ++ ++ /***************MACCFG1***********************/ ++ ++ /***************MACCFG2***********************/ ++ tmp = 0; ++ ++ if (iface_speed < E_ENET_SPEED_1000) ++ tmp |= MACCFG2_NIBBLE_MODE; ++ else if (iface_speed == E_ENET_SPEED_1000) ++ tmp |= MACCFG2_BYTE_MODE; ++ ++ tmp |= ((uint32_t) cfg->preamble_len & 0x0000000f) ++ << PREAMBLE_LENGTH_SHIFT; ++ ++ if (cfg->rx_preamble) ++ tmp |= MACCFG2_PRE_AM_Rx_EN; ++ if (cfg->tx_preamble) ++ tmp |= MACCFG2_PRE_AM_Tx_EN; ++ if (cfg->rx_len_check) ++ tmp |= MACCFG2_LENGTH_CHECK; ++ if (cfg->tx_pad_crc) ++ tmp |= MACCFG2_PAD_CRC_EN; ++ if (cfg->tx_crc) ++ tmp |= MACCFG2_CRC_EN; ++ if (!cfg->halfdup_on) ++ tmp |= MACCFG2_FULL_DUPLEX; ++ iowrite32be(tmp, ®s->maccfg2); ++ ++ /***************MACCFG2***********************/ ++ ++ /***************IPGIFG************************/ ++ tmp = 0; ++ tmp = (((cfg->non_back_to_back_ipg1 << ++ IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT) ++ & IPGIFG_NON_BACK_TO_BACK_IPG_1) ++ | ((cfg->non_back_to_back_ipg2 << ++ IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT) ++ & IPGIFG_NON_BACK_TO_BACK_IPG_2) ++ | ((cfg->min_ifg_enforcement << ++ IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT) ++ & IPGIFG_MIN_IFG_ENFORCEMENT) ++ | (cfg->back_to_back_ipg & IPGIFG_BACK_TO_BACK_IPG)); ++ iowrite32be(tmp, ®s->ipgifg); ++ ++ /***************IPGIFG************************/ ++ ++ /***************HAFDUP************************/ ++ tmp = 0; ++ ++ if (cfg->halfdup_alt_backoff_en) ++ tmp = (uint32_t)(HAFDUP_ALT_BEB | ++ ((cfg->halfdup_alt_backoff_val & 0x0000000f) ++ << HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT)); ++ if (cfg->halfdup_bp_no_backoff) ++ tmp |= HAFDUP_BP_NO_BACKOFF; ++ if (cfg->halfdup_no_backoff) ++ tmp |= HAFDUP_NO_BACKOFF; ++ if (cfg->halfdup_excess_defer) ++ tmp |= HAFDUP_EXCESS_DEFER; ++ tmp |= ((cfg->halfdup_retransmit << HAFDUP_RETRANSMISSION_MAX_SHIFT) ++ & HAFDUP_RETRANSMISSION_MAX); ++ tmp |= (cfg->halfdup_coll_window & HAFDUP_COLLISION_WINDOW); ++ ++ iowrite32be(tmp, ®s->hafdup); ++ /***************HAFDUP************************/ ++ ++ /***************MAXFRM************************/ ++ /* Initialize MAXFRM */ ++ iowrite32be(cfg->maximum_frame, ®s->maxfrm); ++ ++ /***************MAXFRM************************/ ++ ++ /***************CAM1************************/ ++ iowrite32be(0xffffffff, ®s->cam1); ++ iowrite32be(0xffffffff, ®s->cam2); ++ ++ /***************IMASK************************/ ++ iowrite32be(exception_mask, ®s->imask); ++ /***************IMASK************************/ ++ ++ /***************IEVENT************************/ ++ iowrite32be(0xffffffff, ®s->ievent); ++ ++ /***************MACSTNADDR1/2*****************/ ++ ++ tmp = (uint32_t)((macaddr[5] << 24) | ++ (macaddr[4] << 16) | ++ (macaddr[3] << 8) | ++ macaddr[2]); ++ iowrite32be(tmp, ®s->macstnaddr1); ++ ++ tmp = (uint32_t)((macaddr[1] << 24) | ++ (macaddr[0] << 16)); ++ iowrite32be(tmp, ®s->macstnaddr2); ++ ++ /***************MACSTNADDR1/2*****************/ ++ ++ /*****************HASH************************/ ++ for (i = 0; i < NUM_OF_HASH_REGS ; i++) { ++ /* Initialize IADDRx */ ++ iowrite32be(0, ®s->igaddr[i]); ++ /* Initialize GADDRx */ ++ iowrite32be(0, ®s->gaddr[i]); ++ } ++ ++ dtsec_reset_stat(regs); ++ ++ return 0; ++} ++ ++uint16_t dtsec_get_max_frame_len(struct dtsec_regs *regs) ++{ ++ return (uint16_t)ioread32be(®s->maxfrm); ++} ++ ++void dtsec_set_max_frame_len(struct dtsec_regs *regs, uint16_t length) ++{ ++ iowrite32be(length, ®s->maxfrm); ++} ++ ++void dtsec_set_mac_address(struct dtsec_regs *regs, uint8_t *adr) ++{ ++ uint32_t tmp; ++ ++ tmp = (uint32_t)((adr[5] << 24) | ++ (adr[4] << 16) | ++ (adr[3] << 8) | ++ adr[2]); ++ iowrite32be(tmp, ®s->macstnaddr1); ++ ++ tmp = (uint32_t)((adr[1] << 24) | ++ (adr[0] << 16)); ++ iowrite32be(tmp, ®s->macstnaddr2); ++} ++ ++void dtsec_get_mac_address(struct dtsec_regs *regs, uint8_t *macaddr) ++{ ++ uint32_t tmp1, tmp2; ++ ++ tmp1 = ioread32be(®s->macstnaddr1); ++ tmp2 = ioread32be(®s->macstnaddr2); ++ ++ macaddr[0] = (uint8_t)((tmp2 & 0x00ff0000) >> 16); ++ macaddr[1] = (uint8_t)((tmp2 & 0xff000000) >> 24); ++ macaddr[2] = (uint8_t)(tmp1 & 0x000000ff); ++ macaddr[3] = (uint8_t)((tmp1 & 0x0000ff00) >> 8); ++ macaddr[4] = (uint8_t)((tmp1 & 0x00ff0000) >> 16); ++ macaddr[5] = (uint8_t)((tmp1 & 0xff000000) >> 24); ++} ++ ++void dtsec_set_bucket(struct dtsec_regs *regs, int bucket, bool enable) ++{ ++ int reg_idx = (bucket >> 5) & 0xf; ++ int bit_idx = bucket & 0x1f; ++ uint32_t bit_mask = 0x80000000 >> bit_idx; ++ uint32_t *reg; ++ ++ if (reg_idx > 7) ++ reg = ®s->gaddr[reg_idx-8]; ++ else ++ reg = ®s->igaddr[reg_idx]; ++ ++ if (enable) ++ iowrite32be(ioread32be(reg) | bit_mask, reg); ++ else ++ iowrite32be(ioread32be(reg) & (~bit_mask), reg); ++} ++ ++void dtsec_reset_filter_table(struct dtsec_regs *regs, bool mcast, bool ucast) ++{ ++ int i; ++ bool ghtx; ++ ++ ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? TRUE : FALSE); ++ ++ if (ucast || (ghtx && mcast)) { ++ for (i = 0; i < NUM_OF_HASH_REGS; i++) ++ iowrite32be(0, ®s->igaddr[i]); ++ } ++ if (mcast) { ++ for (i = 0; i < NUM_OF_HASH_REGS; i++) ++ iowrite32be(0, ®s->gaddr[i]); ++ } ++} ++ ++int dtsec_set_tbi_phy_addr(struct dtsec_regs *regs, ++ uint8_t addr) ++{ ++ if (addr > 0 && addr < 32) ++ iowrite32be(addr, ®s->tbipa); ++ else ++ return -EINVAL; ++ ++ return 0; ++} ++ ++int dtsec_adjust_link(struct dtsec_regs *regs, ++ enum enet_interface iface_mode, ++ enum enet_speed speed, bool full_dx) ++{ ++ uint32_t tmp; ++ ++ if ((speed == E_ENET_SPEED_1000) && !full_dx) ++ return -EINVAL; ++ ++ tmp = ioread32be(®s->maccfg2); ++ if (!full_dx) ++ tmp &= ~MACCFG2_FULL_DUPLEX; ++ else ++ tmp |= MACCFG2_FULL_DUPLEX; ++ ++ tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); ++ if (speed < E_ENET_SPEED_1000) ++ tmp |= MACCFG2_NIBBLE_MODE; ++ else if (speed == E_ENET_SPEED_1000) ++ tmp |= MACCFG2_BYTE_MODE; ++ iowrite32be(tmp, ®s->maccfg2); ++ ++ tmp = ioread32be(®s->ecntrl); ++ if (speed == E_ENET_SPEED_100) ++ tmp |= DTSEC_ECNTRL_R100M; ++ else ++ tmp &= ~DTSEC_ECNTRL_R100M; ++ iowrite32be(tmp, ®s->ecntrl); ++ ++ return 0; ++} ++ ++void dtsec_set_uc_promisc(struct dtsec_regs *regs, bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->rctrl); ++ ++ if (enable) ++ tmp |= RCTRL_UPROM; ++ else ++ tmp &= ~RCTRL_UPROM; ++ ++ iowrite32be(tmp, ®s->rctrl); ++} ++ ++void dtsec_set_mc_promisc(struct dtsec_regs *regs, bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->rctrl); ++ ++ if (enable) ++ tmp |= RCTRL_MPROM; ++ else ++ tmp &= ~RCTRL_MPROM; ++ ++ iowrite32be(tmp, ®s->rctrl); ++} ++ ++bool dtsec_get_clear_carry_regs(struct dtsec_regs *regs, ++ uint32_t *car1, uint32_t *car2) ++{ ++ /* read carry registers */ ++ *car1 = ioread32be(®s->car1); ++ *car2 = ioread32be(®s->car2); ++ /* clear carry registers */ ++ if (*car1) ++ iowrite32be(*car1, ®s->car1); ++ if (*car2) ++ iowrite32be(*car2, ®s->car2); ++ ++ return (bool)((*car1 | *car2) ? TRUE : FALSE); ++} ++ ++ ++void dtsec_reset_stat(struct dtsec_regs *regs) ++{ ++ /* clear HW counters */ ++ iowrite32be(ioread32be(®s->ecntrl) | ++ DTSEC_ECNTRL_CLRCNT, ®s->ecntrl); ++} ++ ++int dtsec_set_stat_level(struct dtsec_regs *regs, enum mac_stat_level level) ++{ ++ switch (level) { ++ case E_MAC_STAT_NONE: ++ iowrite32be(0xffffffff, ®s->cam1); ++ iowrite32be(0xffffffff, ®s->cam2); ++ iowrite32be(ioread32be(®s->ecntrl) & ~DTSEC_ECNTRL_STEN, ++ ®s->ecntrl); ++ iowrite32be(ioread32be(®s->imask) & ~DTSEC_IMASK_MSROEN, ++ ®s->imask); ++ break; ++ case E_MAC_STAT_PARTIAL: ++ iowrite32be(CAM1_ERRORS_ONLY, ®s->cam1); ++ iowrite32be(CAM2_ERRORS_ONLY, ®s->cam2); ++ iowrite32be(ioread32be(®s->ecntrl) | DTSEC_ECNTRL_STEN, ++ ®s->ecntrl); ++ iowrite32be(ioread32be(®s->imask) | DTSEC_IMASK_MSROEN, ++ ®s->imask); ++ break; ++ case E_MAC_STAT_MIB_GRP1: ++ iowrite32be((uint32_t)~CAM1_MIB_GRP_1, ®s->cam1); ++ iowrite32be((uint32_t)~CAM2_MIB_GRP_1, ®s->cam2); ++ iowrite32be(ioread32be(®s->ecntrl) | DTSEC_ECNTRL_STEN, ++ ®s->ecntrl); ++ iowrite32be(ioread32be(®s->imask) | DTSEC_IMASK_MSROEN, ++ ®s->imask); ++ break; ++ case E_MAC_STAT_FULL: ++ iowrite32be(0, ®s->cam1); ++ iowrite32be(0, ®s->cam2); ++ iowrite32be(ioread32be(®s->ecntrl) | DTSEC_ECNTRL_STEN, ++ ®s->ecntrl); ++ iowrite32be(ioread32be(®s->imask) | DTSEC_IMASK_MSROEN, ++ ®s->imask); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++void dtsec_set_ts(struct dtsec_regs *regs, bool en) ++{ ++ if (en) { ++ iowrite32be(ioread32be(®s->rctrl) | RCTRL_RTSE, ++ ®s->rctrl); ++ iowrite32be(ioread32be(®s->tctrl) | DTSEC_TCTRL_TTSE, ++ ®s->tctrl); ++ } else { ++ iowrite32be(ioread32be(®s->rctrl) & ~RCTRL_RTSE, ++ ®s->rctrl); ++ iowrite32be(ioread32be(®s->tctrl) & ~DTSEC_TCTRL_TTSE, ++ ®s->tctrl); ++ } ++} ++ ++void dtsec_enable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->maccfg1); ++ ++ if (apply_rx) ++ tmp |= MACCFG1_RX_EN ; ++ ++ if (apply_tx) ++ tmp |= MACCFG1_TX_EN ; ++ ++ iowrite32be(tmp, ®s->maccfg1); ++} ++ ++void dtsec_clear_addr_in_paddr(struct dtsec_regs *regs, uint8_t paddr_num) ++{ ++ iowrite32be(0, ®s->macaddr[paddr_num].exact_match1); ++ iowrite32be(0, ®s->macaddr[paddr_num].exact_match2); ++} ++ ++void dtsec_add_addr_in_paddr(struct dtsec_regs *regs, ++ uint64_t addr, ++ uint8_t paddr_num) ++{ ++ uint32_t tmp; ++ ++ tmp = (uint32_t)(addr); ++ /* swap */ ++ tmp = (((tmp & 0x000000FF) << 24) | ++ ((tmp & 0x0000FF00) << 8) | ++ ((tmp & 0x00FF0000) >> 8) | ++ ((tmp & 0xFF000000) >> 24)); ++ iowrite32be(tmp, ®s->macaddr[paddr_num].exact_match1); ++ ++ tmp = (uint32_t)(addr>>32); ++ /* swap */ ++ tmp = (((tmp & 0x000000FF) << 24) | ++ ((tmp & 0x0000FF00) << 8) | ++ ((tmp & 0x00FF0000) >> 8) | ++ ((tmp & 0xFF000000) >> 24)); ++ iowrite32be(tmp, ®s->macaddr[paddr_num].exact_match2); ++} ++ ++void dtsec_disable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->maccfg1); ++ ++ if (apply_rx) ++ tmp &= ~MACCFG1_RX_EN; ++ ++ if (apply_tx) ++ tmp &= ~MACCFG1_TX_EN; ++ ++ iowrite32be(tmp, ®s->maccfg1); ++} ++ ++void dtsec_set_tx_pause_time(struct dtsec_regs *regs, uint16_t time) ++{ ++ uint32_t ptv = 0; ++ ++ /* fixme: don't enable tx pause for half-duplex */ ++ ++ if (time) { ++ ptv = ioread32be(®s->ptv); ++ ptv &= 0xffff0000; ++ ptv |= time & 0x0000ffff; ++ iowrite32be(ptv, ®s->ptv); ++ ++ /* trigger the transmission of a flow-control pause frame */ ++ iowrite32be(ioread32be(®s->maccfg1) | MACCFG1_TX_FLOW, ++ ®s->maccfg1); ++ } else ++ iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW, ++ ®s->maccfg1); ++} ++ ++void dtsec_handle_rx_pause(struct dtsec_regs *regs, bool en) ++{ ++ uint32_t tmp; ++ ++ /* todo: check if mac is set to full-duplex */ ++ ++ tmp = ioread32be(®s->maccfg1); ++ if (en) ++ tmp |= MACCFG1_RX_FLOW; ++ else ++ tmp &= ~MACCFG1_RX_FLOW; ++ iowrite32be(tmp, ®s->maccfg1); ++} ++ ++uint32_t dtsec_get_rctrl(struct dtsec_regs *regs) ++{ ++ return ioread32be(®s->rctrl); ++} ++ ++uint32_t dtsec_get_revision(struct dtsec_regs *regs) ++{ ++ return ioread32be(®s->tsec_id); ++} ++ ++uint32_t dtsec_get_event(struct dtsec_regs *regs, uint32_t ev_mask) ++{ ++ return ioread32be(®s->ievent) & ev_mask; ++} ++ ++void dtsec_ack_event(struct dtsec_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ev_mask, ®s->ievent); ++} ++ ++uint32_t dtsec_get_interrupt_mask(struct dtsec_regs *regs) ++{ ++ return ioread32be(®s->imask); ++} ++ ++uint32_t dtsec_check_and_clear_tmr_event(struct dtsec_regs *regs) ++{ ++ uint32_t event; ++ ++ event = ioread32be(®s->tmr_pevent); ++ event &= ioread32be(®s->tmr_pemask); ++ ++ if (event) ++ iowrite32be(event, ®s->tmr_pevent); ++ return event; ++} ++ ++void dtsec_enable_tmr_interrupt(struct dtsec_regs *regs) ++{ ++ iowrite32be(ioread32be(®s->tmr_pemask) | TMR_PEMASK_TSREEN, ++ ®s->tmr_pemask); ++} ++ ++void dtsec_disable_tmr_interrupt(struct dtsec_regs *regs) ++{ ++ iowrite32be(ioread32be(®s->tmr_pemask) & ~TMR_PEMASK_TSREEN, ++ ®s->tmr_pemask); ++} ++ ++void dtsec_enable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ioread32be(®s->imask) | ev_mask, ®s->imask); ++} ++ ++void dtsec_disable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ioread32be(®s->imask) & ~ev_mask, ®s->imask); ++} ++ ++uint32_t dtsec_get_stat_counter(struct dtsec_regs *regs, ++ enum dtsec_stat_counters reg_name) ++{ ++ uint32_t ret_val; ++ ++ switch (reg_name) { ++ case E_DTSEC_STAT_TR64: ++ ret_val = ioread32be(®s->tr64); ++ break; ++ case E_DTSEC_STAT_TR127: ++ ret_val = ioread32be(®s->tr127); ++ break; ++ case E_DTSEC_STAT_TR255: ++ ret_val = ioread32be(®s->tr255); ++ break; ++ case E_DTSEC_STAT_TR511: ++ ret_val = ioread32be(®s->tr511); ++ break; ++ case E_DTSEC_STAT_TR1K: ++ ret_val = ioread32be(®s->tr1k); ++ break; ++ case E_DTSEC_STAT_TRMAX: ++ ret_val = ioread32be(®s->trmax); ++ break; ++ case E_DTSEC_STAT_TRMGV: ++ ret_val = ioread32be(®s->trmgv); ++ break; ++ case E_DTSEC_STAT_RBYT: ++ ret_val = ioread32be(®s->rbyt); ++ break; ++ case E_DTSEC_STAT_RPKT: ++ ret_val = ioread32be(®s->rpkt); ++ break; ++ case E_DTSEC_STAT_RMCA: ++ ret_val = ioread32be(®s->rmca); ++ break; ++ case E_DTSEC_STAT_RBCA: ++ ret_val = ioread32be(®s->rbca); ++ break; ++ case E_DTSEC_STAT_RXPF: ++ ret_val = ioread32be(®s->rxpf); ++ break; ++ case E_DTSEC_STAT_RALN: ++ ret_val = ioread32be(®s->raln); ++ break; ++ case E_DTSEC_STAT_RFLR: ++ ret_val = ioread32be(®s->rflr); ++ break; ++ case E_DTSEC_STAT_RCDE: ++ ret_val = ioread32be(®s->rcde); ++ break; ++ case E_DTSEC_STAT_RCSE: ++ ret_val = ioread32be(®s->rcse); ++ break; ++ case E_DTSEC_STAT_RUND: ++ ret_val = ioread32be(®s->rund); ++ break; ++ case E_DTSEC_STAT_ROVR: ++ ret_val = ioread32be(®s->rovr); ++ break; ++ case E_DTSEC_STAT_RFRG: ++ ret_val = ioread32be(®s->rfrg); ++ break; ++ case E_DTSEC_STAT_RJBR: ++ ret_val = ioread32be(®s->rjbr); ++ break; ++ case E_DTSEC_STAT_RDRP: ++ ret_val = ioread32be(®s->rdrp); ++ break; ++ case E_DTSEC_STAT_TFCS: ++ ret_val = ioread32be(®s->tfcs); ++ break; ++ case E_DTSEC_STAT_TBYT: ++ ret_val = ioread32be(®s->tbyt); ++ break; ++ case E_DTSEC_STAT_TPKT: ++ ret_val = ioread32be(®s->tpkt); ++ break; ++ case E_DTSEC_STAT_TMCA: ++ ret_val = ioread32be(®s->tmca); ++ break; ++ case E_DTSEC_STAT_TBCA: ++ ret_val = ioread32be(®s->tbca); ++ break; ++ case E_DTSEC_STAT_TXPF: ++ ret_val = ioread32be(®s->txpf); ++ break; ++ case E_DTSEC_STAT_TNCL: ++ ret_val = ioread32be(®s->tncl); ++ break; ++ case E_DTSEC_STAT_TDRP: ++ ret_val = ioread32be(®s->tdrp); ++ break; ++ default: ++ ret_val = 0; ++ } ++ ++ return ret_val; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_dtsec_mii_acc.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_dtsec_mii_acc.c +new file mode 100644 +index 0000000..82f4997 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_dtsec_mii_acc.c +@@ -0,0 +1,148 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "common/general.h" ++#include "fsl_fman_dtsec_mii_acc.h" ++ ++ ++/** ++ * dtsec_mii_get_div() - calculates the value of the dtsec mii divider ++ * @dtsec_freq: dtsec clock frequency (in Mhz) ++ * ++ * This function calculates the dtsec mii clock divider that determines ++ * the MII MDC clock. MII MDC clock can work in the range of 2.5 to 12.5 Mhz. ++ * The output of this function is the value of MIIMCFG[MgmtClk] which ++ * implicitly determines the divider value. ++ * Note: the dTSEC system clock is equal to 1/2 of the FMan clock. ++ * ++ * The table below which reflects dtsec_mii_get_div() functionality ++ * shows the relations among dtsec_freq, MgmtClk, actual divider ++ * and the MII frequency: ++ * ++ * dtsec freq MgmtClk div MII freq ++ * [80..159] 0 (1/4)(1/8) [2.5 to 5.0] ++ * [160..319] 1 (1/4)(1/8) [5.0 to 10.0] ++ * [320..479] 2 (1/6)(1/8) [6.7 to 10.0] ++ * [480..639] 3 (1/8)(1/8) [7.5 to 10.0] ++ * [640..799] 4 (1/10)(1/8) [8.0 to 10.0] ++ * [800..959] 5 (1/14)(1/8) [7.1 to 8.5] ++ * [960..1119] 6 (1/20)(1/8) [6.0 to 7.0] ++ * [1120..1279] 7 (1/28)(1/8) [5.0 to 5.7] ++ * [1280..2800] 7 (1/28)(1/8) [5.7 to 12.5] ++ * ++ * Returns: the MIIMCFG[MgmtClk] appropriate value ++ */ ++ ++static uint8_t dtsec_mii_get_div(uint16_t dtsec_freq) ++{ ++ uint16_t mgmt_clk = (uint16_t)(dtsec_freq / 160); ++ ++ if (mgmt_clk > 7) ++ mgmt_clk = 7; ++ ++ return (uint8_t)mgmt_clk; ++} ++ ++void dtsec_mii_reset(struct dtsec_mii_reg *regs) ++{ ++ /* Reset the management interface */ ++ iowrite32be(ioread32be(®s->miimcfg) | MIIMCFG_RESET_MGMT, ++ ®s->miimcfg); ++ iowrite32be(ioread32be(®s->miimcfg) & ~MIIMCFG_RESET_MGMT, ++ ®s->miimcfg); ++} ++ ++void dtsec_mii_init(struct dtsec_mii_reg *regs, uint16_t dtsec_freq) ++{ ++ /* Setup the MII Mgmt clock speed */ ++ iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), ®s->miimcfg); ++} ++ ++int dtsec_mii_write_reg(struct dtsec_mii_reg *regs, uint8_t addr, ++ uint8_t reg, uint16_t data) ++{ ++ uint32_t tmp; ++ ++ /* Stop the MII management read cycle */ ++ iowrite32be(0, ®s->miimcom); ++ /* Dummy read to make sure MIIMCOM is written */ ++ tmp = ioread32be(®s->miimcom); ++ ++ /* Setting up MII Management Address Register */ ++ tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg); ++ iowrite32be(tmp, ®s->miimadd); ++ ++ /* Setting up MII Management Control Register with data */ ++ iowrite32be((uint32_t)data, ®s->miimcon); ++ /* Dummy read to make sure MIIMCON is written */ ++ tmp = ioread32be(®s->miimcon); ++ ++ /* Wait untill MII management write is complete */ ++ /* todo: a timeout could be useful here */ ++ while ((ioread32be(®s->miimind)) & MIIMIND_BUSY) ++ /* busy wait */; ++ ++ return 0; ++} ++ ++int dtsec_mii_read_reg(struct dtsec_mii_reg *regs, uint8_t addr, ++ uint8_t reg, uint16_t *data) ++{ ++ uint32_t tmp; ++ ++ /* Setting up the MII Management Address Register */ ++ tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg); ++ iowrite32be(tmp, ®s->miimadd); ++ ++ /* Perform an MII management read cycle */ ++ iowrite32be(MIIMCOM_READ_CYCLE, ®s->miimcom); ++ /* Dummy read to make sure MIIMCOM is written */ ++ tmp = ioread32be(®s->miimcom); ++ ++ /* Wait until MII management read is complete */ ++ /* todo: a timeout could be useful here */ ++ while ((ioread32be(®s->miimind)) & MIIMIND_BUSY) ++ /* busy wait */; ++ ++ /* Read MII management status */ ++ *data = (uint16_t)ioread32be(®s->miimstat); ++ ++ iowrite32be(0, ®s->miimcom); ++ /* Dummy read to make sure MIIMCOM is written */ ++ tmp = ioread32be(®s->miimcom); ++ ++ if (*data == 0xffff) ++ return -ENXIO; ++ ++ return 0; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_memac.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_memac.c +new file mode 100644 +index 0000000..a63d06a +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_memac.c +@@ -0,0 +1,427 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "fsl_fman_memac.h" ++ ++ ++uint32_t memac_get_event(struct memac_regs *regs, uint32_t ev_mask) ++{ ++ return ioread32be(®s->ievent) & ev_mask; ++} ++ ++uint32_t memac_get_interrupt_mask(struct memac_regs *regs) ++{ ++ return ioread32be(®s->imask); ++} ++ ++void memac_ack_event(struct memac_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ev_mask, ®s->ievent); ++} ++ ++void memac_set_promiscuous(struct memac_regs *regs, bool val) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ if (val) ++ tmp |= CMD_CFG_PROMIS_EN; ++ else ++ tmp &= ~CMD_CFG_PROMIS_EN; ++ ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void memac_hardware_clear_addr_in_paddr(struct memac_regs *regs, ++ uint8_t paddr_num) ++{ ++ if (paddr_num == 0) { ++ iowrite32be(0, ®s->mac_addr0.mac_addr_l); ++ iowrite32be(0, ®s->mac_addr0.mac_addr_u); ++ } else { ++ iowrite32be(0x0, ®s->mac_addr[paddr_num - 1].mac_addr_l); ++ iowrite32be(0x0, ®s->mac_addr[paddr_num - 1].mac_addr_u); ++ } ++} ++ ++void memac_hardware_add_addr_in_paddr(struct memac_regs *regs, ++ uint8_t *adr, ++ uint8_t paddr_num) ++{ ++ uint32_t tmp0, tmp1; ++ ++ tmp0 = (uint32_t)(adr[0] | ++ adr[1] << 8 | ++ adr[2] << 16 | ++ adr[3] << 24); ++ tmp1 = (uint32_t)(adr[4] | adr[5] << 8); ++ ++ if (paddr_num == 0) { ++ iowrite32be(tmp0, ®s->mac_addr0.mac_addr_l); ++ iowrite32be(tmp1, ®s->mac_addr0.mac_addr_u); ++ } else { ++ iowrite32be(tmp0, ®s->mac_addr[paddr_num-1].mac_addr_l); ++ iowrite32be(tmp1, ®s->mac_addr[paddr_num-1].mac_addr_u); ++ } ++} ++ ++void memac_enable(struct memac_regs *regs, bool apply_rx, bool apply_tx) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ if (apply_rx) ++ tmp |= CMD_CFG_RX_EN; ++ ++ if (apply_tx) ++ tmp |= CMD_CFG_TX_EN; ++ ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void memac_disable(struct memac_regs *regs, bool apply_rx, bool apply_tx) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ if (apply_rx) ++ tmp &= ~CMD_CFG_RX_EN; ++ ++ if (apply_tx) ++ tmp &= ~CMD_CFG_TX_EN; ++ ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void memac_reset_counter(struct memac_regs *regs) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->statn_config); ++ ++ tmp |= STATS_CFG_CLR; ++ ++ iowrite32be(tmp, ®s->statn_config); ++ ++ while (ioread32be(®s->statn_config) & STATS_CFG_CLR); ++} ++ ++void memac_reset(struct memac_regs *regs) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ tmp |= CMD_CFG_SW_RESET; ++ ++ iowrite32be(tmp, ®s->command_config); ++ ++ while (ioread32be(®s->command_config) & CMD_CFG_SW_RESET); ++} ++ ++void memac_init(struct memac_regs *regs, ++ struct memac_cfg *cfg, ++ enum enet_interface enet_interface, ++ enum enet_speed enet_speed, ++ uint32_t exceptions) ++{ ++ uint32_t tmp; ++ ++ /* Config */ ++ tmp = 0; ++ if (cfg->wan_mode_enable) ++ tmp |= CMD_CFG_WAN_MODE; ++ if (cfg->promiscuous_mode_enable) ++ tmp |= CMD_CFG_PROMIS_EN; ++ if (cfg->pause_forward_enable) ++ tmp |= CMD_CFG_PAUSE_FWD; ++ if (cfg->pause_ignore) ++ tmp |= CMD_CFG_PAUSE_IGNORE; ++ if (cfg->tx_addr_ins_enable) ++ tmp |= CMD_CFG_TX_ADDR_INS; ++ if (cfg->loopback_enable) ++ tmp |= CMD_CFG_LOOPBACK_EN; ++ if (cfg->cmd_frame_enable) ++ tmp |= CMD_CFG_CNT_FRM_EN; ++ if (cfg->send_idle_enable) ++ tmp |= CMD_CFG_SEND_IDLE; ++ if (cfg->no_length_check_enable) ++ tmp |= CMD_CFG_NO_LEN_CHK; ++ if (cfg->rx_sfd_any) ++ tmp |= CMD_CFG_SFD_ANY; ++ if (cfg->pad_enable) ++ tmp |= CMD_CFG_TX_PAD_EN; ++ ++ tmp |= CMD_CFG_CRC_FWD; ++ ++ iowrite32be(tmp, ®s->command_config); ++ ++ /* Max Frame Length */ ++ iowrite32be((uint32_t)cfg->max_frame_length, ®s->maxfrm); ++ ++ /* Pause Time */ ++ iowrite32be(cfg->pause_quanta, ®s->pause_quanta[0]); ++ iowrite32be(0, ®s->pause_thresh[0]); ++ ++ /* interrupts */ ++ iowrite32be(MEMAC_EVENTS_MASK, ®s->ievent); ++ iowrite32be(exceptions, ®s->imask); ++ ++ /* IF_MODE */ ++ tmp = 0; ++ switch (enet_interface) { ++ case E_ENET_IF_XGMII: ++ case E_ENET_IF_XFI: ++ tmp |= IF_MODE_XGMII; ++ break; ++ default: ++ tmp |= IF_MODE_GMII; ++ if (enet_interface == E_ENET_IF_RGMII) ++ tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO; ++ } ++ iowrite32be(tmp, ®s->if_mode); ++} ++ ++void memac_set_exception(struct memac_regs *regs, uint32_t val, bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->imask); ++ if (enable) ++ tmp |= val; ++ else ++ tmp &= ~val; ++ ++ iowrite32be(tmp, ®s->imask); ++} ++ ++void memac_set_hash_table(struct memac_regs *regs, uint32_t val) ++{ ++ iowrite32be(val, ®s->hashtable_ctrl); ++} ++ ++uint16_t memac_get_max_frame_length(struct memac_regs *regs) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->maxfrm); ++ ++ return(uint16_t)tmp; ++} ++ ++ ++void memac_set_tx_pause_frames(struct memac_regs *regs, ++ uint8_t priority, ++ uint16_t pause_time, ++ uint16_t thresh_time) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ if (priority == 0xff) { ++ tmp &= ~CMD_CFG_PFC_MODE; ++ priority = 0; ++ } ++ else ++ tmp |= CMD_CFG_PFC_MODE; ++ ++ iowrite32be(tmp, ®s->command_config); ++ ++ tmp = ioread32be(®s->pause_quanta[priority / 2]); ++ if (priority % 2) ++ tmp &= 0x0000FFFF; ++ else ++ tmp &= 0xFFFF0000; ++ tmp |= ((uint32_t)pause_time << (16 * (priority % 2))); ++ iowrite32be(tmp, ®s->pause_quanta[priority / 2]); ++ ++ tmp = ioread32be(®s->pause_thresh[priority / 2]); ++ if (priority % 2) ++ tmp &= 0x0000FFFF; ++ else ++ tmp &= 0xFFFF0000; ++ tmp |= ((uint32_t)thresh_time<<(16 * (priority % 2))); ++ iowrite32be(tmp, ®s->pause_thresh[priority / 2]); ++} ++ ++void memac_set_rx_ignore_pause_frames(struct memac_regs *regs,bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ if (enable) ++ tmp |= CMD_CFG_PAUSE_IGNORE; ++ else ++ tmp &= ~CMD_CFG_PAUSE_IGNORE; ++ ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void memac_set_loopback(struct memac_regs *regs, bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ if (enable) ++ tmp |= CMD_CFG_LOOPBACK_EN; ++ else ++ tmp &= ~CMD_CFG_LOOPBACK_EN; ++ ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++ ++#define GET_MEMAC_CNTR_64(bn) \ ++ (ioread32be(®s->bn ## _l) | \ ++ ((uint64_t)ioread32be(®s->bn ## _u) << 32)) ++ ++uint64_t memac_get_counter(struct memac_regs *regs, ++ enum memac_counters reg_name) ++{ ++ uint64_t ret_val; ++ ++ switch (reg_name) { ++ case E_MEMAC_COUNTER_R64: ++ ret_val = GET_MEMAC_CNTR_64(r64); ++ break; ++ case E_MEMAC_COUNTER_R127: ++ ret_val = GET_MEMAC_CNTR_64(r127); ++ break; ++ case E_MEMAC_COUNTER_R255: ++ ret_val = GET_MEMAC_CNTR_64(r255); ++ break; ++ case E_MEMAC_COUNTER_R511: ++ ret_val = GET_MEMAC_CNTR_64(r511); ++ break; ++ case E_MEMAC_COUNTER_R1023: ++ ret_val = GET_MEMAC_CNTR_64(r1023); ++ break; ++ case E_MEMAC_COUNTER_R1518: ++ ret_val = GET_MEMAC_CNTR_64(r1518); ++ break; ++ case E_MEMAC_COUNTER_R1519X: ++ ret_val = GET_MEMAC_CNTR_64(r1519x); ++ break; ++ case E_MEMAC_COUNTER_RFRG: ++ ret_val = GET_MEMAC_CNTR_64(rfrg); ++ break; ++ case E_MEMAC_COUNTER_RJBR: ++ ret_val = GET_MEMAC_CNTR_64(rjbr); ++ break; ++ case E_MEMAC_COUNTER_RDRP: ++ ret_val = GET_MEMAC_CNTR_64(rdrp); ++ break; ++ case E_MEMAC_COUNTER_RALN: ++ ret_val = GET_MEMAC_CNTR_64(raln); ++ break; ++ case E_MEMAC_COUNTER_TUND: ++ ret_val = GET_MEMAC_CNTR_64(tund); ++ break; ++ case E_MEMAC_COUNTER_ROVR: ++ ret_val = GET_MEMAC_CNTR_64(rovr); ++ break; ++ case E_MEMAC_COUNTER_RXPF: ++ ret_val = GET_MEMAC_CNTR_64(rxpf); ++ break; ++ case E_MEMAC_COUNTER_TXPF: ++ ret_val = GET_MEMAC_CNTR_64(txpf); ++ break; ++ case E_MEMAC_COUNTER_ROCT: ++ ret_val = GET_MEMAC_CNTR_64(roct); ++ break; ++ case E_MEMAC_COUNTER_RMCA: ++ ret_val = GET_MEMAC_CNTR_64(rmca); ++ break; ++ case E_MEMAC_COUNTER_RBCA: ++ ret_val = GET_MEMAC_CNTR_64(rbca); ++ break; ++ case E_MEMAC_COUNTER_RPKT: ++ ret_val = GET_MEMAC_CNTR_64(rpkt); ++ break; ++ case E_MEMAC_COUNTER_RUCA: ++ ret_val = GET_MEMAC_CNTR_64(ruca); ++ break; ++ case E_MEMAC_COUNTER_RERR: ++ ret_val = GET_MEMAC_CNTR_64(rerr); ++ break; ++ case E_MEMAC_COUNTER_TOCT: ++ ret_val = GET_MEMAC_CNTR_64(toct); ++ break; ++ case E_MEMAC_COUNTER_TMCA: ++ ret_val = GET_MEMAC_CNTR_64(tmca); ++ break; ++ case E_MEMAC_COUNTER_TBCA: ++ ret_val = GET_MEMAC_CNTR_64(tbca); ++ break; ++ case E_MEMAC_COUNTER_TUCA: ++ ret_val = GET_MEMAC_CNTR_64(tuca); ++ break; ++ case E_MEMAC_COUNTER_TERR: ++ ret_val = GET_MEMAC_CNTR_64(terr); ++ break; ++ default: ++ ret_val = 0; ++ } ++ ++ return ret_val; ++} ++ ++void memac_defconfig(struct memac_cfg *cfg) ++{ ++ cfg->reset_on_init = FALSE; ++ cfg->wan_mode_enable = FALSE; ++ cfg->promiscuous_mode_enable = FALSE; ++ cfg->pause_forward_enable = FALSE; ++ cfg->pause_ignore = FALSE; ++ cfg->tx_addr_ins_enable = FALSE; ++ cfg->loopback_enable = FALSE; ++ cfg->cmd_frame_enable = FALSE; ++ cfg->rx_error_discard = FALSE; ++ cfg->send_idle_enable = FALSE; ++ cfg->no_length_check_enable = TRUE; ++ cfg->lgth_check_nostdr = FALSE; ++ cfg->time_stamp_enable = FALSE; ++ cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH; ++ cfg->max_frame_length = DEFAULT_FRAME_LENGTH; ++ cfg->pause_quanta = DEFAULT_PAUSE_QUANTA; ++ cfg->pad_enable = TRUE; ++ cfg->phy_tx_ena_on = FALSE; ++ cfg->rx_sfd_any = FALSE; ++ cfg->rx_pbl_fwd = FALSE; ++ cfg->tx_pbl_fwd = FALSE; ++ cfg->debug_mode = FALSE; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_tgec.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_tgec.c +new file mode 100644 +index 0000000..fa80a36 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fman_tgec.c +@@ -0,0 +1,355 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "fsl_fman_tgec.h" ++ ++ ++void tgec_set_mac_address(struct tgec_regs *regs, uint8_t *adr) ++{ ++ uint32_t tmp0, tmp1; ++ ++ tmp0 = (uint32_t)(adr[0] | ++ adr[1] << 8 | ++ adr[2] << 16 | ++ adr[3] << 24); ++ tmp1 = (uint32_t)(adr[4] | adr[5] << 8); ++ iowrite32be(tmp0, ®s->mac_addr_0); ++ iowrite32be(tmp1, ®s->mac_addr_1); ++} ++ ++void tgec_reset_stat(struct tgec_regs *regs) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ tmp |= CMD_CFG_STAT_CLR; ++ ++ iowrite32be(tmp, ®s->command_config); ++ ++ while (ioread32be(®s->command_config) & CMD_CFG_STAT_CLR); ++} ++ ++#define GET_TGEC_CNTR_64(bn) \ ++ (((uint64_t)ioread32be(®s->bn ## _u) << 32) | \ ++ ioread32be(®s->bn ## _l)) ++ ++uint64_t tgec_get_counter(struct tgec_regs *regs, enum tgec_counters reg_name) ++{ ++ uint64_t ret_val; ++ ++ switch (reg_name) { ++ case E_TGEC_COUNTER_R64: ++ ret_val = GET_TGEC_CNTR_64(r64); ++ break; ++ case E_TGEC_COUNTER_R127: ++ ret_val = GET_TGEC_CNTR_64(r127); ++ break; ++ case E_TGEC_COUNTER_R255: ++ ret_val = GET_TGEC_CNTR_64(r255); ++ break; ++ case E_TGEC_COUNTER_R511: ++ ret_val = GET_TGEC_CNTR_64(r511); ++ break; ++ case E_TGEC_COUNTER_R1023: ++ ret_val = GET_TGEC_CNTR_64(r1023); ++ break; ++ case E_TGEC_COUNTER_R1518: ++ ret_val = GET_TGEC_CNTR_64(r1518); ++ break; ++ case E_TGEC_COUNTER_R1519X: ++ ret_val = GET_TGEC_CNTR_64(r1519x); ++ break; ++ case E_TGEC_COUNTER_TRFRG: ++ ret_val = GET_TGEC_CNTR_64(trfrg); ++ break; ++ case E_TGEC_COUNTER_TRJBR: ++ ret_val = GET_TGEC_CNTR_64(trjbr); ++ break; ++ case E_TGEC_COUNTER_RDRP: ++ ret_val = GET_TGEC_CNTR_64(rdrp); ++ break; ++ case E_TGEC_COUNTER_RALN: ++ ret_val = GET_TGEC_CNTR_64(raln); ++ break; ++ case E_TGEC_COUNTER_TRUND: ++ ret_val = GET_TGEC_CNTR_64(trund); ++ break; ++ case E_TGEC_COUNTER_TROVR: ++ ret_val = GET_TGEC_CNTR_64(trovr); ++ break; ++ case E_TGEC_COUNTER_RXPF: ++ ret_val = GET_TGEC_CNTR_64(rxpf); ++ break; ++ case E_TGEC_COUNTER_TXPF: ++ ret_val = GET_TGEC_CNTR_64(txpf); ++ break; ++ case E_TGEC_COUNTER_ROCT: ++ ret_val = GET_TGEC_CNTR_64(roct); ++ break; ++ case E_TGEC_COUNTER_RMCA: ++ ret_val = GET_TGEC_CNTR_64(rmca); ++ break; ++ case E_TGEC_COUNTER_RBCA: ++ ret_val = GET_TGEC_CNTR_64(rbca); ++ break; ++ case E_TGEC_COUNTER_RPKT: ++ ret_val = GET_TGEC_CNTR_64(rpkt); ++ break; ++ case E_TGEC_COUNTER_RUCA: ++ ret_val = GET_TGEC_CNTR_64(ruca); ++ break; ++ case E_TGEC_COUNTER_RERR: ++ ret_val = GET_TGEC_CNTR_64(rerr); ++ break; ++ case E_TGEC_COUNTER_TOCT: ++ ret_val = GET_TGEC_CNTR_64(toct); ++ break; ++ case E_TGEC_COUNTER_TMCA: ++ ret_val = GET_TGEC_CNTR_64(tmca); ++ break; ++ case E_TGEC_COUNTER_TBCA: ++ ret_val = GET_TGEC_CNTR_64(tbca); ++ break; ++ case E_TGEC_COUNTER_TUCA: ++ ret_val = GET_TGEC_CNTR_64(tuca); ++ break; ++ case E_TGEC_COUNTER_TERR: ++ ret_val = GET_TGEC_CNTR_64(terr); ++ break; ++ default: ++ ret_val = 0; ++ } ++ ++ return ret_val; ++} ++ ++void tgec_enable(struct tgec_regs *regs, bool apply_rx, bool apply_tx) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ if (apply_rx) ++ tmp |= CMD_CFG_RX_EN; ++ if (apply_tx) ++ tmp |= CMD_CFG_TX_EN; ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void tgec_disable(struct tgec_regs *regs, bool apply_rx, bool apply_tx) ++{ ++ uint32_t tmp_reg_32; ++ ++ tmp_reg_32 = ioread32be(®s->command_config); ++ if (apply_rx) ++ tmp_reg_32 &= ~CMD_CFG_RX_EN; ++ if (apply_tx) ++ tmp_reg_32 &= ~CMD_CFG_TX_EN; ++ iowrite32be(tmp_reg_32, ®s->command_config); ++} ++ ++void tgec_set_promiscuous(struct tgec_regs *regs, bool val) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ if (val) ++ tmp |= CMD_CFG_PROMIS_EN; ++ else ++ tmp &= ~CMD_CFG_PROMIS_EN; ++ ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void tgec_set_hash_table(struct tgec_regs *regs, uint32_t value) ++{ ++ iowrite32be(value, ®s->hashtable_ctrl); ++} ++ ++void tgec_tx_mac_pause(struct tgec_regs *regs, uint16_t pause_time) ++{ ++ iowrite32be((uint32_t)pause_time, ®s->pause_quant); ++} ++ ++void tgec_rx_ignore_mac_pause(struct tgec_regs *regs, bool en) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ if (en) ++ tmp |= CMD_CFG_PAUSE_IGNORE; ++ else ++ tmp &= ~CMD_CFG_PAUSE_IGNORE; ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void tgec_enable_1588_time_stamp(struct tgec_regs *regs, bool en) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ if (en) ++ tmp |= CMD_CFG_EN_TIMESTAMP; ++ else ++ tmp &= ~CMD_CFG_EN_TIMESTAMP; ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++uint32_t tgec_get_event(struct tgec_regs *regs, uint32_t ev_mask) ++{ ++ return ioread32be(®s->ievent) & ev_mask; ++} ++ ++void tgec_ack_event(struct tgec_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ev_mask, ®s->ievent); ++} ++ ++uint32_t tgec_get_interrupt_mask(struct tgec_regs *regs) ++{ ++ return ioread32be(®s->imask); ++} ++ ++void tgec_add_addr_in_paddr(struct tgec_regs *regs, uint8_t *adr) ++{ ++ uint32_t tmp0, tmp1; ++ ++ tmp0 = (uint32_t)(adr[0] | ++ adr[1] << 8 | ++ adr[2] << 16 | ++ adr[3] << 24); ++ tmp1 = (uint32_t)(adr[4] | adr[5] << 8); ++ iowrite32be(tmp0, ®s->mac_addr_2); ++ iowrite32be(tmp1, ®s->mac_addr_3); ++} ++ ++void tgec_clear_addr_in_paddr(struct tgec_regs *regs) ++{ ++ iowrite32be(0, ®s->mac_addr_2); ++ iowrite32be(0, ®s->mac_addr_3); ++} ++ ++uint32_t tgec_get_revision(struct tgec_regs *regs) ++{ ++ return ioread32be(®s->tgec_id); ++} ++ ++void tgec_enable_interrupt(struct tgec_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ioread32be(®s->imask) | ev_mask, ®s->imask); ++} ++ ++void tgec_disable_interrupt(struct tgec_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ioread32be(®s->imask) & ~ev_mask, ®s->imask); ++} ++ ++uint16_t tgec_get_max_frame_len(struct tgec_regs *regs) ++{ ++ return (uint16_t) ioread32be(®s->maxfrm); ++} ++ ++void tgec_defconfig(struct tgec_cfg *cfg) ++{ ++ cfg->wan_mode_enable = DEFAULT_WAN_MODE_ENABLE; ++ cfg->promiscuous_mode_enable = DEFAULT_PROMISCUOUS_MODE_ENABLE; ++ cfg->pause_forward_enable = DEFAULT_PAUSE_FORWARD_ENABLE; ++ cfg->pause_ignore = DEFAULT_PAUSE_IGNORE; ++ cfg->tx_addr_ins_enable = DEFAULT_TX_ADDR_INS_ENABLE; ++ cfg->loopback_enable = DEFAULT_LOOPBACK_ENABLE; ++ cfg->cmd_frame_enable = DEFAULT_CMD_FRAME_ENABLE; ++ cfg->rx_error_discard = DEFAULT_RX_ERROR_DISCARD; ++ cfg->send_idle_enable = DEFAULT_SEND_IDLE_ENABLE; ++ cfg->no_length_check_enable = DEFAULT_NO_LENGTH_CHECK_ENABLE; ++ cfg->lgth_check_nostdr = DEFAULT_LGTH_CHECK_NOSTDR; ++ cfg->time_stamp_enable = DEFAULT_TIME_STAMP_ENABLE; ++ cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH; ++ cfg->max_frame_length = DEFAULT_MAX_FRAME_LENGTH; ++ cfg->pause_quant = DEFAULT_PAUSE_QUANT; ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++ cfg->skip_fman11_workaround = FALSE; ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++} ++ ++int tgec_init(struct tgec_regs *regs, struct tgec_cfg *cfg, ++ uint32_t exception_mask) ++{ ++ uint32_t tmp; ++ ++ /* Config */ ++ tmp = 0x40; /* CRC forward */ ++ if (cfg->wan_mode_enable) ++ tmp |= CMD_CFG_WAN_MODE; ++ if (cfg->promiscuous_mode_enable) ++ tmp |= CMD_CFG_PROMIS_EN; ++ if (cfg->pause_forward_enable) ++ tmp |= CMD_CFG_PAUSE_FWD; ++ if (cfg->pause_ignore) ++ tmp |= CMD_CFG_PAUSE_IGNORE; ++ if (cfg->tx_addr_ins_enable) ++ tmp |= CMD_CFG_TX_ADDR_INS; ++ if (cfg->loopback_enable) ++ tmp |= CMD_CFG_LOOPBACK_EN; ++ if (cfg->cmd_frame_enable) ++ tmp |= CMD_CFG_CMD_FRM_EN; ++ if (cfg->rx_error_discard) ++ tmp |= CMD_CFG_RX_ER_DISC; ++ if (cfg->send_idle_enable) ++ tmp |= CMD_CFG_SEND_IDLE; ++ if (cfg->no_length_check_enable) ++ tmp |= CMD_CFG_NO_LEN_CHK; ++ if (cfg->time_stamp_enable) ++ tmp |= CMD_CFG_EN_TIMESTAMP; ++ iowrite32be(tmp, ®s->command_config); ++ /* Max Frame Length */ ++ iowrite32be((uint32_t)cfg->max_frame_length, ®s->maxfrm); ++ /* Pause Time */ ++ iowrite32be(cfg->pause_quant, ®s->pause_quant); ++ ++ /* clear all pending events and set-up interrupts */ ++ tgec_ack_event(regs, 0xffffffff); ++ tgec_enable_interrupt(regs, exception_mask); ++ return 0; ++} ++ ++void tgec_fm_tx_fifo_corruption_errata_10gmac_a007(struct tgec_regs *regs) ++{ ++ uint32_t tmp; ++ ++ /* restore the default tx ipg Length */ ++ tmp = (ioread32be(®s->tx_ipg_len) & ~TX_IPG_LENGTH_MASK) | 12; ++ ++ iowrite32be(tmp, ®s->tx_ipg_len); ++ ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fsl_fman_dtsec_mii_acc.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fsl_fman_dtsec_mii_acc.h +new file mode 100644 +index 0000000..2d74b6a +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/fsl_fman_dtsec_mii_acc.h +@@ -0,0 +1,102 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __FSL_FMAN_DTSEC_MII_ACC_H ++#define __FSL_FMAN_DTSEC_MII_ACC_H ++ ++#include "common/general.h" ++ ++ ++/* MII Management Configuration Register */ ++#define MIIMCFG_RESET_MGMT 0x80000000 ++#define MIIMCFG_MGNTCLK_MASK 0x00000007 ++#define MIIMCFG_MGNTCLK_SHIFT 0 ++ ++/* MII Management Command Register */ ++#define MIIMCOM_SCAN_CYCLE 0x00000002 ++#define MIIMCOM_READ_CYCLE 0x00000001 ++ ++/* MII Management Address Register */ ++#define MIIMADD_PHY_ADDR_SHIFT 8 ++#define MIIMADD_PHY_ADDR_MASK 0x00001f00 ++ ++#define MIIMADD_REG_ADDR_SHIFT 0 ++#define MIIMADD_REG_ADDR_MASK 0x0000001f ++ ++/* MII Management Indicator Register */ ++#define MIIMIND_BUSY 0x00000001 ++ ++ ++/* PHY Control Register */ ++#define PHY_CR_LOOPBACK 0x4000 ++#define PHY_CR_SPEED0 0x2000 ++#define PHY_CR_ANE 0x1000 ++#define PHY_CR_FULLDUPLEX 0x0100 ++#define PHY_CR_SPEED1 0x0040 ++ ++#define PHY_TBICON_SRESET 0x8000 ++#define PHY_TBICON_SPEED2 0x0020 ++ ++/* register map */ ++ ++/* MII Configuration Control Memory Map Registers */ ++struct dtsec_mii_reg { ++ uint32_t reserved1[72]; ++ uint32_t miimcfg; /* MII Mgmt:configuration */ ++ uint32_t miimcom; /* MII Mgmt:command */ ++ uint32_t miimadd; /* MII Mgmt:address */ ++ uint32_t miimcon; /* MII Mgmt:control 3 */ ++ uint32_t miimstat; /* MII Mgmt:status */ ++ uint32_t miimind; /* MII Mgmt:indicators */ ++}; ++ ++/* dTSEC MII API */ ++ ++/* functions to access the mii registers for phy configuration. ++ * this functionality may not be available for all dtsecs in the system. ++ * consult the reference manual for details */ ++void dtsec_mii_reset(struct dtsec_mii_reg *regs); ++/* frequency is in MHz. ++ * note that dtsec clock is 1/2 of fman clock */ ++void dtsec_mii_init(struct dtsec_mii_reg *regs, uint16_t dtsec_freq); ++int dtsec_mii_write_reg(struct dtsec_mii_reg *regs, ++ uint8_t addr, ++ uint8_t reg, ++ uint16_t data); ++ ++int dtsec_mii_read_reg(struct dtsec_mii_reg *regs, ++ uint8_t addr, ++ uint8_t reg, ++ uint16_t *data); ++ ++#endif /* __FSL_FMAN_DTSEC_MII_ACC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/memac.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/memac.c +new file mode 100644 +index 0000000..6e5440d +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/memac.c +@@ -0,0 +1,1036 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 memac.c ++ ++ @Description FM mEMAC driver ++*//***************************************************************************/ ++ ++#include "std_ext.h" ++#include "string_ext.h" ++#include "error_ext.h" ++#include "xx_ext.h" ++#include "endian_ext.h" ++#include "debug_ext.h" ++ ++#include "fm_common.h" ++#include "memac.h" ++ ++ ++/*****************************************************************************/ ++/* Internal routines */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static uint32_t GetMacAddrHashCode(uint64_t ethAddr) ++{ ++ uint64_t mask1, mask2; ++ uint32_t xor = 0; ++ uint8_t i, j; ++ ++ for (i=0; i < 6; i++) ++ { ++ mask1 = ethAddr & (uint64_t)0x01; ++ ethAddr >>= 1; ++ ++ for (j=0; j < 7; j++) ++ { ++ mask2 = ethAddr & (uint64_t)0x01; ++ mask1 ^= mask2; ++ ethAddr >>= 1; ++ } ++ xor |= (mask1 << (5-i)); ++ } ++ ++ return xor; ++} ++ ++ ++/* ......................................................................... */ ++ ++static void SetupSgmiiInternalPhy(t_Memac *p_Memac, uint8_t phyAddr) ++{ ++ uint16_t tmpReg16; ++ ++ /* SGMII mode + AN enable */ ++ tmpReg16 = PHY_SGMII_IF_MODE_AN | PHY_SGMII_IF_MODE_SGMII; ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x14, tmpReg16); ++ ++ /* Device ability according to SGMII specification */ ++ tmpReg16 = PHY_SGMII_DEV_ABILITY_SGMII; ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x4, tmpReg16); ++ ++ /* Adjust link timer for SGMII - ++ According to Cisco SGMII specification the timer should be 1.6 ms. ++ The link_timer register is configured in units of the clock. ++ - When running as 1G SGMII, Serdes clock is 125 MHz, so ++ unit = 1 / (125*10^6 Hz) = 8 ns. ++ 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2 * 10^5 = 0x30d40 ++ - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so ++ unit = 1 / (312.5*10^6 Hz) = 3.2 ns. ++ 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5 * 10^5 = 0x7a120. ++ Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, ++ we always set up here a value of 2.5 SGMII. */ ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x13, 0x0007); ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x12, 0xa120); ++ ++ /* Restart AN */ ++ tmpReg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN; ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x0, tmpReg16); ++} ++ ++/* ......................................................................... */ ++ ++static void SetupSgmiiInternalPhyBaseX(t_Memac *p_Memac, uint8_t phyAddr) ++{ ++ uint16_t tmpReg16; ++ ++ /* 1000BaseX mode */ ++ tmpReg16 = PHY_SGMII_IF_MODE_1000X; ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x14, tmpReg16); ++ ++ /* AN Device capability */ ++ tmpReg16 = PHY_SGMII_DEV_ABILITY_1000X; ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x4, tmpReg16); ++ ++ /* Adjust link timer for SGMII - ++ For Serdes 1000BaseX auto-negotiation the timer should be 10 ms. ++ The link_timer register is configured in units of the clock. ++ - When running as 1G SGMII, Serdes clock is 125 MHz, so ++ unit = 1 / (125*10^6 Hz) = 8 ns. ++ 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0 ++ - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so ++ unit = 1 / (312.5*10^6 Hz) = 3.2 ns. ++ 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08. ++ Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, ++ we always set up here a value of 2.5 SGMII. */ ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x13, 0x002f); ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x12, 0xaf08); ++ ++ /* Restart AN */ ++ tmpReg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN; ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x0, tmpReg16); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error CheckInitParameters(t_Memac *p_Memac) ++{ ++ e_FmMacType portType; ++ ++ portType = ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G); ++ ++#if (FM_MAX_NUM_OF_10G_MACS > 0) ++ if ((portType == e_FM_MAC_10G) && (p_Memac->macId >= FM_MAX_NUM_OF_10G_MACS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("10G MAC ID must be less than %d", FM_MAX_NUM_OF_10G_MACS)); ++#endif /* (FM_MAX_NUM_OF_10G_MACS > 0) */ ++ ++ if ((portType == e_FM_MAC_1G) && (p_Memac->macId >= FM_MAX_NUM_OF_1G_MACS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("1G MAC ID must be less than %d", FM_MAX_NUM_OF_1G_MACS)); ++ if (p_Memac->addr == 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC must have a valid MAC address")); ++ if (!p_Memac->f_Exception) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Uninitialized f_Exception")); ++ if (!p_Memac->f_Event) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Uninitialized f_Event")); ++#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002 ++ if (!p_Memac->p_MemacDriverParam->no_length_check_enable) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!")); ++#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */ ++ ++ return E_OK; ++} ++ ++/* ........................................................................... */ ++ ++static void MemacErrException(t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ struct memac_regs *regs = p_Memac->p_MemMap; ++ uint32_t event, imsk; ++ ++ event = memac_get_event(regs, 0xffffffff); ++ ++ /* ++ * Apparently the imask bits are shifted by 16 bits offset from ++ * their corresponding bits in the ievent - hence the >> 16 ++ */ ++ imsk = memac_get_interrupt_mask(regs) >> 16;; ++ ++ /* ++ * Extract all event bits plus the pending interrupts according to ++ * their imask ++ */ ++ event = (event & ~(MEMAC_ALL_IMASKS >> 16)) | (event & imsk); ++ ++ /* Ignoring the status bits */ ++ event = event & ~(MEMAC_IEVNT_RX_EMPTY | ++ MEMAC_IEVNT_TX_EMPTY | ++ MEMAC_IEVNT_RX_LOWP | ++ MEMAC_IEVNT_PHY_LOS); ++ ++ memac_ack_event(regs, event); ++ ++ if (event & MEMAC_IEVNT_RX_FIFO_OVFL) ++ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_RX_FIFO_OVFL); ++ if (event & MEMAC_IEVNT_TX_FIFO_UNFL) ++ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_TX_FIFO_UNFL); ++ if (event & MEMAC_IEVNT_TX_FIFO_OVFL) ++ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_TX_FIFO_OVFL); ++ if (event & MEMAC_IEVNT_TX_ECC_ER) ++ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_1TX_ECC_ER); ++ if (event & MEMAC_IEVNT_RX_ECC_ER) ++ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_RX_ECC_ER); ++ if (event & MEMAC_IEVNT_REM_FAULT) ++ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_REM_FAULT); ++ if (event & MEMAC_IEVNT_LOC_FAULT) ++ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_LOC_FAULT); ++} ++ ++ ++/* ......................................................................... */ ++ ++static void FreeInitResources(t_Memac *p_Memac) ++{ ++ e_FmMacType portType; ++ ++ portType = ++ ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G); ++ ++ if (portType == e_FM_MAC_10G) ++ FmUnregisterIntr(p_Memac->fmMacControllerDriver.h_Fm, e_FM_MOD_10G_MAC, p_Memac->macId, e_FM_INTR_TYPE_ERR); ++ else ++ FmUnregisterIntr(p_Memac->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Memac->macId, e_FM_INTR_TYPE_ERR); ++ ++ /* release the driver's group hash table */ ++ FreeHashTable(p_Memac->p_MulticastAddrHash); ++ p_Memac->p_MulticastAddrHash = NULL; ++ ++ /* release the driver's individual hash table */ ++ FreeHashTable(p_Memac->p_UnicastAddrHash); ++ p_Memac->p_UnicastAddrHash = NULL; ++} ++ ++ ++/*****************************************************************************/ ++/* mEMAC API routines */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error MemacEnable(t_Handle h_Memac, e_CommMode mode) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ memac_enable(p_Memac->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacDisable (t_Handle h_Memac, e_CommMode mode) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ memac_disable(p_Memac->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacSetPromiscuous(t_Handle h_Memac, bool newVal) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ memac_set_promiscuous(p_Memac->p_MemMap, newVal); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error MemacAdjustLink(t_Handle h_Memac, e_EnetSpeed speed, bool fullDuplex) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++UNUSED(p_Memac); ++DBG(WARNING, ("mEMAC works in automatic-mode; therefore, adjust-link is not needed!")); ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Memac Configs modification functions */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigLoopback(t_Handle h_Memac, bool newVal) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ p_Memac->p_MemacDriverParam->loopback_enable = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigWan(t_Handle h_Memac, bool newVal) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ p_Memac->p_MemacDriverParam->wan_mode_enable = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigMaxFrameLength(t_Handle h_Memac, uint16_t newVal) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ p_Memac->p_MemacDriverParam->max_frame_length = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigPad(t_Handle h_Memac, bool newVal) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ p_Memac->p_MemacDriverParam->pad_enable = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigLengthCheck(t_Handle h_Memac, bool newVal) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ p_Memac->p_MemacDriverParam->no_length_check_enable = !newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigException(t_Handle h_Memac, e_FmMacExceptions exception, bool enable) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Memac->exceptions |= bitMask; ++ else ++ p_Memac->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigResetOnInit(t_Handle h_Memac, bool enable) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ p_Memac->p_MemacDriverParam->reset_on_init = enable; ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Memac Run Time API functions */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error MemacSetTxPauseFrames(t_Handle h_Memac, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ memac_set_tx_pause_frames(p_Memac->p_MemMap, priority, pauseTime, threshTime); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacSetTxAutoPauseFrames(t_Handle h_Memac, ++ uint16_t pauseTime) ++{ ++ return MemacSetTxPauseFrames(h_Memac, FM_MAC_NO_PFC, pauseTime, 0); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacSetRxIgnorePauseFrames(t_Handle h_Memac, bool en) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ memac_set_rx_ignore_pause_frames(p_Memac->p_MemMap, en); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error MemacEnable1588TimeStamp(t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++UNUSED(p_Memac); ++DBG(WARNING, ("mEMAC has 1588 always enabled!")); ++ ++ return E_OK; ++} ++ ++/* Counters handling */ ++/* ......................................................................... */ ++ ++static t_Error MemacGetStatistics(t_Handle h_Memac, t_FmMacStatistics *p_Statistics) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER); ++ ++ p_Statistics->eStatPkts64 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R64); ++ p_Statistics->eStatPkts65to127 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R127); ++ p_Statistics->eStatPkts128to255 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R255); ++ p_Statistics->eStatPkts256to511 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R511); ++ p_Statistics->eStatPkts512to1023 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1023); ++ p_Statistics->eStatPkts1024to1518 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1518); ++ p_Statistics->eStatPkts1519to1522 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1519X); ++/* */ ++ p_Statistics->eStatFragments = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RFRG); ++ p_Statistics->eStatJabbers = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RJBR); ++ ++ p_Statistics->eStatsDropEvents = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RDRP); ++ p_Statistics->eStatCRCAlignErrors = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RALN); ++ ++ p_Statistics->eStatUndersizePkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TUND); ++ p_Statistics->eStatOversizePkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_ROVR); ++/* Pause */ ++ p_Statistics->reStatPause = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RXPF); ++ p_Statistics->teStatPause = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TXPF); ++ ++/* MIB II */ ++ p_Statistics->ifInOctets = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_ROCT); ++ p_Statistics->ifInUcastPkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RUCA); ++ p_Statistics->ifInMcastPkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RMCA); ++ p_Statistics->ifInBcastPkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RBCA); ++ p_Statistics->ifInPkts = p_Statistics->ifInUcastPkts ++ + p_Statistics->ifInMcastPkts ++ + p_Statistics->ifInBcastPkts; ++ p_Statistics->ifInDiscards = 0; ++ p_Statistics->ifInErrors = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RERR); ++ ++ p_Statistics->ifOutOctets = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TOCT); ++ p_Statistics->ifOutUcastPkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TUCA); ++ p_Statistics->ifOutMcastPkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TMCA); ++ p_Statistics->ifOutBcastPkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TBCA); ++ p_Statistics->ifOutPkts = p_Statistics->ifOutUcastPkts ++ + p_Statistics->ifOutMcastPkts ++ + p_Statistics->ifOutBcastPkts; ++ p_Statistics->ifOutDiscards = 0; ++ p_Statistics->ifOutErrors = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TERR); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacModifyMacAddress (t_Handle h_Memac, t_EnetAddr *p_EnetAddr) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ memac_hardware_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t *)(*p_EnetAddr), 0); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacResetCounters (t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ memac_reset_counter(p_Memac->p_MemMap); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacAddExactMatchMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr) ++{ ++ t_Memac *p_Memac = (t_Memac *) h_Memac; ++ uint64_t ethAddr; ++ uint8_t paddrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ if (ethAddr & GROUP_ADDRESS) ++ /* Multicast address has no effect in PADDR */ ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address")); ++ ++ /* Make sure no PADDR contains this address */ ++ for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++) ++ if (p_Memac->indAddrRegUsed[paddrNum]) ++ if (p_Memac->paddr[paddrNum] == ethAddr) ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG); ++ ++ /* Find first unused PADDR */ ++ for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++) ++ if (!(p_Memac->indAddrRegUsed[paddrNum])) ++ { ++ /* mark this PADDR as used */ ++ p_Memac->indAddrRegUsed[paddrNum] = TRUE; ++ /* store address */ ++ p_Memac->paddr[paddrNum] = ethAddr; ++ ++ /* put in hardware */ ++ memac_hardware_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t*)(*p_EthAddr), paddrNum); ++ p_Memac->numOfIndAddrInRegs++; ++ ++ return E_OK; ++ } ++ ++ /* No free PADDR */ ++ RETURN_ERROR(MAJOR, E_FULL, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacDelExactMatchMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr) ++{ ++ t_Memac *p_Memac = (t_Memac *) h_Memac; ++ uint64_t ethAddr; ++ uint8_t paddrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ /* Find used PADDR containing this address */ ++ for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++) ++ { ++ if ((p_Memac->indAddrRegUsed[paddrNum]) && ++ (p_Memac->paddr[paddrNum] == ethAddr)) ++ { ++ /* mark this PADDR as not used */ ++ p_Memac->indAddrRegUsed[paddrNum] = FALSE; ++ /* clear in hardware */ ++ memac_hardware_clear_addr_in_paddr(p_Memac->p_MemMap, paddrNum); ++ p_Memac->numOfIndAddrInRegs--; ++ ++ return E_OK; ++ } ++ } ++ ++ RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacAddHashMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ t_EthHashEntry *p_HashEntry; ++ uint32_t hash; ++ uint64_t ethAddr; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ if (!(ethAddr & GROUP_ADDRESS)) ++ /* Unicast addresses not supported in hash */ ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unicast Address")); ++ ++ hash = GetMacAddrHashCode(ethAddr) & HASH_CTRL_ADDR_MASK; ++ ++ /* Create element to be added to the driver hash table */ ++ p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry)); ++ p_HashEntry->addr = ethAddr; ++ INIT_LIST(&p_HashEntry->node); ++ ++ LIST_AddToTail(&(p_HashEntry->node), &(p_Memac->p_MulticastAddrHash->p_Lsts[hash])); ++ memac_set_hash_table(p_Memac->p_MemMap, (hash | HASH_CTRL_MCAST_EN)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacDelHashMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ t_EthHashEntry *p_HashEntry = NULL; ++ t_List *p_Pos; ++ uint32_t hash; ++ uint64_t ethAddr; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ hash = GetMacAddrHashCode(ethAddr) & HASH_CTRL_ADDR_MASK; ++ ++ LIST_FOR_EACH(p_Pos, &(p_Memac->p_MulticastAddrHash->p_Lsts[hash])) ++ { ++ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos); ++ if (p_HashEntry->addr == ethAddr) ++ { ++ LIST_DelAndInit(&p_HashEntry->node); ++ XX_Free(p_HashEntry); ++ break; ++ } ++ } ++ if (LIST_IsEmpty(&p_Memac->p_MulticastAddrHash->p_Lsts[hash])) ++ memac_set_hash_table(p_Memac->p_MemMap, (hash & ~HASH_CTRL_MCAST_EN)); ++ ++ return E_OK; ++} ++ ++ ++/* ......................................................................... */ ++ ++static t_Error MemacSetException(t_Handle h_Memac, e_FmMacExceptions exception, bool enable) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Memac->exceptions |= bitMask; ++ else ++ p_Memac->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ memac_set_exception(p_Memac->p_MemMap, bitMask, enable); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static uint16_t MemacGetMaxFrameLength(t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Memac, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_Memac->p_MemacDriverParam, E_INVALID_STATE, 0); ++ ++ return memac_get_max_frame_length(p_Memac->p_MemMap); ++} ++ ++/* ......................................................................... */ ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++static t_Error MemacDumpRegs(t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ int i = 0; ++ ++ DECLARE_DUMP; ++ ++ if (p_Memac->p_MemMap) ++ { ++ DUMP_TITLE(p_Memac->p_MemMap, ("mEMAC %d: ", p_Memac->macId)); ++ DUMP_VAR(p_Memac->p_MemMap, command_config); ++ DUMP_VAR(p_Memac->p_MemMap, mac_addr0.mac_addr_l); ++ DUMP_VAR(p_Memac->p_MemMap, mac_addr0.mac_addr_u); ++ DUMP_VAR(p_Memac->p_MemMap, maxfrm); ++ DUMP_VAR(p_Memac->p_MemMap, hashtable_ctrl); ++ DUMP_VAR(p_Memac->p_MemMap, ievent); ++ DUMP_VAR(p_Memac->p_MemMap, tx_ipg_length); ++ DUMP_VAR(p_Memac->p_MemMap, imask); ++ ++ DUMP_SUBSTRUCT_ARRAY(i, 4) ++ { ++ DUMP_VAR(p_Memac->p_MemMap, pause_quanta[i]); ++ } ++ DUMP_SUBSTRUCT_ARRAY(i, 4) ++ { ++ DUMP_VAR(p_Memac->p_MemMap, pause_thresh[i]); ++ } ++ ++ DUMP_VAR(p_Memac->p_MemMap, rx_pause_status); ++ ++ DUMP_SUBSTRUCT_ARRAY(i, MEMAC_NUM_OF_PADDRS) ++ { ++ DUMP_VAR(p_Memac->p_MemMap, mac_addr[i].mac_addr_l); ++ DUMP_VAR(p_Memac->p_MemMap, mac_addr[i].mac_addr_u); ++ } ++ ++ DUMP_VAR(p_Memac->p_MemMap, lpwake_timer); ++ DUMP_VAR(p_Memac->p_MemMap, sleep_timer); ++ DUMP_VAR(p_Memac->p_MemMap, statn_config); ++ DUMP_VAR(p_Memac->p_MemMap, if_mode); ++ DUMP_VAR(p_Memac->p_MemMap, if_status); ++ DUMP_VAR(p_Memac->p_MemMap, hg_config); ++ DUMP_VAR(p_Memac->p_MemMap, hg_pause_quanta); ++ DUMP_VAR(p_Memac->p_MemMap, hg_pause_thresh); ++ DUMP_VAR(p_Memac->p_MemMap, hgrx_pause_status); ++ DUMP_VAR(p_Memac->p_MemMap, hg_fifos_status); ++ DUMP_VAR(p_Memac->p_MemMap, rhm); ++ DUMP_VAR(p_Memac->p_MemMap, thm); ++ } ++ ++ return E_OK; ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ ++/*****************************************************************************/ ++/* mEMAC Init & Free API */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error MemacInit(t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ struct memac_cfg *p_MemacDriverParam; ++ enum enet_interface enet_interface; ++ enum enet_speed enet_speed; ++ uint8_t i, phyAddr; ++ t_EnetAddr ethAddr; ++ e_FmMacType portType; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE); ++ ++ /* not needed! */ ++ /*FM_GetRevision(p_Memac->fmMacControllerDriver.h_Fm, &p_Memac->fmMacControllerDriver.fmRevInfo);*/ ++ ++ CHECK_INIT_PARAMETERS(p_Memac, CheckInitParameters); ++ ++ p_MemacDriverParam = p_Memac->p_MemacDriverParam; ++ ++ portType = ++ ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G); ++ ++ /* First, reset the MAC if desired. */ ++ if (p_MemacDriverParam->reset_on_init) ++ memac_reset(p_Memac->p_MemMap); ++ ++ /* MAC Address */ ++ MAKE_ENET_ADDR_FROM_UINT64(p_Memac->addr, ethAddr); ++ memac_hardware_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t*)ethAddr, 0); ++ ++ enet_interface = (enum enet_interface) ENET_INTERFACE_FROM_MODE(p_Memac->enetMode); ++ enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Memac->enetMode); ++ ++ memac_init(p_Memac->p_MemMap, ++ p_Memac->p_MemacDriverParam, ++ enet_interface, ++ enet_speed, ++ p_Memac->exceptions); ++ ++ if (ENET_INTERFACE_FROM_MODE(p_Memac->enetMode) == e_ENET_IF_SGMII) ++ { ++ /* Configure internal SGMII PHY */ ++ if (p_Memac->enetMode & ENET_IF_SGMII_BASEX) ++ SetupSgmiiInternalPhyBaseX(p_Memac, PHY_MDIO_ADDR); ++ else ++ SetupSgmiiInternalPhy(p_Memac, PHY_MDIO_ADDR); ++ } ++ else if (ENET_INTERFACE_FROM_MODE(p_Memac->enetMode) == e_ENET_IF_QSGMII) ++ { ++ /* Configure 4 internal SGMII PHYs */ ++ for (i = 0; i < 4; i++) ++ { ++ /* QSGMII PHY address occupies 3 upper bits of 5-bit ++ phyAddress; the lower 2 bits are used to extend ++ register address space and access each one of 4 ++ ports inside QSGMII. */ ++ phyAddr = (uint8_t)((PHY_MDIO_ADDR << 2) | i); ++ if (p_Memac->enetMode & ENET_IF_SGMII_BASEX) ++ SetupSgmiiInternalPhyBaseX(p_Memac, phyAddr); ++ else ++ SetupSgmiiInternalPhy(p_Memac, phyAddr); ++ } ++ } ++ ++ /* Max Frame Length */ ++ err = FmSetMacMaxFrame(p_Memac->fmMacControllerDriver.h_Fm, ++ portType, ++ p_Memac->fmMacControllerDriver.macId, ++ p_MemacDriverParam->max_frame_length); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("settings Mac max frame length is FAILED")); ++ ++ p_Memac->p_MulticastAddrHash = AllocHashTable(HASH_TABLE_SIZE); ++ if (!p_Memac->p_MulticastAddrHash) ++ { ++ FreeInitResources(p_Memac); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED")); ++ } ++ ++ p_Memac->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE); ++ if (!p_Memac->p_UnicastAddrHash) ++ { ++ FreeInitResources(p_Memac); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED")); ++ } ++ ++ FmRegisterIntr(p_Memac->fmMacControllerDriver.h_Fm, ++ (portType == e_FM_MAC_10G) ? e_FM_MOD_10G_MAC : e_FM_MOD_1G_MAC, ++ p_Memac->macId, ++ e_FM_INTR_TYPE_ERR, ++ MemacErrException, ++ p_Memac); ++ ++ ++ XX_Free(p_MemacDriverParam); ++ p_Memac->p_MemacDriverParam = NULL; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacFree(t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ ++ FreeInitResources(p_Memac); ++ ++ if (p_Memac->p_MemacDriverParam) ++ { ++ XX_Free(p_Memac->p_MemacDriverParam); ++ p_Memac->p_MemacDriverParam = NULL; ++ } ++ XX_Free(p_Memac); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver) ++{ ++ p_FmMacControllerDriver->f_FM_MAC_Init = MemacInit; ++ p_FmMacControllerDriver->f_FM_MAC_Free = MemacFree; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetStatistics = NULL; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = MemacConfigLoopback; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = MemacConfigMaxFrameLength; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigWan = MemacConfigWan; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = MemacConfigPad; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = NULL; /* half-duplex is detected automatically */ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = MemacConfigLengthCheck; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigException = MemacConfigException; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = MemacConfigResetOnInit; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetException = MemacSetException; ++ ++ p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = MemacEnable1588TimeStamp; /* always enabled */ ++ p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = NULL; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = MemacSetPromiscuous; ++ p_FmMacControllerDriver->f_FM_MAC_AdjustLink = MemacAdjustLink; ++ p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = NULL; ++ ++ p_FmMacControllerDriver->f_FM_MAC_Enable = MemacEnable; ++ p_FmMacControllerDriver->f_FM_MAC_Disable = MemacDisable; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = MemacSetTxAutoPauseFrames; ++ p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = MemacSetTxPauseFrames; ++ p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = MemacSetRxIgnorePauseFrames; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ResetCounters = MemacResetCounters; ++ p_FmMacControllerDriver->f_FM_MAC_GetStatistics = MemacGetStatistics; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = MemacModifyMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = MemacAddHashMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = MemacDelHashMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = MemacAddExactMatchMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = MemacDelExactMatchMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_GetId = NULL; ++ p_FmMacControllerDriver->f_FM_MAC_GetVersion = NULL; ++ p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = MemacGetMaxFrameLength; ++ ++ p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = MEMAC_MII_WritePhyReg; ++ p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = MEMAC_MII_ReadPhyReg; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ p_FmMacControllerDriver->f_FM_MAC_DumpRegs = MemacDumpRegs; ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++} ++ ++ ++/*****************************************************************************/ ++/* mEMAC Config Main Entry */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++t_Handle MEMAC_Config(t_FmMacParams *p_FmMacParam) ++{ ++ t_Memac *p_Memac; ++ struct memac_cfg *p_MemacDriverParam; ++ uintptr_t baseAddr; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL); ++ ++ baseAddr = p_FmMacParam->baseAddr; ++ /* Allocate memory for the mEMAC data structure */ ++ p_Memac = (t_Memac *)XX_Malloc(sizeof(t_Memac)); ++ if (!p_Memac) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("mEMAC driver structure")); ++ return NULL; ++ } ++ memset(p_Memac, 0, sizeof(t_Memac)); ++ InitFmMacControllerDriver(&p_Memac->fmMacControllerDriver); ++ ++ /* Allocate memory for the mEMAC driver parameters data structure */ ++ p_MemacDriverParam = (struct memac_cfg *) XX_Malloc(sizeof(struct memac_cfg)); ++ if (!p_MemacDriverParam) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("mEMAC driver parameters")); ++ MemacFree(p_Memac); ++ return NULL; ++ } ++ memset(p_MemacDriverParam, 0, sizeof(struct memac_cfg)); ++ ++ /* Plant parameter structure pointer */ ++ p_Memac->p_MemacDriverParam = p_MemacDriverParam; ++ ++ memac_defconfig(p_MemacDriverParam); ++ ++ p_Memac->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr); ++ ++ p_Memac->p_MemMap = (struct memac_regs *)UINT_TO_PTR(baseAddr); ++ p_Memac->p_MiiMemMap = (t_MemacMiiAccessMemMap *)UINT_TO_PTR(baseAddr + MEMAC_TO_MII_OFFSET); ++ ++ p_Memac->enetMode = p_FmMacParam->enetMode; ++ p_Memac->macId = p_FmMacParam->macId; ++ p_Memac->exceptions = MEMAC_default_exceptions; ++ p_Memac->f_Exception = p_FmMacParam->f_Exception; ++ p_Memac->f_Event = p_FmMacParam->f_Event; ++ p_Memac->h_App = p_FmMacParam->h_App; ++ ++ return p_Memac; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/memac.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/memac.h +new file mode 100644 +index 0000000..e1c4c53 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/memac.h +@@ -0,0 +1,104 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 memac.h ++ ++ @Description FM Multirate Ethernet MAC (mEMAC) ++*//***************************************************************************/ ++#ifndef __MEMAC_H ++#define __MEMAC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++ ++#include "memac_mii_acc.h" ++#include "fm_mac.h" ++#include "fsl_fman_memac.h" ++ ++ ++#define MEMAC_default_exceptions ((uint32_t)(MEMAC_IMASK_TECC_ER | MEMAC_IMASK_RECC_ER)) ++ ++#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \ ++ case e_FM_MAC_EX_10G_1TX_ECC_ER: \ ++ bitMask = MEMAC_IMASK_TECC_ER; break; \ ++ case e_FM_MAC_EX_10G_RX_ECC_ER: \ ++ bitMask = MEMAC_IMASK_RECC_ER; break; \ ++ default: bitMask = 0;break;} ++ ++ ++typedef struct ++{ ++ t_FmMacControllerDriver fmMacControllerDriver; /**< Upper Mac control block */ ++ t_Handle h_App; /**< Handle to the upper layer application */ ++ struct memac_regs *p_MemMap; /**< Pointer to MAC memory mapped registers */ ++ t_MemacMiiAccessMemMap *p_MiiMemMap; /**< Pointer to MII memory mapped registers */ ++ uint64_t addr; /**< MAC address of device */ ++ e_EnetMode enetMode; /**< Ethernet physical interface */ ++ t_FmMacExceptionCallback *f_Exception; ++ int mdioIrq; ++ t_FmMacExceptionCallback *f_Event; ++ bool indAddrRegUsed[MEMAC_NUM_OF_PADDRS]; /**< Whether a particular individual address recognition register is being used */ ++ uint64_t paddr[MEMAC_NUM_OF_PADDRS]; /**< MAC address for particular individual address recognition register */ ++ uint8_t numOfIndAddrInRegs; /**< Number of individual addresses in registers for this station. */ ++ t_EthHash *p_MulticastAddrHash; /**< Pointer to driver's global address hash table */ ++ t_EthHash *p_UnicastAddrHash; /**< Pointer to driver's individual address hash table */ ++ bool debugMode; ++ uint8_t macId; ++ uint32_t exceptions; ++ struct memac_cfg *p_MemacDriverParam; ++} t_Memac; ++ ++ ++/* Internal PHY access */ ++#define PHY_MDIO_ADDR 0 ++ ++/* Internal PHY Registers - SGMII */ ++#define PHY_SGMII_CR_PHY_RESET 0x8000 ++#define PHY_SGMII_CR_RESET_AN 0x0200 ++#define PHY_SGMII_CR_DEF_VAL 0x1140 ++#define PHY_SGMII_DEV_ABILITY_SGMII 0x4001 ++#define PHY_SGMII_DEV_ABILITY_1000X 0x01A0 ++#define PHY_SGMII_IF_MODE_AN 0x0002 ++#define PHY_SGMII_IF_MODE_SGMII 0x0001 ++#define PHY_SGMII_IF_MODE_1000X 0x0000 ++ ++ ++#define MEMAC_TO_MII_OFFSET 0x030 /* Offset from the MEM map to the MDIO mem map */ ++ ++t_Error MEMAC_MII_WritePhyReg(t_Handle h_Memac, uint8_t phyAddr, uint8_t reg, uint16_t data); ++t_Error MEMAC_MII_ReadPhyReg(t_Handle h_Memac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data); ++ ++ ++#endif /* __MEMAC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/memac_mii_acc.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/memac_mii_acc.c +new file mode 100644 +index 0000000..be5b867 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/memac_mii_acc.c +@@ -0,0 +1,240 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "error_ext.h" ++#include "std_ext.h" ++#include "fm_mac.h" ++#include "memac.h" ++#include "xx_ext.h" ++ ++#include "fm_common.h" ++ ++ ++static void WritePhyReg10G(t_MemacMiiAccessMemMap *p_MiiAccess, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t data) ++{ ++ uint32_t tmpReg; ++ ++ tmpReg = GET_UINT32(p_MiiAccess->mdio_cfg); ++ /* Leave only MDIO_CLK_DIV bits set on */ ++ tmpReg &= MDIO_CFG_CLK_DIV_MASK; ++ /* Set maximum MDIO_HOLD value to allow phy to see ++ change of data signal */ ++ tmpReg |= MDIO_CFG_HOLD_MASK; ++ /* Add 10G interface mode */ ++ tmpReg |= MDIO_CFG_ENC45; ++ WRITE_UINT32(p_MiiAccess->mdio_cfg, tmpReg); ++ ++ /* Wait for command completion */ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY) ++ XX_UDelay(1); ++ ++ /* Specify phy and register to be accessed */ ++ WRITE_UINT32(p_MiiAccess->mdio_ctrl, phyAddr); ++ WRITE_UINT32(p_MiiAccess->mdio_addr, reg); ++ CORE_MemoryBarrier(); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY) ++ XX_UDelay(1); ++ ++ /* Write data */ ++ WRITE_UINT32(p_MiiAccess->mdio_data, data); ++ CORE_MemoryBarrier(); ++ ++ /* Wait for write transaction end */ ++ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MDIO_DATA_BSY) ++ XX_UDelay(1); ++} ++ ++static uint32_t ReadPhyReg10G(t_MemacMiiAccessMemMap *p_MiiAccess, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t *p_Data) ++{ ++ uint32_t tmpReg; ++ ++ tmpReg = GET_UINT32(p_MiiAccess->mdio_cfg); ++ /* Leave only MDIO_CLK_DIV bits set on */ ++ tmpReg &= MDIO_CFG_CLK_DIV_MASK; ++ /* Set maximum MDIO_HOLD value to allow phy to see ++ change of data signal */ ++ tmpReg |= MDIO_CFG_HOLD_MASK; ++ /* Add 10G interface mode */ ++ tmpReg |= MDIO_CFG_ENC45; ++ WRITE_UINT32(p_MiiAccess->mdio_cfg, tmpReg); ++ ++ /* Wait for command completion */ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY) ++ XX_UDelay(1); ++ ++ /* Specify phy and register to be accessed */ ++ WRITE_UINT32(p_MiiAccess->mdio_ctrl, phyAddr); ++ WRITE_UINT32(p_MiiAccess->mdio_addr, reg); ++ CORE_MemoryBarrier(); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY) ++ XX_UDelay(1); ++ ++ /* Read cycle */ ++ tmpReg = phyAddr; ++ tmpReg |= MDIO_CTL_READ; ++ WRITE_UINT32(p_MiiAccess->mdio_ctrl, tmpReg); ++ CORE_MemoryBarrier(); ++ ++ /* Wait for data to be available */ ++ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MDIO_DATA_BSY) ++ XX_UDelay(1); ++ ++ *p_Data = (uint16_t)GET_UINT32(p_MiiAccess->mdio_data); ++ ++ /* Check if there was an error */ ++ return GET_UINT32(p_MiiAccess->mdio_cfg); ++} ++ ++static void WritePhyReg1G(t_MemacMiiAccessMemMap *p_MiiAccess, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t data) ++{ ++ uint32_t tmpReg; ++ ++ /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */ ++ tmpReg = GET_UINT32(p_MiiAccess->mdio_cfg); ++ tmpReg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK); ++ WRITE_UINT32(p_MiiAccess->mdio_cfg, tmpReg); ++ ++ /* Wait for command completion */ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY) ++ XX_UDelay(1); ++ ++ /* Write transaction */ ++ tmpReg = (phyAddr << MDIO_CTL_PHY_ADDR_SHIFT); ++ tmpReg |= reg; ++ WRITE_UINT32(p_MiiAccess->mdio_ctrl, tmpReg); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY) ++ XX_UDelay(1); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_data, data); ++ ++ CORE_MemoryBarrier(); ++ ++ /* Wait for write transaction to end */ ++ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MDIO_DATA_BSY) ++ XX_UDelay(1); ++} ++ ++static uint32_t ReadPhyReg1G(t_MemacMiiAccessMemMap *p_MiiAccess, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t *p_Data) ++{ ++ uint32_t tmpReg; ++ ++ /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */ ++ tmpReg = GET_UINT32(p_MiiAccess->mdio_cfg); ++ tmpReg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK); ++ WRITE_UINT32(p_MiiAccess->mdio_cfg, tmpReg); ++ ++ /* Wait for command completion */ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY) ++ XX_UDelay(1); ++ ++ /* Read transaction */ ++ tmpReg = (phyAddr << MDIO_CTL_PHY_ADDR_SHIFT); ++ tmpReg |= reg; ++ tmpReg |= MDIO_CTL_READ; ++ WRITE_UINT32(p_MiiAccess->mdio_ctrl, tmpReg); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY) ++ XX_UDelay(1); ++ ++ /* Wait for data to be available */ ++ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MDIO_DATA_BSY) ++ XX_UDelay(1); ++ ++ *p_Data = (uint16_t)GET_UINT32(p_MiiAccess->mdio_data); ++ ++ /* Check error */ ++ return GET_UINT32(p_MiiAccess->mdio_cfg); ++} ++ ++/*****************************************************************************/ ++t_Error MEMAC_MII_WritePhyReg(t_Handle h_Memac, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t data) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ /* Figure out interface type - 10G vs 1G. ++ In 10G interface both phyAddr and devAddr present. */ ++ if (ENET_SPEED_FROM_MODE(p_Memac->enetMode) == e_ENET_SPEED_10000) ++ WritePhyReg10G(p_Memac->p_MiiMemMap, phyAddr, reg, data); ++ else ++ WritePhyReg1G(p_Memac->p_MiiMemMap, phyAddr, reg, data); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error MEMAC_MII_ReadPhyReg(t_Handle h_Memac, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t *p_Data) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ uint32_t ans; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ /* Figure out interface type - 10G vs 1G. ++ In 10G interface both phyAddr and devAddr present. */ ++ if (ENET_SPEED_FROM_MODE(p_Memac->enetMode) == e_ENET_SPEED_10000) ++ ans = ReadPhyReg10G(p_Memac->p_MiiMemMap, phyAddr, reg, p_Data); ++ else ++ ans = ReadPhyReg1G(p_Memac->p_MiiMemMap, phyAddr, reg, p_Data); ++ ++ if (ans & MDIO_CFG_READ_ERR) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ++ ("Read Error: phyAddr 0x%x, dev 0x%x, reg 0x%x, cfgReg 0x%x", ++ ((phyAddr & 0xe0) >> 5), (phyAddr & 0x1f), reg, ans)); ++ ++ return E_OK; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/memac_mii_acc.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/memac_mii_acc.h +new file mode 100644 +index 0000000..dab4360 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/memac_mii_acc.h +@@ -0,0 +1,73 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __MEMAC_MII_ACC_H ++#define __MEMAC_MII_ACC_H ++ ++#include "std_ext.h" ++ ++ ++/* MII Management Registers */ ++#define MDIO_CFG_CLK_DIV_MASK 0x0000ff80 ++#define MDIO_CFG_CLK_DIV_SHIFT 7 ++#define MDIO_CFG_HOLD_MASK 0x0000001c ++#define MDIO_CFG_ENC45 0x00000040 ++#define MDIO_CFG_READ_ERR 0x00000002 ++#define MDIO_CFG_BSY 0x00000001 ++ ++#define MDIO_CTL_PHY_ADDR_SHIFT 5 ++#define MDIO_CTL_READ 0x00008000 ++ ++#define MDIO_DATA_BSY 0x80000000 ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/*----------------------------------------------------*/ ++/* MII Configuration Control Memory Map Registers */ ++/*----------------------------------------------------*/ ++typedef _Packed struct t_MemacMiiAccessMemMap ++{ ++ volatile uint32_t mdio_cfg; /* 0x030 */ ++ volatile uint32_t mdio_ctrl; /* 0x034 */ ++ volatile uint32_t mdio_data; /* 0x038 */ ++ volatile uint32_t mdio_addr; /* 0x03c */ ++} _PackedType t_MemacMiiAccessMemMap ; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++#endif /* __MEMAC_MII_ACC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/tgec.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/tgec.c +new file mode 100644 +index 0000000..522d64b +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/tgec.c +@@ -0,0 +1,1018 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 tgec.c ++ ++ @Description FM 10G MAC ... ++*//***************************************************************************/ ++ ++#include "std_ext.h" ++#include "string_ext.h" ++#include "error_ext.h" ++#include "xx_ext.h" ++#include "endian_ext.h" ++#include "debug_ext.h" ++#include "crc_mac_addr_ext.h" ++ ++#include "fm_common.h" ++#include "fsl_fman_tgec.h" ++#include "tgec.h" ++ ++ ++/*****************************************************************************/ ++/* Internal routines */ ++/*****************************************************************************/ ++ ++static t_Error CheckInitParameters(t_Tgec *p_Tgec) ++{ ++ if (ENET_SPEED_FROM_MODE(p_Tgec->enetMode) < e_ENET_SPEED_10000) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 10G MAC driver only support 10G speed")); ++#if (FM_MAX_NUM_OF_10G_MACS > 0) ++ if (p_Tgec->macId >= FM_MAX_NUM_OF_10G_MACS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("macId of 10G can not be greater than 0")); ++#endif /* (FM_MAX_NUM_OF_10G_MACS > 0) */ ++ ++ if (p_Tgec->addr == 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 10G MAC Must have a valid MAC Address")); ++ if (!p_Tgec->f_Exception) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("uninitialized f_Exception")); ++ if (!p_Tgec->f_Event) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("uninitialized f_Event")); ++#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002 ++ if (!p_Tgec->p_TgecDriverParam->no_length_check_enable) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!")); ++#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static uint32_t GetMacAddrHashCode(uint64_t ethAddr) ++{ ++ uint32_t crc; ++ ++ /* CRC calculation */ ++ GET_MAC_ADDR_CRC(ethAddr, crc); ++ ++ crc = GetMirror32(crc); ++ ++ return crc; ++} ++ ++/* ......................................................................... */ ++ ++static void TgecErrException(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ uint32_t event; ++ struct tgec_regs *p_TgecMemMap = p_Tgec->p_MemMap; ++ ++ /* do not handle MDIO events */ ++ event = tgec_get_event(p_TgecMemMap, ~(TGEC_IMASK_MDIO_SCAN_EVENT | TGEC_IMASK_MDIO_CMD_CMPL)); ++ event &= tgec_get_interrupt_mask(p_TgecMemMap); ++ ++ tgec_ack_event(p_TgecMemMap, event); ++ ++ if (event & TGEC_IMASK_REM_FAULT) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_REM_FAULT); ++ if (event & TGEC_IMASK_LOC_FAULT) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_LOC_FAULT); ++ if (event & TGEC_IMASK_TX_ECC_ER) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_1TX_ECC_ER); ++ if (event & TGEC_IMASK_TX_FIFO_UNFL) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_FIFO_UNFL); ++ if (event & TGEC_IMASK_TX_FIFO_OVFL) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_FIFO_OVFL); ++ if (event & TGEC_IMASK_TX_ER) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_ER); ++ if (event & TGEC_IMASK_RX_FIFO_OVFL) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_FIFO_OVFL); ++ if (event & TGEC_IMASK_RX_ECC_ER) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_ECC_ER); ++ if (event & TGEC_IMASK_RX_JAB_FRM) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_JAB_FRM); ++ if (event & TGEC_IMASK_RX_OVRSZ_FRM) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_OVRSZ_FRM); ++ if (event & TGEC_IMASK_RX_RUNT_FRM) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_RUNT_FRM); ++ if (event & TGEC_IMASK_RX_FRAG_FRM) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_FRAG_FRM); ++ if (event & TGEC_IMASK_RX_LEN_ER) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_LEN_ER); ++ if (event & TGEC_IMASK_RX_CRC_ER) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_CRC_ER); ++ if (event & TGEC_IMASK_RX_ALIGN_ER) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_ALIGN_ER); ++} ++ ++/* ......................................................................... */ ++ ++static void TgecException(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ uint32_t event; ++ struct tgec_regs *p_TgecMemMap = p_Tgec->p_MemMap; ++ ++ /* handle only MDIO events */ ++ event = tgec_get_event(p_TgecMemMap, (TGEC_IMASK_MDIO_SCAN_EVENT | TGEC_IMASK_MDIO_CMD_CMPL)); ++ event &= tgec_get_interrupt_mask(p_TgecMemMap); ++ ++ tgec_ack_event(p_TgecMemMap, event); ++ ++ if (event & TGEC_IMASK_MDIO_SCAN_EVENT) ++ p_Tgec->f_Event(p_Tgec->h_App, e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO); ++ if (event & TGEC_IMASK_MDIO_CMD_CMPL) ++ p_Tgec->f_Event(p_Tgec->h_App, e_FM_MAC_EX_10G_MDIO_CMD_CMPL); ++} ++ ++/* ......................................................................... */ ++ ++static void FreeInitResources(t_Tgec *p_Tgec) ++{ ++ if ((p_Tgec->mdioIrq != 0) && (p_Tgec->mdioIrq != NO_IRQ)) ++ { ++ XX_DisableIntr(p_Tgec->mdioIrq); ++ XX_FreeIntr(p_Tgec->mdioIrq); ++ } ++ else if (p_Tgec->mdioIrq == 0) ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ FmUnregisterIntr(p_Tgec->fmMacControllerDriver.h_Fm, e_FM_MOD_10G_MAC, p_Tgec->macId, e_FM_INTR_TYPE_ERR); ++ ++ /* release the driver's group hash table */ ++ FreeHashTable(p_Tgec->p_MulticastAddrHash); ++ p_Tgec->p_MulticastAddrHash = NULL; ++ ++ /* release the driver's individual hash table */ ++ FreeHashTable(p_Tgec->p_UnicastAddrHash); ++ p_Tgec->p_UnicastAddrHash = NULL; ++} ++ ++ ++/*****************************************************************************/ ++/* 10G MAC API routines */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error TgecEnable(t_Handle h_Tgec, e_CommMode mode) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ tgec_enable(p_Tgec->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecDisable (t_Handle h_Tgec, e_CommMode mode) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ tgec_disable(p_Tgec->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecSetPromiscuous(t_Handle h_Tgec, bool newVal) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ tgec_set_promiscuous(p_Tgec->p_MemMap, newVal); ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Tgec Configs modification functions */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error TgecConfigLoopback(t_Handle h_Tgec, bool newVal) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ p_Tgec->p_TgecDriverParam->loopback_enable = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecConfigWan(t_Handle h_Tgec, bool newVal) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ p_Tgec->p_TgecDriverParam->wan_mode_enable = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecConfigMaxFrameLength(t_Handle h_Tgec, uint16_t newVal) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ p_Tgec->p_TgecDriverParam->max_frame_length = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecConfigLengthCheck(t_Handle h_Tgec, bool newVal) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ UNUSED(newVal); ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ p_Tgec->p_TgecDriverParam->no_length_check_enable = !newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecConfigException(t_Handle h_Tgec, e_FmMacExceptions exception, bool enable) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Tgec->exceptions |= bitMask; ++ else ++ p_Tgec->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++/* ......................................................................... */ ++ ++static t_Error TgecConfigSkipFman11Workaround(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ p_Tgec->p_TgecDriverParam->skip_fman11_workaround = TRUE; ++ ++ return E_OK; ++} ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++ ++/*****************************************************************************/ ++/* Tgec Run Time API functions */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++/* backward compatibility. will be removed in the future. */ ++static t_Error TgecTxMacPause(t_Handle h_Tgec, uint16_t pauseTime) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ tgec_tx_mac_pause(p_Tgec->p_MemMap, pauseTime); ++ ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecSetTxPauseFrames(t_Handle h_Tgec, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ UNUSED(priority); UNUSED(threshTime); ++ ++ tgec_tx_mac_pause(p_Tgec->p_MemMap, pauseTime); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecRxIgnoreMacPause(t_Handle h_Tgec, bool en) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ tgec_rx_ignore_mac_pause(p_Tgec->p_MemMap, en); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecGetStatistics(t_Handle h_Tgec, t_FmMacStatistics *p_Statistics) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ struct tgec_regs *p_TgecMemMap; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER); ++ ++ p_TgecMemMap = p_Tgec->p_MemMap; ++ ++ p_Statistics->eStatPkts64 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R64); ++ p_Statistics->eStatPkts65to127 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R127); ++ p_Statistics->eStatPkts128to255 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R255); ++ p_Statistics->eStatPkts256to511 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R511); ++ p_Statistics->eStatPkts512to1023 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R1023); ++ p_Statistics->eStatPkts1024to1518 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R1518); ++ p_Statistics->eStatPkts1519to1522 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R1519X); ++/* */ ++ p_Statistics->eStatFragments = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TRFRG); ++ p_Statistics->eStatJabbers = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TRJBR); ++ ++ p_Statistics->eStatsDropEvents = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RDRP); ++ p_Statistics->eStatCRCAlignErrors = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RALN); ++ ++ p_Statistics->eStatUndersizePkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TRUND); ++ p_Statistics->eStatOversizePkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TROVR); ++/* Pause */ ++ p_Statistics->reStatPause = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RXPF); ++ p_Statistics->teStatPause = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TXPF); ++ ++/* MIB II */ ++ p_Statistics->ifInOctets = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_ROCT); ++ p_Statistics->ifInUcastPkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RUCA); ++ p_Statistics->ifInMcastPkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RMCA); ++ p_Statistics->ifInBcastPkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RBCA); ++ p_Statistics->ifInPkts = p_Statistics->ifInUcastPkts ++ + p_Statistics->ifInMcastPkts ++ + p_Statistics->ifInBcastPkts; ++ p_Statistics->ifInDiscards = 0; ++ p_Statistics->ifInErrors = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RERR); ++ ++ p_Statistics->ifOutOctets = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TOCT); ++ p_Statistics->ifOutUcastPkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TUCA); ++ p_Statistics->ifOutMcastPkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TMCA); ++ p_Statistics->ifOutBcastPkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TBCA); ++ p_Statistics->ifOutPkts = p_Statistics->ifOutUcastPkts ++ + p_Statistics->ifOutMcastPkts ++ + p_Statistics->ifOutBcastPkts; ++ p_Statistics->ifOutDiscards = 0; ++ p_Statistics->ifOutErrors = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TERR); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecEnable1588TimeStamp(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ tgec_enable_1588_time_stamp(p_Tgec->p_MemMap, 1); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecDisable1588TimeStamp(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ tgec_enable_1588_time_stamp(p_Tgec->p_MemMap, 0); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecModifyMacAddress (t_Handle h_Tgec, t_EnetAddr *p_EnetAddr) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ p_Tgec->addr = ENET_ADDR_TO_UINT64(*p_EnetAddr); ++ tgec_set_mac_address(p_Tgec->p_MemMap, (uint8_t *)(*p_EnetAddr)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecResetCounters (t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ tgec_reset_stat(p_Tgec->p_MemMap); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecAddExactMatchMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *) h_Tgec; ++ uint64_t ethAddr; ++ uint8_t paddrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ if (ethAddr & GROUP_ADDRESS) ++ /* Multicast address has no effect in PADDR */ ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address")); ++ ++ /* Make sure no PADDR contains this address */ ++ for (paddrNum = 0; paddrNum < TGEC_NUM_OF_PADDRS; paddrNum++) ++ if (p_Tgec->indAddrRegUsed[paddrNum]) ++ if (p_Tgec->paddr[paddrNum] == ethAddr) ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG); ++ ++ /* Find first unused PADDR */ ++ for (paddrNum = 0; paddrNum < TGEC_NUM_OF_PADDRS; paddrNum++) ++ { ++ if (!(p_Tgec->indAddrRegUsed[paddrNum])) ++ { ++ /* mark this PADDR as used */ ++ p_Tgec->indAddrRegUsed[paddrNum] = TRUE; ++ /* store address */ ++ p_Tgec->paddr[paddrNum] = ethAddr; ++ ++ /* put in hardware */ ++ tgec_add_addr_in_paddr(p_Tgec->p_MemMap, (uint8_t*)(*p_EthAddr)/* , paddrNum */); ++ p_Tgec->numOfIndAddrInRegs++; ++ ++ return E_OK; ++ } ++ } ++ ++ /* No free PADDR */ ++ RETURN_ERROR(MAJOR, E_FULL, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecDelExactMatchMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *) h_Tgec; ++ uint64_t ethAddr; ++ uint8_t paddrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ /* Find used PADDR containing this address */ ++ for (paddrNum = 0; paddrNum < TGEC_NUM_OF_PADDRS; paddrNum++) ++ { ++ if ((p_Tgec->indAddrRegUsed[paddrNum]) && ++ (p_Tgec->paddr[paddrNum] == ethAddr)) ++ { ++ /* mark this PADDR as not used */ ++ p_Tgec->indAddrRegUsed[paddrNum] = FALSE; ++ /* clear in hardware */ ++ tgec_clear_addr_in_paddr(p_Tgec->p_MemMap /*, paddrNum */); ++ p_Tgec->numOfIndAddrInRegs--; ++ ++ return E_OK; ++ } ++ } ++ ++ RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecAddHashMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ t_EthHashEntry *p_HashEntry; ++ uint32_t crc; ++ uint32_t hash; ++ uint64_t ethAddr; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ if (!(ethAddr & GROUP_ADDRESS)) ++ /* Unicast addresses not supported in hash */ ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unicast Address")); ++ ++ /* CRC calculation */ ++ crc = GetMacAddrHashCode(ethAddr); ++ ++ hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; /* Take 9 MSB bits */ ++ ++ /* Create element to be added to the driver hash table */ ++ p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry)); ++ p_HashEntry->addr = ethAddr; ++ INIT_LIST(&p_HashEntry->node); ++ ++ LIST_AddToTail(&(p_HashEntry->node), &(p_Tgec->p_MulticastAddrHash->p_Lsts[hash])); ++ tgec_set_hash_table(p_Tgec->p_MemMap, (hash | TGEC_HASH_MCAST_EN)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecDelHashMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ t_EthHashEntry *p_HashEntry = NULL; ++ t_List *p_Pos; ++ uint32_t crc; ++ uint32_t hash; ++ uint64_t ethAddr; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ((*(uint64_t *)p_EthAddr) >> 16); ++ ++ /* CRC calculation */ ++ crc = GetMacAddrHashCode(ethAddr); ++ ++ hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; /* Take 9 MSB bits */ ++ ++ LIST_FOR_EACH(p_Pos, &(p_Tgec->p_MulticastAddrHash->p_Lsts[hash])) ++ { ++ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos); ++ if (p_HashEntry->addr == ethAddr) ++ { ++ LIST_DelAndInit(&p_HashEntry->node); ++ XX_Free(p_HashEntry); ++ break; ++ } ++ } ++ if (LIST_IsEmpty(&p_Tgec->p_MulticastAddrHash->p_Lsts[hash])) ++ tgec_set_hash_table(p_Tgec->p_MemMap, (hash & ~TGEC_HASH_MCAST_EN)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecGetId(t_Handle h_Tgec, uint32_t *macId) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ UNUSED(p_Tgec); ++ UNUSED(macId); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("TgecGetId Not Supported")); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecGetVersion(t_Handle h_Tgec, uint32_t *macVersion) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ *macVersion = tgec_get_revision(p_Tgec->p_MemMap); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecSetExcpetion(t_Handle h_Tgec, e_FmMacExceptions exception, bool enable) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Tgec->exceptions |= bitMask; ++ else ++ p_Tgec->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ if (enable) ++ tgec_enable_interrupt(p_Tgec->p_MemMap, bitMask); ++ else ++ tgec_disable_interrupt(p_Tgec->p_MemMap, bitMask); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static uint16_t TgecGetMaxFrameLength(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Tgec, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE, 0); ++ ++ return tgec_get_max_frame_len(p_Tgec->p_MemMap); ++} ++ ++/* ......................................................................... */ ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++static t_Error TgecTxEccWorkaround(t_Tgec *p_Tgec) ++{ ++ t_Error err; ++ ++#if defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0) ++ XX_Print("Applying 10G TX ECC workaround (10GMAC-A004) ... "); ++#endif /* (DEBUG_ERRORS > 0) */ ++ /* enable and set promiscuous */ ++ tgec_enable(p_Tgec->p_MemMap, TRUE, TRUE); ++ tgec_set_promiscuous(p_Tgec->p_MemMap, TRUE); ++ err = Fm10GTxEccWorkaround(p_Tgec->fmMacControllerDriver.h_Fm, p_Tgec->macId); ++ /* disable */ ++ tgec_set_promiscuous(p_Tgec->p_MemMap, FALSE); ++ tgec_enable(p_Tgec->p_MemMap, FALSE, FALSE); ++#if defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0) ++ if (err) ++ XX_Print("FAILED!\n"); ++ else ++ XX_Print("done.\n"); ++#endif /* (DEBUG_ERRORS > 0) */ ++ tgec_reset_stat(p_Tgec->p_MemMap); ++ ++ return err; ++} ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++/* ......................................................................... */ ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++static t_Error TgecDumpRegs(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ DECLARE_DUMP; ++ ++ if (p_Tgec->p_MemMap) ++ { ++ DUMP_TITLE(p_Tgec->p_MemMap, ("10G MAC %d: ", p_Tgec->macId)); ++ DUMP_VAR(p_Tgec->p_MemMap, tgec_id); ++ DUMP_VAR(p_Tgec->p_MemMap, command_config); ++ DUMP_VAR(p_Tgec->p_MemMap, mac_addr_0); ++ DUMP_VAR(p_Tgec->p_MemMap, mac_addr_1); ++ DUMP_VAR(p_Tgec->p_MemMap, maxfrm); ++ DUMP_VAR(p_Tgec->p_MemMap, pause_quant); ++ DUMP_VAR(p_Tgec->p_MemMap, rx_fifo_sections); ++ DUMP_VAR(p_Tgec->p_MemMap, tx_fifo_sections); ++ DUMP_VAR(p_Tgec->p_MemMap, rx_fifo_almost_f_e); ++ DUMP_VAR(p_Tgec->p_MemMap, tx_fifo_almost_f_e); ++ DUMP_VAR(p_Tgec->p_MemMap, hashtable_ctrl); ++ DUMP_VAR(p_Tgec->p_MemMap, mdio_cfg_status); ++ DUMP_VAR(p_Tgec->p_MemMap, mdio_command); ++ DUMP_VAR(p_Tgec->p_MemMap, mdio_data); ++ DUMP_VAR(p_Tgec->p_MemMap, mdio_regaddr); ++ DUMP_VAR(p_Tgec->p_MemMap, status); ++ DUMP_VAR(p_Tgec->p_MemMap, tx_ipg_len); ++ DUMP_VAR(p_Tgec->p_MemMap, mac_addr_2); ++ DUMP_VAR(p_Tgec->p_MemMap, mac_addr_3); ++ DUMP_VAR(p_Tgec->p_MemMap, rx_fifo_ptr_rd); ++ DUMP_VAR(p_Tgec->p_MemMap, rx_fifo_ptr_wr); ++ DUMP_VAR(p_Tgec->p_MemMap, tx_fifo_ptr_rd); ++ DUMP_VAR(p_Tgec->p_MemMap, tx_fifo_ptr_wr); ++ DUMP_VAR(p_Tgec->p_MemMap, imask); ++ DUMP_VAR(p_Tgec->p_MemMap, ievent); ++ } ++ ++ return E_OK; ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ ++/*****************************************************************************/ ++/* FM Init & Free API */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error TgecInit(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ struct tgec_cfg *p_TgecDriverParam; ++ t_EnetAddr ethAddr; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE); ++ ++ FM_GetRevision(p_Tgec->fmMacControllerDriver.h_Fm, &p_Tgec->fmMacControllerDriver.fmRevInfo); ++ CHECK_INIT_PARAMETERS(p_Tgec, CheckInitParameters); ++ ++ p_TgecDriverParam = p_Tgec->p_TgecDriverParam; ++ ++ MAKE_ENET_ADDR_FROM_UINT64(p_Tgec->addr, ethAddr); ++ tgec_set_mac_address(p_Tgec->p_MemMap, (uint8_t *)ethAddr); ++ ++ /* interrupts */ ++#ifdef FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 ++ { ++ if (p_Tgec->fmMacControllerDriver.fmRevInfo.majorRev <=2) ++ p_Tgec->exceptions &= ~(TGEC_IMASK_REM_FAULT | TGEC_IMASK_LOC_FAULT); ++ } ++#endif /* FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 */ ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++ if (p_Tgec->fmMacControllerDriver.fmRevInfo.majorRev <= 6 /*fixed for rev3 */) ++ { ++ if (!p_Tgec->p_TgecDriverParam->skip_fman11_workaround && ++ ((err = TgecTxEccWorkaround(p_Tgec)) != E_OK)) ++ { ++ FreeInitResources(p_Tgec); ++ REPORT_ERROR(MINOR, err, ("TgecTxEccWorkaround FAILED")); ++ } ++ } ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++ err = tgec_init(p_Tgec->p_MemMap, p_TgecDriverParam, p_Tgec->exceptions); ++ if (err) ++ { ++ FreeInitResources(p_Tgec); ++ RETURN_ERROR(MAJOR, err, ("This TGEC version does not support the required i/f mode")); ++ } ++ ++ /* Max Frame Length */ ++ err = FmSetMacMaxFrame(p_Tgec->fmMacControllerDriver.h_Fm, ++ e_FM_MAC_10G, ++ p_Tgec->fmMacControllerDriver.macId, ++ p_TgecDriverParam->max_frame_length); ++ /* we consider having no IPC a non crasher... */ ++ ++#ifdef FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 ++ if (p_Tgec->fmMacControllerDriver.fmRevInfo.majorRev == 2) ++ tgec_fm_tx_fifo_corruption_errata_10gmac_a007(p_Tgec->p_MemMap); ++#endif /* FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 */ ++ ++ p_Tgec->p_MulticastAddrHash = AllocHashTable(HASH_TABLE_SIZE); ++ if (!p_Tgec->p_MulticastAddrHash) ++ { ++ FreeInitResources(p_Tgec); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED")); ++ } ++ ++ p_Tgec->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE); ++ if (!p_Tgec->p_UnicastAddrHash) ++ { ++ FreeInitResources(p_Tgec); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED")); ++ } ++ ++ FmRegisterIntr(p_Tgec->fmMacControllerDriver.h_Fm, ++ e_FM_MOD_10G_MAC, ++ p_Tgec->macId, ++ e_FM_INTR_TYPE_ERR, ++ TgecErrException, ++ p_Tgec); ++ if ((p_Tgec->mdioIrq != 0) && (p_Tgec->mdioIrq != NO_IRQ)) ++ { ++ XX_SetIntr(p_Tgec->mdioIrq, TgecException, p_Tgec); ++ XX_EnableIntr(p_Tgec->mdioIrq); ++ } ++ else if (p_Tgec->mdioIrq == 0) ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, (NO_MSG)); ++ ++ XX_Free(p_TgecDriverParam); ++ p_Tgec->p_TgecDriverParam = NULL; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecFree(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ ++ FreeInitResources(p_Tgec); ++ ++ if (p_Tgec->p_TgecDriverParam) ++ { ++ XX_Free(p_Tgec->p_TgecDriverParam); ++ p_Tgec->p_TgecDriverParam = NULL; ++ } ++ XX_Free (p_Tgec); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver) ++{ ++ p_FmMacControllerDriver->f_FM_MAC_Init = TgecInit; ++ p_FmMacControllerDriver->f_FM_MAC_Free = TgecFree; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetStatistics = NULL; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = TgecConfigLoopback; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = TgecConfigMaxFrameLength; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigWan = TgecConfigWan; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = NULL; /* TGEC always works with pad+crc */ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = NULL; /* half-duplex is not supported in xgec */ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = TgecConfigLengthCheck; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigException = TgecConfigException; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = NULL; ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++ p_FmMacControllerDriver->f_FM_MAC_ConfigSkipFman11Workaround= TgecConfigSkipFman11Workaround; ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetException = TgecSetExcpetion; ++ ++ p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = TgecEnable1588TimeStamp; ++ p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = TgecDisable1588TimeStamp; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = TgecSetPromiscuous; ++ p_FmMacControllerDriver->f_FM_MAC_AdjustLink = NULL; ++ p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = NULL; ++ ++ p_FmMacControllerDriver->f_FM_MAC_Enable = TgecEnable; ++ p_FmMacControllerDriver->f_FM_MAC_Disable = TgecDisable; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = TgecTxMacPause; ++ p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = TgecSetTxPauseFrames; ++ p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = TgecRxIgnoreMacPause; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ResetCounters = TgecResetCounters; ++ p_FmMacControllerDriver->f_FM_MAC_GetStatistics = TgecGetStatistics; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = TgecModifyMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = TgecAddHashMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = TgecDelHashMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = TgecAddExactMatchMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = TgecDelExactMatchMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_GetId = TgecGetId; ++ p_FmMacControllerDriver->f_FM_MAC_GetVersion = TgecGetVersion; ++ p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = TgecGetMaxFrameLength; ++ ++ p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = TGEC_MII_WritePhyReg; ++ p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = TGEC_MII_ReadPhyReg; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ p_FmMacControllerDriver->f_FM_MAC_DumpRegs = TgecDumpRegs; ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++} ++ ++ ++/*****************************************************************************/ ++/* Tgec Config Main Entry */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++t_Handle TGEC_Config(t_FmMacParams *p_FmMacParam) ++{ ++ t_Tgec *p_Tgec; ++ struct tgec_cfg *p_TgecDriverParam; ++ uintptr_t baseAddr; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL); ++ ++ baseAddr = p_FmMacParam->baseAddr; ++ /* allocate memory for the UCC GETH data structure. */ ++ p_Tgec = (t_Tgec *)XX_Malloc(sizeof(t_Tgec)); ++ if (!p_Tgec) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("10G MAC driver structure")); ++ return NULL; ++ } ++ memset(p_Tgec, 0, sizeof(t_Tgec)); ++ InitFmMacControllerDriver(&p_Tgec->fmMacControllerDriver); ++ ++ /* allocate memory for the 10G MAC driver parameters data structure. */ ++ p_TgecDriverParam = (struct tgec_cfg *) XX_Malloc(sizeof(struct tgec_cfg)); ++ if (!p_TgecDriverParam) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("10G MAC driver parameters")); ++ TgecFree(p_Tgec); ++ return NULL; ++ } ++ memset(p_TgecDriverParam, 0, sizeof(struct tgec_cfg)); ++ ++ /* Plant parameter structure pointer */ ++ p_Tgec->p_TgecDriverParam = p_TgecDriverParam; ++ ++ tgec_defconfig(p_TgecDriverParam); ++ ++ p_Tgec->p_MemMap = (struct tgec_regs *)UINT_TO_PTR(baseAddr); ++ p_Tgec->p_MiiMemMap = (t_TgecMiiAccessMemMap *)UINT_TO_PTR(baseAddr + TGEC_TO_MII_OFFSET); ++ p_Tgec->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr); ++ p_Tgec->enetMode = p_FmMacParam->enetMode; ++ p_Tgec->macId = p_FmMacParam->macId; ++ p_Tgec->exceptions = DEFAULT_exceptions; ++ p_Tgec->mdioIrq = p_FmMacParam->mdioIrq; ++ p_Tgec->f_Exception = p_FmMacParam->f_Exception; ++ p_Tgec->f_Event = p_FmMacParam->f_Event; ++ p_Tgec->h_App = p_FmMacParam->h_App; ++ ++ return p_Tgec; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/tgec.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/tgec.h +new file mode 100644 +index 0000000..2aa3923 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/tgec.h +@@ -0,0 +1,151 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 tgec.h ++ ++ @Description FM 10G MAC ... ++*//***************************************************************************/ ++#ifndef __TGEC_H ++#define __TGEC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++#include "enet_ext.h" ++ ++#include "tgec_mii_acc.h" ++#include "fm_mac.h" ++ ++ ++#define DEFAULT_exceptions \ ++ ((uint32_t)(TGEC_IMASK_MDIO_SCAN_EVENT | \ ++ TGEC_IMASK_REM_FAULT | \ ++ TGEC_IMASK_LOC_FAULT | \ ++ TGEC_IMASK_TX_ECC_ER | \ ++ TGEC_IMASK_TX_FIFO_UNFL | \ ++ TGEC_IMASK_TX_FIFO_OVFL | \ ++ TGEC_IMASK_TX_ER | \ ++ TGEC_IMASK_RX_FIFO_OVFL | \ ++ TGEC_IMASK_RX_ECC_ER | \ ++ TGEC_IMASK_RX_JAB_FRM | \ ++ TGEC_IMASK_RX_OVRSZ_FRM | \ ++ TGEC_IMASK_RX_RUNT_FRM | \ ++ TGEC_IMASK_RX_FRAG_FRM | \ ++ TGEC_IMASK_RX_CRC_ER | \ ++ TGEC_IMASK_RX_ALIGN_ER)) ++ ++#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \ ++ case e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO: \ ++ bitMask = TGEC_IMASK_MDIO_SCAN_EVENT ; break; \ ++ case e_FM_MAC_EX_10G_MDIO_CMD_CMPL: \ ++ bitMask = TGEC_IMASK_MDIO_CMD_CMPL ; break; \ ++ case e_FM_MAC_EX_10G_REM_FAULT: \ ++ bitMask = TGEC_IMASK_REM_FAULT ; break; \ ++ case e_FM_MAC_EX_10G_LOC_FAULT: \ ++ bitMask = TGEC_IMASK_LOC_FAULT ; break; \ ++ case e_FM_MAC_EX_10G_1TX_ECC_ER: \ ++ bitMask = TGEC_IMASK_TX_ECC_ER ; break; \ ++ case e_FM_MAC_EX_10G_TX_FIFO_UNFL: \ ++ bitMask = TGEC_IMASK_TX_FIFO_UNFL ; break; \ ++ case e_FM_MAC_EX_10G_TX_FIFO_OVFL: \ ++ bitMask = TGEC_IMASK_TX_FIFO_OVFL ; break; \ ++ case e_FM_MAC_EX_10G_TX_ER: \ ++ bitMask = TGEC_IMASK_TX_ER ; break; \ ++ case e_FM_MAC_EX_10G_RX_FIFO_OVFL: \ ++ bitMask = TGEC_IMASK_RX_FIFO_OVFL ; break; \ ++ case e_FM_MAC_EX_10G_RX_ECC_ER: \ ++ bitMask = TGEC_IMASK_RX_ECC_ER ; break; \ ++ case e_FM_MAC_EX_10G_RX_JAB_FRM: \ ++ bitMask = TGEC_IMASK_RX_JAB_FRM ; break; \ ++ case e_FM_MAC_EX_10G_RX_OVRSZ_FRM: \ ++ bitMask = TGEC_IMASK_RX_OVRSZ_FRM ; break; \ ++ case e_FM_MAC_EX_10G_RX_RUNT_FRM: \ ++ bitMask = TGEC_IMASK_RX_RUNT_FRM ; break; \ ++ case e_FM_MAC_EX_10G_RX_FRAG_FRM: \ ++ bitMask = TGEC_IMASK_RX_FRAG_FRM ; break; \ ++ case e_FM_MAC_EX_10G_RX_LEN_ER: \ ++ bitMask = TGEC_IMASK_RX_LEN_ER ; break; \ ++ case e_FM_MAC_EX_10G_RX_CRC_ER: \ ++ bitMask = TGEC_IMASK_RX_CRC_ER ; break; \ ++ case e_FM_MAC_EX_10G_RX_ALIGN_ER: \ ++ bitMask = TGEC_IMASK_RX_ALIGN_ER ; break; \ ++ default: bitMask = 0;break;} ++ ++#define MAX_PACKET_ALIGNMENT 31 ++#define MAX_INTER_PACKET_GAP 0x7f ++#define MAX_INTER_PALTERNATE_BEB 0x0f ++#define MAX_RETRANSMISSION 0x0f ++#define MAX_COLLISION_WINDOW 0x03ff ++ ++#define TGEC_NUM_OF_PADDRS 1 /* number of pattern match registers (entries) */ ++ ++#define GROUP_ADDRESS 0x0000010000000000LL /* Group address bit indication */ ++ ++#define HASH_TABLE_SIZE 512 /* Hash table size (= 32 bits * 8 regs) */ ++ ++#define TGEC_TO_MII_OFFSET 0x1030 /* Offset from the MEM map to the MDIO mem map */ ++ ++/* 10-gigabit Ethernet MAC Controller ID (10GEC_ID) */ ++#define TGEC_ID_ID 0xffff0000 ++#define TGEC_ID_MAC_VERSION 0x0000FF00 ++#define TGEC_ID_MAC_REV 0x000000ff ++ ++ ++typedef struct { ++ t_FmMacControllerDriver fmMacControllerDriver; /**< Upper Mac control block */ ++ t_Handle h_App; /**< Handle to the upper layer application */ ++ struct tgec_regs *p_MemMap; /**< pointer to 10G memory mapped registers. */ ++ t_TgecMiiAccessMemMap *p_MiiMemMap; /**< pointer to MII memory mapped registers. */ ++ uint64_t addr; /**< MAC address of device; */ ++ e_EnetMode enetMode; /**< Ethernet physical interface */ ++ t_FmMacExceptionCallback *f_Exception; ++ int mdioIrq; ++ t_FmMacExceptionCallback *f_Event; ++ bool indAddrRegUsed[TGEC_NUM_OF_PADDRS]; /**< Whether a particular individual address recognition register is being used */ ++ uint64_t paddr[TGEC_NUM_OF_PADDRS]; /**< MAC address for particular individual address recognition register */ ++ uint8_t numOfIndAddrInRegs; /**< Number of individual addresses in registers for this station. */ ++ t_EthHash *p_MulticastAddrHash; /**< pointer to driver's global address hash table */ ++ t_EthHash *p_UnicastAddrHash; /**< pointer to driver's individual address hash table */ ++ bool debugMode; ++ uint8_t macId; ++ uint32_t exceptions; ++ struct tgec_cfg *p_TgecDriverParam; ++} t_Tgec; ++ ++ ++t_Error TGEC_MII_WritePhyReg(t_Handle h_Tgec, uint8_t phyAddr, uint8_t reg, uint16_t data); ++t_Error TGEC_MII_ReadPhyReg(t_Handle h_Tgec, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data); ++ ++ ++#endif /* __TGEC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/tgec_mii_acc.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/tgec_mii_acc.c +new file mode 100644 +index 0000000..e0fafd1 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/tgec_mii_acc.c +@@ -0,0 +1,139 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "error_ext.h" ++#include "std_ext.h" ++#include "fm_mac.h" ++#include "tgec.h" ++#include "xx_ext.h" ++ ++#include "fm_common.h" ++ ++ ++/*****************************************************************************/ ++t_Error TGEC_MII_WritePhyReg(t_Handle h_Tgec, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t data) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ t_TgecMiiAccessMemMap *p_MiiAccess; ++ uint32_t cfgStatusReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ p_MiiAccess = p_Tgec->p_MiiMemMap; ++ ++ /* Configure MII */ ++ cfgStatusReg = GET_UINT32(p_MiiAccess->mdio_cfg_status); ++ cfgStatusReg &= ~MIIMCOM_DIV_MASK; ++ /* (one half of fm clock => 2.5Mhz) */ ++ cfgStatusReg |=((((p_Tgec->fmMacControllerDriver.clkFreq*10)/2)/25) << MIIMCOM_DIV_SHIFT); ++ WRITE_UINT32(p_MiiAccess->mdio_cfg_status, cfgStatusReg); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY) ++ XX_UDelay (1); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_command, phyAddr); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_regaddr, reg); ++ ++ CORE_MemoryBarrier(); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY) ++ XX_UDelay (1); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_data, data); ++ ++ CORE_MemoryBarrier(); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MIIDATA_BUSY) ++ XX_UDelay (1); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error TGEC_MII_ReadPhyReg(t_Handle h_Tgec, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t *p_Data) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ t_TgecMiiAccessMemMap *p_MiiAccess; ++ uint32_t cfgStatusReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ p_MiiAccess = p_Tgec->p_MiiMemMap; ++ ++ /* Configure MII */ ++ cfgStatusReg = GET_UINT32(p_MiiAccess->mdio_cfg_status); ++ cfgStatusReg &= ~MIIMCOM_DIV_MASK; ++ /* (one half of fm clock => 2.5Mhz) */ ++ cfgStatusReg |=((((p_Tgec->fmMacControllerDriver.clkFreq*10)/2)/25) << MIIMCOM_DIV_SHIFT); ++ WRITE_UINT32(p_MiiAccess->mdio_cfg_status, cfgStatusReg); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY) ++ XX_UDelay (1); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_command, phyAddr); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_regaddr, reg); ++ ++ CORE_MemoryBarrier(); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY) ++ XX_UDelay (1); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_command, (uint32_t)(phyAddr | MIIMCOM_READ_CYCLE)); ++ ++ CORE_MemoryBarrier(); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MIIDATA_BUSY) ++ XX_UDelay (1); ++ ++ *p_Data = (uint16_t)GET_UINT32(p_MiiAccess->mdio_data); ++ ++ cfgStatusReg = GET_UINT32(p_MiiAccess->mdio_cfg_status); ++ ++ if (cfgStatusReg & MIIMIND_READ_ERROR) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ++ ("Read Error: phyAddr 0x%x, dev 0x%x, reg 0x%x, cfgStatusReg 0x%x", ++ ((phyAddr & 0xe0)>>5), (phyAddr & 0x1f), reg, cfgStatusReg)); ++ ++ return E_OK; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/tgec_mii_acc.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/tgec_mii_acc.h +new file mode 100644 +index 0000000..645cdde +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/MAC/tgec_mii_acc.h +@@ -0,0 +1,80 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __TGEC_MII_ACC_H ++#define __TGEC_MII_ACC_H ++ ++#include "std_ext.h" ++ ++ ++/* MII Management Command Register */ ++#define MIIMCOM_READ_POST_INCREMENT 0x00004000 ++#define MIIMCOM_READ_CYCLE 0x00008000 ++#define MIIMCOM_SCAN_CYCLE 0x00000800 ++#define MIIMCOM_PREAMBLE_DISABLE 0x00000400 ++ ++#define MIIMCOM_MDIO_HOLD_1_REG_CLK 0 ++#define MIIMCOM_MDIO_HOLD_2_REG_CLK 1 ++#define MIIMCOM_MDIO_HOLD_3_REG_CLK 2 ++#define MIIMCOM_MDIO_HOLD_4_REG_CLK 3 ++ ++#define MIIMCOM_DIV_MASK 0x0000ff00 ++#define MIIMCOM_DIV_SHIFT 8 ++ ++/* MII Management Indicator Register */ ++#define MIIMIND_BUSY 0x00000001 ++#define MIIMIND_READ_ERROR 0x00000002 ++ ++#define MIIDATA_BUSY 0x80000000 ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/*----------------------------------------------------*/ ++/* MII Configuration Control Memory Map Registers */ ++/*----------------------------------------------------*/ ++typedef _Packed struct t_TgecMiiAccessMemMap ++{ ++ volatile uint32_t mdio_cfg_status; /* 0x030 */ ++ volatile uint32_t mdio_command; /* 0x034 */ ++ volatile uint32_t mdio_data; /* 0x038 */ ++ volatile uint32_t mdio_regaddr; /* 0x03c */ ++} _PackedType t_TgecMiiAccessMemMap ; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++#endif /* __TGEC_MII_ACC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Makefile b/drivers/net/dpa/NetCommSw/Peripherals/FM/Makefile +new file mode 100644 +index 0000000..67d6e21 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Makefile +@@ -0,0 +1,22 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++NCSW_FM_INC = $(srctree)/drivers/net/dpa/NetCommSw/Peripherals/FM/inc ++ ++EXTRA_CFLAGS += -I$(NCSW_FM_INC) ++ ++ ++obj-y += fsl-ncsw-PFM1.o ++ ++fsl-ncsw-PFM1-objs := fm.o fm_muram.o ++ ++obj-y += MAC/ ++obj-y += Pcd/ ++obj-y += SP/ ++obj-y += Port/ ++obj-y += HC/ ++obj-y += Rtc/ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/Makefile b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/Makefile +new file mode 100644 +index 0000000..72c921d +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/Makefile +@@ -0,0 +1,19 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/dpa/NetCommSw/Peripherals/FM/inc ++ ++EXTRA_CFLAGS += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-Pcd.o ++ ++fsl-ncsw-Pcd-objs := fman_kg.o fman_prs.o fm_cc.o fm_kg.o fm_pcd.o fm_plcr.o fm_prs.o fm_manip.o ++ ++ifeq ($(CONFIG_FMAN_T4240),y) ++fsl-ncsw-Pcd-objs += fm_replic.o ++endif +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/crc64.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/crc64.h +new file mode 100644 +index 0000000..335ee68 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/crc64.h +@@ -0,0 +1,360 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 crc64.h ++ ++ @Description brief This file contains the CRC64 Table, and __inline__ ++ functions used for calculating crc. ++*//***************************************************************************/ ++#ifndef __CRC64_H ++#define __CRC64_H ++ ++#include "std_ext.h" ++ ++ ++#define BITS_PER_BYTE 8 ++ ++#define CRC64_EXPON_ECMA_182 0xC96C5795D7870F42ULL ++#define CRC64_DEFAULT_INITVAL 0xFFFFFFFFFFFFFFFFULL ++ ++#define CRC64_BYTE_MASK 0xFF ++#define CRC64_TABLE_ENTRIES ( 1 << BITS_PER_BYTE ) ++#define CRC64_ODD_MASK 1 ++ ++ ++/** ++ \brief '64 bit crc' Table ++ */ ++struct crc64_t { ++ uint64_t initial; /**< Initial seed */ ++ uint64_t table[CRC64_TABLE_ENTRIES]; /**< CRC table entries */ ++}; ++ ++ ++static struct crc64_t CRC64_ECMA_182 = { ++ CRC64_DEFAULT_INITVAL, ++ { ++ 0x0000000000000000ULL, ++ 0xb32e4cbe03a75f6fULL, ++ 0xf4843657a840a05bULL, ++ 0x47aa7ae9abe7ff34ULL, ++ 0x7bd0c384ff8f5e33ULL, ++ 0xc8fe8f3afc28015cULL, ++ 0x8f54f5d357cffe68ULL, ++ 0x3c7ab96d5468a107ULL, ++ 0xf7a18709ff1ebc66ULL, ++ 0x448fcbb7fcb9e309ULL, ++ 0x0325b15e575e1c3dULL, ++ 0xb00bfde054f94352ULL, ++ 0x8c71448d0091e255ULL, ++ 0x3f5f08330336bd3aULL, ++ 0x78f572daa8d1420eULL, ++ 0xcbdb3e64ab761d61ULL, ++ 0x7d9ba13851336649ULL, ++ 0xceb5ed8652943926ULL, ++ 0x891f976ff973c612ULL, ++ 0x3a31dbd1fad4997dULL, ++ 0x064b62bcaebc387aULL, ++ 0xb5652e02ad1b6715ULL, ++ 0xf2cf54eb06fc9821ULL, ++ 0x41e11855055bc74eULL, ++ 0x8a3a2631ae2dda2fULL, ++ 0x39146a8fad8a8540ULL, ++ 0x7ebe1066066d7a74ULL, ++ 0xcd905cd805ca251bULL, ++ 0xf1eae5b551a2841cULL, ++ 0x42c4a90b5205db73ULL, ++ 0x056ed3e2f9e22447ULL, ++ 0xb6409f5cfa457b28ULL, ++ 0xfb374270a266cc92ULL, ++ 0x48190ecea1c193fdULL, ++ 0x0fb374270a266cc9ULL, ++ 0xbc9d3899098133a6ULL, ++ 0x80e781f45de992a1ULL, ++ 0x33c9cd4a5e4ecdceULL, ++ 0x7463b7a3f5a932faULL, ++ 0xc74dfb1df60e6d95ULL, ++ 0x0c96c5795d7870f4ULL, ++ 0xbfb889c75edf2f9bULL, ++ 0xf812f32ef538d0afULL, ++ 0x4b3cbf90f69f8fc0ULL, ++ 0x774606fda2f72ec7ULL, ++ 0xc4684a43a15071a8ULL, ++ 0x83c230aa0ab78e9cULL, ++ 0x30ec7c140910d1f3ULL, ++ 0x86ace348f355aadbULL, ++ 0x3582aff6f0f2f5b4ULL, ++ 0x7228d51f5b150a80ULL, ++ 0xc10699a158b255efULL, ++ 0xfd7c20cc0cdaf4e8ULL, ++ 0x4e526c720f7dab87ULL, ++ 0x09f8169ba49a54b3ULL, ++ 0xbad65a25a73d0bdcULL, ++ 0x710d64410c4b16bdULL, ++ 0xc22328ff0fec49d2ULL, ++ 0x85895216a40bb6e6ULL, ++ 0x36a71ea8a7ace989ULL, ++ 0x0adda7c5f3c4488eULL, ++ 0xb9f3eb7bf06317e1ULL, ++ 0xfe5991925b84e8d5ULL, ++ 0x4d77dd2c5823b7baULL, ++ 0x64b62bcaebc387a1ULL, ++ 0xd7986774e864d8ceULL, ++ 0x90321d9d438327faULL, ++ 0x231c512340247895ULL, ++ 0x1f66e84e144cd992ULL, ++ 0xac48a4f017eb86fdULL, ++ 0xebe2de19bc0c79c9ULL, ++ 0x58cc92a7bfab26a6ULL, ++ 0x9317acc314dd3bc7ULL, ++ 0x2039e07d177a64a8ULL, ++ 0x67939a94bc9d9b9cULL, ++ 0xd4bdd62abf3ac4f3ULL, ++ 0xe8c76f47eb5265f4ULL, ++ 0x5be923f9e8f53a9bULL, ++ 0x1c4359104312c5afULL, ++ 0xaf6d15ae40b59ac0ULL, ++ 0x192d8af2baf0e1e8ULL, ++ 0xaa03c64cb957be87ULL, ++ 0xeda9bca512b041b3ULL, ++ 0x5e87f01b11171edcULL, ++ 0x62fd4976457fbfdbULL, ++ 0xd1d305c846d8e0b4ULL, ++ 0x96797f21ed3f1f80ULL, ++ 0x2557339fee9840efULL, ++ 0xee8c0dfb45ee5d8eULL, ++ 0x5da24145464902e1ULL, ++ 0x1a083bacedaefdd5ULL, ++ 0xa9267712ee09a2baULL, ++ 0x955cce7fba6103bdULL, ++ 0x267282c1b9c65cd2ULL, ++ 0x61d8f8281221a3e6ULL, ++ 0xd2f6b4961186fc89ULL, ++ 0x9f8169ba49a54b33ULL, ++ 0x2caf25044a02145cULL, ++ 0x6b055fede1e5eb68ULL, ++ 0xd82b1353e242b407ULL, ++ 0xe451aa3eb62a1500ULL, ++ 0x577fe680b58d4a6fULL, ++ 0x10d59c691e6ab55bULL, ++ 0xa3fbd0d71dcdea34ULL, ++ 0x6820eeb3b6bbf755ULL, ++ 0xdb0ea20db51ca83aULL, ++ 0x9ca4d8e41efb570eULL, ++ 0x2f8a945a1d5c0861ULL, ++ 0x13f02d374934a966ULL, ++ 0xa0de61894a93f609ULL, ++ 0xe7741b60e174093dULL, ++ 0x545a57dee2d35652ULL, ++ 0xe21ac88218962d7aULL, ++ 0x5134843c1b317215ULL, ++ 0x169efed5b0d68d21ULL, ++ 0xa5b0b26bb371d24eULL, ++ 0x99ca0b06e7197349ULL, ++ 0x2ae447b8e4be2c26ULL, ++ 0x6d4e3d514f59d312ULL, ++ 0xde6071ef4cfe8c7dULL, ++ 0x15bb4f8be788911cULL, ++ 0xa6950335e42fce73ULL, ++ 0xe13f79dc4fc83147ULL, ++ 0x521135624c6f6e28ULL, ++ 0x6e6b8c0f1807cf2fULL, ++ 0xdd45c0b11ba09040ULL, ++ 0x9aefba58b0476f74ULL, ++ 0x29c1f6e6b3e0301bULL, ++ 0xc96c5795d7870f42ULL, ++ 0x7a421b2bd420502dULL, ++ 0x3de861c27fc7af19ULL, ++ 0x8ec62d7c7c60f076ULL, ++ 0xb2bc941128085171ULL, ++ 0x0192d8af2baf0e1eULL, ++ 0x4638a2468048f12aULL, ++ 0xf516eef883efae45ULL, ++ 0x3ecdd09c2899b324ULL, ++ 0x8de39c222b3eec4bULL, ++ 0xca49e6cb80d9137fULL, ++ 0x7967aa75837e4c10ULL, ++ 0x451d1318d716ed17ULL, ++ 0xf6335fa6d4b1b278ULL, ++ 0xb199254f7f564d4cULL, ++ 0x02b769f17cf11223ULL, ++ 0xb4f7f6ad86b4690bULL, ++ 0x07d9ba1385133664ULL, ++ 0x4073c0fa2ef4c950ULL, ++ 0xf35d8c442d53963fULL, ++ 0xcf273529793b3738ULL, ++ 0x7c0979977a9c6857ULL, ++ 0x3ba3037ed17b9763ULL, ++ 0x888d4fc0d2dcc80cULL, ++ 0x435671a479aad56dULL, ++ 0xf0783d1a7a0d8a02ULL, ++ 0xb7d247f3d1ea7536ULL, ++ 0x04fc0b4dd24d2a59ULL, ++ 0x3886b22086258b5eULL, ++ 0x8ba8fe9e8582d431ULL, ++ 0xcc0284772e652b05ULL, ++ 0x7f2cc8c92dc2746aULL, ++ 0x325b15e575e1c3d0ULL, ++ 0x8175595b76469cbfULL, ++ 0xc6df23b2dda1638bULL, ++ 0x75f16f0cde063ce4ULL, ++ 0x498bd6618a6e9de3ULL, ++ 0xfaa59adf89c9c28cULL, ++ 0xbd0fe036222e3db8ULL, ++ 0x0e21ac88218962d7ULL, ++ 0xc5fa92ec8aff7fb6ULL, ++ 0x76d4de52895820d9ULL, ++ 0x317ea4bb22bfdfedULL, ++ 0x8250e80521188082ULL, ++ 0xbe2a516875702185ULL, ++ 0x0d041dd676d77eeaULL, ++ 0x4aae673fdd3081deULL, ++ 0xf9802b81de97deb1ULL, ++ 0x4fc0b4dd24d2a599ULL, ++ 0xfceef8632775faf6ULL, ++ 0xbb44828a8c9205c2ULL, ++ 0x086ace348f355aadULL, ++ 0x34107759db5dfbaaULL, ++ 0x873e3be7d8faa4c5ULL, ++ 0xc094410e731d5bf1ULL, ++ 0x73ba0db070ba049eULL, ++ 0xb86133d4dbcc19ffULL, ++ 0x0b4f7f6ad86b4690ULL, ++ 0x4ce50583738cb9a4ULL, ++ 0xffcb493d702be6cbULL, ++ 0xc3b1f050244347ccULL, ++ 0x709fbcee27e418a3ULL, ++ 0x3735c6078c03e797ULL, ++ 0x841b8ab98fa4b8f8ULL, ++ 0xadda7c5f3c4488e3ULL, ++ 0x1ef430e13fe3d78cULL, ++ 0x595e4a08940428b8ULL, ++ 0xea7006b697a377d7ULL, ++ 0xd60abfdbc3cbd6d0ULL, ++ 0x6524f365c06c89bfULL, ++ 0x228e898c6b8b768bULL, ++ 0x91a0c532682c29e4ULL, ++ 0x5a7bfb56c35a3485ULL, ++ 0xe955b7e8c0fd6beaULL, ++ 0xaeffcd016b1a94deULL, ++ 0x1dd181bf68bdcbb1ULL, ++ 0x21ab38d23cd56ab6ULL, ++ 0x9285746c3f7235d9ULL, ++ 0xd52f0e859495caedULL, ++ 0x6601423b97329582ULL, ++ 0xd041dd676d77eeaaULL, ++ 0x636f91d96ed0b1c5ULL, ++ 0x24c5eb30c5374ef1ULL, ++ 0x97eba78ec690119eULL, ++ 0xab911ee392f8b099ULL, ++ 0x18bf525d915feff6ULL, ++ 0x5f1528b43ab810c2ULL, ++ 0xec3b640a391f4fadULL, ++ 0x27e05a6e926952ccULL, ++ 0x94ce16d091ce0da3ULL, ++ 0xd3646c393a29f297ULL, ++ 0x604a2087398eadf8ULL, ++ 0x5c3099ea6de60cffULL, ++ 0xef1ed5546e415390ULL, ++ 0xa8b4afbdc5a6aca4ULL, ++ 0x1b9ae303c601f3cbULL, ++ 0x56ed3e2f9e224471ULL, ++ 0xe5c372919d851b1eULL, ++ 0xa26908783662e42aULL, ++ 0x114744c635c5bb45ULL, ++ 0x2d3dfdab61ad1a42ULL, ++ 0x9e13b115620a452dULL, ++ 0xd9b9cbfcc9edba19ULL, ++ 0x6a978742ca4ae576ULL, ++ 0xa14cb926613cf817ULL, ++ 0x1262f598629ba778ULL, ++ 0x55c88f71c97c584cULL, ++ 0xe6e6c3cfcadb0723ULL, ++ 0xda9c7aa29eb3a624ULL, ++ 0x69b2361c9d14f94bULL, ++ 0x2e184cf536f3067fULL, ++ 0x9d36004b35545910ULL, ++ 0x2b769f17cf112238ULL, ++ 0x9858d3a9ccb67d57ULL, ++ 0xdff2a94067518263ULL, ++ 0x6cdce5fe64f6dd0cULL, ++ 0x50a65c93309e7c0bULL, ++ 0xe388102d33392364ULL, ++ 0xa4226ac498dedc50ULL, ++ 0x170c267a9b79833fULL, ++ 0xdcd7181e300f9e5eULL, ++ 0x6ff954a033a8c131ULL, ++ 0x28532e49984f3e05ULL, ++ 0x9b7d62f79be8616aULL, ++ 0xa707db9acf80c06dULL, ++ 0x14299724cc279f02ULL, ++ 0x5383edcd67c06036ULL, ++ 0xe0ada17364673f59ULL ++ } ++}; ++ ++ ++/** ++ \brief Initializes the crc seed ++ */ ++static __inline__ uint64_t crc64_init(void) ++{ ++ return CRC64_ECMA_182.initial; ++} ++ ++/** ++ \brief Computes 64 bit the crc ++ \param[in] data Pointer to the Data in the frame ++ \param[in] len Length of the Data ++ \param[in] crc seed ++ \return calculated crc ++ */ ++static __inline__ uint64_t crc64_compute(void const *data, ++ uint32_t len, ++ uint64_t seed) ++{ ++ uint32_t i; ++ uint64_t crc = seed; ++ uint8_t *bdata = (uint8_t *) data; ++ ++ for (i = 0; i < len; i++) ++ crc = ++ CRC64_ECMA_182. ++ table[(crc ^ *bdata++) & CRC64_BYTE_MASK] ^ (crc >> 8); ++ ++ return crc; ++} ++ ++ ++#endif /* __CRC64_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_cc.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_cc.c +new file mode 100644 +index 0000000..85810a9 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_cc.c +@@ -0,0 +1,6940 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_cc.c ++ ++ @Description FM Coarse Classifier implementation ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_muram_ext.h" ++ ++#include "fm_common.h" ++#include "fm_pcd.h" ++#include "fm_hc.h" ++#include "fm_cc.h" ++#include "crc64.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++ ++static t_Error CcRootTryLock(t_Handle h_FmPcdCcTree) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree; ++ ++ ASSERT_COND(h_FmPcdCcTree); ++ ++ if (FmPcdLockTryLock(p_FmPcdCcTree->p_Lock)) ++ return E_OK; ++ ++ return ERROR_CODE(E_BUSY); ++} ++ ++static void CcRootReleaseLock(t_Handle h_FmPcdCcTree) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree; ++ ++ ASSERT_COND(h_FmPcdCcTree); ++ ++ FmPcdLockUnlock(p_FmPcdCcTree->p_Lock); ++} ++ ++static void UpdateNodeOwner(t_FmPcdCcNode *p_CcNode, bool add) ++{ ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_CcNode); ++ ++ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); ++ ++ if (add) ++ p_CcNode->owners++; ++ else ++ { ++ ASSERT_COND(p_CcNode->owners); ++ p_CcNode->owners--; ++ } ++ ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++} ++ ++static __inline__ t_FmPcdStatsObj* DequeueStatsObj(t_List *p_List) ++{ ++ t_FmPcdStatsObj *p_StatsObj = NULL; ++ t_List *p_Next; ++ ++ if (!LIST_IsEmpty(p_List)) ++ { ++ p_Next = LIST_FIRST(p_List); ++ p_StatsObj = LIST_OBJECT(p_Next, t_FmPcdStatsObj, node); ++ ASSERT_COND(p_StatsObj); ++ LIST_DelAndInit(p_Next); ++ } ++ ++ return p_StatsObj; ++} ++ ++static __inline__ void EnqueueStatsObj(t_List *p_List, ++ t_FmPcdStatsObj *p_StatsObj) ++{ ++ LIST_AddToTail(&p_StatsObj->node, p_List); ++} ++ ++static void FreeStatObjects(t_List *p_List, ++ t_Handle h_FmMuram) ++{ ++ t_FmPcdStatsObj *p_StatsObj; ++ ++ while (!LIST_IsEmpty(p_List)) ++ { ++ p_StatsObj = DequeueStatsObj(p_List); ++ ASSERT_COND(p_StatsObj); ++ ++ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd); ++ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsCounters); ++ ++ XX_Free(p_StatsObj); ++ } ++} ++ ++static t_FmPcdStatsObj* GetStatsObj(t_FmPcdCcNode *p_CcNode) ++{ ++ t_FmPcdStatsObj* p_StatsObj; ++ t_Handle h_FmMuram; ++ ++ ASSERT_COND(p_CcNode); ++ ++ /* If 'maxNumOfKeys' was passed, all statistics object were preallocated ++ upon node initialization */ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ p_StatsObj = DequeueStatsObj(&p_CcNode->availableStatsLst); ++ } ++ else ++ { ++ h_FmMuram = ((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram; ++ ASSERT_COND(h_FmMuram); ++ ++ p_StatsObj = XX_Malloc(sizeof(t_FmPcdStatsObj)); ++ if (!p_StatsObj) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("statistics object")); ++ return NULL; ++ } ++ ++ p_StatsObj->h_StatsAd = (t_Handle)FM_MURAM_AllocMem(h_FmMuram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_StatsObj->h_StatsAd) ++ { ++ XX_Free(p_StatsObj); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics ADs")); ++ return NULL; ++ } ++ IOMemSet32(p_StatsObj->h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ p_StatsObj->h_StatsCounters = (t_Handle)FM_MURAM_AllocMem(h_FmMuram, ++ p_CcNode->countersArraySize, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_StatsObj->h_StatsCounters) ++ { ++ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd); ++ XX_Free(p_StatsObj); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics counters")); ++ return NULL; ++ } ++ IOMemSet32(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize); ++ } ++ ++ return p_StatsObj; ++} ++ ++static void PutStatsObj(t_FmPcdCcNode *p_CcNode, ++ t_FmPcdStatsObj *p_StatsObj) ++{ ++ t_Handle h_FmMuram; ++ ++ ASSERT_COND(p_CcNode); ++ ASSERT_COND(p_StatsObj); ++ ++ /* If 'maxNumOfKeys' was passed, all statistics object were preallocated ++ upon node initialization and now will be enqueued back to the list */ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ /* Nullify counters */ ++ IOMemSet32(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize); ++ ++ EnqueueStatsObj(&p_CcNode->availableStatsLst, p_StatsObj); ++ } ++ else ++ { ++ h_FmMuram = ((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram; ++ ASSERT_COND(h_FmMuram); ++ ++ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd); ++ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsCounters); ++ ++ XX_Free(p_StatsObj); ++ } ++} ++ ++static void SetStatsCounters(t_AdOfTypeStats *p_StatsAd, ++ uint32_t statsCountersAddr) ++{ ++ uint32_t tmp = (statsCountersAddr & FM_PCD_AD_STATS_COUNTERS_ADDR_MASK); ++ ++ WRITE_UINT32(p_StatsAd->statsTableAddr, tmp); ++} ++ ++ ++static void UpdateStatsAd(t_FmPcdCcStatsParams *p_FmPcdCcStatsParams, ++ t_Handle h_Ad, ++ uint64_t physicalMuramBase) ++{ ++ t_AdOfTypeStats *p_StatsAd; ++ uint32_t statsCountersAddr, nextActionAddr, tmp; ++#if (DPAA_VERSION >= 11) ++ uint32_t frameLengthRangesAddr; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ p_StatsAd = (t_AdOfTypeStats *)p_FmPcdCcStatsParams->h_StatsAd; ++ ++ tmp = FM_PCD_AD_STATS_TYPE; ++ ++#if (DPAA_VERSION >= 11) ++ if (p_FmPcdCcStatsParams->h_StatsFLRs) ++ { ++ frameLengthRangesAddr = (uint32_t)((XX_VirtToPhys(p_FmPcdCcStatsParams->h_StatsFLRs) - physicalMuramBase)); ++ tmp |= (frameLengthRangesAddr & FM_PCD_AD_STATS_FLR_ADDR_MASK); ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ WRITE_UINT32(p_StatsAd->profileTableAddr, tmp); ++ ++ nextActionAddr = (uint32_t)((XX_VirtToPhys(h_Ad) - physicalMuramBase)); ++ tmp = 0; ++ tmp |= (uint32_t)((nextActionAddr << FM_PCD_AD_STATS_NEXT_ACTION_SHIFT) & FM_PCD_AD_STATS_NEXT_ACTION_MASK); ++ tmp |= (FM_PCD_AD_STATS_NAD_EN | FM_PCD_AD_STATS_OP_CODE); ++ ++#if (DPAA_VERSION >= 11) ++ if (p_FmPcdCcStatsParams->h_StatsFLRs) ++ tmp |= FM_PCD_AD_STATS_FLR_EN; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ WRITE_UINT32(p_StatsAd->nextActionIndx, tmp); ++ ++ statsCountersAddr = (uint32_t)((XX_VirtToPhys(p_FmPcdCcStatsParams->h_StatsCounters) - physicalMuramBase)); ++ SetStatsCounters(p_StatsAd, statsCountersAddr); ++} ++ ++static void FillAdOfTypeContLookup(t_Handle h_Ad, ++ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams, ++ t_Handle h_FmPcd, ++ t_Handle p_CcNode, ++ t_Handle h_Manip, ++ t_Handle h_FrmReplic) ++{ ++ t_FmPcdCcNode *p_Node = (t_FmPcdCcNode *)p_CcNode; ++ t_AdOfTypeContLookup *p_AdContLookup = (t_AdOfTypeContLookup *)h_Ad; ++ t_Handle h_TmpAd; ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t tmpReg32; ++ t_Handle p_AdNewPtr = NULL; ++ ++ UNUSED(h_Manip); ++ UNUSED(h_FrmReplic); ++ ++ /* there are 3 cases handled in this routine of building a "Continue lookup" type AD. ++ * Case 1: No Manip. The action descriptor is built within the match table. ++ * p_AdResult = p_AdNewPtr; ++ * Case 2: Manip exists. A new AD is created - p_AdNewPtr. It is initialized ++ * either in the FmPcdManipUpdateAdResultForCc routine or it was already ++ * initialized and returned here. ++ * p_AdResult (within the match table) will be initialized after ++ * this routine returns and point to the existing AD. ++ * Case 3: Manip exists. The action descriptor is built within the match table. ++ * FmPcdManipUpdateAdContLookupForCc returns a NULL p_AdNewPtr. ++ */ ++ ++ /* As default, the "new" ptr is the current one. i.e. the content of the result ++ * AD will be written into the match table itself (case (1))*/ ++ p_AdNewPtr = p_AdContLookup; ++ ++ /* Initialize an action descriptor, if current statistics mode requires an Ad */ ++ if (p_FmPcdCcStatsParams) ++ { ++ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsAd); ++ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsCounters); ++ ++ /* Swapping addresses between statistics Ad and the current lookup AD */ ++ h_TmpAd = p_FmPcdCcStatsParams->h_StatsAd; ++ p_FmPcdCcStatsParams->h_StatsAd = h_Ad; ++ h_Ad = h_TmpAd; ++ ++ p_AdNewPtr = h_Ad; ++ p_AdContLookup = h_Ad; ++ ++ /* Init statistics Ad and connect current lookup AD as 'next action' from statistics Ad */ ++ UpdateStatsAd(p_FmPcdCcStatsParams, ++ h_Ad, ++ p_FmPcd->physicalMuramBase); ++ } ++ ++#if DPAA_VERSION >= 11 ++ if (h_Manip && h_FrmReplic) ++ FmPcdManipUpdateAdContLookupForCc(h_Manip, ++ h_Ad, ++ &p_AdNewPtr, ++ (uint32_t)((XX_VirtToPhys(FrmReplicGroupGetSourceTableDescriptor(h_FrmReplic)) - p_FmPcd->physicalMuramBase))); ++ else if (h_FrmReplic) ++ FrmReplicGroupUpdateAd(h_FrmReplic, h_Ad, &p_AdNewPtr); ++ else ++#endif /* (DPAA_VERSION >= 11) */ ++ if (h_Manip) ++ FmPcdManipUpdateAdContLookupForCc(h_Manip, ++ h_Ad, ++ &p_AdNewPtr, ++ ++#ifdef FM_CAPWAP_SUPPORT ++ /*no check for opcode of manip - this step can be reached only with capwap_applic_specific*/ ++ (uint32_t)((XX_VirtToPhys(p_Node->h_AdTable) - p_FmPcd->physicalMuramBase)) ++#else /* not FM_CAPWAP_SUPPORT */ ++ (uint32_t)((XX_VirtToPhys(p_Node->h_Ad) - p_FmPcd->physicalMuramBase)) ++#endif /* not FM_CAPWAP_SUPPORT */ ++ ); ++ ++ /* if (p_AdNewPtr = NULL) --> Done. (case (3)) */ ++ if (p_AdNewPtr) ++ { ++ /* cases (1) & (2) */ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ tmpReg32 |= p_Node->sizeOfExtraction ? ((p_Node->sizeOfExtraction - 1) << 24) : 0; ++ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Node->h_AdTable) - p_FmPcd->physicalMuramBase); ++ WRITE_UINT32(p_AdContLookup->ccAdBase, tmpReg32); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= p_Node->numOfKeys << 24; ++ tmpReg32 |= (p_Node->lclMask ? FM_PCD_AD_CONT_LOOKUP_LCL_MASK : 0); ++ tmpReg32 |= p_Node->h_KeysMatchTable ? ++ (uint32_t)(XX_VirtToPhys(p_Node->h_KeysMatchTable) - p_FmPcd->physicalMuramBase) : 0; ++ WRITE_UINT32(p_AdContLookup->matchTblPtr, tmpReg32); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= p_Node->prsArrayOffset << 24; ++ tmpReg32 |= p_Node->offset << 16; ++ tmpReg32 |= p_Node->parseCode; ++ WRITE_UINT32(p_AdContLookup->pcAndOffsets, tmpReg32); ++ ++ Mem2IOCpy32((void*)&p_AdContLookup->gmask, p_Node->p_GlblMask, CC_GLBL_MASK_SIZE); ++ } ++} ++ ++static t_Error AllocAndFillAdForContLookupManip(t_Handle h_CcNode) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_CcNode); ++ ++ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); ++ ++ if (!p_CcNode->h_Ad) ++ { ++ p_CcNode->h_Ad = (t_Handle)FM_MURAM_AllocMem(((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ ++ if (!p_CcNode->h_Ad) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC action descriptor")); ++ ++ IOMemSet32(p_CcNode->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ FillAdOfTypeContLookup(p_CcNode->h_Ad, ++ NULL, ++ p_CcNode->h_FmPcd, ++ p_CcNode, ++ NULL, ++ NULL); ++ } ++ else ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ ++ return E_OK; ++} ++ ++static t_Error SetRequiredAction(t_Handle h_FmPcd, ++ uint32_t requiredAction, ++ t_FmPcdCcKeyAndNextEngineParams *p_CcKeyAndNextEngineParamsTmp, ++ t_Handle h_AdTmp, ++ uint16_t numOfEntries, ++ t_Handle h_Tree) ++{ ++ t_AdOfTypeResult *p_AdTmp = (t_AdOfTypeResult *)h_AdTmp; ++ uint32_t tmpReg32; ++ t_Error err; ++ t_FmPcdCcNode *p_CcNode; ++ int i = 0; ++ uint16_t tmp = 0; ++ uint16_t profileId; ++ uint8_t relativeSchemeId, physicalSchemeId; ++ t_CcNodeInformation ccNodeInfo; ++ ++ for (i = 0; i < numOfEntries; i++) ++ { ++ if (i == 0) ++ h_AdTmp = PTR_MOVE(h_AdTmp, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ else ++ h_AdTmp = PTR_MOVE(h_AdTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ switch (p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.nextEngine) ++ { ++ case (e_FM_PCD_CC): ++ if (requiredAction) ++ { ++ p_CcNode = p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.ccParams.h_CcNode; ++ ASSERT_COND(p_CcNode); ++ if (p_CcNode->shadowAction == requiredAction) ++ break; ++ if ((requiredAction & UPDATE_CC_WITH_TREE) && !(p_CcNode->shadowAction & UPDATE_CC_WITH_TREE)) ++ { ++ ++ ASSERT_COND(LIST_NumOfObjs(&p_CcNode->ccTreesLst) == 0); ++ if (p_CcNode->shadowAction & UPDATE_CC_WITH_DELETE_TREE) ++ p_CcNode->shadowAction &= ~UPDATE_CC_WITH_DELETE_TREE; ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = h_Tree; ++ EnqueueNodeInfoToRelevantLst(&p_CcNode->ccTreesLst, &ccNodeInfo, NULL); ++ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= UPDATE_CC_WITH_TREE; ++ } ++ if ((requiredAction & UPDATE_CC_WITH_DELETE_TREE) && !(p_CcNode->shadowAction & UPDATE_CC_WITH_DELETE_TREE)) ++ { ++ ASSERT_COND(LIST_NumOfObjs(&p_CcNode->ccTreesLst) == 1); ++ if (p_CcNode->shadowAction & UPDATE_CC_WITH_TREE) ++ p_CcNode->shadowAction &= ~UPDATE_CC_WITH_TREE; ++ DequeueNodeInfoFromRelevantLst(&p_CcNode->ccTreesLst, h_Tree, NULL); ++ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= UPDATE_CC_WITH_DELETE_TREE; ++ } ++ if (p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine != e_FM_PCD_INVALID) ++ tmp = (uint8_t)(p_CcNode->numOfKeys + 1); ++ else ++ tmp = p_CcNode->numOfKeys; ++ err = SetRequiredAction(h_FmPcd, ++ requiredAction, ++ p_CcNode->keyAndNextEngineParams, ++ p_CcNode->h_AdTable, ++ tmp, ++ h_Tree); ++ if (err != E_OK) ++ return err; ++ p_CcNode->shadowAction |= requiredAction; ++ } ++ break; ++ ++ case (e_FM_PCD_KG): ++ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction & UPDATE_NIA_ENQ_WITHOUT_DMA)) ++ { ++ physicalSchemeId = FmPcdKgGetSchemeId(p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme); ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(h_FmPcd, physicalSchemeId); ++ if (relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ if (!FmPcdKgIsSchemeValidSw(p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid direct scheme.")); ++ if (!KgIsSchemeAlwaysDirect(h_FmPcd, relativeSchemeId)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this action scheme has to be direct.")); ++ err = FmPcdKgCcGetSetParams(h_FmPcd, p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme, requiredAction, 0); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= requiredAction; ++ } ++ break; ++ ++ case (e_FM_PCD_PLCR): ++ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction & UPDATE_NIA_ENQ_WITHOUT_DMA)) ++ { ++ if (!p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.overrideParams) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this initialization only overrideFqid can be initialized")); ++ if (!p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.sharedProfile) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this initialization only overrideFqid can be initialized")); ++ err = FmPcdPlcrGetAbsoluteIdByProfileParams(h_FmPcd, e_FM_PCD_PLCR_SHARED, NULL, p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.newRelativeProfileId, &profileId); ++ if (err!= E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ err = FmPcdPlcrCcGetSetParams(h_FmPcd, profileId, requiredAction); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= requiredAction; ++ } ++ break; ++ ++ case (e_FM_PCD_DONE): ++ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction & UPDATE_NIA_ENQ_WITHOUT_DMA)) ++ { ++ tmpReg32 = GET_UINT32(p_AdTmp->nia); ++ if ((tmpReg32 & GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd)) != GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine was previously assigned not as PCD_DONE")); ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ WRITE_UINT32(p_AdTmp->nia, tmpReg32); ++ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= requiredAction; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ return E_OK; ++} ++ ++static t_Error ReleaseModifiedDataStructure(t_Handle h_FmPcd, ++ t_List *h_FmPcdOldPointersLst, ++ t_List *h_FmPcdNewPointersLst, ++ uint16_t numOfGoodChanges, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams, ++ bool useShadowStructs) ++{ ++ t_List *p_Pos; ++ t_Error err = E_OK; ++ t_CcNodeInformation ccNodeInfo, *p_CcNodeInformation; ++ t_Handle h_Muram; ++ t_FmPcdCcNode *p_FmPcdCcNextNode; ++ t_List *p_UpdateLst; ++ uint32_t intFlags; ++ ++ UNUSED(numOfGoodChanges); ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_AdditionalParams->h_CurrentNode,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdOldPointersLst,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdNewPointersLst,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((numOfGoodChanges == LIST_NumOfObjs(h_FmPcdOldPointersLst)),E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((1 == LIST_NumOfObjs(h_FmPcdNewPointersLst)),E_INVALID_STATE); ++ ++ /* We don't update subtree of the new node with new tree because it was done in the previous stage */ ++ if (p_AdditionalParams->h_NodeForAdd) ++ { ++ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_AdditionalParams->h_NodeForAdd; ++ ++ if (!p_AdditionalParams->tree) ++ p_UpdateLst = &p_FmPcdCcNextNode->ccPrevNodesLst; ++ else ++ p_UpdateLst = &p_FmPcdCcNextNode->ccTreeIdLst; ++ ++ p_CcNodeInformation = FindNodeInfoInReleventLst(p_UpdateLst, ++ p_AdditionalParams->h_CurrentNode, ++ p_FmPcdCcNextNode->h_Spinlock); ++ ++ if (p_CcNodeInformation) ++ p_CcNodeInformation->index++; ++ else ++ { ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = (t_Handle)p_AdditionalParams->h_CurrentNode; ++ ccNodeInfo.index = 1; ++ EnqueueNodeInfoToRelevantLst(p_UpdateLst, ++ &ccNodeInfo, ++ p_FmPcdCcNextNode->h_Spinlock); ++ } ++ if (p_AdditionalParams->h_ManipForAdd) ++ { ++ p_CcNodeInformation = FindNodeInfoInReleventLst(FmPcdManipGetNodeLstPointedOnThisManip(p_AdditionalParams->h_ManipForAdd), ++ p_AdditionalParams->h_CurrentNode, ++ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForAdd)); ++ ++ if (p_CcNodeInformation) ++ p_CcNodeInformation->index++; ++ else ++ { ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = (t_Handle)p_AdditionalParams->h_CurrentNode; ++ ccNodeInfo.index = 1; ++ EnqueueNodeInfoToRelevantLst(FmPcdManipGetNodeLstPointedOnThisManip(p_AdditionalParams->h_ManipForAdd), ++ &ccNodeInfo, ++ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForAdd)); ++ } ++ } ++ } ++ ++ if (p_AdditionalParams->h_NodeForRmv) ++ { ++ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_AdditionalParams->h_NodeForRmv; ++ ++ if (!p_AdditionalParams->tree) ++ { ++ p_UpdateLst = &p_FmPcdCcNextNode->ccPrevNodesLst; ++ ++ while (!LIST_IsEmpty(&p_FmPcdCcNextNode->ccTreesLst)) ++ { ++ p_Pos = LIST_NEXT(&p_FmPcdCcNextNode->ccTreesLst); ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ ++ ASSERT_COND(p_CcNodeInformation->h_CcNode); ++ ++ err = SetRequiredAction(h_FmPcd, ++ UPDATE_CC_WITH_DELETE_TREE, ++ &((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams[p_AdditionalParams->savedKeyIndex], ++ PTR_MOVE(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_AdTable, p_AdditionalParams->savedKeyIndex*FM_PCD_CC_AD_ENTRY_SIZE), ++ 1, ++ p_CcNodeInformation->h_CcNode); ++ } ++ } ++ else ++ { ++ p_UpdateLst = &p_FmPcdCcNextNode->ccTreeIdLst; ++ ++ err = SetRequiredAction(h_FmPcd, ++ UPDATE_CC_WITH_DELETE_TREE, ++ &((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams[p_AdditionalParams->savedKeyIndex], ++ UINT_TO_PTR(((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->ccTreeBaseAddr + p_AdditionalParams->savedKeyIndex*FM_PCD_CC_AD_ENTRY_SIZE), ++ 1, ++ p_AdditionalParams->h_CurrentNode); ++ } ++ if (err) ++ return err; ++ ++ /* We remove from the subtree of the removed node tree because it wasn't done in the previous stage ++ Update ccPrevNodesLst or ccTreeIdLst of the removed node ++ Update of the node owner */ ++ p_CcNodeInformation = FindNodeInfoInReleventLst(p_UpdateLst, ++ p_AdditionalParams->h_CurrentNode, ++ p_FmPcdCcNextNode->h_Spinlock); ++ ++ ASSERT_COND(p_CcNodeInformation); ++ ASSERT_COND(p_CcNodeInformation->index); ++ ++ p_CcNodeInformation->index--; ++ ++ if (p_CcNodeInformation->index == 0) ++ DequeueNodeInfoFromRelevantLst(p_UpdateLst, ++ p_AdditionalParams->h_CurrentNode, ++ p_FmPcdCcNextNode->h_Spinlock); ++ ++ UpdateNodeOwner(p_FmPcdCcNextNode, FALSE); ++ ++ if (p_AdditionalParams->h_ManipForRmv) ++ { ++ p_CcNodeInformation = FindNodeInfoInReleventLst(FmPcdManipGetNodeLstPointedOnThisManip(p_AdditionalParams->h_ManipForRmv), ++ p_AdditionalParams->h_CurrentNode, ++ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForRmv)); ++ ++ ASSERT_COND(p_CcNodeInformation); ++ ASSERT_COND(p_CcNodeInformation->index); ++ ++ p_CcNodeInformation->index--; ++ ++ if (p_CcNodeInformation->index == 0) ++ DequeueNodeInfoFromRelevantLst(FmPcdManipGetNodeLstPointedOnThisManip(p_AdditionalParams->h_ManipForRmv), ++ p_AdditionalParams->h_CurrentNode, ++ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForRmv)); ++ } ++ } ++ ++ if (p_AdditionalParams->h_ManipForRmv) ++ FmPcdManipUpdateOwner(p_AdditionalParams->h_ManipForRmv, FALSE); ++ ++ if (p_AdditionalParams->p_StatsObjForRmv) ++ PutStatsObj((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode), ++ p_AdditionalParams->p_StatsObjForRmv); ++ ++#if (DPAA_VERSION >= 11) ++ if (p_AdditionalParams->h_FrmReplicForRmv) ++ FrmReplicGroupUpdateOwner(p_AdditionalParams->h_FrmReplicForRmv, ++ FALSE/* remove */); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (!useShadowStructs) ++ { ++ h_Muram = FmPcdGetMuramHandle(h_FmPcd); ++ ASSERT_COND(h_Muram); ++ ++ if ((p_AdditionalParams->tree && ++ !((t_FmPcd *)h_FmPcd)->p_CcShadow) || ++ (!p_AdditionalParams->tree && ++ !((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->maxNumOfKeys)) ++ { ++ /* We release new AD which was allocated and updated for copy from to actual AD */ ++ p_Pos = LIST_FIRST(h_FmPcdNewPointersLst); ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ ASSERT_COND(p_CcNodeInformation->h_CcNode); ++ FM_MURAM_FreeMem(h_Muram, p_CcNodeInformation->h_CcNode); ++ } ++ ++ /* Free Old data structure if it has to be freed - new data structure was allocated*/ ++ if (p_AdditionalParams->p_AdTableOld) ++ FM_MURAM_FreeMem(h_Muram,p_AdditionalParams->p_AdTableOld); ++ ++ if (p_AdditionalParams->p_KeysMatchTableOld) ++ FM_MURAM_FreeMem(h_Muram,p_AdditionalParams->p_KeysMatchTableOld); ++ } ++ ++ /* Update current modified node with changed fields if it's required*/ ++ if (!p_AdditionalParams->tree) ++ { ++ if (p_AdditionalParams->p_AdTableNew) ++ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_AdTable = p_AdditionalParams->p_AdTableNew; ++ ++ if (p_AdditionalParams->p_KeysMatchTableNew) ++ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_KeysMatchTable = p_AdditionalParams->p_KeysMatchTableNew; ++ ++ /* Locking node's spinlock before updating 'keys and next engine' structure, ++ as it maybe used to retrieve keys statistics */ ++ intFlags = XX_LockIntrSpinlock(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_Spinlock); ++ ++ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->numOfKeys = p_AdditionalParams->numOfKeys; ++ ++ memcpy(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams, ++ &p_AdditionalParams->keyAndNextEngineParams, ++ sizeof(t_FmPcdCcKeyAndNextEngineParams) * (CC_MAX_NUM_OF_KEYS)); ++ ++ XX_UnlockIntrSpinlock(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_Spinlock, intFlags); ++ } ++ else ++ { ++ uint8_t numEntries = ((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->numOfEntries; ++ ASSERT_COND(numEntries < FM_PCD_MAX_NUM_OF_CC_GROUPS); ++ memcpy(&((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams, ++ &p_AdditionalParams->keyAndNextEngineParams, ++ sizeof(t_FmPcdCcKeyAndNextEngineParams) * numEntries); ++ } ++ ++ ReleaseLst(h_FmPcdOldPointersLst); ++ ReleaseLst(h_FmPcdNewPointersLst); ++ ++ XX_Free(p_AdditionalParams); ++ ++ return E_OK; ++} ++ ++static t_Handle BuildNewAd(t_Handle h_Ad, ++ t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams, ++ t_FmPcdCcNode *p_CcNode, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_FmPcdCcNodeTmp; ++ ++ p_FmPcdCcNodeTmp = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode)); ++ if (!p_FmPcdCcNodeTmp) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_FmPcdCcNodeTmp")); ++ return NULL; ++ } ++ memset(p_FmPcdCcNodeTmp, 0, sizeof(t_FmPcdCcNode)); ++ ++ p_FmPcdCcNodeTmp->numOfKeys = p_FmPcdModifyCcKeyAdditionalParams->numOfKeys; ++ p_FmPcdCcNodeTmp->h_KeysMatchTable = p_FmPcdModifyCcKeyAdditionalParams->p_KeysMatchTableNew; ++ p_FmPcdCcNodeTmp->h_AdTable = p_FmPcdModifyCcKeyAdditionalParams->p_AdTableNew; ++ ++ p_FmPcdCcNodeTmp->lclMask = p_CcNode->lclMask; ++ p_FmPcdCcNodeTmp->parseCode = p_CcNode->parseCode; ++ p_FmPcdCcNodeTmp->offset = p_CcNode->offset; ++ p_FmPcdCcNodeTmp->prsArrayOffset = p_CcNode->prsArrayOffset; ++ p_FmPcdCcNodeTmp->ctrlFlow = p_CcNode->ctrlFlow; ++ p_FmPcdCcNodeTmp->ccKeySizeAccExtraction = p_CcNode->ccKeySizeAccExtraction; ++ p_FmPcdCcNodeTmp->sizeOfExtraction = p_CcNode->sizeOfExtraction; ++ p_FmPcdCcNodeTmp->glblMaskSize = p_CcNode->glblMaskSize; ++ p_FmPcdCcNodeTmp->p_GlblMask = p_CcNode->p_GlblMask; ++ ++ if (p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_CC) ++ { ++ if (p_FmPcdCcNextEngineParams->h_Manip) ++ { ++ if (AllocAndFillAdForContLookupManip(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode)!= E_OK) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ return NULL; ++ } ++ } ++ FillAdOfTypeContLookup(h_Ad, ++ NULL, ++ p_CcNode->h_FmPcd, ++ p_FmPcdCcNodeTmp, ++ p_FmPcdCcNextEngineParams->h_Manip, ++ NULL); ++ } ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_FR) && ++ (p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic)) ++ { ++ FillAdOfTypeContLookup(h_Ad, ++ NULL, ++ p_CcNode->h_FmPcd, ++ p_FmPcdCcNodeTmp, ++ p_FmPcdCcNextEngineParams->h_Manip, ++ p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic); ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ XX_Free(p_FmPcdCcNodeTmp); ++ ++ return E_OK; ++} ++ ++static t_Error DynamicChangeHc(t_Handle h_FmPcd, ++ t_List *h_OldPointersLst, ++ t_List *h_NewPointersLst, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams, ++ bool useShadowStructs) ++{ ++ t_List *p_PosOld, *p_PosNew; ++ uint32_t oldAdAddrOffset, newAdAddrOffset; ++ uint16_t i = 0; ++ t_Error err = E_OK; ++ uint8_t numOfModifiedPtr; ++ ++ ASSERT_COND(h_FmPcd); ++ ASSERT_COND(h_OldPointersLst); ++ ASSERT_COND(h_NewPointersLst); ++ ++ numOfModifiedPtr = (uint8_t)LIST_NumOfObjs(h_OldPointersLst); ++ ++ p_PosNew = LIST_FIRST(h_NewPointersLst); ++ p_PosOld = LIST_FIRST(h_OldPointersLst); ++ ++ /* Retrieve address of new AD */ ++ newAdAddrOffset = FmPcdCcGetNodeAddrOffsetFromNodeInfo(h_FmPcd, p_PosNew); ++ if (newAdAddrOffset == (uint32_t)ILLEGAL_BASE) ++ { ++ ReleaseModifiedDataStructure(h_FmPcd, ++ h_OldPointersLst, ++ h_NewPointersLst, ++ 0, ++ p_AdditionalParams, ++ useShadowStructs); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("New AD address")); ++ } ++ ++ for (i=0; ih_Hc, oldAdAddrOffset, newAdAddrOffset); ++ if (err) ++ { ++ ReleaseModifiedDataStructure(h_FmPcd, ++ h_OldPointersLst, ++ h_NewPointersLst, ++ i, ++ p_AdditionalParams, ++ useShadowStructs); ++ RETURN_ERROR(MAJOR, err, ("For part of nodes changes are done - situation is danger")); ++ } ++ ++ p_PosOld = LIST_NEXT(p_PosOld); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error DoDynamicChange(t_Handle h_FmPcd, ++ t_List *h_OldPointersLst, ++ t_List *h_NewPointersLst, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams, ++ bool useShadowStructs) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode); ++ t_List *p_PosNew; ++ t_CcNodeInformation *p_CcNodeInfo; ++ t_FmPcdCcNextEngineParams nextEngineParams; ++ t_Handle h_Ad; ++ uint32_t keySize; ++ t_Error err = E_OK; ++ uint8_t numOfModifiedPtr; ++ ++ ASSERT_COND(h_FmPcd); ++ ++ SANITY_CHECK_RETURN_ERROR((LIST_NumOfObjs(h_OldPointersLst) >= 1),E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((LIST_NumOfObjs(h_NewPointersLst) == 1),E_INVALID_STATE); ++ ++ memset(&nextEngineParams, 0, sizeof(t_FmPcdCcNextEngineParams)); ++ ++ numOfModifiedPtr = (uint8_t)LIST_NumOfObjs(h_OldPointersLst); ++ ++ p_PosNew = LIST_FIRST(h_NewPointersLst); ++ ++ /* Invoke host-command to copy from the new Ad to existing Ads */ ++ err = DynamicChangeHc(h_FmPcd, h_OldPointersLst, h_NewPointersLst, p_AdditionalParams, useShadowStructs); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (useShadowStructs) ++ { ++ /* When the host-command above has ended, the old structures are 'free'and we can update ++ them by copying from the new shadow structures. */ ++ if (p_CcNode->lclMask) ++ keySize = (uint32_t)(2 * p_CcNode->ccKeySizeAccExtraction); ++ else ++ keySize = p_CcNode->ccKeySizeAccExtraction; ++ ++ IO2IOCpy32(p_AdditionalParams->p_KeysMatchTableOld, ++ p_AdditionalParams->p_KeysMatchTableNew, ++ p_CcNode->maxNumOfKeys * keySize * sizeof (uint8_t)); ++ ++ IO2IOCpy32(p_AdditionalParams->p_AdTableOld, ++ p_AdditionalParams->p_AdTableNew, ++ (uint32_t)((p_CcNode->maxNumOfKeys + 1) * FM_PCD_CC_AD_ENTRY_SIZE)); ++ ++ /* Retrieve the address of the allocated Ad */ ++ p_CcNodeInfo = CC_NODE_F_OBJECT(p_PosNew); ++ h_Ad = p_CcNodeInfo->h_CcNode; ++ ++ /* Build a new Ad that holds the old (now updated) structures */ ++ p_AdditionalParams->p_KeysMatchTableNew = p_AdditionalParams->p_KeysMatchTableOld; ++ p_AdditionalParams->p_AdTableNew = p_AdditionalParams->p_AdTableOld; ++ ++ nextEngineParams.nextEngine = e_FM_PCD_CC; ++ nextEngineParams.params.ccParams.h_CcNode = (t_Handle)p_CcNode; ++ ++ BuildNewAd(h_Ad, p_AdditionalParams, p_CcNode, &nextEngineParams); ++ ++ /* HC to copy from the new Ad (old updated structures) to current Ad (uses shadow structures) */ ++ err = DynamicChangeHc(h_FmPcd, h_OldPointersLst, h_NewPointersLst, p_AdditionalParams, useShadowStructs); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = ReleaseModifiedDataStructure(h_FmPcd, ++ h_OldPointersLst, ++ h_NewPointersLst, ++ numOfModifiedPtr, ++ p_AdditionalParams, ++ useShadowStructs); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++#ifdef FM_CAPWAP_SUPPORT ++static bool IsCapwapApplSpecific(t_Handle h_Node) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_Node; ++ bool isManipForCapwapApplSpecificBuild = FALSE; ++ int i = 0; ++ ++ ASSERT_COND(h_Node); ++ /* assumption that this function called only for INDEXED_FLOW_ID - so no miss*/ ++ for (i = 0; i < p_CcNode->numOfKeys; i++) ++ { ++ if ( p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip && ++ FmPcdManipIsCapwapApplSpecific(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip)) ++ { ++ isManipForCapwapApplSpecificBuild = TRUE; ++ break; ++ } ++ } ++ return isManipForCapwapApplSpecificBuild; ++ ++} ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++static t_Error CcUpdateParam(t_Handle h_FmPcd, ++ t_Handle h_PcdParams, ++ t_Handle h_FmPort, ++ t_FmPcdCcKeyAndNextEngineParams *p_CcKeyAndNextEngineParams, ++ uint16_t numOfEntries, ++ t_Handle h_Ad, ++ bool validate, ++ uint16_t level, ++ t_Handle h_FmTree, ++ bool modify) ++{ ++ t_FmPcdCcNode *p_CcNode; ++ t_Error err; ++ uint16_t tmp = 0; ++ int i = 0; ++ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *) h_FmTree; ++ ++ level++; ++ ++ if (p_CcTree->h_IpReassemblyManip) ++ { ++ err = FmPcdManipUpdate(h_FmPcd, ++ h_PcdParams, ++ h_FmPort, ++ p_CcTree->h_IpReassemblyManip, ++ NULL, ++ validate, ++ level, ++ h_FmTree, ++ modify); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (numOfEntries) ++ { ++ for (i=0; ikeyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine != e_FM_PCD_INVALID) ++ tmp = (uint8_t)(p_CcNode->numOfKeys + 1); ++ else ++ tmp = p_CcNode->numOfKeys; ++ ++ err = CcUpdateParam(h_FmPcd, ++ h_PcdParams, ++ h_FmPort, ++ p_CcNode->keyAndNextEngineParams, ++ tmp, ++ p_CcNode->h_AdTable, ++ validate, ++ level, ++ h_FmTree, ++ modify); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ else ++ { ++ if (p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip) ++ { ++ err = FmPcdManipUpdate(h_FmPcd, ++ NULL, ++ h_FmPort, ++ p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip, ++ h_Ad, ++ validate, ++ level, ++ h_FmTree, ++ modify); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ } ++ } ++ ++ return E_OK; ++} ++ ++static ccPrivateInfo_t IcDefineCode(t_FmPcdCcNodeParams *p_CcNodeParam) ++{ ++ switch (p_CcNodeParam->extractCcParams.extractNonHdr.action) ++ { ++ case (e_FM_PCD_ACTION_EXACT_MATCH): ++ switch (p_CcNodeParam->extractCcParams.extractNonHdr.src) ++ { ++ case (e_FM_PCD_EXTRACT_FROM_KEY): ++ return CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH; ++ case (e_FM_PCD_EXTRACT_FROM_HASH): ++ return CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH; ++ default: ++ return CC_PRIVATE_INFO_NONE; ++ } ++ ++ case (e_FM_PCD_ACTION_INDEXED_LOOKUP): ++ switch (p_CcNodeParam->extractCcParams.extractNonHdr.src) ++ { ++ case (e_FM_PCD_EXTRACT_FROM_HASH): ++ return CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP; ++ case (e_FM_PCD_EXTRACT_FROM_FLOW_ID): ++ return CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP; ++ default: ++ return CC_PRIVATE_INFO_NONE; ++ } ++ ++ default: ++ break; ++ } ++ ++ return CC_PRIVATE_INFO_NONE; ++} ++ ++static t_CcNodeInformation * DequeueAdditionalInfoFromRelevantLst(t_List *p_List) ++{ ++ t_CcNodeInformation *p_CcNodeInfo = NULL; ++ ++ if (!LIST_IsEmpty(p_List)) ++ { ++ p_CcNodeInfo = CC_NODE_F_OBJECT(p_List->p_Next); ++ LIST_DelAndInit(&p_CcNodeInfo->node); ++ } ++ ++ return p_CcNodeInfo; ++} ++ ++void ReleaseLst(t_List *p_List) ++{ ++ t_CcNodeInformation *p_CcNodeInfo = NULL; ++ ++ if (!LIST_IsEmpty(p_List)) ++ { ++ p_CcNodeInfo = DequeueAdditionalInfoFromRelevantLst(p_List); ++ while (p_CcNodeInfo) ++ { ++ XX_Free(p_CcNodeInfo); ++ p_CcNodeInfo = DequeueAdditionalInfoFromRelevantLst(p_List); ++ } ++ } ++ ++ LIST_Del(p_List); ++} ++ ++static void DeleteNode(t_FmPcdCcNode *p_CcNode) ++{ ++ uint32_t i; ++ ++ if (!p_CcNode) ++ return; ++ ++ if (p_CcNode->p_GlblMask) ++ { ++ XX_Free(p_CcNode->p_GlblMask); ++ p_CcNode->p_GlblMask = NULL; ++ } ++ ++ if (p_CcNode->h_KeysMatchTable) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_CcNode->h_KeysMatchTable); ++ p_CcNode->h_KeysMatchTable = NULL; ++ } ++ ++ if (p_CcNode->h_AdTable) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_CcNode->h_AdTable); ++ p_CcNode->h_AdTable = NULL; ++ } ++ ++ if (p_CcNode->h_Ad) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_CcNode->h_Ad); ++ p_CcNode->h_Ad = NULL; ++ } ++ ++ if (p_CcNode->h_StatsFLRs) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_CcNode->h_StatsFLRs); ++ p_CcNode->h_StatsFLRs = NULL; ++ } ++ ++ if (p_CcNode->h_Spinlock) ++ { ++ XX_FreeSpinlock(p_CcNode->h_Spinlock); ++ p_CcNode->h_Spinlock = NULL; ++ } ++ ++ /* Releasing all currently used statistics objects, including 'miss' entry */ ++ for (i = 0; i < p_CcNode->numOfKeys + 1; i++) ++ if (p_CcNode->keyAndNextEngineParams[i].p_StatsObj) ++ PutStatsObj(p_CcNode, p_CcNode->keyAndNextEngineParams[i].p_StatsObj); ++ ++ if (!LIST_IsEmpty(&p_CcNode->availableStatsLst)) ++ { ++ t_Handle h_FmMuram = FmPcdGetMuramHandle(p_CcNode->h_FmPcd); ++ ++ ASSERT_COND(h_FmMuram); ++ ++ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram); ++ } ++ ++ LIST_Del(&p_CcNode->availableStatsLst); ++ ++ ReleaseLst(&p_CcNode->ccPrevNodesLst); ++ ReleaseLst(&p_CcNode->ccTreeIdLst); ++ ReleaseLst(&p_CcNode->ccTreesLst); ++ ++ XX_Free(p_CcNode); ++} ++ ++static void DeleteTree(t_FmPcdCcTree *p_FmPcdTree, t_FmPcd *p_FmPcd) ++{ ++ if (p_FmPcdTree) ++ { ++ if (p_FmPcdTree->ccTreeBaseAddr) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_FmPcd), UINT_TO_PTR(p_FmPcdTree->ccTreeBaseAddr)); ++ p_FmPcdTree->ccTreeBaseAddr = 0; ++ } ++ ++ ReleaseLst(&p_FmPcdTree->fmPortsLst); ++ ++ XX_Free(p_FmPcdTree); ++ } ++} ++ ++static void GetCcExtractKeySize(uint8_t parseCodeRealSize, uint8_t *parseCodeCcSize) ++{ ++ if ((parseCodeRealSize > 0) && (parseCodeRealSize < 2)) ++ *parseCodeCcSize = 1; ++ else if (parseCodeRealSize == 2) ++ *parseCodeCcSize = 2; ++ else if ((parseCodeRealSize > 2) && (parseCodeRealSize <= 4)) ++ *parseCodeCcSize = 4; ++ else if ((parseCodeRealSize > 4) && (parseCodeRealSize <= 8)) ++ *parseCodeCcSize = 8; ++ else if ((parseCodeRealSize > 8) && (parseCodeRealSize <= 16)) ++ *parseCodeCcSize = 16; ++ else if ((parseCodeRealSize > 16) && (parseCodeRealSize <= 24)) ++ *parseCodeCcSize = 24; ++ else if ((parseCodeRealSize > 24) && (parseCodeRealSize <= 32)) ++ *parseCodeCcSize = 32; ++ else if ((parseCodeRealSize > 32) && (parseCodeRealSize <= 40)) ++ *parseCodeCcSize = 40; ++ else if ((parseCodeRealSize > 40) && (parseCodeRealSize <= 48)) ++ *parseCodeCcSize = 48; ++ else if ((parseCodeRealSize > 48) && (parseCodeRealSize <= 56)) ++ *parseCodeCcSize = 56; ++ else ++ *parseCodeCcSize = 0; ++} ++ ++static void GetSizeHeaderField(e_NetHeaderType hdr, ++ e_FmPcdHdrIndex index, ++ t_FmPcdFields field, ++ uint8_t *parseCodeRealSize) ++{ ++ UNUSED(index); ++ switch (hdr) ++ { ++ case (HEADER_TYPE_ETH): ++ switch (field.eth) ++ { ++ case (NET_HEADER_FIELD_ETH_DA): ++ *parseCodeRealSize = 6; ++ break; ++ ++ case (NET_HEADER_FIELD_ETH_SA): ++ *parseCodeRealSize = 6; ++ break; ++ ++ case (NET_HEADER_FIELD_ETH_TYPE): ++ *parseCodeRealSize = 2; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported1")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_PPPoE): ++ switch (field.pppoe) ++ { ++ case (NET_HEADER_FIELD_PPPoE_PID): ++ *parseCodeRealSize = 2; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported1")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_VLAN): ++ switch (field.vlan) ++ { ++ case (NET_HEADER_FIELD_VLAN_TCI): ++ *parseCodeRealSize = 2; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported2")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_MPLS): ++ switch (field.mpls) ++ { ++ case (NET_HEADER_FIELD_MPLS_LABEL_STACK): ++ *parseCodeRealSize = 4; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported3")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_IPv4): ++ switch (field.ipv4) ++ { ++ case (NET_HEADER_FIELD_IPv4_DST_IP): ++ case (NET_HEADER_FIELD_IPv4_SRC_IP): ++ *parseCodeRealSize = 4; ++ break; ++ ++ case (NET_HEADER_FIELD_IPv4_TOS): ++ case (NET_HEADER_FIELD_IPv4_PROTO): ++ *parseCodeRealSize = 1; ++ break; ++ ++ case (NET_HEADER_FIELD_IPv4_DST_IP | NET_HEADER_FIELD_IPv4_SRC_IP): ++ *parseCodeRealSize = 8; ++ break; ++ ++ case (NET_HEADER_FIELD_IPv4_TTL): ++ *parseCodeRealSize = 1; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported4")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_IPv6): ++ switch (field.ipv6) ++ { ++ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC): ++ *parseCodeRealSize = 4; ++ break; ++ ++ case (NET_HEADER_FIELD_IPv6_NEXT_HDR): ++ case (NET_HEADER_FIELD_IPv6_HOP_LIMIT): ++ *parseCodeRealSize = 1; ++ break; ++ ++ case (NET_HEADER_FIELD_IPv6_DST_IP): ++ case (NET_HEADER_FIELD_IPv6_SRC_IP): ++ *parseCodeRealSize = 16; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported5")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_IP): ++ switch (field.ip) ++ { ++ case (NET_HEADER_FIELD_IP_DSCP): ++ case (NET_HEADER_FIELD_IP_PROTO): ++ *parseCodeRealSize = 1; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported5")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_GRE): ++ switch (field.gre) ++ { ++ case ( NET_HEADER_FIELD_GRE_TYPE): ++ *parseCodeRealSize = 2; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported6")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_MINENCAP): ++ switch (field.minencap) ++ { ++ case (NET_HEADER_FIELD_MINENCAP_TYPE): ++ *parseCodeRealSize = 1; ++ break; ++ ++ case (NET_HEADER_FIELD_MINENCAP_DST_IP): ++ case (NET_HEADER_FIELD_MINENCAP_SRC_IP): ++ *parseCodeRealSize = 4; ++ break; ++ ++ case (NET_HEADER_FIELD_MINENCAP_SRC_IP | NET_HEADER_FIELD_MINENCAP_DST_IP): ++ *parseCodeRealSize = 8; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported7")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_TCP): ++ switch (field.tcp) ++ { ++ case (NET_HEADER_FIELD_TCP_PORT_SRC): ++ case (NET_HEADER_FIELD_TCP_PORT_DST): ++ *parseCodeRealSize = 2; ++ break; ++ ++ case (NET_HEADER_FIELD_TCP_PORT_SRC | NET_HEADER_FIELD_TCP_PORT_DST): ++ *parseCodeRealSize = 4; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported8")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_UDP): ++ switch (field.udp) ++ { ++ case (NET_HEADER_FIELD_UDP_PORT_SRC): ++ case (NET_HEADER_FIELD_UDP_PORT_DST): ++ *parseCodeRealSize = 2; ++ break; ++ ++ case (NET_HEADER_FIELD_UDP_PORT_SRC | NET_HEADER_FIELD_UDP_PORT_DST): ++ *parseCodeRealSize = 4; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported9")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported10")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++} ++ ++t_Error ValidateNextEngineParams(t_Handle h_FmPcd, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, ++ e_FmPcdCcStatsMode statsMode) ++{ ++ uint16_t absoluteProfileId; ++ t_Error err = E_OK; ++ uint8_t relativeSchemeId; ++ ++ if ((statsMode == e_FM_PCD_CC_STATS_MODE_NONE) && ++ (p_FmPcdCcNextEngineParams->statisticsEn)) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ++ ("Statistics are requested for a key, but statistics mode was set" ++ "to 'NONE' upon initialization of this match table")); ++ ++ switch (p_FmPcdCcNextEngineParams->nextEngine) ++ { ++ case (e_FM_PCD_INVALID): ++ err = E_NOT_SUPPORTED; ++ break; ++ ++ case (e_FM_PCD_DONE): ++ if ((p_FmPcdCcNextEngineParams->params.enqueueParams.action == e_FM_PCD_ENQ_FRAME) && ++ p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid) ++ { ++ if (!p_FmPcdCcNextEngineParams->params.enqueueParams.newFqid) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ("When overrideFqid is set, newFqid must not be zero")); ++ if (p_FmPcdCcNextEngineParams->params.enqueueParams.newFqid & ~0x00FFFFFF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidForCtrlFlow must be between 1 and 2^24-1")); ++ } ++ break; ++ ++ case (e_FM_PCD_KG): ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(h_FmPcd, ++ FmPcdKgGetSchemeId(p_FmPcdCcNextEngineParams->params.kgParams.h_DirectScheme)); ++ if (relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ if (!FmPcdKgIsSchemeValidSw(p_FmPcdCcNextEngineParams->params.kgParams.h_DirectScheme)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("not valid schemeIndex in KG next engine param")); ++ if (!KgIsSchemeAlwaysDirect(h_FmPcd, relativeSchemeId)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("CC Node may point only to a scheme that is always direct.")); ++ break; ++ ++ case (e_FM_PCD_PLCR): ++ if (p_FmPcdCcNextEngineParams->params.plcrParams.overrideParams) ++ { ++ /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */ ++ if (p_FmPcdCcNextEngineParams->params.plcrParams.sharedProfile) ++ { ++ err = FmPcdPlcrGetAbsoluteIdByProfileParams(h_FmPcd, ++ e_FM_PCD_PLCR_SHARED, ++ NULL, ++ p_FmPcdCcNextEngineParams->params.plcrParams.newRelativeProfileId, ++ &absoluteProfileId); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Shared profile offset is out of range")); ++ if (!FmPcdPlcrIsProfileValid(h_FmPcd, absoluteProfileId)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid profile")); ++ } ++ } ++ break; ++ ++ case (e_FM_PCD_HASH): ++ p_FmPcdCcNextEngineParams->nextEngine = e_FM_PCD_CC; ++ case (e_FM_PCD_CC): ++ if (!p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode) ++ RETURN_ERROR(MAJOR, E_NULL_POINTER, ("handler to next Node is NULL")); ++ break; ++ ++#if (DPAA_VERSION >= 11) ++ case (e_FM_PCD_FR): ++ if (!p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic) ++ err = E_NOT_SUPPORTED; ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine is not correct")); ++ } ++ ++ ++ return err; ++} ++ ++static uint8_t GetGenParseCode(t_Handle h_FmPcd, ++ e_FmPcdExtractFrom src, ++ uint32_t offset, ++ bool glblMask, ++ uint8_t *parseArrayOffset, ++ bool fromIc, ++ ccPrivateInfo_t icCode) ++{ ++ UNUSED(h_FmPcd); ++ ++ if (!fromIc) ++ { ++ switch (src) ++ { ++ case (e_FM_PCD_EXTRACT_FROM_FRAME_START): ++ if (glblMask) ++ return CC_PC_GENERIC_WITH_MASK ; ++ else ++ return CC_PC_GENERIC_WITHOUT_MASK; ++ ++ case (e_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE): ++ *parseArrayOffset = CC_PC_PR_NEXT_HEADER_OFFSET; ++ if (offset) ++ return CC_PR_OFFSET; ++ else ++ return CC_PR_WITHOUT_OFFSET; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src")); ++ return CC_PC_ILLEGAL; ++ } ++ } ++ else ++ { ++ switch (icCode) ++ { ++ case (CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH): ++ *parseArrayOffset = 0x50; ++ return CC_PC_GENERIC_IC_GMASK; ++ ++ case (CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH): ++ *parseArrayOffset = 0x48; ++ return CC_PC_GENERIC_IC_GMASK; ++ ++ case (CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP): ++ *parseArrayOffset = 0x48; ++ return CC_PC_GENERIC_IC_HASH_INDEXED; ++ ++ case (CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP): ++ *parseArrayOffset = 0x16; ++ return CC_PC_GENERIC_IC_HASH_INDEXED; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src")); ++ break; ++ } ++ } ++ ++ return CC_PC_ILLEGAL; ++} ++ ++static uint8_t GetFullFieldParseCode(e_NetHeaderType hdr, ++ e_FmPcdHdrIndex index, ++ t_FmPcdFields field) ++{ ++ switch (hdr) ++ { ++ case (HEADER_TYPE_NONE): ++ ASSERT_COND(FALSE); ++ return CC_PC_ILLEGAL; ++ ++ case (HEADER_TYPE_ETH): ++ switch (field.eth) ++ { ++ case (NET_HEADER_FIELD_ETH_DA): ++ return CC_PC_FF_MACDST; ++ case (NET_HEADER_FIELD_ETH_SA): ++ return CC_PC_FF_MACSRC; ++ case (NET_HEADER_FIELD_ETH_TYPE): ++ return CC_PC_FF_ETYPE; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_VLAN): ++ switch (field.vlan) ++ { ++ case (NET_HEADER_FIELD_VLAN_TCI): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_TCI1; ++ if (index == e_FM_PCD_HDR_INDEX_LAST) ++ return CC_PC_FF_TCI2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_MPLS): ++ switch (field.mpls) ++ { ++ case (NET_HEADER_FIELD_MPLS_LABEL_STACK): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_MPLS1; ++ if (index == e_FM_PCD_HDR_INDEX_LAST) ++ return CC_PC_FF_MPLS_LAST; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS index")); ++ return CC_PC_ILLEGAL; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_IPv4): ++ switch (field.ipv4) ++ { ++ case (NET_HEADER_FIELD_IPv4_DST_IP): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV4DST1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV4DST2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index")); ++ return CC_PC_ILLEGAL; ++ case (NET_HEADER_FIELD_IPv4_TOS): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV4IPTOS_TC1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV4IPTOS_TC2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index")); ++ return CC_PC_ILLEGAL; ++ case (NET_HEADER_FIELD_IPv4_PROTO): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV4PTYPE1; ++ if(index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV4PTYPE2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index")); ++ return CC_PC_ILLEGAL; ++ case (NET_HEADER_FIELD_IPv4_SRC_IP): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV4SRC1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV4SRC2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index")); ++ return CC_PC_ILLEGAL; ++ case (NET_HEADER_FIELD_IPv4_SRC_IP | NET_HEADER_FIELD_IPv4_DST_IP): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV4SRC1_IPV4DST1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV4SRC2_IPV4DST2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index")); ++ return CC_PC_ILLEGAL; ++ case (NET_HEADER_FIELD_IPv4_TTL): ++ return CC_PC_FF_IPV4TTL; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_IPv6): ++ switch (field.ipv6) ++ { ++ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return CC_PC_ILLEGAL; ++ ++ case (NET_HEADER_FIELD_IPv6_NEXT_HDR): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV6PTYPE1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV6PTYPE2; ++ if (index == e_FM_PCD_HDR_INDEX_LAST) ++ return CC_PC_FF_IPPID; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return CC_PC_ILLEGAL; ++ ++ case (NET_HEADER_FIELD_IPv6_DST_IP): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV6DST1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV6DST2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return CC_PC_ILLEGAL; ++ ++ case (NET_HEADER_FIELD_IPv6_SRC_IP): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV6SRC1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV6SRC2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return CC_PC_ILLEGAL; ++ ++ case (NET_HEADER_FIELD_IPv6_HOP_LIMIT): ++ return CC_PC_FF_IPV6HOP_LIMIT; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_IP): ++ switch (field.ip) ++ { ++ case (NET_HEADER_FIELD_IP_DSCP): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPDSCP; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP index")); ++ return CC_PC_ILLEGAL; ++ ++ case (NET_HEADER_FIELD_IP_PROTO): ++ if (index == e_FM_PCD_HDR_INDEX_LAST) ++ return CC_PC_FF_IPPID; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP index")); ++ return CC_PC_ILLEGAL; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_GRE): ++ switch (field.gre) ++ { ++ case (NET_HEADER_FIELD_GRE_TYPE): ++ return CC_PC_FF_GREPTYPE; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_MINENCAP): ++ switch (field.minencap) ++ { ++ case (NET_HEADER_FIELD_MINENCAP_TYPE): ++ return CC_PC_FF_MINENCAP_PTYPE; ++ ++ case (NET_HEADER_FIELD_MINENCAP_DST_IP): ++ return CC_PC_FF_MINENCAP_IPDST; ++ ++ case (NET_HEADER_FIELD_MINENCAP_SRC_IP): ++ return CC_PC_FF_MINENCAP_IPSRC; ++ ++ case (NET_HEADER_FIELD_MINENCAP_SRC_IP | NET_HEADER_FIELD_MINENCAP_DST_IP): ++ return CC_PC_FF_MINENCAP_IPSRC_IPDST; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_TCP): ++ switch (field.tcp) ++ { ++ case (NET_HEADER_FIELD_TCP_PORT_SRC): ++ return CC_PC_FF_L4PSRC; ++ ++ case (NET_HEADER_FIELD_TCP_PORT_DST): ++ return CC_PC_FF_L4PDST; ++ ++ case (NET_HEADER_FIELD_TCP_PORT_DST | NET_HEADER_FIELD_TCP_PORT_SRC): ++ return CC_PC_FF_L4PSRC_L4PDST; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_PPPoE): ++ switch (field.pppoe) ++ { ++ case (NET_HEADER_FIELD_PPPoE_PID): ++ return CC_PC_FF_PPPPID; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_UDP): ++ switch (field.udp) ++ { ++ case (NET_HEADER_FIELD_UDP_PORT_SRC): ++ return CC_PC_FF_L4PSRC; ++ ++ case (NET_HEADER_FIELD_UDP_PORT_DST): ++ return CC_PC_FF_L4PDST; ++ ++ case (NET_HEADER_FIELD_UDP_PORT_DST | NET_HEADER_FIELD_UDP_PORT_SRC): ++ return CC_PC_FF_L4PSRC_L4PDST; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++} ++ ++static uint8_t GetPrParseCode(e_NetHeaderType hdr, ++ e_FmPcdHdrIndex hdrIndex, ++ uint32_t offset, ++ bool glblMask, ++ uint8_t *parseArrayOffset) ++{ ++ bool offsetRelevant = FALSE; ++ ++ if (offset) ++ offsetRelevant = TRUE; ++ ++ switch (hdr) ++ { ++ case (HEADER_TYPE_NONE): ++ ASSERT_COND(FALSE); ++ return CC_PC_ILLEGAL; ++ ++ case (HEADER_TYPE_ETH): ++ *parseArrayOffset = (uint8_t)CC_PC_PR_ETH_OFFSET; ++ break; ++ ++ case (HEADER_TYPE_USER_DEFINED_SHIM1): ++ if (offset || glblMask) ++ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM1_OFFSET; ++ else ++ return CC_PC_PR_SHIM1; ++ break; ++ ++ case (HEADER_TYPE_USER_DEFINED_SHIM2): ++ if (offset || glblMask) ++ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM2_OFFSET; ++ else ++ return CC_PC_PR_SHIM2; ++ break; ++ ++ case (HEADER_TYPE_LLC_SNAP): ++ *parseArrayOffset = CC_PC_PR_USER_LLC_SNAP_OFFSET; ++ break; ++ ++ case (HEADER_TYPE_PPPoE): ++ *parseArrayOffset = CC_PC_PR_PPPOE_OFFSET; ++ break; ++ ++ case (HEADER_TYPE_MPLS): ++ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) ++ *parseArrayOffset = CC_PC_PR_MPLS1_OFFSET; ++ else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST) ++ *parseArrayOffset = CC_PC_PR_MPLS_LAST_OFFSET; ++ else ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index")); ++ return CC_PC_ILLEGAL; ++ } ++ break; ++ ++ case (HEADER_TYPE_IPv4): ++ case (HEADER_TYPE_IPv6): ++ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) ++ *parseArrayOffset = CC_PC_PR_IP1_OFFSET; ++ else if (hdrIndex == e_FM_PCD_HDR_INDEX_2) ++ *parseArrayOffset = CC_PC_PR_IP_LAST_OFFSET; ++ else ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header index")); ++ return CC_PC_ILLEGAL; ++ } ++ break; ++ ++ case (HEADER_TYPE_MINENCAP): ++ *parseArrayOffset = CC_PC_PR_MINENC_OFFSET; ++ break; ++ ++ case (HEADER_TYPE_GRE): ++ *parseArrayOffset = CC_PC_PR_GRE_OFFSET; ++ break; ++ ++ case (HEADER_TYPE_TCP): ++ case (HEADER_TYPE_UDP): ++ case (HEADER_TYPE_IPSEC_AH): ++ case (HEADER_TYPE_IPSEC_ESP): ++ case (HEADER_TYPE_DCCP): ++ case (HEADER_TYPE_SCTP): ++ *parseArrayOffset = CC_PC_PR_L4_OFFSET; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header for this type of operation")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ if (offsetRelevant) ++ return CC_PR_OFFSET; ++ else ++ return CC_PR_WITHOUT_OFFSET; ++} ++ ++static uint8_t GetFieldParseCode(e_NetHeaderType hdr, ++ t_FmPcdFields field, ++ uint32_t offset, ++ uint8_t *parseArrayOffset, ++ e_FmPcdHdrIndex hdrIndex) ++{ ++ bool offsetRelevant = FALSE; ++ ++ if (offset) ++ offsetRelevant = TRUE; ++ ++ switch (hdr) ++ { ++ case (HEADER_TYPE_NONE): ++ ASSERT_COND(FALSE); ++ case (HEADER_TYPE_ETH): ++ switch (field.eth) ++ { ++ case (NET_HEADER_FIELD_ETH_TYPE): ++ *parseArrayOffset = CC_PC_PR_ETYPE_LAST_OFFSET; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ break; ++ ++ case (HEADER_TYPE_VLAN): ++ switch (field.vlan) ++ { ++ case (NET_HEADER_FIELD_VLAN_TCI): ++ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) ++ *parseArrayOffset = CC_PC_PR_VLAN1_OFFSET; ++ else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST) ++ *parseArrayOffset = CC_PC_PR_VLAN2_OFFSET; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal header ")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ if (offsetRelevant) ++ return CC_PR_OFFSET; ++ else ++ return CC_PR_WITHOUT_OFFSET; ++} ++ ++static void FillAdOfTypeResult(t_Handle h_Ad, ++ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams, ++ t_FmPcd *p_FmPcd, ++ t_FmPcdCcNextEngineParams *p_CcNextEngineParams) ++{ ++ t_AdOfTypeResult *p_AdResult = (t_AdOfTypeResult *)h_Ad; ++ t_Handle h_TmpAd; ++ uint32_t tmp = 0, tmpNia = 0; ++ uint16_t profileId; ++ t_Handle p_AdNewPtr = NULL; ++ ++ /* There are 3 cases handled in this routine of building a "result" type AD. ++ * Case 1: No Manip. The action descriptor is built within the match table. ++ * Case 2: Manip exists. A new AD is created - p_AdNewPtr. It is initialized ++ * either in the FmPcdManipUpdateAdResultForCc routine or it was already ++ * initialized and returned here. ++ * p_AdResult (within the match table) will be initialized after ++ * this routine returns and point to the existing AD. ++ * Case 3: Manip exists. The action descriptor is built within the match table. ++ * FmPcdManipUpdateAdResultForCc returns a NULL p_AdNewPtr. ++ * ++ * If statistics were enabled and the statistics mode of this node requires ++ * a statistics Ad, it will be placed after the result Ad and before the ++ * manip Ad, if manip Ad exists here. ++ */ ++ ++ /* As default, the "new" ptr is the current one. i.e. the content of the result ++ * AD will be written into the match table itself (case (1))*/ ++ p_AdNewPtr = p_AdResult; ++ ++ /* Initialize an action descriptor, if current statistics mode requires an Ad */ ++ if (p_FmPcdCcStatsParams) ++ { ++ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsAd); ++ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsCounters); ++ ++ /* Swapping addresses between statistics Ad and the current lookup AD addresses */ ++ h_TmpAd = p_FmPcdCcStatsParams->h_StatsAd; ++ p_FmPcdCcStatsParams->h_StatsAd = h_Ad; ++ h_Ad = h_TmpAd; ++ ++ p_AdNewPtr = h_Ad; ++ p_AdResult = h_Ad; ++ ++ /* Init statistics Ad and connect current lookup AD as 'next action' from statistics Ad */ ++ UpdateStatsAd(p_FmPcdCcStatsParams, ++ h_Ad, ++ p_FmPcd->physicalMuramBase); ++ } ++ ++ /* Create manip and return p_AdNewPtr to either a new descriptor or NULL */ ++ if (p_CcNextEngineParams->h_Manip) ++ FmPcdManipUpdateAdResultForCc(p_CcNextEngineParams->h_Manip, ++ p_CcNextEngineParams, ++ h_Ad, ++ &p_AdNewPtr); ++ ++ /* if (p_AdNewPtr = NULL) --> Done. (case (3)) */ ++ if (p_AdNewPtr) ++ { ++ /* case (1) and (2) */ ++ switch (p_CcNextEngineParams->nextEngine) ++ { ++ case (e_FM_PCD_DONE): ++ if (p_CcNextEngineParams->params.enqueueParams.action == e_FM_PCD_ENQ_FRAME) ++ { ++ if (p_CcNextEngineParams->params.enqueueParams.overrideFqid) ++ { ++ tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE; ++ tmp |= p_CcNextEngineParams->params.enqueueParams.newFqid; ++#if (DPAA_VERSION >= 11) ++ tmp |= (p_CcNextEngineParams->params.enqueueParams.newRelativeStorageProfileId & FM_PCD_AD_RESULT_VSP_MASK) << FM_PCD_AD_RESULT_VSP_SHIFT; ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ else ++ { ++ tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE; ++ tmp |= FM_PCD_AD_RESULT_PLCR_DIS; ++ } ++ } ++ ++ if (p_CcNextEngineParams->params.enqueueParams.action == e_FM_PCD_DROP_FRAME) ++ tmpNia |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd); ++ else ++ tmpNia |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd); ++ break; ++ ++ case (e_FM_PCD_KG): ++ if (p_CcNextEngineParams->params.kgParams.overrideFqid) ++ { ++ tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE; ++ tmp |= p_CcNextEngineParams->params.kgParams.newFqid; ++#if (DPAA_VERSION >= 11) ++ tmp |= (p_CcNextEngineParams->params.kgParams.newRelativeStorageProfileId & FM_PCD_AD_RESULT_VSP_MASK) << FM_PCD_AD_RESULT_VSP_SHIFT; ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ else ++ { ++ tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE; ++ tmp |= FM_PCD_AD_RESULT_PLCR_DIS; ++ } ++ tmpNia = NIA_KG_DIRECT; ++ tmpNia |= NIA_ENG_KG; ++ tmpNia |= NIA_KG_CC_EN; ++ tmpNia |= FmPcdKgGetSchemeId(p_CcNextEngineParams->params.kgParams.h_DirectScheme); ++ break; ++ ++ case (e_FM_PCD_PLCR): ++ tmp = 0; ++ if (p_CcNextEngineParams->params.plcrParams.overrideParams) ++ { ++ tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE; ++ ++ /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */ ++ if (p_CcNextEngineParams->params.plcrParams.sharedProfile) ++ { ++ tmpNia |= NIA_PLCR_ABSOLUTE; ++ FmPcdPlcrGetAbsoluteIdByProfileParams((t_Handle)p_FmPcd, ++ e_FM_PCD_PLCR_SHARED, ++ NULL, ++ p_CcNextEngineParams->params.plcrParams.newRelativeProfileId, ++ &profileId); ++ } ++ else ++ profileId = p_CcNextEngineParams->params.plcrParams.newRelativeProfileId; ++ ++ tmp |= p_CcNextEngineParams->params.plcrParams.newFqid; ++#if (DPAA_VERSION >= 11) ++ tmp |= (p_CcNextEngineParams->params.plcrParams.newRelativeStorageProfileId & FM_PCD_AD_RESULT_VSP_MASK)<< FM_PCD_AD_RESULT_VSP_SHIFT; ++#endif /* (DPAA_VERSION >= 11) */ ++ WRITE_UINT32(p_AdResult->plcrProfile,(uint32_t)((uint32_t)profileId << FM_PCD_AD_PROFILEID_FOR_CNTRL_SHIFT)); ++ } ++ else ++ tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE; ++ ++ tmpNia |= NIA_ENG_PLCR | p_CcNextEngineParams->params.plcrParams.newRelativeProfileId; ++ break; ++ ++ default: ++ return; ++ } ++ WRITE_UINT32(p_AdResult->fqid, tmp); ++ ++ if (p_CcNextEngineParams->h_Manip) ++ { ++ tmp = GET_UINT32(p_AdResult->plcrProfile); ++ tmp |= (uint32_t)(XX_VirtToPhys(p_AdNewPtr) - (p_FmPcd->physicalMuramBase)) >> 4; ++ WRITE_UINT32(p_AdResult->plcrProfile, tmp); ++ ++ tmpNia |= FM_PCD_AD_RESULT_EXTENDED_MODE; ++ tmpNia |= FM_PCD_AD_RESULT_NADEN; ++ } ++ ++#if (DPAA_VERSION >= 11) ++ tmpNia |= FM_PCD_AD_RESULT_NO_OM_VSPE; ++#endif /* (DPAA_VERSION >= 11) */ ++ WRITE_UINT32(p_AdResult->nia, tmpNia); ++ } ++} ++ ++static t_Error CcUpdateParams(t_Handle h_FmPcd, ++ t_Handle h_PcdParams, ++ t_Handle h_FmPort, ++ t_Handle h_FmTree, ++ bool validate) ++{ ++ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *) h_FmTree; ++ ++ return CcUpdateParam(h_FmPcd, ++ h_PcdParams, ++ h_FmPort, ++ p_CcTree->keyAndNextEngineParams, ++ p_CcTree->numOfEntries, ++ UINT_TO_PTR(p_CcTree->ccTreeBaseAddr), ++ validate, ++ 0, ++ h_FmTree, ++ FALSE); ++} ++ ++ ++static void ReleaseNewNodeCommonPart(t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo) ++{ ++ if (p_AdditionalInfo->p_AdTableNew) ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(((t_FmPcdCcNode *)(p_AdditionalInfo->h_CurrentNode))->h_FmPcd), ++ p_AdditionalInfo->p_AdTableNew); ++ ++ if (p_AdditionalInfo->p_KeysMatchTableNew) ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(((t_FmPcdCcNode *)(p_AdditionalInfo->h_CurrentNode))->h_FmPcd), ++ p_AdditionalInfo->p_KeysMatchTableNew); ++} ++ ++static t_Error UpdateGblMask(t_FmPcdCcNode *p_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Mask) ++{ ++ uint8_t prvGlblMaskSize = p_CcNode->glblMaskSize; ++ ++ if (p_Mask && ++ !p_CcNode->glblMaskUpdated && ++ (keySize <= 4) && ++ !p_CcNode->lclMask) ++ { ++ memcpy(p_CcNode->p_GlblMask, p_Mask, (sizeof(uint8_t))*keySize); ++ p_CcNode->glblMaskUpdated = TRUE; ++ p_CcNode->glblMaskSize = 4; ++ } ++ else if (p_Mask && ++ (keySize <= 4) && ++ !p_CcNode->lclMask) ++ { ++ if (memcmp(p_CcNode->p_GlblMask, p_Mask, keySize) != 0) ++ { ++ p_CcNode->lclMask = TRUE; ++ p_CcNode->glblMaskSize = 0; ++ } ++ } ++ else if (!p_Mask && p_CcNode->glblMaskUpdated && (keySize <= 4)) ++ { ++ uint32_t tmpMask = 0xffffffff; ++ if (memcmp(p_CcNode->p_GlblMask, &tmpMask, 4) != 0) ++ { ++ p_CcNode->lclMask = TRUE; ++ p_CcNode->glblMaskSize = 0; ++ } ++ } ++ else if (p_Mask) ++ { ++ p_CcNode->lclMask = TRUE; ++ p_CcNode->glblMaskSize = 0; ++ } ++ ++ /* In static mode (maxNumOfKeys > 0), local mask is supported ++ only is mask support was enabled at initialization */ ++ if (p_CcNode->maxNumOfKeys && (!p_CcNode->maskSupport) && p_CcNode->lclMask) ++ { ++ p_CcNode->lclMask = FALSE; ++ p_CcNode->glblMaskSize = prvGlblMaskSize; ++ return ERROR_CODE(E_NOT_SUPPORTED); ++ } ++ ++ return E_OK; ++} ++ ++static __inline__ t_Handle GetNewAd(t_Handle h_FmPcdCcNodeOrTree, bool isTree) ++{ ++ t_FmPcd *p_FmPcd; ++ t_Handle h_Ad; ++ ++ if (isTree) ++ p_FmPcd = (t_FmPcd *)(((t_FmPcdCcTree *)h_FmPcdCcNodeOrTree)->h_FmPcd); ++ else ++ p_FmPcd = (t_FmPcd *)(((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->h_FmPcd); ++ ++ if ((isTree && p_FmPcd->p_CcShadow) || ++ (!isTree && ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->maxNumOfKeys)) ++ { ++ /* The allocated shadow is divided as follows: ++ 0 . . . 16 . . . ++ --------------------------------------------------- ++ | Shadow | Shadow Keys | Shadow Next | ++ | Ad | Match Table | Engine Table | ++ | (16 bytes) | (maximal size) | (maximal size) | ++ --------------------------------------------------- ++ */ ++ if (!p_FmPcd->p_CcShadow) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated")); ++ return NULL; ++ } ++ ++ h_Ad = p_FmPcd->p_CcShadow; ++ } ++ else ++ { ++ h_Ad = (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd), ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!h_Ad) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptor")); ++ return NULL; ++ } ++ } ++ ++ return h_Ad; ++} ++ ++static t_Error BuildNewNodeCommonPart(t_FmPcdCcNode *p_CcNode, ++ int *size, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ if (p_CcNode->lclMask) ++ *size = 2 * p_CcNode->ccKeySizeAccExtraction; ++ else ++ *size = p_CcNode->ccKeySizeAccExtraction; ++ ++ if (p_CcNode->maxNumOfKeys == 0) ++ { ++ p_AdditionalInfo->p_AdTableNew = ++ (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd), ++ (uint32_t)( (p_AdditionalInfo->numOfKeys+1) * FM_PCD_CC_AD_ENTRY_SIZE), ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_AdditionalInfo->p_AdTableNew) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptors table")); ++ ++ p_AdditionalInfo->p_KeysMatchTableNew = ++ (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd), ++ (uint32_t)(*size * sizeof(uint8_t) * (p_AdditionalInfo->numOfKeys + 1)), ++ FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN); ++ if (!p_AdditionalInfo->p_KeysMatchTableNew) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_AdditionalInfo->p_AdTableNew); ++ p_AdditionalInfo->p_AdTableNew = NULL; ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node key match table")); ++ } ++ ++ IOMemSet32((uint8_t*)p_AdditionalInfo->p_AdTableNew, 0, (uint32_t)((p_AdditionalInfo->numOfKeys+1) * FM_PCD_CC_AD_ENTRY_SIZE)); ++ IOMemSet32((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0, *size * sizeof(uint8_t) * (p_AdditionalInfo->numOfKeys + 1)); ++ } ++ else ++ { ++ /* The allocated shadow is divided as follows: ++ 0 . . . 16 . . . ++ --------------------------------------------------- ++ | Shadow | Shadow Keys | Shadow Next | ++ | Ad | Match Table | Engine Table | ++ | (16 bytes) | (maximal size) | (maximal size) | ++ --------------------------------------------------- ++ */ ++ ++ if (!p_FmPcd->p_CcShadow) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated")); ++ ++ p_AdditionalInfo->p_KeysMatchTableNew = PTR_MOVE(p_FmPcd->p_CcShadow, FM_PCD_CC_AD_ENTRY_SIZE); ++ p_AdditionalInfo->p_AdTableNew = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, p_CcNode->keysMatchTableMaxSize); ++ ++ IOMemSet32((uint8_t*)p_AdditionalInfo->p_AdTableNew, 0, (uint32_t)((p_CcNode->maxNumOfKeys + 1) * FM_PCD_CC_AD_ENTRY_SIZE)); ++ IOMemSet32((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0, (*size) * sizeof(uint8_t) * (p_CcNode->maxNumOfKeys)); ++ } ++ ++ p_AdditionalInfo->p_AdTableOld = p_CcNode->h_AdTable; ++ p_AdditionalInfo->p_KeysMatchTableOld = p_CcNode->h_KeysMatchTable; ++ ++ return E_OK; ++} ++ ++static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine(t_Handle h_FmPcd, ++ t_FmPcdCcNode *p_CcNode, ++ uint16_t keyIndex, ++ t_FmPcdCcKeyParams *p_KeyParams, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo, ++ bool add) ++{ ++ t_Error err = E_OK; ++ t_Handle p_AdTableNewTmp, p_KeysMatchTableNewTmp; ++ t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp; ++ int size; ++ int i = 0, j = 0; ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t requiredAction = 0; ++ bool prvLclMask; ++ t_CcNodeInformation *p_CcNodeInformation; ++ t_FmPcdCcStatsParams statsParams = {0}; ++ t_List *p_Pos; ++ t_FmPcdStatsObj *p_StatsObj; ++ ++ /* Check that new NIA is legal */ ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_KeyParams->ccNextEngineParams, ++ p_CcNode->statisticsMode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ prvLclMask = p_CcNode->lclMask; ++ ++ /* Check that new key is not require update of localMask */ ++ err = UpdateGblMask(p_CcNode, ++ p_CcNode->ccKeySizeAccExtraction, ++ p_KeyParams->p_Mask); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ /* Update internal data structure with new next engine for the given index */ ++ memcpy(&p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams, ++ &p_KeyParams->ccNextEngineParams, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].key, ++ p_KeyParams->p_Key, ++ p_CcNode->userSizeOfExtraction); ++ ++ if ((p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ && p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip) ++ { ++ err = AllocAndFillAdForContLookupManip(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ if (p_KeyParams->p_Mask) ++ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask, ++ p_KeyParams->p_Mask, ++ p_CcNode->userSizeOfExtraction); ++ else ++ memset(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask, ++ 0xFF, ++ p_CcNode->userSizeOfExtraction); ++ ++ /* Update numOfKeys */ ++ if (add) ++ p_AdditionalInfo->numOfKeys = (uint8_t)(p_CcNode->numOfKeys + 1); ++ else ++ p_AdditionalInfo->numOfKeys = (uint8_t)p_CcNode->numOfKeys; ++ ++ /* Allocate new tables in MURAM: keys match table and action descriptors table */ ++ err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /* Check that manip is legal and what requiredAction is necessary for this manip */ ++ if (p_KeyParams->ccNextEngineParams.h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine(&p_KeyParams->ccNextEngineParams,&requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction = requiredAction; ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction |= UPDATE_CC_WITH_TREE; ++ ++ /* Update new Ad and new Key Table according to new requirement */ ++ i = 0; ++ for (j = 0; j < p_AdditionalInfo->numOfKeys; j++) ++ { ++ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j*FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ if (j == keyIndex) ++ { ++ if (p_KeyParams->ccNextEngineParams.statisticsEn) ++ { ++ /* Allocate a statistics object that holds statistics AD and counters. ++ - For added key - New statistics AD and counters pointer need to be allocated ++ new statistics object. If statistics were enabled, we need to replace the ++ existing descriptor with a new descriptor with nullified counters. ++ */ ++ p_StatsObj = GetStatsObj(p_CcNode); ++ ASSERT_COND(p_StatsObj); ++ ++ /* Store allocated statistics object */ ++ ASSERT_COND(keyIndex < CC_MAX_NUM_OF_KEYS); ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = p_StatsObj; ++ ++ statsParams.h_StatsAd = p_StatsObj->h_StatsAd; ++ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; ++#if (DPAA_VERSION >= 11) ++ statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs; ++ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* Building action descriptor for the received new key */ ++ NextStepAd(p_AdTableNewTmp, ++ &statsParams, ++ &p_KeyParams->ccNextEngineParams, ++ p_FmPcd); ++ } ++ else ++ { ++ /* Building action descriptor for the received new key */ ++ NextStepAd(p_AdTableNewTmp, ++ NULL, ++ &p_KeyParams->ccNextEngineParams, ++ p_FmPcd); ++ } ++ ++ /* Copy the received new key into keys match table */ ++ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j*size*sizeof(uint8_t)); ++ ++ Mem2IOCpy32((void*)p_KeysMatchTableNewTmp, p_KeyParams->p_Key, p_CcNode->userSizeOfExtraction); ++ ++ /* Update mask for the received new key */ ++ if (p_CcNode->lclMask) ++ { ++ if (p_KeyParams->p_Mask) ++ { ++ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ p_KeyParams->p_Mask, ++ p_CcNode->userSizeOfExtraction); ++ } ++ else if (p_CcNode->ccKeySizeAccExtraction > 4) ++ { ++ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ 0xff, ++ p_CcNode->userSizeOfExtraction); ++ } ++ else ++ { ++ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ p_CcNode->p_GlblMask, ++ p_CcNode->userSizeOfExtraction); ++ } ++ } ++ ++ /* If key modification requested, the old entry is omitted and replaced by the new parameters */ ++ if (!add) ++ i++; ++ } ++ else ++ { ++ /* Copy existing action descriptors to the newly allocated Ad table */ ++ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Copy existing keys and their masks to the newly allocated keys match table */ ++ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t)); ++ p_KeysMatchTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableOld, i * size * sizeof(uint8_t)); ++ ++ if (p_CcNode->lclMask) ++ { ++ if (prvLclMask) ++ { ++ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction), ++ PTR_MOVE(p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction), ++ p_CcNode->ccKeySizeAccExtraction); ++ } ++ else ++ { ++ p_KeysMatchTableOldTmp = PTR_MOVE(p_CcNode->h_KeysMatchTable, ++ i * p_CcNode->ccKeySizeAccExtraction*sizeof(uint8_t)); ++ ++ if (p_CcNode->ccKeySizeAccExtraction > 4) ++ { ++ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ 0xff, ++ p_CcNode->userSizeOfExtraction); ++ } ++ else ++ { ++ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ p_CcNode->p_GlblMask, ++ p_CcNode->userSizeOfExtraction); ++ } ++ } ++ } ++ ++ IO2IOCpy32(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction); ++ ++ i++; ++ } ++ } ++ ++ /* Miss action descriptor */ ++ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j * FM_PCD_CC_AD_ENTRY_SIZE); ++ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i * FM_PCD_CC_AD_ENTRY_SIZE); ++ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ if (!LIST_IsEmpty(&p_CcNode->ccTreesLst)) ++ { ++ LIST_FOR_EACH(p_Pos, &p_CcNode->ccTreesLst) ++ { ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ ASSERT_COND(p_CcNodeInformation->h_CcNode); ++ /* Update the manipulation which has to be updated from parameters of the port */ ++ /* It's has to be updated with restrictions defined in the function */ ++ err = SetRequiredAction(p_CcNode->h_FmPcd, ++ p_CcNode->shadowAction | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction, ++ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], ++ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, keyIndex*FM_PCD_CC_AD_ENTRY_SIZE), ++ 1, ++ p_CcNodeInformation->h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ err = CcUpdateParam(p_CcNode->h_FmPcd, ++ NULL, ++ NULL, ++ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], ++ 1, ++ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, keyIndex*FM_PCD_CC_AD_ENTRY_SIZE), ++ TRUE, ++ p_CcNodeInformation->index, ++ p_CcNodeInformation->h_CcNode, ++ TRUE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ } ++ ++ if (p_CcNode->lclMask) ++ memset(p_CcNode->p_GlblMask, 0xff, CC_GLBL_MASK_SIZE * sizeof(uint8_t)); ++ ++ if (p_KeyParams->ccNextEngineParams.nextEngine == e_FM_PCD_CC) ++ p_AdditionalInfo->h_NodeForAdd = p_KeyParams->ccNextEngineParams.params.ccParams.h_CcNode; ++ if (p_KeyParams->ccNextEngineParams.h_Manip) ++ p_AdditionalInfo->h_ManipForAdd = p_KeyParams->ccNextEngineParams.h_Manip; ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_KeyParams->ccNextEngineParams.nextEngine == e_FM_PCD_FR) && ++ (p_KeyParams->ccNextEngineParams.params.frParams.h_FrmReplic)) ++ p_AdditionalInfo->h_FrmReplicForAdd = p_KeyParams->ccNextEngineParams.params.frParams.h_FrmReplic; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (!add) ++ { ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ p_AdditionalInfo->h_NodeForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode; ++ ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip) ++ p_AdditionalInfo->h_ManipForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip; ++ ++ /* If statistics were previously enabled, store the old statistics object to be released */ ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ { ++ p_AdditionalInfo->p_StatsObjForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj; ++ } ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_FR) && ++ (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic)) ++ p_AdditionalInfo->h_FrmReplicForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic; ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ return E_OK; ++} ++ ++static t_Error BuildNewNodeRemoveKey(t_FmPcdCcNode *p_CcNode, ++ uint16_t keyIndex, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo) ++{ ++ int i = 0, j = 0; ++ t_Handle p_AdTableNewTmp,p_KeysMatchTableNewTmp; ++ t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp; ++ int size; ++ t_Error err = E_OK; ++ ++ /*save new numOfKeys*/ ++ p_AdditionalInfo->numOfKeys = (uint16_t)(p_CcNode->numOfKeys - 1); ++ ++ /*function which allocates in the memory new KeyTbl, AdTbl*/ ++ err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /*update new Ad and new Key Table according to new requirement*/ ++ for (i=0, j=0; jnumOfKeys; i++, j++) ++ { ++ if (j == keyIndex) ++ { ++ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE); ++ j++; ++ } ++ if (j == p_CcNode->numOfKeys) ++ break; ++ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, i * FM_PCD_CC_AD_ENTRY_SIZE); ++ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE); ++ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ p_KeysMatchTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableOld, j * size * sizeof(uint8_t)); ++ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, i * size * sizeof(uint8_t)); ++ IO2IOCpy32(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, size * sizeof(uint8_t)); ++ } ++ ++ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, i * FM_PCD_CC_AD_ENTRY_SIZE); ++ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE); ++ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ p_AdditionalInfo->h_NodeForRmv = ++ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode; ++ ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip) ++ p_AdditionalInfo->h_ManipForRmv = ++ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip; ++ ++ /* If statistics were previously enabled, store the old statistics object to be released */ ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ { ++ p_AdditionalInfo->p_StatsObjForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj; ++ } ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_FR) && ++ (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic)) ++ p_AdditionalInfo->h_FrmReplicForRmv = ++ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ return E_OK; ++} ++ ++static t_Error BuildNewNodeModifyKey(t_FmPcdCcNode *p_CcNode, ++ uint16_t keyIndex, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ t_Error err = E_OK; ++ t_Handle p_AdTableNewTmp, p_KeysMatchTableNewTmp; ++ t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp; ++ int size; ++ int i = 0, j = 0; ++ bool prvLclMask; ++ t_FmPcdStatsObj *p_StatsObj, tmpStatsObj; ++ p_AdditionalInfo->numOfKeys = p_CcNode->numOfKeys; ++ ++ prvLclMask = p_CcNode->lclMask; ++ ++ /* Check that new key is not require update of localMask */ ++ err = UpdateGblMask(p_CcNode, ++ p_CcNode->ccKeySizeAccExtraction, ++ p_Mask); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ /* Update internal data structure with new next engine for the given index */ ++ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].key, ++ p_Key, ++ p_CcNode->userSizeOfExtraction); ++ ++ if (p_Mask) ++ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask, ++ p_Mask, ++ p_CcNode->userSizeOfExtraction); ++ else ++ memset(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask, ++ 0xFF, ++ p_CcNode->userSizeOfExtraction); ++ ++ /*function which build in the memory new KeyTbl, AdTbl*/ ++ err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /*fill the New AdTable and New KeyTable*/ ++ for (j=0, i=0; jnumOfKeys; j++, i++) ++ { ++ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j*FM_PCD_CC_AD_ENTRY_SIZE); ++ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ if (j == keyIndex) ++ { ++ ASSERT_COND(keyIndex < CC_MAX_NUM_OF_KEYS); ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ { ++ /* As statistics were enabled, we need to update the existing ++ statistics descriptor with a new nullified counters. */ ++ p_StatsObj = GetStatsObj(p_CcNode); ++ ASSERT_COND(p_StatsObj); ++ ++ SetStatsCounters(p_AdTableNewTmp, ++ (uint32_t)((XX_VirtToPhys(p_StatsObj->h_StatsCounters) - p_FmPcd->physicalMuramBase))); ++ ++ tmpStatsObj.h_StatsAd = p_StatsObj->h_StatsAd; ++ tmpStatsObj.h_StatsCounters = p_StatsObj->h_StatsCounters; ++ ++ /* As we need to replace only the counters, we build a new statistics ++ object that holds the old AD and the new counters - this will be the ++ currently used statistics object. ++ The newly allocated AD is not required and may be released back to ++ the available objects with the previous counters pointer. */ ++ p_StatsObj->h_StatsAd = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd; ++ ++ p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd = tmpStatsObj.h_StatsAd; ++ ++ /* Store allocated statistics object */ ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = p_StatsObj; ++ ++ /* As statistics were previously enabled, store the old statistics object to be released */ ++ p_AdditionalInfo->p_StatsObjForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj; ++ } ++ ++ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t)); ++ ++ Mem2IOCpy32(p_KeysMatchTableNewTmp, p_Key, p_CcNode->userSizeOfExtraction); ++ ++ if (p_CcNode->lclMask) ++ { ++ if (p_Mask) ++ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ p_Mask, ++ p_CcNode->userSizeOfExtraction); ++ else if (p_CcNode->ccKeySizeAccExtraction > 4) ++ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ 0xff, ++ p_CcNode->userSizeOfExtraction); ++ else ++ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ p_CcNode->p_GlblMask, ++ p_CcNode->userSizeOfExtraction); ++ } ++ } ++ else ++ { ++ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t)); ++ p_KeysMatchTableOldTmp = PTR_MOVE(p_CcNode->h_KeysMatchTable, i * size * sizeof(uint8_t)); ++ ++ if (p_CcNode->lclMask) ++ { ++ if (prvLclMask) ++ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction), ++ PTR_MOVE(p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction), ++ p_CcNode->userSizeOfExtraction); ++ else ++ { ++ p_KeysMatchTableOldTmp = PTR_MOVE(p_CcNode->h_KeysMatchTable, i * p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t)); ++ ++ if (p_CcNode->ccKeySizeAccExtraction > 4) ++ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ 0xff, ++ p_CcNode->userSizeOfExtraction); ++ else ++ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction), ++ p_CcNode->p_GlblMask, ++ p_CcNode->userSizeOfExtraction); ++ } ++ } ++ IO2IOCpy32((void*)p_KeysMatchTableNewTmp, ++ p_KeysMatchTableOldTmp, ++ p_CcNode->ccKeySizeAccExtraction); ++ } ++ } ++ ++ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j * FM_PCD_CC_AD_ENTRY_SIZE); ++ p_AdTableOldTmp = PTR_MOVE(p_CcNode->h_AdTable, i * FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ return E_OK; ++} ++ ++static t_Error BuildNewNodeModifyNextEngine(t_Handle h_FmPcd, ++ t_Handle h_FmPcdCcNodeOrTree, ++ uint16_t keyIndex, ++ t_FmPcdCcNextEngineParams *p_CcNextEngineParams, ++ t_List *h_OldLst, ++ t_List *h_NewLst, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo) ++{ ++ t_Error err = E_OK; ++ uint32_t requiredAction = 0; ++ t_List *p_Pos; ++ t_CcNodeInformation *p_CcNodeInformation, ccNodeInfo; ++ t_Handle p_Ad; ++ t_FmPcdCcNode *p_FmPcdCcNode1 = NULL; ++ t_FmPcdCcTree *p_FmPcdCcTree = NULL; ++ t_FmPcdStatsObj *p_StatsObj; ++ t_FmPcdCcStatsParams statsParams = {0}; ++ ++ ASSERT_COND(p_CcNextEngineParams); ++ ++ /* check that new NIA is legal */ ++ if (!p_AdditionalInfo->tree) ++ err = ValidateNextEngineParams(h_FmPcd, ++ p_CcNextEngineParams, ++ ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->statisticsMode); ++ else ++ /* Statistics are not supported for CC root */ ++ err = ValidateNextEngineParams(h_FmPcd, ++ p_CcNextEngineParams, ++ e_FM_PCD_CC_STATS_MODE_NONE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /* Update internal data structure for next engine per index (index - key) */ ++ memcpy(&p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams, ++ p_CcNextEngineParams, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ /* Check that manip is legal and what requiredAction is necessary for this manip */ ++ if (p_CcNextEngineParams->h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine(p_CcNextEngineParams, &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ if (!p_AdditionalInfo->tree) ++ { ++ p_FmPcdCcNode1 = (t_FmPcdCcNode *)h_FmPcdCcNodeOrTree; ++ p_AdditionalInfo->numOfKeys = p_FmPcdCcNode1->numOfKeys; ++ p_Ad = p_FmPcdCcNode1->h_AdTable; ++ ++ if (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ p_AdditionalInfo->h_NodeForRmv = p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode; ++ ++ if (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip) ++ p_AdditionalInfo->h_ManipForRmv = p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip; ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_FR) && ++ (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic)) ++ p_AdditionalInfo->h_FrmReplicForRmv = p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic; ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ else ++ { ++ p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcNodeOrTree; ++ p_Ad = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); ++ ++ if (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ p_AdditionalInfo->h_NodeForRmv = p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode; ++ ++ if (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip) ++ p_AdditionalInfo->h_ManipForRmv = p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip; ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_FR) && ++ (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic)) ++ p_AdditionalInfo->h_FrmReplicForRmv = p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic; ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_CC) ++ && p_CcNextEngineParams->h_Manip) ++ { ++ err = AllocAndFillAdForContLookupManip(p_CcNextEngineParams->params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ ASSERT_COND(p_Ad); ++ ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = PTR_MOVE(p_Ad, keyIndex * FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* If statistics were enabled, this Ad is the statistics Ad. Need to follow its ++ nextAction to retrieve the actual Nia-Ad. If statistics should remain enabled, ++ only the actual Nia-Ad should be modified. */ ++ if ((!p_AdditionalInfo->tree) && ++ (((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj) && ++ (p_CcNextEngineParams->statisticsEn)) ++ ccNodeInfo.h_CcNode = ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd; ++ ++ EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL); ++ ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ p_Ad = GetNewAd(h_FmPcdCcNodeOrTree, p_AdditionalInfo->tree); ++ if (!p_Ad) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptor")); ++ IOMemSet32((uint8_t *)p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* If statistics were not enabled before, but requested now - Allocate a statistics ++ object that holds statistics AD and counters. */ ++ if ((!p_AdditionalInfo->tree) && ++ (!((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj) && ++ (p_CcNextEngineParams->statisticsEn)) ++ { ++ p_StatsObj = GetStatsObj((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree); ++ ASSERT_COND(p_StatsObj); ++ ++ /* Store allocated statistics object */ ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = p_StatsObj; ++ ++ statsParams.h_StatsAd = p_StatsObj->h_StatsAd; ++ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; ++ ++#if (DPAA_VERSION >= 11) ++ statsParams.h_StatsFLRs = ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->h_StatsFLRs; ++ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ NextStepAd(p_Ad, ++ &statsParams, ++ p_CcNextEngineParams, ++ h_FmPcd); ++ } ++ else ++ NextStepAd(p_Ad, ++ NULL, ++ p_CcNextEngineParams, ++ h_FmPcd); ++ ++ ccNodeInfo.h_CcNode = p_Ad; ++ EnqueueNodeInfoToRelevantLst(h_NewLst, &ccNodeInfo, NULL); ++ ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction = requiredAction; ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction |= UPDATE_CC_WITH_TREE; ++ ++ if (!p_AdditionalInfo->tree) ++ { ++ ASSERT_COND(p_FmPcdCcNode1); ++ if (!LIST_IsEmpty(&p_FmPcdCcNode1->ccTreesLst)) ++ { ++ LIST_FOR_EACH(p_Pos, &p_FmPcdCcNode1->ccTreesLst) ++ { ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ ++ ASSERT_COND(p_CcNodeInformation->h_CcNode); ++ /* Update the manipulation which has to be updated from parameters of the port ++ it's has to be updated with restrictions defined in the function */ ++ ++ err = SetRequiredAction(p_FmPcdCcNode1->h_FmPcd, ++ p_FmPcdCcNode1->shadowAction | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction, ++ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], ++ p_Ad, ++ 1, ++ p_CcNodeInformation->h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ err = CcUpdateParam(p_FmPcdCcNode1->h_FmPcd, ++ NULL, ++ NULL, ++ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], ++ 1, ++ p_Ad, ++ TRUE, ++ p_CcNodeInformation->index, ++ p_CcNodeInformation->h_CcNode, ++ TRUE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ } ++ } ++ else ++ { ++ ASSERT_COND(p_FmPcdCcTree); ++ ++ err = SetRequiredAction(h_FmPcd, ++ p_FmPcdCcTree->requiredAction | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction, ++ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], ++ p_Ad, ++ 1, ++ (t_Handle)p_FmPcdCcTree); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ err = CcUpdateParam(h_FmPcd, ++ NULL, ++ NULL, ++ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], ++ 1, ++ p_Ad, ++ TRUE, ++ 0, ++ (t_Handle)p_FmPcdCcTree, TRUE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ if (p_CcNextEngineParams->nextEngine == e_FM_PCD_CC) ++ p_AdditionalInfo->h_NodeForAdd = p_CcNextEngineParams->params.ccParams.h_CcNode; ++ if (p_CcNextEngineParams->h_Manip) ++ p_AdditionalInfo->h_ManipForAdd = p_CcNextEngineParams->h_Manip; ++ ++ /* If statistics were previously enabled, but now are disabled, ++ store the old statistics object to be released */ ++ if ((!p_AdditionalInfo->tree) && ++ (((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj) && ++ (!p_CcNextEngineParams->statisticsEn)) ++ { ++ p_AdditionalInfo->p_StatsObjForRmv = ++ ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj; ++ ++ ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = NULL; ++ } ++#if (DPAA_VERSION >= 11) ++ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_FR) && ++ (p_CcNextEngineParams->params.frParams.h_FrmReplic)) ++ p_AdditionalInfo->h_FrmReplicForAdd = p_CcNextEngineParams->params.frParams.h_FrmReplic; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ return E_OK; ++} ++ ++static void UpdateAdPtrOfNodesWhichPointsOnCrntMdfNode(t_FmPcdCcNode *p_CrntMdfNode, ++ t_List *h_OldLst, ++ t_FmPcdCcNextEngineParams **p_NextEngineParams) ++{ ++ t_CcNodeInformation *p_CcNodeInformation; ++ t_FmPcdCcNode *p_NodePtrOnCurrentMdfNode = NULL; ++ t_List *p_Pos; ++ int i = 0; ++ t_Handle p_AdTablePtOnCrntCurrentMdfNode/*, p_AdTableNewModified*/; ++ t_CcNodeInformation ccNodeInfo; ++ ++ LIST_FOR_EACH(p_Pos, &p_CrntMdfNode->ccPrevNodesLst) ++ { ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ p_NodePtrOnCurrentMdfNode = (t_FmPcdCcNode *)p_CcNodeInformation->h_CcNode; ++ ++ ASSERT_COND(p_NodePtrOnCurrentMdfNode); ++ ++ /* Search in the previous node which exact index points on this current modified node for getting AD */ ++ for (i = 0; i < p_NodePtrOnCurrentMdfNode->numOfKeys + 1; i++) ++ { ++ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ { ++ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode == (t_Handle)p_CrntMdfNode) ++ { ++ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip) ++ p_AdTablePtOnCrntCurrentMdfNode = p_CrntMdfNode->h_Ad; ++ else if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].p_StatsObj) ++ p_AdTablePtOnCrntCurrentMdfNode = ++ p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].p_StatsObj->h_StatsAd; ++ else ++ p_AdTablePtOnCrntCurrentMdfNode = ++ PTR_MOVE(p_NodePtrOnCurrentMdfNode->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = p_AdTablePtOnCrntCurrentMdfNode; ++ EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL); ++ ++ if (!(*p_NextEngineParams)) ++ *p_NextEngineParams = &p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams; ++ } ++ } ++ } ++ ++ ASSERT_COND(i != p_NodePtrOnCurrentMdfNode->numOfKeys); ++ } ++} ++ ++static void UpdateAdPtrOfTreesWhichPointsOnCrntMdfNode(t_FmPcdCcNode *p_CrntMdfNode, ++ t_List *h_OldLst, ++ t_FmPcdCcNextEngineParams **p_NextEngineParams) ++{ ++ t_CcNodeInformation *p_CcNodeInformation; ++ t_FmPcdCcTree *p_TreePtrOnCurrentMdfNode = NULL; ++ t_List *p_Pos; ++ int i = 0; ++ t_Handle p_AdTableTmp; ++ t_CcNodeInformation ccNodeInfo; ++ ++ LIST_FOR_EACH(p_Pos, &p_CrntMdfNode->ccTreeIdLst) ++ { ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ p_TreePtrOnCurrentMdfNode = (t_FmPcdCcTree *)p_CcNodeInformation->h_CcNode; ++ ++ ASSERT_COND(p_TreePtrOnCurrentMdfNode); ++ ++ /*search in the trees which exact index points on this current modified node for getting AD */ ++ for (i = 0; i < p_TreePtrOnCurrentMdfNode->numOfEntries; i++) ++ { ++ if (p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ { ++ if (p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode == (t_Handle)p_CrntMdfNode) ++ { ++ p_AdTableTmp = UINT_TO_PTR(p_TreePtrOnCurrentMdfNode->ccTreeBaseAddr + i*FM_PCD_CC_AD_ENTRY_SIZE); ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = p_AdTableTmp; ++ EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL); ++ ++ if (!(*p_NextEngineParams)) ++ *p_NextEngineParams = &p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams; ++ } ++ } ++ } ++ ++ ASSERT_COND(i == p_TreePtrOnCurrentMdfNode->numOfEntries); ++ } ++} ++ ++static t_FmPcdModifyCcKeyAdditionalParams* ModifyKeyCommonPart1(t_Handle h_FmPcdCcNodeOrTree, ++ uint16_t keyIndex, ++ e_ModifyState modifyState, ++ bool ttlCheck, ++ bool hashCheck, ++ bool tree) ++{ ++ t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams; ++ int i = 0, j = 0; ++ bool wasUpdate = FALSE; ++ t_FmPcdCcNode *p_CcNode = NULL; ++ t_FmPcdCcTree *p_FmPcdCcTree; ++ uint16_t numOfKeys; ++ t_FmPcdCcKeyAndNextEngineParams *p_KeyAndNextEngineParams; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcdCcNodeOrTree, E_INVALID_HANDLE, NULL); ++ ++ p_KeyAndNextEngineParams = (t_FmPcdCcKeyAndNextEngineParams *)XX_Malloc(sizeof(t_FmPcdCcKeyAndNextEngineParams)*CC_MAX_NUM_OF_KEYS); ++ if (!p_KeyAndNextEngineParams) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Next engine and required action structure")); ++ return NULL; ++ } ++ memset(p_KeyAndNextEngineParams, 0, sizeof(t_FmPcdCcKeyAndNextEngineParams)*CC_MAX_NUM_OF_KEYS); ++ ++ if (!tree) ++ { ++ p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNodeOrTree; ++ numOfKeys = p_CcNode->numOfKeys; ++ ++ /* node has to be pointed by another node or tree */ ++ if (!LIST_NumOfObjs(&p_CcNode->ccPrevNodesLst) && ++ !LIST_NumOfObjs(&p_CcNode->ccTreeIdLst)) ++ { ++ XX_Free(p_KeyAndNextEngineParams); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("node has to be pointed by node or tree")); ++ return NULL; ++ } ++ ++ if (!LIST_NumOfObjs(&p_CcNode->ccTreesLst) || ++ (LIST_NumOfObjs(&p_CcNode->ccTreesLst) != 1)) ++ { ++ XX_Free(p_KeyAndNextEngineParams); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("node has to be belonging to some tree and only to one tree")); ++ return NULL; ++ } ++ ++ memcpy(p_KeyAndNextEngineParams, ++ p_CcNode->keyAndNextEngineParams, ++ CC_MAX_NUM_OF_KEYS * sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ ++ if (ttlCheck) ++ { ++ if ((p_CcNode->parseCode == CC_PC_FF_IPV4TTL) || ++ (p_CcNode->parseCode == CC_PC_FF_IPV6HOP_LIMIT)) ++ { ++ XX_Free(p_KeyAndNextEngineParams); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("nodeId of CC_PC_FF_IPV4TTL or CC_PC_FF_IPV6HOP_LIMIT can not be used for this operation")); ++ return NULL; ++ } ++ } ++ ++ if (hashCheck) ++ { ++ if (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED) ++ { ++ XX_Free(p_KeyAndNextEngineParams); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("nodeId of CC_PC_GENERIC_IC_HASH_INDEXED can not be used for this operation")); ++ return NULL; ++ } ++ } ++ } ++ else ++ { ++ p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcNodeOrTree; ++ numOfKeys = p_FmPcdCcTree->numOfEntries; ++ memcpy(p_KeyAndNextEngineParams, ++ p_FmPcdCcTree->keyAndNextEngineParams, ++ FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ } ++ ++ p_FmPcdModifyCcKeyAdditionalParams = ++ (t_FmPcdModifyCcKeyAdditionalParams *)XX_Malloc(sizeof(t_FmPcdModifyCcKeyAdditionalParams)); ++ if (!p_FmPcdModifyCcKeyAdditionalParams) ++ { ++ XX_Free(p_KeyAndNextEngineParams); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of internal data structure FAILED")); ++ return NULL; ++ } ++ memset(p_FmPcdModifyCcKeyAdditionalParams, 0, sizeof(t_FmPcdModifyCcKeyAdditionalParams)); ++ ++ p_FmPcdModifyCcKeyAdditionalParams->h_CurrentNode = h_FmPcdCcNodeOrTree; ++ p_FmPcdModifyCcKeyAdditionalParams->savedKeyIndex = keyIndex; ++ ++ while (i < numOfKeys) ++ { ++ if ((j == keyIndex) && !wasUpdate) ++ { ++ if (modifyState == e_MODIFY_STATE_ADD) ++ j++; ++ else if (modifyState == e_MODIFY_STATE_REMOVE) ++ i++; ++ wasUpdate = TRUE; ++ } ++ else ++ { ++ memcpy(&p_FmPcdModifyCcKeyAdditionalParams->keyAndNextEngineParams[j], ++ p_KeyAndNextEngineParams + i, ++ sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ i++; ++ j++; ++ } ++ } ++ ++ if (keyIndex == numOfKeys) ++ { ++ if (modifyState == e_MODIFY_STATE_ADD) ++ j++; ++ else if (modifyState == e_MODIFY_STATE_REMOVE) ++ i++; ++ } ++ ++ memcpy(&p_FmPcdModifyCcKeyAdditionalParams->keyAndNextEngineParams[j], ++ p_KeyAndNextEngineParams + numOfKeys, ++ sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ ++ XX_Free(p_KeyAndNextEngineParams); ++ ++ return p_FmPcdModifyCcKeyAdditionalParams; ++} ++ ++static t_Error UpdatePtrWhichPointOnCrntMdfNode(t_FmPcdCcNode *p_CcNode, ++ t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams, ++ t_List *h_OldLst, ++ t_List *h_NewLst) ++{ ++ t_FmPcdCcNextEngineParams *p_NextEngineParams = NULL; ++ t_CcNodeInformation ccNodeInfo = {0}; ++ t_Handle h_NewAd; ++ ++ /* Building a list of all action descriptors that point to the previous node */ ++ if (!LIST_IsEmpty(&p_CcNode->ccPrevNodesLst)) ++ UpdateAdPtrOfNodesWhichPointsOnCrntMdfNode(p_CcNode, h_OldLst, &p_NextEngineParams); ++ ++ if (!LIST_IsEmpty(&p_CcNode->ccTreeIdLst)) ++ UpdateAdPtrOfTreesWhichPointsOnCrntMdfNode(p_CcNode, h_OldLst, &p_NextEngineParams); ++ ++ /* This node must be found as next engine of one of its previous nodes or trees*/ ++ ASSERT_COND(p_NextEngineParams); ++ ++ /* Building a new action descriptor that points to the modified node */ ++ h_NewAd = GetNewAd(p_CcNode, FALSE); ++ if (!h_NewAd) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ IOMemSet32(h_NewAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ BuildNewAd(h_NewAd, ++ p_FmPcdModifyCcKeyAdditionalParams, ++ p_CcNode, ++ p_NextEngineParams); ++ ++ ccNodeInfo.h_CcNode = h_NewAd; ++ EnqueueNodeInfoToRelevantLst(h_NewLst, &ccNodeInfo, NULL); ++ ++ return E_OK; ++} ++ ++static void UpdateCcRootOwner(t_FmPcdCcTree *p_FmPcdCcTree, bool add) ++{ ++ ASSERT_COND(p_FmPcdCcTree); ++ ++ /* this routine must be protected by the calling routine! */ ++ ++ if (add) ++ p_FmPcdCcTree->owners++; ++ else ++ { ++ ASSERT_COND(p_FmPcdCcTree->owners); ++ p_FmPcdCcTree->owners--; ++ } ++} ++ ++static t_Error CheckAndSetManipParamsWithCcNodeParams(t_FmPcdCcNode *p_CcNode) ++{ ++ t_Error err = E_OK; ++ int i = 0; ++ ++ for (i = 0; i < p_CcNode->numOfKeys; i++) ++ { ++ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip) ++ { ++ err = FmPcdManipCheckParamsWithCcNodeParams(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip, ++ (t_Handle)p_CcNode); ++ if (err) ++ return err; ++ } ++ } ++ ++ return err; ++} ++static t_Error ValidateAndCalcStatsParams(t_FmPcdCcNode *p_CcNode, ++ t_FmPcdCcNodeParams *p_CcNodeParam, ++ uint32_t *p_NumOfRanges, ++ uint32_t *p_CountersArraySize) ++{ ++ e_FmPcdCcStatsMode statisticsMode = p_CcNode->statisticsMode; ++ ++ UNUSED(p_CcNodeParam); ++ ++ switch (statisticsMode) ++ { ++ case e_FM_PCD_CC_STATS_MODE_NONE: ++ return E_OK; ++ ++ case e_FM_PCD_CC_STATS_MODE_FRAME: ++ case e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME: ++ *p_NumOfRanges = 1; ++ *p_CountersArraySize = 2 * FM_PCD_CC_STATS_COUNTER_SIZE; ++ return E_OK; ++ ++#if (DPAA_VERSION >= 11) ++ case e_FM_PCD_CC_STATS_MODE_RMON: ++ { ++ uint16_t *p_FrameLengthRanges = p_CcNodeParam->keysParams.frameLengthRanges; ++ uint32_t i; ++ ++ if (p_FrameLengthRanges[0] <= 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Statistics mode")); ++ ++ if (p_FrameLengthRanges[0] == 0xFFFF) ++ { ++ *p_NumOfRanges = 1; ++ *p_CountersArraySize = 2 * FM_PCD_CC_STATS_COUNTER_SIZE; ++ return E_OK; ++ } ++ ++ for (i = 1; i < FM_PCD_CC_STATS_MAX_NUM_OF_FLR; i++) ++ { ++ if (p_FrameLengthRanges[i-1] >= p_FrameLengthRanges[i]) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("Frame length range must be larger at least by 1 from preceding range")); ++ ++ /* Stop when last range is reached */ ++ if (p_FrameLengthRanges[i] == 0xFFFF) ++ break; ++ } ++ ++ if ((i >= FM_PCD_CC_STATS_MAX_NUM_OF_FLR) || ++ (p_FrameLengthRanges[i] != 0xFFFF)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Last Frame length range must be 0xFFFF")); ++ ++ *p_NumOfRanges = i+1; ++ ++ /* Allocate an extra counter for byte count, as counters ++ array always begins with byte count */ ++ *p_CountersArraySize = (*p_NumOfRanges + 1) * FM_PCD_CC_STATS_COUNTER_SIZE; ++ ++ } ++ return E_OK; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Statistics mode")); ++ } ++} ++ ++static t_Error CheckParams(t_Handle h_FmPcd, ++ t_FmPcdCcNodeParams *p_CcNodeParam, ++ t_FmPcdCcNode *p_CcNode, ++ bool *isKeyTblAlloc) ++{ ++ int tmp = 0; ++ t_FmPcdCcKeyParams *p_KeyParams; ++ t_Error err; ++ uint32_t requiredAction = 0; ++ ++ /* Validate statistics parameters */ ++ err = ValidateAndCalcStatsParams(p_CcNode, ++ p_CcNodeParam, ++ &(p_CcNode->numOfStatsFLRs), ++ &(p_CcNode->countersArraySize)); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters")); ++ ++ /* Validate next engine parameters on Miss */ ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ p_CcNode->statisticsMode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("For this node MissNextEngineParams are not valid")); ++ ++ if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine(&p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ memcpy(&p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams, ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].requiredAction = requiredAction; ++ ++ if ((p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ && p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.h_Manip) ++ { ++ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++) ++ { ++ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp]; ++ ++ if (!p_KeyParams->p_Key) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_Key is not initialized")); ++ ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_KeyParams->ccNextEngineParams, ++ p_CcNode->statisticsMode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ err = UpdateGblMask(p_CcNode, ++ p_CcNodeParam->keysParams.keySize, ++ p_KeyParams->p_Mask); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ if (p_KeyParams->ccNextEngineParams.h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine(&p_KeyParams->ccNextEngineParams, &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ /* Store 'key' parameters - key, mask (if passed by the user) */ ++ memcpy(p_CcNode->keyAndNextEngineParams[tmp].key, p_KeyParams->p_Key, p_CcNodeParam->keysParams.keySize); ++ ++ if (p_KeyParams->p_Mask) ++ memcpy(p_CcNode->keyAndNextEngineParams[tmp].mask, ++ p_KeyParams->p_Mask, ++ p_CcNodeParam->keysParams.keySize); ++ else ++ memset((void *)(p_CcNode->keyAndNextEngineParams[tmp].mask), ++ 0xFF, ++ p_CcNodeParam->keysParams.keySize); ++ ++ /* Store next engine parameters */ ++ memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams, ++ &p_KeyParams->ccNextEngineParams, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction; ++ ++ if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip) ++ { ++ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ } ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (p_CcNode->maxNumOfKeys < p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Number of keys exceed the provided maximal number of keys")); ++ } ++ ++ *isKeyTblAlloc = TRUE; ++ ++ return E_OK; ++} ++ ++static t_Error Ipv4TtlOrIpv6HopLimitCheckParams(t_Handle h_FmPcd, ++ t_FmPcdCcNodeParams *p_CcNodeParam, ++ t_FmPcdCcNode *p_CcNode, ++ bool *isKeyTblAlloc) ++{ ++ int tmp = 0; ++ t_FmPcdCcKeyParams *p_KeyParams; ++ t_Error err; ++ uint8_t key = 0x01; ++ uint32_t requiredAction = 0; ++ ++ if (p_CcNode->numOfKeys != 1) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT the maximal supported 'numOfKeys' is 1")); ++ ++ if ((p_CcNodeParam->keysParams.maxNumOfKeys) && (p_CcNodeParam->keysParams.maxNumOfKeys != 1)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT the maximal supported 'maxNumOfKeys' is 1")); ++ ++ /* Validate statistics parameters */ ++ err = ValidateAndCalcStatsParams(p_CcNode, ++ p_CcNodeParam, ++ &(p_CcNode->numOfStatsFLRs), ++ &(p_CcNode->countersArraySize)); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters")); ++ ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ p_CcNodeParam->keysParams.statisticsMode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("For this node MissNextEngineParams are not valid")); ++ ++ if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine(&p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ memcpy(&p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams, ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].requiredAction = requiredAction; ++ ++ if ((p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ && p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.h_Manip) ++ { ++ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++) ++ { ++ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp]; ++ ++ if (p_KeyParams->p_Mask) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT p_Mask can not be initialized")); ++ ++ if (memcmp(p_KeyParams->p_Key, &key, 1) != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT p_Key has to be 1")); ++ ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_KeyParams->ccNextEngineParams, ++ p_CcNode->statisticsMode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ if (p_KeyParams->ccNextEngineParams.h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine(&p_KeyParams->ccNextEngineParams, &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ /* Store 'key' parameters - key (fixed to 0x01), key size of 1 byte and full mask */ ++ p_CcNode->keyAndNextEngineParams[tmp].key[0] = key; ++ p_CcNode->keyAndNextEngineParams[tmp].mask[0] = 0xFF; ++ ++ /* Store NextEngine parameters */ ++ memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams, ++ &p_KeyParams->ccNextEngineParams, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip) ++ { ++ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction; ++ } ++ ++ *isKeyTblAlloc = FALSE; ++ ++ return E_OK; ++} ++ ++static t_Error IcHashIndexedCheckParams(t_Handle h_FmPcd, ++ t_FmPcdCcNodeParams *p_CcNodeParam, ++ t_FmPcdCcNode *p_CcNode, ++ bool *isKeyTblAlloc) ++{ ++ int tmp = 0, countOnes = 0; ++ t_FmPcdCcKeyParams *p_KeyParams; ++ t_Error err; ++ uint16_t glblMask = p_CcNodeParam->extractCcParams.extractNonHdr.icIndxMask; ++ uint16_t countMask = (uint16_t)(glblMask >> 4); ++ uint32_t requiredAction = 0; ++ ++ if (glblMask & 0x000f) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("icIndxMask has to be with last nibble 0")); ++ ++ while (countMask) ++ { ++ countOnes++; ++ countMask = (uint16_t)(countMask >> 1); ++ } ++ ++ if (!POWER_OF_2(p_CcNode->numOfKeys)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Node of the type INDEXED numOfKeys has to be powerOfTwo")); ++ ++ if (p_CcNode->numOfKeys != ((uint32_t)1 << countOnes)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Node of the type IC_HASH_INDEXED numOfKeys has to be powerOfTwo")); ++ ++ if (p_CcNodeParam->keysParams.maxNumOfKeys && ++ (p_CcNodeParam->keysParams.maxNumOfKeys != p_CcNode->numOfKeys)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Node of the type INDEXED 'maxNumOfKeys' should be 0 or equal 'numOfKeys'")); ++ ++ /* Validate statistics parameters */ ++ err = ValidateAndCalcStatsParams(p_CcNode, ++ p_CcNodeParam, ++ &(p_CcNode->numOfStatsFLRs), ++ &(p_CcNode->countersArraySize)); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters")); ++ ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ p_CcNode->statisticsMode); ++ if (GET_ERROR_TYPE(err)!= E_NOT_SUPPORTED) ++ RETURN_ERROR(MAJOR, err, ("MissNextEngineParams for the node of the type IC_INDEX_HASH has to be UnInitialized")); ++ ++ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++) ++ { ++ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp]; ++ ++ if (p_KeyParams->p_Mask || p_KeyParams->p_Key) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Node of the type IC_HASH_INDEXED p_Key or p_Mask has to be NULL")); ++ ++ if ((glblMask & (tmp * 16)) == (tmp * 16)) ++ { ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_KeyParams->ccNextEngineParams, ++ p_CcNode->statisticsMode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("This index has to be initialized for the node of the type IC_INDEX_HASH according to settings of GlobalMask ")); ++ ++ if (p_KeyParams->ccNextEngineParams.h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine(&p_KeyParams->ccNextEngineParams, &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction; ++ } ++ ++ memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams, ++ &p_KeyParams->ccNextEngineParams, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip) ++ { ++ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ } ++ else ++ { ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_KeyParams->ccNextEngineParams, ++ p_CcNode->statisticsMode); ++ if (GET_ERROR_TYPE(err)!= E_NOT_SUPPORTED) ++ RETURN_ERROR(MAJOR, err, ("This index has to be UnInitialized for the node of the type IC_INDEX_HASH according to settings of GlobalMask")); ++ } ++ } ++ ++ *isKeyTblAlloc = FALSE; ++ memcpy(PTR_MOVE(p_CcNode->p_GlblMask, 2), &glblMask, 2); ++ ++ return E_OK; ++} ++ ++static t_Error ModifyNextEngineParamNode(t_Handle h_FmPcd, ++ t_Handle h_FmPcdCcNode, ++ uint16_t keyIndex, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_FmPcd *p_FmPcd; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode,E_INVALID_HANDLE); ++ ++ if (keyIndex >= p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("keyIndex > previously cleared last index + 1")); ++ ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ p_ModifyKeyParams = ModifyKeyCommonPart1(p_CcNode, keyIndex, e_MODIFY_STATE_CHANGE, FALSE, FALSE, FALSE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ } ++ ++ err = BuildNewNodeModifyNextEngine(h_FmPcd, ++ p_CcNode, ++ keyIndex, ++ p_FmPcdCcNextEngineParams, ++ &h_OldPointersLst, ++ &h_NewPointersLst, ++ p_ModifyKeyParams); ++ if (err) ++ { ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, p_ModifyKeyParams, FALSE); ++ ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++} ++ ++static t_Error FindKeyIndex(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ uint16_t *p_KeyIndex) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint8_t tmpMask[FM_PCD_MAX_SIZE_OF_KEY]; ++ uint16_t i; ++ ++ ASSERT_COND(p_Key); ++ ASSERT_COND(p_KeyIndex); ++ ASSERT_COND(keySize < FM_PCD_MAX_SIZE_OF_KEY); ++ ++ if (keySize != p_CcNode->userSizeOfExtraction) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Key size doesn't match the extraction size of the node")); ++ ++ /* If user didn't pass a mask for this key, we'll look for full extraction mask */ ++ if (!p_Mask) ++ memset(tmpMask, 0xFF, keySize); ++ ++ for (i = 0 ; i < p_CcNode->numOfKeys; i++) ++ { ++ /* Comparing received key */ ++ if (memcmp(p_Key, p_CcNode->keyAndNextEngineParams[i].key, keySize) == 0) ++ { ++ if (p_Mask) ++ { ++ /* If a user passed a mask for this key, it must match to the existing key's mask for a correct match */ ++ if (memcmp(p_Mask, p_CcNode->keyAndNextEngineParams[i].mask, keySize) == 0) ++ { ++ *p_KeyIndex = i; ++ return E_OK; ++ } ++ } ++ else ++ { ++ /* If user didn't pass a mask for this key, check if the existing key mask is full extraction */ ++ if (memcmp(tmpMask, p_CcNode->keyAndNextEngineParams[i].mask, keySize) == 0) ++ { ++ *p_KeyIndex = i; ++ return E_OK; ++ } ++ } ++ } ++ } ++ ++ return ERROR_CODE(E_NOT_FOUND); ++} ++ ++static t_Error CalcAndUpdateCcShadow(t_FmPcdCcNode *p_CcNode, ++ bool isKeyTblAlloc, ++ uint32_t *p_MatchTableSize, ++ uint32_t *p_AdTableSize) ++{ ++ uint32_t shadowSize; ++ t_Error err; ++ ++ /* Calculate keys table maximal size - each entry consists of a key and a mask, ++ (if local mask support is requested) */ ++ *p_MatchTableSize = p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t) * p_CcNode->maxNumOfKeys; ++ ++ if (p_CcNode->maskSupport) ++ *p_MatchTableSize *= 2; ++ ++ /* Calculate next action descriptors table, including one more entry for miss */ ++ *p_AdTableSize = (uint32_t)((p_CcNode->maxNumOfKeys + 1) * FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Calculate maximal shadow size of this node. ++ All shadow structures will be used for runtime modifications host command. If ++ keys table was allocated for this node, the keys table and next engines table may ++ be modified in run time (entries added or removed), so shadow tables are requires. ++ Otherwise, the only supported runtime modification is a specific next engine update ++ and this requires shadow memory of a single AD */ ++ ++ /* Shadow size should be enough to hold the following 3 structures: ++ * 1 - an action descriptor */ ++ shadowSize = FM_PCD_CC_AD_ENTRY_SIZE; ++ ++ /* 2 - keys match table, if was allocated for the current node */ ++ if (isKeyTblAlloc) ++ shadowSize += *p_MatchTableSize; ++ ++ /* 3 - next action descriptors table */ ++ shadowSize += *p_AdTableSize; ++ ++ /* Update shadow to the calculated size */ ++ err = FmPcdUpdateCcShadow (p_CcNode->h_FmPcd, (uint32_t)shadowSize, FM_PCD_CC_AD_TABLE_ALIGN); ++ if (err != E_OK) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node shadow")); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error AllocStatsObjs(t_FmPcdCcNode *p_CcNode) ++{ ++ t_FmPcdStatsObj *p_StatsObj; ++ t_Handle h_FmMuram, h_StatsAd, h_StatsCounters; ++ uint32_t i; ++ ++ h_FmMuram = FmPcdGetMuramHandle(p_CcNode->h_FmPcd); ++ if (!h_FmMuram) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM")); ++ ++ /* Allocate statistics ADs and statistics counter. An extra pair (AD + counters) ++ will be allocated to support runtime modifications */ ++ for (i = 0; i < p_CcNode->maxNumOfKeys + 2; i++) ++ { ++ /* Allocate list object structure */ ++ p_StatsObj = XX_Malloc(sizeof(t_FmPcdStatsObj)); ++ if (!p_StatsObj) ++ { ++ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Statistics object")); ++ } ++ memset(p_StatsObj, 0, sizeof(t_FmPcdStatsObj)); ++ ++ /* Allocate statistics AD from MURAM */ ++ h_StatsAd = (t_Handle)FM_MURAM_AllocMem(h_FmMuram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!h_StatsAd) ++ { ++ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram); ++ XX_Free(p_StatsObj); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics ADs")); ++ } ++ IOMemSet32(h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Allocate statistics counters from MURAM */ ++ h_StatsCounters = (t_Handle)FM_MURAM_AllocMem(h_FmMuram, ++ p_CcNode->countersArraySize, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!h_StatsCounters) ++ { ++ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram); ++ FM_MURAM_FreeMem(h_FmMuram, h_StatsAd); ++ XX_Free(p_StatsObj); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics counters")); ++ } ++ IOMemSet32(h_StatsCounters, 0, p_CcNode->countersArraySize); ++ ++ p_StatsObj->h_StatsAd = h_StatsAd; ++ p_StatsObj->h_StatsCounters = h_StatsCounters; ++ ++ EnqueueStatsObj(&p_CcNode->availableStatsLst, p_StatsObj); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error MatchTableGetKeyStatistics(t_FmPcdCcNode *p_CcNode, ++ uint16_t keyIndex, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics) ++{ ++ uint32_t *p_StatsCounters, i; ++ ++ if (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this match table")); ++ ++ if (keyIndex >= p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("The provided keyIndex exceeds the number of keys in this match table")); ++ ++ if (!p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this key")); ++ ++ memset(p_KeyStatistics, 0, sizeof (t_FmPcdCcKeyStatistics)); ++ ++ p_StatsCounters = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsCounters; ++ ASSERT_COND(p_StatsCounters); ++ ++ p_KeyStatistics->byteCount = GET_UINT32(*p_StatsCounters); ++ ++ for (i = 1; i <= p_CcNode->numOfStatsFLRs; i++) ++ { ++ p_StatsCounters = PTR_MOVE(p_StatsCounters, FM_PCD_CC_STATS_COUNTER_SIZE); ++ ++ p_KeyStatistics->frameCount += GET_UINT32(*p_StatsCounters); ++ ++#if (DPAA_VERSION >= 11) ++ p_KeyStatistics->frameLengthRangeCount[i-1] = GET_UINT32(*p_StatsCounters); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++t_CcNodeInformation* FindNodeInfoInReleventLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock) ++{ ++ t_CcNodeInformation *p_CcInformation; ++ t_List *p_Pos; ++ uint32_t intFlags; ++ ++ intFlags = XX_LockIntrSpinlock(h_Spinlock); ++ ++ for (p_Pos = LIST_FIRST(p_List); p_Pos != (p_List); p_Pos = LIST_NEXT(p_Pos)) ++ { ++ p_CcInformation = CC_NODE_F_OBJECT(p_Pos); ++ ++ ASSERT_COND(p_CcInformation->h_CcNode); ++ ++ if (p_CcInformation->h_CcNode == h_Info) ++ { ++ XX_UnlockIntrSpinlock(h_Spinlock, intFlags); ++ return p_CcInformation; ++ } ++ } ++ ++ XX_UnlockIntrSpinlock(h_Spinlock, intFlags); ++ ++ return NULL; ++} ++ ++void EnqueueNodeInfoToRelevantLst(t_List *p_List, t_CcNodeInformation *p_CcInfo, t_Handle h_Spinlock) ++{ ++ t_CcNodeInformation *p_CcInformation; ++ uint32_t intFlags = 0; ++ ++ p_CcInformation = (t_CcNodeInformation *)XX_Malloc(sizeof(t_CcNodeInformation)); ++ ++ if (p_CcInformation) ++ { ++ memset(p_CcInformation, 0, sizeof(t_CcNodeInformation)); ++ memcpy(p_CcInformation, p_CcInfo, sizeof(t_CcNodeInformation)); ++ INIT_LIST(&p_CcInformation->node); ++ ++ if (h_Spinlock) ++ intFlags = XX_LockIntrSpinlock(h_Spinlock); ++ ++ LIST_AddToTail(&p_CcInformation->node, p_List); ++ ++ if (h_Spinlock) ++ XX_UnlockIntrSpinlock(h_Spinlock, intFlags); ++ } ++ else ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC Node Information")); ++} ++ ++void DequeueNodeInfoFromRelevantLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock) ++{ ++ t_CcNodeInformation *p_CcInformation = NULL; ++ uint32_t intFlags = 0; ++ t_List *p_Pos; ++ ++ if (h_Spinlock) ++ intFlags = XX_LockIntrSpinlock(h_Spinlock); ++ ++ if (LIST_IsEmpty(p_List)) ++ { ++ XX_RestoreAllIntr(intFlags); ++ return; ++ } ++ ++ for (p_Pos = LIST_FIRST(p_List); p_Pos != (p_List); p_Pos = LIST_NEXT(p_Pos)) ++ { ++ p_CcInformation = CC_NODE_F_OBJECT(p_Pos); ++ ASSERT_COND(p_CcInformation); ++ ASSERT_COND(p_CcInformation->h_CcNode); ++ if (p_CcInformation->h_CcNode == h_Info) ++ break; ++ } ++ ++ if (p_CcInformation) ++ { ++ LIST_DelAndInit(&p_CcInformation->node); ++ XX_Free(p_CcInformation); ++ } ++ ++ if (h_Spinlock) ++ XX_UnlockIntrSpinlock(h_Spinlock, intFlags); ++} ++ ++void NextStepAd(t_Handle h_Ad, ++ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, ++ t_FmPcd *p_FmPcd) ++{ ++ switch (p_FmPcdCcNextEngineParams->nextEngine) ++ { ++ case (e_FM_PCD_KG): ++ case (e_FM_PCD_PLCR): ++ case (e_FM_PCD_DONE): ++ /* if NIA is not CC, create a "result" type AD */ ++ FillAdOfTypeResult(h_Ad, ++ p_FmPcdCcStatsParams, ++ p_FmPcd, ++ p_FmPcdCcNextEngineParams); ++ break; ++#if (DPAA_VERSION >= 11) ++ case (e_FM_PCD_FR): ++ if (p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic) ++ { ++ FillAdOfTypeContLookup(h_Ad, ++ p_FmPcdCcStatsParams, ++ p_FmPcd, ++ p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode, ++ p_FmPcdCcNextEngineParams->h_Manip, ++ p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic); ++ FrmReplicGroupUpdateOwner(p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic, ++ TRUE/* add */); ++ } ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ case (e_FM_PCD_CC): ++ /* if NIA is not CC, create a TD to continue the CC lookup */ ++ FillAdOfTypeContLookup(h_Ad, ++ p_FmPcdCcStatsParams, ++ p_FmPcd, ++ p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode, ++ p_FmPcdCcNextEngineParams->h_Manip, ++ NULL); ++ ++ UpdateNodeOwner(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode, TRUE); ++ break; ++ ++ default: ++ return; ++ } ++} ++ ++t_Error FmPcdCcTreeAddIPR(t_Handle h_FmPcd, ++ t_Handle h_FmTree, ++ t_Handle h_NetEnv, ++ t_Handle h_IpReassemblyManip, ++ bool createSchemes) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree; ++ t_FmPcdCcNextEngineParams nextEngineParams; ++ t_NetEnvParams netEnvParams; ++ t_Handle h_Ad; ++ bool isIpv6Present; ++ uint8_t ipv4GroupId, ipv6GroupId; ++ t_Error err; ++ ++ ASSERT_COND(p_FmPcdCcTree); ++ ++ /* this routine must be protected by the calling routine! */ ++ ++ memset(&nextEngineParams, 0, sizeof(t_FmPcdCcNextEngineParams)); ++ memset(&netEnvParams, 0, sizeof(t_NetEnvParams)); ++ ++ h_Ad = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); ++ ++ isIpv6Present = FmPcdManipIpReassmIsIpv6Hdr(h_IpReassemblyManip); ++ ++ if (isIpv6Present && (p_FmPcdCcTree->numOfEntries > (FM_PCD_MAX_NUM_OF_CC_GROUPS-2))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("need two free entries for IPR")); ++ ++ if (p_FmPcdCcTree->numOfEntries > (FM_PCD_MAX_NUM_OF_CC_GROUPS-1)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("need two free entries for IPR")); ++ ++ nextEngineParams.nextEngine = e_FM_PCD_DONE; ++ nextEngineParams.h_Manip = h_IpReassemblyManip; ++ ++ /* Lock tree */ ++ err = CcRootTryLock(p_FmPcdCcTree); ++ if (err) ++ return ERROR_CODE(E_BUSY); ++ ++ if (p_FmPcdCcTree->h_IpReassemblyManip == h_IpReassemblyManip) ++ { ++ CcRootReleaseLock(p_FmPcdCcTree); ++ return E_OK; ++ } ++ ++ if ((p_FmPcdCcTree->h_IpReassemblyManip) && ++ (p_FmPcdCcTree->h_IpReassemblyManip != h_IpReassemblyManip)) ++ { ++ CcRootReleaseLock(p_FmPcdCcTree); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("This tree was previously updated with different IPR")); ++ } ++ ++ /* Initialize IPR for the first time for this tree */ ++ if (isIpv6Present) ++ { ++ ipv6GroupId = p_FmPcdCcTree->numOfGrps++; ++ p_FmPcdCcTree->fmPcdGroupParam[ipv6GroupId].baseGroupEntry = (FM_PCD_MAX_NUM_OF_CC_GROUPS-2); ++ ++ if (createSchemes) ++ { ++ err = FmPcdManipBuildIpReassmScheme(h_FmPcd, h_NetEnv, p_FmPcdCcTree, h_IpReassemblyManip, FALSE, ipv6GroupId); ++ if (err) ++ { ++ p_FmPcdCcTree->numOfGrps--; ++ CcRootReleaseLock(p_FmPcdCcTree); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ ++ NextStepAd(PTR_MOVE(h_Ad, (FM_PCD_MAX_NUM_OF_CC_GROUPS-2) * FM_PCD_CC_AD_ENTRY_SIZE), ++ NULL, ++ &nextEngineParams, ++ h_FmPcd); ++ } ++ ++ ipv4GroupId = p_FmPcdCcTree->numOfGrps++; ++ p_FmPcdCcTree->fmPcdGroupParam[ipv4GroupId].totalBitsMask = 0; ++ p_FmPcdCcTree->fmPcdGroupParam[ipv4GroupId].baseGroupEntry = (FM_PCD_MAX_NUM_OF_CC_GROUPS-1); ++ ++ if (createSchemes) ++ { ++ err = FmPcdManipBuildIpReassmScheme(h_FmPcd, h_NetEnv, p_FmPcdCcTree, h_IpReassemblyManip, TRUE, ipv4GroupId); ++ if (err) ++ { ++ p_FmPcdCcTree->numOfGrps--; ++ if (isIpv6Present) ++ { ++ p_FmPcdCcTree->numOfGrps--; ++ FmPcdManipDeleteIpReassmSchemes(h_IpReassemblyManip); ++ } ++ CcRootReleaseLock(p_FmPcdCcTree); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ ++ NextStepAd(PTR_MOVE(h_Ad, (FM_PCD_MAX_NUM_OF_CC_GROUPS-1) * FM_PCD_CC_AD_ENTRY_SIZE), ++ NULL, ++ &nextEngineParams, ++ h_FmPcd); ++ ++ p_FmPcdCcTree->h_IpReassemblyManip = h_IpReassemblyManip; ++ ++ CcRootReleaseLock(p_FmPcdCcTree); ++ ++ return E_OK; ++} ++ ++ ++t_Handle FmPcdCcTreeGetSavedManipParams(t_Handle h_FmTree) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree; ++ ++ ASSERT_COND(p_FmPcdCcTree); ++ ++ return p_FmPcdCcTree->h_FmPcdCcSavedManipParams; ++} ++ ++void FmPcdCcTreeSetSavedManipParams(t_Handle h_FmTree, t_Handle h_SavedManipParams) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree; ++ ++ ASSERT_COND(p_FmPcdCcTree); ++ ++ p_FmPcdCcTree->h_FmPcdCcSavedManipParams = h_SavedManipParams; ++} ++ ++uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ ++ ASSERT_COND(p_CcNode); ++ ++ return p_CcNode->parseCode; ++} ++ ++uint8_t FmPcdCcGetOffset(t_Handle h_CcNode) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ ++ ASSERT_COND(p_CcNode); ++ ++ return p_CcNode->offset; ++} ++ ++uint16_t FmPcdCcGetNumOfKeys(t_Handle h_CcNode) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ ++ ASSERT_COND(p_CcNode); ++ ++ return p_CcNode->numOfKeys; ++} ++ ++t_Error FmPcdCcModifyNextEngineParamTree(t_Handle h_FmPcd, ++ t_Handle h_FmPcdCcTree, ++ uint8_t grpId, ++ uint8_t index, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree; ++ t_FmPcd *p_FmPcd; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ uint16_t keyIndex; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((grpId <= 7),E_INVALID_VALUE); ++ ++ if (grpId >= p_FmPcdCcTree->numOfGrps) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("grpId you asked > numOfGroup of relevant tree")); ++ ++ if (index >= p_FmPcdCcTree->fmPcdGroupParam[grpId].numOfEntriesInGroup) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("index > numOfEntriesInGroup")); ++ ++ p_FmPcd = (t_FmPcd *)h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ keyIndex = (uint16_t)(p_FmPcdCcTree->fmPcdGroupParam[grpId].baseGroupEntry + index); ++ ++ p_ModifyKeyParams = ModifyKeyCommonPart1(p_FmPcdCcTree, keyIndex, e_MODIFY_STATE_CHANGE, FALSE, FALSE, TRUE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ p_ModifyKeyParams->tree = TRUE; ++ ++ if (p_FmPcd->p_CcShadow) ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = BuildNewNodeModifyNextEngine(p_FmPcd, ++ p_FmPcdCcTree, ++ keyIndex, ++ p_FmPcdCcNextEngineParams, ++ &h_OldPointersLst, ++ &h_NewPointersLst, ++ p_ModifyKeyParams); ++ if (err) ++ { ++ XX_Free(p_ModifyKeyParams); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, p_ModifyKeyParams, FALSE); ++ ++ if (p_FmPcd->p_CcShadow) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++ ++} ++ ++t_Error FmPcdCcRemoveKey(t_Handle h_FmPcd, ++ t_Handle h_FmPcdCcNode, ++ uint16_t keyIndex) ++{ ++ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *) h_FmPcdCcNode; ++ t_FmPcd *p_FmPcd; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ bool useShadowStructs = FALSE; ++ t_Error err = E_OK; ++ ++ if (keyIndex >= p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("impossible to remove key when numOfKeys <= keyIndex")); ++ ++ if (!p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keyIndex you asked > numOfKeys of relevant node that was initialized")); ++ ++ if (p_CcNode->h_FmPcd != h_FmPcd) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("handler to FmPcd is different from the handle provided at node initialization time")); ++ ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ p_ModifyKeyParams = ModifyKeyCommonPart1(p_CcNode, keyIndex, e_MODIFY_STATE_REMOVE, TRUE, TRUE, FALSE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ useShadowStructs = TRUE; ++ } ++ ++ err = BuildNewNodeRemoveKey(p_CcNode, keyIndex, p_ModifyKeyParams); ++ if (err) ++ { ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode, ++ p_ModifyKeyParams, ++ &h_OldPointersLst, ++ &h_NewPointersLst); ++ if (err) ++ { ++ ReleaseNewNodeCommonPart(p_ModifyKeyParams); ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, ++ &h_OldPointersLst, ++ &h_NewPointersLst, ++ p_ModifyKeyParams, ++ useShadowStructs); ++ ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++} ++ ++t_Error FmPcdCcModifyKey(t_Handle h_FmPcd, ++ t_Handle h_FmPcdCcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_FmPcd *p_FmPcd; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ uint16_t tmpKeyIndex; ++ bool useShadowStructs = FALSE; ++ t_Error err = E_OK; ++ ++ if (keyIndex >= p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("keyIndex > previously cleared last index + 1")); ++ ++ if (keySize != p_CcNode->userSizeOfExtraction) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("size for ModifyKey has to be the same as defined in SetNode")); ++ ++ if (p_CcNode->h_FmPcd != h_FmPcd) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("handler to FmPcd is different from the handle provided at node initialization time")); ++ ++ err = FindKeyIndex(h_FmPcdCcNode, ++ keySize, ++ p_Key, ++ p_Mask, ++ &tmpKeyIndex); ++ if (GET_ERROR_TYPE(err) != E_NOT_FOUND) ++ RETURN_ERROR(MINOR, E_ALREADY_EXISTS, ++ ("The received key and mask pair was already found in the match table of the provided node")); ++ ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ p_ModifyKeyParams = ModifyKeyCommonPart1(p_CcNode, keyIndex, e_MODIFY_STATE_CHANGE, TRUE, TRUE, FALSE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ useShadowStructs = TRUE; ++ } ++ ++ err = BuildNewNodeModifyKey(p_CcNode, ++ keyIndex, ++ p_Key, ++ p_Mask, ++ p_ModifyKeyParams); ++ if (err) ++ { ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode, ++ p_ModifyKeyParams, ++ &h_OldPointersLst, ++ &h_NewPointersLst); ++ if (err) ++ { ++ ReleaseNewNodeCommonPart(p_ModifyKeyParams); ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, ++ &h_OldPointersLst, ++ &h_NewPointersLst, ++ p_ModifyKeyParams, ++ useShadowStructs); ++ ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++} ++ ++t_Error FmPcdCcModifyMissNextEngineParamNode(t_Handle h_FmPcd, ++ t_Handle h_FmPcdCcNode, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_FmPcd *p_FmPcd; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ uint16_t keyIndex; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_CcNode,E_INVALID_VALUE); ++ ++ keyIndex = p_CcNode->numOfKeys; ++ ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ p_ModifyKeyParams = ModifyKeyCommonPart1(p_CcNode, keyIndex, e_MODIFY_STATE_CHANGE, FALSE, TRUE, FALSE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ } ++ ++ err = BuildNewNodeModifyNextEngine(h_FmPcd, ++ p_CcNode, ++ keyIndex, ++ p_FmPcdCcNextEngineParams, ++ &h_OldPointersLst, ++ &h_NewPointersLst, ++ p_ModifyKeyParams); ++ if (err) ++ { ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, p_ModifyKeyParams, FALSE); ++ ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++} ++ ++t_Error FmPcdCcAddKey(t_Handle h_FmPcd, ++ t_Handle h_FmPcdCcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_FmPcdCcKeyParams) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_FmPcd *p_FmPcd; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ bool useShadowStructs = FALSE; ++ uint16_t tmpKeyIndex; ++ t_Error err = E_OK; ++ ++ if (keyIndex > p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("keyIndex > previously cleared last index + 1")); ++ ++ if (keySize != p_CcNode->userSizeOfExtraction) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be defined as it was defined in initialization step")); ++ ++ if (p_CcNode->h_FmPcd != h_FmPcd) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("handler to FmPcd is different from the handle provided at node initialization time")); ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (p_CcNode->numOfKeys == p_CcNode->maxNumOfKeys) ++ RETURN_ERROR(MAJOR, E_FULL, ("number of keys exceeds the maximal number of keys provided at node initialization time")); ++ } ++ else if (p_CcNode->numOfKeys == FM_PCD_MAX_NUM_OF_KEYS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("number of keys can not be larger than %d", FM_PCD_MAX_NUM_OF_KEYS)); ++ ++ err = FindKeyIndex(h_FmPcdCcNode, ++ keySize, ++ p_FmPcdCcKeyParams->p_Key, ++ p_FmPcdCcKeyParams->p_Mask, ++ &tmpKeyIndex); ++ if (GET_ERROR_TYPE(err) != E_NOT_FOUND) ++ RETURN_ERROR(MINOR, E_ALREADY_EXISTS, ++ ("The received key and mask pair was already found in the match table of the provided node")); ++ ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ p_ModifyKeyParams = ModifyKeyCommonPart1(p_CcNode, ++ keyIndex, ++ e_MODIFY_STATE_ADD, ++ TRUE, ++ TRUE, ++ FALSE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ useShadowStructs = TRUE; ++ } ++ ++ err = BuildNewNodeAddOrMdfyKeyAndNextEngine (h_FmPcd, ++ p_CcNode, ++ keyIndex, ++ p_FmPcdCcKeyParams, ++ p_ModifyKeyParams, ++ TRUE); ++ if (err) ++ { ++ ReleaseNewNodeCommonPart(p_ModifyKeyParams); ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode, ++ p_ModifyKeyParams, ++ &h_OldPointersLst, ++ &h_NewPointersLst); ++ if (err) ++ { ++ ReleaseNewNodeCommonPart(p_ModifyKeyParams); ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, ++ &h_OldPointersLst, ++ &h_NewPointersLst, ++ p_ModifyKeyParams, ++ useShadowStructs); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++} ++ ++t_Error FmPcdCcModifyKeyAndNextEngine(t_Handle h_FmPcd, ++ t_Handle h_FmPcdCcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_FmPcdCcKeyParams) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_FmPcd *p_FmPcd; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ uint16_t tmpKeyIndex; ++ bool useShadowStructs = FALSE; ++ t_Error err = E_OK; ++ ++ if (keyIndex > p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("keyIndex > previously cleared last index + 1")); ++ ++ if (keySize != p_CcNode->userSizeOfExtraction) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be defined as it was defined in initialization step")); ++ ++ if (p_CcNode->h_FmPcd != h_FmPcd) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("handler to FmPcd is different from the handle provided at node initialization time")); ++ ++ err = FindKeyIndex(h_FmPcdCcNode, ++ keySize, ++ p_FmPcdCcKeyParams->p_Key, ++ p_FmPcdCcKeyParams->p_Mask, ++ &tmpKeyIndex); ++ if (GET_ERROR_TYPE(err) != E_NOT_FOUND) ++ RETURN_ERROR(MINOR, E_ALREADY_EXISTS, ++ ("The received key and mask pair was already found in the match table of the provided node")); ++ ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ p_ModifyKeyParams = ModifyKeyCommonPart1(p_CcNode, keyIndex, e_MODIFY_STATE_CHANGE, TRUE, TRUE, FALSE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ useShadowStructs = TRUE; ++ } ++ ++ err = BuildNewNodeAddOrMdfyKeyAndNextEngine (h_FmPcd, ++ p_CcNode, ++ keyIndex, ++ p_FmPcdCcKeyParams, ++ p_ModifyKeyParams, ++ FALSE); ++ if (err) ++ { ++ ReleaseNewNodeCommonPart(p_ModifyKeyParams); ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode, ++ p_ModifyKeyParams, ++ &h_OldPointersLst, ++ &h_NewPointersLst); ++ if (err) ++ { ++ ReleaseNewNodeCommonPart(p_ModifyKeyParams); ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, ++ &h_OldPointersLst, ++ &h_NewPointersLst, ++ p_ModifyKeyParams, ++ useShadowStructs); ++ ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++} ++ ++uint32_t FmPcdCcGetNodeAddrOffsetFromNodeInfo(t_Handle h_FmPcd, t_Handle h_Pointer) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_CcNodeInformation *p_CcNodeInfo; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE, (uint32_t)ILLEGAL_BASE); ++ ++ p_CcNodeInfo = CC_NODE_F_OBJECT(h_Pointer); ++ ++ return (uint32_t)(XX_VirtToPhys(p_CcNodeInfo->h_CcNode) - p_FmPcd->physicalMuramBase); ++} ++ ++t_Error FmPcdCcGetGrpParams(t_Handle h_FmPcdCcTree, uint8_t grpId, uint32_t *p_GrpBits, uint8_t *p_GrpBase) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *) h_FmPcdCcTree; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE); ++ ++ if (grpId >= p_FmPcdCcTree->numOfGrps) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("grpId you asked > numOfGroup of relevant tree")); ++ ++ *p_GrpBits = p_FmPcdCcTree->fmPcdGroupParam[grpId].totalBitsMask; ++ *p_GrpBase = p_FmPcdCcTree->fmPcdGroupParam[grpId].baseGroupEntry; ++ ++ return E_OK; ++} ++ ++t_Error FmPcdCcBindTree(t_Handle h_FmPcd, ++ t_Handle h_PcdParams, ++ t_Handle h_FmPcdCcTree, ++ uint32_t *p_Offset, ++ t_Handle h_FmPort) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE); ++ ++ /* this routine must be protected by the calling routine by locking all PCD modules! */ ++ ++ err = CcUpdateParams(h_FmPcd, h_PcdParams, h_FmPort, h_FmPcdCcTree, TRUE); ++ ++ if (err == E_OK) ++ UpdateCcRootOwner(p_FmPcdCcTree, TRUE); ++ ++ *p_Offset = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr)) - ++ p_FmPcd->physicalMuramBase); ++ ++ return err; ++} ++ ++t_Error FmPcdCcUnbindTree(t_Handle h_FmPcd, t_Handle h_FmPcdCcTree) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree; ++ ++ /* this routine must be protected by the calling routine by locking all PCD modules! */ ++ ++ UNUSED(h_FmPcd); ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree,E_INVALID_HANDLE); ++ ++ UpdateCcRootOwner(p_FmPcdCcTree, FALSE); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdCcNodeTreeTryLock(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, t_List *p_List) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_List *p_Pos, *p_Tmp; ++ t_CcNodeInformation *p_CcNodeInfo, nodeInfo; ++ uint32_t intFlags; ++ t_Error err = E_OK; ++ ++ intFlags = FmPcdLock(h_FmPcd); ++ ++ if (LIST_IsEmpty(&p_CcNode->ccTreesLst)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("asked for more nodes in CC than MAX")); ++ ++ LIST_FOR_EACH(p_Pos, &p_CcNode->ccTreesLst) ++ { ++ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos); ++ ASSERT_COND(p_CcNodeInfo->h_CcNode); ++ ++ err = CcRootTryLock(p_CcNodeInfo->h_CcNode); ++ ++ if (err) ++ { ++ LIST_FOR_EACH(p_Tmp, &p_CcNode->ccTreesLst) ++ { ++ if (p_Tmp == p_Pos) ++ break; ++ ++ CcRootReleaseLock(p_CcNodeInfo->h_CcNode); ++ } ++ break; ++ } ++ ++ memset(&nodeInfo, 0, sizeof(t_CcNodeInformation)); ++ nodeInfo.h_CcNode = p_CcNodeInfo->h_CcNode; ++ EnqueueNodeInfoToRelevantLst(p_List, &nodeInfo, NULL); ++ } ++ ++ FmPcdUnlock(h_FmPcd, intFlags); ++ CORE_MemoryBarrier(); ++ ++ return err; ++} ++ ++void FmPcdCcNodeTreeReleaseLock(t_Handle h_FmPcd, t_List *p_List) ++{ ++ t_List *p_Pos; ++ t_CcNodeInformation *p_CcNodeInfo; ++ t_Handle h_FmPcdCcTree; ++ uint32_t intFlags; ++ ++ intFlags = FmPcdLock(h_FmPcd); ++ ++ LIST_FOR_EACH(p_Pos, p_List) ++ { ++ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos); ++ h_FmPcdCcTree = p_CcNodeInfo->h_CcNode; ++ CcRootReleaseLock(h_FmPcdCcTree); ++ } ++ ++ ReleaseLst(p_List); ++ ++ FmPcdUnlock(h_FmPcd, intFlags); ++ CORE_MemoryBarrier(); ++} ++ ++ ++t_Error FmPcdUpdateCcShadow (t_FmPcd *p_FmPcd, uint32_t size, uint32_t align) ++{ ++ uint32_t intFlags; ++ uint32_t newSize = 0, newAlign = 0; ++ bool allocFail = FALSE; ++ ++ ASSERT_COND(p_FmPcd); ++ ++ if (!size) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("size must be larger then 0")); ++ ++ if (!POWER_OF_2(align)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("alignment must be power of 2")); ++ ++ newSize = p_FmPcd->ccShadowSize; ++ newAlign = p_FmPcd->ccShadowAlign; ++ ++ /* Check if current shadow is large enough to hold the requested size */ ++ if (size > p_FmPcd->ccShadowSize) ++ newSize = size; ++ ++ /* Check if current shadow matches the requested alignment */ ++ if (align > p_FmPcd->ccShadowAlign) ++ newAlign = align; ++ ++ /* If a bigger shadow size or bigger shadow alignment are required, ++ a new shadow will be allocated */ ++ if ((newSize != p_FmPcd->ccShadowSize) || (newAlign != p_FmPcd->ccShadowAlign)) ++ { ++ intFlags = FmPcdLock(p_FmPcd); ++ ++ if (p_FmPcd->p_CcShadow) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_FmPcd), p_FmPcd->p_CcShadow); ++ p_FmPcd->ccShadowSize = 0; ++ p_FmPcd->ccShadowAlign = 0; ++ } ++ ++ p_FmPcd->p_CcShadow = FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd), ++ newSize, ++ newAlign); ++ if (!p_FmPcd->p_CcShadow) ++ { ++ allocFail = TRUE; ++ ++ /* If new shadow size allocation failed, ++ re-allocate with previous parameters */ ++ p_FmPcd->p_CcShadow = FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd), ++ p_FmPcd->ccShadowSize, ++ p_FmPcd->ccShadowAlign); ++ } ++ ++ FmPcdUnlock(p_FmPcd, intFlags); ++ ++ if (allocFail) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Shadow memory")); ++ ++ p_FmPcd->ccShadowSize = newSize; ++ p_FmPcd->ccShadowAlign = newAlign; ++ } ++ ++ return E_OK; ++} ++ ++#if (DPAA_VERSION >= 11) ++void FmPcdCcGetAdTablesThatPointOnReplicGroup(t_Handle h_Node, ++ t_Handle h_ReplicGroup, ++ t_List *p_AdTables, ++ uint32_t *p_NumOfAdTables) ++{ ++ t_FmPcdCcNode *p_CurrentNode = (t_FmPcdCcNode *)h_Node; ++ int i = 0; ++ void * p_AdTable; ++ t_CcNodeInformation ccNodeInfo; ++ ++ ASSERT_COND(h_Node); ++ *p_NumOfAdTables = 0; ++ ++ /* search in the current node which exact index points on this current replicator group for getting AD */ ++ for (i = 0; i < p_CurrentNode->numOfKeys + 1; i++) ++ { ++ if ((p_CurrentNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) && ++ ((p_CurrentNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic == (t_Handle)h_ReplicGroup))) ++ { ++ /* save the current ad table in the list */ ++ /* this entry uses the input replicator group */ ++ p_AdTable = PTR_MOVE(p_CurrentNode->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = p_AdTable; ++ EnqueueNodeInfoToRelevantLst(p_AdTables, &ccNodeInfo, NULL); ++ (*p_NumOfAdTables)++; ++ } ++ } ++ ++ ASSERT_COND(i != p_CurrentNode->numOfKeys); ++} ++#endif /* (DPAA_VERSION >= 11) */ ++/*********************** End of inter-module routines ************************/ ++ ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++ ++t_Handle FM_PCD_CcRootBuild(t_Handle h_FmPcd, t_FmPcdCcTreeParams *p_PcdGroupsParam) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_Error err = E_OK; ++ int i = 0, j = 0, k = 0; ++ t_FmPcdCcTree *p_FmPcdCcTree; ++ uint8_t numOfEntries; ++ t_Handle p_CcTreeTmp; ++ t_FmPcdCcGrpParams *p_FmPcdCcGroupParams; ++ t_FmPcdCcKeyAndNextEngineParams *p_Params, *p_KeyAndNextEngineParams; ++ t_NetEnvParams netEnvParams; ++ uint8_t lastOne = 0; ++ uint32_t requiredAction = 0; ++ t_FmPcdCcNode *p_FmPcdCcNextNode; ++ t_CcNodeInformation ccNodeInfo, *p_CcInformation; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_PcdGroupsParam,E_INVALID_HANDLE, NULL); ++ ++ if (p_PcdGroupsParam->numOfGrps > FM_PCD_MAX_NUM_OF_CC_GROUPS) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfGrps should not exceed %d", FM_PCD_MAX_NUM_OF_CC_GROUPS)); ++ return NULL; ++ } ++ ++ p_FmPcdCcTree = (t_FmPcdCcTree*)XX_Malloc(sizeof(t_FmPcdCcTree)); ++ if (!p_FmPcdCcTree) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("PCD tree structure")); ++ return NULL; ++ } ++ memset(p_FmPcdCcTree, 0, sizeof(t_FmPcdCcTree)); ++ p_FmPcdCcTree->h_FmPcd = h_FmPcd; ++ ++ p_Params = (t_FmPcdCcKeyAndNextEngineParams*)XX_Malloc(FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ memset(p_Params, 0, FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ ++ INIT_LIST(&p_FmPcdCcTree->fmPortsLst); ++ ++#ifdef FM_CAPWAP_SUPPORT ++ if ((p_PcdGroupsParam->numOfGrps == 1) && ++ (p_PcdGroupsParam->ccGrpParams[0].numOfDistinctionUnits == 0) && ++ (p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].nextEngine == e_FM_PCD_CC) && ++ p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode && ++ IsCapwapApplSpecific(p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode)) ++ { ++ p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip = FmPcdManipApplSpecificBuild(); ++ if (!p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip) ++ { ++ DeleteTree(p_FmPcdCcTree,p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ return NULL; ++ } ++ } ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++ numOfEntries = 0; ++ p_FmPcdCcTree->netEnvId = FmPcdGetNetEnvId(p_PcdGroupsParam->h_NetEnv); ++ ++ for (i = 0; i < p_PcdGroupsParam->numOfGrps; i++) ++ { ++ p_FmPcdCcGroupParams = &p_PcdGroupsParam->ccGrpParams[i]; ++ ++ if (p_FmPcdCcGroupParams->numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_CC_UNITS) ++ { ++ DeleteTree(p_FmPcdCcTree,p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("numOfDistinctionUnits (group %d) should not exceed %d", i, FM_PCD_MAX_NUM_OF_CC_UNITS)); ++ return NULL; ++ } ++ ++ p_FmPcdCcTree->fmPcdGroupParam[i].baseGroupEntry = numOfEntries; ++ p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup =(uint8_t)( 0x01 << p_FmPcdCcGroupParams->numOfDistinctionUnits); ++ numOfEntries += p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; ++ if (numOfEntries > FM_PCD_MAX_NUM_OF_CC_GROUPS) ++ { ++ DeleteTree(p_FmPcdCcTree,p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfEntries can not be larger than %d", FM_PCD_MAX_NUM_OF_CC_GROUPS)); ++ return NULL; ++ } ++ ++ if (lastOne) ++ { ++ if (p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup > lastOne) ++ { ++ DeleteTree(p_FmPcdCcTree,p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_CONFLICT, ("numOfEntries per group must be set in descending order")); ++ return NULL; ++ } ++ } ++ ++ lastOne = p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; ++ ++ netEnvParams.netEnvId = p_FmPcdCcTree->netEnvId; ++ netEnvParams.numOfDistinctionUnits = p_FmPcdCcGroupParams->numOfDistinctionUnits; ++ ++ memcpy(netEnvParams.unitIds, ++ &p_FmPcdCcGroupParams->unitIds, ++ (sizeof(uint8_t)) * p_FmPcdCcGroupParams->numOfDistinctionUnits); ++ ++ err = PcdGetUnitsVector(p_FmPcd, &netEnvParams); ++ if (err) ++ { ++ DeleteTree(p_FmPcdCcTree,p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return NULL; ++ } ++ ++ p_FmPcdCcTree->fmPcdGroupParam[i].totalBitsMask = netEnvParams.vector; ++ for (j = 0; j < p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; j++) ++ { ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], ++ e_FM_PCD_CC_STATS_MODE_NONE); ++ if (err) ++ { ++ DeleteTree(p_FmPcdCcTree,p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, err, (NO_MSG)); ++ return NULL; ++ } ++ ++ if (p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j].h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine(&p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], &requiredAction); ++ if (err) ++ { ++ DeleteTree(p_FmPcdCcTree,p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ return NULL; ++ } ++ } ++ p_KeyAndNextEngineParams = p_Params+k; ++ ++ memcpy(&p_KeyAndNextEngineParams->nextEngineParams, ++ &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ if ((p_KeyAndNextEngineParams->nextEngineParams.nextEngine == e_FM_PCD_CC) ++ && p_KeyAndNextEngineParams->nextEngineParams.h_Manip) ++ { ++ err = AllocAndFillAdForContLookupManip(p_KeyAndNextEngineParams->nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ { ++ DeleteTree(p_FmPcdCcTree,p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); ++ return NULL; ++ } ++ } ++ ++ requiredAction |= UPDATE_CC_WITH_TREE; ++ p_KeyAndNextEngineParams->requiredAction = requiredAction; ++ ++ k++; ++ } ++ } ++ ++ p_FmPcdCcTree->numOfEntries = (uint8_t)k; ++ p_FmPcdCcTree->numOfGrps = p_PcdGroupsParam->numOfGrps; ++ ++ p_FmPcdCcTree->ccTreeBaseAddr = ++ PTR_TO_UINT(FM_MURAM_AllocMem(FmPcdGetMuramHandle(h_FmPcd), ++ (uint32_t)( FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE), ++ FM_PCD_CC_TREE_ADDR_ALIGN)); ++ if (!p_FmPcdCcTree->ccTreeBaseAddr) ++ { ++ DeleteTree(p_FmPcdCcTree,p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); ++ return NULL; ++ } ++ IOMemSet32(UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr), 0, (uint32_t)(FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE)); ++ ++ p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); ++ ++ j = 0; ++ for (i = 0; i < numOfEntries; i++) ++ { ++ p_KeyAndNextEngineParams = p_Params + i; ++ ++ NextStepAd(p_CcTreeTmp, ++ NULL, ++ &p_KeyAndNextEngineParams->nextEngineParams, ++ p_FmPcd); ++ ++ p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ memcpy(&p_FmPcdCcTree->keyAndNextEngineParams[i], ++ p_KeyAndNextEngineParams, ++ sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ ++ if (p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine== e_FM_PCD_CC) ++ { ++ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; ++ p_CcInformation = FindNodeInfoInReleventLst(&p_FmPcdCcNextNode->ccTreeIdLst, ++ (t_Handle)p_FmPcdCcTree, ++ p_FmPcdCcNextNode->h_Spinlock); ++ ++ if (!p_CcInformation) ++ { ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = (t_Handle)p_FmPcdCcTree; ++ ccNodeInfo.index = 1; ++ EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccTreeIdLst, ++ &ccNodeInfo, ++ p_FmPcdCcNextNode->h_Spinlock); ++ } ++ else ++ p_CcInformation->index++; ++ } ++ } ++ ++ FmPcdIncNetEnvOwners(h_FmPcd, p_FmPcdCcTree->netEnvId); ++ p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ FM_PCD_CcRootDelete(p_FmPcdCcTree); ++ XX_Free(p_Params); ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return NULL; ++ } ++ ++ for (i = 0; i < numOfEntries; i++) ++ { ++ if (p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction) ++ { ++ err = SetRequiredAction(h_FmPcd, ++ p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction, ++ &p_FmPcdCcTree->keyAndNextEngineParams[i], ++ p_CcTreeTmp, ++ 1, ++ p_FmPcdCcTree); ++ if (err) ++ { ++ FmPcdLockUnlockAll(p_FmPcd); ++ FM_PCD_CcRootDelete(p_FmPcdCcTree); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); ++ return NULL; ++ } ++ p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ } ++ } ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ p_FmPcdCcTree->p_Lock = FmPcdAcquireLock(p_FmPcd); ++ if (!p_FmPcdCcTree->p_Lock) ++ { ++ FM_PCD_CcRootDelete(p_FmPcdCcTree); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM CC lock")); ++ return NULL; ++ } ++ ++ XX_Free(p_Params); ++ ++ return p_FmPcdCcTree; ++} ++ ++t_Error FM_PCD_CcRootDelete(t_Handle h_CcTree) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree; ++ int i= 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE); ++ p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ FmPcdDecNetEnvOwners(p_FmPcd, p_CcTree->netEnvId); ++ ++ if (p_CcTree->owners) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("the tree with this ID can not be removed because this tree is occupied, first - unbind this tree")); ++ ++ /* Delete reassembly schemes if exist */ ++ if (p_CcTree->h_IpReassemblyManip) ++ { ++ FmPcdManipDeleteIpReassmSchemes(p_CcTree->h_IpReassemblyManip); ++ FmPcdManipUpdateOwner(p_CcTree->h_IpReassemblyManip, FALSE); ++ } ++ ++ for (i = 0; i numOfEntries; i++) ++ { ++ if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ UpdateNodeOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE); ++ ++ if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip) ++ FmPcdManipUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip, FALSE); ++ ++#ifdef FM_CAPWAP_SUPPORT ++ if ((p_CcTree->numOfGrps == 1) && ++ (p_CcTree->fmPcdGroupParam[0].numOfEntriesInGroup == 1) && ++ (p_CcTree->keyAndNextEngineParams[0].nextEngineParams.nextEngine == e_FM_PCD_CC) && ++ p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode && ++ IsCapwapApplSpecific(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode)) ++ { ++ if (FM_PCD_ManipNodeDelete(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.h_Manip) != E_OK) ++ return E_INVALID_STATE; ++ } ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) && ++ (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic)) ++ FrmReplicGroupUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic, ++ FALSE); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ if (p_CcTree->p_Lock) ++ FmPcdReleaseLock(p_CcTree->h_FmPcd, p_CcTree->p_Lock); ++ ++ DeleteTree(p_CcTree, p_FmPcd); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_CcRootModifyNextEngine(t_Handle h_CcTree, ++ uint8_t grpId, ++ uint8_t index, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE); ++ p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdCcModifyNextEngineParamTree(p_FmPcd, ++ p_CcTree, ++ grpId, ++ index, ++ p_FmPcdCcNextEngineParams); ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ if (err) ++ { ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodeParam) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *) h_FmPcd; ++ t_FmPcdCcNode *p_CcNode, *p_FmPcdCcNextNode; ++ t_Error err = E_OK; ++ uint32_t tmp, keySize; ++ bool glblMask = FALSE; ++ t_FmPcdCcKeyParams *p_KeyParams; ++ t_Handle h_FmMuram, p_KeysMatchTblTmp, p_AdTableTmp; ++#if (DPAA_VERSION >= 11) ++ t_Handle h_StatsFLRs; ++#endif /* (DPAA_VERSION >= 11) */ ++ bool fullField = FALSE; ++ ccPrivateInfo_t icCode = CC_PRIVATE_INFO_NONE; ++ bool isKeyTblAlloc, fromIc = FALSE; ++ uint32_t matchTableSize, adTableSize; ++ t_CcNodeInformation ccNodeInfo, *p_CcInformation; ++ t_FmPcdStatsObj *p_StatsObj; ++ t_FmPcdCcStatsParams statsParams = {0}; ++ t_Handle h_Manip; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE,NULL); ++ ++ p_CcNode = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode)); ++ if (!p_CcNode) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); ++ return NULL; ++ } ++ memset(p_CcNode, 0, sizeof(t_FmPcdCcNode)); ++ ++ p_CcNode->p_GlblMask = (t_Handle)XX_Malloc(CC_GLBL_MASK_SIZE * sizeof(uint8_t)); ++ memset(p_CcNode->p_GlblMask, 0, CC_GLBL_MASK_SIZE * sizeof(uint8_t)); ++ ++ p_CcNode->h_FmPcd = h_FmPcd; ++ p_CcNode->numOfKeys = p_CcNodeParam->keysParams.numOfKeys; ++ p_CcNode->maxNumOfKeys = p_CcNodeParam->keysParams.maxNumOfKeys; ++ p_CcNode->maskSupport = p_CcNodeParam->keysParams.maskSupport; ++ p_CcNode->statisticsMode = p_CcNodeParam->keysParams.statisticsMode; ++ ++ /* For backward compatibility - even if statistics mode is nullified, ++ we'll fix it to frame mode so we can support per-key request for ++ statistics using 'statisticsEn' in next engine parameters */ ++ if (!p_CcNode->maxNumOfKeys && ++ (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE)) ++ p_CcNode->statisticsMode = e_FM_PCD_CC_STATS_MODE_FRAME; ++ ++ h_FmMuram = FmPcdGetMuramHandle(h_FmPcd); ++ if (!h_FmMuram) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM")); ++ return NULL; ++ } ++ ++ INIT_LIST(&p_CcNode->ccPrevNodesLst); ++ INIT_LIST(&p_CcNode->ccTreeIdLst); ++ INIT_LIST(&p_CcNode->ccTreesLst); ++ INIT_LIST(&p_CcNode->availableStatsLst); ++ ++ p_CcNode->h_Spinlock = XX_InitSpinlock(); ++ if (!p_CcNode->h_Spinlock) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC node spinlock")); ++ return NULL; ++ } ++ ++ if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_BY_HDR) && ++ ((p_CcNodeParam->extractCcParams.extractByHdr.hdr == HEADER_TYPE_IPv4) || ++ (p_CcNodeParam->extractCcParams.extractByHdr.hdr == HEADER_TYPE_IPv6)) && ++ (p_CcNodeParam->extractCcParams.extractByHdr.type == e_FM_PCD_EXTRACT_FULL_FIELD) && ++ ((p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv6 == NET_HEADER_FIELD_IPv6_HOP_LIMIT) || ++ (p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv4 == NET_HEADER_FIELD_IPv4_TTL))) ++ { ++ err = Ipv4TtlOrIpv6HopLimitCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); ++ glblMask = FALSE; ++ } ++ else if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_NON_HDR) && ++ ((p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_KEY) || ++ (p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_HASH) || ++ (p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_FLOW_ID))) ++ { ++ if ((p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_FLOW_ID) && ++ (p_CcNodeParam->extractCcParams.extractNonHdr.offset != 0)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("In the case of the extraction from e_FM_PCD_EXTRACT_FROM_FLOW_ID offset has to be 0")); ++ return NULL; ++ } ++ ++ icCode = IcDefineCode(p_CcNodeParam); ++ fromIc = TRUE; ++ if (icCode == CC_PRIVATE_INFO_NONE) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ++ ("user asked extraction from IC and field in internal context or action wasn't initialized in the right way")); ++ return NULL; ++ } ++ ++ if ((icCode == CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP) || ++ (icCode == CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP)) ++ { ++ err = IcHashIndexedCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); ++ glblMask = TRUE; ++ } ++ else ++ { ++ err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); ++ if (p_CcNode->glblMaskSize) ++ glblMask = TRUE; ++ } ++ } ++ else ++ { ++ err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); ++ if (p_CcNode->glblMaskSize) ++ glblMask = TRUE; ++ } ++ ++ if (err) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return NULL; ++ } ++ ++ switch (p_CcNodeParam->extractCcParams.type) ++ { ++ case (e_FM_PCD_EXTRACT_BY_HDR): ++ switch (p_CcNodeParam->extractCcParams.extractByHdr.type) ++ { ++ case (e_FM_PCD_EXTRACT_FULL_FIELD): ++ p_CcNode->parseCode = ++ GetFullFieldParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr, ++ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex, ++ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField); ++ GetSizeHeaderField(p_CcNodeParam->extractCcParams.extractByHdr.hdr, ++ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex, ++ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField, ++ &p_CcNode->sizeOfExtraction); ++ fullField = TRUE; ++ if ((p_CcNode->parseCode != CC_PC_FF_TCI1) && ++ (p_CcNode->parseCode != CC_PC_FF_TCI2) && ++ (p_CcNode->parseCode != CC_PC_FF_MPLS1) && ++ (p_CcNode->parseCode != CC_PC_FF_MPLS1) && ++ (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC1) && ++ (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC2) && ++ (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1) && ++ (p_CcNode->parseCode != CC_PC_FF_IPDSCP) && ++ (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2) && ++ glblMask) ++ { ++ glblMask = FALSE; ++ p_CcNode->glblMaskSize = 4; ++ p_CcNode->lclMask = TRUE; ++ } ++ break; ++ ++ case (e_FM_PCD_EXTRACT_FROM_HDR): ++ p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.size; ++ p_CcNode->offset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset; ++ p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset; ++ p_CcNode->parseCode = ++ GetPrParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr, ++ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex, ++ p_CcNode->offset,glblMask, ++ &p_CcNode->prsArrayOffset); ++ break; ++ ++ case (e_FM_PCD_EXTRACT_FROM_FIELD): ++ p_CcNode->offset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset; ++ p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset; ++ p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.size; ++ p_CcNode->parseCode = ++ GetFieldParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr, ++ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.field, ++ p_CcNode->offset, ++ &p_CcNode->prsArrayOffset, ++ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex); ++ break; ++ ++ default: ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ return NULL; ++ } ++ break; ++ ++ case (e_FM_PCD_EXTRACT_NON_HDR): ++ /* get the field code for the generic extract */ ++ p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractNonHdr.size; ++ p_CcNode->offset = p_CcNodeParam->extractCcParams.extractNonHdr.offset; ++ p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractNonHdr.offset; ++ p_CcNode->parseCode = ++ GetGenParseCode(h_FmPcd, ++ p_CcNodeParam->extractCcParams.extractNonHdr.src, ++ p_CcNode->offset, ++ glblMask, ++ &p_CcNode->prsArrayOffset, ++ fromIc,icCode); ++ ++ if (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED) ++ { ++ if ((p_CcNode->offset + p_CcNode->sizeOfExtraction) > 8) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_INVALID_SELECTION,("when node of the type CC_PC_GENERIC_IC_HASH_INDEXED offset + size can not be bigger then size of HASH 64 bits (8 bytes)")); ++ return NULL; ++ } ++ } ++ if ((p_CcNode->parseCode == CC_PC_GENERIC_IC_GMASK) || ++ (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED)) ++ { ++ p_CcNode->offset += p_CcNode->prsArrayOffset; ++ p_CcNode->prsArrayOffset = 0; ++ } ++ break; ++ ++ default: ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ return NULL; ++ } ++ ++ if (p_CcNode->parseCode == CC_PC_ILLEGAL) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("illegal extraction type")); ++ return NULL; ++ } ++ ++ if ((p_CcNode->sizeOfExtraction > FM_PCD_MAX_SIZE_OF_KEY) || ++ !p_CcNode->sizeOfExtraction) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("sizeOfExatrction can not be greater than 56 and not 0")); ++ return NULL; ++ } ++ ++ if (p_CcNodeParam->keysParams.keySize != p_CcNode->sizeOfExtraction) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction")); ++ return NULL; ++ } ++ ++ p_CcNode->userSizeOfExtraction = p_CcNode->sizeOfExtraction; ++ ++ if (!glblMask) ++ memset(p_CcNode->p_GlblMask, 0xff, CC_GLBL_MASK_SIZE * sizeof(uint8_t)); ++ ++ err = CheckAndSetManipParamsWithCcNodeParams(p_CcNode); ++ if (err != E_OK) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction")); ++ return NULL; ++ } ++ ++ /* Calculating matching table entry size by rounding up the user-defined size of extraction to valid entry size */ ++ GetCcExtractKeySize(p_CcNode->sizeOfExtraction, &p_CcNode->ccKeySizeAccExtraction); ++ ++ /* If local mask is used, it is stored next to each key in the keys match table */ ++ if (p_CcNode->lclMask) ++ keySize = (uint32_t)(2 * p_CcNode->ccKeySizeAccExtraction); ++ else ++ keySize = p_CcNode->ccKeySizeAccExtraction; ++ ++ /* Update CC shadow with maximal size required by this node */ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ err = CalcAndUpdateCcShadow(p_CcNode, ++ isKeyTblAlloc, ++ &matchTableSize, ++ &adTableSize); ++ if (err != E_OK) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return NULL; ++ } ++ ++ p_CcNode->keysMatchTableMaxSize = matchTableSize; ++ ++ if (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_NONE) ++ { ++ err = AllocStatsObjs(p_CcNode); ++ if (err != E_OK) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return NULL; ++ } ++ } ++ ++ /* If manipulation will be initialized before this node, it will use the table ++ descriptor in the AD table of previous node and this node will need an extra ++ AD as his table descriptor. */ ++ p_CcNode->h_Ad = (t_Handle)FM_MURAM_AllocMem(h_FmMuram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_CcNode->h_Ad) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC action descriptor")); ++ return NULL; ++ } ++ } ++ else ++ { ++ matchTableSize = (uint32_t)(keySize * sizeof(uint8_t) * (p_CcNode->numOfKeys + 1)); ++ adTableSize = (uint32_t)(FM_PCD_CC_AD_ENTRY_SIZE * (p_CcNode->numOfKeys + 1)); ++ } ++ ++#if (DPAA_VERSION >= 11) ++ switch (p_CcNode->statisticsMode) ++ { ++ ++ case e_FM_PCD_CC_STATS_MODE_RMON: ++ /* If RMON statistics or RMON conditional statistics modes are requested, ++ allocate frame length ranges array */ ++ p_CcNode->h_StatsFLRs = ++ FM_MURAM_AllocMem(h_FmMuram, ++ (uint32_t)(p_CcNode->numOfStatsFLRs) * FM_PCD_CC_STATS_FLR_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ ++ if (!p_CcNode->h_StatsFLRs) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC frame length ranges array")); ++ return NULL; ++ } ++ ++ /* Initialize using value received from the user */ ++ for (tmp = 0; tmp < p_CcNode->numOfStatsFLRs; tmp++) ++ { ++ h_StatsFLRs = PTR_MOVE(p_CcNode->h_StatsFLRs, tmp * FM_PCD_CC_STATS_FLR_SIZE); ++ ++ Mem2IOCpy32(h_StatsFLRs, ++ &(p_CcNodeParam->keysParams.frameLengthRanges[tmp]), ++ FM_PCD_CC_STATS_FLR_SIZE); ++ } ++ break; ++ ++ default: ++ break; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++ /* Allocate keys match table. Not required for some CC nodes, for example for IPv4 TTL ++ identification, IPv6 hop count identification, etc. */ ++ if (isKeyTblAlloc) ++ { ++ p_CcNode->h_KeysMatchTable = ++ (t_Handle)FM_MURAM_AllocMem(h_FmMuram, ++ matchTableSize, ++ FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN); ++ if (!p_CcNode->h_KeysMatchTable) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node key match table")); ++ return NULL; ++ } ++ IOMemSet32((uint8_t *)p_CcNode->h_KeysMatchTable, ++ 0, ++ matchTableSize); ++ } ++ ++ /* Allocate action descriptors table */ ++ p_CcNode->h_AdTable = ++ (t_Handle)FM_MURAM_AllocMem(h_FmMuram, ++ adTableSize, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_CcNode->h_AdTable) ++ { ++ DeleteNode(p_CcNode); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptors table")); ++ return NULL; ++ } ++ IOMemSet32((uint8_t *)p_CcNode->h_AdTable, 0, adTableSize); ++ ++ p_KeysMatchTblTmp = p_CcNode->h_KeysMatchTable; ++ p_AdTableTmp = p_CcNode->h_AdTable; ++ ++ /* For each key, create the key and the next step AD */ ++ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++) ++ { ++ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp]; ++ ++ if (p_KeysMatchTblTmp) ++ { ++ /* Copy the key */ ++ Mem2IOCpy32((void*)p_KeysMatchTblTmp, p_KeyParams->p_Key, p_CcNode->sizeOfExtraction); ++ ++ /* Copy the key mask or initialize it to 0xFF..F */ ++ if (p_CcNode->lclMask && p_KeyParams->p_Mask) ++ { ++ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTblTmp, ++ p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */ ++ p_KeyParams->p_Mask, ++ p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */ ++ } ++ else if (p_CcNode->lclMask) ++ { ++ IOMemSet32(PTR_MOVE(p_KeysMatchTblTmp, ++ p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */ ++ 0xff, ++ p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */ ++ } ++ ++ p_KeysMatchTblTmp = PTR_MOVE(p_KeysMatchTblTmp, keySize * sizeof(uint8_t)); ++ } ++ ++ /* Create the next action descriptor in the match table */ ++ if (p_KeyParams->ccNextEngineParams.statisticsEn) ++ { ++ p_StatsObj = GetStatsObj(p_CcNode); ++ ASSERT_COND(p_StatsObj); ++ ++ statsParams.h_StatsAd = p_StatsObj->h_StatsAd; ++ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; ++#if (DPAA_VERSION >= 11) ++ statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs; ++ ++#endif /* (DPAA_VERSION >= 11) */ ++ NextStepAd(p_AdTableTmp, ++ &statsParams, ++ &p_KeyParams->ccNextEngineParams, ++ p_FmPcd); ++ ++ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj; ++ } ++ else ++ { ++ NextStepAd(p_AdTableTmp, ++ NULL, ++ &p_KeyParams->ccNextEngineParams, ++ p_FmPcd); ++ ++ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL; ++ } ++ ++ p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ } ++ ++ /* Update next engine for the 'miss' entry */ ++ if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.statisticsEn) ++ { ++ p_StatsObj = GetStatsObj(p_CcNode); ++ ASSERT_COND(p_StatsObj); ++ ++ statsParams.h_StatsAd = p_StatsObj->h_StatsAd; ++ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; ++#if (DPAA_VERSION >= 11) ++ statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs; ++ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ NextStepAd(p_AdTableTmp, ++ &statsParams, ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ p_FmPcd); ++ ++ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj; ++ } ++ else ++ { ++ NextStepAd(p_AdTableTmp, ++ NULL, ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ p_FmPcd); ++ ++ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL; ++ } ++ ++ /* This parameter will be used to initialize the "key length" field in the action descriptor ++ that points to this node and it should be 0 for full field extraction */ ++ if (fullField == TRUE) ++ p_CcNode->sizeOfExtraction = 0; ++ ++ for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++) ++ { ++ if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ { ++ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode; ++ p_CcInformation = FindNodeInfoInReleventLst(&p_FmPcdCcNextNode->ccPrevNodesLst, ++ (t_Handle)p_CcNode, ++ p_FmPcdCcNextNode->h_Spinlock); ++ if (!p_CcInformation) ++ { ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = (t_Handle)p_CcNode; ++ ccNodeInfo.index = 1; ++ EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccPrevNodesLst, ++ &ccNodeInfo, ++ p_FmPcdCcNextNode->h_Spinlock); ++ } ++ else ++ p_CcInformation->index++; ++ ++ if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip) ++ { ++ h_Manip = p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip; ++ p_CcInformation = FindNodeInfoInReleventLst(FmPcdManipGetNodeLstPointedOnThisManip(h_Manip), ++ (t_Handle)p_CcNode, ++ FmPcdManipGetSpinlock(h_Manip)); ++ if (!p_CcInformation) ++ { ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = (t_Handle)p_CcNode; ++ ccNodeInfo.index = 1; ++ EnqueueNodeInfoToRelevantLst(FmPcdManipGetNodeLstPointedOnThisManip(h_Manip), ++ &ccNodeInfo, ++ FmPcdManipGetSpinlock(h_Manip)); ++ } ++ else ++ p_CcInformation->index++; ++ } ++ } ++ } ++ ++ p_AdTableTmp = p_CcNode->h_AdTable; ++ ++ if (!FmPcdLockTryLockAll(h_FmPcd)) ++ { ++ FM_PCD_MatchTableDelete((t_Handle)p_CcNode); ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return NULL; ++ } ++ ++ /* Required action for each next engine */ ++ for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++) ++ { ++ if (p_CcNode->keyAndNextEngineParams[tmp].requiredAction) ++ { ++ err = SetRequiredAction(h_FmPcd, ++ p_CcNode->keyAndNextEngineParams[tmp].requiredAction, ++ &p_CcNode->keyAndNextEngineParams[tmp], ++ p_AdTableTmp, ++ 1, ++ NULL); ++ if (err) ++ { ++ FmPcdLockUnlockAll(h_FmPcd); ++ FM_PCD_MatchTableDelete((t_Handle)p_CcNode); ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return NULL; ++ } ++ p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ } ++ } ++ ++ FmPcdLockUnlockAll(h_FmPcd); ++ return p_CcNode; ++} ++ ++t_Error FM_PCD_MatchTableDelete(t_Handle h_CcNode) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ int i = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ if (p_CcNode->owners) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("This node cannot be removed because it is occupied; first unbind this node")); ++ ++ for (i = 0; i < p_CcNode->numOfKeys; i++) ++ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ UpdateNodeOwner(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE); ++ ++ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ UpdateNodeOwner(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE); ++ ++ /* Handle also Miss entry */ ++ for (i = 0; i < p_CcNode->numOfKeys + 1; i++) ++ { ++ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip) ++ FmPcdManipUpdateOwner(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip, FALSE); ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) && ++ (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic)) ++ { ++ FrmReplicGroupUpdateOwner(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic, ++ FALSE); ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ DeleteNode(p_CcNode); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_MatchTableAddKey(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_KeyParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (keyIndex == FM_PCD_LAST_KEY_INDEX) ++ keyIndex = p_CcNode->numOfKeys; ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdCcAddKey(p_FmPcd, ++ p_CcNode, ++ keyIndex, ++ keySize, ++ p_KeyParams); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch (GET_ERROR_TYPE(err)) ++ { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableRemoveKey(t_Handle h_CcNode, uint16_t keyIndex) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdCcRemoveKey(p_FmPcd, p_CcNode, keyIndex); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch (GET_ERROR_TYPE(err)) ++ { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_MatchTableModifyKey(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_List h_List; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ INIT_LIST(&h_List); ++ ++ err = FmPcdCcNodeTreeTryLock(p_FmPcd, p_CcNode, &h_List); ++ if (err) ++ { ++ DBG(TRACE, ("Node's trees lock failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdCcModifyKey(p_FmPcd, ++ p_CcNode, ++ keyIndex, ++ keySize, ++ p_Key, ++ p_Mask); ++ ++ FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List); ++ ++ switch (GET_ERROR_TYPE(err)) ++ { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableModifyNextEngine(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = ModifyNextEngineParamNode(p_FmPcd, ++ p_CcNode, ++ keyIndex, ++ p_FmPcdCcNextEngineParams); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch (GET_ERROR_TYPE(err)) ++ { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableModifyMissNextEngine(t_Handle h_CcNode, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdCcModifyMissNextEngineParamNode(p_FmPcd, ++ p_CcNode, ++ p_FmPcdCcNextEngineParams); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch (GET_ERROR_TYPE(err)) ++ { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableModifyKeyAndNextEngine(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_KeyParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdCcModifyKeyAndNextEngine(p_FmPcd, ++ p_CcNode, ++ keyIndex, ++ keySize, ++ p_KeyParams); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch (GET_ERROR_TYPE(err)) ++ { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++ ++t_Error FM_PCD_MatchTableFindNRemoveKey(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint16_t keyIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex); ++ if (GET_ERROR_TYPE(err) != E_OK) ++ { ++ FmPcdLockUnlockAll(p_FmPcd); ++ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the match table of the provided node")); ++ } ++ ++ err = FmPcdCcRemoveKey(p_FmPcd, p_CcNode, keyIndex); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch (GET_ERROR_TYPE(err)) ++ { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++ ++t_Error FM_PCD_MatchTableFindNModifyNextEngine(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint16_t keyIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex); ++ if (GET_ERROR_TYPE(err) != E_OK) ++ { ++ FmPcdLockUnlockAll(p_FmPcd); ++ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the match table of the provided node")); ++ } ++ ++ err = ModifyNextEngineParamNode(p_FmPcd, ++ p_CcNode, ++ keyIndex, ++ p_FmPcdCcNextEngineParams); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch (GET_ERROR_TYPE(err)) ++ { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableFindNModifyKeyAndNextEngine(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ t_FmPcdCcKeyParams *p_KeyParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint16_t keyIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex); ++ if (GET_ERROR_TYPE(err) != E_OK) ++ { ++ FmPcdLockUnlockAll(p_FmPcd); ++ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the match table of the provided node")); ++ } ++ ++ err = FmPcdCcModifyKeyAndNextEngine(p_FmPcd, ++ h_CcNode, ++ keyIndex, ++ keySize, ++ p_KeyParams); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch (GET_ERROR_TYPE(err)) ++ { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableFindNModifyKey(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ uint8_t *p_NewKey, ++ uint8_t *p_NewMask) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_List h_List; ++ uint16_t keyIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_NewKey, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ INIT_LIST(&h_List); ++ ++ err = FmPcdCcNodeTreeTryLock(p_FmPcd, p_CcNode, &h_List); ++ if (err) ++ { ++ DBG(TRACE, ("Node's trees lock failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex); ++ if (GET_ERROR_TYPE(err) != E_OK) ++ { ++ FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List); ++ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the " ++ "match table of the provided node")); ++ } ++ ++ err = FmPcdCcModifyKey(p_FmPcd, ++ p_CcNode, ++ keyIndex, ++ keySize, ++ p_NewKey, ++ p_NewMask); ++ ++ FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List); ++ ++ switch (GET_ERROR_TYPE(err)) ++ { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableGetNextEngine(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ ++ if (keyIndex >= p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("keyIndex exceeds current number of keys")); ++ ++ if (keyIndex > (FM_PCD_MAX_NUM_OF_KEYS - 1)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keyIndex can not be larger than %d", (FM_PCD_MAX_NUM_OF_KEYS - 1))); ++ ++ memcpy(p_FmPcdCcNextEngineParams, ++ &p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ return E_OK; ++} ++ ++ ++uint32_t FM_PCD_MatchTableGetKeyCounter(t_Handle h_CcNode, uint16_t keyIndex) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint32_t *p_StatsCounters, frameCount; ++ uint32_t intFlags; ++ ++ SANITY_CHECK_RETURN_VALUE(p_CcNode, E_INVALID_HANDLE, 0); ++ ++ if (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this match table")); ++ return 0; ++ } ++ ++ if ((p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_FRAME) && ++ (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Frame count is not supported in the statistics mode of this match table")); ++ return 0; ++ } ++ ++ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); ++ ++ if (keyIndex >= p_CcNode->numOfKeys) ++ { ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("The provided keyIndex exceeds the number of keys in this match table")); ++ return 0; ++ } ++ ++ if (!p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ { ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this key")); ++ return 0; ++ } ++ ++ p_StatsCounters = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsCounters; ++ ASSERT_COND(p_StatsCounters); ++ ++ /* The first counter is byte counter, so we need to advance to the next counter */ ++ frameCount = GET_UINT32(*(uint32_t *)(PTR_MOVE(p_StatsCounters, ++ FM_PCD_CC_STATS_COUNTER_SIZE))); ++ ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ ++ return frameCount; ++} ++ ++t_Error FM_PCD_MatchTableGetKeyStatistics(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint32_t intFlags; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER); ++ ++ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); ++ ++ err = MatchTableGetKeyStatistics(p_CcNode, ++ keyIndex, ++ p_KeyStatistics); ++ ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_MatchTableFindNGetKeyStatistics(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint16_t keyIndex; ++ uint32_t intFlags; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER); ++ ++ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); ++ ++ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex); ++ if (GET_ERROR_TYPE(err) != E_OK) ++ { ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the " ++ "match table of the provided node")); ++ } ++ ++ err = MatchTableGetKeyStatistics(p_CcNode, ++ keyIndex, ++ p_KeyStatistics); ++ ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_MatchTableGetIndexedHashBucket(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t hashShift, ++ t_Handle *p_CcNodeBucketHandle, ++ uint8_t *p_BucketIndex, ++ uint16_t *p_LastIndex) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint16_t glblMask; ++ uint64_t crc64 = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNodeBucketHandle, E_NULL_POINTER); ++ ++ memcpy(&glblMask, PTR_MOVE(p_CcNode->p_GlblMask, 2), 2); ++ ++ crc64 = crc64_init(); ++ crc64 = crc64_compute(p_Key, keySize, crc64); ++ crc64 >>= hashShift; ++ ++ *p_BucketIndex = (uint8_t)(((crc64 >> (8 * (6 - p_CcNode->userOffset))) & glblMask) >> 4); ++ if (*p_BucketIndex >= p_CcNode->numOfKeys) ++ RETURN_ERROR(MINOR, E_NOT_IN_RANGE, ("bucket index!")); ++ ++ *p_CcNodeBucketHandle = p_CcNode->keyAndNextEngineParams[*p_BucketIndex].nextEngineParams.params.ccParams.h_CcNode; ++ if (!*p_CcNodeBucketHandle) ++ RETURN_ERROR(MINOR, E_NOT_FOUND, ("bucket!")); ++ ++ *p_LastIndex = ((t_FmPcdCcNode *)*p_CcNodeBucketHandle)->numOfKeys; ++ ++ return E_OK; ++} ++ ++t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) ++{ ++ t_FmPcdCcNode *p_CcNodeHashTbl; ++ t_FmPcdCcNodeParams *p_IndxHashCcNodeParam, *p_ExactMatchCcNodeParam; ++ t_Handle h_CcNode; ++ t_FmPcdCcKeyParams *p_HashKeyParams; ++ int i; ++ uint16_t numOfSets, numOfWays, countMask, onesCount = 0; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_Param, E_NULL_POINTER, NULL); ++ ++ if (p_Param->maxNumOfKeys == 0) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("Max number of keys must be higher then 0")); ++ return NULL; ++ } ++ ++ if (p_Param->hashResMask == 0) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("Hash result mask must differ from 0")); ++ return NULL; ++ } ++ ++#if (DPAA_VERSION >= 11) ++ if (p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_RMON) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("RMON statistics mode is not supported for hash table")); ++ return NULL; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ p_ExactMatchCcNodeParam = (t_FmPcdCcNodeParams*)XX_Malloc(sizeof(t_FmPcdCcNodeParams)); ++ if (!p_ExactMatchCcNodeParam) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_ExactMatchCcNodeParam")); ++ return NULL; ++ } ++ memset(p_ExactMatchCcNodeParam, 0, sizeof(t_FmPcdCcNodeParams)); ++ ++ p_IndxHashCcNodeParam = (t_FmPcdCcNodeParams*)XX_Malloc(sizeof(t_FmPcdCcNodeParams)); ++ if (!p_IndxHashCcNodeParam) ++ { ++ XX_Free(p_ExactMatchCcNodeParam); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_IndxHashCcNodeParam")); ++ return NULL; ++ } ++ memset(p_IndxHashCcNodeParam, 0, sizeof(t_FmPcdCcNodeParams)); ++ ++ /* Calculate number of sets and number of ways of the hash table */ ++ countMask = (uint16_t)(p_Param->hashResMask >> 4); ++ while (countMask) ++ { ++ onesCount++; ++ countMask = (uint16_t)(countMask >> 1); ++ } ++ ++ numOfSets = (uint16_t)(1 << onesCount); ++ numOfWays = (uint16_t)DIV_CEIL(p_Param->maxNumOfKeys, numOfSets); ++ ++ if (p_Param->maxNumOfKeys % numOfSets) ++ DBG(INFO, ("'maxNumOfKeys' is not a multiple of hash number of ways, so number of ways will be rounded up")); ++ ++ /* Building exact-match node params, will be used to create the hash buckets */ ++ p_ExactMatchCcNodeParam->extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR; ++ ++ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.src = e_FM_PCD_EXTRACT_FROM_KEY; ++ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.action = e_FM_PCD_ACTION_EXACT_MATCH; ++ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.offset = 0; ++ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.size = p_Param->matchKeySize; ++ ++ p_ExactMatchCcNodeParam->keysParams.maxNumOfKeys = numOfWays; ++ p_ExactMatchCcNodeParam->keysParams.maskSupport = FALSE; ++ p_ExactMatchCcNodeParam->keysParams.statisticsMode = p_Param->statisticsMode; ++ p_ExactMatchCcNodeParam->keysParams.numOfKeys = 0; ++ p_ExactMatchCcNodeParam->keysParams.keySize = p_Param->matchKeySize; ++ p_ExactMatchCcNodeParam->keysParams.ccNextEngineParamsForMiss = p_Param->ccNextEngineParamsForMiss; ++ ++ p_HashKeyParams = p_IndxHashCcNodeParam->keysParams.keyParams; ++ ++ for (i = 0; i < numOfSets; i++) ++ { ++ h_CcNode = FM_PCD_MatchTableSet(h_FmPcd, p_ExactMatchCcNodeParam); ++ if (!h_CcNode) ++ break; ++ ++ p_HashKeyParams[i].ccNextEngineParams.nextEngine = e_FM_PCD_CC; ++ p_HashKeyParams[i].ccNextEngineParams.statisticsEn = FALSE; ++ p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode = h_CcNode; ++ } ++ ++ if (i < numOfSets) ++ { ++ for (i = i-1; i >=0; i--) ++ FM_PCD_MatchTableDelete(p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode); ++ ++ REPORT_ERROR(MAJOR, E_NULL_POINTER, NO_MSG); ++ XX_Free(p_IndxHashCcNodeParam); ++ XX_Free(p_ExactMatchCcNodeParam); ++ return NULL; ++ } ++ ++ /* Creating indexed-hash CC node */ ++ p_IndxHashCcNodeParam->extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR; ++ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.src = e_FM_PCD_EXTRACT_FROM_HASH; ++ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.action = e_FM_PCD_ACTION_INDEXED_LOOKUP; ++ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.icIndxMask = p_Param->hashResMask; ++ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.offset = p_Param->hashShift; ++ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.size = 2; ++ ++ p_IndxHashCcNodeParam->keysParams.maxNumOfKeys = numOfSets; ++ p_IndxHashCcNodeParam->keysParams.maskSupport = FALSE; ++ p_IndxHashCcNodeParam->keysParams.statisticsMode = e_FM_PCD_CC_STATS_MODE_NONE; ++ p_IndxHashCcNodeParam->keysParams.numOfKeys = numOfSets; /* Number of keys of this node is number of sets of the hash */ ++ p_IndxHashCcNodeParam->keysParams.keySize = 2; ++ ++ p_CcNodeHashTbl = FM_PCD_MatchTableSet(h_FmPcd, p_IndxHashCcNodeParam); ++ ++ XX_Free(p_IndxHashCcNodeParam); ++ XX_Free(p_ExactMatchCcNodeParam); ++ ++ return p_CcNodeHashTbl; ++} ++ ++t_Error FM_PCD_HashTableDelete(t_Handle h_HashTbl) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle *p_HashBuckets; ++ uint16_t i, numOfBuckets; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ ++ numOfBuckets = p_HashTbl->numOfKeys; ++ ++ p_HashBuckets = (t_Handle *)XX_Malloc(numOfBuckets * sizeof(t_Handle)); ++ if (!p_HashBuckets) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ ++ for (i = 0; i < numOfBuckets; i++) ++ p_HashBuckets[i] = p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; ++ ++ err = FM_PCD_MatchTableDelete(p_HashTbl); ++ ++ for (i = 0; i < numOfBuckets; i++) ++ err |= FM_PCD_MatchTableDelete(p_HashBuckets[i]); ++ ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ XX_Free(p_HashBuckets); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_HashTableAddKey(t_Handle h_HashTbl, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_KeyParams) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle h_HashBucket; ++ uint8_t bucketIndex; ++ uint16_t lastIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_KeyParams->p_Key, E_NULL_POINTER); ++ ++ if (p_KeyParams->p_Mask) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Keys masks not supported for hash table")); ++ ++ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl, ++ keySize, ++ p_KeyParams->p_Key, ++ p_HashTbl->userOffset, ++ &h_HashBucket, ++ &bucketIndex, ++ &lastIndex); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return FM_PCD_MatchTableAddKey(h_HashBucket, ++ FM_PCD_LAST_KEY_INDEX, ++ keySize, ++ p_KeyParams); ++} ++ ++t_Error FM_PCD_HashTableRemoveKey(t_Handle h_HashTbl, ++ uint8_t keySize, ++ uint8_t *p_Key) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle h_HashBucket; ++ uint8_t bucketIndex; ++ uint16_t lastIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ ++ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl, ++ keySize, ++ p_Key, ++ p_HashTbl->userOffset, ++ &h_HashBucket, ++ &bucketIndex, ++ &lastIndex); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return FM_PCD_MatchTableFindNRemoveKey(h_HashBucket, ++ keySize, ++ p_Key, ++ NULL); ++} ++ ++t_Error FM_PCD_HashTableModifyNextEngine(t_Handle h_HashTbl, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle h_HashBucket; ++ uint8_t bucketIndex; ++ uint16_t lastIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ ++ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl, ++ keySize, ++ p_Key, ++ p_HashTbl->userOffset, ++ &h_HashBucket, ++ &bucketIndex, ++ &lastIndex); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return FM_PCD_MatchTableFindNModifyNextEngine(h_HashBucket, ++ keySize, ++ p_Key, ++ NULL, ++ p_FmPcdCcNextEngineParams); ++} ++ ++t_Error FM_PCD_HashTableModifyMissNextEngine(t_Handle h_HashTbl, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle h_HashBucket; ++ uint8_t i; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(h_HashTbl, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ ++ for (i = 0; i < p_HashTbl->numOfKeys; i++) ++ { ++ h_HashBucket = p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; ++ ++ err = FM_PCD_MatchTableModifyMissNextEngine(h_HashBucket, ++ p_FmPcdCcNextEngineParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++ ++t_Error FM_PCD_HashTableGetMissNextEngine(t_Handle h_HashTbl, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_FmPcdCcNode *p_HashBucket; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ ++ /* Miss next engine of each bucket was initialized with the next engine of the hash table */ ++ p_HashBucket = p_HashTbl->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode; ++ ++ memcpy(p_FmPcdCcNextEngineParams, ++ &p_HashBucket->keyAndNextEngineParams[p_HashBucket->numOfKeys].nextEngineParams, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_HashTableFindNGetKeyStatistics(t_Handle h_HashTbl, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle h_HashBucket; ++ uint8_t bucketIndex; ++ uint16_t lastIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER); ++ ++ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl, ++ keySize, ++ p_Key, ++ p_HashTbl->userOffset, ++ &h_HashBucket, ++ &bucketIndex, ++ &lastIndex); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return FM_PCD_MatchTableFindNGetKeyStatistics(h_HashBucket, ++ keySize, ++ p_Key, ++ NULL, ++ p_KeyStatistics); ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_cc.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_cc.h +new file mode 100644 +index 0000000..9efe721 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_cc.h +@@ -0,0 +1,390 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_cc.h ++ ++ @Description FM PCD CC ... ++*//***************************************************************************/ ++#ifndef __FM_CC_H ++#define __FM_CC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++ ++#include "fm_pcd.h" ++ ++ ++/***********************************************************************/ ++/* Coarse classification defines */ ++/***********************************************************************/ ++ ++#define CC_MAX_NUM_OF_KEYS MAX(FM_PCD_MAX_NUM_OF_KEYS + 1, FM_PCD_MAX_NUM_OF_FLOWS) ++ ++#define CC_PC_FF_MACDST 0x00 ++#define CC_PC_FF_MACSRC 0x01 ++#define CC_PC_FF_ETYPE 0x02 ++ ++#define CC_PC_FF_TCI1 0x03 ++#define CC_PC_FF_TCI2 0x04 ++ ++#define CC_PC_FF_MPLS1 0x06 ++#define CC_PC_FF_MPLS_LAST 0x07 ++ ++#define CC_PC_FF_IPV4DST1 0x08 ++#define CC_PC_FF_IPV4DST2 0x16 ++#define CC_PC_FF_IPV4IPTOS_TC1 0x09 ++#define CC_PC_FF_IPV4IPTOS_TC2 0x17 ++#define CC_PC_FF_IPV4PTYPE1 0x0A ++#define CC_PC_FF_IPV4PTYPE2 0x18 ++#define CC_PC_FF_IPV4SRC1 0x0b ++#define CC_PC_FF_IPV4SRC2 0x19 ++#define CC_PC_FF_IPV4SRC1_IPV4DST1 0x0c ++#define CC_PC_FF_IPV4SRC2_IPV4DST2 0x1a ++#define CC_PC_FF_IPV4TTL 0x29 ++ ++ ++#define CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1 0x0d /*TODO - CLASS - what is it? TOS*/ ++#define CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2 0x1b ++#define CC_PC_FF_IPV6PTYPE1 0x0e ++#define CC_PC_FF_IPV6PTYPE2 0x1c ++#define CC_PC_FF_IPV6DST1 0x0f ++#define CC_PC_FF_IPV6DST2 0x1d ++#define CC_PC_FF_IPV6SRC1 0x10 ++#define CC_PC_FF_IPV6SRC2 0x1e ++#define CC_PC_FF_IPV6HOP_LIMIT 0x2a ++#define CC_PC_FF_IPPID 0x24 ++#define CC_PC_FF_IPDSCP 0x76 ++ ++#define CC_PC_FF_GREPTYPE 0x11 ++ ++#define CC_PC_FF_MINENCAP_PTYPE 0x12 ++#define CC_PC_FF_MINENCAP_IPDST 0x13 ++#define CC_PC_FF_MINENCAP_IPSRC 0x14 ++#define CC_PC_FF_MINENCAP_IPSRC_IPDST 0x15 ++ ++#define CC_PC_FF_L4PSRC 0x1f ++#define CC_PC_FF_L4PDST 0x20 ++#define CC_PC_FF_L4PSRC_L4PDST 0x21 ++ ++#define CC_PC_FF_PPPPID 0x05 ++ ++#define CC_PC_PR_SHIM1 0x22 ++#define CC_PC_PR_SHIM2 0x23 ++ ++#define CC_PC_GENERIC_WITHOUT_MASK 0x27 ++#define CC_PC_GENERIC_WITH_MASK 0x28 ++#define CC_PC_GENERIC_IC_GMASK 0x2B ++#define CC_PC_GENERIC_IC_HASH_INDEXED 0x2C ++ ++#define CC_PR_OFFSET 0x25 ++#define CC_PR_WITHOUT_OFFSET 0x26 ++ ++#define CC_PC_PR_ETH_OFFSET 19 ++#define CC_PC_PR_USER_DEFINED_SHIM1_OFFSET 16 ++#define CC_PC_PR_USER_DEFINED_SHIM2_OFFSET 17 ++#define CC_PC_PR_USER_LLC_SNAP_OFFSET 20 ++#define CC_PC_PR_VLAN1_OFFSET 21 ++#define CC_PC_PR_VLAN2_OFFSET 22 ++#define CC_PC_PR_PPPOE_OFFSET 24 ++#define CC_PC_PR_MPLS1_OFFSET 25 ++#define CC_PC_PR_MPLS_LAST_OFFSET 26 ++#define CC_PC_PR_IP1_OFFSET 27 ++#define CC_PC_PR_IP_LAST_OFFSET 28 ++#define CC_PC_PR_MINENC_OFFSET 28 ++#define CC_PC_PR_L4_OFFSET 30 ++#define CC_PC_PR_GRE_OFFSET 29 ++#define CC_PC_PR_ETYPE_LAST_OFFSET 23 ++#define CC_PC_PR_NEXT_HEADER_OFFSET 31 ++ ++#define CC_PC_ILLEGAL 0xff ++#define CC_SIZE_ILLEGAL 0 ++ ++#define FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN 16 ++#define FM_PCD_CC_AD_TABLE_ALIGN 16 ++#define FM_PCD_CC_AD_ENTRY_SIZE 16 ++#define FM_PCD_CC_NUM_OF_KEYS 255 ++#define FM_PCD_CC_TREE_ADDR_ALIGN 256 ++ ++#define FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE 0x00000000 ++#define FM_PCD_AD_RESULT_DATA_FLOW_TYPE 0x80000000 ++#define FM_PCD_AD_RESULT_PLCR_DIS 0x20000000 ++#define FM_PCD_AD_RESULT_EXTENDED_MODE 0x80000000 ++#define FM_PCD_AD_RESULT_NADEN 0x20000000 ++#define FM_PCD_AD_RESULT_STATISTICS_EN 0x40000000 ++ ++#define FM_PCD_AD_CONT_LOOKUP_TYPE 0x40000000 ++#define FM_PCD_AD_CONT_LOOKUP_LCL_MASK 0x00800000 ++ ++#define FM_PCD_AD_STATS_TYPE 0x40000000 ++#define FM_PCD_AD_STATS_FLR_ADDR_MASK 0x00FFFFFF ++#define FM_PCD_AD_STATS_COUNTERS_ADDR_MASK 0x00FFFFFF ++#define FM_PCD_AD_STATS_NEXT_ACTION_MASK 0xFFFF0000 ++#define FM_PCD_AD_STATS_NEXT_ACTION_SHIFT 12 ++#define FM_PCD_AD_STATS_NAD_EN 0x00008000 ++#define FM_PCD_AD_STATS_OP_CODE 0x00000036 ++#define FM_PCD_AD_STATS_FLR_EN 0x00004000 ++#define FM_PCD_AD_STATS_COND_EN 0x00002000 ++ ++ ++ ++#define FM_PCD_AD_BYPASS_TYPE 0xc0000000 ++ ++#define FM_PCD_AD_TYPE_MASK 0xc0000000 ++#define FM_PCD_AD_OPCODE_MASK 0x0000000f ++ ++#define FM_PCD_AD_PROFILEID_FOR_CNTRL_SHIFT 16 ++#if (DPAA_VERSION >= 11) ++#define FM_PCD_AD_RESULT_VSP_SHIFT 24 ++#define FM_PCD_AD_RESULT_NO_OM_VSPE 0x02000000 ++#define FM_PCD_AD_RESULT_VSP_MASK 0x3f ++#define FM_PCD_AD_NCSPFQIDM_MASK 0x80000000 ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#define GLBL_MASK_FOR_HASH_INDEXED 0xfff00000 ++#define CC_GLBL_MASK_SIZE 4 ++ ++typedef uint32_t ccPrivateInfo_t; /**< private info of CC: */ ++ ++#define CC_PRIVATE_INFO_NONE 0 ++#define CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP 0x80000000 ++#define CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH 0x40000000 ++#define CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH 0x20000000 ++#define CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP 0x10000000 ++ ++/***********************************************************************/ ++/* Memory map */ ++/***********************************************************************/ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++typedef _Packed struct ++{ ++ volatile uint32_t fqid; ++ volatile uint32_t plcrProfile; ++ volatile uint32_t nia; ++ volatile uint32_t res; ++} _PackedType t_AdOfTypeResult; ++ ++typedef _Packed struct ++{ ++ volatile uint32_t ccAdBase; ++ volatile uint32_t matchTblPtr; ++ volatile uint32_t pcAndOffsets; ++ volatile uint32_t gmask; ++} _PackedType t_AdOfTypeContLookup; ++ ++typedef _Packed struct ++{ ++ volatile uint32_t profileTableAddr; ++ volatile uint32_t reserved; ++ volatile uint32_t nextActionIndx; ++ volatile uint32_t statsTableAddr; ++} _PackedType t_AdOfTypeStats; ++ ++typedef _Packed union ++{ ++ volatile t_AdOfTypeResult adResult; ++ volatile t_AdOfTypeContLookup adContLookup; ++} _PackedType t_Ad; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/***********************************************************************/ ++/* Driver's internal structures */ ++/***********************************************************************/ ++ ++typedef enum e_ModifyState ++{ ++ e_MODIFY_STATE_ADD = 0, ++ e_MODIFY_STATE_REMOVE, ++ e_MODIFY_STATE_CHANGE ++} e_ModifyState; ++ ++typedef struct t_FmPcdStatsObj ++{ ++ t_Handle h_StatsAd; ++ t_Handle h_StatsCounters; ++ t_List node; ++} t_FmPcdStatsObj; ++ ++typedef struct ++{ ++ uint8_t key[FM_PCD_MAX_SIZE_OF_KEY]; ++ uint8_t mask[FM_PCD_MAX_SIZE_OF_KEY]; ++ ++ t_FmPcdCcNextEngineParams nextEngineParams; ++ uint32_t requiredAction; ++ uint32_t shadowAction; ++ ++ t_FmPcdStatsObj *p_StatsObj; ++ ++} t_FmPcdCcKeyAndNextEngineParams; ++ ++typedef struct ++{ ++ t_Handle p_Ad; ++ e_FmPcdEngine fmPcdEngine; ++ bool adAllocated; ++ bool isTree; ++ ++ uint32_t myInfo; ++ t_List *h_CcNextNodesLst; ++ t_Handle h_AdditionalInfo; ++ t_Handle h_Node; ++} t_FmPcdModifyCcAdditionalParams; ++ ++typedef struct ++{ ++ t_Handle p_AdTableNew; ++ t_Handle p_KeysMatchTableNew; ++ t_Handle p_AdTableOld; ++ t_Handle p_KeysMatchTableOld; ++ uint16_t numOfKeys; ++ t_Handle h_CurrentNode; ++ uint16_t savedKeyIndex; ++ t_Handle h_NodeForAdd; ++ t_Handle h_NodeForRmv; ++ t_Handle h_ManipForRmv; ++ t_Handle h_ManipForAdd; ++ t_FmPcdStatsObj *p_StatsObjForRmv; ++#if (DPAA_VERSION >= 11) ++ t_Handle h_FrmReplicForAdd; ++ t_Handle h_FrmReplicForRmv; ++#endif /* (DPAA_VERSION >= 11) */ ++ bool tree; ++ ++ t_FmPcdCcKeyAndNextEngineParams keyAndNextEngineParams[CC_MAX_NUM_OF_KEYS]; ++} t_FmPcdModifyCcKeyAdditionalParams; ++ ++typedef struct ++{ ++ t_Handle h_Manip; ++ t_Handle h_CcNode; ++} t_CcNextEngineInfo; ++ ++typedef struct ++{ ++ uint16_t numOfKeys; ++ uint16_t maxNumOfKeys; ++ ++ bool maskSupport; ++ uint32_t keysMatchTableMaxSize; ++ ++ e_FmPcdCcStatsMode statisticsMode; ++ uint32_t numOfStatsFLRs; ++ uint32_t countersArraySize; ++ ++ bool glblMaskUpdated; ++ t_Handle p_GlblMask; ++ bool lclMask; ++ uint8_t parseCode; ++ uint8_t offset; ++ uint8_t prsArrayOffset; ++ bool ctrlFlow; ++ uint8_t owners; ++ ++ uint8_t ccKeySizeAccExtraction; ++ uint8_t sizeOfExtraction; ++ uint8_t glblMaskSize; ++ ++ t_Handle h_KeysMatchTable; ++ t_Handle h_AdTable; ++ t_Handle h_StatsAds; ++ t_Handle h_Ad; ++ t_Handle h_StatsFLRs; ++ ++ t_List availableStatsLst; ++ ++ t_List ccPrevNodesLst; ++ ++ t_List ccTreeIdLst; ++ t_List ccTreesLst; ++ ++ t_Handle h_FmPcd; ++ uint32_t shadowAction; ++ uint8_t userSizeOfExtraction; ++ uint8_t userOffset; ++ ++ t_Handle h_Spinlock; ++ ++ t_FmPcdCcKeyAndNextEngineParams keyAndNextEngineParams[CC_MAX_NUM_OF_KEYS]; ++} t_FmPcdCcNode; ++ ++typedef struct ++{ ++ t_FmPcdCcNode *p_FmPcdCcNode; ++ bool occupied; ++ uint8_t owners; ++ volatile bool lock; ++} t_FmPcdCcNodeArray; ++ ++typedef struct ++{ ++ uint8_t numOfEntriesInGroup; ++ uint32_t totalBitsMask; ++ uint8_t baseGroupEntry; ++} t_FmPcdCcGroupParam; ++ ++typedef struct ++{ ++ t_Handle h_FmPcd; ++ uint8_t netEnvId; ++ uintptr_t ccTreeBaseAddr; ++ uint8_t numOfGrps; ++ t_FmPcdCcGroupParam fmPcdGroupParam[FM_PCD_MAX_NUM_OF_CC_GROUPS]; ++ t_List fmPortsLst; ++ t_FmPcdLock *p_Lock; ++ uint8_t numOfEntries; ++ uint8_t owners; ++ t_Handle h_FmPcdCcSavedManipParams; ++ bool modifiedState; ++ uint32_t requiredAction; ++ t_Handle h_IpReassemblyManip; ++ ++ t_FmPcdCcKeyAndNextEngineParams keyAndNextEngineParams[FM_PCD_MAX_NUM_OF_CC_GROUPS]; ++} t_FmPcdCcTree; ++ ++ ++bool FmPcdManipIsManipNode(t_Handle h_Ad); ++t_Error FmPcdCcNodeTreeTryLock(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, t_List *p_List); ++void FmPcdCcNodeTreeReleaseLock(t_Handle h_FmPcd, t_List *p_List); ++t_Error FmPcdUpdateCcShadow (t_FmPcd *p_FmPcd, uint32_t size, uint32_t align); ++ ++ ++#endif /* __FM_CC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_kg.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_kg.c +new file mode 100644 +index 0000000..bdbc8ae +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_kg.c +@@ -0,0 +1,3263 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_kg.c ++ ++ @Description FM PCD ... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "net_ext.h" ++#include "fm_port_ext.h" ++ ++#include "fm_common.h" ++#include "fm_pcd.h" ++#include "fm_hc.h" ++#include "fm_pcd_ipc.h" ++#include "fm_kg.h" ++#include "fsl_fman_kg.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++static uint32_t KgHwLock(t_Handle h_FmPcdKg) ++{ ++ ASSERT_COND(h_FmPcdKg); ++ return XX_LockIntrSpinlock(((t_FmPcdKg *)h_FmPcdKg)->h_HwSpinlock); ++} ++ ++static void KgHwUnlock(t_Handle h_FmPcdKg, uint32_t intFlags) ++{ ++ ASSERT_COND(h_FmPcdKg); ++ XX_UnlockIntrSpinlock(((t_FmPcdKg *)h_FmPcdKg)->h_HwSpinlock, intFlags); ++} ++ ++static uint32_t KgSchemeLock(t_Handle h_Scheme) ++{ ++ ASSERT_COND(h_Scheme); ++ return FmPcdLockSpinlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock); ++} ++ ++static void KgSchemeUnlock(t_Handle h_Scheme, uint32_t intFlags) ++{ ++ ASSERT_COND(h_Scheme); ++ FmPcdUnlockSpinlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock, intFlags); ++} ++ ++static bool KgSchemeFlagTryLock(t_Handle h_Scheme) ++{ ++ ASSERT_COND(h_Scheme); ++ return FmPcdLockTryLock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock); ++} ++ ++static void KgSchemeFlagUnlock(t_Handle h_Scheme) ++{ ++ ASSERT_COND(h_Scheme); ++ FmPcdLockUnlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock); ++} ++ ++static t_Error WriteKgarWait(t_FmPcd *p_FmPcd, uint32_t fmkg_ar) ++{ ++ ++ struct fman_kg_regs *regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ if (fman_kg_write_ar_wait(regs, fmkg_ar)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Keygen scheme access violation")); ++ ++ return E_OK; ++} ++ ++static e_FmPcdKgExtractDfltSelect GetGenericSwDefault(t_FmPcdKgExtractDflt swDefaults[], uint8_t numOfSwDefaults, uint8_t code) ++{ ++ int i; ++ ++ switch (code) ++ { ++ case (KG_SCH_GEN_PARSE_RESULT_N_FQID): ++ case (KG_SCH_GEN_DEFAULT): ++ case (KG_SCH_GEN_NEXTHDR): ++ for (i=0 ; ifmRevInfo.majorRev < 6) ++ return KG_SCH_KN_PTYPE2; ++#endif /* FM_KG_NO_IPPID_SUPPORT */ ++ return KG_SCH_KN_IPPID; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return 0; ++ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return (KG_SCH_KN_IPV6FL1 | KG_SCH_KN_IPTOS_TC1); ++ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST)) ++ return (KG_SCH_KN_IPV6FL2 | KG_SCH_KN_IPTOS_TC2); ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return 0; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_GRE): ++ switch (field.gre) ++ { ++ case (NET_HEADER_FIELD_GRE_TYPE): ++ return KG_SCH_KN_GREPTYPE; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_MINENCAP): ++ switch (field.minencap) ++ { ++ case (NET_HEADER_FIELD_MINENCAP_SRC_IP): ++ return KG_SCH_KN_IPSRC2; ++ case (NET_HEADER_FIELD_MINENCAP_DST_IP): ++ return KG_SCH_KN_IPDST2; ++ case (NET_HEADER_FIELD_MINENCAP_TYPE): ++ return KG_SCH_KN_PTYPE2; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_TCP): ++ switch (field.tcp) ++ { ++ case (NET_HEADER_FIELD_TCP_PORT_SRC): ++ return KG_SCH_KN_L4PSRC; ++ case (NET_HEADER_FIELD_TCP_PORT_DST): ++ return KG_SCH_KN_L4PDST; ++ case (NET_HEADER_FIELD_TCP_FLAGS): ++ return KG_SCH_KN_TFLG; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_UDP): ++ switch (field.udp) ++ { ++ case (NET_HEADER_FIELD_UDP_PORT_SRC): ++ return KG_SCH_KN_L4PSRC; ++ case (NET_HEADER_FIELD_UDP_PORT_DST): ++ return KG_SCH_KN_L4PDST; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_IPSEC_AH): ++ switch (field.ipsecAh) ++ { ++ case (NET_HEADER_FIELD_IPSEC_AH_SPI): ++ return KG_SCH_KN_IPSEC_SPI; ++ case (NET_HEADER_FIELD_IPSEC_AH_NH): ++ return KG_SCH_KN_IPSEC_NH; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_IPSEC_ESP): ++ switch (field.ipsecEsp) ++ { ++ case (NET_HEADER_FIELD_IPSEC_ESP_SPI): ++ return KG_SCH_KN_IPSEC_SPI; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_SCTP): ++ switch (field.sctp) ++ { ++ case (NET_HEADER_FIELD_SCTP_PORT_SRC): ++ return KG_SCH_KN_L4PSRC; ++ case (NET_HEADER_FIELD_SCTP_PORT_DST): ++ return KG_SCH_KN_L4PDST; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_DCCP): ++ switch (field.dccp) ++ { ++ case (NET_HEADER_FIELD_DCCP_PORT_SRC): ++ return KG_SCH_KN_L4PSRC; ++ case (NET_HEADER_FIELD_DCCP_PORT_DST): ++ return KG_SCH_KN_L4PDST; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_PPPoE): ++ switch (field.pppoe) ++ { ++ case (NET_HEADER_FIELD_PPPoE_PID): ++ return KG_SCH_KN_PPPID; ++ case (NET_HEADER_FIELD_PPPoE_SID): ++ return KG_SCH_KN_PPPSID; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++} ++ ++ ++static uint8_t GetKnownFieldId(uint32_t bitMask) ++{ ++ uint8_t cnt = 0; ++ ++ while (bitMask) ++ if (bitMask & 0x80000000) ++ break; ++ else ++ { ++ cnt++; ++ bitMask <<= 1; ++ } ++ return cnt; ++ ++} ++ ++static uint8_t GetExtractedOrMask(uint8_t bitOffset, bool fqid) ++{ ++ uint8_t i, mask, numOfOnesToClear, walking1Mask = 1; ++ ++ /* bitOffset 1-7 --> mask 0x1-0x7F */ ++ if (bitOffset<8) ++ { ++ mask = 0; ++ for (i = 0 ; i < bitOffset ; i++, walking1Mask <<= 1) ++ mask |= walking1Mask; ++ } ++ else ++ { ++ mask = 0xFF; ++ numOfOnesToClear = 0; ++ if (fqid && bitOffset>24) ++ /* bitOffset 25-31 --> mask 0xFE-0x80 */ ++ numOfOnesToClear = (uint8_t)(bitOffset-24); ++ else ++ /* bitOffset 9-15 --> mask 0xFE-0x80 */ ++ if (!fqid && bitOffset>8) ++ numOfOnesToClear = (uint8_t)(bitOffset-8); ++ for (i = 0 ; i < numOfOnesToClear ; i++, walking1Mask <<= 1) ++ mask &= ~walking1Mask; ++ /* bitOffset 8-24 for FQID, 8 for PP --> no mask (0xFF)*/ ++ } ++ return mask; ++} ++ ++static void IncSchemeOwners(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort) ++{ ++ t_FmPcdKg *p_FmPcdKg; ++ t_FmPcdKgScheme *p_Scheme; ++ uint32_t intFlags; ++ uint8_t relativeSchemeId; ++ int i; ++ ++ p_FmPcdKg = p_FmPcd->p_FmPcdKg; ++ ++ /* for each scheme - update owners counters */ ++ for (i = 0; i < p_BindPort->numOfSchemes; i++) ++ { ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]); ++ ASSERT_COND(relativeSchemeId < FM_PCD_KG_NUM_OF_SCHEMES); ++ ++ p_Scheme = &p_FmPcdKg->schemes[relativeSchemeId]; ++ ++ /* increment owners number */ ++ intFlags = KgSchemeLock(p_Scheme); ++ p_Scheme->owners++; ++ KgSchemeUnlock(p_Scheme, intFlags); ++ } ++} ++ ++static void DecSchemeOwners(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort) ++{ ++ t_FmPcdKg *p_FmPcdKg; ++ t_FmPcdKgScheme *p_Scheme; ++ uint32_t intFlags; ++ uint8_t relativeSchemeId; ++ int i; ++ ++ p_FmPcdKg = p_FmPcd->p_FmPcdKg; ++ ++ /* for each scheme - update owners counters */ ++ for (i = 0; i < p_BindPort->numOfSchemes; i++) ++ { ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]); ++ ASSERT_COND(relativeSchemeId < FM_PCD_KG_NUM_OF_SCHEMES); ++ ++ p_Scheme = &p_FmPcdKg->schemes[relativeSchemeId]; ++ ++ /* increment owners number */ ++ ASSERT_COND(p_Scheme->owners); ++ intFlags = KgSchemeLock(p_Scheme); ++ p_Scheme->owners--; ++ KgSchemeUnlock(p_Scheme, intFlags); ++ } ++} ++ ++static void UpateSchemePointedOwner(t_FmPcdKgScheme *p_Scheme, bool add) ++{ ++ /* this routine is locked by the calling routine */ ++ ASSERT_COND(p_Scheme); ++ ASSERT_COND(p_Scheme->valid); ++ ++ if (add) ++ p_Scheme->pointedOwners++; ++ else ++ p_Scheme->pointedOwners--; ++} ++ ++static t_Error KgWriteSp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint32_t spReg, bool add) ++{ ++ struct fman_kg_regs *p_KgRegs; ++ ++ uint32_t tmpKgarReg = 0, intFlags; ++ t_Error err = E_OK; ++ ++ /* The calling routine had locked the port, so for each port only one core can access ++ * (so we don't need a lock here) */ ++ ++ if (p_FmPcd->h_Hc) ++ return FmHcKgWriteSp(p_FmPcd->h_Hc, hardwarePortId, spReg, add); ++ ++ p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ tmpKgarReg = FmPcdKgBuildReadPortSchemeBindActionReg(hardwarePortId); ++ /* lock a common KG reg */ ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ err = WriteKgarWait(p_FmPcd, tmpKgarReg); ++ if (err) ++ { ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ fman_kg_write_sp(p_KgRegs, spReg, add); ++ ++ tmpKgarReg = FmPcdKgBuildWritePortSchemeBindActionReg(hardwarePortId); ++ ++ err = WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ return err; ++} ++ ++static t_Error KgWriteCpp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint32_t cppReg) ++{ ++ struct fman_kg_regs *p_KgRegs; ++ uint32_t tmpKgarReg, intFlags; ++ t_Error err; ++ ++ p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcKgWriteCpp(p_FmPcd->h_Hc, hardwarePortId, cppReg); ++ return err; ++ } ++ ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ fman_kg_write_cpp(p_KgRegs, cppReg); ++ tmpKgarReg = FmPcdKgBuildWritePortClsPlanBindActionReg(hardwarePortId); ++ err = WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ ++ return err; ++} ++ ++static uint32_t BuildCppReg(t_FmPcd *p_FmPcd, uint8_t clsPlanGrpId) ++{ ++ uint32_t tmpKgpeCpp; ++ ++ tmpKgpeCpp = (uint32_t)(p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].baseEntry / 8); ++ tmpKgpeCpp |= (uint32_t)(((p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].sizeOfGrp / 8) - 1) << FM_KG_PE_CPP_MASK_SHIFT); ++ ++ return tmpKgpeCpp; ++} ++ ++static t_Error BindPortToClsPlanGrp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId) ++{ ++ uint32_t tmpKgpeCpp = 0; ++ ++ tmpKgpeCpp = BuildCppReg(p_FmPcd, clsPlanGrpId); ++ return KgWriteCpp(p_FmPcd, hardwarePortId, tmpKgpeCpp); ++} ++ ++static void UnbindPortToClsPlanGrp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId) ++{ ++ KgWriteCpp(p_FmPcd, hardwarePortId, 0); ++} ++ ++static uint32_t ReadClsPlanBlockActionReg(uint8_t grpId) ++{ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ FM_KG_KGAR_READ | ++ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY | ++ DUMMY_PORT_ID | ++ ((uint32_t)grpId << FM_PCD_KG_KGAR_NUM_SHIFT) | ++ FM_PCD_KG_KGAR_WSEL_MASK); ++ ++ /* if we ever want to write 1 by 1, use: ++ sel = (uint8_t)(0x01 << (7- (entryId % CLS_PLAN_NUM_PER_GRP))); ++ */ ++} ++ ++static void PcdKgErrorException(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint32_t event,schemeIndexes = 0, index = 0; ++ struct fman_kg_regs *p_KgRegs; ++ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ fman_kg_get_event(p_KgRegs, &event, &schemeIndexes); ++ ++ if (event & FM_EX_KG_DOUBLE_ECC) ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC); ++ if (event & FM_EX_KG_KEYSIZE_OVERFLOW) ++ { ++ if (schemeIndexes) ++ { ++ while (schemeIndexes) ++ { ++ if (schemeIndexes & 0x1) ++ p_FmPcd->f_FmPcdIndexedException(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW, (uint16_t)(31 - index)); ++ schemeIndexes >>= 1; ++ index+=1; ++ } ++ } ++ else /* this should happen only when interrupt is forced. */ ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW); ++ } ++} ++ ++static t_Error KgInitGuest(t_FmPcd *p_FmPcd) ++{ ++ t_Error err = E_OK; ++ t_FmPcdIpcKgSchemesParams kgAlloc; ++ uint32_t replyLength; ++ t_FmPcdIpcReply reply; ++ t_FmPcdIpcMsg msg; ++ ++ ASSERT_COND(p_FmPcd->guestId != NCSW_MASTER_ID); ++ ++ /* in GUEST_PARTITION, we use the IPC */ ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ memset(&kgAlloc, 0, sizeof(t_FmPcdIpcKgSchemesParams)); ++ kgAlloc.numOfSchemes = p_FmPcd->p_FmPcdKg->numOfSchemes; ++ kgAlloc.guestId = p_FmPcd->guestId; ++ msg.msgId = FM_PCD_ALLOC_KG_SCHEMES; ++ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc)); ++ replyLength = sizeof(uint32_t) + p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(kgAlloc), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != (sizeof(uint32_t) + p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ memcpy(p_FmPcd->p_FmPcdKg->schemesIds, (uint8_t*)(reply.replyBody),p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t)); ++ ++ return (t_Error)reply.error; ++} ++ ++static t_Error KgInitMaster(t_FmPcd *p_FmPcd) ++{ ++ t_Error err = E_OK; ++ struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); ++ ++ if (p_FmPcd->exceptions & FM_EX_KG_DOUBLE_ECC) ++ FmEnableRamsEcc(p_FmPcd->h_Fm); ++ ++ fman_kg_init(p_Regs, p_FmPcd->exceptions, GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd)); ++ ++ /* register even if no interrupts enabled, to allow future enablement */ ++ FmRegisterIntr(p_FmPcd->h_Fm, ++ e_FM_MOD_KG, ++ 0, ++ e_FM_INTR_TYPE_ERR, ++ PcdKgErrorException, ++ p_FmPcd); ++ ++ fman_kg_enable_scheme_interrupts(p_Regs); ++ ++ if (p_FmPcd->p_FmPcdKg->numOfSchemes) ++ { ++ err = FmPcdKgAllocSchemes(p_FmPcd, ++ p_FmPcd->p_FmPcdKg->numOfSchemes, ++ p_FmPcd->guestId, ++ p_FmPcd->p_FmPcdKg->schemesIds); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++static void ValidateSchemeSw(t_FmPcdKgScheme *p_Scheme) ++{ ++ ASSERT_COND(!p_Scheme->valid); ++ if (p_Scheme->netEnvId != ILLEGAL_NETENV) ++ FmPcdIncNetEnvOwners(p_Scheme->h_FmPcd, p_Scheme->netEnvId); ++ p_Scheme->valid = TRUE; ++} ++ ++static t_Error InvalidateSchemeSw(t_FmPcdKgScheme *p_Scheme) ++{ ++ if (p_Scheme->owners) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Trying to delete a scheme that has ports bound to")); ++ ++ if (p_Scheme->netEnvId != ILLEGAL_NETENV) ++ FmPcdDecNetEnvOwners(p_Scheme->h_FmPcd, p_Scheme->netEnvId); ++ p_Scheme->valid = FALSE; ++ ++ return E_OK; ++} ++ ++static t_Error BuildSchemeRegs(t_FmPcdKgScheme *p_Scheme, ++ t_FmPcdKgSchemeParams *p_SchemeParams, ++ struct fman_kg_scheme_regs *p_SchemeRegs) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)(p_Scheme->h_FmPcd); ++ uint32_t grpBits = 0; ++ uint8_t grpBase; ++ bool direct=TRUE, absolute=FALSE; ++ uint16_t profileId=0, numOfProfiles=0, relativeProfileId; ++ t_Error err = E_OK; ++ int i = 0; ++ t_NetEnvParams netEnvParams; ++ uint32_t tmpReg, fqbTmp = 0, ppcTmp = 0, selectTmp, maskTmp, knownTmp, genTmp; ++ t_FmPcdKgKeyExtractAndHashParams *p_KeyAndHash = NULL; ++ uint8_t j, curr, idx; ++ uint8_t id, shift=0, code=0, offset=0, size=0; ++ t_FmPcdExtractEntry *p_Extract = NULL; ++ t_FmPcdKgExtractedOrParams *p_ExtractOr; ++ bool generic = FALSE; ++ t_KnownFieldsMasks bitMask; ++ e_FmPcdKgExtractDfltSelect swDefault = (e_FmPcdKgExtractDfltSelect)0; ++ t_FmPcdKgSchemesExtracts *p_LocalExtractsArray; ++ uint8_t numOfSwDefaults = 0; ++ t_FmPcdKgExtractDflt swDefaults[NUM_OF_SW_DEFAULTS]; ++ uint8_t currGenId = 0; ++ ++ memset(swDefaults, 0, NUM_OF_SW_DEFAULTS*sizeof(t_FmPcdKgExtractDflt)); ++ memset(p_SchemeRegs, 0, sizeof(struct fman_kg_scheme_regs)); ++ ++ if (p_SchemeParams->netEnvParams.numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("numOfDistinctionUnits should not exceed %d", FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)); ++ ++ /* by netEnv parameters, get match vector */ ++ if (!p_SchemeParams->alwaysDirect) ++ { ++ p_Scheme->netEnvId = FmPcdGetNetEnvId(p_SchemeParams->netEnvParams.h_NetEnv); ++ netEnvParams.netEnvId = p_Scheme->netEnvId; ++ netEnvParams.numOfDistinctionUnits = p_SchemeParams->netEnvParams.numOfDistinctionUnits; ++ memcpy(netEnvParams.unitIds, p_SchemeParams->netEnvParams.unitIds, (sizeof(uint8_t))*p_SchemeParams->netEnvParams.numOfDistinctionUnits); ++ err = PcdGetUnitsVector(p_FmPcd, &netEnvParams); ++ if (err) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ p_Scheme->matchVector = netEnvParams.vector; ++ } ++ else ++ { ++ p_Scheme->matchVector = SCHEME_ALWAYS_DIRECT; ++ p_Scheme->netEnvId = ILLEGAL_NETENV; ++ } ++ ++ if (p_SchemeParams->nextEngine == e_FM_PCD_INVALID) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next Engine of the scheme is not Valid")); ++ ++ if (p_SchemeParams->bypassFqidGeneration) ++ { ++#ifdef FM_KG_NO_BYPASS_FQID_GEN ++ if ((p_FmPcd->fmRevInfo.majorRev != 4) && (p_FmPcd->fmRevInfo.majorRev < 6)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("bypassFqidGeneration.")); ++#endif /* FM_KG_NO_BYPASS_FQID_GEN */ ++ if (p_SchemeParams->baseFqid) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("baseFqid set for a scheme that does not generate an FQID")); ++ } ++ else ++ if (!p_SchemeParams->baseFqid) ++ DBG(WARNING, ("baseFqid is 0.")); ++ ++ if (p_SchemeParams->nextEngine == e_FM_PCD_PLCR) ++ { ++ direct = p_SchemeParams->kgNextEngineParams.plcrProfile.direct; ++ p_Scheme->directPlcr = direct; ++ absolute = (bool)(p_SchemeParams->kgNextEngineParams.plcrProfile.sharedProfile ? TRUE : FALSE); ++ if (!direct && absolute) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Indirect policing is not available when profile is shared.")); ++ ++ if (direct) ++ { ++ profileId = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.directRelativeProfileId; ++ numOfProfiles = 1; ++ } ++ else ++ { ++ profileId = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase; ++ shift = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.fqidOffsetShift; ++ numOfProfiles = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.numOfProfiles; ++ } ++ } ++ ++ if (p_SchemeParams->nextEngine == e_FM_PCD_CC) ++ { ++#ifdef FM_KG_NO_BYPASS_PLCR_PROFILE_GEN ++ if ((p_SchemeParams->kgNextEngineParams.cc.plcrNext) && (p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration)) ++ { ++ if ((p_FmPcd->fmRevInfo.majorRev != 4) && (p_FmPcd->fmRevInfo.majorRev < 6)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("bypassPlcrProfileGeneration.")); ++ } ++#endif /* FM_KG_NO_BYPASS_PLCR_PROFILE_GEN */ ++ ++ err = FmPcdCcGetGrpParams(p_SchemeParams->kgNextEngineParams.cc.h_CcTree, ++ p_SchemeParams->kgNextEngineParams.cc.grpId, ++ &grpBits, ++ &grpBase); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ p_Scheme->ccUnits = grpBits; ++ ++ if ((p_SchemeParams->kgNextEngineParams.cc.plcrNext) && ++ (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration)) ++ { ++ if (p_SchemeParams->kgNextEngineParams.cc.plcrProfile.sharedProfile) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Shared profile may not be used after Coarse classification.")); ++ absolute = FALSE; ++ direct = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.direct; ++ if (direct) ++ { ++ profileId = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.directRelativeProfileId; ++ numOfProfiles = 1; ++ } ++ else ++ { ++ profileId = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase; ++ shift = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.fqidOffsetShift; ++ numOfProfiles = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.numOfProfiles; ++ } ++ } ++ } ++ ++ /* if policer is used directly after KG, or after CC */ ++ if ((p_SchemeParams->nextEngine == e_FM_PCD_PLCR) || ++ ((p_SchemeParams->nextEngine == e_FM_PCD_CC) && ++ (p_SchemeParams->kgNextEngineParams.cc.plcrNext) && ++ (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration))) ++ { ++ /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */ ++ if (absolute) ++ { ++ /* for absolute direct policy only, */ ++ relativeProfileId = profileId; ++ err = FmPcdPlcrGetAbsoluteIdByProfileParams((t_Handle)p_FmPcd,e_FM_PCD_PLCR_SHARED,NULL, relativeProfileId, &profileId); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Shared profile not valid offset")); ++ if (!FmPcdPlcrIsProfileValid(p_FmPcd, profileId)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Shared profile not valid.")); ++ p_Scheme->relativeProfileId = profileId; ++ } ++ else ++ { ++ /* save relative profile id's for later check */ ++ p_Scheme->nextRelativePlcrProfile = TRUE; ++ p_Scheme->relativeProfileId = profileId; ++ p_Scheme->numOfProfiles = numOfProfiles; ++ } ++ } ++ else ++ { ++ /* if policer is NOT going to be used after KG at all than if bypassFqidGeneration ++ is set, we do not need numOfUsedExtractedOrs and hashDistributionNumOfFqids */ ++ if (p_SchemeParams->bypassFqidGeneration && p_SchemeParams->numOfUsedExtractedOrs) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("numOfUsedExtractedOrs is set in a scheme that does not generate FQID or policer profile ID")); ++ if (p_SchemeParams->bypassFqidGeneration && ++ p_SchemeParams->useHash && ++ p_SchemeParams->keyExtractAndHashParams.hashDistributionNumOfFqids) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("hashDistributionNumOfFqids is set in a scheme that does not generate FQID or policer profile ID")); ++ } ++ ++ /* configure all 21 scheme registers */ ++ tmpReg = KG_SCH_MODE_EN; ++ switch (p_SchemeParams->nextEngine) ++ { ++ case (e_FM_PCD_PLCR): ++ /* add to mode register - NIA */ ++ tmpReg |= KG_SCH_MODE_NIA_PLCR; ++ tmpReg |= NIA_ENG_PLCR; ++ tmpReg |= (uint32_t)(p_SchemeParams->kgNextEngineParams.plcrProfile.sharedProfile ? NIA_PLCR_ABSOLUTE:0); ++ /* initialize policer profile command - */ ++ /* configure kgse_ppc */ ++ if (direct) ++ /* use profileId as base, other fields are 0 */ ++ p_SchemeRegs->kgse_ppc = (uint32_t)profileId; ++ else ++ { ++ if (shift > MAX_PP_SHIFT) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_PP_SHIFT)); ++ ++ if (!numOfProfiles || !POWER_OF_2(numOfProfiles)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2")); ++ ++ ppcTmp = ((uint32_t)shift << KG_SCH_PP_SHIFT_HIGH_SHIFT) & KG_SCH_PP_SHIFT_HIGH; ++ ppcTmp |= ((uint32_t)shift << KG_SCH_PP_SHIFT_LOW_SHIFT) & KG_SCH_PP_SHIFT_LOW; ++ ppcTmp |= ((uint32_t)(numOfProfiles-1) << KG_SCH_PP_MASK_SHIFT); ++ ppcTmp |= (uint32_t)profileId; ++ ++ p_SchemeRegs->kgse_ppc = ppcTmp; ++ } ++ break; ++ case (e_FM_PCD_CC): ++ /* mode reg - define NIA */ ++ tmpReg |= (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC); ++ ++ p_SchemeRegs->kgse_ccbs = grpBits; ++ tmpReg |= (uint32_t)(grpBase << KG_SCH_MODE_CCOBASE_SHIFT); ++ ++ if (p_SchemeParams->kgNextEngineParams.cc.plcrNext) ++ { ++ if (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration) ++ { ++ /* find out if absolute or relative */ ++ if (absolute) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("It is illegal to request a shared profile in a scheme that is in a KG->CC->PLCR flow")); ++ if (direct) ++ { ++ /* mask = 0, base = directProfileId */ ++ p_SchemeRegs->kgse_ppc = (uint32_t)profileId; ++ } ++ else ++ { ++ if (shift > MAX_PP_SHIFT) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_PP_SHIFT)); ++ if (!numOfProfiles || !POWER_OF_2(numOfProfiles)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2")); ++ ++ ppcTmp = ((uint32_t)shift << KG_SCH_PP_SHIFT_HIGH_SHIFT) & KG_SCH_PP_SHIFT_HIGH; ++ ppcTmp |= ((uint32_t)shift << KG_SCH_PP_SHIFT_LOW_SHIFT) & KG_SCH_PP_SHIFT_LOW; ++ ppcTmp |= ((uint32_t)(numOfProfiles-1) << KG_SCH_PP_MASK_SHIFT); ++ ppcTmp |= (uint32_t)profileId; ++ ++ p_SchemeRegs->kgse_ppc = ppcTmp; ++ } ++ } ++ else ++ ppcTmp = KG_SCH_PP_NO_GEN; ++ } ++ break; ++ case (e_FM_PCD_DONE): ++ if (p_SchemeParams->kgNextEngineParams.doneAction == e_FM_PCD_DROP_FRAME) ++ tmpReg |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd); ++ else ++ tmpReg |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Next engine not supported")); ++ } ++ p_SchemeRegs->kgse_mode = tmpReg; ++ ++ p_SchemeRegs->kgse_mv = p_Scheme->matchVector; ++ ++#if (DPAA_VERSION >= 11) ++ if (p_SchemeParams->overrideStorageProfile) ++ { ++ p_SchemeRegs->kgse_om |= KG_SCH_OM_VSPE; ++ ++ tmpReg = 0; ++ if (p_SchemeParams->storageProfile.direct) ++ { ++ profileId = p_SchemeParams->storageProfile.profileSelect.directRelativeProfileId; ++ shift = 0; ++ numOfProfiles = 1; ++ } ++ else ++ { ++ profileId = p_SchemeParams->storageProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase; ++ shift = p_SchemeParams->storageProfile.profileSelect.indirectProfile.fqidOffsetShift; ++ numOfProfiles = p_SchemeParams->storageProfile.profileSelect.indirectProfile.numOfProfiles; ++ } ++ if (shift > MAX_SP_SHIFT) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_SP_SHIFT)); ++ ++ if (!numOfProfiles || !POWER_OF_2(numOfProfiles)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2")); ++ ++ tmpReg = (uint32_t)shift << KG_SCH_VSP_SHIFT; ++ tmpReg |= ((uint32_t)(numOfProfiles-1) << KG_SCH_VSP_MASK_SHIFT); ++ tmpReg |= (uint32_t)profileId; ++ ++ ++ p_SchemeRegs->kgse_vsp = tmpReg; ++ ++ p_Scheme->vspe = TRUE; ++ ++ } ++ else ++ p_SchemeRegs->kgse_vsp = KG_SCH_VSP_NO_KSP_EN; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (p_SchemeParams->useHash) ++ { ++ p_KeyAndHash = &p_SchemeParams->keyExtractAndHashParams; ++ ++ if (p_KeyAndHash->numOfUsedExtracts >= FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfUsedExtracts out of range")); ++ ++ /* configure kgse_dv0 */ ++ p_SchemeRegs->kgse_dv0 = p_KeyAndHash->privateDflt0; ++ ++ /* configure kgse_dv1 */ ++ p_SchemeRegs->kgse_dv1 = p_KeyAndHash->privateDflt1; ++ ++ if (!p_SchemeParams->bypassFqidGeneration) ++ { ++ if (!p_KeyAndHash->hashDistributionNumOfFqids || !POWER_OF_2(p_KeyAndHash->hashDistributionNumOfFqids)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashDistributionNumOfFqids must not be 0 and must be a power of 2")); ++ if ((p_KeyAndHash->hashDistributionNumOfFqids-1) & p_SchemeParams->baseFqid) ++ DBG(WARNING, ("baseFqid unaligned. Distribution may result in less than hashDistributionNumOfFqids queues.")); ++ } ++ ++ /* configure kgse_ekdv */ ++ tmpReg = 0; ++ for ( i=0 ;inumOfUsedDflts ; i++) ++ { ++ switch (p_KeyAndHash->dflts[i].type) ++ { ++ case (e_FM_PCD_KG_MAC_ADDR): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_MAC_ADDR_SHIFT); ++ break; ++ case (e_FM_PCD_KG_TCI): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_TCI_SHIFT); ++ break; ++ case (e_FM_PCD_KG_ENET_TYPE): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_ENET_TYPE_SHIFT); ++ break; ++ case (e_FM_PCD_KG_PPP_SESSION_ID): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PPP_SESSION_ID_SHIFT); ++ break; ++ case (e_FM_PCD_KG_PPP_PROTOCOL_ID): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PPP_PROTOCOL_ID_SHIFT); ++ break; ++ case (e_FM_PCD_KG_MPLS_LABEL): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_MPLS_LABEL_SHIFT); ++ break; ++ case (e_FM_PCD_KG_IP_ADDR): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IP_ADDR_SHIFT); ++ break; ++ case (e_FM_PCD_KG_PROTOCOL_TYPE): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PROTOCOL_TYPE_SHIFT); ++ break; ++ case (e_FM_PCD_KG_IP_TOS_TC): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IP_TOS_TC_SHIFT); ++ break; ++ case (e_FM_PCD_KG_IPV6_FLOW_LABEL): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_L4_PORT_SHIFT); ++ break; ++ case (e_FM_PCD_KG_IPSEC_SPI): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IPSEC_SPI_SHIFT); ++ break; ++ case (e_FM_PCD_KG_L4_PORT): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_L4_PORT_SHIFT); ++ break; ++ case (e_FM_PCD_KG_TCP_FLAG): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_TCP_FLAG_SHIFT); ++ break; ++ case (e_FM_PCD_KG_GENERIC_FROM_DATA): ++ swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_FROM_DATA; ++ swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect; ++ numOfSwDefaults ++; ++ break; ++ case (e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V): ++ swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V; ++ swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect; ++ numOfSwDefaults ++; ++ break; ++ case (e_FM_PCD_KG_GENERIC_NOT_FROM_DATA): ++ swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_NOT_FROM_DATA; ++ swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect; ++ numOfSwDefaults ++; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ } ++ p_SchemeRegs->kgse_ekdv = tmpReg; ++ ++ p_LocalExtractsArray = (t_FmPcdKgSchemesExtracts *)XX_Malloc(sizeof(t_FmPcdKgSchemesExtracts)); ++ if (!p_LocalExtractsArray) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); ++ ++ /* configure kgse_ekfc and kgse_gec */ ++ knownTmp = 0; ++ for ( i=0 ;inumOfUsedExtracts ; i++) ++ { ++ p_Extract = &p_KeyAndHash->extractArray[i]; ++ switch (p_Extract->type) ++ { ++ case (e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO): ++ knownTmp |= KG_SCH_KN_PORT_ID; ++ /* save in driver structure */ ++ p_LocalExtractsArray->extractsArray[i].id = GetKnownFieldId(KG_SCH_KN_PORT_ID); ++ p_LocalExtractsArray->extractsArray[i].known = TRUE; ++ break; ++ case (e_FM_PCD_EXTRACT_BY_HDR): ++ switch (p_Extract->extractByHdr.hdr) ++ { ++ ++#ifdef FM_CAPWAP_SUPPORT ++ case (HEADER_TYPE_UDP_LITE): ++ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP; ++ break; ++#endif ++ case (HEADER_TYPE_UDP_ENCAP_ESP): ++ switch (p_Extract->extractByHdr.type) ++ { ++ case (e_FM_PCD_EXTRACT_FROM_HDR): ++ /* case where extraction from ESP only */ ++ if (p_Extract->extractByHdr.extractByHdrType.fromHdr.offset >= UDP_HEADER_SIZE) ++ { ++ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP); ++ p_Extract->extractByHdr.extractByHdrType.fromHdr.offset -= UDP_HEADER_SIZE; ++ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE; ++ } ++ else ++ { ++ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP; ++ p_Extract->extractByHdr.ignoreProtocolValidation = FALSE; ++ } ++ break; ++ case (e_FM_PCD_EXTRACT_FROM_FIELD): ++ switch (p_Extract->extractByHdr.extractByHdrType.fromField.field.udpEncapEsp) ++ { ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC): ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST): ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN): ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM): ++ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP; ++ break; ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI): ++ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR; ++ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP); ++ p_Extract->extractByHdr.extractByHdrType.fromField.size = p_Extract->extractByHdr.extractByHdrType.fromField.size; ++ /*p_Extract->extractByHdr.extractByHdrType.fromField.offset += ESP_SPI_OFFSET;*/ ++ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE; ++ break; ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM): ++ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR; ++ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP); ++ p_Extract->extractByHdr.extractByHdrType.fromField.size = p_Extract->extractByHdr.extractByHdrType.fromField.size; ++ p_Extract->extractByHdr.extractByHdrType.fromField.offset += ESP_SEQ_NUM_OFFSET; ++ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE; ++ break; ++ } ++ break; ++ case (e_FM_PCD_EXTRACT_FULL_FIELD): ++ switch (p_Extract->extractByHdr.extractByHdrType.fullField.udpEncapEsp) ++ { ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC): ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST): ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN): ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM): ++ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP; ++ break; ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI): ++ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR; ++ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP); ++ p_Extract->extractByHdr.extractByHdrType.fromHdr.size = ESP_SPI_SIZE; ++ p_Extract->extractByHdr.extractByHdrType.fromHdr.offset = ESP_SPI_OFFSET; ++ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE; ++ break; ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM): ++ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR; ++ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP); ++ p_Extract->extractByHdr.extractByHdrType.fromHdr.size = ESP_SEQ_NUM_SIZE; ++ p_Extract->extractByHdr.extractByHdrType.fromHdr.offset = ESP_SEQ_NUM_OFFSET; ++ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE; ++ break; ++ } ++ break; ++ } ++ break; ++ default: ++ break; ++ } ++ switch (p_Extract->extractByHdr.type) ++ { ++ case (e_FM_PCD_EXTRACT_FROM_HDR): ++ generic = TRUE; ++ /* get the header code for the generic extract */ ++ code = GetGenHdrCode(p_Extract->extractByHdr.hdr, p_Extract->extractByHdr.hdrIndex, p_Extract->extractByHdr.ignoreProtocolValidation); ++ /* set generic register fields */ ++ offset = p_Extract->extractByHdr.extractByHdrType.fromHdr.offset; ++ size = p_Extract->extractByHdr.extractByHdrType.fromHdr.size; ++ break; ++ case (e_FM_PCD_EXTRACT_FROM_FIELD): ++ generic = TRUE; ++ /* get the field code for the generic extract */ ++ code = GetGenFieldCode(p_Extract->extractByHdr.hdr, ++ p_Extract->extractByHdr.extractByHdrType.fromField.field, p_Extract->extractByHdr.ignoreProtocolValidation,p_Extract->extractByHdr.hdrIndex); ++ offset = p_Extract->extractByHdr.extractByHdrType.fromField.offset; ++ size = p_Extract->extractByHdr.extractByHdrType.fromField.size; ++ break; ++ case (e_FM_PCD_EXTRACT_FULL_FIELD): ++ if (!p_Extract->extractByHdr.ignoreProtocolValidation) ++ { ++ /* if we have a known field for it - use it, otherwise use generic */ ++ bitMask = GetKnownProtMask(p_FmPcd, p_Extract->extractByHdr.hdr, p_Extract->extractByHdr.hdrIndex, ++ p_Extract->extractByHdr.extractByHdrType.fullField); ++ if (bitMask) ++ { ++ knownTmp |= bitMask; ++ /* save in driver structure */ ++ p_LocalExtractsArray->extractsArray[i].id = GetKnownFieldId(bitMask); ++ p_LocalExtractsArray->extractsArray[i].known = TRUE; ++ } ++ else ++ generic = TRUE; ++ ++ } ++ else ++ generic = TRUE; ++ if (generic) ++ { ++ /* tmp - till we cover more headers under generic */ ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Full header selection not supported")); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ break; ++ case (e_FM_PCD_EXTRACT_NON_HDR): ++ /* use generic */ ++ generic = TRUE; ++ offset = 0; ++ /* get the field code for the generic extract */ ++ code = GetGenCode(p_Extract->extractNonHdr.src, &offset); ++ offset += p_Extract->extractNonHdr.offset; ++ size = p_Extract->extractNonHdr.size; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ if (generic) ++ { ++ /* set generic register fields */ ++ if (currGenId >= FM_KG_NUM_OF_GENERIC_REGS) ++ RETURN_ERROR(MAJOR, E_FULL, ("Generic registers are fully used")); ++ if (!code) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG); ++ ++ genTmp = KG_SCH_GEN_VALID; ++ genTmp |= (uint32_t)(code << KG_SCH_GEN_HT_SHIFT); ++ genTmp |= offset; ++ if ((size > MAX_KG_SCH_SIZE) || (size < 1)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal extraction (size out of range)")); ++ genTmp |= (uint32_t)((size - 1) << KG_SCH_GEN_SIZE_SHIFT); ++ swDefault = GetGenericSwDefault(swDefaults, numOfSwDefaults, code); ++ if (swDefault == e_FM_PCD_KG_DFLT_ILLEGAL) ++ DBG(WARNING, ("No sw default configured")); ++ ++ genTmp |= swDefault << KG_SCH_GEN_DEF_SHIFT; ++ genTmp |= KG_SCH_GEN_MASK; ++ p_SchemeRegs->kgse_gec[currGenId] = genTmp; ++ /* save in driver structure */ ++ p_LocalExtractsArray->extractsArray[i].id = currGenId++; ++ p_LocalExtractsArray->extractsArray[i].known = FALSE; ++ generic = FALSE; ++ } ++ } ++ p_SchemeRegs->kgse_ekfc = knownTmp; ++ ++ selectTmp = 0; ++ maskTmp = 0xFFFFFFFF; ++ /* configure kgse_bmch, kgse_bmcl and kgse_fqb */ ++ ++ if (p_KeyAndHash->numOfUsedMasks >= FM_PCD_KG_NUM_OF_EXTRACT_MASKS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Only %d masks supported", FM_PCD_KG_NUM_OF_EXTRACT_MASKS)); ++ for ( i=0 ;inumOfUsedMasks ; i++) ++ { ++ /* Get the relative id of the extract (for known 0-0x1f, for generic 0-7) */ ++ id = p_LocalExtractsArray->extractsArray[p_KeyAndHash->masks[i].extractArrayIndex].id; ++ /* Get the shift of the select field (depending on i) */ ++ GET_MASK_SEL_SHIFT(shift,i); ++ if (p_LocalExtractsArray->extractsArray[p_KeyAndHash->masks[i].extractArrayIndex].known) ++ selectTmp |= id << shift; ++ else ++ selectTmp |= (id + MASK_FOR_GENERIC_BASE_ID) << shift; ++ ++ /* Get the shift of the offset field (depending on i) - may ++ be in kgse_bmch or in kgse_fqb (depending on i) */ ++ GET_MASK_OFFSET_SHIFT(shift,i); ++ if (i<=1) ++ selectTmp |= p_KeyAndHash->masks[i].offset << shift; ++ else ++ fqbTmp |= p_KeyAndHash->masks[i].offset << shift; ++ ++ /* Get the shift of the mask field (depending on i) */ ++ GET_MASK_SHIFT(shift,i); ++ /* pass all bits */ ++ maskTmp |= KG_SCH_BITMASK_MASK << shift; ++ /* clear bits that need masking */ ++ maskTmp &= ~(0xFF << shift) ; ++ /* set mask bits */ ++ maskTmp |= (p_KeyAndHash->masks[i].mask << shift) ; ++ } ++ p_SchemeRegs->kgse_bmch = selectTmp; ++ p_SchemeRegs->kgse_bmcl = maskTmp; ++ /* kgse_fqb will be written t the end of the routine */ ++ ++ /* configure kgse_hc */ ++ if (p_KeyAndHash->hashShift > MAX_HASH_SHIFT) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashShift must not be larger than %d", MAX_HASH_SHIFT)); ++ if (p_KeyAndHash->hashDistributionFqidsShift > MAX_DIST_FQID_SHIFT) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashDistributionFqidsShift must not be larger than %d", MAX_DIST_FQID_SHIFT)); ++ ++ tmpReg = 0; ++ ++ tmpReg |= ((p_KeyAndHash->hashDistributionNumOfFqids - 1) << p_KeyAndHash->hashDistributionFqidsShift); ++ tmpReg |= p_KeyAndHash->hashShift << KG_SCH_HASH_CONFIG_SHIFT_SHIFT; ++ ++ if (p_KeyAndHash->symmetricHash) ++ { ++ if ((!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_MACSRC) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_MACDST)) || ++ (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPSRC1) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPDST1)) || ++ (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPSRC2) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPDST2)) || ++ (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_L4PSRC) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_L4PDST))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("symmetricHash set but src/dest extractions missing")); ++ tmpReg |= KG_SCH_HASH_CONFIG_SYM; ++ } ++ p_SchemeRegs->kgse_hc = tmpReg; ++ ++ /* build the return array describing the order of the extractions */ ++ ++ /* the last currGenId places of the array ++ are for generic extracts that are always last. ++ We now sort for the calculation of the order of the known ++ extractions we sort the known extracts between orderedArray[0] and ++ orderedArray[p_KeyAndHash->numOfUsedExtracts - currGenId - 1]. ++ for the calculation of the order of the generic extractions we use: ++ num_of_generic - currGenId ++ num_of_known - p_KeyAndHash->numOfUsedExtracts - currGenId ++ first_generic_index = num_of_known */ ++ curr = 0; ++ for (i=0;inumOfUsedExtracts ; i++) ++ { ++ if (p_LocalExtractsArray->extractsArray[i].known) ++ { ++ ASSERT_COND(curr<(p_KeyAndHash->numOfUsedExtracts - currGenId)); ++ j = curr; ++ /* id is the extract id (port id = 0, mac src = 1 etc.). the value in the array is the original ++ index in the user's extractions array */ ++ /* we compare the id of the current extract with the id of the extract in the orderedArray[j-1] ++ location */ ++ while ((j > 0) && (p_LocalExtractsArray->extractsArray[i].id < ++ p_LocalExtractsArray->extractsArray[p_Scheme->orderedArray[j-1]].id)) ++ { ++ p_Scheme->orderedArray[j] = ++ p_Scheme->orderedArray[j-1]; ++ j--; ++ } ++ p_Scheme->orderedArray[j] = (uint8_t)i; ++ curr++; ++ } ++ else ++ { ++ /* index is first_generic_index + generic index (id) */ ++ idx = (uint8_t)(p_KeyAndHash->numOfUsedExtracts - currGenId + p_LocalExtractsArray->extractsArray[i].id); ++ ASSERT_COND(idx < FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY); ++ p_Scheme->orderedArray[idx]= (uint8_t)i; ++ } ++ } ++ XX_Free(p_LocalExtractsArray); ++ p_LocalExtractsArray = NULL; ++ ++ } ++ else ++ { ++ /* clear all unused registers: */ ++ p_SchemeRegs->kgse_ekfc = 0; ++ p_SchemeRegs->kgse_ekdv = 0; ++ p_SchemeRegs->kgse_bmch = 0; ++ p_SchemeRegs->kgse_bmcl = 0; ++ p_SchemeRegs->kgse_hc = 0; ++ p_SchemeRegs->kgse_dv0 = 0; ++ p_SchemeRegs->kgse_dv1 = 0; ++ } ++ ++ if (p_SchemeParams->bypassFqidGeneration) ++ p_SchemeRegs->kgse_hc |= KG_SCH_HASH_CONFIG_NO_FQID; ++ ++ /* configure kgse_spc */ ++ if ( p_SchemeParams->schemeCounter.update) ++ p_SchemeRegs->kgse_spc = p_SchemeParams->schemeCounter.value; ++ ++ ++ /* check that are enough generic registers */ ++ if (p_SchemeParams->numOfUsedExtractedOrs + currGenId > FM_KG_NUM_OF_GENERIC_REGS) ++ RETURN_ERROR(MAJOR, E_FULL, ("Generic registers are fully used")); ++ ++ /* extracted OR mask on Qid */ ++ for ( i=0 ;inumOfUsedExtractedOrs ; i++) ++ { ++ ++ p_Scheme->extractedOrs = TRUE; ++ /* configure kgse_gec[i] */ ++ p_ExtractOr = &p_SchemeParams->extractedOrs[i]; ++ switch (p_ExtractOr->type) ++ { ++ case (e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO): ++ code = KG_SCH_GEN_PARSE_RESULT_N_FQID; ++ offset = 0; ++ break; ++ case (e_FM_PCD_EXTRACT_BY_HDR): ++ /* get the header code for the generic extract */ ++ code = GetGenHdrCode(p_ExtractOr->extractByHdr.hdr, p_ExtractOr->extractByHdr.hdrIndex, p_ExtractOr->extractByHdr.ignoreProtocolValidation); ++ /* set generic register fields */ ++ offset = p_ExtractOr->extractionOffset; ++ break; ++ case (e_FM_PCD_EXTRACT_NON_HDR): ++ /* get the field code for the generic extract */ ++ offset = 0; ++ code = GetGenCode(p_ExtractOr->src, &offset); ++ offset += p_ExtractOr->extractionOffset; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ /* set generic register fields */ ++ if (!code) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG); ++ genTmp = KG_SCH_GEN_EXTRACT_TYPE | KG_SCH_GEN_VALID; ++ genTmp |= (uint32_t)(code << KG_SCH_GEN_HT_SHIFT); ++ genTmp |= offset; ++ if (!!p_ExtractOr->bitOffsetInFqid == !!p_ExtractOr->bitOffsetInPlcrProfile) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" extracted byte must effect either FQID or Policer profile")); ++ ++ /************************************************************************************ ++ bitOffsetInFqid and bitOffsetInPolicerProfile are translated to rotate parameter ++ in the following way: ++ ++ Driver API and implementation: ++ ============================== ++ FQID: extracted OR byte may be shifted right 1-31 bits to effect parts of the FQID. ++ if shifted less than 8 bits, or more than 24 bits a mask is set on the bits that ++ are not overlapping FQID. ++ ------------------------ ++ | FQID (24) | ++ ------------------------ ++ -------- ++ | | extracted OR byte ++ -------- ++ ++ Policer Profile: extracted OR byte may be shifted right 1-15 bits to effect parts of the ++ PP id. Unless shifted exactly 8 bits to overlap the PP id, a mask is set on the bits that ++ are not overlapping PP id. ++ ++ -------- ++ | PP (8) | ++ -------- ++ -------- ++ | | extracted OR byte ++ -------- ++ ++ HW implementation ++ ================= ++ FQID and PP construct a 32 bit word in the way describe below. Extracted byte is located ++ as the highest byte of that word and may be rotated to effect any part os the FQID or ++ the PP. ++ ------------------------ -------- ++ | FQID (24) || PP (8) | ++ ------------------------ -------- ++ -------- ++ | | extracted OR byte ++ -------- ++ ++ ************************************************************************************/ ++ ++ if (p_ExtractOr->bitOffsetInFqid) ++ { ++ if (p_ExtractOr->bitOffsetInFqid > MAX_KG_SCH_FQID_BIT_OFFSET ) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal extraction (bitOffsetInFqid out of range)")); ++ if (p_ExtractOr->bitOffsetInFqid<8) ++ genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInFqid+24) << KG_SCH_GEN_SIZE_SHIFT); ++ else ++ genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInFqid-8) << KG_SCH_GEN_SIZE_SHIFT); ++ p_ExtractOr->mask &= GetExtractedOrMask(p_ExtractOr->bitOffsetInFqid, TRUE); ++ } ++ else /* effect policer profile */ ++ { ++ if (p_ExtractOr->bitOffsetInPlcrProfile > MAX_KG_SCH_PP_BIT_OFFSET ) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal extraction (bitOffsetInPlcrProfile out of range)")); ++ p_Scheme->bitOffsetInPlcrProfile = p_ExtractOr->bitOffsetInPlcrProfile; ++ genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInPlcrProfile+16) << KG_SCH_GEN_SIZE_SHIFT); ++ p_ExtractOr->mask &= GetExtractedOrMask(p_ExtractOr->bitOffsetInPlcrProfile, FALSE); ++ } ++ ++ genTmp |= (uint32_t)(p_ExtractOr->extractionOffset << KG_SCH_GEN_DEF_SHIFT); ++ /* clear bits that need masking */ ++ genTmp &= ~KG_SCH_GEN_MASK ; ++ /* set mask bits */ ++ genTmp |= (uint32_t)(p_ExtractOr->mask << KG_SCH_GEN_MASK_SHIFT); ++ p_SchemeRegs->kgse_gec[currGenId++] = genTmp; ++ ++ } ++ /* clear all unused GEC registers */ ++ for ( i=currGenId ;ikgse_gec[i] = 0; ++ ++ /* add base Qid for this scheme */ ++ /* add configuration for kgse_fqb */ ++ if (p_SchemeParams->baseFqid & ~0x00FFFFFF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("baseFqid must be between 1 and 2^24-1")); ++ ++ fqbTmp |= p_SchemeParams->baseFqid; ++ p_SchemeRegs->kgse_fqb = fqbTmp; ++ ++ p_Scheme->nextEngine = p_SchemeParams->nextEngine; ++ p_Scheme->doneAction = p_SchemeParams->kgNextEngineParams.doneAction; ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++t_Error FmPcdKgBuildClsPlanGrp(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_Grp, t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdKgClsPlanGrp *p_ClsPlanGrp; ++ t_FmPcdIpcKgClsPlanParams kgAlloc; ++ t_Error err = E_OK; ++ uint32_t oredVectors = 0; ++ int i, j; ++ ++ /* this routine is protected by the calling routine ! */ ++ if (p_Grp->numOfOptions >= FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Too many classification plan basic options selected.")); ++ ++ /* find a new clsPlan group */ ++ for (i = 0; i < FM_MAX_NUM_OF_PORTS; i++) ++ if (!p_FmPcd->p_FmPcdKg->clsPlanGrps[i].used) ++ break; ++ if (i == FM_MAX_NUM_OF_PORTS) ++ RETURN_ERROR(MAJOR, E_FULL,("No classification plan groups available.")); ++ ++ p_FmPcd->p_FmPcdKg->clsPlanGrps[i].used = TRUE; ++ ++ p_Grp->clsPlanGrpId = (uint8_t)i; ++ ++ if (p_Grp->numOfOptions == 0) ++ p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId = (uint8_t)i; ++ ++ p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[i]; ++ p_ClsPlanGrp->netEnvId = p_Grp->netEnvId; ++ p_ClsPlanGrp->owners = 0; ++ FmPcdSetClsPlanGrpId(p_FmPcd, p_Grp->netEnvId, p_Grp->clsPlanGrpId); ++ if (p_Grp->numOfOptions != 0) ++ FmPcdIncNetEnvOwners(p_FmPcd, p_Grp->netEnvId); ++ ++ p_ClsPlanGrp->sizeOfGrp = (uint16_t)(1 << p_Grp->numOfOptions); ++ /* a minimal group of 8 is required */ ++ if (p_ClsPlanGrp->sizeOfGrp < CLS_PLAN_NUM_PER_GRP) ++ p_ClsPlanGrp->sizeOfGrp = CLS_PLAN_NUM_PER_GRP; ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ { ++ err = KgAllocClsPlanEntries(h_FmPcd, p_ClsPlanGrp->sizeOfGrp, p_FmPcd->guestId, &p_ClsPlanGrp->baseEntry); ++ ++ if (err) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG); ++ } ++ else ++ { ++ t_FmPcdIpcMsg msg; ++ uint32_t replyLength; ++ t_FmPcdIpcReply reply; ++ ++ /* in GUEST_PARTITION, we use the IPC, to also set a private driver group if required */ ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ memset(&kgAlloc, 0, sizeof(kgAlloc)); ++ kgAlloc.guestId = p_FmPcd->guestId; ++ kgAlloc.numOfClsPlanEntries = p_ClsPlanGrp->sizeOfGrp; ++ msg.msgId = FM_PCD_ALLOC_KG_CLSPLAN; ++ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc)); ++ replyLength = (sizeof(uint32_t) + sizeof(p_ClsPlanGrp->baseEntry)); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(kgAlloc), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (replyLength != (sizeof(uint32_t) + sizeof(p_ClsPlanGrp->baseEntry))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ if ((t_Error)reply.error != E_OK) ++ RETURN_ERROR(MINOR, (t_Error)reply.error, NO_MSG); ++ ++ p_ClsPlanGrp->baseEntry = *(uint8_t*)(reply.replyBody); ++ } ++ ++ /* build classification plan entries parameters */ ++ p_ClsPlanSet->baseEntry = p_ClsPlanGrp->baseEntry; ++ p_ClsPlanSet->numOfClsPlanEntries = p_ClsPlanGrp->sizeOfGrp; ++ ++ oredVectors = 0; ++ for (i = 0; inumOfOptions; i++) ++ { ++ oredVectors |= p_Grp->optVectors[i]; ++ /* save an array of used options - the indexes represent the power of 2 index */ ++ p_ClsPlanGrp->optArray[i] = p_Grp->options[i]; ++ } ++ /* set the classification plan relevant entries so that all bits ++ * relevant to the list of options is cleared ++ */ ++ for (j = 0; jsizeOfGrp; j++) ++ p_ClsPlanSet->vectors[j] = ~oredVectors; ++ ++ for (i = 0; inumOfOptions; i++) ++ { ++ /* option i got the place 2^i in the clsPlan array. all entries that ++ * have bit i set, should have the vector bit cleared. So each option ++ * has one location that it is exclusive (1,2,4,8...) and represent the ++ * presence of that option only, and other locations that represent a ++ * combination of options. ++ * e.g: ++ * If ethernet-BC is option 1 it gets entry 2 in the table. Entry 2 ++ * now represents a frame with ethernet-BC header - so the bit ++ * representing ethernet-BC should be set and all other option bits ++ * should be cleared. ++ * Entries 2,3,6,7,10... also have ethernet-BC and therefore have bit ++ * vector[1] set, but they also have other bits set: ++ * 3=1+2, options 0 and 1 ++ * 6=2+4, options 1 and 2 ++ * 7=1+2+4, options 0,1,and 2 ++ * 10=2+8, options 1 and 3 ++ * etc. ++ * */ ++ ++ /* now for each option (i), we set their bits in all entries (j) ++ * that contain bit 2^i. ++ */ ++ for (j = 0; jsizeOfGrp; j++) ++ { ++ if (j & (1<vectors[j] |= p_Grp->optVectors[i]; ++ } ++ } ++ ++ return E_OK; ++} ++ ++void FmPcdKgDestroyClsPlanGrp(t_Handle h_FmPcd, uint8_t grpId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdIpcKgClsPlanParams kgAlloc; ++ t_Error err; ++ t_FmPcdIpcMsg msg; ++ uint32_t replyLength; ++ t_FmPcdIpcReply reply; ++ ++ /* check that no port is bound to this clsPlan */ ++ if (p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].owners) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Trying to delete a clsPlan grp that has ports bound to")); ++ return; ++ } ++ ++ FmPcdSetClsPlanGrpId(p_FmPcd, p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].netEnvId, ILLEGAL_CLS_PLAN); ++ ++ if (grpId == p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId) ++ p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId = ILLEGAL_CLS_PLAN; ++ else ++ FmPcdDecNetEnvOwners(p_FmPcd, p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].netEnvId); ++ ++ /* free blocks */ ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ KgFreeClsPlanEntries(h_FmPcd, ++ p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].sizeOfGrp, ++ p_FmPcd->guestId, ++ p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].baseEntry); ++ else /* in GUEST_PARTITION, we use the IPC, to also set a private driver group if required */ ++ { ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ kgAlloc.guestId = p_FmPcd->guestId; ++ kgAlloc.numOfClsPlanEntries = p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].sizeOfGrp; ++ kgAlloc.clsPlanBase = p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].baseEntry; ++ msg.msgId = FM_PCD_FREE_KG_CLSPLAN; ++ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc)); ++ replyLength = sizeof(uint32_t); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(kgAlloc), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return; ++ } ++ if (replyLength != sizeof(uint32_t)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return; ++ } ++ if ((t_Error)reply.error != E_OK) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Free KG clsPlan failed")); ++ return; ++ } ++ } ++ ++ /* clear clsPlan driver structure */ ++ memset(&p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId], 0, sizeof(t_FmPcdKgClsPlanGrp)); ++} ++ ++t_Error FmPcdKgBuildBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort, uint32_t *p_SpReg, bool add) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t j, schemesPerPortVector = 0; ++ t_FmPcdKgScheme *p_Scheme; ++ uint8_t i, relativeSchemeId; ++ uint32_t tmp, walking1Mask; ++ uint8_t swPortIndex = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ ++ /* for each scheme */ ++ for (i = 0; inumOfSchemes; i++) ++ { ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]); ++ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ ++ if (add) ++ { ++ p_Scheme = &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId]; ++ if (!FmPcdKgIsSchemeValidSw(p_Scheme)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Requested scheme is invalid.")); ++ /* check netEnvId of the port against the scheme netEnvId */ ++ if ((p_Scheme->netEnvId != p_BindPort->netEnvId) && (p_Scheme->netEnvId != ILLEGAL_NETENV)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port may not be bound to requested scheme - differ in netEnvId")); ++ ++ /* if next engine is private port policer profile, we need to check that it is valid */ ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, p_BindPort->hardwarePortId); ++ if (p_Scheme->nextRelativePlcrProfile) ++ { ++ for (j = 0;jnumOfProfiles;j++) ++ { ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].h_FmPort); ++ if (p_Scheme->relativeProfileId+j >= p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Relative profile not in range")); ++ if (!FmPcdPlcrIsProfileValid(p_FmPcd, (uint16_t)(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase + p_Scheme->relativeProfileId + j))) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Relative profile not valid.")); ++ } ++ } ++ if (!p_BindPort->useClsPlan) ++ { ++ /* This check may be redundant as port is a assigned to the whole NetEnv */ ++ ++ /* if this port does not use clsPlan, it may not be bound to schemes with units that contain ++ cls plan options. Schemes that are used only directly, should not be checked. ++ it also may not be bound to schemes that go to CC with units that are options - so we OR ++ the match vector and the grpBits (= ccUnits) */ ++ if ((p_Scheme->matchVector != SCHEME_ALWAYS_DIRECT) || p_Scheme->ccUnits) ++ { ++ walking1Mask = 0x80000000; ++ tmp = (p_Scheme->matchVector == SCHEME_ALWAYS_DIRECT)? 0:p_Scheme->matchVector; ++ tmp |= p_Scheme->ccUnits; ++ while (tmp) ++ { ++ if (tmp & walking1Mask) ++ { ++ tmp &= ~walking1Mask; ++ if (!PcdNetEnvIsUnitWithoutOpts(p_FmPcd, p_Scheme->netEnvId, walking1Mask)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port (without clsPlan) may not be bound to requested scheme - uses clsPlan options")); ++ } ++ walking1Mask >>= 1; ++ } ++ } ++ } ++ } ++ /* build vector */ ++ schemesPerPortVector |= 1 << (31 - p_BindPort->schemesIds[i]); ++ } ++ ++ *p_SpReg = schemesPerPortVector; ++ ++ return E_OK; ++} ++ ++t_Error FmPcdKgBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t spReg; ++ t_Error err = E_OK; ++ ++ err = FmPcdKgBuildBindPortToSchemes(h_FmPcd, p_SchemeBind, &spReg, TRUE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ err = KgWriteSp(p_FmPcd, p_SchemeBind->hardwarePortId, spReg, TRUE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ IncSchemeOwners(p_FmPcd, p_SchemeBind); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdKgUnbindPortToSchemes(t_Handle h_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t spReg; ++ t_Error err = E_OK; ++ ++ err = FmPcdKgBuildBindPortToSchemes(p_FmPcd, p_SchemeBind, &spReg, FALSE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ err = KgWriteSp(p_FmPcd, p_SchemeBind->hardwarePortId, spReg, FALSE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ DecSchemeOwners(p_FmPcd, p_SchemeBind); ++ ++ return E_OK; ++} ++ ++bool FmPcdKgIsSchemeValidSw(t_Handle h_Scheme) ++{ ++ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme*)h_Scheme; ++ ++ return p_Scheme->valid; ++} ++ ++bool KgIsSchemeAlwaysDirect(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ if (p_FmPcd->p_FmPcdKg->schemes[schemeId].matchVector == SCHEME_ALWAYS_DIRECT) ++ return TRUE; ++ else ++ return FALSE; ++} ++ ++t_Error FmPcdKgAllocSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint8_t i, j; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE); ++ ++ /* This routine is issued only on master core of master partition - ++ either directly or through IPC, so no need for lock */ ++ ++ for (j = 0, i = 0; i < FM_PCD_KG_NUM_OF_SCHEMES && j < numOfSchemes; i++) ++ { ++ if (!p_FmPcd->p_FmPcdKg->schemesMng[i].allocated) ++ { ++ p_FmPcd->p_FmPcdKg->schemesMng[i].allocated = TRUE; ++ p_FmPcd->p_FmPcdKg->schemesMng[i].ownerId = guestId; ++ p_SchemesIds[j] = i; ++ j++; ++ } ++ } ++ ++ if (j != numOfSchemes) ++ { ++ /* roll back */ ++ for (j--; j; j--) ++ { ++ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[j]].allocated = FALSE; ++ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[j]].ownerId = 0; ++ p_SchemesIds[j] = 0; ++ } ++ ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("No schemes found")); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FmPcdKgFreeSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint8_t i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE); ++ ++ /* This routine is issued only on master core of master partition - ++ either directly or through IPC */ ++ ++ for (i = 0; i < numOfSchemes; i++) ++ { ++ if (!p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].allocated) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Scheme was not previously allocated")); ++ } ++ if (p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].ownerId != guestId) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Scheme is not owned by caller. ")); ++ } ++ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].allocated = FALSE; ++ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].ownerId = 0; ++ } ++ ++ return E_OK; ++} ++ ++t_Error KgAllocClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t *p_First) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint8_t numOfBlocks, blocksFound=0, first=0; ++ uint8_t i, j; ++ ++ /* This routine is issued only on master core of master partition - ++ either directly or through IPC, so no need for lock */ ++ ++ if (!numOfClsPlanEntries) ++ return E_OK; ++ ++ if ((numOfClsPlanEntries % CLS_PLAN_NUM_PER_GRP) || (!POWER_OF_2(numOfClsPlanEntries))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfClsPlanEntries must be a power of 2 and divisible by 8")); ++ ++ numOfBlocks = (uint8_t)(numOfClsPlanEntries/CLS_PLAN_NUM_PER_GRP); ++ ++ /* try to find consequent blocks */ ++ first = 0; ++ for (i = 0; i < FM_PCD_MAX_NUM_OF_CLS_PLANS/CLS_PLAN_NUM_PER_GRP;) ++ { ++ if (!p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated) ++ { ++ blocksFound++; ++ i++; ++ if (blocksFound == numOfBlocks) ++ break; ++ } ++ else ++ { ++ blocksFound = 0; ++ /* advance i to the next aligned address */ ++ first = i = (uint8_t)(first + numOfBlocks); ++ } ++ } ++ ++ if (blocksFound == numOfBlocks) ++ { ++ *p_First = (uint8_t)(first * CLS_PLAN_NUM_PER_GRP); ++ for (j = first; j < (first + numOfBlocks); j++) ++ { ++ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[j].allocated = TRUE; ++ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[j].ownerId = guestId; ++ } ++ return E_OK; ++ } ++ else ++ RETURN_ERROR(MINOR, E_FULL, ("No resources for clsPlan")); ++} ++ ++void KgFreeClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t base) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint8_t numOfBlocks; ++ uint8_t i, baseBlock; ++ ++#ifdef DISABLE_ASSERTIONS ++UNUSED(guestId); ++#endif /* DISABLE_ASSERTIONS */ ++ ++ /* This routine is issued only on master core of master partition - ++ either directly or through IPC, so no need for lock */ ++ ++ numOfBlocks = (uint8_t)(numOfClsPlanEntries/CLS_PLAN_NUM_PER_GRP); ++ ASSERT_COND(!(base%CLS_PLAN_NUM_PER_GRP)); ++ ++ baseBlock = (uint8_t)(base/CLS_PLAN_NUM_PER_GRP); ++ for (i=baseBlock;ip_FmPcdKg->clsPlanBlocksMng[i].allocated); ++ ASSERT_COND(guestId == p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].ownerId); ++ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated = FALSE; ++ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].ownerId = 0; ++ } ++} ++ ++void KgEnable(t_FmPcd *p_FmPcd) ++{ ++ struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ fman_kg_enable(p_Regs); ++} ++ ++void KgDisable(t_FmPcd *p_FmPcd) ++{ ++ struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ fman_kg_disable(p_Regs); ++} ++ ++void KgSetClsPlan(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanSet *p_Set) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ struct fman_kg_cp_regs *p_FmPcdKgPortRegs; ++ uint32_t tmpKgarReg = 0, intFlags; ++ uint16_t i, j; ++ ++ /* This routine is protected by the calling routine ! */ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ p_FmPcdKgPortRegs = &p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs; ++ ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ for (i=p_Set->baseEntry;ibaseEntry+p_Set->numOfClsPlanEntries;i+=8) ++ { ++ tmpKgarReg = FmPcdKgBuildWriteClsPlanBlockActionReg((uint8_t)(i / CLS_PLAN_NUM_PER_GRP)); ++ ++ for (j = i; j < i+8; j++) ++ { ++ ASSERT_COND(IN_RANGE(0, (j - p_Set->baseEntry), FM_PCD_MAX_NUM_OF_CLS_PLANS-1)); ++ WRITE_UINT32(p_FmPcdKgPortRegs->kgcpe[j % CLS_PLAN_NUM_PER_GRP],p_Set->vectors[j - p_Set->baseEntry]); ++ } ++ ++ if (WriteKgarWait(p_FmPcd, tmpKgarReg) != E_OK) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("WriteKgarWait FAILED")); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ return; ++ } ++ } ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++} ++ ++t_Handle KgConfig( t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams) ++{ ++ t_FmPcdKg *p_FmPcdKg; ++ ++ UNUSED(p_FmPcd); ++ ++ if (p_FmPcdParams->numOfSchemes > FM_PCD_KG_NUM_OF_SCHEMES) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("numOfSchemes should not exceed %d", FM_PCD_KG_NUM_OF_SCHEMES)); ++ return NULL; ++ } ++ ++ p_FmPcdKg = (t_FmPcdKg *)XX_Malloc(sizeof(t_FmPcdKg)); ++ if (!p_FmPcdKg) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Keygen allocation FAILED")); ++ return NULL; ++ } ++ memset(p_FmPcdKg, 0, sizeof(t_FmPcdKg)); ++ ++ ++ if (FmIsMaster(p_FmPcd->h_Fm)) ++ { ++ p_FmPcdKg->p_FmPcdKgRegs = (struct fman_kg_regs *)UINT_TO_PTR(FmGetPcdKgBaseAddr(p_FmPcdParams->h_Fm)); ++ p_FmPcd->exceptions |= DEFAULT_fmPcdKgErrorExceptions; ++ p_FmPcdKg->p_IndirectAccessRegs = (u_FmPcdKgIndirectAccessRegs *)&p_FmPcdKg->p_FmPcdKgRegs->fmkg_indirect[0]; ++ } ++ ++ p_FmPcdKg->numOfSchemes = p_FmPcdParams->numOfSchemes; ++ if ((p_FmPcd->guestId == NCSW_MASTER_ID) && !p_FmPcdKg->numOfSchemes) ++ { ++ p_FmPcdKg->numOfSchemes = FM_PCD_KG_NUM_OF_SCHEMES; ++ DBG(WARNING, ("numOfSchemes was defined 0 by user, re-defined by driver to FM_PCD_KG_NUM_OF_SCHEMES")); ++ } ++ ++ p_FmPcdKg->emptyClsPlanGrpId = ILLEGAL_CLS_PLAN; ++ ++ return p_FmPcdKg; ++} ++ ++t_Error KgInit(t_FmPcd *p_FmPcd) ++{ ++ t_Error err = E_OK; ++ ++ p_FmPcd->p_FmPcdKg->h_HwSpinlock = XX_InitSpinlock(); ++ if (!p_FmPcd->p_FmPcdKg->h_HwSpinlock) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM KG HW spinlock")); ++ ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ err = KgInitMaster(p_FmPcd); ++ else ++ err = KgInitGuest(p_FmPcd); ++ ++ if (err != E_OK) ++ { ++ if (p_FmPcd->p_FmPcdKg->h_HwSpinlock) ++ XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock); ++ } ++ ++ return err; ++} ++ ++t_Error KgFree(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdIpcKgSchemesParams kgAlloc; ++ t_Error err = E_OK; ++ t_FmPcdIpcMsg msg; ++ uint32_t replyLength; ++ t_FmPcdIpcReply reply; ++ ++ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_KG, 0, e_FM_INTR_TYPE_ERR); ++ ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ { ++ err = FmPcdKgFreeSchemes(p_FmPcd, ++ p_FmPcd->p_FmPcdKg->numOfSchemes, ++ p_FmPcd->guestId, ++ p_FmPcd->p_FmPcdKg->schemesIds); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (p_FmPcd->p_FmPcdKg->h_HwSpinlock) ++ XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock); ++ ++ return E_OK; ++ } ++ ++ /* guest */ ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ kgAlloc.numOfSchemes = p_FmPcd->p_FmPcdKg->numOfSchemes; ++ kgAlloc.guestId = p_FmPcd->guestId; ++ ASSERT_COND(kgAlloc.numOfSchemes < FM_PCD_KG_NUM_OF_SCHEMES); ++ memcpy(kgAlloc.schemesIds, p_FmPcd->p_FmPcdKg->schemesIds, (sizeof(uint8_t))*kgAlloc.numOfSchemes); ++ msg.msgId = FM_PCD_FREE_KG_SCHEMES; ++ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc)); ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(kgAlloc), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ ++ if (p_FmPcd->p_FmPcdKg->h_HwSpinlock) ++ XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock); ++ ++ return (t_Error)reply.error; ++} ++ ++t_Error FmPcdKgSetOrBindToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t netEnvId, protocolOpt_t *p_OptArray, uint8_t *p_ClsPlanGrpId, bool *p_IsEmptyClsPlanGrp) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdKgInterModuleClsPlanGrpParams grpParams, *p_GrpParams; ++ t_FmPcdKgClsPlanGrp *p_ClsPlanGrp; ++ t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet; ++ t_Error err; ++ ++ /* This function is issued only from FM_PORT_SetPcd which locked all PCD modules, ++ so no need for lock here */ ++ ++ memset(&grpParams, 0, sizeof(grpParams)); ++ grpParams.clsPlanGrpId = ILLEGAL_CLS_PLAN; ++ p_GrpParams = &grpParams; ++ ++ p_GrpParams->netEnvId = netEnvId; ++ ++ /* Get from the NetEnv the information of the clsPlan (can be already created, ++ * or needs to build) */ ++ err = PcdGetClsPlanGrpParams(h_FmPcd, p_GrpParams); ++ if (err) ++ RETURN_ERROR(MINOR,err,NO_MSG); ++ ++ if (p_GrpParams->grpExists) ++ { ++ /* this group was already updated (at least) in SW */ ++ *p_ClsPlanGrpId = p_GrpParams->clsPlanGrpId; ++ } ++ else ++ { ++ p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet)); ++ if (!p_ClsPlanSet) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set")); ++ memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet)); ++ /* Build (in SW) the clsPlan parameters, including the vectors to be written to HW */ ++ err = FmPcdKgBuildClsPlanGrp(h_FmPcd, p_GrpParams, p_ClsPlanSet); ++ if (err) ++ { ++ XX_Free(p_ClsPlanSet); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ *p_ClsPlanGrpId = p_GrpParams->clsPlanGrpId; ++ ++ if (p_FmPcd->h_Hc) ++ { ++ /* write clsPlan entries to memory */ ++ err = FmHcPcdKgSetClsPlan(p_FmPcd->h_Hc, p_ClsPlanSet); ++ if (err) ++ { ++ XX_Free(p_ClsPlanSet); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ else ++ /* write clsPlan entries to memory */ ++ KgSetClsPlan(p_FmPcd, p_ClsPlanSet); ++ ++ XX_Free(p_ClsPlanSet); ++ } ++ ++ /* Set caller parameters */ ++ ++ /* mark if this is an empty classification group */ ++ if (*p_ClsPlanGrpId == p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId) ++ *p_IsEmptyClsPlanGrp = TRUE; ++ else ++ *p_IsEmptyClsPlanGrp = FALSE; ++ ++ p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[*p_ClsPlanGrpId]; ++ ++ /* increment owners number */ ++ p_ClsPlanGrp->owners++; ++ ++ /* copy options array for port */ ++ memcpy(p_OptArray, &p_FmPcd->p_FmPcdKg->clsPlanGrps[*p_ClsPlanGrpId].optArray, FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)*sizeof(protocolOpt_t)); ++ ++ /* bind port to the new or existing group */ ++ err = BindPortToClsPlanGrp(p_FmPcd, hardwarePortId, p_GrpParams->clsPlanGrpId); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdKgDeleteOrUnbindPortToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdKgClsPlanGrp *p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId]; ++ t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet; ++ t_Error err; ++ ++ /* This function is issued only from FM_PORT_DeletePcd which locked all PCD modules, ++ so no need for lock here */ ++ ++ UnbindPortToClsPlanGrp(p_FmPcd, hardwarePortId); ++ ++ /* decrement owners number */ ++ ASSERT_COND(p_ClsPlanGrp->owners); ++ p_ClsPlanGrp->owners--; ++ ++ if (!p_ClsPlanGrp->owners) ++ { ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdKgDeleteClsPlan(p_FmPcd->h_Hc, clsPlanGrpId); ++ return err; ++ } ++ else ++ { ++ /* clear clsPlan entries in memory */ ++ p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet)); ++ if (!p_ClsPlanSet) ++ { ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set")); ++ } ++ memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet)); ++ ++ p_ClsPlanSet->baseEntry = p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].baseEntry; ++ p_ClsPlanSet->numOfClsPlanEntries = p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].sizeOfGrp; ++ KgSetClsPlan(p_FmPcd, p_ClsPlanSet); ++ XX_Free(p_ClsPlanSet); ++ ++ FmPcdKgDestroyClsPlanGrp(h_FmPcd, clsPlanGrpId); ++ } ++ } ++ return E_OK; ++} ++ ++uint32_t FmPcdKgGetRequiredAction(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid); ++ ++ return p_FmPcd->p_FmPcdKg->schemes[schemeId].requiredAction; ++} ++ ++uint32_t FmPcdKgGetPointedOwners(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid); ++ ++ return p_FmPcd->p_FmPcdKg->schemes[schemeId].pointedOwners; ++} ++ ++bool FmPcdKgIsDirectPlcr(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid); ++ ++ return p_FmPcd->p_FmPcdKg->schemes[schemeId].directPlcr; ++} ++ ++ ++uint16_t FmPcdKgGetRelativeProfileId(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid); ++ ++ return p_FmPcd->p_FmPcdKg->schemes[schemeId].relativeProfileId; ++} ++ ++bool FmPcdKgIsDistrOnPlcrProfile(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid); ++ ++ if ((p_FmPcd->p_FmPcdKg->schemes[schemeId].extractedOrs && ++ p_FmPcd->p_FmPcdKg->schemes[schemeId].bitOffsetInPlcrProfile) || ++ p_FmPcd->p_FmPcdKg->schemes[schemeId].nextRelativePlcrProfile) ++ return TRUE; ++ else ++ return FALSE; ++ ++} ++ ++e_FmPcdEngine FmPcdKgGetNextEngine(t_Handle h_FmPcd, uint8_t relativeSchemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].valid); ++ ++ return p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine; ++} ++ ++e_FmPcdDoneAction FmPcdKgGetDoneAction(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid); ++ ++ return p_FmPcd->p_FmPcdKg->schemes[schemeId].doneAction; ++} ++ ++void FmPcdKgUpdateRequiredAction(t_Handle h_Scheme, uint32_t requiredAction) ++{ ++ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme *)h_Scheme; ++ ++ /* this routine is protected by calling routine */ ++ ++ ASSERT_COND(p_Scheme->valid); ++ ++ p_Scheme->requiredAction |= requiredAction; ++} ++ ++bool FmPcdKgHwSchemeIsValid(uint32_t schemeModeReg) ++{ ++ return (bool)!!(schemeModeReg & KG_SCH_MODE_EN); ++} ++ ++uint32_t FmPcdKgBuildWriteSchemeActionReg(uint8_t schemeId, bool updateCounter) ++{ ++ return (uint32_t)(((uint32_t)schemeId << FM_PCD_KG_KGAR_NUM_SHIFT) | ++ FM_KG_KGAR_GO | ++ FM_KG_KGAR_WRITE | ++ FM_KG_KGAR_SEL_SCHEME_ENTRY | ++ DUMMY_PORT_ID | ++ (updateCounter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT:0)); ++} ++ ++uint32_t FmPcdKgBuildReadSchemeActionReg(uint8_t schemeId) ++{ ++ return (uint32_t)(((uint32_t)schemeId << FM_PCD_KG_KGAR_NUM_SHIFT) | ++ FM_KG_KGAR_GO | ++ FM_KG_KGAR_READ | ++ FM_KG_KGAR_SEL_SCHEME_ENTRY | ++ DUMMY_PORT_ID | ++ FM_KG_KGAR_SCM_WSEL_UPDATE_CNT); ++ ++} ++ ++uint32_t FmPcdKgBuildWriteClsPlanBlockActionReg(uint8_t grpId) ++{ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ FM_KG_KGAR_WRITE | ++ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY | ++ DUMMY_PORT_ID | ++ ((uint32_t)grpId << FM_PCD_KG_KGAR_NUM_SHIFT) | ++ FM_PCD_KG_KGAR_WSEL_MASK); ++ ++ /* if we ever want to write 1 by 1, use: ++ sel = (uint8_t)(0x01 << (7- (entryId % CLS_PLAN_NUM_PER_GRP))); ++ */ ++} ++ ++uint32_t FmPcdKgBuildWritePortSchemeBindActionReg(uint8_t hardwarePortId) ++{ ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ FM_KG_KGAR_WRITE | ++ FM_PCD_KG_KGAR_SEL_PORT_ENTRY | ++ hardwarePortId | ++ FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP); ++} ++ ++uint32_t FmPcdKgBuildReadPortSchemeBindActionReg(uint8_t hardwarePortId) ++{ ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ FM_KG_KGAR_READ | ++ FM_PCD_KG_KGAR_SEL_PORT_ENTRY | ++ hardwarePortId | ++ FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP); ++} ++ ++uint32_t FmPcdKgBuildWritePortClsPlanBindActionReg(uint8_t hardwarePortId) ++{ ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ FM_KG_KGAR_WRITE | ++ FM_PCD_KG_KGAR_SEL_PORT_ENTRY | ++ hardwarePortId | ++ FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP); ++} ++ ++uint8_t FmPcdKgGetClsPlanGrpBase(t_Handle h_FmPcd, uint8_t clsPlanGrp) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ return p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrp].baseEntry; ++} ++ ++uint16_t FmPcdKgGetClsPlanGrpSize(t_Handle h_FmPcd, uint8_t clsPlanGrp) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ return p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrp].sizeOfGrp; ++} ++ ++ ++uint8_t FmPcdKgGetSchemeId(t_Handle h_Scheme) ++{ ++ return ((t_FmPcdKgScheme*)h_Scheme)->schemeId; ++ ++} ++ ++#if (DPAA_VERSION >= 11) ++bool FmPcdKgGetVspe(t_Handle h_Scheme) ++{ ++ return ((t_FmPcdKgScheme*)h_Scheme)->vspe; ++ ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++uint8_t FmPcdKgGetRelativeSchemeId(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint8_t i; ++ ++ for (i = 0;ip_FmPcdKg->numOfSchemes;i++) ++ if (p_FmPcd->p_FmPcdKg->schemesIds[i] == schemeId) ++ return i; ++ ++ if (i == p_FmPcd->p_FmPcdKg->numOfSchemes) ++ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("Scheme is out of partition range")); ++ ++ return FM_PCD_KG_NUM_OF_SCHEMES; ++} ++ ++t_Error FmPcdKgCcGetSetParams(t_Handle h_FmPcd, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint8_t relativeSchemeId, physicalSchemeId; ++ uint32_t tmpKgarReg, tmpReg32 = 0, intFlags; ++ t_Error err; ++ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme*)h_Scheme; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, 0); ++ ++ /* Calling function locked all PCD modules, so no need to lock here */ ++ ++ if (!FmPcdKgIsSchemeValidSw(h_Scheme)) ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid")); ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdKgCcGetSetParams(p_FmPcd->h_Hc, h_Scheme, requiredAction, value); ++ ++ UpateSchemePointedOwner(h_Scheme,TRUE); ++ FmPcdKgUpdateRequiredAction(h_Scheme,requiredAction); ++ return err; ++ } ++ ++ physicalSchemeId = p_Scheme->schemeId; ++ ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId); ++ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ ++ if (!p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].pointedOwners || ++ !(p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].requiredAction & requiredAction)) ++ { ++ if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) ++ { ++ switch (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine) ++ { ++ case (e_FM_PCD_DONE): ++ if (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].doneAction == e_FM_PCD_ENQ_FRAME) ++ { ++ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode); ++ ASSERT_COND(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32 | NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA); ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ } ++ break; ++ case (e_FM_PCD_PLCR): ++ if (!p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].directPlcr || ++ (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].extractedOrs && ++ p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].bitOffsetInPlcrProfile) || ++ p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextRelativePlcrProfile) ++ { ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this situation PP can not be with distribution and has to be shared")); ++ } ++ err = FmPcdPlcrCcGetSetParams(h_FmPcd, p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].relativeProfileId, requiredAction); ++ if (err) ++ { ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("in this situation the next engine after scheme can be or PLCR or ENQ_FRAME")); ++ } ++ } ++ if (requiredAction & UPDATE_KG_NIA_CC_WA) ++ { ++ if (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine == e_FM_PCD_CC) ++ { ++ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode); ++ ASSERT_COND(tmpReg32 & (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC)); ++ tmpReg32 &= ~NIA_FM_CTL_AC_CC; ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32 | NIA_FM_CTL_AC_PRE_CC); ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ } ++ } ++ if (requiredAction & UPDATE_KG_OPT_MODE) ++ { ++ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_om, value); ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ } ++ if (requiredAction & UPDATE_KG_NIA) ++ { ++ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode); ++ tmpReg32 &= ~(NIA_ENG_MASK | NIA_AC_MASK); ++ tmpReg32 |= value; ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32); ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ } ++ } ++ ++ UpateSchemePointedOwner(h_Scheme, TRUE); ++ FmPcdKgUpdateRequiredAction(h_Scheme, requiredAction); ++ ++ return E_OK; ++} ++/*********************** End of inter-module routines ************************/ ++ ++ ++/****************************************/ ++/* API routines */ ++/****************************************/ ++ ++t_Handle FM_PCD_KgSchemeSet(t_Handle h_FmPcd, t_FmPcdKgSchemeParams *p_SchemeParams) ++{ ++ t_FmPcd *p_FmPcd; ++ struct fman_kg_scheme_regs schemeRegs; ++ struct fman_kg_scheme_regs *p_MemRegs; ++ uint8_t i; ++ t_Error err = E_OK; ++ uint32_t tmpKgarReg; ++ uint32_t intFlags; ++ uint8_t physicalSchemeId, relativeSchemeId = 0; ++ t_FmPcdKgScheme *p_Scheme; ++ ++ if (p_SchemeParams->modify) ++ { ++ p_Scheme = (t_FmPcdKgScheme *)p_SchemeParams->id.h_Scheme; ++ p_FmPcd = p_Scheme->h_FmPcd; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, NULL); ++ ++ if (!FmPcdKgIsSchemeValidSw(p_Scheme)) ++ { ++ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ++ ("Scheme is invalid")); ++ return NULL; ++ } ++ ++ if (!KgSchemeFlagTryLock(p_Scheme)) ++ { ++ DBG(TRACE, ("Scheme Try Lock - BUSY")); ++ /* Signal to caller BUSY condition */ ++ p_SchemeParams->id.h_Scheme = NULL; ++ return NULL; ++ } ++ } ++ else ++ { ++ p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, NULL); ++ ++ relativeSchemeId = p_SchemeParams->id.relativeSchemeId; ++ /* check that schemeId is in range */ ++ if (relativeSchemeId >= p_FmPcd->p_FmPcdKg->numOfSchemes) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("relative-scheme-id %d!", relativeSchemeId)); ++ return NULL; ++ } ++ ++ p_Scheme = &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId]; ++ if (FmPcdKgIsSchemeValidSw(p_Scheme)) ++ { ++ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ++ ("Scheme id (%d)!", relativeSchemeId)); ++ return NULL; ++ } ++ ++ p_Scheme->schemeId = p_FmPcd->p_FmPcdKg->schemesIds[relativeSchemeId]; ++ p_Scheme->h_FmPcd = p_FmPcd; ++ ++ p_Scheme->p_Lock = FmPcdAcquireLock(p_FmPcd); ++ if (!p_Scheme->p_Lock) ++ REPORT_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM KG Scheme lock obj!")); ++ } ++ ++ err = BuildSchemeRegs((t_Handle)p_Scheme, p_SchemeParams, &schemeRegs); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ if (p_SchemeParams->modify) ++ KgSchemeFlagUnlock(p_Scheme); ++ if (!p_SchemeParams->modify && ++ p_Scheme->p_Lock) ++ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock); ++ return NULL; ++ } ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdKgSetScheme(p_FmPcd->h_Hc, ++ (t_Handle)p_Scheme, ++ &schemeRegs, ++ p_SchemeParams->schemeCounter.update); ++ if (p_SchemeParams->modify) ++ KgSchemeFlagUnlock(p_Scheme); ++ if (err) ++ { ++ if (!p_SchemeParams->modify && ++ p_Scheme->p_Lock) ++ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock); ++ return NULL; ++ } ++ if (!p_SchemeParams->modify) ++ ValidateSchemeSw(p_Scheme); ++ return (t_Handle)p_Scheme; ++ } ++ ++ physicalSchemeId = p_Scheme->schemeId; ++ ++ /* configure all 21 scheme registers */ ++ p_MemRegs = &p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs; ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WRITE_UINT32(p_MemRegs->kgse_ppc, schemeRegs.kgse_ppc); ++ WRITE_UINT32(p_MemRegs->kgse_ccbs, schemeRegs.kgse_ccbs); ++ WRITE_UINT32(p_MemRegs->kgse_mode, schemeRegs.kgse_mode); ++ WRITE_UINT32(p_MemRegs->kgse_mv, schemeRegs.kgse_mv); ++ WRITE_UINT32(p_MemRegs->kgse_dv0, schemeRegs.kgse_dv0); ++ WRITE_UINT32(p_MemRegs->kgse_dv1, schemeRegs.kgse_dv1); ++ WRITE_UINT32(p_MemRegs->kgse_ekdv, schemeRegs.kgse_ekdv); ++ WRITE_UINT32(p_MemRegs->kgse_ekfc, schemeRegs.kgse_ekfc); ++ WRITE_UINT32(p_MemRegs->kgse_bmch, schemeRegs.kgse_bmch); ++ WRITE_UINT32(p_MemRegs->kgse_bmcl, schemeRegs.kgse_bmcl); ++ WRITE_UINT32(p_MemRegs->kgse_hc, schemeRegs.kgse_hc); ++ WRITE_UINT32(p_MemRegs->kgse_spc, schemeRegs.kgse_spc); ++ WRITE_UINT32(p_MemRegs->kgse_fqb, schemeRegs.kgse_fqb); ++ WRITE_UINT32(p_MemRegs->kgse_om, schemeRegs.kgse_om); ++ WRITE_UINT32(p_MemRegs->kgse_vsp, schemeRegs.kgse_vsp); ++ for (i=0 ; ikgse_gec[i], schemeRegs.kgse_gec[i]); ++ ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, p_SchemeParams->schemeCounter.update); ++ ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ ++ if (!p_SchemeParams->modify) ++ ValidateSchemeSw(p_Scheme); ++ else ++ KgSchemeFlagUnlock(p_Scheme); ++ ++ return (t_Handle)p_Scheme; ++} ++ ++t_Error FM_PCD_KgSchemeDelete(t_Handle h_Scheme) ++{ ++ t_FmPcd *p_FmPcd; ++ uint8_t physicalSchemeId; ++ uint32_t tmpKgarReg, intFlags; ++ t_Error err = E_OK; ++ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme *)h_Scheme; ++ ++ SANITY_CHECK_RETURN_ERROR(h_Scheme, E_INVALID_HANDLE); ++ ++ p_FmPcd = (t_FmPcd*)(p_Scheme->h_FmPcd); ++ ++ /* check that no port is bound to this scheme */ ++ err = InvalidateSchemeSw(h_Scheme); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdKgDeleteScheme(p_FmPcd->h_Hc, h_Scheme); ++ if (p_Scheme->p_Lock) ++ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock); ++ return err; ++ } ++ ++ physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId; ++ ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ /* clear mode register, including enable bit */ ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, 0); ++ ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE); ++ ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ ++ if (p_Scheme->p_Lock) ++ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock); ++ ++ return E_OK; ++} ++ ++uint32_t FM_PCD_KgSchemeGetCounter(t_Handle h_Scheme) ++{ ++ t_FmPcd *p_FmPcd; ++ uint32_t tmpKgarReg, spc, intFlags; ++ uint8_t physicalSchemeId; ++ ++ SANITY_CHECK_RETURN_VALUE(h_Scheme, E_INVALID_HANDLE, 0); ++ ++ p_FmPcd = (t_FmPcd*)(((t_FmPcdKgScheme *)h_Scheme)->h_FmPcd); ++ if (p_FmPcd->h_Hc) ++ return FmHcPcdKgGetSchemeCounter(p_FmPcd->h_Hc, h_Scheme); ++ ++ physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId; ++ ++ if (FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId) == FM_PCD_KG_NUM_OF_SCHEMES) ++ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ ++ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ if (!(GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode) & KG_SCH_MODE_EN)) ++ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid")); ++ spc = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_spc); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ ++ return spc; ++} ++ ++t_Error FM_PCD_KgSchemeSetCounter(t_Handle h_Scheme, uint32_t value) ++{ ++ t_FmPcd *p_FmPcd; ++ uint32_t tmpKgarReg, intFlags; ++ uint8_t physicalSchemeId; ++ ++ SANITY_CHECK_RETURN_VALUE(h_Scheme, E_INVALID_HANDLE, 0); ++ ++ p_FmPcd = (t_FmPcd*)(((t_FmPcdKgScheme *)h_Scheme)->h_FmPcd); ++ ++ if (!FmPcdKgIsSchemeValidSw(h_Scheme)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Requested scheme is invalid.")); ++ ++ if (p_FmPcd->h_Hc) ++ return FmHcPcdKgSetSchemeCounter(p_FmPcd->h_Hc, h_Scheme, value); ++ ++ physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId; ++ /* check that schemeId is in range */ ++ if (FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId) == FM_PCD_KG_NUM_OF_SCHEMES) ++ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ ++ /* read specified scheme into scheme registers */ ++ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ if (!(GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode) & KG_SCH_MODE_EN)) ++ { ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid")); ++ } ++ ++ /* change counter value */ ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_spc, value); ++ ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE); ++ ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_KgSetAdditionalDataAfterParsing(t_Handle h_FmPcd, uint8_t payloadOffset) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ struct fman_kg_regs *p_Regs; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, E_NULL_POINTER); ++ ++ p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ if (!FmIsMaster(p_FmPcd->h_Fm)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_KgSetAdditionalDataAfterParsing - guest mode!")); ++ ++ WRITE_UINT32(p_Regs->fmkg_fdor,payloadOffset); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_KgSetDfltValue(t_Handle h_FmPcd, uint8_t valueId, uint32_t value) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ struct fman_kg_regs *p_Regs; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((valueId == 0) || (valueId == 1)), E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, E_NULL_POINTER); ++ ++ p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ if (!FmIsMaster(p_FmPcd->h_Fm)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_KgSetDfltValue - guest mode!")); ++ ++ if (valueId == 0) ++ WRITE_UINT32(p_Regs->fmkg_gdv0r,value); ++ else ++ WRITE_UINT32(p_Regs->fmkg_gdv1r,value); ++ return E_OK; ++} ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++t_Error FM_PCD_KgDumpRegs(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ int i = 0, j = 0; ++ uint8_t hardwarePortId = 0; ++ uint32_t tmpKgarReg, intFlags; ++ t_Error err = E_OK; ++ ++ DECLARE_DUMP; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(((p_FmPcd->guestId == NCSW_MASTER_ID) || ++ p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs), E_INVALID_OPERATION); ++ ++ DUMP_SUBTITLE(("\n")); ++ DUMP_TITLE(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, ("FmPcdKgRegs Regs")); ++ ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_gcr); ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_eer); ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_eeer); ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_seer); ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_seeer); ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_gsr); ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_tpc); ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_serc); ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_fdor); ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_gdv0r); ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_gdv1r); ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_feer); ++ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_ar); ++ ++ DUMP_SUBTITLE(("\n")); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ for (j = 0;jp_FmPcdKg->p_IndirectAccessRegs->schemeRegs, ("FmPcdKgIndirectAccessSchemeRegs Scheme %d Regs", j)); ++ ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_mode); ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_ekfc); ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_ekdv); ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_bmch); ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_bmcl); ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_fqb); ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_hc); ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_ppc); ++ ++ DUMP_TITLE(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_gec, ("kgse_gec")); ++ DUMP_SUBSTRUCT_ARRAY(i, FM_KG_NUM_OF_GENERIC_REGS) ++ { ++ DUMP_MEMORY(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_gec[i], sizeof(uint32_t)); ++ } ++ ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_spc); ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_dv0); ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_dv1); ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_ccbs); ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_mv); ++ } ++ DUMP_SUBTITLE(("\n")); ++ ++ for (i=0;ip_FmPcdKg->p_IndirectAccessRegs->portRegs, ("FmPcdKgIndirectAccessPortRegs PCD Port %d regs", hardwarePortId)); ++ ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->portRegs, fmkg_pe_sp); ++ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->portRegs, fmkg_pe_cpp); ++ } ++ ++ DUMP_SUBTITLE(("\n")); ++ for (j=0;jp_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs, ("FmPcdKgIndirectAccessClsPlanRegs Regs group %d", j)); ++ DUMP_TITLE(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs.kgcpe, ("kgcpe")); ++ ++ tmpKgarReg = ReadClsPlanBlockActionReg((uint8_t)j); ++ err = WriteKgarWait(p_FmPcd, tmpKgarReg); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ DUMP_SUBSTRUCT_ARRAY(i, 8) ++ DUMP_MEMORY(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs.kgcpe[i], sizeof(uint32_t)); ++ } ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ ++ return E_OK; ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_kg.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_kg.h +new file mode 100644 +index 0000000..cb7521a +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_kg.h +@@ -0,0 +1,206 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_kg.h ++ ++ @Description FM KG private header ++*//***************************************************************************/ ++#ifndef __FM_KG_H ++#define __FM_KG_H ++ ++#include "std_ext.h" ++ ++/***********************************************************************/ ++/* Keygen defines */ ++/***********************************************************************/ ++/* maskes */ ++#if (DPAA_VERSION >= 11) ++#define KG_SCH_VSP_SHIFT_MASK 0x0003f000 ++#define KG_SCH_OM_VSPE 0x00000001 ++#define KG_SCH_VSP_NO_KSP_EN 0x80000000 ++ ++#define MAX_SP_SHIFT 23 ++#define KG_SCH_VSP_MASK_SHIFT 12 ++#define KG_SCH_VSP_SHIFT 24 ++#endif /* (DPAA_VERSION >= 11) */ ++ ++typedef uint32_t t_KnownFieldsMasks; ++#define KG_SCH_KN_PORT_ID 0x80000000 ++#define KG_SCH_KN_MACDST 0x40000000 ++#define KG_SCH_KN_MACSRC 0x20000000 ++#define KG_SCH_KN_TCI1 0x10000000 ++#define KG_SCH_KN_TCI2 0x08000000 ++#define KG_SCH_KN_ETYPE 0x04000000 ++#define KG_SCH_KN_PPPSID 0x02000000 ++#define KG_SCH_KN_PPPID 0x01000000 ++#define KG_SCH_KN_MPLS1 0x00800000 ++#define KG_SCH_KN_MPLS2 0x00400000 ++#define KG_SCH_KN_MPLS_LAST 0x00200000 ++#define KG_SCH_KN_IPSRC1 0x00100000 ++#define KG_SCH_KN_IPDST1 0x00080000 ++#define KG_SCH_KN_PTYPE1 0x00040000 ++#define KG_SCH_KN_IPTOS_TC1 0x00020000 ++#define KG_SCH_KN_IPV6FL1 0x00010000 ++#define KG_SCH_KN_IPSRC2 0x00008000 ++#define KG_SCH_KN_IPDST2 0x00004000 ++#define KG_SCH_KN_PTYPE2 0x00002000 ++#define KG_SCH_KN_IPTOS_TC2 0x00001000 ++#define KG_SCH_KN_IPV6FL2 0x00000800 ++#define KG_SCH_KN_GREPTYPE 0x00000400 ++#define KG_SCH_KN_IPSEC_SPI 0x00000200 ++#define KG_SCH_KN_IPSEC_NH 0x00000100 ++#define KG_SCH_KN_IPPID 0x00000080 ++#define KG_SCH_KN_L4PSRC 0x00000004 ++#define KG_SCH_KN_L4PDST 0x00000002 ++#define KG_SCH_KN_TFLG 0x00000001 ++ ++typedef uint8_t t_GenericCodes; ++#define KG_SCH_GEN_SHIM1 0x70 ++#define KG_SCH_GEN_DEFAULT 0x10 ++#define KG_SCH_GEN_PARSE_RESULT_N_FQID 0x20 ++#define KG_SCH_GEN_START_OF_FRM 0x40 ++#define KG_SCH_GEN_SHIM2 0x71 ++#define KG_SCH_GEN_IP_PID_NO_V 0x72 ++#define KG_SCH_GEN_ETH 0x03 ++#define KG_SCH_GEN_ETH_NO_V 0x73 ++#define KG_SCH_GEN_SNAP 0x04 ++#define KG_SCH_GEN_SNAP_NO_V 0x74 ++#define KG_SCH_GEN_VLAN1 0x05 ++#define KG_SCH_GEN_VLAN1_NO_V 0x75 ++#define KG_SCH_GEN_VLAN2 0x06 ++#define KG_SCH_GEN_VLAN2_NO_V 0x76 ++#define KG_SCH_GEN_ETH_TYPE 0x07 ++#define KG_SCH_GEN_ETH_TYPE_NO_V 0x77 ++#define KG_SCH_GEN_PPP 0x08 ++#define KG_SCH_GEN_PPP_NO_V 0x78 ++#define KG_SCH_GEN_MPLS1 0x09 ++#define KG_SCH_GEN_MPLS2 0x19 ++#define KG_SCH_GEN_MPLS3 0x29 ++#define KG_SCH_GEN_MPLS1_NO_V 0x79 ++#define KG_SCH_GEN_MPLS_LAST 0x0a ++#define KG_SCH_GEN_MPLS_LAST_NO_V 0x7a ++#define KG_SCH_GEN_IPV4 0x0b ++#define KG_SCH_GEN_IPV6 0x1b ++#define KG_SCH_GEN_L3_NO_V 0x7b ++#define KG_SCH_GEN_IPV4_TUNNELED 0x0c ++#define KG_SCH_GEN_IPV6_TUNNELED 0x1c ++#define KG_SCH_GEN_MIN_ENCAP 0x2c ++#define KG_SCH_GEN_IP2_NO_V 0x7c ++#define KG_SCH_GEN_GRE 0x0d ++#define KG_SCH_GEN_GRE_NO_V 0x7d ++#define KG_SCH_GEN_TCP 0x0e ++#define KG_SCH_GEN_UDP 0x1e ++#define KG_SCH_GEN_IPSEC_AH 0x2e ++#define KG_SCH_GEN_SCTP 0x3e ++#define KG_SCH_GEN_DCCP 0x4e ++#define KG_SCH_GEN_IPSEC_ESP 0x6e ++#define KG_SCH_GEN_L4_NO_V 0x7e ++#define KG_SCH_GEN_NEXTHDR 0x7f ++/* shifts */ ++#define KG_SCH_PP_SHIFT_HIGH_SHIFT 27 ++#define KG_SCH_PP_SHIFT_LOW_SHIFT 12 ++#define KG_SCH_PP_MASK_SHIFT 16 ++#define KG_SCH_MODE_CCOBASE_SHIFT 24 ++#define KG_SCH_DEF_MAC_ADDR_SHIFT 30 ++#define KG_SCH_DEF_TCI_SHIFT 28 ++#define KG_SCH_DEF_ENET_TYPE_SHIFT 26 ++#define KG_SCH_DEF_PPP_SESSION_ID_SHIFT 24 ++#define KG_SCH_DEF_PPP_PROTOCOL_ID_SHIFT 22 ++#define KG_SCH_DEF_MPLS_LABEL_SHIFT 20 ++#define KG_SCH_DEF_IP_ADDR_SHIFT 18 ++#define KG_SCH_DEF_PROTOCOL_TYPE_SHIFT 16 ++#define KG_SCH_DEF_IP_TOS_TC_SHIFT 14 ++#define KG_SCH_DEF_IPV6_FLOW_LABEL_SHIFT 12 ++#define KG_SCH_DEF_IPSEC_SPI_SHIFT 10 ++#define KG_SCH_DEF_L4_PORT_SHIFT 8 ++#define KG_SCH_DEF_TCP_FLAG_SHIFT 6 ++#define KG_SCH_HASH_CONFIG_SHIFT_SHIFT 24 ++#define KG_SCH_GEN_MASK_SHIFT 16 ++#define KG_SCH_GEN_HT_SHIFT 8 ++#define KG_SCH_GEN_SIZE_SHIFT 24 ++#define KG_SCH_GEN_DEF_SHIFT 29 ++#define FM_PCD_KG_KGAR_NUM_SHIFT 16 ++ ++/* others */ ++#define NUM_OF_SW_DEFAULTS 3 ++#define MAX_PP_SHIFT 23 ++#define MAX_KG_SCH_SIZE 16 ++#define MASK_FOR_GENERIC_BASE_ID 0x20 ++#define MAX_HASH_SHIFT 40 ++#define MAX_KG_SCH_FQID_BIT_OFFSET 31 ++#define MAX_KG_SCH_PP_BIT_OFFSET 15 ++#define MAX_DIST_FQID_SHIFT 23 ++ ++#define GET_MASK_SEL_SHIFT(shift,i) \ ++switch (i) { \ ++ case (0):shift = 26;break; \ ++ case (1):shift = 20;break; \ ++ case (2):shift = 10;break; \ ++ case (3):shift = 4;break; \ ++ default: \ ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); \ ++} ++ ++#define GET_MASK_OFFSET_SHIFT(shift,i) \ ++switch (i) { \ ++ case (0):shift = 16;break; \ ++ case (1):shift = 0;break; \ ++ case (2):shift = 28;break; \ ++ case (3):shift = 24;break; \ ++ default: \ ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); \ ++} ++ ++#define GET_MASK_SHIFT(shift,i) \ ++switch (i) { \ ++ case (0):shift = 24;break; \ ++ case (1):shift = 16;break; \ ++ case (2):shift = 8;break; \ ++ case (3):shift = 0;break; \ ++ default: \ ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); \ ++} ++ ++/***********************************************************************/ ++/* Keygen defines */ ++/***********************************************************************/ ++ ++#define KG_DOUBLE_MEANING_REGS_OFFSET 0x100 ++#define NO_VALIDATION 0x70 ++#define KG_ACTION_REG_TO 1024 ++#define KG_MAX_PROFILE 255 ++#define SCHEME_ALWAYS_DIRECT 0xFFFFFFFF ++ ++ ++#endif /* __FM_KG_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_manip.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_manip.c +new file mode 100644 +index 0000000..e6c8d2d +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_manip.c +@@ -0,0 +1,4193 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_manip.c ++ ++ @Description FM PCD manip ... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_port_ext.h" ++#include "fm_muram_ext.h" ++#include "memcpy_ext.h" ++ ++#include "fm_common.h" ++#include "fm_hc.h" ++#include "fm_manip.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++static t_Handle GetManipInfo(t_FmPcdManip *p_Manip, e_ManipInfo manipInfo) ++{ ++ t_FmPcdManip *p_CurManip = p_Manip; ++ ++ if (!MANIP_IS_UNIFIED(p_Manip)) ++ p_CurManip = p_Manip; ++ else ++ { ++ /* go to first unified */ ++ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip)) ++ p_CurManip = p_CurManip->h_PrevManip; ++ } ++ ++ switch (manipInfo) ++ { ++ case (e_MANIP_HMCT): ++ return p_CurManip->p_Hmct; ++ case (e_MANIP_HMTD): ++ return p_CurManip->h_Ad; ++ case (e_MANIP_HANDLER_TABLE_OWNER): ++ return (t_Handle)p_CurManip; ++ default: ++ return NULL; ++ } ++} ++static uint16_t GetHmctSize(t_FmPcdManip *p_Manip) ++{ ++ uint16_t size = 0; ++ t_FmPcdManip *p_CurManip = p_Manip; ++ ++ if (!MANIP_IS_UNIFIED(p_Manip)) ++ return p_Manip->tableSize; ++ ++ /* accumulate sizes, starting with the first node */ ++ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip)) ++ p_CurManip = p_CurManip->h_PrevManip; ++ ++ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) ++ { ++ size += p_CurManip->tableSize; ++ p_CurManip = (t_FmPcdManip *)p_CurManip->h_NextManip; ++ } ++ size += p_CurManip->tableSize; /* add last size */ ++ ++ return(size); ++} ++static uint16_t GetDataSize(t_FmPcdManip *p_Manip) ++{ ++ uint16_t size = 0; ++ t_FmPcdManip *p_CurManip = p_Manip; ++ ++ if (!MANIP_IS_UNIFIED(p_Manip)) ++ return p_Manip->dataSize; ++ ++ /* accumulate sizes, starting with the first node */ ++ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip)) ++ p_CurManip = p_CurManip->h_PrevManip; ++ ++ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) ++ { ++ size += p_CurManip->dataSize; ++ p_CurManip = (t_FmPcdManip *)p_CurManip->h_NextManip; ++ } ++ size += p_CurManip->dataSize; /* add last size */ ++ ++ return(size); ++} ++static t_Error CalculateTableSize(t_FmPcdManipParams *p_FmPcdManipParams, uint16_t *p_TableSize, uint8_t *p_DataSize) ++{ ++ uint8_t localDataSize, remain, tableSize = 0, dataSize = 0; ++ ++ if (p_FmPcdManipParams->u.hdr.rmv) ++ { ++ switch (p_FmPcdManipParams->u.hdr.rmvParams.type){ ++ case (e_FM_PCD_MANIP_RMV_GENERIC): ++ case (e_FM_PCD_MANIP_RMV_BY_HDR): ++ /* As long as the only rmv command is the L2, no check on type is required */ ++ tableSize += HMCD_BASIC_SIZE; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown rmvParams.type")); ++ } ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.insrt) ++ { ++ switch (p_FmPcdManipParams->u.hdr.insrtParams.type){ ++ case (e_FM_PCD_MANIP_INSRT_GENERIC): ++ remain = (uint8_t)(p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size % 4); ++ if (remain) ++ localDataSize = (uint8_t)(p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size + 4 - remain); ++ else ++ localDataSize = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size; ++ tableSize += (uint8_t)(HMCD_BASIC_SIZE + localDataSize); ++ break; ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR): ++ /* As long as the only insert command is the internal L2, no check on type is required */ ++ tableSize += HMCD_BASIC_SIZE+HMCD_PTR_SIZE; ++ if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.type == e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2) ++ switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.specificL2) ++ { ++ case (e_FM_PCD_MANIP_HDR_INSRT_MPLS): ++ dataSize += p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.size; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ } ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown insrtParams.type")); ++ } ++ } ++ if (p_FmPcdManipParams->u.hdr.fieldUpdate) ++ { ++ switch (p_FmPcdManipParams->u.hdr.fieldUpdateParams.type){ ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN): ++ tableSize += HMCD_BASIC_SIZE; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN) ++ { ++ tableSize += HMCD_PTR_SIZE; ++ dataSize += DSCP_TO_VLAN_TABLE_SIZE; ++ } ++ break; ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4): ++ tableSize += HMCD_BASIC_SIZE; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_ID) ++ { ++ tableSize += HMCD_PARAM_SIZE; ++ dataSize += 2; ++ } ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_SRC) ++ tableSize += HMCD_IPV4_ADDR_SIZE; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_DST) ++ tableSize += HMCD_IPV4_ADDR_SIZE; ++ break; ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6): ++ tableSize += HMCD_BASIC_SIZE; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV6_SRC) ++ tableSize += HMCD_IPV6_ADDR_SIZE; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV6_DST) ++ tableSize += HMCD_IPV6_ADDR_SIZE; ++ break; ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP): ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates == HDR_MANIP_TCP_UDP_CHECKSUM) ++ /* we implement this case with the update-checksum descriptor */ ++ tableSize += HMCD_BASIC_SIZE; ++ else ++ /* we implement this case with the TCP/UDP-update descriptor */ ++ tableSize += HMCD_BASIC_SIZE + HMCD_PARAM_SIZE; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown fieldUpdateParams.type")); ++ } ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.custom) ++ { ++ switch (p_FmPcdManipParams->u.hdr.customParams.type){ ++ case (e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE): ++ { ++ tableSize += HMCD_BASIC_SIZE + HMCD_PARAM_SIZE + HMCD_PARAM_SIZE; ++ dataSize += p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdrSize; ++ if ((p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) && ++ (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id)) ++ dataSize += 2; ++ } ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown customParams.type")); ++ } ++ } ++ ++ *p_TableSize = tableSize; ++ *p_DataSize = dataSize; ++ ++ return E_OK; ++} ++ ++static t_Error BuildHmct(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams, uint8_t *p_DestHmct, uint8_t *p_DestData, bool new) ++{ ++ uint32_t *p_TmpHmct = (uint32_t*)p_DestHmct, *p_LocalData; ++ uint32_t tmpReg=0, *p_Last = NULL; ++ uint8_t remain, i, size=0, origSize, *p_UsrData = NULL, *p_TmpData = p_DestData; ++ t_Handle h_FmPcd = p_Manip->h_FmPcd; ++ uint8_t j=0; ++ ++ if (p_FmPcdManipParams->u.hdr.rmv) ++ { ++ if (p_FmPcdManipParams->u.hdr.rmvParams.type == e_FM_PCD_MANIP_RMV_GENERIC) ++ { ++ /* initialize HMCD */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_RMV) << HMCD_OC_SHIFT; ++ /* tmp, should be conditional */ ++ tmpReg |= p_FmPcdManipParams->u.hdr.rmvParams.u.generic.offset << HMCD_RMV_OFFSET_SHIFT; ++ tmpReg |= p_FmPcdManipParams->u.hdr.rmvParams.u.generic.size << HMCD_RMV_SIZE_SHIFT; ++ } ++ else if (p_FmPcdManipParams->u.hdr.rmvParams.type == e_FM_PCD_MANIP_RMV_BY_HDR) ++ { ++ uint8_t hmcdOpt; ++ if (!p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.type == e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ ++ /* initialize HMCD */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_L2_RMV) << HMCD_OC_SHIFT; ++ ++ switch (p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.u.specificL2) ++ { ++ case (e_FM_PCD_MANIP_HDR_RMV_ETHERNET): ++ hmcdOpt = HMCD_RMV_L2_ETHERNET; ++ break; ++ case (e_FM_PCD_MANIP_HDR_RMV_STACKED_QTAGS): ++ hmcdOpt = HMCD_RMV_L2_STACKED_QTAGS; ++ break; ++ case (e_FM_PCD_MANIP_HDR_RMV_ETHERNET_AND_MPLS): ++ hmcdOpt = HMCD_RMV_L2_ETHERNET_AND_MPLS; ++ break; ++ case (e_FM_PCD_MANIP_HDR_RMV_MPLS): ++ hmcdOpt = HMCD_RMV_L2_MPLS; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ } ++ tmpReg |= hmcdOpt << HMCD_L2_MODE_SHIFT; ++ } ++ else ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("manip header remove type!")); ++ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ /* advance to next command */ ++ p_TmpHmct += HMCD_BASIC_SIZE/4; ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.insrt) ++ { ++ if (p_FmPcdManipParams->u.hdr.insrtParams.type == e_FM_PCD_MANIP_INSRT_GENERIC) ++ { ++ /* initialize HMCD */ ++ if (p_FmPcdManipParams->u.hdr.insrtParams.u.generic.replace) ++ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_REPLACE) << HMCD_OC_SHIFT; ++ else ++ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_INSRT) << HMCD_OC_SHIFT; ++ ++ tmpReg |= p_FmPcdManipParams->u.hdr.insrtParams.u.generic.offset << HMCD_INSRT_OFFSET_SHIFT; ++ tmpReg |= p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size << HMCD_INSRT_SIZE_SHIFT; ++ ++ size = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size; ++ p_UsrData = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.p_Data; ++ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE/4; ++ ++ /* initialize data to be inserted */ ++ /* if size is not a multiple of 4, padd with 0's */ ++ origSize = size; ++ remain = (uint8_t)(size % 4); ++ if (remain) ++ { ++ size += (uint8_t)(4 - remain); ++ p_LocalData = (uint32_t *)XX_Malloc(size); ++ memset((uint8_t *)p_LocalData, 0, size); ++ memcpy((uint8_t *)p_LocalData, p_UsrData, origSize); ++ } ++ else ++ p_LocalData = (uint32_t*)p_UsrData; ++ ++ /* initialize data and advance pointer to next command */ ++ for (i = 0; iu.hdr.insrtParams.type == e_FM_PCD_MANIP_INSRT_BY_HDR) ++ { ++ uint8_t hmcdOpt; ++ if (!p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.type == e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ ++ /* initialize HMCD */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_L2_INSRT) << HMCD_OC_SHIFT; ++ ++ switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.specificL2) ++ { ++ case (e_FM_PCD_MANIP_HDR_INSRT_MPLS): ++ if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.update) ++ hmcdOpt = HMCD_INSRT_N_UPDATE_L2_MPLS; ++ else ++ hmcdOpt = HMCD_INSRT_L2_MPLS; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ } ++ tmpReg |= hmcdOpt << HMCD_L2_MODE_SHIFT; ++ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE/4; ++ ++ /* set size and pointer of user's data */ ++ size = (uint8_t)p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.size; ++ ++ ASSERT_COND(p_TmpData); ++ Mem2IOCpy32(p_TmpData, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.p_Data, size); ++ tmpReg = (size << HMCD_INSRT_L2_SIZE_SHIFT) | (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase)); ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ p_TmpHmct += HMCD_PTR_SIZE/4; ++ p_TmpData += size; ++ } ++ else ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("manip header insert type!")); ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.fieldUpdate) ++ { ++ switch (p_FmPcdManipParams->u.hdr.fieldUpdateParams.type){ ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN): ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_VLAN_PRI_UPDATE) << HMCD_OC_SHIFT; ++ ++ /* set mode & table pointer */ ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN) ++ { ++ /* set Mode */ ++ tmpReg |= (uint32_t)(HMCD_VLAN_PRI_UPDATE_DSCP_TO_VPRI) << HMCD_VLAN_PRI_REP_MODE_SHIFT; ++ /* set VPRI default */ ++ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.vpriDefVal; ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ /* write the table pointer into the Manip descriptor */ ++ p_TmpHmct += HMCD_BASIC_SIZE/4; ++ ++ tmpReg = 0; ++ ASSERT_COND(p_TmpData); ++ for (i=0; iu.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.dscpToVpriTable[i]) << (32-4*(j+1)); ++ j++; ++ /* Than we write this register to the next table word ++ * (i=7-->word 0, i=15-->word 1,... i=63-->word 7) */ ++ if ((i%8) == 7) ++ { ++ WRITE_UINT32(*((uint32_t*)p_TmpData + (i+1)/8-1), tmpReg); ++ tmpReg = 0; ++ j = 0; ++ } ++ } ++ WRITE_UINT32(*p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase))); ++ p_TmpHmct += HMCD_PTR_SIZE/4; ++ ++ p_TmpData += DSCP_TO_VLAN_TABLE_SIZE; ++ } ++ else if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI) ++ { ++ /* set Mode */ ++ /* line commented out as it has no-side-effect ('0' value). */ ++ /*tmpReg |= HMCD_VLAN_PRI_UPDATE << HMCD_VLAN_PRI_REP_MODE_SHIFT*/; ++ /* set VPRI parameter */ ++ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.vpri; ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ p_TmpHmct += HMCD_BASIC_SIZE/4; ++ } ++ break; ++ ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4): ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_IPV4_UPDATE) << HMCD_OC_SHIFT; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_TTL) ++ tmpReg |= HMCD_IPV4_UPDATE_TTL; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_TOS) ++ { ++ tmpReg |= HMCD_IPV4_UPDATE_TOS; ++ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.tos << HMCD_IPV4_UPDATE_TOS_SHIFT; ++ } ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_ID) ++ tmpReg |= HMCD_IPV4_UPDATE_ID; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_SRC) ++ tmpReg |= HMCD_IPV4_UPDATE_SRC; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_DST) ++ tmpReg |= HMCD_IPV4_UPDATE_DST; ++ /* write the first 4 bytes of the descriptor */ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE/4; ++ ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_ID) ++ { ++ ASSERT_COND(p_TmpData); ++ WRITE_UINT16(*(uint16_t*)p_TmpData, p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.id); ++ WRITE_UINT32(*p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase))); ++ p_TmpData += 2; ++ p_TmpHmct += HMCD_PTR_SIZE/4; ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_SRC) ++ { ++ WRITE_UINT32(*p_TmpHmct, p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.src); ++ p_TmpHmct += HMCD_IPV4_ADDR_SIZE/4; ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_DST) ++ { ++ WRITE_UINT32(*p_TmpHmct, p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.dst); ++ p_TmpHmct += HMCD_IPV4_ADDR_SIZE/4; ++ } ++ break; ++ ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6): ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_IPV6_UPDATE) << HMCD_OC_SHIFT; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_HL) ++ tmpReg |= HMCD_IPV6_UPDATE_HL; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_TC) ++ { ++ tmpReg |= HMCD_IPV6_UPDATE_TC; ++ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.trafficClass << HMCD_IPV6_UPDATE_TC_SHIFT; ++ } ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_SRC) ++ tmpReg |= HMCD_IPV6_UPDATE_SRC; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_DST) ++ tmpReg |= HMCD_IPV6_UPDATE_DST; ++ /* write the first 4 bytes of the descriptor */ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE/4; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_SRC) ++ for (i = 0 ; i < NET_HEADER_FIELD_IPv6_ADDR_SIZE ; i+=4) ++ { ++ WRITE_UINT32(*p_TmpHmct, *(uint32_t*)&p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.src[i]); ++ p_TmpHmct += HMCD_PTR_SIZE/4; ++ } ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_DST) ++ for (i = 0 ; i < NET_HEADER_FIELD_IPv6_ADDR_SIZE ; i+=4) ++ { ++ WRITE_UINT32(*p_TmpHmct, *(uint32_t*)&p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.dst[i]); ++ p_TmpHmct += HMCD_PTR_SIZE/4; ++ } ++ break; ++ ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP): ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates == HDR_MANIP_TCP_UDP_CHECKSUM) ++ { ++ /* we implement this case with the update-checksum descriptor */ ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_TCP_UDP_CHECKSUM) << HMCD_OC_SHIFT; ++ /* write the first 4 bytes of the descriptor */ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE/4; ++ } ++ else ++ { ++ /* we implement this case with the TCP/UDP update descriptor */ ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_TCP_UDP_UPDATE) << HMCD_OC_SHIFT; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_DST) ++ tmpReg |= HMCD_TCP_UDP_UPDATE_DST; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_SRC) ++ tmpReg |= HMCD_TCP_UDP_UPDATE_SRC; ++ /* write the first 4 bytes of the descriptor */ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE/4; ++ ++ tmpReg = 0; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_SRC) ++ tmpReg |= ((uint32_t)p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.src) << HMCD_TCP_UDP_UPDATE_SRC_SHIFT; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_DST) ++ tmpReg |= ((uint32_t)p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.dst); ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ p_TmpHmct += HMCD_PTR_SIZE/4; ++ } ++ break; ++ ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown fieldUpdateParams.type")); ++ } ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.custom) ++ { ++ switch (p_FmPcdManipParams->u.hdr.customParams.type) ++ { ++ case (e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE): ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_REPLACE_IP) << HMCD_OC_SHIFT; ++ ++ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.decTtlHl) ++ tmpReg |= HMCD_IP_REPLACE_TTL_HL; ++ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV4_BY_IPV6) ++ /* line commented out as it has no-side-effect ('0' value). */ ++ /*tmpReg |= HMCD_IP_REPLACE_REPLACE_IPV4*/; ++ else if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) ++ { ++ tmpReg |= HMCD_IP_REPLACE_REPLACE_IPV6; ++ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id) ++ tmpReg |= HMCD_IP_REPLACE_ID; ++ } ++ else ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("One flag out of HDR_MANIP_IP_REPLACE_IPV4, HDR_MANIP_IP_REPLACE_IPV6 - must be set.")); ++ ++ /* write the first 4 bytes of the descriptor */ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE/4; ++ ++ size = p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdrSize; ++ ASSERT_COND(p_TmpData); ++ Mem2IOCpy32(p_TmpData, p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdr, size); ++ tmpReg = (uint32_t)(size << HMCD_IP_REPLACE_L3HDRSIZE_SHIFT); ++ tmpReg |= (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase)); ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ p_TmpHmct += HMCD_PTR_SIZE/4; ++ p_TmpData += size; ++ ++ if ((p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) && ++ (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id)) ++ { ++ WRITE_UINT16(*(uint16_t*)p_TmpData, p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.id); ++ WRITE_UINT32(*p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase))); ++ p_TmpData += 2; ++ } ++ p_TmpHmct += HMCD_PTR_SIZE/4; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown customParams.type")); ++ } ++ } ++ ++ ++ /* If this node has a nextManip, and no parsing is required after it, the old table must be copied to the new table ++ the old table and should be freed */ ++ if (p_FmPcdManipParams->h_NextManip && ++ (MANIP_DONT_REPARSE(p_FmPcdManipParams->h_NextManip))) ++ { ++ if (new) ++ { ++ /* If this is the first time this manip is created we need to free unused memory. If it ++ * is a dynamic changes case, the memory used is either the CC shadow or the existing ++ * table - no allocation, no free */ ++ MANIP_UPDATE_UNIFIED_POSITION(p_FmPcdManipParams->h_NextManip); ++ ++ p_Manip->unifiedPosition = e_MANIP_UNIFIED_FIRST; ++ ++ /* The HMTD of the next Manip is never going to be used */ ++ if (((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->muramAllocate) ++ FM_MURAM_FreeMem(((t_FmPcd *)((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_FmPcd)->h_FmMuram, ((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad); ++ else ++ XX_Free(((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad); ++ ((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad = NULL; ++ ++ /* advance pointer */ ++ p_TmpHmct += MANIP_GET_HMCT_SIZE(p_FmPcdManipParams->h_NextManip)/4; ++ } ++ } ++ else ++ { ++ ASSERT_COND(p_Last); ++ /* set the "last" indication on the last command of the current table */ ++ WRITE_UINT32(*p_Last, GET_UINT32(*p_Last) | HMCD_LAST); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error CreateManipActionNew(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams) ++{ ++ t_FmPcdManip *p_CurManip; ++ t_Error err; ++ uint32_t nextSize = 0, totalSize; ++ uint16_t tmpReg; ++ uint8_t *p_OldHmct, *p_TmpHmctPtr, *p_TmpDataPtr; ++ ++ /* set Manip structure */ ++ if (p_FmPcdManipParams->h_NextManip) ++ { ++ if (MANIP_DONT_REPARSE(p_FmPcdManipParams->h_NextManip)) ++ nextSize = (uint32_t)(GetHmctSize(p_FmPcdManipParams->h_NextManip) + GetDataSize(p_FmPcdManipParams->h_NextManip)); ++ else ++ p_Manip->cascadedNext = TRUE; ++ } ++ p_Manip->dontParseAfterManip = p_FmPcdManipParams->u.hdr.dontParseAfterManip; ++ ++ /* Allocate new table */ ++ /* calculate table size according to manip parameters */ ++ err = CalculateTableSize(p_FmPcdManipParams, &p_Manip->tableSize, &p_Manip->dataSize); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ totalSize =(uint16_t)(p_Manip->tableSize + p_Manip->dataSize + nextSize); ++ ++ p_Manip->p_Hmct = (uint8_t*)FM_MURAM_AllocMem(((t_FmPcd *)p_Manip->h_FmPcd)->h_FmMuram, totalSize, 4); ++ if (!p_Manip->p_Hmct) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc failed")); ++ ++ if (p_Manip->dataSize) ++ p_Manip->p_Data = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct, (p_Manip->tableSize + nextSize)); ++ ++ /* update shadow size to allow runtime replacement of Header manipulation */ ++ /* The allocated shadow is divided as follows: ++ 0 . . . 16 . . . ++ -------------------------------- ++ | Shadow | Shadow HMTD | ++ | HMTD | Match Table | ++ | (16 bytes) | (maximal size) | ++ -------------------------------- ++ */ ++ ++ err = FmPcdUpdateCcShadow (p_Manip->h_FmPcd, (uint32_t)(totalSize + 16), (uint16_t)FM_PCD_CC_AD_TABLE_ALIGN); ++ if (err != E_OK) ++ { ++ FM_MURAM_FreeMem(p_Manip->h_FmPcd, p_Manip->p_Hmct); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for HdrManip node shadow")); ++ } ++ ++ ++ if (p_FmPcdManipParams->h_NextManip && ++ (MANIP_DONT_REPARSE(p_FmPcdManipParams->h_NextManip))) ++ { ++ p_OldHmct = (uint8_t *)GetManipInfo(p_FmPcdManipParams->h_NextManip, e_MANIP_HMCT); ++ p_CurManip = p_FmPcdManipParams->h_NextManip; ++ /* Run till the last Manip (which is the first to configure) */ ++ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) ++ p_CurManip = p_CurManip->h_NextManip; ++ ++ while (p_CurManip) ++ { ++ /* If this is a unified table, point to the part of the table ++ * which is the relative offset in HMCT. ++ */ ++ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct, ++ (p_Manip->tableSize + ++ (PTR_TO_UINT(p_CurManip->p_Hmct) - ++ PTR_TO_UINT(p_OldHmct)))); ++ if (p_CurManip->p_Data) ++ p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct, ++ (p_Manip->tableSize + ++ (PTR_TO_UINT(p_CurManip->p_Data) - ++ PTR_TO_UINT(p_OldHmct)))); ++ else ++ p_TmpDataPtr = NULL; ++ ++ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, p_TmpDataPtr, FALSE); ++ /* update old manip table pointer */ ++ MANIP_SET_HMCT_PTR(p_CurManip, p_TmpHmctPtr); ++ MANIP_SET_DATA_PTR(p_CurManip, p_TmpDataPtr); ++ ++ p_CurManip = p_CurManip->h_PrevManip; ++ } ++ /* We copied the HMCT to create a new large HMCT so we can free the old one */ ++ FM_MURAM_FreeMem(MANIP_GET_MURAM(p_FmPcdManipParams->h_NextManip), p_OldHmct); ++ } ++ ++ /* Fill table */ ++ err = BuildHmct(p_Manip, p_FmPcdManipParams, p_Manip->p_Hmct, p_Manip->p_Data, TRUE); ++ if (err) ++ { ++ FM_MURAM_FreeMem(p_Manip->h_FmPcd, p_Manip->p_Hmct); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ /* Build HMTD (table descriptor) */ ++ tmpReg = HMTD_CFG_TYPE; /* NADEN = 0 */ ++ /* add parseAfterManip */ ++ if (!p_Manip->dontParseAfterManip) ++ tmpReg |= HMTD_CFG_PRS_AFTER_HM; ++ /* create cascade */ ++ if (p_FmPcdManipParams->h_NextManip && ++ !MANIP_DONT_REPARSE(p_FmPcdManipParams->h_NextManip)) ++ { ++ /* indicate that there's another HM table descriptor */ ++ tmpReg |= HMTD_CFG_NEXT_AD_EN; ++ WRITE_UINT16(((t_Hmtd *)p_Manip->h_Ad)->nextAdIdx, ++ (uint16_t)((uint32_t)(XX_VirtToPhys(MANIP_GET_HMTD_PTR(p_FmPcdManipParams->h_NextManip)) - ++ (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase)) >> 4)); ++ } ++ ++ WRITE_UINT16(((t_Hmtd *)p_Manip->h_Ad)->cfg, tmpReg); ++ WRITE_UINT32(((t_Hmtd *)p_Manip->h_Ad)->hmcdBasePtr, ++ (uint32_t)(XX_VirtToPhys(p_Manip->p_Hmct) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase))); ++ ++ WRITE_UINT8(((t_Hmtd *)p_Manip->h_Ad)->opCode, HMAN_OC); ++ ++ return E_OK; ++} ++ ++static t_Error CreateManipActionShadow(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams) ++{ ++ uint8_t *p_WholeHmct, *p_TmpHmctPtr, newDataSize, *p_TmpDataPtr = NULL; ++ uint16_t newSize; ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; ++ t_Error err; ++ t_FmPcdManip *p_CurManip = p_Manip; ++ ++ err = CalculateTableSize(p_FmPcdManipParams, &newSize, &newDataSize); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ /* check coherency of new table parameters */ ++ if (newSize > p_Manip->tableSize) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration requires larger size than current one (command table).")); ++ if (newDataSize > p_Manip->dataSize) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration requires larger size than current one (data).")); ++ if (p_FmPcdManipParams->h_NextManip) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration can not contain h_NextManip.")); ++ if (MANIP_IS_UNIFIED(p_Manip) && (newSize != p_Manip->tableSize)) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration in a chained manipulation requires different size than current one.")); ++ if (p_Manip->dontParseAfterManip != p_FmPcdManipParams->u.hdr.dontParseAfterManip) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration differs in dontParseAfterManip value.")); ++ ++ p_Manip->tableSize = newSize; ++ p_Manip->dataSize = newDataSize; ++ ++ ++ /* Build the new table in the shadow */ ++ if (!MANIP_IS_UNIFIED(p_Manip)) ++ { ++ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, 16); ++ if (p_Manip->p_Data) ++ p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_TmpHmctPtr, ++ (PTR_TO_UINT(p_Manip->p_Data) - PTR_TO_UINT(p_Manip->p_Hmct))); ++ ++ BuildHmct(p_Manip, p_FmPcdManipParams, p_TmpHmctPtr, p_Manip->p_Data, FALSE); ++ } ++ else ++ { ++ p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT); ++ ASSERT_COND(p_WholeHmct); ++ ++ /* Run till the last Manip (which is the first to configure) */ ++ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) ++ p_CurManip = p_CurManip->h_NextManip; ++ ++ while (p_CurManip) ++ { ++ /* If this is a non-head node in a unified table, point to the part of the shadow ++ * which is the relative offset in HMCT. ++ * else, point to the beginning of the ++ * shadow table (we save 16 for the HMTD. ++ */ ++ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, ++ (16 + PTR_TO_UINT(p_CurManip->p_Hmct) - PTR_TO_UINT(p_WholeHmct))); ++ if (p_CurManip->p_Data) ++ p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, ++ (16 + PTR_TO_UINT(p_CurManip->p_Data) - PTR_TO_UINT(p_WholeHmct))); ++ ++ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, p_TmpDataPtr, FALSE); ++ p_CurManip = p_CurManip->h_PrevManip; ++ } ++ } ++ ++ return E_OK; ++} ++ ++static t_Error CreateManipActionBackToOrig(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams) ++{ ++ uint8_t *p_WholeHmct, *p_TmpHmctPtr, *p_TmpDataPtr; ++ t_FmPcdManip *p_CurManip = p_Manip; ++ ++ /* Build the new table in the shadow */ ++ if (!MANIP_IS_UNIFIED(p_Manip)) ++ BuildHmct(p_Manip, p_FmPcdManipParams, p_Manip->p_Hmct, p_Manip->p_Data, FALSE); ++ else ++ { ++ p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT); ++ ASSERT_COND(p_WholeHmct); ++ ++ /* Run till the last Manip (which is the first to configure) */ ++ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) ++ p_CurManip = p_CurManip->h_NextManip; ++ ++ while (p_CurManip) ++ { ++ /* If this is a unified table, point to the part of the table ++ * which is the relative offset in HMCT. ++ */ ++ p_TmpHmctPtr = p_CurManip->p_Hmct; /*- (uint32_t)p_WholeHmct*/ ++ p_TmpDataPtr = p_CurManip->p_Data; /*- (uint32_t)p_WholeHmct*/ ++ ++ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, p_TmpDataPtr, FALSE); ++ ++ p_CurManip = p_CurManip->h_PrevManip; ++ } ++ } ++ ++ return E_OK; ++} ++ ++static t_Error UpdateManipIc(t_Handle h_Manip, uint8_t icOffset) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ t_Handle p_Ad; ++ uint32_t tmpReg32 = 0; ++ SANITY_CHECK_RETURN_ERROR(h_Manip,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE); ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ if (p_Manip->updateParams & INTERNAL_CONTEXT_OFFSET) ++ { ++ tmpReg32 = *(uint32_t *)&((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets; ++ tmpReg32 |= (uint32_t)((uint32_t)icOffset << 16); ++ *(uint32_t *)&((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets = tmpReg32; ++ p_Manip->updateParams &= ~INTERNAL_CONTEXT_OFFSET; ++ p_Manip->icOffset = icOffset; ++ } ++ else ++ { ++ if (p_Manip->icOffset != icOffset) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("this manipulation was updated previously by different value");); ++ } ++ break; ++#ifdef FM_CAPWAP_SUPPORT ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ if (p_Manip->h_Frag) ++ { ++ if (p_Manip->updateParams & INTERNAL_CONTEXT_OFFSET) ++ { ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ tmpReg32 |= GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets); ++ tmpReg32 |= (uint32_t)((uint32_t)icOffset << 16); ++ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets, tmpReg32); ++ p_Manip->updateParams &= ~INTERNAL_CONTEXT_OFFSET; ++ p_Manip->icOffset = icOffset; ++ } ++ else ++ { ++ if (p_Manip->icOffset != icOffset) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("this manipulation was updated previousely by different value");); ++ } ++ } ++ break; ++#endif /* FM_CAPWAP_SUPPORT */ ++ } ++ ++ return E_OK; ++} ++ ++static t_Error UpdateInitMvIntFrameHeaderFromFrameToBufferPrefix(t_Handle h_FmPort, t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate) ++{ ++ ++ t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)h_Ad; ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ t_Error err; ++ uint32_t tmpReg32; ++ ++ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode & HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX), E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Manip->muramAllocate, E_INVALID_STATE); ++ ++ if (p_Manip->updateParams) ++ { ++ if ((!(p_Manip->updateParams & OFFSET_OF_PR)) || ++ (p_Manip->shadowUpdateParams & OFFSET_OF_PR)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); ++ ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_PSO; ++ fmPortGetSetCcParams.setCcParams.psoSize = 16; ++ ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Parser result offset wasn't configured previousely")); ++#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ++ ASSERT_COND(!(fmPortGetSetCcParams.getCcParams.prOffset % 16)); ++#endif ++ } ++ else if (validate) ++ { ++ if ((!(p_Manip->shadowUpdateParams & OFFSET_OF_PR)) || ++ (p_Manip->updateParams & OFFSET_OF_PR)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated")); ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_PSO; ++ fmPortGetSetCcParams.setCcParams.psoSize = 16; ++ ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Parser result offset wasn't configured previousely")); ++ ++ } ++ ++ ASSERT_COND(p_Ad); ++ ++ if (p_Manip->updateParams & OFFSET_OF_PR) ++ { ++ tmpReg32 = 0; ++ tmpReg32 |= fmPortGetSetCcParams.getCcParams.prOffset; ++ WRITE_UINT32(p_Ad->matchTblPtr, (GET_UINT32(p_Ad->matchTblPtr) | tmpReg32)); ++ p_Manip->updateParams &= ~OFFSET_OF_PR; ++ p_Manip->shadowUpdateParams |= OFFSET_OF_PR; ++ } ++ else if (validate) ++ { ++ tmpReg32 = GET_UINT32(p_Ad->matchTblPtr); ++ if ((uint8_t)tmpReg32 != fmPortGetSetCcParams.getCcParams.prOffset) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value");); ++ } ++ ++ return E_OK; ++} ++ ++#ifdef FM_CAPWAP_SUPPORT ++static t_Error UpdateModifyCapwapFragmenation(t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate,t_Handle h_FmTree) ++{ ++ t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)h_Ad; ++ t_FmPcdCcSavedManipParams *p_SavedManipParams = NULL; ++ uint32_t tmpReg32 = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->frag,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION) || (p_Manip->opcode == HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER)), E_INVALID_STATE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag; ++ ++ if (p_Manip->updateParams) ++ { ++ ++ if ((!(p_Manip->updateParams & OFFSET_OF_DATA)) || ++ ((p_Manip->shadowUpdateParams & OFFSET_OF_DATA))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); ++ p_SavedManipParams = FmPcdCcTreeGetSavedManipParams(h_FmTree); ++ if (!p_SavedManipParams) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("for this manipulation tree has to be configured previosely with this type")); ++ p_Manip->fragParams.dataOffset = p_SavedManipParams->capwapParams.dataOffset; ++ ++ tmpReg32 = GET_UINT32(p_Ad->pcAndOffsets); ++ tmpReg32 |= ((uint32_t)p_Manip->fragParams.dataOffset<< 16); ++ WRITE_UINT32(p_Ad->pcAndOffsets,tmpReg32); ++ ++ p_Manip->updateParams &= ~OFFSET_OF_DATA; ++ p_Manip->shadowUpdateParams |= OFFSET_OF_DATA; ++ } ++ else if (validate) ++ { ++ ++ p_SavedManipParams = FmPcdCcTreeGetSavedManipParams(h_FmTree); ++ if (!p_SavedManipParams) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("for this manipulation tree has to be configured previosely with this type")); ++ if (p_Manip->fragParams.dataOffset != p_SavedManipParams->capwapParams.dataOffset) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value")); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error UpdateInitCapwapFragmentation(t_Handle h_FmPort, ++ t_FmPcdManip *p_Manip, ++ t_Handle h_Ad, ++ bool validate, ++ t_Handle h_FmTree) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ t_Error err; ++ uint32_t tmpReg32 = 0; ++ t_FmPcdCcSavedManipParams *p_SavedManipParams; ++ ++ UNUSED(h_Ad); ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->frag,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION) || ++ (p_Manip->opcode == HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER)), E_INVALID_STATE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag; ++ ++ if (p_Manip->updateParams) ++ { ++ if ((!(p_Manip->updateParams & OFFSET_OF_DATA)) || ++ ((p_Manip->shadowUpdateParams & OFFSET_OF_DATA))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN | UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL; ++ /* For CAPWAP Rassembly used FMAN_CTRL2 hardcoded - so for fragmentation its better to use FMAN_CTRL1 */ ++ fmPortGetSetCcParams.setCcParams.orFmanCtrl = FPM_PORT_FM_CTL1; ++ ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Data offset wasn't configured previousely")); ++ ++ p_SavedManipParams = (t_FmPcdCcSavedManipParams *)XX_Malloc(sizeof(t_FmPcdCcSavedManipParams)); ++ p_SavedManipParams->capwapParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset; ++ ++#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ++ ASSERT_COND(!(p_SavedManipParams->capwapParams.dataOffset % 16)); ++#endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */ ++ ++ FmPcdCcTreeSetSavedManipParams(h_FmTree, (t_Handle)p_SavedManipParams); ++ } ++ else if (validate) ++ { ++ if ((!(p_Manip->shadowUpdateParams & OFFSET_OF_DATA)) || ++ ((p_Manip->updateParams & OFFSET_OF_DATA))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated")); ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN | UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL; ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Data offset wasn't configured previousely")); ++ } ++ ++ if (p_Manip->updateParams) ++ { ++ tmpReg32 = GET_UINT32(p_Ad->pcAndOffsets); ++ tmpReg32 |= ((uint32_t)fmPortGetSetCcParams.getCcParams.dataOffset<< 16); ++ WRITE_UINT32(p_Ad->pcAndOffsets,tmpReg32); ++ ++ p_Manip->updateParams &= ~OFFSET_OF_DATA; ++ p_Manip->shadowUpdateParams |= OFFSET_OF_DATA; ++ p_Manip->fragParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset; ++ } ++ else if (validate) ++ { ++ if (p_Manip->fragParams.dataOffset != fmPortGetSetCcParams.getCcParams.dataOffset) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value")); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error UpdateInitCapwapReasm(t_Handle h_FmPcd, ++ t_Handle h_FmPort, ++ t_FmPcdManip *p_Manip, ++ t_Handle h_Ad, ++ bool validate) ++{ ++ t_CapwapReasmPram *p_ReassmTbl; ++ t_Error err; ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ uint8_t i = 0; ++ uint16_t size; ++ uint32_t tmpReg32; ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdCcCapwapReassmTimeoutParams ccCapwapReassmTimeoutParams; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Manip->frag,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST), E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc,E_INVALID_HANDLE); ++ ++ if (p_Manip->h_FmPcd != h_FmPcd) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("handler of PCD previously was initiated by different value")); ++ ++ UNUSED(h_Ad); ++ ++ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); ++ p_ReassmTbl = (t_CapwapReasmPram *)p_Manip->h_Frag; ++ ++ if (p_Manip->updateParams) ++ { ++ if ((!(p_Manip->updateParams & NUM_OF_TASKS) && ++ !(p_Manip->updateParams & OFFSET_OF_DATA) && ++ !(p_Manip->updateParams & OFFSET_OF_PR) && ++ !(p_Manip->updateParams & HW_PORT_ID)) || ++ ((p_Manip->shadowUpdateParams & NUM_OF_TASKS) || ++ (p_Manip->shadowUpdateParams & OFFSET_OF_DATA) || (p_Manip->shadowUpdateParams & OFFSET_OF_PR) || ++ (p_Manip->shadowUpdateParams & HW_PORT_ID))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); ++ ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL; ++ ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (fmPortGetSetCcParams.getCcParams.type & NUM_OF_TASKS) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Num of tasks wasn't configured previousely")); ++ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previousely")); ++ if (fmPortGetSetCcParams.getCcParams.type & HW_PORT_ID) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("hwPortId wasn't updated")); ++#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ++ ASSERT_COND((fmPortGetSetCcParams.getCcParams.dataOffset % 16) == 0); ++#endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */ ++ } ++ else if (validate) ++ { ++ if ((!(p_Manip->shadowUpdateParams & NUM_OF_TASKS) && ++ !(p_Manip->shadowUpdateParams & OFFSET_OF_DATA) && ++ !(p_Manip->shadowUpdateParams & OFFSET_OF_PR) && ++ !(p_Manip->shadowUpdateParams & HW_PORT_ID)) && ++ ((p_Manip->updateParams & NUM_OF_TASKS) || ++ (p_Manip->updateParams & OFFSET_OF_DATA) || (p_Manip->updateParams & OFFSET_OF_PR) || ++ (p_Manip->updateParams & HW_PORT_ID))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated")); ++ ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL; ++ ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (fmPortGetSetCcParams.getCcParams.type & NUM_OF_TASKS) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("NumOfTasks wasn't configured previously")); ++ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previously")); ++ if (fmPortGetSetCcParams.getCcParams.type & HW_PORT_ID) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("hwPortId wasn't updated")); ++ } ++ ++ if (p_Manip->updateParams) ++ { ++ if (p_Manip->updateParams & NUM_OF_TASKS) ++ { ++ /*recommendation of Microcode team - (maxNumFramesInProcess * 2) */ ++ size = (uint16_t)(p_Manip->fragParams.maxNumFramesInProcess*2 + fmPortGetSetCcParams.getCcParams.numOfTasks); ++ if (size > 255) ++ RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("numOfOpenReassmEntries + numOfTasks per port can not be greater than 256")); ++ ++ p_Manip->fragParams.numOfTasks = fmPortGetSetCcParams.getCcParams.numOfTasks; ++ ++ /*p_ReassmFrmDescrIndxPoolTbl*/ ++ p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl = ++ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)(size + 1), ++ 4); ++ if (!p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly frame buffer index pool table")); ++ ++ IOMemSet32(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl, 0, (uint32_t)(size + 1)); ++ ++ for ( i = 0; i < size; i++) ++ WRITE_UINT8(*(uint8_t *)PTR_MOVE(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl, i), (uint8_t)(i+1)); ++ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl) - p_FmPcd->physicalMuramBase); ++ ++ WRITE_UINT32(p_ReassmTbl->reasmFrmDescIndexPoolTblPtr, tmpReg32); ++ ++ /*p_ReassmFrmDescrPoolTbl*/ ++ p_Manip->fragParams.p_ReassmFrmDescrPoolTbl = ++ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)((size + 1) * FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE), ++ 4); ++ ++ if (!p_Manip->fragParams.p_ReassmFrmDescrPoolTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly frame buffer pool table")); ++ ++ IOMemSet32(p_Manip->fragParams.p_ReassmFrmDescrPoolTbl, 0, (uint32_t)((size +1)* FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE)); ++ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_ReassmFrmDescrPoolTbl) - p_FmPcd->physicalMuramBase); ++ ++ WRITE_UINT32(p_ReassmTbl->reasmFrmDescPoolTblPtr, tmpReg32); ++ ++ /*p_TimeOutTbl*/ ++ ++ p_Manip->fragParams.p_TimeOutTbl = ++ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)((size + 1)* FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE), ++ 4); ++ ++ if (!p_Manip->fragParams.p_TimeOutTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly timeout table")); ++ ++ IOMemSet32(p_Manip->fragParams.p_TimeOutTbl, 0, (uint16_t)((size + 1)*FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE)); ++ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_TimeOutTbl) - p_FmPcd->physicalMuramBase); ++ WRITE_UINT32(p_ReassmTbl->timeOutTblPtr, tmpReg32); ++ ++ p_Manip->updateParams &= ~NUM_OF_TASKS; ++ p_Manip->shadowUpdateParams |= NUM_OF_TASKS; ++ } ++ ++ if (p_Manip->updateParams & OFFSET_OF_DATA) ++ { ++ p_Manip->fragParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset; ++ tmpReg32 = GET_UINT32(p_ReassmTbl->mode); ++ tmpReg32|= p_Manip->fragParams.dataOffset; ++ WRITE_UINT32(p_ReassmTbl->mode, tmpReg32); ++ p_Manip->updateParams &= ~OFFSET_OF_DATA; ++ p_Manip->shadowUpdateParams |= OFFSET_OF_DATA; ++ } ++ ++ if (!(fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR)) ++ { ++ p_Manip->fragParams.prOffset = fmPortGetSetCcParams.getCcParams.prOffset; ++ ++ tmpReg32 = GET_UINT32(p_ReassmTbl->mode); ++ tmpReg32|= FM_PCD_MANIP_CAPWAP_REASM_PR_COPY; ++ WRITE_UINT32(p_ReassmTbl->mode, tmpReg32); ++ ++ tmpReg32 = GET_UINT32(p_ReassmTbl->intStatsTblPtr); ++ tmpReg32 |= (uint32_t)p_Manip->fragParams.prOffset << 24; ++ WRITE_UINT32(p_ReassmTbl->intStatsTblPtr, tmpReg32); ++ p_Manip->updateParams &= ~OFFSET_OF_PR; ++ p_Manip->shadowUpdateParams |= OFFSET_OF_PR; ++ } ++ else ++ { ++ p_Manip->fragParams.prOffset = 0xff; ++ p_Manip->updateParams &= ~OFFSET_OF_PR; ++ p_Manip->shadowUpdateParams |= OFFSET_OF_PR; ++ } ++ ++ p_Manip->fragParams.hwPortId = fmPortGetSetCcParams.getCcParams.hardwarePortId; ++ p_Manip->updateParams &= ~HW_PORT_ID; ++ p_Manip->shadowUpdateParams |= HW_PORT_ID; ++ ++ /*timeout hc */ ++ ccCapwapReassmTimeoutParams.fqidForTimeOutFrames = p_Manip->fragParams.fqidForTimeOutFrames; ++ ccCapwapReassmTimeoutParams.portIdAndCapwapReassmTbl = (uint32_t)p_Manip->fragParams.hwPortId << 24; ++ ccCapwapReassmTimeoutParams.portIdAndCapwapReassmTbl |= (uint32_t)((XX_VirtToPhys(p_ReassmTbl) - p_FmPcd->physicalMuramBase)); ++ ccCapwapReassmTimeoutParams.timeoutRequestTime = (((uint32_t)1<fragParams.bitFor1Micro) * p_Manip->fragParams.timeoutRoutineRequestTime)/2; ++ return FmHcPcdCcCapwapTimeoutReassm(p_FmPcd->h_Hc,&ccCapwapReassmTimeoutParams); ++ } ++ ++ else if (validate) ++ { ++ if (fmPortGetSetCcParams.getCcParams.hardwarePortId != p_Manip->fragParams.hwPortId) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Reassembly manipulation previously was assigned to another port")); ++ if (fmPortGetSetCcParams.getCcParams.numOfTasks != p_Manip->fragParams.numOfTasks) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfTasks for this manipulation previously was defined by another value ")); ++ ++ ++ if (!(fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR)) ++ { ++ if (p_Manip->fragParams.prOffset != fmPortGetSetCcParams.getCcParams.prOffset) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value ")); ++ } ++ else ++ { ++ if (p_Manip->fragParams.prOffset != 0xff) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value ")); ++ } ++ if (fmPortGetSetCcParams.getCcParams.dataOffset != p_Manip->fragParams.dataOffset) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Data offset previously was defined by another value ")); ++ } ++ ++ return E_OK; ++} ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++t_Error FmPcdRegisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdCcIpReassmTimeoutParams ccIpReassmTimeoutParams = {0}; ++ t_Error err = E_OK; ++ uint8_t result; ++ uint32_t bitFor1Micro, tsbs, log2num; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(h_IpReasmCommonPramTbl); ++ ++ bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm); ++ bitFor1Micro = 32 - bitFor1Micro; ++ LOG2(FM_PCD_MANIP_IP_REASSM_TIMEOUT_THREAD_THRESH, log2num); ++ tsbs = bitFor1Micro - log2num; ++ ++ ccIpReassmTimeoutParams.iprcpt = (uint32_t)(XX_VirtToPhys(h_IpReasmCommonPramTbl) - p_FmPcd->physicalMuramBase); ++ ccIpReassmTimeoutParams.tsbs = (uint8_t)tsbs; ++ ccIpReassmTimeoutParams.activate = TRUE; ++ if ((err = FmHcPcdCcIpTimeoutReassm(p_FmPcd->h_Hc, &ccIpReassmTimeoutParams, &result)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ switch (result) ++ { ++ case (0): ++ return E_OK; ++ case (1): ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("failed to allocate TNUM")); ++ case (2): ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("failed to allocate internal buffer")); ++ case (3): ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("'Disable Timeout Task' with invalid IPRCPT")); ++ case (4): ++ RETURN_ERROR(MAJOR, E_FULL, ("too many timeout tasks")); ++ case (5): ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("invalid sub command")); ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ } ++ return E_OK; ++} ++ ++static t_Error CreateIpReassCommonTable(t_FmPcdManip *p_Manip) ++{ ++ uint32_t tmpReg32 = 0, i; ++ uint64_t tmpReg64, size; ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; ++ t_Error err = E_OK; ++ ++ /* Allocation of the IP Reassembly Common Parameters table. This table is located in the ++ MURAM. Its size is 64 bytes and its base address should be 8-byte aligned. ++ It contains parameters that are common to both the IPv4 reassembly function and IPv6 ++ reassembly function.*/ ++ p_Manip->ipReassmParams.p_IpReassCommonTbl = ++ (t_IpReassCommonTbl *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_SIZE, ++ FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_ALIGN); ++ ++ if (!p_Manip->ipReassmParams.p_IpReassCommonTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly common parameters table")); ++ ++ IOMemSet32(p_Manip->ipReassmParams.p_IpReassCommonTbl, 0, FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_SIZE); ++ ++ /* Setting the TimeOut Mode.*/ ++ tmpReg32 = 0; ++ if (p_Manip->ipReassmParams.timeOutMode == e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES) ++ tmpReg32 |= FM_PCD_MANIP_IP_REASM_TIME_OUT_BETWEEN_FRAMES; ++ ++ /* Setting TimeOut FQID - Frames that time out are enqueued to this FQID. ++ In order to cause TimeOut frames to be discarded, this queue should be configured accordingly*/ ++ tmpReg32 |= p_Manip->ipReassmParams.fqidForTimeOutFrames; ++ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->timeoutModeAndFqid, tmpReg32); ++ ++ /* Calculation the size of IP Reassembly Frame Descriptor - number of frames that are allowed to be reassembled simultaneously + 129.*/ ++ size = p_Manip->ipReassmParams.maxNumFramesInProcess + 129; ++ ++ /*Allocation of IP Reassembly Frame Descriptor Indexes Pool - This pool resides in the MURAM */ ++ p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr = ++ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)(size * 2), ++ 256)); ++ if (!p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly frame descriptor indexes pool")); ++ ++ IOMemSet32(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr), 0, (uint32_t)(size * 2)); ++ ++ /* The entries in IP Reassembly Frame Descriptor Indexes Pool contains indexes starting with 1 up to ++ the maximum number of frames that are allowed to be reassembled simultaneously + 128. ++ The last entry in this pool must contain the index zero*/ ++ for (i=0; i<(size-1); i++) ++ WRITE_UINT16(*(uint16_t *)PTR_MOVE(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr), (i<<1)), ++ (uint16_t)(i+1)); ++ ++ /* Sets the IP Reassembly Frame Descriptor Indexes Pool offset from MURAM */ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr)) - p_FmPcd->physicalMuramBase); ++ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->reassFrmDescIndexPoolTblPtr, tmpReg32); ++ ++ /* Allocation of the Reassembly Frame Descriptors Pool - This pool resides in external memory. ++ The number of entries in this pool should be equal to the number of entries in IP Reassembly Frame Descriptor Indexes Pool.*/ ++ p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr = ++ PTR_TO_UINT(XX_MallocSmart((uint32_t)(size * 64), p_Manip->ipReassmParams.dataMemId, 64)); ++ ++ if (!p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED")); ++ ++ IOMemSet32(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr), 0, (uint32_t)(size * 64)); ++ ++ /* Sets the Reassembly Frame Descriptors Pool and liodn offset*/ ++ tmpReg64 = (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr))); ++ tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT); ++ tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT); ++ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->liodnAndReassFrmDescPoolPtrHi, (uint32_t)(tmpReg64 >> 32)); ++ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->reassFrmDescPoolPtrLow, (uint32_t)tmpReg64); ++ ++ /*Allocation of the TimeOut table - This table resides in the MURAM. ++ The number of entries in this table is identical to the number of entries in the Reassembly Frame Descriptors Pool*/ ++ p_Manip->ipReassmParams.timeOutTblAddr = ++ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)(size * 8),8)); ++ ++ if (!p_Manip->ipReassmParams.timeOutTblAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly timeout table")); ++ ++ IOMemSet32(UINT_TO_PTR(p_Manip->ipReassmParams.timeOutTblAddr), 0, (uint16_t)(size * 8)); ++ ++ /* Sets the TimeOut table offset from MURAM */ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.timeOutTblAddr)) - p_FmPcd->physicalMuramBase); ++ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->timeOutTblPtr, tmpReg32); ++ ++ /* Sets the Expiration Delay */ ++ tmpReg32 = 0; ++ tmpReg32 |= (((uint32_t)(1 << FmGetTimeStampScale(p_FmPcd->h_Fm))) * p_Manip->ipReassmParams.timeoutThresholdForReassmProcess); ++ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->expirationDelay, tmpReg32); ++ ++ err = FmPcdRegisterReassmPort(p_FmPcd, p_Manip->ipReassmParams.p_IpReassCommonTbl); ++ if (err != E_OK) ++ { ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.p_IpReassCommonTbl); ++ RETURN_ERROR(MAJOR, err, ("port registration")); ++ } ++ ++ return err; ++} ++ ++static t_Error CreateIpReassTable(t_FmPcdManip *p_Manip, bool ipv4) ++{ ++ t_FmPcd *p_FmPcd = p_Manip->h_FmPcd; ++ uint32_t tmpReg32, autoLearnHashTblSize; ++ uint32_t numOfWays, setSize, setSizeCode, keySize; ++ uint32_t waySize, numOfSets, numOfEntries; ++ uint64_t tmpReg64; ++ uint16_t minFragSize; ++ uintptr_t *p_AutoLearnHashTblAddr, *p_AutoLearnSetLockTblAddr; ++ t_IpReassTbl **p_IpReassTbl; ++ ++ if (ipv4) ++ { ++ p_IpReassTbl = &p_Manip->ipReassmParams.p_Ipv4ReassTbl; ++ p_AutoLearnHashTblAddr = &p_Manip->ipReassmParams.ipv4AutoLearnHashTblAddr; ++ p_AutoLearnSetLockTblAddr = &p_Manip->ipReassmParams.ipv4AutoLearnSetLockTblAddr; ++ minFragSize = p_Manip->ipReassmParams.minFragSize[0]; ++ numOfWays = p_Manip->ipReassmParams.numOfFramesPerHashEntry[0]; ++ keySize = 4 + 4 + 1 + 2; /* 3-tuple + IP-Id */ ++ } ++ else ++ { ++ p_IpReassTbl = &p_Manip->ipReassmParams.p_Ipv6ReassTbl; ++ p_AutoLearnHashTblAddr = &p_Manip->ipReassmParams.ipv6AutoLearnHashTblAddr; ++ p_AutoLearnSetLockTblAddr = &p_Manip->ipReassmParams.ipv6AutoLearnSetLockTblAddr; ++ minFragSize = p_Manip->ipReassmParams.minFragSize[1]; ++ numOfWays = p_Manip->ipReassmParams.numOfFramesPerHashEntry[1]; ++ keySize = 16 + 16 + 4; /* 2-tuple + IP-Id */ ++ if (numOfWays > e_FM_PCD_MANIP_SIX_WAYS_HASH) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("num of ways")); ++ } ++ keySize += 2; /* 2 bytes reserved for RFDIndex */ ++#if (DPAA_VERSION >= 11) ++ keySize += 2; /* 2 bytes reserved */ ++#endif /* (DPAA_VERSION >= 11) */ ++ waySize = ROUND_UP(keySize, 8); ++ ++ /* Allocates the IP Reassembly Parameters Table - This table is located in the MURAM.*/ ++ *p_IpReassTbl = (t_IpReassTbl *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ FM_PCD_MANIP_IP_REASM_TABLE_SIZE, ++ FM_PCD_MANIP_IP_REASM_TABLE_ALIGN); ++ if (!*p_IpReassTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly IPv4/IPv6 specific parameters table")); ++ memset(*p_IpReassTbl, 0, sizeof(t_IpReassTbl)); ++ ++ /* Sets the IP Reassembly common Parameters table offset from MURAM in the IP Reassembly Table descriptor*/ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->ipReassmParams.p_IpReassCommonTbl) - p_FmPcd->physicalMuramBase); ++ WRITE_UINT32((*p_IpReassTbl)->ipReassCommonPrmTblPtr, tmpReg32); ++ ++ /* Calculate set size (set size is rounded-up to next power of 2) */ ++ NEXT_POWER_OF_2(numOfWays * waySize, setSize); ++ ++ /* Get set size code */ ++ LOG2(setSize, setSizeCode); ++ ++ /* Sets ways number and set size code */ ++ WRITE_UINT16((*p_IpReassTbl)->waysNumAndSetSize, (uint16_t)((numOfWays << 8) | setSizeCode)); ++ ++ /* It is recommended that the total number of entries in this table ++ (number of sets * number of ways) will be twice the number of frames that ++ are expected to be reassembled simultaneously.*/ ++ numOfEntries = (uint32_t)(p_Manip->ipReassmParams.maxNumFramesInProcess * 2); ++ ++ /* sets number calculation - number of entries = number of sets * number of ways */ ++ numOfSets = numOfEntries / numOfWays; ++ ++ /* Sets AutoLearnHashKeyMask*/ ++ NEXT_POWER_OF_2(numOfSets, numOfSets); ++ ++ WRITE_UINT16((*p_IpReassTbl)->autoLearnHashKeyMask, (uint16_t)(numOfSets - 1)); ++ ++ /* Allocation of IP Reassembly Automatic Learning Hash Table - This table resides in external memory. ++ The size of this table is determined by the number of sets and the set size. ++ Table size = set size * number of sets ++ This table base address should be aligned to SetSize.*/ ++ autoLearnHashTblSize = numOfSets * setSize; ++ ++ *p_AutoLearnHashTblAddr = PTR_TO_UINT(XX_MallocSmart(autoLearnHashTblSize, p_Manip->ipReassmParams.dataMemId, setSize)); ++ if (!*p_AutoLearnHashTblAddr) ++ { ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, *p_IpReassTbl); ++ *p_IpReassTbl = NULL; ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED")); ++ } ++ IOMemSet32(UINT_TO_PTR(*p_AutoLearnHashTblAddr), 0, autoLearnHashTblSize); ++ ++ /* Sets the IP Reassembly Automatic Learning Hash Table and liodn offset */ ++ tmpReg64 = ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT); ++ tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT); ++ tmpReg64 |= XX_VirtToPhys(UINT_TO_PTR(*p_AutoLearnHashTblAddr)); ++ WRITE_UINT32((*p_IpReassTbl)->liodnAlAndAutoLearnHashTblPtrHi, (uint32_t)(tmpReg64 >> 32)); ++ WRITE_UINT32((*p_IpReassTbl)->autoLearnHashTblPtrLow, (uint32_t)tmpReg64); ++ ++ /* Allocation of the Set Lock table - This table resides in external memory ++ The size of this table is (number of sets in the IP Reassembly Automatic Learning Hash table)*4 bytes. ++ This table resides in external memory and its base address should be 4-byte aligned */ ++ *p_AutoLearnSetLockTblAddr = PTR_TO_UINT(XX_MallocSmart((uint32_t)(numOfSets * 4), p_Manip->ipReassmParams.dataMemId, 4)); ++ if (!*p_AutoLearnSetLockTblAddr) ++ { ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, *p_IpReassTbl); ++ *p_IpReassTbl = NULL; ++ XX_FreeSmart(UINT_TO_PTR(*p_AutoLearnHashTblAddr)); ++ *p_AutoLearnHashTblAddr = 0; ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED")); ++ } ++ IOMemSet32(UINT_TO_PTR(*p_AutoLearnSetLockTblAddr), 0, (numOfSets * 4)); ++ ++ /* sets Set Lock table pointer and liodn offset*/ ++ tmpReg64 = ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT); ++ tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT); ++ tmpReg64 |= XX_VirtToPhys(UINT_TO_PTR(*p_AutoLearnSetLockTblAddr)); ++ WRITE_UINT32((*p_IpReassTbl)->liodnSlAndAutoLearnSetLockTblPtrHi, (uint32_t)(tmpReg64 >> 32)); ++ WRITE_UINT32((*p_IpReassTbl)->autoLearnSetLockTblPtrLow, (uint32_t)tmpReg64); ++ ++ /* Sets user's requested minimum fragment size (in Bytes) for First/Middle fragment */ ++ WRITE_UINT16((*p_IpReassTbl)->minFragSize, minFragSize); ++ ++ return E_OK; ++} ++ ++static t_Error UpdateInitIpReasm(t_Handle h_FmPcd, ++ t_Handle h_PcdParams, ++ t_Handle h_FmPort, ++ t_FmPcdManip *p_Manip, ++ t_Handle h_Ad, ++ bool validate) ++{ ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ uint32_t tmpReg32; ++ t_Error err; ++ t_FmPortPcdParams *p_PcdParams = (t_FmPortPcdParams *)h_PcdParams; ++#if (DPAA_VERSION >= 11) ++ uint8_t *p_Ptr; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Manip->frag, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_IP_REASSEMBLY), E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Manip->updateParams || h_PcdParams, E_INVALID_HANDLE); ++ ++ UNUSED(h_Ad); ++ ++ if (!p_Manip->updateParams) ++ return E_OK; ++ ++ if (p_Manip->h_FmPcd != h_FmPcd) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("handler of PCD previously was initiated by different value")); ++ ++ if (p_Manip->updateParams) ++ { ++ if ((!(p_Manip->updateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS))) || ++ ((p_Manip->shadowUpdateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS)))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); ++ ++ fmPortGetSetCcParams.setCcParams.type = 0; ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams; ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (fmPortGetSetCcParams.getCcParams.type & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previously")); ++ } ++ else if (validate) ++ { ++ if ((!(p_Manip->shadowUpdateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS))) || ++ ((p_Manip->updateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS)))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated")); ++ ++ fmPortGetSetCcParams.setCcParams.type = 0; ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams; ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (fmPortGetSetCcParams.getCcParams.type & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previously")); ++ } ++ ++ if (p_Manip->updateParams) ++ { ++ if (p_Manip->updateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS)) ++ { ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint8_t *p_Ptr, i, totalNumOfTnums; ++ ++ totalNumOfTnums = (uint8_t)(fmPortGetSetCcParams.getCcParams.numOfTasks + ++ fmPortGetSetCcParams.getCcParams.numOfExtraTasks); ++ ++ p_Manip->ipReassmParams.internalBufferPoolAddr = ++ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)(totalNumOfTnums * BMI_FIFO_UNITS), ++ BMI_FIFO_UNITS)); ++ if (!p_Manip->ipReassmParams.internalBufferPoolAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly internal buffers pool")); ++ IOMemSet32(UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolAddr), ++ 0, ++ (uint32_t)(totalNumOfTnums * BMI_FIFO_UNITS)); ++ ++ p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr = ++ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)(5 + totalNumOfTnums), ++ 4)); ++ if (!p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly internal buffers management")); ++ ++ p_Ptr = (uint8_t*)UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr); ++ WRITE_UINT32(*(uint32_t*)p_Ptr, (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolAddr)) - p_FmPcd->physicalMuramBase)); ++ for (i=0, p_Ptr += 4; i < totalNumOfTnums; i++, p_Ptr++) ++ WRITE_UINT8(*p_Ptr, i); ++ WRITE_UINT8(*p_Ptr, 0xFF); ++ ++ tmpReg32 = (4 << FM_PCD_MANIP_IP_REASM_COMMON_INT_BUFFER_IDX_SHIFT) | ++ ((uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr)) - p_FmPcd->physicalMuramBase)); ++ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->internalBufferManagement, tmpReg32); ++ ++ p_Manip->updateParams &= ~(NUM_OF_TASKS | NUM_OF_EXTRA_TASKS); ++ p_Manip->shadowUpdateParams |= (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS); ++ } ++ } ++ ++ if (p_Manip->ipReassmParams.h_Ipv4Scheme) ++ { ++ p_PcdParams->p_KgParams->h_Schemes[p_PcdParams->p_KgParams->numOfSchemes] = p_Manip->ipReassmParams.h_Ipv4Scheme; ++ p_PcdParams->p_KgParams->numOfSchemes++; ++ } ++ if (p_Manip->ipReassmParams.h_Ipv6Scheme) ++ { ++ p_PcdParams->p_KgParams->h_Schemes[p_PcdParams->p_KgParams->numOfSchemes] = p_Manip->ipReassmParams.h_Ipv6Scheme; ++ p_PcdParams->p_KgParams->numOfSchemes++; ++ } ++ ++#if (DPAA_VERSION >= 11) ++ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); ++ fmPortGetSetCcParams.setCcParams.type = 0; ++ fmPortGetSetCcParams.getCcParams.type = FM_REV; ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (fmPortGetSetCcParams.getCcParams.revInfo.majorRev >= 6) ++ { ++ if ((err = FmPortSetGprFunc(h_FmPort, e_FM_PORT_GPR_MURAM_PAGE, (void**)&p_Ptr)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ tmpReg32 = NIA_ENG_KG; ++ if (p_Manip->ipReassmParams.h_Ipv4Scheme) ++ { ++ tmpReg32 |= NIA_KG_DIRECT; ++ tmpReg32 |= NIA_KG_CC_EN; ++ tmpReg32 |= FmPcdKgGetSchemeId(p_Manip->ipReassmParams.h_Ipv4Scheme); ++ WRITE_UINT32(*(uint32_t*)PTR_MOVE(p_Ptr, NIA_IPR_DIRECT_SCHEME_IPV4_OFFSET), tmpReg32); ++ } ++ if (p_Manip->ipReassmParams.h_Ipv6Scheme) ++ { ++ tmpReg32 &= ~NIA_AC_MASK; ++ tmpReg32 |= NIA_KG_DIRECT; ++ tmpReg32 |= NIA_KG_CC_EN; ++ tmpReg32 |= FmPcdKgGetSchemeId(p_Manip->ipReassmParams.h_Ipv6Scheme); ++ WRITE_UINT32(*(uint32_t*)PTR_MOVE(p_Ptr, NIA_IPR_DIRECT_SCHEME_IPV6_OFFSET), tmpReg32); ++ } ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ return E_OK; ++} ++ ++#if (DPAA_VERSION == 10) ++static t_Error FmPcdFragHcScratchPoolFill(t_Handle h_FmPcd, uint8_t scratchBpid) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdCcFragScratchPoolCmdParams fmPcdCcFragScratchPoolCmdParams; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ memset(&fmPcdCcFragScratchPoolCmdParams, 0, sizeof(t_FmPcdCcFragScratchPoolCmdParams)); ++ ++ fmPcdCcFragScratchPoolCmdParams.numOfBuffers = NUM_OF_SCRATCH_POOL_BUFFERS; ++ fmPcdCcFragScratchPoolCmdParams.bufferPoolId = scratchBpid; ++ if ((err = FmHcPcdCcIpFragScratchPollCmd(p_FmPcd->h_Hc, TRUE, &fmPcdCcFragScratchPoolCmdParams)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (fmPcdCcFragScratchPoolCmdParams.numOfBuffers != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Fill scratch pool failed," ++ "Failed to release %d buffers to the BM (missing FBPRs)", ++ fmPcdCcFragScratchPoolCmdParams.numOfBuffers)); ++ ++ return E_OK; ++} ++ ++static t_Error FmPcdFragHcScratchPoolEmpty(t_Handle h_FmPcd, uint8_t scratchBpid) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdCcFragScratchPoolCmdParams fmPcdCcFragScratchPoolCmdParams; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ memset(&fmPcdCcFragScratchPoolCmdParams, 0, sizeof(t_FmPcdCcFragScratchPoolCmdParams)); ++ ++ fmPcdCcFragScratchPoolCmdParams.bufferPoolId = scratchBpid; ++ if ((err = FmHcPcdCcIpFragScratchPollCmd(p_FmPcd->h_Hc, FALSE, &fmPcdCcFragScratchPoolCmdParams)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++#endif /* (DPAA_VERSION == 10) */ ++ ++static void ReleaseManipHandler(t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd) ++{ ++ if (p_Manip->h_Ad) ++ { ++ if (p_Manip->muramAllocate) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->h_Ad); ++ else ++ XX_Free(p_Manip->h_Ad); ++ p_Manip->h_Ad = NULL; ++ } ++ if (p_Manip->p_Template) ++ { ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->p_Template); ++ p_Manip->p_Template = NULL; ++ } ++ if (p_Manip->h_Frag) ++ { ++ if (p_Manip->fragParams.p_AutoLearnHashTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_AutoLearnHashTbl); ++ if (p_Manip->fragParams.p_ReassmFrmDescrPoolTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_ReassmFrmDescrPoolTbl); ++ if (p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl); ++ if (p_Manip->fragParams.p_TimeOutTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_TimeOutTbl); ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->h_Frag); ++ ++ } ++ if (p_Manip->frag) ++ { ++ if (p_Manip->ipFragParams.p_Frag) ++ { ++#if (DPAA_VERSION == 10) ++ FmPcdFragHcScratchPoolEmpty((t_Handle)p_FmPcd, p_Manip->ipFragParams.scratchBpid); ++#endif /* (DPAA_VERSION == 10) */ ++ ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipFragParams.p_Frag); ++ } ++ } ++ else if (p_Manip->reassm) ++ { ++ FmPcdUnregisterReassmPort(p_FmPcd, p_Manip->ipReassmParams.p_IpReassCommonTbl); ++ ++ if (p_Manip->ipReassmParams.timeOutTblAddr) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->ipReassmParams.timeOutTblAddr)); ++ if (p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr) ++ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr)); ++ ++ if (p_Manip->ipReassmParams.ipv4AutoLearnHashTblAddr) ++ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.ipv4AutoLearnHashTblAddr)); ++ if (p_Manip->ipReassmParams.ipv6AutoLearnHashTblAddr) ++ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.ipv6AutoLearnHashTblAddr)); ++ if (p_Manip->ipReassmParams.ipv4AutoLearnSetLockTblAddr) ++ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.ipv4AutoLearnSetLockTblAddr)); ++ if (p_Manip->ipReassmParams.ipv6AutoLearnSetLockTblAddr) ++ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.ipv6AutoLearnSetLockTblAddr)); ++ if (p_Manip->ipReassmParams.p_Ipv4ReassTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.p_Ipv4ReassTbl); ++ if (p_Manip->ipReassmParams.p_Ipv6ReassTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.p_Ipv6ReassTbl); ++ if (p_Manip->ipReassmParams.p_IpReassCommonTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.p_IpReassCommonTbl); ++ if (p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr)); ++ if (p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr)); ++ if (p_Manip->ipReassmParams.internalBufferPoolAddr) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolAddr)); ++ ++ if (p_Manip->ipReassmParams.h_Ipv6Ad) ++ XX_FreeSmart(p_Manip->ipReassmParams.h_Ipv6Ad); ++ if (p_Manip->ipReassmParams.h_Ipv4Ad) ++ XX_FreeSmart(p_Manip->ipReassmParams.h_Ipv4Ad); ++ } ++ ++ if (p_Manip->p_StatsTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->p_StatsTbl); ++} ++ ++#ifdef FM_CAPWAP_SUPPORT ++static t_Error CheckManipParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_ManipParams) ++{ ++ if (p_ManipParams->u.hdr.rmv) ++ { ++ switch (p_ManipParams->u.hdr.rmvParams.type) ++ { ++ case (e_FM_PCD_MANIP_RMV_BY_HDR): ++ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.type) ++ { ++ case (e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START) : ++ if (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.include) ++ { ++ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.hdrInfo.hdr) ++ { ++ case (HEADER_TYPE_CAPWAP_DTLS) : ++ p_Manip->opcode = HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST; ++ p_Manip->muramAllocate = TRUE; ++ if (p_ManipParams->u.hdr.insrt) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for CAPWAP_DTLS_HDR remove can not be insrt manipualtion after")); ++ if (p_ManipParams->fragOrReasm) ++ { ++ if (!p_ManipParams->fragOrReasmParams.frag) ++ { ++ switch (p_ManipParams->fragOrReasmParams.hdr) ++ { ++ case (HEADER_TYPE_CAPWAP): ++ p_Manip->opcode = HMAN_OC_CAPWAP_REASSEMBLY; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("unsupported header for Reassembly")); ++ } ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for this type of manipulation frag can not be TRUE")); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("non valid net header of remove location")); ++ } ++ } ++ else ++ { ++ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.hdrInfo.hdr) ++ { ++ case (HEADER_TYPE_CAPWAP_DTLS) : ++ case (HEADER_TYPE_CAPWAP) : ++ if (p_ManipParams->fragOrReasm || p_ManipParams->u.hdr.insrt) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for the type of remove e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_TILL_CAPWAP can not be insert or fragOrReasm TRUE")); ++ p_Manip->opcode = HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR; ++ p_Manip->muramAllocate = TRUE; ++ p_ManipParams->u.hdr.insrt = TRUE; //internal frame header ++ break; ++ default : ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); ++ } ++ } ++ break; ++ default : ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); ++ } ++ } ++ else if (p_ManipParams->u.hdr.insrt) ++ { ++ switch (p_ManipParams->u.hdr.insrtParams.type) ++ { ++ case (e_FM_PCD_MANIP_INSRT_BY_TEMPLATE) : ++ ++ p_Manip->opcode = HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER; ++ p_Manip->muramAllocate = FALSE; ++ if (p_ManipParams->fragOrReasm) ++ { ++ if (p_ManipParams->fragOrReasmParams.frag) ++ { ++ switch (p_ManipParams->fragOrReasmParams.hdr) ++ { ++ case (HEADER_TYPE_CAPWAP): ++ p_Manip->opcode = HMAN_OC_CAPWAP_FRAGMENTATION; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid header for fragmentation")); ++ } ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_STATE,("can not reach this point")); ++ } ++ break; ++ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for only isert manipulation unsupported type")); ++ } ++ } ++ else if (p_ManipParams->fragOrReasm) ++ { ++ if (p_ManipParams->fragOrReasmParams.frag) ++ { ++ switch (p_ManipParams->fragOrReasmParams.hdr) ++ { ++ case (HEADER_TYPE_CAPWAP): ++ p_Manip->opcode = HMAN_OC_CAPWAP_FRAGMENTATION; ++ p_Manip->muramAllocate = FALSE; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported header for fragmentation")); ++ } ++ } ++ else ++ { ++ switch (p_ManipParams->fragOrReasmParams.hdr) ++ { ++ case (HEADER_TYPE_CAPWAP): ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Reassembly has to be with additional operation - rmv = TRUE, type of remove - e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_INCLUDE_SPECIFIC_LOCATION,type = e_FM_PCD_MANIP_LOC_BY_HDR, hdr = HEADER_TYPE_CAPWAP_DTLS")); ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported header for reassembly")); ++ } ++ } ++ ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("User didn't ask for any manipulation")); ++ ++ p_Manip->insrt = p_ManipParams->u.hdr.insrt; ++ p_Manip->rmv = p_ManipParams->u.hdr.rmv; ++ ++ return E_OK; ++} ++ ++#else /* not FM_CAPWAP_SUPPORT */ ++static t_Error CheckManipParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_ManipParams) ++{ ++ switch (p_ManipParams->type) ++ { ++ case e_FM_PCD_MANIP_HDR : ++ /* Check that next-manip is not already used */ ++ if (p_ManipParams->h_NextManip) ++ { ++ if (!MANIP_IS_FIRST(p_ManipParams->h_NextManip)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("h_NextManip is already a part of another chain")); ++ if (MANIP_GET_TYPE(p_ManipParams->h_NextManip) != e_FM_PCD_MANIP_HDR) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("For a Header Manipulation node - no support of h_NextManip of type other than Header Manipulation.")); ++ } ++ ++ if (p_ManipParams->u.hdr.rmv) ++ { ++ switch (p_ManipParams->u.hdr.rmvParams.type) ++ { ++ case (e_FM_PCD_MANIP_RMV_BY_HDR): ++ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.type) ++ { ++ case (e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2) : ++ p_Manip->opcode = HMAN_OC; ++ p_Manip->muramAllocate = TRUE; ++ break; ++ default : ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); ++ } ++ break; ++ case (e_FM_PCD_MANIP_RMV_GENERIC): ++ p_Manip->opcode = HMAN_OC; ++ p_Manip->muramAllocate = TRUE; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); ++ } ++ p_Manip->rmv = TRUE; ++ } ++ else if (p_ManipParams->u.hdr.insrt) ++ { ++ switch (p_ManipParams->u.hdr.insrtParams.type) ++ { ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR) : ++ case (e_FM_PCD_MANIP_INSRT_GENERIC): ++ p_Manip->opcode = HMAN_OC; ++ p_Manip->muramAllocate = TRUE; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for only isert manipulation unsupported type")); ++ } ++ p_Manip->insrt = TRUE; ++ } ++ else if (p_ManipParams->u.hdr.fieldUpdate) ++ { ++ /* Check parameters */ ++ if (p_ManipParams->u.hdr.fieldUpdateParams.type == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN) ++ { ++ if ((p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI) ++ && (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.vpri > 7)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("vpri should get values of 0-7 ")); ++ if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN) ++ { ++ int i; ++ ++ if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.vpriDefVal > 7) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("vpriDefVal should get values of 0-7 ")); ++ for (i = 0 ; i < FM_PCD_MANIP_DSCP_TO_VLAN_TRANS ; i++) ++ if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.dscpToVpriTable[i] & 0xf0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dscpToVpriTabl value out of range (0-15)")); ++ } ++ ++ } ++ ++ p_Manip->opcode = HMAN_OC; ++ p_Manip->muramAllocate = TRUE; ++ p_Manip->fieldUpdate = TRUE; ++ } ++ else if (p_ManipParams->u.hdr.custom) ++ { ++ p_Manip->opcode = HMAN_OC; ++ p_Manip->muramAllocate = TRUE; ++ p_Manip->custom = TRUE; ++ } ++ break; ++ case e_FM_PCD_MANIP_REASSEM : ++ if (p_ManipParams->h_NextManip) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("next manip with reassembly")); ++ switch (p_ManipParams->u.reassem.hdr) ++ { ++ case (HEADER_TYPE_IPv4): ++ p_Manip->ipReassmParams.hdr = HEADER_TYPE_IPv4; ++ break; ++ case (HEADER_TYPE_IPv6): ++ p_Manip->ipReassmParams.hdr = HEADER_TYPE_IPv6; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("header for reassembly")); ++ } ++ p_Manip->opcode = HMAN_OC_IP_REASSEMBLY; ++ break; ++ case e_FM_PCD_MANIP_FRAG : ++ if (p_ManipParams->h_NextManip) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("next manip with fragmentation")); ++ switch (p_ManipParams->u.frag.hdr) ++ { ++ case (HEADER_TYPE_IPv4): ++ case (HEADER_TYPE_IPv6): ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("header for fragmentation")); ++ } ++ p_Manip->opcode = HMAN_OC_IP_FRAGMENTATION; ++ p_Manip->muramAllocate = TRUE; ++ break; ++ case e_FM_PCD_MANIP_SPECIAL_OFFLOAD : ++ switch (p_ManipParams->u.specialOffload.type) ++ { ++ case (e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC): ++ p_Manip->opcode = HMAN_OC_IPSEC_MANIP; ++ p_Manip->muramAllocate = TRUE; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("special offload type")); ++ } ++ break; ++ default : ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("manip type")); ++ } ++ ++ return E_OK; ++} ++#endif /* not FM_CAPWAP_SUPPORT */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++static t_Error UpdateIndxStats(t_Handle h_FmPcd, ++ t_Handle h_FmPort, ++ t_FmPcdManip *p_Manip) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint32_t tmpReg32 = 0; ++ t_AdOfTypeContLookup *p_Ad; ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ if (p_Manip->h_FmPcd != h_FmPcd) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("handler of PCD previously was initiated by different value")); ++ ++ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); ++ ++ if (!p_Manip->p_StatsTbl) ++ { ++ ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_CC; ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ tmpReg32 = GET_UINT32(p_Ad->ccAdBase); ++ ++ p_Manip->p_StatsTbl = ++ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)p_Manip->owner * FM_PCD_MANIP_INDEXED_STATS_ENTRY_SIZE, ++ 4); ++ if (!p_Manip->p_StatsTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Manipulation indexed statistics table")); ++ ++ IOMemSet32(p_Manip->p_StatsTbl, 0, (uint32_t)(p_Manip->owner * 4)); ++ ++ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->p_StatsTbl) - p_FmPcd->physicalMuramBase); ++ ++ if (p_Manip->cnia) ++ tmpReg32 |= FM_PCD_MANIP_INDEXED_STATS_CNIA; ++ ++ tmpReg32 |= FM_PCD_MANIP_INDEXED_STATS_DPD; ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ } ++ else ++ { ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_CC; ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ return E_OK; ++} ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++static t_Error FmPcdManipInitUpdate(t_Handle h_FmPcd, ++ t_Handle h_PcdParams, ++ t_Handle h_FmPort, ++ t_Handle h_Manip, ++ t_Handle h_Ad, ++ bool validate, ++ int level, ++ t_Handle h_FmTree) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_Manip,E_INVALID_HANDLE); ++ ++ UNUSED(level); ++ UNUSED(h_FmPcd); ++ UNUSED(h_FmTree); ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ err = UpdateInitMvIntFrameHeaderFromFrameToBufferPrefix(h_FmPort, p_Manip, h_Ad, validate); ++ break; ++#ifdef FM_CAPWAP_SUPPORT ++ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): ++ if (!p_Manip->h_Frag) ++ break; ++ case (HMAN_OC_CAPWAP_FRAGMENTATION): ++ err = UpdateInitCapwapFragmentation(h_FmPort, p_Manip, h_Ad, validate, h_FmTree); ++ break; ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ if (p_Manip->h_Frag) ++ err = UpdateInitCapwapReasm(h_FmPcd, h_FmPort, p_Manip, h_Ad, validate); ++ break; ++ case (HMAN_OC_CAPWAP_INDEXED_STATS): ++ err = UpdateIndxStats(h_FmPcd, h_FmPort, p_Manip); ++ break; ++#endif /* FM_CAPWAP_SUPPORT */ ++ case (HMAN_OC_IP_REASSEMBLY): ++ err = UpdateInitIpReasm(h_FmPcd, h_PcdParams, h_FmPort, p_Manip, h_Ad, validate); ++ break; ++ default: ++ return E_OK; ++ } ++ ++ return err; ++} ++ ++static t_Error FmPcdManipModifyUpdate(t_Handle h_Manip, t_Handle h_Ad, bool validate, int level, t_Handle h_FmTree) ++{ ++ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ t_Error err = E_OK; ++ ++ UNUSED(level); ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("modify node with this type of manipulation is not suppported")); ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ ++ if (p_Manip->h_Frag) ++ { ++ if (!(p_Manip->shadowUpdateParams & NUM_OF_TASKS) && ++ !(p_Manip->shadowUpdateParams & OFFSET_OF_DATA) && ++ !(p_Manip->shadowUpdateParams & OFFSET_OF_PR)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("modify node with this type of manipulation requires manipulation be updated previously in SetPcd function")); ++ } ++ break; ++#ifdef FM_CAPWAP_SUPPORT ++ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): ++ if (p_Manip->h_Frag) ++ err = UpdateModifyCapwapFragmenation(p_Manip, h_Ad, validate, h_FmTree); ++ break; ++#endif /* FM_CAPWAP_SUPPORT */ ++ default: ++ return E_OK; ++ } ++ ++ return err; ++} ++ ++#ifdef FM_CAPWAP_SUPPORT ++static t_Error GetPrOffsetByHeaderOrField(t_FmManipHdrInfo *p_HdrInfo, uint8_t *parseArrayOffset) ++{ ++ e_NetHeaderType hdr = p_HdrInfo->hdr; ++ e_FmPcdHdrIndex hdrIndex = p_HdrInfo->hdrIndex; ++ bool byField = p_HdrInfo->byField; ++ t_FmPcdFields field; ++ ++ if (byField) ++ field = p_HdrInfo->fullField; ++ ++ if (byField) ++ { ++ switch (hdr) ++ { ++ case (HEADER_TYPE_ETH): ++ switch (field.eth) ++ { ++ case (NET_HEADER_FIELD_ETH_TYPE): ++ *parseArrayOffset = CC_PC_PR_ETYPE_LAST_OFFSET; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of the type Ethernet with this field not supported")); ++ } ++ break; ++ case (HEADER_TYPE_VLAN): ++ switch (field.vlan) ++ { ++ case (NET_HEADER_FIELD_VLAN_TCI) : ++ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) ++ *parseArrayOffset = CC_PC_PR_VLAN1_OFFSET; ++ else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST) ++ *parseArrayOffset = CC_PC_PR_VLAN2_OFFSET; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of the type VLAN with this field not supported")); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of this header by field not supported")); ++ } ++ } ++ else ++ { ++ switch (hdr){ ++ case (HEADER_TYPE_ETH): ++ *parseArrayOffset = (uint8_t)CC_PC_PR_ETH_OFFSET; ++ break; ++ case (HEADER_TYPE_USER_DEFINED_SHIM1): ++ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM1_OFFSET; ++ break; ++ case (HEADER_TYPE_USER_DEFINED_SHIM2): ++ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM2_OFFSET; ++ break; ++ case (HEADER_TYPE_LLC_SNAP): ++ *parseArrayOffset = CC_PC_PR_USER_LLC_SNAP_OFFSET; ++ break; ++ case (HEADER_TYPE_PPPoE): ++ *parseArrayOffset = CC_PC_PR_PPPOE_OFFSET; ++ break; ++ case (HEADER_TYPE_MPLS): ++ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) ++ *parseArrayOffset = CC_PC_PR_MPLS1_OFFSET; ++ else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST) ++ *parseArrayOffset = CC_PC_PR_MPLS_LAST_OFFSET; ++ break; ++ case (HEADER_TYPE_IPv4): ++ case (HEADER_TYPE_IPv6): ++ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) ++ *parseArrayOffset = CC_PC_PR_IP1_OFFSET; ++ else if (hdrIndex == e_FM_PCD_HDR_INDEX_2) ++ *parseArrayOffset = CC_PC_PR_IP_LAST_OFFSET; ++ break; ++ case (HEADER_TYPE_MINENCAP): ++ *parseArrayOffset = CC_PC_PR_MINENC_OFFSET; ++ break; ++ case (HEADER_TYPE_GRE): ++ *parseArrayOffset = CC_PC_PR_GRE_OFFSET; ++ break; ++ case (HEADER_TYPE_TCP): ++ case (HEADER_TYPE_UDP): ++ case (HEADER_TYPE_IPSEC_AH): ++ case (HEADER_TYPE_IPSEC_ESP): ++ case (HEADER_TYPE_DCCP): ++ case (HEADER_TYPE_SCTP): ++ *parseArrayOffset = CC_PC_PR_L4_OFFSET; ++ break; ++ case (HEADER_TYPE_CAPWAP): ++ case (HEADER_TYPE_CAPWAP_DTLS): ++ *parseArrayOffset = CC_PC_PR_NEXT_HEADER_OFFSET; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of this header is not supported")); ++ } ++ } ++ return E_OK; ++} ++ ++static t_Error RmvHdrTillSpecLocNOrInsrtIntFrmHdr(t_FmPcdManipHdrRmvParams *p_ManipParams, t_FmPcdManip *p_Manip) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ uint32_t tmpReg32 = 0; ++ uint8_t prsArrayOffset = 0; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ if (p_Manip->rmv) ++ { ++ err = GetPrOffsetByHeaderOrField(&p_ManipParams->u.byHdr.u.fromStartByHdr.hdrInfo, &prsArrayOffset); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ tmpReg32 |= (uint32_t)prsArrayOffset << 24; ++ tmpReg32 |= HMAN_RMV_HDR; ++ } ++ ++ if (p_Manip->insrt) ++ tmpReg32 |= HMAN_INSRT_INT_FRM_HDR; ++ ++ tmpReg32 |= (uint32_t)HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR; ++ ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ return E_OK; ++} ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++static t_Error MvIntFrameHeaderFromFrameToBufferPrefix(t_FmPcdManip *p_Manip, bool caamUsed) ++{ ++ t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ uint32_t tmpReg32 = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Ad,E_INVALID_HANDLE); ++ ++ p_Manip->updateParams |= OFFSET_OF_PR | INTERNAL_CONTEXT_OFFSET; ++ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ *(uint32_t *)&p_Ad->ccAdBase = tmpReg32; ++ ++ tmpReg32 = 0; ++ tmpReg32 |= HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX; ++ tmpReg32 |= (uint32_t)0x16 << 16; ++ *(uint32_t *)&p_Ad->pcAndOffsets = tmpReg32; ++ ++ if (caamUsed) ++ *(uint32_t *)&p_Ad->gmask = 0xf0000000; ++ ++ return E_OK; ++} ++ ++#ifdef FM_CAPWAP_SUPPORT ++static t_Error CapwapRmvDtlsHdr(t_FmPcd *p_FmPcd, t_FmPcdManip *p_Manip) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ uint32_t tmpReg32 = 0; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ ++ tmpReg32 = 0; ++ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST; ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ ++ ++ if (p_Manip->h_Frag) ++ { ++ p_Manip->updateParams |= INTERNAL_CONTEXT_OFFSET; ++ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->h_Frag) - (p_FmPcd->physicalMuramBase)); ++ } ++ ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ return err; ++} ++ ++static t_Error CapwapReassembly(t_CapwapReassemblyParams *p_ManipParams, ++ t_FmPcdManip *p_Manip, ++ t_FmPcd *p_FmPcd, ++ uint8_t poolId) ++{ ++ t_Handle p_Table; ++ uint32_t tmpReg32 = 0; ++ int i = 0; ++ uint8_t log2Num; ++ uint8_t numOfSets; ++ uint32_t j = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!p_FmPcd->h_Hc) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("hc port has to be initialized in this mode")); ++ if (!POWER_OF_2(p_ManipParams->timeoutRoutineRequestTime)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("timeoutRoutineRequestTime has to be power of 2")); ++ if (!POWER_OF_2(p_ManipParams->maxNumFramesInProcess)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("maxNumFramesInProcess has to be power of 2")); ++ if (!p_ManipParams->timeoutRoutineRequestTime && p_ManipParams->timeoutThresholdForReassmProcess) ++ DBG(WARNING, ("if timeoutRoutineRequestTime 0, timeoutThresholdForReassmProcess is uselessly")); ++ if (p_ManipParams->numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH) ++ { ++ if ((p_ManipParams->maxNumFramesInProcess < 4) || ++ (p_ManipParams->maxNumFramesInProcess > 512)) ++ RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("In the case of numOfFramesPerHashEntry = e_FM_PCD_MANIP_EIGHT_WAYS_HASH maxNumFramesInProcess has to be in the range 4-512")); ++ } ++ else ++ { ++ if ((p_ManipParams->maxNumFramesInProcess < 8) || ++ (p_ManipParams->maxNumFramesInProcess > 2048)) ++ RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("In the case of numOfFramesPerHashEntry = e_FM_PCD_MANIP_FOUR_WAYS_HASH maxNumFramesInProcess has to be in the range 8-2048")); ++ } ++ ++ p_Manip->updateParams |= (NUM_OF_TASKS | OFFSET_OF_PR | OFFSET_OF_DATA | HW_PORT_ID); ++ ++ p_Manip->h_Frag = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE, ++ FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN); ++ if (!p_Manip->h_Frag) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc CAPWAP reassembly parameters table")); ++ ++ IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE); ++ ++ p_Table = (t_CapwapReasmPram *)p_Manip->h_Frag; ++ ++ p_Manip->fragParams.p_AutoLearnHashTbl = ++ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)(p_ManipParams->maxNumFramesInProcess * 2 * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE), ++ FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN); ++ ++ if (!p_Manip->fragParams.p_AutoLearnHashTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY,("MURAM alloc for CAPWAP automatic learning hash table")); ++ ++ IOMemSet32(p_Manip->fragParams.p_AutoLearnHashTbl, 0, (uint32_t)(p_ManipParams->maxNumFramesInProcess * 2 * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE)); ++ ++ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_AutoLearnHashTbl) - p_FmPcd->physicalMuramBase); ++ ++ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->autoLearnHashTblPtr, tmpReg32); ++ ++ tmpReg32 = 0; ++ if (p_ManipParams->timeOutMode == e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES) ++ tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_BETWEEN_FRAMES; ++ if (p_ManipParams->haltOnDuplicationFrag) ++ tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_HALT_ON_DUPLICATE_FRAG; ++ if (p_ManipParams->numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH) ++ { ++ i = 8; ++ tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_AUTOMATIC_LEARNIN_HASH_8_WAYS; ++ } ++ else ++ i = 4; ++ ++ numOfSets = (uint8_t)((p_ManipParams->maxNumFramesInProcess * 2) / i); ++ LOG2(numOfSets, log2Num); ++ tmpReg32 |= (uint32_t)(log2Num - 1) << 24; ++ ++ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->mode, tmpReg32); ++ ++ for (j=0; jmaxNumFramesInProcess*2; j++) ++ if (((j / i) % 2)== 0) ++ WRITE_UINT32(*(uint32_t *)PTR_MOVE(p_Manip->fragParams.p_AutoLearnHashTbl, j * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE), 0x80000000); ++ ++ tmpReg32 = 0x00008000; ++ tmpReg32 |= (uint32_t)poolId << 16; ++ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->bufferPoolIdAndRisc1SetIndexes, tmpReg32); ++ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->risc23SetIndexes, 0x80008000); ++ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->risc4SetIndexesAndExtendedStatsTblPtr, 0x80000000); ++ ++ p_Manip->fragParams.maxNumFramesInProcess = p_ManipParams->maxNumFramesInProcess; ++ ++ p_Manip->fragParams.sgBpid = poolId; ++ ++ p_Manip->fragParams.fqidForTimeOutFrames = p_ManipParams->fqidForTimeOutFrames; ++ p_Manip->fragParams.timeoutRoutineRequestTime = p_ManipParams->timeoutRoutineRequestTime; ++ p_Manip->fragParams.bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= (((uint32_t)1<fragParams.bitFor1Micro) * p_ManipParams->timeoutThresholdForReassmProcess); ++ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->expirationDelay, tmpReg32); ++ ++ return E_OK; ++} ++ ++static t_Error CapwapFragmentation(t_CapwapFragmentationParams *p_ManipParams, ++ t_FmPcdManip *p_Manip, ++ t_FmPcd *p_FmPcd, ++ uint8_t poolId) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ uint32_t tmpReg32 = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ ++ p_Manip->updateParams |= OFFSET_OF_DATA; ++ ++ p_Manip->frag = TRUE; ++ ++ p_Manip->h_Frag = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_Manip->h_Frag) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP fragmentation table descriptor")); ++ ++ IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag; ++ ++ tmpReg32 = 0; ++ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_FRAGMENTATION; ++ ++ if (p_ManipParams->headerOptionsCompr) ++ tmpReg32 |= FM_PCD_MANIP_CAPWAP_FRAG_COMPR_OPTION_FIELD_EN; ++ tmpReg32 |= ((uint32_t)poolId << 8); ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation; ++ p_Manip->fragParams.sgBpid = poolId; ++ ++ return E_OK; ++} ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++static t_Error FillReassmManipParams(t_FmPcdManip *p_Manip, bool ipv4) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; ++ uint32_t tmpReg32; ++ t_Error err = E_OK; ++ ++ /* Creates the IP Reassembly Parameters table. It contains parameters that are specific to either the IPv4 reassembly ++ function or to the IPv6 reassembly function. If both IPv4 reassembly and IPv6 reassembly are required, then ++ two separate IP Reassembly Parameter tables are required.*/ ++ if ((err = CreateIpReassTable(p_Manip, ipv4)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /* Sets the first Ad register (ccAdBase) - Action Descriptor Type and Pointer to the IP Reassembly Parameters Table offset from MURAM*/ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ ++ /* Gets the required Action descriptor table pointer */ ++ if (ipv4) ++ { ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->ipReassmParams.h_Ipv4Ad; ++ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->ipReassmParams.p_Ipv4ReassTbl) - (p_FmPcd->physicalMuramBase)); ++ } ++ else ++ { ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->ipReassmParams.h_Ipv6Ad; ++ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->ipReassmParams.p_Ipv6ReassTbl) - (p_FmPcd->physicalMuramBase)); ++ } ++ ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ /* Sets the second Ad register (matchTblPtr) - Buffer pool ID (BPID for V2) and Scatter/Gather table offset*/ ++ /* mark the Scatter/Gather table offset to be set later on when the port will be known */ ++ p_Manip->updateParams = (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS); ++ ++#if (DPAA_VERSION == 10) ++ tmpReg32 = (uint32_t)(p_Manip->ipReassmParams.sgBpid << 8); ++ WRITE_UINT32(p_Ad->matchTblPtr, tmpReg32); ++#endif /* (DPAA_VERSION == 10) */ ++#if (DPAA_VERSION >= 11) ++ if (p_Manip->ipReassmParams.nonConsistentSpFqid != 0) ++ { ++ tmpReg32 = FM_PCD_AD_NCSPFQIDM_MASK | (uint32_t)(p_Manip->ipReassmParams.nonConsistentSpFqid); ++ WRITE_UINT32(p_Ad->gmask, tmpReg32); ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* Sets the third Ad register (pcAndOffsets)- IP Reassemble Operation Code*/ ++ tmpReg32 = 0; ++ tmpReg32 |= (uint32_t)HMAN_OC_IP_REASSEMBLY; ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ p_Manip->reassm = TRUE; ++ ++ return E_OK; ++} ++ ++static t_Error SetIpv4ReassmManip(t_FmPcdManip *p_Manip) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; ++ ++ /* Allocation if IPv4 Action descriptor */ ++ p_Manip->ipReassmParams.h_Ipv4Ad = ++ (t_Handle)XX_MallocSmart(FM_PCD_CC_AD_ENTRY_SIZE, ++ p_Manip->ipReassmParams.dataMemId, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_Manip->ipReassmParams.h_Ipv4Ad) ++ { ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of IPv4 table descriptor")); ++ } ++ ++ memset(p_Manip->ipReassmParams.h_Ipv4Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Fill reassembly manipulation parameter in the IP Reassembly Action Descriptor */ ++ return FillReassmManipParams(p_Manip, TRUE); ++} ++ ++static t_Error SetIpv6ReassmManip(t_FmPcdManip *p_Manip) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; ++ ++ /* Allocation if IPv6 Action descriptor */ ++ p_Manip->ipReassmParams.h_Ipv6Ad = ++ (t_Handle)XX_MallocSmart(FM_PCD_CC_AD_ENTRY_SIZE, ++ p_Manip->ipReassmParams.dataMemId, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_Manip->ipReassmParams.h_Ipv6Ad) ++ { ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of IPv6 table descriptor")); ++ } ++ ++ memset(p_Manip->ipReassmParams.h_Ipv6Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Fill reassembly manipulation parameter in the IP Reassembly Action Descriptor */ ++ return FillReassmManipParams(p_Manip, FALSE); ++} ++ ++static t_Error IpReassembly(t_FmPcdManipReassemParams *p_ManipReassmParams, ++ t_FmPcdManip *p_Manip) ++{ ++ uint32_t maxSetNumber = 10000; ++ t_FmPcdManipReassemIpParams reassmManipParams = p_ManipReassmParams->u.ipReassem; ++ t_Error res; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((t_FmPcd *)p_Manip->h_FmPcd)->h_Hc, E_INVALID_HANDLE); ++ ++ /* Check validation of user's parameter.*/ ++ if ((reassmManipParams.timeoutThresholdForReassmProcess < 1000) || ++ (reassmManipParams.timeoutThresholdForReassmProcess > 8000000)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("timeoutThresholdForReassmProcess should be 1msec - 8sec")); ++ /* It is recommended that the total number of entries in this table (number of sets * number of ways) ++ will be twice the number of frames that are expected to be reassembled simultaneously.*/ ++ if (reassmManipParams.maxNumFramesInProcess > ++ (reassmManipParams.maxNumFramesInProcess * maxSetNumber / 2)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumFramesInProcess has to be less than (maximun set number * number of ways / 2)")); ++ ++ if ((p_ManipReassmParams->hdr == HEADER_TYPE_IPv6) && ++ (reassmManipParams.minFragSize[1] < 256)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("minFragSize[1] must be >= 256")); ++ ++ /* Saves user's reassembly manipulation parameters */ ++ p_Manip->ipReassmParams.relativeSchemeId[0] = reassmManipParams.relativeSchemeId[0]; ++ p_Manip->ipReassmParams.relativeSchemeId[1] = reassmManipParams.relativeSchemeId[1]; ++ p_Manip->ipReassmParams.numOfFramesPerHashEntry[0] = reassmManipParams.numOfFramesPerHashEntry[0]; ++ p_Manip->ipReassmParams.numOfFramesPerHashEntry[1] = reassmManipParams.numOfFramesPerHashEntry[1]; ++ p_Manip->ipReassmParams.minFragSize[0] = reassmManipParams.minFragSize[0]; ++ p_Manip->ipReassmParams.minFragSize[1] = reassmManipParams.minFragSize[1]; ++ p_Manip->ipReassmParams.maxNumFramesInProcess = reassmManipParams.maxNumFramesInProcess; ++ p_Manip->ipReassmParams.timeOutMode = reassmManipParams.timeOutMode; ++ p_Manip->ipReassmParams.fqidForTimeOutFrames = reassmManipParams.fqidForTimeOutFrames; ++ p_Manip->ipReassmParams.timeoutThresholdForReassmProcess = reassmManipParams.timeoutThresholdForReassmProcess; ++ p_Manip->ipReassmParams.dataMemId = reassmManipParams.dataMemId; ++ p_Manip->ipReassmParams.dataLiodnOffset = reassmManipParams.dataLiodnOffset; ++#if (DPAA_VERSION == 10) ++ p_Manip->ipReassmParams.sgBpid = reassmManipParams.sgBpid; ++#endif /* (DPAA_VERSION == 10) */ ++#if (DPAA_VERSION >= 11) ++ if (reassmManipParams.nonConsistentSpFqid != 0) ++ { ++ p_Manip->ipReassmParams.nonConsistentSpFqid = reassmManipParams.nonConsistentSpFqid; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* Creates and initializes the IP Reassembly common parameter table */ ++ CreateIpReassCommonTable(p_Manip); ++ ++ /* Creation of IPv4 reassembly manipulation */ ++ if ((p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv6) || (p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv4)) ++ { ++ res = SetIpv4ReassmManip(p_Manip); ++ if (res != E_OK) ++ return res; ++ } ++ ++ /* Creation of IPv6 reassembly manipulation */ ++ if (p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv6) ++ { ++ res = SetIpv6ReassmManip(p_Manip); ++ if (res != E_OK) ++ return res; ++ } ++ ++ return E_OK; ++} ++ ++static void setReassmSchemeParams(t_FmPcd* p_FmPcd, t_FmPcdKgSchemeParams *p_Scheme, t_Handle h_CcTree, bool ipv4, uint8_t groupId) ++{ ++ uint32_t j; ++ uint8_t res; ++ ++ /* Configures scheme's network environment parameters */ ++ p_Scheme->netEnvParams.numOfDistinctionUnits = 2; ++ if (ipv4) ++ res = FmPcdNetEnvGetUnitId(p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_IPv4, FALSE, 0); ++ else ++ res = FmPcdNetEnvGetUnitId(p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_IPv6, FALSE, 0); ++ ASSERT_COND(res != FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ p_Scheme->netEnvParams.unitIds[0] = res; ++ ++ res = FmPcdNetEnvGetUnitId(p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_USER_DEFINED_SHIM2, FALSE, 0); ++ ASSERT_COND(res != FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ p_Scheme->netEnvParams.unitIds[1] = res; ++ ++ /* Configures scheme's next engine parameters*/ ++ p_Scheme->nextEngine = e_FM_PCD_CC; ++ p_Scheme->kgNextEngineParams.cc.h_CcTree = h_CcTree; ++ p_Scheme->kgNextEngineParams.cc.grpId = groupId; ++ p_Scheme->useHash = TRUE; ++ ++ /* Configures scheme's key*/ ++ if (ipv4 == TRUE) ++ { ++ p_Scheme->keyExtractAndHashParams.numOfUsedExtracts = 4; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].type = e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.hdr = HEADER_TYPE_IPv4 ; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.extractByHdrType.fullField.ipv4 = NET_HEADER_FIELD_IPv4_DST_IP; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].type = e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.hdr = HEADER_TYPE_IPv4; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.extractByHdrType.fullField.ipv4 = NET_HEADER_FIELD_IPv4_SRC_IP; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].type = e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.hdr = HEADER_TYPE_IPv4; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fullField.ipv4 = NET_HEADER_FIELD_IPv4_PROTO; ++ p_Scheme->keyExtractAndHashParams.extractArray[3].type = e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.hdr = HEADER_TYPE_IPv4; ++ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.ignoreProtocolValidation = FALSE; ++ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.extractByHdrType.fromHdr.size = 2; ++ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.extractByHdrType.fromHdr.offset = 4; ++ } ++ else /* IPv6 */ ++ { ++ p_Scheme->keyExtractAndHashParams.numOfUsedExtracts = 3; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].type = e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.hdr = HEADER_TYPE_IPv6 ; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.extractByHdrType.fullField.ipv6 = NET_HEADER_FIELD_IPv6_DST_IP; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].type = e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.hdr = HEADER_TYPE_IPv6; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.extractByHdrType.fullField.ipv6 = NET_HEADER_FIELD_IPv6_SRC_IP; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].type = e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.hdr = HEADER_TYPE_USER_DEFINED_SHIM2; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fromHdr.size = 4; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fromHdr.offset = 4; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.ignoreProtocolValidation = TRUE; ++ } ++ ++ p_Scheme->keyExtractAndHashParams.privateDflt0 = 0x01020304; ++ p_Scheme->keyExtractAndHashParams.privateDflt1 = 0x11121314; ++ p_Scheme->keyExtractAndHashParams.numOfUsedDflts = FM_PCD_KG_NUM_OF_DEFAULT_GROUPS; ++ for (j=0; jkeyExtractAndHashParams.dflts[j].type = (e_FmPcdKgKnownFieldsDfltTypes)j; /* all types */ ++ p_Scheme->keyExtractAndHashParams.dflts[j].dfltSelect = e_FM_PCD_KG_DFLT_GBL_0; ++ } ++} ++ ++static t_Error IpReassemblyStats(t_FmPcdManip *p_Manip, t_FmPcdManipReassemIpStats *p_Stats) ++{ ++ ASSERT_COND(p_Manip); ++ ASSERT_COND(p_Stats); ++ ASSERT_COND(p_Manip->ipReassmParams.p_IpReassCommonTbl); ++ ++ p_Stats->timeout = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalTimeOutCounter); ++ p_Stats->rfdPoolBusy = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalRfdPoolBusyCounter); ++ p_Stats->internalBufferBusy = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalInternalBufferBusy); ++ p_Stats->externalBufferBusy = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalExternalBufferBusy); ++ p_Stats->sgFragments = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalSgFragmentCounter); ++ p_Stats->dmaSemaphoreDepletion = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalDmaSemaphoreDepletionCounter); ++ ++ if (p_Manip->ipReassmParams.p_Ipv4ReassTbl) ++ { ++ p_Stats->specificHdrStatistics[0].successfullyReassembled = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalSuccessfullyReasmFramesCounter); ++ p_Stats->specificHdrStatistics[0].validFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalValidFragmentCounter); ++ p_Stats->specificHdrStatistics[0].processedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalProcessedFragCounter); ++ p_Stats->specificHdrStatistics[0].malformedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalMalformdFragCounter); ++ p_Stats->specificHdrStatistics[0].autoLearnBusy = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalSetBusyCounter); ++ p_Stats->specificHdrStatistics[0].discardedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalDiscardedFragsCounter); ++ p_Stats->specificHdrStatistics[0].moreThan16Fragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalMoreThan16FramesCounter); ++ } ++ if (p_Manip->ipReassmParams.p_Ipv6ReassTbl) ++ { ++ p_Stats->specificHdrStatistics[1].successfullyReassembled = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalSuccessfullyReasmFramesCounter); ++ p_Stats->specificHdrStatistics[1].validFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalValidFragmentCounter); ++ p_Stats->specificHdrStatistics[1].processedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalProcessedFragCounter); ++ p_Stats->specificHdrStatistics[1].malformedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalMalformdFragCounter); ++ p_Stats->specificHdrStatistics[1].autoLearnBusy = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalSetBusyCounter); ++ p_Stats->specificHdrStatistics[1].discardedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalDiscardedFragsCounter); ++ p_Stats->specificHdrStatistics[1].moreThan16Fragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalMoreThan16FramesCounter); ++ } ++ return E_OK; ++} ++ ++#ifdef FM_CAPWAP_SUPPORT ++static t_Error IndxStats(t_FmPcdStatsParams *p_StatsParams,t_FmPcdManip *p_Manip,t_FmPcd *p_FmPcd) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ uint32_t tmpReg32 = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ ++ UNUSED(p_FmPcd); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ ++ tmpReg32 = 0; ++ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_INDEXED_STATS; ++ if (p_StatsParams->type == e_FM_PCD_STATS_PER_FLOWID) ++ tmpReg32 |= (uint32_t)0x16 << 16; ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ return E_OK; ++} ++ ++static t_Error InsrtHdrByTempl(t_FmPcdManipHdrInsrtParams *p_ManipParams, t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdManipHdrInsrtByTemplateParams *p_InsrtByTemplate = &p_ManipParams->u.byTemplate; ++ uint8_t tmpReg8 = 0xff; ++ t_AdOfTypeContLookup *p_Ad; ++ bool ipModify = FALSE; ++ uint32_t tmpReg32 = 0, tmpRegNia = 0; ++ uint16_t tmpReg16 = 0; ++ t_Error err = E_OK; ++ uint8_t extraAddedBytes = 0, blockSize = 0, extraAddedBytesAlignedToBlockSize = 0, log2Num = 0; ++ uint8_t *p_Template = NULL; ++ ++ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd,E_NULL_POINTER); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ if (p_Manip->insrt) ++ { ++ if ((!p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterIp) || ++ (!p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterVlan)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : asking for header template modifications with no template for insertion (template size)")); ++ ++ if (p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterIp && (p_InsrtByTemplate->size <= p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : size of template < ipOuterOffset")); ++ ++ if (p_InsrtByTemplate->size > 128) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Size of header template for insertion can not be more than 128")); ++ ++ if (p_InsrtByTemplate->size) ++ { ++ p_Manip->p_Template = (uint8_t *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ p_InsrtByTemplate->size, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if(!p_Manip->p_Template) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED")); ++ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->p_Template) - (p_FmPcd->physicalMuramBase)); ++ tmpReg32 |= (uint32_t)p_InsrtByTemplate->size << 24; ++ *(uint32_t *)&p_Ad->matchTblPtr = tmpReg32; ++ } ++ ++ tmpReg32 = 0; ++ ++ p_Template = (uint8_t *)XX_Malloc(p_InsrtByTemplate->size * sizeof(uint8_t)); ++ ++ if (!p_Template) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("XX_Malloc allocation FAILED")); ++ ++ memcpy(p_Template, p_InsrtByTemplate->hdrTemplate, p_InsrtByTemplate->size * sizeof(uint8_t)); ++ ++ ++ if (p_InsrtByTemplate->modifyOuterIp) ++ { ++ ipModify = TRUE; ++ ++ tmpReg8 = (uint8_t)p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset]; ++ ++ if((tmpReg8 & 0xf0) == 0x40) ++ tmpReg8 = 4; ++ else if((tmpReg8 & 0xf0) == 0x60) ++ tmpReg8 = 6; ++ else ++ tmpReg8 = 0xff; ++ ++ if (tmpReg8 != 0xff) ++ { ++ if(p_InsrtByTemplate->modifyOuterIpParams.dscpEcn & 0xff00) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : IPV4 present in header template, dscpEcn has to be only 1 byte")); ++ if(p_InsrtByTemplate->modifyOuterIpParams.recalculateLength) ++ { ++ ++ if((p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize + p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedNotAlignedToBlockSize) > 255) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("extra Byte added can not be more than 256 bytes")); ++ extraAddedBytes = (uint8_t) (p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize + p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedNotAlignedToBlockSize); ++ blockSize = p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.blockSize; ++ extraAddedBytesAlignedToBlockSize = p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize; ++ /*IP header template - IP totalLength - ++ (1 byte) extraByteForIp = headerTemplateSize - ipOffset + insertedBytesAfterThisStage , ++ in the case of SEC insertedBytesAfterThisStage - SEC trailer (21/31) + header(13) ++ second byte - extraByteForIp = headerTemplate - ipOffset + insertedBytesAfterThisStage*/ ++ } ++ if (blockSize) ++ { ++ if (!POWER_OF_2(blockSize)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("inputFrmPaddingUpToBlockSize has to be power of 2")); ++ } ++ ++ } ++ if (tmpReg8 == 4) ++ { ++ if ((IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP + p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset) > p_InsrtByTemplate->size) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : IP present in header template, user asked for IP modifications but ipOffset + ipTotalLengthFieldOffset in header template bigger than template size")); ++ ++ ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_DSCECN_FIELD_OFFSET_FROM_IP] = (uint8_t)p_InsrtByTemplate->modifyOuterIpParams.dscpEcn; ++ ++ if (blockSize) ++ blockSize -= 1; ++ ++ if ((p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes) > 255) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes has to be less than 255")); ++ ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP + 1] = blockSize;// IPV6 - in AD instead of SEQ IND ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP] = (uint8_t)(p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes);// for IPV6 decrement additional 40 bytes of IPV6 heade size ++ ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_ID_FIELD_OFFSET_FROM_IP] = 0x00; ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_ID_FIELD_OFFSET_FROM_IP + 1] = extraAddedBytesAlignedToBlockSize; ++ ++ ++ ++ /*IP header template - relevant only for ipv4 CheckSum = 0*/ ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP] = 0x00; ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP + 1] = 0x00; ++ ++ ++ /*UDP checksum has to be 0*/ ++ if (p_InsrtByTemplate->modifyOuterIpParams.udpPresent) ++ { ++ if ((p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + UDP_CHECKSUM_FIELD_SIZE) > p_InsrtByTemplate->size) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : UDP present according to user but (UDP offset + UDP header size) < size of header template")); ++ ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP ] = 0x00; ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + 1] = 0x00; ++ ++ } ++ ++ if (p_InsrtByTemplate->modifyOuterIpParams.ipIdentGenId > 7) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("ipIdentGenId has to be one out of 8 sequence number generators (0 - 7) for IP identification field")); ++ ++ tmpRegNia |= (uint32_t)p_InsrtByTemplate->modifyOuterIpParams.ipIdentGenId<<24; ++ } ++ else if (tmpReg8 == 6) ++ { ++ /*TODO - add check for maximum value of blockSize;*/ ++ if (blockSize) ++ LOG2(blockSize, log2Num); ++ tmpRegNia |= (uint32_t)log2Num << 24; ++ ++ // for IPV6 decrement additional 40 bytes of IPV6 heade size - because IPV6 header size is not included in payloadLength ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP] = (uint8_t)(p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes - 40); ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP + 1] = extraAddedBytesAlignedToBlockSize; ++ if (p_InsrtByTemplate->modifyOuterIpParams.udpPresent) ++ { ++ if ((p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + UDP_CHECKSUM_FIELD_SIZE) > p_InsrtByTemplate->size) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : UDP present according to user but (UDP offset + UDP header size) < size of header template")); ++ if (p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_NEXT_HEADER_OFFSET_FROM_IP] != 0x88) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("OUr suppport is only IPv6/UDPLite")); ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_LENGTH_FIELD_OFFSET_FROM_UDP] = 0x00; ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_LENGTH_FIELD_OFFSET_FROM_UDP + 1] = 0x08; ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP] = 0x00; ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + 1] = 0x00; ++ } ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("IP version supported only IPV4")); ++ } ++ ++ tmpReg32 = tmpReg16 = tmpReg8 = 0; ++ /*TODO - check it*/ ++ if (p_InsrtByTemplate->modifyOuterVlan) ++ { ++ if (p_InsrtByTemplate->modifyOuterVlanParams.vpri & ~0x07) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE,("Inconsistent parameters : user asked for VLAN modifications but VPRI more than 3 bits")); ++ ++ memcpy(&tmpReg16, &p_Template[VLAN_TAG_FIELD_OFFSET_FROM_ETH], 2*(sizeof(uint8_t))); ++ if ((tmpReg16 != 0x9100) && (tmpReg16!= 0x9200) && (tmpReg16 != 0x8100)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE,("Inconsistent parameters : user asked for VLAN modifications but Tag Protocol identifier is not VLAN ")); ++ ++ memcpy(&tmpReg8, &p_Template[14],1*(sizeof(uint8_t))); ++ tmpReg8 &= 0x1f; ++ tmpReg8 |= (uint8_t)(p_InsrtByTemplate->modifyOuterVlanParams.vpri << 5); ++ ++ p_Template[14] = tmpReg8; ++ } ++ ++ Mem2IOCpy32(p_Manip->p_Template, p_Template, p_InsrtByTemplate->size); ++ ++ XX_Free(p_Template); ++ } ++ ++ tmpReg32 = 0; ++ if (p_Manip->h_Frag) ++ { ++ tmpRegNia |= (uint32_t)(XX_VirtToPhys(p_Manip->h_Frag) - (p_FmPcd->physicalMuramBase)); ++ tmpReg32 |= (uint32_t)p_Manip->sizeForFragmentation << 16; ++ } ++ else ++ tmpReg32 = 0xffff0000; ++ ++ if (ipModify) ++ tmpReg32 |= (uint32_t)p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset << 8; ++ else ++ tmpReg32 |= (uint32_t)0x0000ff00; ++ ++ tmpReg32 |= (uint32_t)HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER; ++ *(uint32_t *)&p_Ad->pcAndOffsets = tmpReg32; ++ ++ tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ *(uint32_t *)&p_Ad->ccAdBase = tmpRegNia; ++ ++ return err; ++} ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++static t_Error IpFragmentationStats(t_FmPcdManip *p_Manip, t_FmPcdManipFragIpStats *p_Stats) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ ++ ASSERT_COND(p_Manip); ++ ASSERT_COND(p_Stats); ++ ASSERT_COND(p_Manip->h_Ad); ++ ASSERT_COND(p_Manip->ipFragParams.p_Frag); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ ++ p_Stats->totalFrames = GET_UINT32(p_Ad->gmask); ++ p_Stats->fragmentedFrames = GET_UINT32(p_Manip->ipFragParams.p_Frag->ccAdBase) & 0x00ffffff; ++ p_Stats->generatedFragments = GET_UINT32(p_Manip->ipFragParams.p_Frag->matchTblPtr); ++ ++ return E_OK; ++} ++ ++static t_Error IpFragmentation(t_FmPcdManipFragIpParams *p_ManipParams, t_FmPcdManip *p_Manip) ++{ ++ uint32_t pcAndOffsetsReg = 0, ccAdBaseReg = 0, gmaskReg = 0; ++ t_FmPcd *p_FmPcd; ++#if (DPAA_VERSION == 10) ++ t_Error err = E_OK; ++#endif /* (DPAA_VERSION == 10) */ ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_ManipParams->sizeForFragmentation != 0xFFFF, E_INVALID_VALUE); ++ ++ p_FmPcd = p_Manip->h_FmPcd; ++ /* Allocation of fragmentation Action Descriptor */ ++ p_Manip->ipFragParams.p_Frag = (t_AdOfTypeContLookup *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_Manip->ipFragParams.p_Frag) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Fragmentation table descriptor")); ++ IOMemSet32( p_Manip->ipFragParams.p_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Prepare the third Ad register (pcAndOffsets)- OperationCode */ ++ pcAndOffsetsReg = (uint32_t)HMAN_OC_IP_FRAGMENTATION; ++ ++ /* Prepare the first Ad register (ccAdBase) - Don't frag action and Action descriptor type*/ ++ ccAdBaseReg = FM_PCD_AD_CONT_LOOKUP_TYPE; ++ ccAdBaseReg |= (p_ManipParams->dontFragAction << FM_PCD_MANIP_IP_FRAG_DF_SHIFT); ++ ++ ++ /* Set Scatter/Gather BPid */ ++ if (p_ManipParams->sgBpidEn) ++ { ++ ccAdBaseReg |= FM_PCD_MANIP_IP_FRAG_SG_BDID_EN; ++ pcAndOffsetsReg |= ((p_ManipParams->sgBpid << FM_PCD_MANIP_IP_FRAG_SG_BDID_SHIFT) & FM_PCD_MANIP_IP_FRAG_SG_BDID_MASK); ++ } ++ ++ /* Prepare the first Ad register (gmask) - scratch buffer pool id and Pointer to fragment ID */ ++ gmaskReg = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr)) - p_FmPcd->physicalMuramBase); ++#if (DPAA_VERSION == 10) ++ gmaskReg |= p_ManipParams->scratchBpid << FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID; ++#else ++ gmaskReg |= (0xFF) << FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID; ++#endif /* (DPAA_VERSION == 10) */ ++ ++ /* Set all Ad registers */ ++ WRITE_UINT32(p_Manip->ipFragParams.p_Frag->pcAndOffsets, pcAndOffsetsReg); ++ WRITE_UINT32(p_Manip->ipFragParams.p_Frag->ccAdBase, ccAdBaseReg); ++ WRITE_UINT32(p_Manip->ipFragParams.p_Frag->gmask, gmaskReg); ++ ++ /* Saves user's fragmentation manipulation parameters */ ++ p_Manip->frag = TRUE; ++ p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation; ++ ++#if (DPAA_VERSION == 10) ++ p_Manip->ipFragParams.scratchBpid = p_ManipParams->scratchBpid; ++ ++ /* scratch buffer pool initialization */ ++ if ((err = FmPcdFragHcScratchPoolFill((t_Handle)p_FmPcd, p_ManipParams->scratchBpid)) != E_OK) ++ { ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipFragParams.p_Frag); ++ p_Manip->ipFragParams.p_Frag = NULL; ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++#endif /* (DPAA_VERSION == 10) */ ++ ++ return E_OK; ++} ++ ++static t_Error IPManip(t_FmPcdManip *p_Manip) ++{ ++ t_Error err = E_OK; ++ t_FmPcd *p_FmPcd; ++ t_AdOfTypeContLookup *p_Ad; ++ uint32_t tmpReg32 = 0, tmpRegNia = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); ++ p_FmPcd = p_Manip->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd,E_INVALID_HANDLE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ ++ tmpReg32 = FM_PCD_MANIP_IP_NO_FRAGMENTATION; ++ if (p_Manip->frag == TRUE) ++ { ++ tmpRegNia = (uint32_t)(XX_VirtToPhys(p_Manip->ipFragParams.p_Frag) - (p_FmPcd->physicalMuramBase)); ++ tmpReg32 = (uint32_t)p_Manip->sizeForFragmentation << FM_PCD_MANIP_IP_MTU_SHIFT; ++ } ++ ++ tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ tmpReg32 |= HMAN_OC_IP_MANIP; ++ ++#if (DPAA_VERSION >= 11) ++ tmpRegNia |= FM_PCD_MANIP_IP_CNIA; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ WRITE_UINT32(p_Ad->ccAdBase, tmpRegNia); ++ WRITE_UINT32(p_Ad->gmask, 0); /* Total frame counter - MUST be initialized to zero.*/ ++ ++ return err; ++} ++ ++static t_Error IPSecManip(t_FmPcdManipParams *p_ManipParams, ++ t_FmPcdManip *p_Manip) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ t_FmPcdManipSpecialOffloadIPSecParams *p_IPSecParams; ++ t_Error err = E_OK; ++ uint32_t tmpReg32 = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_INVALID_HANDLE); ++ ++ p_IPSecParams = &p_ManipParams->u.specialOffload.u.ipsec; ++ ++ SANITY_CHECK_RETURN_ERROR(!p_IPSecParams->variableIpHdrLen || ++ p_IPSecParams->decryption, E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR(!p_IPSecParams->variableIpVersion || ++ !p_IPSecParams->decryption, E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR(!p_IPSecParams->variableIpVersion || ++ p_IPSecParams->outerIPHdrLen, E_INVALID_VALUE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ tmpReg32 |= (p_IPSecParams->decryption)?FM_PCD_MANIP_IPSEC_DEC:0; ++ tmpReg32 |= (p_IPSecParams->ecnCopy)?FM_PCD_MANIP_IPSEC_ECN_EN:0; ++ tmpReg32 |= (p_IPSecParams->dscpCopy)?FM_PCD_MANIP_IPSEC_DSCP_EN:0; ++ tmpReg32 |= (p_IPSecParams->variableIpHdrLen)?FM_PCD_MANIP_IPSEC_VIPL_EN:0; ++ tmpReg32 |= (p_IPSecParams->variableIpVersion)?FM_PCD_MANIP_IPSEC_VIPV_EN:0; ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ tmpReg32 = HMAN_OC_IPSEC_MANIP; ++ tmpReg32 |= p_IPSecParams->outerIPHdrLen << FM_PCD_MANIP_IPSEC_IP_HDR_LEN_SHIFT; ++ if (p_ManipParams->h_NextManip) ++ { ++ WRITE_UINT32(p_Ad->matchTblPtr, ++ (uint32_t)(XX_VirtToPhys(((t_FmPcdManip *)p_ManipParams->h_NextManip)->h_Ad)- ++ (((t_FmPcd *)p_Manip->h_FmPcd)->physicalMuramBase)) >> 4); ++ ++ tmpReg32 |= FM_PCD_MANIP_IPSEC_NADEN; ++ } ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ return err; ++} ++ ++#ifdef FM_CAPWAP_SUPPORT ++static t_Error CheckStatsParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdStatsParams *p_StatsParams) ++{ ++ ++ switch (p_StatsParams->type) ++ { ++ case (e_FM_PCD_STATS_PER_FLOWID): ++ p_Manip->opcode = HMAN_OC_CAPWAP_INDEXED_STATS; ++ p_Manip->muramAllocate = TRUE; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported statistics type")); ++ } ++ ++ return E_OK; ++} ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++static t_Handle ManipOrStatsSetNode(t_Handle h_FmPcd, t_Handle *p_Params, bool stats) ++{ ++ t_FmPcdManip *p_Manip; ++ t_Error err; ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ ++ p_Manip = (t_FmPcdManip*)XX_Malloc(sizeof(t_FmPcdManip)); ++ if (!p_Manip) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); ++ return NULL; ++ } ++ memset(p_Manip, 0, sizeof(t_FmPcdManip)); ++ ++ p_Manip->type = ((t_FmPcdManipParams *)p_Params)->type; ++ memcpy((uint8_t*)&p_Manip->manipParams, p_Params, sizeof(p_Manip->manipParams)); ++ ++ if (!stats) ++ err = CheckManipParamsAndSetType(p_Manip, (t_FmPcdManipParams *)p_Params); ++#ifdef FM_CAPWAP_SUPPORT ++ else ++ err = CheckStatsParamsAndSetType(p_Manip, (t_FmPcdStatsParams *)p_Params); ++#else ++ else ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Statistics node!")); ++ return NULL; ++ } ++#endif /* FM_CAPWAP_SUPPORT */ ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("INVALID HEADER MANIPULATION TYPE")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ if (p_Manip->opcode != HMAN_OC_IP_REASSEMBLY) ++ { ++ /* In Case of IP reassembly manipulation the IPv4/IPv6 reassembly action descriptor will ++ be defines later on */ ++ if (p_Manip->muramAllocate) ++ { ++ p_Manip->h_Ad = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_Manip->h_Ad) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Manipulation action descriptor")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ IOMemSet32(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ } ++ else ++ { ++ p_Manip->h_Ad = (t_Handle)XX_Malloc(FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t)); ++ if (!p_Manip->h_Ad) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of Manipulation action descriptor")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ memset(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t)); ++ } ++ } ++ ++ p_Manip->h_FmPcd = h_FmPcd; ++ ++ return p_Manip; ++} ++ ++static void UpdateAdPtrOfNodesWhichPointsOnCrntMdfManip(t_FmPcdManip *p_CrntMdfManip, ++ t_List *h_NodesLst) ++{ ++ t_CcNodeInformation *p_CcNodeInformation; ++ t_FmPcdCcNode *p_NodePtrOnCurrentMdfManip = NULL; ++ t_List *p_Pos; ++ int i = 0; ++ t_Handle p_AdTablePtOnCrntCurrentMdfNode/*, p_AdTableNewModified*/; ++ t_CcNodeInformation ccNodeInfo; ++ ++ LIST_FOR_EACH(p_Pos, &p_CrntMdfManip->nodesLst) ++ { ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ p_NodePtrOnCurrentMdfManip = (t_FmPcdCcNode *)p_CcNodeInformation->h_CcNode; ++ ++ ASSERT_COND(p_NodePtrOnCurrentMdfManip); ++ ++ /* Search in the previous node which exact index points on this current modified node for getting AD */ ++ for (i = 0; i < p_NodePtrOnCurrentMdfManip->numOfKeys + 1; i++) ++ { ++ if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC) ++ { ++ if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].nextEngineParams.h_Manip == (t_Handle)p_CrntMdfManip) ++ { ++ if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].p_StatsObj) ++ p_AdTablePtOnCrntCurrentMdfNode = ++ p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].p_StatsObj->h_StatsAd; ++ else ++ p_AdTablePtOnCrntCurrentMdfNode = ++ PTR_MOVE(p_NodePtrOnCurrentMdfManip->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = p_AdTablePtOnCrntCurrentMdfNode; ++ EnqueueNodeInfoToRelevantLst(h_NodesLst, &ccNodeInfo, NULL); ++ } ++ } ++ } ++ ++ ASSERT_COND(i != p_NodePtrOnCurrentMdfManip->numOfKeys); ++ } ++} ++ ++static void BuildHmtd(uint8_t *p_Dest, uint8_t *p_Src, uint8_t *p_Hmcd, t_FmPcd *p_FmPcd) ++{ ++ t_Error err; ++ ++ /* Copy the HMTD */ ++ IO2IOCpy32(p_Dest, (uint8_t*)p_Src, 16); ++ /* Replace the HMCT table pointer */ ++ WRITE_UINT32(((t_Hmtd *)p_Dest)->hmcdBasePtr, ++ (uint32_t)(XX_VirtToPhys(p_Hmcd) - ((t_FmPcd*)p_FmPcd)->physicalMuramBase)); ++ /* Call Host Command to replace HMTD by a new HMTD */ ++ err = FmHcPcdCcDoDynamicChange(p_FmPcd->h_Hc, ++ (uint32_t)(XX_VirtToPhys(p_Src) - p_FmPcd->physicalMuramBase), ++ (uint32_t)(XX_VirtToPhys(p_Dest) - p_FmPcd->physicalMuramBase)); ++ if (err) ++ REPORT_ERROR(MINOR, err, ("Failed in dynamic manip change, continued to the rest of the owners.")); ++} ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++t_Error FmPcdManipUpdate(t_Handle h_FmPcd, ++ t_Handle h_PcdParams, ++ t_Handle h_FmPort, ++ t_Handle h_Manip, ++ t_Handle h_Ad, ++ bool validate, ++ int level, ++ t_Handle h_FmTree, ++ bool modify) ++{ ++ t_Error err; ++ ++ if (!modify) ++ err = FmPcdManipInitUpdate(h_FmPcd, h_PcdParams, h_FmPort, h_Manip, h_Ad, validate, level, h_FmTree); ++ else ++ err = FmPcdManipModifyUpdate(h_Manip, h_Ad, validate, level, h_FmTree); ++ ++ return err; ++} ++ ++uint32_t FmPcdManipGetRequiredAction (t_Handle h_Manip) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ ++ ASSERT_COND(h_Manip); ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ return UPDATE_NIA_ENQ_WITHOUT_DMA; ++ default: ++ return 0; ++ } ++} ++ ++void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add) ++{ ++ ++ uint32_t intFlags; ++ ++ intFlags = XX_LockIntrSpinlock(((t_FmPcdManip *)h_Manip)->h_Spinlock); ++ if (add) ++ ((t_FmPcdManip *)h_Manip)->owner++; ++ else ++ { ++ ASSERT_COND(((t_FmPcdManip *)h_Manip)->owner); ++ ((t_FmPcdManip *)h_Manip)->owner--; ++ } ++ XX_UnlockIntrSpinlock(((t_FmPcdManip *)h_Manip)->h_Spinlock, intFlags); ++} ++ ++t_List *FmPcdManipGetNodeLstPointedOnThisManip(t_Handle h_Manip) ++{ ++ ASSERT_COND(h_Manip); ++ return &((t_FmPcdManip *)h_Manip)->nodesLst; ++} ++ ++t_List *FmPcdManipGetSpinlock(t_Handle h_Manip) ++{ ++ ASSERT_COND(h_Manip); ++ return ((t_FmPcdManip *)h_Manip)->h_Spinlock; ++} ++ ++t_Error FmPcdManipCheckParamsForCcNextEngine(t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, uint32_t *requiredAction) ++{ ++ t_FmPcdManip *p_Manip; ++ t_Error err; ++ bool pointFromCc = TRUE; ++ ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams->h_Manip, E_NULL_POINTER); ++ ++ p_Manip = (t_FmPcdManip *)(p_FmPcdCcNextEngineParams->h_Manip); ++ *requiredAction = 0; ++ ++ while (p_Manip) ++ { ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_CAPWAP_INDEXED_STATS): ++ if (p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE")); ++ if (p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid) ++ p_Manip->cnia = TRUE; ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ *requiredAction = UPDATE_NIA_ENQ_WITHOUT_DMA; ++ case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR): ++ p_Manip->ownerTmp++; ++ break; ++ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): ++ if ((p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE) && ++ !p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE with fqidForCtrlFlow FALSE")); ++ p_Manip->ownerTmp++; ++ break; ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ if ((p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_CC) && ++ (FmPcdCcGetParseCode(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode) != CC_PC_GENERIC_IC_HASH_INDEXED)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation next engine has to be CC and action = e_FM_PCD_ACTION_INDEXED_LOOKUP")); ++ err = UpdateManipIc(p_FmPcdCcNextEngineParams->h_Manip, FmPcdCcGetOffset(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode)); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ *requiredAction = UPDATE_NIA_ENQ_WITHOUT_DMA; ++ break; ++ case (HMAN_OC_IP_FRAGMENTATION): ++#if (DPAA_VERSION == 10) ++ if (!(p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_DONE)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE")); ++#else ++ if (!((p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_DONE) || ++ (p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_PLCR))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("For this type of header manipulation has to be nextEngine " ++ "e_FM_PCD_DONE or e_FM_PCD_PLCR")); ++#endif /* (DPAA_VERSION == 10) */ ++ p_Manip->ownerTmp++; ++ break; ++ case (HMAN_OC_IP_REASSEMBLY): ++ if (p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE")); ++ p_Manip->ownerTmp++; ++ break; ++ case (HMAN_OC_IPSEC_MANIP): ++ p_Manip->ownerTmp++; ++ break; ++ case (HMAN_OC): ++ if (( p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_CC) && MANIP_IS_CASCADE_NEXT(p_Manip)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't have a cascaded manipulation when and Next Engine is CC")); ++ if (!MANIP_IS_FIRST(p_Manip) && pointFromCc) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("h_Manip is already used and may not be shared (no sharing of non-head manip nodes)")); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE,("invalid type of header manipulation for this state")); ++ } ++ p_Manip = p_Manip->h_NextManip; ++ pointFromCc = FALSE; ++ } ++ return E_OK; ++} ++ ++ ++t_Error FmPcdManipCheckParamsWithCcNodeParams(t_Handle h_Manip, t_Handle h_FmPcdCcNode) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcNode, E_INVALID_HANDLE); ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_CAPWAP_INDEXED_STATS): ++ if (p_Manip->ownerTmp != FmPcdCcGetNumOfKeys(h_FmPcdCcNode)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("The manipulation of the type statistics flowId if exist has to be pointed by all numOfKeys")); ++ break; ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ if (p_Manip->h_Frag) ++ { ++ if (p_Manip->ownerTmp != FmPcdCcGetNumOfKeys(h_FmPcdCcNode)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("The manipulation of the type remove DTLS if exist has to be pointed by all numOfKeys")); ++ err = UpdateManipIc(h_Manip, FmPcdCcGetOffset(h_FmPcdCcNode)); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ return err; ++} ++ ++void FmPcdManipUpdateAdResultForCc(t_Handle h_Manip, ++ t_FmPcdCcNextEngineParams *p_CcNextEngineParams, ++ t_Handle p_Ad, ++ t_Handle *p_AdNewPtr) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ ++ ++ /* This routine creates a Manip AD and can return in "p_AdNewPtr" ++ * either the new descriptor or NULL if it writes the Manip AD into p_AD (into the match table) */ ++ ++ ASSERT_COND(p_Manip); ++ ASSERT_COND(p_CcNextEngineParams); ++ ASSERT_COND(p_Ad); ++ ASSERT_COND(p_AdNewPtr); ++ ++ FmPcdManipUpdateOwner(h_Manip, TRUE); ++ ++ /* According to "type", either build & initialize a new AD (p_AdNew) or initialize ++ * p_Ad ( the AD in the match table) and set p_AdNew = NULL. */ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR): ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ case (HMAN_OC_CAPWAP_INDEXED_STATS): ++ *p_AdNewPtr = p_Manip->h_Ad; ++ break; ++ case (HMAN_OC_IPSEC_MANIP): ++ *p_AdNewPtr = p_Manip->h_Ad; ++ break; ++ case (HMAN_OC_IP_FRAGMENTATION): ++ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_DONE) && ++ (!p_CcNextEngineParams->params.enqueueParams.overrideFqid)) ++ { ++ memcpy((uint8_t *)p_Ad, (uint8_t *)p_Manip->h_Ad, sizeof(t_AdOfTypeContLookup)); ++#if (DPAA_VERSION >= 11) ++ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, ++ GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase) & ~FM_PCD_MANIP_IP_CNIA); ++#endif /* (DPAA_VERSION >= 11) */ ++ *p_AdNewPtr = NULL; ++ } ++ else ++ *p_AdNewPtr = p_Manip->h_Ad; ++ break; ++ case (HMAN_OC_IP_REASSEMBLY): ++ if (FmPcdManipIpReassmIsIpv6Hdr(p_Manip)) ++ { ++ if (!p_Manip->ipReassmParams.ipv6Assigned) ++ { ++ *p_AdNewPtr = p_Manip->ipReassmParams.h_Ipv6Ad; ++ p_Manip->ipReassmParams.ipv6Assigned = TRUE; ++ FmPcdManipUpdateOwner(h_Manip, FALSE); ++ } ++ else ++ { ++ *p_AdNewPtr = p_Manip->ipReassmParams.h_Ipv4Ad; ++ p_Manip->ipReassmParams.ipv6Assigned = FALSE; ++ } ++ } ++ else ++ *p_AdNewPtr = p_Manip->ipReassmParams.h_Ipv4Ad; ++ memcpy((uint8_t *)p_Ad, (uint8_t *)*p_AdNewPtr, sizeof(t_AdOfTypeContLookup)); ++ *p_AdNewPtr = NULL; ++ break; ++ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): ++ case (HMAN_OC_CAPWAP_FRAGMENTATION): ++ WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->fqid, ((t_AdOfTypeResult *)(p_Manip->h_Ad))->fqid); ++ WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->plcrProfile, ((t_AdOfTypeResult *)(p_Manip->h_Ad))->plcrProfile); ++ WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->nia, ((t_AdOfTypeResult *)(p_Manip->h_Ad))->nia); ++ *p_AdNewPtr = NULL; ++ break; ++ case (HMAN_OC): ++ /* Allocate and initialize HMTD */ ++ *p_AdNewPtr = p_Manip->h_Ad; ++ break; ++ default: ++ break; ++ } ++} ++ ++void FmPcdManipUpdateAdContLookupForCc(t_Handle h_Manip, t_Handle p_Ad, t_Handle *p_AdNewPtr, uint32_t adTableOffset) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ ++ /* This routine creates a Manip AD and can return in "p_AdNewPtr" ++ * either the new descriptor or NULL if it writes the Manip AD into p_AD (into the match table) */ ++ ASSERT_COND(p_Manip); ++ ++ FmPcdManipUpdateOwner(h_Manip, TRUE); ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->ccAdBase); ++ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->matchTblPtr, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->matchTblPtr); ++ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->pcAndOffsets); ++ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->gmask, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->gmask); ++ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, (GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase) | adTableOffset)); ++ *p_AdNewPtr = NULL; ++ break; ++ ++ case (HMAN_OC): ++ /* Initialize HMTD within the match table*/ ++ IOMemSet32(p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ /* copy the existing HMTD */ /* ask Alla - memcpy??? */ ++ memcpy((uint8_t*)p_Ad, p_Manip->h_Ad, sizeof(t_Hmtd)); ++ /* update NADEN to be "1"*/ ++ WRITE_UINT16(((t_Hmtd *)p_Ad)->cfg, ++ (uint16_t)(GET_UINT16(((t_Hmtd *)p_Ad)->cfg) | HMTD_CFG_NEXT_AD_EN)); ++ /* update next action descriptor */ ++ WRITE_UINT16(((t_Hmtd *)p_Ad)->nextAdIdx, (uint16_t)(adTableOffset >> 4)); ++ /* mark that Manip's HMTD is not used */ ++ *p_AdNewPtr = NULL; ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++t_Error FmPcdManipBuildIpReassmScheme(t_FmPcd *p_FmPcd, t_Handle h_NetEnv, t_Handle h_CcTree, t_Handle h_Manip, bool isIpv4, uint8_t groupId) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ t_FmPcdKgSchemeParams *p_SchemeParams = NULL; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(h_NetEnv); ++ ASSERT_COND(p_Manip); ++ ++ /* scheme was already build, no need to check for IPv6 */ ++ if (p_Manip->ipReassmParams.h_Ipv4Scheme) ++ return E_OK; ++ ++ p_SchemeParams = XX_Malloc(sizeof(t_FmPcdKgSchemeParams)); ++ if (!p_SchemeParams) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation failed for scheme")); ++ ++ /* Configures the IPv4 or IPv6 scheme*/ ++ memset(p_SchemeParams, 0, sizeof(t_FmPcdKgSchemeParams)); ++ p_SchemeParams->netEnvParams.h_NetEnv = h_NetEnv; ++ p_SchemeParams->id.relativeSchemeId = ++ (uint8_t)((isIpv4 == TRUE) ? ++ p_Manip->ipReassmParams.relativeSchemeId[0] : ++ p_Manip->ipReassmParams.relativeSchemeId[1]); ++ p_SchemeParams->schemeCounter.update = TRUE; ++#if (DPAA_VERSION >= 11) ++ p_SchemeParams->alwaysDirect = TRUE; ++ p_SchemeParams->bypassFqidGeneration = TRUE; ++#else ++ p_SchemeParams->keyExtractAndHashParams.hashDistributionNumOfFqids = 1; ++ p_SchemeParams->baseFqid = 0xFFFFFF; /*TODO- baseFqid*/ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ setReassmSchemeParams(p_FmPcd, p_SchemeParams, h_CcTree, isIpv4, groupId); ++ ++ /* Sets the new scheme */ ++ if (isIpv4) ++ p_Manip->ipReassmParams.h_Ipv4Scheme = FM_PCD_KgSchemeSet(p_FmPcd, p_SchemeParams); ++ else ++ p_Manip->ipReassmParams.h_Ipv6Scheme = FM_PCD_KgSchemeSet(p_FmPcd, p_SchemeParams); ++ ++ XX_Free(p_SchemeParams); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdManipDeleteIpReassmSchemes(t_Handle h_Manip) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ ++ ASSERT_COND(p_Manip); ++ ++ if (p_Manip->ipReassmParams.h_Ipv4Scheme) ++ FM_PCD_KgSchemeDelete(p_Manip->ipReassmParams.h_Ipv4Scheme); ++ ++ if (p_Manip->ipReassmParams.h_Ipv6Scheme) ++ FM_PCD_KgSchemeDelete(p_Manip->ipReassmParams.h_Ipv6Scheme); ++ ++ return E_OK; ++} ++ ++bool FmPcdManipIpReassmIsIpv6Hdr(t_Handle h_Manip) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ ++ ASSERT_COND(p_Manip); ++ ++ return (p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv6); ++} ++ ++#ifdef FM_CAPWAP_SUPPORT ++t_Handle FmPcdManipApplSpecificBuild(void) ++{ ++ t_FmPcdManip *p_Manip; ++ ++ p_Manip = (t_FmPcdManip*)XX_Malloc(sizeof(t_FmPcdManip)); ++ if (!p_Manip) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); ++ return NULL; ++ } ++ memset(p_Manip, 0, sizeof(t_FmPcdManip)); ++ ++ p_Manip->opcode = HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX; ++ p_Manip->muramAllocate = FALSE; ++ ++ p_Manip->h_Ad = (t_Handle)XX_Malloc(FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t)); ++ if (!p_Manip->h_Ad) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of Manipulation action descriptor")); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ memset(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t)); ++ ++ /*treatFdStatusFieldsAsErrors = TRUE hardcoded - assumption its always come after CAAM*/ ++ /*Application specific = type of flowId index, move internal frame header from data to IC, ++ SEC errors check*/ ++ if (MvIntFrameHeaderFromFrameToBufferPrefix(p_Manip, TRUE)!= E_OK) ++ { ++ XX_Free(p_Manip->h_Ad); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ return p_Manip; ++} ++ ++bool FmPcdManipIsCapwapApplSpecific(t_Handle h_Manip) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ ASSERT_COND(h_Manip); ++ ++ return (bool)((p_Manip->opcode == HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST) ? TRUE : FALSE); ++} ++#endif /* FM_CAPWAP_SUPPORT */ ++/*********************** End of inter-module routines ************************/ ++ ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++ ++t_Handle FM_PCD_ManipNodeSet(t_Handle h_FmPcd, t_FmPcdManipParams *p_ManipParams) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdManip *p_Manip; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE,NULL); ++ SANITY_CHECK_RETURN_VALUE(p_ManipParams,E_INVALID_HANDLE,NULL); ++ ++ p_Manip = ManipOrStatsSetNode(h_FmPcd, (t_Handle)p_ManipParams, FALSE); ++ if (!p_Manip) ++ return NULL; ++ ++ if (((p_Manip->opcode == HMAN_OC_IP_REASSEMBLY) || ++ (p_Manip->opcode == HMAN_OC_IP_FRAGMENTATION) || ++ (p_Manip->opcode == HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX) || ++ (p_Manip->opcode == HMAN_OC) || ++ (p_Manip->opcode == HMAN_OC_IPSEC_MANIP)) && ++ (!FmPcdIsAdvancedOffloadSupported(p_FmPcd))) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Advanced-offload must be enabled")); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ p_Manip->h_Spinlock = XX_InitSpinlock(); ++ if (!p_Manip->h_Spinlock) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ INIT_LIST(&p_Manip->nodesLst); ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_IP_REASSEMBLY): ++ /* IpReassembly */ ++ err = IpReassembly(&p_ManipParams->u.reassem, p_Manip); ++ break; ++ case (HMAN_OC_IP_FRAGMENTATION): ++ /* IpFragmentation */ ++ err = IpFragmentation(&p_ManipParams->u.frag.u.ipFrag ,p_Manip); ++ if (err) ++ break; ++ err = IPManip(p_Manip); ++ break; ++ case (HMAN_OC_IPSEC_MANIP) : ++ err = IPSecManip(p_ManipParams, p_Manip); ++ break; ++#ifdef FM_CAPWAP_SUPPORT ++ case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR): ++ /* HmanType1 */ ++ err = RmvHdrTillSpecLocNOrInsrtIntFrmHdr(&p_ManipParams->u.hdr.rmvParams, p_Manip); ++ break; ++ case (HMAN_OC_CAPWAP_FRAGMENTATION): ++ err = CapwapFragmentation(&p_ManipParams->fragOrReasmParams.u.capwapFragParams, ++ p_Manip, ++ p_FmPcd, ++ p_ManipParams->fragOrReasmParams.sgBpid); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ if (p_Manip->insrt) ++ p_Manip->opcode = HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER; ++ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): ++ /* HmanType2 + if user asked only for fragmentation still need to allocate HmanType2 */ ++ err = InsrtHdrByTempl(&p_ManipParams->u.hdr.insrtParams, p_Manip, p_FmPcd); ++ break; ++ case (HMAN_OC_CAPWAP_REASSEMBLY): ++ err = CapwapReassembly(&p_ManipParams->fragOrReasmParams.u.capwapReasmParams, ++ p_Manip, ++ p_FmPcd, ++ p_ManipParams->fragOrReasmParams.sgBpid); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ if (p_Manip->rmv) ++ p_Manip->opcode = HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST; ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ /*CAPWAP decapsulation + if user asked only for reassembly still need to allocate CAPWAP decapsulation*/ ++ err = CapwapRmvDtlsHdr(p_FmPcd, p_Manip); ++ break; ++#endif /* FM_CAPWAP_SUPPORT */ ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ /*Application Specific type 1*/ ++ err = MvIntFrameHeaderFromFrameToBufferPrefix(p_Manip, TRUE); ++ break; ++ case (HMAN_OC): ++ /* New Manip */ ++ err = CreateManipActionNew(p_Manip, p_ManipParams); ++ break; ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ if (p_ManipParams->h_NextManip) ++ { ++ /* in the check routine we've verified that h_NextManip has no owners ++ * and that only supported types are allowed. */ ++ p_Manip->h_NextManip = p_ManipParams->h_NextManip; ++ /* save a "prev" pointer in h_NextManip */ ++ MANIP_SET_PREV(p_Manip->h_NextManip, p_Manip); ++ FmPcdManipUpdateOwner(p_Manip->h_NextManip, TRUE); ++ } ++ ++ return p_Manip; ++} ++ ++t_Error FM_PCD_ManipNodeReplace(t_Handle h_Manip, t_FmPcdManipParams *p_ManipParams) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip, *p_FirstManip; ++ t_FmPcd *p_FmPcd = (t_FmPcd *)(p_Manip->h_FmPcd); ++ t_Error err; ++ uint8_t *p_WholeHmct = NULL, *p_ShadowHmct = NULL, *p_Hmtd = NULL; ++ t_List lstOfNodeshichPointsOnCrntMdfManip, *p_Pos; ++ t_CcNodeInformation *p_CcNodeInfo; ++ SANITY_CHECK_RETURN_ERROR(h_Manip,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_INVALID_HANDLE); ++ ++ INIT_LIST(&lstOfNodeshichPointsOnCrntMdfManip); ++ ++ if ((p_ManipParams->type != e_FM_PCD_MANIP_HDR) || ++ (p_Manip->type != e_FM_PCD_MANIP_HDR)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("FM_PCD_ManipNodeReplace Functionality supported only for Header Manipulation.")); ++ ++ ASSERT_COND(p_Manip->opcode == HMAN_OC); ++ ASSERT_COND(p_Manip->manipParams.h_NextManip == p_Manip->h_NextManip); ++ memcpy((uint8_t*)&p_Manip->manipParams, p_ManipParams, sizeof(p_Manip->manipParams)); ++ p_Manip->manipParams.h_NextManip = p_Manip->h_NextManip; ++ ++ /* The replacement of the HdrManip depends on the node type.*/ ++ /* ++ * (1) If this is an independent node, all its owners should be updated. ++ * ++ * (2) If it is the head of a cascaded chain (it does not have a "prev" but ++ * it has a "next" and it has a "cascaded-next" indication), the next ++ * node remains unchanged, and the behavior is as in (1). ++ * ++ * (3) If it is not the head, but a part of a cascaded chain, in can be ++ * also replaced as a regular node with just one owner. ++ * ++ * (4) If it is a part of a chain implemented as a unified table, the ++ * whole table is replaced and the owners of the head node must be updated. ++ * ++ */ ++ /* lock shadow */ ++ if (!p_FmPcd->p_CcShadow) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated")); ++ ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ return ERROR_CODE(E_BUSY); ++ ++ /* this routine creates a new manip action in the CC Shadow. */ ++ err = CreateManipActionShadow(p_Manip, p_ManipParams); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ /* If the owners list is empty (these are NOT the "owners" counter, but pointers from CC) ++ * replace only HMTD and no lcok is required. Otherwise ++ * lock the whole PCD ++ * In case 4 MANIP_IS_UNIFIED_NON_FIRST(p_Manip) - Use the head node instead. */ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ p_ShadowHmct = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, 16); ++ ++ p_FirstManip = (t_FmPcdManip*)GetManipInfo(p_Manip, e_MANIP_HANDLER_TABLE_OWNER); ++ ASSERT_COND(p_FirstManip); ++ ++ if (!LIST_IsEmpty(&p_FirstManip->nodesLst)) ++ UpdateAdPtrOfNodesWhichPointsOnCrntMdfManip(p_FirstManip, &lstOfNodeshichPointsOnCrntMdfManip); ++ ++ p_Hmtd = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMTD); ++ ASSERT_COND(p_Hmtd); ++ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_Hmtd, p_ShadowHmct, ((t_FmPcd*)(p_Manip->h_FmPcd))); ++ ++ LIST_FOR_EACH(p_Pos, &lstOfNodeshichPointsOnCrntMdfManip) ++ { ++ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos); ++ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_CcNodeInfo->h_CcNode, p_ShadowHmct, ((t_FmPcd*)(p_Manip->h_FmPcd))); ++ } ++ ++ p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT); ++ ASSERT_COND(p_WholeHmct); ++ ++ /* re-build the HMCT n the original location */ ++ err = CreateManipActionBackToOrig(p_Manip, p_ManipParams); ++ if (err) ++ { ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ p_Hmtd = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMTD); ++ ASSERT_COND(p_Hmtd); ++ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_Hmtd, p_WholeHmct,((t_FmPcd*)p_Manip->h_FmPcd)); ++ ++ /* If LIST > 0, create a list of p_Ad's that point to the HMCT. Join also t_HMTD to this list. ++ * For each p_Hmct (from list+fixed): ++ * call Host Command to replace HMTD by a new one */ ++ LIST_FOR_EACH(p_Pos, &lstOfNodeshichPointsOnCrntMdfManip) ++ { ++ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos); ++ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_CcNodeInfo->h_CcNode, p_WholeHmct, ((t_FmPcd*)(p_Manip->h_FmPcd))); ++ } ++ ++ ++ ReleaseLst(&lstOfNodeshichPointsOnCrntMdfManip); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ /* unlock shadow */ ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ManipNodeDelete(t_Handle h_ManipNode) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_ManipNode; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); ++ ++ if (p_Manip->owner) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("This manipulation node not be removed because this node is occupied, first - unbind this node ")); ++ ++ if (p_Manip->h_NextManip) ++ { ++ MANIP_SET_PREV(p_Manip->h_NextManip, NULL); ++ FmPcdManipUpdateOwner(p_Manip->h_NextManip, FALSE); ++ } ++ ++ if (p_Manip->p_Hmct && MANIP_IS_UNIFIED_FIRST(p_Manip)) ++ FM_MURAM_FreeMem(((t_FmPcd *)p_Manip->h_FmPcd)->h_FmMuram, p_Manip->p_Hmct); ++ ++ if (p_Manip->h_Spinlock) ++ { ++ XX_FreeSpinlock(p_Manip->h_Spinlock); ++ p_Manip->h_Spinlock = NULL; ++ } ++ ++ ReleaseManipHandler(p_Manip, p_Manip->h_FmPcd); ++ ++ XX_Free(h_ManipNode); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ManipGetStatistics(t_Handle h_ManipNode, t_FmPcdManipStats *p_FmPcdManipStats) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_ManipNode; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdManipStats, E_NULL_POINTER); ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_IP_REASSEMBLY): ++ return IpReassemblyStats(p_Manip, &p_FmPcdManipStats->u.reassem.u.ipReassem); ++ case (HMAN_OC_IP_FRAGMENTATION): ++ return IpFragmentationStats(p_Manip, &p_FmPcdManipStats->u.frag.u.ipFrag); ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("no statistics to this type of manip")); ++ } ++ ++ return E_OK; ++} ++ ++#ifdef FM_CAPWAP_SUPPORT ++t_Handle FM_PCD_StatisticsSetNode(t_Handle h_FmPcd, t_FmPcdStatsParams *p_StatsParams) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdManip *p_Manip; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE,NULL); ++ SANITY_CHECK_RETURN_VALUE(p_StatsParams,E_INVALID_HANDLE,NULL); ++ ++ p_Manip = ManipOrStatsSetNode(h_FmPcd, (t_Handle)p_StatsParams, TRUE); ++ if (!p_Manip) ++ return NULL; ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_CAPWAP_INDEXED_STATS): ++ /* Indexed statistics */ ++ err = IndxStats(p_StatsParams, p_Manip, p_FmPcd); ++ break; ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED Statistics type")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ return p_Manip; ++} ++#endif /* FM_CAPWAP_SUPPORT */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_manip.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_manip.h +new file mode 100644 +index 0000000..390ca6e +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_manip.h +@@ -0,0 +1,480 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_manip.h ++ ++ @Description FM PCD manip... ++*//***************************************************************************/ ++#ifndef __FM_MANIP_H ++#define __FM_MANIP_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++ ++#include "fm_cc.h" ++ ++ ++/***********************************************************************/ ++/* Header manipulations defines */ ++/***********************************************************************/ ++ ++#define NUM_OF_SCRATCH_POOL_BUFFERS 1000 /*TODO - Change it!!*/ ++ ++#define HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR 0x2e ++#define HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER 0x31 ++#define HMAN_OC_CAPWAP_FRAGMENTATION 0x33 ++#define HMAN_OC_IP_MANIP 0x34 ++#define HMAN_OC_IP_FRAGMENTATION 0x74 ++#define HMAN_OC_IP_REASSEMBLY 0xB4 ++#define HMAN_OC_IPSEC_MANIP 0xF4 ++#define HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX 0x2f ++#define HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST 0x30 ++#define HMAN_OC_CAPWAP_REASSEMBLY 0x11 /* dummy */ ++#define HMAN_OC_CAPWAP_INDEXED_STATS 0x32 /* dummy */ ++#define HMAN_OC 0x35 ++ ++#define HMAN_RMV_HDR 0x80000000 ++#define HMAN_INSRT_INT_FRM_HDR 0x40000000 ++ ++#define UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP 6 ++#define UDP_CHECKSUM_FIELD_SIZE 2 ++#define UDP_LENGTH_FIELD_OFFSET_FROM_UDP 4 ++ ++#define IPv4_DSCECN_FIELD_OFFSET_FROM_IP 1 ++#define IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP 2 ++#define IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP 10 ++#define VLAN_TAG_FIELD_OFFSET_FROM_ETH 12 ++#define IPv4_ID_FIELD_OFFSET_FROM_IP 4 ++ ++#define IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP 4 ++#define IPv6_NEXT_HEADER_OFFSET_FROM_IP 6 ++ ++#define FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE 0x80 ++#define FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN 8 ++#define FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE 32 ++#define FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE 4 ++#define FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE 8 ++ ++ ++#define FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_BETWEEN_FRAMES 0x40000000 ++#define FM_PCD_MANIP_CAPWAP_REASM_HALT_ON_DUPLICATE_FRAG 0x10000000 ++#define FM_PCD_MANIP_CAPWAP_REASM_AUTOMATIC_LEARNIN_HASH_8_WAYS 0x08000000 ++#define FM_PCD_MANIP_CAPWAP_REASM_PR_COPY 0x00800000 ++ ++#define FM_PCD_MANIP_CAPWAP_FRAG_COMPR_OPTION_FIELD_EN 0x80000000 ++ ++#define FM_PCD_MANIP_INDEXED_STATS_ENTRY_SIZE 4 ++#define FM_PCD_MANIP_INDEXED_STATS_CNIA 0x20000000 ++#define FM_PCD_MANIP_INDEXED_STATS_DPD 0x10000000 ++ ++#define FM_PCD_MANIP_IP_REASM_TABLE_SIZE 0x40 ++#define FM_PCD_MANIP_IP_REASM_TABLE_ALIGN 8 ++ ++#define FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_SIZE 64 ++#define FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_ALIGN 8 ++#define FM_PCD_MANIP_IP_REASM_TIME_OUT_BETWEEN_FRAMES 0x80000000 ++#define FM_PCD_MANIP_IP_REASM_COUPLING_ENABLE 0x40000000 ++#define FM_PCD_MANIP_IP_REASM_COUPLING_MASK 0xFF000000 ++#define FM_PCD_MANIP_IP_REASM_COUPLING_SHIFT 24 ++#define FM_PCD_MANIP_IP_REASM_LIODN_MASK 0x0000003F ++#define FM_PCD_MANIP_IP_REASM_LIODN_SHIFT 56 ++#define FM_PCD_MANIP_IP_REASM_ELIODN_MASK 0x000003c0 ++#define FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT 38 ++#define FM_PCD_MANIP_IP_REASM_COMMON_INT_BUFFER_IDX_MASK 0x000000FF ++#define FM_PCD_MANIP_IP_REASM_COMMON_INT_BUFFER_IDX_SHIFT 24 ++ ++#define FM_PCD_MANIP_IP_MTU_SHIFT 16 ++#define FM_PCD_MANIP_IP_NO_FRAGMENTATION 0xFFFF0000 ++#define FM_PCD_MANIP_IP_CNIA 0x20000000 ++ ++#define FM_PCD_MANIP_IP_REASSM_TIMEOUT_THREAD_THRESH 1024 ++#define FM_PCD_MANIP_IP_FRAG_DF_SHIFT 28 ++#define FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID 24 ++#define FM_PCD_MANIP_IP_FRAG_SG_BDID_EN 0x08000000 ++#define FM_PCD_MANIP_IP_FRAG_SG_BDID_MASK 0xFF000000 ++#define FM_PCD_MANIP_IP_FRAG_SG_BDID_SHIFT 24 ++ ++#define FM_PCD_MANIP_IPSEC_DEC 0x10000000 ++#define FM_PCD_MANIP_IPSEC_VIPV_EN 0x08000000 ++#define FM_PCD_MANIP_IPSEC_ECN_EN 0x04000000 ++#define FM_PCD_MANIP_IPSEC_DSCP_EN 0x02000000 ++#define FM_PCD_MANIP_IPSEC_VIPL_EN 0x01000000 ++#define FM_PCD_MANIP_IPSEC_NADEN 0x20000000 ++ ++#define FM_PCD_MANIP_IPSEC_IP_HDR_LEN_MASK 0x00FF0000 ++#define FM_PCD_MANIP_IPSEC_IP_HDR_LEN_SHIFT 16 ++ ++#define e_FM_MANIP_IP_INDX 1 ++ ++#define HMCD_OPCODE_GENERIC_RMV 0x01 ++#define HMCD_OPCODE_GENERIC_INSRT 0x02 ++#define HMCD_OPCODE_GENERIC_REPLACE 0x05 ++#define HMCD_OPCODE_L2_RMV 0x08 ++#define HMCD_OPCODE_L2_INSRT 0x09 ++#define HMCD_OPCODE_VLAN_PRI_UPDATE 0x0B ++#define HMCD_OPCODE_IPV4_UPDATE 0x0C ++#define HMCD_OPCODE_IPV6_UPDATE 0x10 ++#define HMCD_OPCODE_TCP_UDP_UPDATE 0x0E ++#define HMCD_OPCODE_TCP_UDP_CHECKSUM 0x14 ++#define HMCD_OPCODE_REPLACE_IP 0x12 ++ ++#define HMCD_DSCP_VALUES 64 ++ ++#define HMCD_BASIC_SIZE 4 ++#define HMCD_PTR_SIZE 4 ++#define HMCD_PARAM_SIZE 4 ++#define HMCD_IPV4_ADDR_SIZE 4 ++#define HMCD_IPV6_ADDR_SIZE 0x10 ++ ++#define HMCD_LAST 0x00800000 ++ ++#define HMCD_OC_SHIFT 24 ++ ++#define HMCD_RMV_OFFSET_SHIFT 0 ++#define HMCD_RMV_SIZE_SHIFT 8 ++ ++#define HMCD_INSRT_OFFSET_SHIFT 0 ++#define HMCD_INSRT_SIZE_SHIFT 8 ++ ++#define HMTD_CFG_TYPE 0x4000 ++#define HMTD_CFG_EXT_HMCT 0x0080 ++#define HMTD_CFG_PRS_AFTER_HM 0x0040 ++#define HMTD_CFG_NEXT_AD_EN 0x0020 ++ ++#define HMCD_RMV_L2_ETHERNET 0 ++#define HMCD_RMV_L2_STACKED_QTAGS 1 ++#define HMCD_RMV_L2_ETHERNET_AND_MPLS 2 ++#define HMCD_RMV_L2_MPLS 3 ++ ++#define HMCD_INSRT_L2_MPLS 0 ++#define HMCD_INSRT_N_UPDATE_L2_MPLS 1 ++#define HMCD_INSRT_L2_SIZE_SHIFT 24 ++ ++#define HMCD_L2_MODE_SHIFT 16 ++ ++#define HMCD_VLAN_PRI_REP_MODE_SHIFT 16 ++#define HMCD_VLAN_PRI_UPDATE 0 ++#define HMCD_VLAN_PRI_UPDATE_DSCP_TO_VPRI 1 ++ ++#define HMCD_IPV4_UPDATE_TTL 0x00000001 ++#define HMCD_IPV4_UPDATE_TOS 0x00000002 ++#define HMCD_IPV4_UPDATE_DST 0x00000020 ++#define HMCD_IPV4_UPDATE_SRC 0x00000040 ++#define HMCD_IPV4_UPDATE_ID 0x00000080 ++#define HMCD_IPV4_UPDATE_TOS_SHIFT 8 ++ ++#define HMCD_IPV6_UPDATE_HL 0x00000001 ++#define HMCD_IPV6_UPDATE_TC 0x00000002 ++#define HMCD_IPV6_UPDATE_DST 0x00000040 ++#define HMCD_IPV6_UPDATE_SRC 0x00000080 ++#define HMCD_IPV6_UPDATE_TC_SHIFT 8 ++ ++#define HMCD_TCP_UDP_UPDATE_DST 0x00004000 ++#define HMCD_TCP_UDP_UPDATE_SRC 0x00008000 ++#define HMCD_TCP_UDP_UPDATE_SRC_SHIFT 16 ++ ++#define HMCD_IP_REPLACE_REPLACE_IPV4 0x00000000 ++#define HMCD_IP_REPLACE_REPLACE_IPV6 0x00010000 ++#define HMCD_IP_REPLACE_TTL_HL 0x00200000 ++#define HMCD_IP_REPLACE_ID 0x00400000 ++ ++#define HMCD_IP_REPLACE_L3HDRSIZE_SHIFT 24 ++ ++#define DSCP_TO_VLAN_TABLE_SIZE 32 ++ ++#define MANIP_GET_HMCT_SIZE(h_Manip) (((t_FmPcdManip *)h_Manip)->tableSize) ++#define MANIP_GET_DATA_SIZE(h_Manip) (((t_FmPcdManip *)h_Manip)->dataSize) ++ ++#define MANIP_GET_HMCT_PTR(h_Manip) (((t_FmPcdManip *)h_Manip)->p_Hmct) ++#define MANIP_GET_DATA_PTR(h_Manip) (((t_FmPcdManip *)h_Manip)->p_Data) ++ ++#define MANIP_SET_HMCT_PTR(h_Manip, h_NewPtr) (((t_FmPcdManip *)h_Manip)->p_Hmct = h_NewPtr) ++#define MANIP_SET_DATA_PTR(h_Manip, h_NewPtr) (((t_FmPcdManip *)h_Manip)->p_Data = h_NewPtr) ++ ++#define MANIP_GET_HMTD_PTR(h_Manip) (((t_FmPcdManip *)h_Manip)->h_Ad) ++#define MANIP_DONT_REPARSE(h_Manip) (((t_FmPcdManip *)h_Manip)->dontParseAfterManip) ++#define MANIP_SET_PREV(h_Manip, h_Prev) (((t_FmPcdManip *)h_Manip)->h_PrevManip = h_Prev) ++#define MANIP_GET_OWNERS(h_Manip) (((t_FmPcdManip *)h_Manip)->owner) ++#define MANIP_GET_TYPE(h_Manip) (((t_FmPcdManip *)h_Manip)->type) ++#define MANIP_SET_UNIFIED_TBL_PTR_INDICATION(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedTablePtr = TRUE) ++#define MANIP_GET_MURAM(h_Manip) (((t_FmPcd *)((t_FmPcdManip *)h_Manip)->h_FmPcd)->h_FmMuram) ++#define MANIP_FREE_HMTD(h_Manip) \ ++ {if (((t_FmPcdManip *)h_Manip)->muramAllocate) \ ++ FM_MURAM_FreeMem(((t_FmPcd *)((t_FmPcdManip *)h_Manip)->h_FmPcd)->h_FmMuram, ((t_FmPcdManip *)h_Manip)->h_Ad);\ ++ else \ ++ XX_Free(((t_FmPcdManip *)h_Manip)->h_Ad); \ ++ ((t_FmPcdManip *)h_Manip)->h_Ad = NULL; \ ++ } ++/* position regarding Manip SW structure */ ++#define MANIP_IS_FIRST(h_Manip) (!(((t_FmPcdManip *)h_Manip)->h_PrevManip)) ++#define MANIP_IS_CASCADE_NEXT(h_Manip) (((t_FmPcdManip *)h_Manip)->cascadedNext) ++#define MANIP_IS_UNIFIED(h_Manip) (!(((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_NONE)) ++#define MANIP_IS_UNIFIED_NON_FIRST(h_Manip) ((((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_MID) || \ ++ (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_LAST)) ++#define MANIP_IS_UNIFIED_NON_LAST(h_Manip) ((((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_FIRST) ||\ ++ (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_MID)) ++#define MANIP_IS_UNIFIED_FIRST(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_FIRST) ++#define MANIP_IS_UNIFIED_LAST(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_LAST) ++ ++#define MANIP_UPDATE_UNIFIED_POSITION(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedPosition = \ ++ (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_NONE)? \ ++ e_MANIP_UNIFIED_LAST : e_MANIP_UNIFIED_MID) ++ ++typedef enum e_ManipUnifiedPosition { ++ e_MANIP_UNIFIED_NONE = 0, ++ e_MANIP_UNIFIED_FIRST, ++ e_MANIP_UNIFIED_MID, ++ e_MANIP_UNIFIED_LAST ++} e_ManipUnifiedPosition; ++ ++typedef enum e_ManipInfo { ++ e_MANIP_HMTD, ++ e_MANIP_HMCT, ++ e_MANIP_HANDLER_TABLE_OWNER ++}e_ManipInfo; ++/***********************************************************************/ ++/* Memory map */ ++/***********************************************************************/ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++typedef _Packed struct t_CapwapReasmPram { ++ volatile uint32_t mode; ++ volatile uint32_t autoLearnHashTblPtr; ++ volatile uint32_t intStatsTblPtr; ++ volatile uint32_t reasmFrmDescPoolTblPtr; ++ volatile uint32_t reasmFrmDescIndexPoolTblPtr; ++ volatile uint32_t timeOutTblPtr; ++ volatile uint32_t bufferPoolIdAndRisc1SetIndexes; ++ volatile uint32_t risc23SetIndexes; ++ volatile uint32_t risc4SetIndexesAndExtendedStatsTblPtr; ++ volatile uint32_t extendedStatsTblPtr; ++ volatile uint32_t expirationDelay; ++ volatile uint32_t totalProcessedFragCounter; ++ volatile uint32_t totalUnsuccessfulReasmFramesCounter; ++ volatile uint32_t totalDuplicatedFragCounter; ++ volatile uint32_t totalMalformdFragCounter; ++ volatile uint32_t totalTimeOutCounter; ++ volatile uint32_t totalSetBusyCounter; ++ volatile uint32_t totalRfdPoolBusyCounter; ++ volatile uint32_t totalDiscardedFragsCounter; ++ volatile uint32_t totalMoreThan16FramesCounter; ++ volatile uint32_t internalBufferBusy; ++ volatile uint32_t externalBufferBusy; ++ volatile uint32_t reserved1[4]; ++} _PackedType t_CapwapReasmPram; ++ ++typedef _Packed struct t_IpReassTbl { ++ volatile uint16_t waysNumAndSetSize; ++ volatile uint16_t autoLearnHashKeyMask; ++ volatile uint32_t ipReassCommonPrmTblPtr; ++ volatile uint32_t liodnAlAndAutoLearnHashTblPtrHi; ++ volatile uint32_t autoLearnHashTblPtrLow; ++ volatile uint32_t liodnSlAndAutoLearnSetLockTblPtrHi; ++ volatile uint32_t autoLearnSetLockTblPtrLow; ++ volatile uint16_t minFragSize; ++ volatile uint16_t reserved1; ++ volatile uint32_t totalSuccessfullyReasmFramesCounter; ++ volatile uint32_t totalValidFragmentCounter; ++ volatile uint32_t totalProcessedFragCounter; ++ volatile uint32_t totalMalformdFragCounter; ++ volatile uint32_t totalSetBusyCounter; ++ volatile uint32_t totalDiscardedFragsCounter; ++ volatile uint32_t totalMoreThan16FramesCounter; ++ volatile uint32_t reserved2[2]; ++} _PackedType t_IpReassTbl; ++ ++typedef _Packed struct t_IpReassCommonTbl { ++ volatile uint32_t timeoutModeAndFqid; ++ volatile uint32_t reassFrmDescIndexPoolTblPtr; ++ volatile uint32_t liodnAndReassFrmDescPoolPtrHi; ++ volatile uint32_t reassFrmDescPoolPtrLow; ++ volatile uint32_t timeOutTblPtr; ++ volatile uint32_t expirationDelay; ++ volatile uint32_t internalBufferManagement; ++ volatile uint32_t reserved2; ++ volatile uint32_t totalTimeOutCounter; ++ volatile uint32_t totalRfdPoolBusyCounter; ++ volatile uint32_t totalInternalBufferBusy; ++ volatile uint32_t totalExternalBufferBusy; ++ volatile uint32_t totalSgFragmentCounter; ++ volatile uint32_t totalDmaSemaphoreDepletionCounter; ++ volatile uint32_t reserved3[2]; ++} _PackedType t_IpReassCommonTbl; ++ ++typedef _Packed struct t_Hmtd { ++ volatile uint16_t cfg; ++ volatile uint8_t eliodnOffset; ++ volatile uint8_t extHmcdBasePtrHi; ++ volatile uint32_t hmcdBasePtr; ++ volatile uint16_t nextAdIdx; ++ volatile uint8_t res1; ++ volatile uint8_t opCode; ++ volatile uint32_t res2; ++} _PackedType t_Hmtd; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/***********************************************************************/ ++/* Driver's internal structures */ ++/***********************************************************************/ ++typedef struct ++{ ++ t_Handle p_AutoLearnHashTbl; ++ t_Handle p_ReassmFrmDescrPoolTbl; ++ t_Handle p_ReassmFrmDescrIndxPoolTbl; ++ t_Handle p_TimeOutTbl; ++ uint16_t maxNumFramesInProcess; ++ uint8_t numOfTasks; ++ //uint8_t poolId; ++ uint8_t prOffset; ++ uint16_t dataOffset; ++ uint8_t sgBpid; ++ uint8_t hwPortId; ++ uint32_t fqidForTimeOutFrames; ++ uint32_t timeoutRoutineRequestTime; ++ uint32_t bitFor1Micro; ++} t_FragParams; ++ ++typedef struct ++{ ++ t_AdOfTypeContLookup *p_Frag; ++#if (DPAA_VERSION == 10) ++ uint8_t scratchBpid; ++#endif /* (DPAA_VERSION == 10) */ ++} t_IpFragParams; ++ ++typedef struct t_IpReassmParams ++{ ++ t_Handle h_Ipv4Ad; ++ t_Handle h_Ipv6Ad; ++ bool ipv6Assigned; ++ e_NetHeaderType hdr; /* Header selection */ ++ t_IpReassCommonTbl *p_IpReassCommonTbl; ++ t_IpReassTbl *p_Ipv4ReassTbl; ++ t_IpReassTbl *p_Ipv6ReassTbl; ++ uintptr_t ipv4AutoLearnHashTblAddr; ++ uintptr_t ipv6AutoLearnHashTblAddr; ++ uintptr_t ipv4AutoLearnSetLockTblAddr; ++ uintptr_t ipv6AutoLearnSetLockTblAddr; ++ uintptr_t reassFrmDescrIndxPoolTblAddr; ++ uintptr_t reassFrmDescrPoolTblAddr; ++ uintptr_t timeOutTblAddr; ++ uintptr_t internalBufferPoolManagementIndexAddr; ++ uintptr_t internalBufferPoolAddr; ++ uint32_t maxNumFramesInProcess; ++ uint8_t sgBpid; ++ uint8_t dataMemId; ++ uint16_t dataLiodnOffset; ++ uint32_t fqidForTimeOutFrames; ++ e_FmPcdManipReassemTimeOutMode timeOutMode; ++ uint32_t timeoutThresholdForReassmProcess; ++ uint16_t minFragSize[2]; ++ e_FmPcdManipReassemWaysNumber numOfFramesPerHashEntry[2]; ++ uint8_t relativeSchemeId[2]; ++ t_Handle h_Ipv4Scheme; ++ t_Handle h_Ipv6Scheme; ++ uint32_t nonConsistentSpFqid; ++} t_IpReassmParams; ++ ++ ++typedef struct{ ++ e_FmPcdManipType type; ++ t_FmPcdManipParams manipParams; ++ bool muramAllocate; ++ t_Handle h_Ad; ++ uint32_t opcode; ++ bool rmv; ++ bool insrt; ++ t_Handle h_NextManip; ++ t_Handle h_PrevManip; ++ /* HdrManip parameters*/ ++ uint8_t *p_Hmct; ++ uint8_t *p_Data; ++ bool dontParseAfterManip; ++ bool fieldUpdate; ++ bool custom; ++ uint16_t tableSize; ++ uint8_t dataSize; ++ bool cascadedNext; ++ e_ManipUnifiedPosition unifiedPosition; ++ /* end HdrManip */ ++ uint8_t *p_Template; ++ t_Handle h_Frag; ++ bool frag; ++ bool reassm; ++ uint16_t sizeForFragmentation; ++ uint8_t owner; ++ uint32_t updateParams; ++ uint32_t shadowUpdateParams; ++ t_FragParams fragParams; ++ union { ++ t_IpReassmParams ipReassmParams; ++ t_IpFragParams ipFragParams; ++ }; ++ uint8_t icOffset; ++ uint16_t ownerTmp; ++ bool cnia; ++ t_Handle p_StatsTbl; ++ t_Handle h_FmPcd; ++ t_List nodesLst; ++ t_Handle h_Spinlock; ++ ++} t_FmPcdManip; ++ ++typedef struct t_FmPcdCcSavedManipParams ++{ ++ union ++ { ++ struct ++ { ++ uint16_t dataOffset; ++ //uint8_t poolId; ++ }capwapParams; ++ struct ++ { ++ uint16_t dataOffset; ++ uint8_t poolId; ++ }ipParams; ++ }; ++ ++} t_FmPcdCcSavedManipParams; ++ ++ ++#endif /* __FM_MANIP_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_pcd.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_pcd.c +new file mode 100644 +index 0000000..0f54050 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_pcd.c +@@ -0,0 +1,2112 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_pcd.c ++ ++ @Description FM PCD ... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "xx_ext.h" ++#include "sprint_ext.h" ++#include "debug_ext.h" ++#include "net_ext.h" ++#include "fm_ext.h" ++#include "fm_pcd_ext.h" ++ ++#include "fm_common.h" ++#include "fm_pcd.h" ++#include "fm_pcd_ipc.h" ++#include "fm_hc.h" ++#include "fm_muram_ext.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++static t_Error CheckFmPcdParameters(t_FmPcd *p_FmPcd) ++{ ++ if (!p_FmPcd->h_Fm) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("h_Fm has to be initialized")); ++ ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ { ++ if (p_FmPcd->p_FmPcdKg && !p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Something WRONG")); ++ ++ if (p_FmPcd->p_FmPcdPlcr && !p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Something WRONG")); ++ ++ if (!p_FmPcd->f_Exception) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_FmPcdExceptions has to be initialized")); ++ ++ if ((!p_FmPcd->f_FmPcdIndexedException) && (p_FmPcd->p_FmPcdPlcr || p_FmPcd->p_FmPcdKg)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_FmPcdIndexedException has to be initialized")); ++ ++ if (p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit > PRS_MAX_CYCLE_LIMIT) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("prsMaxParseCycleLimit has to be less than 8191")); ++ } ++ ++ return E_OK; ++} ++ ++static volatile bool blockingFlag = FALSE; ++static void IpcMsgCompletionCB(t_Handle h_FmPcd, ++ uint8_t *p_Msg, ++ uint8_t *p_Reply, ++ uint32_t replyLength, ++ t_Error status) ++{ ++ UNUSED(h_FmPcd);UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status); ++ blockingFlag = FALSE; ++} ++ ++static t_Error IpcMsgHandlerCB(t_Handle h_FmPcd, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ t_FmPcdIpcMsg *p_IpcMsg = (t_FmPcdIpcMsg*)p_Msg; ++ t_FmPcdIpcReply *p_IpcReply = (t_FmPcdIpcReply*)p_Reply; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE); ++ ++#ifdef DISABLE_SANITY_CHECKS ++ UNUSED(msgLength); ++#endif /* DISABLE_SANITY_CHECKS */ ++ ++ ASSERT_COND(p_Msg); ++ ++ memset(p_IpcReply, 0, (sizeof(uint8_t) * FM_PCD_MAX_REPLY_SIZE)); ++ *p_ReplyLength = 0; ++ ++ switch (p_IpcMsg->msgId) ++ { ++ case (FM_PCD_MASTER_IS_ALIVE): ++ *(uint8_t*)(p_IpcReply->replyBody) = 1; ++ p_IpcReply->error = E_OK; ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ case (FM_PCD_MASTER_IS_ENABLED): ++ /* count partitions registrations */ ++ if (p_FmPcd->enabled) ++ p_FmPcd->numOfEnabledGuestPartitionsPcds++; ++ *(uint8_t*)(p_IpcReply->replyBody) = (uint8_t)p_FmPcd->enabled; ++ p_IpcReply->error = E_OK; ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ case (FM_PCD_GUEST_DISABLE): ++ if (p_FmPcd->numOfEnabledGuestPartitionsPcds) ++ { ++ p_FmPcd->numOfEnabledGuestPartitionsPcds--; ++ p_IpcReply->error = E_OK; ++ } ++ else ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE,("Trying to disable an unregistered partition")); ++ p_IpcReply->error = E_INVALID_STATE; ++ } ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ case (FM_PCD_GET_COUNTER): ++ { ++ e_FmPcdCounters inCounter; ++ uint32_t outCounter; ++ ++ memcpy((uint8_t*)&inCounter, p_IpcMsg->msgBody, sizeof(uint32_t)); ++ outCounter = FM_PCD_GetCounter(h_FmPcd, inCounter); ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&outCounter, sizeof(uint32_t)); ++ p_IpcReply->error = E_OK; ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ break; ++ } ++ case (FM_PCD_ALLOC_KG_SCHEMES): ++ { ++ t_FmPcdIpcKgSchemesParams ipcSchemesParams; ++ ++ memcpy((uint8_t*)&ipcSchemesParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgSchemesParams)); ++ err = FmPcdKgAllocSchemes(h_FmPcd, ++ ipcSchemesParams.numOfSchemes, ++ ipcSchemesParams.guestId, ++ p_IpcReply->replyBody); ++ p_IpcReply->error = err; ++ *p_ReplyLength = sizeof(uint32_t) + ipcSchemesParams.numOfSchemes*sizeof(uint8_t); ++ break; ++ } ++ case (FM_PCD_FREE_KG_SCHEMES): ++ { ++ t_FmPcdIpcKgSchemesParams ipcSchemesParams; ++ ++ memcpy((uint8_t*)&ipcSchemesParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgSchemesParams)); ++ err = FmPcdKgFreeSchemes(h_FmPcd, ++ ipcSchemesParams.numOfSchemes, ++ ipcSchemesParams.guestId, ++ ipcSchemesParams.schemesIds); ++ p_IpcReply->error = err; ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ } ++ case (FM_PCD_ALLOC_KG_CLSPLAN): ++ { ++ t_FmPcdIpcKgClsPlanParams ipcKgClsPlanParams; ++ ++ memcpy((uint8_t*)&ipcKgClsPlanParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgClsPlanParams)); ++ err = KgAllocClsPlanEntries(h_FmPcd, ++ ipcKgClsPlanParams.numOfClsPlanEntries, ++ ipcKgClsPlanParams.guestId, ++ p_IpcReply->replyBody); ++ p_IpcReply->error = err; ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ } ++ case (FM_PCD_FREE_KG_CLSPLAN): ++ { ++ t_FmPcdIpcKgClsPlanParams ipcKgClsPlanParams; ++ ++ memcpy((uint8_t*)&ipcKgClsPlanParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgClsPlanParams)); ++ KgFreeClsPlanEntries(h_FmPcd, ++ ipcKgClsPlanParams.numOfClsPlanEntries, ++ ipcKgClsPlanParams.guestId, ++ ipcKgClsPlanParams.clsPlanBase); ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ } ++ case (FM_PCD_ALLOC_PROFILES): ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ uint16_t base; ++ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); ++ base = PlcrAllocProfilesForPartition(h_FmPcd, ++ ipcAllocParams.base, ++ ipcAllocParams.num, ++ ipcAllocParams.guestId); ++ memcpy(p_IpcReply->replyBody, (uint16_t*)&base, sizeof(uint16_t)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint16_t); ++ break; ++ } ++ case (FM_PCD_FREE_PROFILES): ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); ++ PlcrFreeProfilesForPartition(h_FmPcd, ++ ipcAllocParams.base, ++ ipcAllocParams.num, ++ ipcAllocParams.guestId); ++ break; ++ } ++ case (FM_PCD_SET_PORT_PROFILES): ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); ++ PlcrSetPortProfiles(h_FmPcd, ++ ipcAllocParams.guestId, ++ ipcAllocParams.num, ++ ipcAllocParams.base); ++ break; ++ } ++ case (FM_PCD_CLEAR_PORT_PROFILES): ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); ++ PlcrClearPortProfiles(h_FmPcd, ++ ipcAllocParams.guestId); ++ break; ++ } ++ case (FM_PCD_GET_SW_PRS_OFFSET): ++ { ++ t_FmPcdIpcSwPrsLable ipcSwPrsLable; ++ uint32_t swPrsOffset; ++ ++ memcpy((uint8_t*)&ipcSwPrsLable, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcSwPrsLable)); ++ swPrsOffset = ++ FmPcdGetSwPrsOffset(h_FmPcd, ++ (e_NetHeaderType)ipcSwPrsLable.enumHdr, ++ ipcSwPrsLable.indexPerHdr); ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&swPrsOffset, sizeof(uint32_t)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ break; ++ } ++ case (FM_PCD_PRS_INC_PORT_STATS): ++ { ++ t_FmPcdIpcPrsIncludePort ipcPrsIncludePort; ++ ++ memcpy((uint8_t*)&ipcPrsIncludePort, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcPrsIncludePort)); ++ PrsIncludePortInStatistics(h_FmPcd, ++ ipcPrsIncludePort.hardwarePortId, ++ ipcPrsIncludePort.include); ++ break; ++ } ++ default: ++ *p_ReplyLength = 0; ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!")); ++ } ++ return E_OK; ++} ++ ++static uint32_t NetEnvLock(t_Handle h_NetEnv) ++{ ++ ASSERT_COND(h_NetEnv); ++ return XX_LockIntrSpinlock(((t_FmPcdNetEnv*)h_NetEnv)->h_Spinlock); ++} ++ ++static void NetEnvUnlock(t_Handle h_NetEnv, uint32_t intFlags) ++{ ++ ASSERT_COND(h_NetEnv); ++ XX_UnlockIntrSpinlock(((t_FmPcdNetEnv*)h_NetEnv)->h_Spinlock, intFlags); ++} ++ ++static void EnqueueLockToFreeLst(t_FmPcd *p_FmPcd, t_FmPcdLock *p_Lock) ++{ ++ uint32_t intFlags; ++ ++ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock); ++ LIST_AddToTail(&p_Lock->node, &p_FmPcd->freeLocksLst); ++ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags); ++} ++ ++static t_FmPcdLock * DequeueLockFromFreeLst(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdLock *p_Lock = NULL; ++ uint32_t intFlags; ++ ++ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock); ++ if (!LIST_IsEmpty(&p_FmPcd->freeLocksLst)) ++ { ++ p_Lock = FM_PCD_LOCK_OBJ(p_FmPcd->freeLocksLst.p_Next); ++ LIST_DelAndInit(&p_Lock->node); ++ } ++ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags); ++ ++ return p_Lock; ++} ++ ++static void EnqueueLockToAcquiredLst(t_FmPcd *p_FmPcd, t_FmPcdLock *p_Lock) ++{ ++ uint32_t intFlags; ++ ++ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock); ++ LIST_AddToTail(&p_Lock->node, &p_FmPcd->acquiredLocksLst); ++ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags); ++} ++ ++static t_Error FillFreeLocksLst(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdLock *p_Lock; ++ int i; ++ ++ for (i=0; i<10; i++) ++ { ++ p_Lock = (t_FmPcdLock *)XX_Malloc(sizeof(t_FmPcdLock)); ++ if (!p_Lock) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("FM-PCD lock obj!")); ++ memset(p_Lock, 0, sizeof(t_FmPcdLock)); ++ INIT_LIST(&p_Lock->node); ++ p_Lock->h_Spinlock = XX_InitSpinlock(); ++ if (!p_Lock->h_Spinlock) ++ { ++ XX_Free(p_Lock); ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("FM-PCD spinlock obj!")); ++ } ++ EnqueueLockToFreeLst(p_FmPcd, p_Lock); ++ } ++ ++ return E_OK; ++} ++ ++static void ReleaseFreeLocksLst(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdLock *p_Lock; ++ ++ p_Lock = DequeueLockFromFreeLst(p_FmPcd); ++ while (p_Lock) ++ { ++ XX_FreeSpinlock(p_Lock->h_Spinlock); ++ XX_Free(p_Lock); ++ p_Lock = DequeueLockFromFreeLst(p_FmPcd); ++ } ++} ++ ++ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++void FmPcdSetClsPlanGrpId(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint8_t clsPlanGrpId) ++{ ++ ASSERT_COND(p_FmPcd); ++ p_FmPcd->netEnvs[netEnvId].clsPlanGrpId = clsPlanGrpId; ++} ++ ++t_Error PcdGetClsPlanGrpParams(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_GrpParams) ++{ ++ uint8_t netEnvId = p_GrpParams->netEnvId; ++ int i, k, j; ++ ++ ASSERT_COND(p_FmPcd); ++ if (p_FmPcd->netEnvs[netEnvId].clsPlanGrpId != ILLEGAL_CLS_PLAN) ++ { ++ p_GrpParams->grpExists = TRUE; ++ p_GrpParams->clsPlanGrpId = p_FmPcd->netEnvs[netEnvId].clsPlanGrpId; ++ return E_OK; ++ } ++ ++ for (i=0; ((i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE)); i++) ++ { ++ for (k=0; ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE)); k++) ++ { ++ /* if an option exists, add it to the opts list */ ++ if (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt) ++ { ++ /* check if this option already exists, add if it doesn't */ ++ for (j = 0;jnumOfOptions;j++) ++ { ++ if (p_GrpParams->options[j] == p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt) ++ break; ++ } ++ p_GrpParams->optVectors[j] |= p_FmPcd->netEnvs[netEnvId].unitsVectors[i]; ++ if (j == p_GrpParams->numOfOptions) ++ { ++ p_GrpParams->options[p_GrpParams->numOfOptions] = p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt; ++ p_GrpParams->numOfOptions++; ++ } ++ } ++ } ++ } ++ ++ if (p_GrpParams->numOfOptions == 0) ++ { ++ if (p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId != ILLEGAL_CLS_PLAN) ++ { ++ p_GrpParams->grpExists = TRUE; ++ p_GrpParams->clsPlanGrpId = p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId; ++ } ++ } ++ ++ return E_OK; ++ ++} ++ ++t_Error PcdGetVectorForOpt(t_FmPcd *p_FmPcd, uint8_t netEnvId, protocolOpt_t opt, uint32_t *p_Vector) ++{ ++ uint8_t j,k; ++ ++ *p_Vector = 0; ++ ++ ASSERT_COND(p_FmPcd); ++ for (j=0; ((j < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) && ++ (p_FmPcd->netEnvs[netEnvId].units[j].hdrs[0].hdr != HEADER_TYPE_NONE)); j++) ++ { ++ for (k=0; ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].units[j].hdrs[k].hdr != HEADER_TYPE_NONE)); k++) ++ { ++ if (p_FmPcd->netEnvs[netEnvId].units[j].hdrs[k].opt == opt) ++ *p_Vector |= p_FmPcd->netEnvs[netEnvId].unitsVectors[j]; ++ } ++ } ++ ++ if (!*p_Vector) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Requested option was not defined for this Network Environment Characteristics module")); ++ else ++ return E_OK; ++} ++ ++t_Error PcdGetUnitsVector(t_FmPcd *p_FmPcd, t_NetEnvParams *p_Params) ++{ ++ int i; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(p_Params->netEnvId < FM_MAX_NUM_OF_PORTS); ++ ++ p_Params->vector = 0; ++ for (i=0; inumOfDistinctionUnits ;i++) ++ { ++ if (p_FmPcd->netEnvs[p_Params->netEnvId].units[p_Params->unitIds[i]].hdrs[0].hdr == HEADER_TYPE_NONE) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Requested unit was not defined for this Network Environment Characteristics module")); ++ ASSERT_COND(p_FmPcd->netEnvs[p_Params->netEnvId].unitsVectors[p_Params->unitIds[i]]); ++ p_Params->vector |= p_FmPcd->netEnvs[p_Params->netEnvId].unitsVectors[p_Params->unitIds[i]]; ++ } ++ ++ return E_OK; ++} ++ ++bool PcdNetEnvIsUnitWithoutOpts(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint32_t unitVector) ++{ ++ int i=0, k; ++ ++ ASSERT_COND(p_FmPcd); ++ /* check whether a given unit may be used by non-clsPlan users. */ ++ /* first, recognize the unit by its vector */ ++ while (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE) ++ { ++ if (p_FmPcd->netEnvs[netEnvId].unitsVectors[i] == unitVector) ++ { ++ for (k=0; ++ ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE)); ++ k++) ++ /* check that no option exists */ ++ if ((protocolOpt_t)p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt) ++ return FALSE; ++ break; ++ } ++ i++; ++ } ++ /* assert that a unit was found to mach the vector */ ++ ASSERT_COND(p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); ++ ++ return TRUE; ++} ++bool FmPcdNetEnvIsHdrExist(t_Handle h_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ int i, k; ++ ++ ASSERT_COND(p_FmPcd); ++ ++ for (i=0; ((i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE)); i++) ++ { ++ for (k=0; ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE)); k++) ++ if (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr == hdr) ++ return TRUE; ++ } ++ for (i=0; ((i < FM_PCD_MAX_NUM_OF_ALIAS_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr != HEADER_TYPE_NONE)); i++) ++ { ++ if (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr == hdr) ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++uint8_t FmPcdNetEnvGetUnitId(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr, bool interchangable, protocolOpt_t opt) ++{ ++ uint8_t i, k; ++ ++ ASSERT_COND(p_FmPcd); ++ ++ if (interchangable) ++ { ++ for (i=0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++) ++ { ++ for (k=0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++) ++ { ++ if ((p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr == hdr) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt == opt)) ++ ++ return i; ++ } ++ } ++ } ++ else ++ { ++ for (i=0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++) ++ if ((p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr == hdr) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].opt == opt) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[1].hdr == HEADER_TYPE_NONE)) ++ return i; ++ ++ for (i=0; (i < FM_PCD_MAX_NUM_OF_ALIAS_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr != HEADER_TYPE_NONE); i++) ++ if ((p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr == hdr) && ++ (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].opt == opt)) ++ return p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].aliasHdr; ++ } ++ ++ return FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS; ++} ++ ++t_Error FmPcdUnregisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdCcIpReassmTimeoutParams ccIpReassmTimeoutParams = {0}; ++ uint8_t result; ++ t_Error err = E_OK; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(h_IpReasmCommonPramTbl); ++ ++ ccIpReassmTimeoutParams.iprcpt = (uint32_t)(XX_VirtToPhys(h_IpReasmCommonPramTbl) - p_FmPcd->physicalMuramBase); ++ ccIpReassmTimeoutParams.activate = FALSE; /*Disable Timeout Task*/ ++ ++ if ((err = FmHcPcdCcIpTimeoutReassm(p_FmPcd->h_Hc, &ccIpReassmTimeoutParams, &result)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ switch (result) ++ { ++ case (0): ++ return E_OK; ++ case (1): ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("")); ++ case (2): ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("")); ++ case (3): ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("Disable Timeout Task with invalid IPRCPT")); ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++e_NetHeaderType FmPcdGetAliasHdr(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr) ++{ ++ int i; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(netEnvId < FM_MAX_NUM_OF_PORTS); ++ ++ for (i=0; (i < FM_PCD_MAX_NUM_OF_ALIAS_HDRS) ++ && (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr != HEADER_TYPE_NONE); i++) ++ { ++ if (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr == hdr) ++ return p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].aliasHdr; ++ } ++ ++ return HEADER_TYPE_NONE; ++} ++ ++void FmPcdPortRegister(t_Handle h_FmPcd, t_Handle h_FmPort, uint8_t hardwarePortId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint16_t swPortIndex = 0; ++ ++ ASSERT_COND(h_FmPcd); ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].h_FmPort = h_FmPort; ++} ++ ++uint32_t FmPcdGetLcv(t_Handle h_FmPcd, uint32_t netEnvId, uint8_t hdrNum) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(h_FmPcd); ++ return p_FmPcd->netEnvs[netEnvId].lcvs[hdrNum]; ++} ++ ++uint32_t FmPcdGetMacsecLcv(t_Handle h_FmPcd, uint32_t netEnvId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(h_FmPcd); ++ return p_FmPcd->netEnvs[netEnvId].macsecVector; ++} ++ ++uint8_t FmPcdGetNetEnvId(t_Handle h_NetEnv) ++{ ++ return ((t_FmPcdNetEnv*)h_NetEnv)->netEnvId; ++} ++ ++void FmPcdIncNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId) ++{ ++ uint32_t intFlags; ++ ++ ASSERT_COND(h_FmPcd); ++ ++ intFlags = NetEnvLock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId]); ++ ((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId].owners++; ++ NetEnvUnlock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId], intFlags); ++} ++ ++void FmPcdDecNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId) ++{ ++ uint32_t intFlags; ++ ++ ASSERT_COND(h_FmPcd); ++ ASSERT_COND(((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId].owners); ++ ++ intFlags = NetEnvLock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId]); ++ ((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId].owners--; ++ NetEnvUnlock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId], intFlags); ++} ++ ++uint32_t FmPcdLock(t_Handle h_FmPcd) ++{ ++ ASSERT_COND(h_FmPcd); ++ return XX_LockIntrSpinlock(((t_FmPcd*)h_FmPcd)->h_Spinlock); ++} ++ ++void FmPcdUnlock(t_Handle h_FmPcd, uint32_t intFlags) ++{ ++ ASSERT_COND(h_FmPcd); ++ XX_UnlockIntrSpinlock(((t_FmPcd*)h_FmPcd)->h_Spinlock, intFlags); ++} ++ ++t_FmPcdLock * FmPcdAcquireLock(t_Handle h_FmPcd) ++{ ++ t_FmPcdLock *p_Lock; ++ ASSERT_COND(h_FmPcd); ++ p_Lock = DequeueLockFromFreeLst((t_FmPcd*)h_FmPcd); ++ if (!p_Lock) ++ { ++ FillFreeLocksLst(h_FmPcd); ++ p_Lock = DequeueLockFromFreeLst((t_FmPcd*)h_FmPcd); ++ } ++ ++ if (p_Lock) ++ EnqueueLockToAcquiredLst((t_FmPcd*)h_FmPcd, p_Lock); ++ return p_Lock; ++} ++ ++void FmPcdReleaseLock(t_Handle h_FmPcd, t_FmPcdLock *p_Lock) ++{ ++ uint32_t intFlags; ++ ASSERT_COND(h_FmPcd); ++ intFlags = FmPcdLock(h_FmPcd); ++ LIST_DelAndInit(&p_Lock->node); ++ FmPcdUnlock(h_FmPcd, intFlags); ++ EnqueueLockToFreeLst((t_FmPcd*)h_FmPcd, p_Lock); ++} ++ ++bool FmPcdLockTryLockAll(t_Handle h_FmPcd) ++{ ++ uint32_t intFlags; ++ t_List *p_Pos, *p_SavedPos=NULL; ++ ++ ASSERT_COND(h_FmPcd); ++ intFlags = FmPcdLock(h_FmPcd); ++ LIST_FOR_EACH(p_Pos, &((t_FmPcd*)h_FmPcd)->acquiredLocksLst) ++ { ++ t_FmPcdLock *p_Lock = FM_PCD_LOCK_OBJ(p_Pos); ++ if (!FmPcdLockTryLock(p_Lock)) ++ { ++ p_SavedPos = p_Pos; ++ break; ++ } ++ } ++ if (p_SavedPos) ++ { ++ LIST_FOR_EACH(p_Pos, &((t_FmPcd*)h_FmPcd)->acquiredLocksLst) ++ { ++ t_FmPcdLock *p_Lock = FM_PCD_LOCK_OBJ(p_Pos); ++ if (p_Pos == p_SavedPos) ++ break; ++ FmPcdLockUnlock(p_Lock); ++ } ++ } ++ FmPcdUnlock(h_FmPcd, intFlags); ++ ++ CORE_MemoryBarrier(); ++ ++ if (p_SavedPos) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++void FmPcdLockUnlockAll(t_Handle h_FmPcd) ++{ ++ uint32_t intFlags; ++ t_List *p_Pos; ++ ++ ASSERT_COND(h_FmPcd); ++ intFlags = FmPcdLock(h_FmPcd); ++ LIST_FOR_EACH(p_Pos, &((t_FmPcd*)h_FmPcd)->acquiredLocksLst) ++ { ++ t_FmPcdLock *p_Lock = FM_PCD_LOCK_OBJ(p_Pos); ++ p_Lock->flag = FALSE; ++ } ++ FmPcdUnlock(h_FmPcd, intFlags); ++ ++ CORE_MemoryBarrier(); ++} ++ ++t_Handle FmPcdGetHcHandle(t_Handle h_FmPcd) ++{ ++ ASSERT_COND(h_FmPcd); ++ SANITY_CHECK_RETURN_VALUE(((t_FmPcd*)h_FmPcd)->h_Hc, E_INVALID_HANDLE, NULL); ++ return ((t_FmPcd*)h_FmPcd)->h_Hc; ++} ++ ++bool FmPcdIsAdvancedOffloadSupported(t_Handle h_FmPcd) ++{ ++ ASSERT_COND(h_FmPcd); ++ return ((t_FmPcd*)h_FmPcd)->advancedOffloadSupport; ++} ++/*********************** End of inter-module routines ************************/ ++ ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++ ++t_Handle FM_PCD_Config(t_FmPcdParams *p_FmPcdParams) ++{ ++ t_FmPcd *p_FmPcd = NULL; ++ t_FmPhysAddr physicalMuramBase; ++ uint8_t i; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcdParams, E_INVALID_HANDLE,NULL); ++ ++ p_FmPcd = (t_FmPcd *) XX_Malloc(sizeof(t_FmPcd)); ++ if (!p_FmPcd) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD")); ++ return NULL; ++ } ++ memset(p_FmPcd, 0, sizeof(t_FmPcd)); ++ ++ p_FmPcd->p_FmPcdDriverParam = (t_FmPcdDriverParam *) XX_Malloc(sizeof(t_FmPcdDriverParam)); ++ if (!p_FmPcd->p_FmPcdDriverParam) ++ { ++ XX_Free(p_FmPcd); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Driver Param")); ++ return NULL; ++ } ++ memset(p_FmPcd->p_FmPcdDriverParam, 0, sizeof(t_FmPcdDriverParam)); ++ ++ p_FmPcd->h_Fm = p_FmPcdParams->h_Fm; ++ p_FmPcd->guestId = FmGetGuestId(p_FmPcd->h_Fm); ++ p_FmPcd->h_FmMuram = FmGetMuramHandle(p_FmPcd->h_Fm); ++ if (p_FmPcd->h_FmMuram) ++ { ++ FmGetPhysicalMuramBase(p_FmPcdParams->h_Fm, &physicalMuramBase); ++ p_FmPcd->physicalMuramBase = (uint64_t)((uint64_t)(&physicalMuramBase)->low | ((uint64_t)(&physicalMuramBase)->high << 32)); ++ } ++ ++ for (i = 0; inetEnvs[i].clsPlanGrpId = ILLEGAL_CLS_PLAN; ++ ++ if (p_FmPcdParams->useHostCommand) ++ { ++ t_FmHcParams hcParams; ++ ++ memset(&hcParams, 0, sizeof(hcParams)); ++ hcParams.h_Fm = p_FmPcd->h_Fm; ++ hcParams.h_FmPcd = (t_Handle)p_FmPcd; ++ memcpy((uint8_t*)&hcParams.params, (uint8_t*)&p_FmPcdParams->hc, sizeof(t_FmPcdHcParams)); ++ p_FmPcd->h_Hc = FmHcConfigAndInit(&hcParams); ++ if (!p_FmPcd->h_Hc) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD HC")); ++ FM_PCD_Free(p_FmPcd); ++ return NULL; ++ } ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("No Host Command defined for a guest partition.")); ++ ++ if (p_FmPcdParams->kgSupport) ++ { ++ p_FmPcd->p_FmPcdKg = (t_FmPcdKg *)KgConfig(p_FmPcd, p_FmPcdParams); ++ if (!p_FmPcd->p_FmPcdKg) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Keygen")); ++ FM_PCD_Free(p_FmPcd); ++ return NULL; ++ } ++ } ++ ++ if (p_FmPcdParams->plcrSupport) ++ { ++ p_FmPcd->p_FmPcdPlcr = (t_FmPcdPlcr *)PlcrConfig(p_FmPcd, p_FmPcdParams); ++ if (!p_FmPcd->p_FmPcdPlcr) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Policer")); ++ FM_PCD_Free(p_FmPcd); ++ return NULL; ++ } ++ } ++ ++ if (p_FmPcdParams->prsSupport) ++ { ++ p_FmPcd->p_FmPcdPrs = (t_FmPcdPrs *)PrsConfig(p_FmPcd, p_FmPcdParams); ++ if (!p_FmPcd->p_FmPcdPrs) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Parser")); ++ FM_PCD_Free(p_FmPcd); ++ return NULL; ++ } ++ } ++ ++ p_FmPcd->h_Spinlock = XX_InitSpinlock(); ++ if (!p_FmPcd->h_Spinlock) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD spinlock")); ++ FM_PCD_Free(p_FmPcd); ++ return NULL; ++ } ++ INIT_LIST(&p_FmPcd->freeLocksLst); ++ INIT_LIST(&p_FmPcd->acquiredLocksLst); ++ ++ p_FmPcd->numOfEnabledGuestPartitionsPcds = 0; ++ ++ p_FmPcd->f_Exception = p_FmPcdParams->f_Exception; ++ p_FmPcd->f_FmPcdIndexedException = p_FmPcdParams->f_ExceptionId; ++ p_FmPcd->h_App = p_FmPcdParams->h_App; ++ ++ p_FmPcd->p_CcShadow = NULL; ++ p_FmPcd->ccShadowSize = 0; ++ p_FmPcd->ccShadowAlign = 0; ++ ++ p_FmPcd->h_ShadowSpinlock = XX_InitSpinlock(); ++ if (!p_FmPcd->h_ShadowSpinlock) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD shadow spinlock")); ++ FM_PCD_Free(p_FmPcd); ++ return NULL; ++ } ++ ++ return p_FmPcd; ++} ++ ++t_Handle FM_PCD_GetHcDevH(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *) h_FmPcd; ++ ++ return (p_FmPcd) ? FmGcGetHcPortDevH(p_FmPcd->h_Hc) : NULL; ++} ++ ++t_Error FM_PCD_Init(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ t_FmPcdIpcMsg msg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); ++ ++ FM_GetRevision(p_FmPcd->h_Fm, &p_FmPcd->fmRevInfo); ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ { ++ memset(p_FmPcd->fmPcdIpcHandlerModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE); ++ if (Sprint (p_FmPcd->fmPcdIpcHandlerModuleName, "FM_PCD_%d_%d", FmGetId(p_FmPcd->h_Fm), NCSW_MASTER_ID) != 10) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ memset(p_FmPcd->fmPcdModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE); ++ if (Sprint (p_FmPcd->fmPcdModuleName, "FM_PCD_%d_%d",FmGetId(p_FmPcd->h_Fm), p_FmPcd->guestId) != (p_FmPcd->guestId<10 ? 10:11)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ ++ p_FmPcd->h_IpcSession = XX_IpcInitSession(p_FmPcd->fmPcdIpcHandlerModuleName, p_FmPcd->fmPcdModuleName); ++ if (p_FmPcd->h_IpcSession) ++ { ++ t_FmPcdIpcReply reply; ++ uint32_t replyLength; ++ uint8_t isMasterAlive = 0; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_PCD_MASTER_IS_ALIVE; ++ msg.msgBody[0] = p_FmPcd->guestId; ++ blockingFlag = TRUE; ++ ++ do ++ { ++ replyLength = sizeof(uint32_t) + sizeof(isMasterAlive); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(p_FmPcd->guestId), ++ (uint8_t*)&reply, ++ &replyLength, ++ IpcMsgCompletionCB, ++ h_FmPcd)) != E_OK) ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ while (blockingFlag) ; ++ if (replyLength != (sizeof(uint32_t) + sizeof(isMasterAlive))) ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ isMasterAlive = *(uint8_t*)(reply.replyBody); ++ } while (!isMasterAlive); ++ } ++ } ++ ++ CHECK_INIT_PARAMETERS(p_FmPcd, CheckFmPcdParameters); ++ ++ if (p_FmPcd->p_FmPcdKg) ++ { ++ err = KgInit(p_FmPcd); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (p_FmPcd->p_FmPcdPlcr) ++ { ++ err = PlcrInit(p_FmPcd); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (p_FmPcd->p_FmPcdPrs) ++ { ++ err = PrsInit(p_FmPcd); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ { ++ /* register to inter-core messaging mechanism */ ++ memset(p_FmPcd->fmPcdModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE); ++ if (Sprint (p_FmPcd->fmPcdModuleName, "FM_PCD_%d_%d",FmGetId(p_FmPcd->h_Fm),NCSW_MASTER_ID) != 10) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ err = XX_IpcRegisterMsgHandler(p_FmPcd->fmPcdModuleName, IpcMsgHandlerCB, p_FmPcd, FM_PCD_MAX_REPLY_SIZE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /* IPv6 Frame-Id used for fragmentation */ ++ p_FmPcd->ipv6FrameIdAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, 4, 4)); ++ if (!p_FmPcd->ipv6FrameIdAddr) ++ { ++ FM_PCD_Free(p_FmPcd); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for IPv6 Frame-Id")); ++ } ++ IOMemSet32(UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr), 0, 4); ++ ++ XX_Free(p_FmPcd->p_FmPcdDriverParam); ++ p_FmPcd->p_FmPcdDriverParam = NULL; ++ ++ FmRegisterPcd(p_FmPcd->h_Fm, p_FmPcd); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_Free(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd =(t_FmPcd *)h_FmPcd; ++ t_Error err = E_OK; ++ ++ if (p_FmPcd->ipv6FrameIdAddr) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr)); ++ ++ if (p_FmPcd->enabled) ++ FM_PCD_Disable(p_FmPcd); ++ ++ if (p_FmPcd->p_FmPcdDriverParam) ++ { ++ XX_Free(p_FmPcd->p_FmPcdDriverParam); ++ p_FmPcd->p_FmPcdDriverParam = NULL; ++ } ++ ++ if (p_FmPcd->p_FmPcdKg) ++ { ++ if ((err = KgFree(p_FmPcd)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ XX_Free(p_FmPcd->p_FmPcdKg); ++ p_FmPcd->p_FmPcdKg = NULL; ++ } ++ ++ if (p_FmPcd->p_FmPcdPlcr) ++ { ++ if ((err = PlcrFree(p_FmPcd)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ XX_Free(p_FmPcd->p_FmPcdPlcr); ++ p_FmPcd->p_FmPcdPlcr = NULL; ++ } ++ ++ if (p_FmPcd->p_FmPcdPrs) ++ { ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ PrsFree(p_FmPcd); ++ XX_Free(p_FmPcd->p_FmPcdPrs); ++ p_FmPcd->p_FmPcdPrs = NULL; ++ } ++ ++ if (p_FmPcd->h_Hc) ++ { ++ FmHcFree(p_FmPcd->h_Hc); ++ p_FmPcd->h_Hc = NULL; ++ } ++ ++ XX_IpcUnregisterMsgHandler(p_FmPcd->fmPcdModuleName); ++ ++ FmUnregisterPcd(p_FmPcd->h_Fm); ++ ++ ReleaseFreeLocksLst(p_FmPcd); ++ ++ if (p_FmPcd->h_Spinlock) ++ XX_FreeSpinlock(p_FmPcd->h_Spinlock); ++ ++ if (p_FmPcd->h_ShadowSpinlock) ++ XX_FreeSpinlock(p_FmPcd->h_ShadowSpinlock); ++ ++ XX_Free(p_FmPcd); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ConfigException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigException - guest mode!")); ++ ++ GET_FM_PCD_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_FmPcd->exceptions |= bitMask; ++ else ++ p_FmPcd->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ConfigHcFramesDataMemory(t_Handle h_FmPcd, uint8_t memId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ return FmHcSetFramesDataMemory(p_FmPcd->h_Hc, memId); ++} ++ ++t_Error FM_PCD_Enable(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ ++ if (p_FmPcd->enabled) ++ return E_OK; ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ p_FmPcd->h_IpcSession) ++ { ++ uint8_t enabled; ++ t_FmPcdIpcMsg msg; ++ t_FmPcdIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_PCD_MASTER_IS_ENABLED; ++ replyLength = sizeof(uint32_t) + sizeof(enabled); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t) + sizeof(enabled)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ p_FmPcd->enabled = (bool)!!(*(uint8_t*)(reply.replyBody)); ++ if (!p_FmPcd->enabled) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-PCD master should be enabled first!")); ++ ++ return E_OK; ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ if (p_FmPcd->p_FmPcdKg) ++ KgEnable(p_FmPcd); ++ ++ if (p_FmPcd->p_FmPcdPlcr) ++ PlcrEnable(p_FmPcd); ++ ++ if (p_FmPcd->p_FmPcdPrs) ++ PrsEnable(p_FmPcd); ++ ++ p_FmPcd->enabled = TRUE; ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_Disable(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ ++ if (!p_FmPcd->enabled) ++ return E_OK; ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ p_FmPcd->h_IpcSession) ++ { ++ t_FmPcdIpcMsg msg; ++ t_FmPcdIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_PCD_GUEST_DISABLE; ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ if (reply.error == E_OK) ++ p_FmPcd->enabled = FALSE; ++ ++ return (t_Error)(reply.error); ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ if (p_FmPcd->numOfEnabledGuestPartitionsPcds != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Trying to disable a master partition PCD while" ++ "guest partitions are still enabled!")); ++ ++ if (p_FmPcd->p_FmPcdKg) ++ KgDisable(p_FmPcd); ++ ++ if (p_FmPcd->p_FmPcdPlcr) ++ PlcrDisable(p_FmPcd); ++ ++ if (p_FmPcd->p_FmPcdPrs) ++ PrsDisable(p_FmPcd); ++ ++ p_FmPcd->enabled = FALSE; ++ ++ return E_OK; ++} ++ ++t_Handle FM_PCD_NetEnvCharacteristicsSet(t_Handle h_FmPcd, t_FmPcdNetEnvParams *p_NetEnvParams) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t intFlags, specialUnits = 0; ++ uint8_t bitId = 0; ++ uint8_t i, j, k; ++ uint8_t netEnvCurrId; ++ uint8_t ipsecAhUnit = 0,ipsecEspUnit = 0; ++ bool ipsecAhExists = FALSE, ipsecEspExists = FALSE, shim1Selected = FALSE; ++ uint8_t hdrNum; ++ t_FmPcdNetEnvParams *p_modifiedNetEnvParams; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_STATE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_NetEnvParams, E_NULL_POINTER, NULL); ++ ++ intFlags = FmPcdLock(p_FmPcd); ++ ++ /* find a new netEnv */ ++ for (i = 0; i < FM_MAX_NUM_OF_PORTS; i++) ++ if (!p_FmPcd->netEnvs[i].used) ++ break; ++ ++ if (i== FM_MAX_NUM_OF_PORTS) ++ { ++ REPORT_ERROR(MAJOR, E_FULL,("No more than %d netEnv's allowed.", FM_MAX_NUM_OF_PORTS)); ++ FmPcdUnlock(p_FmPcd, intFlags); ++ return NULL; ++ } ++ ++ p_FmPcd->netEnvs[i].used = TRUE; ++ FmPcdUnlock(p_FmPcd, intFlags); ++ ++ /* As anyone doesn't have handle of this netEnv yet, no need ++ to protect it with spinlocks */ ++ ++ p_modifiedNetEnvParams = (t_FmPcdNetEnvParams *) XX_Malloc(sizeof(t_FmPcdNetEnvParams)); ++ if (!p_modifiedNetEnvParams) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FmPcdNetEnvParams")); ++ return NULL; ++ } ++ ++ memcpy(p_modifiedNetEnvParams, p_NetEnvParams, sizeof(t_FmPcdNetEnvParams)); ++ p_NetEnvParams = p_modifiedNetEnvParams; ++ ++ netEnvCurrId = (uint8_t)i; ++ ++ /* clear from previous use */ ++ memset(&p_FmPcd->netEnvs[netEnvCurrId].units, 0, FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS * sizeof(t_FmPcdIntDistinctionUnit)); ++ memset(&p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs, 0, FM_PCD_MAX_NUM_OF_ALIAS_HDRS * sizeof(t_FmPcdNetEnvAliases)); ++ memcpy(&p_FmPcd->netEnvs[netEnvCurrId].units, p_NetEnvParams->units, p_NetEnvParams->numOfDistinctionUnits*sizeof(t_FmPcdIntDistinctionUnit)); ++ ++ p_FmPcd->netEnvs[netEnvCurrId].netEnvId = netEnvCurrId; ++ p_FmPcd->netEnvs[netEnvCurrId].h_FmPcd = p_FmPcd; ++ ++ p_FmPcd->netEnvs[netEnvCurrId].clsPlanGrpId = ILLEGAL_CLS_PLAN; ++ ++ /* check that header with opt is not interchanged with the same header */ ++ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++) ++ { ++ for (k = 0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++) ++ { ++ /* if an option exists, check that other headers are not the same header ++ without option */ ++ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt) ++ { ++ for (j = 0; (j < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[j].hdr != HEADER_TYPE_NONE); j++) ++ { ++ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[j].hdr == p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr) && ++ !p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[j].opt) ++ { ++ REPORT_ERROR(MINOR, E_FULL, ++ ("Illegal unit - header with opt may not be interchangeable with the same header without opt")); ++ XX_Free(p_modifiedNetEnvParams); ++ return NULL; ++ } ++ } ++ } ++ } ++ } ++ ++ /* Specific headers checking */ ++ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++) ++ { ++ for (k = 0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++) ++ { ++ /* Some headers pairs may not be defined on different units as the parser ++ doesn't distinguish */ ++ /* IPSEC_AH and IPSEC_SPI can't be 2 units, */ ++ /* check that header with opt is not interchanged with the same header */ ++ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPSEC_AH) ++ { ++ if (ipsecEspExists && (ipsecEspUnit != i)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("HEADER_TYPE_IPSEC_AH and HEADER_TYPE_IPSEC_ESP may not be defined in separate units")); ++ XX_Free(p_modifiedNetEnvParams); ++ return NULL; ++ } ++ else ++ { ++ ipsecAhUnit = i; ++ ipsecAhExists = TRUE; ++ } ++ } ++ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPSEC_ESP) ++ { ++ if (ipsecAhExists && (ipsecAhUnit != i)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("HEADER_TYPE_IPSEC_AH and HEADER_TYPE_IPSEC_ESP may not be defined in separate units")); ++ XX_Free(p_modifiedNetEnvParams); ++ return NULL; ++ } ++ else ++ { ++ ipsecEspUnit = i; ++ ipsecEspExists = TRUE; ++ } ++ } ++ /* ENCAP_ESP */ ++ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_UDP_ENCAP_ESP) ++ { ++ /* IPSec UDP encapsulation is currently set to use SHIM1 */ ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_UDP_ENCAP_ESP; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM1; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM1; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0; ++ } ++#ifdef FM_CAPWAP_SUPPORT ++ /* UDP_LITE */ ++ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_UDP_LITE) ++ { ++ /* IPSec UDP encapsulation is currently set to use SHIM1 */ ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_UDP_LITE; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_UDP; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_UDP; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0; ++ } ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++ /* IP FRAG */ ++ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPv4) && ++ (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt == IPV4_FRAG_1)) ++ { ++ /* If IPv4+Frag, we need to set 2 units - SHIM 2 and IPv4. We first set SHIM2, and than check if ++ * IPv4 exists. If so we don't need to set an extra unit ++ * We consider as "having IPv4" any IPv4 without interchangable headers ++ * but including any options. */ ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_IPv4; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].opt = IPV4_FRAG_1; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM2; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM2; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0; ++ ++ /* check if IPv4 header exists by itself */ ++ if (FmPcdNetEnvGetUnitId(p_FmPcd, netEnvCurrId, HEADER_TYPE_IPv4, FALSE, 0) == FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ { ++ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits].hdrs[0].hdr = HEADER_TYPE_IPv4; ++ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits++].hdrs[0].opt = 0; ++ } ++ } ++ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPv6) && ++ (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt == IPV6_FRAG_1)) ++ { ++ /* If IPv6+Frag, we need to set 2 units - SHIM 2 and IPv6. We first set SHIM2, and than check if ++ * IPv4 exists. If so we don't need to set an extra unit ++ * We consider as "having IPv6" any IPv6 without interchangable headers ++ * but including any options. */ ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_IPv6; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].opt = IPV6_FRAG_1; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM2; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM2; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0; ++ ++ /* check if IPv6 header exists by itself */ ++ if (FmPcdNetEnvGetUnitId(p_FmPcd, netEnvCurrId, HEADER_TYPE_IPv6, FALSE, 0) == FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ { ++ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits].hdrs[0].hdr = HEADER_TYPE_IPv6; ++ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits++].hdrs[0].opt = 0; ++ } ++ } ++ } ++ } ++ ++ /* if private header (shim), check that no other headers specified */ ++ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++) ++ { ++ if (IS_PRIVATE_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr)) ++ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[1].hdr != HEADER_TYPE_NONE) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("SHIM header may not be interchanged with other headers")); ++ XX_Free(p_modifiedNetEnvParams); ++ return NULL; ++ } ++ } ++ ++ for (i = 0; i < p_NetEnvParams->numOfDistinctionUnits; i++) ++ { ++ if (IS_PRIVATE_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr)) ++ switch (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr) ++ { ++ case (HEADER_TYPE_USER_DEFINED_SHIM1): ++ if (shim1Selected) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("SHIM header cannot be selected with UDP_IPSEC_ESP")); ++ XX_Free(p_modifiedNetEnvParams); ++ return NULL; ++ } ++ shim1Selected = TRUE; ++ p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i] = 0x00000001; ++ break; ++ case (HEADER_TYPE_USER_DEFINED_SHIM2): ++ p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i] = 0x00000002; ++ break; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Requested SHIM not supported")); ++ } ++ else ++ { ++ p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i] = (uint32_t)(0x80000000 >> bitId++); ++ ++ if (IS_SPECIAL_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr)) ++ p_FmPcd->netEnvs[netEnvCurrId].macsecVector = p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i]; ++ } ++ } ++ ++ /* define a set of hardware parser LCV's according to the defined netenv */ ++ ++ /* set an array of LCV's for each header in the netEnv */ ++ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++) ++ { ++ /* private headers have no LCV in the hard parser */ ++ if (!IS_PRIVATE_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr)) ++ { ++ for (k = 0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++) ++ { ++ GET_PRS_HDR_NUM(hdrNum, p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr); ++ if ((hdrNum == ILLEGAL_HDR_NUM) || (hdrNum == NO_HDR_NUM)) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG); ++ XX_Free(p_modifiedNetEnvParams); ++ return NULL; ++ } ++ p_FmPcd->netEnvs[netEnvCurrId].lcvs[hdrNum] |= p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i]; ++ } ++ } ++ } ++ XX_Free(p_modifiedNetEnvParams); ++ ++ p_FmPcd->netEnvs[netEnvCurrId].h_Spinlock = XX_InitSpinlock(); ++ if (!p_FmPcd->netEnvs[netEnvCurrId].h_Spinlock) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Pcd NetEnv spinlock")); ++ return NULL; ++ } ++ return &p_FmPcd->netEnvs[netEnvCurrId]; ++} ++ ++t_Error FM_PCD_NetEnvCharacteristicsDelete(t_Handle h_NetEnv) ++{ ++ t_FmPcdNetEnv *p_NetEnv = (t_FmPcdNetEnv*)h_NetEnv; ++ t_FmPcd *p_FmPcd = p_NetEnv->h_FmPcd; ++ uint32_t intFlags; ++ uint8_t netEnvId = p_NetEnv->netEnvId; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ ++ /* check that no port is bound to this netEnv */ ++ if (p_FmPcd->netEnvs[netEnvId].owners) ++ { ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ++ ("Trying to delete a netEnv that has ports/schemes/trees/clsPlanGrps bound to")); ++ } ++ ++ intFlags = FmPcdLock(p_FmPcd); ++ ++ p_FmPcd->netEnvs[netEnvId].used = FALSE; ++ p_FmPcd->netEnvs[netEnvId].clsPlanGrpId = ILLEGAL_CLS_PLAN; ++ ++ memset(p_FmPcd->netEnvs[netEnvId].units, 0, sizeof(t_FmPcdIntDistinctionUnit)*FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ memset(p_FmPcd->netEnvs[netEnvId].unitsVectors, 0, sizeof(uint32_t)*FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ memset(p_FmPcd->netEnvs[netEnvId].lcvs, 0, sizeof(uint32_t)*FM_PCD_PRS_NUM_OF_HDRS); ++ ++ if (p_FmPcd->netEnvs[netEnvId].h_Spinlock) ++ XX_FreeSpinlock(p_FmPcd->netEnvs[netEnvId].h_Spinlock); ++ ++ FmPcdUnlock(p_FmPcd, intFlags); ++ return E_OK; ++} ++ ++void FM_PCD_HcTxConf(t_Handle h_FmPcd, t_DpaaFD *p_Fd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN(h_FmPcd, E_INVALID_STATE); ++ ++ FmHcTxConf(p_FmPcd->h_Hc, p_Fd); ++} ++ ++t_Error FM_PCD_SetAdvancedOffloadSupport(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmCtrlCodeRevisionInfo revInfo; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->enabled, E_INVALID_STATE); ++ ++ if ((err = FM_GetFmanCtrlCodeRevision(p_FmPcd->h_Fm, &revInfo)) != E_OK) ++ { ++ DBG(WARNING, ("FM in guest-mode without IPC, can't validate firmware revision.")); ++ revInfo.packageRev = IP_OFFLOAD_PACKAGE_NUMBER; ++ } ++ if (revInfo.packageRev != IP_OFFLOAD_PACKAGE_NUMBER) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Fman ctrl code package")); ++ ++ p_FmPcd->advancedOffloadSupport = TRUE; ++ ++ return E_OK; ++} ++ ++uint32_t FM_PCD_GetCounter(t_Handle h_FmPcd, e_FmPcdCounters counter) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t outCounter = 0; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, 0); ++ ++ switch (counter) ++ { ++ case (e_FM_PCD_KG_COUNTERS_TOTAL): ++ if (!p_FmPcd->p_FmPcdKg) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("KeyGen is not activated")); ++ return 0; ++ } ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ !p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs && ++ !p_FmPcd->h_IpcSession) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++ return 0; ++ } ++ break; ++ ++ case (e_FM_PCD_PLCR_COUNTERS_YELLOW): ++ case (e_FM_PCD_PLCR_COUNTERS_RED): ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED): ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW): ++ case (e_FM_PCD_PLCR_COUNTERS_TOTAL): ++ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH): ++ if (!p_FmPcd->p_FmPcdPlcr) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Policer is not activated")); ++ return 0; ++ } ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ !p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs && ++ !p_FmPcd->h_IpcSession) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in \"guest-mode\" without neither IPC nor mapped register!")); ++ return 0; ++ } ++ ++ /* check that counters are enabled */ ++ if (p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs && ++ !(GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr) & FM_PCD_PLCR_GCR_STEN)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ return 0; ++ } ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs || ++ ((p_FmPcd->guestId != NCSW_MASTER_ID) && p_FmPcd->h_IpcSession)); ++ break; ++ ++ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH): ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES): ++ if (!p_FmPcd->p_FmPcdPrs) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Parser is not activated")); ++ return 0; ++ } ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ !p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs && ++ !p_FmPcd->h_IpcSession) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++ return 0; ++ } ++ break; ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported type of counter")); ++ return 0; ++ } ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ p_FmPcd->h_IpcSession) ++ { ++ t_FmPcdIpcMsg msg; ++ t_FmPcdIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_PCD_GET_COUNTER; ++ memcpy(msg.msgBody, (uint8_t *)&counter, sizeof(uint32_t)); ++ replyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) +sizeof(uint32_t), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t) + sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ ++ memcpy((uint8_t*)&outCounter, reply.replyBody, sizeof(uint32_t)); ++ return outCounter; ++ } ++ ++ switch (counter) ++ { ++ /* Parser statistics */ ++ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pds); ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rrs); ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rrs); ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rrs); ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srrs); ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rres); ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rres); ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rres); ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srres); ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spcs); ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spscs); ++ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_hxscs); ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrcs); ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrscs); ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwcs); ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwscs); ++ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_fcscs); ++ case (e_FM_PCD_KG_COUNTERS_TOTAL): ++ return GET_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_tpc); ++ ++ /* Policer statistics */ ++ case (e_FM_PCD_PLCR_COUNTERS_YELLOW): ++ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ypcnt); ++ case (e_FM_PCD_PLCR_COUNTERS_RED): ++ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rpcnt); ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED): ++ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rrpcnt); ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW): ++ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rypcnt); ++ case (e_FM_PCD_PLCR_COUNTERS_TOTAL): ++ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_tpcnt); ++ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH): ++ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_flmcnt); ++ ++ default: ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Unsupported type of counter")); ++ return 0; ++ } ++} ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++t_Error FM_PCD_DumpRegs(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ ++ DECLARE_DUMP; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPcd->p_FmPcdKg) ++ err |= FM_PCD_KgDumpRegs(h_FmPcd); ++ if (p_FmPcd->p_FmPcdPlcr) ++ err |= FM_PCD_PlcrDumpRegs(h_FmPcd); ++ if (p_FmPcd->p_FmPcdPrs) ++ err |= FM_PCD_PrsDumpRegs(h_FmPcd); ++ ++ return err; ++} ++ ++t_Error FM_PCD_HcDumpRegs(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ DECLARE_DUMP; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_STATE); ++ ++ return FmHcDumpRegs(p_FmPcd->h_Hc); ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++t_Error FM_PCD_SetException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t bitMask = 0, tmpReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetException - guest mode!")); ++ ++ GET_FM_PCD_EXCEPTION_FLAG(bitMask, exception); ++ ++ if (bitMask) ++ { ++ if (enable) ++ p_FmPcd->exceptions |= bitMask; ++ else ++ p_FmPcd->exceptions &= ~bitMask; ++ ++ switch (exception) ++ { ++ case (e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC): ++ case (e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW): ++ if (!p_FmPcd->p_FmPcdKg) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - keygen is not working")); ++ break; ++ case (e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC): ++ case (e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR): ++ case (e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE): ++ case (e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE): ++ if (!p_FmPcd->p_FmPcdPlcr) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - policer is not working")); ++ break; ++ case (e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC): ++ case (e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC): ++ if (!p_FmPcd->p_FmPcdPrs) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - parser is not working")); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported exception")); ++ ++ } ++ ++ switch (exception) ++ { ++ case (e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer); ++ if (enable) ++ tmpReg |= FM_EX_KG_DOUBLE_ECC; ++ else ++ tmpReg &= ~FM_EX_KG_DOUBLE_ECC; ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer, tmpReg); ++ break; ++ case (e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer); ++ if (enable) ++ tmpReg |= FM_EX_KG_KEYSIZE_OVERFLOW; ++ else ++ tmpReg &= ~FM_EX_KG_KEYSIZE_OVERFLOW; ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer, tmpReg); ++ break; ++ case (e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_perer); ++ if (enable) ++ tmpReg |= FM_PCD_PRS_DOUBLE_ECC; ++ else ++ tmpReg &= ~FM_PCD_PRS_DOUBLE_ECC; ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_perer, tmpReg); ++ break; ++ case (e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pever); ++ if (enable) ++ tmpReg |= FM_PCD_PRS_SINGLE_ECC; ++ else ++ tmpReg &= ~FM_PCD_PRS_SINGLE_ECC; ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pever, tmpReg); ++ break; ++ case (e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier); ++ if (enable) ++ tmpReg |= FM_PCD_PLCR_DOUBLE_ECC; ++ else ++ tmpReg &= ~FM_PCD_PLCR_DOUBLE_ECC; ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier, tmpReg); ++ break; ++ case (e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier); ++ if (enable) ++ tmpReg |= FM_PCD_PLCR_INIT_ENTRY_ERROR; ++ else ++ tmpReg &= ~FM_PCD_PLCR_INIT_ENTRY_ERROR; ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier, tmpReg); ++ break; ++ case (e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier); ++ if (enable) ++ tmpReg |= FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE; ++ else ++ tmpReg &= ~FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE; ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier, tmpReg); ++ break; ++ case (e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier); ++ if (enable) ++ tmpReg |= FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE; ++ else ++ tmpReg &= ~FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE; ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier, tmpReg); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported exception")); ++ } ++ /* for ECC exceptions driver automatically enables ECC mechanism, if disabled. ++ Driver may disable them automatically, depending on driver's status */ ++ if (enable && ( (exception == e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC) | ++ (exception == e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC) | ++ (exception == e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC) | ++ (exception == e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC))) ++ FmEnableRamsEcc(p_FmPcd->h_Fm); ++ if (!enable && ( (exception == e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC) | ++ (exception == e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC) | ++ (exception == e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC) | ++ (exception == e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC))) ++ FmDisableRamsEcc(p_FmPcd->h_Fm); ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ForceIntr (t_Handle h_FmPcd, e_FmPcdExceptions exception) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ForceIntr - guest mode!")); ++ ++ switch (exception) ++ { ++ case (e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC): ++ case (e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW): ++ if (!p_FmPcd->p_FmPcdKg) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - keygen is not working")); ++ break; ++ case (e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC): ++ case (e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR): ++ case (e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE): ++ case (e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE): ++ if (!p_FmPcd->p_FmPcdPlcr) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - policer is not working")); ++ break; ++ case (e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC): ++ case (e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC): ++ if (!p_FmPcd->p_FmPcdPrs) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt -parsrer is not working")); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Invalid interrupt requested")); ++ ++ } ++ switch (exception) ++ { ++ case e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC: ++ if (!(p_FmPcd->exceptions & FM_PCD_EX_PRS_DOUBLE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ break; ++ case e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC: ++ if (!(p_FmPcd->exceptions & FM_PCD_EX_PRS_SINGLE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ break; ++ case e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC: ++ if (!(p_FmPcd->exceptions & FM_EX_KG_DOUBLE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_feer, FM_EX_KG_DOUBLE_ECC); ++ break; ++ case e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW: ++ if (!(p_FmPcd->exceptions & FM_EX_KG_KEYSIZE_OVERFLOW)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_feer, FM_EX_KG_KEYSIZE_OVERFLOW); ++ break; ++ case e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC: ++ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_DOUBLE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, FM_PCD_PLCR_DOUBLE_ECC); ++ break; ++ case e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR: ++ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_INIT_ENTRY_ERROR)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, FM_PCD_PLCR_INIT_ENTRY_ERROR); ++ break; ++ case e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE: ++ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE); ++ break; ++ case e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE: ++ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception may not be forced")); ++ } ++ ++ return E_OK; ++} ++ ++ ++t_Error FM_PCD_ModifyCounter(t_Handle h_FmPcd, e_FmPcdCounters counter, uint32_t value) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ModifyCounter - guest mode!")); ++ ++ switch (counter) ++ { ++ case (e_FM_PCD_KG_COUNTERS_TOTAL): ++ if (!p_FmPcd->p_FmPcdKg) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Invalid counters - KeyGen is not working")); ++ break; ++ case (e_FM_PCD_PLCR_COUNTERS_YELLOW): ++ case (e_FM_PCD_PLCR_COUNTERS_RED): ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED): ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW): ++ case (e_FM_PCD_PLCR_COUNTERS_TOTAL): ++ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH): ++ if (!p_FmPcd->p_FmPcdPlcr) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Invalid counters - Policer is not working")); ++ if (!(GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr) & FM_PCD_PLCR_GCR_STEN)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH): ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES): ++ if (!p_FmPcd->p_FmPcdPrs) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported type of counter")); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported type of counter")); ++ } ++ switch (counter) ++ { ++ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pds, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rrs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rrs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rrs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srrs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rres, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rres, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rres, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srres, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spcs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spscs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_hxscs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrcs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrscs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwcs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwscs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_fcscs, value); ++ break; ++ case (e_FM_PCD_KG_COUNTERS_TOTAL): ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_tpc,value); ++ break; ++ ++ /*Policer counters*/ ++ case (e_FM_PCD_PLCR_COUNTERS_YELLOW): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ypcnt, value); ++ break; ++ case (e_FM_PCD_PLCR_COUNTERS_RED): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rpcnt, value); ++ break; ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rrpcnt, value); ++ break; ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rypcnt, value); ++ break; ++ case (e_FM_PCD_PLCR_COUNTERS_TOTAL): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_tpcnt, value); ++ break; ++ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_flmcnt, value); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported type of counter")); ++ } ++ ++ return E_OK; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_pcd.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_pcd.h +new file mode 100644 +index 0000000..b6b9b35 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_pcd.h +@@ -0,0 +1,540 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_pcd.h ++ ++ @Description FM PCD ... ++*//***************************************************************************/ ++#ifndef __FM_PCD_H ++#define __FM_PCD_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_common.h" ++#include "fsl_fman_prs.h" ++#include "fsl_fman_kg.h" ++ ++#define __ERR_MODULE__ MODULE_FM_PCD ++ ++ ++/****************************/ ++/* Defaults */ ++/****************************/ ++#define DEFAULT_plcrAutoRefresh FALSE ++#define DEFAULT_fmPcdKgErrorExceptions (FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW) ++#define DEFAULT_fmPcdPlcrErrorExceptions (FM_PCD_EX_PLCR_DOUBLE_ECC | FM_PCD_EX_PLCR_INIT_ENTRY_ERROR) ++#define DEFAULT_fmPcdPlcrExceptions 0 ++#define DEFAULT_fmPcdPrsErrorExceptions (FM_PCD_EX_PRS_DOUBLE_ECC) ++ ++#define DEFAULT_fmPcdPrsExceptions FM_PCD_EX_PRS_SINGLE_ECC ++#define DEFAULT_numOfUsedProfilesPerWindow 16 ++#define DEFAULT_numOfSharedPlcrProfiles 4 ++ ++/****************************/ ++/* Network defines */ ++/****************************/ ++#define UDP_HEADER_SIZE 8 ++ ++#define ESP_SPI_OFFSET 0 ++#define ESP_SPI_SIZE 4 ++#define ESP_SEQ_NUM_OFFSET ESP_SPI_SIZE ++#define ESP_SEQ_NUM_SIZE 4 ++ ++/****************************/ ++/* General defines */ ++/****************************/ ++#define ILLEGAL_CLS_PLAN 0xff ++#define ILLEGAL_NETENV 0xff ++ ++#define FM_PCD_MAX_NUM_OF_ALIAS_HDRS 3 ++ ++/****************************/ ++/* Error defines */ ++/****************************/ ++ ++#define FM_PCD_EX_PLCR_DOUBLE_ECC 0x20000000 ++#define FM_PCD_EX_PLCR_INIT_ENTRY_ERROR 0x10000000 ++#define FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE 0x08000000 ++#define FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE 0x04000000 ++ ++#define GET_FM_PCD_EXCEPTION_FLAG(bitMask, exception) \ ++switch (exception){ \ ++ case e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC: \ ++ bitMask = FM_EX_KG_DOUBLE_ECC; break; \ ++ case e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC: \ ++ bitMask = FM_PCD_EX_PLCR_DOUBLE_ECC; break; \ ++ case e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW: \ ++ bitMask = FM_EX_KG_KEYSIZE_OVERFLOW; break; \ ++ case e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR: \ ++ bitMask = FM_PCD_EX_PLCR_INIT_ENTRY_ERROR; break; \ ++ case e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE: \ ++ bitMask = FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE; break; \ ++ case e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE: \ ++ bitMask = FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE; break; \ ++ case e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC: \ ++ bitMask = FM_PCD_EX_PRS_DOUBLE_ECC; break; \ ++ case e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC: \ ++ bitMask = FM_PCD_EX_PRS_SINGLE_ECC; break; \ ++ default: bitMask = 0;break;} ++ ++/***********************************************************************/ ++/* Policer defines */ ++/***********************************************************************/ ++#define FM_PCD_PLCR_GCR_STEN 0x40000000 ++#define FM_PCD_PLCR_DOUBLE_ECC 0x80000000 ++#define FM_PCD_PLCR_INIT_ENTRY_ERROR 0x40000000 ++#define FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE 0x80000000 ++#define FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE 0x40000000 ++ ++/***********************************************************************/ ++/* Memory map */ ++/***********************************************************************/ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++typedef _Packed struct { ++/* General Configuration and Status Registers */ ++ volatile uint32_t fmpl_gcr; /* 0x000 FMPL_GCR - FM Policer General Configuration */ ++ volatile uint32_t fmpl_gsr; /* 0x004 FMPL_GSR - FM Policer Global Status Register */ ++ volatile uint32_t fmpl_evr; /* 0x008 FMPL_EVR - FM Policer Event Register */ ++ volatile uint32_t fmpl_ier; /* 0x00C FMPL_IER - FM Policer Interrupt Enable Register */ ++ volatile uint32_t fmpl_ifr; /* 0x010 FMPL_IFR - FM Policer Interrupt Force Register */ ++ volatile uint32_t fmpl_eevr; /* 0x014 FMPL_EEVR - FM Policer Error Event Register */ ++ volatile uint32_t fmpl_eier; /* 0x018 FMPL_EIER - FM Policer Error Interrupt Enable Register */ ++ volatile uint32_t fmpl_eifr; /* 0x01C FMPL_EIFR - FM Policer Error Interrupt Force Register */ ++/* Global Statistic Counters */ ++ volatile uint32_t fmpl_rpcnt; /* 0x020 FMPL_RPC - FM Policer RED Packets Counter */ ++ volatile uint32_t fmpl_ypcnt; /* 0x024 FMPL_YPC - FM Policer YELLOW Packets Counter */ ++ volatile uint32_t fmpl_rrpcnt; /* 0x028 FMPL_RRPC - FM Policer Recolored RED Packet Counter */ ++ volatile uint32_t fmpl_rypcnt; /* 0x02C FMPL_RYPC - FM Policer Recolored YELLOW Packet Counter */ ++ volatile uint32_t fmpl_tpcnt; /* 0x030 FMPL_TPC - FM Policer Total Packet Counter */ ++ volatile uint32_t fmpl_flmcnt; /* 0x034 FMPL_FLMC - FM Policer Frame Length Mismatch Counter */ ++ volatile uint32_t fmpl_res0[21]; /* 0x038 - 0x08B Reserved */ ++/* Profile RAM Access Registers */ ++ volatile uint32_t fmpl_par; /* 0x08C FMPL_PAR - FM Policer Profile Action Register*/ ++ t_FmPcdPlcrProfileRegs profileRegs; ++/* Error Capture Registers */ ++ volatile uint32_t fmpl_serc; /* 0x100 FMPL_SERC - FM Policer Soft Error Capture */ ++ volatile uint32_t fmpl_upcr; /* 0x104 FMPL_UPCR - FM Policer Uninitialized Profile Capture Register */ ++ volatile uint32_t fmpl_res2; /* 0x108 Reserved */ ++/* Debug Registers */ ++ volatile uint32_t fmpl_res3[61]; /* 0x10C-0x200 Reserved Debug*/ ++/* Profile Selection Mapping Registers Per Port-ID (n=1-11, 16) */ ++ volatile uint32_t fmpl_dpmr; /* 0x200 FMPL_DPMR - FM Policer Default Mapping Register */ ++ volatile uint32_t fmpl_pmr[63]; /*+default 0x204-0x2FF FMPL_PMR1 - FMPL_PMR63, - FM Policer Profile Mapping Registers. ++ (for port-ID 1-11, only for supported Port-ID registers) */ ++} _PackedType t_FmPcdPlcrRegs; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/***********************************************************************/ ++/* Driver's internal structures */ ++/***********************************************************************/ ++ ++typedef struct { ++ bool known; ++ uint8_t id; ++} t_FmPcdKgSchemesExtractsEntry; ++ ++typedef struct { ++ t_FmPcdKgSchemesExtractsEntry extractsArray[FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY]; ++} t_FmPcdKgSchemesExtracts; ++ ++typedef struct { ++ t_Handle h_Manip; ++ bool keepRes; ++ e_FmPcdEngine nextEngine; ++ uint8_t parseCode; ++} t_FmPcdInfoForManip; ++ ++/**************************************************************************//** ++ @Description A structure of parameters to communicate ++ between the port and PCD regarding the KG scheme. ++*//***************************************************************************/ ++typedef struct { ++ uint8_t netEnvId; /* in */ ++ uint8_t numOfDistinctionUnits; /* in */ ++ uint8_t unitIds[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; /* in */ ++ uint32_t vector; /* out */ ++} t_NetEnvParams; ++ ++typedef struct { ++ bool allocated; ++ uint8_t ownerId; /* guestId for KG in multi-partition only. ++ portId for PLCR in any environment */ ++} t_FmPcdAllocMng; ++ ++typedef struct { ++ volatile bool lock; ++ bool used; ++ uint8_t owners; ++ uint8_t netEnvId; ++ uint8_t guestId; ++ uint8_t baseEntry; ++ uint16_t sizeOfGrp; ++ protocolOpt_t optArray[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)]; ++} t_FmPcdKgClsPlanGrp; ++ ++typedef struct { ++ t_Handle h_FmPcd; ++ uint8_t schemeId; ++ t_FmPcdLock *p_Lock; ++ bool valid; ++ uint8_t netEnvId; ++ uint8_t owners; ++ uint32_t matchVector; ++ uint32_t ccUnits; ++ bool nextRelativePlcrProfile; ++ uint16_t relativeProfileId; ++ uint16_t numOfProfiles; ++ t_FmPcdKgKeyOrder orderedArray; ++ e_FmPcdEngine nextEngine; ++ e_FmPcdDoneAction doneAction; ++ uint8_t pointedOwners; ++ uint32_t requiredAction; ++ bool extractedOrs; ++ uint8_t bitOffsetInPlcrProfile; ++ bool directPlcr; ++#if (DPAA_VERSION >= 11) ++ bool vspe; ++#endif ++} t_FmPcdKgScheme; ++ ++typedef _Packed union { ++ struct fman_kg_scheme_regs schemeRegs; ++ struct fman_kg_pe_regs portRegs; ++ struct fman_kg_cp_regs clsPlanRegs; ++} _PackedType u_FmPcdKgIndirectAccessRegs; ++ ++typedef struct { ++ struct fman_kg_regs *p_FmPcdKgRegs; ++ uint32_t schemeExceptionsBitMask; ++ uint8_t numOfSchemes; ++ t_Handle h_HwSpinlock; ++ uint8_t schemesIds[FM_PCD_KG_NUM_OF_SCHEMES]; ++ t_FmPcdKgScheme schemes[FM_PCD_KG_NUM_OF_SCHEMES]; ++ t_FmPcdKgClsPlanGrp clsPlanGrps[FM_MAX_NUM_OF_PORTS]; ++ uint8_t emptyClsPlanGrpId; ++ t_FmPcdAllocMng schemesMng[FM_PCD_KG_NUM_OF_SCHEMES]; /* only for MASTER ! */ ++ t_FmPcdAllocMng clsPlanBlocksMng[FM_PCD_MAX_NUM_OF_CLS_PLANS/CLS_PLAN_NUM_PER_GRP]; ++ u_FmPcdKgIndirectAccessRegs *p_IndirectAccessRegs; ++} t_FmPcdKg; ++ ++typedef struct { ++ uint16_t profilesBase; ++ uint16_t numOfProfiles; ++ t_Handle h_FmPort; ++} t_FmPcdPlcrMapParam; ++ ++typedef struct { ++ uint16_t absoluteProfileId; ++ t_Handle h_FmPcd; ++ bool valid; ++ t_FmPcdLock *p_Lock; ++ t_FmPcdAllocMng profilesMng; ++ uint8_t pointedOwners; ++ uint32_t requiredAction; ++ e_FmPcdEngine nextEngineOnGreen; /**< Green next engine type */ ++ u_FmPcdPlcrNextEngineParams paramsOnGreen; /**< Green next engine params */ ++ ++ e_FmPcdEngine nextEngineOnYellow; /**< Yellow next engine type */ ++ u_FmPcdPlcrNextEngineParams paramsOnYellow; /**< Yellow next engine params */ ++ ++ e_FmPcdEngine nextEngineOnRed; /**< Red next engine type */ ++ u_FmPcdPlcrNextEngineParams paramsOnRed; /**< Red next engine params */ ++} t_FmPcdPlcrProfile; ++ ++typedef struct { ++ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs; ++ uint16_t partPlcrProfilesBase; ++ uint16_t partNumOfPlcrProfiles; ++ t_FmPcdPlcrProfile profiles[FM_PCD_PLCR_NUM_ENTRIES]; ++ uint16_t numOfSharedProfiles; ++ uint16_t sharedProfilesIds[FM_PCD_PLCR_NUM_ENTRIES]; ++ t_FmPcdPlcrMapParam portsMapping[FM_MAX_NUM_OF_PORTS]; ++ t_Handle h_HwSpinlock; ++ t_Handle h_SwSpinlock; ++} t_FmPcdPlcr; ++ ++typedef struct { ++ uint32_t *p_SwPrsCode; ++ uint32_t *p_CurrSwPrs; ++ uint8_t currLabel; ++ struct fman_prs_regs *p_FmPcdPrsRegs; ++ t_FmPcdPrsLabelParams labelsTable[FM_PCD_PRS_NUM_OF_LABELS]; ++ uint32_t fmPcdPrsPortIdStatistics; ++} t_FmPcdPrs; ++ ++typedef struct { ++ struct { ++ e_NetHeaderType hdr; ++ protocolOpt_t opt; /* only one option !! */ ++ } hdrs[FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS]; ++} t_FmPcdIntDistinctionUnit; ++ ++typedef struct { ++ e_NetHeaderType hdr; ++ protocolOpt_t opt; /* only one option !! */ ++ e_NetHeaderType aliasHdr; ++} t_FmPcdNetEnvAliases; ++ ++typedef struct { ++ uint8_t netEnvId; ++ t_Handle h_FmPcd; ++ t_Handle h_Spinlock; ++ bool used; ++ uint8_t owners; ++ uint8_t clsPlanGrpId; ++ t_FmPcdIntDistinctionUnit units[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; ++ uint32_t unitsVectors[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; ++ uint32_t lcvs[FM_PCD_PRS_NUM_OF_HDRS]; ++ uint32_t macsecVector; ++ t_FmPcdNetEnvAliases aliasHdrs[FM_PCD_MAX_NUM_OF_ALIAS_HDRS]; ++} t_FmPcdNetEnv; ++ ++typedef struct { ++ struct fman_prs_cfg dfltCfg; ++ bool plcrAutoRefresh; ++ uint16_t prsMaxParseCycleLimit; ++} t_FmPcdDriverParam; ++ ++typedef struct { ++ t_Handle h_Fm; ++ t_Handle h_FmMuram; ++ t_FmRevisionInfo fmRevInfo; ++ ++ uint64_t physicalMuramBase; ++ ++ t_Handle h_Spinlock; ++ t_List freeLocksLst; ++ t_List acquiredLocksLst; ++ ++ t_Handle h_IpcSession; /* relevant for guest only */ ++ bool enabled; ++ uint8_t guestId; /**< Guest Partition Id */ ++ uint8_t numOfEnabledGuestPartitionsPcds; ++ char fmPcdModuleName[MODULE_NAME_SIZE]; ++ char fmPcdIpcHandlerModuleName[MODULE_NAME_SIZE]; /* relevant for guest only - this is the master's name */ ++ t_FmPcdNetEnv netEnvs[FM_MAX_NUM_OF_PORTS]; ++ t_FmPcdKg *p_FmPcdKg; ++ t_FmPcdPlcr *p_FmPcdPlcr; ++ t_FmPcdPrs *p_FmPcdPrs; ++ ++ void *p_CcShadow; /**< CC MURAM shadow */ ++ uint32_t ccShadowSize; ++ uint32_t ccShadowAlign; ++ volatile bool shadowLock; ++ t_Handle h_ShadowSpinlock; ++ ++ t_Handle h_Hc; ++ ++ uint32_t exceptions; ++ t_FmPcdExceptionCallback *f_Exception; ++ t_FmPcdIdExceptionCallback *f_FmPcdIndexedException; ++ t_Handle h_App; ++ uintptr_t ipv6FrameIdAddr; ++ bool advancedOffloadSupport; ++ ++ t_FmPcdDriverParam *p_FmPcdDriverParam; ++} t_FmPcd; ++ ++#if (DPAA_VERSION >= 11) ++typedef uint8_t t_FmPcdFrmReplicUpdateType; ++#define FRM_REPLIC_UPDATE_COUNTER 0x01 ++#define FRM_REPLIC_UPDATE_INFO 0x02 ++#endif /* (DPAA_VERSION >= 11) */ ++/***********************************************************************/ ++/* PCD internal routines */ ++/***********************************************************************/ ++ ++t_Error PcdGetVectorForOpt(t_FmPcd *p_FmPcd, uint8_t netEnvId, protocolOpt_t opt, uint32_t *p_Vector); ++t_Error PcdGetUnitsVector(t_FmPcd *p_FmPcd, t_NetEnvParams *p_Params); ++bool PcdNetEnvIsUnitWithoutOpts(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint32_t unitVector); ++t_Error PcdGetClsPlanGrpParams(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_GrpParams); ++void FmPcdSetClsPlanGrpId(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint8_t clsPlanGrpId); ++e_NetHeaderType FmPcdGetAliasHdr(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr); ++uint8_t FmPcdNetEnvGetUnitIdForSingleHdr(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr); ++uint8_t FmPcdNetEnvGetUnitId(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr, bool interchangable, protocolOpt_t opt); ++ ++t_Error FmPcdManipBuildIpReassmScheme(t_FmPcd *p_FmPcd, t_Handle h_NetEnv, t_Handle h_CcTree, t_Handle h_Manip, bool isIpv4, uint8_t groupId); ++t_Error FmPcdManipDeleteIpReassmSchemes(t_Handle h_Manip); ++bool FmPcdManipIpReassmIsIpv6Hdr(t_Handle h_Manip); ++ ++t_Handle KgConfig( t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams); ++t_Error KgInit(t_FmPcd *p_FmPcd); ++t_Error KgFree(t_FmPcd *p_FmPcd); ++void KgSetClsPlan(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanSet *p_Set); ++bool KgIsSchemeAlwaysDirect(t_Handle h_FmPcd, uint8_t schemeId); ++void KgEnable(t_FmPcd *p_FmPcd); ++void KgDisable(t_FmPcd *p_FmPcd); ++t_Error KgAllocClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t *p_First); ++void KgFreeClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t base); ++ ++/* only for MULTI partittion */ ++t_Error FmPcdKgAllocSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds); ++t_Error FmPcdKgFreeSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds); ++/* only for SINGLE partittion */ ++t_Error KgBindPortToSchemes(t_Handle h_FmPcd , uint8_t hardwarePortId, uint32_t spReg); ++ ++t_FmPcdLock *FmPcdAcquireLock(t_Handle h_FmPcd); ++void FmPcdReleaseLock(t_Handle h_FmPcd, t_FmPcdLock *p_Lock); ++ ++t_Handle PlcrConfig(t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams); ++t_Error PlcrInit(t_FmPcd *p_FmPcd); ++t_Error PlcrFree(t_FmPcd *p_FmPcd); ++void PlcrEnable(t_FmPcd *p_FmPcd); ++void PlcrDisable(t_FmPcd *p_FmPcd); ++uint16_t PlcrAllocProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId); ++void PlcrFreeProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId); ++t_Error PlcrSetPortProfiles(t_FmPcd *p_FmPcd, ++ uint8_t hardwarePortId, ++ uint16_t numOfProfiles, ++ uint16_t base); ++t_Error PlcrClearPortProfiles(t_FmPcd *p_FmPcd, uint8_t hardwarePortId); ++ ++t_Handle PrsConfig(t_FmPcd *p_FmPcd,t_FmPcdParams *p_FmPcdParams); ++t_Error PrsInit(t_FmPcd *p_FmPcd); ++void PrsEnable(t_FmPcd *p_FmPcd); ++void PrsDisable(t_FmPcd *p_FmPcd); ++void PrsFree(t_FmPcd *p_FmPcd ); ++t_Error PrsIncludePortInStatistics(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, bool include); ++ ++t_Error FmPcdCcGetGrpParams(t_Handle treeId, uint8_t grpId, uint32_t *p_GrpBits, uint8_t *p_GrpBase); ++uint8_t FmPcdCcGetOffset(t_Handle h_CcNode); ++uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode); ++uint16_t FmPcdCcGetNumOfKeys(t_Handle h_CcNode); ++t_Error ValidateNextEngineParams(t_Handle h_FmPcd, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, e_FmPcdCcStatsMode supportedStatsMode); ++ ++void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add); ++t_Error FmPcdManipCheckParamsForCcNextEngine(t_FmPcdCcNextEngineParams *p_InfoForManip, uint32_t *requiredAction); ++void FmPcdManipUpdateAdResultForCc(t_Handle h_Manip, ++ t_FmPcdCcNextEngineParams *p_CcNextEngineParams, ++ t_Handle p_Ad, ++ t_Handle *p_AdNewPtr); ++void FmPcdManipUpdateAdContLookupForCc(t_Handle h_Manip, t_Handle p_Ad, t_Handle *p_AdNew, uint32_t adTableOffset); ++void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add); ++t_Error FmPcdManipCheckParamsWithCcNodeParams(t_Handle h_Manip, t_Handle h_FmPcdCcNode); ++#ifdef FM_CAPWAP_SUPPORT ++t_Handle FmPcdManipApplSpecificBuild(void); ++bool FmPcdManipIsCapwapApplSpecific(t_Handle h_Manip); ++#endif /* FM_CAPWAP_SUPPORT */ ++#if (DPAA_VERSION >= 11) ++void * FrmReplicGroupGetSourceTableDescriptor(t_Handle h_ReplicGroup); ++void FrmReplicGroupUpdateOwner(t_Handle h_ReplicGroup, bool add); ++void FrmReplicGroupUpdateAd(t_Handle h_ReplicGroup, void *p_Ad, t_Handle *h_AdNew); ++ ++void FmPcdCcGetAdTablesThatPointOnReplicGroup(t_Handle h_Node, ++ t_Handle h_ReplicGroup, ++ t_List *p_AdTables, ++ uint32_t *p_NumOfAdTables); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++void EnqueueNodeInfoToRelevantLst(t_List *p_List, t_CcNodeInformation *p_CcInfo, t_Handle h_Spinlock); ++void DequeueNodeInfoFromRelevantLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock); ++t_CcNodeInformation* FindNodeInfoInReleventLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock); ++t_List *FmPcdManipGetSpinlock(t_Handle h_Manip); ++t_List *FmPcdManipGetNodeLstPointedOnThisManip(t_Handle h_Manip); ++ ++typedef struct ++{ ++ t_Handle h_StatsAd; ++ t_Handle h_StatsCounters; ++#if (DPAA_VERSION >= 11) ++ t_Handle h_StatsFLRs; ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmPcdCcStatsParams; ++ ++void NextStepAd(t_Handle h_Ad, ++ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, ++ t_FmPcd *p_FmPcd); ++void ReleaseLst(t_List *p_List); ++ ++static __inline__ t_Handle FmPcdGetMuramHandle(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ASSERT_COND(p_FmPcd); ++ return p_FmPcd->h_FmMuram; ++} ++ ++static __inline__ uint64_t FmPcdGetMuramPhysBase(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ASSERT_COND(p_FmPcd); ++ return p_FmPcd->physicalMuramBase; ++} ++ ++static __inline__ uint32_t FmPcdLockSpinlock(t_FmPcdLock *p_Lock) ++{ ++ ASSERT_COND(p_Lock); ++ return XX_LockIntrSpinlock(p_Lock->h_Spinlock); ++} ++ ++static __inline__ void FmPcdUnlockSpinlock(t_FmPcdLock *p_Lock, uint32_t flags) ++{ ++ ASSERT_COND(p_Lock); ++ XX_UnlockIntrSpinlock(p_Lock->h_Spinlock, flags); ++} ++ ++static __inline__ bool FmPcdLockTryLock(t_FmPcdLock *p_Lock) ++{ ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_Lock); ++ intFlags = XX_LockIntrSpinlock(p_Lock->h_Spinlock); ++ if (p_Lock->flag) ++ { ++ XX_UnlockIntrSpinlock(p_Lock->h_Spinlock, intFlags); ++ return FALSE; ++ } ++ p_Lock->flag = TRUE; ++ XX_UnlockIntrSpinlock(p_Lock->h_Spinlock, intFlags); ++ return TRUE; ++} ++ ++static __inline__ void FmPcdLockUnlock(t_FmPcdLock *p_Lock) ++{ ++ ASSERT_COND(p_Lock); ++ p_Lock->flag = FALSE; ++} ++ ++ ++#endif /* __FM_PCD_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_pcd_ipc.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_pcd_ipc.h +new file mode 100644 +index 0000000..5184ce6 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_pcd_ipc.h +@@ -0,0 +1,280 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_pcd_ipc.h ++ ++ @Description FM PCD Inter-Partition prototypes, structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_PCD_IPC_H ++#define __FM_PCD_IPC_H ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description Structure for getting a sw parser address according to a label ++ Fields commented 'IN' are passed by the port module to be used ++ by the FM module. ++ Fields commented 'OUT' will be filled by FM before returning to port. ++*//***************************************************************************/ ++typedef _Packed struct t_FmPcdIpcSwPrsLable ++{ ++ uint32_t enumHdr; /**< IN. The existance of this header will envoke ++ the sw parser code. */ ++ uint8_t indexPerHdr; /**< IN. Normally 0, if more than one sw parser ++ attachments for the same header, use this ++ ++ index to distinguish between them. */ ++} _PackedType t_FmPcdIpcSwPrsLable; ++ ++/**************************************************************************//** ++ @Description Structure for port-PCD communication. ++ Fields commented 'IN' are passed by the port module to be used ++ by the FM module. ++ Fields commented 'OUT' will be filled by FM before returning to port. ++ Some fields are optional (depending on configuration) and ++ will be analized by the port and FM modules accordingly. ++*//***************************************************************************/ ++ ++typedef struct t_FmPcdIpcKgSchemesParams ++{ ++ uint8_t guestId; ++ uint8_t numOfSchemes; ++ uint8_t schemesIds[FM_PCD_KG_NUM_OF_SCHEMES]; ++} _PackedType t_FmPcdIpcKgSchemesParams; ++ ++typedef struct t_FmPcdIpcKgClsPlanParams ++{ ++ uint8_t guestId; ++ uint16_t numOfClsPlanEntries; ++ uint8_t clsPlanBase; ++} _PackedType t_FmPcdIpcKgClsPlanParams; ++ ++typedef _Packed struct t_FmPcdIpcPrsIncludePort ++{ ++ uint8_t hardwarePortId; ++ bool include; ++} _PackedType t_FmPcdIpcPrsIncludePort; ++ ++ ++#define FM_PCD_MAX_REPLY_SIZE 16 ++#define FM_PCD_MAX_MSG_SIZE 36 ++#define FM_PCD_MAX_REPLY_BODY_SIZE 36 ++ ++typedef _Packed struct { ++ uint32_t msgId; ++ uint8_t msgBody[FM_PCD_MAX_MSG_SIZE]; ++} _PackedType t_FmPcdIpcMsg; ++ ++typedef _Packed struct t_FmPcdIpcReply { ++ uint32_t error; ++ uint8_t replyBody[FM_PCD_MAX_REPLY_BODY_SIZE]; ++} _PackedType t_FmPcdIpcReply; ++ ++typedef _Packed struct t_FmIpcResourceAllocParams { ++ uint8_t guestId; ++ uint16_t base; ++ uint16_t num; ++}_PackedType t_FmIpcResourceAllocParams; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++ ++/**************************************************************************//** ++ @Function FM_PCD_ALLOC_KG_SCHEMES ++ ++ @Description Used by FM PCD front-end in order to allocate KG resources ++ ++ @Param[in/out] t_FmPcdIpcKgAllocParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_ALLOC_KG_SCHEMES 3 ++ ++/**************************************************************************//** ++ @Function FM_PCD_FREE_KG_SCHEMES ++ ++ @Description Used by FM PCD front-end in order to Free KG resources ++ ++ @Param[in/out] t_FmPcdIpcKgSchemesParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_FREE_KG_SCHEMES 4 ++ ++/**************************************************************************//** ++ @Function FM_PCD_ALLOC_PROFILES ++ ++ @Description Used by FM PCD front-end in order to allocate Policer profiles ++ ++ @Param[in/out] t_FmIpcResourceAllocParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_ALLOC_PROFILES 5 ++ ++/**************************************************************************//** ++ @Function FM_PCD_FREE_PROFILES ++ ++ @Description Used by FM PCD front-end in order to Free Policer profiles ++ ++ @Param[in/out] t_FmIpcResourceAllocParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_FREE_PROFILES 6 ++ ++/**************************************************************************//** ++ @Function FM_PCD_SET_PORT_PROFILES ++ ++ @Description Used by FM PCD front-end in order to allocate Policer profiles ++ for specific port ++ ++ @Param[in/out] t_FmIpcResourceAllocParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_SET_PORT_PROFILES 7 ++ ++/**************************************************************************//** ++ @Function FM_PCD_CLEAR_PORT_PROFILES ++ ++ @Description Used by FM PCD front-end in order to allocate Policer profiles ++ for specific port ++ ++ @Param[in/out] t_FmIpcResourceAllocParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_CLEAR_PORT_PROFILES 8 ++ ++/**************************************************************************//** ++ @Function FM_PCD_GET_PHYS_MURAM_BASE ++ ++ @Description Used by FM PCD front-end in order to get MURAM base address ++ ++ @Param[in/out] t_FmPcdIcPhysAddr Pointer ++*//***************************************************************************/ ++#define FM_PCD_GET_PHYS_MURAM_BASE 9 ++ ++/**************************************************************************//** ++ @Function FM_PCD_GET_SW_PRS_OFFSET ++ ++ @Description Used by FM front-end to get the SW parser offset of the start of ++ code relevant to a given label. ++ ++ @Param[in/out] t_FmPcdIpcSwPrsLable Pointer ++*//***************************************************************************/ ++#define FM_PCD_GET_SW_PRS_OFFSET 10 ++ ++/**************************************************************************//** ++ @Function FM_PCD_MASTER_IS_ENABLED ++ ++ @Description Used by FM front-end in order to verify ++ PCD enablement. ++ ++ @Param[in] bool Pointer ++*//***************************************************************************/ ++#define FM_PCD_MASTER_IS_ENABLED 15 ++ ++/**************************************************************************//** ++ @Function FM_PCD_GUEST_DISABLE ++ ++ @Description Used by FM front-end to inform back-end when ++ front-end PCD is disabled ++ ++ @Param[in] None ++*//***************************************************************************/ ++#define FM_PCD_GUEST_DISABLE 16 ++ ++/**************************************************************************//** ++ @Function FM_PCD_FREE_KG_CLSPLAN ++ ++ @Description Used by FM PCD front-end in order to Free KG classification plan entries ++ ++ @Param[in/out] t_FmPcdIpcKgClsPlanParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_FREE_KG_CLSPLAN 22 ++ ++/**************************************************************************//** ++ @Function FM_PCD_ALLOC_KG_CLSPLAN ++ ++ @Description Used by FM PCD front-end in order to allocate KG classification plan entries ++ ++ @Param[in/out] t_FmPcdIpcKgClsPlanParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_ALLOC_KG_CLSPLAN 23 ++ ++/**************************************************************************//** ++ @Function FM_PCD_MASTER_IS_ALIVE ++ ++ @Description Used by FM front-end to check that back-end exists ++ ++ @Param[in] None ++*//***************************************************************************/ ++#define FM_PCD_MASTER_IS_ALIVE 24 ++ ++/**************************************************************************//** ++ @Function FM_PCD_GET_COUNTER ++ ++ @Description Used by FM front-end to read PCD counters ++ ++ @Param[in/out] t_FmPcdIpcGetCounter Pointer ++*//***************************************************************************/ ++#define FM_PCD_GET_COUNTER 25 ++ ++/**************************************************************************//** ++ @Function FM_PCD_PRS_INC_PORT_STATS ++ ++ @Description Used by FM front-end to set/clear statistics for port ++ ++ @Param[in/out] t_FmPcdIpcPrsIncludePort Pointer ++*//***************************************************************************/ ++#define FM_PCD_PRS_INC_PORT_STATS 26 ++ ++#if (DPAA_VERSION >= 11) ++/* TODO - doc */ ++#define FM_PCD_ALLOC_SP 27 ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++/** @} */ /* end of FM_PCD_IPC_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#endif /* __FM_PCD_IPC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_plcr.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_plcr.c +new file mode 100644 +index 0000000..ded7960 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_plcr.c +@@ -0,0 +1,1927 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_plcr.c ++ ++ @Description FM PCD POLICER... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "net_ext.h" ++#include "fm_ext.h" ++ ++#include "fm_common.h" ++#include "fm_pcd.h" ++#include "fm_hc.h" ++#include "fm_pcd_ipc.h" ++#include "fm_plcr.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++static uint32_t PlcrProfileLock(t_Handle h_Profile) ++{ ++ ASSERT_COND(h_Profile); ++ return FmPcdLockSpinlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock); ++} ++ ++static void PlcrProfileUnlock(t_Handle h_Profile, uint32_t intFlags) ++{ ++ ASSERT_COND(h_Profile); ++ FmPcdUnlockSpinlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock, intFlags); ++} ++ ++static bool PlcrProfileFlagTryLock(t_Handle h_Profile) ++{ ++ ASSERT_COND(h_Profile); ++ return FmPcdLockTryLock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock); ++} ++ ++static void PlcrProfileFlagUnlock(t_Handle h_Profile) ++{ ++ ASSERT_COND(h_Profile); ++ FmPcdLockUnlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock); ++} ++ ++static uint32_t PlcrHwLock(t_Handle h_FmPcdPlcr) ++{ ++ ASSERT_COND(h_FmPcdPlcr); ++ return XX_LockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_HwSpinlock); ++} ++ ++static void PlcrHwUnlock(t_Handle h_FmPcdPlcr, uint32_t intFlags) ++{ ++ ASSERT_COND(h_FmPcdPlcr); ++ XX_UnlockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_HwSpinlock, intFlags); ++} ++ ++static uint32_t PlcrSwLock(t_Handle h_FmPcdPlcr) ++{ ++ ASSERT_COND(h_FmPcdPlcr); ++ return XX_LockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_SwSpinlock); ++} ++ ++static void PlcrSwUnlock(t_Handle h_FmPcdPlcr, uint32_t intFlags) ++{ ++ ASSERT_COND(h_FmPcdPlcr); ++ XX_UnlockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_SwSpinlock, intFlags); ++} ++ ++static bool IsProfileShared(t_Handle h_FmPcd, uint16_t absoluteProfileId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint16_t i; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, FALSE); ++ ++ for (i=0;ip_FmPcdPlcr->numOfSharedProfiles;i++) ++ if (p_FmPcd->p_FmPcdPlcr->sharedProfilesIds[i] == absoluteProfileId) ++ return TRUE; ++ return FALSE; ++} ++ ++static t_Error SetProfileNia(t_FmPcd *p_FmPcd, e_FmPcdEngine nextEngine, u_FmPcdPlcrNextEngineParams *p_NextEngineParams, uint32_t *nextAction) ++{ ++ uint32_t nia; ++ uint16_t absoluteProfileId; ++ uint8_t relativeSchemeId, physicalSchemeId; ++ ++ nia = FM_PCD_PLCR_NIA_VALID; ++ ++ switch (nextEngine) ++ { ++ case e_FM_PCD_DONE : ++ switch (p_NextEngineParams->action) ++ { ++ case e_FM_PCD_DROP_FRAME : ++ nia |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd); ++ break; ++ case e_FM_PCD_ENQ_FRAME: ++ nia |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ break; ++ case e_FM_PCD_KG: ++ physicalSchemeId = FmPcdKgGetSchemeId(p_NextEngineParams->h_DirectScheme); ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId); ++ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ if (!FmPcdKgIsSchemeValidSw(p_NextEngineParams->h_DirectScheme)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid direct scheme.")); ++ if (!KgIsSchemeAlwaysDirect(p_FmPcd, relativeSchemeId)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Policer Profile may point only to a scheme that is always direct.")); ++ nia |= NIA_ENG_KG | NIA_KG_DIRECT | physicalSchemeId; ++ break; ++ case e_FM_PCD_PLCR: ++ absoluteProfileId = ((t_FmPcdPlcrProfile *)p_NextEngineParams->h_Profile)->absoluteProfileId; ++ if (!IsProfileShared(p_FmPcd, absoluteProfileId)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next profile must be a shared profile")); ++ if (!FmPcdPlcrIsProfileValid(p_FmPcd, absoluteProfileId)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid profile ")); ++ nia |= NIA_ENG_PLCR | NIA_PLCR_ABSOLUTE | absoluteProfileId; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ *nextAction = nia; ++ ++ return E_OK; ++} ++ ++static uint32_t CalcFPP(uint32_t fpp) ++{ ++ if (fpp > 15) ++ return 15 - (0x1f - fpp); ++ else ++ return 16 + fpp; ++} ++ ++static void GetInfoRateReg(e_FmPcdPlcrRateMode rateMode, ++ uint32_t rate, ++ uint64_t tsuInTenthNano, ++ uint32_t fppShift, ++ uint64_t *p_Integer, ++ uint64_t *p_Fraction) ++{ ++ uint64_t tmp, div; ++ ++ if (rateMode == e_FM_PCD_PLCR_BYTE_MODE) ++ { ++ /* now we calculate the initial integer for the bigger rate */ ++ /* from Kbps to Bytes/TSU */ ++ tmp = (uint64_t)rate; ++ tmp *= 1000; /* kb --> b */ ++ tmp *= tsuInTenthNano; /* bps --> bpTsu(in 10nano) */ ++ ++ div = 1000000000; /* nano */ ++ div *= 10; /* 10 nano */ ++ div *= 8; /* bit to byte */ ++ } ++ else ++ { ++ /* now we calculate the initial integer for the bigger rate */ ++ /* from Kbps to Bytes/TSU */ ++ tmp = (uint64_t)rate; ++ tmp *= tsuInTenthNano; /* bps --> bpTsu(in 10nano) */ ++ ++ div = 1000000000; /* nano */ ++ div *= 10; /* 10 nano */ ++ } ++ *p_Integer = (tmp<h_Fm); /* TimeStamp per nano seconds units */ ++ /* we want the tsu to count 10 nano for better precision normally tsu is 3.9 nano, now we will get 39 */ ++ tsuInTenthNanos = (uint32_t)(1000*10/(1<comittedInfoRate > p_NonPassthroughAlgParam->peakOrAccessiveInfoRate) ++ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->comittedInfoRate, tsuInTenthNanos, 0, &integer, &fraction); ++ else ++ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->peakOrAccessiveInfoRate, tsuInTenthNanos, 0, &integer, &fraction); ++ ++ /* we shift integer, as in cir/pir it is represented by the MSB 16 bits, and ++ * the LSB bits are for the fraction */ ++ temp = (uint32_t)((integer<<16) & 0x00000000FFFFFFFF); ++ /* temp is effected by the rate. For low rates it may be as low as 0, and then we'll ++ * take max FP = 31. ++ * For high rates it will never exceed the 32 bit reg (after the 16 shift), as it is ++ * limited by the 10G physical port. ++ */ ++ if (temp != 0) ++ { ++ /* In this case, the largest rate integer is non 0, if it does not occupy all (high) 16 ++ * bits of the PIR_EIR we can use this fact and enlarge it to occupy all 16 bits. ++ * The logic is to have as many bits for integer in the higher rates, but if we have "0"s ++ * in the integer part of the cir/pir register, than these bits are wasted. So we want ++ * to use these bits for the fraction. in this way we will have for fraction - the number ++ * of "0" bits and the rest - for integer. ++ * In other words: For each bit we shift it in PIR_EIR, we move the FP in the TS ++ * one bit to the left - preserving the relationship and achieving more bits ++ * for integer in the TS. ++ */ ++ ++ /* count zeroes left of the higher used bit (in order to shift the value such that ++ * unused bits may be used for fraction). ++ */ ++ while ((temp & 0x80000000) == 0) ++ { ++ temp = temp << 1; ++ fppShift++; ++ } ++ if (fppShift > 15) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, ("timeStampPeriod to Information rate ratio is too small")); ++ return; ++ } ++ } ++ else ++ { ++ temp = (uint32_t)fraction; /* fraction will alyas be smaller than 2^16 */ ++ if (!temp) ++ /* integer and fraction are 0, we set FP to its max val */ ++ fppShift = 31; ++ else ++ { ++ /* integer was 0 but fraction is not. FP is 16 for the fraction, ++ * + all left zeroes of the fraction. */ ++ fppShift=16; ++ /* count zeroes left of the higher used bit (in order to shift the value such that ++ * unused bits may be used for fraction). ++ */ ++ while ((temp & 0x8000) == 0) ++ { ++ temp = temp << 1; ++ fppShift++; ++ } ++ } ++ } ++ ++ /* ++ * This means that the FM TS register will now be used so that 'fppShift' bits are for ++ * fraction and the rest for integer */ ++ /* now we re-calculate cir and pir_eir with the calculated FP */ ++ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->comittedInfoRate, tsuInTenthNanos, fppShift, &integer, &fraction); ++ *cir = (uint32_t)(integer << 16 | (fraction & 0xFFFF)); ++ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->peakOrAccessiveInfoRate, tsuInTenthNanos, fppShift, &integer, &fraction); ++ *pir_eir = (uint32_t)(integer << 16 | (fraction & 0xFFFF)); ++ ++ *cbs = p_NonPassthroughAlgParam->comittedBurstSize; ++ *pbs_ebs = p_NonPassthroughAlgParam->peakOrAccessiveBurstSize; ++ ++ /* convert FP as it should be written to reg. ++ * 0-15 --> 16-31 ++ * 16-31 --> 0-15 ++ */ ++ *fpp = CalcFPP(fppShift); ++} ++ ++static void WritePar(t_FmPcd *p_FmPcd, uint32_t par) ++{ ++ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ WRITE_UINT32(p_FmPcdPlcrRegs->fmpl_par, par); ++ ++ while (GET_UINT32(p_FmPcdPlcrRegs->fmpl_par) & FM_PCD_PLCR_PAR_GO) ; ++} ++ ++static t_Error BuildProfileRegs(t_FmPcd *p_FmPcd, ++ t_FmPcdPlcrProfileParams *p_ProfileParams, ++ t_FmPcdPlcrProfileRegs *p_PlcrRegs) ++{ ++ t_Error err = E_OK; ++ uint32_t pemode, gnia, ynia, rnia; ++ ++ ASSERT_COND(p_FmPcd); ++ ++/* Set G, Y, R Nia */ ++ err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnGreen, &(p_ProfileParams->paramsOnGreen), &gnia); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnYellow, &(p_ProfileParams->paramsOnYellow), &ynia); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnRed, &(p_ProfileParams->paramsOnRed), &rnia); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++/* Mode fmpl_pemode */ ++ pemode = FM_PCD_PLCR_PEMODE_PI; ++ ++ switch (p_ProfileParams->algSelection) ++ { ++ case e_FM_PCD_PLCR_PASS_THROUGH: ++ p_PlcrRegs->fmpl_pecir = 0; ++ p_PlcrRegs->fmpl_pecbs = 0; ++ p_PlcrRegs->fmpl_pepepir_eir = 0; ++ p_PlcrRegs->fmpl_pepbs_ebs = 0; ++ p_PlcrRegs->fmpl_pelts = 0; ++ p_PlcrRegs->fmpl_pects = 0; ++ p_PlcrRegs->fmpl_pepts_ets = 0; ++ pemode &= ~FM_PCD_PLCR_PEMODE_ALG_MASK; ++ switch (p_ProfileParams->colorMode) ++ { ++ case e_FM_PCD_PLCR_COLOR_BLIND: ++ pemode |= FM_PCD_PLCR_PEMODE_CBLND; ++ switch (p_ProfileParams->color.dfltColor) ++ { ++ case e_FM_PCD_PLCR_GREEN: ++ pemode &= ~FM_PCD_PLCR_PEMODE_DEFC_MASK; ++ break; ++ case e_FM_PCD_PLCR_YELLOW: ++ pemode |= FM_PCD_PLCR_PEMODE_DEFC_Y; ++ break; ++ case e_FM_PCD_PLCR_RED: ++ pemode |= FM_PCD_PLCR_PEMODE_DEFC_R; ++ break; ++ case e_FM_PCD_PLCR_OVERRIDE: ++ pemode |= FM_PCD_PLCR_PEMODE_DEFC_OVERRIDE; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ break; ++ case e_FM_PCD_PLCR_COLOR_AWARE: ++ pemode &= ~FM_PCD_PLCR_PEMODE_CBLND; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ break; ++ ++ case e_FM_PCD_PLCR_RFC_2698: ++ /* Select algorithm MODE[ALG] = "01" */ ++ pemode |= FM_PCD_PLCR_PEMODE_ALG_RFC2698; ++ if (p_ProfileParams->nonPassthroughAlgParams.comittedInfoRate > p_ProfileParams->nonPassthroughAlgParams.peakOrAccessiveInfoRate) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("in RFC2698 Peak rate must be equal or larger than comittedInfoRate.")); ++ goto cont_rfc; ++ case e_FM_PCD_PLCR_RFC_4115: ++ /* Select algorithm MODE[ALG] = "10" */ ++ pemode |= FM_PCD_PLCR_PEMODE_ALG_RFC4115; ++cont_rfc: ++ /* Select Color-Blind / Color-Aware operation (MODE[CBLND]) */ ++ switch (p_ProfileParams->colorMode) ++ { ++ case e_FM_PCD_PLCR_COLOR_BLIND: ++ pemode |= FM_PCD_PLCR_PEMODE_CBLND; ++ break; ++ case e_FM_PCD_PLCR_COLOR_AWARE: ++ pemode &= ~FM_PCD_PLCR_PEMODE_CBLND; ++ /*In color aware more select override color interpretation (MODE[OVCLR]) */ ++ switch (p_ProfileParams->color.override) ++ { ++ case e_FM_PCD_PLCR_GREEN: ++ pemode &= ~FM_PCD_PLCR_PEMODE_OVCLR_MASK; ++ break; ++ case e_FM_PCD_PLCR_YELLOW: ++ pemode |= FM_PCD_PLCR_PEMODE_OVCLR_Y; ++ break; ++ case e_FM_PCD_PLCR_RED: ++ pemode |= FM_PCD_PLCR_PEMODE_OVCLR_R; ++ break; ++ case e_FM_PCD_PLCR_OVERRIDE: ++ pemode |= FM_PCD_PLCR_PEMODE_OVCLR_G_NC; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ /* Select Measurement Unit Mode to BYTE or PACKET (MODE[PKT]) */ ++ switch (p_ProfileParams->nonPassthroughAlgParams.rateMode) ++ { ++ case e_FM_PCD_PLCR_BYTE_MODE : ++ pemode &= ~FM_PCD_PLCR_PEMODE_PKT; ++ switch (p_ProfileParams->nonPassthroughAlgParams.byteModeParams.frameLengthSelection) ++ { ++ case e_FM_PCD_PLCR_L2_FRM_LEN: ++ pemode |= FM_PCD_PLCR_PEMODE_FLS_L2; ++ break; ++ case e_FM_PCD_PLCR_L3_FRM_LEN: ++ pemode |= FM_PCD_PLCR_PEMODE_FLS_L3; ++ break; ++ case e_FM_PCD_PLCR_L4_FRM_LEN: ++ pemode |= FM_PCD_PLCR_PEMODE_FLS_L4; ++ break; ++ case e_FM_PCD_PLCR_FULL_FRM_LEN: ++ pemode |= FM_PCD_PLCR_PEMODE_FLS_FULL; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ switch (p_ProfileParams->nonPassthroughAlgParams.byteModeParams.rollBackFrameSelection) ++ { ++ case e_FM_PCD_PLCR_ROLLBACK_L2_FRM_LEN: ++ pemode &= ~FM_PCD_PLCR_PEMODE_RBFLS; ++ break; ++ case e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN: ++ pemode |= FM_PCD_PLCR_PEMODE_RBFLS; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ break; ++ case e_FM_PCD_PLCR_PACKET_MODE : ++ pemode |= FM_PCD_PLCR_PEMODE_PKT; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ /* Select timeStamp floating point position (MODE[FPP]) to fit the actual traffic rates. For PACKET ++ mode with low traffic rates move the fixed point to the left to increase fraction accuracy. For BYTE ++ mode with high traffic rates move the fixed point to the right to increase integer accuracy. */ ++ ++ /* Configure Traffic Parameters*/ ++ { ++ uint32_t cir=0, cbs=0, pir_eir=0, pbs_ebs=0, fpp=0; ++ ++ CalcRates(p_FmPcd, &p_ProfileParams->nonPassthroughAlgParams, &cir, &cbs, &pir_eir, &pbs_ebs, &fpp); ++ ++ /* Set Committed Information Rate (CIR) */ ++ p_PlcrRegs->fmpl_pecir = cir; ++ /* Set Committed Burst Size (CBS). */ ++ p_PlcrRegs->fmpl_pecbs = cbs; ++ /* Set Peak Information Rate (PIR_EIR used as PIR) */ ++ p_PlcrRegs->fmpl_pepepir_eir = pir_eir; ++ /* Set Peak Burst Size (PBS_EBS used as PBS) */ ++ p_PlcrRegs->fmpl_pepbs_ebs = pbs_ebs; ++ ++ /* Initialize the Metering Buckets to be full (write them with 0xFFFFFFFF. */ ++ /* Peak Rate Token Bucket Size (PTS_ETS used as PTS) */ ++ p_PlcrRegs->fmpl_pepts_ets = 0xFFFFFFFF; ++ /* Committed Rate Token Bucket Size (CTS) */ ++ p_PlcrRegs->fmpl_pects = 0xFFFFFFFF; ++ ++ /* Set the FPP based on calculation */ ++ pemode |= (fpp << FM_PCD_PLCR_PEMODE_FPP_SHIFT); ++ } ++ break; /* FM_PCD_PLCR_PEMODE_ALG_RFC2698 , FM_PCD_PLCR_PEMODE_ALG_RFC4115 */ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ p_PlcrRegs->fmpl_pemode = pemode; ++ ++ p_PlcrRegs->fmpl_pegnia = gnia; ++ p_PlcrRegs->fmpl_peynia = ynia; ++ p_PlcrRegs->fmpl_pernia = rnia; ++ ++ /* Zero Counters */ ++ p_PlcrRegs->fmpl_pegpc = 0; ++ p_PlcrRegs->fmpl_peypc = 0; ++ p_PlcrRegs->fmpl_perpc = 0; ++ p_PlcrRegs->fmpl_perypc = 0; ++ p_PlcrRegs->fmpl_perrpc = 0; ++ ++ return E_OK; ++} ++ ++static t_Error AllocSharedProfiles(t_FmPcd *p_FmPcd, uint16_t numOfProfiles, uint16_t *profilesIds) ++{ ++ uint32_t profilesFound; ++ uint16_t i, k=0; ++ uint32_t intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ if (!numOfProfiles) ++ return E_OK; ++ ++ if (numOfProfiles>FM_PCD_PLCR_NUM_ENTRIES) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles is too big.")); ++ ++ intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr); ++ /* Find numOfProfiles free profiles (may be spread) */ ++ profilesFound = 0; ++ for (i=0;ip_FmPcdPlcr->profiles[i].profilesMng.allocated) ++ { ++ profilesFound++; ++ profilesIds[k] = i; ++ k++; ++ if (profilesFound == numOfProfiles) ++ break; ++ } ++ ++ if (profilesFound != numOfProfiles) ++ { ++ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE,NO_MSG); ++ } ++ ++ for (i = 0;ip_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated = TRUE; ++ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.ownerId = 0; ++ } ++ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ return E_OK; ++} ++ ++static void FreeSharedProfiles(t_FmPcd *p_FmPcd, uint16_t numOfProfiles, uint16_t *profilesIds) ++{ ++ uint16_t i; ++ ++ SANITY_CHECK_RETURN(p_FmPcd, E_INVALID_HANDLE); ++ ++ ASSERT_COND(numOfProfiles); ++ ++ for (i=0; i < numOfProfiles; i++) ++ { ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated); ++ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated = FALSE; ++ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.ownerId = p_FmPcd->guestId; ++ } ++} ++ ++/*********************************************/ ++/*............Policer Exception..............*/ ++/*********************************************/ ++static void EventsCB(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint32_t event, mask, force; ++ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ event = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_evr); ++ mask = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier); ++ ++ event &= mask; ++ ++ /* clear the forced events */ ++ force = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr); ++ if (force & event) ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, force & ~event); ++ ++ ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_evr, event); ++ ++ if (event & FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE) ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE); ++ if (event & FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE) ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE); ++} ++ ++/* ..... */ ++ ++static void ErrorExceptionsCB(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint32_t event, force, captureReg, mask; ++ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ event = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eevr); ++ mask = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier); ++ ++ event &= mask; ++ ++ /* clear the forced events */ ++ force = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr); ++ if (force & event) ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, force & ~event); ++ ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eevr, event); ++ ++ if (event & FM_PCD_PLCR_DOUBLE_ECC) ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC); ++ if (event & FM_PCD_PLCR_INIT_ENTRY_ERROR) ++ { ++ captureReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_upcr); ++ /*ASSERT_COND(captureReg & PLCR_ERR_UNINIT_CAP); ++ p_UnInitCapt->profileNum = (uint8_t)(captureReg & PLCR_ERR_UNINIT_NUM_MASK); ++ p_UnInitCapt->portId = (uint8_t)((captureReg & PLCR_ERR_UNINIT_PID_MASK) >>PLCR_ERR_UNINIT_PID_SHIFT) ; ++ p_UnInitCapt->absolute = (bool)(captureReg & PLCR_ERR_UNINIT_ABSOLUTE_MASK);*/ ++ p_FmPcd->f_FmPcdIndexedException(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR,(uint16_t)(captureReg & PLCR_ERR_UNINIT_NUM_MASK)); ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_upcr, PLCR_ERR_UNINIT_CAP); ++ } ++} ++ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++t_Handle PlcrConfig(t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams) ++{ ++ t_FmPcdPlcr *p_FmPcdPlcr; ++ uint16_t i=0; ++ ++ UNUSED(p_FmPcd); ++ UNUSED(p_FmPcdParams); ++ ++ p_FmPcdPlcr = (t_FmPcdPlcr *) XX_Malloc(sizeof(t_FmPcdPlcr)); ++ if (!p_FmPcdPlcr) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer structure allocation FAILED")); ++ return NULL; ++ } ++ memset(p_FmPcdPlcr, 0, sizeof(t_FmPcdPlcr)); ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ { ++ p_FmPcdPlcr->p_FmPcdPlcrRegs = (t_FmPcdPlcrRegs *)UINT_TO_PTR(FmGetPcdPlcrBaseAddr(p_FmPcdParams->h_Fm)); ++ p_FmPcd->p_FmPcdDriverParam->plcrAutoRefresh = DEFAULT_plcrAutoRefresh; ++ p_FmPcd->exceptions |= (DEFAULT_fmPcdPlcrExceptions | DEFAULT_fmPcdPlcrErrorExceptions); ++ } ++ ++ p_FmPcdPlcr->numOfSharedProfiles = DEFAULT_numOfSharedPlcrProfiles; ++ ++ p_FmPcdPlcr->partPlcrProfilesBase = p_FmPcdParams->partPlcrProfilesBase; ++ p_FmPcdPlcr->partNumOfPlcrProfiles = p_FmPcdParams->partNumOfPlcrProfiles; ++ /* for backward compatabilty. if no policer profile, will set automatically to the max */ ++ if ((p_FmPcd->guestId == NCSW_MASTER_ID) && ++ (p_FmPcdPlcr->partNumOfPlcrProfiles == 0)) ++ p_FmPcdPlcr->partNumOfPlcrProfiles = FM_PCD_PLCR_NUM_ENTRIES; ++ ++ for (i=0; iprofiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE; ++ ++ return p_FmPcdPlcr; ++} ++ ++t_Error PlcrInit(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdDriverParam *p_Param = p_FmPcd->p_FmPcdDriverParam; ++ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr; ++ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ t_Error err = E_OK; ++ uint32_t tmpReg32 = 0; ++ uint16_t base; ++ ++ if ((p_FmPcdPlcr->partPlcrProfilesBase + p_FmPcdPlcr->partNumOfPlcrProfiles) > FM_PCD_PLCR_NUM_ENTRIES) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partPlcrProfilesBase+partNumOfPlcrProfiles out of range!!!")); ++ ++ p_FmPcdPlcr->h_HwSpinlock = XX_InitSpinlock(); ++ if (!p_FmPcdPlcr->h_HwSpinlock) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer HW spinlock")); ++ ++ p_FmPcdPlcr->h_SwSpinlock = XX_InitSpinlock(); ++ if (!p_FmPcdPlcr->h_SwSpinlock) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer SW spinlock")); ++ ++ base = PlcrAllocProfilesForPartition(p_FmPcd, ++ p_FmPcdPlcr->partPlcrProfilesBase, ++ p_FmPcdPlcr->partNumOfPlcrProfiles, ++ p_FmPcd->guestId); ++ if (base == (uint16_t)ILLEGAL_BASE) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ ++ if (p_FmPcdPlcr->numOfSharedProfiles) ++ { ++ err = AllocSharedProfiles(p_FmPcd, ++ p_FmPcdPlcr->numOfSharedProfiles, ++ p_FmPcdPlcr->sharedProfilesIds); ++ if (err) ++ RETURN_ERROR(MAJOR, err,NO_MSG); ++ } ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ return E_OK; ++ ++ /**********************FMPL_GCR******************/ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_PLCR_GCR_STEN; ++ if (p_Param->plcrAutoRefresh) ++ tmpReg32 |= FM_PCD_PLCR_GCR_DAR; ++ tmpReg32 |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd); ++ ++ WRITE_UINT32(p_Regs->fmpl_gcr, tmpReg32); ++ /**********************FMPL_GCR******************/ ++ ++ /**********************FMPL_EEVR******************/ ++ WRITE_UINT32(p_Regs->fmpl_eevr, (FM_PCD_PLCR_DOUBLE_ECC | FM_PCD_PLCR_INIT_ENTRY_ERROR)); ++ /**********************FMPL_EEVR******************/ ++ /**********************FMPL_EIER******************/ ++ tmpReg32 = 0; ++ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_DOUBLE_ECC) ++ { ++ FmEnableRamsEcc(p_FmPcd->h_Fm); ++ tmpReg32 |= FM_PCD_PLCR_DOUBLE_ECC; ++ } ++ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_INIT_ENTRY_ERROR) ++ tmpReg32 |= FM_PCD_PLCR_INIT_ENTRY_ERROR; ++ WRITE_UINT32(p_Regs->fmpl_eier, tmpReg32); ++ /**********************FMPL_EIER******************/ ++ ++ /**********************FMPL_EVR******************/ ++ WRITE_UINT32(p_Regs->fmpl_evr, (FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE | FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE)); ++ /**********************FMPL_EVR******************/ ++ /**********************FMPL_IER******************/ ++ tmpReg32 = 0; ++ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE) ++ tmpReg32 |= FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE; ++ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE) ++ tmpReg32 |= FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE; ++ WRITE_UINT32(p_Regs->fmpl_ier, tmpReg32); ++ /**********************FMPL_IER******************/ ++ ++ /* register even if no interrupts enabled, to allow future enablement */ ++ FmRegisterIntr(p_FmPcd->h_Fm, ++ e_FM_MOD_PLCR, ++ 0, ++ e_FM_INTR_TYPE_ERR, ++ ErrorExceptionsCB, ++ p_FmPcd); ++ FmRegisterIntr(p_FmPcd->h_Fm, ++ e_FM_MOD_PLCR, ++ 0, ++ e_FM_INTR_TYPE_NORMAL, ++ EventsCB, ++ p_FmPcd); ++ ++ /* driver initializes one DFLT profile at the last entry*/ ++ /**********************FMPL_DPMR******************/ ++ tmpReg32 = 0; ++ WRITE_UINT32(p_Regs->fmpl_dpmr, tmpReg32); ++ p_FmPcd->p_FmPcdPlcr->profiles[0].profilesMng.allocated = TRUE; ++ ++ return E_OK; ++} ++ ++t_Error PlcrFree(t_FmPcd *p_FmPcd) ++{ ++ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PLCR, 0, e_FM_INTR_TYPE_ERR); ++ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PLCR, 0, e_FM_INTR_TYPE_NORMAL); ++ ++ if (p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles) ++ FreeSharedProfiles(p_FmPcd, ++ p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles, ++ p_FmPcd->p_FmPcdPlcr->sharedProfilesIds); ++ ++ if (p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles) ++ PlcrFreeProfilesForPartition(p_FmPcd, ++ p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase, ++ p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles, ++ p_FmPcd->guestId); ++ ++ if (p_FmPcd->p_FmPcdPlcr->h_SwSpinlock) ++ XX_FreeSpinlock(p_FmPcd->p_FmPcdPlcr->h_SwSpinlock); ++ ++ if (p_FmPcd->p_FmPcdPlcr->h_HwSpinlock) ++ XX_FreeSpinlock(p_FmPcd->p_FmPcdPlcr->h_HwSpinlock); ++ ++ return E_OK; ++} ++ ++void PlcrEnable(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ ++ WRITE_UINT32(p_Regs->fmpl_gcr, GET_UINT32(p_Regs->fmpl_gcr) | FM_PCD_PLCR_GCR_EN); ++} ++ ++void PlcrDisable(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ ++ WRITE_UINT32(p_Regs->fmpl_gcr, GET_UINT32(p_Regs->fmpl_gcr) & ~FM_PCD_PLCR_GCR_EN); ++} ++ ++uint16_t PlcrAllocProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId) ++{ ++ uint32_t intFlags; ++ uint16_t profilesFound = 0; ++ int i = 0; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr); ++ ++ if (!numOfProfiles) ++ return 0; ++ ++ if ((numOfProfiles > FM_PCD_PLCR_NUM_ENTRIES) || ++ (base + numOfProfiles > FM_PCD_PLCR_NUM_ENTRIES)) ++ return (uint16_t)ILLEGAL_BASE; ++ ++ if (p_FmPcd->h_IpcSession) ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ t_FmPcdIpcMsg msg; ++ t_FmPcdIpcReply reply; ++ t_Error err; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ++ ipcAllocParams.guestId = p_FmPcd->guestId; ++ ipcAllocParams.num = p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles; ++ ipcAllocParams.base = p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase; ++ msg.msgId = FM_PCD_ALLOC_PROFILES; ++ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); ++ replyLength = sizeof(uint32_t) + sizeof(uint16_t); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if ((err != E_OK) || ++ (replyLength != (sizeof(uint32_t) + sizeof(uint16_t)))) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return (uint16_t)ILLEGAL_BASE; ++ } ++ else ++ memcpy((uint8_t*)&p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase, reply.replyBody, sizeof(uint16_t)); ++ if (p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase == (uint16_t)ILLEGAL_BASE) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return (uint16_t)ILLEGAL_BASE; ++ } ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ { ++ DBG(WARNING, ("FM Guest mode, without IPC - can't validate Policer-profiles range!")); ++ return (uint16_t)ILLEGAL_BASE; ++ } ++ ++ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock); ++ for (i=base; i<(base+numOfProfiles); i++) ++ if (p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == (uint8_t)ILLEGAL_BASE) ++ profilesFound++; ++ else ++ break; ++ ++ if (profilesFound == numOfProfiles) ++ for (i=base; i<(base+numOfProfiles); i++) ++ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = guestId; ++ else ++ { ++ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags); ++ return (uint16_t)ILLEGAL_BASE; ++ } ++ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags); ++ ++ return base; ++} ++ ++void PlcrFreeProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId) ++{ ++ int i = 0; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr); ++ ++ if (p_FmPcd->h_IpcSession) ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ t_FmPcdIpcMsg msg; ++ t_Error err; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ++ ipcAllocParams.guestId = p_FmPcd->guestId; ++ ipcAllocParams.num = p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles; ++ ipcAllocParams.base = p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase; ++ msg.msgId = FM_PCD_FREE_PROFILES; ++ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return; ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ { ++ DBG(WARNING, ("FM Guest mode, without IPC - can't validate Policer-profiles range!")); ++ return; ++ } ++ ++ for (i=base; i<(base+numOfProfiles); i++) ++ { ++ if (p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == guestId) ++ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE; ++ else ++ DBG(WARNING, ("Request for freeing storage profile window which wasn't allocated to this partition")); ++ } ++} ++ ++t_Error PlcrSetPortProfiles(t_FmPcd *p_FmPcd, ++ uint8_t hardwarePortId, ++ uint16_t numOfProfiles, ++ uint16_t base) ++{ ++ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ uint32_t log2Num, tmpReg32; ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ !p_Regs && ++ p_FmPcd->h_IpcSession) ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ t_FmPcdIpcMsg msg; ++ t_Error err; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ++ ipcAllocParams.guestId = hardwarePortId; ++ ipcAllocParams.num = numOfProfiles; ++ ipcAllocParams.base = base; ++ msg.msgId = FM_PCD_SET_PORT_PROFILES; ++ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ return E_OK; ++ } ++ else if (!p_Regs) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ if (GET_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1]) & FM_PCD_PLCR_PMR_V) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("The requesting port has already an allocated profiles window.")); ++ ++ /**********************FMPL_PMRx******************/ ++ LOG2((uint64_t)numOfProfiles, log2Num); ++ tmpReg32 = base; ++ tmpReg32 |= log2Num << 16; ++ tmpReg32 |= FM_PCD_PLCR_PMR_V; ++ WRITE_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1], tmpReg32); ++ ++ return E_OK; ++} ++ ++t_Error PlcrClearPortProfiles(t_FmPcd *p_FmPcd, uint8_t hardwarePortId) ++{ ++ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ !p_Regs && ++ p_FmPcd->h_IpcSession) ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ t_FmPcdIpcMsg msg; ++ t_Error err; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ++ ipcAllocParams.guestId = hardwarePortId; ++ msg.msgId = FM_PCD_CLEAR_PORT_PROFILES; ++ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ return E_OK; ++ } ++ else if (!p_Regs) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ WRITE_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1], 0); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdPlcrAllocProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId, uint16_t numOfProfiles) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ uint32_t profilesFound; ++ uint32_t intFlags; ++ uint16_t i, first, swPortIndex = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ if (!numOfProfiles) ++ return E_OK; ++ ++ ASSERT_COND(hardwarePortId); ++ ++ if (numOfProfiles>FM_PCD_PLCR_NUM_ENTRIES) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles is too big.")); ++ ++ if (!POWER_OF_2(numOfProfiles)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numProfiles must be a power of 2.")); ++ ++ first = 0; ++ profilesFound = 0; ++ intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr); ++ ++ for (i=0; ip_FmPcdPlcr->profiles[i].profilesMng.allocated) ++ { ++ profilesFound++; ++ i++; ++ if (profilesFound == numOfProfiles) ++ break; ++ } ++ else ++ { ++ profilesFound = 0; ++ /* advance i to the next aligned address */ ++ i = first = (uint16_t)(first + numOfProfiles); ++ } ++ } ++ ++ if (profilesFound == numOfProfiles) ++ { ++ for (i=first; ip_FmPcdPlcr->profiles[i].profilesMng.allocated = TRUE; ++ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = hardwarePortId; ++ } ++ } ++ else ++ { ++ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ RETURN_ERROR(MINOR, E_FULL, ("No profiles.")); ++ } ++ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ err = PlcrSetPortProfiles(p_FmPcd, hardwarePortId, numOfProfiles, first); ++ if (err) ++ { ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles = numOfProfiles; ++ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase = first; ++ ++ return E_OK; ++} ++ ++t_Error FmPcdPlcrFreeProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ uint32_t intFlags; ++ uint16_t i, swPortIndex = 0; ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); ++ ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ err = PlcrClearPortProfiles(p_FmPcd, hardwarePortId); ++ if (err) ++ RETURN_ERROR(MAJOR, err,NO_MSG); ++ ++ intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr); ++ for (i=p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase; ++ i<(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase + ++ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles); ++ i++) ++ { ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == hardwarePortId); ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated); ++ ++ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated = FALSE; ++ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = p_FmPcd->guestId; ++ } ++ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles = 0; ++ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase = 0; ++ ++ return E_OK; ++} ++ ++t_Error FmPcdPlcrCcGetSetParams(t_Handle h_FmPcd, uint16_t profileIndx ,uint32_t requiredAction) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr; ++ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs = p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ uint32_t tmpReg32, intFlags; ++ t_Error err; ++ ++ /* Calling function locked all PCD modules, so no need to lock here */ ++ ++ if (profileIndx >= FM_PCD_PLCR_NUM_ENTRIES) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Policer profile out of range")); ++ ++ if (!FmPcdPlcrIsProfileValid(p_FmPcd, profileIndx)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Policer profile is not valid")); ++ ++ /*intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx]);*/ ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdPlcrCcGetSetParams(p_FmPcd->h_Hc, profileIndx, requiredAction); ++ ++ FmPcdPlcrUpatePointedOwner(p_FmPcd, profileIndx, TRUE); ++ FmPcdPlcrUpdateRequiredAction(p_FmPcd, profileIndx, requiredAction); ++ ++ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ ++ return err; ++ } ++ ++ /* lock the HW because once we read the registers we don't want them to be changed ++ * by another access. (We can copy to a tmp location and release the lock!) */ ++ ++ intFlags = PlcrHwLock(p_FmPcdPlcr); ++ WritePar(p_FmPcd, FmPcdPlcrBuildReadPlcrActionReg(profileIndx)); ++ ++ if (!p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].pointedOwners || ++ !(p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].requiredAction & requiredAction)) ++ { ++ if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) ++ { ++ if ((p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnGreen!= e_FM_PCD_DONE) || ++ (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnYellow!= e_FM_PCD_DONE) || ++ (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnRed!= e_FM_PCD_DONE)) ++ { ++ PlcrHwUnlock(p_FmPcdPlcr, intFlags); ++ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ ++ RETURN_ERROR (MAJOR, E_OK, ("In this case the next engine can be e_FM_PCD_DONE")); ++ } ++ ++ if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnGreen.action == e_FM_PCD_ENQ_FRAME) ++ { ++ tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia); ++ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) ++ { ++ PlcrHwUnlock(p_FmPcdPlcr, intFlags); ++ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); ++ } ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia, tmpReg32); ++ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx); ++ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEGNIA; ++ WritePar(p_FmPcd, tmpReg32); ++ } ++ ++ if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnYellow.action == e_FM_PCD_ENQ_FRAME) ++ { ++ tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia); ++ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) ++ { ++ PlcrHwUnlock(p_FmPcdPlcr, intFlags); ++ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); ++ } ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia, tmpReg32); ++ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx); ++ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEYNIA; ++ WritePar(p_FmPcd, tmpReg32); ++ PlcrHwUnlock(p_FmPcdPlcr, intFlags); ++ } ++ ++ if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnRed.action == e_FM_PCD_ENQ_FRAME) ++ { ++ tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia); ++ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) ++ { ++ PlcrHwUnlock(p_FmPcdPlcr, intFlags); ++ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); ++ } ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia, tmpReg32); ++ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx); ++ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PERNIA; ++ WritePar(p_FmPcd, tmpReg32); ++ ++ } ++ } ++ } ++ PlcrHwUnlock(p_FmPcdPlcr, intFlags); ++ ++ FmPcdPlcrUpatePointedOwner(p_FmPcd, profileIndx, TRUE); ++ FmPcdPlcrUpdateRequiredAction(p_FmPcd, profileIndx, requiredAction); ++ ++ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ ++ ++ return E_OK; ++} ++ ++void FmPcdPlcrUpatePointedOwner(t_Handle h_FmPcd, uint16_t absoluteProfileId, bool add) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ /* this routine is protected by calling routine */ ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); ++ ++ if (add) ++ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].pointedOwners++; ++ else ++ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].pointedOwners--; ++} ++ ++uint32_t FmPcdPlcrGetPointedOwners(t_Handle h_FmPcd, uint16_t absoluteProfileId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); ++ ++ return p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].pointedOwners; ++} ++ ++uint32_t FmPcdPlcrGetRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); ++ ++ return p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction; ++} ++ ++bool FmPcdPlcrIsProfileValid(t_Handle h_FmPcd, uint16_t absoluteProfileId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr; ++ ++ ASSERT_COND(absoluteProfileId < FM_PCD_PLCR_NUM_ENTRIES); ++ ++ return p_FmPcdPlcr->profiles[absoluteProfileId].valid; ++} ++ ++void FmPcdPlcrValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t intFlags; ++ ++ ASSERT_COND(!p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); ++ ++ intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]); ++ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid = TRUE; ++ PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId], intFlags); ++} ++ ++void FmPcdPlcrInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); ++ ++ intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]); ++ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid = FALSE; ++ PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId], intFlags); ++} ++ ++uint16_t FmPcdPlcrProfileGetAbsoluteId(t_Handle h_Profile) ++{ ++ return ((t_FmPcdPlcrProfile*)h_Profile)->absoluteProfileId; ++} ++ ++t_Error FmPcdPlcrGetAbsoluteIdByProfileParams(t_Handle h_FmPcd, ++ e_FmPcdProfileTypeSelection profileType, ++ t_Handle h_FmPort, ++ uint16_t relativeProfile, ++ uint16_t *p_AbsoluteId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr; ++ uint8_t i; ++ ++ switch (profileType) ++ { ++ case e_FM_PCD_PLCR_PORT_PRIVATE: ++ /* get port PCD id from port handle */ ++ for (i=0;ip_FmPcdPlcr->portsMapping[i].h_FmPort == h_FmPort) ++ break; ++ if (i == FM_MAX_NUM_OF_PORTS) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE , ("Invalid port handle.")); ++ ++ if (!p_FmPcd->p_FmPcdPlcr->portsMapping[i].numOfProfiles) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Port has no allocated profiles")); ++ if (relativeProfile >= p_FmPcd->p_FmPcdPlcr->portsMapping[i].numOfProfiles) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Profile id is out of range")); ++ *p_AbsoluteId = (uint16_t)(p_FmPcd->p_FmPcdPlcr->portsMapping[i].profilesBase + relativeProfile); ++ break; ++ case e_FM_PCD_PLCR_SHARED: ++ if (relativeProfile >= p_FmPcdPlcr->numOfSharedProfiles) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Profile id is out of range")); ++ *p_AbsoluteId = (uint16_t)(p_FmPcdPlcr->sharedProfilesIds[relativeProfile]); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Invalid policer profile type")); ++ } ++ ++ return E_OK; ++} ++ ++uint16_t FmPcdPlcrGetPortProfilesBase(t_Handle h_FmPcd, uint8_t hardwarePortId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint16_t swPortIndex = 0; ++ ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ return p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase; ++} ++ ++uint16_t FmPcdPlcrGetPortNumOfProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint16_t swPortIndex = 0; ++ ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ return p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles; ++ ++} ++uint32_t FmPcdPlcrBuildWritePlcrActionReg(uint16_t absoluteProfileId) ++{ ++ return (uint32_t)(FM_PCD_PLCR_PAR_GO | ++ ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT)); ++} ++ ++uint32_t FmPcdPlcrBuildWritePlcrActionRegs(uint16_t absoluteProfileId) ++{ ++ return (uint32_t)(FM_PCD_PLCR_PAR_GO | ++ ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT) | ++ FM_PCD_PLCR_PAR_PWSEL_MASK); ++} ++ ++bool FmPcdPlcrHwProfileIsValid(uint32_t profileModeReg) ++{ ++ ++ if (profileModeReg & FM_PCD_PLCR_PEMODE_PI) ++ return TRUE; ++ else ++ return FALSE; ++} ++ ++uint32_t FmPcdPlcrBuildReadPlcrActionReg(uint16_t absoluteProfileId) ++{ ++ return (uint32_t)(FM_PCD_PLCR_PAR_GO | ++ FM_PCD_PLCR_PAR_R | ++ ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT) | ++ FM_PCD_PLCR_PAR_PWSEL_MASK); ++} ++ ++uint32_t FmPcdPlcrBuildCounterProfileReg(e_FmPcdPlcrProfileCounters counter) ++{ ++ switch (counter) ++ { ++ case (e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER): ++ return FM_PCD_PLCR_PAR_PWSEL_PEGPC; ++ case (e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER): ++ return FM_PCD_PLCR_PAR_PWSEL_PEYPC; ++ case (e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER) : ++ return FM_PCD_PLCR_PAR_PWSEL_PERPC; ++ case (e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER) : ++ return FM_PCD_PLCR_PAR_PWSEL_PERYPC; ++ case (e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER) : ++ return FM_PCD_PLCR_PAR_PWSEL_PERRPC; ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ return 0; ++ } ++} ++ ++uint32_t FmPcdPlcrBuildNiaProfileReg(bool green, bool yellow, bool red) ++{ ++ ++ uint32_t tmpReg32 = 0; ++ ++ if (green) ++ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEGNIA; ++ if (yellow) ++ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEYNIA; ++ if (red) ++ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PERNIA; ++ ++ return tmpReg32; ++} ++ ++void FmPcdPlcrUpdateRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId, uint32_t requiredAction) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ /* this routine is protected by calling routine */ ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); ++ ++ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction |= requiredAction; ++} ++/*********************** End of inter-module routines ************************/ ++ ++ ++/**************************************************/ ++/*............Policer API.........................*/ ++/**************************************************/ ++ ++t_Error FM_PCD_ConfigPlcrAutoRefreshMode(t_Handle h_FmPcd, bool enable) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE); ++ ++ if (!FmIsMaster(p_FmPcd->h_Fm)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigPlcrAutoRefreshMode - guest mode!")); ++ ++ p_FmPcd->p_FmPcdDriverParam->plcrAutoRefresh = enable; ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ConfigPlcrNumOfSharedProfiles(t_Handle h_FmPcd, uint16_t numOfSharedPlcrProfiles) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE); ++ ++ p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles = numOfSharedPlcrProfiles; ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_SetPlcrStatistics(t_Handle h_FmPcd, bool enable) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t tmpReg32; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE); ++ ++ if (!FmIsMaster(p_FmPcd->h_Fm)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetPlcrStatistics - guest mode!")); ++ ++ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr); ++ if (enable) ++ tmpReg32 |= FM_PCD_PLCR_GCR_STEN; ++ else ++ tmpReg32 &= ~FM_PCD_PLCR_GCR_STEN; ++ ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr, tmpReg32); ++ return E_OK; ++} ++ ++/* ... */ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++t_Error FM_PCD_PlcrDumpRegs(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ int i = 0; ++ ++ DECLARE_DUMP; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(((p_FmPcd->guestId == NCSW_MASTER_ID) || ++ p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs), E_INVALID_OPERATION); ++ ++ DUMP_SUBTITLE(("\n")); ++ DUMP_TITLE(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, ("FM-PCD policer regs")); ++ ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_gcr); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_gsr); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_evr); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_ier); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_ifr); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_eevr); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_eier); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_eifr); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_rpcnt); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_ypcnt); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_rrpcnt); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_rypcnt); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_tpcnt); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_flmcnt); ++ ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_serc); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_upcr); ++ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_dpmr); ++ ++ DUMP_TITLE(&p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_pmr, ("fmpl_pmr")); ++ DUMP_SUBSTRUCT_ARRAY(i, 63) ++ { ++ DUMP_MEMORY(&p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_pmr[i], sizeof(uint32_t)); ++ } ++ ++ return E_OK; ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++t_Handle FM_PCD_PlcrProfileSet(t_Handle h_FmPcd, ++ t_FmPcdPlcrProfileParams *p_ProfileParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs; ++ t_FmPcdPlcrProfileRegs plcrProfileReg; ++ uint32_t intFlags; ++ uint16_t absoluteProfileId; ++ t_Error err = E_OK; ++ uint32_t tmpReg32; ++ t_FmPcdPlcrProfile *p_Profile; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); ++ ++ if (p_ProfileParams->modify) ++ { ++ p_Profile = (t_FmPcdPlcrProfile *)p_ProfileParams->id.h_Profile; ++ p_FmPcd = p_Profile->h_FmPcd; ++ absoluteProfileId = p_Profile->absoluteProfileId; ++ if (absoluteProfileId >= FM_PCD_PLCR_NUM_ENTRIES) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big ")); ++ return NULL; ++ } ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE, NULL); ++ ++ /* Try lock profile using flag */ ++ if (!PlcrProfileFlagTryLock(p_Profile)) ++ { ++ DBG(TRACE, ("Profile Try Lock - BUSY")); ++ /* Signal to caller BUSY condition */ ++ p_ProfileParams->id.h_Profile = NULL; ++ return NULL; ++ } ++ } ++ else ++ { ++ p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE, NULL); ++ ++ /* SMP: needs to be protected only if another core now changes the windows */ ++ err = FmPcdPlcrGetAbsoluteIdByProfileParams(h_FmPcd, ++ p_ProfileParams->id.newParams.profileType, ++ p_ProfileParams->id.newParams.h_FmPort, ++ p_ProfileParams->id.newParams.relativeProfileId, ++ &absoluteProfileId); ++ ++ if (absoluteProfileId >= FM_PCD_PLCR_NUM_ENTRIES) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big ")); ++ return NULL; ++ } ++ ++ if (FmPcdPlcrIsProfileValid(p_FmPcd, absoluteProfileId)) ++ { ++ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Policer Profile is already used")); ++ return NULL; ++ } ++ ++ /* initialize profile struct */ ++ p_Profile = &p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]; ++ p_Profile->h_FmPcd = p_FmPcd; ++ p_Profile->absoluteProfileId = absoluteProfileId; ++ ++ p_Profile->p_Lock = FmPcdAcquireLock(p_FmPcd); ++ if (!p_Profile->p_Lock) ++ REPORT_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM Policer Profile lock obj!")); ++ } ++ ++ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, NULL); ++ ++ p_Profile->nextEngineOnGreen = p_ProfileParams->nextEngineOnGreen; ++ memcpy(&p_Profile->paramsOnGreen, &(p_ProfileParams->paramsOnGreen), sizeof(u_FmPcdPlcrNextEngineParams)); ++ ++ p_Profile->nextEngineOnYellow = p_ProfileParams->nextEngineOnYellow; ++ memcpy(&p_Profile->paramsOnYellow, &(p_ProfileParams->paramsOnYellow), sizeof(u_FmPcdPlcrNextEngineParams)); ++ ++ p_Profile->nextEngineOnRed = p_ProfileParams->nextEngineOnRed; ++ memcpy(&p_Profile->paramsOnRed, &(p_ProfileParams->paramsOnRed), sizeof(u_FmPcdPlcrNextEngineParams)); ++ ++ memset(&plcrProfileReg, 0, sizeof(t_FmPcdPlcrProfileRegs)); ++ ++ /* build the policer profile registers */ ++ err = BuildProfileRegs(h_FmPcd, p_ProfileParams, &plcrProfileReg); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ if (p_ProfileParams->modify) ++ /* unlock */ ++ PlcrProfileFlagUnlock(p_Profile); ++ if (!p_ProfileParams->modify && ++ p_Profile->p_Lock) ++ /* release allocated Profile lock */ ++ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock); ++ return NULL; ++ } ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdPlcrSetProfile(p_FmPcd->h_Hc, (t_Handle)p_Profile, &plcrProfileReg); ++ if (p_ProfileParams->modify) ++ PlcrProfileFlagUnlock(p_Profile); ++ if (err) ++ { ++ /* release the allocated scheme lock */ ++ if (!p_ProfileParams->modify && ++ p_Profile->p_Lock) ++ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock); ++ ++ return NULL; ++ } ++ if (!p_ProfileParams->modify) ++ FmPcdPlcrValidateProfileSw(p_FmPcd,absoluteProfileId); ++ return (t_Handle)p_Profile; ++ } ++ ++ p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ SANITY_CHECK_RETURN_VALUE(p_FmPcdPlcrRegs, E_INVALID_HANDLE, NULL); ++ ++ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pemode , plcrProfileReg.fmpl_pemode); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia , plcrProfileReg.fmpl_pegnia); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia , plcrProfileReg.fmpl_peynia); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia , plcrProfileReg.fmpl_pernia); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pecir , plcrProfileReg.fmpl_pecir); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pecbs , plcrProfileReg.fmpl_pecbs); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepepir_eir,plcrProfileReg.fmpl_pepepir_eir); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepbs_ebs,plcrProfileReg.fmpl_pepbs_ebs); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pelts , plcrProfileReg.fmpl_pelts); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pects , plcrProfileReg.fmpl_pects); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepts_ets,plcrProfileReg.fmpl_pepts_ets); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc , plcrProfileReg.fmpl_pegpc); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc , plcrProfileReg.fmpl_peypc); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc , plcrProfileReg.fmpl_perpc); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc , plcrProfileReg.fmpl_perypc); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc , plcrProfileReg.fmpl_perrpc); ++ ++ tmpReg32 = FmPcdPlcrBuildWritePlcrActionRegs(absoluteProfileId); ++ WritePar(p_FmPcd, tmpReg32); ++ ++ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ if (!p_ProfileParams->modify) ++ FmPcdPlcrValidateProfileSw(p_FmPcd,absoluteProfileId); ++ else ++ PlcrProfileFlagUnlock(p_Profile); ++ ++ return (t_Handle)p_Profile; ++} ++ ++t_Error FM_PCD_PlcrProfileDelete(t_Handle h_Profile) ++{ ++ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile; ++ t_FmPcd *p_FmPcd; ++ uint16_t profileIndx; ++ uint32_t tmpReg32, intFlags; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE); ++ p_FmPcd = p_Profile->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ profileIndx = p_Profile->absoluteProfileId; ++ ++ FmPcdPlcrInvalidateProfileSw(p_FmPcd,profileIndx); ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdPlcrDeleteProfile(p_FmPcd->h_Hc, h_Profile); ++ if (p_Profile->p_Lock) ++ /* release allocated Profile lock */ ++ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock); ++ ++ return err; ++ } ++ ++ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->profileRegs.fmpl_pemode, ~FM_PCD_PLCR_PEMODE_PI); ++ ++ tmpReg32 = FmPcdPlcrBuildWritePlcrActionRegs(profileIndx); ++ WritePar(p_FmPcd, tmpReg32); ++ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ if (p_Profile->p_Lock) ++ /* release allocated Profile lock */ ++ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock); ++ ++ return E_OK; ++} ++ ++/***************************************************/ ++/*............Policer Profile Counter..............*/ ++/***************************************************/ ++uint32_t FM_PCD_PlcrProfileGetCounter(t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter) ++{ ++ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile; ++ t_FmPcd *p_FmPcd; ++ uint16_t profileIndx; ++ uint32_t intFlags, counterVal = 0; ++ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE); ++ p_FmPcd = p_Profile->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ if (p_FmPcd->h_Hc) ++ return FmHcPcdPlcrGetProfileCounter(p_FmPcd->h_Hc, h_Profile, counter); ++ ++ p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ SANITY_CHECK_RETURN_VALUE(p_FmPcdPlcrRegs, E_INVALID_HANDLE, 0); ++ ++ profileIndx = p_Profile->absoluteProfileId; ++ ++ if (profileIndx >= FM_PCD_PLCR_NUM_ENTRIES) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big ")); ++ return 0; ++ } ++ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); ++ WritePar(p_FmPcd, FmPcdPlcrBuildReadPlcrActionReg(profileIndx)); ++ ++ switch (counter) ++ { ++ case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER: ++ counterVal = (GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc)); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER: ++ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER: ++ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER: ++ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER: ++ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc); ++ break; ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ break; ++ } ++ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ return counterVal; ++} ++ ++t_Error FM_PCD_PlcrProfileSetCounter(t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value) ++{ ++ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile; ++ t_FmPcd *p_FmPcd; ++ uint16_t profileIndx; ++ uint32_t tmpReg32, intFlags; ++ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE); ++ ++ p_FmPcd = p_Profile->h_FmPcd; ++ profileIndx = p_Profile->absoluteProfileId; ++ ++ if (p_FmPcd->h_Hc) ++ return FmHcPcdPlcrSetProfileCounter(p_FmPcd->h_Hc, h_Profile, counter, value); ++ ++ p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdPlcrRegs, E_INVALID_HANDLE); ++ ++ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); ++ switch (counter) ++ { ++ case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER: ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc, value); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER: ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc, value); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER: ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc, value); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER: ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc ,value); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER: ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc ,value); ++ break; ++ default: ++ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ /* Activate the atomic write action by writing FMPL_PAR with: GO=1, RW=1, PSI=0, PNUM = ++ * Profile Number, PWSEL=0xFFFF (select all words). ++ */ ++ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx); ++ tmpReg32 |= FmPcdPlcrBuildCounterProfileReg(counter); ++ WritePar(p_FmPcd, tmpReg32); ++ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ return E_OK; ++} ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++t_Error FM_PCD_PlcrProfileDumpRegs(t_Handle h_Profile) ++{ ++ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile; ++ t_FmPcd *p_FmPcd; ++ t_FmPcdPlcrProfileRegs *p_ProfilesRegs; ++ uint16_t profileIndx; ++ uint32_t tmpReg, intFlags; ++ ++ DECLARE_DUMP; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE); ++ p_FmPcd = p_Profile->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE); ++ ++ profileIndx = p_Profile->absoluteProfileId; ++ ++ DUMP_SUBTITLE(("\n")); ++ DUMP_TITLE(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, ("FM-PCD policer-profile regs")); ++ ++ p_ProfilesRegs = &p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->profileRegs; ++ ++ tmpReg = FmPcdPlcrBuildReadPlcrActionReg((uint16_t)profileIndx); ++ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); ++ WritePar(p_FmPcd, tmpReg); ++ ++ DUMP_TITLE(p_ProfilesRegs, ("Profile %d regs", profileIndx)); ++ ++ DUMP_VAR(p_ProfilesRegs, fmpl_pemode); ++ DUMP_VAR(p_ProfilesRegs, fmpl_pegnia); ++ DUMP_VAR(p_ProfilesRegs, fmpl_peynia); ++ DUMP_VAR(p_ProfilesRegs, fmpl_pernia); ++ DUMP_VAR(p_ProfilesRegs, fmpl_pecir); ++ DUMP_VAR(p_ProfilesRegs, fmpl_pecbs); ++ DUMP_VAR(p_ProfilesRegs, fmpl_pepepir_eir); ++ DUMP_VAR(p_ProfilesRegs, fmpl_pepbs_ebs); ++ DUMP_VAR(p_ProfilesRegs, fmpl_pelts); ++ DUMP_VAR(p_ProfilesRegs, fmpl_pects); ++ DUMP_VAR(p_ProfilesRegs, fmpl_pepts_ets); ++ DUMP_VAR(p_ProfilesRegs, fmpl_pegpc); ++ DUMP_VAR(p_ProfilesRegs, fmpl_peypc); ++ DUMP_VAR(p_ProfilesRegs, fmpl_perpc); ++ DUMP_VAR(p_ProfilesRegs, fmpl_perypc); ++ DUMP_VAR(p_ProfilesRegs, fmpl_perrpc); ++ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ return E_OK; ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_plcr.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_plcr.h +new file mode 100644 +index 0000000..2bb8b96 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_plcr.h +@@ -0,0 +1,165 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_plcr.h ++ ++ @Description FM Policer private header ++*//***************************************************************************/ ++#ifndef __FM_PLCR_H ++#define __FM_PLCR_H ++ ++#include "std_ext.h" ++ ++ ++/***********************************************************************/ ++/* Policer defines */ ++/***********************************************************************/ ++ ++#define FM_PCD_PLCR_PAR_GO 0x80000000 ++#define FM_PCD_PLCR_PAR_PWSEL_MASK 0x0000FFFF ++#define FM_PCD_PLCR_PAR_R 0x40000000 ++ ++/* shifts */ ++#define FM_PCD_PLCR_PAR_PNUM_SHIFT 16 ++ ++/* masks */ ++#define FM_PCD_PLCR_PEMODE_PI 0x80000000 ++#define FM_PCD_PLCR_PEMODE_CBLND 0x40000000 ++#define FM_PCD_PLCR_PEMODE_ALG_MASK 0x30000000 ++#define FM_PCD_PLCR_PEMODE_ALG_RFC2698 0x10000000 ++#define FM_PCD_PLCR_PEMODE_ALG_RFC4115 0x20000000 ++#define FM_PCD_PLCR_PEMODE_DEFC_MASK 0x0C000000 ++#define FM_PCD_PLCR_PEMODE_DEFC_Y 0x04000000 ++#define FM_PCD_PLCR_PEMODE_DEFC_R 0x08000000 ++#define FM_PCD_PLCR_PEMODE_DEFC_OVERRIDE 0x0C000000 ++#define FM_PCD_PLCR_PEMODE_OVCLR_MASK 0x03000000 ++#define FM_PCD_PLCR_PEMODE_OVCLR_Y 0x01000000 ++#define FM_PCD_PLCR_PEMODE_OVCLR_R 0x02000000 ++#define FM_PCD_PLCR_PEMODE_OVCLR_G_NC 0x03000000 ++#define FM_PCD_PLCR_PEMODE_PKT 0x00800000 ++#define FM_PCD_PLCR_PEMODE_FPP_MASK 0x001F0000 ++#define FM_PCD_PLCR_PEMODE_FPP_SHIFT 16 ++#define FM_PCD_PLCR_PEMODE_FLS_MASK 0x0000F000 ++#define FM_PCD_PLCR_PEMODE_FLS_L2 0x00003000 ++#define FM_PCD_PLCR_PEMODE_FLS_L3 0x0000B000 ++#define FM_PCD_PLCR_PEMODE_FLS_L4 0x0000E000 ++#define FM_PCD_PLCR_PEMODE_FLS_FULL 0x0000F000 ++#define FM_PCD_PLCR_PEMODE_RBFLS 0x00000800 ++#define FM_PCD_PLCR_PEMODE_TRA 0x00000004 ++#define FM_PCD_PLCR_PEMODE_TRB 0x00000002 ++#define FM_PCD_PLCR_PEMODE_TRC 0x00000001 ++#define FM_PCD_PLCR_DOUBLE_ECC 0x80000000 ++#define FM_PCD_PLCR_INIT_ENTRY_ERROR 0x40000000 ++#define FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE 0x80000000 ++#define FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE 0x40000000 ++ ++#define FM_PCD_PLCR_NIA_VALID 0x80000000 ++ ++#define FM_PCD_PLCR_GCR_EN 0x80000000 ++#define FM_PCD_PLCR_GCR_STEN 0x40000000 ++#define FM_PCD_PLCR_GCR_DAR 0x20000000 ++#define FM_PCD_PLCR_GCR_DEFNIA 0x00FFFFFF ++#define FM_PCD_PLCR_NIA_ABS 0x00000100 ++ ++#define FM_PCD_PLCR_GSR_BSY 0x80000000 ++#define FM_PCD_PLCR_GSR_DQS 0x60000000 ++#define FM_PCD_PLCR_GSR_RPB 0x20000000 ++#define FM_PCD_PLCR_GSR_FQS 0x0C000000 ++#define FM_PCD_PLCR_GSR_LPALG 0x0000C000 ++#define FM_PCD_PLCR_GSR_LPCA 0x00003000 ++#define FM_PCD_PLCR_GSR_LPNUM 0x000000FF ++ ++#define FM_PCD_PLCR_EVR_PSIC 0x80000000 ++#define FM_PCD_PLCR_EVR_AAC 0x40000000 ++ ++#define FM_PCD_PLCR_PAR_PSI 0x20000000 ++#define FM_PCD_PLCR_PAR_PNUM 0x00FF0000 ++/* PWSEL Selctive select options */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEMODE 0x00008000 /* 0 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEGNIA 0x00004000 /* 1 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEYNIA 0x00002000 /* 2 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PERNIA 0x00001000 /* 3 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PECIR 0x00000800 /* 4 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PECBS 0x00000400 /* 5 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEPIR_EIR 0x00000200 /* 6 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEPBS_EBS 0x00000100 /* 7 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PELTS 0x00000080 /* 8 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PECTS 0x00000040 /* 9 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEPTS_ETS 0x00000020 /* 10 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEGPC 0x00000010 /* 11 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEYPC 0x00000008 /* 12 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PERPC 0x00000004 /* 13 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PERYPC 0x00000002 /* 14 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PERRPC 0x00000001 /* 15 */ ++ ++#define FM_PCD_PLCR_PAR_PMR_BRN_1TO1 0x0000 /* - Full bit replacement. {PBNUM[0:N-1] ++ 1-> 2^N specific locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_2TO2 0x1 /* - {PBNUM[0:N-2],PNUM[N-1]}. ++ 2-> 2^(N-1) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_4TO4 0x2 /* - {PBNUM[0:N-3],PNUM[N-2:N-1]}. ++ 4-> 2^(N-2) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_8TO8 0x3 /* - {PBNUM[0:N-4],PNUM[N-3:N-1]}. ++ 8->2^(N-3) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_16TO16 0x4 /* - {PBNUM[0:N-5],PNUM[N-4:N-1]}. ++ 16-> 2^(N-4) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_32TO32 0x5 /* {PBNUM[0:N-6],PNUM[N-5:N-1]}. ++ 32-> 2^(N-5) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_64TO64 0x6 /* {PBNUM[0:N-7],PNUM[N-6:N-1]}. ++ 64-> 2^(N-6) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_128TO128 0x7 /* {PBNUM[0:N-8],PNUM[N-7:N-1]}. ++ 128-> 2^(N-7) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_256TO256 0x8 /* - No bit replacement for N=8. {PNUM[N-8:N-1]}. ++ When N=8 this option maps all 256 profiles by the DISPATCH bus into one group. */ ++ ++#define FM_PCD_PLCR_PMR_V 0x80000000 ++#define PLCR_ERR_ECC_CAP 0x80000000 ++#define PLCR_ERR_ECC_TYPE_DOUBLE 0x40000000 ++#define PLCR_ERR_ECC_PNUM_MASK 0x00000FF0 ++#define PLCR_ERR_ECC_OFFSET_MASK 0x0000000F ++ ++#define PLCR_ERR_UNINIT_CAP 0x80000000 ++#define PLCR_ERR_UNINIT_NUM_MASK 0x000000FF ++#define PLCR_ERR_UNINIT_PID_MASK 0x003f0000 ++#define PLCR_ERR_UNINIT_ABSOLUTE_MASK 0x00008000 ++ ++/* shifts */ ++#define PLCR_ERR_ECC_PNUM_SHIFT 4 ++#define PLCR_ERR_UNINIT_PID_SHIFT 16 ++ ++#define FM_PCD_PLCR_PMR_BRN_SHIFT 16 ++ ++#define PLCR_PORT_WINDOW_SIZE(hardwarePortId) ++ ++ ++#endif /* __FM_PLCR_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_prs.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_prs.c +new file mode 100644 +index 0000000..e198afd +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_prs.c +@@ -0,0 +1,457 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_pcd.c ++ ++ @Description FM PCD ... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "net_ext.h" ++ ++#include "fm_common.h" ++#include "fm_pcd.h" ++#include "fm_pcd_ipc.h" ++#include "fm_prs.h" ++#include "fsl_fman_prs.h" ++ ++ ++static void PcdPrsErrorException(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint32_t event, ev_mask; ++ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); ++ ev_mask = fman_prs_get_err_ev_mask(PrsRegs); ++ ++ event = fman_prs_get_err_event(PrsRegs, ev_mask); ++ ++ fman_prs_ack_err_event(PrsRegs, event); ++ ++ DBG(TRACE, ("parser error - 0x%08x\n",event)); ++ ++ if(event & FM_PCD_PRS_DOUBLE_ECC) ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC); ++} ++ ++static void PcdPrsException(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint32_t event, ev_mask; ++ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); ++ ev_mask = fman_prs_get_expt_ev_mask(PrsRegs); ++ event = fman_prs_get_expt_event(PrsRegs, ev_mask); ++ ++ ASSERT_COND(event & FM_PCD_PRS_SINGLE_ECC); ++ ++ DBG(TRACE, ("parser event - 0x%08x\n",event)); ++ ++ fman_prs_ack_expt_event(PrsRegs, event); ++ ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC); ++} ++ ++t_Handle PrsConfig(t_FmPcd *p_FmPcd,t_FmPcdParams *p_FmPcdParams) ++{ ++ t_FmPcdPrs *p_FmPcdPrs; ++ uintptr_t baseAddr; ++ ++ UNUSED(p_FmPcd); ++ UNUSED(p_FmPcdParams); ++ ++ p_FmPcdPrs = (t_FmPcdPrs *) XX_Malloc(sizeof(t_FmPcdPrs)); ++ if (!p_FmPcdPrs) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Parser structure allocation FAILED")); ++ return NULL; ++ } ++ memset(p_FmPcdPrs, 0, sizeof(t_FmPcdPrs)); ++ fman_prs_defconfig(&p_FmPcd->p_FmPcdDriverParam->dfltCfg); ++ ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ { ++ baseAddr = FmGetPcdPrsBaseAddr(p_FmPcdParams->h_Fm); ++ p_FmPcdPrs->p_SwPrsCode = (uint32_t *)UINT_TO_PTR(baseAddr); ++ p_FmPcdPrs->p_FmPcdPrsRegs = (struct fman_prs_regs *)UINT_TO_PTR(baseAddr + PRS_REGS_OFFSET); ++ } ++ ++ p_FmPcdPrs->fmPcdPrsPortIdStatistics = p_FmPcd->p_FmPcdDriverParam->dfltCfg.port_id_stat; ++ p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit = p_FmPcd->p_FmPcdDriverParam->dfltCfg.max_prs_cyc_lim; ++ p_FmPcd->exceptions |= p_FmPcd->p_FmPcdDriverParam->dfltCfg.prs_exceptions; ++ ++ return p_FmPcdPrs; ++} ++ ++t_Error PrsInit(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdDriverParam *p_Param = p_FmPcd->p_FmPcdDriverParam; ++ uint32_t *p_TmpCode; ++ uint32_t *p_LoadTarget = (uint32_t *)PTR_MOVE(p_FmPcd->p_FmPcdPrs->p_SwPrsCode, ++ FM_PCD_SW_PRS_SIZE-FM_PCD_PRS_SW_PATCHES_SIZE); ++ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++#ifdef FM_CAPWAP_SUPPORT ++ uint8_t swPrsPatch[] = SW_PRS_UDP_LITE_PATCH; ++#else ++ uint8_t swPrsPatch[] = SW_PRS_IP_FRAG_PATCH; ++#endif /* FM_CAPWAP_SUPPORT */ ++ uint32_t i; ++ ++ ASSERT_COND(sizeof(swPrsPatch) <= (FM_PCD_PRS_SW_PATCHES_SIZE-FM_PCD_PRS_SW_TAIL_SIZE)); ++ ++ /* nothing to do in guest-partition */ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ return E_OK; ++ ++ p_TmpCode = (uint32_t *)XX_MallocSmart(ROUND_UP(sizeof(swPrsPatch),4), 0, sizeof(uint32_t)); ++ if (!p_TmpCode) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Tmp Sw-Parser code allocation FAILED")); ++ memset((uint8_t *)p_TmpCode, 0, ROUND_UP(sizeof(swPrsPatch),4)); ++ memcpy((uint8_t *)p_TmpCode, (uint8_t *)swPrsPatch, sizeof(swPrsPatch)); ++ ++ fman_prs_init(PrsRegs, &p_Param->dfltCfg); ++ ++ /* register even if no interrupts enabled, to allow future enablement */ ++ FmRegisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_ERR, PcdPrsErrorException, p_FmPcd); ++ ++ /* register even if no interrupts enabled, to allow future enablement */ ++ FmRegisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_NORMAL, PcdPrsException, p_FmPcd); ++ ++ if(p_FmPcd->exceptions & FM_PCD_EX_PRS_SINGLE_ECC) ++ FmEnableRamsEcc(p_FmPcd->h_Fm); ++ ++ if(p_FmPcd->exceptions & FM_PCD_EX_PRS_DOUBLE_ECC) ++ FmEnableRamsEcc(p_FmPcd->h_Fm); ++ ++ /* load sw parser Ip-Frag patch */ ++ for (i=0; iguestId == NCSW_MASTER_ID); ++ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_ERR); ++ /* register even if no interrupts enabled, to allow future enablement */ ++ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_NORMAL); ++} ++ ++void PrsEnable(t_FmPcd *p_FmPcd) ++{ ++ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); ++ fman_prs_enable(PrsRegs); ++} ++ ++void PrsDisable(t_FmPcd *p_FmPcd) ++{ ++ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); ++ fman_prs_disable(PrsRegs); ++} ++ ++t_Error PrsIncludePortInStatistics(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, bool include) ++{ ++ struct fman_prs_regs *PrsRegs; ++ uint32_t bitMask = 0; ++ uint8_t prsPortId; ++ ++ SANITY_CHECK_RETURN_ERROR((hardwarePortId >=1 && hardwarePortId <= 16), E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE); ++ ++ PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ GET_FM_PCD_PRS_PORT_ID(prsPortId, hardwarePortId); ++ GET_FM_PCD_INDEX_FLAG(bitMask, prsPortId); ++ ++ if (include) ++ p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics |= bitMask; ++ else ++ p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics &= ~bitMask; ++ ++ fman_prs_set_stst_port_msk(PrsRegs, ++ p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdPrsIncludePortInStatistics(t_Handle h_FmPcd, uint8_t hardwarePortId, bool include) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR((hardwarePortId >=1 && hardwarePortId <= 16), E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE); ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ p_FmPcd->h_IpcSession) ++ { ++ t_FmPcdIpcPrsIncludePort prsIncludePortParams; ++ t_FmPcdIpcMsg msg; ++ ++ prsIncludePortParams.hardwarePortId = hardwarePortId; ++ prsIncludePortParams.include = include; ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_PCD_PRS_INC_PORT_STATS; ++ memcpy(msg.msgBody, &prsIncludePortParams, sizeof(prsIncludePortParams)); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) +sizeof(prsIncludePortParams), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ return E_OK; ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ return PrsIncludePortInStatistics(p_FmPcd, hardwarePortId, include); ++} ++ ++uint32_t FmPcdGetSwPrsOffset(t_Handle h_FmPcd, e_NetHeaderType hdr, uint8_t indexPerHdr) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdPrsLabelParams *p_Label; ++ int i; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE, 0); ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ p_FmPcd->h_IpcSession) ++ { ++ t_Error err = E_OK; ++ t_FmPcdIpcSwPrsLable labelParams; ++ t_FmPcdIpcMsg msg; ++ uint32_t prsOffset = 0; ++ t_FmPcdIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ labelParams.enumHdr = (uint32_t)hdr; ++ labelParams.indexPerHdr = indexPerHdr; ++ msg.msgId = FM_PCD_GET_SW_PRS_OFFSET; ++ memcpy(msg.msgBody, &labelParams, sizeof(labelParams)); ++ replyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) +sizeof(labelParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t) + sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ ++ memcpy((uint8_t*)&prsOffset, reply.replyBody, sizeof(uint32_t)); ++ return prsOffset; ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdPrs->currLabel < FM_PCD_PRS_NUM_OF_LABELS); ++ ++ for (i=0; ip_FmPcdPrs->currLabel; i++) ++ { ++ p_Label = &p_FmPcd->p_FmPcdPrs->labelsTable[i]; ++ ++ if ((hdr == p_Label->hdr) && (indexPerHdr == p_Label->indexPerHdr)) ++ return p_Label->instructionOffset; ++ } ++ ++ REPORT_ERROR(MAJOR, E_NOT_FOUND, ("Sw Parser attachment Not found")); ++ return (uint32_t)ILLEGAL_BASE; ++} ++ ++void FM_PCD_SetPrsStatistics(t_Handle h_FmPcd, bool enable) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ struct fman_prs_regs *PrsRegs; ++ ++ SANITY_CHECK_RETURN(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE); ++ ++ PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ ++ if(p_FmPcd->guestId != NCSW_MASTER_ID) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetPrsStatistics - guest mode!")); ++ return; ++ } ++ ++ fman_prs_set_stst(PrsRegs, enable); ++} ++ ++t_Error FM_PCD_PrsLoadSw(t_Handle h_FmPcd, t_FmPcdPrsSwParams *p_SwPrs) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t *p_LoadTarget; ++ uint32_t *p_TmpCode; ++ int i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_SwPrs, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->enabled, E_INVALID_HANDLE); ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode!")); ++ ++ if (!p_SwPrs->override) ++ { ++ if(p_FmPcd->p_FmPcdPrs->p_CurrSwPrs > p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SW parser base must be larger than current loaded code")); ++ } ++ else ++ p_FmPcd->p_FmPcdPrs->currLabel = 0; ++ ++ if (p_SwPrs->size > FM_PCD_SW_PRS_SIZE - FM_PCD_PRS_SW_TAIL_SIZE - p_SwPrs->base*2) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_SwPrs->size may not be larger than MAX_SW_PRS_CODE_SIZE")); ++ ++ if (p_FmPcd->p_FmPcdPrs->currLabel + p_SwPrs->numOfLabels > FM_PCD_PRS_NUM_OF_LABELS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceeded number of labels allowed ")); ++ ++ p_TmpCode = (uint32_t *)XX_MallocSmart(ROUND_UP(p_SwPrs->size,4), 0, sizeof(uint32_t)); ++ if (!p_TmpCode) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Tmp Sw-Parser code allocation FAILED")); ++ memset((uint8_t *)p_TmpCode, 0, ROUND_UP(p_SwPrs->size,4)); ++ memcpy((uint8_t *)p_TmpCode, p_SwPrs->p_Code, p_SwPrs->size); ++ ++ /* save sw parser labels */ ++ memcpy(&p_FmPcd->p_FmPcdPrs->labelsTable[p_FmPcd->p_FmPcdPrs->currLabel], ++ p_SwPrs->labelsTable, ++ p_SwPrs->numOfLabels*sizeof(t_FmPcdPrsLabelParams)); ++ p_FmPcd->p_FmPcdPrs->currLabel += p_SwPrs->numOfLabels; ++ ++ /* load sw parser code */ ++ p_LoadTarget = p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4; ++ for(i=0; isize,4); i++) ++ WRITE_UINT32(p_LoadTarget[i], p_TmpCode[i]); ++ p_FmPcd->p_FmPcdPrs->p_CurrSwPrs = ++ p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4 + ROUND_UP(p_SwPrs->size,4); ++ ++ /* copy data parameters */ ++ for (i=0;ip_FmPcdPrs->p_SwPrsCode+PRS_SW_DATA/4+i), p_SwPrs->swPrsDataParams[i]); ++ ++ /* Clear last 4 bytes */ ++ WRITE_UINT32(*(p_FmPcd->p_FmPcdPrs->p_SwPrsCode+(PRS_SW_DATA-FM_PCD_PRS_SW_TAIL_SIZE)/4), 0); ++ ++ XX_FreeSmart(p_TmpCode); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ConfigPrsMaxCycleLimit(t_Handle h_FmPcd,uint16_t value) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); ++ ++ if(p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigPrsMaxCycleLimit - guest mode!")); ++ ++ p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit = value; ++ ++ return E_OK; ++} ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++t_Error FM_PCD_PrsDumpRegs(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ DECLARE_DUMP; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(((p_FmPcd->guestId == NCSW_MASTER_ID) || ++ p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs), E_INVALID_OPERATION); ++ ++ DUMP_SUBTITLE(("\n")); ++ DUMP_TITLE(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs, ("FM-PCD parser regs")); ++ ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_rpclim); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_rpimac); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,pmeec); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_pevr); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_pever); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_perr); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_perer); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_ppsc); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_pds); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l2rrs); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l3rrs); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l4rrs); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_srrs); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l2rres); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l3rres); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l4rres); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_srres); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_spcs); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_spscs); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_hxscs); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_mrcs); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_mwcs); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_mrscs); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_mwscs); ++ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_fcscs); ++ ++ return E_OK; ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_prs.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_prs.h +new file mode 100644 +index 0000000..3e5974c5 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_prs.h +@@ -0,0 +1,193 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_prs.h ++ ++ @Description FM Parser private header ++*//***************************************************************************/ ++#ifndef __FM_PRS_H ++#define __FM_PRS_H ++ ++#include "std_ext.h" ++ ++ ++/***********************************************************************/ ++/* SW parser IP_FRAG patch */ ++/***********************************************************************/ ++ ++ ++#ifdef FM_CAPWAP_SUPPORT ++#define SW_PRS_UDP_LITE_PATCH \ ++{\ ++ 0x31,0x92,0x50,0x29,0x00,0x88,0x08,0x16,0x00,0x00, \ ++ 0x00,0x01,0x00,0x05,0x00,0x81,0x1C,0x0B,0x00,0x01, \ ++ 0x1B,0xFF, \ ++} ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++#if (DPAA_VERSION == 10) ++/* Version: 106.1.9 */ ++#define SW_PRS_IP_FRAG_PATCH \ ++{ \ ++ 0x31,0x52,0x00,0xDA,0x0A,0x00,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x43,0x0A,0x00,0x00,0x00,0x01,0x1B,0xFE, \ ++ 0x00,0x00,0x99,0x00,0x53,0x13,0x00,0x00,0x00,0x00, \ ++ 0x9F,0x98,0x53,0x13,0x00,0x00,0x1B,0x23,0x33,0xF1, \ ++ 0x00,0xF9,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00, \ ++ 0x28,0x7F,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0x01, \ ++ 0x32,0xC1,0x32,0xF0,0x00,0x4A,0x00,0x80,0x1F,0xFF, \ ++ 0x00,0x01,0x1B,0xFE,0x31,0x52,0x00,0xDA,0x06,0x00, \ ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x2F,0x00,0x00, \ ++ 0x00,0x01,0x1B,0xFE,0x31,0x52,0x00,0xDA,0x00,0x40, \ ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x95,0x00,0x00, \ ++ 0x00,0x00,0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55, \ ++ 0x00,0x28,0x28,0x43,0x30,0x7E,0x43,0x45,0x00,0x00, \ ++ 0x30,0x7E,0x43,0x45,0x00,0x3C,0x1B,0x5D,0x32,0x11, \ ++ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x83,0x8F, \ ++ 0x2F,0x0F,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \ ++ 0x00,0x55,0x00,0x01,0x00,0x81,0x32,0x11,0x00,0x00, \ ++ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \ ++ 0x28,0x43,0x06,0x00,0x1B,0x3E,0x30,0x7E,0x53,0x79, \ ++ 0x00,0x2B,0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x81, \ ++ 0x00,0x00,0x87,0x8F,0x28,0x23,0x06,0x00,0x32,0x11, \ ++ 0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01,0x00,0x81, \ ++ 0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50,0x00,0x01, \ ++ 0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00,0x00,0x01, \ ++ 0x1B,0xFE,0x00,0x00,0x9B,0x8E,0x53,0x90,0x00,0x00, \ ++ 0x06,0x29,0x00,0x00,0x83,0x8F,0x28,0x23,0x06,0x00, \ ++ 0x06,0x29,0x32,0xC1,0x00,0x55,0x00,0x28,0x00,0x00, \ ++ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \ ++ 0x28,0x43,0x06,0x00,0x00,0x01,0x1B,0xFE,0x32,0xC1, \ ++ 0x00,0x55,0x00,0x28,0x28,0x43,0x1B,0xCF,0x00,0x00, \ ++ 0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55,0x00,0x28, \ ++ 0x28,0x43,0x30,0x7E,0x43,0xBF,0x00,0x2C,0x32,0x11, \ ++ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x87,0x8F, \ ++ 0x28,0x23,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \ ++ 0x00,0x81,0x00,0x00,0x83,0x8F,0x2F,0x0F,0x06,0x00, \ ++ 0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01, \ ++ 0x00,0x81,0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50, \ ++ 0x00,0x01,0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00, \ ++ 0x1B,0x9C,0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00, \ ++ 0x00,0x00,0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02, \ ++ 0x00,0x00,0x00,0x01,0x32,0xC1,0x32,0xF0,0x00,0x4A, \ ++ 0x00,0x80,0x1F,0xFF,0x00,0x01,0x1B,0xFE, \ ++} ++ ++#else ++/* version: 106.3.13 */ ++#define SW_PRS_IP_FRAG_PATCH \ ++{ \ ++ 0x31,0x52,0x00,0xDA,0x0E,0x4F,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x52,0xF6,0x08,0x4B,0x31,0x53,0x00,0xFB, \ ++ 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x2B, \ ++ 0x33,0xF1,0x00,0xFB,0x00,0xDF,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x28,0x7F,0x31,0x52,0x00,0xDA,0x0A,0x00, \ ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x00,0x00,0x00, \ ++ 0x00,0x01,0x1B,0xFE,0x00,0x00,0x99,0x00,0x53,0x09, \ ++ 0x00,0x00,0x00,0x00,0x9F,0x98,0x53,0x09,0x00,0x00, \ ++ 0x1B,0x24,0x09,0x5F,0x00,0x20,0x00,0x00,0x09,0x4F, \ ++ 0x00,0x20,0x00,0x00,0x34,0xB7,0x00,0xF9,0x00,0x00, \ ++ 0x01,0x00,0x00,0x00,0x00,0x00,0x2B,0x97,0x31,0xB3, \ ++ 0x29,0x8F,0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00, \ ++ 0x00,0x00,0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02, \ ++ 0x00,0x00,0x00,0x01,0x1B,0xFE,0x00,0x01,0x1B,0xFE, \ ++ 0x31,0x52,0x00,0xDA,0x0E,0x4F,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x53,0x3C,0x04,0x4B,0x31,0x53,0x00,0xFB, \ ++ 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x2B, \ ++ 0x33,0xF1,0x00,0xFB,0x00,0xDF,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x28,0x7F,0x31,0x52,0x00,0xDA,0x06,0x00, \ ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x46,0x00,0x00, \ ++ 0x00,0x01,0x1B,0xFE,0x31,0x52,0x00,0xDA,0x00,0x40, \ ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x53,0xAC,0x00,0x00, \ ++ 0x00,0x00,0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55, \ ++ 0x00,0x28,0x28,0x43,0x30,0x7E,0x43,0x5C,0x00,0x00, \ ++ 0x30,0x7E,0x43,0x5C,0x00,0x3C,0x1B,0x74,0x32,0x11, \ ++ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x83,0x8F, \ ++ 0x2F,0x0F,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \ ++ 0x00,0x55,0x00,0x01,0x00,0x81,0x32,0x11,0x00,0x00, \ ++ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \ ++ 0x28,0x43,0x06,0x00,0x1B,0x55,0x30,0x7E,0x53,0x90, \ ++ 0x00,0x2B,0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x81, \ ++ 0x00,0x00,0x87,0x8F,0x28,0x23,0x06,0x00,0x32,0x11, \ ++ 0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01,0x00,0x81, \ ++ 0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50,0x00,0x01, \ ++ 0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00,0x00,0x01, \ ++ 0x1B,0xFE,0x00,0x00,0x9B,0x8E,0x53,0xA7,0x00,0x00, \ ++ 0x06,0x29,0x00,0x00,0x83,0x8F,0x28,0x23,0x06,0x00, \ ++ 0x06,0x29,0x32,0xC1,0x00,0x55,0x00,0x28,0x00,0x00, \ ++ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \ ++ 0x28,0x43,0x06,0x00,0x00,0x01,0x1B,0xFE,0x32,0xC1, \ ++ 0x00,0x55,0x00,0x28,0x28,0x43,0x1B,0xF1,0x00,0x00, \ ++ 0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55,0x00,0x28, \ ++ 0x28,0x43,0x30,0x7E,0x43,0xD6,0x00,0x2C,0x32,0x11, \ ++ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x87,0x8F, \ ++ 0x28,0x23,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \ ++ 0x00,0x81,0x00,0x00,0x83,0x8F,0x2F,0x0F,0x06,0x00, \ ++ 0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01, \ ++ 0x00,0x81,0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50, \ ++ 0x00,0x01,0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00, \ ++ 0x1B,0xB3,0x09,0x5F,0x00,0x20,0x00,0x00,0x09,0x4F, \ ++ 0x00,0x20,0x00,0x00,0x34,0xB7,0x00,0xF9,0x00,0x00, \ ++ 0x01,0x00,0x00,0x00,0x00,0x00,0x2B,0x97,0x31,0xB3, \ ++ 0x29,0x8F,0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00, \ ++ 0x00,0x00,0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02, \ ++ 0x00,0x00,0x00,0x01,0x1B,0xFE,0x00,0x01,0x1B,0xFE, \ ++} ++#endif /* (DPAA_VERSION == 10) */ ++ ++/****************************/ ++/* Parser defines */ ++/****************************/ ++#define FM_PCD_PRS_SW_TAIL_SIZE 4 /**< Number of bytes that must be cleared at ++ the end of the SW parser area */ ++ ++/* masks */ ++#define PRS_ERR_CAP 0x80000000 ++#define PRS_ERR_TYPE_DOUBLE 0x40000000 ++#define PRS_ERR_SINGLE_ECC_CNT_MASK 0x00FF0000 ++#define PRS_ERR_ADDR_MASK 0x000001FF ++ ++/* others */ ++#define PRS_MAX_CYCLE_LIMIT 8191 ++#define PRS_SW_DATA 0x00000800 ++#define PRS_REGS_OFFSET 0x00000840 ++ ++#define GET_FM_PCD_PRS_PORT_ID(prsPortId,hardwarePortId) \ ++ prsPortId = (uint8_t)(hardwarePortId & 0x0f) ++ ++#define GET_FM_PCD_INDEX_FLAG(bitMask, prsPortId) \ ++ bitMask = 0x80000000>>prsPortId ++ ++ ++#endif /* __FM_PRS_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_replic.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_replic.c +new file mode 100644 +index 0000000..6f8b3a3 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_replic.c +@@ -0,0 +1,991 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_replic.c ++ ++ @Description FM frame replicator ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_muram_ext.h" ++#include "fm_common.h" ++#include "fm_hc.h" ++#include "fm_replic.h" ++#include "fm_cc.h" ++#include "list_ext.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++static uint8_t GetMemberPosition(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ uint32_t memberIndex, ++ bool isAddOperation) ++{ ++ uint8_t memberPosition; ++ uint32_t lastMemberIndex; ++ ++ ASSERT_COND(p_ReplicGroup); ++ ++ /* the last member index is different between add and remove operation - ++ in case of remove - this is exactly the last member index ++ in case of add - this is the last member index + 1 - e.g. ++ if we have 4 members, the index of the actual last member is 3(because the ++ index starts from 0) therefore in order to add a new member as the last ++ member we shall use memberIndex = 4 and not 3 ++ */ ++ if (isAddOperation) ++ lastMemberIndex = p_ReplicGroup->numOfEntries; ++ else ++ lastMemberIndex = p_ReplicGroup->numOfEntries-1; ++ ++ /* last */ ++ if (memberIndex == lastMemberIndex) ++ memberPosition = FRM_REPLIC_LAST_MEMBER_INDEX; ++ else ++ { ++ /* first */ ++ if (memberIndex == 0) ++ memberPosition = FRM_REPLIC_FIRST_MEMBER_INDEX; ++ else ++ { ++ /* middle */ ++ ASSERT_COND(memberIndex < lastMemberIndex); ++ memberPosition = FRM_REPLIC_MIDDLE_MEMBER_INDEX; ++ } ++ } ++ return memberPosition; ++} ++ ++static t_Error MemberCheckParams(t_Handle h_FmPcd, ++ t_FmPcdCcNextEngineParams *p_MemberParams) ++{ ++ t_Error err; ++ ++ ++ if ((p_MemberParams->nextEngine != e_FM_PCD_DONE) && ++ (p_MemberParams->nextEngine != e_FM_PCD_KG) && ++ (p_MemberParams->nextEngine != e_FM_PCD_PLCR)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Next engine of a member should be MatchTable(cc) or Done or Policer")); ++ ++ /* check the regular parameters of the next engine */ ++ err = ValidateNextEngineParams(h_FmPcd, p_MemberParams, e_FM_PCD_CC_STATS_MODE_NONE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("member next engine parameters")); ++ ++ return E_OK; ++} ++ ++static t_Error CheckParams(t_Handle h_FmPcd, ++ t_FmPcdFrmReplicGroupParams *p_ReplicGroupParam) ++{ ++ int i; ++ t_Error err; ++ ++ /* check that max num of entries is at least 2 */ ++ if (!IN_RANGE(2, p_ReplicGroupParam->maxNumOfEntries, FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES)) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("maxNumOfEntries in the frame replicator parameters should be 2-%d",FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES)); ++ ++ /* check that number of entries is greater than zero */ ++ if (!p_ReplicGroupParam->numOfEntries) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOFEntries in the frame replicator group should be greater than zero")); ++ ++ /* check that max num of entries is equal or greater than number of entries */ ++ if (p_ReplicGroupParam->maxNumOfEntries < p_ReplicGroupParam->numOfEntries) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumOfEntries should be equal or greater than numOfEntries")); ++ ++ for (i=0; inumOfEntries; i++) ++ { ++ err = MemberCheckParams(h_FmPcd, &p_ReplicGroupParam->nextEngineParams[i]); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("member check parameters")); ++ } ++ return E_OK; ++} ++ ++static t_FmPcdFrmReplicMember *GetAvailableMember(t_FmPcdFrmReplicGroup *p_ReplicGroup) ++{ ++ t_FmPcdFrmReplicMember *p_ReplicMember = NULL; ++ t_List *p_Next; ++ ++ if (!LIST_IsEmpty(&p_ReplicGroup->availableMembersList)) ++ { ++ p_Next = LIST_FIRST(&p_ReplicGroup->availableMembersList); ++ p_ReplicMember = LIST_OBJECT(p_Next, t_FmPcdFrmReplicMember, node); ++ ASSERT_COND(p_ReplicMember); ++ LIST_DelAndInit(p_Next); ++ } ++ return p_ReplicMember; ++} ++ ++static void PutAvailableMember(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdFrmReplicMember *p_ReplicMember) ++{ ++ LIST_AddToTail(&p_ReplicMember->node, &p_ReplicGroup->availableMembersList); ++} ++ ++static void AddMemberToList(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdFrmReplicMember *p_CurrentMember, ++ t_List *p_ListHead) ++{ ++ LIST_Add(&p_CurrentMember->node, p_ListHead); ++ ++ p_ReplicGroup->numOfEntries++; ++} ++ ++static void RemoveMemberFromList(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdFrmReplicMember *p_CurrentMember) ++{ ++ ASSERT_COND(p_ReplicGroup->numOfEntries); ++ LIST_DelAndInit(&p_CurrentMember->node); ++ p_ReplicGroup->numOfEntries--; ++} ++ ++static void LinkSourceToMember(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_AdOfTypeContLookup *p_SourceTd, ++ t_FmPcdFrmReplicMember *p_ReplicMember) ++{ ++ t_FmPcd *p_FmPcd; ++ ++ ASSERT_COND(p_SourceTd); ++ ASSERT_COND(p_ReplicMember); ++ ASSERT_COND(p_ReplicGroup); ++ ASSERT_COND(p_ReplicGroup->h_FmPcd); ++ ++ /* Link the first member in the group to the source TD */ ++ p_FmPcd = p_ReplicGroup->h_FmPcd; ++ ++ WRITE_UINT32(p_SourceTd->matchTblPtr, ++ (uint32_t)(XX_VirtToPhys(p_ReplicMember->p_MemberAd) - ++ p_FmPcd->physicalMuramBase)); ++} ++ ++static void LinkMemberToMember(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdFrmReplicMember *p_CurrentMember, ++ t_FmPcdFrmReplicMember *p_NextMember) ++{ ++ t_AdOfTypeResult *p_CurrReplicAd = (t_AdOfTypeResult*)p_CurrentMember->p_MemberAd; ++ t_AdOfTypeResult *p_NextReplicAd = NULL; ++ t_FmPcd *p_FmPcd; ++ uint32_t offset = 0; ++ ++ /* Check if the next member exists or it's NULL (- means that this is the last member) */ ++ if (p_NextMember) ++ { ++ p_NextReplicAd = (t_AdOfTypeResult*)p_NextMember->p_MemberAd; ++ p_FmPcd = p_ReplicGroup->h_FmPcd; ++ offset = (XX_VirtToPhys(p_NextReplicAd) - (p_FmPcd->physicalMuramBase)); ++ offset = ((offset>>NEXT_FRM_REPLIC_ADDR_SHIFT)<< NEXT_FRM_REPLIC_MEMBER_INDEX_SHIFT); ++ } ++ ++ /* link the current AD to point to the AD of the next member */ ++ WRITE_UINT32(p_CurrReplicAd->res, offset); ++} ++ ++static t_Error ModifyDescriptor(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ void *p_OldDescriptor, ++ void *p_NewDescriptor) ++{ ++ t_Handle h_Hc; ++ t_Error err; ++ t_FmPcd *p_FmPcd; ++ ++ ASSERT_COND(p_ReplicGroup); ++ ASSERT_COND(p_ReplicGroup->h_FmPcd); ++ ASSERT_COND(p_OldDescriptor); ++ ASSERT_COND(p_NewDescriptor); ++ ++ p_FmPcd = p_ReplicGroup->h_FmPcd; ++ h_Hc = FmPcdGetHcHandle(p_FmPcd); ++ if (!h_Hc) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("Host command")); ++ ++ err = FmHcPcdCcDoDynamicChange(h_Hc, ++ (uint32_t)(XX_VirtToPhys(p_OldDescriptor) - p_FmPcd->physicalMuramBase), ++ (uint32_t)(XX_VirtToPhys(p_NewDescriptor) - p_FmPcd->physicalMuramBase)); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Dynamic change host command")); ++ ++ return E_OK; ++} ++ ++static void FillReplicAdOfTypeResult(void *p_ReplicAd, bool last) ++{ ++ t_AdOfTypeResult *p_CurrReplicAd = (t_AdOfTypeResult*)p_ReplicAd; ++ uint32_t tmp; ++ ++ tmp = GET_UINT32(p_CurrReplicAd->plcrProfile); ++ if (last) ++ /* clear the NL bit in case it's the last member in the group*/ ++ WRITE_UINT32(p_CurrReplicAd->plcrProfile,(tmp & ~FRM_REPLIC_NL_BIT)); ++ else ++ /* set the NL bit in case it's not the last member in the group */ ++ WRITE_UINT32(p_CurrReplicAd->plcrProfile, (tmp |FRM_REPLIC_NL_BIT)); ++ ++ /* set FR bit in the action descriptor */ ++ tmp = GET_UINT32(p_CurrReplicAd->nia); ++ WRITE_UINT32(p_CurrReplicAd->nia, ++ (tmp | FRM_REPLIC_FR_BIT | FM_PCD_AD_RESULT_EXTENDED_MODE )); ++} ++ ++static void BuildSourceTd(void *p_Ad) ++{ ++ t_AdOfTypeContLookup *p_SourceTd; ++ ++ ASSERT_COND(p_Ad); ++ ++ p_SourceTd = (t_AdOfTypeContLookup *)p_Ad; ++ ++ IOMemSet32((uint8_t*)p_SourceTd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* initialize the source table descriptor */ ++ WRITE_UINT32(p_SourceTd->ccAdBase, FM_PCD_AD_CONT_LOOKUP_TYPE); ++ WRITE_UINT32(p_SourceTd->pcAndOffsets, FRM_REPLIC_SOURCE_TD_OPCODE); ++} ++ ++static t_Error BuildShadowAndModifyDescriptor(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdFrmReplicMember *p_NextMember, ++ t_FmPcdFrmReplicMember *p_CurrentMember, ++ bool sourceDescriptor, ++ bool last) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdFrmReplicMember shadowMember; ++ t_Error err; ++ ++ ASSERT_COND(p_ReplicGroup); ++ ASSERT_COND(p_ReplicGroup->h_FmPcd); ++ ++ p_FmPcd = p_ReplicGroup->h_FmPcd; ++ ASSERT_COND(p_FmPcd->p_CcShadow); ++ ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ return ERROR_CODE(E_BUSY); ++ ++ if (sourceDescriptor) ++ { ++ BuildSourceTd(p_FmPcd->p_CcShadow); ++ LinkSourceToMember(p_ReplicGroup, p_FmPcd->p_CcShadow, p_NextMember); ++ ++ /* Modify the source table descriptor according to the prepared shadow descriptor */ ++ err = ModifyDescriptor(p_ReplicGroup, ++ p_ReplicGroup->p_SourceTd, ++ p_FmPcd->p_CcShadow/* new prepared source td */); ++ ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Modify source Descriptor in BuildShadowAndModifyDescriptor")); ++ ++ } ++ else ++ { ++ IO2IOCpy32(p_FmPcd->p_CcShadow, ++ p_CurrentMember->p_MemberAd, ++ FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* update the last bit in the shadow ad */ ++ FillReplicAdOfTypeResult(p_FmPcd->p_CcShadow, last); ++ ++ shadowMember.p_MemberAd = p_FmPcd->p_CcShadow; ++ ++ /* update the next FR member index */ ++ LinkMemberToMember(p_ReplicGroup, &shadowMember, p_NextMember); ++ ++ /* Modify the next member according to the prepared shadow descriptor */ ++ err = ModifyDescriptor(p_ReplicGroup, ++ p_CurrentMember->p_MemberAd, ++ p_FmPcd->p_CcShadow); ++ ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Modify Descriptor in BuildShadowAndModifyDescriptor")); ++ } ++ ++ ++ return E_OK; ++} ++ ++static t_FmPcdFrmReplicMember* GetMemberByIndex(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ uint16_t memberIndex) ++{ ++ int i=0; ++ t_List *p_Pos; ++ t_FmPcdFrmReplicMember *p_Member = NULL; ++ ++ LIST_FOR_EACH(p_Pos, &p_ReplicGroup->membersList) ++ { ++ if (i == memberIndex) ++ { ++ p_Member = LIST_OBJECT(p_Pos, t_FmPcdFrmReplicMember, node); ++ return p_Member; ++ } ++ i++; ++ } ++ return p_Member; ++} ++ ++static t_Error AllocMember(t_FmPcdFrmReplicGroup *p_ReplicGroup) ++{ ++ t_FmPcdFrmReplicMember *p_CurrentMember; ++ t_Handle h_Muram; ++ ++ ASSERT_COND(p_ReplicGroup); ++ ++ h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd); ++ ASSERT_COND(h_Muram); ++ ++ /* Initialize an internal structure of a member to add to the available members list */ ++ p_CurrentMember = (t_FmPcdFrmReplicMember *)XX_Malloc(sizeof(t_FmPcdFrmReplicMember)); ++ if (!p_CurrentMember) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Frame replicator member")); ++ ++ memset(p_CurrentMember, 0 ,sizeof(t_FmPcdFrmReplicMember)); ++ ++ /* Allocate the member AD */ ++ p_CurrentMember->p_MemberAd = ++ (t_AdOfTypeResult*)FM_MURAM_AllocMem(h_Muram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ ++ if (!p_CurrentMember->p_MemberAd) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("member AD table")); ++ ++ IOMemSet32((uint8_t*)p_CurrentMember->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Add the new member to the available members list */ ++ LIST_AddToTail(&p_CurrentMember->node, &(p_ReplicGroup->availableMembersList)); ++ ++ return E_OK; ++} ++ ++static t_FmPcdFrmReplicMember* InitMember(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdCcNextEngineParams *p_MemberParams, ++ bool last) ++{ ++ t_FmPcdFrmReplicMember *p_CurrentMember = NULL; ++ ++ ASSERT_COND(p_ReplicGroup); ++ ++ /* Get an available member from the internal members list */ ++ p_CurrentMember = GetAvailableMember(p_ReplicGroup); ++ if (!p_CurrentMember) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_FOUND, ("Available member")); ++ return NULL; ++ } ++ p_CurrentMember->h_Manip = NULL; ++ ++ /* clear the Ad of the new member */ ++ IOMemSet32((uint8_t*)p_CurrentMember->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ INIT_LIST(&p_CurrentMember->node); ++ ++ /* Initialize the Ad of the member */ ++ NextStepAd(p_CurrentMember->p_MemberAd, ++ NULL, ++ p_MemberParams, ++ p_ReplicGroup->h_FmPcd); ++ ++ /* save Manip handle (for free needs) */ ++ if (p_MemberParams->h_Manip) ++ p_CurrentMember->h_Manip = p_MemberParams->h_Manip; ++ ++ /* Initialize the relevant frame replicator fields in the AD */ ++ FillReplicAdOfTypeResult(p_CurrentMember->p_MemberAd, last); ++ ++ return p_CurrentMember; ++} ++ ++static void FreeMember(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdFrmReplicMember *p_Member) ++{ ++ /* Note: Can't free the member AD just returns the member to the available ++ member list - therefore only memset the AD */ ++ ++ /* zero the AD */ ++ IOMemSet32(p_Member->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ ++ /* return the member to the available members list */ ++ PutAvailableMember(p_ReplicGroup, p_Member); ++} ++ ++static t_Error RemoveMember(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ uint16_t memberIndex) ++{ ++ t_FmPcd *p_FmPcd = NULL; ++ t_FmPcdFrmReplicMember *p_CurrentMember = NULL, *p_PreviousMember = NULL, *p_NextMember = NULL; ++ t_Error err; ++ uint8_t memberPosition; ++ ++ p_FmPcd = p_ReplicGroup->h_FmPcd; ++ ASSERT_COND(p_FmPcd); ++ ++ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex); ++ ASSERT_COND(p_CurrentMember); ++ ++ /* determine the member position in the group */ ++ memberPosition = GetMemberPosition(p_ReplicGroup, ++ memberIndex, ++ FALSE/*remove operation*/); ++ ++ switch (memberPosition) ++ { ++ case FRM_REPLIC_FIRST_MEMBER_INDEX: ++ p_NextMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex+1)); ++ ASSERT_COND(p_NextMember); ++ ++ /* update the source td itself by using a host command */ ++ err = BuildShadowAndModifyDescriptor(p_ReplicGroup, ++ p_NextMember, ++ NULL, ++ TRUE/*sourceDescriptor*/, ++ FALSE/*last*/); ++ break; ++ ++ case FRM_REPLIC_MIDDLE_MEMBER_INDEX: ++ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1)); ++ ASSERT_COND(p_PreviousMember); ++ ++ p_NextMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex+1)); ++ ASSERT_COND(p_NextMember); ++ ++ err = BuildShadowAndModifyDescriptor(p_ReplicGroup, ++ p_NextMember, ++ p_PreviousMember, ++ FALSE/*sourceDescriptor*/, ++ FALSE/*last*/); ++ ++ break; ++ ++ case FRM_REPLIC_LAST_MEMBER_INDEX: ++ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1)); ++ ASSERT_COND(p_PreviousMember); ++ ++ err = BuildShadowAndModifyDescriptor(p_ReplicGroup, ++ NULL, ++ p_PreviousMember, ++ FALSE/*sourceDescriptor*/, ++ TRUE/*last*/); ++ break; ++ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member position in remove member")); ++ } ++ ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (p_CurrentMember->h_Manip) ++ { ++ FmPcdManipUpdateOwner(p_CurrentMember->h_Manip, FALSE); ++ p_CurrentMember->h_Manip = NULL; ++ } ++ ++ /* remove the member from the driver internal members list */ ++ RemoveMemberFromList(p_ReplicGroup, p_CurrentMember); ++ ++ /* return the member to the available members list */ ++ FreeMember(p_ReplicGroup, p_CurrentMember); ++ ++ return E_OK; ++} ++ ++static void DeleteGroup(t_FmPcdFrmReplicGroup *p_ReplicGroup) ++{ ++ int i, j; ++ t_Handle h_Muram; ++ t_FmPcdFrmReplicMember *p_Member, *p_CurrentMember; ++ ++ if (p_ReplicGroup) ++ { ++ ASSERT_COND(p_ReplicGroup->h_FmPcd); ++ h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd); ++ ASSERT_COND(h_Muram); ++ ++ /* free the source table descriptor */ ++ if (p_ReplicGroup->p_SourceTd) ++ { ++ FM_MURAM_FreeMem(h_Muram, p_ReplicGroup->p_SourceTd); ++ p_ReplicGroup->p_SourceTd = NULL; ++ } ++ ++ /* Remove all members from the members linked list (hw and sw) and ++ return the members to the available members list */ ++ if (p_ReplicGroup->numOfEntries) ++ { ++ j = p_ReplicGroup->numOfEntries-1; ++ ++ /* manually removal of the member because there are no owners of ++ this group */ ++ for (i=j; i>=0; i--) ++ { ++ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)i/*memberIndex*/); ++ ASSERT_COND(p_CurrentMember); ++ ++ if (p_CurrentMember->h_Manip) ++ { ++ FmPcdManipUpdateOwner(p_CurrentMember->h_Manip, FALSE); ++ p_CurrentMember->h_Manip = NULL; ++ } ++ ++ /* remove the member from the internal driver members list */ ++ RemoveMemberFromList(p_ReplicGroup, p_CurrentMember); ++ ++ /* return the member to the available members list */ ++ FreeMember(p_ReplicGroup, p_CurrentMember); ++ } ++ } ++ ++ /* Free members AD */ ++ for (i=0; imaxNumOfEntries; i++) ++ { ++ p_Member = GetAvailableMember(p_ReplicGroup); ++ ASSERT_COND(p_Member); ++ if (p_Member->p_MemberAd) ++ { ++ FM_MURAM_FreeMem(h_Muram, p_Member->p_MemberAd); ++ p_Member->p_MemberAd = NULL; ++ } ++ XX_Free(p_Member); ++ } ++ ++ /* release the group lock */ ++ if (p_ReplicGroup->p_Lock) ++ FmPcdReleaseLock(p_ReplicGroup->h_FmPcd, p_ReplicGroup->p_Lock); ++ ++ /* free the replicator group */ ++ XX_Free(p_ReplicGroup); ++ p_ReplicGroup = NULL; ++ } ++} ++ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++/* NOTE: the inter-module routines are locked by cc in case of using them */ ++void * FrmReplicGroupGetSourceTableDescriptor(t_Handle h_ReplicGroup) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup; ++ ASSERT_COND(p_ReplicGroup); ++ ++ return (p_ReplicGroup->p_SourceTd); ++} ++ ++void FrmReplicGroupUpdateAd(t_Handle h_ReplicGroup, ++ void *p_Ad, ++ t_Handle *h_AdNew) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup; ++ t_AdOfTypeResult *p_AdResult = (t_AdOfTypeResult*)p_Ad; ++ t_FmPcd *p_FmPcd; ++ ++ ASSERT_COND(p_ReplicGroup); ++ p_FmPcd = p_ReplicGroup->h_FmPcd; ++ ++ /* build a bypass ad */ ++ WRITE_UINT32(p_AdResult->fqid, FM_PCD_AD_BYPASS_TYPE | ++ (uint32_t)((XX_VirtToPhys(p_ReplicGroup->p_SourceTd)) - p_FmPcd->physicalMuramBase)); ++ ++ *h_AdNew = NULL; ++} ++ ++void FrmReplicGroupUpdateOwner(t_Handle h_ReplicGroup, ++ bool add) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup; ++ ASSERT_COND(p_ReplicGroup); ++ ++ /* update the group owner counter */ ++ if (add) ++ p_ReplicGroup->owners++; ++ else ++ { ++ ASSERT_COND(p_ReplicGroup->owners); ++ p_ReplicGroup->owners--; ++ } ++} ++ ++t_Error FrmReplicGroupTryLock(t_Handle h_ReplicGroup) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup; ++ ++ ASSERT_COND(h_ReplicGroup); ++ ++ if (FmPcdLockTryLock(p_ReplicGroup->p_Lock)) ++ return E_OK; ++ ++ return ERROR_CODE(E_BUSY); ++} ++ ++void FrmReplicGroupUnlock(t_Handle h_ReplicGroup) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup; ++ ++ ASSERT_COND(h_ReplicGroup); ++ ++ FmPcdLockUnlock(p_ReplicGroup->p_Lock); ++} ++/*********************** End of inter-module routines ************************/ ++ ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++t_Handle FM_PCD_FrmReplicSetGroup(t_Handle h_FmPcd, ++ t_FmPcdFrmReplicGroupParams *p_ReplicGroupParam) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup; ++ t_FmPcdFrmReplicMember *p_CurrentMember, *p_NextMember = NULL; ++ int i; ++ t_Error err; ++ bool last = FALSE; ++ t_Handle h_Muram; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_ReplicGroupParam, E_INVALID_HANDLE, NULL); ++ ++ if (!FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Advanced-offload must be enabled")); ++ return NULL; ++ } ++ ++ err = CheckParams(h_FmPcd, p_ReplicGroupParam); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, (NO_MSG)); ++ return NULL; ++ } ++ ++ p_ReplicGroup = (t_FmPcdFrmReplicGroup*)XX_Malloc(sizeof(t_FmPcdFrmReplicGroup)); ++ if (!p_ReplicGroup) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); ++ return NULL; ++ } ++ memset(p_ReplicGroup, 0, sizeof(t_FmPcdFrmReplicGroup)); ++ ++ /* initialize lists for internal driver use */ ++ INIT_LIST(&p_ReplicGroup->availableMembersList); ++ INIT_LIST(&p_ReplicGroup->membersList); ++ ++ p_ReplicGroup->h_FmPcd = h_FmPcd; ++ ++ h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd); ++ ASSERT_COND(h_Muram); ++ ++ /* initialize the group lock */ ++ p_ReplicGroup->p_Lock = FmPcdAcquireLock(p_ReplicGroup->h_FmPcd); ++ if (!p_ReplicGroup->p_Lock) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Replic group lock")); ++ DeleteGroup(p_ReplicGroup); ++ return NULL; ++ } ++ ++ /* Allocate the frame replicator source table descriptor */ ++ p_ReplicGroup->p_SourceTd = ++ (t_Handle)FM_MURAM_AllocMem(h_Muram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_ReplicGroup->p_SourceTd) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("frame replicator source table descriptor")); ++ DeleteGroup(p_ReplicGroup); ++ return NULL; ++ } ++ ++ /* update the shadow size - required for the host commands */ ++ err = FmPcdUpdateCcShadow(p_ReplicGroup->h_FmPcd, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, ("Update CC shadow")); ++ DeleteGroup(p_ReplicGroup); ++ return NULL; ++ } ++ ++ p_ReplicGroup->maxNumOfEntries = p_ReplicGroupParam->maxNumOfEntries; ++ ++ /* Allocate the maximal number of members ADs and Statistics AD for the group ++ It prevents allocation of Muram in run-time */ ++ for (i=0; imaxNumOfEntries; i++) ++ { ++ err = AllocMember(p_ReplicGroup); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, ("allocate a new member")); ++ DeleteGroup(p_ReplicGroup); ++ return NULL; ++ } ++ } ++ ++ /* Initialize the members linked lists: ++ (hw - the one that is used by the FMan controller and ++ sw - the one that is managed by the driver internally) */ ++ for (i=(p_ReplicGroupParam->numOfEntries-1); i>=0; i--) ++ { ++ /* check if this is the last member in the group */ ++ if (i == (p_ReplicGroupParam->numOfEntries-1)) ++ last = TRUE; ++ else ++ last = FALSE; ++ ++ /* Initialize a new member */ ++ p_CurrentMember = InitMember(p_ReplicGroup, ++ &(p_ReplicGroupParam->nextEngineParams[i]), ++ last); ++ if (!p_CurrentMember) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("No available member")); ++ DeleteGroup(p_ReplicGroup); ++ return NULL; ++ } ++ ++ /* Build the members group - link two consecutive members in the hw linked list */ ++ LinkMemberToMember(p_ReplicGroup, p_CurrentMember, p_NextMember); ++ ++ /* update the driver internal members list to be compatible to the hw members linked list */ ++ AddMemberToList(p_ReplicGroup, p_CurrentMember, &p_ReplicGroup->membersList); ++ ++ p_NextMember = p_CurrentMember; ++ } ++ ++ /* initialize the source table descriptor */ ++ BuildSourceTd(p_ReplicGroup->p_SourceTd); ++ ++ /* link the source table descriptor to point to the first member in the group */ ++ LinkSourceToMember(p_ReplicGroup, p_ReplicGroup->p_SourceTd, p_NextMember); ++ ++ return p_ReplicGroup; ++} ++ ++t_Error FM_PCD_FrmReplicDeleteGroup(t_Handle h_ReplicGroup) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup; ++ ++ SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE); ++ ++ if (p_ReplicGroup->owners) ++ RETURN_ERROR(MAJOR, ++ E_INVALID_STATE, ++ ("the group has owners and can't be deleted")); ++ ++ DeleteGroup(p_ReplicGroup); ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* API Run-time Frame replicator Control unit functions */ ++/*****************************************************************************/ ++t_Error FM_PCD_FrmReplicAddMember(t_Handle h_ReplicGroup, ++ uint16_t memberIndex, ++ t_FmPcdCcNextEngineParams *p_MemberParams) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup*) h_ReplicGroup; ++ t_FmPcdFrmReplicMember *p_NewMember, *p_CurrentMember = NULL, *p_PreviousMember = NULL; ++ t_Error err; ++ uint8_t memberPosition; ++ ++ SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_MemberParams, E_INVALID_HANDLE); ++ ++ /* group lock */ ++ err = FrmReplicGroupTryLock(p_ReplicGroup); ++ if (err) ++ { ++ if (GET_ERROR_TYPE(err) == E_BUSY) ++ return ERROR_CODE(E_BUSY); ++ else ++ RETURN_ERROR(MAJOR, err, ("try lock in Add member")); ++ } ++ ++ if (memberIndex > p_ReplicGroup->numOfEntries) ++ { ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ++ ("memberIndex is greater than the members in the list")); ++ } ++ ++ if (memberIndex >= p_ReplicGroup->maxNumOfEntries) ++ { ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("memberIndex is greater than the allowed number of members in the group")); ++ } ++ ++ if ((p_ReplicGroup->numOfEntries + 1) > FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES) ++ { ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("numOfEntries with new entry can not be larger than %d\n", ++ FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES)); ++ } ++ ++ err = MemberCheckParams(p_ReplicGroup->h_FmPcd, p_MemberParams); ++ if (err) ++ { ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ RETURN_ERROR(MAJOR, err, ("member check parameters in add operation")); ++ } ++ /* determine the member position in the group */ ++ memberPosition = GetMemberPosition(p_ReplicGroup, ++ memberIndex, ++ TRUE/* add operation */); ++ ++ /* Initialize a new member */ ++ p_NewMember = InitMember(p_ReplicGroup, ++ p_MemberParams, ++ (memberPosition == FRM_REPLIC_LAST_MEMBER_INDEX ? TRUE : FALSE)); ++ if (!p_NewMember) ++ { ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("No available member")); ++ } ++ ++ switch (memberPosition) ++ { ++ case FRM_REPLIC_FIRST_MEMBER_INDEX: ++ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex); ++ ASSERT_COND(p_CurrentMember); ++ ++ LinkMemberToMember(p_ReplicGroup, p_NewMember, p_CurrentMember); ++ ++ /* update the internal group source TD */ ++ LinkSourceToMember(p_ReplicGroup, ++ p_ReplicGroup->p_SourceTd, ++ p_NewMember); ++ ++ /* add member to the internal sw member list */ ++ AddMemberToList(p_ReplicGroup, ++ p_NewMember, ++ &p_ReplicGroup->membersList); ++ break; ++ ++ case FRM_REPLIC_MIDDLE_MEMBER_INDEX: ++ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex); ++ ASSERT_COND(p_CurrentMember); ++ ++ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1)); ++ ASSERT_COND(p_PreviousMember); ++ ++ LinkMemberToMember(p_ReplicGroup, p_NewMember, p_CurrentMember); ++ LinkMemberToMember(p_ReplicGroup, p_PreviousMember, p_NewMember); ++ ++ AddMemberToList(p_ReplicGroup, p_NewMember, &p_PreviousMember->node); ++ break; ++ ++ case FRM_REPLIC_LAST_MEMBER_INDEX: ++ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1)); ++ ASSERT_COND(p_PreviousMember); ++ ++ LinkMemberToMember(p_ReplicGroup, p_PreviousMember, p_NewMember); ++ FillReplicAdOfTypeResult(p_PreviousMember->p_MemberAd, FALSE/*last*/); ++ ++ /* add the new member to the internal sw member list */ ++ AddMemberToList(p_ReplicGroup, p_NewMember, &p_PreviousMember->node); ++ break; ++ ++ default: ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member position in add member")); ++ ++ } ++ ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_FrmReplicRemoveMember(t_Handle h_ReplicGroup, ++ uint16_t memberIndex) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup*) h_ReplicGroup; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE); ++ ++ /* lock */ ++ err = FrmReplicGroupTryLock(p_ReplicGroup); ++ if (err) ++ { ++ if (GET_ERROR_TYPE(err) == E_BUSY) ++ return ERROR_CODE(E_BUSY); ++ else ++ RETURN_ERROR(MAJOR, err, ("try lock in Remove member")); ++ } ++ ++ if (memberIndex >= p_ReplicGroup->numOfEntries) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member index to remove")); ++ ++ /* Design decision: group must contain at least one member ++ No possibility to remove the last member from the group */ ++ if (p_ReplicGroup->numOfEntries == 1) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ("Can't remove the last member. At least one member should be related to a group.")); ++ ++ err = RemoveMember(p_ReplicGroup, memberIndex); ++ ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ ++ switch (GET_ERROR_TYPE(err)) ++ { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++/*********************** End of API routines ************************/ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_replic.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_replic.h +new file mode 100644 +index 0000000..3cfd67e +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fm_replic.h +@@ -0,0 +1,104 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_replic.h ++ ++ @Description FM frame replicator ++*//***************************************************************************/ ++#ifndef __FM_REPLIC_H ++#define __FM_REPLIC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++ ++ ++#define FRM_REPLIC_SOURCE_TD_OPCODE 0x75 ++#define NEXT_FRM_REPLIC_ADDR_SHIFT 4 ++#define NEXT_FRM_REPLIC_MEMBER_INDEX_SHIFT 16 ++#define FRM_REPLIC_FR_BIT 0x08000000 ++#define FRM_REPLIC_NL_BIT 0x10000000 ++#define FRM_REPLIC_INVALID_MEMBER_INDEX 0xffff ++#define FRM_REPLIC_FIRST_MEMBER_INDEX 0 ++ ++#define FRM_REPLIC_MIDDLE_MEMBER_INDEX 1 ++#define FRM_REPLIC_LAST_MEMBER_INDEX 2 ++ ++#define SOURCE_TD_ITSELF_OPTION 0x01 ++#define SOURCE_TD_COPY_OPTION 0x02 ++#define SOURCE_TD_ITSELF_AND_COPY_OPTION SOURCE_TD_ITSELF_OPTION | SOURCE_TD_COPY_OPTION ++#define SOURCE_TD_NONE 0x04 ++ ++/*typedef enum e_SourceTdOption ++{ ++ e_SOURCE_TD_NONE = 0, ++ e_SOURCE_TD_ITSELF_OPTION = 1, ++ e_SOURCE_TD_COPY_OPTION = 2, ++ e_SOURCE_TD_ITSELF_AND_COPY_OPTION = e_SOURCE_TD_ITSELF_OPTION | e_SOURCE_TD_COPY_OPTION ++} e_SourceTdOption; ++*/ ++ ++typedef _Packed struct ++{ ++ volatile uint32_t type; ++ volatile uint32_t frGroupPointer; ++ volatile uint32_t operationCode; ++ volatile uint32_t reserved; ++} _PackedType t_FrmReplicGroupSourceAd; ++ ++typedef struct t_FmPcdFrmReplicMember ++{ ++ void *p_MemberAd; /**< pointer to the member AD */ ++ void *p_StatisticsAd;/**< pointer to the statistics AD of the member */ ++ t_Handle h_Manip; /**< manip handle - need for free routines */ ++ t_List node; ++} t_FmPcdFrmReplicMember; ++ ++typedef struct t_FmPcdFrmReplicGroup ++{ ++ t_Handle h_FmPcd; ++#ifdef UNDER_CONSTRUCTION_STATISTICS_SUPPORT ++ e_FmPcdCcStatsMode statisticsMode; ++#endif /* UNDER_CONSTRUCTION_STATISTICS_SUPPORT */ ++ ++ uint8_t maxNumOfEntries;/**< maximal number of members in the group */ ++ uint8_t numOfEntries; /**< actual number of members in the group */ ++ uint16_t owners; /**< how many keys share this frame replicator group */ ++ void *p_SourceTd; /**< pointer to the frame replicator source table descriptor */ ++ t_List membersList; /**< the members list - should reflect the order of the members as in the hw linked list*/ ++ t_List availableMembersList;/**< list of all the available members in the group */ ++ t_FmPcdLock *p_Lock; ++} t_FmPcdFrmReplicGroup; ++ ++ ++#endif /* __FM_REPLIC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fman_kg.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fman_kg.c +new file mode 100644 +index 0000000..14a680e +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fman_kg.c +@@ -0,0 +1,888 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "fsl_fman_kg.h" ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++ ++static uint32_t build_ar_bind_scheme(uint8_t hwport_id, bool write) ++{ ++ uint32_t rw; ++ ++ rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ; ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ rw | ++ FM_PCD_KG_KGAR_SEL_PORT_ENTRY | ++ hwport_id | ++ FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP); ++} ++ ++static void clear_pe_all_scheme(struct fman_kg_regs *regs, uint8_t hwport_id) ++{ ++ uint32_t ar; ++ ++ fman_kg_write_sp(regs, 0xffffffff, 0); ++ ++ ar = build_ar_bind_scheme(hwport_id, TRUE); ++ fman_kg_write_ar_wait(regs, ar); ++} ++ ++static uint32_t build_ar_bind_cls_plan(uint8_t hwport_id, bool write) ++{ ++ uint32_t rw; ++ ++ rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ; ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ rw | ++ FM_PCD_KG_KGAR_SEL_PORT_ENTRY | ++ hwport_id | ++ FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP); ++} ++ ++static void clear_pe_all_cls_plan(struct fman_kg_regs *regs, uint8_t hwport_id) ++{ ++ uint32_t ar; ++ ++ fman_kg_write_cpp(regs, 0); ++ ++ ar = build_ar_bind_cls_plan(hwport_id, TRUE); ++ fman_kg_write_ar_wait(regs, ar); ++} ++ ++static uint8_t get_gen_ht_code(enum fman_kg_gen_extract_src src, ++ bool no_validation, ++ uint8_t *offset) ++{ ++ int code; ++ ++ switch (src) { ++ case E_FMAN_KG_GEN_EXTRACT_ETH: ++ code = no_validation ? 0x73 : 0x3; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_ETYPE: ++ code = no_validation ? 0x77 : 0x7; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_SNAP: ++ code = no_validation ? 0x74 : 0x4; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_1: ++ code = no_validation ? 0x75 : 0x5; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_N: ++ code = no_validation ? 0x76 : 0x6; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_PPPoE: ++ code = no_validation ? 0x78 : 0x8; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_MPLS_1: ++ code = no_validation ? 0x79 : 0x9; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_MPLS_2: ++ code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x19; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_MPLS_3: ++ code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x29; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_MPLS_N: ++ code = no_validation ? 0x7a : 0xa; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IPv4_1: ++ code = no_validation ? 0x7b : 0xb; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IPv6_1: ++ code = no_validation ? 0x7b : 0x1b; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IPv4_2: ++ code = no_validation ? 0x7c : 0xc; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IPv6_2: ++ code = no_validation ? 0x7c : 0x1c; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_MINENCAP: ++ code = no_validation ? 0x7c : 0x2c; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IP_PID: ++ code = no_validation ? 0x72 : 0x2; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_GRE: ++ code = no_validation ? 0x7d : 0xd; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_TCP: ++ code = no_validation ? 0x7e : 0xe; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_UDP: ++ code = no_validation ? 0x7e : 0x1e; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_SCTP: ++ code = no_validation ? 0x7e : 0x3e; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_DCCP: ++ code = no_validation ? 0x7e : 0x4e; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IPSEC_AH: ++ code = no_validation ? 0x7e : 0x2e; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IPSEC_ESP: ++ code = no_validation ? 0x7e : 0x6e; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_SHIM_1: ++ code = 0x70; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_SHIM_2: ++ code = 0x71; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_FROM_DFLT: ++ code = 0x10; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_FROM_FRAME_START: ++ code = 0x40; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_FROM_PARSE_RESULT: ++ code = 0x20; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_FROM_END_OF_PARSE: ++ code = 0x7f; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_FROM_FQID: ++ code = 0x20; ++ *offset += 0x20; ++ break; ++ ++ default: ++ code = FM_KG_SCH_GEN_HT_INVALID; ++ } ++ ++ return (uint8_t)code; ++} ++ ++static uint32_t build_ar_scheme(uint8_t scheme, ++ uint8_t hwport_id, ++ bool update_counter, ++ bool write) ++{ ++ uint32_t rw; ++ ++ rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ); ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ rw | ++ FM_KG_KGAR_SEL_SCHEME_ENTRY | ++ hwport_id | ++ ((uint32_t)scheme << FM_KG_KGAR_NUM_SHIFT) | ++ (update_counter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT : 0)); ++} ++ ++static uint32_t build_ar_cls_plan(uint8_t grp, ++ uint8_t entries_mask, ++ uint8_t hwport_id, ++ bool write) ++{ ++ uint32_t rw; ++ ++ rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ); ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ rw | ++ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY | ++ hwport_id | ++ ((uint32_t)grp << FM_KG_KGAR_NUM_SHIFT) | ++ ((uint32_t)entries_mask << FM_KG_KGAR_WSEL_SHIFT)); ++} ++ ++int fman_kg_write_ar_wait(struct fman_kg_regs *regs, uint32_t fmkg_ar) ++{ ++ iowrite32be(fmkg_ar, ®s->fmkg_ar); ++ /* Wait for GO to be idle and read error */ ++ while ((fmkg_ar = ioread32be(®s->fmkg_ar)) & FM_KG_KGAR_GO) ; ++ if (fmkg_ar & FM_PCD_KG_KGAR_ERR) ++ return -EINVAL; ++ return 0; ++} ++ ++void fman_kg_write_sp(struct fman_kg_regs *regs, uint32_t sp, bool add) ++{ ++ ++ struct fman_kg_pe_regs *kgpe_regs; ++ uint32_t tmp; ++ ++ kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]); ++ tmp = ioread32be(&kgpe_regs->fmkg_pe_sp); ++ ++ if (add) ++ tmp |= sp; ++ else /* clear */ ++ tmp &= ~sp; ++ ++ iowrite32be(tmp, &kgpe_regs->fmkg_pe_sp); ++ ++} ++ ++void fman_kg_write_cpp(struct fman_kg_regs *regs, uint32_t cpp) ++{ ++ struct fman_kg_pe_regs *kgpe_regs; ++ ++ kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]); ++ ++ iowrite32be(cpp, &kgpe_regs->fmkg_pe_cpp); ++} ++ ++void fman_kg_get_event(struct fman_kg_regs *regs, ++ uint32_t *event, ++ uint32_t *scheme_idx) ++{ ++ uint32_t mask, force; ++ ++ *event = ioread32be(®s->fmkg_eer); ++ mask = ioread32be(®s->fmkg_eeer); ++ *scheme_idx = ioread32be(®s->fmkg_seer); ++ *scheme_idx &= ioread32be(®s->fmkg_seeer); ++ ++ *event &= mask; ++ ++ /* clear the forced events */ ++ force = ioread32be(®s->fmkg_feer); ++ if (force & *event) ++ iowrite32be(force & ~*event ,®s->fmkg_feer); ++ ++ iowrite32be(*event, ®s->fmkg_eer); ++ iowrite32be(*scheme_idx, ®s->fmkg_seer); ++} ++ ++ ++void fman_kg_init(struct fman_kg_regs *regs, ++ uint32_t exceptions, ++ uint32_t dflt_nia) ++{ ++ uint32_t tmp; ++ int i; ++ ++ iowrite32be(FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW, ++ ®s->fmkg_eer); ++ ++ tmp = 0; ++ if (exceptions & FM_EX_KG_DOUBLE_ECC) ++ tmp |= FM_EX_KG_DOUBLE_ECC; ++ ++ if (exceptions & FM_EX_KG_KEYSIZE_OVERFLOW) ++ tmp |= FM_EX_KG_KEYSIZE_OVERFLOW; ++ ++ iowrite32be(tmp, ®s->fmkg_eeer); ++ iowrite32be(0, ®s->fmkg_fdor); ++ iowrite32be(0, ®s->fmkg_gdv0r); ++ iowrite32be(0, ®s->fmkg_gdv1r); ++ iowrite32be(dflt_nia, ®s->fmkg_gcr); ++ ++ /* Clear binding between ports to schemes and classification plans ++ * so that all ports are not bound to any scheme/classification plan */ ++ for (i = 0; i < FMAN_MAX_NUM_OF_HW_PORTS; i++) { ++ clear_pe_all_scheme(regs, (uint8_t)i); ++ clear_pe_all_cls_plan(regs, (uint8_t)i); ++ } ++} ++ ++void fman_kg_enable_scheme_interrupts(struct fman_kg_regs *regs) ++{ ++ /* enable and enable all scheme interrupts */ ++ iowrite32be(0xFFFFFFFF, ®s->fmkg_seer); ++ iowrite32be(0xFFFFFFFF, ®s->fmkg_seeer); ++} ++ ++void fman_kg_enable(struct fman_kg_regs *regs) ++{ ++ iowrite32be(ioread32be(®s->fmkg_gcr) | FM_KG_KGGCR_EN, ++ ®s->fmkg_gcr); ++} ++ ++void fman_kg_disable(struct fman_kg_regs *regs) ++{ ++ iowrite32be(ioread32be(®s->fmkg_gcr) & ~FM_KG_KGGCR_EN, ++ ®s->fmkg_gcr); ++} ++ ++void fman_kg_set_data_after_prs(struct fman_kg_regs *regs, uint8_t offset) ++{ ++ iowrite32be(offset, ®s->fmkg_fdor); ++} ++ ++void fman_kg_set_dflt_val(struct fman_kg_regs *regs, ++ uint8_t def_id, ++ uint32_t val) ++{ ++ if(def_id == 0) ++ iowrite32be(val, ®s->fmkg_gdv0r); ++ else ++ iowrite32be(val, ®s->fmkg_gdv1r); ++} ++ ++ ++void fman_kg_set_exception(struct fman_kg_regs *regs, ++ uint32_t exception, ++ bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->fmkg_eeer); ++ ++ if (enable) { ++ tmp |= exception; ++ } else { ++ tmp &= ~exception; ++ } ++ ++ iowrite32be(tmp, ®s->fmkg_eeer); ++} ++ ++void fman_kg_get_exception(struct fman_kg_regs *regs, ++ uint32_t *events, ++ uint32_t *scheme_ids, ++ bool clear) ++{ ++ uint32_t mask; ++ ++ *events = ioread32be(®s->fmkg_eer); ++ mask = ioread32be(®s->fmkg_eeer); ++ *events &= mask; ++ ++ *scheme_ids = 0; ++ ++ if (*events & FM_EX_KG_KEYSIZE_OVERFLOW) { ++ *scheme_ids = ioread32be(®s->fmkg_seer); ++ mask = ioread32be(®s->fmkg_seeer); ++ *scheme_ids &= mask; ++ } ++ ++ if (clear) { ++ iowrite32be(*scheme_ids, ®s->fmkg_seer); ++ iowrite32be(*events, ®s->fmkg_eer); ++ } ++} ++ ++void fman_kg_get_capture(struct fman_kg_regs *regs, ++ struct fman_kg_ex_ecc_attr *ecc_attr, ++ bool clear) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->fmkg_serc); ++ ++ if (tmp & KG_FMKG_SERC_CAP) { ++ /* Captured data is valid */ ++ ecc_attr->valid = TRUE; ++ ecc_attr->double_ecc = ++ (bool)((tmp & KG_FMKG_SERC_CET) ? TRUE : FALSE); ++ ecc_attr->single_ecc_count = ++ (uint8_t)((tmp & KG_FMKG_SERC_CNT_MSK) >> ++ KG_FMKG_SERC_CNT_SHIFT); ++ ecc_attr->addr = (uint16_t)(tmp & KG_FMKG_SERC_ADDR_MSK); ++ ++ if (clear) ++ iowrite32be(KG_FMKG_SERC_CAP, ®s->fmkg_serc); ++ } else { ++ /* No ECC error is captured */ ++ ecc_attr->valid = FALSE; ++ } ++} ++ ++int fman_kg_build_scheme(struct fman_kg_scheme_params *params, ++ struct fman_kg_scheme_regs *scheme_regs) ++{ ++ struct fman_kg_extract_params *extract_params; ++ struct fman_kg_gen_extract_params *gen_params; ++ uint32_t tmp_reg, i, select, mask, fqb; ++ uint8_t offset, shift, ht; ++ ++ /* Zero out all registers so no need to care about unused ones */ ++ memset(scheme_regs, 0, sizeof(struct fman_kg_scheme_regs)); ++ ++ /* Mode register */ ++ tmp_reg = fm_kg_build_nia(params->next_engine, ++ params->next_engine_action); ++ if (tmp_reg == KG_NIA_INVALID) { ++ return -EINVAL; ++ } ++ ++ if (params->next_engine == E_FMAN_PCD_PLCR) { ++ tmp_reg |= FMAN_KG_SCH_MODE_NIA_PLCR; ++ } ++ else if (params->next_engine == E_FMAN_PCD_CC) { ++ tmp_reg |= (uint32_t)params->cc_params.base_offset << ++ FMAN_KG_SCH_MODE_CCOBASE_SHIFT; ++ } ++ ++ tmp_reg |= FMAN_KG_SCH_MODE_EN; ++ scheme_regs->kgse_mode = tmp_reg; ++ ++ /* Match vector */ ++ scheme_regs->kgse_mv = params->match_vector; ++ ++ extract_params = ¶ms->extract_params; ++ ++ /* Scheme default values registers */ ++ scheme_regs->kgse_dv0 = extract_params->def_scheme_0; ++ scheme_regs->kgse_dv1 = extract_params->def_scheme_1; ++ ++ /* Extract Known Fields Command register */ ++ scheme_regs->kgse_ekfc = extract_params->known_fields; ++ ++ /* Entry Extract Known Default Value register */ ++ tmp_reg = 0; ++ tmp_reg |= extract_params->known_fields_def.mac_addr << ++ FMAN_KG_SCH_DEF_MAC_ADDR_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.vlan_tci << ++ FMAN_KG_SCH_DEF_VLAN_TCI_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.etype << ++ FMAN_KG_SCH_DEF_ETYPE_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ppp_sid << ++ FMAN_KG_SCH_DEF_PPP_SID_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ppp_pid << ++ FMAN_KG_SCH_DEF_PPP_PID_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.mpls << ++ FMAN_KG_SCH_DEF_MPLS_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ip_addr << ++ FMAN_KG_SCH_DEF_IP_ADDR_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ptype << ++ FMAN_KG_SCH_DEF_PTYPE_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ip_tos_tc << ++ FMAN_KG_SCH_DEF_IP_TOS_TC_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ipv6_fl << ++ FMAN_KG_SCH_DEF_IPv6_FL_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ipsec_spi << ++ FMAN_KG_SCH_DEF_IPSEC_SPI_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.l4_port << ++ FMAN_KG_SCH_DEF_L4_PORT_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.tcp_flg << ++ FMAN_KG_SCH_DEF_TCP_FLG_SHIFT; ++ ++ scheme_regs->kgse_ekdv = tmp_reg; ++ ++ /* Generic extract registers */ ++ if (extract_params->gen_extract_num > FM_KG_NUM_OF_GENERIC_REGS) { ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < extract_params->gen_extract_num; i++) { ++ gen_params = extract_params->gen_extract + i; ++ ++ tmp_reg = FMAN_KG_SCH_GEN_VALID; ++ tmp_reg |= (uint32_t)gen_params->def_val << ++ FMAN_KG_SCH_GEN_DEF_SHIFT; ++ ++ if (gen_params->type == E_FMAN_KG_HASH_EXTRACT) { ++ if ((gen_params->extract > FMAN_KG_SCH_GEN_SIZE_MAX) || ++ (gen_params->extract == 0)) { ++ return -EINVAL; ++ } ++ } else { ++ tmp_reg |= FMAN_KG_SCH_GEN_OR; ++ } ++ ++ tmp_reg |= (uint32_t)gen_params->extract << ++ FMAN_KG_SCH_GEN_SIZE_SHIFT; ++ tmp_reg |= (uint32_t)gen_params->mask << ++ FMAN_KG_SCH_GEN_MASK_SHIFT; ++ ++ offset = gen_params->offset; ++ ht = get_gen_ht_code(gen_params->src, ++ gen_params->no_validation, ++ &offset); ++ tmp_reg |= (uint32_t)ht << FMAN_KG_SCH_GEN_HT_SHIFT; ++ tmp_reg |= offset; ++ ++ scheme_regs->kgse_gec[i] = tmp_reg; ++ } ++ ++ /* Masks registers */ ++ if (extract_params->masks_num > FM_KG_EXTRACT_MASKS_NUM) { ++ return -EINVAL; ++ } ++ ++ select = 0; ++ mask = 0; ++ fqb = 0; ++ for (i = 0; i < extract_params->masks_num; i++) { ++ /* MCSx fields */ ++ KG_GET_MASK_SEL_SHIFT(shift, i); ++ if (extract_params->masks[i].is_known) { ++ /* Mask known field */ ++ select |= extract_params->masks[i].field_or_gen_idx << ++ shift; ++ } else { ++ /* Mask generic extract */ ++ select |= (extract_params->masks[i].field_or_gen_idx + ++ FM_KG_MASK_SEL_GEN_BASE) << shift; ++ } ++ ++ /* MOx fields - spread between se_bmch and se_fqb registers */ ++ KG_GET_MASK_OFFSET_SHIFT(shift, i); ++ if (i < 2) { ++ select |= (uint32_t)extract_params->masks[i].offset << ++ shift; ++ } else { ++ fqb |= (uint32_t)extract_params->masks[i].offset << ++ shift; ++ } ++ ++ /* BMx fields */ ++ KG_GET_MASK_SHIFT(shift, i); ++ mask |= (uint32_t)extract_params->masks[i].mask << shift; ++ } ++ ++ /* Finish with rest of BMx fileds - ++ * don't mask bits for unused masks by setting ++ * corresponding BMx field = 0xFF */ ++ for (i = extract_params->masks_num; i < FM_KG_EXTRACT_MASKS_NUM; i++) { ++ KG_GET_MASK_SHIFT(shift, i); ++ mask |= 0xFF << shift; ++ } ++ ++ scheme_regs->kgse_bmch = select; ++ scheme_regs->kgse_bmcl = mask; ++ ++ /* Finish with FQB register initialization. ++ * Check fqid is 24-bit value. */ ++ if (params->base_fqid & ~0x00FFFFFF) { ++ return -EINVAL; ++ } ++ ++ fqb |= params->base_fqid; ++ scheme_regs->kgse_fqb = fqb; ++ ++ /* Hash Configuration register */ ++ tmp_reg = 0; ++ if (params->hash_params.use_hash) { ++ /* Check hash mask is 24-bit value */ ++ if (params->hash_params.mask & ~0x00FFFFFF) { ++ return -EINVAL; ++ } ++ ++ /* Hash function produces 64-bit value, 24 bits of that ++ * are used to generate fq_id and policer profile. ++ * Thus, maximal shift is 40 bits to allow 24 bits out of 64. ++ */ ++ if (params->hash_params.shift_r > FMAN_KG_SCH_HASH_HSHIFT_MAX) { ++ return -EINVAL; ++ } ++ ++ tmp_reg |= params->hash_params.mask; ++ tmp_reg |= (uint32_t)params->hash_params.shift_r << ++ FMAN_KG_SCH_HASH_HSHIFT_SHIFT; ++ ++ if (params->hash_params.sym) { ++ tmp_reg |= FMAN_KG_SCH_HASH_SYM; ++ } ++ ++ } ++ ++ if (params->bypass_fqid_gen) { ++ tmp_reg |= FMAN_KG_SCH_HASH_NO_FQID_GEN; ++ } ++ ++ scheme_regs->kgse_hc = tmp_reg; ++ ++ /* Policer Profile register */ ++ if (params->policer_params.bypass_pp_gen) { ++ tmp_reg = FMAN_KG_SCH_PP_NO_GEN; ++ } else { ++ /* Lower 8 bits of 24-bits extracted from hash result ++ * are used for policer profile generation. ++ * That leaves maximum shift value = 23. */ ++ if (params->policer_params.shift > FMAN_KG_SCH_PP_SHIFT_MAX) { ++ return -EINVAL; ++ } ++ ++ tmp_reg = params->policer_params.base; ++ tmp_reg |= ((uint32_t)params->policer_params.shift << ++ FMAN_KG_SCH_PP_SH_SHIFT) & ++ FMAN_KG_SCH_PP_SH_MASK; ++ tmp_reg |= ((uint32_t)params->policer_params.shift << ++ FMAN_KG_SCH_PP_SL_SHIFT) & ++ FMAN_KG_SCH_PP_SL_MASK; ++ tmp_reg |= (uint32_t)params->policer_params.mask << ++ FMAN_KG_SCH_PP_MASK_SHIFT; ++ } ++ ++ scheme_regs->kgse_ppc = tmp_reg; ++ ++ /* Coarse Classification Bit Select register */ ++ if (params->next_engine == E_FMAN_PCD_CC) { ++ scheme_regs->kgse_ccbs = params->cc_params.qlcv_bits_sel; ++ } ++ ++ /* Packets Counter register */ ++ if (params->update_counter) { ++ scheme_regs->kgse_spc = params->counter_value; ++ } ++ ++ return 0; ++} ++ ++int fman_kg_write_scheme(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id, ++ struct fman_kg_scheme_regs *scheme_regs, ++ bool update_counter) ++{ ++ struct fman_kg_scheme_regs *kgse_regs; ++ uint32_t tmp_reg; ++ int err, i; ++ ++ /* Write indirect scheme registers */ ++ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]); ++ ++ iowrite32be(scheme_regs->kgse_mode, &kgse_regs->kgse_mode); ++ iowrite32be(scheme_regs->kgse_ekfc, &kgse_regs->kgse_ekfc); ++ iowrite32be(scheme_regs->kgse_ekdv, &kgse_regs->kgse_ekdv); ++ iowrite32be(scheme_regs->kgse_bmch, &kgse_regs->kgse_bmch); ++ iowrite32be(scheme_regs->kgse_bmcl, &kgse_regs->kgse_bmcl); ++ iowrite32be(scheme_regs->kgse_fqb, &kgse_regs->kgse_fqb); ++ iowrite32be(scheme_regs->kgse_hc, &kgse_regs->kgse_hc); ++ iowrite32be(scheme_regs->kgse_ppc, &kgse_regs->kgse_ppc); ++ iowrite32be(scheme_regs->kgse_spc, &kgse_regs->kgse_spc); ++ iowrite32be(scheme_regs->kgse_dv0, &kgse_regs->kgse_dv0); ++ iowrite32be(scheme_regs->kgse_dv1, &kgse_regs->kgse_dv1); ++ iowrite32be(scheme_regs->kgse_ccbs, &kgse_regs->kgse_ccbs); ++ iowrite32be(scheme_regs->kgse_mv, &kgse_regs->kgse_mv); ++ ++ for (i = 0 ; i < FM_KG_NUM_OF_GENERIC_REGS ; i++) ++ iowrite32be(scheme_regs->kgse_gec[i], &kgse_regs->kgse_gec[i]); ++ ++ /* Write AR (Action register) */ ++ tmp_reg = build_ar_scheme(scheme_id, hwport_id, update_counter, TRUE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ return err; ++} ++ ++int fman_kg_delete_scheme(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id) ++{ ++ struct fman_kg_scheme_regs *kgse_regs; ++ uint32_t tmp_reg; ++ int err, i; ++ ++ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]); ++ ++ /* Clear all registers including enable bit in mode register */ ++ for (i = 0; i < (sizeof(struct fman_kg_scheme_regs)) / 4; ++i) { ++ iowrite32be(0, ((uint32_t *)kgse_regs + i)); ++ } ++ ++ /* Write AR (Action register) */ ++ tmp_reg = build_ar_scheme(scheme_id, hwport_id, FALSE, TRUE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ return err; ++} ++ ++int fman_kg_get_scheme_counter(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id, ++ uint32_t *counter) ++{ ++ struct fman_kg_scheme_regs *kgse_regs; ++ uint32_t tmp_reg; ++ int err; ++ ++ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]); ++ ++ tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ ++ if (err != 0) ++ return err; ++ ++ *counter = ioread32be(&kgse_regs->kgse_spc); ++ ++ return 0; ++} ++ ++int fman_kg_set_scheme_counter(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id, ++ uint32_t counter) ++{ ++ struct fman_kg_scheme_regs *kgse_regs; ++ uint32_t tmp_reg; ++ int err; ++ ++ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]); ++ ++ tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE); ++ ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ if (err != 0) ++ return err; ++ ++ /* Keygen indirect access memory contains all scheme_id registers ++ * by now. Change only counter value. */ ++ iowrite32be(counter, &kgse_regs->kgse_spc); ++ ++ /* Write back scheme registers */ ++ tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, TRUE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ ++ return err; ++} ++ ++uint32_t fman_kg_get_schemes_total_counter(struct fman_kg_regs *regs) ++{ ++ return ioread32be(®s->fmkg_tpc); ++} ++ ++int fman_kg_build_cls_plan(struct fman_kg_cls_plan_params *params, ++ struct fman_kg_cp_regs *cls_plan_regs) ++{ ++ uint8_t entries_set, entry_bit; ++ int i; ++ ++ /* Zero out all group's register */ ++ memset(cls_plan_regs, 0, sizeof(struct fman_kg_cp_regs)); ++ ++ /* Go over all classification entries in params->entries_mask and ++ * configure the corresponding cpe register */ ++ entries_set = params->entries_mask; ++ for (i = 0; entries_set; i++) { ++ entry_bit = (uint8_t)(0x80 >> i); ++ if ((entry_bit & entries_set) == 0) ++ continue; ++ entries_set ^= entry_bit; ++ cls_plan_regs->kgcpe[i] = params->mask_vector[i]; ++ } ++ ++ return 0; ++} ++ ++int fman_kg_write_cls_plan(struct fman_kg_regs *regs, ++ uint8_t grp_id, ++ uint8_t entries_mask, ++ uint8_t hwport_id, ++ struct fman_kg_cp_regs *cls_plan_regs) ++{ ++ struct fman_kg_cp_regs *kgcpe_regs; ++ uint32_t tmp_reg; ++ int i, err; ++ ++ /* Check group index is valid and the group isn't empty */ ++ if (grp_id >= FM_KG_CLS_PLAN_GRPS_NUM) ++ return -EINVAL; ++ ++ /* Write indirect classification plan registers */ ++ kgcpe_regs = (struct fman_kg_cp_regs *)&(regs->fmkg_indirect[0]); ++ ++ for (i = 0; i < FM_KG_NUM_CLS_PLAN_ENTR; i++) { ++ iowrite32be(cls_plan_regs->kgcpe[i], &kgcpe_regs->kgcpe[i]); ++ } ++ ++ tmp_reg = build_ar_cls_plan(grp_id, entries_mask, hwport_id, TRUE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ return err; ++} ++ ++int fman_kg_write_bind_schemes(struct fman_kg_regs *regs, ++ uint8_t hwport_id, ++ uint32_t schemes) ++{ ++ struct fman_kg_pe_regs *kg_pe_regs; ++ uint32_t tmp_reg; ++ int err; ++ ++ kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]); ++ ++ iowrite32be(schemes, &kg_pe_regs->fmkg_pe_sp); ++ ++ tmp_reg = build_ar_bind_scheme(hwport_id, TRUE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ return err; ++} ++ ++int fman_kg_build_bind_cls_plans(uint8_t grp_base, ++ uint8_t grp_mask, ++ uint32_t *bind_cls_plans) ++{ ++ /* Check grp_base and grp_mask are 5-bits values */ ++ if ((grp_base & ~0x0000001F) || (grp_mask & !0x0000001F)) ++ return -EINVAL; ++ ++ *bind_cls_plans = (uint32_t) ((grp_mask << FMAN_KG_PE_CPP_MASK_SHIFT) | grp_base); ++ return 0; ++} ++ ++ ++int fman_kg_write_bind_cls_plans(struct fman_kg_regs *regs, ++ uint8_t hwport_id, ++ uint32_t bind_cls_plans) ++{ ++ struct fman_kg_pe_regs *kg_pe_regs; ++ uint32_t tmp_reg; ++ int err; ++ ++ kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]); ++ ++ iowrite32be(bind_cls_plans, &kg_pe_regs->fmkg_pe_cpp); ++ ++ tmp_reg = build_ar_bind_cls_plan(hwport_id, TRUE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ return err; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fman_prs.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fman_prs.c +new file mode 100644 +index 0000000..caa1d28 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Pcd/fman_prs.c +@@ -0,0 +1,124 @@ ++/* ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "fsl_fman_prs.h" ++ ++uint32_t fman_prs_get_err_event(struct fman_prs_regs *regs, uint32_t ev_mask) ++{ ++ return ioread32be(®s->fmpr_perr) & ev_mask; ++} ++ ++uint32_t fman_prs_get_err_ev_mask(struct fman_prs_regs *regs) ++{ ++ return ioread32be(®s->fmpr_perer); ++} ++ ++void fman_prs_ack_err_event(struct fman_prs_regs *regs, uint32_t event) ++{ ++ iowrite32be(event, ®s->fmpr_perr); ++} ++ ++uint32_t fman_prs_get_expt_event(struct fman_prs_regs *regs, uint32_t ev_mask) ++{ ++ return ioread32be(®s->fmpr_pevr) & ev_mask; ++} ++ ++uint32_t fman_prs_get_expt_ev_mask(struct fman_prs_regs *regs) ++{ ++ return ioread32be(®s->fmpr_pever); ++} ++ ++void fman_prs_ack_expt_event(struct fman_prs_regs *regs, uint32_t event) ++{ ++ iowrite32be(event, ®s->fmpr_pevr); ++} ++ ++void fman_prs_defconfig(struct fman_prs_cfg *cfg) ++{ ++ cfg->port_id_stat = 0; ++ cfg->max_prs_cyc_lim = DEFAULT_MAX_PRS_CYC_LIM; ++ cfg->prs_exceptions = 0x03000000; ++} ++ ++int fman_prs_init(struct fman_prs_regs *regs, struct fman_prs_cfg *cfg) ++{ ++ uint32_t tmp; ++ ++ iowrite32be(cfg->max_prs_cyc_lim, ®s->fmpr_rpclim); ++ iowrite32be((FM_PCD_PRS_SINGLE_ECC | FM_PCD_PRS_PORT_IDLE_STS), ++ ®s->fmpr_pevr); ++ ++ if (cfg->prs_exceptions & FM_PCD_EX_PRS_SINGLE_ECC) ++ iowrite32be(FM_PCD_PRS_SINGLE_ECC, ®s->fmpr_pever); ++ else ++ iowrite32be(0, ®s->fmpr_pever); ++ ++ iowrite32be(FM_PCD_PRS_DOUBLE_ECC, ®s->fmpr_perr); ++ ++ tmp = 0; ++ if (cfg->prs_exceptions & FM_PCD_EX_PRS_DOUBLE_ECC) ++ tmp |= FM_PCD_PRS_DOUBLE_ECC; ++ iowrite32be(tmp, ®s->fmpr_perer); ++ ++ iowrite32be(cfg->port_id_stat, ®s->fmpr_ppsc); ++ ++ return 0; ++} ++ ++void fman_prs_enable(struct fman_prs_regs *regs) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->fmpr_rpimac) | FM_PCD_PRS_RPIMAC_EN; ++ iowrite32be(tmp, ®s->fmpr_rpimac); ++} ++ ++void fman_prs_disable(struct fman_prs_regs *regs) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->fmpr_rpimac) & ~FM_PCD_PRS_RPIMAC_EN; ++ iowrite32be(tmp, ®s->fmpr_rpimac); ++} ++ ++void fman_prs_set_stst_port_msk(struct fman_prs_regs *regs, uint32_t pid_msk) ++{ ++ iowrite32be(pid_msk, ®s->fmpr_ppsc); ++} ++ ++void fman_prs_set_stst(struct fman_prs_regs *regs, bool enable) ++{ ++ if (enable) ++ iowrite32be(FM_PCD_PRS_PPSC_ALL_PORTS, ®s->fmpr_ppsc); ++ else ++ iowrite32be(0, ®s->fmpr_ppsc); ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Port/Makefile b/drivers/net/dpa/NetCommSw/Peripherals/FM/Port/Makefile +new file mode 100644 +index 0000000..9acf110 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Port/Makefile +@@ -0,0 +1,15 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/dpa/NetCommSw/Peripherals/FM/inc ++ ++EXTRA_CFLAGS += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-Pcd.o ++ ++fsl-ncsw-Pcd-objs := fm_port.o fm_port_im.o +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Port/fm_port.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/Port/fm_port.c +new file mode 100644 +index 0000000..b7cd2da +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Port/fm_port.c +@@ -0,0 +1,5725 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_port.c ++ ++ @Description FM driver routines implementation. ++*//***************************************************************************/ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "string_ext.h" ++#include "sprint_ext.h" ++#include "debug_ext.h" ++#include "fm_muram_ext.h" ++ ++#include "fm_port.h" ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++static t_Error CheckInitParameters(t_FmPort *p_FmPort) ++{ ++ t_FmPortDriverParam *p_Params = p_FmPort->p_FmPortDriverParam; ++ t_Error ans = E_OK; ++ uint32_t unusedMask; ++ ++ if (p_FmPort->imEn) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ if (p_FmPort->fifoDeqPipelineDepth > 2) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoDeqPipelineDepth for IM 10G can't be larger than 2")); ++ ++ if ((ans = FmPortImCheckInitParameters(p_FmPort)) != E_OK) ++ return ERROR_CODE(ans); ++ } ++ else ++ { ++ /****************************************/ ++ /* Rx only */ ++ /****************************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ /* external buffer pools */ ++ if (!p_Params->extBufPools.numOfPoolsUsed) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.numOfPoolsUsed=0. At least one buffer pool must be defined")); ++ ++ if (FmSpCheckBufPoolsParams(&p_Params->extBufPools, p_Params->p_BackupBmPools, &p_Params->bufPoolDepletion)!= E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ ++ /* Check that part of IC that needs copying is small enough to enter start margin */ ++ if (p_Params->intContext.size && (p_Params->intContext.size + p_Params->intContext.extBufOffset > p_Params->bufMargins.startMargins)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size is larger than start margins")); ++ ++ if (p_Params->liodnOffset & ~FM_LIODN_OFFSET_MASK) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1)); ++ ++#ifdef FM_NO_BACKUP_POOLS ++ if ((p_FmPort->fmRevInfo.majorRev != 4) && (p_FmPort->fmRevInfo.majorRev < 6)) ++ if (p_FmPort->p_FmPortDriverParam->p_BackupBmPools) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("BackupBmPools")); ++#endif /* FM_NO_BACKUP_POOLS */ ++ } ++ ++ /****************************************/ ++ /* Non Rx ports */ ++ /****************************************/ ++ else ++ { ++ if (p_Params->deqSubPortal >= FM_MAX_NUM_OF_SUB_PORTALS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" deqSubPortal has to be in the range of 0 - %d", FM_MAX_NUM_OF_SUB_PORTALS)); ++ ++ /* to protect HW internal-context from overwrite */ ++ if ((p_Params->intContext.size) && (p_Params->intContext.intContextOffset < MIN_TX_INT_OFFSET)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("non-Rx intContext.intContextOffset can't be smaller than %d", MIN_TX_INT_OFFSET)); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) || (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) ++ /* in O/H DEFAULT_notSupported indicates that it is not suppported and should not be checked */ ++ || (p_FmPort->fifoDeqPipelineDepth != DEFAULT_notSupported)) ++ { ++ /* Check that not larger than 8 */ ++ if ((!p_FmPort->fifoDeqPipelineDepth) ||( p_FmPort->fifoDeqPipelineDepth > MAX_FIFO_PIPELINE_DEPTH)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoDeqPipelineDepth can't be larger than %d", MAX_FIFO_PIPELINE_DEPTH)); ++ } ++ } ++ ++ /****************************************/ ++ /* Rx Or Offline Parsing */ ++ /****************************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ { ++ ++ if (!p_Params->dfltFqid) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dfltFqid must be between 1 and 2^24-1")); ++#if defined(FM_CAPWAP_SUPPORT) && defined(FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004) ++ if (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.manipExtraSpace % 16) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufferPrefixContent.manipExtraSpace has to be devidable by 16")); ++#endif /* defined(FM_CAPWAP_SUPPORT) && ... */ ++ } ++ ++ /****************************************/ ++ /* All ports */ ++ /****************************************/ ++ /* common BMI registers values */ ++ /* Check that Queue Id is not larger than 2^24, and is not 0 */ ++ if ((p_Params->errFqid & ~0x00FFFFFF) || !p_Params->errFqid) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("errFqid must be between 1 and 2^24-1")); ++ if (p_Params->dfltFqid & ~0x00FFFFFF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dfltFqid must be between 1 and 2^24-1")); ++ } ++ ++ /****************************************/ ++ /* Rx only */ ++ /****************************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ /* Check that divisible by 256 and not larger than 256 */ ++ if (p_Params->rxFifoPriElevationLevel % BMI_FIFO_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoPriElevationLevel has to be divisible by %d", BMI_FIFO_UNITS)); ++ if (!p_Params->rxFifoPriElevationLevel || (p_Params->rxFifoPriElevationLevel > BMI_MAX_FIFO_SIZE)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoPriElevationLevel has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE)); ++ if (p_Params->rxFifoThreshold % BMI_FIFO_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoThreshold has to be divisible by %d", BMI_FIFO_UNITS)); ++ if (!p_Params->rxFifoThreshold ||(p_Params->rxFifoThreshold > BMI_MAX_FIFO_SIZE)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoThreshold has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE)); ++ ++ /* Check that not larger than 16 */ ++ if (p_Params->cutBytesFromEnd > FRAME_END_DATA_SIZE) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cutBytesFromEnd can't be larger than %d", FRAME_END_DATA_SIZE)); ++ ++ if (FmSpCheckBufMargins(&p_Params->bufMargins)!= E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ ++ /* extra FIFO size (allowed only to Rx ports) */ ++ if (p_Params->setSizeOfFifo && (p_FmPort->fifoBufs.extra % BMI_FIFO_UNITS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoBufs.extra has to be divisible by %d", BMI_FIFO_UNITS)); ++ ++ if (p_Params->bufPoolDepletion.poolsGrpModeEnable && ++ !p_Params->bufPoolDepletion.numOfPools) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPools can not be 0 when poolsGrpModeEnable=TRUE")); ++#ifdef FM_CSI_CFED_LIMIT ++ if (p_FmPort->fmRevInfo.majorRev == 4) ++ { ++ /* Check that not larger than 16 */ ++ if (p_Params->cutBytesFromEnd + p_Params->cheksumLastBytesIgnore > FRAME_END_DATA_SIZE) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cheksumLastBytesIgnore + cutBytesFromEnd can't be larger than %d", FRAME_END_DATA_SIZE)); ++ } ++#endif /* FM_CSI_CFED_LIMIT */ ++ } ++ ++ /****************************************/ ++ /* Non Rx ports */ ++ /****************************************/ ++ /* extra FIFO size (allowed only to Rx ports) */ ++ else if (p_FmPort->fifoBufs.extra) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" No fifoBufs.extra for non Rx ports")); ++ ++ ++ /****************************************/ ++ /* Tx only */ ++ /****************************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G)) ++ { ++ /* Check that divisible by 256 and not larger than 256 */ ++ if (p_Params->txFifoMinFillLevel % BMI_FIFO_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoMinFillLevel has to be divisible by %d", BMI_FIFO_UNITS)); ++ if (p_Params->txFifoMinFillLevel > (BMI_MAX_FIFO_SIZE - 256)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoMinFillLevel has to be in the range of 0 - %d", BMI_MAX_FIFO_SIZE)); ++ if (p_Params->txFifoLowComfLevel % BMI_FIFO_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoLowComfLevel has to be divisible by %d", BMI_FIFO_UNITS)); ++ if (!p_Params->txFifoLowComfLevel || (p_Params->txFifoLowComfLevel > BMI_MAX_FIFO_SIZE)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoLowComfLevel has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE)); ++ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_TX) ++ if (p_FmPort->fifoDeqPipelineDepth > 2) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoDeqPipelineDepth for 1G can't be larger than 2")); ++ } ++ /****************************************/ ++ /* Non Tx Ports */ ++ /****************************************/ ++ /* If discard override was selected , no frames may be discarded. */ ++ else if (p_Params->frmDiscardOverride && p_Params->errorsToDiscard) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ++ ("errorsToDiscard is not empty, but frmDiscardOverride selected (all discarded frames to be enqueued to error queue).")); ++ ++ /****************************************/ ++ /* Rx and Offline parsing */ ++ /****************************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ unusedMask = BMI_STATUS_OP_MASK_UNUSED; ++ else ++ unusedMask = BMI_STATUS_RX_MASK_UNUSED; ++ ++ /* Check that no common bits with BMI_STATUS_MASK_UNUSED */ ++ if (p_Params->errorsToDiscard & unusedMask) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("errorsToDiscard contains undefined bits")); ++ } ++ ++ /****************************************/ ++ /* Offline Ports */ ++ /****************************************/ ++#ifdef FM_OP_OPEN_DMA_MIN_LIMIT ++ if ((p_FmPort->fmRevInfo.majorRev >= 6) && ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) && ++ p_Params->setNumOfOpenDmas && ++ (p_FmPort->openDmas.num < MIN_NUM_OF_OP_DMAS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Offline port, openDmas.num can't be smaller than %d", MIN_NUM_OF_OP_DMAS)); ++#endif /* FM_OP_OPEN_DMA_MIN_LIMIT */ ++ ++ /****************************************/ ++ /* Offline & HC Ports */ ++ /****************************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ++ { ++#ifndef FM_FRAME_END_PARAMS_FOR_OP ++ if ((p_FmPort->fmRevInfo.majorRev < 6) && ++ (p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore != DEFAULT_notSupported)) ++ /* this is an indication that user called config for this mode which is not supported in this integration */ ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("cheksumLastBytesIgnore is available for Rx & Tx ports only")); ++#endif /* !FM_FRAME_END_PARAMS_FOR_OP */ ++ ++#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP ++ if ((!((p_FmPort->fmRevInfo.majorRev == 4) || ++ (p_FmPort->fmRevInfo.majorRev >= 6))) && ++ (p_FmPort->fifoDeqPipelineDepth != DEFAULT_notSupported)) ++ /* this is an indication that user called config for this mode which is not supported in this integration */ ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("fifoDeqPipelineDepth is available for Tx ports only")); ++#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */ ++ } ++ /****************************************/ ++ /* All ports */ ++ /****************************************/ ++ ++ /* Check that not larger than 16 */ ++ if ((p_Params->cheksumLastBytesIgnore > FRAME_END_DATA_SIZE) && ((p_Params->cheksumLastBytesIgnore != DEFAULT_notSupported))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cheksumLastBytesIgnore can't be larger than %d", FRAME_END_DATA_SIZE)); ++ ++ if (FmSpCheckIntContextParams(&p_Params->intContext)!= E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ ++ /* common BMI registers values */ ++ if (p_Params->setNumOfTasks && ((!p_FmPort->tasks.num) || (p_FmPort->tasks.num > MAX_NUM_OF_TASKS))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("tasks.num can't be larger than %d", MAX_NUM_OF_TASKS)); ++ if (p_Params->setNumOfTasks && (p_FmPort->tasks.extra > MAX_NUM_OF_EXTRA_TASKS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("tasks.extra can't be larger than %d", MAX_NUM_OF_EXTRA_TASKS)); ++ if (p_Params->setNumOfOpenDmas && ((!p_FmPort->openDmas.num) || (p_FmPort->openDmas.num > MAX_NUM_OF_DMAS))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas.num can't be larger than %d", MAX_NUM_OF_DMAS)); ++ if (p_Params->setNumOfOpenDmas && (p_FmPort->openDmas.extra > MAX_NUM_OF_EXTRA_DMAS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas.extra can't be larger than %d", MAX_NUM_OF_EXTRA_DMAS)); ++ if (p_Params->setSizeOfFifo && (!p_FmPort->fifoBufs.num || (p_FmPort->fifoBufs.num > BMI_MAX_FIFO_SIZE))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoBufs.num has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE)); ++ if (p_Params->setSizeOfFifo && (p_FmPort->fifoBufs.num % BMI_FIFO_UNITS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoBufs.num has to be divisible by %d", BMI_FIFO_UNITS)); ++ ++#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if (p_FmPort->fmRevInfo.majorRev == 4) ++ if (p_FmPort->p_FmPortDriverParam->deqPrefetchOption != DEFAULT_notSupported) ++ /* this is an indication that user called config for this mode which is not supported in this integration */ ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("deqPrefetchOption")); ++#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ ++ return E_OK; ++} ++ ++static t_Error VerifySizeOfFifo(t_FmPort *p_FmPort) ++{ ++ uint32_t minFifoSizeRequired = 0; ++ ++ /*************************/ ++ /* TX PORTS */ ++ /*************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G)) ++ { ++ minFifoSizeRequired = (uint32_t)DIV_CEIL(p_FmPort->maxFrameLength, BMI_FIFO_UNITS); ++ if (p_FmPort->imEn) ++ minFifoSizeRequired += 3*BMI_FIFO_UNITS; ++ else ++ minFifoSizeRequired += (p_FmPort->fifoDeqPipelineDepth+3)*BMI_FIFO_UNITS; ++ ++ /* add some margin for back to back capability to improve performance ++ * allows the hardware to pipeline new frame dma while the previous ++ * frame not yet transmitted). */ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) ++ minFifoSizeRequired += 3*BMI_FIFO_UNITS; ++ else ++ minFifoSizeRequired += 2*BMI_FIFO_UNITS; ++ } ++ ++ /*************************/ ++ /* RX IM PORTS */ ++ /*************************/ ++ else if (((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) && ++ p_FmPort->imEn) ++ minFifoSizeRequired = (uint32_t)(DIV_CEIL(p_FmPort->maxFrameLength, BMI_FIFO_UNITS) + ++ (4*BMI_FIFO_UNITS)); ++ ++ /*************************/ ++ /* RX non-IM PORTS */ ++ /*************************/ ++ else if (((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) && ++ !p_FmPort->imEn) ++ { ++#ifdef FM_FIFO_ALLOCATION_ALG ++ if (p_FmPort->fmRevInfo.majorRev == 4) ++ { ++ if (p_FmPort->rxPoolsParams.numOfPools == 1) ++ minFifoSizeRequired = 8*BMI_FIFO_UNITS; ++ else ++ minFifoSizeRequired = (uint32_t)(DIV_CEIL(p_FmPort->rxPoolsParams.secondLargestBufSize, BMI_FIFO_UNITS) + ++ (7*BMI_FIFO_UNITS)); ++ } ++ else ++#endif /* FM_FIFO_ALLOCATION_ALG */ ++ minFifoSizeRequired = (uint32_t)(DIV_CEIL(p_FmPort->rxPoolsParams.largestBufSize, BMI_FIFO_UNITS) + ++ (7*BMI_FIFO_UNITS)); ++ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ minFifoSizeRequired += 12*BMI_FIFO_UNITS; ++ else ++ minFifoSizeRequired += 3*BMI_FIFO_UNITS; ++ } ++ ++ /* For O/H ports, check fifo size and update if necessary */ ++ else if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ++ minFifoSizeRequired = (uint32_t)((p_FmPort->tasks.num + 4)*BMI_FIFO_UNITS); ++ ++ /* for all ports - verify size */ ++ if (minFifoSizeRequired && (p_FmPort->fifoBufs.num < minFifoSizeRequired)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("User defined FIFO size should be enlarged to %d", ++ minFifoSizeRequired)); ++ ++ /* check if pool size is not too big */ ++ /* This is a definition problem in which if the fifo for the RX port ++ is lower than the largest pool size the hardware will allocate scatter gather ++ buffers even though the frame size can fit in a single buffer. */ ++ if (((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ && !p_FmPort->imEn) ++ { ++ if (p_FmPort->rxPoolsParams.largestBufSize > p_FmPort->fifoBufs.num) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("Frame larger than port Fifo size (%u) will be split to more "\ ++ "than a single buffer (S/G) even if shorter than largest buffer size (%u)", ++ p_FmPort->fifoBufs.num, p_FmPort->rxPoolsParams.largestBufSize)); ++ } ++ ++ return E_OK; ++} ++ ++static void FmPortDriverParamFree(t_FmPort *p_FmPort) ++{ ++ if (p_FmPort->p_FmPortDriverParam) ++ { ++ XX_Free(p_FmPort->p_FmPortDriverParam); ++ p_FmPort->p_FmPortDriverParam = NULL; ++ } ++} ++ ++static t_Error SetExtBufferPools(t_FmPort *p_FmPort) ++{ ++ t_FmExtPools *p_ExtBufPools = &p_FmPort->p_FmPortDriverParam->extBufPools; ++ t_FmBufPoolDepletion *p_BufPoolDepletion = &p_FmPort->p_FmPortDriverParam->bufPoolDepletion; ++ volatile uint32_t *p_ExtBufRegs; ++ volatile uint32_t *p_BufPoolDepletionReg; ++ bool rxPort; ++ uint8_t orderedArray[FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ uint16_t sizesArray[BM_MAX_NUM_OF_POOLS]; ++ uint8_t numOfPools; ++ int i=0, j=0; ++ uint32_t tmpReg, vector; ++ ++ memset(&orderedArray, 0, sizeof(uint8_t) * FM_PORT_MAX_NUM_OF_EXT_POOLS); ++ memset(&sizesArray, 0, sizeof(uint16_t) * BM_MAX_NUM_OF_POOLS); ++ memcpy(&p_FmPort->extBufPools, p_ExtBufPools, sizeof(t_FmExtPools)); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_ExtBufRegs = p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi; ++ p_BufPoolDepletionReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rmpd; ++ rxPort = TRUE; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_ExtBufRegs = p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oebmpi; ++ p_BufPoolDepletionReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ompd; ++ rxPort = FALSE; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for port type")); ++ } ++ ++ FmSpSetBufPoolsInAscOrderOfBufSizes(p_ExtBufPools, orderedArray, sizesArray); ++ ++ /* build the register value */ ++ for (i=0;inumOfPoolsUsed;i++) ++ { ++ tmpReg = BMI_EXT_BUF_POOL_VALID | BMI_EXT_BUF_POOL_EN_COUNTER; ++ tmpReg |= ((uint32_t)orderedArray[i] << BMI_EXT_BUF_POOL_ID_SHIFT); ++ tmpReg |= sizesArray[orderedArray[i]]; ++ /* functionality available only for some deriviatives (limited by config) */ ++ if (p_FmPort->p_FmPortDriverParam->p_BackupBmPools) ++ for (j=0;jp_FmPortDriverParam->p_BackupBmPools->numOfBackupPools;j++) ++ if (orderedArray[i] == p_FmPort->p_FmPortDriverParam->p_BackupBmPools->poolIds[j]) ++ { ++ tmpReg |= BMI_EXT_BUF_POOL_BACKUP; ++ break; ++ } ++ WRITE_UINT32(*(p_ExtBufRegs+i), tmpReg); ++ } ++ ++ if (p_FmPort->p_FmPortDriverParam->p_BackupBmPools) ++ XX_Free(p_FmPort->p_FmPortDriverParam->p_BackupBmPools); ++ ++ numOfPools = (uint8_t)(rxPort ? FM_PORT_MAX_NUM_OF_EXT_POOLS:FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS); ++ ++ /* clear unused pools */ ++ for (i=p_ExtBufPools->numOfPoolsUsed;irxPoolsParams.numOfPools = p_ExtBufPools->numOfPoolsUsed; ++ p_FmPort->rxPoolsParams.largestBufSize = sizesArray[orderedArray[p_ExtBufPools->numOfPoolsUsed-1]]; ++ p_FmPort->rxPoolsParams.secondLargestBufSize = sizesArray[orderedArray[p_ExtBufPools->numOfPoolsUsed-2]]; ++ ++ /* FMBM_RMPD reg. - pool depletion */ ++ tmpReg = 0; ++ if (p_BufPoolDepletion->poolsGrpModeEnable) ++ { ++ /* calculate vector for number of pools depletion */ ++ vector = 0; ++ for (i=0;ipoolsToConsider[i]) ++ { ++ for (j=0;jnumOfPoolsUsed;j++) ++ { ++ if (i == orderedArray[j]) ++ { ++ vector |= 0x80000000 >> j; ++ break; ++ } ++ } ++ } ++ } ++ /* configure num of pools and vector for number of pools mode */ ++ tmpReg |= (((uint32_t)p_BufPoolDepletion->numOfPools - 1) << BMI_POOL_DEP_NUM_OF_POOLS_SHIFT); ++ tmpReg |= vector; ++ } ++ ++ if (p_BufPoolDepletion->singlePoolModeEnable) ++ { ++ /* calculate vector for number of pools depletion */ ++ vector = 0; ++ for (i=0;ipoolsToConsiderForSingleMode[i]) ++ { ++ for (j=0;jnumOfPoolsUsed;j++) ++ { ++ if (i == orderedArray[j]) ++ { ++ vector |= 0x00000080 >> j; ++ break; ++ } ++ } ++ } ++ } ++ tmpReg |= vector; ++ } ++ ++#if (DPAA_VERSION >= 11) ++ /* fill QbbPEV */ ++ if (p_BufPoolDepletion->poolsGrpModeEnable || ++ p_BufPoolDepletion->singlePoolModeEnable) ++ { ++ vector = 0; ++ for (i=0; ipfcPrioritiesEn[i] == TRUE) ++ { ++ vector |= 0x00008000 >> i; ++ } ++ } ++ tmpReg |= vector; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ WRITE_UINT32(*p_BufPoolDepletionReg, tmpReg); ++ ++ return E_OK; ++} ++ ++static t_Error ClearPerfCnts(t_FmPort *p_FmPort) ++{ ++ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_QUEUE_UTIL, 0); ++ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL, 0); ++ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL, 0); ++ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL, 0); ++ return E_OK; ++} ++ ++static t_Error BmiRxPortInit(t_FmPort *p_FmPort) ++{ ++ t_FmPortRxBmiRegs *p_Regs = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs; ++ uint32_t tmpReg; ++ t_FmPortDriverParam *p_Params = p_FmPort->p_FmPortDriverParam; ++ uint32_t errorsToEnq = 0; ++ t_FmPortPerformanceCnt performanceContersParams; ++ t_Error err; ++ ++ /* check that port is not busy */ ++ if (GET_UINT32(p_Regs->fmbm_rcfg) & BMI_PORT_CFG_EN) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Port(%d,%d) is already enabled",p_FmPort->portType, p_FmPort->portId)); ++ ++ /* Set Config register */ ++ tmpReg = 0; ++ if (p_FmPort->imEn) ++ tmpReg |= BMI_PORT_CFG_IM; ++ /* No discard - all error frames go to error queue */ ++ else if (p_Params->frmDiscardOverride) ++ tmpReg |= BMI_PORT_CFG_FDOVR; ++ ++ WRITE_UINT32(p_Regs->fmbm_rcfg, tmpReg); ++ ++ /* Configure dma attributes */ ++ tmpReg = 0; ++ tmpReg |= (uint32_t)p_Params->dmaSwapData << BMI_DMA_ATTR_SWP_SHIFT; ++ tmpReg |= (uint32_t)p_Params->dmaIntContextCacheAttr << BMI_DMA_ATTR_IC_CACHE_SHIFT; ++ tmpReg |= (uint32_t)p_Params->dmaHeaderCacheAttr << BMI_DMA_ATTR_HDR_CACHE_SHIFT; ++ tmpReg |= (uint32_t)p_Params->dmaScatterGatherCacheAttr << BMI_DMA_ATTR_SG_CACHE_SHIFT; ++ if (p_Params->dmaWriteOptimize) ++ tmpReg |= BMI_DMA_ATTR_WRITE_OPTIMIZE; ++ ++ WRITE_UINT32(p_Regs->fmbm_rda, tmpReg); ++ ++ /* Configure Rx Fifo params */ ++ tmpReg = 0; ++ tmpReg |= ((p_Params->rxFifoPriElevationLevel/BMI_FIFO_UNITS - 1) << BMI_RX_FIFO_PRI_ELEVATION_SHIFT); ++ tmpReg |= ((p_Params->rxFifoThreshold/BMI_FIFO_UNITS - 1) << BMI_RX_FIFO_THRESHOLD_SHIFT); ++ ++ WRITE_UINT32(p_Regs->fmbm_rfp, tmpReg); ++ ++#ifdef FM_NO_RESTRICT_ON_ACCESS_RSRC ++ if (p_FmPort->fmRevInfo.majorRev < 6) ++ /* always allow access to the extra resources */ ++ WRITE_UINT32(p_Regs->fmbm_reth, BMI_RX_FIFO_THRESHOLD_BC); ++#endif /* FM_NO_RESTRICT_ON_ACCESS_RSRC */ ++ ++ /* frame end parameters */ ++ tmpReg = 0; ++ tmpReg |= ((uint32_t)p_Params->cheksumLastBytesIgnore << BMI_RX_FRAME_END_CS_IGNORE_SHIFT); ++ tmpReg |= ((uint32_t)p_Params->cutBytesFromEnd<< BMI_RX_FRAME_END_CUT_SHIFT); ++ ++ WRITE_UINT32(p_Regs->fmbm_rfed, tmpReg); ++ ++ /* IC parameters */ ++ tmpReg = 0; ++ tmpReg |= (((uint32_t)p_Params->intContext.extBufOffset/OFFSET_UNITS) << BMI_IC_TO_EXT_SHIFT); ++ tmpReg |= (((uint32_t)p_Params->intContext.intContextOffset/OFFSET_UNITS) << BMI_IC_FROM_INT_SHIFT); ++ tmpReg |= (((uint32_t)p_Params->intContext.size/OFFSET_UNITS) << BMI_IC_SIZE_SHIFT); ++ ++ WRITE_UINT32(p_Regs->fmbm_ricp, tmpReg); ++ ++ if (!p_FmPort->imEn) ++ { ++ /* Call the external Buffer routine which also checks fifo ++ size and updates it if necessary */ ++ /* define external buffer pools and pool depletion*/ ++ ++ /* check if the largest external buffer pool is large enough */ ++ if ((p_Params->bufMargins.startMargins + ++ MIN_EXT_BUF_SIZE + ++ p_Params->bufMargins.endMargins) > p_FmPort->rxPoolsParams.largestBufSize) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("bufMargins.startMargins (%d) + minimum buf size (64) + " ++ "bufMargins.endMargins (%d) is larger than maximum external buffer size (%d)", ++ p_Params->bufMargins.startMargins, ++ p_Params->bufMargins.endMargins, ++ p_FmPort->rxPoolsParams.largestBufSize)); ++ ++ /* buffer margins */ ++ tmpReg = 0; ++ tmpReg |= (((uint32_t)p_Params->bufMargins.startMargins) << BMI_EXT_BUF_MARG_START_SHIFT); ++ tmpReg |= (((uint32_t)p_Params->bufMargins.endMargins) << BMI_EXT_BUF_MARG_END_SHIFT); ++#if (DPAA_VERSION >= 11) ++ if (p_Params->noScatherGather) ++ tmpReg |= BMI_SG_DISABLE; ++#endif ++ WRITE_UINT32(p_Regs->fmbm_rebm, tmpReg); ++ } ++ ++ if (p_FmPort->internalBufferOffset) ++ { ++ tmpReg = (uint32_t)((p_FmPort->internalBufferOffset%OFFSET_UNITS) ? ++ (p_FmPort->internalBufferOffset/OFFSET_UNITS + 1) : ++ (p_FmPort->internalBufferOffset/OFFSET_UNITS)); ++ p_FmPort->internalBufferOffset = (uint8_t)(tmpReg * OFFSET_UNITS); ++ WRITE_UINT32(p_Regs->fmbm_rim, tmpReg << BMI_IM_FOF_SHIFT); ++ } ++ ++ /* NIA */ ++ if (p_FmPort->imEn) ++ WRITE_UINT32(p_Regs->fmbm_rfne, NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_RX); ++ else ++ { ++ tmpReg = 0; ++ if (p_Params->forwardReuseIntContext) ++ tmpReg |= BMI_PORT_RFNE_FRWD_RPD; ++ /* L3/L4 checksum verify is enabled by default. */ ++ /*tmpReg |= BMI_PORT_RFNE_FRWD_DCL4C;*/ ++ WRITE_UINT32(p_Regs->fmbm_rfne, tmpReg | (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); ++ } ++ WRITE_UINT32(p_Regs->fmbm_rfene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR); ++ ++ /* command attribute */ ++ tmpReg = BMI_CMD_RX_MR_DEF; ++ if (!p_FmPort->imEn) ++ { ++ tmpReg |= BMI_CMD_ATTR_ORDER; ++ if (p_Params->syncReq) ++ tmpReg |= BMI_CMD_ATTR_SYNC; ++ tmpReg |= ((uint32_t)p_Params->color << BMI_CMD_ATTR_COLOR_SHIFT); ++ } ++ ++ WRITE_UINT32(p_Regs->fmbm_rfca, tmpReg); ++ ++ /* default queues */ ++ if (!p_FmPort->imEn) ++ { ++ WRITE_UINT32(p_Regs->fmbm_rfqid, p_Params->dfltFqid); ++ WRITE_UINT32(p_Regs->fmbm_refqid, p_Params->errFqid); ++ } ++ ++ /* set counters */ ++ WRITE_UINT32(p_Regs->fmbm_rstc, BMI_COUNTERS_EN); ++ ++ performanceContersParams.taskCompVal = (uint8_t)p_FmPort->tasks.num; ++ performanceContersParams.queueCompVal = 1; ++ performanceContersParams.dmaCompVal =(uint8_t) p_FmPort->openDmas.num; ++ performanceContersParams.fifoCompVal = p_FmPort->fifoBufs.num; ++ if ((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &performanceContersParams)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ WRITE_UINT32(p_Regs->fmbm_rpc, BMI_COUNTERS_EN); ++ ++ /* error/status mask - check that if discard OV is set, no ++ discard is required for specific errors.*/ ++ WRITE_UINT32(p_Regs->fmbm_rfsdm, p_Params->errorsToDiscard); ++ ++ errorsToEnq = (RX_ERRS_TO_ENQ & ~p_Params->errorsToDiscard); ++ WRITE_UINT32(p_Regs->fmbm_rfsem, errorsToEnq); ++ ++ return E_OK; ++} ++ ++static t_Error BmiTxPortInit(t_FmPort *p_FmPort) ++{ ++ t_FmPortTxBmiRegs *p_Regs = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs; ++ uint32_t tmpReg; ++ t_FmPortDriverParam *p_Params = p_FmPort->p_FmPortDriverParam; ++ /*uint32_t rateCountUnit;*/ ++ t_FmPortPerformanceCnt performanceContersParams; ++ ++ /* check that port is not busy */ ++ if (GET_UINT32(p_Regs->fmbm_tcfg) & BMI_PORT_CFG_EN) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port is already enabled")); ++ ++ tmpReg = 0; ++ if (p_FmPort->imEn) ++ tmpReg |= BMI_PORT_CFG_IM; ++ ++ WRITE_UINT32(p_Regs->fmbm_tcfg, tmpReg); ++ ++ /* Configure dma attributes */ ++ tmpReg = 0; ++ tmpReg |= (uint32_t)p_Params->dmaSwapData << BMI_DMA_ATTR_SWP_SHIFT; ++ tmpReg |= (uint32_t)p_Params->dmaIntContextCacheAttr << BMI_DMA_ATTR_IC_CACHE_SHIFT; ++ tmpReg |= (uint32_t)p_Params->dmaHeaderCacheAttr << BMI_DMA_ATTR_HDR_CACHE_SHIFT; ++ tmpReg |= (uint32_t)p_Params->dmaScatterGatherCacheAttr << BMI_DMA_ATTR_SG_CACHE_SHIFT; ++ ++ WRITE_UINT32(p_Regs->fmbm_tda, tmpReg); ++ ++ /* Configure Tx Fifo params */ ++ tmpReg = 0; ++ tmpReg |= ((p_Params->txFifoMinFillLevel/BMI_FIFO_UNITS) << BMI_TX_FIFO_MIN_FILL_SHIFT); ++ tmpReg |= (((uint32_t)p_FmPort->fifoDeqPipelineDepth - 1) << BMI_FIFO_PIPELINE_DEPTH_SHIFT); ++ tmpReg |= ((p_Params->txFifoLowComfLevel/BMI_FIFO_UNITS - 1) << BMI_TX_LOW_COMF_SHIFT); ++ ++ WRITE_UINT32(p_Regs->fmbm_tfp, tmpReg); ++ ++ /* frame end parameters */ ++ tmpReg = 0; ++ tmpReg |= ((uint32_t)p_Params->cheksumLastBytesIgnore << BMI_FRAME_END_CS_IGNORE_SHIFT); ++ ++ WRITE_UINT32(p_Regs->fmbm_tfed, tmpReg); ++ ++ if (!p_FmPort->imEn) ++ { ++ /* IC parameters */ ++ tmpReg = 0; ++ tmpReg |= (((uint32_t)p_Params->intContext.extBufOffset/OFFSET_UNITS) << BMI_IC_TO_EXT_SHIFT); ++ tmpReg |= (((uint32_t)p_Params->intContext.intContextOffset/OFFSET_UNITS) << BMI_IC_FROM_INT_SHIFT); ++ tmpReg |= (((uint32_t)p_Params->intContext.size/OFFSET_UNITS) << BMI_IC_SIZE_SHIFT); ++ ++ WRITE_UINT32(p_Regs->fmbm_ticp, tmpReg); ++ } ++ ++ /* NIA */ ++ if (p_FmPort->imEn) ++ { ++ WRITE_UINT32(p_Regs->fmbm_tfdne, NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_TX); ++ WRITE_UINT32(p_Regs->fmbm_tfene, NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_TX); ++#if (DPAA_VERSION >= 11) ++/* TODO - what should be the TFNE for FMan v3 IM? */ ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ else ++ { ++ WRITE_UINT32(p_Regs->fmbm_tfdne, NIA_ENG_QMI_DEQ); ++ WRITE_UINT32(p_Regs->fmbm_tfene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR); ++#if (DPAA_VERSION >= 11) ++ WRITE_UINT32(p_Regs->fmbm_tfne, ++ (!p_Params->dfltFqid ? ++ BMI_EBD_EN | NIA_BMI_AC_FETCH_ALL_FRAME : ++ NIA_BMI_AC_FETCH_ALL_FRAME)); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* The line bellow is a trick so the FM will not release the buffer ++ to BM nor will try to enq the frame to QM */ ++ if (!p_Params->dfltFqid && p_Params->dontReleaseBuf) ++ { ++ /* override fmbm_tcfqid 0 with a false non-0 value. This will force FM to ++ * act according to tfene. Otherwise, if fmbm_tcfqid is 0 the FM will release ++ * buffers to BM regardless of fmbm_tfene ++ */ ++ WRITE_UINT32(p_Regs->fmbm_tcfqid, 0xFFFFFF); ++ WRITE_UINT32(p_Regs->fmbm_tfene, NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE); ++#if (DPAA_VERSION >= 11) ++ WRITE_UINT32(p_Regs->fmbm_tfne, ++ (GET_UINT32(p_Regs->fmbm_tfne) & ~BMI_EBD_EN)); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ } ++ ++ /* command attribute */ ++ tmpReg = BMI_CMD_TX_MR_DEF; ++ if (p_FmPort->imEn) ++ tmpReg |= BMI_CMD_MR_DEAS; ++ else ++ { ++ tmpReg |= BMI_CMD_ATTR_ORDER; ++ tmpReg |= ((uint32_t)p_Params->color << BMI_CMD_ATTR_COLOR_SHIFT); ++ } ++ WRITE_UINT32(p_Regs->fmbm_tfca, tmpReg); ++ ++ /* default queues */ ++ if (!p_FmPort->imEn) ++ { ++ if (p_Params->dfltFqid || !p_Params->dontReleaseBuf) ++ WRITE_UINT32(p_Regs->fmbm_tcfqid, p_Params->dfltFqid); ++ WRITE_UINT32(p_Regs->fmbm_tfeqid, p_Params->errFqid); ++ } ++ ++ /* statistics & performance counters */ ++ WRITE_UINT32(p_Regs->fmbm_tstc, BMI_COUNTERS_EN); ++ ++ performanceContersParams.taskCompVal = (uint8_t)p_FmPort->tasks.num; ++ performanceContersParams.queueCompVal = 1; ++ performanceContersParams.dmaCompVal = (uint8_t)p_FmPort->openDmas.num; ++ performanceContersParams.fifoCompVal = p_FmPort->fifoBufs.num; ++ FM_PORT_SetPerformanceCountersParams(p_FmPort, &performanceContersParams); ++ ++ WRITE_UINT32(p_Regs->fmbm_tpc, BMI_COUNTERS_EN); ++ ++ ++ return E_OK; ++} ++ ++static t_Error BmiOhPortInit(t_FmPort *p_FmPort) ++{ ++ t_FmPortOhBmiRegs *p_Regs = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs; ++ uint32_t tmpReg, errorsToEnq = 0; ++ t_FmPortDriverParam *p_Params = p_FmPort->p_FmPortDriverParam; ++ t_FmPortPerformanceCnt performanceContersParams; ++ ++ /* check that port is not busy */ ++ if (GET_UINT32(p_Regs->fmbm_ocfg) & BMI_PORT_CFG_EN) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port is already enabled")); ++ ++ /* Configure dma attributes */ ++ tmpReg = 0; ++ tmpReg |= (uint32_t)p_Params->dmaSwapData << BMI_DMA_ATTR_SWP_SHIFT; ++ tmpReg |= (uint32_t)p_Params->dmaIntContextCacheAttr << BMI_DMA_ATTR_IC_CACHE_SHIFT; ++ tmpReg |= (uint32_t)p_Params->dmaHeaderCacheAttr << BMI_DMA_ATTR_HDR_CACHE_SHIFT; ++ tmpReg |= (uint32_t)p_Params->dmaScatterGatherCacheAttr << BMI_DMA_ATTR_SG_CACHE_SHIFT; ++ if (p_Params->dmaWriteOptimize) ++ tmpReg |= BMI_DMA_ATTR_WRITE_OPTIMIZE; ++ ++ WRITE_UINT32(p_Regs->fmbm_oda, tmpReg); ++ ++ /* IC parameters */ ++ tmpReg = 0; ++ tmpReg |= (((uint32_t)p_Params->intContext.extBufOffset/OFFSET_UNITS) << BMI_IC_TO_EXT_SHIFT); ++ tmpReg |= (((uint32_t)p_Params->intContext.intContextOffset/OFFSET_UNITS) << BMI_IC_FROM_INT_SHIFT); ++ tmpReg |= (((uint32_t)p_Params->intContext.size/OFFSET_UNITS) << BMI_IC_SIZE_SHIFT); ++ ++ WRITE_UINT32(p_Regs->fmbm_oicp, tmpReg); ++ ++ /* NIA */ ++ WRITE_UINT32(p_Regs->fmbm_ofdne, NIA_ENG_QMI_DEQ); ++ ++ if (p_FmPort->portType==e_FM_PORT_TYPE_OH_HOST_COMMAND) ++ WRITE_UINT32(p_Regs->fmbm_ofene, NIA_ENG_QMI_ENQ); ++ else ++ WRITE_UINT32(p_Regs->fmbm_ofene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR); ++ ++ /* command attribute */ ++ if (p_FmPort->portType==e_FM_PORT_TYPE_OH_HOST_COMMAND) ++ tmpReg = BMI_CMD_MR_DEAS | BMI_CMD_MR_MA; ++ else ++ tmpReg = BMI_CMD_ATTR_ORDER | BMI_CMD_MR_DEAS | BMI_CMD_MR_MA; ++ ++ if (p_Params->syncReq) ++ tmpReg |= BMI_CMD_ATTR_SYNC; ++ tmpReg |= ((uint32_t)p_Params->color << BMI_CMD_ATTR_COLOR_SHIFT); ++ WRITE_UINT32(p_Regs->fmbm_ofca, tmpReg); ++ ++ /* No discard - all error frames go to error queue */ ++ if (p_Params->frmDiscardOverride) ++ tmpReg = BMI_PORT_CFG_FDOVR; ++ else ++ tmpReg = 0; ++ WRITE_UINT32(p_Regs->fmbm_ocfg, tmpReg); ++ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ { ++ WRITE_UINT32(p_Regs->fmbm_ofsdm, p_Params->errorsToDiscard); ++ ++ errorsToEnq = (OP_ERRS_TO_ENQ & ~p_Params->errorsToDiscard); ++ WRITE_UINT32(p_Regs->fmbm_ofsem, errorsToEnq); ++ ++ /* NIA */ ++ WRITE_UINT32(p_Regs->fmbm_ofne, (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); ++ ++#ifndef FM_NO_OP_OBSERVED_POOLS ++ /* Call the external Buffer routine which also checks fifo ++ size and updates it if necessary */ ++ if ((p_FmPort->fmRevInfo.majorRev == 4) && ++ p_Params->enBufPoolDepletion) ++ { ++ /* define external buffer pools */ ++ t_Error err = SetExtBufferPools(p_FmPort); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++#endif /* FM_NO_OP_OBSERVED_POOLS */ ++ } ++ else ++ /* NIA */ ++ WRITE_UINT32(p_Regs->fmbm_ofne, NIA_ENG_FM_CTL | NIA_FM_CTL_AC_HC); ++ ++ /* default queues */ ++ WRITE_UINT32(p_Regs->fmbm_ofqid, p_Params->dfltFqid); ++ WRITE_UINT32(p_Regs->fmbm_oefqid, p_Params->errFqid); ++ ++ if (p_FmPort->internalBufferOffset) ++ { ++ tmpReg = (uint32_t)((p_FmPort->internalBufferOffset % OFFSET_UNITS) ? ++ (p_FmPort->internalBufferOffset/OFFSET_UNITS + 1): ++ (p_FmPort->internalBufferOffset/OFFSET_UNITS)); ++ p_FmPort->internalBufferOffset = (uint8_t)(tmpReg * OFFSET_UNITS); ++ WRITE_UINT32(p_Regs->fmbm_oim, tmpReg << BMI_IM_FOF_SHIFT); ++ } ++ /* statistics & performance counters */ ++ WRITE_UINT32(p_Regs->fmbm_ostc, BMI_COUNTERS_EN); ++ ++ performanceContersParams.taskCompVal = (uint8_t)p_FmPort->tasks.num; ++ performanceContersParams.queueCompVal = 0; ++ performanceContersParams.dmaCompVal = (uint8_t)p_FmPort->openDmas.num; ++ performanceContersParams.fifoCompVal = p_FmPort->fifoBufs.num; ++ FM_PORT_SetPerformanceCountersParams(p_FmPort, &performanceContersParams); ++ ++ WRITE_UINT32(p_Regs->fmbm_opc, BMI_COUNTERS_EN); ++#ifdef FM_DEQ_PIPELINE_PARAMS_FOR_OP ++ if ((p_FmPort->fmRevInfo.majorRev == 4) || ++ (p_FmPort->fmRevInfo.majorRev >= 6)) ++ { ++ tmpReg = (((uint32_t)p_FmPort->fifoDeqPipelineDepth - 1) << BMI_FIFO_PIPELINE_DEPTH_SHIFT); ++ WRITE_UINT32(p_Regs->fmbm_ofp, tmpReg); ++ } ++#endif /* FM_DEQ_PIPELINE_PARAMS_FOR_OP */ ++ ++#ifdef FM_FRAME_END_PARAMS_FOR_OP ++ if (p_FmPort->fmRevInfo.majorRev >= 6) ++ { ++ /* frame end parameters */ ++ tmpReg = 0; ++ tmpReg |= ((uint32_t)p_Params->cheksumLastBytesIgnore << BMI_FRAME_END_CS_IGNORE_SHIFT); ++ ++ WRITE_UINT32(p_Regs->fmbm_ofed, tmpReg); ++ } ++#endif /* FM_FRAME_END_PARAMS_FOR_OP */ ++ ++ return E_OK; ++} ++ ++static t_Error QmiInit(t_FmPort *p_FmPort) ++{ ++ t_FmPortDriverParam *p_Params = NULL; ++ uint32_t tmpReg; ++ ++ p_Params = p_FmPort->p_FmPortDriverParam; ++ ++ /* check that port is not busy */ ++ if (((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX)) && ++ (GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) & QMI_PORT_CFG_EN)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port is already enabled")); ++ ++ /* enable & clear counters */ ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc, QMI_PORT_CFG_EN_COUNTERS); ++ ++ /* The following is done for non-Rx ports only */ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ { ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_TX)) ++ { ++ /* define dequeue NIA */ ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, NIA_ENG_BMI | NIA_BMI_AC_TX); ++ /* define enqueue NIA */ ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE); ++ } ++ else /* for HC & OP */ ++ { ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, NIA_ENG_BMI | NIA_BMI_AC_FETCH); ++ /* define enqueue NIA */ ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_RELEASE); ++ } ++ ++ /* configure dequeue */ ++ tmpReg = 0; ++ if (p_Params->deqHighPriority) ++ tmpReg |= QMI_DEQ_CFG_PRI; ++ ++ switch (p_Params->deqType) ++ { ++ case (e_FM_PORT_DEQ_TYPE1): ++ tmpReg |= QMI_DEQ_CFG_TYPE1; ++ break; ++ case (e_FM_PORT_DEQ_TYPE2): ++ tmpReg |= QMI_DEQ_CFG_TYPE2; ++ break; ++ case (e_FM_PORT_DEQ_TYPE3): ++ tmpReg |= QMI_DEQ_CFG_TYPE3; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid dequeue type")); ++ } ++ ++#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if (p_FmPort->fmRevInfo.majorRev != 4) ++#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ switch (p_Params->deqPrefetchOption) ++ { ++ case (e_FM_PORT_DEQ_NO_PREFETCH): ++ /* Do nothing - QMI_DEQ_CFG_PREFETCH_WAITING_TNUM | QMI_DEQ_CFG_PREFETCH_1_FRAME = 0 */ ++ break; ++ case (e_FM_PORT_DEQ_PARTIAL_PREFETCH): ++ tmpReg |= QMI_DEQ_CFG_PREFETCH_WAITING_TNUM | QMI_DEQ_CFG_PREFETCH_3_FRAMES; ++ break; ++ case (e_FM_PORT_DEQ_FULL_PREFETCH): ++ tmpReg |= QMI_DEQ_CFG_PREFETCH_NO_TNUM | QMI_DEQ_CFG_PREFETCH_3_FRAMES; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid dequeue prefetch option")); ++ } ++ ++ tmpReg |= p_Params->deqByteCnt; ++ tmpReg |= (uint32_t)p_Params->deqSubPortal << QMI_DEQ_CFG_SUBPORTAL_SHIFT; ++ ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndc, tmpReg); ++ } ++ else /* rx port */ ++ /* define enqueue NIA */ ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_RELEASE); ++ ++ return E_OK; ++} ++ ++static t_Error BmiRxPortCheckAndGetCounterPtr(t_FmPort *p_FmPort, e_FmPortCounters counter, volatile uint32_t **p_Ptr) ++{ ++ t_FmPortRxBmiRegs *p_BmiRegs = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs; ++ ++ /* check that counters are enabled */ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_CYCLE): ++ case (e_FM_PORT_COUNTERS_TASK_UTIL): ++ case (e_FM_PORT_COUNTERS_QUEUE_UTIL): ++ case (e_FM_PORT_COUNTERS_DMA_UTIL): ++ case (e_FM_PORT_COUNTERS_FIFO_UTIL): ++ case (e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION): ++ /* performance counters - may be read when disabled */ ++ break; ++ case (e_FM_PORT_COUNTERS_FRAME): ++ case (e_FM_PORT_COUNTERS_DISCARD_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_BAD_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_LARGE_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_FILTER_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR): ++ case (e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD): ++ case (e_FM_PORT_COUNTERS_DEALLOC_BUF): ++ case (e_FM_PORT_COUNTERS_PREPARE_TO_ENQUEUE_COUNTER): ++ if (!(GET_UINT32(p_BmiRegs->fmbm_rstc) & BMI_COUNTERS_EN)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports")); ++ } ++ ++ /* Set counter */ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_CYCLE): ++ *p_Ptr = &p_BmiRegs->fmbm_rccn; ++ break; ++ case (e_FM_PORT_COUNTERS_TASK_UTIL): ++ *p_Ptr = &p_BmiRegs->fmbm_rtuc; ++ break; ++ case (e_FM_PORT_COUNTERS_QUEUE_UTIL): ++ *p_Ptr = &p_BmiRegs->fmbm_rrquc; ++ break; ++ case (e_FM_PORT_COUNTERS_DMA_UTIL): ++ *p_Ptr = &p_BmiRegs->fmbm_rduc; ++ break; ++ case (e_FM_PORT_COUNTERS_FIFO_UTIL): ++ *p_Ptr = &p_BmiRegs->fmbm_rfuc; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION): ++ *p_Ptr = &p_BmiRegs->fmbm_rpac; ++ break; ++ case (e_FM_PORT_COUNTERS_FRAME): ++ *p_Ptr = &p_BmiRegs->fmbm_rfrc; ++ break; ++ case (e_FM_PORT_COUNTERS_DISCARD_FRAME): ++ *p_Ptr = &p_BmiRegs->fmbm_rfcd; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_BAD_FRAME): ++ *p_Ptr = &p_BmiRegs->fmbm_rfbc; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_LARGE_FRAME): ++ *p_Ptr = &p_BmiRegs->fmbm_rlfc; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_FILTER_FRAME): ++ *p_Ptr = &p_BmiRegs->fmbm_rffc; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR): ++ *p_Ptr = &p_BmiRegs->fmbm_rfldec; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD): ++ *p_Ptr = &p_BmiRegs->fmbm_rodc; ++ break; ++ case (e_FM_PORT_COUNTERS_DEALLOC_BUF): ++ *p_Ptr = &p_BmiRegs->fmbm_rbdc; ++ break; ++ case (e_FM_PORT_COUNTERS_PREPARE_TO_ENQUEUE_COUNTER): ++ *p_Ptr = &p_BmiRegs->fmbm_rpec; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports")); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error BmiTxPortCheckAndGetCounterPtr(t_FmPort *p_FmPort, e_FmPortCounters counter, volatile uint32_t **p_Ptr) ++{ ++ t_FmPortTxBmiRegs *p_BmiRegs = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs; ++ ++ /* check that counters are enabled */ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_CYCLE): ++ case (e_FM_PORT_COUNTERS_TASK_UTIL): ++ case (e_FM_PORT_COUNTERS_QUEUE_UTIL): ++ case (e_FM_PORT_COUNTERS_DMA_UTIL): ++ case (e_FM_PORT_COUNTERS_FIFO_UTIL): ++ /* performance counters - may be read when disabled */ ++ break; ++ case (e_FM_PORT_COUNTERS_FRAME): ++ case (e_FM_PORT_COUNTERS_DISCARD_FRAME): ++ case (e_FM_PORT_COUNTERS_LENGTH_ERR): ++ case (e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT): ++ case (e_FM_PORT_COUNTERS_DEALLOC_BUF): ++ if (!(GET_UINT32(p_BmiRegs->fmbm_tstc) & BMI_COUNTERS_EN)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Tx ports")); ++ } ++ ++ /* Set counter */ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_CYCLE): ++ *p_Ptr = &p_BmiRegs->fmbm_tccn; ++ break; ++ case (e_FM_PORT_COUNTERS_TASK_UTIL): ++ *p_Ptr = &p_BmiRegs->fmbm_ttuc; ++ break; ++ case (e_FM_PORT_COUNTERS_QUEUE_UTIL): ++ *p_Ptr = &p_BmiRegs->fmbm_ttcquc; ++ break; ++ case (e_FM_PORT_COUNTERS_DMA_UTIL): ++ *p_Ptr = &p_BmiRegs->fmbm_tduc; ++ break; ++ case (e_FM_PORT_COUNTERS_FIFO_UTIL): ++ *p_Ptr = &p_BmiRegs->fmbm_tfuc; ++ break; ++ case (e_FM_PORT_COUNTERS_FRAME): ++ *p_Ptr = &p_BmiRegs->fmbm_tfrc; ++ break; ++ case (e_FM_PORT_COUNTERS_DISCARD_FRAME): ++ *p_Ptr = &p_BmiRegs->fmbm_tfdc; ++ break; ++ case (e_FM_PORT_COUNTERS_LENGTH_ERR): ++ *p_Ptr = &p_BmiRegs->fmbm_tfledc; ++ break; ++ case (e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT): ++ *p_Ptr = &p_BmiRegs->fmbm_tfufdc; ++ break; ++ case (e_FM_PORT_COUNTERS_DEALLOC_BUF): ++ *p_Ptr = &p_BmiRegs->fmbm_tbdc; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Tx ports")); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error BmiOhPortCheckAndGetCounterPtr(t_FmPort *p_FmPort, e_FmPortCounters counter, volatile uint32_t **p_Ptr) ++{ ++ t_FmPortOhBmiRegs *p_BmiRegs = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs; ++ ++ /* check that counters are enabled */ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_CYCLE): ++ case (e_FM_PORT_COUNTERS_TASK_UTIL): ++ case (e_FM_PORT_COUNTERS_DMA_UTIL): ++ case (e_FM_PORT_COUNTERS_FIFO_UTIL): ++ /* performance counters - may be read when disabled */ ++ break; ++ case (e_FM_PORT_COUNTERS_FRAME): ++ case (e_FM_PORT_COUNTERS_DISCARD_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR): ++ case (e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD): ++ case (e_FM_PORT_COUNTERS_WRED_DISCARD): ++ case (e_FM_PORT_COUNTERS_LENGTH_ERR): ++ case (e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT): ++ case (e_FM_PORT_COUNTERS_DEALLOC_BUF): ++ if (!(GET_UINT32(p_BmiRegs->fmbm_ostc) & BMI_COUNTERS_EN)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ break; ++ case (e_FM_PORT_COUNTERS_RX_FILTER_FRAME): /* only valid for offline parsing */ ++ /* only driver uses host command port, so ASSERT rather than RETURN_ERROR */ ++ ASSERT_COND(p_FmPort->portType != e_FM_PORT_TYPE_OH_HOST_COMMAND); ++ if (!(GET_UINT32(p_BmiRegs->fmbm_ostc) & BMI_COUNTERS_EN)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter(%d) is not available for O/H ports", counter)); ++ } ++ ++ /* Set counter */ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_CYCLE): ++ *p_Ptr = &p_BmiRegs->fmbm_occn; ++ break; ++ case (e_FM_PORT_COUNTERS_TASK_UTIL): ++ *p_Ptr = &p_BmiRegs->fmbm_otuc; ++ break; ++ case (e_FM_PORT_COUNTERS_DMA_UTIL): ++ *p_Ptr = &p_BmiRegs->fmbm_oduc; ++ break; ++ case (e_FM_PORT_COUNTERS_FIFO_UTIL): ++ *p_Ptr = &p_BmiRegs->fmbm_ofuc; ++ break; ++ case (e_FM_PORT_COUNTERS_FRAME): ++ *p_Ptr = &p_BmiRegs->fmbm_ofrc; ++ break; ++ case (e_FM_PORT_COUNTERS_DISCARD_FRAME): ++ *p_Ptr = &p_BmiRegs->fmbm_ofdc; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_FILTER_FRAME): ++ *p_Ptr = &p_BmiRegs->fmbm_offc; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR): ++ *p_Ptr = &p_BmiRegs->fmbm_ofldec; ++ break; ++ case (e_FM_PORT_COUNTERS_WRED_DISCARD): ++ *p_Ptr = &p_BmiRegs->fmbm_ofwdc; ++ break; ++ case (e_FM_PORT_COUNTERS_LENGTH_ERR): ++ *p_Ptr = &p_BmiRegs->fmbm_ofledc; ++ break; ++ case (e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT): ++ *p_Ptr = &p_BmiRegs->fmbm_ofufdc; ++ break; ++ case (e_FM_PORT_COUNTERS_DEALLOC_BUF): ++ *p_Ptr = &p_BmiRegs->fmbm_obdc; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD): ++ *p_Ptr = &p_BmiRegs->fmbm_oodc; ++ break; ++ case (e_FM_PORT_COUNTERS_PREPARE_TO_ENQUEUE_COUNTER): ++ *p_Ptr = &p_BmiRegs->fmbm_opec; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for O/H ports")); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error AdditionalPrsParams(t_FmPort *p_FmPort, t_FmPcdPrsAdditionalHdrParams *p_HdrParams, uint32_t *p_SoftSeqAttachReg) ++{ ++ uint8_t hdrNum, Ipv4HdrNum; ++ u_FmPcdHdrPrsOpts *p_prsOpts; ++ uint32_t tmpReg = *p_SoftSeqAttachReg, tmpPrsOffset; ++ ++ if (IS_PRIVATE_HEADER(p_HdrParams->hdr) || IS_SPECIAL_HEADER(p_HdrParams->hdr)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("No additional parameters for private or special headers.")); ++ ++ if (p_HdrParams->errDisable) ++ tmpReg |= PRS_HDR_ERROR_DIS; ++ ++ /* Set parser options */ ++ if (p_HdrParams->usePrsOpts) ++ { ++ p_prsOpts = &p_HdrParams->prsOpts; ++ switch (p_HdrParams->hdr) ++ { ++ case (HEADER_TYPE_MPLS): ++ if (p_prsOpts->mplsPrsOptions.labelInterpretationEnable) ++ tmpReg |= PRS_HDR_MPLS_LBL_INTER_EN; ++ GET_PRS_HDR_NUM(hdrNum, p_prsOpts->mplsPrsOptions.nextParse); ++ if (hdrNum == ILLEGAL_HDR_NUM) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ GET_PRS_HDR_NUM(Ipv4HdrNum, HEADER_TYPE_IPv4); ++ if (hdrNum < Ipv4HdrNum) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("Header must be equal or higher than IPv4")); ++ tmpReg |= ((uint32_t)hdrNum * PRS_HDR_ENTRY_SIZE) << PRS_HDR_MPLS_NEXT_HDR_SHIFT; ++ break; ++ case (HEADER_TYPE_PPPoE): ++ if (p_prsOpts->pppoePrsOptions.enableMTUCheck) ++ tmpReg |= PRS_HDR_PPPOE_MTU_CHECK_EN; ++ break; ++ case (HEADER_TYPE_IPv6): ++ if (p_prsOpts->ipv6PrsOptions.routingHdrEnable) ++ tmpReg |= PRS_HDR_IPV6_ROUTE_HDR_EN; ++ break; ++ case (HEADER_TYPE_TCP): ++ if (p_prsOpts->tcpPrsOptions.padIgnoreChecksum) ++ tmpReg |= PRS_HDR_TCP_PAD_REMOVAL; ++ else ++ tmpReg &= ~PRS_HDR_TCP_PAD_REMOVAL; ++ break; ++ case (HEADER_TYPE_UDP): ++ if (p_prsOpts->udpPrsOptions.padIgnoreChecksum) ++ tmpReg |= PRS_HDR_UDP_PAD_REMOVAL; ++ else ++ tmpReg &= ~PRS_HDR_UDP_PAD_REMOVAL; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid header")); ++ } ++ } ++ ++ /* set software parsing (address is devided in 2 since parser uses 2 byte access. */ ++ if (p_HdrParams->swPrsEnable) ++ { ++ tmpPrsOffset = FmPcdGetSwPrsOffset(p_FmPort->h_FmPcd, p_HdrParams->hdr, p_HdrParams->indexPerHdr); ++ if (tmpPrsOffset == ILLEGAL_BASE) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ tmpReg |= (PRS_HDR_SW_PRS_EN | tmpPrsOffset); ++ } ++ *p_SoftSeqAttachReg = tmpReg; ++ ++ return E_OK; ++} ++ ++static uint32_t GetPortSchemeBindParams(t_Handle h_FmPort, t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint32_t walking1Mask = 0x80000000, tmp; ++ uint8_t idx = 0; ++ ++ p_SchemeBind->netEnvId = p_FmPort->netEnvId; ++ p_SchemeBind->hardwarePortId = p_FmPort->hardwarePortId; ++ p_SchemeBind->useClsPlan = p_FmPort->useClsPlan; ++ p_SchemeBind->numOfSchemes = 0; ++ tmp = p_FmPort->schemesPerPortVector; ++ if (tmp) ++ { ++ while (tmp) ++ { ++ if (tmp & walking1Mask) ++ { ++ p_SchemeBind->schemesIds[p_SchemeBind->numOfSchemes] = idx; ++ p_SchemeBind->numOfSchemes++; ++ tmp &= ~walking1Mask; ++ } ++ walking1Mask >>= 1; ++ idx++; ++ } ++ } ++ ++ return tmp; ++} ++ ++static t_Error SetPcd(t_FmPort *p_FmPort, t_FmPortPcdParams *p_PcdParams) ++{ ++ t_Error err = E_OK; ++ uint32_t tmpReg; ++ volatile uint32_t *p_BmiNia=NULL; ++ volatile uint32_t *p_BmiPrsNia=NULL; ++ volatile uint32_t *p_BmiPrsStartOffset=NULL; ++ volatile uint32_t *p_BmiInitPrsResult=NULL; ++ volatile uint32_t *p_BmiCcBase=NULL; ++ uint8_t hdrNum, L3HdrNum, greHdrNum; ++ int i; ++ bool isEmptyClsPlanGrp; ++ uint32_t tmpHxs[FM_PCD_PRS_NUM_OF_HDRS]; ++ uint16_t absoluteProfileId; ++ uint8_t physicalSchemeId; ++ uint32_t ccTreePhysOffset; ++ t_FmPcdKgInterModuleBindPortToSchemes schemeBind; ++ ++ ASSERT_COND(p_FmPort); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only")); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only")); ++ ++ p_FmPort->netEnvId = FmPcdGetNetEnvId(p_PcdParams->h_NetEnv); ++ ++ p_FmPort->pcdEngines = 0; ++ ++ /* initialize p_FmPort->pcdEngines field in port's structure */ ++ switch (p_PcdParams->pcdSupport) ++ { ++ case (e_FM_PORT_PCD_SUPPORT_NONE): ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("No PCD configuration required if e_FM_PORT_PCD_SUPPORT_NONE selected")); ++ case (e_FM_PORT_PCD_SUPPORT_PRS_ONLY): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PLCR_ONLY): ++ p_FmPort->pcdEngines |= FM_PCD_PLCR; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_PLCR; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_KG; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ p_FmPort->pcdEngines |= FM_PCD_KG; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_KG; ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ p_FmPort->pcdEngines |= FM_PCD_PLCR; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC_AND_PLCR): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ p_FmPort->pcdEngines |= FM_PCD_PLCR; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_KG; ++ p_FmPort->pcdEngines |= FM_PCD_PLCR; ++ break; ++#ifdef FM_CAPWAP_SUPPORT ++ case (e_FM_PORT_PCD_SUPPORT_CC_ONLY): ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_CC_AND_KG): ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ p_FmPort->pcdEngines |= FM_PCD_KG; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR): ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ p_FmPort->pcdEngines |= FM_PCD_KG; ++ p_FmPort->pcdEngines |= FM_PCD_PLCR; ++ break; ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid pcdSupport")); ++ } ++ ++ if ((p_FmPort->pcdEngines & FM_PCD_PRS) && ++ (p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams > FM_PCD_PRS_NUM_OF_HDRS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Port parser numOfHdrsWithAdditionalParams may not exceed %d", FM_PCD_PRS_NUM_OF_HDRS)); ++ ++ /* check that parameters exist for each and only each defined engine */ ++ if ((!!(p_FmPort->pcdEngines & FM_PCD_PRS) != !!p_PcdParams->p_PrsParams) || ++ (!!(p_FmPort->pcdEngines & FM_PCD_KG) != !!p_PcdParams->p_KgParams) || ++ (!!(p_FmPort->pcdEngines & FM_PCD_CC) != !!p_PcdParams->p_CcParams)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PCD initialization structure is not consistent with pcdSupport")); ++ ++ /* get PCD registers pointers */ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne; ++ p_BmiPrsNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne; ++ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpso; ++ p_BmiInitPrsResult = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rprai[0]; ++ p_BmiCcBase = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rccb; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne; ++ p_BmiPrsNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne; ++ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opso; ++ p_BmiInitPrsResult = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oprai[0]; ++ p_BmiCcBase = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_occb; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ /* set PCD port parameter */ ++ if (p_FmPort->pcdEngines & FM_PCD_CC) ++ { ++ err = FmPcdCcBindTree(p_FmPort->h_FmPcd, ++ p_PcdParams, ++ p_PcdParams->p_CcParams->h_CcTree, ++ &ccTreePhysOffset, ++ p_FmPort); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ WRITE_UINT32(*p_BmiCcBase, ccTreePhysOffset); ++ p_FmPort->ccTreeId = p_PcdParams->p_CcParams->h_CcTree; ++ } ++ ++ if (p_FmPort->pcdEngines & FM_PCD_KG) ++ { ++ if (p_PcdParams->p_KgParams->numOfSchemes == 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For ports using Keygen, at least one scheme must be bound. ")); ++ ++ err = FmPcdKgSetOrBindToClsPlanGrp(p_FmPort->h_FmPcd, ++ p_FmPort->hardwarePortId, ++ p_FmPort->netEnvId, ++ p_FmPort->optArray, ++ &p_FmPort->clsPlanGrpId, ++ &isEmptyClsPlanGrp); ++ if (err) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FmPcdKgSetOrBindToClsPlanGrp failed. ")); ++ ++ p_FmPort->useClsPlan = !isEmptyClsPlanGrp; ++ ++ schemeBind.netEnvId = p_FmPort->netEnvId; ++ schemeBind.hardwarePortId = p_FmPort->hardwarePortId; ++ schemeBind.numOfSchemes = p_PcdParams->p_KgParams->numOfSchemes; ++ schemeBind.useClsPlan = p_FmPort->useClsPlan; ++ ++ /* for each scheme */ ++ for (i=0; ip_KgParams->numOfSchemes; i++) ++ { ++ ASSERT_COND(p_PcdParams->p_KgParams->h_Schemes[i]); ++ physicalSchemeId = FmPcdKgGetSchemeId(p_PcdParams->p_KgParams->h_Schemes[i]); ++ schemeBind.schemesIds[i] = physicalSchemeId; ++ /* build vector */ ++ p_FmPort->schemesPerPortVector |= 1 << (31 - (uint32_t)physicalSchemeId); ++#if (DPAA_VERSION >= 11) ++ /*because of the state that VSPE is defined per port - all PCD path should be according to this requirement ++ if !VSPE - in port, for relevant scheme VSPE can not be set*/ ++ if (!p_FmPort->vspe && FmPcdKgGetVspe((p_PcdParams->p_KgParams->h_Schemes[i]))) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("VSPE is not at port level")); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ err = FmPcdKgBindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /***************************/ ++ /* configure NIA after BMI */ ++ /***************************/ ++ /* rfne may contain FDCS bits, so first we read them. */ ++ p_FmPort->savedBmiNia = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK; ++ ++ /* If policer is used directly after BMI or PRS */ ++ if ((p_FmPort->pcdEngines & FM_PCD_PLCR) && ++ ((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PLCR_ONLY) || ++ (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR))) ++ { ++ if (!p_PcdParams->p_PlcrParams->h_Profile) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Profile should be initialized")); ++ ++ absoluteProfileId = (uint16_t)FmPcdPlcrProfileGetAbsoluteId(p_PcdParams->p_PlcrParams->h_Profile); ++ ++ if (!FmPcdPlcrIsProfileValid(p_FmPort->h_FmPcd, absoluteProfileId)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Private port profile not valid.")); ++ ++ tmpReg = (uint32_t)(absoluteProfileId | NIA_PLCR_ABSOLUTE); ++ ++ if (p_FmPort->pcdEngines & FM_PCD_PRS) /* e_FM_PCD_SUPPORT_PRS_AND_PLCR */ ++ /* update BMI HPNIA */ ++ WRITE_UINT32(*p_BmiPrsNia, (uint32_t)(NIA_ENG_PLCR | tmpReg)); ++ else /* e_FM_PCD_SUPPORT_PLCR_ONLY */ ++ /* update BMI NIA */ ++ p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_PLCR); ++ } ++ ++#ifdef FM_CAPWAP_SUPPORT ++ /* if CC is used directly after BMI */ ++ if ((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_ONLY) || ++ (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_AND_KG) || ++ (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR)) ++ { ++ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("e_FM_PORT_PCD_SUPPORT_CC_xx available for offline parsing ports only")); ++ p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC); ++ /* check that prs start offset == RIM[FOF] */ ++ } ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++ if (p_FmPort->pcdEngines & FM_PCD_PRS) ++ { ++ ASSERT_COND(p_PcdParams->p_PrsParams); ++ /* if PRS is used it is always first */ ++ GET_PRS_HDR_NUM(hdrNum, p_PcdParams->p_PrsParams->firstPrsHdr); ++ if (hdrNum == ILLEGAL_HDR_NUM) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unsupported header.")); ++ p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_PRS | (uint32_t)(hdrNum)); ++ /* set after parser NIA */ ++ tmpReg = 0; ++ switch (p_PcdParams->pcdSupport) ++ { ++ case (e_FM_PORT_PCD_SUPPORT_PRS_ONLY): ++ WRITE_UINT32(*p_BmiPrsNia, GET_NIA_BMI_AC_ENQ_FRAME(p_FmPort->h_FmPcd)); ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC): ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR): ++ tmpReg = NIA_KG_CC_EN; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG): ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR): ++ if (p_PcdParams->p_KgParams->directScheme) ++ { ++ physicalSchemeId = FmPcdKgGetSchemeId(p_PcdParams->p_KgParams->h_DirectScheme); ++ /* check that this scheme was bound to this port */ ++ for (i=0 ; ip_KgParams->numOfSchemes; i++) ++ if (p_PcdParams->p_KgParams->h_DirectScheme == p_PcdParams->p_KgParams->h_Schemes[i]) ++ break; ++ if (i == p_PcdParams->p_KgParams->numOfSchemes) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Direct scheme is not one of the port selected schemes.")); ++ tmpReg |= (uint32_t)(NIA_KG_DIRECT | physicalSchemeId); ++ } ++ WRITE_UINT32(*p_BmiPrsNia, NIA_ENG_KG | tmpReg); ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC): ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC_AND_PLCR): ++ WRITE_UINT32(*p_BmiPrsNia, (uint32_t)(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC)); ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR): ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid PCD support")); ++ } ++ ++ /* set start parsing offset */ ++ WRITE_UINT32(*p_BmiPrsStartOffset, p_PcdParams->p_PrsParams->parsingOffset); ++ ++ /************************************/ ++ /* Parser port parameters */ ++ /************************************/ ++ /* stop before configuring */ ++ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, PRS_CAC_STOP); ++ /* wait for parser to be in idle state */ ++ while (GET_UINT32(p_FmPort->p_FmPortPrsRegs->pcac) & PRS_CAC_ACTIVE) ; ++ ++ /* set soft seq attachment register */ ++ memset(tmpHxs, 0, FM_PCD_PRS_NUM_OF_HDRS*sizeof(uint32_t)); ++ ++ /* set protocol options */ ++ for (i=0;p_FmPort->optArray[i];i++) ++ switch (p_FmPort->optArray[i]) ++ { ++ case (ETH_BROADCAST): ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_ETH) ++ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_ETH_BC_SHIFT; ++ break; ++ case (ETH_MULTICAST): ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_ETH) ++ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_ETH_MC_SHIFT; ++ break; ++ case (VLAN_STACKED): ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_VLAN) ++ tmpHxs[hdrNum] |= (i+1)<< PRS_HDR_VLAN_STACKED_SHIFT; ++ break; ++ case (MPLS_STACKED): ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_MPLS) ++ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_MPLS_STACKED_SHIFT; ++ break; ++ case (IPV4_BROADCAST_1): ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4) ++ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_1_BC_SHIFT; ++ break; ++ case (IPV4_MULTICAST_1): ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4) ++ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_1_MC_SHIFT; ++ break; ++ case (IPV4_UNICAST_2): ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4) ++ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_2_UC_SHIFT; ++ break; ++ case (IPV4_MULTICAST_BROADCAST_2): ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4) ++ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_2_MC_BC_SHIFT; ++ break; ++ case (IPV6_MULTICAST_1): ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6) ++ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV6_1_MC_SHIFT; ++ break; ++ case (IPV6_UNICAST_2): ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6) ++ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV6_2_UC_SHIFT; ++ break; ++ case (IPV6_MULTICAST_2): ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6) ++ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV6_2_MC_SHIFT; ++ break; ++ } ++ ++ if (FmPcdNetEnvIsHdrExist(p_FmPort->h_FmPcd, ++ p_FmPort->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP)) ++ { ++ p_PcdParams->p_PrsParams->additionalParams ++ [p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams].hdr = HEADER_TYPE_UDP; ++ p_PcdParams->p_PrsParams->additionalParams ++ [p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams].swPrsEnable = TRUE; ++ p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams++; ++ } ++ ++ /* set MPLS default next header - HW reset workaround */ ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_MPLS) ++ tmpHxs[hdrNum] |= PRS_HDR_MPLS_LBL_INTER_EN; ++ GET_PRS_HDR_NUM(L3HdrNum, HEADER_TYPE_USER_DEFINED_L3); ++ tmpHxs[hdrNum] |= (uint32_t)L3HdrNum << PRS_HDR_MPLS_NEXT_HDR_SHIFT; ++ ++ /* for GRE, disable errors */ ++ GET_PRS_HDR_NUM(greHdrNum, HEADER_TYPE_GRE); ++ tmpHxs[greHdrNum] |= PRS_HDR_ERROR_DIS; ++ ++ /* For UDP remove PAD from L4 checksum calculation */ ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_UDP); ++ tmpHxs[hdrNum] |= PRS_HDR_UDP_PAD_REMOVAL; ++ /* For TCP remove PAD from L4 checksum calculation */ ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_TCP); ++ tmpHxs[hdrNum] |= PRS_HDR_TCP_PAD_REMOVAL; ++ ++ /* config additional params for specific headers */ ++ for (i=0; ip_PrsParams->numOfHdrsWithAdditionalParams; i++) ++ { ++ GET_PRS_HDR_NUM(hdrNum, p_PcdParams->p_PrsParams->additionalParams[i].hdr); ++ if (hdrNum== ILLEGAL_HDR_NUM) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ if (hdrNum==NO_HDR_NUM) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Private headers may not use additional parameters")); ++ ++ err = AdditionalPrsParams(p_FmPort, &p_PcdParams->p_PrsParams->additionalParams[i], &tmpHxs[hdrNum]); ++ if (err) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ } ++ ++ /* Check if ip-reassembly port - need to update NIAs */ ++ if (p_FmPort->h_IpReassemblyManip) ++ { ++ /* link to sw parser code for IP Frag - only if no other code is applied. */ ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4) ++ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN)) ++ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | IP_FRAG_SW_PATCH_IPv4_LABEL); ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6) ++ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN)) ++ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | IP_FRAG_SW_PATCH_IPv6_LABEL); ++ } ++ ++ if (FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd) && ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ { ++ /* link to sw parser code for IP Frag - only if no other code is applied. */ ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6) ++ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN)) ++ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | IP_FRAG_SW_PATCH_IPv6_LABEL); ++ } ++ ++#ifdef FM_CAPWAP_SUPPORT ++ if (FmPcdNetEnvIsHdrExist(p_FmPort->h_FmPcd, ++ p_FmPort->netEnvId, HEADER_TYPE_UDP_LITE)) ++ { ++ /* link to sw parser code for udp lite - only if no other code is applied. */ ++ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_USER_DEFINED_L4) ++ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN)) ++ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | UDP_LITE_SW_PATCH_LABEL); ++ } ++#endif /* FM_CAPWAP_SUPPORT */ ++ for (i=0 ; ip_FmPortPrsRegs->hdrs[i].lcv, ++ FmPcdGetLcv(p_FmPort->h_FmPcd, p_FmPort->netEnvId, (uint8_t)i)); ++ /* set HXS register according to default+Additional params+protocol options */ ++ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->hdrs[i].softSeqAttach, tmpHxs[i]); ++ } ++ ++ /* set tpid. */ ++ tmpReg = PRS_TPID_DFLT; ++ if (p_PcdParams->p_PrsParams->setVlanTpid1) ++ { ++ tmpReg &= PRS_TPID2_MASK; ++ tmpReg |= (uint32_t)p_PcdParams->p_PrsParams->vlanTpid1 << PRS_PCTPID_SHIFT; ++ } ++ if (p_PcdParams->p_PrsParams->setVlanTpid2) ++ { ++ tmpReg &= PRS_TPID1_MASK; ++ tmpReg |= (uint32_t)p_PcdParams->p_PrsParams->vlanTpid2; ++ } ++ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pctpid, tmpReg); ++ ++ /* enable parser */ ++ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, 0); ++ ++ if (p_PcdParams->p_PrsParams->prsResultPrivateInfo) ++ p_FmPort->privateInfo = p_PcdParams->p_PrsParams->prsResultPrivateInfo; ++ ++ } /* end parser */ ++ else ++ p_FmPort->privateInfo = 0; ++ ++ WRITE_UINT32(*p_BmiPrsStartOffset, GET_UINT32(*p_BmiPrsStartOffset) + p_FmPort->internalBufferOffset); ++ ++ /* set initial parser result - used for all engines */ ++ for (i=0;iprivateInfo << BMI_PR_PORTID_SHIFT) ++ | BMI_PRS_RESULT_HIGH)); ++ else ++ { ++ if (i< FM_PORT_PRS_RESULT_NUM_OF_WORDS/2) ++ WRITE_UINT32(*(p_BmiInitPrsResult+i), BMI_PRS_RESULT_HIGH); ++ else ++ WRITE_UINT32(*(p_BmiInitPrsResult+i), BMI_PRS_RESULT_LOW); ++ } ++ } ++ ++ return E_OK; ++} ++ ++static t_Error DeletePcd(t_FmPort *p_FmPort) ++{ ++ t_Error err = E_OK; ++ volatile uint32_t *p_BmiNia=NULL; ++ volatile uint32_t *p_BmiPrsStartOffset = NULL; ++ ++ ASSERT_COND(p_FmPort); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only")); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only")); ++ ++ if (!p_FmPort->pcdEngines) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("called for non PCD port")); ++ ++ /* get PCD registers pointers */ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne; ++ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpso; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne; ++ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opso; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ if ((GET_UINT32(*p_BmiNia) & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)) != (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("port has to be detached previousely")); ++ ++ /* "cut" PCD out of the port's flow - go to BMI */ ++ /* WRITE_UINT32(*p_BmiNia, (p_FmPort->savedBmiNia & BMI_RFNE_FDCS_MASK) | (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); */ ++ ++ if (p_FmPort->pcdEngines | FM_PCD_PRS) ++ { ++ WRITE_UINT32(*p_BmiPrsStartOffset, 0); ++ ++ /* stop parser */ ++ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, PRS_CAC_STOP); ++ /* wait for parser to be in idle state */ ++ while (GET_UINT32(p_FmPort->p_FmPortPrsRegs->pcac) & PRS_CAC_ACTIVE) ; ++ } ++ ++ if (p_FmPort->pcdEngines & FM_PCD_KG) ++ { ++ t_FmPcdKgInterModuleBindPortToSchemes schemeBind; ++ ++ /* unbind all schemes */ ++ p_FmPort->schemesPerPortVector = GetPortSchemeBindParams(p_FmPort, &schemeBind); ++ ++ err = FmPcdKgUnbindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ err = FmPcdKgDeleteOrUnbindPortToClsPlanGrp(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, p_FmPort->clsPlanGrpId); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ p_FmPort->useClsPlan = FALSE; ++ } ++ ++ if (p_FmPort->pcdEngines & FM_PCD_CC) ++ { ++ /* unbind - we need to get the treeId too */ ++ err = FmPcdCcUnbindTree(p_FmPort->h_FmPcd, p_FmPort->ccTreeId); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ p_FmPort->pcdEngines = 0; ++ ++ return E_OK; ++} ++ ++static t_Error AttachPCD(t_FmPort *p_FmPort) ++{ ++ volatile uint32_t *p_BmiNia=NULL; ++ ++ ASSERT_COND(p_FmPort); ++ ++ /* get PCD registers pointers */ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only")); ++ } ++ ++ if (p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY) ++ if (FmSetNumOfRiscsPerPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId, 1, p_FmPort->orFmanCtrl)!= E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ /* check that current NIA is BMI to BMI */ ++ if ((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) != (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("may be called only for ports in BMI-to-BMI state.")); ++ ++ WRITE_UINT32(*p_BmiNia, p_FmPort->savedBmiNia); ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_PNEN) ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, p_FmPort->savedQmiPnen); ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_PNDN) ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, p_FmPort->savedNonRxQmiRegsPndn); ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_FENE) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofene, p_FmPort->savedBmiFene); ++ else ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfene, p_FmPort->savedBmiFene); ++ } ++ if (p_FmPort->requiredAction & UPDATE_NIA_FPNE) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne, p_FmPort->savedBmiFpne); ++ else ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, p_FmPort->savedBmiFpne); ++ } ++ if (p_FmPort->requiredAction & UPDATE_NIA_CMNE) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocmne, p_FmPort->savedBmiCmne); ++ else ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcmne, p_FmPort->savedBmiCmne); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error DetachPCD(t_FmPort *p_FmPort) ++{ ++ volatile uint32_t *p_BmiNia=NULL; ++ ++ ASSERT_COND(p_FmPort); ++ ++ /* get PCD registers pointers */ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only")); ++ } ++ ++ WRITE_UINT32(*p_BmiNia, (p_FmPort->savedBmiNia & BMI_RFNE_FDCS_MASK) | (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_PNEN) ++ { ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE); ++ break; ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_RX): ++ case (e_FM_PORT_TYPE_RX_10G): ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_RELEASE); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Can not reach this stage")); ++ } ++ } ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_PNDN) ++ { ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, NIA_ENG_BMI | NIA_BMI_AC_TX); ++ break; ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, NIA_ENG_BMI | NIA_BMI_AC_FETCH); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Can not reach this stage")); ++ } ++ } ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_FENE) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR); ++ else ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR); ++ } ++ ++ if (p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY) ++ if (FmSetNumOfRiscsPerPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId, 2, p_FmPort->orFmanCtrl)!= E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ p_FmPort->requiredAction = 0; ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++void FmPortSetMacsecLcv(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_BmiCfgReg = NULL; ++ uint32_t macsecEn = BMI_PORT_CFG_EN_MACSEC; ++ uint32_t lcv, walking1Mask = 0x80000000; ++ uint8_t cnt = 0; ++ ++ SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_OPERATION, ("The routine is relevant for Rx ports only")); ++ return; ++ } ++ ++ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcfg; ++ /* get LCV for MACSEC */ ++ if ((p_FmPort->h_FmPcd) && ((lcv = FmPcdGetMacsecLcv(p_FmPort->h_FmPcd, p_FmPort->netEnvId))!= 0)) ++ { ++ while (!(lcv & walking1Mask)) ++ { ++ cnt++; ++ walking1Mask >>= 1; ++ } ++ ++ macsecEn |= (uint32_t)cnt << BMI_PORT_CFG_MS_SEL_SHIFT; ++ } ++ ++ WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) | macsecEn); ++} ++ ++void FmPortSetMacsecCmd(t_Handle h_FmPort, uint8_t dfltSci) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_BmiCfgReg = NULL; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_OPERATION, ("The routine is relevant for Tx ports only")); ++ return; ++ } ++ ++ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfca; ++ tmpReg = GET_UINT32(*p_BmiCfgReg) & ~BMI_CMD_ATTR_MACCMD_MASK; ++ tmpReg |= BMI_CMD_ATTR_MACCMD_SECURED; ++ tmpReg |= (((uint32_t)dfltSci << BMI_CMD_ATTR_MACCMD_SC_SHIFT) & BMI_CMD_ATTR_MACCMD_SC_MASK); ++ ++ WRITE_UINT32(*p_BmiCfgReg, tmpReg); ++} ++ ++uint8_t FmPortGetNetEnvId(t_Handle h_FmPort) ++{ ++ return ((t_FmPort*)h_FmPort)->netEnvId; ++} ++ ++uint8_t FmPortGetHardwarePortId(t_Handle h_FmPort) ++{ ++ return ((t_FmPort*)h_FmPort)->hardwarePortId; ++} ++ ++uint32_t FmPortGetPcdEngines(t_Handle h_FmPort) ++{ ++ return ((t_FmPort*)h_FmPort)->pcdEngines; ++} ++ ++#if (DPAA_VERSION >= 11) ++t_Error FmPortSetGprFunc(t_Handle h_FmPort, e_FmPortGprFuncType gprFunc, void **p_Value) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint32_t muramPageOffset; ++ ++ ASSERT_COND(p_FmPort); ++ ASSERT_COND(p_Value); ++ ++ if (p_FmPort->gprFunc != e_FM_PORT_GPR_EMPTY) ++ { ++ if (p_FmPort->gprFunc != gprFunc) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("gpr was assigned with different func")); ++ } ++ else ++ { ++ switch (gprFunc) ++ { ++ case (e_FM_PORT_GPR_MURAM_PAGE): ++ p_FmPort->p_MuramPage = FM_MURAM_AllocMem(p_FmPort->h_FmMuram, ++ 256, ++ 8); ++ if (!p_FmPort->p_MuramPage) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for page")); ++ ++ IOMemSet32(p_FmPort->p_MuramPage, 0, 256); ++ muramPageOffset = (uint32_t)(XX_VirtToPhys(p_FmPort->p_MuramPage) - ++ p_FmPort->fmMuramPhysBaseAddr); ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr, muramPageOffset); ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ogpr, muramPageOffset); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ p_FmPort->gprFunc = gprFunc; ++ } ++ ++ switch (p_FmPort->gprFunc) ++ { ++ case (e_FM_PORT_GPR_MURAM_PAGE): ++ *p_Value = p_FmPort->p_MuramPage; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ return E_OK; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++t_Error FmPortGetSetCcParams(t_Handle h_FmPort, t_FmPortGetSetCcParams *p_CcParams) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ int tmpInt; ++ volatile uint32_t *p_BmiPrsStartOffset = NULL; ++ ++ /* this function called from Cc for pass and receive parameters port params between CC and PORT*/ ++ ++ if ((p_CcParams->getCcParams.type & OFFSET_OF_PR) && ++ (p_FmPort->bufferOffsets.prsResultOffset != ILLEGAL_BASE)) ++ { ++ p_CcParams->getCcParams.prOffset = (uint8_t)p_FmPort->bufferOffsets.prsResultOffset; ++ p_CcParams->getCcParams.type &= ~OFFSET_OF_PR; ++ } ++ if (p_CcParams->getCcParams.type & HW_PORT_ID) ++ { ++ p_CcParams->getCcParams.hardwarePortId = (uint8_t)p_FmPort->hardwarePortId; ++ p_CcParams->getCcParams.type &= ~HW_PORT_ID; ++ } ++ if ((p_CcParams->getCcParams.type & OFFSET_OF_DATA) && ++ (p_FmPort->bufferOffsets.dataOffset != ILLEGAL_BASE)) ++ { ++ p_CcParams->getCcParams.dataOffset = (uint16_t)p_FmPort->bufferOffsets.dataOffset; ++ p_CcParams->getCcParams.type &= ~OFFSET_OF_DATA; ++ } ++ if (p_CcParams->getCcParams.type & NUM_OF_TASKS) ++ { ++ p_CcParams->getCcParams.numOfTasks = (uint8_t)p_FmPort->tasks.num; ++ p_CcParams->getCcParams.type &= ~NUM_OF_TASKS; ++ } ++ if (p_CcParams->getCcParams.type & NUM_OF_EXTRA_TASKS) ++ { ++ p_CcParams->getCcParams.numOfExtraTasks = (uint8_t)p_FmPort->tasks.extra; ++ p_CcParams->getCcParams.type &= ~NUM_OF_EXTRA_TASKS; ++ } ++ if (p_CcParams->getCcParams.type & FM_REV) ++ { ++ p_CcParams->getCcParams.revInfo.majorRev = p_FmPort->fmRevInfo.majorRev; ++ p_CcParams->getCcParams.revInfo.minorRev = p_FmPort->fmRevInfo.minorRev; ++ p_CcParams->getCcParams.type &= ~FM_REV; ++ } ++ if (p_CcParams->getCcParams.type & GET_NIA_FPNE) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ p_CcParams->getCcParams.nia = GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne); ++ else ++ p_CcParams->getCcParams.nia = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne); ++ p_CcParams->getCcParams.type &= ~GET_NIA_FPNE; ++ } ++ if (p_CcParams->getCcParams.type & GET_NIA_PNDN) ++ { ++ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ p_CcParams->getCcParams.nia = GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn); ++ p_CcParams->getCcParams.type &= ~GET_NIA_PNDN; ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY) && ++ !(p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY)) ++ { ++ p_FmPort->requiredAction |= UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY; ++ p_FmPort->orFmanCtrl = p_CcParams->setCcParams.orFmanCtrl; ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_NIA_PNEN) && ++ !(p_FmPort->requiredAction & UPDATE_NIA_PNEN)) ++ { ++ p_FmPort->savedQmiPnen = p_CcParams->setCcParams.nia; ++ p_FmPort->requiredAction |= UPDATE_NIA_PNEN; ++ } ++ else if (p_CcParams->setCcParams.type & UPDATE_NIA_PNEN) ++ { ++ if (p_FmPort->savedQmiPnen != p_CcParams->setCcParams.nia) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PNEN was defined previously different")); ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_NIA_PNDN) && ++ !(p_FmPort->requiredAction & UPDATE_NIA_PNDN)) ++ { ++ p_FmPort->savedNonRxQmiRegsPndn = p_CcParams->setCcParams.nia; ++ p_FmPort->requiredAction |= UPDATE_NIA_PNDN; ++ } ++ else if (p_CcParams->setCcParams.type & UPDATE_NIA_PNDN) ++ { ++ if (p_FmPort->savedNonRxQmiRegsPndn != p_CcParams->setCcParams.nia) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PNDN was defined previously different")); ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_NIA_FENE) && ++ (p_CcParams->setCcParams.overwrite || ++ !(p_FmPort->requiredAction & UPDATE_NIA_FENE))) ++ { ++ p_FmPort->savedBmiFene = p_CcParams->setCcParams.nia; ++ p_FmPort->requiredAction |= UPDATE_NIA_FENE; ++ } ++ else if (p_CcParams->setCcParams.type & UPDATE_NIA_FENE) ++ { ++ if (p_FmPort->savedBmiFene != p_CcParams->setCcParams.nia) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("xFENE was defined previously different")); ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_NIA_FPNE) && ++ !(p_FmPort->requiredAction & UPDATE_NIA_FPNE)) ++ { ++ p_FmPort->savedBmiFpne = p_CcParams->setCcParams.nia; ++ p_FmPort->requiredAction |= UPDATE_NIA_FPNE; ++ } ++ else if (p_CcParams->setCcParams.type & UPDATE_NIA_FPNE) ++ { ++ if (p_FmPort->savedBmiFpne != p_CcParams->setCcParams.nia) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("xFPNE was defined previously different")); ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_NIA_CMNE) && ++ !(p_FmPort->requiredAction & UPDATE_NIA_CMNE)) ++ { ++ p_FmPort->savedBmiCmne = p_CcParams->setCcParams.nia; ++ p_FmPort->requiredAction |= UPDATE_NIA_CMNE; ++ } ++ else if (p_CcParams->setCcParams.type & UPDATE_NIA_CMNE) ++ { ++ if (p_FmPort->savedBmiCmne != p_CcParams->setCcParams.nia) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("xCMNE was defined previously different")); ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_PSO) && ++ !(p_FmPort->requiredAction & UPDATE_PSO)) ++ { ++ /* get PCD registers pointers */ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpso; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opso; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ /* set start parsing offset */ ++ tmpInt = (int)GET_UINT32(*p_BmiPrsStartOffset)+ p_CcParams->setCcParams.psoSize; ++ if (tmpInt>0) ++ WRITE_UINT32(*p_BmiPrsStartOffset, (uint32_t)tmpInt); ++ ++ p_FmPort->requiredAction |= UPDATE_PSO; ++ p_FmPort->savedPrsStartOffset = p_CcParams->setCcParams.psoSize; ++ ++ } ++ else if (p_CcParams->setCcParams.type & UPDATE_PSO) ++ { ++ if (p_FmPort->savedPrsStartOffset != p_CcParams->setCcParams.psoSize) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("parser start offset was defoned previousley different")); ++ } ++ ++ return E_OK; ++} ++/*********************** End of inter-module routines ************************/ ++ ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++ ++t_Handle FM_PORT_Config(t_FmPortParams *p_FmPortParams) ++{ ++ t_FmPort *p_FmPort; ++ uintptr_t baseAddr = p_FmPortParams->baseAddr; ++ uint32_t tmpReg; ++ ++ /* Allocate FM structure */ ++ p_FmPort = (t_FmPort *) XX_Malloc(sizeof(t_FmPort)); ++ if (!p_FmPort) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Port driver structure")); ++ return NULL; ++ } ++ memset(p_FmPort, 0, sizeof(t_FmPort)); ++ ++ /* Allocate the FM driver's parameters structure */ ++ p_FmPort->p_FmPortDriverParam = (t_FmPortDriverParam *)XX_Malloc(sizeof(t_FmPortDriverParam)); ++ if (!p_FmPort->p_FmPortDriverParam) ++ { ++ XX_Free(p_FmPort); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Port driver parameters")); ++ return NULL; ++ } ++ memset(p_FmPort->p_FmPortDriverParam, 0, sizeof(t_FmPortDriverParam)); ++ ++ /* Initialize FM port parameters which will be kept by the driver */ ++ p_FmPort->portType = p_FmPortParams->portType; ++ p_FmPort->portId = p_FmPortParams->portId; ++ p_FmPort->pcdEngines = FM_PCD_NONE; ++ p_FmPort->f_Exception = p_FmPortParams->f_Exception; ++ p_FmPort->h_App = p_FmPortParams->h_App; ++ p_FmPort->h_Fm = p_FmPortParams->h_Fm; ++ ++ /* get FM revision */ ++ FM_GetRevision(p_FmPort->h_Fm, &p_FmPort->fmRevInfo); ++ ++ /* calculate global portId number */ ++ SW_PORT_ID_TO_HW_PORT_ID(p_FmPort->hardwarePortId, p_FmPort->portType, p_FmPortParams->portId); ++ ++ if (p_FmPort->fmRevInfo.majorRev >= 6) ++ { ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) && ++ (p_FmPortParams->portId != FM_OH_PORT_ID)) ++ DBG(WARNING, ++ ("Port ID %d is recommended for HC port. Overwriting HW defaults to be suitable for HC.", ++ FM_OH_PORT_ID)); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) && ++ (p_FmPortParams->portId == FM_OH_PORT_ID)) ++ DBG(WARNING, ("Use non-zero portId for OP port due to insufficient resources on portId 0.")); ++ } ++ ++ /* Initialize FM port parameters for initialization phase only */ ++ p_FmPort->p_FmPortDriverParam->baseAddr = baseAddr; ++ /* set memory map pointers */ ++ p_FmPort->p_FmPortQmiRegs = (t_FmPortQmiRegs *)UINT_TO_PTR(baseAddr + QMI_PORT_REGS_OFFSET); ++ p_FmPort->p_FmPortBmiRegs = (u_FmPortBmiRegs *)UINT_TO_PTR(baseAddr + BMI_PORT_REGS_OFFSET); ++ p_FmPort->p_FmPortPrsRegs = (t_FmPortPrsRegs *)UINT_TO_PTR(baseAddr + PRS_PORT_REGS_OFFSET); ++ ++ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.privDataSize = DEFAULT_PORT_bufferPrefixContent_privDataSize; ++ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passPrsResult= DEFAULT_PORT_bufferPrefixContent_passPrsResult; ++ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passTimeStamp= DEFAULT_PORT_bufferPrefixContent_passTimeStamp; ++ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passAllOtherPCDInfo ++ = DEFAULT_PORT_bufferPrefixContent_passTimeStamp; ++ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign = DEFAULT_PORT_bufferPrefixContent_dataAlign; ++ p_FmPort->p_FmPortDriverParam->dmaSwapData = DEFAULT_PORT_dmaSwapData; ++ p_FmPort->p_FmPortDriverParam->dmaIntContextCacheAttr = DEFAULT_PORT_dmaIntContextCacheAttr; ++ p_FmPort->p_FmPortDriverParam->dmaHeaderCacheAttr = DEFAULT_PORT_dmaHeaderCacheAttr; ++ p_FmPort->p_FmPortDriverParam->dmaScatterGatherCacheAttr = DEFAULT_PORT_dmaScatterGatherCacheAttr; ++ p_FmPort->p_FmPortDriverParam->dmaWriteOptimize = DEFAULT_PORT_dmaWriteOptimize; ++ p_FmPort->p_FmPortDriverParam->liodnBase = p_FmPortParams->liodnBase; ++ p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore = DEFAULT_PORT_cheksumLastBytesIgnore; ++ p_FmPort->p_FmPortDriverParam->color = DEFAULT_PORT_color; ++ ++ p_FmPort->maxFrameLength = DEFAULT_PORT_maxFrameLength; ++ /* resource distribution. */ ++#ifdef FM_NO_GUARANTEED_RESET_VALUES ++ if (1) /* if (p_FmPort->fmRevInfo.majorRev < 6) */ ++ { ++ p_FmPort->fifoBufs.num = DEFAULT_PORT_numOfFifoBufs(p_FmPort->portType)*BMI_FIFO_UNITS; ++ p_FmPort->fifoBufs.extra = DEFAULT_PORT_extraNumOfFifoBufs*BMI_FIFO_UNITS; ++ p_FmPort->openDmas.num = DEFAULT_PORT_numOfOpenDmas(p_FmPort->portType, p_FmPort->fmRevInfo.majorRev); ++ p_FmPort->openDmas.extra = DEFAULT_PORT_extraNumOfOpenDmas(p_FmPort->portType); ++ p_FmPort->tasks.num = DEFAULT_PORT_numOfTasks(p_FmPort->portType); ++ p_FmPort->tasks.extra = DEFAULT_PORT_extraNumOfTasks(p_FmPort->portType); ++ } ++ else ++#endif /* FM_NO_GUARANTEED_RESET_VALUES */ ++ { ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) && ++ (p_FmPortParams->portId != FM_OH_PORT_ID)) ++ { ++ /* Overwrite HC defaults */ ++ p_FmPort->fifoBufs.num = DEFAULT_PORT_numOfFifoBufs(p_FmPort->portType)*BMI_FIFO_UNITS; ++ p_FmPort->fifoBufs.extra = DEFAULT_PORT_extraNumOfFifoBufs*BMI_FIFO_UNITS; ++ p_FmPort->openDmas.num = DEFAULT_PORT_numOfOpenDmas(p_FmPort->portType, p_FmPort->fmRevInfo.majorRev); ++ p_FmPort->openDmas.extra = DEFAULT_PORT_extraNumOfOpenDmas(p_FmPort->portType); ++ p_FmPort->tasks.num = DEFAULT_PORT_numOfTasks(p_FmPort->portType); ++ p_FmPort->tasks.extra = DEFAULT_PORT_extraNumOfTasks(p_FmPort->portType); ++ } ++ else ++ { ++ p_FmPort->fifoBufs.num = 0; ++ p_FmPort->fifoBufs.extra = 0; ++ p_FmPort->openDmas.num = 0; ++ p_FmPort->openDmas.extra = 0; ++ p_FmPort->tasks.num = 0; ++ p_FmPort->tasks.extra = 0; ++ } ++ } ++ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) ++ p_FmPort->p_FmPortDriverParam->syncReq = DEFAULT_PORT_syncReqForHc; ++ else ++ p_FmPort->p_FmPortDriverParam->syncReq = DEFAULT_PORT_syncReq; ++ ++ /* Port type specific initialization: */ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_TX_10G)) ++ p_FmPort->p_FmPortDriverParam->frmDiscardOverride = DEFAULT_PORT_frmDiscardOverride; ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX): ++ case (e_FM_PORT_TYPE_RX_10G): ++ /* Initialize FM port parameters for initialization phase only */ ++ p_FmPort->p_FmPortDriverParam->cutBytesFromEnd = DEFAULT_PORT_cutBytesFromEnd; ++ p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = FALSE; ++ p_FmPort->p_FmPortDriverParam->frmDiscardOverride = DEFAULT_PORT_frmDiscardOverride; ++#ifdef FM_NO_GUARANTEED_RESET_VALUES ++ if (1) /* if (p_FmPort->fmRevInfo.majorRev < 6) */ ++ { ++ p_FmPort->p_FmPortDriverParam->rxFifoPriElevationLevel = DEFAULT_PORT_rxFifoPriElevationLevel; ++ p_FmPort->p_FmPortDriverParam->rxFifoThreshold = DEFAULT_PORT_rxFifoThreshold; ++ } ++ else ++#endif /* FM_NO_GUARANTEED_RESET_VALUES */ ++ { ++ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfp); ++ p_FmPort->p_FmPortDriverParam->rxFifoPriElevationLevel = (((tmpReg & BMI_RX_FIFO_PRI_ELEVATION_MASK) >> BMI_RX_FIFO_PRI_ELEVATION_SHIFT) + 1) * BMI_FIFO_UNITS ; ++ p_FmPort->p_FmPortDriverParam->rxFifoThreshold = (((tmpReg & BMI_RX_FIFO_THRESHOLD_MASK) >> BMI_RX_FIFO_THRESHOLD_SHIFT) + 1) * BMI_FIFO_UNITS; ++ } ++ ++ p_FmPort->p_FmPortDriverParam->bufMargins.endMargins = DEFAULT_PORT_BufMargins_endMargins; ++ p_FmPort->p_FmPortDriverParam->errorsToDiscard = DEFAULT_PORT_errorsToDiscard; ++ p_FmPort->p_FmPortDriverParam->forwardReuseIntContext = DEFAULT_PORT_forwardIntContextReuse; ++#if (DPAA_VERSION >= 11) ++ p_FmPort->p_FmPortDriverParam->noScatherGather = DEFAULT_PORT_noScatherGather; ++#endif /* (DPAA_VERSION >= 11) */ ++ break; ++ ++ case (e_FM_PORT_TYPE_TX): ++ p_FmPort->p_FmPortDriverParam->dontReleaseBuf = FALSE; ++#ifdef FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 ++ tmpReg = 0x00001013; ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfp, tmpReg); ++#endif /* FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 */ ++ case (e_FM_PORT_TYPE_TX_10G): ++#ifdef FM_NO_GUARANTEED_RESET_VALUES ++ if (1) /* if (p_FmPort->fmRevInfo.majorRev < 6) */ ++ { ++ p_FmPort->p_FmPortDriverParam->txFifoMinFillLevel = DEFAULT_PORT_txFifoMinFillLevel; ++ p_FmPort->fifoDeqPipelineDepth = ++ (uint8_t)((p_FmPort->portType == e_FM_PORT_TYPE_TX) ? ++ DEFAULT_PORT_fifoDeqPipelineDepth_1G : ++ DEFAULT_PORT_fifoDeqPipelineDepth_10G); ++ p_FmPort->p_FmPortDriverParam->txFifoLowComfLevel = DEFAULT_PORT_txFifoLowComfLevel; ++ } ++ else ++#endif /* FM_NO_GUARANTEED_RESET_VALUES */ ++ { ++ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfp); ++ p_FmPort->p_FmPortDriverParam->txFifoMinFillLevel = ++ ((tmpReg & BMI_TX_FIFO_MIN_FILL_MASK) >> BMI_TX_FIFO_MIN_FILL_SHIFT) * BMI_FIFO_UNITS ; ++ p_FmPort->fifoDeqPipelineDepth = ++ (uint8_t)(((tmpReg & BMI_FIFO_PIPELINE_DEPTH_MASK) >> BMI_FIFO_PIPELINE_DEPTH_SHIFT) + 1); ++ p_FmPort->p_FmPortDriverParam->txFifoLowComfLevel = ++ (((tmpReg & BMI_TX_LOW_COMF_MASK) >> BMI_TX_LOW_COMF_SHIFT) + 1) * BMI_FIFO_UNITS; ++ } ++ ++ p_FmPort->p_FmPortDriverParam->deqType = DEFAULT_PORT_deqType; ++ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = DEFAULT_PORT_deqPrefetchOption; ++ p_FmPort->p_FmPortDriverParam->deqHighPriority = ++ (bool)((p_FmPort->portType == e_FM_PORT_TYPE_TX) ? ++ DEFAULT_PORT_deqHighPriority_1G : ++ DEFAULT_PORT_deqHighPriority_10G); ++ p_FmPort->p_FmPortDriverParam->deqByteCnt = ++ (uint16_t)((p_FmPort->portType == e_FM_PORT_TYPE_TX) ? ++ DEFAULT_PORT_deqByteCnt_1G : ++ DEFAULT_PORT_deqByteCnt_10G); ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_FmPort->p_FmPortDriverParam->errorsToDiscard = DEFAULT_PORT_errorsToDiscard; ++#if (DPAA_VERSION >= 11) ++ p_FmPort->p_FmPortDriverParam->noScatherGather = DEFAULT_PORT_noScatherGather; ++#endif /* (DPAA_VERSION >= 11) */ ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = DEFAULT_PORT_deqPrefetchOption_HC; ++ p_FmPort->p_FmPortDriverParam->deqHighPriority = DEFAULT_PORT_deqHighPriority_1G; ++ p_FmPort->p_FmPortDriverParam->deqType = DEFAULT_PORT_deqType; ++ p_FmPort->p_FmPortDriverParam->deqByteCnt = DEFAULT_PORT_deqByteCnt_1G; ++ ++#ifdef FM_NO_GUARANTEED_RESET_VALUES ++ if (1) /* if (p_FmPort->fmRevInfo.majorRev < 6) */ ++ p_FmPort->fifoDeqPipelineDepth = DEFAULT_PORT_fifoDeqPipelineDepth_OH; ++ else ++#endif /* FM_NO_GUARANTEED_RESET_VALUES */ ++ { ++ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofp); ++ p_FmPort->fifoDeqPipelineDepth = ++ (uint8_t)(((tmpReg & BMI_FIFO_PIPELINE_DEPTH_MASK) >> BMI_FIFO_PIPELINE_DEPTH_SHIFT) + 1); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) && ++ (p_FmPortParams->portId != FM_OH_PORT_ID)) ++ { ++ /* Overwrite HC defaults */ ++ p_FmPort->fifoDeqPipelineDepth = DEFAULT_PORT_fifoDeqPipelineDepth_OH; ++ } ++ } ++ ++#ifndef FM_FRAME_END_PARAMS_FOR_OP ++ if (p_FmPort->fmRevInfo.majorRev < 6) ++ p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore = DEFAULT_notSupported; ++#endif /* !FM_FRAME_END_PARAMS_FOR_OP */ ++ ++#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP ++ if (!((p_FmPort->fmRevInfo.majorRev == 4) || ++ (p_FmPort->fmRevInfo.majorRev >= 6))) ++ p_FmPort->fifoDeqPipelineDepth = DEFAULT_notSupported; ++#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */ ++ break; ++ ++ default: ++ XX_Free(p_FmPort->p_FmPortDriverParam); ++ XX_Free(p_FmPort); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ return NULL; ++ } ++#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if (p_FmPort->fmRevInfo.majorRev == 4) ++ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = (e_FmPortDeqPrefetchOption)DEFAULT_notSupported; ++#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ ++ p_FmPort->imEn = p_FmPortParams->independentModeEnable; ++ ++ if (p_FmPort->imEn) ++ { ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G)) ++ p_FmPort->fifoDeqPipelineDepth = DEFAULT_PORT_fifoDeqPipelineDepth_IM; ++ FmPortConfigIM(p_FmPort, p_FmPortParams); ++ } ++ else ++ { ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX): ++ case (e_FM_PORT_TYPE_RX_10G): ++ /* Initialize FM port parameters for initialization phase only */ ++ memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools, ++ &p_FmPortParams->specificParams.rxParams.extBufPools, ++ sizeof(t_FmExtPools)); ++ p_FmPort->p_FmPortDriverParam->errFqid = p_FmPortParams->specificParams.rxParams.errFqid; ++ p_FmPort->p_FmPortDriverParam->dfltFqid = p_FmPortParams->specificParams.rxParams.dfltFqid; ++ p_FmPort->p_FmPortDriverParam->liodnOffset = p_FmPortParams->specificParams.rxParams.liodnOffset; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_TX): ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ p_FmPort->p_FmPortDriverParam->errFqid = p_FmPortParams->specificParams.nonRxParams.errFqid; ++ p_FmPort->p_FmPortDriverParam->deqSubPortal = ++ (uint8_t)(p_FmPortParams->specificParams.nonRxParams.qmChannel & QMI_DEQ_CFG_SUBPORTAL_MASK); ++ p_FmPort->p_FmPortDriverParam->dfltFqid = p_FmPortParams->specificParams.nonRxParams.dfltFqid; ++ break; ++ default: ++ XX_Free(p_FmPort->p_FmPortDriverParam); ++ XX_Free(p_FmPort); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ return NULL; ++ } ++ } ++ ++ memset(p_FmPort->name, 0, (sizeof(char)) * MODULE_NAME_SIZE); ++ if (Sprint (p_FmPort->name, "FM-%d-port-%s-%d", ++ FmGetId(p_FmPort->h_Fm), ++ ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING || ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ? ++ "OH" : (p_FmPort->portType == e_FM_PORT_TYPE_RX ? ++ "1g-RX" : (p_FmPort->portType == e_FM_PORT_TYPE_TX ? ++ "1g-TX" : (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G ? ++ "10g-RX" : "10g-TX")))), ++ p_FmPort->portId) == 0) ++ { ++ XX_Free(p_FmPort->p_FmPortDriverParam); ++ XX_Free(p_FmPort); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ return NULL; ++ } ++ ++ p_FmPort->h_Spinlock = XX_InitSpinlock(); ++ if (!p_FmPort->h_Spinlock) ++ { ++ XX_Free(p_FmPort->p_FmPortDriverParam); ++ XX_Free(p_FmPort); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ return NULL; ++ } ++ ++ return p_FmPort; ++} ++ ++/**************************************************************************//** ++ @Function FM_PORT_Init ++ ++ @Description Initializes the FM module ++ ++ @Param[in] h_FmPort - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PORT_Init(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_FmPortDriverParam *p_Params; ++ t_Error err = E_OK; ++ t_FmInterModulePortInitParams fmParams; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ err = FmSpBuildBufferStructure(&p_FmPort->p_FmPortDriverParam->intContext, ++ &p_FmPort->p_FmPortDriverParam->bufferPrefixContent, ++ &p_FmPort->p_FmPortDriverParam->bufMargins, ++ &p_FmPort->bufferOffsets, ++ &p_FmPort->internalBufferOffset); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 ++ if ((p_FmPort->p_FmPortDriverParam->bcbWorkaround) && ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ { ++ p_FmPort->p_FmPortDriverParam->errorsToDiscard |= FM_PORT_FRM_ERR_PHYSICAL; ++ if (!p_FmPort->fifoBufs.num) ++ p_FmPort->fifoBufs.num = 50 * BMI_FIFO_UNITS; ++ p_FmPort->fifoBufs.num += 4*KILOBYTE; ++ } ++#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */ ++ ++ CHECK_INIT_PARAMETERS(p_FmPort, CheckInitParameters); ++ ++ p_Params = p_FmPort->p_FmPortDriverParam; ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ if (!p_FmPort->imEn) ++ { ++ /* Call the external Buffer routine which also checks fifo ++ size and updates it if necessary */ ++ /* define external buffer pools and pool depletion*/ ++ err = SetExtBufferPools(p_FmPort); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /************************************************************/ ++ /* Call FM module routine for communicating parameters */ ++ /************************************************************/ ++ memset(&fmParams, 0, sizeof(fmParams)); ++ fmParams.hardwarePortId = p_FmPort->hardwarePortId; ++ fmParams.portType = (e_FmPortType)p_FmPort->portType; ++ fmParams.numOfTasks = (uint8_t)p_FmPort->tasks.num; ++ fmParams.numOfExtraTasks = (uint8_t)p_FmPort->tasks.extra; ++ fmParams.numOfOpenDmas = (uint8_t)p_FmPort->openDmas.num; ++ fmParams.numOfExtraOpenDmas = (uint8_t)p_FmPort->openDmas.extra; ++ if (p_FmPort->fifoBufs.num) ++ { ++ err = VerifySizeOfFifo(p_FmPort); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ fmParams.sizeOfFifo = p_FmPort->fifoBufs.num; ++ fmParams.extraSizeOfFifo = p_FmPort->fifoBufs.extra; ++ fmParams.independentMode = p_FmPort->imEn; ++ fmParams.liodnOffset = p_Params->liodnOffset; ++ fmParams.liodnBase = p_Params->liodnBase; ++ fmParams.deqPipelineDepth = p_FmPort->fifoDeqPipelineDepth; ++ fmParams.maxFrameLength = p_FmPort->maxFrameLength; ++#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ++ { ++ if (!((p_FmPort->fmRevInfo.majorRev == 4) || ++ (p_FmPort->fmRevInfo.majorRev >= 6))) ++ /* HC ports do not have fifoDeqPipelineDepth, but it is needed only ++ * for deq threshold calculation. ++ */ ++ fmParams.deqPipelineDepth = 2; ++ } ++#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */ ++ ++ ++ err = FmGetSetPortParams(p_FmPort->h_Fm, &fmParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /* get params for use in init */ ++ p_FmPort->fmMuramPhysBaseAddr = ++ (uint64_t)((uint64_t)(fmParams.fmMuramPhysBaseAddr.low) | ++ ((uint64_t)(fmParams.fmMuramPhysBaseAddr.high) << 32)); ++ p_FmPort->h_FmMuram = FmGetMuramHandle(p_FmPort->h_Fm); ++ ++#ifndef FM_NO_GUARANTEED_RESET_VALUES ++ if (p_FmPort->fmRevInfo.majorRev >= 6) ++ { ++ p_FmPort->tasks.num = fmParams.numOfTasks; ++ p_FmPort->tasks.extra = fmParams.numOfExtraTasks; ++ p_FmPort->openDmas.num = fmParams.numOfOpenDmas; ++ p_FmPort->openDmas.extra = fmParams.numOfExtraOpenDmas; ++ p_FmPort->fifoBufs.num = fmParams.sizeOfFifo; ++ p_FmPort->fifoBufs.extra = fmParams.extraSizeOfFifo; ++ } ++#endif /* FM_NO_GUARANTEED_RESET_VALUES */ ++ ++ /**********************/ ++ /* Init BMI Registers */ ++ /**********************/ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ err = BmiRxPortInit(p_FmPort); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ err = BmiTxPortInit(p_FmPort); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ err = BmiOhPortInit(p_FmPort); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ } ++ ++ /**********************/ ++ /* Init QMI Registers */ ++ /**********************/ ++ if (!p_FmPort->imEn && ((err = QmiInit(p_FmPort)) != E_OK)) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (p_FmPort->imEn && ((err = FmPortImInit(p_FmPort)) != E_OK)) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ FmPortDriverParamFree(p_FmPort); ++ ++ return E_OK; ++} ++ ++/**************************************************************************//** ++ @Function FM_PORT_Free ++ ++ @Description Frees all resources that were assigned to FM module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmPort - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PORT_Free(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_FmInterModulePortFreeParams fmParams; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ ++ if (p_FmPort->pcdEngines) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Trying to free a port with PCD. FM_PORT_DeletePCD must be called first.")); ++ ++ if (p_FmPort->enabled) ++ { ++ if (FM_PORT_Disable(p_FmPort) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM_PORT_Disable FAILED")); ++ } ++ ++ if (p_FmPort->imEn) ++ FmPortImFree(p_FmPort); ++ ++ FmPortDriverParamFree(p_FmPort); ++ ++ fmParams.hardwarePortId = p_FmPort->hardwarePortId; ++ fmParams.portType = (e_FmPortType)p_FmPort->portType; ++ fmParams.deqPipelineDepth = p_FmPort->fifoDeqPipelineDepth; ++ ++ FmFreePortParams(p_FmPort->h_Fm, &fmParams); ++ ++#if (DPAA_VERSION >= 11) ++ if (FmVSPFreeForPort(p_FmPort->h_Fm, ++ p_FmPort->portType, ++ p_FmPort->portId) != E_OK) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("VSP free of port FAILED")); ++ ++ if (p_FmPort->p_MuramPage) ++ FM_MURAM_FreeMem(p_FmPort->h_FmMuram, p_FmPort->p_MuramPage); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (p_FmPort->h_Spinlock) ++ XX_FreeSpinlock(p_FmPort->h_Spinlock); ++ ++ XX_Free(p_FmPort); ++ ++ return E_OK; ++} ++ ++ ++/*************************************************/ ++/* API Advanced Init unit functions */ ++/*************************************************/ ++ ++t_Error FM_PORT_ConfigNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_OpenDmas) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->setNumOfOpenDmas = TRUE; ++ memcpy(&p_FmPort->openDmas, p_OpenDmas, sizeof(t_FmPortRsrc)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ memcpy(&p_FmPort->tasks, p_NumOfTasks, sizeof(t_FmPortRsrc)); ++ p_FmPort->p_FmPortDriverParam->setNumOfTasks = TRUE; ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->setSizeOfFifo = TRUE; ++ memcpy(&p_FmPort->fifoBufs, p_SizeOfFifo, sizeof(t_FmPortRsrc)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDeqHighPriority(t_Handle h_FmPort, bool highPri) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("not available for Rx ports")); ++ ++ p_FmPort->p_FmPortDriverParam->deqHighPriority = highPri; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDeqType(t_Handle h_FmPort, e_FmPortDeqType deqType) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Rx ports")); ++ ++ p_FmPort->p_FmPortDriverParam->deqType = deqType; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDeqPrefetchOption(t_Handle h_FmPort, e_FmPortDeqPrefetchOption deqPrefetchOption) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Rx ports")); ++ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = deqPrefetchOption; ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigBackupPools(t_Handle h_FmPort, t_FmBackupBmPools *p_BackupBmPools) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->p_BackupBmPools = (t_FmBackupBmPools *)XX_Malloc(sizeof(t_FmBackupBmPools)); ++ if (!p_FmPort->p_FmPortDriverParam->p_BackupBmPools) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BackupBmPools allocation failed")); ++ memcpy(p_FmPort->p_FmPortDriverParam->p_BackupBmPools, p_BackupBmPools, sizeof(t_FmBackupBmPools)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDeqByteCnt(t_Handle h_FmPort, uint16_t deqByteCnt) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Rx ports")); ++ ++ p_FmPort->p_FmPortDriverParam->deqByteCnt = deqByteCnt; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigBufferPrefixContent(t_Handle h_FmPort, t_FmBufferPrefixContent *p_FmBufferPrefixContent) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ memcpy(&p_FmPort->p_FmPortDriverParam->bufferPrefixContent, p_FmBufferPrefixContent, sizeof(t_FmBufferPrefixContent)); ++ /* if dataAlign was not initialized by user, we return to driver's deafult */ ++ if (!p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign) ++ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign = DEFAULT_PORT_bufferPrefixContent_dataAlign; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigCheksumLastBytesIgnore(t_Handle h_FmPort, uint8_t cheksumLastBytesIgnore) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore = cheksumLastBytesIgnore; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigCutBytesFromEnd(t_Handle h_FmPort, uint8_t cutBytesFromEnd) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->cutBytesFromEnd = cutBytesFromEnd; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigPoolDepletion(t_Handle h_FmPort, t_FmBufPoolDepletion *p_BufPoolDepletion) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = TRUE; ++ memcpy(&p_FmPort->p_FmPortDriverParam->bufPoolDepletion, p_BufPoolDepletion, sizeof(t_FmBufPoolDepletion)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigObservedPoolDepletion(t_Handle h_FmPort, t_FmPortObservedBufPoolDepletion *p_FmPortObservedBufPoolDepletion) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for OP ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = TRUE; ++ memcpy(&p_FmPort->p_FmPortDriverParam->bufPoolDepletion, ++ &p_FmPortObservedBufPoolDepletion->poolDepletionParams, ++ sizeof(t_FmBufPoolDepletion)); ++ memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools, ++ &p_FmPortObservedBufPoolDepletion->poolsParams, ++ sizeof(t_FmExtPools)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigExtBufPools(t_Handle h_FmPort, t_FmExtPools *p_FmExtPools) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for OP ports only")); ++ ++ memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools, p_FmExtPools, sizeof(t_FmExtPools)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDontReleaseTxBufToBM(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->dontReleaseBuf = TRUE; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDfltColor(t_Handle h_FmPort, e_FmPortColor color) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ p_FmPort->p_FmPortDriverParam->color = color; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigSyncReq(t_Handle h_FmPort, bool syncReq) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType == e_FM_PORT_TYPE_TX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for Tx ports")); ++ ++ p_FmPort->p_FmPortDriverParam->syncReq = syncReq; ++ ++ return E_OK; ++} ++ ++ ++t_Error FM_PORT_ConfigFrmDiscardOverride(t_Handle h_FmPort, bool override) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType == e_FM_PORT_TYPE_TX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Tx ports")); ++ ++ p_FmPort->p_FmPortDriverParam->frmDiscardOverride = override; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigErrorsToDiscard(t_Handle h_FmPort, fmPortFrameErrSelect_t errs) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->errorsToDiscard = errs; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDmaSwapData(t_Handle h_FmPort, e_FmDmaSwapOption swapData) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->dmaSwapData = swapData; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDmaIcCacheAttr(t_Handle h_FmPort, e_FmDmaCacheOption intContextCacheAttr) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->dmaIntContextCacheAttr = intContextCacheAttr; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDmaHdrAttr(t_Handle h_FmPort, e_FmDmaCacheOption headerCacheAttr) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->dmaHeaderCacheAttr = headerCacheAttr; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDmaScatterGatherAttr(t_Handle h_FmPort, e_FmDmaCacheOption scatterGatherCacheAttr) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->dmaScatterGatherCacheAttr = scatterGatherCacheAttr; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDmaWriteOptimize(t_Handle h_FmPort, bool optimize) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_TX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for Tx ports")); ++ ++ p_FmPort->p_FmPortDriverParam->dmaWriteOptimize = optimize; ++ ++ return E_OK; ++} ++ ++#if (DPAA_VERSION >= 11) ++t_Error FM_PORT_ConfigNoScatherGather(t_Handle h_FmPort, bool noScatherGather) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ UNUSED(noScatherGather); ++ UNUSED(p_FmPort); ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->noScatherGather = noScatherGather; ++ ++ return E_OK; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++t_Error FM_PORT_ConfigForwardReuseIntContext(t_Handle h_FmPort, bool forwardReuse) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->forwardReuseIntContext = forwardReuse; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigMaxFrameLength(t_Handle h_FmPort, uint16_t length) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->maxFrameLength = length; ++ ++ return E_OK; ++} ++ ++#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 ++t_Error FM_PORT_ConfigBCBWorkaround(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->bcbWorkaround = TRUE; ++ ++ return E_OK; ++} ++#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */ ++ ++/****************************************************/ ++/* Hidden-DEBUG Only API */ ++/****************************************************/ ++ ++t_Error FM_PORT_ConfigTxFifoMinFillLevel(t_Handle h_FmPort, uint32_t minFillLevel) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->txFifoMinFillLevel = minFillLevel; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigFifoDeqPipelineDepth(t_Handle h_FmPort, uint8_t deqPipelineDepth) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for Rx ports")); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for IM ports!")); ++ ++ p_FmPort->fifoDeqPipelineDepth = deqPipelineDepth; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigTxFifoLowComfLevel(t_Handle h_FmPort, uint32_t fifoLowComfLevel) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->txFifoLowComfLevel = fifoLowComfLevel; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigRxFifoThreshold(t_Handle h_FmPort, uint32_t fifoThreshold) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->rxFifoThreshold = fifoThreshold; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigRxFifoPriElevationLevel(t_Handle h_FmPort, uint32_t priElevationLevel) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->rxFifoPriElevationLevel = priElevationLevel; ++ ++ return E_OK; ++} ++/****************************************************/ ++/* API Run-time Control unit functions */ ++/****************************************************/ ++ ++t_Error FM_PORT_SetNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfOpenDmas) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((!p_NumOfOpenDmas->num) || (p_NumOfOpenDmas->num > MAX_NUM_OF_DMAS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas-num can't be larger than %d", MAX_NUM_OF_DMAS)); ++ if (p_NumOfOpenDmas->extra > MAX_NUM_OF_EXTRA_DMAS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas-extra can't be larger than %d", MAX_NUM_OF_EXTRA_DMAS)); ++ err = FmSetNumOfOpenDmas(p_FmPort->h_Fm, p_FmPort->hardwarePortId, (uint8_t*)&p_NumOfOpenDmas->num, (uint8_t*)&p_NumOfOpenDmas->extra, FALSE); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ memcpy(&p_FmPort->openDmas, p_NumOfOpenDmas, sizeof(t_FmPortRsrc)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ /* only driver uses host command port, so ASSERT rather than RETURN_ERROR */ ++ ASSERT_COND(p_FmPort->portType != e_FM_PORT_TYPE_OH_HOST_COMMAND); ++ ++ if ((!p_NumOfTasks->num) || (p_NumOfTasks->num > MAX_NUM_OF_TASKS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("NumOfTasks-num can't be larger than %d", MAX_NUM_OF_TASKS)); ++ if (p_NumOfTasks->extra > MAX_NUM_OF_EXTRA_TASKS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("NumOfTasks-extra can't be larger than %d", MAX_NUM_OF_EXTRA_TASKS)); ++ ++ err = FmSetNumOfTasks(p_FmPort->h_Fm, p_FmPort->hardwarePortId, (uint8_t*)&p_NumOfTasks->num, (uint8_t*)&p_NumOfTasks->extra, FALSE); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ /* update driver's struct */ ++ memcpy(&p_FmPort->tasks, p_NumOfTasks, sizeof(t_FmPortRsrc)); ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if (!p_SizeOfFifo->num || (p_SizeOfFifo->num > BMI_MAX_FIFO_SIZE)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SizeOfFifo-num has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE)); ++ if (p_SizeOfFifo->num % BMI_FIFO_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SizeOfFifo-num has to be divisible by %d", BMI_FIFO_UNITS)); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ /* extra FIFO size (allowed only to Rx ports) */ ++ if (p_SizeOfFifo->extra % BMI_FIFO_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SizeOfFifo-extra has to be divisible by %d", BMI_FIFO_UNITS)); ++ } ++ else ++ if (p_SizeOfFifo->extra) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" No SizeOfFifo-extra for non Rx ports")); ++ ++ memcpy(&p_FmPort->fifoBufs, p_SizeOfFifo, sizeof(t_FmPortRsrc)); ++ ++ /* we do not change user's parameter */ ++ err = VerifySizeOfFifo(p_FmPort); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ err = FmSetSizeOfFifo(p_FmPort->h_Fm, ++ p_FmPort->hardwarePortId, ++ &p_SizeOfFifo->num, ++ &p_SizeOfFifo->extra, ++ FALSE); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++uint32_t FM_PORT_GetBufferDataOffset(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, 0); ++ ++ return p_FmPort->bufferOffsets.dataOffset; ++} ++ ++uint8_t * FM_PORT_GetBufferICInfo(t_Handle h_FmPort, char *p_Data) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL); ++ ++ if (p_FmPort->bufferOffsets.pcdInfoOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (uint8_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.pcdInfoOffset); ++} ++ ++t_FmPrsResult * FM_PORT_GetBufferPrsResult(t_Handle h_FmPort, char *p_Data) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL); ++ ++ if (p_FmPort->bufferOffsets.prsResultOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (t_FmPrsResult *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.prsResultOffset); ++} ++ ++uint64_t * FM_PORT_GetBufferTimeStamp(t_Handle h_FmPort, char *p_Data) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL); ++ ++ if (p_FmPort->bufferOffsets.timeStampOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (uint64_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.timeStampOffset); ++} ++ ++uint8_t * FM_PORT_GetBufferHashResult(t_Handle h_FmPort, char *p_Data) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL); ++ ++ if (p_FmPort->bufferOffsets.hashResultOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (uint8_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.hashResultOffset); ++} ++ ++t_Error FM_PORT_Disable(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_BmiCfgReg = NULL; ++ volatile uint32_t *p_BmiStatusReg = NULL; ++ bool rxPort = FALSE; ++ int tries; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcfg; ++ p_BmiStatusReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rst; ++ rxPort = TRUE; ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg; ++ p_BmiStatusReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tst; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocfg; ++ p_BmiStatusReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ost; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ /* check if port is already disabled */ ++ if (!(GET_UINT32(*p_BmiCfgReg) & BMI_PORT_CFG_EN)) ++ { ++ if (!rxPort && !p_FmPort->imEn) ++ { ++ if (!(GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc)& QMI_PORT_CFG_EN)) ++ /* port is disabled */ ++ return E_OK; ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistency: Port's QMI is enabled but BMI disabled")); ++ } ++ /* port is disabled */ ++ return E_OK; ++ } ++ ++ /* Disable QMI */ ++ if (!rxPort && !p_FmPort->imEn) ++ { ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc, ++ GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) & ~QMI_PORT_CFG_EN); ++ /* wait for QMI to finish Handling dequeue tnums */ ++ tries=1000; ++ while ((GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pns) & QMI_PORT_STATUS_DEQ_FD_BSY) && ++ --tries) ++ XX_UDelay(1); ++ if (!tries) ++ { ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc, ++ GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) | QMI_PORT_CFG_EN); ++ RETURN_ERROR(MAJOR, E_BUSY, ("%s: can't disable! QMI busy", p_FmPort->name)); ++ } ++ } ++ ++ /* Disable BMI */ ++ WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) & ~BMI_PORT_CFG_EN); ++ ++ if (p_FmPort->imEn) ++ FmPortImDisable(p_FmPort); ++ ++ tries=5000; ++ while ((GET_UINT32(*p_BmiStatusReg) & BMI_PORT_STATUS_BSY) && ++ --tries) ++ XX_UDelay(1); ++ ++ if (!tries) ++ { ++ if (!rxPort && !p_FmPort->imEn) ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc, ++ GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) | QMI_PORT_CFG_EN); ++ WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) | BMI_PORT_CFG_EN); ++ ++ RETURN_ERROR(MAJOR, E_BUSY, ("%s: can't disable! BMI Busy", p_FmPort->name)); ++ } ++ ++ p_FmPort->enabled = 0; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_Enable(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_BmiCfgReg = NULL; ++ bool rxPort = FALSE; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcfg; ++ rxPort = TRUE; ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocfg; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ /* check if port is already enabled */ ++ if (GET_UINT32(*p_BmiCfgReg) & BMI_PORT_CFG_EN) ++ { ++ if (!rxPort && !p_FmPort->imEn) ++ { ++ if (GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc)& QMI_PORT_CFG_EN) ++ /* port is enabled */ ++ return E_OK; ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistency: Port's BMI is enabled but QMI disabled")); ++ } ++ /* port is enabled */ ++ return E_OK; ++ } ++ ++ if (p_FmPort->imEn) ++ FmPortImEnable(p_FmPort); ++ ++ /* Enable QMI */ ++ if (!rxPort && !p_FmPort->imEn) ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc, ++ GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) | QMI_PORT_CFG_EN); ++ ++ /* Enable BMI */ ++ WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) | BMI_PORT_CFG_EN); ++ ++ p_FmPort->enabled = 1; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetRateLimit(t_Handle h_FmPort, t_FmPortRateLimit *p_RateLimit) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint32_t tmpRateLimit, tmpRateLimitScale; ++ volatile uint32_t *p_RateLimitReg, *p_RateLimitScaleReg; ++ uint8_t factor, countUnitBit; ++ uint16_t baseGran; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx and Offline parsing ports only")); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ p_RateLimitReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_trlmt; ++ p_RateLimitScaleReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_trlmts; ++ baseGran = 16000; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_RateLimitReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_orlmt; ++ p_RateLimitScaleReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_orlmts; ++ baseGran = 10000; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ countUnitBit = (uint8_t)FmGetTimeStampScale(p_FmPort->h_Fm); /* TimeStamp per nano seconds units */ ++ /* normally, we use 1 usec as the reference count */ ++ factor = 1; ++ /* if ratelimit is too small for a 1usec factor, multiply the factor */ ++ while (p_RateLimit->rateLimit < baseGran/factor) ++ { ++ if (countUnitBit==31) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Rate limit is too small")); ++ ++ countUnitBit++; ++ factor <<= 1; ++ } ++ /* if ratelimit is too large for a 1usec factor, it is also larger than max rate*/ ++ if (p_RateLimit->rateLimit > ((uint32_t)baseGran * (1<<10) * (uint32_t)factor)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Rate limit is too large")); ++ ++ tmpRateLimit = (uint32_t)(p_RateLimit->rateLimit*factor/baseGran - 1); ++ ++ if (!p_RateLimit->maxBurstSize || (p_RateLimit->maxBurstSize > MAX_BURST_SIZE)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxBurstSize must be between 1K and %dk", MAX_BURST_SIZE)); ++ ++ tmpRateLimitScale = ((31 - (uint32_t)countUnitBit) << BMI_COUNT_RATE_UNIT_SHIFT) | BMI_RATE_LIMIT_EN; ++ ++ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ tmpRateLimit |= (uint32_t)(p_RateLimit->maxBurstSize - 1) << BMI_MAX_BURST_SHIFT; ++ else ++ { ++#ifndef FM_NO_ADVANCED_RATE_LIMITER ++ ++ if ((p_FmPort->fmRevInfo.majorRev == 4) || (p_FmPort->fmRevInfo.majorRev >= 6)) ++ { ++ switch (p_RateLimit->rateLimitDivider) ++ { ++ case (e_FM_PORT_DUAL_RATE_LIMITER_NONE): ++ break; ++ case (e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_2): ++ tmpRateLimitScale |= BMI_RATE_LIMIT_SCALE_BY_2; ++ break; ++ case (e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_4): ++ tmpRateLimitScale |= BMI_RATE_LIMIT_SCALE_BY_4; ++ break; ++ case (e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8): ++ tmpRateLimitScale |= BMI_RATE_LIMIT_SCALE_BY_8; ++ break; ++ default: ++ break; ++ } ++ tmpRateLimit |= BMI_RATE_LIMIT_BURST_SIZE_GRAN; ++ } ++ else ++#endif /* ! FM_NO_ADVANCED_RATE_LIMITER */ ++ { ++ if (p_RateLimit->rateLimitDivider != e_FM_PORT_DUAL_RATE_LIMITER_NONE) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("FM_PORT_ConfigDualRateLimitScaleDown")); ++ ++ if (p_RateLimit->maxBurstSize % 1000) ++ { ++ p_RateLimit->maxBurstSize = (uint16_t)((p_RateLimit->maxBurstSize/1000)+1); ++ DBG(WARNING, ("rateLimit.maxBurstSize rounded up to %d", (p_RateLimit->maxBurstSize/1000+1)*1000)); ++ } ++ else ++ p_RateLimit->maxBurstSize = (uint16_t)(p_RateLimit->maxBurstSize/1000); ++ } ++ tmpRateLimit |= (uint32_t)(p_RateLimit->maxBurstSize - 1) << BMI_MAX_BURST_SHIFT; ++ ++ } ++ WRITE_UINT32(*p_RateLimitScaleReg, tmpRateLimitScale); ++ WRITE_UINT32(*p_RateLimitReg, tmpRateLimit); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_DeleteRateLimit(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_RateLimitReg, *p_RateLimitScaleReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx and Offline parsing ports only")); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ p_RateLimitReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_trlmt; ++ p_RateLimitScaleReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_trlmts; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_RateLimitReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_orlmt; ++ p_RateLimitScaleReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_orlmts; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ WRITE_UINT32(*p_RateLimitScaleReg, 0); ++ WRITE_UINT32(*p_RateLimitReg, 0); ++ ++ return E_OK; ++} ++ ++ ++t_Error FM_PORT_SetFrameQueueCounters(t_Handle h_FmPort, bool enable) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ tmpReg = GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc); ++ if (enable) ++ tmpReg |= QMI_PORT_CFG_EN_COUNTERS ; ++ else ++ tmpReg &= ~QMI_PORT_CFG_EN_COUNTERS; ++ ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc, tmpReg); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetPerformanceCounters(t_Handle h_FmPort, bool enable) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_BmiPcReg = NULL; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiPcReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpc; ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ p_BmiPcReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tpc; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ p_BmiPcReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opc; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ if (enable) ++ WRITE_UINT32(*p_BmiPcReg, BMI_COUNTERS_EN); ++ else ++ WRITE_UINT32(*p_BmiPcReg, 0); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetPerformanceCountersParams(t_Handle h_FmPort, t_FmPortPerformanceCnt *p_FmPortPerformanceCnt) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint32_t tmpReg; ++ volatile uint32_t *p_BmiPcpReg = NULL; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiPcpReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpcp; ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ p_BmiPcpReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tpcp; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ p_BmiPcpReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opcp; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ /* check parameters */ ++ if (!p_FmPortPerformanceCnt->taskCompVal || ++ (p_FmPortPerformanceCnt->taskCompVal > p_FmPort->tasks.num)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("performanceCnt.taskCompVal has to be in the range of 1 - %d (current value)!", ++ p_FmPort->tasks.num)); ++ if (!p_FmPortPerformanceCnt->dmaCompVal || ++ (p_FmPortPerformanceCnt->dmaCompVal > p_FmPort->openDmas.num)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("performanceCnt.dmaCompVal has to be in the range of 1 - %d (current value)!", ++ p_FmPort->openDmas.num)); ++ if (!p_FmPortPerformanceCnt->fifoCompVal || ++ (p_FmPortPerformanceCnt->fifoCompVal > p_FmPort->fifoBufs.num)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("performanceCnt.fifoCompVal has to be in the range of 256 - %d (current value)!", ++ p_FmPort->fifoBufs.num)); ++ if (p_FmPortPerformanceCnt->fifoCompVal % BMI_FIFO_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("performanceCnt.fifoCompVal has to be divisible by %d", ++ BMI_FIFO_UNITS)); ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ if (!p_FmPortPerformanceCnt->queueCompVal || ++ (p_FmPortPerformanceCnt->queueCompVal > MAX_PERFORMANCE_RX_QUEUE_COMP)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("performanceCnt.queueCompVal for Rx has to be in the range of 1 - %d", ++ MAX_PERFORMANCE_RX_QUEUE_COMP)); ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ if (!p_FmPortPerformanceCnt->queueCompVal || ++ (p_FmPortPerformanceCnt->queueCompVal > MAX_PERFORMANCE_TX_QUEUE_COMP)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("performanceCnt.queueCompVal for Tx has to be in the range of 1 - %d", ++ MAX_PERFORMANCE_TX_QUEUE_COMP)); ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ if (p_FmPortPerformanceCnt->queueCompVal) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("performanceCnt.queueCompVal is not relevant for H/O ports.")); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ tmpReg = 0; ++ tmpReg |= ((uint32_t)(p_FmPortPerformanceCnt->queueCompVal - 1) << BMI_PERFORMANCE_PORT_COMP_SHIFT); ++ tmpReg |= ((uint32_t)(p_FmPortPerformanceCnt->dmaCompVal- 1) << BMI_PERFORMANCE_DMA_COMP_SHIFT); ++ tmpReg |= ((uint32_t)(p_FmPortPerformanceCnt->fifoCompVal/BMI_FIFO_UNITS - 1) << BMI_PERFORMANCE_FIFO_COMP_SHIFT); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) && (p_FmPort->portType != e_FM_PORT_TYPE_OH_HOST_COMMAND)) ++ tmpReg |= ((uint32_t)(p_FmPortPerformanceCnt->taskCompVal - 1) << BMI_PERFORMANCE_TASK_COMP_SHIFT); ++ ++ WRITE_UINT32(*p_BmiPcpReg, tmpReg); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_AnalyzePerformanceParams(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_FmPortPerformanceCnt currParams, savedParams; ++ t_Error err; ++ bool underTest, failed = FALSE; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ ++ XX_Print("Analyzing Performance parameters for port (type %d, id%d)\n", ++ p_FmPort->portType, p_FmPort->portId); ++ ++ currParams.taskCompVal = (uint8_t)p_FmPort->tasks.num; ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ++ currParams.queueCompVal = 0; ++ else ++ currParams.queueCompVal = 1; ++ currParams.dmaCompVal =(uint8_t) p_FmPort->openDmas.num; ++ currParams.fifoCompVal = p_FmPort->fifoBufs.num; ++ ++ FM_PORT_SetPerformanceCounters(p_FmPort, FALSE); ++ ClearPerfCnts(p_FmPort); ++ if ((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &currParams)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ FM_PORT_SetPerformanceCounters(p_FmPort, TRUE); ++ XX_UDelay(1000000); ++ FM_PORT_SetPerformanceCounters(p_FmPort, FALSE); ++ if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL)) ++ { ++ XX_Print ("Max num of defined port tasks (%d) utilized - Please enlarge\n",p_FmPort->tasks.num); ++ failed = TRUE; ++ } ++ if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL)) ++ { ++ XX_Print ("Max num of defined port openDmas (%d) utilized - Please enlarge\n",p_FmPort->openDmas.num); ++ failed = TRUE; ++ } ++ if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL)) ++ { ++ XX_Print("Max size of defined port fifo (%d) utilized - Please enlarge\n",p_FmPort->fifoBufs.num); ++ failed = TRUE; ++ } ++ if (failed) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG); ++ ++ memset(&savedParams, 0, sizeof(savedParams)); ++ while (TRUE) ++ { ++ underTest = FALSE; ++ if ((currParams.taskCompVal != 1) && !savedParams.taskCompVal) ++ { ++ currParams.taskCompVal--; ++ underTest = TRUE; ++ } ++ if ((currParams.dmaCompVal != 1) && !savedParams.dmaCompVal) ++ { ++ currParams.dmaCompVal--; ++ underTest = TRUE; ++ } ++ if ((currParams.fifoCompVal != BMI_FIFO_UNITS) && !savedParams.fifoCompVal) ++ { ++ currParams.fifoCompVal -= BMI_FIFO_UNITS; ++ underTest = TRUE; ++ } ++ if (!underTest) ++ break; ++ ++ ClearPerfCnts(p_FmPort); ++ if ((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &currParams)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ FM_PORT_SetPerformanceCounters(p_FmPort, TRUE); ++ XX_UDelay(1000000); ++ FM_PORT_SetPerformanceCounters(p_FmPort, FALSE); ++ ++ if (!savedParams.taskCompVal && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL)) ++ savedParams.taskCompVal = (uint8_t)(currParams.taskCompVal+2); ++ if (!savedParams.dmaCompVal && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL)) ++ savedParams.dmaCompVal = (uint8_t)(currParams.dmaCompVal+2); ++ if (!savedParams.fifoCompVal && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL)) ++ savedParams.fifoCompVal = currParams.fifoCompVal+(2*BMI_FIFO_UNITS); ++ } ++ ++ XX_Print("best vals: tasks %d, dmas %d, fifos %d\n", ++ savedParams.taskCompVal, savedParams.dmaCompVal, savedParams.fifoCompVal); ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetStatisticsCounters(t_Handle h_FmPort, bool enable) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint32_t tmpReg; ++ volatile uint32_t *p_BmiStcReg = NULL; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiStcReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rstc; ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ p_BmiStcReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tstc; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ p_BmiStcReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ostc; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ tmpReg = GET_UINT32(*p_BmiStcReg); ++ ++ if (enable) ++ tmpReg |= BMI_COUNTERS_EN; ++ else ++ tmpReg &= ~BMI_COUNTERS_EN; ++ ++ WRITE_UINT32(*p_BmiStcReg, tmpReg); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetErrorsRoute(t_Handle h_FmPort, fmPortFrameErrSelect_t errs) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_ErrQReg, *p_ErrDiscard; ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_ErrQReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsem; ++ p_ErrDiscard = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsdm; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_ErrQReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsem; ++ p_ErrDiscard = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only")); ++ } ++ ++ if (GET_UINT32(*p_ErrDiscard) & errs) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Selectd Errors that were configured to cause frame discard.")); ++ ++ WRITE_UINT32(*p_ErrQReg, errs); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, bool enable) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint32_t tmpReg; ++ int i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(poolIdp_FmPortDriverParam, E_INVALID_STATE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only")); ++ ++ for (i=0 ; i< FM_PORT_MAX_NUM_OF_EXT_POOLS ; i++) ++ { ++ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i]); ++ if ((uint8_t)((tmpReg & BMI_EXT_BUF_POOL_ID_MASK) >> BMI_EXT_BUF_POOL_ID_SHIFT) == poolId) ++ { ++ if (enable) ++ tmpReg |= BMI_EXT_BUF_POOL_EN_COUNTER; ++ else ++ tmpReg &= ~BMI_EXT_BUF_POOL_EN_COUNTER; ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i], tmpReg); ++ break; ++ } ++ } ++ if (i == FM_PORT_MAX_NUM_OF_EXT_POOLS) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE,("poolId %d is not included in this ports pools", poolId)); ++ ++ return E_OK; ++} ++ ++uint32_t FM_PORT_GetCounter(t_Handle h_FmPort, e_FmPortCounters counter) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ bool bmiCounter = FALSE; ++ volatile uint32_t *p_Reg; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_DEQ_TOTAL): ++ case (e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT): ++ case (e_FM_PORT_COUNTERS_DEQ_CONFIRM): ++ /* check that counter is available for the port type */ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports")); ++ return 0; ++ } ++ bmiCounter = FALSE; ++ case (e_FM_PORT_COUNTERS_ENQ_TOTAL): ++ bmiCounter = FALSE; ++ break; ++ default: /* BMI counters (or error - will be checked in BMI routine )*/ ++ bmiCounter = TRUE; ++ break; ++ } ++ ++ if (bmiCounter) ++ { ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ if (BmiRxPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, NO_MSG); ++ return 0; ++ } ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ if (BmiTxPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, NO_MSG); ++ return 0; ++ } ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ if (BmiOhPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, NO_MSG); ++ return 0; ++ } ++ break; ++ default: ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Unsupported port type")); ++ return 0; ++ } ++ return GET_UINT32(*p_Reg); ++ } ++ else /* QMI counter */ ++ { ++ /* check that counters are enabled */ ++ if (!(GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) & QMI_PORT_CFG_EN_COUNTERS)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ return 0; ++ } ++ ++ /* Set counter */ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_ENQ_TOTAL): ++ return GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnetfc); ++ case (e_FM_PORT_COUNTERS_DEQ_TOTAL): ++ return GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndtfc); ++ case (e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT): ++ return GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndfdc); ++ case (e_FM_PORT_COUNTERS_DEQ_CONFIRM): ++ return GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndcc); ++ default: ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available")); ++ return 0; ++ } ++ } ++} ++ ++t_Error FM_PORT_ModifyCounter(t_Handle h_FmPort, e_FmPortCounters counter, uint32_t value) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ bool bmiCounter = FALSE; ++ volatile uint32_t *p_Reg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_DEQ_TOTAL): ++ case (e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT): ++ case (e_FM_PORT_COUNTERS_DEQ_CONFIRM ): ++ /* check that counter is available for the port type */ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports")); ++ case (e_FM_PORT_COUNTERS_ENQ_TOTAL): ++ bmiCounter = FALSE; ++ break; ++ default: /* BMI counters (or error - will be checked in BMI routine )*/ ++ bmiCounter = TRUE; ++ break; ++ } ++ ++ if (bmiCounter) ++ { ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ if (BmiRxPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG); ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ if (BmiTxPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG); ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ if (BmiOhPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported port type")); ++ } ++ WRITE_UINT32(*p_Reg, value); ++ } ++ else /* QMI counter */ ++ { ++ ++ /* check that counters are enabled */ ++ if (!(GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) & QMI_PORT_CFG_EN_COUNTERS)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ ++ /* Set counter */ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_ENQ_TOTAL): ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnetfc, value); ++ break; ++ case (e_FM_PORT_COUNTERS_DEQ_TOTAL): ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndtfc, value); ++ break; ++ case (e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT): ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndfdc, value); ++ break; ++ case (e_FM_PORT_COUNTERS_DEQ_CONFIRM): ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndcc, value); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available")); ++ } ++ } ++ ++ return E_OK; ++} ++ ++uint32_t FM_PORT_GetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint32_t extPoolReg; ++ uint8_t tmpPool; ++ uint8_t i; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) && (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for non-Rx ports")); ++ return 0; ++ } ++ ++ for (i=0;ip_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i]); ++ if (extPoolReg & BMI_EXT_BUF_POOL_VALID) ++ { ++ tmpPool = (uint8_t)((extPoolReg & BMI_EXT_BUF_POOL_ID_MASK) >> BMI_EXT_BUF_POOL_ID_SHIFT); ++ if (tmpPool == poolId) ++ { ++ if (extPoolReg & BMI_EXT_BUF_POOL_EN_COUNTER) ++ return GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt[i]); ++ else ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not enabled")); ++ return 0; ++ } ++ } ++ } ++ } ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Pool %d is not used", poolId)); ++ return 0; ++} ++ ++t_Error FM_PORT_ModifyAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, uint32_t value) ++{ ++ t_FmPort *p_FmPort = (t_FmPort *)h_FmPort; ++ uint32_t extPoolReg; ++ uint8_t tmpPool; ++ uint8_t i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) && (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for non-Rx ports")); ++ ++ ++ for (i=0;ip_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i]); ++ if (extPoolReg & BMI_EXT_BUF_POOL_VALID) ++ { ++ tmpPool = (uint8_t)((extPoolReg & BMI_EXT_BUF_POOL_ID_MASK) >> BMI_EXT_BUF_POOL_ID_SHIFT); ++ if (tmpPool == poolId) ++ { ++ if (extPoolReg & BMI_EXT_BUF_POOL_EN_COUNTER) ++ { ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt[i], value); ++ return E_OK; ++ } ++ else ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not enabled")); ++ } ++ } ++ } ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Pool %d is not used", poolId)); ++} ++ ++bool FM_PORT_IsStalled(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err; ++ bool isStalled; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, FALSE); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, FALSE); ++ ++ err = FmIsPortStalled(p_FmPort->h_Fm, p_FmPort->hardwarePortId, &isStalled); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return TRUE; ++ } ++ return isStalled; ++} ++ ++t_Error FM_PORT_ReleaseStalled(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ return FmResumeStalledPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId); ++} ++ ++t_Error FM_PORT_SetRxL4ChecksumVerify(t_Handle h_FmPort, bool l4Checksum) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only")); ++ ++ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne); ++ if (l4Checksum) ++ tmpReg &= ~BMI_PORT_RFNE_FRWD_DCL4C; ++ else ++ tmpReg |= BMI_PORT_RFNE_FRWD_DCL4C; ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, tmpReg); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++/* API Run-time PCD Control unit functions */ ++/*****************************************************************************/ ++ ++#if (DPAA_VERSION >= 11) ++t_Error FM_PORT_VSPAlloc(t_Handle h_FmPort, t_FmPortVSPAllocParams *p_VSPParams) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ volatile uint32_t *p_BmiStorageProfileId = NULL, *p_BmiVspe = NULL; ++ uint32_t tmpReg = 0, tmp = 0; ++ uint16_t hwStoragePrflId; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->h_Fm, E_INVALID_HANDLE); ++ /*for numOfProfiles = 0 don't call this function*/ ++ SANITY_CHECK_RETURN_ERROR(p_VSPParams->numOfProfiles, E_INVALID_VALUE); ++ /*dfltRelativeId should be in the range of numOfProfiles*/ ++ SANITY_CHECK_RETURN_ERROR(IN_RANGE(0, p_VSPParams->dfltRelativeId, (p_VSPParams->numOfProfiles - 1)), E_INVALID_VALUE); ++ /*p_FmPort should be from Rx type or OP*/ ++ SANITY_CHECK_RETURN_ERROR(((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)), E_INVALID_VALUE); ++ /*port should be disabled*/ ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->enabled, E_INVALID_STATE); ++ /*if its called for Rx port relevant Tx Port should be passed (initialized) too and it should be disabled*/ ++ SANITY_CHECK_RETURN_ERROR(((p_VSPParams->h_FmTxPort && ++ !((t_FmPort *)(p_VSPParams->h_FmTxPort))->enabled) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)), E_INVALID_VALUE); ++ /*should be called before SetPCD - this port should be without PCD*/ ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->pcdEngines, E_INVALID_STATE); ++ ++ /*alloc window of VSPs for this port*/ ++ err = FmVSPAllocForPort(p_FmPort->h_Fm, ++ p_FmPort->portType, ++ p_FmPort->portId, ++ p_VSPParams->numOfProfiles); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /*get absolute VSP ID for dfltRelative*/ ++ err = FmVSPGetAbsoluteProfileId(p_FmPort->h_Fm, ++ p_FmPort->portType, ++ p_FmPort->portId, ++ p_VSPParams->dfltRelativeId, ++ &hwStoragePrflId); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err,NO_MSG); ++ ++ /*fill relevant registers for p_FmPort and relative TxPort in the case p_FmPort from Rx type*/ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiStorageProfileId = &(((t_FmPort *)(p_VSPParams->h_FmTxPort))->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfqid); ++ p_BmiVspe = &(((t_FmPort *)(p_VSPParams->h_FmTxPort))->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfne); ++ ++ tmpReg = GET_UINT32(*p_BmiStorageProfileId) & ~BMI_SP_ID_MASK; ++ tmpReg |= (uint32_t)hwStoragePrflId<p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfqid; ++ p_BmiVspe = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpp; ++ hwStoragePrflId = p_VSPParams->dfltRelativeId; ++ break; ++ ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ tmpReg = NIA_ENG_BMI | NIA_BMI_AC_FETCH_ALL_FRAME; ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn,tmpReg); ++ ++ p_BmiStorageProfileId = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofqid; ++ p_BmiVspe = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opp; ++ tmp |= BMI_EBD_EN; ++ break; ++ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only")); ++ } ++ ++ p_FmPort->vspe = TRUE; ++ ++ tmpReg = GET_UINT32(*p_BmiStorageProfileId) & ~BMI_SP_ID_MASK; ++ tmpReg |= (uint32_t)hwStoragePrflId<= 11) */ ++ ++t_Error FM_PORT_PcdPlcrAllocProfiles(t_Handle h_FmPort, uint16_t numOfProfiles) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ ++ p_FmPort->h_FmPcd = FmGetPcdHandle(p_FmPort->h_Fm); ++ ASSERT_COND(p_FmPort->h_FmPcd); ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ if (numOfProfiles) ++ { ++ err = FmPcdPlcrAllocProfiles(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, numOfProfiles); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ /* set the port handle within the PCD policer, even if no profiles defined */ ++ FmPcdPortRegister(p_FmPort->h_FmPcd, h_FmPort, p_FmPort->hardwarePortId); ++ ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_PcdPlcrFreeProfiles(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdPlcrFreeProfiles(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId); ++ ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ if (err) ++ RETURN_ERROR(MAJOR, err,NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_PcdKgModifyInitialScheme (t_Handle h_FmPort, t_FmPcdKgSchemeSelect *p_FmPcdKgScheme) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_BmiHpnia = NULL; ++ uint32_t tmpReg; ++ uint8_t relativeSchemeId; ++ uint8_t physicalSchemeId; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG , E_INVALID_STATE); ++ ++ tmpReg = (uint32_t)((p_FmPort->pcdEngines & FM_PCD_CC)? NIA_KG_CC_EN:0); ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiHpnia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiHpnia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only")); ++ } ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ /* if we want to change to direct scheme, we need to check that this scheme is valid */ ++ if (p_FmPcdKgScheme->direct) ++ { ++ physicalSchemeId = FmPcdKgGetSchemeId(p_FmPcdKgScheme->h_DirectScheme); ++ /* check that this scheme is bound to this port */ ++ if (!(p_FmPort->schemesPerPortVector & (uint32_t)(1 << (31 - (uint32_t)physicalSchemeId)))) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("called with a scheme that is not bound to this port")); ++ } ++ ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPort->h_FmPcd, physicalSchemeId); ++ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("called with invalid Scheme ")); ++ } ++ ++ if (!FmPcdKgIsSchemeValidSw(p_FmPcdKgScheme->h_DirectScheme)) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("called with uninitialized Scheme ")); ++ } ++ ++ WRITE_UINT32(*p_BmiHpnia, NIA_ENG_KG | tmpReg | NIA_KG_DIRECT | (uint32_t)physicalSchemeId); ++ } ++ else /* change to indirect scheme */ ++ WRITE_UINT32(*p_BmiHpnia, NIA_ENG_KG | tmpReg); ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_PcdPlcrModifyInitialProfile (t_Handle h_FmPort, t_Handle h_Profile) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_BmiNia; ++ volatile uint32_t *p_BmiHpnia; ++ uint32_t tmpReg; ++ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile); ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_PLCR , E_INVALID_STATE); ++ ++ /* check relevance of this routine - only when policer is used ++ directly after BMI or Parser */ ++ if ((p_FmPort->pcdEngines & FM_PCD_KG) || (p_FmPort->pcdEngines & FM_PCD_CC)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("relevant only when PCD support mode is e_FM_PCD_SUPPORT_PLCR_ONLY or e_FM_PCD_SUPPORT_PRS_AND_PLCR")); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne; ++ p_BmiHpnia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne; ++ tmpReg = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne; ++ p_BmiHpnia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne; ++ tmpReg = 0; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only")); ++ } ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ if (!FmPcdPlcrIsProfileValid(p_FmPort->h_FmPcd, absoluteProfileId)) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Invalid profile")); ++ } ++ ++ tmpReg = (uint32_t)(NIA_ENG_PLCR | NIA_PLCR_ABSOLUTE | absoluteProfileId); ++ ++ if (p_FmPort->pcdEngines & FM_PCD_PRS) /* e_FM_PCD_SUPPORT_PRS_AND_PLCR */ ++ { ++ /* update BMI HPNIA */ ++ WRITE_UINT32(*p_BmiHpnia, tmpReg); ++ } ++ else /* e_FM_PCD_SUPPORT_PLCR_ONLY */ ++ { ++ /* rfne may contain FDCS bits, so first we read them. */ ++ tmpReg |= (GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK); ++ /* update BMI NIA */ ++ WRITE_UINT32(*p_BmiNia, tmpReg); ++ } ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_PcdCcModifyTree (t_Handle h_FmPort, t_Handle h_CcTree) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ volatile uint32_t *p_BmiCcBase=NULL; ++ volatile uint32_t *p_BmiNia=NULL; ++ uint32_t ccTreePhysOffset; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_VALUE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only")); ++ ++ /* get PCD registers pointers */ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only")); ++ } ++ ++ /* check that current NIA is BMI to BMI */ ++ if ((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) != GET_NIA_BMI_AC_ENQ_FRAME(p_FmPort->h_FmPcd)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("may be called only for ports in BMI-to-BMI state.")); ++ ++ if (p_FmPort->pcdEngines & FM_PCD_CC) ++ { ++ if (p_FmPort->h_IpReassemblyManip) ++ { ++ err = FmPcdCcTreeAddIPR(p_FmPort->h_FmPcd, ++ h_CcTree, ++ NULL, ++ p_FmPort->h_IpReassemblyManip, ++ FALSE); ++ if (err != E_OK) ++ { ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiCcBase = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rccb; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiCcBase = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_occb; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ err = FmPcdCcBindTree(p_FmPort->h_FmPcd, NULL, h_CcTree, &ccTreePhysOffset, h_FmPort); ++ if (err) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ WRITE_UINT32(*p_BmiCcBase, ccTreePhysOffset); ++ ++ p_FmPort->ccTreeId = h_CcTree; ++ RELEASE_LOCK(p_FmPort->lock); ++ } ++ else ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Coarse Classification not defined for this port.")); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_AttachPCD(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only")); ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ if (p_FmPort->h_IpReassemblyTree) ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ ++ err = AttachPCD(h_FmPort); ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return err; ++} ++ ++t_Error FM_PORT_DetachPCD(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only")); ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = DetachPCD(h_FmPort); ++ if (err != E_OK) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ if (p_FmPort->h_IpReassemblyTree) ++ p_FmPort->pcdEngines &= ~FM_PCD_CC; ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetPCD(t_Handle h_FmPort, t_FmPortPcdParams *p_PcdParam) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ t_FmPortPcdParams modifiedPcdParams, *p_PcdParams; ++ t_FmPcdCcTreeParams *p_FmPcdCcTreeParams; ++ t_FmPortPcdCcParams fmPortPcdCcParams; ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only")); ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ p_FmPort->h_FmPcd = FmGetPcdHandle(p_FmPort->h_Fm); ++ ASSERT_COND(p_FmPort->h_FmPcd); ++ ++ memcpy(&modifiedPcdParams, p_PcdParam, sizeof(t_FmPortPcdParams)); ++ p_PcdParams = &modifiedPcdParams; ++ if (p_PcdParams->h_IpReassemblyManip) ++ { ++ if ((p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG) && ++ (p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC) && ++ (p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR) && ++ (p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR)) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("pcdSupport must have KG for supporting IPR")); ++ } ++ p_FmPort->h_IpReassemblyManip = p_PcdParams->h_IpReassemblyManip; ++ if (!p_PcdParams->p_CcParams) ++ { ++ if (!((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_KG) || ++ (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR))) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PCD initialization structure is not consistent with pcdSupport")); ++ } ++ ++ /* No user-tree, need to build internal tree */ ++ p_FmPcdCcTreeParams = (t_FmPcdCcTreeParams*)XX_Malloc(sizeof(t_FmPcdCcTreeParams)); ++ if (!p_FmPcdCcTreeParams) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_FmPcdCcTreeParams")); ++ memset(p_FmPcdCcTreeParams, 0, sizeof(t_FmPcdCcTreeParams)); ++ p_FmPcdCcTreeParams->h_NetEnv = p_PcdParams->h_NetEnv; ++ p_FmPort->h_IpReassemblyTree = FM_PCD_CcRootBuild(p_FmPort->h_FmPcd, p_FmPcdCcTreeParams); ++ ++ if (!p_FmPort->h_IpReassemblyTree) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ XX_Free(p_FmPcdCcTreeParams); ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM_PCD_CcBuildTree for IPR failed")); ++ } ++ if (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_KG) ++ p_PcdParams->pcdSupport = e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC; ++ else ++ p_PcdParams->pcdSupport = e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR; ++ ++ memset(&fmPortPcdCcParams, 0, sizeof(t_FmPortPcdCcParams)); ++ fmPortPcdCcParams.h_CcTree = p_FmPort->h_IpReassemblyTree; ++ p_PcdParams->p_CcParams = &fmPortPcdCcParams; ++ XX_Free(p_FmPcdCcTreeParams); ++ } ++ ++ err = FmPcdCcTreeAddIPR(p_FmPort->h_FmPcd, ++ p_PcdParams->p_CcParams->h_CcTree, ++ p_PcdParams->h_NetEnv, ++ p_FmPort->h_IpReassemblyManip, ++ TRUE); ++ if (err != E_OK) ++ { ++ if (p_FmPort->h_IpReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree); ++ p_FmPort->h_IpReassemblyTree = NULL; ++ } ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ } ++ ++ if (!FmPcdLockTryLockAll(p_FmPort->h_FmPcd)) ++ { ++ if (p_FmPort->h_IpReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree); ++ p_FmPort->h_IpReassemblyTree = NULL; ++ } ++ RELEASE_LOCK(p_FmPort->lock); ++ DBG(TRACE, ("Try LockAll - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = SetPcd(h_FmPort, p_PcdParams); ++ if (err) ++ { ++ if (p_FmPort->h_IpReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree); ++ p_FmPort->h_IpReassemblyTree = NULL; ++ } ++ FmPcdLockUnlockAll(p_FmPort->h_FmPcd); ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ if ((p_FmPort->pcdEngines & FM_PCD_PRS) && ++ (p_PcdParams->p_PrsParams->includeInPrsStatistics)) ++ { ++ err = FmPcdPrsIncludePortInStatistics(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, TRUE); ++ if (err) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_IpReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree); ++ p_FmPort->h_IpReassemblyTree = NULL; ++ } ++ FmPcdLockUnlockAll(p_FmPort->h_FmPcd); ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ p_FmPort->includeInPrsStatistics = TRUE; ++ } ++ ++ FmPcdIncNetEnvOwners(p_FmPort->h_FmPcd, p_FmPort->netEnvId); ++ ++ if (FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd)) ++ { ++ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); ++ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ { ++#if (DPAA_VERSION >= 11) ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#ifdef FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 ++ if ((p_FmPort->fmRevInfo.majorRev < 6) && ++ (p_FmPort->pcdEngines & FM_PCD_KG)) ++ { ++ int i; ++ for (i = 0; ip_KgParams->numOfSchemes; i++) ++ /* The following function must be locked */ ++ FmPcdKgCcGetSetParams(p_FmPort->h_FmPcd, ++ p_PcdParams->p_KgParams->h_Schemes[i], ++ UPDATE_KG_NIA_CC_WA, ++ 0); ++ } ++#endif /* FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 */ ++ ++ /* Set post-bmi-fetch nia */ ++ p_FmPort->savedBmiNia &= BMI_RFNE_FDCS_MASK; ++ p_FmPort->savedBmiNia |= (NIA_FM_CTL_AC_POST_BMI_FETCH | NIA_ENG_FM_CTL); ++ ++ /* Set pre-bmi-fetch nia */ ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN; ++#if (DPAA_VERSION >= 11) ++ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_PRE_BMI_FETCH_FULL_FRAME | NIA_ENG_FM_CTL); ++#else ++ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_PRE_BMI_FETCH_HEADER | NIA_ENG_FM_CTL); ++#endif /* (DPAA_VERSION >= 11) */ ++ if ((err = FmPortGetSetCcParams(p_FmPort, &fmPortGetSetCcParams)) != E_OK) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_IpReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree); ++ p_FmPort->h_IpReassemblyTree = NULL; ++ } ++ FmPcdLockUnlockAll(p_FmPort->h_FmPcd); ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ } ++ ++ FmPcdLockUnlockAll(p_FmPort->h_FmPcd); ++ ++ /* Set pop-to-next-step nia */ ++#if (DPAA_VERSION == 10) ++ if (p_FmPort->fmRevInfo.majorRev < 6) ++ { ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL; ++ } ++ else ++ { ++#endif /* (DPAA_VERSION == 10) */ ++ fmPortGetSetCcParams.getCcParams.type = GET_NIA_FPNE; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_CMNE; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL; ++#if (DPAA_VERSION == 10) ++ } ++#endif /* (DPAA_VERSION == 10) */ ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_IpReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree); ++ p_FmPort->h_IpReassemblyTree = NULL; ++ } ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ /* Set post-bmi-prepare-to-enq nia */ ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_FENE; ++ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_POST_BMI_ENQ | NIA_ENG_FM_CTL); ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_IpReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree); ++ p_FmPort->h_IpReassemblyTree = NULL; ++ } ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ if (p_FmPort->h_IpReassemblyManip) ++ { ++#if (DPAA_VERSION == 10) ++ if (p_FmPort->fmRevInfo.majorRev < 6) ++ { ++ /* Overwrite post-bmi-prepare-to-enq nia */ ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_FENE; ++ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_POST_BMI_ENQ_ORR | NIA_ENG_FM_CTL | NIA_ORDER_RESTOR); ++ fmPortGetSetCcParams.setCcParams.overwrite = TRUE; ++ } ++ else ++ { ++#endif /* (DPAA_VERSION == 10) */ ++ /* Set the ORR bit (for order-restoration) */ ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_FPNE; ++ fmPortGetSetCcParams.setCcParams.nia = fmPortGetSetCcParams.getCcParams.nia | NIA_ORDER_RESTOR; ++#if (DPAA_VERSION == 10) ++ } ++#endif /* (DPAA_VERSION == 10) */ ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_IpReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree); ++ p_FmPort->h_IpReassemblyTree = NULL; ++ } ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ } ++ } ++ else ++ FmPcdLockUnlockAll(p_FmPort->h_FmPcd); ++ ++ err = AttachPCD(h_FmPort); ++ if (err) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_IpReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree); ++ p_FmPort->h_IpReassemblyTree = NULL; ++ } ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return err; ++} ++ ++t_Error FM_PORT_DeletePCD(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only")); ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = DetachPCD(h_FmPort); ++ if (err) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ FmPcdDecNetEnvOwners(p_FmPort->h_FmPcd, p_FmPort->netEnvId); ++ ++ /* we do it anyway, instead of checking if included */ ++ if ((p_FmPort->pcdEngines & FM_PCD_PRS) && ++ p_FmPort->includeInPrsStatistics) ++ { ++ FmPcdPrsIncludePortInStatistics(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, FALSE); ++ p_FmPort->includeInPrsStatistics = FALSE; ++ } ++ ++ if (!FmPcdLockTryLockAll(p_FmPort->h_FmPcd)) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ DBG(TRACE, ("Try LockAll - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = DeletePcd(h_FmPort); ++ FmPcdLockUnlockAll(p_FmPort->h_FmPcd); ++ if (err) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (p_FmPort->h_IpReassemblyTree) ++ { ++ err = FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree); ++ if (err) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ p_FmPort->h_IpReassemblyTree = NULL; ++ } ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return err; ++} ++ ++t_Error FM_PORT_PcdKgBindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_FmPcdKgInterModuleBindPortToSchemes schemeBind; ++ t_Error err = E_OK; ++ uint32_t tmpScmVec=0; ++ int i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG , E_INVALID_STATE); ++ ++ schemeBind.netEnvId = p_FmPort->netEnvId; ++ schemeBind.hardwarePortId = p_FmPort->hardwarePortId; ++ schemeBind.numOfSchemes = p_PortScheme->numOfSchemes; ++ schemeBind.useClsPlan = p_FmPort->useClsPlan; ++ for (i=0; ih_Schemes[i]); ++ /* build vector */ ++ tmpScmVec |= 1 << (31 - (uint32_t)schemeBind.schemesIds[i]); ++ } ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdKgBindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind); ++ if (err == E_OK) ++ p_FmPort->schemesPerPortVector |= tmpScmVec; ++ ++#ifdef FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 ++ if ((FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd)) && ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) && ++ (p_FmPort->fmRevInfo.majorRev < 6)) ++ { ++ for (i=0; inumOfSchemes; i++) ++ FmPcdKgCcGetSetParams(p_FmPort->h_FmPcd, p_PortScheme->h_Schemes[i], UPDATE_KG_NIA_CC_WA, 0); ++ } ++#endif /* FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 */ ++ ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return err; ++} ++ ++t_Error FM_PORT_PcdKgUnbindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_FmPcdKgInterModuleBindPortToSchemes schemeBind; ++ t_Error err = E_OK; ++ uint32_t tmpScmVec=0; ++ int i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG , E_INVALID_STATE); ++ ++ schemeBind.netEnvId = p_FmPort->netEnvId; ++ schemeBind.hardwarePortId = p_FmPort->hardwarePortId; ++ schemeBind.numOfSchemes = p_PortScheme->numOfSchemes; ++ for (i=0; ih_Schemes[i]); ++ /* build vector */ ++ tmpScmVec |= 1 << (31 - (uint32_t)schemeBind.schemesIds[i]); ++ } ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdKgUnbindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind); ++ if (err == E_OK) ++ p_FmPort->schemesPerPortVector &= ~tmpScmVec; ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return err; ++} ++ ++t_Error FM_PORT_PcdPrsModifyStartOffset (t_Handle h_FmPort, t_FmPcdPrsStart *p_FmPcdPrsStart) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_BmiPrsStartOffset = NULL; ++ volatile uint32_t *p_BmiNia = NULL; ++ uint32_t tmpReg; ++ uint8_t hdrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_PRS , E_INVALID_STATE); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpso; ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne; ++ tmpReg = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opso; ++ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne; ++ tmpReg = 0; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only")); ++ } ++ ++ /* check that current NIA is BMI to BMI */ ++ if ((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) != ++ GET_NIA_BMI_AC_ENQ_FRAME(p_FmPort->h_FmPcd)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("may be called only for ports in BMI-to-BMI state.")); ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ /* set the first header */ ++ GET_PRS_HDR_NUM(hdrNum, p_FmPcdPrsStart->firstPrsHdr); ++ if ((hdrNum == ILLEGAL_HDR_NUM) || (hdrNum == NO_HDR_NUM)) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unsupported header.")); ++ } ++ WRITE_UINT32(*p_BmiNia, (uint32_t)(NIA_ENG_PRS | (uint32_t)hdrNum | tmpReg)); ++ ++ /* set start parsing offset */ ++ WRITE_UINT32(*p_BmiPrsStartOffset, ++ (uint32_t)(p_FmPcdPrsStart->parsingOffset + ++ p_FmPort->internalBufferOffset)); ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return E_OK; ++} ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++t_Error FM_PORT_DumpRegs(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ char arr[20]; ++ uint8_t flag; ++ int i=0; ++ ++ DECLARE_DUMP; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortQmiRegs, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortBmiRegs, E_INVALID_HANDLE); ++ ++ memset(arr, 0, sizeof(arr)); ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ strcpy(arr, "OFFLINE-PARSING"); ++ flag = 0; ++ break; ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ strcpy(arr, "HOST-COMMAND"); ++ flag = 0; ++ break; ++ case (e_FM_PORT_TYPE_RX): ++ strcpy(arr, "RX"); ++ flag = 1; ++ break; ++ case (e_FM_PORT_TYPE_RX_10G): ++ strcpy(arr, "RX-10G"); ++ flag = 1; ++ break; ++ case (e_FM_PORT_TYPE_TX): ++ strcpy(arr, "TX"); ++ flag = 2; ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ strcpy(arr, "TX-10G"); ++ flag = 2; ++ break; ++ default: ++ return ERROR_CODE(E_INVALID_VALUE); ++ } ++ ++ DUMP_TITLE(NULL, ++ ("FMan-Port (%s #%d) registers:", ++ arr, p_FmPort->portId)); ++ ++ err = FmDumpPortRegs(p_FmPort->h_Fm, p_FmPort->hardwarePortId); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ DUMP_TITLE(p_FmPort->p_FmPortBmiRegs, ("Bmi Port Regs")); ++ ++ switch (flag) ++ { ++ case (0): ++ ++ DUMP_SUBTITLE(("\n")); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ocfg); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ost); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oda); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oicp); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofdne); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofne); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofca); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofpne); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opso); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opp); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_occb); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oim); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofp); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofed); ++ ++ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oprai), ("fmbm_oprai")); ++ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_PRS_RESULT_NUM_OF_WORDS) ++ { ++ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oprai[i]), sizeof(uint32_t)); ++ } ++ DUMP_SUBTITLE(("\n")); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofqid ); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oefqid); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofsdm ); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofsem ); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofene ); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_orlmts); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_orlmt); ++ ++ { ++#ifndef FM_NO_OP_OBSERVED_POOLS ++ if (p_FmPort->fmRevInfo.majorRev == 4) ++ { ++ DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oebmpi, ("fmbm_oebmpi")); ++ ++ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS) ++ { ++ DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oebmpi[i], sizeof(uint32_t)); ++ } ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ocgm); ++ } ++#endif /* !FM_NO_OP_OBSERVED_POOLS */ ++ } ++ ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ostc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofrc ); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofdc ); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofledc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofufdc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_offc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofwdc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofldec); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opcp); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_occn); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_otuc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oduc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofuc); ++ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_odcfg), ("fmbm_odcfg")); ++ DUMP_SUBSTRUCT_ARRAY(i, 3) ++ { ++ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_odcfg[i]), sizeof(uint32_t)); ++ } ++ DUMP_SUBTITLE(("\n")); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ogpr); ++ break; ++ case (1): ++ DUMP_SUBTITLE(("\n")); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rcfg); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rst); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rda); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfp); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_reth); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfed); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_ricp); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rebm); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfne); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfca); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfpne); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpso); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpp); ++ ++ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rprai), ("fmbm_rprai")); ++ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_PRS_RESULT_NUM_OF_WORDS) ++ { ++ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rprai[i]), sizeof(uint32_t)); ++ } ++ DUMP_SUBTITLE(("\n")); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfqid); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_refqid); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfsdm); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfsem); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfene); ++ DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi, ("fmbm_ebmpi")); ++ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_MAX_NUM_OF_EXT_POOLS) ++ { ++ DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i], sizeof(uint32_t)); ++ } ++ DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt, ("fmbm_acnt")); ++ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_MAX_NUM_OF_EXT_POOLS) ++ { ++ DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt[i], sizeof(uint32_t)); ++ } ++ DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm, ("fmbm_rcgm")); ++ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_NUM_OF_CONGESTION_GRPS/32) ++ { ++ DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm[i], sizeof(uint32_t)); ++ } ++ DUMP_SUBTITLE(("\n")); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rmpd); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rstc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfrc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfbc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rlfc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rffc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfcd); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfldec); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rodc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpcp); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rccn); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rtuc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rrquc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rduc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfuc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpac); ++ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rdcfg), ("fmbm_rdcfg")); ++ DUMP_SUBSTRUCT_ARRAY(i, 3) ++ { ++ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rdcfg[i]), sizeof(uint32_t)); ++ } ++ DUMP_SUBTITLE(("\n")); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rgpr); ++ break; ++ case (2): ++ ++ DUMP_SUBTITLE(("\n")); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tcfg); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tst); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tda); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfp); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfed); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_ticp); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfdne); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfca); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tcfqid); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfeqid); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfene); ++#if (DPAA_VERSION >= 11) ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfne); ++#endif /* (DPAA_VERSION >= 11) */ ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_trlmts); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_trlmt); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tstc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfrc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfdc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfledc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfufdc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tpc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tpcp); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tccn); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_ttuc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_ttcquc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tduc); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfuc); ++ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tdcfg), ("fmbm_tdcfg")); ++ DUMP_SUBSTRUCT_ARRAY(i, 3) ++ { ++ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tdcfg[i]), sizeof(uint32_t)); ++ } ++ DUMP_SUBTITLE(("\n")); ++ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tgpr); ++ break; ++ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid flag")); ++ } ++ ++ DUMP_TITLE(p_FmPort->p_FmPortQmiRegs, ("Qmi Port Regs")); ++ ++ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnc); ++ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pns); ++ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnts); ++ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnen); ++ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnetfc); ++ ++ if (flag !=1) ++ { ++ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndn); ++ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndc); ++ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndtfc); ++ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndfdc); ++ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndcc); ++ } ++ ++ return E_OK; ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++t_Error FM_PORT_AddCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ bool tmpArray[FM_PORT_NUM_OF_CONGESTION_GRPS], opPort; ++ uint8_t priorityTmpArray[FM_PORT_NUM_OF_CONGESTION_GRPS]; ++ int i; ++ uint8_t mod; ++ uint32_t tmpReg = 0; ++#if (DPAA_VERSION >= 11) ++ int j; ++ t_Error err; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ ++ /* un-necessary check of the indexes; probably will be needed in the future when there ++ will be more CGs available .... ++ for (i=0; inumOfCongestionGrpsToConsider; i++) ++ if (p_CongestionGrps->congestionGrpsToConsider[i] >= FM_PORT_NUM_OF_CONGESTION_GRPS) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("CG id!")); ++ */ ++ ++#ifdef FM_NO_OP_OBSERVED_CGS ++ if ((p_FmPort->fmRevInfo.majorRev != 4) && ++ (p_FmPort->fmRevInfo.majorRev < 6)) ++ { ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx ports only")); ++ } ++ else ++#endif /* FM_NO_OP_OBSERVED_CGS */ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx & OP ports only")); ++ ++ opPort = (bool)((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ? TRUE:FALSE); ++ ++ /* to minimize memory access (groups may belong to the same regsiter, and may ++ be out of order), we first collect all information into a 256 booleans array, ++ representing each possible group. */ ++ ++ memset(&tmpArray, 0, FM_PORT_NUM_OF_CONGESTION_GRPS*sizeof(bool)); ++ memset(&priorityTmpArray, 0, FM_PORT_NUM_OF_CONGESTION_GRPS*sizeof(uint8_t)); ++ ++ for (i=0; inumOfCongestionGrpsToConsider; i++) ++ { ++ tmpArray[p_CongestionGrps->congestionGrpsToConsider[i]] = TRUE; ++ ++#if (DPAA_VERSION >= 11) ++ for (j=0;jpfcPrioritiesEn[i][j]) ++ priorityTmpArray[p_CongestionGrps->congestionGrpsToConsider[i]] |= (0x01 <<(FM_MAX_NUM_OF_PFC_PRIORITIES-j-1)); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ for (i=0; ip_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocgm): ++ GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm[FM_PORT_CG_REG_NUM(i)]); ++ ++ /* set in the register, the bit representing the relevant congestion group. */ ++ ++ if (tmpArray[i]) ++ { ++ tmpReg |= (0x00000001 << (uint32_t)mod); ++ ++#if (DPAA_VERSION >= 11) ++ err = FmSetCongestionGroupPFCpriority(p_FmPort->h_Fm,i,priorityTmpArray[i]); ++ if (err) ++ return err; ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ if (mod == 31) /* last in a 32 bunch of congestion groups - write the corresponding register */ ++ { ++ if (opPort) ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocgm, tmpReg); ++ else ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm[FM_PORT_CG_REG_NUM(i)], tmpReg); ++ } ++ } ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_RemoveCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ bool tmpArray[FM_PORT_NUM_OF_CONGESTION_GRPS], opPort; ++ int i; ++ uint8_t mod; ++ uint32_t tmpReg = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ ++ /* un-necessary check of the indexes; probably will be needed in the future when there ++ will be more CGs available .... ++ for (i=0; inumOfCongestionGrpsToConsider; i++) ++ if (p_CongestionGrps->congestionGrpsToConsider[i] >= FM_PORT_NUM_OF_CONGESTION_GRPS) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("CG id!")); ++ */ ++ ++#ifdef FM_NO_OP_OBSERVED_CGS ++ if ((p_FmPort->fmRevInfo.majorRev != 4) && ++ (p_FmPort->fmRevInfo.majorRev < 6)) ++ { ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx ports only")); ++ } ++ else ++#endif /* FM_NO_OP_OBSERVED_CGS */ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx & OP ports only")); ++ ++ opPort = (bool)((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ? TRUE:FALSE); ++ ++ /* to minimize memory access (groups may belong to the same regsiter, and may ++ be out of order), we first collect all information into a 256 booleans array, ++ representing each possible group. */ ++ memset(&tmpArray, 0, FM_PORT_NUM_OF_CONGESTION_GRPS*sizeof(bool)); ++ for (i=0; inumOfCongestionGrpsToConsider; i++) ++ tmpArray[p_CongestionGrps->congestionGrpsToConsider[i]] = TRUE; ++ ++ for (i=0; ip_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocgm): ++ GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm[FM_PORT_CG_REG_NUM(i)]); ++ ++ /* set in the register, the bit representing the relevant congestion group. */ ++ if (tmpArray[i]) ++ { ++ tmpReg &= ~(0x00000001 << (uint32_t)mod); ++ ++#if (DPAA_VERSION >= 11) ++ { ++ t_Error err = FmSetCongestionGroupPFCpriority(p_FmPort->h_Fm, i, 0); ++ if (err) ++ return err; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ if (mod == 31) /* last in a 32 bunch of congestion groups - write the corresponding register */ ++ { ++ if (opPort) ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocgm, tmpReg); ++ else ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm[FM_PORT_CG_REG_NUM(i)], tmpReg); ++ } ++ } ++ ++ return E_OK; ++} ++ ++#if (DPAA_VERSION >= 11) ++#endif /* (DPAA_VERSION >= 11) */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Port/fm_port.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/Port/fm_port.h +new file mode 100644 +index 0000000..5c01851 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Port/fm_port.h +@@ -0,0 +1,942 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_port.h ++ ++ @Description FM Port internal structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_PORT_H ++#define __FM_PORT_H ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "fm_port_ext.h" ++ ++#include "fm_common.h" ++#include "fm_sp_common.h" ++ ++ ++#define __ERR_MODULE__ MODULE_FM_PORT ++ ++ ++#define MIN_EXT_BUF_SIZE 64 ++#define DATA_ALIGNMENT 64 ++#define MAX_LIODN_OFFSET 64 ++ ++/**************************************************************************//** ++ @Description Memory Map defines ++*//***************************************************************************/ ++#define BMI_PORT_REGS_OFFSET 0 ++#define QMI_PORT_REGS_OFFSET 0x400 ++#define PRS_PORT_REGS_OFFSET 0x800 ++ ++/**************************************************************************//** ++ @Description defaults ++*//***************************************************************************/ ++#define DEFAULT_PORT_deqHighPriority_1G FALSE ++#define DEFAULT_PORT_deqHighPriority_10G TRUE ++#define DEFAULT_PORT_deqType e_FM_PORT_DEQ_TYPE1 ++#define DEFAULT_PORT_deqPrefetchOption e_FM_PORT_DEQ_FULL_PREFETCH ++#define DEFAULT_PORT_deqPrefetchOption_HC e_FM_PORT_DEQ_NO_PREFETCH ++#define DEFAULT_PORT_deqByteCnt_10G 0x1400 ++#define DEFAULT_PORT_deqByteCnt_1G 0x400 ++#define DEFAULT_PORT_bufferPrefixContent_privDataSize DEFAULT_FM_SP_bufferPrefixContent_privDataSize ++#define DEFAULT_PORT_bufferPrefixContent_passPrsResult DEFAULT_FM_SP_bufferPrefixContent_passPrsResult ++#define DEFAULT_PORT_bufferPrefixContent_passTimeStamp DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp ++#define DEFAULT_PORT_bufferPrefixContent_allOtherPCDInfo DEFAULT_FM_SP_bufferPrefixContent_allOtherPCDInfo ++#define DEFAULT_PORT_bufferPrefixContent_dataAlign DEFAULT_FM_SP_bufferPrefixContent_dataAlign ++#define DEFAULT_PORT_cheksumLastBytesIgnore 0 ++#define DEFAULT_PORT_cutBytesFromEnd 4 ++#define DEFAULT_PORT_txFifoMinFillLevel 0 ++#define DEFAULT_PORT_fifoDeqPipelineDepth_IM 2 ++#define DEFAULT_PORT_fifoDeqPipelineDepth_1G 1 ++#define DEFAULT_PORT_fifoDeqPipelineDepth_10G 4 ++#define DEFAULT_PORT_fifoDeqPipelineDepth_OH 2 ++ ++#define DEFAULT_PORT_txFifoLowComfLevel (5*KILOBYTE) ++#define DEFAULT_PORT_rxFifoPriElevationLevel BMI_MAX_FIFO_SIZE ++#define DEFAULT_PORT_rxFifoThreshold (BMI_MAX_FIFO_SIZE*3/4) ++#define DEFAULT_PORT_frmDiscardOverride FALSE ++ ++#define DEFAULT_PORT_dmaSwapData DEFAULT_FM_SP_dmaSwapData ++#define DEFAULT_PORT_dmaIntContextCacheAttr DEFAULT_FM_SP_dmaIntContextCacheAttr ++#define DEFAULT_PORT_dmaHeaderCacheAttr DEFAULT_FM_SP_dmaHeaderCacheAttr ++#define DEFAULT_PORT_dmaScatterGatherCacheAttr DEFAULT_FM_SP_dmaScatterGatherCacheAttr ++#define DEFAULT_PORT_dmaWriteOptimize DEFAULT_FM_SP_dmaWriteOptimize ++ ++#define DEFAULT_PORT_noScatherGather DEFAULT_FM_SP_noScatherGather ++#define DEFAULT_PORT_forwardIntContextReuse FALSE ++#define DEFAULT_PORT_BufMargins_startMargins 32 ++#define DEFAULT_PORT_BufMargins_endMargins 0 ++#define DEFAULT_PORT_syncReq TRUE ++#define DEFAULT_PORT_syncReqForHc FALSE ++#define DEFAULT_PORT_color e_FM_PORT_COLOR_GREEN ++#define DEFAULT_PORT_errorsToDiscard FM_PORT_FRM_ERR_CLS_DISCARD ++/* #define DEFAULT_PORT_dualRateLimitScaleDown e_FM_PORT_DUAL_RATE_LIMITER_NONE */ ++/* #define DEFAULT_PORT_rateLimitBurstSizeHighGranularity FALSE */ ++#define DEFAULT_PORT_exception IM_EV_BSY ++#define DEFAULT_PORT_maxFrameLength 9600 ++ ++#define DEFAULT_notSupported 0xff ++ ++/* Host command port MUST NOT be changed to more than 1 !!! */ ++#define DEFAULT_PORT_numOfTasks(type) \ ++ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \ ++ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 16 : \ ++ ((((type) == e_FM_PORT_TYPE_RX) || \ ++ ((type) == e_FM_PORT_TYPE_TX) || \ ++ ((type) == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ? 3 : 1)) ++ ++#define DEFAULT_PORT_extraNumOfTasks(type) \ ++ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \ ++ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 8 : \ ++ ((((type) == e_FM_PORT_TYPE_RX) || \ ++ ((type) == e_FM_PORT_TYPE_TX)) ? 2 : 0)) ++ ++#define DEFAULT_PORT_numOfOpenDmas(type, rev) \ ++ (uint32_t)((((type) == e_FM_PORT_TYPE_TX_10G) || \ ++ ((type) == e_FM_PORT_TYPE_RX_10G)) ? 8 : ((rev>=6) ? 2 : 1)) ++ ++#define DEFAULT_PORT_extraNumOfOpenDmas(type) \ ++ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \ ++ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 8 : \ ++ ((((type) == e_FM_PORT_TYPE_RX) || \ ++ ((type) == e_FM_PORT_TYPE_TX)) ? 1 : 0)) ++ ++#define DEFAULT_PORT_numOfFifoBufs(type) \ ++ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \ ++ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 48 : \ ++ ((((type) == e_FM_PORT_TYPE_RX) || \ ++ ((type) == e_FM_PORT_TYPE_TX)) ? 44 : 8)) ++ ++#define DEFAULT_PORT_extraNumOfFifoBufs 0 ++ ++#define DEFAULT_PORT_txBdRingLength 16 ++#define DEFAULT_PORT_rxBdRingLength 128 ++#define DEFAULT_PORT_ImfwExtStructsMemId 0 ++#define DEFAULT_PORT_ImfwExtStructsMemAttr MEMORY_ATTR_CACHEABLE ++ ++#define FM_PORT_CG_REG_NUM(_cgId) (((FM_PORT_NUM_OF_CONGESTION_GRPS/32)-1)-_cgId/32) ++ ++/**************************************************************************//** ++ @Collection PCD Engines ++*//***************************************************************************/ ++typedef uint32_t fmPcdEngines_t; /**< options as defined below: */ ++ ++#define FM_PCD_NONE 0 /**< No PCD Engine indicated */ ++#define FM_PCD_PRS 0x80000000 /**< Parser indicated */ ++#define FM_PCD_KG 0x40000000 /**< Keygen indicated */ ++#define FM_PCD_CC 0x20000000 /**< Coarse classification indicated */ ++#define FM_PCD_PLCR 0x10000000 /**< Policer indicated */ ++#define FM_PCD_MANIP 0x08000000 /**< Manipulation indicated */ ++/* @} */ ++ ++#define FM_PORT_MAX_NUM_OF_EXT_POOLS_ALL_INTEGRATIONS 8 ++#define FM_PORT_MAX_NUM_OF_CONGESTION_GRPS_ALL_INTEGRATIONS 256 ++#define FM_PORT_CG_REG_NUM(_cgId) (((FM_PORT_NUM_OF_CONGESTION_GRPS/32)-1)-_cgId/32) ++ ++#define FM_OH_PORT_ID 0 ++ ++/***********************************************************************/ ++/* SW parser IP-fragmentation labels (offsets) */ ++/***********************************************************************/ ++#if (DPAA_VERSION == 10) ++#define IP_FRAG_SW_PATCH_IPv4_SIZE 0x025 ++#define IP_FRAG_SW_PATCH_IPv4_LABEL 0x300 ++#else ++#define IP_FRAG_SW_PATCH_IPv4_SIZE 0x046 ++#define IP_FRAG_SW_PATCH_IPv4_LABEL 0x2E0 ++#endif /* (DPAA_VERSION == 10) */ ++#define IP_FRAG_SW_PATCH_IPv6_LABEL \ ++ (IP_FRAG_SW_PATCH_IPv4_LABEL + IP_FRAG_SW_PATCH_IPv4_SIZE) ++ ++#ifdef FM_CAPWAP_SUPPORT ++#define UDP_LITE_SW_PATCH_LABEL 0x2E0 ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++/**************************************************************************//** ++ @Description Memory Mapped Registers ++*//***************************************************************************/ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++typedef _Packed struct ++{ ++ volatile uint32_t fmbm_rcfg; /**< Rx Configuration */ ++ volatile uint32_t fmbm_rst; /**< Rx Status */ ++ volatile uint32_t fmbm_rda; /**< Rx DMA attributes*/ ++ volatile uint32_t fmbm_rfp; /**< Rx FIFO Parameters*/ ++ volatile uint32_t fmbm_rfed; /**< Rx Frame End Data*/ ++ volatile uint32_t fmbm_ricp; /**< Rx Internal Context Parameters*/ ++ volatile uint32_t fmbm_rim; /**< Rx Internal Buffer Margins*/ ++ volatile uint32_t fmbm_rebm; /**< Rx External Buffer Margins*/ ++ volatile uint32_t fmbm_rfne; /**< Rx Frame Next Engine*/ ++ volatile uint32_t fmbm_rfca; /**< Rx Frame Command Attributes.*/ ++ volatile uint32_t fmbm_rfpne; /**< Rx Frame Parser Next Engine*/ ++ volatile uint32_t fmbm_rpso; /**< Rx Parse Start Offset*/ ++ volatile uint32_t fmbm_rpp; /**< Rx Policer Profile */ ++ volatile uint32_t fmbm_rccb; /**< Rx Coarse Classification Base */ ++ volatile uint32_t fmbm_reth; /**< Rx Excessive Threshold */ ++ volatile uint32_t reserved1[0x01];/**< (0x03C) */ ++ volatile uint32_t fmbm_rprai[FM_PORT_PRS_RESULT_NUM_OF_WORDS]; ++ /**< Rx Parse Results Array Initialization*/ ++ volatile uint32_t fmbm_rfqid; /**< Rx Frame Queue ID*/ ++ volatile uint32_t fmbm_refqid; /**< Rx Error Frame Queue ID*/ ++ volatile uint32_t fmbm_rfsdm; /**< Rx Frame Status Discard Mask*/ ++ volatile uint32_t fmbm_rfsem; /**< Rx Frame Status Error Mask*/ ++ volatile uint32_t fmbm_rfene; /**< Rx Frame Enqueue Next Engine */ ++ volatile uint32_t reserved2[0x02];/**< (0x074-0x078) */ ++ volatile uint32_t fmbm_rcmne; /**< Rx Frame Continuous Mode Next Engine */ ++ volatile uint32_t reserved3[0x20];/**< (0x080 0x0FF) */ ++ volatile uint32_t fmbm_ebmpi[FM_PORT_MAX_NUM_OF_EXT_POOLS_ALL_INTEGRATIONS]; ++ /**< Buffer Manager pool Information-*/ ++ volatile uint32_t fmbm_acnt[FM_PORT_MAX_NUM_OF_EXT_POOLS_ALL_INTEGRATIONS]; ++ /**< Allocate Counter-*/ ++ volatile uint32_t reserved4[0x08]; ++ /**< 0x130/0x140 - 0x15F reserved -*/ ++ volatile uint32_t fmbm_rcgm[FM_PORT_MAX_NUM_OF_CONGESTION_GRPS_ALL_INTEGRATIONS/32]; ++ /**< Congestion Group Map*/ ++ volatile uint32_t fmbm_rmpd; /**< BM Pool Depletion */ ++ volatile uint32_t reserved5[0x1F];/**< (0x184 0x1FF) */ ++ volatile uint32_t fmbm_rstc; /**< Rx Statistics Counters*/ ++ volatile uint32_t fmbm_rfrc; /**< Rx Frame Counter*/ ++ volatile uint32_t fmbm_rfbc; /**< Rx Bad Frames Counter*/ ++ volatile uint32_t fmbm_rlfc; /**< Rx Large Frames Counter*/ ++ volatile uint32_t fmbm_rffc; /**< Rx Filter Frames Counter*/ ++ volatile uint32_t fmbm_rfcd; /**< Rx Frame Discard Counter*/ ++ volatile uint32_t fmbm_rfldec; /**< Rx Frames List DMA Error Counter*/ ++ volatile uint32_t fmbm_rodc; /**< Rx Out of Buffers Discard Counter-*/ ++ volatile uint32_t fmbm_rbdc; /**< Rx Buffers Deallocate Counter-*/ ++ volatile uint32_t fmbm_rpec; /**< Rx RX Prepare to enqueue Counter-*/ ++ volatile uint32_t reserved6[0x16];/**< (0x228 0x27F) */ ++ volatile uint32_t fmbm_rpc; /**< Rx Performance Counters*/ ++ volatile uint32_t fmbm_rpcp; /**< Rx Performance Count Parameters*/ ++ volatile uint32_t fmbm_rccn; /**< Rx Cycle Counter*/ ++ volatile uint32_t fmbm_rtuc; /**< Rx Tasks Utilization Counter*/ ++ volatile uint32_t fmbm_rrquc; /**< Rx Receive Queue Utilization Counter*/ ++ volatile uint32_t fmbm_rduc; /**< Rx DMA Utilization Counter*/ ++ volatile uint32_t fmbm_rfuc; /**< Rx FIFO Utilization Counter*/ ++ volatile uint32_t fmbm_rpac; /**< Rx Pause Activation Counter*/ ++ volatile uint32_t reserved7[0x18];/**< (0x2A0-0x2FF) */ ++ volatile uint32_t fmbm_rdcfg[0x3];/**< Rx Debug-*/ ++ volatile uint32_t fmbm_rgpr; /**< Rx General Purpose Register. */ ++ volatile uint32_t reserved8[0x3a];/**< (0x310-0x3FF) */ ++} _PackedType t_FmPortRxBmiRegs; ++ ++typedef _Packed struct ++{ ++ volatile uint32_t fmbm_tcfg; /**< Tx Configuration */ ++ volatile uint32_t fmbm_tst; /**< Tx Status */ ++ volatile uint32_t fmbm_tda; /**< Tx DMA attributes */ ++ volatile uint32_t fmbm_tfp; /**< Tx FIFO Parameters */ ++ volatile uint32_t fmbm_tfed; /**< Tx Frame End Data */ ++ volatile uint32_t fmbm_ticp; /**< Tx Internal Context Parameters */ ++ volatile uint32_t fmbm_tfdne; /**< Tx Frame Dequeue Next Engine. */ ++ volatile uint32_t fmbm_tfca; /**< Tx Frame Command attribute. */ ++ volatile uint32_t fmbm_tcfqid; /**< Tx Confirmation Frame Queue ID. */ ++ volatile uint32_t fmbm_tfeqid; /**< Tx Frame Error Queue ID */ ++ volatile uint32_t fmbm_tfene; /**< Tx Frame Enqueue Next Engine */ ++ volatile uint32_t fmbm_trlmts; /**< Tx Rate Limiter Scale */ ++ volatile uint32_t fmbm_trlmt; /**< Tx Rate Limiter */ ++ volatile uint32_t fmbm_tccb; /**< Tx Coarse Classification Base */ ++ volatile uint32_t reserved0[0x0e];/**< (0x038-0x070) */ ++ volatile uint32_t fmbm_tfne; /**< Tx Frame Next Engine */ ++ volatile uint32_t reserved1[0x02];/**< (0x074-0x7C) */ ++ volatile uint32_t fmbm_tcmne; /**< Tx Frame Continuous Mode Next Engine */ ++ volatile uint32_t reserved2[0x60];/**< (0x080-0x200) */ ++ volatile uint32_t fmbm_tstc; /**< Tx Statistics Counters */ ++ volatile uint32_t fmbm_tfrc; /**< Tx Frame Counter */ ++ volatile uint32_t fmbm_tfdc; /**< Tx Frames Discard Counter */ ++ volatile uint32_t fmbm_tfledc; /**< Tx Frame Length error discard counter */ ++ volatile uint32_t fmbm_tfufdc; /**< Tx Frame unsupported format discard Counter */ ++ volatile uint32_t fmbm_tbdc; /**< Tx Buffers Deallocate Counter */ ++ volatile uint32_t reserved3[0x1A];/**< (0x218-0x280) */ ++ volatile uint32_t fmbm_tpc; /**< Tx Performance Counters*/ ++ volatile uint32_t fmbm_tpcp; /**< Tx Performance Count Parameters*/ ++ volatile uint32_t fmbm_tccn; /**< Tx Cycle Counter*/ ++ volatile uint32_t fmbm_ttuc; /**< Tx Tasks Utilization Counter*/ ++ volatile uint32_t fmbm_ttcquc; /**< Tx Transmit Confirm Queue Utilization Counter*/ ++ volatile uint32_t fmbm_tduc; /**< Tx DMA Utilization Counter*/ ++ volatile uint32_t fmbm_tfuc; /**< Tx FIFO Utilization Counter*/ ++ volatile uint32_t reserved4[16]; /**< (0x29C-0x2FF) */ ++ volatile uint32_t fmbm_tdcfg[0x3];/**< Tx Debug-*/ ++ volatile uint32_t fmbm_tgpr; /**< O/H General Purpose Register */ ++ volatile uint32_t reserved5[0x3a];/**< (0x310-0x3FF) */ ++} _PackedType t_FmPortTxBmiRegs; ++ ++typedef _Packed struct ++{ ++ volatile uint32_t fmbm_ocfg; /**< O/H Configuration */ ++ volatile uint32_t fmbm_ost; /**< O/H Status */ ++ volatile uint32_t fmbm_oda; /**< O/H DMA attributes */ ++ volatile uint32_t fmbm_oicp; /**< O/H Internal Context Parameters */ ++ volatile uint32_t fmbm_ofdne; /**< O/H Frame Dequeue Next Engine */ ++ volatile uint32_t fmbm_ofne; /**< O/H Frame Next Engine */ ++ volatile uint32_t fmbm_ofca; /**< O/H Frame Command Attributes. */ ++ volatile uint32_t fmbm_ofpne; /**< O/H Frame Parser Next Engine */ ++ volatile uint32_t fmbm_opso; /**< O/H Parse Start Offset */ ++ volatile uint32_t fmbm_opp; /**< O/H Policer Profile */ ++ volatile uint32_t fmbm_occb; /**< O/H Coarse Classification base */ ++ volatile uint32_t fmbm_oim; /**< O/H Internal margins*/ ++ volatile uint32_t fmbm_ofp; /**< O/H Fifo Parameters*/ ++ volatile uint32_t fmbm_ofed; /**< O/H Frame End Data*/ ++ volatile uint32_t reserved0[2]; /**< (0x038 - 0x03F) */ ++ volatile uint32_t fmbm_oprai[FM_PORT_PRS_RESULT_NUM_OF_WORDS]; ++ /**< O/H Parse Results Array Initialization */ ++ volatile uint32_t fmbm_ofqid; /**< O/H Frame Queue ID */ ++ volatile uint32_t fmbm_oefqid; /**< O/H Error Frame Queue ID */ ++ volatile uint32_t fmbm_ofsdm; /**< O/H Frame Status Discard Mask */ ++ volatile uint32_t fmbm_ofsem; /**< O/H Frame Status Error Mask */ ++ volatile uint32_t fmbm_ofene; /**< O/H Frame Enqueue Next Engine */ ++ volatile uint32_t fmbm_orlmts; /**< O/H Rate Limiter Scale */ ++ volatile uint32_t fmbm_orlmt; /**< O/H Rate Limiter */ ++ volatile uint32_t fmbm_ocmne; /**< O/H Continuous Mode Next Engine */ ++ volatile uint32_t reserved1[0x20];/**< (0x080 - 0x0FF) */ ++ volatile uint32_t fmbm_oebmpi[2]; /**< Buffer Manager Observed Pool Information */ ++ volatile uint32_t reserved2[0x16];/**< (0x108 - 0x15F) */ ++ volatile uint32_t fmbm_ocgm; /**< Observed Congestion Group Map */ ++ volatile uint32_t reserved3[0x7]; /**< (0x164 - 0x17F) */ ++ volatile uint32_t fmbm_ompd; /**< Observed BMan Pool Depletion */ ++ volatile uint32_t reserved4[0x1F];/**< (0x184 - 0x1FF) */ ++ volatile uint32_t fmbm_ostc; /**< O/H Statistics Counters */ ++ volatile uint32_t fmbm_ofrc; /**< O/H Frame Counter */ ++ volatile uint32_t fmbm_ofdc; /**< O/H Frames Discard Counter */ ++ volatile uint32_t fmbm_ofledc; /**< O/H Frames Length Error Discard Counter */ ++ volatile uint32_t fmbm_ofufdc; /**< O/H Frames Unsupported Format Discard Counter */ ++ volatile uint32_t fmbm_offc; /**< O/H Filter Frames Counter */ ++ volatile uint32_t fmbm_ofwdc; /**< - Rx Frames WRED Discard Counter */ ++ volatile uint32_t fmbm_ofldec; /**< O/H Frames List DMA Error Counter */ ++ volatile uint32_t fmbm_obdc; /**< O/H Buffers Deallocate Counter */ ++ volatile uint32_t fmbm_oodc; /**< O/H Out of Buffers Discard Counter */ ++ volatile uint32_t fmbm_opec; /**< O/H Prepare to enqueue Counter */ ++ volatile uint32_t reserved5[0x15];/**< ( - 0x27F) */ ++ volatile uint32_t fmbm_opc; /**< O/H Performance Counters */ ++ volatile uint32_t fmbm_opcp; /**< O/H Performance Count Parameters */ ++ volatile uint32_t fmbm_occn; /**< O/H Cycle Counter */ ++ volatile uint32_t fmbm_otuc; /**< O/H Tasks Utilization Counter */ ++ volatile uint32_t fmbm_oduc; /**< O/H DMA Utilization Counter */ ++ volatile uint32_t fmbm_ofuc; /**< O/H FIFO Utilization Counter */ ++ volatile uint32_t reserved6[26]; /**< (0x298-0x2FF) */ ++ volatile uint32_t fmbm_odcfg[0x3];/**< O/H Debug (only 1 in P1023) */ ++ volatile uint32_t fmbm_ogpr; /**< O/H General Purpose Register. */ ++ volatile uint32_t reserved7[0x3a];/**< (0x310 0x3FF) */ ++} _PackedType t_FmPortOhBmiRegs; ++ ++typedef _Packed union ++{ ++ t_FmPortRxBmiRegs rxPortBmiRegs; ++ t_FmPortTxBmiRegs txPortBmiRegs; ++ t_FmPortOhBmiRegs ohPortBmiRegs; ++} _PackedType u_FmPortBmiRegs; ++ ++typedef _Packed struct ++{ ++ volatile uint32_t reserved1[2]; /**< 0xn024 - 0x02B */ ++ volatile uint32_t fmqm_pndn; /**< PortID n Dequeue NIA Register */ ++ volatile uint32_t fmqm_pndc; /**< PortID n Dequeue Config Register */ ++ volatile uint32_t fmqm_pndtfc; /**< PortID n Dequeue Total Frame Counter */ ++ volatile uint32_t fmqm_pndfdc; /**< PortID n Dequeue FQID from Default Counter */ ++ volatile uint32_t fmqm_pndcc; /**< PortID n Dequeue Confirm Counter */ ++} _PackedType t_FmPortNonRxQmiRegs; ++ ++typedef _Packed struct ++{ ++ volatile uint32_t fmqm_pnc; /**< PortID n Configuration Register */ ++ volatile uint32_t fmqm_pns; /**< PortID n Status Register */ ++ volatile uint32_t fmqm_pnts; /**< PortID n Task Status Register */ ++ volatile uint32_t reserved0[4]; /**< 0xn00C - 0xn01B */ ++ volatile uint32_t fmqm_pnen; /**< PortID n Enqueue NIA Register */ ++ volatile uint32_t fmqm_pnetfc; /**< PortID n Enqueue Total Frame Counter */ ++ t_FmPortNonRxQmiRegs nonRxQmiRegs; /**< Registers for Tx Hc & Op ports */ ++} _PackedType t_FmPortQmiRegs; ++ ++typedef _Packed struct ++{ ++ _Packed struct ++ { ++ volatile uint32_t softSeqAttach; /**< Soft Sequence Attachment */ ++ volatile uint32_t lcv; /**< Line-up Enable Confirmation Mask */ ++ } _PackedType hdrs[FM_PCD_PRS_NUM_OF_HDRS]; ++ volatile uint8_t reserved0[0x378]; ++ volatile uint32_t pcac; /**< Parse Internal Memory Configuration Access Control Register */ ++ volatile uint32_t pctpid; /**< Parse Internal Memory Configured TPID Register */ ++} _PackedType t_FmPortPrsRegs; ++ ++/**************************************************************************//* ++ @Description Basic buffer descriptor (BD) structure ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ volatile uint16_t status; ++ volatile uint16_t length; ++ volatile uint8_t reserved0[0x6]; ++ volatile uint8_t reserved1[0x1]; ++ volatile t_FmPhysAddr buff; ++} _PackedType t_FmImBd; ++ ++typedef _Packed struct ++{ ++ volatile uint16_t gen; /**< tbd */ ++ volatile uint8_t reserved0[0x1]; ++ volatile t_FmPhysAddr bdRingBase; /**< tbd */ ++ volatile uint16_t bdRingSize; /**< tbd */ ++ volatile uint16_t offsetIn; /**< tbd */ ++ volatile uint16_t offsetOut; /**< tbd */ ++ volatile uint8_t reserved1[0x12]; /**< 0x0e - 0x1f */ ++} _PackedType t_FmPortImQd; ++ ++typedef _Packed struct ++{ ++ volatile uint32_t mode; /**< Mode register */ ++ volatile uint32_t rxQdPtr; /**< tbd */ ++ volatile uint32_t txQdPtr; /**< tbd */ ++ volatile uint16_t mrblr; /**< tbd */ ++ volatile uint16_t rxQdBsyCnt; /**< tbd */ ++ volatile uint8_t reserved0[0x10]; /**< 0x10 - 0x1f */ ++ t_FmPortImQd rxQd; ++ t_FmPortImQd txQd; ++ volatile uint8_t reserved1[0xa0]; /**< 0x60 - 0xff */ ++} _PackedType t_FmPortImPram; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/**************************************************************************//** ++ @Description Registers bit fields ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description BMI defines ++*//***************************************************************************/ ++#if (DPAA_VERSION >= 11) ++#define BMI_SP_ID_MASK 0xff000000 ++#define BMI_SP_ID_SHIFT 24 ++#define BMI_SP_EN 0x01000000 ++#define BMI_EBD_EN 0x80000000 ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#define BMI_PORT_CFG_EN 0x80000000 ++#define BMI_PORT_CFG_EN_MACSEC 0x00800000 ++#define BMI_PORT_CFG_FDOVR 0x02000000 ++#define BMI_PORT_CFG_IM 0x01000000 ++#define BMI_PORT_STATUS_BSY 0x80000000 ++#define BMI_COUNTERS_EN 0x80000000 ++#define BMI_DMA_ATTR_WRITE_OPTIMIZE FM_SP_DMA_ATTR_WRITE_OPTIMIZE ++ ++#define BMI_PORT_RFNE_FRWD_DCL4C 0x10000000 ++#define BMI_PORT_RFNE_FRWD_RPD 0x40000000 ++#define BMI_RFNE_FDCS_MASK 0xFF000000 ++ ++#define BMI_CMD_MR_LEAC 0x00200000 ++#define BMI_CMD_MR_SLEAC 0x00100000 ++#define BMI_CMD_MR_MA 0x00080000 ++#define BMI_CMD_MR_DEAS 0x00040000 ++#define BMI_CMD_TX_MR_DEF (0) ++#define BMI_CMD_RX_MR_DEF (BMI_CMD_MR_LEAC | \ ++ BMI_CMD_MR_SLEAC | \ ++ BMI_CMD_MR_MA | \ ++ BMI_CMD_MR_DEAS) ++#define BMI_CMD_ATTR_ORDER 0x80000000 ++#define BMI_CMD_ATTR_SYNC 0x02000000 ++#define BMI_CMD_ATTR_MODE_MISS_ALLIGN_ADDR_EN 0x00080000 ++#define BMI_CMD_ATTR_MACCMD_MASK 0x0000ff00 ++#define BMI_CMD_ATTR_MACCMD_OVERRIDE 0x00008000 ++#define BMI_CMD_ATTR_MACCMD_SECURED 0x00001000 ++#define BMI_CMD_ATTR_MACCMD_SC_MASK 0x00000f00 ++ ++#define BMI_EXT_BUF_POOL_EN_COUNTER FM_SP_EXT_BUF_POOL_EN_COUNTER ++#define BMI_EXT_BUF_POOL_VALID FM_SP_EXT_BUF_POOL_VALID ++ ++#define BMI_EXT_BUF_POOL_BACKUP FM_SP_EXT_BUF_POOL_BACKUP ++ ++#define BMI_EXT_BUF_POOL_ID_MASK 0x003F0000 ++#define BMI_STATUS_RX_MASK_UNUSED (uint32_t)(~(FM_PORT_FRM_ERR_DMA | \ ++ FM_PORT_FRM_ERR_PHYSICAL | \ ++ FM_PORT_FRM_ERR_SIZE | \ ++ FM_PORT_FRM_ERR_CLS_DISCARD | \ ++ FM_PORT_FRM_ERR_EXTRACTION | \ ++ FM_PORT_FRM_ERR_NO_SCHEME | \ ++ FM_PORT_FRM_ERR_COLOR_RED | \ ++ FM_PORT_FRM_ERR_COLOR_YELLOW | \ ++ FM_PORT_FRM_ERR_ILL_PLCR | \ ++ FM_PORT_FRM_ERR_PLCR_FRAME_LEN | \ ++ FM_PORT_FRM_ERR_PRS_TIMEOUT | \ ++ FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | \ ++ FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED | \ ++ FM_PORT_FRM_ERR_PRS_HDR_ERR | \ ++ FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW)) ++ ++#define BMI_STATUS_OP_MASK_UNUSED (uint32_t)(BMI_STATUS_RX_MASK_UNUSED & \ ++ ~(FM_PORT_FRM_ERR_LENGTH | \ ++ FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT)) ++ ++#define BMI_RATE_LIMIT_EN 0x80000000 ++#define BMI_RATE_LIMIT_BURST_SIZE_GRAN 0x80000000 ++#define BMI_RATE_LIMIT_SCALE_BY_2 0x00000001 ++#define BMI_RATE_LIMIT_SCALE_BY_4 0x00000002 ++#define BMI_RATE_LIMIT_SCALE_BY_8 0x00000003 ++ ++#define BMI_RX_FIFO_THRESHOLD_BC 0x80000000 ++ ++#define BMI_PRS_RESULT_HIGH 0x00000000 ++#define BMI_PRS_RESULT_LOW 0xFFFFFFFF ++ ++ ++#define RX_ERRS_TO_ENQ (FM_PORT_FRM_ERR_DMA | \ ++ FM_PORT_FRM_ERR_PHYSICAL | \ ++ FM_PORT_FRM_ERR_SIZE | \ ++ FM_PORT_FRM_ERR_EXTRACTION | \ ++ FM_PORT_FRM_ERR_NO_SCHEME | \ ++ FM_PORT_FRM_ERR_ILL_PLCR | \ ++ FM_PORT_FRM_ERR_PLCR_FRAME_LEN | \ ++ FM_PORT_FRM_ERR_PRS_TIMEOUT | \ ++ FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | \ ++ FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED | \ ++ FM_PORT_FRM_ERR_PRS_HDR_ERR | \ ++ FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW | \ ++ FM_PORT_FRM_ERR_IPRE) ++ ++#define OP_ERRS_TO_ENQ (RX_ERRS_TO_ENQ | \ ++ FM_PORT_FRM_ERR_LENGTH | \ ++ FM_PORT_FRM_ERR_NON_FM | \ ++ FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT) ++ ++ ++#define BMI_RX_FIFO_PRI_ELEVATION_MASK 0x03FF0000 ++#define BMI_RX_FIFO_THRESHOLD_MASK 0x000003FF ++#define BMI_TX_FIFO_MIN_FILL_MASK 0x03FF0000 ++#define BMI_FIFO_PIPELINE_DEPTH_MASK 0x0000F000 ++#define BMI_TX_LOW_COMF_MASK 0x000003FF ++ ++/* shifts */ ++#define BMI_PORT_CFG_MS_SEL_SHIFT 16 ++#define BMI_DMA_ATTR_SWP_SHIFT FM_SP_DMA_ATTR_SWP_SHIFT ++#define BMI_DMA_ATTR_IC_CACHE_SHIFT FM_SP_DMA_ATTR_IC_CACHE_SHIFT ++#define BMI_DMA_ATTR_HDR_CACHE_SHIFT FM_SP_DMA_ATTR_HDR_CACHE_SHIFT ++#define BMI_DMA_ATTR_SG_CACHE_SHIFT FM_SP_DMA_ATTR_SG_CACHE_SHIFT ++ ++#define BMI_IM_FOF_SHIFT 28 ++#define BMI_PR_PORTID_SHIFT 24 ++ ++#define BMI_RX_FIFO_PRI_ELEVATION_SHIFT 16 ++#define BMI_RX_FIFO_THRESHOLD_SHIFT 0 ++ ++#define BMI_RX_FRAME_END_CS_IGNORE_SHIFT 24 ++#define BMI_RX_FRAME_END_CUT_SHIFT 16 ++ ++#define BMI_IC_TO_EXT_SHIFT FM_SP_IC_TO_EXT_SHIFT ++#define BMI_IC_FROM_INT_SHIFT FM_SP_IC_FROM_INT_SHIFT ++#define BMI_IC_SIZE_SHIFT FM_SP_IC_SIZE_SHIFT ++ ++#define BMI_INT_BUF_MARG_SHIFT 28 ++ ++#define BMI_EXT_BUF_MARG_START_SHIFT FM_SP_EXT_BUF_MARG_START_SHIFT ++#define BMI_SG_DISABLE FM_SP_SG_DISABLE ++#define BMI_EXT_BUF_MARG_END_SHIFT FM_SP_EXT_BUF_MARG_END_SHIFT ++ ++#define BMI_CMD_ATTR_COLOR_SHIFT 26 ++#define BMI_CMD_ATTR_COM_MODE_SHIFT 16 ++#define BMI_CMD_ATTR_MACCMD_SHIFT 8 ++#define BMI_CMD_ATTR_MACCMD_OVERRIDE_SHIFT 15 ++#define BMI_CMD_ATTR_MACCMD_SECURED_SHIFT 12 ++#define BMI_CMD_ATTR_MACCMD_SC_SHIFT 8 ++ ++#define BMI_POOL_DEP_NUM_OF_POOLS_SHIFT FM_SP_POOL_DEP_NUM_OF_POOLS_SHIFT ++#define BMI_POOL_DEP_NUM_OF_POOLS_VECTOR_SHIFT 24 ++ ++#define BMI_EXT_BUF_POOL_ID_SHIFT FM_SP_EXT_BUF_POOL_ID_SHIFT ++#define BMI_TX_FIFO_MIN_FILL_SHIFT 16 ++#define BMI_FIFO_PIPELINE_DEPTH_SHIFT 12 ++#define BMI_TX_LOW_COMF_SHIFT 0 ++ ++#define BMI_FRAME_END_CS_IGNORE_SHIFT 24 ++ ++#define BMI_PERFORMANCE_TASK_COMP_SHIFT 24 ++#define BMI_PERFORMANCE_PORT_COMP_SHIFT 16 ++#define BMI_PERFORMANCE_DMA_COMP_SHIFT 12 ++#define BMI_PERFORMANCE_FIFO_COMP_SHIFT 0 ++ ++#define BMI_MAX_BURST_SHIFT 16 ++#define BMI_COUNT_RATE_UNIT_SHIFT 16 ++ ++/* sizes */ ++#define FRAME_END_DATA_SIZE 16 ++#define FRAME_OFFSET_UNITS 16 ++#define MIN_TX_INT_OFFSET 16 ++#define MAX_FRAME_OFFSET 64 ++#define MAX_FIFO_PIPELINE_DEPTH 8 ++#define MAX_PERFORMANCE_TASK_COMP 64 ++#define MAX_PERFORMANCE_TX_QUEUE_COMP 8 ++#define MAX_PERFORMANCE_RX_QUEUE_COMP 64 ++#define MAX_PERFORMANCE_DMA_COMP 16 ++#define MAX_NUM_OF_TASKS 64 ++#define MAX_NUM_OF_EXTRA_TASKS 8 ++#define MAX_NUM_OF_DMAS 16 ++#define MAX_NUM_OF_EXTRA_DMAS 8 ++#define MAX_BURST_SIZE 1024 ++#define MIN_NUM_OF_OP_DMAS 2 ++ ++/**************************************************************************//** ++ @Description QMI defines ++*//***************************************************************************/ ++/* masks */ ++#define QMI_PORT_CFG_EN 0x80000000 ++#define QMI_PORT_CFG_EN_COUNTERS 0x10000000 ++#define QMI_PORT_STATUS_DEQ_TNUM_BSY 0x80000000 ++#define QMI_PORT_STATUS_DEQ_FD_BSY 0x20000000 ++ ++#define QMI_DEQ_CFG_PREFETCH_NO_TNUM 0x02000000 ++#define QMI_DEQ_CFG_PREFETCH_WAITING_TNUM 0 ++#define QMI_DEQ_CFG_PREFETCH_1_FRAME 0 ++#define QMI_DEQ_CFG_PREFETCH_3_FRAMES 0x01000000 ++ ++#define QMI_DEQ_CFG_PRI 0x80000000 ++#define QMI_DEQ_CFG_TYPE1 0x10000000 ++#define QMI_DEQ_CFG_TYPE2 0x20000000 ++#define QMI_DEQ_CFG_TYPE3 0x30000000 ++ ++#define QMI_DEQ_CFG_SUBPORTAL_MASK 0x1f ++#define QMI_DEQ_CFG_SUBPORTAL_SHIFT 20 ++ ++/**************************************************************************//** ++ @Description PARSER defines ++*//***************************************************************************/ ++/* masks */ ++#define PRS_HDR_ERROR_DIS 0x00000800 ++#define PRS_HDR_SW_PRS_EN 0x00000400 ++#define PRS_CP_OFFSET_MASK 0x0000000F ++#define PRS_TPID1_MASK 0xFFFF0000 ++#define PRS_TPID2_MASK 0x0000FFFF ++#define PRS_TPID_DFLT 0x91009100 ++ ++#define PRS_HDR_MPLS_LBL_INTER_EN 0x00200000 ++#define PRS_HDR_IPV6_ROUTE_HDR_EN 0x00008000 ++#define PRS_HDR_PPPOE_MTU_CHECK_EN 0x80000000 ++#define PRS_HDR_UDP_PAD_REMOVAL 0x80000000 ++#define PRS_HDR_TCP_PAD_REMOVAL 0x80000000 ++#define PRS_CAC_STOP 0x00000001 ++#define PRS_CAC_ACTIVE 0x00000100 ++ ++/* shifts */ ++#define PRS_PCTPID_SHIFT 16 ++#define PRS_HDR_MPLS_NEXT_HDR_SHIFT 22 ++#define PRS_HDR_ETH_BC_SHIFT 28 ++#define PRS_HDR_ETH_MC_SHIFT 24 ++#define PRS_HDR_VLAN_STACKED_SHIFT 16 ++#define PRS_HDR_MPLS_STACKED_SHIFT 16 ++#define PRS_HDR_IPV4_1_BC_SHIFT 28 ++#define PRS_HDR_IPV4_1_MC_SHIFT 24 ++#define PRS_HDR_IPV4_2_UC_SHIFT 20 ++#define PRS_HDR_IPV4_2_MC_BC_SHIFT 16 ++#define PRS_HDR_IPV6_1_MC_SHIFT 24 ++#define PRS_HDR_IPV6_2_UC_SHIFT 20 ++#define PRS_HDR_IPV6_2_MC_SHIFT 16 ++ ++#define PRS_HDR_ETH_BC_MASK 0x0fffffff ++#define PRS_HDR_ETH_MC_MASK 0xf0ffffff ++#define PRS_HDR_VLAN_STACKED_MASK 0xfff0ffff ++#define PRS_HDR_MPLS_STACKED_MASK 0xfff0ffff ++#define PRS_HDR_IPV4_1_BC_MASK 0x0fffffff ++#define PRS_HDR_IPV4_1_MC_MASK 0xf0ffffff ++#define PRS_HDR_IPV4_2_UC_MASK 0xff0fffff ++#define PRS_HDR_IPV4_2_MC_BC_MASK 0xfff0ffff ++#define PRS_HDR_IPV6_1_MC_MASK 0xf0ffffff ++#define PRS_HDR_IPV6_2_UC_MASK 0xff0fffff ++#define PRS_HDR_IPV6_2_MC_MASK 0xfff0ffff ++ ++/* others */ ++#define PRS_HDR_ENTRY_SIZE 8 ++#define DEFAULT_CLS_PLAN_VECTOR 0xFFFFFFFF ++ ++#define IPSEC_SW_PATCH_START 0x20 ++#define SCTP_SW_PATCH_START 0x4D ++#define DCCP_SW_PATCH_START 0x41 ++ ++/**************************************************************************//** ++ @Description IM defines ++*//***************************************************************************/ ++#define BD_R_E 0x80000000 ++#define BD_L 0x08000000 ++ ++#define BD_RX_CRE 0x00080000 ++#define BD_RX_FTL 0x00040000 ++#define BD_RX_FTS 0x00020000 ++#define BD_RX_OV 0x00010000 ++ ++#define BD_RX_ERRORS (BD_RX_CRE | BD_RX_FTL | BD_RX_FTS | BD_RX_OV) ++#define BD_ERROR_PASS_FRAME BD_RX_ERRORS ++ ++#define FM_IM_SIZEOF_BD sizeof(t_FmImBd) ++ ++#define BD_STATUS_MASK 0xffff0000 ++#define BD_LENGTH_MASK 0x0000ffff ++ ++#define BD_STATUS_AND_LENGTH_SET(bd, val) WRITE_UINT32(*(volatile uint32_t*)(bd), (val)) ++ ++#define BD_STATUS_AND_LENGTH(bd) GET_UINT32(*(volatile uint32_t*)(bd)) ++ ++#define BD_GET(id) &p_FmPort->im.p_BdRing[id] ++ ++#define IM_ILEGAL_BD_ID 0xffff ++ ++/* others */ ++#define IM_PRAM_ALIGN 0x100 ++ ++/* masks */ ++#define IM_MODE_GBL 0x20000000 ++#define IM_MODE_BO_MASK 0x18000000 ++#define IM_MODE_BO_SHIFT 3 ++#define IM_MODE_GRC_STP 0x00800000 ++ ++#define IM_MODE_SET_BO(val) (uint32_t)((val << (31-IM_MODE_BO_SHIFT)) & IM_MODE_BO_MASK) ++ ++#define IM_RXQD_BSYINTM 0x0008 ++#define IM_RXQD_RXFINTM 0x0010 ++#define IM_RXQD_FPMEVT_SEL_MASK 0x0003 ++ ++#define IM_EV_BSY 0x40000000 ++#define IM_EV_RX 0x80000000 ++ ++ ++/**************************************************************************//** ++ @Description Additional defines ++*//***************************************************************************/ ++ ++typedef struct { ++ t_Handle h_FmMuram; ++ t_FmPortImPram *p_FmPortImPram; ++ uint8_t fwExtStructsMemId; ++ uint32_t fwExtStructsMemAttr; ++ uint16_t bdRingSize; ++ t_FmImBd *p_BdRing; ++ t_Handle *p_BdShadow; ++ uint16_t currBdId; ++ uint16_t firstBdOfFrameId; ++ ++ /* Rx port parameters */ ++ uint8_t dataMemId; /**< Memory partition ID for data buffers */ ++ uint32_t dataMemAttributes; /**< Memory attributes for data buffers */ ++ t_BufferPoolInfo rxPool; ++ uint16_t mrblr; ++ uint16_t rxFrameAccumLength; ++ t_FmPortImRxStoreCallback *f_RxStore; ++ ++ /* Tx port parameters */ ++ uint32_t txFirstBdStatus; ++ t_FmPortImTxConfCallback *f_TxConf; ++} t_FmMacIm; ++ ++ ++typedef struct { ++ uint32_t dfltFqid; ++ uint32_t confFqid; ++ uint32_t errFqid; ++ uintptr_t baseAddr; ++ uint8_t deqSubPortal; ++ bool deqHighPriority; ++ e_FmPortDeqType deqType; ++ e_FmPortDeqPrefetchOption deqPrefetchOption; ++ uint16_t deqByteCnt; ++ uint8_t cheksumLastBytesIgnore; ++ uint8_t cutBytesFromEnd; ++ t_FmBufPoolDepletion bufPoolDepletion; ++ uint8_t pipelineDepth; ++ uint16_t fifoLowComfLevel; ++ bool frmDiscardOverride; ++ bool enRateLimit; ++ t_FmPortRateLimit rateLimit; ++ e_FmPortDualRateLimiterScaleDown rateLimitDivider; ++ bool enBufPoolDepletion; ++ uint16_t liodnOffset; ++ uint16_t liodnBase; ++ t_FmExtPools extBufPools; ++ e_FmDmaSwapOption dmaSwapData; ++ e_FmDmaCacheOption dmaIntContextCacheAttr; ++ e_FmDmaCacheOption dmaHeaderCacheAttr; ++ e_FmDmaCacheOption dmaScatterGatherCacheAttr; ++ bool dmaReadOptimize; ++ bool dmaWriteOptimize; ++ uint32_t txFifoMinFillLevel; ++ uint32_t txFifoLowComfLevel; ++ uint32_t rxFifoPriElevationLevel; ++ uint32_t rxFifoThreshold; ++ t_FmSpBufMargins bufMargins; ++ t_FmSpIntContextDataCopy intContext; ++ bool syncReq; ++ e_FmPortColor color; ++ fmPortFrameErrSelect_t errorsToDiscard; ++ fmPortFrameErrSelect_t errorsToEnq; ++ bool forwardReuseIntContext; ++ t_FmBufferPrefixContent bufferPrefixContent; ++ t_FmBackupBmPools *p_BackupBmPools; ++ bool dontReleaseBuf; ++ bool setNumOfTasks; ++ bool setNumOfOpenDmas; ++ bool setSizeOfFifo; ++#if (DPAA_VERSION >= 11) ++ bool noScatherGather; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 ++ bool bcbWorkaround; ++#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */ ++} t_FmPortDriverParam; ++ ++ ++typedef struct t_FmPortRxPoolsParams ++{ ++ uint8_t numOfPools; ++ uint16_t secondLargestBufSize; ++ uint16_t largestBufSize; ++} t_FmPortRxPoolsParams; ++ ++typedef struct { ++ t_Handle h_Fm; ++ t_Handle h_FmPcd; ++ t_Handle h_FmMuram; ++ t_FmRevisionInfo fmRevInfo; ++ uint8_t portId; ++ e_FmPortType portType; ++ int enabled; ++ char name[MODULE_NAME_SIZE]; ++ uint8_t hardwarePortId; ++ uint16_t fmClkFreq; ++ t_FmPortQmiRegs *p_FmPortQmiRegs; ++ u_FmPortBmiRegs *p_FmPortBmiRegs; ++ t_FmPortPrsRegs *p_FmPortPrsRegs; ++ fmPcdEngines_t pcdEngines; ++ uint32_t savedBmiNia; ++ uint8_t netEnvId; ++ uint32_t optArray[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)]; ++ uint32_t lcvs[FM_PCD_PRS_NUM_OF_HDRS]; ++ uint8_t privateInfo; ++ uint32_t schemesPerPortVector; ++ bool useClsPlan; ++ uint8_t clsPlanGrpId; ++ t_Handle ccTreeId; ++ t_Handle completeArg; ++ void (*f_Complete)(t_Handle arg); ++ t_FmSpBufferOffsets bufferOffsets; ++ /* Independent-Mode parameters support */ ++ bool imEn; ++ t_FmMacIm im; ++ uint8_t fifoDeqPipelineDepth; ++ volatile bool lock; ++ t_Handle h_Spinlock; ++ t_FmPortExceptionCallback *f_Exception; ++ t_Handle h_App; ++ uint8_t internalBufferOffset; ++ uint8_t fmanCtrlEventId; ++ uint32_t exceptions; ++ bool polling; ++ t_FmExtPools extBufPools; ++ uint32_t requiredAction; ++ uint32_t savedQmiPnen; ++ uint32_t savedBmiFene; ++ uint32_t savedBmiFpne; ++ uint32_t savedBmiCmne; ++ uint32_t savedNonRxQmiRegsPndn; ++ int savedPrsStartOffset; ++ bool includeInPrsStatistics; ++ uint16_t maxFrameLength; ++ t_FmFmanCtrl orFmanCtrl; ++ t_FmPortRsrc openDmas; ++ t_FmPortRsrc tasks; ++ t_FmPortRsrc fifoBufs; ++ t_FmPortRxPoolsParams rxPoolsParams; ++ t_Handle h_IpReassemblyManip; ++ t_Handle h_IpReassemblyTree; ++ uint64_t fmMuramPhysBaseAddr; ++#if (DPAA_VERSION >= 11) ++ bool vspe; ++ e_FmPortGprFuncType gprFunc; ++ void *p_MuramPage; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ t_FmPortDriverParam *p_FmPortDriverParam; ++} t_FmPort; ++ ++ ++void FmPortConfigIM (t_FmPort *p_FmPort, t_FmPortParams *p_FmPortParams); ++t_Error FmPortImCheckInitParameters(t_FmPort *p_FmPort); ++ ++t_Error FmPortImInit(t_FmPort *p_FmPort); ++void FmPortImFree(t_FmPort *p_FmPort); ++ ++t_Error FmPortImEnable (t_FmPort *p_FmPort); ++t_Error FmPortImDisable (t_FmPort *p_FmPort); ++t_Error FmPortImRx (t_FmPort *p_FmPort); ++ ++void FmPortSetMacsecLcv(t_Handle h_FmPort); ++void FmPortSetMacsecCmd(t_Handle h_FmPort, uint8_t dfltSci); ++ ++ ++t_Error FM_PORT_SetNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfOpenDmas); ++t_Error FM_PORT_SetNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks); ++t_Error FM_PORT_SetSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo); ++ ++static __inline__ uint8_t * BdBufferGet (t_PhysToVirt *f_PhysToVirt, t_FmImBd *p_Bd) ++{ ++ uint64_t physAddr = (uint64_t)((uint64_t)GET_UINT8(p_Bd->buff.high) << 32); ++ physAddr |= GET_UINT32(p_Bd->buff.low); ++ ++ return (uint8_t *)f_PhysToVirt((physAddress_t)(physAddr)); ++} ++ ++static __inline__ void SET_ADDR(volatile t_FmPhysAddr *fmPhysAddr, uint64_t value) ++{ ++ WRITE_UINT8(fmPhysAddr->high,(uint8_t)((value & 0x000000ff00000000LL) >> 32)); ++ WRITE_UINT32(fmPhysAddr->low,(uint32_t)value); ++} ++ ++static __inline__ void BdBufferSet(t_VirtToPhys *f_VirtToPhys, t_FmImBd *p_Bd, uint8_t *p_Buffer) ++{ ++ uint64_t physAddr = (uint64_t)(f_VirtToPhys(p_Buffer)); ++ SET_ADDR(&p_Bd->buff, physAddr); ++} ++ ++static __inline__ uint16_t GetNextBdId(t_FmPort *p_FmPort, uint16_t id) ++{ ++ if (id < p_FmPort->im.bdRingSize-1) ++ return (uint16_t)(id+1); ++ else ++ return 0; ++} ++ ++ ++#endif /* __FM_PORT_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Port/fm_port_im.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/Port/fm_port_im.c +new file mode 100644 +index 0000000..bf358a5 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Port/fm_port_im.c +@@ -0,0 +1,754 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_port_im.c ++ ++ @Description FM Port Independent-Mode ... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "string_ext.h" ++#include "error_ext.h" ++#include "fm_muram_ext.h" ++ ++#include "fm_port.h" ++ ++ ++#define TX_CONF_STATUS_UNSENT 0x1 ++ ++ ++typedef enum e_TxConfType ++{ ++ e_TX_CONF_TYPE_CHECK = 0 /**< check if all the buffers were touched by the muxator, no confirmation callback */ ++ ,e_TX_CONF_TYPE_CALLBACK = 1 /**< confirm to user all the available sent buffers */ ++ ,e_TX_CONF_TYPE_FLUSH = 3 /**< confirm all buffers plus the unsent one with an appropriate status */ ++} e_TxConfType; ++ ++ ++static void ImException(t_Handle h_FmPort, uint32_t event) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ ASSERT_COND(((event & IM_EV_RX) && FmIsMaster(p_FmPort->h_Fm)) || ++ !FmIsMaster(p_FmPort->h_Fm)); ++ ++ if (event & IM_EV_RX) ++ FmPortImRx(p_FmPort); ++ if ((event & IM_EV_BSY) && p_FmPort->f_Exception) ++ p_FmPort->f_Exception(p_FmPort->h_App, e_FM_PORT_EXCEPTION_IM_BUSY); ++} ++ ++ ++static t_Error TxConf(t_FmPort *p_FmPort, e_TxConfType confType) ++{ ++ t_Error retVal = E_BUSY; ++ uint32_t bdStatus; ++ uint16_t savedStartBdId, confBdId; ++ ++ ASSERT_COND(p_FmPort); ++ ++ /* ++ if (confType==e_TX_CONF_TYPE_CHECK) ++ return (WfqEntryIsQueueEmpty(p_FmPort->im.h_WfqEntry) ? E_OK : E_BUSY); ++ */ ++ ++ confBdId = savedStartBdId = p_FmPort->im.currBdId; ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(confBdId)); ++ ++ /* If R bit is set, we don't enter, or we break. ++ we run till we get to R, or complete the loop */ ++ while ((!(bdStatus & BD_R_E) || (confType == e_TX_CONF_TYPE_FLUSH)) && (retVal != E_OK)) ++ { ++ if (confType & e_TX_CONF_TYPE_CALLBACK) /* if it is confirmation with user callbacks */ ++ BD_STATUS_AND_LENGTH_SET(BD_GET(confBdId), 0); ++ ++ /* case 1: R bit is 0 and Length is set -> confirm! */ ++ if ((confType & e_TX_CONF_TYPE_CALLBACK) && (bdStatus & BD_LENGTH_MASK)) ++ { ++ if (p_FmPort->im.f_TxConf) ++ { ++ if ((confType == e_TX_CONF_TYPE_FLUSH) && (bdStatus & BD_R_E)) ++ p_FmPort->im.f_TxConf(p_FmPort->h_App, ++ BdBufferGet(XX_PhysToVirt, BD_GET(confBdId)), ++ TX_CONF_STATUS_UNSENT, ++ p_FmPort->im.p_BdShadow[confBdId]); ++ else ++ p_FmPort->im.f_TxConf(p_FmPort->h_App, ++ BdBufferGet(XX_PhysToVirt, BD_GET(confBdId)), ++ 0, ++ p_FmPort->im.p_BdShadow[confBdId]); ++ } ++ } ++ /* case 2: R bit is 0 and Length is 0 -> not used yet, nop! */ ++ ++ confBdId = GetNextBdId(p_FmPort, confBdId); ++ if (confBdId == savedStartBdId) ++ retVal = E_OK; ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(confBdId)); ++ } ++ ++ return retVal; ++} ++ ++t_Error FmPortImEnable(t_FmPort *p_FmPort) ++{ ++ uint32_t tmpReg = GET_UINT32(p_FmPort->im.p_FmPortImPram->mode); ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, (uint32_t)(tmpReg & ~IM_MODE_GRC_STP)); ++ return E_OK; ++} ++ ++t_Error FmPortImDisable(t_FmPort *p_FmPort) ++{ ++ uint32_t tmpReg = GET_UINT32(p_FmPort->im.p_FmPortImPram->mode); ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, (uint32_t)(tmpReg | IM_MODE_GRC_STP)); ++ return E_OK; ++} ++ ++t_Error FmPortImRx(t_FmPort *p_FmPort) ++{ ++ t_Handle h_CurrUserPriv, h_NewUserPriv; ++ uint32_t bdStatus; ++ volatile uint8_t buffPos; ++ uint16_t length; ++ uint16_t errors/*, reportErrors*/; ++ uint8_t *p_CurData, *p_Data; ++ uint32_t flags; ++ ++ ASSERT_COND(p_FmPort); ++ ++ flags = XX_LockIntrSpinlock(p_FmPort->h_Spinlock); ++ if (p_FmPort->lock) ++ { ++ XX_UnlockIntrSpinlock(p_FmPort->h_Spinlock, flags); ++ return E_OK; ++ } ++ p_FmPort->lock = TRUE; ++ XX_UnlockIntrSpinlock(p_FmPort->h_Spinlock, flags); ++ ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId)); ++ ++ while (!(bdStatus & BD_R_E)) /* while there is data in the Rx BD */ ++ { ++ if ((p_Data = p_FmPort->im.rxPool.f_GetBuf(p_FmPort->im.rxPool.h_BufferPool, &h_NewUserPriv)) == NULL) ++ { ++ p_FmPort->lock = FALSE; ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Data buffer")); ++ } ++ ++ if (p_FmPort->im.firstBdOfFrameId == IM_ILEGAL_BD_ID) ++ p_FmPort->im.firstBdOfFrameId = p_FmPort->im.currBdId; ++ ++ errors = 0; ++ p_CurData = BdBufferGet(p_FmPort->im.rxPool.f_PhysToVirt, BD_GET(p_FmPort->im.currBdId)); ++ h_CurrUserPriv = p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]; ++ length = (uint16_t)((bdStatus & BD_L) ? ++ ((bdStatus & BD_LENGTH_MASK) - p_FmPort->im.rxFrameAccumLength): ++ (bdStatus & BD_LENGTH_MASK)); ++ p_FmPort->im.rxFrameAccumLength += length; ++ ++ /* determine whether buffer is first, last, first and last (single */ ++ /* buffer frame) or middle (not first and not last) */ ++ buffPos = (uint8_t)((p_FmPort->im.currBdId == p_FmPort->im.firstBdOfFrameId) ? ++ ((bdStatus & BD_L) ? SINGLE_BUF : FIRST_BUF) : ++ ((bdStatus & BD_L) ? LAST_BUF : MIDDLE_BUF)); ++ ++ if (bdStatus & BD_L) ++ { ++ p_FmPort->im.rxFrameAccumLength = 0; ++ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID; ++ } ++ ++ BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, BD_GET(p_FmPort->im.currBdId), p_Data); ++ ++ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), BD_R_E); ++ ++ errors = (uint16_t)((bdStatus & BD_RX_ERRORS) >> 16); ++ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId] = h_NewUserPriv; ++ ++ p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId); ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.offsetOut, (uint16_t)(p_FmPort->im.currBdId<<4)); ++ /* Pass the buffer if one of the conditions is true: ++ - There are no errors ++ - This is a part of a larger frame ( the application has already received some buffers ) ++ - There is an error, but it was defined to be passed anyway. */ ++ if ((buffPos != SINGLE_BUF) || !errors || (errors & (uint16_t)(BD_ERROR_PASS_FRAME>>16))) ++ { ++ if (p_FmPort->im.f_RxStore(p_FmPort->h_App, ++ p_CurData, ++ length, ++ errors, ++ buffPos, ++ h_CurrUserPriv) == e_RX_STORE_RESPONSE_PAUSE) ++ break; ++ } ++ else if (p_FmPort->im.rxPool.f_PutBuf(p_FmPort->im.rxPool.h_BufferPool, ++ p_CurData, ++ h_CurrUserPriv)) ++ { ++ p_FmPort->lock = FALSE; ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Failed freeing data buffer")); ++ } ++ ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId)); ++ } ++ p_FmPort->lock = FALSE; ++ return E_OK; ++} ++ ++void FmPortConfigIM (t_FmPort *p_FmPort, t_FmPortParams *p_FmPortParams) ++{ ++ ASSERT_COND(p_FmPort); ++ ++ SANITY_CHECK_RETURN(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->im.h_FmMuram = p_FmPortParams->specificParams.imRxTxParams.h_FmMuram; ++ p_FmPort->p_FmPortDriverParam->liodnOffset = p_FmPortParams->specificParams.imRxTxParams.liodnOffset; ++ p_FmPort->im.dataMemId = p_FmPortParams->specificParams.imRxTxParams.dataMemId; ++ p_FmPort->im.dataMemAttributes = p_FmPortParams->specificParams.imRxTxParams.dataMemAttributes; ++ ++ p_FmPort->im.fwExtStructsMemId = DEFAULT_PORT_ImfwExtStructsMemId; ++ p_FmPort->im.fwExtStructsMemAttr = DEFAULT_PORT_ImfwExtStructsMemAttr; ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ p_FmPort->im.rxPool.h_BufferPool = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.h_BufferPool; ++ p_FmPort->im.rxPool.f_GetBuf = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_GetBuf; ++ p_FmPort->im.rxPool.f_PutBuf = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_PutBuf; ++ p_FmPort->im.rxPool.bufferSize = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.bufferSize; ++ p_FmPort->im.rxPool.f_PhysToVirt = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_PhysToVirt; ++ if (!p_FmPort->im.rxPool.f_PhysToVirt) ++ p_FmPort->im.rxPool.f_PhysToVirt = XX_PhysToVirt; ++ p_FmPort->im.rxPool.f_VirtToPhys = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_VirtToPhys; ++ if (!p_FmPort->im.rxPool.f_VirtToPhys) ++ p_FmPort->im.rxPool.f_VirtToPhys = XX_VirtToPhys; ++ p_FmPort->im.f_RxStore = p_FmPortParams->specificParams.imRxTxParams.f_RxStore; ++ ++ p_FmPort->im.mrblr = 0x8000; ++ while (p_FmPort->im.mrblr) ++ { ++ if (p_FmPort->im.rxPool.bufferSize & p_FmPort->im.mrblr) ++ break; ++ p_FmPort->im.mrblr >>= 1; ++ } ++ if (p_FmPort->im.mrblr != p_FmPort->im.rxPool.bufferSize) ++ DBG(WARNING, ("Max-Rx-Buffer-Length set to %d", p_FmPort->im.mrblr)); ++ p_FmPort->im.bdRingSize = DEFAULT_PORT_rxBdRingLength; ++ p_FmPort->exceptions = DEFAULT_PORT_exception; ++ if (FmIsMaster(p_FmPort->h_Fm)) ++ p_FmPort->polling = FALSE; ++ else ++ p_FmPort->polling = TRUE; ++ p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ; ++ } ++ else ++ { ++ p_FmPort->im.f_TxConf = p_FmPortParams->specificParams.imRxTxParams.f_TxConf; ++ ++ p_FmPort->im.bdRingSize = DEFAULT_PORT_txBdRingLength; ++ } ++} ++ ++t_Error FmPortImCheckInitParameters(t_FmPort *p_FmPort) ++{ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_TX) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_TX_10G)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ if (!POWER_OF_2(p_FmPort->im.mrblr)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("max Rx buffer length must be power of 2!!!")); ++ if (p_FmPort->im.mrblr < 256) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("max Rx buffer length must at least 256!!!")); ++ if (p_FmPort->p_FmPortDriverParam->liodnOffset & ~FM_LIODN_OFFSET_MASK) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1)); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FmPortImInit(t_FmPort *p_FmPort) ++{ ++ t_FmImBd *p_Bd=NULL; ++ t_Handle h_BufContext; ++ uint64_t tmpPhysBase; ++ uint16_t log2Num; ++ uint8_t *p_Data/*, *p_Tmp*/; ++ int i; ++ t_Error err; ++ uint16_t tmpReg16; ++ uint32_t tmpReg32; ++ ++ ASSERT_COND(p_FmPort); ++ ++ p_FmPort->im.p_FmPortImPram = ++ (t_FmPortImPram *)FM_MURAM_AllocMem(p_FmPort->im.h_FmMuram, sizeof(t_FmPortImPram), IM_PRAM_ALIGN); ++ if (!p_FmPort->im.p_FmPortImPram) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Parameter-RAM!!!")); ++ WRITE_BLOCK(p_FmPort->im.p_FmPortImPram, 0, sizeof(t_FmPortImPram)); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ p_FmPort->im.p_BdRing = ++ (t_FmImBd *)XX_MallocSmart((uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize), ++ p_FmPort->im.fwExtStructsMemId, ++ 4); ++ if (!p_FmPort->im.p_BdRing) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD ring!!!")); ++ IOMemSet32(p_FmPort->im.p_BdRing, 0, (uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize)); ++ ++ p_FmPort->im.p_BdShadow = (t_Handle *)XX_Malloc((uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize)); ++ if (!p_FmPort->im.p_BdShadow) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD shadow!!!")); ++ memset(p_FmPort->im.p_BdShadow, 0, (uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize)); ++ ++ /* Initialize the Rx-BD ring */ ++ for (i=0; iim.bdRingSize; i++) ++ { ++ p_Bd = BD_GET(i); ++ BD_STATUS_AND_LENGTH_SET (p_Bd, BD_R_E); ++ ++ if ((p_Data = p_FmPort->im.rxPool.f_GetBuf(p_FmPort->im.rxPool.h_BufferPool, &h_BufContext)) == NULL) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Data buffer")); ++ BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, p_Bd, p_Data); ++ p_FmPort->im.p_BdShadow[i] = h_BufContext; ++ } ++ ++ if ((p_FmPort->im.dataMemAttributes & MEMORY_ATTR_CACHEABLE) || ++ (p_FmPort->im.fwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE)) ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_GBL | IM_MODE_SET_BO(2)); ++ else ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_SET_BO(2)); ++ ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->rxQdPtr, ++ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) - ++ p_FmPort->fmMuramPhysBaseAddr + 0x20)); ++ ++ LOG2((uint64_t)p_FmPort->im.mrblr, log2Num); ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->mrblr, log2Num); ++ ++ /* Initialize Rx QD */ ++ tmpPhysBase = (uint64_t)(XX_VirtToPhys(p_FmPort->im.p_BdRing)); ++ SET_ADDR(&p_FmPort->im.p_FmPortImPram->rxQd.bdRingBase, tmpPhysBase); ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.bdRingSize, (uint16_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize)); ++ ++ /* Update the IM PRAM address in the BMI */ ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfqid, ++ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) - ++ p_FmPort->fmMuramPhysBaseAddr)); ++ if (!p_FmPort->polling || p_FmPort->exceptions) ++ { ++ /* Allocate, configure and register interrupts */ ++ err = FmAllocFmanCtrlEventReg(p_FmPort->h_Fm, &p_FmPort->fmanCtrlEventId); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ ASSERT_COND(!(p_FmPort->fmanCtrlEventId & ~IM_RXQD_FPMEVT_SEL_MASK)); ++ tmpReg16 = (uint16_t)(p_FmPort->fmanCtrlEventId & IM_RXQD_FPMEVT_SEL_MASK); ++ tmpReg32 = 0; ++ ++ if (p_FmPort->exceptions & IM_EV_BSY) ++ { ++ tmpReg16 |= IM_RXQD_BSYINTM; ++ tmpReg32 |= IM_EV_BSY; ++ } ++ if (!p_FmPort->polling) ++ { ++ tmpReg16 |= IM_RXQD_RXFINTM; ++ tmpReg32 |= IM_EV_RX; ++ } ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16); ++ ++ FmRegisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, ImException , (t_Handle)p_FmPort); ++ ++ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32); ++ } ++ else ++ p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ; ++ } ++ else ++ { ++ p_FmPort->im.p_BdRing = (t_FmImBd *)XX_MallocSmart((uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize), p_FmPort->im.fwExtStructsMemId, 4); ++ if (!p_FmPort->im.p_BdRing) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Tx BD ring!!!")); ++ IOMemSet32(p_FmPort->im.p_BdRing, 0, (uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize)); ++ ++ p_FmPort->im.p_BdShadow = (t_Handle *)XX_Malloc((uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize)); ++ if (!p_FmPort->im.p_BdShadow) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD shadow!!!")); ++ memset(p_FmPort->im.p_BdShadow, 0, (uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize)); ++ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID; ++ ++ if ((p_FmPort->im.dataMemAttributes & MEMORY_ATTR_CACHEABLE) || ++ (p_FmPort->im.fwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE)) ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_GBL | IM_MODE_SET_BO(2)); ++ else ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_SET_BO(2)); ++ ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->txQdPtr, ++ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) - ++ p_FmPort->fmMuramPhysBaseAddr + 0x40)); ++ ++ /* Initialize Tx QD */ ++ tmpPhysBase = (uint64_t)(XX_VirtToPhys(p_FmPort->im.p_BdRing)); ++ SET_ADDR(&p_FmPort->im.p_FmPortImPram->txQd.bdRingBase, tmpPhysBase); ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->txQd.bdRingSize, (uint16_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize)); ++ ++ /* Update the IM PRAM address in the BMI */ ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfqid, ++ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) - ++ p_FmPort->fmMuramPhysBaseAddr)); ++ } ++ ++ ++ return E_OK; ++} ++ ++void FmPortImFree(t_FmPort *p_FmPort) ++{ ++ uint32_t bdStatus; ++ uint8_t *p_CurData; ++ ++ ASSERT_COND(p_FmPort); ++ ASSERT_COND(p_FmPort->im.p_FmPortImPram); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ if (!p_FmPort->polling || p_FmPort->exceptions) ++ { ++ /* Deallocate and unregister interrupts */ ++ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, 0); ++ ++ FmFreeFmanCtrlEventReg(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId); ++ ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, 0); ++ ++ FmUnregisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId); ++ } ++ /* Try first clean what has received */ ++ FmPortImRx(p_FmPort); ++ ++ /* Now, get rid of the the empty buffer! */ ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId)); ++ ++ while (bdStatus & BD_R_E) /* while there is data in the Rx BD */ ++ { ++ p_CurData = BdBufferGet(p_FmPort->im.rxPool.f_PhysToVirt, BD_GET(p_FmPort->im.currBdId)); ++ ++ BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, BD_GET(p_FmPort->im.currBdId), NULL); ++ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), 0); ++ ++ p_FmPort->im.rxPool.f_PutBuf(p_FmPort->im.rxPool.h_BufferPool, ++ p_CurData, ++ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]); ++ ++ p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId); ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId)); ++ } ++ } ++ else ++ TxConf(p_FmPort, e_TX_CONF_TYPE_FLUSH); ++ ++ FM_MURAM_FreeMem(p_FmPort->im.h_FmMuram, p_FmPort->im.p_FmPortImPram); ++ ++ if (p_FmPort->im.p_BdShadow) ++ XX_Free(p_FmPort->im.p_BdShadow); ++ ++ if (p_FmPort->im.p_BdRing) ++ XX_FreeSmart(p_FmPort->im.p_BdRing); ++} ++ ++ ++t_Error FM_PORT_ConfigIMMaxRxBufLength(t_Handle h_FmPort, uint16_t newVal) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->im.mrblr = newVal; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigIMRxBdRingLength(t_Handle h_FmPort, uint16_t newVal) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->im.bdRingSize = newVal; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigIMTxBdRingLength(t_Handle h_FmPort, uint16_t newVal) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->im.bdRingSize = newVal; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigIMFmanCtrlExternalStructsMemory(t_Handle h_FmPort, ++ uint8_t memId, ++ uint32_t memAttributes) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->im.fwExtStructsMemId = memId; ++ p_FmPort->im.fwExtStructsMemAttr = memAttributes; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigIMPolling(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Available for Rx ports only")); ++ ++ if (!FmIsMaster(p_FmPort->h_Fm)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Available on master-partition only;" ++ "in guest-partitions, IM is always in polling!")); ++ ++ p_FmPort->polling = TRUE; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetIMExceptions(t_Handle h_FmPort, e_FmPortExceptions exception, bool enable) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err; ++ uint16_t tmpReg16; ++ uint32_t tmpReg32; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if (exception == e_FM_PORT_EXCEPTION_IM_BUSY) ++ { ++ if (enable) ++ { ++ p_FmPort->exceptions |= IM_EV_BSY; ++ if (p_FmPort->fmanCtrlEventId == (uint8_t)NO_IRQ) ++ { ++ /* Allocate, configure and register interrupts */ ++ err = FmAllocFmanCtrlEventReg(p_FmPort->h_Fm, &p_FmPort->fmanCtrlEventId); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ASSERT_COND(!(p_FmPort->fmanCtrlEventId & ~IM_RXQD_FPMEVT_SEL_MASK)); ++ ++ FmRegisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, ImException, (t_Handle)p_FmPort); ++ tmpReg16 = (uint16_t)((p_FmPort->fmanCtrlEventId & IM_RXQD_FPMEVT_SEL_MASK) | IM_RXQD_BSYINTM); ++ tmpReg32 = IM_EV_BSY; ++ } ++ else ++ { ++ tmpReg16 = (uint16_t)(GET_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen) | IM_RXQD_BSYINTM); ++ tmpReg32 = FmGetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId) | IM_EV_BSY; ++ } ++ ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16); ++ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32); ++ } ++ else ++ { ++ p_FmPort->exceptions &= ~IM_EV_BSY; ++ if (!p_FmPort->exceptions && p_FmPort->polling) ++ { ++ FmFreeFmanCtrlEventReg(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId); ++ FmUnregisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId); ++ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, 0); ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, 0); ++ p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ; ++ } ++ else ++ { ++ tmpReg16 = (uint16_t)(GET_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen) & ~IM_RXQD_BSYINTM); ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16); ++ tmpReg32 = FmGetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId) & ~IM_EV_BSY; ++ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32); ++ } ++ } ++ } ++ else ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Invalid exception.")); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ImTx( t_Handle h_FmPort, ++ uint8_t *p_Data, ++ uint16_t length, ++ bool lastBuffer, ++ t_Handle h_BufContext) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint16_t nextBdId; ++ uint32_t bdStatus, nextBdStatus; ++ bool firstBuffer; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId)); ++ nextBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId); ++ nextBdStatus = BD_STATUS_AND_LENGTH(BD_GET(nextBdId)); ++ ++ if (!(bdStatus & BD_R_E) && !(nextBdStatus & BD_R_E)) ++ { ++ /* Confirm the current BD - BD is available */ ++ if ((bdStatus & BD_LENGTH_MASK) && (p_FmPort->im.f_TxConf)) ++ p_FmPort->im.f_TxConf (p_FmPort->h_App, ++ BdBufferGet(XX_PhysToVirt, BD_GET(p_FmPort->im.currBdId)), ++ 0, ++ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]); ++ ++ bdStatus = length; ++ ++ /* if this is the first BD of a frame */ ++ if (p_FmPort->im.firstBdOfFrameId == IM_ILEGAL_BD_ID) ++ { ++ firstBuffer = TRUE; ++ p_FmPort->im.txFirstBdStatus = (bdStatus | BD_R_E); ++ ++ if (!lastBuffer) ++ p_FmPort->im.firstBdOfFrameId = p_FmPort->im.currBdId; ++ } ++ else ++ firstBuffer = FALSE; ++ ++ BdBufferSet(XX_VirtToPhys, BD_GET(p_FmPort->im.currBdId), p_Data); ++ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId] = h_BufContext; ++ ++ /* deal with last */ ++ if (lastBuffer) ++ { ++ /* if single buffer frame */ ++ if (firstBuffer) ++ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), p_FmPort->im.txFirstBdStatus | BD_L); ++ else ++ { ++ /* Set the last BD of the frame */ ++ BD_STATUS_AND_LENGTH_SET (BD_GET(p_FmPort->im.currBdId), (bdStatus | BD_R_E | BD_L)); ++ /* Set the first BD of the frame */ ++ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.firstBdOfFrameId), p_FmPort->im.txFirstBdStatus); ++ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID; ++ } ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->txQd.offsetIn, (uint16_t)(GetNextBdId(p_FmPort, p_FmPort->im.currBdId)<<4)); ++ } ++ else if (!firstBuffer) /* mid frame buffer */ ++ BD_STATUS_AND_LENGTH_SET (BD_GET(p_FmPort->im.currBdId), bdStatus | BD_R_E); ++ ++ p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId); ++ } ++ else ++ { ++ /* Discard current frame. Return error. */ ++ if (p_FmPort->im.firstBdOfFrameId != IM_ILEGAL_BD_ID) ++ { ++ /* Error: No free BD */ ++ /* Response: Discard current frame. Return error. */ ++ uint16_t cleanBdId = p_FmPort->im.firstBdOfFrameId; ++ ++ ASSERT_COND(p_FmPort->im.firstBdOfFrameId != p_FmPort->im.currBdId); ++ ++ /* Since firstInFrame is not NULL, one buffer at least has already been ++ inserted into the BD ring. Using do-while covers the situation of a ++ frame spanned throughout the whole Tx BD ring (p_CleanBd is incremented ++ prior to testing whether or not it's equal to TxBd). */ ++ do ++ { ++ BD_STATUS_AND_LENGTH_SET(BD_GET(cleanBdId), 0); ++ /* Advance BD pointer */ ++ cleanBdId = GetNextBdId(p_FmPort, cleanBdId); ++ } while (cleanBdId != p_FmPort->im.currBdId); ++ ++ p_FmPort->im.currBdId = cleanBdId; ++ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID; ++ } ++ ++ return ERROR_CODE(E_FULL); ++ } ++ ++ return E_OK; ++} ++ ++void FM_PORT_ImTxConf(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ TxConf(p_FmPort, e_TX_CONF_TYPE_CALLBACK); ++} ++ ++t_Error FM_PORT_ImRx(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ return FmPortImRx(p_FmPort); ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Rtc/Makefile b/drivers/net/dpa/NetCommSw/Peripherals/FM/Rtc/Makefile +new file mode 100644 +index 0000000..dbe51ff +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Rtc/Makefile +@@ -0,0 +1,15 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/dpa/NetCommSw/Peripherals/FM/inc ++ ++EXTRA_CFLAGS += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-RTC.o ++ ++fsl-ncsw-RTC-objs := fm_rtc.o +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Rtc/fm_rtc.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/Rtc/fm_rtc.c +new file mode 100644 +index 0000000..d65b1d4 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Rtc/fm_rtc.c +@@ -0,0 +1,878 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_rtc.c ++ ++ @Description FM RTC driver implementation. ++ ++ @Cautions None ++*//***************************************************************************/ ++ ++#include "error_ext.h" ++#include "debug_ext.h" ++#include "string_ext.h" ++#include "part_ext.h" ++#include "xx_ext.h" ++#include "ncsw_ext.h" ++ ++#include "fm_rtc.h" ++#include "fm_common.h" ++ ++ ++/*****************************************************************************/ ++static void SetDefaultParam(t_FmRtc *p_Rtc) ++{ ++ t_FmRtcDriverParam *p_RtcDriverParam = p_Rtc->p_RtcDriverParam; ++ int i; ++ ++ p_Rtc->outputClockDivisor = DEFAULT_outputClockDivisor; ++ p_Rtc->p_RtcDriverParam->bypass = DEFAULT_bypass; ++ p_RtcDriverParam->srcClk = DEFAULT_srcClock; ++ p_RtcDriverParam->invertInputClkPhase = DEFAULT_invertInputClkPhase; ++ p_RtcDriverParam->invertOutputClkPhase = DEFAULT_invertOutputClkPhase; ++ p_RtcDriverParam->pulseRealign = DEFAULT_pulseRealign; ++ for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++) ++ { ++ p_RtcDriverParam->alarmPolarity[i] = DEFAULT_alarmPolarity; ++ } ++ for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++) ++ { ++ p_RtcDriverParam->triggerPolarity[i] = DEFAULT_triggerPolarity; ++ } ++ p_Rtc->clockPeriodNanoSec = DEFAULT_clockPeriod; /* 1 usec */ ++} ++ ++/*****************************************************************************/ ++static t_Error CheckInitParameters(t_FmRtc *p_Rtc) ++{ ++ t_FmRtcDriverParam *p_RtcDriverParam = p_Rtc->p_RtcDriverParam; ++ int i; ++ ++ if ((p_RtcDriverParam->srcClk != e_FM_RTC_SOURCE_CLOCK_EXTERNAL) && ++ (p_RtcDriverParam->srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM) && ++ (p_RtcDriverParam->srcClk != e_FM_RTC_SOURCE_CLOCK_OSCILATOR)) ++ RETURN_ERROR(MAJOR, E_INVALID_CLOCK, ("Source clock undefined")); ++ ++ if (p_Rtc->outputClockDivisor == 0) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("Divisor for output clock (should be positive)")); ++ } ++ ++ for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++) ++ { ++ if ((p_RtcDriverParam->alarmPolarity[i] != e_FM_RTC_ALARM_POLARITY_ACTIVE_LOW) && ++ (p_RtcDriverParam->alarmPolarity[i] != e_FM_RTC_ALARM_POLARITY_ACTIVE_HIGH)) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm %d signal polarity", i)); ++ } ++ } ++ for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++) ++ { ++ if ((p_RtcDriverParam->triggerPolarity[i] != e_FM_RTC_TRIGGER_ON_FALLING_EDGE) && ++ (p_RtcDriverParam->triggerPolarity[i] != e_FM_RTC_TRIGGER_ON_RISING_EDGE)) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Trigger %d signal polarity", i)); ++ } ++ } ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++static void RtcExceptions(t_Handle h_FmRtc) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ t_FmRtcMemMap *p_MemMap; ++ register uint32_t events; ++ ++ ASSERT_COND(p_Rtc); ++ p_MemMap = p_Rtc->p_MemMap; ++ ++ /* Get valid events */ ++ events = GET_UINT32(p_MemMap->tmr_tevent); ++ events &= GET_UINT32(p_MemMap->tmr_temask); ++ ++ /* Clear event bits */ ++ WRITE_UINT32(p_MemMap->tmr_tevent, events); ++ ++ if (events & TMR_TEVENT_ALM1) ++ { ++ if (p_Rtc->alarmParams[0].clearOnExpiration) ++ { ++ WRITE_UINT32(p_MemMap->tmr_alarm[0].tmr_alarm_l, 0); ++ WRITE_UINT32(p_MemMap->tmr_temask, GET_UINT32(p_MemMap->tmr_temask) & ~TMR_TEVENT_ALM1); ++ } ++ ASSERT_COND(p_Rtc->alarmParams[0].f_AlarmCallback); ++ p_Rtc->alarmParams[0].f_AlarmCallback(p_Rtc->h_App, 0); ++ } ++ if (events & TMR_TEVENT_ALM2) ++ { ++ if (p_Rtc->alarmParams[1].clearOnExpiration) ++ { ++ WRITE_UINT32(p_MemMap->tmr_alarm[1].tmr_alarm_l, 0); ++ WRITE_UINT32(p_MemMap->tmr_temask, GET_UINT32(p_MemMap->tmr_temask) & ~TMR_TEVENT_ALM2); ++ } ++ ASSERT_COND(p_Rtc->alarmParams[1].f_AlarmCallback); ++ p_Rtc->alarmParams[1].f_AlarmCallback(p_Rtc->h_App, 1); ++ } ++ if (events & TMR_TEVENT_PP1) ++ { ++ ASSERT_COND(p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback); ++ p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback(p_Rtc->h_App, 0); ++ } ++ if (events & TMR_TEVENT_PP2) ++ { ++ ASSERT_COND(p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback); ++ p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback(p_Rtc->h_App, 1); ++ } ++ if (events & TMR_TEVENT_ETS1) ++ { ++ ASSERT_COND(p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback); ++ p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback(p_Rtc->h_App, 0); ++ } ++ if (events & TMR_TEVENT_ETS2) ++ { ++ ASSERT_COND(p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback); ++ p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback(p_Rtc->h_App, 1); ++ } ++} ++ ++ ++/*****************************************************************************/ ++t_Handle FM_RTC_Config(t_FmRtcParams *p_FmRtcParam) ++{ ++ t_FmRtc *p_Rtc; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmRtcParam, E_NULL_POINTER, NULL); ++ ++ /* Allocate memory for the FM RTC driver parameters */ ++ p_Rtc = (t_FmRtc *)XX_Malloc(sizeof(t_FmRtc)); ++ if (!p_Rtc) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver structure")); ++ return NULL; ++ } ++ ++ memset(p_Rtc, 0, sizeof(t_FmRtc)); ++ ++ /* Allocate memory for the FM RTC driver parameters */ ++ p_Rtc->p_RtcDriverParam = (t_FmRtcDriverParam *)XX_Malloc(sizeof(t_FmRtcDriverParam)); ++ if (!p_Rtc->p_RtcDriverParam) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver parameters")); ++ XX_Free(p_Rtc); ++ return NULL; ++ } ++ ++ memset(p_Rtc->p_RtcDriverParam, 0, sizeof(t_FmRtcDriverParam)); ++ ++ /* Store RTC configuration parameters */ ++ p_Rtc->h_Fm = p_FmRtcParam->h_Fm; ++ ++ /* Set default RTC configuration parameters */ ++ SetDefaultParam(p_Rtc); ++ ++ /* Store RTC parameters in the RTC control structure */ ++ p_Rtc->p_MemMap = (t_FmRtcMemMap *)UINT_TO_PTR(p_FmRtcParam->baseAddress); ++ p_Rtc->h_App = p_FmRtcParam->h_App; ++ ++ return p_Rtc; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_Init(t_Handle h_FmRtc) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ t_FmRtcDriverParam *p_RtcDriverParam; ++ t_FmRtcMemMap *p_MemMap; ++ uint32_t freqCompensation; ++ uint32_t tmrCtrl; ++ int i; ++ uint64_t tmpDouble; ++ ++ p_RtcDriverParam = p_Rtc->p_RtcDriverParam; ++ p_MemMap = p_Rtc->p_MemMap; ++ ++ if (CheckInitParameters(p_Rtc)!=E_OK) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ++ ("Init Parameters are not Valid")); ++ ++ /* TODO check that no timestamping MACs are working in this stage. */ ++ WRITE_UINT32(p_MemMap->tmr_ctrl, TMR_CTRL_TMSR); ++ XX_UDelay(10); ++ WRITE_UINT32(p_MemMap->tmr_ctrl, 0); ++ ++ /* Set the source clock */ ++ switch (p_RtcDriverParam->srcClk) ++ { ++ case e_FM_RTC_SOURCE_CLOCK_SYSTEM: ++ tmrCtrl = TMR_CTRL_CKSEL_MAC_CLK; ++ break; ++ case e_FM_RTC_SOURCE_CLOCK_OSCILATOR: ++ tmrCtrl = TMR_CTRL_CKSEL_OSC_CLK; ++ break; ++ default: ++ /* Use a clock from the External TMR reference clock.*/ ++ tmrCtrl = TMR_CTRL_CKSEL_EXT_CLK; ++ break; ++ } ++ ++ /* whatever period the user picked, the timestamp will advance in '1' every time ++ * the period passed. */ ++ tmrCtrl |= ((1 << TMR_CTRL_TCLK_PERIOD_SHIFT) & TMR_CTRL_TCLK_PERIOD_MASK); ++ ++ if (p_RtcDriverParam->invertInputClkPhase) ++ tmrCtrl |= TMR_CTRL_CIPH; ++ if (p_RtcDriverParam->invertOutputClkPhase) ++ tmrCtrl |= TMR_CTRL_COPH; ++ ++ for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++) ++ { ++ if (p_RtcDriverParam->alarmPolarity[i] == e_FM_RTC_ALARM_POLARITY_ACTIVE_LOW) ++ tmrCtrl |= (TMR_CTRL_ALMP1 >> i); ++ } ++ ++ for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++) ++ if (p_RtcDriverParam->triggerPolarity[i] == e_FM_RTC_TRIGGER_ON_FALLING_EDGE) ++ tmrCtrl |= (TMR_CTRL_ETEP1 << i); ++ ++ if (!p_RtcDriverParam->timerSlaveMode && p_Rtc->p_RtcDriverParam->bypass) ++ tmrCtrl |= TMR_CTRL_BYP; ++ ++ WRITE_UINT32(p_MemMap->tmr_ctrl, tmrCtrl); ++ ++ for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++) ++ { ++ /* Clear TMR_ALARM registers */ ++ WRITE_UINT32(p_MemMap->tmr_alarm[i].tmr_alarm_l, 0xFFFFFFFF); ++ WRITE_UINT32(p_MemMap->tmr_alarm[i].tmr_alarm_h, 0xFFFFFFFF); ++ } ++ ++ /* Clear TMR_TEVENT */ ++ WRITE_UINT32(p_MemMap->tmr_tevent, TMR_TEVENT_ALL); ++ ++ /* Initialize TMR_TEMASK */ ++ WRITE_UINT32(p_MemMap->tmr_temask, 0); ++ ++ ++ /* find source clock frequency in Mhz */ ++ if (p_Rtc->p_RtcDriverParam->srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM) ++ p_Rtc->srcClkFreqMhz = p_Rtc->p_RtcDriverParam->extSrcClkFreq; ++ else ++ p_Rtc->srcClkFreqMhz = (uint32_t)(FmGetClockFreq(p_Rtc->h_Fm)/2); ++ ++ /* if timer in Master mode Initialize TMR_CTRL */ ++ /* We want the counter (TMR_CNT) to count in nano-seconds */ ++ if (!p_RtcDriverParam->timerSlaveMode && p_Rtc->p_RtcDriverParam->bypass) ++ { ++ p_Rtc->clockPeriodNanoSec = (1000 / p_Rtc->srcClkFreqMhz); ++ } ++ else ++ { ++ /* Initialize TMR_ADD with the initial frequency compensation value: ++ freqCompensation = (2^32 / frequency ratio) */ ++ /* frequency ratio = sorce clock/rtc clock = ++ * (p_Rtc->srcClkFreqMhz*1000000))/ 1/(p_Rtc->clockPeriodNanoSec * 1000000000) */ ++ freqCompensation = (uint32_t)DIV_CEIL(ACCUMULATOR_OVERFLOW * 1000, ++ p_Rtc->clockPeriodNanoSec * p_Rtc->srcClkFreqMhz); ++ WRITE_UINT32(p_MemMap->tmr_add, freqCompensation); ++ } ++ /* check the legality of the relation between source and destination clocks */ ++ /* should be larger than 1.0001 */ ++ tmpDouble = 10000 * (uint64_t)p_Rtc->clockPeriodNanoSec * (uint64_t)p_Rtc->srcClkFreqMhz; ++ if ((tmpDouble) <= 10001) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ++ ("Invalid relation between source and destination clocks. Should be larger than 1.0001")); ++ ++ ++ for (i=0; i < 2; i++) ++ /* Clear TMR_FIPER registers */ ++ WRITE_UINT32(p_MemMap->tmr_fiper[i], 0xFFFFFFFF); ++ ++ /* Initialize TMR_PRSC */ ++ WRITE_UINT32(p_MemMap->tmr_prsc, p_Rtc->outputClockDivisor); ++ ++ /* Clear TMR_OFF */ ++ WRITE_UINT32(p_MemMap->tmr_off_l, 0); ++ WRITE_UINT32(p_MemMap->tmr_off_h, 0); ++ ++ /* Register the FM RTC interrupt */ ++ FmRegisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL, RtcExceptions , p_Rtc); ++ ++ /* Free parameters structures */ ++ XX_Free(p_Rtc->p_RtcDriverParam); ++ p_Rtc->p_RtcDriverParam = NULL; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_Free(t_Handle h_FmRtc) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ ++ if (p_Rtc->p_RtcDriverParam) ++ { ++ XX_Free(p_Rtc->p_RtcDriverParam); ++ } ++ else ++ { ++ FM_RTC_Disable(h_FmRtc); ++ } ++ ++ /* Unregister FM RTC interrupt */ ++ FmUnregisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL); ++ XX_Free(p_Rtc); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigSourceClock(t_Handle h_FmRtc, ++ e_FmSrcClk srcClk, ++ uint32_t freqInMhz) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->p_RtcDriverParam->srcClk = srcClk; ++ if (srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM) ++ p_Rtc->p_RtcDriverParam->extSrcClkFreq = freqInMhz; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigPeriod(t_Handle h_FmRtc, uint32_t period) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->clockPeriodNanoSec = period; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigFrequencyBypass(t_Handle h_FmRtc, bool enabled) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->p_RtcDriverParam->bypass = enabled; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigInvertedInputClockPhase(t_Handle h_FmRtc, bool inverted) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->p_RtcDriverParam->invertInputClkPhase = inverted; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigInvertedOutputClockPhase(t_Handle h_FmRtc, bool inverted) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->p_RtcDriverParam->invertOutputClkPhase = inverted; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigOutputClockDivisor(t_Handle h_FmRtc, uint16_t divisor) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->outputClockDivisor = divisor; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigPulseRealignment(t_Handle h_FmRtc, bool enable) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->p_RtcDriverParam->pulseRealign = enable; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigAlarmPolarity(t_Handle h_FmRtc, ++ uint8_t alarmId, ++ e_FmRtcAlarmPolarity alarmPolarity) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (alarmId >= FM_RTC_NUM_OF_ALARMS) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID")); ++ } ++ ++ p_Rtc->p_RtcDriverParam->alarmPolarity[alarmId] = alarmPolarity; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigExternalTriggerPolarity(t_Handle h_FmRtc, ++ uint8_t triggerId, ++ e_FmRtcTriggerPolarity triggerPolarity) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID")); ++ } ++ ++ p_Rtc->p_RtcDriverParam->triggerPolarity[triggerId] = triggerPolarity; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_Enable(t_Handle h_FmRtc, bool resetClock) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ uint32_t tmrCtrl; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ tmrCtrl = GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl); ++ ++ /* TODO check that no timestamping MACs are working in this stage. */ ++ if (resetClock) ++ { ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, (tmrCtrl | TMR_CTRL_TMSR)); ++ ++ XX_UDelay(10); ++ /* Clear TMR_OFF */ ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_off_l, 0); ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_off_h, 0); ++ } ++ ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, (tmrCtrl | TMR_CTRL_TE)); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_Disable(t_Handle h_FmRtc) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ uint32_t tmrCtrl; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ /* TODO A check must be added here, that no timestamping MAC's ++ * are working in this stage. */ ++ tmrCtrl = GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl); ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, (tmrCtrl & ~(TMR_CTRL_TE))); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_SetClockOffset(t_Handle h_FmRtc, int64_t offset) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ /* TMR_OFF_L must be written first */ ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_off_l, (uint32_t)offset); ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_off_h, (uint32_t)(offset >> 32)); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_SetAlarm(t_Handle h_FmRtc, t_FmRtcAlarmParams *p_FmRtcAlarmParams) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ t_FmRtcMemMap *p_MemMap; ++ uint32_t tmpReg; ++ uint64_t tmpAlarm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_MemMap = p_Rtc->p_MemMap; ++ ++ if (p_FmRtcAlarmParams->alarmId >= FM_RTC_NUM_OF_ALARMS) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID")); ++ } ++ ++ if (p_FmRtcAlarmParams->alarmTime < p_Rtc->clockPeriodNanoSec) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm time must be equal or larger than RTC period - %d nanoseconds", p_Rtc->clockPeriodNanoSec)); ++ if (p_FmRtcAlarmParams->alarmTime % (uint64_t)p_Rtc->clockPeriodNanoSec) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm time must be a multiple of RTC period - %d nanoseconds", p_Rtc->clockPeriodNanoSec)); ++ tmpAlarm = p_FmRtcAlarmParams->alarmTime/(uint64_t)p_Rtc->clockPeriodNanoSec; ++ ++ /* TMR_ALARM_L must be written first */ ++ WRITE_UINT32(p_MemMap->tmr_alarm[p_FmRtcAlarmParams->alarmId].tmr_alarm_l, (uint32_t)tmpAlarm); ++ WRITE_UINT32(p_MemMap->tmr_alarm[p_FmRtcAlarmParams->alarmId].tmr_alarm_h, ++ (uint32_t)(tmpAlarm >> 32)); ++ ++ if (p_FmRtcAlarmParams->f_AlarmCallback) ++ { ++ p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].f_AlarmCallback = p_FmRtcAlarmParams->f_AlarmCallback; ++ p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].clearOnExpiration = p_FmRtcAlarmParams->clearOnExpiration; ++ ++ if (p_FmRtcAlarmParams->alarmId == 0) ++ tmpReg = TMR_TEVENT_ALM1; ++ else ++ tmpReg = TMR_TEVENT_ALM2; ++ WRITE_UINT32(p_MemMap->tmr_temask, GET_UINT32(p_MemMap->tmr_temask) | tmpReg); ++ } ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_SetPeriodicPulse(t_Handle h_FmRtc, t_FmRtcPeriodicPulseParams *p_FmRtcPeriodicPulseParams) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ t_FmRtcMemMap *p_MemMap; ++ uint32_t tmpReg; ++ uint64_t tmpFiper; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_MemMap = p_Rtc->p_MemMap; ++ ++ if (p_FmRtcPeriodicPulseParams->periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID")); ++ } ++ if (GET_UINT32(p_MemMap->tmr_ctrl) & TMR_CTRL_TE) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Can't set Periodic pulse when RTC is enabled.")); ++ if (p_FmRtcPeriodicPulseParams->periodicPulsePeriod < p_Rtc->clockPeriodNanoSec) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse must be equal or larger than RTC period - %d nanoseconds", p_Rtc->clockPeriodNanoSec)); ++ if (p_FmRtcPeriodicPulseParams->periodicPulsePeriod % (uint64_t)p_Rtc->clockPeriodNanoSec) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse must be a multiple of RTC period - %d nanoseconds", p_Rtc->clockPeriodNanoSec)); ++ tmpFiper = p_FmRtcPeriodicPulseParams->periodicPulsePeriod/(uint64_t)p_Rtc->clockPeriodNanoSec; ++ if (tmpFiper & 0xffffffff00000000LL) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse/RTC Period must be smaller than 4294967296", p_Rtc->clockPeriodNanoSec)); ++ ++ WRITE_UINT32(p_MemMap->tmr_fiper[p_FmRtcPeriodicPulseParams->periodicPulseId], (uint32_t)tmpFiper); ++ ++ if (p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback) ++ { ++ p_Rtc->periodicPulseParams[p_FmRtcPeriodicPulseParams->periodicPulseId].f_PeriodicPulseCallback = ++ p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback; ++ ++ if (p_FmRtcPeriodicPulseParams->periodicPulseId == 0) ++ tmpReg = TMR_TEVENT_PP1; ++ else ++ tmpReg = TMR_TEVENT_PP2; ++ WRITE_UINT32(p_MemMap->tmr_temask, GET_UINT32(p_MemMap->tmr_temask) | tmpReg); ++ } ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ClearPeriodicPulse(t_Handle h_FmRtc, uint8_t periodicPulseId) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID")); ++ } ++ ++ p_Rtc->periodicPulseParams[periodicPulseId].f_PeriodicPulseCallback = NULL; ++ ++ if (periodicPulseId == 0) ++ tmpReg = TMR_TEVENT_PP1; ++ else ++ tmpReg = TMR_TEVENT_PP2; ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_temask, GET_UINT32(p_Rtc->p_MemMap->tmr_temask) & ~tmpReg); ++ ++ if (GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) & TMR_CTRL_FS) ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) & ~TMR_CTRL_FS); ++ ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_fiper[periodicPulseId], 0xFFFFFFFF); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_SetExternalTrigger(t_Handle h_FmRtc, t_FmRtcExternalTriggerParams *p_FmRtcExternalTriggerParams) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (p_FmRtcExternalTriggerParams->externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID")); ++ } ++ ++ if (p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback) ++ { ++ p_Rtc->externalTriggerParams[p_FmRtcExternalTriggerParams->externalTriggerId].f_ExternalTriggerCallback = p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback; ++ if (p_FmRtcExternalTriggerParams->externalTriggerId == 0) ++ tmpReg = TMR_TEVENT_ETS1; ++ else ++ tmpReg = TMR_TEVENT_ETS2; ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_temask, GET_UINT32(p_Rtc->p_MemMap->tmr_temask) | tmpReg); ++ } ++ ++ if (p_FmRtcExternalTriggerParams->usePulseAsInput) ++ { ++ if (p_FmRtcExternalTriggerParams->externalTriggerId == 0) ++ tmpReg = TMR_CTRL_PP1L; ++ else ++ tmpReg = TMR_CTRL_PP2L; ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) | tmpReg); ++ } ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ClearExternalTrigger(t_Handle h_FmRtc, uint8_t externalTriggerId) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID")); ++ ++ p_Rtc->externalTriggerParams[externalTriggerId].f_ExternalTriggerCallback = NULL; ++ ++ if (externalTriggerId == 0) ++ tmpReg = TMR_TEVENT_ETS1; ++ else ++ tmpReg = TMR_TEVENT_ETS2; ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_temask, GET_UINT32(p_Rtc->p_MemMap->tmr_temask) & ~tmpReg); ++ ++ if (externalTriggerId == 0) ++ tmpReg = TMR_CTRL_PP1L; ++ else ++ tmpReg = TMR_CTRL_PP2L; ++ ++ if (GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) & tmpReg) ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) & ~tmpReg); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_GetExternalTriggerTimeStamp(t_Handle h_FmRtc, ++ uint8_t triggerId, ++ uint64_t *p_TimeStamp) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ uint64_t timeStamp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID")); ++ } ++ ++ timeStamp = (uint64_t)GET_UINT32(p_Rtc->p_MemMap->tmr_etts[triggerId].tmr_etts_l); ++ timeStamp |= ((uint64_t)GET_UINT32(p_Rtc->p_MemMap->tmr_etts[triggerId].tmr_etts_h) << 32); ++ ++ timeStamp = timeStamp*p_Rtc->clockPeriodNanoSec; ++ *p_TimeStamp = timeStamp; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_GetCurrentTime(t_Handle h_FmRtc, uint64_t *p_Ts) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ uint64_t time; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ /* TMR_CNT_L must be read first to get an accurate value */ ++ time = (uint64_t)GET_UINT32(p_Rtc->p_MemMap->tmr_cnt_l); ++ time |= ((uint64_t)GET_UINT32(p_Rtc->p_MemMap->tmr_cnt_h) << 32); ++ ++ time = time*p_Rtc->clockPeriodNanoSec; ++ ++ *p_Ts = time; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_SetCurrentTime(t_Handle h_FmRtc, uint64_t ts) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ ts = ts/p_Rtc->clockPeriodNanoSec; ++ /* TMR_CNT_L must be written first to get an accurate value */ ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_cnt_l, (uint32_t)ts); ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_cnt_h, (uint32_t)(ts >> 32)); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_GetFreqCompensation(t_Handle h_FmRtc, uint32_t *p_Compensation) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ *p_Compensation = GET_UINT32(p_Rtc->p_MemMap->tmr_add); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_SetFreqCompensation(t_Handle h_FmRtc, uint32_t freqCompensation) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ /* set the new freqCompensation */ ++ WRITE_UINT32(p_Rtc->p_MemMap->tmr_add, freqCompensation); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++t_Error FM_RTC_DumpRegs(t_Handle h_FmRtc) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ t_FmRtcMemMap *p_MemMap = p_Rtc->p_MemMap; ++ int i = 0; ++ ++ DECLARE_DUMP; ++ ++ if (p_MemMap) ++ { ++ ++ DUMP_TITLE(p_MemMap, ("RTC:")); ++ DUMP_VAR(p_MemMap, tmr_id); ++ DUMP_VAR(p_MemMap, tmr_id2); ++ DUMP_VAR(p_MemMap, tmr_ctrl); ++ DUMP_VAR(p_MemMap, tmr_tevent); ++ DUMP_VAR(p_MemMap, tmr_temask); ++ DUMP_VAR(p_MemMap, tmr_cnt_h); ++ DUMP_VAR(p_MemMap, tmr_cnt_l); ++ DUMP_VAR(p_MemMap, tmr_ctrl); ++ DUMP_VAR(p_MemMap, tmr_add); ++ DUMP_VAR(p_MemMap, tmr_acc); ++ DUMP_VAR(p_MemMap, tmr_prsc); ++ DUMP_VAR(p_MemMap, tmr_off_h); ++ DUMP_VAR(p_MemMap, tmr_off_l); ++ ++ DUMP_SUBSTRUCT_ARRAY(i, 2) ++ { ++ DUMP_VAR(p_MemMap, tmr_alarm[i].tmr_alarm_h); ++ DUMP_VAR(p_MemMap, tmr_alarm[i].tmr_alarm_l); ++ } ++ DUMP_SUBSTRUCT_ARRAY(i, 2) ++ { ++ DUMP_VAR(p_MemMap, tmr_fiper[i]); ++ DUMP_VAR(p_MemMap, tmr_fiper[i]); ++ } ++ DUMP_SUBSTRUCT_ARRAY(i, 2) ++ { ++ DUMP_VAR(p_MemMap, tmr_etts[i].tmr_etts_l); ++ DUMP_VAR(p_MemMap, tmr_etts[i].tmr_etts_l); ++ } ++ } ++ ++ return E_OK; ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/Rtc/fm_rtc.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/Rtc/fm_rtc.h +new file mode 100644 +index 0000000..4c1a422 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/Rtc/fm_rtc.h +@@ -0,0 +1,216 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_rtc.h ++ ++ @Description Memory map and internal definitions for FM RTC IEEE1588 Timer driver. ++ ++ @Cautions None ++*//***************************************************************************/ ++ ++#ifndef __FM_RTC_H__ ++#define __FM_RTC_H__ ++ ++#include "std_ext.h" ++#include "fm_rtc_ext.h" ++ ++ ++#define __ERR_MODULE__ MODULE_FM_RTC ++ ++/* General definitions */ ++ ++#define NANOSEC_PER_ONE_HZ_TICK 1000000000 ++#define MIN_RTC_CLK_FREQ_HZ 1000 ++#define MHz 1000000 ++ ++#define ACCUMULATOR_OVERFLOW ((uint64_t)(1LL << 32)) ++ ++/* RTC default values */ ++#define DEFAULT_srcClock e_FM_RTC_SOURCE_CLOCK_SYSTEM ++#define DEFAULT_bypass FALSE ++#define DEFAULT_invertInputClkPhase FALSE ++#define DEFAULT_invertOutputClkPhase FALSE ++#define DEFAULT_outputClockDivisor 0x00000002 ++#define DEFAULT_alarmPolarity e_FM_RTC_ALARM_POLARITY_ACTIVE_HIGH ++#define DEFAULT_triggerPolarity e_FM_RTC_TRIGGER_ON_FALLING_EDGE ++#define DEFAULT_pulseRealign FALSE ++#define DEFAULT_clockPeriod 1000 ++ ++/* FM RTC Registers definitions */ ++#define TMR_CTRL_ALMP1 0x80000000 ++#define TMR_CTRL_ALMP2 0x40000000 ++#define TMR_CTRL_FS 0x10000000 ++#define TMR_CTRL_PP1L 0x08000000 ++#define TMR_CTRL_PP2L 0x04000000 ++#define TMR_CTRL_TCLK_PERIOD_MASK 0x03FF0000 ++#define TMR_CTRL_FRD 0x00004000 ++#define TMR_CTRL_SLV 0x00002000 ++#define TMR_CTRL_ETEP1 0x00000100 ++#define TMR_CTRL_COPH 0x00000080 ++#define TMR_CTRL_CIPH 0x00000040 ++#define TMR_CTRL_TMSR 0x00000020 ++#define TMR_CTRL_DBG 0x00000010 ++#define TMR_CTRL_BYP 0x00000008 ++#define TMR_CTRL_TE 0x00000004 ++#define TMR_CTRL_CKSEL_OSC_CLK 0x00000003 ++#define TMR_CTRL_CKSEL_MAC_CLK 0x00000001 ++#define TMR_CTRL_CKSEL_EXT_CLK 0x00000000 ++#define TMR_CTRL_TCLK_PERIOD_SHIFT 16 ++ ++#define TMR_TEVENT_ETS2 0x02000000 ++#define TMR_TEVENT_ETS1 0x01000000 ++#define TMR_TEVENT_ALM2 0x00020000 ++#define TMR_TEVENT_ALM1 0x00010000 ++#define TMR_TEVENT_PP1 0x00000080 ++#define TMR_TEVENT_PP2 0x00000040 ++#define TMR_TEVENT_PP3 0x00000020 ++#define TMR_TEVENT_ALL (TMR_TEVENT_ETS2 | TMR_TEVENT_ETS1 | \ ++ TMR_TEVENT_ALM2 | TMR_TEVENT_ALM1 | \ ++ TMR_TEVENT_PP1 | TMR_TEVENT_PP2 | TMR_TEVENT_PP3) ++ ++#define TMR_PRSC_OCK_MASK 0x0000FFFF ++ ++ ++/**************************************************************************//** ++ @Description Memory Mapped Registers ++*//***************************************************************************/ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description FM RTC timer alarm ++*//***************************************************************************/ ++typedef _Packed struct t_TmrAlaram ++{ ++ volatile uint32_t tmr_alarm_h; /**< */ ++ volatile uint32_t tmr_alarm_l; /**< */ ++} _PackedType t_TmrAlaram; ++ ++/**************************************************************************//** ++ @Description FM RTC timer Ex trigger ++*//***************************************************************************/ ++typedef _Packed struct t_TmrExtTrigger ++{ ++ volatile uint32_t tmr_etts_h; /**< */ ++ volatile uint32_t tmr_etts_l; /**< */ ++} _PackedType t_TmrExtTrigger; ++ ++typedef _Packed struct ++{ ++ volatile uint32_t tmr_id; /* Module ID and version register */ ++ volatile uint32_t tmr_id2; /* Module ID and configuration register */ ++ volatile uint32_t PTP_RESERVED1[30]; ++ volatile uint32_t tmr_ctrl; /* timer control register */ ++ volatile uint32_t tmr_tevent; /* timer event register */ ++ volatile uint32_t tmr_temask; /* timer event mask register */ ++ volatile uint32_t PTP_RESERVED2[3]; ++ volatile uint32_t tmr_cnt_h; /* timer counter high register */ ++ volatile uint32_t tmr_cnt_l; /* timer counter low register */ ++ volatile uint32_t tmr_add; /* timer drift compensation addend register */ ++ volatile uint32_t tmr_acc; /* timer accumulator register */ ++ volatile uint32_t tmr_prsc; /* timer prescale */ ++ volatile uint32_t PTP_RESERVED3; ++ volatile uint32_t tmr_off_h; /* timer offset high */ ++ volatile uint32_t tmr_off_l; /* timer offset low */ ++ volatile t_TmrAlaram tmr_alarm[FM_RTC_NUM_OF_ALARMS]; /* timer alarm */ ++ volatile uint32_t PTP_RESERVED4[2]; ++ volatile uint32_t tmr_fiper[FM_RTC_NUM_OF_PERIODIC_PULSES]; /* timer fixed period interval */ ++ volatile uint32_t PTP_RESERVED5[2]; ++ volatile t_TmrExtTrigger tmr_etts[FM_RTC_NUM_OF_EXT_TRIGGERS]; /*time stamp general purpose external */ ++ volatile uint32_t PTP_RESERVED6[3]; ++} _PackedType t_FmRtcMemMap; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/**************************************************************************//** ++ @Description RTC FM driver parameters structure. ++*//***************************************************************************/ ++typedef struct t_FmRtcDriverParam ++{ ++ t_Handle h_Fm; /**< */ ++ e_FmSrcClk srcClk; /**< */ ++ uint32_t extSrcClkFreq; /**< */ ++ uint32_t rtcFreqHz; /**< */ ++ bool timerSlaveMode; /*Slave/Master Mode*/ ++ bool invertInputClkPhase; ++ bool invertOutputClkPhase; ++ uint32_t eventsMask; ++ bool bypass; /**< Indicates if frequency compensation is bypassed */ ++ bool pulseRealign; ++ e_FmRtcAlarmPolarity alarmPolarity[FM_RTC_NUM_OF_ALARMS]; ++ e_FmRtcTriggerPolarity triggerPolarity[FM_RTC_NUM_OF_EXT_TRIGGERS]; ++} t_FmRtcDriverParam; ++ ++typedef struct t_FmRtcAlarm ++{ ++ t_FmRtcExceptionsCallback *f_AlarmCallback; ++ bool clearOnExpiration; ++} t_FmRtcAlarm; ++ ++typedef struct t_FmRtcPeriodicPulse ++{ ++ t_FmRtcExceptionsCallback *f_PeriodicPulseCallback; ++} t_FmRtcPeriodicPulse; ++ ++typedef struct t_FmRtcExternalTrigger ++{ ++ t_FmRtcExceptionsCallback *f_ExternalTriggerCallback; ++} t_FmRtcExternalTrigger; ++ ++ ++/**************************************************************************//** ++ @Description RTC FM driver control structure. ++*//***************************************************************************/ ++typedef struct t_FmRtc ++{ ++ t_Part *p_Part; /**< Pointer to the integration device */ ++ t_Handle h_Fm; ++ t_Handle h_App; /**< Application handle */ ++ t_FmRtcMemMap *p_MemMap; /**< Pointer to RTC memory map */ ++ uint32_t clockPeriodNanoSec; /**< RTC clock period in nano-seconds (for FS mode) */ ++ uint32_t srcClkFreqMhz; ++ uint16_t outputClockDivisor; /**< Output clock divisor (for FS mode) */ ++ t_FmRtcAlarm alarmParams[FM_RTC_NUM_OF_ALARMS]; ++ t_FmRtcPeriodicPulse periodicPulseParams[FM_RTC_NUM_OF_PERIODIC_PULSES]; ++ t_FmRtcExternalTrigger externalTriggerParams[FM_RTC_NUM_OF_EXT_TRIGGERS]; ++ t_FmRtcDriverParam *p_RtcDriverParam; /**< RTC Driver parameters (for Init phase) */ ++} t_FmRtc; ++ ++ ++#endif /* __FM_RTC_H__ */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/SP/Makefile b/drivers/net/dpa/NetCommSw/Peripherals/FM/SP/Makefile +new file mode 100644 +index 0000000..ad469cd +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/SP/Makefile +@@ -0,0 +1,15 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/dpa/NetCommSw/Peripherals/FM/inc ++ ++EXTRA_CFLAGS += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-sp.o ++ ++fsl-ncsw-sp-objs := fm_sp.o +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/SP/fm_sp.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/SP/fm_sp.c +new file mode 100644 +index 0000000..a457078 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/SP/fm_sp.c +@@ -0,0 +1,857 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_sp.c ++ ++ @Description FM PCD Storage profile ... ++*//***************************************************************************/ ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "net_ext.h" ++ ++#include "fm_vsp_ext.h" ++#include "fm_sp.h" ++#include "fm_common.h" ++ ++ ++#if (DPAA_VERSION >= 11) ++ ++static void fm_vsp_fill_entry(fm_pcd_storage_profile_regs *regs, ++ uint16_t index, ++ fm_storage_profile_params *fm_vsp_params) ++{ ++ int i = 0, j = 0; ++ fm_pcd_storage_profile_regs *sp_regs; ++ uint32_t tmp_reg, vector; ++ t_FmExtPools *ext_buf_pools = fm_vsp_params->fm_ext_pools; ++ t_FmBufPoolDepletion *buf_pool_depletion= fm_vsp_params->buf_pool_depletion; ++ t_FmBackupBmPools *backup_pools = fm_vsp_params->backup_pools; ++ t_FmSpIntContextDataCopy *int_context_data_copy = fm_vsp_params->int_context; ++ t_FmSpBufMargins *external_buffer_margins = fm_vsp_params->buf_margins; ++ bool no_scather_gather = fm_vsp_params->no_scather_gather; ++ uint16_t liodn_offset = fm_vsp_params->liodn_offset; ++ ++ ASSERT_COND(regs); ++ ASSERT_COND(ext_buf_pools); ++ ASSERT_COND(int_context_data_copy); ++ ASSERT_COND(external_buffer_margins); ++ ASSERT_COND(IN_RANGE(0, index, FM_VSP_MAX_NUM_OF_ENTRIES)); ++ ++ sp_regs = ®s[index]; ++ ++ /* fill external buffers manager pool information register*/ ++ for (i=0;inumOfPoolsUsed;i++) ++ { ++ tmp_reg = FM_SP_EXT_BUF_POOL_VALID | FM_SP_EXT_BUF_POOL_EN_COUNTER; ++ tmp_reg |= ((uint32_t)ext_buf_pools->extBufPool[i].id << FM_SP_EXT_BUF_POOL_ID_SHIFT); ++ tmp_reg |= ext_buf_pools->extBufPool[i].size; ++ /* functionality available only for some deriviatives (limited by config) */ ++ if (backup_pools) ++ for (j=0;jnumOfBackupPools;j++) ++ if (ext_buf_pools->extBufPool[i].id == backup_pools->poolIds[j]) ++ { ++ tmp_reg |= FM_SP_EXT_BUF_POOL_BACKUP; ++ break; ++ } ++ ++ WRITE_UINT32(sp_regs->fm_sp_ebmpi[i], tmp_reg); ++ } ++ ++ /* clear unused pools */ ++ for (i=ext_buf_pools->numOfPoolsUsed;ifm_sp_ebmpi[i], 0); ++ ++ /* fill pool depletion register*/ ++ tmp_reg = 0; ++ ++ if (buf_pool_depletion && buf_pool_depletion->poolsGrpModeEnable) ++ { ++ /* calculate vector for number of pools depletion */ ++ vector = 0; ++ for (i=0;ipoolsToConsider[i]) ++ for (j=0;jnumOfPoolsUsed;j++) ++ if (i == ext_buf_pools->extBufPool[j].id) ++ { ++ vector |= 0x80000000 >> j; ++ break; ++ } ++ ++ /* configure num of pools and vector for number of pools mode */ ++ tmp_reg |= (((uint32_t)buf_pool_depletion->numOfPools - 1) << FM_SP_POOL_DEP_NUM_OF_POOLS_SHIFT); ++ tmp_reg |= vector; ++ } ++ ++ if (buf_pool_depletion && buf_pool_depletion->singlePoolModeEnable) ++ { ++ /* calculate vector for number of pools depletion */ ++ vector = 0; ++ for (i=0;ipoolsToConsiderForSingleMode[i]) ++ for (j=0;jnumOfPoolsUsed;j++) ++ if (i == ext_buf_pools->extBufPool[j].id) ++ { ++ vector |= 0x00000080 >> j; ++ break; ++ } ++ ++ /* configure num of pools and vector for number of pools mode */ ++ tmp_reg |= vector; ++ } ++ ++ /* fill QbbPEV */ ++ if (buf_pool_depletion) ++ { ++ vector = 0; ++ for (i=0; ipfcPrioritiesEn[i] == TRUE) ++ vector|= 0x00008000 >> i; ++ tmp_reg |= vector; ++ } ++ WRITE_UINT32(sp_regs->fm_sp_mpd, tmp_reg); ++ ++ /* fill dma attributes register */ ++ tmp_reg = 0; ++ tmp_reg |= (uint32_t)fm_vsp_params->dma_swap_data << FM_SP_DMA_ATTR_SWP_SHIFT; ++ tmp_reg |= (uint32_t)fm_vsp_params->int_context_cache_attr << FM_SP_DMA_ATTR_IC_CACHE_SHIFT; ++ tmp_reg |= (uint32_t)fm_vsp_params->header_cache_attr << FM_SP_DMA_ATTR_HDR_CACHE_SHIFT; ++ tmp_reg |= (uint32_t)fm_vsp_params->scatter_gather_cache_attr << FM_SP_DMA_ATTR_SG_CACHE_SHIFT; ++ if (fm_vsp_params->dma_write_optimize) ++ tmp_reg |= FM_SP_DMA_ATTR_WRITE_OPTIMIZE; ++ WRITE_UINT32(sp_regs->fm_sp_da, tmp_reg); ++ ++ /* IC parameters - fill internal context parameters register */ ++ tmp_reg = 0; ++ tmp_reg |= (((uint32_t)int_context_data_copy->extBufOffset/OFFSET_UNITS) << FM_SP_IC_TO_EXT_SHIFT); ++ tmp_reg |= (((uint32_t)int_context_data_copy->intContextOffset/OFFSET_UNITS) << FM_SP_IC_FROM_INT_SHIFT); ++ tmp_reg |= (((uint32_t)int_context_data_copy->size/OFFSET_UNITS) << FM_SP_IC_SIZE_SHIFT); ++ WRITE_UINT32(sp_regs->fm_sp_icp, tmp_reg); ++ ++ /* buffer margins - fill external buffer margins register */ ++ tmp_reg = 0; ++ tmp_reg |= (((uint32_t)external_buffer_margins->startMargins) << FM_SP_EXT_BUF_MARG_START_SHIFT); ++ tmp_reg |= (((uint32_t)external_buffer_margins->endMargins) << FM_SP_EXT_BUF_MARG_END_SHIFT); ++ if (no_scather_gather) ++ tmp_reg |= FM_SP_SG_DISABLE; ++ WRITE_UINT32(sp_regs->fm_sp_ebm, tmp_reg); ++ ++ /* buffer margins - fill spliodn register */ ++ WRITE_UINT32(sp_regs->fm_sp_spliodn, liodn_offset); ++} ++ ++static t_Error CheckParamsGeneratedInternally(t_FmVspEntry *p_FmVspEntry) ++{ ++ t_Error err = E_OK; ++ ++ if ((err = FmSpCheckIntContextParams(&p_FmVspEntry->intContext))!= E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if ((err = FmSpCheckBufMargins(&p_FmVspEntry->bufMargins)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ return err; ++ ++} ++static t_Error CheckParams(t_FmVspEntry *p_FmVspEntry) ++{ ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->h_Fm, E_INVALID_HANDLE); ++ ++ if ((err = FmSpCheckBufPoolsParams(&p_FmVspEntry->p_FmVspEntryDriverParams->extBufPools, ++ p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools, ++ p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion)) != E_OK) ++ ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (p_FmVspEntry->p_FmVspEntryDriverParams->liodnOffset & ~FM_LIODN_OFFSET_MASK) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1)); ++ ++ err = FmVSPCheckRelativeProfile(p_FmVspEntry->h_Fm, ++ p_FmVspEntry->portType, ++ p_FmVspEntry->portId, ++ p_FmVspEntry->relativeProfileId); ++ ++ return err; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++void FmSpSetBufPoolsInAscOrderOfBufSizes(t_FmExtPools *p_FmExtPools, ++ uint8_t *orderedArray, ++ uint16_t *sizesArray) ++{ ++ uint16_t bufSize = 0; ++ int i=0, j=0, k=0; ++ ++ /* First we copy the external buffers pools information to an ordered local array */ ++ for (i=0;inumOfPoolsUsed;i++) ++ { ++ /* get pool size */ ++ bufSize = p_FmExtPools->extBufPool[i].size; ++ ++ /* keep sizes in an array according to poolId for direct access */ ++ sizesArray[p_FmExtPools->extBufPool[i].id] = bufSize; ++ ++ /* save poolId in an ordered array according to size */ ++ for (j=0;j<=i;j++) ++ { ++ /* this is the next free place in the array */ ++ if (j==i) ++ orderedArray[i] = p_FmExtPools->extBufPool[i].id; ++ else ++ { ++ /* find the right place for this poolId */ ++ if (bufSize < sizesArray[orderedArray[j]]) ++ { ++ /* move the poolIds one place ahead to make room for this poolId */ ++ for (k=i;k>j;k--) ++ orderedArray[k] = orderedArray[k-1]; ++ ++ /* now k==j, this is the place for the new size */ ++ orderedArray[k] = p_FmExtPools->extBufPool[i].id; ++ break; ++ } ++ } ++ } ++ } ++} ++ ++t_Error FmSpCheckBufPoolsParams(t_FmExtPools *p_FmExtPools, ++ t_FmBackupBmPools *p_FmBackupBmPools, ++ t_FmBufPoolDepletion *p_FmBufPoolDepletion) ++{ ++ ++ int i = 0, j = 0; ++ bool found; ++ uint8_t count = 0; ++ ++ if (p_FmExtPools) ++ { ++ if (p_FmExtPools->numOfPoolsUsed > FM_PORT_MAX_NUM_OF_EXT_POOLS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfPoolsUsed can't be larger than %d", FM_PORT_MAX_NUM_OF_EXT_POOLS)); ++ ++ for (i=0;inumOfPoolsUsed;i++) ++ { ++ if (p_FmExtPools->extBufPool[i].id >= BM_MAX_NUM_OF_POOLS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.extBufPool[%d].id can't be larger than %d", i, BM_MAX_NUM_OF_POOLS)); ++ if (!p_FmExtPools->extBufPool[i].size) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.extBufPool[%d].size is 0", i)); ++ } ++ } ++ if (!p_FmExtPools && (p_FmBackupBmPools || p_FmBufPoolDepletion)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("backupBmPools ot bufPoolDepletion can not be defined without external pools")); ++ ++ /* backup BM pools indication is valid only for some chip derivatives ++ (limited by the config routine) */ ++ if (p_FmBackupBmPools) ++ { ++ if (p_FmBackupBmPools->numOfBackupPools >= p_FmExtPools->numOfPoolsUsed) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_BackupBmPools must be smaller than extBufPools.numOfPoolsUsed")); ++ found = FALSE; ++ for (i = 0;inumOfBackupPools;i++) ++ { ++ ++ for (j=0;jnumOfPoolsUsed;j++) ++ { ++ if (p_FmBackupBmPools->poolIds[i] == p_FmExtPools->extBufPool[j].id) ++ { ++ found = TRUE; ++ break; ++ } ++ } ++ if (!found) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("All p_BackupBmPools.poolIds must be included in extBufPools.extBufPool[n].id")); ++ else ++ found = FALSE; ++ } ++ } ++ ++ /* up to extBufPools.numOfPoolsUsed pools may be defined */ ++ if (p_FmBufPoolDepletion && p_FmBufPoolDepletion->poolsGrpModeEnable) ++ { ++ if ((p_FmBufPoolDepletion->numOfPools > p_FmExtPools->numOfPoolsUsed)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPools can't be larger than %d and can't be larger than numOfPoolsUsed", FM_PORT_MAX_NUM_OF_EXT_POOLS)); ++ ++ if (!p_FmBufPoolDepletion->numOfPools) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPoolsToConsider can not be 0 when poolsGrpModeEnable=TRUE")); ++ ++ found = FALSE; ++ count = 0; ++ /* for each pool that is in poolsToConsider, check if it is defined ++ in extBufPool */ ++ for (i=0;ipoolsToConsider[i]) ++ { ++ for (j=0;jnumOfPoolsUsed;j++) ++ { ++ if (i == p_FmExtPools->extBufPool[j].id) ++ { ++ found = TRUE; ++ count++; ++ break; ++ } ++ } ++ if (!found) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Pools selected for depletion are not used.")); ++ else ++ found = FALSE; ++ } ++ } ++ /* check that the number of pools that we have checked is equal to the number announced by the user */ ++ if (count != p_FmBufPoolDepletion->numOfPools) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPools is larger than the number of pools defined.")); ++ } ++ ++ if (p_FmBufPoolDepletion && p_FmBufPoolDepletion->singlePoolModeEnable) ++ { ++ /* calculate vector for number of pools depletion */ ++ found = FALSE; ++ count = 0; ++ for (i=0;ipoolsToConsiderForSingleMode[i]) ++ { ++ for (j=0;jnumOfPoolsUsed;j++) ++ { ++ if (i == p_FmExtPools->extBufPool[j].id) ++ { ++ found = TRUE; ++ count++; ++ break; ++ } ++ } ++ if (!found) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Pools selected for depletion are not used.")); ++ else ++ found = FALSE; ++ } ++ } ++ if (!count) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("No pools defined for single buffer mode pool depletion.")); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FmSpCheckIntContextParams(t_FmSpIntContextDataCopy *p_FmSpIntContextDataCopy) ++{ ++ /* Check that divisible by 16 and not larger than 240 */ ++ if (p_FmSpIntContextDataCopy->intContextOffset >MAX_INT_OFFSET) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.intContextOffset can't be larger than %d", MAX_INT_OFFSET)); ++ if (p_FmSpIntContextDataCopy->intContextOffset % OFFSET_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.intContextOffset has to be divisible by %d", OFFSET_UNITS)); ++ ++ /* check that ic size+ic internal offset, does not exceed ic block size */ ++ if (p_FmSpIntContextDataCopy->size + p_FmSpIntContextDataCopy->intContextOffset > MAX_IC_SIZE) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size + intContext.intContextOffset has to be smaller than %d", MAX_IC_SIZE)); ++ /* Check that divisible by 16 and not larger than 256 */ ++ if (p_FmSpIntContextDataCopy->size % OFFSET_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size has to be divisible by %d", OFFSET_UNITS)); ++ ++ /* Check that divisible by 16 and not larger than 4K */ ++ if (p_FmSpIntContextDataCopy->extBufOffset > MAX_EXT_OFFSET) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.extBufOffset can't be larger than %d", MAX_EXT_OFFSET)); ++ if (p_FmSpIntContextDataCopy->extBufOffset % OFFSET_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.extBufOffset has to be divisible by %d", OFFSET_UNITS)); ++ ++ return E_OK; ++} ++ ++t_Error FmSpCheckBufMargins(t_FmSpBufMargins *p_FmSpBufMargins) ++{ ++ /* Check the margin definition */ ++ if (p_FmSpBufMargins->startMargins > MAX_EXT_BUFFER_OFFSET) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufMargins.startMargins can't be larger than %d", MAX_EXT_BUFFER_OFFSET)); ++ if (p_FmSpBufMargins->endMargins > MAX_EXT_BUFFER_OFFSET) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufMargins.endMargins can't be larger than %d", MAX_EXT_BUFFER_OFFSET)); ++ ++ return E_OK; ++} ++ ++t_Error FmSpBuildBufferStructure(t_FmSpIntContextDataCopy *p_FmSpIntContextDataCopy, ++ t_FmBufferPrefixContent *p_BufferPrefixContent, ++ t_FmSpBufMargins *p_FmSpBufMargins, ++ t_FmSpBufferOffsets *p_FmSpBufferOffsets, ++ uint8_t *internalBufferOffset) ++{ ++ uint32_t tmp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmSpIntContextDataCopy, E_INVALID_VALUE); ++ ASSERT_COND(p_FmSpIntContextDataCopy); ++ ASSERT_COND(p_BufferPrefixContent); ++ ASSERT_COND(p_FmSpBufMargins); ++ ASSERT_COND(p_FmSpBufferOffsets); ++ ++ /* Align start of internal context data to 16 byte */ ++ p_FmSpIntContextDataCopy->extBufOffset = ++ (uint16_t)((p_BufferPrefixContent->privDataSize & (OFFSET_UNITS-1)) ? ++ ((p_BufferPrefixContent->privDataSize + OFFSET_UNITS) & ~(uint16_t)(OFFSET_UNITS-1)) : ++ p_BufferPrefixContent->privDataSize); ++ ++ /* Translate margin and intContext params to FM parameters */ ++ /* Initialize with illegal value. Later we'll set legal values. */ ++ p_FmSpBufferOffsets->prsResultOffset = (uint32_t)ILLEGAL_BASE; ++ p_FmSpBufferOffsets->timeStampOffset = (uint32_t)ILLEGAL_BASE; ++ p_FmSpBufferOffsets->hashResultOffset= (uint32_t)ILLEGAL_BASE; ++ p_FmSpBufferOffsets->pcdInfoOffset = (uint32_t)ILLEGAL_BASE; ++ ++ /* Internally the driver supports 4 options ++ 1. prsResult/timestamp/hashResult selection (in fact 8 options, but for simplicity we'll ++ relate to it as 1). ++ 2. All IC context (from AD) not including debug.*/ ++ ++ /* This 'if' covers option 2. We copy from beginning of context. */ ++ if (p_BufferPrefixContent->passAllOtherPCDInfo) ++ { ++ p_FmSpIntContextDataCopy->size = 128; /* must be aligned to 16 */ ++ /* Start copying data after 16 bytes (FD) from the beginning of the internal context */ ++ p_FmSpIntContextDataCopy->intContextOffset = 16; ++ ++ if (p_BufferPrefixContent->passAllOtherPCDInfo) ++ p_FmSpBufferOffsets->pcdInfoOffset = p_FmSpIntContextDataCopy->extBufOffset; ++ if (p_BufferPrefixContent->passPrsResult) ++ p_FmSpBufferOffsets->prsResultOffset = ++ (uint32_t)(p_FmSpIntContextDataCopy->extBufOffset + 16); ++ if (p_BufferPrefixContent->passTimeStamp) ++ p_FmSpBufferOffsets->timeStampOffset = ++ (uint32_t)(p_FmSpIntContextDataCopy->extBufOffset + 48); ++ if (p_BufferPrefixContent->passHashResult) ++ p_FmSpBufferOffsets->hashResultOffset = ++ (uint32_t)(p_FmSpIntContextDataCopy->extBufOffset + 56); ++ } ++ else ++ { ++ /* This case covers the options under 1 */ ++ /* Copy size must be in 16-byte granularity. */ ++ p_FmSpIntContextDataCopy->size = ++ (uint16_t)((p_BufferPrefixContent->passPrsResult ? 32 : 0) + ++ ((p_BufferPrefixContent->passTimeStamp || ++ p_BufferPrefixContent->passHashResult) ? 16 : 0)); ++ ++ /* Align start of internal context data to 16 byte */ ++ p_FmSpIntContextDataCopy->intContextOffset = ++ (uint8_t)(p_BufferPrefixContent->passPrsResult ? 32 : ++ ((p_BufferPrefixContent->passTimeStamp || ++ p_BufferPrefixContent->passHashResult) ? 64 : 0)); ++ ++ if (p_BufferPrefixContent->passPrsResult) ++ p_FmSpBufferOffsets->prsResultOffset = p_FmSpIntContextDataCopy->extBufOffset; ++ if (p_BufferPrefixContent->passTimeStamp) ++ p_FmSpBufferOffsets->timeStampOffset = p_BufferPrefixContent->passPrsResult ? ++ (p_FmSpIntContextDataCopy->extBufOffset + sizeof(t_FmPrsResult)) : ++ p_FmSpIntContextDataCopy->extBufOffset; ++ if (p_BufferPrefixContent->passHashResult) ++ /* If PR is not requested, whether TS is requested or not, IC will be copied from TS */ ++ p_FmSpBufferOffsets->hashResultOffset = p_BufferPrefixContent->passPrsResult ? ++ (p_FmSpIntContextDataCopy->extBufOffset + sizeof(t_FmPrsResult) + 8) : ++ p_FmSpIntContextDataCopy->extBufOffset + 8; ++ } ++ ++ if (p_FmSpIntContextDataCopy->size) ++ p_FmSpBufMargins->startMargins = ++ (uint16_t)(p_FmSpIntContextDataCopy->extBufOffset + ++ p_FmSpIntContextDataCopy->size); ++ else ++ /* No Internal Context passing, STartMargin is immediately after privateInfo */ ++ p_FmSpBufMargins->startMargins = p_BufferPrefixContent->privDataSize; ++ ++ /* save extra space for manip in both external and internal buffers */ ++ if (p_BufferPrefixContent->manipExtraSpace) ++ { ++ uint8_t extraSpace; ++#ifdef FM_CAPWAP_SUPPORT ++ if ((p_BufferPrefixContent->manipExtraSpace + CAPWAP_FRAG_EXTRA_SPACE) >= 256) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("p_BufferPrefixContent->manipExtraSpace should be less than %d", ++ 256-CAPWAP_FRAG_EXTRA_SPACE)); ++ extraSpace = (uint8_t)(p_BufferPrefixContent->manipExtraSpace + CAPWAP_FRAG_EXTRA_SPACE); ++#else ++ extraSpace = p_BufferPrefixContent->manipExtraSpace; ++#endif /* FM_CAPWAP_SUPPORT */ ++ p_FmSpBufferOffsets->manipOffset = p_FmSpBufMargins->startMargins; ++ p_FmSpBufMargins->startMargins += extraSpace; ++ *internalBufferOffset = extraSpace; ++ } ++ ++ /* align data start */ ++ tmp = (uint32_t)(p_FmSpBufMargins->startMargins % p_BufferPrefixContent->dataAlign); ++ if (tmp) ++ p_FmSpBufMargins->startMargins += (p_BufferPrefixContent->dataAlign-tmp); ++ p_FmSpBufferOffsets->dataOffset = p_FmSpBufMargins->startMargins; ++ ++ return E_OK; ++} ++/*********************** End of inter-module routines ************************/ ++ ++ ++#if (DPAA_VERSION >= 11) ++/*****************************************************************************/ ++/* API routines */ ++/*****************************************************************************/ ++t_Handle FM_VSP_Config(t_FmVspParams *p_FmVspParams) ++{ ++ t_FmVspEntry *p_FmVspEntry = NULL; ++ ++ p_FmVspEntry = (t_FmVspEntry *)XX_Malloc(sizeof(t_FmVspEntry)); ++ if (!p_FmVspEntry) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_StorageProfile allocation failed")); ++ return NULL; ++ } ++ memset(p_FmVspEntry, 0, sizeof(t_FmVspEntry)); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams = (t_FmVspEntryDriverParams *)XX_Malloc(sizeof(t_FmVspEntryDriverParams)); ++ if (!p_FmVspEntry->p_FmVspEntryDriverParams) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_StorageProfile allocation failed")); ++ XX_Free(p_FmVspEntry); ++ return NULL; ++ } ++ memset(p_FmVspEntry->p_FmVspEntryDriverParams, 0, sizeof(t_FmVspEntryDriverParams)); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.privDataSize = DEFAULT_FM_SP_bufferPrefixContent_privDataSize; ++ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.passPrsResult= DEFAULT_FM_SP_bufferPrefixContent_passPrsResult; ++ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.passTimeStamp= DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp; ++ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.passAllOtherPCDInfo ++ = DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp; ++ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.dataAlign = DEFAULT_FM_SP_bufferPrefixContent_dataAlign; ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaSwapData = DEFAULT_FM_SP_dmaSwapData; ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaIntContextCacheAttr = DEFAULT_FM_SP_dmaIntContextCacheAttr; ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaHeaderCacheAttr = DEFAULT_FM_SP_dmaHeaderCacheAttr; ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaScatterGatherCacheAttr = DEFAULT_FM_SP_dmaScatterGatherCacheAttr; ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaWriteOptimize = DEFAULT_FM_SP_dmaWriteOptimize; ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->noScatherGather = DEFAULT_FM_SP_noScatherGather; ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->liodnOffset = p_FmVspParams->liodnOffset; ++ ++ memcpy(&p_FmVspEntry->p_FmVspEntryDriverParams->extBufPools, &p_FmVspParams->extBufPools, sizeof(t_FmExtPools)); ++ ++ p_FmVspEntry->h_Fm = p_FmVspParams->h_Fm; ++ p_FmVspEntry->portType = p_FmVspParams->portParams.portType; ++ p_FmVspEntry->portId = p_FmVspParams->portParams.portId ; ++ ++ p_FmVspEntry->relativeProfileId = p_FmVspParams->relativeProfileId; ++ ++ return p_FmVspEntry; ++} ++ ++t_Error FM_VSP_Init(t_Handle h_FmVsp) ++{ ++ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry *)h_FmVsp; ++ fm_storage_profile_params fm_vsp_params; ++ uint8_t orderedArray[FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ uint16_t sizesArray[BM_MAX_NUM_OF_POOLS]; ++ t_Error err; ++ uint16_t absoluteProfileId = 0; ++ int i = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams,E_INVALID_HANDLE); ++ ++ CHECK_INIT_PARAMETERS(p_FmVspEntry, CheckParams); ++ ++ memset(&orderedArray, 0, sizeof(uint8_t) * FM_PORT_MAX_NUM_OF_EXT_POOLS); ++ memset(&sizesArray, 0, sizeof(uint16_t) * BM_MAX_NUM_OF_POOLS); ++ ++ err = FmSpBuildBufferStructure(&p_FmVspEntry->intContext, ++ &p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent, ++ &p_FmVspEntry->bufMargins, ++ &p_FmVspEntry->bufferOffsets, ++ &p_FmVspEntry->internalBufferOffset); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ ++ err = CheckParamsGeneratedInternally(p_FmVspEntry); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ ++ p_FmVspEntry->p_FmSpRegsBase = ++ (fm_pcd_storage_profile_regs *)FmGetVSPBaseAddr(p_FmVspEntry->h_Fm); ++ if (!p_FmVspEntry->p_FmSpRegsBase) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("impossible to initialize SpRegsBase")); ++ ++ /* order external buffer pools in ascending order of buffer pools sizes */ ++ FmSpSetBufPoolsInAscOrderOfBufSizes(&(p_FmVspEntry->p_FmVspEntryDriverParams)->extBufPools, ++ orderedArray, ++ sizesArray); ++ ++ p_FmVspEntry->extBufPools.numOfPoolsUsed = ++ p_FmVspEntry->p_FmVspEntryDriverParams->extBufPools.numOfPoolsUsed; ++ for (i = 0; i < p_FmVspEntry->extBufPools.numOfPoolsUsed; i++) ++ { ++ p_FmVspEntry->extBufPools.extBufPool[i].id = orderedArray[i]; ++ p_FmVspEntry->extBufPools.extBufPool[i].size = sizesArray[orderedArray[i]]; ++ } ++ ++ /* on user responsibility to fill it according requirement */ ++ memset(&fm_vsp_params, 0, sizeof(fm_storage_profile_params)); ++ fm_vsp_params.dma_swap_data = p_FmVspEntry->p_FmVspEntryDriverParams->dmaSwapData; ++ fm_vsp_params.int_context_cache_attr = p_FmVspEntry->p_FmVspEntryDriverParams->dmaIntContextCacheAttr; ++ fm_vsp_params.header_cache_attr = p_FmVspEntry->p_FmVspEntryDriverParams->dmaHeaderCacheAttr; ++ fm_vsp_params.scatter_gather_cache_attr = p_FmVspEntry->p_FmVspEntryDriverParams->dmaScatterGatherCacheAttr; ++ fm_vsp_params.dma_write_optimize = p_FmVspEntry->p_FmVspEntryDriverParams->dmaWriteOptimize; ++ fm_vsp_params.liodn_offset = p_FmVspEntry->p_FmVspEntryDriverParams->liodnOffset; ++ fm_vsp_params.no_scather_gather = p_FmVspEntry->p_FmVspEntryDriverParams->noScatherGather; ++ ++ fm_vsp_params.buf_pool_depletion = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion; ++ fm_vsp_params.backup_pools = p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools; ++ fm_vsp_params.fm_ext_pools = &p_FmVspEntry->extBufPools; ++ ++ fm_vsp_params.buf_margins = &p_FmVspEntry->bufMargins; ++ fm_vsp_params.int_context = &p_FmVspEntry->intContext; ++ ++ /*no check on err - it was checked earlier*/ ++ FmVSPGetAbsoluteProfileId(p_FmVspEntry->h_Fm, ++ p_FmVspEntry->portType, ++ p_FmVspEntry->portId, ++ p_FmVspEntry->relativeProfileId, ++ &absoluteProfileId); ++ ++ /*set all registers related to VSP*/ ++ fm_vsp_fill_entry(p_FmVspEntry->p_FmSpRegsBase, absoluteProfileId, &fm_vsp_params); ++ ++ p_FmVspEntry->absoluteSpId = absoluteProfileId; ++ ++ if (p_FmVspEntry->p_FmVspEntryDriverParams) ++ XX_Free(p_FmVspEntry->p_FmVspEntryDriverParams); ++ p_FmVspEntry->p_FmVspEntryDriverParams = NULL; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_Free(t_Handle h_FmVsp) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry *)h_FmVsp; ++ SANITY_CHECK_RETURN_ERROR(h_FmVsp, E_INVALID_HANDLE); ++ XX_Free(p_FmVspEntry); ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigBufferPrefixContent(t_Handle h_FmVsp, t_FmBufferPrefixContent *p_FmBufferPrefixContent) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ memcpy(&p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent, p_FmBufferPrefixContent, sizeof(t_FmBufferPrefixContent)); ++ /* if dataAlign was not initialized by user, we return to driver's default */ ++ if (!p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.dataAlign) ++ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.dataAlign = DEFAULT_FM_SP_bufferPrefixContent_dataAlign; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigDmaSwapData(t_Handle h_FmVsp, e_FmDmaSwapOption swapData) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaSwapData = swapData; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigDmaIcCacheAttr(t_Handle h_FmVsp, e_FmDmaCacheOption intContextCacheAttr) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaIntContextCacheAttr = intContextCacheAttr; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigDmaHdrAttr(t_Handle h_FmVsp, e_FmDmaCacheOption headerCacheAttr) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaHeaderCacheAttr = headerCacheAttr; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigDmaScatterGatherAttr(t_Handle h_FmVsp, e_FmDmaCacheOption scatterGatherCacheAttr) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaScatterGatherCacheAttr = scatterGatherCacheAttr; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigDmaWriteOptimize(t_Handle h_FmVsp, bool optimize) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaWriteOptimize = optimize; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigNoScatherGather(t_Handle h_FmVsp, bool noScatherGather) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->noScatherGather = noScatherGather; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigPoolDepletion(t_Handle h_FmVsp, t_FmBufPoolDepletion *p_BufPoolDepletion) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmVsp, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_BufPoolDepletion, E_INVALID_HANDLE); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion = (t_FmBufPoolDepletion *)XX_Malloc(sizeof(t_FmBufPoolDepletion)); ++ if (!p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BufPoolDepletion allocation failed")); ++ memcpy(p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion, p_BufPoolDepletion, sizeof(t_FmBufPoolDepletion)); ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigBackupPools(t_Handle h_FmVsp, t_FmBackupBmPools *p_BackupBmPools) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmVsp, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_BackupBmPools, E_INVALID_HANDLE); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools = (t_FmBackupBmPools *)XX_Malloc(sizeof(t_FmBackupBmPools)); ++ if (!p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BackupBmPools allocation failed")); ++ memcpy(p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools, p_BackupBmPools, sizeof(t_FmBackupBmPools)); ++ ++ return E_OK; ++} ++ ++uint32_t FM_VSP_GetBufferDataOffset(t_Handle h_FmVsp) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, 0); ++ ++ return p_FmVspEntry->bufferOffsets.dataOffset; ++} ++ ++uint8_t * FM_VSP_GetBufferICInfo(t_Handle h_FmVsp, char *p_Data) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL); ++ ++ if (p_FmVspEntry->bufferOffsets.pcdInfoOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (uint8_t *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.pcdInfoOffset); ++} ++ ++t_FmPrsResult * FM_VSP_GetBufferPrsResult(t_Handle h_FmVsp, char *p_Data) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL); ++ ++ if (p_FmVspEntry->bufferOffsets.prsResultOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (t_FmPrsResult *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.prsResultOffset); ++} ++ ++uint64_t * FM_VSP_GetBufferTimeStamp(t_Handle h_FmVsp, char *p_Data) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL); ++ ++ if (p_FmVspEntry->bufferOffsets.timeStampOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (uint64_t *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.timeStampOffset); ++} ++ ++uint8_t * FM_VSP_GetBufferHashResult(t_Handle h_FmVsp, char *p_Data) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL); ++ ++ if (p_FmVspEntry->bufferOffsets.hashResultOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (uint8_t *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.hashResultOffset); ++} ++ ++#endif /* (DPAA_VERSION >= 11) */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/SP/fm_sp.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/SP/fm_sp.h +new file mode 100644 +index 0000000..30b41b6 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/SP/fm_sp.h +@@ -0,0 +1,131 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_sp.h ++ ++ @Description FM SP ... ++*//***************************************************************************/ ++#ifndef __FM_SP_H ++#define __FM_SP_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++ ++#include "fm_sp_common.h" ++#include "fm_common.h" ++ ++ ++#define __ERR_MODULE__ MODULE_FM_SP ++ ++ ++ ++/***********************************************************************/ ++/* Memory map */ ++/***********************************************************************/ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++typedef _Packed struct { ++ volatile uint32_t fm_sp_ebmpi[FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ /*offset 0 - 0xc*/ ++ /**< Buffer Manager pool Information-*/ ++ ++ volatile uint32_t res[8-FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ /*offset 0x10 - 0xc*/ ++ volatile uint32_t fm_sp_acnt; /*offset 0x20*/ ++ volatile uint32_t fm_sp_ebm; /*offset 0x24*/ ++ volatile uint32_t fm_sp_da; /*offset 0x28*/ ++ volatile uint32_t fm_sp_icp; /*offset 0x2c*/ ++ volatile uint32_t fm_sp_mpd; /*offset 0x30*/ ++ volatile uint32_t res1[2]; /*offset 0x34 - 0x38*/ ++ volatile uint32_t fm_sp_spliodn; /*offset 0x3c*/ ++} _PackedType fm_pcd_storage_profile_regs; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++typedef struct fm_storage_profile_params { ++ t_FmExtPools *fm_ext_pools; ++ t_FmBackupBmPools *backup_pools; ++ t_FmSpIntContextDataCopy *int_context; ++ t_FmSpBufMargins *buf_margins; ++ ++ e_FmDmaSwapOption dma_swap_data; ++ e_FmDmaCacheOption int_context_cache_attr; ++ e_FmDmaCacheOption header_cache_attr; ++ e_FmDmaCacheOption scatter_gather_cache_attr; ++ bool dma_write_optimize; ++ uint16_t liodn_offset; ++ bool no_scather_gather; ++ t_FmBufPoolDepletion *buf_pool_depletion; ++} fm_storage_profile_params; ++ ++typedef struct { ++ t_FmBufferPrefixContent bufferPrefixContent; ++ e_FmDmaSwapOption dmaSwapData; ++ e_FmDmaCacheOption dmaIntContextCacheAttr; ++ e_FmDmaCacheOption dmaHeaderCacheAttr; ++ e_FmDmaCacheOption dmaScatterGatherCacheAttr; ++ bool dmaWriteOptimize; ++ uint16_t liodnOffset; ++ bool noScatherGather; ++ t_FmBufPoolDepletion *p_BufPoolDepletion; ++ t_FmBackupBmPools *p_BackupBmPools; ++ t_FmExtPools extBufPools; ++} t_FmVspEntryDriverParams; ++ ++typedef struct { ++ bool valid; ++ volatile bool lock; ++ uint8_t pointedOwners; ++ uint16_t absoluteSpId; ++ uint8_t internalBufferOffset; ++ t_FmSpBufMargins bufMargins; ++ t_FmSpIntContextDataCopy intContext; ++ t_FmSpBufferOffsets bufferOffsets; ++ t_Handle h_Fm; ++ e_FmPortType portType; /**< Port type */ ++ uint8_t portId; /**< Port Id - relative to type */ ++ uint8_t relativeProfileId; ++ fm_pcd_storage_profile_regs *p_FmSpRegsBase; ++ t_FmExtPools extBufPools; ++ t_FmVspEntryDriverParams *p_FmVspEntryDriverParams; ++} t_FmVspEntry; ++ ++ ++#endif /* __FM_SP_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/fm.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/fm.c +new file mode 100644 +index 0000000..10601ec +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/fm.c +@@ -0,0 +1,6162 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm.c ++ ++ @Description FM driver routines implementation. ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "xx_ext.h" ++#include "string_ext.h" ++#include "sprint_ext.h" ++#include "debug_ext.h" ++#include "fm_muram_ext.h" ++ ++#include "fm_common.h" ++#include "fm_ipc.h" ++#include "fm.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++static volatile bool blockingFlag = FALSE; ++static void IpcMsgCompletionCB(t_Handle h_Fm, ++ uint8_t *p_Msg, ++ uint8_t *p_Reply, ++ uint32_t replyLength, ++ t_Error status) ++{ ++ UNUSED(h_Fm);UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status); ++ blockingFlag = FALSE; ++} ++ ++static void FreeInitResources(t_Fm *p_Fm) ++{ ++ if (p_Fm->camBaseAddr) ++ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->camBaseAddr)); ++ if (p_Fm->fifoBaseAddr) ++ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->fifoBaseAddr)); ++ if (p_Fm->resAddr) ++ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->resAddr)); ++} ++ ++static bool IsFmanCtrlCodeLoaded(t_Fm *p_Fm) ++{ ++ t_FMIramRegs *p_Iram; ++ ++ ASSERT_COND(p_Fm); ++ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); ++ ++ return (bool)!!(GET_UINT32(p_Iram->iready) & IRAM_READY); ++} ++ ++static t_Error CheckFmParameters(t_Fm *p_Fm) ++{ ++ if (IsFmanCtrlCodeLoaded(p_Fm) && !p_Fm->p_FmDriverParam->resetOnInit) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Old FMan CTRL code is loaded; FM must be reset!")); ++#if (DPAA_VERSION < 11) ++ if (!p_Fm->p_FmDriverParam->dmaAxiDbgNumOfBeats || (p_Fm->p_FmDriverParam->dmaAxiDbgNumOfBeats > DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("axiDbgNumOfBeats has to be in the range 1 - %d", DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS)); ++#endif /* (DPAA_VERSION < 11) */ ++ if (p_Fm->p_FmDriverParam->dmaCamNumOfEntries % DMA_CAM_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaCamNumOfEntries has to be divisble by %d", DMA_CAM_UNITS)); ++ if (!p_Fm->p_FmDriverParam->dmaCamNumOfEntries || (p_Fm->p_FmDriverParam->dmaCamNumOfEntries > DMA_MODE_MAX_CAM_NUM_OF_ENTRIES)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaCamNumOfEntries has to be in the range 1 - %d", DMA_MODE_MAX_CAM_NUM_OF_ENTRIES)); ++ if (p_Fm->p_FmDriverParam->dmaCommQThresholds.assertEmergency > DMA_THRESH_MAX_COMMQ) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaCommQThresholds.assertEmergency can not be larger than %d", DMA_THRESH_MAX_COMMQ)); ++ if (p_Fm->p_FmDriverParam->dmaCommQThresholds.clearEmergency > DMA_THRESH_MAX_COMMQ) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaCommQThresholds.clearEmergency can not be larger than %d", DMA_THRESH_MAX_COMMQ)); ++ if (p_Fm->p_FmDriverParam->dmaCommQThresholds.clearEmergency >= p_Fm->p_FmDriverParam->dmaCommQThresholds.assertEmergency) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaCommQThresholds.clearEmergency must be smaller than dmaCommQThresholds.assertEmergency")); ++#if (DPAA_VERSION < 11) ++ if (p_Fm->p_FmDriverParam->dmaReadBufThresholds.assertEmergency > DMA_THRESH_MAX_BUF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaReadBufThresholds.assertEmergency can not be larger than %d", DMA_THRESH_MAX_BUF)); ++ if (p_Fm->p_FmDriverParam->dmaReadBufThresholds.clearEmergency > DMA_THRESH_MAX_BUF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaReadBufThresholds.clearEmergency can not be larger than %d", DMA_THRESH_MAX_BUF)); ++ if (p_Fm->p_FmDriverParam->dmaReadBufThresholds.clearEmergency >= p_Fm->p_FmDriverParam->dmaReadBufThresholds.assertEmergency) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaReadBufThresholds.clearEmergency must be smaller than dmaReadBufThresholds.assertEmergency")); ++ if (p_Fm->p_FmDriverParam->dmaWriteBufThresholds.assertEmergency > DMA_THRESH_MAX_BUF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaWriteBufThresholds.assertEmergency can not be larger than %d", DMA_THRESH_MAX_BUF)); ++ if (p_Fm->p_FmDriverParam->dmaWriteBufThresholds.clearEmergency > DMA_THRESH_MAX_BUF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaWriteBufThresholds.clearEmergency can not be larger than %d", DMA_THRESH_MAX_BUF)); ++ if (p_Fm->p_FmDriverParam->dmaWriteBufThresholds.clearEmergency >= p_Fm->p_FmDriverParam->dmaWriteBufThresholds.assertEmergency) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaWriteBufThresholds.clearEmergency must be smaller than dmaWriteBufThresholds.assertEmergency")); ++#endif /* (DPAA_VERSION < 11) */ ++#if (DPAA_VERSION >= 11) ++ if ((p_Fm->p_FmDriverParam->dmaDbgCntMode == e_FM_DMA_DBG_CNT_INT_READ_EM)|| ++ (p_Fm->p_FmDriverParam->dmaDbgCntMode == e_FM_DMA_DBG_CNT_INT_WRITE_EM) || ++ (p_Fm->p_FmDriverParam->dmaDbgCntMode == e_FM_DMA_DBG_CNT_RAW_WAR_PROT)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaDbgCntMode value not supported by this integration.")); ++ if ((p_Fm->p_FmDriverParam->dmaEmergency.emergencyBusSelect == FM_DMA_MURAM_READ_EMERGENCY)|| ++ (p_Fm->p_FmDriverParam->dmaEmergency.emergencyBusSelect == FM_DMA_MURAM_WRITE_EMERGENCY)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("emergencyBusSelect value not supported by this integration.")); ++ if (p_Fm->p_FmDriverParam->dmaStopOnBusError) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaStopOnBusError not supported by this integration.")); ++#ifdef FM_AID_MODE_NO_TNUM_SW005 ++ if (p_Fm->p_FmDriverParam->dmaAidMode != e_FM_DMA_AID_OUT_PORT_ID) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaAidMode not supported by this integration.")); ++#endif /* FM_AID_MODE_NO_TNUM_SW005 */ ++ if (p_Fm->p_FmDriverParam->dmaAxiDbgNumOfBeats) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaAxiDbgNumOfBeats not supported by this integration.")); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (!p_Fm->p_FmStateStruct->fmClkFreq) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fmClkFreq must be set.")); ++ if (USEC_TO_CLK(p_Fm->p_FmDriverParam->dmaWatchdog, p_Fm->p_FmStateStruct->fmClkFreq) > DMA_MAX_WATCHDOG) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("dmaWatchdog depends on FM clock. dmaWatchdog(in microseconds) * clk (in Mhz), may not exceed 0x08x", DMA_MAX_WATCHDOG)); ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_Fm->partVSPBase + p_Fm->partNumOfVSPs) > FM_VSP_MAX_NUM_OF_ENTRIES) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partVSPBase+partNumOfVSPs out of range!!!")); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (p_Fm->p_FmStateStruct->totalFifoSize % BMI_FIFO_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalFifoSize number has to be divisible by %d", BMI_FIFO_UNITS)); ++ if (!p_Fm->p_FmStateStruct->totalFifoSize || ++ (p_Fm->p_FmStateStruct->totalFifoSize > BMI_MAX_FIFO_SIZE)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalFifoSize number has to be in the range 256 - %d", BMI_MAX_FIFO_SIZE)); ++ if (!p_Fm->p_FmStateStruct->totalNumOfTasks || ++ (p_Fm->p_FmStateStruct->totalNumOfTasks > BMI_MAX_NUM_OF_TASKS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfTasks number has to be in the range 1 - %d", BMI_MAX_NUM_OF_TASKS)); ++ ++#ifdef FM_HAS_TOTAL_DMAS ++ if (!p_Fm->p_FmStateStruct->maxNumOfOpenDmas || ++ (p_Fm->p_FmStateStruct->maxNumOfOpenDmas > BMI_MAX_NUM_OF_DMAS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumOfOpenDmas number has to be in the range 1 - %d", BMI_MAX_NUM_OF_DMAS)); ++#endif /* FM_HAS_TOTAL_DMAS */ ++ ++ if (p_Fm->p_FmDriverParam->thresholds.dispLimit > FPM_MAX_DISP_LIMIT) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("thresholds.dispLimit can't be greater than %d", FPM_MAX_DISP_LIMIT)); ++ ++ if (!p_Fm->f_Exception) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided")); ++ if (!p_Fm->f_BusError) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided")); ++ ++#ifdef FM_NO_WATCHDOG ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev == 2) && ++ (p_Fm->p_FmDriverParam->dmaWatchdog)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("watchdog!")); ++#endif /* FM_NO_WATCHDOG */ ++ ++#ifdef FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev < 6) && ++ (p_Fm->p_FmDriverParam->haltOnUnrecoverableEccError)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("HaltOnEccError!")); ++#endif /* FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 */ ++ ++#ifdef FM_NO_TNUM_AGING ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) && ++ (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)) ++ if (p_Fm->p_FmDriverParam->tnumAgingPeriod) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Tnum aging!")); ++#endif /* FM_NO_TNUM_AGING */ ++ ++ /* check that user did not set revision-dependent exceptions */ ++#ifdef FM_NO_DISPATCH_RAM_ECC ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) && ++ (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)) ++ if (p_Fm->p_FmDriverParam->userSetExceptions & FM_EX_BMI_DISPATCH_RAM_ECC) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_BMI_DISPATCH_RAM_ECC!")); ++#endif /* FM_NO_DISPATCH_RAM_ECC */ ++ ++#ifdef FM_QMI_NO_ECC_EXCEPTIONS ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev == 4) ++ if (p_Fm->p_FmDriverParam->userSetExceptions & (FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_QMI_SINGLE_ECC/e_FM_EX_QMI_DOUBLE_ECC!")); ++#endif /* FM_QMI_NO_ECC_EXCEPTIONS */ ++ ++#ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ if (p_Fm->p_FmDriverParam->userSetExceptions & FM_EX_QMI_SINGLE_ECC) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_QMI_SINGLE_ECC!")); ++#endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */ ++ ++ return E_OK; ++} ++ ++ ++static void SendIpcIsr(t_Fm *p_Fm, uint32_t macEvent, uint32_t pendingReg) ++{ ++ ASSERT_COND(p_Fm->guestId == NCSW_MASTER_ID); ++ ++ if (p_Fm->intrMng[macEvent].guestId == NCSW_MASTER_ID) ++ p_Fm->intrMng[macEvent].f_Isr(p_Fm->intrMng[macEvent].h_SrcHandle); ++ ++ /* If the MAC is running on guest-partition and we have IPC session with it, ++ we inform him about the event through IPC; otherwise, we ignore the event. */ ++ else if (p_Fm->h_IpcSessions[p_Fm->intrMng[macEvent].guestId]) ++ { ++ t_Error err; ++ t_FmIpcIsr fmIpcIsr; ++ t_FmIpcMsg msg; ++ ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_GUEST_ISR; ++ fmIpcIsr.pendingReg = pendingReg; ++ fmIpcIsr.boolErr = FALSE; ++ memcpy(msg.msgBody, &fmIpcIsr, sizeof(fmIpcIsr)); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[p_Fm->intrMng[macEvent].guestId], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(fmIpcIsr), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ } ++ else ++ DBG(TRACE, ("FM Guest mode, without IPC - can't call ISR!")); ++} ++ ++static void BmiErrEvent(t_Fm *p_Fm) ++{ ++ uint32_t event, mask, force; ++ ++ event = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ievr); ++ mask = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier); ++ event &= mask; ++ ++ /* clear the forced events */ ++ force = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ifr); ++ if (force & event) ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ifr, force & ~event); ++ ++ /* clear the acknowledged events */ ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ievr, event); ++ ++ if (event & BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_STORAGE_PROFILE_ECC); ++ if (event & BMI_ERR_INTR_EN_LIST_RAM_ECC) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_LIST_RAM_ECC); ++ if (event & BMI_ERR_INTR_EN_STATISTICS_RAM_ECC) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_STATISTICS_RAM_ECC); ++ if (event & BMI_ERR_INTR_EN_DISPATCH_RAM_ECC) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_DISPATCH_RAM_ECC); ++} ++ ++static void QmiErrEvent(t_Fm *p_Fm) ++{ ++ uint32_t event, mask, force; ++ ++ event = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_eie); ++ mask = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_eien); ++ ++ event &= mask; ++ ++ /* clear the forced events */ ++ force = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_eif); ++ if (force & event) ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eif, force & ~event); ++ ++ /* clear the acknowledged events */ ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eie, event); ++ ++ if (event & QMI_ERR_INTR_EN_DOUBLE_ECC) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_DOUBLE_ECC); ++ if (event & QMI_ERR_INTR_EN_DEQ_FROM_DEF) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID); ++} ++ ++static void DmaErrEvent(t_Fm *p_Fm) ++{ ++ uint64_t addr=0; ++ uint32_t status, mask, tmpReg=0; ++ uint8_t tnum; ++ uint8_t hardwarePortId; ++ uint8_t relativePortId; ++ uint16_t liodn; ++ ++ status = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmsr); ++ mask = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr); ++ ++ /* get bus error regs before clearing BER */ ++ if ((status & DMA_STATUS_BUS_ERR) && (mask & DMA_MODE_BER)) ++ { ++ addr = (uint64_t)GET_UINT32(p_Fm->p_FmDmaRegs->fmdmtal); ++ addr |= ((uint64_t)(GET_UINT32(p_Fm->p_FmDmaRegs->fmdmtah)) << 32); ++ ++ /* get information about the owner of that bus error */ ++ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmtcid); ++ } ++ ++ /* clear set events */ ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmsr, status); ++ ++ if ((status & DMA_STATUS_BUS_ERR) && (mask & DMA_MODE_BER)) ++ { ++ hardwarePortId = (uint8_t)(((tmpReg & DMA_TRANSFER_PORTID_MASK) >> DMA_TRANSFER_PORTID_SHIFT)); ++ HW_PORT_ID_TO_SW_PORT_ID(relativePortId, hardwarePortId); ++ tnum = (uint8_t)((tmpReg & DMA_TRANSFER_TNUM_MASK) >> DMA_TRANSFER_TNUM_SHIFT); ++ liodn = (uint16_t)(tmpReg & DMA_TRANSFER_LIODN_MASK); ++ ASSERT_COND(p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] != e_FM_PORT_TYPE_DUMMY); ++ p_Fm->f_BusError(p_Fm->h_App, ++ p_Fm->p_FmStateStruct->portsTypes[hardwarePortId], ++ relativePortId, ++ addr, ++ tnum, ++ liodn); ++ } ++ if (mask & DMA_MODE_ECC) ++ { ++ if (status & DMA_STATUS_FM_SPDAT_ECC) ++ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_SINGLE_PORT_ECC); ++ if (status & DMA_STATUS_READ_ECC) ++ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_READ_ECC); ++ if (status & DMA_STATUS_SYSTEM_WRITE_ECC) ++ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_SYSTEM_WRITE_ECC); ++ if (status & DMA_STATUS_FM_WRITE_ECC) ++ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_FM_WRITE_ECC); ++ } ++} ++ ++static void FpmErrEvent(t_Fm *p_Fm) ++{ ++ uint32_t event; ++ ++ event = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee); ++ ++ /* clear the all occurred events */ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, event); ++ ++ if ((event & FPM_EV_MASK_DOUBLE_ECC) && (event & FPM_EV_MASK_DOUBLE_ECC_EN)) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_DOUBLE_ECC); ++ if ((event & FPM_EV_MASK_STALL) && (event & FPM_EV_MASK_STALL_EN)) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_STALL_ON_TASKS); ++ if ((event & FPM_EV_MASK_SINGLE_ECC) && (event & FPM_EV_MASK_SINGLE_ECC_EN)) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_SINGLE_ECC); ++} ++ ++static void MuramErrIntr(t_Fm *p_Fm) ++{ ++ uint32_t event, mask; ++ ++ event = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr); ++ mask = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rie); ++ ++ ASSERT_COND(event & FPM_RAM_CTL_MURAM_ECC); ++ ++ /* clear MURAM event bit */ ++ /* Prior to V3 this event bit clearing does not work ! ) */ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, event & ~FPM_RAM_CTL_IRAM_ECC); ++ ++ ASSERT_COND(event & FPM_RAM_CTL_RAMS_ECC_EN); ++ ++ if ((mask & FPM_MURAM_ECC_ERR_EX_EN)) ++ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_MURAM_ECC); ++} ++ ++static void IramErrIntr(t_Fm *p_Fm) ++{ ++ uint32_t event, mask; ++ ++ event = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr) ; ++ mask = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rie); ++ ++ ASSERT_COND(event & FPM_RAM_CTL_IRAM_ECC); ++ ++ /* clear the acknowledged events (do not clear IRAM event) */ ++ /* Prior to V3 this event bit clearing does not work ! ) */ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, event & ~FPM_RAM_CTL_MURAM_ECC); ++ ++ ASSERT_COND(event & FPM_RAM_CTL_IRAM_ECC_EN); ++ ++ if ((mask & FPM_IRAM_ECC_ERR_EX_EN)) ++ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_IRAM_ECC); ++} ++ ++static void QmiEvent(t_Fm *p_Fm) ++{ ++ uint32_t event, mask, force; ++ ++ event = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_ie); ++ mask = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_ien); ++ ++ event &= mask; ++ ++ /* clear the forced events */ ++ force = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_if); ++ if (force & event) ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_if, force & ~event); ++ ++ /* clear the acknowledged events */ ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_ie, event); ++ ++ if (event & QMI_INTR_EN_SINGLE_ECC) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_SINGLE_ECC); ++} ++ ++static void UnimplementedIsr(t_Handle h_Arg) ++{ ++ UNUSED(h_Arg); ++ ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unimplemented ISR!")); ++} ++ ++static void UnimplementedFmanCtrlIsr(t_Handle h_Arg, uint32_t event) ++{ ++ UNUSED(h_Arg); UNUSED(event); ++ ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unimplemented FmCtl ISR!")); ++} ++ ++static void EnableTimeStamp(t_Fm *p_Fm) ++{ ++ uint64_t fraction; ++ uint32_t integer, tsFrequency, tmpReg; ++ ++ ASSERT_COND(p_Fm); ++ ASSERT_COND(p_Fm->p_FmStateStruct); ++ ASSERT_COND(p_Fm->p_FmStateStruct->count1MicroBit); ++ ++ tsFrequency = (uint32_t)(1<p_FmStateStruct->count1MicroBit); /* in Mhz */ ++ ++ /* configure timestamp so that bit 8 will count 1 microsecond */ ++ /* Find effective count rate at TIMESTAMP least significant bits: ++ Effective_Count_Rate = 1MHz x 2^8 = 256MHz ++ Find frequency ratio between effective count rate and the clock: ++ Effective_Count_Rate / CLK e.g. for 600 MHz clock: ++ 256/600 = 0.4266666... */ ++ integer = tsFrequency/p_Fm->p_FmStateStruct->fmClkFreq; ++ /* we multiply by 2^16 to keep the fraction of the division */ ++ /* we do not divide back, since we write this value as fraction - see spec */ ++ fraction = ((tsFrequency << 16) - (integer << 16) * p_Fm->p_FmStateStruct->fmClkFreq) / p_Fm->p_FmStateStruct->fmClkFreq; ++ /* we check remainder of the division in order to round up if not integer */ ++ if (((tsFrequency << 16) - (integer << 16) * p_Fm->p_FmStateStruct->fmClkFreq) % p_Fm->p_FmStateStruct->fmClkFreq) ++ fraction++; ++ ++ tmpReg = (integer << FPM_TS_INT_SHIFT) | (uint16_t)fraction; ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_tsc2, tmpReg); ++ ++ /* enable timestamp with original clock */ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_tsc1, FPM_TS_CTL_EN); ++ ++ p_Fm->p_FmStateStruct->enabledTimeStamp = TRUE; ++} ++ ++static t_Error ClearIRam(t_Fm *p_Fm) ++{ ++ t_FMIramRegs *p_Iram; ++ int i; ++ ++ ASSERT_COND(p_Fm); ++ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); ++ ++ /* Enable the auto-increment */ ++ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE); ++ while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ; ++ ++ for (i=0; i < (FM_IRAM_SIZE/4); i++) ++ WRITE_UINT32(p_Iram->idata, 0xffffffff); ++ ++ WRITE_UINT32(p_Iram->iadd, FM_IRAM_SIZE - 4); ++ CORE_MemoryBarrier(); ++ while (GET_UINT32(p_Iram->idata) != 0xffffffff) ; ++ ++ return E_OK; ++} ++ ++static t_Error LoadFmanCtrlCode(t_Fm *p_Fm) ++{ ++ t_FMIramRegs *p_Iram; ++ int i; ++ uint32_t tmp; ++ uint8_t compTo16; ++ ++ ASSERT_COND(p_Fm); ++ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); ++ ++ /* Enable the auto-increment */ ++ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE); ++ while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ; ++ ++ for (i=0; i < (p_Fm->p_FmDriverParam->firmware.size / 4); i++) ++ WRITE_UINT32(p_Iram->idata, p_Fm->p_FmDriverParam->firmware.p_Code[i]); ++ ++ compTo16 = (uint8_t)(p_Fm->p_FmDriverParam->firmware.size % 16); ++ if (compTo16) ++ for (i=0; i < ((16-compTo16) / 4); i++) ++ WRITE_UINT32(p_Iram->idata, 0xffffffff); ++ ++ WRITE_UINT32(p_Iram->iadd,p_Fm->p_FmDriverParam->firmware.size-4); ++ while (GET_UINT32(p_Iram->iadd) != (p_Fm->p_FmDriverParam->firmware.size-4)) ; ++ ++ /* verify that writing has completed */ ++ while (GET_UINT32(p_Iram->idata) != p_Fm->p_FmDriverParam->firmware.p_Code[(p_Fm->p_FmDriverParam->firmware.size / 4)-1]) ; ++ ++ if (p_Fm->p_FmDriverParam->fwVerify) ++ { ++ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE); ++ while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ; ++ for (i=0; i < (p_Fm->p_FmDriverParam->firmware.size / 4); i++) ++ { ++ tmp = GET_UINT32(p_Iram->idata); ++ if (tmp != p_Fm->p_FmDriverParam->firmware.p_Code[i]) ++ RETURN_ERROR(MAJOR, E_WRITE_FAILED, ++ ("UCode write error : write 0x%x, read 0x%x", ++ p_Fm->p_FmDriverParam->firmware.p_Code[i],tmp)); ++ } ++ WRITE_UINT32(p_Iram->iadd, 0x0); ++ } ++ ++ /* Enable patch from IRAM */ ++ WRITE_UINT32(p_Iram->iready, IRAM_READY); ++ XX_UDelay(1000); ++ ++ DBG(INFO, ("FMan-Controller code (ver %d.%d.%d) loaded to IRAM.", ++ ((uint16_t *)p_Fm->p_FmDriverParam->firmware.p_Code)[2], ++ ((uint8_t *)p_Fm->p_FmDriverParam->firmware.p_Code)[6], ++ ((uint8_t *)p_Fm->p_FmDriverParam->firmware.p_Code)[7])); ++ ++ return E_OK; ++} ++ ++#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 ++static t_Error FwNotResetErratumBugzilla6173WA(t_Fm *p_Fm) ++{ ++ t_FMIramRegs *p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); ++ uint32_t tmpReg; ++ ++ /* write to IRAM first location the debug instruction */ ++ WRITE_UINT32(p_Iram->iadd, 0); ++ while (GET_UINT32(p_Iram->iadd) != 0) ; ++ WRITE_UINT32(p_Iram->idata, FM_FW_DEBUG_INSTRUCTION); ++ ++ WRITE_UINT32(p_Iram->iadd, 0); ++ while (GET_UINT32(p_Iram->iadd) != 0) ; ++ while (GET_UINT32(p_Iram->idata) != FM_FW_DEBUG_INSTRUCTION) ; ++ ++ /* Enable patch from IRAM */ ++ WRITE_UINT32(p_Iram->iready, IRAM_READY); ++ CORE_MemoryBarrier(); ++ XX_UDelay(100); ++ ++ /* reset FMAN */ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET); ++ CORE_MemoryBarrier(); ++ XX_UDelay(100); ++ ++ /* verify breakpoint debug status register */ ++ tmpReg = GET_UINT32(*(uint32_t *)UINT_TO_PTR(p_Fm->baseAddr + FM_DEBUG_STATUS_REGISTER_OFFSET)); ++ if (!tmpReg) ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid debug status register value is '0'")); ++ ++ /*************************************/ ++ /* Load FMan-Controller code to IRAM */ ++ /*************************************/ ++ if (ClearIRam(p_Fm) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ if (p_Fm->p_FmDriverParam->firmware.p_Code && ++ (LoadFmanCtrlCode(p_Fm) != E_OK)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ XX_UDelay(100); ++ ++ /* reset FMAN again to start the microcode */ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET); ++ CORE_MemoryBarrier(); ++ XX_UDelay(100); ++ ++ if (GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gs) & QMI_GS_HALT_NOT_BUSY) ++ { ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee); ++ /* clear tmpReg event bits in order not to clear standing events */ ++ tmpReg &= ~(FPM_EV_MASK_DOUBLE_ECC | FPM_EV_MASK_STALL | FPM_EV_MASK_SINGLE_ECC); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg | FPM_EV_MASK_RELEASE_FM); ++ CORE_MemoryBarrier(); ++ XX_UDelay(100); ++ } ++ ++ return E_OK; ++} ++#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ ++ ++static void GuestErrorIsr(t_Fm *p_Fm, uint32_t pending) ++{ ++#define FM_G_CALL_1G_MAC_ERR_ISR(_id) \ ++do { \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].h_SrcHandle);\ ++} while (0) ++#define FM_G_CALL_10G_MAC_ERR_ISR(_id) \ ++do { \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].h_SrcHandle);\ ++} while (0) ++ ++ /* error interrupts */ ++ if (pending & ERR_INTR_EN_1G_MAC0) ++ FM_G_CALL_1G_MAC_ERR_ISR(0); ++ if (pending & ERR_INTR_EN_1G_MAC1) ++ FM_G_CALL_1G_MAC_ERR_ISR(1); ++ if (pending & ERR_INTR_EN_1G_MAC2) ++ FM_G_CALL_1G_MAC_ERR_ISR(2); ++ if (pending & ERR_INTR_EN_1G_MAC3) ++ FM_G_CALL_1G_MAC_ERR_ISR(3); ++ if (pending & ERR_INTR_EN_1G_MAC4) ++ FM_G_CALL_1G_MAC_ERR_ISR(4); ++ if (pending & ERR_INTR_EN_1G_MAC5) ++ FM_G_CALL_1G_MAC_ERR_ISR(5); ++ if (pending & ERR_INTR_EN_1G_MAC6) ++ FM_G_CALL_1G_MAC_ERR_ISR(6); ++ if (pending & ERR_INTR_EN_1G_MAC7) ++ FM_G_CALL_1G_MAC_ERR_ISR(7); ++ if (pending & ERR_INTR_EN_10G_MAC0) ++ FM_G_CALL_10G_MAC_ERR_ISR(0); ++ if (pending & ERR_INTR_EN_10G_MAC1) ++ FM_G_CALL_10G_MAC_ERR_ISR(1); ++} ++ ++static void GuestEventIsr(t_Fm *p_Fm, uint32_t pending) ++{ ++#define FM_G_CALL_1G_MAC_ISR(_id) \ ++do { \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].h_SrcHandle);\ ++} while (0) ++#define FM_G_CALL_10G_MAC_ISR(_id) \ ++do { \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].h_SrcHandle);\ ++} while (0) ++ ++ if (pending & INTR_EN_1G_MAC0) ++ FM_G_CALL_1G_MAC_ISR(0); ++ if (pending & INTR_EN_1G_MAC1) ++ FM_G_CALL_1G_MAC_ISR(1); ++ if (pending & INTR_EN_1G_MAC2) ++ FM_G_CALL_1G_MAC_ISR(2); ++ if (pending & INTR_EN_1G_MAC3) ++ FM_G_CALL_1G_MAC_ISR(3); ++ if (pending & INTR_EN_1G_MAC4) ++ FM_G_CALL_1G_MAC_ISR(4); ++ if (pending & INTR_EN_1G_MAC5) ++ FM_G_CALL_1G_MAC_ISR(5); ++ if (pending & INTR_EN_1G_MAC6) ++ FM_G_CALL_1G_MAC_ISR(6); ++ if (pending & INTR_EN_1G_MAC7) ++ FM_G_CALL_1G_MAC_ISR(7); ++ if (pending & INTR_EN_10G_MAC0) ++ FM_G_CALL_10G_MAC_ISR(0); ++ if (pending & INTR_EN_10G_MAC1) ++ FM_G_CALL_10G_MAC_ISR(1); ++ if (pending & INTR_EN_TMR) ++ p_Fm->intrMng[e_FM_EV_TMR].f_Isr(p_Fm->intrMng[e_FM_EV_TMR].h_SrcHandle); ++} ++ ++#if (DPAA_VERSION >= 11) ++static t_Error SetVSPWindow(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t baseStorageProfile, ++ uint8_t log2NumOfProfiles) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ uint32_t tmpReg; ++ ++ ASSERT_COND(h_Fm); ++ ASSERT_COND(hardwarePortId); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->p_FmBmiRegs && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcVspSetPortWindow fmIpcVspSetPortWindow; ++ t_FmIpcMsg msg; ++ t_Error err = E_OK; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&fmIpcVspSetPortWindow, 0, sizeof(t_FmIpcVspSetPortWindow)); ++ fmIpcVspSetPortWindow.hardwarePortId = hardwarePortId; ++ fmIpcVspSetPortWindow.baseStorageProfile = baseStorageProfile; ++ fmIpcVspSetPortWindow.log2NumOfProfiles = log2NumOfProfiles; ++ msg.msgId = FM_VSP_SET_PORT_WINDOW; ++ memcpy(msg.msgBody, &fmIpcVspSetPortWindow, sizeof(t_FmIpcVspSetPortWindow)); ++ ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ return E_OK; ++ } ++ else if (!p_Fm->p_FmBmiRegs) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1]); ++ tmpReg |= (uint32_t)((uint32_t)baseStorageProfile & 0x3f) << 16; ++ tmpReg |= (uint32_t)log2NumOfProfiles << 28; ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], tmpReg); ++ ++ return E_OK; ++} ++ ++static uint8_t AllocVSPsForPartition(t_Handle h_Fm, uint8_t base, uint8_t numOfProfiles, uint8_t guestId) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ uint8_t profilesFound = 0; ++ int i = 0; ++ uint32_t intFlags; ++ ++ if (!numOfProfiles) ++ return E_OK; ++ ++ if ((numOfProfiles > FM_VSP_MAX_NUM_OF_ENTRIES) || ++ (base + numOfProfiles > FM_VSP_MAX_NUM_OF_ENTRIES)) ++ return (uint8_t)ILLEGAL_BASE; ++ ++ if (p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ t_Error err; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ++ ipcAllocParams.guestId = p_Fm->guestId; ++ ipcAllocParams.num = p_Fm->partNumOfVSPs; ++ ipcAllocParams.base = p_Fm->partVSPBase; ++ msg.msgId = FM_VSP_ALLOC; ++ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); ++ replyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if ((err != E_OK) || ++ (replyLength != (sizeof(uint32_t) + sizeof(uint8_t)))) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ else ++ memcpy((uint8_t*)&p_Fm->partVSPBase, reply.replyBody, sizeof(uint8_t)); ++ if (p_Fm->partVSPBase == ILLEGAL_BASE) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ DBG(WARNING, ("FM Guest mode, without IPC - can't validate VSP range!")); ++ return (uint8_t)ILLEGAL_BASE; ++ } ++ ++ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); ++ for (i = base; i < base + numOfProfiles; i++) ++ if (p_Fm->p_FmSp->profiles[i].profilesMng.ownerId == (uint8_t)ILLEGAL_BASE) ++ profilesFound++; ++ else ++ break; ++ ++ if (profilesFound == numOfProfiles) ++ for (i = base; ip_FmSp->profiles[i].profilesMng.ownerId = guestId; ++ else ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ return (uint8_t)ILLEGAL_BASE; ++ } ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ ++ return base; ++} ++ ++static void FreeVSPsForPartition(t_Handle h_Fm, uint8_t base, uint8_t numOfProfiles, uint8_t guestId) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ int i = 0; ++ ++ ASSERT_COND(p_Fm); ++ ++ if (p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ t_Error err; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ++ ipcAllocParams.guestId = p_Fm->guestId; ++ ipcAllocParams.num = p_Fm->partNumOfVSPs; ++ ipcAllocParams.base = p_Fm->partVSPBase; ++ msg.msgId = FM_VSP_FREE; ++ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); ++ replyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return; ++ } ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ DBG(WARNING, ("FM Guest mode, without IPC - can't validate VSP range!")); ++ return; ++ } ++ ++ ASSERT_COND(p_Fm->p_FmSp); ++ ++ for (i=base; ip_FmSp->profiles[i].profilesMng.ownerId == guestId) ++ p_Fm->p_FmSp->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE; ++ else ++ DBG(WARNING, ("Request for freeing storage profile window which wasn't allocated to this partition")); ++ } ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++static t_Error FmGuestHandleIpcMsgCB(t_Handle h_Fm, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_FmIpcMsg *p_IpcMsg = (t_FmIpcMsg*)p_Msg; ++ ++ UNUSED(p_Reply); ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((msgLength > sizeof(uint32_t)), E_INVALID_VALUE); ++ ++#ifdef DISABLE_SANITY_CHECKS ++ UNUSED(msgLength); ++#endif /* DISABLE_SANITY_CHECKS */ ++ ++ ASSERT_COND(p_Msg); ++ ++ *p_ReplyLength = 0; ++ ++ switch (p_IpcMsg->msgId) ++ { ++ case (FM_GUEST_ISR): ++ { ++ t_FmIpcIsr ipcIsr; ++ ++ memcpy((uint8_t*)&ipcIsr, p_IpcMsg->msgBody, sizeof(t_FmIpcIsr)); ++ if (ipcIsr.boolErr) ++ GuestErrorIsr(p_Fm, ipcIsr.pendingReg); ++ else ++ GuestEventIsr(p_Fm, ipcIsr.pendingReg); ++ break; ++ } ++ default: ++ *p_ReplyLength = 0; ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!")); ++ } ++ return E_OK; ++} ++ ++static t_Error FmHandleIpcMsgCB(t_Handle h_Fm, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength) ++{ ++ t_Error err; ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_FmIpcMsg *p_IpcMsg = (t_FmIpcMsg*)p_Msg; ++ t_FmIpcReply *p_IpcReply = (t_FmIpcReply*)p_Reply; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE); ++ ++#ifdef DISABLE_SANITY_CHECKS ++ UNUSED(msgLength); ++#endif /* DISABLE_SANITY_CHECKS */ ++ ++ ASSERT_COND(p_IpcMsg); ++ ++ memset(p_IpcReply, 0, (sizeof(uint8_t) * FM_IPC_MAX_REPLY_SIZE)); ++ *p_ReplyLength = 0; ++ ++ switch (p_IpcMsg->msgId) ++ { ++ case (FM_GET_SET_PORT_PARAMS): ++ { ++ t_FmIpcPortInInitParams ipcInitParams; ++ t_FmInterModulePortInitParams initParams; ++ t_FmIpcPortOutInitParams ipcOutInitParams; ++ ++ memcpy((uint8_t*)&ipcInitParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortInInitParams)); ++ initParams.hardwarePortId = ipcInitParams.hardwarePortId; ++ initParams.portType = (e_FmPortType)ipcInitParams.enumPortType; ++ initParams.independentMode = (bool)(ipcInitParams.boolIndependentMode); ++ initParams.liodnOffset = ipcInitParams.liodnOffset; ++ initParams.numOfTasks = ipcInitParams.numOfTasks; ++ initParams.numOfExtraTasks = ipcInitParams.numOfExtraTasks; ++ initParams.numOfOpenDmas = ipcInitParams.numOfOpenDmas; ++ initParams.numOfExtraOpenDmas = ipcInitParams.numOfExtraOpenDmas; ++ initParams.sizeOfFifo = ipcInitParams.sizeOfFifo; ++ initParams.extraSizeOfFifo = ipcInitParams.extraSizeOfFifo; ++ initParams.deqPipelineDepth = ipcInitParams.deqPipelineDepth; ++ initParams.maxFrameLength = ipcInitParams.maxFrameLength; ++ initParams.liodnBase = ipcInitParams.liodnBase; ++ ++ p_IpcReply->error = (uint32_t)FmGetSetPortParams(h_Fm, &initParams); ++ ++ ipcOutInitParams.ipcPhysAddr.high = initParams.fmMuramPhysBaseAddr.high; ++ ipcOutInitParams.ipcPhysAddr.low = initParams.fmMuramPhysBaseAddr.low; ++ ipcOutInitParams.sizeOfFifo = initParams.sizeOfFifo; ++ ipcOutInitParams.extraSizeOfFifo = initParams.extraSizeOfFifo; ++ ipcOutInitParams.numOfTasks = initParams.numOfTasks; ++ ipcOutInitParams.numOfExtraTasks = initParams.numOfExtraTasks; ++ ipcOutInitParams.numOfOpenDmas = initParams.numOfOpenDmas; ++ ipcOutInitParams.numOfExtraOpenDmas = initParams.numOfExtraOpenDmas; ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcOutInitParams, sizeof(ipcOutInitParams)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams); ++ break; ++ } ++ case (FM_SET_SIZE_OF_FIFO): ++ { ++ t_FmIpcPortRsrcParams ipcPortRsrcParams; ++ ++ memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams)); ++ p_IpcReply->error = (uint32_t)FmSetSizeOfFifo(h_Fm, ++ ipcPortRsrcParams.hardwarePortId, ++ &ipcPortRsrcParams.val, ++ &ipcPortRsrcParams.extra, ++ (bool)ipcPortRsrcParams.boolInitialConfig); ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ } ++ case (FM_SET_NUM_OF_TASKS): ++ { ++ t_FmIpcPortRsrcParams ipcPortRsrcParams; ++ ++ memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams)); ++ p_IpcReply->error = (uint32_t)FmSetNumOfTasks(h_Fm, ipcPortRsrcParams.hardwarePortId, ++ (uint8_t*)&ipcPortRsrcParams.val, ++ (uint8_t*)&ipcPortRsrcParams.extra, ++ (bool)ipcPortRsrcParams.boolInitialConfig); ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ } ++ case (FM_SET_NUM_OF_OPEN_DMAS): ++ { ++ t_FmIpcPortRsrcParams ipcPortRsrcParams; ++ ++ memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams)); ++ p_IpcReply->error = (uint32_t)FmSetNumOfOpenDmas(h_Fm, ipcPortRsrcParams.hardwarePortId, ++ (uint8_t*)&ipcPortRsrcParams.val, ++ (uint8_t*)&ipcPortRsrcParams.extra, ++ (bool)ipcPortRsrcParams.boolInitialConfig); ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ } ++ case (FM_RESUME_STALLED_PORT): ++ *p_ReplyLength = sizeof(uint32_t); ++ p_IpcReply->error = (uint32_t)FmResumeStalledPort(h_Fm, p_IpcMsg->msgBody[0]); ++ break; ++ case (FM_MASTER_IS_ALIVE): ++ { ++ uint8_t guestId = p_IpcMsg->msgBody[0]; ++ /* build the FM master partition IPC address */ ++ memset(p_Fm->fmIpcHandlerModuleName[guestId], 0, (sizeof(char)) * MODULE_NAME_SIZE); ++ if (Sprint (p_Fm->fmIpcHandlerModuleName[guestId], "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, guestId) != (guestId<10 ? 6:7)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ p_Fm->h_IpcSessions[guestId] = XX_IpcInitSession(p_Fm->fmIpcHandlerModuleName[guestId], p_Fm->fmModuleName); ++ if (p_Fm->h_IpcSessions[guestId] == NULL) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM Master IPC session for guest %d", guestId)); ++ *(uint8_t*)(p_IpcReply->replyBody) = 1; ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ } ++ case (FM_IS_PORT_STALLED): ++ { ++ bool tmp; ++ ++ p_IpcReply->error = (uint32_t)FmIsPortStalled(h_Fm, p_IpcMsg->msgBody[0], &tmp); ++ *(uint8_t*)(p_IpcReply->replyBody) = (uint8_t)tmp; ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ } ++ case (FM_RESET_MAC): ++ { ++ t_FmIpcMacParams ipcMacParams; ++ ++ memcpy((uint8_t*)&ipcMacParams, p_IpcMsg->msgBody, sizeof(t_FmIpcMacParams)); ++ p_IpcReply->error = (uint32_t)FmResetMac(p_Fm, ++ (e_FmMacType)(ipcMacParams.enumType), ++ ipcMacParams.id); ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ } ++ case (FM_SET_MAC_MAX_FRAME): ++ { ++ t_FmIpcMacMaxFrameParams ipcMacMaxFrameParams; ++ ++ memcpy((uint8_t*)&ipcMacMaxFrameParams, p_IpcMsg->msgBody, sizeof(t_FmIpcMacMaxFrameParams)); ++ err = FmSetMacMaxFrame(p_Fm, ++ (e_FmMacType)(ipcMacMaxFrameParams.macParams.enumType), ++ ipcMacMaxFrameParams.macParams.id, ++ ipcMacMaxFrameParams.maxFrameLength); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ break; ++ } ++#if (DPAA_VERSION >= 11) ++ case (FM_VSP_ALLOC) : ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ uint8_t vspBase; ++ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); ++ vspBase = AllocVSPsForPartition(h_Fm, ipcAllocParams.base, ipcAllocParams.num, ipcAllocParams.guestId); ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&vspBase, sizeof(uint8_t)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ } ++ case (FM_VSP_FREE) : ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); ++ FreeVSPsForPartition(h_Fm, ipcAllocParams.base, ipcAllocParams.num, ipcAllocParams.guestId); ++ break; ++ } ++ case (FM_VSP_SET_PORT_WINDOW) : ++ { ++ t_FmIpcVspSetPortWindow ipcVspSetPortWindow; ++ memcpy(&ipcVspSetPortWindow, p_IpcMsg->msgBody, sizeof(t_FmIpcVspSetPortWindow)); ++ err = SetVSPWindow(h_Fm, ++ ipcVspSetPortWindow.hardwarePortId, ++ ipcVspSetPortWindow.baseStorageProfile, ++ ipcVspSetPortWindow.log2NumOfProfiles); ++ return err; ++ } ++ case (FM_SET_CONG_GRP_PFC_PRIO) : ++ { ++ t_FmIpcSetCongestionGroupPfcPriority fmIpcSetCongestionGroupPfcPriority; ++ memcpy(&fmIpcSetCongestionGroupPfcPriority, p_IpcMsg->msgBody, sizeof(t_FmIpcSetCongestionGroupPfcPriority)); ++ err = FmSetCongestionGroupPFCpriority(h_Fm, ++ fmIpcSetCongestionGroupPfcPriority.congestionGroupId, ++ fmIpcSetCongestionGroupPfcPriority.priorityBitMap); ++ return err; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ case (FM_FREE_PORT): ++ { ++ t_FmInterModulePortFreeParams portParams; ++ t_FmIpcPortFreeParams ipcPortParams; ++ ++ memcpy((uint8_t*)&ipcPortParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortFreeParams)); ++ portParams.hardwarePortId = ipcPortParams.hardwarePortId; ++ portParams.portType = (e_FmPortType)(ipcPortParams.enumPortType); ++ portParams.deqPipelineDepth = ipcPortParams.deqPipelineDepth; ++ FmFreePortParams(h_Fm, &portParams); ++ break; ++ } ++ case (FM_REGISTER_INTR): ++ { ++ t_FmIpcRegisterIntr ipcRegIntr; ++ ++ memcpy((uint8_t*)&ipcRegIntr, p_IpcMsg->msgBody, sizeof(ipcRegIntr)); ++ p_Fm->intrMng[ipcRegIntr.event].guestId = ipcRegIntr.guestId; ++ break; ++ } ++ case (FM_GET_PARAMS): ++ { ++ t_FmIpcParams ipcParams; ++ uint32_t tmpReg; ++ ++ /* Get clock frequency */ ++ ipcParams.fmClkFreq = p_Fm->p_FmStateStruct->fmClkFreq; ++ ++ /* read FM revision register 1 */ ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_ip_rev_1); ++ ipcParams.majorRev = (uint8_t)((tmpReg & FPM_REV1_MAJOR_MASK) >> FPM_REV1_MAJOR_SHIFT); ++ ipcParams.minorRev = (uint8_t)((tmpReg & FPM_REV1_MINOR_MASK) >> FPM_REV1_MINOR_SHIFT); ++ ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcParams, sizeof(t_FmIpcParams)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcParams); ++ break; ++ } ++ case (FM_GET_FMAN_CTRL_CODE_REV): ++ { ++ t_FmCtrlCodeRevisionInfo fmanCtrlRevInfo; ++ t_FmIpcFmanCtrlCodeRevisionInfo ipcRevInfo; ++ ++ p_IpcReply->error = (uint32_t)FM_GetFmanCtrlCodeRevision(h_Fm, &fmanCtrlRevInfo); ++ ipcRevInfo.packageRev = fmanCtrlRevInfo.packageRev; ++ ipcRevInfo.majorRev = fmanCtrlRevInfo.majorRev; ++ ipcRevInfo.minorRev = fmanCtrlRevInfo.minorRev; ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcRevInfo, sizeof(t_FmIpcFmanCtrlCodeRevisionInfo)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcFmanCtrlCodeRevisionInfo); ++ break; ++ } ++ ++ case (FM_DMA_STAT): ++ { ++ t_FmDmaStatus dmaStatus; ++ t_FmIpcDmaStatus ipcDmaStatus; ++ ++ FM_GetDmaStatus(h_Fm, &dmaStatus); ++ ipcDmaStatus.boolCmqNotEmpty = (uint8_t)dmaStatus.cmqNotEmpty; ++ ipcDmaStatus.boolBusError = (uint8_t)dmaStatus.busError; ++ ipcDmaStatus.boolReadBufEccError = (uint8_t)dmaStatus.readBufEccError; ++ ipcDmaStatus.boolWriteBufEccSysError = (uint8_t)dmaStatus.writeBufEccSysError; ++ ipcDmaStatus.boolWriteBufEccFmError = (uint8_t)dmaStatus.writeBufEccFmError; ++ ipcDmaStatus.boolSinglePortEccError = (uint8_t)dmaStatus.singlePortEccError; ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcDmaStatus, sizeof(t_FmIpcDmaStatus)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus); ++ break; ++ } ++ case (FM_ALLOC_FMAN_CTRL_EVENT_REG): ++ p_IpcReply->error = (uint32_t)FmAllocFmanCtrlEventReg(h_Fm, (uint8_t*)p_IpcReply->replyBody); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ case (FM_FREE_FMAN_CTRL_EVENT_REG): ++ FmFreeFmanCtrlEventReg(h_Fm, p_IpcMsg->msgBody[0]); ++ break; ++ case (FM_GET_TIMESTAMP_SCALE): ++ { ++ uint32_t timeStamp = FmGetTimeStampScale(h_Fm); ++ ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&timeStamp, sizeof(uint32_t)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ break; ++ } ++ case (FM_GET_COUNTER): ++ { ++ e_FmCounters inCounter; ++ uint32_t outCounter; ++ ++ memcpy((uint8_t*)&inCounter, p_IpcMsg->msgBody, sizeof(uint32_t)); ++ outCounter = FM_GetCounter(h_Fm, inCounter); ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&outCounter, sizeof(uint32_t)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ break; ++ } ++ case (FM_SET_FMAN_CTRL_EVENTS_ENABLE): ++ { ++ t_FmIpcFmanEvents ipcFmanEvents; ++ ++ memcpy((uint8_t*)&ipcFmanEvents, p_IpcMsg->msgBody, sizeof(t_FmIpcFmanEvents)); ++ FmSetFmanCtrlIntr(h_Fm, ++ ipcFmanEvents.eventRegId, ++ ipcFmanEvents.enableEvents); ++ break; ++ } ++ case (FM_GET_FMAN_CTRL_EVENTS_ENABLE): ++ { ++ uint32_t tmp = FmGetFmanCtrlIntr(h_Fm, p_IpcMsg->msgBody[0]); ++ ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&tmp, sizeof(uint32_t)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ break; ++ } ++ case (FM_GET_PHYS_MURAM_BASE): ++ { ++ t_FmPhysAddr physAddr; ++ t_FmIpcPhysAddr ipcPhysAddr; ++ ++ FmGetPhysicalMuramBase(h_Fm, &physAddr); ++ ipcPhysAddr.high = physAddr.high; ++ ipcPhysAddr.low = physAddr.low; ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcPhysAddr, sizeof(t_FmIpcPhysAddr)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcPhysAddr); ++ break; ++ } ++ case (FM_ENABLE_RAM_ECC): ++ { ++ if (((err = FM_EnableRamsEcc(h_Fm)) != E_OK) || ++ ((err = FM_SetException(h_Fm, e_FM_EX_IRAM_ECC, TRUE)) != E_OK) || ++ ((err = FM_SetException(h_Fm, e_FM_EX_MURAM_ECC, TRUE)) != E_OK)) ++#if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) ++ UNUSED(err); ++#else ++ REPORT_ERROR(MINOR, err, NO_MSG); ++#endif /* (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) */ ++ break; ++ } ++ case (FM_DISABLE_RAM_ECC): ++ { ++ ++ if (((err = FM_SetException(h_Fm, e_FM_EX_IRAM_ECC, FALSE)) != E_OK) || ++ ((err = FM_SetException(h_Fm, e_FM_EX_MURAM_ECC, FALSE)) != E_OK) || ++ ((err = FM_DisableRamsEcc(h_Fm)) != E_OK)) ++#if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) ++ UNUSED(err); ++#else ++ REPORT_ERROR(MINOR, err, NO_MSG); ++#endif /* (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) */ ++ break; ++ } ++ case (FM_SET_NUM_OF_FMAN_CTRL): ++ { ++ t_FmIpcPortNumOfFmanCtrls ipcPortNumOfFmanCtrls; ++ ++ memcpy((uint8_t*)&ipcPortNumOfFmanCtrls, p_IpcMsg->msgBody, sizeof(t_FmIpcPortNumOfFmanCtrls)); ++ err = FmSetNumOfRiscsPerPort(h_Fm, ++ ipcPortNumOfFmanCtrls.hardwarePortId, ++ ipcPortNumOfFmanCtrls.numOfFmanCtrls, ++ ipcPortNumOfFmanCtrls.orFmanCtrl); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ break; ++ } ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++ case (FM_10G_TX_ECC_WA): ++ p_IpcReply->error = (uint32_t)Fm10GTxEccWorkaround(h_Fm, p_IpcMsg->msgBody[0]); ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ default: ++ *p_ReplyLength = 0; ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!")); ++ } ++ return E_OK; ++} ++ ++ ++/****************************************/ ++/* Inter-Module functions */ ++/****************************************/ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++t_Error Fm10GTxEccWorkaround(t_Handle h_Fm, uint8_t macId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ int timeout = 1000; ++ t_Error err = E_OK; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ uint8_t rxHardwarePortId, txHardwarePortId; ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_10G_TX_ECC_WA; ++ msg.msgBody[0] = macId; ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(macId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++ ++ SANITY_CHECK_RETURN_ERROR((macId == 0), E_NOT_SUPPORTED); ++ SANITY_CHECK_RETURN_ERROR(IsFmanCtrlCodeLoaded(p_Fm), E_INVALID_STATE); ++ ++ SW_PORT_ID_TO_HW_PORT_ID(rxHardwarePortId, e_FM_PORT_TYPE_RX_10G, macId); ++ SW_PORT_ID_TO_HW_PORT_ID(txHardwarePortId, e_FM_PORT_TYPE_TX_10G, macId); ++ if ((p_Fm->p_FmStateStruct->portsTypes[rxHardwarePortId] != e_FM_PORT_TYPE_DUMMY) || ++ (p_Fm->p_FmStateStruct->portsTypes[txHardwarePortId] != e_FM_PORT_TYPE_DUMMY)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("MAC should be initialized prior to Rx and Tx ports!")); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc, 0x40000000); ++ CORE_MemoryBarrier(); ++ while ((GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc) & 0x40000000) && ++ --timeout) ; ++ if (!timeout) ++ return ERROR_CODE(E_TIMEOUT); ++ return E_OK; ++} ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++t_Error FmSetCongestionGroupPFCpriority(t_Handle h_Fm, ++ uint32_t congestionGroupId, ++ uint8_t priorityBitMap) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ ++ ASSERT_COND(h_Fm); ++ ++ if (congestionGroupId > FM_PORT_NUM_OF_CONGESTION_GRPS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("Congestion group ID bigger than %d \n!", ++ FM_PORT_NUM_OF_CONGESTION_GRPS)); ++ ++ if (p_Fm->guestId == NCSW_MASTER_ID) ++ { ++ uint32_t *p_Cpg = (uint32_t*)(p_Fm->baseAddr+FM_MM_CGP); ++ uint32_t tmpReg; ++ uint32_t reg_num; ++ uint32_t offset; ++ ++ ASSERT_COND(p_Fm->baseAddr); ++ reg_num = (FM_PORT_NUM_OF_CONGESTION_GRPS-1-(congestionGroupId))/4; ++ offset = (congestionGroupId%4); ++ ++ tmpReg = GET_UINT32(p_Cpg[reg_num]); ++ ++ if (priorityBitMap)//adding priority ++ { ++ if (tmpReg & (0xFF<<(offset*8))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("PFC priority for the congestion group is already set!")); ++ } ++ tmpReg |= (uint32_t)priorityBitMap << (offset*8); ++ WRITE_UINT32(p_Cpg[reg_num], tmpReg); ++ } ++ ++ else if (p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcSetCongestionGroupPfcPriority fmIpcSetCongestionGroupPfcPriority; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&fmIpcSetCongestionGroupPfcPriority, 0, sizeof(t_FmIpcSetCongestionGroupPfcPriority)); ++ fmIpcSetCongestionGroupPfcPriority.congestionGroupId = congestionGroupId; ++ fmIpcSetCongestionGroupPfcPriority.priorityBitMap = priorityBitMap; ++ ++ msg.msgId = FM_SET_CONG_GRP_PFC_PRIO; ++ memcpy(msg.msgBody, &fmIpcSetCongestionGroupPfcPriority, sizeof(t_FmIpcSetCongestionGroupPfcPriority)); ++ ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("guest without IPC!")); ++ ++ return E_OK; ++} ++ ++uintptr_t FmGetPcdPrsBaseAddr(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); ++ ++ if (!p_Fm->baseAddr) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ++ ("No base-addr; probably Guest with IPC!")); ++ return 0; ++ } ++ ++ return (p_Fm->baseAddr + FM_MM_PRS); ++} ++ ++uintptr_t FmGetPcdKgBaseAddr(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); ++ ++ if (!p_Fm->baseAddr) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ++ ("No base-addr; probably Guest with IPC!")); ++ return 0; ++ } ++ ++ return (p_Fm->baseAddr + FM_MM_KG); ++} ++ ++uintptr_t FmGetPcdPlcrBaseAddr(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); ++ ++ if (!p_Fm->baseAddr) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ++ ("No base-addr; probably Guest with IPC!")); ++ return 0; ++ } ++ ++ return (p_Fm->baseAddr + FM_MM_PLCR); ++} ++ ++#if (DPAA_VERSION >= 11) ++uintptr_t FmGetVSPBaseAddr(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); ++ ++ return p_Fm->vspBaseAddr; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++t_Handle FmGetMuramHandle(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, NULL); ++ ++ return (p_Fm->h_FmMuram); ++} ++ ++void FmGetPhysicalMuramBase(t_Handle h_Fm, t_FmPhysAddr *p_FmPhysAddr) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ if (p_Fm->fmMuramPhysBaseAddr) ++ { ++ /* General FM driver initialization */ ++ p_FmPhysAddr->low = (uint32_t)p_Fm->fmMuramPhysBaseAddr; ++ p_FmPhysAddr->high = (uint8_t)((p_Fm->fmMuramPhysBaseAddr & 0x000000ff00000000LL) >> 32); ++ return; ++ } ++ ++ ASSERT_COND(p_Fm->guestId != NCSW_MASTER_ID); ++ ++ if (p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ t_FmIpcPhysAddr ipcPhysAddr; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_PHYS_MURAM_BASE; ++ replyLength = sizeof(uint32_t) + sizeof(t_FmPhysAddr); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return; ++ } ++ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmPhysAddr))) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_VALUE,("IPC reply length mismatch")); ++ return; ++ } ++ memcpy((uint8_t*)&ipcPhysAddr, reply.replyBody, sizeof(t_FmIpcPhysAddr)); ++ p_FmPhysAddr->high = ipcPhysAddr.high; ++ p_FmPhysAddr->low = ipcPhysAddr.low; ++ } ++ else ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++} ++ ++#if (DPAA_VERSION >= 11) ++t_Error FmVSPAllocForPort (t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint8_t numOfVSPs) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ t_Error err = E_OK; ++ uint32_t profilesFound, intFlags; ++ uint8_t first, i; ++ uint8_t log2Num; ++ uint8_t swPortIndex=0, hardwarePortId; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ if (!numOfVSPs) ++ return E_OK; ++ ++ if (numOfVSPs > FM_VSP_MAX_NUM_OF_ENTRIES) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles can not be bigger than %d.",FM_VSP_MAX_NUM_OF_ENTRIES)); ++ ++ if (!POWER_OF_2(numOfVSPs)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numProfiles must be a power of 2.")); ++ ++ LOG2((uint64_t)numOfVSPs, log2Num); ++ ++ if ((log2Num == 0) || (p_Fm->partVSPBase == 0)) ++ first = 0; ++ else ++ first = 1< (p_Fm->partVSPBase + p_Fm->partNumOfVSPs)) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("can not allocate storage profile port window")); ++ ++ if (first < p_Fm->partVSPBase) ++ while (first < p_Fm->partVSPBase) ++ first = first + numOfVSPs; ++ ++ if ((first + numOfVSPs) > (p_Fm->partVSPBase + p_Fm->partNumOfVSPs)) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("can not allocate storage profile port window")); ++ ++ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); ++ profilesFound = 0; ++ for (i=first; i < p_Fm->partVSPBase + p_Fm->partNumOfVSPs; ) ++ { ++ if (!p_Fm->p_FmSp->profiles[i].profilesMng.allocated) ++ { ++ profilesFound++; ++ i++; ++ if (profilesFound == numOfVSPs) ++ break; ++ } ++ else ++ { ++ profilesFound = 0; ++ /* advance i to the next aligned address */ ++ first = i = (uint8_t)(first + numOfVSPs); ++ } ++ } ++ if (profilesFound == numOfVSPs) ++ for (i = first; ip_FmSp->profiles[i].profilesMng.allocated = TRUE; ++ else ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ RETURN_ERROR(MINOR, E_FULL, ("No profiles.")); ++ } ++ ++ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, portType, portId) ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles = numOfVSPs; ++ p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase = first; ++ ++ if ((err = SetVSPWindow(h_Fm,hardwarePortId, first,log2Num)) != E_OK) ++ for (i = first; i < first + numOfVSPs; i++) ++ p_Fm->p_FmSp->profiles[i].profilesMng.allocated = FALSE; ++ ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmVSPFreeForPort(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ uint8_t swPortIndex=0, hardwarePortId, first, numOfVSPs, i; ++ uint32_t intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, portType, portId) ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ numOfVSPs = p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles; ++ first = p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase; ++ ++ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); ++ for (i = first; i < first + numOfVSPs; i++) ++ p_Fm->p_FmSp->profiles[i].profilesMng.allocated = FALSE; ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ ++ p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles = 0; ++ p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase = 0; ++ ++ return E_OK; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++t_Error FmAllocFmanCtrlEventReg(t_Handle h_Fm, uint8_t *p_EventId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint8_t i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_ALLOC_FMAN_CTRL_EVENT_REG; ++ replyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ ++ *p_EventId = *(uint8_t*)(reply.replyBody); ++ ++ return (t_Error)(reply.error); ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ for (i=0;iusedEventRegs[i]) ++ { ++ p_Fm->usedEventRegs[i] = TRUE; ++ *p_EventId = i; ++ break; ++ } ++ ++ if (i==FM_NUM_OF_FMAN_CTRL_EVENT_REGS) ++ RETURN_ERROR(MAJOR, E_BUSY, ("No resource - FMan controller event register.")); ++ ++ return E_OK; ++} ++ ++void FmFreeFmanCtrlEventReg(t_Handle h_Fm, uint8_t eventId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_FREE_FMAN_CTRL_EVENT_REG; ++ msg.msgBody[0] = eventId; ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(eventId), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return; ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ return; ++ } ++ ++ ((t_Fm*)h_Fm)->usedEventRegs[eventId] = FALSE; ++} ++ ++void FmSetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, uint32_t enableEvents) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->p_FmFpmRegs && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcFmanEvents fmanCtrl; ++ t_Error err; ++ t_FmIpcMsg msg; ++ ++ fmanCtrl.eventRegId = eventRegId; ++ fmanCtrl.enableEvents = enableEvents; ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_SET_FMAN_CTRL_EVENTS_ENABLE; ++ memcpy(msg.msgBody, &fmanCtrl, sizeof(fmanCtrl)); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(fmanCtrl), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return; ++ } ++ else if (!p_Fm->p_FmFpmRegs) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ return; ++ } ++ ++ ASSERT_COND(eventRegId < FM_NUM_OF_FMAN_CTRL_EVENT_REGS); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_cee[eventRegId], enableEvents); ++} ++ ++uint32_t FmGetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->p_FmFpmRegs && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength, ctrlIntr; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_FMAN_CTRL_EVENTS_ENABLE; ++ msg.msgBody[0] = eventRegId; ++ replyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(eventRegId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return 0; ++ } ++ if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return 0; ++ } ++ memcpy((uint8_t*)&ctrlIntr, reply.replyBody, sizeof(uint32_t)); ++ return ctrlIntr; ++ } ++ else if (!p_Fm->p_FmFpmRegs) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ return 0; ++ } ++ ++ return GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_cee[eventRegId]); ++} ++ ++void FmRegisterIntr(t_Handle h_Fm, ++ e_FmEventModules module, ++ uint8_t modId, ++ e_FmIntrType intrType, ++ void (*f_Isr) (t_Handle h_Arg), ++ t_Handle h_Arg) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ int event = 0; ++ ++ ASSERT_COND(h_Fm); ++ ++ GET_FM_MODULE_EVENT(module, modId, intrType, event); ++ ASSERT_COND(event < e_FM_EV_DUMMY_LAST); ++ ++ /* register in local FM structure */ ++ p_Fm->intrMng[event].f_Isr = f_Isr; ++ p_Fm->intrMng[event].h_SrcHandle = h_Arg; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcRegisterIntr fmIpcRegisterIntr; ++ t_Error err; ++ t_FmIpcMsg msg; ++ ++ /* register in Master FM structure */ ++ fmIpcRegisterIntr.event = (uint32_t)event; ++ fmIpcRegisterIntr.guestId = p_Fm->guestId; ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_REGISTER_INTR; ++ memcpy(msg.msgBody, &fmIpcRegisterIntr, sizeof(fmIpcRegisterIntr)); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(fmIpcRegisterIntr), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++} ++ ++void FmUnregisterIntr(t_Handle h_Fm, ++ e_FmEventModules module, ++ uint8_t modId, ++ e_FmIntrType intrType) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ int event = 0; ++ ++ ASSERT_COND(h_Fm); ++ ++ GET_FM_MODULE_EVENT(module, modId,intrType, event); ++ ASSERT_COND(event < e_FM_EV_DUMMY_LAST); ++ ++ p_Fm->intrMng[event].f_Isr = UnimplementedIsr; ++ p_Fm->intrMng[event].h_SrcHandle = NULL; ++} ++ ++void FmRegisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Arg, uint32_t event), t_Handle h_Arg) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ ASSERT_COND(eventRegIdguestId != NCSW_MASTER_ID) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode")); ++ return; ++ } ++ ++ p_Fm->fmanCtrlIntr[eventRegId].f_Isr = f_Isr; ++ p_Fm->fmanCtrlIntr[eventRegId].h_SrcHandle = h_Arg; ++} ++ ++void FmUnregisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ ASSERT_COND(eventRegIdguestId != NCSW_MASTER_ID) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode")); ++ return; ++ } ++ ++ p_Fm->fmanCtrlIntr[eventRegId].f_Isr = UnimplementedFmanCtrlIsr; ++ p_Fm->fmanCtrlIntr[eventRegId].h_SrcHandle = NULL; ++} ++ ++void FmRegisterPcd(t_Handle h_Fm, t_Handle h_FmPcd) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ if (p_Fm->h_Pcd) ++ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("PCD already set")); ++ ++ p_Fm->h_Pcd = h_FmPcd; ++} ++ ++void FmUnregisterPcd(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ if (!p_Fm->h_Pcd) ++ REPORT_ERROR(MAJOR, E_NOT_FOUND, ("PCD handle!")); ++ ++ p_Fm->h_Pcd = NULL; ++} ++ ++t_Handle FmGetPcdHandle(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ return p_Fm->h_Pcd; ++} ++ ++uint8_t FmGetId(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0xff); ++ ++ return p_Fm->p_FmStateStruct->fmId; ++} ++ ++t_Error FmSetNumOfRiscsPerPort(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t numOfFmanCtrls, ++ t_FmFmanCtrl orFmanCtrl) ++{ ++ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t tmpReg = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((numOfFmanCtrls > 0) && (numOfFmanCtrls < 3)) , E_INVALID_HANDLE); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->p_FmFpmRegs && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcPortNumOfFmanCtrls params; ++ t_FmIpcMsg msg; ++ ++ memset(&msg, 0, sizeof(msg)); ++ params.hardwarePortId = hardwarePortId; ++ params.numOfFmanCtrls = numOfFmanCtrls; ++ params.orFmanCtrl = orFmanCtrl; ++ msg.msgId = FM_SET_NUM_OF_FMAN_CTRL; ++ memcpy(msg.msgBody, ¶ms, sizeof(params)); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) +sizeof(params), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ return E_OK; ++ } ++ else if (!p_Fm->p_FmFpmRegs) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ tmpReg = (uint32_t)(hardwarePortId << FPM_PORT_FM_CTL_PORTID_SHIFT); ++ ++ /* TODO - maybe to put CTL# according to another criteria */ ++ if (numOfFmanCtrls == 2) ++ tmpReg = FPM_PORT_FM_CTL2 | FPM_PORT_FM_CTL1; ++ ++ /* order restoration */ ++ tmpReg |= (orFmanCtrl << FPM_PRC_ORA_FM_CTL_SEL_SHIFT) | orFmanCtrl; ++ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_prc, tmpReg); ++ ++ return E_OK; ++} ++ ++t_Error FmGetSetPortParams(t_Handle h_Fm,t_FmInterModulePortInitParams *p_PortParams) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_Error err; ++ uint32_t tmpReg, intFlags; ++ uint8_t hardwarePortId = p_PortParams->hardwarePortId, macId; ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ t_FmIpcPortInInitParams portInParams; ++ t_FmIpcPortOutInitParams portOutParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ portInParams.hardwarePortId = p_PortParams->hardwarePortId; ++ portInParams.enumPortType = (uint32_t)p_PortParams->portType; ++ portInParams.boolIndependentMode= (uint8_t)p_PortParams->independentMode; ++ portInParams.liodnOffset = p_PortParams->liodnOffset; ++ portInParams.numOfTasks = p_PortParams->numOfTasks; ++ portInParams.numOfExtraTasks = p_PortParams->numOfExtraTasks; ++ portInParams.numOfOpenDmas = p_PortParams->numOfOpenDmas; ++ portInParams.numOfExtraOpenDmas = p_PortParams->numOfExtraOpenDmas; ++ portInParams.sizeOfFifo = p_PortParams->sizeOfFifo; ++ portInParams.extraSizeOfFifo = p_PortParams->extraSizeOfFifo; ++ portInParams.deqPipelineDepth = p_PortParams->deqPipelineDepth; ++ portInParams.maxFrameLength = p_PortParams->maxFrameLength; ++ portInParams.liodnBase = p_PortParams->liodnBase; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_SET_PORT_PARAMS; ++ memcpy(msg.msgBody, &portInParams, sizeof(portInParams)); ++ replyLength = (sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams)); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) +sizeof(portInParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ memcpy((uint8_t*)&portOutParams, reply.replyBody, sizeof(t_FmIpcPortOutInitParams)); ++ ++ p_PortParams->fmMuramPhysBaseAddr.high = portOutParams.ipcPhysAddr.high; ++ p_PortParams->fmMuramPhysBaseAddr.low = portOutParams.ipcPhysAddr.low; ++ p_PortParams->numOfTasks = portOutParams.numOfTasks; ++ p_PortParams->numOfExtraTasks = portOutParams.numOfExtraTasks; ++ p_PortParams->numOfOpenDmas = portOutParams.numOfOpenDmas; ++ p_PortParams->numOfExtraOpenDmas = portOutParams.numOfExtraOpenDmas; ++ p_PortParams->sizeOfFifo = portOutParams.sizeOfFifo; ++ p_PortParams->extraSizeOfFifo = portOutParams.extraSizeOfFifo; ++ ++ return (t_Error)(reply.error); ++ } ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); ++ if (p_PortParams->independentMode) ++ { ++ /* set port parameters */ ++ p_Fm->independentMode = p_PortParams->independentMode; ++ /* disable dispatch limit */ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_mxd, 0); ++ } ++ ++ if (p_PortParams->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) ++ { ++ if (p_Fm->hcPortInitialized) ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Only one host command port is allowed.")); ++ } ++ else ++ p_Fm->hcPortInitialized = TRUE; ++ } ++ p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] = p_PortParams->portType; ++ ++ err = FmSetNumOfTasks(p_Fm, p_PortParams->hardwarePortId, &p_PortParams->numOfTasks, &p_PortParams->numOfExtraTasks, TRUE); ++ if (err) ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4) ++#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ if ((p_PortParams->portType != e_FM_PORT_TYPE_RX) && ++ (p_PortParams->portType != e_FM_PORT_TYPE_RX_10G)) ++ /* for transmit & O/H ports */ ++ { ++ uint8_t enqTh; ++ uint8_t deqTh; ++ bool update = FALSE; ++ ++ /* update qmi ENQ/DEQ threshold */ ++ p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums += p_PortParams->deqPipelineDepth; ++ tmpReg = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc); ++ enqTh = (uint8_t)(tmpReg>>8); ++ /* if enqTh is too big, we reduce it to the max value that is still OK */ ++ if (enqTh >= (QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums)) ++ { ++ enqTh = (uint8_t)(QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums - 1); ++ tmpReg &= ~QMI_CFG_ENQ_MASK; ++ tmpReg |= ((uint32_t)enqTh << 8); ++ update = TRUE; ++ } ++ ++ deqTh = (uint8_t)tmpReg; ++ /* if deqTh is too small, we enlarge it to the min value that is still OK. ++ deqTh may not be larger than 63 (QMI_MAX_NUM_OF_TNUMS-1). */ ++ if ((deqTh <= p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums) && (deqTh < QMI_MAX_NUM_OF_TNUMS-1)) ++ { ++ deqTh = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums + 1); ++ tmpReg &= ~QMI_CFG_DEQ_MASK; ++ tmpReg |= (uint32_t)deqTh; ++ update = TRUE; ++ } ++ if (update) ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc, tmpReg); ++ } ++ ++#ifdef FM_LOW_END_RESTRICTION ++ if ((hardwarePortId==0x1) || (hardwarePortId==0x29)) ++ { ++ if (p_Fm->p_FmStateStruct->lowEndRestriction) ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("OP #0 cannot work with Tx Port #1.")); ++ } ++ else ++ p_Fm->p_FmStateStruct->lowEndRestriction = TRUE; ++ } ++#endif /* FM_LOW_END_RESTRICTION */ ++ ++ err = FmSetSizeOfFifo(p_Fm, ++ p_PortParams->hardwarePortId, ++ &p_PortParams->sizeOfFifo, ++ &p_PortParams->extraSizeOfFifo, ++ TRUE); ++ if (err) ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = FmSetNumOfOpenDmas(p_Fm, ++ p_PortParams->hardwarePortId, ++ &p_PortParams->numOfOpenDmas, ++ &p_PortParams->numOfExtraOpenDmas, ++ TRUE); ++ if (err) ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], (uint32_t)p_PortParams->liodnOffset); ++ ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6) ++ { ++ tmpReg = (uint32_t)(hardwarePortId << FPM_PORT_FM_CTL_PORTID_SHIFT); ++ if (p_PortParams->independentMode) ++ { ++ if ((p_PortParams->portType==e_FM_PORT_TYPE_RX) || (p_PortParams->portType==e_FM_PORT_TYPE_RX_10G)) ++ tmpReg |= (FPM_PORT_FM_CTL1 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT) |FPM_PORT_FM_CTL1; ++ else ++ tmpReg |= (FPM_PORT_FM_CTL2 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT) |FPM_PORT_FM_CTL2; ++ } ++ else ++ { ++ tmpReg |= (FPM_PORT_FM_CTL2|FPM_PORT_FM_CTL1); ++ ++ /* order restoration */ ++ if (hardwarePortId%2) ++ tmpReg |= (FPM_PORT_FM_CTL1 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT); ++ else ++ tmpReg |= (FPM_PORT_FM_CTL2 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT); ++ } ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_prc, tmpReg); ++ } ++ ++ /* set LIODN base for this port */ ++ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2]); ++ if (hardwarePortId%2) ++ { ++ tmpReg &= ~FM_LIODN_BASE_MASK; ++ tmpReg |= (uint32_t)p_PortParams->liodnBase; ++ } ++ else ++ { ++ tmpReg &= ~(FM_LIODN_BASE_MASK<< DMA_LIODN_SHIFT); ++ tmpReg |= (uint32_t)p_PortParams->liodnBase << DMA_LIODN_SHIFT; ++ } ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2], tmpReg); ++ ++ HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId); ++ ++#if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS) ++ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX_10G) || ++ (p_PortParams->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ ASSERT_COND(macId < FM_MAX_NUM_OF_10G_MACS); ++ if (p_PortParams->maxFrameLength >= p_Fm->p_FmStateStruct->macMaxFrameLengths10G[macId]) ++ p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] = p_PortParams->maxFrameLength; ++ else ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Port maxFrameLength is smaller than MAC current MTU")); ++ } ++ else ++#endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */ ++ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX) || ++ (p_PortParams->portType == e_FM_PORT_TYPE_RX)) ++ { ++ ASSERT_COND(macId < FM_MAX_NUM_OF_1G_MACS); ++ if (p_PortParams->maxFrameLength >= p_Fm->p_FmStateStruct->macMaxFrameLengths1G[macId]) ++ p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] = p_PortParams->maxFrameLength; ++ else ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Port maxFrameLength is smaller than MAC current MTU")); ++ } ++ ++ FmGetPhysicalMuramBase(p_Fm, &p_PortParams->fmMuramPhysBaseAddr); ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ ++ return E_OK; ++} ++ ++void FmFreePortParams(t_Handle h_Fm,t_FmInterModulePortFreeParams *p_PortParams) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t tmpReg, intFlags; ++ uint8_t hardwarePortId = p_PortParams->hardwarePortId; ++ uint8_t numOfTasks, macId; ++ t_Error err; ++ t_FmIpcPortFreeParams portParams; ++ t_FmIpcMsg msg; ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ portParams.hardwarePortId = p_PortParams->hardwarePortId; ++ portParams.enumPortType = (uint32_t)p_PortParams->portType; ++ portParams.deqPipelineDepth = p_PortParams->deqPipelineDepth; ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_FREE_PORT; ++ memcpy(msg.msgBody, &portParams, sizeof(portParams)); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(portParams), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return; ++ } ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); ++ ++ if (p_PortParams->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) ++ { ++ ASSERT_COND(p_Fm->hcPortInitialized); ++ p_Fm->hcPortInitialized = FALSE; ++ } ++ ++ p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] = e_FM_PORT_TYPE_DUMMY; ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]); ++ /* free numOfTasks */ ++ numOfTasks = (uint8_t)(((tmpReg & BMI_NUM_OF_TASKS_MASK) >> BMI_NUM_OF_TASKS_SHIFT) + 1); ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfTasks >= numOfTasks); ++ p_Fm->p_FmStateStruct->accumulatedNumOfTasks -= numOfTasks; ++ ++ /* free numOfOpenDmas */ ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas >= ++ ((tmpReg & BMI_NUM_OF_DMAS_MASK) >> BMI_NUM_OF_DMAS_SHIFT) + 1); ++ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas -= ++ (((tmpReg & BMI_NUM_OF_DMAS_MASK) >> BMI_NUM_OF_DMAS_SHIFT) + 1); ++ ++#ifdef FM_HAS_TOTAL_DMAS ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6) ++ { ++ /* update total num of DMA's with committed number of open DMAS, and max uncommitted pool. */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2) & ~BMI_CFG2_DMAS_MASK; ++ tmpReg |= (uint32_t)(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize - 1) << BMI_CFG2_DMAS_SHIFT; ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2, tmpReg); ++ } ++#endif /* FM_HAS_TOTAL_DMAS */ ++ ++ /* free sizeOfFifo */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1]); ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedFifoSize >= ++ (((tmpReg & BMI_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS)); ++ p_Fm->p_FmStateStruct->accumulatedFifoSize -= ++ (((tmpReg & BMI_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS); ++ ++ /* clear registers */ ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], 0); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], 0); ++ /* WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], 0); */ ++ ++#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4) ++#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ if ((p_PortParams->portType != e_FM_PORT_TYPE_RX) && ++ (p_PortParams->portType != e_FM_PORT_TYPE_RX_10G)) ++ /* for transmit & O/H ports */ ++ { ++ uint8_t enqTh; ++ uint8_t deqTh; ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc); ++ /* update qmi ENQ/DEQ threshold */ ++ p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums -= p_PortParams->deqPipelineDepth; ++ ++ /* p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums is now smaller, ++ so we can enlarge enqTh */ ++ enqTh = (uint8_t)(QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums - 1); ++ tmpReg &= ~QMI_CFG_ENQ_MASK; ++ tmpReg |= ((uint32_t)enqTh << QMI_CFG_ENQ_SHIFT); ++ ++ /* p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums is now smaller, ++ so we can reduce deqTh */ ++ deqTh = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums + 1); ++ tmpReg &= ~QMI_CFG_DEQ_MASK; ++ tmpReg |= (uint32_t)deqTh; ++ ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc, tmpReg); ++ } ++ ++ HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId); ++ ++#if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS) ++ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX_10G) || ++ (p_PortParams->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ ASSERT_COND(macId < FM_MAX_NUM_OF_10G_MACS); ++ p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] = 0; ++ } ++ else ++#endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */ ++ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX) || ++ (p_PortParams->portType == e_FM_PORT_TYPE_RX)) ++ { ++ ASSERT_COND(macId < FM_MAX_NUM_OF_1G_MACS); ++ p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] = 0; ++ } ++ ++#ifdef FM_LOW_END_RESTRICTION ++ if ((hardwarePortId==0x1) || (hardwarePortId==0x29)) ++ p_Fm->p_FmStateStruct->lowEndRestriction = FALSE; ++#endif /* FM_LOW_END_RESTRICTION */ ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++} ++ ++t_Error FmIsPortStalled(t_Handle h_Fm, uint8_t hardwarePortId, bool *p_IsStalled) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t tmpReg; ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_IS_PORT_STALLED; ++ msg.msgBody[0] = hardwarePortId; ++ replyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(hardwarePortId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ ++ *p_IsStalled = (bool)!!(*(uint8_t*)(reply.replyBody)); ++ ++ return (t_Error)(reply.error); ++ } ++ else if (!p_Fm->baseAddr) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId]); ++ *p_IsStalled = (bool)!!(tmpReg & FPM_PS_STALLED); ++ ++ return E_OK; ++} ++ ++t_Error FmResumeStalledPort(t_Handle h_Fm, uint8_t hardwarePortId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t tmpReg; ++ t_Error err; ++ bool isStalled; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_RESUME_STALLED_PORT; ++ msg.msgBody[0] = hardwarePortId; ++ replyLength = sizeof(uint32_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(hardwarePortId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++ else if (!p_Fm->baseAddr) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Not available for this FM revision!")); ++ ++ /* Get port status */ ++ err = FmIsPortStalled(h_Fm, hardwarePortId, &isStalled); ++ if (err) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't get port status")); ++ if (!isStalled) ++ return E_OK; ++ ++ tmpReg = (uint32_t)((hardwarePortId << FPM_PORT_FM_CTL_PORTID_SHIFT) | FPM_PRC_REALSE_STALLED); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_prc, tmpReg); ++ ++ return E_OK; ++} ++ ++t_Error FmResetMac(t_Handle h_Fm, e_FmMacType type, uint8_t macId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t bitMask; ++ ++#ifndef FM_MAC_RESET ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ return E_OK; ++#endif /*(FM_MAC_RESET >= 11)*/ ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcMacParams macParams; ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ macParams.id = macId; ++ macParams.enumType = (uint32_t)type; ++ msg.msgId = FM_RESET_MAC; ++ memcpy(msg.msgBody, &macParams, sizeof(macParams)); ++ replyLength = sizeof(uint32_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(macParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++ else if (!p_Fm->baseAddr) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ /* Get the relevant bit mask */ ++ if (type == e_FM_MAC_10G) ++ { ++ switch (macId) ++ { ++ case (0): ++ bitMask = FPM_RSTC_10G0_RESET; ++ break; ++ case (1): ++ bitMask = FPM_RSTC_10G1_RESET; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Illegal MAC Id")); ++ } ++ } ++ else ++ { ++ switch (macId) ++ { ++ case (0): ++ bitMask = FPM_RSTC_1G0_RESET; ++ break; ++ case (1): ++ bitMask = FPM_RSTC_1G1_RESET; ++ break; ++ case (2): ++ bitMask = FPM_RSTC_1G2_RESET; ++ break; ++ case (3): ++ bitMask = FPM_RSTC_1G3_RESET; ++ break; ++ case (4): ++ bitMask = FPM_RSTC_1G4_RESET; ++ break; ++ case (5): ++ bitMask = FPM_RSTC_1G5_RESET; ++ break; ++ case (6): ++ bitMask = FPM_RSTC_1G6_RESET; ++ break; ++ case (7): ++ bitMask = FPM_RSTC_1G7_RESET; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Illegal MAC Id")); ++ } ++ } ++ ++ /* reset */ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, bitMask); ++ ++ return E_OK; ++} ++ ++t_Error FmSetMacMaxFrame(t_Handle h_Fm, e_FmMacType type, uint8_t macId, uint16_t mtu) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcMacMaxFrameParams macMaxFrameLengthParams; ++ t_Error err; ++ t_FmIpcMsg msg; ++ ++ memset(&msg, 0, sizeof(msg)); ++ macMaxFrameLengthParams.macParams.id = macId; ++ macMaxFrameLengthParams.macParams.enumType = (uint32_t)type; ++ macMaxFrameLengthParams.maxFrameLength = (uint16_t)mtu; ++ msg.msgId = FM_SET_MAC_MAX_FRAME; ++ memcpy(msg.msgBody, &macMaxFrameLengthParams, sizeof(macMaxFrameLengthParams)); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(macMaxFrameLengthParams), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ return E_OK; ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ /* if port is already initialized, check that MaxFrameLength is smaller ++ * or equal to the port's max */ ++#if (defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS)) ++ if (type == e_FM_MAC_10G) ++ { ++ if ((!p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId]) ++ || (p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] && ++ (mtu <= p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId]))) ++ p_Fm->p_FmStateStruct->macMaxFrameLengths10G[macId] = mtu; ++ else ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("MAC maxFrameLength is larger than Port maxFrameLength")); ++ ++ } ++ else ++#else ++ UNUSED(type); ++#endif /* (defined(FM_MAX_NUM_OF_10G_MACS) && ... */ ++ if ((!p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId]) ++ || (p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] && ++ (mtu <= p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId]))) ++ p_Fm->p_FmStateStruct->macMaxFrameLengths1G[macId] = mtu; ++ else ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("MAC maxFrameLength is larger than Port maxFrameLength")); ++ ++ return E_OK; ++} ++ ++uint16_t FmGetClockFreq(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ /* for multicore environment: this depends on the ++ * fact that fmClkFreq was properly initialized at "init". */ ++ return p_Fm->p_FmStateStruct->fmClkFreq; ++} ++ ++uint32_t FmGetTimeStampScale(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength, timeStamp; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_TIMESTAMP_SCALE; ++ replyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ ++ memcpy((uint8_t*)&timeStamp, reply.replyBody, sizeof(uint32_t)); ++ return timeStamp; ++ } ++ else if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->baseAddr) ++ { ++ if (!(GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_tsc1) & FPM_TS_CTL_EN)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("timestamp is not enabled!")); ++ ++ return p_Fm->p_FmStateStruct->count1MicroBit; ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ DBG(WARNING, ("No IPC - can't validate FM if timestamp enabled.")); ++ ++ return p_Fm->p_FmStateStruct->count1MicroBit; ++} ++ ++t_Error FmEnableRamsEcc(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ p_Fm->p_FmStateStruct->ramsEccOwners++; ++ p_Fm->p_FmStateStruct->internalCall = TRUE; ++ ++ return FM_EnableRamsEcc(p_Fm); ++} ++ ++t_Error FmDisableRamsEcc(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ ASSERT_COND(p_Fm->p_FmStateStruct->ramsEccOwners); ++ p_Fm->p_FmStateStruct->ramsEccOwners--; ++ ++ if (p_Fm->p_FmStateStruct->ramsEccOwners==0) ++ { ++ p_Fm->p_FmStateStruct->internalCall = TRUE; ++ return FM_DisableRamsEcc(p_Fm); ++ } ++ ++ return E_OK; ++} ++ ++uint8_t FmGetGuestId(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ return p_Fm->guestId; ++} ++ ++bool FmIsMaster(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ return (p_Fm->guestId == NCSW_MASTER_ID); ++} ++ ++#ifdef FM_NO_GUARANTEED_RESET_VALUES ++t_Error FmSetSizeOfFifo(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint32_t *p_SizeOfFifo, ++ uint32_t *p_ExtraSizeOfFifo, ++ bool initialConfig) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_FmIpcPortRsrcParams rsrcParams; ++ t_Error err; ++ uint32_t tmpReg = 0, sizeOfFifo = *p_SizeOfFifo, extraSizeOfFifo = *p_ExtraSizeOfFifo; ++ uint16_t oldVal = 0; ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ rsrcParams.hardwarePortId = hardwarePortId; ++ rsrcParams.val = sizeOfFifo; ++ rsrcParams.extra = extraSizeOfFifo; ++ rsrcParams.boolInitialConfig = (uint8_t)initialConfig; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_SET_SIZE_OF_FIFO; ++ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams)); ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(rsrcParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++ else if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->baseAddr) ++ { ++ DBG(WARNING, ("No IPC - can't validate FM total-fifo size.")); ++ ++ tmpReg = (uint32_t)((sizeOfFifo/BMI_FIFO_UNITS - 1) | ++ ((extraSizeOfFifo/BMI_FIFO_UNITS) << BMI_EXTRA_FIFO_SIZE_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], tmpReg); ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++ ++ if (!initialConfig) ++ { ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1]); ++ /* read into oldVal the current extra fifo size */ ++ oldVal = (uint16_t)((((tmpReg & BMI_EXTRA_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS) >> BMI_EXTRA_FIFO_SIZE_SHIFT); ++ } ++ ++ if (extraSizeOfFifo > oldVal) ++ { ++ if (extraSizeOfFifo && !p_Fm->p_FmStateStruct->extraFifoPoolSize) ++ /* if this is the first time a port requires extraFifoPoolSize, the total extraFifoPoolSize ++ * must be initialized to 1 buffer per port ++ */ ++ p_Fm->p_FmStateStruct->extraFifoPoolSize = FM_MAX_NUM_OF_RX_PORTS*BMI_FIFO_UNITS; ++ ++ p_Fm->p_FmStateStruct->extraFifoPoolSize = MAX(p_Fm->p_FmStateStruct->extraFifoPoolSize, extraSizeOfFifo); ++ } ++ ++ if (!initialConfig) ++ /* read into oldVal the current num of tasks */ ++ oldVal = (uint16_t)(((tmpReg & BMI_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS); ++ ++ /* check that there are enough uncommitted fifo size */ ++ if ((p_Fm->p_FmStateStruct->accumulatedFifoSize - oldVal + sizeOfFifo) > ++ (p_Fm->p_FmStateStruct->totalFifoSize - p_Fm->p_FmStateStruct->extraFifoPoolSize)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Requested fifo size and extra size exceed total FIFO size.")); ++ else ++ { ++ /* update accumulated */ ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedFifoSize >= oldVal); ++ p_Fm->p_FmStateStruct->accumulatedFifoSize -= oldVal; ++ p_Fm->p_FmStateStruct->accumulatedFifoSize += sizeOfFifo; ++ /* calculate reg */ ++ tmpReg = (uint32_t)((sizeOfFifo/BMI_FIFO_UNITS - 1) | ++ ((extraSizeOfFifo/BMI_FIFO_UNITS) << BMI_EXTRA_FIFO_SIZE_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], tmpReg); ++ } ++ ++ return E_OK; ++} ++ ++#else /*FM_NO_GUARANTEED_RESET_VALUES*/ ++t_Error FmSetSizeOfFifo(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint32_t *p_SizeOfFifo, ++ uint32_t *p_ExtraSizeOfFifo, ++ bool initialConfig) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_FmIpcPortRsrcParams rsrcParams; ++ t_Error err; ++ uint32_t tmpReg = 0, sizeOfFifo = *p_SizeOfFifo, extraSizeOfFifo = *p_ExtraSizeOfFifo; ++ uint16_t currentVal, currentExtraVal; ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ /* it's illegal to be in a state where this is not the first set and no value is specified */ ++ ASSERT_COND(initialConfig || sizeOfFifo); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ rsrcParams.hardwarePortId = hardwarePortId; ++ rsrcParams.val = sizeOfFifo; ++ rsrcParams.extra = extraSizeOfFifo; ++ rsrcParams.boolInitialConfig = (uint8_t)initialConfig; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_SET_SIZE_OF_FIFO; ++ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams)); ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(rsrcParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++ else if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->baseAddr) ++ { ++ DBG(WARNING, ("No IPC - can't validate FM total-fifo size.")); ++ ++ if (sizeOfFifo) ++ { ++ /* whether it is the first time with explicit value, or runtime "set" - write register */ ++ tmpReg = (uint32_t)((sizeOfFifo/BMI_FIFO_UNITS - 1) | ++ ((extraSizeOfFifo/BMI_FIFO_UNITS) << BMI_EXTRA_FIFO_SIZE_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], tmpReg); ++ } ++ else /* first config without explicit value: Do Nothing - reset value shouldn't be ++ changed, read register for port save */ ++ { ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1]); ++ /* read into oldVal the current extra fifo size */ ++ *p_ExtraSizeOfFifo = (uint16_t)((((tmpReg & BMI_EXTRA_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS) >> BMI_EXTRA_FIFO_SIZE_SHIFT); ++ *p_SizeOfFifo = (uint16_t)(((tmpReg & BMI_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS); ++ } ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++ ++ if (!initialConfig || !sizeOfFifo) ++ { ++ /* !initialConfig - runtime change of existing value. ++ * !numOfTasks - first configuration according to values in regs. ++ * In both cases: read the current FIFO size */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1]); ++ /* read into oldVal the current extra fifo size */ ++ currentExtraVal = (uint16_t)((((tmpReg & BMI_EXTRA_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS) >> BMI_EXTRA_FIFO_SIZE_SHIFT); ++ currentVal = (uint16_t)(((tmpReg & BMI_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS); ++ } ++ else /* first time and sizeOfFifo explicitly specified */ ++ currentVal = currentExtraVal = 0; ++ ++ if (!sizeOfFifo) ++ { ++ /* This is the first configuration and user did not specify value (!numOfTasks), ++ * reset values will be used and we just save these values for resource management */ ++ if (currentExtraVal) ++ { ++ if (!p_Fm->p_FmStateStruct->extraFifoPoolSize) ++ /* if this is the first time a port requires extraFifoPoolSize, the total extraFifoPoolSize ++ * must be initialized to 1 buffer per port ++ */ ++ p_Fm->p_FmStateStruct->extraFifoPoolSize = FM_MAX_NUM_OF_RX_PORTS*BMI_FIFO_UNITS; ++ ++ p_Fm->p_FmStateStruct->extraFifoPoolSize = MAX(p_Fm->p_FmStateStruct->extraFifoPoolSize, extraSizeOfFifo); ++ } ++ if ((p_Fm->p_FmStateStruct->accumulatedFifoSize + currentVal) > ++ (p_Fm->p_FmStateStruct->totalFifoSize - p_Fm->p_FmStateStruct->extraFifoPoolSize)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Total port's fifo size and extra size exceed total available FIFO size.")); ++ ++ p_Fm->p_FmStateStruct->accumulatedFifoSize += currentVal; ++ ++ *p_SizeOfFifo = currentVal; ++ *p_ExtraSizeOfFifo = currentExtraVal; ++ ++ } ++ else ++ { ++ /* user requires a specific value. ++ * If this is the first configuration call, (numOfTasks != 0) currentVal & currentExtraVal are set to "0", ++ * otherwise they hold the value written in the register. ++ */ ++ if (extraSizeOfFifo > currentExtraVal) ++ { ++ if (extraSizeOfFifo && !p_Fm->p_FmStateStruct->extraFifoPoolSize) ++ /* if this is the first time a port requires extraFifoPoolSize, the total extraFifoPoolSize ++ * must be initialized to 1 buffer per port ++ */ ++ p_Fm->p_FmStateStruct->extraFifoPoolSize = FM_MAX_NUM_OF_RX_PORTS*BMI_FIFO_UNITS; ++ ++ p_Fm->p_FmStateStruct->extraFifoPoolSize = MAX(p_Fm->p_FmStateStruct->extraFifoPoolSize, extraSizeOfFifo); ++ } ++ ++ /* check that there are enough uncommitted fifo size */ ++ if ((p_Fm->p_FmStateStruct->accumulatedFifoSize - currentVal + sizeOfFifo) > ++ (p_Fm->p_FmStateStruct->totalFifoSize - p_Fm->p_FmStateStruct->extraFifoPoolSize)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Requested fifo size and extra size exceed total FIFO size.")); ++ else ++ { ++ /* update accumulated */ ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedFifoSize >= currentVal); ++ p_Fm->p_FmStateStruct->accumulatedFifoSize -= currentVal; ++ p_Fm->p_FmStateStruct->accumulatedFifoSize += sizeOfFifo; ++ /* calculate reg */ ++ tmpReg = (uint32_t)((sizeOfFifo/BMI_FIFO_UNITS - 1) | ++ ((extraSizeOfFifo/BMI_FIFO_UNITS) << BMI_EXTRA_FIFO_SIZE_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], tmpReg); ++ } ++ *p_SizeOfFifo = sizeOfFifo; ++ *p_ExtraSizeOfFifo = extraSizeOfFifo; ++ ++ } ++ ++ return E_OK; ++} ++#endif /* FM_NO_GUARANTEED_RESET_VALUES */ ++ ++#ifdef FM_NO_GUARANTEED_RESET_VALUES ++t_Error FmSetNumOfTasks(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t *p_NumOfTasks, ++ uint8_t *p_NumOfExtraTasks, ++ bool initialConfig) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ t_Error err; ++ uint32_t tmpReg = 0; ++ uint8_t oldVal = 0, numOfTasks = *p_NumOfTasks, numOfExtraTasks = *p_NumOfExtraTasks; ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcPortRsrcParams rsrcParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ rsrcParams.hardwarePortId = hardwarePortId; ++ rsrcParams.val = numOfTasks; ++ rsrcParams.extra = numOfExtraTasks; ++ rsrcParams.boolInitialConfig = (uint8_t)initialConfig; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_SET_NUM_OF_TASKS; ++ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams)); ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(rsrcParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++ else if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->baseAddr) ++ { ++ DBG(WARNING, ("No IPC - can't validate FM total-num-of-tasks.")); ++ ++ /* calculate reg */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK); ++ tmpReg |= (uint32_t)(((numOfTasks-1) << BMI_NUM_OF_TASKS_SHIFT) | ++ (numOfExtraTasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1],tmpReg); ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++ ++ if (!initialConfig) ++ { ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]); ++ /* read into oldVal the current extra tasks */ ++ oldVal = (uint8_t)((tmpReg & BMI_NUM_OF_EXTRA_TASKS_MASK) >> BMI_EXTRA_NUM_OF_TASKS_SHIFT); ++ } ++ ++ if (numOfExtraTasks > oldVal) ++ p_Fm->p_FmStateStruct->extraTasksPoolSize = ++ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraTasksPoolSize, numOfExtraTasks); ++ ++ if (!initialConfig) ++ /* read into oldVal the current num of tasks */ ++ oldVal = (uint8_t)(((tmpReg & BMI_NUM_OF_TASKS_MASK) >> BMI_NUM_OF_TASKS_SHIFT) + 1); ++ ++ /* check that there are enough uncommitted tasks */ ++ if ((p_Fm->p_FmStateStruct->accumulatedNumOfTasks - oldVal + numOfTasks) > ++ (p_Fm->p_FmStateStruct->totalNumOfTasks - p_Fm->p_FmStateStruct->extraTasksPoolSize)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ++ ("Requested numOfTasks and extra tasks pool for fm%d exceed total numOfTasks.", ++ p_Fm->p_FmStateStruct->fmId)); ++ else ++ { ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfTasks >= oldVal); ++ /* update accumulated */ ++ p_Fm->p_FmStateStruct->accumulatedNumOfTasks -= oldVal; ++ p_Fm->p_FmStateStruct->accumulatedNumOfTasks += numOfTasks; ++ /* calculate reg */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK); ++ tmpReg |= (uint32_t)(((numOfTasks-1) << BMI_NUM_OF_TASKS_SHIFT) | ++ (numOfExtraTasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1],tmpReg); ++ } ++ ++ return E_OK; ++} ++ ++#else /*FM_NO_GUARANTEED_RESET_VALUES*/ ++t_Error FmSetNumOfTasks(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t *p_NumOfTasks, ++ uint8_t *p_NumOfExtraTasks, ++ bool initialConfig) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ t_Error err; ++ uint32_t tmpReg = 0; ++ uint8_t currentVal, currentExtraVal,numOfTasks = *p_NumOfTasks, numOfExtraTasks = *p_NumOfExtraTasks; ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ /* it's illegal to be in a state where this is not the first set and no value is specified */ ++ ASSERT_COND(initialConfig || numOfTasks); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcPortRsrcParams rsrcParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ rsrcParams.hardwarePortId = hardwarePortId; ++ rsrcParams.val = numOfTasks; ++ rsrcParams.extra = numOfExtraTasks; ++ rsrcParams.boolInitialConfig = (uint8_t)initialConfig; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_SET_NUM_OF_TASKS; ++ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams)); ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(rsrcParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++ else if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->baseAddr) ++ { ++ DBG(WARNING, ("No Ipc - can't validate FM total-num-of-tasks.")); ++ ++ if (numOfTasks) ++ { ++ /* whether it is the first time with explicit value, or runtime "set" - write register */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK); ++ tmpReg |= (uint32_t)(((numOfTasks-1) << BMI_NUM_OF_TASKS_SHIFT) | ++ (numOfExtraTasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1],tmpReg); ++ } ++ else /* first config without explicit value: Do Nothing - reset value shouldn't be ++ changed, read register for port save */ ++ { ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]); ++ *p_NumOfTasks = (uint8_t)(((tmpReg & BMI_NUM_OF_TASKS_MASK) >> BMI_NUM_OF_TASKS_SHIFT) + 1); ++ *p_NumOfExtraTasks = (uint8_t)((tmpReg & BMI_NUM_OF_EXTRA_TASKS_MASK) >> BMI_EXTRA_NUM_OF_TASKS_SHIFT); ++ } ++ ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++ ++ if (!initialConfig || !numOfTasks) ++ { ++ /* !initialConfig - runtime change of existing value. ++ * !numOfTasks - first configuration according to values in regs. ++ * In both cases: read the current number of tasks */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]); ++ currentVal = (uint8_t)(((tmpReg & BMI_NUM_OF_TASKS_MASK) >> BMI_NUM_OF_TASKS_SHIFT) + 1); ++ currentExtraVal = (uint8_t)((tmpReg & BMI_NUM_OF_EXTRA_TASKS_MASK) >> BMI_EXTRA_NUM_OF_TASKS_SHIFT); ++ } ++ else /* first time and numOfTasks explicitly specified */ ++ currentVal = currentExtraVal = 0; ++ ++ if (!numOfTasks) ++ { ++ /* This is the first configuration and user did not specify value (!numOfTasks), ++ * reset values will be used and we just save these values for resource management */ ++ p_Fm->p_FmStateStruct->extraTasksPoolSize = ++ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraTasksPoolSize, currentExtraVal); ++ if ((p_Fm->p_FmStateStruct->accumulatedNumOfTasks + currentVal) > ++ (p_Fm->p_FmStateStruct->totalNumOfTasks - p_Fm->p_FmStateStruct->extraTasksPoolSize)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ++ ("Total ports' numOfTasks and extra tasks pool for fm%d exceed total available numOfTasks.", ++ p_Fm->p_FmStateStruct->fmId)); ++ p_Fm->p_FmStateStruct->accumulatedNumOfTasks += currentVal; ++ *p_NumOfTasks = currentVal; ++ *p_NumOfExtraTasks = currentExtraVal; ++ } ++ else ++ { ++ /* user requires a specific value. ++ * If this is the first configuration call, (numOfTasks != 0) currentVal & currentExtraVal are set to "0", ++ * otherwise they hold the value written in the register. ++ */ ++ if (numOfExtraTasks > currentExtraVal) ++ p_Fm->p_FmStateStruct->extraTasksPoolSize = ++ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraTasksPoolSize, numOfExtraTasks); ++ ++ /* check that there are enough uncommitted tasks */ ++ if ((p_Fm->p_FmStateStruct->accumulatedNumOfTasks - currentVal + numOfTasks) > ++ (p_Fm->p_FmStateStruct->totalNumOfTasks - p_Fm->p_FmStateStruct->extraTasksPoolSize)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ++ ("Requested numOfTasks and extra tasks pool for fm%d exceed total numOfTasks.", ++ p_Fm->p_FmStateStruct->fmId)); ++ else ++ { ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfTasks >= currentVal); ++ /* update acummulated */ ++ p_Fm->p_FmStateStruct->accumulatedNumOfTasks -= currentVal; ++ p_Fm->p_FmStateStruct->accumulatedNumOfTasks += numOfTasks; ++ /* calculate reg */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK); ++ tmpReg |= (uint32_t)(((numOfTasks-1) << BMI_NUM_OF_TASKS_SHIFT) | ++ (numOfExtraTasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1],tmpReg); ++ } ++ *p_NumOfTasks = numOfTasks; ++ *p_NumOfExtraTasks = numOfExtraTasks; ++ } ++ ++ return E_OK; ++} ++#endif /* FM_NO_GUARANTEED_RESET_VALUES */ ++ ++#ifdef FM_NO_GUARANTEED_RESET_VALUES ++t_Error FmSetNumOfOpenDmas(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t *p_NumOfOpenDmas, ++ uint8_t *p_NumOfExtraOpenDmas, ++ bool initialConfig) ++ ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ uint8_t oldVal = 0, numOfOpenDmas = *p_NumOfOpenDmas, numOfExtraOpenDmas = *p_NumOfExtraOpenDmas; ++ uint32_t tmpReg = 0; ++ t_Error err; ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcPortRsrcParams rsrcParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ rsrcParams.hardwarePortId = hardwarePortId; ++ rsrcParams.val = numOfOpenDmas; ++ rsrcParams.extra = numOfExtraOpenDmas; ++ rsrcParams.boolInitialConfig = (uint8_t)initialConfig; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_SET_NUM_OF_OPEN_DMAS; ++ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams)); ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(rsrcParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++#ifdef FM_HAS_TOTAL_DMAS ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++#else ++ else if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->baseAddr && ++ (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)) ++ { ++ /*DBG(WARNING, ("No IPC - can't validate FM total-num-of-dmas."));*/ ++ ++ /* calculate reg */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK); ++ tmpReg |= (uint32_t)(((numOfOpenDmas-1) << BMI_NUM_OF_DMAS_SHIFT) | ++ (numOfExtraOpenDmas << BMI_EXTRA_NUM_OF_DMAS_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], tmpReg); ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++#endif /* FM_HAS_TOTAL_DMAS */ ++ ++ if (!initialConfig) ++ { ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]); ++ /* read into oldVal the current extra tasks */ ++ oldVal = (uint8_t)((tmpReg & BMI_NUM_OF_EXTRA_DMAS_MASK) >> BMI_EXTRA_NUM_OF_DMAS_SHIFT); ++ } ++ ++ if (numOfExtraOpenDmas > oldVal) ++ p_Fm->p_FmStateStruct->extraOpenDmasPoolSize = ++ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraOpenDmasPoolSize, numOfExtraOpenDmas); ++ ++ if (!initialConfig) ++ /* read into oldVal the current num of tasks */ ++ oldVal = (uint8_t)(((tmpReg & BMI_NUM_OF_DMAS_MASK) >> BMI_NUM_OF_DMAS_SHIFT) + 1); ++ ++ /* check that there are enough uncommitted open DMA's */ ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas >= oldVal); ++#ifdef FM_HAS_TOTAL_DMAS ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev < 6) && ++ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - oldVal + numOfOpenDmas > ++ p_Fm->p_FmStateStruct->maxNumOfOpenDmas)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ++ ("Requested numOfOpenDmas for fm%d exceeds total numOfOpenDmas.", ++ p_Fm->p_FmStateStruct->fmId)); ++#else ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) && ++ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - oldVal + numOfOpenDmas > DMA_THRESH_MAX_COMMQ + 1)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ++ ("Requested numOfOpenDmas for fm%d exceeds DMA Command queue (%d)", ++ p_Fm->p_FmStateStruct->fmId, DMA_THRESH_MAX_COMMQ+1)); ++#endif /* FM_HAS_TOTAL_DMAS */ ++ else ++ { ++ /* update acummulated */ ++ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas -= oldVal; ++ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas += numOfOpenDmas; ++ ++ /* calculate reg */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK); ++ tmpReg |= (uint32_t)(((numOfOpenDmas-1) << BMI_NUM_OF_DMAS_SHIFT) | ++ (numOfExtraOpenDmas << BMI_EXTRA_NUM_OF_DMAS_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], tmpReg); ++ ++#ifdef FM_HAS_TOTAL_DMAS ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6) ++ { ++ /* update total num of DMA's with committed number of open DMAS, and max uncommitted pool. */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2) & ~BMI_CFG2_DMAS_MASK; ++ tmpReg |= (uint32_t)(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize - 1) << BMI_CFG2_DMAS_SHIFT; ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2, tmpReg); ++ } ++#endif /* FM_HAS_TOTAL_DMAS */ ++ } ++ ++ ++ return E_OK; ++} ++ ++#else /* FM_NO_GUARANTEED_RESET_VALUES */ ++t_Error FmSetNumOfOpenDmas(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t *p_NumOfOpenDmas, ++ uint8_t *p_NumOfExtraOpenDmas, ++ bool initialConfig) ++ ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ uint32_t tmpReg = 0; ++ t_Error err; ++ uint8_t currentVal, currentExtraVal, numOfOpenDmas = *p_NumOfOpenDmas, numOfExtraOpenDmas = *p_NumOfExtraOpenDmas; ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcPortRsrcParams rsrcParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ rsrcParams.hardwarePortId = hardwarePortId; ++ rsrcParams.val = numOfOpenDmas; ++ rsrcParams.extra = numOfExtraOpenDmas; ++ rsrcParams.boolInitialConfig = (uint8_t)initialConfig; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_SET_NUM_OF_OPEN_DMAS; ++ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams)); ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(rsrcParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++#ifdef FM_HAS_TOTAL_DMAS ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++#else ++ else if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->baseAddr && ++ (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)) ++ { ++ /*DBG(WARNING, ("No IPC - can't validate FM total-num-of-dmas."));*/ ++ ++ if (numOfOpenDmas) ++ { ++ /* whether it is the first time with explicit value, or runtime "set" - write register */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK); ++ tmpReg |= (uint32_t)(((numOfOpenDmas-1) << BMI_NUM_OF_DMAS_SHIFT) | ++ (numOfExtraOpenDmas << BMI_EXTRA_NUM_OF_DMAS_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], tmpReg); ++ } ++ else /* first config without explicit value: Do Nothing - reset value shouldn't be ++ changed, read register for port save */ ++ { ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]); ++ /* read into oldVal the current extra tasks */ ++ *p_NumOfOpenDmas = (uint8_t)((tmpReg & BMI_NUM_OF_EXTRA_DMAS_MASK) >> BMI_EXTRA_NUM_OF_DMAS_SHIFT); ++ *p_NumOfExtraOpenDmas = (uint8_t)(((tmpReg & BMI_NUM_OF_DMAS_MASK) >> BMI_NUM_OF_DMAS_SHIFT) + 1); ++ } ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++#endif /* FM_HAS_TOTAL_DMAS */ ++ ++ /* it's illegal to be in a state where this is not the first set and no value is specified */ ++ ASSERT_COND(initialConfig || numOfOpenDmas); ++ ++ if (!initialConfig || !numOfOpenDmas) ++ { ++ /* !initialConfig - runtime change of existing value. ++ * !numOfTasks - first configuration according to values in regs. ++ * In both cases: read the current number of open Dma's */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]); ++ /* read into oldVal the current extra tasks */ ++ currentExtraVal = (uint8_t)((tmpReg & BMI_NUM_OF_EXTRA_DMAS_MASK) >> BMI_EXTRA_NUM_OF_DMAS_SHIFT); ++ currentVal = (uint8_t)(((tmpReg & BMI_NUM_OF_DMAS_MASK) >> BMI_NUM_OF_DMAS_SHIFT) + 1); ++ } ++ else /* first time and numOfTasks explicitly specified */ ++ currentVal = currentExtraVal = 0; ++ ++ if (!numOfOpenDmas) ++ { ++ /* This is the first configuration and user did not specify value (!numOfOpenDmas), ++ * reset values will be used and we just save these values for resource management */ ++ p_Fm->p_FmStateStruct->extraOpenDmasPoolSize = ++ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraOpenDmasPoolSize, currentExtraVal); ++ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas += currentVal; ++ *p_NumOfOpenDmas = currentVal; ++ *p_NumOfExtraOpenDmas = currentExtraVal; ++ } ++ else ++ { ++ /* user requires a specific value. ++ * If this is the first configuration call, (numOfTasks != 0) currentVal & currentExtraVal are set to "0", ++ * otherwise they hold the value written in the register. ++ */ ++ if (numOfExtraOpenDmas > currentExtraVal) ++ p_Fm->p_FmStateStruct->extraOpenDmasPoolSize = ++ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraOpenDmasPoolSize, numOfExtraOpenDmas); ++ ++ ++ /* read into oldVal the current num of tasks */ ++#ifdef FM_HAS_TOTAL_DMAS ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev < 6) && ++ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - currentVal + numOfOpenDmas > ++ p_Fm->p_FmStateStruct->maxNumOfOpenDmas)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ++ ("Requested numOfOpenDmas for fm%d exceeds total numOfOpenDmas.", ++ p_Fm->p_FmStateStruct->fmId)); ++#else ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) && ++ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - currentVal + numOfOpenDmas > DMA_THRESH_MAX_COMMQ + 1)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ++ ("Requested numOfOpenDmas for fm%d exceeds DMA Command queue (%d)", ++ p_Fm->p_FmStateStruct->fmId, DMA_THRESH_MAX_COMMQ+1)); ++#endif /* FM_HAS_TOTAL_DMAS */ ++ else ++ { ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas >= currentVal); ++ /* update acummulated */ ++ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas -= currentVal; ++ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas += numOfOpenDmas; ++ ++ /* calculate reg */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK); ++ tmpReg |= (uint32_t)(((numOfOpenDmas-1) << BMI_NUM_OF_DMAS_SHIFT) | ++ (numOfExtraOpenDmas << BMI_EXTRA_NUM_OF_DMAS_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], tmpReg); ++#ifdef FM_HAS_TOTAL_DMAS ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6) ++ { ++ /* update total num of DMA's with committed number of open DMAS, and max uncommitted pool. */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2) & ~BMI_CFG2_DMAS_MASK; ++ tmpReg |= (uint32_t)(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize - 1) << BMI_CFG2_DMAS_SHIFT; ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2, tmpReg); ++ } ++#endif /* FM_HAS_TOTAL_DMAS */ ++ ++ } ++ *p_NumOfOpenDmas = numOfOpenDmas; ++ *p_NumOfExtraOpenDmas = numOfExtraOpenDmas; ++ } ++ ++ ++ return E_OK; ++} ++#endif /* FM_NO_GUARANTEED_RESET_VALUES */ ++ ++#if (DPAA_VERSION >= 11) ++t_Error FmVSPCheckRelativeProfile(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint16_t relativeProfile) ++{ ++ t_Fm *p_Fm; ++ t_FmSp *p_FmPcdSp; ++ uint8_t swPortIndex=0, hardwarePortId; ++ ++ ASSERT_COND(h_Fm); ++ p_Fm = (t_Fm*)h_Fm; ++ ++ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, portType, portId) ++ ASSERT_COND(hardwarePortId); ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ p_FmPcdSp = p_Fm->p_FmSp; ++ ASSERT_COND(p_FmPcdSp); ++ ++ if (!p_FmPcdSp->portsMapping[swPortIndex].numOfProfiles) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE , ("Port has no allocated profiles")); ++ if (relativeProfile >= p_FmPcdSp->portsMapping[swPortIndex].numOfProfiles) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE , ("Profile id is out of range")); ++ ++ return E_OK; ++} ++ ++t_Error FmVSPGetAbsoluteProfileId(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint16_t relativeProfile, ++ uint16_t *p_AbsoluteId) ++{ ++ t_Fm *p_Fm; ++ t_FmSp *p_FmPcdSp; ++ uint8_t swPortIndex=0, hardwarePortId; ++ t_Error err; ++ ++ ASSERT_COND(h_Fm); ++ p_Fm = (t_Fm*)h_Fm; ++ ++ err = FmVSPCheckRelativeProfile(h_Fm, portType, portId, relativeProfile); ++ if (err != E_OK) ++ return err; ++ ++ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, portType, portId) ++ ASSERT_COND(hardwarePortId); ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ p_FmPcdSp = p_Fm->p_FmSp; ++ ASSERT_COND(p_FmPcdSp); ++ ++ *p_AbsoluteId = (uint16_t)(p_FmPcdSp->portsMapping[swPortIndex].profilesBase + relativeProfile); ++ ++ return E_OK; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++static t_Error InitFmDma(t_Fm *p_Fm) ++{ ++ t_FmDriverParam *p_FmDriverParam = NULL; ++ uint32_t tmpReg; ++ ++ ASSERT_COND(p_Fm); ++ ASSERT_COND(p_Fm->p_FmDriverParam); ++ ++ p_FmDriverParam = p_Fm->p_FmDriverParam; ++ ++ /* clear status reg events */ ++#if (DPAA_VERSION >= 11) ++ tmpReg = DMA_STATUS_FM_SPDAT_ECC; ++#else ++ tmpReg = DMA_STATUS_FM_ECC; ++#endif /* DPAA_VERSION >= 11 */ ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmsr, GET_UINT32(p_Fm->p_FmDmaRegs->fmdmsr) | tmpReg); ++ ++ /* configure mode register */ ++ tmpReg = 0; ++ tmpReg |= p_FmDriverParam->dmaCacheOverride << DMA_MODE_CACHE_OR_SHIFT; ++ if (p_FmDriverParam->dmaAidOverride) ++ tmpReg |= DMA_MODE_AID_OR; ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_DMA_BUS_ERROR) ++ tmpReg |= DMA_MODE_BER; ++ if (p_FmDriverParam->dmaEnEmergency) ++ { ++ tmpReg |= p_FmDriverParam->dmaEmergency.emergencyBusSelect; ++ tmpReg |= p_FmDriverParam->dmaEmergency.emergencyLevel << DMA_MODE_EMERGENCY_LEVEL_SHIFT; ++ if (p_FmDriverParam->dmaEnEmergencySmoother) ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmemsr, p_FmDriverParam->dmaEmergencySwitchCounter); ++ } ++ tmpReg |= ((p_FmDriverParam->dmaCamNumOfEntries/DMA_CAM_UNITS) - 1) << DMA_MODE_CEN_SHIFT; ++ tmpReg |= p_FmDriverParam->dmaDbgCntMode << DMA_MODE_DBG_SHIFT; ++ tmpReg |= DMA_MODE_SECURE_PROT; ++ tmpReg |= p_FmDriverParam->dmaAidMode << DMA_MODE_AID_MODE_SHIFT; ++ ++#if (DPAA_VERSION >= 11) ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_DMA_SINGLE_PORT_ECC) ++ tmpReg |= DMA_MODE_ECC; ++#else ++ if ((p_Fm->p_FmStateStruct->exceptions & FM_EX_DMA_SYSTEM_WRITE_ECC) | (p_Fm->p_FmStateStruct->exceptions & FM_EX_DMA_READ_ECC) | (p_Fm->p_FmStateStruct->exceptions & FM_EX_DMA_FM_WRITE_ECC)) ++ tmpReg |= DMA_MODE_ECC; ++ if (p_FmDriverParam->dmaStopOnBusError) ++ tmpReg |= DMA_MODE_SBER; ++ tmpReg |= (uint32_t)(p_FmDriverParam->dmaAxiDbgNumOfBeats - 1) << DMA_MODE_AXI_DBG_SHIFT; ++#ifdef FM_PEDANTIC_DMA ++ tmpReg |= DMA_MODE_EMERGENCY_READ; ++#endif /* FM_PEDANTIC_DMA */ ++#endif /* DPAA_VERSION >= 11 */ ++ ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmmr, tmpReg); ++ ++ /* configure thresholds register */ ++ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmtr); ++ tmpReg |= ((uint32_t)p_FmDriverParam->dmaCommQThresholds.assertEmergency << DMA_THRESH_COMMQ_SHIFT) | ++ ((uint32_t)p_FmDriverParam->dmaReadBufThresholds.assertEmergency << DMA_THRESH_READ_INT_BUF_SHIFT) | ++ ((uint32_t)p_FmDriverParam->dmaWriteBufThresholds.assertEmergency); ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmtr, tmpReg); ++ ++ /* configure hysteresis register */ ++ tmpReg = ((uint32_t)p_FmDriverParam->dmaCommQThresholds.clearEmergency << DMA_THRESH_COMMQ_SHIFT) | ++ ((uint32_t)p_FmDriverParam->dmaReadBufThresholds.clearEmergency << DMA_THRESH_READ_INT_BUF_SHIFT) | ++ ((uint32_t)p_FmDriverParam->dmaWriteBufThresholds.clearEmergency); ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmhy, tmpReg); ++ ++ /* configure emergency threshold */ ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmsetr, p_FmDriverParam->dmaSosEmergency); ++ ++ /* configure Watchdog */ ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmwcr, USEC_TO_CLK(p_FmDriverParam->dmaWatchdog, p_Fm->p_FmStateStruct->fmClkFreq)); ++ ++ /* Allocate MURAM for CAM */ ++ p_Fm->camBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, ++ (uint32_t)(p_FmDriverParam->dmaCamNumOfEntries*DMA_CAM_SIZEOF_ENTRY), ++ DMA_CAM_ALIGN)); ++ if (!p_Fm->camBaseAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for DMA CAM failed")); ++ ++ WRITE_BLOCK(UINT_TO_PTR(p_Fm->camBaseAddr), ++ 0, ++ (uint32_t)(p_FmDriverParam->dmaCamNumOfEntries*DMA_CAM_SIZEOF_ENTRY)); ++ ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev == 2) ++ { ++ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->camBaseAddr)); ++ ++ p_Fm->camBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, ++ (uint32_t)(p_FmDriverParam->dmaCamNumOfEntries*72 + 128), ++ 64)); ++ if (!p_Fm->camBaseAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for DMA CAM failed")); ++ ++ WRITE_BLOCK(UINT_TO_PTR(p_Fm->camBaseAddr), ++ 0, ++ (uint32_t)(p_FmDriverParam->dmaCamNumOfEntries*72 + 128)); ++ ++ switch (p_FmDriverParam->dmaCamNumOfEntries) ++ { ++ case (8): ++ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xff000000); ++ break; ++ case (16): ++ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffff0000); ++ break; ++ case (24): ++ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffffff00); ++ break; ++ case (32): ++ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffffffff); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("wrong dmaCamNumOfEntries")); ++ } ++ } ++ ++ /* VirtToPhys */ ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmebcr, ++ (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->camBaseAddr)) - p_Fm->fmMuramPhysBaseAddr)); ++ ++ return E_OK; ++} ++ ++static t_Error InitFmFpm(t_Fm *p_Fm) ++{ ++ t_FmDriverParam *p_FmDriverParam = NULL; ++ uint32_t tmpReg; ++ int i; ++ ++ ASSERT_COND(p_Fm); ++ ASSERT_COND(p_Fm->p_FmDriverParam); ++ ++ p_FmDriverParam = p_Fm->p_FmDriverParam; ++ ++ tmpReg = (uint32_t)(p_FmDriverParam->thresholds.dispLimit << FPM_DISP_LIMIT_SHIFT); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_mxd, tmpReg); ++ ++ tmpReg = (((uint32_t)p_FmDriverParam->thresholds.prsDispTh << FPM_THR1_PRS_SHIFT) | ++ ((uint32_t)p_FmDriverParam->thresholds.kgDispTh << FPM_THR1_KG_SHIFT) | ++ ((uint32_t)p_FmDriverParam->thresholds.plcrDispTh << FPM_THR1_PLCR_SHIFT) | ++ ((uint32_t)p_FmDriverParam->thresholds.bmiDispTh << FPM_THR1_BMI_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_dis1, tmpReg); ++ ++ tmpReg = (((uint32_t)p_FmDriverParam->thresholds.qmiEnqDispTh << FPM_THR2_QMI_ENQ_SHIFT) | ++ ((uint32_t)p_FmDriverParam->thresholds.qmiDeqDispTh << FPM_THR2_QMI_DEQ_SHIFT) | ++ ((uint32_t)p_FmDriverParam->thresholds.fmCtl1DispTh << FPM_THR2_FM_CTL1_SHIFT) | ++ ((uint32_t)p_FmDriverParam->thresholds.fmCtl2DispTh << FPM_THR2_FM_CTL2_SHIFT)); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_dis2, tmpReg); ++ ++ /* define exceptions and error behavior */ ++ tmpReg = 0; ++ /* Clear events */ ++ tmpReg |= (FPM_EV_MASK_STALL | FPM_EV_MASK_DOUBLE_ECC | FPM_EV_MASK_SINGLE_ECC); ++ /* enable interrupts */ ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_FPM_STALL_ON_TASKS) ++ tmpReg |= FPM_EV_MASK_STALL_EN; ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_FPM_SINGLE_ECC) ++ tmpReg |= FPM_EV_MASK_SINGLE_ECC_EN; ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_FPM_DOUBLE_ECC) ++ tmpReg |= FPM_EV_MASK_DOUBLE_ECC_EN; ++ tmpReg |= (p_Fm->p_FmDriverParam->catastrophicErr << FPM_EV_MASK_CAT_ERR_SHIFT); ++ tmpReg |= (p_Fm->p_FmDriverParam->dmaErr << FPM_EV_MASK_DMA_ERR_SHIFT); ++ if (!p_Fm->p_FmDriverParam->haltOnExternalActivation) ++ tmpReg |= FPM_EV_MASK_EXTERNAL_HALT; ++ if (!p_Fm->p_FmDriverParam->haltOnUnrecoverableEccError) ++ tmpReg |= FPM_EV_MASK_ECC_ERR_HALT; ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg); ++ ++ /* clear all fmCtls event registers */ ++ for (i=0;ip_FmFpmRegs->fmfp_cev[i], 0xFFFFFFFF); ++ ++ /* RAM ECC - enable and clear events */ ++ /* first we need to clear all parser memory, as it is uninitialized and ++ may cause ECC errors ++ */ ++ tmpReg = 0; ++ /* event bits */ ++ tmpReg = (FPM_RAM_CTL_MURAM_ECC | FPM_RAM_CTL_IRAM_ECC); ++ /* Rams enable is not effected by the RCR bit, but by a COP configuration */ ++ if (p_Fm->p_FmDriverParam->externalEccRamsEnable) ++ tmpReg |= FPM_RAM_CTL_RAMS_ECC_EN_SRC_SEL; ++ ++ /* enable test mode */ ++ if (p_FmDriverParam->enMuramTestMode) ++ tmpReg |= FPM_RAM_CTL_MURAM_TEST_ECC; ++ if (p_FmDriverParam->enIramTestMode) ++ tmpReg |= FPM_RAM_CTL_IRAM_TEST_ECC; ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, tmpReg); ++ ++ tmpReg = 0; ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_IRAM_ECC) ++ { ++ tmpReg |= FPM_IRAM_ECC_ERR_EX_EN; ++ FmEnableRamsEcc(p_Fm); ++ } ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_MURAM_ECC) ++ { ++ tmpReg |= FPM_MURAM_ECC_ERR_EX_EN; ++ FmEnableRamsEcc(p_Fm); ++ } ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rie, tmpReg); ++ ++ return E_OK; ++} ++ ++static t_Error InitFmBmi(t_Fm *p_Fm) ++{ ++ uint32_t tmpReg; ++ ++ ASSERT_COND(p_Fm); ++ ASSERT_COND(p_Fm->p_FmDriverParam); ++ ++ tmpReg = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->fifoBaseAddr)) - p_Fm->fmMuramPhysBaseAddr); ++ tmpReg = tmpReg / BMI_FIFO_ALIGN; ++ ++ tmpReg |= ((p_Fm->p_FmStateStruct->totalFifoSize/BMI_FIFO_UNITS - 1) << BMI_CFG1_FIFO_SIZE_SHIFT); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg1, tmpReg); ++ ++ tmpReg = ((uint32_t)(p_Fm->p_FmStateStruct->totalNumOfTasks - 1) << BMI_CFG2_TASKS_SHIFT); ++#ifdef FM_HAS_TOTAL_DMAS ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6) ++ tmpReg |= (uint32_t)(p_Fm->p_FmStateStruct->maxNumOfOpenDmas - 1) << BMI_CFG2_DMAS_SHIFT; ++#endif /* FM_HAS_TOTAL_DMAS */ ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2, tmpReg); ++ ++ /* define unmaskable exceptions, enable and clear events */ ++ tmpReg = 0; ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ievr, (BMI_ERR_INTR_EN_LIST_RAM_ECC | ++ BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC | ++ BMI_ERR_INTR_EN_STATISTICS_RAM_ECC | ++ BMI_ERR_INTR_EN_DISPATCH_RAM_ECC)); ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_LIST_RAM_ECC) ++ tmpReg |= BMI_ERR_INTR_EN_LIST_RAM_ECC; ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STORAGE_PROFILE_ECC) ++ tmpReg |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC; ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STATISTICS_RAM_ECC) ++ tmpReg |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC; ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_DISPATCH_RAM_ECC) ++ tmpReg |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC; ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier, tmpReg); ++ ++ return E_OK; ++} ++ ++static t_Error InitFmQmi(t_Fm *p_Fm) ++{ ++ uint32_t tmpReg; ++ ++ ASSERT_COND(p_Fm); ++ ASSERT_COND(p_Fm->p_FmDriverParam); ++ ++ /* Clear error interrupt events */ ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eie, (QMI_ERR_INTR_EN_DOUBLE_ECC | QMI_ERR_INTR_EN_DEQ_FROM_DEF)); ++ tmpReg = 0; ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID) ++ tmpReg |= QMI_ERR_INTR_EN_DEQ_FROM_DEF; ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DOUBLE_ECC) ++ tmpReg |= QMI_ERR_INTR_EN_DOUBLE_ECC; ++ /* enable events */ ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eien, tmpReg); ++ ++ if (p_Fm->p_FmDriverParam->tnumAgingPeriod) ++ { ++ uint16_t periodInFmClocks; ++ uint8_t remainder; ++ ++ /* tnumAgingPeriod is in units of microseconds, p_FmClockFreq is in Mhz */ ++ periodInFmClocks = (uint16_t)(p_Fm->p_FmDriverParam->tnumAgingPeriod*p_Fm->p_FmStateStruct->fmClkFreq); ++ /* periodInFmClocks must be a 64 multiply */ ++ remainder = (uint8_t)(periodInFmClocks % 64); ++ if (remainder > 64) ++ tmpReg = (uint32_t)((periodInFmClocks/64) + 1); ++ else ++ { ++ tmpReg = (uint32_t)(periodInFmClocks/64); ++ if (!tmpReg) ++ tmpReg = 1; ++ } ++ tmpReg <<= QMI_TAPC_TAP; ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_tapc, tmpReg); ++ ++ } ++ ++ tmpReg = 0; ++ /* Clear interrupt events */ ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) && (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)) ++ { ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_ie, QMI_INTR_EN_SINGLE_ECC); ++ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_SINGLE_ECC) ++ tmpReg |= QMI_INTR_EN_SINGLE_ECC; ++ /* enable events */ ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_ien, tmpReg); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error InitGuestMode(t_Fm *p_Fm) ++{ ++ t_Error err = E_OK; ++ int i; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ ASSERT_COND(p_Fm); ++ ASSERT_COND(p_Fm->guestId != NCSW_MASTER_ID); ++ ++ /* build the FM guest partition IPC address */ ++ if (Sprint (p_Fm->fmModuleName, "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, p_Fm->guestId) != (p_Fm->guestId<10 ? 6:7)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ ++ /* build the FM master partition IPC address */ ++ memset(p_Fm->fmIpcHandlerModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE); ++ if (Sprint (p_Fm->fmIpcHandlerModuleName[0], "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, NCSW_MASTER_ID) != 6) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ ++ for (i=0;iintrMng[i].f_Isr = UnimplementedIsr; ++ ++ p_Fm->h_IpcSessions[0] = XX_IpcInitSession(p_Fm->fmIpcHandlerModuleName[0], p_Fm->fmModuleName); ++ if (p_Fm->h_IpcSessions[0]) ++ { ++ uint8_t isMasterAlive; ++ t_FmIpcParams ipcParams; ++ ++ err = XX_IpcRegisterMsgHandler(p_Fm->fmModuleName, FmGuestHandleIpcMsgCB, p_Fm, FM_IPC_MAX_REPLY_SIZE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_MASTER_IS_ALIVE; ++ msg.msgBody[0] = p_Fm->guestId; ++ replyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ do ++ { ++ blockingFlag = TRUE; ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(p_Fm->guestId), ++ (uint8_t*)&reply, ++ &replyLength, ++ IpcMsgCompletionCB, ++ p_Fm)) != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ while (blockingFlag) ; ++ if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t))) ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ isMasterAlive = *(uint8_t*)(reply.replyBody); ++ } while (!isMasterAlive); ++ ++ /* read FM parameters and save */ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_PARAMS; ++ replyLength = sizeof(uint32_t) + sizeof(t_FmIpcParams); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcParams))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ memcpy((uint8_t*)&ipcParams, reply.replyBody, sizeof(t_FmIpcParams)); ++ ++ p_Fm->p_FmStateStruct->fmClkFreq = ipcParams.fmClkFreq; ++ p_Fm->p_FmStateStruct->revInfo.majorRev = ipcParams.majorRev; ++ p_Fm->p_FmStateStruct->revInfo.minorRev = ipcParams.minorRev; ++ } ++ else ++ { ++ uint32_t tmpReg; ++ ++ DBG(WARNING, ("FM Guest mode - without IPC")); ++ if (!p_Fm->p_FmStateStruct->fmClkFreq) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("No fmClkFreq configured for guest without IPC")); ++ if (p_Fm->baseAddr) ++ { ++ /* read revision register 1 */ ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_ip_rev_1); ++ p_Fm->p_FmStateStruct->revInfo.majorRev = (uint8_t)((tmpReg & FPM_REV1_MAJOR_MASK) >> FPM_REV1_MAJOR_SHIFT); ++ p_Fm->p_FmStateStruct->revInfo.minorRev = (uint8_t)((tmpReg & FPM_REV1_MINOR_MASK) >> FPM_REV1_MINOR_SHIFT); ++ } ++ } ++ ++#if (DPAA_VERSION >= 11) ++ p_Fm->partVSPBase = AllocVSPsForPartition(p_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId); ++ if (p_Fm->partVSPBase == ILLEGAL_BASE) ++ DBG(WARNING, ("partition VSPs allocation is FAILED")); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* General FM driver initialization */ ++ if (p_Fm->baseAddr) ++ p_Fm->fmMuramPhysBaseAddr = ++ (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_MURAM))); ++ ++ XX_Free(p_Fm->p_FmDriverParam); ++ p_Fm->p_FmDriverParam = NULL; ++ ++ if ((p_Fm->guestId == NCSW_MASTER_ID) || ++ (p_Fm->h_IpcSessions[0])) ++ { ++ FM_DisableRamsEcc(p_Fm); ++ FmMuramClear(p_Fm->h_FmMuram); ++ FM_EnableRamsEcc(p_Fm); ++ } ++ ++ return E_OK; ++} ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++t_Error FmDumpPortRegs (t_Handle h_Fm, uint8_t hardwarePortId) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ ++ DECLARE_DUMP; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((p_Fm->guestId == NCSW_MASTER_ID) || ++ p_Fm->baseAddr), E_INVALID_OPERATION); ++ ++ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], ("fmbm_pp for port %u", (hardwarePortId))); ++ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], sizeof(uint32_t)); ++ ++ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], ("fmbm_pfs for port %u", (hardwarePortId ))); ++ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], sizeof(uint32_t)); ++ ++ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], ("fmbm_spliodn for port %u", (hardwarePortId))); ++ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], sizeof(uint32_t)); ++ ++ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId], ("fmfp_ps for port %u", (hardwarePortId))); ++ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId], sizeof(uint32_t)); ++ ++ DUMP_TITLE(&p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2], ("fmdmplr for port %u", (hardwarePortId))); ++ DUMP_MEMORY(&p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2], sizeof(uint32_t)); ++ ++ return E_OK; ++} ++#endif /* (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) */ ++ ++ ++/*****************************************************************************/ ++/* API Init unit functions */ ++/*****************************************************************************/ ++t_Handle FM_Config(t_FmParams *p_FmParam) ++{ ++ t_Fm *p_Fm; ++ uint8_t i; ++ uintptr_t baseAddr; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmParam, E_NULL_POINTER, NULL); ++ SANITY_CHECK_RETURN_VALUE(((p_FmParam->firmware.p_Code && p_FmParam->firmware.size) || ++ (!p_FmParam->firmware.p_Code && !p_FmParam->firmware.size)), ++ E_INVALID_VALUE, NULL); ++ ++ baseAddr = p_FmParam->baseAddr; ++ ++ /* Allocate FM structure */ ++ p_Fm = (t_Fm *) XX_Malloc(sizeof(t_Fm)); ++ if (!p_Fm) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM driver structure")); ++ return NULL; ++ } ++ memset(p_Fm, 0, sizeof(t_Fm)); ++ ++ p_Fm->p_FmStateStruct = (t_FmStateStruct *) XX_Malloc(sizeof(t_FmStateStruct)); ++ if (!p_Fm->p_FmStateStruct) ++ { ++ XX_Free(p_Fm); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Status structure")); ++ return NULL; ++ } ++ memset(p_Fm->p_FmStateStruct, 0, sizeof(t_FmStateStruct)); ++ ++ /* Initialize FM parameters which will be kept by the driver */ ++ p_Fm->p_FmStateStruct->fmId = p_FmParam->fmId; ++ p_Fm->guestId = p_FmParam->guestId; ++ ++ for (i=0; ip_FmStateStruct->portsTypes[i] = e_FM_PORT_TYPE_DUMMY; ++ ++ /* Allocate the FM driver's parameters structure */ ++ p_Fm->p_FmDriverParam = (t_FmDriverParam *)XX_Malloc(sizeof(t_FmDriverParam)); ++ if (!p_Fm->p_FmDriverParam) ++ { ++ XX_Free(p_Fm->p_FmStateStruct); ++ XX_Free(p_Fm); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM driver parameters")); ++ return NULL; ++ } ++ memset(p_Fm->p_FmDriverParam, 0, sizeof(t_FmDriverParam)); ++ ++#if (DPAA_VERSION >= 11) ++ p_Fm->p_FmSp = (t_FmSp *)XX_Malloc(sizeof(t_FmSp)); ++ if (!p_Fm->p_FmSp) ++ { ++ XX_Free(p_Fm->p_FmDriverParam); ++ XX_Free(p_Fm->p_FmStateStruct); ++ XX_Free(p_Fm); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("allocation for internal data structure failed")); ++ return NULL; ++ } ++ memset(p_Fm->p_FmSp, 0, sizeof(t_FmSp)); ++ ++ for (i=0; ip_FmSp->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* Initialize FM parameters which will be kept by the driver */ ++ p_Fm->p_FmStateStruct->fmId = p_FmParam->fmId; ++ p_Fm->h_FmMuram = p_FmParam->h_FmMuram; ++ p_Fm->h_App = p_FmParam->h_App; ++ p_Fm->p_FmStateStruct->fmClkFreq = p_FmParam->fmClkFreq; ++ p_Fm->f_Exception = p_FmParam->f_Exception; ++ p_Fm->f_BusError = p_FmParam->f_BusError; ++ p_Fm->p_FmFpmRegs = (t_FmFpmRegs *)UINT_TO_PTR(baseAddr + FM_MM_FPM); ++ p_Fm->p_FmBmiRegs = (t_FmBmiRegs *)UINT_TO_PTR(baseAddr + FM_MM_BMI); ++ p_Fm->p_FmQmiRegs = (t_FmQmiRegs *)UINT_TO_PTR(baseAddr + FM_MM_QMI); ++ p_Fm->p_FmDmaRegs = (t_FmDmaRegs *)UINT_TO_PTR(baseAddr + FM_MM_DMA); ++ p_Fm->baseAddr = baseAddr; ++ p_Fm->p_FmStateStruct->irq = p_FmParam->irq; ++ p_Fm->p_FmStateStruct->errIrq = p_FmParam->errIrq; ++ p_Fm->hcPortInitialized = FALSE; ++ p_Fm->independentMode = FALSE; ++ ++ p_Fm->h_Spinlock = XX_InitSpinlock(); ++ if (!p_Fm->h_Spinlock) ++ { ++ XX_Free(p_Fm->p_FmDriverParam); ++ XX_Free(p_Fm->p_FmStateStruct); ++ XX_Free(p_Fm); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("cant allocate spinlock!")); ++ return NULL; ++ } ++ ++#if (DPAA_VERSION >= 11) ++ p_Fm->partVSPBase = p_FmParam->partVSPBase; ++ p_Fm->partNumOfVSPs = p_FmParam->partNumOfVSPs; ++ p_Fm->vspBaseAddr = p_FmParam->vspBaseAddr; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++ ++ p_Fm->p_FmStateStruct->ramsEccEnable = FALSE; ++ p_Fm->p_FmStateStruct->extraFifoPoolSize = 0; ++ p_Fm->p_FmStateStruct->exceptions = DEFAULT_exceptions; ++ /*p_Fm->p_FmDriverParam->numOfPartitions = p_FmParam->numOfPartitions; */ ++ p_Fm->p_FmDriverParam->tnumAgingPeriod = 0; ++ p_Fm->p_FmDriverParam->resetOnInit = DEFAULT_resetOnInit; ++ ++ p_Fm->p_FmDriverParam->catastrophicErr = DEFAULT_catastrophicErr; ++ p_Fm->p_FmDriverParam->dmaErr = DEFAULT_dmaErr; ++ p_Fm->p_FmDriverParam->haltOnExternalActivation = DEFAULT_haltOnExternalActivation; ++ p_Fm->p_FmDriverParam->haltOnUnrecoverableEccError = DEFAULT_haltOnUnrecoverableEccError; ++ p_Fm->p_FmDriverParam->enIramTestMode = FALSE; ++ p_Fm->p_FmDriverParam->enMuramTestMode = FALSE; ++ p_Fm->p_FmDriverParam->externalEccRamsEnable = DEFAULT_externalEccRamsEnable; ++ ++ p_Fm->p_FmDriverParam->fwVerify = DEFAULT_VerifyUcode; ++ p_Fm->p_FmDriverParam->firmware.size = p_FmParam->firmware.size; ++ if (p_Fm->p_FmDriverParam->firmware.size) ++ { ++ p_Fm->p_FmDriverParam->firmware.p_Code = (uint32_t *)XX_Malloc(p_Fm->p_FmDriverParam->firmware.size); ++ if (!p_Fm->p_FmDriverParam->firmware.p_Code) ++ { ++ XX_FreeSpinlock(p_Fm->h_Spinlock); ++ XX_Free(p_Fm->p_FmStateStruct); ++ XX_Free(p_Fm->p_FmDriverParam); ++ XX_Free(p_Fm); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM firmware code")); ++ return NULL; ++ } ++ memcpy(p_Fm->p_FmDriverParam->firmware.p_Code, p_FmParam->firmware.p_Code ,p_Fm->p_FmDriverParam->firmware.size); ++ } ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ return p_Fm; ++ ++ /* read revision register 1 */ ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_ip_rev_1); ++ p_Fm->p_FmStateStruct->revInfo.majorRev = (uint8_t)((tmpReg & FPM_REV1_MAJOR_MASK) >> FPM_REV1_MAJOR_SHIFT); ++ p_Fm->p_FmStateStruct->revInfo.minorRev = (uint8_t)((tmpReg & FPM_REV1_MINOR_MASK) >> FPM_REV1_MINOR_SHIFT); ++ /* Chip dependent, will be configured in Init */ ++ ++ p_Fm->p_FmDriverParam->dmaAidOverride = DEFAULT_aidOverride; ++ p_Fm->p_FmDriverParam->dmaAidMode = DEFAULT_aidMode; ++#ifdef FM_AID_MODE_NO_TNUM_SW005 ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ p_Fm->p_FmDriverParam->dmaAidMode = e_FM_DMA_AID_OUT_PORT_ID; ++#endif /* FM_AID_MODE_NO_TNUM_SW005 */ ++#ifdef FM_NO_GUARANTEED_RESET_VALUES ++ ++ if (1)//p_Fm->p_FmStateStruct->revInfo.majorRev < 6) ++ { ++ p_Fm->p_FmStateStruct->totalFifoSize = 0; ++ p_Fm->p_FmStateStruct->totalNumOfTasks = BMI_MAX_NUM_OF_TASKS; ++ p_Fm->p_FmStateStruct->maxNumOfOpenDmas = BMI_MAX_NUM_OF_DMAS; ++ p_Fm->p_FmDriverParam->dmaCommQThresholds.clearEmergency = DEFAULT_dmaCommQLow; ++ p_Fm->p_FmDriverParam->dmaCommQThresholds.assertEmergency = DEFAULT_dmaCommQHigh; ++ p_Fm->p_FmDriverParam->dmaReadBufThresholds.clearEmergency = DEFAULT_dmaReadIntBufLow; ++ p_Fm->p_FmDriverParam->dmaReadBufThresholds.assertEmergency = DEFAULT_dmaReadIntBufHigh; ++ p_Fm->p_FmDriverParam->dmaWriteBufThresholds.clearEmergency = DEFAULT_dmaWriteIntBufLow; ++ p_Fm->p_FmDriverParam->dmaWriteBufThresholds.assertEmergency = DEFAULT_dmaWriteIntBufHigh; ++ p_Fm->p_FmDriverParam->dmaCacheOverride = DEFAULT_cacheOverride; ++ p_Fm->p_FmDriverParam->dmaCamNumOfEntries = DEFAULT_dmaCamNumOfEntries; ++ p_Fm->p_FmDriverParam->dmaDbgCntMode = DEFAULT_dmaDbgCntMode; ++ p_Fm->p_FmDriverParam->dmaEnEmergency = FALSE; ++ p_Fm->p_FmDriverParam->dmaAxiDbgNumOfBeats = DEFAULT_axiDbgNumOfBeats; ++ p_Fm->p_FmDriverParam->dmaSosEmergency = DEFAULT_dmaSosEmergency; ++ p_Fm->p_FmDriverParam->dmaWatchdog = DEFAULT_dmaWatchdog; ++ p_Fm->p_FmDriverParam->thresholds.dispLimit = DEFAULT_dispLimit; ++ p_Fm->p_FmDriverParam->thresholds.prsDispTh = DEFAULT_prsDispTh; ++ p_Fm->p_FmDriverParam->thresholds.plcrDispTh = DEFAULT_plcrDispTh; ++ p_Fm->p_FmDriverParam->thresholds.kgDispTh = DEFAULT_kgDispTh; ++ p_Fm->p_FmDriverParam->thresholds.bmiDispTh = DEFAULT_bmiDispTh; ++ p_Fm->p_FmDriverParam->thresholds.qmiEnqDispTh = DEFAULT_qmiEnqDispTh; ++ p_Fm->p_FmDriverParam->thresholds.qmiDeqDispTh = DEFAULT_qmiDeqDispTh; ++ p_Fm->p_FmDriverParam->thresholds.fmCtl1DispTh = DEFAULT_fmCtl1DispTh; ++ p_Fm->p_FmDriverParam->thresholds.fmCtl2DispTh = DEFAULT_fmCtl2DispTh; ++ p_Fm->p_FmDriverParam->dmaEnEmergencySmoother = FALSE; ++ } ++ else ++#endif /* FM_NO_GUARANTEED_RESET_VALUES */ ++ { ++ /* read the values from the registers as they are initialized by the HW with ++ * the required values. ++ */ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg1); ++ p_Fm->p_FmStateStruct->totalFifoSize = ++ (((tmpReg & BMI_TOTAL_FIFO_SIZE_MASK) >> BMI_CFG1_FIFO_SIZE_SHIFT) + 1) * BMI_FIFO_UNITS; ++ ++#ifdef FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 ++ tmpReg = 0x007B0000; ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2, tmpReg); ++#endif /* FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 */ ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2); ++ p_Fm->p_FmStateStruct->totalNumOfTasks = ++ (uint8_t)(((tmpReg & BMI_TOTAL_NUM_OF_TASKS_MASK) >> BMI_CFG2_TASKS_SHIFT) + 1); ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmtr); ++ p_Fm->p_FmDriverParam->dmaCommQThresholds.assertEmergency = ++ (uint8_t)(tmpReg >> DMA_THRESH_COMMQ_SHIFT); ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmhy); ++ p_Fm->p_FmDriverParam->dmaCommQThresholds.clearEmergency = ++ (uint8_t)(tmpReg >> DMA_THRESH_COMMQ_SHIFT); ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr); ++ p_Fm->p_FmDriverParam->dmaCacheOverride = (e_FmDmaCacheOverride)((tmpReg & DMA_MODE_CACHE_OR_MASK) >> DMA_MODE_CACHE_OR_SHIFT); ++ p_Fm->p_FmDriverParam->dmaCamNumOfEntries = (uint8_t)((((tmpReg & DMA_MODE_CEN_MASK) >> DMA_MODE_CEN_SHIFT) +1)*DMA_CAM_UNITS); ++ p_Fm->p_FmDriverParam->dmaDbgCntMode = (e_FmDmaDbgCntMode)((tmpReg & DMA_MODE_DBG_MASK) >> DMA_MODE_DBG_SHIFT); ++ p_Fm->p_FmDriverParam->dmaEnEmergency = (bool)((tmpReg & DMA_MODE_EB)? TRUE : FALSE); ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_mxd); ++ p_Fm->p_FmDriverParam->thresholds.dispLimit = (uint8_t)((tmpReg & FPM_DISP_LIMIT_MASK) << FPM_DISP_LIMIT_SHIFT); ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_dis1); ++ p_Fm->p_FmDriverParam->thresholds.prsDispTh = (uint8_t)((tmpReg & FPM_THR1_PRS_MASK ) << FPM_THR1_PRS_SHIFT); ++ p_Fm->p_FmDriverParam->thresholds.plcrDispTh = (uint8_t)((tmpReg & FPM_THR1_KG_MASK ) << FPM_THR1_KG_SHIFT); ++ p_Fm->p_FmDriverParam->thresholds.kgDispTh = (uint8_t)((tmpReg & FPM_THR1_PLCR_MASK ) << FPM_THR1_PLCR_SHIFT); ++ p_Fm->p_FmDriverParam->thresholds.bmiDispTh = (uint8_t)((tmpReg & FPM_THR1_BMI_MASK ) << FPM_THR1_BMI_SHIFT); ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_dis2); ++ p_Fm->p_FmDriverParam->thresholds.qmiEnqDispTh = (uint8_t)((tmpReg & FPM_THR2_QMI_ENQ_MASK ) << FPM_THR2_QMI_ENQ_SHIFT); ++ p_Fm->p_FmDriverParam->thresholds.qmiDeqDispTh = (uint8_t)((tmpReg & FPM_THR2_QMI_DEQ_MASK ) << FPM_THR2_QMI_DEQ_SHIFT); ++ p_Fm->p_FmDriverParam->thresholds.fmCtl1DispTh = (uint8_t)((tmpReg & FPM_THR2_FM_CTL1_MASK ) << FPM_THR2_FM_CTL1_SHIFT); ++ p_Fm->p_FmDriverParam->thresholds.fmCtl2DispTh = (uint8_t)((tmpReg & FPM_THR2_FM_CTL2_MASK ) << FPM_THR2_FM_CTL2_SHIFT); ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmsetr); ++ p_Fm->p_FmDriverParam->dmaSosEmergency = tmpReg; ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmwcr); ++ p_Fm->p_FmDriverParam->dmaWatchdog = tmpReg/p_Fm->p_FmStateStruct->fmClkFreq; ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmemsr); ++ p_Fm->p_FmDriverParam->dmaEnEmergencySmoother = (bool)((tmpReg & DMA_EMSR_EMSTR_MASK)? TRUE : FALSE); ++ p_Fm->p_FmDriverParam->dmaEmergencySwitchCounter = (tmpReg & DMA_EMSR_EMSTR_MASK); ++ } ++ ++ return p_Fm; ++} ++ ++/**************************************************************************//** ++ @Function FM_Init ++ ++ @Description Initializes the FM module ++ ++ @Param[in] h_Fm - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_Init(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_FmDriverParam *p_FmDriverParam = NULL; ++ t_Error err = E_OK; ++ uint32_t cfgReg = 0; ++ int i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ ++ p_Fm->p_FmStateStruct->count1MicroBit = FM_TIMESTAMP_1_USEC_BIT; ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ return InitGuestMode(p_Fm); ++ ++#ifdef FM_NO_GUARANTEED_RESET_VALUES ++ if (1)//p_Fm->p_FmStateStruct->revInfo.majorRev < 6) ++ /* if user didn't configured totalFifoSize - (totalFifoSize=0) we configure default ++ * according to chip. otherwise, we use user's configuration. ++ */ ++ if (p_Fm->p_FmStateStruct->totalFifoSize == 0) ++ p_Fm->p_FmStateStruct->totalFifoSize = DEFAULT_totalFifoSize(p_Fm->p_FmStateStruct->revInfo.majorRev); ++#endif /* FM_NO_GUARANTEED_RESET_VALUES */ ++ ++ CHECK_INIT_PARAMETERS(p_Fm, CheckFmParameters); ++ ++ p_FmDriverParam = p_Fm->p_FmDriverParam; ++ ++ /* clear revision-dependent non existing exception */ ++#ifdef FM_NO_DISPATCH_RAM_ECC ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) && ++ (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)) ++ p_Fm->p_FmStateStruct->exceptions &= ~FM_EX_BMI_DISPATCH_RAM_ECC; ++#endif /* FM_NO_DISPATCH_RAM_ECC */ ++ ++#ifdef FM_QMI_NO_ECC_EXCEPTIONS ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev == 4) ++ p_Fm->p_FmStateStruct->exceptions &= ~(FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC); ++#endif /* FM_QMI_NO_ECC_EXCEPTIONS */ ++ ++#ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ p_Fm->p_FmStateStruct->exceptions &= ~FM_EX_QMI_SINGLE_ECC; ++#endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */ ++ ++ FmMuramClear(p_Fm->h_FmMuram); ++ ++ /* clear CPG */ ++ IOMemSet32(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_CGP), 0, FM_PORT_NUM_OF_CONGESTION_GRPS); ++ ++ /* add to the default exceptions the user's definitions */ ++ p_Fm->p_FmStateStruct->exceptions |= p_FmDriverParam->userSetExceptions; ++ ++#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 ++ if (p_FmDriverParam->resetOnInit) ++ { ++ if ((err = FwNotResetErratumBugzilla6173WA(p_Fm)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ else ++ { ++#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ ++ ++ /* Reset the FM if required. */ ++ if (p_FmDriverParam->resetOnInit) ++ { ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET); ++ CORE_MemoryBarrier(); ++ XX_UDelay(100); ++ ++ if (GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gs) & QMI_GS_HALT_NOT_BUSY) ++ { ++ uint32_t tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee); ++ /* clear tmpReg event bits in order not to clear standing events */ ++ tmpReg &= ~(FPM_EV_MASK_DOUBLE_ECC | FPM_EV_MASK_STALL | FPM_EV_MASK_SINGLE_ECC); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg | FPM_EV_MASK_RELEASE_FM); ++ CORE_MemoryBarrier(); ++ XX_UDelay(100); ++ } ++ } ++ ++ /*************************************/ ++ /* Load FMan-Controller code to IRAM */ ++ /*************************************/ ++ if (ClearIRam(p_Fm) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ if (p_Fm->p_FmDriverParam->firmware.p_Code && ++ (LoadFmanCtrlCode(p_Fm) != E_OK)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 ++ } ++#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++ /* save first 256 byte in MURAM */ ++ p_Fm->resAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, 256, 0)); ++ if (!p_Fm->resAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for reserved Area failed")); ++ ++ WRITE_BLOCK(UINT_TO_PTR(p_Fm->resAddr), 0, 256); ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++#if (DPAA_VERSION >= 11) ++ p_Fm->partVSPBase = AllocVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId); ++ if (p_Fm->partVSPBase == ILLEGAL_BASE) ++ DBG(WARNING, ("partition VSPs allocation is FAILED")); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* General FM driver initialization */ ++ p_Fm->fmMuramPhysBaseAddr = ++ (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_MURAM))); ++ ++ for (i=0;iintrMng[i].f_Isr = UnimplementedIsr; ++ for (i=0;ifmanCtrlIntr[i].f_Isr = UnimplementedFmanCtrlIsr; ++ ++ /**********************/ ++ /* Init DMA Registers */ ++ /**********************/ ++ err = InitFmDma(p_Fm); ++ if (err != E_OK) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /**********************/ ++ /* Init FPM Registers */ ++ /**********************/ ++ err = InitFmFpm(p_Fm); ++ if (err != E_OK) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /* define common resources */ ++ /* allocate MURAM for FIFO according to total size */ ++ p_Fm->fifoBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, ++ p_Fm->p_FmStateStruct->totalFifoSize, ++ BMI_FIFO_ALIGN)); ++ if (!p_Fm->fifoBaseAddr) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for BMI FIFO failed")); ++ } ++ ++ /**********************/ ++ /* Init BMI Registers */ ++ /**********************/ ++ err = InitFmBmi(p_Fm); ++ if (err != E_OK) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /**********************/ ++ /* Init QMI Registers */ ++ /**********************/ ++ err = InitFmQmi(p_Fm); ++ if (err != E_OK) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /* build the FM master partition IPC address */ ++ if (Sprint (p_Fm->fmModuleName, "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, NCSW_MASTER_ID) != 6) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ } ++ ++ err = XX_IpcRegisterMsgHandler(p_Fm->fmModuleName, FmHandleIpcMsgCB, p_Fm, FM_IPC_MAX_REPLY_SIZE); ++ if (err) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /* Register the FM interrupts handlers */ ++ if (p_Fm->p_FmStateStruct->irq != NO_IRQ) ++ { ++ XX_SetIntr(p_Fm->p_FmStateStruct->irq, FM_EventIsr, p_Fm); ++ XX_EnableIntr(p_Fm->p_FmStateStruct->irq); ++ } ++ ++ if (p_Fm->p_FmStateStruct->errIrq != NO_IRQ) ++ { ++ XX_SetIntr(p_Fm->p_FmStateStruct->errIrq, (void (*) (t_Handle))FM_ErrorIsr, p_Fm); ++ XX_EnableIntr(p_Fm->p_FmStateStruct->errIrq); ++ } ++ ++ /**********************/ ++ /* Enable all modules */ ++ /**********************/ ++ /* clear & enable global counters - calculate reg and save for later, ++ because it's the same reg for QMI enable */ ++ cfgReg = QMI_CFG_EN_COUNTERS; ++#ifndef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4) ++ cfgReg |= (uint32_t)(((QMI_DEF_TNUMS_THRESH) << 8) | (uint32_t)QMI_DEF_TNUMS_THRESH); ++#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_init, BMI_INIT_START); ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc, cfgReg | QMI_CFG_ENQ_EN | QMI_CFG_DEQ_EN); ++ ++ EnableTimeStamp(p_Fm); ++ ++ if (p_Fm->p_FmDriverParam->firmware.p_Code) ++ { ++ XX_Free(p_Fm->p_FmDriverParam->firmware.p_Code); ++ p_Fm->p_FmDriverParam->firmware.p_Code = NULL; ++ } ++ ++ XX_Free(p_Fm->p_FmDriverParam); ++ p_Fm->p_FmDriverParam = NULL; ++ ++ return E_OK; ++} ++ ++/**************************************************************************//** ++ @Function FM_Free ++ ++ @Description Frees all resources that were assigned to FM module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_Fm - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_Free(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++#if (DPAA_VERSION >= 11) ++ FreeVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId); ++ ++ if (p_Fm->p_FmSp) ++ { ++ XX_Free(p_Fm->p_FmSp); ++ p_Fm->p_FmSp = NULL; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (p_Fm->fmModuleName) ++ XX_IpcUnregisterMsgHandler(p_Fm->fmModuleName); ++ ++ if (!p_Fm->recoveryMode) ++ XX_Free(p_Fm->p_FmStateStruct); ++ ++ XX_Free(p_Fm); ++ ++ return E_OK; ++ } ++ ++ /* disable BMI and QMI */ ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_init, 0); ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc, 0); ++ ++ if ((p_Fm->guestId == NCSW_MASTER_ID) && (p_Fm->fmModuleName[0] != 0)) ++ XX_IpcUnregisterMsgHandler(p_Fm->fmModuleName); ++ ++ if (p_Fm->p_FmStateStruct) ++ { ++ if (p_Fm->p_FmStateStruct->irq != NO_IRQ) ++ { ++ XX_DisableIntr(p_Fm->p_FmStateStruct->irq); ++ XX_FreeIntr(p_Fm->p_FmStateStruct->irq); ++ } ++ if (p_Fm->p_FmStateStruct->errIrq != NO_IRQ) ++ { ++ XX_DisableIntr(p_Fm->p_FmStateStruct->errIrq); ++ XX_FreeIntr(p_Fm->p_FmStateStruct->errIrq); ++ } ++ } ++ ++#if (DPAA_VERSION >= 11) ++ FreeVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId); ++ ++ if (p_Fm->p_FmSp) ++ { ++ XX_Free(p_Fm->p_FmSp); ++ p_Fm->p_FmSp = NULL; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (p_Fm->h_Spinlock) ++ XX_FreeSpinlock(p_Fm->h_Spinlock); ++ ++ if (p_Fm->p_FmDriverParam) ++ { ++ if (p_Fm->p_FmDriverParam->firmware.p_Code) ++ XX_Free(p_Fm->p_FmDriverParam->firmware.p_Code); ++ XX_Free(p_Fm->p_FmDriverParam); ++ p_Fm->p_FmDriverParam = NULL; ++ } ++ ++ FreeInitResources(p_Fm); ++ ++ if (!p_Fm->recoveryMode && p_Fm->p_FmStateStruct) ++ XX_Free(p_Fm->p_FmStateStruct); ++ ++ XX_Free(p_Fm); ++ ++ return E_OK; ++} ++ ++/*************************************************/ ++/* API Advanced Init unit functions */ ++/*************************************************/ ++ ++t_Error FM_ConfigResetOnInit(t_Handle h_Fm, bool enable) ++{ ++ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->resetOnInit = enable; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigTotalFifoSize(t_Handle h_Fm, uint32_t totalFifoSize) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmStateStruct->totalFifoSize = totalFifoSize; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaCacheOverride(t_Handle h_Fm, e_FmDmaCacheOverride cacheOverride) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dmaCacheOverride = cacheOverride; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaAidOverride(t_Handle h_Fm, bool aidOverride) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dmaAidOverride = aidOverride; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaAidMode(t_Handle h_Fm, e_FmDmaAidMode aidMode) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dmaAidMode = aidMode; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaAxiDbgNumOfBeats(t_Handle h_Fm, uint8_t axiDbgNumOfBeats) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++#if (DPAA_VERSION >= 11) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); ++#endif ++ p_Fm->p_FmDriverParam->dmaAxiDbgNumOfBeats = axiDbgNumOfBeats; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaCamNumOfEntries(t_Handle h_Fm, uint8_t numOfEntries) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dmaCamNumOfEntries = numOfEntries; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaDbgCounter(t_Handle h_Fm, e_FmDmaDbgCntMode fmDmaDbgCntMode) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dmaDbgCntMode = fmDmaDbgCntMode; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaStopOnBusErr(t_Handle h_Fm, bool stop) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dmaStopOnBusError = stop; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaEmergency(t_Handle h_Fm, t_FmDmaEmergency *p_Emergency) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dmaEnEmergency = TRUE; ++ memcpy(&p_Fm->p_FmDriverParam->dmaEmergency, p_Emergency, sizeof(t_FmDmaEmergency)); ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaEmergencySmoother(t_Handle h_Fm, uint32_t emergencyCnt) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dmaEnEmergencySmoother = TRUE; ++ p_Fm->p_FmDriverParam->dmaEmergencySwitchCounter = emergencyCnt; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaErr(t_Handle h_Fm, e_FmDmaErr dmaErr) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dmaErr = dmaErr; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigCatastrophicErr(t_Handle h_Fm, e_FmCatastrophicErr catastrophicErr) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->catastrophicErr = catastrophicErr; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigEnableMuramTestMode(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); ++ ++ p_Fm->p_FmDriverParam->enMuramTestMode = TRUE; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigEnableIramTestMode(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE ); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); ++ ++ p_Fm->p_FmDriverParam->enIramTestMode = TRUE; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigHaltOnExternalActivation(t_Handle h_Fm, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->haltOnExternalActivation = enable; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigHaltOnUnrecoverableEccError(t_Handle h_Fm, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); ++ ++ p_Fm->p_FmDriverParam->haltOnUnrecoverableEccError = enable; ++ return E_OK; ++} ++ ++t_Error FM_ConfigException(t_Handle h_Fm, e_FmExceptions exception, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Fm->p_FmDriverParam->userSetExceptions |= bitMask; ++ else ++ p_Fm->p_FmStateStruct->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigExternalEccRamsEnable(t_Handle h_Fm, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->externalEccRamsEnable = enable; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigTnumAgingPeriod(t_Handle h_Fm, uint16_t tnumAgingPeriod) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->tnumAgingPeriod = tnumAgingPeriod; ++ ++ return E_OK; ++} ++ ++/****************************************************/ ++/* Hidden-DEBUG Only API */ ++/****************************************************/ ++ ++t_Error FM_ConfigThresholds(t_Handle h_Fm, t_FmThresholds *p_FmThresholds) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ memcpy(&p_Fm->p_FmDriverParam->thresholds, p_FmThresholds, sizeof(t_FmThresholds)); ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaSosEmergencyThreshold(t_Handle h_Fm, uint32_t dmaSosEmergency) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dmaSosEmergency = dmaSosEmergency; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaWriteBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds) ++ ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++#if (DPAA_VERSION >= 11) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); ++#endif ++ memcpy(&p_Fm->p_FmDriverParam->dmaWriteBufThresholds, p_FmDmaThresholds, sizeof(t_FmDmaThresholds)); ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaCommQThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ memcpy(&p_Fm->p_FmDriverParam->dmaCommQThresholds, p_FmDmaThresholds, sizeof(t_FmDmaThresholds)); ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaReadBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++#if (DPAA_VERSION >= 11) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); ++#endif ++ memcpy(&p_Fm->p_FmDriverParam->dmaReadBufThresholds, p_FmDmaThresholds, sizeof(t_FmDmaThresholds)); ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaWatchdog(t_Handle h_Fm, uint32_t watchdogValue) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dmaWatchdog = watchdogValue; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigEnableCounters(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++UNUSED(p_Fm); ++ ++ return E_OK; ++} ++ ++/****************************************************/ ++/* API Run-time Control uint functions */ ++/****************************************************/ ++void FM_EventIsr(t_Handle h_Fm) ++{ ++#define FM_M_CALL_1G_MAC_ISR(_id) \ ++ { \ ++ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].guestId) \ ++ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id), pending); \ ++ else \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].h_SrcHandle);\ ++ } ++#define FM_M_CALL_10G_MAC_ISR(_id) \ ++ { \ ++ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].guestId) \ ++ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id), pending); \ ++ else \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].h_SrcHandle);\ ++ } ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t pending, event; ++ ++ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ /* normal interrupts */ ++ pending = GET_UINT32(p_Fm->p_FmFpmRegs->fm_npi); ++ if (!pending) ++ return; ++ ++ if (pending & INTR_EN_QMI) ++ QmiEvent(p_Fm); ++ if (pending & INTR_EN_PRS) ++ p_Fm->intrMng[e_FM_EV_PRS].f_Isr(p_Fm->intrMng[e_FM_EV_PRS].h_SrcHandle); ++ if (pending & INTR_EN_PLCR) ++ p_Fm->intrMng[e_FM_EV_PLCR].f_Isr(p_Fm->intrMng[e_FM_EV_PLCR].h_SrcHandle); ++ if (pending & INTR_EN_TMR) ++ p_Fm->intrMng[e_FM_EV_TMR].f_Isr(p_Fm->intrMng[e_FM_EV_TMR].h_SrcHandle); ++ ++ /* MAC events may belong to different partitions */ ++ if (pending & INTR_EN_1G_MAC0) ++ FM_M_CALL_1G_MAC_ISR(0); ++ if (pending & INTR_EN_1G_MAC1) ++ FM_M_CALL_1G_MAC_ISR(1); ++ if (pending & INTR_EN_1G_MAC2) ++ FM_M_CALL_1G_MAC_ISR(2); ++ if (pending & INTR_EN_1G_MAC3) ++ FM_M_CALL_1G_MAC_ISR(3); ++ if (pending & INTR_EN_1G_MAC4) ++ FM_M_CALL_1G_MAC_ISR(4); ++ if (pending & INTR_EN_1G_MAC5) ++ FM_M_CALL_1G_MAC_ISR(5); ++ if (pending & INTR_EN_1G_MAC6) ++ FM_M_CALL_1G_MAC_ISR(6); ++ if (pending & INTR_EN_1G_MAC7) ++ FM_M_CALL_1G_MAC_ISR(7); ++ if (pending & INTR_EN_10G_MAC0) ++ FM_M_CALL_10G_MAC_ISR(0); ++ if (pending & INTR_EN_10G_MAC1) ++ FM_M_CALL_10G_MAC_ISR(1); ++ ++ /* IM port events may belong to different partitions */ ++ if (pending & INTR_EN_REV0) ++ { ++ event = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_fcev[0]) & GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_cee[0]); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_cev[0], event); ++ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_0].guestId) ++ /*TODO IPC ISR For Fman Ctrl */ ++ ASSERT_COND(0); ++ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_0, pending); */ ++ else ++ p_Fm->fmanCtrlIntr[0].f_Isr(p_Fm->fmanCtrlIntr[0].h_SrcHandle, event); ++ ++ } ++ if (pending & INTR_EN_REV1) ++ { ++ event = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_fcev[1]) & GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_cee[1]); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_cev[1], event); ++ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_1].guestId) ++ /*TODO IPC ISR For Fman Ctrl */ ++ ASSERT_COND(0); ++ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_1, pending); */ ++ else ++ p_Fm->fmanCtrlIntr[1].f_Isr(p_Fm->fmanCtrlIntr[1].h_SrcHandle, event); ++ } ++ if (pending & INTR_EN_REV2) ++ { ++ event = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_fcev[2]) & GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_cee[2]); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_cev[2], event); ++ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_2].guestId) ++ /*TODO IPC ISR For Fman Ctrl */ ++ ASSERT_COND(0); ++ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_2, pending); */ ++ else ++ p_Fm->fmanCtrlIntr[2].f_Isr(p_Fm->fmanCtrlIntr[2].h_SrcHandle, event); ++ } ++ if (pending & INTR_EN_REV3) ++ { ++ event = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_fcev[3]) & GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_cee[3]); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_cev[3], event); ++ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_3].guestId) ++ /*TODO IPC ISR For Fman Ctrl */ ++ ASSERT_COND(0); ++ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_2, pendin3); */ ++ else ++ p_Fm->fmanCtrlIntr[3].f_Isr(p_Fm->fmanCtrlIntr[3].h_SrcHandle, event); ++ } ++#ifdef FM_MACSEC_SUPPORT ++ if (pending & INTR_EN_MACSEC_MAC0) ++ { ++ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].guestId) ++ SendIpcIsr(p_Fm, e_FM_EV_MACSEC_MAC0, pending); ++ else ++ p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].f_Isr(p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].h_SrcHandle); ++ } ++#endif /* FM_MACSEC_SUPPORT */ ++} ++ ++t_Error FM_ErrorIsr(t_Handle h_Fm) ++{ ++#define FM_M_CALL_1G_MAC_ERR_ISR(_id) \ ++ { \ ++ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].guestId) \ ++ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id), pending); \ ++ else \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].h_SrcHandle);\ ++ } ++#define FM_M_CALL_10G_MAC_ERR_ISR(_id) \ ++ { \ ++ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].guestId) \ ++ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id), pending); \ ++ else \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].h_SrcHandle);\ ++ } ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t pending; ++ ++ SANITY_CHECK_RETURN_ERROR(h_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ /* error interrupts */ ++ pending = GET_UINT32(p_Fm->p_FmFpmRegs->fm_epi); ++ if (!pending) ++ return ERROR_CODE(E_EMPTY); ++ ++ if (pending & ERR_INTR_EN_BMI) ++ BmiErrEvent(p_Fm); ++ if (pending & ERR_INTR_EN_QMI) ++ QmiErrEvent(p_Fm); ++ if (pending & ERR_INTR_EN_FPM) ++ FpmErrEvent(p_Fm); ++ if (pending & ERR_INTR_EN_DMA) ++ DmaErrEvent(p_Fm); ++ if (pending & ERR_INTR_EN_IRAM) ++ IramErrIntr(p_Fm); ++ if (pending & ERR_INTR_EN_MURAM) ++ MuramErrIntr(p_Fm); ++ if (pending & ERR_INTR_EN_PRS) ++ p_Fm->intrMng[e_FM_EV_ERR_PRS].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_PRS].h_SrcHandle); ++ if (pending & ERR_INTR_EN_PLCR) ++ p_Fm->intrMng[e_FM_EV_ERR_PLCR].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_PLCR].h_SrcHandle); ++ if (pending & ERR_INTR_EN_KG) ++ p_Fm->intrMng[e_FM_EV_ERR_KG].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_KG].h_SrcHandle); ++ ++ /* MAC events may belong to different partitions */ ++ if (pending & ERR_INTR_EN_1G_MAC0) ++ FM_M_CALL_1G_MAC_ERR_ISR(0); ++ if (pending & ERR_INTR_EN_1G_MAC1) ++ FM_M_CALL_1G_MAC_ERR_ISR(1); ++ if (pending & ERR_INTR_EN_1G_MAC2) ++ FM_M_CALL_1G_MAC_ERR_ISR(2); ++ if (pending & ERR_INTR_EN_1G_MAC3) ++ FM_M_CALL_1G_MAC_ERR_ISR(3); ++ if (pending & ERR_INTR_EN_1G_MAC4) ++ FM_M_CALL_1G_MAC_ERR_ISR(4); ++ if (pending & ERR_INTR_EN_1G_MAC5) ++ FM_M_CALL_1G_MAC_ERR_ISR(5); ++ if (pending & ERR_INTR_EN_1G_MAC6) ++ FM_M_CALL_1G_MAC_ERR_ISR(6); ++ if (pending & ERR_INTR_EN_1G_MAC7) ++ FM_M_CALL_1G_MAC_ERR_ISR(7); ++ if (pending & ERR_INTR_EN_10G_MAC0) ++ FM_M_CALL_10G_MAC_ERR_ISR(0); ++ if (pending & ERR_INTR_EN_10G_MAC1) ++ FM_M_CALL_10G_MAC_ERR_ISR(1); ++ ++#ifdef FM_MACSEC_SUPPORT ++ if (pending & ERR_INTR_EN_MACSEC_MAC0) ++ { ++ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].guestId) ++ SendIpcIsr(p_Fm, e_FM_EV_ERR_MACSEC_MAC0, pending); ++ else ++ p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].h_SrcHandle); ++ } ++#endif /* FM_MACSEC_SUPPORT */ ++ ++ return E_OK; ++} ++ ++t_Error FM_SetPortsBandwidth(t_Handle h_Fm, t_FmPortsBandwidthParams *p_PortsBandwidth) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ int i; ++ uint8_t sum; ++ uint8_t hardwarePortId; ++ uint32_t tmpRegs[8] = {0,0,0,0,0,0,0,0}; ++ uint8_t relativePortId, shift, weight, maxPercent = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ /* check that all ports add up to 100% */ ++ sum = 0; ++ for (i=0;inumOfPorts;i++) ++ sum +=p_PortsBandwidth->portsBandwidths[i].bandwidth; ++ if (sum != 100) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Sum of ports bandwidth differ from 100%")); ++ ++ /* find highest percent */ ++ for (i=0;inumOfPorts;i++) ++ { ++ if (p_PortsBandwidth->portsBandwidths[i].bandwidth > maxPercent) ++ maxPercent = p_PortsBandwidth->portsBandwidths[i].bandwidth; ++ } ++ ++ /* calculate weight for each port */ ++ for (i=0;inumOfPorts;i++) ++ { ++ weight = (uint8_t)((p_PortsBandwidth->portsBandwidths[i].bandwidth * PORT_MAX_WEIGHT )/maxPercent); ++ /* we want even division between 1-to-PORT_MAX_WEIGHT. so if exect division ++ is not reached, we round up so that: ++ 0 until maxPercent/PORT_MAX_WEIGHT get "1" ++ maxPercent/PORT_MAX_WEIGHT+1 until (maxPercent/PORT_MAX_WEIGHT)*2 get "2" ++ ... ++ maxPercent - maxPercent/PORT_MAX_WEIGHT until maxPercent get "PORT_MAX_WEIGHT: */ ++ if ((uint8_t)((p_PortsBandwidth->portsBandwidths[i].bandwidth * PORT_MAX_WEIGHT ) % maxPercent)) ++ weight++; ++ ++ /* find the location of this port within the register */ ++ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, ++ p_PortsBandwidth->portsBandwidths[i].type, ++ p_PortsBandwidth->portsBandwidths[i].relativePortId); ++ relativePortId = (uint8_t)(hardwarePortId % 8); ++ shift = (uint8_t)(32-4*(relativePortId+1)); ++ ++ ++ if (weight > 1) ++ /* Add this port to tmpReg */ ++ /* (each 8 ports result in one register)*/ ++ tmpRegs[hardwarePortId/8] |= ((weight-1) << shift); ++ } ++ ++ for (i=0;i<8;i++) ++ if (tmpRegs[i]) ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_arb[i], tmpRegs[i]); ++ ++ return E_OK; ++} ++ ++t_Error FM_EnableRamsEcc(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ /*SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);*/ ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ t_FmIpcMsg msg; ++ t_Error err; ++ ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_ENABLE_RAM_ECC; ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ return E_OK; ++ } ++ ++ if (!p_Fm->p_FmStateStruct->internalCall) ++ p_Fm->p_FmStateStruct->explicitEnable = TRUE; ++ p_Fm->p_FmStateStruct->internalCall = FALSE; ++ ++ if (p_Fm->p_FmStateStruct->ramsEccEnable) ++ return E_OK; ++ else ++ { ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr); ++ if (tmpReg & FPM_RAM_CTL_RAMS_ECC_EN_SRC_SEL) ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, tmpReg | FPM_RAM_CTL_IRAM_ECC_EN); ++ else ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, tmpReg | (FPM_RAM_CTL_RAMS_ECC_EN | FPM_RAM_CTL_IRAM_ECC_EN)); ++ p_Fm->p_FmStateStruct->ramsEccEnable = TRUE; ++ } ++ ++ return E_OK; ++} ++ ++t_Error FM_DisableRamsEcc(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t tmpReg; ++ bool explicitDisable = FALSE; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ /*SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);*/ ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_DISABLE_RAM_ECC; ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ NULL, ++ NULL, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ return E_OK; ++ } ++ ++ if (!p_Fm->p_FmStateStruct->internalCall) ++ explicitDisable = TRUE; ++ p_Fm->p_FmStateStruct->internalCall = FALSE; ++ ++ /* if rams are already disabled, or if rams were explicitly enabled and are ++ currently called indirectly (not explicitly), ignore this call. */ ++ if (!p_Fm->p_FmStateStruct->ramsEccEnable || ++ (p_Fm->p_FmStateStruct->explicitEnable && !explicitDisable)) ++ return E_OK; ++ else ++ { ++ if (p_Fm->p_FmStateStruct->explicitEnable) ++ /* This is the case were both explicit are TRUE. ++ Turn off this flag for cases were following ramsEnable ++ routines are called */ ++ p_Fm->p_FmStateStruct->explicitEnable = FALSE; ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr); ++ if (tmpReg & FPM_RAM_CTL_RAMS_ECC_EN_SRC_SEL) ++ { ++ DBG(WARNING, ("Rams ECC is configured to be controlled through JTAG")); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, tmpReg & ~FPM_RAM_CTL_IRAM_ECC_EN); ++ } ++ else ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, tmpReg & ~(FPM_RAM_CTL_RAMS_ECC_EN | FPM_RAM_CTL_IRAM_ECC_EN)); ++ p_Fm->p_FmStateStruct->ramsEccEnable = FALSE; ++ } ++ ++ return E_OK; ++} ++ ++t_Error FM_SetException(t_Handle h_Fm, e_FmExceptions exception, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t bitMask = 0; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Fm->p_FmStateStruct->exceptions |= bitMask; ++ else ++ p_Fm->p_FmStateStruct->exceptions &= ~bitMask; ++ ++ switch (exception) ++ { ++ case (e_FM_EX_DMA_BUS_ERROR): ++ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr); ++ if (enable) ++ tmpReg |= DMA_MODE_BER; ++ else ++ tmpReg &= ~DMA_MODE_BER; ++ /* disable bus error */ ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmmr, tmpReg); ++ break; ++ case (e_FM_EX_DMA_READ_ECC): ++ case (e_FM_EX_DMA_SYSTEM_WRITE_ECC): ++ case (e_FM_EX_DMA_FM_WRITE_ECC): ++ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr); ++ if (enable) ++ tmpReg |= DMA_MODE_ECC; ++ else ++ tmpReg &= ~DMA_MODE_ECC; ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmmr, tmpReg); ++ break; ++ case (e_FM_EX_FPM_STALL_ON_TASKS): ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee); ++ if (enable) ++ tmpReg |= FPM_EV_MASK_STALL_EN; ++ else ++ tmpReg &= ~FPM_EV_MASK_STALL_EN; ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg); ++ break; ++ case (e_FM_EX_FPM_SINGLE_ECC): ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee); ++ if (enable) ++ tmpReg |= FPM_EV_MASK_SINGLE_ECC_EN; ++ else ++ tmpReg &= ~FPM_EV_MASK_SINGLE_ECC_EN; ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg); ++ break; ++ case ( e_FM_EX_FPM_DOUBLE_ECC): ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee); ++ if (enable) ++ tmpReg |= FPM_EV_MASK_DOUBLE_ECC_EN; ++ else ++ tmpReg &= ~FPM_EV_MASK_DOUBLE_ECC_EN; ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg); ++ break; ++ case ( e_FM_EX_QMI_SINGLE_ECC): ++#if defined(FM_QMI_NO_ECC_EXCEPTIONS) || defined(FM_QMI_NO_SINGLE_ECC_EXCEPTION) ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev == 4) || ++ (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("e_FM_EX_QMI_SINGLE_ECC")); ++ return E_OK; ++ } ++#endif /* FM_QMI_NO_ECC_EXCEPTIONS */ ++ tmpReg = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_ien); ++ if (enable) ++ tmpReg |= QMI_INTR_EN_SINGLE_ECC; ++ else ++ tmpReg &= ~QMI_INTR_EN_SINGLE_ECC; ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_ien, tmpReg); ++ break; ++ case (e_FM_EX_QMI_DOUBLE_ECC): ++#ifdef FM_QMI_NO_ECC_EXCEPTIONS ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev == 4) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("e_FM_EX_QMI_DOUBLE_ECC")); ++ return E_OK; ++ } ++#endif /* FM_QMI_NO_ECC_EXCEPTIONS */ ++ tmpReg = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_eien); ++ if (enable) ++ tmpReg |= QMI_ERR_INTR_EN_DOUBLE_ECC; ++ else ++ tmpReg &= ~QMI_ERR_INTR_EN_DOUBLE_ECC; ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eien, tmpReg); ++ break; ++ case (e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID): ++ tmpReg = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_eien); ++ if (enable) ++ tmpReg |= QMI_ERR_INTR_EN_DEQ_FROM_DEF; ++ else ++ tmpReg &= ~QMI_ERR_INTR_EN_DEQ_FROM_DEF; ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eien, tmpReg); ++ break; ++ case (e_FM_EX_BMI_LIST_RAM_ECC): ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier); ++ if (enable) ++ tmpReg |= BMI_ERR_INTR_EN_LIST_RAM_ECC; ++ else ++ tmpReg &= ~BMI_ERR_INTR_EN_LIST_RAM_ECC; ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier, tmpReg); ++ break; ++ case (e_FM_EX_BMI_STORAGE_PROFILE_ECC): ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier); ++ if (enable) ++ tmpReg |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC; ++ else ++ tmpReg &= ~BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC; ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier, tmpReg); ++ break; ++ case (e_FM_EX_BMI_STATISTICS_RAM_ECC): ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier); ++ if (enable) ++ tmpReg |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC; ++ else ++ tmpReg &= ~BMI_ERR_INTR_EN_STATISTICS_RAM_ECC; ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier, tmpReg); ++ break; ++ case (e_FM_EX_BMI_DISPATCH_RAM_ECC): ++ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier); ++ if (enable) ++ { ++#ifdef FM_NO_DISPATCH_RAM_ECC ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("e_FM_EX_BMI_DISPATCH_RAM_ECC")); ++ return E_OK; ++ } ++#endif /* FM_NO_DISPATCH_RAM_ECC */ ++ tmpReg |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC; ++ } ++ else ++ tmpReg &= ~BMI_ERR_INTR_EN_DISPATCH_RAM_ECC; ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier, tmpReg); ++ break; ++ case (e_FM_EX_IRAM_ECC): ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rie); ++ if (enable) ++ { ++ /* enable ECC if not enabled */ ++ FmEnableRamsEcc(p_Fm); ++ /* enable ECC interrupts */ ++ tmpReg |= FPM_IRAM_ECC_ERR_EX_EN; ++ } ++ else ++ { ++ /* ECC mechanism may be disabled, depending on driver status */ ++ FmDisableRamsEcc(p_Fm); ++ tmpReg &= ~FPM_IRAM_ECC_ERR_EX_EN; ++ } ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rie, tmpReg); ++ break; ++ ++ case (e_FM_EX_MURAM_ECC): ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rie); ++ if (enable) ++ { ++ /* enable ECC if not enabled */ ++ FmEnableRamsEcc(p_Fm); ++ /* enable ECC interrupts */ ++ tmpReg |= FPM_MURAM_ECC_ERR_EX_EN; ++ } ++ else ++ { ++ /* ECC mechanism may be disabled, depending on driver status */ ++ FmDisableRamsEcc(p_Fm); ++ tmpReg &= ~FPM_MURAM_ECC_ERR_EX_EN; ++ } ++ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rie, tmpReg); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++t_Error FM_GetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ p_FmRevisionInfo->majorRev = p_Fm->p_FmStateStruct->revInfo.majorRev; ++ p_FmRevisionInfo->minorRev = p_Fm->p_FmStateStruct->revInfo.minorRev; ++ ++ return E_OK; ++} ++ ++t_Error FM_GetFmanCtrlCodeRevision(t_Handle h_Fm, t_FmCtrlCodeRevisionInfo *p_RevisionInfo) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_FMIramRegs *p_Iram; ++ uint32_t revInfo; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_RevisionInfo, E_NULL_POINTER); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ t_FmIpcFmanCtrlCodeRevisionInfo ipcRevInfo; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_FMAN_CTRL_CODE_REV; ++ replyLength = sizeof(uint32_t) + sizeof(t_FmCtrlCodeRevisionInfo); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmCtrlCodeRevisionInfo))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ memcpy((uint8_t*)&ipcRevInfo, reply.replyBody, sizeof(t_FmCtrlCodeRevisionInfo)); ++ p_RevisionInfo->packageRev = ipcRevInfo.packageRev; ++ p_RevisionInfo->majorRev = ipcRevInfo.majorRev; ++ p_RevisionInfo->minorRev = ipcRevInfo.minorRev; ++ return (t_Error)(reply.error); ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); ++ WRITE_UINT32(p_Iram->iadd, 0x4); ++ while (GET_UINT32(p_Iram->iadd) != 0x4) ; ++ revInfo = GET_UINT32(p_Iram->idata); ++ p_RevisionInfo->packageRev = (uint16_t)((revInfo & 0xFFFF0000) >> 16); ++ p_RevisionInfo->majorRev = (uint8_t)((revInfo & 0x0000FF00) >> 8); ++ p_RevisionInfo->minorRev = (uint8_t)(revInfo & 0x000000FF); ++ ++ return E_OK; ++} ++ ++uint32_t FM_GetCounter(t_Handle h_Fm, e_FmCounters counter) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_Error err; ++ uint32_t counterValue; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_Fm->p_FmDriverParam, E_INVALID_STATE, 0); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength, outCounter; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_COUNTER; ++ memcpy(msg.msgBody, (uint8_t *)&counter, sizeof(uint32_t)); ++ replyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) +sizeof(counterValue), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return 0; ++ } ++ if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return 0; ++ } ++ ++ memcpy((uint8_t*)&outCounter, reply.replyBody, sizeof(uint32_t)); ++ return outCounter; ++ } ++ else if (!p_Fm->baseAddr) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!")); ++ return 0; ++ } ++ ++ /* When applicable (when there is an 'enable counters' bit, ++ check that counters are enabled */ ++ switch (counter) ++ { ++ case (e_FM_COUNTERS_DEQ_1): ++ case (e_FM_COUNTERS_DEQ_2): ++ case (e_FM_COUNTERS_DEQ_3): ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Requested counter not supported")); ++ return 0; ++ } ++ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME): ++ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME): ++ case (e_FM_COUNTERS_DEQ_0): ++ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT): ++ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT): ++ case (e_FM_COUNTERS_DEQ_FROM_FD): ++ case (e_FM_COUNTERS_DEQ_CONFIRM): ++ if (!(GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc) & QMI_CFG_EN_COUNTERS)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ return 0; ++ } ++ break; ++ default: ++ break; ++ } ++ ++ switch (counter) ++ { ++ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME): ++ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_etfc); ++ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME): ++ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dtfc); ++ case (e_FM_COUNTERS_DEQ_0): ++ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc0); ++ case (e_FM_COUNTERS_DEQ_1): ++ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc1); ++ case (e_FM_COUNTERS_DEQ_2): ++ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc2); ++ case (e_FM_COUNTERS_DEQ_3): ++ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc3); ++ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT): ++ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dfdc); ++ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT): ++ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dfcc); ++ case (e_FM_COUNTERS_DEQ_FROM_FD): ++ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dffc); ++ case (e_FM_COUNTERS_DEQ_CONFIRM): ++ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dcc); ++ break; ++ } ++ /* should never get here */ ++ ASSERT_COND(FALSE); ++ return 0; ++} ++ ++t_Error FM_ModifyCounter(t_Handle h_Fm, e_FmCounters counter, uint32_t val) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ /* When applicable (when there is an 'enable counters' bit, ++ check that counters are enabled */ ++ switch (counter) ++ { ++ case (e_FM_COUNTERS_DEQ_1): ++ case (e_FM_COUNTERS_DEQ_2): ++ case (e_FM_COUNTERS_DEQ_3): ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Requested counter not supported")); ++ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME): ++ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME): ++ case (e_FM_COUNTERS_DEQ_0): ++ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT): ++ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT): ++ case (e_FM_COUNTERS_DEQ_FROM_FD): ++ case (e_FM_COUNTERS_DEQ_CONFIRM): ++ if (!(GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc) & QMI_CFG_EN_COUNTERS)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ break; ++ default: ++ break; ++ } ++ ++ /* Set counter */ ++ switch (counter) ++ { ++ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME): ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_etfc, val); ++ break; ++ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME): ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dtfc, val); ++ break; ++ case (e_FM_COUNTERS_DEQ_0): ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc0, val); ++ break; ++ case (e_FM_COUNTERS_DEQ_1): ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc1, val); ++ break; ++ case (e_FM_COUNTERS_DEQ_2): ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc2, val); ++ break; ++ case (e_FM_COUNTERS_DEQ_3): ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc3, val); ++ break; ++ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT): ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dfdc, val); ++ break; ++ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT): ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dfcc, val); ++ break; ++ case (e_FM_COUNTERS_DEQ_FROM_FD): ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dffc, val); ++ break; ++ case (e_FM_COUNTERS_DEQ_CONFIRM): ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dcc, val); ++ break; ++ default: ++ break; ++ } ++ ++ return E_OK; ++} ++ ++void FM_SetDmaEmergency(t_Handle h_Fm, e_FmDmaMuramPort muramPort, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t bitMask; ++ ++ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ bitMask = (uint32_t)((muramPort==e_FM_DMA_MURAM_PORT_WRITE) ? DMA_MODE_EMERGENCY_WRITE : DMA_MODE_EMERGENCY_READ); ++ ++ if (enable) ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmmr, GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr) | bitMask); ++ else /* disable */ ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmmr, GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr) & ~bitMask); ++ ++ return; ++} ++ ++void FM_SetDmaExtBusPri(t_Handle h_Fm, e_FmDmaExtBusPri pri) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmmr, GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr) | ((uint32_t)pri << DMA_MODE_BUS_PRI_SHIFT) ); ++ ++ return; ++} ++ ++void FM_GetDmaStatus(t_Handle h_Fm, t_FmDmaStatus *p_FmDmaStatus) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcDmaStatus ipcDmaStatus; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ t_Error err; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_DMA_STAT; ++ replyLength = sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return; ++ } ++ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus))) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return; ++ } ++ memcpy((uint8_t*)&ipcDmaStatus, reply.replyBody, sizeof(t_FmIpcDmaStatus)); ++ ++ p_FmDmaStatus->cmqNotEmpty = (bool)ipcDmaStatus.boolCmqNotEmpty; /**< Command queue is not empty */ ++ p_FmDmaStatus->busError = (bool)ipcDmaStatus.boolBusError; /**< Bus error occurred */ ++ p_FmDmaStatus->readBufEccError = (bool)ipcDmaStatus.boolReadBufEccError; /**< Double ECC error on buffer Read */ ++ p_FmDmaStatus->writeBufEccSysError =(bool)ipcDmaStatus.boolWriteBufEccSysError; /**< Double ECC error on buffer write from system side */ ++ p_FmDmaStatus->writeBufEccFmError = (bool)ipcDmaStatus.boolWriteBufEccFmError; /**< Double ECC error on buffer write from FM side */ ++ p_FmDmaStatus->singlePortEccError = (bool)ipcDmaStatus.boolSinglePortEccError; /**< Double ECC error on buffer write from FM side */ ++ return; ++ } ++ else if (!p_Fm->baseAddr) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ return; ++ } ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmsr); ++ ++ p_FmDmaStatus->cmqNotEmpty = (bool)(tmpReg & DMA_STATUS_CMD_QUEUE_NOT_EMPTY); ++ p_FmDmaStatus->busError = (bool)(tmpReg & DMA_STATUS_BUS_ERR); ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ p_FmDmaStatus->singlePortEccError = (bool)(tmpReg & DMA_STATUS_FM_SPDAT_ECC); ++ else ++ { ++ p_FmDmaStatus->readBufEccError = (bool)(tmpReg & DMA_STATUS_READ_ECC); ++ p_FmDmaStatus->writeBufEccSysError = (bool)(tmpReg & DMA_STATUS_SYSTEM_WRITE_ECC); ++ p_FmDmaStatus->writeBufEccFmError = (bool)(tmpReg & DMA_STATUS_FM_WRITE_ECC); ++ } ++} ++ ++void FM_Resume(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee); ++ /* clear tmpReg event bits in order not to clear standing events */ ++ tmpReg &= ~(FPM_EV_MASK_DOUBLE_ECC | FPM_EV_MASK_STALL | FPM_EV_MASK_SINGLE_ECC); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg | FPM_EV_MASK_RELEASE_FM); ++} ++ ++t_Error FM_GetSpecialOperationCoding(t_Handle h_Fm, ++ fmSpecialOperations_t spOper, ++ uint8_t *p_SpOperCoding) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_FmCtrlCodeRevisionInfo revInfo; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_SpOperCoding, E_NULL_POINTER); ++ ++ if (!spOper) ++ { ++ *p_SpOperCoding = 0; ++ return E_OK; ++ } ++ ++ if ((err = FM_GetFmanCtrlCodeRevision(p_Fm, &revInfo)) != E_OK) ++ { ++ DBG(WARNING, ("FM in guest-mode without IPC, can't validate firmware revision.")); ++ revInfo.packageRev = IP_OFFLOAD_PACKAGE_NUMBER; ++ } ++ else if (revInfo.packageRev != IP_OFFLOAD_PACKAGE_NUMBER) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Fman ctrl code package")); ++ ++ if (revInfo.packageRev == IP_OFFLOAD_PACKAGE_NUMBER) ++ { ++ switch (spOper) ++ { ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_IPSEC_MANIP): ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_IPSEC_MANIP|FM_SP_OP_RPD): ++ *p_SpOperCoding = 5; ++ break; ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_MANIP): ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_MANIP|FM_SP_OP_RPD): ++ *p_SpOperCoding = 6; ++ break; ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_RPD): ++ *p_SpOperCoding = 3; ++ break; ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN): ++ *p_SpOperCoding = 1; ++ break; ++ case (FM_SP_OP_IPSEC|FM_SP_OP_RPD): ++ *p_SpOperCoding = 4; ++ break; ++ case (FM_SP_OP_IPSEC): ++ *p_SpOperCoding = 2; ++ break; ++ case (FM_SP_OP_DCL4C): ++ *p_SpOperCoding = 7; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ } ++ } ++ return E_OK; ++} ++ ++t_Error FM_CtrlMonStart(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ t_FmTrbRegs *p_MonRegs; ++ uint8_t i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ for (i = 0; i < FM_NUM_OF_CTRL; i++) ++ { ++ p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(i)); ++ ++ /* Reset control registers */ ++ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_RESET); ++ WRITE_UINT32(p_MonRegs->tcrl, TRB_TCRL_RESET); ++ ++ /* Configure: counter #1 counts all stalls in risc - ldsched stall ++ counter #2 counts all stalls in risc - other stall*/ ++ WRITE_UINT32(p_MonRegs->tcrl, TRB_TCRL_RESET | TRB_TCRL_UTIL); ++ ++ /* Enable monitoring */ ++ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_ENABLE_COUNTERS); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FM_CtrlMonStop(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ t_FmTrbRegs *p_MonRegs; ++ uint8_t i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ for (i = 0; i < FM_NUM_OF_CTRL; i++) ++ { ++ p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(i)); ++ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_DISABLE_COUNTERS); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FM_CtrlMonGetCounters(t_Handle h_Fm, uint8_t fmCtrlIndex, t_FmCtrlMon *p_Mon) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ t_FmTrbRegs *p_MonRegs; ++ uint64_t clkCnt, utilValue, effValue; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ SANITY_CHECK_RETURN_ERROR(p_Mon, E_NULL_POINTER); ++ ++ if (fmCtrlIndex >= FM_NUM_OF_CTRL) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FM Controller index")); ++ ++ p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(fmCtrlIndex)); ++ ++ clkCnt = (uint64_t) ++ ((uint64_t)GET_UINT32(p_MonRegs->tpcch) << 32 | GET_UINT32(p_MonRegs->tpccl)); ++ ++ utilValue = (uint64_t) ++ ((uint64_t)GET_UINT32(p_MonRegs->tpc1h) << 32 | GET_UINT32(p_MonRegs->tpc1l)); ++ ++ effValue = (uint64_t) ++ ((uint64_t)GET_UINT32(p_MonRegs->tpc2h) << 32 | GET_UINT32(p_MonRegs->tpc2l)); ++ ++ p_Mon->percentCnt[0] = (uint8_t)((clkCnt - utilValue) * 100 / clkCnt); ++ if (clkCnt != utilValue) ++ p_Mon->percentCnt[1] = (uint8_t)(((clkCnt - utilValue) - effValue) * 100 / (clkCnt - utilValue)); ++ else ++ p_Mon->percentCnt[1] = 0; ++ ++ return E_OK; ++} ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++t_Error FM_DumpRegs(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ uint8_t i,j = 0; ++ ++ DECLARE_DUMP; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(((p_Fm->guestId == NCSW_MASTER_ID) || ++ p_Fm->baseAddr), E_INVALID_OPERATION); ++ ++ DUMP_SUBTITLE(("\n")); ++ ++ DUMP_TITLE(p_Fm->p_FmFpmRegs, ("FM-FPM Regs")); ++ ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tnc); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_prc); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_brkc); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_mxd); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_dis1); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_dis2); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_epi); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_rie); ++ ++ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_fcev, ("fmfp_fcev")); ++ DUMP_SUBSTRUCT_ARRAY(i, 4) ++ { ++ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_fcev[i], sizeof(uint32_t)); ++ } ++ ++ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_cee, ("fmfp_cee")); ++ DUMP_SUBSTRUCT_ARRAY(i, 4) ++ { ++ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_cee[i], sizeof(uint32_t)); ++ } ++ ++ DUMP_SUBTITLE(("\n")); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tsc1); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tsc2); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tsp); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tsf); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_rcr); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_extc); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_ext1); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_ext2); ++ ++ DUMP_SUBTITLE(("\n")); ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_dra, 0); ++ CORE_MemoryBarrier(); ++ for (j=0; j<128; j++) ++ { ++ DUMP_TITLE(j, ("fmfp_dra")); ++ DUMP_SUBSTRUCT_ARRAY(i, 4) ++ { ++ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_drd[i], sizeof(uint32_t)); ++ } ++ DUMP_TITLE(j, ("fmfp_ts")); ++ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_ts[j], sizeof(uint32_t)); ++ } ++ ++ DUMP_SUBTITLE(("\n")); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_ip_rev_1); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_ip_rev_2); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_rstc); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_cld); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_npi); ++ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_ee); ++ ++ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_cev, ("fmfp_cev")); ++ DUMP_SUBSTRUCT_ARRAY(i, 4) ++ { ++ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_cev[i], sizeof(uint32_t)); ++ } ++ ++ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_ps, ("fmfp_ps")); ++ DUMP_SUBSTRUCT_ARRAY(i, 64) ++ { ++ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_ps[i], sizeof(uint32_t)); ++ } ++ ++ DUMP_TITLE(p_Fm->p_FmDmaRegs, ("FM-DMA Regs")); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmsr); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmemsr); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmmr); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmtr); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmhy); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmsetr); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmtah); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmtal); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmtcid); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmra); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmrd); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmwcr); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmebcr); ++ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmdcr); ++ ++ DUMP_TITLE(&p_Fm->p_FmDmaRegs->fmdmplr, ("fmdmplr")); ++ ++ DUMP_SUBSTRUCT_ARRAY(i, FM_MAX_NUM_OF_HW_PORT_IDS/2) ++ { ++ DUMP_MEMORY(&p_Fm->p_FmDmaRegs->fmdmplr[i], sizeof(uint32_t)); ++ } ++ ++ DUMP_TITLE(p_Fm->p_FmBmiRegs, ("FM-BMI COMMON Regs")); ++ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_init); ++ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_cfg1); ++ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_cfg2); ++ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_ievr); ++ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_ier); ++ ++ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_arb, ("fmbm_arb")); ++ DUMP_SUBSTRUCT_ARRAY(i, 8) ++ { ++ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_arb[i], sizeof(uint32_t)); ++ } ++ ++ DUMP_TITLE(p_Fm->p_FmQmiRegs, ("FM-QMI COMMON Regs")); ++ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_gc); ++ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_eie); ++ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_eien); ++ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_eif); ++ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_ie); ++ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_ien); ++ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_if); ++ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_gs); ++ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_etfc); ++ ++ return E_OK; ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ ++ ++/****************************************************/ ++/* Hidden-DEBUG Only API */ ++/****************************************************/ ++ ++t_Error FM_ForceIntr (t_Handle h_Fm, e_FmExceptions exception) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ ++ switch (exception) ++ { ++ case e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eif, QMI_ERR_INTR_EN_DEQ_FROM_DEF); ++ break; ++ case e_FM_EX_QMI_SINGLE_ECC: ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("e_FM_EX_QMI_SINGLE_ECC not supported on this integration.")); ++ ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_SINGLE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_if, QMI_INTR_EN_SINGLE_ECC); ++ break; ++ case e_FM_EX_QMI_DOUBLE_ECC: ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DOUBLE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eif, QMI_ERR_INTR_EN_DOUBLE_ECC); ++ break; ++ case e_FM_EX_BMI_LIST_RAM_ECC: ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_LIST_RAM_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ifr, BMI_ERR_INTR_EN_LIST_RAM_ECC); ++ break; ++ case e_FM_EX_BMI_STORAGE_PROFILE_ECC: ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STORAGE_PROFILE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ifr, BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC); ++ break; ++ case e_FM_EX_BMI_STATISTICS_RAM_ECC: ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STATISTICS_RAM_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ifr, BMI_ERR_INTR_EN_STATISTICS_RAM_ECC); ++ break; ++ case e_FM_EX_BMI_DISPATCH_RAM_ECC: ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_DISPATCH_RAM_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ifr, BMI_ERR_INTR_EN_DISPATCH_RAM_ECC); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception may not be forced")); ++ } ++ ++ return E_OK; ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/fm.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/fm.h +new file mode 100644 +index 0000000..4f3ad00 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/fm.h +@@ -0,0 +1,897 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm.h ++ ++ @Description FM internal structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_H ++#define __FM_H ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "fm_ext.h" ++#include "fm_ipc.h" ++ ++ ++#define __ERR_MODULE__ MODULE_FM ++ ++#define FM_MAX_NUM_OF_HW_PORT_IDS 64 ++#define FM_MAX_NUM_OF_GUESTS 100 ++ ++/**************************************************************************//** ++ @Description Exceptions ++*//***************************************************************************/ ++#define FM_EX_DMA_BUS_ERROR 0x80000000 /**< DMA bus error. */ ++#define FM_EX_DMA_READ_ECC 0x40000000 ++#define FM_EX_DMA_SYSTEM_WRITE_ECC 0x20000000 ++#define FM_EX_DMA_FM_WRITE_ECC 0x10000000 ++#define FM_EX_FPM_STALL_ON_TASKS 0x08000000 /**< Stall of tasks on FPM */ ++#define FM_EX_FPM_SINGLE_ECC 0x04000000 /**< Single ECC on FPM */ ++#define FM_EX_FPM_DOUBLE_ECC 0x02000000 ++#define FM_EX_QMI_SINGLE_ECC 0x01000000 /**< Single ECC on FPM */ ++#define FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID 0x00800000 /**< Dequeu from default queue id */ ++#define FM_EX_QMI_DOUBLE_ECC 0x00400000 ++#define FM_EX_BMI_LIST_RAM_ECC 0x00200000 ++#define FM_EX_BMI_STORAGE_PROFILE_ECC 0x00100000 ++#define FM_EX_BMI_STATISTICS_RAM_ECC 0x00080000 ++#define FM_EX_IRAM_ECC 0x00040000 ++#define FM_EX_MURAM_ECC 0x00020000 ++#define FM_EX_BMI_DISPATCH_RAM_ECC 0x00010000 ++#define FM_EX_DMA_SINGLE_PORT_ECC 0x00008000 ++ ++#define GET_EXCEPTION_FLAG(bitMask, exception) \ ++switch (exception){ \ ++ case e_FM_EX_DMA_BUS_ERROR: \ ++ bitMask = FM_EX_DMA_BUS_ERROR; break; \ ++ case e_FM_EX_DMA_SINGLE_PORT_ECC: \ ++ bitMask = FM_EX_DMA_SINGLE_PORT_ECC; break; \ ++ case e_FM_EX_DMA_READ_ECC: \ ++ bitMask = FM_EX_DMA_READ_ECC; break; \ ++ case e_FM_EX_DMA_SYSTEM_WRITE_ECC: \ ++ bitMask = FM_EX_DMA_SYSTEM_WRITE_ECC; break; \ ++ case e_FM_EX_DMA_FM_WRITE_ECC: \ ++ bitMask = FM_EX_DMA_FM_WRITE_ECC; break; \ ++ case e_FM_EX_FPM_STALL_ON_TASKS: \ ++ bitMask = FM_EX_FPM_STALL_ON_TASKS; break; \ ++ case e_FM_EX_FPM_SINGLE_ECC: \ ++ bitMask = FM_EX_FPM_SINGLE_ECC; break; \ ++ case e_FM_EX_FPM_DOUBLE_ECC: \ ++ bitMask = FM_EX_FPM_DOUBLE_ECC; break; \ ++ case e_FM_EX_QMI_SINGLE_ECC: \ ++ bitMask = FM_EX_QMI_SINGLE_ECC; break; \ ++ case e_FM_EX_QMI_DOUBLE_ECC: \ ++ bitMask = FM_EX_QMI_DOUBLE_ECC; break; \ ++ case e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: \ ++ bitMask = FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID; break; \ ++ case e_FM_EX_BMI_LIST_RAM_ECC: \ ++ bitMask = FM_EX_BMI_LIST_RAM_ECC; break; \ ++ case e_FM_EX_BMI_STORAGE_PROFILE_ECC: \ ++ bitMask = FM_EX_BMI_STORAGE_PROFILE_ECC; break; \ ++ case e_FM_EX_BMI_STATISTICS_RAM_ECC: \ ++ bitMask = FM_EX_BMI_STATISTICS_RAM_ECC; break; \ ++ case e_FM_EX_BMI_DISPATCH_RAM_ECC: \ ++ bitMask = FM_EX_BMI_DISPATCH_RAM_ECC; break; \ ++ case e_FM_EX_IRAM_ECC: \ ++ bitMask = FM_EX_IRAM_ECC; break; \ ++ case e_FM_EX_MURAM_ECC: \ ++ bitMask = FM_EX_MURAM_ECC; break; \ ++ default: bitMask = 0;break; \ ++} ++ ++#define GET_FM_MODULE_EVENT(_mod, _id, _intrType, _event) \ ++ switch (_mod) { \ ++ case e_FM_MOD_PRS: \ ++ if (_id) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_PRS : e_FM_EV_PRS; \ ++ break; \ ++ case e_FM_MOD_KG: \ ++ if (_id) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_KG : e_FM_EV_DUMMY_LAST; \ ++ break; \ ++ case e_FM_MOD_PLCR: \ ++ if (_id) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_PLCR : e_FM_EV_PLCR; \ ++ break; \ ++ case e_FM_MOD_TMR: \ ++ if (_id) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_DUMMY_LAST : e_FM_EV_TMR; \ ++ break; \ ++ case e_FM_MOD_10G_MAC: \ ++ if (_id >= FM_MAX_NUM_OF_10G_MACS) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? (e_FM_EV_ERR_10G_MAC0 + _id) : (e_FM_EV_10G_MAC0 + _id); \ ++ break; \ ++ case e_FM_MOD_1G_MAC: \ ++ if (_id >= FM_MAX_NUM_OF_1G_MACS) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? (e_FM_EV_ERR_1G_MAC0 + _id) : (e_FM_EV_1G_MAC0 + _id); \ ++ break; \ ++ case e_FM_MOD_MACSEC: \ ++ switch (_id){ \ ++ case (0): _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_MACSEC_MAC0:e_FM_EV_MACSEC_MAC0; \ ++ break; \ ++ } \ ++ break; \ ++ case e_FM_MOD_FMAN_CTRL: \ ++ if (_intrType == e_FM_INTR_TYPE_ERR) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (e_FM_EV_FMAN_CTRL_0 + _id); \ ++ break; \ ++ default: _event = e_FM_EV_DUMMY_LAST; \ ++ break; \ ++ } ++ ++/**************************************************************************//** ++ @Description defaults ++*//***************************************************************************/ ++#define DEFAULT_exceptions (FM_EX_DMA_BUS_ERROR |\ ++ FM_EX_DMA_READ_ECC |\ ++ FM_EX_DMA_SYSTEM_WRITE_ECC |\ ++ FM_EX_DMA_FM_WRITE_ECC |\ ++ FM_EX_FPM_STALL_ON_TASKS |\ ++ FM_EX_FPM_SINGLE_ECC |\ ++ FM_EX_FPM_DOUBLE_ECC |\ ++ FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID|\ ++ FM_EX_BMI_LIST_RAM_ECC |\ ++ FM_EX_BMI_STORAGE_PROFILE_ECC |\ ++ FM_EX_BMI_STATISTICS_RAM_ECC |\ ++ FM_EX_IRAM_ECC |\ ++ FM_EX_MURAM_ECC |\ ++ FM_EX_BMI_DISPATCH_RAM_ECC |\ ++ FM_EX_QMI_DOUBLE_ECC |\ ++ FM_EX_QMI_SINGLE_ECC) ++ ++ ++#define DEFAULT_totalFifoSize(major) \ ++ (((major == 2) || (major == 5)) ? \ ++ (100*KILOBYTE) : ((major == 6) ? \ ++ (288*KILOBYTE) : ((major == 4) ? \ ++ (46*KILOBYTE) : (122*KILOBYTE)))) ++ ++#define DEFAULT_eccEnable FALSE ++#define DEFAULT_dispLimit 0 ++#define DEFAULT_prsDispTh 16 ++#define DEFAULT_plcrDispTh 16 ++#define DEFAULT_kgDispTh 16 ++#define DEFAULT_bmiDispTh 16 ++#define DEFAULT_qmiEnqDispTh 16 ++#define DEFAULT_qmiDeqDispTh 16 ++#define DEFAULT_fmCtl1DispTh 16 ++#define DEFAULT_fmCtl2DispTh 16 ++#define DEFAULT_cacheOverride e_FM_DMA_NO_CACHE_OR ++#ifdef FM_PEDANTIC_DMA ++#define DEFAULT_aidOverride TRUE ++#else ++#define DEFAULT_aidOverride FALSE ++#endif /* FM_PEDANTIC_DMA */ ++#define DEFAULT_aidMode e_FM_DMA_AID_OUT_TNUM ++#define DEFAULT_dmaStopOnBusError FALSE ++#define DEFAULT_stopAtBusError FALSE ++#define DEFAULT_axiDbgNumOfBeats 1 ++#define DEFAULT_dmaCamNumOfEntries 32 ++#define DEFAULT_dmaCommQLow ((DMA_THRESH_MAX_COMMQ+1)/2) ++#define DEFAULT_dmaCommQHigh ((DMA_THRESH_MAX_COMMQ+1)*3/4) ++#define DEFAULT_dmaReadIntBufLow ((DMA_THRESH_MAX_BUF+1)/2) ++#define DEFAULT_dmaReadIntBufHigh ((DMA_THRESH_MAX_BUF+1)*3/4) ++#define DEFAULT_dmaWriteIntBufLow ((DMA_THRESH_MAX_BUF+1)/2) ++#define DEFAULT_dmaWriteIntBufHigh ((DMA_THRESH_MAX_BUF+1)*3/4) ++#define DEFAULT_dmaSosEmergency 0 ++#define DEFAULT_dmaDbgCntMode e_FM_DMA_DBG_NO_CNT ++#define DEFAULT_catastrophicErr e_FM_CATASTROPHIC_ERR_STALL_PORT ++#define DEFAULT_dmaErr e_FM_DMA_ERR_CATASTROPHIC ++#define DEFAULT_resetOnInit FALSE ++#define DEFAULT_haltOnExternalActivation FALSE /* do not change! if changed, must be disabled for rev1 ! */ ++#define DEFAULT_haltOnUnrecoverableEccError FALSE /* do not change! if changed, must be disabled for rev1 ! */ ++#define DEFAULT_externalEccRamsEnable FALSE ++#define DEFAULT_VerifyUcode FALSE ++#define DEFAULT_tnumAgingPeriod 0 ++#define DEFAULT_dmaWatchdog 0 /* disabled */ ++ ++#define FM_TIMESTAMP_1_USEC_BIT 8 ++ ++/**************************************************************************//** ++ @Collection Defines used for enabling/disabling FM interrupts ++ @{ ++*//***************************************************************************/ ++#define ERR_INTR_EN_DMA 0x00010000 ++#define ERR_INTR_EN_FPM 0x80000000 ++#define ERR_INTR_EN_BMI 0x00800000 ++#define ERR_INTR_EN_QMI 0x00400000 ++#define ERR_INTR_EN_PRS 0x00200000 ++#define ERR_INTR_EN_KG 0x00100000 ++#define ERR_INTR_EN_PLCR 0x00080000 ++#define ERR_INTR_EN_MURAM 0x00040000 ++#define ERR_INTR_EN_IRAM 0x00020000 ++#define ERR_INTR_EN_10G_MAC0 0x00008000 ++#define ERR_INTR_EN_10G_MAC1 0x00000040 ++#define ERR_INTR_EN_1G_MAC0 0x00004000 ++#define ERR_INTR_EN_1G_MAC1 0x00002000 ++#define ERR_INTR_EN_1G_MAC2 0x00001000 ++#define ERR_INTR_EN_1G_MAC3 0x00000800 ++#define ERR_INTR_EN_1G_MAC4 0x00000400 ++#define ERR_INTR_EN_1G_MAC5 0x00000200 ++#define ERR_INTR_EN_1G_MAC6 0x00000100 ++#define ERR_INTR_EN_1G_MAC7 0x00000080 ++#define ERR_INTR_EN_MACSEC_MAC0 0x00000001 ++ ++#define INTR_EN_QMI 0x40000000 ++#define INTR_EN_PRS 0x20000000 ++#define INTR_EN_PLCR 0x08000000 ++#define INTR_EN_1G_MAC0 0x00080000 ++#define INTR_EN_1G_MAC1 0x00040000 ++#define INTR_EN_1G_MAC2 0x00020000 ++#define INTR_EN_1G_MAC3 0x00010000 ++#define INTR_EN_1G_MAC4 0x00000040 ++#define INTR_EN_1G_MAC5 0x00000020 ++#define INTR_EN_1G_MAC6 0x00000008 ++#define INTR_EN_1G_MAC7 0x00000002 ++#define INTR_EN_10G_MAC0 0x00200000 ++#define INTR_EN_10G_MAC1 0x00100000 ++#define INTR_EN_REV0 0x00008000 ++#define INTR_EN_REV1 0x00004000 ++#define INTR_EN_REV2 0x00002000 ++#define INTR_EN_REV3 0x00001000 ++#define INTR_EN_BRK 0x00000080 ++#define INTR_EN_TMR 0x01000000 ++#define INTR_EN_MACSEC_MAC0 0x00000001 ++/* @} */ ++ ++/**************************************************************************//** ++ @Description Modules registers offsets ++*//***************************************************************************/ ++#define FM_MM_MURAM 0x00000000 ++#define FM_MM_BMI 0x00080000 ++#define FM_MM_QMI 0x00080400 ++#define FM_MM_PRS 0x000c7000 ++#define FM_MM_KG 0x000C1000 ++#define FM_MM_DMA 0x000C2000 ++#define FM_MM_FPM 0x000C3000 ++#define FM_MM_PLCR 0x000C0000 ++#define FM_MM_IMEM 0x000C4000 ++#define FM_MM_CGP 0x000DB000 ++#define FM_MM_TRB(i) (0x000D0200 + 0x400 * (i)) ++#if (DPAA_VERSION >= 11) ++#define FM_MM_SP 0x000dc000 ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++/**************************************************************************//** ++ @Description Memory Mapped Registers ++*//***************************************************************************/ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++typedef _Packed struct ++{ ++ volatile uint32_t fmfp_tnc; /**< FPM TNUM Control */ ++ volatile uint32_t fmfp_prc; /**< FPM Port_ID FmCtl Association */ ++ volatile uint32_t fmfp_brkc; /**< FPM Breakpoint Control */ ++ volatile uint32_t fmfp_mxd; /**< FPM Maximum dispatch */ ++ volatile uint32_t fmfp_dis1; /**< FPM Dispatch Thresholds1 */ ++ volatile uint32_t fmfp_dis2; /**< FPM Dispatch Thresholds2 */ ++ volatile uint32_t fm_epi; /**< FM Error Pending Interrupts */ ++ volatile uint32_t fm_rie; /**< FM Error Interrupt Enable */ ++ volatile uint32_t fmfp_fcev[4]; /**< FPM FMan-Controller Event 1-4 */ ++ volatile uint8_t res1[16]; /**< reserved */ ++ volatile uint32_t fmfp_cee[4]; /**< PM FMan-Controller Event 1-4 */ ++ volatile uint8_t res2[16]; /**< reserved */ ++ volatile uint32_t fmfp_tsc1; /**< FPM TimeStamp Control1 */ ++ volatile uint32_t fmfp_tsc2; /**< FPM TimeStamp Control2 */ ++ volatile uint32_t fmfp_tsp; /**< FPM Time Stamp */ ++ volatile uint32_t fmfp_tsf; /**< FPM Time Stamp Fraction */ ++ volatile uint32_t fm_rcr; /**< FM Rams Control */ ++ volatile uint32_t fmfp_extc; /**< FPM External Requests Control */ ++ volatile uint32_t fmfp_ext1; /**< FPM External Requests Config1 */ ++ volatile uint32_t fmfp_ext2; /**< FPM External Requests Config2 */ ++ volatile uint32_t fmfp_drd[4]; /**< FPM Data_Ram Data 0-3 */ ++ volatile uint8_t res3[48]; /**< reserved */ ++ volatile uint32_t fmfp_dra; /**< FPM Data Ram Access */ ++ volatile uint32_t fm_ip_rev_1; /**< FM IP Block Revision 1 */ ++ volatile uint32_t fm_ip_rev_2; /**< FM IP Block Revision 2 */ ++ volatile uint32_t fm_rstc; /**< FM Reset Command */ ++ volatile uint32_t fm_cld; /**< FM Classifier Debug */ ++ volatile uint32_t fm_npi; /**< FM Normal Pending Interrupts */ ++ volatile uint32_t fmfp_exte; /**< FPM External Requests Enable */ ++ volatile uint32_t fmfp_ee; /**< FPM Event & Enable */ ++ volatile uint32_t fmfp_cev[4]; /**< FPM CPU Event 1-4 */ ++ volatile uint8_t res4[16]; /**< reserved */ ++ volatile uint32_t fmfp_ps[0x40]; /**< FPM Port Status */ ++ volatile uint8_t reserved1[0x200]; ++ volatile uint32_t fmfp_ts[128]; /**< 0x400: FPM Task Status */ ++} _PackedType t_FmFpmRegs; ++ ++#define NUM_OF_DBG_TRAPS 3 ++ ++typedef _Packed struct ++{ ++ volatile uint32_t fmbm_init; /**< BMI Initialization */ ++ volatile uint32_t fmbm_cfg1; /**< BMI Configuration 1 */ ++ volatile uint32_t fmbm_cfg2; /**< BMI Configuration 2 */ ++ volatile uint32_t reserved[5]; ++ volatile uint32_t fmbm_ievr; /**< Interrupt Event Register */ ++ volatile uint32_t fmbm_ier; /**< Interrupt Enable Register */ ++ volatile uint32_t fmbm_ifr; /**< Interrupt Force Register */ ++ volatile uint32_t reserved1[5]; ++ volatile uint32_t fmbm_arb[8]; /**< BMI Arbitration */ ++ volatile uint32_t reserved2[12]; ++ volatile uint32_t fmbm_dtc[NUM_OF_DBG_TRAPS]; /**< BMI Debug Trap Counter */ ++ volatile uint32_t reserved3; ++ volatile uint32_t fmbm_dcv[NUM_OF_DBG_TRAPS][4]; /**< BMI Debug Compare Value */ ++ volatile uint32_t fmbm_dcm[NUM_OF_DBG_TRAPS][4]; /**< BMI Debug Compare Mask */ ++ volatile uint32_t fmbm_gde; /**< BMI Global Debug Enable */ ++ volatile uint32_t fmbm_pp[63]; /**< BMI Port Parameters */ ++ volatile uint32_t reserved4; ++ volatile uint32_t fmbm_pfs[63]; /**< BMI Port FIFO Size */ ++ volatile uint32_t reserved5; ++ volatile uint32_t fmbm_spliodn[63]; /**< Port Partition ID */ ++} _PackedType t_FmBmiRegs; ++ ++typedef _Packed struct ++{ ++ volatile uint32_t fmqm_gc; /**< General Configuration Register */ ++ volatile uint32_t reserved0; ++ volatile uint32_t fmqm_eie; /**< Error Interrupt Event Register */ ++ volatile uint32_t fmqm_eien; /**< Error Interrupt Enable Register */ ++ volatile uint32_t fmqm_eif; /**< Error Interrupt Force Register */ ++ volatile uint32_t fmqm_ie; /**< Interrupt Event Register */ ++ volatile uint32_t fmqm_ien; /**< Interrupt Enable Register */ ++ volatile uint32_t fmqm_if; /**< Interrupt Force Register */ ++ volatile uint32_t fmqm_gs; /**< Global Status Register */ ++ volatile uint32_t reserved1; ++ volatile uint32_t fmqm_etfc; /**< Enqueue Total Frame Counter */ ++ volatile uint32_t fmqm_dtfc; /**< Dequeue Total Frame Counter */ ++ volatile uint32_t fmqm_dc0; /**< Dequeue Counter 0 */ ++ volatile uint32_t fmqm_dc1; /**< Dequeue Counter 1 */ ++ volatile uint32_t fmqm_dc2; /**< Dequeue Counter 2 */ ++ volatile uint32_t fmqm_dc3; /**< Dequeue Counter 3 */ ++ volatile uint32_t fmqm_dfdc; /**< Dequeue FQID from Default Counter */ ++ volatile uint32_t fmqm_dfcc; /**< Dequeue FQID from Context Counter */ ++ volatile uint32_t fmqm_dffc; /**< Dequeue FQID from FD Counter */ ++ volatile uint32_t fmqm_dcc; /**< Dequeue Confirm Counter */ ++ volatile uint32_t reserved1a[7]; ++ volatile uint32_t fmqm_tapc; /**< Tnum Aging Period Control */ ++ volatile uint32_t fmqm_dmcvc; /**< Dequeue MAC Command Valid Counter */ ++ volatile uint32_t fmqm_difdcc; /**< Dequeue Invalid FD Command Counter */ ++ volatile uint32_t fmqm_da1v; /**< Dequeue A1 Valid Counter */ ++ volatile uint32_t reserved1b; ++ volatile uint32_t fmqm_dtc; /**< 0x0080 Debug Trap Counter */ ++ volatile uint32_t fmqm_efddd; /**< 0x0084 Enqueue Frame Descriptor Dynamic Debug */ ++ volatile uint32_t reserved3[2]; ++ _Packed struct { ++ volatile uint32_t fmqm_dtcfg1; /**< 0x0090 Debug Trap Configuration 1 Register */ ++ volatile uint32_t fmqm_dtval1; /**< Debug Trap Value 1 Register */ ++ volatile uint32_t fmqm_dtm1; /**< Debug Trap Mask 1 Register */ ++ volatile uint32_t fmqm_dtc1; /**< Debug Trap Counter 1 Register */ ++ volatile uint32_t fmqm_dtcfg2; /**< Debug Trap Configuration 2 Register */ ++ volatile uint32_t fmqm_dtval2; /**< Debug Trap Value 2 Register */ ++ volatile uint32_t fmqm_dtm2; /**< Debug Trap Mask 2 Register */ ++ volatile uint32_t reserved1; ++ } _PackedType dbgTraps[NUM_OF_DBG_TRAPS]; ++} _PackedType t_FmQmiRegs; ++ ++typedef _Packed struct ++{ ++ volatile uint32_t fmdmsr; /**< FM DMA status register 0x04 */ ++ volatile uint32_t fmdmmr; /**< FM DMA mode register 0x08 */ ++ volatile uint32_t fmdmtr; /**< FM DMA bus threshold register 0x0c */ ++ volatile uint32_t fmdmhy; /**< FM DMA bus hysteresis register 0x10 */ ++ volatile uint32_t fmdmsetr; /**< FM DMA SOS emergency Threshold Register 0x14 */ ++ volatile uint32_t fmdmtah; /**< FM DMA transfer bus address high register 0x18 */ ++ volatile uint32_t fmdmtal; /**< FM DMA transfer bus address low register 0x1C */ ++ volatile uint32_t fmdmtcid; /**< FM DMA transfer bus communication ID register 0x20 */ ++ volatile uint32_t fmdmra; /**< FM DMA bus internal ram address register 0x24 */ ++ volatile uint32_t fmdmrd; /**< FM DMA bus internal ram data register 0x28 */ ++ volatile uint32_t fmdmwcr; /**< FM DMA CAM watchdog counter value 0x2C */ ++ volatile uint32_t fmdmebcr; /**< FM DMA CAM base in MURAM register 0x30 */ ++ volatile uint32_t fmdmccqdr; /**< FM DMA CAM and CMD Queue Debug register 0x34 */ ++ volatile uint32_t fmdmccqvr1; /**< FM DMA CAM and CMD Queue Value register #1 0x38 */ ++ volatile uint32_t fmdmccqvr2; /**< FM DMA CAM and CMD Queue Value register #2 0x3C */ ++ volatile uint32_t fmdmcqvr3; /**< FM DMA CMD Queue Value register #3 0x40 */ ++ volatile uint32_t fmdmcqvr4; /**< FM DMA CMD Queue Value register #4 0x44 */ ++ volatile uint32_t fmdmcqvr5; /**< FM DMA CMD Queue Value register #5 0x48 */ ++ volatile uint32_t fmdmsefrc; /**< FM DMA Semaphore Entry Full Reject Counter 0x50 */ ++ volatile uint32_t fmdmsqfrc; /**< FM DMA Semaphore Queue Full Reject Counter 0x54 */ ++ volatile uint32_t fmdmssrc; /**< FM DMA Semaphore SYNC Reject Counter 0x54 */ ++ volatile uint32_t fmdmdcr; /**< FM DMA Debug Counter */ ++ volatile uint32_t fmdmemsr; /**< FM DMA Emrgency Smoother Register */ ++ volatile uint32_t reserved; ++ volatile uint32_t fmdmplr[FM_MAX_NUM_OF_HW_PORT_IDS/2]; ++ /**< FM DMA PID-LIODN # register */ ++} _PackedType t_FmDmaRegs; ++ ++typedef _Packed struct ++{ ++ volatile uint32_t iadd; /**< FM IRAM instruction address register */ ++ volatile uint32_t idata; /**< FM IRAM instruction data register */ ++ volatile uint32_t itcfg; /**< FM IRAM timing config register */ ++ volatile uint32_t iready; /**< FM IRAM ready register */ ++ volatile uint8_t res[0x80000-0x10]; ++} _PackedType t_FMIramRegs; ++ ++/* Trace buffer registers - ++ each FM Controller has its own trace buffer residing at FM_MM_TRB(fmCtrlIndex) offset */ ++typedef _Packed struct t_FmTrbRegs ++{ ++ volatile uint32_t tcrh; ++ volatile uint32_t tcrl; ++ volatile uint32_t tesr; ++ volatile uint32_t tecr0h; ++ volatile uint32_t tecr0l; ++ volatile uint32_t terf0h; ++ volatile uint32_t terf0l; ++ volatile uint32_t tecr1h; ++ volatile uint32_t tecr1l; ++ volatile uint32_t terf1h; ++ volatile uint32_t terf1l; ++ volatile uint32_t tpcch; ++ volatile uint32_t tpccl; ++ volatile uint32_t tpc1h; ++ volatile uint32_t tpc1l; ++ volatile uint32_t tpc2h; ++ volatile uint32_t tpc2l; ++ volatile uint32_t twdimr; ++ volatile uint32_t twicvr; ++ volatile uint32_t tar; ++ volatile uint32_t tdr; ++ volatile uint32_t tsnum1; ++ volatile uint32_t tsnum2; ++ volatile uint32_t tsnum3; ++ volatile uint32_t tsnum4; ++} _PackedType t_FmTrbRegs; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/**************************************************************************//** ++ @Description General defines ++*//***************************************************************************/ ++#define FM_DEBUG_STATUS_REGISTER_OFFSET 0x000d1084UL ++#define FM_FW_DEBUG_INSTRUCTION 0x6ffff805UL ++ ++/**************************************************************************//** ++ @Description DMA definitions ++*//***************************************************************************/ ++/* masks */ ++#define DMA_MODE_AID_OR 0x20000000 ++#define DMA_MODE_SBER 0x10000000 ++#define DMA_MODE_BER 0x00200000 ++#define DMA_MODE_EB 0x00100000 ++#define DMA_MODE_ECC 0x00000020 ++#define DMA_MODE_PRIVILEGE_PROT 0x00001000 ++#define DMA_MODE_SECURE_PROT 0x00000800 ++#define DMA_MODE_EMERGENCY_READ 0x00080000 ++#define DMA_MODE_EMERGENCY_WRITE 0x00040000 ++#define DMA_MODE_CACHE_OR_MASK 0xC0000000 ++#define DMA_MODE_CEN_MASK 0x0000E000 ++#define DMA_MODE_DBG_MASK 0x00000380 ++ ++#define DMA_TRANSFER_PORTID_MASK 0xFF000000 ++#define DMA_TRANSFER_TNUM_MASK 0x00FF0000 ++#define DMA_TRANSFER_LIODN_MASK 0x00000FFF ++ ++#define DMA_HIGH_LIODN_MASK 0x0FFF0000 ++#define DMA_LOW_LIODN_MASK 0x00000FFF ++ ++#define DMA_STATUS_CMD_QUEUE_NOT_EMPTY 0x10000000 ++#define DMA_STATUS_BUS_ERR 0x08000000 ++#define DMA_STATUS_READ_ECC 0x04000000 ++#define DMA_STATUS_SYSTEM_WRITE_ECC 0x02000000 ++#define DMA_STATUS_FM_WRITE_ECC 0x01000000 ++#define DMA_STATUS_SYSTEM_DPEXT_ECC 0x00800000 ++#define DMA_STATUS_FM_DPEXT_ECC 0x00400000 ++#define DMA_STATUS_SYSTEM_DPDAT_ECC 0x00200000 ++#define DMA_STATUS_FM_DPDAT_ECC 0x00100000 ++#define DMA_STATUS_FM_SPDAT_ECC 0x00080000 ++ ++#define DMA_STATUS_FM_ECC (DMA_STATUS_READ_ECC | \ ++ DMA_STATUS_SYSTEM_WRITE_ECC | \ ++ DMA_STATUS_FM_WRITE_ECC | \ ++ DMA_STATUS_SYSTEM_DPEXT_ECC | \ ++ DMA_STATUS_FM_DPEXT_ECC | \ ++ DMA_STATUS_SYSTEM_DPDAT_ECC | \ ++ DMA_STATUS_FM_DPDAT_ECC | \ ++ DMA_STATUS_FM_SPDAT_ECC) ++ ++#define FM_LIODN_BASE_MASK 0x00000FFF ++ ++#define DMA_EMSR_EMSTR_MASK 0x0000FFFF ++ ++/* shifts */ ++#define DMA_MODE_CACHE_OR_SHIFT 30 ++#define DMA_MODE_BUS_PRI_SHIFT 16 ++#define DMA_MODE_AXI_DBG_SHIFT 24 ++#define DMA_MODE_CEN_SHIFT 13 ++#define DMA_MODE_BUS_PROT_SHIFT 10 ++#define DMA_MODE_DBG_SHIFT 7 ++#define DMA_MODE_EMERGENCY_LEVEL_SHIFT 6 ++#define DMA_MODE_AID_MODE_SHIFT 4 ++#define DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS 16 ++#define DMA_MODE_MAX_CAM_NUM_OF_ENTRIES 64 ++ ++#define DMA_THRESH_COMMQ_SHIFT 24 ++#define DMA_THRESH_READ_INT_BUF_SHIFT 16 ++ ++#define DMA_LIODN_SHIFT 16 ++ ++#define DMA_TRANSFER_PORTID_SHIFT 24 ++#define DMA_TRANSFER_TNUM_SHIFT 16 ++ ++/* sizes */ ++#define DMA_MAX_WATCHDOG 0xffffffff ++ ++/* others */ ++#define DMA_CAM_SIZEOF_ENTRY 0x40 ++#define DMA_CAM_ALIGN 0x1000 ++#define DMA_CAM_UNITS 8 ++ ++ ++/**************************************************************************//** ++ @Description FPM defines ++*//***************************************************************************/ ++/* masks */ ++#define FPM_EV_MASK_DOUBLE_ECC 0x80000000 ++#define FPM_EV_MASK_STALL 0x40000000 ++#define FPM_EV_MASK_SINGLE_ECC 0x20000000 ++#define FPM_EV_MASK_RELEASE_FM 0x00010000 ++#define FPM_EV_MASK_DOUBLE_ECC_EN 0x00008000 ++#define FPM_EV_MASK_STALL_EN 0x00004000 ++#define FPM_EV_MASK_SINGLE_ECC_EN 0x00002000 ++#define FPM_EV_MASK_EXTERNAL_HALT 0x00000008 ++#define FPM_EV_MASK_ECC_ERR_HALT 0x00000004 ++ ++#define FPM_RAM_CTL_RAMS_ECC_EN 0x80000000 ++#define FPM_RAM_CTL_IRAM_ECC_EN 0x40000000 ++#define FPM_RAM_CTL_MURAM_ECC 0x00008000 ++#define FPM_RAM_CTL_IRAM_ECC 0x00004000 ++#define FPM_RAM_CTL_MURAM_TEST_ECC 0x20000000 ++#define FPM_RAM_CTL_IRAM_TEST_ECC 0x10000000 ++#define FPM_RAM_CTL_RAMS_ECC_EN_SRC_SEL 0x08000000 ++ ++#define FPM_IRAM_ECC_ERR_EX_EN 0x00020000 ++#define FPM_MURAM_ECC_ERR_EX_EN 0x00040000 ++ ++#define FPM_REV1_MAJOR_MASK 0x0000FF00 ++#define FPM_REV1_MINOR_MASK 0x000000FF ++ ++#define FPM_REV2_INTEG_MASK 0x00FF0000 ++#define FPM_REV2_ERR_MASK 0x0000FF00 ++#define FPM_REV2_CFG_MASK 0x000000FF ++ ++#define FPM_TS_FRACTION_MASK 0x0000FFFF ++#define FPM_TS_CTL_EN 0x80000000 ++ ++#define FPM_PRC_REALSE_STALLED 0x00800000 ++ ++#define FPM_PS_STALLED 0x00800000 ++#define FPM_PS_FM_CTL1_SEL 0x80000000 ++#define FPM_PS_FM_CTL2_SEL 0x40000000 ++#define FPM_PS_FM_CTL_SEL_MASK (FPM_PS_FM_CTL1_SEL | FPM_PS_FM_CTL2_SEL) ++ ++#define FPM_RSTC_FM_RESET 0x80000000 ++#define FPM_RSTC_1G0_RESET 0x40000000 ++#define FPM_RSTC_1G1_RESET 0x20000000 ++#define FPM_RSTC_1G2_RESET 0x10000000 ++#define FPM_RSTC_1G3_RESET 0x08000000 ++#define FPM_RSTC_10G0_RESET 0x04000000 ++#define FPM_RSTC_1G4_RESET 0x02000000 ++#define FPM_RSTC_1G5_RESET 0x01000000 ++#define FPM_RSTC_1G6_RESET 0x00800000 ++#define FPM_RSTC_1G7_RESET 0x00400000 ++#define FPM_RSTC_10G1_RESET 0x00200000 ++ ++ ++#define FPM_DISP_LIMIT_MASK 0x1F000000 ++#define FPM_THR1_PRS_MASK 0xFF000000 ++#define FPM_THR1_KG_MASK 0x00FF0000 ++#define FPM_THR1_PLCR_MASK 0x0000FF00 ++#define FPM_THR1_BMI_MASK 0x000000FF ++ ++#define FPM_THR2_QMI_ENQ_MASK 0xFF000000 ++#define FPM_THR2_QMI_DEQ_MASK 0x000000FF ++#define FPM_THR2_FM_CTL1_MASK 0x00FF0000 ++#define FPM_THR2_FM_CTL2_MASK 0x0000FF00 ++ ++/* shifts */ ++#define FPM_DISP_LIMIT_SHIFT 24 ++ ++#define FPM_THR1_PRS_SHIFT 24 ++#define FPM_THR1_KG_SHIFT 16 ++#define FPM_THR1_PLCR_SHIFT 8 ++#define FPM_THR1_BMI_SHIFT 0 ++ ++#define FPM_THR2_QMI_ENQ_SHIFT 24 ++#define FPM_THR2_QMI_DEQ_SHIFT 0 ++#define FPM_THR2_FM_CTL1_SHIFT 16 ++#define FPM_THR2_FM_CTL2_SHIFT 8 ++ ++#define FPM_EV_MASK_CAT_ERR_SHIFT 1 ++#define FPM_EV_MASK_DMA_ERR_SHIFT 0 ++ ++#define FPM_REV1_MAJOR_SHIFT 8 ++#define FPM_REV1_MINOR_SHIFT 0 ++ ++#define FPM_REV2_INTEG_SHIFT 16 ++#define FPM_REV2_ERR_SHIFT 8 ++#define FPM_REV2_CFG_SHIFT 0 ++ ++#define FPM_TS_INT_SHIFT 16 ++ ++#define FPM_PORT_FM_CTL_PORTID_SHIFT 24 ++ ++#define FPM_PS_FM_CTL_SEL_SHIFT 30 ++#define FPM_PRC_ORA_FM_CTL_SEL_SHIFT 16 ++ ++/* Interrupts defines */ ++#define FPM_EVENT_FM_CTL_0 0x00008000 ++#define FPM_EVENT_FM_CTL 0x0000FF00 ++#define FPM_EVENT_FM_CTL_BRK 0x00000080 ++ ++/* others */ ++#define FPM_MAX_DISP_LIMIT 31 ++ ++/**************************************************************************//** ++ @Description BMI defines ++*//***************************************************************************/ ++/* masks */ ++#define BMI_INIT_START 0x80000000 ++#define BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC 0x80000000 ++#define BMI_ERR_INTR_EN_LIST_RAM_ECC 0x40000000 ++#define BMI_ERR_INTR_EN_STATISTICS_RAM_ECC 0x20000000 ++#define BMI_ERR_INTR_EN_DISPATCH_RAM_ECC 0x10000000 ++ ++#define BMI_NUM_OF_TASKS_MASK 0x3F000000 /* port */ ++#define BMI_NUM_OF_EXTRA_TASKS_MASK 0x000F0000 ++#define BMI_NUM_OF_DMAS_MASK 0x00000F00 ++#define BMI_NUM_OF_EXTRA_DMAS_MASK 0x0000000F ++#define BMI_FIFO_SIZE_MASK 0x000003FF /* port */ ++#define BMI_EXTRA_FIFO_SIZE_MASK 0x03FF0000 ++#define BMI_CFG2_DMAS_MASK 0x0000003F ++ ++#define BMI_TOTAL_FIFO_SIZE_MASK 0x07FF0000 ++#define BMI_TOTAL_NUM_OF_TASKS_MASK 0x007F0000 ++/* shifts */ ++#define BMI_CFG2_TASKS_SHIFT 16 ++#define BMI_CFG2_DMAS_SHIFT 0 ++#define BMI_CFG1_FIFO_SIZE_SHIFT 16 ++#define BMI_FIFO_SIZE_SHIFT 0 ++#define BMI_EXTRA_FIFO_SIZE_SHIFT 16 ++#define BMI_NUM_OF_TASKS_SHIFT 24 ++#define BMI_EXTRA_NUM_OF_TASKS_SHIFT 16 ++#define BMI_NUM_OF_DMAS_SHIFT 8 ++#define BMI_EXTRA_NUM_OF_DMAS_SHIFT 0 ++ ++/* others */ ++#define BMI_FIFO_ALIGN 0x100 ++ ++/**************************************************************************//** ++ @Description QMI defines ++*//***************************************************************************/ ++/* masks */ ++#define QMI_CFG_ENQ_EN 0x80000000 ++#define QMI_CFG_DEQ_EN 0x40000000 ++#define QMI_CFG_EN_COUNTERS 0x10000000 ++#define QMI_CFG_SOFT_RESET 0x01000000 ++#define QMI_CFG_DEQ_MASK 0x0000003F ++#define QMI_CFG_ENQ_MASK 0x00003F00 ++ ++#define QMI_GS_HALT_NOT_BUSY 0x00000002 ++ ++#define QMI_ERR_INTR_EN_DOUBLE_ECC 0x80000000 ++#define QMI_ERR_INTR_EN_DEQ_FROM_DEF 0x40000000 ++#define QMI_INTR_EN_SINGLE_ECC 0x80000000 ++ ++/* shifts */ ++#define QMI_CFG_ENQ_SHIFT 8 ++#define QMI_TAPC_TAP 22 ++ ++/**************************************************************************//** ++ @Description IRAM defines ++*//***************************************************************************/ ++/* masks */ ++#define IRAM_IADD_AIE 0x80000000 ++#define IRAM_READY 0x80000000 ++ ++/**************************************************************************//** ++ @Description TRB defines ++*//***************************************************************************/ ++/* masks */ ++#define TRB_TCRH_RESET 0x04000000 ++#define TRB_TCRH_ENABLE_COUNTERS 0x84008000 ++#define TRB_TCRH_DISABLE_COUNTERS 0x8400C000 ++#define TRB_TCRL_RESET 0x20000000 ++#define TRB_TCRL_UTIL 0x00000460 ++ ++typedef struct { ++ void (*f_Isr) (t_Handle h_Arg, uint32_t event); ++ t_Handle h_SrcHandle; ++} t_FmanCtrlIntrSrc; ++ ++typedef struct ++{ ++ /* uint8_t numOfPartitions; */ ++ bool resetOnInit; ++ t_FmThresholds thresholds; ++ e_FmDmaCacheOverride dmaCacheOverride; ++ e_FmDmaAidMode dmaAidMode; ++ bool dmaAidOverride; ++ uint8_t dmaAxiDbgNumOfBeats; ++ uint8_t dmaCamNumOfEntries; ++ uint32_t dmaWatchdog; ++ t_FmDmaThresholds dmaCommQThresholds; ++ t_FmDmaThresholds dmaWriteBufThresholds; ++ t_FmDmaThresholds dmaReadBufThresholds; ++ uint32_t dmaSosEmergency; ++ e_FmDmaDbgCntMode dmaDbgCntMode; ++ bool dmaStopOnBusError; ++ bool dmaEnEmergency; ++ t_FmDmaEmergency dmaEmergency; ++ bool dmaEnEmergencySmoother; ++ uint32_t dmaEmergencySwitchCounter; ++ bool haltOnExternalActivation; ++ bool haltOnUnrecoverableEccError; ++ e_FmCatastrophicErr catastrophicErr; ++ e_FmDmaErr dmaErr; ++ bool enMuramTestMode; ++ bool enIramTestMode; ++ bool externalEccRamsEnable; ++ uint16_t tnumAgingPeriod; ++ t_FmFirmwareParams firmware; ++ bool fwVerify; ++ uint32_t userSetExceptions; ++} t_FmDriverParam; ++ ++typedef void (t_FmanCtrlIsr)( t_Handle h_Fm, uint32_t event); ++ ++typedef struct ++{ ++/***************************/ ++/* Master/Guest parameters */ ++ uint8_t fmId; ++ e_FmPortType portsTypes[FM_MAX_NUM_OF_HW_PORT_IDS]; ++ uint16_t fmClkFreq; ++ t_FmRevisionInfo revInfo; ++/**************************/ ++/* Master Only parameters */ ++/**************************/ ++ bool enabledTimeStamp; ++ uint8_t count1MicroBit; ++ uint8_t totalNumOfTasks; ++ uint32_t totalFifoSize; ++ uint8_t maxNumOfOpenDmas; ++ uint8_t accumulatedNumOfTasks; ++ uint32_t accumulatedFifoSize; ++ uint8_t accumulatedNumOfOpenDmas; ++ uint8_t accumulatedNumOfDeqTnums; ++#ifdef FM_LOW_END_RESTRICTION ++ bool lowEndRestriction; ++#endif /* FM_LOW_END_RESTRICTION */ ++ uint32_t exceptions; ++ int irq; ++ int errIrq; ++ bool ramsEccEnable; ++ bool explicitEnable; ++ bool internalCall; ++ uint8_t ramsEccOwners; ++ uint32_t extraFifoPoolSize; ++ uint8_t extraTasksPoolSize; ++ uint8_t extraOpenDmasPoolSize; ++#if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS) ++ uint16_t portMaxFrameLengths10G[FM_MAX_NUM_OF_10G_MACS]; ++ uint16_t macMaxFrameLengths10G[FM_MAX_NUM_OF_10G_MACS]; ++#endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */ ++ uint16_t portMaxFrameLengths1G[FM_MAX_NUM_OF_1G_MACS]; ++ uint16_t macMaxFrameLengths1G[FM_MAX_NUM_OF_1G_MACS]; ++} t_FmStateStruct; ++ ++#if (DPAA_VERSION >= 11) ++typedef struct t_FmMapParam { ++ uint16_t profilesBase; ++ uint16_t numOfProfiles; ++ t_Handle h_FmPort; ++} t_FmMapParam; ++ ++typedef struct t_FmAllocMng { ++ bool allocated; ++ uint8_t ownerId; /* guestId for KG in multi-partition only, ++ portId for PLCR in any environment */ ++} t_FmAllocMng; ++ ++typedef struct t_FmPcdSpEntry { ++ bool valid; ++ t_FmAllocMng profilesMng; ++} t_FmPcdSpEntry; ++ ++typedef struct t_FmSp { ++ void *p_FmPcdStoragePrflRegs; ++ t_FmPcdSpEntry profiles[FM_VSP_MAX_NUM_OF_ENTRIES]; ++ t_FmMapParam portsMapping[FM_MAX_NUM_OF_PORTS]; ++} t_FmSp; ++ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++typedef struct t_Fm ++{ ++/***************************/ ++/* Master/Guest parameters */ ++/***************************/ ++/* locals for recovery */ ++ uintptr_t baseAddr; ++ ++/* un-needed for recovery */ ++ t_Handle h_Pcd; ++ char fmModuleName[MODULE_NAME_SIZE]; ++ char fmIpcHandlerModuleName[FM_MAX_NUM_OF_GUESTS][MODULE_NAME_SIZE]; ++ t_Handle h_IpcSessions[FM_MAX_NUM_OF_GUESTS]; ++ t_FmIntrSrc intrMng[e_FM_EV_DUMMY_LAST]; /* FM exceptions user callback */ ++ uint8_t guestId; ++/**************************/ ++/* Master Only parameters */ ++/**************************/ ++/* locals for recovery */ ++ t_FmFpmRegs *p_FmFpmRegs; ++ t_FmBmiRegs *p_FmBmiRegs; ++ t_FmQmiRegs *p_FmQmiRegs; ++ t_FmDmaRegs *p_FmDmaRegs; ++ t_FmExceptionsCallback *f_Exception; ++ t_FmBusErrorCallback *f_BusError; ++ t_Handle h_App; /* Application handle */ ++ t_Handle h_Spinlock; ++ bool recoveryMode; ++ t_FmStateStruct *p_FmStateStruct; ++#if (DPAA_VERSION >= 11) ++ t_FmSp *p_FmSp; ++ uint8_t partNumOfVSPs; ++ uint8_t partVSPBase; ++ uintptr_t vspBaseAddr; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/* un-needed for recovery */ ++ t_Handle h_FmMuram; ++ uint64_t fmMuramPhysBaseAddr; ++ bool independentMode; ++ bool hcPortInitialized; ++ uintptr_t camBaseAddr; /* save for freeing */ ++ uintptr_t resAddr; ++ uintptr_t fifoBaseAddr; /* save for freeing */ ++ t_FmanCtrlIntrSrc fmanCtrlIntr[FM_NUM_OF_FMAN_CTRL_EVENT_REGS]; /* FM exceptions user callback */ ++ bool usedEventRegs[FM_NUM_OF_FMAN_CTRL_EVENT_REGS]; ++ ++ t_FmDriverParam *p_FmDriverParam; ++} t_Fm; ++ ++ ++#endif /* __FM_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/fm_ipc.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/fm_ipc.h +new file mode 100644 +index 0000000..f39d5d9 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/fm_ipc.h +@@ -0,0 +1,464 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_ipc.h ++ ++ @Description FM Inter-Partition prototypes, structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_IPC_H ++#define __FM_IPC_H ++ ++#include "error_ext.h" ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_IPC_grp FM Inter-Partition messaging Unit ++ ++ @Description FM Inter-Partition messaging unit API definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description enum for defining MAC types ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description A structure of parameters for specifying a MAC. ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint8_t id; ++ uint32_t enumType; ++} _PackedType t_FmIpcMacParams; ++ ++/**************************************************************************//** ++ @Description A structure of parameters for specifying a MAC. ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ t_FmIpcMacParams macParams; ++ uint16_t maxFrameLength; ++} _PackedType t_FmIpcMacMaxFrameParams; ++ ++/**************************************************************************//** ++ @Description FM physical Address ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcPhysAddr ++{ ++ volatile uint8_t high; ++ volatile uint32_t low; ++} _PackedType t_FmIpcPhysAddr; ++ ++ ++typedef _Packed struct t_FmIpcPortOutInitParams { ++ uint8_t numOfTasks; /**< OUT */ ++ uint8_t numOfExtraTasks; /**< OUT */ ++ uint8_t numOfOpenDmas; /**< OUT */ ++ uint8_t numOfExtraOpenDmas; /**< OUT */ ++ uint32_t sizeOfFifo; /**< OUT */ ++ uint32_t extraSizeOfFifo; /**< OUT */ ++ t_FmIpcPhysAddr ipcPhysAddr; /**< OUT */ ++} _PackedType t_FmIpcPortOutInitParams; ++ ++/**************************************************************************//** ++ @Description Structure for IPC communication during FM_PORT_Init. ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcPortInInitParams { ++ uint8_t hardwarePortId; /**< IN. port Id */ ++ uint32_t enumPortType; /**< IN. Port type */ ++ uint8_t boolIndependentMode;/**< IN. TRUE if FM Port operates in independent mode */ ++ uint16_t liodnOffset; /**< IN. Port's requested resource */ ++ uint8_t numOfTasks; /**< IN. Port's requested resource */ ++ uint8_t numOfExtraTasks; /**< IN. Port's requested resource */ ++ uint8_t numOfOpenDmas; /**< IN. Port's requested resource */ ++ uint8_t numOfExtraOpenDmas; /**< IN. Port's requested resource */ ++ uint32_t sizeOfFifo; /**< IN. Port's requested resource */ ++ uint32_t extraSizeOfFifo; /**< IN. Port's requested resource */ ++ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */ ++ uint16_t maxFrameLength; /**< IN. Port's max frame length. */ ++ uint16_t liodnBase; /**< IN. Irrelevant for P4080 rev 1. ++ LIODN base for this port, to be ++ used together with LIODN offset. */ ++} _PackedType t_FmIpcPortInInitParams; ++ ++ ++/**************************************************************************//** ++ @Description Structure for IPC communication between port and FM ++ regarding tasks and open DMA resources management. ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcPortRsrcParams { ++ uint8_t hardwarePortId; /**< IN. port Id */ ++ uint32_t val; /**< IN. Port's requested resource */ ++ uint32_t extra; /**< IN. Port's requested resource */ ++ uint8_t boolInitialConfig; ++} _PackedType t_FmIpcPortRsrcParams; ++ ++ ++/**************************************************************************//** ++ @Description Structure for IPC communication between port and FM ++ regarding tasks and open DMA resources management. ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcPortFifoParams { ++ t_FmIpcPortRsrcParams rsrcParams; ++ uint32_t enumPortType; ++ uint8_t boolIndependentMode; ++ uint8_t deqPipelineDepth; ++ uint8_t numOfPools; ++ uint16_t secondLargestBufSize; ++ uint16_t largestBufSize; ++ uint8_t boolInitialConfig; ++} _PackedType t_FmIpcPortFifoParams; ++ ++/**************************************************************************//** ++ @Description Structure for port-FM communication during FM_PORT_Free. ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcPortFreeParams { ++ uint8_t hardwarePortId; /**< IN. port Id */ ++ uint32_t enumPortType; /**< IN. Port type */ ++ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */ ++} _PackedType t_FmIpcPortFreeParams; ++ ++/**************************************************************************//** ++ @Description Structure for defining DMA status ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcDmaStatus { ++ uint8_t boolCmqNotEmpty; /**< Command queue is not empty */ ++ uint8_t boolBusError; /**< Bus error occurred */ ++ uint8_t boolReadBufEccError; /**< Double ECC error on buffer Read */ ++ uint8_t boolWriteBufEccSysError; /**< Double ECC error on buffer write from system side */ ++ uint8_t boolWriteBufEccFmError; /**< Double ECC error on buffer write from FM side */ ++ uint8_t boolSinglePortEccError; /**< Single port ECC error from FM side */ ++} _PackedType t_FmIpcDmaStatus; ++ ++typedef _Packed struct t_FmIpcRegisterIntr ++{ ++ uint8_t guestId; /* IN */ ++ uint32_t event; /* IN */ ++} _PackedType t_FmIpcRegisterIntr; ++ ++typedef _Packed struct t_FmIpcIsr ++{ ++ uint8_t boolErr; /* IN */ ++ uint32_t pendingReg; /* IN */ ++} _PackedType t_FmIpcIsr; ++ ++/**************************************************************************//** ++ @Description structure for returning FM parameters ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcParams { ++ uint16_t fmClkFreq; /**< OUT: FM Clock frequency */ ++ uint8_t majorRev; /**< OUT: FM Major revision */ ++ uint8_t minorRev; /**< OUT: FM Minor revision */ ++} _PackedType t_FmIpcParams; ++ ++ ++/**************************************************************************//** ++ @Description structure for returning Fman Ctrl Code revision information ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcFmanCtrlCodeRevisionInfo { ++ uint16_t packageRev; /**< OUT: Package revision */ ++ uint8_t majorRev; /**< OUT: Major revision */ ++ uint8_t minorRev; /**< OUT: Minor revision */ ++} _PackedType t_FmIpcFmanCtrlCodeRevisionInfo; ++ ++/**************************************************************************//** ++ @Description Structure for defining Fm number of Fman controlers ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcPortNumOfFmanCtrls { ++ uint8_t hardwarePortId; /**< IN. port Id */ ++ uint8_t numOfFmanCtrls; /**< IN. Port type */ ++ t_FmFmanCtrl orFmanCtrl; /**< IN. fman controller for order restoration*/ ++} t_FmIpcPortNumOfFmanCtrls; ++ ++/**************************************************************************//** ++ @Description structure for setting Fman contriller events ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcFmanEvents { ++ uint8_t eventRegId; /**< IN: Fman controller event register id */ ++ uint32_t enableEvents; /**< IN/OUT: required enabled events mask */ ++} _PackedType t_FmIpcFmanEvents; ++ ++typedef _Packed struct t_FmIpcResourceAllocParams { ++ uint8_t guestId; ++ uint16_t base; ++ uint16_t num; ++}_PackedType t_FmIpcResourceAllocParams; ++ ++typedef _Packed struct t_FmIpcVspSetPortWindow { ++ uint8_t hardwarePortId; ++ uint8_t baseStorageProfile; ++ uint8_t log2NumOfProfiles; ++}_PackedType t_FmIpcVspSetPortWindow; ++ ++typedef _Packed struct t_FmIpcSetCongestionGroupPfcPriority { ++ uint32_t congestionGroupId; ++ uint8_t priorityBitMap; ++}_PackedType t_FmIpcSetCongestionGroupPfcPriority; ++ ++#define FM_IPC_MAX_REPLY_BODY_SIZE 20 ++#define FM_IPC_MAX_REPLY_SIZE (FM_IPC_MAX_REPLY_BODY_SIZE + sizeof(uint32_t)) ++#define FM_IPC_MAX_MSG_SIZE 30 ++ ++typedef _Packed struct t_FmIpcMsg ++{ ++ uint32_t msgId; ++ uint8_t msgBody[FM_IPC_MAX_MSG_SIZE]; ++} _PackedType t_FmIpcMsg; ++ ++typedef _Packed struct t_FmIpcReply ++{ ++ uint32_t error; ++ uint8_t replyBody[FM_IPC_MAX_REPLY_BODY_SIZE]; ++} _PackedType t_FmIpcReply; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/***************************************************************************/ ++/************************ FRONT-END-TO-BACK-END*****************************/ ++/***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_GET_TIMESTAMP_SCALE ++ ++ @Description Used by FM front-end. ++ ++ @Param[out] uint32_t Pointer ++*//***************************************************************************/ ++#define FM_GET_TIMESTAMP_SCALE 1 ++ ++/**************************************************************************//** ++ @Function FM_GET_COUNTER ++ ++ @Description Used by FM front-end. ++ ++ @Param[in/out] t_FmIpcGetCounter Pointer ++*//***************************************************************************/ ++#define FM_GET_COUNTER 2 ++ ++/**************************************************************************//** ++ @Function FM_GET_SET_PORT_PARAMS ++ ++ @Description Used by FM front-end for the PORT module in order to set and get ++ parameters in/from master FM module on FM PORT initialization time. ++ ++ @Param[in/out] t_FmIcPortInitParams Pointer ++*//***************************************************************************/ ++#define FM_GET_SET_PORT_PARAMS 4 ++ ++/**************************************************************************//** ++ @Function FM_FREE_PORT ++ ++ @Description Used by FM front-end for the PORT module when a port is freed ++ to free all FM PORT resources. ++ ++ @Param[in] uint8_t Pointer ++*//***************************************************************************/ ++#define FM_FREE_PORT 5 ++ ++/**************************************************************************//** ++ @Function FM_RESET_MAC ++ ++ @Description Used by front-end for the MAC module to reset the MAC registers ++ ++ @Param[in] t_FmIpcMacParams Pointer . ++*//***************************************************************************/ ++#define FM_RESET_MAC 6 ++ ++/**************************************************************************//** ++ @Function FM_RESUME_STALLED_PORT ++ ++ @Description Used by FM front-end for the PORT module in order to ++ release a stalled FM Port. ++ ++ @Param[in] uint8_t Pointer ++*//***************************************************************************/ ++#define FM_RESUME_STALLED_PORT 7 ++ ++/**************************************************************************//** ++ @Function FM_IS_PORT_STALLED ++ ++ @Description Used by FM front-end for the PORT module in order to check whether ++ an FM port is stalled. ++ ++ @Param[in/out] t_FmIcPortIsStalled Pointer ++*//***************************************************************************/ ++#define FM_IS_PORT_STALLED 8 ++ ++/**************************************************************************//** ++ @Function FM_GET_PARAMS ++ ++ @Description Used by FM front-end for the PORT module in order to dump ++ return FM parameters. ++ ++ @Param[in] uint8_t Pointer ++*//***************************************************************************/ ++#define FM_GET_PARAMS 10 ++ ++/**************************************************************************//** ++ @Function FM_REGISTER_INTR ++ ++ @Description Used by FM front-end to register an interrupt handler to ++ be called upon interrupt for guest. ++ ++ @Param[out] t_FmIpcRegisterIntr Pointer ++*//***************************************************************************/ ++#define FM_REGISTER_INTR 11 ++ ++/**************************************************************************//** ++ @Function FM_DMA_STAT ++ ++ @Description Used by FM front-end to read the FM DMA status. ++ ++ @Param[out] t_FmIpcDmaStatus Pointer ++*//***************************************************************************/ ++#define FM_DMA_STAT 13 ++ ++/**************************************************************************//** ++ @Function FM_ALLOC_FMAN_CTRL_EVENT_REG ++ ++ @Description Used by FM front-end to allocate event register. ++ ++ @Param[out] Event register id Pointer ++*//***************************************************************************/ ++#define FM_ALLOC_FMAN_CTRL_EVENT_REG 14 ++ ++/**************************************************************************//** ++ @Function FM_FREE_FMAN_CTRL_EVENT_REG ++ ++ @Description Used by FM front-end to free locate event register. ++ ++ @Param[in] uint8_t Pointer - Event register id ++*//***************************************************************************/ ++#define FM_FREE_FMAN_CTRL_EVENT_REG 15 ++ ++/**************************************************************************//** ++ @Function FM_SET_FMAN_CTRL_EVENTS_ENABLE ++ ++ @Description Used by FM front-end to enable events in the FPM ++ Fman controller event register. ++ ++ @Param[in] t_FmIpcFmanEvents Pointer ++*//***************************************************************************/ ++#define FM_SET_FMAN_CTRL_EVENTS_ENABLE 16 ++ ++/**************************************************************************//** ++ @Function FM_SET_FMAN_CTRL_EVENTS_ENABLE ++ ++ @Description Used by FM front-end to enable events in the FPM ++ Fman controller event register. ++ ++ @Param[in/out] t_FmIpcFmanEvents Pointer ++*//***************************************************************************/ ++#define FM_GET_FMAN_CTRL_EVENTS_ENABLE 17 ++ ++/**************************************************************************//** ++ @Function FM_SET_MAC_MAX_FRAME ++ ++ @Description Used by FM front-end to set MAC's MTU/RTU's in ++ back-end. ++ ++ @Param[in/out] t_FmIpcMacMaxFrameParams Pointer ++*//***************************************************************************/ ++#define FM_SET_MAC_MAX_FRAME 18 ++ ++/**************************************************************************//** ++ @Function FM_GET_PHYS_MURAM_BASE ++ ++ @Description Used by FM front-end in order to get MURAM base address ++ ++ @Param[in/out] t_FmIpcPhysAddr Pointer ++*//***************************************************************************/ ++#define FM_GET_PHYS_MURAM_BASE 19 ++ ++/**************************************************************************//** ++ @Function FM_MASTER_IS_ALIVE ++ ++ @Description Used by FM front-end in order to verify Master is up ++ ++ @Param[in/out] bool ++*//***************************************************************************/ ++#define FM_MASTER_IS_ALIVE 20 ++ ++#define FM_ENABLE_RAM_ECC 21 ++#define FM_DISABLE_RAM_ECC 22 ++#define FM_SET_NUM_OF_FMAN_CTRL 23 ++#define FM_SET_SIZE_OF_FIFO 24 ++#define FM_SET_NUM_OF_TASKS 25 ++#define FM_SET_NUM_OF_OPEN_DMAS 26 ++#define FM_VSP_ALLOC 27 ++#define FM_VSP_FREE 28 ++#define FM_VSP_SET_PORT_WINDOW 29 ++#define FM_GET_FMAN_CTRL_CODE_REV 30 ++#define FM_SET_CONG_GRP_PFC_PRIO 31 ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++#define FM_10G_TX_ECC_WA 100 ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++/***************************************************************************/ ++/************************ BACK-END-TO-FRONT-END*****************************/ ++/***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_GUEST_ISR ++ ++ @Description Used by FM back-end to report an interrupt to the front-end. ++ ++ @Param[out] t_FmIpcIsr Pointer ++*//***************************************************************************/ ++#define FM_GUEST_ISR 1 ++ ++ ++ ++/** @} */ /* end of FM_IPC_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#endif /* __FM_IPC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/fm_muram.c b/drivers/net/dpa/NetCommSw/Peripherals/FM/fm_muram.c +new file mode 100644 +index 0000000..a1cbe3f +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/fm_muram.c +@@ -0,0 +1,175 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 FM_muram.c ++ ++ @Description FM MURAM ... ++*//***************************************************************************/ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "mm_ext.h" ++#include "string_ext.h" ++#include "sprint_ext.h" ++#include "fm_muram_ext.h" ++#include "fm_common.h" ++ ++ ++#define __ERR_MODULE__ MODULE_FM_MURAM ++ ++ ++typedef struct ++{ ++ t_Handle h_Mem; ++ uintptr_t baseAddr; ++ uint32_t size; ++} t_FmMuram; ++ ++ ++void FmMuramClear(t_Handle h_FmMuram) ++{ ++ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram; ++ ++ SANITY_CHECK_RETURN(h_FmMuram, E_INVALID_HANDLE); ++ IOMemSet32(UINT_TO_PTR(p_FmMuram->baseAddr), 0, p_FmMuram->size); ++} ++ ++ ++t_Handle FM_MURAM_ConfigAndInit(uintptr_t baseAddress, uint32_t size) ++{ ++ t_Handle h_Mem; ++ t_FmMuram *p_FmMuram; ++ ++ if (!baseAddress) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("baseAddress 0 is not supported")); ++ return NULL; ++ } ++ ++ if (baseAddress%4) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("baseAddress not 4 bytes aligned!")); ++ return NULL; ++ } ++ ++ /* Allocate FM MURAM structure */ ++ p_FmMuram = (t_FmMuram *) XX_Malloc(sizeof(t_FmMuram)); ++ if (!p_FmMuram) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM MURAM driver structure")); ++ return NULL; ++ } ++ memset(p_FmMuram, 0, sizeof(t_FmMuram)); ++ ++ ++ if ((MM_Init(&h_Mem, baseAddress, size) != E_OK) || (!h_Mem)) ++ { ++ XX_Free(p_FmMuram); ++ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-MURAM partition!!!")); ++ return NULL; ++ } ++ ++ /* Initialize FM MURAM parameters which will be kept by the driver */ ++ p_FmMuram->baseAddr = baseAddress; ++ p_FmMuram->size = size; ++ p_FmMuram->h_Mem = h_Mem; ++ ++ return p_FmMuram; ++} ++ ++t_Error FM_MURAM_Free(t_Handle h_FmMuram) ++{ ++ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram; ++ ++ if (p_FmMuram->h_Mem) ++ MM_Free(p_FmMuram->h_Mem); ++ ++ XX_Free(h_FmMuram); ++ ++ return E_OK; ++} ++ ++void * FM_MURAM_AllocMem(t_Handle h_FmMuram, uint32_t size, uint32_t align) ++{ ++ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram; ++ uintptr_t addr; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmMuram, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_FmMuram->h_Mem, E_INVALID_HANDLE, NULL); ++ ++ addr = (uintptr_t)MM_Get(p_FmMuram->h_Mem, size, align ,"FM MURAM"); ++ ++ if (addr == ILLEGAL_BASE) ++ return NULL; ++ ++ return UINT_TO_PTR(addr); ++} ++ ++void * FM_MURAM_AllocMemForce(t_Handle h_FmMuram, uint64_t base, uint32_t size) ++{ ++ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram; ++ uintptr_t addr; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmMuram, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_FmMuram->h_Mem, E_INVALID_HANDLE, NULL); ++ ++ addr = (uintptr_t)MM_GetForce(p_FmMuram->h_Mem, base, size, "FM MURAM"); ++ ++ if (addr == ILLEGAL_BASE) ++ return NULL; ++ ++ return UINT_TO_PTR(addr); ++} ++ ++t_Error FM_MURAM_FreeMem(t_Handle h_FmMuram, void *ptr) ++{ ++ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmMuram, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMuram->h_Mem, E_INVALID_HANDLE); ++ ++ if (MM_Put(p_FmMuram->h_Mem, PTR_TO_UINT(ptr)) == 0) ++ RETURN_ERROR(MINOR, E_INVALID_ADDRESS, ("memory pointer!!!")); ++ ++ return E_OK; ++} ++ ++uint64_t FM_MURAM_GetFreeMemSize(t_Handle h_FmMuram) ++{ ++ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmMuram, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(p_FmMuram->h_Mem, E_INVALID_HANDLE, 0); ++ ++ return MM_GetFreeMemSize(p_FmMuram->h_Mem); ++} +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/inc/fm_common.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/inc/fm_common.h +new file mode 100644 +index 0000000..6476c7a +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/inc/fm_common.h +@@ -0,0 +1,1103 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_common.h ++ ++ @Description FM internal structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_COMMON_H ++#define __FM_COMMON_H ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_ext.h" ++#include "fm_port_ext.h" ++ ++ ++#define e_FM_PORT_TYPE_OH_HOST_COMMAND e_FM_PORT_TYPE_DUMMY ++ ++#define CLS_PLAN_NUM_PER_GRP 8 ++ ++#define IP_OFFLOAD_PACKAGE_NUMBER 106 ++ ++ ++/**************************************************************************//** ++ @Description Enum for inter-module interrupts registration ++*//***************************************************************************/ ++typedef enum e_FmEventModules{ ++ e_FM_MOD_PRS, /**< Parser event */ ++ e_FM_MOD_KG, /**< Keygen event */ ++ e_FM_MOD_PLCR, /**< Policer event */ ++ e_FM_MOD_10G_MAC, /**< 10G MAC event */ ++ e_FM_MOD_1G_MAC, /**< 1G MAC event */ ++ e_FM_MOD_TMR, /**< Timer event */ ++ e_FM_MOD_FMAN_CTRL, /**< FMAN Controller Timer event */ ++ e_FM_MOD_MACSEC, ++ e_FM_MOD_DUMMY_LAST ++} e_FmEventModules; ++ ++/**************************************************************************//** ++ @Description Enum for interrupts types ++*//***************************************************************************/ ++typedef enum e_FmIntrType { ++ e_FM_INTR_TYPE_ERR, ++ e_FM_INTR_TYPE_NORMAL ++} e_FmIntrType; ++ ++/**************************************************************************//** ++ @Description Enum for inter-module interrupts registration ++*//***************************************************************************/ ++typedef enum e_FmInterModuleEvent ++{ ++ e_FM_EV_PRS = 0, /**< Parser event */ ++ e_FM_EV_ERR_PRS, /**< Parser error event */ ++ e_FM_EV_KG, /**< Keygen event */ ++ e_FM_EV_ERR_KG, /**< Keygen error event */ ++ e_FM_EV_PLCR, /**< Policer event */ ++ e_FM_EV_ERR_PLCR, /**< Policer error event */ ++ e_FM_EV_ERR_10G_MAC0, /**< 10G MAC 0 error event */ ++ e_FM_EV_ERR_10G_MAC1, /**< 10G MAC 1 error event */ ++ e_FM_EV_ERR_1G_MAC0, /**< 1G MAC 0 error event */ ++ e_FM_EV_ERR_1G_MAC1, /**< 1G MAC 1 error event */ ++ e_FM_EV_ERR_1G_MAC2, /**< 1G MAC 2 error event */ ++ e_FM_EV_ERR_1G_MAC3, /**< 1G MAC 3 error event */ ++ e_FM_EV_ERR_1G_MAC4, /**< 1G MAC 4 error event */ ++ e_FM_EV_ERR_1G_MAC5, /**< 1G MAC 5 error event */ ++ e_FM_EV_ERR_1G_MAC6, /**< 1G MAC 6 error event */ ++ e_FM_EV_ERR_1G_MAC7, /**< 1G MAC 7 error event */ ++ e_FM_EV_ERR_MACSEC_MAC0, ++ e_FM_EV_TMR, /**< Timer event */ ++ e_FM_EV_10G_MAC0, /**< 10G MAC 0 event (Magic packet detection)*/ ++ e_FM_EV_10G_MAC1, /**< 10G MAC 1 event (Magic packet detection)*/ ++ e_FM_EV_1G_MAC0, /**< 1G MAC 0 event (Magic packet detection)*/ ++ e_FM_EV_1G_MAC1, /**< 1G MAC 1 event (Magic packet detection)*/ ++ e_FM_EV_1G_MAC2, /**< 1G MAC 2 (Magic packet detection)*/ ++ e_FM_EV_1G_MAC3, /**< 1G MAC 3 (Magic packet detection)*/ ++ e_FM_EV_1G_MAC4, /**< 1G MAC 4 (Magic packet detection)*/ ++ e_FM_EV_1G_MAC5, /**< 1G MAC 5 (Magic packet detection)*/ ++ e_FM_EV_1G_MAC6, /**< 1G MAC 6 (Magic packet detection)*/ ++ e_FM_EV_1G_MAC7, /**< 1G MAC 7 (Magic packet detection)*/ ++ e_FM_EV_MACSEC_MAC0, /**< MACSEC MAC 0 event */ ++ e_FM_EV_FMAN_CTRL_0, /**< Fman controller event 0 */ ++ e_FM_EV_FMAN_CTRL_1, /**< Fman controller event 1 */ ++ e_FM_EV_FMAN_CTRL_2, /**< Fman controller event 2 */ ++ e_FM_EV_FMAN_CTRL_3, /**< Fman controller event 3 */ ++ e_FM_EV_DUMMY_LAST ++} e_FmInterModuleEvent; ++ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description PCD KG scheme registers ++*//***************************************************************************/ ++typedef _Packed struct t_FmPcdPlcrProfileRegs { ++ volatile uint32_t fmpl_pemode; /* 0x090 FMPL_PEMODE - FM Policer Profile Entry Mode*/ ++ volatile uint32_t fmpl_pegnia; /* 0x094 FMPL_PEGNIA - FM Policer Profile Entry GREEN Next Invoked Action*/ ++ volatile uint32_t fmpl_peynia; /* 0x098 FMPL_PEYNIA - FM Policer Profile Entry YELLOW Next Invoked Action*/ ++ volatile uint32_t fmpl_pernia; /* 0x09C FMPL_PERNIA - FM Policer Profile Entry RED Next Invoked Action*/ ++ volatile uint32_t fmpl_pecir; /* 0x0A0 FMPL_PECIR - FM Policer Profile Entry Committed Information Rate*/ ++ volatile uint32_t fmpl_pecbs; /* 0x0A4 FMPL_PECBS - FM Policer Profile Entry Committed Burst Size*/ ++ volatile uint32_t fmpl_pepepir_eir; /* 0x0A8 FMPL_PEPIR_EIR - FM Policer Profile Entry Peak/Excess Information Rate*/ ++ volatile uint32_t fmpl_pepbs_ebs; /* 0x0AC FMPL_PEPBS_EBS - FM Policer Profile Entry Peak/Excess Information Rate*/ ++ volatile uint32_t fmpl_pelts; /* 0x0B0 FMPL_PELTS - FM Policer Profile Entry Last TimeStamp*/ ++ volatile uint32_t fmpl_pects; /* 0x0B4 FMPL_PECTS - FM Policer Profile Entry Committed Token Status*/ ++ volatile uint32_t fmpl_pepts_ets; /* 0x0B8 FMPL_PEPTS_ETS - FM Policer Profile Entry Peak/Excess Token Status*/ ++ volatile uint32_t fmpl_pegpc; /* 0x0BC FMPL_PEGPC - FM Policer Profile Entry GREEN Packet Counter*/ ++ volatile uint32_t fmpl_peypc; /* 0x0C0 FMPL_PEYPC - FM Policer Profile Entry YELLOW Packet Counter*/ ++ volatile uint32_t fmpl_perpc; /* 0x0C4 FMPL_PERPC - FM Policer Profile Entry RED Packet Counter */ ++ volatile uint32_t fmpl_perypc; /* 0x0C8 FMPL_PERYPC - FM Policer Profile Entry Recolored YELLOW Packet Counter*/ ++ volatile uint32_t fmpl_perrpc; /* 0x0CC FMPL_PERRPC - FM Policer Profile Entry Recolored RED Packet Counter*/ ++ volatile uint32_t fmpl_res1[12]; /* 0x0D0-0x0FF Reserved */ ++} _PackedType t_FmPcdPlcrProfileRegs; ++ ++ ++typedef _Packed struct t_FmPcdCcCapwapReassmTimeoutParams { ++ volatile uint32_t portIdAndCapwapReassmTbl; ++ volatile uint32_t fqidForTimeOutFrames; ++ volatile uint32_t timeoutRequestTime; ++}_PackedType t_FmPcdCcCapwapReassmTimeoutParams; ++ ++ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/*for UNDER_CONSTRUCTION_FM_RMU_USE_SEC its defined in fm_ext.h*/ ++typedef uint32_t t_FmFmanCtrl; ++ ++#define FPM_PORT_FM_CTL1 0x00000001 ++#define FPM_PORT_FM_CTL2 0x00000002 ++ ++ ++ ++typedef struct t_FmPcdCcFragScratchPoolCmdParams { ++ uint32_t numOfBuffers; ++ uint8_t bufferPoolId; ++} t_FmPcdCcFragScratchPoolCmdParams; ++ ++typedef struct t_FmPcdCcIpReassmTimeoutParams { ++ bool activate; ++ uint8_t tsbs; ++ uint32_t iprcpt; ++} t_FmPcdCcIpReassmTimeoutParams; ++ ++typedef struct { ++ uint8_t baseEntry; ++ uint16_t numOfClsPlanEntries; ++ uint32_t vectors[FM_PCD_MAX_NUM_OF_CLS_PLANS]; ++} t_FmPcdKgInterModuleClsPlanSet; ++ ++/**************************************************************************//** ++ @Description Structure for binding a port to keygen schemes. ++*//***************************************************************************/ ++typedef struct t_FmPcdKgInterModuleBindPortToSchemes { ++ uint8_t hardwarePortId; ++ uint8_t netEnvId; ++ bool useClsPlan; /**< TRUE if this port uses the clsPlan mechanism */ ++ uint8_t numOfSchemes; ++ uint8_t schemesIds[FM_PCD_KG_NUM_OF_SCHEMES]; ++} t_FmPcdKgInterModuleBindPortToSchemes; ++ ++typedef struct { ++ uint32_t nextCcNodeInfo; ++ t_List node; ++} t_CcNodeInfo; ++ ++typedef struct ++{ ++ t_Handle h_CcNode; ++ uint16_t index; ++ t_List node; ++}t_CcNodeInformation; ++#define CC_NODE_F_OBJECT(ptr) LIST_OBJECT(ptr, t_CcNodeInformation, node) ++ ++typedef struct ++{ ++ t_Handle h_Manip; ++ t_List node; ++}t_ManipInfo; ++#define CC_NEXT_NODE_F_OBJECT(ptr) LIST_OBJECT(ptr, t_CcNodeInfo, node) ++ ++typedef struct { ++ uint32_t type; ++ uint8_t prOffset; ++ uint16_t dataOffset; ++ // uint8_t poolIndex; ++ // uint8_t poolIdForManip; ++ uint8_t numOfTasks; ++ uint8_t numOfExtraTasks; ++ uint8_t hardwarePortId; ++ t_FmRevisionInfo revInfo; ++ uint32_t nia; ++} t_GetCcParams; ++ ++typedef struct { ++ uint32_t type; ++ int psoSize; ++ uint32_t nia; ++ t_FmFmanCtrl orFmanCtrl; ++ bool overwrite; ++} t_SetCcParams; ++ ++typedef struct { ++ t_GetCcParams getCcParams; ++ t_SetCcParams setCcParams; ++} t_FmPortGetSetCcParams; ++ ++ ++static __inline__ bool TRY_LOCK(t_Handle h_Spinlock, volatile bool *p_Flag) ++{ ++ uint32_t intFlags; ++ if (h_Spinlock) ++ intFlags = XX_LockIntrSpinlock(h_Spinlock); ++ else ++ intFlags = XX_DisableAllIntr(); ++ ++ if (*p_Flag) ++ { ++ if (h_Spinlock) ++ XX_UnlockIntrSpinlock(h_Spinlock, intFlags); ++ else ++ XX_RestoreAllIntr(intFlags); ++ return FALSE; ++ } ++ *p_Flag = TRUE; ++ ++ if (h_Spinlock) ++ XX_UnlockIntrSpinlock(h_Spinlock, intFlags); ++ else ++ XX_RestoreAllIntr(intFlags); ++ ++ return TRUE; ++} ++ ++#define RELEASE_LOCK(_flag) _flag = FALSE; ++ ++/**************************************************************************//** ++ @Collection Defines used for manipulation CC and BMI ++ @{ ++*//***************************************************************************/ ++#define INTERNAL_CONTEXT_OFFSET 0x80000000 ++#define OFFSET_OF_PR 0x40000000 ++//#define BUFFER_POOL_ID_FOR_MANIP 0x20000000 ++#define NUM_OF_TASKS 0x10000000 ++#define OFFSET_OF_DATA 0x08000000 ++#define HW_PORT_ID 0x04000000 ++#define FM_REV 0x02000000 ++#define GET_NIA_FPNE 0x01000000 ++#define GET_NIA_PNDN 0x00800000 ++#define NUM_OF_EXTRA_TASKS 0x00400000 ++ ++#define UPDATE_NIA_PNEN 0x80000000 ++#define UPDATE_PSO 0x40000000 ++#define UPDATE_NIA_PNDN 0x20000000 ++#define UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY 0x10000000 ++#define UPDATE_NIA_FENE 0x04000000 ++#define UPDATE_NIA_CMNE 0x02000000 ++#define UPDATE_NIA_FPNE 0x01000000 ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection Defines used for manipulation CC and CC ++ @{ ++*//***************************************************************************/ ++#define UPDATE_NIA_ENQ_WITHOUT_DMA 0x80000000 ++#define UPDATE_CC_WITH_TREE 0x40000000 ++#define UPDATE_CC_WITH_DELETE_TREE 0x20000000 ++#define UPDATE_KG_NIA_CC_WA 0x10000000 ++#define UPDATE_KG_OPT_MODE 0x08000000 ++#define UPDATE_KG_NIA 0x04000000 ++/* @} */ ++ ++#define FM_MAX_NUM_OF_PORTS (FM_MAX_NUM_OF_OH_PORTS + \ ++ FM_MAX_NUM_OF_1G_RX_PORTS + \ ++ FM_MAX_NUM_OF_10G_RX_PORTS + \ ++ FM_MAX_NUM_OF_1G_TX_PORTS + \ ++ FM_MAX_NUM_OF_10G_TX_PORTS) ++ ++#define MODULE_NAME_SIZE 30 ++#define DUMMY_PORT_ID 0 ++ ++#define FM_LIODN_OFFSET_MASK 0x3FF ++ ++/**************************************************************************//** ++ @Description NIA Description ++*//***************************************************************************/ ++#define NIA_ENG_MASK 0x007C0000 ++#define NIA_AC_MASK 0x0003ffff ++ ++#define NIA_ORDER_RESTOR 0x00800000 ++#define NIA_ENG_FM_CTL 0x00000000 ++#define NIA_ENG_PRS 0x00440000 ++#define NIA_ENG_KG 0x00480000 ++#define NIA_ENG_PLCR 0x004C0000 ++#define NIA_ENG_BMI 0x00500000 ++#define NIA_ENG_QMI_ENQ 0x00540000 ++#define NIA_ENG_QMI_DEQ 0x00580000 ++ ++#define NIA_FM_CTL_AC_CC 0x00000006 ++#define NIA_FM_CTL_AC_HC 0x0000000C ++#define NIA_FM_CTL_AC_IND_MODE_TX 0x00000008 ++#define NIA_FM_CTL_AC_IND_MODE_RX 0x0000000A ++#define NIA_FM_CTL_AC_FRAG 0x0000000e ++#define NIA_FM_CTL_AC_PRE_BMI_FETCH_HEADER 0x00000010 ++#define NIA_FM_CTL_AC_PRE_BMI_FETCH_FULL_FRAME 0x00000018 ++#define NIA_FM_CTL_AC_POST_BMI_FETCH 0x00000012 ++#define NIA_FM_CTL_AC_PRE_BMI_ENQ_FRAME 0x0000001A ++#define NIA_FM_CTL_AC_PRE_BMI_DISCARD_FRAME 0x0000001E ++#define NIA_FM_CTL_AC_POST_BMI_ENQ_ORR 0x00000014 ++#define NIA_FM_CTL_AC_POST_BMI_ENQ 0x00000022 ++#define NIA_FM_CTL_AC_PRE_CC 0x00000020 ++#define NIA_FM_CTL_AC_POST_TX 0x00000024 ++ ++#define NIA_BMI_AC_ENQ_FRAME 0x00000002 ++#define NIA_BMI_AC_TX_RELEASE 0x000002C0 ++#define NIA_BMI_AC_RELEASE 0x000000C0 ++#define NIA_BMI_AC_DISCARD 0x000000C1 ++#define NIA_BMI_AC_TX 0x00000274 ++#define NIA_BMI_AC_FETCH 0x00000208 ++#define NIA_BMI_AC_MASK 0x000003FF ++#define NIA_BMI_AC_FETCH_ALL_FRAME 0x0000020c ++ ++#define NIA_KG_DIRECT 0x00000100 ++#define NIA_KG_CC_EN 0x00000200 ++#define NIA_PLCR_ABSOLUTE 0x00008000 ++ ++#define NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA 0x00000202 ++ ++#define GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd) \ ++ (uint32_t)((FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ? \ ++ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_PRE_BMI_ENQ_FRAME) : \ ++ (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)) ++#define GET_NIA_BMI_AC_DISCARD_FRAME(h_FmPcd) \ ++ (uint32_t)((FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ? \ ++ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_PRE_BMI_DISCARD_FRAME) : \ ++ (NIA_ENG_BMI | NIA_BMI_AC_DISCARD)) ++ ++#define NIA_IPR_DIRECT_SCHEME_IPV4_OFFSET 0x10 ++#define NIA_IPR_DIRECT_SCHEME_IPV6_OFFSET 0x14 ++ ++/**************************************************************************//** ++ @Description Port Id defines ++*//***************************************************************************/ ++#if (DPAA_VERSION == 10) ++#define BASE_OH_PORTID 1 ++#else ++#define BASE_OH_PORTID 2 ++#endif /* (DPAA_VERSION == 10) */ ++#define BASE_1G_RX_PORTID 8 ++#define BASE_10G_RX_PORTID 0x10 ++#define BASE_1G_TX_PORTID 0x28 ++#define BASE_10G_TX_PORTID 0x30 ++ ++#define FM_PCD_PORT_OH_BASE_INDX 0 ++#define FM_PCD_PORT_1G_RX_BASE_INDX (FM_PCD_PORT_OH_BASE_INDX+FM_MAX_NUM_OF_OH_PORTS) ++#define FM_PCD_PORT_10G_RX_BASE_INDX (FM_PCD_PORT_1G_RX_BASE_INDX+FM_MAX_NUM_OF_1G_RX_PORTS) ++#define FM_PCD_PORT_1G_TX_BASE_INDX (FM_PCD_PORT_10G_RX_BASE_INDX+FM_MAX_NUM_OF_10G_RX_PORTS) ++#define FM_PCD_PORT_10G_TX_BASE_INDX (FM_PCD_PORT_1G_TX_BASE_INDX+FM_MAX_NUM_OF_1G_TX_PORTS) ++ ++#if (FM_MAX_NUM_OF_OH_PORTS > 0) ++#define CHECK_PORT_ID_OH_PORTS(_relativePortId) \ ++ if ((_relativePortId) >= FM_MAX_NUM_OF_OH_PORTS) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal OH_PORT port id")) ++#else ++#define CHECK_PORT_ID_OH_PORTS(_relativePortId) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal OH_PORT port id")) ++#endif ++#if (FM_MAX_NUM_OF_1G_RX_PORTS > 0) ++#define CHECK_PORT_ID_1G_RX_PORTS(_relativePortId) \ ++ if ((_relativePortId) >= FM_MAX_NUM_OF_1G_RX_PORTS) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_RX_PORT port id")) ++#else ++#define CHECK_PORT_ID_1G_RX_PORTS(_relativePortId) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_RX_PORT port id")) ++#endif ++#if (FM_MAX_NUM_OF_10G_RX_PORTS > 0) ++#define CHECK_PORT_ID_10G_RX_PORTS(_relativePortId) \ ++ if ((_relativePortId) >= FM_MAX_NUM_OF_10G_RX_PORTS) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_RX_PORT port id")) ++#else ++#define CHECK_PORT_ID_10G_RX_PORTS(_relativePortId) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_RX_PORT port id")) ++#endif ++#if (FM_MAX_NUM_OF_1G_TX_PORTS > 0) ++#define CHECK_PORT_ID_1G_TX_PORTS(_relativePortId) \ ++ if ((_relativePortId) >= FM_MAX_NUM_OF_1G_TX_PORTS) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_TX_PORT port id")) ++#else ++#define CHECK_PORT_ID_1G_TX_PORTS(_relativePortId) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_TX_PORT port id")) ++#endif ++#if (FM_MAX_NUM_OF_10G_TX_PORTS > 0) ++#define CHECK_PORT_ID_10G_TX_PORTS(_relativePortId) \ ++ if ((_relativePortId) >= FM_MAX_NUM_OF_10G_TX_PORTS) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_TX_PORT port id")) ++#else ++#define CHECK_PORT_ID_10G_TX_PORTS(_relativePortId) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_TX_PORT port id")) ++#endif ++ ++ ++#define SW_PORT_ID_TO_HW_PORT_ID(_port, _type, _relativePortId) \ ++switch (_type) { \ ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): \ ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): \ ++ CHECK_PORT_ID_OH_PORTS(_relativePortId); \ ++ _port = (uint8_t)(BASE_OH_PORTID + (_relativePortId)); \ ++ break; \ ++ case (e_FM_PORT_TYPE_RX): \ ++ CHECK_PORT_ID_1G_RX_PORTS(_relativePortId); \ ++ _port = (uint8_t)(BASE_1G_RX_PORTID + (_relativePortId)); \ ++ break; \ ++ case (e_FM_PORT_TYPE_RX_10G): \ ++ CHECK_PORT_ID_10G_RX_PORTS(_relativePortId); \ ++ _port = (uint8_t)(BASE_10G_RX_PORTID + (_relativePortId)); \ ++ break; \ ++ case (e_FM_PORT_TYPE_TX): \ ++ CHECK_PORT_ID_1G_TX_PORTS(_relativePortId); \ ++ _port = (uint8_t)(BASE_1G_TX_PORTID + (_relativePortId)); \ ++ break; \ ++ case (e_FM_PORT_TYPE_TX_10G): \ ++ CHECK_PORT_ID_10G_TX_PORTS(_relativePortId); \ ++ _port = (uint8_t)(BASE_10G_TX_PORTID + (_relativePortId)); \ ++ break; \ ++ default: \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal port type")); \ ++ _port = 0; \ ++ break; \ ++} ++ ++#define HW_PORT_ID_TO_SW_PORT_ID(_relativePortId, hardwarePortId) \ ++{ if (((hardwarePortId) >= BASE_OH_PORTID) && \ ++ ((hardwarePortId) < BASE_OH_PORTID+FM_MAX_NUM_OF_OH_PORTS)) \ ++ _relativePortId = (uint8_t)((hardwarePortId)-BASE_OH_PORTID); \ ++ else if (((hardwarePortId) >= BASE_10G_TX_PORTID) && \ ++ ((hardwarePortId) < BASE_10G_TX_PORTID+FM_MAX_NUM_OF_10G_TX_PORTS)) \ ++ _relativePortId = (uint8_t)((hardwarePortId)-BASE_10G_TX_PORTID); \ ++ else if (((hardwarePortId) >= BASE_1G_TX_PORTID) && \ ++ ((hardwarePortId) < BASE_1G_TX_PORTID+FM_MAX_NUM_OF_1G_TX_PORTS)) \ ++ _relativePortId = (uint8_t)((hardwarePortId)-BASE_1G_TX_PORTID); \ ++ else if (((hardwarePortId) >= BASE_10G_RX_PORTID) && \ ++ ((hardwarePortId) < BASE_10G_RX_PORTID+FM_MAX_NUM_OF_10G_RX_PORTS)) \ ++ _relativePortId = (uint8_t)((hardwarePortId)-BASE_10G_RX_PORTID); \ ++ else if (((hardwarePortId) >= BASE_1G_RX_PORTID) && \ ++ ((hardwarePortId) < BASE_1G_RX_PORTID+FM_MAX_NUM_OF_1G_RX_PORTS)) \ ++ _relativePortId = (uint8_t)((hardwarePortId)-BASE_1G_RX_PORTID); \ ++ else { \ ++ _relativePortId = (uint8_t)DUMMY_PORT_ID; \ ++ ASSERT_COND(TRUE); \ ++ } \ ++} ++ ++#define HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId) \ ++do { \ ++ if (((hardwarePortId) >= BASE_OH_PORTID) && ((hardwarePortId) < BASE_OH_PORTID+FM_MAX_NUM_OF_OH_PORTS)) \ ++ swPortIndex = (uint8_t)((hardwarePortId)-BASE_OH_PORTID+FM_PCD_PORT_OH_BASE_INDX); \ ++ else if (((hardwarePortId) >= BASE_1G_RX_PORTID) && \ ++ ((hardwarePortId) < BASE_1G_RX_PORTID+FM_MAX_NUM_OF_1G_RX_PORTS)) \ ++ swPortIndex = (uint8_t)((hardwarePortId)-BASE_1G_RX_PORTID+FM_PCD_PORT_1G_RX_BASE_INDX); \ ++ else if (((hardwarePortId) >= BASE_10G_RX_PORTID) && \ ++ ((hardwarePortId) < BASE_10G_RX_PORTID+FM_MAX_NUM_OF_10G_RX_PORTS)) \ ++ swPortIndex = (uint8_t)((hardwarePortId)-BASE_10G_RX_PORTID+FM_PCD_PORT_10G_RX_BASE_INDX); \ ++ else if (((hardwarePortId) >= BASE_1G_TX_PORTID) && \ ++ ((hardwarePortId) < BASE_1G_TX_PORTID+FM_MAX_NUM_OF_1G_TX_PORTS)) \ ++ swPortIndex = (uint8_t)((hardwarePortId)-BASE_1G_TX_PORTID+FM_PCD_PORT_1G_TX_BASE_INDX); \ ++ else if (((hardwarePortId) >= BASE_10G_TX_PORTID) && \ ++ ((hardwarePortId) < BASE_10G_TX_PORTID+FM_MAX_NUM_OF_10G_TX_PORTS)) \ ++ swPortIndex = (uint8_t)((hardwarePortId)-BASE_10G_TX_PORTID+FM_PCD_PORT_10G_TX_BASE_INDX); \ ++ else ASSERT_COND(FALSE); \ ++} while (0) ++ ++#define SW_PORT_INDX_TO_HW_PORT_ID(hardwarePortId, swPortIndex) \ ++do { \ ++ if (((swPortIndex) >= FM_PCD_PORT_OH_BASE_INDX) && ((swPortIndex) < FM_PCD_PORT_1G_RX_BASE_INDX)) \ ++ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_OH_BASE_INDX+BASE_OH_PORTID); \ ++ else if (((swPortIndex) >= FM_PCD_PORT_1G_RX_BASE_INDX) && ((swPortIndex) < FM_PCD_PORT_10G_RX_BASE_INDX)) \ ++ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_1G_RX_BASE_INDX+BASE_1G_RX_PORTID); \ ++ else if (((swPortIndex) >= FM_PCD_PORT_10G_RX_BASE_INDX) && ((swPortIndex) < FM_MAX_NUM_OF_PORTS)) \ ++ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_10G_RX_BASE_INDX+BASE_10G_RX_PORTID); \ ++ else if (((swPortIndex) >= FM_PCD_PORT_1G_TX_BASE_INDX) && ((swPortIndex) < FM_PCD_PORT_10G_TX_BASE_INDX)) \ ++ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_1G_TX_BASE_INDX+BASE_1G_TX_PORTID); \ ++ else if (((swPortIndex) >= FM_PCD_PORT_10G_TX_BASE_INDX) && ((swPortIndex) < FM_MAX_NUM_OF_PORTS)) \ ++ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_10G_TX_BASE_INDX+BASE_10G_TX_PORTID); \ ++ else ASSERT_COND(FALSE); \ ++} while (0) ++ ++#define BMI_FIFO_UNITS 0x100 ++ ++typedef struct { ++ void (*f_Isr) (t_Handle h_Arg); ++ t_Handle h_SrcHandle; ++ uint8_t guestId; ++} t_FmIntrSrc; ++ ++#define ILLEGAL_HDR_NUM 0xFF ++#define NO_HDR_NUM FM_PCD_PRS_NUM_OF_HDRS ++ ++#define IS_PRIVATE_HEADER(hdr) (((hdr) == HEADER_TYPE_USER_DEFINED_SHIM1) || \ ++ ((hdr) == HEADER_TYPE_USER_DEFINED_SHIM2)) ++#define IS_SPECIAL_HEADER(hdr) ((hdr) == HEADER_TYPE_MACSEC) ++ ++#define GET_PRS_HDR_NUM(num, hdr) \ ++switch (hdr) \ ++{ case (HEADER_TYPE_ETH): num = 0; break; \ ++ case (HEADER_TYPE_LLC_SNAP): num = 1; break; \ ++ case (HEADER_TYPE_VLAN): num = 2; break; \ ++ case (HEADER_TYPE_PPPoE): num = 3; break; \ ++ case (HEADER_TYPE_MPLS): num = 4; break; \ ++ case (HEADER_TYPE_IPv4): num = 5; break; \ ++ case (HEADER_TYPE_IPv6): num = 6; break; \ ++ case (HEADER_TYPE_GRE): num = 7; break; \ ++ case (HEADER_TYPE_MINENCAP): num = 8; break; \ ++ case (HEADER_TYPE_USER_DEFINED_L3): num = 9; break; \ ++ case (HEADER_TYPE_TCP): num = 10; break; \ ++ case (HEADER_TYPE_UDP): num = 11; break; \ ++ case (HEADER_TYPE_IPSEC_AH): \ ++ case (HEADER_TYPE_IPSEC_ESP): num = 12; break; \ ++ case (HEADER_TYPE_SCTP): num = 13; break; \ ++ case (HEADER_TYPE_DCCP): num = 14; break; \ ++ case (HEADER_TYPE_USER_DEFINED_L4): num = 15; break; \ ++ case (HEADER_TYPE_USER_DEFINED_SHIM1): \ ++ case (HEADER_TYPE_USER_DEFINED_SHIM2): \ ++ case (HEADER_TYPE_MACSEC): \ ++ num = NO_HDR_NUM; break; \ ++ default: \ ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unsupported header for parser"));\ ++ num = ILLEGAL_HDR_NUM; break; \ ++} ++ ++#define FM_PCD_MAX_NUM_OF_OPTIONS(clsPlanEntries) ((clsPlanEntries==256)? 8:((clsPlanEntries==128)? 7: ((clsPlanEntries==64)? 6: ((clsPlanEntries==32)? 5:0)))) ++ ++ ++/**************************************************************************//** ++ @Description A structure for initializing a keygen classification plan group ++*//***************************************************************************/ ++typedef struct t_FmPcdKgInterModuleClsPlanGrpParams { ++ uint8_t netEnvId; /* IN */ ++ bool grpExists; /* OUT (unused in FmPcdKgBuildClsPlanGrp)*/ ++ uint8_t clsPlanGrpId; /* OUT */ ++ bool emptyClsPlanGrp; /* OUT */ ++ uint8_t numOfOptions; /* OUT in FmPcdGetSetClsPlanGrpParams IN in FmPcdKgBuildClsPlanGrp*/ ++ protocolOpt_t options[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)]; ++ /* OUT in FmPcdGetSetClsPlanGrpParams IN in FmPcdKgBuildClsPlanGrp*/ ++ uint32_t optVectors[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)]; ++ /* OUT in FmPcdGetSetClsPlanGrpParams IN in FmPcdKgBuildClsPlanGrp*/ ++} t_FmPcdKgInterModuleClsPlanGrpParams; ++ ++typedef struct t_FmPcdLock { ++ t_Handle h_Spinlock; ++ volatile bool flag; ++ t_List node; ++} t_FmPcdLock; ++#define FM_PCD_LOCK_OBJ(ptr) LIST_OBJECT(ptr, t_FmPcdLock, node) ++ ++ ++typedef t_Error (t_FmPortGetSetCcParamsCallback) (t_Handle h_FmPort, ++ t_FmPortGetSetCcParams *p_FmPortGetSetCcParams); ++ ++ ++/***********************************************************************/ ++/* Common API for FM-PCD module */ ++/***********************************************************************/ ++t_Handle FmPcdGetHcHandle(t_Handle h_FmPcd); ++uint32_t FmPcdGetSwPrsOffset(t_Handle h_FmPcd, e_NetHeaderType hdr, uint8_t indexPerHdr); ++uint32_t FmPcdGetLcv(t_Handle h_FmPcd, uint32_t netEnvId, uint8_t hdrNum); ++uint32_t FmPcdGetMacsecLcv(t_Handle h_FmPcd, uint32_t netEnvId); ++void FmPcdIncNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId); ++void FmPcdDecNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId); ++uint8_t FmPcdGetNetEnvId(t_Handle h_NetEnv); ++void FmPcdPortRegister(t_Handle h_FmPcd, t_Handle h_FmPort, uint8_t hardwarePortId); ++uint32_t FmPcdLock(t_Handle h_FmPcd); ++void FmPcdUnlock(t_Handle h_FmPcd, uint32_t intFlags); ++bool FmPcdNetEnvIsHdrExist(t_Handle h_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr); ++t_Error FmPcdFragHcScratchPoolInit(t_Handle h_FmPcd, uint8_t scratchBpid); ++t_Error FmPcdRegisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl); ++t_Error FmPcdUnregisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl); ++bool FmPcdIsAdvancedOffloadSupported(t_Handle h_FmPcd); ++bool FmPcdLockTryLockAll(t_Handle h_FmPcd); ++void FmPcdLockUnlockAll(t_Handle h_FmPcd); ++ ++/***********************************************************************/ ++/* Common API for FM-PCD KG module */ ++/***********************************************************************/ ++uint8_t FmPcdKgGetClsPlanGrpBase(t_Handle h_FmPcd, uint8_t clsPlanGrp); ++uint16_t FmPcdKgGetClsPlanGrpSize(t_Handle h_FmPcd, uint8_t clsPlanGrp); ++t_Error FmPcdKgBuildClsPlanGrp(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_Grp, t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet); ++ ++uint8_t FmPcdKgGetSchemeId(t_Handle h_Scheme); ++#if (DPAA_VERSION >= 11) ++bool FmPcdKgGetVspe(t_Handle h_Scheme); ++#endif /* (DPAA_VERSION >= 11) */ ++uint8_t FmPcdKgGetRelativeSchemeId(t_Handle h_FmPcd, uint8_t schemeId); ++void FmPcdKgDestroyClsPlanGrp(t_Handle h_FmPcd, uint8_t grpId); ++t_Error FmPcdKgCheckInvalidateSchemeSw(t_Handle h_Scheme); ++t_Error FmPcdKgBuildBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_BindPortToSchemes, uint32_t *p_SpReg, bool add); ++bool FmPcdKgHwSchemeIsValid(uint32_t schemeModeReg); ++uint32_t FmPcdKgBuildWriteSchemeActionReg(uint8_t schemeId, bool updateCounter); ++uint32_t FmPcdKgBuildReadSchemeActionReg(uint8_t schemeId); ++uint32_t FmPcdKgBuildWriteClsPlanBlockActionReg(uint8_t grpId); ++uint32_t FmPcdKgBuildWritePortSchemeBindActionReg(uint8_t hardwarePortId); ++uint32_t FmPcdKgBuildReadPortSchemeBindActionReg(uint8_t hardwarePortId); ++uint32_t FmPcdKgBuildWritePortClsPlanBindActionReg(uint8_t hardwarePortId); ++bool FmPcdKgIsSchemeValidSw(t_Handle h_Scheme); ++ ++t_Error FmPcdKgBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind); ++t_Error FmPcdKgUnbindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind); ++uint32_t FmPcdKgGetRequiredAction(t_Handle h_FmPcd, uint8_t schemeId); ++uint32_t FmPcdKgGetPointedOwners(t_Handle h_FmPcd, uint8_t schemeId); ++e_FmPcdDoneAction FmPcdKgGetDoneAction(t_Handle h_FmPcd, uint8_t schemeId); ++e_FmPcdEngine FmPcdKgGetNextEngine(t_Handle h_FmPcd, uint8_t schemeId); ++void FmPcdKgUpdateRequiredAction(t_Handle h_Scheme, uint32_t requiredAction); ++bool FmPcdKgIsDirectPlcr(t_Handle h_FmPcd, uint8_t schemeId); ++bool FmPcdKgIsDistrOnPlcrProfile(t_Handle h_FmPcd, uint8_t schemeId); ++uint16_t FmPcdKgGetRelativeProfileId(t_Handle h_FmPcd, uint8_t schemeId); ++t_Error FmPcdKgCcGetSetParams(t_Handle h_FmPcd, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value); ++t_Error FmPcdKgSetOrBindToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t netEnvId, protocolOpt_t *p_OptArray, uint8_t *p_ClsPlanGrpId, bool *p_IsEmptyClsPlanGrp); ++t_Error FmPcdKgDeleteOrUnbindPortToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId); ++ ++/***********************************************************************/ ++/* Common API for FM-PCD parser module */ ++/***********************************************************************/ ++t_Error FmPcdPrsIncludePortInStatistics(t_Handle p_FmPcd, uint8_t hardwarePortId, bool include); ++ ++/***********************************************************************/ ++/* Common API for FM-PCD policer module */ ++/***********************************************************************/ ++t_Error FmPcdPlcrAllocProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId, uint16_t numOfProfiles); ++t_Error FmPcdPlcrFreeProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId); ++bool FmPcdPlcrIsProfileValid(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++uint16_t FmPcdPlcrGetPortProfilesBase(t_Handle h_FmPcd, uint8_t hardwarePortId); ++uint16_t FmPcdPlcrGetPortNumOfProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId); ++uint32_t FmPcdPlcrBuildWritePlcrActionRegs(uint16_t absoluteProfileId); ++uint32_t FmPcdPlcrBuildCounterProfileReg(e_FmPcdPlcrProfileCounters counter); ++uint32_t FmPcdPlcrBuildWritePlcrActionReg(uint16_t absoluteProfileId); ++uint32_t FmPcdPlcrBuildReadPlcrActionReg(uint16_t absoluteProfileId); ++uint16_t FmPcdPlcrProfileGetAbsoluteId(t_Handle h_Profile); ++t_Error FmPcdPlcrGetAbsoluteIdByProfileParams(t_Handle h_FmPcd, ++ e_FmPcdProfileTypeSelection profileType, ++ t_Handle h_FmPort, ++ uint16_t relativeProfile, ++ uint16_t *p_AbsoluteId); ++void FmPcdPlcrInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++void FmPcdPlcrValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++bool FmPcdPlcrHwProfileIsValid(uint32_t profileModeReg); ++uint32_t FmPcdPlcrGetRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++uint32_t FmPcdPlcrGetPointedOwners(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++void FmPcdPlcrUpatePointedOwner(t_Handle h_FmPcd, uint16_t absoluteProfileId, bool add); ++uint32_t FmPcdPlcrBuildNiaProfileReg(bool green, bool yellow, bool red); ++void FmPcdPlcrUpdateRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId, uint32_t requiredAction); ++t_Error FmPcdPlcrCcGetSetParams(t_Handle h_FmPcd, uint16_t profileIndx,uint32_t requiredAction); ++ ++/***********************************************************************/ ++/* Common API for FM-PCD CC module */ ++/***********************************************************************/ ++uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode); ++uint8_t FmPcdCcGetOffset(t_Handle h_CcNode); ++uint32_t FmPcdCcGetNodeAddrOffset(t_Handle h_FmPcd, t_Handle h_Pointer); ++t_Error FmPcdCcRemoveKey(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, uint16_t keyIndex); ++t_Error FmPcdCcAddKey(t_Handle h_FmPcd, t_Handle h_CcNode, uint16_t keyIndex, uint8_t keySize, t_FmPcdCcKeyParams *p_FmPCdCcKeyParams); ++t_Error FmPcdCcModifyKey(t_Handle h_FmPcd, t_Handle h_CcNode, uint16_t keyIndex, uint8_t keySize, uint8_t *p_Key, uint8_t *p_Mask); ++t_Error FmPcdCcModifyKeyAndNextEngine(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, uint16_t keyIndex, uint8_t keySize, t_FmPcdCcKeyParams *p_FmPcdCcKeyParams); ++t_Error FmPcdCcModifyMissNextEngineParamNode(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++t_Error FmPcdCcModifyNextEngineParamTree(t_Handle h_FmPcd, t_Handle h_FmPcdCcTree, uint8_t grpId, uint8_t index, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++t_Error FmPcdCcModiyNextEngineParamNode(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, uint16_t keyIndex,t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++uint32_t FmPcdCcGetNodeAddrOffsetFromNodeInfo(t_Handle h_FmPcd, t_Handle h_Pointer); ++t_Handle FmPcdCcTreeGetSavedManipParams(t_Handle h_FmTree); ++void FmPcdCcTreeSetSavedManipParams(t_Handle h_FmTree, t_Handle h_SavedManipParams); ++t_Error FmPcdCcTreeAddIPR(t_Handle h_FmPcd, t_Handle h_FmTree, t_Handle h_NetEnv, t_Handle h_IpReassemblyManip, bool schemes); ++t_Error FmPcdCcBindTree(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_CcTree, uint32_t *p_Offset,t_Handle h_FmPort); ++t_Error FmPcdCcUnbindTree(t_Handle h_FmPcd, t_Handle h_CcTree); ++ ++/***********************************************************************/ ++/* Common API for FM-PCD Manip module */ ++/***********************************************************************/ ++t_Error FmPcdManipUpdate(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_FmPort, t_Handle h_Manip, t_Handle h_Ad, bool validate, int level, t_Handle h_FmTree, bool modify); ++uint32_t FmPcdManipGetRequiredAction (t_Handle h_Manip); ++ ++/***********************************************************************/ ++/* Common API for FM-Port module */ ++/***********************************************************************/ ++#if (DPAA_VERSION >= 11) ++typedef enum e_FmPortGprFuncType ++{ ++ e_FM_PORT_GPR_EMPTY = 0, ++ e_FM_PORT_GPR_MURAM_PAGE ++} e_FmPortGprFuncType; ++ ++t_Error FmPortSetGprFunc(t_Handle h_FmPort, e_FmPortGprFuncType gprFunc, void **p_Value); ++#endif /* DPAA_VERSION >= 11) */ ++t_Error FmPortGetSetCcParams(t_Handle h_FmPort, t_FmPortGetSetCcParams *p_FmPortGetSetCcParams); ++uint8_t FmPortGetNetEnvId(t_Handle h_FmPort); ++uint8_t FmPortGetHardwarePortId(t_Handle h_FmPort); ++uint32_t FmPortGetPcdEngines(t_Handle h_FmPort); ++void FmPortPcdKgSwUnbindClsPlanGrp (t_Handle h_FmPort); ++ ++ ++#if (DPAA_VERSION >= 11) ++t_Error FmPcdFrmReplicUpdate(t_Handle h_FmPcd, t_Handle h_FmPort, t_Handle h_FrmReplic); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Function FmRegisterIntr ++ ++ @Description Used to register an inter-module event handler to be processed by FM ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] mod The module that causes the event ++ @Param[in] modId Module id - if more than 1 instansiation of this ++ mode exists,0 otherwise. ++ @Param[in] intrType Interrupt type (error/normal) selection. ++ @Param[in] f_Isr The interrupt service routine. ++ @Param[in] h_Arg Argument to be passed to f_Isr. ++ ++ @Return None. ++*//***************************************************************************/ ++void FmRegisterIntr(t_Handle h_Fm, ++ e_FmEventModules mod, ++ uint8_t modId, ++ e_FmIntrType intrType, ++ void (*f_Isr) (t_Handle h_Arg), ++ t_Handle h_Arg); ++ ++/**************************************************************************//** ++ @Function FmUnregisterIntr ++ ++ @Description Used to un-register an inter-module event handler that was processed by FM ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] mod The module that causes the event ++ @Param[in] modId Module id - if more than 1 instansiation of this ++ mode exists,0 otherwise. ++ @Param[in] intrType Interrupt type (error/normal) selection. ++ ++ @Return None. ++*//***************************************************************************/ ++void FmUnregisterIntr(t_Handle h_Fm, ++ e_FmEventModules mod, ++ uint8_t modId, ++ e_FmIntrType intrType); ++ ++/**************************************************************************//** ++ @Function FmRegisterFmCtlIntr ++ ++ @Description Used to register to one of the fmCtl events in the FM module ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] eventRegId FmCtl event id (0-7). ++ @Param[in] f_Isr The interrupt service routine. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++void FmRegisterFmCtlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Fm, uint32_t event)); ++ ++ ++/**************************************************************************//** ++ @Description enum for defining MAC types ++*//***************************************************************************/ ++typedef enum e_FmMacType { ++ e_FM_MAC_10G = 0, /**< 10G MAC */ ++ e_FM_MAC_1G /**< 1G MAC */ ++} e_FmMacType; ++ ++/**************************************************************************//** ++ @Description Structure for port-FM communication during FM_PORT_Init. ++ Fields commented 'IN' are passed by the port module to be used ++ by the FM module. ++ Fields commented 'OUT' will be filled by FM before returning to port. ++ Some fields are optional (depending on configuration) and ++ will be analized by the port and FM modules accordingly. ++*//***************************************************************************/ ++typedef struct t_FmInterModulePortInitParams { ++ uint8_t hardwarePortId; /**< IN. port Id */ ++ e_FmPortType portType; /**< IN. Port type */ ++ bool independentMode; /**< IN. TRUE if FM Port operates in independent mode */ ++ uint16_t liodnOffset; /**< IN. Port's requested resource */ ++ uint8_t numOfTasks; /**< IN. Port's requested resource */ ++ uint8_t numOfExtraTasks; /**< IN. Port's requested resource */ ++ uint8_t numOfOpenDmas; /**< IN. Port's requested resource */ ++ uint8_t numOfExtraOpenDmas; /**< IN. Port's requested resource */ ++ uint32_t sizeOfFifo; /**< IN. Port's requested resource */ ++ uint32_t extraSizeOfFifo; /**< IN. Port's requested resource */ ++ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */ ++ uint16_t maxFrameLength; /**< IN. Port's max frame length. */ ++ uint16_t liodnBase; /**< IN. Irrelevant for P4080 rev 1. ++ LIODN base for this port, to be ++ used together with LIODN offset. */ ++ t_FmPhysAddr fmMuramPhysBaseAddr;/**< OUT. FM-MURAM physical address*/ ++} t_FmInterModulePortInitParams; ++ ++/**************************************************************************//** ++ @Description Structure for port-FM communication during FM_PORT_Free. ++*//***************************************************************************/ ++typedef struct t_FmInterModulePortFreeParams { ++ uint8_t hardwarePortId; /**< IN. port Id */ ++ e_FmPortType portType; /**< IN. Port type */ ++ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */ ++} t_FmInterModulePortFreeParams; ++ ++/**************************************************************************//** ++ @Function FmGetPcdPrsBaseAddr ++ ++ @Description Get the base address of the Parser from the FM module ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return Base address. ++*//***************************************************************************/ ++uintptr_t FmGetPcdPrsBaseAddr(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetPcdKgBaseAddr ++ ++ @Description Get the base address of the Keygen from the FM module ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return Base address. ++*//***************************************************************************/ ++uintptr_t FmGetPcdKgBaseAddr(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetPcdPlcrBaseAddr ++ ++ @Description Get the base address of the Policer from the FM module ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return Base address. ++*//***************************************************************************/ ++uintptr_t FmGetPcdPlcrBaseAddr(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetMuramHandle ++ ++ @Description Get the handle of the MURAM from the FM module ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return MURAM module handle. ++*//***************************************************************************/ ++t_Handle FmGetMuramHandle(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetPhysicalMuramBase ++ ++ @Description Get the physical base address of the MURAM from the FM module ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] fmPhysAddr Physical MURAM base ++ ++ @Return Physical base address. ++*//***************************************************************************/ ++void FmGetPhysicalMuramBase(t_Handle h_Fm, t_FmPhysAddr *fmPhysAddr); ++ ++/**************************************************************************//** ++ @Function FmGetTimeStampScale ++ ++ @Description Used internally by other modules in order to get the timeStamp ++ period as requested by the application. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return TimeStamp period in nanoseconds. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++uint32_t FmGetTimeStampScale(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmResumeStalledPort ++ ++ @Description Used internally by FM port to release a stalled port. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] hardwarePortId HW port id. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FmResumeStalledPort(t_Handle h_Fm, uint8_t hardwarePortId); ++ ++/**************************************************************************//** ++ @Function FmIsPortStalled ++ ++ @Description Used internally by FM port to read the port's status. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] hardwarePortId HW port id. ++ @Param[in] p_IsStalled A pointer to the boolean port stalled state ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FmIsPortStalled(t_Handle h_Fm, uint8_t hardwarePortId, bool *p_IsStalled); ++ ++/**************************************************************************//** ++ @Function FmResetMac ++ ++ @Description Used by MAC driver to reset the MAC registers ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] type MAC type. ++ @Param[in] macId MAC id - according to type. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FmResetMac(t_Handle h_Fm, e_FmMacType type, uint8_t macId); ++ ++/**************************************************************************//** ++ @Function FmGetClockFreq ++ ++ @Description Used by MAC driver to get the FM clock frequency ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return clock-freq on success; 0 otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++uint16_t FmGetClockFreq(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetId ++ ++ @Description Used by PCD driver to read rhe FM id ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++uint8_t FmGetId(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetSetPortParams ++ ++ @Description Used by FM-PORT driver to pass and receive parameters between ++ PORT and FM modules. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in,out] p_PortParams A structure of FM Port parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FmGetSetPortParams(t_Handle h_Fm,t_FmInterModulePortInitParams *p_PortParams); ++ ++/**************************************************************************//** ++ @Function FmFreePortParams ++ ++ @Description Used by FM-PORT driver to free port's resources within the FM. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in,out] p_PortParams A structure of FM Port parameters. ++ ++ @Return None. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++void FmFreePortParams(t_Handle h_Fm,t_FmInterModulePortFreeParams *p_PortParams); ++ ++/**************************************************************************//** ++ @Function FmSetNumOfRiscsPerPort ++ ++ @Description Used by FM-PORT driver to pass parameter between ++ PORT and FM modules for working with number of RISC.. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] hardwarePortId hardware port Id. ++ @Param[in] numOfFmanCtrls number of Fman Controllers. ++ @Param[in] orFmanCtrl Fman Controller for order restoration. ++ ++ @Return None. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FmSetNumOfRiscsPerPort(t_Handle h_Fm, uint8_t hardwarePortId, uint8_t numOfFmanCtrls, t_FmFmanCtrl orFmanCtrl); ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//* ++ @Function FmDumpPortRegs ++ ++ @Description Dumps FM port registers which are part of FM common registers ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] hardwarePortId HW port id. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only FM_Init(). ++*//***************************************************************************/ ++t_Error FmDumpPortRegs(t_Handle h_Fm,uint8_t hardwarePortId); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++void FmRegisterPcd(t_Handle h_Fm, t_Handle h_FmPcd); ++void FmUnregisterPcd(t_Handle h_Fm); ++t_Handle FmGetPcdHandle(t_Handle h_Fm); ++t_Error FmEnableRamsEcc(t_Handle h_Fm); ++t_Error FmDisableRamsEcc(t_Handle h_Fm); ++void FmGetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo); ++t_Error FmAllocFmanCtrlEventReg(t_Handle h_Fm, uint8_t *p_EventId); ++void FmFreeFmanCtrlEventReg(t_Handle h_Fm, uint8_t eventId); ++void FmSetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, uint32_t enableEvents); ++uint32_t FmGetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId); ++void FmRegisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Fm, uint32_t event), t_Handle h_Arg); ++void FmUnregisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId); ++t_Error FmSetMacMaxFrame(t_Handle h_Fm, e_FmMacType type, uint8_t macId, uint16_t mtu); ++bool FmIsMaster(t_Handle h_Fm); ++uint8_t FmGetGuestId(t_Handle h_Fm); ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++t_Error Fm10GTxEccWorkaround(t_Handle h_Fm, uint8_t macId); ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++void FmMuramClear(t_Handle h_FmMuram); ++t_Error FmSetNumOfOpenDmas(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t *p_NumOfOpenDmas, ++ uint8_t *p_NumOfExtraOpenDmas, ++ bool initialConfig); ++t_Error FmSetNumOfTasks(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t *p_NumOfTasks, ++ uint8_t *p_NumOfExtraTasks, ++ bool initialConfig); ++t_Error FmSetSizeOfFifo(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint32_t *p_SizeOfFifo, ++ uint32_t *p_ExtraSizeOfFifo, ++ bool initialConfig); ++ ++t_Error FmSetCongestionGroupPFCpriority(t_Handle h_Fm, ++ uint32_t congestionGroupId, ++ uint8_t priorityBitMap); ++ ++#if (DPAA_VERSION >= 11) ++t_Error FmVSPAllocForPort(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint8_t numOfStorageProfiles); ++ ++t_Error FmVSPFreeForPort(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId); ++ ++t_Error FmVSPGetAbsoluteProfileId(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint16_t relativeProfile, ++ uint16_t *p_AbsoluteId); ++t_Error FmVSPCheckRelativeProfile(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint16_t relativeProfile); ++ ++uintptr_t FmGetVSPBaseAddr(t_Handle h_Fm); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++#endif /* __FM_COMMON_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/inc/fm_hc.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/inc/fm_hc.h +new file mode 100644 +index 0000000..db2d60b +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/inc/fm_hc.h +@@ -0,0 +1,90 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __FM_HC_H ++#define __FM_HC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "fsl_fman_kg.h" ++ ++#define __ERR_MODULE__ MODULE_FM_PCD ++ ++ ++typedef struct t_FmHcParams { ++ t_Handle h_Fm; ++ t_Handle h_FmPcd; ++ t_FmPcdHcParams params; ++} t_FmHcParams; ++ ++ ++t_Handle FmHcConfigAndInit(t_FmHcParams *p_FmHcParams); ++t_Handle FmGcGetHcPortDevH(t_Handle h_FmHc); ++void FmHcFree(t_Handle h_FmHc); ++t_Error FmHcSetFramesDataMemory(t_Handle h_FmHc, ++ uint8_t memId); ++t_Error FmHcDumpRegs(t_Handle h_FmHc); ++ ++void FmHcTxConf(t_Handle h_FmHc, t_DpaaFD *p_Fd); ++ ++t_Error FmHcPcdKgSetScheme(t_Handle h_FmHc, ++ t_Handle h_Scheme, ++ struct fman_kg_scheme_regs *p_SchemeRegs, ++ bool updateCounter); ++t_Error FmHcPcdKgDeleteScheme(t_Handle h_FmHc, t_Handle h_Scheme); ++t_Error FmHcPcdCcCapwapTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcCapwapReassmTimeoutParams *p_CcCapwapReassmTimeoutParams ); ++t_Error FmHcPcdCcIpFragScratchPollCmd(t_Handle h_FmHc, bool fill, t_FmPcdCcFragScratchPoolCmdParams *p_FmPcdCcFragScratchPoolCmdParams); ++t_Error FmHcPcdCcIpTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcIpReassmTimeoutParams *p_CcIpReassmTimeoutParams, uint8_t *p_Result); ++t_Error FmHcPcdKgSetClsPlan(t_Handle h_FmHc, t_FmPcdKgInterModuleClsPlanSet *p_Set); ++t_Error FmHcPcdKgDeleteClsPlan(t_Handle h_FmHc, uint8_t clsPlanGrpId); ++ ++t_Error FmHcPcdKgSetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t value); ++uint32_t FmHcPcdKgGetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme); ++ ++t_Error FmHcPcdCcDoDynamicChange(t_Handle h_FmHc, uint32_t oldAdAddrOffset, uint32_t newAdAddrOffset); ++ ++t_Error FmHcPcdPlcrSetProfile(t_Handle h_FmHc, t_Handle h_Profile, t_FmPcdPlcrProfileRegs *p_PlcrRegs); ++t_Error FmHcPcdPlcrDeleteProfile(t_Handle h_FmHc, t_Handle h_Profile); ++ ++t_Error FmHcPcdPlcrSetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value); ++uint32_t FmHcPcdPlcrGetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter); ++ ++t_Error FmHcKgWriteSp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t spReg, bool add); ++t_Error FmHcKgWriteCpp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t cppReg); ++ ++t_Error FmHcPcdKgCcGetSetParams(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value); ++t_Error FmHcPcdPlcrCcGetSetParams(t_Handle h_FmHc,uint16_t absoluteProfileId, uint32_t requiredAction); ++ ++ ++ ++#endif /* __FM_HC_H */ +diff --git a/drivers/net/dpa/NetCommSw/Peripherals/FM/inc/fm_sp_common.h b/drivers/net/dpa/NetCommSw/Peripherals/FM/inc/fm_sp_common.h +new file mode 100644 +index 0000000..0675444 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/Peripherals/FM/inc/fm_sp_common.h +@@ -0,0 +1,154 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_sp_common.h ++ ++ @Description FM SP ... ++*//***************************************************************************/ ++#ifndef __FM_SP_COMMON_H ++#define __FM_SP_COMMON_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++ ++#include "fm_ext.h" ++#include "fm_pcd_ext.h" ++ ++ ++/* sizes */ ++#define CAPWAP_FRAG_EXTRA_SPACE 32 ++#define OFFSET_UNITS 16 ++#define MAX_INT_OFFSET 240 ++#define MAX_IC_SIZE 256 ++#define MAX_EXT_OFFSET 496 ++#define MAX_EXT_BUFFER_OFFSET 511 ++ ++/**************************************************************************//** ++ @Description defaults ++*//***************************************************************************/ ++#define DEFAULT_FM_SP_bufferPrefixContent_privDataSize 0 ++#define DEFAULT_FM_SP_bufferPrefixContent_passPrsResult FALSE ++#define DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp FALSE ++#define DEFAULT_FM_SP_bufferPrefixContent_allOtherPCDInfo FALSE ++#define DEFAULT_FM_SP_bufferPrefixContent_dataAlign 64 ++#define DEFAULT_FM_SP_dmaSwapData e_FM_DMA_NO_SWP ++#define DEFAULT_FM_SP_dmaIntContextCacheAttr e_FM_DMA_NO_STASH ++#define DEFAULT_FM_SP_dmaHeaderCacheAttr e_FM_DMA_NO_STASH ++#define DEFAULT_FM_SP_dmaScatterGatherCacheAttr e_FM_DMA_NO_STASH ++#define DEFAULT_FM_SP_dmaWriteOptimize TRUE ++#define DEFAULT_FM_SP_noScatherGather FALSE ++ ++/**************************************************************************//** ++ @Description Registers bit fields ++*//***************************************************************************/ ++#define FM_SP_EXT_BUF_POOL_EN_COUNTER 0x40000000 ++#define FM_SP_EXT_BUF_POOL_VALID 0x80000000 ++#define FM_SP_EXT_BUF_POOL_BACKUP 0x20000000 ++#define FM_SP_DMA_ATTR_WRITE_OPTIMIZE 0x00100000 ++#define FM_SP_SG_DISABLE 0x80000000 ++ ++/* shifts */ ++#define FM_SP_EXT_BUF_POOL_ID_SHIFT 16 ++#define FM_SP_POOL_DEP_NUM_OF_POOLS_SHIFT 16 ++#define FM_SP_EXT_BUF_MARG_START_SHIFT 16 ++#define FM_SP_EXT_BUF_MARG_END_SHIFT 0 ++#define FM_SP_DMA_ATTR_SWP_SHIFT 30 ++#define FM_SP_DMA_ATTR_IC_CACHE_SHIFT 28 ++#define FM_SP_DMA_ATTR_HDR_CACHE_SHIFT 26 ++#define FM_SP_DMA_ATTR_SG_CACHE_SHIFT 24 ++#define FM_SP_IC_TO_EXT_SHIFT 16 ++#define FM_SP_IC_FROM_INT_SHIFT 8 ++#define FM_SP_IC_SIZE_SHIFT 0 ++ ++ ++/**************************************************************************//** ++ @Description structure for defining internal context copying ++*//***************************************************************************/ ++typedef struct ++{ ++ uint16_t extBufOffset; /**< Offset in External buffer to which internal ++ context is copied to (Rx) or taken from (Tx, Op). */ ++ uint8_t intContextOffset; /**< Offset within internal context to copy from ++ (Rx) or to copy to (Tx, Op). */ ++ uint16_t size; /**< Internal offset size to be copied */ ++} t_FmSpIntContextDataCopy; ++ ++/**************************************************************************//** ++ @Description struct for defining external buffer margins ++*//***************************************************************************/ ++typedef struct { ++ uint16_t startMargins; /**< Number of bytes to be left at the beginning ++ of the external buffer (must be divisible by 16) */ ++ uint16_t endMargins; /**< number of bytes to be left at the end ++ of the external buffer(must be divisible by 16) */ ++} t_FmSpBufMargins; ++ ++typedef struct { ++ uint32_t dataOffset; ++ uint32_t prsResultOffset; ++ uint32_t timeStampOffset; ++ uint32_t hashResultOffset; ++ uint32_t pcdInfoOffset; ++ uint32_t manipOffset; ++} t_FmSpBufferOffsets; ++ ++ ++t_Error FmSpBuildBufferStructure(t_FmSpIntContextDataCopy *p_FmPortIntContextDataCopy, ++ t_FmBufferPrefixContent *p_BufferPrefixContent, ++ t_FmSpBufMargins *p_FmPortBufMargins, ++ t_FmSpBufferOffsets *p_FmPortBufferOffsets, ++ uint8_t *internalBufferOffset); ++ ++t_Error FmSpCheckIntContextParams(t_FmSpIntContextDataCopy *p_FmSpIntContextDataCopy); ++t_Error FmSpCheckBufPoolsParams(t_FmExtPools *p_FmExtPools, ++ t_FmBackupBmPools *p_FmBackupBmPools, ++ t_FmBufPoolDepletion *p_FmBufPoolDepletion); ++t_Error FmSpCheckBufMargins(t_FmSpBufMargins *p_FmSpBufMargins); ++void FmSpSetBufPoolsInAscOrderOfBufSizes(t_FmExtPools *p_FmExtPools, uint8_t *orderedArray, uint16_t *sizesArray); ++ ++t_Error FmPcdSpAllocProfiles(t_Handle h_FmPcd, ++ uint8_t hardwarePortId, ++ uint16_t numOfStorageProfiles, ++ uint16_t *base, ++ uint8_t *log2Num); ++t_Error FmPcdSpGetAbsoluteProfileId(t_Handle h_FmPcd, ++ t_Handle h_FmPort, ++ uint16_t relativeProfile, ++ uint16_t *p_AbsoluteId); ++void SpInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++void SpValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++ ++ ++#endif /* __FM_SP_COMMON_H */ +diff --git a/drivers/net/dpa/NetCommSw/etc/Makefile b/drivers/net/dpa/NetCommSw/etc/Makefile +new file mode 100644 +index 0000000..ed10553 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/etc/Makefile +@@ -0,0 +1,11 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++ ++obj-y += fsl-ncsw-etc.o ++ ++fsl-ncsw-etc-objs := mm.o memcpy.o sprint.o list.o error.o +diff --git a/drivers/net/dpa/NetCommSw/etc/error.c b/drivers/net/dpa/NetCommSw/etc/error.c +new file mode 100644 +index 0000000..fead7f50 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/etc/error.c +@@ -0,0 +1,95 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 error.c ++ ++ @Description General errors and events reporting utilities. ++*//***************************************************************************/ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++#include "error_ext.h" ++ ++ ++const char *dbgLevelStrings[] = ++{ ++ "CRITICAL" ++ ,"MAJOR" ++ ,"MINOR" ++ ,"WARNING" ++ ,"INFO" ++ ,"TRACE" ++}; ++ ++ ++char * ErrTypeStrings (e_ErrorType err) ++{ ++ switch (err) ++ { ++ case (E_OK): return "OK"; ++ case (E_WRITE_FAILED): return "Write Access Failed"; ++ case (E_NO_DEVICE): return "No Device"; ++ case (E_NOT_AVAILABLE): return "Resource Is Unavailable"; ++ case (E_NO_MEMORY): return "Memory Allocation Failed"; ++ case (E_INVALID_ADDRESS): return "Invalid Address"; ++ case (E_BUSY): return "Resource Is Busy"; ++ case (E_ALREADY_EXISTS): return "Resource Already Exists"; ++ case (E_INVALID_OPERATION): return "Invalid Operation"; ++ case (E_INVALID_VALUE): return "Invalid Value"; ++ case (E_NOT_IN_RANGE): return "Value Out Of Range"; ++ case (E_NOT_SUPPORTED): return "Unsupported Operation"; ++ case (E_INVALID_STATE): return "Invalid State"; ++ case (E_INVALID_HANDLE): return "Invalid Handle"; ++ case (E_INVALID_ID): return "Invalid ID"; ++ case (E_NULL_POINTER): return "Unexpected NULL Pointer"; ++ case (E_INVALID_SELECTION): return "Invalid Selection"; ++ case (E_INVALID_COMM_MODE): return "Invalid Communication Mode"; ++ case (E_INVALID_MEMORY_TYPE): return "Invalid Memory Type"; ++ case (E_INVALID_CLOCK): return "Invalid Clock"; ++ case (E_CONFLICT): return "Conflict In Settings"; ++ case (E_NOT_ALIGNED): return "Incorrect Alignment"; ++ case (E_NOT_FOUND): return "Resource Not Found"; ++ case (E_FULL): return "Resource Is Full"; ++ case (E_EMPTY): return "Resource Is Empty"; ++ case (E_ALREADY_FREE): return "Resource Already Free"; ++ case (E_READ_FAILED): return "Read Access Failed"; ++ case (E_INVALID_FRAME): return "Invalid Frame"; ++ case (E_SEND_FAILED): return "Send Operation Failed"; ++ case (E_RECEIVE_FAILED): return "Receive Operation Failed"; ++ case (E_TIMEOUT): return "Operation Timed Out"; ++ default: ++ break; ++ } ++ return NULL; ++} ++#endif /* (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) */ +diff --git a/drivers/net/dpa/NetCommSw/etc/list.c b/drivers/net/dpa/NetCommSw/etc/list.c +new file mode 100644 +index 0000000..2d044be +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/etc/list.c +@@ -0,0 +1,71 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 list.c ++ ++ @Description Implementation of list. ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "list_ext.h" ++ ++ ++void LIST_Append(t_List *p_NewList, t_List *p_Head) ++{ ++ t_List *p_First = LIST_FIRST(p_NewList); ++ ++ if (p_First != p_NewList) ++ { ++ t_List *p_Last = LIST_LAST(p_NewList); ++ t_List *p_Cur = LIST_NEXT(p_Head); ++ ++ LIST_PREV(p_First) = p_Head; ++ LIST_FIRST(p_Head) = p_First; ++ LIST_NEXT(p_Last) = p_Cur; ++ LIST_LAST(p_Cur) = p_Last; ++ } ++} ++ ++ ++int LIST_NumOfObjs(t_List *p_List) ++{ ++ t_List *p_Tmp; ++ int numOfObjs = 0; ++ ++ if (!LIST_IsEmpty(p_List)) ++ LIST_FOR_EACH(p_Tmp, p_List) ++ numOfObjs++; ++ ++ return numOfObjs; ++} +diff --git a/drivers/net/dpa/NetCommSw/etc/memcpy.c b/drivers/net/dpa/NetCommSw/etc/memcpy.c +new file mode 100644 +index 0000000..02973e5 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/etc/memcpy.c +@@ -0,0 +1,601 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "std_ext.h" ++#include "xx_ext.h" ++#include "memcpy_ext.h" ++ ++ ++void * MemCpy32(void* pDst,void* pSrc, uint32_t size) ++{ ++ uint32_t leftAlign; ++ uint32_t rightAlign; ++ uint32_t lastWord; ++ uint32_t currWord; ++ uint32_t *p_Src32; ++ uint32_t *p_Dst32; ++ uint8_t *p_Src8; ++ uint8_t *p_Dst8; ++ ++ p_Src8 = (uint8_t*)(pSrc); ++ p_Dst8 = (uint8_t*)(pDst); ++ /* first copy byte by byte till the source first alignment ++ * this step is necessary to ensure we do not even try to access ++ * data which is before the source buffer, hence it is not ours. ++ */ ++ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */ ++ { ++ *p_Dst8++ = *p_Src8++; ++ size--; ++ } ++ ++ /* align destination (possibly disaligning source)*/ ++ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */ ++ { ++ *p_Dst8++ = *p_Src8++; ++ size--; ++ } ++ ++ /* dest is aligned and source is not necessarily aligned */ ++ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */ ++ rightAlign = 32 - leftAlign; ++ ++ ++ if (leftAlign == 0) ++ { ++ /* source is also aligned */ ++ p_Src32 = (uint32_t*)(p_Src8); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ while (size >> 2) /* size >= 4 */ ++ { ++ *p_Dst32++ = *p_Src32++; ++ size -= 4; ++ } ++ p_Src8 = (uint8_t*)(p_Src32); ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ } ++ else ++ { ++ /* source is not aligned (destination is aligned)*/ ++ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3)); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ lastWord = *p_Src32++; ++ while(size >> 3) /* size >= 8 */ ++ { ++ currWord = *p_Src32; ++ *p_Dst32 = (lastWord << leftAlign) | (currWord >> rightAlign); ++ lastWord = currWord; ++ p_Src32++; ++ p_Dst32++; ++ size -= 4; ++ } ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3); ++ } ++ ++ /* complete the left overs */ ++ while (size--) ++ *p_Dst8++ = *p_Src8++; ++ ++ return pDst; ++} ++ ++void * IO2IOCpy32(void* pDst,void* pSrc, uint32_t size) ++{ ++ uint32_t leftAlign; ++ uint32_t rightAlign; ++ uint32_t lastWord; ++ uint32_t currWord; ++ uint32_t *p_Src32; ++ uint32_t *p_Dst32; ++ uint8_t *p_Src8; ++ uint8_t *p_Dst8; ++ ++ p_Src8 = (uint8_t*)(pSrc); ++ p_Dst8 = (uint8_t*)(pDst); ++ /* first copy byte by byte till the source first alignment ++ * this step is necessary to ensure we do not even try to access ++ * data which is before the source buffer, hence it is not ours. ++ */ ++ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */ ++ { ++ WRITE_UINT8(*p_Dst8, GET_UINT8(*p_Src8)); ++ p_Dst8++;p_Src8++; ++ size--; ++ } ++ ++ /* align destination (possibly disaligning source)*/ ++ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */ ++ { ++ WRITE_UINT8(*p_Dst8, GET_UINT8(*p_Src8)); ++ p_Dst8++;p_Src8++; ++ size--; ++ } ++ ++ /* dest is aligned and source is not necessarily aligned */ ++ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */ ++ rightAlign = 32 - leftAlign; ++ ++ if (leftAlign == 0) ++ { ++ /* source is also aligned */ ++ p_Src32 = (uint32_t*)(p_Src8); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ while (size >> 2) /* size >= 4 */ ++ { ++ WRITE_UINT32(*p_Dst32, GET_UINT32(*p_Src32)); ++ p_Dst32++;p_Src32++; ++ size -= 4; ++ } ++ p_Src8 = (uint8_t*)(p_Src32); ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ } ++ else ++ { ++ /* source is not aligned (destination is aligned)*/ ++ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3)); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ lastWord = GET_UINT32(*p_Src32); ++ p_Src32++; ++ while(size >> 3) /* size >= 8 */ ++ { ++ currWord = GET_UINT32(*p_Src32); ++ WRITE_UINT32(*p_Dst32, (lastWord << leftAlign) | (currWord >> rightAlign)); ++ lastWord = currWord; ++ p_Src32++;p_Dst32++; ++ size -= 4; ++ } ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3); ++ } ++ ++ /* complete the left overs */ ++ while (size--) ++ { ++ WRITE_UINT8(*p_Dst8, GET_UINT8(*p_Src8)); ++ p_Dst8++;p_Src8++; ++ } ++ ++ return pDst; ++} ++ ++void * Mem2IOCpy32(void* pDst,void* pSrc, uint32_t size) ++{ ++ uint32_t leftAlign; ++ uint32_t rightAlign; ++ uint32_t lastWord; ++ uint32_t currWord; ++ uint32_t *p_Src32; ++ uint32_t *p_Dst32; ++ uint8_t *p_Src8; ++ uint8_t *p_Dst8; ++ ++ p_Src8 = (uint8_t*)(pSrc); ++ p_Dst8 = (uint8_t*)(pDst); ++ /* first copy byte by byte till the source first alignment ++ * this step is necessary to ensure we do not even try to access ++ * data which is before the source buffer, hence it is not ours. ++ */ ++ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */ ++ { ++ WRITE_UINT8(*p_Dst8, *p_Src8); ++ p_Dst8++;p_Src8++; ++ size--; ++ } ++ ++ /* align destination (possibly disaligning source)*/ ++ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */ ++ { ++ WRITE_UINT8(*p_Dst8, *p_Src8); ++ p_Dst8++;p_Src8++; ++ size--; ++ } ++ ++ /* dest is aligned and source is not necessarily aligned */ ++ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */ ++ rightAlign = 32 - leftAlign; ++ ++ if (leftAlign == 0) ++ { ++ /* source is also aligned */ ++ p_Src32 = (uint32_t*)(p_Src8); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ while (size >> 2) /* size >= 4 */ ++ { ++ WRITE_UINT32(*p_Dst32, *p_Src32); ++ p_Dst32++;p_Src32++; ++ size -= 4; ++ } ++ p_Src8 = (uint8_t*)(p_Src32); ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ } ++ else ++ { ++ /* source is not aligned (destination is aligned)*/ ++ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3)); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ lastWord = *p_Src32++; ++ while(size >> 3) /* size >= 8 */ ++ { ++ currWord = *p_Src32; ++ WRITE_UINT32(*p_Dst32, (lastWord << leftAlign) | (currWord >> rightAlign)); ++ lastWord = currWord; ++ p_Src32++;p_Dst32++; ++ size -= 4; ++ } ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3); ++ } ++ ++ /* complete the left overs */ ++ while (size--) ++ { ++ WRITE_UINT8(*p_Dst8, *p_Src8); ++ p_Dst8++;p_Src8++; ++ } ++ ++ return pDst; ++} ++ ++void * IO2MemCpy32(void* pDst,void* pSrc, uint32_t size) ++{ ++ uint32_t leftAlign; ++ uint32_t rightAlign; ++ uint32_t lastWord; ++ uint32_t currWord; ++ uint32_t *p_Src32; ++ uint32_t *p_Dst32; ++ uint8_t *p_Src8; ++ uint8_t *p_Dst8; ++ ++ p_Src8 = (uint8_t*)(pSrc); ++ p_Dst8 = (uint8_t*)(pDst); ++ /* first copy byte by byte till the source first alignment ++ * this step is necessary to ensure we do not even try to access ++ * data which is before the source buffer, hence it is not ours. ++ */ ++ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */ ++ { ++ *p_Dst8 = GET_UINT8(*p_Src8); ++ p_Dst8++;p_Src8++; ++ size--; ++ } ++ ++ /* align destination (possibly disaligning source)*/ ++ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */ ++ { ++ *p_Dst8 = GET_UINT8(*p_Src8); ++ p_Dst8++;p_Src8++; ++ size--; ++ } ++ ++ /* dest is aligned and source is not necessarily aligned */ ++ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */ ++ rightAlign = 32 - leftAlign; ++ ++ if (leftAlign == 0) ++ { ++ /* source is also aligned */ ++ p_Src32 = (uint32_t*)(p_Src8); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ while (size >> 2) /* size >= 4 */ ++ { ++ *p_Dst32 = GET_UINT32(*p_Src32); ++ p_Dst32++;p_Src32++; ++ size -= 4; ++ } ++ p_Src8 = (uint8_t*)(p_Src32); ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ } ++ else ++ { ++ /* source is not aligned (destination is aligned)*/ ++ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3)); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ lastWord = GET_UINT32(*p_Src32); ++ p_Src32++; ++ while(size >> 3) /* size >= 8 */ ++ { ++ currWord = GET_UINT32(*p_Src32); ++ *p_Dst32 = (lastWord << leftAlign) | (currWord >> rightAlign); ++ lastWord = currWord; ++ p_Src32++;p_Dst32++; ++ size -= 4; ++ } ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3); ++ } ++ ++ /* complete the left overs */ ++ while (size--) ++ { ++ *p_Dst8 = GET_UINT8(*p_Src8); ++ p_Dst8++;p_Src8++; ++ } ++ ++ return pDst; ++} ++ ++void * MemCpy64(void* pDst,void* pSrc, uint32_t size) ++{ ++ uint32_t leftAlign; ++ uint32_t rightAlign; ++ uint64_t lastWord; ++ uint64_t currWord; ++ uint64_t *pSrc64; ++ uint64_t *pDst64; ++ uint8_t *p_Src8; ++ uint8_t *p_Dst8; ++ ++ p_Src8 = (uint8_t*)(pSrc); ++ p_Dst8 = (uint8_t*)(pDst); ++ /* first copy byte by byte till the source first alignment ++ * this step is necessarily to ensure we do not even try to access ++ * data which is before the source buffer, hence it is not ours. ++ */ ++ while((PTR_TO_UINT(p_Src8) & 7) && size) /* (pSrc mod 8) > 0 and size > 0 */ ++ { ++ *p_Dst8++ = *p_Src8++; ++ size--; ++ } ++ ++ /* align destination (possibly disaligning source)*/ ++ while((PTR_TO_UINT(p_Dst8) & 7) && size) /* (pDst mod 8) > 0 and size > 0 */ ++ { ++ *p_Dst8++ = *p_Src8++; ++ size--; ++ } ++ ++ /* dest is aligned and source is not necessarily aligned */ ++ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 7) << 3); /* leftAlign = (pSrc mod 8)*8 */ ++ rightAlign = 64 - leftAlign; ++ ++ ++ if (leftAlign == 0) ++ { ++ /* source is also aligned */ ++ pSrc64 = (uint64_t*)(p_Src8); ++ pDst64 = (uint64_t*)(p_Dst8); ++ while (size >> 3) /* size >= 8 */ ++ { ++ *pDst64++ = *pSrc64++; ++ size -= 8; ++ } ++ p_Src8 = (uint8_t*)(pSrc64); ++ p_Dst8 = (uint8_t*)(pDst64); ++ } ++ else ++ { ++ /* source is not aligned (destination is aligned)*/ ++ pSrc64 = (uint64_t*)(p_Src8 - (leftAlign >> 3)); ++ pDst64 = (uint64_t*)(p_Dst8); ++ lastWord = *pSrc64++; ++ while(size >> 4) /* size >= 16 */ ++ { ++ currWord = *pSrc64; ++ *pDst64 = (lastWord << leftAlign) | (currWord >> rightAlign); ++ lastWord = currWord; ++ pSrc64++; ++ pDst64++; ++ size -= 8; ++ } ++ p_Dst8 = (uint8_t*)(pDst64); ++ p_Src8 = (uint8_t*)(pSrc64) - 8 + (leftAlign >> 3); ++ } ++ ++ /* complete the left overs */ ++ while (size--) ++ *p_Dst8++ = *p_Src8++; ++ ++ return pDst; ++} ++ ++void * MemSet32(void* pDst, uint8_t val, uint32_t size) ++{ ++ uint32_t val32; ++ uint32_t *p_Dst32; ++ uint8_t *p_Dst8; ++ ++ p_Dst8 = (uint8_t*)(pDst); ++ ++ /* generate four 8-bit val's in 32-bit container */ ++ val32 = (uint32_t) val; ++ val32 |= (val32 << 8); ++ val32 |= (val32 << 16); ++ ++ /* align destination to 32 */ ++ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */ ++ { ++ *p_Dst8++ = val; ++ size--; ++ } ++ ++ /* 32-bit chunks */ ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ while (size >> 2) /* size >= 4 */ ++ { ++ *p_Dst32++ = val32; ++ size -= 4; ++ } ++ ++ /* complete the leftovers */ ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ while (size--) ++ *p_Dst8++ = val; ++ ++ return pDst; ++} ++ ++void * IOMemSet32(void* pDst, uint8_t val, uint32_t size) ++{ ++ uint32_t val32; ++ uint32_t *p_Dst32; ++ uint8_t *p_Dst8; ++ ++ p_Dst8 = (uint8_t*)(pDst); ++ ++ /* generate four 8-bit val's in 32-bit container */ ++ val32 = (uint32_t) val; ++ val32 |= (val32 << 8); ++ val32 |= (val32 << 16); ++ ++ /* align destination to 32 */ ++ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */ ++ { ++ WRITE_UINT8(*p_Dst8, val); ++ p_Dst8++; ++ size--; ++ } ++ ++ /* 32-bit chunks */ ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ while (size >> 2) /* size >= 4 */ ++ { ++ WRITE_UINT32(*p_Dst32, val32); ++ p_Dst32++; ++ size -= 4; ++ } ++ ++ /* complete the leftovers */ ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ while (size--) ++ { ++ WRITE_UINT8(*p_Dst8, val); ++ p_Dst8++; ++ } ++ ++ return pDst; ++} ++ ++void * MemSet64(void* pDst, uint8_t val, uint32_t size) ++{ ++ uint64_t val64; ++ uint64_t *pDst64; ++ uint8_t *p_Dst8; ++ ++ p_Dst8 = (uint8_t*)(pDst); ++ ++ /* generate four 8-bit val's in 32-bit container */ ++ val64 = (uint64_t) val; ++ val64 |= (val64 << 8); ++ val64 |= (val64 << 16); ++ val64 |= (val64 << 24); ++ val64 |= (val64 << 32); ++ ++ /* align destination to 64 */ ++ while((PTR_TO_UINT(p_Dst8) & 7) && size) /* (pDst mod 8) > 0 and size > 0 */ ++ { ++ *p_Dst8++ = val; ++ size--; ++ } ++ ++ /* 64-bit chunks */ ++ pDst64 = (uint64_t*)(p_Dst8); ++ while (size >> 4) /* size >= 8 */ ++ { ++ *pDst64++ = val64; ++ size -= 8; ++ } ++ ++ /* complete the leftovers */ ++ p_Dst8 = (uint8_t*)(pDst64); ++ while (size--) ++ *p_Dst8++ = val; ++ ++ return pDst; ++} ++ ++void MemDisp(uint8_t *p, int size) ++{ ++ uint32_t space = (uint32_t)(PTR_TO_UINT(p) & 0x3); ++ uint8_t *p_Limit; ++ ++ if (space) ++ { ++ p_Limit = (p - space + 4); ++ ++ XX_Print("0x%08X: ", (p - space)); ++ ++ while (space--) ++ { ++ XX_Print("--"); ++ } ++ while (size && (p < p_Limit)) ++ { ++ XX_Print("%02x", *(uint8_t*)p); ++ size--; ++ p++; ++ } ++ ++ XX_Print(" "); ++ p_Limit += 12; ++ ++ while ((size > 3) && (p < p_Limit)) ++ { ++ XX_Print("%08x ", *(uint32_t*)p); ++ size -= 4; ++ p += 4; ++ } ++ XX_Print("\r\n"); ++ } ++ ++ while (size > 15) ++ { ++ XX_Print("0x%08X: %08x %08x %08x %08x\r\n", ++ p, *(uint32_t *)p, *(uint32_t *)(p + 4), ++ *(uint32_t *)(p + 8), *(uint32_t *)(p + 12)); ++ size -= 16; ++ p += 16; ++ } ++ ++ if (size) ++ { ++ XX_Print("0x%08X: ", p); ++ ++ while (size > 3) ++ { ++ XX_Print("%08x ", *(uint32_t *)p); ++ size -= 4; ++ p += 4; ++ } ++ while (size) ++ { ++ XX_Print("%02x", *(uint8_t *)p); ++ size--; ++ p++; ++ } ++ ++ XX_Print("\r\n"); ++ } ++} +diff --git a/drivers/net/dpa/NetCommSw/etc/mm.c b/drivers/net/dpa/NetCommSw/etc/mm.c +new file mode 100644 +index 0000000..7b9d201 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/etc/mm.c +@@ -0,0 +1,1142 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "string_ext.h" ++#include "error_ext.h" ++#include "std_ext.h" ++#include "part_ext.h" ++#include "xx_ext.h" ++ ++#include "mm.h" ++ ++ ++ ++ ++/********************************************************************** ++ * MM internal routines set * ++ **********************************************************************/ ++ ++/**************************************************************** ++ * Routine: CreateBusyBlock ++ * ++ * Description: ++ * Initializes a new busy block of "size" bytes and started ++ * rom "base" address. Each busy block has a name that ++ * specified the purpose of the memory allocation. ++ * ++ * Arguments: ++ * base - base address of the busy block ++ * size - size of the busy block ++ * name - name that specified the busy block ++ * ++ * Return value: ++ * A pointer to new created structure returned on success; ++ * Otherwise, NULL. ++ ****************************************************************/ ++static t_BusyBlock * CreateBusyBlock(uint64_t base, uint64_t size, char *name) ++{ ++ t_BusyBlock *p_BusyBlock; ++ uint32_t n; ++ ++ p_BusyBlock = (t_BusyBlock *)XX_Malloc(sizeof(t_BusyBlock)); ++ if ( !p_BusyBlock ) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ return NULL; ++ } ++ ++ p_BusyBlock->base = base; ++ p_BusyBlock->end = base + size; ++ ++ n = strlen(name); ++ if (n >= MM_MAX_NAME_LEN) ++ n = MM_MAX_NAME_LEN - 1; ++ strncpy(p_BusyBlock->name, name, MM_MAX_NAME_LEN-1); ++ p_BusyBlock->name[n] = '\0'; ++ p_BusyBlock->p_Next = 0; ++ ++ return p_BusyBlock; ++} ++ ++/**************************************************************** ++ * Routine: CreateNewBlock ++ * ++ * Description: ++ * Initializes a new memory block of "size" bytes and started ++ * from "base" address. ++ * ++ * Arguments: ++ * base - base address of the memory block ++ * size - size of the memory block ++ * ++ * Return value: ++ * A pointer to new created structure returned on success; ++ * Otherwise, NULL. ++ ****************************************************************/ ++static t_MemBlock * CreateNewBlock(uint64_t base, uint64_t size) ++{ ++ t_MemBlock *p_MemBlock; ++ ++ p_MemBlock = (t_MemBlock *)XX_Malloc(sizeof(t_MemBlock)); ++ if ( !p_MemBlock ) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ return NULL; ++ } ++ ++ p_MemBlock->base = base; ++ p_MemBlock->end = base+size; ++ p_MemBlock->p_Next = 0; ++ ++ return p_MemBlock; ++} ++ ++/**************************************************************** ++ * Routine: CreateFreeBlock ++ * ++ * Description: ++ * Initializes a new free block of of "size" bytes and ++ * started from "base" address. ++ * ++ * Arguments: ++ * base - base address of the free block ++ * size - size of the free block ++ * ++ * Return value: ++ * A pointer to new created structure returned on success; ++ * Otherwise, NULL. ++ ****************************************************************/ ++static t_FreeBlock * CreateFreeBlock(uint64_t base, uint64_t size) ++{ ++ t_FreeBlock *p_FreeBlock; ++ ++ p_FreeBlock = (t_FreeBlock *)XX_Malloc(sizeof(t_FreeBlock)); ++ if ( !p_FreeBlock ) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ return NULL; ++ } ++ ++ p_FreeBlock->base = base; ++ p_FreeBlock->end = base + size; ++ p_FreeBlock->p_Next = 0; ++ ++ return p_FreeBlock; ++} ++ ++/**************************************************************** ++ * Routine: AddFree ++ * ++ * Description: ++ * Adds a new free block to the free lists. It updates each ++ * free list to include a new free block. ++ * Note, that all free block in each free list are ordered ++ * by their base address. ++ * ++ * Arguments: ++ * p_MM - pointer to the MM object ++ * base - base address of a given free block ++ * end - end address of a given free block ++ * ++ * Return value: ++ * ++ * ++ ****************************************************************/ ++static t_Error AddFree(t_MM *p_MM, uint64_t base, uint64_t end) ++{ ++ t_FreeBlock *p_PrevB, *p_CurrB, *p_NewB; ++ uint64_t alignment; ++ uint64_t alignBase; ++ int i; ++ ++ /* Updates free lists to include a just released block */ ++ for (i=0; i <= MM_MAX_ALIGNMENT; i++) ++ { ++ p_PrevB = p_NewB = 0; ++ p_CurrB = p_MM->freeBlocks[i]; ++ ++ alignment = (uint64_t)(0x1 << i); ++ alignBase = MAKE_ALIGNED(base, alignment); ++ ++ /* Goes to the next free list if there is no block to free */ ++ if (alignBase >= end) ++ continue; ++ ++ /* Looks for a free block that should be updated */ ++ while ( p_CurrB ) ++ { ++ if ( alignBase <= p_CurrB->end ) ++ { ++ if ( end > p_CurrB->end ) ++ { ++ t_FreeBlock *p_NextB; ++ while ( p_CurrB->p_Next && end > p_CurrB->p_Next->end ) ++ { ++ p_NextB = p_CurrB->p_Next; ++ p_CurrB->p_Next = p_CurrB->p_Next->p_Next; ++ XX_Free(p_NextB); ++ } ++ ++ p_NextB = p_CurrB->p_Next; ++ if ( !p_NextB || (p_NextB && end < p_NextB->base) ) ++ { ++ p_CurrB->end = end; ++ } ++ else ++ { ++ p_CurrB->end = p_NextB->end; ++ p_CurrB->p_Next = p_NextB->p_Next; ++ XX_Free(p_NextB); ++ } ++ } ++ else if ( (end < p_CurrB->base) && ((end-alignBase) >= alignment) ) ++ { ++ if ((p_NewB = CreateFreeBlock(alignBase, end-alignBase)) == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ ++ p_NewB->p_Next = p_CurrB; ++ if (p_PrevB) ++ p_PrevB->p_Next = p_NewB; ++ else ++ p_MM->freeBlocks[i] = p_NewB; ++ break; ++ } ++ ++ if ((alignBase < p_CurrB->base) && (end >= p_CurrB->base)) ++ { ++ p_CurrB->base = alignBase; ++ } ++ ++ /* if size of the free block is less then alignment ++ * deletes that free block from the free list. */ ++ if ( (p_CurrB->end - p_CurrB->base) < alignment) ++ { ++ if ( p_PrevB ) ++ p_PrevB->p_Next = p_CurrB->p_Next; ++ else ++ p_MM->freeBlocks[i] = p_CurrB->p_Next; ++ XX_Free(p_CurrB); ++ } ++ break; ++ } ++ else ++ { ++ p_PrevB = p_CurrB; ++ p_CurrB = p_CurrB->p_Next; ++ } ++ } ++ ++ /* If no free block found to be updated, insert a new free block ++ * to the end of the free list. ++ */ ++ if ( !p_CurrB && ((((uint64_t)(end-base)) & ((uint64_t)(alignment-1))) == 0) ) ++ { ++ if ((p_NewB = CreateFreeBlock(alignBase, end-base)) == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ ++ if (p_PrevB) ++ p_PrevB->p_Next = p_NewB; ++ else ++ p_MM->freeBlocks[i] = p_NewB; ++ } ++ ++ /* Update boundaries of the new free block */ ++ if ((alignment == 1) && !p_NewB) ++ { ++ if ( p_CurrB && base > p_CurrB->base ) ++ base = p_CurrB->base; ++ if ( p_CurrB && end < p_CurrB->end ) ++ end = p_CurrB->end; ++ } ++ } ++ ++ return (E_OK); ++} ++ ++/**************************************************************** ++ * Routine: CutFree ++ * ++ * Description: ++ * Cuts a free block from holdBase to holdEnd from the free lists. ++ * That is, it updates all free lists of the MM object do ++ * not include a block of memory from holdBase to holdEnd. ++ * For each free lists it seek for a free block that holds ++ * either holdBase or holdEnd. If such block is found it updates it. ++ * ++ * Arguments: ++ * p_MM - pointer to the MM object ++ * holdBase - base address of the allocated block ++ * holdEnd - end address of the allocated block ++ * ++ * Return value: ++ * E_OK is returned on success, ++ * otherwise returns an error code. ++ * ++ ****************************************************************/ ++static t_Error CutFree(t_MM *p_MM, uint64_t holdBase, uint64_t holdEnd) ++{ ++ t_FreeBlock *p_PrevB, *p_CurrB, *p_NewB; ++ uint64_t alignBase, base, end; ++ uint64_t alignment; ++ int i; ++ ++ for (i=0; i <= MM_MAX_ALIGNMENT; i++) ++ { ++ p_PrevB = p_NewB = 0; ++ p_CurrB = p_MM->freeBlocks[i]; ++ ++ alignment = (uint64_t)(0x1 << i); ++ alignBase = MAKE_ALIGNED(holdEnd, alignment); ++ ++ while ( p_CurrB ) ++ { ++ base = p_CurrB->base; ++ end = p_CurrB->end; ++ ++ if ( (holdBase <= base) && (holdEnd <= end) && (holdEnd > base) ) ++ { ++ if ( alignBase >= end || ++ (alignBase < end && ((end-alignBase) < alignment)) ) ++ { ++ if (p_PrevB) ++ p_PrevB->p_Next = p_CurrB->p_Next; ++ else ++ p_MM->freeBlocks[i] = p_CurrB->p_Next; ++ XX_Free(p_CurrB); ++ } ++ else ++ { ++ p_CurrB->base = alignBase; ++ } ++ break; ++ } ++ else if ( (holdBase > base) && (holdEnd <= end) ) ++ { ++ if ( (holdBase-base) >= alignment ) ++ { ++ if ( (alignBase < end) && ((end-alignBase) >= alignment) ) ++ { ++ if ((p_NewB = CreateFreeBlock(alignBase, end-alignBase)) == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ p_NewB->p_Next = p_CurrB->p_Next; ++ p_CurrB->p_Next = p_NewB; ++ } ++ p_CurrB->end = holdBase; ++ } ++ else if ( (alignBase < end) && ((end-alignBase) >= alignment) ) ++ { ++ p_CurrB->base = alignBase; ++ } ++ else ++ { ++ if (p_PrevB) ++ p_PrevB->p_Next = p_CurrB->p_Next; ++ else ++ p_MM->freeBlocks[i] = p_CurrB->p_Next; ++ XX_Free(p_CurrB); ++ } ++ break; ++ } ++ else ++ { ++ p_PrevB = p_CurrB; ++ p_CurrB = p_CurrB->p_Next; ++ } ++ } ++ } ++ ++ return (E_OK); ++} ++ ++/**************************************************************** ++ * Routine: AddBusy ++ * ++ * Description: ++ * Adds a new busy block to the list of busy blocks. Note, ++ * that all busy blocks are ordered by their base address in ++ * the busy list. ++ * ++ * Arguments: ++ * MM - handler to the MM object ++ * p_NewBusyB - pointer to the a busy block ++ * ++ * Return value: ++ * None. ++ * ++ ****************************************************************/ ++static void AddBusy(t_MM *p_MM, t_BusyBlock *p_NewBusyB) ++{ ++ t_BusyBlock *p_CurrBusyB, *p_PrevBusyB; ++ ++ /* finds a place of a new busy block in the list of busy blocks */ ++ p_PrevBusyB = 0; ++ p_CurrBusyB = p_MM->busyBlocks; ++ ++ while ( p_CurrBusyB && p_NewBusyB->base > p_CurrBusyB->base ) ++ { ++ p_PrevBusyB = p_CurrBusyB; ++ p_CurrBusyB = p_CurrBusyB->p_Next; ++ } ++ ++ /* insert the new busy block into the list of busy blocks */ ++ if ( p_CurrBusyB ) ++ p_NewBusyB->p_Next = p_CurrBusyB; ++ if ( p_PrevBusyB ) ++ p_PrevBusyB->p_Next = p_NewBusyB; ++ else ++ p_MM->busyBlocks = p_NewBusyB; ++} ++ ++/**************************************************************** ++ * Routine: CutBusy ++ * ++ * Description: ++ * Cuts a block from base to end from the list of busy blocks. ++ * This is done by updating the list of busy blocks do not ++ * include a given block, that block is going to be free. If a ++ * given block is a part of some other busy block, so that ++ * busy block is updated. If there are number of busy blocks ++ * included in the given block, so all that blocks are removed ++ * from the busy list and the end blocks are updated. ++ * If the given block devides some block into two parts, a new ++ * busy block is added to the busy list. ++ * ++ * Arguments: ++ * p_MM - pointer to the MM object ++ * base - base address of a given busy block ++ * end - end address of a given busy block ++ * ++ * Return value: ++ * E_OK on success, E_NOMEMORY otherwise. ++ * ++ ****************************************************************/ ++static t_Error CutBusy(t_MM *p_MM, uint64_t base, uint64_t end) ++{ ++ t_BusyBlock *p_CurrB, *p_PrevB, *p_NewB; ++ ++ p_CurrB = p_MM->busyBlocks; ++ p_PrevB = p_NewB = 0; ++ ++ while ( p_CurrB ) ++ { ++ if ( base < p_CurrB->end ) ++ { ++ if ( end > p_CurrB->end ) ++ { ++ t_BusyBlock *p_NextB; ++ while ( p_CurrB->p_Next && end >= p_CurrB->p_Next->end ) ++ { ++ p_NextB = p_CurrB->p_Next; ++ p_CurrB->p_Next = p_CurrB->p_Next->p_Next; ++ XX_Free(p_NextB); ++ } ++ ++ p_NextB = p_CurrB->p_Next; ++ if ( p_NextB && end > p_NextB->base ) ++ { ++ p_NextB->base = end; ++ } ++ } ++ ++ if ( base <= p_CurrB->base ) ++ { ++ if ( end < p_CurrB->end && end > p_CurrB->base ) ++ { ++ p_CurrB->base = end; ++ } ++ else if ( end >= p_CurrB->end ) ++ { ++ if ( p_PrevB ) ++ p_PrevB->p_Next = p_CurrB->p_Next; ++ else ++ p_MM->busyBlocks = p_CurrB->p_Next; ++ XX_Free(p_CurrB); ++ } ++ } ++ else ++ { ++ if ( end < p_CurrB->end && end > p_CurrB->base ) ++ { ++ if ((p_NewB = CreateBusyBlock(end, ++ p_CurrB->end-end, ++ p_CurrB->name)) == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ p_NewB->p_Next = p_CurrB->p_Next; ++ p_CurrB->p_Next = p_NewB; ++ } ++ p_CurrB->end = base; ++ } ++ break; ++ } ++ else ++ { ++ p_PrevB = p_CurrB; ++ p_CurrB = p_CurrB->p_Next; ++ } ++ } ++ ++ return (E_OK); ++} ++ ++/**************************************************************** ++ * Routine: MmGetGreaterAlignment ++ * ++ * Description: ++ * Allocates a block of memory according to the given size ++ * and the alignment. That routine is called from the MM_Get ++ * routine if the required alignment is greater then MM_MAX_ALIGNMENT. ++ * In that case, it goes over free blocks of 64 byte align list ++ * and checks if it has the required size of bytes of the required ++ * alignment. If no blocks found returns ILLEGAL_BASE. ++ * After the block is found and data is allocated, it calls ++ * the internal CutFree routine to update all free lists ++ * do not include a just allocated block. Of course, each ++ * free list contains a free blocks with the same alignment. ++ * It is also creates a busy block that holds ++ * information about an allocated block. ++ * ++ * Arguments: ++ * MM - handle to the MM object ++ * size - size of the MM ++ * alignment - index as a power of two defines ++ * a required alignment that is greater then 64. ++ * name - the name that specifies an allocated block. ++ * ++ * Return value: ++ * base address of an allocated block. ++ * ILLEGAL_BASE if can't allocate a block ++ * ++ ****************************************************************/ ++static uint64_t MmGetGreaterAlignment(t_MM *p_MM, uint64_t size, uint64_t alignment, char* name) ++{ ++ t_FreeBlock *p_FreeB; ++ t_BusyBlock *p_NewBusyB; ++ uint64_t holdBase, holdEnd, alignBase = 0; ++ ++ /* goes over free blocks of the 64 byte alignment list ++ and look for a block of the suitable size and ++ base address according to the alignment. */ ++ p_FreeB = p_MM->freeBlocks[MM_MAX_ALIGNMENT]; ++ ++ while ( p_FreeB ) ++ { ++ alignBase = MAKE_ALIGNED(p_FreeB->base, alignment); ++ ++ /* the block is found if the aligned base inside the block ++ * and has the anough size. */ ++ if ( alignBase >= p_FreeB->base && ++ alignBase < p_FreeB->end && ++ size <= (p_FreeB->end - alignBase) ) ++ break; ++ else ++ p_FreeB = p_FreeB->p_Next; ++ } ++ ++ /* If such block isn't found */ ++ if ( !p_FreeB ) ++ return (uint64_t)(ILLEGAL_BASE); ++ ++ holdBase = alignBase; ++ holdEnd = alignBase + size; ++ ++ /* init a new busy block */ ++ if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL) ++ return (uint64_t)(ILLEGAL_BASE); ++ ++ /* calls Update routine to update a lists of free blocks */ ++ if ( CutFree ( p_MM, holdBase, holdEnd ) != E_OK ) ++ return (uint64_t)(ILLEGAL_BASE); ++ ++ /* insert the new busy block into the list of busy blocks */ ++ AddBusy ( p_MM, p_NewBusyB ); ++ ++ return (holdBase); ++} ++ ++ ++/********************************************************************** ++ * MM API routines set * ++ **********************************************************************/ ++ ++/*****************************************************************************/ ++t_Error MM_Init(t_Handle *h_MM, uint64_t base, uint64_t size) ++{ ++ t_MM *p_MM; ++ uint64_t newBase, newSize; ++ int i; ++ ++ if (!size) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Size (should be positive)")); ++ } ++ ++ /* Initializes a new MM object */ ++ p_MM = (t_MM *)XX_Malloc(sizeof(t_MM)); ++ if (!p_MM) ++ { ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ } ++ ++ p_MM->h_Spinlock = XX_InitSpinlock(); ++ if (!p_MM->h_Spinlock) ++ { ++ XX_Free(p_MM); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MM spinlock!")); ++ } ++ ++ /* Initializes counter of free memory to total size */ ++ p_MM->freeMemSize = size; ++ ++ /* Initializes a new memory block */ ++ if ((p_MM->memBlocks = CreateNewBlock(base, size)) == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ ++ /* A busy list is empty */ ++ p_MM->busyBlocks = 0; ++ ++ /* Initializes a new free block for each free list*/ ++ for (i=0; i <= MM_MAX_ALIGNMENT; i++) ++ { ++ newBase = MAKE_ALIGNED( base, (0x1 << i) ); ++ newSize = size - (newBase - base); ++ ++ if ((p_MM->freeBlocks[i] = CreateFreeBlock(newBase, newSize)) == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ } ++ ++ *h_MM = p_MM; ++ ++ return (E_OK); ++} ++ ++/*****************************************************************************/ ++void MM_Free(t_Handle h_MM) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_MemBlock *p_MemBlock; ++ t_BusyBlock *p_BusyBlock; ++ t_FreeBlock *p_FreeBlock; ++ void *p_Block; ++ int i; ++ ++ ASSERT_COND(p_MM); ++ ++ /* release memory allocated for busy blocks */ ++ p_BusyBlock = p_MM->busyBlocks; ++ while ( p_BusyBlock ) ++ { ++ p_Block = p_BusyBlock; ++ p_BusyBlock = p_BusyBlock->p_Next; ++ XX_Free(p_Block); ++ } ++ ++ /* release memory allocated for free blocks */ ++ for (i=0; i <= MM_MAX_ALIGNMENT; i++) ++ { ++ p_FreeBlock = p_MM->freeBlocks[i]; ++ while ( p_FreeBlock ) ++ { ++ p_Block = p_FreeBlock; ++ p_FreeBlock = p_FreeBlock->p_Next; ++ XX_Free(p_Block); ++ } ++ } ++ ++ /* release memory allocated for memory blocks */ ++ p_MemBlock = p_MM->memBlocks; ++ while ( p_MemBlock ) ++ { ++ p_Block = p_MemBlock; ++ p_MemBlock = p_MemBlock->p_Next; ++ XX_Free(p_Block); ++ } ++ ++ if (p_MM->h_Spinlock) ++ XX_FreeSpinlock(p_MM->h_Spinlock); ++ ++ /* release memory allocated for MM object itself */ ++ XX_Free(p_MM); ++} ++ ++/*****************************************************************************/ ++uint64_t MM_Get(t_Handle h_MM, uint64_t size, uint64_t alignment, char* name) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_FreeBlock *p_FreeB; ++ t_BusyBlock *p_NewBusyB; ++ uint64_t holdBase, holdEnd, j, i = 0; ++ uint32_t intFlags; ++ ++ SANITY_CHECK_RETURN_VALUE(p_MM, E_INVALID_HANDLE, (uint64_t)ILLEGAL_BASE); ++ ++ /* checks that alignment value is greater then zero */ ++ if (alignment == 0) ++ { ++ alignment = 1; ++ } ++ ++ j = alignment; ++ ++ /* checks if alignment is a power of two, if it correct and if the ++ required size is multiple of the given alignment. */ ++ while ((j & 0x1) == 0) ++ { ++ i++; ++ j = j >> 1; ++ } ++ ++ /* if the given alignment isn't power of two, returns an error */ ++ if (j != 1) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("alignment (should be power of 2)")); ++ return (uint64_t)ILLEGAL_BASE; ++ } ++ ++ if (i > MM_MAX_ALIGNMENT) ++ { ++ return (MmGetGreaterAlignment(p_MM, size, alignment, name)); ++ } ++ ++ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); ++ /* look for a block of the size greater or equal to the required size. */ ++ p_FreeB = p_MM->freeBlocks[i]; ++ while ( p_FreeB && (p_FreeB->end - p_FreeB->base) < size ) ++ p_FreeB = p_FreeB->p_Next; ++ ++ /* If such block is found */ ++ if ( !p_FreeB ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ holdBase = p_FreeB->base; ++ holdEnd = holdBase + size; ++ ++ /* init a new busy block */ ++ if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* calls Update routine to update a lists of free blocks */ ++ if ( CutFree ( p_MM, holdBase, holdEnd ) != E_OK ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* Decreasing the allocated memory size from free memory size */ ++ p_MM->freeMemSize -= size; ++ ++ /* insert the new busy block into the list of busy blocks */ ++ AddBusy ( p_MM, p_NewBusyB ); ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ ++ return (holdBase); ++} ++ ++/*****************************************************************************/ ++uint64_t MM_GetForce(t_Handle h_MM, uint64_t base, uint64_t size, char* name) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_FreeBlock *p_FreeB; ++ t_BusyBlock *p_NewBusyB; ++ uint32_t intFlags; ++ bool blockIsFree = FALSE; ++ ++ ASSERT_COND(p_MM); ++ ++ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); ++ p_FreeB = p_MM->freeBlocks[0]; /* The biggest free blocks are in the ++ free list with alignment 1 */ ++ ++ while ( p_FreeB ) ++ { ++ if ( base >= p_FreeB->base && (base+size) <= p_FreeB->end ) ++ { ++ blockIsFree = TRUE; ++ break; ++ } ++ else ++ p_FreeB = p_FreeB->p_Next; ++ } ++ ++ if ( !blockIsFree ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* init a new busy block */ ++ if ((p_NewBusyB = CreateBusyBlock(base, size, name)) == NULL) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* calls Update routine to update a lists of free blocks */ ++ if ( CutFree ( p_MM, base, base+size ) != E_OK ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* Decreasing the allocated memory size from free memory size */ ++ p_MM->freeMemSize -= size; ++ ++ /* insert the new busy block into the list of busy blocks */ ++ AddBusy ( p_MM, p_NewBusyB ); ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ ++ return (base); ++} ++ ++/*****************************************************************************/ ++uint64_t MM_GetForceMin(t_Handle h_MM, uint64_t size, uint64_t alignment, uint64_t min, char* name) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_FreeBlock *p_FreeB; ++ t_BusyBlock *p_NewBusyB; ++ uint64_t holdBase, holdEnd, j = alignment, i=0; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_MM); ++ ++ /* checks if alignment is a power of two, if it correct and if the ++ required size is multiple of the given alignment. */ ++ while ((j & 0x1) == 0) ++ { ++ i++; ++ j = j >> 1; ++ } ++ ++ if ( (j != 1) || (i > MM_MAX_ALIGNMENT) ) ++ { ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); ++ p_FreeB = p_MM->freeBlocks[i]; ++ ++ /* look for the first block that contains the minimum ++ base address. If the whole required size may be fit ++ into it, use that block, otherwise look for the next ++ block of size greater or equal to the required size. */ ++ while ( p_FreeB && (min >= p_FreeB->end)) ++ p_FreeB = p_FreeB->p_Next; ++ ++ /* If such block is found */ ++ if ( !p_FreeB ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* if this block is large enough, use this block */ ++ holdBase = ( min <= p_FreeB->base ) ? p_FreeB->base : min; ++ if ((holdBase + size) <= p_FreeB->end ) ++ { ++ holdEnd = holdBase + size; ++ } ++ else ++ { ++ p_FreeB = p_FreeB->p_Next; ++ while ( p_FreeB && ((p_FreeB->end - p_FreeB->base) < size) ) ++ p_FreeB = p_FreeB->p_Next; ++ ++ /* If such block is found */ ++ if ( !p_FreeB ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ holdBase = p_FreeB->base; ++ holdEnd = holdBase + size; ++ } ++ ++ /* init a new busy block */ ++ if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* calls Update routine to update a lists of free blocks */ ++ if ( CutFree( p_MM, holdBase, holdEnd ) != E_OK ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* Decreasing the allocated memory size from free memory size */ ++ p_MM->freeMemSize -= size; ++ ++ /* insert the new busy block into the list of busy blocks */ ++ AddBusy( p_MM, p_NewBusyB ); ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ ++ return (holdBase); ++} ++ ++/*****************************************************************************/ ++uint64_t MM_Put(t_Handle h_MM, uint64_t base) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_BusyBlock *p_BusyB, *p_PrevBusyB; ++ uint64_t size; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_MM); ++ ++ /* Look for a busy block that have the given base value. ++ * That block will be returned back to the memory. ++ */ ++ p_PrevBusyB = 0; ++ ++ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); ++ p_BusyB = p_MM->busyBlocks; ++ while ( p_BusyB && base != p_BusyB->base ) ++ { ++ p_PrevBusyB = p_BusyB; ++ p_BusyB = p_BusyB->p_Next; ++ } ++ ++ if ( !p_BusyB ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(0); ++ } ++ ++ if ( AddFree( p_MM, p_BusyB->base, p_BusyB->end ) != E_OK ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(0); ++ } ++ ++ /* removes a busy block form the list of busy blocks */ ++ if ( p_PrevBusyB ) ++ p_PrevBusyB->p_Next = p_BusyB->p_Next; ++ else ++ p_MM->busyBlocks = p_BusyB->p_Next; ++ ++ size = p_BusyB->end - p_BusyB->base; ++ ++ /* Adding the deallocated memory size to free memory size */ ++ p_MM->freeMemSize += size; ++ ++ XX_Free(p_BusyB); ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ ++ return (size); ++} ++ ++/*****************************************************************************/ ++uint64_t MM_PutForce(t_Handle h_MM, uint64_t base, uint64_t size) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ uint64_t end = base + size; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_MM); ++ ++ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); ++ ++ if ( CutBusy( p_MM, base, end ) != E_OK ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(0); ++ } ++ ++ if ( AddFree ( p_MM, base, end ) != E_OK ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(0); ++ } ++ ++ /* Adding the deallocated memory size to free memory size */ ++ p_MM->freeMemSize += size; ++ ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ ++ return (size); ++} ++ ++/*****************************************************************************/ ++t_Error MM_Add(t_Handle h_MM, uint64_t base, uint64_t size) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_MemBlock *p_MemB, *p_NewMemB; ++ t_Error errCode; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_MM); ++ ++ /* find a last block in the list of memory blocks to insert a new ++ * memory block ++ */ ++ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); ++ ++ p_MemB = p_MM->memBlocks; ++ while ( p_MemB->p_Next ) ++ { ++ if ( base >= p_MemB->base && base < p_MemB->end ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG); ++ } ++ p_MemB = p_MemB->p_Next; ++ } ++ /* check for a last memory block */ ++ if ( base >= p_MemB->base && base < p_MemB->end ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG); ++ } ++ ++ /* create a new memory block */ ++ if ((p_NewMemB = CreateNewBlock(base, size)) == NULL) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ } ++ ++ /* append a new memory block to the end of the list of memory blocks */ ++ p_MemB->p_Next = p_NewMemB; ++ ++ /* add a new free block to the free lists */ ++ errCode = AddFree(p_MM, base, base+size); ++ if (errCode) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ p_MemB->p_Next = 0; ++ XX_Free(p_NewMemB); ++ return ((t_Error)errCode); ++ } ++ ++ /* Adding the new block size to free memory size */ ++ p_MM->freeMemSize += size; ++ ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ ++ return (E_OK); ++} ++ ++/*****************************************************************************/ ++uint64_t MM_GetMemBlock(t_Handle h_MM, int index) ++{ ++ t_MM *p_MM = (t_MM*)h_MM; ++ t_MemBlock *p_MemBlock; ++ int i; ++ ++ ASSERT_COND(p_MM); ++ ++ p_MemBlock = p_MM->memBlocks; ++ for (i=0; i < index; i++) ++ p_MemBlock = p_MemBlock->p_Next; ++ ++ if ( p_MemBlock ) ++ return (p_MemBlock->base); ++ else ++ return (uint64_t)ILLEGAL_BASE; ++} ++ ++/*****************************************************************************/ ++uint64_t MM_GetBase(t_Handle h_MM) ++{ ++ t_MM *p_MM = (t_MM*)h_MM; ++ t_MemBlock *p_MemBlock; ++ ++ ASSERT_COND(p_MM); ++ ++ p_MemBlock = p_MM->memBlocks; ++ return p_MemBlock->base; ++} ++ ++/*****************************************************************************/ ++bool MM_InRange(t_Handle h_MM, uint64_t addr) ++{ ++ t_MM *p_MM = (t_MM*)h_MM; ++ t_MemBlock *p_MemBlock; ++ ++ ASSERT_COND(p_MM); ++ ++ p_MemBlock = p_MM->memBlocks; ++ ++ if ((addr >= p_MemBlock->base) && (addr < p_MemBlock->end)) ++ return TRUE; ++ else ++ return FALSE; ++} ++ ++/*****************************************************************************/ ++uint64_t MM_GetFreeMemSize(t_Handle h_MM) ++{ ++ t_MM *p_MM = (t_MM*)h_MM; ++ ++ ASSERT_COND(p_MM); ++ ++ return p_MM->freeMemSize; ++} ++ ++/*****************************************************************************/ ++void MM_Dump(t_Handle h_MM) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_FreeBlock *p_FreeB; ++ t_BusyBlock *p_BusyB; ++ int i; ++ ++ p_BusyB = p_MM->busyBlocks; ++ XX_Print("List of busy blocks:\n"); ++ while (p_BusyB) ++ { ++ XX_Print("\t0x%p: (%s: b=0x%llx, e=0x%llx)\n", p_BusyB, p_BusyB->name, p_BusyB->base, p_BusyB->end ); ++ p_BusyB = p_BusyB->p_Next; ++ } ++ ++ XX_Print("\nLists of free blocks according to alignment:\n"); ++ for (i=0; i <= MM_MAX_ALIGNMENT; i++) ++ { ++ XX_Print("%d alignment:\n", (0x1 << i)); ++ p_FreeB = p_MM->freeBlocks[i]; ++ while (p_FreeB) ++ { ++ XX_Print("\t0x%p: (b=0x%llx, e=0x%llx)\n", p_FreeB, p_FreeB->base, p_FreeB->end); ++ p_FreeB = p_FreeB->p_Next; ++ } ++ XX_Print("\n"); ++ } ++} +diff --git a/drivers/net/dpa/NetCommSw/etc/mm.h b/drivers/net/dpa/NetCommSw/etc/mm.h +new file mode 100644 +index 0000000..43b2298 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/etc/mm.h +@@ -0,0 +1,105 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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: mm.h ++ * ++ * ++ * Description: ++ * MM (Memory Management) object definitions. ++ * It also includes definitions of the Free Block, Busy Block ++ * and Memory Block structures used by the MM object. ++ * ++ ****************************************************************/ ++ ++#ifndef __MM_H ++#define __MM_H ++ ++ ++#include "mm_ext.h" ++ ++#define __ERR_MODULE__ MODULE_MM ++ ++ ++#define MAKE_ALIGNED(addr, align) \ ++ (((uint64_t)(addr) + ((align) - 1)) & (~(((uint64_t)align) - 1))) ++ ++ ++/* t_MemBlock data structure defines parameters of the Memory Block */ ++typedef struct t_MemBlock ++{ ++ struct t_MemBlock *p_Next; /* Pointer to the next memory block */ ++ ++ uint64_t base; /* Base address of the memory block */ ++ uint64_t end; /* End address of the memory block */ ++} t_MemBlock; ++ ++ ++/* t_FreeBlock data structure defines parameters of the Free Block */ ++typedef struct t_FreeBlock ++{ ++ struct t_FreeBlock *p_Next; /* Pointer to the next free block */ ++ ++ uint64_t base; /* Base address of the block */ ++ uint64_t end; /* End address of the block */ ++} t_FreeBlock; ++ ++ ++/* t_BusyBlock data structure defines parameters of the Busy Block */ ++typedef struct t_BusyBlock ++{ ++ struct t_BusyBlock *p_Next; /* Pointer to the next free block */ ++ ++ uint64_t base; /* Base address of the block */ ++ uint64_t end; /* End address of the block */ ++ char name[MM_MAX_NAME_LEN]; /* That block of memory was allocated for ++ something specified by the Name */ ++} t_BusyBlock; ++ ++ ++/* t_MM data structure defines parameters of the MM object */ ++typedef struct t_MM ++{ ++ t_Handle h_Spinlock; ++ ++ t_MemBlock *memBlocks; /* List of memory blocks (Memory list) */ ++ t_BusyBlock *busyBlocks; /* List of busy blocks (Busy list) */ ++ t_FreeBlock *freeBlocks[MM_MAX_ALIGNMENT + 1]; ++ /* Alignment lists of free blocks (Free lists) */ ++ ++ uint64_t freeMemSize; /* Total size of free memory (in bytes) */ ++} t_MM; ++ ++ ++#endif /* __MM_H */ +diff --git a/drivers/net/dpa/NetCommSw/etc/sprint.c b/drivers/net/dpa/NetCommSw/etc/sprint.c +new file mode 100644 +index 0000000..46d2956 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/etc/sprint.c +@@ -0,0 +1,81 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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: sprint.c */ ++/* */ ++/* Description: */ ++/* Debug routines (externals) */ ++/*------------------------------------------------------*/ ++#include "string_ext.h" ++#include "stdlib_ext.h" ++#include "stdarg_ext.h" ++#include "sprint_ext.h" ++#include "std_ext.h" ++#include "xx_ext.h" ++ ++ ++int Sprint(char * buf, const char *fmt, ...) ++{ ++ va_list args; ++ int i; ++ ++ va_start(args, fmt); ++ i=vsprintf(buf,fmt,args); ++ va_end(args); ++ return i; ++} ++ ++int Snprint(char * buf, uint32_t size, const char *fmt, ...) ++{ ++ va_list args; ++ int i; ++ ++ va_start(args, fmt); ++ i=vsnprintf(buf,size,fmt,args); ++ va_end(args); ++ return i; ++} ++ ++#ifndef NCSW_VXWORKS ++int Sscan(const char * buf, const char * fmt, ...) ++{ ++ va_list args; ++ int i; ++ ++ va_start(args,fmt); ++ i = vsscanf(buf,fmt,args); ++ va_end(args); ++ return i; ++} ++#endif /* NCSW_VXWORKS */ +diff --git a/drivers/net/dpa/NetCommSw/inc/Peripherals/crc_mac_addr_ext.h b/drivers/net/dpa/NetCommSw/inc/Peripherals/crc_mac_addr_ext.h +new file mode 100644 +index 0000000..a84d563 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/Peripherals/crc_mac_addr_ext.h +@@ -0,0 +1,364 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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: crc_mac_addr_ext.h */ ++/* */ ++/* Description: */ ++/* Define a macro that calculate the crc value of */ ++/* an Ethernet MAC address (48 bitd address */ ++/*------------------------------------------------------*/ ++ ++#ifndef __crc_mac_addr_ext_h ++#define __crc_mac_addr_ext_h ++ ++#include "std_ext.h" ++ ++ ++static uint32_t crc_table[256] = ++{ ++ 0x00000000, ++ 0x77073096, ++ 0xee0e612c, ++ 0x990951ba, ++ 0x076dc419, ++ 0x706af48f, ++ 0xe963a535, ++ 0x9e6495a3, ++ 0x0edb8832, ++ 0x79dcb8a4, ++ 0xe0d5e91e, ++ 0x97d2d988, ++ 0x09b64c2b, ++ 0x7eb17cbd, ++ 0xe7b82d07, ++ 0x90bf1d91, ++ 0x1db71064, ++ 0x6ab020f2, ++ 0xf3b97148, ++ 0x84be41de, ++ 0x1adad47d, ++ 0x6ddde4eb, ++ 0xf4d4b551, ++ 0x83d385c7, ++ 0x136c9856, ++ 0x646ba8c0, ++ 0xfd62f97a, ++ 0x8a65c9ec, ++ 0x14015c4f, ++ 0x63066cd9, ++ 0xfa0f3d63, ++ 0x8d080df5, ++ 0x3b6e20c8, ++ 0x4c69105e, ++ 0xd56041e4, ++ 0xa2677172, ++ 0x3c03e4d1, ++ 0x4b04d447, ++ 0xd20d85fd, ++ 0xa50ab56b, ++ 0x35b5a8fa, ++ 0x42b2986c, ++ 0xdbbbc9d6, ++ 0xacbcf940, ++ 0x32d86ce3, ++ 0x45df5c75, ++ 0xdcd60dcf, ++ 0xabd13d59, ++ 0x26d930ac, ++ 0x51de003a, ++ 0xc8d75180, ++ 0xbfd06116, ++ 0x21b4f4b5, ++ 0x56b3c423, ++ 0xcfba9599, ++ 0xb8bda50f, ++ 0x2802b89e, ++ 0x5f058808, ++ 0xc60cd9b2, ++ 0xb10be924, ++ 0x2f6f7c87, ++ 0x58684c11, ++ 0xc1611dab, ++ 0xb6662d3d, ++ 0x76dc4190, ++ 0x01db7106, ++ 0x98d220bc, ++ 0xefd5102a, ++ 0x71b18589, ++ 0x06b6b51f, ++ 0x9fbfe4a5, ++ 0xe8b8d433, ++ 0x7807c9a2, ++ 0x0f00f934, ++ 0x9609a88e, ++ 0xe10e9818, ++ 0x7f6a0dbb, ++ 0x086d3d2d, ++ 0x91646c97, ++ 0xe6635c01, ++ 0x6b6b51f4, ++ 0x1c6c6162, ++ 0x856530d8, ++ 0xf262004e, ++ 0x6c0695ed, ++ 0x1b01a57b, ++ 0x8208f4c1, ++ 0xf50fc457, ++ 0x65b0d9c6, ++ 0x12b7e950, ++ 0x8bbeb8ea, ++ 0xfcb9887c, ++ 0x62dd1ddf, ++ 0x15da2d49, ++ 0x8cd37cf3, ++ 0xfbd44c65, ++ 0x4db26158, ++ 0x3ab551ce, ++ 0xa3bc0074, ++ 0xd4bb30e2, ++ 0x4adfa541, ++ 0x3dd895d7, ++ 0xa4d1c46d, ++ 0xd3d6f4fb, ++ 0x4369e96a, ++ 0x346ed9fc, ++ 0xad678846, ++ 0xda60b8d0, ++ 0x44042d73, ++ 0x33031de5, ++ 0xaa0a4c5f, ++ 0xdd0d7cc9, ++ 0x5005713c, ++ 0x270241aa, ++ 0xbe0b1010, ++ 0xc90c2086, ++ 0x5768b525, ++ 0x206f85b3, ++ 0xb966d409, ++ 0xce61e49f, ++ 0x5edef90e, ++ 0x29d9c998, ++ 0xb0d09822, ++ 0xc7d7a8b4, ++ 0x59b33d17, ++ 0x2eb40d81, ++ 0xb7bd5c3b, ++ 0xc0ba6cad, ++ 0xedb88320, ++ 0x9abfb3b6, ++ 0x03b6e20c, ++ 0x74b1d29a, ++ 0xead54739, ++ 0x9dd277af, ++ 0x04db2615, ++ 0x73dc1683, ++ 0xe3630b12, ++ 0x94643b84, ++ 0x0d6d6a3e, ++ 0x7a6a5aa8, ++ 0xe40ecf0b, ++ 0x9309ff9d, ++ 0x0a00ae27, ++ 0x7d079eb1, ++ 0xf00f9344, ++ 0x8708a3d2, ++ 0x1e01f268, ++ 0x6906c2fe, ++ 0xf762575d, ++ 0x806567cb, ++ 0x196c3671, ++ 0x6e6b06e7, ++ 0xfed41b76, ++ 0x89d32be0, ++ 0x10da7a5a, ++ 0x67dd4acc, ++ 0xf9b9df6f, ++ 0x8ebeeff9, ++ 0x17b7be43, ++ 0x60b08ed5, ++ 0xd6d6a3e8, ++ 0xa1d1937e, ++ 0x38d8c2c4, ++ 0x4fdff252, ++ 0xd1bb67f1, ++ 0xa6bc5767, ++ 0x3fb506dd, ++ 0x48b2364b, ++ 0xd80d2bda, ++ 0xaf0a1b4c, ++ 0x36034af6, ++ 0x41047a60, ++ 0xdf60efc3, ++ 0xa867df55, ++ 0x316e8eef, ++ 0x4669be79, ++ 0xcb61b38c, ++ 0xbc66831a, ++ 0x256fd2a0, ++ 0x5268e236, ++ 0xcc0c7795, ++ 0xbb0b4703, ++ 0x220216b9, ++ 0x5505262f, ++ 0xc5ba3bbe, ++ 0xb2bd0b28, ++ 0x2bb45a92, ++ 0x5cb36a04, ++ 0xc2d7ffa7, ++ 0xb5d0cf31, ++ 0x2cd99e8b, ++ 0x5bdeae1d, ++ 0x9b64c2b0, ++ 0xec63f226, ++ 0x756aa39c, ++ 0x026d930a, ++ 0x9c0906a9, ++ 0xeb0e363f, ++ 0x72076785, ++ 0x05005713, ++ 0x95bf4a82, ++ 0xe2b87a14, ++ 0x7bb12bae, ++ 0x0cb61b38, ++ 0x92d28e9b, ++ 0xe5d5be0d, ++ 0x7cdcefb7, ++ 0x0bdbdf21, ++ 0x86d3d2d4, ++ 0xf1d4e242, ++ 0x68ddb3f8, ++ 0x1fda836e, ++ 0x81be16cd, ++ 0xf6b9265b, ++ 0x6fb077e1, ++ 0x18b74777, ++ 0x88085ae6, ++ 0xff0f6a70, ++ 0x66063bca, ++ 0x11010b5c, ++ 0x8f659eff, ++ 0xf862ae69, ++ 0x616bffd3, ++ 0x166ccf45, ++ 0xa00ae278, ++ 0xd70dd2ee, ++ 0x4e048354, ++ 0x3903b3c2, ++ 0xa7672661, ++ 0xd06016f7, ++ 0x4969474d, ++ 0x3e6e77db, ++ 0xaed16a4a, ++ 0xd9d65adc, ++ 0x40df0b66, ++ 0x37d83bf0, ++ 0xa9bcae53, ++ 0xdebb9ec5, ++ 0x47b2cf7f, ++ 0x30b5ffe9, ++ 0xbdbdf21c, ++ 0xcabac28a, ++ 0x53b39330, ++ 0x24b4a3a6, ++ 0xbad03605, ++ 0xcdd70693, ++ 0x54de5729, ++ 0x23d967bf, ++ 0xb3667a2e, ++ 0xc4614ab8, ++ 0x5d681b02, ++ 0x2a6f2b94, ++ 0xb40bbe37, ++ 0xc30c8ea1, ++ 0x5a05df1b, ++ 0x2d02ef8d ++}; ++ ++ ++#define GET_MAC_ADDR_CRC(addr, crc) \ ++{ \ ++ uint32_t i; \ ++ uint8_t data; \ ++ \ ++ /* CRC calculation */ \ ++ crc = 0xffffffff; \ ++ for (i=0; i < 6; i++) \ ++ { \ ++ data = (uint8_t)(addr >> ((5-i)*8)); \ ++ crc = crc^data; \ ++ crc = crc_table[crc&0xff] ^ (crc>>8); \ ++ } \ ++} \ ++ ++/* Define a macro for getting the mirrored value of */ ++/* a byte size number. (0x11010011 --> 0x11001011) */ ++/* Sometimes the mirrored value of the CRC is required */ ++static __inline__ uint8_t GetMirror(uint8_t n) ++{ ++ uint8_t mirror[16] = ++ { ++ 0x00, ++ 0x08, ++ 0x04, ++ 0x0c, ++ 0x02, ++ 0x0a, ++ 0x06, ++ 0x0e, ++ 0x01, ++ 0x09, ++ 0x05, ++ 0x0d, ++ 0x03, ++ 0x0b, ++ 0x07, ++ 0x0f ++ }; ++ return ((uint8_t)(((mirror[n & 0x0f] << 4) | (mirror[n >> 4])))); ++} ++ ++static __inline__ uint32_t GetMirror32(uint32_t n) ++{ ++ return (((uint32_t)GetMirror((uint8_t)(n))<<24) | ++ ((uint32_t)GetMirror((uint8_t)(n>>8))<<16) | ++ ((uint32_t)GetMirror((uint8_t)(n>>16))<<8) | ++ ((uint32_t)GetMirror((uint8_t)(n>>24)))); ++} ++ ++#define MIRROR GetMirror ++#define MIRROR_32 GetMirror32 ++ ++ ++#endif /* __crc_mac_addr_ext_h */ +diff --git a/drivers/net/dpa/NetCommSw/inc/Peripherals/dpaa_ext.h b/drivers/net/dpa/NetCommSw/inc/Peripherals/dpaa_ext.h +new file mode 100644 +index 0000000..c20a6eb +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/Peripherals/dpaa_ext.h +@@ -0,0 +1,205 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 dpaa_ext.h ++ ++ @Description DPAA Application Programming Interface. ++*//***************************************************************************/ ++#ifndef __DPAA_EXT_H ++#define __DPAA_EXT_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group DPAA_grp Data Path Acceleration Architecture API ++ ++ @Description DPAA API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description Frame descriptor ++*//***************************************************************************/ ++typedef _Packed struct t_DpaaFD { ++ volatile uint32_t id; /**< FD id */ ++ volatile uint32_t addrl; /**< Data Address */ ++ volatile uint32_t length; /**< Frame length */ ++ volatile uint32_t status; /**< FD status */ ++} _PackedType t_DpaaFD; ++ ++/**************************************************************************//** ++ @Description enum for defining frame format ++*//***************************************************************************/ ++typedef enum e_DpaaFDFormatType { ++ e_DPAA_FD_FORMAT_TYPE_SHORT_SBSF = 0x0, /**< Simple frame Single buffer; Offset and ++ small length (9b OFFSET, 20b LENGTH) */ ++ e_DPAA_FD_FORMAT_TYPE_LONG_SBSF = 0x2, /**< Simple frame, single buffer; big length ++ (29b LENGTH ,No OFFSET) */ ++ e_DPAA_FD_FORMAT_TYPE_SHORT_MBSF = 0x4, /**< Simple frame, Scatter Gather table; Offset ++ and small length (9b OFFSET, 20b LENGTH) */ ++ e_DPAA_FD_FORMAT_TYPE_LONG_MBSF = 0x6, /**< Simple frame, Scatter Gather table; ++ big length (29b LENGTH ,No OFFSET) */ ++ e_DPAA_FD_FORMAT_TYPE_COMPOUND = 0x1, /**< Compound Frame (29b CONGESTION-WEIGHT ++ No LENGTH or OFFSET) */ ++ e_DPAA_FD_FORMAT_TYPE_DUMMY ++} e_DpaaFDFormatType; ++ ++/**************************************************************************//** ++ @Collection Frame descriptor macros ++*//***************************************************************************/ ++#define DPAA_FD_DD_MASK 0xc0000000 /**< FD DD field mask */ ++#define DPAA_FD_PID_MASK 0x3f000000 /**< FD PID field mask */ ++#define DPAA_FD_ELIODN_MASK 0x0000f000 /**< FD ELIODN field mask */ ++#define DPAA_FD_BPID_MASK 0x00ff0000 /**< FD BPID field mask */ ++#define DPAA_FD_ADDRH_MASK 0x000000ff /**< FD ADDRH field mask */ ++#define DPAA_FD_ADDRL_MASK 0xffffffff /**< FD ADDRL field mask */ ++#define DPAA_FD_FORMAT_MASK 0xe0000000 /**< FD FORMAT field mask */ ++#define DPAA_FD_OFFSET_MASK 0x1ff00000 /**< FD OFFSET field mask */ ++#define DPAA_FD_LENGTH_MASK 0x000fffff /**< FD LENGTH field mask */ ++ ++#define DPAA_FD_GET_DD(fd) ((((t_DpaaFD *)fd)->id & DPAA_FD_DD_MASK) >> (31-1)) /**< Macro to get FD DD field */ ++#define DPAA_FD_GET_PID(fd) (((((t_DpaaFD *)fd)->id & DPAA_FD_PID_MASK) >> (31-7)) | \ ++ ((((t_DpaaFD *)fd)->id & DPAA_FD_ELIODN_MASK) >> (31-19-6))) /**< Macro to get FD PID field */ ++#define DPAA_FD_GET_BPID(fd) ((((t_DpaaFD *)fd)->id & DPAA_FD_BPID_MASK) >> (31-15)) /**< Macro to get FD BPID field */ ++#define DPAA_FD_GET_ADDRH(fd) (((t_DpaaFD *)fd)->id & DPAA_FD_ADDRH_MASK) /**< Macro to get FD ADDRH field */ ++#define DPAA_FD_GET_ADDRL(fd) ((t_DpaaFD *)fd)->addrl /**< Macro to get FD ADDRL field */ ++#define DPAA_FD_GET_PHYS_ADDR(fd) ((physAddress_t)(((uint64_t)DPAA_FD_GET_ADDRH(fd) << 32) | (uint64_t)DPAA_FD_GET_ADDRL(fd))) /**< Macro to get FD ADDR field */ ++#define DPAA_FD_GET_FORMAT(fd) ((((t_DpaaFD *)fd)->length & DPAA_FD_FORMAT_MASK) >> (31-2)) /**< Macro to get FD FORMAT field */ ++#define DPAA_FD_GET_OFFSET(fd) ((((t_DpaaFD *)fd)->length & DPAA_FD_OFFSET_MASK) >> (31-11)) /**< Macro to get FD OFFSET field */ ++#define DPAA_FD_GET_LENGTH(fd) (((t_DpaaFD *)fd)->length & DPAA_FD_LENGTH_MASK) /**< Macro to get FD LENGTH field */ ++#define DPAA_FD_GET_STATUS(fd) ((t_DpaaFD *)fd)->status /**< Macro to get FD STATUS field */ ++#define DPAA_FD_GET_ADDR(fd) XX_PhysToVirt(DPAA_FD_GET_PHYS_ADDR(fd)) /**< Macro to get FD ADDR (virtual) */ ++ ++#define DPAA_FD_SET_DD(fd,val) (((t_DpaaFD *)fd)->id = ((((t_DpaaFD *)fd)->id & ~DPAA_FD_DD_MASK) | (((val) << (31-1)) & DPAA_FD_DD_MASK ))) /**< Macro to set FD DD field */ ++ /**< Macro to set FD PID field or LIODN offset*/ ++#define DPAA_FD_SET_PID(fd,val) (((t_DpaaFD *)fd)->id = ((((t_DpaaFD *)fd)->id & ~(DPAA_FD_PID_MASK|DPAA_FD_ELIODN_MASK)) | ((((val) << (31-7)) & DPAA_FD_PID_MASK) | ((((val)>>6) << (31-19)) & DPAA_FD_ELIODN_MASK)))) ++#define DPAA_FD_SET_BPID(fd,val) (((t_DpaaFD *)fd)->id = ((((t_DpaaFD *)fd)->id & ~DPAA_FD_BPID_MASK) | (((val) << (31-15)) & DPAA_FD_BPID_MASK))) /**< Macro to set FD BPID field */ ++#define DPAA_FD_SET_ADDRH(fd,val) (((t_DpaaFD *)fd)->id = ((((t_DpaaFD *)fd)->id & ~DPAA_FD_ADDRH_MASK) | ((val) & DPAA_FD_ADDRH_MASK))) /**< Macro to set FD ADDRH field */ ++#define DPAA_FD_SET_ADDRL(fd,val) ((t_DpaaFD *)fd)->addrl = (val) /**< Macro to set FD ADDRL field */ ++#define DPAA_FD_SET_ADDR(fd,val) \ ++do { \ ++ uint64_t physAddr = (uint64_t)(XX_VirtToPhys(val)); \ ++ DPAA_FD_SET_ADDRH(fd, ((uint32_t)(physAddr >> 32))); \ ++ DPAA_FD_SET_ADDRL(fd, (uint32_t)physAddr); \ ++} while (0) /**< Macro to set FD ADDR field */ ++#define DPAA_FD_SET_FORMAT(fd,val) (((t_DpaaFD *)fd)->length = ((((t_DpaaFD *)fd)->length & ~DPAA_FD_FORMAT_MASK) | (((val) << (31-2))& DPAA_FD_FORMAT_MASK))) /**< Macro to set FD FORMAT field */ ++#define DPAA_FD_SET_OFFSET(fd,val) (((t_DpaaFD *)fd)->length = ((((t_DpaaFD *)fd)->length & ~DPAA_FD_OFFSET_MASK) | (((val) << (31-11))& DPAA_FD_OFFSET_MASK) )) /**< Macro to set FD OFFSET field */ ++#define DPAA_FD_SET_LENGTH(fd,val) (((t_DpaaFD *)fd)->length = (((t_DpaaFD *)fd)->length & ~DPAA_FD_LENGTH_MASK) | ((val) & DPAA_FD_LENGTH_MASK)) /**< Macro to set FD LENGTH field */ ++#define DPAA_FD_SET_STATUS(fd,val) ((t_DpaaFD *)fd)->status = (val) /**< Macro to set FD STATUS field */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description Frame Scatter/Gather Table Entry ++*//***************************************************************************/ ++typedef _Packed struct t_DpaaSGTE { ++ volatile uint32_t addrh; /**< Buffer Address high */ ++ volatile uint32_t addrl; /**< Buffer Address low */ ++ volatile uint32_t length; /**< Buffer length */ ++ volatile uint32_t offset; /**< SGTE offset */ ++} _PackedType t_DpaaSGTE; ++ ++#define DPAA_NUM_OF_SG_TABLE_ENTRY 16 ++ ++/**************************************************************************//** ++ @Description Frame Scatter/Gather Table ++*//***************************************************************************/ ++typedef _Packed struct t_DpaaSGT { ++ t_DpaaSGTE tableEntry[DPAA_NUM_OF_SG_TABLE_ENTRY]; ++ /**< Structure that holds information about ++ a single S/G entry. */ ++} _PackedType t_DpaaSGT; ++ ++/**************************************************************************//** ++ @Description Compound Frame Table ++*//***************************************************************************/ ++typedef _Packed struct t_DpaaCompTbl { ++ t_DpaaSGTE outputBuffInfo; /**< Structure that holds information about ++ the compound-frame output buffer; ++ NOTE: this may point to a S/G table */ ++ t_DpaaSGTE inputBuffInfo; /**< Structure that holds information about ++ the compound-frame input buffer; ++ NOTE: this may point to a S/G table */ ++} _PackedType t_DpaaCompTbl; ++ ++/**************************************************************************//** ++ @Collection Frame Scatter/Gather Table Entry macros ++*//***************************************************************************/ ++#define DPAA_SGTE_ADDRH_MASK 0x000000ff /**< SGTE ADDRH field mask */ ++#define DPAA_SGTE_ADDRL_MASK 0xffffffff /**< SGTE ADDRL field mask */ ++#define DPAA_SGTE_E_MASK 0x80000000 /**< SGTE Extension field mask */ ++#define DPAA_SGTE_F_MASK 0x40000000 /**< SGTE Final field mask */ ++#define DPAA_SGTE_LENGTH_MASK 0x3fffffff /**< SGTE LENGTH field mask */ ++#define DPAA_SGTE_BPID_MASK 0x00ff0000 /**< SGTE BPID field mask */ ++#define DPAA_SGTE_OFFSET_MASK 0x00001fff /**< SGTE OFFSET field mask */ ++ ++#define DPAA_SGTE_GET_ADDRH(sgte) (((t_DpaaSGTE *)sgte)->addrh & DPAA_SGTE_ADDRH_MASK) /**< Macro to get SGTE ADDRH field */ ++#define DPAA_SGTE_GET_ADDRL(sgte) ((t_DpaaSGTE *)sgte)->addrl /**< Macro to get SGTE ADDRL field */ ++#define DPAA_SGTE_GET_PHYS_ADDR(sgte) ((physAddress_t)(((uint64_t)DPAA_SGTE_GET_ADDRH(sgte) << 32) | (uint64_t)DPAA_SGTE_GET_ADDRL(sgte))) /**< Macro to get FD ADDR field */ ++#define DPAA_SGTE_GET_EXTENSION(sgte) ((((t_DpaaSGTE *)sgte)->length & DPAA_SGTE_E_MASK) >> (31-0)) /**< Macro to get SGTE EXTENSION field */ ++#define DPAA_SGTE_GET_FINAL(sgte) ((((t_DpaaSGTE *)sgte)->length & DPAA_SGTE_F_MASK) >> (31-1)) /**< Macro to get SGTE FINAL field */ ++#define DPAA_SGTE_GET_LENGTH(sgte) (((t_DpaaSGTE *)sgte)->length & DPAA_SGTE_LENGTH_MASK) /**< Macro to get SGTE LENGTH field */ ++#define DPAA_SGTE_GET_BPID(sgte) ((((t_DpaaSGTE *)sgte)->offset & DPAA_SGTE_BPID_MASK) >> (31-15)) /**< Macro to get SGTE BPID field */ ++#define DPAA_SGTE_GET_OFFSET(sgte) (((t_DpaaSGTE *)sgte)->offset & DPAA_SGTE_OFFSET_MASK) /**< Macro to get SGTE OFFSET field */ ++#define DPAA_SGTE_GET_ADDR(sgte) XX_PhysToVirt(DPAA_SGTE_GET_PHYS_ADDR(sgte)) ++ ++#define DPAA_SGTE_SET_ADDRH(sgte,val) (((t_DpaaSGTE *)sgte)->addrh = ((((t_DpaaSGTE *)sgte)->addrh & ~DPAA_SGTE_ADDRH_MASK) | ((val) & DPAA_SGTE_ADDRH_MASK))) /**< Macro to set SGTE ADDRH field */ ++#define DPAA_SGTE_SET_ADDRL(sgte,val) ((t_DpaaSGTE *)sgte)->addrl = (val) /**< Macro to set SGTE ADDRL field */ ++#define DPAA_SGTE_SET_ADDR(sgte,val) \ ++do { \ ++ uint64_t physAddr = (uint64_t)(XX_VirtToPhys(val)); \ ++ DPAA_SGTE_SET_ADDRH(sgte, ((uint32_t)(physAddr >> 32))); \ ++ DPAA_SGTE_SET_ADDRL(sgte, (uint32_t)physAddr); \ ++} while (0) /**< Macro to set SGTE ADDR field */ ++#define DPAA_SGTE_SET_EXTENSION(sgte,val) (((t_DpaaSGTE *)sgte)->length = ((((t_DpaaSGTE *)sgte)->length & ~DPAA_SGTE_E_MASK) | (((val) << (31-0))& DPAA_SGTE_E_MASK))) /**< Macro to set SGTE EXTENSION field */ ++#define DPAA_SGTE_SET_FINAL(sgte,val) (((t_DpaaSGTE *)sgte)->length = ((((t_DpaaSGTE *)sgte)->length & ~DPAA_SGTE_F_MASK) | (((val) << (31-1))& DPAA_SGTE_F_MASK))) /**< Macro to set SGTE FINAL field */ ++#define DPAA_SGTE_SET_LENGTH(sgte,val) (((t_DpaaSGTE *)sgte)->length = (((t_DpaaSGTE *)sgte)->length & ~DPAA_SGTE_LENGTH_MASK) | ((val) & DPAA_SGTE_LENGTH_MASK)) /**< Macro to set SGTE LENGTH field */ ++#define DPAA_SGTE_SET_BPID(sgte,val) (((t_DpaaSGTE *)sgte)->offset = ((((t_DpaaSGTE *)sgte)->offset & ~DPAA_SGTE_BPID_MASK) | (((val) << (31-15))& DPAA_SGTE_BPID_MASK))) /**< Macro to set SGTE BPID field */ ++#define DPAA_SGTE_SET_OFFSET(sgte,val) (((t_DpaaSGTE *)sgte)->offset = ((((t_DpaaSGTE *)sgte)->offset & ~DPAA_SGTE_OFFSET_MASK) | (((val) << (31-31))& DPAA_SGTE_OFFSET_MASK) )) /**< Macro to set SGTE OFFSET field */ ++/* @} */ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/** @} */ /* end of DPAA_grp group */ ++ ++ ++#endif /* __DPAA_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_ext.h b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_ext.h +new file mode 100644 +index 0000000..6acf50b +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_ext.h +@@ -0,0 +1,1681 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_ext.h ++ ++ @Description FM Application Programming Interface. ++*//***************************************************************************/ ++#ifndef __FM_EXT ++#define __FM_EXT ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "dpaa_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_lib_grp FM library ++ ++ @Description FM API functions, definitions and enums ++ ++ The FM module is the main driver module and is a mandatory module ++ for FM driver users. This module must be initialized first prior ++ to any other drivers modules. ++ The FM is a "singleton" module. It is responsible of the common ++ HW modules: FPM, DMA, common QMI and common BMI initializations and ++ run-time control routines. This module must be initialized always ++ when working with any of the FM modules. ++ NOTE - We assume that the FM library will be initialized only by core No. 0! ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Enum for defining port types ++*//***************************************************************************/ ++typedef enum e_FmPortType { ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING = 0, /**< Offline parsing port */ ++ e_FM_PORT_TYPE_RX, /**< 1G Rx port */ ++ e_FM_PORT_TYPE_RX_10G, /**< 10G Rx port */ ++ e_FM_PORT_TYPE_TX, /**< 1G Tx port */ ++ e_FM_PORT_TYPE_TX_10G, /**< 10G Tx port */ ++ e_FM_PORT_TYPE_DUMMY ++} e_FmPortType; ++ ++/**************************************************************************//** ++ @Collection General FM defines ++*//***************************************************************************/ ++#define FM_MAX_NUM_OF_PARTITIONS 64 /**< Maximum number of partitions */ ++#define FM_PHYS_ADDRESS_SIZE 6 /**< FM Physical address size */ ++/* @} */ ++ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description FM physical Address ++*//***************************************************************************/ ++typedef _Packed struct t_FmPhysAddr { ++ volatile uint8_t high; /**< High part of the physical address */ ++ volatile uint32_t low; /**< Low part of the physical address */ ++} _PackedType t_FmPhysAddr; ++ ++/**************************************************************************//** ++ @Description Parse results memory layout ++*//***************************************************************************/ ++typedef _Packed struct t_FmPrsResult { ++ volatile uint8_t lpid; /**< Logical port id */ ++ volatile uint8_t shimr; /**< Shim header result */ ++ volatile uint16_t l2r; /**< Layer 2 result */ ++ volatile uint16_t l3r; /**< Layer 3 result */ ++ volatile uint8_t l4r; /**< Layer 4 result */ ++ volatile uint8_t cplan; /**< Classification plan id */ ++ volatile uint16_t nxthdr; /**< Next Header */ ++ volatile uint16_t cksum; /**< Running-sum */ ++ volatile uint16_t flags_frag_off; /**< Flags & fragment-offset field of the last IP-header */ ++ volatile uint8_t route_type; /**< Routing type field of a IPv6 routing extension header */ ++ volatile uint8_t rhp_ip_valid; /**< Routing Extension Header Present; last bit is IP valid */ ++ volatile uint8_t shim_off[2]; /**< Shim offset */ ++ volatile uint8_t ip_pid_off; /**< IP PID (last IP-proto) offset */ ++ volatile uint8_t eth_off; /**< ETH offset */ ++ volatile uint8_t llc_snap_off; /**< LLC_SNAP offset */ ++ volatile uint8_t vlan_off[2]; /**< VLAN offset */ ++ volatile uint8_t etype_off; /**< ETYPE offset */ ++ volatile uint8_t pppoe_off; /**< PPP offset */ ++ volatile uint8_t mpls_off[2]; /**< MPLS offset */ ++ volatile uint8_t ip_off[2]; /**< IP offset */ ++ volatile uint8_t gre_off; /**< GRE offset */ ++ volatile uint8_t l4_off; /**< Layer 4 offset */ ++ volatile uint8_t nxthdr_off; /**< Parser end point */ ++} _PackedType t_FmPrsResult; ++ ++/**************************************************************************//** ++ @Collection FM Parser results ++*//***************************************************************************/ ++#define FM_PR_L2_VLAN_STACK 0x00000100 /**< Parse Result: VLAN stack */ ++#define FM_PR_L2_ETHERNET 0x00008000 /**< Parse Result: Ethernet*/ ++#define FM_PR_L2_VLAN 0x00004000 /**< Parse Result: VLAN */ ++#define FM_PR_L2_LLC_SNAP 0x00002000 /**< Parse Result: LLC_SNAP */ ++#define FM_PR_L2_MPLS 0x00001000 /**< Parse Result: MPLS */ ++#define FM_PR_L2_PPPoE 0x00000800 /**< Parse Result: PPPoE */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection FM Frame descriptor macros ++*//***************************************************************************/ ++#define FM_FD_CMD_FCO 0x80000000 /**< Frame queue Context Override */ ++#define FM_FD_CMD_RPD 0x40000000 /**< Read Prepended Data */ ++#define FM_FD_CMD_UPD 0x20000000 /**< Update Prepended Data */ ++#define FM_FD_CMD_DTC 0x10000000 /**< Do L4 Checksum */ ++#define FM_FD_CMD_DCL4C 0x10000000 /**< Didn't calculate L4 Checksum */ ++#define FM_FD_CMD_CFQ 0x00ffffff /**< Confirmation Frame Queue */ ++ ++#define FM_FD_ERR_UNSUPPORTED_FORMAT 0x04000000 /**< Not for Rx-Port! Unsupported Format */ ++#define FM_FD_ERR_LENGTH 0x02000000 /**< Not for Rx-Port! Length Error */ ++#define FM_FD_ERR_DMA 0x01000000 /**< DMA Data error */ ++ ++#define FM_FD_IPR 0x00000001 /**< IPR frame (not error) */ ++ ++#define FM_FD_ERR_IPR_NCSP (0x00100000 | FM_FD_IPR) /**< IPR non-consistent-sp */ ++#define FM_FD_ERR_IPR (0x00200000 | FM_FD_IPR) /**< IPR error */ ++#define FM_FD_ERR_IPR_TO (0x00300000 | FM_FD_IPR) /**< IPR timeout */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++#define FM_FD_ERR_CRE 0x00200000 ++#define FM_FD_ERR_CHE 0x00100000 ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++#define FM_FD_ERR_PHYSICAL 0x00080000 /**< Rx FIFO overflow, FCS error, code error, running disparity ++ error (SGMII and TBI modes), FIFO parity error. PHY ++ Sequence error, PHY error control character detected. */ ++#define FM_FD_ERR_SIZE 0x00040000 /**< Frame too long OR Frame size exceeds max_length_frame */ ++#define FM_FD_ERR_CLS_DISCARD 0x00020000 /**< classification discard */ ++#define FM_FD_ERR_EXTRACTION 0x00008000 /**< Extract Out of Frame */ ++#define FM_FD_ERR_NO_SCHEME 0x00004000 /**< No Scheme Selected */ ++#define FM_FD_ERR_KEYSIZE_OVERFLOW 0x00002000 /**< Keysize Overflow */ ++#define FM_FD_ERR_COLOR_RED 0x00000800 /**< Frame color is red */ ++#define FM_FD_ERR_COLOR_YELLOW 0x00000400 /**< Frame color is yellow */ ++#define FM_FD_ERR_ILL_PLCR 0x00000200 /**< Illegal Policer Profile selected */ ++#define FM_FD_ERR_PLCR_FRAME_LEN 0x00000100 /**< Policer frame length error */ ++#define FM_FD_ERR_PRS_TIMEOUT 0x00000080 /**< Parser Time out Exceed */ ++#define FM_FD_ERR_PRS_ILL_INSTRUCT 0x00000040 /**< Invalid Soft Parser instruction */ ++#define FM_FD_ERR_PRS_HDR_ERR 0x00000020 /**< Header error was identified during parsing */ ++#define FM_FD_ERR_BLOCK_LIMIT_EXCEEDED 0x00000008 /**< Frame parsed beyind 256 first bytes */ ++ ++#define FM_FD_TX_STATUS_ERR_MASK (FM_FD_ERR_UNSUPPORTED_FORMAT | \ ++ FM_FD_ERR_LENGTH | \ ++ FM_FD_ERR_DMA) /**< TX Error FD bits */ ++ ++#define FM_FD_RX_STATUS_ERR_MASK (FM_FD_ERR_UNSUPPORTED_FORMAT | \ ++ FM_FD_ERR_LENGTH | \ ++ FM_FD_ERR_DMA | \ ++ FM_FD_ERR_IPR | \ ++ FM_FD_ERR_IPR_TO | \ ++ FM_FD_ERR_IPR_NCSP | \ ++ FM_FD_ERR_PHYSICAL | \ ++ FM_FD_ERR_SIZE | \ ++ FM_FD_ERR_CLS_DISCARD | \ ++ FM_FD_ERR_COLOR_RED | \ ++ FM_FD_ERR_COLOR_YELLOW | \ ++ FM_FD_ERR_ILL_PLCR | \ ++ FM_FD_ERR_PLCR_FRAME_LEN | \ ++ FM_FD_ERR_EXTRACTION | \ ++ FM_FD_ERR_NO_SCHEME | \ ++ FM_FD_ERR_KEYSIZE_OVERFLOW | \ ++ FM_FD_ERR_PRS_TIMEOUT | \ ++ FM_FD_ERR_PRS_ILL_INSTRUCT | \ ++ FM_FD_ERR_PRS_HDR_ERR | \ ++ FM_FD_ERR_BLOCK_LIMIT_EXCEEDED) /**< RX Error FD bits */ ++ ++#define FM_FD_RX_STATUS_ERR_NON_FM 0x00400000 /**< non Frame-Manager error */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description Context A ++*//***************************************************************************/ ++typedef _Packed struct t_FmContextA { ++ volatile uint32_t command; /**< ContextA Command */ ++ volatile uint8_t res0[4]; /**< ContextA Reserved bits */ ++} _PackedType t_FmContextA; ++ ++/**************************************************************************//** ++ @Description Context B ++*//***************************************************************************/ ++typedef uint32_t t_FmContextB; ++ ++/**************************************************************************//** ++ @Collection Special Operation options ++*//***************************************************************************/ ++typedef uint32_t fmSpecialOperations_t; /**< typedef for defining Special Operation options */ ++ ++#define FM_SP_OP_IPSEC 0x80000000 /**< activate features that related to IPSec (e.g fix Eth-type) */ ++#define FM_SP_OP_IPSEC_UPDATE_UDP_LEN 0x40000000 /**< update the UDP-Len after Encryption */ ++#define FM_SP_OP_IPSEC_MANIP 0x20000000 /**< handle the IPSec-manip options */ ++#define FM_SP_OP_RPD 0x10000000 /**< Set the RPD bit */ ++#define FM_SP_OP_DCL4C 0x08000000 /**< Set the DCL4C bit */ ++#define FM_SP_OP_CHECK_SEC_ERRORS 0x04000000 /**< Check SEC errors */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection Context A macros ++*//***************************************************************************/ ++#define FM_CONTEXTA_OVERRIDE_MASK 0x80000000 ++#define FM_CONTEXTA_ICMD_MASK 0x40000000 ++#define FM_CONTEXTA_A1_VALID_MASK 0x20000000 ++#define FM_CONTEXTA_MACCMD_MASK 0x00ff0000 ++#define FM_CONTEXTA_MACCMD_VALID_MASK 0x00800000 ++#define FM_CONTEXTA_MACCMD_SECURED_MASK 0x00100000 ++#define FM_CONTEXTA_MACCMD_SC_MASK 0x000f0000 ++#define FM_CONTEXTA_A1_MASK 0x0000ffff ++ ++#define FM_CONTEXTA_GET_OVERRIDE(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_OVERRIDE_MASK) >> (31-0)) ++#define FM_CONTEXTA_GET_ICMD(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_ICMD_MASK) >> (31-1)) ++#define FM_CONTEXTA_GET_A1_VALID(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_A1_VALID_MASK) >> (31-2)) ++#define FM_CONTEXTA_GET_A1(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_A1_MASK) >> (31-31)) ++#define FM_CONTEXTA_GET_MACCMD(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_MASK) >> (31-15)) ++#define FM_CONTEXTA_GET_MACCMD_VALID(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_VALID_MASK) >> (31-8)) ++#define FM_CONTEXTA_GET_MACCMD_SECURED(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_SECURED_MASK) >> (31-11)) ++#define FM_CONTEXTA_GET_MACCMD_SECURE_CHANNEL(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_SC_MASK) >> (31-15)) ++ ++#define FM_CONTEXTA_SET_OVERRIDE(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_OVERRIDE_MASK) | (((uint32_t)(val) << (31-0)) & FM_CONTEXTA_OVERRIDE_MASK) )) ++#define FM_CONTEXTA_SET_ICMD(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_ICMD_MASK) | (((val) << (31-1)) & FM_CONTEXTA_ICMD_MASK) )) ++#define FM_CONTEXTA_SET_A1_VALID(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_A1_VALID_MASK) | (((val) << (31-2)) & FM_CONTEXTA_A1_VALID_MASK) )) ++#define FM_CONTEXTA_SET_A1(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_A1_MASK) | (((val) << (31-31)) & FM_CONTEXTA_A1_MASK) )) ++#define FM_CONTEXTA_SET_MACCMD(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_MASK) | (((val) << (31-15)) & FM_CONTEXTA_MACCMD_MASK) )) ++#define FM_CONTEXTA_SET_MACCMD_VALID(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_VALID_MASK) | (((val) << (31-8)) & FM_CONTEXTA_MACCMD_VALID_MASK) )) ++#define FM_CONTEXTA_SET_MACCMD_SECURED(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_SECURED_MASK) | (((val) << (31-11)) & FM_CONTEXTA_MACCMD_SECURED_MASK) )) ++#define FM_CONTEXTA_SET_MACCMD_SECURE_CHANNEL(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_SC_MASK) | (((val) << (31-15)) & FM_CONTEXTA_MACCMD_SC_MASK) )) ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection Context B macros ++*//***************************************************************************/ ++#define FM_CONTEXTB_FQID_MASK 0x00ffffff ++ ++#define FM_CONTEXTB_GET_FQID(contextB) (*((t_FmContextB *)contextB) & FM_CONTEXTB_FQID_MASK) ++#define FM_CONTEXTB_SET_FQID(contextB,val) (*((t_FmContextB *)contextB) = ((*((t_FmContextB *)contextB) & ~FM_CONTEXTB_FQID_MASK) | ((val) & FM_CONTEXTB_FQID_MASK))) ++/* @} */ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/**************************************************************************//** ++ @Description FM Exceptions ++*//***************************************************************************/ ++typedef enum e_FmExceptions { ++ e_FM_EX_DMA_BUS_ERROR = 0, /**< DMA bus error. */ ++ e_FM_EX_DMA_READ_ECC, /**< Read Buffer ECC error (Valid for FM rev < 6)*/ ++ e_FM_EX_DMA_SYSTEM_WRITE_ECC, /**< Write Buffer ECC error on system side (Valid for FM rev < 6)*/ ++ e_FM_EX_DMA_FM_WRITE_ECC, /**< Write Buffer ECC error on FM side (Valid for FM rev < 6)*/ ++ e_FM_EX_DMA_SINGLE_PORT_ECC, /**< Single Port ECC error on FM side (Valid for FM rev > 6)*/ ++ e_FM_EX_FPM_STALL_ON_TASKS, /**< Stall of tasks on FPM */ ++ e_FM_EX_FPM_SINGLE_ECC, /**< Single ECC on FPM. */ ++ e_FM_EX_FPM_DOUBLE_ECC, /**< Double ECC error on FPM ram access */ ++ e_FM_EX_QMI_SINGLE_ECC, /**< Single ECC on QMI. */ ++ e_FM_EX_QMI_DOUBLE_ECC, /**< Double bit ECC occurred on QMI */ ++ e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,/**< Dequeue from unknown port id */ ++ e_FM_EX_BMI_LIST_RAM_ECC, /**< Linked List RAM ECC error */ ++ e_FM_EX_BMI_STORAGE_PROFILE_ECC, /**< Storage Profile ECC Error */ ++ e_FM_EX_BMI_STATISTICS_RAM_ECC, /**< Statistics Count RAM ECC Error Enable */ ++ e_FM_EX_BMI_DISPATCH_RAM_ECC, /**< Dispatch RAM ECC Error Enable */ ++ e_FM_EX_IRAM_ECC, /**< Double bit ECC occurred on IRAM*/ ++ e_FM_EX_MURAM_ECC /**< Double bit ECC occurred on MURAM*/ ++} e_FmExceptions; ++ ++/**************************************************************************//** ++ @Description Enum for defining port DMA swap mode ++*//***************************************************************************/ ++typedef enum e_FmDmaSwapOption { ++ e_FM_DMA_NO_SWP, /**< No swap, transfer data as is.*/ ++ e_FM_DMA_SWP_PPC_LE, /**< The transferred data should be swapped ++ in PowerPc Little Endian mode. */ ++ e_FM_DMA_SWP_BE /**< The transferred data should be swapped ++ in Big Endian mode */ ++} e_FmDmaSwapOption; ++ ++/**************************************************************************//** ++ @Description Enum for defining port DMA cache attributes ++*//***************************************************************************/ ++typedef enum e_FmDmaCacheOption { ++ e_FM_DMA_NO_STASH = 0, /**< Cacheable, no Allocate (No Stashing) */ ++ e_FM_DMA_STASH = 1 /**< Cacheable and Allocate (Stashing on) */ ++} e_FmDmaCacheOption; ++ ++ ++/**************************************************************************//** ++ @Group FM_init_grp FM Initialization Unit ++ ++ @Description FM Initialization Unit ++ ++ Initialization Flow ++ Initialization of the FM Module will be carried out by the application ++ according to the following sequence: ++ - Calling the configuration routine with basic parameters. ++ - Calling the advance initialization routines to change driver's defaults. ++ - Calling the initialization routine. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function t_FmExceptionsCallback ++ ++ @Description Exceptions user callback routine, will be called upon an ++ exception passing the exception identification. ++ ++ @Param[in] h_App - User's application descriptor. ++ @Param[in] exception - The exception. ++*//***************************************************************************/ ++typedef void (t_FmExceptionsCallback)(t_Handle h_App, ++ e_FmExceptions exception); ++ ++ ++/**************************************************************************//** ++ @Function t_FmBusErrorCallback ++ ++ @Description Bus error user callback routine, will be called upon a ++ bus error, passing parameters describing the errors and the owner. ++ ++ @Param[in] h_App - User's application descriptor. ++ @Param[in] portType - Port type (e_FmPortType) ++ @Param[in] portId - Port id - relative to type. ++ @Param[in] addr - Address that caused the error ++ @Param[in] tnum - Owner of error ++ @Param[in] liodn - Logical IO device number ++*//***************************************************************************/ ++typedef void (t_FmBusErrorCallback) (t_Handle h_App, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint64_t addr, ++ uint8_t tnum, ++ uint16_t liodn); ++ ++/**************************************************************************//** ++ @Description A structure for defining buffer prefix area content. ++*//***************************************************************************/ ++typedef struct t_FmBufferPrefixContent { ++ uint16_t privDataSize; /**< Number of bytes to be left at the beginning ++ of the external buffer; Note that the private-area will ++ start from the base of the buffer address. */ ++ bool passPrsResult; /**< TRUE to pass the parse result to/from the FM; ++ User may use FM_PORT_GetBufferPrsResult() in order to ++ get the parser-result from a buffer. */ ++ bool passTimeStamp; /**< TRUE to pass the timeStamp to/from the FM ++ User may use FM_PORT_GetBufferTimeStamp() in order to ++ get the parser-result from a buffer. */ ++ bool passHashResult; /**< TRUE to pass the KG hash result to/from the FM ++ User may use FM_PORT_GetBufferHashResult() in order to ++ get the parser-result from a buffer. */ ++ bool passAllOtherPCDInfo;/**< Add all other Internal-Context information: ++ AD, hash-result, key, etc. */ ++ uint16_t dataAlign; /**< 0 to use driver's default alignment [64], ++ other value for selecting a data alignment (must be a power of 2); ++ if write optimization is used, must be >= 16. */ ++ uint8_t manipExtraSpace; /**< Maximum extra size needed (insertion-size minus removal-size); ++ Note that this field impacts the size of the buffer-prefix ++ (i.e. it pushes the data offset); ++ This field is irrelevant if DPAA_VERSION==10 */ ++} t_FmBufferPrefixContent; ++ ++/**************************************************************************//** ++ @Description A structure of information about each of the external ++ buffer pools used by a port or storage-profile. ++*//***************************************************************************/ ++typedef struct t_FmExtPoolParams { ++ uint8_t id; /**< External buffer pool id */ ++ uint16_t size; /**< External buffer pool buffer size */ ++} t_FmExtPoolParams; ++ ++/**************************************************************************//** ++ @Description A structure for informing the driver about the external ++ buffer pools allocated in the BM and used by a port or a ++ storage-profile. ++*//***************************************************************************/ ++typedef struct t_FmExtPools { ++ uint8_t numOfPoolsUsed; /**< Number of pools use by this port */ ++ t_FmExtPoolParams extBufPool[FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ /**< Parameters for each port */ ++} t_FmExtPools; ++ ++/**************************************************************************//** ++ @Description A structure for defining backup BM Pools. ++*//***************************************************************************/ ++typedef struct t_FmBackupBmPools { ++ uint8_t numOfBackupPools; /**< Number of BM backup pools - ++ must be smaller than the total number of ++ pools defined for the specified port.*/ ++ uint8_t poolIds[FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ /**< numOfBackupPools pool id's, specifying which ++ pools should be used only as backup. Pool ++ id's specified here must be a subset of the ++ pools used by the specified port.*/ ++} t_FmBackupBmPools; ++ ++/**************************************************************************//** ++ @Description A structure for defining BM pool depletion criteria ++*//***************************************************************************/ ++typedef struct t_FmBufPoolDepletion { ++ bool poolsGrpModeEnable; /**< select mode in which pause frames will be sent after ++ a number of pools (all together!) are depleted */ ++ uint8_t numOfPools; /**< the number of depleted pools that will invoke ++ pause frames transmission. */ ++ bool poolsToConsider[BM_MAX_NUM_OF_POOLS]; ++ /**< For each pool, TRUE if it should be considered for ++ depletion (Note - this pool must be used by this port!). */ ++ bool singlePoolModeEnable; /**< select mode in which pause frames will be sent after ++ a single-pool is depleted; */ ++ bool poolsToConsiderForSingleMode[BM_MAX_NUM_OF_POOLS]; ++ /**< For each pool, TRUE if it should be considered for ++ depletion (Note - this pool must be used by this port!) */ ++#if (DPAA_VERSION >= 11) ++ bool pfcPrioritiesEn[FM_MAX_NUM_OF_PFC_PRIORITIES]; ++ /**< This field is used by the MAC as the Priority Enable Vector in the PFC frame which is transmitted */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmBufPoolDepletion; ++ ++/**************************************************************************//** ++ @Description A Structure for defining Ucode patch for loading. ++*//***************************************************************************/ ++typedef struct t_FmFirmwareParams { ++ uint32_t size; /**< Size of uCode */ ++ uint32_t *p_Code; /**< A pointer to the uCode */ ++} t_FmFirmwareParams; ++ ++/**************************************************************************//** ++ @Description A Structure for defining FM initialization parameters ++*//***************************************************************************/ ++typedef struct t_FmParams { ++ uint8_t fmId; /**< Index of the FM */ ++ uint8_t guestId; /**< FM Partition Id */ ++ uintptr_t baseAddr; /**< A pointer to base of memory mapped FM registers (virtual); ++ this field is optional when the FM runs in "guest-mode" ++ (i.e. guestId != NCSW_MASTER_ID); in that case, the driver will ++ use the memory-map instead of calling the IPC where possible; ++ NOTE that this should include ALL common registers of the FM including ++ the PCD registers area (i.e. until the VSP pages - 880KB). */ ++ t_Handle h_FmMuram; /**< A handle of an initialized MURAM object, ++ to be used by the FM. */ ++ uint16_t fmClkFreq; /**< In Mhz; ++ Relevant when FM not runs in "guest-mode". */ ++ t_FmExceptionsCallback *f_Exception; /**< An application callback routine to handle exceptions; ++ Relevant when FM not runs in "guest-mode". */ ++ t_FmBusErrorCallback *f_BusError; /**< An application callback routine to handle exceptions; ++ Relevant when FM not runs in "guest-mode". */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks; ++ Relevant when FM not runs in "guest-mode". */ ++ int irq; /**< FM interrupt source for normal events; ++ Relevant when FM not runs in "guest-mode". */ ++ int errIrq; /**< FM interrupt source for errors; ++ Relevant when FM not runs in "guest-mode". */ ++ t_FmFirmwareParams firmware; /**< The firmware parameters structure; ++ Relevant when FM not runs in "guest-mode". */ ++ ++#if (DPAA_VERSION >= 11) ++ uintptr_t vspBaseAddr; /**< A pointer to base of memory mapped FM VSP registers (virtual); ++ i.e. up to 24KB, depending on the specific chip. */ ++ uint8_t partVSPBase; /**< The first Virtual-Storage-Profile-id dedicated to this partition. ++ NOTE: this parameter relevant only when working with multiple partitions. */ ++ uint8_t partNumOfVSPs; /**< Number of VSPs dedicated to this partition. ++ NOTE: this parameter relevant only when working with multiple partitions. */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_Config ++ ++ @Description Creates the FM module and returns its handle (descriptor). ++ This descriptor must be passed as first parameter to all other ++ FM function calls. ++ ++ No actual initialization or configuration of FM hardware is ++ done by this routine. All FM parameters get default values that ++ may be changed by calling one or more of the advance config routines. ++ ++ @Param[in] p_FmParams - A pointer to a data structure of mandatory FM parameters ++ ++ @Return A handle to the FM object, or NULL for Failure. ++*//***************************************************************************/ ++t_Handle FM_Config(t_FmParams *p_FmParams); ++ ++/**************************************************************************//** ++ @Function FM_Init ++ ++ @Description Initializes the FM module by defining the software structure ++ and configuring the hardware registers. ++ ++ @Param[in] h_Fm - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_Init(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_Free ++ ++ @Description Frees all resources that were assigned to FM module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_Fm - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_Free(t_Handle h_Fm); ++ ++ ++/**************************************************************************//** ++ @Group FM_advanced_init_grp FM Advanced Configuration Unit ++ ++ @Description Advanced configuration routines are optional routines that may ++ be called in order to change the default driver settings. ++ ++ Note: Advanced configuration routines are not available for guest partition. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Enum for selecting DMA debug mode ++*//***************************************************************************/ ++typedef enum e_FmDmaDbgCntMode { ++ e_FM_DMA_DBG_NO_CNT = 0, /**< No counting */ ++ e_FM_DMA_DBG_CNT_DONE, /**< Count DONE commands */ ++ e_FM_DMA_DBG_CNT_COMM_Q_EM, /**< count command queue emergency signals */ ++ e_FM_DMA_DBG_CNT_INT_READ_EM, /**< Count Internal Read buffer emergency signal */ ++ e_FM_DMA_DBG_CNT_INT_WRITE_EM, /**< Count Internal Write buffer emergency signal */ ++ e_FM_DMA_DBG_CNT_FPM_WAIT, /**< Count FPM WAIT signal */ ++ e_FM_DMA_DBG_CNT_SIGLE_BIT_ECC, /**< Single bit ECC errors. */ ++ e_FM_DMA_DBG_CNT_RAW_WAR_PROT /**< Number of times there was a need for RAW & WAR protection. */ ++} e_FmDmaDbgCntMode; ++ ++/**************************************************************************//** ++ @Description Enum for selecting DMA Cache Override ++*//***************************************************************************/ ++typedef enum e_FmDmaCacheOverride { ++ e_FM_DMA_NO_CACHE_OR = 0, /**< No override of the Cache field */ ++ e_FM_DMA_NO_STASH_DATA, /**< Data should not be stashed in system level cache */ ++ e_FM_DMA_MAY_STASH_DATA, /**< Data may be stashed in system level cache */ ++ e_FM_DMA_STASH_DATA /**< Data should be stashed in system level cache */ ++} e_FmDmaCacheOverride; ++ ++/**************************************************************************//** ++ @Description Enum for selecting DMA External Bus Priority ++*//***************************************************************************/ ++typedef enum e_FmDmaExtBusPri { ++ e_FM_DMA_EXT_BUS_NORMAL = 0, /**< Normal priority */ ++ e_FM_DMA_EXT_BUS_EBS, /**< AXI extended bus service priority */ ++ e_FM_DMA_EXT_BUS_SOS, /**< AXI sos priority */ ++ e_FM_DMA_EXT_BUS_EBS_AND_SOS /**< AXI ebs + sos priority */ ++} e_FmDmaExtBusPri; ++ ++/**************************************************************************//** ++ @Description Enum for choosing the field that will be output on AID ++*//***************************************************************************/ ++typedef enum e_FmDmaAidMode { ++ e_FM_DMA_AID_OUT_PORT_ID = 0, /**< 4 LSB of PORT_ID */ ++ e_FM_DMA_AID_OUT_TNUM /**< 4 LSB of TNUM */ ++} e_FmDmaAidMode; ++ ++/**************************************************************************//** ++ @Description Enum for selecting FPM Catastrophic error behavior ++*//***************************************************************************/ ++typedef enum e_FmCatastrophicErr { ++ e_FM_CATASTROPHIC_ERR_STALL_PORT = 0, /**< Port_ID is stalled (only reset can release it) */ ++ e_FM_CATASTROPHIC_ERR_STALL_TASK /**< Only erroneous task is stalled */ ++} e_FmCatastrophicErr; ++ ++/**************************************************************************//** ++ @Description Enum for selecting FPM DMA Error behavior ++*//***************************************************************************/ ++typedef enum e_FmDmaErr { ++ e_FM_DMA_ERR_CATASTROPHIC = 0, /**< Dma error is treated as a catastrophic ++ error (e_FmCatastrophicErr)*/ ++ e_FM_DMA_ERR_REPORT /**< Dma error is just reported */ ++} e_FmDmaErr; ++ ++/**************************************************************************//** ++ @Description Enum for selecting DMA Emergency level by BMI emergency signal ++*//***************************************************************************/ ++typedef enum e_FmDmaEmergencyLevel { ++ e_FM_DMA_EM_EBS = 0, /**< EBS emergency */ ++ e_FM_DMA_EM_SOS /**< SOS emergency */ ++} e_FmDmaEmergencyLevel; ++ ++/**************************************************************************//** ++ @Collection Enum for selecting DMA Emergency options ++*//***************************************************************************/ ++typedef uint32_t fmEmergencyBus_t; /**< DMA emergency options */ ++ ++#define FM_DMA_MURAM_READ_EMERGENCY 0x00800000 /**< Enable emergency for MURAM1 */ ++#define FM_DMA_MURAM_WRITE_EMERGENCY 0x00400000 /**< Enable emergency for MURAM2 */ ++#define FM_DMA_EXT_BUS_EMERGENCY 0x00100000 /**< Enable emergency for external bus */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description A structure for defining DMA emergency level ++*//***************************************************************************/ ++typedef struct t_FmDmaEmergency { ++ fmEmergencyBus_t emergencyBusSelect; /**< An OR of the busses where emergency ++ should be enabled */ ++ e_FmDmaEmergencyLevel emergencyLevel; /**< EBS/SOS */ ++} t_FmDmaEmergency; ++ ++/**************************************************************************//* ++ @Description structure for defining FM threshold ++*//***************************************************************************/ ++typedef struct t_FmThresholds { ++ uint8_t dispLimit; /**< The number of times a frames may ++ be passed in the FM before assumed to ++ be looping. */ ++ uint8_t prsDispTh; /**< This is the number pf packets that may be ++ queued in the parser dispatch queue*/ ++ uint8_t plcrDispTh; /**< This is the number pf packets that may be ++ queued in the policer dispatch queue*/ ++ uint8_t kgDispTh; /**< This is the number pf packets that may be ++ queued in the keygen dispatch queue*/ ++ uint8_t bmiDispTh; /**< This is the number pf packets that may be ++ queued in the BMI dispatch queue*/ ++ uint8_t qmiEnqDispTh; /**< This is the number pf packets that may be ++ queued in the QMI enqueue dispatch queue*/ ++ uint8_t qmiDeqDispTh; /**< This is the number pf packets that may be ++ queued in the QMI dequeue dispatch queue*/ ++ uint8_t fmCtl1DispTh; /**< This is the number pf packets that may be ++ queued in fmCtl1 dispatch queue*/ ++ uint8_t fmCtl2DispTh; /**< This is the number pf packets that may be ++ queued in fmCtl2 dispatch queue*/ ++} t_FmThresholds; ++ ++/**************************************************************************//* ++ @Description structure for defining DMA thresholds ++*//***************************************************************************/ ++typedef struct t_FmDmaThresholds { ++ uint8_t assertEmergency; /**< When this value is reached, ++ assert emergency (Threshold)*/ ++ uint8_t clearEmergency; /**< After emergency is asserted, it is held ++ until this value is reached (Hystheresis) */ ++} t_FmDmaThresholds; ++ ++ ++/**************************************************************************//** ++ @Function FM_ConfigResetOnInit ++ ++ @Description Define whether to reset the FM before initialization. ++ Change the default configuration [FALSE]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] enable When TRUE, FM will be reset before any initialization. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigResetOnInit(t_Handle h_Fm, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_ConfigTotalFifoSize ++ ++ @Description Define Total FIFO size for the whole FM. ++ Calling this routine changes the total Fifo size in the internal driver ++ data base from its default configuration [major] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] totalFifoSize The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigTotalFifoSize(t_Handle h_Fm, uint32_t totalFifoSize); ++ ++ /**************************************************************************//** ++ @Function FM_ConfigDmaCacheOverride ++ ++ @Description Define cache override mode. ++ Calling this routine changes the cache override mode ++ in the internal driver data base from its default configuration [e_FM_DMA_NO_CACHE_OR] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] cacheOverride The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaCacheOverride(t_Handle h_Fm, e_FmDmaCacheOverride cacheOverride); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaAidOverride ++ ++ @Description Define DMA AID override mode. ++ Calling this routine changes the AID override mode ++ in the internal driver data base from its default configuration [TRUE] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] aidOverride The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaAidOverride(t_Handle h_Fm, bool aidOverride); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaAidMode ++ ++ @Description Define DMA AID mode. ++ Calling this routine changes the AID mode in the internal ++ driver data base from its default configuration [e_FM_DMA_AID_OUT_TNUM] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] aidMode The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaAidMode(t_Handle h_Fm, e_FmDmaAidMode aidMode); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaAxiDbgNumOfBeats ++ ++ @Description Define DMA AXI number of beats. ++ Calling this routine changes the AXI number of beats in the internal ++ driver data base from its default configuration [1] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] axiDbgNumOfBeats The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaAxiDbgNumOfBeats(t_Handle h_Fm, uint8_t axiDbgNumOfBeats); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaCamNumOfEntries ++ ++ @Description Define number of CAM entries. ++ Calling this routine changes the number of CAM entries in the internal ++ driver data base from its default configuration [32]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] numOfEntries The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaCamNumOfEntries(t_Handle h_Fm, uint8_t numOfEntries); ++ ++/**************************************************************************//** ++ @Function FM_ConfigEnableCounters ++ ++ @Description Obsolete, always return E_OK. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_ConfigEnableCounters(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaDbgCounter ++ ++ @Description Define DMA debug counter. ++ Calling this routine changes the number of the DMA debug counter in the internal ++ driver data base from its default configuration [e_FM_DMA_DBG_NO_CNT]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] fmDmaDbgCntMode An enum selecting the debug counter mode. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaDbgCounter(t_Handle h_Fm, e_FmDmaDbgCntMode fmDmaDbgCntMode); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaStopOnBusErr ++ ++ @Description Define bus error behavior. ++ Calling this routine changes the bus error behavior definition ++ in the internal driver data base from its default ++ configuration [FALSE]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] stop TRUE to stop on bus error, FALSE to continue. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ Only if bus error is enabled. ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaStopOnBusErr(t_Handle h_Fm, bool stop); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaEmergency ++ ++ @Description Define DMA emergency. ++ Calling this routine changes the DMA emergency definition ++ in the internal driver data base from its default ++ configuration where's it's disabled. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] p_Emergency An OR mask of all required options. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaEmergency(t_Handle h_Fm, t_FmDmaEmergency *p_Emergency); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaErr ++ ++ @Description DMA error treatment. ++ Calling this routine changes the DMA error treatment ++ in the internal driver data base from its default ++ configuration [e_FM_DMA_ERR_CATASTROPHIC]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] dmaErr The selected new choice. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaErr(t_Handle h_Fm, e_FmDmaErr dmaErr); ++ ++/**************************************************************************//** ++ @Function FM_ConfigCatastrophicErr ++ ++ @Description Define FM behavior on catastrophic error. ++ Calling this routine changes the FM behavior on catastrophic ++ error in the internal driver data base from its default ++ [e_FM_CATASTROPHIC_ERR_STALL_PORT]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] catastrophicErr The selected new choice. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigCatastrophicErr(t_Handle h_Fm, e_FmCatastrophicErr catastrophicErr); ++ ++/**************************************************************************//** ++ @Function FM_ConfigEnableMuramTestMode ++ ++ @Description Enable MURAM test mode. ++ Calling this routine changes the internal driver data base ++ from its default selection of test mode where it's disabled. ++ This routine is only avaiable on old FM revisions (FMan v2). ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigEnableMuramTestMode(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_ConfigEnableIramTestMode ++ ++ @Description Enable IRAM test mode. ++ Calling this routine changes the internal driver data base ++ from its default selection of test mode where it's disabled. ++ This routine is only avaiable on old FM revisions (FMan v2). ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigEnableIramTestMode(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_ConfigHaltOnExternalActivation ++ ++ @Description Define FM behavior on external halt activation. ++ Calling this routine changes the FM behavior on external halt ++ activation in the internal driver data base from its default ++ [FALSE]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] enable TRUE to enable halt on external halt ++ activation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigHaltOnExternalActivation(t_Handle h_Fm, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_ConfigHaltOnUnrecoverableEccError ++ ++ @Description Define FM behavior on external halt activation. ++ Calling this routine changes the FM behavior on unrecoverable ++ ECC error in the internal driver data base from its default ++ [FALSE]. ++ This routine is only avaiable on old FM revisions (FMan v2). ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] enable TRUE to enable halt on unrecoverable Ecc error ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigHaltOnUnrecoverableEccError(t_Handle h_Fm, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_ConfigException ++ ++ @Description Define FM exceptions. ++ Calling this routine changes the exceptions defaults in the ++ internal driver data base where all exceptions are enabled. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigException(t_Handle h_Fm, e_FmExceptions exception, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_ConfigExternalEccRamsEnable ++ ++ @Description Select external ECC enabling. ++ Calling this routine changes the ECC enabling control in the internal ++ driver data base from its default [FALSE]. ++ When this option is enabled Rams ECC enabling is not effected ++ by FM_EnableRamsEcc/FM_DisableRamsEcc, but by a JTAG. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] enable TRUE to enable this option. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigExternalEccRamsEnable(t_Handle h_Fm, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_ConfigTnumAgingPeriod ++ ++ @Description Define Tnum aging period. ++ Calling this routine changes the Tnum aging of dequeue TNUM's ++ in the QMI in the internal driver data base from its default ++ [0]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] tnumAgingPeriod Tnum Aging Period in microseconds. ++ Note that period is recalculated in units of ++ 64 FM clocks. Driver will pick the closest ++ possible period. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigTnumAgingPeriod(t_Handle h_Fm, uint16_t tnumAgingPeriod); ++ ++/**************************************************************************//* ++ @Function FM_ConfigDmaEmergencySmoother ++ ++ @Description Define DMA emergency smoother. ++ Calling this routine changes the definition of the minimum ++ amount of DATA beats transferred on the AXI READ and WRITE ++ ports before lowering the emergency level. ++ By default smoother is disabled. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] emergencyCnt emergency switching counter. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaEmergencySmoother(t_Handle h_Fm, uint32_t emergencyCnt); ++ ++/**************************************************************************//* ++ @Function FM_ConfigThresholds ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default FM threshold configuration: ++ dispLimit: [0] ++ prsDispTh: [16] ++ plcrDispTh: [16] ++ kgDispTh: [16] ++ bmiDispTh: [16] ++ qmiEnqDispTh: [16] ++ qmiDeqDispTh: [16] ++ fmCtl1DispTh: [16] ++ fmCtl2DispTh: [16] ++ ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] p_FmThresholds A structure of threshold parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigThresholds(t_Handle h_Fm, t_FmThresholds *p_FmThresholds); ++ ++/**************************************************************************//* ++ @Function FM_ConfigDmaSosEmergencyThreshold ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default dma SOS emergency configuration [0] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] dmaSosEmergency The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaSosEmergencyThreshold(t_Handle h_Fm, uint32_t dmaSosEmergency); ++ ++/**************************************************************************//* ++ @Function FM_ConfigDmaWriteBufThresholds ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default configuration of DMA write buffer threshold ++ assertEmergency: [DMA_THRESH_MAX_BUF] ++ clearEmergency: [DMA_THRESH_MAX_BUF] ++ This routine is only avaiable on old FM revisions (FMan v2). ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] p_FmDmaThresholds A structure of thresholds to define emergency behavior - ++ When 'assertEmergency' value is reached, emergency is asserted, ++ then it is held until 'clearEmergency' value is reached. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaWriteBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds); ++ ++ /**************************************************************************//* ++ @Function FM_ConfigDmaCommQThresholds ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default configuration of DMA command queue threshold ++ assertEmergency: [DMA_THRESH_MAX_COMMQ] ++ clearEmergency: [DMA_THRESH_MAX_COMMQ] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] p_FmDmaThresholds A structure of thresholds to define emergency behavior - ++ When 'assertEmergency' value is reached, emergency is asserted, ++ then it is held until 'clearEmergency' value is reached.. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaCommQThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds); ++ ++/**************************************************************************//* ++ @Function FM_ConfigDmaReadBufThresholds ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default configuration of DMA read buffer threshold ++ assertEmergency: [DMA_THRESH_MAX_BUF] ++ clearEmergency: [DMA_THRESH_MAX_BUF] ++ This routine is only avaiable on old FM revisions (FMan v2). ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] p_FmDmaThresholds A structure of thresholds to define emergency behavior - ++ When 'assertEmergency' value is reached, emergency is asserted, ++ then it is held until 'clearEmergency' value is reached.. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaReadBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds); ++ ++/**************************************************************************//* ++ @Function FM_ConfigDmaWatchdog ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default watchdog configuration, which is disabled ++ [0]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] watchDogValue The selected new value - in microseconds. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaWatchdog(t_Handle h_Fm, uint32_t watchDogValue); ++ ++/** @} */ /* end of FM_advanced_init_grp group */ ++/** @} */ /* end of FM_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_runtime_control_grp FM Runtime Control Unit ++ ++ @Description FM Runtime control unit API functions, definitions and enums. ++ The FM driver provides a set of control routines. ++ These routines may only be called after the module was fully ++ initialized (both configuration and initialization routines were ++ called). They are typically used to get information from hardware ++ (status, counters/statistics, revision etc.), to modify a current ++ state or to force/enable a required action. Run-time control may ++ be called whenever necessary and as many times as needed. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection General FM defines. ++*//***************************************************************************/ ++#define FM_MAX_NUM_OF_VALID_PORTS (FM_MAX_NUM_OF_OH_PORTS + \ ++ FM_MAX_NUM_OF_1G_RX_PORTS + \ ++ FM_MAX_NUM_OF_10G_RX_PORTS + \ ++ FM_MAX_NUM_OF_1G_TX_PORTS + \ ++ FM_MAX_NUM_OF_10G_TX_PORTS) /**< Number of available FM ports */ ++/* @} */ ++ ++/**************************************************************************//* ++ @Description A Structure for Port bandwidth requirement. Port is identified ++ by type and relative id. ++*//***************************************************************************/ ++typedef struct t_FmPortBandwidth { ++ e_FmPortType type; /**< FM port type */ ++ uint8_t relativePortId; /**< Type relative port id */ ++ uint8_t bandwidth; /**< bandwidth - (in term of percents) */ ++} t_FmPortBandwidth; ++ ++/**************************************************************************//* ++ @Description A Structure containing an array of Port bandwidth requirements. ++ The user should state the ports requiring bandwidth in terms of ++ percentage - i.e. all port's bandwidths in the array must add ++ up to 100. ++*//***************************************************************************/ ++typedef struct t_FmPortsBandwidthParams { ++ uint8_t numOfPorts; /**< The number of relevant ports, which is the ++ number of valid entries in the array below */ ++ t_FmPortBandwidth portsBandwidths[FM_MAX_NUM_OF_VALID_PORTS]; ++ /**< for each port, it's bandwidth (all port's ++ bandwidths must add up to 100.*/ ++} t_FmPortsBandwidthParams; ++ ++/**************************************************************************//** ++ @Description DMA Emergency control on MURAM ++*//***************************************************************************/ ++typedef enum e_FmDmaMuramPort { ++ e_FM_DMA_MURAM_PORT_WRITE, /**< MURAM write port */ ++ e_FM_DMA_MURAM_PORT_READ /**< MURAM read port */ ++} e_FmDmaMuramPort; ++ ++/**************************************************************************//** ++ @Description Enum for defining FM counters ++*//***************************************************************************/ ++typedef enum e_FmCounters { ++ e_FM_COUNTERS_ENQ_TOTAL_FRAME = 0, /**< QMI total enqueued frames counter */ ++ e_FM_COUNTERS_DEQ_TOTAL_FRAME, /**< QMI total dequeued frames counter */ ++ e_FM_COUNTERS_DEQ_0, /**< QMI 0 frames from QMan counter */ ++ e_FM_COUNTERS_DEQ_1, /**< QMI 1 frames from QMan counter */ ++ e_FM_COUNTERS_DEQ_2, /**< QMI 2 frames from QMan counter */ ++ e_FM_COUNTERS_DEQ_3, /**< QMI 3 frames from QMan counter */ ++ e_FM_COUNTERS_DEQ_FROM_DEFAULT, /**< QMI dequeue from default queue counter */ ++ e_FM_COUNTERS_DEQ_FROM_CONTEXT, /**< QMI dequeue from FQ context counter */ ++ e_FM_COUNTERS_DEQ_FROM_FD, /**< QMI dequeue from FD command field counter */ ++ e_FM_COUNTERS_DEQ_CONFIRM /**< QMI dequeue confirm counter */ ++} e_FmCounters; ++ ++/**************************************************************************//** ++ @Description A Structure for returning FM revision information ++*//***************************************************************************/ ++typedef struct t_FmRevisionInfo { ++ uint8_t majorRev; /**< Major revision */ ++ uint8_t minorRev; /**< Minor revision */ ++} t_FmRevisionInfo; ++ ++/**************************************************************************//** ++ @Description A Structure for returning FM ctrl code revision information ++*//***************************************************************************/ ++typedef struct t_FmCtrlCodeRevisionInfo { ++ uint16_t packageRev; /**< Package revision */ ++ uint8_t majorRev; /**< Major revision */ ++ uint8_t minorRev; /**< Minor revision */ ++} t_FmCtrlCodeRevisionInfo; ++ ++/**************************************************************************//** ++ @Description A Structure for defining DMA status ++*//***************************************************************************/ ++typedef struct t_FmDmaStatus { ++ bool cmqNotEmpty; /**< Command queue is not empty */ ++ bool busError; /**< Bus error occurred */ ++ bool readBufEccError; /**< Double ECC error on buffer Read (Valid for FM rev < 6)*/ ++ bool writeBufEccSysError; /**< Double ECC error on buffer write from system side (Valid for FM rev < 6)*/ ++ bool writeBufEccFmError; /**< Double ECC error on buffer write from FM side (Valid for FM rev < 6) */ ++ bool singlePortEccError; /**< Single Port ECC error from FM side (Valid for FM rev >= 6)*/ ++} t_FmDmaStatus; ++ ++/**************************************************************************//** ++ @Description A Structure for obtaining FM controller monitor values ++*//***************************************************************************/ ++typedef struct t_FmCtrlMon { ++ uint8_t percentCnt[2]; /**< Percentage value */ ++} t_FmCtrlMon; ++ ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//** ++ @Function FM_DumpRegs ++ ++ @Description Dumps all FM registers ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FM_DumpRegs(t_Handle h_Fm); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++/**************************************************************************//** ++ @Function FM_SetException ++ ++ @Description Calling this routine enables/disables the specified exception. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_SetException(t_Handle h_Fm, e_FmExceptions exception, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_EnableRamsEcc ++ ++ @Description Enables ECC mechanism for all the different FM RAM's; E.g. IRAM, ++ MURAM, Parser, Keygen, Policer, etc. ++ Note: ++ If FM_ConfigExternalEccRamsEnable was called to enable external ++ setting of ECC, this routine effects IRAM ECC only. ++ This routine is also called by the driver if an ECC exception is ++ enabled. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_EnableRamsEcc(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_DisableRamsEcc ++ ++ @Description Disables ECC mechanism for all the different FM RAM's; E.g. IRAM, ++ MURAM, Parser, Keygen, Policer, etc. ++ Note: ++ If FM_ConfigExternalEccRamsEnable was called to enable external ++ setting of ECC, this routine effects IRAM ECC only. ++ In opposed to FM_EnableRamsEcc, this routine must be called ++ explicitly to disable all Rams ECC. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_DisableRamsEcc(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_GetRevision ++ ++ @Description Returns the FM revision ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[out] p_FmRevisionInfo A structure of revision information parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FM_GetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo); ++ ++/**************************************************************************//** ++ @Function FM_GetFmanCtrlCodeRevision ++ ++ @Description Returns the Fman controller code revision ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[out] p_RevisionInfo A structure of revision information parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FM_GetFmanCtrlCodeRevision(t_Handle h_Fm, t_FmCtrlCodeRevisionInfo *p_RevisionInfo); ++ ++/**************************************************************************//** ++ @Function FM_GetCounter ++ ++ @Description Reads one of the FM counters. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] counter The requested counter. ++ ++ @Return Counter's current value. ++ ++ @Cautions Allowed only following FM_Init(). ++ Note that it is user's responsibility to call this routine only ++ for enabled counters, and there will be no indication if a ++ disabled counter is accessed. ++*//***************************************************************************/ ++uint32_t FM_GetCounter(t_Handle h_Fm, e_FmCounters counter); ++ ++/**************************************************************************//** ++ @Function FM_ModifyCounter ++ ++ @Description Sets a value to an enabled counter. Use "0" to reset the counter. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] counter The requested counter. ++ @Param[in] val The requested value to be written into the counter. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ModifyCounter(t_Handle h_Fm, e_FmCounters counter, uint32_t val); ++ ++/**************************************************************************//** ++ @Function FM_Resume ++ ++ @Description Release FM after halt FM command or after unrecoverable ECC error. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++void FM_Resume(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_SetDmaEmergency ++ ++ @Description Manual emergency set ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] muramPort MURAM direction select. ++ @Param[in] enable TRUE to manually enable emergency, FALSE to disable. ++ ++ @Return None. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++void FM_SetDmaEmergency(t_Handle h_Fm, e_FmDmaMuramPort muramPort, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_SetDmaExtBusPri ++ ++ @Description Set the DMA external bus priority ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] pri External bus priority select ++ ++ @Return None. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++void FM_SetDmaExtBusPri(t_Handle h_Fm, e_FmDmaExtBusPri pri); ++ ++/**************************************************************************//** ++ @Function FM_GetDmaStatus ++ ++ @Description Reads the DMA current status ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[out] p_FmDmaStatus A structure of DMA status parameters. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++void FM_GetDmaStatus(t_Handle h_Fm, t_FmDmaStatus *p_FmDmaStatus); ++ ++/**************************************************************************//** ++ @Function FM_ErrorIsr ++ ++ @Description FM interrupt-service-routine for errors. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; E_EMPTY if no errors found in register, other ++ error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ErrorIsr(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_EventIsr ++ ++ @Description FM interrupt-service-routine for normal events. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++void FM_EventIsr(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_GetSpecialOperationCoding ++ ++ @Description Return a specific coding according to the input mask. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] spOper special operation mask. ++ @Param[out] p_SpOperCoding special operation code. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FM_GetSpecialOperationCoding(t_Handle h_Fm, ++ fmSpecialOperations_t spOper, ++ uint8_t *p_SpOperCoding); ++ ++/**************************************************************************//** ++ @Function FM_CtrlMonStart ++ ++ @Description Start monitoring utilization of all available FM controllers. ++ ++ In order to obtain FM controllers utilization the following sequence ++ should be used: ++ -# FM_CtrlMonStart() ++ -# FM_CtrlMonStop() ++ -# FM_CtrlMonGetCounters() - issued for each FM controller ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID). ++*//***************************************************************************/ ++t_Error FM_CtrlMonStart(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_CtrlMonStop ++ ++ @Description Stop monitoring utilization of all available FM controllers. ++ ++ In order to obtain FM controllers utilization the following sequence ++ should be used: ++ -# FM_CtrlMonStart() ++ -# FM_CtrlMonStop() ++ -# FM_CtrlMonGetCounters() - issued for each FM controller ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID). ++*//***************************************************************************/ ++t_Error FM_CtrlMonStop(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_CtrlMonGetCounters ++ ++ @Description Obtain FM controller utilization parameters. ++ ++ In order to obtain FM controllers utilization the following sequence ++ should be used: ++ -# FM_CtrlMonStart() ++ -# FM_CtrlMonStop() ++ -# FM_CtrlMonGetCounters() - issued for each FM controller ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] fmCtrlIndex FM Controller index for that utilization results ++ are requested. ++ @Param[in] p_Mon Pointer to utilization results structure. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID). ++*//***************************************************************************/ ++t_Error FM_CtrlMonGetCounters(t_Handle h_Fm, uint8_t fmCtrlIndex, t_FmCtrlMon *p_Mon); ++ ++ ++/**************************************************************************//* ++ @Function FM_ForceIntr ++ ++ @Description Causes an interrupt event on the requested source. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] exception An exception to be forced. ++ ++ @Return E_OK on success; Error code if the exception is not enabled, ++ or is not able to create interrupt. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ForceIntr (t_Handle h_Fm, e_FmExceptions exception); ++ ++/**************************************************************************//* ++ @Function FM_SetPortsBandwidth ++ ++ @Description Sets relative weights between ports when accessing common resources. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] p_PortsBandwidth A structure of ports bandwidths in percentage, i.e. ++ total must equal 100. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_SetPortsBandwidth(t_Handle h_Fm, t_FmPortsBandwidthParams *p_PortsBandwidth); ++ ++/** @} */ /* end of FM_runtime_control_grp group */ ++/** @} */ /* end of FM_lib_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#ifdef NCSW_BACKWARD_COMPATIBLE_API ++typedef t_FmFirmwareParams t_FmPcdFirmwareParams; ++typedef t_FmBufferPrefixContent t_FmPortBufferPrefixContent; ++typedef t_FmExtPoolParams t_FmPortExtPoolParams; ++typedef t_FmExtPools t_FmPortExtPools; ++typedef t_FmBackupBmPools t_FmPortBackupBmPools; ++typedef t_FmBufPoolDepletion t_FmPortBufPoolDepletion; ++typedef e_FmDmaSwapOption e_FmPortDmaSwapOption; ++typedef e_FmDmaCacheOption e_FmPortDmaCacheOption; ++ ++#define FM_CONTEXTA_GET_OVVERIDE FM_CONTEXTA_GET_OVERRIDE ++#define FM_CONTEXTA_SET_OVVERIDE FM_CONTEXTA_SET_OVERRIDE ++ ++#define e_FM_EX_BMI_PIPELINE_ECC e_FM_EX_BMI_STORAGE_PROFILE_ECC ++#define e_FM_PORT_DMA_NO_SWP e_FM_DMA_NO_SWP ++#define e_FM_PORT_DMA_SWP_PPC_LE e_FM_DMA_SWP_PPC_LE ++#define e_FM_PORT_DMA_SWP_BE e_FM_DMA_SWP_BE ++#define e_FM_PORT_DMA_NO_STASH e_FM_DMA_NO_STASH ++#define e_FM_PORT_DMA_STASH e_FM_DMA_STASH ++#endif /* NCSW_BACKWARD_COMPATIBLE_API */ ++ ++ ++#endif /* __FM_EXT */ +diff --git a/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_mac_ext.h b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_mac_ext.h +new file mode 100644 +index 0000000..614622e +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_mac_ext.h +@@ -0,0 +1,819 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_mac_ext.h ++ ++ @Description FM MAC ... ++*//***************************************************************************/ ++#ifndef __FM_MAC_EXT_H ++#define __FM_MAC_EXT_H ++ ++#include "std_ext.h" ++#include "enet_ext.h" ++ ++ ++/**************************************************************************//** ++ ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_mac_grp FM MAC ++ ++ @Description FM MAC API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++#define FM_MAC_NO_PFC 0xff ++ ++ ++/**************************************************************************//** ++ @Description FM MAC Exceptions ++*//***************************************************************************/ ++typedef enum e_FmMacExceptions { ++ e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO = 0 /**< 10GEC MDIO scan event interrupt */ ++ ,e_FM_MAC_EX_10G_MDIO_CMD_CMPL /**< 10GEC MDIO command completion interrupt */ ++ ,e_FM_MAC_EX_10G_REM_FAULT /**< 10GEC, mEMAC Remote fault interrupt */ ++ ,e_FM_MAC_EX_10G_LOC_FAULT /**< 10GEC, mEMAC Local fault interrupt */ ++ ,e_FM_MAC_EX_10G_1TX_ECC_ER /**< 10GEC, mEMAC Transmit frame ECC error interrupt */ ++ ,e_FM_MAC_EX_10G_TX_FIFO_UNFL /**< 10GEC, mEMAC Transmit FIFO underflow interrupt */ ++ ,e_FM_MAC_EX_10G_TX_FIFO_OVFL /**< 10GEC, mEMAC Transmit FIFO overflow interrupt */ ++ ,e_FM_MAC_EX_10G_TX_ER /**< 10GEC Transmit frame error interrupt */ ++ ,e_FM_MAC_EX_10G_RX_FIFO_OVFL /**< 10GEC, mEMAC Receive FIFO overflow interrupt */ ++ ,e_FM_MAC_EX_10G_RX_ECC_ER /**< 10GEC, mEMAC Receive frame ECC error interrupt */ ++ ,e_FM_MAC_EX_10G_RX_JAB_FRM /**< 10GEC Receive jabber frame interrupt */ ++ ,e_FM_MAC_EX_10G_RX_OVRSZ_FRM /**< 10GEC Receive oversized frame interrupt */ ++ ,e_FM_MAC_EX_10G_RX_RUNT_FRM /**< 10GEC Receive runt frame interrupt */ ++ ,e_FM_MAC_EX_10G_RX_FRAG_FRM /**< 10GEC Receive fragment frame interrupt */ ++ ,e_FM_MAC_EX_10G_RX_LEN_ER /**< 10GEC Receive payload length error interrupt */ ++ ,e_FM_MAC_EX_10G_RX_CRC_ER /**< 10GEC Receive CRC error interrupt */ ++ ,e_FM_MAC_EX_10G_RX_ALIGN_ER /**< 10GEC Receive alignment error interrupt */ ++ ,e_FM_MAC_EX_1G_BAB_RX /**< dTSEC Babbling receive error */ ++ ,e_FM_MAC_EX_1G_RX_CTL /**< dTSEC Receive control (pause frame) interrupt */ ++ ,e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET /**< dTSEC Graceful transmit stop complete */ ++ ,e_FM_MAC_EX_1G_BAB_TX /**< dTSEC Babbling transmit error */ ++ ,e_FM_MAC_EX_1G_TX_CTL /**< dTSEC Transmit control (pause frame) interrupt */ ++ ,e_FM_MAC_EX_1G_TX_ERR /**< dTSEC Transmit error */ ++ ,e_FM_MAC_EX_1G_LATE_COL /**< dTSEC Late collision */ ++ ,e_FM_MAC_EX_1G_COL_RET_LMT /**< dTSEC Collision retry limit */ ++ ,e_FM_MAC_EX_1G_TX_FIFO_UNDRN /**< dTSEC Transmit FIFO underrun */ ++ ,e_FM_MAC_EX_1G_MAG_PCKT /**< dTSEC Magic Packet detection */ ++ ,e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET /**< dTSEC MII management read completion */ ++ ,e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET /**< dTSEC MII management write completion */ ++ ,e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET /**< dTSEC Graceful receive stop complete */ ++ ,e_FM_MAC_EX_1G_TX_DATA_ERR /**< dTSEC Internal data error on transmit */ ++ ,e_FM_MAC_EX_1G_RX_DATA_ERR /**< dTSEC Internal data error on receive */ ++ ,e_FM_MAC_EX_1G_1588_TS_RX_ERR /**< dTSEC Time-Stamp Receive Error */ ++ ,e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL /**< dTSEC MIB counter overflow */ ++} e_FmMacExceptions; ++ ++/**************************************************************************//** ++ @Description TM MAC statistics level ++*//***************************************************************************/ ++typedef enum e_FmMacStatisticsLevel { ++ e_FM_MAC_NONE_STATISTICS = 0, /**< No statistics */ ++ e_FM_MAC_PARTIAL_STATISTICS, /**< Only error counters are available; Optimized for performance */ ++ e_FM_MAC_FULL_STATISTICS /**< All counters available; Not optimized for performance */ ++} e_FmMacStatisticsLevel; ++ ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Priority Flow Control Parameters ++*//***************************************************************************/ ++typedef struct t_FmMacPfcParams { ++ bool pfcEnable; /**< Enable/Disable PFC */ ++ ++ uint16_t pauseQuanta[FM_MAX_NUM_OF_PFC_PRIORITIES]; /**< Pause Quanta per priority to be sent in a pause frame. Each quanta represents a 512 bit-times*/ ++ ++ uint16_t pauseThresholdQuanta[FM_MAX_NUM_OF_PFC_PRIORITIES];/**< Pause threshold per priority, when timer passes this threshold time a PFC frames is sent again if the port is still congested or BM pool in depletion*/ ++ ++ ++} t_FmMacPfcParams; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Function t_FmMacExceptionCallback ++ ++ @Description Fm Mac Exception Callback from FM MAC to the user ++ ++ @Param[in] h_App - Handle to the upper layer handler ++ ++ @Param[in] exceptions - The exception that occurred ++ ++ @Return void. ++*//***************************************************************************/ ++typedef void (t_FmMacExceptionCallback)(t_Handle h_App, e_FmMacExceptions exceptions); ++ ++ ++/**************************************************************************//** ++ @Description TM MAC statistics rfc3635 ++*//***************************************************************************/ ++typedef struct t_FmMacStatistics { ++/* RMON */ ++ uint64_t eStatPkts64; /**< r-10G tr-DT 64 byte frame counter */ ++ uint64_t eStatPkts65to127; /**< r-10G 65 to 127 byte frame counter */ ++ uint64_t eStatPkts128to255; /**< r-10G 128 to 255 byte frame counter */ ++ uint64_t eStatPkts256to511; /**< r-10G 256 to 511 byte frame counter */ ++ uint64_t eStatPkts512to1023; /**< r-10G 512 to 1023 byte frame counter */ ++ uint64_t eStatPkts1024to1518; /**< r-10G 1024 to 1518 byte frame counter */ ++ uint64_t eStatPkts1519to1522; /**< r-10G 1519 to 1522 byte good frame count */ ++/* */ ++ uint64_t eStatFragments; /**< Total number of packets that were less than 64 octets long with a wrong CRC.*/ ++ uint64_t eStatJabbers; /**< Total number of packets longer than valid maximum length octets */ ++ uint64_t eStatsDropEvents; /**< number of dropped packets due to internal errors of the MAC Client (during recieve). */ ++ uint64_t eStatCRCAlignErrors; /**< Incremented when frames of correct length but with CRC error are received.*/ ++ uint64_t eStatUndersizePkts; /**< Incremented for frames under 64 bytes with a valid FCS and otherwise well formed; ++ This count does not include range length errors */ ++ uint64_t eStatOversizePkts; /**< Incremented for frames which exceed 1518 (non VLAN) or 1522 (VLAN) and contains ++ a valid FCS and otherwise well formed */ ++/* Pause */ ++ uint64_t teStatPause; /**< Pause MAC Control received */ ++ uint64_t reStatPause; /**< Pause MAC Control sent */ ++/* MIB II */ ++ uint64_t ifInOctets; /**< Total number of byte received. */ ++ uint64_t ifInPkts; /**< Total number of packets received.*/ ++ uint64_t ifInUcastPkts; /**< Total number of unicast frame received; ++ NOTE: this counter is not supported on dTSEC MAC */ ++ uint64_t ifInMcastPkts; /**< Total number of multicast frame received*/ ++ uint64_t ifInBcastPkts; /**< Total number of broadcast frame received */ ++ uint64_t ifInDiscards; /**< Frames received, but discarded due to problems within the MAC RX. */ ++ uint64_t ifInErrors; /**< Number of frames received with error: ++ - FIFO Overflow Error ++ - CRC Error ++ - Frame Too Long Error ++ - Alignment Error ++ - The dedicated Error Code (0xfe, not a code error) was received */ ++ uint64_t ifOutOctets; /**< Total number of byte sent. */ ++ uint64_t ifOutPkts; /**< Total number of packets sent .*/ ++ uint64_t ifOutUcastPkts; /**< Total number of unicast frame sent; ++ NOTE: this counter is not supported on dTSEC MAC */ ++ uint64_t ifOutMcastPkts; /**< Total number of multicast frame sent */ ++ uint64_t ifOutBcastPkts; /**< Total number of multicast frame sent */ ++ uint64_t ifOutDiscards; /**< Frames received, but discarded due to problems within the MAC TX N/A!.*/ ++ uint64_t ifOutErrors; /**< Number of frames transmitted with error: ++ - FIFO Overflow Error ++ - FIFO Underflow Error ++ - Other */ ++} t_FmMacStatistics; ++ ++ ++/**************************************************************************//** ++ @Group FM_mac_init_grp FM MAC Initialization Unit ++ ++ @Description FM MAC Initialization Unit ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description FM MAC config input ++*//***************************************************************************/ ++typedef struct t_FmMacParams { ++ uintptr_t baseAddr; /**< Base of memory mapped FM MAC registers */ ++ t_EnetAddr addr; /**< MAC address of device; First octet is sent first */ ++ uint8_t macId; /**< MAC ID <10G-MAC 0> */ ++ e_EnetMode enetMode; /**< Ethernet operation mode (MAC-PHY interface and speed); ++ Note that the speed should indicate the maximum rate that ++ this MAC should support rather than the actuall speed; ++ i.e. user should use the FM_MAC_AdjustLink() routine to ++ provide accurate speed; ++ In addition, in mEMAC, in case where user is using the higher MACs ++ (i.e. the MACs that should support 10G), user should pass here ++ speed=10000 even if the interface is not allowing that (e.g. SGMII). */ ++ t_Handle h_Fm; /**< A handle to the FM object this port related to */ ++ int mdioIrq; /**< MDIO exceptions interrupt source - not valid for all ++ MACs; MUST be set to 'NO_IRQ' for MACs that don't have ++ mdio-irq, or for polling */ ++ t_FmMacExceptionCallback *f_Event; /**< MDIO Events Callback Routine */ ++ t_FmMacExceptionCallback *f_Exception; /**< Exception Callback Routine */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks */ ++} t_FmMacParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_MAC_Config ++ ++ @Description Creates descriptor for the FM MAC module. ++ ++ The routine returns a handle (descriptor) to the FM MAC object. ++ This descriptor must be passed as first parameter to all other ++ FM MAC function calls. ++ ++ No actual initialization or configuration of FM MAC hardware is ++ done by this routine. ++ ++ @Param[in] p_FmMacParam - Pointer to data structure of parameters ++ ++ @Retval Handle to FM MAC object, or NULL for Failure. ++*//***************************************************************************/ ++t_Handle FM_MAC_Config(t_FmMacParams *p_FmMacParam); ++ ++/**************************************************************************//** ++ @Function FM_MAC_Init ++ ++ @Description Initializes the FM MAC module ++ ++ @Param[in] h_FmMac - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MAC_Init(t_Handle h_FmMac); ++ ++/**************************************************************************//** ++ @Function FM_Free ++ ++ @Description Frees all resources that were assigned to FM MAC module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmMac - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MAC_Free(t_Handle h_FmMac); ++ ++ ++/**************************************************************************//** ++ @Group FM_mac_advanced_init_grp FM MAC Advanced Configuration Unit ++ ++ @Description Configuration functions used to change default values. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigResetOnInit ++ ++ @Description Tell the driver whether to reset the FM MAC before initialization or ++ not. It changes the default configuration [FALSE]. ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] enable When TRUE, FM will be reset before any initialization. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigResetOnInit(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigLoopback ++ ++ @Description Enable/Disable internal loopback mode ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] enable TRUE to enable or FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigLoopback(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigMaxFrameLength ++ ++ @Description Setup maximum Rx Frame Length (in 1G MAC, effects also Tx) ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] newVal MAX Frame length ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigMaxFrameLength(t_Handle h_FmMac, uint16_t newVal); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigWan ++ ++ @Description ENABLE WAN mode in 10G-MAC ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] enable TRUE to enable or FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigWan(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigPadAndCrc ++ ++ @Description Config PAD and CRC mode ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] enable TRUE to enable or FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++ Not supported on 10G-MAC (i.e. CRC & PAD are added automatically ++ by HW); on mEMAC, this routine supports only PAD (i.e. CRC is ++ added automatically by HW). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigPadAndCrc(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigHalfDuplex ++ ++ @Description Config Half Duplex Mode ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] enable TRUE to enable or FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigHalfDuplex(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigTbiPhyAddr ++ ++ @Description Configures the address of internal TBI PHY. ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] newVal TBI PHY address (1-31). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigTbiPhyAddr(t_Handle h_FmMac, uint8_t newVal); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigLengthCheck ++ ++ @Description Configure the frame length checking. ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] enable TRUE to enable or FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigLengthCheck(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigException ++ ++ @Description Change Exception selection from default ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] ex Type of the desired exceptions ++ @Param[in] enable TRUE to enable the specified exception, FALSE to disable it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigException(t_Handle h_FmMac, e_FmMacExceptions ex, bool enable); ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++t_Error FM_MAC_ConfigSkipFman11Workaround (t_Handle h_FmMac); ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++/** @} */ /* end of FM_mac_advanced_init_grp group */ ++/** @} */ /* end of FM_mac_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_mac_runtime_control_grp FM MAC Runtime Control Unit ++ ++ @Description FM MAC Runtime control unit API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_MAC_Enable ++ ++ @Description Enable the MAC ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] mode Mode of operation (RX, TX, Both) ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_Enable(t_Handle h_FmMac, e_CommMode mode); ++ ++/**************************************************************************//** ++ @Function FM_MAC_Disable ++ ++ @Description DISABLE the MAC ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] mode Define what part to Disable (RX, TX or BOTH) ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_Disable(t_Handle h_FmMac, e_CommMode mode); ++ ++/**************************************************************************//** ++ @Function FM_MAC_Enable1588TimeStamp ++ ++ @Description Enables the TSU operation. ++ ++ @Param[in] h_Fm - Handle to the PTP as returned from the FM_MAC_PtpConfig. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_Enable1588TimeStamp(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_MAC_Disable1588TimeStamp ++ ++ @Description Disables the TSU operation. ++ ++ @Param[in] h_Fm - Handle to the PTP as returned from the FM_MAC_PtpConfig. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_Disable1588TimeStamp(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_MAC_SetTxAutoPauseFrames ++ ++ @Description Enable/Disable transmission of Pause-Frames. ++ The routine changes the default configuration [0xf000]. ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] pauseTime - Pause quanta value used with transmitted pause frames. ++ Each quanta represents a 512 bit-times; Note that '0' ++ as an input here will be used as disabling the ++ transmission of the pause-frames. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_SetTxAutoPauseFrames(t_Handle h_FmMac, ++ uint16_t pauseTime); ++ ++ /**************************************************************************//** ++ @Function FM_MAC_SetTxPauseFrames ++ ++ @Description Enable/Disable transmission of Pause-Frames. ++ The routine changes the default configuration: ++ pause-time - [0xf000] ++ threshold-time - [0] ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] priority - the PFC class of service; use 'FM_MAC_NO_PFC' ++ to indicate legacy pause support (i.e. no PFC). ++ @Param[in] pauseTime - Pause quanta value used with transmitted pause frames. ++ Each quanta represents a 512 bit-times; ++ Note that '0' as an input here will be used as disabling the ++ transmission of the pause-frames. ++ @Param[in] threshTime - Pause Threshold equanta value used by the MAC to retransmit pause frame. ++ if the situation causing a pause frame to be sent didn't finish when the timer ++ reached the threshold quanta, the MAC will retransmit the pause frame. ++ Each quanta represents a 512 bit-times. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++ PFC is supported only on new mEMAC; i.e. in MACs that don't have ++ PFC support (10G-MAC and dTSEC), user should use 'FM_MAC_NO_PFC' ++ in the 'priority' field. ++*//***************************************************************************/ ++t_Error FM_MAC_SetTxPauseFrames(t_Handle h_FmMac, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime); ++ ++/**************************************************************************//** ++ @Function FM_MAC_SetRxIgnorePauseFrames ++ ++ @Description Enable/Disable ignoring of Pause-Frames. ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] en - boolean indicates whether to ignore the incoming pause ++ frames or not. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_SetRxIgnorePauseFrames(t_Handle h_FmMac, bool en); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ResetCounters ++ ++ @Description reset all statistics counters ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ResetCounters(t_Handle h_FmMac); ++ ++/**************************************************************************//** ++ @Function FM_MAC_SetException ++ ++ @Description Enable/Disable a specific Exception ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] ex - Type of the desired exceptions ++ @Param[in] enable - TRUE to enable the specified exception, FALSE to disable it. ++ ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_SetException(t_Handle h_FmMac, e_FmMacExceptions ex, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_SetStatistics ++ ++ @Description Define Statistics level. ++ Where applicable, the routine also enables the MIB counters ++ overflow interrupt in order to keep counters accurate ++ and account for overflows. ++ This routine is relevant only for dTSEC. ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] statisticsLevel - Full statistics level provides all standard counters but may ++ reduce performance. Partial statistics provides only special ++ event counters (errors etc.). If selected, regular counters (such as ++ byte/packet) will be invalid and will return -1. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_SetStatistics(t_Handle h_FmMac, e_FmMacStatisticsLevel statisticsLevel); ++ ++/**************************************************************************//** ++ @Function FM_MAC_GetStatistics ++ ++ @Description get all statistics counters ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] p_Statistics - Structure with statistics ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_GetStatistics(t_Handle h_FmMac, t_FmMacStatistics *p_Statistics); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ModifyMacAddr ++ ++ @Description Replace the main MAC Address ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] p_EnetAddr - Ethernet Mac address ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ModifyMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ ++/**************************************************************************//** ++ @Function FM_MAC_AddHashMacAddr ++ ++ @Description Add an Address to the hash table. This is for filter purpose only. ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] p_EnetAddr - Ethernet Mac address ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). It is a filter only address. ++ @Cautions Some address need to be filterd out in upper FM blocks. ++*//***************************************************************************/ ++t_Error FM_MAC_AddHashMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ ++/**************************************************************************//** ++ @Function FM_MAC_RemoveHashMacAddr ++ ++ @Description Delete an Address to the hash table. This is for filter purpose only. ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] p_EnetAddr - Ethernet Mac address ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_RemoveHashMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ ++/**************************************************************************//** ++ @Function FM_MAC_AddExactMatchMacAddr ++ ++ @Description Add a unicast or multicast mac address for exact-match filtering ++ (8 on dTSEC, 2 for 10G-MAC) ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] p_EnetAddr - MAC Address to ADD ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_AddExactMatchMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ ++/**************************************************************************//** ++ @Function FM_MAC_RemovelExactMatchMacAddr ++ ++ @Description Remove a uni cast or multi cast mac address. ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] p_EnetAddr - MAC Address to remove ++ ++ @Return E_OK on success; Error code otherwise.. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_RemovelExactMatchMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ ++/**************************************************************************//** ++ @Function FM_MAC_SetPromiscuous ++ ++ @Description Enable/Disable MAC Promiscuous mode for ALL mac addresses. ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] enable - TRUE to enable or FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_SetPromiscuous(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_AdjustLink ++ ++ @Description Adjusts the Ethernet link with new speed/duplex setup. ++ This routine is relevant only for dTSEC. ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] speed - Ethernet speed. ++ @Param[in] fullDuplex - TRUE for Full-Duplex mode; ++ FALSE for Half-Duplex mode. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MAC_AdjustLink(t_Handle h_FmMac, e_EnetSpeed speed, bool fullDuplex); ++ ++/**************************************************************************//** ++ @Function FM_MAC_RestartAutoneg ++ ++ @Description Restarts the autonegotiation process. ++ When autonegegotiation process is invoked under traffic the ++ autonegotiation process between the internal TBI PHY and the ++ external PHY does not always complete succesfuly. Calling this ++ function will restart the autonegotiation process that will end ++ succesfuly. It is recomended to call this function after issuing ++ autoneg restart command to the Eth Phy. ++ This routine is relevant only for dTSEC. ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MAC_RestartAutoneg(t_Handle h_FmMac); ++ ++/**************************************************************************//** ++ @Function FM_MAC_GetId ++ ++ @Description Return the MAC ID ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[out] p_MacId - MAC ID of device ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_GetId(t_Handle h_FmMac, uint32_t *p_MacId); ++ ++/**************************************************************************//** ++ @Function FM_MAC_GetVesrion ++ ++ @Description Return Mac HW chip version ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[out] p_MacVresion - Mac version as defined by the chip ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_GetVesrion(t_Handle h_FmMac, uint32_t *p_MacVresion); ++ ++/**************************************************************************//** ++ @Function FM_MAC_MII_WritePhyReg ++ ++ @Description Write data into Phy Register ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] phyAddr - Phy Address on the MII bus ++ @Param[in] reg - Register Number. ++ @Param[in] data - Data to write. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_MII_WritePhyReg(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t data); ++ ++/**************************************************************************//** ++ @Function FM_MAC_MII_ReadPhyReg ++ ++ @Description Read data from Phy Register ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] phyAddr - Phy Address on the MII bus ++ @Param[in] reg - Register Number. ++ @Param[out] p_Data - Data from PHY. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_MII_ReadPhyReg(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data); ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//** ++ @Function FM_MAC_DumpRegs ++ ++ @Description Dump internal registers ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_DumpRegs(t_Handle h_FmMac); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++/** @} */ /* end of FM_mac_runtime_control_grp group */ ++/** @} */ /* end of FM_mac_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++/**************************************************************************//** ++ @Function DtsecRestartTbiAN ++ ++ @Description Restart TBI autonegotiation for a given Dtsec TBI interface. ++ ++ @Param[in] h_Dtsec - A handle to the Dtsec. ++*//***************************************************************************/ ++void DtsecRestartTbiAN(t_Handle h_Dtsec); ++ ++#endif /* __FM_MAC_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_muram_ext.h b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_muram_ext.h +new file mode 100644 +index 0000000..ef62c8e +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_muram_ext.h +@@ -0,0 +1,170 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_muram_ext.h ++ ++ @Description FM MURAM Application Programming Interface. ++*//***************************************************************************/ ++#ifndef __FM_MURAM_EXT ++#define __FM_MURAM_EXT ++ ++#include "error_ext.h" ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_muram_grp FM MURAM ++ ++ @Description FM MURAM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_muram_init_grp FM MURAM Initialization Unit ++ ++ @Description FM MURAM initialization API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_MURAM_ConfigAndInit ++ ++ @Description Creates partition in the MURAM. ++ ++ The routine returns a handle (descriptor) to the MURAM partition. ++ This descriptor must be passed as first parameter to all other ++ FM-MURAM function calls. ++ ++ No actual initialization or configuration of FM_MURAM hardware is ++ done by this routine. ++ ++ @Param[in] baseAddress - Pointer to base of memory mapped FM-MURAM. ++ @Param[in] size - Size of the FM-MURAM partition. ++ ++ @Return Handle to FM-MURAM object, or NULL for Failure. ++*//***************************************************************************/ ++t_Handle FM_MURAM_ConfigAndInit(uintptr_t baseAddress, uint32_t size); ++ ++/**************************************************************************//** ++ @Function FM_MURAM_Free ++ ++ @Description Frees all resources that were assigned to FM-MURAM module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmMuram - FM-MURAM module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MURAM_Free(t_Handle h_FmMuram); ++ ++/** @} */ /* end of FM_muram_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_muram_ctrl_grp FM MURAM Control Unit ++ ++ @Description FM MURAM control API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_MURAM_AllocMem ++ ++ @Description Allocate some memory from FM-MURAM partition. ++ ++ @Param[in] h_FmMuram - FM-MURAM module descriptor. ++ @Param[in] size - size of the memory to be allocated. ++ @Param[in] align - Alignment of the memory. ++ ++ @Return address of the allocated memory; NULL otherwise. ++*//***************************************************************************/ ++void * FM_MURAM_AllocMem(t_Handle h_FmMuram, uint32_t size, uint32_t align); ++ ++/**************************************************************************//** ++ @Function FM_MURAM_AllocMemForce ++ ++ @Description Allocate some specific memory from FM-MURAM partition (according ++ to base). ++ ++ @Param[in] h_FmMuram - FM-MURAM module descriptor. ++ @Param[in] base - the desired base-address to be allocated. ++ @Param[in] size - size of the memory to be allocated. ++ ++ @Return address of the allocated memory; NULL otherwise. ++*//***************************************************************************/ ++void * FM_MURAM_AllocMemForce(t_Handle h_FmMuram, uint64_t base, uint32_t size); ++ ++/**************************************************************************//** ++ @Function FM_MURAM_FreeMem ++ ++ @Description Free an allocated memory from FM-MURAM partition. ++ ++ @Param[in] h_FmMuram - FM-MURAM module descriptor. ++ @Param[in] ptr - A pointer to an allocated memory. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MURAM_FreeMem(t_Handle h_FmMuram, void *ptr); ++ ++/**************************************************************************//** ++ @Function FM_MURAM_GetFreeMemSize ++ ++ @Description Returns the size (in bytes) of free MURAM memory. ++ ++ @Param[in] h_FmMuram - FM-MURAM module descriptor. ++ ++ @Return Free MURAM memory size in bytes. ++*//***************************************************************************/ ++uint64_t FM_MURAM_GetFreeMemSize(t_Handle h_FmMuram); ++ ++/** @} */ /* end of FM_muram_ctrl_grp group */ ++/** @} */ /* end of FM_muram_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++ ++#endif /* __FM_MURAM_EXT */ +diff --git a/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_pcd_ext.h b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_pcd_ext.h +new file mode 100644 +index 0000000..f4dfd63 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_pcd_ext.h +@@ -0,0 +1,3650 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_pcd_ext.h ++ ++ @Description FM PCD API definitions ++*//***************************************************************************/ ++#ifndef __FM_PCD_EXT ++#define __FM_PCD_EXT ++ ++#include "std_ext.h" ++#include "net_ext.h" ++#include "list_ext.h" ++#include "fm_ext.h" ++#include "fsl_fman_kg.h" ++ ++ ++/**************************************************************************//** ++ ++ @Group FM_grp Frame Manager API ++ ++ @Description Frame Manager Application Programming Interface ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_PCD_grp FM PCD ++ ++ @Description Frame Manager PCD (Parse-Classify-Distribute) API. ++ ++ The FM PCD module is responsible for the initialization of all ++ global classifying FM modules. This includes the parser general and ++ common registers, the key generator global and common registers, ++ and the policer global and common registers. ++ In addition, the FM PCD SW module will initialize all required ++ key generator schemes, coarse classification flows, and policer ++ profiles. When a FM module is configured to work with one of these ++ entities, it will register to it using the FM PORT API. The PCD ++ module will manage the PCD resources - i.e. resource management of ++ KeyGen schemes, etc. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection General PCD defines ++*//***************************************************************************/ ++#define FM_PCD_MAX_NUM_OF_PRIVATE_HDRS 2 /**< Number of units/headers saved for user */ ++ ++#define FM_PCD_PRS_NUM_OF_HDRS 16 /**< Number of headers supported by HW parser */ ++#define FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS (32 - FM_PCD_MAX_NUM_OF_PRIVATE_HDRS) ++ /**< Number of distinction units is limited by ++ register size (32 bits) minus reserved bits ++ for private headers. */ ++#define FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS 4 /**< Maximum number of interchangeable headers ++ in a distinction unit */ ++#define FM_PCD_KG_NUM_OF_GENERIC_REGS FM_KG_NUM_OF_GENERIC_REGS /**< Total number of generic KeyGen registers */ ++#define FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY 35 /**< Max number allowed on any configuration; ++ For HW implementation reasons, in most ++ cases less than this will be allowed; The ++ driver will return an initialization error ++ if resource is unavailable. */ ++#define FM_PCD_KG_NUM_OF_EXTRACT_MASKS 4 /**< Total number of masks allowed on KeyGen extractions. */ ++#define FM_PCD_KG_NUM_OF_DEFAULT_GROUPS 16 /**< Number of default value logical groups */ ++ ++#define FM_PCD_PRS_NUM_OF_LABELS 32 /**< Maximum number of SW parser labels */ ++#define FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */ ++#define FM_PCD_PRS_SW_OFFSET 0x00000040 /**< Size of illegal addresses at the beginning ++ of the SW parser area */ ++#if (DPAA_VERSION >= 11) ++#define FM_PCD_PRS_SW_PATCHES_SIZE 0x00000240 /**< Number of bytes saved for patches */ ++#else ++#define FM_PCD_PRS_SW_PATCHES_SIZE 0x00000200 /**< Number of bytes saved for patches */ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#define FM_PCD_PRS_SW_TAIL_SIZE 4 /**< Number of bytes that must be cleared at ++ the end of the SW parser area */ ++#define FM_SW_PRS_MAX_IMAGE_SIZE (FM_PCD_SW_PRS_SIZE-FM_PCD_PRS_SW_OFFSET-FM_PCD_PRS_SW_TAIL_SIZE-FM_PCD_PRS_SW_PATCHES_SIZE) ++ /**< Maximum size of SW parser code */ ++ ++#define FM_PCD_MAX_MANIP_INSRT_TEMPLATE_SIZE 128 /**< Maximum size of insertion template for ++ insert manipulation */ ++ ++#if (DPAA_VERSION >= 11) ++#define FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES 64 /**< Maximum possible entries for frame replicator group */ ++#endif /* (DPAA_VERSION >= 11) */ ++/* @} */ ++ ++ ++/**************************************************************************//** ++ @Group FM_PCD_init_grp FM PCD Initialization Unit ++ ++ @Description Frame Manager PCD Initialization Unit API ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description PCD counters ++*//***************************************************************************/ ++typedef enum e_FmPcdCounters { ++ e_FM_PCD_KG_COUNTERS_TOTAL, /**< KeyGen counter */ ++ e_FM_PCD_PLCR_COUNTERS_RED, /**< Policer counter - counts the total number of RED packets that exit the Policer. */ ++ e_FM_PCD_PLCR_COUNTERS_YELLOW, /**< Policer counter - counts the total number of YELLOW packets that exit the Policer. */ ++ e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED, /**< Policer counter - counts the number of packets that changed color to RED by the Policer; ++ This is a subset of e_FM_PCD_PLCR_COUNTERS_RED packet count, indicating active color changes. */ ++ e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW, /**< Policer counter - counts the number of packets that changed color to YELLOW by the Policer; ++ This is a subset of e_FM_PCD_PLCR_COUNTERS_YELLOW packet count, indicating active color changes. */ ++ e_FM_PCD_PLCR_COUNTERS_TOTAL, /**< Policer counter - counts the total number of packets passed in the Policer. */ ++ e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH, /**< Policer counter - counts the number of packets with length mismatch. */ ++ e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH, /**< Parser counter - counts the number of times the parser block is dispatched. */ ++ e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times L2 parse result is returned (including errors). */ ++ e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times L3 parse result is returned (including errors). */ ++ e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times L4 parse result is returned (including errors). */ ++ e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times SHIM parse result is returned (including errors). */ ++ e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times L2 parse result is returned with errors. */ ++ e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times L3 parse result is returned with errors. */ ++ e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times L4 parse result is returned with errors. */ ++ e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times SHIM parse result is returned with errors. */ ++ e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES, /**< Parser counter - counts the number of cycles spent executing soft parser instruction (including stall cycles). */ ++ e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES, /**< Parser counter - counts the number of cycles stalled waiting for parser internal memory reads while executing soft parser instruction. */ ++ e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES, /**< Parser counter - counts the number of cycles spent executing hard parser (including stall cycles). */ ++ e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES, /**< MURAM counter - counts the number of cycles while performing FMan Memory read. */ ++ e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES, /**< MURAM counter - counts the number of cycles stalled while performing FMan Memory read. */ ++ e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES, /**< MURAM counter - counts the number of cycles while performing FMan Memory write. */ ++ e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES, /**< MURAM counter - counts the number of cycles stalled while performing FMan Memory write. */ ++ e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES /**< FPM counter - counts the number of cycles stalled while performing a FPM Command. */ ++} e_FmPcdCounters; ++ ++/**************************************************************************//** ++ @Description PCD interrupts ++*//***************************************************************************/ ++typedef enum e_FmPcdExceptions { ++ e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC, /**< KeyGen double-bit ECC error is detected on internal memory read access. */ ++ e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW, /**< KeyGen scheme configuration error indicating a key size larger than 56 bytes. */ ++ e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC, /**< Policer double-bit ECC error has been detected on PRAM read access. */ ++ e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR, /**< Policer access to a non-initialized profile has been detected. */ ++ e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE, /**< Policer RAM self-initialization complete */ ++ e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE, /**< Policer atomic action complete */ ++ e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC, /**< Parser double-bit ECC error */ ++ e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC /**< Parser single-bit ECC error */ ++} e_FmPcdExceptions; ++ ++ ++/**************************************************************************//** ++ @Description Exceptions user callback routine, will be called upon an ++ exception passing the exception identification. ++ ++ @Param[in] h_App - User's application descriptor. ++ @Param[in] exception - The exception. ++ *//***************************************************************************/ ++typedef void (t_FmPcdExceptionCallback) (t_Handle h_App, e_FmPcdExceptions exception); ++ ++/**************************************************************************//** ++ @Description Exceptions user callback routine, will be called upon an exception ++ passing the exception identification. ++ ++ @Param[in] h_App - User's application descriptor. ++ @Param[in] exception - The exception. ++ @Param[in] index - id of the relevant source (may be scheme or profile id). ++ *//***************************************************************************/ ++typedef void (t_FmPcdIdExceptionCallback) ( t_Handle h_App, ++ e_FmPcdExceptions exception, ++ uint16_t index); ++ ++/**************************************************************************//** ++ @Description A callback for enqueuing frame onto a QM queue. ++ ++ @Param[in] h_QmArg - Application's handle passed to QM module on enqueue. ++ @Param[in] p_Fd - Frame descriptor for the frame. ++ ++ @Return E_OK on success; Error code otherwise. ++ *//***************************************************************************/ ++typedef t_Error (t_FmPcdQmEnqueueCallback) (t_Handle h_QmArg, void *p_Fd); ++ ++/**************************************************************************//** ++ @Description Host-Command parameters structure. ++ ++ When using Host command for PCD functionalities, a dedicated port ++ must be used. If this routine is called for a PCD in a single partition ++ environment, or it is the Master partition in a Multi-partition ++ environment, The port will be initialized by the PCD driver ++ initialization routine. ++ *//***************************************************************************/ ++typedef struct t_FmPcdHcParams { ++ uintptr_t portBaseAddr; /**< Virtual Address of Host-Command Port memory mapped registers.*/ ++ uint8_t portId; /**< Port Id (0-6 relative to Host-Command/Offline-Parsing ports); ++ NOTE: When configuring Host Command port for ++ FMANv3 devices (DPAA_VERSION 11 and higher), ++ portId=0 MUST be used. */ ++ uint16_t liodnBase; /**< LIODN base for this port, to be used together with LIODN offset ++ (irrelevant for P4080 revision 1.0) */ ++ uint32_t errFqid; /**< Host-Command Port error queue Id. */ ++ uint32_t confFqid; /**< Host-Command Port confirmation queue Id. */ ++ uint32_t qmChannel; /**< QM channel dedicated to this Host-Command port; ++ will be used by the FM for dequeue. */ ++ t_FmPcdQmEnqueueCallback *f_QmEnqueue; /**< Callback routine for enqueuing a frame to the QM */ ++ t_Handle h_QmArg; /**< Application's handle passed to QM module on enqueue */ ++} t_FmPcdHcParams; ++ ++/**************************************************************************//** ++ @Description The main structure for PCD initialization ++ *//***************************************************************************/ ++typedef struct t_FmPcdParams { ++ bool prsSupport; /**< TRUE if Parser will be used for any of the FM ports. */ ++ bool ccSupport; /**< TRUE if Coarse Classification will be used for any ++ of the FM ports. */ ++ bool kgSupport; /**< TRUE if KeyGen will be used for any of the FM ports. */ ++ bool plcrSupport; /**< TRUE if Policer will be used for any of the FM ports. */ ++ t_Handle h_Fm; /**< A handle to the FM module. */ ++ uint8_t numOfSchemes; /**< Number of schemes dedicated to this partition. ++ this parameter is relevant if 'kgSupport'=TRUE. */ ++ bool useHostCommand; /**< Optional for single partition, Mandatory for Multi partition */ ++ t_FmPcdHcParams hc; /**< Host Command parameters, relevant only if 'useHostCommand'=TRUE; ++ Relevant when FM not runs in "guest-mode". */ ++ ++ t_FmPcdExceptionCallback *f_Exception; /**< Callback routine for general PCD exceptions; ++ Relevant when FM not runs in "guest-mode". */ ++ t_FmPcdIdExceptionCallback *f_ExceptionId; /**< Callback routine for specific KeyGen scheme or ++ Policer profile exceptions; ++ Relevant when FM not runs in "guest-mode". */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks; ++ Relevant when FM not runs in "guest-mode". */ ++ uint8_t partPlcrProfilesBase; /**< The first policer-profile-id dedicated to this partition. ++ this parameter is relevant if 'plcrSupport'=TRUE. ++ NOTE: this parameter relevant only when working with multiple partitions. */ ++ uint16_t partNumOfPlcrProfiles; /**< Number of policer-profiles dedicated to this partition. ++ this parameter is relevant if 'plcrSupport'=TRUE. ++ NOTE: this parameter relevant only when working with multiple partitions. */ ++} t_FmPcdParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_PCD_Config ++ ++ @Description Basic configuration of the PCD module. ++ Creates descriptor for the FM PCD module. ++ ++ @Param[in] p_FmPcdParams A structure of parameters for the initialization of PCD. ++ ++ @Return A handle to the initialized module. ++*//***************************************************************************/ ++t_Handle FM_PCD_Config(t_FmPcdParams *p_FmPcdParams); ++ ++t_Handle FM_PCD_GetHcDevH(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_Init ++ ++ @Description Initialization of the PCD module. ++ ++ @Param[in] h_FmPcd - FM PCD module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PCD_Init(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_Free ++ ++ @Description Frees all resources that were assigned to FM module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmPcd - FM PCD module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PCD_Free(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Group FM_PCD_advanced_cfg_grp FM PCD Advanced Configuration Unit ++ ++ @Description Frame Manager PCD Advanced Configuration API. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_PCD_ConfigException ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default selection of exceptions enabling. ++ [4]. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_ConfigException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ConfigHcFramesDataMemory ++ ++ @Description Configures memory-partition-id for FMan-Controller Host-Command ++ frames. Calling this routine changes the internal driver data ++ base from its default configuration [0]. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] memId Memory partition ID. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions This routine may be called only if 'useHostCommand' was TRUE ++ when FM_PCD_Config() routine was called. ++*//***************************************************************************/ ++t_Error FM_PCD_ConfigHcFramesDataMemory(t_Handle h_FmPcd, uint8_t memId); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ConfigPlcrNumOfSharedProfiles ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default selection of exceptions enablement. ++ [4]. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] numOfSharedPlcrProfiles Number of profiles to ++ be shared between ports on this partition ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PCD_ConfigPlcrNumOfSharedProfiles(t_Handle h_FmPcd, uint16_t numOfSharedPlcrProfiles); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ConfigPlcrAutoRefreshMode ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default selection of exceptions enablement. ++ By default auto-refresh is [disabled]. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] enable TRUE to enable, FALSE to disable ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_ConfigPlcrAutoRefreshMode(t_Handle h_FmPcd, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ConfigPrsMaxCycleLimit ++ ++ @Description Calling this routine changes the internal data structure for ++ the maximum parsing time from its default value ++ [0]. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] value 0 to disable the mechanism, or new ++ maximum parsing time. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_ConfigPrsMaxCycleLimit(t_Handle h_FmPcd,uint16_t value); ++ ++/** @} */ /* end of FM_PCD_advanced_cfg_grp group */ ++/** @} */ /* end of FM_PCD_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_PCD_Runtime_grp FM PCD Runtime Unit ++ ++ @Description Frame Manager PCD Runtime Unit API ++ ++ The runtime control allows creation of PCD infrastructure modules ++ such as Network Environment Characteristics, Classification Plan ++ Groups and Coarse Classification Trees. ++ It also allows on-the-fly initialization, modification and removal ++ of PCD modules such as KeyGen schemes, coarse classification nodes ++ and Policer profiles. ++ ++ In order to explain the programming model of the PCD driver interface ++ a few terms should be explained, and will be used below. ++ - Distinction Header - One of the 16 protocols supported by the FM parser, ++ or one of the SHIM headers (1 or 2). May be a header with a special ++ option (see below). ++ - Interchangeable Headers Group - This is a group of Headers recognized ++ by either one of them. For example, if in a specific context the user ++ chooses to treat IPv4 and IPV6 in the same way, they may create an ++ interchangeable Headers Unit consisting of these 2 headers. ++ - A Distinction Unit - a Distinction Header or an Interchangeable Headers ++ Group. ++ - Header with special option - applies to Ethernet, MPLS, VLAN, IPv4 and ++ IPv6, includes multicast, broadcast and other protocol specific options. ++ In terms of hardware it relates to the options available in the classification ++ plan. ++ - Network Environment Characteristics - a set of Distinction Units that define ++ the total recognizable header selection for a certain environment. This is ++ NOT the list of all headers that will ever appear in a flow, but rather ++ everything that needs distinction in a flow, where distinction is made by KeyGen ++ schemes and coarse classification action descriptors. ++ ++ The PCD runtime modules initialization is done in stages. The first stage after ++ initializing the PCD module itself is to establish a Network Flows Environment ++ Definition. The application may choose to establish one or more such environments. ++ Later, when needed, the application will have to state, for some of its modules, ++ to which single environment it belongs. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description A structure for SW parser labels ++ *//***************************************************************************/ ++typedef struct t_FmPcdPrsLabelParams { ++ uint32_t instructionOffset; /**< SW parser label instruction offset (2 bytes ++ resolution), relative to Parser RAM. */ ++ e_NetHeaderType hdr; /**< The existence of this header will invoke ++ the SW parser code. */ ++ uint8_t indexPerHdr; /**< Normally 0, if more than one SW parser ++ attachments for the same header, use this ++ index to distinguish between them. */ ++} t_FmPcdPrsLabelParams; ++ ++/**************************************************************************//** ++ @Description A structure for SW parser ++ *//***************************************************************************/ ++typedef struct t_FmPcdPrsSwParams { ++ bool override; /**< FALSE to invoke a check that nothing else ++ was loaded to this address, including ++ internal patches. ++ TRUE to override any existing code.*/ ++ uint32_t size; /**< SW parser code size */ ++ uint16_t base; /**< SW parser base (in instruction counts! ++ must be larger than 0x20)*/ ++ uint8_t *p_Code; /**< SW parser code */ ++ uint32_t swPrsDataParams[FM_PCD_PRS_NUM_OF_HDRS]; ++ /**< SW parser data (parameters) */ ++ uint8_t numOfLabels; /**< Number of labels for SW parser. */ ++ t_FmPcdPrsLabelParams labelsTable[FM_PCD_PRS_NUM_OF_LABELS]; ++ /**< SW parser labels table, containing ++ numOfLabels entries */ ++} t_FmPcdPrsSwParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_PCD_Enable ++ ++ @Description This routine should be called after PCD is initialized for enabling all ++ PCD engines according to their existing configuration. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init() and when PCD is disabled. ++*//***************************************************************************/ ++t_Error FM_PCD_Enable(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_Disable ++ ++ @Description This routine may be called when PCD is enabled in order to ++ disable all PCD engines. It may be called ++ only when none of the ports in the system are using the PCD. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init() and when PCD is enabled. ++*//***************************************************************************/ ++t_Error FM_PCD_Disable(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_GetCounter ++ ++ @Description Reads one of the FM PCD counters. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] counter The requested counter. ++ ++ @Return Counter's current value. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ Note that it is user's responsibility to call this routine only ++ for enabled counters, and there will be no indication if a ++ disabled counter is accessed. ++*//***************************************************************************/ ++uint32_t FM_PCD_GetCounter(t_Handle h_FmPcd, e_FmPcdCounters counter); ++ ++/**************************************************************************//** ++@Function FM_PCD_PrsLoadSw ++ ++@Description This routine may be called in order to load software parsing code. ++ ++ ++@Param[in] h_FmPcd FM PCD module descriptor. ++@Param[in] p_SwPrs A pointer to a structure of software ++ parser parameters, including the software ++ parser image. ++ ++@Return E_OK on success; Error code otherwise. ++ ++@Cautions Allowed only following FM_PCD_Init() and when PCD is disabled. ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_PrsLoadSw(t_Handle h_FmPcd, t_FmPcdPrsSwParams *p_SwPrs); ++ ++/**************************************************************************//** ++@Function FM_PCD_SetAdvancedOffloadSupport ++ ++@Description This routine must be called in order to support the following features: ++ IP-fragmentation, IP-reassembly, IPsec, Header-manipulation, frame-replicator. ++ ++@Param[in] h_FmPcd FM PCD module descriptor. ++ ++@Return E_OK on success; Error code otherwise. ++ ++@Cautions Allowed only following FM_PCD_Init() and when PCD is disabled. ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_SetAdvancedOffloadSupport(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSetDfltValue ++ ++ @Description Calling this routine sets a global default value to be used ++ by the KeyGen when parser does not recognize a required ++ field/header. ++ By default default values are 0. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] valueId 0,1 - one of 2 global default values. ++ @Param[in] value The requested default value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init() and when PCD is disabled. ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_KgSetDfltValue(t_Handle h_FmPcd, uint8_t valueId, uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSetAdditionalDataAfterParsing ++ ++ @Description Calling this routine allows the KeyGen to access data past ++ the parser finishing point. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] payloadOffset the number of bytes beyond the parser location. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init() and when PCD is disabled. ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_KgSetAdditionalDataAfterParsing(t_Handle h_FmPcd, uint8_t payloadOffset); ++ ++/**************************************************************************//** ++ @Function FM_PCD_SetException ++ ++ @Description Calling this routine enables/disables PCD interrupts. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_SetException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ModifyCounter ++ ++ @Description Sets a value to an enabled counter. Use "0" to reset the counter. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] counter The requested counter. ++ @Param[in] value The requested value to be written into the counter. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_ModifyCounter(t_Handle h_FmPcd, e_FmPcdCounters counter, uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_PCD_SetPlcrStatistics ++ ++ @Description This routine may be used to enable/disable policer statistics ++ counter. By default the statistics is enabled. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor ++ @Param[in] enable TRUE to enable, FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_SetPlcrStatistics(t_Handle h_FmPcd, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PCD_SetPrsStatistics ++ ++ @Description Defines whether to gather parser statistics including all ports. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] enable TRUE to enable, FALSE to disable. ++ ++ @Return None ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++void FM_PCD_SetPrsStatistics(t_Handle h_FmPcd, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HcTxConf ++ ++ @Description This routine should be called to confirm frames that were ++ received on the HC confirmation queue. ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ @Param[in] p_Fd Frame descriptor of the received frame. ++ ++ @Cautions Allowed only following FM_PCD_Init(). Allowed only if 'useHostCommand' ++ option was selected in the initialization. ++*//***************************************************************************/ ++void FM_PCD_HcTxConf(t_Handle h_FmPcd, t_DpaaFD *p_Fd); ++ ++/**************************************************************************//* ++ @Function FM_PCD_ForceIntr ++ ++ @Description Causes an interrupt event on the requested source. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] exception An exception to be forced. ++ ++ @Return E_OK on success; Error code if the exception is not enabled, ++ or is not able to create interrupt. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_ForceIntr (t_Handle h_FmPcd, e_FmPcdExceptions exception); ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//** ++ @Function FM_PCD_DumpRegs ++ ++ @Description Dumps all PCD registers ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ NOTE: this routine may be called only for FM in master mode ++ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers ++ are mapped. ++*//***************************************************************************/ ++t_Error FM_PCD_DumpRegs(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgDumpRegs ++ ++ @Description Dumps all PCD KG registers ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ NOTE: this routine may be called only for FM in master mode ++ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers ++ are mapped. ++*//***************************************************************************/ ++t_Error FM_PCD_KgDumpRegs(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrDumpRegs ++ ++ @Description Dumps all PCD Policer registers ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ NOTE: this routine may be called only for FM in master mode ++ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers ++ are mapped. ++*//***************************************************************************/ ++t_Error FM_PCD_PlcrDumpRegs(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrProfileDumpRegs ++ ++ @Description Dumps all PCD Policer profile registers ++ ++ @Param[in] h_Profile A handle to a Policer profile. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ NOTE: this routine may be called only for FM in master mode ++ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers ++ are mapped. ++*//***************************************************************************/ ++t_Error FM_PCD_PlcrProfileDumpRegs(t_Handle h_Profile); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PrsDumpRegs ++ ++ @Description Dumps all PCD Parser registers ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ NOTE: this routine may be called only for FM in master mode ++ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers ++ are mapped. ++*//***************************************************************************/ ++t_Error FM_PCD_PrsDumpRegs(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HcDumpRegs ++ ++ @Description Dumps HC Port registers ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ NOTE: this routine may be called only for FM in master mode ++ (i.e. 'guestId'=NCSW_MASTER_ID). ++*//***************************************************************************/ ++t_Error FM_PCD_HcDumpRegs(t_Handle h_FmPcd); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ ++ ++/**************************************************************************//** ++ KeyGen FM_PCD_Runtime_build_grp FM PCD Runtime Building Unit ++ ++ @Description Frame Manager PCD Runtime Building API ++ ++ This group contains routines for setting, deleting and modifying ++ PCD resources, for defining the total PCD tree. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection Definitions of coarse classification ++ parameters as required by KeyGen (when coarse classification ++ is the next engine after this scheme). ++*//***************************************************************************/ ++#define FM_PCD_MAX_NUM_OF_CC_TREES 8 ++#define FM_PCD_MAX_NUM_OF_CC_GROUPS 16 ++#define FM_PCD_MAX_NUM_OF_CC_UNITS 4 ++#define FM_PCD_MAX_NUM_OF_KEYS 256 ++#define FM_PCD_MAX_NUM_OF_FLOWS (4*KILOBYTE) ++#define FM_PCD_MAX_SIZE_OF_KEY 56 ++#define FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP 16 ++#define FM_PCD_LAST_KEY_INDEX 0xffff ++#define FM_PCD_MANIP_DSCP_VALUES 64 ++ ++#define FM_PCD_MAX_NUM_OF_CC_NODES 255 /* Obsolete, not used - will be removed in the future */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection A set of definitions to allow protocol ++ special option description. ++*//***************************************************************************/ ++typedef uint32_t protocolOpt_t; /**< A general type to define a protocol option. */ ++ ++typedef protocolOpt_t ethProtocolOpt_t; /**< Ethernet protocol options. */ ++#define ETH_BROADCAST 0x80000000 /**< Ethernet Broadcast. */ ++#define ETH_MULTICAST 0x40000000 /**< Ethernet Multicast. */ ++ ++typedef protocolOpt_t vlanProtocolOpt_t; /**< VLAN protocol options. */ ++#define VLAN_STACKED 0x20000000 /**< Stacked VLAN. */ ++ ++typedef protocolOpt_t mplsProtocolOpt_t; /**< MPLS protocol options. */ ++#define MPLS_STACKED 0x10000000 /**< Stacked MPLS. */ ++ ++typedef protocolOpt_t ipv4ProtocolOpt_t; /**< IPv4 protocol options. */ ++#define IPV4_BROADCAST_1 0x08000000 /**< IPv4 Broadcast. */ ++#define IPV4_MULTICAST_1 0x04000000 /**< IPv4 Multicast. */ ++#define IPV4_UNICAST_2 0x02000000 /**< Tunneled IPv4 - Unicast. */ ++#define IPV4_MULTICAST_BROADCAST_2 0x01000000 /**< Tunneled IPv4 - Broadcast/Multicast. */ ++ ++#define IPV4_FRAG_1 0x00000008 /**< IPV4 reassembly option. ++ IPV4 Reassembly manipulation requires network ++ environment with IPV4 header and IPV4_FRAG_1 option */ ++ ++typedef protocolOpt_t ipv6ProtocolOpt_t; /**< IPv6 protocol options. */ ++#define IPV6_MULTICAST_1 0x00800000 /**< IPv6 Multicast. */ ++#define IPV6_UNICAST_2 0x00400000 /**< Tunneled IPv6 - Unicast. */ ++#define IPV6_MULTICAST_2 0x00200000 /**< Tunneled IPv6 - Multicast. */ ++ ++#define IPV6_FRAG_1 0x00000004 /**< IPV6 reassembly option. ++ IPV6 Reassembly manipulation requires network ++ environment with IPV6 header and IPV6_FRAG_1 option; ++ in case where fragment found, the fragment-extension offset ++ may be found at 'shim2' (in parser-result). */ ++/* @} */ ++ ++#define FM_PCD_MANIP_MAX_HDR_SIZE 256 ++#define FM_PCD_MANIP_DSCP_TO_VLAN_TRANS 64 ++ ++/**************************************************************************//** ++ @Collection A set of definitions to support Header Manipulation selection. ++*//***************************************************************************/ ++typedef uint32_t hdrManipFlags_t; /**< A general type to define a HMan update command flags. */ ++ ++typedef hdrManipFlags_t ipv4HdrManipUpdateFlags_t; /**< IPv4 protocol HMan update command flags. */ ++ ++#define HDR_MANIP_IPV4_TOS 0x80000000 /**< update TOS with the given value ('tos' field ++ of t_FmPcdManipHdrFieldUpdateIpv4) */ ++#define HDR_MANIP_IPV4_ID 0x40000000 /**< update IP ID with the given value ('id' field ++ of t_FmPcdManipHdrFieldUpdateIpv4) */ ++#define HDR_MANIP_IPV4_TTL 0x20000000 /**< Decrement TTL by 1 */ ++#define HDR_MANIP_IPV4_SRC 0x10000000 /**< update IP source address with the given value ++ ('src' field of t_FmPcdManipHdrFieldUpdateIpv4) */ ++#define HDR_MANIP_IPV4_DST 0x08000000 /**< update IP destination address with the given value ++ ('dst' field of t_FmPcdManipHdrFieldUpdateIpv4) */ ++ ++typedef hdrManipFlags_t ipv6HdrManipUpdateFlags_t; /**< IPv6 protocol HMan update command flags. */ ++ ++#define HDR_MANIP_IPV6_TC 0x80000000 /**< update Traffic Class address with the given value ++ ('trafficClass' field of t_FmPcdManipHdrFieldUpdateIpv6) */ ++#define HDR_MANIP_IPV6_HL 0x40000000 /**< Decrement Hop Limit by 1 */ ++#define HDR_MANIP_IPV6_SRC 0x20000000 /**< update IP source address with the given value ++ ('src' field of t_FmPcdManipHdrFieldUpdateIpv6) */ ++#define HDR_MANIP_IPV6_DST 0x10000000 /**< update IP destination address with the given value ++ ('dst' field of t_FmPcdManipHdrFieldUpdateIpv6) */ ++ ++typedef hdrManipFlags_t tcpUdpHdrManipUpdateFlags_t;/**< TCP/UDP protocol HMan update command flags. */ ++ ++#define HDR_MANIP_TCP_UDP_SRC 0x80000000 /**< update TCP/UDP source address with the given value ++ ('src' field of t_FmPcdManipHdrFieldUpdateTcpUdp) */ ++#define HDR_MANIP_TCP_UDP_DST 0x40000000 /**< update TCP/UDP destination address with the given value ++ ('dst' field of t_FmPcdManipHdrFieldUpdateTcpUdp) */ ++#define HDR_MANIP_TCP_UDP_CHECKSUM 0x20000000 /**< update TCP/UDP checksum */ ++ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description A type used for returning the order of the key extraction. ++ each value in this array represents the index of the extraction ++ command as defined by the user in the initialization extraction array. ++ The valid size of this array is the user define number of extractions ++ required (also marked by the second '0' in this array). ++*//***************************************************************************/ ++typedef uint8_t t_FmPcdKgKeyOrder [FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY]; ++ ++/**************************************************************************//** ++ @Description All PCD engines ++*//***************************************************************************/ ++typedef enum e_FmPcdEngine { ++ e_FM_PCD_INVALID = 0, /**< Invalid PCD engine */ ++ e_FM_PCD_DONE, /**< No PCD Engine indicated */ ++ e_FM_PCD_KG, /**< KeyGen */ ++ e_FM_PCD_CC, /**< Coarse classifier */ ++ e_FM_PCD_PLCR, /**< Policer */ ++ e_FM_PCD_PRS, /**< Parser */ ++#if (DPAA_VERSION >= 11) ++ e_FM_PCD_FR, /**< Frame-Replicator */ ++#endif /* (DPAA_VERSION >= 11) */ ++ e_FM_PCD_HASH /**< Hash table */ ++} e_FmPcdEngine; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting extraction by header types ++*//***************************************************************************/ ++typedef enum e_FmPcdExtractByHdrType { ++ e_FM_PCD_EXTRACT_FROM_HDR, /**< Extract bytes from header */ ++ e_FM_PCD_EXTRACT_FROM_FIELD, /**< Extract bytes from header field */ ++ e_FM_PCD_EXTRACT_FULL_FIELD /**< Extract a full field */ ++} e_FmPcdExtractByHdrType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting extraction source ++ (when it is not the header) ++*//***************************************************************************/ ++typedef enum e_FmPcdExtractFrom { ++ e_FM_PCD_EXTRACT_FROM_FRAME_START, /**< KG & CC: Extract from beginning of frame */ ++ e_FM_PCD_EXTRACT_FROM_DFLT_VALUE, /**< KG only: Extract from a default value */ ++ e_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE, /**< KG & CC: Extract from the point where parsing had finished */ ++ e_FM_PCD_EXTRACT_FROM_KEY, /**< CC only: Field where saved KEY */ ++ e_FM_PCD_EXTRACT_FROM_HASH, /**< CC only: Field where saved HASH */ ++ e_FM_PCD_EXTRACT_FROM_PARSE_RESULT, /**< KG only: Extract from the parser result */ ++ e_FM_PCD_EXTRACT_FROM_ENQ_FQID, /**< KG & CC: Extract from enqueue FQID */ ++ e_FM_PCD_EXTRACT_FROM_FLOW_ID /**< CC only: Field where saved Dequeue FQID */ ++} e_FmPcdExtractFrom; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting extraction type ++*//***************************************************************************/ ++typedef enum e_FmPcdExtractType { ++ e_FM_PCD_EXTRACT_BY_HDR, /**< Extract according to header */ ++ e_FM_PCD_EXTRACT_NON_HDR, /**< Extract from data that is not the header */ ++ e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO /**< Extract private info as specified by user */ ++} e_FmPcdExtractType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting default extraction value ++*//***************************************************************************/ ++typedef enum e_FmPcdKgExtractDfltSelect { ++ e_FM_PCD_KG_DFLT_GBL_0, /**< Default selection is KG register 0 */ ++ e_FM_PCD_KG_DFLT_GBL_1, /**< Default selection is KG register 1 */ ++ e_FM_PCD_KG_DFLT_PRIVATE_0, /**< Default selection is a per scheme register 0 */ ++ e_FM_PCD_KG_DFLT_PRIVATE_1, /**< Default selection is a per scheme register 1 */ ++ e_FM_PCD_KG_DFLT_ILLEGAL /**< Illegal selection */ ++} e_FmPcdKgExtractDfltSelect; ++ ++/**************************************************************************//** ++ @Description Enumeration type defining all default groups - each group shares ++ a default value, one of four user-initialized values. ++*//***************************************************************************/ ++typedef enum e_FmPcdKgKnownFieldsDfltTypes { ++ e_FM_PCD_KG_MAC_ADDR, /**< MAC Address */ ++ e_FM_PCD_KG_TCI, /**< TCI field */ ++ e_FM_PCD_KG_ENET_TYPE, /**< ENET Type */ ++ e_FM_PCD_KG_PPP_SESSION_ID, /**< PPP Session id */ ++ e_FM_PCD_KG_PPP_PROTOCOL_ID, /**< PPP Protocol id */ ++ e_FM_PCD_KG_MPLS_LABEL, /**< MPLS label */ ++ e_FM_PCD_KG_IP_ADDR, /**< IP address */ ++ e_FM_PCD_KG_PROTOCOL_TYPE, /**< Protocol type */ ++ e_FM_PCD_KG_IP_TOS_TC, /**< TOS or TC */ ++ e_FM_PCD_KG_IPV6_FLOW_LABEL, /**< IPV6 flow label */ ++ e_FM_PCD_KG_IPSEC_SPI, /**< IPSEC SPI */ ++ e_FM_PCD_KG_L4_PORT, /**< L4 Port */ ++ e_FM_PCD_KG_TCP_FLAG, /**< TCP Flag */ ++ e_FM_PCD_KG_GENERIC_FROM_DATA, /**< grouping implemented by SW, ++ any data extraction that is not the full ++ field described above */ ++ e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V, /**< grouping implemented by SW, ++ any data extraction without validation */ ++ e_FM_PCD_KG_GENERIC_NOT_FROM_DATA /**< grouping implemented by SW, ++ extraction from parser result or ++ direct use of default value */ ++} e_FmPcdKgKnownFieldsDfltTypes; ++ ++/**************************************************************************//** ++ @Description Enumeration type for defining header index for scenarios with ++ multiple (tunneled) headers ++*//***************************************************************************/ ++typedef enum e_FmPcdHdrIndex { ++ e_FM_PCD_HDR_INDEX_NONE = 0, /**< used when multiple headers not used, also ++ to specify regular IP (not tunneled). */ ++ e_FM_PCD_HDR_INDEX_1, /**< may be used for VLAN, MPLS, tunneled IP */ ++ e_FM_PCD_HDR_INDEX_2, /**< may be used for MPLS, tunneled IP */ ++ e_FM_PCD_HDR_INDEX_3, /**< may be used for MPLS */ ++ e_FM_PCD_HDR_INDEX_LAST = 0xFF /**< may be used for VLAN, MPLS */ ++} e_FmPcdHdrIndex; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer profile functional type ++*//***************************************************************************/ ++typedef enum e_FmPcdProfileTypeSelection { ++ e_FM_PCD_PLCR_PORT_PRIVATE, /**< Port dedicated profile */ ++ e_FM_PCD_PLCR_SHARED /**< Shared profile (shared within partition) */ ++} e_FmPcdProfileTypeSelection; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer profile algorithm ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrAlgorithmSelection { ++ e_FM_PCD_PLCR_PASS_THROUGH, /**< Policer pass through */ ++ e_FM_PCD_PLCR_RFC_2698, /**< Policer algorithm RFC 2698 */ ++ e_FM_PCD_PLCR_RFC_4115 /**< Policer algorithm RFC 4115 */ ++} e_FmPcdPlcrAlgorithmSelection; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting a policer profile color mode ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrColorMode { ++ e_FM_PCD_PLCR_COLOR_BLIND, /**< Color blind */ ++ e_FM_PCD_PLCR_COLOR_AWARE /**< Color aware */ ++} e_FmPcdPlcrColorMode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting a policer profile color ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrColor { ++ e_FM_PCD_PLCR_GREEN, /**< Green color code */ ++ e_FM_PCD_PLCR_YELLOW, /**< Yellow color code */ ++ e_FM_PCD_PLCR_RED, /**< Red color code */ ++ e_FM_PCD_PLCR_OVERRIDE /**< Color override code */ ++} e_FmPcdPlcrColor; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer profile packet frame length selector ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrFrameLengthSelect { ++ e_FM_PCD_PLCR_L2_FRM_LEN, /**< L2 frame length */ ++ e_FM_PCD_PLCR_L3_FRM_LEN, /**< L3 frame length */ ++ e_FM_PCD_PLCR_L4_FRM_LEN, /**< L4 frame length */ ++ e_FM_PCD_PLCR_FULL_FRM_LEN /**< Full frame length */ ++} e_FmPcdPlcrFrameLengthSelect; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting roll-back frame ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrRollBackFrameSelect { ++ e_FM_PCD_PLCR_ROLLBACK_L2_FRM_LEN, /**< Roll-back L2 frame length */ ++ e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN /**< Roll-back Full frame length */ ++} e_FmPcdPlcrRollBackFrameSelect; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer profile packet or byte mode ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrRateMode { ++ e_FM_PCD_PLCR_BYTE_MODE, /**< Byte mode */ ++ e_FM_PCD_PLCR_PACKET_MODE /**< Packet mode */ ++} e_FmPcdPlcrRateMode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for defining action of frame ++*//***************************************************************************/ ++typedef enum e_FmPcdDoneAction { ++ e_FM_PCD_ENQ_FRAME = 0, /**< Enqueue frame */ ++ e_FM_PCD_DROP_FRAME /**< Drop frame */ ++} e_FmPcdDoneAction; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer counter ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrProfileCounters { ++ e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER, /**< Green packets counter */ ++ e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER, /**< Yellow packets counter */ ++ e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER, /**< Red packets counter */ ++ e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER, /**< Recolored yellow packets counter */ ++ e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER /**< Recolored red packets counter */ ++} e_FmPcdPlcrProfileCounters; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the PCD action after extraction ++*//***************************************************************************/ ++typedef enum e_FmPcdAction { ++ e_FM_PCD_ACTION_NONE, /**< NONE */ ++ e_FM_PCD_ACTION_EXACT_MATCH, /**< Exact match on the selected extraction */ ++ e_FM_PCD_ACTION_INDEXED_LOOKUP /**< Indexed lookup on the selected extraction */ ++} e_FmPcdAction; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of insert manipulation ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrInsrtType { ++ e_FM_PCD_MANIP_INSRT_GENERIC, /**< Insert according to offset & size */ ++ e_FM_PCD_MANIP_INSRT_BY_HDR, /**< Insert according to protocol */ ++#ifdef FM_CAPWAP_SUPPORT ++ e_FM_PCD_MANIP_INSRT_BY_TEMPLATE /**< Insert template to start of frame */ ++#endif /* FM_CAPWAP_SUPPORT */ ++} e_FmPcdManipHdrInsrtType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of remove manipulation ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrRmvType { ++ e_FM_PCD_MANIP_RMV_GENERIC, /**< Remove according to offset & size */ ++ e_FM_PCD_MANIP_RMV_BY_HDR /**< Remove according to offset & size */ ++} e_FmPcdManipHdrRmvType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific L2 fields removal ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrRmvSpecificL2 { ++ e_FM_PCD_MANIP_HDR_RMV_ETHERNET, /**< Ethernet/802.3 MAC */ ++ e_FM_PCD_MANIP_HDR_RMV_STACKED_QTAGS, /**< stacked QTags */ ++ e_FM_PCD_MANIP_HDR_RMV_ETHERNET_AND_MPLS, /**< MPLS and Ethernet/802.3 MAC header until ++ the header which follows the MPLS header */ ++ e_FM_PCD_MANIP_HDR_RMV_MPLS /**< Remove MPLS header (Unlimited MPLS labels) */ ++} e_FmPcdManipHdrRmvSpecificL2; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific fields updates ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrFieldUpdateType { ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN, /**< VLAN updates */ ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4, /**< IPV4 updates */ ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6, /**< IPV6 updates */ ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP, /**< TCP_UDP updates */ ++} e_FmPcdManipHdrFieldUpdateType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting VLAN updates ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrFieldUpdateVlan { ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI, /**< Replace VPri of outer most VLAN tag. */ ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN /**< DSCP to VLAN priority bits translation */ ++} e_FmPcdManipHdrFieldUpdateVlan; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific L2 fields removal ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrInsrtSpecificL2 { ++ e_FM_PCD_MANIP_HDR_INSRT_MPLS /**< Insert MPLS header (Unlimited MPLS labels) */ ++} e_FmPcdManipHdrInsrtSpecificL2; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of header insertion ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrInsrtByHdrType { ++ e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2 /**< Specific L2 fields insertion */ ++} e_FmPcdManipHdrInsrtByHdrType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific customCommand ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrCustomType { ++ e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE, /**< Replace IPv4/IPv6 */ ++} e_FmPcdManipHdrCustomType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific customCommand ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrCustomIpReplace { ++ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV4_BY_IPV6, /**< Replace IPv4 by IPv6 */ ++ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4 /**< Replace IPv6 by IPv4 */ ++} e_FmPcdManipHdrCustomIpReplace; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of header removal ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrRmvByHdrType { ++ e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2 = 0, /**< Specific L2 fields removal */ ++#ifdef FM_CAPWAP_SUPPORT ++ e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START, /**< Locate from data that is not the header */ ++#endif /* FM_CAPWAP_SUPPORT */ ++} e_FmPcdManipHdrRmvByHdrType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of timeout mode ++*//***************************************************************************/ ++typedef enum e_FmPcdManipReassemTimeOutMode { ++ e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES, /**< Limits the time of the reassembly process ++ from the first fragment to the last */ ++ e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAG /**< Limits the time of receiving the fragment */ ++} e_FmPcdManipReassemTimeOutMode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of WaysNumber mode ++*//***************************************************************************/ ++typedef enum e_FmPcdManipReassemWaysNumber { ++ e_FM_PCD_MANIP_ONE_WAY_HASH = 1, /**< One way hash */ ++ e_FM_PCD_MANIP_TWO_WAYS_HASH, /**< Two ways hash */ ++ e_FM_PCD_MANIP_THREE_WAYS_HASH, /**< Three ways hash */ ++ e_FM_PCD_MANIP_FOUR_WAYS_HASH, /**< Four ways hash */ ++ e_FM_PCD_MANIP_FIVE_WAYS_HASH, /**< Five ways hash */ ++ e_FM_PCD_MANIP_SIX_WAYS_HASH, /**< Six ways hash */ ++ e_FM_PCD_MANIP_SEVEN_WAYS_HASH, /**< Seven ways hash */ ++ e_FM_PCD_MANIP_EIGHT_WAYS_HASH /**< Eight ways hash */ ++} e_FmPcdManipReassemWaysNumber; ++ ++#ifdef FM_CAPWAP_SUPPORT ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of statistics mode ++*//***************************************************************************/ ++typedef enum e_FmPcdStatsType { ++ e_FM_PCD_STATS_PER_FLOWID = 0 /**< Flow ID is used as index for getting statistics */ ++} e_FmPcdStatsType; ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting manipulation type ++*//***************************************************************************/ ++typedef enum e_FmPcdManipType { ++ e_FM_PCD_MANIP_HDR = 0, /**< Header manipulation */ ++ e_FM_PCD_MANIP_REASSEM, /**< Reassembly */ ++ e_FM_PCD_MANIP_FRAG, /**< Fragmentation */ ++ e_FM_PCD_MANIP_SPECIAL_OFFLOAD /**< Special Offloading */ ++} e_FmPcdManipType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of statistics mode ++*//***************************************************************************/ ++typedef enum e_FmPcdCcStatsMode { ++ e_FM_PCD_CC_STATS_MODE_NONE = 0, /**< No statistics support */ ++ e_FM_PCD_CC_STATS_MODE_FRAME, /**< Frame count statistics */ ++ e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME, /**< Byte and frame count statistics */ ++#if (DPAA_VERSION >= 11) ++ e_FM_PCD_CC_STATS_MODE_RMON, /**< Byte and frame length range count statistics; ++ This mode is supported only on B4860 device */ ++#endif /* (DPAA_VERSION >= 11) */ ++} e_FmPcdCcStatsMode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for determining the action in case an IP packet ++ is larger than MTU but its DF (Don't Fragment) bit is set. ++*//***************************************************************************/ ++typedef enum e_FmPcdManipDontFragAction { ++ e_FM_PCD_MANIP_DISCARD_PACKET = 0, /**< Discard packet */ ++ e_FM_PCD_MANIP_ENQ_TO_ERR_Q_OR_DISCARD_PACKET = e_FM_PCD_MANIP_DISCARD_PACKET, ++ /**< Obsolete, cannot enqueue to error queue; ++ In practice, selects to discard packets; ++ Will be removed in the future */ ++ e_FM_PCD_MANIP_FRAGMENT_PACKET, /**< Fragment packet and continue normal processing */ ++ e_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG /**< Continue normal processing without fragmenting the packet */ ++} e_FmPcdManipDontFragAction; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of special offload manipulation ++*//***************************************************************************/ ++typedef enum e_FmPcdManipSpecialOffloadType { ++ e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC /**< IPSec offload manipulation */ ++} e_FmPcdManipSpecialOffloadType; ++ ++ ++/**************************************************************************//** ++ @Description A Union of protocol dependent special options ++*//***************************************************************************/ ++typedef union u_FmPcdHdrProtocolOpt { ++ ethProtocolOpt_t ethOpt; /**< Ethernet options */ ++ vlanProtocolOpt_t vlanOpt; /**< VLAN options */ ++ mplsProtocolOpt_t mplsOpt; /**< MPLS options */ ++ ipv4ProtocolOpt_t ipv4Opt; /**< IPv4 options */ ++ ipv6ProtocolOpt_t ipv6Opt; /**< IPv6 options */ ++} u_FmPcdHdrProtocolOpt; ++ ++/**************************************************************************//** ++ @Description A union holding protocol fields ++ ++ ++ Fields supported as "full fields": ++ HEADER_TYPE_ETH: ++ NET_HEADER_FIELD_ETH_DA ++ NET_HEADER_FIELD_ETH_SA ++ NET_HEADER_FIELD_ETH_TYPE ++ ++ HEADER_TYPE_LLC_SNAP: ++ NET_HEADER_FIELD_LLC_SNAP_TYPE ++ ++ HEADER_TYPE_VLAN: ++ NET_HEADER_FIELD_VLAN_TCI ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_LAST) ++ ++ HEADER_TYPE_MPLS: ++ NET_HEADER_FIELD_MPLS_LABEL_STACK ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_2, ++ e_FM_PCD_HDR_INDEX_LAST) ++ ++ HEADER_TYPE_IPv4: ++ NET_HEADER_FIELD_IPv4_SRC_IP ++ NET_HEADER_FIELD_IPv4_DST_IP ++ NET_HEADER_FIELD_IPv4_PROTO ++ NET_HEADER_FIELD_IPv4_TOS ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_2/e_FM_PCD_HDR_INDEX_LAST) ++ ++ HEADER_TYPE_IPv6: ++ NET_HEADER_FIELD_IPv6_SRC_IP ++ NET_HEADER_FIELD_IPv6_DST_IP ++ NET_HEADER_FIELD_IPv6_NEXT_HDR ++ NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC (must come together!) ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_2/e_FM_PCD_HDR_INDEX_LAST) ++ ++ (Note that starting from DPAA 1-1, NET_HEADER_FIELD_IPv6_NEXT_HDR applies to ++ the last next header indication, meaning the next L4, which may be ++ present at the Ipv6 last extension. On earlier revisions this field ++ applies to the Next-Header field of the main IPv6 header) ++ ++ HEADER_TYPE_IP: ++ NET_HEADER_FIELD_IP_PROTO ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_LAST) ++ NET_HEADER_FIELD_IP_DSCP ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1) ++ HEADER_TYPE_GRE: ++ NET_HEADER_FIELD_GRE_TYPE ++ ++ HEADER_TYPE_MINENCAP ++ NET_HEADER_FIELD_MINENCAP_SRC_IP ++ NET_HEADER_FIELD_MINENCAP_DST_IP ++ NET_HEADER_FIELD_MINENCAP_TYPE ++ ++ HEADER_TYPE_TCP: ++ NET_HEADER_FIELD_TCP_PORT_SRC ++ NET_HEADER_FIELD_TCP_PORT_DST ++ NET_HEADER_FIELD_TCP_FLAGS ++ ++ HEADER_TYPE_UDP: ++ NET_HEADER_FIELD_UDP_PORT_SRC ++ NET_HEADER_FIELD_UDP_PORT_DST ++ ++ ++ HEADER_TYPE_UDP_LITE: - relevant only if FM_CAPWAP_SUPPORT define ++ NET_HEADER_FIELD_UDP_LITE_PORT_SRC ++ NET_HEADER_FIELD_UDP_LITE_PORT_DST ++ ++ HEADER_TYPE_IPSEC_AH: ++ NET_HEADER_FIELD_IPSEC_AH_SPI ++ NET_HEADER_FIELD_IPSEC_AH_NH ++ ++ HEADER_TYPE_IPSEC_ESP: ++ NET_HEADER_FIELD_IPSEC_ESP_SPI ++ ++ HEADER_TYPE_SCTP: ++ NET_HEADER_FIELD_SCTP_PORT_SRC ++ NET_HEADER_FIELD_SCTP_PORT_DST ++ ++ HEADER_TYPE_DCCP: ++ NET_HEADER_FIELD_DCCP_PORT_SRC ++ NET_HEADER_FIELD_DCCP_PORT_DST ++ ++ HEADER_TYPE_PPPoE: ++ NET_HEADER_FIELD_PPPoE_PID ++ NET_HEADER_FIELD_PPPoE_SID ++ ++ ***************************************************************** ++ Fields supported as "from fields": ++ HEADER_TYPE_ETH (with or without validation): ++ NET_HEADER_FIELD_ETH_TYPE ++ ++ HEADER_TYPE_VLAN (with or without validation): ++ NET_HEADER_FIELD_VLAN_TCI ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_LAST) ++ ++ HEADER_TYPE_IPv4 (without validation): ++ NET_HEADER_FIELD_IPv4_PROTO ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_2/e_FM_PCD_HDR_INDEX_LAST) ++ ++ HEADER_TYPE_IPv6 (without validation): ++ NET_HEADER_FIELD_IPv6_NEXT_HDR ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_2/e_FM_PCD_HDR_INDEX_LAST) ++ ++*//***************************************************************************/ ++typedef union t_FmPcdFields { ++ headerFieldEth_t eth; /**< Ethernet */ ++ headerFieldVlan_t vlan; /**< VLAN */ ++ headerFieldLlcSnap_t llcSnap; /**< LLC SNAP */ ++ headerFieldPppoe_t pppoe; /**< PPPoE */ ++ headerFieldMpls_t mpls; /**< MPLS */ ++ headerFieldIp_t ip; /**< IP */ ++ headerFieldIpv4_t ipv4; /**< IPv4 */ ++ headerFieldIpv6_t ipv6; /**< IPv6 */ ++ headerFieldUdp_t udp; /**< UDP */ ++ headerFieldUdpLite_t udpLite; /**< UDP Lite */ ++ headerFieldTcp_t tcp; /**< TCP */ ++ headerFieldSctp_t sctp; /**< SCTP */ ++ headerFieldDccp_t dccp; /**< DCCP */ ++ headerFieldGre_t gre; /**< GRE */ ++ headerFieldMinencap_t minencap; /**< Minimal Encapsulation */ ++ headerFieldIpsecAh_t ipsecAh; /**< IPSec AH */ ++ headerFieldIpsecEsp_t ipsecEsp; /**< IPSec ESP */ ++ headerFieldUdpEncapEsp_t udpEncapEsp; /**< UDP Encapsulation ESP */ ++} t_FmPcdFields; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header extraction for key generation ++*//***************************************************************************/ ++typedef struct t_FmPcdFromHdr { ++ uint8_t size; /**< Size in byte */ ++ uint8_t offset; /**< Byte offset */ ++} t_FmPcdFromHdr; ++ ++/**************************************************************************//** ++ @Description Parameters for defining field extraction for key generation ++*//***************************************************************************/ ++typedef struct t_FmPcdFromField { ++ t_FmPcdFields field; /**< Field selection */ ++ uint8_t size; /**< Size in byte */ ++ uint8_t offset; /**< Byte offset */ ++} t_FmPcdFromField; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a single network environment unit ++ ++ A distinction unit should be defined if it will later be used ++ by one or more PCD engines to distinguish between flows. ++*//***************************************************************************/ ++typedef struct t_FmPcdDistinctionUnit { ++ struct { ++ e_NetHeaderType hdr; /**< One of the headers supported by the FM */ ++ u_FmPcdHdrProtocolOpt opt; /**< Select only one option ! */ ++ } hdrs[FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS]; ++} t_FmPcdDistinctionUnit; ++ ++/**************************************************************************//** ++ @Description Parameters for defining all different distinction units supported ++ by a specific PCD Network Environment Characteristics module. ++ ++ Each unit represent a protocol or a group of protocols that may ++ be used later by the different PCD engines to distinguish ++ between flows. ++*//***************************************************************************/ ++typedef struct t_FmPcdNetEnvParams { ++ uint8_t numOfDistinctionUnits; /**< Number of different units to be identified */ ++ t_FmPcdDistinctionUnit units[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; /**< An array of numOfDistinctionUnits of the ++ different units to be identified */ ++} t_FmPcdNetEnvParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a single extraction action when ++ creating a key ++*//***************************************************************************/ ++typedef struct t_FmPcdExtractEntry { ++ e_FmPcdExtractType type; /**< Extraction type select */ ++ union { ++ struct { ++ e_NetHeaderType hdr; /**< Header selection */ ++ bool ignoreProtocolValidation; ++ /**< Ignore protocol validation */ ++ e_FmPcdHdrIndex hdrIndex; /**< Relevant only for MPLS, VLAN and tunneled ++ IP. Otherwise should be cleared. */ ++ e_FmPcdExtractByHdrType type; /**< Header extraction type select */ ++ union { ++ t_FmPcdFromHdr fromHdr; /**< Extract bytes from header parameters */ ++ t_FmPcdFromField fromField; /**< Extract bytes from field parameters */ ++ t_FmPcdFields fullField; /**< Extract full filed parameters */ ++ } extractByHdrType; ++ } extractByHdr; /**< used when type = e_FM_PCD_KG_EXTRACT_BY_HDR */ ++ struct { ++ e_FmPcdExtractFrom src; /**< Non-header extraction source */ ++ e_FmPcdAction action; /**< Relevant for CC Only */ ++ uint16_t icIndxMask; /**< Relevant only for CC when ++ action = e_FM_PCD_ACTION_INDEXED_LOOKUP; ++ Note that the number of bits that are set within ++ this mask must be log2 of the CC-node 'numOfKeys'. ++ Note that the mask cannot be set on the lower bits. */ ++ uint8_t offset; /**< Byte offset */ ++ uint8_t size; /**< Size in byte */ ++ } extractNonHdr; /**< used when type = e_FM_PCD_KG_EXTRACT_NON_HDR */ ++ }; ++} t_FmPcdExtractEntry; ++ ++/**************************************************************************//** ++ @Description Parameters for defining masks for each extracted field in the key. ++*//***************************************************************************/ ++typedef struct t_FmPcdKgExtractMask { ++ uint8_t extractArrayIndex; /**< Index in the extraction array, as initialized by user */ ++ uint8_t offset; /**< Byte offset */ ++ uint8_t mask; /**< A byte mask (selected bits will be used) */ ++} t_FmPcdKgExtractMask; ++ ++/**************************************************************************//** ++ @Description Parameters for defining default selection per groups of fields ++*//***************************************************************************/ ++typedef struct t_FmPcdKgExtractDflt { ++ e_FmPcdKgKnownFieldsDfltTypes type; /**< Default type select */ ++ e_FmPcdKgExtractDfltSelect dfltSelect; /**< Default register select */ ++} t_FmPcdKgExtractDflt; ++ ++/**************************************************************************//** ++ @Description Parameters for defining key extraction and hashing ++*//***************************************************************************/ ++typedef struct t_FmPcdKgKeyExtractAndHashParams { ++ uint32_t privateDflt0; /**< Scheme default register 0 */ ++ uint32_t privateDflt1; /**< Scheme default register 1 */ ++ uint8_t numOfUsedExtracts; /**< defines the valid size of the following array */ ++ t_FmPcdExtractEntry extractArray [FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY]; /**< An array of extractions definition. */ ++ uint8_t numOfUsedDflts; /**< defines the valid size of the following array */ ++ t_FmPcdKgExtractDflt dflts[FM_PCD_KG_NUM_OF_DEFAULT_GROUPS]; ++ /**< For each extraction used in this scheme, specify the required ++ default register to be used when header is not found. ++ types not specified in this array will get undefined value. */ ++ uint8_t numOfUsedMasks; /**< defines the valid size of the following array */ ++ t_FmPcdKgExtractMask masks[FM_PCD_KG_NUM_OF_EXTRACT_MASKS]; ++ uint8_t hashShift; /**< hash result right shift. Select the 24 bits out of the 64 hash ++ result. 0 means using the 24 LSB's, otherwise use the ++ 24 LSB's after shifting right.*/ ++ uint32_t hashDistributionNumOfFqids; /**< must be > 1 and a power of 2. Represents the range ++ of queues for the key and hash functionality */ ++ uint8_t hashDistributionFqidsShift; /**< selects the FQID bits that will be effected by the hash */ ++ bool symmetricHash; /**< TRUE to generate the same hash for frames with swapped source and ++ destination fields on all layers; If TRUE, driver will check that for ++ all layers, if SRC extraction is selected, DST extraction must also be ++ selected, and vice versa. */ ++} t_FmPcdKgKeyExtractAndHashParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a single FQID mask (extracted OR). ++*//***************************************************************************/ ++typedef struct t_FmPcdKgExtractedOrParams { ++ e_FmPcdExtractType type; /**< Extraction type select */ ++ union { ++ struct { /**< used when type = e_FM_PCD_KG_EXTRACT_BY_HDR */ ++ e_NetHeaderType hdr; ++ e_FmPcdHdrIndex hdrIndex; /**< Relevant only for MPLS, VLAN and tunneled ++ IP. Otherwise should be cleared.*/ ++ bool ignoreProtocolValidation; ++ /**< continue extraction even if protocol is not recognized */ ++ } extractByHdr; /**< Header to extract by */ ++ e_FmPcdExtractFrom src; /**< used when type = e_FM_PCD_KG_EXTRACT_NON_HDR */ ++ }; ++ uint8_t extractionOffset; /**< Offset for extraction (in bytes). */ ++ e_FmPcdKgExtractDfltSelect dfltValue; /**< Select register from which extraction is taken if ++ field not found */ ++ uint8_t mask; /**< Extraction mask (specified bits are used) */ ++ uint8_t bitOffsetInFqid; /**< 0-31, Selects which bits of the 24 FQID bits to effect using ++ the extracted byte; Assume byte is placed as the 8 MSB's in ++ a 32 bit word where the lower bits ++ are the FQID; i.e if bitOffsetInFqid=1 than its LSB ++ will effect the FQID MSB, if bitOffsetInFqid=24 than the ++ extracted byte will effect the 8 LSB's of the FQID, ++ if bitOffsetInFqid=31 than the byte's MSB will effect ++ the FQID's LSB; 0 means - no effect on FQID; ++ Note that one, and only one of ++ bitOffsetInFqid or bitOffsetInPlcrProfile must be set (i.e, ++ extracted byte must effect either FQID or Policer profile).*/ ++ uint8_t bitOffsetInPlcrProfile; ++ /**< 0-15, Selects which bits of the 8 policer profile id bits to ++ effect using the extracted byte; Assume byte is placed ++ as the 8 MSB's in a 16 bit word where the lower bits ++ are the policer profile id; i.e if bitOffsetInPlcrProfile=1 ++ than its LSB will effect the profile MSB, if bitOffsetInFqid=8 ++ than the extracted byte will effect the whole policer profile id, ++ if bitOffsetInFqid=15 than the byte's MSB will effect ++ the Policer Profile id's LSB; ++ 0 means - no effect on policer profile; Note that one, and only one of ++ bitOffsetInFqid or bitOffsetInPlcrProfile must be set (i.e, ++ extracted byte must effect either FQID or Policer profile).*/ ++} t_FmPcdKgExtractedOrParams; ++ ++/**************************************************************************//** ++ @Description Parameters for configuring a scheme counter ++*//***************************************************************************/ ++typedef struct t_FmPcdKgSchemeCounter { ++ bool update; /**< FALSE to keep the current counter state ++ and continue from that point, TRUE to update/reset ++ the counter when the scheme is written. */ ++ uint32_t value; /**< If update=TRUE, this value will be written into the ++ counter. clear this field to reset the counter. */ ++} t_FmPcdKgSchemeCounter; ++ ++/**************************************************************************//** ++ @Description Parameters for configuring a policer profile for a KeyGen scheme ++ (when policer is the next engine after this scheme). ++*//***************************************************************************/ ++typedef struct t_FmPcdKgPlcrProfile { ++ bool sharedProfile; /**< TRUE if this profile is shared between ports ++ (managed by master partition); Must not be TRUE ++ if profile is after Coarse Classification*/ ++ bool direct; /**< if TRUE, directRelativeProfileId only selects the profile ++ id, if FALSE fqidOffsetRelativeProfileIdBase is used ++ together with fqidOffsetShift and numOfProfiles ++ parameters, to define a range of profiles from ++ which the KeyGen result will determine the ++ destination policer profile. */ ++ union { ++ uint16_t directRelativeProfileId; /**< Used if 'direct' is TRUE, to select policer profile. ++ should indicate the policer profile offset within the ++ port's policer profiles or shared window. */ ++ struct { ++ uint8_t fqidOffsetShift; /**< Shift on the KeyGen create FQID offset (i.e. not the ++ final FQID - without the FQID base). */ ++ uint8_t fqidOffsetRelativeProfileIdBase; ++ /**< The base of the FMan Port's relative Storage-Profile ID; ++ this value will be "OR'ed" with the KeyGen create FQID ++ offset (i.e. not the final FQID - without the FQID base); ++ the final result should indicate the Storage-Profile offset ++ within the FMan Port's relative Storage-Profiles window/ ++ (or the SHARED window depends on 'sharedProfile'). */ ++ uint8_t numOfProfiles; /**< Range of profiles starting at base */ ++ } indirectProfile; /**< Indirect profile parameters */ ++ } profileSelect; /**< Direct/indirect profile selection and parameters */ ++} t_FmPcdKgPlcrProfile; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Parameters for configuring a storage profile for a KeyGen scheme. ++*//***************************************************************************/ ++typedef struct t_FmPcdKgStorageProfile { ++ bool direct; /**< If TRUE, directRelativeProfileId only selects the ++ profile id; ++ If FALSE, fqidOffsetRelativeProfileIdBase is used ++ together with fqidOffsetShift and numOfProfiles ++ parameters to define a range of profiles from which ++ the KeyGen result will determine the destination ++ storage profile. */ ++ union { ++ uint16_t directRelativeProfileId; /**< Used when 'direct' is TRUE, to select a storage profile; ++ should indicate the storage profile offset within the ++ port's storage profiles window. */ ++ struct { ++ uint8_t fqidOffsetShift; /**< Shift on the KeyGen create FQID offset (i.e. not the ++ final FQID - without the FQID base). */ ++ uint8_t fqidOffsetRelativeProfileIdBase; ++ /**< The base of the FMan Port's relative Storage-Profile ID; ++ this value will be "OR'ed" with the KeyGen create FQID ++ offset (i.e. not the final FQID - without the FQID base); ++ the final result should indicate the Storage-Profile offset ++ within the FMan Port's relative Storage-Profiles window. */ ++ uint8_t numOfProfiles; /**< Range of profiles starting at base. */ ++ } indirectProfile; /**< Indirect profile parameters. */ ++ } profileSelect; /**< Direct/indirect profile selection and parameters. */ ++} t_FmPcdKgStorageProfile; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Description Parameters for defining CC as the next engine after KeyGen ++*//***************************************************************************/ ++typedef struct t_FmPcdKgCc { ++ t_Handle h_CcTree; /**< A handle to a CC Tree */ ++ uint8_t grpId; /**< CC group id within the CC tree */ ++ bool plcrNext; /**< TRUE if after CC, in case of data frame, ++ policing is required. */ ++ bool bypassPlcrProfileGeneration; /**< TRUE to bypass KeyGen policer profile generation; ++ selected profile is the one set at port initialization. */ ++ t_FmPcdKgPlcrProfile plcrProfile; /**< Valid only if plcrNext = TRUE and ++ bypassPlcrProfileGeneration = FALSE */ ++} t_FmPcdKgCc; ++ ++/**************************************************************************//** ++ @Description Parameters for defining initializing a KeyGen scheme ++*//***************************************************************************/ ++typedef struct t_FmPcdKgSchemeParams { ++ bool modify; /**< TRUE to change an existing scheme */ ++ union ++ { ++ uint8_t relativeSchemeId; /**< if modify=FALSE:Partition relative scheme id */ ++ t_Handle h_Scheme; /**< if modify=TRUE: a handle of the existing scheme */ ++ } id; ++ bool alwaysDirect; /**< This scheme is reached only directly, i.e. no need ++ for match vector; KeyGen will ignore it when matching */ ++ struct { /**< HL Relevant only if alwaysDirect = FALSE */ ++ t_Handle h_NetEnv; /**< A handle to the Network environment as returned ++ by FM_PCD_NetEnvCharacteristicsSet() */ ++ uint8_t numOfDistinctionUnits; /**< Number of NetEnv units listed in unitIds array */ ++ uint8_t unitIds[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; ++ /**< Indexes as passed to SetNetEnvCharacteristics array*/ ++ } netEnvParams; ++ bool useHash; /**< use the KeyGen Hash functionality */ ++ t_FmPcdKgKeyExtractAndHashParams keyExtractAndHashParams; ++ /**< used only if useHash = TRUE */ ++ bool bypassFqidGeneration; /**< Normally - FALSE, TRUE to avoid FQID update in the IC; ++ In such a case FQID after KeyGen will be the default FQID ++ defined for the relevant port, or the FQID defined by CC ++ in cases where CC was the previous engine. */ ++ uint32_t baseFqid; /**< Base FQID; Relevant only if bypassFqidGeneration = FALSE; ++ If hash is used and an even distribution is expected ++ according to hashDistributionNumOfFqids, baseFqid must be aligned to ++ hashDistributionNumOfFqids. */ ++ uint8_t numOfUsedExtractedOrs; /**< Number of FQID masks listed in extractedOrs array */ ++ t_FmPcdKgExtractedOrParams extractedOrs[FM_PCD_KG_NUM_OF_GENERIC_REGS]; ++ /**< FM_PCD_KG_NUM_OF_GENERIC_REGS ++ registers are shared between qidMasks ++ functionality and some of the extraction ++ actions; Normally only some will be used ++ for qidMask. Driver will return error if ++ resource is full at initialization time. */ ++ ++#if (DPAA_VERSION >= 11) ++ bool overrideStorageProfile; /**< TRUE if KeyGen override previously decided storage profile */ ++ t_FmPcdKgStorageProfile storageProfile; /**< Used when overrideStorageProfile TRUE */ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ e_FmPcdEngine nextEngine; /**< may be BMI, PLCR or CC */ ++ union { /**< depends on nextEngine */ ++ e_FmPcdDoneAction doneAction; /**< Used when next engine is BMI (done) */ ++ t_FmPcdKgPlcrProfile plcrProfile; /**< Used when next engine is PLCR */ ++ t_FmPcdKgCc cc; /**< Used when next engine is CC */ ++ } kgNextEngineParams; ++ t_FmPcdKgSchemeCounter schemeCounter; /**< A structure of parameters for updating ++ the scheme counter */ ++} t_FmPcdKgSchemeParams; ++ ++/**************************************************************************//** ++ @Collection Definitions for CC statistics ++*//***************************************************************************/ ++#if (DPAA_VERSION >= 11) ++#define FM_PCD_CC_STATS_MAX_NUM_OF_FLR 10 /* Maximal supported number of frame length ranges */ ++#define FM_PCD_CC_STATS_FLR_SIZE 2 /* Size in bytes of a frame length range limit */ ++#endif /* (DPAA_VERSION >= 11) */ ++#define FM_PCD_CC_STATS_COUNTER_SIZE 4 /* Size in bytes of a frame length range counter */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description Parameters for defining CC as the next engine after a CC node. ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNextCcParams { ++ t_Handle h_CcNode; /**< A handle of the next CC node */ ++} t_FmPcdCcNextCcParams; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Parameters for defining Frame replicator as the next engine after a CC node. ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNextFrParams { ++ t_Handle h_FrmReplic; /**< A handle of the next frame replicator group */ ++} t_FmPcdCcNextFrParams; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Description Parameters for defining Policer as the next engine after a CC node. ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNextPlcrParams { ++ bool overrideParams; /**< TRUE if CC override previously decided parameters*/ ++ bool sharedProfile; /**< Relevant only if overrideParams=TRUE: ++ TRUE if this profile is shared between ports */ ++ uint16_t newRelativeProfileId; /**< Relevant only if overrideParams=TRUE: ++ (otherwise profile id is taken from KeyGen); ++ This parameter should indicate the policer ++ profile offset within the port's ++ policer profiles or from SHARED window.*/ ++ uint32_t newFqid; /**< Relevant only if overrideParams=TRUE: ++ FQID for enqueuing the frame; ++ In earlier chips if policer next engine is KEYGEN, ++ this parameter can be 0, because the KEYGEN ++ always decides the enqueue FQID.*/ ++#if (DPAA_VERSION >= 11) ++ uint8_t newRelativeStorageProfileId; ++ /**< Indicates the relative storage profile offset within ++ the port's storage profiles window; ++ Relevant only if the port was configured with VSP. */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmPcdCcNextPlcrParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining enqueue as the next action after a CC node. ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNextEnqueueParams { ++ e_FmPcdDoneAction action; /**< Action - when next engine is BMI (done) */ ++ bool overrideFqid; /**< TRUE if CC override previously decided fqid and vspid, ++ relevant if action = e_FM_PCD_ENQ_FRAME */ ++ uint32_t newFqid; /**< Valid if overrideFqid=TRUE, FQID for enqueuing the frame ++ (otherwise FQID is taken from KeyGen), ++ relevant if action = e_FM_PCD_ENQ_FRAME */ ++#if (DPAA_VERSION >= 11) ++ uint8_t newRelativeStorageProfileId; ++ /**< Valid if overrideFqid=TRUE, Indicates the relative virtual ++ storage profile offset within the port's storage profiles ++ window; Relevant only if the port was configured with VSP. */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmPcdCcNextEnqueueParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining KeyGen as the next engine after a CC node. ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNextKgParams { ++ bool overrideFqid; /**< TRUE if CC override previously decided fqid and vspid, ++ Note - this parameters irrelevant for earlier chips */ ++ uint32_t newFqid; /**< Valid if overrideFqid=TRUE, FQID for enqueuing the frame ++ (otherwise FQID is taken from KeyGen), ++ Note - this parameters irrelevant for earlier chips */ ++#if (DPAA_VERSION >= 11) ++ uint8_t newRelativeStorageProfileId; ++ /**< Valid if overrideFqid=TRUE, Indicates the relative virtual ++ storage profile offset within the port's storage profiles ++ window; Relevant only if the port was configured with VSP. */ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ t_Handle h_DirectScheme; /**< Direct scheme handle to go to. */ ++} t_FmPcdCcNextKgParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the next engine after a CC node. ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNextEngineParams { ++ e_FmPcdEngine nextEngine; /**< User has to initialize parameters ++ according to nextEngine definition */ ++ union { ++ t_FmPcdCcNextCcParams ccParams; /**< Parameters in case next engine is CC */ ++ t_FmPcdCcNextPlcrParams plcrParams; /**< Parameters in case next engine is PLCR */ ++ t_FmPcdCcNextEnqueueParams enqueueParams; /**< Parameters in case next engine is BMI */ ++ t_FmPcdCcNextKgParams kgParams; /**< Parameters in case next engine is KG */ ++#if (DPAA_VERSION >= 11) ++ t_FmPcdCcNextFrParams frParams; /**< Parameters in case next engine is FR */ ++#endif /* (DPAA_VERSION >= 11) */ ++ } params; /**< union used for all the next-engine parameters options */ ++ ++ t_Handle h_Manip; /**< Handle to Manipulation object. ++ Relevant if next engine is of type result ++ (e_FM_PCD_PLCR, e_FM_PCD_KG, e_FM_PCD_DONE) */ ++ ++ bool statisticsEn; /**< If TRUE, statistics counters are incremented ++ for each frame passing through this ++ Coarse Classification entry. */ ++} t_FmPcdCcNextEngineParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a single CC key ++*//***************************************************************************/ ++typedef struct t_FmPcdCcKeyParams { ++ uint8_t *p_Key; /**< Relevant only if 'action' = e_FM_PCD_ACTION_EXACT_MATCH; ++ pointer to the key of the size defined in keySize */ ++ uint8_t *p_Mask; /**< Relevant only if 'action' = e_FM_PCD_ACTION_EXACT_MATCH; ++ pointer to the Mask per key of the size defined ++ in keySize. p_Key and p_Mask (if defined) has to be ++ of the same size defined in the keySize; ++ NOTE that if this value is equal for all entries whithin ++ this table, the driver will automatically use global-mask ++ (i.e. one common mask for all entries) instead of private ++ one; that is done in order to spare some memory and for ++ better performance. */ ++ t_FmPcdCcNextEngineParams ccNextEngineParams; ++ /**< parameters for the next for the defined Key in ++ the p_Key */ ++} t_FmPcdCcKeyParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining CC keys parameters ++ The driver supports two methods for CC node allocation: dynamic and static. ++ Static mode was created in order to prevent runtime alloc/free ++ of FMan memory (MURAM), which may cause fragmentation; in this mode, ++ the driver automatically allocates the memory according to ++ 'maxNumOfKeys' parameter. The driver calculates the maximal memory ++ size that may be used for this CC-Node taking into consideration ++ 'maskSupport' and 'statisticsMode' parameters. ++ When 'action' = e_FM_PCD_ACTION_INDEXED_LOOKUP in the extraction ++ parameters of this node, 'maxNumOfKeys' must be equal to 'numOfKeys'. ++ In dynamic mode, 'maxNumOfKeys' must be zero. At initialization, ++ all required structures are allocated according to 'numOfKeys' ++ parameter. During runtime modification, these structures are ++ re-allocated according to the updated number of keys. ++ ++ Please note that 'action' and 'icIndxMask' mentioned in the ++ specific parameter explanations are passed in the extraction ++ parameters of the node (fields of extractCcParams.extractNonHdr). ++*//***************************************************************************/ ++typedef struct t_KeysParams { ++ uint16_t maxNumOfKeys; /**< Maximum number of keys that will (ever) be used in this CC-Node; ++ A value of zero may be used for dynamic memory allocation. */ ++ bool maskSupport; /**< This parameter is relevant only if a node is initialized with ++ 'action' = e_FM_PCD_ACTION_EXACT_MATCH and maxNumOfKeys > 0; ++ Should be TRUE to reserve table memory for key masks, even if ++ initial keys do not contain masks, or if the node was initialized ++ as 'empty' (without keys); this will allow user to add keys with ++ masks at runtime. ++ NOTE that if user want to use only global-masks (i.e. one common mask ++ for all the entries within this table, this parameter should set to 'FALSE'. */ ++ e_FmPcdCcStatsMode statisticsMode; /**< Determines the supported statistics mode for all node's keys. ++ To enable statistics gathering, statistics should be enabled per ++ every key, using 'statisticsEn' in next engine parameters structure ++ of that key; ++ If 'maxNumOfKeys' is set, all required structures will be ++ preallocated for all keys. */ ++#if (DPAA_VERSION >= 11) ++ uint16_t frameLengthRanges[FM_PCD_CC_STATS_MAX_NUM_OF_FLR]; ++ /**< Relevant only for 'RMON' statistics mode ++ (this feature is supported only on B4860 device); ++ Holds a list of programmable thresholds - for each received frame, ++ its length in bytes is examined against these range thresholds and ++ the appropriate counter is incremented by 1 - for example, to belong ++ to range i, the following should hold: ++ range i-1 threshold < frame length <= range i threshold ++ Each range threshold must be larger then its preceding range ++ threshold, and last range threshold must be 0xFFFF. */ ++#endif /* (DPAA_VERSION >= 11) */ ++ uint16_t numOfKeys; /**< Number of initial keys; ++ Note that in case of 'action' = e_FM_PCD_ACTION_INDEXED_LOOKUP, ++ this field should be power-of-2 of the number of bits that are ++ set in 'icIndxMask'. */ ++ uint8_t keySize; /**< Size of key - for extraction of type FULL_FIELD, 'keySize' has ++ to be the standard size of the selected key; For other extraction ++ types, 'keySize' has to be as size of extraction; When 'action' = ++ e_FM_PCD_ACTION_INDEXED_LOOKUP, 'keySize' must be 2. */ ++ t_FmPcdCcKeyParams keyParams[FM_PCD_MAX_NUM_OF_KEYS]; ++ /**< An array with 'numOfKeys' entries, each entry specifies the ++ corresponding key parameters; ++ When 'action' = e_FM_PCD_ACTION_EXACT_MATCH, this value must not ++ exceed 255 (FM_PCD_MAX_NUM_OF_KEYS-1) as the last entry is saved ++ for the 'miss' entry. */ ++ t_FmPcdCcNextEngineParams ccNextEngineParamsForMiss; ++ /**< Parameters for defining the next engine when a key is not matched; ++ Not relevant if action = e_FM_PCD_ACTION_INDEXED_LOOKUP. */ ++} t_KeysParams; ++ ++ ++/**************************************************************************//** ++ @Description Parameters for defining a CC node ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNodeParams { ++ t_FmPcdExtractEntry extractCcParams; /**< Extraction parameters */ ++ t_KeysParams keysParams; /**< Keys definition matching the selected extraction */ ++} t_FmPcdCcNodeParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a hash table ++*//***************************************************************************/ ++typedef struct t_FmPcdHashTableParams { ++ uint16_t maxNumOfKeys; /**< Maximum Number Of Keys that will (ever) be used in this Hash-table */ ++ e_FmPcdCcStatsMode statisticsMode; /**< If not e_FM_PCD_CC_STATS_MODE_NONE, the required structures for the ++ requested statistics mode will be allocated according to maxNumOfKeys. */ ++ uint16_t hashResMask; /**< Mask that will be used on the hash-result; ++ The number-of-sets for this hash will be calculated ++ as (2^(number of bits set in 'hashResMask')); ++ The 4 lower bits must be cleared. */ ++ uint8_t hashShift; /**< Byte offset from the beginning of the KeyGen hash result to the ++ 2-bytes to be used as hash index. */ ++ uint8_t matchKeySize; /**< Size of the exact match keys held by the hash buckets */ ++ ++ t_FmPcdCcNextEngineParams ccNextEngineParamsForMiss; /**< Parameters for defining the next engine when a key is not matched */ ++} t_FmPcdHashTableParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a CC tree group. ++ ++ This structure defines a CC group in terms of NetEnv units ++ and the action to be taken in each case. The unitIds list must ++ be given in order from low to high indices. ++ ++ t_FmPcdCcNextEngineParams is a list of 2^numOfDistinctionUnits ++ structures where each defines the next action to be taken for ++ each units combination. for example: ++ numOfDistinctionUnits = 2 ++ unitIds = {1,3} ++ p_NextEnginePerEntriesInGrp[0] = t_FmPcdCcNextEngineParams for the case that ++ unit 1 - not found; unit 3 - not found; ++ p_NextEnginePerEntriesInGrp[1] = t_FmPcdCcNextEngineParams for the case that ++ unit 1 - not found; unit 3 - found; ++ p_NextEnginePerEntriesInGrp[2] = t_FmPcdCcNextEngineParams for the case that ++ unit 1 - found; unit 3 - not found; ++ p_NextEnginePerEntriesInGrp[3] = t_FmPcdCcNextEngineParams for the case that ++ unit 1 - found; unit 3 - found; ++*//***************************************************************************/ ++typedef struct t_FmPcdCcGrpParams { ++ uint8_t numOfDistinctionUnits; /**< Up to 4 */ ++ uint8_t unitIds[FM_PCD_MAX_NUM_OF_CC_UNITS]; ++ /**< Indices of the units as defined in ++ FM_PCD_NetEnvCharacteristicsSet() */ ++ t_FmPcdCcNextEngineParams nextEnginePerEntriesInGrp[FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP]; ++ /**< Maximum entries per group is 16 */ ++} t_FmPcdCcGrpParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining CC tree groups ++*//***************************************************************************/ ++typedef struct t_FmPcdCcTreeParams { ++ t_Handle h_NetEnv; /**< A handle to the Network environment as returned ++ by FM_PCD_NetEnvCharacteristicsSet() */ ++ uint8_t numOfGrps; /**< Number of CC groups within the CC tree */ ++ t_FmPcdCcGrpParams ccGrpParams[FM_PCD_MAX_NUM_OF_CC_GROUPS]; ++ /**< Parameters for each group. */ ++} t_FmPcdCcTreeParams; ++ ++ ++/**************************************************************************//** ++ @Description CC key statistics structure ++*//***************************************************************************/ ++typedef struct t_FmPcdCcKeyStatistics { ++ uint32_t byteCount; /**< This counter reflects byte count of frames that ++ were matched by this key. */ ++ uint32_t frameCount; /**< This counter reflects count of frames that ++ were matched by this key. */ ++#if (DPAA_VERSION >= 11) ++ uint32_t frameLengthRangeCount[FM_PCD_CC_STATS_MAX_NUM_OF_FLR]; ++ /**< These counters reflect how many frames matched ++ this key in 'RMON' statistics mode: ++ Each counter holds the number of frames of a ++ specific frames length range, according to the ++ ranges provided at initialization. */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmPcdCcKeyStatistics; ++ ++/**************************************************************************//** ++ @Description Parameters for defining policer byte rate ++*//***************************************************************************/ ++typedef struct t_FmPcdPlcrByteRateModeParams { ++ e_FmPcdPlcrFrameLengthSelect frameLengthSelection; /**< Frame length selection */ ++ e_FmPcdPlcrRollBackFrameSelect rollBackFrameSelection; /**< relevant option only e_FM_PCD_PLCR_L2_FRM_LEN, ++ e_FM_PCD_PLCR_FULL_FRM_LEN */ ++} t_FmPcdPlcrByteRateModeParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the policer profile (based on ++ RFC-2698 or RFC-4115 attributes). ++*//***************************************************************************/ ++typedef struct t_FmPcdPlcrNonPassthroughAlgParams { ++ e_FmPcdPlcrRateMode rateMode; /**< Byte mode or Packet mode */ ++ t_FmPcdPlcrByteRateModeParams byteModeParams; /**< Valid for Byte NULL for Packet */ ++ uint32_t comittedInfoRate; /**< KBits/Second or Packets/Second */ ++ uint32_t comittedBurstSize; /**< Bytes/Packets */ ++ uint32_t peakOrAccessiveInfoRate; /**< KBits/Second or Packets/Second */ ++ uint32_t peakOrAccessiveBurstSize; /**< Bytes/Packets */ ++} t_FmPcdPlcrNonPassthroughAlgParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the next engine after policer ++*//***************************************************************************/ ++typedef union u_FmPcdPlcrNextEngineParams { ++ e_FmPcdDoneAction action; /**< Action - when next engine is BMI (done) */ ++ t_Handle h_Profile; /**< Policer profile handle - used when next engine ++ is Policer, must be a SHARED profile */ ++ t_Handle h_DirectScheme; /**< Direct scheme select - when next engine is KeyGen */ ++} u_FmPcdPlcrNextEngineParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the policer profile entry ++*//***************************************************************************/ ++typedef struct t_FmPcdPlcrProfileParams { ++ bool modify; /**< TRUE to change an existing profile */ ++ union { ++ struct { ++ e_FmPcdProfileTypeSelection profileType; /**< Type of policer profile */ ++ t_Handle h_FmPort; /**< Relevant for per-port profiles only */ ++ uint16_t relativeProfileId; /**< Profile id - relative to shared group or to port */ ++ } newParams; /**< use it when modify = FALSE */ ++ t_Handle h_Profile; /**< A handle to a profile - use it when modify=TRUE */ ++ } id; ++ e_FmPcdPlcrAlgorithmSelection algSelection; /**< Profile Algorithm PASS_THROUGH, RFC_2698, RFC_4115 */ ++ e_FmPcdPlcrColorMode colorMode; /**< COLOR_BLIND, COLOR_AWARE */ ++ ++ union { ++ e_FmPcdPlcrColor dfltColor; /**< For Color-Blind Pass-Through mode; the policer will re-color ++ any incoming packet with the default value. */ ++ e_FmPcdPlcrColor override; /**< For Color-Aware modes; the profile response to a ++ pre-color value of 2'b11. */ ++ } color; ++ ++ t_FmPcdPlcrNonPassthroughAlgParams nonPassthroughAlgParams; /**< RFC2698 or RFC4115 parameters */ ++ ++ e_FmPcdEngine nextEngineOnGreen; /**< Next engine for green-colored frames */ ++ u_FmPcdPlcrNextEngineParams paramsOnGreen; /**< Next engine parameters for green-colored frames */ ++ ++ e_FmPcdEngine nextEngineOnYellow; /**< Next engine for yellow-colored frames */ ++ u_FmPcdPlcrNextEngineParams paramsOnYellow; /**< Next engine parameters for yellow-colored frames */ ++ ++ e_FmPcdEngine nextEngineOnRed; /**< Next engine for red-colored frames */ ++ u_FmPcdPlcrNextEngineParams paramsOnRed; /**< Next engine parameters for red-colored frames */ ++ ++ bool trapProfileOnFlowA; /**< Obsolete - do not use */ ++ bool trapProfileOnFlowB; /**< Obsolete - do not use */ ++ bool trapProfileOnFlowC; /**< Obsolete - do not use */ ++} t_FmPcdPlcrProfileParams; ++ ++/**************************************************************************//** ++ @Description Parameters for selecting a location for requested manipulation ++*//***************************************************************************/ ++typedef struct t_FmManipHdrInfo ++{ ++ e_NetHeaderType hdr; /**< Header selection */ ++ e_FmPcdHdrIndex hdrIndex; /**< Relevant only for MPLS, VLAN and tunneled IP. Otherwise should be cleared. */ ++ bool byField; /**< TRUE if the location of manipulation is according to some field in the specific header*/ ++ t_FmPcdFields fullField; /**< Relevant only when byField = TRUE: Extract field */ ++} t_FmManipHdrInfo; ++ ++#ifdef FM_CAPWAP_SUPPORT ++/**************************************************************************//** ++ @Description Parameters for defining an insertion manipulation ++ of type e_FM_PCD_MANIP_INSRT_TO_START_OF_FRAME_TEMPLATE ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrInsrtByTemplateParams { ++ uint8_t size; /**< Size of insert template to the start of the frame. */ ++ uint8_t hdrTemplate[FM_PCD_MAX_MANIP_INSRT_TEMPLATE_SIZE]; ++ /**< Array of the insertion template. */ ++ ++ bool modifyOuterIp; /**< TRUE if user want to modify some fields in outer IP. */ ++ struct { ++ uint16_t ipOuterOffset; /**< Offset of outer IP in the insert template, relevant if modifyOuterIp = TRUE.*/ ++ uint16_t dscpEcn; /**< value of dscpEcn in IP outer, relevant if modifyOuterIp = TRUE. ++ in IPV4 dscpEcn only byte - it has to be adjusted to the right*/ ++ bool udpPresent; /**< TRUE if UDP is present in the insert template, relevant if modifyOuterIp = TRUE.*/ ++ uint8_t udpOffset; /**< Offset in the insert template of UDP, relevant if modifyOuterIp = TRUE and udpPresent=TRUE.*/ ++ uint8_t ipIdentGenId; /**< Used by FMan-CTRL to calculate IP-identification field,relevant if modifyOuterIp = TRUE.*/ ++ bool recalculateLength; /**< TRUE if recalculate length has to be performed due to the engines in the path which can change the frame later, relevant if modifyOuterIp = TRUE.*/ ++ struct { ++ uint8_t blockSize; /**< The CAAM block-size; Used by FMan-CTRL to calculate the IP Total Length field.*/ ++ uint8_t extraBytesAddedAlignedToBlockSize; /**< Used by FMan-CTRL to calculate the IP Total Length field and UDP length*/ ++ uint8_t extraBytesAddedNotAlignedToBlockSize;/**< Used by FMan-CTRL to calculate the IP Total Length field and UDP length.*/ ++ } recalculateLengthParams; /**< Recalculate length parameters - relevant if modifyOuterIp = TRUE and recalculateLength = TRUE */ ++ } modifyOuterIpParams; /**< Outer IP modification parameters - ignored if modifyOuterIp is FALSE */ ++ ++ bool modifyOuterVlan; /**< TRUE if user wants to modify VPri field in the outer VLAN header*/ ++ struct { ++ uint8_t vpri; /**< Value of VPri, relevant if modifyOuterVlan = TRUE ++ VPri only 3 bits, it has to be adjusted to the right*/ ++ } modifyOuterVlanParams; ++} t_FmPcdManipHdrInsrtByTemplateParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining CAPWAP fragmentation ++*//***************************************************************************/ ++typedef struct t_CapwapFragmentationParams { ++ uint16_t sizeForFragmentation; /**< if length of the frame is greater than this value, CAPWAP fragmentation will be executed.*/ ++ bool headerOptionsCompr; /**< TRUE - first fragment include the CAPWAP header options field, ++ and all other fragments exclude the CAPWAP options field, ++ FALSE - all fragments include CAPWAP header options field. */ ++} t_CapwapFragmentationParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining CAPWAP reassembly ++*//***************************************************************************/ ++typedef struct t_CapwapReassemblyParams { ++ uint16_t maxNumFramesInProcess; /**< Number of frames which can be reassembled concurrently; must be power of 2. ++ In case numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 4 - 512, ++ In case numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 8 - 2048 */ ++ bool haltOnDuplicationFrag; /**< If TRUE, reassembly process will be halted due to duplicated fragment, ++ and all processed fragments will be enqueued with error indication; ++ If FALSE, only duplicated fragments will be enqueued with error indication. */ ++ ++ e_FmPcdManipReassemTimeOutMode timeOutMode; /**< Expiration delay initialized by the reassembly process */ ++ uint32_t fqidForTimeOutFrames; /**< FQID in which time out frames will enqueue during Time Out Process */ ++ uint32_t timeoutRoutineRequestTime; ++ /**< Represents the time interval in microseconds between consecutive ++ timeout routine requests It has to be power of 2. */ ++ uint32_t timeoutThresholdForReassmProcess; ++ /**< Time interval (microseconds) for marking frames in process as too old; ++ Frames in process are those for which at least one fragment was received ++ but not all fragments. */ ++ ++ e_FmPcdManipReassemWaysNumber numOfFramesPerHashEntry;/**< Number of frames per hash entry (needed for the reassembly process) */ ++} t_CapwapReassemblyParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining fragmentation/reassembly manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipFragOrReasmParams { ++ bool frag; /**< TRUE if using the structure for fragmentation, ++ otherwise this structure is used for reassembly */ ++ uint8_t sgBpid; /**< Scatter/Gather buffer pool id; ++ Same LIODN number is used for these buffers as for ++ the received frames buffers, so buffers of this pool ++ need to be allocated in the same memory area as the ++ received buffers. If the received buffers arrive ++ from different sources, the Scatter/Gather BP id ++ should be mutual to all these sources. */ ++ e_NetHeaderType hdr; /**< Header selection */ ++ union { ++ t_CapwapFragmentationParams capwapFragParams; /**< Structure for CAPWAP fragmentation, ++ relevant if 'frag' = TRUE, 'hdr' = HEADER_TYPE_CAPWAP */ ++ t_CapwapReassemblyParams capwapReasmParams; /**< Structure for CAPWAP reassembly, ++ relevant if 'frag' = FALSE, 'hdr' = HEADER_TYPE_CAPWAP */ ++ } u; ++} t_FmPcdManipFragOrReasmParams; ++ ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++/**************************************************************************//** ++ @Description Parameters for defining header removal by header type ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrRmvByHdrParams { ++ e_FmPcdManipHdrRmvByHdrType type; /**< Selection of header removal location */ ++ union { ++#ifdef FM_CAPWAP_SUPPORT ++ struct { ++ bool include; /**< If FALSE, remove until the specified header (not including the header); ++ If TRUE, remove also the specified header. */ ++ t_FmManipHdrInfo hdrInfo; ++ } fromStartByHdr; /**< Relevant when type = e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START */ ++#endif /* FM_CAPWAP_SUPPORT */ ++ e_FmPcdManipHdrRmvSpecificL2 specificL2; /**< Relevant when type = e_FM_PCD_MANIP_BY_HDR_SPECIFIC_L2; ++ Defines which L2 headers to remove. */ ++ } u; ++} t_FmPcdManipHdrRmvByHdrParams; ++ ++/**************************************************************************//** ++ @Description Parameters for configuring IP fragmentation manipulation ++ ++ Restrictions: ++ - IP Fragmentation output fragments must not be forwarded to application directly. ++ - Maximum number of fragments per frame is 16. ++ - Fragmentation of IP fragments is not supported. ++ - IPv4 packets containing header Option fields are fragmented by copying all option ++ fields to each fragment, regardless of the copy bit value. ++ - Transmit confirmation is not supported. ++ - Fragmentation after SEC can't handle S/G frames. ++ - Fragmentation nodes must be set as the last PCD action (i.e. the ++ corresponding CC node key must have next engine set to e_FM_PCD_DONE). ++ - Only BMan buffers shall be used for frames to be fragmented. ++ - IPF does not support VSP. Therefore, on the same port where we have IPF ++ we cannot support VSP. ++ - NOTE: The following comment is relevant only for FMAN v3 devices: IPF ++ does not support VSP. Therefore, on the same port where we have IPF we ++ cannot support VSP. ++*//***************************************************************************/ ++typedef struct t_FmPcdManipFragIpParams { ++ uint16_t sizeForFragmentation; /**< If length of the frame is greater than this value, ++ IP fragmentation will be executed.*/ ++#if (DPAA_VERSION == 10) ++ uint8_t scratchBpid; /**< Absolute buffer pool id according to BM configuration.*/ ++#endif /* (DPAA_VERSION == 10) */ ++ bool sgBpidEn; /**< Enable a dedicated buffer pool id for the Scatter/Gather buffer allocation; ++ If disabled, the Scatter/Gather buffer will be allocated from the same pool as the ++ received frame's buffer. */ ++ uint8_t sgBpid; /**< Scatter/Gather buffer pool id; ++ This parameters is relevant when 'sgBpidEn=TRUE'; ++ Same LIODN number is used for these buffers as for the received frames buffers, so buffers ++ of this pool need to be allocated in the same memory area as the received buffers. ++ If the received buffers arrive from different sources, the Scatter/Gather BP id should be ++ mutual to all these sources. */ ++ e_FmPcdManipDontFragAction dontFragAction; /**< Don't Fragment Action - If an IP packet is larger ++ than MTU and its DF bit is set, then this field will ++ determine the action to be taken.*/ ++} t_FmPcdManipFragIpParams; ++ ++/**************************************************************************//** ++ @Description Parameters for configuring IP reassembly manipulation. ++ ++ This is a common structure for both IPv4 and IPv6 reassembly ++ manipulation. For reassembly of both IPv4 and IPv6, make sure to ++ set the 'hdr' field in t_FmPcdManipReassemParams to HEADER_TYPE_IPv6. ++ ++ Restrictions: ++ - Application must define at least one scheme to catch the reassembled frames. ++ - Maximum number of fragments per frame is 16. ++ - Reassembly of IPv4 fragments containing Option fields is supported. ++ ++*//***************************************************************************/ ++typedef struct t_FmPcdManipReassemIpParams { ++ uint8_t relativeSchemeId[2]; /**< Partition relative scheme id: ++ relativeSchemeId[0] - Relative scheme ID for IPV4 Reassembly manipulation; ++ relativeSchemeId[1] - Relative scheme ID for IPV6 Reassembly manipulation; ++ NOTE: The following comment is relevant only for FMAN v2 devices: ++ Relative scheme ID for IPv4/IPv6 Reassembly manipulation must be smaller than ++ the user schemes id to ensure that the reassembly's schemes will be first match; ++ Rest schemes, if defined, should have higher relative scheme ID. */ ++#if (DPAA_VERSION >= 11) ++ uint32_t nonConsistentSpFqid; /**< In case that other fragments of the frame corresponds to different storage ++ profile than the opening fragment (Non-Consistent-SP state) ++ then one of two possible scenarios occurs: ++ if 'nonConsistentSpFqid != 0', the reassembled frame will be enqueued to ++ this fqid, otherwise a 'Non Consistent SP' bit will be set in the FD[status].*/ ++#else ++ uint8_t sgBpid; /**< Buffer pool id for the S/G frame created by the reassembly process */ ++#endif /* (DPAA_VERSION >= 11) */ ++ uint8_t dataMemId; /**< Memory partition ID for the IPR's external tables structure */ ++ uint16_t dataLiodnOffset; /**< LIODN offset for access the IPR's external tables structure. */ ++ uint16_t minFragSize[2]; /**< Minimum fragment size: ++ minFragSize[0] - for ipv4, minFragSize[1] - for ipv6 */ ++ e_FmPcdManipReassemWaysNumber numOfFramesPerHashEntry[2]; ++ /**< Number of frames per hash entry needed for reassembly process: ++ numOfFramesPerHashEntry[0] - for ipv4 (max value is e_FM_PCD_MANIP_EIGHT_WAYS_HASH); ++ numOfFramesPerHashEntry[1] - for ipv6 (max value is e_FM_PCD_MANIP_SIX_WAYS_HASH). */ ++ uint16_t maxNumFramesInProcess; /**< Number of frames which can be processed by Reassembly in the same time; ++ Must be power of 2; ++ In the case numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 4 - 512; ++ In the case numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 8 - 2048. */ ++ e_FmPcdManipReassemTimeOutMode timeOutMode; /**< Expiration delay initialized by Reassembly process */ ++ uint32_t fqidForTimeOutFrames; /**< FQID in which time out frames will enqueue during Time Out Process */ ++ uint32_t timeoutThresholdForReassmProcess; ++ /**< Represents the time interval in microseconds which defines ++ if opened frame (at least one fragment was processed but not all the fragments)is found as too old*/ ++} t_FmPcdManipReassemIpParams; ++ ++/**************************************************************************//** ++ @Description structure for defining IPSEC manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipSpecialOffloadIPSecParams { ++ bool decryption; /**< TRUE if being used in decryption direction; ++ FALSE if being used in encryption direction. */ ++ bool ecnCopy; /**< TRUE to copy the ECN bits from inner/outer to outer/inner ++ (direction depends on the 'decryption' field). */ ++ bool dscpCopy; /**< TRUE to copy the DSCP bits from inner/outer to outer/inner ++ (direction depends on the 'decryption' field). */ ++ bool variableIpHdrLen; /**< TRUE for supporting variable IP header length in decryption. */ ++ bool variableIpVersion; /**< TRUE for supporting both IP version on the same SA in encryption */ ++ uint8_t outerIPHdrLen; /**< if 'variableIpVersion == TRUE' than this field must be set to non-zero value; ++ It is specifies the length of the outer IP header that was configured in the ++ corresponding SA. */ ++} t_FmPcdManipSpecialOffloadIPSecParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining special offload manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipSpecialOffloadParams { ++ e_FmPcdManipSpecialOffloadType type; /**< Type of special offload manipulation */ ++ union ++ { ++ t_FmPcdManipSpecialOffloadIPSecParams ipsec; /**< Parameters for IPSec; Relevant when ++ type = e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC */ ++ } u; ++} t_FmPcdManipSpecialOffloadParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining generic removal manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrRmvGenericParams { ++ uint8_t offset; /**< Offset from beginning of header to the start ++ location of the removal */ ++ uint8_t size; /**< Size of removed section */ ++} t_FmPcdManipHdrRmvGenericParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining generic insertion manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrInsrtGenericParams { ++ uint8_t offset; /**< Offset from beginning of header to the start ++ location of the insertion */ ++ uint8_t size; /**< Size of inserted section */ ++ bool replace; /**< TRUE to override (replace) existing data at ++ 'offset', FALSE to insert */ ++ uint8_t *p_Data; /**< Pointer to data to be inserted */ ++} t_FmPcdManipHdrInsrtGenericParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation VLAN DSCP To Vpri translation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrFieldUpdateVlanDscpToVpri { ++ uint8_t dscpToVpriTable[FM_PCD_MANIP_DSCP_TO_VLAN_TRANS]; ++ /**< A table of VPri values for each DSCP value; ++ The index is the DSCP value (0-0x3F) and the ++ value is the corresponding VPRI (0-15). */ ++ uint8_t vpriDefVal; /**< 0-7, Relevant only if if updateType = ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN, ++ this field is the Q Tag default value if the ++ IP header is not found. */ ++} t_FmPcdManipHdrFieldUpdateVlanDscpToVpri; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation VLAN fields updates ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrFieldUpdateVlan { ++ e_FmPcdManipHdrFieldUpdateVlan updateType; /**< Selects VLAN update type */ ++ union { ++ uint8_t vpri; /**< 0-7, Relevant only if If updateType = ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_PRI, this ++ is the new VLAN pri. */ ++ t_FmPcdManipHdrFieldUpdateVlanDscpToVpri dscpToVpri; /**< Parameters structure, Relevant only if updateType ++ = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN. */ ++ } u; ++} t_FmPcdManipHdrFieldUpdateVlan; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation IPV4 fields updates ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrFieldUpdateIpv4 { ++ ipv4HdrManipUpdateFlags_t validUpdates; /**< ORed flag, selecting the required updates */ ++ uint8_t tos; /**< 8 bit New TOS; Relevant if validUpdates contains ++ HDR_MANIP_IPV4_TOS */ ++ uint16_t id; /**< 16 bit New IP ID; Relevant only if validUpdates ++ contains HDR_MANIP_IPV4_ID */ ++ uint32_t src; /**< 32 bit New IP SRC; Relevant only if validUpdates ++ contains HDR_MANIP_IPV4_SRC */ ++ uint32_t dst; /**< 32 bit New IP DST; Relevant only if validUpdates ++ contains HDR_MANIP_IPV4_DST */ ++} t_FmPcdManipHdrFieldUpdateIpv4; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation IPV6 fields updates ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrFieldUpdateIpv6 { ++ ipv6HdrManipUpdateFlags_t validUpdates; /**< ORed flag, selecting the required updates */ ++ uint8_t trafficClass; /**< 8 bit New Traffic Class; Relevant if validUpdates contains ++ HDR_MANIP_IPV6_TC */ ++ uint8_t src[NET_HEADER_FIELD_IPv6_ADDR_SIZE]; ++ /**< 16 byte new IP SRC; Relevant only if validUpdates ++ contains HDR_MANIP_IPV6_SRC */ ++ uint8_t dst[NET_HEADER_FIELD_IPv6_ADDR_SIZE]; ++ /**< 16 byte new IP DST; Relevant only if validUpdates ++ contains HDR_MANIP_IPV6_DST */ ++} t_FmPcdManipHdrFieldUpdateIpv6; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation TCP/UDP fields updates ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrFieldUpdateTcpUdp { ++ tcpUdpHdrManipUpdateFlags_t validUpdates; /**< ORed flag, selecting the required updates */ ++ uint16_t src; /**< 16 bit New TCP/UDP SRC; Relevant only if validUpdates ++ contains HDR_MANIP_TCP_UDP_SRC */ ++ uint16_t dst; /**< 16 bit New TCP/UDP DST; Relevant only if validUpdates ++ contains HDR_MANIP_TCP_UDP_DST */ ++} t_FmPcdManipHdrFieldUpdateTcpUdp; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation fields updates ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrFieldUpdateParams { ++ e_FmPcdManipHdrFieldUpdateType type; /**< Type of header field update manipulation */ ++ union { ++ t_FmPcdManipHdrFieldUpdateVlan vlan; /**< Parameters for VLAN update. Relevant when ++ type = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN */ ++ t_FmPcdManipHdrFieldUpdateIpv4 ipv4; /**< Parameters for IPv4 update. Relevant when ++ type = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4 */ ++ t_FmPcdManipHdrFieldUpdateIpv6 ipv6; /**< Parameters for IPv6 update. Relevant when ++ type = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6 */ ++ t_FmPcdManipHdrFieldUpdateTcpUdp tcpUdp; /**< Parameters for TCP/UDP update. Relevant when ++ type = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP */ ++ } u; ++} t_FmPcdManipHdrFieldUpdateParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining custom header manipulation for IP replacement ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrCustomIpHdrReplace { ++ e_FmPcdManipHdrCustomIpReplace replaceType; /**< Selects replace update type */ ++ bool decTtlHl; /**< Decrement TTL (IPV4) or Hop limit (IPV6) by 1 */ ++ bool updateIpv4Id; /**< Relevant when replaceType = ++ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4 */ ++ uint16_t id; /**< 16 bit New IP ID; Relevant only if ++ updateIpv4Id = TRUE */ ++ uint8_t hdrSize; /**< The size of the new IP header */ ++ uint8_t hdr[FM_PCD_MANIP_MAX_HDR_SIZE]; ++ /**< The new IP header */ ++} t_FmPcdManipHdrCustomIpHdrReplace; ++ ++/**************************************************************************//** ++ @Description Parameters for defining custom header manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrCustomParams { ++ e_FmPcdManipHdrCustomType type; /**< Type of header field update manipulation */ ++ union { ++ t_FmPcdManipHdrCustomIpHdrReplace ipHdrReplace; /**< Parameters IP header replacement */ ++ } u; ++} t_FmPcdManipHdrCustomParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining specific L2 insertion manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrInsrtSpecificL2Params { ++ e_FmPcdManipHdrInsrtSpecificL2 specificL2; /**< Selects which L2 headers to insert */ ++ bool update; /**< TRUE to update MPLS header */ ++ uint8_t size; /**< size of inserted section */ ++ uint8_t *p_Data; /**< data to be inserted */ ++} t_FmPcdManipHdrInsrtSpecificL2Params; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header insertion manipulation by header type ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrInsrtByHdrParams { ++ e_FmPcdManipHdrInsrtByHdrType type; /**< Selects manipulation type */ ++ union { ++ ++ t_FmPcdManipHdrInsrtSpecificL2Params specificL2Params; ++ /**< Used when type = e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2: ++ Selects which L2 headers to remove */ ++ } u; ++} t_FmPcdManipHdrInsrtByHdrParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header insertion manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrInsrtParams { ++ e_FmPcdManipHdrInsrtType type; /**< Type of insertion manipulation */ ++ union { ++ t_FmPcdManipHdrInsrtByHdrParams byHdr; /**< Parameters for defining header insertion manipulation by header type, ++ relevant if 'type' = e_FM_PCD_MANIP_INSRT_BY_HDR */ ++ t_FmPcdManipHdrInsrtGenericParams generic; /**< Parameters for defining generic header insertion manipulation, ++ relevant if 'type' = e_FM_PCD_MANIP_INSRT_GENERIC */ ++#ifdef FM_CAPWAP_SUPPORT ++ t_FmPcdManipHdrInsrtByTemplateParams byTemplate; /**< Parameters for defining header insertion manipulation by template, ++ relevant if 'type' = e_FM_PCD_MANIP_INSRT_BY_TEMPLATE */ ++#endif /* FM_CAPWAP_SUPPORT */ ++ } u; ++} t_FmPcdManipHdrInsrtParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header removal manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrRmvParams { ++ e_FmPcdManipHdrRmvType type; /**< Type of header removal manipulation */ ++ union { ++ t_FmPcdManipHdrRmvByHdrParams byHdr; /**< Parameters for defining header removal manipulation by header type, ++ relevant if type = e_FM_PCD_MANIP_RMV_BY_HDR */ ++ t_FmPcdManipHdrRmvGenericParams generic; /**< Parameters for defining generic header removal manipulation, ++ relevant if type = e_FM_PCD_MANIP_RMV_GENERIC */ ++ } u; ++} t_FmPcdManipHdrRmvParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation node ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrParams { ++ bool rmv; /**< TRUE, to define removal manipulation */ ++ t_FmPcdManipHdrRmvParams rmvParams; /**< Parameters for removal manipulation, relevant if 'rmv' = TRUE */ ++ ++ bool insrt; /**< TRUE, to define insertion manipulation */ ++ t_FmPcdManipHdrInsrtParams insrtParams; /**< Parameters for insertion manipulation, relevant if 'insrt' = TRUE */ ++ ++ bool fieldUpdate; /**< TRUE, to define field update manipulation */ ++ t_FmPcdManipHdrFieldUpdateParams fieldUpdateParams; /**< Parameters for field update manipulation, relevant if 'fieldUpdate' = TRUE */ ++ ++ bool custom; /**< TRUE, to define custom manipulation */ ++ t_FmPcdManipHdrCustomParams customParams; /**< Parameters for custom manipulation, relevant if 'custom' = TRUE */ ++ ++ bool dontParseAfterManip;/**< FALSE to activate the parser a second time after ++ completing the manipulation on the frame */ ++} t_FmPcdManipHdrParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining fragmentation manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipFragParams { ++ e_NetHeaderType hdr; /**< Header selection */ ++ union { ++ t_FmPcdManipFragIpParams ipFrag; /**< Parameters for defining IP fragmentation, ++ relevant if 'hdr' = HEADER_TYPE_Ipv4 or HEADER_TYPE_Ipv6 */ ++ } u; ++} t_FmPcdManipFragParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining reassembly manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipReassemParams { ++ e_NetHeaderType hdr; /**< Header selection */ ++ union { ++ t_FmPcdManipReassemIpParams ipReassem; /**< Parameters for defining IP reassembly, ++ relevant if 'hdr' = HEADER_TYPE_Ipv4 or HEADER_TYPE_Ipv6 */ ++ } u; ++} t_FmPcdManipReassemParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a manipulation node ++*//***************************************************************************/ ++typedef struct t_FmPcdManipParams { ++ e_FmPcdManipType type; /**< Selects type of manipulation node */ ++ union{ ++ t_FmPcdManipHdrParams hdr; /**< Parameters for defining header manipulation node */ ++ t_FmPcdManipReassemParams reassem; /**< Parameters for defining reassembly manipulation node */ ++ t_FmPcdManipFragParams frag; /**< Parameters for defining fragmentation manipulation node */ ++ t_FmPcdManipSpecialOffloadParams specialOffload; /**< Parameters for defining special offload manipulation node */ ++ } u; ++ ++ t_Handle h_NextManip; /**< Supported for Header Manipulation only; ++ Handle to another (previously defined) manipulation node; ++ Allows concatenation of manipulation actions; ++ This parameter is optional and may be NULL. */ ++#ifdef FM_CAPWAP_SUPPORT ++ bool fragOrReasm; /**< TRUE, if defined fragmentation/reassembly manipulation */ ++ t_FmPcdManipFragOrReasmParams fragOrReasmParams; /**< Parameters for fragmentation/reassembly manipulation, ++ relevant if fragOrReasm = TRUE */ ++#endif /* FM_CAPWAP_SUPPORT */ ++} t_FmPcdManipParams; ++ ++/**************************************************************************//** ++ @Description Structure for retrieving IP reassembly statistics ++*//***************************************************************************/ ++typedef struct t_FmPcdManipReassemIpStats { ++ /* common counters for both IPv4 and IPv6 */ ++ uint32_t timeout; /**< Counts the number of TimeOut occurrences */ ++ uint32_t rfdPoolBusy; /**< Counts the number of failed attempts to allocate ++ a Reassembly Frame Descriptor */ ++ uint32_t internalBufferBusy; /**< Counts the number of times an internal buffer busy occurred */ ++ uint32_t externalBufferBusy; /**< Counts the number of times external buffer busy occurred */ ++ uint32_t sgFragments; /**< Counts the number of Scatter/Gather fragments */ ++ uint32_t dmaSemaphoreDepletion; /**< Counts the number of failed attempts to allocate a DMA semaphore */ ++ struct { ++ uint32_t successfullyReassembled; /**< Counts the number of successfully reassembled frames */ ++ uint32_t validFragments; /**< Counts the total number of valid fragments that ++ have been processed for all frames */ ++ uint32_t processedFragments; /**< Counts the number of processed fragments ++ (valid and error fragments) for all frames */ ++ uint32_t malformedFragments; /**< Counts the number of malformed fragments processed for all frames */ ++ uint32_t discardedFragments; /**< Counts the number of fragments discarded by the reassembly process */ ++ uint32_t autoLearnBusy; /**< Counts the number of times a busy condition occurs when attempting ++ to access an IP-Reassembly Automatic Learning Hash set */ ++ uint32_t moreThan16Fragments; /**< Counts the fragment occurrences in which the number of fragments-per-frame ++ exceeds 16 */ ++ } specificHdrStatistics[2]; /**< slot '0' is for IPv4, slot '1' is for IPv6 */ ++} t_FmPcdManipReassemIpStats; ++ ++/**************************************************************************//** ++ @Description Structure for retrieving IP fragmentation statistics ++*//***************************************************************************/ ++typedef struct t_FmPcdManipFragIpStats { ++ uint32_t totalFrames; /**< Number of frames that passed through the manipulation node */ ++ uint32_t fragmentedFrames; /**< Number of frames that were fragmented */ ++ uint32_t generatedFragments; /**< Number of fragments that were generated */ ++} t_FmPcdManipFragIpStats; ++ ++/**************************************************************************//** ++ @Description Structure for retrieving reassembly statistics ++*//***************************************************************************/ ++typedef struct t_FmPcdManipReassemStats { ++ union { ++ t_FmPcdManipReassemIpStats ipReassem; /**< Structure for IP reassembly statistics */ ++ } u; ++} t_FmPcdManipReassemStats; ++ ++/**************************************************************************//** ++ @Description Structure for retrieving fragmentation statistics ++*//***************************************************************************/ ++typedef struct t_FmPcdManipFragStats { ++ union { ++ t_FmPcdManipFragIpStats ipFrag; /**< Structure for IP fragmentation statistics */ ++ } u; ++} t_FmPcdManipFragStats; ++ ++/**************************************************************************//** ++ @Description Structure for selecting manipulation statistics ++*//***************************************************************************/ ++typedef struct t_FmPcdManipStats { ++ union { ++ t_FmPcdManipReassemStats reassem; /**< Structure for reassembly statistics */ ++ t_FmPcdManipFragStats frag; /**< Structure for fragmentation statistics */ ++ } u; ++} t_FmPcdManipStats; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Parameters for defining frame replicator group and its members ++*//***************************************************************************/ ++typedef struct t_FmPcdFrmReplicGroupParams { ++ uint8_t maxNumOfEntries; /**< Maximal number of members in the group; ++ Must be at least 2. */ ++ uint8_t numOfEntries; /**< Number of members in the group; ++ Must be at least 1. */ ++ t_FmPcdCcNextEngineParams nextEngineParams[FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES]; ++ /**< Array of members' parameters */ ++} t_FmPcdFrmReplicGroupParams; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++/**************************************************************************//** ++ @Description structure for defining statistics node ++*//***************************************************************************/ ++typedef struct t_FmPcdStatsParams { ++ e_FmPcdStatsType type; /**< type of statistics node */ ++} t_FmPcdStatsParams; ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++ ++/**************************************************************************//** ++ @Function FM_PCD_NetEnvCharacteristicsSet ++ ++ @Description Define a set of Network Environment Characteristics. ++ ++ When setting an environment it is important to understand its ++ application. It is not meant to describe the flows that will run ++ on the ports using this environment, but what the user means TO DO ++ with the PCD mechanisms in order to parse-classify-distribute those ++ frames. ++ By specifying a distinction unit, the user means it would use that option ++ for distinction between frames at either a KeyGen scheme or a coarse ++ classification action descriptor. Using interchangeable headers to define a ++ unit means that the user is indifferent to which of the interchangeable ++ headers is present in the frame, and wants the distinction to be based ++ on the presence of either one of them. ++ ++ Depending on context, there are limitations to the use of environments. A ++ port using the PCD functionality is bound to an environment. Some or even ++ all ports may share an environment but also an environment per port is ++ possible. When initializing a scheme, a classification plan group (see below), ++ or a coarse classification tree, one of the initialized environments must be ++ stated and related to. When a port is bound to a scheme, a classification ++ plan group, or a coarse classification tree, it MUST be bound to the same ++ environment. ++ ++ The different PCD modules, may relate (for flows definition) ONLY on ++ distinction units as defined by their environment. When initializing a ++ scheme for example, it may not choose to select IPV4 as a match for ++ recognizing flows unless it was defined in the relating environment. In ++ fact, to guide the user through the configuration of the PCD, each module's ++ characterization in terms of flows is not done using protocol names, but using ++ environment indexes. ++ ++ In terms of HW implementation, the list of distinction units sets the LCV vectors ++ and later used for match vector, classification plan vectors and coarse classification ++ indexing. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_NetEnvParams A structure of parameters for the initialization of ++ the network environment. ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_NetEnvCharacteristicsSet(t_Handle h_FmPcd, t_FmPcdNetEnvParams *p_NetEnvParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_NetEnvCharacteristicsDelete ++ ++ @Description Deletes a set of Network Environment Characteristics. ++ ++ @Param[in] h_NetEnv A handle to the Network environment. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PCD_NetEnvCharacteristicsDelete(t_Handle h_NetEnv); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSchemeSet ++ ++ @Description Initializing or modifying and enabling a scheme for the KeyGen. ++ This routine should be called for adding or modifying a scheme. ++ When a scheme needs modifying, the API requires that it will be ++ rewritten. In such a case 'modify' should be TRUE. If the ++ routine is called for a valid scheme and 'modify' is FALSE, ++ it will return error. ++ ++ @Param[in] h_FmPcd If this is a new scheme - A handle to an FM PCD Module. ++ Otherwise NULL (ignored by driver). ++ @Param[in,out] p_SchemeParams A structure of parameters for defining the scheme ++ ++ @Return A handle to the initialized scheme on success; NULL code otherwise. ++ When used as "modify" (rather than for setting a new scheme), ++ p_SchemeParams->id.h_Scheme will return NULL if action fails due to scheme ++ BUSY state. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_KgSchemeSet(t_Handle h_FmPcd, ++ t_FmPcdKgSchemeParams *p_SchemeParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSchemeDelete ++ ++ @Description Deleting an initialized scheme. ++ ++ @Param[in] h_Scheme scheme handle as returned by FM_PCD_KgSchemeSet() ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init() & FM_PCD_KgSchemeSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_KgSchemeDelete(t_Handle h_Scheme); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSchemeGetCounter ++ ++ @Description Reads scheme packet counter. ++ ++ @Param[in] h_Scheme scheme handle as returned by FM_PCD_KgSchemeSet(). ++ ++ @Return Counter's current value. ++ ++ @Cautions Allowed only following FM_PCD_Init() & FM_PCD_KgSchemeSet(). ++*//***************************************************************************/ ++uint32_t FM_PCD_KgSchemeGetCounter(t_Handle h_Scheme); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSchemeSetCounter ++ ++ @Description Writes scheme packet counter. ++ ++ @Param[in] h_Scheme scheme handle as returned by FM_PCD_KgSchemeSet(). ++ @Param[in] value New scheme counter value - typically '0' for ++ resetting the counter. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init() & FM_PCD_KgSchemeSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_KgSchemeSetCounter(t_Handle h_Scheme, uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrProfileSet ++ ++ @Description Sets a profile entry in the policer profile table. ++ The routine overrides any existing value. ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ @Param[in] p_Profile A structure of parameters for defining a ++ policer profile entry. ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ When used as "modify" (rather than for setting a new profile), ++ p_Profile->id.h_Profile will return NULL if action fails due to profile ++ BUSY state. ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_PlcrProfileSet(t_Handle h_FmPcd, ++ t_FmPcdPlcrProfileParams *p_Profile); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrProfileDelete ++ ++ @Description Delete a profile entry in the policer profile table. ++ The routine set entry to invalid. ++ ++ @Param[in] h_Profile A handle to the profile. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Error FM_PCD_PlcrProfileDelete(t_Handle h_Profile); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrProfileGetCounter ++ ++ @Description Sets an entry in the classification plan. ++ The routine overrides any existing value. ++ ++ @Param[in] h_Profile A handle to the profile. ++ @Param[in] counter Counter selector. ++ ++ @Return specific counter value. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++uint32_t FM_PCD_PlcrProfileGetCounter(t_Handle h_Profile, ++ e_FmPcdPlcrProfileCounters counter); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrProfileSetCounter ++ ++ @Description Sets an entry in the classification plan. ++ The routine overrides any existing value. ++ ++ @Param[in] h_Profile A handle to the profile. ++ @Param[in] counter Counter selector. ++ @Param[in] value value to set counter with. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Error FM_PCD_PlcrProfileSetCounter(t_Handle h_Profile, ++ e_FmPcdPlcrProfileCounters counter, ++ uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_PCD_CcRootBuild ++ ++ @Description This routine must be called to define a complete coarse ++ classification tree. This is the way to define coarse ++ classification to a certain flow - the KeyGen schemes ++ may point only to trees defined in this way. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_Params A structure of parameters to define the tree. ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_CcRootBuild (t_Handle h_FmPcd, ++ t_FmPcdCcTreeParams *p_Params); ++ ++/**************************************************************************//** ++ @Function FM_PCD_CcRootDelete ++ ++ @Description Deleting an built tree. ++ ++ @Param[in] h_CcTree A handle to a CC tree. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Error FM_PCD_CcRootDelete(t_Handle h_CcTree); ++ ++/**************************************************************************//** ++ @Function FM_PCD_CcRootModifyNextEngine ++ ++ @Description Modify the Next Engine Parameters in the entry of the tree. ++ ++ @Param[in] h_CcTree A handle to the tree ++ @Param[in] grpId A Group index in the tree ++ @Param[in] index Entry index in the group defined by grpId ++ @Param[in] p_FmPcdCcNextEngineParams Pointer to new next engine parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_CcBuildTree(). ++*//***************************************************************************/ ++t_Error FM_PCD_CcRootModifyNextEngine(t_Handle h_CcTree, ++ uint8_t grpId, ++ uint8_t index, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableSet ++ ++ @Description This routine should be called for each CC (coarse classification) ++ node. The whole CC tree should be built bottom up so that each ++ node points to already defined nodes. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_Param A structure of parameters defining the CC node ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_Param); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableDelete ++ ++ @Description Deleting an built node. ++ ++ @Param[in] h_CcNode A handle to a CC node. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableDelete(t_Handle h_CcNode); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableModifyMissNextEngine ++ ++ @Description Modify the Next Engine Parameters of the Miss key case of the node. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] p_FmPcdCcNextEngineParams Parameters for defining next engine ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableModifyMissNextEngine(t_Handle h_CcNode, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableRemoveKey ++ ++ @Description Remove the key (including next engine parameters of this key) ++ defined by the index of the relevant node. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for removing ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableRemoveKey(t_Handle h_CcNode, uint16_t keyIndex); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableAddKey ++ ++ @Description Add the key (including next engine parameters of this key in the ++ index defined by the keyIndex. Note that 'FM_PCD_LAST_KEY_INDEX' ++ may be used by user that don't care about the position of the ++ key in the table - in that case, the key will be automatically ++ added by the driver in the last available entry. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for adding. ++ @Param[in] keySize Key size of added key ++ @Param[in] p_KeyParams A pointer to the parameters includes ++ new key with Next Engine Parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableAddKey(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_KeyParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableModifyNextEngine ++ ++ @Description Modify the Next Engine Parameters in the relevant key entry of the node. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for Next Engine modifications ++ @Param[in] p_FmPcdCcNextEngineParams Parameters for defining next engine ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableModifyNextEngine(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableModifyKeyAndNextEngine ++ ++ @Description Modify the key and Next Engine Parameters of this key in the ++ index defined by the keyIndex. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for adding ++ @Param[in] keySize Key size of added key ++ @Param[in] p_KeyParams A pointer to the parameters includes ++ modified key and modified Next Engine Parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableModifyKeyAndNextEngine(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_KeyParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableModifyKey ++ ++ @Description Modify the key in the index defined by the keyIndex. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for adding ++ @Param[in] keySize Key size of added key ++ @Param[in] p_Key A pointer to the new key ++ @Param[in] p_Mask A pointer to the new mask if relevant, ++ otherwise pointer to NULL ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableModifyKey(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableFindNRemoveKey ++ ++ @Description Remove the key (including next engine parameters of this key) ++ defined by the key and mask. Note that this routine will search ++ the node to locate the index of the required key (& mask) to remove. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keySize Key size of the one to remove. ++ @Param[in] p_Key A pointer to the requested key to remove. ++ @Param[in] p_Mask A pointer to the mask if relevant, ++ otherwise pointer to NULL ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableFindNRemoveKey(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableFindNModifyNextEngine ++ ++ @Description Modify the Next Engine Parameters in the relevant key entry of ++ the node. Note that this routine will search the node to locate ++ the index of the required key (& mask) to modify. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keySize Key size of the one to modify. ++ @Param[in] p_Key A pointer to the requested key to modify. ++ @Param[in] p_Mask A pointer to the mask if relevant, ++ otherwise pointer to NULL ++ @Param[in] p_FmPcdCcNextEngineParams Parameters for defining next engine ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableFindNModifyNextEngine(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableFindNModifyKeyAndNextEngine ++ ++ @Description Modify the key and Next Engine Parameters of this key in the ++ index defined by the keyIndex. Note that this routine will search ++ the node to locate the index of the required key (& mask) to modify. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keySize Key size of the one to modify. ++ @Param[in] p_Key A pointer to the requested key to modify. ++ @Param[in] p_Mask A pointer to the mask if relevant, ++ otherwise pointer to NULL ++ @Param[in] p_KeyParams A pointer to the parameters includes ++ modified key and modified Next Engine Parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableFindNModifyKeyAndNextEngine(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ t_FmPcdCcKeyParams *p_KeyParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableFindNModifyKey ++ ++ @Description Modify the key in the index defined by the keyIndex. Note that ++ this routine will search the node to locate the index of the ++ required key (& mask) to modify. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keySize Key size of the one to modify. ++ @Param[in] p_Key A pointer to the requested key to modify. ++ @Param[in] p_Mask A pointer to the mask if relevant, ++ otherwise pointer to NULL ++ @Param[in] p_NewKey A pointer to the new key ++ @Param[in] p_NewMask A pointer to the new mask if relevant, ++ otherwise pointer to NULL ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableFindNModifyKey(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ uint8_t *p_NewKey, ++ uint8_t *p_NewMask); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableGetKeyCounter ++ ++ @Description This routine may be used to get a counter of specific key in a CC ++ Node; This counter reflects how many frames passed that were matched ++ this key. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for adding ++ ++ @Return The specific key counter. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++uint32_t FM_PCD_MatchTableGetKeyCounter(t_Handle h_CcNode, uint16_t keyIndex); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableGetKeyStatistics ++ ++ @Description This routine may be used to get statistics counters of specific key ++ in a CC Node. ++ ++ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and ++ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, ++ these counters reflect how many frames passed that were matched ++ this key; The total frames count will be returned in the counter ++ of the first range (as only one frame length range was defined). ++ If 'e_FM_PCD_CC_STATS_MODE_RMON' was set for this node, the total ++ frame count will be separated to frame length counters, based on ++ provided frame length ranges. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for adding ++ @Param[out] p_KeyStatistics Key statistics counters ++ ++ @Return The specific key statistics. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableGetKeyStatistics(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableFindNGetKeyStatistics ++ ++ @Description This routine may be used to get statistics counters of specific key ++ in a CC Node. ++ ++ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and ++ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, ++ these counters reflect how many frames passed that were matched ++ this key; The total frames count will be returned in the counter ++ of the first range (as only one frame length range was defined). ++ If 'e_FM_PCD_CC_STATS_MODE_RMON' was set for this node, the total ++ frame count will be separated to frame length counters, based on ++ provided frame length ranges. ++ Note that this routine will search the node to locate the index ++ of the required key based on received key parameters. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keySize Size of the requested key ++ @Param[in] p_Key A pointer to the requested key ++ @Param[in] p_Mask A pointer to the mask if relevant, ++ otherwise pointer to NULL ++ @Param[out] p_KeyStatistics Key statistics counters ++ ++ @Return The specific key statistics. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableFindNGetKeyStatistics(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics); ++ ++/**************************************************************************//* ++ @Function FM_PCD_MatchTableGetNextEngine ++ ++ @Description Gets NextEngine of the relevant keyIndex. ++ ++ @Param[in] h_CcNode A handle to the node. ++ @Param[in] keyIndex keyIndex in the relevant node. ++ @Param[out] p_FmPcdCcNextEngineParams here updated nextEngine parameters for ++ the relevant keyIndex of the CC Node ++ received as parameter to this function ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableGetNextEngine(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//* ++ @Function FM_PCD_MatchTableGetIndexedHashBucket ++ ++ @Description This routine simulates KeyGen operation on the provided key and ++ calculates to which hash bucket it will be mapped. ++ ++ @Param[in] h_CcNode A handle to the node. ++ @Param[in] kgKeySize Key size as it was configured in the KG ++ scheme that leads to this hash. ++ @Param[in] p_KgKey Pointer to the key; must be like the key ++ that the KG is generated, i.e. the same ++ extraction and with mask if exist. ++ @Param[in] kgHashShift Hash-shift as it was configured in the KG ++ scheme that leads to this hash. ++ @Param[out] p_CcNodeBucketHandle Pointer to the bucket of the provided key. ++ @Param[out] p_BucketIndex Index to the bucket of the provided key ++ @Param[out] p_LastIndex Pointer to last index in the bucket of the ++ provided key. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet() ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableGetIndexedHashBucket(t_Handle h_CcNode, ++ uint8_t kgKeySize, ++ uint8_t *p_KgKey, ++ uint8_t kgHashShift, ++ t_Handle *p_CcNodeBucketHandle, ++ uint8_t *p_BucketIndex, ++ uint16_t *p_LastIndex); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableSet ++ ++ @Description This routine initializes a hash table structure. ++ KeyGen hash result determines the hash bucket. ++ Next, KeyGen key is compared against all keys of this ++ bucket (exact match). ++ Number of sets (number of buckets) of the hash equals to the ++ number of 1-s in 'hashResMask' in the provided parameters. ++ Number of hash table ways is then calculated by dividing ++ 'maxNumOfKeys' equally between the hash sets. This is the maximal ++ number of keys that a hash bucket may hold. ++ The hash table is initialized empty and keys may be ++ added to it following the initialization. Keys masks are not ++ supported in current hash table implementation. ++ The initialized hash table can be integrated as a node in a ++ CC tree. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_Param A structure of parameters defining the hash table ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableDelete ++ ++ @Description This routine deletes the provided hash table and released all ++ its allocated resources. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableDelete(t_Handle h_HashTbl); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableAddKey ++ ++ @Description This routine adds the provided key (including next engine ++ parameters of this key) to the hash table. ++ The key is added as the last key of the bucket that it is ++ mapped to. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[in] keySize Key size of added key ++ @Param[in] p_KeyParams A pointer to the parameters includes ++ new key with next engine parameters; The pointer ++ to the key mask must be NULL, as masks are not ++ supported in hash table implementation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableAddKey(t_Handle h_HashTbl, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_KeyParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableRemoveKey ++ ++ @Description This routine removes the requested key (including next engine ++ parameters of this key) from the hash table. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[in] keySize Key size of the one to remove. ++ @Param[in] p_Key A pointer to the requested key to remove. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableRemoveKey(t_Handle h_HashTbl, ++ uint8_t keySize, ++ uint8_t *p_Key); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableModifyNextEngine ++ ++ @Description This routine modifies the next engine for the provided key. The ++ key should be previously added to the hash table. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[in] keySize Key size of the key to modify. ++ @Param[in] p_Key A pointer to the requested key to modify. ++ @Param[in] p_FmPcdCcNextEngineParams A structure for defining new next engine ++ parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableModifyNextEngine(t_Handle h_HashTbl, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableModifyMissNextEngine ++ ++ @Description This routine modifies the next engine on key match miss. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[in] p_FmPcdCcNextEngineParams A structure for defining new next engine ++ parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableModifyMissNextEngine(t_Handle h_HashTbl, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//* ++ @Function FM_PCD_HashTableGetMissNextEngine ++ ++ @Description Gets NextEngine in case of key match miss. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[out] p_FmPcdCcNextEngineParams Next engine parameters for the specified ++ hash table. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableGetMissNextEngine(t_Handle h_HashTbl, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableFindNGetKeyStatistics ++ ++ @Description This routine may be used to get statistics counters of specific key ++ in a hash table. ++ ++ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and ++ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, ++ these counters reflect how many frames passed that were matched ++ this key; The total frames count will be returned in the counter ++ of the first range (as only one frame length range was defined). ++ If 'e_FM_PCD_CC_STATS_MODE_RMON' was set for this node, the total ++ frame count will be separated to frame length counters, based on ++ provided frame length ranges. ++ Note that this routine will identify the bucket of this key in ++ the hash table and will search the bucket to locate the index ++ of the required key based on received key parameters. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[in] keySize Size of the requested key ++ @Param[in] p_Key A pointer to the requested key ++ @Param[out] p_KeyStatistics Key statistics counters ++ ++ @Return The specific key statistics. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableFindNGetKeyStatistics(t_Handle h_HashTbl, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ManipNodeSet ++ ++ @Description This routine should be called for defining a manipulation ++ node. A manipulation node must be defined before the CC node ++ that precedes it. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_FmPcdManipParams A structure of parameters defining the manipulation ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_ManipNodeSet(t_Handle h_FmPcd, t_FmPcdManipParams *p_FmPcdManipParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ManipNodeDelete ++ ++ @Description Delete an existing manipulation node. ++ ++ @Param[in] h_ManipNode A handle to a manipulation node. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_ManipNodeSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_ManipNodeDelete(t_Handle h_ManipNode); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ManipGetStatistics ++ ++ @Description Retrieve the manipulation statistics. ++ ++ @Param[in] h_ManipNode A handle to a manipulation node. ++ @Param[out] p_FmPcdManipStats A structure for retrieving the manipulation statistics ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_ManipNodeSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_ManipGetStatistics(t_Handle h_ManipNode, t_FmPcdManipStats *p_FmPcdManipStats); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ManipNodeReplace ++ ++ @Description Change existing manipulation node to be according to new requirement. ++ ++ @Param[in] h_ManipNode A handle to a manipulation node. ++ @Param[out] p_ManipParams A structure of parameters defining the change requirement ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_ManipNodeSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_ManipNodeReplace(t_Handle h_ManipNode, t_FmPcdManipParams *p_ManipParams); ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Function FM_PCD_FrmReplicSetGroup ++ ++ @Description Initialize a Frame Replicator group. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_FrmReplicGroupParam A structure of parameters for the initialization of ++ the frame replicator group. ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_FrmReplicSetGroup(t_Handle h_FmPcd, t_FmPcdFrmReplicGroupParams *p_FrmReplicGroupParam); ++ ++/**************************************************************************//** ++ @Function FM_PCD_FrmReplicDeleteGroup ++ ++ @Description Delete a Frame Replicator group. ++ ++ @Param[in] h_FrmReplicGroup A handle to the frame replicator group. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_FrmReplicSetGroup(). ++*//***************************************************************************/ ++t_Error FM_PCD_FrmReplicDeleteGroup(t_Handle h_FrmReplicGroup); ++ ++/**************************************************************************//** ++ @Function FM_PCD_FrmReplicAddMember ++ ++ @Description Add the member in the index defined by the memberIndex. ++ ++ @Param[in] h_FrmReplicGroup A handle to the frame replicator group. ++ @Param[in] memberIndex member index for adding. ++ @Param[in] p_MemberParams A pointer to the new member parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_FrmReplicSetGroup() of this group. ++*//***************************************************************************/ ++t_Error FM_PCD_FrmReplicAddMember(t_Handle h_FrmReplicGroup, ++ uint16_t memberIndex, ++ t_FmPcdCcNextEngineParams *p_MemberParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_FrmReplicRemoveMember ++ ++ @Description Remove the member defined by the index from the relevant group. ++ ++ @Param[in] h_FrmReplicGroup A handle to the frame replicator group. ++ @Param[in] memberIndex member index for removing. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_FrmReplicSetGroup() of this group. ++*//***************************************************************************/ ++t_Error FM_PCD_FrmReplicRemoveMember(t_Handle h_FrmReplicGroup, ++ uint16_t memberIndex); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++/**************************************************************************//** ++ @Function FM_PCD_StatisticsSetNode ++ ++ @Description This routine should be called for defining a statistics node. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_FmPcdstatsParams A structure of parameters defining the statistics ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_StatisticsSetNode(t_Handle h_FmPcd, t_FmPcdStatsParams *p_FmPcdstatsParams); ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++/** @} */ /* end of FM_PCD_Runtime_build_grp group */ ++/** @} */ /* end of FM_PCD_Runtime_grp group */ ++/** @} */ /* end of FM_PCD_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#ifdef NCSW_BACKWARD_COMPATIBLE_API ++#define FM_PCD_MAX_NUM_OF_INTERCHANGABLE_HDRS FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS ++#define e_FM_PCD_MANIP_ONE_WAYS_HASH e_FM_PCD_MANIP_ONE_WAY_HASH ++#define e_FM_PCD_MANIP_TOW_WAYS_HASH e_FM_PCD_MANIP_TWO_WAYS_HASH ++ ++#define FM_PCD_SetNetEnvCharacteristics(_pcd, _params) \ ++ FM_PCD_NetEnvCharacteristicsSet(_pcd, _params) ++#define FM_PCD_KgSetScheme(_pcd, _params) FM_PCD_KgSchemeSet(_pcd, _params) ++#define FM_PCD_CcBuildTree(_pcd, _params) FM_PCD_CcRootBuild(_pcd, _params) ++#define FM_PCD_CcSetNode(_pcd, _params) FM_PCD_MatchTableSet(_pcd, _params) ++#define FM_PCD_PlcrSetProfile(_pcd, _params) FM_PCD_PlcrProfileSet(_pcd, _params) ++#define FM_PCD_ManipSetNode(_pcd, _params) FM_PCD_ManipNodeSet(_pcd, _params) ++ ++#define FM_PCD_DeleteNetEnvCharacteristics(_pcd, ...) \ ++ FM_PCD_NetEnvCharacteristicsDelete(__VA_ARGS__) ++#define FM_PCD_KgDeleteScheme(_pcd, ...) \ ++ FM_PCD_KgSchemeDelete(__VA_ARGS__) ++#define FM_PCD_KgGetSchemeCounter(_pcd, ...) \ ++ FM_PCD_KgSchemeGetCounter(__VA_ARGS__) ++#define FM_PCD_KgSetSchemeCounter(_pcd, ...) \ ++ FM_PCD_KgSchemeSetCounter(__VA_ARGS__) ++#define FM_PCD_PlcrDeleteProfile(_pcd, ...) \ ++ FM_PCD_PlcrProfileDelete(__VA_ARGS__) ++#define FM_PCD_PlcrGetProfileCounter(_pcd, ...) \ ++ FM_PCD_PlcrProfileGetCounter(__VA_ARGS__) ++#define FM_PCD_PlcrSetProfileCounter(_pcd, ...) \ ++ FM_PCD_PlcrProfileSetCounter(__VA_ARGS__) ++#define FM_PCD_CcDeleteTree(_pcd, ...) \ ++ FM_PCD_CcRootDelete(__VA_ARGS__) ++#define FM_PCD_CcTreeModifyNextEngine(_pcd, ...) \ ++ FM_PCD_CcRootModifyNextEngine(__VA_ARGS__) ++#define FM_PCD_CcDeleteNode(_pcd, ...) \ ++ FM_PCD_MatchTableDelete(__VA_ARGS__) ++#define FM_PCD_CcNodeModifyMissNextEngine(_pcd, ...) \ ++ FM_PCD_MatchTableModifyMissNextEngine(__VA_ARGS__) ++#define FM_PCD_CcNodeRemoveKey(_pcd, ...) \ ++ FM_PCD_MatchTableRemoveKey(__VA_ARGS__) ++#define FM_PCD_CcNodeAddKey(_pcd, ...) \ ++ FM_PCD_MatchTableAddKey(__VA_ARGS__) ++#define FM_PCD_CcNodeModifyNextEngine(_pcd, ...) \ ++ FM_PCD_MatchTableModifyNextEngine(__VA_ARGS__) ++#define FM_PCD_CcNodeModifyKeyAndNextEngine(_pcd, ...) \ ++ FM_PCD_MatchTableModifyKeyAndNextEngine(__VA_ARGS__) ++#define FM_PCD_CcNodeModifyKey(_pcd, ...) \ ++ FM_PCD_MatchTableModifyKey(__VA_ARGS__) ++#define FM_PCD_CcNodeFindNRemoveKey(_pcd, ...) \ ++ FM_PCD_MatchTableFindNRemoveKey(__VA_ARGS__) ++#define FM_PCD_CcNodeFindNModifyNextEngine(_pcd, ...) \ ++ FM_PCD_MatchTableFindNModifyNextEngine(__VA_ARGS__) ++#define FM_PCD_CcNodeFindNModifyKeyAndNextEngine(_pcd, ...) \ ++ FM_PCD_MatchTableFindNModifyKeyAndNextEngine(__VA_ARGS__) ++#define FM_PCD_CcNodeFindNModifyKey(_pcd, ...) \ ++ FM_PCD_MatchTableFindNModifyKey(__VA_ARGS__) ++#define FM_PCD_CcIndexedHashNodeGetBucket(_pcd, ...) \ ++ FM_PCD_MatchTableGetIndexedHashBucket(__VA_ARGS__) ++#define FM_PCD_CcNodeGetNextEngine(_pcd, ...) \ ++ FM_PCD_MatchTableGetNextEngine(__VA_ARGS__) ++#define FM_PCD_CcNodeGetKeyCounter(_pcd, ...) \ ++ FM_PCD_MatchTableGetKeyCounter(__VA_ARGS__) ++#define FM_PCD_ManipDeleteNode(_pcd, ...) \ ++ FM_PCD_ManipNodeDelete(__VA_ARGS__) ++#endif /* NCSW_BACKWARD_COMPATIBLE_API */ ++ ++ ++#endif /* __FM_PCD_EXT */ +diff --git a/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_port_ext.h b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_port_ext.h +new file mode 100644 +index 0000000..afa2cd9 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_port_ext.h +@@ -0,0 +1,2247 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_port_ext.h ++ ++ @Description FM-Port Application Programming Interface. ++*//***************************************************************************/ ++#ifndef __FM_PORT_EXT ++#define __FM_PORT_EXT ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_ext.h" ++#include "net_ext.h" ++ ++ ++/**************************************************************************//** ++ ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_PORT_grp FM Port ++ ++ @Description FM Port API ++ ++ The FM uses a general module called "port" to represent a Tx port ++ (MAC), an Rx port (MAC) or Offline Parsing port. ++ The number of ports in an FM varies between SOCs. ++ The SW driver manages these ports as sub-modules of the FM, i.e. ++ after an FM is initialized, its ports may be initialized and ++ operated upon. ++ ++ The port is initialized aware of its type, but other functions on ++ a port may be indifferent to its type. When necessary, the driver ++ verifies coherence and returns error if applicable. ++ ++ On initialization, user specifies the port type and it's index ++ (relative to the port's type) - always starting at 0. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description An enum for defining port PCD modes. ++ This enum defines the superset of PCD engines support - i.e. not ++ all engines have to be used, but all have to be enabled. The real ++ flow of a specific frame depends on the PCD configuration and the ++ frame headers and payload. ++ Note: the first engine and the first engine after the parser (if ++ exists) should be in order, the order is important as it will ++ define the flow of the port. However, as for the rest engines ++ (the ones that follows), the order is not important anymore as ++ it is defined by the PCD graph itself. ++*//***************************************************************************/ ++typedef enum e_FmPortPcdSupport { ++ e_FM_PORT_PCD_SUPPORT_NONE = 0 /**< BMI to BMI, PCD is not used */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_ONLY /**< Use only Parser */ ++ , e_FM_PORT_PCD_SUPPORT_PLCR_ONLY /**< Use only Policer */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR /**< Use Parser and Policer */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_KG /**< Use Parser and Keygen */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC /**< Use Parser, Keygen and Coarse Classification */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR ++ /**< Use all PCD engines */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR /**< Use Parser, Keygen and Policer */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_CC /**< Use Parser and Coarse Classification */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_CC_AND_PLCR /**< Use Parser and Coarse Classification and Policer */ ++#ifdef FM_CAPWAP_SUPPORT ++ , e_FM_PORT_PCD_SUPPORT_CC_ONLY /**< Use only Coarse Classification */ ++ , e_FM_PORT_PCD_SUPPORT_CC_AND_KG /**< Use Coarse Classification,and Keygen */ ++ , e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR /**< Use Coarse Classification, Keygen and Policer */ ++#endif /* FM_CAPWAP_SUPPORT */ ++} e_FmPortPcdSupport; ++ ++/**************************************************************************//** ++ @Description Port interrupts ++*//***************************************************************************/ ++typedef enum e_FmPortExceptions { ++ e_FM_PORT_EXCEPTION_IM_BUSY /**< Independent-Mode Rx-BUSY */ ++} e_FmPortExceptions; ++ ++ ++/**************************************************************************//** ++ @Collection General FM Port defines ++*//***************************************************************************/ ++#define FM_PORT_PRS_RESULT_NUM_OF_WORDS 8 /**< Number of 4 bytes words in parser result */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection FM Frame error ++*//***************************************************************************/ ++typedef uint32_t fmPortFrameErrSelect_t; /**< typedef for defining Frame Descriptor errors */ ++ ++#define FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT FM_FD_ERR_UNSUPPORTED_FORMAT /**< Not for Rx-Port! Unsupported Format */ ++#define FM_PORT_FRM_ERR_LENGTH FM_FD_ERR_LENGTH /**< Not for Rx-Port! Length Error */ ++#define FM_PORT_FRM_ERR_DMA FM_FD_ERR_DMA /**< DMA Data error */ ++#define FM_PORT_FRM_ERR_NON_FM FM_FD_RX_STATUS_ERR_NON_FM /**< non Frame-Manager error; probably come from SEC that ++ was chained to FM */ ++ ++#define FM_PORT_FRM_ERR_IPRE (FM_FD_ERR_IPR & ~FM_FD_IPR) /**< IPR error */ ++#define FM_PORT_FRM_ERR_IPR_NCSP (FM_FD_ERR_IPR_NCSP & ~FM_FD_IPR) /**< IPR non-consistent-sp */ ++ ++#define FM_PORT_FRM_ERR_IPFE 0 /**< Obsolete; will be removed in the future */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++#define FM_PORT_FRM_ERR_CRE FM_FD_ERR_CRE ++#define FM_PORT_FRM_ERR_CHE FM_FD_ERR_CHE ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++#define FM_PORT_FRM_ERR_PHYSICAL FM_FD_ERR_PHYSICAL /**< Rx FIFO overflow, FCS error, code error, running disparity ++ error (SGMII and TBI modes), FIFO parity error. PHY ++ Sequence error, PHY error control character detected. */ ++#define FM_PORT_FRM_ERR_SIZE FM_FD_ERR_SIZE /**< Frame too long OR Frame size exceeds max_length_frame */ ++#define FM_PORT_FRM_ERR_CLS_DISCARD FM_FD_ERR_CLS_DISCARD /**< classification discard */ ++#define FM_PORT_FRM_ERR_EXTRACTION FM_FD_ERR_EXTRACTION /**< Extract Out of Frame */ ++#define FM_PORT_FRM_ERR_NO_SCHEME FM_FD_ERR_NO_SCHEME /**< No Scheme Selected */ ++#define FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW FM_FD_ERR_KEYSIZE_OVERFLOW /**< Keysize Overflow */ ++#define FM_PORT_FRM_ERR_COLOR_RED FM_FD_ERR_COLOR_RED /**< Frame color is red */ ++#define FM_PORT_FRM_ERR_COLOR_YELLOW FM_FD_ERR_COLOR_YELLOW /**< Frame color is yellow */ ++#define FM_PORT_FRM_ERR_ILL_PLCR FM_FD_ERR_ILL_PLCR /**< Illegal Policer Profile selected */ ++#define FM_PORT_FRM_ERR_PLCR_FRAME_LEN FM_FD_ERR_PLCR_FRAME_LEN /**< Policer frame length error */ ++#define FM_PORT_FRM_ERR_PRS_TIMEOUT FM_FD_ERR_PRS_TIMEOUT /**< Parser Time out Exceed */ ++#define FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT FM_FD_ERR_PRS_ILL_INSTRUCT /**< Invalid Soft Parser instruction */ ++#define FM_PORT_FRM_ERR_PRS_HDR_ERR FM_FD_ERR_PRS_HDR_ERR /**< Header error was identified during parsing */ ++#define FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED FM_FD_ERR_BLOCK_LIMIT_EXCEEDED /**< Frame parsed beyind 256 first bytes */ ++#define FM_PORT_FRM_ERR_PROCESS_TIMEOUT 0x00000001 /**< FPM Frame Processing Timeout Exceeded */ ++/* @} */ ++ ++ ++ ++/**************************************************************************//** ++ @Group FM_PORT_init_grp FM Port Initialization Unit ++ ++ @Description FM Port Initialization Unit ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Exceptions user callback routine, will be called upon an ++ exception passing the exception identification. ++ ++ @Param[in] h_App - User's application descriptor. ++ @Param[in] exception - The exception. ++ *//***************************************************************************/ ++typedef void (t_FmPortExceptionCallback) (t_Handle h_App, e_FmPortExceptions exception); ++ ++/**************************************************************************//** ++ @Description User callback function called by driver with received data. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_App Application's handle originally specified to ++ the API Config function ++ @Param[in] p_Data A pointer to data received ++ @Param[in] length length of received data ++ @Param[in] status receive status and errors ++ @Param[in] position position of buffer in frame ++ @Param[in] h_BufContext A handle of the user acossiated with this buffer ++ ++ @Retval e_RX_STORE_RESPONSE_CONTINUE - order the driver to continue Rx ++ operation for all ready data. ++ @Retval e_RX_STORE_RESPONSE_PAUSE - order the driver to stop Rx operation. ++*//***************************************************************************/ ++typedef e_RxStoreResponse (t_FmPortImRxStoreCallback) (t_Handle h_App, ++ uint8_t *p_Data, ++ uint16_t length, ++ uint16_t status, ++ uint8_t position, ++ t_Handle h_BufContext); ++ ++/**************************************************************************//** ++ @Description User callback function called by driver when transmit completed. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_App Application's handle originally specified to ++ the API Config function ++ @Param[in] p_Data A pointer to data received ++ @Param[in] status transmit status and errors ++ @Param[in] lastBuffer is last buffer in frame ++ @Param[in] h_BufContext A handle of the user acossiated with this buffer ++ *//***************************************************************************/ ++typedef void (t_FmPortImTxConfCallback) (t_Handle h_App, ++ uint8_t *p_Data, ++ uint16_t status, ++ t_Handle h_BufContext); ++ ++/**************************************************************************//** ++ @Description A structure for additional Rx port parameters ++*//***************************************************************************/ ++typedef struct t_FmPortRxParams { ++ uint32_t errFqid; /**< Error Queue Id. */ ++ uint32_t dfltFqid; /**< Default Queue Id. */ ++ uint16_t liodnOffset; /**< Port's LIODN offset. */ ++ t_FmExtPools extBufPools; /**< Which external buffer pools are used ++ (up to FM_PORT_MAX_NUM_OF_EXT_POOLS), and their sizes. */ ++} t_FmPortRxParams; ++ ++/**************************************************************************//** ++ @Description A structure for additional non-Rx port parameters ++*//***************************************************************************/ ++typedef struct t_FmPortNonRxParams { ++ uint32_t errFqid; /**< Error Queue Id. */ ++ uint32_t dfltFqid; /**< For Tx - Default Confirmation queue, ++ 0 means no Tx confirmation for processed ++ frames. For OP port - default Rx queue. */ ++ uint32_t qmChannel; /**< QM-channel dedicated to this port; will be used ++ by the FM for dequeue. */ ++} t_FmPortNonRxParams; ++ ++/**************************************************************************//** ++ @Description A structure for additional Rx port parameters ++*//***************************************************************************/ ++typedef struct t_FmPortImRxTxParams { ++ t_Handle h_FmMuram; /**< A handle of the FM-MURAM partition */ ++ uint16_t liodnOffset; /**< For Rx ports only. Port's LIODN Offset. */ ++ uint8_t dataMemId; /**< Memory partition ID for data buffers */ ++ uint32_t dataMemAttributes; /**< Memory attributes for data buffers */ ++ t_BufferPoolInfo rxPoolParams; /**< For Rx ports only. */ ++ t_FmPortImRxStoreCallback *f_RxStore; /**< For Rx ports only. */ ++ t_FmPortImTxConfCallback *f_TxConf; /**< For Tx ports only. */ ++} t_FmPortImRxTxParams; ++ ++/**************************************************************************//** ++ @Description A union for additional parameters depending on port type ++*//***************************************************************************/ ++typedef union u_FmPortSpecificParams { ++ t_FmPortImRxTxParams imRxTxParams; /**< Rx/Tx Independent-Mode port parameter structure */ ++ t_FmPortRxParams rxParams; /**< Rx port parameters structure */ ++ t_FmPortNonRxParams nonRxParams; /**< Non-Rx port parameters structure */ ++} u_FmPortSpecificParams; ++ ++/**************************************************************************//** ++ @Description A structure representing FM initialization parameters ++*//***************************************************************************/ ++typedef struct t_FmPortParams { ++ uintptr_t baseAddr; /**< Virtual Address of memory mapped FM Port registers.*/ ++ t_Handle h_Fm; /**< A handle to the FM object this port related to */ ++ e_FmPortType portType; /**< Port type */ ++ uint8_t portId; /**< Port Id - relative to type; ++ NOTE: When configuring Offline Parsing port for ++ FMANv3 devices (DPAA_VERSION 11 and higher), ++ it is highly recommended NOT to use portId=0 due to lack ++ of HW resources on portId=0. */ ++ bool independentModeEnable; ++ /**< This port is Independent-Mode - Used for Rx/Tx ports only! */ ++ uint16_t liodnBase; /**< Irrelevant for P4080 rev 1. LIODN base for this port, to be ++ used together with LIODN offset. */ ++ u_FmPortSpecificParams specificParams; /**< Additional parameters depending on port ++ type. */ ++ ++ t_FmPortExceptionCallback *f_Exception; /**< Relevant for IM only Callback routine to be called on BUSY exception */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks */ ++} t_FmPortParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_PORT_Config ++ ++ @Description Creates a descriptor for the FM PORT module. ++ ++ The routine returns a handle (descriptor) to the FM PORT object. ++ This descriptor must be passed as first parameter to all other ++ FM PORT function calls. ++ ++ No actual initialization or configuration of FM hardware is ++ done by this routine. ++ ++ @Param[in] p_FmPortParams - Pointer to data structure of parameters ++ ++ @Retval Handle to FM object, or NULL for Failure. ++*//***************************************************************************/ ++t_Handle FM_PORT_Config(t_FmPortParams *p_FmPortParams); ++ ++/**************************************************************************//** ++ @Function FM_PORT_Init ++ ++ @Description Initializes the FM PORT module by defining the software structure ++ and configuring the hardware registers. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PORT_Init(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_Free ++ ++ @Description Frees all resources that were assigned to FM PORT module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PORT_Free(t_Handle h_FmPort); ++ ++ ++/**************************************************************************//** ++ @Group FM_PORT_advanced_init_grp FM Port Advanced Configuration Unit ++ ++ @Description Configuration functions used to change default values. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description enum for defining QM frame dequeue ++*//***************************************************************************/ ++typedef enum e_FmPortDeqType { ++ e_FM_PORT_DEQ_TYPE1, /**< Dequeue from the SP channel - with priority precedence, ++ and Intra-Class Scheduling respected. */ ++ e_FM_PORT_DEQ_TYPE2, /**< Dequeue from the SP channel - with active FQ precedence, ++ and Intra-Class Scheduling respected. */ ++ e_FM_PORT_DEQ_TYPE3 /**< Dequeue from the SP channel - with active FQ precedence, ++ and override Intra-Class Scheduling */ ++} e_FmPortDeqType; ++ ++/**************************************************************************//** ++ @Description enum for defining QM frame dequeue ++*//***************************************************************************/ ++typedef enum e_FmPortDeqPrefetchOption { ++ e_FM_PORT_DEQ_NO_PREFETCH, /**< QMI preforms a dequeue action for a single frame ++ only when a dedicated portID Tnum is waiting. */ ++ e_FM_PORT_DEQ_PARTIAL_PREFETCH, /**< QMI preforms a dequeue action for 3 frames when ++ one dedicated portId tnum is waiting. */ ++ e_FM_PORT_DEQ_FULL_PREFETCH /**< QMI preforms a dequeue action for 3 frames when ++ no dedicated portId tnums are waiting. */ ++ ++} e_FmPortDeqPrefetchOption; ++ ++/**************************************************************************//** ++ @Description enum for defining port default color ++*//***************************************************************************/ ++typedef enum e_FmPortColor { ++ e_FM_PORT_COLOR_GREEN, /**< Default port color is green */ ++ e_FM_PORT_COLOR_YELLOW, /**< Default port color is yellow */ ++ e_FM_PORT_COLOR_RED, /**< Default port color is red */ ++ e_FM_PORT_COLOR_OVERRIDE /**< Ignore color */ ++} e_FmPortColor; ++ ++/**************************************************************************//** ++ @Description A structure for defining Dual Tx rate limiting scale ++*//***************************************************************************/ ++typedef enum e_FmPortDualRateLimiterScaleDown { ++ e_FM_PORT_DUAL_RATE_LIMITER_NONE = 0, /**< Use only single rate limiter */ ++ e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_2, /**< Divide high rate limiter by 2 */ ++ e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_4, /**< Divide high rate limiter by 4 */ ++ e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8 /**< Divide high rate limiter by 8 */ ++} e_FmPortDualRateLimiterScaleDown; ++ ++ ++/**************************************************************************//** ++ @Description A structure for defining FM port resources ++*//***************************************************************************/ ++typedef struct t_FmPortRsrc { ++ uint32_t num; /**< Committed required resource */ ++ uint32_t extra; /**< Extra (not committed) required resource */ ++} t_FmPortRsrc; ++ ++/**************************************************************************//** ++ @Description A structure for defining observed pool depletion ++*//***************************************************************************/ ++typedef struct t_FmPortObservedBufPoolDepletion { ++ t_FmBufPoolDepletion poolDepletionParams;/**< parameters to define pool depletion */ ++ t_FmExtPools poolsParams; /**< Which external buffer pools are observed ++ (up to FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS), ++ and their sizes. */ ++} t_FmPortObservedBufPoolDepletion; ++ ++/**************************************************************************//** ++ @Description A structure for defining Tx rate limiting ++*//***************************************************************************/ ++typedef struct t_FmPortRateLimit { ++ uint16_t maxBurstSize; /**< in KBytes for Tx ports, in frames ++ for OP ports. (note that ++ for early chips burst size is ++ rounded up to a multiply of 1000 frames).*/ ++ uint32_t rateLimit; /**< in Kb/sec for Tx ports, in frame/sec for ++ OP ports. Rate limit refers to ++ data rate (rather than line rate). */ ++ e_FmPortDualRateLimiterScaleDown rateLimitDivider; /**< For OP ports only. Not-valid ++ for some earlier chip revisions */ ++} t_FmPortRateLimit; ++ ++/**************************************************************************//** ++ @Description A structure for defining the parameters of ++ the Rx port performance counters ++*//***************************************************************************/ ++typedef struct t_FmPortPerformanceCnt { ++ uint8_t taskCompVal; /**< Task compare value */ ++ uint8_t queueCompVal; /**< Rx queue/Tx confirm queue compare ++ value (unused for H/O) */ ++ uint8_t dmaCompVal; /**< Dma compare value */ ++ uint32_t fifoCompVal; /**< Fifo compare value (in bytes) */ ++} t_FmPortPerformanceCnt; ++ ++ ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigNumOfOpenDmas ++ ++ @Description Calling this routine changes the max number of open DMA's ++ available for this port. It changes this parameter in the ++ internal driver data base from its default configuration ++ [OP: 1] ++ [1G-RX, 1G-TX: 1 (+1)] ++ [10G-RX, 10G-TX: 8 (+8)] ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_OpenDmas A pointer to a structure of parameters defining ++ the open DMA allocation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_OpenDmas); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigNumOfTasks ++ ++ @Description Calling this routine changes the max number of tasks ++ available for this port. It changes this parameter in the ++ internal driver data base from its default configuration ++ [OP: 1] ++ [1G-RX, 1G-TX: 3 (+2)] ++ [10G-RX, 10G-TX: 16 (+8)] ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_NumOfTasks A pointer to a structure of parameters defining ++ the tasks allocation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigSizeOfFifo ++ ++ @Description Calling this routine changes the max FIFO size configured for this port. ++ ++ This function changes the internal driver data base from its ++ default configuration. Please refer to the driver's User Guide for ++ information on default FIFO sizes in the various devices. ++ [OP: 2KB] ++ [1G-RX, 1G-TX: 11KB] ++ [10G-RX, 10G-TX: 12KB] ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_SizeOfFifo A pointer to a structure of parameters defining ++ the FIFO allocation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDeqHighPriority ++ ++ @Description Calling this routine changes the dequeue priority in the ++ internal driver data base from its default configuration ++ 1G: [FALSE] ++ 10G: [TRUE] ++ ++ May be used for Non-Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] highPri TRUE to select high priority, FALSE for normal operation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDeqHighPriority(t_Handle h_FmPort, bool highPri); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDeqType ++ ++ @Description Calling this routine changes the dequeue type parameter in the ++ internal driver data base from its default configuration ++ [e_FM_PORT_DEQ_TYPE1]. ++ ++ May be used for Non-Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] deqType According to QM definition. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDeqType(t_Handle h_FmPort, e_FmPortDeqType deqType); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDeqPrefetchOption ++ ++ @Description Calling this routine changes the dequeue prefetch option parameter in the ++ internal driver data base from its default configuration ++ [e_FM_PORT_DEQ_FULL_PREFETCH] ++ Note: Available for some chips only ++ ++ May be used for Non-Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] deqPrefetchOption New option ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDeqPrefetchOption(t_Handle h_FmPort, e_FmPortDeqPrefetchOption deqPrefetchOption); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDeqByteCnt ++ ++ @Description Calling this routine changes the dequeue byte count parameter in ++ the internal driver data base from its default configuration ++ 1G:[0x400]. ++ 10G:[0x1400]. ++ ++ May be used for Non-Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] deqByteCnt New byte count ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDeqByteCnt(t_Handle h_FmPort, uint16_t deqByteCnt); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigBufferPrefixContent ++ ++ @Description Defines the structure, size and content of the application buffer. ++ The prefix will ++ In Tx ports, if 'passPrsResult', the application ++ should set a value to their offsets in the prefix of ++ the FM will save the first 'privDataSize', than, ++ depending on 'passPrsResult' and 'passTimeStamp', copy parse result ++ and timeStamp, and the packet itself (in this order), to the ++ application buffer, and to offset. ++ Calling this routine changes the buffer margins definitions ++ in the internal driver data base from its default ++ configuration: Data size: [DEFAULT_FM_SP_bufferPrefixContent_privDataSize] ++ Pass Parser result: [DEFAULT_FM_SP_bufferPrefixContent_passPrsResult]. ++ Pass timestamp: [DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp]. ++ ++ May be used for all ports ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in,out] p_FmBufferPrefixContent A structure of parameters describing the ++ structure of the buffer. ++ Out parameter: Start margin - offset ++ of data from start of external buffer. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigBufferPrefixContent(t_Handle h_FmPort, ++ t_FmBufferPrefixContent *p_FmBufferPrefixContent); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigCheksumLastBytesIgnore ++ ++ @Description Calling this routine changes the number of checksum bytes to ignore ++ parameter in the internal driver data base from its default configuration ++ [0] ++ ++ May be used by Tx & Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] cheksumLastBytesIgnore New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigCheksumLastBytesIgnore(t_Handle h_FmPort, uint8_t cheksumLastBytesIgnore); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigCutBytesFromEnd ++ ++ @Description Calling this routine changes the number of bytes to cut from a ++ frame's end parameter in the internal driver data base ++ from its default configuration [4] ++ Note that if the result of (frame length before chop - cutBytesFromEnd) is ++ less than 14 bytes, the chop operation is not executed. ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] cutBytesFromEnd New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigCutBytesFromEnd(t_Handle h_FmPort, uint8_t cutBytesFromEnd); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigPoolDepletion ++ ++ @Description Calling this routine enables pause frame generation depending on the ++ depletion status of BM pools. It also defines the conditions to activate ++ this functionality. By default, this functionality is disabled. ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_BufPoolDepletion A structure of pool depletion parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigPoolDepletion(t_Handle h_FmPort, t_FmBufPoolDepletion *p_BufPoolDepletion); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigObservedPoolDepletion ++ ++ @Description Calling this routine enables a mechanism to stop port enqueue ++ depending on the depletion status of selected BM pools. ++ It also defines the conditions to activate ++ this functionality. By default, this functionality is disabled. ++ ++ Note: Available for some chips only ++ ++ May be used for OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmPortObservedBufPoolDepletion A structure of parameters for pool depletion. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigObservedPoolDepletion(t_Handle h_FmPort, ++ t_FmPortObservedBufPoolDepletion *p_FmPortObservedBufPoolDepletion); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigExtBufPools ++ ++ @Description This routine should be called for OP ports ++ that internally use BM buffer pools. In such cases, e.g. for fragmentation and ++ re-assembly, the FM needs new BM buffers. By calling this routine the user ++ specifies the BM buffer pools that should be used. ++ ++ Note: Available for some chips only ++ ++ May be used for OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmExtPools A structure of parameters for the external pools. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigExtBufPools(t_Handle h_FmPort, t_FmExtPools *p_FmExtPools); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigBackupPools ++ ++ @Description Calling this routine allows the configuration of some of the BM pools ++ defined for this port as backup pools. ++ A pool configured to be a backup pool will be used only if all other ++ enabled non-backup pools are depleted. ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmPortBackupBmPools An array of pool id's. All pools specified here will ++ be defined as backup pools. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigBackupPools(t_Handle h_FmPort, t_FmBackupBmPools *p_FmPortBackupBmPools); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigFrmDiscardOverride ++ ++ @Description Calling this routine changes the error frames destination parameter ++ in the internal driver data base from its default configuration: ++ override = [FALSE] ++ ++ May be used for Rx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] override TRUE to override discarding of error frames and ++ enqueueing them to error queue. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigFrmDiscardOverride(t_Handle h_FmPort, bool override); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigErrorsToDiscard ++ ++ @Description Calling this routine changes the behaviour on error parameter ++ in the internal driver data base from its default configuration: ++ [FM_PORT_FRM_ERR_CLS_DISCARD]. ++ If a requested error was previously defined as "ErrorsToEnqueue" it's ++ definition will change and the frame will be discarded. ++ Errors that were not defined either as "ErrorsToEnqueue" nor as ++ "ErrorsToDiscard", will be forwarded to CPU. ++ ++ May be used for Rx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] errs A list of errors to discard ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigErrorsToDiscard(t_Handle h_FmPort, fmPortFrameErrSelect_t errs); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDmaSwapData ++ ++ @Description Calling this routine changes the DMA swap data aparameter ++ in the internal driver data base from its default ++ configuration [DEFAULT_FM_SP_dmaSwapData] ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] swapData New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDmaSwapData(t_Handle h_FmPort, e_FmDmaSwapOption swapData); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDmaIcCacheAttr ++ ++ @Description Calling this routine changes the internal context cache ++ attribute parameter in the internal driver data base ++ from its default configuration [DEFAULT_FM_SP_dmaIntContextCacheAttr] ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] intContextCacheAttr New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDmaIcCacheAttr(t_Handle h_FmPort, e_FmDmaCacheOption intContextCacheAttr); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDmaHdrAttr ++ ++ @Description Calling this routine changes the header cache ++ attribute parameter in the internal driver data base ++ from its default configuration [DEFAULT_FM_SP_dmaHeaderCacheAttr] ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] headerCacheAttr New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDmaHdrAttr(t_Handle h_FmPort, e_FmDmaCacheOption headerCacheAttr); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDmaScatterGatherAttr ++ ++ @Description Calling this routine changes the scatter gather cache ++ attribute parameter in the internal driver data base ++ from its default configuration [DEFAULT_FM_SP_dmaScatterGatherCacheAttr] ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] scatterGatherCacheAttr New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDmaScatterGatherAttr(t_Handle h_FmPort, e_FmDmaCacheOption scatterGatherCacheAttr); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDmaWriteOptimize ++ ++ @Description Calling this routine changes the write optimization ++ parameter in the internal driver data base ++ from its default configuration: By default optimize = [DEFAULT_FM_SP_dmaWriteOptimize]. ++ Note: ++ ++ 1. For head optimization, data alignment must be >= 16 (supported by default). ++ ++ 3. For tail optimization, note that the optimization is performed by extending the write transaction ++ of the frame payload at the tail as needed to achieve optimal bus transfers, so that the last write ++ is extended to be on 16/64 bytes aligned block (chip dependent). ++ ++ ++ Relevant for non-Tx port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] optimize TRUE to enable optimization, FALSE for normal operation ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDmaWriteOptimize(t_Handle h_FmPort, bool optimize); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigNoScatherGather ++ ++ @Description Calling this routine changes the noScatherGather parameter in internal driver data base ++ from its default configuration. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] noScatherGather (TRUE - frame is discarded if can not be stored in single buffer, ++ FALSE - frame can be stored in scatter gather (S/G) format). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigNoScatherGather(t_Handle h_FmPort, bool noScatherGather); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDfltColor ++ ++ @Description Calling this routine changes the internal default color parameter ++ in the internal driver data base ++ from its default configuration [e_FM_PORT_COLOR_GREEN] ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] color New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDfltColor(t_Handle h_FmPort, e_FmPortColor color); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigSyncReq ++ ++ @Description Calling this routine changes the synchronization attribute parameter ++ in the internal driver data base from its default configuration: ++ syncReq = [TRUE] ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] syncReq TRUE to request synchronization, FALSE otherwize. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigSyncReq(t_Handle h_FmPort, bool syncReq); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigForwardReuseIntContext ++ ++ @Description This routine is relevant for Rx ports that are routed to OP port. ++ It changes the internal context reuse option in the internal ++ driver data base from its default configuration: ++ reuse = [FALSE] ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] reuse TRUE to reuse internal context on frames ++ forwarded to OP port. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigForwardReuseIntContext(t_Handle h_FmPort, bool reuse); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDontReleaseTxBufToBM ++ ++ @Description This routine should be called if no Tx confirmation ++ is done, and yet buffers should not be released to the BM. ++ Normally, buffers are returned using the Tx confirmation ++ process. When Tx confirmation is not used (defFqid=0), ++ buffers are typically released to the BM. This routine ++ may be called to avoid this behavior and not release the ++ buffers. ++ ++ May be used for Tx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDontReleaseTxBufToBM(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigIMMaxRxBufLength ++ ++ @Description Changes the maximum receive buffer length from its default ++ configuration: Closest rounded down power of 2 value of the ++ data buffer size. ++ ++ The maximum receive buffer length directly affects the structure ++ of received frames (single- or multi-buffered) and the performance ++ of both the FM and the driver. ++ ++ The selection between single- or multi-buffered frames should be ++ done according to the characteristics of the specific application. ++ The recommended mode is to use a single data buffer per packet, ++ as this mode provides the best performance. However, the user can ++ select to use multiple data buffers per packet. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] newVal Maximum receive buffer length (in bytes). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++ This routine is to be used only if Independent-Mode is enabled. ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigIMMaxRxBufLength(t_Handle h_FmPort, uint16_t newVal); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigIMRxBdRingLength ++ ++ @Description Changes the receive BD ring length from its default ++ configuration:[128] ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] newVal The desired BD ring length. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++ This routine is to be used only if Independent-Mode is enabled. ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigIMRxBdRingLength(t_Handle h_FmPort, uint16_t newVal); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigIMTxBdRingLength ++ ++ @Description Changes the transmit BD ring length from its default ++ configuration:[16] ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] newVal The desired BD ring length. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++ This routine is to be used only if Independent-Mode is enabled. ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigIMTxBdRingLength(t_Handle h_FmPort, uint16_t newVal); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigIMFmanCtrlExternalStructsMemory ++ ++ @Description Configures memory partition and attributes for FMan-Controller ++ data structures (e.g. BD rings). ++ Calling this routine changes the internal driver data base ++ from its default configuration ++ [0, MEMORY_ATTR_CACHEABLE]. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] memId Memory partition ID. ++ @Param[in] memAttributes Memory attributes mask (a combination of MEMORY_ATTR_x flags). ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigIMFmanCtrlExternalStructsMemory(t_Handle h_FmPort, ++ uint8_t memId, ++ uint32_t memAttributes); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigIMPolling ++ ++ @Description Changes the Rx flow from interrupt driven (default) to polling. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++ This routine is to be used only if Independent-Mode is enabled. ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigIMPolling(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigMaxFrameLength ++ ++ @Description Changes the definition of the max size of frame that should be ++ transmitted/received on this port from its default value [9600]. ++ This parameter is used for confirmation of the minimum Fifo ++ size calculations and only for Tx ports or ports working in ++ independent mode. This should be larger than the maximum possible ++ MTU that will be used for this port (i.e. its MAC). ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] length Max size of frame ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++ This routine is to be used only if Independent-Mode is enabled. ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigMaxFrameLength(t_Handle h_FmPort, uint16_t length); ++ ++/**************************************************************************//* ++ @Function FM_PORT_ConfigTxFifoMinFillLevel ++ ++ @Description Calling this routine changes the fifo minimum ++ fill level parameter in the internal driver data base ++ from its default configuration [0] ++ ++ May be used for Tx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] minFillLevel New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigTxFifoMinFillLevel(t_Handle h_FmPort, uint32_t minFillLevel); ++ ++/**************************************************************************//* ++ @Function FM_PORT_ConfigFifoDeqPipelineDepth ++ ++ @Description Calling this routine changes the fifo dequeue ++ pipeline depth parameter in the internal driver data base ++ ++ from its default configuration: 1G ports: [1], ++ 10G port: [4] ++ ++ May be used for Tx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] deqPipelineDepth New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigFifoDeqPipelineDepth(t_Handle h_FmPort, uint8_t deqPipelineDepth); ++ ++/**************************************************************************//* ++ @Function FM_PORT_ConfigTxFifoLowComfLevel ++ ++ @Description Calling this routine changes the fifo low comfort level ++ parameter in internal driver data base ++ from its default configuration [5] ++ ++ May be used for Tx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] fifoLowComfLevel New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigTxFifoLowComfLevel(t_Handle h_FmPort, uint32_t fifoLowComfLevel); ++ ++/**************************************************************************//* ++ @Function FM_PORT_ConfigRxFifoThreshold ++ ++ @Description Calling this routine changes the threshold of the FIFO ++ fill level parameter in the internal driver data base ++ from its default configuration [BMI_MAX_FIFO_SIZE] ++ ++ If the total number of buffers which are ++ currently in use and associated with the ++ specific RX port exceed this threshold, the ++ BMI will signal the MAC to send a pause frame ++ over the link. ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] fifoThreshold New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigRxFifoThreshold(t_Handle h_FmPort, uint32_t fifoThreshold); ++ ++/**************************************************************************//* ++ @Function FM_PORT_ConfigRxFifoPriElevationLevel ++ ++ @Description Calling this routine changes the priority elevation level ++ parameter in the internal driver data base from its default ++ configuration [BMI_MAX_FIFO_SIZE] ++ ++ If the total number of buffers which are currently in use and ++ associated with the specific RX port exceed the amount specified ++ in priElevationLevel, BMI will signal the main FM's DMA to ++ elevate the FM priority on the system bus. ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] priElevationLevel New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigRxFifoPriElevationLevel(t_Handle h_FmPort, uint32_t priElevationLevel); ++ ++#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 ++/**************************************************************************//* ++ @Function FM_PORT_ConfigBCBWorkaround ++ ++ @Description Configures BCB errata workaround. ++ ++ When BCB errata is applicable, the workaround is always ++ performed by FM Controller. Thus, this functions doesn't ++ actually enable errata workaround but rather allows driver ++ to perform adjustments required due to errata workaround ++ execution in FM controller. ++ ++ Applying BCB workaround also configures FM_PORT_FRM_ERR_PHYSICAL ++ errors to be discarded. Thus FM_PORT_FRM_ERR_PHYSICAL can't be ++ set by FM_PORT_SetErrorsRoute() function. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigBCBWorkaround(t_Handle h_FmPort); ++#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */ ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//* ++ @Function FM_PORT_ConfigInternalBuffOffset ++ ++ @Description Configures internal buffer offset. ++ ++ May be used for Rx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] val New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigInternalBuffOffset(t_Handle h_FmPort, uint8_t val); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/** @} */ /* end of FM_PORT_advanced_init_grp group */ ++/** @} */ /* end of FM_PORT_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_PORT_runtime_control_grp FM Port Runtime Control Unit ++ ++ @Description FM Port Runtime control unit API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description enum for defining FM Port counters ++*//***************************************************************************/ ++typedef enum e_FmPortCounters { ++ e_FM_PORT_COUNTERS_CYCLE, /**< BMI performance counter */ ++ e_FM_PORT_COUNTERS_TASK_UTIL, /**< BMI performance counter */ ++ e_FM_PORT_COUNTERS_QUEUE_UTIL, /**< BMI performance counter */ ++ e_FM_PORT_COUNTERS_DMA_UTIL, /**< BMI performance counter */ ++ e_FM_PORT_COUNTERS_FIFO_UTIL, /**< BMI performance counter */ ++ e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION, /**< BMI Rx only performance counter */ ++ e_FM_PORT_COUNTERS_FRAME, /**< BMI statistics counter */ ++ e_FM_PORT_COUNTERS_DISCARD_FRAME, /**< BMI statistics counter */ ++ e_FM_PORT_COUNTERS_DEALLOC_BUF, /**< BMI deallocate buffer statistics counter */ ++ e_FM_PORT_COUNTERS_RX_BAD_FRAME, /**< BMI Rx only statistics counter */ ++ e_FM_PORT_COUNTERS_RX_LARGE_FRAME, /**< BMI Rx only statistics counter */ ++ e_FM_PORT_COUNTERS_RX_FILTER_FRAME, /**< BMI Rx & OP only statistics counter */ ++ e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR, /**< BMI Rx, OP & HC only statistics counter */ ++ e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD, /**< BMI Rx, OP & HC statistics counter */ ++ e_FM_PORT_COUNTERS_PREPARE_TO_ENQUEUE_COUNTER, /**< BMI Rx, OP & HC only statistics counter */ ++ e_FM_PORT_COUNTERS_WRED_DISCARD, /**< BMI OP & HC only statistics counter */ ++ e_FM_PORT_COUNTERS_LENGTH_ERR, /**< BMI non-Rx statistics counter */ ++ e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT, /**< BMI non-Rx statistics counter */ ++ e_FM_PORT_COUNTERS_DEQ_TOTAL, /**< QMI total QM dequeues counter */ ++ e_FM_PORT_COUNTERS_ENQ_TOTAL, /**< QMI total QM enqueues counter */ ++ e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT, /**< QMI counter */ ++ e_FM_PORT_COUNTERS_DEQ_CONFIRM /**< QMI counter */ ++} e_FmPortCounters; ++ ++ ++/**************************************************************************//** ++ @Description Structure for Port id parameters. ++ Fields commented 'IN' are passed by the port module to be used ++ by the FM module. ++ Fields commented 'OUT' will be filled by FM before returning to port. ++*//***************************************************************************/ ++typedef struct t_FmPortCongestionGrps { ++ uint16_t numOfCongestionGrpsToConsider; /**< The number of required CGs ++ to define the size of the following array */ ++ uint8_t congestionGrpsToConsider[FM_PORT_NUM_OF_CONGESTION_GRPS]; ++ /**< An array of CG indexes; ++ Note that the size of the array should be ++ 'numOfCongestionGrpsToConsider'. */ ++#if (DPAA_VERSION >= 11) ++ bool pfcPrioritiesEn[FM_PORT_NUM_OF_CONGESTION_GRPS][FM_MAX_NUM_OF_PFC_PRIORITIES]; ++ /**< a matrix that represents the map between the CG ids ++ defined in 'congestionGrpsToConsider' to the priorties ++ mapping array. */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmPortCongestionGrps; ++ ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//** ++ @Function FM_PORT_DumpRegs ++ ++ @Description Dump all regs. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_DumpRegs(t_Handle h_FmPort); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetBufferDataOffset ++ ++ @Description Relevant for Rx ports. ++ Returns the data offset from the beginning of the data buffer ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ ++ @Return data offset. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++uint32_t FM_PORT_GetBufferDataOffset(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetBufferICInfo ++ ++ @Description Returns the Internal Context offset from the beginning of the data buffer ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return Internal context info pointer on success, NULL if 'allOtherInfo' was not ++ configured for this port. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++uint8_t * FM_PORT_GetBufferICInfo(t_Handle h_FmPort, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetBufferPrsResult ++ ++ @Description Returns the pointer to the parse result in the data buffer. ++ In Rx ports this is relevant after reception, if parse ++ result is configured to be part of the data passed to the ++ application. For non Rx ports it may be used to get the pointer ++ of the area in the buffer where parse result should be ++ initialized - if so configured. ++ See FM_PORT_ConfigBufferPrefixContent for data buffer prefix ++ configuration. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return Parse result pointer on success, NULL if parse result was not ++ configured for this port. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_FmPrsResult * FM_PORT_GetBufferPrsResult(t_Handle h_FmPort, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetBufferTimeStamp ++ ++ @Description Returns the time stamp in the data buffer. ++ Relevant for Rx ports for getting the buffer time stamp. ++ See FM_PORT_ConfigBufferPrefixContent for data buffer prefix ++ configuration. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return A pointer to the hash result on success, NULL otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++uint64_t * FM_PORT_GetBufferTimeStamp(t_Handle h_FmPort, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetBufferHashResult ++ ++ @Description Given a data buffer, on the condition that hash result was defined ++ as a part of the buffer content (see FM_PORT_ConfigBufferPrefixContent) ++ this routine will return the pointer to the hash result location in the ++ buffer prefix. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return A pointer to the hash result on success, NULL otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++uint8_t * FM_PORT_GetBufferHashResult(t_Handle h_FmPort, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_PORT_Disable ++ ++ @Description Gracefully disable an FM port. The port will not start new tasks after all ++ tasks associated with the port are terminated. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ This is a blocking routine, it returns after port is ++ gracefully stopped, i.e. the port will not except new frames, ++ but it will finish all frames or tasks which were already began ++*//***************************************************************************/ ++t_Error FM_PORT_Disable(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_Enable ++ ++ @Description A runtime routine provided to allow disable/enable of port. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_Enable(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetRateLimit ++ ++ @Description Calling this routine enables rate limit algorithm. ++ By default, this functionality is disabled. ++ Note that rate-limit mechanism uses the FM time stamp. ++ The selected rate limit specified here would be ++ rounded DOWN to the nearest 16M. ++ ++ May be used for Tx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_RateLimit A structure of rate limit parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetRateLimit(t_Handle h_FmPort, t_FmPortRateLimit *p_RateLimit); ++ ++/**************************************************************************//** ++ @Function FM_PORT_DeleteRateLimit ++ ++ @Description Calling this routine disables and clears rate limit ++ initialization. ++ ++ May be used for Tx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_DeleteRateLimit(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetStatisticsCounters ++ ++ @Description Calling this routine enables/disables port's statistics counters. ++ By default, counters are enabled. ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] enable TRUE to enable, FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetStatisticsCounters(t_Handle h_FmPort, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetFrameQueueCounters ++ ++ @Description Calling this routine enables/disables port's enqueue/dequeue counters. ++ By default, counters are enabled. ++ ++ May be used for all ports ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] enable TRUE to enable, FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetFrameQueueCounters(t_Handle h_FmPort, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PORT_AnalyzePerformanceParams ++ ++ @Description User may call this routine to so the driver will analyze if the ++ basic performance parameters are correct and also the driver may ++ suggest of improvments; The basic parameters are FIFO sizes, number ++ of DMAs and number of TNUMs for the port. ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_AnalyzePerformanceParams(t_Handle h_FmPort); ++ ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetAllocBufCounter ++ ++ @Description Calling this routine enables/disables BM pool allocate ++ buffer counters. ++ By default, counters are enabled. ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] poolId BM pool id. ++ @Param[in] enable TRUE to enable, FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetCounter ++ ++ @Description Reads one of the FM PORT counters. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] fmPortCounter The requested counter. ++ ++ @Return Counter's current value. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ Note that it is user's responsibility to call this routine only ++ for enabled counters, and there will be no indication if a ++ disabled counter is accessed. ++*//***************************************************************************/ ++uint32_t FM_PORT_GetCounter(t_Handle h_FmPort, e_FmPortCounters fmPortCounter); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ModifyCounter ++ ++ @Description Sets a value to an enabled counter. Use "0" to reset the counter. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] fmPortCounter The requested counter. ++ @Param[in] value The requested value to be written into the counter. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ModifyCounter(t_Handle h_FmPort, e_FmPortCounters fmPortCounter, uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetAllocBufCounter ++ ++ @Description Reads one of the FM PORT buffer counters. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] poolId The requested pool. ++ ++ @Return Counter's current value. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ Note that it is user's responsibility to call this routine only ++ for enabled counters, and there will be no indication if a ++ disabled counter is accessed. ++*//***************************************************************************/ ++uint32_t FM_PORT_GetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ModifyAllocBufCounter ++ ++ @Description Sets a value to an enabled counter. Use "0" to reset the counter. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] poolId The requested pool. ++ @Param[in] value The requested value to be written into the counter. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ModifyAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_PORT_AddCongestionGrps ++ ++ @Description This routine effects the corresponding Tx port. ++ It should be called in order to enable pause ++ frame transmission in case of congestion in one or more ++ of the congestion groups relevant to this port. ++ Each call to this routine may add one or more congestion ++ groups to be considered relevant to this port. ++ ++ May be used for Rx, or RX+OP ports only (depending on chip) ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_CongestionGrps A pointer to an array of congestion groups ++ id's to consider. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_AddCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps); ++ ++/**************************************************************************//** ++ @Function FM_PORT_RemoveCongestionGrps ++ ++ @Description This routine effects the corresponding Tx port. It should be ++ called when congestion groups were ++ defined for this port and are no longer relevant, or pause ++ frames transmitting is not required on their behalf. ++ Each call to this routine may remove one or more congestion ++ groups to be considered relevant to this port. ++ ++ May be used for Rx, or RX+OP ports only (depending on chip) ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_CongestionGrps A pointer to an array of congestion groups ++ id's to consider. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_RemoveCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps); ++ ++/**************************************************************************//** ++ @Function FM_PORT_IsStalled ++ ++ @Description A routine for checking whether the specified port is stalled. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return TRUE if port is stalled, FALSE otherwize ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++bool FM_PORT_IsStalled(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ReleaseStalled ++ ++ @Description This routine may be called in case the port was stalled and may ++ now be released. ++ Note that this routine is available only on older FMan revisions ++ (FMan v2, DPAA v1.0 only). ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ReleaseStalled(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetRxL4ChecksumVerify ++ ++ @Description This routine is relevant for Rx ports (1G and 10G). The routine ++ set/clear the L3/L4 checksum verification (on RX side). ++ Note that this takes affect only if hw-parser is enabled! ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] l4Checksum boolean indicates whether to do L3/L4 checksum ++ on frames or not. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetRxL4ChecksumVerify(t_Handle h_FmPort, bool l4Checksum); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetErrorsRoute ++ ++ @Description Errors selected for this routine will cause a frame with that error ++ to be enqueued to error queue. ++ Errors not selected for this routine will cause a frame with that error ++ to be enqueued to the one of the other port queues. ++ By default all errors are defined to be enqueued to error queue. ++ Errors that were configured to be discarded (at initialization) ++ may not be selected here. ++ ++ May be used for Rx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] errs A list of errors to enqueue to error queue ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetErrorsRoute(t_Handle h_FmPort, fmPortFrameErrSelect_t errs); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetIMExceptions ++ ++ @Description Calling this routine enables/disables FM PORT interrupts. ++ ++ @Param[in] h_FmPort FM PORT module descriptor. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PORT_SetIMExceptions(t_Handle h_FmPort, e_FmPortExceptions exception, bool enable); ++ ++/**************************************************************************//* ++ @Function FM_PORT_SetPerformanceCounters ++ ++ @Description Calling this routine enables/disables port's performance counters. ++ By default, counters are enabled. ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] enable TRUE to enable, FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetPerformanceCounters(t_Handle h_FmPort, bool enable); ++ ++/**************************************************************************//* ++ @Function FM_PORT_SetPerformanceCountersParams ++ ++ @Description Calling this routine defines port's performance ++ counters parameters. ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmPortPerformanceCnt A pointer to a structure of performance ++ counters parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetPerformanceCountersParams(t_Handle h_FmPort, t_FmPortPerformanceCnt *p_FmPortPerformanceCnt); ++ ++/**************************************************************************//** ++ @Group FM_PORT_pcd_runtime_control_grp FM Port PCD Runtime Control Unit ++ ++ @Description FM Port PCD Runtime control unit API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description A structure defining the KG scheme after the parser. ++ This is relevant only to change scheme selection mode - from ++ direct to indirect and vice versa, or when the scheme is selected directly, ++ to select the scheme id. ++ ++*//***************************************************************************/ ++typedef struct t_FmPcdKgSchemeSelect { ++ bool direct; /**< TRUE to use 'h_Scheme' directly, FALSE to use LCV. */ ++ t_Handle h_DirectScheme; /**< Scheme handle, selects the scheme after parser; ++ Relevant only when 'direct' is TRUE. */ ++} t_FmPcdKgSchemeSelect; ++ ++/**************************************************************************//** ++ @Description A structure of scheme parameters ++*//***************************************************************************/ ++typedef struct t_FmPcdPortSchemesParams { ++ uint8_t numOfSchemes; /**< Number of schemes for port to be bound to. */ ++ t_Handle h_Schemes[FM_PCD_KG_NUM_OF_SCHEMES]; /**< Array of 'numOfSchemes' schemes for the ++ port to be bound to */ ++} t_FmPcdPortSchemesParams; ++ ++/**************************************************************************//** ++ @Description Union for defining port protocol parameters for parser ++*//***************************************************************************/ ++typedef union u_FmPcdHdrPrsOpts { ++ /* MPLS */ ++ struct { ++ bool labelInterpretationEnable; /**< When this bit is set, the last MPLS label will be ++ interpreted as described in HW spec table. When the bit ++ is cleared, the parser will advance to MPLS next parse */ ++ e_NetHeaderType nextParse; /**< must be equal or higher than IPv4 */ ++ } mplsPrsOptions; ++ /* VLAN */ ++ struct { ++ uint16_t tagProtocolId1; /**< User defined Tag Protocol Identifier, to be recognized ++ on VLAN TAG on top of 0x8100 and 0x88A8 */ ++ uint16_t tagProtocolId2; /**< User defined Tag Protocol Identifier, to be recognized ++ on VLAN TAG on top of 0x8100 and 0x88A8 */ ++ } vlanPrsOptions; ++ /* PPP */ ++ struct{ ++ bool enableMTUCheck; /**< Check validity of MTU according to RFC2516 */ ++ } pppoePrsOptions; ++ ++ /* IPV6 */ ++ struct{ ++ bool routingHdrEnable; /**< TRUE to enable routing header, otherwise ignore */ ++ } ipv6PrsOptions; ++ ++ /* UDP */ ++ struct{ ++ bool padIgnoreChecksum; /**< TRUE to ignore pad in checksum */ ++ } udpPrsOptions; ++ ++ /* TCP */ ++ struct { ++ bool padIgnoreChecksum; /**< TRUE to ignore pad in checksum */ ++ } tcpPrsOptions; ++} u_FmPcdHdrPrsOpts; ++ ++/**************************************************************************//** ++ @Description A structure for defining each header for the parser ++*//***************************************************************************/ ++typedef struct t_FmPcdPrsAdditionalHdrParams { ++ e_NetHeaderType hdr; /**< Selected header */ ++ bool errDisable; /**< TRUE to disable error indication */ ++ bool swPrsEnable; /**< Enable jump to SW parser when this ++ header is recognized by the HW parser. */ ++ uint8_t indexPerHdr; /**< Normally 0, if more than one sw parser ++ attachments exists for the same header, ++ (in the main sw parser code) use this ++ index to distinguish between them. */ ++ bool usePrsOpts; /**< TRUE to use parser options. */ ++ u_FmPcdHdrPrsOpts prsOpts; /**< A union according to header type, ++ defining the parser options selected.*/ ++} t_FmPcdPrsAdditionalHdrParams; ++ ++/**************************************************************************//** ++ @Description struct for defining port PCD parameters ++*//***************************************************************************/ ++typedef struct t_FmPortPcdPrsParams { ++ uint8_t prsResultPrivateInfo; /**< The private info provides a method of inserting ++ port information into the parser result. This information ++ may be extracted by Keygen and be used for frames ++ distribution when a per-port distinction is required, ++ it may also be used as a port logical id for analyzing ++ incoming frames. */ ++ uint8_t parsingOffset; /**< Number of bytes from beginning of packet to start parsing */ ++ e_NetHeaderType firstPrsHdr; /**< The type of the first header expected at 'parsingOffset' */ ++ bool includeInPrsStatistics; /**< TRUE to include this port in the parser statistics; ++ NOTE: this field is not valid when the FM is in "guest" mode ++ and IPC is not available. */ ++ uint8_t numOfHdrsWithAdditionalParams; /**< Normally 0, some headers may get ++ special parameters */ ++ t_FmPcdPrsAdditionalHdrParams additionalParams[FM_PCD_PRS_NUM_OF_HDRS]; ++ /**< 'numOfHdrsWithAdditionalParams' structures ++ of additional parameters ++ for each header that requires them */ ++ bool setVlanTpid1; /**< TRUE to configure user selection of Ethertype to ++ indicate a VLAN tag (in addition to the TPID values ++ 0x8100 and 0x88A8). */ ++ uint16_t vlanTpid1; /**< extra tag to use if setVlanTpid1=TRUE. */ ++ bool setVlanTpid2; /**< TRUE to configure user selection of Ethertype to ++ indicate a VLAN tag (in addition to the TPID values ++ 0x8100 and 0x88A8). */ ++ uint16_t vlanTpid2; /**< extra tag to use if setVlanTpid1=TRUE. */ ++} t_FmPortPcdPrsParams; ++ ++/**************************************************************************//** ++ @Description struct for defining coarse alassification parameters ++*//***************************************************************************/ ++typedef struct t_FmPortPcdCcParams { ++ t_Handle h_CcTree; /**< A handle to a CC tree */ ++} t_FmPortPcdCcParams; ++ ++/**************************************************************************//** ++ @Description struct for defining keygen parameters ++*//***************************************************************************/ ++typedef struct t_FmPortPcdKgParams { ++ uint8_t numOfSchemes; /**< Number of schemes for port to be bound to. */ ++ t_Handle h_Schemes[FM_PCD_KG_NUM_OF_SCHEMES]; ++ /**< Array of 'numOfSchemes' schemes handles for the ++ port to be bound to */ ++ bool directScheme; /**< TRUE for going from parser to a specific scheme, ++ regardless of parser result */ ++ t_Handle h_DirectScheme; /**< relevant only if direct == TRUE, Scheme handle, ++ as returned by FM_PCD_KgSetScheme */ ++} t_FmPortPcdKgParams; ++ ++/**************************************************************************//** ++ @Description struct for defining policer parameters ++*//***************************************************************************/ ++typedef struct t_FmPortPcdPlcrParams { ++ t_Handle h_Profile; /**< Selected profile handle; Relevant for one of ++ following cases: ++ e_FM_PORT_PCD_SUPPORT_PLCR_ONLY or ++ e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR were selected, ++ or if any flow uses a KG scheme were policer ++ profile is not generated ++ (bypassPlcrProfileGeneration selected) */ ++} t_FmPortPcdPlcrParams; ++ ++/**************************************************************************//** ++ @Description struct for defining port PCD parameters ++*//***************************************************************************/ ++typedef struct t_FmPortPcdParams { ++ e_FmPortPcdSupport pcdSupport; /**< Relevant for Rx and offline ports only. ++ Describes the active PCD engines for this port. */ ++ t_Handle h_NetEnv; /**< HL Unused in PLCR only mode */ ++ t_FmPortPcdPrsParams *p_PrsParams; /**< Parser parameters for this port */ ++ t_FmPortPcdCcParams *p_CcParams; /**< Coarse classification parameters for this port */ ++ t_FmPortPcdKgParams *p_KgParams; /**< Keygen parameters for this port */ ++ t_FmPortPcdPlcrParams *p_PlcrParams; /**< Policer parameters for this port */ ++ t_Handle h_IpReassemblyManip;/**< IP Reassembly manipulation */ ++} t_FmPortPcdParams; ++ ++/**************************************************************************//** ++ @Description A structure for defining the Parser starting point ++*//***************************************************************************/ ++typedef struct t_FmPcdPrsStart { ++ uint8_t parsingOffset; /**< Number of bytes from beginning of packet to ++ start parsing */ ++ e_NetHeaderType firstPrsHdr; /**< The type of the first header axpected at ++ 'parsingOffset' */ ++} t_FmPcdPrsStart; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description struct for defining external buffer margins ++*//***************************************************************************/ ++typedef struct t_FmPortVSPAllocParams { ++ uint8_t numOfProfiles; /**< Number of Virtual Storage Profiles */ ++ uint8_t dfltRelativeId; /**< The default Virtual-Storage-Profile-id dedicated to Rx/OP port ++ The same default Virtual-Storage-Profile-id will be for coupled Tx port ++ if relevant function called for Rx port */ ++ t_Handle h_FmTxPort; /**< Handle to coupled Tx Port; not relevant for OP port. */ ++} t_FmPortVSPAllocParams; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetPCD ++ ++ @Description Calling this routine defines the port's PCD configuration. ++ It changes it from its default configuration which is PCD ++ disabled (BMI to BMI) and configures it according to the passed ++ parameters. ++ ++ May be used for Rx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmPortPcd A Structure of parameters defining the port's PCD ++ configuration. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetPCD(t_Handle h_FmPort, t_FmPortPcdParams *p_FmPortPcd); ++ ++/**************************************************************************//** ++ @Function FM_PORT_DeletePCD ++ ++ @Description Calling this routine releases the port's PCD configuration. ++ The port returns to its default configuration which is PCD ++ disabled (BMI to BMI) and all PCD configuration is removed. ++ ++ May be used for Rx and OP ports which are ++ in PCD mode only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_DeletePCD(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_AttachPCD ++ ++ @Description This routine may be called after FM_PORT_DetachPCD was called, ++ to return to the originally configured PCD support flow. ++ The couple of routines are used to allow PCD configuration changes ++ that demand that PCD will not be used while changes take place. ++ ++ May be used for Rx and OP ports which are ++ in PCD mode only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_AttachPCD(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_DetachPCD ++ ++ @Description Calling this routine detaches the port from its PCD functionality. ++ The port returns to its default flow which is BMI to BMI. ++ ++ May be used for Rx and OP ports which are ++ in PCD mode only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_AttachPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_DetachPCD(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdPlcrAllocProfiles ++ ++ @Description This routine may be called only for ports that use the Policer in ++ order to allocate private policer profiles. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] numOfProfiles The number of required policer profiles ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() and FM_PCD_Init(), ++ and before FM_PORT_SetPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdPlcrAllocProfiles(t_Handle h_FmPort, uint16_t numOfProfiles); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdPlcrFreeProfiles ++ ++ @Description This routine should be called for freeing private policer profiles. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() and FM_PCD_Init(), ++ and before FM_PORT_SetPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdPlcrFreeProfiles(t_Handle h_FmPort); ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Function FM_PORT_VSPAlloc ++ ++ @Description This routine allocated VSPs per port and forces the port to work ++ in VSP mode. Note that the port is initialized by default with the ++ physical-storage-profile only. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_Params A structure of parameters for allocation VSP's per port ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(), and before FM_PORT_SetPCD() ++ and also before FM_PORT_Enable() (i.e. the port should be disabled). ++*//***************************************************************************/ ++t_Error FM_PORT_VSPAlloc(t_Handle h_FmPort, t_FmPortVSPAllocParams *p_Params); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdKgModifyInitialScheme ++ ++ @Description This routine may be called only for ports that use the keygen in ++ order to change the initial scheme frame should be routed to. ++ The change may be of a scheme id (in case of direct mode), ++ from direct to indirect, or from indirect to direct - specifying the scheme id. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmPcdKgScheme A structure of parameters for defining whether ++ a scheme is direct/indirect, and if direct - scheme id. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() and FM_PORT_SetPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdKgModifyInitialScheme (t_Handle h_FmPort, t_FmPcdKgSchemeSelect *p_FmPcdKgScheme); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdPlcrModifyInitialProfile ++ ++ @Description This routine may be called for ports with flows ++ e_FM_PORT_PCD_SUPPORT_PLCR_ONLY or e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR ++ only, to change the initial Policer profile frame should be ++ routed to. The change may be of a profile and/or absolute/direct ++ mode selection. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] h_Profile Policer profile handle ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() and FM_PORT_SetPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdPlcrModifyInitialProfile (t_Handle h_FmPort, t_Handle h_Profile); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdCcModifyTree ++ ++ @Description This routine may be called for ports that use coarse classification tree ++ if the user wishes to replace the tree. The routine may not be called while port ++ receives packets using the PCD functionalities, therefor port must be first detached ++ from the PCD, only than the routine may be called, and than port be attached to PCD again. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] h_CcTree A CC tree that was already built. The tree id as returned from ++ the BuildTree routine. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(), FM_PORT_SetPCD() and FM_PORT_DetachPCD() ++*//***************************************************************************/ ++t_Error FM_PORT_PcdCcModifyTree (t_Handle h_FmPort, t_Handle h_CcTree); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdKgBindSchemes ++ ++ @Description These routines may be called for adding more schemes for the ++ port to be bound to. The selected schemes are not added, ++ just this specific port starts using them. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_PortScheme A structure defining the list of schemes to be added. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() and FM_PORT_SetPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdKgBindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdKgUnbindSchemes ++ ++ @Description These routines may be called for adding more schemes for the ++ port to be bound to. The selected schemes are not removed or invalidated, ++ just this specific port stops using them. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_PortScheme A structure defining the list of schemes to be added. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() and FM_PORT_SetPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdKgUnbindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdPrsModifyStartOffset ++ ++ @Description Runtime change of the parser start offset within the header. ++ The routine may not be called while port ++ receives packets using the PCD functionalities, therefore port must be first detached ++ from the PCD, only than the routine may be called, and than port be attached to PCD again. ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmPcdPrsStart A structure of parameters for defining the ++ start point for the parser. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(), FM_PORT_SetPCD() and FM_PORT_DetatchPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdPrsModifyStartOffset (t_Handle h_FmPort, t_FmPcdPrsStart *p_FmPcdPrsStart); ++ ++ ++/** @} */ /* end of FM_PORT_pcd_runtime_control_grp group */ ++/** @} */ /* end of FM_PORT_runtime_control_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_PORT_runtime_data_grp FM Port Runtime Data-path Unit ++ ++ @Description FM Port Runtime data unit API functions, definitions and enums. ++ This API is valid only if working in Independent-Mode. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_PORT_ImTx ++ ++ @Description Tx function, called to transmit a data buffer on the port. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_Data A pointer to an LCP data buffer. ++ @Param[in] length Size of data for transmission. ++ @Param[in] lastBuffer Buffer position - TRUE for the last buffer ++ of a frame, including a single buffer frame ++ @Param[in] h_BufContext A handle of the user acossiated with this buffer ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ NOTE - This routine can be used only when working in ++ Independent-Mode mode. ++*//***************************************************************************/ ++t_Error FM_PORT_ImTx( t_Handle h_FmPort, ++ uint8_t *p_Data, ++ uint16_t length, ++ bool lastBuffer, ++ t_Handle h_BufContext); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ImTxConf ++ ++ @Description Tx port confirmation routine, optional, may be called to verify ++ transmission of all frames. The procedure performed by this ++ routine will be performed automatically on next buffer transmission, ++ but if desired, calling this routine will invoke this action on ++ demand. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ NOTE - This routine can be used only when working in ++ Independent-Mode mode. ++*//***************************************************************************/ ++void FM_PORT_ImTxConf(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ImRx ++ ++ @Description Rx function, may be called to poll for received buffers. ++ Normally, Rx process is invoked by the driver on Rx interrupt. ++ Alternatively, this routine may be called on demand. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ NOTE - This routine can be used only when working in ++ Independent-Mode mode. ++*//***************************************************************************/ ++t_Error FM_PORT_ImRx(t_Handle h_FmPort); ++ ++/** @} */ /* end of FM_PORT_runtime_data_grp group */ ++/** @} */ /* end of FM_PORT_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++ ++#ifdef NCSW_BACKWARD_COMPATIBLE_API ++#define FM_PORT_ConfigTxFifoDeqPipelineDepth FM_PORT_ConfigFifoDeqPipelineDepth ++#endif /* NCSW_BACKWARD_COMPATIBLE_API */ ++ ++ ++#endif /* __FM_PORT_EXT */ +diff --git a/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_rtc_ext.h b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_rtc_ext.h +new file mode 100644 +index 0000000..c8fa262 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_rtc_ext.h +@@ -0,0 +1,593 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_rtc_ext.h ++ ++ @Description External definitions and API for FM RTC IEEE1588 Timer Module. ++ ++ @Cautions None. ++*//***************************************************************************/ ++ ++#ifndef __FM_RTC_EXT_H__ ++#define __FM_RTC_EXT_H__ ++ ++ ++#include "error_ext.h" ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group fm_rtc_grp FM RTC ++ ++ @Description FM RTC functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group fm_rtc_init_grp FM RTC Initialization Unit ++ ++ @Description FM RTC initialization API. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description FM RTC Alarm Polarity Options. ++*//***************************************************************************/ ++typedef enum e_FmRtcAlarmPolarity ++{ ++ e_FM_RTC_ALARM_POLARITY_ACTIVE_HIGH, /**< Active-high output polarity */ ++ e_FM_RTC_ALARM_POLARITY_ACTIVE_LOW /**< Active-low output polarity */ ++} e_FmRtcAlarmPolarity; ++ ++/**************************************************************************//** ++ @Description FM RTC Trigger Polarity Options. ++*//***************************************************************************/ ++typedef enum e_FmRtcTriggerPolarity ++{ ++ e_FM_RTC_TRIGGER_ON_RISING_EDGE, /**< Trigger on rising edge */ ++ e_FM_RTC_TRIGGER_ON_FALLING_EDGE /**< Trigger on falling edge */ ++} e_FmRtcTriggerPolarity; ++ ++/**************************************************************************//** ++ @Description IEEE1588 Timer Module FM RTC Optional Clock Sources. ++*//***************************************************************************/ ++typedef enum e_FmSrcClock ++{ ++ e_FM_RTC_SOURCE_CLOCK_EXTERNAL, /**< external high precision timer reference clock */ ++ e_FM_RTC_SOURCE_CLOCK_SYSTEM, /**< MAC system clock */ ++ e_FM_RTC_SOURCE_CLOCK_OSCILATOR /**< RTC clock oscilator */ ++}e_FmSrcClk; ++ ++/**************************************************************************//** ++ @Description FM RTC configuration parameters structure. ++ ++ This structure should be passed to FM_RTC_Config(). ++*//***************************************************************************/ ++typedef struct t_FmRtcParams ++{ ++ t_Handle h_Fm; /**< FM Handle*/ ++ uintptr_t baseAddress; /**< Base address of FM RTC registers */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks */ ++} t_FmRtcParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_RTC_Config ++ ++ @Description Configures the FM RTC module according to user's parameters. ++ ++ The driver assigns default values to some FM RTC parameters. ++ These parameters can be overwritten using the advanced ++ configuration routines. ++ ++ @Param[in] p_FmRtcParam - FM RTC configuration parameters. ++ ++ @Return Handle to the new FM RTC object; NULL pointer on failure. ++ ++ @Cautions None ++*//***************************************************************************/ ++t_Handle FM_RTC_Config(t_FmRtcParams *p_FmRtcParam); ++ ++/**************************************************************************//** ++ @Function FM_RTC_Init ++ ++ @Description Initializes the FM RTC driver and hardware. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_Init(t_Handle h_FmRtc); ++ ++/**************************************************************************//** ++ @Function FM_RTC_Free ++ ++ @Description Frees the FM RTC object and all allocated resources. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_Free(t_Handle h_FmRtc); ++ ++ ++/**************************************************************************//** ++ @Group fm_rtc_adv_config_grp FM RTC Advanced Configuration Unit ++ ++ @Description FM RTC advanced configuration functions. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigPeriod ++ ++ @Description Configures the period of the timestamp if different than ++ default [1000]. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] period - Period in nano-seconds. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigPeriod(t_Handle h_FmRtc, uint32_t period); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigSourceClock ++ ++ @Description Configures the source clock of the RTC. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] srcClk - Source clock selection. ++ @Param[in] freqInMhz - the source-clock frequency (in MHz). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigSourceClock(t_Handle h_FmRtc, ++ e_FmSrcClk srcClk, ++ uint32_t freqInMhz); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigPulseRealignment ++ ++ @Description Configures the RTC to automatic FIPER pulse realignment in ++ response to timer adjustments [FALSE] ++ ++ In this mode, the RTC clock is identical to the source clock. ++ This feature can be useful when the system contains an external ++ RTC with inherent frequency compensation. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] enable - TRUE to enable automatic realignment. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigPulseRealignment(t_Handle h_FmRtc, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigFrequencyBypass ++ ++ @Description Configures the RTC to bypass the frequency compensation ++ mechanism. [FALSE] ++ ++ In this mode, the RTC clock is identical to the source clock. ++ This feature can be useful when the system contains an external ++ RTC with inherent frequency compensation. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] enabled - TRUE to bypass frequency compensation; ++ FALSE otherwise. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigFrequencyBypass(t_Handle h_FmRtc, bool enabled); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigInvertedInputClockPhase ++ ++ @Description Configures the RTC to invert the source clock phase on input. ++ [FALSE] ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] inverted - TRUE to invert the source clock phase on input. ++ FALSE otherwise. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigInvertedInputClockPhase(t_Handle h_FmRtc, bool inverted); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigInvertedOutputClockPhase ++ ++ @Description Configures the RTC to invert the output clock phase. ++ [FALSE] ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] inverted - TRUE to invert the output clock phase. ++ FALSE otherwise. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigInvertedOutputClockPhase(t_Handle h_FmRtc, bool inverted); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigOutputClockDivisor ++ ++ @Description Configures the divisor for generating the output clock from ++ the RTC clock. [0x00000002] ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] divisor - Divisor for generation of the output clock. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigOutputClockDivisor(t_Handle h_FmRtc, uint16_t divisor); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigAlarmPolarity ++ ++ @Description Configures the polarity (active-high/active-low) of a specific ++ alarm signal. [e_FM_RTC_ALARM_POLARITY_ACTIVE_HIGH] ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] alarmId - Alarm ID. ++ @Param[in] alarmPolarity - Alarm polarity. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigAlarmPolarity(t_Handle h_FmRtc, ++ uint8_t alarmId, ++ e_FmRtcAlarmPolarity alarmPolarity); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigExternalTriggerPolarity ++ ++ @Description Configures the polarity (rising/falling edge) of a specific ++ external trigger signal. [e_FM_RTC_TRIGGER_ON_FALLING_EDGE] ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] triggerId - Trigger ID. ++ @Param[in] triggerPolarity - Trigger polarity. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigExternalTriggerPolarity(t_Handle h_FmRtc, ++ uint8_t triggerId, ++ e_FmRtcTriggerPolarity triggerPolarity); ++ ++/** @} */ /* end of fm_rtc_adv_config_grp */ ++/** @} */ /* end of fm_rtc_init_grp */ ++ ++ ++/**************************************************************************//** ++ @Group fm_rtc_control_grp FM RTC Control Unit ++ ++ @Description FM RTC runtime control API. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function t_FmRtcExceptionsCallback ++ ++ @Description Exceptions user callback routine, used for RTC different mechanisms. ++ ++ @Param[in] h_App - User's application descriptor. ++ @Param[in] id - source id. ++*//***************************************************************************/ ++typedef void (t_FmRtcExceptionsCallback) ( t_Handle h_App, uint8_t id); ++ ++/**************************************************************************//** ++ @Description FM RTC alarm parameters. ++*//***************************************************************************/ ++typedef struct t_FmRtcAlarmParams { ++ uint8_t alarmId; /**< 0 or 1 */ ++ uint64_t alarmTime; /**< In nanoseconds, the time when the alarm ++ should go off - must be a multiple of ++ the RTC period */ ++ t_FmRtcExceptionsCallback *f_AlarmCallback; /**< This routine will be called when RTC ++ reaches alarmTime */ ++ bool clearOnExpiration; /**< TRUE to turn off the alarm once expired. */ ++} t_FmRtcAlarmParams; ++ ++/**************************************************************************//** ++ @Description FM RTC Periodic Pulse parameters. ++*//***************************************************************************/ ++typedef struct t_FmRtcPeriodicPulseParams { ++ uint8_t periodicPulseId; /**< 0 or 1 */ ++ uint64_t periodicPulsePeriod; /**< In Nanoseconds. Must be ++ a multiple of the RTC period */ ++ t_FmRtcExceptionsCallback *f_PeriodicPulseCallback; /**< This routine will be called every ++ periodicPulsePeriod. */ ++} t_FmRtcPeriodicPulseParams; ++ ++/**************************************************************************//** ++ @Description FM RTC Periodic Pulse parameters. ++*//***************************************************************************/ ++typedef struct t_FmRtcExternalTriggerParams { ++ uint8_t externalTriggerId; /**< 0 or 1 */ ++ bool usePulseAsInput; /**< Use the pulse interrupt instead of ++ an external signal */ ++ t_FmRtcExceptionsCallback *f_ExternalTriggerCallback; /**< This routine will be called every ++ periodicPulsePeriod. */ ++} t_FmRtcExternalTriggerParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_RTC_Enable ++ ++ @Description Enable the RTC (time count is started). ++ ++ The user can select to resume the time count from previous ++ point, or to restart the time count. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] resetClock - Restart the time count from zero. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_Enable(t_Handle h_FmRtc, bool resetClock); ++ ++/**************************************************************************//** ++ @Function FM_RTC_Disable ++ ++ @Description Disables the RTC (time count is stopped). ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_Disable(t_Handle h_FmRtc); ++ ++/**************************************************************************//** ++ @Function FM_RTC_SetClockOffset ++ ++ @Description Sets the clock offset (usually relative to another clock). ++ ++ The user can pass a negative offset value. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] offset - New clock offset (in nanoseconds). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_SetClockOffset(t_Handle h_FmRtc, int64_t offset); ++ ++/**************************************************************************//** ++ @Function FM_RTC_SetAlarm ++ ++ @Description Schedules an alarm event to a given RTC time. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] p_FmRtcAlarmParams - Alarm parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++ Must be called only prior to FM_RTC_Enable(). ++*//***************************************************************************/ ++t_Error FM_RTC_SetAlarm(t_Handle h_FmRtc, t_FmRtcAlarmParams *p_FmRtcAlarmParams); ++ ++/**************************************************************************//** ++ @Function FM_RTC_SetPeriodicPulse ++ ++ @Description Sets a periodic pulse. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] p_FmRtcPeriodicPulseParams - Periodic pulse parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++ Must be called only prior to FM_RTC_Enable(). ++*//***************************************************************************/ ++t_Error FM_RTC_SetPeriodicPulse(t_Handle h_FmRtc, t_FmRtcPeriodicPulseParams *p_FmRtcPeriodicPulseParams); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ClearPeriodicPulse ++ ++ @Description Clears a periodic pulse. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] periodicPulseId - Periodic pulse id. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_ClearPeriodicPulse(t_Handle h_FmRtc, uint8_t periodicPulseId); ++ ++/**************************************************************************//** ++ @Function FM_RTC_SetExternalTrigger ++ ++ @Description Sets an external trigger indication and define a callback ++ routine to be called on such event. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] p_FmRtcExternalTriggerParams - External Trigger parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_SetExternalTrigger(t_Handle h_FmRtc, t_FmRtcExternalTriggerParams *p_FmRtcExternalTriggerParams); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ClearExternalTrigger ++ ++ @Description Clears external trigger indication. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] id - External Trigger id. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_ClearExternalTrigger(t_Handle h_FmRtc, uint8_t id); ++ ++/**************************************************************************//** ++ @Function FM_RTC_GetExternalTriggerTimeStamp ++ ++ @Description Reads the External Trigger TimeStamp. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] triggerId - External Trigger id. ++ @Param[out] p_TimeStamp - External Trigger timestamp (in nanoseconds). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_GetExternalTriggerTimeStamp(t_Handle h_FmRtc, ++ uint8_t triggerId, ++ uint64_t *p_TimeStamp); ++ ++/**************************************************************************//** ++ @Function FM_RTC_GetCurrentTime ++ ++ @Description Returns the current RTC time. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[out] p_Ts - returned time stamp (in nanoseconds). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_GetCurrentTime(t_Handle h_FmRtc, uint64_t *p_Ts); ++ ++/**************************************************************************//** ++ @Function FM_RTC_SetCurrentTime ++ ++ @Description Sets the current RTC time. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] ts - The new time stamp (in nanoseconds). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_SetCurrentTime(t_Handle h_FmRtc, uint64_t ts); ++ ++/**************************************************************************//** ++ @Function FM_RTC_GetFreqCompensation ++ ++ @Description Retrieves the frequency compensation value ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[out] p_Compensation - A pointer to the returned value of compensation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_GetFreqCompensation(t_Handle h_FmRtc, uint32_t *p_Compensation); ++ ++/**************************************************************************//** ++ @Function FM_RTC_SetFreqCompensation ++ ++ @Description Sets a new frequency compensation value. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] freqCompensation - The new frequency compensation value to set. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_SetFreqCompensation(t_Handle h_FmRtc, uint32_t freqCompensation); ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//** ++ @Function FM_RTC_DumpRegs ++ ++ @Description Dumps all FM registers ++ ++ @Param[in] h_FmRtc A handle to an FM RTC Module. ++ ++ @Return E_OK on success; ++ ++ @Cautions Allowed only FM_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_DumpRegs(t_Handle h_FmRtc); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++/** @} */ /* end of fm_rtc_control_grp */ ++/** @} */ /* end of fm_rtc_grp */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#endif /* __FM_RTC_EXT_H__ */ +diff --git a/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_vsp_ext.h b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_vsp_ext.h +new file mode 100644 +index 0000000..f9aed03 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/Peripherals/fm_vsp_ext.h +@@ -0,0 +1,411 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm_vsp_ext.h ++ ++ @Description FM Virtual Storage-Profile ... ++*//***************************************************************************/ ++#ifndef __FM_VSP_EXT_H ++#define __FM_VSP_EXT_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++ ++#include "fm_ext.h" ++ ++ ++/**************************************************************************//** ++ ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_VSP_grp FM Virtual-Storage-Profile ++ ++ @Description FM Virtual-Storage-Profile API ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_VSP_init_grp FM VSP Initialization Unit ++ ++ @Description FM VSP initialization API. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Virtual Storage Profile ++*//***************************************************************************/ ++typedef struct t_FmVspParams { ++ t_Handle h_Fm; /**< A handle to the FM object this VSP related to */ ++ t_FmExtPools extBufPools; /**< Which external buffer pools are used ++ (up to FM_PORT_MAX_NUM_OF_EXT_POOLS), and their sizes. ++ parameter associated with Rx / OP port */ ++ uint16_t liodnOffset; /**< VSP's LIODN offset */ ++ struct { ++ e_FmPortType portType; /**< Port type */ ++ uint8_t portId; /**< Port Id - relative to type */ ++ } portParams; ++ uint8_t relativeProfileId; /**< VSP Id - relative to VSP's range ++ defined in relevant FM object */ ++} t_FmVspParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_VSP_Config ++ ++ @Description Creates descriptor for the FM VSP module. ++ ++ The routine returns a handle (descriptor) to the FM VSP object. ++ This descriptor must be passed as first parameter to all other ++ FM VSP function calls. ++ ++ No actual initialization or configuration of FM hardware is ++ done by this routine. ++ ++@Param[in] p_FmVspParams Pointer to data structure of parameters ++ ++ @Retval Handle to FM VSP object, or NULL for Failure. ++*//***************************************************************************/ ++t_Handle FM_VSP_Config(t_FmVspParams *p_FmVspParams); ++ ++/**************************************************************************//** ++ @Function FM_VSP_Init ++ ++ @Description Initializes the FM VSP module ++ ++ @Param[in] h_FmVsp - FM VSP module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_VSP_Init(t_Handle h_FmVsp); ++ ++/**************************************************************************//** ++ @Function FM_VSP_Free ++ ++ @Description Frees all resources that were assigned to FM VSP module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmVsp - FM VSP module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_VSP_Free(t_Handle h_FmVsp); ++ ++ ++/**************************************************************************//** ++ @Group FM_VSP_adv_config_grp FM VSP Advanced Configuration Unit ++ ++ @Description FM VSP advanced configuration functions. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigBufferPrefixContent ++ ++ @Description Defines the structure, size and content of the application buffer. ++ ++ The prefix will ++ In VSPs defined for Tx ports, if 'passPrsResult', the application ++ should set a value to their offsets in the prefix of ++ the FM will save the first 'privDataSize', than, ++ depending on 'passPrsResult' and 'passTimeStamp', copy parse result ++ and timeStamp, and the packet itself (in this order), to the ++ application buffer, and to offset. ++ ++ Calling this routine changes the buffer margins definitions ++ in the internal driver data base from its default ++ configuration: Data size: [DEFAULT_FM_SP_bufferPrefixContent_privDataSize] ++ Pass Parser result: [DEFAULT_FM_SP_bufferPrefixContent_passPrsResult]. ++ Pass timestamp: [DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp]. ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in,out] p_FmBufferPrefixContent A structure of parameters describing the ++ structure of the buffer. ++ Out parameter: Start margin - offset ++ of data from start of external buffer. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigBufferPrefixContent(t_Handle h_FmVsp, ++ t_FmBufferPrefixContent *p_FmBufferPrefixContent); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigDmaSwapData ++ ++ @Description Calling this routine changes the DMA swap data parameter ++ in the internal driver data base from its default ++ configuration [DEFAULT_FM_SP_dmaSwapData] ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] swapData New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigDmaSwapData(t_Handle h_FmVsp, e_FmDmaSwapOption swapData); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigDmaIcCacheAttr ++ ++ @Description Calling this routine changes the internal context cache ++ attribute parameter in the internal driver data base ++ from its default configuration [DEFAULT_FM_SP_dmaIntContextCacheAttr] ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] intContextCacheAttr New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigDmaIcCacheAttr(t_Handle h_FmVsp, ++ e_FmDmaCacheOption intContextCacheAttr); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigDmaHdrAttr ++ ++ @Description Calling this routine changes the header cache ++ attribute parameter in the internal driver data base ++ from its default configuration [DEFAULT_FM_SP_dmaHeaderCacheAttr] ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] headerCacheAttr New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigDmaHdrAttr(t_Handle h_FmVsp, e_FmDmaCacheOption headerCacheAttr); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigDmaScatterGatherAttr ++ ++ @Description Calling this routine changes the scatter gather cache ++ attribute parameter in the internal driver data base ++ from its default configuration [DEFAULT_FM_SP_dmaScatterGatherCacheAttr] ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] scatterGatherCacheAttr New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigDmaScatterGatherAttr(t_Handle h_FmVsp, ++ e_FmDmaCacheOption scatterGatherCacheAttr); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigDmaWriteOptimize ++ ++ @Description Calling this routine changes the write optimization ++ parameter in the internal driver data base ++ from its default configuration: optimize = [DEFAULT_FM_SP_dmaWriteOptimize] ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] optimize TRUE to enable optimization, FALSE for normal operation ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigDmaWriteOptimize(t_Handle h_FmVsp, bool optimize); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigNoScatherGather ++ ++ @Description Calling this routine changes the possibility to receive S/G frame ++ in the internal driver data base ++ from its default configuration: optimize = [DEFAULT_FM_SP_noScatherGather] ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] noScatherGather TRUE to operate without scatter/gather capability. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigNoScatherGather(t_Handle h_FmVsp, bool noScatherGather); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigPoolDepletion ++ ++ @Description Calling this routine enables pause frame generation depending on the ++ depletion status of BM pools. It also defines the conditions to activate ++ this functionality. By default, this functionality is disabled. ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] p_BufPoolDepletion A structure of pool depletion parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigPoolDepletion(t_Handle h_FmVsp, t_FmBufPoolDepletion *p_BufPoolDepletion); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigBackupPools ++ ++ @Description Calling this routine allows the configuration of some of the BM pools ++ defined for this port as backup pools. ++ A pool configured to be a backup pool will be used only if all other ++ enabled non-backup pools are depleted. ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] p_BackupBmPools An array of pool id's. All pools specified here will ++ be defined as backup pools. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigBackupPools(t_Handle h_FmVsp, t_FmBackupBmPools *p_BackupBmPools); ++ ++/** @} */ /* end of FM_VSP_adv_config_grp group */ ++/** @} */ /* end of FM_VSP_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_VSP_control_grp FM VSP Control Unit ++ ++ @Description FM VSP runtime control API. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_VSP_GetBufferDataOffset ++ ++ @Description Relevant for Rx ports. ++ Returns the data offset from the beginning of the data buffer ++ ++ @Param[in] h_FmVsp - FM PORT module descriptor ++ ++ @Return data offset. ++ ++ @Cautions Allowed only following FM_VSP_Init(). ++*//***************************************************************************/ ++uint32_t FM_VSP_GetBufferDataOffset(t_Handle h_FmVsp); ++ ++/**************************************************************************//** ++ @Function FM_VSP_GetBufferICInfo ++ ++ @Description Returns the Internal Context offset from the beginning of the data buffer ++ ++ @Param[in] h_FmVsp - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return Internal context info pointer on success, NULL if 'allOtherInfo' was not ++ configured for this port. ++ ++ @Cautions Allowed only following FM_VSP_Init(). ++*//***************************************************************************/ ++uint8_t * FM_VSP_GetBufferICInfo(t_Handle h_FmVsp, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_VSP_GetBufferPrsResult ++ ++ @Description Returns the pointer to the parse result in the data buffer. ++ In Rx ports this is relevant after reception, if parse ++ result is configured to be part of the data passed to the ++ application. For non Rx ports it may be used to get the pointer ++ of the area in the buffer where parse result should be ++ initialized - if so configured. ++ See FM_VSP_ConfigBufferPrefixContent for data buffer prefix ++ configuration. ++ ++ @Param[in] h_FmVsp - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return Parse result pointer on success, NULL if parse result was not ++ configured for this port. ++ ++ @Cautions Allowed only following FM_VSP_Init(). ++*//***************************************************************************/ ++t_FmPrsResult * FM_VSP_GetBufferPrsResult(t_Handle h_FmVsp, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_VSP_GetBufferTimeStamp ++ ++ @Description Returns the time stamp in the data buffer. ++ Relevant for Rx ports for getting the buffer time stamp. ++ See FM_VSP_ConfigBufferPrefixContent for data buffer prefix ++ configuration. ++ ++ @Param[in] h_FmVsp - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return A pointer to the hash result on success, NULL otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Init(). ++*//***************************************************************************/ ++uint64_t * FM_VSP_GetBufferTimeStamp(t_Handle h_FmVsp, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_VSP_GetBufferHashResult ++ ++ @Description Given a data buffer, on the condition that hash result was defined ++ as a part of the buffer content (see FM_VSP_ConfigBufferPrefixContent) ++ this routine will return the pointer to the hash result location in the ++ buffer prefix. ++ ++ @Param[in] h_FmVsp - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return A pointer to the hash result on success, NULL otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Init(). ++*//***************************************************************************/ ++uint8_t * FM_VSP_GetBufferHashResult(t_Handle h_FmVsp, char *p_Data); ++ ++ ++/** @} */ /* end of FM_VSP_control_grp group */ ++/** @} */ /* end of FM_VSP_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#endif /* __FM_VSP_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/Peripherals/mii_acc_ext.h b/drivers/net/dpa/NetCommSw/inc/Peripherals/mii_acc_ext.h +new file mode 100644 +index 0000000..f635d3c +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/Peripherals/mii_acc_ext.h +@@ -0,0 +1,76 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __MII_ACC_EXT_H ++#define __MII_ACC_EXT_H ++ ++ ++/**************************************************************************//** ++ @Function MII_ReadPhyReg ++ ++ @Description This routine is called to read a specified PHY ++ register value. ++ ++ @Param[in] h_MiiAccess - Handle to MII configuration access registers ++ @Param[in] phyAddr - PHY address (0-31). ++ @Param[in] reg - PHY register to read ++ @Param[out] p_Data - Gets the register value. ++ ++ @Return Always zero (success). ++*//***************************************************************************/ ++int MII_ReadPhyReg(t_Handle h_MiiAccess, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t *p_Data); ++ ++/**************************************************************************//** ++ @Function MII_WritePhyReg ++ ++ @Description This routine is called to write data to a specified PHY ++ register. ++ ++ @Param[in] h_MiiAccess - Handle to MII configuration access registers ++ @Param[in] phyAddr - PHY address (0-31). ++ @Param[in] reg - PHY register to write ++ @Param[in] data - Data to write in register. ++ ++ @Return Always zero (success). ++*//***************************************************************************/ ++int MII_WritePhyReg(t_Handle h_MiiAccess, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t data); ++ ++ ++#endif /* __MII_ACC_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/core_ext.h b/drivers/net/dpa/NetCommSw/inc/core_ext.h +new file mode 100644 +index 0000000..9cd5669 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/core_ext.h +@@ -0,0 +1,85 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 core_ext.h ++ ++ @Description Generic interface to basic core operations. ++ ++ The system integrator must ensure that this interface is ++ mapped to a specific core implementation, by including the ++ appropriate header file. ++*//***************************************************************************/ ++#ifndef __CORE_EXT_H ++#define __CORE_EXT_H ++ ++ ++#ifdef NCSW_PPC_CORE ++#include "ppc_ext.h" ++#elif defined(NCSW_VXWORKS) ++#include "core_vxw_ext.h" ++#else ++#error "Core is not defined!" ++#endif /* NCSW_CORE */ ++ ++#if (!defined(CORE_IS_LITTLE_ENDIAN) && !defined(CORE_IS_BIG_ENDIAN)) ++#error "Must define core as little-endian or big-endian!" ++#endif /* (!defined(CORE_IS_LITTLE_ENDIAN) && ... */ ++ ++#ifndef CORE_CACHELINE_SIZE ++#error "Must define the core cache-line size!" ++#endif /* !CORE_CACHELINE_SIZE */ ++ ++ ++/**************************************************************************//** ++ @Function CORE_GetId ++ ++ @Description Returns the core ID in the system. ++ ++ @Return Core ID. ++*//***************************************************************************/ ++uint32_t CORE_GetId(void); ++ ++/**************************************************************************//** ++ @Function CORE_MemoryBarrier ++ ++ @Description This routine will cause the core to stop executing any commands ++ until all previous memory read/write commands are completely out ++ of the core's pipeline. ++ ++ @Return None. ++*//***************************************************************************/ ++void CORE_MemoryBarrier(void); ++#define fsl_mem_core_barrier() CORE_MemoryBarrier() ++ ++#endif /* __CORE_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/cores/e500v2_ext.h b/drivers/net/dpa/NetCommSw/inc/cores/e500v2_ext.h +new file mode 100644 +index 0000000..099c7b9 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/cores/e500v2_ext.h +@@ -0,0 +1,474 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 e500v2_ext.h ++ ++ @Description E500 external definitions prototypes ++ This file is not included by the E500 ++ source file as it is an assembly file. It is used ++ only for prototypes exposure, for inclusion ++ by user and other modules. ++*//***************************************************************************/ ++ ++#ifndef __E500V2_EXT_H ++#define __E500V2_EXT_H ++ ++#include "std_ext.h" ++ ++ ++/* Layer 1 Cache Manipulations ++ *============================== ++ * Should not be called directly by the user. ++ */ ++void L1DCache_Invalidate (void); ++void L1ICache_Invalidate(void); ++void L1DCache_Enable(void); ++void L1ICache_Enable(void); ++void L1DCache_Disable(void); ++void L1ICache_Disable(void); ++void L1DCache_Flush(void); ++void L1ICache_Flush(void); ++/* ++ * ++ */ ++uint32_t L1DCache_LineLock(uint32_t addr); ++uint32_t L1ICache_LineLock(uint32_t addr); ++void L1Cache_BroadCastEnable(void); ++void L1Cache_BroadCastDisable(void); ++ ++ ++#define CORE_DCacheEnable E500_DCacheEnable ++#define CORE_ICacheEnable E500_ICacheEnable ++#define CORE_DCacheDisable E500_DCacheDisable ++#define CORE_ICacheDisable E500_ICacheDisable ++#define CORE_GetId E500_GetId ++#define CORE_TestAndSet E500_TestAndSet ++#define CORE_MemoryBarrier E500_MemoryBarrier ++#define CORE_InstructionSync E500_InstructionSync ++ ++#define CORE_SetDozeMode E500_SetDozeMode ++#define CORE_SetNapMode E500_SetNapMode ++#define CORE_SetSleepMode E500_SetSleepMode ++#define CORE_SetJogMode E500_SetJogMode ++#define CORE_SetDeepSleepMode E500_SetDeepSleepMode ++ ++#define CORE_RecoverDozeMode E500_RecoverDozeMode ++#define CORE_RecoverNapMode E500_RecoverNapMode ++#define CORE_RecoverSleepMode E500_RecoverSleepMode ++#define CORE_RecoverJogMode E500_RecoverJogMode ++ ++void E500_SetDozeMode(void); ++void E500_SetNapMode(void); ++void E500_SetSleepMode(void); ++void E500_SetJogMode(void); ++t_Error E500_SetDeepSleepMode(uint32_t bptrAddress); ++ ++void E500_RecoverDozeMode(void); ++void E500_RecoverNapMode(void); ++void E500_RecoverSleepMode(void); ++void E500_RecoverJogMode(void); ++ ++ ++/**************************************************************************//** ++ @Group E500_id E500 Application Programming Interface ++ ++ @Description E500 API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group E500_init_grp E500 Initialization Unit ++ ++ @Description E500 initialization unit API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++ ++/**************************************************************************//** ++ @Function E500_DCacheEnable ++ ++ @Description Enables the data cache for memory pages that are ++ not cache inhibited. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_DCacheEnable(void); ++ ++/**************************************************************************//** ++ @Function E500_ICacheEnable ++ ++ @Description Enables the instruction cache for memory pages that are ++ not cache inhibited. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_ICacheEnable(void); ++ ++/**************************************************************************//** ++ @Function E500_DCacheDisable ++ ++ @Description Disables the data cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_DCacheDisable(void); ++ ++/**************************************************************************//** ++ @Function E500_ICacheDisable ++ ++ @Description Disables the instruction cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_ICacheDisable(void); ++ ++/**************************************************************************//** ++ @Function E500_DCacheFlush ++ ++ @Description Flushes the data cache ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_DCacheFlush(void); ++ ++/**************************************************************************//** ++ @Function E500_ICacheFlush ++ ++ @Description Flushes the instruction cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_ICacheFlush(void); ++ ++/**************************************************************************//** ++ @Function E500_DCacheSetStashId ++ ++ @Description Set Stash Id for data cache ++ ++ @Param[in] stashId the stash id to be set. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_DCacheSetStashId(uint8_t stashId); ++ ++/**************************************************************************//** ++ @Description E500mc L2 Cache Operation Mode ++*//***************************************************************************/ ++typedef enum e_E500mcL2CacheMode ++{ ++ e_L2_CACHE_MODE_DATA_ONLY = 0x00000001, /**< Cache data only */ ++ e_L2_CACHE_MODE_INST_ONLY = 0x00000002, /**< Cache instructions only */ ++ e_L2_CACHE_MODE_DATA_AND_INST = 0x00000003 /**< Cache data and instructions */ ++} e_E500mcL2CacheMode; ++ ++#if defined(CORE_E500MC) || defined(CORE_E5500) ++/**************************************************************************//** ++ @Function E500_L2CacheEnable ++ ++ @Description Enables the cache for memory pages that are not cache inhibited. ++ ++ @param[in] mode - L2 cache mode: data only, instruction only or instruction and data. ++ ++ @Return None. ++ ++ @Cautions This routine must be call only ONCE for both caches. I.e. it is ++ not possible to call this routine for i-cache and than to call ++ again for d-cache; The second call will override the first one. ++*//***************************************************************************/ ++void E500_L2CacheEnable(e_E500mcL2CacheMode mode); ++ ++/**************************************************************************//** ++ @Function E500_L2CacheDisable ++ ++ @Description Disables the cache (data instruction or both). ++ ++ @Return None. ++ ++*//***************************************************************************/ ++void E500_L2CacheDisable(void); ++ ++/**************************************************************************//** ++ @Function E500_L2CacheFlush ++ ++ @Description Flushes the cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_L2CacheFlush(void); ++ ++/**************************************************************************//** ++ @Function E500_L2SetStashId ++ ++ @Description Set Stash Id ++ ++ @Param[in] stashId the stash id to be set. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_L2SetStashId(uint8_t stashId); ++#endif /* defined(CORE_E500MC) || defined(CORE_E5500) */ ++ ++#ifdef CORE_E6500 ++/**************************************************************************//** ++ @Function E6500_L2CacheEnable ++ ++ @Description Enables the cache for memory pages that are not cache inhibited. ++ ++ @param[in] mode - L2 cache mode: support data & instruction only. ++ ++ @Return None. ++ ++ @Cautions This routine must be call only ONCE for both caches. I.e. it is ++ not possible to call this routine for i-cache and than to call ++ again for d-cache; The second call will override the first one. ++*//***************************************************************************/ ++void E6500_L2CacheEnable(uintptr_t clusterBase); ++ ++/**************************************************************************//** ++ @Function E6500_L2CacheDisable ++ ++ @Description Disables the cache (data instruction or both). ++ ++ @Return None. ++ ++*//***************************************************************************/ ++void E6500_L2CacheDisable(uintptr_t clusterBase); ++ ++/**************************************************************************//** ++ @Function E6500_L2CacheFlush ++ ++ @Description Flushes the cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void E6500_L2CacheFlush(uintptr_t clusterBase); ++ ++/**************************************************************************//** ++ @Function E6500_L2SetStashId ++ ++ @Description Set Stash Id ++ ++ @Param[in] stashId the stash id to be set. ++ ++ @Return None. ++*//***************************************************************************/ ++void E6500_L2SetStashId(uintptr_t clusterBase, uint8_t stashId); ++ ++/**************************************************************************//** ++ @Function E6500_GetCcsrBase ++ ++ @Description Obtain SoC CCSR base address ++ ++ @Param[in] None. ++ ++ @Return Physical CCSR base address. ++*//***************************************************************************/ ++physAddress_t E6500_GetCcsrBase(void); ++#endif /* CORE_E6500 */ ++ ++/**************************************************************************//** ++ @Function E500_AddressBusStreamingEnable ++ ++ @Description Enables address bus streaming on the CCB. ++ ++ This setting, along with the ECM streaming configuration ++ parameters, enables address bus streaming on the CCB. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_AddressBusStreamingEnable(void); ++ ++/**************************************************************************//** ++ @Function E500_AddressBusStreamingDisable ++ ++ @Description Disables address bus streaming on the CCB. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_AddressBusStreamingDisable(void); ++ ++/**************************************************************************//** ++ @Function E500_AddressBroadcastEnable ++ ++ @Description Enables address broadcast. ++ ++ The e500 broadcasts cache management instructions (dcbst, dcblc ++ (CT = 1), icblc (CT = 1), dcbf, dcbi, mbar, msync, tlbsync, icbi) ++ based on ABE. ABE must be set to allow management of external ++ L2 caches. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_AddressBroadcastEnable(void); ++ ++/**************************************************************************//** ++ @Function E500_AddressBroadcastDisable ++ ++ @Description Disables address broadcast. ++ ++ The e500 broadcasts cache management instructions (dcbst, dcblc ++ (CT = 1), icblc (CT = 1), dcbf, dcbi, mbar, msync, tlbsync, icbi) ++ based on ABE. ABE must be set to allow management of external ++ L2 caches. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_AddressBroadcastDisable(void); ++ ++/**************************************************************************//** ++ @Function E500_IsTaskletSupported ++ ++ @Description Checks if tasklets are supported by the e500 interrupt handler. ++ ++ @Retval TRUE - Tasklets are supported. ++ @Retval FALSE - Tasklets are not supported. ++*//***************************************************************************/ ++bool E500_IsTaskletSupported(void); ++ ++void E500_EnableTimeBase(void); ++void E500_DisableTimeBase(void); ++ ++uint64_t E500_GetTimeBaseTime(void); ++ ++void E500_GenericIntrInit(void); ++ ++t_Error E500_SetIntr(int ppcIntrSrc, ++ void (* Isr)(t_Handle handle), ++ t_Handle handle); ++ ++t_Error E500_ClearIntr(int ppcIntrSrc); ++ ++/**************************************************************************//** ++ @Function E500_GenericIntrHandler ++ ++ @Description This is the general e500 interrupt handler. ++ ++ It is called by the main assembly interrupt handler ++ when an exception occurs and no other function has been ++ assigned to this exception. ++ ++ @Param intrEntry - (In) The exception interrupt vector entry. ++*//***************************************************************************/ ++void E500_GenericIntrHandler(uint32_t intrEntry); ++ ++/**************************************************************************//** ++ @Function CriticalIntr ++ ++ @Description This is the specific critical e500 interrupt handler. ++ ++ It is called by the main assembly interrupt handler ++ when an critical interrupt. ++ ++ @Param intrEntry - (In) The exception interrupt vector entry. ++*//***************************************************************************/ ++void CriticalIntr(uint32_t intrEntry); ++ ++ ++/**************************************************************************//** ++ @Function E500_GetId ++ ++ @Description Returns the core ID in the system. ++ ++ @Return Core ID. ++*//***************************************************************************/ ++uint32_t E500_GetId(void); ++ ++/**************************************************************************//** ++ @Function E500_TestAndSet ++ ++ @Description This routine tries to atomically test-and-set an integer ++ in memory to a non-zero value. ++ ++ The memory will be set only if it is tested as zero, in which ++ case the routine returns the new non-zero value; otherwise the ++ routine returns zero. ++ ++ @Param[in] p - pointer to a volatile int in memory, on which test-and-set ++ operation should be made. ++ ++ @Retval Zero - Operation failed - memory was already set. ++ @Retval Non-zero - Operation succeeded - memory has been set. ++*//***************************************************************************/ ++int E500_TestAndSet(volatile int *p); ++ ++/**************************************************************************//** ++ @Function E500_MemoryBarrier ++ ++ @Description This routine will cause the core to stop executing any commands ++ until all previous memory read/write commands are completely out ++ of the core's pipeline. ++ ++ @Return None. ++*//***************************************************************************/ ++static __inline__ void E500_MemoryBarrier(void) ++{ ++#ifndef CORE_E500V2 ++ __asm__ ("mbar 1"); ++#else /* CORE_E500V2 */ ++ /**** ERRATA WORK AROUND START ****/ ++ /* ERRATA num: CPU1 */ ++ /* Description: "mbar MO = 1" instruction fails to order caching-inhibited ++ guarded loads and stores. */ ++ ++ /* "msync" instruction is used instead */ ++ ++ __asm__ ("msync"); ++ ++ /**** ERRATA WORK AROUND END ****/ ++#endif /* CORE_E500V2 */ ++} ++ ++/**************************************************************************//** ++ @Function E500_InstructionSync ++ ++ @Description This routine will cause the core to wait for previous instructions ++ (including any interrupts they generate) to complete before the ++ synchronization command executes, which purges all instructions ++ from the processor's pipeline and refetches the next instruction. ++ ++ @Return None. ++*//***************************************************************************/ ++static __inline__ void E500_InstructionSync(void) ++{ ++ __asm__ ("isync"); ++} ++ ++ ++/** @} */ /* end of E500_init_grp group */ ++/** @} */ /* end of E500_grp group */ ++ ++ ++#endif /* __E500V2_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/cores/ppc_ext.h b/drivers/net/dpa/NetCommSw/inc/cores/ppc_ext.h +new file mode 100644 +index 0000000..9344b3a +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/cores/ppc_ext.h +@@ -0,0 +1,141 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 ppc_ext.h ++ ++ @Description Core API for PowerPC cores ++ ++ These routines must be implemented by each specific PowerPC ++ core driver. ++*//***************************************************************************/ ++#ifndef __PPC_EXT_H ++#define __PPC_EXT_H ++ ++#include "part_ext.h" ++ ++ ++#define CORE_IS_BIG_ENDIAN ++ ++#if defined(CORE_E300) || defined(CORE_E500V2) ++#define CORE_CACHELINE_SIZE 32 ++#elif defined(CORE_E500MC) || defined(CORE_E5500) || defined(CORE_E6500) ++#define CORE_CACHELINE_SIZE 64 ++#else ++#error "Core not defined!" ++#endif /* defined(CORE_E300) || ... */ ++ ++ ++/**************************************************************************//** ++ @Function CORE_TestAndSet ++ ++ @Description This routine tries to atomically test-and-set an integer ++ in memory to a non-zero value. ++ ++ The memory will be set only if it is tested as zero, in which ++ case the routine returns the new non-zero value; otherwise the ++ routine returns zero. ++ ++ @Param[in] p - pointer to a volatile int in memory, on which test-and-set ++ operation should be made. ++ ++ @Retval Zero - Operation failed - memory was already set. ++ @Retval Non-zero - Operation succeeded - memory has been set. ++*//***************************************************************************/ ++int CORE_TestAndSet(volatile int *p); ++ ++/**************************************************************************//** ++ @Function CORE_InstructionSync ++ ++ @Description This routine will cause the core to wait for previous instructions ++ (including any interrupts they generate) to complete before the ++ synchronization command executes, which purges all instructions ++ from the processor's pipeline and refetches the next instruction. ++ ++ @Return None. ++*//***************************************************************************/ ++void CORE_InstructionSync(void); ++ ++/**************************************************************************//** ++ @Function CORE_DCacheEnable ++ ++ @Description Enables the data cache for memory pages that are ++ not cache inhibited. ++ ++ @Return None. ++*//***************************************************************************/ ++void CORE_DCacheEnable(void); ++ ++/**************************************************************************//** ++ @Function CORE_ICacheEnable ++ ++ @Description Enables the instruction cache for memory pages that are ++ not cache inhibited. ++ ++ @Return None. ++*//***************************************************************************/ ++void CORE_ICacheEnable(void); ++ ++/**************************************************************************//** ++ @Function CORE_DCacheDisable ++ ++ @Description Disables the data cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void CORE_DCacheDisable(void); ++ ++/**************************************************************************//** ++ @Function CORE_ICacheDisable ++ ++ @Description Disables the instruction cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void CORE_ICacheDisable(void); ++ ++ ++ ++#if defined(CORE_E300) ++#include "e300_ext.h" ++#elif defined(CORE_E500V2) || defined(CORE_E500MC) || defined(CORE_E5500) || defined(CORE_E6500) ++#include "e500v2_ext.h" ++#if !defined(NCSW_LINUX) ++#include "e500v2_asm_ext.h" ++#endif ++#else ++#error "Core not defined!" ++#endif ++ ++ ++#endif /* __PPC_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/ctype_ext.h b/drivers/net/dpa/NetCommSw/inc/ctype_ext.h +new file mode 100644 +index 0000000..e3d5d8d +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/ctype_ext.h +@@ -0,0 +1,94 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __CTYPE_EXT_H ++#define __CTYPE_EXT_H ++ ++ ++#if defined(NCSW_LINUX) && defined(__KERNEL__) ++/* ++ * NOTE! This ctype does not handle EOF like the standard C ++ * library is required to. ++ */ ++ ++#define _U 0x01 /* upper */ ++#define _L 0x02 /* lower */ ++#define _D 0x04 /* digit */ ++#define _C 0x08 /* cntrl */ ++#define _P 0x10 /* punct */ ++#define _S 0x20 /* white space (space/lf/tab) */ ++#define _X 0x40 /* hex digit */ ++#define _SP 0x80 /* hard space (0x20) */ ++ ++extern unsigned char _ctype[]; ++ ++#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) ++ ++#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) ++#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) ++#define iscntrl(c) ((__ismask(c)&(_C)) != 0) ++#define isdigit(c) ((__ismask(c)&(_D)) != 0) ++#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) ++#define islower(c) ((__ismask(c)&(_L)) != 0) ++#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) ++#define ispunct(c) ((__ismask(c)&(_P)) != 0) ++#define isspace(c) ((__ismask(c)&(_S)) != 0) ++#define isupper(c) ((__ismask(c)&(_U)) != 0) ++#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) ++ ++#define isascii(c) (((unsigned char)(c))<=0x7f) ++#define toascii(c) (((unsigned char)(c))&0x7f) ++ ++static __inline__ unsigned char __tolower(unsigned char c) ++{ ++ if (isupper(c)) ++ c -= 'A'-'a'; ++ return c; ++} ++ ++static __inline__ unsigned char __toupper(unsigned char c) ++{ ++ if (islower(c)) ++ c -= 'a'-'A'; ++ return c; ++} ++ ++#define tolower(c) __tolower(c) ++#define toupper(c) __toupper(c) ++ ++#else ++#include ++#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */ ++ ++ ++#endif /* __CTYPE_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/ddr_std_ext.h b/drivers/net/dpa/NetCommSw/inc/ddr_std_ext.h +new file mode 100644 +index 0000000..4e94922 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/ddr_std_ext.h +@@ -0,0 +1,75 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __DDR_SDT_EXT_H ++#define __DDR_SDT_EXT_H ++ ++ ++/**************************************************************************//** ++ @Group ddr_Generic_Resources ++ ++ @Description ddr generic functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++ ++/**************************************************************************//** ++ @Description SPD maximum size ++*//***************************************************************************/ ++#define SPD_MAX_SIZE 256 ++ ++/**************************************************************************//** ++ @Description DDR types select ++*//***************************************************************************/ ++typedef enum e_DdrType ++{ ++ e_DDR_DDR1, ++ e_DDR_DDR2, ++ e_DDR_DDR3, ++ e_DDR_DDR3L ++} e_DdrType; ++ ++/**************************************************************************//** ++ @Description DDR Mode. ++*//***************************************************************************/ ++typedef enum e_DdrMode ++{ ++ e_DDR_BUS_WIDTH_32BIT, ++ e_DDR_BUS_WIDTH_64BIT ++} e_DdrMode; ++ ++/** @} */ /* end of ddr_Generic_Resources group */ ++ ++ ++ ++#endif /* __DDR_SDT_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/debug_ext.h b/drivers/net/dpa/NetCommSw/inc/debug_ext.h +new file mode 100644 +index 0000000..00ae748 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/debug_ext.h +@@ -0,0 +1,265 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 debug_ext.h ++ ++ @Description Debug mode definitions. ++*//***************************************************************************/ ++ ++#ifndef __DEBUG_EXT_H ++#define __DEBUG_EXT_H ++ ++#include "std_ext.h" ++#include "xx_ext.h" ++#include "memcpy_ext.h" ++#if (DEBUG_ERRORS > 0) ++#include "sprint_ext.h" ++#include "string_ext.h" ++#endif /* DEBUG_ERRORS > 0 */ ++ ++ ++#if (DEBUG_ERRORS > 0) ++ ++/* Internally used macros */ ++ ++#define DUMP_Print XX_Print ++#define DUMP_MAX_LEVELS 6 ++#define DUMP_MAX_STR 64 ++ ++ ++#define _CREATE_DUMP_SUBSTR(phrase) \ ++ dumpTmpLevel = 0; dumpSubStr[0] = '\0'; \ ++ sprintf(dumpTmpStr, "%s", #phrase); \ ++ p_DumpToken = strtok(dumpTmpStr, (dumpIsArr[0] ? "[" : ".")); \ ++ while (p_DumpToken != NULL) \ ++ { \ ++ strcat(dumpSubStr, p_DumpToken); \ ++ if (dumpIsArr[dumpTmpLevel]) \ ++ { \ ++ strcat(dumpSubStr, dumpIdxStr[dumpTmpLevel]); \ ++ p_DumpToken = strtok(NULL, "."); \ ++ } \ ++ if ((p_DumpToken = strtok(NULL, (dumpIsArr[++dumpTmpLevel] ? "[" : "."))) != 0) \ ++ strcat(dumpSubStr, "."); \ ++ }\ ++ ++ ++/**************************************************************************//** ++ @Group gen_id General Drivers Utilities ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group dump_id Memory and Registers Dump Mechanism ++ ++ @Description Macros for dumping memory mapped structures. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Declaration of dump mechanism variables. ++ ++ This macro must be declared at the beginning of each routine ++ which uses the dump mechanism macros, before the routine's code ++ starts. ++*//***************************************************************************/ ++#define DECLARE_DUMP \ ++ char dumpIdxStr[DUMP_MAX_LEVELS + 1][6] = { "", }; \ ++ char dumpSubStr[DUMP_MAX_STR] = ""; \ ++ char dumpTmpStr[DUMP_MAX_STR] = ""; \ ++ char *p_DumpToken = NULL; \ ++ int dumpArrIdx = 0, dumpArrSize = 0, dumpVarSize = 0, dumpLevel = 0, dumpTmpLevel = 0; \ ++ uint8_t dumpIsArr[DUMP_MAX_LEVELS + 1] = { 0 }; \ ++ /* Prevent warnings if not all used */ \ ++ UNUSED(dumpIdxStr[0][0]); \ ++ UNUSED(dumpSubStr[0]); \ ++ UNUSED(dumpTmpStr[0]); \ ++ UNUSED(p_DumpToken); \ ++ UNUSED(dumpArrIdx); \ ++ UNUSED(dumpArrSize); \ ++ UNUSED(dumpVarSize); \ ++ UNUSED(dumpLevel); \ ++ UNUSED(dumpTmpLevel); \ ++ UNUSED(dumpIsArr[0]); ++ ++ ++/**************************************************************************//** ++ @Description Prints a title for a subsequent dumped structure or memory. ++ ++ The inputs for this macro are the structure/memory title and ++ its base addresses. ++*//***************************************************************************/ ++#define DUMP_TITLE(addr, msg) \ ++ DUMP_Print("\r\n"); DUMP_Print msg; \ ++ if (addr) \ ++ DUMP_Print(" (%p)", (addr)); \ ++ DUMP_Print("\r\n---------------------------------------------------------\r\n"); ++ ++/**************************************************************************//** ++ @Description Prints a subtitle for a subsequent dumped sub-structure (optional). ++ ++ The inputs for this macro are the sub-structure subtitle. ++ A separating line with this subtitle will be printed. ++*//***************************************************************************/ ++#define DUMP_SUBTITLE(subtitle) \ ++ DUMP_Print("----------- "); DUMP_Print subtitle; DUMP_Print("\r\n") ++ ++ ++/**************************************************************************//** ++ @Description Dumps a memory region in 4-bytes aligned format. ++ ++ The inputs for this macro are the base addresses and size ++ (in bytes) of the memory region. ++*//***************************************************************************/ ++#define DUMP_MEMORY(addr, size) \ ++ MemDisp((uint8_t *)(addr), (int)(size)) ++ ++ ++/**************************************************************************//** ++ @Description Declares a dump loop, for dumping a sub-structure array. ++ ++ The inputs for this macro are: ++ - idx: an index variable, for indexing the sub-structure items ++ inside the loop. This variable must be declared separately ++ in the beginning of the routine. ++ - cnt: the number of times to repeat the loop. This number should ++ equal the number of items in the sub-structures array. ++ ++ Note, that the body of the loop must be written inside brackets. ++*//***************************************************************************/ ++#define DUMP_SUBSTRUCT_ARRAY(idx, cnt) \ ++ for (idx=0, dumpIsArr[dumpLevel++] = 1; \ ++ (idx < cnt) && sprintf(dumpIdxStr[dumpLevel-1], "[%d]", idx); \ ++ idx++, ((idx < cnt) || ((dumpIsArr[--dumpLevel] = 0) == 0))) ++ ++ ++/**************************************************************************//** ++ @Description Dumps a structure's member variable. ++ ++ The input for this macro is the full reference for the member ++ variable, where the structure is referenced using a pointer. ++ ++ Note, that a members array must be dumped using DUMP_ARR macro, ++ rather than using this macro. ++ ++ If the member variable is part of a sub-structure hierarchy, ++ the full hierarchy (including array indexing) must be specified. ++ ++ Examples: p_Struct->member ++ p_Struct->sub.member ++ p_Struct->sub[i].member ++*//***************************************************************************/ ++#define DUMP_VAR(st, phrase) \ ++ do { \ ++ void *addr = (void *)&((st)->phrase); \ ++ physAddress_t physAddr = XX_VirtToPhys(addr); \ ++ _CREATE_DUMP_SUBSTR(phrase); \ ++ dumpVarSize = sizeof((st)->phrase); \ ++ switch (dumpVarSize) \ ++ { \ ++ case 1: DUMP_Print("0x%010llX: 0x%02x%14s\t%s\r\n", \ ++ physAddr, GET_UINT8(*(uint8_t*)addr), "", dumpSubStr); break; \ ++ case 2: DUMP_Print("0x%010llX: 0x%04x%12s\t%s\r\n", \ ++ physAddr, GET_UINT16(*(uint16_t*)addr), "", dumpSubStr); break; \ ++ case 4: DUMP_Print("0x%010llX: 0x%08x%8s\t%s\r\n", \ ++ physAddr, GET_UINT32(*(uint32_t*)addr), "", dumpSubStr); break; \ ++ case 8: DUMP_Print("0x%010llX: 0x%016llx\t%s\r\n", \ ++ physAddr, GET_UINT64(*(uint64_t*)addr), dumpSubStr); break; \ ++ default: DUMP_Print("Bad size %d (" #st "->" #phrase ")\r\n", dumpVarSize); \ ++ } \ ++ } while (0) ++ ++ ++/**************************************************************************//** ++ @Description Dumps a structure's members array. ++ ++ The input for this macro is the full reference for the members ++ array, where the structure is referenced using a pointer. ++ ++ If the members array is part of a sub-structure hierarchy, ++ the full hierarchy (including array indexing) must be specified. ++ ++ Examples: p_Struct->array ++ p_Struct->sub.array ++ p_Struct->sub[i].array ++*//***************************************************************************/ ++#define DUMP_ARR(st, phrase) \ ++ do { \ ++ physAddress_t physAddr; \ ++ _CREATE_DUMP_SUBSTR(phrase); \ ++ dumpArrSize = ARRAY_SIZE((st)->phrase); \ ++ dumpVarSize = sizeof((st)->phrase[0]); \ ++ switch (dumpVarSize) \ ++ { \ ++ case 1: \ ++ for (dumpArrIdx=0; dumpArrIdx < dumpArrSize; dumpArrIdx++) { \ ++ physAddr = XX_VirtToPhys((void *)&((st)->phrase[dumpArrIdx])); \ ++ DUMP_Print("0x%010llX: 0x%02x%14s\t%s[%d]\r\n", \ ++ physAddr, GET_UINT8((st)->phrase[dumpArrIdx]), "", dumpSubStr, dumpArrIdx); \ ++ } break; \ ++ case 2: \ ++ for (dumpArrIdx=0; dumpArrIdx < dumpArrSize; dumpArrIdx++) { \ ++ physAddr = XX_VirtToPhys((void *)&((st)->phrase[dumpArrIdx])); \ ++ DUMP_Print("0x%010llX: 0x%04x%12s\t%s[%d]\r\n", \ ++ physAddr, GET_UINT16((st)->phrase[dumpArrIdx]), "", dumpSubStr, dumpArrIdx); \ ++ } break; \ ++ case 4: \ ++ for (dumpArrIdx=0; dumpArrIdx < dumpArrSize; dumpArrIdx++) { \ ++ physAddr = XX_VirtToPhys((void *)&((st)->phrase[dumpArrIdx])); \ ++ DUMP_Print("0x%010llX: 0x%08x%8s\t%s[%d]\r\n", \ ++ physAddr, GET_UINT32((st)->phrase[dumpArrIdx]), "", dumpSubStr, dumpArrIdx); \ ++ } break; \ ++ case 8: \ ++ for (dumpArrIdx=0; dumpArrIdx < dumpArrSize; dumpArrIdx++) { \ ++ physAddr = XX_VirtToPhys((void *)&((st)->phrase[dumpArrIdx])); \ ++ DUMP_Print("0x%010llX: 0x%016llx\t%s[%d]\r\n", \ ++ physAddr, GET_UINT64((st)->phrase[dumpArrIdx]), dumpSubStr, dumpArrIdx); \ ++ } break; \ ++ default: DUMP_Print("Bad size %d (" #st "->" #phrase "[0])\r\n", dumpVarSize); \ ++ } \ ++ } while (0) ++ ++ ++#endif /* DEBUG_ERRORS > 0 */ ++ ++ ++/** @} */ /* end of dump_id group */ ++/** @} */ /* end of gen_id group */ ++ ++ ++#endif /* __DEBUG_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/endian_ext.h b/drivers/net/dpa/NetCommSw/inc/endian_ext.h +new file mode 100644 +index 0000000..252f89b +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/endian_ext.h +@@ -0,0 +1,446 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 endian_ext.h ++ ++ @Description Big/little endian swapping routines. ++*//***************************************************************************/ ++ ++#ifndef __ENDIAN_EXT_H ++#define __ENDIAN_EXT_H ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group gen_id General Drivers Utilities ++ ++ @Description General usage API. This API is intended for usage by both the ++ internal modules and the user's application. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group endian_id Big/Little-Endian Conversion ++ ++ @Description Routines and macros for Big/Little-Endian conversion and ++ general byte swapping. ++ ++ All routines and macros are expecting unsigned values as ++ parameters, but will generate the correct result also for ++ signed values. Therefore, signed/unsigned casting is allowed. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection Byte-Swap Macros ++ ++ Macros for swapping byte order. ++ ++ @Cautions The parameters of these macros are evaluated multiple times. ++ For calculated expressions or expressions that contain function ++ calls it is recommended to use the byte-swap routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Swaps the byte order of a given 16-bit value. ++ ++ @Param[in] val - The 16-bit value to swap. ++ ++ @Return The byte-swapped value.. ++ ++ @Cautions The given value is evaluated multiple times by this macro. ++ For calculated expressions or expressions that contain function ++ calls it is recommended to use the SwapUint16() routine. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define SWAP_UINT16(val) \ ++ ((uint16_t)((((val) & 0x00FF) << 8) | (((val) & 0xFF00) >> 8))) ++ ++/**************************************************************************//** ++ @Description Swaps the byte order of a given 32-bit value. ++ ++ @Param[in] val - The 32-bit value to swap. ++ ++ @Return The byte-swapped value.. ++ ++ @Cautions The given value is evaluated multiple times by this macro. ++ For calculated expressions or expressions that contain function ++ calls it is recommended to use the SwapUint32() routine. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define SWAP_UINT32(val) \ ++ ((uint32_t)((((val) & 0x000000FF) << 24) | \ ++ (((val) & 0x0000FF00) << 8) | \ ++ (((val) & 0x00FF0000) >> 8) | \ ++ (((val) & 0xFF000000) >> 24))) ++ ++/**************************************************************************//** ++ @Description Swaps the byte order of a given 64-bit value. ++ ++ @Param[in] val - The 64-bit value to swap. ++ ++ @Return The byte-swapped value.. ++ ++ @Cautions The given value is evaluated multiple times by this macro. ++ For calculated expressions or expressions that contain function ++ calls it is recommended to use the SwapUint64() routine. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define SWAP_UINT64(val) \ ++ ((uint64_t)((((val) & 0x00000000000000FFULL) << 56) | \ ++ (((val) & 0x000000000000FF00ULL) << 40) | \ ++ (((val) & 0x0000000000FF0000ULL) << 24) | \ ++ (((val) & 0x00000000FF000000ULL) << 8) | \ ++ (((val) & 0x000000FF00000000ULL) >> 8) | \ ++ (((val) & 0x0000FF0000000000ULL) >> 24) | \ ++ (((val) & 0x00FF000000000000ULL) >> 40) | \ ++ (((val) & 0xFF00000000000000ULL) >> 56))) ++ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection Byte-Swap Routines ++ ++ Routines for swapping the byte order of a given parameter and ++ returning the swapped value. ++ ++ These inline routines are safer than the byte-swap macros, ++ because they evaluate the parameter expression only once. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function SwapUint16 ++ ++ @Description Returns the byte-swapped value of a given 16-bit value. ++ ++ @Param[in] val - The 16-bit value. ++ ++ @Return The byte-swapped value of the parameter. ++*//***************************************************************************/ ++static __inline__ uint16_t SwapUint16(uint16_t val) ++{ ++ return (uint16_t)(((val & 0x00FF) << 8) | ++ ((val & 0xFF00) >> 8)); ++} ++ ++/**************************************************************************//** ++ @Function SwapUint32 ++ ++ @Description Returns the byte-swapped value of a given 32-bit value. ++ ++ @Param[in] val - The 32-bit value. ++ ++ @Return The byte-swapped value of the parameter. ++*//***************************************************************************/ ++static __inline__ uint32_t SwapUint32(uint32_t val) ++{ ++ return (uint32_t)(((val & 0x000000FF) << 24) | ++ ((val & 0x0000FF00) << 8) | ++ ((val & 0x00FF0000) >> 8) | ++ ((val & 0xFF000000) >> 24)); ++} ++ ++/**************************************************************************//** ++ @Function SwapUint64 ++ ++ @Description Returns the byte-swapped value of a given 64-bit value. ++ ++ @Param[in] val - The 64-bit value. ++ ++ @Return The byte-swapped value of the parameter. ++*//***************************************************************************/ ++static __inline__ uint64_t SwapUint64(uint64_t val) ++{ ++ return (uint64_t)(((val & 0x00000000000000FFULL) << 56) | ++ ((val & 0x000000000000FF00ULL) << 40) | ++ ((val & 0x0000000000FF0000ULL) << 24) | ++ ((val & 0x00000000FF000000ULL) << 8) | ++ ((val & 0x000000FF00000000ULL) >> 8) | ++ ((val & 0x0000FF0000000000ULL) >> 24) | ++ ((val & 0x00FF000000000000ULL) >> 40) | ++ ((val & 0xFF00000000000000ULL) >> 56)); ++} ++ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection In-place Byte-Swap-And-Set Routines ++ ++ Routines for swapping the byte order of a given variable and ++ setting the swapped value back to the same variable. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function SwapUint16P ++ ++ @Description Swaps the byte order of a given 16-bit variable. ++ ++ @Param[in] p_Val - Pointer to the 16-bit variable. ++ ++ @Return None. ++*//***************************************************************************/ ++static __inline__ void SwapUint16P(uint16_t *p_Val) ++{ ++ *p_Val = SwapUint16(*p_Val); ++} ++ ++/**************************************************************************//** ++ @Function SwapUint32P ++ ++ @Description Swaps the byte order of a given 32-bit variable. ++ ++ @Param[in] p_Val - Pointer to the 32-bit variable. ++ ++ @Return None. ++*//***************************************************************************/ ++static __inline__ void SwapUint32P(uint32_t *p_Val) ++{ ++ *p_Val = SwapUint32(*p_Val); ++} ++ ++/**************************************************************************//** ++ @Function SwapUint64P ++ ++ @Description Swaps the byte order of a given 64-bit variable. ++ ++ @Param[in] p_Val - Pointer to the 64-bit variable. ++ ++ @Return None. ++*//***************************************************************************/ ++static __inline__ void SwapUint64P(uint64_t *p_Val) ++{ ++ *p_Val = SwapUint64(*p_Val); ++} ++ ++/* @} */ ++ ++ ++/**************************************************************************//** ++ @Collection Little-Endian Conversion Macros ++ ++ These macros convert given parameters to or from Little-Endian ++ format. Use these macros when you want to read or write a specific ++ Little-Endian value in memory, without a-priori knowing the CPU ++ byte order. ++ ++ These macros use the byte-swap routines. For conversion of ++ constants in initialization structures, you may use the CONST ++ versions of these macros (see below), which are using the ++ byte-swap macros instead. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Converts a given 16-bit value from CPU byte order to ++ Little-Endian byte order. ++ ++ @Param[in] val - The 16-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CPU_TO_LE16(val) SwapUint16(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 32-bit value from CPU byte order to ++ Little-Endian byte order. ++ ++ @Param[in] val - The 32-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CPU_TO_LE32(val) SwapUint32(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 64-bit value from CPU byte order to ++ Little-Endian byte order. ++ ++ @Param[in] val - The 64-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CPU_TO_LE64(val) SwapUint64(val) ++ ++ ++/**************************************************************************//** ++ @Description Converts a given 16-bit value from Little-Endian byte order to ++ CPU byte order. ++ ++ @Param[in] val - The 16-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define LE16_TO_CPU(val) CPU_TO_LE16(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 32-bit value from Little-Endian byte order to ++ CPU byte order. ++ ++ @Param[in] val - The 32-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define LE32_TO_CPU(val) CPU_TO_LE32(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 64-bit value from Little-Endian byte order to ++ CPU byte order. ++ ++ @Param[in] val - The 64-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define LE64_TO_CPU(val) CPU_TO_LE64(val) ++ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection Little-Endian Constant Conversion Macros ++ ++ These macros convert given constants to or from Little-Endian ++ format. Use these macros when you want to read or write a specific ++ Little-Endian constant in memory, without a-priori knowing the ++ CPU byte order. ++ ++ These macros use the byte-swap macros, therefore can be used for ++ conversion of constants in initialization structures. ++ ++ @Cautions The parameters of these macros are evaluated multiple times. ++ For non-constant expressions, use the non-CONST macro versions. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Converts a given 16-bit constant from CPU byte order to ++ Little-Endian byte order. ++ ++ @Param[in] val - The 16-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CONST_CPU_TO_LE16(val) SWAP_UINT16(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 32-bit constant from CPU byte order to ++ Little-Endian byte order. ++ ++ @Param[in] val - The 32-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CONST_CPU_TO_LE32(val) SWAP_UINT32(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 64-bit constant from CPU byte order to ++ Little-Endian byte order. ++ ++ @Param[in] val - The 64-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CONST_CPU_TO_LE64(val) SWAP_UINT64(val) ++ ++ ++/**************************************************************************//** ++ @Description Converts a given 16-bit constant from Little-Endian byte order ++ to CPU byte order. ++ ++ @Param[in] val - The 16-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CONST_LE16_TO_CPU(val) CONST_CPU_TO_LE16(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 32-bit constant from Little-Endian byte order ++ to CPU byte order. ++ ++ @Param[in] val - The 32-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CONST_LE32_TO_CPU(val) CONST_CPU_TO_LE32(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 64-bit constant from Little-Endian byte order ++ to CPU byte order. ++ ++ @Param[in] val - The 64-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CONST_LE64_TO_CPU(val) CONST_CPU_TO_LE64(val) ++ ++/* @} */ ++ ++ ++/** @} */ /* end of endian_id group */ ++/** @} */ /* end of gen_id group */ ++ ++ ++#endif /* __ENDIAN_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/enet_ext.h b/drivers/net/dpa/NetCommSw/inc/enet_ext.h +new file mode 100644 +index 0000000..c6b9071 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/enet_ext.h +@@ -0,0 +1,203 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 enet_ext.h ++ ++ @Description Ethernet generic definitions and enums. ++*//***************************************************************************/ ++ ++#ifndef __ENET_EXT_H ++#define __ENET_EXT_H ++ ++#include "fsl_enet.h" ++ ++#define ENET_NUM_OCTETS_PER_ADDRESS 6 /**< Number of octets (8-bit bytes) in an ethernet address */ ++#define ENET_GROUP_ADDR 0x01 /**< Group address mask for ethernet addresses */ ++ ++ ++/**************************************************************************//** ++ @Description Ethernet Address ++*//***************************************************************************/ ++typedef uint8_t t_EnetAddr[ENET_NUM_OCTETS_PER_ADDRESS]; ++ ++/**************************************************************************//** ++ @Description Ethernet Address Type. ++*//***************************************************************************/ ++typedef enum e_EnetAddrType ++{ ++ e_ENET_ADDR_TYPE_INDIVIDUAL, /**< Individual (unicast) address */ ++ e_ENET_ADDR_TYPE_GROUP, /**< Group (multicast) address */ ++ e_ENET_ADDR_TYPE_BROADCAST /**< Broadcast address */ ++} e_EnetAddrType; ++ ++/**************************************************************************//** ++ @Description Ethernet MAC-PHY Interface ++*//***************************************************************************/ ++typedef enum e_EnetInterface ++{ ++ e_ENET_IF_MII = E_ENET_IF_MII, /**< MII interface */ ++ e_ENET_IF_RMII = E_ENET_IF_RMII, /**< RMII interface */ ++ e_ENET_IF_SMII = E_ENET_IF_SMII, /**< SMII interface */ ++ e_ENET_IF_GMII = E_ENET_IF_GMII, /**< GMII interface */ ++ e_ENET_IF_RGMII = E_ENET_IF_RGMII, /**< RGMII interface */ ++ e_ENET_IF_TBI = E_ENET_IF_TBI, /**< TBI interface */ ++ e_ENET_IF_RTBI = E_ENET_IF_RTBI, /**< RTBI interface */ ++ e_ENET_IF_SGMII = E_ENET_IF_SGMII, /**< SGMII interface */ ++ e_ENET_IF_XGMII = E_ENET_IF_XGMII, /**< XGMII interface */ ++ e_ENET_IF_QSGMII= E_ENET_IF_QSGMII, /**< QSGMII interface */ ++ e_ENET_IF_XFI = E_ENET_IF_XFI /**< XFI interface */ ++} e_EnetInterface; ++ ++#define ENET_IF_SGMII_BASEX 0x80000000 /**< SGMII/QSGII interface with 1000BaseX ++ auto-negotiation between MAC and phy ++ or backplane; ++ Note: 1000BaseX auto-negotiation relates ++ only to interface between MAC and phy/backplane, ++ SGMII phy can still synchronize with far-end phy ++ at 10Mbps, 100Mbps or 1000Mbps */ ++ ++/**************************************************************************//** ++ @Description Ethernet Duplex Mode ++*//***************************************************************************/ ++typedef enum e_EnetDuplexMode ++{ ++ e_ENET_HALF_DUPLEX, /**< Half-Duplex mode */ ++ e_ENET_FULL_DUPLEX /**< Full-Duplex mode */ ++} e_EnetDuplexMode; ++ ++/**************************************************************************//** ++ @Description Ethernet Speed (nominal data rate) ++*//***************************************************************************/ ++typedef enum e_EnetSpeed ++{ ++ e_ENET_SPEED_10 = E_ENET_SPEED_10, /**< 10 Mbps */ ++ e_ENET_SPEED_100 = E_ENET_SPEED_100, /**< 100 Mbps */ ++ e_ENET_SPEED_1000 = E_ENET_SPEED_1000, /**< 1000 Mbps = 1 Gbps */ ++ e_ENET_SPEED_10000 = E_ENET_SPEED_10000 /**< 10000 Mbps = 10 Gbps */ ++} e_EnetSpeed; ++ ++/**************************************************************************//** ++ @Description Ethernet mode (combination of MAC-PHY interface and speed) ++*//***************************************************************************/ ++typedef enum e_EnetMode ++{ ++ e_ENET_MODE_INVALID = 0, /**< Invalid Ethernet mode */ ++ e_ENET_MODE_MII_10 = (e_ENET_IF_MII | e_ENET_SPEED_10), /**< 10 Mbps MII */ ++ e_ENET_MODE_MII_100 = (e_ENET_IF_MII | e_ENET_SPEED_100), /**< 100 Mbps MII */ ++ e_ENET_MODE_RMII_10 = (e_ENET_IF_RMII | e_ENET_SPEED_10), /**< 10 Mbps RMII */ ++ e_ENET_MODE_RMII_100 = (e_ENET_IF_RMII | e_ENET_SPEED_100), /**< 100 Mbps RMII */ ++ e_ENET_MODE_SMII_10 = (e_ENET_IF_SMII | e_ENET_SPEED_10), /**< 10 Mbps SMII */ ++ e_ENET_MODE_SMII_100 = (e_ENET_IF_SMII | e_ENET_SPEED_100), /**< 100 Mbps SMII */ ++ e_ENET_MODE_GMII_1000 = (e_ENET_IF_GMII | e_ENET_SPEED_1000), /**< 1000 Mbps GMII */ ++ e_ENET_MODE_RGMII_10 = (e_ENET_IF_RGMII | e_ENET_SPEED_10), /**< 10 Mbps RGMII */ ++ e_ENET_MODE_RGMII_100 = (e_ENET_IF_RGMII | e_ENET_SPEED_100), /**< 100 Mbps RGMII */ ++ e_ENET_MODE_RGMII_1000 = (e_ENET_IF_RGMII | e_ENET_SPEED_1000), /**< 1000 Mbps RGMII */ ++ e_ENET_MODE_TBI_1000 = (e_ENET_IF_TBI | e_ENET_SPEED_1000), /**< 1000 Mbps TBI */ ++ e_ENET_MODE_RTBI_1000 = (e_ENET_IF_RTBI | e_ENET_SPEED_1000), /**< 1000 Mbps RTBI */ ++ e_ENET_MODE_SGMII_10 = (e_ENET_IF_SGMII | e_ENET_SPEED_10), ++ /**< 10 Mbps SGMII with auto-negotiation between MAC and ++ SGMII phy according to Cisco SGMII specification */ ++ e_ENET_MODE_SGMII_100 = (e_ENET_IF_SGMII | e_ENET_SPEED_100), ++ /**< 100 Mbps SGMII with auto-negotiation between MAC and ++ SGMII phy according to Cisco SGMII specification */ ++ e_ENET_MODE_SGMII_1000 = (e_ENET_IF_SGMII | e_ENET_SPEED_1000), ++ /**< 1000 Mbps SGMII with auto-negotiation between MAC and ++ SGMII phy according to Cisco SGMII specification */ ++ e_ENET_MODE_SGMII_BASEX_10 = (ENET_IF_SGMII_BASEX | e_ENET_IF_SGMII | e_ENET_SPEED_10), ++ /**< 10 Mbps SGMII with 1000BaseX auto-negotiation between ++ MAC and SGMII phy or backplane */ ++ e_ENET_MODE_SGMII_BASEX_100 = (ENET_IF_SGMII_BASEX | e_ENET_IF_SGMII | e_ENET_SPEED_100), ++ /**< 100 Mbps SGMII with 1000BaseX auto-negotiation between ++ MAC and SGMII phy or backplane */ ++ e_ENET_MODE_SGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | e_ENET_IF_SGMII | e_ENET_SPEED_1000), ++ /**< 1000 Mbps SGMII with 1000BaseX auto-negotiation between ++ MAC and SGMII phy or backplane */ ++ e_ENET_MODE_QSGMII_1000 = (e_ENET_IF_QSGMII| e_ENET_SPEED_1000), ++ /**< 1000 Mbps QSGMII with auto-negotiation between MAC and ++ QSGMII phy according to Cisco QSGMII specification */ ++ e_ENET_MODE_QSGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | e_ENET_IF_QSGMII| e_ENET_SPEED_1000), ++ /**< 1000 Mbps QSGMII with 1000BaseX auto-negotiation between ++ MAC and QSGMII phy or backplane */ ++ e_ENET_MODE_XGMII_10000 = (e_ENET_IF_XGMII | e_ENET_SPEED_10000), /**< 10000 Mbps XGMII */ ++ e_ENET_MODE_XFI_10000 = (e_ENET_IF_XFI | e_ENET_SPEED_10000) /**< 10000 Mbps XFI */ ++} e_EnetMode; ++ ++ ++#define IS_ENET_MODE_VALID(mode) \ ++ (((mode) == e_ENET_MODE_MII_10 ) || \ ++ ((mode) == e_ENET_MODE_MII_100 ) || \ ++ ((mode) == e_ENET_MODE_RMII_10 ) || \ ++ ((mode) == e_ENET_MODE_RMII_100 ) || \ ++ ((mode) == e_ENET_MODE_SMII_10 ) || \ ++ ((mode) == e_ENET_MODE_SMII_100 ) || \ ++ ((mode) == e_ENET_MODE_GMII_1000 ) || \ ++ ((mode) == e_ENET_MODE_RGMII_10 ) || \ ++ ((mode) == e_ENET_MODE_RGMII_100 ) || \ ++ ((mode) == e_ENET_MODE_RGMII_1000 ) || \ ++ ((mode) == e_ENET_MODE_TBI_1000 ) || \ ++ ((mode) == e_ENET_MODE_RTBI_1000 ) || \ ++ ((mode) == e_ENET_MODE_SGMII_10 ) || \ ++ ((mode) == e_ENET_MODE_SGMII_100 ) || \ ++ ((mode) == e_ENET_MODE_SGMII_1000 ) || \ ++ ((mode) == e_ENET_MODE_SGMII_BASEX_10 ) || \ ++ ((mode) == e_ENET_MODE_SGMII_BASEX_100 ) || \ ++ ((mode) == e_ENET_MODE_SGMII_BASEX_1000 ) || \ ++ ((mode) == e_ENET_MODE_XGMII_10000) || \ ++ ((mode) == e_ENET_MODE_QSGMII_1000) || \ ++ ((mode) == e_ENET_MODE_QSGMII_BASEX_1000) || \ ++ ((mode) == e_ENET_MODE_XFI_10000)) ++ ++ ++#define MAKE_ENET_MODE(_interface, _speed) (e_EnetMode)((_interface) | (_speed)) ++ ++#define ENET_INTERFACE_FROM_MODE(mode) (e_EnetInterface)((mode) & 0x0FFF0000) ++#define ENET_SPEED_FROM_MODE(mode) (e_EnetSpeed)((mode) & 0x0000FFFF) ++ ++#define ENET_ADDR_TO_UINT64(_enetAddr) \ ++ (uint64_t)(((uint64_t)(_enetAddr)[0] << 40) | \ ++ ((uint64_t)(_enetAddr)[1] << 32) | \ ++ ((uint64_t)(_enetAddr)[2] << 24) | \ ++ ((uint64_t)(_enetAddr)[3] << 16) | \ ++ ((uint64_t)(_enetAddr)[4] << 8) | \ ++ ((uint64_t)(_enetAddr)[5])) ++ ++#define MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enetAddr) \ ++ do { \ ++ int i; \ ++ for (i=0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) \ ++ (_enetAddr)[i] = (uint8_t)((_addr64) >> ((5-i)*8)); \ ++ } while (0) ++ ++ ++#endif /* __ENET_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/error_ext.h b/drivers/net/dpa/NetCommSw/inc/error_ext.h +new file mode 100644 +index 0000000..bbd6743 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/error_ext.h +@@ -0,0 +1,527 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 error_ext.h ++ ++ @Description Error definitions. ++*//***************************************************************************/ ++ ++#ifndef __ERROR_EXT_H ++#define __ERROR_EXT_H ++ ++#if !defined(NCSW_LINUX) ++#include ++#endif ++ ++#include "std_ext.h" ++#include "xx_ext.h" ++#include "core_ext.h" ++ ++ ++ ++ ++/**************************************************************************//** ++ @Group gen_id General Drivers Utilities ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group gen_error_id Errors, Events and Debug ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/****************************************************************************** ++The scheme below provides the bits description for error codes: ++ ++ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ++| Reserved (should be zero) | Module ID | ++ ++ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ++| Error Type | ++******************************************************************************/ ++ ++#define ERROR_CODE(_err) ((((uint32_t)_err) & 0x0000FFFF) | __ERR_MODULE__) ++ ++#define GET_ERROR_TYPE(_errcode) ((_errcode) & 0x0000FFFF) ++ /**< Extract module code from error code (#t_Error) */ ++ ++#define GET_ERROR_MODULE(_errcode) ((_errcode) & 0x00FF0000) ++ /**< Extract error type (#e_ErrorType) from ++ error code (#t_Error) */ ++ ++ ++/**************************************************************************//** ++ @Description Error Type Enumeration ++*//***************************************************************************/ ++typedef enum e_ErrorType /* Comments / Associated Message Strings */ ++{ /* ------------------------------------------------------------ */ ++ E_OK = 0 /* Never use "RETURN_ERROR" with E_OK; Use "return E_OK;" */ ++ ,E_WRITE_FAILED = EIO /**< Write access failed on memory/device. */ ++ /* String: none, or device name. */ ++ ,E_NO_DEVICE = ENXIO /**< The associated device is not initialized. */ ++ /* String: none. */ ++ ,E_NOT_AVAILABLE = EAGAIN ++ /**< Resource is unavailable. */ ++ /* String: none, unless the operation is not the main goal ++ of the function (in this case add resource description). */ ++ ,E_NO_MEMORY = ENOMEM /**< External memory allocation failed. */ ++ /* String: description of item for which allocation failed. */ ++ ,E_INVALID_ADDRESS = EFAULT ++ /**< Invalid address. */ ++ /* String: description of the specific violation. */ ++ ,E_BUSY = EBUSY /**< Resource or module is busy. */ ++ /* String: none, unless the operation is not the main goal ++ of the function (in this case add resource description). */ ++ ,E_ALREADY_EXISTS = EEXIST ++ /**< Requested resource or item already exists. */ ++ /* Use when resource duplication or sharing are not allowed. ++ String: none, unless the operation is not the main goal ++ of the function (in this case add item description). */ ++ ,E_INVALID_OPERATION = ENODEV ++ /**< The operation/command is invalid (unrecognized). */ ++ /* String: none. */ ++ ,E_INVALID_VALUE = EDOM /**< Invalid value. */ ++ /* Use for non-enumeration parameters, and ++ only when other error types are not suitable. ++ String: parameter description + "(should be )", ++ e.g: "Maximum Rx buffer length (should be divisible by 8)", ++ "Channel number (should be even)". */ ++ ,E_NOT_IN_RANGE = ERANGE/**< Parameter value is out of range. */ ++ /* Don't use this error for enumeration parameters. ++ String: parameter description + "(should be %d-%d)", ++ e.g: "Number of pad characters (should be 0-15)". */ ++ ,E_NOT_SUPPORTED = ENOSYS ++ /**< The function is not supported or not implemented. */ ++ /* String: none. */ ++ ,E_INVALID_STATE /**< The operation is not allowed in current module state. */ ++ /* String: none. */ ++ ,E_INVALID_HANDLE /**< Invalid handle of module or object. */ ++ /* String: none, unless the function takes in more than one ++ handle (in this case add the handle description) */ ++ ,E_INVALID_ID /**< Invalid module ID (usually enumeration or index). */ ++ /* String: none, unless the function takes in more than one ++ ID (in this case add the ID description) */ ++ ,E_NULL_POINTER /**< Unexpected NULL pointer. */ ++ /* String: pointer description. */ ++ ,E_INVALID_SELECTION /**< Invalid selection or mode. */ ++ /* Use for enumeration values, only when other error types ++ are not suitable. ++ String: parameter description. */ ++ ,E_INVALID_COMM_MODE /**< Invalid communication mode. */ ++ /* String: none, unless the function takes in more than one ++ communication mode indications (in this case add ++ parameter description). */ ++ ,E_INVALID_MEMORY_TYPE /**< Invalid memory type. */ ++ /* String: none, unless the function takes in more than one ++ memory types (in this case add memory description, ++ e.g: "Data memory", "Buffer descriptors memory"). */ ++ ,E_INVALID_CLOCK /**< Invalid clock. */ ++ /* String: none, unless the function takes in more than one ++ clocks (in this case add clock description, ++ e.g: "Rx clock", "Tx clock"). */ ++ ,E_CONFLICT /**< Some setting conflicts with another setting. */ ++ /* String: description of the conflicting settings. */ ++ ,E_NOT_ALIGNED /**< Non-aligned address. */ ++ /* String: parameter description + "(should be %d-bytes aligned)", ++ e.g: "Rx data buffer (should be 32-bytes aligned)". */ ++ ,E_NOT_FOUND /**< Requested resource or item was not found. */ ++ /* Use only when the resource/item is uniquely identified. ++ String: none, unless the operation is not the main goal ++ of the function (in this case add item description). */ ++ ,E_FULL /**< Resource is full. */ ++ /* String: none, unless the operation is not the main goal ++ of the function (in this case add resource description). */ ++ ,E_EMPTY /**< Resource is empty. */ ++ /* String: none, unless the operation is not the main goal ++ of the function (in this case add resource description). */ ++ ,E_ALREADY_FREE /**< Specified resource or item is already free or deleted. */ ++ /* String: none, unless the operation is not the main goal ++ of the function (in this case add item description). */ ++ ,E_READ_FAILED /**< Read access failed on memory/device. */ ++ /* String: none, or device name. */ ++ ,E_INVALID_FRAME /**< Invalid frame object (NULL handle or missing buffers). */ ++ /* String: none. */ ++ ,E_SEND_FAILED /**< Send operation failed on device. */ ++ /* String: none, or device name. */ ++ ,E_RECEIVE_FAILED /**< Receive operation failed on device. */ ++ /* String: none, or device name. */ ++ ,E_TIMEOUT/* = ETIMEDOUT*/ /**< The operation timed out. */ ++ /* String: none. */ ++ ++ ,E_DUMMY_LAST /* NEVER USED */ ++ ++} e_ErrorType; ++ ++/**************************************************************************//** ++ @Description Event Type Enumeration ++*//***************************************************************************/ ++typedef enum e_Event /* Comments / Associated Flags and Message Strings */ ++{ /* ------------------------------------------------------------ */ ++ EV_NO_EVENT = 0 /**< No event; Never used. */ ++ ++ ,EV_RX_DISCARD /**< Received packet discarded (by the driver, and only for ++ complete packets); ++ Flags: error flags in case of error, zero otherwise. */ ++ /* String: reason for discard, e.g: "Error in frame", ++ "Disordered frame", "Incomplete frame", "No frame object". */ ++ ,EV_RX_ERROR /**< Receive error (by hardware/firmware); ++ Flags: usually status flags from the buffer descriptor. */ ++ /* String: none. */ ++ ,EV_TX_ERROR /**< Transmit error (by hardware/firmware); ++ Flags: usually status flags from the buffer descriptor. */ ++ /* String: none. */ ++ ,EV_NO_BUFFERS /**< System ran out of buffer objects; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_NO_MB_FRAMES /**< System ran out of multi-buffer frame objects; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_NO_SB_FRAMES /**< System ran out of single-buffer frame objects; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_TX_QUEUE_FULL /**< Transmit queue is full; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_RX_QUEUE_FULL /**< Receive queue is full; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_INTR_QUEUE_FULL /**< Interrupt queue overflow; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_NO_DATA_BUFFER /**< Data buffer allocation (from higher layer) failed; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_OBJ_POOL_EMPTY /**< Objects pool is empty; ++ Flags: zero. */ ++ /* String: object description (name). */ ++ ,EV_BUS_ERROR /**< Illegal access on bus; ++ Flags: the address (if available) or bus identifier */ ++ /* String: bus/address/module description. */ ++ ,EV_PTP_TXTS_QUEUE_FULL /**< PTP Tx timestamps queue is full; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_PTP_RXTS_QUEUE_FULL /**< PTP Rx timestamps queue is full; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_DUMMY_LAST ++ ++} e_Event; ++ ++ ++/**************************************************************************//** ++ @Collection Debug Levels for Errors and Events ++ ++ The level description refers to errors only. ++ For events, classification is done by the user. ++ ++ The TRACE, INFO and WARNING levels are allowed only when using ++ the DBG macro, and are not allowed when using the error macros ++ (RETURN_ERROR or REPORT_ERROR). ++ @{ ++*//***************************************************************************/ ++#define REPORT_LEVEL_CRITICAL 1 /**< Crasher: Incorrect flow, NULL pointers/handles. */ ++#define REPORT_LEVEL_MAJOR 2 /**< Cannot proceed: Invalid operation, parameters or ++ configuration. */ ++#define REPORT_LEVEL_MINOR 3 /**< Recoverable problem: a repeating call with the same ++ parameters may be successful. */ ++#define REPORT_LEVEL_WARNING 4 /**< Something is not exactly right, yet it is not an error. */ ++#define REPORT_LEVEL_INFO 5 /**< Messages which may be of interest to user/programmer. */ ++#define REPORT_LEVEL_TRACE 6 /**< Program flow messages. */ ++ ++#define EVENT_DISABLED 0xFF /**< Disabled event (not reported at all) */ ++ ++/* @} */ ++ ++ ++ ++#define NO_MSG ("") ++ ++#ifndef DEBUG_GLOBAL_LEVEL ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING ++#endif /* DEBUG_GLOBAL_LEVEL */ ++ ++#ifndef ERROR_GLOBAL_LEVEL ++#define ERROR_GLOBAL_LEVEL DEBUG_GLOBAL_LEVEL ++#endif /* ERROR_GLOBAL_LEVEL */ ++ ++#ifndef EVENT_GLOBAL_LEVEL ++#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR ++#endif /* EVENT_GLOBAL_LEVEL */ ++ ++#ifdef EVENT_LOCAL_LEVEL ++#define EVENT_DYNAMIC_LEVEL EVENT_LOCAL_LEVEL ++#else ++#define EVENT_DYNAMIC_LEVEL EVENT_GLOBAL_LEVEL ++#endif /* EVENT_LOCAL_LEVEL */ ++ ++ ++#ifndef DEBUG_DYNAMIC_LEVEL ++#define DEBUG_USING_STATIC_LEVEL ++ ++#ifdef DEBUG_STATIC_LEVEL ++#define DEBUG_DYNAMIC_LEVEL DEBUG_STATIC_LEVEL ++#else ++#define DEBUG_DYNAMIC_LEVEL DEBUG_GLOBAL_LEVEL ++#endif /* DEBUG_STATIC_LEVEL */ ++ ++#else /* DEBUG_DYNAMIC_LEVEL */ ++#ifdef DEBUG_STATIC_LEVEL ++#error "Please use either DEBUG_STATIC_LEVEL or DEBUG_DYNAMIC_LEVEL (not both)" ++#else ++int DEBUG_DYNAMIC_LEVEL = DEBUG_GLOBAL_LEVEL; ++#endif /* DEBUG_STATIC_LEVEL */ ++#endif /* !DEBUG_DYNAMIC_LEVEL */ ++ ++ ++#ifndef ERROR_DYNAMIC_LEVEL ++ ++#ifdef ERROR_STATIC_LEVEL ++#define ERROR_DYNAMIC_LEVEL ERROR_STATIC_LEVEL ++#else ++#define ERROR_DYNAMIC_LEVEL ERROR_GLOBAL_LEVEL ++#endif /* ERROR_STATIC_LEVEL */ ++ ++#else /* ERROR_DYNAMIC_LEVEL */ ++#ifdef ERROR_STATIC_LEVEL ++#error "Please use either ERROR_STATIC_LEVEL or ERROR_DYNAMIC_LEVEL (not both)" ++#else ++int ERROR_DYNAMIC_LEVEL = ERROR_GLOBAL_LEVEL; ++#endif /* ERROR_STATIC_LEVEL */ ++#endif /* !ERROR_DYNAMIC_LEVEL */ ++ ++#define PRINT_FORMAT "[CPU%02d, %s:%d %s]" ++#define PRINT_FMT_PARAMS CORE_GetId(), __FILE__, __LINE__, __FUNCTION__ ++ ++#if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) ++/* No debug/error/event messages at all */ ++#define DBG(_level, _vmsg) ++ ++#define REPORT_ERROR(_level, _err, _vmsg) ++ ++#define RETURN_ERROR(_level, _err, _vmsg) \ ++ return ERROR_CODE(_err) ++ ++#if (REPORT_EVENTS > 0) ++ ++#define REPORT_EVENT(_ev, _appId, _flg, _vmsg) \ ++ do { \ ++ if (_ev##_LEVEL <= EVENT_DYNAMIC_LEVEL) { \ ++ XX_EventById((uint32_t)(_ev), (t_Handle)(_appId), (uint16_t)(_flg), NO_MSG); \ ++ } \ ++ } while (0) ++ ++#else ++ ++#define REPORT_EVENT(_ev, _appId, _flg, _vmsg) ++ ++#endif /* (REPORT_EVENTS > 0) */ ++ ++ ++#else /* DEBUG_ERRORS > 0 */ ++ ++extern const char *dbgLevelStrings[]; ++extern const char *moduleStrings[]; ++#if (REPORT_EVENTS > 0) ++extern const char *eventStrings[]; ++#endif /* (REPORT_EVENTS > 0) */ ++ ++char * ErrTypeStrings (e_ErrorType err); ++ ++ ++#if ((defined(DEBUG_USING_STATIC_LEVEL)) && (DEBUG_DYNAMIC_LEVEL < REPORT_LEVEL_WARNING)) ++/* No need for DBG macro - debug level is higher anyway */ ++#define DBG(_level, _vmsg) ++#else ++#define DBG(_level, _vmsg) \ ++ do { \ ++ if (REPORT_LEVEL_##_level <= DEBUG_DYNAMIC_LEVEL) { \ ++ XX_Print("> %s (%s) " PRINT_FORMAT ": ", \ ++ dbgLevelStrings[REPORT_LEVEL_##_level - 1], \ ++ moduleStrings[__ERR_MODULE__ >> 16], \ ++ PRINT_FMT_PARAMS); \ ++ XX_Print _vmsg; \ ++ XX_Print("\r\n"); \ ++ } \ ++ } while (0) ++#endif /* (defined(DEBUG_USING_STATIC_LEVEL) && (DEBUG_DYNAMIC_LEVEL < WARNING)) */ ++ ++ ++#define REPORT_ERROR(_level, _err, _vmsg) \ ++ do { \ ++ if (REPORT_LEVEL_##_level <= ERROR_DYNAMIC_LEVEL) { \ ++ XX_Print("! %s %s Error " PRINT_FORMAT ": %s; ", \ ++ dbgLevelStrings[REPORT_LEVEL_##_level - 1], \ ++ moduleStrings[__ERR_MODULE__ >> 16], \ ++ PRINT_FMT_PARAMS, \ ++ ErrTypeStrings((e_ErrorType)GET_ERROR_TYPE(_err))); \ ++ XX_Print _vmsg; \ ++ XX_Print("\r\n"); \ ++ } \ ++ } while (0) ++ ++ ++#define RETURN_ERROR(_level, _err, _vmsg) \ ++ do { \ ++ REPORT_ERROR(_level, (_err), _vmsg); \ ++ return ERROR_CODE(_err); \ ++ } while (0) ++ ++ ++#if (REPORT_EVENTS > 0) ++ ++#define REPORT_EVENT(_ev, _appId, _flg, _vmsg) \ ++ do { \ ++ if (_ev##_LEVEL <= EVENT_DYNAMIC_LEVEL) { \ ++ XX_Print("~ %s %s Event " PRINT_FORMAT ": %s (flags: 0x%04x); ", \ ++ dbgLevelStrings[_ev##_LEVEL - 1], \ ++ moduleStrings[__ERR_MODULE__ >> 16], \ ++ PRINT_FMT_PARAMS, \ ++ eventStrings[((_ev) - EV_NO_EVENT - 1)], \ ++ (uint16_t)(_flg)); \ ++ XX_Print _vmsg; \ ++ XX_Print("\r\n"); \ ++ XX_EventById((uint32_t)(_ev), (t_Handle)(_appId), (uint16_t)(_flg), NO_MSG); \ ++ } \ ++ } while (0) ++ ++#else /* not REPORT_EVENTS */ ++ ++#define REPORT_EVENT(_ev, _appId, _flg, _vmsg) ++ ++#endif /* (REPORT_EVENTS > 0) */ ++ ++#endif /* (DEBUG_ERRORS > 0) */ ++ ++ ++/**************************************************************************//** ++ @Function ASSERT_COND ++ ++ @Description Assertion macro. ++ ++ @Param[in] _cond - The condition being checked, in positive form; ++ Failure of the condition triggers the assert. ++*//***************************************************************************/ ++#ifdef DISABLE_ASSERTIONS ++#define ASSERT_COND(_cond) ++#else ++#define ASSERT_COND(_cond) \ ++ do { \ ++ if (!(_cond)) { \ ++ XX_Print("*** ASSERT_COND failed " PRINT_FORMAT "\r\n", \ ++ PRINT_FMT_PARAMS); \ ++ XX_Exit(1); \ ++ } \ ++ } while (0) ++#endif /* DISABLE_ASSERTIONS */ ++ ++ ++#ifdef DISABLE_INIT_PARAMETERS_CHECK ++ ++#define CHECK_INIT_PARAMETERS(handle, f_check) ++#define CHECK_INIT_PARAMETERS_RETURN_VALUE(handle, f_check, retval) ++ ++#else ++ ++#define CHECK_INIT_PARAMETERS(handle, f_check) \ ++ do { \ ++ t_Error err = f_check(handle); \ ++ if (err != E_OK) { \ ++ RETURN_ERROR(MAJOR, err, NO_MSG); \ ++ } \ ++ } while (0) ++ ++#define CHECK_INIT_PARAMETERS_RETURN_VALUE(handle, f_check, retval) \ ++ do { \ ++ t_Error err = f_check(handle); \ ++ if (err != E_OK) { \ ++ REPORT_ERROR(MAJOR, err, NO_MSG); \ ++ return (retval); \ ++ } \ ++ } while (0) ++ ++#endif /* DISABLE_INIT_PARAMETERS_CHECK */ ++ ++#ifdef DISABLE_SANITY_CHECKS ++ ++#define SANITY_CHECK_RETURN_ERROR(_cond, _err) ++#define SANITY_CHECK_RETURN_VALUE(_cond, _err, retval) ++#define SANITY_CHECK_RETURN(_cond, _err) ++#define SANITY_CHECK_EXIT(_cond, _err) ++ ++#else /* DISABLE_SANITY_CHECKS */ ++ ++#define SANITY_CHECK_RETURN_ERROR(_cond, _err) \ ++ do { \ ++ if (!(_cond)) { \ ++ RETURN_ERROR(CRITICAL, (_err), NO_MSG); \ ++ } \ ++ } while (0) ++ ++#define SANITY_CHECK_RETURN_VALUE(_cond, _err, retval) \ ++ do { \ ++ if (!(_cond)) { \ ++ REPORT_ERROR(CRITICAL, (_err), NO_MSG); \ ++ return (retval); \ ++ } \ ++ } while (0) ++ ++#define SANITY_CHECK_RETURN(_cond, _err) \ ++ do { \ ++ if (!(_cond)) { \ ++ REPORT_ERROR(CRITICAL, (_err), NO_MSG); \ ++ return; \ ++ } \ ++ } while (0) ++ ++#define SANITY_CHECK_EXIT(_cond, _err) \ ++ do { \ ++ if (!(_cond)) { \ ++ REPORT_ERROR(CRITICAL, (_err), NO_MSG); \ ++ XX_Exit(1); \ ++ } \ ++ } while (0) ++ ++#endif /* DISABLE_SANITY_CHECKS */ ++ ++/** @} */ /* end of Debug/error Utils group */ ++ ++/** @} */ /* end of General Utils group */ ++ ++#endif /* __ERROR_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/etc/list_ext.h b/drivers/net/dpa/NetCommSw/inc/etc/list_ext.h +new file mode 100644 +index 0000000..ee6b9f2 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/etc/list_ext.h +@@ -0,0 +1,358 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 list_ext.h ++ ++ @Description External prototypes for list.c ++*//***************************************************************************/ ++ ++#ifndef __LIST_EXT_H ++#define __LIST_EXT_H ++ ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group etc_id Utility Library Application Programming Interface ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group list_id List ++ ++ @Description List module functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description List structure. ++*//***************************************************************************/ ++typedef struct List ++{ ++ struct List *p_Next; /**< A pointer to the next list object */ ++ struct List *p_Prev; /**< A pointer to the previous list object */ ++} t_List; ++ ++ ++/**************************************************************************//** ++ @Function LIST_FIRST/LIST_LAST/LIST_NEXT/LIST_PREV ++ ++ @Description Macro to get first/last/next/previous entry in a list. ++ ++ @Param[in] p_List - A pointer to a list. ++*//***************************************************************************/ ++#define LIST_FIRST(p_List) (p_List)->p_Next ++#define LIST_LAST(p_List) (p_List)->p_Prev ++#define LIST_NEXT LIST_FIRST ++#define LIST_PREV LIST_LAST ++ ++ ++/**************************************************************************//** ++ @Function LIST_INIT ++ ++ @Description Macro for initialization of a list struct. ++ ++ @Param[in] lst - The t_List object to initialize. ++*//***************************************************************************/ ++#define LIST_INIT(lst) {&(lst), &(lst)} ++ ++ ++/**************************************************************************//** ++ @Function LIST ++ ++ @Description Macro to declare of a list. ++ ++ @Param[in] listName - The list object name. ++*//***************************************************************************/ ++#define LIST(listName) t_List listName = LIST_INIT(listName) ++ ++ ++/**************************************************************************//** ++ @Function INIT_LIST ++ ++ @Description Macro to initialize a list pointer. ++ ++ @Param[in] p_List - The list pointer. ++*//***************************************************************************/ ++#define INIT_LIST(p_List) LIST_FIRST(p_List) = LIST_LAST(p_List) = (p_List) ++ ++ ++/**************************************************************************//** ++ @Function LIST_OBJECT ++ ++ @Description Macro to get the struct (object) for this entry. ++ ++ @Param[in] type - The type of the struct (object) this list is embedded in. ++ @Param[in] member - The name of the t_List object within the struct. ++ ++ @Return The structure pointer for this entry. ++*//***************************************************************************/ ++#define MEMBER_OFFSET(type, member) (PTR_TO_UINT(&((type *)0)->member)) ++#define LIST_OBJECT(p_List, type, member) \ ++ ((type *)((char *)(p_List)-MEMBER_OFFSET(type, member))) ++ ++ ++/**************************************************************************//** ++ @Function LIST_FOR_EACH ++ ++ @Description Macro to iterate over a list. ++ ++ @Param[in] p_Pos - A pointer to a list to use as a loop counter. ++ @Param[in] p_Head - A pointer to the head for your list pointer. ++ ++ @Cautions You can't delete items with this routine. ++ For deletion use LIST_FOR_EACH_SAFE(). ++*//***************************************************************************/ ++#define LIST_FOR_EACH(p_Pos, p_Head) \ ++ for (p_Pos = LIST_FIRST(p_Head); p_Pos != (p_Head); p_Pos = LIST_NEXT(p_Pos)) ++ ++ ++/**************************************************************************//** ++ @Function LIST_FOR_EACH_SAFE ++ ++ @Description Macro to iterate over a list safe against removal of list entry. ++ ++ @Param[in] p_Pos - A pointer to a list to use as a loop counter. ++ @Param[in] p_Tmp - Another pointer to a list to use as temporary storage. ++ @Param[in] p_Head - A pointer to the head for your list pointer. ++*//***************************************************************************/ ++#define LIST_FOR_EACH_SAFE(p_Pos, p_Tmp, p_Head) \ ++ for (p_Pos = LIST_FIRST(p_Head), p_Tmp = LIST_FIRST(p_Pos); \ ++ p_Pos != (p_Head); \ ++ p_Pos = p_Tmp, p_Tmp = LIST_NEXT(p_Pos)) ++ ++ ++/**************************************************************************//** ++ @Function LIST_FOR_EACH_OBJECT_SAFE ++ ++ @Description Macro to iterate over list of given type safely. ++ ++ @Param[in] p_Pos - A pointer to a list to use as a loop counter. ++ @Param[in] p_Tmp - Another pointer to a list to use as temporary storage. ++ @Param[in] type - The type of the struct this is embedded in. ++ @Param[in] p_Head - A pointer to the head for your list pointer. ++ @Param[in] member - The name of the list_struct within the struct. ++ ++ @Cautions You can't delete items with this routine. ++ For deletion use LIST_FOR_EACH_SAFE(). ++*//***************************************************************************/ ++#define LIST_FOR_EACH_OBJECT_SAFE(p_Pos, p_Tmp, p_Head, type, member) \ ++ for (p_Pos = LIST_OBJECT(LIST_FIRST(p_Head), type, member), \ ++ p_Tmp = LIST_OBJECT(LIST_FIRST(&p_Pos->member), type, member); \ ++ &p_Pos->member != (p_Head); \ ++ p_Pos = p_Tmp, \ ++ p_Tmp = LIST_OBJECT(LIST_FIRST(&p_Pos->member), type, member)) ++ ++/**************************************************************************//** ++ @Function LIST_FOR_EACH_OBJECT ++ ++ @Description Macro to iterate over list of given type. ++ ++ @Param[in] p_Pos - A pointer to a list to use as a loop counter. ++ @Param[in] type - The type of the struct this is embedded in. ++ @Param[in] p_Head - A pointer to the head for your list pointer. ++ @Param[in] member - The name of the list_struct within the struct. ++ ++ @Cautions You can't delete items with this routine. ++ For deletion use LIST_FOR_EACH_SAFE(). ++*//***************************************************************************/ ++#define LIST_FOR_EACH_OBJECT(p_Pos, type, p_Head, member) \ ++ for (p_Pos = LIST_OBJECT(LIST_FIRST(p_Head), type, member); \ ++ &p_Pos->member != (p_Head); \ ++ p_Pos = LIST_OBJECT(LIST_FIRST(&(p_Pos->member)), type, member)) ++ ++ ++/**************************************************************************//** ++ @Function LIST_Add ++ ++ @Description Add a new entry to a list. ++ ++ Insert a new entry after the specified head. ++ This is good for implementing stacks. ++ ++ @Param[in] p_New - A pointer to a new list entry to be added. ++ @Param[in] p_Head - A pointer to a list head to add it after. ++ ++ @Return none. ++*//***************************************************************************/ ++static __inline__ void LIST_Add(t_List *p_New, t_List *p_Head) ++{ ++ LIST_PREV(LIST_NEXT(p_Head)) = p_New; ++ LIST_NEXT(p_New) = LIST_NEXT(p_Head); ++ LIST_PREV(p_New) = p_Head; ++ LIST_NEXT(p_Head) = p_New; ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_AddToTail ++ ++ @Description Add a new entry to a list. ++ ++ Insert a new entry before the specified head. ++ This is useful for implementing queues. ++ ++ @Param[in] p_New - A pointer to a new list entry to be added. ++ @Param[in] p_Head - A pointer to a list head to add it before. ++ ++ @Return none. ++*//***************************************************************************/ ++static __inline__ void LIST_AddToTail(t_List *p_New, t_List *p_Head) ++{ ++ LIST_NEXT(LIST_PREV(p_Head)) = p_New; ++ LIST_PREV(p_New) = LIST_PREV(p_Head); ++ LIST_NEXT(p_New) = p_Head; ++ LIST_PREV(p_Head) = p_New; ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_Del ++ ++ @Description Deletes entry from a list. ++ ++ @Param[in] p_Entry - A pointer to the element to delete from the list. ++ ++ @Return none. ++ ++ @Cautions LIST_IsEmpty() on entry does not return true after this, ++ the entry is in an undefined state. ++*//***************************************************************************/ ++static __inline__ void LIST_Del(t_List *p_Entry) ++{ ++ LIST_PREV(LIST_NEXT(p_Entry)) = LIST_PREV(p_Entry); ++ LIST_NEXT(LIST_PREV(p_Entry)) = LIST_NEXT(p_Entry); ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_DelAndInit ++ ++ @Description Deletes entry from list and reinitialize it. ++ ++ @Param[in] p_Entry - A pointer to the element to delete from the list. ++ ++ @Return none. ++*//***************************************************************************/ ++static __inline__ void LIST_DelAndInit(t_List *p_Entry) ++{ ++ LIST_Del(p_Entry); ++ INIT_LIST(p_Entry); ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_Move ++ ++ @Description Delete from one list and add as another's head. ++ ++ @Param[in] p_Entry - A pointer to the list entry to move. ++ @Param[in] p_Head - A pointer to the list head that will precede our entry. ++ ++ @Return none. ++*//***************************************************************************/ ++static __inline__ void LIST_Move(t_List *p_Entry, t_List *p_Head) ++{ ++ LIST_Del(p_Entry); ++ LIST_Add(p_Entry, p_Head); ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_MoveToTail ++ ++ @Description Delete from one list and add as another's tail. ++ ++ @Param[in] p_Entry - A pointer to the entry to move. ++ @Param[in] p_Head - A pointer to the list head that will follow our entry. ++ ++ @Return none. ++*//***************************************************************************/ ++static __inline__ void LIST_MoveToTail(t_List *p_Entry, t_List *p_Head) ++{ ++ LIST_Del(p_Entry); ++ LIST_AddToTail(p_Entry, p_Head); ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_IsEmpty ++ ++ @Description Tests whether a list is empty. ++ ++ @Param[in] p_List - A pointer to the list to test. ++ ++ @Return 1 if the list is empty, 0 otherwise. ++*//***************************************************************************/ ++static __inline__ int LIST_IsEmpty(t_List *p_List) ++{ ++ return (LIST_FIRST(p_List) == p_List); ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_Append ++ ++ @Description Join two lists. ++ ++ @Param[in] p_NewList - A pointer to the new list to add. ++ @Param[in] p_Head - A pointer to the place to add it in the first list. ++ ++ @Return none. ++*//***************************************************************************/ ++void LIST_Append(t_List *p_NewList, t_List *p_Head); ++ ++ ++/**************************************************************************//** ++ @Function LIST_NumOfObjs ++ ++ @Description Counts number of objects in the list ++ ++ @Param[in] p_List - A pointer to the list which objects are to be counted. ++ ++ @Return Number of objects in the list. ++*//***************************************************************************/ ++int LIST_NumOfObjs(t_List *p_List); ++ ++/** @} */ /* end of list_id group */ ++/** @} */ /* end of etc_id group */ ++ ++ ++#endif /* __LIST_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/etc/mem_ext.h b/drivers/net/dpa/NetCommSw/inc/etc/mem_ext.h +new file mode 100644 +index 0000000..d0565d4 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/etc/mem_ext.h +@@ -0,0 +1,318 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 mem_ext.h ++ ++ @Description External prototypes for the memory manager object ++*//***************************************************************************/ ++ ++#ifndef __MEM_EXT_H ++#define __MEM_EXT_H ++ ++#include "std_ext.h" ++#include "part_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group etc_id Utility Library Application Programming Interface ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group mem_id Slab Memory Manager ++ ++ @Description Slab Memory Manager module functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/* Each block is of the following structure: ++ * ++ * ++ * +-----------+----------+---------------------------+-----------+-----------+ ++ * | Alignment | Prefix | Data | Postfix | Alignment | ++ * | field | field | field | field | Padding | ++ * | | | | | | ++ * +-----------+----------+---------------------------+-----------+-----------+ ++ * and at the beginning of all bytes, an additional optional padding might reside ++ * to ensure that the first blocks data field is aligned as requested. ++ */ ++ ++ ++#define MEM_MAX_NAME_LENGTH 8 ++ ++/**************************************************************************//* ++ @Description Memory Segment structure ++*//***************************************************************************/ ++ ++typedef struct ++{ ++ char name[MEM_MAX_NAME_LENGTH]; ++ /* The segment's name */ ++ uint8_t **p_Bases; /* Base addresses of the segments */ ++ uint8_t **p_BlocksStack; /* Array of pointers to blocks */ ++ t_Handle h_Spinlock; ++ uint16_t dataSize; /* Size of each data block */ ++ uint16_t prefixSize; /* How many bytes to reserve before the data */ ++ uint16_t postfixSize; /* How many bytes to reserve after the data */ ++ uint16_t alignment; /* Requested alignment for the data field */ ++ int allocOwner; /* Memory allocation owner */ ++ uint32_t getFailures; /* Number of times get failed */ ++ uint32_t num; /* Number of blocks in segment */ ++ uint32_t current; /* Current block */ ++ bool consecutiveMem; /* Allocate consecutive data blocks memory */ ++#ifdef DEBUG_MEM_LEAKS ++ void *p_MemDbg; /* MEM debug database (MEM leaks detection) */ ++ uint32_t blockOffset; ++ uint32_t blockSize; ++#endif /* DEBUG_MEM_LEAKS */ ++} t_MemorySegment; ++ ++ ++ ++/**************************************************************************//** ++ @Function MEM_Init ++ ++ @Description Create a new memory segment. ++ ++ @Param[in] name - Name of memory partition. ++ @Param[in] p_Handle - Handle to new segment is returned through here. ++ @Param[in] num - Number of blocks in new segment. ++ @Param[in] dataSize - Size of blocks in segment. ++ @Param[in] prefixSize - How many bytes to allocate before the data. ++ @Param[in] postfixSize - How many bytes to allocate after the data. ++ @Param[in] alignment - Requested alignment for data field (in bytes). ++ ++ @Return E_OK - success, E_NO_MEMORY - out of memory. ++*//***************************************************************************/ ++t_Error MEM_Init(char name[], ++ t_Handle *p_Handle, ++ uint32_t num, ++ uint16_t dataSize, ++ uint16_t prefixSize, ++ uint16_t postfixSize, ++ uint16_t alignment); ++ ++/**************************************************************************//** ++ @Function MEM_InitSmart ++ ++ @Description Create a new memory segment. ++ ++ @Param[in] name - Name of memory partition. ++ @Param[in] p_Handle - Handle to new segment is returned through here. ++ @Param[in] num - Number of blocks in new segment. ++ @Param[in] dataSize - Size of blocks in segment. ++ @Param[in] prefixSize - How many bytes to allocate before the data. ++ @Param[in] postfixSize - How many bytes to allocate after the data. ++ @Param[in] alignment - Requested alignment for data field (in bytes). ++ @Param[in] memPartitionId - Memory partition ID for allocation. ++ @Param[in] consecutiveMem - Whether to allocate the memory blocks ++ continuously or not. ++ ++ @Return E_OK - success, E_NO_MEMORY - out of memory. ++*//***************************************************************************/ ++t_Error MEM_InitSmart(char name[], ++ t_Handle *p_Handle, ++ uint32_t num, ++ uint16_t dataSize, ++ uint16_t prefixSize, ++ uint16_t postfixSize, ++ uint16_t alignment, ++ uint8_t memPartitionId, ++ bool consecutiveMem); ++ ++/**************************************************************************//** ++ @Function MEM_InitByAddress ++ ++ @Description Create a new memory segment with a specified base address. ++ ++ @Param[in] name - Name of memory partition. ++ @Param[in] p_Handle - Handle to new segment is returned through here. ++ @Param[in] num - Number of blocks in new segment. ++ @Param[in] dataSize - Size of blocks in segment. ++ @Param[in] prefixSize - How many bytes to allocate before the data. ++ @Param[in] postfixSize - How many bytes to allocate after the data. ++ @Param[in] alignment - Requested alignment for data field (in bytes). ++ @Param[in] address - The required base address. ++ ++ @Return E_OK - success, E_NO_MEMORY - out of memory. ++ *//***************************************************************************/ ++t_Error MEM_InitByAddress(char name[], ++ t_Handle *p_Handle, ++ uint32_t num, ++ uint16_t dataSize, ++ uint16_t prefixSize, ++ uint16_t postfixSize, ++ uint16_t alignment, ++ uint8_t *address); ++ ++/**************************************************************************//** ++ @Function MEM_Free ++ ++ @Description Free a specific memory segment. ++ ++ @Param[in] h_Mem - Handle to memory segment. ++ ++ @Return None. ++*//***************************************************************************/ ++void MEM_Free(t_Handle h_Mem); ++ ++/**************************************************************************//** ++ @Function MEM_Get ++ ++ @Description Get a block of memory from a segment. ++ ++ @Param[in] h_Mem - Handle to memory segment. ++ ++ @Return Pointer to new memory block on success,0 otherwise. ++*//***************************************************************************/ ++void * MEM_Get(t_Handle h_Mem); ++ ++/**************************************************************************//** ++ @Function MEM_GetN ++ ++ @Description Get up to N blocks of memory from a segment. ++ ++ The blocks are assumed to be of a fixed size (one size per segment). ++ ++ @Param[in] h_Mem - Handle to memory segment. ++ @Param[in] num - Number of blocks to allocate. ++ @Param[out] array - Array of at least num pointers to which the addresses ++ of the allocated blocks are written. ++ ++ @Return The number of blocks actually allocated. ++ ++ @Cautions Interrupts are disabled for all of the allocation loop. ++ Although this loop is very short for each block (several machine ++ instructions), you should not allocate a very large number ++ of blocks via this routine. ++*//***************************************************************************/ ++uint16_t MEM_GetN(t_Handle h_Mem, uint32_t num, void *array[]); ++ ++/**************************************************************************//** ++ @Function MEM_Put ++ ++ @Description Put a block of memory back to a segment. ++ ++ @Param[in] h_Mem - Handle to memory segment. ++ @Param[in] p_Block - The block to return. ++ ++ @Return Pointer to new memory block on success,0 otherwise. ++*//***************************************************************************/ ++t_Error MEM_Put(t_Handle h_Mem, void *p_Block); ++ ++/**************************************************************************//** ++ @Function MEM_ComputePartitionSize ++ ++ @Description calculate a tight upper boundary of the size of a partition with ++ given attributes. ++ ++ The returned value is suitable if one wants to use MEM_InitByAddress(). ++ ++ @Param[in] num - The number of blocks in the segment. ++ @Param[in] dataSize - Size of block to get. ++ @Param[in] prefixSize - The prefix size ++ @Param postfixSize - The postfix size ++ @Param[in] alignment - The requested alignment value (in bytes) ++ ++ @Return The memory block size a segment with the given attributes needs. ++*//***************************************************************************/ ++uint32_t MEM_ComputePartitionSize(uint32_t num, ++ uint16_t dataSize, ++ uint16_t prefixSize, ++ uint16_t postfixSize, ++ uint16_t alignment); ++ ++#ifdef DEBUG_MEM_LEAKS ++#if !((defined(__MWERKS__) || defined(__GNUC__)) && (__dest_os == __ppc_eabi)) ++#error "Memory-Leaks-Debug option is supported only for freescale CodeWarrior" ++#endif /* !(defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Function MEM_CheckLeaks ++ ++ @Description Report MEM object leaks. ++ ++ This routine is automatically called by the MEM_Free() routine, ++ but it can also be invoked while the MEM object is alive. ++ ++ @Param[in] h_Mem - Handle to memory segment. ++ ++ @Return None. ++*//***************************************************************************/ ++void MEM_CheckLeaks(t_Handle h_Mem); ++ ++#else /* not DEBUG_MEM_LEAKS */ ++#define MEM_CheckLeaks(h_Mem) ++#endif /* not DEBUG_MEM_LEAKS */ ++ ++/**************************************************************************//** ++ @Description Get base of MEM ++*//***************************************************************************/ ++#define MEM_GetBase(h_Mem) ((t_MemorySegment *)(h_Mem))->p_Bases[0] ++ ++/**************************************************************************//** ++ @Description Get size of MEM block ++*//***************************************************************************/ ++#define MEM_GetSize(h_Mem) ((t_MemorySegment *)(h_Mem))->dataSize ++ ++/**************************************************************************//** ++ @Description Get prefix size of MEM block ++*//***************************************************************************/ ++#define MEM_GetPrefixSize(h_Mem) ((t_MemorySegment *)(h_Mem))->prefixSize ++ ++/**************************************************************************//** ++ @Description Get postfix size of MEM block ++*//***************************************************************************/ ++#define MEM_GetPostfixSize(h_Mem) ((t_MemorySegment *)(h_Mem))->postfixSize ++ ++/**************************************************************************//** ++ @Description Get alignment of MEM block (in bytes) ++*//***************************************************************************/ ++#define MEM_GetAlignment(h_Mem) ((t_MemorySegment *)(h_Mem))->alignment ++ ++/**************************************************************************//** ++ @Description Get the number of blocks in the segment ++*//***************************************************************************/ ++#define MEM_GetNumOfBlocks(h_Mem) ((t_MemorySegment *)(h_Mem))->num ++ ++/** @} */ /* end of MEM group */ ++/** @} */ /* end of etc_id group */ ++ ++ ++#endif /* __MEM_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/etc/memcpy_ext.h b/drivers/net/dpa/NetCommSw/inc/etc/memcpy_ext.h +new file mode 100644 +index 0000000..cc5bb72 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/etc/memcpy_ext.h +@@ -0,0 +1,174 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 memcpy_ext.h ++ ++ @Description Efficient functions for copying and setting blocks of memory. ++*//***************************************************************************/ ++ ++#ifndef __MEMCPY_EXT_H ++#define __MEMCPY_EXT_H ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group etc_id Utility Library Application Programming Interface ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group mem_cpy Memory Copy ++ ++ @Description Memory Copy module functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function MemCpy32 ++ ++ @Description Copies one memory buffer into another one in 4-byte chunks! ++ Which should be more efficient than byte by byte. ++ ++ For large buffers (over 60 bytes) this function is about 4 times ++ more efficient than the trivial memory copy. For short buffers ++ it is reduced to the trivial copy and may be a bit worse. ++ ++ @Param[in] pDst - The address of the destination buffer. ++ @Param[in] pSrc - The address of the source buffer. ++ @Param[in] size - The number of bytes that will be copied from pSrc to pDst. ++ ++ @Return pDst (the address of the destination buffer). ++ ++ @Cautions There is no parameter or boundary checking! It is up to the user ++ to supply non-null parameters as source & destination and size ++ that actually fits into the destination buffer. ++*//***************************************************************************/ ++void * MemCpy32(void* pDst,void* pSrc, uint32_t size); ++void * IO2IOCpy32(void* pDst,void* pSrc, uint32_t size); ++void * IO2MemCpy32(void* pDst,void* pSrc, uint32_t size); ++void * Mem2IOCpy32(void* pDst,void* pSrc, uint32_t size); ++ ++/**************************************************************************//** ++ @Function MemCpy64 ++ ++ @Description Copies one memory buffer into another one in 8-byte chunks! ++ Which should be more efficient than byte by byte. ++ ++ For large buffers (over 60 bytes) this function is about 8 times ++ more efficient than the trivial memory copy. For short buffers ++ it is reduced to the trivial copy and may be a bit worse. ++ ++ Some testing suggests that MemCpy32() preforms better than ++ MemCpy64() over small buffers. On average they break even at ++ 100 byte buffers. For buffers larger than that MemCpy64 is ++ superior. ++ ++ @Param[in] pDst - The address of the destination buffer. ++ @Param[in] pSrc - The address of the source buffer. ++ @Param[in] size - The number of bytes that will be copied from pSrc to pDst. ++ ++ @Return pDst (the address of the destination buffer). ++ ++ @Cautions There is no parameter or boundary checking! It is up to the user ++ to supply non null parameters as source & destination and size ++ that actually fits into their buffer. ++ ++ Do not use under Linux. ++*//***************************************************************************/ ++void * MemCpy64(void* pDst,void* pSrc, uint32_t size); ++ ++/**************************************************************************//** ++ @Function MemSet32 ++ ++ @Description Sets all bytes of a memory buffer to a specific value, in ++ 4-byte chunks. ++ ++ @Param[in] pDst - The address of the destination buffer. ++ @Param[in] val - Value to set destination bytes to. ++ @Param[in] size - The number of bytes that will be set to val. ++ ++ @Return pDst (the address of the destination buffer). ++ ++ @Cautions There is no parameter or boundary checking! It is up to the user ++ to supply non null parameter as destination and size ++ that actually fits into the destination buffer. ++*//***************************************************************************/ ++void * MemSet32(void* pDst, uint8_t val, uint32_t size); ++void * IOMemSet32(void* pDst, uint8_t val, uint32_t size); ++ ++/**************************************************************************//** ++ @Function MemSet64 ++ ++ @Description Sets all bytes of a memory buffer to a specific value, in ++ 8-byte chunks. ++ ++ @Param[in] pDst - The address of the destination buffer. ++ @Param[in] val - Value to set destination bytes to. ++ @Param[in] size - The number of bytes that will be set to val. ++ ++ @Return pDst (the address of the destination buffer). ++ ++ @Cautions There is no parameter or boundary checking! It is up to the user ++ to supply non null parameter as destination and size ++ that actually fits into the destination buffer. ++*//***************************************************************************/ ++void * MemSet64(void* pDst, uint8_t val, uint32_t size); ++ ++/**************************************************************************//** ++ @Function MemDisp ++ ++ @Description Displays a block of memory in chunks of 32 bits. ++ ++ @Param[in] addr - The address of the memory to display. ++ @Param[in] size - The number of bytes that will be displayed. ++ ++ @Return None. ++ ++ @Cautions There is no parameter or boundary checking! It is up to the user ++ to supply non null parameter as destination and size ++ that actually fits into the destination buffer. ++*//***************************************************************************/ ++void MemDisp(uint8_t *addr, int size); ++ ++/** @} */ /* end of mem_cpy group */ ++/** @} */ /* end of etc_id group */ ++ ++ ++#endif /* __MEMCPY_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/etc/mm_ext.h b/drivers/net/dpa/NetCommSw/inc/etc/mm_ext.h +new file mode 100644 +index 0000000..fa7c85e +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/etc/mm_ext.h +@@ -0,0 +1,310 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 mm_ext.h ++ ++ @Description Memory Manager Application Programming Interface ++*//***************************************************************************/ ++#ifndef __MM_EXT ++#define __MM_EXT ++ ++#include "std_ext.h" ++ ++#define MM_MAX_ALIGNMENT 20 /* Alignments from 2 to 128 are available ++ where maximum alignment defined as ++ MM_MAX_ALIGNMENT power of 2 */ ++ ++#define MM_MAX_NAME_LEN 32 ++ ++/**************************************************************************//** ++ @Group etc_id Utility Library Application Programming Interface ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group mm_grp Flexible Memory Manager ++ ++ @Description Flexible Memory Manager module functions,definitions and enums. ++ (All of the following functions,definitions and enums can be found in mm_ext.h) ++ ++ @{ ++*//***************************************************************************/ ++ ++ ++/**************************************************************************//** ++ @Function MM_Init ++ ++ @Description Initializes a new MM object. ++ ++ It initializes a new memory block consisting of base address ++ and size of the available memory by calling to MemBlock_Init ++ routine. It is also initializes a new free block for each ++ by calling FreeBlock_Init routine, which is pointed to ++ the almost all memory started from the required alignment ++ from the base address and to the end of the memory. ++ The handle to the new MM object is returned via "MM" ++ argument (passed by reference). ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] base - Base address of the MM. ++ @Param[in] size - Size of the MM. ++ ++ @Return E_OK is returned on success. E_NOMEMORY is returned if the new MM object or a new free block can not be initialized. ++*//***************************************************************************/ ++t_Error MM_Init(t_Handle *h_MM, uint64_t base, uint64_t size); ++ ++/**************************************************************************//** ++ @Function MM_Get ++ ++ @Description Allocates a block of memory according to the given size and the alignment. ++ ++ The Alignment argument tells from which ++ free list allocate a block of memory. 2^alignment indicates ++ the alignment that the base address of the allocated block ++ should have. So, the only values 1, 2, 4, 8, 16, 32 and 64 ++ are available for the alignment argument. ++ The routine passes through the specific free list of free ++ blocks and seeks for a first block that have anough memory ++ that is required (best fit). ++ After the block is found and data is allocated, it calls ++ the internal MM_CutFree routine to update all free lists ++ do not include a just allocated block. Of course, each ++ free list contains a free blocks with the same alignment. ++ It is also creates a busy block that holds ++ information about an allocated block. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] size - Size of the MM. ++ @Param[in] alignment - Index as a power of two defines a required ++ alignment (in bytes); Should be 1, 2, 4, 8, 16, 32 or 64 ++ @Param[in] name - The name that specifies an allocated block. ++ ++ @Return base address of an allocated block ILLEGAL_BASE if can't allocate a block ++*//***************************************************************************/ ++uint64_t MM_Get(t_Handle h_MM, uint64_t size, uint64_t alignment, char *name); ++ ++/**************************************************************************//** ++ @Function MM_GetBase ++ ++ @Description Gets the base address of the required MM objects. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ ++ @Return base address of the block. ++*//***************************************************************************/ ++uint64_t MM_GetBase(t_Handle h_MM); ++ ++/**************************************************************************//** ++ @Function MM_GetForce ++ ++ @Description Force memory allocation. ++ ++ It means to allocate a block of memory of the given ++ size from the given base address. ++ The routine checks if the required block can be allocated ++ (that is it is free) and then, calls the internal MM_CutFree ++ routine to update all free lists do not include that block. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] base - Base address of the MM. ++ @Param[in] size - Size of the MM. ++ @Param[in] name - Name that specifies an allocated block. ++ ++ @Return base address of an allocated block, ILLEGAL_BASE if can't allocate a block. ++*//***************************************************************************/ ++uint64_t MM_GetForce(t_Handle h_MM, uint64_t base, uint64_t size, char *name); ++ ++/**************************************************************************//** ++ @Function MM_GetForceMin ++ ++ @Description Allocates a block of memory according to the given size, the alignment and minimum base address. ++ ++ The Alignment argument tells from which ++ free list allocate a block of memory. 2^alignment indicates ++ the alignment that the base address of the allocated block ++ should have. So, the only values 1, 2, 4, 8, 16, 32 and 64 ++ are available for the alignment argument. ++ The minimum baser address forces the location of the block ++ to be from a given address onward. ++ The routine passes through the specific free list of free ++ blocks and seeks for the first base address equal or smaller ++ than the required minimum address and end address larger than ++ than the required base + its size - i.e. that may contain ++ the required block. ++ After the block is found and data is allocated, it calls ++ the internal MM_CutFree routine to update all free lists ++ do not include a just allocated block. Of course, each ++ free list contains a free blocks with the same alignment. ++ It is also creates a busy block that holds ++ information about an allocated block. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] size - Size of the MM. ++ @Param[in] alignment - Index as a power of two defines a required ++ alignment (in bytes); Should be 1, 2, 4, 8, 16, 32 or 64 ++ @Param[in] min - The minimum base address of the block. ++ @Param[in] name - Name that specifies an allocated block. ++ ++ @Return base address of an allocated block,ILLEGAL_BASE if can't allocate a block. ++*//***************************************************************************/ ++uint64_t MM_GetForceMin(t_Handle h_MM, ++ uint64_t size, ++ uint64_t alignment, ++ uint64_t min, ++ char *name); ++ ++/**************************************************************************//** ++ @Function MM_Put ++ ++ @Description Puts a block of memory of the given base address back to the memory. ++ ++ It checks if there is a busy block with the ++ given base address. If not, it returns 0, that ++ means can't free a block. Otherwise, it gets parameters of ++ the busy block and after it updates lists of free blocks, ++ removes that busy block from the list by calling to MM_CutBusy ++ routine. ++ After that it calls to MM_AddFree routine to add a new free ++ block to the free lists. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] base - Base address of the MM. ++ ++ @Return The size of bytes released, 0 if failed. ++*//***************************************************************************/ ++uint64_t MM_Put(t_Handle h_MM, uint64_t base); ++ ++/**************************************************************************//** ++ @Function MM_PutForce ++ ++ @Description Releases a block of memory of the required size from the required base address. ++ ++ First, it calls to MM_CutBusy routine ++ to cut a free block from the busy list. And then, calls to ++ MM_AddFree routine to add the free block to the free lists. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] base - Base address of of a block to free. ++ @Param[in] size - Size of a block to free. ++ ++ @Return The number of bytes released, 0 on failure. ++*//***************************************************************************/ ++uint64_t MM_PutForce(t_Handle h_MM, uint64_t base, uint64_t size); ++ ++/**************************************************************************//** ++ @Function MM_Add ++ ++ @Description Adds a new memory block for memory allocation. ++ ++ When a new memory block is initialized and added to the ++ memory list, it calls to MM_AddFree routine to add the ++ new free block to the free lists. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] base - Base address of the memory block. ++ @Param[in] size - Size of the memory block. ++ ++ @Return E_OK on success, otherwise returns an error code. ++*//***************************************************************************/ ++t_Error MM_Add(t_Handle h_MM, uint64_t base, uint64_t size); ++ ++/**************************************************************************//** ++ @Function MM_Dump ++ ++ @Description Prints results of free and busy lists. ++ ++ @Param[in] h_MM - Handle to the MM object. ++*//***************************************************************************/ ++void MM_Dump(t_Handle h_MM); ++ ++/**************************************************************************//** ++ @Function MM_Free ++ ++ @Description Releases memory allocated for MM object. ++ ++ @Param[in] h_MM - Handle of the MM object. ++*//***************************************************************************/ ++void MM_Free(t_Handle h_MM); ++ ++/**************************************************************************//** ++ @Function MM_GetMemBlock ++ ++ @Description Returns base address of the memory block specified by the index. ++ ++ If index is 0, returns base address ++ of the first memory block, 1 - returns base address ++ of the second memory block, etc. ++ Note, those memory blocks are allocated by the ++ application before MM_Init or MM_Add and have to ++ be released by the application before or after invoking ++ the MM_Free routine. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] index - Index of the memory block. ++ ++ @Return valid base address or ILLEGAL_BASE if no memory block specified by the index. ++*//***************************************************************************/ ++uint64_t MM_GetMemBlock(t_Handle h_MM, int index); ++ ++/**************************************************************************//** ++ @Function MM_InRange ++ ++ @Description Checks if a specific address is in the memory range of the passed MM object. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] addr - The address to be checked. ++ ++ @Return TRUE if the address is in the address range of the block, FALSE otherwise. ++*//***************************************************************************/ ++bool MM_InRange(t_Handle h_MM, uint64_t addr); ++ ++/**************************************************************************//** ++ @Function MM_GetFreeMemSize ++ ++ @Description Returns the size (in bytes) of free memory. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ ++ @Return Free memory size in bytes. ++*//***************************************************************************/ ++uint64_t MM_GetFreeMemSize(t_Handle h_MM); ++ ++ ++/** @} */ /* end of mm_grp group */ ++/** @} */ /* end of etc_id group */ ++ ++#endif /* __MM_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/etc/sprint_ext.h b/drivers/net/dpa/NetCommSw/inc/etc/sprint_ext.h +new file mode 100644 +index 0000000..52f7a9d +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/etc/sprint_ext.h +@@ -0,0 +1,118 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 sprint_ext.h ++ ++ @Description Debug routines (externals). ++ ++*//***************************************************************************/ ++ ++#ifndef __SPRINT_EXT_H ++#define __SPRINT_EXT_H ++ ++ ++#if defined(NCSW_LINUX) && defined(__KERNEL__) ++#include ++ ++#elif defined(NCSW_VXWORKS) ++#include "private/stdioP.h" ++ ++#else ++#include ++#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */ ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group etc_id Utility Library Application Programming Interface ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group sprint_id Sprint ++ ++ @Description Sprint & Sscan module functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function Sprint ++ ++ @Description Format a string and place it in a buffer. ++ ++ @Param[in] buff - The buffer to place the result into. ++ @Param[in] str - The format string to use. ++ @Param[in] ... - Arguments for the format string. ++ ++ @Return Number of bytes formatted. ++*//***************************************************************************/ ++int Sprint(char *buff, const char *str, ...); ++ ++/**************************************************************************//** ++ @Function Snprint ++ ++ @Description Format a string and place it in a buffer. ++ ++ @Param[in] buf - The buffer to place the result into. ++ @Param[in] size - The size of the buffer, including the trailing null space. ++ @Param[in] fmt - The format string to use. ++ @Param[in] ... - Arguments for the format string. ++ ++ @Return Number of bytes formatted. ++*//***************************************************************************/ ++int Snprint(char * buf, uint32_t size, const char *fmt, ...); ++ ++/**************************************************************************//** ++ @Function Sscan ++ ++ @Description Unformat a buffer into a list of arguments. ++ ++ @Param[in] buf - input buffer. ++ @Param[in] fmt - formatting of buffer. ++ @Param[out] ... - resulting arguments. ++ ++ @Return Number of bytes unformatted. ++*//***************************************************************************/ ++int Sscan(const char * buf, const char * fmt, ...); ++ ++/** @} */ /* end of sprint_id group */ ++/** @} */ /* end of etc_id group */ ++ ++ ++#endif /* __SPRINT_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/flib/common/arch/ppc_access.h b/drivers/net/dpa/NetCommSw/inc/flib/common/arch/ppc_access.h +new file mode 100644 +index 0000000..c3953bb +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/flib/common/arch/ppc_access.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 FL_E500_MACROS_H ++#define FL_E500_MACROS_H ++ ++#endif /* FL_E500_MACROS_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/flib/common/general.h b/drivers/net/dpa/NetCommSw/inc/flib/common/general.h +new file mode 100644 +index 0000000..8150e01 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/flib/common/general.h +@@ -0,0 +1,51 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __GENERAL_H ++#define __GENERAL_H ++ ++#include "std_ext.h" ++#if !defined(NCSW_LINUX) ++#include "errno.h" ++#endif ++ ++ ++extern uint32_t get_mac_addr_crc(uint64_t _addr); ++ ++ ++#define iowrite32be(val, addr) WRITE_UINT32(*addr, val) ++#define ioread32be(addr) GET_UINT32(*addr) ++ ++#define ether_crc(len, addr) get_mac_addr_crc(*(uint64_t *)(addr)>>16) ++ ++ ++#endif /* __GENERAL_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/flib/fsl_enet.h b/drivers/net/dpa/NetCommSw/inc/flib/fsl_enet.h +new file mode 100644 +index 0000000..bb0dea9 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/flib/fsl_enet.h +@@ -0,0 +1,76 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __FSL_ENET_H ++#define __FSL_ENET_H ++ ++/** ++ @Description Ethernet MAC-PHY Interface ++*/ ++ ++enum enet_interface { ++ E_ENET_IF_MII = 0x00010000, /**< MII interface */ ++ E_ENET_IF_RMII = 0x00020000, /**< RMII interface */ ++ E_ENET_IF_SMII = 0x00030000, /**< SMII interface */ ++ E_ENET_IF_GMII = 0x00040000, /**< GMII interface */ ++ E_ENET_IF_RGMII = 0x00050000, /**< RGMII interface */ ++ E_ENET_IF_TBI = 0x00060000, /**< TBI interface */ ++ E_ENET_IF_RTBI = 0x00070000, /**< RTBI interface */ ++ E_ENET_IF_SGMII = 0x00080000, /**< SGMII interface */ ++ E_ENET_IF_XGMII = 0x00090000, /**< XGMII interface */ ++ E_ENET_IF_QSGMII = 0x000a0000, /**< QSGMII interface */ ++ E_ENET_IF_XFI = 0x000b0000 /**< XFI interface */ ++}; ++ ++/** ++ @Description Ethernet Speed (nominal data rate) ++*/ ++enum enet_speed { ++ E_ENET_SPEED_10 = 10, /**< 10 Mbps */ ++ E_ENET_SPEED_100 = 100, /**< 100 Mbps */ ++ E_ENET_SPEED_1000 = 1000, /**< 1000 Mbps = 1 Gbps */ ++ E_ENET_SPEED_10000 = 10000 /**< 10000 Mbps = 10 Gbps */ ++}; ++ ++enum mac_stat_level { ++ /* No statistics */ ++ E_MAC_STAT_NONE = 0, ++ /* Only RMON MIB group 1 (ether stats). Optimized for performance */ ++ E_MAC_STAT_MIB_GRP1, ++ /* Only error counters are available. Optimized for performance */ ++ E_MAC_STAT_PARTIAL, ++ /* All counters available. Not optimized for performance */ ++ E_MAC_STAT_FULL ++}; ++ ++ ++#endif /* __FSL_ENET_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_dtsec.h b/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_dtsec.h +new file mode 100644 +index 0000000..55527c1 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_dtsec.h +@@ -0,0 +1,1060 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __FSL_FMAN_DTSEC_H ++#define __FSL_FMAN_DTSEC_H ++ ++#include "common/general.h" ++#include "fsl_enet.h" ++ ++/** ++ * DOC: dTSEC Init sequence ++ * ++ * To prepare dTSEC block for transfer use the following call sequence: ++ * ++ * - dtsec_defconfig() - This step is optional and yet recommended. Its use is ++ * to obtain the default dTSEC configuration parameters. ++ * ++ * - Change dtsec configuration in &dtsec_cfg. This structure will be used ++ * to customize the dTSEC behavior. ++ * ++ * - dtsec_init() - Applies the configuration on dTSEC hardware. Note that ++ * dTSEC is initialized while both Tx and Rx are disabled. ++ * ++ * - dtsec_set_mac_address() - Set the station address (mac address). ++ * This is used by dTSEC to match against received packets. ++ * ++ * - dtsec_adjust_link() - Set the link speed and duplex parameters ++ * after the PHY establishes the link. ++ * ++ * - dtsec_enable_tx() and dtsec_enable_rx() to enable transmission and ++ * reception. ++ */ ++ ++/** ++ * DOC: dTSEC Graceful stop ++ * ++ * To temporary stop dTSEC activity use dtsec_stop_tx() and dtsec_stop_rx(). ++ * Note that these functions request dTSEC graceful stop but return before this ++ * stop is complete. To query for graceful stop completion use ++ * dtsec_get_event() and check DTSEC_IEVENT_GTSC and DTSEC_IEVENT_GRSC bits. ++ * Alternatively the dTSEC interrupt mask can be set to enable graceful stop ++ * interrupts. ++ * ++ * To resume operation after graceful stop use dtsec_start_tx() and ++ * dtsec_start_rx(). ++ */ ++ ++/** ++ * DOC: dTSEC interrupt handling ++ * ++ * This code does not provide an interrupt handler for dTSEC. Instead this ++ * handler should be implemented and registered to the operating system by the ++ * caller. Some primitives for accessing the event status and mask registers ++ * are provided. ++ * ++ * See "dTSEC Events" section for a list of events that dTSEC can generate. ++ */ ++ ++/** ++ * DOC: dTSEC Events ++ * ++ * Interrupt events cause dTSEC event bits to be set. Software may poll the ++ * event register at any time to check for pending interrupts. If an event ++ * occurs and its corresponding enable bit is set in the interrupt mask ++ * register, the event also causes a hardware interrupt at the PIC. ++ * ++ * To poll for event status use the dtsec_get_event() function. ++ * To configure the interrupt mask use dtsec_enable_interrupt() and ++ * dtsec_disable_interrupt() functions. ++ * After servicing a dTSEC interrupt use dtsec_ack_event to reset the serviced ++ * event bit. ++ * ++ * The following events may be signaled by dTSEC hardware: ++ * ++ * %DTSEC_IEVENT_BABR - Babbling receive error. This bit indicates that ++ * a frame was received with length in excess of the MAC's maximum frame length ++ * register. ++ * ++ * %DTSEC_IEVENT_RXC - Receive control (pause frame) interrupt. A pause ++ * control frame was received while Rx pause frame handling is enabled. ++ * Also see dtsec_handle_rx_pause(). ++ * ++ * %DTSEC_IEVENT_MSRO - MIB counter overflow. The count for one of the MIB ++ * counters has exceeded the size of its register. ++ * ++ * %DTSEC_IEVENT_GTSC - Graceful transmit stop complete. Graceful stop is now ++ * complete. The transmitter is in a stopped state, in which only pause frames ++ * can be transmitted. ++ * Also see dtsec_stop_tx(). ++ * ++ * %DTSEC_IEVENT_BABT - Babbling transmit error. The transmitted frame length ++ * has exceeded the value in the MAC's Maximum Frame Length register. ++ * ++ * %DTSEC_IEVENT_TXC - Transmit control (pause frame) interrupt. his bit ++ * indicates that a control frame was transmitted. ++ * ++ * %DTSEC_IEVENT_TXE - Transmit error. This bit indicates that an error ++ * occurred on the transmitted channel. This bit is set whenever any transmit ++ * error occurs which causes the dTSEC to discard all or part of a frame ++ * (LC, CRL, XFUN). ++ * ++ * %DTSEC_IEVENT_LC - Late collision. This bit indicates that a collision ++ * occurred beyond the collision window (slot time) in half-duplex mode. ++ * The frame is truncated with a bad CRC and the remainder of the frame ++ * is discarded. ++ * ++ * %DTSEC_IEVENT_CRL - Collision retry limit. is bit indicates that the number ++ * of successive transmission collisions has exceeded the MAC's half-duplex ++ * register's retransmission maximum count. The frame is discarded without ++ * being transmitted and transmission of the next frame commences. This only ++ * occurs while in half-duplex mode. ++ * The number of retransmit attempts can be set in ++ * &dtsec_halfdup_cfg.@retransmit before calling dtsec_init(). ++ * ++ * %DTSEC_IEVENT_XFUN - Transmit FIFO underrun. This bit indicates that the ++ * transmit FIFO became empty before the complete frame was transmitted. ++ * The frame is truncated with a bad CRC and the remainder of the frame is ++ * discarded. ++ * ++ * %DTSEC_IEVENT_MAG - TBD ++ * ++ * %DTSEC_IEVENT_MMRD - MII management read completion. ++ * ++ * %DTSEC_IEVENT_MMWR - MII management write completion. ++ * ++ * %DTSEC_IEVENT_GRSC - Graceful receive stop complete. It allows the user to ++ * know if the system has completed the stop and it is safe to write to receive ++ * registers (status, control or configuration registers) that are used by the ++ * system during normal operation. ++ * ++ * %DTSEC_IEVENT_TDPE - Internal data error on transmit. This bit indicates ++ * that the dTSEC has detected a parity error on its stored transmit data, which ++ * is likely to compromise the validity of recently transferred frames. ++ * ++ * %DTSEC_IEVENT_RDPE - Internal data error on receive. This bit indicates that ++ * the dTSEC has detected a parity error on its stored receive data, which is ++ * likely to compromise the validity of recently transferred frames. ++ */ ++/* Interrupt Mask Register (IMASK) */ ++#define DTSEC_IMASK_BREN 0x80000000 ++#define DTSEC_IMASK_RXCEN 0x40000000 ++#define DTSEC_IMASK_MSROEN 0x04000000 ++#define DTSEC_IMASK_GTSCEN 0x02000000 ++#define DTSEC_IMASK_BTEN 0x01000000 ++#define DTSEC_IMASK_TXCEN 0x00800000 ++#define DTSEC_IMASK_TXEEN 0x00400000 ++#define DTSEC_IMASK_LCEN 0x00040000 ++#define DTSEC_IMASK_CRLEN 0x00020000 ++#define DTSEC_IMASK_XFUNEN 0x00010000 ++#define DTSEC_IMASK_ABRTEN 0x00008000 ++#define DTSEC_IMASK_IFERREN 0x00004000 ++#define DTSEC_IMASK_MAGEN 0x00000800 ++#define DTSEC_IMASK_MMRDEN 0x00000400 ++#define DTSEC_IMASK_MMWREN 0x00000200 ++#define DTSEC_IMASK_GRSCEN 0x00000100 ++#define DTSEC_IMASK_TDPEEN 0x00000002 ++#define DTSEC_IMASK_RDPEEN 0x00000001 ++ ++#define EVENTS_MASK \ ++ ((uint32_t)(DTSEC_IMASK_BREN | \ ++ DTSEC_IMASK_RXCEN | \ ++ DTSEC_IMASK_BTEN | \ ++ DTSEC_IMASK_TXCEN | \ ++ DTSEC_IMASK_TXEEN | \ ++ DTSEC_IMASK_ABRTEN | \ ++ DTSEC_IMASK_LCEN | \ ++ DTSEC_IMASK_CRLEN | \ ++ DTSEC_IMASK_XFUNEN | \ ++ DTSEC_IMASK_IFERREN | \ ++ DTSEC_IMASK_MAGEN | \ ++ DTSEC_IMASK_TDPEEN | \ ++ DTSEC_IMASK_RDPEEN)) ++ ++/* dtsec timestamp event bits */ ++#define TMR_PEMASK_TSREEN 0x00010000 ++#define TMR_PEVENT_TSRE 0x00010000 ++ ++/* Group address bit indication */ ++#define MAC_GROUP_ADDRESS 0x0000010000000000ULL ++/* size in bytes of L2 address */ ++#define MAC_ADDRLEN 6 ++ ++#define DEFAULT_HALFDUP_ON FALSE ++#define DEFAULT_HALFDUP_RETRANSMIT 0xf ++#define DEFAULT_HALFDUP_COLL_WINDOW 0x37 ++#define DEFAULT_HALFDUP_EXCESS_DEFER TRUE ++#define DEFAULT_HALFDUP_NO_BACKOFF FALSE ++#define DEFAULT_HALFDUP_BP_NO_BACKOFF FALSE ++#define DEFAULT_HALFDUP_ALT_BACKOFF_VAL 0x0A ++#define DEFAULT_HALFDUP_ALT_BACKOFF_EN FALSE ++#define DEFAULT_RX_DROP_BCAST FALSE ++#define DEFAULT_RX_SHORT_FRM TRUE ++#define DEFAULT_RX_LEN_CHECK FALSE ++#define DEFAULT_TX_PAD_CRC TRUE ++#define DEFAULT_TX_CRC FALSE ++#define DEFAULT_RX_CTRL_ACC FALSE ++#define DEFAULT_TX_PAUSE_TIME 0xf000 ++#define DEFAULT_TBIPA 5 ++#define DEFAULT_RX_PREPEND 0 ++#define DEFAULT_PTP_TSU_EN TRUE ++#define DEFAULT_PTP_EXCEPTION_EN TRUE ++#define DEFAULT_PREAMBLE_LEN 7 ++#define DEFAULT_RX_PREAMBLE FALSE ++#define DEFAULT_TX_PREAMBLE FALSE ++#define DEFAULT_LOOPBACK FALSE ++#define DEFAULT_RX_TIME_STAMP_EN FALSE ++#define DEFAULT_TX_TIME_STAMP_EN FALSE ++#define DEFAULT_RX_FLOW TRUE ++#define DEFAULT_TX_FLOW TRUE ++#define DEFAULT_RX_GROUP_HASH_EXD FALSE ++#define DEFAULT_TX_PAUSE_TIME_EXTD 0 ++#define DEFAULT_RX_PROMISC FALSE ++#define DEFAULT_NON_BACK_TO_BACK_IPG1 0x40 ++#define DEFAULT_NON_BACK_TO_BACK_IPG2 0x60 ++#define DEFAULT_MIN_IFG_ENFORCEMENT 0x50 ++#define DEFAULT_BACK_TO_BACK_IPG 0x60 ++#define DEFAULT_MAXIMUM_FRAME 0x600 ++#define DEFAULT_TBI_PHY_ADDR 5 ++ ++/* register related defines (bits, field offsets..) */ ++#define DTSEC_ID1_ID 0xffff0000 ++#define DTSEC_ID1_REV_MJ 0x0000FF00 ++#define DTSEC_ID1_REV_MN 0x000000ff ++ ++#define DTSEC_ID2_INT_REDUCED_OFF 0x00010000 ++#define DTSEC_ID2_INT_NORMAL_OFF 0x00020000 ++ ++#define DTSEC_ECNTRL_CLRCNT 0x00004000 ++#define DTSEC_ECNTRL_AUTOZ 0x00002000 ++#define DTSEC_ECNTRL_STEN 0x00001000 ++#define DTSEC_ECNTRL_CFG_RO 0x80000000 ++#define DTSEC_ECNTRL_GMIIM 0x00000040 ++#define DTSEC_ECNTRL_TBIM 0x00000020 ++#define DTSEC_ECNTRL_SGMIIM 0x00000002 ++#define DTSEC_ECNTRL_RPM 0x00000010 ++#define DTSEC_ECNTRL_R100M 0x00000008 ++#define DTSEC_ECNTRL_RMM 0x00000004 ++#define DTSEC_ECNTRL_QSGMIIM 0x00000001 ++ ++#define DTSEC_TCTRL_THDF 0x00000800 ++#define DTSEC_TCTRL_TTSE 0x00000040 ++#define DTSEC_TCTRL_GTS 0x00000020 ++#define DTSEC_TCTRL_TFC_PAUSE 0x00000010 ++ ++/* PTV offsets */ ++#define PTV_PTE_OFST 16 ++ ++#define RCTRL_CFA 0x00008000 ++#define RCTRL_GHTX 0x00000400 ++#define RCTRL_RTSE 0x00000040 ++#define RCTRL_GRS 0x00000020 ++#define RCTRL_BC_REJ 0x00000010 ++#define RCTRL_MPROM 0x00000008 ++#define RCTRL_RSF 0x00000004 ++#define RCTRL_UPROM 0x00000001 ++#define RCTRL_PROM (RCTRL_UPROM | RCTRL_MPROM) ++ ++#define TMR_CTL_ESFDP 0x00000800 ++#define TMR_CTL_ESFDE 0x00000400 ++ ++#define MACCFG1_SOFT_RESET 0x80000000 ++#define MACCFG1_LOOPBACK 0x00000100 ++#define MACCFG1_RX_FLOW 0x00000020 ++#define MACCFG1_TX_FLOW 0x00000010 ++#define MACCFG1_TX_EN 0x00000001 ++#define MACCFG1_RX_EN 0x00000004 ++#define MACCFG1_RESET_RxMC 0x00080000 ++#define MACCFG1_RESET_TxMC 0x00040000 ++#define MACCFG1_RESET_RxFUN 0x00020000 ++#define MACCFG1_RESET_TxFUN 0x00010000 ++ ++#define MACCFG2_NIBBLE_MODE 0x00000100 ++#define MACCFG2_BYTE_MODE 0x00000200 ++#define MACCFG2_PRE_AM_Rx_EN 0x00000080 ++#define MACCFG2_PRE_AM_Tx_EN 0x00000040 ++#define MACCFG2_LENGTH_CHECK 0x00000010 ++#define MACCFG2_MAGIC_PACKET_EN 0x00000008 ++#define MACCFG2_PAD_CRC_EN 0x00000004 ++#define MACCFG2_CRC_EN 0x00000002 ++#define MACCFG2_FULL_DUPLEX 0x00000001 ++ ++#define PREAMBLE_LENGTH_SHIFT 12 ++ ++#define IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT 24 ++#define IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT 16 ++#define IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT 8 ++ ++#define IPGIFG_NON_BACK_TO_BACK_IPG_1 0x7F000000 ++#define IPGIFG_NON_BACK_TO_BACK_IPG_2 0x007F0000 ++#define IPGIFG_MIN_IFG_ENFORCEMENT 0x0000FF00 ++#define IPGIFG_BACK_TO_BACK_IPG 0x0000007F ++ ++#define HAFDUP_ALT_BEB 0x00080000 ++#define HAFDUP_BP_NO_BACKOFF 0x00040000 ++#define HAFDUP_NO_BACKOFF 0x00020000 ++#define HAFDUP_EXCESS_DEFER 0x00010000 ++#define HAFDUP_COLLISION_WINDOW 0x000003ff ++ ++#define HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT 20 ++#define HAFDUP_RETRANSMISSION_MAX_SHIFT 12 ++#define HAFDUP_RETRANSMISSION_MAX 0x0000f000 ++ ++#define NUM_OF_HASH_REGS 8 /* Number of hash table registers */ ++ ++/* CAR1/2 bits */ ++#define DTSEC_CAR1_TR64 0x80000000 ++#define DTSEC_CAR1_TR127 0x40000000 ++#define DTSEC_CAR1_TR255 0x20000000 ++#define DTSEC_CAR1_TR511 0x10000000 ++#define DTSEC_CAR1_TRK1 0x08000000 ++#define DTSEC_CAR1_TRMAX 0x04000000 ++#define DTSEC_CAR1_TRMGV 0x02000000 ++ ++#define DTSEC_CAR1_RBYT 0x00010000 ++#define DTSEC_CAR1_RPKT 0x00008000 ++#define DTSEC_CAR1_RFCS 0x00004000 ++#define DTSEC_CAR1_RMCA 0x00002000 ++#define DTSEC_CAR1_RBCA 0x00001000 ++#define DTSEC_CAR1_RXCF 0x00000800 ++#define DTSEC_CAR1_RXPF 0x00000400 ++#define DTSEC_CAR1_RXUO 0x00000200 ++#define DTSEC_CAR1_RALN 0x00000100 ++#define DTSEC_CAR1_RFLR 0x00000080 ++#define DTSEC_CAR1_RCDE 0x00000040 ++#define DTSEC_CAR1_RCSE 0x00000020 ++#define DTSEC_CAR1_RUND 0x00000010 ++#define DTSEC_CAR1_ROVR 0x00000008 ++#define DTSEC_CAR1_RFRG 0x00000004 ++#define DTSEC_CAR1_RJBR 0x00000002 ++#define DTSEC_CAR1_RDRP 0x00000001 ++ ++#define DTSEC_CAR2_TJBR 0x00080000 ++#define DTSEC_CAR2_TFCS 0x00040000 ++#define DTSEC_CAR2_TXCF 0x00020000 ++#define DTSEC_CAR2_TOVR 0x00010000 ++#define DTSEC_CAR2_TUND 0x00008000 ++#define DTSEC_CAR2_TFRG 0x00004000 ++#define DTSEC_CAR2_TBYT 0x00002000 ++#define DTSEC_CAR2_TPKT 0x00001000 ++#define DTSEC_CAR2_TMCA 0x00000800 ++#define DTSEC_CAR2_TBCA 0x00000400 ++#define DTSEC_CAR2_TXPF 0x00000200 ++#define DTSEC_CAR2_TDFR 0x00000100 ++#define DTSEC_CAR2_TEDF 0x00000080 ++#define DTSEC_CAR2_TSCL 0x00000040 ++#define DTSEC_CAR2_TMCL 0x00000020 ++#define DTSEC_CAR2_TLCL 0x00000010 ++#define DTSEC_CAR2_TXCL 0x00000008 ++#define DTSEC_CAR2_TNCL 0x00000004 ++#define DTSEC_CAR2_TDRP 0x00000001 ++ ++#define CAM1_ERRORS_ONLY \ ++ (DTSEC_CAR1_RXPF | DTSEC_CAR1_RALN | DTSEC_CAR1_RFLR \ ++ | DTSEC_CAR1_RCDE | DTSEC_CAR1_RCSE | DTSEC_CAR1_RUND \ ++ | DTSEC_CAR1_ROVR | DTSEC_CAR1_RFRG | DTSEC_CAR1_RJBR \ ++ | DTSEC_CAR1_RDRP) ++ ++#define CAM2_ERRORS_ONLY (DTSEC_CAR2_TFCS | DTSEC_CAR2_TXPF | DTSEC_CAR2_TDRP) ++ ++/* ++ * Group of dTSEC specific counters relating to the standard RMON MIB Group 1 ++ * (or Ethernet) statistics. ++ */ ++#define CAM1_MIB_GRP_1 \ ++ (DTSEC_CAR1_RDRP | DTSEC_CAR1_RBYT | DTSEC_CAR1_RPKT | DTSEC_CAR1_RMCA\ ++ | DTSEC_CAR1_RBCA | DTSEC_CAR1_RALN | DTSEC_CAR1_RUND | DTSEC_CAR1_ROVR\ ++ | DTSEC_CAR1_RFRG | DTSEC_CAR1_RJBR \ ++ | DTSEC_CAR1_TR64 | DTSEC_CAR1_TR127 | DTSEC_CAR1_TR255 \ ++ | DTSEC_CAR1_TR511 | DTSEC_CAR1_TRMAX) ++ ++#define CAM2_MIB_GRP_1 (DTSEC_CAR2_TNCL | DTSEC_CAR2_TDRP) ++ ++/* memory map */ ++ ++struct dtsec_regs { ++ /* dTSEC General Control and Status Registers */ ++ uint32_t tsec_id; /* 0x000 ETSEC_ID register */ ++ uint32_t tsec_id2; /* 0x004 ETSEC_ID2 register */ ++ uint32_t ievent; /* 0x008 Interrupt event register */ ++ uint32_t imask; /* 0x00C Interrupt mask register */ ++ uint32_t reserved0010[1]; ++ uint32_t ecntrl; /* 0x014 E control register */ ++ uint32_t ptv; /* 0x018 Pause time value register */ ++ uint32_t tbipa; /* 0x01C TBI PHY address register */ ++ uint32_t tmr_ctrl; /* 0x020 Time-stamp Control register */ ++ uint32_t tmr_pevent; /* 0x024 Time-stamp event register */ ++ uint32_t tmr_pemask; /* 0x028 Timer event mask register */ ++ uint32_t reserved002c[5]; ++ uint32_t tctrl; /* 0x040 Transmit control register */ ++ uint32_t reserved0044[3]; ++ uint32_t rctrl; /* 0x050 Receive control register */ ++ uint32_t reserved0054[11]; ++ uint32_t igaddr[8]; /* 0x080-0x09C Individual/group address */ ++ uint32_t gaddr[8]; /* 0x0A0-0x0BC Group address registers 0-7 */ ++ uint32_t reserved00c0[16]; ++ uint32_t maccfg1; /* 0x100 MAC configuration #1 */ ++ uint32_t maccfg2; /* 0x104 MAC configuration #2 */ ++ uint32_t ipgifg; /* 0x108 IPG/IFG */ ++ uint32_t hafdup; /* 0x10C Half-duplex */ ++ uint32_t maxfrm; /* 0x110 Maximum frame */ ++ uint32_t reserved0114[10]; ++ uint32_t ifstat; /* 0x13C Interface status */ ++ uint32_t macstnaddr1; /* 0x140 Station Address,part 1 */ ++ uint32_t macstnaddr2; /* 0x144 Station Address,part 2 */ ++ struct { ++ uint32_t exact_match1; /* octets 1-4 */ ++ uint32_t exact_match2; /* octets 5-6 */ ++ } macaddr[15]; /* 0x148-0x1BC mac exact match addresses 1-15 */ ++ uint32_t reserved01c0[16]; ++ uint32_t tr64; /* 0x200 transmit and receive 64 byte frame counter */ ++ uint32_t tr127; /* 0x204 transmit and receive 65 to 127 byte frame ++ * counter */ ++ uint32_t tr255; /* 0x208 transmit and receive 128 to 255 byte frame ++ * counter */ ++ uint32_t tr511; /* 0x20C transmit and receive 256 to 511 byte frame ++ * counter */ ++ uint32_t tr1k; /* 0x210 transmit and receive 512 to 1023 byte frame ++ * counter */ ++ uint32_t trmax; /* 0x214 transmit and receive 1024 to 1518 byte frame ++ * counter */ ++ uint32_t trmgv; /* 0x218 transmit and receive 1519 to 1522 byte good ++ * VLAN frame count */ ++ uint32_t rbyt; /* 0x21C receive byte counter */ ++ uint32_t rpkt; /* 0x220 receive packet counter */ ++ uint32_t rfcs; /* 0x224 receive FCS error counter */ ++ uint32_t rmca; /* 0x228 RMCA receive multicast packet counter */ ++ uint32_t rbca; /* 0x22C receive broadcast packet counter */ ++ uint32_t rxcf; /* 0x230 receive control frame packet counter */ ++ uint32_t rxpf; /* 0x234 receive pause frame packet counter */ ++ uint32_t rxuo; /* 0x238 receive unknown OP code counter */ ++ uint32_t raln; /* 0x23C receive alignment error counter */ ++ uint32_t rflr; /* 0x240 receive frame length error counter */ ++ uint32_t rcde; /* 0x244 receive code error counter */ ++ uint32_t rcse; /* 0x248 receive carrier sense error counter */ ++ uint32_t rund; /* 0x24C receive undersize packet counter */ ++ uint32_t rovr; /* 0x250 receive oversize packet counter */ ++ uint32_t rfrg; /* 0x254 receive fragments counter */ ++ uint32_t rjbr; /* 0x258 receive jabber counter */ ++ uint32_t rdrp; /* 0x25C receive drop */ ++ uint32_t tbyt; /* 0x260 transmit byte counter */ ++ uint32_t tpkt; /* 0x264 transmit packet counter */ ++ uint32_t tmca; /* 0x268 transmit multicast packet counter */ ++ uint32_t tbca; /* 0x26C transmit broadcast packet counter */ ++ uint32_t txpf; /* 0x270 transmit pause control frame counter */ ++ uint32_t tdfr; /* 0x274 transmit deferral packet counter */ ++ uint32_t tedf; /* 0x278 transmit excessive deferral packet counter */ ++ uint32_t tscl; /* 0x27C transmit single collision packet counter */ ++ uint32_t tmcl; /* 0x280 transmit multiple collision packet counter */ ++ uint32_t tlcl; /* 0x284 transmit late collision packet counter */ ++ uint32_t txcl; /* 0x288 transmit excessive collision packet counter */ ++ uint32_t tncl; /* 0x28C transmit total collision counter */ ++ uint32_t reserved0290[1]; ++ uint32_t tdrp; /* 0x294 transmit drop frame counter */ ++ uint32_t tjbr; /* 0x298 transmit jabber frame counter */ ++ uint32_t tfcs; /* 0x29C transmit FCS error counter */ ++ uint32_t txcf; /* 0x2A0 transmit control frame counter */ ++ uint32_t tovr; /* 0x2A4 transmit oversize frame counter */ ++ uint32_t tund; /* 0x2A8 transmit undersize frame counter */ ++ uint32_t tfrg; /* 0x2AC transmit fragments frame counter */ ++ uint32_t car1; /* 0x2B0 carry register one register* */ ++ uint32_t car2; /* 0x2B4 carry register two register* */ ++ uint32_t cam1; /* 0x2B8 carry register one mask register */ ++ uint32_t cam2; /* 0x2BC carry register two mask register */ ++ uint32_t reserved02c0[848]; ++}; ++ ++/** ++ * struct dtsec_mib_grp_1_counters - MIB counter overflows ++ * ++ * @tr64: Transmit and Receive 64 byte frame count. Increment for each ++ * good or bad frame, of any type, transmitted or received, which ++ * is 64 bytes in length. ++ * @tr127: Transmit and Receive 65 to 127 byte frame count. Increments for ++ * each good or bad frame of any type, transmitted or received, ++ * which is 65-127 bytes in length. ++ * @tr255: Transmit and Receive 128 to 255 byte frame count. Increments ++ * for each good or bad frame, of any type, transmitted or ++ * received, which is 128-255 bytes in length. ++ * @tr511: Transmit and Receive 256 to 511 byte frame count. Increments ++ * for each good or bad frame, of any type, transmitted or ++ * received, which is 256-511 bytes in length. ++ * @tr1k: Transmit and Receive 512 to 1023 byte frame count. Increments ++ * for each good or bad frame, of any type, transmitted or ++ * received, which is 512-1023 bytes in length. ++ * @trmax: Transmit and Receive 1024 to 1518 byte frame count. Increments ++ * for each good or bad frame, of any type, transmitted or ++ * received, which is 1024-1518 bytes in length. ++ * @rfrg: Receive fragments count. Increments for each received frame ++ * which is less than 64 bytes in length and contains an invalid ++ * FCS. This includes integral and non-integral lengths. ++ * @rjbr: Receive jabber count. Increments for received frames which ++ * exceed 1518 (non VLAN) or 1522 (VLAN) bytes and contain an ++ * invalid FCS. This includes alignment errors. ++ * @rdrp: Receive dropped packets count. Increments for received frames ++ * which are streamed to system but are later dropped due to lack ++ * of system resources. Does not increment for frames rejected due ++ * to address filtering. ++ * @raln: Receive alignment error count. Increments for each received ++ * frame from 64 to 1518 (non VLAN) or 1522 (VLAN) which contains ++ * an invalid FCS and is not an integral number of bytes. ++ * @rund: Receive undersize packet count. Increments each time a frame is ++ * received which is less than 64 bytes in length and contains a ++ * valid FCS and is otherwise well formed. This count does not ++ * include range length errors. ++ * @rovr: Receive oversize packet count. Increments each time a frame is ++ * received which exceeded 1518 (non VLAN) or 1522 (VLAN) and ++ * contains a valid FCS and is otherwise well formed. ++ * @rbyt: Receive byte count. Increments by the byte count of frames ++ * received, including those in bad packets, excluding preamble and ++ * SFD but including FCS bytes. ++ * @rpkt: Receive packet count. Increments for each received frame ++ * (including bad packets, all unicast, broadcast, and multicast ++ * packets). ++ * @rmca: Receive multicast packet count. Increments for each multicast ++ * frame with valid CRC and of lengths 64 to 1518 (non VLAN) or ++ * 1522 (VLAN), excluding broadcast frames. This count does not ++ * include range/length errors. ++ * @rbca: Receive broadcast packet count. Increments for each broadcast ++ * frame with valid CRC and of lengths 64 to 1518 (non VLAN) or ++ * 1522 (VLAN), excluding multicast frames. Does not include ++ * range/length errors. ++ * @tdrp: Transmit drop frame count. Increments each time a memory error ++ * or an underrun has occurred. ++ * @tncl: Transmit total collision counter. Increments by the number of ++ * collisions experienced during the transmission of a frame. Does ++ * not increment for aborted frames. ++ * ++ * The structure contains a group of dTSEC HW specific counters relating to the ++ * standard RMON MIB Group 1 (or Ethernet statistics) counters. This structure ++ * is counting only the carry events of the corresponding HW counters. ++ * ++ * tr64 to trmax notes: Frame sizes specified are considered excluding preamble ++ * and SFD but including FCS bytes. ++ */ ++struct dtsec_mib_grp_1_counters { ++ uint64_t rdrp; ++ uint64_t tdrp; ++ uint64_t rbyt; ++ uint64_t rpkt; ++ uint64_t rbca; ++ uint64_t rmca; ++ uint64_t raln; ++ uint64_t rund; ++ uint64_t rovr; ++ uint64_t rfrg; ++ uint64_t rjbr; ++ uint64_t tncl; ++ uint64_t tr64; ++ uint64_t tr127; ++ uint64_t tr255; ++ uint64_t tr511; ++ uint64_t tr1k; ++ uint64_t trmax; ++}; ++ ++enum dtsec_stat_counters { ++ E_DTSEC_STAT_TR64, ++ E_DTSEC_STAT_TR127, ++ E_DTSEC_STAT_TR255, ++ E_DTSEC_STAT_TR511, ++ E_DTSEC_STAT_TR1K, ++ E_DTSEC_STAT_TRMAX, ++ E_DTSEC_STAT_TRMGV, ++ E_DTSEC_STAT_RBYT, ++ E_DTSEC_STAT_RPKT, ++ E_DTSEC_STAT_RMCA, ++ E_DTSEC_STAT_RBCA, ++ E_DTSEC_STAT_RXPF, ++ E_DTSEC_STAT_RALN, ++ E_DTSEC_STAT_RFLR, ++ E_DTSEC_STAT_RCDE, ++ E_DTSEC_STAT_RCSE, ++ E_DTSEC_STAT_RUND, ++ E_DTSEC_STAT_ROVR, ++ E_DTSEC_STAT_RFRG, ++ E_DTSEC_STAT_RJBR, ++ E_DTSEC_STAT_RDRP, ++ E_DTSEC_STAT_TFCS, ++ E_DTSEC_STAT_TBYT, ++ E_DTSEC_STAT_TPKT, ++ E_DTSEC_STAT_TMCA, ++ E_DTSEC_STAT_TBCA, ++ E_DTSEC_STAT_TXPF, ++ E_DTSEC_STAT_TNCL, ++ E_DTSEC_STAT_TDRP ++}; ++ ++ ++/** ++ * struct dtsec_cfg - dTSEC configuration ++ * ++ * @halfdup_on: Transmit half-duplex flow control, under software ++ * control for 10/100-Mbps half-duplex media. If set, ++ * back pressure is applied to media by raising carrier. ++ * @halfdup_retransmit: Number of retransmission attempts following a collision. ++ * If this is exceeded dTSEC aborts transmission due to ++ * excessive collisions. The standard specifies the ++ * attempt limit to be 15. ++ * @halfdup_coll_window:The number of bytes of the frame during which ++ * collisions may occur. The default value of 55 ++ * corresponds to the frame byte at the end of the ++ * standard 512-bit slot time window. If collisions are ++ * detected after this byte, the late collision event is ++ * asserted and transmission of current frame is aborted. ++ * @rx_drop_bcast: Discard broadcast frames. If set, all broadcast frames ++ * will be discarded by dTSEC. ++ * @rx_short_frm: Accept short frames. If set, dTSEC will accept frames ++ * of length 14..63 bytes. ++ * @rx_len_check: Length check for received frames. If set, the MAC ++ * checks the frame's length field on receive to ensure it ++ * matches the actual data field length. This only works ++ * for received frames with length field less than 1500. ++ * No check is performed for larger frames. ++ * @tx_pad_crc: Pad and append CRC. If set, the MAC pads all ++ * transmitted short frames and appends a CRC to every ++ * frame regardless of padding requirement. ++ * @tx_crc: Transmission CRC enable. If set, the MAC appends a CRC ++ * to all frames. If frames presented to the MAC have a ++ * valid length and contain a valid CRC, @tx_crc should be ++ * reset. ++ * This field is ignored if @tx_pad_crc is set. ++ * @rx_ctrl_acc: Control frame accept. If set, this overrides 802.3 ++ * standard control frame behavior, and all Ethernet frames ++ * that have an ethertype of 0x8808 are treated as normal ++ * Ethernet frames and passed up to the packet interface on ++ * a DA match. Received pause control frames are passed to ++ * the packet interface only if Rx flow control is also ++ * disabled. See dtsec_handle_rx_pause() function. ++ * @tx_pause_time: Transmit pause time value. This pause value is used as ++ * part of the pause frame to be sent when a transmit pause ++ * frame is initiated. If set to 0 this disables ++ * transmission of pause frames. ++ * @rx_preamble: Receive preamble enable. If set, the MAC recovers the ++ * received Ethernet 7-byte preamble and passes it to the ++ * packet interface at the start of each received frame. ++ * This field should be reset for internal MAC loop-back ++ * mode. ++ * @tx_preamble: User defined preamble enable for transmitted frames. ++ * If set, a user-defined preamble must passed to the MAC ++ * and it is transmitted instead of the standard preamble. ++ * @preamble_len: Length, in bytes, of the preamble field preceding each ++ * Ethernet start-of-frame delimiter byte. The default ++ * value of 0x7 should be used in order to guarantee ++ * reliable operation with IEEE 802.3 compliant hardware. ++ * @rx_prepend: Packet alignment padding length. The specified number ++ * of bytes (1-31) of zero padding are inserted before the ++ * start of each received frame. For Ethernet, where ++ * optional preamble extraction is enabled, the padding ++ * appears before the preamble, otherwise the padding ++ * precedes the layer 2 header. ++ * ++ * This structure contains basic dTSEC configuration and must be passed to ++ * dtsec_init() function. A default set of configuration values can be obtained ++ * by calling dtsec_defconfig(). ++ */ ++struct dtsec_cfg { ++ bool halfdup_on; ++ bool halfdup_alt_backoff_en; ++ bool halfdup_excess_defer; ++ bool halfdup_no_backoff; ++ bool halfdup_bp_no_backoff; ++ uint8_t halfdup_alt_backoff_val; ++ uint16_t halfdup_retransmit; ++ uint16_t halfdup_coll_window; ++ bool rx_drop_bcast; ++ bool rx_short_frm; ++ bool rx_len_check; ++ bool tx_pad_crc; ++ bool tx_crc; ++ bool rx_ctrl_acc; ++ unsigned short tx_pause_time; ++ unsigned short tbipa; ++ bool ptp_tsu_en; ++ bool ptp_exception_en; ++ bool rx_preamble; ++ bool tx_preamble; ++ unsigned char preamble_len; ++ unsigned char rx_prepend; ++ bool loopback; ++ bool rx_time_stamp_en; ++ bool tx_time_stamp_en; ++ bool rx_flow; ++ bool tx_flow; ++ bool rx_group_hash_exd; ++ bool rx_promisc; ++ uint8_t tbi_phy_addr; ++ uint16_t tx_pause_time_extd; ++ uint16_t maximum_frame; ++ uint32_t non_back_to_back_ipg1; ++ uint32_t non_back_to_back_ipg2; ++ uint32_t min_ifg_enforcement; ++ uint32_t back_to_back_ipg; ++}; ++ ++ ++/** ++ * dtsec_defconfig() - Get default dTSEC configuration ++ * @cfg: pointer to configuration structure. ++ * ++ * Call this function to obtain a default set of configuration values for ++ * initializing dTSEC. The user can overwrite any of the values before calling ++ * dtsec_init(), if specific configuration needs to be applied. ++ */ ++void dtsec_defconfig(struct dtsec_cfg *cfg); ++ ++/** ++ * dtsec_init() - Init dTSEC hardware block ++ * @regs: Pointer to dTSEC register block ++ * @cfg: dTSEC configuration data ++ * @iface_mode: dTSEC interface mode, the type of MAC - PHY interface. ++ * @iface_speed: 1G or 10G ++ * @macaddr: MAC station address to be assigned to the device ++ * @fm_rev_maj: major rev number ++ * @fm_rev_min: minor rev number ++ * @exceptions_mask: initial exceptions mask ++ * ++ * This function initializes dTSEC and applies basic configuration. ++ * ++ * dTSEC initialization sequence: ++ * Before enabling Rx/Tx call dtsec_set_address() to set MAC address, ++ * dtsec_adjust_link() to configure interface speed and duplex and finally ++ * dtsec_enable_tx()/dtsec_enable_rx() to start transmission and reception. ++ * ++ * Returns: 0 if successful, an error code otherwise. ++ */ ++int dtsec_init(struct dtsec_regs *regs, struct dtsec_cfg *cfg, ++ enum enet_interface iface_mode, ++ enum enet_speed iface_speed, ++ uint8_t *macaddr, uint8_t fm_rev_maj, ++ uint8_t fm_rev_min, ++ uint32_t exception_mask); ++ ++/** ++ * dtsec_get_revision() - Get dTSEC hardware revision ++ * @regs: Pointer to dTSEC register block ++ * ++ * Returns dtsec_id content ++ * ++ * Call this function to obtain the dTSEC hardware version. ++ */ ++uint32_t dtsec_get_revision(struct dtsec_regs *regs); ++ ++/** ++ * dtsec_set_uc_promisc() - Sets unicast promiscuous mode ++ * @regs: Pointer to dTSEC register block ++ * @enable: Enable unicast promiscuous mode ++ * ++ * Use this function to enable/disable dTSEC L2 address filtering. If the ++ * address filtering is disabled all unicast packets are accepted. ++ * To set dTSEC in promiscuous mode call both dtsec_set_uc_promisc() and ++ * dtsec_set_mc_promisc() to disable filtering for both unicast and multicast ++ * addresses. ++ */ ++void dtsec_set_uc_promisc(struct dtsec_regs *regs, bool enable); ++ ++/** ++ * dtsec_adjust_link() - Adjust dTSEC speed/duplex settings ++ * @regs: Pointer to dTSEC register block ++ * @iface_mode: dTSEC interface mode ++ * @speed: Link speed ++ * @full_dx: True for full-duplex, false for half-duplex. ++ * ++ * This function configures the MAC to function and the desired rates. Use it ++ * to configure dTSEC after dtsec_init() and whenever the link speed changes ++ * (for instance following PHY auto-negociation). ++ * ++ * Returns: 0 if successful, an error code otherwise. ++ */ ++int dtsec_adjust_link(struct dtsec_regs *regs, ++ enum enet_interface iface_mode, ++ enum enet_speed speed, bool full_dx); ++ ++/** ++ * dtsec_set_tbi_phy_addr() - Updates TBI address field ++ * @regs: Pointer to dTSEC register block ++ * @address: Valid PHY address in the range of 1 to 31. 0 is reserved. ++ * ++ * In SGMII mode, the dTSEC's TBIPA field must contain a valid TBI PHY address ++ * so that the associated TBI PHY (i.e. the link) may be initialized. ++ * ++ * Returns: 0 if successful, an error code otherwise. ++ */ ++int dtsec_set_tbi_phy_addr(struct dtsec_regs *regs, ++ uint8_t addr); ++ ++/** ++ * dtsec_disable() - Disable dTSEC Tx and Rx ++ * @regs: Pointer to dTSEC register block ++ * @apply_rx: disable rx side ++ * @apply_tx: disable tx side ++ * ++ * This function disables Tx and Rx in dTSEC. ++ */ ++void dtsec_disable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx); ++ ++/** ++ * dtsec_enable() - Enable dTSEC Tx and Tx ++ * @regs: Pointer to dTSEC register block ++ * @apply_rx: enable rx side ++ * @apply_tx: enable tx side ++ * ++ * This function resets Tx and Rx graceful stop bit and enables dTSEC Tx and Rx. ++ */ ++void dtsec_enable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx); ++ ++/** ++ * dtsec_set_mac_address() - Set MAC station address ++ * @regs: Pointer to dTSEC register block ++ * @macaddr: MAC address array ++ * ++ * This function sets MAC station address. To enable unicast reception call ++ * this after dtsec_init(). While promiscuous mode is disabled dTSEC will match ++ * the destination address of received unicast frames against this address. ++ */ ++void dtsec_set_mac_address(struct dtsec_regs *regs, uint8_t *macaddr); ++ ++/** ++ * dtsec_get_mac_address() - Query MAC station address ++ * @regs: Pointer to dTSEC register block ++ * @macaddr: MAC address array ++ */ ++void dtsec_get_mac_address(struct dtsec_regs *regs, uint8_t *macaddr); ++ ++/** ++ * dtsec_set_max_frame_len() - Set max frame length ++ * @regs: Pointer to dTSEC register block ++ * @length: Max frame length. ++ * ++ * Sets maximum frame length for received and transmitted frames. Frames that ++ * exceeds this length are truncated. ++ */ ++ ++void dtsec_set_max_frame_len(struct dtsec_regs *regs, uint16_t length); ++ ++ ++/** ++ * dtsec_get_max_frame_len() - Query max frame length ++ * @regs: Pointer to dTSEC register block ++ * ++ * Returns: the current value of the maximum frame length. ++ */ ++uint16_t dtsec_get_max_frame_len(struct dtsec_regs *regs); ++ ++ ++/** ++ * dtsec_handle_rx_pause() - Configure pause frame handling ++ * @regs: Pointer to dTSEC register block ++ * @en: Enable pause frame handling in dTSEC ++ * ++ * If enabled, dTSEC will handle pause frames internally. This must be disabled ++ * if dTSEC is set in half-duplex mode. ++ * If pause frame handling is disabled and &dtsec_cfg.rx_ctrl_acc is set, pause ++ * frames will be transferred to the packet interface just like regular Ethernet ++ * frames. ++ */ ++void dtsec_handle_rx_pause(struct dtsec_regs *regs, bool en); ++ ++/** ++ * dtsec_set_tx_pause_time() - Configure Tx pause time ++ * @regs: Pointer to dTSEC register block ++ * @time: Time value included in pause frames ++ * ++ * Call this function to set the time value used in transmitted pause frames. ++ * If time is 0, transmission of pause frames is disabled ++ */ ++void dtsec_set_tx_pause_time(struct dtsec_regs *regs, uint16_t time); ++ ++/** ++ * dtsec_ack_event() - Acknowledge handled events ++ * @regs: Pointer to dTSEC register block ++ * @ev_mask: Events to acknowledge ++ * ++ * After handling events signaled by dTSEC in either polling or interrupt mode, ++ * call this function to reset the associated status bits in dTSEC event ++ * register. ++ */ ++void dtsec_ack_event(struct dtsec_regs *regs, uint32_t ev_mask); ++ ++/** ++ * dtsec_get_event() - Returns currently asserted events ++ * @regs: Pointer to dTSEC register block ++ * @ev_mask: Mask of relevant events ++ * ++ * Call this function to obtain a bit-mask of events that are currently asserted ++ * in dTSEC, taken from IEVENT register. ++ * ++ * Returns: a bit-mask of events asserted in dTSEC. ++ */ ++uint32_t dtsec_get_event(struct dtsec_regs *regs, uint32_t ev_mask); ++/** ++ * dtsec_get_interrupt_mask() - Returns a bit-mask of enabled interrupts ++ * @regs: Pointer to dTSEC register block ++ * ++ * Call this function to obtain a bit-mask of enabled interrupts ++ * in dTSEC, taken from IMASK register. ++ * ++ * Returns: a bit-mask of enabled interrupts in dTSEC. ++ */ ++uint32_t dtsec_get_interrupt_mask(struct dtsec_regs *regs); ++ ++void dtsec_clear_addr_in_paddr (struct dtsec_regs *regs, ++ uint8_t paddr_num); ++ ++void dtsec_add_addr_in_paddr (struct dtsec_regs *regs, ++ uint64_t addr, ++ uint8_t paddr_num); ++ ++void dtsec_enable_tmr_interrupt (struct dtsec_regs *regs); ++ ++void dtsec_disable_tmr_interrupt(struct dtsec_regs *regs); ++ ++/** ++ * dtsec_disable_interrupt() - Disables interrupts for the specified events ++ * @regs: Pointer to dTSEC register block ++ * @ev_mask: Mask of relevant events ++ * ++ * Call this function to disable interrupts in dTSEC for the specified events. ++ * To enable interrupts use dtsec_enable_interrupt(). ++ */ ++void dtsec_disable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask); ++ ++/** ++ * dtsec_enable_interrupt() - Enable interrupts for the specified events ++ * @regs: Pointer to dTSEC register block ++ * @ev_mask: Mask of relevant events ++ * ++ * Call this function to enable interrupts in dTSEC for the specified events. ++ * To disable interrupts use dtsec_disable_interrupt(). ++ */ ++void dtsec_enable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask); ++ ++/** ++ * dtsec_set_ts() - Enables dTSEC timestamps ++ * @regs: Pointer to dTSEC register block ++ * @en: true to enable timestamps, false to disable them ++ * ++ * Call this function to enable/disable dTSEC timestamps. This affects both ++ * Tx and Rx. ++ */ ++void dtsec_set_ts(struct dtsec_regs *regs, bool en); ++ ++/** ++ * dtsec_set_bucket() - Enables/disables a filter bucket ++ * @regs: Pointer to dTSEC register block ++ * @bucket: Bucket index ++ * @enable: true/false to enable/disable this bucket ++ * ++ * This function enables or disables the specified bucket. Enabling a bucket ++ * associated with an address configures dTSEC to accept received packets ++ * with that destination address. ++ * Multiple addresses may be associated with the same bucket. Disabling a ++ * bucket will affect all addresses associated with that bucket. A bucket that ++ * is enabled requires further filtering and verification in the upper layers ++ * ++ */ ++void dtsec_set_bucket(struct dtsec_regs *regs, int bucket, bool enable); ++ ++/** ++ * dtsec_reset_filter_table() - Resets the address filtering table ++ * @regs: Pointer to dTSEC register block ++ * @mcast: Reset multicast entries ++ * @ucast: Reset unicast entries ++ * ++ * Resets all entries in L2 address filter table. After calling this function ++ * all buckets enabled using dtsec_set_bucket() will be disabled. ++ * If dtsec_init_filter_table() was called with @unicast_hash set to false, ++ * @ucast argument is ignored. ++ * This does not affect the primary nor the 15 additional addresses configured ++ * using dtsec_set_address() or dtsec_set_match_address(). ++ */ ++void dtsec_reset_filter_table(struct dtsec_regs *regs, bool mcast, bool ucast); ++ ++/** ++ * dtsec_set_mc_promisc() - Set multicast promiscous mode ++ * @regs: Pointer to dTSEC register block ++ * @enable: Enable multicast promiscous mode ++ * ++ * Call this to enable/disable L2 address filtering for multicast packets. ++ */ ++void dtsec_set_mc_promisc(struct dtsec_regs *regs, bool enable); ++ ++/* statistics APIs */ ++ ++/** ++ * dtsec_set_stat_level() - Enable a group of MIB statistics counters ++ * @regs: Pointer to dTSEC register block ++ * @level: Specifies a certain group of dTSEC MIB HW counters or _all_, ++ * to specify all the existing counters. ++ * If set to _none_, it disables all the counters. ++ * ++ * Enables the MIB statistics hw counters and sets up the carry interrupt ++ * masks for the counters corresponding to the @level input parameter. ++ * ++ * Returns: error if invalid @level value given. ++ */ ++int dtsec_set_stat_level(struct dtsec_regs *regs, enum mac_stat_level level); ++ ++/** ++ * dtsec_reset_stat() - Completely resets all dTSEC HW counters ++ * @regs: Pointer to dTSEC register block ++ */ ++void dtsec_reset_stat(struct dtsec_regs *regs); ++ ++/** ++ * dtsec_get_clear_carry_regs() - Read and clear carry bits (CAR1-2 registers) ++ * @regs: Pointer to dTSEC register block ++ * @car1: car1 register value ++ * @car2: car2 register value ++ * ++ * When set, the carry bits signal that an overflow occurred on the ++ * corresponding counters. ++ * Note that the carry bits (CAR1-2 registers) will assert the ++ * %DTSEC_IEVENT_MSRO interrupt if unmasked (via CAM1-2 regs). ++ * ++ * Returns: true if overflow occurred, otherwise - false ++ */ ++bool dtsec_get_clear_carry_regs(struct dtsec_regs *regs, ++ uint32_t *car1, uint32_t *car2); ++ ++uint32_t dtsec_check_and_clear_tmr_event(struct dtsec_regs *regs); ++ ++uint32_t dtsec_get_stat_counter(struct dtsec_regs *regs, ++ enum dtsec_stat_counters reg_name); ++ ++void dtsec_start_tx(struct dtsec_regs *regs); ++void dtsec_start_rx(struct dtsec_regs *regs); ++void dtsec_stop_rx(struct dtsec_regs *regs); ++void dtsec_stop_tx(struct dtsec_regs *regs); ++uint32_t dtsec_get_rctrl(struct dtsec_regs *regs); ++ ++#endif /* __FSL_FMAN_DTSEC_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_kg.h b/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_kg.h +new file mode 100644 +index 0000000..dd981bb +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_kg.h +@@ -0,0 +1,514 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __FSL_FMAN_KG_H ++#define __FSL_FMAN_KG_H ++ ++#include "common/general.h" ++ ++#define FM_KG_NUM_OF_GENERIC_REGS 8 /**< Num of generic KeyGen regs */ ++#define FMAN_MAX_NUM_OF_HW_PORTS 64 ++/**< Total num of masks allowed on KG extractions */ ++#define FM_KG_EXTRACT_MASKS_NUM 4 ++#define FM_KG_NUM_CLS_PLAN_ENTR 8 /**< Num of class. plan regs */ ++#define FM_KG_CLS_PLAN_GRPS_NUM 32 /**< Max num of class. groups */ ++ ++struct fman_kg_regs { ++ uint32_t fmkg_gcr; ++ uint32_t res004; ++ uint32_t res008; ++ uint32_t fmkg_eer; ++ uint32_t fmkg_eeer; ++ uint32_t res014; ++ uint32_t res018; ++ uint32_t fmkg_seer; ++ uint32_t fmkg_seeer; ++ uint32_t fmkg_gsr; ++ uint32_t fmkg_tpc; ++ uint32_t fmkg_serc; ++ uint32_t res030[4]; ++ uint32_t fmkg_fdor; ++ uint32_t fmkg_gdv0r; ++ uint32_t fmkg_gdv1r; ++ uint32_t res04c[6]; ++ uint32_t fmkg_feer; ++ uint32_t res068[38]; ++ uint32_t fmkg_indirect[63]; ++ uint32_t fmkg_ar; ++}; ++ ++struct fman_kg_scheme_regs { ++ uint32_t kgse_mode; /**< MODE */ ++ uint32_t kgse_ekfc; /**< Extract Known Fields Command */ ++ uint32_t kgse_ekdv; /**< Extract Known Default Value */ ++ uint32_t kgse_bmch; /**< Bit Mask Command High */ ++ uint32_t kgse_bmcl; /**< Bit Mask Command Low */ ++ uint32_t kgse_fqb; /**< Frame Queue Base */ ++ uint32_t kgse_hc; /**< Hash Command */ ++ uint32_t kgse_ppc; /**< Policer Profile Command */ ++ uint32_t kgse_gec[FM_KG_NUM_OF_GENERIC_REGS]; ++ /**< Generic Extract Command */ ++ uint32_t kgse_spc; /**< KeyGen Scheme Entry Statistic Packet Counter */ ++ uint32_t kgse_dv0; /**< KeyGen Scheme Entry Default Value 0 */ ++ uint32_t kgse_dv1; /**< KeyGen Scheme Entry Default Value 1 */ ++ uint32_t kgse_ccbs; /**< KeyGen Scheme Entry Coarse Classification Bit*/ ++ uint32_t kgse_mv; /**< KeyGen Scheme Entry Match vector */ ++ uint32_t kgse_om; /**< KeyGen Scheme Entry Operation Mode bits */ ++ uint32_t kgse_vsp; /**< KeyGen Scheme Entry Virtual Storage Profile */ ++}; ++ ++struct fman_kg_pe_regs{ ++ uint32_t fmkg_pe_sp; ++ uint32_t fmkg_pe_cpp; ++}; ++ ++struct fman_kg_cp_regs { ++ uint32_t kgcpe[FM_KG_NUM_CLS_PLAN_ENTR]; ++}; ++ ++ ++#define FM_KG_KGAR_GO 0x80000000 ++#define FM_KG_KGAR_READ 0x40000000 ++#define FM_KG_KGAR_WRITE 0x00000000 ++#define FM_KG_KGAR_SEL_SCHEME_ENTRY 0x00000000 ++#define FM_KG_KGAR_SCM_WSEL_UPDATE_CNT 0x00008000 ++ ++#define KG_SCH_PP_SHIFT_HIGH 0x80000000 ++#define KG_SCH_PP_NO_GEN 0x10000000 ++#define KG_SCH_PP_SHIFT_LOW 0x0000F000 ++#define KG_SCH_MODE_NIA_PLCR 0x40000000 ++#define KG_SCH_GEN_EXTRACT_TYPE 0x00008000 ++#define KG_SCH_BITMASK_MASK 0x000000FF ++#define KG_SCH_GEN_VALID 0x80000000 ++#define KG_SCH_GEN_MASK 0x00FF0000 ++#define FM_PCD_KG_KGAR_ERR 0x20000000 ++#define FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY 0x01000000 ++#define FM_PCD_KG_KGAR_SEL_PORT_ENTRY 0x02000000 ++#define FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP 0x00008000 ++#define FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP 0x00004000 ++#define FM_PCD_KG_KGAR_WSEL_MASK 0x0000FF00 ++#define KG_SCH_HASH_CONFIG_NO_FQID 0x80000000 ++#define KG_SCH_HASH_CONFIG_SYM 0x40000000 ++ ++#define FM_EX_KG_DOUBLE_ECC 0x80000000 ++#define FM_EX_KG_KEYSIZE_OVERFLOW 0x40000000 ++ ++/* ECC capture register */ ++#define KG_FMKG_SERC_CAP 0x80000000 ++#define KG_FMKG_SERC_CET 0x40000000 ++#define KG_FMKG_SERC_CNT_MSK 0x00FF0000 ++#define KG_FMKG_SERC_CNT_SHIFT 16 ++#define KG_FMKG_SERC_ADDR_MSK 0x000003FF ++ ++/* Masks */ ++#define FM_KG_KGGCR_EN 0x80000000 ++#define KG_SCH_GEN_VALID 0x80000000 ++#define KG_SCH_GEN_EXTRACT_TYPE 0x00008000 ++#define KG_ERR_TYPE_DOUBLE 0x40000000 ++#define KG_ERR_ADDR_MASK 0x00000FFF ++#define KG_SCH_MODE_EN 0x80000000 ++ ++/* shifts */ ++#define FM_KG_KGAR_NUM_SHIFT 16 ++#define FM_KG_PE_CPP_MASK_SHIFT 16 ++#define FM_KG_KGAR_WSEL_SHIFT 8 ++ ++#define FM_KG_SCH_GEN_HT_INVALID 0 ++ ++#define FM_KG_MASK_SEL_GEN_BASE 0x20 ++ ++#define KG_GET_MASK_SEL_SHIFT(shift, i) \ ++switch (i) \ ++{ \ ++ case 0: (shift) = 26; break; \ ++ case 1: (shift) = 20; break; \ ++ case 2: (shift) = 10; break; \ ++ case 3: (shift) = 4; break; \ ++ default: (shift) = 0; \ ++} ++ ++#define KG_GET_MASK_OFFSET_SHIFT(shift, i) \ ++switch (i) \ ++{ \ ++ case 0: (shift) = 16; break; \ ++ case 1: (shift) = 0; break; \ ++ case 2: (shift) = 28; break; \ ++ case 3: (shift) = 24; break; \ ++ default: (shift) = 0; \ ++} ++ ++#define KG_GET_MASK_SHIFT(shift, i) \ ++switch (i) \ ++{ \ ++ case 0: shift = 24; break; \ ++ case 1: shift = 16; break; \ ++ case 2: shift = 8; break; \ ++ case 3: shift = 0; break; \ ++ default: shift = 0; \ ++} ++ ++/* Port entry CPP register */ ++#define FMAN_KG_PE_CPP_MASK_SHIFT 16 ++ ++/* Scheme registers */ ++#define FMAN_KG_SCH_MODE_EN 0x80000000 ++#define FMAN_KG_SCH_MODE_NIA_PLCR 0x40000000 ++#define FMAN_KG_SCH_MODE_CCOBASE_SHIFT 24 ++ ++#define FMAN_KG_SCH_DEF_MAC_ADDR_SHIFT 30 ++#define FMAN_KG_SCH_DEF_VLAN_TCI_SHIFT 28 ++#define FMAN_KG_SCH_DEF_ETYPE_SHIFT 26 ++#define FMAN_KG_SCH_DEF_PPP_SID_SHIFT 24 ++#define FMAN_KG_SCH_DEF_PPP_PID_SHIFT 22 ++#define FMAN_KG_SCH_DEF_MPLS_SHIFT 20 ++#define FMAN_KG_SCH_DEF_IP_ADDR_SHIFT 18 ++#define FMAN_KG_SCH_DEF_PTYPE_SHIFT 16 ++#define FMAN_KG_SCH_DEF_IP_TOS_TC_SHIFT 14 ++#define FMAN_KG_SCH_DEF_IPv6_FL_SHIFT 12 ++#define FMAN_KG_SCH_DEF_IPSEC_SPI_SHIFT 10 ++#define FMAN_KG_SCH_DEF_L4_PORT_SHIFT 8 ++#define FMAN_KG_SCH_DEF_TCP_FLG_SHIFT 6 ++ ++#define FMAN_KG_SCH_GEN_VALID 0x80000000 ++#define FMAN_KG_SCH_GEN_SIZE_MAX 16 ++#define FMAN_KG_SCH_GEN_OR 0x00008000 ++ ++#define FMAN_KG_SCH_GEN_DEF_SHIFT 29 ++#define FMAN_KG_SCH_GEN_SIZE_SHIFT 24 ++#define FMAN_KG_SCH_GEN_MASK_SHIFT 16 ++#define FMAN_KG_SCH_GEN_HT_SHIFT 8 ++ ++#define FMAN_KG_SCH_HASH_HSHIFT_SHIFT 24 ++#define FMAN_KG_SCH_HASH_HSHIFT_MAX 0x28 ++#define FMAN_KG_SCH_HASH_SYM 0x40000000 ++#define FMAN_KG_SCH_HASH_NO_FQID_GEN 0x80000000 ++ ++#define FMAN_KG_SCH_PP_SH_SHIFT 27 ++#define FMAN_KG_SCH_PP_SL_SHIFT 12 ++#define FMAN_KG_SCH_PP_SH_MASK 0x80000000 ++#define FMAN_KG_SCH_PP_SL_MASK 0x0000F000 ++#define FMAN_KG_SCH_PP_SHIFT_MAX 0x17 ++#define FMAN_KG_SCH_PP_MASK_SHIFT 16 ++#define FMAN_KG_SCH_PP_NO_GEN 0x10000000 ++ ++enum fman_kg_gen_extract_src { ++ E_FMAN_KG_GEN_EXTRACT_ETH, ++ E_FMAN_KG_GEN_EXTRACT_ETYPE, ++ E_FMAN_KG_GEN_EXTRACT_SNAP, ++ E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_1, ++ E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_N, ++ E_FMAN_KG_GEN_EXTRACT_PPPoE, ++ E_FMAN_KG_GEN_EXTRACT_MPLS_1, ++ E_FMAN_KG_GEN_EXTRACT_MPLS_2, ++ E_FMAN_KG_GEN_EXTRACT_MPLS_3, ++ E_FMAN_KG_GEN_EXTRACT_MPLS_N, ++ E_FMAN_KG_GEN_EXTRACT_IPv4_1, ++ E_FMAN_KG_GEN_EXTRACT_IPv6_1, ++ E_FMAN_KG_GEN_EXTRACT_IPv4_2, ++ E_FMAN_KG_GEN_EXTRACT_IPv6_2, ++ E_FMAN_KG_GEN_EXTRACT_MINENCAP, ++ E_FMAN_KG_GEN_EXTRACT_IP_PID, ++ E_FMAN_KG_GEN_EXTRACT_GRE, ++ E_FMAN_KG_GEN_EXTRACT_TCP, ++ E_FMAN_KG_GEN_EXTRACT_UDP, ++ E_FMAN_KG_GEN_EXTRACT_SCTP, ++ E_FMAN_KG_GEN_EXTRACT_DCCP, ++ E_FMAN_KG_GEN_EXTRACT_IPSEC_AH, ++ E_FMAN_KG_GEN_EXTRACT_IPSEC_ESP, ++ E_FMAN_KG_GEN_EXTRACT_SHIM_1, ++ E_FMAN_KG_GEN_EXTRACT_SHIM_2, ++ E_FMAN_KG_GEN_EXTRACT_FROM_DFLT, ++ E_FMAN_KG_GEN_EXTRACT_FROM_FRAME_START, ++ E_FMAN_KG_GEN_EXTRACT_FROM_PARSE_RESULT, ++ E_FMAN_KG_GEN_EXTRACT_FROM_END_OF_PARSE, ++ E_FMAN_KG_GEN_EXTRACT_FROM_FQID ++}; ++ ++struct fman_kg_ex_ecc_attr ++{ ++ bool valid; ++ bool double_ecc; ++ uint16_t addr; ++ uint8_t single_ecc_count; ++}; ++ ++enum fman_kg_def_select ++{ ++ E_FMAN_KG_DEF_GLOBAL_0, ++ E_FMAN_KG_DEF_GLOBAL_1, ++ E_FMAN_KG_DEF_SCHEME_0, ++ E_FMAN_KG_DEF_SCHEME_1 ++}; ++ ++struct fman_kg_extract_def ++{ ++ enum fman_kg_def_select mac_addr; ++ enum fman_kg_def_select vlan_tci; ++ enum fman_kg_def_select etype; ++ enum fman_kg_def_select ppp_sid; ++ enum fman_kg_def_select ppp_pid; ++ enum fman_kg_def_select mpls; ++ enum fman_kg_def_select ip_addr; ++ enum fman_kg_def_select ptype; ++ enum fman_kg_def_select ip_tos_tc; ++ enum fman_kg_def_select ipv6_fl; ++ enum fman_kg_def_select ipsec_spi; ++ enum fman_kg_def_select l4_port; ++ enum fman_kg_def_select tcp_flg; ++}; ++ ++enum fman_kg_gen_extract_type ++{ ++ E_FMAN_KG_HASH_EXTRACT, ++ E_FMAN_KG_OR_EXTRACT ++}; ++ ++struct fman_kg_gen_extract_params ++{ ++ /* Hash or Or-ed extract */ ++ enum fman_kg_gen_extract_type type; ++ enum fman_kg_gen_extract_src src; ++ bool no_validation; ++ /* Extraction offset from the header location specified above */ ++ uint8_t offset; ++ /* Size of extraction for FMAN_KG_HASH_EXTRACT, ++ * hash result shift for FMAN_KG_OR_EXTRACT */ ++ uint8_t extract; ++ uint8_t mask; ++ /* Default value to use when header specified ++ * by fman_kg_gen_extract_src doesn't present */ ++ enum fman_kg_def_select def_val; ++}; ++ ++struct fman_kg_extract_mask ++{ ++ /**< Indication if mask is on known field extraction or ++ * on general extraction; TRUE for known field */ ++ bool is_known; ++ /**< One of FMAN_KG_EXTRACT_xxx defines for known fields mask and ++ * generic register index for generic extracts mask */ ++ uint32_t field_or_gen_idx; ++ /**< Byte offset from start of the extracted data specified ++ * by field_or_gen_idx */ ++ uint8_t offset; ++ /**< Byte mask (selected bits will be used) */ ++ uint8_t mask; ++}; ++ ++struct fman_kg_extract_params ++{ ++ /* Or-ed mask of FMAN_KG_EXTRACT_xxx defines */ ++ uint32_t known_fields; ++ struct fman_kg_extract_def known_fields_def; ++ /* Number of entries in gen_extract */ ++ uint8_t gen_extract_num; ++ struct fman_kg_gen_extract_params gen_extract[FM_KG_NUM_OF_GENERIC_REGS]; ++ /* Number of entries in masks */ ++ uint8_t masks_num; ++ struct fman_kg_extract_mask masks[FM_KG_EXTRACT_MASKS_NUM]; ++ uint32_t def_scheme_0; ++ uint32_t def_scheme_1; ++}; ++ ++struct fman_kg_hash_params ++{ ++ bool use_hash; ++ uint8_t shift_r; ++ uint32_t mask; /**< 24-bit mask */ ++ bool sym; /**< Symmetric hash for src and dest pairs */ ++}; ++ ++struct fman_kg_pp_params ++{ ++ uint8_t base; ++ uint8_t shift; ++ uint8_t mask; ++ bool bypass_pp_gen; ++}; ++ ++struct fman_kg_cc_params ++{ ++ uint8_t base_offset; ++ uint32_t qlcv_bits_sel; ++}; ++ ++enum fman_pcd_engine ++{ ++ E_FMAN_PCD_INVALID = 0, /**< Invalid PCD engine indicated*/ ++ E_FMAN_PCD_DONE, /**< No PCD Engine indicated */ ++ E_FMAN_PCD_KG, /**< Keygen indicated */ ++ E_FMAN_PCD_CC, /**< Coarse classification indicated */ ++ E_FMAN_PCD_PLCR, /**< Policer indicated */ ++ E_FMAN_PCD_PRS /**< Parser indicated */ ++}; ++ ++struct fman_kg_cls_plan_params ++{ ++ uint8_t entries_mask; ++ uint32_t mask_vector[FM_KG_NUM_CLS_PLAN_ENTR]; ++}; ++ ++struct fman_kg_scheme_params ++{ ++ uint32_t match_vector; ++ struct fman_kg_extract_params extract_params; ++ struct fman_kg_hash_params hash_params; ++ uint32_t base_fqid; ++ /* What we do w/features supported per FM version ?? */ ++ bool bypass_fqid_gen; ++ struct fman_kg_pp_params policer_params; ++ struct fman_kg_cc_params cc_params; ++ bool update_counter; ++ /**< counter_value: Set scheme counter to the specified value; ++ * relevant only when update_counter = TRUE. */ ++ uint32_t counter_value; ++ enum fman_pcd_engine next_engine; ++ /**< Next engine action code */ ++ uint32_t next_engine_action; ++}; ++ ++ ++ ++int fman_kg_write_ar_wait(struct fman_kg_regs *regs, uint32_t fmkg_ar); ++void fman_kg_write_sp(struct fman_kg_regs *regs, uint32_t sp, bool add); ++void fman_kg_write_cpp(struct fman_kg_regs *regs, uint32_t cpp); ++void fman_kg_get_event(struct fman_kg_regs *regs, ++ uint32_t *event, ++ uint32_t *scheme_idx); ++void fman_kg_init(struct fman_kg_regs *regs, ++ uint32_t exceptions, ++ uint32_t dflt_nia); ++void fman_kg_enable_scheme_interrupts(struct fman_kg_regs *regs); ++void fman_kg_enable(struct fman_kg_regs *regs); ++void fman_kg_disable(struct fman_kg_regs *regs); ++int fman_kg_write_bind_cls_plans(struct fman_kg_regs *regs, ++ uint8_t hwport_id, ++ uint32_t bind_cls_plans); ++int fman_kg_build_bind_cls_plans(uint8_t grp_base, ++ uint8_t grp_mask, ++ uint32_t *bind_cls_plans); ++int fman_kg_write_bind_schemes(struct fman_kg_regs *regs, ++ uint8_t hwport_id, ++ uint32_t schemes); ++int fman_kg_write_cls_plan(struct fman_kg_regs *regs, ++ uint8_t grp_id, ++ uint8_t entries_mask, ++ uint8_t hwport_id, ++ struct fman_kg_cp_regs *cls_plan_regs); ++int fman_kg_build_cls_plan(struct fman_kg_cls_plan_params *params, ++ struct fman_kg_cp_regs *cls_plan_regs); ++uint32_t fman_kg_get_schemes_total_counter(struct fman_kg_regs *regs); ++int fman_kg_set_scheme_counter(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id, ++ uint32_t counter); ++int fman_kg_get_scheme_counter(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id, ++ uint32_t *counter); ++int fman_kg_delete_scheme(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id); ++int fman_kg_write_scheme(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id, ++ struct fman_kg_scheme_regs *scheme_regs, ++ bool update_counter); ++int fman_kg_build_scheme(struct fman_kg_scheme_params *params, ++ struct fman_kg_scheme_regs *scheme_regs); ++void fman_kg_get_capture(struct fman_kg_regs *regs, ++ struct fman_kg_ex_ecc_attr *ecc_attr, ++ bool clear); ++void fman_kg_get_exception(struct fman_kg_regs *regs, ++ uint32_t *events, ++ uint32_t *scheme_ids, ++ bool clear); ++void fman_kg_set_exception(struct fman_kg_regs *regs, ++ uint32_t exception, ++ bool enable); ++void fman_kg_set_dflt_val(struct fman_kg_regs *regs, ++ uint8_t def_id, ++ uint32_t val); ++void fman_kg_set_data_after_prs(struct fman_kg_regs *regs, uint8_t offset); ++ ++ ++ ++/**************************************************************************//** ++ @Description NIA Description ++*//***************************************************************************/ ++#define KG_NIA_ORDER_RESTOR 0x00800000 ++#define KG_NIA_ENG_FM_CTL 0x00000000 ++#define KG_NIA_ENG_PRS 0x00440000 ++#define KG_NIA_ENG_KG 0x00480000 ++#define KG_NIA_ENG_PLCR 0x004C0000 ++#define KG_NIA_ENG_BMI 0x00500000 ++#define KG_NIA_ENG_QMI_ENQ 0x00540000 ++#define KG_NIA_ENG_QMI_DEQ 0x00580000 ++#define KG_NIA_ENG_MASK 0x007C0000 ++ ++#define KG_NIA_AC_MASK 0x0003FFFF ++ ++#define KG_NIA_INVALID 0xFFFFFFFF ++ ++static __inline__ uint32_t fm_kg_build_nia(enum fman_pcd_engine next_engine, ++ uint32_t next_engine_action) ++{ ++ uint32_t nia; ++ ++ if (next_engine_action & ~KG_NIA_AC_MASK) ++ return KG_NIA_INVALID; ++ ++ switch (next_engine) { ++ case E_FMAN_PCD_DONE: ++ nia = KG_NIA_ENG_BMI | next_engine_action; ++ break; ++ ++ case E_FMAN_PCD_KG: ++ nia = KG_NIA_ENG_KG | next_engine_action; ++ break; ++ ++ case E_FMAN_PCD_CC: ++ nia = KG_NIA_ENG_FM_CTL | next_engine_action; ++ break; ++ ++ case E_FMAN_PCD_PLCR: ++ nia = KG_NIA_ENG_PLCR | next_engine_action; ++ break; ++ ++ default: ++ nia = KG_NIA_INVALID; ++ } ++ ++ return nia; ++} ++ ++#endif /* __FSL_FMAN_KG_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_memac.h b/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_memac.h +new file mode 100644 +index 0000000..5cf48c7 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_memac.h +@@ -0,0 +1,381 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __FSL_FMAN_MEMAC_H ++#define __FSL_FMAN_MEMAC_H ++ ++#include "common/general.h" ++#include "fsl_enet.h" ++ ++ ++#define MEMAC_NUM_OF_PADDRS 7 /* Num of additional exact match MAC adr regs */ ++ ++/* Control and Configuration Register (COMMAND_CONFIG) */ ++#define CMD_CFG_MG 0x80000000 /* 00 Magic Packet detection */ ++#define CMD_CFG_REG_LOWP_RXETY 0x01000000 /* 07 Rx low power indication */ ++#define CMD_CFG_TX_LOWP_ENA 0x00800000 /* 08 Tx Low Power Idle Enable */ ++#define CMD_CFG_SFD_ANY 0x00200000 /* 10 Disable SFD check */ ++#define CMD_CFG_PFC_MODE 0x00080000 /* 12 Enable PFC */ ++#define CMD_CFG_NO_LEN_CHK 0x00020000 /* 14 Payload length check disable */ ++#define CMD_CFG_SEND_IDLE 0x00010000 /* 15 Force idle generation */ ++#define CMD_CFG_CNT_FRM_EN 0x00002000 /* 18 Control frame rx enable */ ++#define CMD_CFG_SW_RESET 0x00001000 /* 19 S/W Reset, self clearing bit */ ++#define CMD_CFG_TX_PAD_EN 0x00000800 /* 20 Enable Tx padding of frames */ ++#define CMD_CFG_LOOPBACK_EN 0x00000400 /* 21 XGMII/GMII loopback enable */ ++#define CMD_CFG_TX_ADDR_INS 0x00000200 /* 22 Tx source MAC addr insertion */ ++#define CMD_CFG_PAUSE_IGNORE 0x00000100 /* 23 Ignore Pause frame quanta */ ++#define CMD_CFG_PAUSE_FWD 0x00000080 /* 24 Terminate/frwd Pause frames */ ++#define CMD_CFG_CRC_FWD 0x00000040 /* 25 Terminate/frwd CRC of frames */ ++#define CMD_CFG_PAD_EN 0x00000020 /* 26 Frame padding removal */ ++#define CMD_CFG_PROMIS_EN 0x00000010 /* 27 Promiscuous operation enable */ ++#define CMD_CFG_WAN_MODE 0x00000008 /* 28 WAN mode enable */ ++#define CMD_CFG_RX_EN 0x00000002 /* 30 MAC receive path enable */ ++#define CMD_CFG_TX_EN 0x00000001 /* 31 MAC transmit path enable */ ++ ++/* Interface Mode Register (IF_MODE) */ ++#define IF_MODE_MASK 0x00000003 /* 30-31 Mask on i/f mode bits */ ++#define IF_MODE_XGMII 0x00000000 /* 30-31 XGMII (10G) interface */ ++#define IF_MODE_GMII 0x00000002 /* 30-31 GMII (1G) interface */ ++#define IF_MODE_RGMII 0x00000004 ++#define IF_MODE_RGMII_AUTO 0x00008000 ++ ++/* Hash table Control Register (HASHTABLE_CTRL) */ ++#define HASH_CTRL_MCAST_SHIFT 26 ++#define HASH_CTRL_MCAST_EN 0x00000100 /* 23 Mcast frame rx for hash */ ++#define HASH_CTRL_ADDR_MASK 0x0000003F /* 26-31 Hash table address code */ ++ ++#define GROUP_ADDRESS 0x0000010000000000LL /* MAC mcast indication */ ++#define HASH_TABLE_SIZE 64 /* Hash tbl size */ ++ ++/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */ ++#define TX_IPG_LENGTH_MASK 0x0000003F ++ ++/* Statistics Configuration Register (STATN_CONFIG) */ ++#define STATS_CFG_CLR 0x00000004 /* 29 Reset all counters */ ++#define STATS_CFG_CLR_ON_RD 0x00000002 /* 30 Clear on read */ ++#define STATS_CFG_SATURATE 0x00000001 /* 31 Saturate at the maximum val */ ++ ++/* Interrupt Mask Register (IMASK) */ ++#define MEMAC_IMASK_MGI 0x40000000 /* 1 Magic pkt detec indication */ ++#define MEMAC_IMASK_TECC_ER 0x02000000 /* 6 Transmit frame ECC error evnt */ ++#define MEMAC_IMASK_RECC_ER 0x01000000 /* 7 Receive frame ECC error evnt */ ++ ++#define MEMAC_ALL_IMASKS \ ++ ((uint32_t)(MEMAC_IMASK_MGI | \ ++ MEMAC_IMASK_TECC_ER | \ ++ MEMAC_IMASK_RECC_ER)) ++ ++#define MEMAC_IEVNT_PCS 0x80000000 /* PCS (XG). Link sync (G) */ ++#define MEMAC_IEVNT_AN 0x40000000 /* Auto-negotiation */ ++#define MEMAC_IEVNT_LT 0x20000000 /* Link Training/New page */ ++#define MEMAC_IEVNT_MGI 0x00004000 /* Magic pkt detection */ ++#define MEMAC_IEVNT_RX_FIFO_OVFL 0x00001000 /* Rx FIFO overflow */ ++#define MEMAC_IEVNT_TX_FIFO_UNFL 0x00000800 /* Tx FIFO underflow */ ++#define MEMAC_IEVNT_TX_FIFO_OVFL 0x00000400 /* Tx FIFO overflow */ ++#define MEMAC_IEVNT_TX_ECC_ER 0x00000200 /* Tx frame ECC error */ ++#define MEMAC_IEVNT_RX_ECC_ER 0x00000100 /* Rx frame ECC error */ ++#define MEMAC_IEVNT_LI_FAULT 0x00000080 /* Link Interruption flt */ ++#define MEMAC_IEVNT_RX_EMPTY 0x00000040 /* Rx FIFO empty */ ++#define MEMAC_IEVNT_TX_EMPTY 0x00000020 /* Tx FIFO empty */ ++#define MEMAC_IEVNT_RX_LOWP 0x00000010 /* Low Power Idle */ ++#define MEMAC_IEVNT_PHY_LOS 0x00000004 /* Phy loss of signal */ ++#define MEMAC_IEVNT_REM_FAULT 0x00000002 /* Remote fault (XGMII) */ ++#define MEMAC_IEVNT_LOC_FAULT 0x00000001 /* Local fault (XGMII) */ ++ ++#define MEMAC_EVENTS_MASK \ ++ ((uint32_t)(MEMAC_IEVNT_PCS | \ ++ MEMAC_IEVNT_AN | \ ++ MEMAC_IEVNT_LT | \ ++ MEMAC_IEVNT_MGI | \ ++ MEMAC_IEVNT_RX_FIFO_OVFL | \ ++ MEMAC_IEVNT_TX_FIFO_UNFL | \ ++ MEMAC_IEVNT_TX_FIFO_OVFL | \ ++ MEMAC_IEVNT_TX_ECC_ER | \ ++ MEMAC_IEVNT_RX_ECC_ER | \ ++ MEMAC_IEVNT_LI_FAULT | \ ++ MEMAC_IEVNT_RX_EMPTY | \ ++ MEMAC_IEVNT_TX_EMPTY | \ ++ MEMAC_IEVNT_RX_LOWP | \ ++ MEMAC_IEVNT_PHY_LOS | \ ++ MEMAC_IEVNT_REM_FAULT | \ ++ MEMAC_IEVNT_LOC_FAULT)) ++ ++enum memac_counters { ++ E_MEMAC_COUNTER_R64, ++ E_MEMAC_COUNTER_R127, ++ E_MEMAC_COUNTER_R255, ++ E_MEMAC_COUNTER_R511, ++ E_MEMAC_COUNTER_R1023, ++ E_MEMAC_COUNTER_R1518, ++ E_MEMAC_COUNTER_R1519X, ++ E_MEMAC_COUNTER_RFRG, ++ E_MEMAC_COUNTER_RJBR, ++ E_MEMAC_COUNTER_RDRP, ++ E_MEMAC_COUNTER_RALN, ++ E_MEMAC_COUNTER_TUND, ++ E_MEMAC_COUNTER_ROVR, ++ E_MEMAC_COUNTER_RXPF, ++ E_MEMAC_COUNTER_TXPF, ++ E_MEMAC_COUNTER_ROCT, ++ E_MEMAC_COUNTER_RMCA, ++ E_MEMAC_COUNTER_RBCA, ++ E_MEMAC_COUNTER_RPKT, ++ E_MEMAC_COUNTER_RUCA, ++ E_MEMAC_COUNTER_RERR, ++ E_MEMAC_COUNTER_TOCT, ++ E_MEMAC_COUNTER_TMCA, ++ E_MEMAC_COUNTER_TBCA, ++ E_MEMAC_COUNTER_TUCA, ++ E_MEMAC_COUNTER_TERR ++}; ++ ++#define DEFAULT_PAUSE_QUANTA 0xf000 ++#define DEFAULT_FRAME_LENGTH 0x600 ++#define DEFAULT_TX_IPG_LENGTH 12 ++ ++/* ++ * memory map ++ */ ++ ++struct mac_addr { ++ uint32_t mac_addr_l; /* Lower 32 bits of 48-bit MAC address */ ++ uint32_t mac_addr_u; /* Upper 16 bits of 48-bit MAC address */ ++}; ++ ++struct memac_regs { ++ /* General Control and Status */ ++ uint32_t res0000[2]; ++ uint32_t command_config; /* 0x008 Ctrl and cfg */ ++ struct mac_addr mac_addr0; /* 0x00C-0x010 MAC_ADDR_0...1 */ ++ uint32_t maxfrm; /* 0x014 Max frame length */ ++ uint32_t res0018[5]; ++ uint32_t hashtable_ctrl; /* 0x02C Hash table control */ ++ uint32_t res0030[4]; ++ uint32_t ievent; /* 0x040 Interrupt event */ ++ uint32_t tx_ipg_length; /* 0x044 Transmitter inter-packet-gap */ ++ uint32_t res0048; ++ uint32_t imask; /* 0x04C Interrupt mask */ ++ uint32_t res0050; ++ uint32_t pause_quanta[4]; /* 0x054 Pause quanta */ ++ uint32_t pause_thresh[4]; /* 0x064 Pause quanta threshold */ ++ uint32_t rx_pause_status; /* 0x074 Receive pause status */ ++ uint32_t res0078[2]; ++ struct mac_addr mac_addr[MEMAC_NUM_OF_PADDRS]; /* 0x80-0x0B4 mac padr */ ++ uint32_t lpwake_timer; /* 0x0B8 Low Power Wakeup Timer */ ++ uint32_t sleep_timer; /* 0x0BC Transmit EEE Low Power Timer */ ++ uint32_t res00c0[8]; ++ uint32_t statn_config; /* 0x0E0 Statistics configuration */ ++ uint32_t res00e4[7]; ++ /* Rx Statistics Counter */ ++ uint32_t reoct_l; ++ uint32_t reoct_u; ++ uint32_t roct_l; ++ uint32_t roct_u; ++ uint32_t raln_l; ++ uint32_t raln_u; ++ uint32_t rxpf_l; ++ uint32_t rxpf_u; ++ uint32_t rfrm_l; ++ uint32_t rfrm_u; ++ uint32_t rfcs_l; ++ uint32_t rfcs_u; ++ uint32_t rvlan_l; ++ uint32_t rvlan_u; ++ uint32_t rerr_l; ++ uint32_t rerr_u; ++ uint32_t ruca_l; ++ uint32_t ruca_u; ++ uint32_t rmca_l; ++ uint32_t rmca_u; ++ uint32_t rbca_l; ++ uint32_t rbca_u; ++ uint32_t rdrp_l; ++ uint32_t rdrp_u; ++ uint32_t rpkt_l; ++ uint32_t rpkt_u; ++ uint32_t rund_l; ++ uint32_t rund_u; ++ uint32_t r64_l; ++ uint32_t r64_u; ++ uint32_t r127_l; ++ uint32_t r127_u; ++ uint32_t r255_l; ++ uint32_t r255_u; ++ uint32_t r511_l; ++ uint32_t r511_u; ++ uint32_t r1023_l; ++ uint32_t r1023_u; ++ uint32_t r1518_l; ++ uint32_t r1518_u; ++ uint32_t r1519x_l; ++ uint32_t r1519x_u; ++ uint32_t rovr_l; ++ uint32_t rovr_u; ++ uint32_t rjbr_l; ++ uint32_t rjbr_u; ++ uint32_t rfrg_l; ++ uint32_t rfrg_u; ++ uint32_t rcnp_l; ++ uint32_t rcnp_u; ++ uint32_t rdrntp_l; ++ uint32_t rdrntp_u; ++ uint32_t res01d0[12]; ++ /* Tx Statistics Counter */ ++ uint32_t teoct_l; ++ uint32_t teoct_u; ++ uint32_t toct_l; ++ uint32_t toct_u; ++ uint32_t res0210[2]; ++ uint32_t txpf_l; ++ uint32_t txpf_u; ++ uint32_t tfrm_l; ++ uint32_t tfrm_u; ++ uint32_t tfcs_l; ++ uint32_t tfcs_u; ++ uint32_t tvlan_l; ++ uint32_t tvlan_u; ++ uint32_t terr_l; ++ uint32_t terr_u; ++ uint32_t tuca_l; ++ uint32_t tuca_u; ++ uint32_t tmca_l; ++ uint32_t tmca_u; ++ uint32_t tbca_l; ++ uint32_t tbca_u; ++ uint32_t res0258[2]; ++ uint32_t tpkt_l; ++ uint32_t tpkt_u; ++ uint32_t tund_l; ++ uint32_t tund_u; ++ uint32_t t64_l; ++ uint32_t t64_u; ++ uint32_t t127_l; ++ uint32_t t127_u; ++ uint32_t t255_l; ++ uint32_t t255_u; ++ uint32_t t511_l; ++ uint32_t t511_u; ++ uint32_t t1023_l; ++ uint32_t t1023_u; ++ uint32_t t1518_l; ++ uint32_t t1518_u; ++ uint32_t t1519x_l; ++ uint32_t t1519x_u; ++ uint32_t res02a8[6]; ++ uint32_t tcnp_l; ++ uint32_t tcnp_u; ++ uint32_t res02c8[14]; ++ /* Line Interface Control */ ++ uint32_t if_mode; /* 0x300 Interface Mode Control */ ++ uint32_t if_status; /* 0x304 Interface Status */ ++ uint32_t res0308[14]; ++ /* HiGig/2 */ ++ uint32_t hg_config; /* 0x340 Control and cfg */ ++ uint32_t res0344[3]; ++ uint32_t hg_pause_quanta; /* 0x350 Pause quanta */ ++ uint32_t res0354[3]; ++ uint32_t hg_pause_thresh; /* 0x360 Pause quanta threshold */ ++ uint32_t res0364[3]; ++ uint32_t hgrx_pause_status; /* 0x370 Receive pause status */ ++ uint32_t hg_fifos_status; /* 0x374 fifos status */ ++ uint32_t rhm; /* 0x378 rx messages counter */ ++ uint32_t thm; /* 0x37C tx messages counter */ ++}; ++ ++struct memac_cfg { ++ bool reset_on_init; ++ bool rx_error_discard; ++ bool pause_ignore; ++ bool pause_forward_enable; ++ bool no_length_check_enable; ++ bool cmd_frame_enable; ++ bool send_idle_enable; ++ bool wan_mode_enable; ++ bool promiscuous_mode_enable; ++ bool tx_addr_ins_enable; ++ bool loopback_enable; ++ bool lgth_check_nostdr; ++ bool time_stamp_enable; ++ bool pad_enable; ++ bool phy_tx_ena_on; ++ bool rx_sfd_any; ++ bool rx_pbl_fwd; ++ bool tx_pbl_fwd; ++ bool debug_mode; ++ uint16_t max_frame_length; ++ uint16_t pause_quanta; ++ uint32_t tx_ipg_length; ++}; ++ ++/** ++ * memac_defconfig() - Get default MEMAC configuration ++ * @cfg: pointer to configuration structure. ++ * ++ * Call this function to obtain a default set of configuration values for ++ * initializing MEMAC. The user can overwrite any of the values before calling ++ * memac_init(), if specific configuration needs to be applied. ++ */ ++void memac_defconfig(struct memac_cfg *cfg); ++void memac_set_promiscuous(struct memac_regs *regs, bool val); ++void memac_hardware_add_addr_in_paddr(struct memac_regs *regs, ++ uint8_t *adr, ++ uint8_t paddr_num); ++void memac_hardware_clear_addr_in_paddr(struct memac_regs *regs, ++ uint8_t paddr_num); ++void memac_enable(struct memac_regs *regs, bool apply_rx, bool apply_tx); ++void memac_disable(struct memac_regs *regs, bool apply_rx, bool apply_tx); ++uint64_t memac_get_counter(struct memac_regs *regs, ++ enum memac_counters reg_name); ++void memac_set_tx_pause_frames(struct memac_regs *regs, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime); ++uint16_t memac_get_max_frame_length(struct memac_regs *regs); ++void memac_init(struct memac_regs *regs, ++ struct memac_cfg *cfg, ++ enum enet_interface enet_interface, ++ enum enet_speed enet_speed, ++ uint32_t exceptions); ++void memac_set_exception(struct memac_regs *regs, uint32_t val, bool enable); ++void memac_reset_counter(struct memac_regs *regs); ++void memac_reset(struct memac_regs *regs); ++void memac_set_hash_table(struct memac_regs *regs, uint32_t val); ++void memac_set_rx_ignore_pause_frames(struct memac_regs *regs,bool enable); ++void memac_set_loopback(struct memac_regs *regs, bool enable); ++void memac_reset_counter(struct memac_regs *regs); ++uint32_t memac_get_event(struct memac_regs *regs, uint32_t ev_mask); ++void memac_ack_event(struct memac_regs *regs, uint32_t ev_mask); ++uint32_t memac_get_interrupt_mask(struct memac_regs *regs); ++ ++ ++#endif /*__FSL_FMAN_MEMAC_H*/ +diff --git a/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_prs.h b/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_prs.h +new file mode 100644 +index 0000000..30d2ecf +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_prs.h +@@ -0,0 +1,101 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __FSL_FMAN_PRS_H ++#define __FSL_FMAN_PRS_H ++ ++#include "common/general.h" ++ ++#define FM_PCD_EX_PRS_DOUBLE_ECC 0x02000000 ++#define FM_PCD_EX_PRS_SINGLE_ECC 0x01000000 ++ ++#define FM_PCD_PRS_PPSC_ALL_PORTS 0xffff0000 ++#define FM_PCD_PRS_RPIMAC_EN 0x00000001 ++#define FM_PCD_PRS_PORT_IDLE_STS 0xffff0000 ++#define FM_PCD_PRS_SINGLE_ECC 0x00004000 ++#define FM_PCD_PRS_DOUBLE_ECC 0x00004000 ++#define PRS_MAX_CYCLE_LIMIT 8191 ++ ++#define DEFAULT_MAX_PRS_CYC_LIM 0 ++ ++struct fman_prs_regs { ++ uint32_t fmpr_rpclim; ++ uint32_t fmpr_rpimac; ++ uint32_t pmeec; ++ uint32_t res00c[5]; ++ uint32_t fmpr_pevr; ++ uint32_t fmpr_pever; ++ uint32_t res028; ++ uint32_t fmpr_perr; ++ uint32_t fmpr_perer; ++ uint32_t res034; ++ uint32_t res038[10]; ++ uint32_t fmpr_ppsc; ++ uint32_t res064; ++ uint32_t fmpr_pds; ++ uint32_t fmpr_l2rrs; ++ uint32_t fmpr_l3rrs; ++ uint32_t fmpr_l4rrs; ++ uint32_t fmpr_srrs; ++ uint32_t fmpr_l2rres; ++ uint32_t fmpr_l3rres; ++ uint32_t fmpr_l4rres; ++ uint32_t fmpr_srres; ++ uint32_t fmpr_spcs; ++ uint32_t fmpr_spscs; ++ uint32_t fmpr_hxscs; ++ uint32_t fmpr_mrcs; ++ uint32_t fmpr_mwcs; ++ uint32_t fmpr_mrscs; ++ uint32_t fmpr_mwscs; ++ uint32_t fmpr_fcscs; ++}; ++ ++struct fman_prs_cfg { ++ uint32_t port_id_stat; ++ uint16_t max_prs_cyc_lim; ++ uint32_t prs_exceptions; ++}; ++ ++uint32_t fman_prs_get_err_event(struct fman_prs_regs *regs, uint32_t ev_mask); ++uint32_t fman_prs_get_err_ev_mask(struct fman_prs_regs *regs); ++void fman_prs_ack_err_event(struct fman_prs_regs *regs, uint32_t event); ++uint32_t fman_prs_get_expt_event(struct fman_prs_regs *regs, uint32_t ev_mask); ++uint32_t fman_prs_get_expt_ev_mask(struct fman_prs_regs *regs); ++void fman_prs_ack_expt_event(struct fman_prs_regs *regs, uint32_t event); ++void fman_prs_defconfig(struct fman_prs_cfg *cfg); ++int fman_prs_init(struct fman_prs_regs *regs, struct fman_prs_cfg *cfg); ++void fman_prs_enable(struct fman_prs_regs *regs); ++void fman_prs_disable(struct fman_prs_regs *regs); ++void fman_prs_set_stst_port_msk(struct fman_prs_regs *regs, uint32_t pid_msk); ++void fman_prs_set_stst(struct fman_prs_regs *regs, bool enable); ++#endif /* __FSL_FMAN_PRS_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_tgec.h b/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_tgec.h +new file mode 100644 +index 0000000..2505888 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/flib/fsl_fman_tgec.h +@@ -0,0 +1,472 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __FSL_FMAN_TGEC_H ++#define __FSL_FMAN_TGEC_H ++ ++#include "common/general.h" ++#include "fsl_enet.h" ++ ++ ++/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */ ++#define TX_IPG_LENGTH_MASK 0x000003ff ++ ++enum tgec_counters { ++ E_TGEC_COUNTER_R64, ++ E_TGEC_COUNTER_R127, ++ E_TGEC_COUNTER_R255, ++ E_TGEC_COUNTER_R511, ++ E_TGEC_COUNTER_R1023, ++ E_TGEC_COUNTER_R1518, ++ E_TGEC_COUNTER_R1519X, ++ E_TGEC_COUNTER_TRFRG, ++ E_TGEC_COUNTER_TRJBR, ++ E_TGEC_COUNTER_RDRP, ++ E_TGEC_COUNTER_RALN, ++ E_TGEC_COUNTER_TRUND, ++ E_TGEC_COUNTER_TROVR, ++ E_TGEC_COUNTER_RXPF, ++ E_TGEC_COUNTER_TXPF, ++ E_TGEC_COUNTER_ROCT, ++ E_TGEC_COUNTER_RMCA, ++ E_TGEC_COUNTER_RBCA, ++ E_TGEC_COUNTER_RPKT, ++ E_TGEC_COUNTER_RUCA, ++ E_TGEC_COUNTER_RERR, ++ E_TGEC_COUNTER_TOCT, ++ E_TGEC_COUNTER_TMCA, ++ E_TGEC_COUNTER_TBCA, ++ E_TGEC_COUNTER_TUCA, ++ E_TGEC_COUNTER_TERR ++}; ++ ++/* Command and Configuration Register (COMMAND_CONFIG) */ ++#define CMD_CFG_EN_TIMESTAMP 0x00100000 ++#define CMD_CFG_TX_ADDR_INS_SEL 0x00080000 ++#define CMD_CFG_NO_LEN_CHK 0x00020000 ++#define CMD_CFG_SEND_IDLE 0x00010000 ++#define CMD_CFG_RX_ER_DISC 0x00004000 ++#define CMD_CFG_CMD_FRM_EN 0x00002000 ++#define CMD_CFG_STAT_CLR 0x00001000 ++#define CMD_CFG_LOOPBACK_EN 0x00000400 ++#define CMD_CFG_TX_ADDR_INS 0x00000200 ++#define CMD_CFG_PAUSE_IGNORE 0x00000100 ++#define CMD_CFG_PAUSE_FWD 0x00000080 ++#define CMD_CFG_PROMIS_EN 0x00000010 ++#define CMD_CFG_WAN_MODE 0x00000008 ++#define CMD_CFG_RX_EN 0x00000002 ++#define CMD_CFG_TX_EN 0x00000001 ++ ++/* Interrupt Mask Register (IMASK) */ ++#define TGEC_IMASK_MDIO_SCAN_EVENT 0x00010000 ++#define TGEC_IMASK_MDIO_CMD_CMPL 0x00008000 ++#define TGEC_IMASK_REM_FAULT 0x00004000 ++#define TGEC_IMASK_LOC_FAULT 0x00002000 ++#define TGEC_IMASK_TX_ECC_ER 0x00001000 ++#define TGEC_IMASK_TX_FIFO_UNFL 0x00000800 ++#define TGEC_IMASK_TX_FIFO_OVFL 0x00000400 ++#define TGEC_IMASK_TX_ER 0x00000200 ++#define TGEC_IMASK_RX_FIFO_OVFL 0x00000100 ++#define TGEC_IMASK_RX_ECC_ER 0x00000080 ++#define TGEC_IMASK_RX_JAB_FRM 0x00000040 ++#define TGEC_IMASK_RX_OVRSZ_FRM 0x00000020 ++#define TGEC_IMASK_RX_RUNT_FRM 0x00000010 ++#define TGEC_IMASK_RX_FRAG_FRM 0x00000008 ++#define TGEC_IMASK_RX_LEN_ER 0x00000004 ++#define TGEC_IMASK_RX_CRC_ER 0x00000002 ++#define TGEC_IMASK_RX_ALIGN_ER 0x00000001 ++ ++#define EVENTS_MASK \ ++ ((uint32_t)(TGEC_IMASK_MDIO_SCAN_EVENT | \ ++ TGEC_IMASK_MDIO_CMD_CMPL | \ ++ TGEC_IMASK_REM_FAULT | \ ++ TGEC_IMASK_LOC_FAULT | \ ++ TGEC_IMASK_TX_ECC_ER | \ ++ TGEC_IMASK_TX_FIFO_UNFL | \ ++ TGEC_IMASK_TX_FIFO_OVFL | \ ++ TGEC_IMASK_TX_ER | \ ++ TGEC_IMASK_RX_FIFO_OVFL | \ ++ TGEC_IMASK_RX_ECC_ER | \ ++ TGEC_IMASK_RX_JAB_FRM | \ ++ TGEC_IMASK_RX_OVRSZ_FRM | \ ++ TGEC_IMASK_RX_RUNT_FRM | \ ++ TGEC_IMASK_RX_FRAG_FRM | \ ++ TGEC_IMASK_RX_LEN_ER | \ ++ TGEC_IMASK_RX_CRC_ER | \ ++ TGEC_IMASK_RX_ALIGN_ER)) ++ ++/* Hashtable Control Register (HASHTABLE_CTRL) */ ++#define TGEC_HASH_MCAST_SHIFT 23 ++#define TGEC_HASH_MCAST_EN 0x00000200 ++#define TGEC_HASH_ADR_MSK 0x000001ff ++ ++#define DEFAULT_WAN_MODE_ENABLE FALSE ++#define DEFAULT_PROMISCUOUS_MODE_ENABLE FALSE ++#define DEFAULT_PAUSE_FORWARD_ENABLE FALSE ++#define DEFAULT_PAUSE_IGNORE FALSE ++#define DEFAULT_TX_ADDR_INS_ENABLE FALSE ++#define DEFAULT_LOOPBACK_ENABLE FALSE ++#define DEFAULT_CMD_FRAME_ENABLE FALSE ++#define DEFAULT_RX_ERROR_DISCARD FALSE ++#define DEFAULT_SEND_IDLE_ENABLE FALSE ++#define DEFAULT_NO_LENGTH_CHECK_ENABLE TRUE ++#define DEFAULT_LGTH_CHECK_NOSTDR FALSE ++#define DEFAULT_TIME_STAMP_ENABLE FALSE ++#define DEFAULT_TX_IPG_LENGTH 12 ++#define DEFAULT_MAX_FRAME_LENGTH 0x600 ++#define DEFAULT_PAUSE_QUANT 0xf000 ++ ++/* ++ * 10G memory map ++ */ ++struct tgec_regs { ++ uint32_t tgec_id; /* 0x000 Controller ID */ ++ uint32_t reserved001[1]; /* 0x004 */ ++ uint32_t command_config; /* 0x008 Control and configuration */ ++ uint32_t mac_addr_0; /* 0x00c Lower 32 bits of the MAC adr */ ++ uint32_t mac_addr_1; /* 0x010 Upper 16 bits of the MAC adr */ ++ uint32_t maxfrm; /* 0x014 Maximum frame length */ ++ uint32_t pause_quant; /* 0x018 Pause quanta */ ++ uint32_t rx_fifo_sections; /* 0x01c */ ++ uint32_t tx_fifo_sections; /* 0x020 */ ++ uint32_t rx_fifo_almost_f_e; /* 0x024 */ ++ uint32_t tx_fifo_almost_f_e; /* 0x028 */ ++ uint32_t hashtable_ctrl; /* 0x02c Hash table control*/ ++ uint32_t mdio_cfg_status; /* 0x030 */ ++ uint32_t mdio_command; /* 0x034 */ ++ uint32_t mdio_data; /* 0x038 */ ++ uint32_t mdio_regaddr; /* 0x03c */ ++ uint32_t status; /* 0x040 */ ++ uint32_t tx_ipg_len; /* 0x044 Transmitter inter-packet-gap */ ++ uint32_t mac_addr_2; /* 0x048 Lower 32 bits of 2nd MAC adr */ ++ uint32_t mac_addr_3; /* 0x04c Upper 16 bits of 2nd MAC adr */ ++ uint32_t rx_fifo_ptr_rd; /* 0x050 */ ++ uint32_t rx_fifo_ptr_wr; /* 0x054 */ ++ uint32_t tx_fifo_ptr_rd; /* 0x058 */ ++ uint32_t tx_fifo_ptr_wr; /* 0x05c */ ++ uint32_t imask; /* 0x060 Interrupt mask */ ++ uint32_t ievent; /* 0x064 Interrupt event */ ++ uint32_t udp_port; /* 0x068 Defines a UDP Port number */ ++ uint32_t type_1588v2; /* 0x06c Type field for 1588v2 */ ++ uint32_t reserved070[4]; /* 0x070 */ ++ /*10Ge Statistics Counter */ ++ uint32_t tfrm_u; /* 80 aFramesTransmittedOK */ ++ uint32_t tfrm_l; /* 84 aFramesTransmittedOK */ ++ uint32_t rfrm_u; /* 88 aFramesReceivedOK */ ++ uint32_t rfrm_l; /* 8c aFramesReceivedOK */ ++ uint32_t rfcs_u; /* 90 aFrameCheckSequenceErrors */ ++ uint32_t rfcs_l; /* 94 aFrameCheckSequenceErrors */ ++ uint32_t raln_u; /* 98 aAlignmentErrors */ ++ uint32_t raln_l; /* 9c aAlignmentErrors */ ++ uint32_t txpf_u; /* A0 aPAUSEMACCtrlFramesTransmitted */ ++ uint32_t txpf_l; /* A4 aPAUSEMACCtrlFramesTransmitted */ ++ uint32_t rxpf_u; /* A8 aPAUSEMACCtrlFramesReceived */ ++ uint32_t rxpf_l; /* Ac aPAUSEMACCtrlFramesReceived */ ++ uint32_t rlong_u; /* B0 aFrameTooLongErrors */ ++ uint32_t rlong_l; /* B4 aFrameTooLongErrors */ ++ uint32_t rflr_u; /* B8 aInRangeLengthErrors */ ++ uint32_t rflr_l; /* Bc aInRangeLengthErrors */ ++ uint32_t tvlan_u; /* C0 VLANTransmittedOK */ ++ uint32_t tvlan_l; /* C4 VLANTransmittedOK */ ++ uint32_t rvlan_u; /* C8 VLANReceivedOK */ ++ uint32_t rvlan_l; /* Cc VLANReceivedOK */ ++ uint32_t toct_u; /* D0 ifOutOctets */ ++ uint32_t toct_l; /* D4 ifOutOctets */ ++ uint32_t roct_u; /* D8 ifInOctets */ ++ uint32_t roct_l; /* Dc ifInOctets */ ++ uint32_t ruca_u; /* E0 ifInUcastPkts */ ++ uint32_t ruca_l; /* E4 ifInUcastPkts */ ++ uint32_t rmca_u; /* E8 ifInMulticastPkts */ ++ uint32_t rmca_l; /* Ec ifInMulticastPkts */ ++ uint32_t rbca_u; /* F0 ifInBroadcastPkts */ ++ uint32_t rbca_l; /* F4 ifInBroadcastPkts */ ++ uint32_t terr_u; /* F8 ifOutErrors */ ++ uint32_t terr_l; /* Fc ifOutErrors */ ++ uint32_t reserved100[2]; /* 100-108*/ ++ uint32_t tuca_u; /* 108 ifOutUcastPkts */ ++ uint32_t tuca_l; /* 10c ifOutUcastPkts */ ++ uint32_t tmca_u; /* 110 ifOutMulticastPkts */ ++ uint32_t tmca_l; /* 114 ifOutMulticastPkts */ ++ uint32_t tbca_u; /* 118 ifOutBroadcastPkts */ ++ uint32_t tbca_l; /* 11c ifOutBroadcastPkts */ ++ uint32_t rdrp_u; /* 120 etherStatsDropEvents */ ++ uint32_t rdrp_l; /* 124 etherStatsDropEvents */ ++ uint32_t reoct_u; /* 128 etherStatsOctets */ ++ uint32_t reoct_l; /* 12c etherStatsOctets */ ++ uint32_t rpkt_u; /* 130 etherStatsPkts */ ++ uint32_t rpkt_l; /* 134 etherStatsPkts */ ++ uint32_t trund_u; /* 138 etherStatsUndersizePkts */ ++ uint32_t trund_l; /* 13c etherStatsUndersizePkts */ ++ uint32_t r64_u; /* 140 etherStatsPkts64Octets */ ++ uint32_t r64_l; /* 144 etherStatsPkts64Octets */ ++ uint32_t r127_u; /* 148 etherStatsPkts65to127Octets */ ++ uint32_t r127_l; /* 14c etherStatsPkts65to127Octets */ ++ uint32_t r255_u; /* 150 etherStatsPkts128to255Octets */ ++ uint32_t r255_l; /* 154 etherStatsPkts128to255Octets */ ++ uint32_t r511_u; /* 158 etherStatsPkts256to511Octets */ ++ uint32_t r511_l; /* 15c etherStatsPkts256to511Octets */ ++ uint32_t r1023_u; /* 160 etherStatsPkts512to1023Octets */ ++ uint32_t r1023_l; /* 164 etherStatsPkts512to1023Octets */ ++ uint32_t r1518_u; /* 168 etherStatsPkts1024to1518Octets */ ++ uint32_t r1518_l; /* 16c etherStatsPkts1024to1518Octets */ ++ uint32_t r1519x_u; /* 170 etherStatsPkts1519toX */ ++ uint32_t r1519x_l; /* 174 etherStatsPkts1519toX */ ++ uint32_t trovr_u; /* 178 etherStatsOversizePkts */ ++ uint32_t trovr_l; /* 17c etherStatsOversizePkts */ ++ uint32_t trjbr_u; /* 180 etherStatsJabbers */ ++ uint32_t trjbr_l; /* 184 etherStatsJabbers */ ++ uint32_t trfrg_u; /* 188 etherStatsFragments */ ++ uint32_t trfrg_l; /* 18C etherStatsFragments */ ++ uint32_t rerr_u; /* 190 ifInErrors */ ++ uint32_t rerr_l; /* 194 ifInErrors */ ++}; ++ ++/** ++ * struct tgec_cfg - TGEC configuration ++ * ++ * @rx_error_discard: Receive Erroneous Frame Discard Enable. When set to 1 ++ * any frame received with an error is discarded in the ++ * Core and not forwarded to the Client interface. ++ * When set to 0 (Reset value), erroneous Frames are ++ * forwarded to the Client interface with ff_rx_err ++ * asserted. ++ * @pause_ignore: Ignore Pause Frame Quanta. If set to 1 received pause ++ * frames are ignored by the MAC. When set to 0 ++ * (Reset value) the transmit process is stopped for the ++ * amount of time specified in the pause quanta received ++ * within a pause frame. ++ * @pause_forward_enable: ++ * Terminate / Forward Pause Frames. If set to 1 pause ++ * frames are forwarded to the user application. When set ++ * to 0 (Reset value) pause frames are terminated and ++ * discarded within the MAC. ++ * @no_length_check_enable: ++ * Payload Length Check Disable. When set to 0 ++ * (Reset value), the Core checks the frame's payload ++ * length with the Frame Length/Type field, when set to 1 ++ * the payload length check is disabled. ++ * @cmd_frame_enable: Enables reception of all command frames. When set to 1 ++ * all Command Frames are accepted, when set to 0 ++ * (Reset Value) only Pause Frames are accepted and all ++ * other Command Frames are rejected. ++ * @send_idle_enable: Force Idle Generation. When set to 1, the MAC ++ * permanently sends XGMII Idle sequences even when faults ++ * are received. ++ * @wan_mode_enable: WAN Mode Enable. Sets WAN mode (1) or LAN mode ++ * (0, default) of operation. ++ * @promiscuous_mode_enable: ++ * Enables MAC promiscuous operation. When set to 1, all ++ * frames are received without any MAC address filtering, ++ * when set to 0 (Reset value) Unicast Frames with a ++ * destination address not matching the Core MAC Address ++ * (MAC Address programmed in Registers MAC_ADDR_0 and ++ * MAC_ADDR_1 or the MAC address programmed in Registers ++ * MAC_ADDR_2 and MAC_ADDR_3) are rejected. ++ * @tx_addr_ins_enable: Set Source MAC Address on Transmit. If set to 1 the ++ * MAC overwrites the source MAC address received from the ++ * Client Interface with one of the MAC addresses. If set ++ * to 0 (Reset value), the source MAC address from the ++ * Client Interface is transmitted unmodified to the line. ++ * @loopback_enable: PHY Interface Loopback. When set to 1, the signal ++ * loop_ena is set to '1', when set to 0 (Reset value) ++ * the signal loop_ena is set to 0. ++ * @lgth_check_nostdr: The Core interprets the Length/Type field differently ++ * depending on the value of this Bit ++ * @time_stamp_enable: This bit selects between enabling and disabling the ++ * IEEE 1588 functionality. 1: IEEE 1588 is enabled ++ * 0: IEEE 1588 is disabled ++ * @max_frame_length: Maximum supported received frame length. ++ * The 10GEC MAC supports reception of any frame size up ++ * to 16,352 bytes (0x3FE0). Typical settings are ++ * 0x05EE (1,518 bytes) for standard frames. ++ * Default setting is 0x0600 (1,536 bytes). ++ * Received frames that exceed this stated maximum ++ * are truncated. ++ * @pause_quant: Pause quanta value used with transmitted pause frames. ++ * Each quanta represents a 512 bit-times. ++ * @tx_ipg_length: Transmit Inter-Packet-Gap (IPG) value. A 6-bit value: ++ * Depending on LAN or WAN mode of operation the value has ++ * the following meaning: - LAN Mode: Number of octets in ++ * steps of 4. Valid values are 8, 12, 16, ... 100. DIC is ++ * fully supported (see 10.6.1 page 49) for any setting. A ++ * default of 12 (reset value) must be set to conform to ++ * IEEE802.3ae. Warning: When set to 8, PCS layers may not ++ * be able to perform clock rate compensation. - WAN Mode: ++ * Stretch factor. Valid values are 4..15. The stretch ++ * factor is calculated as (value+1)*8. A default of 12 ++ * (reset value) must be set to conform to IEEE 802.3ae ++ * (i.e. 13*8=104). A larger value shrinks the IPG ++ * (increasing bandwidth). ++ * ++ * This structure contains basic TGEC configuration and must be passed to ++ * tgec_init() function. A default set of configuration values can be obtained ++ * by calling tgec_defconfig(). ++ */ ++struct tgec_cfg { ++ bool rx_error_discard; ++ bool pause_ignore; ++ bool pause_forward_enable; ++ bool no_length_check_enable; ++ bool cmd_frame_enable; ++ bool send_idle_enable; ++ bool wan_mode_enable; ++ bool promiscuous_mode_enable; ++ bool tx_addr_ins_enable; ++ bool loopback_enable; ++ bool lgth_check_nostdr; ++ bool time_stamp_enable; ++ uint16_t max_frame_length; ++ uint16_t pause_quant; ++ uint32_t tx_ipg_length; ++ bool skip_fman11_workaround; ++}; ++ ++void tgec_set_mac_address(struct tgec_regs *regs, uint8_t *macaddr); ++ ++/** ++ * tgec_reset_stat() - Completely resets all TGEC HW counters ++ * @regs: Pointer to TGEC register block ++ */ ++void tgec_reset_stat(struct tgec_regs *regs); ++ ++/** ++ * tgec_get_counter() - Reads TGEC HW counters ++ * @regs: Pointer to TGEC register block ++ * @reg_name: Counter name according to the appropriate enum ++ * ++ * Returns: Required counter value ++ */ ++ ++uint64_t tgec_get_counter(struct tgec_regs *regs, enum tgec_counters reg_name); ++ ++void tgec_enable(struct tgec_regs *regs, bool apply_rx, bool apply_tx); ++void tgec_disable(struct tgec_regs *regs, bool apply_rx, bool apply_tx); ++void tgec_set_promiscuous(struct tgec_regs *regs, bool val); ++ ++/** ++ * tgec_set_hash_table() - Sets the Hashtable Control Register ++ * @regs: Pointer to TGEC register block ++ * @value: Value to be written in Hashtable Control Register ++ */ ++void tgec_set_hash_table(struct tgec_regs *regs, uint32_t value); ++ ++/** ++ * tgec_tx_mac_pause() - Sets the Pause Quanta Register ++ * @regs: Pointer to TGEC register block ++ * @pause_time: Pause quanta value used with transmitted pause frames. ++ * Each quanta represents a 512 bit-times ++ */ ++ ++void tgec_tx_mac_pause(struct tgec_regs *regs, uint16_t pause_time); ++ ++/** ++ * tgec_rx_ignore_mac_pause() - Changes the policy WRT pause frames ++ * @regs: Pointer to TGEC register block ++ * @en: Ignore/Respond to pause frame quanta ++ * ++ * Sets the value of PAUSE_IGNORE field in the COMMAND_CONFIG Register ++ * 0 - MAC stops transmit process for the duration specified ++ * in the Pause frame quanta of a received Pause frame. ++ * 1 - MAC ignores received Pause frames. ++ */ ++ ++void tgec_rx_ignore_mac_pause(struct tgec_regs *regs, bool en); ++ ++/** ++ * tgec_enable_1588_time_stamp() - change timestamp functionality ++ * @regs: Pointer to TGEC register block ++ * @en: enable/disable timestamp functionality ++ * ++ * Sets the value of EN_TIMESTAMP field in the COMMAND_CONFIG Register ++ * IEEE 1588 timestamp functionality control: ++ * 0 disabled, 1 enabled ++ */ ++ ++void tgec_enable_1588_time_stamp(struct tgec_regs *regs, bool en); ++ ++uint32_t tgec_get_event(struct tgec_regs *regs, uint32_t ev_mask); ++void tgec_ack_event(struct tgec_regs *regs, uint32_t ev_mask); ++uint32_t tgec_get_interrupt_mask(struct tgec_regs *regs); ++ ++ ++/** ++ * tgec_add_addr_in_paddr() - Sets additional exact match MAC address ++ * @regs: Pointer to TGEC register block ++ * @addr_ptr: Pointer to 6-byte array containing the MAC address ++ * ++ * Sets the additional station MAC address ++ */ ++ ++void tgec_add_addr_in_paddr(struct tgec_regs *regs, uint8_t *addr_ptr); ++void tgec_clear_addr_in_paddr(struct tgec_regs *regs); ++uint32_t tgec_get_revision(struct tgec_regs *regs); ++void tgec_enable_interrupt(struct tgec_regs *regs, uint32_t ev_mask); ++void tgec_disable_interrupt(struct tgec_regs *regs, uint32_t ev_mask); ++ ++/** ++ * tgec_get_max_frame_len() - Returns the maximum frame length value ++ * @regs: Pointer to TGEC register block ++ */ ++ ++uint16_t tgec_get_max_frame_len(struct tgec_regs *regs); ++ ++/** ++ * tgec_defconfig() - Initialize the main tgec configuration parameters ++ * @cfg: Pointer to tgec_cfg structure ++ * ++ * This routine determines the values of the tgec_cfg structure members. ++ * This structure represents the initial parameters which the tgec controller ++ * will be initialized with later when calling the tgec_init function. ++ */ ++ ++void tgec_defconfig(struct tgec_cfg *cfg); ++ ++/** ++ * tgec_init() - Init tgec hardware block ++ * @regs: Pointer to tgec register block ++ * @cfg: tgec configuration data ++ * @exceptions_mask: initial exceptions mask ++ * ++ * This function initializes the tgec controller and applies its ++ * basic configuration. ++ * ++ * Returns: 0 if successful, an error code otherwise. ++ */ ++ ++int tgec_init(struct tgec_regs *regs, struct tgec_cfg *cfg, ++ uint32_t exception_mask); ++ ++ ++void tgec_fm_tx_fifo_corruption_errata_10gmac_a007(struct tgec_regs *regs); ++ ++ ++#endif /* __FSL_FMAN_TGEC_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/integrations/P1023/dpaa_integration_ext.h b/drivers/net/dpa/NetCommSw/inc/integrations/P1023/dpaa_integration_ext.h +new file mode 100644 +index 0000000..9864217 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/integrations/P1023/dpaa_integration_ext.h +@@ -0,0 +1,234 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 dpaa_integration_ext.h ++ ++ @Description P1023 FM external definitions and structures. ++*//***************************************************************************/ ++#ifndef __DPAA_INTEGRATION_EXT_H ++#define __DPAA_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++ ++ ++#define DPAA_VERSION 10 ++ ++typedef enum e_DpaaSwPortal { ++ e_DPAA_SWPORTAL0 = 0, ++ e_DPAA_SWPORTAL1, ++ e_DPAA_SWPORTAL2, ++ e_DPAA_SWPORTAL_DUMMY_LAST ++} e_DpaaSwPortal; ++ ++typedef enum { ++ e_DPAA_DCPORTAL0 = 0, ++ e_DPAA_DCPORTAL2, ++ e_DPAA_DCPORTAL_DUMMY_LAST ++} e_DpaaDcPortal; ++ ++#define DPAA_MAX_NUM_OF_SW_PORTALS e_DPAA_SWPORTAL_DUMMY_LAST ++#define DPAA_MAX_NUM_OF_DC_PORTALS e_DPAA_DCPORTAL_DUMMY_LAST ++ ++/***************************************************************************** ++ QMAN INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define QM_MAX_NUM_OF_POOL_CHANNELS 3 ++#define QM_MAX_NUM_OF_WQ 8 ++#define QM_MAX_NUM_OF_SWP_AS 2 ++#define QM_MAX_NUM_OF_CGS 64 ++#define QM_MAX_NUM_OF_FQIDS (16*MEGABYTE) ++ ++typedef enum { ++ e_QM_FQ_CHANNEL_SWPORTAL0 = 0, ++ e_QM_FQ_CHANNEL_SWPORTAL1, ++ e_QM_FQ_CHANNEL_SWPORTAL2, ++ ++ e_QM_FQ_CHANNEL_POOL1 = 0x21, ++ e_QM_FQ_CHANNEL_POOL2, ++ e_QM_FQ_CHANNEL_POOL3, ++ ++ e_QM_FQ_CHANNEL_FMAN0_SP0 = 0x40, ++ e_QM_FQ_CHANNEL_FMAN0_SP1, ++ e_QM_FQ_CHANNEL_FMAN0_SP2, ++ e_QM_FQ_CHANNEL_FMAN0_SP3, ++ e_QM_FQ_CHANNEL_FMAN0_SP4, ++ e_QM_FQ_CHANNEL_FMAN0_SP5, ++ e_QM_FQ_CHANNEL_FMAN0_SP6, ++ ++ ++ e_QM_FQ_CHANNEL_CAAM = 0x80 ++} e_QmFQChannel; ++ ++/***************************************************************************** ++ BMAN INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define BM_MAX_NUM_OF_POOLS 8 ++ ++/***************************************************************************** ++ SEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define SEC_NUM_OF_DECOS 2 ++#define SEC_ALL_DECOS_MASK 0x00000003 ++#define SEC_RNGB ++#define SEC_NO_ESP_TRAILER_REMOVAL ++ ++/***************************************************************************** ++ FM INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define INTG_MAX_NUM_OF_FM 1 ++ ++/* Ports defines */ ++#define FM_MAX_NUM_OF_1G_RX_PORTS 2 ++#define FM_MAX_NUM_OF_10G_RX_PORTS 0 ++#define FM_MAX_NUM_OF_RX_PORTS (FM_MAX_NUM_OF_10G_RX_PORTS+FM_MAX_NUM_OF_1G_RX_PORTS) ++#define FM_MAX_NUM_OF_1G_TX_PORTS 2 ++#define FM_MAX_NUM_OF_10G_TX_PORTS 0 ++#define FM_MAX_NUM_OF_TX_PORTS (FM_MAX_NUM_OF_10G_TX_PORTS+FM_MAX_NUM_OF_1G_TX_PORTS) ++#define FM_MAX_NUM_OF_OH_PORTS 5 ++#define FM_MAX_NUM_OF_1G_MACS (FM_MAX_NUM_OF_1G_RX_PORTS) ++#define FM_MAX_NUM_OF_10G_MACS (FM_MAX_NUM_OF_10G_RX_PORTS) ++#define FM_MAX_NUM_OF_MACS (FM_MAX_NUM_OF_1G_MACS+FM_MAX_NUM_OF_10G_MACS) ++#define FM_MAX_NUM_OF_MACSECS 1 ++ ++#define FM_MACSEC_SUPPORT ++#define FM_DISABLE_SEC_ERRORS ++ ++#define FM_LOW_END_RESTRICTION /* prevents the use of TX port 1 with OP port 0 */ ++ ++#define FM_PORT_MAX_NUM_OF_EXT_POOLS 4 /**< Number of external BM pools per Rx port */ ++#define FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS 2 /**< Number of Offline parsing port external BM pools per Rx port */ ++#define FM_PORT_NUM_OF_CONGESTION_GRPS 32 /**< Total number of congestion groups in QM */ ++#define FM_MAX_NUM_OF_SUB_PORTALS 7 ++ ++/* Rams defines */ ++#define FM_MURAM_SIZE (64*KILOBYTE) ++#define FM_IRAM_SIZE (32*KILOBYTE) ++#define FM_NUM_OF_CTRL 2 ++ ++/* PCD defines */ ++#define FM_PCD_PLCR_NUM_ENTRIES 32 /**< Total number of policer profiles */ ++#define FM_PCD_KG_NUM_OF_SCHEMES 16 /**< Total number of KG schemes */ ++#define FM_PCD_MAX_NUM_OF_CLS_PLANS 128 /**< Number of classification plan entries. */ ++ ++/* RTC defines */ ++#define FM_RTC_NUM_OF_ALARMS 2 ++#define FM_RTC_NUM_OF_PERIODIC_PULSES 2 ++#define FM_RTC_NUM_OF_EXT_TRIGGERS 2 ++ ++/* QMI defines */ ++#define QMI_MAX_NUM_OF_TNUMS 15 ++ ++/* FPM defines */ ++#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4 ++ ++/* DMA defines */ ++#define DMA_THRESH_MAX_COMMQ 15 ++#define DMA_THRESH_MAX_BUF 7 ++ ++/* BMI defines */ ++#define BMI_MAX_NUM_OF_TASKS 64 ++#define BMI_MAX_NUM_OF_DMAS 16 ++#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE) ++#define PORT_MAX_WEIGHT 4 ++ ++/***************************************************************************** ++ FM MACSEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define NUM_OF_RX_SC 16 ++#define NUM_OF_TX_SC 16 ++ ++#define NUM_OF_SA_PER_RX_SC 2 ++#define NUM_OF_SA_PER_TX_SC 2 ++ ++/**************************************************************************//** ++ @Description Enum for inter-module interrupts registration ++*//***************************************************************************/ ++ ++typedef enum e_FmMacsecEventModules{ ++ e_FM_MACSEC_MOD_SC_TX, ++ e_FM_MACSEC_MOD_DUMMY_LAST ++} e_FmMacsecEventModules; ++ ++typedef enum e_FmMacsecInterModuleEvent { ++ e_FM_MACSEC_EV_SC_TX, ++ e_FM_MACSEC_EV_ERR_SC_TX, ++ e_FM_MACSEC_EV_DUMMY_LAST ++} e_FmMacsecInterModuleEvent; ++ ++#define NUM_OF_INTER_MODULE_EVENTS (NUM_OF_TX_SC * 2) ++ ++#define GET_MACSEC_MODULE_EVENT(mod, id, intrType, event) \ ++ switch(mod){ \ ++ case e_FM_MACSEC_MOD_SC_TX: \ ++ event = (intrType == e_FM_INTR_TYPE_ERR) ? \ ++ e_FM_MACSEC_EV_ERR_SC_TX: \ ++ e_FM_MACSEC_EV_SC_TX; \ ++ event += (uint8_t)(2 * id);break; \ ++ break; \ ++ default:event = e_FM_MACSEC_EV_DUMMY_LAST; \ ++ break;} ++ ++ ++/* 1023 unique features */ ++#define FM_QMI_NO_ECC_EXCEPTIONS ++#define FM_CSI_CFED_LIMIT ++#define FM_PEDANTIC_DMA ++#define FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++#define FM_FIFO_ALLOCATION_ALG ++#define FM_DEQ_PIPELINE_PARAMS_FOR_OP ++#define FM_HAS_TOTAL_DMAS ++#define FM_KG_NO_IPPID_SUPPORT ++#define FM_NO_GUARANTEED_RESET_VALUES ++#define FM_MAC_RESET ++ ++/* FM erratas */ ++#define FM_RX_PREAM_4_ERRATA_DTSEC_A001 ++#define FM_MAGIC_PACKET_UNRECOGNIZED_ERRATA_DTSEC2 /* No implementation, Out of LLD scope */ ++ ++#define FM_DEBUG_TRACE_FMAN_A004 /* No implementation, Out of LLD scope */ ++#define FM_INT_BUF_LEAK_FMAN_A005 /* No implementation, Out of LLD scope. App must avoid S/G */ ++ ++#define FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 ++ ++/* #define FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ ++ ++/* ++TKT056919 - axi12axi0 can hang if read request follows the single byte write on the very next cycle ++TKT038900 - FM dma lockup occur due to AXI slave protocol violation ++*/ ++#define FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ++ ++ ++#endif /* __DPAA_INTEGRATION_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/integrations/P1023/part_ext.h b/drivers/net/dpa/NetCommSw/inc/integrations/P1023/part_ext.h +new file mode 100644 +index 0000000..6814d5f +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/integrations/P1023/part_ext.h +@@ -0,0 +1,82 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 part_ext.h ++ ++ @Description Definitions for the part (integration) module. ++*//***************************************************************************/ ++ ++#ifndef __PART_EXT_H ++#define __PART_EXT_H ++ ++#include "std_ext.h" ++#include "part_integration_ext.h" ++ ++ ++#if !(defined(MPC8306) || \ ++ defined(MPC8309) || \ ++ defined(MPC834x) || \ ++ defined(MPC836x) || \ ++ defined(MPC832x) || \ ++ defined(MPC837x) || \ ++ defined(MPC8568) || \ ++ defined(MPC8569) || \ ++ defined(P1020) || \ ++ defined(P1021) || \ ++ defined(P1022) || \ ++ defined(P1023) || \ ++ defined(P2020) || \ ++ defined(P3041) || \ ++ defined(P4080) || \ ++ defined(P5020) || \ ++ defined(MSC814x)) ++#error "unable to proceed without chip-definition" ++#endif ++ ++ ++/**************************************************************************//* ++ @Description Part data structure - must be contained in any integration ++ data structure. ++*//***************************************************************************/ ++typedef struct t_Part ++{ ++ uint64_t (* f_GetModuleBase)(t_Handle h_Part, e_ModuleId moduleId); ++ /**< Returns the address of the module's memory map base. */ ++ e_ModuleId (* f_GetModuleIdByBase)(t_Handle h_Part, uint64_t baseAddress); ++ /**< Returns the module's ID according to its memory map base. */ ++} t_Part; ++ ++ ++#endif /* __PART_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/integrations/P1023/part_integration_ext.h b/drivers/net/dpa/NetCommSw/inc/integrations/P1023/part_integration_ext.h +new file mode 100644 +index 0000000..e838283 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/integrations/P1023/part_integration_ext.h +@@ -0,0 +1,635 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 part_integration_ext.h ++ ++ @Description P1023 external definitions and structures. ++*//***************************************************************************/ ++#ifndef __PART_INTEGRATION_EXT_H ++#define __PART_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++#include "dpaa_integration_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group 1023_chip_id P1023 Application Programming Interface ++ ++ @Description P1023 Chip functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++#define INTG_MAX_NUM_OF_CORES 2 ++ ++ ++/**************************************************************************//** ++ @Description Module types. ++*//***************************************************************************/ ++typedef enum e_ModuleId ++{ ++ e_MODULE_ID_LAW, /**< Local Access module */ ++ e_MODULE_ID_ECM, /**< e500 Coherency Module */ ++ e_MODULE_ID_DDR, /**< DDR memory controller */ ++ e_MODULE_ID_I2C_1, /**< I2C 1 */ ++ e_MODULE_ID_I2C_2, /**< I2C 1 */ ++ e_MODULE_ID_DUART_1, /**< DUART module 1 */ ++ e_MODULE_ID_DUART_2, /**< DUART module 2 */ ++ e_MODULE_ID_LBC, /**< Local bus memory controller module */ ++ e_MODULE_ID_PCIE_1, /**< PCI Express 1 controller module */ ++ e_MODULE_ID_PCIE_ATMU_1, /**< PCI 1 ATMU Window */ ++ e_MODULE_ID_PCIE_2, /**< PCI Express 2 controller module */ ++ e_MODULE_ID_PCIE_ATMU_2, /**< PCI 2 ATMU Window */ ++ e_MODULE_ID_PCIE_3, /**< PCI Express 3 controller module */ ++ e_MODULE_ID_PCIE_ATMU_3, /**< PCI 3 ATMU Window */ ++ e_MODULE_ID_MSI, /**< MSI registers */ ++ e_MODULE_ID_L2_SRAM, /**< L2/SRAM Memory-Mapped controller module */ ++ e_MODULE_ID_DMA_1, /**< DMA controller 1 */ ++ e_MODULE_ID_DMA_2, /**< DMA controller 2 */ ++ e_MODULE_ID_EPIC, /**< Programmable interrupt controller */ ++ e_MODULE_ID_ESPI, /**< ESPI module */ ++ e_MODULE_ID_GPIO, /**< General Purpose I/O */ ++ e_MODULE_ID_SEC_GEN, /**< SEC 4.0 General registers */ ++ e_MODULE_ID_SEC_QI, /**< SEC 4.0 QI registers */ ++ e_MODULE_ID_SEC_JQ0, /**< SEC 4.0 JQ-0 registers */ ++ e_MODULE_ID_SEC_JQ1, /**< SEC 4.0 JQ-1 registers */ ++ e_MODULE_ID_SEC_JQ2, /**< SEC 4.0 JQ-2 registers */ ++ e_MODULE_ID_SEC_JQ3, /**< SEC 4.0 JQ-3 registers */ ++ e_MODULE_ID_SEC_RTIC, /**< SEC 4.0 RTIC registers */ ++ e_MODULE_ID_SEC_DECO0_CCB0, /**< SEC 4.0 DECO-0/CCB-0 registers */ ++ e_MODULE_ID_SEC_DECO1_CCB1, /**< SEC 4.0 DECO-1/CCB-1 registers */ ++ e_MODULE_ID_SEC_DECO2_CCB2, /**< SEC 4.0 DECO-2/CCB-2 registers */ ++ e_MODULE_ID_SEC_DECO3_CCB3, /**< SEC 4.0 DECO-3/CCB-3 registers */ ++ e_MODULE_ID_SEC_DECO4_CCB4, /**< SEC 4.0 DECO-4/CCB-4 registers */ ++ e_MODULE_ID_USB_DR_1, /**< USB 2.0 module 1 */ ++ e_MODULE_ID_USB_DR_2, /**< USB 2.0 module 2 */ ++ e_MODULE_ID_ETSEC_MII_MNG, /**< MII MNG registers */ ++ e_MODULE_ID_ETSEC_1, /**< ETSEC module 1 */ ++ e_MODULE_ID_ETSEC_2, /**< ETSEC module 2 */ ++ e_MODULE_ID_GUTS, /**< Serial DMA */ ++ e_MODULE_ID_PM, /**< Performance Monitor module */ ++ e_MODULE_ID_QM, /**< Queue manager module */ ++ e_MODULE_ID_BM, /**< Buffer manager module */ ++ e_MODULE_ID_QM_CE_PORTAL, ++ e_MODULE_ID_QM_CI_PORTAL, ++ e_MODULE_ID_BM_CE_PORTAL, ++ e_MODULE_ID_BM_CI_PORTAL, ++ e_MODULE_ID_FM, /**< Frame manager #1 module */ ++ e_MODULE_ID_FM_RTC, /**< FM Real-Time-Clock */ ++ e_MODULE_ID_FM_MURAM, /**< FM Multi-User-RAM */ ++ e_MODULE_ID_FM_BMI, /**< FM BMI block */ ++ e_MODULE_ID_FM_QMI, /**< FM QMI block */ ++ e_MODULE_ID_FM_PRS, /**< FM parser block */ ++ e_MODULE_ID_FM_PORT_HO0, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO1, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO2, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO3, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO4, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_1GRx0, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx1, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx0, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx1, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PLCR, /**< FM Policer */ ++ e_MODULE_ID_FM_KG, /**< FM Keygen */ ++ e_MODULE_ID_FM_DMA, /**< FM DMA */ ++ e_MODULE_ID_FM_FPM, /**< FM FPM */ ++ e_MODULE_ID_FM_IRAM, /**< FM Instruction-RAM */ ++ e_MODULE_ID_FM_1GMDIO0, /**< FM 1G MDIO MAC 0*/ ++ e_MODULE_ID_FM_1GMDIO1, /**< FM 1G MDIO MAC 1*/ ++ e_MODULE_ID_FM_PRS_IRAM, /**< FM SW-parser Instruction-RAM */ ++ e_MODULE_ID_FM_RISC0, /**< FM risc #0 */ ++ e_MODULE_ID_FM_RISC1, /**< FM risc #1 */ ++ e_MODULE_ID_FM_1GMAC0, /**< FM 1G MAC #0 */ ++ e_MODULE_ID_FM_1GMAC1, /**< FM 1G MAC #1 */ ++ e_MODULE_ID_FM_MACSEC, /**< FM MACSEC */ ++ ++ e_MODULE_ID_DUMMY_LAST ++} e_ModuleId; ++ ++#define NUM_OF_MODULES e_MODULE_ID_DUMMY_LAST ++ ++ ++#define P1023_OFFSET_LAW 0x00000C08 ++#define P1023_OFFSET_ECM 0x00001000 ++#define P1023_OFFSET_DDR 0x00002000 ++#define P1023_OFFSET_I2C1 0x00003000 ++#define P1023_OFFSET_I2C2 0x00003100 ++#define P1023_OFFSET_DUART1 0x00004500 ++#define P1023_OFFSET_DUART2 0x00004600 ++#define P1023_OFFSET_LBC 0x00005000 ++#define P1023_OFFSET_ESPI 0x00007000 ++#define P1023_OFFSET_PCIE2 0x00009000 ++#define P1023_OFFSET_PCIE2_ATMU 0x00009C00 ++#define P1023_OFFSET_PCIE1 0x0000A000 ++#define P1023_OFFSET_PCIE1_ATMU 0x0000AC00 ++#define P1023_OFFSET_PCIE3 0x0000B000 ++#define P1023_OFFSET_PCIE3_ATMU 0x0000BC00 ++#define P1023_OFFSET_DMA2 0x0000C100 ++#define P1023_OFFSET_GPIO 0x0000F000 ++#define P1023_OFFSET_L2_SRAM 0x00020000 ++#define P1023_OFFSET_DMA1 0x00021100 ++#define P1023_OFFSET_USB1 0x00022000 ++#define P1023_OFFSET_SEC_GEN 0x00030000 ++#define P1023_OFFSET_SEC_JQ0 0x00031000 ++#define P1023_OFFSET_SEC_JQ1 0x00032000 ++#define P1023_OFFSET_SEC_JQ2 0x00033000 ++#define P1023_OFFSET_SEC_JQ3 0x00034000 ++#define P1023_OFFSET_SEC_RTIC 0x00036000 ++#define P1023_OFFSET_SEC_QI 0x00037000 ++#define P1023_OFFSET_SEC_DECO0_CCB0 0x00038000 ++#define P1023_OFFSET_SEC_DECO1_CCB1 0x00039000 ++#define P1023_OFFSET_SEC_DECO2_CCB2 0x0003a000 ++#define P1023_OFFSET_SEC_DECO3_CCB3 0x0003b000 ++#define P1023_OFFSET_SEC_DECO4_CCB4 0x0003c000 ++#define P1023_OFFSET_PIC 0x00040000 ++#define P1023_OFFSET_MSI 0x00041600 ++#define P1023_OFFSET_AXI 0x00081000 ++#define P1023_OFFSET_QM 0x00088000 ++#define P1023_OFFSET_BM 0x0008A000 ++#define P1022_OFFSET_PM 0x000E1000 ++ ++#define P1023_OFFSET_GUTIL 0x000E0000 ++#define P1023_OFFSET_PM 0x000E1000 ++#define P1023_OFFSET_DEBUG 0x000E2000 ++#define P1023_OFFSET_SERDES 0x000E3000 ++#define P1023_OFFSET_ROM 0x000F0000 ++#define P1023_OFFSET_FM 0x00100000 ++ ++#define P1023_OFFSET_FM_MURAM (P1023_OFFSET_FM + 0x00000000) ++#define P1023_OFFSET_FM_BMI (P1023_OFFSET_FM + 0x00080000) ++#define P1023_OFFSET_FM_QMI (P1023_OFFSET_FM + 0x00080400) ++#define P1023_OFFSET_FM_PRS (P1023_OFFSET_FM + 0x00080800) ++#define P1023_OFFSET_FM_PORT_HO0 (P1023_OFFSET_FM + 0x00081000) ++#define P1023_OFFSET_FM_PORT_HO1 (P1023_OFFSET_FM + 0x00082000) ++#define P1023_OFFSET_FM_PORT_HO2 (P1023_OFFSET_FM + 0x00083000) ++#define P1023_OFFSET_FM_PORT_HO3 (P1023_OFFSET_FM + 0x00084000) ++#define P1023_OFFSET_FM_PORT_HO4 (P1023_OFFSET_FM + 0x00085000) ++#define P1023_OFFSET_FM_PORT_1GRX0 (P1023_OFFSET_FM + 0x00088000) ++#define P1023_OFFSET_FM_PORT_1GRX1 (P1023_OFFSET_FM + 0x00089000) ++#define P1023_OFFSET_FM_PORT_1GTX0 (P1023_OFFSET_FM + 0x000A8000) ++#define P1023_OFFSET_FM_PORT_1GTX1 (P1023_OFFSET_FM + 0x000A9000) ++#define P1023_OFFSET_FM_PLCR (P1023_OFFSET_FM + 0x000C0000) ++#define P1023_OFFSET_FM_KG (P1023_OFFSET_FM + 0x000C1000) ++#define P1023_OFFSET_FM_DMA (P1023_OFFSET_FM + 0x000C2000) ++#define P1023_OFFSET_FM_FPM (P1023_OFFSET_FM + 0x000C3000) ++#define P1023_OFFSET_FM_IRAM (P1023_OFFSET_FM + 0x000C4000) ++#define P1023_OFFSET_FM_PRS_IRAM (P1023_OFFSET_FM + 0x000C7000) ++#define P1023_OFFSET_FM_RISC0 (P1023_OFFSET_FM + 0x000D0000) ++#define P1023_OFFSET_FM_RISC1 (P1023_OFFSET_FM + 0x000D0400) ++#define P1023_OFFSET_FM_MACSEC (P1023_OFFSET_FM + 0x000D8000) ++#define P1023_OFFSET_FM_1GMAC0 (P1023_OFFSET_FM + 0x000E0000) ++#define P1023_OFFSET_FM_1GMDIO0 (P1023_OFFSET_FM + 0x000E1120) ++#define P1023_OFFSET_FM_1GMAC1 (P1023_OFFSET_FM + 0x000E2000) ++#define P1023_OFFSET_FM_1GMDIO1 (P1023_OFFSET_FM + 0x000E3000) ++#define P1023_OFFSET_FM_RTC (P1023_OFFSET_FM + 0x000FE000) ++ ++/* Offsets relative to QM or BM portals base */ ++#define P1023_OFFSET_PORTALS_CE_AREA 0x00000000 /* cache enabled area */ ++#define P1023_OFFSET_PORTALS_CI_AREA 0x00100000 /* cache inhibited area */ ++ ++#define P1023_OFFSET_PORTALS_CE(portal) (P1023_OFFSET_PORTALS_CE_AREA + 0x4000 * (portal)) ++#define P1023_OFFSET_PORTALS_CI(portal) (P1023_OFFSET_PORTALS_CI_AREA + 0x1000 * (portal)) ++ ++/**************************************************************************//** ++ @Description Transaction source ID (for memory controllers error reporting). ++*//***************************************************************************/ ++typedef enum e_TransSrc ++{ ++ e_TRANS_SRC_PCIE_2 = 0x01, /**< PCIe port 2 */ ++ e_TRANS_SRC_PCIE_1 = 0x02, /**< PCIe port 1 */ ++ e_TRANS_SRC_PCIE_3 = 0x03, /**< PCIe port 3 */ ++ e_TRANS_SRC_LBC = 0x04, /**< Enhanced local bus */ ++ e_TRANS_SRC_DPAA_SW_PORTALS = 0x0E, /**< DPAA software portals or SRAM */ ++ e_TRANS_SRC_DDR = 0x0F, /**< DDR controller */ ++ e_TRANS_SRC_CORE_INS_FETCH = 0x10, /**< Processor (instruction) */ ++ e_TRANS_SRC_CORE_DATA = 0x11, /**< Processor (data) */ ++ e_TRANS_SRC_DMA = 0x15 /**< DMA */ ++} e_TransSrc; ++ ++/**************************************************************************//** ++ @Description Local Access Window Target interface ID ++*//***************************************************************************/ ++typedef enum e_P1023LawTargetId ++{ ++ e_P1023_LAW_TARGET_PCIE_2 = 0x01, /**< PCI Express 2 target interface */ ++ e_P1023_LAW_TARGET_PCIE_1 = 0x02, /**< PCI Express 1 target interface */ ++ e_P1023_LAW_TARGET_PCIE_3 = 0x03, /**< PCI Express 3 target interface */ ++ e_P1023_LAW_TARGET_LBC = 0x04, /**< Local bus target interface */ ++ e_P1023_LAW_TARGET_QM_PORTALS = 0x0E, /**< Queue Manager Portals */ ++ e_P1023_LAW_TARGET_BM_PORTALS = 0x0E, /**< Buffer Manager Portals */ ++ e_P1023_LAW_TARGET_SRAM = 0x0E, /**< SRAM scratchpad */ ++ e_P1023_LAW_TARGET_DDR = 0x0F, /**< DDR target interface */ ++ e_P1023_LAW_TARGET_NONE = 0xFF /**< Invalid target interface */ ++} e_P1023LawTargetId; ++ ++ ++/**************************************************************************//** ++ @Group 1023_init_grp P1023 Initialization Unit ++ ++ @Description P1023 initialization unit API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Part ID and revision number ++*//***************************************************************************/ ++typedef enum e_P1023DeviceName ++{ ++ e_P1023_REV_INVALID = 0x00000000, /**< Invalid revision */ ++ e_SC1023_REV_1_0 = (int)0x80FC0010, /**< SC1023 rev 1.0 */ ++ e_SC1023_REV_1_1 = (int)0x80FC0011, /**< SC1023 rev 1.1 */ ++ e_P1023_REV_1_0 = (int)0x80FE0010, /**< P1023 rev 1.0 with security */ ++ e_P1023_REV_1_1 = (int)0x80FE0011, /**< P1023 rev 1.1 with security */ ++ e_P1017_REV_1_1 = (int)0x80FF0011, /**< P1017 rev 1.1 with security */ ++ e_P1023_REV_1_0_NO_SEC = (int)0x80F60010, /**< P1023 rev 1.0 without security */ ++ e_P1023_REV_1_1_NO_SEC = (int)0x80F60011, /**< P1023 rev 1.1 without security */ ++ e_P1017_REV_1_1_NO_SEC = (int)0x80F70011 /**< P1017 rev 1.1 without security */ ++} e_P1023DeviceName; ++ ++/**************************************************************************//** ++ @Description structure representing P1023 initialization parameters ++*//***************************************************************************/ ++typedef struct t_P1023Params ++{ ++ uintptr_t ccsrBaseAddress; /**< CCSR base address (virtual) */ ++ uintptr_t bmPortalsBaseAddress; /**< Portals base address (virtual) */ ++ uintptr_t qmPortalsBaseAddress; /**< Portals base address (virtual) */ ++} t_P1023Params; ++ ++/**************************************************************************//** ++ @Function P1023_ConfigAndInit ++ ++ @Description General initiation of the chip registers. ++ ++ @Param[in] p_P1023Params - A pointer to data structure of parameters ++ ++ @Return A handle to the P1023 data structure. ++*//***************************************************************************/ ++t_Handle P1023_ConfigAndInit(t_P1023Params *p_P1023Params); ++ ++/**************************************************************************//** ++ @Function P1023_Free ++ ++ @Description Free all resources. ++ ++ @Param h_P1023 - (In) The handle of the initialized P1023 object. ++ ++ @Return E_OK on success; Other value otherwise. ++*//***************************************************************************/ ++t_Error P1023_Free(t_Handle h_P1023); ++ ++/**************************************************************************//** ++ @Function P1023_GetRevInfo ++ ++ @Description This routine enables access to chip and revision information. ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ ++ @Return Part ID and revision. ++*//***************************************************************************/ ++e_P1023DeviceName P1023_GetRevInfo(uintptr_t gutilBase); ++ ++/**************************************************************************//** ++ @Function P1023_GetE500Factor ++ ++ @Description Returns E500 core clock multiplication factor. ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ @Param[in] coreId - Id of the requested core. ++ @Param[out] p_E500MulFactor - Returns E500 to CCB multification factor. ++ @Param[out] p_E500DivFactor - Returns E500 to CCB division factor. ++ ++ @Return E_OK on success; Other value otherwise. ++* ++*//***************************************************************************/ ++t_Error P1023_GetE500Factor(uintptr_t gutilBase, ++ uint32_t coreId, ++ uint32_t *p_E500MulFactor, ++ uint32_t *p_E500DivFactor); ++ ++/**************************************************************************//** ++ @Function P1023_GetFmFactor ++ ++ @Description returns FM multiplication factors. (This value is returned using ++ two parameters to avoid using float parameter). ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ @Param[out] p_FmMulFactor - returns E500 to CCB multification factor. ++ @Param[out] p_FmDivFactor - returns E500 to CCB division factor. ++ ++ @Return E_OK on success; Other value otherwise. ++*//***************************************************************************/ ++t_Error P1023_GetFmFactor(uintptr_t gutilBase, uint32_t *p_FmMulFactor, uint32_t *p_FmDivFactor); ++ ++/**************************************************************************//** ++ @Function P1023_GetCcbFactor ++ ++ @Description returns system multiplication factor. ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ ++ @Return System multiplication factor. ++*//***************************************************************************/ ++uint32_t P1023_GetCcbFactor(uintptr_t gutilBase); ++ ++#if 0 ++/**************************************************************************//** ++ @Function P1023_GetDdrFactor ++ ++ @Description returns the multiplication factor of the clock in for the DDR clock . ++ Note: assumes the ddr_in_clk is identical to the sys_in_clk ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ @Param p_DdrMulFactor - returns DDR in clk multification factor. ++ @Param p_DdrDivFactor - returns DDR division factor. ++ ++ @Return E_OK on success; Other value otherwise.. ++*//***************************************************************************/ ++t_Error P1023_GetDdrFactor( uintptr_t gutilBase, ++ uint32_t *p_DdrMulFactor, ++ uint32_t *p_DdrDivFactor); ++ ++/**************************************************************************//** ++ @Function P1023_GetDdrType ++ ++ @Description returns the multiplication factor of the clock in for the DDR clock . ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ @Param p_DdrType - (Out) returns DDR type DDR1/DDR2/DDR3. ++ ++ @Return E_OK on success; Other value otherwise. ++*//***************************************************************************/ ++t_Error P1023_GetDdrType(uintptr_t gutilBase, e_DdrType *p_DdrType ); ++#endif ++ ++/** @} */ /* end of 1023_init_grp group */ ++/** @} */ /* end of 1023_grp group */ ++ ++#define CORE_E500V2 ++ ++#if 0 /* using unified values */ ++/***************************************************************************** ++ INTEGRATION-SPECIFIC MODULE CODES ++******************************************************************************/ ++#define MODULE_UNKNOWN 0x00000000 ++#define MODULE_MEM 0x00010000 ++#define MODULE_MM 0x00020000 ++#define MODULE_CORE 0x00030000 ++#define MODULE_P1023 0x00040000 ++#define MODULE_MII 0x00050000 ++#define MODULE_PM 0x00060000 ++#define MODULE_MMU 0x00070000 ++#define MODULE_PIC 0x00080000 ++#define MODULE_L2_CACHE 0x00090000 ++#define MODULE_DUART 0x000a0000 ++#define MODULE_SERDES 0x000b0000 ++#define MODULE_PIO 0x000c0000 ++#define MODULE_QM 0x000d0000 ++#define MODULE_BM 0x000e0000 ++#define MODULE_SEC 0x000f0000 ++#define MODULE_FM 0x00100000 ++#define MODULE_FM_MURAM 0x00110000 ++#define MODULE_FM_PCD 0x00120000 ++#define MODULE_FM_RTC 0x00130000 ++#define MODULE_FM_MAC 0x00140000 ++#define MODULE_FM_PORT 0x00150000 ++#define MODULE_FM_MACSEC 0x00160000 ++#define MODULE_FM_MACSEC_SECY 0x00170000 ++#define MODULE_FM_SP 0x00280000 ++#define MODULE_ECM 0x00190000 ++#define MODULE_DMA 0x001a0000 ++#define MODULE_DDR 0x001b0000 ++#define MODULE_LAW 0x001c0000 ++#define MODULE_LBC 0x001d0000 ++#define MODULE_I2C 0x001e0000 ++#define MODULE_ESPI 0x001f0000 ++#define MODULE_PCI 0x00200000 ++#define MODULE_DPA_PORT 0x00210000 ++#define MODULE_USB 0x00220000 ++#endif /* using unified values */ ++ ++/***************************************************************************** ++ LBC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++/**************************************************************************//** ++ @Group lbc_exception_grp LBC Exception Unit ++ ++ @Description LBC Exception unit API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Anchor lbc_exbm ++ ++ @Collection LBC Errors Bit Mask ++ ++ These errors are reported through the exceptions callback.. ++ The values can be or'ed in any combination in the errors mask ++ parameter of the errors report structure. ++ ++ These errors can also be passed as a bit-mask to ++ LBC_EnableErrorChecking() or LBC_DisableErrorChecking(), ++ for enabling or disabling error checking. ++ @{ ++*//***************************************************************************/ ++#define LBC_ERR_BUS_MONITOR 0x80000000 /**< Bus monitor error */ ++#define LBC_ERR_PARITY_ECC 0x20000000 /**< Parity error for GPCM/UPM */ ++#define LBC_ERR_WRITE_PROTECT 0x04000000 /**< Write protection error */ ++#define LBC_ERR_CHIP_SELECT 0x00080000 /**< Unrecognized chip select */ ++ ++#define LBC_ERR_ALL (LBC_ERR_BUS_MONITOR | LBC_ERR_PARITY_ECC | \ ++ LBC_ERR_WRITE_PROTECT | LBC_ERR_CHIP_SELECT) ++ /**< All possible errors */ ++/* @} */ ++/** @} */ /* end of lbc_exception_grp group */ ++ ++#define LBC_NUM_OF_BANKS 2 ++#define LBC_MAX_CS_SIZE 0x0000000100000000LL ++#define LBC_ATOMIC_OPERATION_SUPPORT ++#define LBC_PARITY_SUPPORT ++#define LBC_ADDRESS_SHIFT_SUPPORT ++#define LBC_ADDRESS_HOLD_TIME_CTRL ++#define LBC_HIGH_CLK_DIVIDERS ++#define LBC_FCM_AVAILABLE ++ ++ ++/***************************************************************************** ++ LAW INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define LAW_ARCH_CCB ++#define LAW_NUM_OF_WINDOWS 12 ++#define LAW_MIN_WINDOW_SIZE 0x0000000000001000LL /**< 4KB */ ++#define LAW_MAX_WINDOW_SIZE 0x0000001000000000LL /**< 32GB */ ++ ++ ++/***************************************************************************** ++ SPI INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define SPI_NUM_OF_CONTROLLERS 1 ++ ++/***************************************************************************** ++ PCI/PCIe INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++ ++#define PCI_MAX_INBOUND_WINDOWS_NUM 4 ++#define PCI_MAX_OUTBOUND_WINDOWS_NUM 5 ++ ++/**************************************************************************//** ++ @Description Target interface of an inbound window ++*//***************************************************************************/ ++typedef enum e_PciTargetInterface ++{ ++ e_PCI_TARGET_PCIE_2 = 0x1, /**< PCI Express target interface 2 */ ++ e_PCI_TARGET_PCIE_1 = 0x2, /**< PCI Express target interface 1 */ ++ e_PCI_TARGET_PCIE_3 = 0x3, /**< PCI Express target interface 3 */ ++ e_PCI_TARGET_LOCAL_MEMORY = 0xF /**< Local Memory (DDR SDRAM, Local Bus, SRAM) target interface */ ++ ++} e_PciTargetInterface; ++ ++/***************************************************************************** ++ DDR INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define DDR_NUM_OF_VALID_CS 2 ++ ++/***************************************************************************** ++ SEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define SEC_ERRATA_STAT_REGS_UNUSABLE ++ ++/***************************************************************************** ++ DMA INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define DMA_NUM_OF_CONTROLLERS 2 ++ ++ ++ ++ ++/***************************************************************************** ++ 1588 INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define PTP_V2 ++ ++/**************************************************************************//** ++ @Function P1023_GetMuxControlReg ++ ++ @Description Returns the value of PMUXCR (Alternate Function Signal Multiplex ++ Control Register) ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ ++ @Return Value of PMUXCR ++*//***************************************************************************/ ++uint32_t P1023_GetMuxControlReg(uintptr_t gutilBase); ++ ++/**************************************************************************//** ++ @Function P1023_SetMuxControlReg ++ ++ @Description Sets the value of PMUXCR (Alternate Function Signal Multiplex ++ Control Register) ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ @Param[in] val - the new value for PMUXCR. ++ ++ @Return None ++*//***************************************************************************/ ++void P1023_SetMuxControlReg(uintptr_t gutilBase, uint32_t val); ++ ++/**************************************************************************//** ++ @Function P1023_GetDeviceDisableStatusRegister ++ ++ @Description Returns the value of DEVDISR (Device Disable Register) ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ ++ @Return Value of DEVDISR ++*//***************************************************************************/ ++uint32_t P1023_GetDeviceDisableStatusRegister(uintptr_t gutilBase); ++ ++/**************************************************************************//** ++ @Function P1023_GetPorDeviceStatusRegister ++ ++ @Description Returns the value of POR Device Status Register ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ ++ @Return POR Device Status Register ++*//***************************************************************************/ ++uint32_t P1023_GetPorDeviceStatusRegister(uintptr_t gutilBase); ++ ++/**************************************************************************//** ++ @Function P1023_GetPorBootModeStatusRegister ++ ++ @Description Returns the value of POR Boot Mode Status Register ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ ++ @Return POR Boot Mode Status Register value ++*//***************************************************************************/ ++uint32_t P1023_GetPorBootModeStatusRegister(uintptr_t gutilBase); ++ ++ ++#define PORDEVSR_SGMII1_DIS 0x10000000 ++#define PORDEVSR_SGMII2_DIS 0x08000000 ++#define PORDEVSR_ECP1 0x02000000 ++#define PORDEVSR_IO_SEL 0x00780000 ++#define PORDEVSR_IO_SEL_SHIFT 19 ++#define PORBMSR_HA 0x00070000 ++#define PORBMSR_HA_SHIFT 16 ++ ++#define DEVDISR_QM_BM 0x80000000 ++#define DEVDISR_FM 0x40000000 ++#define DEVDISR_PCIE1 0x20000000 ++#define DEVDISR_MAC_SEC 0x10000000 ++#define DEVDISR_ELBC 0x08000000 ++#define DEVDISR_PCIE2 0x04000000 ++#define DEVDISR_PCIE3 0x02000000 ++#define DEVDISR_CAAM 0x01000000 ++#define DEVDISR_USB0 0x00800000 ++#define DEVDISR_1588 0x00020000 ++#define DEVDISR_CORE0 0x00008000 ++#define DEVDISR_TB0 0x00004000 ++#define DEVDISR_CORE1 0x00002000 ++#define DEVDISR_TB1 0x00001000 ++#define DEVDISR_DMA1 0x00000400 ++#define DEVDISR_DMA2 0x00000200 ++#define DEVDISR_DDR 0x00000010 ++#define DEVDISR_TSEC1 0x00000080 ++#define DEVDISR_TSEC2 0x00000040 ++#define DEVDISR_SPI 0x00000008 ++#define DEVDISR_I2C 0x00000004 ++#define DEVDISR_DUART 0x00000002 ++ ++ ++#endif /* __PART_INTEGRATION_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/integrations/P3040_P4080_P5020/dpaa_integration_ext.h b/drivers/net/dpa/NetCommSw/inc/integrations/P3040_P4080_P5020/dpaa_integration_ext.h +new file mode 100644 +index 0000000..a655882 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/integrations/P3040_P4080_P5020/dpaa_integration_ext.h +@@ -0,0 +1,274 @@ ++/* Copyright (c) 2009-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 dpaa_integration_ext.h ++ ++ @Description P3040/P4080/P5020 FM external definitions and structures. ++*//***************************************************************************/ ++#ifndef __DPAA_INTEGRATION_EXT_H ++#define __DPAA_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++ ++ ++#define DPAA_VERSION 10 ++ ++/**************************************************************************//** ++ @Description DPAA SW Portals Enumeration. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_DPAA_SWPORTAL0 = 0, ++ e_DPAA_SWPORTAL1, ++ e_DPAA_SWPORTAL2, ++ e_DPAA_SWPORTAL3, ++ e_DPAA_SWPORTAL4, ++ e_DPAA_SWPORTAL5, ++ e_DPAA_SWPORTAL6, ++ e_DPAA_SWPORTAL7, ++ e_DPAA_SWPORTAL8, ++ e_DPAA_SWPORTAL9, ++ e_DPAA_SWPORTAL_DUMMY_LAST ++} e_DpaaSwPortal; ++ ++/**************************************************************************//** ++ @Description DPAA Direct Connect Portals Enumeration. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_DPAA_DCPORTAL0 = 0, ++ e_DPAA_DCPORTAL1, ++ e_DPAA_DCPORTAL2, ++ e_DPAA_DCPORTAL3, ++ e_DPAA_DCPORTAL4, ++ e_DPAA_DCPORTAL_DUMMY_LAST ++} e_DpaaDcPortal; ++ ++#define DPAA_MAX_NUM_OF_SW_PORTALS e_DPAA_SWPORTAL_DUMMY_LAST ++#define DPAA_MAX_NUM_OF_DC_PORTALS e_DPAA_DCPORTAL_DUMMY_LAST ++ ++/***************************************************************************** ++ QMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define QM_MAX_NUM_OF_POOL_CHANNELS 15 /**< Total number of channels, dedicated and pool */ ++#define QM_MAX_NUM_OF_WQ 8 /**< Number of work queues per channel */ ++#define QM_MAX_NUM_OF_SWP_AS 4 ++#define QM_MAX_NUM_OF_CGS 256 /**< Number of congestion groups */ ++#define QM_MAX_NUM_OF_FQIDS (16 * MEGABYTE) /**< FQIDs range - 24 bits */ ++ ++/**************************************************************************//** ++ @Description Work Queue Channel assignments in QMan. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_QM_FQ_CHANNEL_SWPORTAL0 = 0, /**< Dedicated channels serviced by software portals 0 to 9 */ ++ e_QM_FQ_CHANNEL_SWPORTAL1, ++ e_QM_FQ_CHANNEL_SWPORTAL2, ++ e_QM_FQ_CHANNEL_SWPORTAL3, ++ e_QM_FQ_CHANNEL_SWPORTAL4, ++ e_QM_FQ_CHANNEL_SWPORTAL5, ++ e_QM_FQ_CHANNEL_SWPORTAL6, ++ e_QM_FQ_CHANNEL_SWPORTAL7, ++ e_QM_FQ_CHANNEL_SWPORTAL8, ++ e_QM_FQ_CHANNEL_SWPORTAL9, ++ ++ e_QM_FQ_CHANNEL_POOL1 = 0x21, /**< Pool channels that can be serviced by any of the software portals */ ++ e_QM_FQ_CHANNEL_POOL2, ++ e_QM_FQ_CHANNEL_POOL3, ++ e_QM_FQ_CHANNEL_POOL4, ++ e_QM_FQ_CHANNEL_POOL5, ++ e_QM_FQ_CHANNEL_POOL6, ++ e_QM_FQ_CHANNEL_POOL7, ++ e_QM_FQ_CHANNEL_POOL8, ++ e_QM_FQ_CHANNEL_POOL9, ++ e_QM_FQ_CHANNEL_POOL10, ++ e_QM_FQ_CHANNEL_POOL11, ++ e_QM_FQ_CHANNEL_POOL12, ++ e_QM_FQ_CHANNEL_POOL13, ++ e_QM_FQ_CHANNEL_POOL14, ++ e_QM_FQ_CHANNEL_POOL15, ++ ++ e_QM_FQ_CHANNEL_FMAN0_SP0 = 0x40, /**< Dedicated channels serviced by Direct Connect Portal 0: ++ connected to FMan 0; assigned in incrementing order to ++ each sub-portal (SP) in the portal */ ++ e_QM_FQ_CHANNEL_FMAN0_SP1, ++ e_QM_FQ_CHANNEL_FMAN0_SP2, ++ e_QM_FQ_CHANNEL_FMAN0_SP3, ++ e_QM_FQ_CHANNEL_FMAN0_SP4, ++ e_QM_FQ_CHANNEL_FMAN0_SP5, ++ e_QM_FQ_CHANNEL_FMAN0_SP6, ++ e_QM_FQ_CHANNEL_FMAN0_SP7, ++ e_QM_FQ_CHANNEL_FMAN0_SP8, ++ e_QM_FQ_CHANNEL_FMAN0_SP9, ++ e_QM_FQ_CHANNEL_FMAN0_SP10, ++ e_QM_FQ_CHANNEL_FMAN0_SP11, ++/* difference between 5020 and 4080 :) */ ++ e_QM_FQ_CHANNEL_FMAN1_SP0 = 0x60, ++ e_QM_FQ_CHANNEL_FMAN1_SP1, ++ e_QM_FQ_CHANNEL_FMAN1_SP2, ++ e_QM_FQ_CHANNEL_FMAN1_SP3, ++ e_QM_FQ_CHANNEL_FMAN1_SP4, ++ e_QM_FQ_CHANNEL_FMAN1_SP5, ++ e_QM_FQ_CHANNEL_FMAN1_SP6, ++ e_QM_FQ_CHANNEL_FMAN1_SP7, ++ e_QM_FQ_CHANNEL_FMAN1_SP8, ++ e_QM_FQ_CHANNEL_FMAN1_SP9, ++ e_QM_FQ_CHANNEL_FMAN1_SP10, ++ e_QM_FQ_CHANNEL_FMAN1_SP11, ++ ++ e_QM_FQ_CHANNEL_CAAM = 0x80, /**< Dedicated channel serviced by Direct Connect Portal 2: ++ connected to SEC 4.x */ ++ ++ e_QM_FQ_CHANNEL_PME = 0xA0, /**< Dedicated channel serviced by Direct Connect Portal 3: ++ connected to PME */ ++ e_QM_FQ_CHANNEL_RAID = 0xC0 /**< Dedicated channel serviced by Direct Connect Portal 4: ++ connected to RAID */ ++} e_QmFQChannel; ++ ++/***************************************************************************** ++ BMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define BM_MAX_NUM_OF_POOLS 64 /**< Number of buffers pools */ ++ ++ ++/***************************************************************************** ++ FM INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define INTG_MAX_NUM_OF_FM 2 ++ ++/* Ports defines */ ++#define FM_MAX_NUM_OF_1G_MACS 5 ++#define FM_MAX_NUM_OF_10G_MACS 1 ++#define FM_MAX_NUM_OF_MACS (FM_MAX_NUM_OF_1G_MACS + FM_MAX_NUM_OF_10G_MACS) ++#define FM_MAX_NUM_OF_OH_PORTS 7 ++ ++#define FM_MAX_NUM_OF_1G_RX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_RX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_RX_PORTS (FM_MAX_NUM_OF_10G_RX_PORTS + FM_MAX_NUM_OF_1G_RX_PORTS) ++ ++#define FM_MAX_NUM_OF_1G_TX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_TX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_TX_PORTS (FM_MAX_NUM_OF_10G_TX_PORTS + FM_MAX_NUM_OF_1G_TX_PORTS) ++ ++#define FM_PORT_MAX_NUM_OF_EXT_POOLS 8 /**< Number of external BM pools per Rx port */ ++#define FM_PORT_NUM_OF_CONGESTION_GRPS 256 /**< Total number of congestion groups in QM */ ++#define FM_MAX_NUM_OF_SUB_PORTALS 12 ++#define FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS 0 ++ ++/* Rams defines */ ++#define FM_MURAM_SIZE (160*KILOBYTE) ++#define FM_IRAM_SIZE ( 64*KILOBYTE) ++#define FM_NUM_OF_CTRL 2 ++ ++/* PCD defines */ ++#define FM_PCD_PLCR_NUM_ENTRIES 256 /**< Total number of policer profiles */ ++#define FM_PCD_KG_NUM_OF_SCHEMES 32 /**< Total number of KG schemes */ ++#define FM_PCD_MAX_NUM_OF_CLS_PLANS 256 /**< Number of classification plan entries. */ ++#define FM_PCD_PRS_SW_PATCHES_SIZE 0x00000200 /**< Number of bytes saved for patches */ ++#define FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */ ++ ++/* RTC defines */ ++#define FM_RTC_NUM_OF_ALARMS 2 /**< RTC number of alarms */ ++#define FM_RTC_NUM_OF_PERIODIC_PULSES 2 /**< RTC number of periodic pulses */ ++#define FM_RTC_NUM_OF_EXT_TRIGGERS 2 /**< RTC number of external triggers */ ++ ++/* QMI defines */ ++#define QMI_MAX_NUM_OF_TNUMS 64 ++#define QMI_DEF_TNUMS_THRESH 48 ++ ++/* FPM defines */ ++#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4 ++ ++/* DMA defines */ ++#define DMA_THRESH_MAX_COMMQ 31 ++#define DMA_THRESH_MAX_BUF 127 ++ ++/* BMI defines */ ++#define BMI_MAX_NUM_OF_TASKS 128 ++#define BMI_MAX_NUM_OF_DMAS 32 ++#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE) ++#define PORT_MAX_WEIGHT 16 ++ ++ ++#define FM_CHECK_PORT_RESTRICTIONS(__validPorts, __newPortIndx) TRUE ++ ++/* p4080-rev1 unique features */ ++#define QM_CGS_NO_FRAME_MODE ++ ++/* p4080 unique features */ ++#define FM_NO_DISPATCH_RAM_ECC ++#define FM_NO_WATCHDOG ++#define FM_NO_TNUM_AGING ++#define FM_KG_NO_BYPASS_FQID_GEN ++#define FM_KG_NO_BYPASS_PLCR_PROFILE_GEN ++#define FM_NO_BACKUP_POOLS ++#define FM_NO_OP_OBSERVED_POOLS ++#define FM_NO_ADVANCED_RATE_LIMITER ++#define FM_NO_OP_OBSERVED_CGS ++#define FM_HAS_TOTAL_DMAS ++#define FM_KG_NO_IPPID_SUPPORT ++#define FM_NO_GUARANTEED_RESET_VALUES ++#define FM_MAC_RESET ++ ++/* FM erratas */ ++#define FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++#define FM_TX_SHORT_FRAME_BAD_TS_ERRATA_10GMAC_A006 /* No implementation, Out of LLD scope */ ++#define FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 ++#define FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 ++#define FM_TX_INVALID_ECC_ERRATA_10GMAC_A009 /* Out of LLD scope, user may disable ECC exceptions using FM_DisableRamsEcc */ ++#define FM_BAD_VLAN_DETECT_ERRATA_10GMAC_A010 ++ ++#define FM_RX_PREAM_4_ERRATA_DTSEC_A001 ++#define FM_GRS_ERRATA_DTSEC_A002 ++#define FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 ++#define FM_GTS_ERRATA_DTSEC_A004 ++#define FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012 ++#define FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 ++#define FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 ++ ++#define FM_MAGIC_PACKET_UNRECOGNIZED_ERRATA_DTSEC2 /* No implementation, Out of LLD scope */ ++#define FM_TX_LOCKUP_ERRATA_DTSEC6 ++ ++#define FM_HC_DEF_FQID_ONLY_ERRATA_FMAN_A003 /* Implemented by ucode */ ++#define FM_DEBUG_TRACE_FMAN_A004 /* No implementation, Out of LLD scope */ ++ ++#define FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 ++ ++#define FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 ++ ++#define FM_LEN_CHECK_ERRATA_FMAN_SW002 ++ ++#define FM_NO_CTXA_COPY_ERRATA_FMAN_SW001 ++#define FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 ++ ++#endif /* __DPAA_INTEGRATION_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/integrations/P3040_P4080_P5020/part_ext.h b/drivers/net/dpa/NetCommSw/inc/integrations/P3040_P4080_P5020/part_ext.h +new file mode 100644 +index 0000000..512f0ba +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/integrations/P3040_P4080_P5020/part_ext.h +@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 part_ext.h ++ ++ @Description Definitions for the part (integration) module. ++*//***************************************************************************/ ++ ++#ifndef __PART_EXT_H ++#define __PART_EXT_H ++ ++#include "std_ext.h" ++#include "part_integration_ext.h" ++ ++ ++#if !(defined(MPC8306) || \ ++ defined(MPC8309) || \ ++ defined(MPC834x) || \ ++ defined(MPC836x) || \ ++ defined(MPC832x) || \ ++ defined(MPC837x) || \ ++ defined(MPC8568) || \ ++ defined(MPC8569) || \ ++ defined(P1020) || \ ++ defined(P1021) || \ ++ defined(P1022) || \ ++ defined(P1023) || \ ++ defined(P2020) || \ ++ defined(P2040) || \ ++ defined(P3041) || \ ++ defined(P4080) || \ ++ defined(SC4080) || \ ++ defined(P5020) || \ ++ defined(MSC814x)) ++#error "unable to proceed without chip-definition" ++#endif /* !(defined(MPC834x) || ... */ ++ ++ ++/**************************************************************************//* ++ @Description Part data structure - must be contained in any integration ++ data structure. ++*//***************************************************************************/ ++typedef struct t_Part ++{ ++ uintptr_t (* f_GetModuleBase)(t_Handle h_Part, e_ModuleId moduleId); ++ /**< Returns the address of the module's memory map base. */ ++ e_ModuleId (* f_GetModuleIdByBase)(t_Handle h_Part, uintptr_t baseAddress); ++ /**< Returns the module's ID according to its memory map base. */ ++} t_Part; ++ ++ ++#endif /* __PART_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/integrations/P3040_P4080_P5020/part_integration_ext.h b/drivers/net/dpa/NetCommSw/inc/integrations/P3040_P4080_P5020/part_integration_ext.h +new file mode 100644 +index 0000000..03c59b8 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/integrations/P3040_P4080_P5020/part_integration_ext.h +@@ -0,0 +1,336 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 part_integration_ext.h ++ ++ @Description P3040/P4080/P5020 external definitions and structures. ++*//***************************************************************************/ ++#ifndef __PART_INTEGRATION_EXT_H ++#define __PART_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++#include "dpaa_integration_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group P3040/P4080/P5020_chip_id P5020 Application Programming Interface ++ ++ @Description P3040/P4080/P5020 Chip functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++#define CORE_E500MC ++ ++#define INTG_MAX_NUM_OF_CORES 1 ++ ++ ++/**************************************************************************//** ++ @Description Module types. ++*//***************************************************************************/ ++typedef enum e_ModuleId ++{ ++ e_MODULE_ID_DUART_1 = 0, ++ e_MODULE_ID_DUART_2, ++ e_MODULE_ID_DUART_3, ++ e_MODULE_ID_DUART_4, ++ e_MODULE_ID_LAW, ++ e_MODULE_ID_LBC, ++ e_MODULE_ID_PAMU, ++ e_MODULE_ID_QM, /**< Queue manager module */ ++ e_MODULE_ID_BM, /**< Buffer manager module */ ++ e_MODULE_ID_QM_CE_PORTAL_0, ++ e_MODULE_ID_QM_CI_PORTAL_0, ++ e_MODULE_ID_QM_CE_PORTAL_1, ++ e_MODULE_ID_QM_CI_PORTAL_1, ++ e_MODULE_ID_QM_CE_PORTAL_2, ++ e_MODULE_ID_QM_CI_PORTAL_2, ++ e_MODULE_ID_QM_CE_PORTAL_3, ++ e_MODULE_ID_QM_CI_PORTAL_3, ++ e_MODULE_ID_QM_CE_PORTAL_4, ++ e_MODULE_ID_QM_CI_PORTAL_4, ++ e_MODULE_ID_QM_CE_PORTAL_5, ++ e_MODULE_ID_QM_CI_PORTAL_5, ++ e_MODULE_ID_QM_CE_PORTAL_6, ++ e_MODULE_ID_QM_CI_PORTAL_6, ++ e_MODULE_ID_QM_CE_PORTAL_7, ++ e_MODULE_ID_QM_CI_PORTAL_7, ++ e_MODULE_ID_QM_CE_PORTAL_8, ++ e_MODULE_ID_QM_CI_PORTAL_8, ++ e_MODULE_ID_QM_CE_PORTAL_9, ++ e_MODULE_ID_QM_CI_PORTAL_9, ++ e_MODULE_ID_BM_CE_PORTAL_0, ++ e_MODULE_ID_BM_CI_PORTAL_0, ++ e_MODULE_ID_BM_CE_PORTAL_1, ++ e_MODULE_ID_BM_CI_PORTAL_1, ++ e_MODULE_ID_BM_CE_PORTAL_2, ++ e_MODULE_ID_BM_CI_PORTAL_2, ++ e_MODULE_ID_BM_CE_PORTAL_3, ++ e_MODULE_ID_BM_CI_PORTAL_3, ++ e_MODULE_ID_BM_CE_PORTAL_4, ++ e_MODULE_ID_BM_CI_PORTAL_4, ++ e_MODULE_ID_BM_CE_PORTAL_5, ++ e_MODULE_ID_BM_CI_PORTAL_5, ++ e_MODULE_ID_BM_CE_PORTAL_6, ++ e_MODULE_ID_BM_CI_PORTAL_6, ++ e_MODULE_ID_BM_CE_PORTAL_7, ++ e_MODULE_ID_BM_CI_PORTAL_7, ++ e_MODULE_ID_BM_CE_PORTAL_8, ++ e_MODULE_ID_BM_CI_PORTAL_8, ++ e_MODULE_ID_BM_CE_PORTAL_9, ++ e_MODULE_ID_BM_CI_PORTAL_9, ++ e_MODULE_ID_FM1, /**< Frame manager #1 module */ ++ e_MODULE_ID_FM1_RTC, /**< FM Real-Time-Clock */ ++ e_MODULE_ID_FM1_MURAM, /**< FM Multi-User-RAM */ ++ e_MODULE_ID_FM1_BMI, /**< FM BMI block */ ++ e_MODULE_ID_FM1_QMI, /**< FM QMI block */ ++ e_MODULE_ID_FM1_PRS, /**< FM parser block */ ++ e_MODULE_ID_FM1_PORT_HO0, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_HO1, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_HO2, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_HO3, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_HO4, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_HO5, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_HO6, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_1GRx0, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GRx1, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GRx2, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GRx3, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GRx4, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_10GRx0, /**< FM Rx 10G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GTx0, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GTx1, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GTx2, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GTx3, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GTx4, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_10GTx0, /**< FM Tx 10G MAC port block */ ++ e_MODULE_ID_FM1_PLCR, /**< FM Policer */ ++ e_MODULE_ID_FM1_KG, /**< FM Keygen */ ++ e_MODULE_ID_FM1_DMA, /**< FM DMA */ ++ e_MODULE_ID_FM1_FPM, /**< FM FPM */ ++ e_MODULE_ID_FM1_IRAM, /**< FM Instruction-RAM */ ++ e_MODULE_ID_FM1_1GMDIO0, /**< FM 1G MDIO MAC 0*/ ++ e_MODULE_ID_FM1_1GMDIO1, /**< FM 1G MDIO MAC 1*/ ++ e_MODULE_ID_FM1_1GMDIO2, /**< FM 1G MDIO MAC 2*/ ++ e_MODULE_ID_FM1_1GMDIO3, /**< FM 1G MDIO MAC 3*/ ++ e_MODULE_ID_FM1_10GMDIO, /**< FM 10G MDIO */ ++ e_MODULE_ID_FM1_PRS_IRAM, /**< FM SW-parser Instruction-RAM */ ++ e_MODULE_ID_FM1_1GMAC0, /**< FM 1G MAC #0 */ ++ e_MODULE_ID_FM1_1GMAC1, /**< FM 1G MAC #1 */ ++ e_MODULE_ID_FM1_1GMAC2, /**< FM 1G MAC #2 */ ++ e_MODULE_ID_FM1_1GMAC3, /**< FM 1G MAC #3 */ ++ e_MODULE_ID_FM1_10GMAC0, /**< FM 10G MAC #0 */ ++ ++ e_MODULE_ID_FM2, /**< Frame manager #2 module */ ++ e_MODULE_ID_FM2_RTC, /**< FM Real-Time-Clock */ ++ e_MODULE_ID_FM2_MURAM, /**< FM Multi-User-RAM */ ++ e_MODULE_ID_FM2_BMI, /**< FM BMI block */ ++ e_MODULE_ID_FM2_QMI, /**< FM QMI block */ ++ e_MODULE_ID_FM2_PRS, /**< FM parser block */ ++ e_MODULE_ID_FM2_PORT_HO0, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_HO1, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_HO2, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_HO3, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_HO4, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_HO5, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_HO6, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_1GRx0, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GRx1, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GRx2, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GRx3, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_10GRx0, /**< FM Rx 10G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GTx0, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GTx1, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GTx2, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GTx3, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_10GTx0, /**< FM Tx 10G MAC port block */ ++ e_MODULE_ID_FM2_PLCR, /**< FM Policer */ ++ e_MODULE_ID_FM2_KG, /**< FM Keygen */ ++ e_MODULE_ID_FM2_DMA, /**< FM DMA */ ++ e_MODULE_ID_FM2_FPM, /**< FM FPM */ ++ e_MODULE_ID_FM2_IRAM, /**< FM Instruction-RAM */ ++ e_MODULE_ID_FM2_1GMDIO0, /**< FM 1G MDIO MAC 0*/ ++ e_MODULE_ID_FM2_1GMDIO1, /**< FM 1G MDIO MAC 1*/ ++ e_MODULE_ID_FM2_1GMDIO2, /**< FM 1G MDIO MAC 2*/ ++ e_MODULE_ID_FM2_1GMDIO3, /**< FM 1G MDIO MAC 3*/ ++ e_MODULE_ID_FM2_10GMDIO, /**< FM 10G MDIO */ ++ e_MODULE_ID_FM2_PRS_IRAM, /**< FM SW-parser Instruction-RAM */ ++ e_MODULE_ID_FM2_1GMAC0, /**< FM 1G MAC #0 */ ++ e_MODULE_ID_FM2_1GMAC1, /**< FM 1G MAC #1 */ ++ e_MODULE_ID_FM2_1GMAC2, /**< FM 1G MAC #2 */ ++ e_MODULE_ID_FM2_1GMAC3, /**< FM 1G MAC #3 */ ++ e_MODULE_ID_FM2_10GMAC0, /**< FM 10G MAC #0 */ ++ ++ e_MODULE_ID_SEC_GEN, /**< SEC 4.0 General registers */ ++ e_MODULE_ID_SEC_QI, /**< SEC 4.0 QI registers */ ++ e_MODULE_ID_SEC_JQ0, /**< SEC 4.0 JQ-0 registers */ ++ e_MODULE_ID_SEC_JQ1, /**< SEC 4.0 JQ-1 registers */ ++ e_MODULE_ID_SEC_JQ2, /**< SEC 4.0 JQ-2 registers */ ++ e_MODULE_ID_SEC_JQ3, /**< SEC 4.0 JQ-3 registers */ ++ e_MODULE_ID_SEC_RTIC, /**< SEC 4.0 RTIC registers */ ++ e_MODULE_ID_SEC_DECO0_CCB0, /**< SEC 4.0 DECO-0/CCB-0 registers */ ++ e_MODULE_ID_SEC_DECO1_CCB1, /**< SEC 4.0 DECO-1/CCB-1 registers */ ++ e_MODULE_ID_SEC_DECO2_CCB2, /**< SEC 4.0 DECO-2/CCB-2 registers */ ++ e_MODULE_ID_SEC_DECO3_CCB3, /**< SEC 4.0 DECO-3/CCB-3 registers */ ++ e_MODULE_ID_SEC_DECO4_CCB4, /**< SEC 4.0 DECO-4/CCB-4 registers */ ++ ++ e_MODULE_ID_MPIC, /**< MPIC */ ++ e_MODULE_ID_GPIO, /**< GPIO */ ++ e_MODULE_ID_SERDES, /**< SERDES */ ++ e_MODULE_ID_CPC_1, /**< CoreNet-Platform-Cache 1 */ ++ e_MODULE_ID_CPC_2, /**< CoreNet-Platform-Cache 2 */ ++ ++ e_MODULE_ID_SRIO_PORTS, /**< RapidIO controller */ ++ e_MODULE_ID_SRIO_MU, /**< RapidIO messaging unit module */ ++ ++ e_MODULE_ID_DUMMY_LAST ++} e_ModuleId; ++ ++#define NUM_OF_MODULES e_MODULE_ID_DUMMY_LAST ++ ++#if 0 /* using unified values */ ++/***************************************************************************** ++ INTEGRATION-SPECIFIC MODULE CODES ++******************************************************************************/ ++#define MODULE_UNKNOWN 0x00000000 ++#define MODULE_MEM 0x00010000 ++#define MODULE_MM 0x00020000 ++#define MODULE_CORE 0x00030000 ++#define MODULE_CHIP 0x00040000 ++#define MODULE_PLTFRM 0x00050000 ++#define MODULE_PM 0x00060000 ++#define MODULE_MMU 0x00070000 ++#define MODULE_PIC 0x00080000 ++#define MODULE_CPC 0x00090000 ++#define MODULE_DUART 0x000a0000 ++#define MODULE_SERDES 0x000b0000 ++#define MODULE_PIO 0x000c0000 ++#define MODULE_QM 0x000d0000 ++#define MODULE_BM 0x000e0000 ++#define MODULE_SEC 0x000f0000 ++#define MODULE_LAW 0x00100000 ++#define MODULE_LBC 0x00110000 ++#define MODULE_PAMU 0x00120000 ++#define MODULE_FM 0x00130000 ++#define MODULE_FM_MURAM 0x00140000 ++#define MODULE_FM_PCD 0x00150000 ++#define MODULE_FM_RTC 0x00160000 ++#define MODULE_FM_MAC 0x00170000 ++#define MODULE_FM_PORT 0x00180000 ++#define MODULE_FM_SP 0x00190000 ++#define MODULE_DPA_PORT 0x001a0000 ++#define MODULE_MII 0x001b0000 ++#define MODULE_I2C 0x001c0000 ++#define MODULE_DMA 0x001d0000 ++#define MODULE_DDR 0x001e0000 ++#define MODULE_ESPI 0x001f0000 ++#define MODULE_DPAA_IPSEC 0x00200000 ++#endif /* using unified values */ ++ ++/***************************************************************************** ++ PAMU INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define PAMU_NUM_OF_PARTITIONS 5 ++ ++#define PAMU_PICS_AVICS_ERRATA_PAMU3 ++ ++/***************************************************************************** ++ LAW INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define LAW_NUM_OF_WINDOWS 32 ++#define LAW_MIN_WINDOW_SIZE 0x0000000000001000LL /**< 4KB */ ++#define LAW_MAX_WINDOW_SIZE 0x0000002000000000LL /**< 64GB */ ++ ++ ++/***************************************************************************** ++ LBC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++/**************************************************************************//** ++ @Group lbc_exception_grp LBC Exception Unit ++ ++ @Description LBC Exception unit API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Anchor lbc_exbm ++ ++ @Collection LBC Errors Bit Mask ++ ++ These errors are reported through the exceptions callback.. ++ The values can be or'ed in any combination in the errors mask ++ parameter of the errors report structure. ++ ++ These errors can also be passed as a bit-mask to ++ LBC_EnableErrorChecking() or LBC_DisableErrorChecking(), ++ for enabling or disabling error checking. ++ @{ ++*//***************************************************************************/ ++#define LBC_ERR_BUS_MONITOR 0x80000000 /**< Bus monitor error */ ++#define LBC_ERR_PARITY_ECC 0x20000000 /**< Parity error for GPCM/UPM */ ++#define LBC_ERR_WRITE_PROTECT 0x04000000 /**< Write protection error */ ++#define LBC_ERR_ATOMIC_WRITE 0x00800000 /**< Atomic write error */ ++#define LBC_ERR_ATOMIC_READ 0x00400000 /**< Atomic read error */ ++#define LBC_ERR_CHIP_SELECT 0x00080000 /**< Unrecognized chip select */ ++ ++#define LBC_ERR_ALL (LBC_ERR_BUS_MONITOR | LBC_ERR_PARITY_ECC | \ ++ LBC_ERR_WRITE_PROTECT | LBC_ERR_ATOMIC_WRITE | \ ++ LBC_ERR_ATOMIC_READ | LBC_ERR_CHIP_SELECT) ++ /**< All possible errors */ ++/* @} */ ++/** @} */ /* end of lbc_exception_grp group */ ++ ++#define LBC_INCORRECT_ERROR_REPORT_ERRATA ++ ++#define LBC_NUM_OF_BANKS 8 ++#define LBC_MAX_CS_SIZE 0x0000000100000000LL ++#define LBC_ATOMIC_OPERATION_SUPPORT ++#define LBC_PARITY_SUPPORT ++#define LBC_ADDRESS_HOLD_TIME_CTRL ++#define LBC_HIGH_CLK_DIVIDERS ++#define LBC_FCM_AVAILABLE ++ ++/***************************************************************************** ++ GPIO INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define GPIO_NUM_OF_PORTS 1 /**< Number of ports in GPIO module; ++ Each port contains up to 32 i/O pins. */ ++ ++#define GPIO_VALID_PIN_MASKS \ ++ { /* Port A */ 0xFFFFFFFF } ++ ++#define GPIO_VALID_INTR_MASKS \ ++ { /* Port A */ 0xFFFFFFFF } ++ ++#endif /* __PART_INTEGRATION_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/integrations/T4240/dpaa_integration_ext.h b/drivers/net/dpa/NetCommSw/inc/integrations/T4240/dpaa_integration_ext.h +new file mode 100644 +index 0000000..641d6c8 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/integrations/T4240/dpaa_integration_ext.h +@@ -0,0 +1,274 @@ ++/* ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 dpaa_integration_ext.h ++ ++ @Description T4240 FM external definitions and structures. ++*//***************************************************************************/ ++#ifndef __DPAA_INTEGRATION_EXT_H ++#define __DPAA_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++ ++ ++#define DPAA_VERSION 11 ++ ++/**************************************************************************//** ++ @Description DPAA SW Portals Enumeration. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_DPAA_SWPORTAL0 = 0, ++ e_DPAA_SWPORTAL1, ++ e_DPAA_SWPORTAL2, ++ e_DPAA_SWPORTAL3, ++ e_DPAA_SWPORTAL4, ++ e_DPAA_SWPORTAL5, ++ e_DPAA_SWPORTAL6, ++ e_DPAA_SWPORTAL7, ++ e_DPAA_SWPORTAL8, ++ e_DPAA_SWPORTAL9, ++ e_DPAA_SWPORTAL10, ++ e_DPAA_SWPORTAL11, ++ e_DPAA_SWPORTAL12, ++ e_DPAA_SWPORTAL13, ++ e_DPAA_SWPORTAL14, ++ e_DPAA_SWPORTAL15, ++ e_DPAA_SWPORTAL16, ++ e_DPAA_SWPORTAL17, ++ e_DPAA_SWPORTAL18, ++ e_DPAA_SWPORTAL19, ++ e_DPAA_SWPORTAL20, ++ e_DPAA_SWPORTAL21, ++ e_DPAA_SWPORTAL22, ++ e_DPAA_SWPORTAL23, ++ e_DPAA_SWPORTAL24, ++ e_DPAA_SWPORTAL_DUMMY_LAST ++} e_DpaaSwPortal; ++ ++/**************************************************************************//** ++ @Description DPAA Direct Connect Portals Enumeration. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_DPAA_DCPORTAL0 = 0, ++ e_DPAA_DCPORTAL1, ++ e_DPAA_DCPORTAL2, ++ e_DPAA_DCPORTAL_DUMMY_LAST ++} e_DpaaDcPortal; ++ ++#define DPAA_MAX_NUM_OF_SW_PORTALS e_DPAA_SWPORTAL_DUMMY_LAST ++#define DPAA_MAX_NUM_OF_DC_PORTALS e_DPAA_DCPORTAL_DUMMY_LAST ++ ++/***************************************************************************** ++ QMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define QM_MAX_NUM_OF_POOL_CHANNELS 15 /**< Total number of channels, dedicated and pool */ ++#define QM_MAX_NUM_OF_WQ 8 /**< Number of work queues per channel */ ++#define QM_MAX_NUM_OF_CGS 256 /**< Congestion groups number */ ++#define QM_MAX_NUM_OF_FQIDS (16 * MEGABYTE) ++ /**< FQIDs range - 24 bits */ ++ ++/**************************************************************************//** ++ @Description Work Queue Channel assignments in QMan. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_QM_FQ_CHANNEL_SWPORTAL0 = 0x0, /**< Dedicated channels serviced by software portals 0 to 24 */ ++ e_QM_FQ_CHANNEL_SWPORTAL1, ++ e_QM_FQ_CHANNEL_SWPORTAL2, ++ e_QM_FQ_CHANNEL_SWPORTAL3, ++ e_QM_FQ_CHANNEL_SWPORTAL4, ++ e_QM_FQ_CHANNEL_SWPORTAL5, ++ e_QM_FQ_CHANNEL_SWPORTAL6, ++ e_QM_FQ_CHANNEL_SWPORTAL7, ++ e_QM_FQ_CHANNEL_SWPORTAL8, ++ e_QM_FQ_CHANNEL_SWPORTAL9, ++ e_QM_FQ_CHANNEL_SWPORTAL10, ++ e_QM_FQ_CHANNEL_SWPORTAL11, ++ e_QM_FQ_CHANNEL_SWPORTAL12, ++ e_QM_FQ_CHANNEL_SWPORTAL13, ++ e_QM_FQ_CHANNEL_SWPORTAL14, ++ e_QM_FQ_CHANNEL_SWPORTAL15, ++ e_QM_FQ_CHANNEL_SWPORTAL16, ++ e_QM_FQ_CHANNEL_SWPORTAL17, ++ e_QM_FQ_CHANNEL_SWPORTAL18, ++ e_QM_FQ_CHANNEL_SWPORTAL19, ++ e_QM_FQ_CHANNEL_SWPORTAL20, ++ e_QM_FQ_CHANNEL_SWPORTAL21, ++ e_QM_FQ_CHANNEL_SWPORTAL22, ++ e_QM_FQ_CHANNEL_SWPORTAL23, ++ e_QM_FQ_CHANNEL_SWPORTAL24, ++ ++ e_QM_FQ_CHANNEL_POOL1 = 0x401, /**< Pool channels that can be serviced by any of the software portals */ ++ e_QM_FQ_CHANNEL_POOL2, ++ e_QM_FQ_CHANNEL_POOL3, ++ e_QM_FQ_CHANNEL_POOL4, ++ e_QM_FQ_CHANNEL_POOL5, ++ e_QM_FQ_CHANNEL_POOL6, ++ e_QM_FQ_CHANNEL_POOL7, ++ e_QM_FQ_CHANNEL_POOL8, ++ e_QM_FQ_CHANNEL_POOL9, ++ e_QM_FQ_CHANNEL_POOL10, ++ e_QM_FQ_CHANNEL_POOL11, ++ e_QM_FQ_CHANNEL_POOL12, ++ e_QM_FQ_CHANNEL_POOL13, ++ e_QM_FQ_CHANNEL_POOL14, ++ e_QM_FQ_CHANNEL_POOL15, ++ ++ e_QM_FQ_CHANNEL_FMAN0_SP0 = 0x800, /**< Dedicated channels serviced by Direct Connect Portal 0: ++ connected to FMan 0; assigned in incrementing order to ++ each sub-portal (SP) in the portal */ ++ e_QM_FQ_CHANNEL_FMAN0_SP1, ++ e_QM_FQ_CHANNEL_FMAN0_SP2, ++ e_QM_FQ_CHANNEL_FMAN0_SP3, ++ e_QM_FQ_CHANNEL_FMAN0_SP4, ++ e_QM_FQ_CHANNEL_FMAN0_SP5, ++ e_QM_FQ_CHANNEL_FMAN0_SP6, ++ e_QM_FQ_CHANNEL_FMAN0_SP7, ++ e_QM_FQ_CHANNEL_FMAN0_SP8, ++ e_QM_FQ_CHANNEL_FMAN0_SP9, ++ e_QM_FQ_CHANNEL_FMAN0_SP10, ++ e_QM_FQ_CHANNEL_FMAN0_SP11, ++ e_QM_FQ_CHANNEL_FMAN0_SP12, ++ e_QM_FQ_CHANNEL_FMAN0_SP13, ++ e_QM_FQ_CHANNEL_FMAN0_SP14, ++ e_QM_FQ_CHANNEL_FMAN0_SP15, ++ ++ e_QM_FQ_CHANNEL_RMAN_SP0 = 0x820, /**< Dedicated channels serviced by Direct Connect Portal 1: connected to RMan */ ++ e_QM_FQ_CHANNEL_RMAN_SP1, ++ ++ e_QM_FQ_CHANNEL_CAAM = 0x840 /**< Dedicated channel serviced by Direct Connect Portal 2: ++ connected to SEC */ ++} e_QmFQChannel; ++ ++/***************************************************************************** ++ BMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define BM_MAX_NUM_OF_POOLS 64 /**< Number of buffers pools */ ++ ++ ++/***************************************************************************** ++ SEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define SEC_NUM_OF_DECOS 3 ++#define SEC_ALL_DECOS_MASK 0x00000003 ++ ++/***************************************************************************** ++ FM INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define INTG_MAX_NUM_OF_FM 2 ++ ++/* Ports defines */ ++#define FM_MAX_NUM_OF_1G_MACS 6 ++#define FM_MAX_NUM_OF_10G_MACS 2 ++#define FM_MAX_NUM_OF_MACS (FM_MAX_NUM_OF_1G_MACS + FM_MAX_NUM_OF_10G_MACS) ++#define FM_MAX_NUM_OF_OH_PORTS 6 ++ ++#define FM_MAX_NUM_OF_1G_RX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_RX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_RX_PORTS (FM_MAX_NUM_OF_10G_RX_PORTS + FM_MAX_NUM_OF_1G_RX_PORTS) ++ ++#define FM_MAX_NUM_OF_1G_TX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_TX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_TX_PORTS (FM_MAX_NUM_OF_10G_TX_PORTS + FM_MAX_NUM_OF_1G_TX_PORTS) ++ ++#define FM_PORT_MAX_NUM_OF_EXT_POOLS 4 /**< Number of external BM pools per Rx port */ ++#define FM_PORT_NUM_OF_CONGESTION_GRPS 256 /**< Total number of congestion groups in QM */ ++#define FM_MAX_NUM_OF_SUB_PORTALS 16 ++#define FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS 0 ++ ++#define FM_VSP_MAX_NUM_OF_ENTRIES 64 ++#define FM_MAX_NUM_OF_PFC_PRIORITIES 8 ++ ++/* RAMs defines */ ++#define FM_MURAM_SIZE (384 * KILOBYTE) ++#define FM_IRAM_SIZE ( 64 * KILOBYTE) ++#define FM_NUM_OF_CTRL 4 ++ ++/* PCD defines */ ++#define FM_PCD_PLCR_NUM_ENTRIES 256 /**< Total number of policer profiles */ ++#define FM_PCD_KG_NUM_OF_SCHEMES 32 /**< Total number of KG schemes */ ++#define FM_PCD_MAX_NUM_OF_CLS_PLANS 256 /**< Number of classification plan entries. */ ++#define FM_PCD_PRS_SW_PATCHES_SIZE 0x00000240 /**< Number of bytes saved for patches */ ++#define FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */ ++ ++/* RTC defines */ ++#define FM_RTC_NUM_OF_ALARMS 2 /**< RTC number of alarms */ ++#define FM_RTC_NUM_OF_PERIODIC_PULSES 3 /**< RTC number of periodic pulses */ ++#define FM_RTC_NUM_OF_EXT_TRIGGERS 2 /**< RTC number of external triggers */ ++ ++/* QMI defines */ ++#define QMI_MAX_NUM_OF_TNUMS 64 ++#define QMI_DEF_TNUMS_THRESH 48 ++ ++/* FPM defines */ ++#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4 ++ ++/* DMA defines */ ++#define DMA_THRESH_MAX_COMMQ 83 ++#define DMA_THRESH_MAX_BUF 127 ++ ++/* BMI defines */ ++#define BMI_MAX_NUM_OF_TASKS 128 ++#define BMI_MAX_NUM_OF_DMAS 84 ++#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE) ++#define PORT_MAX_WEIGHT 16 ++ ++#define FM_CHECK_PORT_RESTRICTIONS(__validPorts, __newPortIndx) TRUE ++ ++/* Unique T4240 */ ++#define FM_OP_OPEN_DMA_MIN_LIMIT ++#define FM_NO_RESTRICT_ON_ACCESS_RSRC ++#define FM_NO_OP_OBSERVED_POOLS ++#define FM_FRAME_END_PARAMS_FOR_OP ++#define FM_DEQ_PIPELINE_PARAMS_FOR_OP ++#define FM_QMI_NO_SINGLE_ECC_EXCEPTION ++ ++/* FM errata */ ++#define FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 ++#define FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 ++ ++#define FM_BCB_ERRATA_BMI_SW001 ++#define FM_LEN_CHECK_ERRATA_FMAN_SW002 ++#define FM_AID_MODE_NO_TNUM_SW005 /* refer to pdm TKT068794 - only support of port_id on aid */ ++ ++/***************************************************************************** ++ RMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define RM_MAX_NUM_OF_IB 4 /**< Number of inbound blocks */ ++#define RM_NUM_OF_IBCU 8 /**< NUmber of classification units in an inbound block */ ++ ++ ++#endif /* __DPAA_INTEGRATION_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/integrations/T4240/part_ext.h b/drivers/net/dpa/NetCommSw/inc/integrations/T4240/part_ext.h +new file mode 100644 +index 0000000..0d62dd1 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/integrations/T4240/part_ext.h +@@ -0,0 +1,71 @@ ++/* ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 part_ext.h ++ ++ @Description Definitions for the part (integration) module. ++*//***************************************************************************/ ++ ++#ifndef __PART_EXT_H ++#define __PART_EXT_H ++ ++#include "std_ext.h" ++#include "part_integration_ext.h" ++ ++#if !(defined(P1023) || \ ++ defined(P2041) || \ ++ defined(P3041) || \ ++ defined(P4080) || \ ++ defined(P5020) || \ ++ defined(P5040) || \ ++ defined(B4860) || \ ++ defined(T4240)) ++#error "unable to proceed without chip-definition" ++#endif ++ ++ ++/**************************************************************************//* ++ @Description Part data structure - must be contained in any integration ++ data structure. ++*//***************************************************************************/ ++typedef struct t_Part ++{ ++ uintptr_t (* f_GetModuleBase)(t_Handle h_Part, e_ModuleId moduleId); ++ /**< Returns the address of the module's memory map base. */ ++ e_ModuleId (* f_GetModuleIdByBase)(t_Handle h_Part, uintptr_t baseAddress); ++ /**< Returns the module's ID according to its memory map base. */ ++} t_Part; ++ ++ ++#endif /* __PART_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/integrations/T4240/part_integration_ext.h b/drivers/net/dpa/NetCommSw/inc/integrations/T4240/part_integration_ext.h +new file mode 100644 +index 0000000..3254c76 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/integrations/T4240/part_integration_ext.h +@@ -0,0 +1,304 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 part_integration_ext.h ++ ++ @Description T4240 external definitions and structures. ++*//***************************************************************************/ ++#ifndef __PART_INTEGRATION_EXT_H ++#define __PART_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++#include "ddr_std_ext.h" ++#include "enet_ext.h" ++#include "dpaa_integration_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group T4240_chip_id T4240 Application Programming Interface ++ ++ @Description T4240 Chip functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++#define CORE_E6500 ++ ++#define INTG_MAX_NUM_OF_CORES 24 ++ ++ ++/**************************************************************************//** ++ @Description Module types. ++*//***************************************************************************/ ++typedef enum e_ModuleId ++{ ++ e_MODULE_ID_DUART_1 = 0, ++ e_MODULE_ID_DUART_2, ++ e_MODULE_ID_DUART_3, ++ e_MODULE_ID_DUART_4, ++ e_MODULE_ID_LAW, ++ e_MODULE_ID_IFC, ++ e_MODULE_ID_PAMU, ++ e_MODULE_ID_QM, /**< Queue manager module */ ++ e_MODULE_ID_BM, /**< Buffer manager module */ ++ e_MODULE_ID_QM_CE_PORTAL_0, ++ e_MODULE_ID_QM_CI_PORTAL_0, ++ e_MODULE_ID_QM_CE_PORTAL_1, ++ e_MODULE_ID_QM_CI_PORTAL_1, ++ e_MODULE_ID_QM_CE_PORTAL_2, ++ e_MODULE_ID_QM_CI_PORTAL_2, ++ e_MODULE_ID_QM_CE_PORTAL_3, ++ e_MODULE_ID_QM_CI_PORTAL_3, ++ e_MODULE_ID_QM_CE_PORTAL_4, ++ e_MODULE_ID_QM_CI_PORTAL_4, ++ e_MODULE_ID_QM_CE_PORTAL_5, ++ e_MODULE_ID_QM_CI_PORTAL_5, ++ e_MODULE_ID_QM_CE_PORTAL_6, ++ e_MODULE_ID_QM_CI_PORTAL_6, ++ e_MODULE_ID_QM_CE_PORTAL_7, ++ e_MODULE_ID_QM_CI_PORTAL_7, ++ e_MODULE_ID_QM_CE_PORTAL_8, ++ e_MODULE_ID_QM_CI_PORTAL_8, ++ e_MODULE_ID_QM_CE_PORTAL_9, ++ e_MODULE_ID_QM_CI_PORTAL_9, ++ e_MODULE_ID_BM_CE_PORTAL_0, ++ e_MODULE_ID_BM_CI_PORTAL_0, ++ e_MODULE_ID_BM_CE_PORTAL_1, ++ e_MODULE_ID_BM_CI_PORTAL_1, ++ e_MODULE_ID_BM_CE_PORTAL_2, ++ e_MODULE_ID_BM_CI_PORTAL_2, ++ e_MODULE_ID_BM_CE_PORTAL_3, ++ e_MODULE_ID_BM_CI_PORTAL_3, ++ e_MODULE_ID_BM_CE_PORTAL_4, ++ e_MODULE_ID_BM_CI_PORTAL_4, ++ e_MODULE_ID_BM_CE_PORTAL_5, ++ e_MODULE_ID_BM_CI_PORTAL_5, ++ e_MODULE_ID_BM_CE_PORTAL_6, ++ e_MODULE_ID_BM_CI_PORTAL_6, ++ e_MODULE_ID_BM_CE_PORTAL_7, ++ e_MODULE_ID_BM_CI_PORTAL_7, ++ e_MODULE_ID_BM_CE_PORTAL_8, ++ e_MODULE_ID_BM_CI_PORTAL_8, ++ e_MODULE_ID_BM_CE_PORTAL_9, ++ e_MODULE_ID_BM_CI_PORTAL_9, ++ e_MODULE_ID_FM, /**< Frame manager module */ ++ e_MODULE_ID_FM_RTC, /**< FM Real-Time-Clock */ ++ e_MODULE_ID_FM_MURAM, /**< FM Multi-User-RAM */ ++ e_MODULE_ID_FM_BMI, /**< FM BMI block */ ++ e_MODULE_ID_FM_QMI, /**< FM QMI block */ ++ e_MODULE_ID_FM_PARSER, /**< FM parser block */ ++ e_MODULE_ID_FM_PORT_HO1, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO2, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO3, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO4, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO5, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO6, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO7, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_1GRx1, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx2, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx3, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx4, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx5, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx6, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GRx1, /**< FM Rx 10G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GRx2, /**< FM Rx 10G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx1, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx2, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx3, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx4, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx5, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx6, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GTx1, /**< FM Tx 10G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GTx2, /**< FM Tx 10G MAC port block */ ++ e_MODULE_ID_FM_PLCR, /**< FM Policer */ ++ e_MODULE_ID_FM_KG, /**< FM Keygen */ ++ e_MODULE_ID_FM_DMA, /**< FM DMA */ ++ e_MODULE_ID_FM_FPM, /**< FM FPM */ ++ e_MODULE_ID_FM_IRAM, /**< FM Instruction-RAM */ ++ e_MODULE_ID_FM_1GMDIO, /**< FM 1G MDIO MAC */ ++ e_MODULE_ID_FM_10GMDIO, /**< FM 10G MDIO */ ++ e_MODULE_ID_FM_PRS_IRAM, /**< FM SW-parser Instruction-RAM */ ++ e_MODULE_ID_FM_1GMAC1, /**< FM 1G MAC #1 */ ++ e_MODULE_ID_FM_1GMAC2, /**< FM 1G MAC #2 */ ++ e_MODULE_ID_FM_1GMAC3, /**< FM 1G MAC #3 */ ++ e_MODULE_ID_FM_1GMAC4, /**< FM 1G MAC #4 */ ++ e_MODULE_ID_FM_1GMAC5, /**< FM 1G MAC #5 */ ++ e_MODULE_ID_FM_1GMAC6, /**< FM 1G MAC #6 */ ++ e_MODULE_ID_FM_10GMAC1, /**< FM 10G MAC */ ++ e_MODULE_ID_FM_10GMAC2, /**< FM 10G MAC */ ++ ++ e_MODULE_ID_SEC_GEN, /**< SEC 4.0 General registers */ ++ e_MODULE_ID_SEC_QI, /**< SEC 4.0 QI registers */ ++ e_MODULE_ID_SEC_JQ0, /**< SEC 4.0 JQ-0 registers */ ++ e_MODULE_ID_SEC_JQ1, /**< SEC 4.0 JQ-1 registers */ ++ e_MODULE_ID_SEC_JQ2, /**< SEC 4.0 JQ-2 registers */ ++ e_MODULE_ID_SEC_JQ3, /**< SEC 4.0 JQ-3 registers */ ++ e_MODULE_ID_SEC_RTIC, /**< SEC 4.0 RTIC registers */ ++ e_MODULE_ID_SEC_DECO0_CCB0, /**< SEC 4.0 DECO-0/CCB-0 registers */ ++ e_MODULE_ID_SEC_DECO1_CCB1, /**< SEC 4.0 DECO-1/CCB-1 registers */ ++ e_MODULE_ID_SEC_DECO2_CCB2, /**< SEC 4.0 DECO-2/CCB-2 registers */ ++ e_MODULE_ID_SEC_DECO3_CCB3, /**< SEC 4.0 DECO-3/CCB-3 registers */ ++ e_MODULE_ID_SEC_DECO4_CCB4, /**< SEC 4.0 DECO-4/CCB-4 registers */ ++ ++ e_MODULE_ID_PIC, /**< PIC */ ++ e_MODULE_ID_GPIO, /**< GPIO */ ++ e_MODULE_ID_SERDES, /**< SERDES */ ++ e_MODULE_ID_CPC_1, /**< CoreNet-Platform-Cache 1 */ ++ e_MODULE_ID_CPC_2, /**< CoreNet-Platform-Cache 2 */ ++ ++ e_MODULE_ID_SRIO_PORTS, /**< RapidIO controller */ ++ ++ e_MODULE_ID_DUMMY_LAST ++} e_ModuleId; ++ ++#define NUM_OF_MODULES e_MODULE_ID_DUMMY_LAST ++ ++#if 0 /* using unified values */ ++/***************************************************************************** ++ INTEGRATION-SPECIFIC MODULE CODES ++******************************************************************************/ ++#define MODULE_UNKNOWN 0x00000000 ++#define MODULE_MEM 0x00010000 ++#define MODULE_MM 0x00020000 ++#define MODULE_CORE 0x00030000 ++#define MODULE_T4240 0x00040000 ++#define MODULE_T4240_PLATFORM 0x00050000 ++#define MODULE_PM 0x00060000 ++#define MODULE_MMU 0x00070000 ++#define MODULE_PIC 0x00080000 ++#define MODULE_CPC 0x00090000 ++#define MODULE_DUART 0x000a0000 ++#define MODULE_SERDES 0x000b0000 ++#define MODULE_PIO 0x000c0000 ++#define MODULE_QM 0x000d0000 ++#define MODULE_BM 0x000e0000 ++#define MODULE_SEC 0x000f0000 ++#define MODULE_LAW 0x00100000 ++#define MODULE_LBC 0x00110000 ++#define MODULE_PAMU 0x00120000 ++#define MODULE_FM 0x00130000 ++#define MODULE_FM_MURAM 0x00140000 ++#define MODULE_FM_PCD 0x00150000 ++#define MODULE_FM_RTC 0x00160000 ++#define MODULE_FM_MAC 0x00170000 ++#define MODULE_FM_PORT 0x00180000 ++#define MODULE_FM_SP 0x00190000 ++#define MODULE_DPA_PORT 0x001a0000 ++#define MODULE_MII 0x001b0000 ++#define MODULE_I2C 0x001c0000 ++#define MODULE_DMA 0x001d0000 ++#define MODULE_DDR 0x001e0000 ++#define MODULE_ESPI 0x001f0000 ++#define MODULE_DPAA_IPSEC 0x00200000 ++#endif /* using unified values */ ++ ++/***************************************************************************** ++ PAMU INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define PAMU_NUM_OF_PARTITIONS 4 ++ ++/***************************************************************************** ++ LAW INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define LAW_NUM_OF_WINDOWS 32 ++#define LAW_MIN_WINDOW_SIZE 0x0000000000001000LL /**< 4 Kbytes */ ++#define LAW_MAX_WINDOW_SIZE 0x0000010000000000LL /**< 1 Tbytes for 40-bit address space */ ++ ++ ++/***************************************************************************** ++ LBC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++/**************************************************************************//** ++ @Group lbc_exception_grp LBC Exception Unit ++ ++ @Description LBC Exception unit API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Anchor lbc_exbm ++ ++ @Collection LBC Errors Bit Mask ++ ++ These errors are reported through the exceptions callback.. ++ The values can be or'ed in any combination in the errors mask ++ parameter of the errors report structure. ++ ++ These errors can also be passed as a bit-mask to ++ LBC_EnableErrorChecking() or LBC_DisableErrorChecking(), ++ for enabling or disabling error checking. ++ @{ ++*//***************************************************************************/ ++#define LBC_ERR_BUS_MONITOR 0x80000000 /**< Bus monitor error */ ++#define LBC_ERR_PARITY_ECC 0x20000000 /**< Parity error for GPCM/UPM */ ++#define LBC_ERR_WRITE_PROTECT 0x04000000 /**< Write protection error */ ++#define LBC_ERR_CHIP_SELECT 0x00080000 /**< Unrecognized chip select */ ++ ++#define LBC_ERR_ALL (LBC_ERR_BUS_MONITOR | LBC_ERR_PARITY_ECC | \ ++ LBC_ERR_WRITE_PROTECT | LBC_ERR_CHIP_SELECT) ++ /**< All possible errors */ ++/* @} */ ++/** @} */ /* end of lbc_exception_grp group */ ++ ++#define LBC_INCORRECT_ERROR_REPORT_ERRATA ++ ++#define LBC_NUM_OF_BANKS 8 ++#define LBC_MAX_CS_SIZE 0x0000000100000000LL /* Up to 4G memory block size */ ++#define LBC_PARITY_SUPPORT ++#define LBC_ADDRESS_HOLD_TIME_CTRL ++#define LBC_HIGH_CLK_DIVIDERS ++#define LBC_FCM_AVAILABLE ++ ++/***************************************************************************** ++ GPIO INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define GPIO_PORT_OFFSET_0x1000 ++ ++#define GPIO_NUM_OF_PORTS 3 /**< Number of ports in GPIO module; ++ Each port contains up to 32 I/O pins. */ ++ ++#define GPIO_VALID_PIN_MASKS \ ++ { /* Port A */ 0xFFFFFFFF, \ ++ /* Port B */ 0xFFFFFFFF, \ ++ /* Port C */ 0xFFFFFFFF } ++ ++#define GPIO_VALID_INTR_MASKS \ ++ { /* Port A */ 0xFFFFFFFF, \ ++ /* Port B */ 0xFFFFFFFF, \ ++ /* Port C */ 0xFFFFFFFF } ++ ++ ++ ++#endif /* __PART_INTEGRATION_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/math_ext.h b/drivers/net/dpa/NetCommSw/inc/math_ext.h +new file mode 100644 +index 0000000..bff428d +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/math_ext.h +@@ -0,0 +1,99 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __MATH_EXT_H ++#define __MATH_EXT_H ++ ++ ++#if defined(NCSW_LINUX) && defined(__KERNEL__) ++#include ++ ++#elif defined(__MWERKS__) ++#define LOW(x) ( sizeof(x)==8 ? *(1+(int32_t*)&x) : (*(int32_t*)&x)) ++#define HIGH(x) (*(int32_t*)&x) ++#define ULOW(x) ( sizeof(x)==8 ? *(1+(uint32_t*)&x) : (*(uint32_t*)&x)) ++#define UHIGH(x) (*(uint32_t*)&x) ++ ++static const double big = 1.0e300; ++ ++/* Macro for checking if a number is a power of 2 */ ++static __inline__ double ceil(double x) ++{ ++ int32_t i0,i1,j0; /*- cc 020130 -*/ ++ uint32_t i,j; /*- cc 020130 -*/ ++ i0 = HIGH(x); ++ i1 = LOW(x); ++ j0 = ((i0>>20)&0x7ff)-0x3ff; ++ if(j0<20) { ++ if(j0<0) { /* raise inexact if x != 0 */ ++ if(big+x>0.0) {/* return 0*sign(x) if |x|<1 */ ++ if(i0<0) {i0=0x80000000;i1=0;} ++ else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;} ++ } ++ } else { ++ i = (uint32_t)(0x000fffff)>>j0; ++ if(((i0&i)|i1)==0) return x; /* x is integral */ ++ if(big+x>0.0) { /* raise inexact flag */ ++ if(i0>0) i0 += (0x00100000)>>j0; ++ i0 &= (~i); i1=0; ++ } ++ } ++ } else if (j0>51) { ++ if(j0==0x400) return x+x; /* inf or NaN */ ++ else return x; /* x is integral */ ++ } else { ++ i = ((uint32_t)(0xffffffff))>>(j0-20); /*- cc 020130 -*/ ++ if((i1&i)==0) return x; /* x is integral */ ++ if(big+x>0.0) { /* raise inexact flag */ ++ if(i0>0) { ++ if(j0==20) i0+=1; ++ else { ++ j = (uint32_t)(i1 + (1<<(52-j0))); ++ if(j ++#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */ ++ ++ ++#endif /* __MATH_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/ncsw_ext.h b/drivers/net/dpa/NetCommSw/inc/ncsw_ext.h +new file mode 100644 +index 0000000..c3341cd +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/ncsw_ext.h +@@ -0,0 +1,432 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 ncsw_ext.h ++ ++ @Description General NetCommSw Standard Definitions ++*//***************************************************************************/ ++ ++#ifndef __NCSW_EXT_H ++#define __NCSW_EXT_H ++ ++#include "memcpy_ext.h" ++ ++ ++#define WRITE_BLOCK IOMemSet32 ++#define COPY_BLOCK Mem2IOCpy32 ++ ++#define PTR_TO_UINT(_ptr) ((uintptr_t)(_ptr)) ++#define UINT_TO_PTR(_val) ((void*)(uintptr_t)(_val)) ++ ++#define PTR_MOVE(_ptr, _offset) (void*)((uint8_t*)(_ptr) + (_offset)) ++ ++ ++#define WRITE_UINT8_UINT24(arg, data08, data24) WRITE_UINT32(arg,((uint32_t)(data08)<<24)|((uint32_t)(data24)&0x00FFFFFF)) ++#define WRITE_UINT24_UINT8(arg, data24, data08) WRITE_UINT32(arg,((uint32_t)(data24)<< 8)|((uint32_t)(data08)&0x000000FF)) ++ ++/* Little-Endian access macros */ ++ ++#define WRITE_UINT16_LE(arg, data) \ ++ WRITE_UINT16((arg), SwapUint16(data)) ++ ++#define WRITE_UINT32_LE(arg, data) \ ++ WRITE_UINT32((arg), SwapUint32(data)) ++ ++#define WRITE_UINT64_LE(arg, data) \ ++ WRITE_UINT64((arg), SwapUint64(data)) ++ ++#define GET_UINT16_LE(arg) \ ++ SwapUint16(GET_UINT16(arg)) ++ ++#define GET_UINT32_LE(arg) \ ++ SwapUint32(GET_UINT32(arg)) ++ ++#define GET_UINT64_LE(arg) \ ++ SwapUint64(GET_UINT64(arg)) ++ ++/* Write and Read again macros */ ++#define WRITE_UINT_SYNC(size, arg, data) \ ++ do { \ ++ WRITE_UINT##size((arg), (data)); \ ++ CORE_MemoryBarrier(); \ ++ } while (0) ++ ++#define WRITE_UINT8_SYNC(arg, data) WRITE_UINT_SYNC(8, (arg), (data)) ++ ++#define WRITE_UINT16_SYNC(arg, data) WRITE_UINT_SYNC(16, (arg), (data)) ++#define WRITE_UINT32_SYNC(arg, data) WRITE_UINT_SYNC(32, (arg), (data)) ++ ++#define MAKE_UINT64(high32, low32) (((uint64_t)high32 << 32) | (low32)) ++ ++ ++/*----------------------*/ ++/* Miscellaneous macros */ ++/*----------------------*/ ++ ++#define UNUSED(X) (X=X) ++ ++#define KILOBYTE 0x400UL /* 1024 */ ++#define MEGABYTE (KILOBYTE * KILOBYTE) /* 1024*1024 */ ++#define GIGABYTE ((uint64_t)(KILOBYTE * MEGABYTE)) /* 1024*1024*1024 */ ++#define TERABYTE ((uint64_t)(KILOBYTE * GIGABYTE)) /* 1024*1024*1024*1024 */ ++ ++#undef NO_IRQ ++#define NO_IRQ (-1) ++#define NCSW_MASTER_ID (0) ++ ++/* Macro for checking if a number is a power of 2 */ ++#define POWER_OF_2(n) (!((n) & ((n)-1))) ++ ++/* Macro for calculating log of base 2 */ ++#define LOG2(num, log2Num) \ ++ do \ ++ { \ ++ uint64_t tmp = (num); \ ++ log2Num = 0; \ ++ while (tmp > 1) \ ++ { \ ++ log2Num++; \ ++ tmp >>= 1; \ ++ } \ ++ } while (0) ++ ++#define NEXT_POWER_OF_2(_num, _nextPow) \ ++do \ ++{ \ ++ if (POWER_OF_2(_num)) \ ++ _nextPow = (_num); \ ++ else \ ++ { \ ++ uint64_t tmp = (_num); \ ++ _nextPow = 1; \ ++ while (tmp) \ ++ { \ ++ _nextPow <<= 1; \ ++ tmp >>= 1; \ ++ } \ ++ } \ ++} while (0) ++ ++/* Ceiling division - not the fastest way, but safer in terms of overflow */ ++#define DIV_CEIL(x,y) (((x)/(y)) + ((((((x)/(y)))*(y)) == (x)) ? 0 : 1)) ++ ++/* Round up a number to be a multiple of a second number */ ++#define ROUND_UP(x,y) ((((x) + (y) - 1) / (y)) * (y)) ++ ++/* Timing macro for converting usec units to number of ticks. */ ++/* (number of usec * clock_Hz) / 1,000,000) - since */ ++/* clk is in MHz units, no division needed. */ ++#define USEC_TO_CLK(usec,clk) ((usec) * (clk)) ++#define CYCLES_TO_USEC(cycles,clk) ((cycles) / (clk)) ++ ++/* Timing macros for converting between nsec units and number of clocks. */ ++#define NSEC_TO_CLK(nsec,clk) DIV_CEIL(((nsec) * (clk)), 1000) ++#define CYCLES_TO_NSEC(cycles,clk) (((cycles) * 1000) / (clk)) ++ ++/* Timing macros for converting between psec units and number of clocks. */ ++#define PSEC_TO_CLK(psec,clk) DIV_CEIL(((psec) * (clk)), 1000000) ++#define CYCLES_TO_PSEC(cycles,clk) (((cycles) * 1000000) / (clk)) ++ ++/* Min, Max macros */ ++#define MIN(a,b) ((a) < (b) ? (a) : (b)) ++#define MAX(a,b) ((a) > (b) ? (a) : (b)) ++#define IN_RANGE(min,val,max) ((min)<=(val) && (val)<=(max)) ++ ++#define ABS(a) ((a<0)?(a*-1):a) ++ ++#if !(defined(ARRAY_SIZE)) ++#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) ++#endif /* !defined(ARRAY_SIZE) */ ++ ++ ++/* possible alignments */ ++#define HALF_WORD_ALIGNMENT 2 ++#define WORD_ALIGNMENT 4 ++#define DOUBLE_WORD_ALIGNMENT 8 ++#define BURST_ALIGNMENT 32 ++ ++#define HALF_WORD_ALIGNED 0x00000001 ++#define WORD_ALIGNED 0x00000003 ++#define DOUBLE_WORD_ALIGNED 0x00000007 ++#define BURST_ALIGNED 0x0000001f ++#ifndef IS_ALIGNED ++#define IS_ALIGNED(n,align) (!((uint32_t)(n) & (align - 1))) ++#endif /* IS_ALIGNED */ ++ ++ ++#define LAST_BUF 1 ++#define FIRST_BUF 2 ++#define SINGLE_BUF (LAST_BUF | FIRST_BUF) ++#define MIDDLE_BUF 4 ++ ++#define ARRAY_END -1 ++ ++#define ILLEGAL_BASE (~0) ++ ++#define BUF_POSITION(first, last) state[(!!(last))<<1 | !!(first)] ++#define DECLARE_POSITION static uint8_t state[4] = { (uint8_t)MIDDLE_BUF, (uint8_t)FIRST_BUF, (uint8_t)LAST_BUF, (uint8_t)SINGLE_BUF }; ++ ++ ++/**************************************************************************//** ++ @Description Timers operation mode ++*//***************************************************************************/ ++typedef enum e_TimerMode ++{ ++ e_TIMER_MODE_INVALID = 0, ++ e_TIMER_MODE_FREE_RUN, /**< Free run - counter continues to increase ++ after reaching the reference value. */ ++ e_TIMER_MODE_PERIODIC, /**< Periodic - counter restarts counting from 0 ++ after reaching the reference value. */ ++ e_TIMER_MODE_SINGLE /**< Single (one-shot) - counter stops counting ++ after reaching the reference value. */ ++} e_TimerMode; ++ ++ ++/**************************************************************************//** ++ @Description Enumeration (bit flags) of communication modes (Transmit, ++ receive or both). ++*//***************************************************************************/ ++typedef enum e_CommMode ++{ ++ e_COMM_MODE_NONE = 0, /**< No transmit/receive communication */ ++ e_COMM_MODE_RX = 1, /**< Only receive communication */ ++ e_COMM_MODE_TX = 2, /**< Only transmit communication */ ++ e_COMM_MODE_RX_AND_TX = 3 /**< Both transmit and receive communication */ ++} e_CommMode; ++ ++/**************************************************************************//** ++ @Description General Diagnostic Mode ++*//***************************************************************************/ ++typedef enum e_DiagMode ++{ ++ e_DIAG_MODE_NONE = 0, /**< Normal operation; no diagnostic mode */ ++ e_DIAG_MODE_CTRL_LOOPBACK, /**< Loopback in the controller */ ++ e_DIAG_MODE_CHIP_LOOPBACK, /**< Loopback in the chip but not in the ++ controller; e.g. IO-pins, SerDes, etc. */ ++ e_DIAG_MODE_PHY_LOOPBACK, /**< Loopback in the external PHY */ ++ e_DIAG_MODE_EXT_LOOPBACK, /**< Loopback in the external line (beyond the PHY) */ ++ e_DIAG_MODE_CTRL_ECHO, /**< Echo incoming data by the controller */ ++ e_DIAG_MODE_PHY_ECHO /**< Echo incoming data by the PHY */ ++} e_DiagMode; ++ ++/**************************************************************************//** ++ @Description Possible RxStore callback responses. ++*//***************************************************************************/ ++typedef enum e_RxStoreResponse ++{ ++ e_RX_STORE_RESPONSE_PAUSE /**< Pause invoking callback with received data; ++ in polling mode, start again invoking callback ++ only next time user invokes the receive routine; ++ in interrupt mode, start again invoking callback ++ only next time a receive event triggers an interrupt; ++ in all cases, received data that are pending are not ++ lost, rather, their processing is temporarily deferred; ++ in all cases, received data are processed in the order ++ in which they were received. */ ++ , e_RX_STORE_RESPONSE_CONTINUE /**< Continue invoking callback with received data. */ ++} e_RxStoreResponse; ++ ++ ++/**************************************************************************//** ++ @Description General Handle ++*//***************************************************************************/ ++typedef void * t_Handle; /**< handle, used as object's descriptor */ ++ ++/**************************************************************************//** ++ @Description MUTEX type ++*//***************************************************************************/ ++typedef uint32_t t_Mutex; ++ ++/**************************************************************************//** ++ @Description Error Code. ++ ++ The high word of the error code is the code of the software ++ module (driver). The low word is the error type (e_ErrorType). ++ To get the values from the error code, use GET_ERROR_TYPE() ++ and GET_ERROR_MODULE(). ++*//***************************************************************************/ ++typedef uint32_t t_Error; ++ ++/**************************************************************************//** ++ @Description General prototype of interrupt service routine (ISR). ++ ++ @Param[in] handle - Optional handle of the module handling the interrupt. ++ ++ @Return None ++ *//***************************************************************************/ ++typedef void (t_Isr)(t_Handle handle); ++ ++/**************************************************************************//** ++ @Anchor mem_attr ++ ++ @Collection Memory Attributes ++ ++ Various attributes of memory partitions. These values may be ++ or'ed together to create a mask of all memory attributes. ++ @{ ++*//***************************************************************************/ ++#define MEMORY_ATTR_CACHEABLE 0x00000001 ++ /**< Memory is cacheable */ ++#define MEMORY_ATTR_QE_2ND_BUS_ACCESS 0x00000002 ++ /**< Memory can be accessed by QUICC Engine ++ through its secondary bus interface */ ++ ++/* @} */ ++ ++ ++/**************************************************************************//** ++ @Function t_GetBufFunction ++ ++ @Description User callback function called by driver to get data buffer. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_BufferPool - A handle to buffer pool manager ++ @Param[out] p_BufContextHandle - Returns the user's private context that ++ should be associated with the buffer ++ ++ @Return Pointer to data buffer, NULL if error ++ *//***************************************************************************/ ++typedef uint8_t * (t_GetBufFunction)(t_Handle h_BufferPool, ++ t_Handle *p_BufContextHandle); ++ ++/**************************************************************************//** ++ @Function t_PutBufFunction ++ ++ @Description User callback function called by driver to return data buffer. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_BufferPool - A handle to buffer pool manager ++ @Param[in] p_Buffer - A pointer to buffer to return ++ @Param[in] h_BufContext - The user's private context associated with ++ the returned buffer ++ ++ @Return E_OK on success; Error code otherwise ++ *//***************************************************************************/ ++typedef t_Error (t_PutBufFunction)(t_Handle h_BufferPool, ++ uint8_t *p_Buffer, ++ t_Handle h_BufContext); ++ ++/**************************************************************************//** ++ @Function t_PhysToVirt ++ ++ @Description Translates a physical address to the matching virtual address. ++ ++ @Param[in] addr - The physical address to translate. ++ ++ @Return Virtual address. ++*//***************************************************************************/ ++typedef void * t_PhysToVirt(physAddress_t addr); ++ ++/**************************************************************************//** ++ @Function t_VirtToPhys ++ ++ @Description Translates a virtual address to the matching physical address. ++ ++ @Param[in] addr - The virtual address to translate. ++ ++ @Return Physical address. ++*//***************************************************************************/ ++typedef physAddress_t t_VirtToPhys(void *addr); ++ ++/**************************************************************************//** ++ @Description Buffer Pool Information Structure. ++*//***************************************************************************/ ++typedef struct t_BufferPoolInfo ++{ ++ t_Handle h_BufferPool; /**< A handle to the buffer pool manager */ ++ t_GetBufFunction *f_GetBuf; /**< User callback to get a free buffer */ ++ t_PutBufFunction *f_PutBuf; /**< User callback to return a buffer */ ++ uint16_t bufferSize; /**< Buffer size (in bytes) */ ++ ++ t_PhysToVirt *f_PhysToVirt; /**< User callback to translate pool buffers ++ physical addresses to virtual addresses */ ++ t_VirtToPhys *f_VirtToPhys; /**< User callback to translate pool buffers ++ virtual addresses to physical addresses */ ++} t_BufferPoolInfo; ++ ++ ++/**************************************************************************//** ++ @Description User callback function called by driver when transmit completed. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_App - Application's handle, as was provided to the ++ driver by the user ++ @Param[in] queueId - Transmit queue ID ++ @Param[in] p_Data - Pointer to the data buffer ++ @Param[in] h_BufContext - The user's private context associated with ++ the given data buffer ++ @Param[in] status - Transmit status and errors ++ @Param[in] flags - Driver-dependent information ++ *//***************************************************************************/ ++typedef void (t_TxConfFunction)(t_Handle h_App, ++ uint32_t queueId, ++ uint8_t *p_Data, ++ t_Handle h_BufContext, ++ uint16_t status, ++ uint32_t flags); ++ ++/**************************************************************************//** ++ @Description User callback function called by driver with receive data. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_App - Application's handle, as was provided to the ++ driver by the user ++ @Param[in] queueId - Receive queue ID ++ @Param[in] p_Data - Pointer to the buffer with received data ++ @Param[in] h_BufContext - The user's private context associated with ++ the given data buffer ++ @Param[in] length - Length of received data ++ @Param[in] status - Receive status and errors ++ @Param[in] position - Position of buffer in frame ++ @Param[in] flags - Driver-dependent information ++ ++ @Retval e_RX_STORE_RESPONSE_CONTINUE - order the driver to continue Rx ++ operation for all ready data. ++ @Retval e_RX_STORE_RESPONSE_PAUSE - order the driver to stop Rx operation. ++ *//***************************************************************************/ ++typedef e_RxStoreResponse (t_RxStoreFunction)(t_Handle h_App, ++ uint32_t queueId, ++ uint8_t *p_Data, ++ t_Handle h_BufContext, ++ uint32_t length, ++ uint16_t status, ++ uint8_t position, ++ uint32_t flags); ++ ++ ++#endif /* __NCSW_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/net_ext.h b/drivers/net/dpa/NetCommSw/inc/net_ext.h +new file mode 100644 +index 0000000..8f3bc36 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/net_ext.h +@@ -0,0 +1,430 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 net_ext.h ++ ++ @Description This file contains common and general netcomm headers definitions. ++*//***************************************************************************/ ++#ifndef __NET_EXT_H ++#define __NET_EXT_H ++ ++#include "std_ext.h" ++ ++ ++typedef uint8_t headerFieldPpp_t; ++ ++#define NET_HEADER_FIELD_PPP_PID (1) ++#define NET_HEADER_FIELD_PPP_COMPRESSED (NET_HEADER_FIELD_PPP_PID << 1) ++#define NET_HEADER_FIELD_PPP_ALL_FIELDS ((NET_HEADER_FIELD_PPP_PID << 2) - 1) ++ ++ ++typedef uint8_t headerFieldPppoe_t; ++ ++#define NET_HEADER_FIELD_PPPoE_VER (1) ++#define NET_HEADER_FIELD_PPPoE_TYPE (NET_HEADER_FIELD_PPPoE_VER << 1) ++#define NET_HEADER_FIELD_PPPoE_CODE (NET_HEADER_FIELD_PPPoE_VER << 2) ++#define NET_HEADER_FIELD_PPPoE_SID (NET_HEADER_FIELD_PPPoE_VER << 3) ++#define NET_HEADER_FIELD_PPPoE_LEN (NET_HEADER_FIELD_PPPoE_VER << 4) ++#define NET_HEADER_FIELD_PPPoE_SESSION (NET_HEADER_FIELD_PPPoE_VER << 5) ++#define NET_HEADER_FIELD_PPPoE_PID (NET_HEADER_FIELD_PPPoE_VER << 6) ++#define NET_HEADER_FIELD_PPPoE_ALL_FIELDS ((NET_HEADER_FIELD_PPPoE_VER << 7) - 1) ++ ++#define NET_HEADER_FIELD_PPPMUX_PID (1) ++#define NET_HEADER_FIELD_PPPMUX_CKSUM (NET_HEADER_FIELD_PPPMUX_PID << 1) ++#define NET_HEADER_FIELD_PPPMUX_COMPRESSED (NET_HEADER_FIELD_PPPMUX_PID << 2) ++#define NET_HEADER_FIELD_PPPMUX_ALL_FIELDS ((NET_HEADER_FIELD_PPPMUX_PID << 3) - 1) ++ ++#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF (1) ++#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_LXT (NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 1) ++#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_LEN (NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 2) ++#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_PID (NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 3) ++#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_USE_PID (NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 4) ++#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_ALL_FIELDS ((NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 5) - 1) ++ ++ ++typedef uint8_t headerFieldEth_t; ++ ++#define NET_HEADER_FIELD_ETH_DA (1) ++#define NET_HEADER_FIELD_ETH_SA (NET_HEADER_FIELD_ETH_DA << 1) ++#define NET_HEADER_FIELD_ETH_LENGTH (NET_HEADER_FIELD_ETH_DA << 2) ++#define NET_HEADER_FIELD_ETH_TYPE (NET_HEADER_FIELD_ETH_DA << 3) ++#define NET_HEADER_FIELD_ETH_FINAL_CKSUM (NET_HEADER_FIELD_ETH_DA << 4) ++#define NET_HEADER_FIELD_ETH_PADDING (NET_HEADER_FIELD_ETH_DA << 5) ++#define NET_HEADER_FIELD_ETH_ALL_FIELDS ((NET_HEADER_FIELD_ETH_DA << 6) - 1) ++ ++#define NET_HEADER_FIELD_ETH_ADDR_SIZE 6 ++ ++typedef uint16_t headerFieldIp_t; ++ ++#define NET_HEADER_FIELD_IP_VER (1) ++#define NET_HEADER_FIELD_IP_DSCP (NET_HEADER_FIELD_IP_VER << 2) ++#define NET_HEADER_FIELD_IP_ECN (NET_HEADER_FIELD_IP_VER << 3) ++#define NET_HEADER_FIELD_IP_PROTO (NET_HEADER_FIELD_IP_VER << 4) ++ ++#define NET_HEADER_FIELD_IP_PROTO_SIZE 1 ++ ++typedef uint16_t headerFieldIpv4_t; ++ ++#define NET_HEADER_FIELD_IPv4_VER (1) ++#define NET_HEADER_FIELD_IPv4_HDR_LEN (NET_HEADER_FIELD_IPv4_VER << 1) ++#define NET_HEADER_FIELD_IPv4_TOS (NET_HEADER_FIELD_IPv4_VER << 2) ++#define NET_HEADER_FIELD_IPv4_TOTAL_LEN (NET_HEADER_FIELD_IPv4_VER << 3) ++#define NET_HEADER_FIELD_IPv4_ID (NET_HEADER_FIELD_IPv4_VER << 4) ++#define NET_HEADER_FIELD_IPv4_FLAG_D (NET_HEADER_FIELD_IPv4_VER << 5) ++#define NET_HEADER_FIELD_IPv4_FLAG_M (NET_HEADER_FIELD_IPv4_VER << 6) ++#define NET_HEADER_FIELD_IPv4_OFFSET (NET_HEADER_FIELD_IPv4_VER << 7) ++#define NET_HEADER_FIELD_IPv4_TTL (NET_HEADER_FIELD_IPv4_VER << 8) ++#define NET_HEADER_FIELD_IPv4_PROTO (NET_HEADER_FIELD_IPv4_VER << 9) ++#define NET_HEADER_FIELD_IPv4_CKSUM (NET_HEADER_FIELD_IPv4_VER << 10) ++#define NET_HEADER_FIELD_IPv4_SRC_IP (NET_HEADER_FIELD_IPv4_VER << 11) ++#define NET_HEADER_FIELD_IPv4_DST_IP (NET_HEADER_FIELD_IPv4_VER << 12) ++#define NET_HEADER_FIELD_IPv4_OPTS (NET_HEADER_FIELD_IPv4_VER << 13) ++#define NET_HEADER_FIELD_IPv4_OPTS_COUNT (NET_HEADER_FIELD_IPv4_VER << 14) ++#define NET_HEADER_FIELD_IPv4_ALL_FIELDS ((NET_HEADER_FIELD_IPv4_VER << 15) - 1) ++ ++#define NET_HEADER_FIELD_IPv4_ADDR_SIZE 4 ++#define NET_HEADER_FIELD_IPv4_PROTO_SIZE 1 ++ ++ ++typedef uint8_t headerFieldIpv6_t; ++ ++#define NET_HEADER_FIELD_IPv6_VER (1) ++#define NET_HEADER_FIELD_IPv6_TC (NET_HEADER_FIELD_IPv6_VER << 1) ++#define NET_HEADER_FIELD_IPv6_SRC_IP (NET_HEADER_FIELD_IPv6_VER << 2) ++#define NET_HEADER_FIELD_IPv6_DST_IP (NET_HEADER_FIELD_IPv6_VER << 3) ++#define NET_HEADER_FIELD_IPv6_NEXT_HDR (NET_HEADER_FIELD_IPv6_VER << 4) ++#define NET_HEADER_FIELD_IPv6_FL (NET_HEADER_FIELD_IPv6_VER << 5) ++#define NET_HEADER_FIELD_IPv6_HOP_LIMIT (NET_HEADER_FIELD_IPv6_VER << 6) ++#define NET_HEADER_FIELD_IPv6_ALL_FIELDS ((NET_HEADER_FIELD_IPv6_VER << 7) - 1) ++ ++#define NET_HEADER_FIELD_IPv6_ADDR_SIZE 16 ++#define NET_HEADER_FIELD_IPv6_NEXT_HDR_SIZE 1 ++ ++#define NET_HEADER_FIELD_ICMP_TYPE (1) ++#define NET_HEADER_FIELD_ICMP_CODE (NET_HEADER_FIELD_ICMP_TYPE << 1) ++#define NET_HEADER_FIELD_ICMP_CKSUM (NET_HEADER_FIELD_ICMP_TYPE << 2) ++#define NET_HEADER_FIELD_ICMP_ID (NET_HEADER_FIELD_ICMP_TYPE << 3) ++#define NET_HEADER_FIELD_ICMP_SQ_NUM (NET_HEADER_FIELD_ICMP_TYPE << 4) ++#define NET_HEADER_FIELD_ICMP_ALL_FIELDS ((NET_HEADER_FIELD_ICMP_TYPE << 5) - 1) ++ ++#define NET_HEADER_FIELD_ICMP_CODE_SIZE 1 ++#define NET_HEADER_FIELD_ICMP_TYPE_SIZE 1 ++ ++#define NET_HEADER_FIELD_IGMP_VERSION (1) ++#define NET_HEADER_FIELD_IGMP_TYPE (NET_HEADER_FIELD_IGMP_VERSION << 1) ++#define NET_HEADER_FIELD_IGMP_CKSUM (NET_HEADER_FIELD_IGMP_VERSION << 2) ++#define NET_HEADER_FIELD_IGMP_DATA (NET_HEADER_FIELD_IGMP_VERSION << 3) ++#define NET_HEADER_FIELD_IGMP_ALL_FIELDS ((NET_HEADER_FIELD_IGMP_VERSION << 4) - 1) ++ ++ ++typedef uint16_t headerFieldTcp_t; ++ ++#define NET_HEADER_FIELD_TCP_PORT_SRC (1) ++#define NET_HEADER_FIELD_TCP_PORT_DST (NET_HEADER_FIELD_TCP_PORT_SRC << 1) ++#define NET_HEADER_FIELD_TCP_SEQ (NET_HEADER_FIELD_TCP_PORT_SRC << 2) ++#define NET_HEADER_FIELD_TCP_ACK (NET_HEADER_FIELD_TCP_PORT_SRC << 3) ++#define NET_HEADER_FIELD_TCP_OFFSET (NET_HEADER_FIELD_TCP_PORT_SRC << 4) ++#define NET_HEADER_FIELD_TCP_FLAGS (NET_HEADER_FIELD_TCP_PORT_SRC << 5) ++#define NET_HEADER_FIELD_TCP_WINDOW (NET_HEADER_FIELD_TCP_PORT_SRC << 6) ++#define NET_HEADER_FIELD_TCP_CKSUM (NET_HEADER_FIELD_TCP_PORT_SRC << 7) ++#define NET_HEADER_FIELD_TCP_URGPTR (NET_HEADER_FIELD_TCP_PORT_SRC << 8) ++#define NET_HEADER_FIELD_TCP_OPTS (NET_HEADER_FIELD_TCP_PORT_SRC << 9) ++#define NET_HEADER_FIELD_TCP_OPTS_COUNT (NET_HEADER_FIELD_TCP_PORT_SRC << 10) ++#define NET_HEADER_FIELD_TCP_ALL_FIELDS ((NET_HEADER_FIELD_TCP_PORT_SRC << 11) - 1) ++ ++#define NET_HEADER_FIELD_TCP_PORT_SIZE 2 ++ ++ ++typedef uint8_t headerFieldSctp_t; ++ ++#define NET_HEADER_FIELD_SCTP_PORT_SRC (1) ++#define NET_HEADER_FIELD_SCTP_PORT_DST (NET_HEADER_FIELD_SCTP_PORT_SRC << 1) ++#define NET_HEADER_FIELD_SCTP_VER_TAG (NET_HEADER_FIELD_SCTP_PORT_SRC << 2) ++#define NET_HEADER_FIELD_SCTP_CKSUM (NET_HEADER_FIELD_SCTP_PORT_SRC << 3) ++#define NET_HEADER_FIELD_SCTP_ALL_FIELDS ((NET_HEADER_FIELD_SCTP_PORT_SRC << 4) - 1) ++ ++#define NET_HEADER_FIELD_SCTP_PORT_SIZE 2 ++ ++typedef uint8_t headerFieldDccp_t; ++ ++#define NET_HEADER_FIELD_DCCP_PORT_SRC (1) ++#define NET_HEADER_FIELD_DCCP_PORT_DST (NET_HEADER_FIELD_DCCP_PORT_SRC << 1) ++#define NET_HEADER_FIELD_DCCP_ALL_FIELDS ((NET_HEADER_FIELD_DCCP_PORT_SRC << 2) - 1) ++ ++#define NET_HEADER_FIELD_DCCP_PORT_SIZE 2 ++ ++ ++typedef uint8_t headerFieldUdp_t; ++ ++#define NET_HEADER_FIELD_UDP_PORT_SRC (1) ++#define NET_HEADER_FIELD_UDP_PORT_DST (NET_HEADER_FIELD_UDP_PORT_SRC << 1) ++#define NET_HEADER_FIELD_UDP_LEN (NET_HEADER_FIELD_UDP_PORT_SRC << 2) ++#define NET_HEADER_FIELD_UDP_CKSUM (NET_HEADER_FIELD_UDP_PORT_SRC << 3) ++#define NET_HEADER_FIELD_UDP_ALL_FIELDS ((NET_HEADER_FIELD_UDP_PORT_SRC << 4) - 1) ++ ++#define NET_HEADER_FIELD_UDP_PORT_SIZE 2 ++ ++typedef uint8_t headerFieldUdpLite_t; ++ ++#define NET_HEADER_FIELD_UDP_LITE_PORT_SRC (1) ++#define NET_HEADER_FIELD_UDP_LITE_PORT_DST (NET_HEADER_FIELD_UDP_LITE_PORT_SRC << 1) ++#define NET_HEADER_FIELD_UDP_LITE_ALL_FIELDS ((NET_HEADER_FIELD_UDP_LITE_PORT_SRC << 2) - 1) ++ ++#define NET_HEADER_FIELD_UDP_LITE_PORT_SIZE 2 ++ ++typedef uint8_t headerFieldUdpEncapEsp_t; ++ ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC (1) ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 1) ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 2) ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 3) ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 4) ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 5) ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_ALL_FIELDS ((NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 6) - 1) ++ ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SIZE 2 ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI_SIZE 4 ++ ++#define NET_HEADER_FIELD_IPHC_CID (1) ++#define NET_HEADER_FIELD_IPHC_CID_TYPE (NET_HEADER_FIELD_IPHC_CID << 1) ++#define NET_HEADER_FIELD_IPHC_HCINDEX (NET_HEADER_FIELD_IPHC_CID << 2) ++#define NET_HEADER_FIELD_IPHC_GEN (NET_HEADER_FIELD_IPHC_CID << 3) ++#define NET_HEADER_FIELD_IPHC_D_BIT (NET_HEADER_FIELD_IPHC_CID << 4) ++#define NET_HEADER_FIELD_IPHC_ALL_FIELDS ((NET_HEADER_FIELD_IPHC_CID << 5) - 1) ++ ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE (1) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_FLAGS (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 1) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_LENGTH (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 2) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_TSN (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 3) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_STREAM_ID (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 4) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_STREAM_SQN (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 5) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_PAYLOAD_PID (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 6) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_UNORDERED (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 7) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_BEGGINING (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 8) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_END (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 9) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_ALL_FIELDS ((NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 10) - 1) ++ ++#define NET_HEADER_FIELD_L2TPv2_TYPE_BIT (1) ++#define NET_HEADER_FIELD_L2TPv2_LENGTH_BIT (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 1) ++#define NET_HEADER_FIELD_L2TPv2_SEQUENCE_BIT (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 2) ++#define NET_HEADER_FIELD_L2TPv2_OFFSET_BIT (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 3) ++#define NET_HEADER_FIELD_L2TPv2_PRIORITY_BIT (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 4) ++#define NET_HEADER_FIELD_L2TPv2_VERSION (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 5) ++#define NET_HEADER_FIELD_L2TPv2_LEN (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 6) ++#define NET_HEADER_FIELD_L2TPv2_TUNNEL_ID (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 7) ++#define NET_HEADER_FIELD_L2TPv2_SESSION_ID (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 8) ++#define NET_HEADER_FIELD_L2TPv2_NS (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 9) ++#define NET_HEADER_FIELD_L2TPv2_NR (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 10) ++#define NET_HEADER_FIELD_L2TPv2_OFFSET_SIZE (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 11) ++#define NET_HEADER_FIELD_L2TPv2_FIRST_BYTE (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 12) ++#define NET_HEADER_FIELD_L2TPv2_ALL_FIELDS ((NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 13) - 1) ++ ++#define NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT (1) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_LENGTH_BIT (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 1) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_SEQUENCE_BIT (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 2) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_VERSION (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 3) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_LENGTH (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 4) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_CONTROL (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 5) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_SENT (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 6) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_RECV (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 7) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_FIRST_BYTE (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 8) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_ALL_FIELDS ((NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 9) - 1) ++ ++#define NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT (1) ++#define NET_HEADER_FIELD_L2TPv3_SESS_VERSION (NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 1) ++#define NET_HEADER_FIELD_L2TPv3_SESS_ID (NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 2) ++#define NET_HEADER_FIELD_L2TPv3_SESS_COOKIE (NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 3) ++#define NET_HEADER_FIELD_L2TPv3_SESS_ALL_FIELDS ((NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 4) - 1) ++ ++ ++typedef uint8_t headerFieldVlan_t; ++ ++#define NET_HEADER_FIELD_VLAN_VPRI (1) ++#define NET_HEADER_FIELD_VLAN_CFI (NET_HEADER_FIELD_VLAN_VPRI << 1) ++#define NET_HEADER_FIELD_VLAN_VID (NET_HEADER_FIELD_VLAN_VPRI << 2) ++#define NET_HEADER_FIELD_VLAN_LENGTH (NET_HEADER_FIELD_VLAN_VPRI << 3) ++#define NET_HEADER_FIELD_VLAN_TYPE (NET_HEADER_FIELD_VLAN_VPRI << 4) ++#define NET_HEADER_FIELD_VLAN_ALL_FIELDS ((NET_HEADER_FIELD_VLAN_VPRI << 5) - 1) ++ ++#define NET_HEADER_FIELD_VLAN_TCI (NET_HEADER_FIELD_VLAN_VPRI | \ ++ NET_HEADER_FIELD_VLAN_CFI | \ ++ NET_HEADER_FIELD_VLAN_VID) ++ ++ ++typedef uint8_t headerFieldLlc_t; ++ ++#define NET_HEADER_FIELD_LLC_DSAP (1) ++#define NET_HEADER_FIELD_LLC_SSAP (NET_HEADER_FIELD_LLC_DSAP << 1) ++#define NET_HEADER_FIELD_LLC_CTRL (NET_HEADER_FIELD_LLC_DSAP << 2) ++#define NET_HEADER_FIELD_LLC_ALL_FIELDS ((NET_HEADER_FIELD_LLC_DSAP << 3) - 1) ++ ++#define NET_HEADER_FIELD_NLPID_NLPID (1) ++#define NET_HEADER_FIELD_NLPID_ALL_FIELDS ((NET_HEADER_FIELD_NLPID_NLPID << 1) - 1) ++ ++ ++typedef uint8_t headerFieldSnap_t; ++ ++#define NET_HEADER_FIELD_SNAP_OUI (1) ++#define NET_HEADER_FIELD_SNAP_PID (NET_HEADER_FIELD_SNAP_OUI << 1) ++#define NET_HEADER_FIELD_SNAP_ALL_FIELDS ((NET_HEADER_FIELD_SNAP_OUI << 2) - 1) ++ ++ ++typedef uint8_t headerFieldLlcSnap_t; ++ ++#define NET_HEADER_FIELD_LLC_SNAP_TYPE (1) ++#define NET_HEADER_FIELD_LLC_SNAP_ALL_FIELDS ((NET_HEADER_FIELD_LLC_SNAP_TYPE << 1) - 1) ++ ++#define NET_HEADER_FIELD_ARP_HTYPE (1) ++#define NET_HEADER_FIELD_ARP_PTYPE (NET_HEADER_FIELD_ARP_HTYPE << 1) ++#define NET_HEADER_FIELD_ARP_HLEN (NET_HEADER_FIELD_ARP_HTYPE << 2) ++#define NET_HEADER_FIELD_ARP_PLEN (NET_HEADER_FIELD_ARP_HTYPE << 3) ++#define NET_HEADER_FIELD_ARP_OPER (NET_HEADER_FIELD_ARP_HTYPE << 4) ++#define NET_HEADER_FIELD_ARP_SHA (NET_HEADER_FIELD_ARP_HTYPE << 5) ++#define NET_HEADER_FIELD_ARP_SPA (NET_HEADER_FIELD_ARP_HTYPE << 6) ++#define NET_HEADER_FIELD_ARP_THA (NET_HEADER_FIELD_ARP_HTYPE << 7) ++#define NET_HEADER_FIELD_ARP_TPA (NET_HEADER_FIELD_ARP_HTYPE << 8) ++#define NET_HEADER_FIELD_ARP_ALL_FIELDS ((NET_HEADER_FIELD_ARP_HTYPE << 9) - 1) ++ ++#define NET_HEADER_FIELD_RFC2684_LLC (1) ++#define NET_HEADER_FIELD_RFC2684_NLPID (NET_HEADER_FIELD_RFC2684_LLC << 1) ++#define NET_HEADER_FIELD_RFC2684_OUI (NET_HEADER_FIELD_RFC2684_LLC << 2) ++#define NET_HEADER_FIELD_RFC2684_PID (NET_HEADER_FIELD_RFC2684_LLC << 3) ++#define NET_HEADER_FIELD_RFC2684_VPN_OUI (NET_HEADER_FIELD_RFC2684_LLC << 4) ++#define NET_HEADER_FIELD_RFC2684_VPN_IDX (NET_HEADER_FIELD_RFC2684_LLC << 5) ++#define NET_HEADER_FIELD_RFC2684_ALL_FIELDS ((NET_HEADER_FIELD_RFC2684_LLC << 6) - 1) ++ ++#define NET_HEADER_FIELD_USER_DEFINED_SRCPORT (1) ++#define NET_HEADER_FIELD_USER_DEFINED_PCDID (NET_HEADER_FIELD_USER_DEFINED_SRCPORT << 1) ++#define NET_HEADER_FIELD_USER_DEFINED_ALL_FIELDS ((NET_HEADER_FIELD_USER_DEFINED_SRCPORT << 2) - 1) ++ ++#define NET_HEADER_FIELD_PAYLOAD_BUFFER (1) ++#define NET_HEADER_FIELD_PAYLOAD_SIZE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 1) ++#define NET_HEADER_FIELD_MAX_FRM_SIZE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 2) ++#define NET_HEADER_FIELD_MIN_FRM_SIZE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 3) ++#define NET_HEADER_FIELD_PAYLOAD_TYPE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 4) ++#define NET_HEADER_FIELD_FRAME_SIZE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 5) ++#define NET_HEADER_FIELD_PAYLOAD_ALL_FIELDS ((NET_HEADER_FIELD_PAYLOAD_BUFFER << 6) - 1) ++ ++ ++typedef uint8_t headerFieldGre_t; ++ ++#define NET_HEADER_FIELD_GRE_TYPE (1) ++#define NET_HEADER_FIELD_GRE_ALL_FIELDS ((NET_HEADER_FIELD_GRE_TYPE << 1) - 1) ++ ++ ++typedef uint8_t headerFieldMinencap_t; ++ ++#define NET_HEADER_FIELD_MINENCAP_SRC_IP (1) ++#define NET_HEADER_FIELD_MINENCAP_DST_IP (NET_HEADER_FIELD_MINENCAP_SRC_IP << 1) ++#define NET_HEADER_FIELD_MINENCAP_TYPE (NET_HEADER_FIELD_MINENCAP_SRC_IP << 2) ++#define NET_HEADER_FIELD_MINENCAP_ALL_FIELDS ((NET_HEADER_FIELD_MINENCAP_SRC_IP << 3) - 1) ++ ++ ++typedef uint8_t headerFieldIpsecAh_t; ++ ++#define NET_HEADER_FIELD_IPSEC_AH_SPI (1) ++#define NET_HEADER_FIELD_IPSEC_AH_NH (NET_HEADER_FIELD_IPSEC_AH_SPI << 1) ++#define NET_HEADER_FIELD_IPSEC_AH_ALL_FIELDS ((NET_HEADER_FIELD_IPSEC_AH_SPI << 2) - 1) ++ ++ ++typedef uint8_t headerFieldIpsecEsp_t; ++ ++#define NET_HEADER_FIELD_IPSEC_ESP_SPI (1) ++#define NET_HEADER_FIELD_IPSEC_ESP_SEQUENCE_NUM (NET_HEADER_FIELD_IPSEC_ESP_SPI << 1) ++#define NET_HEADER_FIELD_IPSEC_ESP_ALL_FIELDS ((NET_HEADER_FIELD_IPSEC_ESP_SPI << 2) - 1) ++ ++#define NET_HEADER_FIELD_IPSEC_ESP_SPI_SIZE 4 ++ ++ ++typedef uint8_t headerFieldMpls_t; ++ ++#define NET_HEADER_FIELD_MPLS_LABEL_STACK (1) ++#define NET_HEADER_FIELD_MPLS_LABEL_STACK_ALL_FIELDS ((NET_HEADER_FIELD_MPLS_LABEL_STACK << 1) - 1) ++ ++ ++typedef uint8_t headerFieldMacsec_t; ++ ++#define NET_HEADER_FIELD_MACSEC_SECTAG (1) ++#define NET_HEADER_FIELD_MACSEC_ALL_FIELDS ((NET_HEADER_FIELD_MACSEC_SECTAG << 1) - 1) ++ ++ ++typedef enum { ++ HEADER_TYPE_NONE = 0, ++ HEADER_TYPE_PAYLOAD, ++ HEADER_TYPE_ETH, ++ HEADER_TYPE_VLAN, ++ HEADER_TYPE_IPv4, ++ HEADER_TYPE_IPv6, ++ HEADER_TYPE_IP, ++ HEADER_TYPE_TCP, ++ HEADER_TYPE_UDP, ++ HEADER_TYPE_UDP_LITE, ++ HEADER_TYPE_IPHC, ++ HEADER_TYPE_SCTP, ++ HEADER_TYPE_SCTP_CHUNK_DATA, ++ HEADER_TYPE_PPPoE, ++ HEADER_TYPE_PPP, ++ HEADER_TYPE_PPPMUX, ++ HEADER_TYPE_PPPMUX_SUBFRAME, ++ HEADER_TYPE_L2TPv2, ++ HEADER_TYPE_L2TPv3_CTRL, ++ HEADER_TYPE_L2TPv3_SESS, ++ HEADER_TYPE_LLC, ++ HEADER_TYPE_LLC_SNAP, ++ HEADER_TYPE_NLPID, ++ HEADER_TYPE_SNAP, ++ HEADER_TYPE_MPLS, ++ HEADER_TYPE_IPSEC_AH, ++ HEADER_TYPE_IPSEC_ESP, ++ HEADER_TYPE_UDP_ENCAP_ESP, /* RFC 3948 */ ++ HEADER_TYPE_MACSEC, ++ HEADER_TYPE_GRE, ++ HEADER_TYPE_MINENCAP, ++ HEADER_TYPE_DCCP, ++ HEADER_TYPE_ICMP, ++ HEADER_TYPE_IGMP, ++ HEADER_TYPE_ARP, ++ HEADER_TYPE_CAPWAP, ++ HEADER_TYPE_CAPWAP_DTLS, ++ HEADER_TYPE_RFC2684, ++ HEADER_TYPE_USER_DEFINED_L2, ++ HEADER_TYPE_USER_DEFINED_L3, ++ HEADER_TYPE_USER_DEFINED_L4, ++ HEADER_TYPE_USER_DEFINED_SHIM1, ++ HEADER_TYPE_USER_DEFINED_SHIM2, ++ MAX_HEADER_TYPE_COUNT ++} e_NetHeaderType; ++ ++ ++#endif /* __NET_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/std_ext.h b/drivers/net/dpa/NetCommSw/inc/std_ext.h +new file mode 100644 +index 0000000..d91e6fd +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/std_ext.h +@@ -0,0 +1,48 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 std_ext.h ++ ++ @Description General Standard Definitions ++*//***************************************************************************/ ++ ++#ifndef __STD_EXT_H ++#define __STD_EXT_H ++ ++ ++#include "types_ext.h" ++#include "ncsw_ext.h" ++ ++ ++#endif /* __STD_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/stdarg_ext.h b/drivers/net/dpa/NetCommSw/inc/stdarg_ext.h +new file mode 100644 +index 0000000..3c8bb0a +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/stdarg_ext.h +@@ -0,0 +1,49 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __STDARG_EXT_H ++#define __STDARG_EXT_H ++ ++ ++#if defined(NCSW_LINUX) && defined(__KERNEL__) ++#include ++ ++#else ++#include ++ ++#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */ ++ ++#include "std_ext.h" ++ ++ ++#endif /* __STDARG_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/stdlib_ext.h b/drivers/net/dpa/NetCommSw/inc/stdlib_ext.h +new file mode 100644 +index 0000000..a47860c +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/stdlib_ext.h +@@ -0,0 +1,162 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __STDLIB_EXT_H ++#define __STDLIB_EXT_H ++ ++ ++#if (defined(NCSW_LINUX)) && defined(__KERNEL__) ++#include "stdarg_ext.h" ++#include "std_ext.h" ++ ++ ++/** ++ * strtoul - convert a string to an uint32_t ++ * @cp: The start of the string ++ * @endp: A pointer to the end of the parsed string will be placed here ++ * @base: The number base to use ++ */ ++uint32_t strtoul(const char *cp,char **endp,uint32_t base); ++ ++/** ++ * strtol - convert a string to a int32_t ++ * @cp: The start of the string ++ * @endp: A pointer to the end of the parsed string will be placed here ++ * @base: The number base to use ++ */ ++long strtol(const char *cp,char **endp,uint32_t base); ++ ++/** ++ * strtoull - convert a string to an uint64_t ++ * @cp: The start of the string ++ * @endp: A pointer to the end of the parsed string will be placed here ++ * @base: The number base to use ++ */ ++uint64_t strtoull(const char *cp,char **endp,uint32_t base); ++ ++/** ++ * strtoll - convert a string to a int64 long ++ * @cp: The start of the string ++ * @endp: A pointer to the end of the parsed string will be placed here ++ * @base: The number base to use ++ */ ++long long strtoll(const char *cp,char **endp,uint32_t base); ++ ++/** ++ * atoi - convert a character to a int ++ * @s: The start of the string ++ */ ++int atoi(const char *s); ++ ++/** ++ * strnlen - Find the length of a length-limited string ++ * @s: The string to be sized ++ * @count: The maximum number of bytes to search ++ */ ++size_t strnlen(const char * s, size_t count); ++ ++/** ++ * strlen - Find the length of a string ++ * @s: The string to be sized ++ */ ++size_t strlen(const char * s); ++ ++/** ++ * strtok - Split a string into tokens ++ * @s: The string to be searched ++ * @ct: The characters to search for ++ * ++ * WARNING: strtok is deprecated, use strsep instead. ++ */ ++char * strtok(char * s,const char * ct); ++ ++/** ++ * strncpy - Copy a length-limited, %NUL-terminated string ++ * @dest: Where to copy the string to ++ * @src: Where to copy the string from ++ * @count: The maximum number of bytes to copy ++ * ++ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer. ++ * However, the result is not %NUL-terminated if the source exceeds ++ * @count bytes. ++ */ ++char * strncpy(char * dest,const char *src,size_t count); ++ ++/** ++ * strcpy - Copy a %NUL terminated string ++ * @dest: Where to copy the string to ++ * @src: Where to copy the string from ++ */ ++char * strcpy(char * dest,const char *src); ++ ++/** ++ * vsscanf - Unformat a buffer into a list of arguments ++ * @buf: input buffer ++ * @fmt: format of buffer ++ * @args: arguments ++ */ ++int vsscanf(const char * buf, const char * fmt, va_list args); ++ ++/** ++ * vsnprintf - Format a string and place it in a buffer ++ * @buf: The buffer to place the result into ++ * @size: The size of the buffer, including the trailing null space ++ * @fmt: The format string to use ++ * @args: Arguments for the format string ++ * ++ * Call this function if you are already dealing with a va_list. ++ * You probably want snprintf instead. ++ */ ++int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); ++ ++/** ++ * vsprintf - Format a string and place it in a buffer ++ * @buf: The buffer to place the result into ++ * @fmt: The format string to use ++ * @args: Arguments for the format string ++ * ++ * Call this function if you are already dealing with a va_list. ++ * You probably want sprintf instead. ++ */ ++int vsprintf(char *buf, const char *fmt, va_list args); ++ ++#else ++#include ++#include ++#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */ ++ ++#include "std_ext.h" ++ ++ ++#endif /* __STDLIB_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/string_ext.h b/drivers/net/dpa/NetCommSw/inc/string_ext.h +new file mode 100644 +index 0000000..a5c6c7e +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/string_ext.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __STRING_EXT_H ++#define __STRING_EXT_H ++ ++ ++#if defined(NCSW_LINUX) && defined(__KERNEL__) ++#include ++#include ++extern char * strtok ( char * str, const char * delimiters ); ++ ++#elif defined(__KERNEL__) ++#include "linux/types.h" ++#include "linux/posix_types.h" ++#include "linux/string.h" ++ ++#else ++#include ++ ++#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */ ++ ++#include "std_ext.h" ++ ++ ++#endif /* __STRING_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/types_ext.h b/drivers/net/dpa/NetCommSw/inc/types_ext.h +new file mode 100644 +index 0000000..fd900e2 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/types_ext.h +@@ -0,0 +1,104 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 types_ext.h ++ ++ @Description General types Standard Definitions ++*//***************************************************************************/ ++ ++#ifndef __TYPES_EXT_H ++#define __TYPES_EXT_H ++ ++#if defined(NCSW_LINUX) ++#include "types_linux.h" ++ ++#elif defined(NCSW_VXWORKS) ++#include "types_vxworks.h" ++ ++#elif defined(__GNUC__) && defined(__cplusplus) ++#include "types_bb_gpp.h" ++ ++#elif defined(__GNUC__) ++#include "types_bb_gcc.h" ++ ++#elif defined(__ghs__) ++#include "types_ghs.h" ++ ++#else ++#include "types_dflt.h" ++#endif /* defined (__ROCOO__) */ ++ ++static __inline__ void TypesChecker(void) ++{ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ _Packed struct strct { ++ __volatile__ int vi; ++ } _PackedType; ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ size_t size = 0; ++ bool tr = TRUE, fls = FALSE; ++ struct strct *p_Struct = NULL; ++ physAddress_t addr = 0x100; ++ ++ tr = fls; ++ p_Struct = p_Struct; ++ size++; ++ if (tr) size++; ++ ++ WRITE_UINT8(*((uint8_t*)((size_t)(addr))), ++ GET_UINT8(*((uint8_t*)((size_t)(addr))))); ++ ++ WRITE_UINT8(*((uint8_t*)((size_t)(UINT8_MAX))), ++ GET_UINT8(*((uint8_t*)((size_t)(UINT8_MAX))))); ++ WRITE_UINT16(*((uint16_t*)((size_t)(UINT16_MAX))), ++ GET_UINT16(*((uint16_t*)((size_t)(UINT16_MAX))))); ++ WRITE_UINT32(*((uint32_t*)((size_t)(UINT32_MAX))), ++ GET_UINT32(*((uint32_t*)((size_t)(UINT32_MAX))))); ++ WRITE_UINT64(*((uint64_t*)((size_t)(UINT64_MAX))), ++ GET_UINT64(*((uint64_t*)((size_t)(UINT64_MAX))))); ++ WRITE_UINT8(*((uint8_t*)((size_t)(INT8_MAX))), ++ GET_UINT8(*((uint8_t*)((size_t)(INT8_MIN))))); ++ WRITE_UINT16(*((uint16_t*)((size_t)(INT16_MAX))), ++ GET_UINT16(*((uint16_t*)((size_t)(INT16_MIN))))); ++ WRITE_UINT32(*((uint32_t*)((size_t)(INT32_MAX))), ++ GET_UINT32(*((uint32_t*)((size_t)(INT32_MIN))))); ++ WRITE_UINT64(*((uint64_t*)((size_t)(INT64_MAX))), ++ GET_UINT64(*((uint64_t*)((size_t)(INT64_MIN))))); ++} ++ ++#endif /* __TYPES_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/xx_common.h b/drivers/net/dpa/NetCommSw/inc/xx_common.h +new file mode 100644 +index 0000000..1c45177 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/xx_common.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 debug_ext.h ++ ++ @Description Debug mode definitions. ++*//***************************************************************************/ ++ ++#ifndef __XX_COMMON_H ++#define __XX_COMMON_H ++ ++/***************************************************************************** ++ * UNIFIED MODULE CODES ++ *****************************************************************************/ ++#define MODULE_UNKNOWN 0x00000000 ++#define MODULE_FM 0x00010000 ++#define MODULE_FM_MURAM 0x00020000 ++#define MODULE_FM_PCD 0x00030000 ++#define MODULE_FM_RTC 0x00040000 ++#define MODULE_FM_MAC 0x00050000 ++#define MODULE_FM_PORT 0x00060000 ++#define MODULE_MM 0x00070000 ++#define MODULE_FM_SP 0x00080000 ++ ++#endif /* __XX_COMMON_H */ +diff --git a/drivers/net/dpa/NetCommSw/inc/xx_ext.h b/drivers/net/dpa/NetCommSw/inc/xx_ext.h +new file mode 100644 +index 0000000..21b62d0 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/inc/xx_ext.h +@@ -0,0 +1,791 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 xx_ext.h ++ ++ @Description Prototypes, externals and typedefs for system-supplied ++ (external) routines ++*//***************************************************************************/ ++ ++#ifndef __XX_EXT_H ++#define __XX_EXT_H ++ ++#include "std_ext.h" ++#include "xx_common.h" ++#include "part_ext.h" ++ ++ ++ ++/**************************************************************************//** ++ @Group xx_id XX Interface (System call hooks) ++ ++ @Description Prototypes, externals and typedefs for system-supplied ++ (external) routines ++ ++ @{ ++*//***************************************************************************/ ++ ++#ifdef DEBUG_XX_MALLOC ++void * XX_MallocDebug(uint32_t size, char *fname, int line); ++ ++void * XX_MallocSmartDebug(uint32_t size, ++ int memPartitionId, ++ uint32_t alignment, ++ char *fname, ++ int line); ++ ++#define XX_Malloc(sz) \ ++ XX_MallocDebug((sz), __FILE__, __LINE__) ++ ++#define XX_MallocSmart(sz, memt, al) \ ++ XX_MallocSmartDebug((sz), (memt), (al), __FILE__, __LINE__) ++ ++#else /* not DEBUG_XX_MALLOC */ ++/**************************************************************************//** ++ @Function XX_Malloc ++ ++ @Description allocates contiguous block of memory. ++ ++ @Param[in] size - Number of bytes to allocate. ++ ++ @Return The address of the newly allocated block on success, NULL on failure. ++*//***************************************************************************/ ++void * XX_Malloc(uint32_t size); ++ ++/**************************************************************************//** ++ @Function XX_MallocSmart ++ ++ @Description Allocates contiguous block of memory in a specified ++ alignment and from the specified segment. ++ ++ @Param[in] size - Number of bytes to allocate. ++ @Param[in] memPartitionId - Memory partition ID; The value zero must ++ be mapped to the default heap partition. ++ @Param[in] alignment - Required memory alignment (in bytes). ++ ++ @Return The address of the newly allocated block on success, NULL on failure. ++*//***************************************************************************/ ++void * XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment); ++#endif /* not DEBUG_XX_MALLOC */ ++ ++/**************************************************************************//** ++ @Function XX_FreeSmart ++ ++ @Description Frees the memory block pointed to by "p". ++ Only for memory allocated by XX_MallocSmart ++ ++ @Param[in] p_Memory - pointer to the memory block. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_FreeSmart(void *p_Memory); ++ ++/**************************************************************************//** ++ @Function XX_Free ++ ++ @Description frees the memory block pointed to by "p". ++ ++ @Param[in] p_Memory - pointer to the memory block. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_Free(void *p_Memory); ++ ++/**************************************************************************//** ++ @Function XX_Print ++ ++ @Description print a string. ++ ++ @Param[in] str - string to print. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_Print(char *str, ...); ++ ++/**************************************************************************//** ++ @Function XX_SetIntr ++ ++ @Description Set an interrupt service routine for a specific interrupt source. ++ ++ @Param[in] irq - Interrupt ID (system-specific number). ++ @Param[in] f_Isr - Callback routine that will be called when the interrupt occurs. ++ @Param[in] handle - The argument for the user callback routine. ++ ++ @Return E_OK on success; error code otherwise.. ++*//***************************************************************************/ ++t_Error XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle); ++ ++/**************************************************************************//** ++ @Function XX_FreeIntr ++ ++ @Description Free a specific interrupt and a specific callback routine. ++ ++ @Param[in] irq - Interrupt ID (system-specific number). ++ ++ @Return E_OK on success; error code otherwise.. ++*//***************************************************************************/ ++t_Error XX_FreeIntr(int irq); ++ ++/**************************************************************************//** ++ @Function XX_EnableIntr ++ ++ @Description Enable a specific interrupt. ++ ++ @Param[in] irq - Interrupt ID (system-specific number). ++ ++ @Return E_OK on success; error code otherwise.. ++*//***************************************************************************/ ++t_Error XX_EnableIntr(int irq); ++ ++/**************************************************************************//** ++ @Function XX_DisableIntr ++ ++ @Description Disable a specific interrupt. ++ ++ @Param[in] irq - Interrupt ID (system-specific number). ++ ++ @Return E_OK on success; error code otherwise.. ++*//***************************************************************************/ ++t_Error XX_DisableIntr(int irq); ++ ++/**************************************************************************//** ++ @Function XX_DisableAllIntr ++ ++ @Description Disable all interrupts by masking them at the CPU. ++ ++ @Return A value that represents the interrupts state before the ++ operation, and should be passed to the matching ++ XX_RestoreAllIntr() call. ++*//***************************************************************************/ ++uint32_t XX_DisableAllIntr(void); ++ ++/**************************************************************************//** ++ @Function XX_RestoreAllIntr ++ ++ @Description Restore previous state of interrupts level at the CPU. ++ ++ @Param[in] flags - A value that represents the interrupts state to restore, ++ as returned by the matching call for XX_DisableAllIntr(). ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_RestoreAllIntr(uint32_t flags); ++ ++ ++/**************************************************************************//** ++ @Function XX_Exit ++ ++ @Description Stop execution and report status (where it is applicable) ++ ++ @Param[in] status - exit status ++*//***************************************************************************/ ++void XX_Exit(int status); ++ ++ ++/*****************************************************************************/ ++/* Tasklet Service Routines */ ++/*****************************************************************************/ ++typedef t_Handle t_TaskletHandle; ++ ++/**************************************************************************//** ++ @Function XX_InitTasklet ++ ++ @Description Create and initialize a tasklet object. ++ ++ @Param[in] routine - A routine to be ran as a tasklet. ++ @Param[in] data - An argument to pass to the tasklet. ++ ++ @Return Tasklet handle is returned on success. NULL is returned otherwise. ++*//***************************************************************************/ ++t_TaskletHandle XX_InitTasklet (void (*routine)(void *), void *data); ++ ++/**************************************************************************//** ++ @Function XX_FreeTasklet ++ ++ @Description Free a tasklet object. ++ ++ @Param[in] h_Tasklet - A handle to a tasklet to be free. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_FreeTasklet (t_TaskletHandle h_Tasklet); ++ ++/**************************************************************************//** ++ @Function XX_ScheduleTask ++ ++ @Description Schedule a tasklet object. ++ ++ @Param[in] h_Tasklet - A handle to a tasklet to be scheduled. ++ @Param[in] immediate - Indicate whether to schedule this tasklet on ++ the immediate queue or on the delayed one. ++ ++ @Return 0 - on success. Error code - otherwise. ++*//***************************************************************************/ ++int XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate); ++ ++/**************************************************************************//** ++ @Function XX_FlushScheduledTasks ++ ++ @Description Flush all tasks there are in the scheduled tasks queue. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_FlushScheduledTasks(void); ++ ++/**************************************************************************//** ++ @Function XX_TaskletIsQueued ++ ++ @Description Check if task is queued. ++ ++ @Param[in] h_Tasklet - A handle to a tasklet to be scheduled. ++ ++ @Return 1 - task is queued. 0 - otherwise. ++*//***************************************************************************/ ++int XX_TaskletIsQueued(t_TaskletHandle h_Tasklet); ++ ++/**************************************************************************//** ++ @Function XX_SetTaskletData ++ ++ @Description Set data to a scheduled task. Used to change data of already ++ scheduled task. ++ ++ @Param[in] h_Tasklet - A handle to a tasklet to be scheduled. ++ @Param[in] data - Data to be set. ++*//***************************************************************************/ ++void XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data); ++ ++/**************************************************************************//** ++ @Function XX_GetTaskletData ++ ++ @Description Get the data of scheduled task. ++ ++ @Param[in] h_Tasklet - A handle to a tasklet to be scheduled. ++ ++ @Return handle to the data of the task. ++*//***************************************************************************/ ++t_Handle XX_GetTaskletData(t_TaskletHandle h_Tasklet); ++ ++/**************************************************************************//** ++ @Function XX_BottomHalf ++ ++ @Description Bottom half implementation, invoked by the interrupt handler. ++ ++ This routine handles all bottom-half tasklets with interrupts ++ enabled. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_BottomHalf(void); ++ ++ ++/*****************************************************************************/ ++/* Spinlock Service Routines */ ++/*****************************************************************************/ ++ ++/**************************************************************************//** ++ @Function XX_InitSpinlock ++ ++ @Description Creates a spinlock. ++ ++ @Return Spinlock handle is returned on success; NULL otherwise. ++*//***************************************************************************/ ++t_Handle XX_InitSpinlock(void); ++ ++/**************************************************************************//** ++ @Function XX_FreeSpinlock ++ ++ @Description Frees the memory allocated for the spinlock creation. ++ ++ @Param[in] h_Spinlock - A handle to a spinlock. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_FreeSpinlock(t_Handle h_Spinlock); ++ ++/**************************************************************************//** ++ @Function XX_LockSpinlock ++ ++ @Description Locks a spinlock. ++ ++ @Param[in] h_Spinlock - A handle to a spinlock. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_LockSpinlock(t_Handle h_Spinlock); ++ ++/**************************************************************************//** ++ @Function XX_UnlockSpinlock ++ ++ @Description Unlocks a spinlock. ++ ++ @Param[in] h_Spinlock - A handle to a spinlock. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_UnlockSpinlock(t_Handle h_Spinlock); ++ ++/**************************************************************************//** ++ @Function XX_LockIntrSpinlock ++ ++ @Description Locks a spinlock (interrupt safe). ++ ++ @Param[in] h_Spinlock - A handle to a spinlock. ++ ++ @Return A value that represents the interrupts state before the ++ operation, and should be passed to the matching ++ XX_UnlockIntrSpinlock() call. ++*//***************************************************************************/ ++uint32_t XX_LockIntrSpinlock(t_Handle h_Spinlock); ++ ++/**************************************************************************//** ++ @Function XX_UnlockIntrSpinlock ++ ++ @Description Unlocks a spinlock (interrupt safe). ++ ++ @Param[in] h_Spinlock - A handle to a spinlock. ++ @Param[in] intrFlags - A value that represents the interrupts state to ++ restore, as returned by the matching call for ++ XX_LockIntrSpinlock(). ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags); ++ ++ ++/*****************************************************************************/ ++/* Timers Service Routines */ ++/*****************************************************************************/ ++ ++/**************************************************************************//** ++ @Function XX_CurrentTime ++ ++ @Description Returns current system time. ++ ++ @Return Current system time (in milliseconds). ++*//***************************************************************************/ ++uint32_t XX_CurrentTime(void); ++ ++/**************************************************************************//** ++ @Function XX_CreateTimer ++ ++ @Description Creates a timer. ++ ++ @Return Timer handle is returned on success; NULL otherwise. ++*//***************************************************************************/ ++t_Handle XX_CreateTimer(void); ++ ++/**************************************************************************//** ++ @Function XX_FreeTimer ++ ++ @Description Frees the memory allocated for the timer creation. ++ ++ @Param[in] h_Timer - A handle to a timer. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_FreeTimer(t_Handle h_Timer); ++ ++/**************************************************************************//** ++ @Function XX_StartTimer ++ ++ @Description Starts a timer. ++ ++ The user can select to start the timer as periodic timer or as ++ one-shot timer. The user should provide a callback routine that ++ will be called when the timer expires. ++ ++ @Param[in] h_Timer - A handle to a timer. ++ @Param[in] msecs - Timer expiration period (in milliseconds). ++ @Param[in] periodic - TRUE for a periodic timer; ++ FALSE for a one-shot timer.. ++ @Param[in] f_TimerExpired - A callback routine to be called when the ++ timer expires. ++ @Param[in] h_Arg - The argument to pass in the timer-expired ++ callback routine. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_StartTimer(t_Handle h_Timer, ++ uint32_t msecs, ++ bool periodic, ++ void (*f_TimerExpired)(t_Handle h_Arg), ++ t_Handle h_Arg); ++ ++/**************************************************************************//** ++ @Function XX_StopTimer ++ ++ @Description Frees the memory allocated for the timer creation. ++ ++ @Param[in] h_Timer - A handle to a timer. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_StopTimer(t_Handle h_Timer); ++ ++/**************************************************************************//** ++ @Function XX_ModTimer ++ ++ @Description Updates the expiration time of a timer. ++ ++ This routine adds the given time to the current system time, ++ and sets this value as the new expiration time of the timer. ++ ++ @Param[in] h_Timer - A handle to a timer. ++ @Param[in] msecs - The new interval until timer expiration ++ (in milliseconds). ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_ModTimer(t_Handle h_Timer, uint32_t msecs); ++ ++/**************************************************************************//** ++ @Function XX_Sleep ++ ++ @Description Non-busy wait until the desired time (in milliseconds) has passed. ++ ++ @Param[in] msecs - The requested sleep time (in milliseconds). ++ ++ @Return Zero if the requested time has elapsed; Otherwise, the value ++ returned will be the unslept amount) in milliseconds. ++ ++ @Cautions This routine enables interrupts during its wait time. ++*//***************************************************************************/ ++uint32_t XX_Sleep(uint32_t msecs); ++ ++/**************************************************************************//** ++ @Function XX_UDelay ++ ++ @Description Busy-wait until the desired time (in microseconds) has passed. ++ ++ @Param[in] usecs - The requested delay time (in microseconds). ++ ++ @Return None. ++ ++ @Cautions It is highly unrecommended to call this routine during interrupt ++ time, because the system time may not be updated properly during ++ the delay loop. The behavior of this routine during interrupt ++ time is unexpected. ++*//***************************************************************************/ ++void XX_UDelay(uint32_t usecs); ++ ++ ++/*****************************************************************************/ ++/* Other Service Routines */ ++/*****************************************************************************/ ++ ++/**************************************************************************//** ++ @Function XX_PhysToVirt ++ ++ @Description Translates a physical address to the matching virtual address. ++ ++ @Param[in] addr - The physical address to translate. ++ ++ @Return Virtual address. ++*//***************************************************************************/ ++void * XX_PhysToVirt(physAddress_t addr); ++ ++/**************************************************************************//** ++ @Function XX_VirtToPhys ++ ++ @Description Translates a virtual address to the matching physical address. ++ ++ @Param[in] addr - The virtual address to translate. ++ ++ @Return Physical address. ++*//***************************************************************************/ ++physAddress_t XX_VirtToPhys(void *addr); ++ ++ ++/**************************************************************************//** ++ @Group xx_ipc XX Inter-Partition-Communication API ++ ++ @Description The following API is to be used when working with multiple ++ partitions configuration. ++ ++ @{ ++*//***************************************************************************/ ++ ++#define XX_IPC_MAX_ADDR_NAME_LENGTH 16 /**< Maximum length of an endpoint name string; ++ The IPC service can use this constant to limit ++ the storage space for IPC endpoint names. */ ++ ++ ++/**************************************************************************//** ++ @Function t_IpcMsgCompletion ++ ++ @Description Callback function used upon IPC non-blocking transaction completion ++ to return message buffer to the caller and to forward reply if available. ++ ++ This callback function may be attached by the source endpoint to any outgoing ++ IPC message to indicate a non-blocking send (see also XX_IpcSendMessage() routine). ++ Upon completion of an IPC transaction (consisting of a message and an optional reply), ++ the IPC service invokes this callback routine to return the message buffer to the sender ++ and to provide the received reply, if requested. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_Module - Abstract handle to the sending module - the same handle as was passed ++ in the XX_IpcSendMessage() function; This handle is typically used to point ++ to the internal data structure of the source endpoint. ++ @Param[in] p_Msg - Pointer to original (sent) message buffer; ++ The source endpoint can free (or reuse) this buffer when message ++ completion callback is called. ++ @Param[in] p_Reply - Pointer to (received) reply buffer; ++ This pointer is the same as was provided by the source endpoint in ++ XX_IpcSendMessage(). ++ @Param[in] replyLength - Length (in bytes) of actual data in the reply buffer. ++ @Param[in] status - Completion status - E_OK or failure indication, e.g. IPC transaction completion ++ timeout. ++ ++ @Return None ++ *//***************************************************************************/ ++typedef void (t_IpcMsgCompletion)(t_Handle h_Module, ++ uint8_t *p_Msg, ++ uint8_t *p_Reply, ++ uint32_t replyLength, ++ t_Error status); ++ ++/**************************************************************************//** ++ @Function t_IpcMsgHandler ++ ++ @Description Callback function used as IPC message handler. ++ ++ The IPC service invokes message handlers for each IPC message received. ++ The actual function pointer should be registered by each destination endpoint ++ via the XX_IpcRegisterMsgHandler() routine. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_Module - Abstract handle to the message handling module - the same handle as ++ was passed in the XX_IpcRegisterMsgHandler() function; this handle is ++ typically used to point to the internal data structure of the destination ++ endpoint. ++ @Param[in] p_Msg - Pointer to message buffer with data received from peer. ++ @Param[in] msgLength - Length (in bytes) of message data. ++ @Param[in] p_Reply - Pointer to reply buffer, to be filled by the message handler and then sent ++ by the IPC service; ++ The reply buffer is allocated by the IPC service with size equals to the ++ replyLength parameter provided in message handler registration (see ++ XX_IpcRegisterMsgHandler() function); ++ If replyLength was initially specified as zero during message handler registration, ++ the IPC service may set this pointer to NULL and assume that a reply is not needed; ++ The IPC service is also responsible for freeing the reply buffer after the ++ reply has been sent or dismissed. ++ @Param[in,out] p_ReplyLength - Pointer to reply length, which has a dual role in this function: ++ [In] equals the replyLength parameter provided in message handler ++ registration (see XX_IpcRegisterMsgHandler() function), and ++ [Out] should be updated by message handler to the actual reply length; if ++ this value is set to zero, the IPC service must assume that a reply should ++ not be sent; ++ Note: If p_Reply is not NULL, p_ReplyLength must not be NULL as well. ++ ++ @Return E_OK on success; Error code otherwise. ++ *//***************************************************************************/ ++typedef t_Error (t_IpcMsgHandler)(t_Handle h_Module, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength); ++ ++/**************************************************************************//** ++ @Function XX_IpcRegisterMsgHandler ++ ++ @Description IPC mailbox registration. ++ ++ This function is used for registering an IPC message handler in the IPC service. ++ This function is called by each destination endpoint to indicate that it is ready ++ to handle incoming messages. The IPC service invokes the message handler upon receiving ++ a message addressed to the specified destination endpoint. ++ ++ @Param[in] addr - The address name string associated with the destination endpoint; ++ This address must be unique across the IPC service domain to ensure ++ correct message routing. ++ @Param[in] f_MsgHandler - Pointer to the message handler callback for processing incoming ++ message; invoked by the IPC service upon receiving a message ++ addressed to the destination endpoint specified by the addr ++ parameter. ++ @Param[in] h_Module - Abstract handle to the message handling module, passed unchanged ++ to f_MsgHandler callback function. ++ @Param[in] replyLength - The maximal data length (in bytes) of any reply that the specified message handler ++ may generate; the IPC service provides the message handler with buffer ++ for reply according to the length specified here (refer also to the description ++ of #t_IpcMsgHandler callback function type); ++ This size shall be zero if the message handler never generates replies. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH], ++ t_IpcMsgHandler *f_MsgHandler, ++ t_Handle h_Module, ++ uint32_t replyLength); ++ ++/**************************************************************************//** ++ @Function XX_IpcUnregisterMsgHandler ++ ++ @Description Release IPC mailbox routine. ++ ++ This function is used for unregistering an IPC message handler from the IPC service. ++ This function is called by each destination endpoint to indicate that it is no longer ++ capable of handling incoming messages. ++ ++ @Param[in] addr - The address name string associated with the destination endpoint; ++ This address is the same as was used when the message handler was ++ registered via XX_IpcRegisterMsgHandler(). ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH]); ++ ++/**************************************************************************//** ++ @Function XX_IpcInitSession ++ ++ @Description This function is used for creating an IPC session between the source endpoint ++ and the destination endpoint. ++ ++ The actual implementation and representation of a session is left for the IPC service. ++ The function returns an abstract handle to the created session. This handle shall be used ++ by the source endpoint in subsequent calls to XX_IpcSendMessage(). ++ The IPC service assumes that before this function is called, no messages are sent from ++ the specified source endpoint to the specified destination endpoint. ++ ++ The IPC service may use a connection-oriented approach or a connectionless approach (or both) ++ as described below. ++ ++ @par Connection-Oriented Approach ++ ++ The IPC service may implement a session in a connection-oriented approach - when this function is called, ++ the IPC service should take the necessary steps to bring up a source-to-destination channel for messages ++ and a destination-to-source channel for replies. The returned handle should represent the internal ++ representation of these channels. ++ ++ @par Connectionless Approach ++ ++ The IPC service may implement a session in a connectionless approach - when this function is called, the ++ IPC service should not perform any particular steps, but it must store the pair of source and destination ++ addresses in some session representation and return it as a handle. When XX_IpcSendMessage() shall be ++ called, the IPC service may use this handle to provide the necessary identifiers for routing the messages ++ through the connectionless medium. ++ ++ @Param[in] destAddr - The address name string associated with the destination endpoint. ++ @Param[in] srcAddr - The address name string associated with the source endpoint. ++ ++ @Return Abstract handle to the initialized session, or NULL on error. ++*//***************************************************************************/ ++t_Handle XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH], ++ char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH]); ++ ++/**************************************************************************//** ++ @Function XX_IpcFreeSession ++ ++ @Description This function is used for terminating an existing IPC session between a source endpoint ++ and a destination endpoint. ++ ++ The IPC service assumes that after this function is called, no messages shall be sent from ++ the associated source endpoint to the associated destination endpoint. ++ ++ @Param[in] h_Session - Abstract handle to the IPC session - the same handle as was originally ++ returned by the XX_IpcInitSession() function. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error XX_IpcFreeSession(t_Handle h_Session); ++ ++/**************************************************************************//** ++ @Function XX_IpcSendMessage ++ ++ @Description IPC message send routine. ++ ++ This function may be used by a source endpoint to send an IPC message to a destination ++ endpoint. The source endpoint cannot send a message to the destination endpoint without ++ first initiating a session with that destination endpoint via XX_IpcInitSession() routine. ++ ++ The source endpoint must provide the buffer pointer and length of the outgoing message. ++ Optionally, it may also provide a buffer for an expected reply. In the latter case, the ++ transaction is not considered complete by the IPC service until the reply has been received. ++ If the source endpoint does not provide a reply buffer, the transaction is considered ++ complete after the message has been sent. The source endpoint must keep the message (and ++ optional reply) buffers valid until the transaction is complete. ++ ++ @par Non-blocking mode ++ ++ The source endpoint may request a non-blocking send by providing a non-NULL pointer to a message ++ completion callback function (f_Completion). Upon completion of the IPC transaction (consisting of a ++ message and an optional reply), the IPC service invokes this callback routine to return the message ++ buffer to the sender and to provide the received reply, if requested. ++ ++ @par Blocking mode ++ ++ The source endpoint may request a blocking send by setting f_Completion to NULL. The function is ++ expected to block until the IPC transaction is complete - either the reply has been received or (if no reply ++ was requested) the message has been sent. ++ ++ @Param[in] h_Session - Abstract handle to the IPC session - the same handle as was originally ++ returned by the XX_IpcInitSession() function. ++ @Param[in] p_Msg - Pointer to message buffer to send. ++ @Param[in] msgLength - Length (in bytes) of actual data in the message buffer. ++ @Param[in] p_Reply - Pointer to reply buffer - if this buffer is not NULL, the IPC service ++ fills this buffer with the received reply data; ++ In blocking mode, the reply data must be valid when the function returns; ++ In non-blocking mode, the reply data is valid when f_Completion is called; ++ If this pointer is NULL, no reply is expected. ++ @Param[in,out] p_ReplyLength - Pointer to reply length, which has a dual role in this function: ++ [In] specifies the maximal length (in bytes) of the reply buffer pointed by ++ p_Reply, and ++ [Out] in non-blocking mode this value is updated by the IPC service to the ++ actual reply length (in bytes). ++ @Param[in] f_Completion - Pointer to a completion callback to be used in non-blocking send mode; ++ The completion callback is invoked by the IPC service upon ++ completion of the IPC transaction (consisting of a message and an optional ++ reply); ++ If this pointer is NULL, the function is expected to block until the IPC ++ transaction is complete. ++ @Param[in] h_Arg - Abstract handle to the sending module; passed unchanged to the f_Completion ++ callback function as the first argument. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error XX_IpcSendMessage(t_Handle h_Session, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength, ++ t_IpcMsgCompletion *f_Completion, ++ t_Handle h_Arg); ++ ++ ++/** @} */ /* end of xx_ipc group */ ++/** @} */ /* end of xx_id group */ ++ ++ ++#endif /* __XX_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/ncsw_config.mk b/drivers/net/dpa/NetCommSw/ncsw_config.mk +new file mode 100644 +index 0000000..0f025f5 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/ncsw_config.mk +@@ -0,0 +1,41 @@ ++# ++# Makefile config for the Freescale NetcommSW ++# ++NET_DPA = $(srctree)/drivers/net ++DRV_DPA = $(srctree)/drivers/net/dpa ++NCSW = $(srctree)/drivers/net/dpa/NetCommSw ++ ++ifeq ("$(CONFIG_FMAN_P3040_P4080_P5020)", "y") ++EXTRA_CFLAGS +=-include $(NCSW)/p3040_4080_5020_dflags.h ++endif ++ifeq ("$(CONFIG_FMAN_P1023)", "y") ++EXTRA_CFLAGS +=-include $(NCSW)/p1023_dflags.h ++endif ++ifdef CONFIG_FMAN_T4240 ++EXTRA_CFLAGS +=-include $(NCSW)/t4240_dflags.h ++endif ++ ++EXTRA_CFLAGS += -I$(DRV_DPA)/ ++EXTRA_CFLAGS += -I$(NCSW)/inc ++EXTRA_CFLAGS += -I$(NCSW)/inc/cores ++EXTRA_CFLAGS += -I$(NCSW)/inc/etc ++EXTRA_CFLAGS += -I$(NCSW)/inc/Peripherals ++EXTRA_CFLAGS += -I$(NCSW)/inc/flib ++ ++ifeq ("$(CONFIG_FMAN_P3040_P4080_P5020)", "y") ++EXTRA_CFLAGS += -I$(NCSW)/inc/integrations/P3040_P4080_P5020 ++endif ++ifeq ("$(CONFIG_FMAN_P1023)", "y") ++EXTRA_CFLAGS += -I$(NCSW)/inc/integrations/P1023 ++endif ++ifdef CONFIG_FMAN_T4240 ++EXTRA_CFLAGS += -I$(NCSW)/inc/integrations/T4240 ++endif ++ ++EXTRA_CFLAGS += -I$(NCSW)/src/inc ++EXTRA_CFLAGS += -I$(NCSW)/src/inc/system ++EXTRA_CFLAGS += -I$(NCSW)/src/inc/wrapper ++EXTRA_CFLAGS += -I$(NCSW)/src/inc/xx ++EXTRA_CFLAGS += -I$(srctree)/include/linux/fmd ++EXTRA_CFLAGS += -I$(srctree)/include/linux/fmd/Peripherals ++EXTRA_CFLAGS += -I$(srctree)/include/linux/fmd/integrations +diff --git a/drivers/net/dpa/NetCommSw/p1023_dflags.h b/drivers/net/dpa/NetCommSw/p1023_dflags.h +new file mode 100644 +index 0000000..b48819d +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/p1023_dflags.h +@@ -0,0 +1,65 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __dflags_h ++#define __dflags_h ++ ++ ++#define NCSW_LINUX ++#if 0 ++#define DEBUG ++#endif ++ ++#define P1023 ++#define NCSW_PPC_CORE ++ ++#define DEBUG_ERRORS 1 ++ ++#if defined(DEBUG) ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_INFO ++ ++#define DEBUG_XX_MALLOC ++#define DEBUG_MEM_LEAKS ++ ++#else ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING ++#endif /* (DEBUG) */ ++ ++#define REPORT_EVENTS 1 ++#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR ++ ++#ifdef CONFIG_P4080_SIM ++#error "Do not define CONFIG_P4080_SIM..." ++#endif ++ ++ ++#endif /* __dflags_h */ +diff --git a/drivers/net/dpa/NetCommSw/p3040_4080_5020_dflags.h b/drivers/net/dpa/NetCommSw/p3040_4080_5020_dflags.h +new file mode 100644 +index 0000000..7438974 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/p3040_4080_5020_dflags.h +@@ -0,0 +1,62 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __dflags_h ++#define __dflags_h ++ ++ ++#define NCSW_LINUX ++ ++#define P4080 ++#define NCSW_PPC_CORE ++ ++#define DEBUG_ERRORS 1 ++ ++#if defined(DEBUG) ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_INFO ++ ++#define DEBUG_XX_MALLOC ++#define DEBUG_MEM_LEAKS ++ ++#else ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING ++#endif /* (DEBUG) */ ++ ++#define REPORT_EVENTS 1 ++#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR ++ ++#ifdef CONFIG_P4080_SIM ++#define SIMULATOR ++#endif /* CONFIG_P4080_SIM */ ++ ++ ++#endif /* __dflags_h */ +diff --git a/drivers/net/dpa/NetCommSw/src/Makefile b/drivers/net/dpa/NetCommSw/src/Makefile +new file mode 100644 +index 0000000..e02b6fa +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/Makefile +@@ -0,0 +1,11 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++# ++obj-y += system/ ++obj-y += wrapper/ ++obj-y += xx/ +diff --git a/drivers/net/dpa/NetCommSw/src/inc/system/sys_ext.h b/drivers/net/dpa/NetCommSw/src/inc/system/sys_ext.h +new file mode 100644 +index 0000000..20f27d2 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/inc/system/sys_ext.h +@@ -0,0 +1,118 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __SYS_EXT_H ++#define __SYS_EXT_H ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group sys_grp System Interfaces ++ ++ @Description Linux system programming interfaces. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group sys_gen_grp System General Interface ++ ++ @Description General definitions, structures and routines of the linux ++ system programming interface. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection Macros for Advanced Configuration Requests ++ @{ ++*//***************************************************************************/ ++#define SYS_MAX_ADV_CONFIG_ARGS 4 ++ /**< Maximum number of arguments in ++ an advanced configuration entry */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description System Object Advanced Configuration Entry ++ ++ This structure represents a single request for an advanced ++ configuration call on the initialized object. An array of such ++ requests may be contained in the settings structure of the ++ corresponding object. ++ ++ The maximum number of arguments is limited to #SYS_MAX_ADV_CONFIG_ARGS. ++*//***************************************************************************/ ++typedef struct t_SysObjectAdvConfigEntry ++{ ++ void *p_Function; /**< Pointer to advanced configuration routine */ ++ ++ uintptr_t args[SYS_MAX_ADV_CONFIG_ARGS]; ++ /**< Array of arguments for the specified routine; ++ All arguments should be casted to uint32_t. */ ++} t_SysObjectAdvConfigEntry; ++ ++ ++/** @} */ /* end of sys_gen_grp */ ++/** @} */ /* end of sys_grp */ ++ ++#define NCSW_PARAMS(_num, _params) ADV_CONFIG_PARAMS_##_num _params ++ ++#define ADV_CONFIG_PARAMS_1(_type) \ ++ , (_type)p_Entry->args[0] ++ ++#define SET_ADV_CONFIG_ARGS_1(_arg0) \ ++ p_Entry->args[0] = (uintptr_t )(_arg0); \ ++ ++#define ARGS(_num, _params) SET_ADV_CONFIG_ARGS_##_num _params ++ ++#define ADD_ADV_CONFIG_START(_p_Entries, _maxEntries) \ ++ { \ ++ t_SysObjectAdvConfigEntry *p_Entry; \ ++ t_SysObjectAdvConfigEntry *p_Entrys = (_p_Entries); \ ++ int i=0, max = (_maxEntries); \ ++ ++#define ADD_ADV_CONFIG_END \ ++ } ++ ++#define ADV_CONFIG_CHECK_START(_p_Entry) \ ++ { \ ++ t_SysObjectAdvConfigEntry *p_Entry = _p_Entry; \ ++ t_Error errCode; \ ++ ++#define ADV_CONFIG_CHECK(_handle, _func, _params) \ ++ if (p_Entry->p_Function == _func) \ ++ { \ ++ errCode = _func(_handle _params); \ ++ } else ++ ++#endif /* __SYS_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/src/inc/system/sys_io_ext.h b/drivers/net/dpa/NetCommSw/src/inc/system/sys_io_ext.h +new file mode 100644 +index 0000000..d6aa9d4 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/inc/system/sys_io_ext.h +@@ -0,0 +1,46 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __SYS_IO_EXT_H ++#define __SYS_IO_EXT_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++ ++ ++t_Error SYS_RegisterIoMap (uint64_t virtAddr, uint64_t physAddr, uint32_t size); ++t_Error SYS_UnregisterIoMap (uint64_t virtAddr); ++uint64_t SYS_PhysToVirt (uint64_t addr); ++uint64_t SYS_VirtToPhys (uint64_t addr); ++ ++ ++#endif /* __SYS_IO_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/src/inc/types_linux.h b/drivers/net/dpa/NetCommSw/src/inc/types_linux.h +new file mode 100644 +index 0000000..ac15d66 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/inc/types_linux.h +@@ -0,0 +1,200 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __TYPES_LINUX_H__ ++#define __TYPES_LINUX_H__ ++ ++#include ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ++ #error "This kernel is probably not supported!!!" ++#elif (!((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) || \ ++ (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27)) || \ ++ (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,30)))) ++ #warning "This kernel is probably not supported!!! You may need to add some fixes." ++#endif /* LINUX_VERSION_CODE */ ++ ++ ++typedef float float_t; /* Single precision floating point */ ++typedef double double_t; /* Double precision floating point */ ++ ++ ++#define _Packed ++#define _PackedType __attribute__ ((packed)) ++ ++typedef phys_addr_t physAddress_t; ++ ++#define UINT8_MAX 0xFF ++#define UINT8_MIN 0 ++#define UINT16_MAX 0xFFFF ++#define UINT16_MIN 0 ++#define UINT32_MAX 0xFFFFFFFF ++#define UINT32_MIN 0 ++#define UINT64_MAX 0xFFFFFFFFFFFFFFFFLL ++#define UINT64_MIN 0 ++#define INT8_MAX 0x7F ++#define INT8_MIN 0x80 ++#define INT16_MAX 0x7FFF ++#define INT16_MIN 0x8000 ++#define INT32_MAX 0x7FFFFFFF ++#define INT32_MIN 0x80000000 ++#define INT64_MAX 0x7FFFFFFFFFFFFFFFLL ++#define INT64_MIN 0x8000000000000000LL ++ ++#define ON 1 ++#define OFF 0 ++ ++#define FALSE false ++#define TRUE true ++ ++ ++/************************/ ++/* memory access macros */ ++/************************/ ++#define GET_UINT8(arg) *(volatile uint8_t *)(&(arg)) ++#define GET_UINT16(arg) in_be16(&(arg))//*(volatile uint16_t*)(&(arg)) ++#define GET_UINT32(arg) in_be32(&(arg))//*(volatile uint32_t*)(&(arg)) ++#define GET_UINT64(arg) *(volatile uint64_t*)(&(arg)) ++ ++#ifdef VERBOSE_WRITE ++void XX_Print(char *str, ...); ++#define WRITE_UINT8(arg, data) \ ++ do { XX_Print("ADDR: 0x%08x, VAL: 0x%02x\r\n", (uint32_t)&(arg), (data)); *(volatile uint8_t *)(&(arg)) = (data); } while (0) ++#define WRITE_UINT16(arg, data) \ ++ do { XX_Print("ADDR: 0x%08x, VAL: 0x%04x\r\n", (uint32_t)&(arg), (data)); out_be16(&(arg), data); /* *(volatile uint16_t*)(&(arg)) = (data);*/ } while (0) ++#define WRITE_UINT32(arg, data) \ ++ do { XX_Print("ADDR: 0x%08x, VAL: 0x%08x\r\n", (uint32_t)&(arg), (data)); out_be32(&(arg), data); /* *(volatile uint32_t*)(&(arg)) = (data);*/ } while (0) ++#define WRITE_UINT64(arg, data) \ ++ do { XX_Print("ADDR: 0x%08x, VAL: 0x%016llx\r\n", (uint32_t)&(arg), (data)); *(volatile uint64_t*)(&(arg)) = (data); } while (0) ++ ++#else /* not VERBOSE_WRITE */ ++#define WRITE_UINT8(arg, data) *(volatile uint8_t *)(&(arg)) = (data) ++#define WRITE_UINT16(arg, data) out_be16(&(arg), data)//*(volatile uint16_t*)(&(arg)) = (data) ++#define WRITE_UINT32(arg, data) out_be32(&(arg), data)//*(volatile unsigned int *)(&(arg)) = (data) ++#define WRITE_UINT64(arg, data) *(volatile uint64_t*)(&(arg)) = (data) ++#endif /* not VERBOSE_WRITE */ ++ ++ ++/*****************************************************************************/ ++/* General stuff */ ++/*****************************************************************************/ ++#ifdef ARRAY_SIZE ++#undef ARRAY_SIZE ++#endif /* ARRAY_SIZE */ ++ ++#ifdef MAJOR ++#undef MAJOR ++#endif /* MAJOR */ ++ ++#ifdef MINOR ++#undef MINOR ++#endif /* MINOR */ ++ ++#ifdef QE_SIZEOF_BD ++#undef QE_SIZEOF_BD ++#endif /* QE_SIZEOF_BD */ ++ ++#ifdef BD_BUFFER_CLEAR ++#undef BD_BUFFER_CLEAR ++#endif /* BD_BUFFER_CLEAR */ ++ ++#ifdef BD_BUFFER ++#undef BD_BUFFER ++#endif /* BD_BUFFER */ ++ ++#ifdef BD_STATUS_AND_LENGTH_SET ++#undef BD_STATUS_AND_LENGTH_SET ++#endif /* BD_STATUS_AND_LENGTH_SET */ ++ ++#ifdef BD_STATUS_AND_LENGTH ++#undef BD_STATUS_AND_LENGTH ++#endif /* BD_STATUS_AND_LENGTH */ ++ ++#ifdef BD_BUFFER_ARG ++#undef BD_BUFFER_ARG ++#endif /* BD_BUFFER_ARG */ ++ ++#ifdef BD_GET_NEXT ++#undef BD_GET_NEXT ++#endif /* BD_GET_NEXT */ ++ ++#ifdef QE_SDEBCR_BA_MASK ++#undef QE_SDEBCR_BA_MASK ++#endif /* QE_SDEBCR_BA_MASK */ ++ ++#ifdef BD_BUFFER_SET ++#undef BD_BUFFER_SET ++#endif /* BD_BUFFER_SET */ ++ ++#ifdef UPGCR_PROTOCOL ++#undef UPGCR_PROTOCOL ++#endif /* UPGCR_PROTOCOL */ ++ ++#ifdef UPGCR_TMS ++#undef UPGCR_TMS ++#endif /* UPGCR_TMS */ ++ ++#ifdef UPGCR_RMS ++#undef UPGCR_RMS ++#endif /* UPGCR_RMS */ ++ ++#ifdef UPGCR_ADDR ++#undef UPGCR_ADDR ++#endif /* UPGCR_ADDR */ ++ ++#ifdef UPGCR_DIAG ++#undef UPGCR_DIAG ++#endif /* UPGCR_DIAG */ ++ ++#ifdef NCSW_PARAMS ++#undef NCSW_PARAMS ++#endif /* NCSW_PARAMS */ ++ ++#ifdef NO_IRQ ++#undef NO_IRQ ++#endif /* NO_IRQ */ ++ ++#define PRINT_LINE XX_Print("%s:\n %s [%d]\n",__FILE__,__FUNCTION__,__LINE__); ++ ++ ++#endif /* __TYPES_LINUX_H__ */ +diff --git a/drivers/net/dpa/NetCommSw/src/inc/wrapper/fsl_fman.h b/drivers/net/dpa/NetCommSw/src/inc/wrapper/fsl_fman.h +new file mode 100644 +index 0000000..6afde38 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/inc/wrapper/fsl_fman.h +@@ -0,0 +1,301 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fsl_fman.h ++ ++ @Description Linux internal kernel API ++*//***************************************************************************/ ++ ++#ifndef __FSL_FMAN_H ++#define __FSL_FMAN_H ++ ++#include ++#include /* struct device */ ++#include /* struct qman_fq */ ++#include "dpaa_integration_ext.h" ++#include "fm_port_ext.h" ++ ++/**************************************************************************//** ++ @Group FM_LnxKern_grp Frame Manager Linux wrapper API ++ ++ @Description FM API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_LnxKern_ctrl_grp Control Unit ++ ++ @Description Control Unit ++ ++ Internal Kernel Control Unit API ++ @{ ++*//***************************************************************************/ ++ ++/*****************************************************************************/ ++/* Internal Linux kernel routines */ ++/*****************************************************************************/ ++ ++/**************************************************************************//** ++ @Description A structure .., ++*//***************************************************************************/ ++struct fm; ++ ++/**************************************************************************//** ++ @Description A structure .., ++*//***************************************************************************/ ++struct fm_port; ++ ++typedef int (*alloc_pcd_fqids)(struct device *dev, uint32_t num, ++ uint8_t alignment, uint32_t *base_fqid); ++ ++typedef int (*free_pcd_fqids)(struct device *dev, uint32_t base_fqid); ++ ++struct fm_port_pcd_param { ++ alloc_pcd_fqids cba; ++ free_pcd_fqids cbf; ++ struct device *dev; ++}; ++ ++/**************************************************************************//** ++ @Description A structure of information about each of the external ++ buffer pools used by the port, ++*//***************************************************************************/ ++struct fm_port_pool_param { ++ uint8_t id; /**< External buffer pool id */ ++ uint16_t size; /**< External buffer pool buffer size */ ++}; ++ ++/**************************************************************************//** ++ @Description structure for additional port parameters ++*//***************************************************************************/ ++struct fm_port_params { ++ uint32_t errq; /**< Error Queue Id. */ ++ uint32_t defq; /**< For Tx and HC - Default Confirmation queue, ++ 0 means no Tx conf for processed frames. ++ For Rx and OP - default Rx queue. */ ++ uint8_t num_pools; /**< Number of pools use by this port */ ++ struct fm_port_pool_param pool_param[FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ /**< Parameters for each pool */ ++ uint16_t priv_data_size; /**< Area that user may save for his own ++ need (E.g. save the SKB) */ ++ bool parse_results; /**< Put the parser-results in the Rx/Tx buffer */ ++ bool hash_results; /**< Put the hash-results in the Rx/Tx buffer */ ++ bool time_stamp; /**< Put the time-stamp in the Rx/Tx buffer */ ++ bool frag_enable; /**< Fragmentation support, for OP only */ ++}; ++ ++/**************************************************************************//** ++ @Function fm_bind ++ ++ @Description Bind to a specific FM device. ++ ++ @Param[in] fm_dev - the OF handle of the FM device. ++ ++ @Return A handle of the FM device. ++ ++ @Cautions Allowed only after the port was created. ++*//***************************************************************************/ ++struct fm *fm_bind(struct device *fm_dev); ++ ++/**************************************************************************//** ++ @Function fm_unbind ++ ++ @Description Un-bind from a specific FM device. ++ ++ @Param[in] fm - A handle of the FM device. ++ ++ @Cautions Allowed only after the port was created. ++*//***************************************************************************/ ++void fm_unbind(struct fm *fm); ++ ++void *fm_get_handle(struct fm *fm); ++void *fm_get_rtc_handle(struct fm *fm); ++struct resource *fm_get_mem_region(struct fm *fm); ++ ++/**************************************************************************//** ++ @Function fm_port_bind ++ ++ @Description Bind to a specific FM-port device (may be Rx or Tx port). ++ ++ @Param[in] fm_port_dev - the OF handle of the FM port device. ++ ++ @Return A handle of the FM port device. ++ ++ @Cautions Allowed only after the port was created. ++*//***************************************************************************/ ++struct fm_port *fm_port_bind(struct device *fm_port_dev); ++ ++/**************************************************************************//** ++ @Function fm_port_unbind ++ ++ @Description Un-bind from a specific FM-port device (may be Rx or Tx port). ++ ++ @Param[in] port - A handle of the FM port device. ++ ++ @Cautions Allowed only after the port was created. ++*//***************************************************************************/ ++void fm_port_unbind(struct fm_port *port); ++ ++/**************************************************************************//** ++ @Function fm_set_rx_port_params ++ ++ @Description Configure parameters for a specific Rx FM-port device. ++ ++ @Param[in] port - A handle of the FM port device. ++ @Param[in] params - Rx port parameters ++ ++ @Cautions Allowed only after the port is binded. ++*//***************************************************************************/ ++void fm_set_rx_port_params(struct fm_port *port, ++ struct fm_port_params *params); ++ ++/**************************************************************************//** ++ @Function fm_port_pcd_bind ++ ++ @Description Bind as a listener on a port PCD. ++ ++ @Param[in] port - A handle of the FM port device. ++ @Param[in] params - PCD port parameters ++ ++ @Cautions Allowed only after the port is binded. ++*//***************************************************************************/ ++void fm_port_pcd_bind (struct fm_port *port, struct fm_port_pcd_param *params); ++ ++/**************************************************************************//** ++ @Function fm_get_tx_port_channel ++ ++ @Description Get qman-channel number for this Tx port. ++ ++ @Param[in] port - A handle of the FM port device. ++ ++ @Return qman-channel number for this Tx port. ++ ++ @Cautions Allowed only after the port is binded. ++*//***************************************************************************/ ++int fm_get_tx_port_channel(struct fm_port *port); ++ ++/**************************************************************************//** ++ @Function fm_set_tx_port_params ++ ++ @Description Configure parameters for a specific Tx FM-port device ++ ++ @Param[in] port - A handle of the FM port device. ++ @Param[in] params - Tx port parameters ++ ++ @Cautions Allowed only after the port is binded. ++*//***************************************************************************/ ++void fm_set_tx_port_params(struct fm_port *port, struct fm_port_params *params); ++ ++ ++/**************************************************************************//** ++ @Function fm_mac_set_handle ++ ++ @Description Set mac handle ++ ++ @Param[in] h_lnx_wrp_fm_dev - A handle of the LnxWrp FM device. ++ @Param[in] h_fm_mac - A handle of the LnxWrp FM MAC device. ++ @Param[in] mac_id - MAC id. ++*//***************************************************************************/ ++void fm_mac_set_handle(t_Handle h_lnx_wrp_fm_dev, t_Handle h_fm_mac, ++ int mac_id); ++ ++/**************************************************************************//** ++ @Function fm_port_enable ++ ++ @Description Enable specific FM-port device (may be Rx or Tx port). ++ ++ @Param[in] port - A handle of the FM port device. ++ ++ @Cautions Allowed only after the port is initialized. ++*//***************************************************************************/ ++int fm_port_enable(struct fm_port *port); ++ ++/**************************************************************************//** ++ @Function fm_port_disable ++ ++ @Description Disable specific FM-port device (may be Rx or Tx port). ++ ++ @Param[in] port - A handle of the FM port device. ++ ++ @Cautions Allowed only after the port is initialized. ++*//***************************************************************************/ ++void fm_port_disable(struct fm_port *port); ++ ++void *fm_port_get_handle(struct fm_port *port); ++ ++/**************************************************************************//** ++ @Function fm_port_get_base_address ++ ++ @Description Get base address of this port. Useful for accessing ++ port-specific registers (i.e., not common ones). ++ ++ @Param[in] port - A handle of the FM port device. ++ ++ @Param[out] base_addr - The port's base addr (virtual address). ++*//***************************************************************************/ ++void fm_port_get_base_addr(const struct fm_port *port, uint64_t *base_addr); ++ ++/**************************************************************************//** ++ @Function fm_mutex_lock ++ ++ @Description Lock function required before any FMD/LLD call. ++*//***************************************************************************/ ++void fm_mutex_lock(void); ++ ++/**************************************************************************//** ++ @Function fm_mutex_unlock ++ ++ @Description Unlock function required after any FMD/LLD call. ++*//***************************************************************************/ ++void fm_mutex_unlock(void); ++ ++/**************************************************************************//** ++ @Function fm_get_max_frm ++ ++ @Description Get the maximum frame size ++*//***************************************************************************/ ++int fm_get_max_frm(void); ++ ++/**************************************************************************//** ++ @Function fm_get_rx_extra_headroom ++ ++ @Description Get the extra headroom size ++*//***************************************************************************/ ++int fm_get_rx_extra_headroom(void); ++ ++/** @} */ /* end of FM_LnxKern_ctrl_grp group */ ++/** @} */ /* end of FM_LnxKern_grp group */ ++ ++ ++#endif /* __FSL_FMAN_H */ +diff --git a/drivers/net/dpa/NetCommSw/src/inc/wrapper/fsl_fman_test.h b/drivers/net/dpa/NetCommSw/src/inc/wrapper/fsl_fman_test.h +new file mode 100644 +index 0000000..0466a47 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/inc/wrapper/fsl_fman_test.h +@@ -0,0 +1,84 @@ ++/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fsl_fman_test.h ++ ++ @Description ++*//***************************************************************************/ ++ ++#ifndef __FSL_FMAN_TEST_H ++#define __FSL_FMAN_TEST_H ++ ++#include ++#include /* raw_smp_processor_id() */ ++ ++//#define FMT_K_DBG ++//#define FMT_K_DBG_RUNTIME ++ ++#define _fmt_prk(stage, format, arg...) \ ++ printk(stage "fmt (cpu:%u): " format, raw_smp_processor_id(), ##arg) ++ ++#define _fmt_inf(format, arg...) _fmt_prk(KERN_INFO, format, ##arg) ++#define _fmt_wrn(format, arg...) _fmt_prk(KERN_WARNING, format, ##arg) ++#define _fmt_err(format, arg...) _fmt_prk(KERN_ERR, format, ##arg) ++ ++/* there are two macros for debugging: for runtime and generic. ++ * Helps when the runtime functions are not targeted for debugging, ++ * thus all the unnecessary information will be skipped. ++ */ ++/* used for generic debugging */ ++#if defined(FMT_K_DBG) ++ #define _fmt_dbg(format, arg...) \ ++ printk("fmt [%s:%u](cpu:%u) - " format, \ ++ __func__, __LINE__, raw_smp_processor_id(), ##arg) ++#else ++# define _fmt_dbg(arg...) ++#endif ++ ++/* used for debugging runtime functions */ ++#if defined(FMT_K_DBG_RUNTIME) ++ #define _fmt_dbgr(format, arg...) \ ++ printk("fmt [%s:%u](cpu:%u) - " format, \ ++ __func__, __LINE__, raw_smp_processor_id(), ##arg) ++#else ++# define _fmt_dbgr(arg...) ++#endif ++ ++#define FMT_RX_ERR_Q 0xffffffff ++#define FMT_RX_DFLT_Q 0xfffffffe ++#define FMT_TX_ERR_Q 0xfffffffd ++#define FMT_TX_CONF_Q 0xfffffffc ++ ++#define FMAN_TEST_MAX_TX_FQS 8 ++ ++#endif /* __FSL_FMAN_TEST_H */ +diff --git a/drivers/net/dpa/NetCommSw/src/inc/wrapper/lnxwrp_fm_ext.h b/drivers/net/dpa/NetCommSw/src/inc/wrapper/lnxwrp_fm_ext.h +new file mode 100644 +index 0000000..8dda657 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/inc/wrapper/lnxwrp_fm_ext.h +@@ -0,0 +1,163 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_fm_ext.h ++ ++ @Description TODO ++*//***************************************************************************/ ++ ++#ifndef __LNXWRP_FM_EXT_H ++#define __LNXWRP_FM_EXT_H ++ ++#include "std_ext.h" ++#include "sys_ext.h" ++#include "fm_ext.h" ++#include "fm_muram_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_port_ext.h" ++#include "fm_mac_ext.h" ++#include "fm_rtc_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group FM_LnxKern_grp Frame Manager Linux wrapper API ++ ++ @Description FM API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_LnxKern_init_grp Initialization Unit ++ ++ @Description Initialization Unit ++ ++ Initialization Flow: ++ Initialization of the FM Module will be carried out by the Linux ++ kernel according to the following sequence: ++ a. Calling the initialization routine with no parameters. ++ b. The driver will register to the Device-Tree. ++ c. The Linux Device-Tree will initiate a call to the driver for ++ initialization. ++ d. The driver will read the appropriate information from the Device-Tree ++ e. [Optional] Calling the advance initialization routines to change ++ driver's defaults. ++ f. Initialization of the device will be automatically upon using it. ++ ++ @{ ++*//***************************************************************************/ ++ ++typedef struct t_WrpFmDevSettings ++{ ++ t_FmParams param; ++ t_SysObjectAdvConfigEntry *advConfig; ++} t_WrpFmDevSettings; ++ ++typedef struct t_WrpFmPcdDevSettings ++{ ++ t_FmPcdParams param; ++ t_SysObjectAdvConfigEntry *advConfig; ++} t_WrpFmPcdDevSettings; ++ ++typedef struct t_WrpFmPortDevSettings ++{ ++ bool frag_enabled; ++ t_FmPortParams param; ++ t_SysObjectAdvConfigEntry *advConfig; ++} t_WrpFmPortDevSettings; ++ ++typedef struct t_WrpFmMacDevSettings ++{ ++ t_FmMacParams param; ++ t_SysObjectAdvConfigEntry *advConfig; ++} t_WrpFmMacDevSettings; ++ ++ ++/**************************************************************************//** ++ @Function LNXWRP_FM_Init ++ ++ @Description Initialize the FM linux wrapper. ++ ++ @Return A handle (descriptor) of the newly created FM Linux wrapper ++ structure. ++*//***************************************************************************/ ++t_Handle LNXWRP_FM_Init(void); ++ ++/**************************************************************************//** ++ @Function LNXWRP_FM_Free ++ ++ @Description Free the FM linux wrapper. ++ ++ @Param[in] h_LnxWrpFm - A handle to the FM linux wrapper. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error LNXWRP_FM_Free(t_Handle h_LnxWrpFm); ++ ++/**************************************************************************//** ++ @Function LNXWRP_FM_GetMacHandle ++ ++ @Description Get the FM-MAC LLD handle from the FM linux wrapper. ++ ++ @Param[in] h_LnxWrpFm - A handle to the FM linux wrapper. ++ @Param[in] fmId - Index of the FM device to get the MAC handle from. ++ @Param[in] macId - Index of the mac handle. ++ ++ @Return A handle of the LLD compressor. ++*//***************************************************************************/ ++t_Handle LNXWRP_FM_GetMacHandle(t_Handle h_LnxWrpFm, uint8_t fmId, uint8_t macId); ++ ++#ifdef CONFIG_FSL_FMAN_TEST ++t_Handle LNXWRP_FM_TEST_Init(void); ++t_Error LNXWRP_FM_TEST_Free(t_Handle h_FmTestLnxWrp); ++#endif /* CONFIG_FSL_FMAN_TEST */ ++ ++/** @} */ /* end of FM_LnxKern_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_LnxKern_ctrl_grp Control Unit ++ ++ @Description Control Unit ++ ++ TODO ++ @{ ++*//***************************************************************************/ ++ ++#include "fsl_fman.h" ++ ++/** @} */ /* end of FM_LnxKern_ctrl_grp group */ ++/** @} */ /* end of FM_LnxKern_grp group */ ++ ++ ++#endif /* __LNXWRP_FM_EXT_H */ +diff --git a/drivers/net/dpa/NetCommSw/src/inc/xx/xx.h b/drivers/net/dpa/NetCommSw/src/inc/xx/xx.h +new file mode 100644 +index 0000000..b183c86 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/inc/xx/xx.h +@@ -0,0 +1,50 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __XX_H ++#define __XX_H ++ ++#include "xx_ext.h" ++ ++void * xx_Malloc(uint32_t n); ++void xx_Free(void *p); ++ ++void *xx_MallocSmart(uint32_t size, int memPartitionId, uint32_t align); ++void xx_FreeSmart(void *p); ++ ++/* never used: */ ++#define GetDeviceName(irq) ((char *)NULL) ++ ++int GetDeviceIrqNum(int irq); ++ ++ ++#endif /* __XX_H */ +diff --git a/drivers/net/dpa/NetCommSw/src/system/Makefile b/drivers/net/dpa/NetCommSw/src/system/Makefile +new file mode 100644 +index 0000000..c464c0f +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/system/Makefile +@@ -0,0 +1,10 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++# ++ ++obj-y += sys_io.o +diff --git a/drivers/net/dpa/NetCommSw/src/system/sys_io.c b/drivers/net/dpa/NetCommSw/src/system/sys_io.c +new file mode 100644 +index 0000000..c106a8b +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/system/sys_io.c +@@ -0,0 +1,171 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ++#include ++#else ++#include ++#endif /* LINUX_VERSION_CODE */ ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++ ++#include ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "list_ext.h" ++#include "sys_io_ext.h" ++ ++ ++#define __ERR_MODULE__ MODULE_UNKNOWN ++ ++ ++typedef struct { ++ uint64_t virtAddr; ++ uint64_t physAddr; ++ uint32_t size; ++ t_List node; ++} t_IoMap; ++#define IOMAP_OBJECT(ptr) LIST_OBJECT(ptr, t_IoMap, node) ++ ++LIST(mapsList); ++ ++ ++static void EnqueueIoMap(t_IoMap *p_IoMap) ++{ ++ uint32_t intFlags; ++ ++ intFlags = XX_DisableAllIntr(); ++ LIST_AddToTail(&p_IoMap->node, &mapsList); ++ XX_RestoreAllIntr(intFlags); ++} ++ ++static t_IoMap * FindIoMapByVirtAddr(uint64_t addr) ++{ ++ t_IoMap *p_IoMap; ++ t_List *p_Pos; ++ ++ LIST_FOR_EACH(p_Pos, &mapsList) ++ { ++ p_IoMap = IOMAP_OBJECT(p_Pos); ++ if ((addr >= p_IoMap->virtAddr) && (addr < p_IoMap->virtAddr+p_IoMap->size)) ++ return p_IoMap; ++ } ++ ++ return NULL; ++} ++ ++static t_IoMap * FindIoMapByPhysAddr(uint64_t addr) ++{ ++ t_IoMap *p_IoMap; ++ t_List *p_Pos; ++ ++ LIST_FOR_EACH(p_Pos, &mapsList) ++ { ++ p_IoMap = IOMAP_OBJECT(p_Pos); ++ if ((addr >= p_IoMap->physAddr) && (addr < p_IoMap->physAddr+p_IoMap->size)) ++ return p_IoMap; ++ } ++ ++ return NULL; ++} ++ ++t_Error SYS_RegisterIoMap (uint64_t virtAddr, uint64_t physAddr, uint32_t size) ++{ ++ t_IoMap *p_IoMap; ++ ++ p_IoMap = (t_IoMap*)XX_Malloc(sizeof(t_IoMap)); ++ if (!p_IoMap) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("message handler object!!!")); ++ memset(p_IoMap, 0, sizeof(t_IoMap)); ++ ++ p_IoMap->virtAddr = virtAddr; ++ p_IoMap->physAddr = physAddr; ++ p_IoMap->size = size; ++ ++ INIT_LIST(&p_IoMap->node); ++ EnqueueIoMap(p_IoMap); ++ ++ return E_OK; ++} ++ ++t_Error SYS_UnregisterIoMap (uint64_t virtAddr) ++{ ++ t_IoMap *p_IoMap = FindIoMapByVirtAddr(virtAddr); ++ if (!p_IoMap) ++ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!")); ++ ++ LIST_Del(&p_IoMap->node); ++ XX_Free(p_IoMap); ++ ++ return E_OK; ++} ++ ++uint64_t SYS_PhysToVirt(uint64_t addr) ++{ ++ t_IoMap *p_IoMap = FindIoMapByPhysAddr(addr); ++ if (p_IoMap) ++ { ++ /* This is optimization - put the latest in the list-head - like a cache */ ++ if (mapsList.p_Next != &p_IoMap->node) ++ { ++ uint32_t intFlags = XX_DisableAllIntr(); ++ LIST_DelAndInit(&p_IoMap->node); ++ LIST_Add(&p_IoMap->node, &mapsList); ++ XX_RestoreAllIntr(intFlags); ++ } ++ return (uint64_t)(addr - p_IoMap->physAddr + p_IoMap->virtAddr); ++ } ++ return PTR_TO_UINT(phys_to_virt((unsigned long)addr)); ++} ++ ++uint64_t SYS_VirtToPhys(uint64_t addr) ++{ ++ t_IoMap *p_IoMap; ++ ++ if (addr == 0) ++ return 0; ++ ++ p_IoMap = FindIoMapByVirtAddr(addr); ++ if (p_IoMap) ++ return (uint64_t)(addr - p_IoMap->virtAddr + p_IoMap->physAddr); ++ return (uint64_t)virt_to_phys(UINT_TO_PTR(addr)); ++} +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/Makefile b/drivers/net/dpa/NetCommSw/src/wrapper/Makefile +new file mode 100644 +index 0000000..c850bf2 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/Makefile +@@ -0,0 +1,19 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++NCSW_FM_INC = $(srctree)/drivers/net/dpa/NetCommSw/Peripherals/FM/inc ++ ++EXTRA_CFLAGS += -I$(NCSW_FM_INC) ++EXTRA_CFLAGS += -I$(NET_DPA) ++ ++obj-y += fsl-ncsw-PFM.o ++obj-$(CONFIG_FSL_FMAN_TEST) += fman_test.o ++ ++fsl-ncsw-PFM-objs := lnxwrp_fm.o lnxwrp_fm_port.o lnxwrp_ioctls_fm.o \ ++ lnxwrp_sysfs.o lnxwrp_sysfs_fm.o lnxwrp_sysfs_fm_port.o \ ++ lnxwrp_resources.o ++obj-$(CONFIG_COMPAT) += lnxwrp_ioctls_fm_compat.o +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/fman_test.c b/drivers/net/dpa/NetCommSw/src/wrapper/fman_test.c +new file mode 100644 +index 0000000..7990b9a +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/fman_test.c +@@ -0,0 +1,1663 @@ ++/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fman_test.c ++ @Authors Pistirica Sorin Andrei ++ @Description FM Linux test environment ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* private headers */ ++#include "fm_ext.h" ++#include "fsl_fman.h" ++#include "fm_port_ext.h" ++#if (DPAA_VERSION == 11) ++#include "../../Peripherals/FM/MAC/memac.h" ++#endif ++#include "fm_test_ioctls.h" ++#include "fsl_fman_test.h" ++ ++#include "dpaa_eth.h" ++#include "dpaa_eth-common.h" ++ ++#define FMT_FRM_WATERMARK 0xdeadbeefdeadbeeaLL ++ ++struct fmt_frame_s { ++ ioc_fmt_buff_desc_t buff; ++ struct list_head list; ++}; ++ ++struct fmt_fqs_s { ++ struct qman_fq fq_base; ++ bool init; ++ struct fmt_port_s *fmt_port_priv; ++}; ++ ++struct fmt_port_pcd_s { ++ int num_queues; ++ struct fmt_fqs_s *fmt_pcd_fqs; ++ uint32_t fqid_base; ++}; ++ ++/* char dev structure: fm test port */ ++struct fmt_port_s { ++ bool valid; ++ uint8_t id; ++ ioc_fmt_port_type port_type; ++ ioc_diag_mode diag; ++ bool compat_test_type; ++ ++ /* fm ports */ ++ /* ! for oh ports p_tx_fm_port_dev == p_rx_fm_port_dev && ++ * p_tx_port == p_rx_port */ ++ /* t_LnxWrpFmPortDev */ ++ struct fm_port *p_tx_port; ++ /* t_LnxWrpFmPortDev->h_Dev: t_FmPort */ ++ void *p_tx_fm_port_dev; ++ /* t_LnxWrpFmPortDev */ ++ struct fm_port *p_rx_port; ++ /* t_LnxWrpFmPortDev->h_Dev: t_FmPort */ ++ void *p_rx_fm_port_dev; ++ ++ void *p_mac_dev; ++ uint64_t fm_phys_base_addr; ++ ++ /* read/write queue manipulation */ ++ spinlock_t rx_q_lock; ++ struct list_head rx_q; ++ ++ /* tx queuee for injecting trafic */ ++ int num_of_tx_fqs; ++ struct fmt_fqs_s p_tx_fqs[FMAN_TEST_MAX_TX_FQS]; ++ ++ /* pcd private queues manipulation */ ++ struct fmt_port_pcd_s fmt_port_pcd; ++ ++ /* debugging stuff */ ++ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_t enqueue_to_qman_frm; ++ atomic_t enqueue_to_rxq; ++ atomic_t dequeue_from_rxq; ++ atomic_t not_enqueue_to_rxq_wrong_frm; ++#endif ++ ++}; ++ ++/* The devices. */ ++struct fmt_s { ++ int major; ++ struct fmt_port_s ports[IOC_FMT_MAX_NUM_OF_PORTS]; ++ struct class *fmt_class; ++}; ++ ++/* fm test structure */ ++static struct fmt_s fm_test; ++ ++#if (DPAA_VERSION == 11) ++struct mac_priv_s { ++ t_Handle mac; ++}; ++#endif ++ ++#define DTSEC_BASE_ADDR 0x000e0000 ++#define DTSEC_MEM_RANGE 0x00002000 ++#define MAC_1G_MACCFG1 0x00000100 ++#define MAC_1G_LOOP_MASK 0x00000100 ++static int set_1gmac_loopback( ++ struct fmt_port_s *fmt_port, ++ bool en) ++{ ++#if (DPAA_VERSION <= 10) ++ uint32_t dtsec_idx = fmt_port->id; /* dtsec for which port */ ++ uint32_t dtsec_idx_off = dtsec_idx * DTSEC_MEM_RANGE; ++ phys_addr_t maccfg1_hw; ++ void *maccfg1_map; ++ uint32_t maccfg1_val; ++ ++ /* compute the maccfg1 register address */ ++ maccfg1_hw = fmt_port->fm_phys_base_addr + ++ (phys_addr_t)(DTSEC_BASE_ADDR + ++ dtsec_idx_off + ++ MAC_1G_MACCFG1); ++ ++ /* map register */ ++ maccfg1_map = ioremap(maccfg1_hw, sizeof(u32)); ++ ++ /* set register */ ++ maccfg1_val = in_be32(maccfg1_map); ++ if (en) ++ maccfg1_val |= MAC_1G_LOOP_MASK; ++ else ++ maccfg1_val &= ~MAC_1G_LOOP_MASK; ++ out_be32(maccfg1_map, maccfg1_val); ++ ++ /* unmap register */ ++ iounmap(maccfg1_map); ++#else ++ struct mac_device *mac_dev; ++ struct mac_priv_s *priv; ++ t_Memac *p_memac; ++ ++ if (!fmt_port) ++ return -EINVAL; ++ ++ mac_dev = (struct mac_device *)fmt_port->p_mac_dev; ++ ++ if (!mac_dev) ++ return -EINVAL; ++ ++ priv = macdev_priv(mac_dev); ++ ++ if (!priv) ++ return -EINVAL; ++ ++ p_memac = priv->mac; ++ ++ if (!p_memac) ++ return -EINVAL; ++ ++ memac_set_loopback(p_memac->p_MemMap, en); ++#endif ++ return 0; ++} ++ ++/* TODO: re-write this function */ ++static int set_10gmac_int_loopback( ++ struct fmt_port_s *fmt_port, ++ bool en) ++{ ++#ifndef FM_10G_MAC_NO_CTRL_LOOPBACK ++#define FM_10GMAC0_OFFSET 0x000f0000 ++#define FM_10GMAC_CMD_CONF_CTRL_OFFSET 0x8 ++#define CMD_CFG_LOOPBACK_EN 0x00000400 ++ ++ uint64_t base_addr, reg_addr; ++ uint32_t tmp_val; ++ ++ base_addr = fmt_port->fm_phys_base_addr + (FM_10GMAC0_OFFSET + ++ ((fmt_port->id-FM_MAX_NUM_OF_1G_RX_PORTS)*0x2000)); ++ ++ base_addr = PTR_TO_UINT(ioremap(base_addr, 0x1000)); ++ ++ reg_addr = base_addr + FM_10GMAC_CMD_CONF_CTRL_OFFSET; ++ tmp_val = GET_UINT32(*((uint32_t *)UINT_TO_PTR(reg_addr))); ++ if (en) ++ tmp_val |= CMD_CFG_LOOPBACK_EN; ++ else ++ tmp_val &= ~CMD_CFG_LOOPBACK_EN; ++ WRITE_UINT32(*((uint32_t *)UINT_TO_PTR(reg_addr)), tmp_val); ++ ++ iounmap(UINT_TO_PTR(base_addr)); ++ ++ return 0; ++#else ++ _fmt_err("TGEC don't have internal-loopback.\n"); ++ return -EPERM; ++#endif ++} ++ ++static int set_mac_int_loopback(struct fmt_port_s *fmt_port, bool en) ++{ ++ int _err = 0; ++ ++ switch (fmt_port->port_type) { ++ ++ case e_IOC_FMT_PORT_T_RXTX: ++ /* 1G port */ ++ if (fmt_port->id < FM_MAX_NUM_OF_1G_RX_PORTS) ++ _err = set_1gmac_loopback(fmt_port, en); ++ /* 10g port */ ++ else if ((fmt_port->id >= FM_MAX_NUM_OF_1G_RX_PORTS) && ++ (fmt_port->id < FM_MAX_NUM_OF_1G_RX_PORTS + ++ FM_MAX_NUM_OF_10G_RX_PORTS)) { ++ ++ _err = set_10gmac_int_loopback(fmt_port, en); ++ } else ++ _err = -EINVAL; ++ break; ++ /* op port does not have MAC (loopback mode) */ ++ case e_IOC_FMT_PORT_T_OP: ++ ++ _err = 0; ++ break; ++ default: ++ ++ _err = -EPERM; ++ break; ++ } ++ ++ return _err; ++} ++ ++static void enqueue_fmt_frame( ++ struct fmt_port_s *fmt_port, ++ struct fmt_frame_s *p_fmt_frame) ++{ ++ spinlock_t *rx_q_lock = NULL; ++ ++ rx_q_lock = &fmt_port->rx_q_lock; ++ ++ spin_lock(rx_q_lock); ++ list_add_tail(&p_fmt_frame->list, &fmt_port->rx_q); ++ spin_unlock(rx_q_lock); ++ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_inc(&fmt_port->enqueue_to_rxq); ++#endif ++} ++ ++static struct fmt_frame_s *dequeue_fmt_frame( ++ struct fmt_port_s *fmt_port) ++{ ++ struct fmt_frame_s *p_fmt_frame = NULL; ++ spinlock_t *rx_q_lock = NULL; ++ ++ rx_q_lock = &fmt_port->rx_q_lock; ++ ++ spin_lock(rx_q_lock); ++ ++ if (!list_empty(&fmt_port->rx_q)) { ++ p_fmt_frame = list_last_entry(&fmt_port->rx_q, ++ struct fmt_frame_s, ++ list); ++ list_del(&p_fmt_frame->list); ++ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_inc(&fmt_port->dequeue_from_rxq); ++#endif ++ } ++ ++ spin_unlock(rx_q_lock); ++ ++ return p_fmt_frame; ++} ++ ++/* eth-dev -to- fmt port association */ ++struct fmt_port_s *match_dpa_to_fmt_port( ++ struct dpa_priv_s *dpa_priv) { ++ struct mac_device *mac_dev = dpa_priv->mac_dev; ++ struct fm_port *fm_port = (struct fm_port *) mac_dev; ++ struct fmt_port_s *fmt_port = NULL; ++ int i; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ /* find the FM-test-port object */ ++ for (i = 0; i < IOC_FMT_MAX_NUM_OF_PORTS; i++) ++ if ((fm_test.ports[i].p_mac_dev && ++ mac_dev == fm_test.ports[i].p_mac_dev) || ++ fm_port == fm_test.ports[i].p_tx_port) { ++ ++ fmt_port = &fm_test.ports[i]; ++ break; ++ } ++ ++ _fmt_dbgr("called\n"); ++ return fmt_port; ++} ++ ++void dump_frame( ++ uint8_t *buffer, ++ uint32_t size) ++{ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ unsigned int i; ++ ++ for (i = 0; i < size; i++) { ++ if (i%16 == 0) ++ printk(KERN_DEBUG "\n"); ++ printk(KERN_DEBUG "%2x ", *(buffer+i)); ++ } ++#endif ++ return; ++} ++ ++bool test_and_steal_frame(struct fmt_port_s *fmt_port, ++ uint32_t fqid, ++ uint8_t *buffer, ++ uint32_t size) ++{ ++ struct fmt_frame_s *p_fmt_frame = NULL; ++ bool test_and_steal_frame_frame; ++ uint32_t data_offset; ++ uint32_t i; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ if (!fmt_port || !fmt_port->p_rx_fm_port_dev) ++ return false; ++ ++ /* check watermark */ ++ test_and_steal_frame_frame = false; ++ for (i = 0; i < size; i++) { ++ uint64_t temp = *((uint64_t *)(buffer + i)); ++ ++ if (temp == (uint64_t) FMT_FRM_WATERMARK) { ++ _fmt_dbgr("watermark found!\n"); ++ test_and_steal_frame_frame = true; ++ break; ++ } ++ } ++ ++ if (!test_and_steal_frame_frame) { ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_inc(&fmt_port->not_enqueue_to_rxq_wrong_frm); ++#endif ++ _fmt_dbgr("NOT watermark found!\n"); ++ return false; ++ } ++ ++ /* do not enqueue the tx conf/err frames */ ++ if ((fqid == FMT_TX_CONF_Q) || (fqid == FMT_TX_ERR_Q)) ++ goto _test_and_steal_frame_return_true; ++ ++ _fmt_dbgr("on port %d got FMUC frame\n", fmt_port->id); ++ data_offset = FM_PORT_GetBufferDataOffset( ++ fmt_port->p_rx_fm_port_dev); ++ ++ p_fmt_frame = kmalloc(sizeof(struct fmt_frame_s), GFP_KERNEL); ++ ++ /* dump frame... no more space left on device */ ++ if (p_fmt_frame == NULL) { ++ _fmt_err("no space left on device!\n"); ++ goto _test_and_steal_frame_return_true; ++ } ++ ++ memset(p_fmt_frame, 0, sizeof(struct fmt_frame_s)); ++ p_fmt_frame->buff.p_data = kmalloc(size * sizeof(uint8_t), GFP_KERNEL); ++ ++ /* No more space left on device*/ ++ if (p_fmt_frame->buff.p_data == NULL) { ++ _fmt_err("no space left on device!\n"); ++ kfree(p_fmt_frame); ++ goto _test_and_steal_frame_return_true; ++ } ++ ++ p_fmt_frame->buff.size = size-data_offset; ++ p_fmt_frame->buff.qid = fqid; ++ ++ memcpy(p_fmt_frame->buff.p_data, ++ (uint8_t *)PTR_MOVE(buffer, data_offset), ++ p_fmt_frame->buff.size); ++ ++ memcpy(p_fmt_frame->buff.buff_context.fm_prs_res, ++ FM_PORT_GetBufferPrsResult(fmt_port->p_rx_fm_port_dev, ++ (char *)buffer), ++ 32); ++ ++ /* enqueue frame - this frame will go to us */ ++ enqueue_fmt_frame(fmt_port, p_fmt_frame); ++ ++_test_and_steal_frame_return_true: ++ return true; ++} ++ ++static int fmt_fq_release(const struct qm_fd *fd) ++{ ++ struct dpa_bp *_dpa_bp; ++ struct bm_buffer _bmb; ++ ++ if (fd->format == qm_fd_contig) { ++ _dpa_bp = dpa_bpid2pool(fd->bpid); ++ BUG_ON(IS_ERR(_dpa_bp)); ++ ++ _bmb.hi = fd->addr_hi; ++ _bmb.lo = fd->addr_lo; ++ ++ while (bman_release(_dpa_bp->pool, &_bmb, 1, 0)) ++ cpu_relax(); ++ ++ } else { ++ _fmt_err("frame not supported !\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++/* sync it w/ dpaa_eth.c: DPA_BP_HEAD */ ++#define DPA_BP_HEADROOM (DPA_TX_PRIV_DATA_SIZE + \ ++ fm_get_rx_extra_headroom() + \ ++ DPA_PARSE_RESULTS_SIZE + \ ++ DPA_HASH_RESULTS_SIZE) ++#define MAC_HEADER_LENGTH 14 ++#define L2_AND_HEADROOM_OFF ((DPA_BP_HEADROOM) + (MAC_HEADER_LENGTH)) ++ ++/* dpa ingress hooks definition */ ++enum dpaa_eth_hook_result fmt_rx_default_hook( ++ struct sk_buff *skb, ++ struct net_device *net_dev, ++ u32 fqid) ++{ ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct fmt_port_s *fmt_port = NULL; ++ uint8_t *buffer; ++ uint32_t buffer_len; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ dpa_priv = netdev_priv(net_dev); ++ fmt_port = match_dpa_to_fmt_port(dpa_priv); ++ ++ /* conversion from skb to fd: ++ * skb cames processed for L3, so we need to go back for ++ * layer 2 offset */ ++ buffer = (uint8_t *)(skb->data - ((int)L2_AND_HEADROOM_OFF)); ++ buffer_len = skb->len + ((int)L2_AND_HEADROOM_OFF); ++ ++ /* if is not out frame let dpa to handle it */ ++ if (test_and_steal_frame(fmt_port, ++ FMT_RX_DFLT_Q, ++ buffer, ++ buffer_len)) ++ goto _fmt_rx_default_hook_stolen; ++ ++ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n"); ++ return DPAA_ETH_CONTINUE; ++ ++_fmt_rx_default_hook_stolen: ++ dev_kfree_skb(skb); ++ ++ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n"); ++ return DPAA_ETH_STOLEN; ++} ++ ++enum dpaa_eth_hook_result fmt_rx_error_hook( ++ struct net_device *net_dev, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct dpa_bp *dpa_bp = NULL; ++ struct fmt_port_s *fmt_port = NULL; ++ void *fd_virt_addr = NULL; ++ dma_addr_t addr = qm_fd_addr(fd); ++ ++ _fmt_dbgr("calling...\n"); ++ ++ dpa_priv = netdev_priv(net_dev); ++ fmt_port = match_dpa_to_fmt_port(dpa_priv); ++ ++ /* dpaa doesn't do this... we have to do it here */ ++ dpa_bp = dpa_bpid2pool(fd->bpid); ++ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL); ++ ++ fd_virt_addr = phys_to_virt(addr); ++ /* if is not out frame let dpa to handle it */ ++ if (test_and_steal_frame(fmt_port, ++ FMT_RX_ERR_Q, ++ fd_virt_addr, ++ fd->length20 + fd->offset)) { ++ goto _fmt_rx_error_hook_stolen; ++ } ++ ++ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n"); ++ return DPAA_ETH_CONTINUE; ++ ++_fmt_rx_error_hook_stolen: ++ /* the frame data doesn't matter, ++ * so, no mapping is needed */ ++ fmt_fq_release(fd); ++ ++ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n"); ++ return DPAA_ETH_STOLEN; ++} ++ ++enum dpaa_eth_hook_result fmt_tx_confirm_hook( ++ struct net_device *net_dev, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct fmt_port_s *fmt_port = NULL; ++ dma_addr_t addr = qm_fd_addr(fd); ++ void *fd_virt_addr = NULL; ++ uint32_t fd_len = 0; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ dpa_priv = netdev_priv(net_dev); ++ fmt_port = match_dpa_to_fmt_port(dpa_priv); ++ ++ fd_virt_addr = phys_to_virt(addr); ++ fd_len = fd->length20 + fd->offset; ++ ++ if (fd_len > fm_get_max_frm()) { ++ _fmt_err("tx confirm bad frame size: %u!\n", fd_len); ++ goto _fmt_tx_confirm_hook_continue; ++ } ++ ++ if (test_and_steal_frame(fmt_port, ++ FMT_TX_CONF_Q, ++ fd_virt_addr, ++ fd_len)) ++ goto _fmt_tx_confirm_hook_stolen; ++ ++_fmt_tx_confirm_hook_continue: ++ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n"); ++ return DPAA_ETH_CONTINUE; ++ ++_fmt_tx_confirm_hook_stolen: ++ kfree(fd_virt_addr); ++ ++ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n"); ++ return DPAA_ETH_STOLEN; ++} ++ ++enum dpaa_eth_hook_result fmt_tx_confirm_error_hook( ++ struct net_device *net_dev, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct fmt_port_s *fmt_port = NULL; ++ dma_addr_t addr = qm_fd_addr(fd); ++ void *fd_virt_addr = NULL; ++ uint32_t fd_len = 0; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ dpa_priv = netdev_priv(net_dev); ++ fmt_port = match_dpa_to_fmt_port(dpa_priv); ++ ++ fd_virt_addr = phys_to_virt(addr); ++ fd_len = fd->length20 + fd->offset; ++ ++ if (fd_len > fm_get_max_frm()) { ++ _fmt_err("tx confirm err bad frame size: %u !\n", fd_len); ++ goto _priv_ingress_tx_err_continue; ++ } ++ ++ if (test_and_steal_frame(fmt_port, FMT_TX_ERR_Q, fd_virt_addr, fd_len)) ++ goto _priv_ingress_tx_err_stolen; ++ ++_priv_ingress_tx_err_continue: ++ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n"); ++ return DPAA_ETH_CONTINUE; ++ ++_priv_ingress_tx_err_stolen: ++ kfree(fd_virt_addr); ++ ++ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n"); ++ return DPAA_ETH_STOLEN; ++} ++ ++/* egress callbacks definition */ ++enum qman_cb_dqrr_result fmt_egress_dqrr( ++ struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dqrr) ++{ ++ /* this callback should never be called */ ++ BUG(); ++ return qman_cb_dqrr_consume; ++} ++ ++static void fmt_egress_error_dqrr( ++ struct qman_portal *p, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ uint8_t *fd_virt_addr = NULL; ++ ++ /* tx failure, on the ern callback - release buffer */ ++ fd_virt_addr = (uint8_t *)phys_to_virt(qm_fd_addr(&msg->ern.fd)); ++ kfree(fd_virt_addr); ++ ++ return; ++} ++ ++static const struct qman_fq fmt_egress_fq __devinitconst = { ++ .cb = { .dqrr = fmt_egress_dqrr, ++ .ern = fmt_egress_error_dqrr, ++ .fqs = NULL} ++}; ++ ++int fmt_fq_alloc( ++ struct fmt_fqs_s *fmt_fqs, ++ const struct qman_fq *qman_fq, ++ uint32_t fqid, uint32_t flags, ++ uint16_t channel, uint8_t wq) ++{ ++ int _errno = 0; ++ ++ _fmt_dbg("calling...\n"); ++ ++ fmt_fqs->fq_base = *qman_fq; ++ ++ if (fqid == 0) { ++ flags |= QMAN_FQ_FLAG_DYNAMIC_FQID; ++ flags &= ~QMAN_FQ_FLAG_NO_MODIFY; ++ } else ++ flags &= ~QMAN_FQ_FLAG_DYNAMIC_FQID; ++ ++ fmt_fqs->init = !(flags & QMAN_FQ_FLAG_NO_MODIFY); ++ ++ _errno = qman_create_fq(fqid, flags, &fmt_fqs->fq_base); ++ if (_errno < 0) { ++ _fmt_err("frame queues create failed.\n"); ++ return -EINVAL; ++ } ++ ++ if (fmt_fqs->init) { ++ struct qm_mcc_initfq initfq; ++ ++ initfq.we_mask = QM_INITFQ_WE_DESTWQ; ++ initfq.fqd.dest.channel = channel; ++ initfq.fqd.dest.wq = wq; ++ ++ _errno = qman_init_fq(&fmt_fqs->fq_base, ++ QMAN_INITFQ_FLAG_SCHED, ++ &initfq); ++ if (_errno < 0) { ++ _fmt_err("frame queues init erorr.\n"); ++ qman_destroy_fq(&fmt_fqs->fq_base, 0); ++ return -EINVAL; ++ } ++ } ++ ++ _fmt_dbg("called.\n"); ++ return 0; ++} ++ ++static int fmt_fq_free(struct fmt_fqs_s *fmt_fq) ++{ ++ int _err = 0; ++ ++ _fmt_dbg("calling...\n"); ++ ++ if (fmt_fq->init) { ++ _err = qman_retire_fq(&fmt_fq->fq_base, NULL); ++ if (unlikely(_err < 0)) ++ _fmt_err("qman_retire_fq(%u) = %d\n", ++ qman_fq_fqid(&fmt_fq->fq_base), _err); ++ ++ _err = qman_oos_fq(&fmt_fq->fq_base); ++ if (unlikely(_err < 0)) ++ _fmt_err("qman_oos_fq(%u) = %d\n", ++ qman_fq_fqid(&fmt_fq->fq_base), _err); ++ } ++ ++ qman_destroy_fq(&fmt_fq->fq_base, 0); ++ ++ _fmt_dbg("called.\n"); ++ return _err; ++} ++ ++/* private pcd dqrr calbacks */ ++static enum qman_cb_dqrr_result fmt_pcd_dqrr( ++ struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct dpa_bp *dpa_bp = NULL; ++ dma_addr_t addr = qm_fd_addr(&dq->fd); ++ uint8_t *fd_virt_addr = NULL; ++ struct fmt_port_s *fmt_port; ++ struct fmt_port_pcd_s *fmt_port_pcd; ++ uint32_t relative_fqid = 0; ++ uint32_t fd_len = 0; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ /* upcast - from pcd_alloc_fq */ ++ fmt_port = ((struct fmt_fqs_s *)fq)->fmt_port_priv; ++ if (!fmt_port) { ++ _fmt_err(" wrong fmt port -to- fq match.\n"); ++ goto _fmt_pcd_dqrr_return; ++ } ++ fmt_port_pcd = &fmt_port->fmt_port_pcd; ++ ++ relative_fqid = dq->fqid - fmt_port_pcd->fqid_base; ++ _fmt_dbgr("pcd dqrr got frame on relative fq:%u@base:%u\n", ++ relative_fqid, fmt_port_pcd->fqid_base); ++ ++ fd_len = dq->fd.length20 + dq->fd.offset; ++ ++ if (fd_len > fm_get_max_frm()) { ++ _fmt_err("pcd dqrr wrong frame size: %u (%u:%u)!\n", ++ fd_len, dq->fd.length20, dq->fd.offset); ++ goto _fmt_pcd_dqrr_return; ++ } ++ ++ dpa_bp = dpa_bpid2pool(dq->fd.bpid); ++ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL); ++ ++ fd_virt_addr = phys_to_virt(addr); ++ if (!test_and_steal_frame(fmt_port, relative_fqid, fd_virt_addr, ++ fd_len)) { ++ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_inc(&fmt_port->not_enqueue_to_rxq_wrong_frm); ++#endif ++ _fmt_wrn("pcd dqrr unrecognized frame@fqid: %u," ++ " frame len: %u (dropped).\n", ++ dq->fqid, dq->fd.length20); ++ dump_frame(fd_virt_addr, fd_len); ++ } ++ ++_fmt_pcd_dqrr_return: ++ /* no need to map again here */ ++ fmt_fq_release(&dq->fd); ++ ++ _fmt_dbgr("calle.\n"); ++ return qman_cb_dqrr_consume; ++} ++ ++static void fmt_pcd_err_dqrr( ++ struct qman_portal *qm, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ _fmt_err("this callback should never be called.\n"); ++ BUG(); ++ return; ++} ++ ++static void fmt_pcd_fqs_dqrr( ++ struct qman_portal *qm, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ _fmt_dbg(" fq state(0x%x)@fqid(%u.\n", msg->fq.fqs, msg->fq.fqid); ++ return; ++} ++ ++/* private pcd queue template */ ++static const struct qman_fq pcd_fq = { ++ .cb = { .dqrr = fmt_pcd_dqrr, ++ .ern = fmt_pcd_err_dqrr, ++ .fqs = fmt_pcd_fqs_dqrr} ++}; ++ ++/* defined as weak in dpaa driver. */ ++/* ! parameters come from IOCTL call - US */ ++int dpa_alloc_pcd_fqids( ++ struct device *dev, ++ uint32_t num, uint8_t alignment, ++ uint32_t *base_fqid) ++{ ++ int _err = 0, i; ++ struct net_device *net_dev = NULL; ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct fmt_port_pcd_s *fmt_port_pcd = NULL; ++ struct fmt_fqs_s *fmt_fqs = NULL; ++ struct fmt_port_s *fmt_port = NULL; ++ int num_allocated = 0; ++ ++ _fmt_dbg("calling...\n"); ++ ++ net_dev = (typeof(net_dev))dev_get_drvdata(dev); ++ dpa_priv = (typeof(dpa_priv))netdev_priv(net_dev); ++ ++ if (!netif_msg_probe(dpa_priv)) { ++ _fmt_err("dpa not probe.\n"); ++ _err = -ENODEV; ++ goto _pcd_alloc_fqs_err; ++ } ++ ++ fmt_port = match_dpa_to_fmt_port(dpa_priv); ++ if (!fmt_port) { ++ _fmt_err("fmt port not found."); ++ _err = -EINVAL; ++ goto _pcd_alloc_fqs_err; ++ } ++ ++ fmt_port_pcd = &fmt_port->fmt_port_pcd; ++ ++ num_allocated = qman_alloc_fqid_range(base_fqid, num, alignment, 0); ++ ++ if ((num_allocated <= 0) || ++ (num_allocated < num) || ++ (alignment && (*base_fqid) % alignment)) { ++ *base_fqid = 0; ++ _fmt_err("Failed to alloc pcd fqs rang.\n"); ++ _err = -EINVAL; ++ goto _pcd_alloc_fqs_err; ++ } ++ ++ _fmt_dbg("wanted %d fqs(align %d), got %d fqids@%u.\n", ++ num, alignment, num_allocated, *base_fqid); ++ ++ /* alloc pcd queues */ ++ fmt_port_pcd->fmt_pcd_fqs = kmalloc(num_allocated * ++ sizeof(struct fmt_fqs_s), ++ GFP_KERNEL); ++ fmt_port_pcd->num_queues = num_allocated; ++ fmt_port_pcd->fqid_base = *base_fqid; ++ fmt_fqs = fmt_port_pcd->fmt_pcd_fqs; ++ ++ /* alloc the pcd queues */ ++ for (i = 0; i < num_allocated; i++, fmt_fqs++) { ++ _err = fmt_fq_alloc( ++ fmt_fqs, ++ &pcd_fq, ++ (*base_fqid) + i, QMAN_FQ_FLAG_NO_ENQUEUE, ++ dpa_priv->channel, 7); ++ ++ if (_err < 0) ++ goto _pcd_alloc_fqs_err; ++ ++ /* upcast to identify from where the frames came from */ ++ fmt_fqs->fmt_port_priv = fmt_port; ++ } ++ ++ _fmt_dbg("called.\n"); ++ return _err; ++_pcd_alloc_fqs_err: ++ if (num_allocated > 0) ++ qman_release_fqid_range(*base_fqid, num_allocated); ++ /*TODO: free fmt_pcd_fqs if are any */ ++ ++ _fmt_dbg("called(_err:%d).\n", _err); ++ return _err; ++} ++ ++/* defined as weak in dpaa driver. */ ++int dpa_free_pcd_fqids( ++ struct device *dev, ++ uint32_t base_fqid) ++{ ++ ++ int _err = 0, i; ++ struct net_device *net_dev = NULL; ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct fmt_port_pcd_s *fmt_port_pcd = NULL; ++ struct fmt_fqs_s *fmt_fqs = NULL; ++ struct fmt_port_s *fmt_port = NULL; ++ int num_allocated = 0; ++ ++ _fmt_dbg("calling...\n"); ++ ++ net_dev = (typeof(net_dev))dev_get_drvdata(dev); ++ dpa_priv = (typeof(dpa_priv))netdev_priv(net_dev); ++ ++ if (!netif_msg_probe(dpa_priv)) { ++ _fmt_err("dpa not probe.\n"); ++ _err = -ENODEV; ++ goto _pcd_free_fqs_err; ++ } ++ ++ fmt_port = match_dpa_to_fmt_port(dpa_priv); ++ if (!fmt_port) { ++ _fmt_err("fmt port not found."); ++ _err = -EINVAL; ++ goto _pcd_free_fqs_err; ++ } ++ ++ fmt_port_pcd = &fmt_port->fmt_port_pcd; ++ num_allocated = fmt_port_pcd->num_queues; ++ fmt_fqs = fmt_port_pcd->fmt_pcd_fqs; ++ ++ for (i = 0; i < num_allocated; i++, fmt_fqs++) ++ fmt_fq_free(fmt_fqs); ++ ++ qman_release_fqid_range(base_fqid,num_allocated); ++ ++ kfree(fmt_port_pcd->fmt_pcd_fqs); ++ memset(fmt_port_pcd, 0, sizeof(*fmt_port_pcd)); ++ ++ /* debugging stuff */ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ _fmt_dbg(" portid: %u.\n", fmt_port->id); ++ _fmt_dbg(" frames enqueue to qman: %u.\n", ++ atomic_read(&fmt_port->enqueue_to_qman_frm)); ++ _fmt_dbg(" frames enqueue to rxq: %u.\n", ++ atomic_read(&fmt_port->enqueue_to_rxq)); ++ _fmt_dbg(" frames dequeue from rxq: %u.\n", ++ atomic_read(&fmt_port->dequeue_from_rxq)); ++ _fmt_dbg(" frames not enqueue to rxq - wrong frm: %u.\n", ++ atomic_read(&fmt_port->not_enqueue_to_rxq_wrong_frm)); ++ atomic_set(&fmt_port->enqueue_to_qman_frm, 0); ++ atomic_set(&fmt_port->enqueue_to_rxq, 0); ++ atomic_set(&fmt_port->dequeue_from_rxq, 0); ++ atomic_set(&fmt_port->not_enqueue_to_rxq_wrong_frm, 0); ++#endif ++ return 0; ++ ++_pcd_free_fqs_err: ++ return _err; ++} ++ ++static int fmt_port_init( ++ struct fmt_port_s *fmt_port, ++ ioc_fmt_port_param_t *p_Params) ++{ ++ struct device_node *fm_node, *fm_port_node; ++ const uint32_t *uint32_prop; ++ int _errno = 0, lenp = 0, i; ++ static struct of_device_id fm_node_of_match[] __devinitdata = { ++ { .compatible = "fsl,fman", }, ++ { /* end of list */ }, ++ }; ++ ++ _fmt_dbg("calling...\n"); ++ ++ /* init send/receive tu US list */ ++ INIT_LIST_HEAD(&fmt_port->rx_q); ++ ++ /* check parameters */ ++ if (p_Params->num_tx_queues > FMAN_TEST_MAX_TX_FQS || ++ p_Params->fm_port_id > IOC_FMT_MAX_NUM_OF_PORTS) { ++ _fmt_dbg("wrong test parameters.\n"); ++ return -EINVAL; ++ } ++ ++ /* set port parameters */ ++ fmt_port->num_of_tx_fqs = p_Params->num_tx_queues; ++ fmt_port->id = p_Params->fm_port_id; ++ fmt_port->port_type = p_Params->fm_port_type; ++ fmt_port->diag = e_IOC_DIAG_MODE_NONE; ++ ++ /* init debugging stuff */ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_set(&fmt_port->enqueue_to_qman_frm, 0); ++ atomic_set(&fmt_port->enqueue_to_rxq, 0); ++ atomic_set(&fmt_port->dequeue_from_rxq, 0); ++ atomic_set(&fmt_port->not_enqueue_to_rxq_wrong_frm, 0); ++#endif ++ ++ /* TODO: This should be done at probe time not at runtime ++ * very ugly function */ ++ /* fill fmt port properties from dts */ ++ for_each_matching_node(fm_node, fm_node_of_match) { ++ ++ uint32_prop = (uint32_t *)of_get_property(fm_node, ++ "cell-index", &lenp); ++ if (unlikely(uint32_prop == NULL)) { ++ _fmt_wrn("of_get_property(%s, cell-index) invalid", ++ fm_node->full_name); ++ return -EINVAL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) { ++ _fmt_wrn("of_get_property(%s, cell-index) invalid", ++ fm_node->full_name); ++ return -EINVAL; ++ } ++ ++ if (*uint32_prop == p_Params->fm_id) { ++ struct resource res; ++ ++ /* Get the FM address */ ++ _errno = of_address_to_resource(fm_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ _fmt_wrn("of_address_to_resource() = %u.\n", _errno); ++ return -EINVAL; ++ } ++ ++ fmt_port->fm_phys_base_addr = res.start; ++ ++ for_each_child_of_node(fm_node, fm_port_node) { ++ struct platform_device *of_dev; ++ ++ if (!of_device_is_available(fm_port_node)) ++ continue; ++ ++ uint32_prop = (uint32_t *)of_get_property( ++ fm_port_node, ++ "cell-index", ++ &lenp); ++ if (uint32_prop == NULL) ++ continue; ++ ++ if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-oh") && ++ (fmt_port->port_type == e_IOC_FMT_PORT_T_OP)) { ++ ++ if (*uint32_prop == fmt_port->id) { ++ of_dev = of_find_device_by_node(fm_port_node); ++ if (unlikely(of_dev == NULL)) { ++ _fmt_wrn("fm id invalid\n"); ++ return -EINVAL; ++ } ++ ++ fmt_port->p_tx_port = ++ fm_port_bind(&of_dev->dev); ++ fmt_port->p_tx_fm_port_dev = ++ (void *)fm_port_get_handle( ++ fmt_port->p_tx_port); ++ fmt_port->p_rx_port = ++ fmt_port->p_tx_port; ++ fmt_port->p_rx_fm_port_dev = ++ fmt_port->p_tx_fm_port_dev; ++ fmt_port->p_mac_dev = NULL; ++ break; ++ } ++ } else if ((*uint32_prop == fmt_port->id) && ++ fmt_port->port_type == e_IOC_FMT_PORT_T_RXTX) { ++ ++ of_dev = of_find_device_by_node(fm_port_node); ++ if (unlikely(of_dev == NULL)) { ++ _fmt_wrn("dtb fm id invalid value"); ++ return -EINVAL; ++ } ++ ++ if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-1g-tx")) { ++ fmt_port->p_tx_port = ++ fm_port_bind(&of_dev->dev); ++ fmt_port->p_tx_fm_port_dev = (void *) ++ fm_port_get_handle( ++ fmt_port->p_tx_port); ++ } else if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-1g-rx")) { ++ fmt_port->p_rx_port = ++ fm_port_bind(&of_dev->dev); ++ fmt_port->p_rx_fm_port_dev = (void *) ++ fm_port_get_handle( ++ fmt_port->p_rx_port); ++ } else if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-1g-mac") || ++ of_device_is_compatible(fm_port_node, ++ "fsl,fman-memac")) ++ fmt_port->p_mac_dev = ++ (typeof(fmt_port->p_mac_dev)) ++ dev_get_drvdata(&of_dev->dev); ++ else ++ continue; ++ ++ if (fmt_port->p_tx_fm_port_dev && ++ fmt_port->p_rx_fm_port_dev && fmt_port->p_mac_dev) ++ break; ++ } else if (((*uint32_prop + FM_MAX_NUM_OF_1G_RX_PORTS) == ++ fmt_port->id) && ++ fmt_port->port_type == e_IOC_FMT_PORT_T_RXTX) { ++ ++ of_dev = of_find_device_by_node(fm_port_node); ++ if (unlikely(of_dev == NULL)) { ++ _fmt_wrn("dtb fm id invalid value\n"); ++ return -EINVAL; ++ } ++ ++ if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-10g-tx")) { ++ fmt_port->p_tx_port = ++ fm_port_bind(&of_dev->dev); ++ fmt_port->p_tx_fm_port_dev = (void *) ++ fm_port_get_handle( ++ fmt_port->p_tx_port); ++ } else if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-10g-rx")) { ++ fmt_port->p_rx_port = ++ fm_port_bind(&of_dev->dev); ++ fmt_port->p_rx_fm_port_dev = (void *) ++ fm_port_get_handle( ++ fmt_port->p_rx_port); ++ } else if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-10g-mac") || ++ of_device_is_compatible(fm_port_node, ++ "fsl,fman-memac")) ++ fmt_port->p_mac_dev = ++ (typeof(fmt_port->p_mac_dev)) ++ dev_get_drvdata(&of_dev->dev); ++ else ++ continue; ++ ++ if (fmt_port->p_tx_fm_port_dev && ++ fmt_port->p_rx_fm_port_dev && fmt_port->p_mac_dev) ++ break; ++ } ++ } /* for_each_child */ ++ } ++ } /* for each matching node */ ++ ++ if (fmt_port->p_tx_fm_port_dev == 0 || ++ fmt_port->p_rx_fm_port_dev == 0) { ++ ++ _fmt_err("bad fm port pointers.\n"); ++ return -EINVAL; ++ } ++ ++ _fmt_dbg("alloc %u tx queues.\n", fmt_port->num_of_tx_fqs); ++ ++ /* init fman test egress dynamic frame queues */ ++ for (i = 0; i < fmt_port->num_of_tx_fqs; i++) { ++ int _errno; ++ _errno = fmt_fq_alloc( ++ &fmt_port->p_tx_fqs[i], ++ &fmt_egress_fq, ++ 0, ++ QMAN_FQ_FLAG_TO_DCPORTAL, ++ fm_get_tx_port_channel(fmt_port->p_tx_port), ++ i); ++ ++ if (_errno < 0) { ++ _fmt_err("tx queues allocation failed.\n"); ++ /* TODO: memory leak here if 1 queue is allocated and ++ * next queues are failing ... */ ++ return -EINVAL; ++ } ++ } ++ ++ /* port is valid and ready to use. */ ++ fmt_port->valid = TRUE; ++ ++ _fmt_dbg("called.\n"); ++ return 0; ++} ++ ++/* fm test chardev functions */ ++static int fmt_open(struct inode *inode, struct file *file) ++{ ++ unsigned int minor = iminor(inode); ++ ++ _fmt_dbg("calling...\n"); ++ ++ if (file->private_data != NULL) ++ return 0; ++ ++ /* The minor represent the port number. ++ * Set the port structure accordingly, thus all the operations ++ * will be done on this port. */ ++ if ((minor >= DEV_FM_TEST_PORTS_MINOR_BASE) && ++ (minor < DEV_FM_TEST_MAX_MINORS)) ++ file->private_data = &fm_test.ports[minor]; ++ else ++ return -ENXIO; ++ ++ _fmt_dbg("called.\n"); ++ return 0; ++} ++ ++static int fmt_close(struct inode *inode, struct file *file) ++{ ++ struct fmt_port_s *fmt_port = NULL; ++ struct fmt_frame_s *fmt_frame = NULL; ++ ++ int err = 0; ++ ++ _fmt_dbg("calling...\n"); ++ ++ fmt_port = file->private_data; ++ if (!fmt_port) ++ return -ENODEV; ++ ++ /* Close the current test port by invalidating it. */ ++ fmt_port->valid = FALSE; ++ ++ /* clean the fmt port queue */ ++ while ((fmt_frame = dequeue_fmt_frame(fmt_port)) != NULL) { ++ if (fmt_frame && fmt_frame->buff.p_data){ ++ kfree(fmt_frame->buff.p_data); ++ kfree(fmt_frame); ++ } ++ } ++ ++ /* !!! the qman queues are cleaning from fm_ioctl... ++ * - very ugly */ ++ ++ _fmt_dbg("called.\n"); ++ return err; ++} ++ ++static int fmt_ioctls(unsigned int minor, ++ struct file *file, ++ unsigned int cmd, ++ unsigned long arg, ++ bool compat) ++{ ++ struct fmt_port_s *fmt_port = NULL; ++ ++ _fmt_dbg("IOCTL minor:%u " ++ " arg:0x%08lx ioctl cmd (0x%08x):(0x%02x:0x%02x.\n", ++ minor, arg, cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); ++ ++ fmt_port = file->private_data; ++ if (!fmt_port) { ++ _fmt_err("invalid fmt port.\n"); ++ return -ENODEV; ++ } ++ ++ /* set test type properly */ ++ if (compat) ++ fmt_port->compat_test_type = true; ++ else ++ fmt_port->compat_test_type = false; ++ ++ switch (cmd) { ++ case FMT_PORT_IOC_INIT: ++ { ++ ioc_fmt_port_param_t param; ++ ++ if (fmt_port->valid) { ++ _fmt_wrn("port is already initialized.\n"); ++ return -EFAULT; ++ } ++#if defined(CONFIG_COMPAT) ++ if (compat) { ++ if (copy_from_user(¶m, ++ (ioc_fmt_port_param_t *)compat_ptr(arg), ++ sizeof(ioc_fmt_port_param_t))) ++ ++ return -EFAULT; ++ } else ++#endif ++ { ++ if (copy_from_user(¶m, ++ (ioc_fmt_port_param_t *) arg, ++ sizeof(ioc_fmt_port_param_t))) ++ ++ return -EFAULT; ++ } ++ ++ return fmt_port_init(fmt_port, ¶m); ++ } ++ ++ case FMT_PORT_IOC_SET_DIAG_MODE: ++ if (get_user(fmt_port->diag, (ioc_diag_mode *)arg)) ++ return -EFAULT; ++ ++ if (fmt_port->diag == e_IOC_DIAG_MODE_CTRL_LOOPBACK) ++ return set_mac_int_loopback(fmt_port, TRUE); ++ else ++ return set_mac_int_loopback(fmt_port, FALSE); ++ break; ++ ++ case FMT_PORT_IOC_SET_DPAECHO_MODE: ++ case FMT_PORT_IOC_SET_IP_HEADER_MANIP: ++ default: ++ _fmt_wrn("ioctl unimplemented minor:%u@ioctl" ++ " cmd:0x%08x(type:0x%02x, nr:0x%02x.\n", ++ minor, cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++#ifdef CONFIG_COMPAT ++static long fmt_compat_ioctl( ++ struct file *file, ++ unsigned int cmd, ++ unsigned long arg) ++{ ++ unsigned int minor = iminor(file->f_path.dentry->d_inode); ++ ++ _fmt_dbg("calling...\n"); ++ return fmt_ioctls(minor, file, cmd, arg, true); ++} ++#endif ++ ++static long fmt_ioctl( ++ struct file *file, ++ unsigned int cmd, ++ unsigned long arg) ++{ ++ unsigned int minor = iminor(file->f_path.dentry->d_inode); ++ unsigned int res; ++ ++ _fmt_dbg("calling...\n"); ++ ++ fm_mutex_lock(); ++ res = fmt_ioctls(minor, file, cmd, arg, false); ++ fm_mutex_unlock(); ++ ++ _fmt_dbg("called.\n"); ++ ++ return res; ++} ++ ++#ifdef CONFIG_COMPAT ++void copy_compat_test_frame_buffer( ++ ioc_fmt_buff_desc_t *buff, ++ ioc_fmt_compat_buff_desc_t *compat_buff) ++{ ++ compat_buff->qid = buff->qid; ++ compat_buff->p_data = ptr_to_compat(buff->p_data); ++ compat_buff->size = buff->size; ++ compat_buff->status = buff->status; ++ ++ compat_buff->buff_context.p_user_priv = ++ ptr_to_compat(buff->buff_context.p_user_priv); ++ memcpy(compat_buff->buff_context.fm_prs_res, ++ buff->buff_context.fm_prs_res, ++ FM_PRS_MAX * sizeof(uint8_t)); ++ memcpy(compat_buff->buff_context.fm_time_stamp, ++ buff->buff_context.fm_time_stamp, ++ FM_TIME_STAMP_MAX * sizeof(uint8_t)); ++} ++#endif ++ ++ssize_t fmt_read( ++ struct file *file, ++ char __user *buf, ++ size_t size, ++ loff_t *ppos) ++{ ++ struct fmt_port_s *fmt_port = NULL; ++ struct fmt_frame_s *p_fmt_frame = NULL; ++ ssize_t cnt = 0; ++ ++ fmt_port = file->private_data; ++ if (!fmt_port || !fmt_port->valid) { ++ _fmt_err("fmt port not valid!\n"); ++ return -ENODEV; ++ } ++ ++ p_fmt_frame = dequeue_fmt_frame(fmt_port); ++ if (p_fmt_frame == NULL) ++ return 0; ++ ++ _fmt_dbgr("calling...\n"); ++ ++#ifdef CONFIG_COMPAT ++ if (fmt_port->compat_test_type){ ++ cnt = sizeof(ioc_fmt_compat_buff_desc_t); ++ } ++ else ++#endif ++ { ++ cnt = sizeof(ioc_fmt_buff_desc_t); ++ } ++ ++ if (size < cnt) { ++ _fmt_err("illegal buffer-size!\n"); ++ cnt = 0; ++ goto _fmt_read_return; ++ } ++ ++ /* Copy structure */ ++#ifdef CONFIG_COMPAT ++ if (fmt_port->compat_test_type) { ++ { ++ ioc_fmt_compat_buff_desc_t compat_buff; ++ copy_compat_test_frame_buffer(&p_fmt_frame->buff, ++ &compat_buff); ++ ++ if (copy_to_user(buf, &compat_buff, cnt)) { ++ _fmt_err("copy_to_user failed!\n"); ++ goto _fmt_read_return; ++ } ++ } ++ ++ ((ioc_fmt_compat_buff_desc_t *)buf)->p_data = ++ ptr_to_compat(buf+sizeof(ioc_fmt_compat_buff_desc_t)); ++ cnt += MIN(p_fmt_frame->buff.size, size-cnt); ++ } else ++#endif ++ { ++ if (copy_to_user(buf, &p_fmt_frame->buff, cnt)) { ++ _fmt_err("copy_to_user failed!\n"); ++ goto _fmt_read_return; ++ } ++ ++ ((ioc_fmt_buff_desc_t *)buf)->p_data = ++ buf + sizeof(ioc_fmt_buff_desc_t); ++ cnt += MIN(p_fmt_frame->buff.size, size-cnt); ++ } ++ ++ if (size < cnt) { ++ _fmt_err("illegal buffer-size!\n"); ++ goto _fmt_read_return; ++ } ++ ++ /* copy frame */ ++#ifdef CONFIG_COMPAT ++ if (fmt_port->compat_test_type) { ++ if (copy_to_user(buf+sizeof(ioc_fmt_compat_buff_desc_t), ++ p_fmt_frame->buff.p_data, cnt)) { ++ _fmt_err("copy_to_user failed!\n"); ++ goto _fmt_read_return; ++ } ++ } else ++#endif ++ { ++ if (copy_to_user(buf+sizeof(ioc_fmt_buff_desc_t), ++ p_fmt_frame->buff.p_data, cnt)) { ++ _fmt_err("copy_to_user failed!\n"); ++ goto _fmt_read_return; ++ } ++ } ++ ++_fmt_read_return: ++ kfree(p_fmt_frame->buff.p_data); ++ kfree(p_fmt_frame); ++ ++ _fmt_dbgr("called.\n"); ++ return cnt; ++} ++ ++ssize_t fmt_write( ++ struct file *file, ++ const char __user *buf, ++ size_t size, ++ loff_t *ppos) ++{ ++ struct fmt_port_s *fmt_port = NULL; ++ ioc_fmt_buff_desc_t buff_desc; ++#ifdef CONFIG_COMPAT ++ ioc_fmt_compat_buff_desc_t buff_desc_compat; ++#endif ++ uint8_t *p_data = NULL; ++ uint32_t data_offset; ++ int _errno; ++ t_DpaaFD fd; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ fmt_port = file->private_data; ++ if (!fmt_port || !fmt_port->valid) { ++ _fmt_err("fmt port not valid.\n"); ++ return -EINVAL; ++ } ++ ++ /* If Compat (32B UserSpace - 64B KernelSpace) */ ++#ifdef CONFIG_COMPAT ++ if (fmt_port->compat_test_type) { ++ if (size < sizeof(ioc_fmt_compat_buff_desc_t)) { ++ _fmt_err("invalid buff_desc size.\n"); ++ return -EFAULT; ++ } ++ ++ if (copy_from_user(&buff_desc_compat, buf, ++ sizeof(ioc_fmt_compat_buff_desc_t))) ++ return -EFAULT; ++ ++ buff_desc.qid = buff_desc_compat.qid; ++ buff_desc.p_data = compat_ptr(buff_desc_compat.p_data); ++ buff_desc.size = buff_desc_compat.size; ++ buff_desc.status = buff_desc_compat.status; ++ ++ buff_desc.buff_context.p_user_priv = ++ compat_ptr(buff_desc_compat.buff_context.p_user_priv); ++ memcpy(buff_desc.buff_context.fm_prs_res, ++ buff_desc_compat.buff_context.fm_prs_res, ++ FM_PRS_MAX * sizeof(uint8_t)); ++ memcpy(buff_desc.buff_context.fm_time_stamp, ++ buff_desc_compat.buff_context.fm_time_stamp, ++ FM_TIME_STAMP_MAX * sizeof(uint8_t)); ++ } else ++#endif ++ { ++ if (size < sizeof(ioc_fmt_buff_desc_t)) { ++ _fmt_err("invalid buff_desc size.\n"); ++ return -EFAULT; ++ } ++ ++ if (copy_from_user(&buff_desc, (ioc_fmt_buff_desc_t *)buf, ++ sizeof(ioc_fmt_buff_desc_t))) ++ return -EFAULT; ++ } ++ ++ data_offset = FM_PORT_GetBufferDataOffset(fmt_port->p_tx_fm_port_dev); ++ p_data = kmalloc(buff_desc.size+data_offset, GFP_KERNEL); ++ if (!p_data) ++ return -ENOMEM; ++ ++ /* If Compat (32UserSpace - 64KernelSpace) the buff_desc.p_data is ok */ ++ if (copy_from_user((uint8_t *)PTR_MOVE(p_data, data_offset), ++ buff_desc.p_data, ++ buff_desc.size)) { ++ kfree(p_data); ++ return -EFAULT; ++ } ++ ++ /* TODO: dma_map_single here (cannnot access the bpool struct) */ ++ ++ /* prepare fd */ ++ memset(&fd, 0, sizeof(fd)); ++ DPAA_FD_SET_ADDR(&fd, p_data); ++ DPAA_FD_SET_OFFSET(&fd, data_offset); ++ DPAA_FD_SET_LENGTH(&fd, buff_desc.size); ++ ++ _errno = qman_enqueue(&fmt_port->p_tx_fqs[buff_desc.qid].fq_base, ++ (struct qm_fd *)&fd, 0); ++ if (_errno) { ++ buff_desc.status = (uint32_t)_errno; ++ if (copy_to_user((ioc_fmt_buff_desc_t *)buf, &buff_desc, ++ sizeof(ioc_fmt_buff_desc_t))) { ++ kfree(p_data); ++ return -EFAULT; ++ } ++ } ++ ++ /* for debugging */ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_inc(&fmt_port->enqueue_to_qman_frm); ++#endif ++ _fmt_dbgr("called.\n"); ++ return buff_desc.size; ++} ++ ++/* fm test character device definition */ ++static const struct file_operations fmt_fops = ++{ ++ .owner = THIS_MODULE, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = fmt_compat_ioctl, ++#endif ++ .unlocked_ioctl = fmt_ioctl, ++ .open = fmt_open, ++ .release = fmt_close, ++ .read = fmt_read, ++ .write = fmt_write, ++}; ++ ++static int fmt_init(void) ++{ ++ int id; ++ ++ _fmt_dbg("calling...\n"); ++ ++ /* Register to the /dev for IOCTL API */ ++ /* Register dynamically a new major number for the character device: */ ++ fm_test.major = register_chrdev(0, DEV_FM_TEST_NAME, &fmt_fops); ++ if (fm_test.major <= 0) { ++ _fmt_wrn("Failed to allocate major number for device %s.\n", ++ DEV_FM_TEST_NAME); ++ return -ENODEV; ++ } ++ ++ /* Creating class for FMan_test */ ++ fm_test.fmt_class = class_create(THIS_MODULE, DEV_FM_TEST_NAME); ++ if (IS_ERR(fm_test.fmt_class)) { ++ unregister_chrdev(fm_test.major, DEV_FM_TEST_NAME); ++ _fmt_wrn("Error creating %s class.\n", DEV_FM_TEST_NAME); ++ return -ENODEV; ++ } ++ ++ for (id = 0; id < IOC_FMT_MAX_NUM_OF_PORTS; id++) ++ if (NULL == device_create(fm_test.fmt_class, NULL, ++ MKDEV(fm_test.major, ++ DEV_FM_TEST_PORTS_MINOR_BASE + id), NULL, ++ DEV_FM_TEST_NAME "%d", id)) { ++ ++ _fmt_err("Error creating %s device.\n", ++ DEV_FM_TEST_NAME); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static void fmt_free(void) ++{ ++ int id; ++ ++ for (id = 0; id < IOC_FMT_MAX_NUM_OF_PORTS; id++) ++ device_destroy(fm_test.fmt_class, MKDEV(fm_test.major, ++ DEV_FM_TEST_PORTS_MINOR_BASE + id)); ++ class_destroy(fm_test.fmt_class); ++} ++ ++static int __init __cold fmt_load(void) ++{ ++ struct dpaa_eth_hooks_s priv_dpaa_eth_hooks; ++ ++ /* set dpaa hooks for default queues */ ++ memset(&priv_dpaa_eth_hooks, 0, sizeof(priv_dpaa_eth_hooks)); ++ priv_dpaa_eth_hooks.rx_default = fmt_rx_default_hook; ++ priv_dpaa_eth_hooks.rx_error = fmt_rx_error_hook; ++ priv_dpaa_eth_hooks.tx_confirm = fmt_tx_confirm_hook; ++ priv_dpaa_eth_hooks.tx_error = fmt_tx_confirm_error_hook; ++ ++ fsl_dpaa_eth_set_hooks(&priv_dpaa_eth_hooks); ++ ++ /* initialize the fman test environment */ ++ if (fmt_init() < 0) { ++ _fmt_err("Failed to init FM-test modul.\n"); ++ fmt_free(); ++ return -ENODEV; ++ } ++ ++ _fmt_inf("FSL FM test module loaded.\n"); ++ ++ return 0; ++} ++ ++static void __exit __cold fmt_unload(void) ++{ ++ fmt_free(); ++ _fmt_inf("FSL FM test module unloaded.\n"); ++} ++ ++module_init(fmt_load); ++module_exit(fmt_unload); +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_fm.c b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_fm.c +new file mode 100644 +index 0000000..8924679 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_fm.c +@@ -0,0 +1,1221 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_fm.c ++ @Author Shlomi Gridish ++ @Description FM Linux wrapper functions. ++*/ ++ ++#include ++#include ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* For struct qe_firmware */ ++#include ++#include /* For file access mask */ ++#include ++ ++/* NetCommSw Headers --------------- */ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "sprint_ext.h" ++#include "debug_ext.h" ++#include "sys_io_ext.h" ++ ++#include "fm_ioctls.h" ++ ++#include "lnxwrp_fm.h" ++#include "lnxwrp_resources.h" ++#include "lnxwrp_sysfs_fm.h" ++#include "lnxwrp_sysfs_fm_port.h" ++ ++#define PROC_PRINT(args...) offset += sprintf(buf+offset,args) ++ ++#define ADD_ADV_CONFIG_NO_RET(_func, _param) \ ++ do { \ ++ if (ip_Function = _func; \ ++ _param \ ++ i++; \ ++ } \ ++ else \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE,\ ++ ("Number of advanced-configuration entries exceeded"));\ ++ } while (0) ++ ++/* Bootarg used to override the Kconfig FSL_FM_MAX_FRAME_SIZE value */ ++#define FSL_FM_MAX_FRM_BOOTARG "fsl_fm_max_frm" ++ ++/* Bootarg used to override FSL_FM_RX_EXTRA_HEADROOM Kconfig value */ ++#define FSL_FM_RX_EXTRA_HEADROOM_BOOTARG "fsl_fm_rx_extra_headroom" ++ ++/* Maximum value for the fsl_fm_rx_extra_headroom bootarg */ ++#define FSL_FM_RX_EXTRA_HEADROOM_MAX 384 ++ ++/* ++ * Max frame size, across all interfaces. ++ * Configurable from Kconfig or bootargs, to avoid allocating ++ * oversized (socket) buffers when not using jumbo frames. ++ * Must be large enough to accomodate the network MTU, but small enough ++ * to avoid wasting skb memory. ++ * ++ * Could be overridden once, at boot-time, via the ++ * fm_set_max_frm() callback. ++ */ ++int fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE; ++ ++/* ++ * Extra headroom for Rx buffers. ++ * FMan is instructed to allocate, on the Rx path, this amount of ++ * space at the beginning of a data buffer, beside the DPA private ++ * data area and the IC fields. ++ * Does not impact Tx buffer layout. ++ * ++ * Configurable from Kconfig or bootargs. Zero by default, it's needed ++ * on particular forwarding scenarios that add extra headers to the ++ * forwarded frame. ++ */ ++int fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM; ++ ++static t_LnxWrpFm lnxWrpFm; ++ ++int fm_get_max_frm() ++{ ++ return fsl_fm_max_frm; ++} ++ ++int fm_get_rx_extra_headroom() ++{ ++ return fsl_fm_rx_extra_headroom; ++} ++ ++static int __init fm_set_max_frm(char *str) ++{ ++ int ret = 0; ++ ++ ret = get_option(&str, &fsl_fm_max_frm); ++ if (ret != 1) { ++ /* ++ * This will only work if CONFIG_EARLY_PRINTK is compiled in, ++ * and something like "earlyprintk=serial,uart0,115200" is ++ * specified in the bootargs ++ */ ++ printk(KERN_WARNING "No suitable %s= prop in bootargs; " ++ "will use the default FSL_FM_MAX_FRAME_SIZE (%d) " ++ "from Kconfig.\n", FSL_FM_MAX_FRM_BOOTARG, ++ CONFIG_FSL_FM_MAX_FRAME_SIZE); ++ ++ fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE; ++ return 1; ++ } ++ ++ /* Don't allow invalid bootargs; fallback to the Kconfig value */ ++ if (fsl_fm_max_frm < 64 || fsl_fm_max_frm > 9600) { ++ printk(KERN_WARNING "Invalid %s=%d in bootargs, valid range is " ++ "64-9600. Falling back to the FSL_FM_MAX_FRAME_SIZE (%d) " ++ "from Kconfig.\n", ++ FSL_FM_MAX_FRM_BOOTARG, fsl_fm_max_frm, ++ CONFIG_FSL_FM_MAX_FRAME_SIZE); ++ ++ fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE; ++ return 1; ++ } ++ ++ printk(KERN_INFO "Using fsl_fm_max_frm=%d from bootargs\n", ++ fsl_fm_max_frm); ++ return 0; ++} ++early_param(FSL_FM_MAX_FRM_BOOTARG, fm_set_max_frm); ++ ++static int __init fm_set_rx_extra_headroom(char *str) ++{ ++ int ret; ++ ++ ret = get_option(&str, &fsl_fm_rx_extra_headroom); ++ ++ if (ret != 1) { ++ printk(KERN_WARNING "No suitable %s= prop in bootargs; " ++ "will use the default FSL_FM_RX_EXTRA_HEADROOM (%d) " ++ "from Kconfig.\n", FSL_FM_RX_EXTRA_HEADROOM_BOOTARG, ++ CONFIG_FSL_FM_RX_EXTRA_HEADROOM); ++ fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM; ++ ++ return 1; ++ } ++ ++ if (fsl_fm_rx_extra_headroom < 0 || ++ fsl_fm_rx_extra_headroom > FSL_FM_RX_EXTRA_HEADROOM_MAX) { ++ printk(KERN_WARNING "Invalid value for %s= prop in " ++ "bootargs; will use the default " ++ "FSL_FM_RX_EXTRA_HEADROOM (%d) from Kconfig.\n", ++ FSL_FM_RX_EXTRA_HEADROOM_BOOTARG, ++ CONFIG_FSL_FM_RX_EXTRA_HEADROOM); ++ fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM; ++ } ++ ++ printk(KERN_INFO "Using fsl_fm_rx_extra_headroom=%d from bootargs\n", ++ fsl_fm_rx_extra_headroom); ++ ++ return 0; ++} ++early_param(FSL_FM_RX_EXTRA_HEADROOM_BOOTARG, fm_set_rx_extra_headroom); ++ ++static irqreturn_t fm_irq(int irq, void *_dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)_dev; ++ ++ if (!p_LnxWrpFmDev || !p_LnxWrpFmDev->h_Dev) ++ return IRQ_NONE; ++ ++ FM_EventIsr(p_LnxWrpFmDev->h_Dev); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t fm_err_irq(int irq, void *_dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)_dev; ++ ++ if (!p_LnxWrpFmDev || !p_LnxWrpFmDev->h_Dev) ++ return IRQ_NONE; ++ ++ if (FM_ErrorIsr(p_LnxWrpFmDev->h_Dev) == E_OK) ++ return IRQ_HANDLED; ++ ++ return IRQ_NONE; ++} ++ ++/* used to protect FMD/LLD from concurrent calls in functions fm_mutex_lock / fm_mutex_unlock */ ++static struct mutex lnxwrp_mutex; ++ ++static t_LnxWrpFmDev * CreateFmDev(uint8_t id) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ int j; ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *)XX_Malloc(sizeof(t_LnxWrpFmDev)); ++ if (!p_LnxWrpFmDev) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ return NULL; ++ } ++ ++ memset(p_LnxWrpFmDev, 0, sizeof(t_LnxWrpFmDev)); ++ p_LnxWrpFmDev->fmDevSettings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)); ++ memset(p_LnxWrpFmDev->fmDevSettings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry))); ++ p_LnxWrpFmDev->fmPcdDevSettings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)); ++ memset(p_LnxWrpFmDev->fmPcdDevSettings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry))); ++ p_LnxWrpFmDev->hcPort.settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)); ++ memset(p_LnxWrpFmDev->hcPort.settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry))); ++ for (j=0; jrxPorts[j].settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)); ++ memset(p_LnxWrpFmDev->rxPorts[j].settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry))); ++ } ++ for (j=0; jtxPorts[j].settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)); ++ memset(p_LnxWrpFmDev->txPorts[j].settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry))); ++ } ++ for (j=0; jopPorts[j].settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)); ++ memset(p_LnxWrpFmDev->opPorts[j].settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry))); ++ } ++ ++ return p_LnxWrpFmDev; ++} ++ ++static void DestroyFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ int j; ++ ++ for (j=0; jopPorts[j].settings.advConfig) ++ XX_Free(p_LnxWrpFmDev->opPorts[j].settings.advConfig); ++ for (j=0; jtxPorts[j].settings.advConfig) ++ XX_Free(p_LnxWrpFmDev->txPorts[j].settings.advConfig); ++ for (j=0; jrxPorts[j].settings.advConfig) ++ XX_Free(p_LnxWrpFmDev->rxPorts[j].settings.advConfig); ++ if (p_LnxWrpFmDev->hcPort.settings.advConfig) ++ XX_Free(p_LnxWrpFmDev->hcPort.settings.advConfig); ++ if (p_LnxWrpFmDev->fmPcdDevSettings.advConfig) ++ XX_Free(p_LnxWrpFmDev->fmPcdDevSettings.advConfig); ++ if (p_LnxWrpFmDev->fmDevSettings.advConfig) ++ XX_Free(p_LnxWrpFmDev->fmDevSettings.advConfig); ++ ++ XX_Free(p_LnxWrpFmDev); ++} ++ ++static t_Error FillRestFmInfo(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++#define FM_BMI_PPIDS_OFFSET 0x00080304 ++#define FM_DMA_PLR_OFFSET 0x000c2060 ++#define FM_FPM_IP_REV_1_OFFSET 0x000c30c4 ++#define DMA_HIGH_LIODN_MASK 0x0FFF0000 ++#define DMA_LOW_LIODN_MASK 0x00000FFF ++#define DMA_LIODN_SHIFT 16 ++ ++typedef _Packed struct { ++ uint32_t plr[32]; ++} _PackedType t_Plr; ++ ++typedef _Packed struct { ++ volatile uint32_t fmbm_ppid[63]; ++} _PackedType t_Ppids; ++ ++ t_Plr *p_Plr; ++ t_Ppids *p_Ppids; ++ int i,j; ++ uint32_t fmRev; ++ ++ static const uint8_t phys1GRxPortId[] = {0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf}; ++ static const uint8_t phys10GRxPortId[] = {0x10,0x11}; ++ static const uint8_t physOhPortId[] = {0x1,0x2,0x3,0x4,0x5,0x6,0x7}; ++ static const uint8_t phys1GTxPortId[] = {0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f}; ++ static const uint8_t phys10GTxPortId[] = {0x30,0x31}; ++ ++ fmRev = (uint32_t)(*((volatile uint32_t *)UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr+FM_FPM_IP_REV_1_OFFSET))); ++ fmRev &= 0xffff; ++ ++ p_Plr = (t_Plr *)UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr+FM_DMA_PLR_OFFSET); ++#ifdef MODULE ++ for (i=0;iplr[i] = 0; ++#endif /* MODULE */ ++ ++ for (i=0; iplr[i/2] & DMA_LOW_LIODN_MASK) : ++ ((p_Plr->plr[i/2] & DMA_HIGH_LIODN_MASK) >> DMA_LIODN_SHIFT)); ++#ifdef FM_PARTITION_ARRAY ++ /* TODO: this was .liodnPerPartition[i] = liodnBase; is the index meaning the same? */ ++ p_LnxWrpFmDev->fmDevSettings.param.liodnBasePerPort[i] = liodnBase; ++#endif /* FM_PARTITION_ARRAY */ ++ ++ if ((i >= phys1GRxPortId[0]) && ++ (i <= phys1GRxPortId[FM_MAX_NUM_OF_1G_RX_PORTS-1])) ++ { ++ for (j=0; jrxPorts[j].settings.param.liodnBase = liodnBase; ++ } ++ else if (FM_MAX_NUM_OF_10G_RX_PORTS && ++ (i >= phys10GRxPortId[0]) && ++ (i <= phys10GRxPortId[FM_MAX_NUM_OF_10G_RX_PORTS-1])) ++ { ++ for (j=0; jrxPorts[FM_MAX_NUM_OF_1G_RX_PORTS+j].settings.param.liodnBase = liodnBase; ++ } ++ else if ((i >= physOhPortId[0]) && ++ (i <= physOhPortId[FM_MAX_NUM_OF_OH_PORTS-1])) ++ { ++ for (j=0; jhcPort.settings.param.liodnBase = liodnBase; ++ else ++ p_LnxWrpFmDev->opPorts[j - 1].settings.param.liodnBase = liodnBase; ++ } ++ else if ((i >= phys1GTxPortId[0]) && ++ (i <= phys1GTxPortId[FM_MAX_NUM_OF_1G_TX_PORTS-1])) ++ { ++ for (j=0; jtxPorts[j].settings.param.liodnBase = liodnBase; ++ } ++ else if (FM_MAX_NUM_OF_10G_TX_PORTS && ++ (i >= phys10GTxPortId[0]) && ++ (i <= phys10GTxPortId[FM_MAX_NUM_OF_10G_TX_PORTS-1])) ++ { ++ for (j=0; jtxPorts[FM_MAX_NUM_OF_1G_TX_PORTS+j].settings.param.liodnBase = liodnBase; ++ } ++ } ++ ++ p_Ppids = (t_Ppids *)UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr+FM_BMI_PPIDS_OFFSET); ++ ++ for (i=0; irxPorts[i].settings.param.specificParams.rxParams.liodnOffset = ++ p_Ppids->fmbm_ppid[phys1GRxPortId[i]-1]; ++ ++ for (i=0; irxPorts[FM_MAX_NUM_OF_1G_RX_PORTS+i].settings.param.specificParams.rxParams.liodnOffset = ++ p_Ppids->fmbm_ppid[phys10GRxPortId[i]-1]; ++ ++#ifdef FM_OP_PARTITION_ERRATA_FMANx8 ++ for (i=0; iopPorts[i-1].settings.param.specificParams.nonRxParams.opLiodnOffset = ++ p_Ppids->fmbm_ppid[physOhPortId[i]-1]; ++ } ++#endif /* FM_OP_PARTITION_ERRATA_FMANx8 */ ++ ++ return E_OK; ++} ++ ++/** ++ * FindFmanMicrocode - find the Fman microcode ++ * ++ * This function returns a pointer to the QE Firmware blob that holds ++ * the Fman microcode. We use the QE Firmware structure because Fman microcode ++ * is similar to QE microcode, so there's no point in defining a new layout. ++ * ++ * Current versions of U-Boot embed the Fman firmware into the device tree, ++ * so we check for that first. Each Fman node in the device tree contains a ++ * node or a pointer to node that holds the firmware. Technically, we should ++ * be fetching the firmware node for the current Fman, but we don't have that ++ * information any more, so we assume that there is only one firmware node in ++ * the device tree, and that all Fmen use the same firmware. ++ */ ++static const struct qe_firmware *FindFmanMicrocode(void) ++{ ++ static const struct qe_firmware *P4080_UCPatch; ++ struct device_node *np; ++ ++ if (P4080_UCPatch) ++ return P4080_UCPatch; ++ ++ /* The firmware should be inside the device tree. */ ++ np = of_find_compatible_node(NULL, NULL, "fsl,fman-firmware"); ++ if (np) { ++ P4080_UCPatch = of_get_property(np, "fsl,firmware", NULL); ++ of_node_put(np); ++ if (P4080_UCPatch) ++ return P4080_UCPatch; ++ else ++ REPORT_ERROR(WARNING, E_NOT_FOUND, ("firmware node is incomplete")); ++ } ++ ++ /* Returning NULL here forces the reuse of the IRAM content */ ++ return NULL; ++} ++ ++static t_LnxWrpFmDev * ReadFmDevTreeNode (struct platform_device *of_dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ struct device_node *fm_node, *dev_node; ++ struct of_device_id name; ++ struct resource res; ++ const uint32_t *uint32_prop; ++ int _errno=0, lenp; ++ ++ fm_node = of_node_get(of_dev->dev.of_node); ++ ++ uint32_prop = (uint32_t *)of_get_property(fm_node, "cell-index", &lenp); ++ if (unlikely(uint32_prop == NULL)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_get_property(%s, cell-index) failed", fm_node->full_name)); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ if (*uint32_prop > INTG_MAX_NUM_OF_FM) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!")); ++ return NULL; ++ } ++ p_LnxWrpFmDev = CreateFmDev(*uint32_prop); ++ if (!p_LnxWrpFmDev) { ++ REPORT_ERROR(MAJOR, E_NULL_POINTER, NO_MSG); ++ return NULL; ++ } ++ p_LnxWrpFmDev->dev = &of_dev->dev; ++ p_LnxWrpFmDev->id = *uint32_prop; ++ ++ /* Get the FM interrupt */ ++ p_LnxWrpFmDev->irq = of_irq_to_resource(fm_node, 0, NULL); ++ if (unlikely(p_LnxWrpFmDev->irq == /*NO_IRQ*/0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_irq_to_resource() = %d", NO_IRQ)); ++ return NULL; ++ } ++ ++ /* Get the FM error interrupt */ ++ p_LnxWrpFmDev->err_irq = of_irq_to_resource(fm_node, 1, NULL); ++ /* TODO - un-comment it once there will be err_irq in the DTS */ ++#if 0 ++ if (unlikely(p_LnxWrpFmDev->err_irq == /*NO_IRQ*/0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_irq_to_resource() = %d", NO_IRQ)); ++ return NULL; ++ } ++#endif /* 0 */ ++ ++ /* Get the FM address */ ++ _errno = of_address_to_resource(fm_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno)); ++ return NULL; ++ } ++ ++ p_LnxWrpFmDev->fmBaseAddr = 0; ++ p_LnxWrpFmDev->fmPhysBaseAddr = res.start; ++ p_LnxWrpFmDev->fmMemSize = res.end + 1 - res.start; ++ ++ uint32_prop = (uint32_t *)of_get_property(fm_node, "clock-frequency", &lenp); ++ if (unlikely(uint32_prop == NULL)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_get_property(%s, clock-frequency) failed", fm_node->full_name)); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ p_LnxWrpFmDev->fmDevSettings.param.fmClkFreq = (*uint32_prop + 500000)/1000000; /* In MHz, rounded */ ++ ++ /* Get the MURAM base address and size */ ++ memset(&name, 0, sizeof(struct of_device_id)); ++ if (WARN_ON(strlen("muram") >= sizeof(name.name))) ++ return NULL; ++ strcpy(name.name, "muram"); ++ if (WARN_ON(strlen("fsl,fman-muram") >= sizeof(name.compatible))) ++ return NULL; ++ strcpy(name.compatible, "fsl,fman-muram"); ++ for_each_child_of_node(fm_node, dev_node) { ++ if (likely(of_match_node(&name, dev_node) != NULL)) { ++ _errno = of_address_to_resource(dev_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno)); ++ return NULL; ++ } ++ ++ p_LnxWrpFmDev->fmMuramBaseAddr = 0; ++ p_LnxWrpFmDev->fmMuramPhysBaseAddr = res.start; ++ p_LnxWrpFmDev->fmMuramMemSize = res.end + 1 - res.start; ++ } ++ } ++ ++ /* Get the RTC base address and size */ ++ memset(&name, 0, sizeof(struct of_device_id)); ++ if (WARN_ON(strlen("rtc") >= sizeof(name.name))) ++ return NULL; ++ strcpy(name.name, "rtc"); ++ if (WARN_ON(strlen("fsl,fman-rtc") >= sizeof(name.compatible))) ++ return NULL; ++ strcpy(name.compatible, "fsl,fman-rtc"); ++ for_each_child_of_node(fm_node, dev_node) { ++ if (likely(of_match_node(&name, dev_node) != NULL)) { ++ _errno = of_address_to_resource(dev_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno)); ++ return NULL; ++ } ++ ++ p_LnxWrpFmDev->fmRtcBaseAddr = 0; ++ p_LnxWrpFmDev->fmRtcPhysBaseAddr = res.start; ++ p_LnxWrpFmDev->fmRtcMemSize = res.end + 1 - res.start; ++ } ++ } ++ ++#if (DPAA_VERSION >= 11) ++ /* Get the VSP base address */ ++ for_each_child_of_node(fm_node, dev_node) { ++ if (of_device_is_compatible(dev_node, "fsl,fman-vsps")) { ++ _errno = of_address_to_resource(dev_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno)); ++ return NULL; ++ } ++ p_LnxWrpFmDev->fmVspBaseAddr = 0; ++ p_LnxWrpFmDev->fmVspPhysBaseAddr = res.start; ++ p_LnxWrpFmDev->fmVspMemSize = res.end + 1 - res.start; ++ } ++ } ++#endif ++ ++ /* Get all PCD nodes */ ++ memset(&name, 0, sizeof(struct of_device_id)); ++ if (WARN_ON(strlen("parser") >= sizeof(name.name))) ++ return NULL; ++ strcpy(name.name, "parser"); ++ if (WARN_ON(strlen("fsl,fman-parser") >= sizeof(name.compatible))) ++ return NULL; ++ strcpy(name.compatible, "fsl,fman-parser"); ++ for_each_child_of_node(fm_node, dev_node) ++ if (likely(of_match_node(&name, dev_node) != NULL)) ++ p_LnxWrpFmDev->prsActive = TRUE; ++ ++ memset(&name, 0, sizeof(struct of_device_id)); ++ if (WARN_ON(strlen("keygen") >= sizeof(name.name))) ++ return NULL; ++ strcpy(name.name, "keygen"); ++ if (WARN_ON(strlen("fsl,fman-keygen") >= sizeof(name.compatible))) ++ return NULL; ++ strcpy(name.compatible, "fsl,fman-keygen"); ++ for_each_child_of_node(fm_node, dev_node) ++ if (likely(of_match_node(&name, dev_node) != NULL)) ++ p_LnxWrpFmDev->kgActive = TRUE; ++ ++ memset(&name, 0, sizeof(struct of_device_id)); ++ if (WARN_ON(strlen("cc") >= sizeof(name.name))) ++ return NULL; ++ strcpy(name.name, "cc"); ++ if (WARN_ON(strlen("fsl,fman-cc") >= sizeof(name.compatible))) ++ return NULL; ++ strcpy(name.compatible, "fsl,fman-cc"); ++ for_each_child_of_node(fm_node, dev_node) ++ if (likely(of_match_node(&name, dev_node) != NULL)) ++ p_LnxWrpFmDev->ccActive = TRUE; ++ ++ memset(&name, 0, sizeof(struct of_device_id)); ++ if (WARN_ON(strlen("policer") >= sizeof(name.name))) ++ return NULL; ++ strcpy(name.name, "policer"); ++ if (WARN_ON(strlen("fsl,fman-policer") >= sizeof(name.compatible))) ++ return NULL; ++ strcpy(name.compatible, "fsl,fman-policer"); ++ for_each_child_of_node(fm_node, dev_node) ++ if (likely(of_match_node(&name, dev_node) != NULL)) ++ p_LnxWrpFmDev->plcrActive = TRUE; ++ ++ if (p_LnxWrpFmDev->prsActive || p_LnxWrpFmDev->kgActive || ++ p_LnxWrpFmDev->ccActive || p_LnxWrpFmDev->plcrActive) ++ p_LnxWrpFmDev->pcdActive = TRUE; ++ ++ if (p_LnxWrpFmDev->pcdActive) ++ { ++ const char *str_prop = (char *)of_get_property(fm_node, "fsl,default-pcd", &lenp); ++ if (str_prop) { ++ if (strncmp(str_prop, "3-tuple", strlen("3-tuple")) == 0) ++ p_LnxWrpFmDev->defPcd = e_FM_PCD_3_TUPLE; ++ } ++ else ++ p_LnxWrpFmDev->defPcd = e_NO_PCD; ++ } ++ ++ of_node_put(fm_node); ++ ++ p_LnxWrpFmDev->hcCh = ++ qman_affine_channel(cpumask_first(qman_affine_cpus())); ++ ++ p_LnxWrpFmDev->active = TRUE; ++ ++ return p_LnxWrpFmDev; ++} ++ ++static void LnxwrpFmDevExceptionsCb(t_Handle h_App, e_FmExceptions exception) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)h_App; ++ ++ ASSERT_COND(p_LnxWrpFmDev); ++ ++ DBG(INFO, ("got fm exception %d", exception)); ++ ++ /* do nothing */ ++ UNUSED(exception); ++} ++ ++static void LnxwrpFmDevBusErrorCb(t_Handle h_App, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint64_t addr, ++ uint8_t tnum, ++ uint16_t liodn) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)h_App; ++ ++ ASSERT_COND(p_LnxWrpFmDev); ++ ++ /* do nothing */ ++ UNUSED(portType);UNUSED(portId);UNUSED(addr);UNUSED(tnum);UNUSED(liodn); ++} ++ ++static t_Error ConfigureFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ struct resource *dev_res; ++ int _errno; ++ ++ if (!p_LnxWrpFmDev->active) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM not configured!!!")); ++ ++#ifndef MODULE ++ _errno = can_request_irq(p_LnxWrpFmDev->irq, 0); ++ if (unlikely(_errno < 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("can_request_irq() = %d", _errno)); ++#endif ++ _errno = devm_request_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->irq, fm_irq, 0, "fman", p_LnxWrpFmDev); ++ if (unlikely(_errno < 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_irq(%d) = %d", p_LnxWrpFmDev->irq, _errno)); ++ ++ if (p_LnxWrpFmDev->err_irq != 0) { ++#ifndef MODULE ++ _errno = can_request_irq(p_LnxWrpFmDev->err_irq, 0); ++ if (unlikely(_errno < 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("can_request_irq() = %d", _errno)); ++#endif ++ _errno = devm_request_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->err_irq, fm_err_irq, IRQF_SHARED, "fman-err", p_LnxWrpFmDev); ++ if (unlikely(_errno < 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_irq(%d) = %d", p_LnxWrpFmDev->err_irq, _errno)); ++ } ++ ++ p_LnxWrpFmDev->res = devm_request_mem_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize, "fman"); ++ if (unlikely(p_LnxWrpFmDev->res == NULL)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_mem_region() failed")); ++ ++ p_LnxWrpFmDev->fmBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize)); ++ if (unlikely(p_LnxWrpFmDev->fmBaseAddr == 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed")); ++ ++ if (SYS_RegisterIoMap((uint64_t)p_LnxWrpFmDev->fmBaseAddr, (uint64_t)p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM memory map")); ++ ++ dev_res = __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize, "fman-muram"); ++ if (unlikely(dev_res == NULL)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("__devm_request_region() failed")); ++ ++ p_LnxWrpFmDev->fmMuramBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize)); ++ if (unlikely(p_LnxWrpFmDev->fmMuramBaseAddr == 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed")); ++ ++ if (SYS_RegisterIoMap((uint64_t)p_LnxWrpFmDev->fmMuramBaseAddr, (uint64_t)p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM MURAM memory map")); ++ ++ if (p_LnxWrpFmDev->fmRtcPhysBaseAddr) ++ { ++ dev_res = __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize, "fman-rtc"); ++ if (unlikely(dev_res == NULL)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("__devm_request_region() failed")); ++ ++ p_LnxWrpFmDev->fmRtcBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize)); ++ if (unlikely(p_LnxWrpFmDev->fmRtcBaseAddr == 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed")); ++ ++ if (SYS_RegisterIoMap((uint64_t)p_LnxWrpFmDev->fmRtcBaseAddr, (uint64_t)p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-RTC memory map")); ++ } ++ ++#if (DPAA_VERSION >= 11) ++ if (p_LnxWrpFmDev->fmVspPhysBaseAddr) { ++ dev_res = __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmVspPhysBaseAddr, p_LnxWrpFmDev->fmVspMemSize, "fman-vsp"); ++ if (unlikely(dev_res == NULL)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("__devm_request_region() failed")); ++ ++ p_LnxWrpFmDev->fmVspBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmVspPhysBaseAddr, p_LnxWrpFmDev->fmVspMemSize)); ++ if (unlikely(p_LnxWrpFmDev->fmVspBaseAddr == 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed")); ++ } ++#endif ++ ++ p_LnxWrpFmDev->fmDevSettings.param.baseAddr = p_LnxWrpFmDev->fmBaseAddr; ++ p_LnxWrpFmDev->fmDevSettings.param.fmId = p_LnxWrpFmDev->id; ++ p_LnxWrpFmDev->fmDevSettings.param.irq = NO_IRQ; ++ p_LnxWrpFmDev->fmDevSettings.param.errIrq = NO_IRQ; ++ p_LnxWrpFmDev->fmDevSettings.param.f_Exception = LnxwrpFmDevExceptionsCb; ++ p_LnxWrpFmDev->fmDevSettings.param.f_BusError = LnxwrpFmDevBusErrorCb; ++ p_LnxWrpFmDev->fmDevSettings.param.h_App = p_LnxWrpFmDev; ++ ++ return FillRestFmInfo(p_LnxWrpFmDev); ++} ++ ++static t_Error InitFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ const struct qe_firmware *fw; ++ ++ if (!p_LnxWrpFmDev->active) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM not configured!!!")); ++ ++ if ((p_LnxWrpFmDev->h_MuramDev = FM_MURAM_ConfigAndInit(p_LnxWrpFmDev->fmMuramBaseAddr, p_LnxWrpFmDev->fmMuramMemSize)) == NULL) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-MURAM!")); ++ ++ /* Loading the fman-controller code */ ++ fw = FindFmanMicrocode(); ++ ++ if (!fw) { ++ /* this forces the reuse of the current IRAM content */ ++ p_LnxWrpFmDev->fmDevSettings.param.firmware.size = 0; ++ p_LnxWrpFmDev->fmDevSettings.param.firmware.p_Code = NULL; ++ } else { ++ p_LnxWrpFmDev->fmDevSettings.param.firmware.p_Code = ++ (void *) fw + fw->microcode[0].code_offset; ++ p_LnxWrpFmDev->fmDevSettings.param.firmware.size = ++ sizeof(u32) * fw->microcode[0].count; ++ DBG(INFO, ("Loading fman-controller code version %d.%d.%d", ++ fw->microcode[0].major, ++ fw->microcode[0].minor, ++ fw->microcode[0].revision)); ++ } ++ ++ p_LnxWrpFmDev->fmDevSettings.param.h_FmMuram = p_LnxWrpFmDev->h_MuramDev; ++ ++#if (DPAA_VERSION >= 11) ++ if (p_LnxWrpFmDev->fmVspBaseAddr) { ++ p_LnxWrpFmDev->fmDevSettings.param.vspBaseAddr = p_LnxWrpFmDev->fmVspBaseAddr; ++ p_LnxWrpFmDev->fmDevSettings.param.partVSPBase = 0; ++ p_LnxWrpFmDev->fmDevSettings.param.partNumOfVSPs = FM_VSP_MAX_NUM_OF_ENTRIES; ++ } ++#endif ++ ++ if ((p_LnxWrpFmDev->h_Dev = FM_Config(&p_LnxWrpFmDev->fmDevSettings.param)) == NULL) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM")); ++ ++ ++ if (FM_ConfigResetOnInit(p_LnxWrpFmDev->h_Dev, TRUE) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM")); ++ ++#ifdef CONFIG_FMAN_P1023 ++ if (FM_ConfigDmaAidOverride(p_LnxWrpFmDev->h_Dev, TRUE) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM")); ++#endif ++ ++ ++#if defined(CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM) && defined(CONFIG_FMAN_P3040_P4080_P5020) ++ /* Enable 14g w/ jumbo frames following HW suggestion. */ ++ FM_ConfigTotalFifoSize(p_LnxWrpFmDev->h_Dev, 128*KILOBYTE); ++#elif defined(CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM) && defined(CONFIG_FMAN_P1023) ++ FM_ConfigTotalFifoSize(p_LnxWrpFmDev->h_Dev, 48*KILOBYTE); ++#endif ++#if (DPAA_VERSION >= 11) ++#define DEFAULT_TOTAL_FIFO_SIZE_FOR_FMAN_V3H 295*KILOBYTE ++ FM_ConfigTotalFifoSize(p_LnxWrpFmDev->h_Dev, ++ DEFAULT_TOTAL_FIFO_SIZE_FOR_FMAN_V3H); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (FM_Init(p_LnxWrpFmDev->h_Dev) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM")); ++ ++ /* TODO: Why we mask these interrupts? */ ++ if (p_LnxWrpFmDev->err_irq == 0) { ++ FM_SetException(p_LnxWrpFmDev->h_Dev, e_FM_EX_DMA_BUS_ERROR,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_READ_ECC,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_SYSTEM_WRITE_ECC,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_FM_WRITE_ECC,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_SINGLE_PORT_ECC, FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_FPM_STALL_ON_TASKS , FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_FPM_SINGLE_ECC, FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_FPM_DOUBLE_ECC,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_QMI_SINGLE_ECC, FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_QMI_DOUBLE_ECC,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_LIST_RAM_ECC,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_STORAGE_PROFILE_ECC, FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_STATISTICS_RAM_ECC, FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_DISPATCH_RAM_ECC, FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_IRAM_ECC,FALSE); ++ /* TODO: FmDisableRamsEcc assert for ramsEccOwners. ++ * FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_MURAM_ECC,FALSE);*/ ++ } ++ ++ if (p_LnxWrpFmDev->fmRtcBaseAddr) ++ { ++ t_FmRtcParams fmRtcParam; ++ ++ memset(&fmRtcParam, 0, sizeof(fmRtcParam)); ++ fmRtcParam.h_App = p_LnxWrpFmDev; ++ fmRtcParam.h_Fm = p_LnxWrpFmDev->h_Dev; ++ fmRtcParam.baseAddress = p_LnxWrpFmDev->fmRtcBaseAddr; ++ ++ if(!(p_LnxWrpFmDev->h_RtcDev = FM_RTC_Config(&fmRtcParam))) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-RTC")); ++ ++ if (FM_RTC_ConfigPeriod(p_LnxWrpFmDev->h_RtcDev, 5) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-RTC")); ++ ++ if (FM_RTC_Init(p_LnxWrpFmDev->h_RtcDev) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-RTC")); ++ } ++ ++ return E_OK; ++} ++ ++/* TODO: to be moved back here */ ++extern void FreeFmPcdDev(t_LnxWrpFmDev *p_LnxWrpFmDev); ++ ++static void FreeFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ if (!p_LnxWrpFmDev->active) ++ return; ++ ++ FreeFmPcdDev(p_LnxWrpFmDev); ++ ++ if (p_LnxWrpFmDev->h_RtcDev) ++ FM_RTC_Free(p_LnxWrpFmDev->h_RtcDev); ++ ++ if (p_LnxWrpFmDev->h_Dev) ++ FM_Free(p_LnxWrpFmDev->h_Dev); ++ ++ if (p_LnxWrpFmDev->h_MuramDev) ++ FM_MURAM_Free(p_LnxWrpFmDev->h_MuramDev); ++ ++ if (p_LnxWrpFmDev->fmRtcBaseAddr) ++ { ++ SYS_UnregisterIoMap(p_LnxWrpFmDev->fmRtcBaseAddr); ++ devm_iounmap(p_LnxWrpFmDev->dev, UINT_TO_PTR(p_LnxWrpFmDev->fmRtcBaseAddr)); ++ __devm_release_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize); ++ } ++ SYS_UnregisterIoMap(p_LnxWrpFmDev->fmMuramBaseAddr); ++ devm_iounmap(p_LnxWrpFmDev->dev, UINT_TO_PTR(p_LnxWrpFmDev->fmMuramBaseAddr)); ++ __devm_release_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize); ++ SYS_UnregisterIoMap(p_LnxWrpFmDev->fmBaseAddr); ++ devm_iounmap(p_LnxWrpFmDev->dev, UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr)); ++ devm_release_mem_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize); ++ if (p_LnxWrpFmDev->err_irq != 0) { ++ devm_free_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->err_irq, p_LnxWrpFmDev); ++ } ++ ++ devm_free_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->irq, p_LnxWrpFmDev); ++} ++ ++/* FMan character device file operations */ ++extern struct file_operations fm_fops; ++ ++static int /*__devinit*/ fm_probe(struct platform_device *of_dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ ++ if ((p_LnxWrpFmDev = ReadFmDevTreeNode(of_dev)) == NULL) ++ return -EIO; ++ if (ConfigureFmDev(p_LnxWrpFmDev) != E_OK) ++ return -EIO; ++ if (InitFmDev(p_LnxWrpFmDev) != E_OK) ++ return -EIO; ++ ++ /* IOCTL ABI checking */ ++ LnxWrpPCDIOCTLEnumChecking(); ++ LnxWrpPCDIOCTLTypeChecking(); ++ ++ Sprint (p_LnxWrpFmDev->name, "%s%d", DEV_FM_NAME, p_LnxWrpFmDev->id); ++ ++ /* Register to the /dev for IOCTL API */ ++ /* Register dynamically a new major number for the character device: */ ++ if ((p_LnxWrpFmDev->major = register_chrdev(0, p_LnxWrpFmDev->name, &fm_fops)) <= 0) { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Failed to allocate a major number for device \"%s\"", p_LnxWrpFmDev->name)); ++ return -EIO; ++ } ++ ++ /* Creating classes for FM */ ++ DBG(TRACE ,("class_create fm_class")); ++ p_LnxWrpFmDev->fm_class = class_create(THIS_MODULE, p_LnxWrpFmDev->name); ++ if (IS_ERR(p_LnxWrpFmDev->fm_class)) { ++ unregister_chrdev(p_LnxWrpFmDev->major, p_LnxWrpFmDev->name); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("class_create error fm_class")); ++ return -EIO; ++ } ++ ++ device_create(p_LnxWrpFmDev->fm_class, NULL, MKDEV(p_LnxWrpFmDev->major, DEV_FM_MINOR_BASE), NULL, ++ "fm%d", p_LnxWrpFmDev->id); ++ device_create(p_LnxWrpFmDev->fm_class, NULL, MKDEV(p_LnxWrpFmDev->major, DEV_FM_PCD_MINOR_BASE), NULL, ++ "fm%d-pcd", p_LnxWrpFmDev->id); ++ dev_set_drvdata(p_LnxWrpFmDev->dev, p_LnxWrpFmDev); ++ ++ /* create sysfs entries for stats and regs */ ++ if ( fm_sysfs_create(p_LnxWrpFmDev->dev) !=0 ) ++ { ++ FreeFmDev(p_LnxWrpFmDev); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Unable to create sysfs entry - fm!!!")); ++ return -EIO; ++ } ++ ++ DBG(TRACE, ("FM%d probed", p_LnxWrpFmDev->id)); ++ ++#if defined(CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM) ++ /* Precalculate resources for FMAN based on number of ++ * FMan ports available ++ */ ++ if(fm_set_active_fman_ports(of_dev, p_LnxWrpFmDev)!= 0) ++ return -EIO; ++ ++#if defined(CONFIG_FMAN_P3040_P4080_P5020) ++ /* 128K MURAM for p3,p4 and p5 */ ++ if(fm_precalculate_fifosizes( ++ p_LnxWrpFmDev, ++ 128*KILOBYTE) ++ != 0) ++ return -EIO; ++#else ++ /* for all other platforms: MURAM Space for fifosize=3/4 * MURAM_SIZE*/ ++ if(fm_precalculate_fifosizes( ++ p_LnxWrpFmDev, ++ 48*KILOBYTE) ++ != 0) ++ return -EIO; ++#endif ++ if(fm_precalculate_open_dma( ++ p_LnxWrpFmDev, ++ BMI_MAX_NUM_OF_DMAS, /* max open dmas:dpaa_integration_ext.h */ ++ FM_DEFAULT_TX10G_OPENDMA, /* default TX 10g open dmas */ ++ FM_DEFAULT_RX10G_OPENDMA, /* default RX 10g open dmas */ ++ FM_10G_OPENDMA_MIN_TRESHOLD,/* TX 10g minimum treshold */ ++ FM_10G_OPENDMA_MIN_TRESHOLD)/* RX 10g minimum treshold */ ++ != 0) ++ return -EIO; ++ if(fm_precalculate_tnums( ++ p_LnxWrpFmDev, ++ BMI_MAX_NUM_OF_TASKS) /* max TNUMS: dpa integration file. */ ++ != 0) ++ return -EIO; ++#endif ++ ++ return 0; ++} ++ ++static int __devexit fm_remove(struct platform_device *of_dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ struct device *dev; ++ ++ dev = &of_dev->dev; ++ p_LnxWrpFmDev = dev_get_drvdata(dev); ++ ++ fm_sysfs_destroy(dev); ++ ++ DBG(TRACE, ("destroy fm_class")); ++ device_destroy(p_LnxWrpFmDev->fm_class, MKDEV(p_LnxWrpFmDev->major, DEV_FM_MINOR_BASE)); ++ device_destroy(p_LnxWrpFmDev->fm_class, MKDEV(p_LnxWrpFmDev->major, DEV_FM_PCD_MINOR_BASE)); ++ class_destroy(p_LnxWrpFmDev->fm_class); ++ ++ /* Destroy chardev */ ++ unregister_chrdev(p_LnxWrpFmDev->major, p_LnxWrpFmDev->name); ++ ++ FreeFmDev(p_LnxWrpFmDev); ++ ++ DestroyFmDev(p_LnxWrpFmDev); ++ ++ dev_set_drvdata(dev, NULL); ++ ++ return 0; ++} ++ ++static const struct of_device_id fm_match[] __devinitconst = { ++ { ++ .compatible = "fsl,fman" ++ }, ++ {} ++}; ++#ifndef MODULE ++MODULE_DEVICE_TABLE(of, fm_match); ++#endif /* !MODULE */ ++ ++static struct platform_driver fm_driver = { ++ .driver = { ++ .name = "fsl-fman", ++ .of_match_table = fm_match, ++ .owner = THIS_MODULE, ++ }, ++ .probe = fm_probe, ++ .remove = __devexit_p(fm_remove) ++}; ++ ++t_Handle LNXWRP_FM_Init(void) ++{ ++ memset(&lnxWrpFm, 0, sizeof(lnxWrpFm)); ++ mutex_init(&lnxwrp_mutex); ++ ++ /* Register to the DTB for basic FM API */ ++ platform_driver_register(&fm_driver); ++ ++ return &lnxWrpFm; ++} ++ ++t_Error LNXWRP_FM_Free(t_Handle h_LnxWrpFm) ++{ ++ platform_driver_unregister(&fm_driver); ++ mutex_destroy(&lnxwrp_mutex); ++ ++ return E_OK; ++} ++ ++ ++struct fm * fm_bind(struct device *fm_dev) ++{ ++ return (struct fm *)(dev_get_drvdata(get_device(fm_dev))); ++} ++EXPORT_SYMBOL(fm_bind); ++ ++void fm_unbind(struct fm *fm) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm; ++ ++ put_device(p_LnxWrpFmDev->dev); ++} ++EXPORT_SYMBOL(fm_unbind); ++ ++struct resource * fm_get_mem_region(struct fm *fm) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm; ++ ++ return p_LnxWrpFmDev->res; ++} ++EXPORT_SYMBOL(fm_get_mem_region); ++ ++void * fm_get_handle(struct fm *fm) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm; ++ ++ return (void *)p_LnxWrpFmDev->h_Dev; ++} ++EXPORT_SYMBOL(fm_get_handle); ++ ++void * fm_get_rtc_handle(struct fm *fm) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm; ++ ++ return (void *)p_LnxWrpFmDev->h_RtcDev; ++} ++EXPORT_SYMBOL(fm_get_rtc_handle); ++ ++struct fm_port * fm_port_bind (struct device *fm_port_dev) ++{ ++ return (struct fm_port *)(dev_get_drvdata(get_device(fm_port_dev))); ++} ++EXPORT_SYMBOL(fm_port_bind); ++ ++void fm_port_unbind(struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port; ++ ++ put_device(p_LnxWrpFmPortDev->dev); ++} ++EXPORT_SYMBOL(fm_port_unbind); ++ ++void * fm_port_get_handle(struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port; ++ ++ return (void *)p_LnxWrpFmPortDev->h_Dev; ++} ++EXPORT_SYMBOL(fm_port_get_handle); ++ ++void fm_port_get_base_addr(const struct fm_port *port, uint64_t *base_addr) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; ++ ++ *base_addr = p_LnxWrpFmPortDev->settings.param.baseAddr; ++} ++EXPORT_SYMBOL(fm_port_get_base_addr); ++ ++void fm_port_pcd_bind (struct fm_port *port, struct fm_port_pcd_param *params) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port; ++ ++ p_LnxWrpFmPortDev->pcd_owner_params.cba = params->cba; ++ p_LnxWrpFmPortDev->pcd_owner_params.cbf = params->cbf; ++ p_LnxWrpFmPortDev->pcd_owner_params.dev = params->dev; ++} ++EXPORT_SYMBOL(fm_port_pcd_bind); ++ ++int fm_get_tx_port_channel(struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port; ++ ++ return p_LnxWrpFmPortDev->txCh; ++} ++EXPORT_SYMBOL(fm_get_tx_port_channel); ++ ++int fm_port_enable (struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port; ++ ++ FM_PORT_Enable(p_LnxWrpFmPortDev->h_Dev); ++ ++ return 0; ++} ++EXPORT_SYMBOL(fm_port_enable); ++ ++void fm_port_disable(struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port; ++ ++ FM_PORT_Disable(p_LnxWrpFmPortDev->h_Dev); ++} ++EXPORT_SYMBOL(fm_port_disable); ++ ++void fm_mutex_lock(void) ++{ ++ mutex_lock(&lnxwrp_mutex); ++} ++EXPORT_SYMBOL(fm_mutex_lock); ++ ++void fm_mutex_unlock(void) ++{ ++ mutex_unlock(&lnxwrp_mutex); ++} ++EXPORT_SYMBOL(fm_mutex_unlock); ++ ++static t_Handle h_FmLnxWrp; ++ ++static int __init __cold fm_load (void) ++{ ++ if ((h_FmLnxWrp = LNXWRP_FM_Init()) == NULL) ++ { ++ printk("Failed to init FM wrapper!\n"); ++ return -ENODEV; ++ } ++ ++ printk(KERN_CRIT "Freescale FM module ("__DATE__ ":"__TIME__")," \ ++ " FMD API version %d.%d.%d\n", ++ FMD_API_VERSION_MAJOR, ++ FMD_API_VERSION_MINOR, ++ FMD_API_VERSION_RESPIN); ++ return 0; ++} ++ ++static void __exit __cold fm_unload (void) ++{ ++ if (h_FmLnxWrp) ++ LNXWRP_FM_Free(h_FmLnxWrp); ++} ++ ++module_init (fm_load); ++module_exit (fm_unload); +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_fm.h b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_fm.h +new file mode 100644 +index 0000000..40f0934 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_fm.h +@@ -0,0 +1,273 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_fm.h ++ ++ @Author Shlomi Gridish ++ ++ @Description FM Linux wrapper functions. ++ ++*/ ++ ++#ifndef __LNXWRP_FM_H__ ++#define __LNXWRP_FM_H__ ++ ++#include /* struct qman_fq */ ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++ ++#include "lnxwrp_fm_ext.h" ++ ++#define __ERR_MODULE__ MODULE_FM ++ ++#define FM_MAX_NUM_OF_ADV_SETTINGS 10 ++ ++#define LNXWRP_FM_NUM_OF_SHARED_PROFILES 16 ++ ++#if defined(CONFIG_FMAN_DISABLE_OH_TO_REUSE_RESOURCES) ++#define FM_10G_OPENDMA_MIN_TRESHOLD 8 /* 10g minimum treshold if only HC is enabled and no OH port enabled */ ++#define FM_OPENDMA_RX_TX_RAPORT 2 /* RX = 2*TX */ ++#else ++#define FM_10G_OPENDMA_MIN_TRESHOLD 7 /* 10g minimum treshold if 7 OH ports are enabled */ ++#define FM_OPENDMA_RX_TX_RAPORT 1 /* RX = TX */ ++#endif ++#define FM_DEFAULT_TX10G_OPENDMA 8 /* default TX 10g open dmas */ ++#define FM_DEFAULT_RX10G_OPENDMA 8 /* default RX 10g open dmas */ ++ ++#define FRAG_MANIP_SPACE 128 ++#define FRAG_DATA_ALIGN 64 ++ ++#ifndef CONFIG_FSL_FM_MAX_FRAME_SIZE ++#define CONFIG_FSL_FM_MAX_FRAME_SIZE 0 ++#endif ++ ++#ifndef CONFIG_FSL_FM_RX_EXTRA_HEADROOM ++#define CONFIG_FSL_FM_RX_EXTRA_HEADROOM 0 ++#endif ++ ++typedef enum { ++ e_NO_PCD = 0, ++ e_FM_PCD_3_TUPLE ++} e_LnxWrpFmPortPcdDefUseCase; ++ ++ ++typedef struct t_FmTestFq { ++ struct qman_fq fq_base; ++ t_Handle h_Arg; ++} t_FmTestFq; ++ ++typedef struct { ++ uint8_t id; /* sw port id, see SW_PORT_ID_TO_HW_PORT_ID() in fm_common.h */ ++ int minor; ++ char name[20]; ++ bool active; ++ uint64_t phys_baseAddr; ++ uint64_t baseAddr; /* Port's *virtual* address */ ++ uint32_t memSize; ++ t_WrpFmPortDevSettings settings; ++ uint8_t totalNumOfSchemes; ++ uint8_t schemesBase; ++ uint8_t numOfSchemesUsed; ++ uint32_t pcdBaseQ; ++ uint16_t pcdNumOfQs; ++ struct fm_port_pcd_param pcd_owner_params; ++ e_LnxWrpFmPortPcdDefUseCase defPcd; ++ t_Handle h_DefNetEnv; ++ t_Handle h_Schemes[FM_PCD_KG_NUM_OF_SCHEMES]; ++ t_FmBufferPrefixContent buffPrefixContent; ++ t_Handle h_Dev; ++ t_Handle h_LnxWrpFmDev; ++ uint16_t txCh; ++ struct device *dev; ++ struct device_attribute *dev_attr_stats; ++ struct device_attribute *dev_attr_regs; ++} t_LnxWrpFmPortDev; ++ ++typedef struct { ++ uint8_t id; ++ bool active; ++ uint64_t baseAddr; ++ uint32_t memSize; ++ t_WrpFmMacDevSettings settings; ++ t_Handle h_Dev; ++ t_Handle h_LnxWrpFmDev; ++} t_LnxWrpFmMacDev; ++ ++/* information about all active ports for an FMan. ++ * !Some ports may be disabled by u-boot, thus will not be available */ ++struct fm_active_ports { ++ uint32_t num_oh_ports; ++ uint32_t num_tx_ports; ++ uint32_t num_rx_ports; ++ uint32_t num_tx25_ports; ++ uint32_t num_rx25_ports; ++ uint32_t num_tx10_ports; ++ uint32_t num_rx10_ports; ++}; ++ ++/* FMan resources precalculated at fm probe based ++ * on available FMan port. */ ++struct fm_resource_settings { ++ /* buffers - fifo sizes */ ++ uint32_t tx1g_num_buffers; ++ uint32_t rx1g_num_buffers; ++ uint32_t tx2g5_num_buffers; /* Not supported yet by LLD */ ++ uint32_t rx2g5_num_buffers; /* Not supported yet by LLD */ ++ uint32_t tx10g_num_buffers; ++ uint32_t rx10g_num_buffers; ++ uint32_t oh_num_buffers; ++ uint32_t shared_ext_buffers; ++ ++ /* open DMAs */ ++ uint32_t tx_1g_dmas; ++ uint32_t rx_1g_dmas; ++ uint32_t tx_2g5_dmas; /* Not supported yet by LLD */ ++ uint32_t rx_2g5_dmas; /* Not supported yet by LLD */ ++ uint32_t tx_10g_dmas; ++ uint32_t rx_10g_dmas; ++ uint32_t oh_dmas; ++ uint32_t shared_ext_open_dma; ++ ++ /* Tnums */ ++ uint32_t tx_1g_tnums; ++ uint32_t rx_1g_tnums; ++ uint32_t tx_2g5_tnums; /* Not supported yet by LLD */ ++ uint32_t rx_2g5_tnums; /* Not supported yet by LLD */ ++ uint32_t tx_10g_tnums; ++ uint32_t rx_10g_tnums; ++ uint32_t oh_tnums; ++ uint32_t shared_ext_tnums; ++}; ++ ++typedef struct { ++ uint8_t id; ++ char name[10]; ++ bool active; ++ bool pcdActive; ++ bool prsActive; ++ bool kgActive; ++ bool ccActive; ++ bool plcrActive; ++ e_LnxWrpFmPortPcdDefUseCase defPcd; ++ uint32_t usedSchemes; ++ uint8_t totalNumOfSharedSchemes; ++ uint8_t sharedSchemesBase; ++ uint8_t numOfSchemesUsed; ++ uint8_t defNetEnvId; ++ uint64_t fmPhysBaseAddr; ++ uint64_t fmBaseAddr; ++ uint32_t fmMemSize; ++ uint64_t fmMuramPhysBaseAddr; ++ uint64_t fmMuramBaseAddr; ++ uint32_t fmMuramMemSize; ++ uint64_t fmRtcPhysBaseAddr; ++ uint64_t fmRtcBaseAddr; ++ uint32_t fmRtcMemSize; ++ uint64_t fmVspPhysBaseAddr; ++ uint64_t fmVspBaseAddr; ++ uint32_t fmVspMemSize; ++ int irq; ++ int err_irq; ++ t_WrpFmDevSettings fmDevSettings; ++ t_WrpFmPcdDevSettings fmPcdDevSettings; ++ t_Handle h_Dev; ++ uint16_t hcCh; ++ ++ t_Handle h_MuramDev; ++ t_Handle h_PcdDev; ++ t_Handle h_RtcDev; ++ ++ t_LnxWrpFmPortDev hcPort; ++ t_LnxWrpFmPortDev opPorts[FM_MAX_NUM_OF_OH_PORTS-1]; ++ t_LnxWrpFmPortDev rxPorts[FM_MAX_NUM_OF_RX_PORTS]; ++ t_LnxWrpFmPortDev txPorts[FM_MAX_NUM_OF_TX_PORTS]; ++ t_LnxWrpFmMacDev macs[FM_MAX_NUM_OF_MACS]; ++ struct fm_active_ports fm_active_ports_info; ++ struct fm_resource_settings fm_resource_settings_info; ++ ++ struct device *dev; ++ struct resource *res; ++ int major; ++ struct class *fm_class; ++ struct device_attribute *dev_attr_stats; ++ struct device_attribute *dev_attr_regs; ++ ++ struct device_attribute *dev_pcd_attr_stats; ++ struct device_attribute *dev_pcd_attr_regs; ++ ++ struct qman_fq *hc_tx_conf_fq, *hc_tx_err_fq, *hc_tx_fq; ++} t_LnxWrpFmDev; ++ ++typedef struct { ++ t_LnxWrpFmDev *p_FmDevs[INTG_MAX_NUM_OF_FM]; ++} t_LnxWrpFm; ++#define LNXWRP_FM_OBJECT(ptr) LIST_OBJECT(ptr, t_LnxWrpFm, fms[((t_LnxWrpFmDev *)ptr)->id]) ++ ++ ++t_Error LnxwrpFmIOCTL(t_LnxWrpFmDev *p_LnxWrpFmDev, unsigned int cmd, unsigned long arg, bool compat); ++t_Error LnxwrpFmPortIOCTL(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev, unsigned int cmd, unsigned long arg, bool compat); ++ ++ ++static __inline__ t_Error AllocSchemesForPort(t_LnxWrpFmDev *p_LnxWrpFmDev, uint8_t numSchemes, uint8_t *p_BaseSchemeNum) ++{ ++ uint32_t schemeMask; ++ uint8_t i; ++ ++ if (!numSchemes) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ ++ schemeMask = 0x80000000; ++ *p_BaseSchemeNum = 0xff; ++ ++ for (i=0; schemeMask && numSchemes; schemeMask>>=1, i++) ++ if ((p_LnxWrpFmDev->usedSchemes & schemeMask) == 0) ++ { ++ p_LnxWrpFmDev->usedSchemes |= schemeMask; ++ numSchemes--; ++ if (*p_BaseSchemeNum==0xff) ++ *p_BaseSchemeNum = i; ++ } ++ else if (*p_BaseSchemeNum!=0xff) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Fragmentation on schemes array!!!")); ++ ++ if (numSchemes) ++ RETURN_ERROR(MINOR, E_FULL, ("schemes!!!")); ++ return E_OK; ++} ++ ++void LnxWrpPCDIOCTLTypeChecking(void); ++void LnxWrpPCDIOCTLEnumChecking(void); ++ ++#endif /* __LNXWRP_FM_H__ */ +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_fm_port.c b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_fm_port.c +new file mode 100644 +index 0000000..8ddc46a +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_fm_port.c +@@ -0,0 +1,1098 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_fm_port.c ++ ++ @Description FMD wrapper - FMan port functions. ++ ++*/ ++ ++#include ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "sprint_ext.h" ++#include "fm_common.h" ++#include "fm_port_ext.h" ++#include "fm_ioctls.h" ++#include "lnxwrp_resources.h" ++#include "lnxwrp_sysfs_fm_port.h" ++ ++/* TODO: duplicated, see lnxwrp_fm.c */ ++#define ADD_ADV_CONFIG_NO_RET(_func, _param)\ ++do {\ ++ if (i < max) {\ ++ p_Entry = &p_Entrys[i];\ ++ p_Entry->p_Function = _func;\ ++ _param\ ++ i++;\ ++ } else {\ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE,\ ++ ("Number of advanced-configuration entries exceeded"));\ ++ } \ ++} while (0) ++ ++ ++static volatile int hcFrmRcv/* = 0 */; ++static spinlock_t lock; ++ ++static enum qman_cb_dqrr_result qm_tx_conf_dqrr_cb(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry ++ *dq) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ((t_FmTestFq *) fq)->h_Arg; ++ unsigned long flags; ++ ++ FM_PCD_HcTxConf(p_LnxWrpFmDev->h_PcdDev, (t_DpaaFD *)&dq->fd); ++ spin_lock_irqsave(&lock, flags); ++ hcFrmRcv--; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static enum qman_cb_dqrr_result qm_tx_dqrr_cb(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__, ++ __func__); ++ return qman_cb_dqrr_consume; ++} ++ ++static void qm_err_cb(struct qman_portal *portal, ++ struct qman_fq *fq, const struct qm_mr_entry *msg) ++{ ++ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__, ++ __func__); ++} ++ ++static struct qman_fq *FqAlloc(t_LnxWrpFmDev * p_LnxWrpFmDev, ++ uint32_t fqid, ++ uint32_t flags, uint16_t channel, uint8_t wq) ++{ ++ int _errno; ++ struct qman_fq *fq = NULL; ++ t_FmTestFq *p_FmtFq; ++ struct qm_mcc_initfq initfq; ++ ++ p_FmtFq = (t_FmTestFq *) XX_Malloc(sizeof(t_FmTestFq)); ++ if (!p_FmtFq) { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj!!!")); ++ return NULL; ++ } ++ ++ p_FmtFq->fq_base.cb.dqrr = ((flags & QMAN_FQ_FLAG_NO_ENQUEUE) ++ ? qm_tx_conf_dqrr_cb ++ : qm_tx_dqrr_cb); ++ p_FmtFq->fq_base.cb.ern = qm_err_cb; ++ /* p_FmtFq->fq_base.cb.fqs = qm_err_cb; */ ++ /* qm_err_cb wrongly called when the FQ is parked */ ++ p_FmtFq->fq_base.cb.fqs = NULL; ++ p_FmtFq->h_Arg = (t_Handle) p_LnxWrpFmDev; ++ if (fqid == 0) { ++ flags |= QMAN_FQ_FLAG_DYNAMIC_FQID; ++ flags &= ~QMAN_FQ_FLAG_NO_MODIFY; ++ } else { ++ flags &= ~QMAN_FQ_FLAG_DYNAMIC_FQID; ++ } ++ ++ if (qman_create_fq(fqid, flags, &p_FmtFq->fq_base)) { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj - qman_new_fq!!!")); ++ XX_Free(p_FmtFq); ++ return NULL; ++ } ++ fq = &p_FmtFq->fq_base; ++ ++ if (!(flags & QMAN_FQ_FLAG_NO_MODIFY)) { ++ initfq.we_mask = QM_INITFQ_WE_DESTWQ; ++ initfq.fqd.dest.channel = channel; ++ initfq.fqd.dest.wq = wq; ++ ++ _errno = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq); ++ if (unlikely(_errno < 0)) { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ++ ("FQ obj - qman_init_fq!!!")); ++ qman_destroy_fq(fq, 0); ++ XX_Free(p_FmtFq); ++ return NULL; ++ } ++ } ++ ++ DBG(TRACE, ++ ("fqid %d, flags 0x%08x, channel %d, wq %d", qman_fq_fqid(fq), ++ flags, channel, wq)); ++ ++ return fq; ++} ++ ++static void FqFree(struct qman_fq *fq) ++{ ++ int _errno; ++ ++ _errno = qman_retire_fq(fq, NULL); ++ if (unlikely(_errno < 0)) ++ printk(KERN_WARNING "qman_retire_fq(%u) = %d\n", qman_fq_fqid(fq), _errno); ++ ++ _errno = qman_oos_fq(fq); ++ if (unlikely(_errno < 0)) ++ printk(KERN_WARNING "qman_oos_fq(%u) = %d\n", qman_fq_fqid(fq), _errno); ++ ++ qman_destroy_fq(fq, 0); ++ XX_Free((t_FmTestFq *) fq); ++} ++ ++static t_Error QmEnqueueCB(t_Handle h_Arg, void *p_Fd) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *) h_Arg; ++ int _errno, timeout = 1000000; ++ unsigned long flags; ++ ++ ASSERT_COND(p_LnxWrpFmDev); ++ ++ spin_lock_irqsave(&lock, flags); ++ hcFrmRcv++; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ _errno = qman_enqueue(p_LnxWrpFmDev->hc_tx_fq, (struct qm_fd *) p_Fd, ++ 0); ++ if (_errno) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ++ ("qman_enqueue() failed")); ++ ++ while (hcFrmRcv && --timeout) { ++ udelay(1); ++ cpu_relax(); ++ } ++ if (timeout == 0) { ++ dump_stack(); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, ++ ("timeout waiting for Tx confirmation")); ++ return E_WRITE_FAILED; ++ } ++ ++ return E_OK; ++} ++ ++static t_LnxWrpFmPortDev *ReadFmPortDevTreeNode(struct platform_device ++ *of_dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev; ++ struct device_node *fm_node, *port_node; ++ struct resource res; ++ const uint32_t *uint32_prop; ++ int _errno = 0, lenp; ++#ifdef CONFIG_FMAN_P1023 ++ static unsigned char have_oh_port/* = 0 */; ++#endif ++ ++ port_node = of_node_get(of_dev->dev.of_node); ++ ++ /* Get the FM node */ ++ fm_node = of_get_parent(port_node); ++ if (unlikely(fm_node == NULL)) { ++ REPORT_ERROR(MAJOR, E_NO_DEVICE, ++ ("of_get_parent() = %d", _errno)); ++ return NULL; ++ } ++ ++ p_LnxWrpFmDev = ++ dev_get_drvdata(&of_find_device_by_node(fm_node)->dev); ++ of_node_put(fm_node); ++ ++ /* if fm_probe() failed, no point in going further with port probing */ ++ if (p_LnxWrpFmDev == NULL) ++ return NULL; ++ ++ uint32_prop = ++ (uint32_t *) of_get_property(port_node, "cell-index", &lenp); ++ if (unlikely(uint32_prop == NULL)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ if (of_device_is_compatible(port_node, "fsl,fman-port-oh")) { ++ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_OH_PORTS)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ ++#ifdef CONFIG_FMAN_P1023 ++ /* Beware, this can be done when there is only ++ one FMan to be initialized */ ++ if (!have_oh_port) { ++ have_oh_port = 1; /* first OP/HC port ++ is used for host command */ ++#else ++ /* Here it is hardcoded the use of the OH port 1 ++ (with cell-index 0) */ ++ if (*uint32_prop == 0) { ++#endif ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort; ++ p_LnxWrpFmPortDev->id = 0; ++ /* ++ p_LnxWrpFmPortDev->id = *uint32_prop-1; ++ p_LnxWrpFmPortDev->id = *uint32_prop; ++ */ ++ p_LnxWrpFmPortDev->settings.param.portType = ++ e_FM_PORT_TYPE_OH_HOST_COMMAND; ++ } else { ++ p_LnxWrpFmPortDev = ++ &p_LnxWrpFmDev->opPorts[*uint32_prop - 1]; ++ p_LnxWrpFmPortDev->id = *uint32_prop - 1; ++ p_LnxWrpFmPortDev->settings.param.portType = ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING; ++ } ++ p_LnxWrpFmPortDev->settings.param.portId = *uint32_prop; ++ ++ uint32_prop = ++ (uint32_t *) of_get_property(port_node, ++ "fsl,qman-channel-id", ++ &lenp); ++ if (uint32_prop == NULL) { ++ /* ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("missing fsl,qman-channel-id")); ++ */ ++ XX_Print("FM warning: missing fsl,qman-channel-id" ++ " for OH port.\n"); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ p_LnxWrpFmPortDev->txCh = *uint32_prop; ++ ++ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams. ++ qmChannel = p_LnxWrpFmPortDev->txCh; ++ } else if (of_device_is_compatible(port_node, "fsl,fman-port-1g-tx")) { ++ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_1G_TX_PORTS)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop]; ++ ++ p_LnxWrpFmPortDev->id = *uint32_prop; ++ p_LnxWrpFmPortDev->settings.param.portId = ++ p_LnxWrpFmPortDev->id; ++ p_LnxWrpFmPortDev->settings.param.portType = e_FM_PORT_TYPE_TX; ++ ++ uint32_prop = (uint32_t *) of_get_property(port_node, ++ "fsl,qman-channel-id", &lenp); ++ if (uint32_prop == NULL) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("missing fsl,qman-channel-id")); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ p_LnxWrpFmPortDev->txCh = *uint32_prop; ++ p_LnxWrpFmPortDev-> ++ settings.param.specificParams.nonRxParams.qmChannel = ++ p_LnxWrpFmPortDev->txCh; ++ } else if (of_device_is_compatible(port_node, "fsl,fman-port-10g-tx")) { ++ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_10G_TX_PORTS)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop + ++ FM_MAX_NUM_OF_1G_TX_PORTS]; ++ ++ p_LnxWrpFmPortDev->id = *uint32_prop; ++ p_LnxWrpFmPortDev->settings.param.portId = ++ p_LnxWrpFmPortDev->id; ++ p_LnxWrpFmPortDev->settings.param.portType = ++ e_FM_PORT_TYPE_TX_10G; ++ uint32_prop = (uint32_t *) of_get_property(port_node, ++ "fsl,qman-channel-id", &lenp); ++ if (uint32_prop == NULL) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("missing fsl,qman-channel-id")); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ p_LnxWrpFmPortDev->txCh = *uint32_prop; ++ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams. ++ qmChannel = p_LnxWrpFmPortDev->txCh; ++ } else if (of_device_is_compatible(port_node, "fsl,fman-port-1g-rx")) { ++ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_1G_RX_PORTS)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop]; ++ ++ p_LnxWrpFmPortDev->id = *uint32_prop; ++ p_LnxWrpFmPortDev->settings.param.portId = ++ p_LnxWrpFmPortDev->id; ++ p_LnxWrpFmPortDev->settings.param.portType = e_FM_PORT_TYPE_RX; ++ if (p_LnxWrpFmDev->pcdActive) ++ p_LnxWrpFmPortDev->defPcd = p_LnxWrpFmDev->defPcd; ++ } else if (of_device_is_compatible(port_node, "fsl,fman-port-10g-rx")) { ++ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_10G_RX_PORTS)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop + ++ FM_MAX_NUM_OF_1G_RX_PORTS]; ++ ++ p_LnxWrpFmPortDev->id = *uint32_prop; ++ p_LnxWrpFmPortDev->settings.param.portId = ++ p_LnxWrpFmPortDev->id; ++ p_LnxWrpFmPortDev->settings.param.portType = ++ e_FM_PORT_TYPE_RX_10G; ++ if (p_LnxWrpFmDev->pcdActive) ++ p_LnxWrpFmPortDev->defPcd = p_LnxWrpFmDev->defPcd; ++ } else { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal port type")); ++ return NULL; ++ } ++ ++ _errno = of_address_to_resource(port_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_address_to_resource() = %d", _errno)); ++ return NULL; ++ } ++ ++ p_LnxWrpFmPortDev->dev = &of_dev->dev; ++ p_LnxWrpFmPortDev->baseAddr = 0; ++ p_LnxWrpFmPortDev->phys_baseAddr = res.start; ++ p_LnxWrpFmPortDev->memSize = res.end + 1 - res.start; ++ p_LnxWrpFmPortDev->settings.param.h_Fm = p_LnxWrpFmDev->h_Dev; ++ p_LnxWrpFmPortDev->h_LnxWrpFmDev = (t_Handle) p_LnxWrpFmDev; ++ ++ of_node_put(port_node); ++ ++ p_LnxWrpFmPortDev->active = TRUE; ++ ++#if defined(CONFIG_FMAN_DISABLE_OH_TO_REUSE_RESOURCES) ++ /* for performance mode no OH port available. */ ++ if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ p_LnxWrpFmPortDev->active = FALSE; ++#endif ++ ++ return p_LnxWrpFmPortDev; ++} ++ ++static t_Error ConfigureFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ++ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ struct resource *dev_res; ++ ++ if (!p_LnxWrpFmPortDev->active) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("FM port not configured!!!")); ++ ++ dev_res = ++ __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, ++ p_LnxWrpFmPortDev->phys_baseAddr, ++ p_LnxWrpFmPortDev->memSize, ++ "fman-port-hc"); ++ if (unlikely(dev_res == NULL)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("__devm_request_region() failed")); ++ p_LnxWrpFmPortDev->baseAddr = ++ PTR_TO_UINT(devm_ioremap ++ (p_LnxWrpFmDev->dev, ++ p_LnxWrpFmPortDev->phys_baseAddr, ++ p_LnxWrpFmPortDev->memSize)); ++ if (unlikely(p_LnxWrpFmPortDev->baseAddr == 0)) ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ++ ("devm_ioremap() failed")); ++ ++ p_LnxWrpFmPortDev->settings.param.baseAddr = ++ p_LnxWrpFmPortDev->baseAddr; ++ ++ return E_OK; ++} ++ ++static t_Error InitFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) ++{ ++#define MY_ADV_CONFIG_CHECK_END \ ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION,\ ++ ("Advanced configuration routine"));\ ++ if (errCode != E_OK)\ ++ RETURN_ERROR(MAJOR, errCode, NO_MSG);\ ++ } ++ ++ int i = 0; ++ ++ if (!p_LnxWrpFmPortDev->active || p_LnxWrpFmPortDev->h_Dev) ++ return E_INVALID_STATE; ++ ++ p_LnxWrpFmPortDev->h_Dev = ++ FM_PORT_Config(&p_LnxWrpFmPortDev->settings.param); ++ if (p_LnxWrpFmPortDev->h_Dev == NULL) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-port")); ++ ++#ifndef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if ((p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_TX_10G) ++ || (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_TX)) { ++ t_Error errCode = E_OK; ++ errCode = ++ FM_PORT_ConfigDeqHighPriority(p_LnxWrpFmPortDev->h_Dev, ++ TRUE); ++ if (errCode != E_OK) ++ RETURN_ERROR(MAJOR, errCode, NO_MSG); ++ errCode = ++ FM_PORT_ConfigDeqPrefetchOption(p_LnxWrpFmPortDev->h_Dev, ++ e_FM_PORT_DEQ_FULL_PREFETCH); ++ if (errCode ++ != E_OK) ++ RETURN_ERROR(MAJOR, errCode, NO_MSG); ++ } ++#endif /* !FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ ++#ifdef FM_BCB_ERRATA_BMI_SW001 ++/* Configure BCB workaround on Rx ports, only for B4860 rev1 */ ++#define SVR_SECURITY_MASK 0x00080000 ++#define SVR_PERSONALITY_MASK 0x0000FF00 ++#define SVR_VER_IGNORE_MASK (SVR_SECURITY_MASK | SVR_PERSONALITY_MASK) ++#define SVR_B4860_REV1_VALUE 0x86800010 ++ ++ if ((p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_RX_10G) || ++ (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_RX)) { ++ unsigned int svr; ++ ++ svr = mfspr(SPRN_SVR); ++ ++ if ((svr & ~SVR_VER_IGNORE_MASK) == SVR_B4860_REV1_VALUE) ++ FM_PORT_ConfigBCBWorkaround(p_LnxWrpFmPortDev->h_Dev); ++ } ++#endif /* FM_BCB_ERRATA_BMI_SW001 */ ++ ++/* Call the driver's advanced configuration routines, if requested: ++ Compare the function pointer of each entry to the available routines, ++ and invoke the matching routine with proper casting of arguments. */ ++ while (p_LnxWrpFmPortDev->settings.advConfig[i].p_Function ++ && (i < FM_MAX_NUM_OF_ADV_SETTINGS)) { ++ ++/* TODO: Change this MACRO */ ++ ADV_CONFIG_CHECK_START( ++ &(p_LnxWrpFmPortDev->settings.advConfig[i])) ++ ++ ADV_CONFIG_CHECK(p_LnxWrpFmPortDev->h_Dev, ++ FM_PORT_ConfigBufferPrefixContent, ++ NCSW_PARAMS(1, ++ (t_FmBufferPrefixContent *))) ++ ++ if((p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) && ++ (p_LnxWrpFmPortDev->settings. ++ frag_enabled == TRUE)) { ++ ++ ADV_CONFIG_CHECK(p_LnxWrpFmPortDev->h_Dev, ++ FM_PORT_ConfigExtBufPools, ++ NCSW_PARAMS(1, (t_FmExtPools *))) ++ ++ /* this define contains an else */ ++ MY_ADV_CONFIG_CHECK_END ++ } ++ ++ /* Advance to next advanced configuration entry */ ++ i++; ++ } ++ ++#if defined(CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM) ++#if (DPAA_VERSION >= 11) ++#warning The resource allocation algorithm is not available for FMan v3 platforms ++#else ++ /* even if these functions return w/ error, do not crash kernel. ++ Do not return anything because the container function is not ++ linux complient (it should return -EIO). */ ++ fm_config_precalculate_fifosize(p_LnxWrpFmPortDev); ++ fm_config_precalculate_open_dma(p_LnxWrpFmPortDev); ++ fm_config_precalculate_tnums(p_LnxWrpFmPortDev); ++#endif ++#endif ++ ++ if (FM_PORT_Init(p_LnxWrpFmPortDev->h_Dev) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++/* FMan Fifo sizes behind the scene": ++ * Using the following formulae (*), under a set of simplifying assumptions (.): ++ * . all ports are configured in Normal Mode (rather than Independent Mode) ++ * . the DPAA Eth driver allocates buffers of size: ++ * . MAXFRM + NET_IP_ALIGN + DPA_PRIV_DATA_SIZE + DPA_PARSE_RESULTS_SIZE ++ * + DPA_HASH_RESULTS_SIZE, i.e.: ++ * MAXFRM + 2 + 16 + sizeof(t_FmPrsResult) + 16, i.e.: ++ * MAXFRM + 66 ++ * . excessive buffer pools not accounted for ++ * ++ * * for Rx ports on P4080: ++ * . IFSZ = ceil(max(FMBM_EBMPI[PBS]) / 256) * 256 + 7 * 256 ++ * . no internal frame offset (FMBM_RIM[FOF] == 0) - otherwise, ++ * add up to 256 to the above ++ * ++ * * for Rx ports on P1023: ++ * . IFSZ = ceil(second_largest(FMBM_EBMPI[PBS] / 256)) * 256 + 7 * 256, ++ * if at least 2 bpools are configured ++ * . IFSZ = 8 * 256, if only a single bpool is configured ++ * ++ * * for Tx ports: ++ * . IFSZ = ceil(frame_size / 256) * 256 + 3 * 256 ++ * + FMBM_TFP[DPDE] * 256, i.e.: ++ * IFSZ = ceil(MAXFRM / 256) * 256 + 3 x 256 + FMBM_TFP[DPDE] * 256 ++ * ++ * * for OH ports on P4080: ++ * . IFSZ = ceil(frame_size / 256) * 256 + 1 * 256 + FMBM_PP[MXT] * 256 ++ * * for OH ports on P1023: ++ * . IFSZ = ceil(frame_size / 256) * 256 + 3 * 256 + FMBM_TFP[DPDE] * 256 ++ * * for both P4080 and P1023: ++ * . (conservative decisions, assuming that BMI must bring the entire ++ * frame, not only the frame header) ++ * . no internal frame offset (FMBM_OIM[FOF] == 0) - otherwise, ++ * add up to 256 to the above ++ * ++ * . for P4080/P5020/P3041/P2040, DPDE is: ++ * > 0 or 1, for 1Gb ports, HW default: 0 ++ * > 2..7 (recommended: 3..7) for 10Gb ports, HW default: 3 ++ * . for P1023, DPDE should be 1 ++ * ++ * . for P1023, MXT is in range (0..31) ++ * . for P4080, MXT is in range (0..63) ++ * ++ */ ++#if 0 ++ if ((p_LnxWrpFmPortDev->defPcd != e_NO_PCD) && ++ (InitFmPort3TupleDefPcd(p_LnxWrpFmPortDev) != E_OK)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++#endif ++ return E_OK; ++} ++ ++void fm_set_rx_port_params(struct fm_port *port, ++ struct fm_port_params *params) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) port; ++ int i; ++ ++ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.errFqid = ++ params->errq; ++ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.dfltFqid = ++ params->defq; ++ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.extBufPools. ++ numOfPoolsUsed = params->num_pools; ++ for (i = 0; i < params->num_pools; i++) { ++ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams. ++ extBufPools.extBufPool[i].id = ++ params->pool_param[i].id; ++ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams. ++ extBufPools.extBufPool[i].size = ++ params->pool_param[i].size; ++ } ++ ++ p_LnxWrpFmPortDev->buffPrefixContent.privDataSize = ++ params->priv_data_size; ++ p_LnxWrpFmPortDev->buffPrefixContent.passPrsResult = ++ params->parse_results; ++ p_LnxWrpFmPortDev->buffPrefixContent.passHashResult = ++ params->hash_results; ++ p_LnxWrpFmPortDev->buffPrefixContent.passTimeStamp = ++ params->time_stamp; ++ ++ ADD_ADV_CONFIG_START(p_LnxWrpFmPortDev->settings.advConfig, ++ FM_MAX_NUM_OF_ADV_SETTINGS) ++ ++ ADD_ADV_CONFIG_NO_RET(FM_PORT_ConfigBufferPrefixContent, ++ ARGS(1, ++ (&p_LnxWrpFmPortDev-> ++ buffPrefixContent))); ++ ++ ADD_ADV_CONFIG_END InitFmPortDev(p_LnxWrpFmPortDev); ++} ++EXPORT_SYMBOL(fm_set_rx_port_params); ++ ++/* this function is called from oh_probe as well, thus it contains oh port ++ * specific parameters (make sure everything is checked) */ ++void fm_set_tx_port_params(struct fm_port *port, ++ struct fm_port_params *params) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) port; ++ ++ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams.errFqid = ++ params->errq; ++ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams. ++ dfltFqid = params->defq; ++ ++ p_LnxWrpFmPortDev->buffPrefixContent.privDataSize = ++ params->priv_data_size; ++ p_LnxWrpFmPortDev->buffPrefixContent.passPrsResult = ++ params->parse_results; ++ p_LnxWrpFmPortDev->buffPrefixContent.passHashResult = ++ params->hash_results; ++ p_LnxWrpFmPortDev->buffPrefixContent.passTimeStamp = ++ params->time_stamp; ++ p_LnxWrpFmPortDev->settings.frag_enabled = FALSE; ++ ++ if ((params->frag_enable == TRUE) && ++ (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) { ++ ++ p_LnxWrpFmPortDev->settings.frag_enabled = TRUE; ++ p_LnxWrpFmPortDev->buffPrefixContent.dataAlign = ++ FRAG_DATA_ALIGN; ++ p_LnxWrpFmPortDev->buffPrefixContent.manipExtraSpace = ++ FRAG_MANIP_SPACE; ++ } ++ ++ ADD_ADV_CONFIG_START(p_LnxWrpFmPortDev->settings.advConfig, ++ FM_MAX_NUM_OF_ADV_SETTINGS) ++ ++ ADD_ADV_CONFIG_NO_RET(FM_PORT_ConfigBufferPrefixContent, ++ ARGS(1, ++ (&p_LnxWrpFmPortDev-> ++ buffPrefixContent))); ++ ++ /* oh port specific parameter (for fragmentation only) */ ++ if ((params->frag_enable == TRUE) && ++ (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) { ++ t_FmExtPools opExtPools; ++ int i; ++ ++ memset(&opExtPools, 0, sizeof(opExtPools)); ++ opExtPools.numOfPoolsUsed = params->num_pools; ++ for (i = 0; i < params->num_pools; i++) { ++ opExtPools.extBufPool[i].id = params->pool_param[i].id; ++ opExtPools.extBufPool[i].size = params->pool_param[i].size; ++ } ++ ADD_ADV_CONFIG_NO_RET(FM_PORT_ConfigExtBufPools, ++ ARGS(1, (&opExtPools))); ++ } ++ ++ ADD_ADV_CONFIG_END InitFmPortDev(p_LnxWrpFmPortDev); ++} ++EXPORT_SYMBOL(fm_set_tx_port_params); ++ ++void fm_mac_set_handle(t_Handle h_lnx_wrp_fm_dev, ++ t_Handle h_fm_mac, ++ int mac_id) ++{ ++ t_LnxWrpFmDev *p_lnx_wrp_fm_dev = (t_LnxWrpFmDev *)h_lnx_wrp_fm_dev; ++ ++ p_lnx_wrp_fm_dev->macs[mac_id].h_Dev = h_fm_mac; ++ p_lnx_wrp_fm_dev->macs[mac_id].h_LnxWrpFmDev = h_lnx_wrp_fm_dev; ++} ++EXPORT_SYMBOL(fm_mac_set_handle); ++ ++static void LnxwrpFmPcdDevExceptionsCb(t_Handle h_App, ++ e_FmPcdExceptions exception) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *) h_App; ++ ++ ASSERT_COND(p_LnxWrpFmDev); ++ ++ DBG(INFO, ("got fm-pcd exception %d", exception)); ++ ++ /* do nothing */ ++ UNUSED(exception); ++} ++ ++static void LnxwrpFmPcdDevIndexedExceptionsCb(t_Handle h_App, ++ e_FmPcdExceptions exception, ++ uint16_t index) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *) h_App; ++ ++ ASSERT_COND(p_LnxWrpFmDev); ++ ++ DBG(INFO, ++ ("got fm-pcd-indexed exception %d, indx %d", exception, index)); ++ ++ /* do nothing */ ++ UNUSED(exception); ++ UNUSED(index); ++} ++ ++static t_Error InitFmPcdDev(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ spin_lock_init(&lock); ++ ++ if (p_LnxWrpFmDev->pcdActive) { ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort; ++ t_FmPcdParams fmPcdParams; ++ t_Error err; ++ ++ memset(&fmPcdParams, 0, sizeof(fmPcdParams)); ++ fmPcdParams.h_Fm = p_LnxWrpFmDev->h_Dev; ++ fmPcdParams.prsSupport = p_LnxWrpFmDev->prsActive; ++ fmPcdParams.kgSupport = p_LnxWrpFmDev->kgActive; ++ fmPcdParams.plcrSupport = p_LnxWrpFmDev->plcrActive; ++ fmPcdParams.ccSupport = p_LnxWrpFmDev->ccActive; ++ fmPcdParams.numOfSchemes = FM_PCD_KG_NUM_OF_SCHEMES; ++ ++#ifndef CONFIG_GUEST_PARTITION ++ fmPcdParams.f_Exception = LnxwrpFmPcdDevExceptionsCb; ++ if (fmPcdParams.kgSupport) ++ fmPcdParams.f_ExceptionId = ++ LnxwrpFmPcdDevIndexedExceptionsCb; ++ fmPcdParams.h_App = p_LnxWrpFmDev; ++#endif /* !CONFIG_GUEST_PARTITION */ ++ ++#ifdef CONFIG_MULTI_PARTITION_SUPPORT ++ fmPcdParams.numOfSchemes = 0; ++ fmPcdParams.numOfClsPlanEntries = 0; ++ fmPcdParams.partitionId = 0; ++#endif /* CONFIG_MULTI_PARTITION_SUPPORT */ ++ fmPcdParams.useHostCommand = TRUE; ++ ++ p_LnxWrpFmDev->hc_tx_fq = ++ FqAlloc(p_LnxWrpFmDev, ++ 0, ++ QMAN_FQ_FLAG_TO_DCPORTAL, ++ p_LnxWrpFmPortDev->txCh, 0); ++ if (!p_LnxWrpFmDev->hc_tx_fq) ++ RETURN_ERROR(MAJOR, E_NULL_POINTER, ++ ("Frame queue allocation failed...")); ++ ++ p_LnxWrpFmDev->hc_tx_conf_fq = ++ FqAlloc(p_LnxWrpFmDev, ++ 0, ++ QMAN_FQ_FLAG_NO_ENQUEUE, ++ p_LnxWrpFmDev->hcCh, 7); ++ if (!p_LnxWrpFmDev->hc_tx_conf_fq) ++ RETURN_ERROR(MAJOR, E_NULL_POINTER, ++ ("Frame queue allocation failed...")); ++ ++ p_LnxWrpFmDev->hc_tx_err_fq = ++ FqAlloc(p_LnxWrpFmDev, ++ 0, ++ QMAN_FQ_FLAG_NO_ENQUEUE, ++ p_LnxWrpFmDev->hcCh, 7); ++ if (!p_LnxWrpFmDev->hc_tx_err_fq) ++ RETURN_ERROR(MAJOR, E_NULL_POINTER, ++ ("Frame queue allocation failed...")); ++ ++ fmPcdParams.hc.portBaseAddr = p_LnxWrpFmPortDev->baseAddr; ++ fmPcdParams.hc.portId = ++ p_LnxWrpFmPortDev->settings.param.portId; ++ fmPcdParams.hc.liodnBase = ++ p_LnxWrpFmPortDev->settings.param.liodnBase; ++ fmPcdParams.hc.errFqid = ++ qman_fq_fqid(p_LnxWrpFmDev->hc_tx_err_fq); ++ fmPcdParams.hc.confFqid = ++ qman_fq_fqid(p_LnxWrpFmDev->hc_tx_conf_fq); ++ fmPcdParams.hc.qmChannel = p_LnxWrpFmPortDev->txCh; ++ fmPcdParams.hc.f_QmEnqueue = QmEnqueueCB; ++ fmPcdParams.hc.h_QmArg = (t_Handle) p_LnxWrpFmDev; ++ ++ p_LnxWrpFmDev->h_PcdDev = FM_PCD_Config(&fmPcdParams); ++ if (!p_LnxWrpFmDev->h_PcdDev) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM PCD!")); ++ ++ err = ++ FM_PCD_ConfigPlcrNumOfSharedProfiles(p_LnxWrpFmDev->h_PcdDev, ++ LNXWRP_FM_NUM_OF_SHARED_PROFILES); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ err = FM_PCD_Init(p_LnxWrpFmDev->h_PcdDev); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (p_LnxWrpFmDev->err_irq == 0) { ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC, ++ FALSE); ++ } ++ } ++ ++ return E_OK; ++} ++ ++void FreeFmPcdDev(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ ++ if (p_LnxWrpFmDev->h_PcdDev) ++ FM_PCD_Free(p_LnxWrpFmDev->h_PcdDev); ++ ++ if (p_LnxWrpFmDev->hc_tx_err_fq) ++ FqFree(p_LnxWrpFmDev->hc_tx_err_fq); ++ ++ if (p_LnxWrpFmDev->hc_tx_conf_fq) ++ FqFree(p_LnxWrpFmDev->hc_tx_conf_fq); ++ ++ if (p_LnxWrpFmDev->hc_tx_fq) ++ FqFree(p_LnxWrpFmDev->hc_tx_fq); ++} ++ ++static void FreeFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ++ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ ++ if (!p_LnxWrpFmPortDev->active) ++ return; ++ ++ if (p_LnxWrpFmPortDev->h_Dev) ++ FM_PORT_Free(p_LnxWrpFmPortDev->h_Dev); ++ ++ devm_iounmap(p_LnxWrpFmDev->dev, ++ UINT_TO_PTR(p_LnxWrpFmPortDev->baseAddr)); ++ __devm_release_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, ++ p_LnxWrpFmPortDev->phys_baseAddr, ++ p_LnxWrpFmPortDev->memSize); ++} ++ ++static int /*__devinit*/ fm_port_probe(struct platform_device *of_dev) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev; ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ struct device *dev; ++ ++ dev = &of_dev->dev; ++ ++ p_LnxWrpFmPortDev = ReadFmPortDevTreeNode(of_dev); ++ if (p_LnxWrpFmPortDev == NULL) ++ return -EIO; ++ /* Port can be inactive, thus will not be probed: ++ - in performance mode, OH ports are disabled ++ ... ++ */ ++ if (!p_LnxWrpFmPortDev->active) ++ return 0; ++ ++ if (ConfigureFmPortDev(p_LnxWrpFmPortDev) != E_OK) ++ return -EIO; ++ ++ dev_set_drvdata(dev, p_LnxWrpFmPortDev); ++ ++ if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_HOST_COMMAND) ++ InitFmPcdDev((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev); ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ ++ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-rx%d", ++ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + DEV_FM_RX_PORTS_MINOR_BASE; ++ } else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_RX_10G) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-rx%d", ++ p_LnxWrpFmDev->name, ++ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_RX_PORTS); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_RX_PORTS + ++ DEV_FM_RX_PORTS_MINOR_BASE; ++ } else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_TX) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-tx%d", ++ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + DEV_FM_TX_PORTS_MINOR_BASE; ++ } else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_TX_10G) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-tx%d", ++ p_LnxWrpFmDev->name, ++ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_TX_PORTS); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_TX_PORTS + ++ DEV_FM_TX_PORTS_MINOR_BASE; ++ } else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_HOST_COMMAND) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-oh%d", ++ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + DEV_FM_OH_PORTS_MINOR_BASE; ++ p_LnxWrpFmPortDev->h_Dev = FM_PCD_GetHcDevH(p_LnxWrpFmDev->h_PcdDev); ++ } else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-oh%d", ++ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id + 1); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + 1 + ++ DEV_FM_OH_PORTS_MINOR_BASE; ++ } ++ ++ device_create(p_LnxWrpFmDev->fm_class, NULL, ++ MKDEV(p_LnxWrpFmDev->major, p_LnxWrpFmPortDev->minor), ++ NULL, p_LnxWrpFmPortDev->name); ++ ++ /* create sysfs entries for stats and regs */ ++ ++ if (fm_port_sysfs_create(dev) != 0) { ++ FreeFmPortDev(p_LnxWrpFmPortDev); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ++ ("Unable to create sys entry - fm port!!!")); ++ return -EIO; ++ } ++ ++#ifdef FM_TX_INVALID_ECC_ERRATA_10GMAC_A009 ++ FM_DisableRamsEcc(p_LnxWrpFmDev->h_Dev); ++#endif /* FM_TX_INVALID_ECC_ERRATA_10GMAC_A009 */ ++ ++ DBG(TRACE, ("%s probed", p_LnxWrpFmPortDev->name)); ++ ++ return 0; ++} ++ ++static int __devexit fm_port_remove(struct platform_device *of_dev) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev; ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ struct device *dev; ++ ++ dev = &of_dev->dev; ++ p_LnxWrpFmPortDev = dev_get_drvdata(dev); ++ ++ fm_port_sysfs_destroy(dev); ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ device_destroy(p_LnxWrpFmDev->fm_class, ++ MKDEV(p_LnxWrpFmDev->major, p_LnxWrpFmPortDev->minor)); ++ ++ FreeFmPortDev(p_LnxWrpFmPortDev); ++ ++ dev_set_drvdata(dev, NULL); ++ ++ return 0; ++} ++ ++static const struct of_device_id fm_port_match[] __devinitconst = { ++ { ++ .compatible = "fsl,fman-port-oh"}, ++ { ++ .compatible = "fsl,fman-port-1g-rx"}, ++ { ++ .compatible = "fsl,fman-port-10g-rx"}, ++ { ++ .compatible = "fsl,fman-port-1g-tx"}, ++ { ++ .compatible = "fsl,fman-port-10g-tx"}, ++ {} ++}; ++ ++#ifndef MODULE ++MODULE_DEVICE_TABLE(of, fm_port_match); ++#endif /* !MODULE */ ++ ++static struct platform_driver fm_port_driver = { ++ ++ .driver = { ++ .name = "fsl-fman-port", ++ .of_match_table = fm_port_match, ++ .owner = THIS_MODULE, ++ }, ++ .probe = fm_port_probe, ++ .remove = __devexit_p(fm_port_remove) ++}; ++ ++ ++t_Error LNXWRP_FM_Port_Init(void) ++{ ++ /* Register to the DTB for basic FM port API */ ++ if (platform_driver_register(&fm_port_driver)) ++ return E_NO_DEVICE; ++ ++ return E_OK; ++} ++ ++void LNXWRP_FM_Port_Free(void) ++{ ++ platform_driver_unregister(&fm_port_driver); ++} ++ ++static int __init __cold fm_port_load(void) ++{ ++ if (LNXWRP_FM_Port_Init() != E_OK) { ++ printk(KERN_CRIT "Failed to init FM Ports wrapper!\n"); ++ return -ENODEV; ++ } ++ ++ printk(KERN_CRIT "Freescale FM Ports module (" __DATE__ ":" __TIME__ ++ ")\n"); ++ ++ return 0; ++} ++ ++static void __exit __cold fm_port_unload(void) ++{ ++ LNXWRP_FM_Port_Free(); ++} ++ ++module_init(fm_port_load); ++module_exit(fm_port_unload); +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_ioctls_fm.c b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_ioctls_fm.c +new file mode 100644 +index 0000000..8690359 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_ioctls_fm.c +@@ -0,0 +1,4423 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_ioctls_fm.c ++ @Author Shlomi Gridish ++ @Description FM Linux wrapper functions. ++*/ ++ ++/* Linux Headers ------------------- */ ++#include ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(CONFIG_COMPAT) ++#include ++#endif ++ ++#include "part_ext.h" ++#include "fm_ioctls.h" ++#include "fm_pcd_ioctls.h" ++#include "fm_port_ioctls.h" ++#include "fm_vsp_ext.h" ++ ++#if defined(CONFIG_COMPAT) ++#include "lnxwrp_ioctls_fm_compat.h" ++#endif ++ ++#include "lnxwrp_fm.h" ++ ++#include "dpaa_eth.h" ++ ++#define CMP_IOC_DEFINE(def) (IOC_##def != def) ++ ++/* fm_pcd_ioctls.h === fm_pcd_ext.h assertions */ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_PRIVATE_HDRS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_PRS_NUM_OF_HDRS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_KG_NUM_OF_GENERIC_REGS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_KG_NUM_OF_EXTRACT_MASKS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_KG_NUM_OF_DEFAULT_GROUPS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_PRS_NUM_OF_LABELS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_SW_PRS_SIZE) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_PRS_SW_OFFSET) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_PRS_SW_PATCHES_SIZE) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_PRS_SW_TAIL_SIZE) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_SW_PRS_MAX_IMAGE_SIZE) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_MANIP_INSRT_TEMPLATE_SIZE) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if DPAA_VERSION >= 11 ++#if CMP_IOC_DEFINE(FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES) ++#error Error: please synchronize IOC_ defines! ++#endif ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_TREES) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_GROUPS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_UNITS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_KEYS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_SIZE_OF_KEY) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_LAST_KEY_INDEX) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++/* net_ioctls.h === net_ext.h assertions */ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPP_PID) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPP_COMPRESSED) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPPoE_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPPMUX_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPPMUX_SUBFRAME_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_ETH_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPv4_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPv6_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_ICMP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IGMP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_TCP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_SCTP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_DCCP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_UDP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_UDP_ENCAP_ESP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPHC_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_SCTP_CHUNK_DATA_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_L2TPv2_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_L2TPv3_CTRL_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_L2TPv3_SESS_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_VLAN_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_LLC_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_NLPID_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_SNAP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_LLC_SNAP_ALL_FIELDS) ++#warning Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_ARP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_RFC2684_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_USER_DEFINED_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PAYLOAD_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_GRE_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_MINENCAP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPSEC_AH_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPSEC_ESP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_MPLS_LABEL_STACK_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_MACSEC_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++/* fm_ioctls.h === fm_ext.h assertions */ ++#if CMP_IOC_DEFINE(FM_MAX_NUM_OF_VALID_PORTS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++void LnxWrpPCDIOCTLTypeChecking(void) ++{ ++ /* fm_ext.h == fm_ioctls.h */ ++ ASSERT_COND(sizeof(ioc_fm_port_bandwidth_params) == sizeof(t_FmPortsBandwidthParams)); ++ ASSERT_COND(sizeof(ioc_fm_revision_info_t) == sizeof(t_FmRevisionInfo)); ++ ++ /* fm_pcd_ext.h == fm_pcd_ioctls.h */ ++ /*ioc_fm_pcd_counters_params_t : NOT USED */ ++ /*ioc_fm_pcd_exception_params_t : private */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_prs_label_params_t) == sizeof(t_FmPcdPrsLabelParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_prs_sw_params_t) == sizeof(t_FmPcdPrsSwParams)); ++ /*ioc_fm_pcd_kg_dflt_value_params_t : private */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_hdr_protocol_opt_u) == sizeof(u_FmPcdHdrProtocolOpt)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_fields_u) == sizeof(t_FmPcdFields)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_from_hdr_t) == sizeof(t_FmPcdFromHdr)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_from_field_t) == sizeof(t_FmPcdFromField)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_distinction_unit_t) == sizeof(t_FmPcdDistinctionUnit)); ++#if !defined(CONFIG_COMPAT) ++ /* different alignment */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_net_env_params_t) == sizeof(t_FmPcdNetEnvParams) + sizeof(void *)); ++#endif ++ ASSERT_COND(sizeof(ioc_fm_pcd_extract_entry_t) == sizeof(t_FmPcdExtractEntry)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_extract_mask_t) == sizeof(t_FmPcdKgExtractMask)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_extract_dflt_t) == sizeof(t_FmPcdKgExtractDflt)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_key_extract_and_hash_params_t) == sizeof(t_FmPcdKgKeyExtractAndHashParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_extracted_or_params_t) == sizeof(t_FmPcdKgExtractedOrParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_counter_t) == sizeof(t_FmPcdKgSchemeCounter)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_plcr_profile_t) == sizeof(t_FmPcdKgPlcrProfile)); ++#if (DPAA_VERSION >= 11) ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_storage_profile_t) == sizeof(t_FmPcdKgStorageProfile)); ++#endif ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_cc_t) == sizeof(t_FmPcdKgCc)); ++#if !defined(CONFIG_COMPAT) ++ /* different alignment */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_params_t) == sizeof(t_FmPcdKgSchemeParams) + sizeof(void *)); ++#endif ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_cc_params_t) == sizeof(t_FmPcdCcNextCcParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_plcr_params_t) == sizeof(t_FmPcdCcNextPlcrParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_enqueue_params_t) == sizeof(t_FmPcdCcNextEnqueueParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_kg_params_t) == sizeof(t_FmPcdCcNextKgParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_engine_params_t) == sizeof(t_FmPcdCcNextEngineParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_key_params_t) == sizeof(t_FmPcdCcKeyParams)); ++ ASSERT_COND(sizeof(ioc_keys_params_t) == sizeof(t_KeysParams)); ++#if !defined(CONFIG_COMPAT) ++ /* different alignment */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_node_params_t) == sizeof(t_FmPcdCcNodeParams) + sizeof(void *)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_hash_table_params_t) == sizeof(t_FmPcdHashTableParams) + sizeof(void *)); ++#endif ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_grp_params_t) == sizeof(t_FmPcdCcGrpParams)); ++#if !defined(CONFIG_COMPAT) ++ /* different alignment */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_tree_params_t) == sizeof(t_FmPcdCcTreeParams) + sizeof(void *)); ++#endif ++ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_byte_rate_mode_param_t) == sizeof(t_FmPcdPlcrByteRateModeParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_non_passthrough_alg_param_t) == sizeof(t_FmPcdPlcrNonPassthroughAlgParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_next_engine_params_u) == sizeof(u_FmPcdPlcrNextEngineParams)); ++ /*ioc_fm_pcd_port_params_t : private */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_profile_params_t) == sizeof(t_FmPcdPlcrProfileParams) + sizeof(void *)); ++ /*ioc_fm_pcd_cc_tree_modify_next_engine_params_t : private */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++#error TODO: unsupported feature ++/* ++ ASSERT_COND(sizeof(TODO) == sizeof(t_FmPcdManipHdrInsrtByTemplateParams)); ++ ASSERT_COND(sizeof(TODO) == sizeof(t_CapwapFragmentationParams)); ++ ASSERT_COND(sizeof(TODO) == sizeof(t_CapwapReassemblyParams)); ++ ASSERT_COND(sizeof(TODO) == sizeof(t_FmPcdManipFragOrReasmParams)); ++ ASSERT_COND(sizeof(TODO) == sizeof(t_FmPcdManipHdrRmvByHdrParams)); ++*/ ++#endif ++ ++ /*ioc_fm_pcd_cc_node_modify_next_engine_params_t : private */ ++ /*ioc_fm_pcd_cc_node_remove_key_params_t : private */ ++ /*ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t : private */ ++ /*ioc_fm_pcd_cc_node_modify_key_params_t : private */ ++ /*ioc_fm_manip_hdr_info_t : private */ ++ /*ioc_fm_pcd_hash_table_set_t : private */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_ip_params_t) == sizeof(t_FmPcdManipFragIpParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_ip_params_t) == sizeof(t_FmPcdManipReassemIpParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_special_offload_ipsec_params_t) == sizeof(t_FmPcdManipSpecialOffloadIPSecParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_special_offload_params_t) == sizeof(t_FmPcdManipSpecialOffloadParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_rmv_generic_params_t) == sizeof(t_FmPcdManipHdrRmvGenericParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_insrt_generic_params_t) == sizeof(t_FmPcdManipHdrInsrtGenericParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_insrt_params_t) == sizeof(t_FmPcdManipHdrInsrtParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_rmv_params_t) == sizeof(t_FmPcdManipHdrRmvParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_params_t) == sizeof(t_FmPcdManipHdrParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_params_t) == sizeof(t_FmPcdManipFragParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_params_t) == sizeof(t_FmPcdManipReassemParams)); ++#if !defined(CONFIG_COMPAT) ++ /* different alignment */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_params_t) == sizeof(t_FmPcdManipParams) + sizeof(void *)); ++#endif ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_ip_stats_t) == sizeof(t_FmPcdManipReassemIpStats)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_ip_stats_t) == sizeof(t_FmPcdManipFragIpStats)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_stats_t) == sizeof(t_FmPcdManipReassemStats)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_stats_t) == sizeof(t_FmPcdManipFragStats)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_stats_t) == sizeof(t_FmPcdManipStats)); ++#if DPAA_VERSION >= 11 ++ ASSERT_COND(sizeof(ioc_fm_pcd_frm_replic_group_params_t) == sizeof(t_FmPcdFrmReplicGroupParams) + sizeof(void *)); ++#endif ++ ++ /* fm_port_ext.h == fm_port_ioctls.h */ ++ ASSERT_COND(sizeof(ioc_fm_port_rate_limit_t) == sizeof(t_FmPortRateLimit)); ++ ASSERT_COND(sizeof(ioc_fm_port_pcd_params_t) == sizeof(t_FmPortPcdParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_select_t) == sizeof(t_FmPcdKgSchemeSelect)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_port_schemes_params_t) == sizeof(t_FmPcdPortSchemesParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_prs_start_t) == sizeof(t_FmPcdPrsStart)); ++ ++ return; ++} ++ ++#define ASSERT_IOC_NET_ENUM(def) ASSERT_COND((unsigned long)e_IOC_NET_##def == (unsigned long)def) ++ ++void LnxWrpPCDIOCTLEnumChecking(void) ++{ ++ /* net_ext.h == net_ioctls.h : sampling checks */ ++ ASSERT_IOC_NET_ENUM(HEADER_TYPE_MACSEC); ++ ASSERT_IOC_NET_ENUM(HEADER_TYPE_PPP); ++ ASSERT_IOC_NET_ENUM(MAX_HEADER_TYPE_COUNT); ++ ++ /* fm_ext.h == fm_ioctls.h */ ++ ASSERT_COND((unsigned long)e_IOC_FM_PORT_TYPE_DUMMY == (unsigned long)e_FM_PORT_TYPE_DUMMY); ++ ASSERT_COND((unsigned long)e_IOC_EX_MURAM_ECC == (unsigned long)e_FM_EX_MURAM_ECC); ++ ASSERT_COND((unsigned long)e_IOC_FM_COUNTERS_DEQ_CONFIRM == (unsigned long)e_FM_COUNTERS_DEQ_CONFIRM); ++ ++ /* fm_pcd_ext.h == fm_pcd_ioctls.h */ ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES == (unsigned long)e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PRS_EXCEPTION_SINGLE_ECC == (unsigned long)e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PRS == (unsigned long)e_FM_PCD_PRS); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_EXTRACT_FULL_FIELD == (unsigned long)e_FM_PCD_EXTRACT_FULL_FIELD); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_EXTRACT_FROM_FLOW_ID == (unsigned long)e_FM_PCD_EXTRACT_FROM_FLOW_ID); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO == (unsigned long)e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_KG_DFLT_ILLEGAL == (unsigned long)e_FM_PCD_KG_DFLT_ILLEGAL); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_KG_GENERIC_NOT_FROM_DATA == (unsigned long)e_FM_PCD_KG_GENERIC_NOT_FROM_DATA); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_HDR_INDEX_LAST == (unsigned long)e_FM_PCD_HDR_INDEX_LAST); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_SHARED == (unsigned long)e_FM_PCD_PLCR_SHARED); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_RFC_4115 == (unsigned long)e_FM_PCD_PLCR_RFC_4115); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_COLOR_AWARE == (unsigned long)e_FM_PCD_PLCR_COLOR_AWARE); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_OVERRIDE == (unsigned long)e_FM_PCD_PLCR_OVERRIDE); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_FULL_FRM_LEN == (unsigned long)e_FM_PCD_PLCR_FULL_FRM_LEN); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN == (unsigned long)e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_PACKET_MODE == (unsigned long)e_FM_PCD_PLCR_PACKET_MODE); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_DROP_FRAME == (unsigned long)e_FM_PCD_DROP_FRAME); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER == (unsigned long)e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP == (unsigned long)e_FM_PCD_ACTION_INDEXED_LOOKUP); ++ ASSERT_COND((unsigned long)e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR == (unsigned long)e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR); ++#if !defined(FM_CAPWAP_SUPPORT) ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_INSRT_GENERIC == (unsigned long)e_FM_PCD_MANIP_INSRT_GENERIC); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_RMV_GENERIC == (unsigned long)e_FM_PCD_MANIP_RMV_GENERIC); ++#else ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_INSRT_BY_TEMPLATE == (unsigned long)e_FM_PCD_MANIP_INSRT_BY_TEMPLATE); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_RMV_BY_HDR == (unsigned long)e_FM_PCD_MANIP_RMV_BY_HDR); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_RMV_BY_HDR_FROM_START == (unsigned long)e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START); ++#endif ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAG == (unsigned long)e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAG); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_EIGHT_WAYS_HASH == (unsigned long)e_FM_PCD_MANIP_EIGHT_WAYS_HASH); ++ ++#ifdef FM_CAPWAP_SUPPORT ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_STATS_PER_FLOWID == (unsigned long)e_FM_PCD_STATS_PER_FLOWID); ++#endif ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD == (unsigned long)e_FM_PCD_MANIP_SPECIAL_OFFLOAD); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_CC_STATS_MODE_FRAME == (unsigned long)e_FM_PCD_CC_STATS_MODE_FRAME); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG == (unsigned long)e_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC == (unsigned long)e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC); ++ ++ /* fm_port_ext.h == fm_port_ioctls.h */ ++#if !defined(FM_CAPWAP_SUPPORT) ++ ASSERT_COND((unsigned long)e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR == (unsigned long)e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR); ++#else ++ ASSERT_COND((unsigned long)e_IOC_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR == (unsigned long)e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR); ++#endif ++ ASSERT_COND((unsigned long)e_IOC_FM_PORT_COUNTERS_DEQ_CONFIRM == (unsigned long)e_FM_PORT_COUNTERS_DEQ_CONFIRM); ++ ASSERT_COND((unsigned long)e_IOC_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8 == (unsigned long)e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8); ++ ++ return; ++} ++ ++static t_Error LnxwrpFmPcdIOCTL(t_LnxWrpFmDev *p_LnxWrpFmDev, unsigned int cmd, unsigned long arg, bool compat) ++{ ++ t_Error err = E_OK; ++ ++/* ++Status: PCD API to fmlib (file: drivers/net/dpa/NetCommSw/inc/Peripherals/fm_pcd_ext.h): ++ ++ FM_PCD_PrsLoadSw ++ FM_PCD_SetAdvancedOffloadSupport ++ FM_PCD_Enable ++ FM_PCD_Disable ++ FM_PCD_ForceIntr ++ FM_PCD_SetException ++ FM_PCD_KgSetAdditionalDataAfterParsing ++ FM_PCD_KgSetDfltValue ++ FM_PCD_NetEnvCharacteristicsSet ++ FM_PCD_NetEnvCharacteristicsDelete ++ FM_PCD_KgSchemeSet ++ FM_PCD_KgSchemeDelete ++ FM_PCD_MatchTableSet ++ FM_PCD_MatchTableDelete ++ FM_PCD_CcRootBuild ++ FM_PCD_CcRootDelete ++ FM_PCD_PlcrProfileSet ++ FM_PCD_PlcrProfileDelete ++ FM_PCD_CcRootModifyNextEngine ++ FM_PCD_MatchTableModifyNextEngine ++ FM_PCD_MatchTableModifyMissNextEngine ++ FM_PCD_MatchTableRemoveKey ++ FM_PCD_MatchTableAddKey ++ FM_PCD_MatchTableModifyKeyAndNextEngine ++ FM_PCD_HashTableSet ++ FM_PCD_HashTableDelete ++ FM_PCD_HashTableAddKey ++ FM_PCD_HashTableRemoveKey ++ FM_PCD_MatchTableModifyKey ++ FM_PCD_ManipNodeReplace ++ FM_PCD_ManipNodeSet ++ FM_PCD_ManipNodeDelete ++ ++Status: not exported, should be thru sysfs ++ FM_PCD_KgSchemeGetCounter ++ FM_PCD_KgSchemeSetCounter ++ FM_PCD_PlcrProfileGetCounter ++ FM_PCD_PlcrProfileSetCounter ++ ++Status: not exported ++ FM_PCD_MatchTableFindNRemoveKey ++ FM_PCD_MatchTableFindNModifyNextEngine ++ FM_PCD_MatchTableFindNModifyKeyAndNextEngine ++ FM_PCD_MatchTableFindNModifyKey ++ FM_PCD_MatchTableGetIndexedHashBucket ++ FM_PCD_MatchTableGetNextEngine ++ FM_PCD_MatchTableGetKeyCounter ++ ++Status: not exported, would be nice to have ++ FM_PCD_HashTableModifyNextEngine ++ FM_PCD_HashTableModifyMissNextEngine ++ FM_PCD_HashTableGetMissNextEngine ++ FM_PCD_ManipGetStatistics ++ ++Status: not exported ++#if DPAA_VERSION >= 11 ++ ++ FM_VSP_GetStatistics -- it's not available yet ++#endif ++ ++Status: feature not supported ++#ifdef FM_CAPWAP_SUPPORT ++#error unsupported feature ++ FM_PCD_StatisticsSetNode ++#endif ++ ++ */ ++ _fm_ioctl_dbg("cmd:0x%08x(type:0x%02x, nr:%u).\n", ++ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd) - 20); ++ ++ switch (cmd) ++ { ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_PRS_LOAD_SW_COMPAT: ++#endif ++ case FM_PCD_IOC_PRS_LOAD_SW: ++ { ++ ioc_fm_pcd_prs_sw_params_t *param; ++ uint8_t *p_code; ++ ++ param = (ioc_fm_pcd_prs_sw_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_prs_sw_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_prs_sw_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_prs_sw_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_prs_sw_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_prs_sw_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_prs_sw_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_prs_sw_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_prs_sw_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_fm_pcd_prs_sw(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_prs_sw_params_t *)arg, ++ sizeof(ioc_fm_pcd_prs_sw_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (!param->p_code || !param->size) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ p_code = (uint8_t *) XX_Malloc(param->size); ++ if (!p_code) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(p_code, 0, param->size); ++ if (copy_from_user(p_code, param->p_code, param->size)) ++ { ++ XX_Free(p_code); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->p_code = p_code; ++ ++ err = FM_PCD_PrsLoadSw(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdPrsSwParams*)param); ++ ++ XX_Free(p_code); ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PCD_IOC_SET_ADVANCED_OFFLOAD_SUPPORT: ++ err = FM_PCD_SetAdvancedOffloadSupport(p_LnxWrpFmDev->h_PcdDev); ++ break; ++ ++ case FM_PCD_IOC_ENABLE: ++ err = FM_PCD_Enable(p_LnxWrpFmDev->h_PcdDev); ++ break; ++ ++ case FM_PCD_IOC_DISABLE: ++ err = FM_PCD_Disable(p_LnxWrpFmDev->h_PcdDev); ++ break; ++ ++ case FM_PCD_IOC_FORCE_INTR: ++ { ++ int exception; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (get_user(exception, (int *) compat_ptr(arg))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ { ++ if (get_user(exception, (int *)arg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_ForceIntr(p_LnxWrpFmDev->h_PcdDev, (e_FmPcdExceptions)exception); ++ break; ++ } ++ ++ case FM_PCD_IOC_SET_EXCEPTION: ++ { ++ ioc_fm_pcd_exception_params_t *param; ++ ++ param = (ioc_fm_pcd_exception_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_exception_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_exception_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_exception_params_t *)compat_ptr(arg), ++ sizeof(ioc_fm_pcd_exception_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_exception_params_t *)arg, ++ sizeof(ioc_fm_pcd_exception_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, param->exception, param->enable); ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PCD_IOC_KG_SET_ADDITIONAL_DATA_AFTER_PARSING: ++ { ++ uint8_t payloadOffset; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (get_user(payloadOffset, (uint8_t*) compat_ptr(arg))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ { ++ if (get_user(payloadOffset, (uint8_t*) arg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_KgSetAdditionalDataAfterParsing(p_LnxWrpFmDev->h_PcdDev, payloadOffset); ++ break; ++ } ++ ++ case FM_PCD_IOC_KG_SET_DFLT_VALUE: ++ { ++ ioc_fm_pcd_kg_dflt_value_params_t *param; ++ ++ param = (ioc_fm_pcd_kg_dflt_value_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_kg_dflt_value_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_kg_dflt_value_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_kg_dflt_value_params_t *)compat_ptr(arg), ++ sizeof(ioc_fm_pcd_kg_dflt_value_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_kg_dflt_value_params_t *)arg, ++ sizeof(ioc_fm_pcd_kg_dflt_value_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_KgSetDfltValue(p_LnxWrpFmDev->h_PcdDev, param->valueId, param->value); ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET: ++ { ++ ioc_fm_pcd_net_env_params_t *param; ++ ++ param = (ioc_fm_pcd_net_env_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_net_env_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_net_env_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_net_env_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_net_env_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_net_env_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_net_env_params_t)); ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_net_env_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_net_env_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_net_env(compat_param, param, COMPAT_US_TO_K); ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_net_env_params_t *) arg, ++ sizeof(ioc_fm_pcd_net_env_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ param->id = FM_PCD_NetEnvCharacteristicsSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdNetEnvParams*)param); ++ ++ if (!param->id) ++ { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_net_env_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_net_env_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_net_env_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_net_env_params_t)); ++ compat_copy_fm_pcd_net_env(compat_param, param, COMPAT_K_TO_US); ++ ++ if (copy_to_user((ioc_compat_fm_pcd_net_env_params_t *) compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_net_env_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_net_env_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_net_env_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_NetEnvCharacteristicsDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_KG_SCHEME_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_KG_SCHEME_SET: ++ { ++ ioc_fm_pcd_kg_scheme_params_t *param; ++ ++ param = (ioc_fm_pcd_kg_scheme_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_kg_scheme_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_kg_scheme_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param = NULL; ++ ++ compat_param = (ioc_compat_fm_pcd_kg_scheme_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_params_t)); ++ ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_kg_scheme_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_kg_scheme(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_kg_scheme_params_t *)arg, ++ sizeof(ioc_fm_pcd_kg_scheme_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ param->id = FM_PCD_KgSchemeSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdKgSchemeParams*)param); ++ ++ if (!param->id) ++ { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_kg_scheme_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_params_t)); ++ compat_copy_fm_pcd_kg_scheme(compat_param, param, COMPAT_K_TO_US); ++ if (copy_to_user((ioc_compat_fm_pcd_kg_scheme_params_t *)compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_kg_scheme_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_kg_scheme_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_KG_SCHEME_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_KG_SCHEME_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_KgSchemeDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_SET: ++ { ++ ioc_fm_pcd_cc_node_params_t *param; ++ uint8_t *keys; ++ uint8_t *masks; ++ int i,k; ++ ++ param = (ioc_fm_pcd_cc_node_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_params_t) + ++ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_params_t) + ++ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ ++ keys = (uint8_t *) (param + 1); ++ masks = keys + IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_params_t) + ++ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_params_t) + ++ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_node_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_node(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_params_t *)arg, sizeof(ioc_fm_pcd_cc_node_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ ASSERT_COND(param->keys_params.num_of_keys <= IOC_FM_PCD_MAX_NUM_OF_KEYS); ++ ASSERT_COND(param->keys_params.key_size <= IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ ++ /* support for indexed lookup */ ++ if( !(param->extract_cc_params.type == e_IOC_FM_PCD_EXTRACT_NON_HDR && ++ param->extract_cc_params.extract_params.extract_non_hdr.src == e_IOC_FM_PCD_EXTRACT_FROM_HASH && ++ param->extract_cc_params.extract_params.extract_non_hdr.action == e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP)) ++ { ++ for (i=0, k=0; ++ i < param->keys_params.num_of_keys; ++ i++, k += IOC_FM_PCD_MAX_SIZE_OF_KEY) ++ { ++ if (param->keys_params.key_params[i].p_key && ++ param->keys_params.key_size) ++ { ++ if (copy_from_user(&keys[k], ++ param->keys_params.key_params[i].p_key, ++ param->keys_params.key_size)) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->keys_params.key_params[i].p_key = &keys[k]; ++ } ++ ++ if (param->keys_params.key_params[i].p_mask) ++ { ++ if (copy_from_user(&masks[k], ++ param->keys_params.key_params[i].p_mask, ++ param->keys_params.key_size)) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->keys_params.key_params[i].p_mask = &masks[k]; ++ } ++ } ++ } ++ ++ param->id = FM_PCD_MatchTableSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdCcNodeParams*)param); ++ ++ if (!param->id) { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_params_t *compat_param; ++ compat_param = (ioc_compat_fm_pcd_cc_node_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_params_t) + ++ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_params_t) + ++ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ compat_copy_fm_pcd_cc_node(compat_param, param, COMPAT_K_TO_US); ++ ++ if (copy_to_user((ioc_compat_fm_pcd_cc_node_params_t *)compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_cc_node_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_cc_node_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_cc_node_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_MatchTableDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_CC_ROOT_BUILD_COMPAT: ++#endif ++ case FM_PCD_IOC_CC_ROOT_BUILD: ++ { ++ ioc_fm_pcd_cc_tree_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_tree_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_cc_tree_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_tree_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_tree_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_tree_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_tree_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tree_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_tree_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_tree_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_tree(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_tree_params_t *)arg, ++ sizeof(ioc_fm_pcd_cc_tree_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ param->id = FM_PCD_CcRootBuild(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdCcTreeParams*)param); ++ ++ if (!param->id) { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_tree_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_tree_params_t *) XX_Malloc(sizeof(ioc_compat_fm_pcd_cc_tree_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tree_params_t)); ++ ++ compat_copy_fm_pcd_cc_tree(compat_param, param, COMPAT_K_TO_US); ++ ++ if (copy_to_user((ioc_compat_fm_pcd_cc_tree_params_t *)compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_cc_tree_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_cc_tree_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_cc_tree_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_CC_ROOT_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_CC_ROOT_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_CcRootDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_PLCR_PROFILE_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_PLCR_PROFILE_SET: ++ { ++ ioc_fm_pcd_plcr_profile_params_t *param; ++ ++ param = (ioc_fm_pcd_plcr_profile_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_plcr_profile_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_plcr_profile_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_plcr_profile_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_fm_pcd_plcr_profile_params_t)); ++ if (copy_from_user(compat_param, ( ++ ioc_compat_fm_pcd_plcr_profile_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_plcr_profile(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_plcr_profile_params_t *)arg, ++ sizeof(ioc_fm_pcd_plcr_profile_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (!param->modify && ++ (((t_FmPcdPlcrProfileParams*)param)->id.newParams.profileType != e_FM_PCD_PLCR_SHARED)) ++ { ++ t_Handle h_Port; ++ ioc_fm_pcd_port_params_t *port_params; ++ ++ port_params = (ioc_fm_pcd_port_params_t*) XX_Malloc(sizeof(ioc_fm_pcd_port_params_t)); ++ if (!port_params) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(port_params, 0, sizeof(ioc_fm_pcd_port_params_t)); ++ if (copy_from_user(port_params, (ioc_fm_pcd_port_params_t*)((t_FmPcdPlcrProfileParams*)param)->id.newParams.h_FmPort, ++ sizeof(ioc_fm_pcd_port_params_t))) ++ { ++ XX_Free(port_params); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ switch(port_params->port_type) ++ { ++ case (e_IOC_FM_PORT_TYPE_RX): ++ if (port_params->port_id < FM_MAX_NUM_OF_1G_RX_PORTS) { ++ h_Port = p_LnxWrpFmDev->rxPorts[port_params->port_id].h_Dev; ++ break; ++ } ++ goto invalid_port_id; ++ ++ case (e_IOC_FM_PORT_TYPE_RX_10G): ++ if (port_params->port_id < FM_MAX_NUM_OF_10G_RX_PORTS) { ++ h_Port = p_LnxWrpFmDev->rxPorts[port_params->port_id + FM_MAX_NUM_OF_1G_RX_PORTS].h_Dev; ++ break; ++ } ++ goto invalid_port_id; ++ ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ if (port_params->port_id && port_params->port_id < FM_MAX_NUM_OF_OH_PORTS) { ++ h_Port = p_LnxWrpFmDev->opPorts[port_params->port_id - 1].h_Dev; ++ break; ++ } ++ goto invalid_port_id; ++ ++ default: ++invalid_port_id: ++ XX_Free(port_params); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ ((t_FmPcdPlcrProfileParams*)param)->id.newParams.h_FmPort = h_Port; ++ XX_Free(port_params); ++ } ++ ++ param->id = FM_PCD_PlcrProfileSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdPlcrProfileParams*)param); ++ ++ if (!param->id) { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_plcr_profile_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_plcr_profile_params_t)); ++ compat_copy_fm_pcd_plcr_profile(compat_param, param, COMPAT_K_TO_US); ++ if (copy_to_user((ioc_compat_fm_pcd_plcr_profile_params_t *) compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_plcr_profile_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_plcr_profile_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_PLCR_PROFILE_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_PLCR_PROFILE_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_PlcrProfileDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_CC_ROOT_MODIFY_NEXT_ENGINE_COMPAT: ++#endif ++ case FM_PCD_IOC_CC_ROOT_MODIFY_NEXT_ENGINE: ++ { ++ ioc_fm_pcd_cc_tree_modify_next_engine_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_tree_modify_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_tree_modify_next_engine_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_tree_modify_next_engine_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t)); ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_fm_pcd_cc_tree_modify_next_engine(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_tree_modify_next_engine_params_t *)arg, ++ sizeof(ioc_fm_pcd_cc_tree_modify_next_engine_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_CcRootModifyNextEngine(param->id, ++ param->grp_indx, ++ param->indx, ++ (t_FmPcdCcNextEngineParams*)(¶m->cc_next_engine_params)); ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_NEXT_ENGINE_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_NEXT_ENGINE: ++ { ++ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t)); ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_node_modify_next_engine(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_next_engine_params_t *)arg, ++ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_MatchTableModifyNextEngine(param->id, ++ param->key_indx, ++ (t_FmPcdCcNextEngineParams*)(¶m->cc_next_engine_params)); ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_MISS_NEXT_ENGINE_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_MISS_NEXT_ENGINE: ++ { ++ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t)); ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_node_modify_next_engine(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_next_engine_params_t *) arg, ++ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_MatchTableModifyMissNextEngine(param->id, ++ (t_FmPcdCcNextEngineParams*)(¶m->cc_next_engine_params)); ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_REMOVE_KEY_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_REMOVE_KEY: ++ { ++ ioc_fm_pcd_cc_node_remove_key_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_node_remove_key_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_remove_key_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_remove_key_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_remove_key_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_remove_key_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_remove_key_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_remove_key_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_node_remove_key_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_remove_key_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->id = compat_ptr(compat_param->id); ++ param->key_indx = compat_param->key_indx; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_remove_key_params_t *) arg, ++ sizeof(ioc_fm_pcd_cc_node_remove_key_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_MatchTableRemoveKey(param->id, param->key_indx); ++ ++ XX_Free(param); ++ break; ++ } ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_ADD_KEY_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_ADD_KEY: ++ { ++ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_node_modify_key_and_next_engine(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)arg, ++ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (param->key_size) ++ { ++ int size = 0; ++ ++ if (param->key_params.p_key) size += param->key_size; ++ if (param->key_params.p_mask) size += param->key_size; ++ ++ if (size) ++ { ++ uint8_t *p_tmp; ++ ++ p_tmp = (uint8_t*) XX_Malloc(size); ++ if (!p_tmp) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD key/mask")); ++ } ++ ++ if (param->key_params.p_key) ++ { ++ if (copy_from_user(p_tmp, param->key_params.p_key, param->key_size)) ++ { ++ XX_Free(p_tmp); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->key_params.p_key = p_tmp; ++ } ++ ++ if (param->key_params.p_mask) ++ { ++ p_tmp += param->key_size; ++ if (copy_from_user(p_tmp, param->key_params.p_mask, param->key_size)) ++ { ++ XX_Free(p_tmp - param->key_size); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->key_params.p_mask = p_tmp; ++ } ++ } ++ } ++ ++ err = FM_PCD_MatchTableAddKey( ++ param->id, ++ param->key_indx, ++ param->key_size, ++ (t_FmPcdCcKeyParams*)¶m->key_params); ++ ++ if (param->key_params.p_key) ++ XX_Free(param->key_params.p_key); ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_AND_NEXT_ENGINE_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_AND_NEXT_ENGINE: ++ { ++ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_node_modify_key_and_next_engine(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)arg, ++ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_MatchTableModifyKeyAndNextEngine(param->id, ++ param->key_indx, ++ param->key_size, ++ (t_FmPcdCcKeyParams*)(¶m->key_params)); ++ ++ XX_Free(param); ++ break; ++ } ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_HASH_TABLE_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_HASH_TABLE_SET: ++ { ++ ioc_fm_pcd_hash_table_params_t *param; ++ ++ param = (ioc_fm_pcd_hash_table_params_t*) XX_Malloc( ++ sizeof(ioc_fm_pcd_hash_table_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_hash_table_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_hash_table_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_hash_table_params_t*) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_hash_table_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_hash_table_params_t*)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_hash_table_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_hash_table(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_hash_table_params_t *)arg, ++ sizeof(ioc_fm_pcd_hash_table_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ param->id = FM_PCD_HashTableSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdHashTableParams *) param); ++ ++ if (!param->id) ++ { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_hash_table_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_hash_table_params_t*) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_hash_table_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_params_t)); ++ compat_copy_fm_pcd_hash_table(compat_param, param, COMPAT_K_TO_US); ++ if (copy_to_user((ioc_compat_fm_pcd_hash_table_params_t*) compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_hash_table_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_hash_table_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_hash_table_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_HASH_TABLE_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_HASH_TABLE_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0, sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ id.obj = compat_pcd_id2ptr(compat_id.obj); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_HashTableDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_HASH_TABLE_ADD_KEY_COMPAT: ++#endif ++ case FM_PCD_IOC_HASH_TABLE_ADD_KEY: ++ { ++ ioc_fm_pcd_hash_table_add_key_params_t *param = NULL; ++ ++ param = (ioc_fm_pcd_hash_table_add_key_params_t*) XX_Malloc( ++ sizeof(ioc_fm_pcd_hash_table_add_key_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_hash_table_add_key_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_hash_table_add_key_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_hash_table_add_key_params_t*) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_hash_table_add_key_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_add_key_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_hash_table_add_key_params_t*) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_hash_table_add_key_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ if (compat_param->key_size) ++ { ++ param->p_hash_tbl = compat_pcd_id2ptr(compat_param->p_hash_tbl); ++ param->key_size = compat_param->key_size; ++ ++ compat_copy_fm_pcd_cc_key(&compat_param->key_params, ¶m->key_params, COMPAT_US_TO_K); ++ } ++ else ++ { ++ XX_Free(compat_param); ++ err = E_INVALID_VALUE; ++ break; ++ } ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_hash_table_add_key_params_t*) arg, ++ sizeof(ioc_fm_pcd_hash_table_add_key_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (param->key_size) ++ { ++ int size = 0; ++ ++ if (param->key_params.p_key) size += param->key_size; ++ if (param->key_params.p_mask) size += param->key_size; ++ ++ if (size) ++ { ++ uint8_t *p_tmp; ++ ++ p_tmp = (uint8_t*) XX_Malloc(size); ++ if (!p_tmp) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD key/mask")); ++ } ++ ++ if (param->key_params.p_key) ++ { ++ if (copy_from_user(p_tmp, param->key_params.p_key, param->key_size)) ++ { ++ XX_Free(p_tmp); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->key_params.p_key = p_tmp; ++ } ++ ++ if (param->key_params.p_mask) ++ { ++ p_tmp += param->key_size; ++ if (copy_from_user(p_tmp, param->key_params.p_mask, param->key_size)) ++ { ++ XX_Free(p_tmp - param->key_size); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->key_params.p_mask = p_tmp; ++ } ++ } ++ } ++ ++ err = FM_PCD_HashTableAddKey( ++ param->p_hash_tbl, ++ param->key_size, ++ (t_FmPcdCcKeyParams*)¶m->key_params); ++ ++ if (param->key_params.p_key) ++ XX_Free(param->key_params.p_key); ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_HASH_TABLE_REMOVE_KEY_COMPAT: ++#endif ++ case FM_PCD_IOC_HASH_TABLE_REMOVE_KEY: ++ { ++ ioc_fm_pcd_hash_table_remove_key_params_t *param = NULL; ++ ++ param = (ioc_fm_pcd_hash_table_remove_key_params_t*) XX_Malloc( ++ sizeof(ioc_fm_pcd_hash_table_remove_key_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_hash_table_remove_key_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_hash_table_remove_key_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_hash_table_remove_key_params_t*) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_hash_table_remove_key_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_remove_key_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_hash_table_remove_key_params_t*) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_hash_table_remove_key_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->p_hash_tbl = compat_pcd_id2ptr(compat_param->p_hash_tbl); ++ param->key_size = compat_param->key_size; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_hash_table_remove_key_params_t*)arg, ++ sizeof(ioc_fm_pcd_hash_table_remove_key_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (param->key_size) ++ { ++ uint8_t *p_key; ++ ++ p_key = (uint8_t*) XX_Malloc(param->key_size); ++ if (!p_key) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ if (param->p_key && copy_from_user(p_key, param->p_key, param->key_size)) ++ { ++ XX_Free(p_key); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ param->p_key = p_key; ++ } ++ ++ err = FM_PCD_HashTableRemoveKey( ++ param->p_hash_tbl, ++ param->key_size, ++ param->p_key); ++ ++ if (param->p_key) ++ XX_Free(param->p_key); ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY: ++ { ++ ioc_fm_pcd_cc_node_modify_key_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_node_modify_key_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_modify_key_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_key_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_modify_key_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_modify_key_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_key_params_t)); ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_node_modify_key_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_node_modify_key(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_key_params_t *)arg, ++ sizeof(ioc_fm_pcd_cc_node_modify_key_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (param->key_size) ++ { ++ int size = 0; ++ ++ if (param->p_key) size += param->key_size; ++ if (param->p_mask) size += param->key_size; ++ ++ if (size) ++ { ++ uint8_t *p_tmp; ++ ++ p_tmp = (uint8_t*) XX_Malloc(size); ++ if (!p_tmp) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD key/mask")); ++ } ++ ++ if (param->p_key) ++ { ++ if (copy_from_user(p_tmp, param->p_key, param->key_size)) ++ { ++ XX_Free(p_tmp); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->p_key = p_tmp; ++ } ++ ++ if (param->p_mask) ++ { ++ p_tmp += param->key_size; ++ if (copy_from_user(p_tmp, param->p_mask, param->key_size)) ++ { ++ XX_Free(p_tmp - param->key_size); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->p_mask = p_tmp; ++ } ++ } ++ } ++ ++ err = FM_PCD_MatchTableModifyKey(param->id, ++ param->key_indx, ++ param->key_size, ++ param->p_key, ++ param->p_mask); ++ ++ if (param->p_key) ++ XX_Free(param->p_key); ++ else if (param->p_mask) ++ XX_Free(param->p_mask); ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MANIP_NODE_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_MANIP_NODE_SET: ++ { ++ ioc_fm_pcd_manip_params_t *param; ++ uint8_t *p_data = NULL; ++ uint8_t size; ++ ++ param = (ioc_fm_pcd_manip_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_manip_params_t)); ++ ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_manip_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_manip_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_manip_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_manip_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_manip_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_manip_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_manip_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_fm_pcd_manip_set_node(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_manip_params_t *)arg, ++ sizeof(ioc_fm_pcd_manip_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (param->type == e_IOC_FM_PCD_MANIP_HDR) ++ { ++ size = param->u.hdr.insrt_params.u.generic.size; ++ p_data = (uint8_t *) XX_Malloc(size); ++ if (!p_data ) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, NO_MSG); ++ } ++ ++ if (param->u.hdr.insrt_params.u.generic.p_data && ++ copy_from_user(p_data, ++ param->u.hdr.insrt_params.u.generic.p_data, size)) ++ { ++ XX_Free(p_data); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->u.hdr.insrt_params.u.generic.p_data = p_data; ++ } ++ ++ if (param->id) ++ { ++ /* Security Hole: the user can pass any piece of garbage ++ in 'param->id', and that will go straight through to the LLD, ++ no checks being done by the wrapper! */ ++ err = FM_PCD_ManipNodeReplace( ++ (t_Handle) param->id, ++ (t_FmPcdManipParams*) param); ++ if (err) ++ { ++ if (p_data) ++ XX_Free(p_data); ++ XX_Free(param); ++ break; ++ } ++ } ++ else ++ { ++ param->id = FM_PCD_ManipNodeSet( ++ p_LnxWrpFmDev->h_PcdDev, ++ (t_FmPcdManipParams*) param); ++ if (!param->id) ++ { ++ if (p_data) ++ XX_Free(p_data); ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_manip_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_manip_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_manip_params_t)); ++ if (!compat_param) ++ { ++ if (p_data) ++ XX_Free(p_data); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_manip_params_t)); ++ ++ compat_fm_pcd_manip_set_node(compat_param, param, COMPAT_K_TO_US); ++ ++ if (copy_to_user((ioc_compat_fm_pcd_manip_params_t *) compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_manip_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_manip_params_t *)arg, ++ param, sizeof(ioc_fm_pcd_manip_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ if (p_data) ++ XX_Free(p_data); ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MANIP_NODE_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_MANIP_NODE_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0, sizeof(ioc_fm_obj_t)); ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_ManipNodeDelete(id.obj); ++ break; ++ } ++ ++#if (DPAA_VERSION >= 11) ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_FRM_REPLIC_GROUP_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_FRM_REPLIC_GROUP_SET: ++ { ++ ioc_fm_pcd_frm_replic_group_params_t *param; ++ ++ param = (ioc_fm_pcd_frm_replic_group_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_frm_replic_group_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_plcr_profile_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_frm_replic_group_params_t ++ *compat_param; ++ ++ compat_param = ++ (ioc_compat_fm_pcd_frm_replic_group_params_t *) ++ XX_Malloc(sizeof(*compat_param)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ++ ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(*compat_param)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_frm_replic_group_params_t *) ++ compat_ptr(arg), ++ sizeof(*compat_param))) { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_frm_replic_group_params(compat_param, ++ param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, ++ (ioc_fm_pcd_frm_replic_group_params_t *)arg, ++ sizeof(ioc_fm_pcd_frm_replic_group_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ } ++ ++ param->id = FM_PCD_FrmReplicSetGroup(p_LnxWrpFmDev->h_PcdDev, ++ (t_FmPcdFrmReplicGroupParams*)param); ++ ++ if (!param->id) { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* ++ * Since the LLD has no errno-style error reporting, ++ * we're left here with no other option than to report ++ * a generic E_INVALID_VALUE ++ */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_frm_replic_group_params_t ++ *compat_param; ++ ++ compat_param = ++ (ioc_compat_fm_pcd_frm_replic_group_params_t *) ++ XX_Malloc(sizeof(*compat_param)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ++ ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(*compat_param)); ++ compat_copy_fm_pcd_frm_replic_group_params(compat_param, ++ param, COMPAT_K_TO_US); ++ if (copy_to_user( ++ (ioc_compat_fm_pcd_frm_replic_group_params_t *) ++ compat_ptr(arg), ++ compat_param, ++ sizeof(*compat_param))) ++ err = E_WRITE_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user( ++ (ioc_fm_pcd_frm_replic_group_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_frm_replic_group_params_t))) ++ err = E_WRITE_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_FRM_REPLIC_GROUP_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_FRM_REPLIC_GROUP_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0, sizeof(ioc_fm_obj_t)); ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, ++ (ioc_compat_fm_obj_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_obj_t))) ++ break; ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, ++ sizeof(ioc_fm_obj_t))) ++ break; ++ } ++ ++ return FM_PCD_FrmReplicDeleteGroup(id.obj); ++ } ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_FRM_REPLIC_MEMBER_ADD_COMPAT: ++#endif ++ case FM_PCD_IOC_FRM_REPLIC_MEMBER_ADD: ++ { ++ ioc_fm_pcd_frm_replic_member_params_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_frm_replic_member_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_pcd_frm_replic_member_params(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ return FM_PCD_FrmReplicAddMember(param.member.h_replic_group, ++ param.member.member_index, ++ (t_FmPcdCcNextEngineParams*)¶m.next_engine_params); ++ } ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_FRM_REPLIC_MEMBER_REMOVE_COMPAT: ++#endif ++ case FM_PCD_IOC_FRM_REPLIC_MEMBER_REMOVE: ++ { ++ ioc_fm_pcd_frm_replic_member_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_frm_replic_member_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_pcd_frm_replic_member(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ return FM_PCD_FrmReplicRemoveMember(param.h_replic_group, param.member_index); ++ } ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_CONFIG_COMPAT: ++#endif ++ case FM_IOC_VSP_CONFIG: ++ { ++ ioc_fm_vsp_params_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_vsp_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_vsp_params(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ param.p_fm = p_LnxWrpFmDev->h_Dev; ++ param.id = FM_VSP_Config((t_FmVspParams *)¶m); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_vsp_params_t compat_param; ++ ++ memset(&compat_param, 0, sizeof(compat_param)); ++ compat_copy_fm_vsp_params(&compat_param, ¶m, COMPAT_K_TO_US); ++ ++ if (copy_to_user(compat_ptr(arg), &compat_param, sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ if (copy_to_user((void *)arg, ¶m, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_INIT_COMPAT: ++#endif ++ case FM_IOC_VSP_INIT: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0, sizeof(ioc_fm_obj_t)); ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, ++ (ioc_compat_fm_obj_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_obj_t))) ++ break; ++ id.obj = compat_pcd_id2ptr(compat_id.obj); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, ++ sizeof(ioc_fm_obj_t))) ++ break; ++ } ++ ++ return FM_VSP_Init(id.obj); ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_FREE_COMPAT: ++#endif ++ case FM_IOC_VSP_FREE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0, sizeof(ioc_fm_obj_t)); ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, ++ (ioc_compat_fm_obj_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_obj_t))) ++ break; ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, ++ sizeof(ioc_fm_obj_t))) ++ break; ++ } ++ ++ return FM_VSP_Free(id.obj); ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_CONFIG_POOL_DEPLETION_COMPAT: ++#endif ++ case FM_IOC_VSP_CONFIG_POOL_DEPLETION: ++ { ++ ioc_fm_buf_pool_depletion_params_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_buf_pool_depletion_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_buf_pool_depletion_params(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (FM_VSP_ConfigPoolDepletion(param.p_fm_vsp, ++ (t_FmBufPoolDepletion *)¶m.fm_buf_pool_depletion)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ break; ++ } ++ ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_CONFIG_BUFFER_PREFIX_CONTENT_COMPAT: ++#endif ++ case FM_IOC_VSP_CONFIG_BUFFER_PREFIX_CONTENT: ++ { ++ ioc_fm_buffer_prefix_content_params_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_buffer_prefix_content_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_buffer_prefix_content_params(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (FM_VSP_ConfigBufferPrefixContent(param.p_fm_vsp, ++ (t_FmBufferPrefixContent *)¶m.fm_buffer_prefix_content)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_CONFIG_NO_SG_COMPAT: ++#endif ++ case FM_IOC_VSP_CONFIG_NO_SG: ++ { ++ ioc_fm_vsp_config_no_sg_params_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_vsp_config_no_sg_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_vsp_config_no_sg_params(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (FM_VSP_ConfigNoScatherGather(param.p_fm_vsp, param.no_sg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_GET_BUFFER_PRS_RESULT_COMPAT: ++#endif ++ case FM_IOC_VSP_GET_BUFFER_PRS_RESULT: ++ { ++ ioc_fm_vsp_prs_result_params_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_vsp_prs_result_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_vsp_prs_result_params(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ /* this call just adds the parse results offset to p_data */ ++ param.p_data = FM_VSP_GetBufferPrsResult(param.p_fm_vsp, param.p_data); ++ ++ if (!param.p_data) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_vsp_prs_result_params_t compat_param; ++ ++ memset(&compat_param, 0, sizeof(compat_param)); ++ compat_copy_fm_vsp_prs_result_params(&compat_param, ¶m, COMPAT_K_TO_US); ++ ++ if (copy_to_user(compat_ptr(arg), &compat_param, sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ if (copy_to_user((void *)arg, ¶m, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ break; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++#warning "feature not supported!" ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_STATISTICS_SET_NODE_COMPAT: ++#endif ++ case FM_PCD_IOC_STATISTICS_SET_NODE: ++ { ++/* ioc_fm_pcd_stats_params_t param; ++ ... ++ param->id = FM_PCD_StatisticsSetNode(p_LnxWrpFmDev->h_PcdDev, ++ (t_FmPcdStatsParams *)¶m); ++*/ ++ err = E_NOT_SUPPORTED; ++ break; ++ } ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ++ ("invalid ioctl: cmd:0x%08x(type:0x%02x, nr: %d.\n", ++ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd))); ++ } ++ ++ if (err) ++ RETURN_ERROR(MINOR, err, ("IOCTL FM PCD")); ++ ++ return E_OK; ++} ++ ++void FM_Get_Api_Version(ioc_fm_api_version_t *p_version) ++{ ++ p_version->version.major = FMD_API_VERSION_MAJOR; ++ p_version->version.minor = FMD_API_VERSION_MINOR; ++ p_version->version.respin = FMD_API_VERSION_RESPIN; ++ p_version->version.reserved = 0; ++} ++ ++t_Error LnxwrpFmIOCTL(t_LnxWrpFmDev *p_LnxWrpFmDev, unsigned int cmd, unsigned long arg, bool compat) ++{ ++ t_Error err = E_OK; ++ ++ switch (cmd) ++ { ++ case FM_IOC_SET_PORTS_BANDWIDTH: ++ { ++ ioc_fm_port_bandwidth_params *param; ++ ++ param = (ioc_fm_port_bandwidth_params*) XX_Malloc(sizeof(ioc_fm_port_bandwidth_params)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_port_bandwidth_params)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_port_bandwidth_params*)compat_ptr(arg), sizeof(ioc_fm_port_bandwidth_params))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_port_bandwidth_params*)arg, sizeof(ioc_fm_port_bandwidth_params))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_SetPortsBandwidth(p_LnxWrpFmDev->h_Dev, (t_FmPortsBandwidthParams*) param); ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_IOC_GET_REVISION: ++ { ++ ioc_fm_revision_info_t *param; ++ ++ param = (ioc_fm_revision_info_t *) XX_Malloc(sizeof(ioc_fm_revision_info_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ FM_GetRevision(p_LnxWrpFmDev->h_Dev, (t_FmRevisionInfo*)param); ++ /* This one never returns anything other than E_OK */ ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_to_user((ioc_fm_revision_info_t *)compat_ptr(arg), ++ param, ++ sizeof(ioc_fm_revision_info_t))) ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_revision_info_t *)arg, ++ param, ++ sizeof(ioc_fm_revision_info_t))) ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_IOC_SET_COUNTER: ++ { ++ ioc_fm_counters_params_t *param; ++ ++ param = (ioc_fm_counters_params_t *) XX_Malloc(sizeof(ioc_fm_counters_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_counters_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_counters_params_t *)compat_ptr(arg), sizeof(ioc_fm_counters_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_counters_params_t *)arg, sizeof(ioc_fm_counters_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_ModifyCounter(p_LnxWrpFmDev->h_Dev, param->cnt, param->val); ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_IOC_GET_COUNTER: ++ { ++ ioc_fm_counters_params_t *param; ++ ++ param = (ioc_fm_counters_params_t *) XX_Malloc(sizeof(ioc_fm_counters_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_counters_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_counters_params_t *)compat_ptr(arg), sizeof(ioc_fm_counters_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_counters_params_t *)arg, sizeof(ioc_fm_counters_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ param->val = FM_GetCounter(p_LnxWrpFmDev->h_Dev, param->cnt); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_to_user((ioc_fm_counters_params_t *)compat_ptr(arg), param, sizeof(ioc_fm_counters_params_t))) ++ err = E_READ_FAILED; ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_counters_params_t *)arg, param, sizeof(ioc_fm_counters_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_IOC_FORCE_INTR: ++ { ++ ioc_fm_exceptions param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (get_user(param, (ioc_fm_exceptions*) compat_ptr(arg))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ { ++ if (get_user(param, (ioc_fm_exceptions*)arg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_ForceIntr(p_LnxWrpFmDev->h_Dev, (e_FmExceptions)param); ++ break; ++ } ++ ++ case FM_IOC_GET_API_VERSION: ++ { ++ ioc_fm_api_version_t version; ++ ++ FM_Get_Api_Version(&version); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_to_user( ++ (ioc_fm_api_version_t *)compat_ptr(arg), ++ &version, sizeof(version))) ++ err = E_READ_FAILED; ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_api_version_t *)arg, ++ &version, sizeof(version))) ++ err = E_READ_FAILED; ++ } ++ } ++ break; ++ ++ case FM_IOC_CTRL_MON_START: ++ { ++ FM_CtrlMonStart(p_LnxWrpFmDev->h_Dev); ++ } ++ break; ++ ++ case FM_IOC_CTRL_MON_STOP: ++ { ++ FM_CtrlMonStop(p_LnxWrpFmDev->h_Dev); ++ } ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_CTRL_MON_GET_COUNTERS_COMPAT: ++#endif ++ case FM_IOC_CTRL_MON_GET_COUNTERS: ++ { ++ ioc_fm_ctrl_mon_counters_params_t param; ++ t_FmCtrlMon mon; ++ ++#if defined(CONFIG_COMPAT) ++ ioc_compat_fm_ctrl_mon_counters_params_t compat_param; ++ ++ if (compat) ++ { ++ if (copy_from_user(&compat_param, (void *)compat_ptr(arg), ++ sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ param.fm_ctrl_index = compat_param.fm_ctrl_index; ++ param.p_mon = (fm_ctrl_mon_t *)compat_ptr(compat_param.p_mon); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(¶m, (void *)arg, sizeof(ioc_fm_counters_params_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ if (FM_CtrlMonGetCounters(p_LnxWrpFmDev->h_Dev, param.fm_ctrl_index, &mon)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (copy_to_user(param.p_mon, &mon, sizeof(t_FmCtrlMon))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ break; ++ ++ default: ++ return LnxwrpFmPcdIOCTL(p_LnxWrpFmDev, cmd, arg, compat); ++ } ++ ++ if (err) ++ RETURN_ERROR(MINOR, E_INVALID_OPERATION, ("IOCTL FM")); ++ ++ return E_OK; ++} ++ ++t_Error LnxwrpFmPortIOCTL(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev, unsigned int cmd, unsigned long arg, bool compat) ++{ ++ t_Error err = E_OK; ++ ++ _fm_ioctl_dbg("cmd:0x%08x(type:0x%02x, nr:%u).\n", ++ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd) - 50); ++ ++ switch (cmd) ++ { ++ case FM_PORT_IOC_DISABLE: ++ FM_PORT_Disable(p_LnxWrpFmPortDev->h_Dev); ++ /* deliberately ignoring error codes here */ ++ return E_OK; ++ ++ case FM_PORT_IOC_ENABLE: ++ FM_PORT_Enable(p_LnxWrpFmPortDev->h_Dev); ++ /* deliberately ignoring error codes here */ ++ return E_OK; ++ ++ case FM_PORT_IOC_SET_ERRORS_ROUTE: ++ { ++ ioc_fm_port_frame_err_select_t errs; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (get_user(errs, (ioc_fm_port_frame_err_select_t*)compat_ptr(arg))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ { ++ if (get_user(errs, (ioc_fm_port_frame_err_select_t*)arg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PORT_SetErrorsRoute(p_LnxWrpFmPortDev->h_Dev, (fmPortFrameErrSelect_t)errs); ++ break; ++ } ++ ++ case FM_PORT_IOC_SET_RATE_LIMIT: ++ { ++ ioc_fm_port_rate_limit_t *param; ++ ++ param = (ioc_fm_port_rate_limit_t *) XX_Malloc(sizeof(ioc_fm_port_rate_limit_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_port_rate_limit_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_port_rate_limit_t *)compat_ptr(arg), sizeof(ioc_fm_port_rate_limit_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_port_rate_limit_t *)arg, sizeof(ioc_fm_port_rate_limit_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PORT_SetRateLimit(p_LnxWrpFmPortDev->h_Dev, (t_FmPortRateLimit *)param); ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PORT_IOC_REMOVE_RATE_LIMIT: ++ FM_PORT_DeleteRateLimit(p_LnxWrpFmPortDev->h_Dev); ++ /* deliberately ignoring error codes here */ ++ return E_OK; ++ ++ case FM_PORT_IOC_ALLOC_PCD_FQIDS: ++ { ++ ioc_fm_port_pcd_fqids_params_t *param; ++ ++ if (!p_LnxWrpFmPortDev->pcd_owner_params.cba) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("No one to listen on this PCD!!!")); ++ ++ param = (ioc_fm_port_pcd_fqids_params_t *) XX_Malloc(sizeof(ioc_fm_port_pcd_fqids_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_port_pcd_fqids_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_port_pcd_fqids_params_t *)compat_ptr(arg), ++ sizeof(ioc_fm_port_pcd_fqids_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_port_pcd_fqids_params_t *)arg, ++ sizeof(ioc_fm_port_pcd_fqids_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (p_LnxWrpFmPortDev->pcd_owner_params.cba(p_LnxWrpFmPortDev->pcd_owner_params.dev, ++ param->num_fqids, ++ param->alignment, ++ ¶m->base_fqid)) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("can't allocate fqids for PCD!!!")); ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_to_user((ioc_fm_port_pcd_fqids_params_t *)compat_ptr(arg), ++ param, sizeof(ioc_fm_port_pcd_fqids_params_t))) ++ err = E_READ_FAILED; ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_port_pcd_fqids_params_t *)arg, ++ param, sizeof(ioc_fm_port_pcd_fqids_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PORT_IOC_FREE_PCD_FQIDS: ++ { ++ uint32_t base_fqid; ++ ++ if (!p_LnxWrpFmPortDev->pcd_owner_params.cbf) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("No one to listen on this PCD!!!")); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (get_user(base_fqid, (uint32_t*) compat_ptr(arg))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ { ++ if (get_user(base_fqid, (uint32_t*)arg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ if (p_LnxWrpFmPortDev->pcd_owner_params.cbf(p_LnxWrpFmPortDev->pcd_owner_params.dev, base_fqid)) ++ err = E_WRITE_FAILED; ++ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_SET_PCD_COMPAT: ++#endif ++ case FM_PORT_IOC_SET_PCD: ++ { ++ ioc_fm_port_pcd_params_t *port_pcd_params; ++ ioc_fm_port_pcd_prs_params_t *port_pcd_prs_params; ++ ioc_fm_port_pcd_cc_params_t *port_pcd_cc_params; ++ ioc_fm_port_pcd_kg_params_t *port_pcd_kg_params; ++ ioc_fm_port_pcd_plcr_params_t *port_pcd_plcr_params; ++ ++ port_pcd_params = (ioc_fm_port_pcd_params_t *) XX_Malloc( ++ sizeof(ioc_fm_port_pcd_params_t) + ++ sizeof(ioc_fm_port_pcd_prs_params_t) + ++ sizeof(ioc_fm_port_pcd_cc_params_t) + ++ sizeof(ioc_fm_port_pcd_kg_params_t) + ++ sizeof(ioc_fm_port_pcd_plcr_params_t)); ++ if (!port_pcd_params) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(port_pcd_params, 0, ++ sizeof(ioc_fm_port_pcd_params_t) + ++ sizeof(ioc_fm_port_pcd_prs_params_t) + ++ sizeof(ioc_fm_port_pcd_cc_params_t) + ++ sizeof(ioc_fm_port_pcd_kg_params_t) + ++ sizeof(ioc_fm_port_pcd_plcr_params_t)); ++ ++ port_pcd_prs_params = (ioc_fm_port_pcd_prs_params_t *) (port_pcd_params + 1); ++ port_pcd_cc_params = (ioc_fm_port_pcd_cc_params_t *) (port_pcd_prs_params + 1); ++ port_pcd_kg_params = (ioc_fm_port_pcd_kg_params_t *) (port_pcd_cc_params + 1); ++ port_pcd_plcr_params = (ioc_fm_port_pcd_plcr_params_t *) (port_pcd_kg_params + 1); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_port_pcd_params_t *compat_port_pcd_params; ++ ioc_fm_port_pcd_prs_params_t *same_port_pcd_prs_params; ++ ioc_compat_fm_port_pcd_cc_params_t *compat_port_pcd_cc_params; ++ ioc_compat_fm_port_pcd_kg_params_t *compat_port_pcd_kg_params; ++ ioc_compat_fm_port_pcd_plcr_params_t *compat_port_pcd_plcr_params; ++ ++ compat_port_pcd_params = (ioc_compat_fm_port_pcd_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_port_pcd_params_t) + ++ sizeof(ioc_fm_port_pcd_prs_params_t) + ++ sizeof(ioc_compat_fm_port_pcd_cc_params_t) + ++ sizeof(ioc_compat_fm_port_pcd_kg_params_t) + ++ sizeof(ioc_compat_fm_port_pcd_plcr_params_t)); ++ if (!compat_port_pcd_params) ++ { ++ XX_Free(port_pcd_params); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ } ++ ++ memset(compat_port_pcd_params, 0, ++ sizeof(ioc_compat_fm_port_pcd_params_t) + ++ sizeof(ioc_fm_port_pcd_prs_params_t) + ++ sizeof(ioc_compat_fm_port_pcd_cc_params_t) + ++ sizeof(ioc_compat_fm_port_pcd_kg_params_t) + ++ sizeof(ioc_compat_fm_port_pcd_plcr_params_t)); ++ same_port_pcd_prs_params = (ioc_fm_port_pcd_prs_params_t *) (compat_port_pcd_params + 1); ++ compat_port_pcd_cc_params = (ioc_compat_fm_port_pcd_cc_params_t *) (same_port_pcd_prs_params + 1); ++ compat_port_pcd_kg_params = (ioc_compat_fm_port_pcd_kg_params_t *) (compat_port_pcd_cc_params + 1); ++ compat_port_pcd_plcr_params = (ioc_compat_fm_port_pcd_plcr_params_t *) (compat_port_pcd_kg_params + 1); ++ ++ if (copy_from_user(compat_port_pcd_params, ++ (ioc_compat_fm_port_pcd_params_t*) compat_ptr(arg), ++ sizeof(ioc_compat_fm_port_pcd_params_t))) ++ err = E_WRITE_FAILED; ++ ++ while (!err) /* pseudo-while */ ++ { ++ /* set pointers from where to copy from: */ ++ port_pcd_params->p_prs_params = compat_ptr(compat_port_pcd_params->p_prs_params); /* same structure */ ++ port_pcd_params->p_cc_params = compat_ptr(compat_port_pcd_params->p_cc_params); ++ port_pcd_params->p_kg_params = compat_ptr(compat_port_pcd_params->p_kg_params); ++ port_pcd_params->p_plcr_params = compat_ptr(compat_port_pcd_params->p_plcr_params); ++ port_pcd_params->p_ip_reassembly_manip = compat_ptr(compat_port_pcd_params->p_ip_reassembly_manip); ++ ++ /* the prs member is the same, no compat structure...memcpy only */ ++ if (port_pcd_params->p_prs_params) ++ { ++ if (copy_from_user(same_port_pcd_prs_params, ++ port_pcd_params->p_prs_params, ++ sizeof(ioc_fm_port_pcd_prs_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ memcpy(port_pcd_prs_params, same_port_pcd_prs_params, sizeof(ioc_fm_port_pcd_prs_params_t)); ++ port_pcd_params->p_prs_params = port_pcd_prs_params; ++ } ++ ++ if (port_pcd_params->p_cc_params) ++ { ++ if (copy_from_user(compat_port_pcd_cc_params, ++ port_pcd_params->p_cc_params, ++ sizeof(ioc_compat_fm_port_pcd_cc_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_cc_params = port_pcd_cc_params; ++ } ++ ++ if (port_pcd_params->p_kg_params) ++ { ++ if (copy_from_user(compat_port_pcd_kg_params, ++ port_pcd_params->p_kg_params, ++ sizeof(ioc_compat_fm_port_pcd_kg_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_kg_params = port_pcd_kg_params; ++ } ++ ++ if (port_pcd_params->p_plcr_params) ++ { ++ if (copy_from_user(compat_port_pcd_plcr_params, ++ port_pcd_params->p_plcr_params, ++ sizeof(ioc_compat_fm_port_pcd_plcr_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_plcr_params = port_pcd_plcr_params; ++ } ++ ++ break; /* pseudo-while: always run once! */ ++ } ++ ++ if (!err) ++ compat_copy_fm_port_pcd(compat_port_pcd_params, port_pcd_params, COMPAT_US_TO_K); ++ ++ XX_Free(compat_port_pcd_params); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(port_pcd_params, ++ (ioc_fm_port_pcd_params_t*) arg, ++ sizeof(ioc_fm_port_pcd_params_t))) ++ err = E_WRITE_FAILED; ++ ++ while (!err) /* pseudo-while */ ++ { ++ if (port_pcd_params->p_prs_params) ++ { ++ if (copy_from_user(port_pcd_prs_params, ++ port_pcd_params->p_prs_params, ++ sizeof(ioc_fm_port_pcd_prs_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_prs_params = port_pcd_prs_params; ++ } ++ ++ if (port_pcd_params->p_cc_params) ++ { ++ if (copy_from_user(port_pcd_cc_params, ++ port_pcd_params->p_cc_params, ++ sizeof(ioc_fm_port_pcd_cc_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_cc_params = port_pcd_cc_params; ++ } ++ ++ if (port_pcd_params->p_kg_params) ++ { ++ if (copy_from_user(port_pcd_kg_params, ++ port_pcd_params->p_kg_params, ++ sizeof(ioc_fm_port_pcd_kg_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_kg_params = port_pcd_kg_params; ++ } ++ ++ if (port_pcd_params->p_plcr_params) ++ { ++ if (copy_from_user(port_pcd_plcr_params, ++ port_pcd_params->p_plcr_params, ++ sizeof(ioc_fm_port_pcd_plcr_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_plcr_params = port_pcd_plcr_params; ++ } ++ ++ break; /* pseudo-while: always run once! */ ++ } ++ } ++ ++ if (!err) ++ err = FM_PORT_SetPCD(p_LnxWrpFmPortDev->h_Dev, (t_FmPortPcdParams*) port_pcd_params); ++ ++ XX_Free(port_pcd_params); ++ break; ++ } ++ ++ case FM_PORT_IOC_DELETE_PCD: ++ err = FM_PORT_DeletePCD(p_LnxWrpFmPortDev->h_Dev); ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_PCD_KG_MODIFY_INITIAL_SCHEME_COMPAT: ++#endif ++ case FM_PORT_IOC_PCD_KG_MODIFY_INITIAL_SCHEME: ++ { ++ ioc_fm_pcd_kg_scheme_select_t *param; ++ ++ param = (ioc_fm_pcd_kg_scheme_select_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_kg_scheme_select_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_kg_scheme_select_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_kg_scheme_select_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_kg_scheme_select_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_kg_scheme_select_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_select_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_kg_scheme_select_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_kg_scheme_select_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_kg_scheme_select(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_kg_scheme_select_t *)arg, ++ sizeof(ioc_fm_pcd_kg_scheme_select_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PORT_PcdKgModifyInitialScheme(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdKgSchemeSelect *)param); ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_PCD_PLCR_MODIFY_INITIAL_PROFILE_COMPAT: ++#endif ++ case FM_PORT_IOC_PCD_PLCR_MODIFY_INITIAL_PROFILE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ id.obj = compat_ptr(compat_id.obj); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PORT_PcdPlcrModifyInitialProfile(p_LnxWrpFmPortDev->h_Dev, id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_PCD_KG_BIND_SCHEMES_COMPAT: ++#endif ++ case FM_PORT_IOC_PCD_KG_BIND_SCHEMES: ++ { ++ ioc_fm_pcd_port_schemes_params_t *param; ++ ++ param = (ioc_fm_pcd_port_schemes_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_port_schemes_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0 , sizeof(ioc_fm_pcd_port_schemes_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_port_schemes_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, ++ (ioc_compat_fm_pcd_port_schemes_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_port_schemes_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_kg_schemes_params(&compat_param, param, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_port_schemes_params_t *) arg, ++ sizeof(ioc_fm_pcd_port_schemes_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PORT_PcdKgBindSchemes(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdPortSchemesParams *)param); ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_PCD_KG_UNBIND_SCHEMES_COMPAT: ++#endif ++ case FM_PORT_IOC_PCD_KG_UNBIND_SCHEMES: ++ { ++ ioc_fm_pcd_port_schemes_params_t *param; ++ ++ param = (ioc_fm_pcd_port_schemes_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_port_schemes_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0 , sizeof(ioc_fm_pcd_port_schemes_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_port_schemes_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, ++ (ioc_compat_fm_pcd_port_schemes_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_port_schemes_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_kg_schemes_params(&compat_param, param, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_port_schemes_params_t *) arg, ++ sizeof(ioc_fm_pcd_port_schemes_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PORT_PcdKgUnbindSchemes(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdPortSchemesParams *)param); ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PORT_IOC_PCD_PRS_MODIFY_START_OFFSET: ++ { ++ ioc_fm_pcd_prs_start_t *param; ++ ++ param = (ioc_fm_pcd_prs_start_t *) XX_Malloc(sizeof(ioc_fm_pcd_prs_start_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_prs_start_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_prs_start_t *)compat_ptr(arg), ++ sizeof(ioc_fm_pcd_prs_start_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_prs_start_t *)arg, ++ sizeof(ioc_fm_pcd_prs_start_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PORT_PcdPrsModifyStartOffset(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdPrsStart *)param); ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PORT_IOC_PCD_PLCR_ALLOC_PROFILES: ++ { ++ uint16_t num; ++ if (get_user(num, (uint16_t*) arg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ err = FM_PORT_PcdPlcrAllocProfiles(p_LnxWrpFmPortDev->h_Dev, num); ++ break; ++ } ++ ++ case FM_PORT_IOC_PCD_PLCR_FREE_PROFILES: ++ err = FM_PORT_PcdPlcrFreeProfiles(p_LnxWrpFmPortDev->h_Dev); ++ break; ++ ++ case FM_PORT_IOC_DETACH_PCD: ++ err = FM_PORT_DetachPCD(p_LnxWrpFmPortDev->h_Dev); ++ break; ++ ++ case FM_PORT_IOC_ATTACH_PCD: ++ err = FM_PORT_AttachPCD(p_LnxWrpFmPortDev->h_Dev); ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_PCD_CC_MODIFY_TREE_COMPAT: ++#endif ++ case FM_PORT_IOC_PCD_CC_MODIFY_TREE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_port_pcd_modify_tree(&compat_id, &id, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PORT_PcdCcModifyTree(p_LnxWrpFmPortDev->h_Dev, id.obj); ++ break; ++ } ++ ++ case FM_PORT_IOC_ADD_CONGESTION_GRPS: ++ case FM_PORT_IOC_REMOVE_CONGESTION_GRPS: ++ { ++ ioc_fm_port_congestion_groups_t *param; ++ ++ param = (ioc_fm_port_congestion_groups_t*) XX_Malloc(sizeof(ioc_fm_port_congestion_groups_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_port_congestion_groups_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (t_FmPortCongestionGrps*) compat_ptr(arg), ++ sizeof(t_FmPortCongestionGrps))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif /* CONFIG_COMPAT */ ++ { ++ if (copy_from_user(param, (t_FmPortCongestionGrps*) arg, ++ sizeof(t_FmPortCongestionGrps))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = (cmd == FM_PORT_IOC_ADD_CONGESTION_GRPS) ++ ? FM_PORT_AddCongestionGrps(p_LnxWrpFmPortDev->h_Dev, (t_FmPortCongestionGrps*) param) ++ : FM_PORT_RemoveCongestionGrps(p_LnxWrpFmPortDev->h_Dev, (t_FmPortCongestionGrps*) param) ++ ; ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PORT_IOC_ADD_RX_HASH_MAC_ADDR: ++ case FM_PORT_IOC_REMOVE_RX_HASH_MAC_ADDR: ++ { ++ ioc_fm_port_mac_addr_params_t *param; ++ ++ param = (ioc_fm_port_mac_addr_params_t*) XX_Malloc( ++ sizeof(ioc_fm_port_mac_addr_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_port_mac_addr_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_port_mac_addr_params_t*) compat_ptr(arg), ++ sizeof(ioc_fm_port_mac_addr_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif /* CONFIG_COMPAT */ ++ { ++ if (copy_from_user(param, (ioc_fm_port_mac_addr_params_t*) arg, ++ sizeof(ioc_fm_port_mac_addr_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (p_LnxWrpFmPortDev->pcd_owner_params.dev) ++ { ++ struct net_device *net_dev = dev_get_drvdata(p_LnxWrpFmPortDev->pcd_owner_params.dev); ++ ++ if (net_dev) ++ { ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ ++ if (priv) ++ { ++ struct mac_device *mac_dev = priv->mac_dev; ++ ++ if (mac_dev) ++ { ++ void *mac_handle = mac_dev->get_mac_handle(mac_dev); ++ ++ err = (cmd == FM_PORT_IOC_ADD_RX_HASH_MAC_ADDR) ++ ? FM_MAC_AddHashMacAddr((t_Handle) mac_handle, (t_EnetAddr*) param) ++ : FM_MAC_RemoveHashMacAddr((t_Handle) mac_handle, (t_EnetAddr*) param) ++ ; ++ } ++ else ++ { ++ err = E_NOT_AVAILABLE; ++ REPORT_ERROR(MINOR, err, ("Attempt to add/remove hash MAC addr. to/from MAC-less port!")); ++ } ++ } ++ else ++ /* Not possible, set err nevertheless: */ ++ err = E_NOT_AVAILABLE; ++ } ++ else ++ { ++ err = E_NOT_AVAILABLE; ++ REPORT_ERROR(MINOR, err, ("No net device (and no MAC!) associated to this port!")); ++ } ++ } ++ else ++ { ++ err = E_NOT_AVAILABLE; ++ REPORT_ERROR(MINOR, err, ("Port not initialized or other error!?!?")); ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PORT_IOC_SET_TX_PAUSE_FRAMES: ++ { ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ++ (t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ ioc_fm_port_tx_pause_frames_params_t param; ++ int mac_id = p_LnxWrpFmPortDev->id; ++ ++ if(&p_LnxWrpFmDev->txPorts[mac_id] != p_LnxWrpFmPortDev) ++ mac_id += FM_MAX_NUM_OF_1G_MACS; /* 10G port */ ++ ++ if (copy_from_user(¶m, (ioc_fm_port_tx_pause_frames_params_t *)arg, ++ sizeof(ioc_fm_port_tx_pause_frames_params_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (p_LnxWrpFmDev && p_LnxWrpFmDev->macs[mac_id].h_Dev) ++ { ++ FM_MAC_SetTxPauseFrames(p_LnxWrpFmDev->macs[mac_id].h_Dev, ++ param.priority, ++ param.pause_time, ++ param.thresh_time); ++ } ++ else ++ { ++ err = E_NOT_AVAILABLE; ++ REPORT_ERROR(MINOR, err, ("Port not initialized or other error!")); ++ } ++ ++ break; ++ } ++ ++ case FM_PORT_IOC_CONFIG_BUFFER_PREFIX_CONTENT: ++ { ++ ioc_fm_buffer_prefix_content_t *param; ++ ++ param = (ioc_fm_buffer_prefix_content_t*) XX_Malloc(sizeof(ioc_fm_buffer_prefix_content_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_buffer_prefix_content_t)); ++ ++ if (copy_from_user(param, (ioc_fm_buffer_prefix_content_t*) arg, ++ sizeof(ioc_fm_buffer_prefix_content_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ if (FM_PORT_ConfigBufferPrefixContent(p_LnxWrpFmPortDev->h_Dev, ++ (t_FmBufferPrefixContent *)param)) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if (DPAA_VERSION >= 11) ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_VSP_ALLOC_COMPAT: ++#endif ++ case FM_PORT_IOC_VSP_ALLOC: ++ { ++ ioc_fm_port_vsp_alloc_params_t *param; ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ t_LnxWrpFmPortDev *p_LnxWrpFmTxPortDev; ++ ++ param = (ioc_fm_port_vsp_alloc_params_t *) XX_Malloc( ++ sizeof(ioc_fm_port_vsp_alloc_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_port_vsp_alloc_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_port_vsp_alloc_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_port_vsp_alloc_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_port_vsp_alloc_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_port_vsp_alloc_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_port_vsp_alloc_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_port_vsp_alloc_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_port_vsp_alloc_params(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_port_vsp_alloc_params_t *)arg, ++ sizeof(ioc_fm_port_vsp_alloc_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ /* Userspace may not have the Tx port t_handle when issuing the IOCTL */ ++ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX || ++ p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX_10G) ++ { ++ /* Determine the Tx port t_Handle from the Rx port id */ ++ p_LnxWrpFmDev = p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ p_LnxWrpFmTxPortDev = &p_LnxWrpFmDev->txPorts[p_LnxWrpFmPortDev->id]; ++ param->p_fm_tx_port = p_LnxWrpFmTxPortDev->h_Dev; ++ } ++ ++ if (FM_PORT_VSPAlloc(p_LnxWrpFmPortDev->h_Dev, (t_FmPortVSPAllocParams *)param)) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ XX_Free(param); ++ break; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ case FM_PORT_IOC_GET_MAC_STATISTICS: ++ { ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ++ (t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ ioc_fm_port_mac_statistics_t param; ++ int mac_id = p_LnxWrpFmPortDev->id; ++ ++ if (!p_LnxWrpFmDev) ++ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Port not initialized or other error!")); ++ ++ if (&p_LnxWrpFmDev->txPorts[mac_id] != p_LnxWrpFmPortDev && ++ &p_LnxWrpFmDev->rxPorts[mac_id] != p_LnxWrpFmPortDev) ++ mac_id += FM_MAX_NUM_OF_1G_MACS; /* 10G port */ ++ ++ if (!p_LnxWrpFmDev->macs[mac_id].h_Dev) ++ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Port not initialized or other error!")); ++ ++ if (FM_MAC_GetStatistics(p_LnxWrpFmDev->macs[mac_id].h_Dev, ++ (t_FmMacStatistics *)¶m)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (copy_to_user((ioc_fm_port_mac_statistics_t *)arg, ¶m, ++ sizeof(ioc_fm_port_mac_statistics_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ break; ++ } ++ ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ++ ("invalid ioctl: cmd:0x%08x(type:0x%02x, nr:0x%02x.\n", ++ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd))); ++ } ++ ++ if (err) ++ RETURN_ERROR(MINOR, E_INVALID_OPERATION, ("IOCTL FM PORT")); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++/* API routines for the FM Linux Device */ ++/*****************************************************************************/ ++ ++static int fm_open(struct inode *inode, struct file *file) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL; ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = NULL; ++ unsigned int major = imajor(inode); ++ unsigned int minor = iminor(inode); ++ struct device_node *fm_node; ++ static struct of_device_id fm_node_of_match[] __devinitdata = { ++ { .compatible = "fsl,fman", }, ++ { /* end of list */ }, ++ }; ++ ++ DBG(TRACE, ("Opening minor - %d - ", minor)); ++ ++ if (file->private_data != NULL) ++ return 0; ++ ++ /* Get all the FM nodes */ ++ for_each_matching_node(fm_node, fm_node_of_match) { ++ struct platform_device *of_dev; ++ ++ of_dev = of_find_device_by_node(fm_node); ++ if (unlikely(of_dev == NULL)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!")); ++ return -ENXIO; ++ } ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *)fm_bind(&of_dev->dev); ++ if (p_LnxWrpFmDev->major == major) ++ break; ++ fm_unbind((struct fm *)p_LnxWrpFmDev); ++ p_LnxWrpFmDev = NULL; ++ } ++ ++ if (!p_LnxWrpFmDev) ++ return -ENODEV; ++ ++ if (minor == DEV_FM_MINOR_BASE) ++ file->private_data = p_LnxWrpFmDev; ++ else if (minor == DEV_FM_PCD_MINOR_BASE) ++ file->private_data = p_LnxWrpFmDev; ++ else { ++ if (minor == DEV_FM_OH_PORTS_MINOR_BASE) ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort; ++ else if ((minor > DEV_FM_OH_PORTS_MINOR_BASE) && (minor < DEV_FM_RX_PORTS_MINOR_BASE)) ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->opPorts[minor-DEV_FM_OH_PORTS_MINOR_BASE-1]; ++ else if ((minor >= DEV_FM_RX_PORTS_MINOR_BASE) && (minor < DEV_FM_TX_PORTS_MINOR_BASE)) ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[minor-DEV_FM_RX_PORTS_MINOR_BASE]; ++ else if ((minor >= DEV_FM_TX_PORTS_MINOR_BASE) && (minor < DEV_FM_MAX_MINORS)) ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[minor-DEV_FM_TX_PORTS_MINOR_BASE]; ++ else ++ return -EINVAL; ++ ++ /* if trying to open port, check if it initialized */ ++ if (!p_LnxWrpFmPortDev->h_Dev) ++ return -ENODEV; ++ ++ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)fm_port_bind(p_LnxWrpFmPortDev->dev); ++ file->private_data = p_LnxWrpFmPortDev; ++ fm_unbind((struct fm *)p_LnxWrpFmDev); ++ } ++ ++ if (file->private_data == NULL) ++ return -ENXIO; ++ ++ return 0; ++} ++ ++static int fm_close(struct inode *inode, struct file *file) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev; ++ unsigned int minor = iminor(inode); ++ int err = 0; ++ ++ DBG(TRACE, ("Closing minor - %d - ", minor)); ++ ++ if ((minor == DEV_FM_MINOR_BASE) || ++ (minor == DEV_FM_PCD_MINOR_BASE)) ++ { ++ p_LnxWrpFmDev = (t_LnxWrpFmDev*)file->private_data; ++ if (!p_LnxWrpFmDev) ++ return -ENODEV; ++ fm_unbind((struct fm *)p_LnxWrpFmDev); ++ } ++ else if (((minor >= DEV_FM_OH_PORTS_MINOR_BASE) && (minor < DEV_FM_RX_PORTS_MINOR_BASE)) || ++ ((minor >= DEV_FM_RX_PORTS_MINOR_BASE) && (minor < DEV_FM_TX_PORTS_MINOR_BASE)) || ++ ((minor >= DEV_FM_TX_PORTS_MINOR_BASE) && (minor < DEV_FM_MAX_MINORS))) ++ { ++ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)file->private_data; ++ if (!p_LnxWrpFmPortDev) ++ return -ENODEV; ++ fm_port_unbind((struct fm_port *)p_LnxWrpFmPortDev); ++ } ++ ++ return err; ++} ++ ++static int fm_ioctls(unsigned int minor, struct file *file, unsigned int cmd, unsigned long arg, bool compat) ++{ ++ DBG(TRACE, ("IOCTL minor - %u, cmd - 0x%08x, arg - 0x%08lx \n", minor, cmd, arg)); ++ ++ if ((minor == DEV_FM_MINOR_BASE) || ++ (minor == DEV_FM_PCD_MINOR_BASE)) ++ { ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ((t_LnxWrpFmDev*)file->private_data); ++ if (!p_LnxWrpFmDev) ++ return -ENODEV; ++ if (LnxwrpFmIOCTL(p_LnxWrpFmDev, cmd, arg, compat)) ++ return -EFAULT; ++ } ++ else if (((minor >= DEV_FM_OH_PORTS_MINOR_BASE) && (minor < DEV_FM_RX_PORTS_MINOR_BASE)) || ++ ((minor >= DEV_FM_RX_PORTS_MINOR_BASE) && (minor < DEV_FM_TX_PORTS_MINOR_BASE)) || ++ ((minor >= DEV_FM_TX_PORTS_MINOR_BASE) && (minor < DEV_FM_MAX_MINORS))) ++ { ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = ((t_LnxWrpFmPortDev*)file->private_data); ++ if (!p_LnxWrpFmPortDev) ++ return -ENODEV; ++ if (LnxwrpFmPortIOCTL(p_LnxWrpFmPortDev, cmd, arg, compat)) ++ return -EFAULT; ++ } ++ else ++ { ++ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("minor")); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++#ifdef CONFIG_COMPAT ++static long fm_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ unsigned int minor = iminor(file->f_path.dentry->d_inode); ++ long res; ++ ++ fm_mutex_lock(); ++ res = fm_ioctls(minor, file, cmd, arg, true); ++ fm_mutex_unlock(); ++ ++ return res; ++} ++#endif ++ ++static long fm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ unsigned int minor = iminor(file->f_path.dentry->d_inode); ++ long res; ++ ++ fm_mutex_lock(); ++ res = fm_ioctls(minor, file, cmd, arg, false); ++ fm_mutex_unlock(); ++ ++ return res; ++} ++ ++/* Globals for FM character device */ ++struct file_operations fm_fops = ++{ ++ .owner = THIS_MODULE, ++ .unlocked_ioctl = fm_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = fm_compat_ioctl, ++#endif ++ .open = fm_open, ++ .release = fm_close, ++}; +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_ioctls_fm_compat.c b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_ioctls_fm_compat.c +new file mode 100644 +index 0000000..c4c6a35 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_ioctls_fm_compat.c +@@ -0,0 +1,1213 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_fm_compat_ioctls.c ++ ++ @Description FM PCD compat functions ++ ++*/ ++ ++#if !defined(CONFIG_COMPAT) ++#error "missing COMPAT layer..." ++#endif ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "part_ext.h" ++#include "fm_ioctls.h" ++#include "fm_pcd_ioctls.h" ++#include "fm_port_ioctls.h" ++#include "lnxwrp_ioctls_fm_compat.h" ++ ++#if defined(FM_COMPAT_DBG) ++static void hex_dump(void * p_addr, unsigned int size) ++{ ++ int i; ++ ++ for(i=0; i\n", p); ++ ++ if(!p) ++ return 0; ++ ++ for(k=1; k < COMPAT_PTR2ID_ARRAY_MAX; k++) ++ if(compat_ptr2id_array[k].ptr == NULL) ++ { ++ compat_ptr2id_array[k].ptr = p; ++ compat_ptr2id_array[k].node_type = node_type; ++ _fm_cpt_dbg(COMPAT_GENERIC, "0x%08x \n", k | COMPAT_PTR2ID_WATERMARK); ++ return k | COMPAT_PTR2ID_WATERMARK; ++ } ++ ++ printk(KERN_WARNING "FMan map list full! No more PCD space on kernel!\n"); ++ return 0; ++} ++EXPORT_SYMBOL(compat_add_ptr2id); ++ ++compat_uptr_t compat_get_ptr2id(void *p, enum fm_map_node_type node_type) ++{ ++ compat_uptr_t k; ++ ++ _fm_cpt_dbg(COMPAT_GENERIC, " (%p) get -> \n", p); ++ ++ for(k=1; k < COMPAT_PTR2ID_ARRAY_MAX; k++) ++ if(compat_ptr2id_array[k].ptr == p && ++ compat_ptr2id_array[k].node_type == node_type) { ++ ++ _fm_cpt_dbg(COMPAT_GENERIC, "0x%08x\n", k | COMPAT_PTR2ID_WATERMARK); ++ return k | COMPAT_PTR2ID_WATERMARK; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(compat_get_ptr2id); ++ ++void *compat_get_id2ptr(compat_uptr_t comp, enum fm_map_node_type node_type) ++{ ++ ++ _fm_cpt_dbg(COMPAT_GENERIC, " (0x%08x) get -> \n", comp); ++ ++ if((COMPAT_PTR2ID_WM_MASK & comp) != COMPAT_PTR2ID_WATERMARK) { ++ _fm_cpt_dbg(COMPAT_GENERIC, "Error, invalid watermark (0x%08x)!\n\n", comp); ++ dump_stack(); ++ return compat_ptr(comp); ++ } ++ ++ comp &= ~COMPAT_PTR2ID_WM_MASK; ++ ++ if(((0 < comp) && (comp < COMPAT_PTR2ID_ARRAY_MAX) && (compat_ptr2id_array[comp].ptr != NULL) ++ && compat_ptr2id_array[comp].node_type == node_type)) { ++ _fm_cpt_dbg(COMPAT_GENERIC, "%p\n", compat_ptr2id_array[comp].ptr); ++ return compat_ptr2id_array[comp].ptr; ++ } ++ return NULL; ++} ++EXPORT_SYMBOL(compat_get_id2ptr); ++/* } maping kernel pointers w/ UserSpace id's */ ++ ++void compat_obj_delete( ++ ioc_compat_fm_obj_t *compat_id, ++ ioc_fm_obj_t *id) ++{ ++ id->obj = compat_pcd_id2ptr(compat_id->obj); ++ compat_del_ptr2id(id->obj, FM_MAP_TYPE_PCD_NODE); ++} ++ ++static inline void compat_copy_fm_pcd_plcr_next_engine( ++ ioc_compat_fm_pcd_plcr_next_engine_params_u *compat_param, ++ ioc_fm_pcd_plcr_next_engine_params_u *param, ++ ioc_fm_pcd_engine next_engine, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ switch (next_engine) ++ { ++ case e_IOC_FM_PCD_PLCR: ++ if (compat == COMPAT_US_TO_K) ++ param->p_profile = compat_pcd_id2ptr(compat_param->p_profile); ++ else ++ compat_param->p_profile = compat_pcd_ptr2id(param->p_profile); ++ break; ++ case e_IOC_FM_PCD_KG: ++ if (compat == COMPAT_US_TO_K) ++ param->p_direct_scheme = compat_pcd_id2ptr(compat_param->p_direct_scheme); ++ else ++ compat_param->p_direct_scheme = compat_pcd_ptr2id(param->p_direct_scheme); ++ break; ++ default: ++ if (compat == COMPAT_US_TO_K) ++ param->action = compat_param->action; ++ else ++ compat_param->action = param->action; ++ break; ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_plcr_profile( ++ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param, ++ ioc_fm_pcd_plcr_profile_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->modify = compat_param->modify; ++ ++ /* profile_select */ ++ if (!compat_param->modify) ++ { ++ param->profile_select.new_params.profile_type = ++ compat_param->profile_select.new_params.profile_type; ++ param->profile_select.new_params.p_fm_port = ++ compat_ptr(compat_param->profile_select.new_params.p_fm_port); ++ param->profile_select.new_params.relative_profile_id = ++ compat_param->profile_select.new_params.relative_profile_id; ++ } ++ else ++ param->profile_select.p_profile = ++ compat_pcd_id2ptr(compat_param->profile_select.p_profile); ++ ++ param->alg_selection = compat_param->alg_selection; ++ param->color_mode = compat_param->color_mode; ++ ++ /* both parameters in the union has the same size, so memcpy works */ ++ memcpy(¶m->color, &compat_param->color, sizeof(param->color)); ++ ++ memcpy(¶m->non_passthrough_alg_param, ++ &compat_param->non_passthrough_alg_param, ++ sizeof(ioc_fm_pcd_plcr_non_passthrough_alg_param_t)); ++ ++ param->next_engine_on_green = compat_param->next_engine_on_green; ++ param->next_engine_on_yellow = compat_param->next_engine_on_yellow; ++ param->next_engine_on_red = compat_param->next_engine_on_red; ++ ++ param->trap_profile_on_flow_A = compat_param->trap_profile_on_flow_A; ++ param->trap_profile_on_flow_B = compat_param->trap_profile_on_flow_B; ++ param->trap_profile_on_flow_C = compat_param->trap_profile_on_flow_C; ++ } ++ else ++ { ++ compat_param->modify = param->modify; ++ ++ /* profile_select */ ++ if (!param->modify) ++ { ++ compat_param->profile_select.new_params.profile_type = ++ param->profile_select.new_params.profile_type; ++ compat_param->profile_select.new_params.p_fm_port = ++ ptr_to_compat(param->profile_select.new_params.p_fm_port); ++ compat_param->profile_select.new_params.relative_profile_id = ++ param->profile_select.new_params.relative_profile_id; ++ } ++ else ++ compat_param->profile_select.p_profile = ++ compat_pcd_ptr2id(param->profile_select.p_profile); ++ ++ compat_param->alg_selection = param->alg_selection; ++ compat_param->color_mode = param->color_mode; ++ ++ /* both parameters in the union has the same size, so memcpy works */ ++ memcpy(&compat_param->color, ¶m->color, sizeof(compat_param->color)); ++ ++ memcpy(&compat_param->non_passthrough_alg_param, ++ ¶m->non_passthrough_alg_param, ++ sizeof(ioc_fm_pcd_plcr_non_passthrough_alg_param_t)); ++ ++ compat_param->next_engine_on_green = param->next_engine_on_green; ++ compat_param->next_engine_on_yellow = param->next_engine_on_yellow; ++ compat_param->next_engine_on_red = param->next_engine_on_red; ++ ++ compat_param->trap_profile_on_flow_A = param->trap_profile_on_flow_A; ++ compat_param->trap_profile_on_flow_B = param->trap_profile_on_flow_B; ++ compat_param->trap_profile_on_flow_C = param->trap_profile_on_flow_C; ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++ ++ compat_copy_fm_pcd_plcr_next_engine(&compat_param->params_on_green, ++ ¶m->params_on_green, param->next_engine_on_green, compat); ++ ++ compat_copy_fm_pcd_plcr_next_engine(&compat_param->params_on_yellow, ++ ¶m->params_on_yellow, param->next_engine_on_yellow, compat); ++ ++ compat_copy_fm_pcd_plcr_next_engine(&compat_param->params_on_red, ++ ¶m->params_on_red, param->next_engine_on_red, compat); ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++static inline void compat_copy_fm_pcd_cc_next_kg( ++ ioc_compat_fm_pcd_cc_next_kg_params_t *compat_param, ++ ioc_fm_pcd_cc_next_kg_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->new_fqid = compat_param->new_fqid; ++ param->override_fqid = compat_param->override_fqid; ++ param->p_direct_scheme = compat_pcd_id2ptr(compat_param->p_direct_scheme); ++ } ++ else ++ { ++ compat_param->new_fqid = param->new_fqid; ++ compat_param->override_fqid = param->override_fqid; ++ compat_param->p_direct_scheme = compat_pcd_ptr2id(param->p_direct_scheme); ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++static inline void compat_copy_fm_pcd_cc_next_cc( ++ ioc_compat_fm_pcd_cc_next_cc_params_t *compat_param, ++ ioc_fm_pcd_cc_next_cc_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ param->cc_node_id = compat_pcd_id2ptr(compat_param->cc_node_id); ++ else ++ compat_param->cc_node_id = compat_pcd_ptr2id(param->cc_node_id); ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++static inline void compat_copy_fm_pcd_cc_next_engine( ++ ioc_compat_fm_pcd_cc_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_next_engine_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->next_engine = compat_param->next_engine; ++ if (param->next_engine != e_IOC_FM_PCD_INVALID ) ++ _fm_cpt_dbg(compat, " param->next_engine = %i \n", param->next_engine); ++ ++ switch (param->next_engine) ++ { ++#if DPAA_VERSION >= 11 ++ case e_IOC_FM_PCD_FR: ++ param->params.fr_params.frm_replic_id = compat_pcd_id2ptr(compat_param->params.fr_params.frm_replic_id); ++ break; ++#endif /* DPAA_VERSION >= 11 */ ++ case e_IOC_FM_PCD_CC: ++ compat_copy_fm_pcd_cc_next_cc(&compat_param->params.cc_params, ¶m->params.cc_params, compat); ++ break; ++ case e_IOC_FM_PCD_KG: ++ param->manip_id = compat_pcd_id2ptr(compat_param->manip_id); ++ compat_copy_fm_pcd_cc_next_kg(&compat_param->params.kg_params, ¶m->params.kg_params, compat); ++ break; ++ case e_IOC_FM_PCD_DONE: ++ case e_IOC_FM_PCD_PLCR: ++ param->manip_id = compat_pcd_id2ptr(compat_param->manip_id); ++ default: ++ memcpy(¶m->params, &compat_param->params, sizeof(param->params)); ++ } ++ param->statistics_en = compat_param->statistics_en; ++ } ++ else ++ { ++ compat_param->next_engine = param->next_engine; ++ ++ switch (compat_param->next_engine) ++ { ++#if DPAA_VERSION >= 11 ++ case e_IOC_FM_PCD_FR: ++ compat_param->params.fr_params.frm_replic_id = compat_pcd_ptr2id(param->params.fr_params.frm_replic_id); ++ break; ++#endif /* DPAA_VERSION >= 11 */ ++ case e_IOC_FM_PCD_CC: ++ compat_copy_fm_pcd_cc_next_cc(&compat_param->params.cc_params, ¶m->params.cc_params, compat); ++ break; ++ case e_IOC_FM_PCD_KG: ++ compat_param->manip_id = compat_pcd_ptr2id(param->manip_id); ++ compat_copy_fm_pcd_cc_next_kg(&compat_param->params.kg_params, ¶m->params.kg_params, compat); ++ break; ++ case e_IOC_FM_PCD_DONE: ++ case e_IOC_FM_PCD_PLCR: ++ compat_param->manip_id = compat_pcd_ptr2id(param->manip_id); ++ default: ++ memcpy(&compat_param->params, ¶m->params, sizeof(compat_param->params)); ++ } ++ compat_param->statistics_en = param->statistics_en; ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_cc_key( ++ ioc_compat_fm_pcd_cc_key_params_t *compat_param, ++ ioc_fm_pcd_cc_key_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->p_key = compat_ptr(compat_param->p_key); ++ param->p_mask = compat_ptr(compat_param->p_mask); ++ } ++ else ++ { ++ compat_param->p_key = ptr_to_compat(param->p_key); ++ compat_param->p_mask = ptr_to_compat(param->p_mask); ++ } ++ ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->cc_next_engine_params, ++ ¶m->cc_next_engine_params, ++ compat); ++} ++ ++void compat_copy_fm_pcd_cc_node_modify_key_and_next_engine( ++ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ param->key_indx = compat_param->key_indx; ++ param->key_size = compat_param->key_size; ++ compat_copy_fm_pcd_cc_key( ++ &compat_param->key_params, ++ ¶m->key_params, ++ compat); ++ } ++ else ++ { ++ compat_param->id = compat_pcd_ptr2id(param->id); ++ compat_param->key_indx = param->key_indx; ++ compat_param->key_size = param->key_size; ++ compat_copy_fm_pcd_cc_key( ++ &compat_param->key_params, ++ ¶m->key_params, ++ compat); ++ } ++} ++ ++void compat_copy_fm_pcd_cc_node_modify_next_engine( ++ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ param->key_indx = compat_param->key_indx; ++ param->key_size = compat_param->key_size; ++ } ++ else ++ { ++ compat_param->id = compat_pcd_ptr2id(param->id); ++ compat_param->key_indx = param->key_indx; ++ compat_param->key_size = param->key_size; ++ } ++ ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->cc_next_engine_params, ++ ¶m->cc_next_engine_params, ++ compat); ++} ++ ++void compat_fm_pcd_cc_tree_modify_next_engine( ++ ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_tree_modify_next_engine_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ param->grp_indx = compat_param->grp_indx; ++ param->indx = compat_param->indx; ++ } ++ else ++ { ++ compat_param->id = compat_pcd_ptr2id(param->id); ++ compat_param->grp_indx = param->grp_indx; ++ compat_param->indx = param->indx; ++ } ++ ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->cc_next_engine_params, ++ ¶m->cc_next_engine_params, ++ compat); ++} ++ ++void compat_copy_fm_pcd_hash_table( ++ ioc_compat_fm_pcd_hash_table_params_t *compat_param, ++ ioc_fm_pcd_hash_table_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param-> max_num_of_keys = compat_param->max_num_of_keys; ++ param->statistics_mode = compat_param->statistics_mode; ++ param->hash_res_mask = compat_param->hash_res_mask; ++ param->hash_shift = compat_param->hash_shift; ++ param->match_key_size = compat_param->match_key_size; ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ } ++ else ++ { ++ compat_param-> max_num_of_keys = param->max_num_of_keys; ++ compat_param->statistics_mode = param->statistics_mode; ++ compat_param->hash_res_mask = param->hash_res_mask; ++ compat_param->hash_shift = param->hash_shift; ++ compat_param->match_key_size = param->match_key_size; ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++ ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->cc_next_engine_params_for_miss, ++ ¶m->cc_next_engine_params_for_miss, ++ compat); ++} ++ ++void compat_copy_fm_pcd_cc_grp( ++ ioc_compat_fm_pcd_cc_grp_params_t *compat_param, ++ ioc_fm_pcd_cc_grp_params_t *param, ++ uint8_t compat) ++{ ++ int k; ++ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->num_of_distinction_units = compat_param->num_of_distinction_units; ++ memcpy(param->unit_ids, compat_param->unit_ids, IOC_FM_PCD_MAX_NUM_OF_CC_UNITS); ++ } ++ else ++ { ++ compat_param->num_of_distinction_units = param->num_of_distinction_units; ++ memcpy(compat_param->unit_ids, param->unit_ids, IOC_FM_PCD_MAX_NUM_OF_CC_UNITS); ++ } ++ ++ for (k=0; k < IOC_FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP; k++) ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->next_engine_per_entries_in_grp[k], ++ ¶m->next_engine_per_entries_in_grp[k], ++ compat); ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_cc_tree( ++ ioc_compat_fm_pcd_cc_tree_params_t *compat_param, ++ ioc_fm_pcd_cc_tree_params_t *param, ++ uint8_t compat) ++{ ++ int k; ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->net_env_id = compat_pcd_id2ptr(compat_param->net_env_id); ++ param->num_of_groups = compat_param->num_of_groups; ++ } ++ else ++ { ++ compat_param->net_env_id = compat_pcd_ptr2id(param->net_env_id); ++ compat_param->num_of_groups = param->num_of_groups; ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++ ++ for (k=0; k < IOC_FM_PCD_MAX_NUM_OF_CC_GROUPS; k++) ++ compat_copy_fm_pcd_cc_grp( ++ &compat_param->fm_pcd_cc_group_params[k], ++ ¶m->fm_pcd_cc_group_params[k], ++ compat); ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_fm_pcd_prs_sw( ++ ioc_compat_fm_pcd_prs_sw_params_t *compat_param, ++ ioc_fm_pcd_prs_sw_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->override = compat_param->override; ++ param->size = compat_param->size; ++ param->base = compat_param->base; ++ param->p_code = compat_ptr(compat_param->p_code); ++ memcpy(param->sw_prs_data_params,compat_param->sw_prs_data_params,IOC_FM_PCD_PRS_NUM_OF_HDRS*sizeof(uint32_t)); ++ param->num_of_labels = compat_param->num_of_labels; ++ memcpy(param->labels_table,compat_param->labels_table,IOC_FM_PCD_PRS_NUM_OF_LABELS*sizeof(ioc_fm_pcd_prs_label_params_t)); ++ } ++} ++ ++void compat_copy_fm_pcd_kg_scheme( ++ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param, ++ ioc_fm_pcd_kg_scheme_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg(compat," {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->modify = compat_param->modify; ++ ++ /* scm_id */ ++ if (compat_param->modify) ++ { ++ param->scm_id.scheme_id = compat_pcd_id2ptr(compat_param->scm_id.scheme_id); ++ _fm_cpt_dbg(compat," param->scm_id.scheme_id = %p \n", param->scm_id.scheme_id); ++ } ++ else ++ param->scm_id.relative_scheme_id = compat_param->scm_id.relative_scheme_id; ++ ++ param->always_direct = compat_param->always_direct; ++ /* net_env_params */ ++ param->net_env_params.net_env_id = compat_pcd_id2ptr(compat_param->net_env_params.net_env_id); ++ param->net_env_params.num_of_distinction_units = compat_param->net_env_params.num_of_distinction_units; ++ memcpy(param->net_env_params.unit_ids, ++ compat_param->net_env_params.unit_ids, ++ IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ ++ param->use_hash = compat_param->use_hash; ++ memcpy(¶m->key_extract_and_hash_params, ++ &compat_param->key_extract_and_hash_params, ++ sizeof(ioc_fm_pcd_kg_key_extract_and_hash_params_t)); ++ param->bypass_fqid_generation = compat_param->bypass_fqid_generation; ++ param->base_fqid = compat_param->base_fqid; ++ param->num_of_used_extracted_ors = compat_param->num_of_used_extracted_ors; ++ memcpy(param->extracted_ors, ++ compat_param->extracted_ors, ++ IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS * sizeof(ioc_fm_pcd_kg_extracted_or_params_t)); ++ param->next_engine = compat_param->next_engine; ++ ++ /* kg_next_engine_params */ ++ if (param->next_engine == e_IOC_FM_PCD_CC) ++ { ++ param->kg_next_engine_params.cc.tree_id = compat_pcd_id2ptr(compat_param->kg_next_engine_params.cc.tree_id); ++ param->kg_next_engine_params.cc.grp_id = compat_param->kg_next_engine_params.cc.grp_id; ++ param->kg_next_engine_params.cc.plcr_next = compat_param->kg_next_engine_params.cc.plcr_next; ++ param->kg_next_engine_params.cc.bypass_plcr_profile_generation ++ = compat_param->kg_next_engine_params.cc.bypass_plcr_profile_generation; ++ memcpy(¶m->kg_next_engine_params.cc.plcr_profile, ++ &compat_param->kg_next_engine_params.cc.plcr_profile, ++ sizeof(ioc_fm_pcd_kg_plcr_profile_t)); ++ } ++ else ++ memcpy(¶m->kg_next_engine_params, ++ &compat_param->kg_next_engine_params, ++ sizeof(param->kg_next_engine_params)); ++ ++ memcpy(¶m->scheme_counter, ++ &compat_param->scheme_counter, ++ sizeof(ioc_fm_pcd_kg_scheme_counter_t)); ++ } ++ else ++ { ++ compat_param->modify = param->modify; ++ ++ /* scm_id */ ++ if (param->modify) ++ compat_param->scm_id.scheme_id = compat_pcd_ptr2id(param->scm_id.scheme_id); ++ else ++ compat_param->scm_id.relative_scheme_id = param->scm_id.relative_scheme_id; ++ ++ compat_param->always_direct = param->always_direct; ++ ++ /* net_env_params */ ++ compat_param->net_env_params.net_env_id = compat_pcd_ptr2id(param->net_env_params.net_env_id); ++ compat_param->net_env_params.num_of_distinction_units = param->net_env_params.num_of_distinction_units; ++ memcpy(compat_param->net_env_params.unit_ids, param->net_env_params.unit_ids, IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ ++ compat_param->use_hash = param->use_hash; ++ memcpy(&compat_param->key_extract_and_hash_params, ¶m->key_extract_and_hash_params, sizeof(ioc_fm_pcd_kg_key_extract_and_hash_params_t)); ++ compat_param->bypass_fqid_generation = param->bypass_fqid_generation; ++ compat_param->base_fqid = param->base_fqid; ++ compat_param->num_of_used_extracted_ors = param->num_of_used_extracted_ors; ++ memcpy(compat_param->extracted_ors, param->extracted_ors, IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS * sizeof(ioc_fm_pcd_kg_extracted_or_params_t)); ++ compat_param->next_engine = param->next_engine; ++ ++ /* kg_next_engine_params */ ++ if (compat_param->next_engine == e_IOC_FM_PCD_CC) ++ { ++ compat_param->kg_next_engine_params.cc.tree_id = compat_pcd_ptr2id(param->kg_next_engine_params.cc.tree_id); ++ compat_param->kg_next_engine_params.cc.grp_id = param->kg_next_engine_params.cc.grp_id; ++ compat_param->kg_next_engine_params.cc.plcr_next = param->kg_next_engine_params.cc.plcr_next; ++ compat_param->kg_next_engine_params.cc.bypass_plcr_profile_generation ++ = param->kg_next_engine_params.cc.bypass_plcr_profile_generation; ++ memcpy(&compat_param->kg_next_engine_params.cc.plcr_profile, ++ ¶m->kg_next_engine_params.cc.plcr_profile, ++ sizeof(ioc_fm_pcd_kg_plcr_profile_t)); ++ } ++ else ++ memcpy(¶m->kg_next_engine_params, &compat_param->kg_next_engine_params, sizeof(compat_param->kg_next_engine_params)); ++ ++ memcpy(&compat_param->scheme_counter, ¶m->scheme_counter, sizeof(ioc_fm_pcd_kg_scheme_counter_t)); ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++ ++ _fm_cpt_dbg(compat," ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_kg_scheme_select( ++ ioc_compat_fm_pcd_kg_scheme_select_t *compat_param, ++ ioc_fm_pcd_kg_scheme_select_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->direct = compat_param->direct; ++ if (param->direct) ++ param->scheme_id = compat_pcd_id2ptr(compat_param->scheme_id); ++ } ++} ++ ++void compat_copy_fm_pcd_kg_schemes_params( ++ ioc_compat_fm_pcd_port_schemes_params_t *compat_param, ++ ioc_fm_pcd_port_schemes_params_t *param, ++ uint8_t compat) ++{ ++ int k; ++ ++ if (compat == COMPAT_US_TO_K) { ++ param->num_of_schemes = compat_param->num_of_schemes; ++ for(k=0; k < compat_param->num_of_schemes; k++) ++ param->scheme_ids[k] = compat_pcd_id2ptr(compat_param->scheme_ids[k]); ++ } ++} ++ ++void compat_copy_fm_port_pcd_cc( ++ ioc_compat_fm_port_pcd_cc_params_t *compat_cc_params , ++ ioc_fm_port_pcd_cc_params_t *p_cc_params, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K){ ++ p_cc_params->cc_tree_id = compat_pcd_id2ptr(compat_cc_params->cc_tree_id); ++ } ++} ++ ++void compat_copy_fm_port_pcd_kg( ++ ioc_compat_fm_port_pcd_kg_params_t *compat_param, ++ ioc_fm_port_pcd_kg_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K){ ++ uint8_t k; ++ ++ param->num_of_schemes = compat_param->num_of_schemes; ++ for(k=0; knum_of_schemes; k++) ++ param->scheme_ids[k] = compat_pcd_id2ptr(compat_param->scheme_ids[k]); ++ ++ param->direct_scheme = compat_param->direct_scheme; ++ if (param->direct_scheme) ++ param->direct_scheme_id = compat_pcd_id2ptr(compat_param->direct_scheme_id); ++ } ++} ++ ++void compat_copy_fm_port_pcd( ++ ioc_compat_fm_port_pcd_params_t *compat_param, ++ ioc_fm_port_pcd_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ ioc_fm_port_pcd_prs_params_t *same_port_pcd_prs_params; ++ ioc_compat_fm_port_pcd_cc_params_t *compat_port_pcd_cc_params; ++ ioc_compat_fm_port_pcd_kg_params_t *compat_port_pcd_kg_params; ++ ioc_compat_fm_port_pcd_plcr_params_t *compat_port_pcd_plcr_params; ++ ++ same_port_pcd_prs_params = (ioc_fm_port_pcd_prs_params_t *) (compat_param + 1); ++ compat_port_pcd_cc_params = (ioc_compat_fm_port_pcd_cc_params_t *) (same_port_pcd_prs_params + 1); ++ compat_port_pcd_kg_params = (ioc_compat_fm_port_pcd_kg_params_t *) (compat_port_pcd_cc_params + 1); ++ compat_port_pcd_plcr_params = (ioc_compat_fm_port_pcd_plcr_params_t *) (compat_port_pcd_kg_params + 1); ++ ++ _fm_cpt_dbg(compat,"\n param->p_prs_params=%p \n", param->p_prs_params); ++ _fm_cpt_dbg(compat," param->p_cc_params=%p \n", param->p_cc_params); ++ _fm_cpt_dbg(compat," param->p_kg_params=%p \n", param->p_kg_params); ++ _fm_cpt_dbg(compat," param->p_plcr_params=%p \n", param->p_plcr_params); ++ _fm_cpt_dbg(compat," param->p_ip_reassembly_manip=%p \n", param->p_ip_reassembly_manip); ++ ++ param->pcd_support = compat_param->pcd_support; ++ param->net_env_id = compat_pcd_id2ptr(compat_param->net_env_id); ++ ++ if (param->p_cc_params) ++ compat_copy_fm_port_pcd_cc(compat_port_pcd_cc_params, param->p_cc_params, COMPAT_US_TO_K); ++ if (param->p_kg_params) ++ compat_copy_fm_port_pcd_kg(compat_port_pcd_kg_params, param->p_kg_params, COMPAT_US_TO_K); ++ if (param->p_plcr_params) ++ param->p_plcr_params->plcr_profile_id = compat_pcd_id2ptr(compat_port_pcd_plcr_params->plcr_profile_id); ++ param->p_ip_reassembly_manip = compat_pcd_id2ptr(compat_param->p_ip_reassembly_manip); ++ } ++} ++ ++void compat_copy_fm_port_pcd_modify_tree( ++ ioc_compat_fm_obj_t *compat_id, ++ ioc_fm_obj_t *id, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ id->obj = compat_pcd_id2ptr(compat_id->obj); ++} ++ ++#if (DPAA_VERSION >= 11) ++void compat_copy_fm_port_vsp_alloc_params( ++ ioc_compat_fm_port_vsp_alloc_params_t *compat_param, ++ ioc_fm_port_vsp_alloc_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ _fm_cpt_dbg(compat," param->p_fm_tx_port=%p \n", param->p_fm_tx_port); ++ ++ param->dflt_relative_id = compat_param->dflt_relative_id; ++ param->num_of_profiles = compat_param->num_of_profiles; ++ param->p_fm_tx_port = compat_pcd_id2ptr(compat_param->p_fm_tx_port); ++ } ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++void compat_copy_fm_pcd_net_env( ++ ioc_compat_fm_pcd_net_env_params_t *compat_param, ++ ioc_fm_pcd_net_env_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->num_of_distinction_units = compat_param->num_of_distinction_units; ++ memcpy(param->units, compat_param->units, sizeof(ioc_fm_pcd_distinction_unit_t)*IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ param->id = NULL; /* to avoid passing garbage to the kernel */ ++ } ++ else ++ { ++ compat_param->num_of_distinction_units = param->num_of_distinction_units; ++ memcpy(compat_param->units, param->units, sizeof(ioc_fm_pcd_distinction_unit_t)*IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++} ++ ++void compat_copy_fm_pcd_cc_node_modify_key( ++ ioc_compat_fm_pcd_cc_node_modify_key_params_t *compat_param, ++ ioc_fm_pcd_cc_node_modify_key_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->key_indx = compat_param->key_indx; ++ param->key_size = compat_param->key_size; ++ param->p_key = (uint8_t *)compat_ptr(compat_param->p_key); ++ _fm_cpt_dbg(compat," param->p_key = %p \n", param->p_key); ++ param->p_mask = (uint8_t *)compat_ptr(compat_param->p_mask); ++ _fm_cpt_dbg(compat," param->p_mask = %p\n", param->p_mask); ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ _fm_cpt_dbg(compat," param->id = %p \n", param->id); ++ } ++ else ++ { ++ compat_param->key_indx = param->key_indx; ++ compat_param->key_size = param->key_size; ++ compat_param->p_key = ptr_to_compat((void *)param->p_key); ++ compat_param->p_mask = ptr_to_compat((void *)param->p_mask); ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++} ++ ++void compat_copy_keys( ++ ioc_compat_keys_params_t *compat_param, ++ ioc_keys_params_t *param, ++ uint8_t compat) ++{ ++ int k = 0; ++ ++ _fm_cpt_dbg(compat," {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) { ++ param->max_num_of_keys = compat_param->max_num_of_keys; ++ param->mask_support = compat_param->mask_support; ++ param->statistics_mode = compat_param->statistics_mode; ++ param->num_of_keys = compat_param->num_of_keys; ++ param->key_size = compat_param->key_size; ++#if (DPAA_VERSION >= 11) ++ memcpy(¶m->frame_length_ranges, ++ &compat_param->frame_length_ranges, ++ sizeof(param->frame_length_ranges[0] * ++ IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR)); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ else { ++ compat_param->max_num_of_keys = param->max_num_of_keys; ++ compat_param->mask_support = param->mask_support; ++ compat_param->statistics_mode = param->statistics_mode; ++ compat_param->num_of_keys = param->num_of_keys; ++ compat_param->key_size = param->key_size; ++#if (DPAA_VERSION >= 11) ++ memcpy(&compat_param->frame_length_ranges, ++ ¶m->frame_length_ranges, ++ sizeof(compat_param->frame_length_ranges[0] * ++ IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR)); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ for (k=0; k < IOC_FM_PCD_MAX_NUM_OF_KEYS; k++) ++ compat_copy_fm_pcd_cc_key( ++ &compat_param->key_params[k], ++ ¶m->key_params[k], ++ compat); ++ ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->cc_next_engine_params_for_miss, ++ ¶m->cc_next_engine_params_for_miss, ++ compat); ++ ++ _fm_cpt_dbg(compat," ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_cc_node( ++ ioc_compat_fm_pcd_cc_node_params_t *compat_param, ++ ioc_fm_pcd_cc_node_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg(compat," {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ memcpy(¶m->extract_cc_params, &compat_param->extract_cc_params, sizeof(ioc_fm_pcd_extract_entry_t)); ++ ++ else ++ { ++ compat_copy_keys(&compat_param->keys_params, ¶m->keys_params, compat); ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ _fm_cpt_dbg(compat," param->id = %p \n", param->id); ++ } ++ ++ compat_copy_keys(&compat_param->keys_params, ¶m->keys_params, compat); ++ ++ _fm_cpt_dbg(compat," ...->}\n"); ++} ++ ++void compat_fm_pcd_manip_set_node( ++ ioc_compat_fm_pcd_manip_params_t *compat_param, ++ ioc_fm_pcd_manip_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) { ++ param->type = compat_param->type; ++ switch (param->type) { ++ case e_IOC_FM_PCD_MANIP_HDR: ++ param->u.hdr.rmv = compat_param->u.hdr.rmv; ++ memcpy(¶m->u.hdr.rmv_params, ++ &compat_param->u.hdr.rmv_params, ++ sizeof(param->u.hdr.rmv_params)); ++ ++ param->u.hdr.insrt = compat_param->u.hdr.insrt; ++ param->u.hdr.insrt_params.type = ++ compat_param->u.hdr.insrt_params.type; ++ switch (compat_param->u.hdr.insrt_params.type) ++ { ++ case e_IOC_FM_PCD_MANIP_INSRT_GENERIC: ++ param->u.hdr.insrt_params.u.generic.offset = ++ compat_param->u.hdr.insrt_params.u.generic.offset; ++ param->u.hdr.insrt_params.u.generic.size = ++ compat_param->u.hdr.insrt_params.u.generic.size; ++ param->u.hdr.insrt_params.u.generic.replace = ++ compat_param->u.hdr.insrt_params.u.generic.replace; ++ param->u.hdr.insrt_params.u.generic.p_data = ++ compat_ptr(compat_param->u.hdr.insrt_params.u.generic.p_data); ++ break; ++ case e_IOC_FM_PCD_MANIP_INSRT_BY_HDR: ++ param->u.hdr.insrt_params.u.by_hdr.type = ++ compat_param->u.hdr.insrt_params.u.by_hdr.type; ++ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.specific_l2 = ++ compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.specific_l2; ++ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.update = ++ compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.update; ++ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.size = ++ compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.size; ++ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.p_data = ++ compat_ptr(compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.p_data); ++ break; ++ default: ++ _fm_cpt_err("Unsupported type: %d", compat_param->u.hdr.insrt_params.type); ++ } ++ ++ param->u.hdr.field_update = compat_param->u.hdr.field_update; ++ memcpy(¶m->u.hdr.field_update_params, ++ &compat_param->u.hdr.field_update_params, ++ sizeof(param->u.hdr.field_update_params)); ++ ++ param->u.hdr.custom = compat_param->u.hdr.custom; ++ memcpy(¶m->u.hdr.custom_params, ++ &compat_param->u.hdr.custom_params, ++ sizeof(param->u.hdr.custom_params)); ++ ++ param->u.hdr.dont_parse_after_manip = ++ compat_param->u.hdr.dont_parse_after_manip; ++ break; ++ case e_IOC_FM_PCD_MANIP_REASSEM: ++ memcpy(¶m->u.reassem, &compat_param->u.reassem, sizeof(param->u.reassem)); ++ break; ++ case e_IOC_FM_PCD_MANIP_FRAG: ++ memcpy(¶m->u.frag, &compat_param->u.frag, sizeof(param->u.frag)); ++ break; ++ case e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD: ++ param->u.special_offload = compat_param->u.special_offload; ++ break; ++ } ++ ++ param->p_next_manip = compat_pcd_id2ptr(compat_param->p_next_manip); ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ } ++ else { ++ compat_param->type = param->type; ++ memcpy(&compat_param->u, ¶m->u, sizeof(compat_param->u)); ++ ++ if (param->type == e_IOC_FM_PCD_MANIP_HDR && ++ param->u.hdr.insrt_params.type == e_IOC_FM_PCD_MANIP_INSRT_GENERIC) ++ compat_param->u.hdr.insrt_params.u.generic.p_data = ++ ptr_to_compat(param->u.hdr.insrt_params.u.generic.p_data); ++ ++ compat_param->p_next_manip = compat_pcd_ptr2id(param->id); ++ /* ... should be one that was added previously by the very call to ++ compat_add_ptr2id() below: */ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++} ++ ++#if (DPAA_VERSION >= 11) ++void compat_copy_fm_pcd_frm_replic_group_params( ++ ioc_compat_fm_pcd_frm_replic_group_params_t *compat_param, ++ ioc_fm_pcd_frm_replic_group_params_t *param, ++ uint8_t compat) ++{ ++ int k; ++ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->max_num_of_entries = compat_param->max_num_of_entries; ++ param->num_of_entries = compat_param->num_of_entries; ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ } ++ else ++ { ++ compat_param->max_num_of_entries = param->max_num_of_entries; ++ compat_param->num_of_entries = param->num_of_entries; ++ compat_param->id = compat_add_ptr2id(param->id, ++ FM_MAP_TYPE_PCD_NODE); ++ } ++ ++ for (k=0; k < IOC_FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES; k++) ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->next_engine_params[k], ++ ¶m->next_engine_params[k], ++ compat); ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_frm_replic_member( ++ ioc_compat_fm_pcd_frm_replic_member_t *compat_param, ++ ioc_fm_pcd_frm_replic_member_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->h_replic_group = compat_pcd_id2ptr(compat_param->h_replic_group); ++ param->member_index = compat_param->member_index; ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_frm_replic_member_params( ++ ioc_compat_fm_pcd_frm_replic_member_params_t *compat_param, ++ ioc_fm_pcd_frm_replic_member_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ compat_copy_fm_pcd_frm_replic_member(&compat_param->member, ++ ¶m->member, compat); ++ ++ compat_copy_fm_pcd_cc_next_engine(&compat_param->next_engine_params, ++ ¶m->next_engine_params, compat); ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_vsp_params( ++ ioc_compat_fm_vsp_params_t *compat_param, ++ ioc_fm_vsp_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->p_fm = compat_pcd_id2ptr(compat_param->p_fm); ++ memcpy(¶m->ext_buf_pools, &compat_param->ext_buf_pools, sizeof(ioc_fm_ext_pools)); ++ param->liodn_offset = compat_param->liodn_offset; ++ param->portParams.port_id = compat_param->portParams.port_id; ++ param->portParams.port_type = compat_param->portParams.port_type; ++ param->relative_profile_id = compat_param->relative_profile_id; ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ } ++ else ++ { ++ compat_param->p_fm = compat_pcd_ptr2id(param->p_fm); ++ memcpy(&compat_param->ext_buf_pools, ¶m->ext_buf_pools, sizeof(ioc_fm_ext_pools)); ++ compat_param->liodn_offset = param->liodn_offset; ++ compat_param->portParams.port_id = param->portParams.port_id; ++ compat_param->portParams.port_type = param->portParams.port_type; ++ compat_param->relative_profile_id = param->relative_profile_id; ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_buf_pool_depletion_params( ++ ioc_compat_fm_buf_pool_depletion_params_t *compat_param, ++ ioc_fm_buf_pool_depletion_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp); ++ memcpy(¶m->fm_buf_pool_depletion, ++ &compat_param->fm_buf_pool_depletion, ++ sizeof(ioc_fm_buf_pool_depletion_t)); ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_buffer_prefix_content_params( ++ ioc_compat_fm_buffer_prefix_content_params_t *compat_param, ++ ioc_fm_buffer_prefix_content_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp); ++ memcpy(¶m->fm_buffer_prefix_content, ++ &compat_param->fm_buffer_prefix_content, ++ sizeof(ioc_fm_buffer_prefix_content_t)); ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_vsp_config_no_sg_params( ++ ioc_compat_fm_vsp_config_no_sg_params_t *compat_param, ++ ioc_fm_vsp_config_no_sg_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp); ++ param->no_sg = compat_param->no_sg; ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_vsp_prs_result_params( ++ ioc_compat_fm_vsp_prs_result_params_t *compat_param, ++ ioc_fm_vsp_prs_result_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp); ++ /* p_data is an user-space pointer that needs to remain unmodified */ ++ param->p_data = (void *)(unsigned long long)compat_param->p_data; ++ } ++ else ++ { ++ compat_param->p_fm_vsp = compat_pcd_ptr2id(param->p_fm_vsp); ++ /* p_data is an user-space pointer that needs to remain unmodified */ ++ compat_param->p_data = (compat_uptr_t)((unsigned long long)param->p_data & 0xFFFFFFFF); ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++#endif /* (DPAA_VERSION >= 11) */ +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_ioctls_fm_compat.h b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_ioctls_fm_compat.h +new file mode 100644 +index 0000000..e8e6677 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_ioctls_fm_compat.h +@@ -0,0 +1,679 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_ioctls_fm_compat.h ++ ++ @Description FM PCD compat structures definition. ++ ++*/ ++ ++#ifndef __FM_COMPAT_IOCTLS_H ++#define __FM_COMPAT_IOCTLS_H ++ ++#include ++ ++#define COMPAT_K_TO_US 0 /* copy from Kernel to User */ ++#define COMPAT_US_TO_K 1 /* copy from User to Kernel */ ++#define COMPAT_GENERIC 2 ++ ++#define COMPAT_COPY_K2US(dest, src, type) compat_copy_##type(src, dest, 0) ++#define COMPAT_COPY_US2K(dest, src, type) compat_copy_##type(dest, src, 1) ++ ++/* mapping kernel pointers w/ UserSpace id's { */ ++/* Because compat_ptr(ptr_to_compat(X)) != X, this way we cannot exchange pointers ++ back and forth (US - KS). compat_ptr is a cast and pointers are broken. */ ++#define COMPAT_PTR2ID_ARRAY_MAX (256+1) /* first location is not used */ ++#define COMPAT_PTR2ID_WATERMARK 0xface0000 ++#define COMPAT_PTR2ID_WM_MASK 0xffff0000 ++ ++/* define it for debug trace */ ++/*#define FM_COMPAT_DBG*/ ++ ++#define _fm_cpt_prk(stage, format, arg...) \ ++ printk(stage "fm_cpt (cpu:%u): " format, raw_smp_processor_id(), ##arg) ++ ++#define _fm_cpt_inf(format, arg...) _fm_cpt_prk(KERN_INFO, format, ##arg) ++#define _fm_cpt_wrn(format, arg...) _fm_cpt_prk(KERN_WARNING, format, ##arg) ++#define _fm_cpt_err(format, arg...) _fm_cpt_prk(KERN_ERR, format, ##arg) ++ ++/* used for compat IOCTL debugging */ ++#if defined(FM_COMPAT_DBG) ++ #define _fm_cpt_dbg(from, format, arg...) \ ++ do{ \ ++ if (from == COMPAT_US_TO_K) \ ++ printk("fm_cpt to KS [%s:%u](cpu:%u) - " format, \ ++ __func__, __LINE__, raw_smp_processor_id(), ##arg); \ ++ else if (from == COMPAT_K_TO_US) \ ++ printk("fm_cpt to US [%s:%u](cpu:%u) - " format, \ ++ __func__, __LINE__, raw_smp_processor_id(), ##arg); \ ++ else \ ++ printk("fm_cpt [%s:%u](cpu:%u) - " format, \ ++ __func__, __LINE__, raw_smp_processor_id(), ##arg); \ ++ }while(0) ++#else ++# define _fm_cpt_dbg(arg...) ++#endif ++ ++/*TODO: per FMan module: ++ * ++ * Parser: FM_MAP_TYPE_PARSER_NODE, ++ * Kg: FM_MAP_TYPE_KG_NODE, ++ * Policer: FM_MAP_TYPE_POLICER_NODE ++ * Manip: FM_MAP_TYPE_MANIP_NODE ++ **/ ++enum fm_map_node_type { ++ FM_MAP_TYPE_UNSPEC = 0, ++ FM_MAP_TYPE_PCD_NODE, ++ ++ /* add types here, update the policy */ ++ ++ __FM_MAP_TYPE_AFTER_LAST, ++ FM_MAP_TYPE_MAX = __FM_MAP_TYPE_AFTER_LAST - 1 ++}; ++ ++void compat_del_ptr2id(void *p, enum fm_map_node_type); ++compat_uptr_t compat_add_ptr2id(void *p, enum fm_map_node_type); ++compat_uptr_t compat_get_ptr2id(void *p, enum fm_map_node_type); ++void *compat_get_id2ptr(compat_uptr_t comp, enum fm_map_node_type); ++ ++static inline compat_uptr_t compat_pcd_ptr2id(void *ptr) { ++ return (ptr)? compat_get_ptr2id(ptr, FM_MAP_TYPE_PCD_NODE) ++ : (compat_uptr_t) 0; ++} ++ ++static inline void *compat_pcd_id2ptr(compat_uptr_t id) { ++ return (id) ? compat_get_id2ptr(id, FM_MAP_TYPE_PCD_NODE) ++ : NULL; ++} ++ ++/* other similar inlines may be added as new nodes are added ++ to enum fm_map_node_type above... */ ++/* } mapping kernel pointers w/ UserSpace id's */ ++ ++/* pcd compat structures { */ ++typedef struct ioc_compat_fm_pcd_cc_node_remove_key_params_t { ++ compat_uptr_t id; ++ uint16_t key_indx; ++} ioc_compat_fm_pcd_cc_node_remove_key_params_t; ++ ++typedef union ioc_compat_fm_pcd_plcr_next_engine_params_u { ++ ioc_fm_pcd_done_action action; ++ compat_uptr_t p_profile; ++ compat_uptr_t p_direct_scheme; ++} ioc_compat_fm_pcd_plcr_next_engine_params_u; ++ ++typedef struct ioc_compat_fm_pcd_plcr_profile_params_t { ++ bool modify; ++ union { ++ struct { ++ ioc_fm_pcd_profile_type_selection profile_type; ++ compat_uptr_t p_fm_port; ++ uint16_t relative_profile_id; ++ } new_params; ++ compat_uptr_t p_profile; ++ } profile_select; ++ ioc_fm_pcd_plcr_algorithm_selection alg_selection; ++ ioc_fm_pcd_plcr_color_mode color_mode; ++ ++ union { ++ ioc_fm_pcd_plcr_color dflt_color; ++ ioc_fm_pcd_plcr_color override; ++ } color; ++ ++ ioc_fm_pcd_plcr_non_passthrough_alg_param_t non_passthrough_alg_param; ++ ++ ioc_fm_pcd_engine next_engine_on_green; ++ ioc_compat_fm_pcd_plcr_next_engine_params_u params_on_green; ++ ++ ioc_fm_pcd_engine next_engine_on_yellow; ++ ioc_compat_fm_pcd_plcr_next_engine_params_u params_on_yellow; ++ ++ ioc_fm_pcd_engine next_engine_on_red; ++ ioc_compat_fm_pcd_plcr_next_engine_params_u params_on_red; ++ ++ bool trap_profile_on_flow_A; ++ bool trap_profile_on_flow_B; ++ bool trap_profile_on_flow_C; ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_plcr_profile_params_t; ++ ++typedef struct ioc_compat_fm_obj_t { ++ compat_uptr_t obj; ++} ioc_compat_fm_obj_t; ++ ++typedef struct ioc_compat_fm_pcd_kg_scheme_select_t { ++ bool direct; ++ compat_uptr_t scheme_id; ++} ioc_compat_fm_pcd_kg_scheme_select_t; ++ ++typedef struct ioc_compat_fm_pcd_port_schemes_params_t { ++ uint8_t num_of_schemes; ++ compat_uptr_t scheme_ids[FM_PCD_KG_NUM_OF_SCHEMES]; ++} ioc_compat_fm_pcd_port_schemes_params_t; ++ ++#if (DPAA_VERSION >= 11) ++typedef struct ioc_compat_fm_port_vsp_alloc_params_t { ++ uint8_t num_of_profiles; /**< Number of Virtual Storage Profiles */ ++ uint8_t dflt_relative_id; /**< The default Virtual-Storage-Profile-id dedicated to Rx/OP port ++ The same default Virtual-Storage-Profile-id will be for coupled Tx port ++ if relevant function called for Rx port */ ++ compat_uptr_t p_fm_tx_port; /**< Handle to coupled Tx Port; not relevant for OP port. */ ++}ioc_compat_fm_port_vsp_alloc_params_t; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++typedef struct ioc_compat_fm_pcd_net_env_params_t { ++ uint8_t num_of_distinction_units; ++ ioc_fm_pcd_distinction_unit_t units[IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; /* same structure*/ ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_net_env_params_t; ++ ++typedef struct ioc_compat_fm_pcd_prs_sw_params_t { ++ bool override; ++ uint32_t size; ++ uint16_t base; ++ compat_uptr_t p_code; ++ uint32_t sw_prs_data_params[IOC_FM_PCD_PRS_NUM_OF_HDRS]; ++ uint8_t num_of_labels; ++ ioc_fm_pcd_prs_label_params_t labels_table[IOC_FM_PCD_PRS_NUM_OF_LABELS]; ++} ioc_compat_fm_pcd_prs_sw_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_next_kg_params_t { ++ bool override_fqid; ++ uint32_t new_fqid; ++#if DPAA_VERSION >= 11 ++ uint8_t new_relative_storage_profile_id; ++#endif ++ compat_uptr_t p_direct_scheme; ++} ioc_compat_fm_pcd_cc_next_kg_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_next_cc_params_t { ++ compat_uptr_t cc_node_id; ++} ioc_compat_fm_pcd_cc_next_cc_params_t; ++ ++#if DPAA_VERSION >= 11 ++typedef struct ioc_compat_fm_pcd_cc_next_fr_params_t { ++ compat_uptr_t frm_replic_id; ++} ioc_compat_fm_pcd_cc_next_fr_params_t; ++#endif /* DPAA_VERSION >= 11 */ ++ ++typedef struct ioc_compat_fm_pcd_cc_next_engine_params_t { ++ ioc_fm_pcd_engine next_engine; ++ union { ++ ioc_compat_fm_pcd_cc_next_cc_params_t cc_params; /**< compat structure*/ ++ ioc_fm_pcd_cc_next_plcr_params_t plcr_params; /**< same structure*/ ++ ioc_fm_pcd_cc_next_enqueue_params_t enqueue_params; /**< same structure*/ ++ ioc_compat_fm_pcd_cc_next_kg_params_t kg_params; /**< compat structure*/ ++#if DPAA_VERSION >= 11 ++ ioc_compat_fm_pcd_cc_next_fr_params_t fr_params; /**< compat structure*/ ++#endif /* DPAA_VERSION >= 11 */ ++ } params; ++ compat_uptr_t manip_id; ++ bool statistics_en; ++} ioc_compat_fm_pcd_cc_next_engine_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_grp_params_t { ++ uint8_t num_of_distinction_units; ++ uint8_t unit_ids [IOC_FM_PCD_MAX_NUM_OF_CC_UNITS]; ++ ioc_compat_fm_pcd_cc_next_engine_params_t next_engine_per_entries_in_grp[IOC_FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP]; ++} ioc_compat_fm_pcd_cc_grp_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_tree_params_t { ++ compat_uptr_t net_env_id; ++ uint8_t num_of_groups; ++ ioc_compat_fm_pcd_cc_grp_params_t fm_pcd_cc_group_params [IOC_FM_PCD_MAX_NUM_OF_CC_GROUPS]; ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_cc_tree_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t { ++ compat_uptr_t id; ++ uint8_t grp_indx; ++ uint8_t indx; ++ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params; ++} ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_key_params_t { ++ compat_uptr_t p_key; ++ compat_uptr_t p_mask; ++ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params; /**< compat structure*/ ++} ioc_compat_fm_pcd_cc_key_params_t; ++ ++typedef struct ioc_compat_keys_params_t { ++ uint16_t max_num_of_keys; ++ bool mask_support; ++ ioc_fm_pcd_cc_stats_mode statistics_mode; ++#if (DPAA_VERSION >= 11) ++ uint16_t frame_length_ranges[IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR]; ++#endif /* (DPAA_VERSION >= 11) */ ++ uint16_t num_of_keys; ++ uint8_t key_size; ++ ioc_compat_fm_pcd_cc_key_params_t key_params[IOC_FM_PCD_MAX_NUM_OF_KEYS]; /**< compat structure*/ ++ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params_for_miss; /**< compat structure*/ ++} ioc_compat_keys_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_node_params_t { ++ ioc_fm_pcd_extract_entry_t extract_cc_params; /**< same structure*/ ++ ioc_compat_keys_params_t keys_params; /**< compat structure*/ ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_cc_node_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a hash table ++*//***************************************************************************/ ++typedef struct ioc_compat_fm_pcd_hash_table_params_t { ++ uint16_t max_num_of_keys; ++ ioc_fm_pcd_cc_stats_mode statistics_mode; ++ uint16_t hash_res_mask; ++ uint8_t hash_shift; ++ uint8_t match_key_size; ++ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params_for_miss; ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_hash_table_params_t; ++ ++typedef struct ioc_compat_fm_pcd_hash_table_add_key_params_t { ++ compat_uptr_t p_hash_tbl; ++ uint8_t key_size; ++ ioc_compat_fm_pcd_cc_key_params_t key_params; ++} ioc_compat_fm_pcd_hash_table_add_key_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_node_modify_key_params_t { ++ compat_uptr_t id; ++ uint16_t key_indx; ++ uint8_t key_size; ++ compat_uptr_t p_key; ++ compat_uptr_t p_mask; ++} ioc_compat_fm_pcd_cc_node_modify_key_params_t; ++ ++typedef struct ioc_compat_fm_pcd_hash_table_remove_key_params_t { ++ compat_uptr_t p_hash_tbl; ++ uint8_t key_size; ++ compat_uptr_t p_key; ++} ioc_compat_fm_pcd_hash_table_remove_key_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t { ++ compat_uptr_t id; ++ uint16_t key_indx; ++ uint8_t key_size; ++ ioc_compat_fm_pcd_cc_key_params_t key_params; ++} ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t; ++ ++typedef struct ioc_compat_fm_port_pcd_plcr_params_t { ++ compat_uptr_t plcr_profile_id; ++} ioc_compat_fm_port_pcd_plcr_params_t; ++ ++typedef struct ioc_compat_fm_port_pcd_cc_params_t { ++ compat_uptr_t cc_tree_id; ++} ioc_compat_fm_port_pcd_cc_params_t; ++ ++typedef struct ioc_compat_fm_port_pcd_kg_params_t { ++ uint8_t num_of_schemes; ++ compat_uptr_t scheme_ids[FM_PCD_KG_NUM_OF_SCHEMES]; ++ bool direct_scheme; ++ compat_uptr_t direct_scheme_id; ++} ioc_compat_fm_port_pcd_kg_params_t; ++ ++typedef struct ioc_compat_fm_port_pcd_params_t { ++ ioc_fm_port_pcd_support pcd_support; ++ compat_uptr_t net_env_id; ++ compat_uptr_t p_prs_params; ++ compat_uptr_t p_cc_params; ++ compat_uptr_t p_kg_params; ++ compat_uptr_t p_plcr_params; ++ compat_uptr_t p_ip_reassembly_manip; ++} ioc_compat_fm_port_pcd_params_t; ++ ++typedef struct ioc_compat_fm_pcd_kg_cc_t { ++ compat_uptr_t tree_id; ++ uint8_t grp_id; ++ bool plcr_next; ++ bool bypass_plcr_profile_generation; ++ ioc_fm_pcd_kg_plcr_profile_t plcr_profile; ++} ioc_compat_fm_pcd_kg_cc_t; ++ ++typedef struct ioc_compat_fm_pcd_kg_scheme_params_t { ++ bool modify; ++ union { ++ uint8_t relative_scheme_id; ++ compat_uptr_t scheme_id; ++ } scm_id; ++ bool always_direct; ++ struct { ++ compat_uptr_t net_env_id; ++ uint8_t num_of_distinction_units; ++ uint8_t unit_ids[IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; ++ } net_env_params; ++ bool use_hash; ++ ioc_fm_pcd_kg_key_extract_and_hash_params_t key_extract_and_hash_params; ++ bool bypass_fqid_generation; ++ uint32_t base_fqid; ++ uint8_t num_of_used_extracted_ors; ++ ioc_fm_pcd_kg_extracted_or_params_t extracted_ors[IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS]; ++#if DPAA_VERSION >= 11 ++ bool override_storage_profile; ++ ioc_fm_pcd_kg_storage_profile_t storage_profile; ++#endif /* DPAA_VERSION >= 11 */ ++ ioc_fm_pcd_engine next_engine; ++ union{ ++ ioc_fm_pcd_done_action done_action; ++ ioc_fm_pcd_kg_plcr_profile_t plcr_profile; ++ ioc_compat_fm_pcd_kg_cc_t cc; ++ } kg_next_engine_params; ++ ioc_fm_pcd_kg_scheme_counter_t scheme_counter; ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_kg_scheme_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t { ++ compat_uptr_t id; ++ uint16_t key_indx; ++ uint8_t key_size; ++ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params; ++} ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_generic_params_t { ++ uint8_t offset; ++ uint8_t size; ++ bool replace; ++ compat_uptr_t p_data; ++} ioc_compat_fm_pcd_manip_hdr_insrt_generic_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_specific_l2_params_t { ++ ioc_fm_pcd_manip_hdr_insrt_specific_l2 specific_l2; ++ bool update; ++ uint8_t size; ++ compat_uptr_t p_data; ++} ioc_compat_fm_pcd_manip_hdr_insrt_specific_l2_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_by_hdr_params_t { ++ ioc_fm_pcd_manip_hdr_insrt_by_hdr_type type; ++ union { ++ ioc_compat_fm_pcd_manip_hdr_insrt_specific_l2_params_t specific_l2_params; ++ } u; ++} ioc_compat_fm_pcd_manip_hdr_insrt_by_hdr_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_params_t { ++ ioc_fm_pcd_manip_hdr_insrt_type type; ++ union { ++ ioc_compat_fm_pcd_manip_hdr_insrt_by_hdr_params_t by_hdr; ++ ioc_compat_fm_pcd_manip_hdr_insrt_generic_params_t generic; ++#ifdef FM_CAPWAP_SUPPORT ++#error CAPWAP not supported! ++ ioc_fm_pcd_manip_hdr_insrt_by_template_params_t by_template; ++#endif /* FM_CAPWAP_SUPPORT */ ++ } u; ++} ioc_compat_fm_pcd_manip_hdr_insrt_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_hdr_params_t { ++ bool rmv; ++ ioc_fm_pcd_manip_hdr_rmv_params_t rmv_params; ++ bool insrt; ++ ioc_compat_fm_pcd_manip_hdr_insrt_params_t insrt_params; ++ bool field_update; ++ ioc_fm_pcd_manip_hdr_field_update_params_t field_update_params; ++ bool custom; ++ ioc_fm_pcd_manip_hdr_custom_params_t custom_params; ++ bool dont_parse_after_manip; ++} ioc_compat_fm_pcd_manip_hdr_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_params_t { ++ ioc_fm_pcd_manip_type type; ++ union { ++ ioc_compat_fm_pcd_manip_hdr_params_t hdr; ++ ioc_fm_pcd_manip_reassem_params_t reassem; ++ ioc_fm_pcd_manip_frag_params_t frag; ++ ioc_fm_pcd_manip_special_offload_params_t special_offload; ++ } u; ++ compat_uptr_t p_next_manip; ++#ifdef FM_CAPWAP_SUPPORT ++#error "FM_CAPWAP_SUPPORT feature not supported!" ++ bool frag_or_reasm; ++ ioc_fm_pcd_manip_frag_or_reasm_params_t frag_or_reasm_params; ++#endif /* FM_CAPWAP_SUPPORT */ ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_manip_params_t; ++ ++#if (DPAA_VERSION >= 11) ++typedef struct ioc_compat_fm_pcd_frm_replic_group_params_t { ++ uint8_t max_num_of_entries; ++ uint8_t num_of_entries; ++ ioc_compat_fm_pcd_cc_next_engine_params_t ++ next_engine_params[IOC_FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES]; ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_frm_replic_group_params_t; ++ ++typedef struct ioc_compat_fm_pcd_frm_replic_member_t { ++ compat_uptr_t h_replic_group; ++ uint16_t member_index; ++} ioc_compat_fm_pcd_frm_replic_member_t; ++ ++typedef struct ioc_compat_fm_pcd_frm_replic_member_params_t { ++ ioc_compat_fm_pcd_frm_replic_member_t member; ++ ioc_compat_fm_pcd_cc_next_engine_params_t next_engine_params; ++} ioc_compat_fm_pcd_frm_replic_member_params_t; ++ ++typedef struct ioc_compat_fm_vsp_params_t { ++ compat_uptr_t p_fm; /**< A handle to the FM object this VSP related to */ ++ ioc_fm_ext_pools ext_buf_pools; /**< Which external buffer pools are used ++ (up to FM_PORT_MAX_NUM_OF_EXT_POOLS), and their sizes. ++ parameter associated with Rx / OP port */ ++ uint16_t liodn_offset; /**< VSP's LIODN offset */ ++ struct { ++ ioc_fm_port_type port_type; /**< Port type */ ++ uint8_t port_id; /**< Port Id - relative to type */ ++ } portParams; ++ uint8_t relative_profile_id; /**< VSP Id - relative to VSP's range ++ defined in relevant FM object */ ++ compat_uptr_t id; /**< return value */ ++} ioc_compat_fm_vsp_params_t; ++ ++typedef struct ioc_compat_fm_buf_pool_depletion_params_t { ++ compat_uptr_t p_fm_vsp; ++ ioc_fm_buf_pool_depletion_t fm_buf_pool_depletion; ++} ioc_compat_fm_buf_pool_depletion_params_t; ++ ++typedef struct ioc_compat_fm_buffer_prefix_content_params_t { ++ compat_uptr_t p_fm_vsp; ++ ioc_fm_buffer_prefix_content_t fm_buffer_prefix_content; ++} ioc_compat_fm_buffer_prefix_content_params_t; ++ ++typedef struct ioc_compat_fm_vsp_config_no_sg_params_t { ++ compat_uptr_t p_fm_vsp; ++ bool no_sg; ++} ioc_compat_fm_vsp_config_no_sg_params_t; ++ ++typedef struct ioc_compat_fm_vsp_prs_result_params_t { ++ compat_uptr_t p_fm_vsp; ++ compat_uptr_t p_data; ++} ioc_compat_fm_vsp_prs_result_params_t; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++typedef struct ioc_compat_fm_ctrl_mon_counters_params_t { ++ uint8_t fm_ctrl_index; ++ compat_uptr_t p_mon; ++} ioc_compat_fm_ctrl_mon_counters_params_t; ++ ++/* } pcd compat structures */ ++ ++void compat_obj_delete( ++ ioc_compat_fm_obj_t *compat_id, ++ ioc_fm_obj_t *id); ++ ++/* pcd compat functions { */ ++void compat_copy_fm_pcd_plcr_profile( ++ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param, ++ ioc_fm_pcd_plcr_profile_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_key( ++ ioc_compat_fm_pcd_cc_key_params_t *compat_param, ++ ioc_fm_pcd_cc_key_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_node_modify_key_and_next_engine( ++ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_node_modify_next_engine( ++ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param, ++ uint8_t compat); ++ ++void compat_fm_pcd_cc_tree_modify_next_engine( ++ ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_tree_modify_next_engine_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_hash_table( ++ ioc_compat_fm_pcd_hash_table_params_t *compat_param, ++ ioc_fm_pcd_hash_table_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_grp( ++ ioc_compat_fm_pcd_cc_grp_params_t *compat_param, ++ ioc_fm_pcd_cc_grp_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_tree( ++ ioc_compat_fm_pcd_cc_tree_params_t *compat_param, ++ ioc_fm_pcd_cc_tree_params_t *param, ++ uint8_t compat); ++ ++void compat_fm_pcd_prs_sw( ++ ioc_compat_fm_pcd_prs_sw_params_t *compat_param, ++ ioc_fm_pcd_prs_sw_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_kg_scheme( ++ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param, ++ ioc_fm_pcd_kg_scheme_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_kg_scheme_select( ++ ioc_compat_fm_pcd_kg_scheme_select_t *compat_param, ++ ioc_fm_pcd_kg_scheme_select_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_kg_schemes_params( ++ ioc_compat_fm_pcd_port_schemes_params_t *compat_param, ++ ioc_fm_pcd_port_schemes_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_port_pcd_kg( ++ ioc_compat_fm_port_pcd_kg_params_t *compat_param, ++ ioc_fm_port_pcd_kg_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_port_pcd( ++ ioc_compat_fm_port_pcd_params_t *compat_param, ++ ioc_fm_port_pcd_params_t *param, ++ uint8_t compat); ++ ++#if (DPAA_VERSION >= 11) ++void compat_copy_fm_port_vsp_alloc_params( ++ ioc_compat_fm_port_vsp_alloc_params_t *compat_param, ++ ioc_fm_port_vsp_alloc_params_t *param, ++ uint8_t compat); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++void compat_copy_fm_pcd_net_env( ++ ioc_compat_fm_pcd_net_env_params_t *compat_param, ++ ioc_fm_pcd_net_env_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_node_modify_key( ++ ioc_compat_fm_pcd_cc_node_modify_key_params_t *compat_param, ++ ioc_fm_pcd_cc_node_modify_key_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_keys( ++ ioc_compat_keys_params_t *compat_param, ++ ioc_keys_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_node( ++ ioc_compat_fm_pcd_cc_node_params_t *compat_param, ++ ioc_fm_pcd_cc_node_params_t *param, ++ uint8_t compat); ++ ++void compat_fm_pcd_manip_set_node( ++ ioc_compat_fm_pcd_manip_params_t *compat_param, ++ ioc_fm_pcd_manip_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_port_pcd_modify_tree( ++ ioc_compat_fm_obj_t *compat_id, ++ ioc_fm_obj_t *id, ++ uint8_t compat); ++ ++#if (DPAA_VERSION >= 11) ++void compat_copy_fm_pcd_frm_replic_group_params( ++ ioc_compat_fm_pcd_frm_replic_group_params_t *compat_param, ++ ioc_fm_pcd_frm_replic_group_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_frm_replic_member( ++ ioc_compat_fm_pcd_frm_replic_member_t *compat_param, ++ ioc_fm_pcd_frm_replic_member_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_frm_replic_member_params( ++ ioc_compat_fm_pcd_frm_replic_member_params_t *compat_param, ++ ioc_fm_pcd_frm_replic_member_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_vsp_params( ++ ioc_compat_fm_vsp_params_t *compat_param, ++ ioc_fm_vsp_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_buf_pool_depletion_params( ++ ioc_compat_fm_buf_pool_depletion_params_t *compat_param, ++ ioc_fm_buf_pool_depletion_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_buffer_prefix_content_params( ++ ioc_compat_fm_buffer_prefix_content_params_t *compat_param, ++ ioc_fm_buffer_prefix_content_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_vsp_config_no_sg_params( ++ ioc_compat_fm_vsp_config_no_sg_params_t *compat_param, ++ ioc_fm_vsp_config_no_sg_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_vsp_prs_result_params( ++ ioc_compat_fm_vsp_prs_result_params_t *compat_param, ++ ioc_fm_vsp_prs_result_params_t *param, ++ uint8_t compat); ++#endif /* (DPAA_VERSION >= 11) */ ++/* } pcd compat functions */ ++#endif +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources.c b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources.c +new file mode 100644 +index 0000000..2686aa2 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources.c +@@ -0,0 +1,1196 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_resources.c ++ ++ @Description FMD wrapper resource allocation functions. ++ ++*/ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++ ++#include ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++#include ++#include ++#include ++#include ++ ++#endif /*#if !defined(FMAN_RESOURCES_UNIT_TEST)*/ ++ ++#include "lnxwrp_resources.h" ++ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++static struct device_node *match_mac_to_dpaa_port(struct device_node ++ *enet_mac_node) ++{ ++ struct device_node *dpaa_node = NULL; ++ struct device_node *dpaa_itf = NULL; ++ ++ /* find DPAA node starting from root */ ++ dpaa_node = of_find_compatible_node(NULL, NULL, "fsl,dpaa"); ++ if (dpaa_node) { ++ /* for all dpaa ports check which one refers this mac node. */ ++ for_each_child_of_node(dpaa_node, dpaa_itf) { ++ struct device_node *by_handle_enet_mac_node = NULL; ++ const phandle *phandle_prop = NULL; ++ int lenp = 0; ++ ++ phandle_prop = ++ (typeof(phandle_prop)) ++ of_get_property(dpaa_itf, "fsl,fman-mac", ++ &lenp); ++ if (phandle_prop == NULL) ++ continue; ++ ++ if (WARN_ON(lenp != sizeof(phandle))) ++ return NULL; ++ ++ by_handle_enet_mac_node = ++ of_find_node_by_phandle(*phandle_prop); ++ if (unlikely(by_handle_enet_mac_node == NULL)) ++ return NULL; ++ ++ /* check */ ++ if (by_handle_enet_mac_node == enet_mac_node) { ++ of_node_put(by_handle_enet_mac_node); ++ return dpaa_itf; ++ } ++ ++ of_node_put(by_handle_enet_mac_node); ++ } ++ of_node_put(dpaa_node); ++ } ++ ++ return NULL; ++} ++ ++static struct device_node *match_fman_port_to_mac(struct device_node *fm_node, ++ struct device_node ++ *fm_port_node) ++{ ++ struct device_node *fm_node_idx = NULL; ++ ++ /* for all enet nodes (macs) check which one refers this FMan port. */ ++ for_each_child_of_node(fm_node, fm_node_idx) { ++ if (of_device_is_compatible(fm_node_idx, "fsl,fman-1g-mac") || ++ of_device_is_compatible(fm_node_idx, "fsl,fman-10g-mac") || ++ of_device_is_compatible(fm_node_idx, "fsl,fman-memac")) { ++ struct device_node *fman_port_node_rx = NULL; ++ struct device_node *fman_port_node_tx = NULL; ++ /* RX is first */ ++ fman_port_node_rx = of_parse_phandle(fm_node_idx, ++ "fsl,port-handles", 0); ++ if (unlikely(fman_port_node_rx == NULL)) ++ continue; ++ /* TX is second */ ++ fman_port_node_tx = of_parse_phandle(fm_node_idx, ++ "fsl,port-handles", 1); ++ if (unlikely(fman_port_node_tx == NULL)) { ++ of_node_put(fman_port_node_rx); ++ continue; ++ } ++ ++ /* check */ ++ if (fman_port_node_rx == fm_port_node ++ || fman_port_node_tx == fm_port_node) { ++ of_node_put(fman_port_node_rx); ++ of_node_put(fman_port_node_tx); ++ return fm_node_idx; ++ } ++ ++ of_node_put(fman_port_node_rx); ++ of_node_put(fman_port_node_tx); ++ } ++ } ++ ++ return NULL; ++} ++ ++static bool is_fman_port_active(struct device_node *fm_node, ++ struct device_node *fm_port_node) ++{ ++ struct device_node *enet_mac_node = NULL; ++ struct device_node *itf_node = NULL; ++ ++ /* Which MAC node refers to this FMan port. */ ++ enet_mac_node = match_fman_port_to_mac(fm_node, fm_port_node); ++ ++ if (unlikely(enet_mac_node == NULL)) ++ return false; ++ ++ /* Which dpaa port node refers this MAC node. */ ++ itf_node = match_mac_to_dpaa_port(enet_mac_node); ++ of_node_put(enet_mac_node); ++ ++ if (unlikely(!itf_node)) ++ return false; ++ ++ /* check if itf (DPAA ports) is available. ++ * if available, means that the FMan port is ++ * also available - return true ++ */ ++ if (!of_device_is_available(itf_node)) { ++ of_node_put(itf_node); ++ return false; ++ } ++ of_node_put(itf_node); ++ ++ return true; ++} ++ ++int fm_set_active_fman_ports(struct platform_device *of_dev, ++ t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ struct device_node *fm_node = NULL; ++ struct device_node *fm_port_node = NULL; ++ ++ memset(&p_LnxWrpFmDev->fm_active_ports_info, 0, ++ sizeof(struct fm_active_ports)); ++ ++ /* get FMan node */ ++ fm_node = of_dev->dev.of_node; ++ ++ /* for all ports which belong to this FMan, check if they are active. ++ * If active, set their parameters. */ ++ for_each_child_of_node(fm_node, fm_port_node) { ++ ++ if (!of_device_is_available(fm_port_node)) ++ continue; ++ ++ /* OH FMan ports */ ++ if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-oh")) { ++ p_LnxWrpFmDev->fm_active_ports_info.num_oh_ports++; ++ continue; ++ } ++ ++ if (!is_fman_port_active(fm_node, fm_port_node)) ++ continue; ++ ++ /* 10g TX FMan ports */ ++ if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-10g-tx")) ++ p_LnxWrpFmDev->fm_active_ports_info.num_tx10_ports++; ++ ++ /* 10g RX FMan ports */ ++ else if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-10g-rx")) ++ p_LnxWrpFmDev->fm_active_ports_info.num_rx10_ports++; ++ ++ /* 1G TX FMan ports */ ++ else if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-1g-tx")) ++ p_LnxWrpFmDev->fm_active_ports_info.num_tx_ports++; ++ ++ /* 1G RX FMan ports */ ++ else if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-1g-rx")) ++ p_LnxWrpFmDev->fm_active_ports_info.num_rx_ports++; ++ } ++ ++ /* If performance is needed no oh port is probed ++ * except the one used for host command. */ ++#if defined(CONFIG_FMAN_DISABLE_OH_TO_REUSE_RESOURCES) ++ if (p_LnxWrpFmDev->fm_active_ports_info.num_oh_ports) ++ p_LnxWrpFmDev->fm_active_ports_info.num_oh_ports = 1; ++ ++ printk(KERN_WARNING "FMAN(%u)-Performance mode - no OH support...\n", ++ p_LnxWrpFmDev->id); ++#endif ++ ++ return 0; ++} ++#endif /*!defined(FMAN_RESOURCES_UNIT_TEST)*/ ++ ++/* BPOOL size is constant and equal w/ DPA_BP_SIZE */ ++static uint32_t get_largest_buf_size(uint32_t max_rx_frame_size, uint32_t buf_size) ++{ ++ uint32_t priv_data_size = 16; /* DPA_PRIV_DATA_SIZE */ ++ uint32_t hash_results_size = 16; /* DPA_HASH_RESULTS_SIZE */ ++ uint32_t parse_results_size = ++ sizeof(t_FmPrsResult); /* DPA_PARSE_RESULTS_SIZE */ ++ uint32_t bp_head = priv_data_size + hash_results_size + ++ parse_results_size + ++ fm_get_rx_extra_headroom(); /* DPA_BP_HEAD */ ++ uint32_t bp_size = bp_head + max_rx_frame_size ++ + NET_IP_ALIGN; /* DPA_BP_SIZE */ ++ ++#ifndef CONFIG_DPAA_ETH_SG_SUPPORT ++ return CEIL_DIV(bp_size, buf_size); ++#else ++ bp_size = CEIL_DIV(bp_size, 16); /* frame split in 16 frags */ ++ ++ return max((uint32_t)16, CEIL_DIV(bp_size, buf_size)); ++#endif /* CONFIG_DPAA_ETH_SG_SUPPORT */ ++} ++ ++/* Calculate the fifosize based on MURAM allocation, number of ports, dpde ++ value and s/g software support (! Kernel does not suport s/g). ++ ++ Algorithm summary: ++ - Calculate the the minimum fifosize required for every type of port ++ (TX,RX for 1G, 2.5G and 10G). ++ - Set TX the minimum fifosize required. ++ - Distribute the remaining buffers (after all TX were set) to RX ports ++ based on: ++ 1G RX = Remaining_buffers * 1/(1+2.5+10) ++ 2.5G RX = Remaining_buffers * 2.5/(1+2.5+10) ++ 10G RX = Remaining_buffers * 10/(1+2.5+10) ++ - if the RX is smaller than the minimum required, then set the minimum ++ required ++ - In the end distribuite the leftovers if there are any (due to ++ unprecise calculus) or if over allocation cat some buffers from all RX ++ ports w/o pass over minimum required treshold, but if there must be ++ pass the treshold in order to cat the over allocation ,then this ++ configuration can not be set - KERN_ALERT. ++*/ ++int fm_precalculate_fifosizes(t_LnxWrpFmDev *p_LnxWrpFmDev, int muram_fifo_size) ++{ ++ ++ /* input parameters */ ++ struct fm_active_ports *fm_active_ports_info = NULL; ++ int num_1g_ports = 0; ++ int num_2g5_ports = 0; ++ int num_10g_ports = 0; ++ int num_oh_ports = 0; ++ ++ /* output parameters */ ++ struct fm_resource_settings *fm_resource_settings_info = NULL; ++ int oh_buff = 0; ++ int tx_1g_bufs = 0, rx_1g_bufs = 0; ++ int tx_2g5_bufs = 0, rx_2g5_bufs = 0; ++ int tx_10g_bufs = 0, rx_10g_bufs = 0; ++ int err = 0; ++ ++ /* throughput parameters: divide it by 10 when used */ ++ int gb1g = 10, gb2g5 = 25, gb10g = 100, gb_sum = 0; ++ ++ /* buffers parameters */ ++ int buf_size = 0x100; /* Buffer unit size */ ++ int total_no_buffers = 0; /* Calculus based on MURAM size for ++ fifos and buf. unit size */ ++ ++ int shared_ext_buff = 0; /* External buffers allocated - LLD ++ boundaries:DEFAULT_PORT_extraSizeOfFifo */ ++ ++ int min_tx_1g_2g5_bufs = 0; /* minimum TX1g buffers required ++ (see refman.) */ ++ int min_tx_10g_bufs = 0; /* minimum TX10g buffers required ++ (see refman.) */ ++ int min_rx_bufs = 0; /* minimum RX buffers required (see refman.) */ ++ ++ /* Buffer sizes calculus */ ++ int max_frame_size = fm_get_max_frm(); ++ int remaining_bufs = 0; ++ int rx_1g_bufs_ceil = 0, rx_2g5_bufs_ceil = 0, rx_10g_bufs_ceil = 0; ++ int rx_2g5_max_bufs = 0, rx_10g_max_bufs = 0; ++ int rx_1g_used = 0, rx_1g_2g5_used = 0, rx_1g_10g_used =0, ++ rx_2g5_used = 0, rx_2g5_10g_used = 0, rx_1g_2g5_10g_used = 0; ++ ++ /* overflow checking */ ++ int tot_rx_buffs, tot_tx_buffs, tot_oh_buffs, tot_used_buffs, ++ leftovers = 0; ++ int overflow = 0; ++ bool loop = false; ++ ++ /* check input parameters correctness */ ++ ASSERT_COND(p_LnxWrpFmDev != NULL); ++ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info; ++ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info; ++ ASSERT_COND(fm_active_ports_info != NULL); ++ ASSERT_COND(fm_resource_settings_info != NULL); ++ ASSERT_COND(fm_active_ports_info->num_tx_ports == ++ fm_active_ports_info->num_rx_ports); ++ ASSERT_COND(fm_active_ports_info->num_tx25_ports == ++ fm_active_ports_info->num_tx25_ports); ++ ASSERT_COND(fm_active_ports_info->num_tx10_ports == ++ fm_active_ports_info->num_tx10_ports); ++ ASSERT_COND(max_frame_size != 0); ++ ASSERT_COND(muram_fifo_size != 0); ++ ++ /* set input parameters */ ++ num_1g_ports = fm_active_ports_info->num_tx_ports; ++ num_2g5_ports = fm_active_ports_info->num_tx25_ports; ++ num_10g_ports = fm_active_ports_info->num_tx10_ports; ++ num_oh_ports = fm_active_ports_info->num_oh_ports; ++ ++ /* throughput calculus */ ++ gb_sum = gb1g * num_1g_ports + gb2g5 * num_2g5_ports ++ + gb10g * num_10g_ports; /* divide it by 10 */ ++ ++ /* Base buffer calculus */ ++ oh_buff = 8; ++ total_no_buffers = muram_fifo_size / buf_size; ++ ++ min_tx_1g_2g5_bufs = CEIL_DIV(max_frame_size, buf_size) ++ + DPDE_1G + 3 + 1; /* +1 to handle Jumbo Frames */ ++ min_tx_10g_bufs = CEIL_DIV(max_frame_size, buf_size) ++ + DPDE_10G + 3 + 1; /* +1 to handle Jumbo Frames */ ++ ++ { ++/* ++ * On P1023RDS FM_FIFO_ALLOCATION_ALG is enabled allowing a smaller Rx FIFO ++ * on hardware major rev 4. If the Rx FIFO is smaller than the size of the ++ * buffer in the buffer pool SG frames will be received ++ */ ++#if defined(FM_FIFO_ALLOCATION_ALG) && \ ++ !defined(FMAN_RESOURCES_UNIT_TEST) && \ ++ defined(CONFIG_DPAA_ETH_SG_SUPPORT) ++ uint8_t fm_rev_major = 0; ++ fm_rev_major = (uint8_t) ((* ++ ((volatile uint32_t *) ++ UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr + ++ 0x000c30c4)) & 0xff00) >> 8); ++ ++ if (fm_rev_major == 4) ++ min_rx_bufs = 8; ++ else ++#endif ++ min_rx_bufs = get_largest_buf_size(max_frame_size, ++ buf_size) + 7; ++ } ++ ++#ifdef CONFIG_FMAN_P1023 ++ shared_ext_buff = 0; ++#else ++ /* changing these might reduce performance */ ++ shared_ext_buff = num_10g_ports ? 32 : 16; /* LLD boundaries: ++ DEFAULT_PORT_extraNumOfFifoBufs */ ++#endif ++ ++ /* TX ports will have minimum required buffers ++ Calculus of the remaining buffers for all RX ports */ ++ tx_1g_bufs = num_1g_ports ? min_tx_1g_2g5_bufs : 0; ++ tx_2g5_bufs = num_2g5_ports ? min_tx_1g_2g5_bufs : 0; ++ tx_10g_bufs = num_10g_ports ? min_tx_10g_bufs : 0; ++ ++ remaining_bufs = total_no_buffers - ++ oh_buff * num_oh_ports - ++ num_1g_ports * min_tx_1g_2g5_bufs - ++ num_2g5_ports * min_tx_1g_2g5_bufs - ++ num_10g_ports * min_tx_10g_bufs - shared_ext_buff; ++ ++ if (remaining_bufs < 0) { ++ printk(KERN_ALERT ++ "\nThis configuration will not work due to low number of" ++ " buffers (%u buffers)...\n", ++ total_no_buffers); ++ err = -1; ++ goto precalculated_fifosize_out; ++ } ++ ++ /* Per port buffer size calculus ++ . for TX ports give always minimum required ++ . for RX ports give whatever left scaled per port type */ ++ /* ------------------------------------------------------- */ ++ if (num_1g_ports) { ++ rx_1g_bufs_ceil = ++ (gb_sum / ++ 10) ? CEIL_DIV(((remaining_bufs * gb1g) / 10), ++ (gb_sum / 10)) : 0; ++ rx_1g_bufs = MAX(min_rx_bufs, rx_1g_bufs_ceil); ++ rx_1g_used = rx_1g_bufs - rx_1g_bufs_ceil; /* always >= 0 */ ++ /* distribute to 2.5g and 10g ports */ ++ rx_1g_2g5_used = ++ (num_2g5_ports + ++ num_10g_ports) ? CEIL_DIV(rx_1g_used * num_1g_ports * ++ num_2g5_ports, ++ num_2g5_ports + ++ num_10g_ports) : 0; ++ rx_1g_10g_used = ++ (num_2g5_ports + ++ num_10g_ports) ? CEIL_DIV(rx_1g_used * num_1g_ports * ++ num_10g_ports, ++ num_2g5_ports + ++ num_10g_ports) : 0; ++ } ++ ++ if (num_2g5_ports) { ++ rx_2g5_bufs_ceil = ++ (gb_sum / ++ 10) ? CEIL_DIV(((remaining_bufs * gb2g5) / 10), ++ (gb_sum / 10)) : 0; ++ rx_2g5_max_bufs = MAX(min_rx_bufs, rx_2g5_bufs_ceil); ++ rx_2g5_bufs = ++ MAX(min_rx_bufs, rx_2g5_max_bufs - rx_1g_2g5_used); ++ rx_2g5_used = rx_2g5_bufs - rx_2g5_bufs_ceil; /* always >= 0 */ ++ /* distribute to 10g ports */ ++ rx_2g5_10g_used = ++ num_10g_ports ? CEIL_DIV(rx_2g5_used * num_2g5_ports, ++ num_10g_ports) : 0; ++ } ++ ++ if (num_10g_ports) { ++ rx_10g_bufs_ceil = ++ (gb_sum / ++ 10) ? CEIL_DIV(((remaining_bufs * gb10g) / 10), ++ (gb_sum / 10)) : 0; ++ rx_10g_max_bufs = MAX(min_rx_bufs, rx_10g_bufs_ceil); ++ /* keep count of all distribution */ ++ rx_1g_2g5_10g_used = rx_1g_10g_used + rx_2g5_10g_used; ++ rx_10g_bufs = ++ MAX(min_rx_bufs, ++ rx_10g_max_bufs - rx_1g_2g5_10g_used); ++ } ++ ++ /* overflow-leftover calculus */ ++ tot_rx_buffs = rx_1g_bufs * num_1g_ports + ++ rx_2g5_bufs * num_2g5_ports + rx_10g_bufs * num_10g_ports; ++ tot_tx_buffs = tx_1g_bufs * num_1g_ports + ++ tx_2g5_bufs * num_2g5_ports + tx_10g_bufs * num_10g_ports; ++ tot_oh_buffs = oh_buff * num_oh_ports; ++ tot_used_buffs = ++ tot_oh_buffs + tot_tx_buffs + tot_rx_buffs + shared_ext_buff; ++ ++ overflow = tot_used_buffs - total_no_buffers; ++ /* used more than available */ ++ if (overflow > 0) { ++ loop = true; ++ while (overflow > 0 && loop) { ++ loop = false; ++ if (overflow && num_10g_ports ++ && rx_10g_bufs > min_rx_bufs) { ++ rx_10g_bufs--; ++ overflow -= num_10g_ports; ++ loop = true; ++ } ++ if (overflow && num_2g5_ports ++ && rx_2g5_bufs > min_rx_bufs) { ++ rx_2g5_bufs--; ++ overflow -= num_2g5_ports; ++ loop = true; ++ } ++ if (overflow && num_1g_ports ++ && rx_1g_bufs > min_rx_bufs) { ++ rx_1g_bufs--; ++ overflow -= num_1g_ports; ++ loop = true; ++ } ++ } ++ ++ if (overflow > 0) { ++ printk(KERN_ALERT ++ "This configuration will not work due to over" ++ " buffer allocation (%d buffers)...\n", ++ overflow); ++ err = -1; ++ goto precalculated_fifosize_out; ++ } ++ } ++ /* left a few buffers */ ++ else if (overflow < 0) { ++ leftovers = total_no_buffers - tot_used_buffs; ++ loop = true; ++ while (leftovers > 0 && loop) { ++ loop = false; ++ if (leftovers && num_1g_ports) { ++ rx_1g_bufs++; ++ leftovers -= num_1g_ports; ++ loop = true; ++ } ++ ++ if (leftovers && num_2g5_ports) { ++ rx_2g5_bufs++; ++ leftovers -= num_2g5_ports; ++ loop = true; ++ } ++ ++ if (leftovers && num_10g_ports) { ++ rx_10g_bufs++; ++ leftovers -= num_10g_ports; ++ loop = true; ++ } ++ } ++ } ++ ++ /* set fifosizes for this FMan ports */ ++ fm_resource_settings_info->tx1g_num_buffers = tx_1g_bufs; ++ fm_resource_settings_info->rx1g_num_buffers = rx_1g_bufs; ++ fm_resource_settings_info->tx2g5_num_buffers = tx_2g5_bufs; ++ fm_resource_settings_info->rx2g5_num_buffers = rx_2g5_bufs; ++ fm_resource_settings_info->tx10g_num_buffers = tx_10g_bufs; ++ fm_resource_settings_info->rx10g_num_buffers = rx_10g_bufs; ++ fm_resource_settings_info->oh_num_buffers = oh_buff; ++ fm_resource_settings_info->shared_ext_buffers = shared_ext_buff; ++ ++precalculated_fifosize_out: ++ printk(KERN_INFO " FMAN(%u) Fifo size settings:\n", ++ p_LnxWrpFmDev->id); ++ printk(KERN_INFO " - Total buffers available(%u - 256B/buffer)\n", ++ total_no_buffers); ++ printk(KERN_INFO " - Total throughput(%uGbps)\n", (gb_sum / 10)); ++ printk(KERN_INFO " - Max frame size(%uB)\n", max_frame_size); ++ if (num_1g_ports) { ++ printk(KERN_INFO ++ " - 1G ports TX %u(%u bufs set (min: %u))\n", ++ num_1g_ports, tx_1g_bufs, min_tx_1g_2g5_bufs); ++ printk(KERN_INFO ++ " - 1G ports RX %u(%u bufs set (min: %u))\n", ++ num_1g_ports, rx_1g_bufs, min_rx_bufs); ++ } ++ if (num_2g5_ports) { ++ printk(KERN_INFO ++ " - 2.5G ports TX %u(%u bufs set (min: %u))\n", ++ num_2g5_ports, tx_2g5_bufs, min_tx_1g_2g5_bufs); ++ printk(KERN_INFO ++ " - 2.5G ports RX %u(%u bufs set (min: %u))\n", ++ num_2g5_ports, rx_2g5_bufs, min_rx_bufs); ++ } ++ if (num_10g_ports) { ++ printk(KERN_INFO ++ " - 10G ports TX %u(%u bufs set (min: %u))\n", ++ num_10g_ports, tx_10g_bufs, min_tx_10g_bufs); ++ printk(KERN_INFO ++ " - 10G ports RX %u(%u bufs set (min: %u))\n", ++ num_10g_ports, rx_10g_bufs, min_rx_bufs); ++ } ++ if (num_oh_ports) ++ printk(KERN_INFO " - OH-HC ports %u(%u)\n", num_oh_ports, ++ oh_buff); ++ printk(KERN_INFO " - Shared extra buffers(%u)\n", shared_ext_buff); ++ ++ return err; ++} ++ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++int fm_config_precalculate_fifosize(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ++ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ struct fm_resource_settings *fm_resource_settings_info = NULL; ++ struct fm_active_ports *fm_active_ports_info = NULL; ++ t_FmPortRsrc portRsrc; ++ t_Error errCode; ++ uint32_t buf_size = 0x100; ++ ++ ASSERT_COND(p_LnxWrpFmDev != NULL); ++ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info; ++ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info; ++ ++ memset(&portRsrc, 0, sizeof(t_FmPortRsrc)); ++ ++/* IF 1G PORT */ ++ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX) { ++ portRsrc.num = ++ fm_resource_settings_info->tx1g_num_buffers * buf_size; ++ portRsrc.extra = 0; ++ } else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_RX) { ++ portRsrc.num = ++ fm_resource_settings_info->rx1g_num_buffers * buf_size; ++ portRsrc.extra = ++ fm_resource_settings_info->shared_ext_buffers * ++ buf_size; ++ } ++/* IF 2.5G PORT */ ++ /* TODO: Not supported by LLD yet. */ ++ ++/* IF 10G PORT */ ++ else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_TX_10G) { ++ portRsrc.num = ++ fm_resource_settings_info->tx10g_num_buffers * ++ buf_size; ++ portRsrc.extra = 0; ++ } else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_RX_10G) { ++ portRsrc.num = ++ fm_resource_settings_info->rx10g_num_buffers * ++ buf_size; ++ portRsrc.extra = ++ fm_resource_settings_info->shared_ext_buffers * ++ buf_size; ++ } else { /* IF OH PORT */ ++ portRsrc.num = ++ fm_resource_settings_info->oh_num_buffers * buf_size; ++ portRsrc.extra = 0; ++ } ++ ++ errCode = FM_PORT_ConfigSizeOfFifo(p_LnxWrpFmPortDev->h_Dev, &portRsrc); ++ if (errCode != E_OK) { ++ printk(KERN_WARNING ++ "FM_PORT_SetSizeOfFifo failed (errCode:0x%2x)", ++ errCode); ++ return -EIO; ++ } ++ ++ return 0; ++} ++#endif /*if !defined(FMAN_RESOURCES_UNIT_TEST)*/ ++ ++/* Compute FMan open DMA based on total number of open DMAs and ++ * number of available FMan ports. ++ * ++ * By default 10g ports are set to input parameters. The other ports ++ * tries to keep the proportion rx=2tx open DMAs or thresholds. ++ * ++ * If leftovers, then those will be set as shared. ++ * ++ * If after computing overflow appears, then it decrements open DMA ++ * for all ports w/o cross the thresholds. If the thresholds are meet ++ * and is still overflow, then it returns error. ++ */ ++int fm_precalculate_open_dma(t_LnxWrpFmDev *p_LnxWrpFmDev, ++ int max_fm_open_dma, ++ int default_tx_10g_dmas, ++ int default_rx_10g_dmas, ++ int min_tx_10g_treshold, int min_rx_10g_treshold) ++{ ++ /* input parameters */ ++ struct fm_active_ports *fm_active_ports_info = NULL; ++ int num_1g_ports = 0; ++ int num_2g5_ports = 0; ++ int num_10g_ports = 0; ++ int num_oh_ports = 0; ++ ++ /* output parameters */ ++ struct fm_resource_settings *fm_resource_settings_info = NULL; ++ int tx_1g_dmas = 0, rx_1g_dmas = 0; ++ int tx_2g5_dmas = 0, rx_2g5_dmas = 0; ++ int tx_10g_dmas = 0, rx_10g_dmas = 0; ++ int oh_dmas = 0; ++ int shared_ext_open_dma = 0; ++ int err = 0; ++ ++ /* open dma calculus */ ++ int remaing_dmas = 0; ++ int rx_tx_raport = ++ FM_OPENDMA_RX_TX_RAPORT; /* RX = FM_OPENDMA_RX_TX_RAPORT *TX */ ++ int min_tx_1_2g5_treshold = 1; ++ int min_rx_1_2g5_treshold = 1; ++ int max_open_dma_treshold = 16; /* LLD: MAX_NUM_OF_DMAS */ ++ int max_ext_open_dma_treshold = 8; /* LLD: MAX_NUM_OF_EXTRA_DMAS */ ++ ++ int open_dmas_computed = 0; ++ int weighted_remaining_ports = 0; ++ int overflow = 0; ++ bool re_loop = false; ++ ++ /* check input parameters correctness */ ++ ASSERT_COND(p_LnxWrpFmDev != NULL); ++ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info; ++ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info; ++ ASSERT_COND(fm_active_ports_info != NULL); ++ ASSERT_COND(fm_resource_settings_info != NULL); ++ ASSERT_COND(fm_active_ports_info->num_tx_ports == ++ fm_active_ports_info->num_rx_ports); ++ ASSERT_COND(fm_active_ports_info->num_tx25_ports == ++ fm_active_ports_info->num_tx25_ports); ++ ASSERT_COND(fm_active_ports_info->num_tx10_ports == ++ fm_active_ports_info->num_tx10_ports); ++ ASSERT_COND(min_tx_10g_treshold <= max_open_dma_treshold); ++ ASSERT_COND(min_tx_10g_treshold <= max_open_dma_treshold); ++ ++ /* set input parameters */ ++ num_1g_ports = fm_active_ports_info->num_tx_ports; ++ num_2g5_ports = fm_active_ports_info->num_tx25_ports; ++ num_10g_ports = fm_active_ports_info->num_tx10_ports; ++ num_oh_ports = fm_active_ports_info->num_oh_ports; ++ ++ /* compute open DMAs per port */ ++ /* ------------------------------------------------------- */ ++ if (num_10g_ports) { ++ tx_10g_dmas = default_tx_10g_dmas; /* per 10G TX port */ ++ rx_10g_dmas = default_rx_10g_dmas; /* per 10G RX port */ ++ } ++ if (num_oh_ports) ++ oh_dmas = 1; /* per OH port */ ++ ++ /* should this be null? or LLD: ++ DEFAULT_PORT_extraNumOfOpenDmas:10g-8,else 1 */ ++ shared_ext_open_dma = 0; ++ ++ /* based on total number of ports set open DMAs for all other ports */ ++ remaing_dmas = max_fm_open_dma - ++ (oh_dmas * num_oh_ports) - ++ (tx_10g_dmas * num_10g_ports + rx_10g_dmas * num_10g_ports) - ++ shared_ext_open_dma; ++ ++ if (remaing_dmas < 0) { ++ printk(KERN_ALERT ++ "This configuration will not work due to low number" ++ " of open dmas (%u open dmas)...\n", ++ max_fm_open_dma); ++ err = -1; ++ goto precalculated_open_dma_out; ++ } ++ ++ weighted_remaining_ports = ++ /*tx */ num_1g_ports * rx_tx_raport + /*rx */ num_1g_ports + ++ /*tx */ num_2g5_ports * rx_tx_raport + /*rx */ num_2g5_ports; ++ ++ /* compute the other ports */ ++ if (num_1g_ports) { ++ tx_1g_dmas = ++ MAX(MIN ++ (ROUND_DIV ++ (remaing_dmas, weighted_remaining_ports), ++ max_open_dma_treshold), min_tx_1_2g5_treshold); ++ rx_1g_dmas = ++ MAX(MIN ++ (ROUND_DIV ++ ((remaing_dmas * rx_tx_raport), ++ weighted_remaining_ports), ++ max_open_dma_treshold), min_rx_1_2g5_treshold); ++ } ++ if (num_2g5_ports) { ++ tx_2g5_dmas = ++ MAX(MIN ++ (CEIL_DIV(remaing_dmas, weighted_remaining_ports), ++ max_open_dma_treshold), min_tx_1_2g5_treshold); ++ rx_2g5_dmas = ++ MAX(MIN ++ (CEIL_DIV ++ ((remaing_dmas * rx_tx_raport), ++ weighted_remaining_ports), ++ max_open_dma_treshold), min_rx_1_2g5_treshold); ++ ++ } ++ ++ /* Check if these settings is not exceding treshold */ ++ open_dmas_computed = num_1g_ports * tx_1g_dmas + ++ num_1g_ports * rx_1g_dmas + ++ num_2g5_ports * tx_2g5_dmas + ++ num_2g5_ports * rx_2g5_dmas + ++ num_10g_ports * tx_10g_dmas + ++ num_10g_ports * rx_10g_dmas + ++ num_oh_ports * oh_dmas + shared_ext_open_dma; ++ ++ /* overflow-leftover calculus */ ++ overflow = open_dmas_computed - max_fm_open_dma; ++ re_loop = true; ++ while (overflow > 0 && re_loop == true) { ++ re_loop = false; ++ if (num_1g_ports && overflow ++ && rx_1g_dmas > min_rx_1_2g5_treshold) { ++ rx_1g_dmas--; ++ overflow -= num_1g_ports; ++ re_loop = true; ++ } ++ if (num_2g5_ports && overflow ++ && rx_2g5_dmas > min_rx_1_2g5_treshold) { ++ rx_2g5_dmas--; ++ overflow -= num_2g5_ports; ++ re_loop = true; ++ } ++ if (num_10g_ports && overflow ++ && rx_10g_dmas > min_rx_10g_treshold) { ++ rx_10g_dmas--; ++ overflow -= num_10g_ports; ++ re_loop = true; ++ } ++ ++ if (num_1g_ports && overflow ++ && tx_1g_dmas > min_tx_1_2g5_treshold) { ++ tx_1g_dmas--; ++ overflow -= num_1g_ports; ++ re_loop = true; ++ } ++ if (num_2g5_ports && overflow ++ && tx_2g5_dmas > min_tx_1_2g5_treshold) { ++ tx_2g5_dmas--; ++ overflow -= num_2g5_ports; ++ re_loop = true; ++ } ++ if (num_10g_ports && overflow ++ && tx_10g_dmas > min_tx_10g_treshold) { ++ tx_10g_dmas--; ++ overflow -= num_10g_ports; ++ re_loop = true; ++ } ++ } ++ ++ if (overflow > 0) { ++ printk(KERN_ALERT ++ "This configuration will not work due to over open dma" ++ " allocation (%d open dmas)...\n", ++ overflow); ++ err = -1; ++ goto precalculated_open_dma_out; ++ } ++ ++ /* could remain leftovers... e.g. overflow=1, ++ 2ports => leftover=1 => shared=1 */ ++ open_dmas_computed = num_1g_ports * tx_1g_dmas + ++ num_1g_ports * rx_1g_dmas + ++ num_2g5_ports * tx_2g5_dmas + ++ num_2g5_ports * rx_2g5_dmas + ++ num_10g_ports * tx_10g_dmas + ++ num_10g_ports * rx_10g_dmas + ++ num_oh_ports * oh_dmas + shared_ext_open_dma; ++ ++ if (max_fm_open_dma - open_dmas_computed > 0) ++ shared_ext_open_dma = ++ MIN(shared_ext_open_dma + max_fm_open_dma - ++ open_dmas_computed, max_ext_open_dma_treshold); ++ ++ /* set open dmas */ ++ fm_resource_settings_info->tx_1g_dmas = tx_1g_dmas; ++ fm_resource_settings_info->rx_1g_dmas = rx_1g_dmas; ++ fm_resource_settings_info->tx_2g5_dmas = tx_2g5_dmas; ++ fm_resource_settings_info->rx_2g5_dmas = rx_2g5_dmas; ++ fm_resource_settings_info->tx_10g_dmas = tx_10g_dmas; ++ fm_resource_settings_info->rx_10g_dmas = rx_10g_dmas; ++ fm_resource_settings_info->oh_dmas = oh_dmas; ++ fm_resource_settings_info->shared_ext_open_dma = shared_ext_open_dma; ++ ++precalculated_open_dma_out: ++ printk(KERN_INFO " FMAN(%u) open dma settings:\n", ++ p_LnxWrpFmDev->id); ++ printk(KERN_INFO " - Total open dma available(%u)\n", ++ max_fm_open_dma); ++ if (num_1g_ports) { ++ printk(KERN_INFO " - 1G ports TX %u(%u)\n", num_1g_ports, ++ tx_1g_dmas); ++ printk(KERN_INFO " - 1G ports RX %u(%u)\n", num_1g_ports, ++ rx_1g_dmas); ++ } ++ if (num_2g5_ports) { ++ printk(KERN_INFO " - 2.5G ports TX %u(%u)\n", num_2g5_ports, ++ tx_2g5_dmas); ++ printk(KERN_INFO " - 2.5G ports RX %u(%u)\n", num_2g5_ports, ++ tx_2g5_dmas); ++ } ++ if (num_10g_ports) { ++ printk(KERN_INFO " - 10G ports TX %u(%u)\n", num_10g_ports, ++ tx_10g_dmas); ++ printk(KERN_INFO " - 10G ports RX %u(%u)\n", num_10g_ports, ++ rx_10g_dmas); ++ } ++ if (num_oh_ports) ++ printk(KERN_INFO " - OH-HC ports %u(%u)\n", num_oh_ports, ++ oh_dmas); ++ printk(KERN_INFO " - Shared extra open dma(%u)\n", ++ shared_ext_open_dma ? shared_ext_open_dma : 0); ++ ++ return err; ++} ++ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++int fm_config_precalculate_open_dma(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ++ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ struct fm_resource_settings *fm_resource_settings_info = NULL; ++ t_FmPortRsrc numOfOpenDmas; ++ t_Error errCode; ++ ++ ASSERT_COND(p_LnxWrpFmDev != NULL); ++ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info; ++ ++ memset(&numOfOpenDmas, 0, sizeof(t_FmPortRsrc)); ++ ++/* IF 1G PORT */ ++ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX) ++ numOfOpenDmas.num = fm_resource_settings_info->tx_1g_dmas; ++ else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_RX) ++ numOfOpenDmas.num = fm_resource_settings_info->rx_1g_dmas; ++/* IF 2.5G PORT*/ ++ /* TODO: Not supported by LLD yet. */ ++ ++/* IF 10G PORT */ ++ else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_TX_10G) ++ numOfOpenDmas.num = fm_resource_settings_info->tx_10g_dmas; ++ else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_RX_10G) ++ numOfOpenDmas.num = fm_resource_settings_info->rx_10g_dmas; ++/* IF OH PORT */ ++ else ++ numOfOpenDmas.num = fm_resource_settings_info->oh_dmas; ++ ++ numOfOpenDmas.extra = fm_resource_settings_info->shared_ext_open_dma; ++ ++ errCode = FM_PORT_ConfigNumOfOpenDmas(p_LnxWrpFmPortDev->h_Dev, ++ &numOfOpenDmas); ++ if (errCode != E_OK) { ++ printk(KERN_WARNING ++ "FM_PORT_SetNumOfOpenDmas failed (errCode:0x%2x)", ++ errCode); ++ return -EIO; ++ } ++ ++ return 0; ++} ++#endif /*if !defined(FMAN_RESOURCES_UNIT_TEST)*/ ++ ++/* Compute FMan tnums based on available tnums and number of ports. ++ Set defaults (minim tresholds) and then distribute leftovers.*/ ++int fm_precalculate_tnums(t_LnxWrpFmDev *p_LnxWrpFmDev, int max_fm_tnums) ++{ ++ /* input parameters */ ++ struct fm_active_ports *fm_active_ports_info = NULL; ++ int num_1g_ports = 0; ++ int num_2g5_ports = 0; ++ int num_10g_ports = 0; ++ int num_oh_ports = 0; ++ ++ /* output parameters */ ++ struct fm_resource_settings *fm_resource_settings_info = NULL; ++ int tx_1g_tnums = 0, rx_1g_tnums = 0; ++ int tx_2g5_tnums = 0, rx_2g5_tnums = 0; ++ int tx_10g_tnums = 0, rx_10g_tnums = 0; ++ int oh_tnums = 0; ++ int shared_ext_tnums = 0; ++ int err = 0; ++ ++ /* open dma calculus */ ++ int default_and_treshold_rx_tx_10g_tnums = 16; /* DPDE_10g */ ++ int default_and_treshold_rx_tx_1g_2g5_tnums = 4; /* DPDE_1g */ ++ int default_and_treshold_oh_tnums = 2; /* Hell knows why */ ++ int max_tnums_treshold = 64; /* LLD: MAX_NUM_OF_TASKS */ ++ int max_ext_tnums_treshold = 8; /* LLD: MAX_NUM_OF_EXTRA_TASKS */ ++ int remaing_tnums = 0; ++ int tnums_computed = 0; ++ int leftovers = 0; ++ bool re_loop = true; ++ ++ /* check input parameters correctness */ ++ ASSERT_COND(p_LnxWrpFmDev != NULL); ++ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info; ++ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info; ++ ASSERT_COND(fm_active_ports_info != NULL); ++ ASSERT_COND(fm_resource_settings_info != NULL); ++ ASSERT_COND(fm_active_ports_info->num_tx_ports == ++ fm_active_ports_info->num_rx_ports); ++ ASSERT_COND(fm_active_ports_info->num_tx25_ports == ++ fm_active_ports_info->num_tx25_ports); ++ ASSERT_COND(fm_active_ports_info->num_tx10_ports == ++ fm_active_ports_info->num_tx10_ports); ++ ++ /* set input parameters */ ++ num_1g_ports = fm_active_ports_info->num_tx_ports; ++ num_2g5_ports = fm_active_ports_info->num_tx25_ports; ++ num_10g_ports = fm_active_ports_info->num_tx10_ports; ++ num_oh_ports = fm_active_ports_info->num_oh_ports; ++ ++ /* compute FMan TNUMs per port */ ++ /* ------------------------------------------------------- */ ++ if (num_1g_ports) { ++ tx_1g_tnums = default_and_treshold_rx_tx_1g_2g5_tnums; ++ rx_1g_tnums = default_and_treshold_rx_tx_1g_2g5_tnums; ++ } ++ if (num_2g5_ports) { ++ tx_2g5_tnums = default_and_treshold_rx_tx_1g_2g5_tnums; ++ rx_2g5_tnums = default_and_treshold_rx_tx_1g_2g5_tnums; ++ } ++ if (num_10g_ports) { ++ tx_10g_tnums = default_and_treshold_rx_tx_10g_tnums; ++ rx_10g_tnums = default_and_treshold_rx_tx_10g_tnums; ++ } ++ if (num_oh_ports) ++ oh_tnums = default_and_treshold_oh_tnums; ++ ++ shared_ext_tnums = num_10g_ports ? ++ max_ext_tnums_treshold : 2; /* DEFAULT_PORT_extraNumOfTasks */ ++ ++ /* based on total number of ports set open DMAs for all other ports */ ++ remaing_tnums = max_fm_tnums - ++ (oh_tnums * num_oh_ports) - ++ (tx_1g_tnums * num_1g_ports + rx_1g_tnums * num_1g_ports) - ++ (tx_2g5_tnums * num_2g5_ports + rx_2g5_tnums * num_2g5_ports) - ++ (tx_10g_tnums * num_10g_ports + rx_10g_tnums * num_10g_ports) - ++ shared_ext_tnums; ++ ++ if (remaing_tnums < 0) { ++ printk(KERN_ALERT ++ "This configuration will not work due to low number" ++ " of tnums (%u tnums) and number of total ports" ++ " available...\n", ++ max_fm_tnums); ++ err = -1; ++ goto precalculated_tnums_out; ++ } ++ ++ leftovers = remaing_tnums; ++ re_loop = true; ++ while (leftovers > 0 && re_loop == true) { ++ re_loop = false; ++ if (num_10g_ports && (leftovers - (int) num_10g_ports) >= 0 ++ && (rx_10g_tnums < max_tnums_treshold)) { ++ rx_10g_tnums++; ++ leftovers -= num_10g_ports; ++ re_loop = true; ++ } ++ ++ if (num_10g_ports && (leftovers - (int) num_10g_ports) >= 0 ++ && (tx_10g_tnums < max_tnums_treshold)) { ++ tx_10g_tnums++; ++ leftovers -= num_10g_ports; ++ re_loop = true; ++ } ++ ++ if (num_2g5_ports && (leftovers - (int) num_2g5_ports) >= 0 ++ && (rx_2g5_tnums < max_tnums_treshold)) { ++ rx_2g5_tnums++; ++ leftovers -= num_2g5_ports; ++ re_loop = true; ++ } ++ ++ if (num_2g5_ports && (leftovers - (int) num_2g5_ports) >= 0 ++ && (tx_2g5_tnums < max_tnums_treshold)) { ++ tx_2g5_tnums++; ++ leftovers -= num_2g5_ports; ++ re_loop = true; ++ } ++ ++ if (num_1g_ports && (leftovers - (int) num_1g_ports) >= 0 ++ && (rx_1g_tnums < max_tnums_treshold)) { ++ rx_1g_tnums++; ++ leftovers -= num_1g_ports; ++ re_loop = true; ++ } ++ ++ if (num_1g_ports && (leftovers - (int) num_1g_ports) >= 0 ++ && (tx_1g_tnums < max_tnums_treshold)) { ++ tx_1g_tnums++; ++ leftovers -= num_1g_ports; ++ re_loop = true; ++ } ++ } ++ ++ tnums_computed = ++ num_1g_ports * tx_1g_tnums + ++ num_1g_ports * rx_1g_tnums + ++ num_2g5_ports * tx_2g5_tnums + ++ num_2g5_ports * rx_2g5_tnums + ++ num_10g_ports * tx_10g_tnums + ++ num_10g_ports * rx_10g_tnums + ++ num_oh_ports * oh_tnums + ++ shared_ext_tnums; ++ ++ if (leftovers > 0) ++ shared_ext_tnums = ++ MIN(shared_ext_tnums + max_fm_tnums - tnums_computed, ++ max_ext_tnums_treshold); ++ ++ ASSERT_COND((oh_tnums * num_oh_ports) + ++ (tx_1g_tnums * num_1g_ports + rx_1g_tnums * num_1g_ports) + ++ (tx_2g5_tnums * num_2g5_ports + ++ rx_2g5_tnums * num_2g5_ports) + ++ (tx_10g_tnums * num_10g_ports + ++ rx_10g_tnums * num_10g_ports) + shared_ext_tnums <= ++ max_fm_tnums); ++ ++ /* set computed tnums */ ++ fm_resource_settings_info->tx_1g_tnums = tx_1g_tnums; ++ fm_resource_settings_info->rx_1g_tnums = rx_1g_tnums; ++ fm_resource_settings_info->tx_2g5_tnums = tx_2g5_tnums; ++ fm_resource_settings_info->rx_2g5_tnums = rx_2g5_tnums; ++ fm_resource_settings_info->tx_10g_tnums = tx_10g_tnums; ++ fm_resource_settings_info->rx_10g_tnums = rx_10g_tnums; ++ fm_resource_settings_info->oh_tnums = oh_tnums; ++ fm_resource_settings_info->shared_ext_tnums = shared_ext_tnums; ++ ++precalculated_tnums_out: ++ printk(KERN_INFO " FMAN(%u) Tnums settings:\n", p_LnxWrpFmDev->id); ++ printk(KERN_INFO " - Total Tnums available(%u)\n", max_fm_tnums); ++ if (num_1g_ports) { ++ printk(KERN_INFO " - 1G ports TX %u(%u)\n", num_1g_ports, ++ tx_1g_tnums); ++ printk(KERN_INFO " - 1G ports RX %u(%u)\n", num_1g_ports, ++ rx_1g_tnums); ++ } ++ if (num_2g5_ports) { ++ printk(KERN_INFO " - 2.5G ports TX %u(%u)\n", num_2g5_ports, ++ tx_2g5_tnums); ++ printk(KERN_INFO " - 2.5G ports RX %u(%u)\n", num_2g5_ports, ++ rx_2g5_tnums); ++ } ++ if (num_10g_ports) { ++ printk(KERN_INFO " - 10G ports TX %u(%u)\n", num_10g_ports, ++ tx_10g_tnums); ++ printk(KERN_INFO " - 10G ports RX %u(%u)\n", num_10g_ports, ++ rx_10g_tnums); ++ } ++ if (num_oh_ports) ++ printk(KERN_INFO " - OH-HC ports %u(%u)\n", num_oh_ports, ++ oh_tnums); ++ printk(KERN_INFO " - Shared extra tnums(%u)\n", shared_ext_tnums); ++ ++ return err; ++} ++ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++int fm_config_precalculate_tnums(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ++ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ struct fm_resource_settings *fm_resource_settings_info = NULL; ++ t_FmPortRsrc numOfTask; ++ t_Error errCode; ++ ++ ASSERT_COND(p_LnxWrpFmDev != NULL); ++ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info; ++ ++ memset(&numOfTask, 0, sizeof(t_FmPortRsrc)); ++ ++/* IF 1G PORT */ ++ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX) ++ numOfTask.num = fm_resource_settings_info->tx_1g_tnums; ++ else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_RX) ++ numOfTask.num = fm_resource_settings_info->rx_1g_tnums; ++/* IF 2.5G PORT*/ ++ /* TODO: Not supported by LLD yet. */ ++ ++/* IF 10G PORT */ ++ else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_TX_10G) ++ numOfTask.num = fm_resource_settings_info->tx_10g_tnums; ++ else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_RX_10G) ++ numOfTask.num = fm_resource_settings_info->rx_10g_tnums; ++/* IF OH PORT */ ++ else ++ numOfTask.num = fm_resource_settings_info->oh_dmas; ++ ++ numOfTask.extra = fm_resource_settings_info->shared_ext_tnums; ++ ++ errCode = FM_PORT_ConfigNumOfTasks(p_LnxWrpFmPortDev->h_Dev, &numOfTask); ++ if (errCode != E_OK) { ++ printk(KERN_WARNING ++ "FM_PORT_SetNumOfTasks failed (errCode:0x%2x)", ++ errCode); ++ return -EIO; ++ } ++ ++ return 0; ++} ++#endif /*if !defined(FMAN_RESOURCES_UNIT_TEST)*/ +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources.h b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources.h +new file mode 100644 +index 0000000..1b72e1d +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources.h +@@ -0,0 +1,121 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_resources.h ++ ++ @Description FMD wrapper resource allocation functions. ++ ++*/ ++ ++#ifndef LNXWRP_RESOURCES_H_ ++#define LNXWRP_RESOURCES_H_ ++ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++#include "lnxwrp_fm.h" ++#else ++#include "lnxwrp_resources_ut.h" ++#endif ++ ++#define ROUND(X) ((2*(X)+1)/2) ++#define CEIL(X) ((X)+1) ++/* #define ROUND_DIV(X, Y) (((X)+(Y)/2)/(Y)) */ ++#define ROUND_DIV(X, Y) ((2*(X)+(Y))/(2*(Y))) ++#define CEIL_DIV(X, Y) (((X)+(Y)-1)/(Y)) ++ ++/* used for resource calculus */ ++#define DPDE_1G 2 /* DQDP 1g - from LLD: ++ DEFAULT_PORT_txFifoDeqPipelineDepth_1G */ ++#define DPDE_10G 8 /* DQDP 10g - from LLD: ++ DEFAULT_PORT_txFifoDeqPipelineDepth_10G */ ++ ++int fm_set_active_fman_ports(struct platform_device *of_dev, ++ t_LnxWrpFmDev *p_LnxWrpFmDev); ++ ++/* Calculate the fifosize based on MURAM allocation, number of ports, dpde ++ * value and s/g software support (! Kernel does not suport s/g). ++ * ++ * Algorithm summary: ++ * - Calculate the the minimum fifosize required for every type of port ++ * (TX,RX for 1G, 2.5G and 10G). ++ * - Set TX the minimum fifosize required. ++ * - Distribute the remaining buffers (after all TX were set) to RX ports ++ * based on: ++ * 1G RX = Remaining_buffers * 1/(1+2.5+10) ++ * 2.5G RX = Remaining_buffers * 2.5/(1+2.5+10) ++ * 10G RX = Remaining_buffers * 10/(1+2.5+10) ++ * - if the RX is smaller than the minimum required, then set the minimum ++ * required ++ * - In the end distribuite the leftovers if there are any (due to ++ * unprecise calculus) or if over allocation cat some buffers from all RX ++ * ports w/o pass over minimum required treshold, but if there must be ++ * pass the treshold in order to cat the over allocation ,then this ++ * configuration can not be set - KERN_ALERT. ++*/ ++int fm_precalculate_fifosizes(t_LnxWrpFmDev *p_LnxWrpFmDev, ++ int muram_fifo_size); ++ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++int fm_config_precalculate_fifosize(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev); ++#endif ++ ++/* Compute FMan open DMA based on total number of open DMAs and ++ * number of available fman ports. ++ * ++ * By default 10g ports are set to input parameters. The other ports ++ * tries to keep the proportion rx=2tx open dmas or tresholds. ++ * ++ * If leftovers, then those will be set as shared. ++ * ++ * If after computing overflow appears, then it decrements open dma ++ * for all ports w/o cross the tresholds. If the tresholds are meet ++ * and is still overflow, then it returns error. ++*/ ++int fm_precalculate_open_dma(t_LnxWrpFmDev *p_LnxWrpFmDev, ++ int max_fm_open_dma, ++ int default_tx_10g_dmas, ++ int default_rx_10g_dmas, ++ int min_tx_10g_treshold, int min_rx_10g_treshold); ++ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++int fm_config_precalculate_open_dma(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev); ++#endif ++ ++/* Compute FMan tnums based on available tnums and number of ports. ++ * Set defaults (minim tresholds) and then distribute leftovers.*/ ++int fm_precalculate_tnums(t_LnxWrpFmDev *p_LnxWrpFmDev, int max_fm_tnums); ++ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++int fm_config_precalculate_tnums(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev); ++#endif ++ ++#endif /* LNXWRP_RESOURCES_H_ */ +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources_ut.c b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources_ut.c +new file mode 100644 +index 0000000..6c06a5a +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources_ut.c +@@ -0,0 +1,191 @@ ++/* Copyright (c) 2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "lnxwrp_resources.h" ++#include "lnxwrp_resources_ut.h" ++ ++#define KILOBYTE 0x400 /* 1024 */ ++ ++typedef enum e_board_type { ++ e_p3041, ++ e_p4080, ++ e_p5020, ++ e_p1023 ++} e_board_type; ++ ++uint8_t board_type; ++uint32_t muram_size = 0; ++uint32_t dmas_num = 0; ++uint32_t task_num = 0; ++uint32_t frame_size = 0; ++uint32_t oh_num = 0; ++uint32_t num_ports_1g = 0; ++uint32_t num_ports_10g = 0; ++uint32_t num_ports_2g5 = 0; ++uint32_t fsl_fman_phy_maxfrm = 0; ++uint32_t dpa_rx_extra_headroom = 0; ++ ++void show_help(void){ ++ printf(" help: \n"); ++ printf(" -b -f -o -g1" ++ " -g10 -g25 \n"); ++ printf(" Maxim num of DMAS availbale: P3/P4/P5:32 , P1023:16 \n"); ++ printf(" Maxim num of TNUMs availbale: P3/P4/P5:128, P1023:32 \n"); ++ printf(" Muram size: P3/P4/P5:160K, P1023:64K \n"); ++ printf(" Number of ports:\n"); ++ printf(" P3/P5: 5p 1g, 1p 10g, 7p oh \n"); ++ printf(" P4 : 4p 1g, 1p 10g, 7p oh \n"); ++ printf(" P1 : 2p 1g, 0p 10g, 4p oh \n"); ++ printf(" MTU: Default:1522, Jumbo:9600 \n"); ++} ++ ++int fm_set_param(t_LnxWrpFmDev *p_LnxWrpFmDev) { ++ struct fm_active_ports *fm_active_ports_info = NULL; ++ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info; ++ ++ switch(board_type){ ++ case e_p3041: ++ case e_p5020: ++ muram_size = 160*KILOBYTE; ++ dmas_num = 32; ++ task_num = 128; ++ if ((num_ports_1g+num_ports_2g5) > 5 || num_ports_10g > 1 || oh_num > 7) ++ goto err_fm_set_param; ++ break; ++ case e_p4080: ++ muram_size = 160*KILOBYTE; ++ dmas_num = 32; ++ task_num = 128; ++ if ((num_ports_1g+num_ports_2g5) > 4 || num_ports_10g > 1 || oh_num > 7) ++ goto err_fm_set_param; ++ break; ++ case e_p1023: ++ muram_size = 64*KILOBYTE; ++ dmas_num = 16; ++ task_num = 128; ++ if ((num_ports_1g+num_ports_2g5) > 2 || oh_num > 4) ++ goto err_fm_set_param; ++ break; ++ default: ++ goto err_fm_set_param; ++ break; ++ } ++ ++ p_LnxWrpFmDev->id = 0; ++ fsl_fman_phy_maxfrm = frame_size; ++ dpa_rx_extra_headroom = 0; /* ATTENTION: can be != 0 */ ++ fm_active_ports_info->num_oh_ports = oh_num; ++ fm_active_ports_info->num_tx_ports = num_ports_1g; ++ fm_active_ports_info->num_rx_ports = num_ports_1g; ++ fm_active_ports_info->num_tx25_ports = num_ports_2g5; ++ fm_active_ports_info->num_rx25_ports = num_ports_2g5; ++ fm_active_ports_info->num_tx10_ports = num_ports_10g; ++ fm_active_ports_info->num_rx10_ports = num_ports_10g; ++ ++ return 0; ++ ++err_fm_set_param: ++ printf(" ERR: To many ports!!! \n"); ++ return -1; ++} ++ ++int main (int argc, char *argv[]){ ++ t_LnxWrpFmDev LnxWrpFmDev; ++ t_LnxWrpFmDev *p_LnxWrpFmDev = &LnxWrpFmDev; ++ int tokens_cnt = 1; ++ ++ char *token = NULL; ++ ++ while(tokens_cnt < argc) ++ { ++ token = argv[tokens_cnt++]; ++ if (strcmp(token, "-b") == 0){ ++ if(strcmp(argv[tokens_cnt],"p3") == 0) ++ board_type = e_p3041; ++ else if(strcmp(argv[tokens_cnt],"p4") == 0) ++ board_type = e_p4080; ++ else if(strcmp(argv[tokens_cnt],"p5") == 0) ++ board_type = e_p5020; ++ else if(strcmp(argv[tokens_cnt],"p1") == 0) ++ board_type = e_p1023; ++ else ++ show_help(); ++ tokens_cnt++; ++ } ++ else if(strcmp(token, "-d") == 0){ ++ dmas_num = atoi(argv[tokens_cnt++]); ++ } ++ else if(strcmp(token, "-t") == 0) ++ task_num = atoi(argv[tokens_cnt++]); ++ else if(strcmp(token, "-f") == 0) ++ frame_size = atoi(argv[tokens_cnt++]); ++ else if(strcmp(token, "-o") == 0) ++ oh_num = atoi(argv[tokens_cnt++]); ++ else if(strcmp(token, "-g1") == 0) ++ num_ports_1g = atoi(argv[tokens_cnt++]); ++ else if(strcmp(token, "-g10") == 0) ++ num_ports_10g = atoi(argv[tokens_cnt++]); ++ else if(strcmp(token, "-g25") == 0) ++ num_ports_2g5 = atoi(argv[tokens_cnt++]); ++ else { ++ show_help(); ++ return -1; ++ } ++ } ++ ++ if(fm_set_param(p_LnxWrpFmDev) < 0){ ++ show_help(); ++ return -1; ++ } ++ ++ if(fm_precalculate_fifosizes( ++ p_LnxWrpFmDev, ++ 128*KILOBYTE) ++ != 0) ++ return -1; ++ if(fm_precalculate_open_dma( ++ p_LnxWrpFmDev, ++ dmas_num, /* max open dmas:dpaa_integration_ext.h */ ++ FM_DEFAULT_TX10G_OPENDMA, /* default TX 10g open dmas */ ++ FM_DEFAULT_RX10G_OPENDMA, /* default RX 10g open dmas */ ++ FM_10G_OPENDMA_MIN_TRESHOLD,/* TX 10g minimum treshold */ ++ FM_10G_OPENDMA_MIN_TRESHOLD)/* RX 10g minimum treshold */ ++ != 0) ++ return -1; ++ if(fm_precalculate_tnums( ++ p_LnxWrpFmDev, ++ task_num) /* max TNUMS: dpa integration file. */ ++ != 0) ++ return -1; ++ ++ return 0; ++} +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources_ut.h b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources_ut.h +new file mode 100644 +index 0000000..063946e +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources_ut.h +@@ -0,0 +1,144 @@ ++/* Copyright (c) 2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 FM_RESS_TEST_H_ ++#define FM_RESS_TEST_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define _Packed ++#define _PackedType __attribute__ ((packed)) ++#define MAX(x, y) (((x) > (y)) ? (x) : (y)) ++#define MIN(x, y) (((x) < (y)) ? (x) : (y)) ++#define KERN_ALERT "" ++#define KERN_INFO "" ++#define ASSERT_COND assert ++#define printk printf ++#define NET_IP_ALIGN 0 ++#define FM_FIFO_ALLOCATION_OLD_ALG ++ ++#if defined(CONFIG_FMAN_DISABLE_OH_AND_DISTRIBUTE_RESOURCES) ++#define FM_10G_OPENDMA_MIN_TRESHOLD 8 /* 10g minimum treshold if only HC is enabled and no OH port enabled */ ++#define FM_OPENDMA_RX_TX_RAPORT 2 /* RX = 2*TX */ ++#else ++#define FM_10G_OPENDMA_MIN_TRESHOLD 7 /* 10g minimum treshold if 7 OH ports are enabled */ ++#define FM_OPENDMA_RX_TX_RAPORT 1 /* RX = TX */ ++#endif ++#define FM_DEFAULT_TX10G_OPENDMA 8 /* default TX 10g open dmas */ ++#define FM_DEFAULT_RX10G_OPENDMA 8 /* default RX 10g open dmas */ ++ ++/* information about all active ports for an FMan. ++ * !Some ports may be disabled by u-boot, thus will not be available */ ++struct fm_active_ports { ++ uint32_t num_oh_ports; ++ uint32_t num_tx_ports; ++ uint32_t num_rx_ports; ++ uint32_t num_tx25_ports; ++ uint32_t num_rx25_ports; ++ uint32_t num_tx10_ports; ++ uint32_t num_rx10_ports; ++}; ++ ++/* FMan resources precalculated at fm probe based ++ * on available FMan port. */ ++struct fm_resource_settings { ++ /* buffers - fifo sizes */ ++ uint32_t tx1g_num_buffers; ++ uint32_t rx1g_num_buffers; ++ uint32_t tx2g5_num_buffers; /* Not supported yet by LLD */ ++ uint32_t rx2g5_num_buffers; /* Not supported yet by LLD */ ++ uint32_t tx10g_num_buffers; ++ uint32_t rx10g_num_buffers; ++ uint32_t oh_num_buffers; ++ uint32_t shared_ext_buffers; ++ ++ ++ /* open DMAs */ ++ uint32_t tx_1g_dmas; ++ uint32_t rx_1g_dmas; ++ uint32_t tx_2g5_dmas; /* Not supported yet by LLD */ ++ uint32_t rx_2g5_dmas; /* Not supported yet by LLD */ ++ uint32_t tx_10g_dmas; ++ uint32_t rx_10g_dmas; ++ uint32_t oh_dmas; ++ uint32_t shared_ext_open_dma; ++ ++ /* Tnums */ ++ uint32_t tx_1g_tnums; ++ uint32_t rx_1g_tnums; ++ uint32_t tx_2g5_tnums; /* Not supported yet by LLD */ ++ uint32_t rx_2g5_tnums; /* Not supported yet by LLD */ ++ uint32_t tx_10g_tnums; ++ uint32_t rx_10g_tnums; ++ uint32_t oh_tnums; ++ uint32_t shared_ext_tnums; ++}; ++ ++typedef struct { ++ uint8_t id; ++ struct fm_active_ports fm_active_ports_info; ++ struct fm_resource_settings fm_resource_settings_info; ++} t_LnxWrpFmDev; ++ ++typedef struct { ++ uint8_t id; ++} t_LnxWrpFmPortDev; ++ ++typedef _Packed struct t_FmPrsResult { ++ volatile uint8_t lpid; /**< Logical port id */ ++ volatile uint8_t shimr; /**< Shim header result */ ++ volatile uint16_t l2r; /**< Layer 2 result */ ++ volatile uint16_t l3r; /**< Layer 3 result */ ++ volatile uint8_t l4r; /**< Layer 4 result */ ++ volatile uint8_t cplan; /**< Classification plan id */ ++ volatile uint16_t nxthdr; /**< Next Header */ ++ volatile uint16_t cksum; /**< Checksum */ ++ volatile uint32_t lcv; /**< LCV */ ++ volatile uint8_t shim_off[3]; /**< Shim offset */ ++ volatile uint8_t eth_off; /**< ETH offset */ ++ volatile uint8_t llc_snap_off; /**< LLC_SNAP offset */ ++ volatile uint8_t vlan_off[2]; /**< VLAN offset */ ++ volatile uint8_t etype_off; /**< ETYPE offset */ ++ volatile uint8_t pppoe_off; /**< PPP offset */ ++ volatile uint8_t mpls_off[2]; /**< MPLS offset */ ++ volatile uint8_t ip_off[2]; /**< IP offset */ ++ volatile uint8_t gre_off; /**< GRE offset */ ++ volatile uint8_t l4_off; /**< Layer 4 offset */ ++ volatile uint8_t nxthdr_off; /**< Parser end point */ ++} _PackedType t_FmPrsResult; ++ ++#endif +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources_ut.make b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources_ut.make +new file mode 100644 +index 0000000..58009cd +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_resources_ut.make +@@ -0,0 +1,28 @@ ++CC=gcc ++ ++LNXWRP_RESS_UT=lnxwrp_resources_ut ++OBJ=lnxwrp_resources ++ ++INC_PATH= ++LIB_PATH= ++ ++INC=$(addprefix -I,$(INC_PATH)) ++LIB=$(addprefix -L,$(LIB_PATH)) ++ ++CFLAGS= -gdwarf-2 -g -O0 -Wall ++XFLAGS= -DFMAN_RESOURCES_UNIT_TEST ++ ++all: $(LNXWRP_RESS_UT) ++ ++$(LNXWRP_RESS_UT):$(addsuffix .o,$(OBJ)) $(LNXWRP_RESS_UT).o ++ $(CC) -o $(LNXWRP_RESS_UT) $(LNXWRP_RESS_UT).o $(addsuffix .o,$(OBJ)) ++ ++%.o: %.c ++ @(echo " (CC) $@") ++ @($(CC) $(INC) $(CFLAGS) $(XFLAGS) -o $(@) -c $<) ++ ++.PHONY: clean ++ ++clean: ++ rm -f *.o ++ rm -f $(LNXWRP_RESS_UT) +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs.c b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs.c +new file mode 100644 +index 0000000..3f122b5 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs.c +@@ -0,0 +1,60 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_sysfs.c ++ ++ @Description FM wrapper sysfs related functions. ++ ++*/ ++ ++#include ++#include "lnxwrp_sysfs.h" ++ ++uint8_t fm_find_statistic_counter_by_name(const char *attr_name, ++ const struct SysfsStats_t *sysfs_stats, ++ uint8_t *offset) ++{ ++ int i = 0; ++ ++ while (sysfs_stats[i].statisticName != NULL) { ++ if (strcmp(sysfs_stats[i].statisticName, attr_name) == 0) { ++ if (offset != NULL) ++ *offset = i; ++ return sysfs_stats[i].statisticCounter; ++ } ++ ++ i++; ++ } ++ WARN(1, "FMD: Should never get here!"); ++ return 0; ++} +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs.h b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs.h +new file mode 100644 +index 0000000..67cb2b0 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs.h +@@ -0,0 +1,67 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_sysfs.h ++ ++ @Description FM sysfs functions. ++ ++*/ ++ ++#ifndef LNXWRP_SYSFS_H_ ++#define LNXWRP_SYSFS_H_ ++ ++/* Linux Headers ------------------- */ ++#include ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++#include ++#include ++ ++struct SysfsStats_t { ++ const char *statisticName; ++ uint8_t statisticCounter; ++}; ++ ++uint8_t fm_find_statistic_counter_by_name(const char *attr_name, ++ const struct SysfsStats_t *sysfs_stats, ++ uint8_t *offset); ++ ++#endif /* LNXWRP_SYSFS_H_ */ +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs_fm.c b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs_fm.c +new file mode 100644 +index 0000000..2cfc0b9 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs_fm.c +@@ -0,0 +1,573 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_sysfs_fm.c ++ ++ @Description FM sysfs related functions. ++ ++*/ ++ ++#include "lnxwrp_sysfs.h" ++#include "lnxwrp_fm.h" ++ ++enum e_FmDmaMatchStatistics { ++ e_FM_DMA_COUNTERS_CMQ_NOT_EMPTY, ++ e_FM_DMA_COUNTERS_BUS_ERROR, ++ e_FM_DMA_COUNTERS_READ_BUF_ECC_ERROR, ++ e_FM_DMA_COUNTERS_WRITE_BUF_ECC_SYS_ERROR, ++ e_FM_DMA_COUNTERS_WRITE_BUF_ECC_FM_ERROR ++}; ++ ++static const struct SysfsStats_t fmSysfsStats[] = { ++ /* FM statistics */ ++ { ++ .statisticName = "enq_total_frame", ++ .statisticCounter = e_FM_COUNTERS_ENQ_TOTAL_FRAME, ++ }, ++ { ++ .statisticName = "deq_total_frame", ++ .statisticCounter = e_FM_COUNTERS_DEQ_TOTAL_FRAME, ++ }, ++ { ++ .statisticName = "deq_0", ++ .statisticCounter = e_FM_COUNTERS_DEQ_0, ++ }, ++ { ++ .statisticName = "deq_1", ++ .statisticCounter = e_FM_COUNTERS_DEQ_1, ++ }, ++ { ++ .statisticName = "deq_2", ++ .statisticCounter = e_FM_COUNTERS_DEQ_2, ++ }, ++ { ++ .statisticName = "deq_3", ++ .statisticCounter = e_FM_COUNTERS_DEQ_3, ++ }, ++ { ++ .statisticName = "deq_from_default", ++ .statisticCounter = e_FM_COUNTERS_DEQ_FROM_DEFAULT, ++ }, ++ { ++ .statisticName = "deq_from_context", ++ .statisticCounter = e_FM_COUNTERS_DEQ_FROM_CONTEXT, ++ }, ++ { ++ .statisticName = "deq_from_fd", ++ .statisticCounter = e_FM_COUNTERS_DEQ_FROM_FD, ++ }, ++ { ++ .statisticName = "deq_confirm", ++ .statisticCounter = e_FM_COUNTERS_DEQ_CONFIRM, ++ }, ++ /* FM:DMA statistics */ ++ { ++ .statisticName = "cmq_not_empty", ++ .statisticCounter = e_FM_DMA_COUNTERS_CMQ_NOT_EMPTY, ++ }, ++ { ++ .statisticName = "bus_error", ++ .statisticCounter = e_FM_DMA_COUNTERS_BUS_ERROR, ++ }, ++ { ++ .statisticName = "read_buf_ecc_error", ++ .statisticCounter = e_FM_DMA_COUNTERS_READ_BUF_ECC_ERROR, ++ }, ++ { ++ .statisticName = "write_buf_ecc_sys_error", ++ .statisticCounter = e_FM_DMA_COUNTERS_WRITE_BUF_ECC_SYS_ERROR, ++ }, ++ { ++ .statisticName = "write_buf_ecc_fm_error", ++ .statisticCounter = e_FM_DMA_COUNTERS_WRITE_BUF_ECC_FM_ERROR, ++ }, ++ /* FM:PCD statistics */ ++ { ++ .statisticName = "pcd_kg_total", ++ .statisticCounter = e_FM_PCD_KG_COUNTERS_TOTAL, ++ }, ++ { ++ .statisticName = "pcd_plcr_yellow", ++ .statisticCounter = e_FM_PCD_PLCR_COUNTERS_YELLOW, ++ }, ++ { ++ .statisticName = "pcd_plcr_red", ++ .statisticCounter = e_FM_PCD_PLCR_COUNTERS_RED, ++ }, ++ { ++ .statisticName = "pcd_plcr_recolored_to_red", ++ .statisticCounter = e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED, ++ }, ++ { ++ .statisticName = "pcd_plcr_recolored_to_yellow", ++ .statisticCounter = e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW, ++ }, ++ { ++ .statisticName = "pcd_plcr_total", ++ .statisticCounter = e_FM_PCD_PLCR_COUNTERS_TOTAL, ++ }, ++ { ++ .statisticName = "pcd_plcr_length_mismatch", ++ .statisticCounter = e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH, ++ }, ++ { ++ .statisticName = "pcd_prs_parse_dispatch", ++ .statisticCounter = e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH, ++ }, ++ { ++ .statisticName = "pcd_prs_l2_parse_result_returned", ++ .statisticCounter = e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED, ++ }, ++ { ++ .statisticName = "pcd_prs_l3_parse_result_returned", ++ .statisticCounter = e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED, ++ }, ++ { ++ .statisticName = "pcd_prs_l4_parse_result_returned", ++ .statisticCounter = e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED, ++ }, ++ { ++ .statisticName = "pcd_prs_shim_parse_result_returned", ++ .statisticCounter = e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED, ++ }, ++ { ++ .statisticName = "pcd_prs_l2_parse_result_returned_with_err", ++ .statisticCounter = ++ e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR, ++ }, ++ { ++ .statisticName = "pcd_prs_l3_parse_result_returned_with_err", ++ .statisticCounter = ++ e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR, ++ }, ++ { ++ .statisticName = "pcd_prs_l4_parse_result_returned_with_err", ++ .statisticCounter = ++ e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR, ++ }, ++ { ++ .statisticName = "pcd_prs_shim_parse_result_returned_with_err", ++ .statisticCounter = ++ e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR, ++ }, ++ { ++ .statisticName = "pcd_prs_soft_prs_cycles", ++ .statisticCounter = e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES, ++ }, ++ { ++ .statisticName = "pcd_prs_soft_prs_stall_cycles", ++ .statisticCounter = e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES, ++ }, ++ { ++ .statisticName = "pcd_prs_hard_prs_cycle_incl_stall_cycles", ++ .statisticCounter = ++ e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES, ++ }, ++ { ++ .statisticName = "pcd_prs_muram_read_cycles", ++ .statisticCounter = e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES, ++ }, ++ { ++ .statisticName = "pcd_prs_muram_read_stall_cycles", ++ .statisticCounter = e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES, ++ }, ++ { ++ .statisticName = "pcd_prs_muram_write_cycles", ++ .statisticCounter = e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES, ++ }, ++ { ++ .statisticName = "pcd_prs_muram_write_stall_cycles", ++ .statisticCounter = e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES, ++ }, ++ { ++ .statisticName = "pcd_prs_fpm_command_stall_cycles", ++ .statisticCounter = e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES, ++ }, ++ {} ++}; ++ ++/* Fm stats and regs dumps via sysfs */ ++static ssize_t show_fm_dma_stats(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL; ++ t_FmDmaStatus fmDmaStatus; ++ unsigned long flags = 0; ++ unsigned n = 0; ++ uint8_t counter_value = 0, counter = 0; ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_LnxWrpFmDev == NULL)) ++ return -EINVAL; ++ ++ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_Dev) ++ return -EIO; ++ ++ counter = fm_find_statistic_counter_by_name( ++ attr->attr.name, ++ fmSysfsStats, NULL); ++ ++ local_irq_save(flags); ++ ++ memset(&fmDmaStatus, 0, sizeof(fmDmaStatus)); ++ FM_GetDmaStatus(p_LnxWrpFmDev->h_Dev, &fmDmaStatus); ++ ++ switch (counter) { ++ case e_FM_DMA_COUNTERS_CMQ_NOT_EMPTY: ++ counter_value = fmDmaStatus.cmqNotEmpty; ++ break; ++ case e_FM_DMA_COUNTERS_BUS_ERROR: ++ counter_value = fmDmaStatus.busError; ++ break; ++ case e_FM_DMA_COUNTERS_READ_BUF_ECC_ERROR: ++ counter_value = fmDmaStatus.readBufEccError; ++ break; ++ case e_FM_DMA_COUNTERS_WRITE_BUF_ECC_SYS_ERROR: ++ counter_value = fmDmaStatus.writeBufEccSysError; ++ break; ++ case e_FM_DMA_COUNTERS_WRITE_BUF_ECC_FM_ERROR: ++ counter_value = fmDmaStatus.writeBufEccFmError; ++ break; ++ default: ++ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__, ++ __func__); ++ break; ++ }; ++ ++ n = snprintf(buf, PAGE_SIZE, "\tFM %u counter: %c\n", ++ p_LnxWrpFmDev->id, counter_value ? 'T' : 'F'); ++ ++ local_irq_restore(flags); ++ ++ return n; ++} ++ ++static ssize_t show_fm_stats(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL; ++ unsigned long flags = 0; ++ unsigned n = 0, counter = 0; ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_LnxWrpFmDev == NULL)) ++ return -EINVAL; ++ ++ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_Dev) ++ return -EIO; ++ ++ counter = fm_find_statistic_counter_by_name( ++ attr->attr.name, ++ fmSysfsStats, NULL); ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, "\tFM %d counter: %d\n", ++ p_LnxWrpFmDev->id, ++ FM_GetCounter(p_LnxWrpFmDev->h_Dev, ++ (e_FmCounters) counter)); ++ ++ local_irq_restore(flags); ++ ++ return n; ++} ++ ++static ssize_t show_fm_pcd_stats(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL; ++ unsigned long flags = 0; ++ unsigned n = 0, counter = 0; ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_LnxWrpFmDev == NULL)) ++ return -EINVAL; ++ ++ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_Dev || ++ !p_LnxWrpFmDev->h_PcdDev) ++ return -EIO; ++ ++ counter = fm_find_statistic_counter_by_name( ++ attr->attr.name, ++ fmSysfsStats, NULL); ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, "\tFM %d counter: %d\n", ++ p_LnxWrpFmDev->id, ++ FM_PCD_GetCounter(p_LnxWrpFmDev->h_PcdDev, ++ (e_FmPcdCounters) counter)); ++ ++ local_irq_restore(flags); ++ ++ return n; ++} ++ ++/* FM */ ++static DEVICE_ATTR(enq_total_frame, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_total_frame, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_0, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_1, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_2, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_3, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_from_default, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_from_context, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_from_fd, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_confirm, S_IRUGO, show_fm_stats, NULL); ++/* FM:DMA */ ++static DEVICE_ATTR(cmq_not_empty, S_IRUGO, show_fm_dma_stats, NULL); ++static DEVICE_ATTR(bus_error, S_IRUGO, show_fm_dma_stats, NULL); ++static DEVICE_ATTR(read_buf_ecc_error, S_IRUGO, show_fm_dma_stats, NULL); ++static DEVICE_ATTR(write_buf_ecc_sys_error, S_IRUGO, show_fm_dma_stats, NULL); ++static DEVICE_ATTR(write_buf_ecc_fm_error, S_IRUGO, show_fm_dma_stats, NULL); ++/* FM:PCD */ ++static DEVICE_ATTR(pcd_kg_total, S_IRUGO, show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_plcr_yellow, S_IRUGO, show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_plcr_red, S_IRUGO, show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_plcr_recolored_to_red, S_IRUGO, show_fm_pcd_stats, ++ NULL); ++static DEVICE_ATTR(pcd_plcr_recolored_to_yellow, S_IRUGO, show_fm_pcd_stats, ++ NULL); ++static DEVICE_ATTR(pcd_plcr_total, S_IRUGO, show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_plcr_length_mismatch, S_IRUGO, show_fm_pcd_stats, ++ NULL); ++static DEVICE_ATTR(pcd_prs_parse_dispatch, S_IRUGO, show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_l2_parse_result_returned, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_l3_parse_result_returned, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_l4_parse_result_returned, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_shim_parse_result_returned, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_l2_parse_result_returned_with_err, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_l3_parse_result_returned_with_err, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_l4_parse_result_returned_with_err, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_shim_parse_result_returned_with_err, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_soft_prs_cycles, S_IRUGO, show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_soft_prs_stall_cycles, S_IRUGO, show_fm_pcd_stats, ++ NULL); ++static DEVICE_ATTR(pcd_prs_hard_prs_cycle_incl_stall_cycles, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_muram_read_cycles, S_IRUGO, show_fm_pcd_stats, ++ NULL); ++static DEVICE_ATTR(pcd_prs_muram_read_stall_cycles, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_muram_write_cycles, S_IRUGO, show_fm_pcd_stats, ++ NULL); ++static DEVICE_ATTR(pcd_prs_muram_write_stall_cycles, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_fpm_command_stall_cycles, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++ ++static struct attribute *fm_dev_stats_attributes[] = { ++ &dev_attr_enq_total_frame.attr, ++ &dev_attr_deq_total_frame.attr, ++ &dev_attr_deq_0.attr, ++ &dev_attr_deq_1.attr, ++ &dev_attr_deq_2.attr, ++ &dev_attr_deq_3.attr, ++ &dev_attr_deq_from_default.attr, ++ &dev_attr_deq_from_context.attr, ++ &dev_attr_deq_from_fd.attr, ++ &dev_attr_deq_confirm.attr, ++ &dev_attr_cmq_not_empty.attr, ++ &dev_attr_bus_error.attr, ++ &dev_attr_read_buf_ecc_error.attr, ++ &dev_attr_write_buf_ecc_sys_error.attr, ++ &dev_attr_write_buf_ecc_fm_error.attr, ++ &dev_attr_pcd_kg_total.attr, ++ &dev_attr_pcd_plcr_yellow.attr, ++ &dev_attr_pcd_plcr_red.attr, ++ &dev_attr_pcd_plcr_recolored_to_red.attr, ++ &dev_attr_pcd_plcr_recolored_to_yellow.attr, ++ &dev_attr_pcd_plcr_total.attr, ++ &dev_attr_pcd_plcr_length_mismatch.attr, ++ &dev_attr_pcd_prs_parse_dispatch.attr, ++ &dev_attr_pcd_prs_l2_parse_result_returned.attr, ++ &dev_attr_pcd_prs_l3_parse_result_returned.attr, ++ &dev_attr_pcd_prs_l4_parse_result_returned.attr, ++ &dev_attr_pcd_prs_shim_parse_result_returned.attr, ++ &dev_attr_pcd_prs_l2_parse_result_returned_with_err.attr, ++ &dev_attr_pcd_prs_l3_parse_result_returned_with_err.attr, ++ &dev_attr_pcd_prs_l4_parse_result_returned_with_err.attr, ++ &dev_attr_pcd_prs_shim_parse_result_returned_with_err.attr, ++ &dev_attr_pcd_prs_soft_prs_cycles.attr, ++ &dev_attr_pcd_prs_soft_prs_stall_cycles.attr, ++ &dev_attr_pcd_prs_hard_prs_cycle_incl_stall_cycles.attr, ++ &dev_attr_pcd_prs_muram_read_cycles.attr, ++ &dev_attr_pcd_prs_muram_read_stall_cycles.attr, ++ &dev_attr_pcd_prs_muram_write_cycles.attr, ++ &dev_attr_pcd_prs_muram_write_stall_cycles.attr, ++ &dev_attr_pcd_prs_fpm_command_stall_cycles.attr, ++ NULL ++}; ++ ++static const struct attribute_group fm_dev_stats_attr_grp = { ++ .name = "statistics", ++ .attrs = fm_dev_stats_attributes ++}; ++ ++static ssize_t show_fm_regs(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL; ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_LnxWrpFmDev == NULL)) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, "FM driver registers dump.\n"); ++ ++ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_Dev) ++ return -EIO; ++ else ++ FM_DumpRegs(p_LnxWrpFmDev->h_Dev); ++ ++ local_irq_restore(flags); ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ return n; ++} ++ ++static ssize_t show_pcd_regs(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL; ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_LnxWrpFmDev == NULL)) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, "FM driver registers dump.\n"); ++ ++ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_PcdDev) ++ return -EIO; ++ else ++ FM_PCD_DumpRegs(p_LnxWrpFmDev->h_PcdDev); ++ ++ local_irq_restore(flags); ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++ ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ return n; ++} ++ ++static DEVICE_ATTR(fm_regs, S_IRUGO, show_fm_regs, NULL); ++static DEVICE_ATTR(fm_pcd_regs, S_IRUGO, show_pcd_regs, NULL); ++ ++int fm_sysfs_create(struct device *dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL; ++ ++ if (dev == NULL) ++ return -EIO; ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ ++ /* store to remove them when module is disabled */ ++ p_LnxWrpFmDev->dev_attr_regs = &dev_attr_fm_regs; ++ p_LnxWrpFmDev->dev_pcd_attr_regs = &dev_attr_fm_pcd_regs; ++ ++ /* Create sysfs statistics group for FM module */ ++ if (sysfs_create_group(&dev->kobj, &fm_dev_stats_attr_grp) != 0) ++ return -EIO; ++ ++ /* Registers dump entry - in future will be moved to debugfs */ ++ if (device_create_file(dev, &dev_attr_fm_regs) != 0 || ++ device_create_file(dev, &dev_attr_fm_pcd_regs) != 0) ++ return -EIO; ++ ++ return 0; ++} ++ ++void fm_sysfs_destroy(struct device *dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL; ++ ++ if (WARN_ON(dev == NULL)) ++ return; ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_LnxWrpFmDev == NULL)) ++ return; ++ ++ sysfs_remove_group(&dev->kobj, &fm_dev_stats_attr_grp); ++ device_remove_file(dev, p_LnxWrpFmDev->dev_attr_regs); ++ device_remove_file(dev, p_LnxWrpFmDev->dev_pcd_attr_regs); ++} +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs_fm.h b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs_fm.h +new file mode 100644 +index 0000000..8aff850 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs_fm.h +@@ -0,0 +1,48 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_sysfs_fm.h ++ ++ @Description FM sysfs functions. ++ ++*/ ++ ++#ifndef LNXWRP_SYSFS_FM_H_ ++#define LNXWRP_SYSFS_FM_H_ ++ ++#include "lnxwrp_sysfs.h" ++ ++int fm_sysfs_create(struct device *dev); ++void fm_sysfs_destroy(struct device *dev); ++ ++#endif /* LNXWRP_SYSFS_FM_H_ */ +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs_fm_port.c b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs_fm_port.c +new file mode 100644 +index 0000000..97dacb7 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs_fm_port.c +@@ -0,0 +1,365 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_sysfs_fm_port.c ++ ++ @Description FM port sysfs related functions. ++ ++*/ ++ ++#include "lnxwrp_sysfs.h" ++#include "lnxwrp_fm.h" ++ ++static const struct SysfsStats_t portSysfsStats[] = { ++ /* RX/TX/OH common statistics */ ++ { ++ .statisticName = "port_frame", ++ .statisticCounter = e_FM_PORT_COUNTERS_FRAME, ++ }, ++ { ++ .statisticName = "port_discard_frame", ++ .statisticCounter = e_FM_PORT_COUNTERS_DISCARD_FRAME, ++ }, ++ { ++ .statisticName = "port_dealloc_buf", ++ .statisticCounter = e_FM_PORT_COUNTERS_DEALLOC_BUF, ++ }, ++ { ++ .statisticName = "port_enq_total", ++ .statisticCounter = e_FM_PORT_COUNTERS_ENQ_TOTAL, ++ }, ++ /* TX/OH */ ++ { ++ .statisticName = "port_length_err", ++ .statisticCounter = e_FM_PORT_COUNTERS_LENGTH_ERR, ++ }, ++ { ++ .statisticName = "port_unsupprted_format", ++ .statisticCounter = e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT, ++ }, ++ { ++ .statisticName = "port_deq_total", ++ .statisticCounter = e_FM_PORT_COUNTERS_DEQ_TOTAL, ++ }, ++ { ++ .statisticName = "port_deq_from_default", ++ .statisticCounter = e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT, ++ }, ++ { ++ .statisticName = "port_deq_confirm", ++ .statisticCounter = e_FM_PORT_COUNTERS_DEQ_CONFIRM, ++ }, ++ /* RX/OH */ ++ { ++ .statisticName = "port_rx_bad_frame", ++ .statisticCounter = e_FM_PORT_COUNTERS_RX_BAD_FRAME, ++ }, ++ { ++ .statisticName = "port_rx_large_frame", ++ .statisticCounter = e_FM_PORT_COUNTERS_RX_LARGE_FRAME, ++ }, ++ { ++ .statisticName = "port_rx_out_of_buffers_discard", ++ .statisticCounter = e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD, ++ }, ++ { ++ .statisticName = "port_rx_filter_frame", ++ .statisticCounter = e_FM_PORT_COUNTERS_RX_FILTER_FRAME, ++ }, ++ /* TODO: Particular statistics for OH ports */ ++ {} ++}; ++ ++static ssize_t show_fm_port_stats(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev; ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ unsigned long flags; ++ int n = 0; ++ uint8_t counter = 0; ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_LnxWrpFmPortDev == NULL)) ++ return -EINVAL; ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ if (WARN_ON(p_LnxWrpFmDev == NULL)) ++ return -EINVAL; ++ ++ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_Dev) ++ return -EIO; ++ ++ if (!p_LnxWrpFmPortDev->h_Dev) { ++ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n"); ++ return n; ++ } ++ ++ counter = fm_find_statistic_counter_by_name( ++ attr->attr.name, ++ portSysfsStats, NULL); ++ ++ if (counter == e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR) { ++ uint32_t fmRev = 0; ++ fmRev = 0xffff & ioread32(UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr ++ + 0x000c30c4)); ++ ++ if (fmRev == 0x0100) { ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "counter not available for revision 1\n"); ++ local_irq_restore(flags); ++ } ++ return n; ++ } ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, "\tFM %d Port %d counter: %d\n", ++ p_LnxWrpFmDev->id, ++ p_LnxWrpFmPortDev->id, ++ FM_PORT_GetCounter(p_LnxWrpFmPortDev->h_Dev, ++ (e_FmPortCounters) counter)); ++ local_irq_restore(flags); ++ ++ return n; ++} ++ ++/* FM PORT RX/TX/OH statistics */ ++static DEVICE_ATTR(port_frame, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_discard_frame, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_dealloc_buf, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_enq_total, S_IRUGO, show_fm_port_stats, NULL); ++/* FM PORT TX/OH statistics */ ++static DEVICE_ATTR(port_length_err, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_unsupprted_format, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_deq_total, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_deq_from_default, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_deq_confirm, S_IRUGO, show_fm_port_stats, NULL); ++/* FM PORT RX/OH statistics */ ++static DEVICE_ATTR(port_rx_bad_frame, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_rx_large_frame, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_rx_out_of_buffers_discard, S_IRUGO, ++ show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_rx_filter_frame, S_IRUGO, show_fm_port_stats, NULL); ++ ++/* FM PORT TX statistics */ ++static struct attribute *fm_tx_port_dev_stats_attributes[] = { ++ &dev_attr_port_frame.attr, ++ &dev_attr_port_discard_frame.attr, ++ &dev_attr_port_dealloc_buf.attr, ++ &dev_attr_port_enq_total.attr, ++ &dev_attr_port_length_err.attr, ++ &dev_attr_port_unsupprted_format.attr, ++ &dev_attr_port_deq_total.attr, ++ &dev_attr_port_deq_from_default.attr, ++ &dev_attr_port_deq_confirm.attr, ++ NULL ++}; ++ ++static const struct attribute_group fm_tx_port_dev_stats_attr_grp = { ++ .name = "statistics", ++ .attrs = fm_tx_port_dev_stats_attributes ++}; ++ ++/* FM PORT RX statistics */ ++static struct attribute *fm_rx_port_dev_stats_attributes[] = { ++ &dev_attr_port_frame.attr, ++ &dev_attr_port_discard_frame.attr, ++ &dev_attr_port_dealloc_buf.attr, ++ &dev_attr_port_enq_total.attr, ++ &dev_attr_port_rx_bad_frame.attr, ++ &dev_attr_port_rx_large_frame.attr, ++ &dev_attr_port_rx_out_of_buffers_discard.attr, ++ &dev_attr_port_rx_filter_frame.attr, ++ NULL ++}; ++ ++static const struct attribute_group fm_rx_port_dev_stats_attr_grp = { ++ .name = "statistics", ++ .attrs = fm_rx_port_dev_stats_attributes ++}; ++ ++/* TODO: add particular OH ports statistics */ ++static struct attribute *fm_oh_port_dev_stats_attributes[] = { ++ &dev_attr_port_frame.attr, ++ &dev_attr_port_discard_frame.attr, ++ &dev_attr_port_dealloc_buf.attr, ++ &dev_attr_port_enq_total.attr, ++ /*TX*/ &dev_attr_port_length_err.attr, ++ &dev_attr_port_unsupprted_format.attr, ++ &dev_attr_port_deq_total.attr, ++ &dev_attr_port_deq_from_default.attr, ++ &dev_attr_port_deq_confirm.attr, ++ /*RX*/ &dev_attr_port_rx_bad_frame.attr, ++ &dev_attr_port_rx_large_frame.attr, ++ &dev_attr_port_rx_out_of_buffers_discard.attr, ++ /*&dev_attr_port_rx_filter_frame.attr, */ ++ NULL ++}; ++ ++static const struct attribute_group fm_oh_port_dev_stats_attr_grp = { ++ .name = "statistics", ++ .attrs = fm_oh_port_dev_stats_attributes ++}; ++ ++static ssize_t show_fm_port_regs(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = ++ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ local_irq_save(flags); ++ ++ if (!p_LnxWrpFmPortDev->h_Dev) { ++ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n"); ++ return n; ++ } else { ++ n = snprintf(buf, PAGE_SIZE, ++ "FM port driver registers dump.\n"); ++ FM_PORT_DumpRegs(p_LnxWrpFmPortDev->h_Dev); ++ } ++ ++ local_irq_restore(flags); ++ ++ return n; ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++ ++ return n; ++#endif ++} ++ ++static DEVICE_ATTR(fm_port_regs, 0x644, show_fm_port_regs, NULL); ++ ++int fm_port_sysfs_create(struct device *dev) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev; ++ ++ if (dev == NULL) ++ return -EINVAL; ++ ++ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_LnxWrpFmPortDev == NULL)) ++ return -EINVAL; ++ ++ /* store to remove them when module is disabled */ ++ p_LnxWrpFmPortDev->dev_attr_regs = &dev_attr_fm_port_regs; ++ ++ /* Registers dump entry - in future will be moved to debugfs */ ++ if (device_create_file(dev, &dev_attr_fm_port_regs) != 0) ++ return -EIO; ++ ++ /* FM Ports statistics */ ++ switch (p_LnxWrpFmPortDev->settings.param.portType) { ++ case e_FM_PORT_TYPE_TX: ++ case e_FM_PORT_TYPE_TX_10G: ++ if (sysfs_create_group ++ (&dev->kobj, &fm_tx_port_dev_stats_attr_grp) != 0) ++ return -EIO; ++ break; ++ case e_FM_PORT_TYPE_RX: ++ case e_FM_PORT_TYPE_RX_10G: ++ if (sysfs_create_group ++ (&dev->kobj, &fm_rx_port_dev_stats_attr_grp) != 0) ++ return -EIO; ++ break; ++ /* TODO:FMD16 e_FM_PORT_TYPE_DUMMY is accutally a HC port. ++ * NetCommSw defined this way... no idea why!!! */ ++ case e_FM_PORT_TYPE_DUMMY: ++ case e_FM_PORT_TYPE_OH_OFFLINE_PARSING: ++ if (sysfs_create_group ++ (&dev->kobj, &fm_oh_port_dev_stats_attr_grp) != 0) ++ return -EIO; ++ break; ++ default: ++ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__, ++ __func__); ++ return -EINVAL; ++ break; ++ }; ++ ++ return 0; ++} ++ ++void fm_port_sysfs_destroy(struct device *dev) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = NULL; ++ ++ /* this function has never been tested !!! */ ++ ++ if (WARN_ON(dev == NULL)) ++ return; ++ ++ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_LnxWrpFmPortDev == NULL)) ++ return; ++ ++ /* The name attribute will be freed also by these 2 functions? */ ++ switch (p_LnxWrpFmPortDev->settings.param.portType) { ++ case e_FM_PORT_TYPE_TX: ++ case e_FM_PORT_TYPE_TX_10G: ++ sysfs_remove_group(&dev->kobj, &fm_tx_port_dev_stats_attr_grp); ++ break; ++ case e_FM_PORT_TYPE_RX: ++ case e_FM_PORT_TYPE_RX_10G: ++ sysfs_remove_group(&dev->kobj, &fm_rx_port_dev_stats_attr_grp); ++ break; ++ /* TODO:FMD16 e_FM_PORT_TYPE_DUMMY is accutally a HC port. ++ * NetCommSw defined this way... no idea why!!! */ ++ case e_FM_PORT_TYPE_DUMMY: ++ case e_FM_PORT_TYPE_OH_OFFLINE_PARSING: ++ sysfs_remove_group(&dev->kobj, &fm_oh_port_dev_stats_attr_grp); ++ break; ++ default: ++ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__, ++ __func__); ++ break; ++ }; ++ ++ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_regs); ++} +diff --git a/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs_fm_port.h b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs_fm_port.h +new file mode 100644 +index 0000000..03b3a03 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/wrapper/lnxwrp_sysfs_fm_port.h +@@ -0,0 +1,48 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 lnxwrp_sysfs_fm_port.h ++ ++ @Description FM port sysfs functions. ++ ++*/ ++ ++#ifndef LNXWRP_SYSFS_FM_PORT_H_ ++#define LNXWRP_SYSFS_FM_PORT_H_ ++ ++#include "lnxwrp_sysfs.h" ++ ++int fm_port_sysfs_create(struct device *dev); ++void fm_port_sysfs_destroy(struct device *dev); ++ ++#endif /* LNXWRP_SYSFS_FM_PORT_H_ */ +diff --git a/drivers/net/dpa/NetCommSw/src/xx/Makefile b/drivers/net/dpa/NetCommSw/src/xx/Makefile +new file mode 100644 +index 0000000..870c1b0 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/xx/Makefile +@@ -0,0 +1,12 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++EXTRA_CFLAGS += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/dpa/NetCommSw/ncsw_config.mk ++ ++obj-y += fsl-ncsw-xx.o ++ ++fsl-ncsw-xx-objs := xx_linux.o udivdi3.o stdlib.o \ ++ module_strings.o +diff --git a/drivers/net/dpa/NetCommSw/src/xx/module_strings.c b/drivers/net/dpa/NetCommSw/src/xx/module_strings.c +new file mode 100644 +index 0000000..98c64fb +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/xx/module_strings.c +@@ -0,0 +1,45 @@ ++/* ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/* Module names for debug messages */ ++const char *moduleStrings[] = ++{ ++ "", /* MODULE_UNKNOWN */ ++ "FM", /* MODULE_FM */ ++ "FM-MURAM", /* MODULE_FM_MURAM */ ++ "FM-PCD", /* MODULE_FM_PCD */ ++ "FM-RTC", /* MODULE_FM_RTC */ ++ "FM-MAC", /* MODULE_FM_MAC */ ++ "FM-Port", /* MODULE_FM_PORT */ ++ "MM", /* MODULE_MM */ ++ "FM-SP" /* MODULE_FM_SP */ ++}; +diff --git a/drivers/net/dpa/NetCommSw/src/xx/stdlib.c b/drivers/net/dpa/NetCommSw/src/xx/stdlib.c +new file mode 100644 +index 0000000..851bcf1 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/xx/stdlib.c +@@ -0,0 +1,264 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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: stdlib.c */ ++/* */ ++/* Description: */ ++/* Standard library routines (externals) */ ++/* */ ++/* Modifications: */ ++/* ============== */ ++/* */ ++/*------------------------------------------------------*/ ++#include "stdlib_ext.h" ++#include "stdarg_ext.h" ++#include "ctype_ext.h" ++#include "string_ext.h" ++#include "std_ext.h" ++#include "xx_ext.h" ++ ++ ++#ifdef MODULE ++/** ++ * strtoul - convert a string to an uint32_t ++ * @cp: The start of the string ++ * @endp: A pointer to the end of the parsed string will be placed here ++ * @base: The number base to use ++ */ ++uint32_t strtoul(const char *cp,char **endp,uint32_t base) ++{ ++ uint32_t result = 0,value; ++ ++ if (!base) { ++ base = 10; ++ if (*cp == '0') { ++ base = 8; ++ cp++; ++ if ((*cp == 'x') && isxdigit(cp[1])) { ++ cp++; ++ base = 16; ++ } ++ } ++ } ++ while (isxdigit(*cp) && ++ (value = (uint32_t)(isdigit(*cp) ? *cp-'0' : toupper((uint8_t)(*cp))-'A'+10)) < base) { ++ result = result*base + value; ++ cp++; ++ } ++ if (endp) ++ *endp = (char *)cp; ++ return result; ++} ++ ++/** ++ * strtol - convert a string to a int32_t ++ * @cp: The start of the string ++ * @endp: A pointer to the end of the parsed string will be placed here ++ * @base: The number base to use ++ */ ++long strtol(const char *cp,char **endp,uint32_t base) ++{ ++ if(*cp=='-') ++ return (long)(-strtoul(cp+1,endp,base)); ++ return (long)strtoul(cp,endp,base); ++} ++ ++/** ++ * strtoull - convert a string to an uint64_t ++ * @cp: The start of the string ++ * @endp: A pointer to the end of the parsed string will be placed here ++ * @base: The number base to use ++ */ ++uint64_t strtoull(const char *cp,char **endp,uint32_t base) ++{ ++ uint64_t result = 0,value; ++ ++ if (!base) { ++ base = 10; ++ if (*cp == '0') { ++ base = 8; ++ cp++; ++ if ((*cp == 'x') && isxdigit(cp[1])) { ++ cp++; ++ base = 16; ++ } ++ } ++ } ++ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) ++ ? toupper((uint8_t)(*cp)) : *cp)-'A'+10) < base) { ++ result = result*base + value; ++ cp++; ++ } ++ if (endp) ++ *endp = (char *)cp; ++ return result; ++} ++ ++/** ++ * strtoll - convert a string to a int64 ++ * @cp: The start of the string ++ * @endp: A pointer to the end of the parsed string will be placed here ++ * @base: The number base to use ++ */ ++long long strtoll(const char *cp,char **endp,uint32_t base) ++{ ++ if(*cp=='-') ++ return (long long)(-strtoull(cp+1,endp,base)); ++ return (long long)(strtoull(cp,endp,base)); ++} ++ ++/** ++ * atoi - convert a string to a int ++ * @s: The start of the string ++ */ ++int atoi(const char *s) ++{ ++ int i=0; ++ const char **tmp_s = &s; ++ ++ while (isdigit(**tmp_s)) ++ i = i*10 + *((*tmp_s)++) - '0'; ++ return i; ++} ++ ++/** ++ * strlen - Find the length of a string ++ * @s: The string to be sized ++ */ ++size_t strlen(const char * s) ++{ ++ const char *sc; ++ ++ for (sc = s; *sc != '\0'; ++sc) ++ /* nothing */; ++ ++ return sc - s; ++} ++ ++/** ++ * strnlen - Find the length of a length-limited string ++ * @s: The string to be sized ++ * @count: The maximum number of bytes to search ++ */ ++size_t strnlen(const char * s, size_t count) ++{ ++ const char *sc; ++ ++ for (sc = s; count-- && *sc != '\0'; ++sc) ++ /* nothing */; ++ ++ return sc - s; ++} ++ ++/** ++ * strcpy - Copy a %NUL terminated string ++ * @dest: Where to copy the string to ++ * @src: Where to copy the string from ++ */ ++char * strcpy(char * dest,const char *src) ++{ ++ char *tmp = dest; ++ ++ while ((*dest++ = *src++) != '\0') ++ /* nothing */; ++ ++ return tmp; ++} ++#endif /* MODULE */ ++ ++/** ++ * strtok - Split a string into tokens ++ * @s: The string to be searched ++ * @ct: The characters to search for ++ * ++ * WARNING: strtok is deprecated, use strsep instead. ++ */ ++char *___strtok; ++ ++char * strtok(char * s,const char * ct) ++{ ++ char *sbegin, *send; ++ ++ sbegin = s ? s : ___strtok; ++ if (!sbegin) { ++ return NULL; ++ } ++ sbegin += strspn(sbegin,ct); ++ if (*sbegin == '\0') { ++ ___strtok = NULL; ++ return( NULL ); ++ } ++ send = strpbrk( sbegin, ct); ++ if (send && *send != '\0') ++ *send++ = '\0'; ++ ___strtok = send; ++ return (sbegin); ++} ++ ++ ++#ifdef MODULE ++/** ++ * strncpy - Copy a length-limited, %NUL-terminated string ++ * @dest: Where to copy the string to ++ * @src: Where to copy the string from ++ * @count: The maximum number of bytes to copy ++ * ++ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer. ++ * However, the result is not %NUL-terminated if the source exceeds ++ * @count bytes. ++ */ ++char * strncpy(char * dest,const char *src,size_t count) ++{ ++ char *tmp = dest; ++ ++ while (count-- && (*dest++ = *src++) != '\0') ++ /* nothing */; ++ ++ return tmp; ++} ++ ++/** ++ * vsprintf - Format a string and place it in a buffer ++ * @buf: The buffer to place the result into ++ * @fmt: The format string to use ++ * @args: Arguments for the format string ++ * ++ * Call this function if you are already dealing with a va_list. ++ * You probably want sprintf instead. ++ */ ++int vsprintf(char *buf, const char *fmt, va_list args) ++{ ++ return vsnprintf(buf, INT32_MAX, fmt, args); ++} ++#endif /* MODULE */ +diff --git a/drivers/net/dpa/NetCommSw/src/xx/udivdi3.c b/drivers/net/dpa/NetCommSw/src/xx/udivdi3.c +new file mode 100644 +index 0000000..419e27e +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/xx/udivdi3.c +@@ -0,0 +1,132 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++#include ++ ++ ++#define BITS_PER_UNIT 8 ++#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT) ++ ++ ++typedef unsigned int UQItype __attribute__ ((mode (QI))); ++typedef int SItype __attribute__ ((mode (SI))); ++typedef unsigned int USItype __attribute__ ((mode (SI))); ++typedef int DItype __attribute__ ((mode (DI))); ++typedef int word_type __attribute__ ((mode (__word__))); ++typedef unsigned int UDItype __attribute__ ((mode (DI))); ++ ++struct DIstruct {SItype low, high;}; ++ ++typedef union ++{ ++ struct DIstruct s; ++ DItype ll; ++} DIunion; ++ ++ ++/* bit divisor, dividend and result. dynamic precision */ ++static __inline__ uint64_t _div64_64(uint64_t dividend, uint64_t divisor) ++{ ++ uint32_t d = divisor; ++ ++ if (divisor > 0xffffffffULL) ++ { ++ unsigned int shift = fls(divisor >> 32); ++ ++ d = divisor >> shift; ++ dividend >>= shift; ++ } ++ ++ /* avoid 64 bit division if possible */ ++ if (dividend >> 32) ++ do_div(dividend, d); ++ else ++ dividend = (uint32_t) dividend / d; ++ ++ return dividend; ++} ++ ++UDItype __udivdi3 (UDItype n, UDItype d) ++{ ++ return _div64_64(n, d); ++} ++ ++DItype __divdi3 (DItype n, DItype d) ++{ ++ DItype sign = 1; ++ if (n<0) ++ { ++ sign *= -1; ++ n *= -1; ++ } ++ if (d<0) ++ { ++ sign *= -1; ++ d *= -1; ++ } ++ return sign*_div64_64((UDItype)n, (UDItype)d); ++} ++ ++UDItype __umoddi3 (UDItype n, UDItype d) ++{ ++ return n-(_div64_64(n, d)*d); ++} ++ ++#ifdef MODULE ++word_type __ucmpdi2 (DItype a, DItype b) ++{ ++ DIunion au, bu; ++ ++ au.ll = a, bu.ll = b; ++ ++ if ((USItype) au.s.high < (USItype) bu.s.high) ++ return 0; ++ else if ((USItype) au.s.high > (USItype) bu.s.high) ++ return 2; ++ if ((USItype) au.s.low < (USItype) bu.s.low) ++ return 0; ++ else if ((USItype) au.s.low > (USItype) bu.s.low) ++ return 2; ++ return 1; ++} ++#endif /* MODULE */ +diff --git a/drivers/net/dpa/NetCommSw/src/xx/xx_linux.c b/drivers/net/dpa/NetCommSw/src/xx/xx_linux.c +new file mode 100644 +index 0000000..209d2e5 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/src/xx/xx_linux.c +@@ -0,0 +1,902 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 xx_linux.c ++ ++ @Description XX routines implementation for Linux. ++*//***************************************************************************/ ++#include ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#ifdef BIGPHYSAREA_ENABLE ++#include ++#endif /* BIGPHYSAREA_ENABLE */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "list_ext.h" ++#include "mm_ext.h" ++#include "sys_io_ext.h" ++#include "xx.h" ++ ++ ++#define __ERR_MODULE__ MODULE_UNKNOWN ++ ++#ifdef BIGPHYSAREA_ENABLE ++#define MAX_ALLOCATION_SIZE 128 * 1024 /* Maximum size allocated with kmalloc is 128K */ ++ ++ ++/* TODO: large allocations => use big phys area */ ++/****************************************************************************** ++ * routine: get_nr_pages ++ * ++ * description: ++ * calculates the number of memory pages for a given size (in bytes) ++ * ++ * arguments: ++ * size - the number of bytes ++ * ++ * return code: ++ * The number of pages ++ * ++ *****************************************************************************/ ++static __inline__ uint32_t get_nr_pages (uint32_t size) ++{ ++ return (uint32_t)((size >> PAGE_SHIFT) + (size & PAGE_SHIFT ? 1 : 0)); ++} ++ ++static bool in_big_phys_area (uint32_t addr) ++{ ++ uint32_t base, size; ++ ++ bigphysarea_get_details (&base, &size); ++ return ((addr >= base) && (addr < base + size)); ++} ++#endif /* BIGPHYSAREA_ENABLE */ ++ ++void * xx_Malloc(uint32_t n) ++{ ++ void *a; ++ uint32_t flags; ++ ++ flags = XX_DisableAllIntr(); ++#ifdef BIGPHYSAREA_ENABLE ++ if (n >= MAX_ALLOCATION_SIZE) ++ a = (void*)bigphysarea_alloc_pages(get_nr_pages(n), 0, GFP_ATOMIC); ++ else ++#endif /* BIGPHYSAREA_ENABLE */ ++ a = (void *)kmalloc((uint32_t)n, GFP_ATOMIC); ++ if (!a) ++ XX_Print("No memory for XX_Malloc\n"); ++ XX_RestoreAllIntr(flags); ++ ++ return a; ++} ++ ++void xx_Free(void *p) ++{ ++#ifdef BIGPHYSAREA_ENABLE ++ if (in_big_phys_area ((uint32_t)p)) ++ bigphysarea_free_pages(p); ++ else ++#endif /* BIGPHYSAREA_ENABLE */ ++ kfree(p); ++} ++ ++void XX_Exit(int status) ++{ ++ WARN(1, "\n\nFMD: fatal error, driver can't go on!!!\n\n"); ++} ++ ++#define BUF_SIZE 512 ++void XX_Print(char *str, ...) ++{ ++ va_list args; ++#ifdef CONFIG_SMP ++ char buf[BUF_SIZE]; ++#endif /* CONFIG_SMP */ ++ ++ va_start(args, str); ++#ifdef CONFIG_SMP ++ if (vsnprintf (buf, BUF_SIZE, str, args) >= BUF_SIZE) ++ printk(KERN_WARNING "Illegal string to print!\n more than %d characters.\n\tString was not printed completelly.\n", BUF_SIZE); ++ printk (KERN_CRIT "cpu%d: %s",raw_smp_processor_id(), buf); ++#else ++ vprintk(str, args); ++#endif /* CONFIG_SMP */ ++ va_end(args); ++} ++ ++void XX_Fprint(void *file, char *str, ...) ++{ ++ va_list args; ++#ifdef CONFIG_SMP ++ char buf[BUF_SIZE]; ++#endif /* CONFIG_SMP */ ++ ++ va_start(args, str); ++#ifdef CONFIG_SMP ++ if (vsnprintf (buf, BUF_SIZE, str, args) >= BUF_SIZE) ++ printk(KERN_WARNING "Illegal string to print!\n more than %d characters.\n\tString was not printed completelly.\n", BUF_SIZE); ++ printk (KERN_CRIT "cpu%d: %s", raw_smp_processor_id(), buf); ++#else ++ vprintk(str, args); ++#endif /* CONFIG_SMP */ ++ va_end(args); ++} ++ ++#ifdef DEBUG_XX_MALLOC ++typedef void (*t_ffn)(void *); ++typedef struct { ++ t_ffn f_free; ++ void *mem; ++ char *fname; ++ int fline; ++ uint32_t size; ++ t_List node; ++} t_MemDebug; ++#define MEMDBG_OBJECT(p_List) LIST_OBJECT(p_List, t_MemDebug, node) ++ ++LIST(memDbgLst); ++ ++ ++void * XX_MallocDebug(uint32_t size, char *fname, int line) ++{ ++ void *mem; ++ t_MemDebug *p_MemDbg; ++ ++ p_MemDbg = (t_MemDebug *)xx_Malloc(sizeof(t_MemDebug)); ++ if (p_MemDbg == NULL) ++ return NULL; ++ ++ mem = xx_Malloc(size); ++ if (mem == NULL) ++ { ++ XX_Free(p_MemDbg); ++ return NULL; ++ } ++ ++ INIT_LIST(&p_MemDbg->node); ++ p_MemDbg->f_free = xx_Free; ++ p_MemDbg->mem = mem; ++ p_MemDbg->fname = fname; ++ p_MemDbg->fline = line; ++ p_MemDbg->size = size+sizeof(t_MemDebug); ++ LIST_AddToTail(&p_MemDbg->node, &memDbgLst); ++ ++ return mem; ++} ++ ++void * XX_MallocSmartDebug(uint32_t size, ++ int memPartitionId, ++ uint32_t align, ++ char *fname, ++ int line) ++{ ++ void *mem; ++ t_MemDebug *p_MemDbg; ++ ++ p_MemDbg = (t_MemDebug *)XX_Malloc(sizeof(t_MemDebug)); ++ if (p_MemDbg == NULL) ++ return NULL; ++ ++ mem = xx_MallocSmart((uint32_t)size, memPartitionId, align); ++ if (mem == NULL) ++ { ++ XX_Free(p_MemDbg); ++ return NULL; ++ } ++ ++ INIT_LIST(&p_MemDbg->node); ++ p_MemDbg->f_free = xx_FreeSmart; ++ p_MemDbg->mem = mem; ++ p_MemDbg->fname = fname; ++ p_MemDbg->fline = line; ++ p_MemDbg->size = size+sizeof(t_MemDebug); ++ LIST_AddToTail(&p_MemDbg->node, &memDbgLst); ++ ++ return mem; ++} ++ ++static void debug_free(void *mem) ++{ ++ t_List *p_MemDbgLh = NULL; ++ t_MemDebug *p_MemDbg; ++ bool found = FALSE; ++ ++ if (LIST_IsEmpty(&memDbgLst)) ++ { ++ REPORT_ERROR(MAJOR, E_ALREADY_FREE, ("Unbalanced free (0x%08x)", mem)); ++ return; ++ } ++ ++ LIST_FOR_EACH(p_MemDbgLh, &memDbgLst) ++ { ++ p_MemDbg = MEMDBG_OBJECT(p_MemDbgLh); ++ if (p_MemDbg->mem == mem) ++ { ++ found = TRUE; ++ break; ++ } ++ } ++ ++ if (!found) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_FOUND, ++ ("Attempt to free unallocated address (0x%08x)",mem)); ++ dump_stack(); ++ return; ++ } ++ ++ LIST_Del(p_MemDbgLh); ++ p_MemDbg->f_free(mem); ++ p_MemDbg->f_free(p_MemDbg); ++} ++ ++void XX_FreeSmart(void *p) ++{ ++ debug_free(p); ++} ++ ++ ++void XX_Free(void *p) ++{ ++ debug_free(p); ++} ++ ++#else /* not DEBUG_XX_MALLOC */ ++void * XX_Malloc(uint32_t size) ++{ ++ return xx_Malloc(size); ++} ++ ++void * XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment) ++{ ++ return xx_MallocSmart(size,memPartitionId, alignment); ++} ++ ++void XX_FreeSmart(void *p) ++{ ++ xx_FreeSmart(p); ++} ++ ++ ++void XX_Free(void *p) ++{ ++ xx_Free(p); ++} ++#endif /* not DEBUG_XX_MALLOC */ ++ ++ ++#if (defined(REPORT_EVENTS) && (REPORT_EVENTS > 0)) ++void XX_EventById(uint32_t event, t_Handle appId, uint16_t flags, char *msg) ++{ ++ e_Event eventCode = (e_Event)event; ++ ++ UNUSED(eventCode); ++ UNUSED(appId); ++ UNUSED(flags); ++ UNUSED(msg); ++} ++#endif /* (defined(REPORT_EVENTS) && ... */ ++ ++ ++uint32_t XX_DisableAllIntr(void) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ return (uint32_t)flags; ++} ++ ++void XX_RestoreAllIntr(uint32_t flags) ++{ ++ local_irq_restore((unsigned long)flags); ++} ++ ++t_Error XX_Call( uint32_t qid, t_Error (* f)(t_Handle), t_Handle id, t_Handle appId, uint16_t flags ) ++{ ++ UNUSED(qid); ++ UNUSED(appId); ++ UNUSED(flags); ++ ++ return f(id); ++} ++ ++int XX_IsICacheEnable(void) ++{ ++ return TRUE; ++} ++ ++int XX_IsDCacheEnable(void) ++{ ++ return TRUE; ++} ++ ++ ++typedef struct { ++ t_Isr *f_Isr; ++ t_Handle handle; ++} t_InterruptHandler; ++ ++ ++t_Handle interruptHandlers[0x00010000]; ++ ++static irqreturn_t LinuxInterruptHandler (int irq, void *dev_id) ++{ ++ t_InterruptHandler *p_IntrHndl = (t_InterruptHandler *)dev_id; ++ p_IntrHndl->f_Isr(p_IntrHndl->handle); ++ return IRQ_HANDLED; ++} ++ ++t_Error XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle) ++{ ++ const char *device; ++ t_InterruptHandler *p_IntrHndl; ++ ++ device = GetDeviceName(irq); ++ if (device == NULL) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Interrupt source - %d", irq)); ++ ++ p_IntrHndl = (t_InterruptHandler *)XX_Malloc(sizeof(t_InterruptHandler)); ++ if (p_IntrHndl == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ p_IntrHndl->f_Isr = f_Isr; ++ p_IntrHndl->handle = handle; ++ interruptHandlers[irq] = p_IntrHndl; ++ ++ if (request_irq(GetDeviceIrqNum(irq), LinuxInterruptHandler, 0, device, p_IntrHndl) < 0) ++ RETURN_ERROR(MAJOR, E_BUSY, ("Can't get IRQ %s\n", device)); ++ disable_irq(GetDeviceIrqNum(irq)); ++ ++ return E_OK; ++} ++ ++t_Error XX_FreeIntr(int irq) ++{ ++ t_InterruptHandler *p_IntrHndl = interruptHandlers[irq]; ++ free_irq(GetDeviceIrqNum(irq), p_IntrHndl); ++ XX_Free(p_IntrHndl); ++ interruptHandlers[irq] = 0; ++ return E_OK; ++} ++ ++t_Error XX_EnableIntr(int irq) ++{ ++ enable_irq(GetDeviceIrqNum(irq)); ++ return E_OK; ++} ++ ++t_Error XX_DisableIntr(int irq) ++{ ++ disable_irq(GetDeviceIrqNum(irq)); ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Tasklet Service Routines */ ++/*****************************************************************************/ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++typedef struct ++{ ++ t_Handle h_Data; ++ void (*f_Callback) (void *); ++ struct delayed_work dwork; ++} t_Tasklet; ++ ++static void GenericTaskletCallback(struct work_struct *p_Work) ++{ ++ t_Tasklet *p_Task = container_of(p_Work, t_Tasklet, dwork.work); ++ ++ p_Task->f_Callback(p_Task->h_Data); ++} ++#endif /* LINUX_VERSION_CODE */ ++ ++ ++t_TaskletHandle XX_InitTasklet (void (*routine)(void *), void *data) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ struct work_struct *p_Task; ++ p_Task = (struct work_struct *)XX_Malloc(sizeof(struct work_struct)); ++ INIT_WORK(p_Task, routine, data); ++#else ++ t_Tasklet *p_Task = (t_Tasklet *)XX_Malloc(sizeof(t_Tasklet)); ++ p_Task->h_Data = data; ++ p_Task->f_Callback = routine; ++ INIT_DELAYED_WORK(&p_Task->dwork, GenericTaskletCallback); ++#endif /* LINUX_VERSION_CODE */ ++ ++ return (t_TaskletHandle)p_Task; ++} ++ ++ ++void XX_FreeTasklet (t_TaskletHandle h_Tasklet) ++{ ++ if (h_Tasklet) ++ XX_Free(h_Tasklet); ++} ++ ++int XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate) ++{ ++ int ans; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ if (immediate) ++ ans = schedule_work(h_Tasklet); ++ else ++ ans = schedule_delayed_work(h_Tasklet, 1); ++#else ++ if (immediate) ++ ans = schedule_delayed_work(&((t_Tasklet *)h_Tasklet)->dwork, 0); ++ else ++ ans = schedule_delayed_work(&((t_Tasklet *)h_Tasklet)->dwork, HZ); ++#endif /* LINUX_VERSION_CODE */ ++ ++ return ans; ++} ++ ++void XX_FlushScheduledTasks(void) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ++ flush_scheduled_tasks(); ++#else ++ flush_scheduled_work(); ++#endif /* LINUX_VERSION_CODE */ ++} ++ ++int XX_TaskletIsQueued(t_TaskletHandle h_Tasklet) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ return (int)(((struct work_struct *)h_Tasklet)->pending); ++#else ++ return (int)delayed_work_pending(&((t_Tasklet *)h_Tasklet)->dwork); ++#endif /* LINUX_VERSION_CODE */ ++} ++ ++void XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ++ ((struct tq_struct *)h_Tasklet)->data = data; ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ ((struct work_struct *)h_Tasklet)->data = data; ++#else ++ ((t_Tasklet *)h_Tasklet)->h_Data = data; ++#endif /* LINUX_VERSION_CODE */ ++} ++ ++t_Handle XX_GetTaskletData(t_TaskletHandle h_Tasklet) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ return (t_Handle)(((struct work_struct *)h_Tasklet)->data); ++#else ++ return ((t_Tasklet *)h_Tasklet)->h_Data; ++#endif /* LINUX_VERSION_CODE */ ++} ++ ++ ++/*****************************************************************************/ ++/* Spinlock Service Routines */ ++/*****************************************************************************/ ++ ++t_Handle XX_InitSpinlock(void) ++{ ++ spinlock_t *p_Spinlock = (spinlock_t *)XX_Malloc(sizeof(spinlock_t)); ++ if (!p_Spinlock) ++ return NULL; ++ ++ spin_lock_init(p_Spinlock); ++ ++ return (t_Handle)p_Spinlock; ++} ++ ++void XX_FreeSpinlock(t_Handle h_Spinlock) ++{ ++ if (h_Spinlock) ++ XX_Free(h_Spinlock); ++} ++ ++void XX_LockSpinlock(t_Handle h_Spinlock) ++{ ++ spin_lock((spinlock_t *)h_Spinlock); ++} ++ ++void XX_UnlockSpinlock(t_Handle h_Spinlock) ++{ ++ spin_unlock((spinlock_t *)h_Spinlock); ++} ++ ++uint32_t XX_LockIntrSpinlock(t_Handle h_Spinlock) ++{ ++ unsigned long intrFlags; ++ spin_lock_irqsave((spinlock_t *)h_Spinlock, intrFlags); ++ return intrFlags; ++} ++ ++void XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags) ++{ ++ spin_unlock_irqrestore((spinlock_t *)h_Spinlock, (unsigned long)intrFlags); ++} ++ ++ ++/*****************************************************************************/ ++/* Timers Service Routines */ ++/*****************************************************************************/ ++/* The time now is in mili sec. resolution */ ++uint32_t XX_CurrentTime(void) ++{ ++ return (jiffies*1000)/HZ; ++} ++ ++ ++t_Handle XX_CreateTimer(void) ++{ ++ struct timer_list *p_Timer = (struct timer_list *)XX_Malloc(sizeof(struct timer_list)); ++ if (p_Timer) ++ { ++ memset(p_Timer, 0, sizeof(struct timer_list)); ++ init_timer(p_Timer); ++ } ++ return (t_Handle)p_Timer; ++} ++ ++void XX_FreeTimer(t_Handle h_Timer) ++{ ++ if (h_Timer) ++ XX_Free(h_Timer); ++} ++ ++void XX_StartTimer(t_Handle h_Timer, ++ uint32_t msecs, ++ bool periodic, ++ void (*f_TimerExpired)(t_Handle), ++ t_Handle h_Arg) ++{ ++ int tmp_jiffies = (msecs*HZ)/1000; ++ struct timer_list *p_Timer = (struct timer_list *)h_Timer; ++ ++ SANITY_CHECK_RETURN((periodic == FALSE), E_NOT_SUPPORTED); ++ ++ p_Timer->function = (void (*)(unsigned long))f_TimerExpired; ++ p_Timer->data = (unsigned long)h_Arg; ++ if ((msecs*HZ)%1000) ++ tmp_jiffies++; ++ p_Timer->expires = (jiffies + tmp_jiffies); ++ ++ add_timer((struct timer_list *)h_Timer); ++} ++ ++void XX_SetTimerData(t_Handle h_Timer, t_Handle data) ++{ ++ struct timer_list *p_Timer = (struct timer_list *)h_Timer; ++ ++ p_Timer->data = (unsigned long)data; ++} ++ ++t_Handle XX_GetTimerData(t_Handle h_Timer) ++{ ++ struct timer_list *p_Timer = (struct timer_list *)h_Timer; ++ ++ return (t_Handle)p_Timer->data; ++} ++ ++uint32_t XX_GetExpirationTime(t_Handle h_Timer) ++{ ++ struct timer_list *p_Timer = (struct timer_list *)h_Timer; ++ ++ return (uint32_t)p_Timer->expires; ++} ++ ++void XX_StopTimer(t_Handle h_Timer) ++{ ++ del_timer((struct timer_list *)h_Timer); ++} ++ ++void XX_ModTimer(t_Handle h_Timer, uint32_t msecs) ++{ ++ int tmp_jiffies = (msecs*HZ)/1000; ++ ++ if ((msecs*HZ)%1000) ++ tmp_jiffies++; ++ mod_timer((struct timer_list *)h_Timer, jiffies + tmp_jiffies); ++} ++ ++int XX_TimerIsActive(t_Handle h_Timer) ++{ ++ return timer_pending((struct timer_list *)h_Timer); ++} ++ ++uint32_t XX_Sleep(uint32_t msecs) ++{ ++ int tmp_jiffies = (msecs*HZ)/1000; ++ ++ if ((msecs*HZ)%1000) ++ tmp_jiffies++; ++ return schedule_timeout(tmp_jiffies); ++} ++ ++/*BEWARE!!!!! UDelay routine is BUSY WAITTING!!!!!*/ ++void XX_UDelay(uint32_t usecs) ++{ ++ udelay(usecs); ++} ++ ++/* TODO: verify that these are correct */ ++#define MSG_BODY_SIZE 512 ++typedef t_Error (t_MsgHandler) (t_Handle h_Mod, uint32_t msgId, uint8_t msgBody[MSG_BODY_SIZE]); ++typedef void (t_MsgCompletionCB) (t_Handle h_Arg, uint8_t msgBody[MSG_BODY_SIZE]); ++t_Error XX_SendMessage(char *p_DestAddr, ++ uint32_t msgId, ++ uint8_t msgBody[MSG_BODY_SIZE], ++ t_MsgCompletionCB *f_CompletionCB, ++ t_Handle h_CBArg); ++ ++typedef struct { ++ char *p_Addr; ++ t_MsgHandler *f_MsgHandlerCB; ++ t_Handle h_Mod; ++ t_List node; ++} t_MsgHndlr; ++#define MSG_HNDLR_OBJECT(ptr) LIST_OBJECT(ptr, t_MsgHndlr, node) ++ ++LIST(msgHndlrList); ++ ++static void EnqueueMsgHndlr(t_MsgHndlr *p_MsgHndlr) ++{ ++ uint32_t intFlags; ++ ++ intFlags = XX_DisableAllIntr(); ++ LIST_AddToTail(&p_MsgHndlr->node, &msgHndlrList); ++ XX_RestoreAllIntr(intFlags); ++} ++/* TODO: add this for multi-platform support ++static t_MsgHndlr * DequeueMsgHndlr(void) ++{ ++ t_MsgHndlr *p_MsgHndlr = NULL; ++ uint32_t intFlags; ++ ++ intFlags = XX_DisableAllIntr(); ++ if (!LIST_IsEmpty(&msgHndlrList)) ++ { ++ p_MsgHndlr = MSG_HNDLR_OBJECT(msgHndlrList.p_Next); ++ LIST_DelAndInit(&p_MsgHndlr->node); ++ } ++ XX_RestoreAllIntr(intFlags); ++ ++ return p_MsgHndlr; ++} ++*/ ++static t_MsgHndlr * FindMsgHndlr(char *p_Addr) ++{ ++ t_MsgHndlr *p_MsgHndlr; ++ t_List *p_Pos; ++ ++ LIST_FOR_EACH(p_Pos, &msgHndlrList) ++ { ++ p_MsgHndlr = MSG_HNDLR_OBJECT(p_Pos); ++ if (strstr(p_MsgHndlr->p_Addr, p_Addr)) ++ return p_MsgHndlr; ++ } ++ ++ return NULL; ++} ++ ++t_Error XX_RegisterMessageHandler (char *p_Addr, t_MsgHandler *f_MsgHandlerCB, t_Handle h_Mod) ++{ ++ t_MsgHndlr *p_MsgHndlr; ++ uint32_t len; ++ ++ p_MsgHndlr = (t_MsgHndlr*)XX_Malloc(sizeof(t_MsgHndlr)); ++ if (!p_MsgHndlr) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("message handler object!!!")); ++ memset(p_MsgHndlr, 0, sizeof(t_MsgHndlr)); ++ ++ len = strlen(p_Addr); ++ p_MsgHndlr->p_Addr = (char*)XX_Malloc(len+1); ++ strncpy(p_MsgHndlr->p_Addr,p_Addr, (uint32_t)(len+1)); ++ ++ p_MsgHndlr->f_MsgHandlerCB = f_MsgHandlerCB; ++ p_MsgHndlr->h_Mod = h_Mod; ++ INIT_LIST(&p_MsgHndlr->node); ++ EnqueueMsgHndlr(p_MsgHndlr); ++ ++ return E_OK; ++} ++ ++t_Error XX_UnregisterMessageHandler (char *p_Addr) ++{ ++ t_MsgHndlr *p_MsgHndlr = FindMsgHndlr(p_Addr); ++ if (!p_MsgHndlr) ++ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!")); ++ ++ LIST_Del(&p_MsgHndlr->node); ++ XX_Free(p_MsgHndlr->p_Addr); ++ XX_Free(p_MsgHndlr); ++ ++ return E_OK; ++} ++ ++t_Error XX_SendMessage(char *p_DestAddr, ++ uint32_t msgId, ++ uint8_t msgBody[MSG_BODY_SIZE], ++ t_MsgCompletionCB *f_CompletionCB, ++ t_Handle h_CBArg) ++{ ++ t_Error ans; ++ t_MsgHndlr *p_MsgHndlr = FindMsgHndlr(p_DestAddr); ++ if (!p_MsgHndlr) ++ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!")); ++ ++ ans = p_MsgHndlr->f_MsgHandlerCB(p_MsgHndlr->h_Mod, msgId, msgBody); ++ ++ if (f_CompletionCB) ++ f_CompletionCB(h_CBArg, msgBody); ++ ++ return ans; ++} ++ ++t_Error XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH], ++ t_IpcMsgHandler *f_MsgHandler, ++ t_Handle h_Module, ++ uint32_t replyLength) ++{ ++ UNUSED(addr);UNUSED(f_MsgHandler);UNUSED(h_Module);UNUSED(replyLength); ++ return E_OK; ++} ++ ++t_Error XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH]) ++{ ++ UNUSED(addr); ++ return E_OK; ++} ++ ++ ++t_Error XX_IpcSendMessage(t_Handle h_Session, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength, ++ t_IpcMsgCompletion *f_Completion, ++ t_Handle h_Arg) ++{ ++ UNUSED(h_Session); UNUSED(p_Msg); UNUSED(msgLength); UNUSED(p_Reply); ++ UNUSED(p_ReplyLength); UNUSED(f_Completion); UNUSED(h_Arg); ++ return E_OK; ++} ++ ++t_Handle XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH], ++ char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH]) ++{ ++ UNUSED(destAddr); UNUSED(srcAddr); ++ return E_OK; ++} ++ ++/*Forced to introduce due to PRINT_FMT_PARAMS define*/ ++uint32_t E500_GetId(void) ++{ ++ return raw_smp_processor_id(); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) ++int GetDeviceIrqNum(int irq) ++{ ++ struct device_node *iPar; ++ struct irq_host *irqHost; ++ uint32_t hwIrq; ++ ++ /* Get the interrupt controller */ ++ iPar = of_find_node_by_name(NULL, "mpic"); ++ hwIrq = 0; ++ ++ ASSERT_COND(iPar != NULL); ++ /* Get the irq host */ ++ irqHost = irq_find_host(iPar); ++ of_node_put(iPar); ++ ++ /* Create irq mapping */ ++ return irq_create_mapping(irqHost, hwIrq); ++} ++#else ++#error "kernel not supported!!!" ++#endif /* LINUX_VERSION_CODE */ ++ ++void * XX_PhysToVirt(physAddress_t addr) ++{ ++ return UINT_TO_PTR(SYS_PhysToVirt((uint64_t)addr)); ++} ++ ++physAddress_t XX_VirtToPhys(void * addr) ++{ ++ return (physAddress_t)SYS_VirtToPhys(PTR_TO_UINT(addr)); ++} ++ ++void * xx_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment) ++{ ++ uintptr_t *returnCode, tmp; ++ ++ if (alignment < sizeof(uintptr_t)) ++ alignment = sizeof(uintptr_t); ++ size += alignment + sizeof(returnCode); ++ tmp = (uintptr_t)xx_Malloc(size); ++ if (tmp == 0) ++ return NULL; ++ returnCode = (uintptr_t*)((tmp + alignment + sizeof(returnCode)) & ~((uintptr_t)alignment - 1)); ++ *(returnCode - 1) = tmp; ++ ++ return (void*)returnCode; ++} ++ ++void xx_FreeSmart(void *p) ++{ ++ xx_Free((void*)(*((uintptr_t *)(p) - 1))); ++} +diff --git a/drivers/net/dpa/NetCommSw/t4240_dflags.h b/drivers/net/dpa/NetCommSw/t4240_dflags.h +new file mode 100644 +index 0000000..435b0d2 +--- /dev/null ++++ b/drivers/net/dpa/NetCommSw/t4240_dflags.h +@@ -0,0 +1,57 @@ ++/* ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __dflags_h ++#define __dflags_h ++ ++ ++#define NCSW_LINUX ++ ++#define T4240 ++#define NCSW_PPC_CORE ++ ++#define DEBUG_ERRORS 1 ++ ++#if defined(DEBUG) ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_INFO ++ ++#define DEBUG_XX_MALLOC ++#define DEBUG_MEM_LEAKS ++ ++#else ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING ++#endif /* (DEBUG) */ ++ ++#define REPORT_EVENTS 1 ++#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR ++ ++#endif /* __dflags_h */ +diff --git a/drivers/net/dpa/dpa-ethtool.c b/drivers/net/dpa/dpa-ethtool.c +new file mode 100644 +index 0000000..11bcf3e +--- /dev/null ++++ b/drivers/net/dpa/dpa-ethtool.c +@@ -0,0 +1,241 @@ ++/* Copyright 2008-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++ ++#include ++ ++#include "dpaa_eth.h" ++ ++static int __cold dpa_get_settings(struct net_device *net_dev, struct ethtool_cmd *et_cmd) ++{ ++ int _errno; ++ struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ ++ if (priv->mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return -ENODEV; ++ } ++ if (unlikely(priv->mac_dev->phy_dev == NULL)) { ++ netdev_err(net_dev, "phy device not initialized\n"); ++ return -ENODEV; ++ } ++ ++ _errno = phy_ethtool_gset(priv->mac_dev->phy_dev, et_cmd); ++ if (unlikely(_errno < 0)) ++ netdev_err(net_dev, "phy_ethtool_gset() = %d\n", _errno); ++ ++ return _errno; ++} ++ ++static int __cold dpa_set_settings(struct net_device *net_dev, struct ethtool_cmd *et_cmd) ++{ ++ int _errno; ++ struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ ++ if (priv->mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return -ENODEV; ++ } ++ if (unlikely(priv->mac_dev->phy_dev == NULL)) { ++ netdev_err(net_dev, "phy device not initialized\n"); ++ return -ENODEV; ++ } ++ ++ _errno = phy_ethtool_sset(priv->mac_dev->phy_dev, et_cmd); ++ if (unlikely(_errno < 0)) ++ netdev_err(net_dev, "phy_ethtool_sset() = %d\n", _errno); ++ ++ return _errno; ++} ++ ++static void __cold dpa_get_drvinfo(struct net_device *net_dev, struct ethtool_drvinfo *drvinfo) ++{ ++ int _errno; ++ ++ strncpy(drvinfo->driver, KBUILD_MODNAME, ++ sizeof(drvinfo->driver) - 1)[sizeof(drvinfo->driver)-1] = 0; ++ strncpy(drvinfo->version, VERSION, ++ sizeof(drvinfo->driver) - 1)[sizeof(drvinfo->version)-1] = 0; ++ _errno = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%X", 0); ++ ++ if (unlikely(_errno >= sizeof(drvinfo->fw_version))) { /* Truncated output */ ++ netdev_notice(net_dev, "snprintf() = %d\n", _errno); ++ } else if (unlikely(_errno < 0)) { ++ netdev_warn(net_dev, "snprintf() = %d\n", _errno); ++ memset(drvinfo->fw_version, 0, sizeof(drvinfo->fw_version)); ++ } ++ strncpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent), ++ sizeof(drvinfo->bus_info) - 1)[sizeof(drvinfo->bus_info)-1] = 0; ++} ++ ++uint32_t __cold dpa_get_msglevel(struct net_device *net_dev) ++{ ++ return ((struct dpa_priv_s *)netdev_priv(net_dev))->msg_enable; ++} ++ ++void __cold dpa_set_msglevel(struct net_device *net_dev, uint32_t msg_enable) ++{ ++ ((struct dpa_priv_s *)netdev_priv(net_dev))->msg_enable = msg_enable; ++} ++ ++int __cold dpa_nway_reset(struct net_device *net_dev) ++{ ++ int _errno; ++ struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ ++ if (priv->mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return -ENODEV; ++ } ++ if (unlikely(priv->mac_dev->phy_dev == NULL)) { ++ netdev_err(net_dev, "phy device not initialized\n"); ++ return -ENODEV; ++ } ++ ++ _errno = 0; ++ if (priv->mac_dev->phy_dev->autoneg) { ++ _errno = phy_start_aneg(priv->mac_dev->phy_dev); ++ if (unlikely(_errno < 0)) ++ netdev_err(net_dev, "phy_start_aneg() = %d\n", ++ _errno); ++ } ++ ++ return _errno; ++} ++ ++void __cold dpa_get_ringparam(struct net_device *net_dev, struct ethtool_ringparam *et_ringparam) ++{ ++ et_ringparam->rx_max_pending = 0; ++ et_ringparam->rx_mini_max_pending = 0; ++ et_ringparam->rx_jumbo_max_pending = 0; ++ et_ringparam->tx_max_pending = 0; ++ ++ et_ringparam->rx_pending = 0; ++ et_ringparam->rx_mini_pending = 0; ++ et_ringparam->rx_jumbo_pending = 0; ++ et_ringparam->tx_pending = 0; ++} ++ ++void __cold dpa_get_pauseparam(struct net_device *net_dev, struct ethtool_pauseparam *et_pauseparam) ++{ ++ struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ ++ if (priv->mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return; ++ } ++ if (unlikely(priv->mac_dev->phy_dev == NULL)) { ++ netdev_err(net_dev, "phy device not initialized\n"); ++ return; ++ } ++ ++ et_pauseparam->autoneg = priv->mac_dev->phy_dev->autoneg; ++} ++ ++int __cold dpa_set_pauseparam(struct net_device *net_dev, struct ethtool_pauseparam *et_pauseparam) ++{ ++ struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ ++ if (priv->mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return -ENODEV; ++ } ++ if (unlikely(priv->mac_dev->phy_dev == NULL)) { ++ netdev_err(net_dev, "phy device not initialized\n"); ++ return -ENODEV; ++ } ++ ++ priv->mac_dev->phy_dev->autoneg = et_pauseparam->autoneg; ++ ++ return 0; ++} ++ ++u32 dpa_get_rx_csum(struct net_device *dev) ++{ ++ netdev_info(dev, "Can't automatically tell the status of " ++ "Rx checksum validation. Feature not available yet.\n" ++ "Rx csum validation is most commonly performed (for supported " ++ "protocols) if a PCD scheme is applied on this interface.\n"); ++ return 0; ++} ++ ++int dpa_set_rx_csum(struct net_device *dev, uint32_t data) ++{ ++ netdev_info(dev, "Can't automatically %s Rx checksum validation." ++ "Feature not available yet.\n" ++ "Rx csum validation is most commonly performed (for supported " ++ "protocols) if a PCD scheme is applied on this interface.\n", ++ data ? "enable" : "disable"); ++ return -EINVAL; ++} ++ ++static int dpa_eth_op_set_flags(struct net_device *dev, u32 data) ++{ ++ return -EINVAL; ++} ++ ++const struct ethtool_ops dpa_ethtool_ops __devinitconst = { ++ .get_settings = dpa_get_settings, ++ .set_settings = dpa_set_settings, ++ .get_drvinfo = dpa_get_drvinfo, ++ .get_msglevel = dpa_get_msglevel, ++ .set_msglevel = dpa_set_msglevel, ++ .nway_reset = dpa_nway_reset, ++ .get_link = ethtool_op_get_link, ++ .get_ringparam = dpa_get_ringparam, ++ .get_pauseparam = dpa_get_pauseparam, ++ .set_pauseparam = dpa_set_pauseparam, ++ .get_tx_csum = ethtool_op_get_tx_csum, ++ .set_tx_csum = ethtool_op_set_tx_ipv6_csum, ++ .get_rx_csum = dpa_get_rx_csum, ++ .set_rx_csum = dpa_set_rx_csum, ++ .get_sg = ethtool_op_get_sg, ++ .set_sg = ethtool_op_set_sg, ++ .get_tso = ethtool_op_get_tso, ++ .set_tso = ethtool_op_set_tso, ++ .get_ufo = ethtool_op_get_ufo, ++ .set_ufo = ethtool_op_set_ufo, ++ .get_flags = ethtool_op_get_flags, ++ .set_flags = dpa_eth_op_set_flags, ++}; +diff --git a/drivers/net/dpa/dpaa_1588.c b/drivers/net/dpa/dpaa_1588.c +new file mode 100644 +index 0000000..8413b1e +--- /dev/null ++++ b/drivers/net/dpa/dpaa_1588.c +@@ -0,0 +1,621 @@ ++/* ++ * drivers/net/dpa/dpaa_1588.c ++ * ++ * Copyright (C) 2011 Freescale Semiconductor, Inc. ++ * Copyright (C) 2009 IXXAT Automation, GmbH ++ * ++ * DPAA Ethernet Driver -- IEEE 1588 interface functionality ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dpaa_eth.h" ++#include "dpaa_1588.h" ++ ++static int dpa_ptp_init_circ(struct dpa_ptp_circ_buf *ptp_buf, u32 size) ++{ ++ struct circ_buf *circ_buf = &ptp_buf->circ_buf; ++ ++ circ_buf->buf = vmalloc(sizeof(struct dpa_ptp_data) * size); ++ if (!circ_buf->buf) ++ return 1; ++ ++ circ_buf->head = 0; ++ circ_buf->tail = 0; ++ ptp_buf->size = size; ++ spin_lock_init(&ptp_buf->ptp_lock); ++ ++ return 0; ++} ++ ++static void dpa_ptp_reset_circ(struct dpa_ptp_circ_buf *ptp_buf, u32 size) ++{ ++ struct circ_buf *circ_buf = &ptp_buf->circ_buf; ++ ++ circ_buf->head = 0; ++ circ_buf->tail = 0; ++ ptp_buf->size = size; ++} ++ ++static int dpa_ptp_insert(struct dpa_ptp_circ_buf *ptp_buf, ++ struct dpa_ptp_data *data) ++{ ++ struct circ_buf *circ_buf = &ptp_buf->circ_buf; ++ int size = ptp_buf->size; ++ struct dpa_ptp_data *tmp; ++ unsigned long flags; ++ int head, tail; ++ ++ spin_lock_irqsave(&ptp_buf->ptp_lock, flags); ++ ++ head = circ_buf->head; ++ tail = circ_buf->tail; ++ ++ if (CIRC_SPACE(head, tail, size) <= 0) ++ circ_buf->tail = (tail + 1) & (size - 1); ++ ++ tmp = (struct dpa_ptp_data *)(circ_buf->buf) + head; ++ memcpy(tmp, data, sizeof(struct dpa_ptp_data)); ++ ++ circ_buf->head = (head + 1) & (size - 1); ++ ++ spin_unlock_irqrestore(&ptp_buf->ptp_lock, flags); ++ ++ return 0; ++} ++ ++static int dpa_ptp_is_ident_match(struct dpa_ptp_ident *dst, ++ struct dpa_ptp_ident *src) ++{ ++ int ret; ++ ++ if ((dst->version != src->version) || (dst->msg_type != src->msg_type)) ++ return 0; ++ ++ if ((dst->netw_prot == src->netw_prot) ++ || src->netw_prot == DPA_PTP_PROT_DONTCARE) { ++ if (dst->seq_id != src->seq_id) ++ return 0; ++ ++ ret = memcmp(dst->snd_port_id, src->snd_port_id, ++ DPA_PTP_SOURCE_PORT_LENGTH); ++ if (ret) ++ return 0; ++ else ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int dpa_ptp_find_and_remove(struct dpa_ptp_circ_buf *ptp_buf, ++ struct dpa_ptp_ident *ident, ++ struct dpa_ptp_time *ts) ++{ ++ struct circ_buf *circ_buf = &ptp_buf->circ_buf; ++ int size = ptp_buf->size; ++ int head, tail, idx; ++ unsigned long flags; ++ struct dpa_ptp_data *tmp, *tmp2; ++ struct dpa_ptp_ident *tmp_ident; ++ ++ spin_lock_irqsave(&ptp_buf->ptp_lock, flags); ++ ++ head = circ_buf->head; ++ tail = idx = circ_buf->tail; ++ ++ if (CIRC_CNT(head, tail, size) == 0) { ++ spin_unlock_irqrestore(&ptp_buf->ptp_lock, flags); ++ return 1; ++ } ++ ++ while (idx != head) { ++ tmp = (struct dpa_ptp_data *)(circ_buf->buf) + idx; ++ tmp_ident = &tmp->ident; ++ if (dpa_ptp_is_ident_match(tmp_ident, ident)) ++ break; ++ idx = (idx + 1) & (size - 1); ++ } ++ ++ if (idx == head) { ++ spin_unlock_irqrestore(&ptp_buf->ptp_lock, flags); ++ return 1; ++ } ++ ++ ts->sec = tmp->ts.sec; ++ ts->nsec = tmp->ts.nsec; ++ ++ if (idx != tail) { ++ while (CIRC_CNT(idx, tail, size) > 0) { ++ tmp = (struct dpa_ptp_data *)(circ_buf->buf) + idx; ++ idx = (idx - 1) & (size - 1); ++ tmp2 = (struct dpa_ptp_data *)(circ_buf->buf) + idx; ++ *tmp = *tmp2; ++ } ++ } ++ circ_buf->tail = (tail + 1) & (size - 1); ++ ++ spin_unlock_irqrestore(&ptp_buf->ptp_lock, flags); ++ ++ return 0; ++} ++ ++static int dpa_ptp_get_time(dma_addr_t fd_addr, u32 *high, u32 *low) ++{ ++ u8 *ts_addr = (u8 *)phys_to_virt(fd_addr); ++ u32 sec, nsec, mod; ++ u64 tmp; ++ ++ ts_addr += DPA_PTP_TIMESTAMP_OFFSET; ++ sec = *((u32 *)ts_addr); ++ nsec = *(((u32 *)ts_addr) + 1); ++ tmp = ((u64)sec << 32 | nsec) * DPA_PTP_NOMINAL_FREQ_PERIOD; ++ ++ mod = do_div(tmp, NANOSEC_PER_SECOND); ++ *high = (u32)tmp; ++ *low = mod; ++ ++ return 0; ++} ++ ++/* ++ * Parse the PTP packets ++ * ++ * The PTP header can be found in an IPv4 packet, IPv6 patcket or in ++ * an IEEE802.3 ethernet frame. This function returns the position of ++ * the PTP packet or NULL if no PTP found ++ */ ++static u8 *dpa_ptp_parse_packet(struct sk_buff *skb, u16 *eth_type) ++{ ++ u8 *pos = skb->data + ETH_ALEN + ETH_ALEN; ++ u8 *ptp_loc = NULL; ++ u8 msg_type; ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ u32 access_len = ETH_ALEN + ETH_ALEN + DPA_ETYPE_LEN; ++#endif ++ struct iphdr *iph; ++ struct udphdr *udph; ++ struct ipv6hdr *ipv6h; ++ ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ /* when we can receive S/G frames we need to check the data we want to ++ * access is in the linear skb buffer */ ++ if (!pskb_may_pull(skb, access_len)) ++ return NULL; ++#endif ++ ++ *eth_type = *((u16 *)pos); ++ ++ /* Check if inner tag is here */ ++ if (*eth_type == ETH_P_8021Q) { ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ access_len += DPA_VLAN_TAG_LEN; ++ ++ if (!pskb_may_pull(skb, access_len)) ++ return NULL; ++#endif ++ ++ pos += DPA_VLAN_TAG_LEN; ++ *eth_type = *((u16 *)pos); ++ } ++ ++ pos += DPA_ETYPE_LEN; ++ ++ switch (*eth_type) { ++ /* Transport of PTP over Ethernet */ ++ case ETH_P_1588: ++ ptp_loc = pos; ++ ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ if (!pskb_may_pull(skb, access_len + PTP_OFFS_MSG_TYPE + 1)) ++ return NULL; ++#endif ++ ++ msg_type = *((u8 *)(ptp_loc + PTP_OFFS_MSG_TYPE)) & 0xf; ++ if ((msg_type == PTP_MSGTYPE_SYNC) ++ || (msg_type == PTP_MSGTYPE_DELREQ) ++ || (msg_type == PTP_MSGTYPE_PDELREQ) ++ || (msg_type == PTP_MSGTYPE_PDELRESP)) ++ return ptp_loc; ++ break; ++ /* Transport of PTP over IPv4 */ ++ case ETH_P_IP: ++ iph = (struct iphdr *)pos; ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ access_len += sizeof(struct iphdr); ++ ++ if (!pskb_may_pull(skb, access_len)) ++ return NULL; ++#endif ++ ++ if (ntohs(iph->protocol) != IPPROTO_UDP) ++ return NULL; ++ ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ access_len += iph->ihl * 4 - sizeof(struct iphdr) + ++ sizeof(struct udphdr); ++ ++ if (!pskb_may_pull(skb, access_len)) ++ return NULL; ++#endif ++ ++ pos += iph->ihl * 4; ++ udph = (struct udphdr *)pos; ++ if (ntohs(udph->dest) != 319) ++ return NULL; ++ ptp_loc = pos + sizeof(struct udphdr); ++ break; ++ /* Transport of PTP over IPv6 */ ++ case ETH_P_IPV6: ++ ipv6h = (struct ipv6hdr *)pos; ++ ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ access_len += sizeof(struct ipv6hdr) + sizeof(struct udphdr); ++#endif ++ ++ if (ntohs(ipv6h->nexthdr) != IPPROTO_UDP) ++ return NULL; ++ ++ pos += sizeof(struct ipv6hdr); ++ udph = (struct udphdr *)pos; ++ if (ntohs(udph->dest) != 319) ++ return NULL; ++ ptp_loc = pos + sizeof(struct udphdr); ++ break; ++ default: ++ break; ++ } ++ ++ return ptp_loc; ++} ++ ++static int dpa_ptp_store_stamp(struct net_device *dev, struct sk_buff *skb, ++ dma_addr_t fd_addr, struct dpa_ptp_data *ptp_data) ++{ ++ u32 sec, nsec; ++ u8 *ptp_loc; ++ u16 eth_type; ++ ++ ptp_loc = dpa_ptp_parse_packet(skb, ð_type); ++ if (!ptp_loc) ++ return -EINVAL; ++ ++ switch (eth_type) { ++ case ETH_P_IP: ++ ptp_data->ident.netw_prot = DPA_PTP_PROT_IPV4; ++ break; ++ case ETH_P_IPV6: ++ ptp_data->ident.netw_prot = DPA_PTP_PROT_IPV6; ++ break; ++ case ETH_P_1588: ++ ptp_data->ident.netw_prot = DPA_PTP_PROT_802_3; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ if (!pskb_may_pull(skb, ptp_loc - skb->data + PTP_OFFS_SEQ_ID + 2)) ++ return -EINVAL; ++#endif ++ ++ ptp_data->ident.version = *(ptp_loc + PTP_OFFS_VER_PTP) & 0xf; ++ ptp_data->ident.msg_type = *(ptp_loc + PTP_OFFS_MSG_TYPE) & 0xf; ++ ptp_data->ident.seq_id = *((u16 *)(ptp_loc + PTP_OFFS_SEQ_ID)); ++ memcpy(ptp_data->ident.snd_port_id, ptp_loc + PTP_OFFS_SRCPRTID, ++ DPA_PTP_SOURCE_PORT_LENGTH); ++ ++ dpa_ptp_get_time(fd_addr, &sec, &nsec); ++ ptp_data->ts.sec = (u64)sec; ++ ptp_data->ts.nsec = nsec; ++ ++ return 0; ++} ++ ++void dpa_ptp_store_txstamp(struct net_device *dev, struct sk_buff *skb, ++ const struct qm_fd *fd) ++{ ++ struct dpa_priv_s *priv = netdev_priv(dev); ++ struct dpa_ptp_tsu *tsu = priv->tsu; ++ struct dpa_ptp_data ptp_tx_data; ++ dma_addr_t fd_addr = qm_fd_addr(fd); ++ int ret; ++ ++ ret = dpa_ptp_store_stamp(dev, skb, fd_addr, &ptp_tx_data); ++ if (ret) ++ return; ++ dpa_ptp_insert(&tsu->tx_timestamps, &ptp_tx_data); ++} ++ ++void dpa_ptp_store_rxstamp(struct net_device *dev, struct sk_buff *skb, ++ const struct qm_fd *fd) ++{ ++ struct dpa_priv_s *priv = netdev_priv(dev); ++ struct dpa_ptp_tsu *tsu = priv->tsu; ++ struct dpa_ptp_data ptp_rx_data; ++ dma_addr_t fd_addr = qm_fd_addr(fd); ++ int ret; ++ ++ ret = dpa_ptp_store_stamp(dev, skb, ++ fd_addr + fm_get_rx_extra_headroom(), ++ &ptp_rx_data); ++ if (ret) ++ return; ++ dpa_ptp_insert(&tsu->rx_timestamps, &ptp_rx_data); ++} ++ ++static uint8_t dpa_get_tx_timestamp(struct dpa_ptp_tsu *ptp_tsu, ++ struct dpa_ptp_ident *ident, ++ struct dpa_ptp_time *ts) ++{ ++ struct dpa_ptp_tsu *tsu = ptp_tsu; ++ struct dpa_ptp_time tmp; ++ int flag; ++ ++ flag = dpa_ptp_find_and_remove(&tsu->tx_timestamps, ident, &tmp); ++ if (!flag) { ++ ts->sec = tmp.sec; ++ ts->nsec = tmp.nsec; ++ return 0; ++ } ++ ++ return -1; ++} ++ ++static uint8_t dpa_get_rx_timestamp(struct dpa_ptp_tsu *ptp_tsu, ++ struct dpa_ptp_ident *ident, ++ struct dpa_ptp_time *ts) ++{ ++ struct dpa_ptp_tsu *tsu = ptp_tsu; ++ struct dpa_ptp_time tmp; ++ int flag; ++ ++ flag = dpa_ptp_find_and_remove(&tsu->rx_timestamps, ident, &tmp); ++ if (!flag) { ++ ts->sec = tmp.sec; ++ ts->nsec = tmp.nsec; ++ return 0; ++ } ++ ++ return -1; ++} ++ ++static void dpa_set_fiper_alarm(struct dpa_ptp_tsu *tsu, ++ struct dpa_ptp_time *cnt_time) ++{ ++ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev; ++ u64 tmp, fiper; ++ ++ if (mac_dev->fm_rtc_disable) ++ mac_dev->fm_rtc_disable(tsu->dpa_priv->net_dev); ++ ++ /* TMR_FIPER1 will pulse every second after ALARM1 expired */ ++ tmp = (u64)cnt_time->sec * NANOSEC_PER_SECOND + (u64)cnt_time->nsec; ++ fiper = NANOSEC_PER_SECOND - DPA_PTP_NOMINAL_FREQ_PERIOD; ++ if (mac_dev->fm_rtc_set_alarm) ++ mac_dev->fm_rtc_set_alarm(tsu->dpa_priv->net_dev, 0, tmp); ++ if (mac_dev->fm_rtc_set_fiper) ++ mac_dev->fm_rtc_set_fiper(tsu->dpa_priv->net_dev, 0, fiper); ++ ++ if (mac_dev->fm_rtc_enable) ++ mac_dev->fm_rtc_enable(tsu->dpa_priv->net_dev); ++} ++ ++static void dpa_get_curr_cnt(struct dpa_ptp_tsu *tsu, ++ struct dpa_ptp_time *curr_time) ++{ ++ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev; ++ u64 tmp; ++ u32 mod; ++ ++ if (mac_dev->fm_rtc_get_cnt) ++ mac_dev->fm_rtc_get_cnt(tsu->dpa_priv->net_dev, &tmp); ++ ++ mod = do_div(tmp, NANOSEC_PER_SECOND); ++ curr_time->sec = (u32)tmp; ++ curr_time->nsec = mod; ++} ++ ++static void dpa_set_1588cnt(struct dpa_ptp_tsu *tsu, ++ struct dpa_ptp_time *cnt_time) ++{ ++ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev; ++ u64 tmp; ++ ++ tmp = (u64)cnt_time->sec * NANOSEC_PER_SECOND + (u64)cnt_time->nsec; ++ ++ if (mac_dev->fm_rtc_set_cnt) ++ mac_dev->fm_rtc_set_cnt(tsu->dpa_priv->net_dev, tmp); ++ ++ /* Restart fiper two seconds later */ ++ cnt_time->sec += 2; ++ cnt_time->nsec = 0; ++ dpa_set_fiper_alarm(tsu, cnt_time); ++} ++ ++static void dpa_get_drift(struct dpa_ptp_tsu *tsu, u32 *addend) ++{ ++ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev; ++ u32 drift; ++ ++ if (mac_dev->fm_rtc_get_drift) ++ mac_dev->fm_rtc_get_drift(tsu->dpa_priv->net_dev, &drift); ++ ++ *addend = drift; ++} ++ ++static void dpa_set_drift(struct dpa_ptp_tsu *tsu, u32 addend) ++{ ++ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev; ++ ++ if (mac_dev->fm_rtc_set_drift) ++ mac_dev->fm_rtc_set_drift(tsu->dpa_priv->net_dev, addend); ++} ++ ++static void dpa_flush_timestamp(struct dpa_ptp_tsu *tsu) ++{ ++ dpa_ptp_reset_circ(&tsu->rx_timestamps, DEFAULT_PTP_RX_BUF_SZ); ++ dpa_ptp_reset_circ(&tsu->tx_timestamps, DEFAULT_PTP_TX_BUF_SZ); ++} ++ ++int dpa_ioctl_1588(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ struct dpa_priv_s *priv = netdev_priv(dev); ++ struct dpa_ptp_tsu *tsu = priv->tsu; ++ struct mac_device *mac_dev = priv->mac_dev; ++ struct dpa_ptp_data ptp_data; ++ struct dpa_ptp_data *ptp_data_user; ++ struct dpa_ptp_time act_time; ++ u32 addend; ++ int retval = 0; ++ ++ if (!tsu || !tsu->valid) ++ return -ENODEV; ++ ++ switch (cmd) { ++ case PTP_ENBL_TXTS_IOCTL: ++ tsu->hwts_tx_en_ioctl = 1; ++ if (mac_dev->fm_rtc_enable) ++ mac_dev->fm_rtc_enable(dev); ++ if (mac_dev->ptp_enable) ++ mac_dev->ptp_enable(mac_dev); ++ break; ++ case PTP_DSBL_TXTS_IOCTL: ++ tsu->hwts_tx_en_ioctl = 0; ++ if (mac_dev->fm_rtc_disable) ++ mac_dev->fm_rtc_disable(dev); ++ if (mac_dev->ptp_disable) ++ mac_dev->ptp_disable(mac_dev); ++ break; ++ case PTP_ENBL_RXTS_IOCTL: ++ tsu->hwts_rx_en_ioctl = 1; ++ break; ++ case PTP_DSBL_RXTS_IOCTL: ++ tsu->hwts_rx_en_ioctl = 0; ++ break; ++ case PTP_GET_RX_TIMESTAMP: ++ ptp_data_user = (struct dpa_ptp_data *)ifr->ifr_data; ++ if (copy_from_user(&ptp_data.ident, ++ &ptp_data_user->ident, sizeof(ptp_data.ident))) ++ return -EINVAL; ++ ++ if (dpa_get_rx_timestamp(tsu, &ptp_data.ident, &ptp_data.ts)) ++ return -EAGAIN; ++ ++ if (copy_to_user((void __user *)&ptp_data_user->ts, ++ &ptp_data.ts, sizeof(ptp_data.ts))) ++ return -EFAULT; ++ break; ++ case PTP_GET_TX_TIMESTAMP: ++ ptp_data_user = (struct dpa_ptp_data *)ifr->ifr_data; ++ if (copy_from_user(&ptp_data.ident, ++ &ptp_data_user->ident, sizeof(ptp_data.ident))) ++ return -EINVAL; ++ ++ if (dpa_get_tx_timestamp(tsu, &ptp_data.ident, &ptp_data.ts)) ++ return -EAGAIN; ++ ++ if (copy_to_user((void __user *)&ptp_data_user->ts, ++ &ptp_data.ts, sizeof(ptp_data.ts))) ++ return -EFAULT; ++ break; ++ case PTP_GET_TIME: ++ dpa_get_curr_cnt(tsu, &act_time); ++ if (copy_to_user(ifr->ifr_data, &act_time, sizeof(act_time))) ++ return -EFAULT; ++ break; ++ case PTP_SET_TIME: ++ if (copy_from_user(&act_time, ifr->ifr_data, sizeof(act_time))) ++ return -EINVAL; ++ dpa_set_1588cnt(tsu, &act_time); ++ break; ++ case PTP_GET_ADJ: ++ dpa_get_drift(tsu, &addend); ++ if (copy_to_user(ifr->ifr_data, &addend, sizeof(addend))) ++ return -EFAULT; ++ break; ++ case PTP_SET_ADJ: ++ if (copy_from_user(&addend, ifr->ifr_data, sizeof(addend))) ++ return -EINVAL; ++ dpa_set_drift(tsu, addend); ++ break; ++ case PTP_SET_FIPER_ALARM: ++ if (copy_from_user(&act_time, ifr->ifr_data, sizeof(act_time))) ++ return -EINVAL; ++ dpa_set_fiper_alarm(tsu, &act_time); ++ break; ++ case PTP_CLEANUP_TS: ++ dpa_flush_timestamp(tsu); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return retval; ++} ++ ++int dpa_ptp_init(struct dpa_priv_s *priv) ++{ ++ struct dpa_ptp_tsu *tsu; ++ ++ /* Allocate memory for PTP structure */ ++ tsu = kzalloc(sizeof(struct dpa_ptp_tsu), GFP_KERNEL); ++ if (!tsu) ++ return -ENOMEM; ++ ++ memset(tsu, 0, sizeof(*tsu)); ++ tsu->valid = TRUE; ++ tsu->dpa_priv = priv; ++ ++ dpa_ptp_init_circ(&tsu->rx_timestamps, DEFAULT_PTP_RX_BUF_SZ); ++ dpa_ptp_init_circ(&tsu->tx_timestamps, DEFAULT_PTP_TX_BUF_SZ); ++ ++ priv->tsu = tsu; ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpa_ptp_init); ++ ++void dpa_ptp_cleanup(struct dpa_priv_s *priv) ++{ ++ struct dpa_ptp_tsu *tsu = priv->tsu; ++ ++ tsu->valid = FALSE; ++ vfree(tsu->rx_timestamps.circ_buf.buf); ++ vfree(tsu->tx_timestamps.circ_buf.buf); ++ ++ kfree(tsu); ++} ++EXPORT_SYMBOL(dpa_ptp_cleanup); ++ ++static int __init __cold dpa_ptp_load(void) ++{ ++ return 0; ++} ++module_init(dpa_ptp_load); ++ ++static void __exit __cold dpa_ptp_unload(void) ++{ ++} ++module_exit(dpa_ptp_unload); +diff --git a/drivers/net/dpa/dpaa_1588.h b/drivers/net/dpa/dpaa_1588.h +new file mode 100644 +index 0000000..eda0e3a +--- /dev/null ++++ b/drivers/net/dpa/dpaa_1588.h +@@ -0,0 +1,141 @@ ++/* ++ * drivers/net/dpa/dpaa_1588.h ++ * ++ * Copyright (C) 2011 Freescale Semiconductor, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ */ ++#ifndef __DPAA_1588_H__ ++#define __DPAA_1588_H__ ++ ++#include ++#include ++#include ++#include ++ ++#define DEFAULT_PTP_RX_BUF_SZ 2048 ++#define DEFAULT_PTP_TX_BUF_SZ 1024 ++ ++/* 1588 private ioctl calls */ ++#define PTP_ENBL_TXTS_IOCTL SIOCDEVPRIVATE ++#define PTP_DSBL_TXTS_IOCTL (SIOCDEVPRIVATE + 1) ++#define PTP_ENBL_RXTS_IOCTL (SIOCDEVPRIVATE + 2) ++#define PTP_DSBL_RXTS_IOCTL (SIOCDEVPRIVATE + 3) ++#define PTP_GET_TX_TIMESTAMP (SIOCDEVPRIVATE + 4) ++#define PTP_GET_RX_TIMESTAMP (SIOCDEVPRIVATE + 5) ++#define PTP_SET_TIME (SIOCDEVPRIVATE + 6) ++#define PTP_GET_TIME (SIOCDEVPRIVATE + 7) ++#define PTP_SET_FIPER_ALARM (SIOCDEVPRIVATE + 8) ++#define PTP_SET_ADJ (SIOCDEVPRIVATE + 9) ++#define PTP_GET_ADJ (SIOCDEVPRIVATE + 10) ++#define PTP_CLEANUP_TS (SIOCDEVPRIVATE + 11) ++ ++/* PTP V2 message type */ ++enum { ++ PTP_MSGTYPE_SYNC = 0x0, ++ PTP_MSGTYPE_DELREQ = 0x1, ++ PTP_MSGTYPE_PDELREQ = 0x2, ++ PTP_MSGTYPE_PDELRESP = 0x3, ++ PTP_MSGTYPE_FLWUP = 0x8, ++ PTP_MSGTYPE_DELRESP = 0x9, ++ PTP_MSGTYPE_PDELRES_FLWUP = 0xA, ++ PTP_MSGTYPE_ANNOUNCE = 0xB, ++ PTP_MSGTYPE_SGNLNG = 0xC, ++ PTP_MSGTYPE_MNGMNT = 0xD, ++}; ++ ++/* Byte offset of data in the PTP V2 headers */ ++#define PTP_OFFS_MSG_TYPE 0 ++#define PTP_OFFS_VER_PTP 1 ++#define PTP_OFFS_MSG_LEN 2 ++#define PTP_OFFS_DOM_NMB 4 ++#define PTP_OFFS_FLAGS 6 ++#define PTP_OFFS_CORFIELD 8 ++#define PTP_OFFS_SRCPRTID 20 ++#define PTP_OFFS_SEQ_ID 30 ++#define PTP_OFFS_CTRL 32 ++#define PTP_OFFS_LOGMEAN 33 ++ ++#define PTP_IP_OFFS 14 ++#define PTP_UDP_OFFS 34 ++#define PTP_HEADER_OFFS 42 ++#define PTP_MSG_TYPE_OFFS (PTP_HEADER_OFFS + PTP_OFFS_MSG_TYPE) ++#define PTP_SPORT_ID_OFFS (PTP_HEADER_OFFS + PTP_OFFS_SRCPRTID) ++#define PTP_SEQ_ID_OFFS (PTP_HEADER_OFFS + PTP_OFFS_SEQ_ID) ++#define PTP_CTRL_OFFS (PTP_HEADER_OFFS + PTP_OFFS_CTRL) ++ ++/* 1588-2008 network protocol enumeration values */ ++#define DPA_PTP_PROT_IPV4 1 ++#define DPA_PTP_PROT_IPV6 2 ++#define DPA_PTP_PROT_802_3 3 ++#define DPA_PTP_PROT_DONTCARE 0xFFFF ++ ++#define DPA_PTP_SOURCE_PORT_LENGTH 10 ++#define DPA_PTP_HEADER_SZE 34 ++#define DPA_ETYPE_LEN 2 ++#define DPA_VLAN_TAG_LEN 4 ++ ++#define DPA_PTP_TIMESTAMP_OFFSET 0x30 ++#define DPA_PTP_NOMINAL_FREQ_PERIOD 5 /* 5ns -> 200M */ ++#define NANOSEC_PER_SECOND 1000000000 ++ ++/* Struct needed to identify a timestamp */ ++struct dpa_ptp_ident { ++ u8 version; ++ u8 msg_type; ++ u16 netw_prot; ++ u16 seq_id; ++ u8 snd_port_id[DPA_PTP_SOURCE_PORT_LENGTH]; ++}; ++ ++/* Timestamp format in 1588-2008 */ ++struct dpa_ptp_time { ++ u64 sec; /* just 48 bit used */ ++ u32 nsec; ++}; ++ ++/* needed for timestamp data over ioctl */ ++struct dpa_ptp_data { ++ struct dpa_ptp_ident ident; ++ struct dpa_ptp_time ts; ++}; ++ ++struct dpa_ptp_circ_buf { ++ struct circ_buf circ_buf; ++ u32 size; ++ spinlock_t ptp_lock; ++}; ++ ++/* PTP TSU control structure */ ++struct dpa_ptp_tsu { ++ struct dpa_priv_s *dpa_priv; ++ bool valid; ++ struct dpa_ptp_circ_buf rx_timestamps; ++ struct dpa_ptp_circ_buf tx_timestamps; ++ ++ /* HW timestamping over ioctl enabled flag */ ++ int hwts_tx_en_ioctl; ++ int hwts_rx_en_ioctl; ++}; ++ ++extern int dpa_ptp_init(struct dpa_priv_s *priv); ++extern void dpa_ptp_cleanup(struct dpa_priv_s *priv); ++extern void dpa_ptp_store_txstamp(struct net_device *dev, struct sk_buff *skb, ++ const struct qm_fd *fd); ++extern void dpa_ptp_store_rxstamp(struct net_device *dev, struct sk_buff *skb, ++ const struct qm_fd *fd); ++extern int dpa_ioctl_1588(struct net_device *dev, struct ifreq *ifr, int cmd); ++#endif +diff --git a/drivers/net/dpa/dpaa_eth-common.h b/drivers/net/dpa/dpaa_eth-common.h +new file mode 100644 +index 0000000..17c2382 +--- /dev/null ++++ b/drivers/net/dpa/dpaa_eth-common.h +@@ -0,0 +1,80 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __DPA_COMMON_H ++#define __DPA_COMMON_H ++ ++#include /* pr_*() */ ++#include /* dev_*() */ ++#include /* smp_processor_id() */ ++ ++#define __hot ++ ++#define cpu_printk(level, format, arg...) \ ++ pr_##level("cpu%d: " format, raw_smp_processor_id(), ##arg) ++ ++/* Simple enum of FQ types - used for array indexing */ ++enum {RX, TX}; ++ ++/* More detailed FQ types - used for fine-grained WQ assignments */ ++enum dpa_fq_type { ++ FQ_TYPE_RX_DEFAULT = 1, /* Rx Default FQs */ ++ FQ_TYPE_RX_ERROR, /* Rx Error FQs */ ++ FQ_TYPE_RX_PCD, /* User-defined PCDs */ ++ FQ_TYPE_TX, /* "Real" Tx FQs */ ++ FQ_TYPE_TX_CONFIRM, /* Tx Confirmation FQs (actually Rx FQs) */ ++ FQ_TYPE_TX_ERROR, /* Tx Error FQs (these are actually Rx FQs) */ ++#ifdef CONFIG_DPA_TX_RECYCLE ++ FQ_TYPE_TX_RECYCLE, /* Tx FQs for recycleable frames only */ ++#endif ++}; ++ ++ ++#define DPA_PARSE_RESULTS_SIZE sizeof(t_FmPrsResult) ++#define DPA_HASH_RESULTS_SIZE 16 ++ ++#define DPA_TX_PRIV_DATA_SIZE 16 ++ ++#define dpaa_eth_init_port(type, port, param, errq_id, defq_id, priv_size, \ ++ has_timer) \ ++{ \ ++ param.errq = errq_id; \ ++ param.defq = defq_id; \ ++ param.priv_data_size = priv_size; \ ++ param.parse_results = true; \ ++ param.hash_results = true; \ ++ param.frag_enable = false; \ ++ param.time_stamp = has_timer; \ ++ fm_set_##type##_port_params(port, ¶m); \ ++} ++ ++#endif /* __DPA_COMMON_H */ +diff --git a/drivers/net/dpa/dpaa_eth.c b/drivers/net/dpa/dpaa_eth.c +new file mode 100644 +index 0000000..23d450b +--- /dev/null ++++ b/drivers/net/dpa/dpaa_eth.c +@@ -0,0 +1,4251 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* arp_hdr_len() */ ++#include /* VLAN_HLEN */ ++#include /* struct icmphdr */ ++#include /* struct iphdr */ ++#include /* struct ipv6hdr */ ++#include /* struct udphdr */ ++#include /* struct tcphdr */ ++#include /* net_ratelimit() */ ++#include /* ETH_P_IP and ETH_P_IPV6 */ ++#include ++#include ++#include ++#include /* get_hard_smp_processor_id() */ ++#ifdef CONFIG_DEBUG_FS ++#include ++#endif ++#include ++ ++#include "fsl_fman.h" ++#include "fm_ext.h" ++#include "fm_port_ext.h" ++ ++#include "mac.h" ++#include "dpaa_eth.h" ++#include "dpaa_1588.h" ++ ++#define ARRAY2_SIZE(arr) (ARRAY_SIZE(arr) * ARRAY_SIZE((arr)[0])) ++ ++/* DPAA platforms benefit from hardware-assisted queue management */ ++#define DPA_NETIF_FEATURES (NETIF_F_HW_QDISC | NETIF_F_HW_ACCEL_MQ) ++ ++#define DEFAULT_COUNT 128 ++#define REFILL_THRESHOLD 80 ++ ++#define DPA_NAPI_WEIGHT 64 ++ ++/* Size in bytes of the Congestion State notification threshold on 10G ports */ ++#define DPA_CS_THRESHOLD_10G 0x10000000 ++/* ++ * Size in bytes of the Congestion State notification threshold on 1G ports. ++ ++ * The 1G dTSECs can quite easily be flooded by cores doing Tx in a tight loop ++ * (e.g. by sending UDP datagrams at "while(1) speed"), ++ * and the larger the frame size, the more acute the problem. ++ * ++ * So we have to find a balance between these factors: ++ * - avoiding the device staying congested for a prolonged time (risking ++ * the netdev watchdog to fire - see also the tx_timeout module param); ++ * - affecting performance of protocols such as TCP, which otherwise ++ * behave well under the congestion notification mechanism; ++ * - preventing the Tx cores from tightly-looping (as if the congestion ++ * threshold was too low to be effective); ++ * - running out of memory if the CS threshold is set too high. ++ */ ++#define DPA_CS_THRESHOLD_1G 0x06000000 ++ ++/* Size in bytes of the FQ taildrop threshold */ ++#define DPA_FQ_TD 0x200000 ++ ++/* S/G table requires at least 256 bytes */ ++#define SGT_BUFFER_SIZE DPA_BP_SIZE(256) ++ ++/* Maximum frame size on Tx for which skb copying is preferrable to ++ * creating a S/G frame */ ++#define DPA_SKB_COPY_MAX_SIZE 256 ++ ++/* Valid checksum indication */ ++#define DPA_CSUM_VALID 0xFFFF ++ ++/* Maximum offset value for a contig or sg FD (represented on 9bits) */ ++#define DPA_MAX_FD_OFFSET ((1 << 9) - 1) ++ ++/* ++ * Maximum size of a buffer that is to be recycled back to the buffer pool. ++ * The value is arbitrary, but tries to reach a balance such that originating ++ * frames may get recycled, while forwarded skbs that get reallocated on Tx ++ * aren't allowed to grow unboundedly. ++ */ ++#define DPA_BP_MAX_BUF_SIZE (DEFAULT_BUF_SIZE + 256) ++ ++#define DPA_DESCRIPTION "FSL DPAA Ethernet driver" ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++MODULE_AUTHOR("Andy Fleming "); ++ ++MODULE_DESCRIPTION(DPA_DESCRIPTION); ++ ++static uint8_t debug = -1; ++module_param(debug, byte, S_IRUGO); ++MODULE_PARM_DESC(debug, "Module/Driver verbosity level"); ++ ++/* This has to work in tandem with the DPA_CS_THRESHOLD_xxx values. */ ++static uint16_t __devinitdata tx_timeout = 1000; ++module_param(tx_timeout, ushort, S_IRUGO); ++MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms"); ++ ++#ifdef CONFIG_DEBUG_FS ++static struct dentry *dpa_debugfs_root; ++#endif ++ ++/* dpaa_eth mirror for the FMan values */ ++static int dpa_rx_extra_headroom; ++static int dpa_max_frm; ++ ++static const char rtx[][3] = { ++ [RX] = "RX", ++ [TX] = "TX" ++}; ++ ++#if defined(CONFIG_FSL_FMAN_TEST) ++/* Defined as weak, to be implemented by fman pcd tester. */ ++int dpa_alloc_pcd_fqids(struct device *, uint32_t, uint8_t, uint32_t *) ++__attribute__((weak)); ++ ++int dpa_free_pcd_fqids(struct device *, uint32_t) __attribute__((weak)); ++#endif /* CONFIG_DPAA_FMAN_UNIT_TESTS */ ++ ++/* BM */ ++ ++#define DPAA_ETH_MAX_PAD (L1_CACHE_BYTES * 8) ++ ++static struct dpa_bp *dpa_bp_array[64]; ++ ++static struct dpa_bp *default_pool; ++ ++/* A set of callbacks for hooking into the fastpath at different points. */ ++static struct dpaa_eth_hooks_s dpaa_eth_hooks; ++/* ++ * This function should only be called on the probe paths, since it makes no ++ * effort to guarantee consistency of the destination hooks structure. ++ */ ++void fsl_dpaa_eth_set_hooks(struct dpaa_eth_hooks_s *hooks) ++{ ++ if (hooks) ++ dpaa_eth_hooks = *hooks; ++ else ++ pr_err("NULL pointer to hooks!\n"); ++} ++EXPORT_SYMBOL(fsl_dpaa_eth_set_hooks); ++ ++ ++struct dpa_bp *dpa_bpid2pool(int bpid) ++{ ++ return dpa_bp_array[bpid]; ++} ++ ++static void dpa_bp_depletion(struct bman_portal *portal, ++ struct bman_pool *pool, void *cb_ctx, int depleted) ++{ ++ if (net_ratelimit()) ++ pr_err("Invalid Pool depleted notification!\n"); ++} ++ ++/* ++ * Copy from a memory region that requires kmapping to a linear buffer, ++ * taking into account page boundaries in the source ++ */ ++static void ++copy_from_unmapped_area(void *dest, dma_addr_t phys_start, size_t buf_size) ++{ ++ struct page *page; ++ size_t size, offset; ++ void *page_vaddr; ++ ++ while (buf_size > 0) { ++ offset = offset_in_page(phys_start); ++ size = (offset + buf_size > PAGE_SIZE) ? ++ PAGE_SIZE - offset : buf_size; ++ ++ page = pfn_to_page(phys_start >> PAGE_SHIFT); ++ page_vaddr = kmap_atomic(page); ++ ++ memcpy(dest, page_vaddr + offset, size); ++ ++ kunmap_atomic(page_vaddr); ++ ++ phys_start += size; ++ dest += size; ++ buf_size -= size; ++ } ++} ++ ++/* ++ * Copy to a memory region that requires kmapping from a linear buffer, ++ * taking into account page boundaries in the destination ++ */ ++static void ++copy_to_unmapped_area(dma_addr_t phys_start, void *src, size_t buf_size) ++{ ++ struct page *page; ++ size_t size, offset; ++ void *page_vaddr; ++ ++ while (buf_size > 0) { ++ offset = offset_in_page(phys_start); ++ size = (offset + buf_size > PAGE_SIZE) ? ++ PAGE_SIZE - offset : buf_size; ++ ++ page = pfn_to_page(phys_start >> PAGE_SHIFT); ++ page_vaddr = kmap_atomic(page); ++ ++ memcpy(page_vaddr + offset, src, size); ++ ++ kunmap_atomic(page_vaddr); ++ ++ phys_start += size; ++ src += size; ++ buf_size -= size; ++ } ++} ++ ++#ifndef CONFIG_DPAA_ETH_SG_SUPPORT ++static void dpa_bp_add_8(const struct dpa_bp *dpa_bp) ++{ ++ struct bm_buffer bmb[8]; ++ struct sk_buff **skbh; ++ dma_addr_t addr; ++ int i; ++ struct sk_buff *skb; ++ int *count_ptr; ++ ++ count_ptr = per_cpu_ptr(dpa_bp->percpu_count, smp_processor_id()); ++ ++ for (i = 0; i < 8; i++) { ++ /* ++ * The buffers tend to be aligned all to the same cache ++ * index. A standard dequeue operation pulls in 15 packets. ++ * This means that when it stashes, it evicts half of the ++ * packets it's stashing. In order to prevent that, we pad ++ * by a variable number of cache lines, to reduce collisions. ++ * We always pad by at least 1 cache line, because we want ++ * a little extra room at the beginning for IPSec and to ++ * accommodate NET_IP_ALIGN. ++ */ ++ int pad = (i + 1) * L1_CACHE_BYTES; ++ ++ skb = dev_alloc_skb(dpa_bp->size + pad); ++ if (unlikely(!skb)) { ++ printk(KERN_ERR "dev_alloc_skb() failed\n"); ++ bm_buffer_set64(&bmb[i], 0); ++ break; ++ } ++ ++ skbh = (struct sk_buff **)(skb->head + pad); ++ *skbh = skb; ++ ++ /* ++ * Here we need to map only for device write (DMA_FROM_DEVICE), ++ * but on Tx recycling we may also get buffers in the pool that ++ * are mapped bidirectionally. ++ * Use DMA_BIDIRECTIONAL here as well to avoid any ++ * inconsistencies when unmapping. ++ */ ++ addr = dma_map_single(dpa_bp->dev, skb->head + pad, ++ dpa_bp->size, DMA_BIDIRECTIONAL); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ dev_err(dpa_bp->dev, "DMA mapping failed"); ++ break; ++ } ++ ++ bm_buffer_set64(&bmb[i], addr); ++ } ++ ++ /* Avoid releasing a completely null buffer; bman_release() requires ++ * at least one buf. */ ++ if (likely(i)) { ++ /* ++ * Release the buffers. In case bman is busy, keep trying ++ * until successful. bman_release() is guaranteed to succeed ++ * in a reasonable amount of time ++ */ ++ while (bman_release(dpa_bp->pool, bmb, i, 0)) ++ cpu_relax(); ++ ++ *count_ptr += i; ++ } ++} ++ ++void dpa_make_private_pool(struct dpa_bp *dpa_bp) ++{ ++ int i; ++ ++ dpa_bp->percpu_count = __alloc_percpu(sizeof(*dpa_bp->percpu_count), ++ __alignof__(*dpa_bp->percpu_count)); ++ ++ /* Give each cpu an allotment of "count" buffers */ ++ for_each_online_cpu(i) { ++ int *thiscount; ++ int *countptr; ++ int j; ++ thiscount = per_cpu_ptr(dpa_bp->percpu_count, ++ smp_processor_id()); ++ countptr = per_cpu_ptr(dpa_bp->percpu_count, i); ++ ++ for (j = 0; j < dpa_bp->target_count; j += 8) ++ dpa_bp_add_8(dpa_bp); ++ ++ /* Adjust the counts */ ++ *countptr = j; ++ ++ if (countptr != thiscount) ++ *thiscount = *thiscount - j; ++ } ++} ++#endif /* CONFIG_DPAA_ETH_SG_SUPPORT */ ++ ++static void dpaa_eth_seed_pool(struct dpa_bp *bp) ++{ ++ int count = bp->target_count; ++ size_t addr = bp->paddr; ++ ++ while (count) { ++ struct bm_buffer bufs[8]; ++ int num_bufs = 0; ++ ++ do { ++ BUG_ON(addr > 0xffffffffffffull); ++ bufs[num_bufs].bpid = bp->bpid; ++ bm_buffer_set64(&bufs[num_bufs++], addr); ++ addr += bp->size; ++ ++ } while (--count && (num_bufs < 8)); ++ ++ while (bman_release(bp->pool, bufs, num_bufs, 0)) ++ cpu_relax(); ++ } ++} ++ ++/* ++ * Add buffers/pages/skbuffs for Rx processing whenever bpool count falls below ++ * REFILL_THRESHOLD. ++ */ ++static void dpaa_eth_refill_bpools(struct dpa_percpu_priv_s *percpu_priv) ++{ ++ int *countptr = percpu_priv->dpa_bp_count; ++ int count = *countptr; ++ const struct dpa_bp *dpa_bp = percpu_priv->dpa_bp; ++ ++#ifndef CONFIG_DPAA_ETH_SG_SUPPORT ++ if (unlikely(count < REFILL_THRESHOLD)) { ++ int i; ++ ++ for (i = count; i < DEFAULT_COUNT; i += 8) ++ dpa_bp_add_8(dpa_bp); ++ } ++#else ++ /* Add pages to the buffer pool */ ++ while (count < DEFAULT_COUNT) ++ count += _dpa_bp_add_8_pages(dpa_bp); ++ *countptr = count; ++ ++ /* Add skbs to the percpu skb list, reuse var count */ ++ count = percpu_priv->skb_count; ++ if (unlikely(count < DEFAULT_SKB_COUNT / 4)) ++ dpa_list_add_skbs(percpu_priv, ++ DEFAULT_SKB_COUNT - count); ++#endif ++} ++ ++static int dpa_make_shared_port_pool(struct dpa_bp *bp) ++{ ++ /* ++ * In MAC-less and Shared-MAC scenarios the physical ++ * address of the buffer pool in device tree is set ++ * to 0 to specify that another entity (USDPAA) will ++ * allocate and seed the buffers ++ */ ++ if (!bp->paddr) ++ return 0; ++ ++ devm_request_mem_region(bp->dev, bp->paddr, ++ bp->size * bp->config_count, KBUILD_MODNAME); ++ bp->vaddr = devm_ioremap_prot(bp->dev, bp->paddr, ++ bp->size * bp->config_count, 0); ++ if (bp->vaddr == NULL) { ++ pr_err("Could not map memory for pool %d\n", bp->bpid); ++ return -EIO; ++ } ++ ++ if (bp->seed_pool) ++ dpaa_eth_seed_pool(bp); ++ ++ return 0; ++} ++ ++static int __devinit __must_check __attribute__((nonnull)) ++dpa_bp_alloc(struct dpa_bp *dpa_bp) ++{ ++ int err; ++ struct bman_pool_params bp_params; ++ struct platform_device *pdev; ++ ++ BUG_ON(dpa_bp->size == 0); ++ BUG_ON(dpa_bp->config_count == 0); ++ ++ bp_params.flags = BMAN_POOL_FLAG_DEPLETION; ++ bp_params.cb = dpa_bp_depletion; ++ bp_params.cb_ctx = dpa_bp; ++ ++ /* We support two options. Either a global shared pool, or ++ * a specified pool. If the pool is specified, we only ++ * create one per bpid */ ++ if (dpa_bp->kernel_pool && default_pool) { ++ atomic_inc(&default_pool->refs); ++ return 0; ++ } ++ ++ if (dpa_bp_array[dpa_bp->bpid]) { ++ atomic_inc(&dpa_bp_array[dpa_bp->bpid]->refs); ++ return 0; ++ } ++ ++ if (dpa_bp->bpid == 0) ++ bp_params.flags |= BMAN_POOL_FLAG_DYNAMIC_BPID; ++ else ++ bp_params.bpid = dpa_bp->bpid; ++ ++ dpa_bp->pool = bman_new_pool(&bp_params); ++ if (unlikely(dpa_bp->pool == NULL)) { ++ pr_err("bman_new_pool() failed\n"); ++ return -ENODEV; ++ } ++ ++ dpa_bp->bpid = bman_get_params(dpa_bp->pool)->bpid; ++ ++ pdev = platform_device_register_simple("dpaa_eth_bpool", ++ dpa_bp->bpid, NULL, 0); ++ if (IS_ERR(pdev)) { ++ err = PTR_ERR(pdev); ++ goto pdev_register_failed; ++ } ++ ++ err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)); ++ if (err) ++ goto pdev_mask_failed; ++ ++ dpa_bp->dev = &pdev->dev; ++ ++ if (dpa_bp->kernel_pool) { ++ dpa_make_private_pool(dpa_bp); ++ if (!default_pool) ++ default_pool = dpa_bp; ++ } else { ++ err = dpa_make_shared_port_pool(dpa_bp); ++ if (err) ++ goto make_shared_pool_failed; ++ } ++ ++ dpa_bp_array[dpa_bp->bpid] = dpa_bp; ++ ++ atomic_set(&dpa_bp->refs, 1); ++ ++ return 0; ++ ++make_shared_pool_failed: ++pdev_mask_failed: ++ platform_device_unregister(pdev); ++pdev_register_failed: ++ bman_free_pool(dpa_bp->pool); ++ ++ return err; ++} ++ ++#ifndef CONFIG_DPAA_ETH_SG_SUPPORT ++static inline void _dpa_bp_free_buf(void *addr) ++{ ++ struct sk_buff **skbh = addr; ++ struct sk_buff *skb; ++ ++ skb = *skbh; ++ dev_kfree_skb_any(skb); ++} ++#else ++static inline void _dpa_bp_free_buf(void *addr) ++{ ++ free_page((unsigned long)addr); ++} ++#endif ++ ++static void __cold __attribute__((nonnull)) ++_dpa_bp_free(struct dpa_bp *dpa_bp) ++{ ++ struct dpa_bp *bp = dpa_bpid2pool(dpa_bp->bpid); ++ ++ if (!atomic_dec_and_test(&bp->refs)) ++ return; ++ ++ if (bp->kernel_pool) { ++ int num; ++ ++ do { ++ struct bm_buffer bmb[8]; ++ int i; ++ ++ num = bman_acquire(bp->pool, bmb, 8, 0); ++ ++ for (i = 0; i < num; i++) { ++ dma_addr_t addr = bm_buf_addr(&bmb[i]); ++ ++ dma_unmap_single(bp->dev, addr, bp->size, ++ DMA_BIDIRECTIONAL); ++ ++ _dpa_bp_free_buf(phys_to_virt(addr)); ++ } ++ } while (num == 8); ++ } ++ ++ dpa_bp_array[bp->bpid] = 0; ++ bman_free_pool(bp->pool); ++} ++ ++static void __cold __attribute__((nonnull)) ++dpa_bp_free(struct dpa_priv_s *priv, struct dpa_bp *dpa_bp) ++{ ++ int i; ++ ++ for (i = 0; i < priv->bp_count; i++) ++ _dpa_bp_free(&priv->dpa_bp[i]); ++} ++ ++/* QM */ ++ ++static struct qman_fq *_dpa_get_tx_conf_queue(const struct dpa_priv_s *priv, ++ struct qman_fq *tx_fq) ++{ ++ int i; ++ ++ for (i = 0; i < DPAA_ETH_TX_QUEUES; i++) ++ if (priv->egress_fqs[i] == tx_fq) ++ return priv->conf_fqs[i]; ++ ++ return NULL; ++} ++ ++static int __devinit __must_check __attribute__((nonnull)) ++_dpa_fq_alloc(struct list_head *list, struct dpa_fq *dpa_fq) ++{ ++ int _errno; ++ const struct dpa_priv_s *priv; ++ struct device *dev; ++ struct qman_fq *fq; ++ struct qm_mcc_initfq initfq; ++ struct qman_fq *confq; ++ ++ priv = netdev_priv(dpa_fq->net_dev); ++ dev = dpa_fq->net_dev->dev.parent; ++ ++ if (dpa_fq->fqid == 0) ++ dpa_fq->flags |= QMAN_FQ_FLAG_DYNAMIC_FQID; ++ ++ dpa_fq->init = !(dpa_fq->flags & QMAN_FQ_FLAG_NO_MODIFY); ++ ++ _errno = qman_create_fq(dpa_fq->fqid, dpa_fq->flags, &dpa_fq->fq_base); ++ if (_errno) { ++ dev_err(dev, "qman_create_fq() failed\n"); ++ return _errno; ++ } ++ fq = &dpa_fq->fq_base; ++ ++ if (dpa_fq->init) { ++ initfq.we_mask = QM_INITFQ_WE_FQCTRL; ++ /* FIXME: why would we want to keep an empty FQ in cache? */ ++ initfq.fqd.fq_ctrl = QM_FQCTRL_PREFERINCACHE; ++ ++ /* FQ placement */ ++ initfq.we_mask |= QM_INITFQ_WE_DESTWQ; ++ ++ initfq.fqd.dest.channel = dpa_fq->channel; ++ initfq.fqd.dest.wq = dpa_fq->wq; ++ ++ /* ++ * Put all egress queues in a congestion group of their own. ++ * Sensu stricto, the Tx confirmation queues are Rx FQs, ++ * rather than Tx - but they nonetheless account for the ++ * memory footprint on behalf of egress traffic. We therefore ++ * place them in the netdev's CGR, along with the Tx FQs. ++ */ ++ if (dpa_fq->fq_type == FQ_TYPE_TX || ++ dpa_fq->fq_type == FQ_TYPE_TX_CONFIRM) { ++ initfq.we_mask |= QM_INITFQ_WE_CGID; ++ initfq.fqd.fq_ctrl |= QM_FQCTRL_CGE; ++ initfq.fqd.cgid = priv->cgr_data.cgr.cgrid; ++ /* ++ * Set a fixed overhead accounting, in an attempt to ++ * reduce the impact of fixed-size skb shells and the ++ * driver's needed headroom on system memory. This is ++ * especially the case when the egress traffic is ++ * composed of small datagrams. ++ * Unfortunately, QMan's OAL value is capped to an ++ * insufficient value, but even that is better than ++ * no overhead accounting at all. ++ */ ++ initfq.we_mask |= QM_INITFQ_WE_OAC; ++ initfq.fqd.oac_init.oac = QM_OAC_CG; ++ initfq.fqd.oac_init.oal = min(sizeof(struct sk_buff) + ++ DPA_BP_HEAD, (size_t)FSL_QMAN_MAX_OAL); ++ } ++ ++ /* ++ * For MAC-less devices we only get here for RX frame queues ++ * initialization, which are the TX queues of the other ++ * partition. ++ * It is safe to rely on one partition to set the FQ taildrop ++ * threshold for the TX queues of the other partition ++ * because the ERN notifications will be received by the ++ * partition doing qman_enqueue. ++ */ ++ if (!priv->mac_dev) { ++ initfq.we_mask |= QM_INITFQ_WE_TDTHRESH; ++ qm_fqd_taildrop_set(&initfq.fqd.td, ++ DPA_FQ_TD, 1); ++ initfq.fqd.fq_ctrl = QM_FQCTRL_TDE; ++ } ++ ++ /* ++ * Configure the Tx confirmation queue, now that we know ++ * which Tx queue it pairs with. ++ */ ++ if (dpa_fq->fq_type == FQ_TYPE_TX) { ++ confq = _dpa_get_tx_conf_queue(priv, &dpa_fq->fq_base); ++ if (confq) { ++ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA | ++ QM_INITFQ_WE_CONTEXTB; ++ /* CTXA[OVFQ] = 1 */ ++ initfq.fqd.context_a.hi = 0x80000000; ++ initfq.fqd.context_a.lo = 0x0; ++ initfq.fqd.context_b = qman_fq_fqid(confq); ++ } ++ } ++ ++#ifdef CONFIG_DPA_TX_RECYCLE ++ /* ++ * Configure the Tx queues for recycled frames, such that the ++ * buffers are released by FMan and no confirmation is sent ++ */ ++ if (dpa_fq->fq_type == FQ_TYPE_TX_RECYCLE) { ++ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA | ++ QM_INITFQ_WE_CONTEXTB; ++ /* ++ * ContextA: OVFQ=1 (use ContextB FQID for confirmation) ++ * OVOM=1 (use contextA2 bits instead of ICAD) ++ * A2V=1 (contextA A2 field is valid) ++ * B0V=1 (contextB field is valid) ++ * ContextA A2: EBD=1 (deallocate buffers inside FMan) ++ * ContextB: Confirmation FQID = 0 ++ */ ++ initfq.fqd.context_a.hi = 0x96000000; ++ initfq.fqd.context_a.lo = 0x80000000; ++ initfq.fqd.context_b = 0; ++ } ++#endif ++ ++ /* Initialization common to all ingress queues */ ++ if (dpa_fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE) { ++ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; ++ initfq.fqd.fq_ctrl |= ++ QM_FQCTRL_CTXASTASHING | QM_FQCTRL_AVOIDBLOCK; ++ initfq.fqd.context_a.stashing.exclusive = ++ QM_STASHING_EXCL_DATA | QM_STASHING_EXCL_CTX | ++ QM_STASHING_EXCL_ANNOTATION; ++ initfq.fqd.context_a.stashing.data_cl = 2; ++ initfq.fqd.context_a.stashing.annotation_cl = 1; ++ initfq.fqd.context_a.stashing.context_cl = ++ DIV_ROUND_UP(sizeof(struct qman_fq), 64); ++ }; ++ ++ _errno = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq); ++ if (_errno < 0) { ++ dev_err(dev, "qman_init_fq(%u) = %d\n", ++ qman_fq_fqid(fq), _errno); ++ qman_destroy_fq(fq, 0); ++ return _errno; ++ } ++ } ++ ++ dpa_fq->fqid = qman_fq_fqid(fq); ++ list_add_tail(&dpa_fq->list, list); ++ ++ return 0; ++} ++ ++static int __cold __attribute__((nonnull)) ++_dpa_fq_free(struct device *dev, struct qman_fq *fq) ++{ ++ int _errno, __errno; ++ struct dpa_fq *dpa_fq; ++ const struct dpa_priv_s *priv; ++ ++ _errno = 0; ++ ++ dpa_fq = container_of(fq, struct dpa_fq, fq_base); ++ priv = netdev_priv(dpa_fq->net_dev); ++ ++ if (dpa_fq->init) { ++ _errno = qman_retire_fq(fq, NULL); ++ if (unlikely(_errno < 0) && netif_msg_drv(priv)) ++ dev_err(dev, "qman_retire_fq(%u) = %d\n", ++ qman_fq_fqid(fq), _errno); ++ ++ __errno = qman_oos_fq(fq); ++ if (unlikely(__errno < 0) && netif_msg_drv(priv)) { ++ dev_err(dev, "qman_oos_fq(%u) = %d\n", ++ qman_fq_fqid(fq), __errno); ++ if (_errno >= 0) ++ _errno = __errno; ++ } ++ } ++ ++ qman_destroy_fq(fq, 0); ++ list_del(&dpa_fq->list); ++ ++ return _errno; ++} ++ ++static int __cold __attribute__((nonnull)) ++dpa_fq_free(struct device *dev, struct list_head *list) ++{ ++ int _errno, __errno; ++ struct dpa_fq *dpa_fq, *tmp; ++ ++ _errno = 0; ++ list_for_each_entry_safe(dpa_fq, tmp, list, list) { ++ __errno = _dpa_fq_free(dev, (struct qman_fq *)dpa_fq); ++ if (unlikely(__errno < 0) && _errno >= 0) ++ _errno = __errno; ++ } ++ ++ return _errno; ++} ++ ++static inline void * __must_check __attribute__((nonnull)) ++dpa_phys2virt(const struct dpa_bp *dpa_bp, dma_addr_t addr) ++{ ++ return dpa_bp->vaddr + (addr - dpa_bp->paddr); ++} ++ ++static void ++dpa_release_sgt(struct qm_sg_entry *sgt, struct dpa_bp *dpa_bp, ++ struct bm_buffer *bmb) ++{ ++ int i = 0, j; ++ ++ do { ++ dpa_bp = dpa_bpid2pool(sgt[i].bpid); ++ BUG_ON(IS_ERR(dpa_bp)); ++ ++ j = 0; ++ do { ++ BUG_ON(sgt[i].extension); ++ ++ bmb[j].hi = sgt[i].addr_hi; ++ bmb[j].lo = sgt[i].addr_lo; ++ ++ j++; i++; ++ } while (j < ARRAY_SIZE(bmb) && ++ !sgt[i-1].final && ++ sgt[i-1].bpid == sgt[i].bpid); ++ ++ while (bman_release(dpa_bp->pool, bmb, j, 0)) ++ cpu_relax(); ++ } while (!sgt[i-1].final); ++} ++ ++static void ++dpa_fd_release_sg(const struct net_device *net_dev, ++ const struct qm_fd *fd) ++{ ++ const struct dpa_priv_s *priv; ++ struct qm_sg_entry *sgt; ++ struct dpa_bp *_dpa_bp, *dpa_bp; ++ struct bm_buffer _bmb, bmb[8]; ++ ++ priv = netdev_priv(net_dev); ++ ++ _bmb.hi = fd->addr_hi; ++ _bmb.lo = fd->addr_lo; ++ ++ _dpa_bp = dpa_bpid2pool(fd->bpid); ++ ++ if (_dpa_bp->vaddr) { ++ sgt = dpa_phys2virt(_dpa_bp, bm_buf_addr(&_bmb)) + ++ dpa_fd_offset(fd); ++ dpa_release_sgt(sgt, dpa_bp, bmb); ++ } else { ++ sgt = kmalloc(DPA_SGT_MAX_ENTRIES * sizeof(*sgt), GFP_ATOMIC); ++ if (sgt == NULL) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, ++ "Memory allocation failed\n"); ++ return; ++ } ++ ++ copy_from_unmapped_area(sgt, bm_buf_addr(&_bmb) + ++ dpa_fd_offset(fd), ++ min(DPA_SGT_MAX_ENTRIES * sizeof(*sgt), ++ _dpa_bp->size)); ++ dpa_release_sgt(sgt, dpa_bp, bmb); ++ kfree(sgt); ++ } ++ ++ while (bman_release(_dpa_bp->pool, &_bmb, 1, 0)) ++ cpu_relax(); ++} ++ ++void __attribute__((nonnull)) ++dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd) ++{ ++ const struct dpa_priv_s *priv; ++ struct qm_sg_entry *sgt; ++ struct dpa_bp *_dpa_bp, *dpa_bp; ++ struct bm_buffer _bmb, bmb[8]; ++ ++ priv = netdev_priv(net_dev); ++ ++ _bmb.hi = fd->addr_hi; ++ _bmb.lo = fd->addr_lo; ++ ++ _dpa_bp = dpa_bpid2pool(fd->bpid); ++ BUG_ON(IS_ERR(_dpa_bp)); ++ ++ if (fd->format == qm_fd_sg) { ++ sgt = (phys_to_virt(bm_buf_addr(&_bmb)) + dpa_fd_offset(fd)); ++ dpa_release_sgt(sgt, dpa_bp, bmb); ++ } ++ ++ while (bman_release(_dpa_bp->pool, &_bmb, 1, 0)) ++ cpu_relax(); ++} ++ ++#ifndef CONFIG_DPAA_ETH_SG_SUPPORT ++/* ++ * Cleanup function for outgoing frame descriptors that were built on Tx path, ++ * either contiguous frames or scatter/gather ones with a single data buffer. ++ * Skb freeing is not handled here. ++ * ++ * This function may be called on error paths in the Tx function, so guard ++ * against cases when not all fd relevant fields were filled in. ++ * ++ * Return the skb backpointer, since for S/G frames the buffer containing it ++ * gets freed here. ++ */ ++struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, ++ const struct qm_fd *fd) ++{ ++ dma_addr_t addr = qm_fd_addr(fd); ++ dma_addr_t sg_addr; ++ struct dpa_bp *bp = priv->dpa_bp; ++ struct sk_buff **skbh; ++ struct sk_buff *skb = NULL; ++ ++ BUG_ON(!fd); ++ ++ if (unlikely(!addr)) ++ return skb; ++ ++ skbh = (struct sk_buff **)phys_to_virt(addr); ++ ++ if (fd->format == qm_fd_contig) { ++ /* For contiguous frames, just unmap data buffer; ++ * mapping direction depends on whether the frame was ++ * meant to be recycled or not */ ++ if (fd->cmd & FM_FD_CMD_FCO) ++ dma_unmap_single(bp->dev, addr, bp->size, ++ DMA_BIDIRECTIONAL); ++ else ++ dma_unmap_single(bp->dev, addr, bp->size, ++ DMA_TO_DEVICE); ++ /* Retrieve the skb backpointer */ ++ skb = *skbh; ++ } else { ++ /* For s/g, we need to unmap both the SGT buffer and the ++ * data buffer, and also free the SGT buffer */ ++ struct qm_sg_entry *sg_entry; ++ void *vaddr = phys_to_virt(addr); ++ ++ /* Unmap first buffer (contains S/G table) */ ++ dma_unmap_single(bp->dev, addr, SGT_BUFFER_SIZE, ++ DMA_TO_DEVICE); ++ ++ /* Unmap data buffer */ ++ sg_entry = (struct qm_sg_entry *)(vaddr + fd->offset); ++ sg_addr = qm_sg_addr(sg_entry); ++ if (likely(sg_addr)) ++ dma_unmap_single(bp->dev, sg_addr, bp->size, ++ DMA_TO_DEVICE); ++ /* Retrieve the skb backpointer */ ++ skb = *skbh; ++ ++ /* Free first buffer (which was allocated on Tx) */ ++ kfree(vaddr); ++ } ++ ++ return skb; ++} ++#endif /* CONFIG_DPAA_ETH_SG_SUPPORT */ ++ ++/* net_device */ ++ ++static struct net_device_stats * __cold ++dpa_get_stats(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ unsigned long *netstats; ++ unsigned long *cpustats; ++ int i, j; ++ struct dpa_percpu_priv_s *percpu_priv; ++ int numstats = sizeof(net_dev->stats) / sizeof(unsigned long); ++ ++ netstats = (unsigned long *)&net_dev->stats; ++ ++ memset(netstats, 0, sizeof(net_dev->stats)); ++ ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ cpustats = (unsigned long *)&percpu_priv->stats; ++ ++ for (j = 0; j < numstats; j++) ++ netstats[j] += cpustats[j]; ++ } ++ ++ return &net_dev->stats; ++} ++ ++static int dpa_change_mtu(struct net_device *net_dev, int new_mtu) ++{ ++ const int max_mtu = dpa_get_max_mtu(); ++ const int min_mtu = dpa_get_min_mtu(); ++ ++ /* Make sure we don't exceed the Ethernet controller's MAXFRM */ ++ if (new_mtu < min_mtu || new_mtu > max_mtu) { ++ netdev_err(net_dev, "Invalid L3 mtu %d " ++ "(must be between %d and %d).\n", ++ new_mtu, min_mtu, max_mtu); ++ return -EINVAL; ++ } ++ net_dev->mtu = new_mtu; ++ ++ return 0; ++} ++ ++/* .ndo_init callback */ ++static int dpa_ndo_init(struct net_device *net_dev) ++{ ++ /* ++ * If fsl_fm_max_frm is set to a higher value than the all-common 1500, ++ * we choose conservatively and let the user explicitly set a higher ++ * MTU via ifconfig. Otherwise, the user may end up with different MTUs ++ * in the same LAN. ++ * If on the other hand fsl_fm_max_frm has been chosen below 1500, ++ * start with the maximum allowed. ++ */ ++ int init_mtu = min(dpa_get_max_mtu(), ETH_DATA_LEN); ++ ++ pr_debug("Setting initial MTU on net device: %d\n", init_mtu); ++ net_dev->mtu = init_mtu; ++ ++ return 0; ++} ++ ++static int dpa_set_mac_address(struct net_device *net_dev, void *addr) ++{ ++ const struct dpa_priv_s *priv; ++ int _errno; ++ ++ priv = netdev_priv(net_dev); ++ ++ _errno = eth_mac_addr(net_dev, addr); ++ if (_errno < 0) { ++ if (netif_msg_drv(priv)) ++ netdev_err(net_dev, ++ "eth_mac_addr() = %d\n", ++ _errno); ++ return _errno; ++ } ++ ++ if (!priv->mac_dev) ++ /* MAC-less interface, so nothing more to do here */ ++ return 0; ++ ++ _errno = priv->mac_dev->change_addr(priv->mac_dev, net_dev->dev_addr); ++ if (_errno < 0) { ++ if (netif_msg_drv(priv)) ++ netdev_err(net_dev, ++ "mac_dev->change_addr() = %d\n", ++ _errno); ++ return _errno; ++ } ++ ++ return 0; ++} ++ ++static void dpa_set_rx_mode(struct net_device *net_dev) ++{ ++ int _errno; ++ const struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ ++ if (!priv->mac_dev) ++ return; ++ ++ if (!!(net_dev->flags & IFF_PROMISC) != priv->mac_dev->promisc) { ++ _errno = priv->mac_dev->change_promisc(priv->mac_dev); ++ if (unlikely(_errno < 0) && netif_msg_drv(priv)) ++ netdev_err(net_dev, ++ "mac_dev->change_promisc() = %d\n", ++ _errno); ++ } ++ ++ _errno = priv->mac_dev->set_multi(net_dev); ++ if (unlikely(_errno < 0) && netif_msg_drv(priv)) ++ netdev_err(net_dev, "mac_dev->set_multi() = %d\n", _errno); ++} ++ ++#ifdef CONFIG_FSL_DPA_1588 ++static int dpa_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ++{ ++ struct dpa_priv_s *priv = netdev_priv(dev); ++ int ret = 0; ++ ++ if (!netif_running(dev)) ++ return -EINVAL; ++ ++ if ((cmd >= PTP_ENBL_TXTS_IOCTL) && (cmd <= PTP_CLEANUP_TS)) { ++ if (priv->tsu && priv->tsu->valid) ++ ret = dpa_ioctl_1588(dev, rq, cmd); ++ else ++ ret = -ENODEV; ++ } ++ ++ return ret; ++} ++#endif ++ ++#ifndef CONFIG_DPAA_ETH_SG_SUPPORT ++/* ++ * When we put the buffer into the pool, we purposefully added ++ * some padding to the address so that the buffers wouldn't all ++ * be page-aligned. But the skb has been reset to a default state, ++ * so it is pointing up to DPAA_ETH_MAX_PAD - L1_CACHE_BYTES bytes ++ * before the actual data. We subtract skb->head from the fd addr, ++ * and then mask off the translated part to get the actual distance. ++ */ ++static int dpa_process_one(struct dpa_percpu_priv_s *percpu_priv, ++ struct sk_buff *skb, struct dpa_bp *bp, const struct qm_fd *fd) ++{ ++ dma_addr_t addr = qm_fd_addr(fd); ++ u32 addrlo = lower_32_bits(addr); ++ u32 skblo = lower_32_bits((unsigned long)skb->head); ++ u32 pad = (addrlo - skblo) & (PAGE_SIZE - 1); ++ unsigned int data_start; ++ ++ (*percpu_priv->dpa_bp_count)--; ++ ++ /* ++ * The skb is currently pointed at head + headroom. The packet ++ * starts at skb->head + pad + fd offset. ++ */ ++ data_start = pad + dpa_fd_offset(fd) - skb_headroom(skb); ++ skb_put(skb, dpa_fd_length(fd) + data_start); ++ skb_pull(skb, data_start); ++ ++ return 0; ++} ++#endif ++ ++/* ++ * Checks whether the checksum field in Parse Results array is valid ++ * (equals 0xFFFF) and increments the .cse counter otherwise ++ */ ++static inline void ++dpa_csum_validation(const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd) ++{ ++ dma_addr_t addr = qm_fd_addr(fd); ++ struct dpa_bp *dpa_bp = priv->dpa_bp; ++ void *frm = phys_to_virt(addr); ++ t_FmPrsResult *parse_result; ++ ++ if (unlikely(!frm)) ++ return; ++ ++ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL); ++ ++ parse_result = (t_FmPrsResult *)(frm + DPA_RX_PRIV_DATA_SIZE); ++ ++ if (parse_result->cksum != DPA_CSUM_VALID) ++ percpu_priv->rx_errors.cse++; ++} ++ ++static void _dpa_rx_error(struct net_device *net_dev, ++ const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ /* ++ * limit common, possibly innocuous Rx FIFO Overflow errors' ++ * interference with zero-loss convergence benchmark results. ++ */ ++ if (likely(fd->status & FM_FD_STAT_ERR_PHYSICAL)) ++ pr_warn_once("fsl-dpa: non-zero error counters " \ ++ "in fman statistics (sysfs)\n"); ++ else ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_err(net_dev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_ERRORS); ++ ++ if (dpaa_eth_hooks.rx_error && ++ dpaa_eth_hooks.rx_error(net_dev, fd, fqid) == DPAA_ETH_STOLEN) ++ /* it's up to the hook to perform resource cleanup */ ++ return; ++ ++ percpu_priv->stats.rx_errors++; ++ ++ if (fd->status & FM_PORT_FRM_ERR_DMA) ++ percpu_priv->rx_errors.dme++; ++ if (fd->status & FM_PORT_FRM_ERR_PHYSICAL) ++ percpu_priv->rx_errors.fpe++; ++ if (fd->status & FM_PORT_FRM_ERR_SIZE) ++ percpu_priv->rx_errors.fse++; ++ if (fd->status & FM_PORT_FRM_ERR_PRS_HDR_ERR) ++ percpu_priv->rx_errors.phe++; ++ if (fd->status & FM_FD_STAT_L4CV) ++ dpa_csum_validation(priv, percpu_priv, fd); ++ ++ dpa_fd_release(net_dev, fd); ++} ++ ++static void _dpa_tx_error(struct net_device *net_dev, ++ const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ struct sk_buff *skb; ++ ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_ERRORS); ++ ++ if (dpaa_eth_hooks.tx_error && ++ dpaa_eth_hooks.tx_error(net_dev, fd, fqid) == DPAA_ETH_STOLEN) ++ /* now the hook must ensure proper cleanup */ ++ return; ++ ++ percpu_priv->stats.tx_errors++; ++ ++ skb = _dpa_cleanup_tx_fd(priv, fd); ++ dev_kfree_skb(skb); ++} ++ ++/* ++ * Helper function to factor out frame validation logic on all Rx paths. Its ++ * purpose is to extract from the Parse Results structure information about ++ * the integrity of the frame, its checksum, the length of the parsed headers ++ * and whether the frame is suitable for GRO. ++ * ++ * @skb will have its ip_summed field overwritten; ++ * @use_gro will only be written with 0, if the frame is definitely not ++ * GRO-able; otherwise, it will be left unchanged; ++ * @hdr_size will be written with a safe value, at least the size of the ++ * headers' length. ++ * ++ * Returns 0 if the frame contained no detectable error (including if the FMan ++ * Parser has not in fact been running), and a non-zero value if the Parser ++ * has run but encountered an error. ++ */ ++int __hot _dpa_process_parse_results(const t_FmPrsResult *parse_results, ++ const struct qm_fd *fd, ++ struct sk_buff *skb, ++ int *use_gro, ++ unsigned int *hdr_size __maybe_unused) ++{ ++ if (likely(fm_l4_hxs_has_run(parse_results))) { ++ /* ++ * Was there any parsing error? Note: this includes the check ++ * for a valid L4 checksum. ++ */ ++ if (unlikely(fm_l4_hxs_error(parse_results))) ++ /* Leave it to the caller to handle the frame. */ ++ return parse_results->l4r; ++ ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ /* ++ * If the HXS Parser has successfully run, we can reduce the ++ * number of bytes we'll memcopy into skb->data. ++ */ ++ *hdr_size = parse_results->nxthdr_off; ++#endif ++ /* ++ * We know the frame is valid. But has the L4 checksum actually ++ * been validated? (The L4CV bit is only set if the frame is ++ * TCP or UDP-with-non-zero-csum.) ++ */ ++ if (fd->status & FM_FD_STAT_L4CV) ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ else ++ /* ++ * If it turns out to be a 0-csum UDP, the stack will ++ * figure it out itself later, sparing us an extra ++ * check here on the fastpath of every incoming frame. ++ */ ++ skb->ip_summed = CHECKSUM_NONE; ++ ++ /* ++ * Don't go through GRO for certain types of traffic that ++ * we know are not GRO-able, such as dgram-based protocols. ++ * In the worst-case scenarios, such as small-pkt terminating ++ * UDP, the extra GRO processing would be overkill. ++ * ++ * The only protocol the Parser supports that is also GRO-able ++ * is currently TCP. ++ */ ++ if (!fm_l4_frame_is_tcp(parse_results)) ++ *use_gro = 0; ++ } else { ++ /* Inform the stack that we haven't done any csum validation. */ ++ skb->ip_summed = CHECKSUM_NONE; ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ /* ++ * Also, since the Parser hasn't run, we don't know the size of ++ * the headers, so we fall back to a safe default. ++ */ ++ *hdr_size = min((ssize_t)DPA_COPIED_HEADERS_SIZE, ++ dpa_fd_length(fd)); ++#endif ++ /* ++ * Bypass GRO for unknown traffic or if no PCDs are applied. ++ * It's unlikely that a GRO handler is installed for this proto ++ * or, if it is, user does not seem to care about performance ++ * (otherwise, PCDs would have been in place). ++ */ ++ *use_gro = 0; ++ } ++ ++ return 0; ++} ++ ++#ifndef CONFIG_DPAA_ETH_SG_SUPPORT ++void __hot _dpa_rx(struct net_device *net_dev, ++ const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ struct dpa_bp *dpa_bp; ++ struct sk_buff *skb; ++ struct sk_buff **skbh; ++ dma_addr_t addr = qm_fd_addr(fd); ++ u32 fd_status = fd->status; ++ unsigned int skb_len; ++ t_FmPrsResult *parse_result; ++ int ret; ++ unsigned int hdr_size_unused; ++ int use_gro = net_dev->features & NETIF_F_GRO; ++ ++ skbh = (struct sk_buff **)phys_to_virt(addr); ++ ++ if (unlikely(fd_status & FM_FD_STAT_ERRORS) != 0) { ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_ERRORS); ++ ++ percpu_priv->stats.rx_errors++; ++ ++ goto _return_dpa_fd_release; ++ } ++ ++ if (unlikely(fd->format != qm_fd_contig)) { ++ percpu_priv->stats.rx_dropped++; ++ if (netif_msg_rx_status(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "Dropping a SG frame\n"); ++ goto _return_dpa_fd_release; ++ } ++ ++ dpa_bp = dpa_bpid2pool(fd->bpid); ++ ++ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL); ++ ++ skb = *skbh; ++ prefetch(skb); ++ ++ /* Fill the SKB */ ++ dpa_process_one(percpu_priv, skb, dpa_bp, fd); ++ ++ prefetch(skb_shinfo(skb)); ++ ++#ifdef CONFIG_FSL_DPA_1588 ++ if (priv->tsu && priv->tsu->valid && priv->tsu->hwts_rx_en_ioctl) ++ dpa_ptp_store_rxstamp(net_dev, skb, fd); ++#endif ++ ++ skb->protocol = eth_type_trans(skb, net_dev); ++ ++ if (unlikely(dpa_check_rx_mtu(skb, net_dev->mtu))) { ++ percpu_priv->stats.rx_dropped++; ++ goto drop_large_frame; ++ } ++ ++ /* Execute the Rx processing hook, if it exists. */ ++ if (dpaa_eth_hooks.rx_default && dpaa_eth_hooks.rx_default(skb, ++ net_dev, fqid) == DPAA_ETH_STOLEN) ++ /* won't count the rx bytes in */ ++ goto skb_stolen; ++ ++ skb_len = skb->len; ++ ++ /* Validate the skb csum and figure out whether GRO is appropriate */ ++ parse_result = (t_FmPrsResult *)((u8 *)skbh + DPA_RX_PRIV_DATA_SIZE); ++ ret = _dpa_process_parse_results(parse_result, fd, skb, &use_gro, ++ &hdr_size_unused); ++ if (unlikely(ret)) { ++ percpu_priv->l4_hxs_errors++; ++ percpu_priv->stats.rx_dropped++; ++ goto drop_invalid_frame; ++ } ++ if (use_gro) { ++ gro_result_t gro_result; ++ ++ gro_result = napi_gro_receive(&percpu_priv->napi, skb); ++ if (unlikely(gro_result == GRO_DROP)) { ++ percpu_priv->stats.rx_dropped++; ++ goto packet_dropped; ++ } ++ } else if (unlikely(netif_receive_skb(skb) == NET_RX_DROP)) { ++ percpu_priv->stats.rx_dropped++; ++ goto packet_dropped; ++ } ++ ++ percpu_priv->stats.rx_packets++; ++ percpu_priv->stats.rx_bytes += skb_len; ++ ++packet_dropped: ++skb_stolen: ++ return; ++ ++drop_invalid_frame: ++drop_large_frame: ++ dev_kfree_skb(skb); ++ return; ++ ++_return_dpa_fd_release: ++ dpa_fd_release(net_dev, fd); ++} ++#endif /* CONFIG_DPAA_ETH_SG_SUPPORT */ ++ ++static void dpaa_eth_napi_disable(struct dpa_priv_s *priv) ++{ ++ struct dpa_percpu_priv_s *percpu_priv; ++ int i; ++ ++ if (priv->shared) ++ return; ++ ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ napi_disable(&percpu_priv->napi); ++ } ++} ++ ++static void dpaa_eth_napi_enable(struct dpa_priv_s *priv) ++{ ++ struct dpa_percpu_priv_s *percpu_priv; ++ int i; ++ ++ if (priv->shared) ++ return; ++ ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ napi_enable(&percpu_priv->napi); ++ } ++} ++ ++static int dpaa_eth_poll(struct napi_struct *napi, int budget) ++{ ++ int cleaned = qman_poll_dqrr(budget); ++ ++ if (cleaned < budget) { ++ int tmp; ++ napi_complete(napi); ++ tmp = qman_irqsource_add(QM_PIRQ_DQRI); ++ BUG_ON(tmp); ++ } ++ ++ return cleaned; ++} ++ ++static void __hot _dpa_tx_conf(struct net_device *net_dev, ++ const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ struct sk_buff *skb; ++ ++ if (unlikely(fd->status & FM_FD_STAT_ERRORS) != 0) { ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_ERRORS); ++ ++ percpu_priv->stats.tx_errors++; ++ } ++ ++ if (dpaa_eth_hooks.tx_confirm && dpaa_eth_hooks.tx_confirm(net_dev, ++ fd, fqid) == DPAA_ETH_STOLEN) ++ /* it's the hook that must now perform cleanup */ ++ return; ++ ++ /* This might not perfectly reflect the reality, if the core dequeueing ++ * the Tx confirmation is different from the one that did the enqueue, ++ * but at least it'll show up in the total count. */ ++ percpu_priv->tx_confirm++; ++ ++ skb = _dpa_cleanup_tx_fd(priv, fd); ++ ++#ifdef CONFIG_FSL_DPA_1588 ++ if (priv->tsu && priv->tsu->valid && priv->tsu->hwts_tx_en_ioctl) ++ dpa_ptp_store_txstamp(net_dev, skb, fd); ++#endif ++ dev_kfree_skb(skb); ++} ++ ++static struct dpa_bp *dpa_size2pool(struct dpa_priv_s *priv, size_t size) ++{ ++ int i; ++ ++ for (i = 0; i < priv->bp_count; i++) ++ if (DPA_BP_SIZE(size) <= priv->dpa_bp[i].size) ++ return dpa_bpid2pool(priv->dpa_bp[i].bpid); ++ return ERR_PTR(-ENODEV); ++} ++ ++/** ++ * Turn on HW checksum computation for this outgoing frame. ++ * If the current protocol is not something we support in this regard ++ * (or if the stack has already computed the SW checksum), we do nothing. ++ * ++ * Returns 0 if all goes well (or HW csum doesn't apply), and a negative value ++ * otherwise. ++ * ++ * Note that this function may modify the fd->cmd field and the skb data buffer ++ * (the Parse Results area). ++ */ ++int dpa_enable_tx_csum(struct dpa_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd, char *parse_results) ++{ ++ t_FmPrsResult *parse_result; ++ struct iphdr *iph; ++ struct ipv6hdr *ipv6h = NULL; ++ int l4_proto; ++ int ethertype = ntohs(skb->protocol); ++ int retval = 0; ++ ++ if (!priv->mac_dev || skb->ip_summed != CHECKSUM_PARTIAL) ++ return 0; ++ ++ /* Note: L3 csum seems to be already computed in sw, but we can't choose ++ * L4 alone from the FM configuration anyway. */ ++ ++ /* Fill in some fields of the Parse Results array, so the FMan ++ * can find them as if they came from the FMan Parser. */ ++ parse_result = (t_FmPrsResult *)parse_results; ++ ++ /* If we're dealing with VLAN, get the real Ethernet type */ ++ if (ethertype == ETH_P_8021Q) { ++ /* We can't always assume the MAC header is set correctly ++ * by the stack, so reset to beginning of skb->data */ ++ skb_reset_mac_header(skb); ++ ethertype = ntohs(vlan_eth_hdr(skb)->h_vlan_encapsulated_proto); ++ } ++ ++ /* Fill in the relevant L3 parse result fields ++ * and read the L4 protocol type */ ++ switch (ethertype) { ++ case ETH_P_IP: ++ parse_result->l3r = FM_L3_PARSE_RESULT_IPV4; ++ iph = ip_hdr(skb); ++ BUG_ON(iph == NULL); ++ l4_proto = ntohs(iph->protocol); ++ break; ++ case ETH_P_IPV6: ++ parse_result->l3r = FM_L3_PARSE_RESULT_IPV6; ++ ipv6h = ipv6_hdr(skb); ++ BUG_ON(ipv6h == NULL); ++ l4_proto = ntohs(ipv6h->nexthdr); ++ break; ++ default: ++ /* We shouldn't even be here */ ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_alert(priv->net_dev, "Can't compute HW csum " ++ "for L3 proto 0x%x\n", ntohs(skb->protocol)); ++ retval = -EIO; ++ goto return_error; ++ } ++ ++ /* Fill in the relevant L4 parse result fields */ ++ switch (l4_proto) { ++ case IPPROTO_UDP: ++ parse_result->l4r = FM_L4_PARSE_RESULT_UDP; ++ break; ++ case IPPROTO_TCP: ++ parse_result->l4r = FM_L4_PARSE_RESULT_TCP; ++ break; ++ default: ++ /* This can as well be a BUG() */ ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_alert(priv->net_dev, "Can't compute HW csum " ++ "for L4 proto 0x%x\n", l4_proto); ++ retval = -EIO; ++ goto return_error; ++ } ++ ++ /* At index 0 is IPOffset_1 as defined in the Parse Results */ ++ parse_result->ip_off[0] = skb_network_offset(skb); ++ parse_result->l4_off = skb_transport_offset(skb); ++ ++ /* Enable L3 (and L4, if TCP or UDP) HW checksum. */ ++ fd->cmd |= FM_FD_CMD_RPD | FM_FD_CMD_DTC; ++ ++ /* ++ * On P1023 and similar platforms fd->cmd interpretation could ++ * be disabled by setting CONTEXT_A bit ICMD; currently this bit ++ * is not set so we do not need to check; in the future, if/when ++ * using context_a we need to check this bit ++ */ ++ ++return_error: ++ return retval; ++} ++ ++static int __hot dpa_shared_tx(struct sk_buff *skb, struct net_device *net_dev) ++{ ++ struct dpa_bp *dpa_bp; ++ struct bm_buffer bmb; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct dpa_priv_s *priv; ++ struct qm_fd fd; ++ int queue_mapping; ++ int err; ++ void *dpa_bp_vaddr; ++ t_FmPrsResult parse_results; ++ ++ priv = netdev_priv(net_dev); ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, smp_processor_id()); ++ ++ memset(&fd, 0, sizeof(fd)); ++ fd.format = qm_fd_contig; ++ ++ queue_mapping = smp_processor_id(); ++ ++ dpa_bp = dpa_size2pool(priv, skb_headlen(skb)); ++ if (unlikely(IS_ERR(dpa_bp))) { ++ percpu_priv->stats.tx_errors++; ++ err = PTR_ERR(dpa_bp); ++ goto bpools_too_small_error; ++ } ++ ++ err = bman_acquire(dpa_bp->pool, &bmb, 1, 0); ++ if (unlikely(err <= 0)) { ++ percpu_priv->stats.tx_errors++; ++ if (err == 0) ++ err = -ENOMEM; ++ goto buf_acquire_failed; ++ } ++ fd.bpid = dpa_bp->bpid; ++ ++ fd.length20 = skb_headlen(skb); ++ fd.addr_hi = bmb.hi; ++ fd.addr_lo = bmb.lo; ++ fd.offset = DPA_BP_HEAD; ++ ++ /* ++ * The virtual address of the buffer pool is expected to be NULL ++ * in scenarios like MAC-less or Shared-MAC between Linux and ++ * USDPAA. In this case the buffers are dynamically mapped/unmapped. ++ */ ++ if (dpa_bp->vaddr) { ++ dpa_bp_vaddr = dpa_phys2virt(dpa_bp, bm_buf_addr(&bmb)); ++ ++ /* Copy the packet payload */ ++ skb_copy_from_linear_data(skb, ++ dpa_bp_vaddr + dpa_fd_offset(&fd), ++ dpa_fd_length(&fd)); ++ ++ /* Enable L3/L4 hardware checksum computation, if applicable */ ++ err = dpa_enable_tx_csum(priv, skb, &fd, ++ dpa_bp_vaddr + DPA_TX_PRIV_DATA_SIZE); ++ } else { ++ err = dpa_enable_tx_csum(priv, skb, &fd, ++ (char *)&parse_results); ++ ++ copy_to_unmapped_area(bm_buf_addr(&bmb) + DPA_TX_PRIV_DATA_SIZE, ++ &parse_results, ++ DPA_PARSE_RESULTS_SIZE); ++ ++ copy_to_unmapped_area(bm_buf_addr(&bmb) + dpa_fd_offset(&fd), ++ skb->data, ++ dpa_fd_length(&fd)); ++ } ++ ++ if (unlikely(err < 0)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "Tx HW csum error: %d\n", err); ++ percpu_priv->stats.tx_errors++; ++ goto l3_l4_csum_failed; ++ } ++ ++ err = dpa_xmit(priv, &percpu_priv->stats, queue_mapping, &fd); ++ ++l3_l4_csum_failed: ++bpools_too_small_error: ++buf_acquire_failed: ++ /* We're done with the skb */ ++ dev_kfree_skb(skb); ++ ++ return NETDEV_TX_OK; ++} ++ ++#ifndef CONFIG_DPAA_ETH_SG_SUPPORT ++static int skb_to_sg_fd(struct dpa_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd) ++{ ++ struct dpa_bp *dpa_bp = priv->dpa_bp; ++ void *vaddr; ++ dma_addr_t paddr; ++ struct sk_buff **skbh; ++ struct qm_sg_entry *sg_entry; ++ struct net_device *net_dev = priv->net_dev; ++ int err; ++ ++ /* Allocate the first buffer in the FD (used for storing S/G table) */ ++ vaddr = kmalloc(SGT_BUFFER_SIZE, GFP_ATOMIC); ++ if (unlikely(vaddr == NULL)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "Memory allocation failed\n"); ++ return -ENOMEM; ++ } ++ /* Store skb backpointer at the beginning of the buffer */ ++ skbh = (struct sk_buff **)vaddr; ++ *skbh = skb; ++ ++ /* Fill in FD */ ++ fd->format = qm_fd_sg; ++ fd->offset = DPA_BP_HEAD; ++ fd->length20 = skb->len; ++ ++ /* Enable hardware checksum computation */ ++ err = dpa_enable_tx_csum(priv, skb, fd, ++ (char *)vaddr + DPA_TX_PRIV_DATA_SIZE); ++ if (unlikely(err < 0)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "HW csum error: %d\n", err); ++ kfree(vaddr); ++ return err; ++ } ++ ++ /* Map the buffer and store its address in the FD */ ++ paddr = dma_map_single(dpa_bp->dev, vaddr, SGT_BUFFER_SIZE, ++ DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, paddr))) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "DMA mapping failed\n"); ++ kfree(vaddr); ++ return -EINVAL; ++ } ++ ++ fd->addr_hi = upper_32_bits(paddr); ++ fd->addr_lo = lower_32_bits(paddr); ++ ++ /* Fill in S/G entry */ ++ sg_entry = (struct qm_sg_entry *)(vaddr + fd->offset); ++ ++ sg_entry->extension = 0; ++ sg_entry->final = 1; ++ sg_entry->length = skb->len; ++ /* ++ * Put the same offset in the data buffer as in the SGT (first) buffer. ++ * This is the format for S/G frames generated by FMan; the manual is ++ * not clear if same is required of Tx S/G frames, but since we know ++ * for sure we have at least DPA_BP_HEAD bytes of skb headroom, lets not ++ * take any chances. ++ */ ++ sg_entry->offset = DPA_BP_HEAD; ++ ++ paddr = dma_map_single(dpa_bp->dev, skb->data - sg_entry->offset, ++ dpa_bp->size, DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, paddr))) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "DMA mapping failed\n"); ++ return -EINVAL; ++ } ++ sg_entry->addr_hi = upper_32_bits(paddr); ++ sg_entry->addr_lo = lower_32_bits(paddr); ++ ++ return 0; ++} ++ ++static int skb_to_contig_fd(struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ struct sk_buff *skb, struct qm_fd *fd) ++{ ++ struct sk_buff **skbh; ++ dma_addr_t addr; ++ struct dpa_bp *dpa_bp = priv->dpa_bp; ++ struct net_device *net_dev = priv->net_dev; ++ enum dma_data_direction dma_dir = DMA_TO_DEVICE; ++ bool can_recycle = false; ++ int offset, extra_offset; ++ int err; ++ ++ /* ++ * We are guaranteed that we have at least DPA_BP_HEAD of headroom. ++ * Buffers we allocated are padded to improve cache usage. In order ++ * to increase buffer re-use, we aim to keep any such buffers the ++ * same. This means the address passed to the FM should be DPA_BP_HEAD ++ * before the data for forwarded frames. ++ * ++ * However, offer some flexibility in fd layout, to allow originating ++ * (termination) buffers to be also recycled when possible. ++ * ++ * First, see if the conditions needed to recycle the skb are met: ++ * - skb not cloned, not shared ++ * - buffer size is large enough to accomodate a maximum size Rx frame ++ * - buffer size does not exceed the maximum size allowed in the pool ++ * (to avoid unbounded increase of buffer size in certain forwarding ++ * conditions) ++ * - buffer address is 16 byte aligned, as per DPAARM ++ * - there's enough room in the buffer pool ++ */ ++ if (likely(skb_is_recycleable(skb, dpa_bp->size) && ++ (skb_end_pointer(skb) - skb->head <= DPA_BP_MAX_BUF_SIZE) && ++ (*percpu_priv->dpa_bp_count < dpa_bp->target_count))) { ++ /* Compute the minimum necessary fd offset */ ++ offset = dpa_bp->size - skb->len - skb_tailroom(skb); ++ ++ /* ++ * And make sure the offset is no lower than DPA_BP_HEAD, ++ * as required by FMan ++ */ ++ offset = max(offset, (int)DPA_BP_HEAD); ++ ++ /* ++ * We also need to align the buffer address to 16, such that ++ * Fman will be able to reuse it on Rx. ++ * Since the buffer going to FMan starts at (skb->data - offset) ++ * this is what we'll try to align. We already know that ++ * headroom is at least DPA_BP_HEAD bytes long, but with ++ * the extra offset needed for alignment we may go beyond ++ * the beginning of the buffer. ++ * ++ * Also need to check that we don't go beyond the maximum ++ * offset that can be set for a contiguous FD. ++ */ ++ extra_offset = (unsigned long)(skb->data - offset) & 0xF; ++ if (likely((offset + extra_offset) <= skb_headroom(skb) && ++ (offset + extra_offset) <= DPA_MAX_FD_OFFSET)) { ++ /* We're good to go for recycling*/ ++ offset += extra_offset; ++ can_recycle = true; ++ } ++ } ++ ++ if (likely(can_recycle)) { ++ /* Buffer will get recycled, setup fd accordingly */ ++ fd->cmd |= FM_FD_CMD_FCO; ++ fd->bpid = dpa_bp->bpid; ++ /* ++ * Since the buffer will get back to the Bman pool ++ * and be re-used on Rx, map it for both read and write ++ */ ++ dma_dir = DMA_BIDIRECTIONAL; ++ } else { ++ /* ++ * No recycling here, so we don't care about address alignment. ++ * Just use the smallest offset required by FMan ++ */ ++ offset = DPA_BP_HEAD; ++ } ++ ++ skbh = (struct sk_buff **)(skb->data - offset); ++ *skbh = skb; ++ ++ ++ /* Enable L3/L4 hardware checksum computation. ++ * ++ * We must do this before dma_map_single(), because we may ++ * need to write into the skb. */ ++ err = dpa_enable_tx_csum(priv, skb, fd, ++ ((char *)skbh) + DPA_TX_PRIV_DATA_SIZE); ++ if (unlikely(err < 0)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "HW csum error: %d\n", err); ++ return err; ++ } ++ ++ fd->format = qm_fd_contig; ++ fd->length20 = skb->len; ++ fd->offset = offset; ++ ++ addr = dma_map_single(dpa_bp->dev, skbh, dpa_bp->size, dma_dir); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "dma_map_single() failed\n"); ++ return -EINVAL; ++ } ++ ++ fd->addr_hi = upper_32_bits(addr); ++ fd->addr_lo = lower_32_bits(addr); ++ ++ return 0; ++} ++ ++int __hot dpa_tx(struct sk_buff *skb, struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv; ++ struct qm_fd fd; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct net_device_stats *percpu_stats; ++ int queue_mapping; ++ int err; ++ ++ /* If there is a Tx hook, run it. */ ++ if (dpaa_eth_hooks.tx && ++ dpaa_eth_hooks.tx(skb, net_dev) == DPAA_ETH_STOLEN) ++ /* won't update any Tx stats */ ++ goto done; ++ ++ priv = netdev_priv(net_dev); ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, smp_processor_id()); ++ percpu_stats = &percpu_priv->stats; ++ ++ clear_fd(&fd); ++ queue_mapping = dpa_get_queue_mapping(skb); ++ ++ if (unlikely(skb_headroom(skb) < DPA_BP_HEAD)) { ++ struct sk_buff *skb_new; ++ ++ skb_new = skb_realloc_headroom(skb, DPA_BP_HEAD); ++ if (unlikely(!skb_new)) { ++ percpu_stats->tx_errors++; ++ kfree_skb(skb); ++ goto done; ++ } ++ kfree_skb(skb); ++ skb = skb_new; ++ } ++ ++#ifdef CONFIG_FSL_DPA_1588 ++ if (priv->tsu && priv->tsu->valid && priv->tsu->hwts_tx_en_ioctl) ++ fd.cmd |= FM_FD_CMD_UPD; ++#endif ++ ++ /* ++ * We have two paths here: ++ * ++ * 1.If the skb is cloned, create a S/G frame to avoid unsharing it. ++ * The S/G table will contain only one entry, pointing to our skb ++ * data buffer. ++ * The private data area containing the skb backpointer will reside ++ * inside the first buffer, such that it won't risk being overwritten ++ * in case a second skb pointing to the same data buffer is being ++ * processed concurently. ++ * No recycling is possible in this case, as the data buffer is shared. ++ * ++ * 2.If skb is not cloned, then the private area inside it can be ++ * safely used to store the skb backpointer. Simply create a contiguous ++ * fd in this case. ++ * Recycling can happen if the right conditions are met. ++ */ ++ if (skb_cloned(skb) && (skb->len > DPA_SKB_COPY_MAX_SIZE)) ++ err = skb_to_sg_fd(priv, skb, &fd); ++ else { ++ /* If cloned skb, but length is below DPA_SKB_COPY_MAX_SIZE, ++ * it's more efficient to unshare it and then use the new skb */ ++ skb = skb_unshare(skb, GFP_ATOMIC); ++ if (unlikely(!skb)) { ++ percpu_stats->tx_errors++; ++ goto done; ++ } ++ err = skb_to_contig_fd(priv, percpu_priv, skb, &fd); ++ } ++ if (unlikely(err < 0)) { ++ percpu_stats->tx_errors++; ++ goto fd_create_failed; ++ } ++ ++ if (fd.cmd & FM_FD_CMD_FCO) { ++ /* This skb is recycleable, and the fd generated from it ++ * has been filled in accordingly */ ++ skb_recycle(skb); ++ skb = NULL; ++ (*percpu_priv->dpa_bp_count)++; ++ percpu_priv->tx_returned++; ++ } ++ ++ if (unlikely(dpa_xmit(priv, percpu_stats, queue_mapping, ++ &fd) < 0)) ++ goto xmit_failed; ++ ++ net_dev->trans_start = jiffies; ++ goto done; ++ ++xmit_failed: ++ if (fd.cmd & FM_FD_CMD_FCO) { ++ (*percpu_priv->dpa_bp_count)--; ++ percpu_priv->tx_returned--; ++ } ++fd_create_failed: ++ _dpa_cleanup_tx_fd(priv, &fd); ++ dev_kfree_skb(skb); ++ ++done: ++ return NETDEV_TX_OK; ++} ++#endif /* CONFIG_DPAA_ETH_SG_SUPPORT */ ++ ++/** ++ * Congestion group state change notification callback. ++ * Stops the device's egress queues while they are congested and ++ * wakes them upon exiting congested state. ++ * Also updates some CGR-related stats. ++ */ ++static void dpaa_eth_cgscn(struct qman_portal *qm, struct qman_cgr *cgr, ++ int congested) ++{ ++ struct dpa_priv_s *priv = (struct dpa_priv_s *)container_of(cgr, ++ struct dpa_priv_s, cgr_data.cgr); ++ ++ if (congested) { ++ priv->cgr_data.congestion_start_jiffies = jiffies; ++ netif_tx_stop_all_queues(priv->net_dev); ++ priv->cgr_data.cgr_congested_count++; ++ } else { ++ priv->cgr_data.congested_jiffies += ++ (jiffies - priv->cgr_data.congestion_start_jiffies); ++ netif_tx_wake_all_queues(priv->net_dev); ++ } ++} ++ ++static enum qman_cb_dqrr_result ++ingress_rx_error_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, smp_processor_id()); ++ ++ if (dpaa_eth_napi_schedule(percpu_priv)) { ++ percpu_priv->in_interrupt++; ++ return qman_cb_dqrr_stop; ++ } ++ ++ dpaa_eth_refill_bpools(percpu_priv); ++ _dpa_rx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static enum qman_cb_dqrr_result __hot ++shared_rx_dqrr(struct qman_portal *portal, struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ const struct qm_fd *fd = &dq->fd; ++ struct dpa_bp *dpa_bp; ++ struct sk_buff *skb; ++ struct qm_sg_entry *sgt; ++ int i; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, smp_processor_id()); ++ ++ dpa_bp = dpa_bpid2pool(fd->bpid); ++ BUG_ON(IS_ERR(dpa_bp)); ++ ++ if (unlikely(fd->status & FM_FD_STAT_ERRORS) != 0) { ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_ERRORS); ++ ++ percpu_priv->stats.rx_errors++; ++ ++ goto out; ++ } ++ ++ skb = __netdev_alloc_skb(net_dev, ++ DPA_BP_HEAD + dpa_fd_length(fd), ++ GFP_ATOMIC); ++ if (unlikely(skb == NULL)) { ++ if (netif_msg_rx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "Could not alloc skb\n"); ++ ++ percpu_priv->stats.rx_dropped++; ++ ++ goto out; ++ } ++ ++ skb_reserve(skb, DPA_BP_HEAD); ++ ++ if (fd->format == qm_fd_sg) { ++ if (dpa_bp->vaddr) { ++ sgt = dpa_phys2virt(dpa_bp, ++ qm_fd_addr(fd)) + dpa_fd_offset(fd); ++ ++ for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) { ++ BUG_ON(sgt[i].extension); ++ ++ /* copy from sgt[i] */ ++ memcpy(skb_put(skb, sgt[i].length), ++ dpa_phys2virt(dpa_bp, ++ qm_sg_addr(&sgt[i]) + ++ sgt[i].offset), ++ sgt[i].length); ++ if (sgt[i].final) ++ break; ++ } ++ } else { ++ sgt = kmalloc(DPA_SGT_MAX_ENTRIES * sizeof(*sgt), ++ GFP_ATOMIC); ++ if (unlikely(sgt == NULL)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, ++ "Memory allocation failed\n"); ++ return -ENOMEM; ++ } ++ ++ copy_from_unmapped_area(sgt, ++ qm_fd_addr(fd) + dpa_fd_offset(fd), ++ min(DPA_SGT_MAX_ENTRIES * sizeof(*sgt), ++ dpa_bp->size)); ++ ++ for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) { ++ BUG_ON(sgt[i].extension); ++ ++ copy_from_unmapped_area( ++ skb_put(skb, sgt[i].length), ++ qm_sg_addr(&sgt[i]) + sgt[i].offset, ++ sgt[i].length); ++ ++ if (sgt[i].final) ++ break; ++ } ++ ++ kfree(sgt); ++ } ++ goto skb_copied; ++ } ++ ++ /* otherwise fd->format == qm_fd_contig */ ++ if (dpa_bp->vaddr) { ++ /* Fill the SKB */ ++ memcpy(skb_put(skb, dpa_fd_length(fd)), ++ dpa_phys2virt(dpa_bp, qm_fd_addr(fd)) + ++ dpa_fd_offset(fd), dpa_fd_length(fd)); ++ } else { ++ copy_from_unmapped_area(skb_put(skb, dpa_fd_length(fd)), ++ qm_fd_addr(fd) + dpa_fd_offset(fd), ++ dpa_fd_length(fd)); ++ } ++ ++skb_copied: ++ skb->protocol = eth_type_trans(skb, net_dev); ++ ++ if (unlikely(dpa_check_rx_mtu(skb, net_dev->mtu))) { ++ percpu_priv->stats.rx_dropped++; ++ dev_kfree_skb_any(skb); ++ goto out; ++ } ++ ++ if (unlikely(netif_rx(skb) != NET_RX_SUCCESS)) ++ percpu_priv->stats.rx_dropped++; ++ else { ++ percpu_priv->stats.rx_packets++; ++ percpu_priv->stats.rx_bytes += dpa_fd_length(fd); ++ } ++ ++out: ++ if (fd->format == qm_fd_sg) ++ dpa_fd_release_sg(net_dev, fd); ++ else ++ dpa_fd_release(net_dev, fd); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++ ++static enum qman_cb_dqrr_result __hot ++ingress_rx_default_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ /* IRQ handler, non-migratable; safe to use __this_cpu_ptr here */ ++ percpu_priv = __this_cpu_ptr(priv->percpu_priv); ++ ++ if (unlikely(dpaa_eth_napi_schedule(percpu_priv))) { ++ percpu_priv->in_interrupt++; ++ return qman_cb_dqrr_stop; ++ } ++ ++ /* Vale of plenty: make sure we didn't run out of buffers */ ++ dpaa_eth_refill_bpools(percpu_priv); ++ _dpa_rx(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static enum qman_cb_dqrr_result ++ingress_tx_error_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, smp_processor_id()); ++ ++ if (dpaa_eth_napi_schedule(percpu_priv)) { ++ percpu_priv->in_interrupt++; ++ return qman_cb_dqrr_stop; ++ } ++ ++ _dpa_tx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static enum qman_cb_dqrr_result __hot ++ingress_tx_default_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ /* Non-migratable context, safe to use __this_cpu_ptr */ ++ percpu_priv = __this_cpu_ptr(priv->percpu_priv); ++ ++ if (dpaa_eth_napi_schedule(percpu_priv)) { ++ percpu_priv->in_interrupt++; ++ return qman_cb_dqrr_stop; ++ } ++ ++ _dpa_tx_conf(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static enum qman_cb_dqrr_result ++shared_tx_error_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct dpa_bp *dpa_bp; ++ const struct qm_fd *fd = &dq->fd; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ dpa_bp = dpa_bpid2pool(fd->bpid); ++ BUG_ON(IS_ERR(dpa_bp)); ++ ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, smp_processor_id()); ++ ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_ERRORS); ++ ++ if ((fd->format == qm_fd_sg) && (!dpa_bp->vaddr)) ++ dpa_fd_release_sg(net_dev, fd); ++ else ++ dpa_fd_release(net_dev, fd); ++ ++ percpu_priv->stats.tx_errors++; ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static enum qman_cb_dqrr_result __hot ++shared_tx_default_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct dpa_bp *dpa_bp; ++ const struct qm_fd *fd = &dq->fd; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ dpa_bp = dpa_bpid2pool(fd->bpid); ++ BUG_ON(IS_ERR(dpa_bp)); ++ ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, smp_processor_id()); ++ ++ if (unlikely(fd->status & FM_FD_STAT_ERRORS) != 0) { ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_ERRORS); ++ ++ percpu_priv->stats.tx_errors++; ++ } ++ ++ if ((fd->format == qm_fd_sg) && (!dpa_bp->vaddr)) ++ dpa_fd_release_sg(net_dev, fd); ++ else ++ dpa_fd_release(net_dev, fd); ++ ++ percpu_priv->tx_confirm++; ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static void count_ern(struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_mr_entry *msg) ++{ ++ switch (msg->ern.rc & QM_MR_RC_MASK) { ++ case QM_MR_RC_CGR_TAILDROP: ++ percpu_priv->ern_cnt.cg_tdrop++; ++ break; ++ case QM_MR_RC_WRED: ++ percpu_priv->ern_cnt.wred++; ++ break; ++ case QM_MR_RC_ERROR: ++ percpu_priv->ern_cnt.err_cond++; ++ break; ++ case QM_MR_RC_ORPWINDOW_EARLY: ++ percpu_priv->ern_cnt.early_window++; ++ break; ++ case QM_MR_RC_ORPWINDOW_LATE: ++ percpu_priv->ern_cnt.late_window++; ++ break; ++ case QM_MR_RC_FQ_TAILDROP: ++ percpu_priv->ern_cnt.fq_tdrop++; ++ break; ++ case QM_MR_RC_ORPWINDOW_RETIRED: ++ percpu_priv->ern_cnt.fq_retired++; ++ break; ++ case QM_MR_RC_ORP_ZERO: ++ percpu_priv->ern_cnt.orp_zero++; ++ break; ++ } ++} ++ ++static void shared_ern(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ struct net_device *net_dev; ++ const struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct dpa_fq *dpa_fq = (struct dpa_fq *)fq; ++ ++ net_dev = dpa_fq->net_dev; ++ priv = netdev_priv(net_dev); ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, smp_processor_id()); ++ ++ dpa_fd_release(net_dev, &msg->ern.fd); ++ ++ percpu_priv->stats.tx_dropped++; ++ percpu_priv->stats.tx_fifo_errors++; ++ count_ern(percpu_priv, msg); ++} ++ ++static void egress_ern(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ struct net_device *net_dev; ++ const struct dpa_priv_s *priv; ++ struct sk_buff *skb; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct qm_fd fd = msg->ern.fd; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ /* Non-migratable context, safe to use __this_cpu_ptr */ ++ percpu_priv = __this_cpu_ptr(priv->percpu_priv); ++ ++ percpu_priv->stats.tx_dropped++; ++ percpu_priv->stats.tx_fifo_errors++; ++ count_ern(percpu_priv, msg); ++ ++ /* ++ * If we intended this buffer to go into the pool ++ * when the FM was done, we need to put it in ++ * manually. ++ */ ++ if (msg->ern.fd.cmd & FM_FD_CMD_FCO) { ++ dpa_fd_release(net_dev, &fd); ++ return; ++ } ++ ++ skb = _dpa_cleanup_tx_fd(priv, &fd); ++ dev_kfree_skb_any(skb); ++} ++ ++static const struct qman_fq rx_shared_fq __devinitconst = { ++ .cb = { .dqrr = shared_rx_dqrr } ++}; ++static const struct qman_fq rx_private_defq __devinitconst = { ++ .cb = { .dqrr = ingress_rx_default_dqrr } ++}; ++static const struct qman_fq rx_private_errq __devinitconst = { ++ .cb = { .dqrr = ingress_rx_error_dqrr } ++}; ++static const struct qman_fq tx_private_defq __devinitconst = { ++ .cb = { .dqrr = ingress_tx_default_dqrr } ++}; ++static const struct qman_fq tx_private_errq __devinitconst = { ++ .cb = { .dqrr = ingress_tx_error_dqrr } ++}; ++static const struct qman_fq tx_shared_defq __devinitconst = { ++ .cb = { .dqrr = shared_tx_default_dqrr } ++}; ++static const struct qman_fq tx_shared_errq __devinitconst = { ++ .cb = { .dqrr = shared_tx_error_dqrr } ++}; ++static const struct qman_fq private_egress_fq __devinitconst = { ++ .cb = { .ern = egress_ern } ++}; ++static const struct qman_fq shared_egress_fq __devinitconst = { ++ .cb = { .ern = shared_ern } ++}; ++ ++#ifdef CONFIG_DPAA_ETH_UNIT_TESTS ++static bool __devinitdata tx_unit_test_passed = true; ++ ++static void __devinit tx_unit_test_ern(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct sk_buff **skbh; ++ struct sk_buff *skb; ++ const struct qm_fd *fd; ++ dma_addr_t addr; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ tx_unit_test_passed = false; ++ ++ fd = &msg->ern.fd; ++ ++ addr = qm_fd_addr(fd); ++ ++ skbh = (struct sk_buff **)phys_to_virt(addr); ++ skb = *skbh; ++ ++ if (!skb || !is_kernel_addr((unsigned long)skb)) ++ panic("Corrupt skb in ERN!\n"); ++ ++ kfree_skb(skb); ++} ++ ++static unsigned char __devinitdata *tx_unit_skb_head; ++static unsigned char __devinitdata *tx_unit_skb_end; ++static int __devinitdata tx_unit_tested; ++ ++static enum qman_cb_dqrr_result __devinit tx_unit_test_dqrr( ++ struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct sk_buff **skbh; ++ struct sk_buff *skb; ++ const struct qm_fd *fd; ++ dma_addr_t addr; ++ unsigned char *startaddr; ++ struct dpa_percpu_priv_s *percpu_priv; ++ ++ tx_unit_test_passed = false; ++ ++ tx_unit_tested++; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, smp_processor_id()); ++ ++ fd = &dq->fd; ++ ++ addr = qm_fd_addr(fd); ++ ++ skbh = (struct sk_buff **)phys_to_virt(addr); ++ startaddr = (unsigned char *)skbh; ++ skb = *skbh; ++ ++ if (!skb || !is_kernel_addr((unsigned long)skb)) ++ panic("Invalid skb address in TX Unit Test FD\n"); ++ ++ /* Make sure we're dealing with the same skb */ ++ if (skb->head != tx_unit_skb_head ++ || skb_end_pointer(skb) != tx_unit_skb_end) ++ goto out; ++ ++ /* ++ * If we recycled, then there must be enough room between fd.addr ++ * and skb->end for a new RX buffer ++ */ ++ if (fd->cmd & FM_FD_CMD_FCO) { ++ size_t bufsize = skb_end_pointer(skb) - startaddr; ++ ++ if (bufsize < dpa_get_max_frm()) ++ goto out; ++ } else { ++ /* ++ * If we didn't recycle, but the buffer was big enough, ++ * increment the counter to put it back ++ */ ++ if (skb_end_pointer(skb) - skb->head >= ++ dpa_get_max_frm()) ++ (*percpu_priv->dpa_bp_count)++; ++ ++ /* If we didn't recycle, the data pointer should be good */ ++ if (skb->data != startaddr + dpa_fd_offset(fd)) ++ goto out; ++ } ++ ++ tx_unit_test_passed = true; ++out: ++ /* The skb is no longer needed, and belongs to us */ ++ kfree_skb(skb); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static const struct qman_fq tx_unit_test_fq __devinitconst = { ++ .cb = { .dqrr = tx_unit_test_dqrr, .ern = tx_unit_test_ern } ++}; ++ ++static struct __devinitdata dpa_fq unit_fq; ++#ifdef CONFIG_DPA_TX_RECYCLE ++static struct dpa_fq unit_recycle_fq; ++#endif ++static bool __devinitdata tx_unit_test_ran; /* Starts as false */ ++ ++static int __devinit dpa_tx_unit_test(struct net_device *net_dev) ++{ ++ /* Create a new FQ */ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct qman_fq *oldq; ++ int size, headroom; ++ struct dpa_percpu_priv_s *percpu_priv; ++ cpumask_var_t old_cpumask; ++ int test_count = 0; ++ int err = 0; ++ int tests_failed = 0; ++ const cpumask_t *cpus = qman_affine_cpus(); ++#ifdef CONFIG_DPA_TX_RECYCLE ++ struct qman_fq *oldrecycleq; ++#endif ++ ++ if (!alloc_cpumask_var(&old_cpumask, GFP_KERNEL)) { ++ pr_err("UNIT test cpumask allocation failed\n"); ++ return -ENOMEM; ++ } ++ ++ cpumask_copy(old_cpumask, tsk_cpus_allowed(current)); ++ set_cpus_allowed_ptr(current, cpus); ++ /* disable bottom halves */ ++ local_bh_disable(); ++ ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, smp_processor_id()); ++ ++ qman_irqsource_remove(QM_PIRQ_DQRI); ++ unit_fq.net_dev = net_dev; ++ unit_fq.fq_base = tx_unit_test_fq; ++ ++ /* Save old queue */ ++ oldq = priv->egress_fqs[smp_processor_id()]; ++ ++ err = qman_create_fq(0, QMAN_FQ_FLAG_DYNAMIC_FQID, &unit_fq.fq_base); ++ ++ if (err < 0) { ++ pr_err("UNIT test FQ create failed: %d\n", err); ++ goto fq_create_fail; ++ } ++ ++ err = qman_init_fq(&unit_fq.fq_base, ++ QMAN_INITFQ_FLAG_SCHED | QMAN_INITFQ_FLAG_LOCAL, NULL); ++ if (err < 0) { ++ pr_err("UNIT test FQ init failed: %d\n", err); ++ goto fq_init_fail; ++ } ++ ++ /* Replace queue 0 with this queue */ ++ priv->egress_fqs[smp_processor_id()] = &unit_fq.fq_base; ++ ++#ifdef CONFIG_DPA_TX_RECYCLE ++ oldrecycleq = priv->recycle_fqs[smp_processor_id()]; ++ unit_recycle_fq.net_dev = net_dev; ++ unit_recycle_fq.fq_base = tx_unit_test_fq; ++ ++ err = qman_create_fq(0, QMAN_FQ_FLAG_DYNAMIC_FQID, ++ &unit_recycle_fq.fq_base); ++ ++ if (err < 0) { ++ pr_err("UNIT test Recycle FQ create failed: %d\n", err); ++ goto recycle_fq_create_fail; ++ } ++ ++ err = qman_init_fq(&unit_recycle_fq.fq_base, ++ QMAN_INITFQ_FLAG_SCHED | QMAN_INITFQ_FLAG_LOCAL, NULL); ++ if (err < 0) { ++ pr_err("UNIT test Recycle FQ init failed: %d\n", err); ++ goto recycle_fq_init_fail; ++ } ++ ++ priv->recycle_fqs[smp_processor_id()] = &unit_recycle_fq.fq_base; ++ ++ pr_err("TX Unit Test using FQ: %d - Recycle FQ: %d\n", ++ qman_fq_fqid(&unit_fq.fq_base), ++ qman_fq_fqid(&unit_recycle_fq.fq_base)); ++#else ++ pr_err("TX Unit Test using FQ %d\n", qman_fq_fqid(&unit_fq.fq_base)); ++#endif ++ ++ /* Try packet sizes from 64-bytes to just above the maximum */ ++ for (size = 64; size <= 9600 + 128; size += 64) { ++ for (headroom = DPA_BP_HEAD; headroom < 0x800; headroom += 16) { ++ int ret; ++ struct sk_buff *skb; ++ ++ test_count++; ++ ++ skb = dev_alloc_skb(size + headroom); ++ ++ if (!skb) { ++ pr_err("Failed to allocate skb\n"); ++ err = -ENOMEM; ++ goto end_test; ++ } ++ ++ if (skb_end_pointer(skb) - skb->head >= ++ dpa_get_max_frm()) ++ (*percpu_priv->dpa_bp_count)--; ++ ++ skb_put(skb, size + headroom); ++ skb_pull(skb, headroom); ++ ++ tx_unit_skb_head = skb->head; ++ tx_unit_skb_end = skb_end_pointer(skb); ++ ++ skb_set_queue_mapping(skb, smp_processor_id()); ++ ++ /* tx */ ++ ret = net_dev->netdev_ops->ndo_start_xmit(skb, net_dev); ++ ++ if (ret != NETDEV_TX_OK) { ++ pr_err("Failed to TX with err %d\n", ret); ++ err = -EIO; ++ goto end_test; ++ } ++ ++ /* Wait for it to arrive */ ++ ret = spin_event_timeout(qman_poll_dqrr(1) != 0, ++ 100000, 1); ++ ++ if (!ret) { ++ pr_err("TX Packet never arrived\n"); ++ /* ++ * Count the test as failed. ++ */ ++ tests_failed++; ++ } ++ ++ /* Was it good? */ ++ if (tx_unit_test_passed == false) { ++ pr_err("Test failed:\n"); ++ pr_err("size: %d pad: %d head: %p end: %p\n", ++ size, headroom, tx_unit_skb_head, ++ tx_unit_skb_end); ++ tests_failed++; ++ } ++ } ++ } ++ ++end_test: ++ err = qman_retire_fq(&unit_fq.fq_base, NULL); ++ if (unlikely(err < 0)) ++ pr_err("Could not retire TX Unit Test FQ (%d)\n", err); ++ ++ err = qman_oos_fq(&unit_fq.fq_base); ++ if (unlikely(err < 0)) ++ pr_err("Could not OOS TX Unit Test FQ (%d)\n", err); ++ ++#ifdef CONFIG_DPA_TX_RECYCLE ++ err = qman_retire_fq(&unit_recycle_fq.fq_base, NULL); ++ if (unlikely(err < 0)) ++ pr_err("Could not retire Recycle TX Unit Test FQ (%d)\n", err); ++ ++ err = qman_oos_fq(&unit_recycle_fq.fq_base); ++ if (unlikely(err < 0)) ++ pr_err("Could not OOS Recycle TX Unit Test FQ (%d)\n", err); ++ ++recycle_fq_init_fail: ++ qman_destroy_fq(&unit_recycle_fq.fq_base, 0); ++ ++recycle_fq_create_fail: ++ priv->recycle_fqs[smp_processor_id()] = oldrecycleq; ++#endif ++ ++fq_init_fail: ++ qman_destroy_fq(&unit_fq.fq_base, 0); ++ ++fq_create_fail: ++ priv->egress_fqs[smp_processor_id()] = oldq; ++ local_bh_enable(); ++ qman_irqsource_add(QM_PIRQ_DQRI); ++ tx_unit_test_ran = true; ++ set_cpus_allowed_ptr(current, old_cpumask); ++ free_cpumask_var(old_cpumask); ++ ++ pr_err("Tested %d/%d packets. %d failed\n", test_count, tx_unit_tested, ++ tests_failed); ++ ++ if (tests_failed) ++ err = -EINVAL; ++ ++ /* Reset counters */ ++ memset(&percpu_priv->stats, 0, sizeof(percpu_priv->stats)); ++ ++ return err; ++} ++#endif ++ ++static int __cold dpa_start(struct net_device *net_dev) ++{ ++ int err, i; ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ ++ if (!mac_dev) ++ goto no_mac; ++ ++ dpaa_eth_napi_enable(priv); ++ ++ err = mac_dev->init_phy(net_dev); ++ if (err < 0) { ++ if (netif_msg_ifup(priv)) ++ netdev_err(net_dev, "init_phy() = %d\n", err); ++ goto init_phy_failed; ++ } ++ ++ for_each_port_device(i, mac_dev->port_dev) ++ fm_port_enable(mac_dev->port_dev[i]); ++ ++ err = priv->mac_dev->start(mac_dev); ++ if (err < 0) { ++ if (netif_msg_ifup(priv)) ++ netdev_err(net_dev, "mac_dev->start() = %d\n", err); ++ goto mac_start_failed; ++ } ++ ++no_mac: ++ netif_tx_start_all_queues(net_dev); ++ ++ return 0; ++ ++mac_start_failed: ++ for_each_port_device(i, mac_dev->port_dev) ++ fm_port_disable(mac_dev->port_dev[i]); ++ ++init_phy_failed: ++ dpaa_eth_napi_disable(priv); ++ ++ return err; ++} ++ ++static int __cold dpa_stop(struct net_device *net_dev) ++{ ++ int _errno, i; ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ ++ netif_tx_stop_all_queues(net_dev); ++ ++ if (!mac_dev) ++ return 0; ++ ++ _errno = mac_dev->stop(mac_dev); ++ if (unlikely(_errno < 0)) ++ if (netif_msg_ifdown(priv)) ++ netdev_err(net_dev, "mac_dev->stop() = %d\n", ++ _errno); ++ ++ for_each_port_device(i, mac_dev->port_dev) ++ fm_port_disable(mac_dev->port_dev[i]); ++ ++ if (mac_dev->phy_dev) ++ phy_disconnect(mac_dev->phy_dev); ++ mac_dev->phy_dev = NULL; ++ ++ dpaa_eth_napi_disable(priv); ++ ++ return _errno; ++} ++ ++static void __cold dpa_timeout(struct net_device *net_dev) ++{ ++ const struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ ++ priv = netdev_priv(net_dev); ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, smp_processor_id()); ++ ++ if (netif_msg_timer(priv)) ++ netdev_crit(net_dev, "Transmit timeout latency: %u ms\n", ++ jiffies_to_msecs(jiffies - net_dev->trans_start)); ++ ++ percpu_priv->stats.tx_errors++; ++} ++ ++static int __devinit dpa_bp_cmp(const void *dpa_bp0, const void *dpa_bp1) ++{ ++ return ((struct dpa_bp *)dpa_bp0)->size - ++ ((struct dpa_bp *)dpa_bp1)->size; ++} ++ ++static struct dpa_bp * __devinit __cold __must_check __attribute__((nonnull)) ++dpa_bp_probe(struct platform_device *_of_dev, size_t *count) ++{ ++ int i, lenp, na, ns; ++ struct device *dev; ++ struct device_node *dev_node; ++ const phandle *phandle_prop; ++ const uint32_t *bpid; ++ const uint32_t *bpool_cfg; ++ struct dpa_bp *dpa_bp; ++ int has_kernel_pool = 0; ++ int has_shared_pool = 0; ++ ++ dev = &_of_dev->dev; ++ ++ /* The default is one, if there's no property */ ++ *count = 1; ++ ++ /* There are three types of buffer pool configuration: ++ * 1) No bp assignment ++ * 2) A static assignment to an empty configuration ++ * 3) A static assignment to one or more configured pools ++ * ++ * We don't support using multiple unconfigured pools. ++ */ ++ ++ /* Get the buffer pools to be used */ ++ phandle_prop = of_get_property(dev->of_node, ++ "fsl,bman-buffer-pools", &lenp); ++ ++ if (phandle_prop) ++ *count = lenp / sizeof(phandle); ++ else { ++ if (default_pool) ++ return default_pool; ++ ++ has_kernel_pool = 1; ++ } ++ ++ dpa_bp = devm_kzalloc(dev, *count * sizeof(*dpa_bp), GFP_KERNEL); ++ if (unlikely(dpa_bp == NULL)) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ dev_node = of_find_node_by_path("/"); ++ if (unlikely(dev_node == NULL)) { ++ dev_err(dev, "of_find_node_by_path(/) failed\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ na = of_n_addr_cells(dev_node); ++ ns = of_n_size_cells(dev_node); ++ ++ for (i = 0; i < *count && phandle_prop; i++) { ++ of_node_put(dev_node); ++ dev_node = of_find_node_by_phandle(phandle_prop[i]); ++ if (unlikely(dev_node == NULL)) { ++ dev_err(dev, "of_find_node_by_phandle() failed\n"); ++ return ERR_PTR(-EFAULT); ++ } ++ ++ if (unlikely(!of_device_is_compatible(dev_node, "fsl,bpool"))) { ++ dev_err(dev, ++ "!of_device_is_compatible(%s, fsl,bpool)\n", ++ dev_node->full_name); ++ dpa_bp = ERR_PTR(-EINVAL); ++ goto _return_of_node_put; ++ } ++ ++ bpid = of_get_property(dev_node, "fsl,bpid", &lenp); ++ if ((bpid == NULL) || (lenp != sizeof(*bpid))) { ++ dev_err(dev, "fsl,bpid property not found.\n"); ++ dpa_bp = ERR_PTR(-EINVAL); ++ goto _return_of_node_put; ++ } ++ dpa_bp[i].bpid = *bpid; ++ ++ bpool_cfg = of_get_property(dev_node, "fsl,bpool-ethernet-cfg", ++ &lenp); ++ if (bpool_cfg && (lenp == (2 * ns + na) * sizeof(*bpool_cfg))) { ++ const uint32_t *seed_pool; ++ ++ dpa_bp[i].config_count = ++ (int)of_read_number(bpool_cfg, ns); ++ dpa_bp[i].size = of_read_number(bpool_cfg + ns, ns); ++ dpa_bp[i].paddr = ++ of_read_number(bpool_cfg + 2 * ns, na); ++ ++ seed_pool = of_get_property(dev_node, ++ "fsl,bpool-ethernet-seeds", &lenp); ++ dpa_bp[i].seed_pool = !!seed_pool; ++ ++ has_shared_pool = 1; ++ } else { ++ has_kernel_pool = 1; ++ } ++ ++ if (i > 0) ++ has_shared_pool = 1; ++ } ++ ++ if (has_kernel_pool && has_shared_pool) { ++ dev_err(dev, "Invalid buffer pool configuration " ++ "for node %s\n", dev_node->full_name); ++ dpa_bp = ERR_PTR(-EINVAL); ++ goto _return_of_node_put; ++ } else if (has_kernel_pool) { ++ dpa_bp->target_count = DEFAULT_COUNT; ++ dpa_bp->size = DEFAULT_BUF_SIZE; ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ if (dpa_bp->size > PAGE_SIZE) { ++ dev_warn(dev, "Default buffer size too large. " ++ "Round down to PAGE_SIZE\n"); ++ dpa_bp->size = PAGE_SIZE; ++ } ++#endif ++ dpa_bp->kernel_pool = 1; ++ } ++ ++ sort(dpa_bp, *count, sizeof(*dpa_bp), dpa_bp_cmp, NULL); ++ ++ return dpa_bp; ++ ++_return_of_node_put: ++ if (dev_node) ++ of_node_put(dev_node); ++ ++ return dpa_bp; ++} ++ ++static int dpa_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp, ++ size_t count) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ int i; ++ ++ if (dpa_bp->kernel_pool) { ++ priv->shared = 0; ++ ++ if (netif_msg_probe(priv)) ++ dev_info(net_dev->dev.parent, ++ "Using private BM buffer pools\n"); ++ } else { ++ priv->shared = 1; ++ } ++ ++ priv->dpa_bp = dpa_bp; ++ priv->bp_count = count; ++ ++ for (i = 0; i < count; i++) { ++ int err; ++ err = dpa_bp_alloc(&dpa_bp[i]); ++ if (err < 0) { ++ dpa_bp_free(priv, dpa_bp); ++ priv->dpa_bp = NULL; ++ return err; ++ } ++ ++ /* For now, just point to the default pool. ++ * We can add support for more pools, later ++ */ ++ if (dpa_bp->kernel_pool) ++ priv->dpa_bp = default_pool; ++ } ++ ++ return 0; ++} ++ ++static struct mac_device * __devinit __cold __must_check ++__attribute__((nonnull)) ++dpa_mac_probe(struct platform_device *_of_dev) ++{ ++ struct device *dpa_dev, *dev; ++ struct device_node *mac_node; ++ int lenp; ++ const phandle *phandle_prop; ++ struct platform_device *of_dev; ++ struct mac_device *mac_dev; ++#ifdef CONFIG_FSL_DPA_1588 ++ struct net_device *net_dev = NULL; ++ struct dpa_priv_s *priv = NULL; ++ struct device_node *timer_node; ++#endif ++ ++ phandle_prop = of_get_property(_of_dev->dev.of_node, ++ "fsl,fman-mac", &lenp); ++ if (phandle_prop == NULL) ++ return NULL; ++ ++ BUG_ON(lenp != sizeof(phandle)); ++ ++ dpa_dev = &_of_dev->dev; ++ ++ mac_node = of_find_node_by_phandle(*phandle_prop); ++ if (unlikely(mac_node == NULL)) { ++ dev_err(dpa_dev, "of_find_node_by_phandle() failed\n"); ++ return ERR_PTR(-EFAULT); ++ } ++ ++ of_dev = of_find_device_by_node(mac_node); ++ if (unlikely(of_dev == NULL)) { ++ dev_err(dpa_dev, "of_find_device_by_node(%s) failed\n", ++ mac_node->full_name); ++ of_node_put(mac_node); ++ return ERR_PTR(-EINVAL); ++ } ++ of_node_put(mac_node); ++ ++ dev = &of_dev->dev; ++ ++ mac_dev = dev_get_drvdata(dev); ++ if (unlikely(mac_dev == NULL)) { ++ dev_err(dpa_dev, "dev_get_drvdata(%s) failed\n", ++ dev_name(dev)); ++ return ERR_PTR(-EINVAL); ++ } ++ ++#ifdef CONFIG_FSL_DPA_1588 ++ phandle_prop = of_get_property(mac_node, "ptimer-handle", &lenp); ++ if (phandle_prop && ((mac_dev->phy_if != PHY_INTERFACE_MODE_SGMII) || ++ ((mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII) && ++ (mac_dev->speed == SPEED_1000)))) { ++ timer_node = of_find_node_by_phandle(*phandle_prop); ++ if (timer_node && (net_dev = dev_get_drvdata(dpa_dev))) { ++ priv = netdev_priv(net_dev); ++ if (!dpa_ptp_init(priv)) ++ dev_info(dev, "%s: ptp-timer enabled\n", ++ mac_node->full_name); ++ } ++ } ++#endif ++ ++ return mac_dev; ++} ++ ++static const char fsl_qman_frame_queues[][25] __devinitconst = { ++ [RX] = "fsl,qman-frame-queues-rx", ++ [TX] = "fsl,qman-frame-queues-tx" ++}; ++ ++#ifdef CONFIG_DEBUG_FS ++static int __cold dpa_debugfs_show(struct seq_file *file, void *offset) ++{ ++ int i; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv, total; ++ struct dpa_bp *dpa_bp; ++ unsigned int dpa_bp_count = 0; ++ unsigned int count_total = 0; ++ struct qm_mcr_querycgr query_cgr; ++ ++ BUG_ON(offset == NULL); ++ ++ priv = netdev_priv((struct net_device *)file->private); ++ ++ dpa_bp = priv->dpa_bp; ++ ++ memset(&total, 0, sizeof(total)); ++ ++ /* "Standard" counters */ ++ seq_printf(file, "\nDPA counters for %s:\n" ++ "CPU irqs rx tx recycle" \ ++ " confirm tx sg tx err rx err l4 hxs drp bp count\n", ++ priv->net_dev->name); ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ /* Only private interfaces have an associated counter for bp ++ * buffers */ ++ if (!priv->shared) ++ dpa_bp_count = *percpu_priv->dpa_bp_count; ++ ++ total.in_interrupt += percpu_priv->in_interrupt; ++ total.stats.rx_packets += percpu_priv->stats.rx_packets; ++ total.stats.tx_packets += percpu_priv->stats.tx_packets; ++ total.tx_returned += percpu_priv->tx_returned; ++ total.tx_confirm += percpu_priv->tx_confirm; ++ total.tx_frag_skbuffs += percpu_priv->tx_frag_skbuffs; ++ total.stats.tx_errors += percpu_priv->stats.tx_errors; ++ total.stats.rx_errors += percpu_priv->stats.rx_errors; ++ total.l4_hxs_errors += percpu_priv->l4_hxs_errors; ++ count_total += dpa_bp_count; ++ ++ seq_printf(file, " %hu/%hu %8u %8lu %8lu %8u %8u" \ ++ " %8u %8lu %8lu %8u %8d\n", ++ get_hard_smp_processor_id(i), i, ++ percpu_priv->in_interrupt, ++ percpu_priv->stats.rx_packets, ++ percpu_priv->stats.tx_packets, ++ percpu_priv->tx_returned, ++ percpu_priv->tx_confirm, ++ percpu_priv->tx_frag_skbuffs, ++ percpu_priv->stats.tx_errors, ++ percpu_priv->stats.rx_errors, ++ percpu_priv->l4_hxs_errors, ++ dpa_bp_count); ++ } ++ seq_printf(file, "Total %8u %8lu %8lu %8u %8u %8u %8lu %8lu"\ ++ " %8u %8d\n", ++ total.in_interrupt, ++ total.stats.rx_packets, ++ total.stats.tx_packets, ++ total.tx_returned, ++ total.tx_confirm, ++ total.tx_frag_skbuffs, ++ total.stats.tx_errors, ++ total.stats.rx_errors, ++ total.l4_hxs_errors, ++ count_total); ++ ++ /* Congestion stats */ ++ seq_printf(file, "\nDevice congestion stats:\n"); ++ seq_printf(file, "Device has been congested for %d ms.\n", ++ jiffies_to_msecs(priv->cgr_data.congested_jiffies)); ++ ++ qman_query_cgr(&priv->cgr_data.cgr, &query_cgr); ++ seq_printf(file, "CGR id %d avg count: %llu\n", ++ priv->cgr_data.cgr.cgrid, qm_mcr_querycgr_a_get64(&query_cgr)); ++ seq_printf(file, "Device entered congestion %u times. " ++ "Current congestion state is: %s.\n", ++ priv->cgr_data.cgr_congested_count, ++ query_cgr.cgr.cs ? "congested" : "not congested"); ++ /* Reset congestion stats (like QMan CGR API does) */ ++ priv->cgr_data.congested_jiffies = 0; ++ priv->cgr_data.cgr_congested_count = 0; ++ ++ /* Rx Errors demultiplexing */ ++ seq_printf(file, "\nDPA RX Errors:\nCPU dma err phys err" \ ++ " size err hdr err csum err\n"); ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ total.rx_errors.dme += percpu_priv->rx_errors.dme; ++ total.rx_errors.fpe += percpu_priv->rx_errors.fpe; ++ total.rx_errors.fse += percpu_priv->rx_errors.fse; ++ total.rx_errors.phe += percpu_priv->rx_errors.phe; ++ total.rx_errors.cse += percpu_priv->rx_errors.cse; ++ ++ seq_printf(file, " %hu/%hu %8u %8u %8u" \ ++ " %8u %8u\n", ++ get_hard_smp_processor_id(i), i, ++ percpu_priv->rx_errors.dme, ++ percpu_priv->rx_errors.fpe, ++ percpu_priv->rx_errors.fse, ++ percpu_priv->rx_errors.phe, ++ percpu_priv->rx_errors.cse); ++ } ++ seq_printf(file, "Total %8u %8u %8u %8u %8u\n", ++ total.rx_errors.dme, ++ total.rx_errors.fpe, ++ total.rx_errors.fse, ++ total.rx_errors.phe, ++ total.rx_errors.cse); ++ ++ /* ERN demultiplexing */ ++ seq_printf(file, "\nDPA ERN counters:\n CPU cg_td wred " \ ++ "err_cond early_w late_w fq_td fq_ret" \ ++ " orp_z\n"); ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ total.ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop; ++ total.ern_cnt.wred += percpu_priv->ern_cnt.wred; ++ total.ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond; ++ total.ern_cnt.early_window += percpu_priv->ern_cnt.early_window; ++ total.ern_cnt.late_window += percpu_priv->ern_cnt.late_window; ++ total.ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop; ++ total.ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired; ++ total.ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero; ++ ++ seq_printf(file, " %hu/%hu %8u %8u %8u %8u %8u %8u" \ ++ " %8u %8u\n", ++ get_hard_smp_processor_id(i), i, ++ percpu_priv->ern_cnt.cg_tdrop, ++ percpu_priv->ern_cnt.wred, ++ percpu_priv->ern_cnt.err_cond, ++ percpu_priv->ern_cnt.early_window, ++ percpu_priv->ern_cnt.late_window, ++ percpu_priv->ern_cnt.fq_tdrop, ++ percpu_priv->ern_cnt.fq_retired, ++ percpu_priv->ern_cnt.orp_zero); ++ } ++ seq_printf(file, "Total %8u %8u %8u %8u %8u %8u %8u %8u\n", ++ total.ern_cnt.cg_tdrop, ++ total.ern_cnt.wred, ++ total.ern_cnt.err_cond, ++ total.ern_cnt.early_window, ++ total.ern_cnt.late_window, ++ total.ern_cnt.fq_tdrop, ++ total.ern_cnt.fq_retired, ++ total.ern_cnt.orp_zero); ++ ++ return 0; ++} ++ ++static int __cold dpa_debugfs_open(struct inode *inode, struct file *file) ++{ ++ int _errno; ++ const struct net_device *net_dev; ++ ++ _errno = single_open(file, dpa_debugfs_show, inode->i_private); ++ if (unlikely(_errno < 0)) { ++ net_dev = (struct net_device *)inode->i_private; ++ ++ if (netif_msg_drv((struct dpa_priv_s *)netdev_priv(net_dev))) ++ netdev_err(net_dev, "single_open() = %d\n", ++ _errno); ++ } ++ return _errno; ++} ++ ++static const struct file_operations dpa_debugfs_fops = { ++ .open = dpa_debugfs_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++ ++#ifdef CONFIG_DPAA_ETH_USE_NDO_SELECT_QUEUE ++static u16 dpa_select_queue(struct net_device *net_dev, struct sk_buff *skb) ++{ ++ return smp_processor_id(); ++} ++#endif ++ ++static const struct net_device_ops dpa_private_ops = { ++ .ndo_open = dpa_start, ++ .ndo_start_xmit = dpa_tx, ++ .ndo_stop = dpa_stop, ++ .ndo_tx_timeout = dpa_timeout, ++ .ndo_get_stats = dpa_get_stats, ++ .ndo_set_mac_address = dpa_set_mac_address, ++ .ndo_validate_addr = eth_validate_addr, ++#ifdef CONFIG_DPAA_ETH_USE_NDO_SELECT_QUEUE ++ .ndo_select_queue = dpa_select_queue, ++#endif ++ .ndo_change_mtu = dpa_change_mtu, ++ .ndo_set_rx_mode = dpa_set_rx_mode, ++ .ndo_init = dpa_ndo_init, ++#ifdef CONFIG_FSL_DPA_1588 ++ .ndo_do_ioctl = dpa_ioctl, ++#endif ++}; ++ ++static const struct net_device_ops dpa_shared_ops = { ++ .ndo_open = dpa_start, ++ .ndo_start_xmit = dpa_shared_tx, ++ .ndo_stop = dpa_stop, ++ .ndo_tx_timeout = dpa_timeout, ++ .ndo_get_stats = dpa_get_stats, ++ .ndo_set_mac_address = dpa_set_mac_address, ++ .ndo_validate_addr = eth_validate_addr, ++#ifdef CONFIG_DPAA_ETH_USE_NDO_SELECT_QUEUE ++ .ndo_select_queue = dpa_select_queue, ++#endif ++ .ndo_set_rx_mode = dpa_set_rx_mode, ++#ifdef CONFIG_FSL_DPA_1588 ++ .ndo_do_ioctl = dpa_ioctl, ++#endif ++}; ++ ++static u32 rx_pool_channel; ++static DEFINE_SPINLOCK(rx_pool_channel_init); ++ ++static int __devinit dpa_get_channel(struct device *dev, ++ struct device_node *dpa_node) ++{ ++ spin_lock(&rx_pool_channel_init); ++ if (!rx_pool_channel) { ++ u32 pool; ++ int ret = qman_alloc_pool(&pool); ++ if (!ret) ++ rx_pool_channel = pool; ++ } ++ spin_unlock(&rx_pool_channel_init); ++ if (!rx_pool_channel) ++ return -ENOMEM; ++ return rx_pool_channel; ++} ++ ++struct fqid_cell { ++ uint32_t start; ++ uint32_t count; ++}; ++ ++static const struct fqid_cell default_fqids[][3] __devinitconst = { ++ [RX] = { {0, 1}, {0, 1}, {0, DPAA_ETH_RX_QUEUES} }, ++ [TX] = { {0, 1}, {0, 1}, {0, DPAA_ETH_TX_QUEUES} } ++}; ++ ++static const struct fqid_cell tx_confirm_fqids[] __devinitconst = { ++ {0, DPAA_ETH_TX_QUEUES} ++}; ++ ++#ifdef CONFIG_DPA_TX_RECYCLE ++static const struct fqid_cell tx_recycle_fqids[] = { ++ {0, DPAA_ETH_TX_QUEUES} ++}; ++#endif ++ ++static int __devinit ++dpa_fq_probe(struct platform_device *_of_dev, struct list_head *list, ++ struct dpa_fq **defq, struct dpa_fq **errq, ++ struct dpa_fq **fqs, struct dpa_fq **txconfq, ++ struct dpa_fq **txrecycle, int ptype) ++{ ++ struct device *dev = &_of_dev->dev; ++ struct device_node *np = dev->of_node; ++ const struct fqid_cell *fqids; ++ int i, j, lenp; ++ int num_fqids; ++ struct dpa_fq *dpa_fq; ++ int err = 0; ++ ++ /* per-core tx confirmation queues */ ++ if (txconfq) { ++ fqids = tx_confirm_fqids; ++ dpa_fq = devm_kzalloc(dev, sizeof(*dpa_fq) * fqids[0].count, ++ GFP_KERNEL); ++ if (dpa_fq == NULL) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ return -ENOMEM; ++ } ++ *txconfq = dpa_fq; ++ for (j = 0; j < fqids[0].count; j++) ++ dpa_fq[j].fq_type = FQ_TYPE_TX_CONFIRM; ++ ++ for (j = 0; j < fqids[0].count; j++) { ++ dpa_fq[j].fqid = fqids[0].start ? ++ fqids[0].start + j : 0; ++ _dpa_assign_wq(dpa_fq + j); ++ list_add_tail(&dpa_fq[j].list, list); ++ } ++ } ++ ++#ifdef CONFIG_DPA_TX_RECYCLE ++ /* per-core tx queues for recycleable frames (FManv3 only) */ ++ if (txrecycle) { ++ fqids = tx_recycle_fqids; ++ dpa_fq = devm_kzalloc(dev, sizeof(*dpa_fq) * fqids[0].count, ++ GFP_KERNEL); ++ if (dpa_fq == NULL) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ return -ENOMEM; ++ } ++ ++ *txrecycle = dpa_fq; ++ for (j = 0; j < fqids[0].count; j++) ++ dpa_fq[j].fq_type = FQ_TYPE_TX_RECYCLE; ++ ++ for (j = 0; j < fqids[0].count; j++) { ++ dpa_fq[j].fqid = fqids[0].start ? ++ fqids[0].start + j : 0; ++ _dpa_assign_wq(dpa_fq + j); ++ list_add_tail(&dpa_fq[j].list, list); ++ } ++ } ++#endif ++ ++ fqids = of_get_property(np, fsl_qman_frame_queues[ptype], &lenp); ++ if (fqids == NULL) { ++ fqids = default_fqids[ptype]; ++ num_fqids = 3; ++ } else ++ num_fqids = lenp / sizeof(*fqids); ++ ++ for (i = 0; i < num_fqids; i++) { ++ dpa_fq = devm_kzalloc(dev, sizeof(*dpa_fq) * fqids[i].count, ++ GFP_KERNEL); ++ if (dpa_fq == NULL) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ return -ENOMEM; ++ } ++ ++ /* The first queue is the Error queue */ ++ if (i == 0 && errq) { ++ *errq = dpa_fq; ++ ++ if (fqids[i].count != 1) { ++ dev_err(dev, "Too many error queues!\n"); ++ err = -EINVAL; ++ goto invalid_error_queues; ++ } ++ ++ dpa_fq[0].fq_type = (ptype == RX ? ++ FQ_TYPE_RX_ERROR : FQ_TYPE_TX_ERROR); ++ } ++ ++ /* The second queue is the the Default queue */ ++ if (i == 1 && defq) { ++ *defq = dpa_fq; ++ ++ if (fqids[i].count != 1) { ++ dev_err(dev, "Too many default queues!\n"); ++ err = -EINVAL; ++ goto invalid_default_queues; ++ } ++ ++ dpa_fq[0].fq_type = (ptype == RX ? ++ FQ_TYPE_RX_DEFAULT : FQ_TYPE_TX_CONFIRM); ++ } ++ ++ /* ++ * All subsequent queues are gathered together. ++ * The first 8 will be used by the private linux interface ++ * if these are TX queues ++ */ ++ if (i == 2 || (!errq && i == 0 && fqs)) { ++ *fqs = dpa_fq; ++ ++ for (j = 0; j < fqids[i].count; j++) ++ dpa_fq[j].fq_type = (ptype == RX ? ++ FQ_TYPE_RX_PCD : FQ_TYPE_TX); ++ } ++ ++#warning We lost the 8-queue enforcement ++ ++ for (j = 0; j < fqids[i].count; j++) { ++ dpa_fq[j].fqid = fqids[i].start ? ++ fqids[i].start + j : 0; ++ _dpa_assign_wq(dpa_fq + j); ++ list_add_tail(&dpa_fq[j].list, list); ++ } ++ } ++ ++invalid_default_queues: ++invalid_error_queues: ++ return err; ++} ++ ++static void dpa_setup_ingress(struct dpa_priv_s *priv, struct dpa_fq *fq, ++ const struct qman_fq *template) ++{ ++ fq->fq_base = *template; ++ fq->net_dev = priv->net_dev; ++ ++ fq->flags = QMAN_FQ_FLAG_NO_ENQUEUE; ++ fq->channel = priv->channel; ++} ++ ++static void dpa_setup_egress(struct dpa_priv_s *priv, ++ struct list_head *head, struct dpa_fq *fq, ++ struct fm_port *port) ++{ ++ struct list_head *ptr = &fq->list; ++ int i = 0; ++ ++ while (true) { ++ struct dpa_fq *iter = list_entry(ptr, struct dpa_fq, list); ++ if (priv->shared) ++ iter->fq_base = shared_egress_fq; ++ else ++ iter->fq_base = private_egress_fq; ++ ++ iter->net_dev = priv->net_dev; ++ priv->egress_fqs[i++] = &iter->fq_base; ++ ++ if (port) { ++ iter->flags = QMAN_FQ_FLAG_TO_DCPORTAL; ++ iter->channel = fm_get_tx_port_channel(port); ++ } else ++ iter->flags = QMAN_FQ_FLAG_NO_MODIFY; ++ ++ if (list_is_last(ptr, head)) ++ break; ++ ++ ptr = ptr->next; ++ } ++} ++ ++#ifdef CONFIG_DPA_TX_RECYCLE ++static void dpa_setup_recycle_queues(struct dpa_priv_s *priv, struct dpa_fq *fq, ++ struct fm_port *port) ++{ ++ int i = 0; ++ struct list_head *ptr = &fq->list; ++ ++ for (i = 0; i < DPAA_ETH_TX_QUEUES; i++) { ++ struct dpa_fq *iter = list_entry(ptr, struct dpa_fq, list); ++ ++ iter->fq_base = private_egress_fq; ++ iter->net_dev = priv->net_dev; ++ ++ priv->recycle_fqs[i] = &iter->fq_base; ++ ++ iter->flags = QMAN_FQ_FLAG_TO_DCPORTAL; ++ iter->channel = fm_get_tx_port_channel(port); ++ ++ ptr = ptr->next; ++ } ++} ++#endif ++ ++static void dpa_setup_conf_queues(struct dpa_priv_s *priv, struct dpa_fq *fq) ++{ ++ struct list_head *ptr = &fq->list; ++ int i; ++ ++ /* ++ * Configure the queues to be core affine. ++ * The implicit assumption here is that each cpu has its own Tx queue ++ */ ++ for (i = 0; i < DPAA_ETH_TX_QUEUES; i++) { ++ struct dpa_fq *iter = list_entry(ptr, struct dpa_fq, list); ++ ++ dpa_setup_ingress(priv, iter, &tx_private_defq); ++ /* Leave the confirmation queue in the default pool channel */ ++ priv->conf_fqs[i] = &iter->fq_base; ++ ++ ptr = ptr->next; ++ } ++} ++ ++static void dpa_setup_ingress_queues(struct dpa_priv_s *priv, ++ struct list_head *head, struct dpa_fq *fq) ++{ ++ struct list_head *ptr = &fq->list; ++ u32 fqid; ++ int portals[NR_CPUS]; ++ int i, cpu, num_portals = 0; ++ const cpumask_t *affine_cpus = qman_affine_cpus(); ++ ++ for_each_cpu(cpu, affine_cpus) ++ portals[num_portals++] = qman_affine_channel(cpu); ++ if (num_portals == 0) { ++ dev_err(fq->net_dev->dev.parent, ++ "No Qman software (affine) channels found"); ++ return; ++ } ++ ++ i = 0; ++ fqid = 0; ++ if (priv->mac_dev) ++ fqid = (priv->mac_dev->res->start & 0x1fffff) >> 6; ++ ++ while (true) { ++ struct dpa_fq *iter = list_entry(ptr, struct dpa_fq, list); ++ ++ if (priv->shared) ++ dpa_setup_ingress(priv, iter, &rx_shared_fq); ++ else ++ dpa_setup_ingress(priv, iter, &rx_private_defq); ++ ++ if (!iter->fqid) ++ iter->fqid = fqid++; ++ ++ /* Assign the queues to a channel in a round-robin fashion */ ++ iter->channel = portals[i]; ++ i = (i + 1) % num_portals; ++ ++ if (list_is_last(ptr, head)) ++ break; ++ ++ ptr = ptr->next; ++ } ++} ++ ++static void __devinit ++dpaa_eth_init_tx_port(struct fm_port *port, struct dpa_fq *errq, ++ struct dpa_fq *defq, bool has_timer) ++{ ++ struct fm_port_params tx_port_param; ++ ++ dpaa_eth_init_port(tx, port, tx_port_param, errq->fqid, defq->fqid, ++ DPA_TX_PRIV_DATA_SIZE, has_timer); ++} ++ ++static void __devinit ++dpaa_eth_init_rx_port(struct fm_port *port, struct dpa_bp *bp, size_t count, ++ struct dpa_fq *errq, struct dpa_fq *defq, bool has_timer) ++{ ++ struct fm_port_params rx_port_param; ++ int i; ++ ++ count = min(ARRAY_SIZE(rx_port_param.pool_param), count); ++ rx_port_param.num_pools = count; ++ for (i = 0; i < count; i++) { ++ if (i >= rx_port_param.num_pools) ++ break; ++ ++ rx_port_param.pool_param[i].id = bp[i].bpid; ++ rx_port_param.pool_param[i].size = bp[i].size; ++ } ++ ++ dpaa_eth_init_port(rx, port, rx_port_param, errq->fqid, defq->fqid, ++ DPA_RX_PRIV_DATA_SIZE, has_timer); ++} ++ ++static void dpa_rx_fq_init(struct dpa_priv_s *priv, struct list_head *head, ++ struct dpa_fq *defq, struct dpa_fq *errq, ++ struct dpa_fq *fqs) ++{ ++ if (fqs) ++ dpa_setup_ingress_queues(priv, head, fqs); ++ ++ /* Only real devices need default/error queues set up */ ++ if (!priv->mac_dev) ++ return; ++ ++ if (defq->fqid == 0 && netif_msg_probe(priv)) ++ pr_info("Using dynamic RX QM frame queues\n"); ++ ++ if (priv->shared) { ++ dpa_setup_ingress(priv, defq, &rx_shared_fq); ++ dpa_setup_ingress(priv, errq, &rx_shared_fq); ++ } else { ++ dpa_setup_ingress(priv, defq, &rx_private_defq); ++ dpa_setup_ingress(priv, errq, &rx_private_errq); ++ } ++} ++ ++static void dpa_tx_fq_init(struct dpa_priv_s *priv, struct list_head *head, ++ struct dpa_fq *defq, struct dpa_fq *errq, ++ struct dpa_fq *fqs, struct dpa_fq *confqs, ++ struct dpa_fq *recyclefqs, struct fm_port *port) ++{ ++ if (fqs) ++ dpa_setup_egress(priv, head, fqs, port); ++ ++ /* Only real devices need default/error queues set up */ ++ if (!priv->mac_dev) ++ return; ++ ++ if (defq->fqid == 0 && netif_msg_probe(priv)) ++ pr_info("Using dynamic TX QM frame queues\n"); ++ ++ /* The shared driver doesn't use tx confirmation */ ++ if (priv->shared) { ++ dpa_setup_ingress(priv, defq, &tx_shared_defq); ++ dpa_setup_ingress(priv, errq, &tx_shared_errq); ++ } else { ++ dpa_setup_ingress(priv, defq, &tx_private_defq); ++ dpa_setup_ingress(priv, errq, &tx_private_errq); ++ if (confqs) ++ dpa_setup_conf_queues(priv, confqs); ++#ifdef CONFIG_DPA_TX_RECYCLE ++ if (recyclefqs) ++ dpa_setup_recycle_queues(priv, recyclefqs, port); ++#endif ++ ++ } ++} ++ ++static int dpa_netdev_init(struct device_node *dpa_node, ++ struct net_device *net_dev) ++{ ++ int err; ++ const uint8_t *mac_addr; ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct device *dev = net_dev->dev.parent; ++ ++ net_dev->features |= DPA_NETIF_FEATURES; ++ net_dev->vlan_features |= DPA_NETIF_FEATURES; ++ ++ if (!priv->mac_dev) { ++ /* Get the MAC address */ ++ mac_addr = of_get_mac_address(dpa_node); ++ if (mac_addr == NULL) { ++ if (netif_msg_probe(priv)) ++ dev_err(dev, "No MAC address found!\n"); ++ return -EINVAL; ++ } ++ } else { ++ net_dev->mem_start = priv->mac_dev->res->start; ++ net_dev->mem_end = priv->mac_dev->res->end; ++ ++ mac_addr = priv->mac_dev->addr; ++ net_dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); ++ net_dev->vlan_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); ++ ++ /* ++ * Advertise S/G and HIGHDMA support for MAC-ful, ++ * private interfaces ++ */ ++ if (!priv->shared) { ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ net_dev->features |= NETIF_F_SG | NETIF_F_HIGHDMA ++ /* ++ * Recent kernels enable GSO automatically, if ++ * we declare NETIF_F_SG. For conformity, we'll ++ * still declare GSO explicitly. ++ */ ++ | NETIF_F_GSO; ++ net_dev->vlan_features |= NETIF_F_SG | NETIF_F_HIGHDMA ++ | NETIF_F_GSO; ++#endif ++ /* Advertise GRO support */ ++ net_dev->features |= NETIF_F_GRO; ++ net_dev->vlan_features |= NETIF_F_GRO; ++ } ++ } ++ ++ memcpy(net_dev->perm_addr, mac_addr, net_dev->addr_len); ++ memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len); ++ ++ SET_ETHTOOL_OPS(net_dev, &dpa_ethtool_ops); ++ net_dev->needed_headroom = DPA_BP_HEAD; ++ net_dev->watchdog_timeo = msecs_to_jiffies(tx_timeout); ++ ++ err = register_netdev(net_dev); ++ if (err < 0) { ++ dev_err(dev, "register_netdev() = %d\n", err); ++ return err; ++ } ++ ++#ifdef CONFIG_DEBUG_FS ++ priv->debugfs_file = debugfs_create_file(net_dev->name, S_IRUGO, ++ dpa_debugfs_root, net_dev, ++ &dpa_debugfs_fops); ++ if (unlikely(priv->debugfs_file == NULL)) { ++ netdev_err(net_dev, "debugfs_create_file(%s/%s/%s) = %d\n", ++ powerpc_debugfs_root->d_iname, ++ dpa_debugfs_root->d_iname, ++ net_dev->name, err); ++ ++ unregister_netdev(net_dev); ++ return -ENOMEM; ++ } ++#endif ++ ++ return 0; ++} ++ ++static int dpa_shared_netdev_init(struct device_node *dpa_node, ++ struct net_device *net_dev) ++{ ++ net_dev->netdev_ops = &dpa_shared_ops; ++ ++ return dpa_netdev_init(dpa_node, net_dev); ++} ++ ++static int dpa_private_netdev_init(struct device_node *dpa_node, ++ struct net_device *net_dev) ++{ ++ int i; ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct dpa_percpu_priv_s *percpu_priv; ++ ++ /* ++ * Although we access another CPU's private data here ++ * we do it at initialization so it is safe ++ */ ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ percpu_priv->net_dev = net_dev; ++ ++ percpu_priv->dpa_bp = priv->dpa_bp; ++ percpu_priv->dpa_bp_count = ++ per_cpu_ptr(priv->dpa_bp->percpu_count, i); ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ /* init the percpu list and add some skbs */ ++ skb_queue_head_init(&percpu_priv->skb_list); ++ ++ dpa_list_add_skbs(percpu_priv, DEFAULT_SKB_COUNT); ++#endif ++ netif_napi_add(net_dev, &percpu_priv->napi, dpaa_eth_poll, ++ DPA_NAPI_WEIGHT); ++ } ++ ++ net_dev->netdev_ops = &dpa_private_ops; ++ ++ return dpa_netdev_init(dpa_node, net_dev); ++} ++ ++int dpa_alloc_pcd_fqids(struct device *dev, uint32_t num, ++ uint8_t alignment, uint32_t *base_fqid) ++{ ++ dev_crit(dev, "callback not implemented!\n"); ++ BUG(); ++ ++ return 0; ++} ++ ++int dpa_free_pcd_fqids(struct device *dev, uint32_t base_fqid) ++{ ++ ++ dev_crit(dev, "callback not implemented!\n"); ++ BUG(); ++ ++ return 0; ++} ++ ++static int dpaa_eth_add_channel(void *__arg) ++{ ++ const cpumask_t *cpus = qman_affine_cpus(); ++ u32 pool = QM_SDQCR_CHANNELS_POOL_CONV((u32)(unsigned long)__arg); ++ int cpu; ++ ++ for_each_cpu(cpu, cpus) { ++ set_cpus_allowed_ptr(current, get_cpu_mask(cpu)); ++ qman_static_dequeue_add(pool); ++ } ++ return 0; ++} ++ ++static int dpaa_eth_cgr_init(struct dpa_priv_s *priv) ++{ ++ struct qm_mcc_initcgr initcgr; ++ u32 cs_th; ++ int err; ++ ++ err = qman_alloc_cgrid(&priv->cgr_data.cgr.cgrid); ++ if (err < 0) { ++ pr_err("Error %d allocating CGR ID\n", err); ++ goto out_error; ++ } ++ priv->cgr_data.cgr.cb = dpaa_eth_cgscn; ++ ++ /* Enable Congestion State Change Notifications and CS taildrop */ ++ initcgr.we_mask = QM_CGR_WE_CSCN_EN | QM_CGR_WE_CS_THRES; ++ initcgr.cgr.cscn_en = QM_CGR_EN; ++ /* ++ * Set different thresholds based on the MAC speed. ++ * TODO: this may turn suboptimal if the MAC is reconfigured at a speed ++ * lower than its max, e.g. if a dTSEC later negotiates a 100Mbps link. ++ * In such cases, we ought to reconfigure the threshold, too. ++ */ ++ if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full) ++ cs_th = DPA_CS_THRESHOLD_10G; ++ else ++ cs_th = DPA_CS_THRESHOLD_1G; ++ qm_cgr_cs_thres_set64(&initcgr.cgr.cs_thres, cs_th, 1); ++ ++ initcgr.we_mask |= QM_CGR_WE_CSTD_EN; ++ initcgr.cgr.cstd_en = QM_CGR_EN; ++ ++ err = qman_create_cgr(&priv->cgr_data.cgr, QMAN_CGR_FLAG_USE_INIT, ++ &initcgr); ++ if (err < 0) { ++ pr_err("Error %d creating CGR with ID %d\n", err, ++ priv->cgr_data.cgr.cgrid); ++ qman_release_cgrid(priv->cgr_data.cgr.cgrid); ++ goto out_error; ++ } ++ pr_debug("Created CGR %d for netdev with hwaddr %pM on " ++ "QMan channel %d\n", priv->cgr_data.cgr.cgrid, ++ priv->mac_dev->addr, priv->cgr_data.cgr.chan); ++ ++out_error: ++ return err; ++} ++ ++static const struct of_device_id dpa_match[] __devinitconst ; ++static int __devinit ++dpaa_eth_probe(struct platform_device *_of_dev) ++{ ++ int err, i; ++ struct device *dev; ++ struct device_node *dpa_node; ++ struct dpa_bp *dpa_bp; ++ struct dpa_fq *dpa_fq, *tmp; ++ struct list_head rxfqlist; ++ struct list_head txfqlist; ++ size_t count; ++ struct net_device *net_dev = NULL; ++ struct dpa_priv_s *priv = NULL; ++ struct dpa_fq *rxdefault = NULL; ++ struct dpa_fq *txdefault = NULL; ++ struct dpa_fq *rxerror = NULL; ++ struct dpa_fq *txerror = NULL; ++ struct dpa_fq *rxextra = NULL; ++ struct dpa_fq *txfqs = NULL; ++ struct dpa_fq *txconf = NULL; ++ struct dpa_fq *txrecycle = NULL; ++ struct fm_port *rxport = NULL; ++ struct fm_port *txport = NULL; ++ bool has_timer = FALSE; ++ bool is_shared = false; ++ struct mac_device *mac_dev; ++ int proxy_enet; ++ const struct of_device_id *match; ++ ++ dev = &_of_dev->dev; ++ ++ dpa_node = dev->of_node; ++ ++ match = of_match_device(dpa_match, dev); ++ if (!match) ++ return -EINVAL; ++ ++ if (!of_device_is_available(dpa_node)) ++ return -ENODEV; ++ ++ /* ++ * If it's not an fsl,dpa-ethernet node, we just serve as a proxy ++ * initializer driver, and don't do any linux device setup ++ */ ++ proxy_enet = strcmp(match->compatible, "fsl,dpa-ethernet"); ++ ++ /* ++ * Allocate this early, so we can store relevant information in ++ * the private area ++ */ ++ if (!proxy_enet) { ++ net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TX_QUEUES); ++ if (!net_dev) { ++ dev_err(dev, "alloc_etherdev_mq() failed\n"); ++ return -ENOMEM; ++ } ++ ++ /* Do this here, so we can be verbose early */ ++ SET_NETDEV_DEV(net_dev, dev); ++ dev_set_drvdata(dev, net_dev); ++ ++ priv = netdev_priv(net_dev); ++ priv->net_dev = net_dev; ++ ++ priv->msg_enable = netif_msg_init(debug, -1); ++ } ++ ++ /* Get the buffer pools assigned to this interface */ ++ dpa_bp = dpa_bp_probe(_of_dev, &count); ++ if (IS_ERR(dpa_bp)) { ++ err = PTR_ERR(dpa_bp); ++ goto bp_probe_failed; ++ } ++ if (!dpa_bp->kernel_pool) ++ is_shared = true; ++ ++ mac_dev = dpa_mac_probe(_of_dev); ++ if (IS_ERR(mac_dev)) { ++ err = PTR_ERR(mac_dev); ++ goto mac_probe_failed; ++ } else if (mac_dev) { ++ rxport = mac_dev->port_dev[RX]; ++ txport = mac_dev->port_dev[TX]; ++ } ++ ++ INIT_LIST_HEAD(&rxfqlist); ++ INIT_LIST_HEAD(&txfqlist); ++ ++ if (rxport) ++ err = dpa_fq_probe(_of_dev, &rxfqlist, &rxdefault, &rxerror, ++ &rxextra, NULL, NULL, RX); ++ else ++ err = dpa_fq_probe(_of_dev, &rxfqlist, NULL, NULL, ++ &rxextra, NULL, NULL, RX); ++ ++ if (err < 0) ++ goto rx_fq_probe_failed; ++ ++ if (txport) ++#ifdef CONFIG_DPA_TX_RECYCLE ++ err = dpa_fq_probe(_of_dev, &txfqlist, &txdefault, &txerror, ++ &txfqs, (is_shared ? NULL : &txconf), ++ (is_shared ? NULL : &txrecycle), TX); ++#else ++ err = dpa_fq_probe(_of_dev, &txfqlist, &txdefault, &txerror, ++ &txfqs, (is_shared ? NULL : &txconf), NULL, TX); ++#endif ++ else ++ err = dpa_fq_probe(_of_dev, &txfqlist, NULL, NULL, &txfqs, ++ NULL, NULL, TX); ++ ++ if (err < 0) ++ goto tx_fq_probe_failed; ++ ++ /* ++ * Now we have all of the configuration information. ++ * We support a number of configurations: ++ * 1) Private interface - An optimized linux ethernet driver with ++ * a real network connection. ++ * 2) Shared interface - A device intended for virtual connections ++ * or for a real interface that is shared between partitions ++ * 3) Proxy initializer - Just configures the MAC on behalf of ++ * another partition ++ */ ++ ++ /* bp init */ ++ if (net_dev) { ++ struct task_struct *kth; ++ ++ err = dpa_bp_create(net_dev, dpa_bp, count); ++ ++ if (err < 0) ++ goto bp_create_failed; ++ ++ priv->mac_dev = mac_dev; ++ ++ priv->channel = dpa_get_channel(dev, dpa_node); ++ ++ if (priv->channel < 0) { ++ err = priv->channel; ++ goto get_channel_failed; ++ } ++ ++ /* Start a thread that will walk the cpus with affine portals ++ * and add this pool channel to each's dequeue mask. */ ++ kth = kthread_run(dpaa_eth_add_channel, ++ (void *)(unsigned long)priv->channel, ++ "dpaa_%p:%d", net_dev, priv->channel); ++ if (!kth) { ++ err = -ENOMEM; ++ goto add_channel_failed; ++ } ++ ++ dpa_rx_fq_init(priv, &rxfqlist, rxdefault, rxerror, rxextra); ++ dpa_tx_fq_init(priv, &txfqlist, txdefault, txerror, txfqs, ++ txconf, txrecycle, txport); ++ ++ /* ++ * Create a congestion group for this netdev, with ++ * dynamically-allocated CGR ID. ++ * Must be executed after probing the MAC, but before ++ * assigning the egress FQs to the CGRs. ++ * Don't create a congestion group for MAC-less interfaces. ++ */ ++ if (priv->mac_dev) { ++ err = dpaa_eth_cgr_init(priv); ++ if (err < 0) { ++ dev_err(dev, "Error initializing CGR\n"); ++ goto cgr_init_failed; ++ } ++ } ++ ++ /* Add the FQs to the interface, and make them active */ ++ INIT_LIST_HEAD(&priv->dpa_fq_list); ++ ++ list_for_each_entry_safe(dpa_fq, tmp, &rxfqlist, list) { ++ err = _dpa_fq_alloc(&priv->dpa_fq_list, dpa_fq); ++ if (err < 0) ++ goto fq_alloc_failed; ++ } ++ ++ list_for_each_entry_safe(dpa_fq, tmp, &txfqlist, list) { ++ err = _dpa_fq_alloc(&priv->dpa_fq_list, dpa_fq); ++ if (err < 0) ++ goto fq_alloc_failed; ++ } ++ ++ if (priv->tsu && priv->tsu->valid) ++ has_timer = TRUE; ++ } ++ ++ /* All real interfaces need their ports initialized */ ++ if (mac_dev) { ++ struct fm_port_pcd_param rx_port_pcd_param; ++ ++ dpaa_eth_init_rx_port(rxport, dpa_bp, count, rxerror, ++ rxdefault, has_timer); ++ dpaa_eth_init_tx_port(txport, txerror, txdefault, has_timer); ++ ++ rx_port_pcd_param.cba = dpa_alloc_pcd_fqids; ++ rx_port_pcd_param.cbf = dpa_free_pcd_fqids; ++ rx_port_pcd_param.dev = dev; ++ fm_port_pcd_bind(rxport, &rx_port_pcd_param); ++ } ++ ++ /* ++ * Proxy interfaces need to be started, and the allocated ++ * memory freed ++ */ ++ if (!net_dev) { ++ devm_kfree(&_of_dev->dev, dpa_bp); ++ devm_kfree(&_of_dev->dev, rxdefault); ++ devm_kfree(&_of_dev->dev, rxerror); ++ devm_kfree(&_of_dev->dev, txdefault); ++ devm_kfree(&_of_dev->dev, txerror); ++ ++ if (mac_dev) ++ for_each_port_device(i, mac_dev->port_dev) ++ fm_port_enable(mac_dev->port_dev[i]); ++ ++ return 0; ++ } ++ ++ /* Now we need to initialize either a private or shared interface */ ++ priv->percpu_priv = __alloc_percpu(sizeof(*priv->percpu_priv), ++ __alignof__(*priv->percpu_priv)); ++ if (priv->percpu_priv == NULL) { ++ dev_err(dev, "__alloc_percpu() failed\n"); ++ err = -ENOMEM; ++ goto alloc_percpu_failed; ++ } ++ ++ if (priv->shared) ++ err = dpa_shared_netdev_init(dpa_node, net_dev); ++ else ++ err = dpa_private_netdev_init(dpa_node, net_dev); ++ ++ if (err < 0) ++ goto netdev_init_failed; ++ ++ dpaa_eth_sysfs_init(&net_dev->dev); ++ ++#ifdef CONFIG_DPAA_ETH_UNIT_TESTS ++ /* The unit test is designed to test private interfaces */ ++ if (!priv->shared && !tx_unit_test_ran) { ++ err = dpa_tx_unit_test(net_dev); ++ ++ WARN_ON(err); ++ } ++#endif ++ ++ return 0; ++ ++netdev_init_failed: ++ if (net_dev) ++ free_percpu(priv->percpu_priv); ++alloc_percpu_failed: ++fq_alloc_failed: ++ if (net_dev) { ++ dpa_fq_free(dev, &priv->dpa_fq_list); ++ qman_release_cgrid(priv->cgr_data.cgr.cgrid); ++ qman_delete_cgr(&priv->cgr_data.cgr); ++ } ++cgr_init_failed: ++add_channel_failed: ++get_channel_failed: ++ if (net_dev) ++ dpa_bp_free(priv, priv->dpa_bp); ++bp_create_failed: ++tx_fq_probe_failed: ++rx_fq_probe_failed: ++mac_probe_failed: ++bp_probe_failed: ++ dev_set_drvdata(dev, NULL); ++ if (net_dev) ++ free_netdev(net_dev); ++ ++ return err; ++} ++ ++static const struct of_device_id dpa_match[] __devinitconst = { ++ { ++ .compatible = "fsl,dpa-ethernet" ++ }, ++ { ++ .compatible = "fsl,dpa-ethernet-init" ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, dpa_match); ++ ++static int __devexit __cold dpa_remove(struct platform_device *of_dev) ++{ ++ int err; ++ struct device *dev; ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ ++ dev = &of_dev->dev; ++ net_dev = dev_get_drvdata(dev); ++ priv = netdev_priv(net_dev); ++ ++ dpaa_eth_sysfs_remove(dev); ++ ++ dev_set_drvdata(dev, NULL); ++ unregister_netdev(net_dev); ++ ++ err = dpa_fq_free(dev, &priv->dpa_fq_list); ++ ++ free_percpu(priv->percpu_priv); ++ ++ dpa_bp_free(priv, priv->dpa_bp); ++ ++#ifdef CONFIG_DEBUG_FS ++ debugfs_remove(priv->debugfs_file); ++#endif ++ ++#ifdef CONFIG_FSL_DPA_1588 ++ if (priv->tsu && priv->tsu->valid) ++ dpa_ptp_cleanup(priv); ++#endif ++ ++ free_netdev(net_dev); ++ ++ return err; ++} ++ ++static struct platform_driver dpa_driver = { ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .of_match_table = dpa_match, ++ .owner = THIS_MODULE, ++ }, ++ .probe = dpaa_eth_probe, ++ .remove = __devexit_p(dpa_remove) ++}; ++ ++static int __init __cold dpa_load(void) ++{ ++ int _errno; ++ ++ pr_info(KBUILD_MODNAME ": " DPA_DESCRIPTION " (" VERSION ")\n"); ++ ++ /* initialise dpaa_eth mirror values */ ++ dpa_rx_extra_headroom = fm_get_rx_extra_headroom(); ++ dpa_max_frm = fm_get_max_frm(); ++ ++#ifdef CONFIG_DEBUG_FS ++ dpa_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, ++ powerpc_debugfs_root); ++ if (unlikely(dpa_debugfs_root == NULL)) { ++ _errno = -ENOMEM; ++ pr_err(KBUILD_MODNAME ": %s:%hu:%s(): " ++ "debugfs_create_dir(%s/"KBUILD_MODNAME") = %d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, ++ powerpc_debugfs_root->d_iname, _errno); ++ goto _return; ++ } ++#endif ++ ++ _errno = platform_driver_register(&dpa_driver); ++ if (unlikely(_errno < 0)) { ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): platform_driver_register() = %d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, _errno); ++ goto _return_debugfs_remove; ++ } ++ ++ goto _return; ++ ++_return_debugfs_remove: ++#ifdef CONFIG_DEBUG_FS ++ debugfs_remove(dpa_debugfs_root); ++#endif ++_return: ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ return _errno; ++} ++module_init(dpa_load); ++ ++static void __exit __cold dpa_unload(void) ++{ ++ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ platform_driver_unregister(&dpa_driver); ++ ++#ifdef CONFIG_DEBUG_FS ++ debugfs_remove(dpa_debugfs_root); ++#endif ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++} ++module_exit(dpa_unload); +diff --git a/drivers/net/dpa/dpaa_eth.h b/drivers/net/dpa/dpaa_eth.h +new file mode 100644 +index 0000000..d33696f +--- /dev/null ++++ b/drivers/net/dpa/dpaa_eth.h +@@ -0,0 +1,604 @@ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __DPA_H ++#define __DPA_H ++ ++#include /* struct ethtool_ops */ ++#include ++#include /* struct list_head */ ++#include /* struct work_struct */ ++#include ++#include ++#include /* vlan_eth_hdr */ ++#include /* ip_hdr */ ++#include /* ipv6_hdr */ ++#ifdef CONFIG_DEBUG_FS ++#include /* struct dentry */ ++#endif ++ ++#include /* struct qman_fq */ ++ ++#include "dpaa_eth-common.h" ++ ++#include "fsl_fman.h" ++#include "fm_ext.h" ++#include "fm_port_ext.h" /* FM_PORT_FRM_ERR_* */ ++ ++#include "mac.h" /* struct mac_device */ ++ ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++#define dpa_get_rx_extra_headroom() fm_get_rx_extra_headroom() ++#else ++#define dpa_get_rx_extra_headroom() dpa_rx_extra_headroom ++#endif ++#define dpa_get_max_frm() dpa_max_frm ++ ++/* ++ * Currently we have the same max_frm on all interfaces, so these macros ++ * don't get a net_device argument. This will change in the future. ++ */ ++#define dpa_get_min_mtu() 64 ++#define dpa_get_max_mtu() \ ++ (dpa_get_max_frm() - (VLAN_ETH_HLEN + ETH_FCS_LEN)) ++ ++#define DPA_RX_PRIV_DATA_SIZE (DPA_TX_PRIV_DATA_SIZE + \ ++ dpa_get_rx_extra_headroom()) ++/* number of Tx queues to FMan */ ++#define DPAA_ETH_TX_QUEUES NR_CPUS ++#define DPAA_ETH_RX_QUEUES 128 ++ ++#if defined(CONFIG_DPAA_FMAN_UNIT_TESTS) ++/*TODO: temporary for fman pcd testing */ ++#define FMAN_PCD_TESTS_MAX_NUM_RANGES 20 ++#endif ++ ++/* return codes for the dpaa-eth hooks */ ++enum dpaa_eth_hook_result { ++ /* fd/skb was retained by the hook. ++ * ++ * On the Rx path, this means the Ethernet driver will _not_ ++ * deliver the skb to the stack. Instead, the hook implementation ++ * is expected to properly dispose of the skb. ++ * ++ * On the Tx path, the Ethernet driver's dpa_tx() function will ++ * immediately return NETDEV_TX_OK. The hook implementation is expected ++ * to free the skb. *DO*NOT* release it to BMan, or enqueue it to FMan, ++ * unless you know exactly what you're doing! ++ * ++ * On the confirmation/error paths, the Ethernet driver will _not_ ++ * perform any fd cleanup, nor update the interface statistics. ++ */ ++ DPAA_ETH_STOLEN, ++ /* ++ * fd/skb was returned to the Ethernet driver for regular processing. ++ * The hook is not allowed to, for instance, reallocate the skb (as if ++ * by linearizing, copying, cloning or reallocating the headroom). ++ */ ++ DPAA_ETH_CONTINUE ++}; ++ ++typedef enum dpaa_eth_hook_result (*dpaa_eth_ingress_hook_t)( ++ struct sk_buff *skb, struct net_device *net_dev, u32 fqid); ++typedef enum dpaa_eth_hook_result (*dpaa_eth_egress_hook_t)( ++ struct sk_buff *skb, struct net_device *net_dev); ++typedef enum dpaa_eth_hook_result (*dpaa_eth_confirm_hook_t)( ++ struct net_device *net_dev, const struct qm_fd *fd, u32 fqid); ++ ++/* ++ * Various hooks used for unit-testing and/or fastpath optimizations. ++ * Currently only one set of such hooks is supported. ++ */ ++struct dpaa_eth_hooks_s { ++ /* ++ * Invoked on the Tx private path, immediately after receiving the skb ++ * from the stack. ++ */ ++ dpaa_eth_egress_hook_t tx; ++ ++ /* ++ * Invoked on the Rx private path, right before passing the skb ++ * up the stack. At that point, the packet's protocol id has already ++ * been set. The skb's data pointer is now at the L3 header, and ++ * skb->mac_header points to the L2 header. skb->len has been adjusted ++ * to be the length of L3+payload (i.e., the length of the ++ * original frame minus the L2 header len). ++ * For more details on what the skb looks like, see eth_type_trans(). ++ */ ++ dpaa_eth_ingress_hook_t rx_default; ++ ++ /* Driver hook for the Rx error private path. */ ++ dpaa_eth_confirm_hook_t rx_error; ++ /* Driver hook for the Tx confirmation private path. */ ++ dpaa_eth_confirm_hook_t tx_confirm; ++ /* Driver hook for the Tx error private path. */ ++ dpaa_eth_confirm_hook_t tx_error; ++}; ++ ++void fsl_dpaa_eth_set_hooks(struct dpaa_eth_hooks_s *hooks); ++ ++/* The netdevice's needed_headroom */ ++#define DPA_BP_HEAD (DPA_TX_PRIV_DATA_SIZE + DPA_PARSE_RESULTS_SIZE + \ ++ DPA_HASH_RESULTS_SIZE) ++#define DPA_BP_SIZE(s) (DPA_BP_HEAD + dpa_get_rx_extra_headroom() + (s)) ++ ++#define DPA_SGT_MAX_ENTRIES 16 /* maximum number of entries in SG Table */ ++ ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++#define DEFAULT_SKB_COUNT 64 /* maximum number of SKBs in each percpu list */ ++/* ++ * We may want this value configurable. Must be <= PAGE_SIZE ++ * A lower value may help with recycling rates, at least on forwarding ++ */ ++#define DEFAULT_BUF_SIZE PAGE_SIZE ++/* ++ * Default amount data to be copied from the beginning of a frame into the ++ * linear part of the skb, in case we aren't using the hardware parser. ++ */ ++#define DPA_COPIED_HEADERS_SIZE 128 ++ ++#else ++/* ++ * Default buffer size is based on L2 MAX_FRM value, minus the FCS which is ++ * stripped down by hardware. ++ */ ++#define DEFAULT_BUF_SIZE DPA_BP_SIZE(dpa_get_max_frm() - ETH_FCS_LEN) ++#endif /* CONFIG_DPAA_ETH_SG_SUPPORT */ ++ ++/* ++ * Largest value that the FQD's OAL field can hold. ++ * This is DPAA-1.x specific. ++ * TODO: This rather belongs in fsl_qman.h ++ */ ++#define FSL_QMAN_MAX_OAL 127 ++ ++/* ++ * Values for the L3R field of the FM Parse Results ++ */ ++/* L3 Type field: First IP Present IPv4 */ ++#define FM_L3_PARSE_RESULT_IPV4 0x8000 ++/* L3 Type field: First IP Present IPv6 */ ++#define FM_L3_PARSE_RESULT_IPV6 0x4000 ++ ++/* ++ * Values for the L4R field of the FM Parse Results ++ * See $8.8.4.7.20 - L4 HXS - L4 Results from DPAA-Rev2 Reference Manual. ++ */ ++/* L4 Type field: UDP */ ++#define FM_L4_PARSE_RESULT_UDP 0x40 ++/* L4 Type field: TCP */ ++#define FM_L4_PARSE_RESULT_TCP 0x20 ++/* ++ * This includes L4 checksum errors, but also other errors that the Hard Parser ++ * can detect, such as invalid combinations of TCP control flags, or bad UDP ++ * lengths. ++ */ ++#define FM_L4_PARSE_ERROR 0x10 ++/* Check if the hardware parser has run */ ++#define FM_L4_HXS_RUN 0xE0 ++ ++/* ++ * FD status field indicating whether the FM Parser has attempted to validate ++ * the L4 csum of the frame. ++ * Note that having this bit set doesn't necessarily imply that the checksum ++ * is valid. One would have to check the parse results to find that out. ++ */ ++#define FM_FD_STAT_L4CV 0x00000004 ++ ++#define FM_FD_STAT_ERRORS \ ++ (FM_PORT_FRM_ERR_DMA | FM_PORT_FRM_ERR_PHYSICAL | \ ++ FM_PORT_FRM_ERR_SIZE | FM_PORT_FRM_ERR_CLS_DISCARD | \ ++ FM_PORT_FRM_ERR_EXTRACTION | FM_PORT_FRM_ERR_NO_SCHEME | \ ++ FM_PORT_FRM_ERR_ILL_PLCR | FM_PORT_FRM_ERR_PRS_TIMEOUT | \ ++ FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | FM_PORT_FRM_ERR_PRS_HDR_ERR) ++ ++#define FM_FD_STAT_ERR_PHYSICAL FM_PORT_FRM_ERR_PHYSICAL ++ ++/* ++ * Check if the FMan Hardware Parser has run for L4 protocols. ++ * ++ * @parse_result_ptr must be of type (t_FmPrsResult *). ++ */ ++#define fm_l4_hxs_has_run(parse_result_ptr) \ ++ ((parse_result_ptr)->l4r & FM_L4_HXS_RUN) ++/* ++ * Iff the FMan Hardware Parser has run for L4 protocols, check error status. ++ * ++ * @parse_result_ptr must be of type (t_FmPrsResult *). ++ */ ++#define fm_l4_hxs_error(parse_result_ptr) \ ++ ((parse_result_ptr)->l4r & FM_L4_PARSE_ERROR) ++/* ++ * Check if the parsed frame was found to be a TCP segment. ++ * ++ * @parse_result_ptr must be of type (t_FmPrsResult *). ++ */ ++#define fm_l4_frame_is_tcp(parse_result_ptr) \ ++ ((parse_result_ptr)->l4r & FM_L4_PARSE_RESULT_TCP) ++ ++struct pcd_range { ++ uint32_t base; ++ uint32_t count; ++}; ++ ++struct dpa_fq { ++ struct qman_fq fq_base; ++ struct list_head list; ++ struct net_device *net_dev; ++ bool init; ++ uint32_t fqid; ++ uint32_t flags; ++ uint16_t channel; ++ uint8_t wq; ++ enum dpa_fq_type fq_type; ++}; ++ ++struct dpa_bp { ++ struct bman_pool *pool; ++ uint8_t bpid; ++ struct device *dev; ++ union { ++ /* ++ * The buffer pools used for the private ports are initialized ++ * with target_count buffers for each CPU; at runtime the ++ * number of buffers per CPU is constantly brought back to this ++ * level ++ */ ++ int target_count; ++ /* ++ * The configured value for the number of buffers in the pool, ++ * used for shared port buffer pools ++ */ ++ int config_count; ++ }; ++ size_t size; ++ bool seed_pool; ++ /* ++ * physical address of the contiguous memory used by the pool to store ++ * the buffers ++ */ ++ dma_addr_t paddr; ++ /* ++ * virtual address of the contiguous memory used by the pool to store ++ * the buffers ++ */ ++ void *vaddr; ++ int kernel_pool; ++ /* current number of buffers in the bpool alloted to this CPU */ ++ int *percpu_count; ++ atomic_t refs; ++}; ++ ++struct dpa_rx_errors { ++ u32 dme; /* DMA Error */ ++ u32 fpe; /* Frame Physical Error */ ++ u32 fse; /* Frame Size Error */ ++ u32 phe; /* Header Error */ ++ u32 cse; /* Checksum Validation Error */ ++}; ++ ++/* Counters for QMan ERN frames - one counter per rejection code */ ++struct dpa_ern_cnt { ++ u32 cg_tdrop; /* Congestion group taildrop */ ++ u32 wred; /* WRED congestion */ ++ u32 err_cond; /* Error condition */ ++ u32 early_window; /* Order restoration, frame too early */ ++ u32 late_window; /* Order restoration, frame too late */ ++ u32 fq_tdrop; /* FQ taildrop */ ++ u32 fq_retired; /* FQ is retired */ ++ u32 orp_zero; /* ORP disabled */ ++}; ++ ++struct dpa_percpu_priv_s { ++ struct net_device *net_dev; ++ /* ++ * Pointer to the percpu_count of the shared buffer pool ++ * used for the private ports; this assumes there is only ++ * one bpool used ++ */ ++ int *dpa_bp_count; ++ struct dpa_bp *dpa_bp; ++ struct napi_struct napi; ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++ /* a list of preallocated SKBs for this CPU */ ++ struct sk_buff_head skb_list; ++ /* current number of skbs in the CPU's list */ ++ int skb_count; ++#endif ++ u32 in_interrupt; ++ u32 tx_returned; ++ u32 tx_confirm; ++ /* fragmented (non-linear) skbuffs received from the stack */ ++ u32 tx_frag_skbuffs; ++ /* ++ * Frames identified as L4 packets (by FMan's Hardware Parser, but for ++ * which the parsing failed due to some error condition. If we come ++ * across such frames, we drop them instead of passing them up the ++ * stack, which means the L4 stats in the stack won't increment. ++ */ ++ u32 l4_hxs_errors; ++ struct net_device_stats stats; ++ struct dpa_rx_errors rx_errors; ++ struct dpa_ern_cnt ern_cnt; ++}; ++ ++struct dpa_priv_s { ++ struct dpa_bp *dpa_bp; ++ size_t bp_count; ++ int shared; ++ struct net_device *net_dev; ++ ++ uint16_t channel; /* "fsl,qman-channel-id" */ ++ struct list_head dpa_fq_list; ++ struct qman_fq *egress_fqs[DPAA_ETH_TX_QUEUES]; ++ struct qman_fq *conf_fqs[DPAA_ETH_TX_QUEUES]; ++#ifdef CONFIG_DPA_TX_RECYCLE ++ struct qman_fq *recycle_fqs[DPAA_ETH_TX_QUEUES]; ++#endif ++ ++ struct mac_device *mac_dev; ++ ++ struct dpa_percpu_priv_s *percpu_priv; ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *debugfs_file; ++#endif ++ ++ uint32_t msg_enable; /* net_device message level */ ++ struct dpa_ptp_tsu *tsu; ++ ++#if defined(CONFIG_DPAA_FMAN_UNIT_TESTS) ++/* TODO: this is temporary until pcd support is implemented in dpaa */ ++ int priv_pcd_num_ranges; ++ struct pcd_range priv_pcd_ranges[FMAN_PCD_TESTS_MAX_NUM_RANGES]; ++#endif ++ ++ struct { ++ /** ++ * All egress queues to a given net device belong to one ++ * (and the same) congestion group. ++ */ ++ struct qman_cgr cgr; ++ /* If congested, when it began. Used for performance stats. */ ++ u32 congestion_start_jiffies; ++ /* Number of jiffies the Tx port was congested. */ ++ u32 congested_jiffies; ++ /** ++ * Counter for the number of times the CGR ++ * entered congestion state ++ */ ++ u32 cgr_congested_count; ++ } cgr_data; ++}; ++ ++extern const struct ethtool_ops dpa_ethtool_ops; ++ ++void __attribute__((nonnull)) ++dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd); ++ ++void dpa_make_private_pool(struct dpa_bp *dpa_bp); ++ ++struct dpa_bp *dpa_bpid2pool(int bpid); ++ ++void __hot _dpa_rx(struct net_device *net_dev, ++ const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd, ++ u32 fqid); ++ ++int __hot dpa_tx(struct sk_buff *skb, struct net_device *net_dev); ++ ++struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, ++ const struct qm_fd *fd); ++ ++int __hot _dpa_process_parse_results(const t_FmPrsResult *parse_results, ++ const struct qm_fd *fd, ++ struct sk_buff *skb, ++ int *use_gro, ++ unsigned int *hdr_size __maybe_unused); ++ ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++void dpa_bp_add_8_pages(const struct dpa_bp *dpa_bp, int cpu_id); ++int _dpa_bp_add_8_pages(const struct dpa_bp *dpa_bp); ++ ++void dpa_list_add_skbs(struct dpa_percpu_priv_s *cpu_priv, int count); ++#endif ++ ++/* ++ * Turn on HW checksum computation for this outgoing frame. ++ * If the current protocol is not something we support in this regard ++ * (or if the stack has already computed the SW checksum), we do nothing. ++ * ++ * Returns 0 if all goes well (or HW csum doesn't apply), and a negative value ++ * otherwise. ++ * ++ * Note that this function may modify the fd->cmd field and the skb data buffer ++ * (the Parse Results area). ++ */ ++int dpa_enable_tx_csum(struct dpa_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd, char *parse_results); ++ ++static inline int dpaa_eth_napi_schedule(struct dpa_percpu_priv_s *percpu_priv) ++{ ++ /* ++ * In case of threaded ISR for RT enable kernel, ++ * in_irq() does not return appropriate value, so use ++ * in_serving_softirq to distinguish softirq or irq context. ++ */ ++ if (unlikely(in_irq() || !in_serving_softirq())) { ++ /* Disable QMan IRQ and invoke NAPI */ ++ int ret = qman_irqsource_remove(QM_PIRQ_DQRI); ++ if (likely(!ret)) { ++ napi_schedule(&percpu_priv->napi); ++ return 1; ++ } ++ } ++ return 0; ++} ++ ++static inline ssize_t __const __must_check __attribute__((nonnull)) ++dpa_fd_length(const struct qm_fd *fd) ++{ ++ return fd->length20; ++} ++ ++static inline ssize_t __const __must_check __attribute__((nonnull)) ++dpa_fd_offset(const struct qm_fd *fd) ++{ ++ return fd->offset; ++} ++ ++/* Verifies if the skb length is below the interface MTU */ ++static inline int dpa_check_rx_mtu(struct sk_buff *skb, int mtu) ++{ ++ if (unlikely(skb->len > mtu)) ++ if ((skb->protocol != ETH_P_8021Q) || (skb->len > mtu + 4)) ++ return -1; ++ ++ return 0; ++} ++ ++void fm_mac_dump_regs(struct mac_device *mac_dev); ++ ++void dpaa_eth_sysfs_remove(struct device *dev); ++void dpaa_eth_sysfs_init(struct device *dev); ++ ++/* Equivalent to a memset(0), but works faster */ ++static inline void clear_fd(struct qm_fd *fd) ++{ ++ fd->opaque_addr = 0; ++ fd->opaque = 0; ++ fd->cmd = 0; ++} ++ ++static inline int __hot dpa_xmit(struct dpa_priv_s *priv, ++ struct net_device_stats *percpu_stats, int queue, ++ struct qm_fd *fd) ++{ ++ int err, i; ++ struct qman_fq *egress_fq; ++ ++#ifdef CONFIG_DPA_TX_RECYCLE ++ /* Choose egress fq based on whether we want ++ * to recycle the frame or not */ ++ if (fd->cmd & FM_FD_CMD_FCO) ++ egress_fq = priv->recycle_fqs[queue]; ++ else ++ egress_fq = priv->egress_fqs[queue]; ++#else ++ egress_fq = priv->egress_fqs[queue]; ++#endif ++ ++ for (i = 0; i < 100000; i++) { ++ err = qman_enqueue(egress_fq, fd, 0); ++ if (err != -EBUSY) ++ break; ++ } ++ ++ if (unlikely(err < 0)) { ++ /* TODO differentiate b/w -EBUSY (EQCR full) and other codes? */ ++ percpu_stats->tx_errors++; ++ percpu_stats->tx_fifo_errors++; ++ return err; ++ } ++ ++ percpu_stats->tx_packets++; ++ percpu_stats->tx_bytes += dpa_fd_length(fd); ++ ++ return 0; ++} ++ ++#if defined CONFIG_DPA_ETH_WQ_LEGACY ++#define DPA_NUM_WQS 8 ++/* ++ * Older WQ assignment: statically-defined FQIDs (such as PCDs) are assigned ++ * round-robin to all WQs available. Dynamically-allocated FQIDs go to WQ7. ++ * ++ * Not necessarily the best scheme, but worked fine so far, so we might want ++ * to keep it around for a while. ++ */ ++static inline void _dpa_assign_wq(struct dpa_fq *fq) ++{ ++ fq->wq = fq->fqid ? fq->fqid % DPA_NUM_WQS : DPA_NUM_WQS - 1; ++} ++#elif defined CONFIG_DPA_ETH_WQ_MULTI ++/* ++ * Use multiple WQs for FQ assignment: ++ * - Tx Confirmation queues go to WQ1. ++ * - Rx Default, Tx and PCD queues go to WQ3 (no differentiation between ++ * Rx and Tx traffic, or between Rx Default and Rx PCD frames). ++ * - Rx Error and Tx Error queues go to WQ2 (giving them a better chance ++ * to be scheduled, in case there are many more FQs in WQ3). ++ * This ensures that Tx-confirmed buffers are timely released. In particular, ++ * it avoids congestion on the Tx Confirm FQs, which can pile up PFDRs if they ++ * are greatly outnumbered by other FQs in the system (usually PCDs), while ++ * dequeue scheduling is round-robin. ++ */ ++static inline void _dpa_assign_wq(struct dpa_fq *fq) ++{ ++ switch (fq->fq_type) { ++ case FQ_TYPE_TX_CONFIRM: ++ fq->wq = 1; ++ break; ++ case FQ_TYPE_RX_DEFAULT: ++ case FQ_TYPE_TX: ++#ifdef CONFIG_DPA_TX_RECYCLE ++ case FQ_TYPE_TX_RECYCLE: ++#endif ++ case FQ_TYPE_RX_PCD: ++ fq->wq = 3; ++ break; ++ case FQ_TYPE_RX_ERROR: ++ case FQ_TYPE_TX_ERROR: ++ fq->wq = 2; ++ break; ++ default: ++ WARN(1, "Invalid FQ type %d for FQID %d!\n", ++ fq->fq_type, fq->fqid); ++ } ++} ++#else ++/* This shouldn't happen, since we've made a "default" choice in the Kconfig. */ ++#error "No WQ assignment scheme chosen; Kconfig out-of-sync?" ++#endif /* CONFIG_DPA_ETH_WQ_ASSIGN_* */ ++ ++ ++#ifdef CONFIG_DPAA_ETH_USE_NDO_SELECT_QUEUE ++/* Use in lieu of skb_get_queue_mapping() */ ++#define dpa_get_queue_mapping(skb) \ ++ smp_processor_id() ++#else ++/* Use the queue selected by XPS */ ++#define dpa_get_queue_mapping(skb) \ ++ skb_get_queue_mapping(skb) ++#endif ++ ++#endif /* __DPA_H */ +diff --git a/drivers/net/dpa/dpaa_eth_sg.c b/drivers/net/dpa/dpaa_eth_sg.c +new file mode 100644 +index 0000000..fb9cab6 +--- /dev/null ++++ b/drivers/net/dpa/dpaa_eth_sg.c +@@ -0,0 +1,793 @@ ++/* ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++ ++#include ++#include ++#include ++#include ++ ++#include "dpaa_eth.h" ++#include "dpaa_1588.h" ++ ++#ifdef CONFIG_DPAA_ETH_SG_SUPPORT ++#define DPA_SGT_MAX_ENTRIES 16 /* maximum number of entries in SG Table */ ++ ++/* ++ * It does not return a page as you get the page from the fd, ++ * this is only for refcounting and DMA unmapping ++ */ ++static inline void dpa_bp_removed_one_page(struct dpa_bp *dpa_bp, ++ dma_addr_t dma_addr) ++{ ++ int *count_ptr; ++ ++ count_ptr = __this_cpu_ptr(dpa_bp->percpu_count); ++ (*count_ptr)--; ++ ++ dma_unmap_single(dpa_bp->dev, dma_addr, dpa_bp->size, ++ DMA_BIDIRECTIONAL); ++} ++ ++/* DMA map and add a page into the bpool */ ++static void dpa_bp_add_page(struct dpa_bp *dpa_bp, unsigned long vaddr) ++{ ++ struct bm_buffer bmb; ++ int *count_ptr; ++ dma_addr_t addr; ++ int offset; ++ ++ count_ptr = __this_cpu_ptr(dpa_bp->percpu_count); ++ ++ /* Make sure we don't map beyond end of page */ ++ offset = vaddr & (PAGE_SIZE - 1); ++ if (unlikely(dpa_bp->size + offset > PAGE_SIZE)) { ++ free_page(vaddr); ++ return; ++ } ++ addr = dma_map_single(dpa_bp->dev, (void *)vaddr, dpa_bp->size, ++ DMA_BIDIRECTIONAL); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ dev_err(dpa_bp->dev, "DMA mapping failed"); ++ return; ++ } ++ ++ bm_buffer_set64(&bmb, addr); ++ ++ while (bman_release(dpa_bp->pool, &bmb, 1, 0)) ++ cpu_relax(); ++ ++ (*count_ptr)++; ++} ++ ++int _dpa_bp_add_8_pages(const struct dpa_bp *dpa_bp) ++{ ++ struct bm_buffer bmb[8]; ++ unsigned long new_page; ++ dma_addr_t addr; ++ int i; ++ struct device *dev = dpa_bp->dev; ++ ++ for (i = 0; i < 8; i++) { ++ new_page = __get_free_page(GFP_ATOMIC); ++ if (likely(new_page)) { ++ addr = dma_map_single(dev, (void *)new_page, ++ dpa_bp->size, DMA_BIDIRECTIONAL); ++ if (likely(!dma_mapping_error(dev, addr))) { ++ bm_buffer_set64(&bmb[i], addr); ++ continue; ++ } else ++ free_page(new_page); ++ } ++ ++ /* Something went wrong */ ++ goto bail_out; ++ } ++ ++release_bufs: ++ /* ++ * Release the buffers. In case bman is busy, keep trying ++ * until successful. bman_release() is guaranteed to succeed ++ * in a reasonable amount of time ++ */ ++ while (unlikely(bman_release(dpa_bp->pool, bmb, i, 0))) ++ cpu_relax(); ++ ++ return i; ++ ++bail_out: ++ dev_err(dpa_bp->dev, "dpa_bp_add_8_pages() failed\n"); ++ bm_buffer_set64(&bmb[i], 0); ++ /* ++ * Avoid releasing a completely null buffer; bman_release() requires ++ * at least one buffer. ++ */ ++ if (likely(i)) ++ goto release_bufs; ++ ++ return 0; ++} ++ ++/* ++ * Cold path wrapper over _dpa_bp_add_8_pages(). ++ */ ++void dpa_bp_add_8_pages(const struct dpa_bp *dpa_bp, int cpu) ++{ ++ int *count_ptr = per_cpu_ptr(dpa_bp->percpu_count, cpu); ++ *count_ptr += _dpa_bp_add_8_pages(dpa_bp); ++} ++ ++void dpa_list_add_skb(struct dpa_percpu_priv_s *cpu_priv, ++ struct sk_buff *new_skb) ++{ ++ struct sk_buff_head *list_ptr; ++ ++ if (cpu_priv->skb_count > DEFAULT_SKB_COUNT) { ++ dev_kfree_skb(new_skb); ++ return; ++ } ++ ++ list_ptr = &cpu_priv->skb_list; ++ skb_queue_head(list_ptr, new_skb); ++ ++ cpu_priv->skb_count += 1; ++} ++ ++static struct sk_buff *dpa_list_get_skb(struct dpa_percpu_priv_s *cpu_priv) ++{ ++ struct sk_buff_head *list_ptr; ++ struct sk_buff *new_skb; ++ ++ list_ptr = &cpu_priv->skb_list; ++ ++ new_skb = skb_dequeue(list_ptr); ++ if (new_skb) ++ cpu_priv->skb_count -= 1; ++ ++ return new_skb; ++} ++ ++void dpa_list_add_skbs(struct dpa_percpu_priv_s *cpu_priv, int count) ++{ ++ struct sk_buff *new_skb; ++ int i; ++ ++ for (i = 0; i < count; i++) { ++ new_skb = dev_alloc_skb(DPA_BP_HEAD + ++ dpa_get_rx_extra_headroom() + ++ DPA_COPIED_HEADERS_SIZE); ++ if (unlikely(!new_skb)) { ++ pr_err("dev_alloc_skb() failed\n"); ++ break; ++ } ++ ++ dpa_list_add_skb(cpu_priv, new_skb); ++ } ++} ++ ++void dpa_make_private_pool(struct dpa_bp *dpa_bp) ++{ ++ int i; ++ ++ dpa_bp->percpu_count = __alloc_percpu(sizeof(*dpa_bp->percpu_count), ++ __alignof__(*dpa_bp->percpu_count)); ++ ++ /* Give each CPU an allotment of "page_count" buffers */ ++ for_each_online_cpu(i) { ++ int j; ++ ++ /* ++ * Although we access another CPU's counters here ++ * we do it at boot time so it is safe ++ */ ++ for (j = 0; j < dpa_bp->config_count; j += 8) ++ dpa_bp_add_8_pages(dpa_bp, i); ++ } ++} ++ ++/* ++ * Cleanup function for outgoing frame descriptors that were built on Tx path, ++ * either contiguous frames or scatter/gather ones. ++ * Skb freeing is not handled here. ++ * ++ * This function may be called on error paths in the Tx function, so guard ++ * against cases when not all fd relevant fields were filled in. ++ * ++ * Return the skb backpointer, since for S/G frames the buffer containing it ++ * gets freed here. ++ */ ++struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, ++ const struct qm_fd *fd) ++{ ++ const struct qm_sg_entry *sgt; ++ int i; ++ struct dpa_bp *dpa_bp = priv->dpa_bp; ++ dma_addr_t addr = qm_fd_addr(fd); ++ struct sk_buff **skbh; ++ struct sk_buff *skb = NULL; ++ const enum dma_data_direction dma_dir = DMA_TO_DEVICE; ++ ++ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, dma_dir); ++ ++ /* retrieve skb back pointer */ ++ skbh = (struct sk_buff **)phys_to_virt(addr); ++ skb = *skbh; ++ ++ if (fd->format == qm_fd_sg) { ++ /* ++ * The sgt page is guaranteed to reside in lowmem. ++ */ ++ sgt = phys_to_virt(addr + dpa_fd_offset(fd)); ++ ++ /* sgt[0] is from lowmem, was dma_map_single()-ed */ ++ dma_unmap_single(dpa_bp->dev, sgt[0].addr, ++ sgt[0].length, dma_dir); ++ ++ /* remaining pages were mapped with dma_map_page() */ ++ for (i = 1; i < skb_shinfo(skb)->nr_frags; i++) { ++ BUG_ON(sgt[i].extension); ++ ++ dma_unmap_page(dpa_bp->dev, sgt[i].addr, ++ dpa_bp->size, dma_dir); ++ } ++ ++ /* ++ * TODO: dpa_bp_add_page() ? ++ * We could put these in the pool, since we allocated them ++ * and we know they're not used by anyone else ++ */ ++ ++ /* Free separately the pages that we allocated on Tx */ ++ free_page((unsigned long)phys_to_virt(addr)); ++} ++ ++ return skb; ++} ++ ++/* ++ * Move the first DPA_COPIED_HEADERS_SIZE bytes to the skb linear buffer to ++ * provide the networking stack the headers it requires in the linear buffer. ++ * ++ * If the entire frame fits in the skb linear buffer, the page holding the ++ * received data is recycled as it is no longer required. ++ * ++ * Return 0 if the ingress skb was properly constructed, non-zero if an error ++ * was encountered and the frame should be dropped. ++ */ ++static int __hot contig_fd_to_skb(const struct dpa_priv_s *priv, ++ const struct qm_fd *fd, struct sk_buff *skb, int *use_gro) ++{ ++ unsigned int copy_size = DPA_COPIED_HEADERS_SIZE; ++ dma_addr_t addr = qm_fd_addr(fd); ++ void *vaddr; ++ struct page *page; ++ int frag_offset, page_offset; ++ struct dpa_bp *dpa_bp = priv->dpa_bp; ++ unsigned char *tailptr; ++ const t_FmPrsResult *parse_results; ++ int ret; ++ ++ vaddr = phys_to_virt(addr); ++ ++#ifdef CONFIG_FSL_DPA_1588 ++ if (priv->tsu && priv->tsu->valid && priv->tsu->hwts_rx_en_ioctl) ++ dpa_ptp_store_rxstamp(priv->net_dev, skb, fd); ++#endif ++ ++ /* Peek at the parse results for frame validation. */ ++ parse_results = (const t_FmPrsResult *)(vaddr + DPA_RX_PRIV_DATA_SIZE); ++ ret = _dpa_process_parse_results(parse_results, fd, skb, use_gro, ++ ©_size); ++ if (unlikely(ret)) ++ /* This is definitely a bad frame, don't go further. */ ++ return ret; ++ ++ tailptr = skb_put(skb, copy_size); ++ ++ /* Copy (at least) the headers in the linear portion */ ++ memcpy(tailptr, vaddr + dpa_fd_offset(fd), copy_size); ++ ++ /* ++ * If frame is longer than the amount we copy in the linear ++ * buffer, add the page as fragment, ++ * otherwise recycle the page ++ */ ++ page = pfn_to_page(addr >> PAGE_SHIFT); ++ ++ if (copy_size < dpa_fd_length(fd)) { ++ /* add the page as a fragment in the skb */ ++ page_offset = (unsigned long)vaddr & (PAGE_SIZE - 1); ++ frag_offset = page_offset + dpa_fd_offset(fd) + copy_size; ++ skb_add_rx_frag(skb, 0, page, frag_offset, ++ dpa_fd_length(fd) - copy_size); ++ } else { ++ /* recycle the page */ ++ dpa_bp_add_page(dpa_bp, (unsigned long)vaddr); ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * Move the first bytes of the frame to the skb linear buffer to ++ * provide the networking stack the headers it requires in the linear buffer, ++ * and add the rest of the frame as skb fragments. ++ * ++ * The page holding the S/G Table is recycled here. ++ */ ++static int __hot sg_fd_to_skb(const struct dpa_priv_s *priv, ++ const struct qm_fd *fd, struct sk_buff *skb, ++ int *use_gro) ++{ ++ const struct qm_sg_entry *sgt; ++ dma_addr_t addr = qm_fd_addr(fd); ++ dma_addr_t sg_addr; ++ void *vaddr, *sg_vaddr; ++ struct dpa_bp *dpa_bp; ++ struct page *page; ++ int frag_offset, frag_len; ++ int page_offset; ++ int i, ret; ++ unsigned int copy_size = DPA_COPIED_HEADERS_SIZE; ++ const t_FmPrsResult *parse_results; ++ ++ vaddr = phys_to_virt(addr); ++ /* ++ * In the case of a SG frame, FMan stores the Internal Context ++ * in the buffer containing the sgt. ++ */ ++ parse_results = (const t_FmPrsResult *)(vaddr + DPA_RX_PRIV_DATA_SIZE); ++ /* Validate the frame before anything else. */ ++ ret = _dpa_process_parse_results(parse_results, fd, skb, use_gro, ++ ©_size); ++ if (unlikely(ret)) ++ /* Bad frame, stop processing now. */ ++ return ret; ++ ++ /* ++ * Iterate through the SGT entries and add the data buffers as ++ * skb fragments ++ */ ++ sgt = vaddr + dpa_fd_offset(fd); ++ for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) { ++ /* Extension bit is not supported */ ++ BUG_ON(sgt[i].extension); ++ ++ dpa_bp = dpa_bpid2pool(sgt[i].bpid); ++ BUG_ON(IS_ERR(dpa_bp)); ++ ++ sg_addr = qm_sg_addr(&sgt[i]); ++ sg_vaddr = phys_to_virt(sg_addr); ++ ++ dpa_bp_removed_one_page(dpa_bp, sg_addr); ++ page = pfn_to_page(sg_addr >> PAGE_SHIFT); ++ ++ /* ++ * Padding at the beginning of the page ++ * (offset in page from where BMan buffer begins) ++ */ ++ page_offset = (unsigned long)sg_vaddr & (PAGE_SIZE - 1); ++ ++ if (i == 0) { ++ /* This is the first fragment */ ++ /* Move the network headers in the skb linear portion */ ++ memcpy(skb_put(skb, copy_size), ++ sg_vaddr + sgt[i].offset, ++ copy_size); ++ ++ /* Adjust offset/length for the remaining data */ ++ frag_offset = sgt[i].offset + page_offset + copy_size; ++ frag_len = sgt[i].length - copy_size; ++ } else { ++ /* ++ * Not the first fragment; all data from buferr will ++ * be added in an skb fragment ++ */ ++ frag_offset = sgt[i].offset + page_offset; ++ frag_len = sgt[i].length; ++ } ++ /* Add data buffer to the skb */ ++ skb_add_rx_frag(skb, i, page, frag_offset, frag_len); ++ ++ if (sgt[i].final) ++ break; ++ } ++ ++#ifdef CONFIG_FSL_DPA_1588 ++ if (priv->tsu && priv->tsu->valid && priv->tsu->hwts_rx_en_ioctl) ++ dpa_ptp_store_rxstamp(priv->net_dev, skb, fd); ++#endif ++ ++ /* recycle the SGT page */ ++ dpa_bp = dpa_bpid2pool(fd->bpid); ++ BUG_ON(IS_ERR(dpa_bp)); ++ dpa_bp_add_page(dpa_bp, (unsigned long)vaddr); ++ ++ return 0; ++} ++ ++void __hot _dpa_rx(struct net_device *net_dev, ++ const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ struct dpa_bp *dpa_bp; ++ struct sk_buff *skb; ++ dma_addr_t addr = qm_fd_addr(fd); ++ u32 fd_status = fd->status; ++ unsigned int skb_len; ++ struct net_device_stats *percpu_stats = &percpu_priv->stats; ++ int use_gro = net_dev->features & NETIF_F_GRO; ++ ++ if (unlikely(fd_status & FM_FD_STAT_ERRORS) != 0) { ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd_status & FM_FD_STAT_ERRORS); ++ ++ percpu_stats->rx_errors++; ++ goto _release_frame; ++ } ++ ++ dpa_bp = dpa_bpid2pool(fd->bpid); ++ skb = dpa_list_get_skb(percpu_priv); ++ ++ if (unlikely(skb == NULL)) { ++ /* List is empty, so allocate a new skb */ ++ skb = dev_alloc_skb(DPA_BP_HEAD + dpa_get_rx_extra_headroom() + ++ DPA_COPIED_HEADERS_SIZE); ++ if (unlikely(skb == NULL)) { ++ if (netif_msg_rx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, ++ "Could not alloc skb\n"); ++ percpu_stats->rx_dropped++; ++ goto _release_frame; ++ } ++ } ++ ++ /* TODO We might want to do some prefetches here (skb, shinfo, data) */ ++ ++ /* ++ * Make sure forwarded skbs will have enough space on Tx, ++ * if extra headers are added. ++ */ ++ skb_reserve(skb, DPA_BP_HEAD + dpa_get_rx_extra_headroom()); ++ ++ dpa_bp_removed_one_page(dpa_bp, addr); ++ ++ /* prefetch the first 64 bytes of the frame or the SGT start */ ++ prefetch(phys_to_virt(addr) + dpa_fd_offset(fd)); ++ ++ if (likely(fd->format == qm_fd_contig)) { ++ if (unlikely(contig_fd_to_skb(priv, fd, skb, &use_gro))) { ++ /* ++ * There was a L4 HXS error - e.g. the L4 csum was ++ * invalid - so drop the frame early instead of passing ++ * it on to the stack. We'll increment our private ++ * counters to track this event. ++ */ ++ percpu_priv->l4_hxs_errors++; ++ percpu_stats->rx_dropped++; ++ goto drop_bad_frame; ++ } ++ } else if (fd->format == qm_fd_sg) { ++ if (unlikely(sg_fd_to_skb(priv, fd, skb, &use_gro))) { ++ percpu_priv->l4_hxs_errors++; ++ percpu_stats->rx_dropped++; ++ goto drop_bad_frame; ++ } ++ } else ++ /* The only FD types that we may receive are contig and S/G */ ++ BUG(); ++ ++ skb->protocol = eth_type_trans(skb, net_dev); ++ ++ /* IP Reassembled frames are allowed to be larger than MTU */ ++ if (unlikely(dpa_check_rx_mtu(skb, net_dev->mtu) && ++ !(fd_status & FM_FD_IPR))) { ++ percpu_stats->rx_dropped++; ++ goto drop_bad_frame; ++ } ++ ++ skb_len = skb->len; ++ ++ if (use_gro) { ++ gro_result_t gro_result; ++ ++ gro_result = napi_gro_receive(&percpu_priv->napi, skb); ++ if (unlikely(gro_result == GRO_DROP)) { ++ percpu_stats->rx_dropped++; ++ goto packet_dropped; ++ } ++ } else if (unlikely(netif_receive_skb(skb) == NET_RX_DROP)) { ++ percpu_stats->rx_dropped++; ++ goto packet_dropped; ++ } ++ ++ percpu_stats->rx_packets++; ++ percpu_stats->rx_bytes += skb_len; ++ ++packet_dropped: ++ return; ++ ++drop_bad_frame: ++ dev_kfree_skb(skb); ++ return; ++ ++_release_frame: ++ dpa_fd_release(net_dev, fd); ++} ++ ++static int __hot skb_to_contig_fd(struct dpa_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd) ++{ ++ struct sk_buff **skbh; ++ dma_addr_t addr; ++ struct dpa_bp *dpa_bp; ++ struct net_device *net_dev = priv->net_dev; ++ int err; ++ ++ /* We are guaranteed that we have at least DPA_BP_HEAD of headroom. */ ++ skbh = (struct sk_buff **)(skb->data - DPA_BP_HEAD); ++ ++ *skbh = skb; ++ ++ dpa_bp = priv->dpa_bp; ++ ++ /* ++ * Enable L3/L4 hardware checksum computation. ++ * ++ * We must do this before dma_map_single(DMA_TO_DEVICE), because we may ++ * need to write into the skb. ++ */ ++ err = dpa_enable_tx_csum(priv, skb, fd, ++ ((char *)skbh) + DPA_TX_PRIV_DATA_SIZE); ++ if (unlikely(err < 0)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "HW csum error: %d\n", err); ++ return err; ++ } ++ ++ /* Fill in the FD */ ++ fd->format = qm_fd_contig; ++ fd->length20 = skb->len; ++ fd->offset = DPA_BP_HEAD; /* This is now guaranteed */ ++ ++ addr = dma_map_single(dpa_bp->dev, skbh, dpa_bp->size, DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "dma_map_single() failed\n"); ++ return -EINVAL; ++ } ++ fd->addr_hi = upper_32_bits(addr); ++ fd->addr_lo = lower_32_bits(addr); ++ ++ return 0; ++} ++ ++static int __hot skb_to_sg_fd(struct dpa_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd) ++{ ++ struct dpa_bp *dpa_bp = priv->dpa_bp; ++ dma_addr_t addr; ++ struct sk_buff **skbh; ++ struct net_device *net_dev = priv->net_dev; ++ int err; ++ ++ struct qm_sg_entry *sgt; ++ unsigned long sgt_page; ++ void *buffer_start; ++ skb_frag_t *frag; ++ int i, j; ++ const enum dma_data_direction dma_dir = DMA_TO_DEVICE; ++ ++ fd->format = qm_fd_sg; ++ ++ /* get a new page to store the SGTable */ ++ sgt_page = __get_free_page(GFP_ATOMIC); ++ if (unlikely(!sgt_page)) { ++ dev_err(dpa_bp->dev, "__get_free_page() failed\n"); ++ return -ENOMEM; ++ } ++ ++ /* ++ * Enable L3/L4 hardware checksum computation. ++ * ++ * We must do this before dma_map_single(DMA_TO_DEVICE), because we may ++ * need to write into the skb. ++ */ ++ err = dpa_enable_tx_csum(priv, skb, fd, ++ (void *)sgt_page + DPA_TX_PRIV_DATA_SIZE); ++ if (unlikely(err < 0)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "HW csum error: %d\n", err); ++ goto csum_failed; ++ } ++ ++ sgt = (struct qm_sg_entry *)(sgt_page + DPA_BP_HEAD); ++ sgt[0].bpid = dpa_bp->bpid; ++ sgt[0].offset = 0; ++ sgt[0].length = skb_headlen(skb); ++ sgt[0].extension = 0; ++ sgt[0].final = 0; ++ addr = dma_map_single(dpa_bp->dev, skb->data, sgt[0].length, dma_dir); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ dev_err(dpa_bp->dev, "DMA mapping failed"); ++ err = -EINVAL; ++ goto sg0_map_failed; ++ ++ } ++ sgt[0].addr_hi = upper_32_bits(addr); ++ sgt[0].addr_lo = lower_32_bits(addr); ++ ++ /* populate the rest of SGT entries */ ++ for (i = 1; i <= skb_shinfo(skb)->nr_frags; i++) { ++ frag = &skb_shinfo(skb)->frags[i - 1]; ++ sgt[i].bpid = dpa_bp->bpid; ++ sgt[i].offset = 0; ++ sgt[i].length = frag->size; ++ sgt[i].extension = 0; ++ sgt[i].final = 0; ++ ++ /* This shouldn't happen */ ++ BUG_ON(!frag->page.p); ++ ++ addr = dma_map_page(dpa_bp->dev, frag->page.p, frag->page_offset, ++ dpa_bp->size, dma_dir); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ dev_err(dpa_bp->dev, "DMA mapping failed"); ++ err = -EINVAL; ++ goto sg_map_failed; ++ } ++ ++ /* keep the offset in the address */ ++ sgt[i].addr_hi = upper_32_bits(addr); ++ sgt[i].addr_lo = lower_32_bits(addr); ++ } ++ sgt[i - 1].final = 1; ++ ++ fd->length20 = skb->len; ++ fd->offset = DPA_BP_HEAD; ++ ++ /* DMA map the SGT page */ ++ buffer_start = (void *)sgt - dpa_fd_offset(fd); ++ skbh = (struct sk_buff **)buffer_start; ++ *skbh = skb; ++ ++ addr = dma_map_single(dpa_bp->dev, buffer_start, dpa_bp->size, dma_dir); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ dev_err(dpa_bp->dev, "DMA mapping failed"); ++ err = -EINVAL; ++ goto sgt_map_failed; ++ } ++ fd->addr_hi = upper_32_bits(addr); ++ fd->addr_lo = lower_32_bits(addr); ++ ++ return 0; ++ ++sgt_map_failed: ++sg_map_failed: ++ for (j = 0; j < i; j++) ++ dma_unmap_page(dpa_bp->dev, qm_sg_addr(&sgt[j]), ++ dpa_bp->size, dma_dir); ++sg0_map_failed: ++csum_failed: ++ free_page(sgt_page); ++ ++ return err; ++} ++ ++int __hot dpa_tx(struct sk_buff *skb, struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv; ++ struct qm_fd fd; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct net_device_stats *percpu_stats; ++ int queue_mapping; ++ int err; ++ ++ priv = netdev_priv(net_dev); ++ /* Non-migratable context, safe to use __this_cpu_ptr */ ++ percpu_priv = __this_cpu_ptr(priv->percpu_priv); ++ percpu_stats = &percpu_priv->stats; ++ ++ clear_fd(&fd); ++ ++ queue_mapping = dpa_get_queue_mapping(skb); ++ ++ ++#ifdef CONFIG_FSL_DPA_1588 ++ if (priv->tsu && priv->tsu->valid && priv->tsu->hwts_tx_en_ioctl) ++ fd.cmd |= FM_FD_CMD_UPD; ++#endif ++ ++ if (skb_is_nonlinear(skb)) { ++ /* Just create a S/G fd based on the skb */ ++ err = skb_to_sg_fd(priv, skb, &fd); ++ percpu_priv->tx_frag_skbuffs++; ++ } else { ++ /* ++ * Make sure we have enough headroom to accomodate private ++ * data, parse results, etc. Normally this shouldn't happen if ++ * we're here via the standard kernel stack. ++ */ ++ if (unlikely(skb_headroom(skb) < DPA_BP_HEAD)) { ++ struct sk_buff *skb_new; ++ ++ skb_new = skb_realloc_headroom(skb, DPA_BP_HEAD); ++ if (unlikely(!skb_new)) { ++ dev_kfree_skb(skb); ++ percpu_stats->tx_errors++; ++ return NETDEV_TX_OK; ++ } ++ dev_kfree_skb(skb); ++ skb = skb_new; ++ } ++ ++ /* ++ * We're going to store the skb backpointer at the beginning ++ * of the data buffer, so we need a privately owned skb ++ */ ++ skb = skb_unshare(skb, GFP_ATOMIC); ++ if (unlikely(!skb)) { ++ percpu_stats->tx_errors++; ++ return NETDEV_TX_OK; ++ } ++ ++ /* Finally, create a contig FD from this skb */ ++ err = skb_to_contig_fd(priv, skb, &fd); ++ } ++ if (unlikely(err < 0)) { ++ percpu_stats->tx_errors++; ++ dev_kfree_skb(skb); ++ return NETDEV_TX_OK; ++ } ++ ++ if (unlikely(dpa_xmit(priv, percpu_stats, queue_mapping, &fd) < 0)) ++ goto xmit_failed; ++ ++ net_dev->trans_start = jiffies; ++ ++ return NETDEV_TX_OK; ++ ++xmit_failed: ++ _dpa_cleanup_tx_fd(priv, &fd); ++ dev_kfree_skb(skb); ++ ++ return NETDEV_TX_OK; ++} ++ ++#endif /* CONFIG_DPAA_ETH_SG_SUPPORT */ +diff --git a/drivers/net/dpa/dpaa_eth_sysfs.c b/drivers/net/dpa/dpaa_eth_sysfs.c +new file mode 100644 +index 0000000..53c0c8f +--- /dev/null ++++ b/drivers/net/dpa/dpaa_eth_sysfs.c +@@ -0,0 +1,189 @@ ++ ++/* ++ * Copyright 2008-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 ++#include ++#include ++#include ++#include ++#include "dpaa_eth.h" ++ ++static ssize_t dpaa_eth_show_addr(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ struct mac_device *mac_dev = priv->mac_dev; ++ ++ if (mac_dev) ++ return sprintf(buf, "%llx", ++ (unsigned long long)mac_dev->res->start); ++ else ++ return sprintf(buf, "none"); ++} ++ ++static ssize_t dpaa_eth_show_fqids(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ ssize_t bytes = 0; ++ int i = 0; ++ char *str; ++ struct dpa_fq *fq; ++ struct dpa_fq *tmp; ++ struct dpa_fq *prev = NULL; ++ u32 first_fqid = 0; ++ u32 last_fqid = 0; ++ char *prevstr = NULL; ++ ++ list_for_each_entry_safe(fq, tmp, &priv->dpa_fq_list, list) { ++ switch (fq->fq_type) { ++ case FQ_TYPE_RX_DEFAULT: ++ str = "Rx default"; ++ break; ++ case FQ_TYPE_RX_ERROR: ++ str = "Rx error"; ++ break; ++ case FQ_TYPE_RX_PCD: ++ str = "Rx PCD"; ++ break; ++ case FQ_TYPE_TX_CONFIRM: ++ str = "Tx confirmation"; ++ break; ++ case FQ_TYPE_TX_ERROR: ++ str = "Tx error"; ++ break; ++ case FQ_TYPE_TX: ++ str = "Tx"; ++ break; ++#ifdef CONFIG_DPA_TX_RECYCLE ++ case FQ_TYPE_TX_RECYCLE: ++ str = "Tx(recycling)"; ++ break; ++#endif ++ default: ++ str = "Unknown"; ++ } ++ ++ if (prev && (abs(fq->fqid - prev->fqid) != 1 || ++ str != prevstr)) { ++ if (last_fqid == first_fqid) ++ bytes += sprintf(buf + bytes, ++ "%s: %d\n", prevstr, prev->fqid); ++ else ++ bytes += sprintf(buf + bytes, ++ "%s: %d - %d\n", prevstr, ++ first_fqid, last_fqid); ++ } ++ ++ if (prev && abs(fq->fqid - prev->fqid) == 1 && str == prevstr) ++ last_fqid = fq->fqid; ++ else ++ first_fqid = last_fqid = fq->fqid; ++ ++ prev = fq; ++ prevstr = str; ++ i++; ++ } ++ ++ if (prev) { ++ if (last_fqid == first_fqid) ++ bytes += sprintf(buf + bytes, "%s: %d\n", prevstr, ++ prev->fqid); ++ else ++ bytes += sprintf(buf + bytes, "%s: %d - %d\n", prevstr, ++ first_fqid, last_fqid); ++ } ++ ++ return bytes; ++} ++ ++static ssize_t dpaa_eth_show_dflt_bpid(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t bytes = 0; ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ struct dpa_bp *dpa_bp = priv->dpa_bp; ++ ++ if (priv->bp_count != 1) ++ bytes += snprintf(buf, PAGE_SIZE, "-1\n"); ++ else ++ bytes += snprintf(buf, PAGE_SIZE, "%u\n", dpa_bp->bpid); ++ ++ return bytes; ++} ++ ++static ssize_t dpaa_eth_show_mac_regs(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ struct mac_device *mac_dev = priv->mac_dev; ++ ++ if (mac_dev) ++ fm_mac_dump_regs(mac_dev); ++ else ++ return sprintf(buf, "no mac registers\n"); ++ ++ return 0; ++} ++ ++static struct device_attribute dpaa_eth_attrs[] = { ++ __ATTR(device_addr, S_IRUGO, dpaa_eth_show_addr, NULL), ++ __ATTR(fqids, S_IRUGO, dpaa_eth_show_fqids, NULL), ++ __ATTR(dflt_bpid, S_IRUGO, dpaa_eth_show_dflt_bpid, NULL), ++ __ATTR(mac_regs, S_IRUGO, dpaa_eth_show_mac_regs, NULL) ++}; ++ ++void dpaa_eth_sysfs_init(struct device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dpaa_eth_attrs); i++) ++ if (device_create_file(dev, &dpaa_eth_attrs[i])) { ++ dev_err(dev, "Error creating sysfs file\n"); ++ goto device_create_file_failed; ++ } ++ ++ return; ++ ++device_create_file_failed: ++ while (i > 0) ++ device_remove_file(dev, &dpaa_eth_attrs[--i]); ++} ++ ++void dpaa_eth_sysfs_remove(struct device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dpaa_eth_attrs); i++) ++ device_remove_file(dev, &dpaa_eth_attrs[i]); ++} +diff --git a/drivers/net/dpa/mac-api.c b/drivers/net/dpa/mac-api.c +new file mode 100644 +index 0000000..7b2b3a9 +--- /dev/null ++++ b/drivers/net/dpa/mac-api.c +@@ -0,0 +1,837 @@ ++/* Copyright 2008-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dpaa_eth-common.h" ++#include "dpaa_eth.h" ++#include "mac.h" ++ ++#include "error_ext.h" /* GET_ERROR_TYPE, E_OK */ ++#include "fm_mac_ext.h" ++#include "fm_rtc_ext.h" ++ ++#include "../ethernet/freescale/fsl_pq_mdio.h" ++ ++#define MAC_DESCRIPTION "FSL FMan MAC API based driver" ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++MODULE_AUTHOR("Emil Medve "); ++ ++MODULE_DESCRIPTION(MAC_DESCRIPTION); ++ ++struct mac_priv_s { ++ t_Handle mac; ++}; ++ ++const char *mac_driver_description __initconst = MAC_DESCRIPTION; ++const size_t mac_sizeof_priv[] __devinitconst = { ++ [DTSEC] = sizeof(struct mac_priv_s), ++ [XGMAC] = sizeof(struct mac_priv_s), ++ [MEMAC] = sizeof(struct mac_priv_s) ++}; ++ ++static const e_EnetMode _100[] __devinitconst = ++{ ++ [PHY_INTERFACE_MODE_MII] = e_ENET_MODE_MII_100, ++ [PHY_INTERFACE_MODE_RMII] = e_ENET_MODE_RMII_100 ++}; ++ ++static const e_EnetMode _1000[] __devinitconst = ++{ ++ [PHY_INTERFACE_MODE_GMII] = e_ENET_MODE_GMII_1000, ++ [PHY_INTERFACE_MODE_SGMII] = e_ENET_MODE_SGMII_1000, ++ [PHY_INTERFACE_MODE_TBI] = e_ENET_MODE_TBI_1000, ++ [PHY_INTERFACE_MODE_RGMII] = e_ENET_MODE_RGMII_1000, ++ [PHY_INTERFACE_MODE_RGMII_ID] = e_ENET_MODE_RGMII_1000, ++ [PHY_INTERFACE_MODE_RGMII_RXID] = e_ENET_MODE_RGMII_1000, ++ [PHY_INTERFACE_MODE_RGMII_TXID] = e_ENET_MODE_RGMII_1000, ++ [PHY_INTERFACE_MODE_RTBI] = e_ENET_MODE_RTBI_1000 ++}; ++ ++static e_EnetMode __cold __attribute__((nonnull)) ++macdev2enetinterface(const struct mac_device *mac_dev) ++{ ++ switch (mac_dev->max_speed) { ++ case SPEED_100: ++ return _100[mac_dev->phy_if]; ++ case SPEED_1000: ++ return _1000[mac_dev->phy_if]; ++ case SPEED_10000: ++ return e_ENET_MODE_XGMII_10000; ++ default: ++ return e_ENET_MODE_MII_100; ++ } ++} ++ ++static void mac_exception(t_Handle _mac_dev, e_FmMacExceptions exception) ++{ ++ struct mac_device *mac_dev; ++ ++ mac_dev = (struct mac_device *)_mac_dev; ++ ++ if (e_FM_MAC_EX_10G_RX_FIFO_OVFL == exception) { ++ /* don't flag RX FIFO after the first */ ++ FM_MAC_SetException( ++ ((struct mac_priv_s *)macdev_priv(_mac_dev))->mac, ++ e_FM_MAC_EX_10G_RX_FIFO_OVFL, false); ++ printk(KERN_ERR "10G MAC got RX FIFO Error = %x\n", exception); ++ } ++ ++ dev_dbg(mac_dev->dev, "%s:%s() -> %d\n", KBUILD_BASENAME".c", __func__, ++ exception); ++} ++ ++static int __devinit __cold init(struct mac_device *mac_dev) ++{ ++ int _errno; ++ t_Error err; ++ struct mac_priv_s *priv; ++ t_FmMacParams param; ++ uint32_t version; ++ ++ priv = macdev_priv(mac_dev); ++ ++ param.baseAddr = (typeof(param.baseAddr))(uintptr_t)devm_ioremap( ++ mac_dev->dev, mac_dev->res->start, 0x2000); ++ param.enetMode = macdev2enetinterface(mac_dev); ++ memcpy(¶m.addr, mac_dev->addr, min(sizeof(param.addr), ++ sizeof(mac_dev->addr))); ++ param.macId = mac_dev->cell_index; ++ param.h_Fm = (t_Handle)mac_dev->fm; ++ param.mdioIrq = NO_IRQ; ++ param.f_Exception = mac_exception; ++ param.f_Event = mac_exception; ++ param.h_App = mac_dev; ++ ++ priv->mac = FM_MAC_Config(¶m); ++ if (unlikely(priv->mac == NULL)) { ++ dev_err(mac_dev->dev, "FM_MAC_Config() failed\n"); ++ _errno = -EINVAL; ++ goto _return; ++ } ++ ++ fm_mac_set_handle(mac_dev->fm_dev, priv->mac, ++ (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) ? ++ param.macId : param.macId + FM_MAX_NUM_OF_1G_MACS); ++ ++ err = FM_MAC_ConfigMaxFrameLength(priv->mac, ++ fm_get_max_frm()); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) { ++ dev_err(mac_dev->dev, ++ "FM_MAC_ConfigMaxFrameLength() = 0x%08x\n", err); ++ goto _return_fm_mac_free; ++ } ++ ++ if (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) { ++ /* 10G always works with pad and CRC */ ++ err = FM_MAC_ConfigPadAndCrc(priv->mac, true); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) { ++ dev_err(mac_dev->dev, ++ "FM_MAC_ConfigPadAndCrc() = 0x%08x\n", err); ++ goto _return_fm_mac_free; ++ } ++ ++ err = FM_MAC_ConfigHalfDuplex(priv->mac, mac_dev->half_duplex); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) { ++ dev_err(mac_dev->dev, ++ "FM_MAC_ConfigHalfDuplex() = 0x%08x\n", err); ++ goto _return_fm_mac_free; ++ } ++ } ++ else { ++ err = FM_MAC_ConfigResetOnInit(priv->mac, true); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) { ++ dev_err(mac_dev->dev, ++ "FM_MAC_ConfigResetOnInit() = 0x%08x\n", err); ++ goto _return_fm_mac_free; ++ } ++ } ++ ++ err = FM_MAC_Init(priv->mac); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) { ++ dev_err(mac_dev->dev, "FM_MAC_Init() = 0x%08x\n", err); ++ goto _return_fm_mac_free; ++ } ++ ++#ifndef CONFIG_FMAN_MIB_CNT_OVF_IRQ_EN ++ /* For 1G MAC, disable by default the MIB counters overflow interrupt */ ++ if (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) { ++ err = FM_MAC_SetException(priv->mac, ++ e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL, FALSE); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) { ++ dev_err(mac_dev->dev, ++ "FM_MAC_SetException() = 0x%08x\n", err); ++ goto _return_fm_mac_free; ++ } ++ } ++#endif /* !CONFIG_FMAN_MIB_CNT_OVF_IRQ_EN */ ++ ++ /* For 10G MAC, disable Tx ECC exception */ ++ if (macdev2enetinterface(mac_dev) == e_ENET_MODE_XGMII_10000) { ++ err = FM_MAC_SetException(priv->mac, ++ e_FM_MAC_EX_10G_1TX_ECC_ER, FALSE); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) { ++ dev_err(mac_dev->dev, ++ "FM_MAC_SetException() = 0x%08x\n", err); ++ goto _return_fm_mac_free; ++ } ++ } ++ ++ err = FM_MAC_GetVesrion(priv->mac, &version); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) { ++ dev_err(mac_dev->dev, "FM_MAC_GetVesrion() = 0x%08x\n", ++ err); ++ goto _return_fm_mac_free; ++ } ++ dev_info(mac_dev->dev, "FMan %s version: 0x%08x\n", ++ ((macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) ? ++ "dTSEC" : "XGEC"), version); ++ ++ goto _return; ++ ++ ++_return_fm_mac_free: ++ err = FM_MAC_Free(priv->mac); ++ if (unlikely(-GET_ERROR_TYPE(err) < 0)) ++ dev_err(mac_dev->dev, "FM_MAC_Free() = 0x%08x\n", err); ++_return: ++ return _errno; ++} ++ ++static int __devinit __cold memac_init(struct mac_device *mac_dev) ++{ ++ int _errno; ++ t_Error err; ++ struct mac_priv_s *priv; ++ t_FmMacParams param; ++ ++ priv = macdev_priv(mac_dev); ++ ++ param.baseAddr = (typeof(param.baseAddr))(uintptr_t)devm_ioremap( ++ mac_dev->dev, mac_dev->res->start, 0x2000); ++ param.enetMode = macdev2enetinterface(mac_dev); ++ memcpy(¶m.addr, mac_dev->addr, sizeof(mac_dev->addr)); ++ param.macId = mac_dev->cell_index; ++ param.h_Fm = (t_Handle)mac_dev->fm; ++ param.mdioIrq = NO_IRQ; ++ param.f_Exception = mac_exception; ++ param.f_Event = mac_exception; ++ param.h_App = mac_dev; ++ ++ priv->mac = FM_MAC_Config(¶m); ++ if (unlikely(priv->mac == NULL)) { ++ dev_err(mac_dev->dev, "FM_MAC_Config() failed\n"); ++ _errno = -EINVAL; ++ goto _return; ++ } ++ ++ err = FM_MAC_ConfigMaxFrameLength(priv->mac, fm_get_max_frm()); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) { ++ dev_err(mac_dev->dev, ++ "FM_MAC_ConfigMaxFrameLength() = 0x%08x\n", err); ++ goto _return_fm_mac_free; ++ } ++ ++ err = FM_MAC_ConfigResetOnInit(priv->mac, true); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) { ++ dev_err(mac_dev->dev, ++ "FM_MAC_ConfigResetOnInit() = 0x%08x\n", err); ++ goto _return_fm_mac_free; ++ } ++ ++ err = FM_MAC_Init(priv->mac); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) { ++ dev_err(mac_dev->dev, "FM_MAC_Init() = 0x%08x\n", err); ++ goto _return_fm_mac_free; ++ } ++ ++ dev_info(mac_dev->dev, "FMan MEMAC\n"); ++ ++ goto _return; ++ ++_return_fm_mac_free: ++ err = FM_MAC_Free(priv->mac); ++ if (unlikely(-GET_ERROR_TYPE(err) < 0)) ++ dev_err(mac_dev->dev, "FM_MAC_Free() = 0x%08x\n", err); ++_return: ++ return _errno; ++} ++ ++static int __cold start(struct mac_device *mac_dev) ++{ ++ int _errno; ++ t_Error err; ++ struct phy_device *phy_dev = mac_dev->phy_dev; ++ ++ err = FM_MAC_Enable(((struct mac_priv_s *)macdev_priv(mac_dev))->mac, ++ e_COMM_MODE_RX_AND_TX); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_MAC_Enable() = 0x%08x\n", err); ++ ++ if (phy_dev) { ++ if (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) ++ phy_start(phy_dev); ++ else if (phy_dev->drv->read_status) ++ phy_dev->drv->read_status(phy_dev); ++ } ++ ++ return _errno; ++} ++ ++static int __cold stop(struct mac_device *mac_dev) ++{ ++ int _errno; ++ t_Error err; ++ ++ if (mac_dev->phy_dev && ++ (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000)) ++ phy_stop(mac_dev->phy_dev); ++ ++ err = FM_MAC_Disable(((struct mac_priv_s *)macdev_priv(mac_dev))->mac, ++ e_COMM_MODE_RX_AND_TX); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_MAC_Disable() = 0x%08x\n", err); ++ ++ return _errno; ++} ++ ++static int __cold change_promisc(struct mac_device *mac_dev) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_MAC_SetPromiscuous( ++ ((struct mac_priv_s *)macdev_priv(mac_dev))->mac, ++ mac_dev->promisc = !mac_dev->promisc); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, ++ "FM_MAC_SetPromiscuous() = 0x%08x\n", err); ++ ++ return _errno; ++} ++ ++static int __cold set_multi(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ struct mac_priv_s *mac_priv; ++ struct mac_address *old_addr, *tmp; ++ struct netdev_hw_addr *ha; ++ int _errno; ++ t_Error err; ++ ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ mac_priv = macdev_priv(mac_dev); ++ ++ /* Clear previous address list */ ++ list_for_each_entry_safe(old_addr, tmp, &mac_dev->mc_addr_list, list) { ++ err = FM_MAC_RemoveHashMacAddr(mac_priv->mac, ++ (t_EnetAddr *)old_addr->addr); ++ _errno = -GET_ERROR_TYPE(err); ++ if (_errno < 0) { ++ dev_err(mac_dev->dev, ++ "FM_MAC_RemoveHashMacAddr() = 0x%08x\n", err); ++ return _errno; ++ } ++ list_del(&old_addr->list); ++ kfree(old_addr); ++ } ++ ++ /* Add all the addresses from the new list */ ++ netdev_for_each_mc_addr(ha, net_dev) { ++ err = FM_MAC_AddHashMacAddr(mac_priv->mac, ++ (t_EnetAddr *)ha->addr); ++ _errno = -GET_ERROR_TYPE(err); ++ if (_errno < 0) { ++ dev_err(mac_dev->dev, ++ "FM_MAC_AddHashMacAddr() = 0x%08x\n", err); ++ return _errno; ++ } ++ tmp = kmalloc(sizeof(struct mac_address), GFP_ATOMIC); ++ if (!tmp) { ++ dev_err(mac_dev->dev, "Out of memory\n"); ++ return -ENOMEM; ++ } ++ memcpy(tmp->addr, ha->addr, ETH_ALEN); ++ list_add(&tmp->list, &mac_dev->mc_addr_list); ++ } ++ return 0; ++} ++ ++static int __cold change_addr(struct mac_device *mac_dev, uint8_t *addr) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_MAC_ModifyMacAddr( ++ ((struct mac_priv_s *)macdev_priv(mac_dev))->mac, ++ (t_EnetAddr *)addr); ++ _errno = -GET_ERROR_TYPE(err); ++ if (_errno < 0) ++ dev_err(mac_dev->dev, ++ "FM_MAC_ModifyMacAddr() = 0x%08x\n", err); ++ ++ return _errno; ++} ++ ++static void adjust_link(struct net_device *net_dev) ++{ ++#if (DPAA_VERSION < 11) ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ struct phy_device *phy_dev = mac_dev->phy_dev; ++ struct mac_priv_s *mac_priv; ++ int _errno; ++ t_Error err; ++ ++ if (!phy_dev->link) { ++ fsl_pq_mdio_lock(NULL); ++ ++ mac_priv = (struct mac_priv_s *)macdev_priv(mac_dev); ++ DtsecRestartTbiAN(mac_priv->mac); ++ ++ fsl_pq_mdio_unlock(NULL); ++ return; ++ } ++ ++ err = FM_MAC_AdjustLink( ++ ((struct mac_priv_s *)macdev_priv(mac_dev))->mac, ++ phy_dev->speed, phy_dev->duplex); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_MAC_AdjustLink() = 0x%08x\n", ++ err); ++#endif ++ ++ return; ++} ++ ++/* Initializes driver's PHY state, and attaches to the PHY. ++ * Returns 0 on success. ++ */ ++static int dtsec_init_phy(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ struct phy_device *phy_dev; ++ ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ ++ if (!mac_dev->phy_node) ++ phy_dev = phy_connect(net_dev, mac_dev->fixed_bus_id, ++ &adjust_link, 0, mac_dev->phy_if); ++ else ++ phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, ++ &adjust_link, 0, mac_dev->phy_if); ++ if (unlikely(phy_dev == NULL) || IS_ERR(phy_dev)) { ++ netdev_err(net_dev, "Could not connect to PHY %s\n", ++ mac_dev->phy_node ? ++ mac_dev->phy_node->full_name : ++ mac_dev->fixed_bus_id); ++ return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev); ++ } ++ ++ /* Remove any features not supported by the controller */ ++ phy_dev->supported &= priv->mac_dev->if_support; ++ phy_dev->advertising = phy_dev->supported; ++ ++ priv->mac_dev->phy_dev = phy_dev; ++ ++ return 0; ++} ++ ++static int xgmac_init_phy(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ struct phy_device *phy_dev; ++ ++ if (!mac_dev->phy_node) ++ phy_dev = phy_attach(net_dev, mac_dev->fixed_bus_id, 0, ++ mac_dev->phy_if); ++ else ++ phy_dev = of_phy_attach(net_dev, mac_dev->phy_node, 0, ++ mac_dev->phy_if); ++ if (unlikely(phy_dev == NULL) || IS_ERR(phy_dev)) { ++ netdev_err(net_dev, "Could not attach to PHY %s\n", ++ mac_dev->phy_node ? ++ mac_dev->phy_node->full_name : ++ mac_dev->fixed_bus_id); ++ return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev); ++ } ++ ++ phy_dev->supported &= priv->mac_dev->if_support; ++ phy_dev->advertising = phy_dev->supported; ++ ++ mac_dev->phy_dev = phy_dev; ++ ++ return 0; ++} ++ ++static int memac_init_phy(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ struct phy_device *phy_dev; ++ ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ ++ if (macdev2enetinterface(mac_dev) == e_ENET_MODE_XGMII_10000) { ++ if (!mac_dev->phy_node) ++ phy_dev = phy_attach(net_dev, mac_dev->fixed_bus_id, 0, ++ mac_dev->phy_if); ++ else ++ phy_dev = of_phy_attach(net_dev, mac_dev->phy_node, 0, ++ mac_dev->phy_if); ++ } else { ++ if (!mac_dev->phy_node) ++ phy_dev = phy_connect(net_dev, mac_dev->fixed_bus_id, ++ &adjust_link, 0, mac_dev->phy_if); ++ else ++ phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, ++ &adjust_link, 0, mac_dev->phy_if); ++ } ++ ++ if (unlikely(phy_dev == NULL) || IS_ERR(phy_dev)) { ++ netdev_err(net_dev, "Could not connect to PHY %s\n", ++ mac_dev->phy_node ? ++ mac_dev->phy_node->full_name : ++ mac_dev->fixed_bus_id); ++ return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev); ++ } ++ ++ /* Remove any features not supported by the controller */ ++ phy_dev->supported &= priv->mac_dev->if_support; ++ phy_dev->advertising = phy_dev->supported; ++ ++ mac_dev->phy_dev = phy_dev; ++ ++ return 0; ++} ++ ++static int __cold uninit(struct mac_device *mac_dev) ++{ ++ int _errno, __errno; ++ t_Error err; ++ const struct mac_priv_s *priv; ++ ++ priv = macdev_priv(mac_dev); ++ ++ err = FM_MAC_Disable(priv->mac, e_COMM_MODE_RX_AND_TX); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_MAC_Disable() = 0x%08x\n", err); ++ ++ err = FM_MAC_Free(priv->mac); ++ __errno = -GET_ERROR_TYPE(err); ++ if (unlikely(__errno < 0)) { ++ dev_err(mac_dev->dev, "FM_MAC_Free() = 0x%08x\n", err); ++ if (_errno < 0) ++ _errno = __errno; ++ } ++ ++ return _errno; ++} ++ ++static int __cold ptp_enable(struct mac_device *mac_dev) ++{ ++ int _errno; ++ t_Error err; ++ const struct mac_priv_s *priv; ++ ++ priv = macdev_priv(mac_dev); ++ ++ err = FM_MAC_Enable1588TimeStamp(priv->mac); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_MAC_Enable1588TimeStamp()" ++ "= 0x%08x\n", err); ++ return _errno; ++} ++ ++static int __cold ptp_disable(struct mac_device *mac_dev) ++{ ++ int _errno; ++ t_Error err; ++ const struct mac_priv_s *priv; ++ ++ priv = macdev_priv(mac_dev); ++ ++ err = FM_MAC_Disable1588TimeStamp(priv->mac); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_MAC_Disable1588TimeStamp()" ++ "= 0x%08x\n", err); ++ return _errno; ++} ++ ++static void *get_mac_handle(struct mac_device *mac_dev) ++{ ++ const struct mac_priv_s *priv; ++ priv = macdev_priv(mac_dev); ++ return (void*)priv->mac; ++} ++ ++static int __cold fm_rtc_enable(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_Enable(fm_get_rtc_handle(mac_dev->fm_dev), 0); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_RTC_Enable = 0x%08x\n", err); ++ ++ return _errno; ++} ++ ++static int __cold fm_rtc_disable(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_Disable(fm_get_rtc_handle(mac_dev->fm_dev)); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_RTC_Disable = 0x%08x\n", err); ++ ++ return _errno; ++} ++ ++static int __cold fm_rtc_get_cnt(struct net_device *net_dev, uint64_t *ts) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_GetCurrentTime(fm_get_rtc_handle(mac_dev->fm_dev), ts); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_RTC_GetCurrentTime = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++ ++static int __cold fm_rtc_set_cnt(struct net_device *net_dev, uint64_t ts) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_SetCurrentTime(fm_get_rtc_handle(mac_dev->fm_dev), ts); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_RTC_SetCurrentTime = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++ ++static int __cold fm_rtc_get_drift(struct net_device *net_dev, uint32_t *drift) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_GetFreqCompensation(fm_get_rtc_handle(mac_dev->fm_dev), ++ drift); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_RTC_GetFreqCompensation =" ++ "0x%08x\n", err); ++ ++ return _errno; ++} ++ ++static int __cold fm_rtc_set_drift(struct net_device *net_dev, uint32_t drift) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_SetFreqCompensation(fm_get_rtc_handle(mac_dev->fm_dev), ++ drift); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_RTC_SetFreqCompensation =" ++ "0x%08x\n", err); ++ ++ return _errno; ++} ++ ++static int __cold fm_rtc_set_alarm(struct net_device *net_dev, uint32_t id, ++ uint64_t time) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ t_FmRtcAlarmParams alarm; ++ int _errno; ++ t_Error err; ++ ++ alarm.alarmId = id; ++ alarm.alarmTime = time; ++ alarm.f_AlarmCallback = NULL; ++ err = FM_RTC_SetAlarm(fm_get_rtc_handle(mac_dev->fm_dev), ++ &alarm); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_RTC_SetAlarm =" ++ "0x%08x\n", err); ++ ++ return _errno; ++} ++ ++static int __cold fm_rtc_set_fiper(struct net_device *net_dev, uint32_t id, ++ uint64_t fiper) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ t_FmRtcPeriodicPulseParams pp; ++ int _errno; ++ t_Error err; ++ ++ pp.periodicPulseId = id; ++ pp.periodicPulsePeriod = fiper; ++ pp.f_PeriodicPulseCallback = NULL; ++ err = FM_RTC_SetPeriodicPulse(fm_get_rtc_handle(mac_dev->fm_dev), &pp); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ dev_err(mac_dev->dev, "FM_RTC_SetPeriodicPulse =" ++ "0x%08x\n", err); ++ ++ return _errno; ++} ++ ++ ++void fm_mac_dump_regs(struct mac_device *mac_dev) ++{ ++ struct mac_priv_s *mac_priv = macdev_priv(mac_dev); ++ ++ FM_MAC_DumpRegs(mac_priv->mac); ++} ++ ++static void __devinit __cold setup_dtsec(struct mac_device *mac_dev) ++{ ++ mac_dev->init_phy = dtsec_init_phy; ++ mac_dev->init = init; ++ mac_dev->start = start; ++ mac_dev->stop = stop; ++ mac_dev->change_promisc = change_promisc; ++ mac_dev->change_addr = change_addr; ++ mac_dev->set_multi = set_multi; ++ mac_dev->uninit = uninit; ++ mac_dev->ptp_enable = ptp_enable; ++ mac_dev->ptp_disable = ptp_disable; ++ mac_dev->get_mac_handle = get_mac_handle; ++ mac_dev->fm_rtc_enable = fm_rtc_enable; ++ mac_dev->fm_rtc_disable = fm_rtc_disable; ++ mac_dev->fm_rtc_get_cnt = fm_rtc_get_cnt; ++ mac_dev->fm_rtc_set_cnt = fm_rtc_set_cnt; ++ mac_dev->fm_rtc_get_drift = fm_rtc_get_drift; ++ mac_dev->fm_rtc_set_drift = fm_rtc_set_drift; ++ mac_dev->fm_rtc_set_alarm = fm_rtc_set_alarm; ++ mac_dev->fm_rtc_set_fiper = fm_rtc_set_fiper; ++} ++ ++static void __devinit __cold setup_xgmac(struct mac_device *mac_dev) ++{ ++ mac_dev->init_phy = xgmac_init_phy; ++ mac_dev->init = init; ++ mac_dev->start = start; ++ mac_dev->stop = stop; ++ mac_dev->change_promisc = change_promisc; ++ mac_dev->change_addr = change_addr; ++ mac_dev->set_multi = set_multi; ++ mac_dev->uninit = uninit; ++} ++ ++static void __devinit __cold setup_memac(struct mac_device *mac_dev) ++{ ++ mac_dev->init_phy = memac_init_phy; ++ mac_dev->init = memac_init; ++ mac_dev->start = start; ++ mac_dev->stop = stop; ++ mac_dev->change_promisc = change_promisc; ++ mac_dev->change_addr = change_addr; ++ mac_dev->set_multi = set_multi; ++ mac_dev->uninit = uninit; ++ mac_dev->fm_rtc_enable = fm_rtc_enable; ++ mac_dev->fm_rtc_disable = fm_rtc_disable; ++ mac_dev->fm_rtc_get_cnt = fm_rtc_get_cnt; ++ mac_dev->fm_rtc_set_cnt = fm_rtc_set_cnt; ++ mac_dev->fm_rtc_get_drift = fm_rtc_get_drift; ++ mac_dev->fm_rtc_set_drift = fm_rtc_set_drift; ++ mac_dev->fm_rtc_set_alarm = fm_rtc_set_alarm; ++ mac_dev->fm_rtc_set_fiper = fm_rtc_set_fiper; ++} ++ ++void (*const mac_setup[])(struct mac_device *mac_dev) __devinitconst = { ++ [DTSEC] = setup_dtsec, ++ [XGMAC] = setup_xgmac, ++ [MEMAC] = setup_memac ++}; +diff --git a/drivers/net/dpa/mac.c b/drivers/net/dpa/mac.c +new file mode 100644 +index 0000000..7f72b2a +--- /dev/null ++++ b/drivers/net/dpa/mac.c +@@ -0,0 +1,441 @@ ++/* Copyright 2008-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dpaa_eth-common.h" ++ ++#include "lnxwrp_fm_ext.h" ++ ++#include "../ethernet/freescale/fsl_pq_mdio.h" ++#include "mac.h" ++ ++#define DTSEC_SUPPORTED \ ++ (SUPPORTED_10baseT_Half \ ++ | SUPPORTED_10baseT_Full \ ++ | SUPPORTED_100baseT_Half \ ++ | SUPPORTED_100baseT_Full \ ++ | SUPPORTED_Autoneg \ ++ | SUPPORTED_MII) ++ ++static const char phy_str[][11] __devinitconst = ++{ ++ [PHY_INTERFACE_MODE_MII] = "mii", ++ [PHY_INTERFACE_MODE_GMII] = "gmii", ++ [PHY_INTERFACE_MODE_SGMII] = "sgmii", ++ [PHY_INTERFACE_MODE_TBI] = "tbi", ++ [PHY_INTERFACE_MODE_RMII] = "rmii", ++ [PHY_INTERFACE_MODE_RGMII] = "rgmii", ++ [PHY_INTERFACE_MODE_RGMII_ID] = "rgmii-id", ++ [PHY_INTERFACE_MODE_RGMII_RXID] = "rgmii-rxid", ++ [PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid", ++ [PHY_INTERFACE_MODE_RTBI] = "rtbi", ++ [PHY_INTERFACE_MODE_XGMII] = "xgmii" ++}; ++ ++static phy_interface_t __devinit __pure __attribute__((nonnull)) str2phy(const char *str) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(phy_str); i++) ++ if (strcmp(str, phy_str[i]) == 0) ++ return (phy_interface_t)i; ++ ++ return PHY_INTERFACE_MODE_MII; ++} ++ ++static const uint16_t phy2speed[] __devinitconst = ++{ ++ [PHY_INTERFACE_MODE_MII] = SPEED_100, ++ [PHY_INTERFACE_MODE_GMII] = SPEED_1000, ++ [PHY_INTERFACE_MODE_SGMII] = SPEED_1000, ++ [PHY_INTERFACE_MODE_TBI] = SPEED_1000, ++ [PHY_INTERFACE_MODE_RMII] = SPEED_100, ++ [PHY_INTERFACE_MODE_RGMII] = SPEED_1000, ++ [PHY_INTERFACE_MODE_RGMII_ID] = SPEED_1000, ++ [PHY_INTERFACE_MODE_RGMII_RXID] = SPEED_1000, ++ [PHY_INTERFACE_MODE_RGMII_TXID] = SPEED_1000, ++ [PHY_INTERFACE_MODE_RTBI] = SPEED_1000, ++ [PHY_INTERFACE_MODE_XGMII] = SPEED_10000 ++}; ++ ++static struct mac_device * __devinit __cold ++alloc_macdev(struct device *dev, size_t sizeof_priv, void (*setup)(struct mac_device *mac_dev)) ++{ ++ struct mac_device *mac_dev; ++ ++ mac_dev = devm_kzalloc(dev, sizeof(*mac_dev) + sizeof_priv, GFP_KERNEL); ++ if (unlikely(mac_dev == NULL)) ++ mac_dev = ERR_PTR(-ENOMEM); ++ else { ++ mac_dev->dev = dev; ++ dev_set_drvdata(dev, mac_dev); ++ setup(mac_dev); ++ } ++ ++ return mac_dev; ++} ++ ++static int __devexit __cold free_macdev(struct mac_device *mac_dev) ++{ ++ dev_set_drvdata(mac_dev->dev, NULL); ++ ++ return mac_dev->uninit(mac_dev); ++} ++ ++static const struct of_device_id mac_match[] __devinitconst = { ++ [DTSEC] = { ++ .compatible = "fsl,fman-1g-mac" ++ }, ++ [XGMAC] = { ++ .compatible = "fsl,fman-10g-mac" ++ }, ++ [MEMAC] = { ++ .compatible = "fsl,fman-memac" ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, mac_match); ++ ++static int __devinit __cold mac_probe(struct platform_device *_of_dev) ++{ ++ int _errno, i, lenp; ++ struct device *dev; ++ struct device_node *mac_node, *dev_node; ++ struct mac_device *mac_dev; ++ struct platform_device *of_dev; ++ struct resource res; ++ const uint8_t *mac_addr; ++ const char *char_prop; ++ const phandle *phandle_prop; ++ const uint32_t *uint32_prop; ++ const struct of_device_id *match; ++ ++ dev = &_of_dev->dev; ++ mac_node = dev->of_node; ++ ++ match = of_match_device(mac_match, dev); ++ if (!match) ++ return -EINVAL; ++ ++ for (i = 0; i < ARRAY_SIZE(mac_match) - 1 && match != mac_match + i; i++); ++ BUG_ON(i >= ARRAY_SIZE(mac_match) - 1); ++ ++ mac_dev = alloc_macdev(dev, mac_sizeof_priv[i], mac_setup[i]); ++ if (IS_ERR(mac_dev)) { ++ _errno = PTR_ERR(mac_dev); ++ dev_err(dev, "alloc_macdev() = %d\n", _errno); ++ goto _return; ++ } ++ ++ INIT_LIST_HEAD(&mac_dev->mc_addr_list); ++ ++ /* Get the FM node */ ++ dev_node = of_get_parent(mac_node); ++ if (unlikely(dev_node == NULL)) { ++ dev_err(dev, "of_get_parent(%s) failed\n", ++ mac_node->full_name); ++ _errno = -EINVAL; ++ goto _return_dev_set_drvdata; ++ } ++ ++ of_dev = of_find_device_by_node(dev_node); ++ if (unlikely(of_dev == NULL)) { ++ dev_err(dev, "of_find_device_by_node(%s) failed\n", ++ dev_node->full_name); ++ _errno = -EINVAL; ++ goto _return_of_node_put; ++ } ++ ++ mac_dev->fm_dev = fm_bind(&of_dev->dev); ++ if (unlikely(mac_dev->fm_dev == NULL)) { ++ dev_err(dev, "fm_bind(%s) failed\n", dev_node->full_name); ++ _errno = -ENODEV; ++ goto _return_of_node_put; ++ } ++ ++ mac_dev->fm = (void *)fm_get_handle(mac_dev->fm_dev); ++ of_node_put(dev_node); ++ ++ /* Get the address of the memory mapped registers */ ++ _errno = of_address_to_resource(mac_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ dev_err(dev, "of_address_to_resource(%s) = %d\n", ++ mac_node->full_name, _errno); ++ goto _return_dev_set_drvdata; ++ } ++ ++ mac_dev->res = __devm_request_region( ++ dev, ++ fm_get_mem_region(mac_dev->fm_dev), ++ res.start, res.end + 1 - res.start, "mac"); ++ if (unlikely(mac_dev->res == NULL)) { ++ dev_err(dev, "__devm_request_mem_region(mac) failed\n"); ++ _errno = -EBUSY; ++ goto _return_dev_set_drvdata; ++ } ++ ++ mac_dev->vaddr = devm_ioremap(dev, mac_dev->res->start, ++ mac_dev->res->end + 1 - mac_dev->res->start); ++ if (unlikely(mac_dev->vaddr == NULL)) { ++ dev_err(dev, "devm_ioremap() failed\n"); ++ _errno = -EIO; ++ goto _return_dev_set_drvdata; ++ } ++ ++ /* ++ * XXX: Warning, future versions of Linux will most likely not even ++ * call the driver code to allow us to override the TBIPA value, ++ * we'll need to address this when we move to newer kernel rev ++ */ ++#define TBIPA_OFFSET 0x1c ++#define TBIPA_DEFAULT_ADDR 5 ++ mac_dev->tbi_node = of_parse_phandle(mac_node, "tbi-handle", 0); ++ if (mac_dev->tbi_node) { ++ u32 tbiaddr = TBIPA_DEFAULT_ADDR; ++ ++ uint32_prop = of_get_property(mac_dev->tbi_node, "reg", NULL); ++ if (uint32_prop) ++ tbiaddr = *uint32_prop; ++ out_be32(mac_dev->vaddr + TBIPA_OFFSET, tbiaddr); ++ } ++ ++ if (!of_device_is_available(mac_node)) { ++ devm_iounmap(dev, mac_dev->vaddr); ++ __devm_release_region(dev, fm_get_mem_region(mac_dev->fm_dev), ++ res.start, res.end + 1 - res.start); ++ fm_unbind(mac_dev->fm_dev); ++ devm_kfree(dev, mac_dev); ++ dev_set_drvdata(dev, NULL); ++ return -ENODEV; ++ } ++ ++ /* Get the cell-index */ ++ uint32_prop = of_get_property(mac_node, "cell-index", &lenp); ++ if (unlikely(uint32_prop == NULL)) { ++ dev_err(dev, "of_get_property(%s, cell-index) failed\n", ++ mac_node->full_name); ++ _errno = -EINVAL; ++ goto _return_dev_set_drvdata; ++ } ++ BUG_ON(lenp != sizeof(uint32_t)); ++ mac_dev->cell_index = *uint32_prop; ++ ++ /* Get the MAC address */ ++ mac_addr = of_get_mac_address(mac_node); ++ if (unlikely(mac_addr == NULL)) { ++ dev_err(dev, "of_get_mac_address(%s) failed\n", ++ mac_node->full_name); ++ _errno = -EINVAL; ++ goto _return_dev_set_drvdata; ++ } ++ memcpy(mac_dev->addr, mac_addr, sizeof(mac_dev->addr)); ++ ++ /* Get the port handles */ ++ phandle_prop = of_get_property(mac_node, "fsl,port-handles", &lenp); ++ if (unlikely(phandle_prop == NULL)) { ++ dev_err(dev, "of_get_property(%s, port-handles) failed\n", ++ mac_node->full_name); ++ _errno = -EINVAL; ++ goto _return_dev_set_drvdata; ++ } ++ BUG_ON(lenp != sizeof(phandle) * ARRAY_SIZE(mac_dev->port_dev)); ++ ++ for_each_port_device(i, mac_dev->port_dev) { ++ /* Find the port node */ ++ dev_node = of_find_node_by_phandle(phandle_prop[i]); ++ if (unlikely(dev_node == NULL)) { ++ dev_err(dev, "of_find_node_by_phandle() failed\n"); ++ _errno = -EINVAL; ++ goto _return_of_node_put; ++ } ++ ++ of_dev = of_find_device_by_node(dev_node); ++ if (unlikely(of_dev == NULL)) { ++ dev_err(dev, "of_find_device_by_node(%s) failed\n", ++ dev_node->full_name); ++ _errno = -EINVAL; ++ goto _return_of_node_put; ++ } ++ ++ mac_dev->port_dev[i] = fm_port_bind(&of_dev->dev); ++ if (unlikely(mac_dev->port_dev[i] == NULL)) { ++ dev_err(dev, "dev_get_drvdata(%s) failed\n", ++ dev_node->full_name); ++ _errno = -EINVAL; ++ goto _return_of_node_put; ++ } ++ of_node_put(dev_node); ++ } ++ ++ /* Get the PHY connection type */ ++ char_prop = (const char *)of_get_property(mac_node, ++ "phy-connection-type", NULL); ++ if (unlikely(char_prop == NULL)) { ++ dev_warn(dev, ++ "of_get_property(%s, phy-connection-type) " ++ "failed. Defaulting to MII\n", ++ mac_node->full_name); ++ mac_dev->phy_if = PHY_INTERFACE_MODE_MII; ++ } else ++ mac_dev->phy_if = str2phy(char_prop); ++ ++ mac_dev->link = false; ++ mac_dev->half_duplex = false; ++ mac_dev->speed = phy2speed[mac_dev->phy_if]; ++ mac_dev->max_speed = mac_dev->speed; ++ mac_dev->if_support = DTSEC_SUPPORTED; ++ /* We don't support half-duplex in SGMII mode */ ++ if (strstr(char_prop, "sgmii")) ++ mac_dev->if_support &= ~(SUPPORTED_10baseT_Half | ++ SUPPORTED_100baseT_Half); ++ ++ /* Gigabit support (no half-duplex) */ ++ if (mac_dev->max_speed == 1000) ++ mac_dev->if_support |= SUPPORTED_1000baseT_Full; ++ ++ /* The 10G interface only supports one mode */ ++ if (strstr(char_prop, "xgmii")) ++ mac_dev->if_support = SUPPORTED_10000baseT_Full; ++ ++ /* Get the rest of the PHY information */ ++ mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0); ++ if (mac_dev->phy_node == NULL) { ++ int sz; ++ const u32 *phy_id = of_get_property(mac_node, "fixed-link", ++ &sz); ++ if (!phy_id || sz < sizeof(*phy_id)) { ++ dev_err(dev, "No PHY (or fixed link) found\n"); ++ _errno = -EINVAL; ++ goto _return_dev_set_drvdata; ++ } ++ ++ sprintf(mac_dev->fixed_bus_id, PHY_ID_FMT, "0", phy_id[0]); ++ } ++ ++ _errno = mac_dev->init(mac_dev); ++ if (unlikely(_errno < 0)) { ++ dev_err(dev, "mac_dev->init() = %d\n", _errno); ++ goto _return_dev_set_drvdata; ++ } ++ ++ dev_info(dev, ++ "FMan MAC address: %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n", ++ mac_dev->addr[0], mac_dev->addr[1], mac_dev->addr[2], ++ mac_dev->addr[3], mac_dev->addr[4], mac_dev->addr[5]); ++ ++ goto _return; ++ ++_return_of_node_put: ++ of_node_put(dev_node); ++_return_dev_set_drvdata: ++ dev_set_drvdata(dev, NULL); ++_return: ++ return _errno; ++} ++ ++static int __devexit __cold mac_remove(struct platform_device *of_dev) ++{ ++ int i, _errno; ++ struct device *dev; ++ struct mac_device *mac_dev; ++ ++ dev = &of_dev->dev; ++ mac_dev = (struct mac_device *)dev_get_drvdata(dev); ++ ++ for_each_port_device(i, mac_dev->port_dev) ++ fm_port_unbind(mac_dev->port_dev[i]); ++ ++ fm_unbind(mac_dev->fm_dev); ++ ++ _errno = free_macdev(mac_dev); ++ ++ return _errno; ++} ++ ++static struct platform_driver mac_driver = { ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .of_match_table = mac_match, ++ .owner = THIS_MODULE, ++ }, ++ .probe = mac_probe, ++ .remove = __devexit_p(mac_remove) ++}; ++ ++static int __init __cold mac_load(void) ++{ ++ int _errno; ++ ++ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ pr_info(KBUILD_MODNAME ": %s (" VERSION ")\n", ++ mac_driver_description); ++ ++ _errno = platform_driver_register(&mac_driver); ++ if (unlikely(_errno < 0)) { ++ pr_err(KBUILD_MODNAME ": %s:%hu:%s(): " \ ++ "platform_driver_register() = %d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, _errno); ++ goto _return; ++ } ++ ++ goto _return; ++ ++_return: ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ return _errno; ++} ++module_init(mac_load); ++ ++static void __exit __cold mac_unload(void) ++{ ++ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ platform_driver_unregister(&mac_driver); ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++} ++module_exit(mac_unload); +diff --git a/drivers/net/dpa/mac.h b/drivers/net/dpa/mac.h +new file mode 100644 +index 0000000..5cdb57c +--- /dev/null ++++ b/drivers/net/dpa/mac.h +@@ -0,0 +1,110 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __MAC_H ++#define __MAC_H ++ ++#include /* struct device, BUS_ID_SIZE */ ++#include /* ETH_ALEN */ ++#include /* phy_interface_t, struct phy_device */ ++#include ++ ++#include "fsl_fman.h" /* struct port_device */ ++ ++enum {DTSEC, XGMAC, MEMAC}; ++ ++struct mac_device { ++ struct device *dev; ++ void *priv; ++ uint8_t cell_index; ++ struct resource *res; ++ void *vaddr; ++ uint8_t addr[ETH_ALEN]; ++ bool promisc; ++ ++ struct fm *fm_dev; ++ struct fm_port *port_dev[2]; ++ ++ phy_interface_t phy_if; ++ u32 if_support; ++ bool link; ++ bool half_duplex; ++ uint16_t speed; ++ uint16_t max_speed; ++ struct device_node *phy_node; ++ char fixed_bus_id[MII_BUS_ID_SIZE + 3]; ++ struct device_node *tbi_node; ++ struct phy_device *phy_dev; ++ void *fm; ++ /* List of multicast addresses */ ++ struct list_head mc_addr_list; ++ ++ int (*init_phy)(struct net_device *net_dev); ++ int (*init)(struct mac_device *mac_dev); ++ int (*start)(struct mac_device *mac_dev); ++ int (*stop)(struct mac_device *mac_dev); ++ int (*change_promisc)(struct mac_device *mac_dev); ++ int (*change_addr)(struct mac_device *mac_dev, uint8_t *addr); ++ int (*set_multi)(struct net_device *net_dev); ++ int (*uninit)(struct mac_device *mac_dev); ++ int (*ptp_enable)(struct mac_device *mac_dev); ++ int (*ptp_disable)(struct mac_device *mac_dev); ++ void *(*get_mac_handle)(struct mac_device *mac_dev); ++ int (*fm_rtc_enable)(struct net_device *net_dev); ++ int (*fm_rtc_disable)(struct net_device *net_dev); ++ int (*fm_rtc_get_cnt)(struct net_device *net_dev, uint64_t *ts); ++ int (*fm_rtc_set_cnt)(struct net_device *net_dev, uint64_t ts); ++ int (*fm_rtc_get_drift)(struct net_device *net_dev, uint32_t *drift); ++ int (*fm_rtc_set_drift)(struct net_device *net_dev, uint32_t drift); ++ int (*fm_rtc_set_alarm)(struct net_device *net_dev, uint32_t id, ++ uint64_t time); ++ int (*fm_rtc_set_fiper)(struct net_device *net_dev, uint32_t id, ++ uint64_t fiper); ++}; ++ ++struct mac_address { ++ uint8_t addr[ETH_ALEN]; ++ struct list_head list; ++}; ++ ++#define for_each_port_device(i, port_dev) \ ++ for (i = 0; i < ARRAY_SIZE(port_dev); i++) ++ ++static inline void * __attribute((nonnull)) macdev_priv(const struct mac_device *mac_dev) ++{ ++ return (void *)mac_dev + sizeof(*mac_dev); ++} ++ ++extern const char *mac_driver_description; ++extern const size_t mac_sizeof_priv[]; ++extern void (*const mac_setup[])(struct mac_device *mac_dev); ++ ++#endif /* __MAC_H */ +diff --git a/drivers/net/dpa/memac_mdio.c b/drivers/net/dpa/memac_mdio.c +new file mode 100644 +index 0000000..5d27ea3 +--- /dev/null ++++ b/drivers/net/dpa/memac_mdio.c +@@ -0,0 +1,322 @@ ++ /* ++ * This file is licensed under the terms of the GNU ++ * General Public License version 2. ++ * This program is licensed "as is" without any warranty of any kind, ++ * whether express or implied. ++ * ++ * QorIQ MEMAC MDIO Controller ++ * ++ * Authors: Sandeep Singh ++ * Andy Fleming ++ * Roy Zang ++ * ++ * Based on memac mdio code from uboot: drivers/net/fm/memac_phy.c ++ */ ++ ++#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 memac_mdio_controller { ++ u32 res0[0xc]; ++ u32 mdio_stat; /* MDIO configuration and status */ ++ u32 mdio_ctl; /* MDIO control */ ++ u32 mdio_data; /* MDIO data */ ++ u32 mdio_addr; /* MDIO address */ ++} __packed; ++ ++#define MDIO_STAT_CLKDIV(x) (((x>>1) & 0xff) << 8) ++#define MDIO_STAT_BSY (1 << 0) ++#define MDIO_STAT_RD_ER (1 << 1) ++#define MDIO_CTL_DEV_ADDR(x) (x & 0x1f) ++#define MDIO_CTL_PORT_ADDR(x) ((x & 0x1f) << 5) ++#define MDIO_CTL_PRE_DIS (1 << 10) ++#define MDIO_CTL_SCAN_EN (1 << 11) ++#define MDIO_CTL_POST_INC (1 << 14) ++#define MDIO_CTL_READ (1 << 15) ++#define MDIO_STAT_ENC (1 << 6) ++#define MDIO_STAT_HOLD_15_CLK (7 << 2) ++ ++#define MDIO_DATA(x) (x & 0xffff) ++#define MDIO_DATA_BSY (1 << 31) ++ ++/* Number of microseconds to wait for an MII register to respond */ ++#define MII_TIMEOUT 1000 ++ ++int memac_mdio_write(struct mii_bus *bus, int port_addr, ++ int dev_addr, int regnum, u16 value) ++{ ++ struct memac_mdio_controller __iomem *regs = bus->priv; ++ u32 mdio_ctl, mdio_stat; ++ int status; ++ ++ mdio_stat = in_be32(®s->mdio_stat); ++ if (bus->is_c45) { ++ if (dev_addr == MDIO_DEVAD_NONE) ++ return 0xffff; ++ mdio_stat = mdio_stat | MDIO_STAT_ENC | MDIO_STAT_HOLD_15_CLK; ++ } else { ++ /* Clause 22 */ ++ dev_addr = regnum & 0x1f; ++ mdio_stat = mdio_stat & ~MDIO_STAT_ENC; ++ } ++ ++ out_be32(®s->mdio_stat, mdio_stat); ++ ++ /* Wait till the bus is free */ ++ status = spin_event_timeout(!(in_be32(®s->mdio_stat) ++ & MDIO_STAT_BSY), MII_TIMEOUT, 0); ++ if (!status) { ++ dev_err(&bus->dev, "Timeout waiting for MII bus\n"); ++ return -ETIMEDOUT; ++ } ++ ++ /* Set the port and dev addr */ ++ mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr); ++ out_be32(®s->mdio_ctl, mdio_ctl); ++ ++ /* Set the register address */ ++ if (bus->is_c45) { ++ status = spin_event_timeout(!(in_be32(®s->mdio_stat) ++ & MDIO_STAT_BSY), MII_TIMEOUT, 0); ++ if (!status) { ++ dev_err(&bus->dev, "Timeout waiting for MII bus\n"); ++ return -ETIMEDOUT; ++ } ++ out_be32(®s->mdio_addr, regnum & 0xffff); ++ } ++ ++ /* Wait till the bus is free */ ++ status = spin_event_timeout(!(in_be32(®s->mdio_stat) ++ & MDIO_STAT_BSY), MII_TIMEOUT, 0); ++ if (!status) { ++ dev_err(&bus->dev, "Timeout waiting for MII bus\n"); ++ return -ETIMEDOUT; ++ } ++ ++ /* Write the value to the register */ ++ out_be32(®s->mdio_data, MDIO_DATA(value)); ++ ++ /* Wait till the MDIO write is complete */ ++ status = spin_event_timeout(!(in_be32(®s->mdio_stat) ++ & MDIO_DATA_BSY), MII_TIMEOUT, 0); ++ if (!status) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ ++ ++int memac_mdio_read(struct mii_bus *bus, int port_addr, int dev_addr, ++ int regnum) ++{ ++ struct memac_mdio_controller __iomem *regs = bus->priv; ++ u32 mdio_ctl, mdio_stat; ++ int status; ++ ++ mdio_stat = in_be32(®s->mdio_stat); ++ if (bus->is_c45) { ++ if (dev_addr == MDIO_DEVAD_NONE) ++ return 0xffff; ++ mdio_stat = mdio_stat | MDIO_STAT_ENC | MDIO_STAT_HOLD_15_CLK; ++ } else { ++ /* Clause 22 */ ++ dev_addr = regnum & 0x1f; ++ mdio_stat = mdio_stat & ~MDIO_STAT_ENC; ++ } ++ ++ out_be32(®s->mdio_stat, mdio_stat); ++ ++ /* Wait till the bus is free */ ++ status = spin_event_timeout(!(in_be32(®s->mdio_stat) ++ & MDIO_STAT_BSY), MII_TIMEOUT, 0); ++ if (!status) ++ return -ETIMEDOUT; ++ ++ /* Set the Port and Device Addrs */ ++ mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr); ++ out_be32(®s->mdio_ctl, mdio_ctl); ++ ++ /* Set the register address */ ++ if (bus->is_c45) { ++ status = spin_event_timeout(!(in_be32(®s->mdio_stat) ++ & MDIO_STAT_BSY), MII_TIMEOUT, 0); ++ if (!status) { ++ dev_err(&bus->dev, "Timeout waiting for MII bus\n"); ++ return -ETIMEDOUT; ++ } ++ out_be32(®s->mdio_addr, regnum & 0xffff); ++ } ++ ++ /* Wait till the bus is free */ ++ status = spin_event_timeout(!(in_be32(®s->mdio_stat) ++ & MDIO_STAT_BSY), MII_TIMEOUT, 0); ++ if (!status) { ++ dev_err(&bus->dev, "Timeout waiting for MII bus\n"); ++ return -ETIMEDOUT; ++ } ++ ++ /* Initiate the read */ ++ mdio_ctl |= MDIO_CTL_READ; ++ out_be32(®s->mdio_ctl, mdio_ctl); ++ ++ /* Wait till the MDIO write is complete */ ++ status = spin_event_timeout(!(in_be32(®s->mdio_stat) ++ & MDIO_STAT_BSY), MII_TIMEOUT, 0); ++ if (!status) { ++ dev_err(&bus->dev, "Timeout waiting for MII bus\n"); ++ return -ETIMEDOUT; ++ } ++ ++ /* Return all Fs if nothing was there */ ++ if (in_be32(®s->mdio_stat) & MDIO_STAT_RD_ER) ++ return 0xffff; ++ ++ return in_be32(®s->mdio_data) & 0xffff; ++} ++ ++ ++/* Reset the MIIM registers, and wait for the bus to free */ ++static int memac_mdio_reset(struct mii_bus *bus) ++{ ++ struct memac_mdio_controller __iomem *regs = bus->priv; ++ int status; ++ ++ clrbits32(®s->mdio_stat, MDIO_STAT_ENC); ++ ++ /* Wait till the bus is free */ ++ status = spin_event_timeout(!(in_be32(®s->mdio_stat) ++ & MDIO_STAT_BSY), MII_TIMEOUT, 0); ++ ++ if (!status) { ++ dev_err(&bus->dev, "Timeout waiting for MII bus\n"); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++ ++static int memac_mdio_probe(struct platform_device *ofdev) ++{ ++ struct memac_mdio_controller __iomem *regs; ++ struct device_node *np = ofdev->dev.of_node; ++ struct mii_bus *new_bus; ++ u64 addr, size; ++ int err = 0; ++ ++ new_bus = mdiobus_alloc(); ++ if (NULL == new_bus) ++ return -ENOMEM; ++ ++ new_bus->name = "Freescale MEMAC MDIO Bus"; ++ new_bus->read = &memac_mdio_read; ++ new_bus->write = &memac_mdio_write; ++ new_bus->reset = &memac_mdio_reset; ++ ++ /* Set the PHY base address */ ++ addr = of_translate_address(np, of_get_address(np, 0, &size, NULL)); ++ regs = ioremap(addr, size); ++ ++ if (NULL == regs) { ++ err = -ENOMEM; ++ goto err_ioremap; ++ } ++ ++ new_bus->priv = (void *)regs; ++ ++ new_bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); ++ ++ if (NULL == new_bus->irq) { ++ err = -ENOMEM; ++ goto err_irq_alloc; ++ } ++ ++ new_bus->parent = &ofdev->dev; ++ dev_set_drvdata(&ofdev->dev, new_bus); ++ ++ sprintf(new_bus->id, "%s@%llx", np->name, (unsigned long long)addr); ++ ++ err = of_mdiobus_register(new_bus, np); ++ ++ if (err) { ++ dev_err(&ofdev->dev, "%s: Cannot register as MDIO bus\n", ++ new_bus->name); ++ goto err_registration; ++ } ++ ++ return 0; ++ ++err_registration: ++ kfree(new_bus->irq); ++err_irq_alloc: ++ iounmap(regs); ++err_ioremap: ++ return err; ++} ++ ++ ++static int memac_mdio_remove(struct platform_device *ofdev) ++{ ++ struct device *device = &ofdev->dev; ++ struct mii_bus *bus = dev_get_drvdata(device); ++ ++ mdiobus_unregister(bus); ++ ++ dev_set_drvdata(device, NULL); ++ ++ iounmap((void __iomem *)bus->priv); ++ bus->priv = NULL; ++ mdiobus_free(bus); ++ ++ return 0; ++} ++ ++static struct of_device_id memac_mdio_match[] = { ++ { ++ .compatible = "fsl,fman-memac-mdio", ++ }, ++ {}, ++}; ++ ++static struct platform_driver memac_mdio_driver = { ++ .driver = { ++ .name = "fsl-fman-memac-mdio", ++ .of_match_table = memac_mdio_match, ++ }, ++ .probe = memac_mdio_probe, ++ .remove = memac_mdio_remove, ++}; ++ ++int __init memac_mdio_init(void) ++{ ++ return platform_driver_register(&memac_mdio_driver); ++} ++ ++void memac_mdio_exit(void) ++{ ++ platform_driver_unregister(&memac_mdio_driver); ++} ++subsys_initcall_sync(memac_mdio_init); ++module_exit(memac_mdio_exit); +diff --git a/drivers/net/dpa/offline_port.c b/drivers/net/dpa/offline_port.c +new file mode 100644 +index 0000000..691cd48 +--- /dev/null ++++ b/drivers/net/dpa/offline_port.c +@@ -0,0 +1,349 @@ ++/* ++ * Copyright 2011-2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ */ ++ ++/* ++ * Offline Parsing / Host Command port driver for FSL QorIQ FMan. ++ * Validates device-tree configuration and sets up the offline ports. ++ */ ++ ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++ ++#include ++#include ++#include ++ ++#include "offline_port.h" ++#include "dpaa_eth-common.h" ++ ++#define OH_MOD_DESCRIPTION "FSL FMan Offline Parsing port driver" ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_AUTHOR("Bogdan Hamciuc "); ++MODULE_DESCRIPTION(OH_MOD_DESCRIPTION); ++ ++ ++static const struct of_device_id oh_port_match_table[] __devinitconst = { ++ { ++ .compatible = "fsl,dpa-oh" ++ }, ++ { ++ .compatible = "fsl,dpa-oh-shared" ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, oh_port_match_table); ++ ++static int oh_port_remove(struct platform_device *_of_dev); ++static int oh_port_probe(struct platform_device *_of_dev); ++ ++static struct platform_driver oh_port_driver = { ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .of_match_table = oh_port_match_table, ++ .owner = THIS_MODULE, ++ }, ++ .probe = oh_port_probe, ++ .remove = __devexit_p(oh_port_remove) ++}; ++ ++/* Allocation code for the OH port's PCD frame queues */ ++static int __devinit __cold oh_alloc_pcd_fqids(struct device *dev, ++ uint32_t num, ++ uint8_t alignment, ++ uint32_t *base_fqid) ++{ ++ dev_crit(dev, "callback not implemented!\n"); ++ BUG(); ++ ++ return 0; ++} ++ ++static int __devinit __cold oh_free_pcd_fqids(struct device *dev, uint32_t base_fqid) ++{ ++ dev_crit(dev, "callback not implemented!\n"); ++ BUG(); ++ ++ return 0; ++} ++ ++static int __devinit ++oh_port_probe(struct platform_device *_of_dev) ++{ ++ struct device *dpa_oh_dev; ++ struct device_node *dpa_oh_node; ++ int lenp, _errno = 0, fq_idx; ++ const phandle *oh_port_handle; ++ struct platform_device *oh_of_dev; ++ struct device_node *oh_node; ++ struct device *oh_dev; ++ struct dpa_oh_config_s *oh_config; ++ uint32_t *oh_all_queues; ++ uint32_t queues_count; ++ uint32_t crt_fqid_base; ++ uint32_t crt_fq_count; ++ struct fm_port_params oh_port_tx_params; ++ struct fm_port_pcd_param oh_port_pcd_params; ++ /* True if the current partition owns the OH port. */ ++ bool init_oh_port; ++ const struct of_device_id *match; ++ ++ dpa_oh_dev = &_of_dev->dev; ++ dpa_oh_node = dpa_oh_dev->of_node; ++ BUG_ON(dpa_oh_node == NULL); ++ ++ match = of_match_device(oh_port_match_table, dpa_oh_dev); ++ if (!match) ++ return -EINVAL; ++ ++ dev_dbg(dpa_oh_dev, "Probing OH port...\n"); ++ ++ /* ++ * Find the referenced OH node ++ */ ++ ++ oh_port_handle = of_get_property(dpa_oh_node, ++ "fsl,fman-oh-port", &lenp); ++ if (oh_port_handle == NULL) { ++ dev_err(dpa_oh_dev, "No OH port handle found in node %s\n", ++ dpa_oh_node->full_name); ++ return -EINVAL; ++ } ++ ++ BUG_ON(lenp % sizeof(*oh_port_handle)); ++ if (lenp != sizeof(*oh_port_handle)) { ++ dev_err(dpa_oh_dev, "Found %lu OH port bindings in node %s," ++ " only 1 phandle is allowed.\n", ++ (unsigned long int)(lenp / sizeof(*oh_port_handle)), ++ dpa_oh_node->full_name); ++ return -EINVAL; ++ } ++ ++ /* Read configuration for the OH port */ ++ oh_node = of_find_node_by_phandle(*oh_port_handle); ++ if (oh_node == NULL) { ++ dev_err(dpa_oh_dev, "Can't find OH node referenced from " ++ "node %s\n", dpa_oh_node->full_name); ++ return -EINVAL; ++ } ++ dev_info(dpa_oh_dev, "Found OH node handle compatible with %s.\n", ++ match->compatible); ++ ++ oh_of_dev = of_find_device_by_node(oh_node); ++ BUG_ON(oh_of_dev == NULL); ++ oh_dev = &oh_of_dev->dev; ++ of_node_put(oh_node); ++ ++ /* ++ * The OH port must be initialized exactly once. ++ * The following scenarios are of interest: ++ * - the node is Linux-private (will always initialize it); ++ * - the node is shared between two Linux partitions ++ * (only one of them will initialize it); ++ * - the node is shared between a Linux and a LWE partition ++ * (Linux will initialize it) - "fsl,dpa-oh-shared" ++ */ ++ ++ /* Check if the current partition owns the OH port ++ * and ought to initialize it. It may be the case that we leave this ++ * to another (also Linux) partition. */ ++ init_oh_port = strcmp(match->compatible, "fsl,dpa-oh-shared"); ++ ++ /* If we aren't the "owner" of the OH node, we're done here. */ ++ if (!init_oh_port) { ++ dev_dbg(dpa_oh_dev, "Not owning the shared OH port %s, " ++ "will not initialize it.\n", oh_node->full_name); ++ return 0; ++ } ++ ++ /* Allocate OH dev private data */ ++ oh_config = devm_kzalloc(dpa_oh_dev, sizeof(*oh_config), GFP_KERNEL); ++ if (oh_config == NULL) { ++ dev_err(dpa_oh_dev, "Can't allocate private data for " ++ "OH node %s referenced from node %s!\n", ++ oh_node->full_name, dpa_oh_node->full_name); ++ return -ENOMEM; ++ } ++ ++ /* ++ * Read FQ ids/nums for the DPA OH node ++ */ ++ oh_all_queues = (uint32_t *)of_get_property(dpa_oh_node, ++ "fsl,qman-frame-queues-oh", &lenp); ++ if (oh_all_queues == NULL) { ++ dev_err(dpa_oh_dev, "No frame queues have been " ++ "defined for OH node %s referenced from node %s\n", ++ oh_node->full_name, dpa_oh_node->full_name); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ ++ /* Check that the OH error and default FQs are there */ ++ BUG_ON(lenp % (2 * sizeof(*oh_all_queues))); ++ queues_count = lenp / (2 * sizeof(*oh_all_queues)); ++ if (queues_count != 2) { ++ dev_err(dpa_oh_dev, "Error and Default queues must be " ++ "defined for OH node %s referenced from node %s\n", ++ oh_node->full_name, dpa_oh_node->full_name); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ ++ /* Read the FQIDs defined for this OH port */ ++ dev_dbg(dpa_oh_dev, "Reading %d queues...\n", queues_count); ++ fq_idx = 0; ++ ++ /* Error FQID - must be present */ ++ crt_fqid_base = oh_all_queues[fq_idx++]; ++ crt_fq_count = oh_all_queues[fq_idx++]; ++ if (crt_fq_count != 1) { ++ dev_err(dpa_oh_dev, "Only 1 Error FQ allowed in OH node %s " ++ "referenced from node %s (read: %d FQIDs).\n", ++ oh_node->full_name, dpa_oh_node->full_name, ++ crt_fq_count); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ oh_config->error_fqid = crt_fqid_base; ++ dev_dbg(dpa_oh_dev, "Read Error FQID 0x%x for OH port %s.\n", ++ oh_config->error_fqid, oh_node->full_name); ++ ++ /* Default FQID - must be present */ ++ crt_fqid_base = oh_all_queues[fq_idx++]; ++ crt_fq_count = oh_all_queues[fq_idx++]; ++ if (crt_fq_count != 1) { ++ dev_err(dpa_oh_dev, "Only 1 Default FQ allowed " ++ "in OH node %s referenced from %s (read: %d FQIDs).\n", ++ oh_node->full_name, dpa_oh_node->full_name, ++ crt_fq_count); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ oh_config->default_fqid = crt_fqid_base; ++ dev_dbg(dpa_oh_dev, "Read Default FQID 0x%x for OH port %s.\n", ++ oh_config->default_fqid, oh_node->full_name); ++ ++ /* Get a handle to the fm_port so we can set ++ * its configuration params */ ++ oh_config->oh_port = fm_port_bind(oh_dev); ++ if (oh_config->oh_port == NULL) { ++ dev_err(dpa_oh_dev, "NULL drvdata from fm port dev %s!\n", ++ oh_node->full_name); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ ++ /* Set Tx params */ ++ dpaa_eth_init_port(tx, oh_config->oh_port, oh_port_tx_params, ++ oh_config->error_fqid, oh_config->default_fqid, ++ DPA_TX_PRIV_DATA_SIZE, FALSE); ++ /* Set PCD params */ ++ oh_port_pcd_params.cba = oh_alloc_pcd_fqids; ++ oh_port_pcd_params.cbf = oh_free_pcd_fqids; ++ oh_port_pcd_params.dev = dpa_oh_dev; ++ fm_port_pcd_bind(oh_config->oh_port, &oh_port_pcd_params); ++ ++ dev_set_drvdata(dpa_oh_dev, oh_config); ++ ++ /* Enable the OH port */ ++ fm_port_enable(oh_config->oh_port); ++ dev_info(dpa_oh_dev, "OH port %s enabled.\n", oh_node->full_name); ++ ++ return 0; ++ ++return_kfree: ++ devm_kfree(dpa_oh_dev, oh_config); ++ return _errno; ++} ++ ++static int __devexit __cold oh_port_remove(struct platform_device *_of_dev) ++{ ++ int _errno = 0; ++ struct dpa_oh_config_s *oh_config; ++ ++ pr_info("Removing OH port...\n"); ++ ++ oh_config = dev_get_drvdata(&_of_dev->dev); ++ if (oh_config == NULL) { ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): No OH config in device private data!\n", ++ KBUILD_BASENAME".c", __LINE__, __func__); ++ _errno = -ENODEV; ++ goto return_error; ++ } ++ if (oh_config->oh_port == NULL) { ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): No fm port in device private data!\n", ++ KBUILD_BASENAME".c", __LINE__, __func__); ++ _errno = -EINVAL; ++ goto return_error; ++ } ++ ++ fm_port_disable(oh_config->oh_port); ++ devm_kfree(&_of_dev->dev, oh_config); ++ dev_set_drvdata(&_of_dev->dev, NULL); ++ ++return_error: ++ return _errno; ++} ++ ++static int __init __cold oh_port_load(void) ++{ ++ int _errno; ++ ++ pr_info(KBUILD_MODNAME ": " OH_MOD_DESCRIPTION " (" VERSION ")\n"); ++ ++ _errno = platform_driver_register(&oh_port_driver); ++ if (_errno < 0) { ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): platform_driver_register() = %d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, _errno); ++ } ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++ return _errno; ++} ++module_init(oh_port_load); ++ ++static void __exit __cold oh_port_unload(void) ++{ ++ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ platform_driver_unregister(&oh_port_driver); ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++} ++module_exit(oh_port_unload); +diff --git a/drivers/net/dpa/offline_port.h b/drivers/net/dpa/offline_port.h +new file mode 100644 +index 0000000..1b1a63f +--- /dev/null ++++ b/drivers/net/dpa/offline_port.h +@@ -0,0 +1,45 @@ ++/* ++ * Copyright 2011 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 __OFFLINE_PORT_H ++#define __OFFLINE_PORT_H ++ ++#include "fsl_fman.h" ++ ++/* OH port configuration */ ++struct dpa_oh_config_s { ++ uint32_t error_fqid; ++ uint32_t default_fqid; ++ struct fm_port *oh_port; ++}; ++ ++#endif /* __OFFLINE_PORT_H */ +diff --git a/drivers/net/dpa/xgmac_mdio.c b/drivers/net/dpa/xgmac_mdio.c +new file mode 100644 +index 0000000..a66c6be +--- /dev/null ++++ b/drivers/net/dpa/xgmac_mdio.c +@@ -0,0 +1,286 @@ ++/* Copyright 2009-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ * ++ * QorIQ 10-G MDIO Controller ++ * ++ * Author: Andy Fleming ++ * ++ * Based on fsl_pq_mdio.c ++ */ ++ ++#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 "xgmac_mdio.h" ++ ++/* Write value to the PHY for this device to the register at regnum, */ ++/* waiting until the write is done before it returns. All PHY */ ++/* configuration has to be done through the TSEC1 MIIM regs */ ++int xgmac_mdio_write(struct mii_bus *bus, int port_addr, ++ int dev_addr, int regnum, u16 value) ++{ ++ struct tgec_mdio_controller __iomem *regs = bus->priv; ++ u32 mdio_ctl, mdio_stat; ++ ++ if (dev_addr == MDIO_DEVAD_NONE) ++ return 0xffff; ++ ++ /* Setup the MII Mgmt clock speed */ ++ mdio_stat = MDIO_STAT_CLKDIV(100); ++ out_be32(®s->mdio_stat, mdio_stat); ++ ++ /* Wait till the bus is free */ ++ while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) ++ cpu_relax(); ++ ++ /* Set the port and dev addr */ ++ mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr); ++ out_be32(®s->mdio_ctl, mdio_ctl); ++ ++ /* Set the register address */ ++ out_be32(®s->mdio_addr, regnum & 0xffff); ++ ++ /* Wait till the bus is free */ ++ while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) ++ cpu_relax(); ++ ++ /* Write the value to the register */ ++ out_be32(®s->mdio_data, MDIO_DATA(value)); ++ ++ /* Wait till the MDIO write is complete */ ++ while ((in_be32(®s->mdio_data)) & MDIO_DATA_BSY) ++ cpu_relax(); ++ ++ return 0; ++} ++ ++ ++/* Reads from register regnum in the PHY for device dev, */ ++/* returning the value. Clears miimcom first. All PHY */ ++/* configuration has to be done through the TSEC1 MIIM regs */ ++int xgmac_mdio_read(struct mii_bus *bus, int port_addr, int dev_addr, ++ int regnum) ++{ ++ struct tgec_mdio_controller __iomem *regs = bus->priv; ++ u32 mdio_ctl, mdio_stat; ++ ++ /* Setup the MII Mgmt clock speed */ ++ mdio_stat = MDIO_STAT_CLKDIV(100); ++ out_be32(®s->mdio_stat, mdio_stat); ++ ++ /* Wait till the bus is free */ ++ while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) ++ cpu_relax(); ++ ++ /* Set the Port and Device Addrs */ ++ mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr); ++ out_be32(®s->mdio_ctl, mdio_ctl); ++ ++ /* Set the register address */ ++ out_be32(®s->mdio_addr, regnum & 0xffff); ++ ++ /* Wait till the bus is free */ ++ while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) ++ cpu_relax(); ++ ++ /* Initiate the read */ ++ mdio_ctl |= MDIO_CTL_READ; ++ out_be32(®s->mdio_ctl, mdio_ctl); ++ ++ /* Wait till the MDIO write is complete */ ++ while ((in_be32(®s->mdio_data)) & MDIO_DATA_BSY) ++ cpu_relax(); ++ ++ /* Return all Fs if nothing was there */ ++ if (in_be32(®s->mdio_stat) & MDIO_STAT_RD_ER) ++ return 0xffff; ++ ++ return in_be32(®s->mdio_data) & 0xffff; ++} ++ ++ ++/* Reset the MIIM registers, and wait for the bus to free */ ++static int xgmac_mdio_reset(struct mii_bus *bus) ++{ ++ struct tgec_mdio_controller __iomem *regs = bus->priv; ++ int timeout = PHY_INIT_TIMEOUT; ++ u32 mdio_stat; ++ ++ mutex_lock(&bus->mdio_lock); ++ ++ /* Setup the MII Mgmt clock speed */ ++ mdio_stat = MDIO_STAT_CLKDIV(100); ++ out_be32(®s->mdio_stat, mdio_stat); ++ ++ /* Wait till the bus is free */ ++ while (((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) && timeout--) ++ cpu_relax(); ++ ++ mutex_unlock(&bus->mdio_lock); ++ ++ if (timeout < 0) { ++ printk(KERN_ERR "%s: The MII Bus is stuck!\n", ++ bus->name); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++ ++static int xgmac_mdio_probe(struct platform_device *ofdev) ++{ ++ struct tgec_mdio_controller __iomem *regs; ++ struct device_node *np = ofdev->dev.of_node; ++ struct mii_bus *new_bus; ++ u64 addr, size; ++ int err = 0; ++ ++ if (!of_device_is_available(np)) ++ return -ENODEV; ++ ++ new_bus = mdiobus_alloc(); ++ if (NULL == new_bus) ++ return -ENOMEM; ++ ++ new_bus->name = "Freescale XGMAC MDIO Bus", ++ new_bus->read = &xgmac_mdio_read, ++ new_bus->write = &xgmac_mdio_write, ++ new_bus->reset = &xgmac_mdio_reset, ++ ++ /* Set the PHY base address */ ++ addr = of_translate_address(np, of_get_address(np, 0, &size, NULL)); ++ regs = ioremap(addr, size); ++ ++ if (NULL == regs) { ++ err = -ENOMEM; ++ goto err_ioremap; ++ } ++ ++ new_bus->priv = (void __force *)regs; ++ ++ new_bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); ++ ++ if (NULL == new_bus->irq) { ++ err = -ENOMEM; ++ goto err_irq_alloc; ++ } ++ ++ new_bus->parent = &ofdev->dev; ++ dev_set_drvdata(&ofdev->dev, new_bus); ++ ++ sprintf(new_bus->id, "%s@%llx", np->name, (unsigned long long)addr); ++ ++ err = of_mdiobus_register(new_bus, np); ++ ++ if (err) { ++ printk(KERN_ERR "%s: Cannot register as MDIO bus\n", ++ new_bus->name); ++ goto err_registration; ++ } ++ ++ return 0; ++ ++err_registration: ++ kfree(new_bus->irq); ++err_irq_alloc: ++ iounmap(regs); ++err_ioremap: ++ return err; ++} ++ ++ ++static int xgmac_mdio_remove(struct platform_device *ofdev) ++{ ++ struct device *device = &ofdev->dev; ++ struct mii_bus *bus = dev_get_drvdata(device); ++ ++ mdiobus_unregister(bus); ++ ++ dev_set_drvdata(device, NULL); ++ ++ iounmap((void __iomem *)bus->priv); ++ bus->priv = NULL; ++ mdiobus_free(bus); ++ ++ return 0; ++} ++ ++static struct of_device_id xgmac_mdio_match[] = { ++ { ++ .compatible = "fsl,fman-xmdio", ++ }, ++ {}, ++}; ++ ++static struct platform_driver xgmac_mdio_driver = { ++ .driver = { ++ .name = "fsl-fman_xmdio", ++ .of_match_table = xgmac_mdio_match, ++ }, ++ .probe = xgmac_mdio_probe, ++ .remove = xgmac_mdio_remove, ++}; ++ ++int __init xgmac_mdio_init(void) ++{ ++ return platform_driver_register(&xgmac_mdio_driver); ++} ++ ++void xgmac_mdio_exit(void) ++{ ++ platform_driver_unregister(&xgmac_mdio_driver); ++} ++subsys_initcall_sync(xgmac_mdio_init); ++module_exit(xgmac_mdio_exit); +diff --git a/drivers/net/dpa/xgmac_mdio.h b/drivers/net/dpa/xgmac_mdio.h +new file mode 100644 +index 0000000..6eb49cd +--- /dev/null ++++ b/drivers/net/dpa/xgmac_mdio.h +@@ -0,0 +1,61 @@ ++/* Copyright 2009-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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. ++ * ++ * Freescale FMAN XGMAC MDIO Driver -- MDIO Management Bus Implementation ++ * Driver for the MDIO bus controller on QorIQ 10G ports ++ * ++ * Author: Andy Fleming ++ */ ++ ++#ifndef __XGMAC_MDIO_H ++#define __XGMAC_MDIO_H ++ ++struct tgec_mdio_controller { ++ u32 res0[0xc]; ++ u32 mdio_stat; /* MDIO configuration and status */ ++ u32 mdio_ctl; /* MDIO control */ ++ u32 mdio_data; /* MDIO data */ ++ u32 mdio_addr; /* MDIO address */ ++} __attribute__ ((packed)); ++ ++#define MDIO_STAT_CLKDIV(x) (((x>>1) & 0xff) << 8) ++#define MDIO_STAT_BSY (1 << 0) ++#define MDIO_STAT_RD_ER (1 << 1) ++#define MDIO_CTL_DEV_ADDR(x) (x & 0x1f) ++#define MDIO_CTL_PORT_ADDR(x) ((x & 0x1f) << 5) ++#define MDIO_CTL_PRE_DIS (1 << 10) ++#define MDIO_CTL_SCAN_EN (1 << 11) ++#define MDIO_CTL_POST_INC (1 << 14) ++#define MDIO_CTL_READ (1 << 15) ++ ++#define MDIO_DATA(x) (x & 0xffff) ++#define MDIO_DATA_BSY (1 << 31) ++ ++#endif /* __XGMAC_MDIO_H */ +diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c +index 20ea075..4db636d 100644 +--- a/drivers/net/ethernet/3com/typhoon.c ++++ b/drivers/net/ethernet/3com/typhoon.c +@@ -1289,11 +1289,8 @@ typhoon_request_firmware(struct typhoon *tp) + return 0; + + err = request_firmware(&typhoon_fw, FIRMWARE_NAME, &tp->pdev->dev); +- if (err) { +- netdev_err(tp->dev, "Failed to load firmware \"%s\"\n", +- FIRMWARE_NAME); ++ if (err) + return err; +- } + + image_data = (u8 *) typhoon_fw->data; + remaining = typhoon_fw->size; +diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c +index 6d9f691..14e54fa 100644 +--- a/drivers/net/ethernet/adaptec/starfire.c ++++ b/drivers/net/ethernet/adaptec/starfire.c +@@ -1044,11 +1044,8 @@ static int netdev_open(struct net_device *dev) + #endif /* VLAN_SUPPORT */ + + retval = request_firmware(&fw_rx, FIRMWARE_RX, &np->pci_dev->dev); +- if (retval) { +- printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n", +- FIRMWARE_RX); ++ if (retval) + goto out_init; +- } + if (fw_rx->size % 4) { + printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n", + fw_rx->size, FIRMWARE_RX); +@@ -1056,11 +1053,8 @@ static int netdev_open(struct net_device *dev) + goto out_rx; + } + retval = request_firmware(&fw_tx, FIRMWARE_TX, &np->pci_dev->dev); +- if (retval) { +- printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n", +- FIRMWARE_TX); ++ if (retval) + goto out_rx; +- } + if (fw_tx->size % 4) { + printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n", + fw_tx->size, FIRMWARE_TX); +diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c +index f872748..a196377 100644 +--- a/drivers/net/ethernet/alteon/acenic.c ++++ b/drivers/net/ethernet/alteon/acenic.c +@@ -2906,11 +2906,8 @@ static int __devinit ace_load_firmware(struct net_device *dev) + fw_name = "acenic/tg1.bin"; + + ret = request_firmware(&fw, fw_name, &ap->pdev->dev); +- if (ret) { +- printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n", +- ap->name, fw_name); ++ if (ret) + return ret; +- } + + fw_data = (void *)fw->data; + +diff --git a/drivers/net/ethernet/atheros/Kconfig b/drivers/net/ethernet/atheros/Kconfig +index 1ed886d..a6cac15 100644 +--- a/drivers/net/ethernet/atheros/Kconfig ++++ b/drivers/net/ethernet/atheros/Kconfig +@@ -63,8 +63,36 @@ config ATL1C + select MII + ---help--- + This driver supports the Atheros L1C gigabit ethernet adapter. ++ This driver supports the following chipsets: ++ ++ 1969:1063 - AR8131 Gigabit Ethernet ++ 1969:1062 - AR8132 Fast Ethernet (10/100 Mbit/s) ++ 1969:2062 - AR8152 v2.0 Fast Ethernet ++ 1969:2060 - AR8152 v1.1 Fast Ethernet ++ 1969:1073 - AR8151 v1.0 Gigabit Ethernet ++ 1969:1083 - AR8151 v2.0 Gigabit Ethernet + + To compile this driver as a module, choose M here. The module + will be called atl1c. + ++config ALX ++ tristate "Atheros ALX Gigabit Ethernet support" ++ depends on PCI ++ select CRC32 ++ select NET_CORE ++ select MII ++ ---help--- ++ This driver supports the Atheros L1C/L1D/L1F gigabit ethernet ++ adapter. alx supports the following chipsets: ++ ++ 1969:1091 - AR8161 ++ 1969:1090 - AR8162 ++ ++ For more information see: ++ ++ https://www.linuxfoundation.org/collaborate/workgroups/networking/alx ++ ++ To compile this driver as a module, choose M here. The module ++ will be called alx. ++ + endif # NET_VENDOR_ATHEROS +diff --git a/drivers/net/ethernet/atheros/Makefile b/drivers/net/ethernet/atheros/Makefile +index e7e76fb..5cf1c65 100644 +--- a/drivers/net/ethernet/atheros/Makefile ++++ b/drivers/net/ethernet/atheros/Makefile +@@ -6,3 +6,4 @@ obj-$(CONFIG_ATL1) += atlx/ + obj-$(CONFIG_ATL2) += atlx/ + obj-$(CONFIG_ATL1E) += atl1e/ + obj-$(CONFIG_ATL1C) += atl1c/ ++obj-$(CONFIG_ALX) += alx/ +diff --git a/drivers/net/ethernet/atheros/alx/Makefile b/drivers/net/ethernet/atheros/alx/Makefile +new file mode 100644 +index 0000000..9f607d3 +--- /dev/null ++++ b/drivers/net/ethernet/atheros/alx/Makefile +@@ -0,0 +1,3 @@ ++obj-$(CONFIG_ALX) += alx.o ++alx-objs := alx_main.o alx_ethtool.o alc_cb.o alc_hw.o alf_cb.o alf_hw.o ++ccflags-y += -D__CHECK_ENDIAN__ +diff --git a/drivers/net/ethernet/atheros/alx/alc_cb.c b/drivers/net/ethernet/atheros/alx/alc_cb.c +new file mode 100644 +index 0000000..8c42c3b +--- /dev/null ++++ b/drivers/net/ethernet/atheros/alx/alc_cb.c +@@ -0,0 +1,912 @@ ++/* ++ * Copyright (c) 2012 Qualcomm Atheros, Inc. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ */ ++ ++#include ++#include ++ ++#include "alc_hw.h" ++ ++ ++/* NIC */ ++static int alc_identify_nic(struct alx_hw *hw) ++{ ++ return 0; ++} ++ ++ ++/* PHY */ ++static int alc_read_phy_reg(struct alx_hw *hw, u16 reg_addr, u16 *phy_data) ++{ ++ unsigned long flags; ++ int retval = 0; ++ ++ spin_lock_irqsave(&hw->mdio_lock, flags); ++ ++ if (l1c_read_phy(hw, false, ALX_MDIO_DEV_TYPE_NORM, false, reg_addr, ++ phy_data)) { ++ alx_hw_err(hw, "error when read phy reg\n"); ++ retval = -EINVAL; ++ } ++ ++ spin_unlock_irqrestore(&hw->mdio_lock, flags); ++ return retval; ++} ++ ++ ++static int alc_write_phy_reg(struct alx_hw *hw, u16 reg_addr, u16 phy_data) ++{ ++ unsigned long flags; ++ int retval = 0; ++ ++ spin_lock_irqsave(&hw->mdio_lock, flags); ++ ++ if (l1c_write_phy(hw, false, ALX_MDIO_DEV_TYPE_NORM, false, reg_addr, ++ phy_data)) { ++ alx_hw_err(hw, "error when write phy reg\n"); ++ retval = -EINVAL; ++ } ++ ++ spin_unlock_irqrestore(&hw->mdio_lock, flags); ++ return retval; ++} ++ ++ ++static int alc_init_phy(struct alx_hw *hw) ++{ ++ u16 phy_id[2]; ++ int retval; ++ ++ spin_lock_init(&hw->mdio_lock); ++ ++ retval = alc_read_phy_reg(hw, MII_PHYSID1, &phy_id[0]); ++ if (retval) ++ return retval; ++ retval = alc_read_phy_reg(hw, MII_PHYSID2, &phy_id[1]); ++ if (retval) ++ return retval; ++ ++ memcpy(&hw->phy_id, phy_id, sizeof(hw->phy_id)); ++ ++ hw->autoneg_advertised = ALX_LINK_SPEED_1GB_FULL | ++ ALX_LINK_SPEED_10_HALF | ++ ALX_LINK_SPEED_10_FULL | ++ ALX_LINK_SPEED_100_HALF | ++ ALX_LINK_SPEED_100_FULL; ++ return retval; ++} ++ ++ ++static int alc_reset_phy(struct alx_hw *hw) ++{ ++ bool pws_en, az_en, ptp_en; ++ int retval = 0; ++ ++ pws_en = az_en = ptp_en = false; ++ CLI_HW_FLAG(PWSAVE_EN); ++ CLI_HW_FLAG(AZ_EN); ++ CLI_HW_FLAG(PTP_EN); ++ ++ if (CHK_HW_FLAG(PWSAVE_CAP)) { ++ pws_en = true; ++ SET_HW_FLAG(PWSAVE_EN); ++ } ++ ++ if (CHK_HW_FLAG(AZ_CAP)) { ++ az_en = true; ++ SET_HW_FLAG(AZ_EN); ++ } ++ ++ if (CHK_HW_FLAG(PTP_CAP)) { ++ ptp_en = true; ++ SET_HW_FLAG(PTP_EN); ++ } ++ ++ alx_hw_info(hw, "reset PHY, pws = %d, az = %d, ptp = %d\n", ++ pws_en, az_en, ptp_en); ++ ++ if (l1c_reset_phy(hw, pws_en, az_en, ptp_en)) { ++ alx_hw_err(hw, "error when reset phy\n"); ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++ ++/* LINK */ ++static int alc_setup_phy_link(struct alx_hw *hw, u32 speed, bool autoneg, ++ bool fc) ++{ ++ u8 link_cap = 0; ++ int retval = 0; ++ ++ alx_hw_info(hw, "speed = 0x%x, autoneg = %d\n", speed, autoneg); ++ if (speed & ALX_LINK_SPEED_1GB_FULL) ++ link_cap |= LX_LC_1000F; ++ ++ if (speed & ALX_LINK_SPEED_100_FULL) ++ link_cap |= LX_LC_100F; ++ ++ if (speed & ALX_LINK_SPEED_100_HALF) ++ link_cap |= LX_LC_100H; ++ ++ if (speed & ALX_LINK_SPEED_10_FULL) ++ link_cap |= LX_LC_10F; ++ ++ if (speed & ALX_LINK_SPEED_10_HALF) ++ link_cap |= LX_LC_10H; ++ ++ if (l1c_init_phy_spdfc(hw, autoneg, link_cap, fc)) { ++ alx_hw_err(hw, "error when init phy speed and fc\n"); ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++ ++static int alc_setup_phy_link_speed(struct alx_hw *hw, u32 speed, ++ bool autoneg, bool fc) ++{ ++ /* ++ * Clear autoneg_advertised and set new values based on input link ++ * speed. ++ */ ++ hw->autoneg_advertised = 0; ++ ++ if (speed & ALX_LINK_SPEED_1GB_FULL) ++ hw->autoneg_advertised |= ALX_LINK_SPEED_1GB_FULL; ++ ++ if (speed & ALX_LINK_SPEED_100_FULL) ++ hw->autoneg_advertised |= ALX_LINK_SPEED_100_FULL; ++ ++ if (speed & ALX_LINK_SPEED_100_HALF) ++ hw->autoneg_advertised |= ALX_LINK_SPEED_100_HALF; ++ ++ if (speed & ALX_LINK_SPEED_10_FULL) ++ hw->autoneg_advertised |= ALX_LINK_SPEED_10_FULL; ++ ++ if (speed & ALX_LINK_SPEED_10_HALF) ++ hw->autoneg_advertised |= ALX_LINK_SPEED_10_HALF; ++ ++ return alc_setup_phy_link(hw, hw->autoneg_advertised, ++ autoneg, fc); ++} ++ ++ ++static int alc_check_phy_link(struct alx_hw *hw, u32 *speed, bool *link_up) ++{ ++ u16 bmsr, giga; ++ int retval; ++ ++ alc_read_phy_reg(hw, MII_BMSR, &bmsr); ++ retval = alc_read_phy_reg(hw, MII_BMSR, &bmsr); ++ if (retval) ++ return retval; ++ ++ if (!(bmsr & BMSR_LSTATUS)) { ++ *link_up = false; ++ *speed = ALX_LINK_SPEED_UNKNOWN; ++ return 0; ++ } ++ *link_up = true; ++ ++ /* Read PHY Specific Status Register (17) */ ++ retval = alc_read_phy_reg(hw, L1C_MII_GIGA_PSSR, &giga); ++ if (retval) ++ return retval; ++ ++ ++ if (!(giga & L1C_GIGA_PSSR_SPD_DPLX_RESOLVED)) { ++ alx_hw_err(hw, "error for speed duplex resolved\n"); ++ return -EINVAL; ++ } ++ ++ switch (giga & L1C_GIGA_PSSR_SPEED) { ++ case L1C_GIGA_PSSR_1000MBS: ++ if (giga & L1C_GIGA_PSSR_DPLX) ++ *speed = ALX_LINK_SPEED_1GB_FULL; ++ else ++ alx_hw_err(hw, "1000M half is invalid\n"); ++ break; ++ case L1C_GIGA_PSSR_100MBS: ++ if (giga & L1C_GIGA_PSSR_DPLX) ++ *speed = ALX_LINK_SPEED_100_FULL; ++ else ++ *speed = ALX_LINK_SPEED_100_HALF; ++ break; ++ case L1C_GIGA_PSSR_10MBS: ++ if (giga & L1C_GIGA_PSSR_DPLX) ++ *speed = ALX_LINK_SPEED_10_FULL; ++ else ++ *speed = ALX_LINK_SPEED_10_HALF; ++ break; ++ default: ++ *speed = ALX_LINK_SPEED_UNKNOWN; ++ retval = -EINVAL; ++ break; ++ } ++ ++ return retval; ++} ++ ++ ++/* ++ * 1. stop_mac ++ * 2. reset mac & dma by reg1400(MASTER) ++ * 3. control speed/duplex, hash-alg ++ * 4. clock switch setting ++ */ ++static int alc_reset_mac(struct alx_hw *hw) ++{ ++ int retval = 0; ++ ++ if (l1c_reset_mac(hw)) { ++ alx_hw_err(hw, "error when reset mac\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++static int alc_start_mac(struct alx_hw *hw) ++{ ++ u16 en_ctrl = 0; ++ int retval = 0; ++ ++ /* set link speed param */ ++ switch (hw->link_speed) { ++ case ALX_LINK_SPEED_1GB_FULL: ++ en_ctrl |= LX_MACSPEED_1000; ++ /* fall through */ ++ case ALX_LINK_SPEED_100_FULL: ++ case ALX_LINK_SPEED_10_FULL: ++ en_ctrl |= LX_MACDUPLEX_FULL; ++ break; ++ } ++ ++ /* set fc param*/ ++ switch (hw->cur_fc_mode) { ++ case alx_fc_full: ++ en_ctrl |= LX_FC_RXEN; /* Flow Control RX Enable */ ++ en_ctrl |= LX_FC_TXEN; /* Flow Control TX Enable */ ++ break; ++ case alx_fc_rx_pause: ++ en_ctrl |= LX_FC_RXEN; /* Flow Control RX Enable */ ++ break; ++ case alx_fc_tx_pause: ++ en_ctrl |= LX_FC_TXEN; /* Flow Control TX Enable */ ++ break; ++ default: ++ break; ++ } ++ ++ if (hw->fc_single_pause) ++ en_ctrl |= LX_SINGLE_PAUSE; ++ ++ ++ en_ctrl |= LX_FLT_DIRECT; /* RX Enable; and TX Always Enable */ ++ en_ctrl |= LX_FLT_BROADCAST; /* RX Broadcast Enable */ ++ en_ctrl |= LX_ADD_FCS; ++ ++ if (CHK_HW_FLAG(VLANSTRIP_EN)) ++ en_ctrl |= LX_VLAN_STRIP; ++ ++ if (CHK_HW_FLAG(PROMISC_EN)) ++ en_ctrl |= LX_FLT_PROMISC; ++ ++ if (CHK_HW_FLAG(MULTIALL_EN)) ++ en_ctrl |= LX_FLT_MULTI_ALL; ++ ++ if (CHK_HW_FLAG(LOOPBACK_EN)) ++ en_ctrl |= LX_LOOPBACK; ++ ++ if (l1c_enable_mac(hw, true, en_ctrl)) { ++ alx_hw_err(hw, "error when start mac\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++/* ++ * 1. stop RXQ (reg15A0) and TXQ (reg1590) ++ * 2. stop MAC (reg1480) ++ */ ++static int alc_stop_mac(struct alx_hw *hw) ++{ ++ int retval = 0; ++ ++ if (l1c_enable_mac(hw, false, 0)) { ++ alx_hw_err(hw, "error when stop mac\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++static int alc_config_mac(struct alx_hw *hw, u16 rxbuf_sz, u16 rx_qnum, ++ u16 rxring_sz, u16 tx_qnum, u16 txring_sz) ++{ ++ u8 *addr; ++ ++ u32 txmem_hi, txmem_lo[4]; ++ ++ u32 rxmem_hi, rfdmem_lo, rrdmem_lo; ++ ++ u16 smb_timer, mtu_with_eth, int_mod; ++ bool hash_legacy; ++ ++ int i; ++ int retval = 0; ++ ++ addr = hw->mac_addr; ++ ++ txmem_hi = ALX_DMA_ADDR_HI(hw->tpdma[0]); ++ for (i = 0; i < tx_qnum; i++) ++ txmem_lo[i] = ALX_DMA_ADDR_LO(hw->tpdma[i]); ++ ++ ++ rxmem_hi = ALX_DMA_ADDR_HI(hw->rfdma[0]); ++ rfdmem_lo = ALX_DMA_ADDR_LO(hw->rfdma[0]); ++ rrdmem_lo = ALX_DMA_ADDR_LO(hw->rrdma[0]); ++ ++ ++ smb_timer = (u16)hw->smb_timer; ++ mtu_with_eth = hw->mtu + ALX_ETH_LENGTH_OF_HEADER; ++ int_mod = hw->imt; ++ ++ hash_legacy = true; ++ ++ if (l1c_init_mac(hw, addr, txmem_hi, txmem_lo, tx_qnum, txring_sz, ++ rxmem_hi, rfdmem_lo, rrdmem_lo, rxring_sz, rxbuf_sz, ++ smb_timer, mtu_with_eth, int_mod, hash_legacy)) { ++ alx_hw_err(hw, "error when config mac\n"); ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++ ++/** ++ * alc_get_mac_addr ++ * @hw: pointer to hardware structure ++ **/ ++static int alc_get_mac_addr(struct alx_hw *hw, u8 *addr) ++{ ++ int retval = 0; ++ ++ if (l1c_get_perm_macaddr(hw, addr)) { ++ alx_hw_err(hw, "error when get permanent mac address\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++static int alc_reset_pcie(struct alx_hw *hw, bool l0s_en, bool l1_en) ++{ ++ int retval = 0; ++ ++ if (!CHK_HW_FLAG(L0S_CAP)) ++ l0s_en = false; ++ ++ if (l0s_en) ++ SET_HW_FLAG(L0S_EN); ++ else ++ CLI_HW_FLAG(L0S_EN); ++ ++ ++ if (!CHK_HW_FLAG(L1_CAP)) ++ l1_en = false; ++ ++ if (l1_en) ++ SET_HW_FLAG(L1_EN); ++ else ++ CLI_HW_FLAG(L1_EN); ++ ++ if (l1c_reset_pcie(hw, l0s_en, l1_en)) { ++ alx_hw_err(hw, "error when reset pcie\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++static int alc_config_aspm(struct alx_hw *hw, bool l0s_en, bool l1_en) ++{ ++ u8 link_stat; ++ int retval = 0; ++ ++ if (!CHK_HW_FLAG(L0S_CAP)) ++ l0s_en = false; ++ ++ if (l0s_en) ++ SET_HW_FLAG(L0S_EN); ++ else ++ CLI_HW_FLAG(L0S_EN); ++ ++ if (!CHK_HW_FLAG(L1_CAP)) ++ l1_en = false; ++ ++ if (l1_en) ++ SET_HW_FLAG(L1_EN); ++ else ++ CLI_HW_FLAG(L1_EN); ++ ++ link_stat = hw->link_up ? LX_LC_ALL : 0; ++ if (l1c_enable_aspm(hw, l0s_en, l1_en, link_stat)) { ++ alx_hw_err(hw, "error when enable aspm\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++static int alc_config_wol(struct alx_hw *hw, u32 wufc) ++{ ++ u32 wol = 0; ++ ++ /* turn on magic packet event */ ++ if (wufc & ALX_WOL_MAGIC) { ++ wol |= L1C_WOL0_MAGIC_EN | L1C_WOL0_PME_MAGIC_EN; ++ if (hw->mac_type == alx_mac_l2cb_v1 && ++ hw->pci_revid == ALX_REV_ID_AR8152_V1_1) { ++ wol |= L1C_WOL0_PATTERN_EN | L1C_WOL0_PME_PATTERN_EN; ++ } ++ /* magic packet maybe Broadcast&multicast&Unicast frame ++ * move to l1c_powersaving ++ */ ++ } ++ ++ /* turn on link up event */ ++ if (wufc & ALX_WOL_PHY) { ++ wol |= L1C_WOL0_LINK_EN | L1C_WOL0_PME_LINK; ++ /* only link up can wake up */ ++ alc_write_phy_reg(hw, L1C_MII_IER, L1C_IER_LINK_UP); ++ } ++ ++ alx_mem_w32(hw, L1C_WOL0, wol); ++ return 0; ++} ++ ++ ++static int alc_config_mac_ctrl(struct alx_hw *hw) ++{ ++ u32 mac; ++ ++ alx_mem_r32(hw, L1C_MAC_CTRL, &mac); ++ ++ /* enable/disable VLAN tag insert,strip */ ++ if (CHK_HW_FLAG(VLANSTRIP_EN)) ++ mac |= L1C_MAC_CTRL_VLANSTRIP; ++ else ++ mac &= ~L1C_MAC_CTRL_VLANSTRIP; ++ ++ if (CHK_HW_FLAG(PROMISC_EN)) ++ mac |= L1C_MAC_CTRL_PROMISC_EN; ++ else ++ mac &= ~L1C_MAC_CTRL_PROMISC_EN; ++ ++ if (CHK_HW_FLAG(MULTIALL_EN)) ++ mac |= L1C_MAC_CTRL_MULTIALL_EN; ++ else ++ mac &= ~L1C_MAC_CTRL_MULTIALL_EN; ++ ++ if (CHK_HW_FLAG(LOOPBACK_EN)) ++ mac |= L1C_MAC_CTRL_LPBACK_EN; ++ else ++ mac &= ~L1C_MAC_CTRL_LPBACK_EN; ++ ++ alx_mem_w32(hw, L1C_MAC_CTRL, mac); ++ return 0; ++} ++ ++ ++static int alc_config_pow_save(struct alx_hw *hw, u32 speed, bool wol_en, ++ bool tx_en, bool rx_en, bool pws_en) ++{ ++ u8 wire_spd = LX_LC_10H; ++ int retval = 0; ++ ++ switch (speed) { ++ case ALX_LINK_SPEED_UNKNOWN: ++ case ALX_LINK_SPEED_10_HALF: ++ wire_spd = LX_LC_10H; ++ break; ++ case ALX_LINK_SPEED_10_FULL: ++ wire_spd = LX_LC_10F; ++ break; ++ case ALX_LINK_SPEED_100_HALF: ++ wire_spd = LX_LC_100H; ++ break; ++ case ALX_LINK_SPEED_100_FULL: ++ wire_spd = LX_LC_100F; ++ break; ++ case ALX_LINK_SPEED_1GB_FULL: ++ wire_spd = LX_LC_1000F; ++ break; ++ } ++ ++ if (l1c_powersaving(hw, wire_spd, wol_en, tx_en, rx_en, pws_en)) { ++ alx_hw_err(hw, "error when set power saving\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++/* RAR, Multicast, VLAN */ ++static int alc_set_mac_addr(struct alx_hw *hw, u8 *addr) ++{ ++ u32 sta; ++ ++ /* ++ * for example: 00-0B-6A-F6-00-DC ++ * 0<-->6AF600DC, 1<-->000B. ++ */ ++ ++ /* low dword */ ++ sta = (((u32)addr[2]) << 24) | (((u32)addr[3]) << 16) | ++ (((u32)addr[4]) << 8) | (((u32)addr[5])) ; ++ alx_mem_w32(hw, L1C_STAD0, sta); ++ ++ /* hight dword */ ++ sta = (((u32)addr[0]) << 8) | (((u32)addr[1])) ; ++ alx_mem_w32(hw, L1C_STAD1, sta); ++ return 0; ++} ++ ++ ++static int alc_set_mc_addr(struct alx_hw *hw, u8 *addr) ++{ ++ u32 crc32, bit, reg, mta; ++ ++ /* ++ * set hash value for a multicast address hash calcu processing. ++ * 1. calcu 32bit CRC for multicast address ++ * 2. reverse crc with MSB to LSB ++ */ ++ crc32 = ALX_ETH_CRC(addr, ALX_ETH_LENGTH_OF_ADDRESS); ++ ++ /* ++ * The HASH Table is a register array of 2 32-bit registers. ++ * It is treated like an array of 64 bits. We want to set ++ * bit BitArray[hash_value]. So we figure out what register ++ * the bit is in, read it, OR in the new bit, then write ++ * back the new value. The register is determined by the ++ * upper 7 bits of the hash value and the bit within that ++ * register are determined by the lower 5 bits of the value. ++ */ ++ reg = (crc32 >> 31) & 0x1; ++ bit = (crc32 >> 26) & 0x1F; ++ ++ alx_mem_r32(hw, L1C_HASH_TBL0 + (reg<<2), &mta); ++ mta |= (0x1 << bit); ++ alx_mem_w32(hw, L1C_HASH_TBL0 + (reg<<2), mta); ++ return 0; ++} ++ ++ ++static int alc_clear_mc_addr(struct alx_hw *hw) ++{ ++ alx_mem_w32(hw, L1C_HASH_TBL0, 0); ++ alx_mem_w32(hw, L1C_HASH_TBL1, 0); ++ return 0; ++} ++ ++ ++/* RTX */ ++static int alc_config_tx(struct alx_hw *hw) ++{ ++ return 0; ++} ++ ++ ++/* INTR */ ++static int alc_ack_phy_intr(struct alx_hw *hw) ++{ ++ u16 isr; ++ return alc_read_phy_reg(hw, L1C_MII_ISR, &isr); ++} ++ ++ ++static int alc_enable_legacy_intr(struct alx_hw *hw) ++{ ++ alx_mem_w32(hw, L1C_ISR, ~((u32) L1C_ISR_DIS)); ++ alx_mem_w32(hw, L1C_IMR, hw->intr_mask); ++ return 0; ++} ++ ++ ++static int alc_disable_legacy_intr(struct alx_hw *hw) ++{ ++ alx_mem_w32(hw, L1C_ISR, L1C_ISR_DIS); ++ alx_mem_w32(hw, L1C_IMR, 0); ++ alx_mem_flush(hw); ++ return 0; ++} ++ ++ ++/* ++ * NV Ram ++ */ ++static int alc_check_nvram(struct alx_hw *hw, bool *exist) ++{ ++ *exist = false; ++ return 0; ++} ++ ++ ++static int alc_read_nvram(struct alx_hw *hw, u16 offset, u32 *data) ++{ ++ int i; ++ u32 ectrl1, ectrl2, edata; ++ int retval = 0; ++ ++ if (offset & 0x3) ++ return retval; /* address do not align */ ++ ++ alx_mem_r32(hw, L1C_EFUSE_CTRL2, &ectrl2); ++ if (!(ectrl2 & L1C_EFUSE_CTRL2_CLK_EN)) ++ alx_mem_w32(hw, L1C_EFUSE_CTRL2, ectrl2|L1C_EFUSE_CTRL2_CLK_EN); ++ ++ alx_mem_w32(hw, L1C_EFUSE_DATA, 0); ++ ectrl1 = FIELDL(L1C_EFUSE_CTRL_ADDR, offset); ++ alx_mem_w32(hw, L1C_EFUSE_CTRL, ectrl1); ++ ++ for (i = 0; i < 10; i++) { ++ udelay(100); ++ alx_mem_r32(hw, L1C_EFUSE_CTRL, &ectrl1); ++ if (ectrl1 & L1C_EFUSE_CTRL_FLAG) ++ break; ++ } ++ if (ectrl1 & L1C_EFUSE_CTRL_FLAG) { ++ alx_mem_r32(hw, L1C_EFUSE_CTRL, &ectrl1); ++ alx_mem_r32(hw, L1C_EFUSE_DATA, &edata); ++ *data = LX_SWAP_DW((ectrl1 << 16) | (edata >> 16)); ++ return retval; ++ } ++ ++ if (!(ectrl2 & L1C_EFUSE_CTRL2_CLK_EN)) ++ alx_mem_w32(hw, L1C_EFUSE_CTRL2, ectrl2); ++ ++ return retval; ++} ++ ++ ++static int alc_write_nvram(struct alx_hw *hw, u16 offset, u32 data) ++{ ++ return 0; ++} ++ ++ ++/* fc */ ++static int alc_get_fc_mode(struct alx_hw *hw, enum alx_fc_mode *mode) ++{ ++ u16 bmsr, giga; ++ int i; ++ int retval = 0; ++ ++ for (i = 0; i < ALX_MAX_SETUP_LNK_CYCLE; i++) { ++ alc_read_phy_reg(hw, MII_BMSR, &bmsr); ++ alc_read_phy_reg(hw, MII_BMSR, &bmsr); ++ if (bmsr & BMSR_LSTATUS) { ++ /* Read phy Specific Status Register (17) */ ++ retval = alc_read_phy_reg(hw, L1C_MII_GIGA_PSSR, &giga); ++ if (retval) ++ return retval; ++ ++ if (!(giga & L1C_GIGA_PSSR_SPD_DPLX_RESOLVED)) { ++ alx_hw_err(hw, ++ "error for speed duplex resolved\n"); ++ return -EINVAL; ++ } ++ ++ if ((giga & L1C_GIGA_PSSR_FC_TXEN) && ++ (giga & L1C_GIGA_PSSR_FC_RXEN)) { ++ *mode = alx_fc_full; ++ } else if (giga & L1C_GIGA_PSSR_FC_TXEN) { ++ *mode = alx_fc_tx_pause; ++ } else if (giga & L1C_GIGA_PSSR_FC_RXEN) { ++ *mode = alx_fc_rx_pause; ++ } else { ++ *mode = alx_fc_none; ++ } ++ break; ++ } ++ mdelay(100); ++ } ++ ++ if (i == ALX_MAX_SETUP_LNK_CYCLE) { ++ alx_hw_err(hw, "error when get flow control mode\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++static int alc_config_fc(struct alx_hw *hw) ++{ ++ u32 mac; ++ int retval = 0; ++ ++ if (hw->disable_fc_autoneg) { ++ hw->fc_was_autonegged = false; ++ hw->cur_fc_mode = hw->req_fc_mode; ++ } else { ++ hw->fc_was_autonegged = true; ++ retval = alc_get_fc_mode(hw, &hw->cur_fc_mode); ++ if (retval) ++ return retval; ++ } ++ ++ alx_mem_r32(hw, L1C_MAC_CTRL, &mac); ++ ++ switch (hw->cur_fc_mode) { ++ case alx_fc_none: /* 0 */ ++ mac &= ~(L1C_MAC_CTRL_RXFC_EN | L1C_MAC_CTRL_TXFC_EN); ++ break; ++ case alx_fc_rx_pause: /* 1 */ ++ mac &= ~L1C_MAC_CTRL_TXFC_EN; ++ mac |= L1C_MAC_CTRL_RXFC_EN; ++ break; ++ case alx_fc_tx_pause: /* 2 */ ++ mac |= L1C_MAC_CTRL_TXFC_EN; ++ mac &= ~L1C_MAC_CTRL_RXFC_EN; ++ break; ++ case alx_fc_full: /* 3 */ ++ case alx_fc_default: /* 4 */ ++ mac |= (L1C_MAC_CTRL_TXFC_EN | L1C_MAC_CTRL_RXFC_EN); ++ break; ++ default: ++ alx_hw_err(hw, "flow control param set incorrectly\n"); ++ return -EINVAL; ++ } ++ ++ alx_mem_w32(hw, L1C_MAC_CTRL, mac); ++ return retval; ++} ++ ++ ++/* ethtool */ ++static int alc_get_ethtool_regs(struct alx_hw *hw, void *buff) ++{ ++ int i; ++ u32 *val = buff; ++ static const int reg[] = { ++ /* 0 */ ++ L1C_LNK_CAP, L1C_PMCTRL, L1C_HALFD, L1C_SLD, L1C_MASTER, ++ L1C_MANU_TIMER, L1C_IRQ_MODU_TIMER, L1C_PHY_CTRL, L1C_LNK_CTRL, ++ L1C_MAC_STS, ++ ++ /* 10 */ ++ L1C_MDIO, L1C_SERDES, L1C_MAC_CTRL, L1C_GAP, L1C_STAD0, ++ L1C_STAD1, L1C_HASH_TBL0, L1C_HASH_TBL1, L1C_RXQ0, L1C_RXQ1, ++ ++ /* 20 */ ++ L1C_RXQ2, L1C_RXQ3, L1C_TXQ0, L1C_TXQ1, L1C_TXQ2, L1C_MTU, ++ L1C_WOL0, L1C_WOL1, L1C_WOL2, ++ }; ++ ++ for (i = 0; i < ARRAY_SIZE(reg); i++) ++ alx_mem_r32(hw, reg[i], &val[i]); ++ return 0; ++} ++ ++ ++/******************************************************************************/ ++static int alc_get_hw_capabilities(struct alx_hw *hw) ++{ ++ /* ++ * because there is some hareware error on some platforms, just disable ++ * this feature when link connected. ++ */ ++ CLI_HW_FLAG(L0S_CAP); ++ CLI_HW_FLAG(L1_CAP); ++ ++ if ((hw->mac_type == alx_mac_l1c) || ++ (hw->mac_type == alx_mac_l1d_v1) || ++ (hw->mac_type == alx_mac_l1d_v2)) ++ SET_HW_FLAG(GIGA_CAP); ++ ++ SET_HW_FLAG(PWSAVE_CAP); ++ return 0; ++} ++ ++ ++/* alc_set_hw_info */ ++static int alc_set_hw_infos(struct alx_hw *hw) ++{ ++ hw->rxstat_reg = 0x1700; ++ hw->rxstat_sz = 0x60; ++ hw->txstat_reg = 0x1760; ++ hw->txstat_sz = 0x68; ++ ++ hw->rx_prod_reg[0] = L1C_RFD_PIDX; ++ hw->rx_cons_reg[0] = L1C_RFD_CIDX; ++ ++ hw->tx_prod_reg[0] = L1C_TPD_PRI0_PIDX; ++ hw->tx_cons_reg[0] = L1C_TPD_PRI0_CIDX; ++ hw->tx_prod_reg[1] = L1C_TPD_PRI1_PIDX; ++ hw->tx_cons_reg[1] = L1C_TPD_PRI1_CIDX; ++ ++ hw->hwreg_sz = 0x80; ++ hw->eeprom_sz = 0; ++ ++ return 0; ++} ++ ++ ++/** ++ * alc_init_hw_callbacks - Inits func ptrs and MAC type ++ * @hw: pointer to hardware structure ++ **/ ++int alc_init_hw_callbacks(struct alx_hw *hw) ++{ ++ /* NIC */ ++ hw->cbs.identify_nic = &alc_identify_nic; ++ /* MAC*/ ++ hw->cbs.reset_mac = &alc_reset_mac; ++ hw->cbs.start_mac = &alc_start_mac; ++ hw->cbs.stop_mac = &alc_stop_mac; ++ hw->cbs.config_mac = &alc_config_mac; ++ hw->cbs.get_mac_addr = &alc_get_mac_addr; ++ hw->cbs.set_mac_addr = &alc_set_mac_addr; ++ hw->cbs.set_mc_addr = &alc_set_mc_addr; ++ hw->cbs.clear_mc_addr = &alc_clear_mc_addr; ++ ++ /* PHY */ ++ hw->cbs.init_phy = &alc_init_phy; ++ hw->cbs.reset_phy = &alc_reset_phy; ++ hw->cbs.read_phy_reg = &alc_read_phy_reg; ++ hw->cbs.write_phy_reg = &alc_write_phy_reg; ++ hw->cbs.check_phy_link = &alc_check_phy_link; ++ hw->cbs.setup_phy_link = &alc_setup_phy_link; ++ hw->cbs.setup_phy_link_speed = &alc_setup_phy_link_speed; ++ ++ /* Interrupt */ ++ hw->cbs.ack_phy_intr = &alc_ack_phy_intr; ++ hw->cbs.enable_legacy_intr = &alc_enable_legacy_intr; ++ hw->cbs.disable_legacy_intr = &alc_disable_legacy_intr; ++ ++ /* Configure */ ++ hw->cbs.config_tx = &alc_config_tx; ++ hw->cbs.config_fc = &alc_config_fc; ++ hw->cbs.config_aspm = &alc_config_aspm; ++ hw->cbs.config_wol = &alc_config_wol; ++ hw->cbs.config_mac_ctrl = &alc_config_mac_ctrl; ++ hw->cbs.config_pow_save = &alc_config_pow_save; ++ hw->cbs.reset_pcie = &alc_reset_pcie; ++ ++ /* NVRam */ ++ hw->cbs.check_nvram = &alc_check_nvram; ++ hw->cbs.read_nvram = &alc_read_nvram; ++ hw->cbs.write_nvram = &alc_write_nvram; ++ ++ /* Others */ ++ hw->cbs.get_ethtool_regs = alc_get_ethtool_regs; ++ ++ /* get hw capabilitites to HW->flags */ ++ alc_get_hw_capabilities(hw); ++ alc_set_hw_infos(hw); ++ ++ alx_hw_info(hw, "HW Flags = 0x%x\n", hw->flags); ++ return 0; ++} ++ +diff --git a/drivers/net/ethernet/atheros/alx/alc_hw.c b/drivers/net/ethernet/atheros/alx/alc_hw.c +new file mode 100644 +index 0000000..b0eb72c +--- /dev/null ++++ b/drivers/net/ethernet/atheros/alx/alc_hw.c +@@ -0,0 +1,1087 @@ ++/* ++ * Copyright (c) 2012 Qualcomm Atheros, Inc. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "alc_hw.h" ++ ++ ++ ++/* ++ * get permanent mac address ++ * 0: success ++ * non-0:fail ++ */ ++u16 l1c_get_perm_macaddr(struct alx_hw *hw, u8 *addr) ++{ ++ u32 val, otp_ctrl, otp_flag, mac0, mac1; ++ u16 i; ++ u16 phy_val; ++ ++ /* get it from register first */ ++ alx_mem_r32(hw, L1C_STAD0, &mac0); ++ alx_mem_r32(hw, L1C_STAD1, &mac1); ++ ++ *(u32 *)(addr + 2) = LX_SWAP_DW(mac0); ++ *(u16 *)addr = (u16)LX_SWAP_W((u16)mac1); ++ ++ if (macaddr_valid(addr)) ++ return 0; ++ ++ alx_mem_r32(hw, L1C_TWSI_DBG, &val); ++ alx_mem_r32(hw, L1C_EFUSE_CTRL2, &otp_ctrl); ++ alx_mem_r32(hw, L1C_MASTER, &otp_flag); ++ ++ if ((val & L1C_TWSI_DBG_DEV_EXIST) != 0 || ++ (otp_flag & L1C_MASTER_OTP_FLG) != 0) { ++ /* nov-memory exist, do software-autoload */ ++ /* enable OTP_CLK for L1C */ ++ if (hw->pci_devid == L1C_DEV_ID || ++ hw->pci_devid == L2C_DEV_ID) { ++ if ((otp_ctrl & L1C_EFUSE_CTRL2_CLK_EN) != 0) { ++ alx_mem_w32(hw, L1C_EFUSE_CTRL2, ++ otp_ctrl | L1C_EFUSE_CTRL2_CLK_EN); ++ udelay(5); ++ } ++ } ++ /* raise voltage temporally for L2CB/L1D */ ++ if (hw->pci_devid == L2CB_DEV_ID || ++ hw->pci_devid == L2CB2_DEV_ID) { ++ /* clear bit[7] of debugport 00 */ ++ l1c_read_phydbg(hw, true, L1C_MIIDBG_ANACTRL, ++ &phy_val); ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_ANACTRL, ++ phy_val & ~L1C_ANACTRL_HB_EN); ++ /* set bit[3] of debugport 3B */ ++ l1c_read_phydbg(hw, true, L1C_MIIDBG_VOLT_CTRL, ++ &phy_val); ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_VOLT_CTRL, ++ phy_val | L1C_VOLT_CTRL_SWLOWEST); ++ udelay(20); ++ } ++ /* do load */ ++ alx_mem_r32(hw, L1C_SLD, &val); ++ alx_mem_w32(hw, L1C_SLD, val | L1C_SLD_START); ++ for (i = 0; i < L1C_SLD_MAX_TO; i++) { ++ mdelay(1); ++ alx_mem_r32(hw, L1C_SLD, &val); ++ if ((val & L1C_SLD_START) == 0) ++ break; ++ } ++ /* disable OTP_CLK for L1C */ ++ if (hw->pci_devid == L1C_DEV_ID || ++ hw->pci_devid == L2C_DEV_ID) { ++ alx_mem_w32(hw, L1C_EFUSE_CTRL2, ++ otp_ctrl & ~L1C_EFUSE_CTRL2_CLK_EN); ++ udelay(5); ++ } ++ /* low voltage */ ++ if (hw->pci_devid == L2CB_DEV_ID || ++ hw->pci_devid == L2CB2_DEV_ID) { ++ /* set bit[7] of debugport 00 */ ++ l1c_read_phydbg(hw, true, L1C_MIIDBG_ANACTRL, ++ &phy_val); ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_ANACTRL, ++ phy_val | L1C_ANACTRL_HB_EN); ++ /* clear bit[3] of debugport 3B */ ++ l1c_read_phydbg(hw, true, L1C_MIIDBG_VOLT_CTRL, ++ &phy_val); ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_VOLT_CTRL, ++ phy_val & ~L1C_VOLT_CTRL_SWLOWEST); ++ udelay(20); ++ } ++ if (i == L1C_SLD_MAX_TO) ++ goto out; ++ } else { ++ if (hw->pci_devid == L1C_DEV_ID || ++ hw->pci_devid == L2C_DEV_ID) { ++ alx_mem_w32(hw, L1C_EFUSE_CTRL2, ++ otp_ctrl & ~L1C_EFUSE_CTRL2_CLK_EN); ++ udelay(5); ++ } ++ } ++ ++ alx_mem_r32(hw, L1C_STAD0, &mac0); ++ alx_mem_r32(hw, L1C_STAD1, &mac1); ++ ++ *(u32 *)(addr + 2) = LX_SWAP_DW(mac0); ++ *(u16 *)addr = (u16)LX_SWAP_W((u16)mac1); ++ ++ if (macaddr_valid(addr)) ++ return 0; ++ ++out: ++ return LX_ERR_ALOAD; ++} ++ ++/* ++ * reset mac & dma ++ * return ++ * 0: success ++ * non-0:fail ++ */ ++u16 l1c_reset_mac(struct alx_hw *hw) ++{ ++ u32 val, mrst_val; ++ u16 ret; ++ u16 i; ++ ++ /* disable all interrupts, RXQ/TXQ */ ++ alx_mem_w32(hw, L1C_IMR, 0); ++ alx_mem_w32(hw, L1C_ISR, L1C_ISR_DIS); ++ ++ ret = l1c_enable_mac(hw, false, 0); ++ if (ret != 0) ++ return ret; ++ /* reset whole mac safely. OOB is meaningful for L1D only */ ++ alx_mem_r32(hw, L1C_MASTER, &mrst_val); ++ mrst_val |= L1C_MASTER_OOB_DIS; ++ alx_mem_w32(hw, L1C_MASTER, mrst_val | L1C_MASTER_DMA_MAC_RST); ++ ++ /* make sure it's idle */ ++ for (i = 0; i < L1C_DMA_MAC_RST_TO; i++) { ++ alx_mem_r32(hw, L1C_MASTER, &val); ++ if ((val & L1C_MASTER_DMA_MAC_RST) == 0) ++ break; ++ udelay(20); ++ } ++ if (i == L1C_DMA_MAC_RST_TO) ++ return LX_ERR_RSTMAC; ++ /* keep the old value */ ++ alx_mem_w32(hw, L1C_MASTER, mrst_val & ~L1C_MASTER_DMA_MAC_RST); ++ ++ /* driver control speed/duplex, hash-alg */ ++ alx_mem_r32(hw, L1C_MAC_CTRL, &val); ++ alx_mem_w32(hw, L1C_MAC_CTRL, val | L1C_MAC_CTRL_WOLSPED_SWEN); ++ ++ /* clk switch setting */ ++ alx_mem_r32(hw, L1C_SERDES, &val); ++ switch (hw->pci_devid) { ++ case L2CB_DEV_ID: ++ alx_mem_w32(hw, L1C_SERDES, val & ~L1C_SERDES_PHYCLK_SLWDWN); ++ break; ++ case L2CB2_DEV_ID: ++ case L1D2_DEV_ID: ++ alx_mem_w32(hw, L1C_SERDES, ++ val | L1C_SERDES_PHYCLK_SLWDWN | ++ L1C_SERDES_MACCLK_SLWDWN); ++ break; ++ default: ++ /* the defalut value of default product is OFF */; ++ } ++ ++ return 0; ++} ++ ++/* reset phy ++ * return ++ * 0: success ++ * non-0:fail ++ */ ++u16 l1c_reset_phy(struct alx_hw *hw, bool pws_en, bool az_en, bool ptp_en) ++{ ++ u32 val; ++ u16 i, phy_val; ++ ++ ptp_en = ptp_en; ++ ++ /* reset PHY core */ ++ alx_mem_r32(hw, L1C_PHY_CTRL, &val); ++ val &= ~(L1C_PHY_CTRL_DSPRST_OUT | L1C_PHY_CTRL_IDDQ | ++ L1C_PHY_CTRL_GATE_25M | L1C_PHY_CTRL_POWER_DOWN | ++ L1C_PHY_CTRL_CLS); ++ val |= L1C_PHY_CTRL_RST_ANALOG; ++ ++ if (pws_en) ++ val |= (L1C_PHY_CTRL_HIB_PULSE | L1C_PHY_CTRL_HIB_EN); ++ else ++ val &= ~(L1C_PHY_CTRL_HIB_PULSE | L1C_PHY_CTRL_HIB_EN); ++ ++ alx_mem_w32(hw, L1C_PHY_CTRL, val); ++ udelay(10); /* 5us is enough */ ++ alx_mem_w32(hw, L1C_PHY_CTRL, val | L1C_PHY_CTRL_DSPRST_OUT); ++ ++ /* delay 800us */ ++ for (i = 0; i < L1C_PHY_CTRL_DSPRST_TO; i++) ++ udelay(10); ++ ++ /* switch clock */ ++ if (hw->pci_devid == L2CB_DEV_ID) { ++ l1c_read_phydbg(hw, true, L1C_MIIDBG_CFGLPSPD, &phy_val); ++ /* clear bit13 */ ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_CFGLPSPD, ++ phy_val & ~L1C_CFGLPSPD_RSTCNT_CLK125SW); ++ } ++ ++ /* fix tx-half-amp issue */ ++ if (hw->pci_devid == L2CB_DEV_ID || hw->pci_devid == L2CB2_DEV_ID) { ++ l1c_read_phydbg(hw, true, L1C_MIIDBG_CABLE1TH_DET, &phy_val); ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_CABLE1TH_DET, ++ phy_val | L1C_CABLE1TH_DET_EN); /* set bit15 */ ++ } ++ ++ if (pws_en) { ++ /* clear bit[3] of debugport 3B to 0, ++ * lower voltage to save power */ ++ if (hw->pci_devid == L2CB_DEV_ID || ++ hw->pci_devid == L2CB2_DEV_ID) { ++ l1c_read_phydbg(hw, true, L1C_MIIDBG_VOLT_CTRL, ++ &phy_val); ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_VOLT_CTRL, ++ phy_val & ~L1C_VOLT_CTRL_SWLOWEST); ++ } ++ /* power saving config */ ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_LEGCYPS, ++ (hw->pci_devid == L1D_DEV_ID || ++ hw->pci_devid == L1D2_DEV_ID) ? ++ L1D_LEGCYPS_DEF : L1C_LEGCYPS_DEF); ++ /* hib */ ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_SYSMODCTRL, ++ L1C_SYSMODCTRL_IECHOADJ_DEF); ++ } else { ++ /*dis powersaving */ ++ l1c_read_phydbg(hw, true, L1C_MIIDBG_LEGCYPS, &phy_val); ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_LEGCYPS, ++ phy_val & ~L1C_LEGCYPS_EN); ++ /* disable hibernate */ ++ l1c_read_phydbg(hw, true, L1C_MIIDBG_HIBNEG, &phy_val); ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_HIBNEG, ++ phy_val & ~L1C_HIBNEG_PSHIB_EN); ++ } ++ ++ /* az is only for l2cbv2 / l1dv1 /l1dv2 */ ++ if (hw->pci_devid == L1D_DEV_ID || ++ hw->pci_devid == L1D2_DEV_ID || ++ hw->pci_devid == L2CB2_DEV_ID) { ++ if (az_en) { ++ switch (hw->pci_devid) { ++ case L2CB2_DEV_ID: ++ alx_mem_w32(hw, L1C_LPI_DECISN_TIMER, ++ L1C_LPI_DESISN_TIMER_L2CB); ++ /* az enable 100M */ ++ l1c_write_phy(hw, true, L1C_MIIEXT_ANEG, true, ++ L1C_MIIEXT_LOCAL_EEEADV, ++ L1C_LOCAL_EEEADV_100BT); ++ /* az long wake threshold */ ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_AZCTRL5, ++ L1C_AZCTRL5_WAKE_LTH_L2CB); ++ /* az short wake threshold */ ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_AZCTRL4, ++ L1C_AZCTRL4_WAKE_STH_L2CB); ++ ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_CLDCTRL3, ++ L1C_CLDCTRL3_L2CB); ++ ++ /* bit7 set to 0, otherwise ping fail */ ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_CLDCTRL7, ++ L1C_CLDCTRL7_L2CB); ++ ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_AZCTRL2, ++ L1C_AZCTRL2_L2CB); ++ break; ++ ++ case L1D_DEV_ID: ++ l1c_write_phydbg(hw, true, ++ L1C_MIIDBG_AZ_ANADECT, L1C_AZ_ANADECT_DEF); ++ phy_val = hw->long_cable ? L1C_CLDCTRL3_L1D : ++ (L1C_CLDCTRL3_L1D & ++ ~(L1C_CLDCTRL3_BP_CABLE1TH_DET_GT | ++ L1C_CLDCTRL3_AZ_DISAMP)); ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_CLDCTRL3, phy_val); ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_AZCTRL, ++ L1C_AZCTRL_L1D); ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_AZCTRL2, ++ L1C_AZCTRL2_L2CB); ++ break; ++ ++ case L1D2_DEV_ID: ++ l1c_write_phydbg(hw, true, ++ L1C_MIIDBG_AZ_ANADECT, ++ L1C_AZ_ANADECT_DEF); ++ phy_val = hw->long_cable ? L1C_CLDCTRL3_L1D : ++ (L1C_CLDCTRL3_L1D & ++ ~L1C_CLDCTRL3_BP_CABLE1TH_DET_GT); ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_CLDCTRL3, phy_val); ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_AZCTRL, ++ L1C_AZCTRL_L1D); ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_AZCTRL2, ++ L1C_AZCTRL2_L1D2); ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_AZCTRL6, ++ L1C_AZCTRL6_L1D2); ++ break; ++ } ++ } else { ++ alx_mem_r32(hw, L1C_LPI_CTRL, &val); ++ alx_mem_w32(hw, L1C_LPI_CTRL, val & ~L1C_LPI_CTRL_EN); ++ l1c_write_phy(hw, true, L1C_MIIEXT_ANEG, true, ++ L1C_MIIEXT_LOCAL_EEEADV, 0); ++ l1c_write_phy(hw, true, L1C_MIIEXT_PCS, true, ++ L1C_MIIEXT_CLDCTRL3, L1C_CLDCTRL3_L2CB); ++ } ++ } ++ ++ /* other debug port need to set */ ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_ANACTRL, L1C_ANACTRL_DEF); ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_SRDSYSMOD, L1C_SRDSYSMOD_DEF); ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_TST10BTCFG, L1C_TST10BTCFG_DEF); ++ /* L1c, L2c, L1d, L2cb link fail inhibit ++ timer issue of L1c UNH-IOL test fail, set bit7*/ ++ l1c_write_phydbg(hw, true, L1C_MIIDBG_TST100BTCFG, ++ L1C_TST100BTCFG_DEF | L1C_TST100BTCFG_LITCH_EN); ++ ++ /* set phy interrupt mask */ ++ l1c_write_phy(hw, false, 0, true, ++ L1C_MII_IER, L1C_IER_LINK_UP | L1C_IER_LINK_DOWN); ++ ++ return 0; ++} ++ ++ ++/* reset pcie ++ * just reset pcie relative registers (pci command, clk, aspm...) ++ * return ++ * 0:success ++ * non-0:fail ++ */ ++u16 l1c_reset_pcie(struct alx_hw *hw, bool l0s_en, bool l1_en) ++{ ++ u32 val; ++ u16 val16; ++ u16 ret; ++ ++ /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */ ++ alx_cfg_r16(hw, PCI_COMMAND, &val16); ++ if ((val16 & (PCI_COMMAND_IO | ++ PCI_COMMAND_MEMORY | ++ PCI_COMMAND_MASTER)) == 0 || ++ (val16 & PCI_COMMAND_INTX_DISABLE) != 0) { ++ val16 = (u16)((val16 | (PCI_COMMAND_IO | ++ PCI_COMMAND_MEMORY | ++ PCI_COMMAND_MASTER)) ++ & ~PCI_COMMAND_INTX_DISABLE); ++ alx_cfg_w16(hw, PCI_COMMAND, val16); ++ } ++ ++ /* Clear any PowerSaving Settings */ ++ alx_cfg_w16(hw, L1C_PM_CSR, 0); ++ ++ /* close write attr for some registes */ ++ alx_mem_r32(hw, L1C_LTSSM_CTRL, &val); ++ alx_mem_w32(hw, L1C_LTSSM_CTRL, val & ~L1C_LTSSM_WRO_EN); ++ ++ /* mask some pcie error bits */ ++ alx_mem_r32(hw, L1C_UE_SVRT, &val); ++ val &= ~(L1C_UE_SVRT_DLPROTERR | L1C_UE_SVRT_FCPROTERR); ++ alx_mem_w32(hw, L1C_UE_SVRT, val); ++ ++ /* pclk */ ++ alx_mem_r32(hw, L1C_MASTER, &val); ++ val &= ~L1C_MASTER_PCLKSEL_SRDS; ++ alx_mem_w32(hw, L1C_MASTER, val); ++ ++ /* Set 1000 bit 2, only used for L1c/L2c , WOL usage */ ++ if (hw->pci_devid == L1C_DEV_ID || hw->pci_devid == L2C_DEV_ID) { ++ alx_mem_r32(hw, L1C_PPHY_MISC1, &val); ++ alx_mem_w32(hw, L1C_PPHY_MISC1, val | L1C_PPHY_MISC1_RCVDET); ++ } else { /* other device should set bit 5 of reg1400 for WOL */ ++ if ((val & L1C_MASTER_WAKEN_25M) == 0) ++ alx_mem_w32(hw, L1C_MASTER, val | L1C_MASTER_WAKEN_25M); ++ } ++ /* l2cb 1.0*/ ++ if (hw->pci_devid == L2CB_DEV_ID && hw->pci_revid == L2CB_V10) { ++ alx_mem_r32(hw, L1C_PPHY_MISC2, &val); ++ FIELD_SETL(val, L1C_PPHY_MISC2_L0S_TH, ++ L1C_PPHY_MISC2_L0S_TH_L2CB1); ++ FIELD_SETL(val, L1C_PPHY_MISC2_CDR_BW, ++ L1C_PPHY_MISC2_CDR_BW_L2CB1); ++ alx_mem_w32(hw, L1C_PPHY_MISC2, val); ++ /* extend L1 sync timer, this will use more power, ++ * only for L2cb v1.0*/ ++ if (!hw->aps_en) { ++ alx_mem_r32(hw, L1C_LNK_CTRL, &val); ++ alx_mem_w32(hw, L1C_LNK_CTRL, ++ val | L1C_LNK_CTRL_EXTSYNC); ++ } ++ } ++ ++ /* l2cbv1.x & l1dv1.x */ ++ if (hw->pci_devid == L2CB_DEV_ID || hw->pci_devid == L1D_DEV_ID) { ++ alx_mem_r32(hw, L1C_PMCTRL, &val); ++ alx_mem_w32(hw, L1C_PMCTRL, val | L1C_PMCTRL_L0S_BUFSRX_EN); ++ /* clear vendor message for L1d & L2cb */ ++ alx_mem_r32(hw, L1C_DMA_DBG, &val); ++ alx_mem_w32(hw, L1C_DMA_DBG, val & ~L1C_DMA_DBG_VENDOR_MSG); ++ } ++ ++ /* hi-tx-perf */ ++ if (hw->hi_txperf) { ++ alx_mem_r32(hw, L1C_PPHY_MISC1, &val); ++ FIELD_SETL(val, L1C_PPHY_MISC1_NFTS, ++ L1C_PPHY_MISC1_NFTS_HIPERF); ++ alx_mem_w32(hw, L1C_PPHY_MISC1, val); ++ } ++ /* l0s, l1 setting */ ++ ret = l1c_enable_aspm(hw, l0s_en, l1_en, 0); ++ ++ udelay(10); ++ ++ return ret; ++} ++ ++ ++/* disable/enable MAC/RXQ/TXQ ++ * en ++ * true:enable ++ * false:disable ++ * return ++ * 0:success ++ * non-0-fail ++ */ ++u16 l1c_enable_mac(struct alx_hw *hw, bool en, u16 en_ctrl) ++{ ++ u32 rxq, txq, mac, val; ++ u16 i; ++ ++ alx_mem_r32(hw, L1C_RXQ0, &rxq); ++ alx_mem_r32(hw, L1C_TXQ0, &txq); ++ alx_mem_r32(hw, L1C_MAC_CTRL, &mac); ++ ++ if (en) { /* enable */ ++ alx_mem_w32(hw, L1C_RXQ0, rxq | L1C_RXQ0_EN); ++ alx_mem_w32(hw, L1C_TXQ0, txq | L1C_TXQ0_EN); ++ if ((en_ctrl & LX_MACSPEED_1000) != 0) { ++ FIELD_SETL(mac, L1C_MAC_CTRL_SPEED, ++ L1C_MAC_CTRL_SPEED_1000); ++ } else { ++ FIELD_SETL(mac, L1C_MAC_CTRL_SPEED, ++ L1C_MAC_CTRL_SPEED_10_100); ++ } ++ ++ test_set_or_clear(mac, en_ctrl, LX_MACDUPLEX_FULL, ++ L1C_MAC_CTRL_FULLD); ++ ++ /* rx filter */ ++ test_set_or_clear(mac, en_ctrl, LX_FLT_PROMISC, ++ L1C_MAC_CTRL_PROMISC_EN); ++ test_set_or_clear(mac, en_ctrl, LX_FLT_MULTI_ALL, ++ L1C_MAC_CTRL_MULTIALL_EN); ++ test_set_or_clear(mac, en_ctrl, LX_FLT_BROADCAST, ++ L1C_MAC_CTRL_BRD_EN); ++ test_set_or_clear(mac, en_ctrl, LX_FLT_DIRECT, ++ L1C_MAC_CTRL_RX_EN); ++ test_set_or_clear(mac, en_ctrl, LX_FC_TXEN, ++ L1C_MAC_CTRL_TXFC_EN); ++ test_set_or_clear(mac, en_ctrl, LX_FC_RXEN, ++ L1C_MAC_CTRL_RXFC_EN); ++ test_set_or_clear(mac, en_ctrl, LX_VLAN_STRIP, ++ L1C_MAC_CTRL_VLANSTRIP); ++ test_set_or_clear(mac, en_ctrl, LX_LOOPBACK, ++ L1C_MAC_CTRL_LPBACK_EN); ++ test_set_or_clear(mac, en_ctrl, LX_SINGLE_PAUSE, ++ L1C_MAC_CTRL_SPAUSE_EN); ++ test_set_or_clear(mac, en_ctrl, LX_ADD_FCS, ++ (L1C_MAC_CTRL_PCRCE | L1C_MAC_CTRL_CRCE)); ++ ++ alx_mem_w32(hw, L1C_MAC_CTRL, mac | L1C_MAC_CTRL_TX_EN); ++ } else { /* disable mac */ ++ alx_mem_w32(hw, L1C_RXQ0, rxq & ~L1C_RXQ0_EN); ++ alx_mem_w32(hw, L1C_TXQ0, txq & ~L1C_TXQ0_EN); ++ ++ /* waiting for rxq/txq be idle */ ++ for (i = 0; i < L1C_DMA_MAC_RST_TO; i++) {/* wait atmost 1ms */ ++ alx_mem_r32(hw, L1C_MAC_STS, &val); ++ if ((val & (L1C_MAC_STS_TXQ_BUSY | ++ L1C_MAC_STS_RXQ_BUSY)) == 0) { ++ break; ++ } ++ udelay(20); ++ } ++ if (L1C_DMA_MAC_RST_TO == i) ++ return LX_ERR_RSTMAC; ++ /* stop mac tx/rx */ ++ alx_mem_w32(hw, L1C_MAC_CTRL, ++ mac & ~(L1C_MAC_CTRL_RX_EN | L1C_MAC_CTRL_TX_EN)); ++ ++ for (i = 0; i < L1C_DMA_MAC_RST_TO; i++) { ++ alx_mem_r32(hw, L1C_MAC_STS, &val); ++ if ((val & L1C_MAC_STS_IDLE) == 0) ++ break; ++ udelay(10); ++ } ++ if (L1C_DMA_MAC_RST_TO == i) ++ return LX_ERR_RSTMAC; ++ } ++ ++ return 0; ++} ++ ++ ++/* enable/disable aspm support ++ * that will change settings for phy/mac/pcie ++ */ ++u16 l1c_enable_aspm(struct alx_hw *hw, bool l0s_en, bool l1_en, u8 lnk_stat) ++{ ++ u32 pmctrl; ++ bool linkon; ++ ++ linkon = (lnk_stat == LX_LC_10H || lnk_stat == LX_LC_10F || ++ lnk_stat == LX_LC_100H || lnk_stat == LX_LC_100F || ++ lnk_stat == LX_LC_1000F) ? true : false; ++ ++ alx_mem_r32(hw, L1C_PMCTRL, &pmctrl); ++ pmctrl &= ~(L1C_PMCTRL_L0S_EN | ++ L1C_PMCTRL_L1_EN | ++ L1C_PMCTRL_ASPM_FCEN); ++ FIELD_SETL(pmctrl, L1C_PMCTRL_LCKDET_TIMER, ++ L1C_PMCTRL_LCKDET_TIMER_DEF); ++ ++ /* l1 timer */ ++ if (hw->pci_devid == L2CB2_DEV_ID || hw->pci_devid == L1D2_DEV_ID) { ++ pmctrl &= ~L1D_PMCTRL_TXL1_AFTER_L0S; ++ FIELD_SETL(pmctrl, L1D_PMCTRL_L1_TIMER, ++ (lnk_stat == LX_LC_100H || ++ lnk_stat == LX_LC_100F || ++ lnk_stat == LX_LC_1000F) ? ++ L1D_PMCTRL_L1_TIMER_16US : 1); ++ } else { ++ FIELD_SETL(pmctrl, L1C_PMCTRL_L1_TIMER, ++ (lnk_stat == LX_LC_100H || ++ lnk_stat == LX_LC_100F || ++ lnk_stat == LX_LC_1000F) ? ++ ((hw->pci_devid == L2CB_DEV_ID) ? ++ L1C_PMCTRL_L1_TIMER_L2CB1 : L1C_PMCTRL_L1_TIMER_DEF ++ ) : 1); ++ } ++ if (l0s_en) { /* on/off l0s only if bios/system enable l0s */ ++ pmctrl |= (L1C_PMCTRL_L0S_EN | L1C_PMCTRL_ASPM_FCEN); ++ } ++ if (l1_en) { /* on/off l1 only if bios/system enable l1 */ ++ pmctrl |= (L1C_PMCTRL_L1_EN | L1C_PMCTRL_ASPM_FCEN); ++ } ++ ++ if (hw->pci_devid == L2CB_DEV_ID || hw->pci_devid == L1D_DEV_ID || ++ hw->pci_devid == L2CB2_DEV_ID || hw->pci_devid == L1D2_DEV_ID) { ++ /* If the pm_request_l1 time exceeds the value of this timer, ++ it will enter L0s instead of L1 for this ASPM request.*/ ++ FIELD_SETL(pmctrl, L1C_PMCTRL_L1REQ_TO, ++ L1C_PMCTRL_L1REG_TO_DEF); ++ ++ pmctrl |= L1C_PMCTRL_RCVR_WT_1US | /* wait 1us not 2ms */ ++ L1C_PMCTRL_L1_SRDSRX_PWD | /* pwd serdes */ ++ L1C_PMCTRL_L1_CLKSW_EN; ++ pmctrl &= ~(L1C_PMCTRL_L1_SRDS_EN | ++ L1C_PMCTRL_L1_SRDSPLL_EN| ++ L1C_PMCTRL_L1_BUFSRX_EN | ++ L1C_PMCTRL_SADLY_EN | ++ L1C_PMCTRL_HOTRST_WTEN); ++ /* disable l0s if linkdown or l2cbv1.x */ ++ if (!linkon || ++ (!hw->aps_en && hw->pci_devid == L2CB_DEV_ID)) { ++ pmctrl &= ~L1C_PMCTRL_L0S_EN; ++ } ++ } else { /* l1c */ ++ FIELD_SETL(pmctrl, L1C_PMCTRL_L1_TIMER, 0); ++ if (linkon) { ++ pmctrl |= L1C_PMCTRL_L1_SRDS_EN | ++ L1C_PMCTRL_L1_SRDSPLL_EN | ++ L1C_PMCTRL_L1_BUFSRX_EN; ++ pmctrl &= ~(L1C_PMCTRL_L1_SRDSRX_PWD| ++ L1C_PMCTRL_L1_CLKSW_EN | ++ L1C_PMCTRL_L0S_EN | ++ L1C_PMCTRL_L1_EN); ++ } else { ++ pmctrl |= L1C_PMCTRL_L1_CLKSW_EN; ++ pmctrl &= ~(L1C_PMCTRL_L1_SRDS_EN | ++ L1C_PMCTRL_L1_SRDSPLL_EN| ++ L1C_PMCTRL_L1_BUFSRX_EN | ++ L1C_PMCTRL_L0S_EN); ++ } ++ } ++ ++ alx_mem_w32(hw, L1C_PMCTRL, pmctrl); ++ ++ return 0; ++} ++ ++ ++/* initialize phy for speed / flow control ++ * lnk_cap ++ * if autoNeg, is link capability to tell the peer ++ * if force mode, is forced speed/duplex ++ */ ++u16 l1c_init_phy_spdfc(struct alx_hw *hw, bool auto_neg, ++ u8 lnk_cap, bool fc_en) ++{ ++ u16 adv, giga, cr; ++ u32 val; ++ u16 ret; ++ ++ /* clear flag */ ++ l1c_write_phy(hw, false, 0, false, L1C_MII_DBG_ADDR, 0); ++ alx_mem_r32(hw, L1C_DRV, &val); ++ FIELD_SETL(val, LX_DRV_PHY, 0); ++ ++ if (auto_neg) { ++ adv = L1C_ADVERTISE_DEFAULT_CAP & ~L1C_ADVERTISE_SPEED_MASK; ++ giga = L1C_GIGA_CR_1000T_DEFAULT_CAP & ++ ~L1C_GIGA_CR_1000T_SPEED_MASK; ++ val |= LX_DRV_PHY_AUTO; ++ if (!fc_en) ++ adv &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); ++ else ++ val |= LX_DRV_PHY_FC; ++ if ((LX_LC_10H & lnk_cap) != 0) { ++ adv |= ADVERTISE_10HALF; ++ val |= LX_DRV_PHY_10; ++ } ++ if ((LX_LC_10F & lnk_cap) != 0) { ++ adv |= ADVERTISE_10HALF | ++ ADVERTISE_10FULL; ++ val |= LX_DRV_PHY_10 | LX_DRV_PHY_DUPLEX; ++ } ++ if ((LX_LC_100H & lnk_cap) != 0) { ++ adv |= ADVERTISE_100HALF; ++ val |= LX_DRV_PHY_100; ++ } ++ if ((LX_LC_100F & lnk_cap) != 0) { ++ adv |= ADVERTISE_100HALF | ++ ADVERTISE_100FULL; ++ val |= LX_DRV_PHY_100 | LX_DRV_PHY_DUPLEX; ++ } ++ if ((LX_LC_1000F & lnk_cap) != 0) { ++ giga |= L1C_GIGA_CR_1000T_FD_CAPS; ++ val |= LX_DRV_PHY_1000 | LX_DRV_PHY_DUPLEX; ++ } ++ ++ ret = l1c_write_phy(hw, false, 0, false, MII_ADVERTISE, adv); ++ ret = l1c_write_phy(hw, false, 0, false, MII_CTRL1000, giga); ++ ++ cr = BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART; ++ ret = l1c_write_phy(hw, false, 0, false, MII_BMCR, cr); ++ } else { /* force mode */ ++ cr = BMCR_RESET; ++ switch (lnk_cap) { ++ case LX_LC_10H: ++ val |= LX_DRV_PHY_10; ++ break; ++ case LX_LC_10F: ++ cr |= BMCR_FULLDPLX; ++ val |= LX_DRV_PHY_10 | LX_DRV_PHY_DUPLEX; ++ break; ++ case LX_LC_100H: ++ cr |= BMCR_SPEED100; ++ val |= LX_DRV_PHY_100; ++ break; ++ case LX_LC_100F: ++ cr |= BMCR_SPEED100 | BMCR_FULLDPLX; ++ val |= LX_DRV_PHY_100 | LX_DRV_PHY_DUPLEX; ++ break; ++ default: ++ return LX_ERR_PARM; ++ } ++ ret = l1c_write_phy(hw, false, 0, false, MII_BMCR, cr); ++ } ++ ++ if (!ret) { ++ l1c_write_phy(hw, false, 0, false, L1C_MII_DBG_ADDR, ++ LX_PHY_INITED); ++ } ++ alx_mem_w32(hw, L1C_DRV, val); ++ ++ return ret; ++} ++ ++ ++/* do power saving setting befor enter suspend mode ++ * NOTE: ++ * 1. phy link must be established before calling this function ++ * 2. wol option (pattern,magic,link,etc.) is configed before call it. ++ */ ++u16 l1c_powersaving(struct alx_hw *hw, u8 wire_spd, bool wol_en, ++ bool mac_txen, bool mac_rxen, bool pws_en) ++{ ++ u32 master_ctrl, mac_ctrl, phy_ctrl; ++ u16 pm_ctrl, ret = 0; ++ ++ master_ctrl = 0; ++ mac_ctrl = 0; ++ phy_ctrl = 0; ++ ++ pws_en = pws_en; ++ ++ alx_mem_r32(hw, L1C_MASTER, &master_ctrl); ++ master_ctrl &= ~L1C_MASTER_PCLKSEL_SRDS; ++ ++ alx_mem_r32(hw, L1C_MAC_CTRL, &mac_ctrl); ++ /* 10/100 half */ ++ FIELD_SETL(mac_ctrl, L1C_MAC_CTRL_SPEED, L1C_MAC_CTRL_SPEED_10_100); ++ mac_ctrl &= ~(L1C_MAC_CTRL_FULLD | ++ L1C_MAC_CTRL_RX_EN | ++ L1C_MAC_CTRL_TX_EN); ++ ++ alx_mem_r32(hw, L1C_PHY_CTRL, &phy_ctrl); ++ phy_ctrl &= ~(L1C_PHY_CTRL_DSPRST_OUT | L1C_PHY_CTRL_CLS); ++ /* if (pws_en) */ ++ phy_ctrl |= (L1C_PHY_CTRL_RST_ANALOG | L1C_PHY_CTRL_HIB_PULSE | ++ L1C_PHY_CTRL_HIB_EN); ++ ++ if (wol_en) { /* enable rx packet or tx packet */ ++ if (mac_rxen) ++ mac_ctrl |= (L1C_MAC_CTRL_RX_EN | L1C_MAC_CTRL_BRD_EN); ++ if (mac_txen) ++ mac_ctrl |= L1C_MAC_CTRL_TX_EN; ++ if (LX_LC_1000F == wire_spd) { ++ FIELD_SETL(mac_ctrl, L1C_MAC_CTRL_SPEED, ++ L1C_MAC_CTRL_SPEED_1000); ++ } ++ if (LX_LC_10F == wire_spd || LX_LC_100F == wire_spd || ++ LX_LC_100F == wire_spd) { ++ mac_ctrl |= L1C_MAC_CTRL_FULLD; ++ } ++ phy_ctrl |= L1C_PHY_CTRL_DSPRST_OUT; ++ ret = l1c_write_phy(hw, false, 0, false, ++ L1C_MII_IER, L1C_IER_LINK_UP); ++ } else { ++ master_ctrl |= L1C_MASTER_PCLKSEL_SRDS; ++ ret = l1c_write_phy(hw, false, 0, false, L1C_MII_IER, 0); ++ phy_ctrl |= (L1C_PHY_CTRL_IDDQ | L1C_PHY_CTRL_POWER_DOWN); ++ } ++ alx_mem_w32(hw, L1C_MASTER, master_ctrl); ++ alx_mem_w32(hw, L1C_MAC_CTRL, mac_ctrl); ++ alx_mem_w32(hw, L1C_PHY_CTRL, phy_ctrl); ++ ++ /* set PME_EN ?? */ ++ if (wol_en) { ++ alx_cfg_r16(hw, L1C_PM_CSR, &pm_ctrl); ++ pm_ctrl |= L1C_PM_CSR_PME_EN; ++ alx_cfg_w16(hw, L1C_PM_CSR, pm_ctrl); ++ } ++ ++ return ret; ++} ++ ++ ++/* read phy register */ ++u16 l1c_read_phy(struct alx_hw *hw, bool ext, u8 dev, bool fast, ++ u16 reg, u16 *data) ++{ ++ u32 val; ++ u16 clk_sel, i, ret = 0; ++ ++ *data = 0; ++ clk_sel = fast ? ++ (u16)L1C_MDIO_CLK_SEL_25MD4 : (u16)L1C_MDIO_CLK_SEL_25MD128; ++ ++ if (ext) { ++ val = FIELDL(L1C_MDIO_EXTN_DEVAD, dev) | ++ FIELDL(L1C_MDIO_EXTN_REG, reg); ++ alx_mem_w32(hw, L1C_MDIO_EXTN, val); ++ ++ val = L1C_MDIO_SPRES_PRMBL | ++ FIELDL(L1C_MDIO_CLK_SEL, clk_sel) | ++ L1C_MDIO_START | ++ L1C_MDIO_MODE_EXT | ++ L1C_MDIO_OP_READ; ++ } else { ++ val = L1C_MDIO_SPRES_PRMBL | ++ FIELDL(L1C_MDIO_CLK_SEL, clk_sel) | ++ FIELDL(L1C_MDIO_REG, reg) | ++ L1C_MDIO_START | ++ L1C_MDIO_OP_READ; ++ } ++ ++ alx_mem_w32(hw, L1C_MDIO, val); ++ ++ for (i = 0; i < L1C_MDIO_MAX_AC_TO; i++) { ++ alx_mem_r32(hw, L1C_MDIO, &val); ++ if ((val & L1C_MDIO_BUSY) == 0) { ++ *data = (u16)FIELD_GETX(val, L1C_MDIO_DATA); ++ break; ++ } ++ udelay(10); ++ } ++ if (L1C_MDIO_MAX_AC_TO == i) ++ ret = LX_ERR_MIIBUSY; ++ ++ return ret; ++} ++ ++/* write phy register */ ++u16 l1c_write_phy(struct alx_hw *hw, bool ext, u8 dev, bool fast, ++ u16 reg, u16 data) ++{ ++ u32 val; ++ u16 clk_sel, i, ret = 0; ++ ++ clk_sel = fast ? ++ (u16)L1C_MDIO_CLK_SEL_25MD4 : (u16)L1C_MDIO_CLK_SEL_25MD128; ++ ++ if (ext) { ++ val = FIELDL(L1C_MDIO_EXTN_DEVAD, dev) | ++ FIELDL(L1C_MDIO_EXTN_REG, reg); ++ alx_mem_w32(hw, L1C_MDIO_EXTN, val); ++ ++ val = L1C_MDIO_SPRES_PRMBL | ++ FIELDL(L1C_MDIO_CLK_SEL, clk_sel) | ++ FIELDL(L1C_MDIO_DATA, data) | ++ L1C_MDIO_START | ++ L1C_MDIO_MODE_EXT; ++ } else { ++ val = L1C_MDIO_SPRES_PRMBL | ++ FIELDL(L1C_MDIO_CLK_SEL, clk_sel) | ++ FIELDL(L1C_MDIO_REG, reg) | ++ FIELDL(L1C_MDIO_DATA, data) | ++ L1C_MDIO_START; ++ } ++ ++ alx_mem_w32(hw, L1C_MDIO, val); ++ ++ for (i = 0; i < L1C_MDIO_MAX_AC_TO; i++) { ++ alx_mem_r32(hw, L1C_MDIO, &val); ++ if ((val & L1C_MDIO_BUSY) == 0) ++ break; ++ udelay(10); ++ } ++ ++ if (L1C_MDIO_MAX_AC_TO == i) ++ ret = LX_ERR_MIIBUSY; ++ ++ return ret; ++} ++ ++u16 l1c_read_phydbg(struct alx_hw *hw, bool fast, u16 reg, u16 *data) ++{ ++ u16 ret; ++ ++ ret = l1c_write_phy(hw, false, 0, fast, L1C_MII_DBG_ADDR, reg); ++ ret = l1c_read_phy(hw, false, 0, fast, L1C_MII_DBG_DATA, data); ++ ++ return ret; ++} ++ ++u16 l1c_write_phydbg(struct alx_hw *hw, bool fast, u16 reg, u16 data) ++{ ++ u16 ret; ++ ++ ret = l1c_write_phy(hw, false, 0, fast, L1C_MII_DBG_ADDR, reg); ++ ret = l1c_write_phy(hw, false, 0, fast, L1C_MII_DBG_DATA, data); ++ ++ return ret; ++} ++ ++ ++/* ++ * initialize mac basically ++ * most of hi-feature no init ++ * MAC/PHY should be reset before call this function ++ * smb_timer : million-second ++ * int_mod : micro-second ++ * disable RSS as default ++ */ ++u16 l1c_init_mac(struct alx_hw *hw, u8 *addr, u32 txmem_hi, ++ u32 *tx_mem_lo, u8 tx_qnum, u16 txring_sz, ++ u32 rxmem_hi, u32 rfdmem_lo, u32 rrdmem_lo, ++ u16 rxring_sz, u16 rxbuf_sz, u16 smb_timer, ++ u16 mtu, u16 int_mod, bool hash_legacy) ++{ ++ u32 val; ++ u16 val16; ++ u8 dmar_len; ++ ++ /* set mac-address */ ++ val = *(u32 *)(addr + 2); ++ alx_mem_w32(hw, L1C_STAD0, LX_SWAP_DW(val)); ++ val = *(u16 *)addr ; ++ alx_mem_w32(hw, L1C_STAD1, LX_SWAP_W((u16)val)); ++ ++ /* clear multicast hash table, algrithm */ ++ alx_mem_w32(hw, L1C_HASH_TBL0, 0); ++ alx_mem_w32(hw, L1C_HASH_TBL1, 0); ++ alx_mem_r32(hw, L1C_MAC_CTRL, &val); ++ if (hash_legacy) ++ val |= L1C_MAC_CTRL_MHASH_ALG_HI5B; ++ else ++ val &= ~L1C_MAC_CTRL_MHASH_ALG_HI5B; ++ alx_mem_w32(hw, L1C_MAC_CTRL, val); ++ ++ /* clear any wol setting/status */ ++ alx_mem_r32(hw, L1C_WOL0, &val); ++ alx_mem_w32(hw, L1C_WOL0, 0); ++ ++ /* clk gating */ ++ alx_mem_w32(hw, L1C_CLK_GATE, (hw->pci_devid == L1D_DEV_ID) ? 0 : ++ (L1C_CLK_GATE_DMAR | L1C_CLK_GATE_DMAW | ++ L1C_CLK_GATE_TXQ | L1C_CLK_GATE_RXQ | ++ L1C_CLK_GATE_TXMAC)); ++ ++ /* descriptor ring base memory */ ++ alx_mem_w32(hw, L1C_TX_BASE_ADDR_HI, txmem_hi); ++ alx_mem_w32(hw, L1C_TPD_RING_SZ, txring_sz); ++ switch (tx_qnum) { ++ case 2: ++ alx_mem_w32(hw, L1C_TPD_PRI1_ADDR_LO, tx_mem_lo[1]); ++ /* fall through */ ++ case 1: ++ alx_mem_w32(hw, L1C_TPD_PRI0_ADDR_LO, tx_mem_lo[0]); ++ break; ++ default: ++ return LX_ERR_PARM; ++ } ++ alx_mem_w32(hw, L1C_RX_BASE_ADDR_HI, rxmem_hi); ++ alx_mem_w32(hw, L1C_RFD_ADDR_LO, rfdmem_lo); ++ alx_mem_w32(hw, L1C_RRD_ADDR_LO, rrdmem_lo); ++ alx_mem_w32(hw, L1C_RFD_BUF_SZ, rxbuf_sz); ++ alx_mem_w32(hw, L1C_RRD_RING_SZ, rxring_sz); ++ alx_mem_w32(hw, L1C_RFD_RING_SZ, rxring_sz); ++ alx_mem_w32(hw, L1C_SMB_TIMER, smb_timer * 500UL); ++ ++ if (hw->pci_devid == L2CB_DEV_ID) { ++ /* revise SRAM configuration */ ++ alx_mem_w32(hw, L1C_SRAM5, L1C_SRAM_RXF_LEN_L2CB1); ++ alx_mem_w32(hw, L1C_SRAM7, L1C_SRAM_TXF_LEN_L2CB1); ++ alx_mem_w32(hw, L1C_SRAM4, L1C_SRAM_RXF_HT_L2CB1); ++ alx_mem_w32(hw, L1C_SRAM0, L1C_SRAM_RFD_HT_L2CB1); ++ alx_mem_w32(hw, L1C_SRAM6, L1C_SRAM_TXF_HT_L2CB1); ++ alx_mem_w32(hw, L1C_SRAM2, L1C_SRAM_TRD_HT_L2CB1); ++ alx_mem_w32(hw, L1C_TXQ2, 0); /* TX watermark, goto L1 state.*/ ++ alx_mem_w32(hw, L1C_RXQ3, 0); /* RXD threshold. */ ++ } ++ alx_mem_w32(hw, L1C_SRAM9, L1C_SRAM_LOAD_PTR); ++ ++ /* int moduration */ ++ alx_mem_r32(hw, L1C_MASTER, &val); ++ val |= L1C_MASTER_IRQMOD2_EN | L1C_MASTER_IRQMOD1_EN | ++ L1C_MASTER_SYSALVTIMER_EN; /* sysalive */ ++ alx_mem_w32(hw, L1C_MASTER, val); ++ /* set Interrupt Moderator Timer (max interrupt per sec) ++ * we use seperate time for rx/tx */ ++ alx_mem_w32(hw, L1C_IRQ_MODU_TIMER, ++ FIELDL(L1C_IRQ_MODU_TIMER1, int_mod) | ++ FIELDL(L1C_IRQ_MODU_TIMER2, int_mod >> 1)); ++ ++ /* tpd threshold to trig int */ ++ alx_mem_w32(hw, L1C_TINT_TPD_THRSHLD, (u32)txring_sz / 3); ++ alx_mem_w32(hw, L1C_TINT_TIMER, int_mod * 2); ++ /* re-send int */ ++ alx_mem_w32(hw, L1C_INT_RETRIG, L1C_INT_RETRIG_TO); ++ ++ /* mtu */ ++ alx_mem_w32(hw, L1C_MTU, (u32)(mtu + 4 + 4)); /* crc + vlan */ ++ ++ /* txq */ ++ if ((mtu + 8) < L1C_TXQ1_JUMBO_TSO_TH) ++ val = (u32)(mtu + 8 + 7); /* 7 for QWORD align */ ++ else ++ val = L1C_TXQ1_JUMBO_TSO_TH; ++ alx_mem_w32(hw, L1C_TXQ1, val >> 3); ++ ++ alx_mem_r32(hw, L1C_DEV_CTRL, &val); ++ dmar_len = (u8)FIELD_GETX(val, L1C_DEV_CTRL_MAXRRS); ++ /* if BIOS had changed the default dma read max length, ++ * restore it to default value */ ++ if (dmar_len < L1C_DEV_CTRL_MAXRRS_MIN) { ++ FIELD_SETL(val, L1C_DEV_CTRL_MAXRRS, L1C_DEV_CTRL_MAXRRS_MIN); ++ alx_mem_w32(hw, L1C_DEV_CTRL, val); ++ dmar_len = L1C_DEV_CTRL_MAXRRS_MIN; ++ } ++ val = FIELDL(L1C_TXQ0_TPD_BURSTPREF, L1C_TXQ0_TPD_BURSTPREF_DEF) | ++ L1C_TXQ0_MODE_ENHANCE | ++ L1C_TXQ0_LSO_8023_EN | ++ L1C_TXQ0_SUPT_IPOPT | ++ FIELDL(L1C_TXQ0_TXF_BURST_PREF, ++ (hw->pci_devid == L2CB_DEV_ID || ++ hw->pci_devid == L2CB2_DEV_ID) ? ++ L1C_TXQ0_TXF_BURST_PREF_L2CB : ++ L1C_TXQ0_TXF_BURST_PREF_DEF); ++ alx_mem_w32(hw, L1C_TXQ0, val); ++ ++ /* fc */ ++ alx_mem_r32(hw, L1C_SRAM5, &val); ++ val = FIELD_GETX(val, L1C_SRAM_RXF_LEN) << 3; /* bytes */ ++ if (val > L1C_SRAM_RXF_LEN_8K) { ++ val16 = L1C_MTU_STD_ALGN; ++ val = (val - (2 * L1C_MTU_STD_ALGN + L1C_MTU_MIN)); ++ } else { ++ val16 = L1C_MTU_STD_ALGN; ++ val = (val - L1C_MTU_STD_ALGN); ++ } ++ alx_mem_w32(hw, L1C_RXQ2, ++ FIELDL(L1C_RXQ2_RXF_XOFF_THRESH, val16 >> 3) | ++ FIELDL(L1C_RXQ2_RXF_XON_THRESH, val >> 3)); ++ /* rxq */ ++ val = FIELDL(L1C_RXQ0_NUM_RFD_PREF, L1C_RXQ0_NUM_RFD_PREF_DEF) | ++ L1C_RXQ0_IPV6_PARSE_EN; ++ if (mtu > L1C_MTU_JUMBO_TH) ++ val |= L1C_RXQ0_CUT_THRU_EN; ++ if ((hw->pci_devid & 1) != 0) { ++ FIELD_SETL(val, L1C_RXQ0_ASPM_THRESH, ++ (hw->pci_devid == L1D2_DEV_ID) ? ++ L1C_RXQ0_ASPM_THRESH_NO : ++ L1C_RXQ0_ASPM_THRESH_100M); ++ } ++ alx_mem_w32(hw, L1C_RXQ0, val); ++ ++ /* rfd producer index */ ++ alx_mem_w32(hw, L1C_RFD_PIDX, (u32)rxring_sz - 1); ++ ++ /* DMA */ ++ val = FIELDL(L1C_DMA_RORDER_MODE, L1C_DMA_RORDER_MODE_OUT) | ++ L1C_DMA_RREQ_PRI_DATA | ++ FIELDL(L1C_DMA_RREQ_BLEN, dmar_len) | ++ FIELDL(L1C_DMA_WDLY_CNT, L1C_DMA_WDLY_CNT_DEF) | ++ FIELDL(L1C_DMA_RDLY_CNT, L1C_DMA_RDLY_CNT_DEF) ; ++ alx_mem_w32(hw, L1C_DMA, val); ++ ++ return 0; ++} ++ ++ ++u16 l1c_get_phy_config(struct alx_hw *hw) ++{ ++ u32 val; ++ u16 phy_val; ++ ++ alx_mem_r32(hw, L1C_PHY_CTRL, &val); ++ if ((val & L1C_PHY_CTRL_DSPRST_OUT) == 0) { /* phy in rst */ ++ return LX_DRV_PHY_UNKNOWN; ++ } ++ ++ alx_mem_r32(hw, L1C_DRV, &val); ++ val = FIELD_GETX(val, LX_DRV_PHY); ++ if (LX_DRV_PHY_UNKNOWN == val) ++ return LX_DRV_PHY_UNKNOWN; ++ ++ l1c_read_phy(hw, false, 0, false, L1C_MII_DBG_ADDR, &phy_val); ++ ++ if (LX_PHY_INITED == phy_val) ++ return (u16) val; ++ ++ return LX_DRV_PHY_UNKNOWN; ++} ++ +diff --git a/drivers/net/ethernet/atheros/alx/alc_hw.h b/drivers/net/ethernet/atheros/alx/alc_hw.h +new file mode 100644 +index 0000000..492b4c1 +--- /dev/null ++++ b/drivers/net/ethernet/atheros/alx/alc_hw.h +@@ -0,0 +1,1324 @@ ++/* ++ * Copyright (c) 2012 Qualcomm Atheros, Inc. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef L1C_HW_H_ ++#define L1C_HW_H_ ++ ++/********************************************************************* ++ * some reqs for l1x_sw.h ++ * ++ * 1. some basic type must be defined if there are not defined by ++ * your compiler: ++ * u8, u16, u32, bool ++ * ++ * 2. PETHCONTEXT difinition should be in l1x_sw.h and it must contain ++ * pci_devid & pci_venid & pci_revid ++ * ++ *********************************************************************/ ++ ++#include "alx_hwcom.h" ++ ++/******************************************************************************/ ++ ++#define L1C_DEV_ID 0x1063 ++#define L2C_DEV_ID 0x1062 ++#define L2CB_DEV_ID 0x2060 ++#define L2CB2_DEV_ID 0x2062 ++#define L1D_DEV_ID 0x1073 ++#define L1D2_DEV_ID 0x1083 ++ ++#define L2CB_V10 0xC0 ++#define L2CB_V11 0xC1 ++#define L2CB_V20 0xC0 ++#define L2CB_V21 0xC1 ++ ++#define L1C_PM_CSR 0x0044 /* 16bit */ ++#define L1C_PM_CSR_PME_STAT BIT(15) ++#define L1C_PM_CSR_DSCAL_MASK ASHFT13(3U) ++#define L1C_PM_CSR_DSCAL_SHIFT 13 ++#define L1C_PM_CSR_DSEL_MASK ASHFT9(0xFU) ++#define L1C_PM_CSR_DSEL_SHIFT 9 ++#define L1C_PM_CSR_PME_EN BIT(8) ++#define L1C_PM_CSR_PWST_MASK ASHFT0(3U) ++#define L1C_PM_CSR_PWST_SHIFT 0 ++ ++#define L1C_PM_DATA 0x0047 /* 8bit */ ++ ++#define L1C_DEV_CAP 0x005C ++#define L1C_DEV_CAP_SPLSL_MASK ASHFT26(3UL) ++#define L1C_DEV_CAP_SPLSL_SHIFT 26 ++#define L1C_DEV_CAP_SPLV_MASK ASHFT18(0xFFUL) ++#define L1C_DEV_CAP_SPLV_SHIFT 18 ++#define L1C_DEV_CAP_RBER BIT(15) ++#define L1C_DEV_CAP_PIPRS BIT(14) ++#define L1C_DEV_CAP_AIPRS BIT(13) ++#define L1C_DEV_CAP_ABPRS BIT(12) ++#define L1C_DEV_CAP_L1ACLAT_MASK ASHFT9(7UL) ++#define L1C_DEV_CAP_L1ACLAT_SHIFT 9 ++#define L1C_DEV_CAP_L0SACLAT_MASK ASHFT6(7UL) ++#define L1C_DEV_CAP_L0SACLAT_SHIFT 6 ++#define L1C_DEV_CAP_EXTAG BIT(5) ++#define L1C_DEV_CAP_PHANTOM BIT(4) ++#define L1C_DEV_CAP_MPL_MASK ASHFT0(7UL) ++#define L1C_DEV_CAP_MPL_SHIFT 0 ++#define L1C_DEV_CAP_MPL_128 1 ++#define L1C_DEV_CAP_MPL_256 2 ++#define L1C_DEV_CAP_MPL_512 3 ++#define L1C_DEV_CAP_MPL_1024 4 ++#define L1C_DEV_CAP_MPL_2048 5 ++#define L1C_DEV_CAP_MPL_4096 6 ++ ++#define L1C_DEV_CTRL 0x0060 /* 16bit */ ++#define L1C_DEV_CTRL_MAXRRS_MASK ASHFT12(7U) ++#define L1C_DEV_CTRL_MAXRRS_SHIFT 12 ++#define L1C_DEV_CTRL_MAXRRS_MIN 2 ++#define L1C_DEV_CTRL_NOSNP_EN BIT(11) ++#define L1C_DEV_CTRL_AUXPWR_EN BIT(10) ++#define L1C_DEV_CTRL_PHANTOM_EN BIT(9) ++#define L1C_DEV_CTRL_EXTAG_EN BIT(8) ++#define L1C_DEV_CTRL_MPL_MASK ASHFT5(7U) ++#define L1C_DEV_CTRL_MPL_SHIFT 5 ++#define L1C_DEV_CTRL_RELORD_EN BIT(4) ++#define L1C_DEV_CTRL_URR_EN BIT(3) ++#define L1C_DEV_CTRL_FERR_EN BIT(2) ++#define L1C_DEV_CTRL_NFERR_EN BIT(1) ++#define L1C_DEV_CTRL_CERR_EN BIT(0) ++ ++#define L1C_DEV_STAT 0x0062 /* 16bit */ ++#define L1C_DEV_STAT_XS_PEND BIT(5) ++#define L1C_DEV_STAT_AUXPWR BIT(4) ++#define L1C_DEV_STAT_UR BIT(3) ++#define L1C_DEV_STAT_FERR BIT(2) ++#define L1C_DEV_STAT_NFERR BIT(1) ++#define L1C_DEV_STAT_CERR BIT(0) ++ ++#define L1C_LNK_CAP 0x0064 ++#define L1C_LNK_CAP_PRTNUM_MASK ASHFT24(0xFFUL) ++#define L1C_LNK_CAP_PRTNUM_SHIFT 24 ++#define L1C_LNK_CAP_CLK_PM BIT(18) ++#define L1C_LNK_CAP_L1EXTLAT_MASK ASHFT15(7UL) ++#define L1C_LNK_CAP_L1EXTLAT_SHIFT 15 ++#define L1C_LNK_CAP_L0SEXTLAT_MASK ASHFT12(7UL) ++#define L1C_LNK_CAP_L0SEXTLAT_SHIFT 12 ++#define L1C_LNK_CAP_ASPM_SUP_MASK ASHFT10(3UL) ++#define L1C_LNK_CAP_ASPM_SUP_SHIFT 10 ++#define L1C_LNK_CAP_ASPM_SUP_L0S 1 ++#define L1C_LNK_CAP_ASPM_SUP_L0SL1 3 ++#define L1C_LNK_CAP_MAX_LWH_MASK ASHFT4(0x3FUL) ++#define L1C_LNK_CAP_MAX_LWH_SHIFT 4 ++#define L1C_LNK_CAP_MAX_LSPD_MASH ASHFT0(0xFUL) ++#define L1C_LNK_CAP_MAX_LSPD_SHIFT 0 ++ ++#define L1C_LNK_CTRL 0x0068 /* 16bit */ ++#define L1C_LNK_CTRL_CLK_PM_EN BIT(8) ++#define L1C_LNK_CTRL_EXTSYNC BIT(7) ++#define L1C_LNK_CTRL_CMNCLK_CFG BIT(6) ++#define L1C_LNK_CTRL_RCB_128B BIT(3) /* 0:64b,1:128b */ ++#define L1C_LNK_CTRL_ASPM_MASK ASHFT0(3U) ++#define L1C_LNK_CTRL_ASPM_SHIFT 0 ++#define L1C_LNK_CTRL_ASPM_DIS 0 ++#define L1C_LNK_CTRL_ASPM_ENL0S 1 ++#define L1C_LNK_CTRL_ASPM_ENL1 2 ++#define L1C_LNK_CTRL_ASPM_ENL0SL1 3 ++ ++#define L1C_LNK_STAT 0x006A /* 16bit */ ++#define L1C_LNK_STAT_SCLKCFG BIT(12) ++#define L1C_LNK_STAT_LNKTRAIN BIT(11) ++#define L1C_LNK_STAT_TRNERR BIT(10) ++#define L1C_LNK_STAT_LNKSPD_MASK ASHFT0(0xFU) ++#define L1C_LNK_STAT_LNKSPD_SHIFT 0 ++#define L1C_LNK_STAT_NEGLW_MASK ASHFT4(0x3FU) ++#define L1C_LNK_STAT_NEGLW_SHIFT 4 ++ ++#define L1C_UE_SVRT 0x010C ++#define L1C_UE_SVRT_UR BIT(20) ++#define L1C_UE_SVRT_ECRCERR BIT(19) ++#define L1C_UE_SVRT_MTLP BIT(18) ++#define L1C_UE_SVRT_RCVOVFL BIT(17) ++#define L1C_UE_SVRT_UNEXPCPL BIT(16) ++#define L1C_UE_SVRT_CPLABRT BIT(15) ++#define L1C_UE_SVRT_CPLTO BIT(14) ++#define L1C_UE_SVRT_FCPROTERR BIT(13) ++#define L1C_UE_SVRT_PTLP BIT(12) ++#define L1C_UE_SVRT_DLPROTERR BIT(4) ++#define L1C_UE_SVRT_TRNERR BIT(0) ++ ++#define L1C_SLD 0x0218 /* efuse load */ ++#define L1C_SLD_FREQ_MASK ASHFT24(3UL) ++#define L1C_SLD_FREQ_SHIFT 24 ++#define L1C_SLD_FREQ_100K 0 ++#define L1C_SLD_FREQ_200K 1 ++#define L1C_SLD_FREQ_300K 2 ++#define L1C_SLD_FREQ_400K 3 ++#define L1C_SLD_EXIST BIT(23) ++#define L1C_SLD_SLVADDR_MASK ASHFT16(0x7FUL) ++#define L1C_SLD_SLVADDR_SHIFT 16 ++#define L1C_SLD_IDLE BIT(13) ++#define L1C_SLD_STAT BIT(12) /* 0:finish,1:in progress */ ++#define L1C_SLD_START BIT(11) ++#define L1C_SLD_STARTADDR_MASK ASHFT0(0xFFUL) ++#define L1C_SLD_STARTADDR_SHIFT 0 ++#define L1C_SLD_MAX_TO 100 ++ ++#define L1C_PPHY_MISC1 0x1000 ++#define L1C_PPHY_MISC1_RCVDET BIT(2) ++#define L1C_PPHY_MISC1_NFTS_MASK ASHFT16(0xFFUL) ++#define L1C_PPHY_MISC1_NFTS_SHIFT 16 ++#define L1C_PPHY_MISC1_NFTS_HIPERF 0xA0 /* ???? */ ++ ++#define L1C_PPHY_MISC2 0x1004 ++#define L1C_PPHY_MISC2_L0S_TH_MASK ASHFT18(0x3UL) ++#define L1C_PPHY_MISC2_L0S_TH_SHIFT 18 ++#define L1C_PPHY_MISC2_L0S_TH_L2CB1 3 ++#define L1C_PPHY_MISC2_CDR_BW_MASK ASHFT16(0x3UL) ++#define L1C_PPHY_MISC2_CDR_BW_SHIFT 16 ++#define L1C_PPHY_MISC2_CDR_BW_L2CB1 3 ++ ++#define L1C_PDLL_TRNS1 0x1104 ++#define L1C_PDLL_TRNS1_D3PLLOFF_EN BIT(11) ++#define L1C_PDLL_TRNS1_REGCLK_SEL_NORM BIT(10) ++#define L1C_PDLL_TRNS1_REPLY_TO_MASK ASHFT0(0x3FFUL) ++#define L1C_PDLL_TRNS1_REPLY_TO_SHIFT 0 ++ ++#define L1C_TWSI_DBG 0x1108 ++#define L1C_TWSI_DBG_DEV_EXIST BIT(29) ++ ++#define L1C_DMA_DBG 0x1114 ++#define L1C_DMA_DBG_VENDOR_MSG BIT(0) ++ ++#define L1C_TLEXTN_STATS 0x1204 /* diff with l1f */ ++#define L1C_TLEXTN_STATS_DEVNO_MASK ASHFT16(0x1FUL) ++#define L1C_TLEXTN_STATS_DEVNO_SHIFT 16 ++#define L1C_TLEXTN_STATS_BUSNO_MASK ASHFT8(0xFFUL) ++#define L1C_TLEXTN_STATS_BUSNO_SHIFT 8 ++ ++#define L1C_EFUSE_CTRL 0x12C0 ++#define L1C_EFUSE_CTRL_FLAG BIT(31) /* 0:read,1:write */ ++#define L1C_EUFSE_CTRL_ACK BIT(30) ++#define L1C_EFUSE_CTRL_ADDR_MASK ASHFT16(0x3FFUL) ++#define L1C_EFUSE_CTRL_ADDR_SHIFT 16 ++ ++#define L1C_EFUSE_DATA 0x12C4 ++ ++#define EFUSE_OP_MAX_AC_TIMER 100 /* 1ms */ ++ ++#define L1C_EFUSE_CTRL2 0x12F0 ++#define L1C_EFUSE_CTRL2_CLK_EN BIT(1) ++ ++#define L1C_PMCTRL 0x12F8 ++#define L1C_PMCTRL_HOTRST_WTEN BIT(31) ++#define L1C_PMCTRL_ASPM_FCEN BIT(30) /* L0s/L1 dis by MAC based on ++ * thrghput(setting in 15A0) */ ++#define L1C_PMCTRL_SADLY_EN BIT(29) ++#define L1C_PMCTRL_L0S_BUFSRX_EN BIT(28) ++#define L1C_PMCTRL_LCKDET_TIMER_MASK ASHFT24(0xFUL) ++#define L1C_PMCTRL_LCKDET_TIMER_SHIFT 24 ++#define L1C_PMCTRL_LCKDET_TIMER_DEF 0xC ++#define L1C_PMCTRL_L1REQ_TO_MASK ASHFT20(0xFUL) ++#define L1C_PMCTRL_L1REQ_TO_SHIFT 20 /* pm_request_l1 time > @ ++ * ->L0s not L1 */ ++#define L1C_PMCTRL_L1REG_TO_DEF 0xC ++#define L1D_PMCTRL_TXL1_AFTER_L0S BIT(19) /* l1dv2.0+ */ ++#define L1D_PMCTRL_L1_TIMER_MASK ASHFT16(7UL) ++#define L1D_PMCTRL_L1_TIMER_SHIFT 16 ++#define L1D_PMCTRL_L1_TIMER_DIS 0 ++#define L1D_PMCTRL_L1_TIMER_2US 1 ++#define L1D_PMCTRL_L1_TIMER_4US 2 ++#define L1D_PMCTRL_L1_TIMER_8US 3 ++#define L1D_PMCTRL_L1_TIMER_16US 4 ++#define L1D_PMCTRL_L1_TIMER_24US 5 ++#define L1D_PMCTRL_L1_TIMER_32US 6 ++#define L1D_PMCTRL_L1_TIMER_63US 7 ++#define L1C_PMCTRL_L1_TIMER_MASK ASHFT16(0xFUL) ++#define L1C_PMCTRL_L1_TIMER_SHIFT 16 ++#define L1C_PMCTRL_L1_TIMER_L2CB1 7 ++#define L1C_PMCTRL_L1_TIMER_DEF 0xF ++#define L1C_PMCTRL_RCVR_WT_1US BIT(15) /* 1:1us, 0:2ms */ ++#define L1C_PMCTRL_PWM_VER_11 BIT(14) /* 0:1.0a,1:1.1 */ ++#define L1C_PMCTRL_L1_CLKSW_EN BIT(13) /* en pcie clk sw in L1 */ ++#define L1C_PMCTRL_L0S_EN BIT(12) ++#define L1D_PMCTRL_RXL1_AFTER_L0S BIT(11) /* l1dv2.0+ */ ++#define L1D_PMCTRL_L0S_TIMER_MASK ASHFT8(7UL) ++#define L1D_PMCTRL_L0S_TIMER_SHIFT 8 ++#define L1C_PMCTRL_L0S_TIMER_MASK ASHFT8(0xFUL) ++#define L1C_PMCTRL_L0S_TIMER_SHIFT 8 ++#define L1C_PMCTRL_L1_BUFSRX_EN BIT(7) ++#define L1C_PMCTRL_L1_SRDSRX_PWD BIT(6) /* power down serdes rx */ ++#define L1C_PMCTRL_L1_SRDSPLL_EN BIT(5) ++#define L1C_PMCTRL_L1_SRDS_EN BIT(4) ++#define L1C_PMCTRL_L1_EN BIT(3) ++#define L1C_PMCTRL_CLKREQ_EN BIT(2) ++#define L1C_PMCTRL_RBER_EN BIT(1) ++#define L1C_PMCTRL_SPRSDWER_EN BIT(0) ++ ++#define L1C_LTSSM_CTRL 0x12FC ++#define L1C_LTSSM_WRO_EN BIT(12) ++#define L1C_LTSSM_TXTLP_BYPASS BIT(7) ++ ++#define L1C_MASTER 0x1400 ++#define L1C_MASTER_OTP_FLG BIT(31) ++#define L1C_MASTER_DEV_NUM_MASK ASHFT24(0x7FUL) ++#define L1C_MASTER_DEV_NUM_SHIFT 24 ++#define L1C_MASTER_REV_NUM_MASK ASHFT16(0xFFUL) ++#define L1C_MASTER_REV_NUM_SHIFT 16 ++#define L1C_MASTER_RDCLR_INT BIT(14) ++#define L1C_MASTER_CLKSW_L2EV1 BIT(13) /* 0:l2ev2.0,1:l2ev1.0 */ ++#define L1C_MASTER_PCLKSEL_SRDS BIT(12) /* 1:alwys sel pclk from ++ * serdes, not sw to 25M */ ++#define L1C_MASTER_IRQMOD2_EN BIT(11) /* IRQ MODURATION FOR RX */ ++#define L1C_MASTER_IRQMOD1_EN BIT(10) /* MODURATION FOR TX/RX */ ++#define L1C_MASTER_MANU_INT BIT(9) /* SOFT MANUAL INT */ ++#define L1C_MASTER_MANUTIMER_EN BIT(8) ++#define L1C_MASTER_SYSALVTIMER_EN BIT(7) /* SYS ALIVE TIMER EN */ ++#define L1C_MASTER_OOB_DIS BIT(6) /* OUT OF BOX DIS */ ++#define L1C_MASTER_WAKEN_25M BIT(5) /* WAKE WO. PCIE CLK */ ++#define L1C_MASTER_BERT_START BIT(4) ++#define L1C_MASTER_PCIE_TSTMOD_MASK ASHFT2(3UL) ++#define L1C_MASTER_PCIE_TSTMOD_SHIFT 2 ++#define L1C_MASTER_PCIE_RST BIT(1) ++#define L1C_MASTER_DMA_MAC_RST BIT(0) /* RST MAC & DMA */ ++#define L1C_DMA_MAC_RST_TO 50 ++ ++#define L1C_MANU_TIMER 0x1404 ++ ++#define L1C_IRQ_MODU_TIMER 0x1408 ++#define L1C_IRQ_MODU_TIMER2_MASK ASHFT16(0xFFFFUL) ++#define L1C_IRQ_MODU_TIMER2_SHIFT 16 /* ONLY FOR RX */ ++#define L1C_IRQ_MODU_TIMER1_MASK ASHFT0(0xFFFFUL) ++#define L1C_IRQ_MODU_TIMER1_SHIFT 0 ++ ++#define L1C_PHY_CTRL 0x140C ++#define L1C_PHY_CTRL_ADDR_MASK ASHFT19(0x1FUL) ++#define L1C_PHY_CTRL_ADDR_SHIFT 19 ++#define L1C_PHY_CTRL_BP_VLTGSW BIT(18) ++#define L1C_PHY_CTRL_100AB_EN BIT(17) ++#define L1C_PHY_CTRL_10AB_EN BIT(16) ++#define L1C_PHY_CTRL_PLL_BYPASS BIT(15) ++#define L1C_PHY_CTRL_POWER_DOWN BIT(14) /* affect MAC & PHY, ++ * go to low power sts */ ++#define L1C_PHY_CTRL_PLL_ON BIT(13) /* 1:PLL ALWAYS ON ++ * 0:CAN SWITCH IN LPW */ ++#define L1C_PHY_CTRL_RST_ANALOG BIT(12) ++#define L1C_PHY_CTRL_HIB_PULSE BIT(11) ++#define L1C_PHY_CTRL_HIB_EN BIT(10) ++#define L1C_PHY_CTRL_GIGA_DIS BIT(9) ++#define L1C_PHY_CTRL_IDDQ_DIS BIT(8) /* POWER ON RST */ ++#define L1C_PHY_CTRL_IDDQ BIT(7) /* WHILE REBOOT, BIT8(1) ++ * EFFECTS BIT7 */ ++#define L1C_PHY_CTRL_LPW_EXIT BIT(6) ++#define L1C_PHY_CTRL_GATE_25M BIT(5) ++#define L1C_PHY_CTRL_RVRS_ANEG BIT(4) ++#define L1C_PHY_CTRL_ANEG_NOW BIT(3) ++#define L1C_PHY_CTRL_LED_MODE BIT(2) ++#define L1C_PHY_CTRL_RTL_MODE BIT(1) ++#define L1C_PHY_CTRL_DSPRST_OUT BIT(0) /* OUT OF DSP RST STATE */ ++#define L1C_PHY_CTRL_DSPRST_TO 80 ++#define L1C_PHY_CTRL_CLS (\ ++ L1C_PHY_CTRL_LED_MODE |\ ++ L1C_PHY_CTRL_100AB_EN |\ ++ L1C_PHY_CTRL_PLL_ON) ++ ++ ++#define L1C_MAC_STS 0x1410 ++#define L1C_MAC_STS_SFORCE_MASK ASHFT14(0xFUL) ++#define L1C_MAC_STS_SFORCE_SHIFT 14 ++#define L1C_MAC_STS_CALIB_DONE BIT13 ++#define L1C_MAC_STS_CALIB_RES_MASK ASHFT8(0x1FUL) ++#define L1C_MAC_STS_CALIB_RES_SHIFT 8 ++#define L1C_MAC_STS_CALIBERR_MASK ASHFT4(0xFUL) ++#define L1C_MAC_STS_CALIBERR_SHIFT 4 ++#define L1C_MAC_STS_TXQ_BUSY BIT(3) ++#define L1C_MAC_STS_RXQ_BUSY BIT(2) ++#define L1C_MAC_STS_TXMAC_BUSY BIT(1) ++#define L1C_MAC_STS_RXMAC_BUSY BIT(0) ++#define L1C_MAC_STS_IDLE (\ ++ L1C_MAC_STS_TXQ_BUSY |\ ++ L1C_MAC_STS_RXQ_BUSY |\ ++ L1C_MAC_STS_TXMAC_BUSY |\ ++ L1C_MAC_STS_RXMAC_BUSY) ++ ++#define L1C_MDIO 0x1414 ++#define L1C_MDIO_MODE_EXT BIT(30) /* 0:normal,1:ext */ ++#define L1C_MDIO_POST_READ BIT(29) ++#define L1C_MDIO_AUTO_POLLING BIT(28) ++#define L1C_MDIO_BUSY BIT(27) ++#define L1C_MDIO_CLK_SEL_MASK ASHFT24(7UL) ++#define L1C_MDIO_CLK_SEL_SHIFT 24 ++#define L1C_MDIO_CLK_SEL_25MD4 0 /* 25M DIV 4 */ ++#define L1C_MDIO_CLK_SEL_25MD6 2 ++#define L1C_MDIO_CLK_SEL_25MD8 3 ++#define L1C_MDIO_CLK_SEL_25MD10 4 ++#define L1C_MDIO_CLK_SEL_25MD32 5 ++#define L1C_MDIO_CLK_SEL_25MD64 6 ++#define L1C_MDIO_CLK_SEL_25MD128 7 ++#define L1C_MDIO_START BIT(23) ++#define L1C_MDIO_SPRES_PRMBL BIT(22) ++#define L1C_MDIO_OP_READ BIT(21) /* 1:read,0:write */ ++#define L1C_MDIO_REG_MASK ASHFT16(0x1FUL) ++#define L1C_MDIO_REG_SHIFT 16 ++#define L1C_MDIO_DATA_MASK ASHFT0(0xFFFFUL) ++#define L1C_MDIO_DATA_SHIFT 0 ++#define L1C_MDIO_MAX_AC_TO 120 ++ ++#define L1C_MDIO_EXTN 0x1448 ++#define L1C_MDIO_EXTN_PORTAD_MASK ASHFT21(0x1FUL) ++#define L1C_MDIO_EXTN_PORTAD_SHIFT 21 ++#define L1C_MDIO_EXTN_DEVAD_MASK ASHFT16(0x1FUL) ++#define L1C_MDIO_EXTN_DEVAD_SHIFT 16 ++#define L1C_MDIO_EXTN_REG_MASK ASHFT0(0xFFFFUL) ++#define L1C_MDIO_EXTN_REG_SHIFT 0 ++ ++#define L1C_PHY_STS 0x1418 ++#define L1C_PHY_STS_LPW BIT(31) ++#define L1C_PHY_STS_LPI BIT(30) ++#define L1C_PHY_STS_PWON_STRIP_MASK ASHFT16(0xFFFUL) ++#define L1C_PHY_STS_PWON_STRIP_SHIFT 16 ++ ++#define L1C_PHY_STS_DUPLEX BIT(3) ++#define L1C_PHY_STS_LINKUP BIT(2) ++#define L1C_PHY_STS_SPEED_MASK ASHFT0(3UL) ++#define L1C_PHY_STS_SPEED_SHIFT 0 ++#define L1C_PHY_STS_SPEED_SHIFT 0 ++#define L1C_PHY_STS_SPEED_1000M 2 ++#define L1C_PHY_STS_SPEED_100M 1 ++#define L1C_PHY_STS_SPEED_10M 0 ++ ++#define L1C_BIST0 0x141C ++#define L1C_BIST0_COL_MASK ASHFT24(0x3FUL) ++#define L1C_BIST0_COL_SHIFT 24 ++#define L1C_BIST0_ROW_MASK ASHFT12(0xFFFUL) ++#define L1C_BIST0_ROW_SHIFT 12 ++#define L1C_BIST0_STEP_MASK ASHFT8(0xFUL) ++#define L1C_BIST0_STEP_SHIFT 8 ++#define L1C_BIST0_PATTERN_MASK ASHFT4(7UL) ++#define L1C_BIST0_PATTERN_SHIFT 4 ++#define L1C_BIST0_CRIT BIT(3) ++#define L1C_BIST0_FIXED BIT(2) ++#define L1C_BIST0_FAIL BIT(1) ++#define L1C_BIST0_START BIT(0) ++ ++#define L1C_BIST1 0x1420 ++#define L1C_BIST1_COL_MASK ASHFT24(0x3FUL) ++#define L1C_BIST1_COL_SHIFT 24 ++#define L1C_BIST1_ROW_MASK ASHFT12(0xFFFUL) ++#define L1C_BIST1_ROW_SHIFT 12 ++#define L1C_BIST1_STEP_MASK ASHFT8(0xFUL) ++#define L1C_BIST1_STEP_SHIFT 8 ++#define L1C_BIST1_PATTERN_MASK ASHFT4(7UL) ++#define L1C_BIST1_PATTERN_SHIFT 4 ++#define L1C_BIST1_CRIT BIT(3) ++#define L1C_BIST1_FIXED BIT(2) ++#define L1C_BIST1_FAIL BIT(1) ++#define L1C_BIST1_START BIT(0) ++ ++#define L1C_SERDES 0x1424 ++#define L1C_SERDES_PHYCLK_SLWDWN BIT(18) ++#define L1C_SERDES_MACCLK_SLWDWN BIT(17) ++#define L1C_SERDES_SELFB_PLL_MASK ASHFT14(3UL) ++#define L1C_SERDES_SELFB_PLL_SHIFT 14 ++#define L1C_SERDES_PHYCLK_SEL_GTX BIT(13) /* 1:gtx_clk, 0:25M */ ++#define L1C_SERDES_PCIECLK_SEL_SRDS BIT(12) /* 1:serdes,0:25M */ ++#define L1C_SERDES_BUFS_RX_EN BIT(11) ++#define L1C_SERDES_PD_RX BIT(10) ++#define L1C_SERDES_PLL_EN BIT(9) ++#define L1C_SERDES_EN BIT(8) ++#define L1C_SERDES_SELFB_PLL_SEL_CSR BIT(6) /* 0:state-machine,1:csr */ ++#define L1C_SERDES_SELFB_PLL_CSR_MASK ASHFT4(3UL) ++#define L1C_SERDES_SELFB_PLL_CSR_SHIFT 4 ++#define L1C_SERDES_SELFB_PLL_CSR_4 3 /* 4-12% OV-CLK */ ++#define L1C_SERDES_SELFB_PLL_CSR_0 2 /* 0-4% OV-CLK */ ++#define L1C_SERDES_SELFB_PLL_CSR_12 1 /* 12-18% OV-CLK */ ++#define L1C_SERDES_SELFB_PLL_CSR_18 0 /* 18-25% OV-CLK */ ++#define L1C_SERDES_VCO_SLOW BIT(3) ++#define L1C_SERDES_VCO_FAST BIT(2) ++#define L1C_SERDES_LOCKDCT_EN BIT(1) ++#define L1C_SERDES_LOCKDCTED BIT(0) ++ ++#define L1C_LED_CTRL 0x1428 ++#define L1C_LED_CTRL_PATMAP2_MASK ASHFT8(3UL) ++#define L1C_LED_CTRL_PATMAP2_SHIFT 8 ++#define L1C_LED_CTRL_PATMAP1_MASK ASHFT6(3UL) ++#define L1C_LED_CTRL_PATMAP1_SHIFT 6 ++#define L1C_LED_CTRL_PATMAP0_MASK ASHFT4(3UL) ++#define L1C_LED_CTRL_PATMAP0_SHIFT 4 ++#define L1C_LED_CTRL_D3_MODE_MASK ASHFT2(3UL) ++#define L1C_LED_CTRL_D3_MODE_SHIFT 2 ++#define L1C_LED_CTRL_D3_MODE_NORMAL 0 ++#define L1C_LED_CTRL_D3_MODE_WOL_DIS 1 ++#define L1C_LED_CTRL_D3_MODE_WOL_ANY 2 ++#define L1C_LED_CTRL_D3_MODE_WOL_EN 3 ++#define L1C_LED_CTRL_DUTY_CYCL_MASK ASHFT0(3UL) ++#define L1C_LED_CTRL_DUTY_CYCL_SHIFT 0 ++#define L1C_LED_CTRL_DUTY_CYCL_50 0 /* 50% */ ++#define L1C_LED_CTRL_DUTY_CYCL_125 1 /* 12.5% */ ++#define L1C_LED_CTRL_DUTY_CYCL_25 2 /* 25% */ ++#define L1C_LED_CTRL_DUTY_CYCL_75 3 /* 75% */ ++ ++#define L1C_LED_PATN 0x142C ++#define L1C_LED_PATN1_MASK ASHFT16(0xFFFFUL) ++#define L1C_LED_PATN1_SHIFT 16 ++#define L1C_LED_PATN0_MASK ASHFT0(0xFFFFUL) ++#define L1C_LED_PATN0_SHIFT 0 ++ ++#define L1C_LED_PATN2 0x1430 ++#define L1C_LED_PATN2_MASK ASHFT0(0xFFFFUL) ++#define L1C_LED_PATN2_SHIFT 0 ++ ++#define L1C_SYSALV 0x1434 ++#define L1C_SYSALV_FLAG BIT(0) ++ ++#define L1C_PCIERR_INST 0x1438 ++#define L1C_PCIERR_INST_TX_RATE_MASK ASHFT4(0xFUL) ++#define L1C_PCIERR_INST_TX_RATE_SHIFT 4 ++#define L1C_PCIERR_INST_RX_RATE_MASK ASHFT0(0xFUL) ++#define L1C_PCIERR_INST_RX_RATE_SHIFT 0 ++ ++#define L1C_LPI_DECISN_TIMER 0x143C ++#define L1C_LPI_DESISN_TIMER_L2CB 0x7D00 ++ ++#define L1C_LPI_CTRL 0x1440 ++#define L1C_LPI_CTRL_CHK_DA BIT(31) ++#define L1C_LPI_CTRL_ENH_TO_MASK ASHFT12(0x1FFFUL) ++#define L1C_LPI_CTRL_ENH_TO_SHIFT 12 ++#define L1C_LPI_CTRL_ENH_TH_MASK ASHFT6(0x1FUL) ++#define L1C_LPI_CTRL_ENH_TH_SHIFT 6 ++#define L1C_LPI_CTRL_ENH_EN BIT(5) ++#define L1C_LPI_CTRL_CHK_RX BIT(4) ++#define L1C_LPI_CTRL_CHK_STATE BIT(3) ++#define L1C_LPI_CTRL_GMII BIT(2) ++#define L1C_LPI_CTRL_TO_PHY BIT(1) ++#define L1C_LPI_CTRL_EN BIT(0) ++ ++#define L1C_LPI_WAIT 0x1444 ++#define L1C_LPI_WAIT_TIMER_MASK ASHFT0(0xFFFFUL) ++#define L1C_LPI_WAIT_TIMER_SHIFT 0 ++ ++#define L1C_MAC_CTRL 0x1480 ++#define L1C_MAC_CTRL_WOLSPED_SWEN BIT(30) /* 0:phy,1:sw */ ++#define L1C_MAC_CTRL_MHASH_ALG_HI5B BIT(29) /* 1:legacy, 0:marvl(low5b)*/ ++#define L1C_MAC_CTRL_SPAUSE_EN BIT(28) ++#define L1C_MAC_CTRL_DBG_EN BIT(27) ++#define L1C_MAC_CTRL_BRD_EN BIT(26) ++#define L1C_MAC_CTRL_MULTIALL_EN BIT(25) ++#define L1C_MAC_CTRL_RX_XSUM_EN BIT(24) ++#define L1C_MAC_CTRL_THUGE BIT(23) ++#define L1C_MAC_CTRL_MBOF BIT(22) ++#define L1C_MAC_CTRL_SPEED_MASK ASHFT20(3UL) ++#define L1C_MAC_CTRL_SPEED_SHIFT 20 ++#define L1C_MAC_CTRL_SPEED_10_100 1 ++#define L1C_MAC_CTRL_SPEED_1000 2 ++#define L1C_MAC_CTRL_SIMR BIT(19) ++#define L1C_MAC_CTRL_SSTCT BIT(17) ++#define L1C_MAC_CTRL_TPAUSE BIT(16) ++#define L1C_MAC_CTRL_PROMISC_EN BIT(15) ++#define L1C_MAC_CTRL_VLANSTRIP BIT(14) ++#define L1C_MAC_CTRL_PRMBLEN_MASK ASHFT10(0xFUL) ++#define L1C_MAC_CTRL_PRMBLEN_SHIFT 10 ++#define L1C_MAC_CTRL_RHUGE_EN BIT(9) ++#define L1C_MAC_CTRL_FLCHK BIT(8) ++#define L1C_MAC_CTRL_PCRCE BIT(7) ++#define L1C_MAC_CTRL_CRCE BIT(6) ++#define L1C_MAC_CTRL_FULLD BIT(5) ++#define L1C_MAC_CTRL_LPBACK_EN BIT(4) ++#define L1C_MAC_CTRL_RXFC_EN BIT(3) ++#define L1C_MAC_CTRL_TXFC_EN BIT(2) ++#define L1C_MAC_CTRL_RX_EN BIT(1) ++#define L1C_MAC_CTRL_TX_EN BIT(0) ++ ++#define L1C_GAP 0x1484 ++#define L1C_GAP_IPGR2_MASK ASHFT24(0x7FUL) ++#define L1C_GAP_IPGR2_SHIFT 24 ++#define L1C_GAP_IPGR1_MASK ASHFT16(0x7FUL) ++#define L1C_GAP_IPGR1_SHIFT 16 ++#define L1C_GAP_MIN_IFG_MASK ASHFT8(0xFFUL) ++#define L1C_GAP_MIN_IFG_SHIFT 8 ++#define L1C_GAP_IPGT_MASK ASHFT0(0x7FUL) ++#define L1C_GAP_IPGT_SHIFT 0 ++ ++#define L1C_STAD0 0x1488 ++#define L1C_STAD1 0x148C ++ ++#define L1C_HASH_TBL0 0x1490 ++#define L1C_HASH_TBL1 0x1494 ++ ++#define L1C_HALFD 0x1498 ++#define L1C_HALFD_JAM_IPG_MASK ASHFT24(0xFUL) ++#define L1C_HALFD_JAM_IPG_SHIFT 24 ++#define L1C_HALFD_ABEBT_MASK ASHFT20(0xFUL) ++#define L1C_HALFD_ABEBT_SHIFT 20 ++#define L1C_HALFD_ABEBE BIT(19) ++#define L1C_HALFD_BPNB BIT(18) ++#define L1C_HALFD_NOBO BIT(17) ++#define L1C_HALFD_EDXSDFR BIT(16) ++#define L1C_HALFD_RETRY_MASK ASHFT12(0xFUL) ++#define L1C_HALFD_RETRY_SHIFT 12 ++#define L1C_HALFD_LCOL_MASK ASHFT0(0x3FFUL) ++#define L1C_HALFD_LCOL_SHIFT 0 ++ ++#define L1C_MTU 0x149C ++#define L1C_MTU_JUMBO_TH 1514 ++#define L1C_MTU_STD_ALGN 1536 ++#define L1C_MTU_MIN 64 ++ ++#define L1C_WOL0 0x14A0 ++#define L1C_WOL0_PT7_MATCH BIT(31) ++#define L1C_WOL0_PT6_MATCH BIT(30) ++#define L1C_WOL0_PT5_MATCH BIT(29) ++#define L1C_WOL0_PT4_MATCH BIT(28) ++#define L1C_WOL0_PT3_MATCH BIT(27) ++#define L1C_WOL0_PT2_MATCH BIT(26) ++#define L1C_WOL0_PT1_MATCH BIT(25) ++#define L1C_WOL0_PT0_MATCH BIT(24) ++#define L1C_WOL0_PT7_EN BIT(23) ++#define L1C_WOL0_PT6_EN BIT(22) ++#define L1C_WOL0_PT5_EN BIT(21) ++#define L1C_WOL0_PT4_EN BIT(20) ++#define L1C_WOL0_PT3_EN BIT(19) ++#define L1C_WOL0_PT2_EN BIT(18) ++#define L1C_WOL0_PT1_EN BIT(17) ++#define L1C_WOL0_PT0_EN BIT(16) ++#define L1C_WOL0_IPV4_SYNC_EVT BIT(14) ++#define L1C_WOL0_IPV6_SYNC_EVT BIT(13) ++#define L1C_WOL0_LINK_EVT BIT(10) ++#define L1C_WOL0_MAGIC_EVT BIT(9) ++#define L1C_WOL0_PATTERN_EVT BIT(8) ++#define L1D_WOL0_OOB_EN BIT(6) ++#define L1C_WOL0_PME_LINK BIT(5) ++#define L1C_WOL0_LINK_EN BIT(4) ++#define L1C_WOL0_PME_MAGIC_EN BIT(3) ++#define L1C_WOL0_MAGIC_EN BIT(2) ++#define L1C_WOL0_PME_PATTERN_EN BIT(1) ++#define L1C_WOL0_PATTERN_EN BIT(0) ++ ++#define L1C_WOL1 0x14A4 ++#define L1C_WOL1_PT3_LEN_MASK ASHFT24(0xFFUL) ++#define L1C_WOL1_PT3_LEN_SHIFT 24 ++#define L1C_WOL1_PT2_LEN_MASK ASHFT16(0xFFUL) ++#define L1C_WOL1_PT2_LEN_SHIFT 16 ++#define L1C_WOL1_PT1_LEN_MASK ASHFT8(0xFFUL) ++#define L1C_WOL1_PT1_LEN_SHIFT 8 ++#define L1C_WOL1_PT0_LEN_MASK ASHFT0(0xFFUL) ++#define L1C_WOL1_PT0_LEN_SHIFT 0 ++ ++#define L1C_WOL2 0x14A8 ++#define L1C_WOL2_PT7_LEN_MASK ASHFT24(0xFFUL) ++#define L1C_WOL2_PT7_LEN_SHIFT 24 ++#define L1C_WOL2_PT6_LEN_MASK ASHFT16(0xFFUL) ++#define L1C_WOL2_PT6_LEN_SHIFT 16 ++#define L1C_WOL2_PT5_LEN_MASK ASHFT8(0xFFUL) ++#define L1C_WOL2_PT5_LEN_SHIFT 8 ++#define L1C_WOL2_PT4_LEN_MASK ASHFT0(0xFFUL) ++#define L1C_WOL2_PT4_LEN_SHIFT 0 ++ ++#define L1C_SRAM0 0x1500 ++#define L1C_SRAM_RFD_TAIL_ADDR_MASK ASHFT16(0xFFFUL) ++#define L1C_SRAM_RFD_TAIL_ADDR_SHIFT 16 ++#define L1C_SRAM_RFD_HEAD_ADDR_MASK ASHFT0(0xFFFUL) ++#define L1C_SRAM_RFD_HEAD_ADDR_SHIFT 0 ++#define L1C_SRAM_RFD_HT_L2CB1 0x02bf02a0L ++ ++#define L1C_SRAM1 0x1510 ++#define L1C_SRAM_RFD_LEN_MASK ASHFT0(0xFFFUL) /* 8BYTES UNIT */ ++#define L1C_SRAM_RFD_LEN_SHIFT 0 ++ ++#define L1C_SRAM2 0x1518 ++#define L1C_SRAM_TRD_TAIL_ADDR_MASK ASHFT16(0xFFFUL) ++#define L1C_SRAM_TRD_TAIL_ADDR_SHIFT 16 ++#define L1C_SRMA_TRD_HEAD_ADDR_MASK ASHFT0(0xFFFUL) ++#define L1C_SRAM_TRD_HEAD_ADDR_SHIFT 0 ++#define L1C_SRAM_TRD_HT_L2CB1 0x03df03c0L ++ ++#define L1C_SRAM3 0x151C ++#define L1C_SRAM_TRD_LEN_MASK ASHFT0(0xFFFUL) /* 8BYTES UNIT */ ++#define L1C_SRAM_TRD_LEN_SHIFT 0 ++ ++#define L1C_SRAM4 0x1520 ++#define L1C_SRAM_RXF_TAIL_ADDR_MASK ASHFT16(0xFFFUL) ++#define L1C_SRAM_RXF_TAIL_ADDR_SHIFT 16 ++#define L1C_SRAM_RXF_HEAD_ADDR_MASK ASHFT0(0xFFFUL) ++#define L1C_SRAM_RXF_HEAD_ADDR_SHIFT 0 ++#define L1C_SRAM_RXF_HT_L2CB1 0x029f0000L ++ ++#define L1C_SRAM5 0x1524 ++#define L1C_SRAM_RXF_LEN_MASK ASHFT0(0xFFFUL) /* 8BYTES UNIT */ ++#define L1C_SRAM_RXF_LEN_SHIFT 0 ++#define L1C_SRAM_RXF_LEN_8K (8*1024) ++#define L1C_SRAM_RXF_LEN_L2CB1 0x02a0L ++ ++#define L1C_SRAM6 0x1528 ++#define L1C_SRAM_TXF_TAIL_ADDR_MASK ASHFT16(0xFFFUL) ++#define L1C_SRAM_TXF_TAIL_ADDR_SHIFT 16 ++#define L1C_SRAM_TXF_HEAD_ADDR_MASK ASHFT0(0xFFFUL) ++#define L1C_SRAM_TXF_HEAD_ADDR_SHIFT 0 ++#define L1C_SRAM_TXF_HT_L2CB1 0x03bf02c0L ++ ++#define L1C_SRAM7 0x152C ++#define L1C_SRAM_TXF_LEN_MASK ASHFT0(0xFFFUL) /* 8BYTES UNIT */ ++#define L1C_SRAM_TXF_LEN_SHIFT 0 ++#define L1C_SRAM_TXF_LEN_L2CB1 0x0100L ++ ++#define L1C_SRAM8 0x1530 ++#define L1C_SRAM_PATTERN_ADDR_MASK ASHFT16(0xFFFUL) ++#define L1C_SRAM_PATTERN_ADDR_SHIFT 16 ++#define L1C_SRAM_TSO_ADDR_MASK ASHFT0(0xFFFUL) ++#define L1C_SRAM_TSO_ADDR_SHIFT 0 ++ ++#define L1C_SRAM9 0x1534 ++#define L1C_SRAM_LOAD_PTR BIT(0) ++ ++#define L1C_RX_BASE_ADDR_HI 0x1540 ++ ++#define L1C_TX_BASE_ADDR_HI 0x1544 ++ ++#define L1C_RFD_ADDR_LO 0x1550 ++#define L1C_RFD_RING_SZ 0x1560 ++#define L1C_RFD_BUF_SZ 0x1564 ++#define L1C_RFD_BUF_SZ_MASK ASHFT0(0xFFFFUL) ++#define L1C_RFD_BUF_SZ_SHIFT 0 ++ ++#define L1C_RRD_ADDR_LO 0x1568 ++#define L1C_RRD_RING_SZ 0x1578 ++#define L1C_RRD_RING_SZ_MASK ASHFT0(0xFFFUL) ++#define L1C_RRD_RING_SZ_SHIFT 0 ++ ++#define L1C_TPD_PRI1_ADDR_LO 0x157C ++#define L1C_TPD_PRI0_ADDR_LO 0x1580 /* LOWEST PRORITY */ ++ ++#define L1C_TPD_PRI1_PIDX 0x15F0 /* 16BIT */ ++#define L1C_TPD_PRI0_PIDX 0x15F2 /* 16BIT */ ++ ++#define L1C_TPD_PRI1_CIDX 0x15F4 /* 16BIT */ ++#define L1C_TPD_PRI0_CIDX 0x15F6 /* 16BIT */ ++ ++#define L1C_TPD_RING_SZ 0x1584 ++#define L1C_TPD_RING_SZ_MASK ASHFT0(0xFFFFUL) ++#define L1C_TPD_RING_SZ_SHIFT 0 ++ ++#define L1C_TXQ0 0x1590 ++#define L1C_TXQ0_TXF_BURST_PREF_MASK ASHFT16(0xFFFFUL) ++#define L1C_TXQ0_TXF_BURST_PREF_SHIFT 16 ++#define L1C_TXQ0_TXF_BURST_PREF_DEF 0x200 ++#define L1C_TXQ0_TXF_BURST_PREF_L2CB 0x40 ++#define L1D_TXQ0_PEDING_CLR BIT(8) ++#define L1C_TXQ0_LSO_8023_EN BIT(7) ++#define L1C_TXQ0_MODE_ENHANCE BIT(6) ++#define L1C_TXQ0_EN BIT(5) ++#define L1C_TXQ0_SUPT_IPOPT BIT(4) ++#define L1C_TXQ0_TPD_BURSTPREF_MASK ASHFT0(0xFUL) ++#define L1C_TXQ0_TPD_BURSTPREF_SHIFT 0 ++#define L1C_TXQ0_TPD_BURSTPREF_DEF 5 ++ ++#define L1C_TXQ1 0x1594 ++#define L1C_TXQ1_JUMBO_TSOTHR_MASK ASHFT0(0x7FFUL) /* 8BYTES UNIT */ ++#define L1C_TXQ1_JUMBO_TSOTHR_SHIFT 0 ++#define L1C_TXQ1_JUMBO_TSO_TH (7*1024) /* byte */ ++ ++#define L1C_TXQ2 0x1598 /* ENTER L1 CONTROL */ ++#define L1C_TXQ2_BURST_EN BIT(31) ++#define L1C_TXQ2_BURST_HI_WM_MASK ASHFT16(0xFFFUL) ++#define L1C_TXQ2_BURST_HI_WM_SHIFT 16 ++#define L1C_TXQ2_BURST_LO_WM_MASK ASHFT0(0xFFFUL) ++#define L1C_TXQ2_BURST_LO_WM_SHIFT 0 ++ ++#define L1C_RFD_PIDX 0x15E0 ++#define L1C_RFD_PIDX_MASK ASHFT0(0xFFFUL) ++#define L1C_RFD_PIDX_SHIFT 0 ++ ++#define L1C_RFD_CIDX 0x15F8 ++#define L1C_RFD_CIDX_MASK ASHFT0(0xFFFUL) ++#define L1C_RFD_CIDX_SHIFT 0 ++ ++#define L1C_RXQ0 0x15A0 ++#define L1C_RXQ0_EN BIT(31) ++#define L1C_RXQ0_CUT_THRU_EN BIT(30) ++#define L1C_RXQ0_RSS_HASH_EN BIT(29) ++#define L1C_RXQ0_NON_IP_QTBL BIT(28) /* 0:q0,1:table */ ++#define L1C_RXQ0_RSS_MODE_MASK ASHFT26(3UL) ++#define L1C_RXQ0_RSS_MODE_SHIFT 26 ++#define L1C_RXQ0_RSS_MODE_DIS 0 ++#define L1C_RXQ0_RSS_MODE_SQSI 1 ++#define L1C_RXQ0_RSS_MODE_MQSI 2 ++#define L1C_RXQ0_RSS_MODE_MQMI 3 ++#define L1C_RXQ0_NUM_RFD_PREF_MASK ASHFT20(0x3FUL) ++#define L1C_RXQ0_NUM_RFD_PREF_SHIFT 20 ++#define L1C_RXQ0_NUM_RFD_PREF_DEF 8 ++#define L1C_RXQ0_RSS_HSTYP_IPV6_TCP_EN BIT(19) ++#define L1C_RXQ0_RSS_HSTYP_IPV6_EN BIT(18) ++#define L1C_RXQ0_RSS_HSTYP_IPV4_TCP_EN BIT(17) ++#define L1C_RXQ0_RSS_HSTYP_IPV4_EN BIT(16) ++#define L1C_RXQ0_RSS_HSTYP_ALL (\ ++ L1C_RXQ0_RSS_HSTYP_IPV6_TCP_EN |\ ++ L1C_RXQ0_RSS_HSTYP_IPV4_TCP_EN |\ ++ L1C_RXQ0_RSS_HSTYP_IPV6_EN |\ ++ L1C_RXQ0_RSS_HSTYP_IPV4_EN) ++#define L1C_RXQ0_IDT_TBL_SIZE_MASK ASHFT8(0xFFUL) ++#define L1C_RXQ0_IDT_TBL_SIZE_SHIFT 8 ++#define L1C_RXQ0_IDT_TBL_SIZE_DEF 0x80 ++#define L1C_RXQ0_IPV6_PARSE_EN BIT(7) ++#define L1C_RXQ0_ASPM_THRESH_MASK ASHFT0(3UL) ++#define L1C_RXQ0_ASPM_THRESH_SHIFT 0 ++#define L1C_RXQ0_ASPM_THRESH_NO 0 ++#define L1C_RXQ0_ASPM_THRESH_1M 1 ++#define L1C_RXQ0_ASPM_THRESH_10M 2 ++#define L1C_RXQ0_ASPM_THRESH_100M 3 ++ ++#define L1C_RXQ1 0x15A4 ++#define L1C_RXQ1_RFD_PREF_DOWN_MASK ASHFT6(0x3FUL) ++#define L1C_RXQ1_RFD_PREF_DOWN_SHIFT 6 ++#define L1C_RXQ1_RFD_PREF_UP_MASK ASHFT0(0x3FUL) ++#define L1C_RXQ1_RFD_PREF_UP_SHIFT 0 ++ ++#define L1C_RXQ2 0x15A8 ++/* XOFF: USED SRAM LOWER THAN IT, THEN NOTIFY THE PEER TO SEND AGAIN */ ++#define L1C_RXQ2_RXF_XOFF_THRESH_MASK ASHFT16(0xFFFUL) ++#define L1C_RXQ2_RXF_XOFF_THRESH_SHIFT 16 ++#define L1C_RXQ2_RXF_XON_THRESH_MASK ASHFT0(0xFFFUL) ++#define L1C_RXQ2_RXF_XON_THRESH_SHIFT 0 ++ ++#define L1C_RXQ3 0x15AC ++#define L1C_RXQ3_RXD_TIMER_MASK ASHFT16(0xFFFFUL) ++#define L1C_RXQ3_RXD_TIMER_SHIFT 16 ++#define L1C_RXQ3_RXD_THRESH_MASK ASHFT0(0xFFFUL) /* 8BYTES UNIT */ ++#define L1C_RXQ3_RXD_THRESH_SHIFT 0 ++ ++#define L1C_DMA 0x15C0 ++#define L1C_DMA_WPEND_CLR BIT(30) ++#define L1C_DMA_RPEND_CLR BIT(29) ++#define L1C_DMA_WDLY_CNT_MASK ASHFT16(0xFUL) ++#define L1C_DMA_WDLY_CNT_SHIFT 16 ++#define L1C_DMA_WDLY_CNT_DEF 4 ++#define L1C_DMA_RDLY_CNT_MASK ASHFT11(0x1FUL) ++#define L1C_DMA_RDLY_CNT_SHIFT 11 ++#define L1C_DMA_RDLY_CNT_DEF 15 ++#define L1C_DMA_RREQ_PRI_DATA BIT(10) /* 0:tpd, 1:data */ ++#define L1C_DMA_WREQ_BLEN_MASK ASHFT7(7UL) ++#define L1C_DMA_WREQ_BLEN_SHIFT 7 ++#define L1C_DMA_RREQ_BLEN_MASK ASHFT4(7UL) ++#define L1C_DMA_RREQ_BLEN_SHIFT 4 ++#define L1C_DMA_RCB_LEN128 BIT(3) /* 0:64bytes,1:128bytes */ ++#define L1C_DMA_RORDER_MODE_MASK ASHFT0(7UL) ++#define L1C_DMA_RORDER_MODE_SHIFT 0 ++#define L1C_DMA_RORDER_MODE_OUT 4 ++#define L1C_DMA_RORDER_MODE_ENHANCE 2 ++#define L1C_DMA_RORDER_MODE_IN 1 ++ ++#define L1C_SMB_TIMER 0x15C4 ++ ++#define L1C_TINT_TPD_THRSHLD 0x15C8 ++ ++#define L1C_TINT_TIMER 0x15CC ++ ++#define L1C_ISR 0x1600 ++#define L1C_ISR_DIS BIT(31) ++#define L1C_ISR_PCIE_LNKDOWN BIT(26) ++#define L1C_ISR_PCIE_CERR BIT(25) ++#define L1C_ISR_PCIE_NFERR BIT(24) ++#define L1C_ISR_PCIE_FERR BIT(23) ++#define L1C_ISR_PCIE_UR BIT(22) ++#define L1C_ISR_MAC_TX BIT(21) ++#define L1C_ISR_MAC_RX BIT(20) ++#define L1C_ISR_RX_Q0 BIT(16) ++#define L1C_ISR_TX_Q0 BIT(15) ++#define L1C_ISR_TXQ_TO BIT(14) ++#define L1C_ISR_PHY_LPW BIT(13) ++#define L1C_ISR_PHY BIT(12) ++#define L1C_ISR_TX_CREDIT BIT(11) ++#define L1C_ISR_DMAW BIT(10) ++#define L1C_ISR_DMAR BIT(9) ++#define L1C_ISR_TXF_UR BIT(8) ++#define L1C_ISR_RFD_UR BIT(4) ++#define L1C_ISR_RXF_OV BIT(3) ++#define L1C_ISR_MANU BIT(2) ++#define L1C_ISR_TIMER BIT(1) ++#define L1C_ISR_SMB BIT(0) ++ ++#define L1C_IMR 0x1604 ++ ++#define L1C_INT_RETRIG 0x1608 /* re-send deassrt/assert ++ * if sw no reflect */ ++#define L1C_INT_RETRIG_TO 20000 /* 40 ms */ ++ ++/* WOL mask register only for L1Dv2.0 and later chips */ ++#define L1D_PATTERN_MASK 0x1620 /* 128bytes, sleep state */ ++#define L1D_PATTERN_MASK_LEN 128 /* 128bytes, 32DWORDs */ ++ ++ ++#define L1C_BTROM_CFG 0x1800 /* pwon rst */ ++ ++#define L1C_DRV 0x1804 /* pwon rst */ ++/* bit definition is in lx_hwcomm.h */ ++ ++#define L1C_DRV_ERR1 0x1808 /* perst */ ++#define L1C_DRV_ERR1_GEN BIT(31) /* geneneral err */ ++#define L1C_DRV_ERR1_NOR BIT(30) /* rrd.nor */ ++#define L1C_DRV_ERR1_TRUNC BIT(29) ++#define L1C_DRV_ERR1_RES BIT(28) ++#define L1C_DRV_ERR1_INTFATAL BIT(27) ++#define L1C_DRV_ERR1_TXQPEND BIT(26) ++#define L1C_DRV_ERR1_DMAW BIT(25) ++#define L1C_DRV_ERR1_DMAR BIT(24) ++#define L1C_DRV_ERR1_PCIELNKDWN BIT(23) ++#define L1C_DRV_ERR1_PKTSIZE BIT(22) ++#define L1C_DRV_ERR1_FIFOFUL BIT(21) ++#define L1C_DRV_ERR1_RFDUR BIT(20) ++#define L1C_DRV_ERR1_RRDSI BIT(19) ++#define L1C_DRV_ERR1_UPDATE BIT(18) ++ ++#define L1C_DRV_ERR2 0x180C /* perst */ ++ ++#define L1C_CLK_GATE 0x1814 ++#define L1C_CLK_GATE_RXMAC BIT(5) ++#define L1C_CLK_GATE_TXMAC BIT(4) ++#define L1C_CLK_GATE_RXQ BIT(3) ++#define L1C_CLK_GATE_TXQ BIT(2) ++#define L1C_CLK_GATE_DMAR BIT(1) ++#define L1C_CLK_GATE_DMAW BIT(0) ++#define L1C_CLK_GATE_ALL (\ ++ L1C_CLK_GATE_RXMAC |\ ++ L1C_CLK_GATE_TXMAC |\ ++ L1C_CLK_GATE_RXQ |\ ++ L1C_CLK_GATE_TXQ |\ ++ L1C_CLK_GATE_DMAR |\ ++ L1C_CLK_GATE_DMAW) ++ ++#define L1C_DBG_ADDR 0x1900 /* DWORD reg */ ++#define L1C_DBG_DATA 0x1904 /* DWORD reg */ ++ ++/***************************** IO mapping registers ***************************/ ++#define L1C_IO_ADDR 0x00 /* DWORD reg */ ++#define L1C_IO_DATA 0x04 /* DWORD reg */ ++#define L1C_IO_MASTER 0x08 /* DWORD same as reg0x1400 */ ++#define L1C_IO_MAC_CTRL 0x0C /* DWORD same as reg0x1480*/ ++#define L1C_IO_ISR 0x10 /* DWORD same as reg0x1600 */ ++#define L1C_IO_IMR 0x14 /* DWORD same as reg0x1604 */ ++#define L1C_IO_TPD_PRI1_PIDX 0x18 /* WORD same as reg0x15F0 */ ++#define L1C_IO_TPD_PRI0_PIDX 0x1A /* WORD same as reg0x15F2 */ ++#define L1C_IO_TPD_PRI1_CIDX 0x1C /* WORD same as reg0x15F4 */ ++#define L1C_IO_TPD_PRI0_CIDX 0x1E /* WORD same as reg0x15F6 */ ++#define L1C_IO_RFD_PIDX 0x20 /* WORD same as reg0x15E0 */ ++#define L1C_IO_RFD_CIDX 0x30 /* WORD same as reg0x15F8 */ ++#define L1C_IO_MDIO 0x38 /* WORD same as reg0x1414 */ ++#define L1C_IO_PHY_CTRL 0x3C /* DWORD same as reg0x140C */ ++ ++ ++ ++/********************* PHY regs definition ***************************/ ++ ++/* Autoneg Advertisement Register (0x4) */ ++#define L1C_ADVERTISE_SPEED_MASK 0x01E0 ++#define L1C_ADVERTISE_DEFAULT_CAP 0x0DE0 /* diff with L1C */ ++ ++/* 1000BASE-T Control Register (0x9) */ ++#define L1C_GIGA_CR_1000T_HD_CAPS 0x0100 ++#define L1C_GIGA_CR_1000T_FD_CAPS 0x0200 ++#define L1C_GIGA_CR_1000T_REPEATER_DTE 0x0400 ++#define L1C_GIGA_CR_1000T_MS_VALUE 0x0800 ++#define L1C_GIGA_CR_1000T_MS_ENABLE 0x1000 ++#define L1C_GIGA_CR_1000T_TEST_MODE_NORMAL 0x0000 ++#define L1C_GIGA_CR_1000T_TEST_MODE_1 0x2000 ++#define L1C_GIGA_CR_1000T_TEST_MODE_2 0x4000 ++#define L1C_GIGA_CR_1000T_TEST_MODE_3 0x6000 ++#define L1C_GIGA_CR_1000T_TEST_MODE_4 0x8000 ++#define L1C_GIGA_CR_1000T_SPEED_MASK 0x0300 ++#define L1C_GIGA_CR_1000T_DEFAULT_CAP 0x0300 ++ ++/* 1000BASE-T Status Register */ ++#define L1C_MII_GIGA_SR 0x0A ++ ++/* PHY Specific Status Register */ ++#define L1C_MII_GIGA_PSSR 0x11 ++#define L1C_GIGA_PSSR_FC_RXEN 0x0004 ++#define L1C_GIGA_PSSR_FC_TXEN 0x0008 ++#define L1C_GIGA_PSSR_SPD_DPLX_RESOLVED 0x0800 ++#define L1C_GIGA_PSSR_DPLX 0x2000 ++#define L1C_GIGA_PSSR_SPEED 0xC000 ++#define L1C_GIGA_PSSR_10MBS 0x0000 ++#define L1C_GIGA_PSSR_100MBS 0x4000 ++#define L1C_GIGA_PSSR_1000MBS 0x8000 ++ ++/* PHY Interrupt Enable Register */ ++#define L1C_MII_IER 0x12 ++#define L1C_IER_LINK_UP 0x0400 ++#define L1C_IER_LINK_DOWN 0x0800 ++ ++/* PHY Interrupt Status Register */ ++#define L1C_MII_ISR 0x13 ++#define L1C_ISR_LINK_UP 0x0400 ++#define L1C_ISR_LINK_DOWN 0x0800 ++ ++/* Cable-Detect-Test Control Register */ ++#define L1C_MII_CDTC 0x16 ++#define L1C_CDTC_EN 1 /* sc */ ++#define L1C_CDTC_PAIR_MASK ASHFT8(3U) ++#define L1C_CDTC_PAIR_SHIFT 8 ++ ++ ++/* Cable-Detect-Test Status Register */ ++#define L1C_MII_CDTS 0x1C ++#define L1C_CDTS_STATUS_MASK ASHFT8(3U) ++#define L1C_CDTS_STATUS_SHIFT 8 ++#define L1C_CDTS_STATUS_NORMAL 0 ++#define L1C_CDTS_STATUS_SHORT 1 ++#define L1C_CDTS_STATUS_OPEN 2 ++#define L1C_CDTS_STATUS_INVALID 3 ++ ++#define L1C_MII_DBG_ADDR 0x1D ++#define L1C_MII_DBG_DATA 0x1E ++ ++/***************************** debug port *************************************/ ++ ++#define L1C_MIIDBG_ANACTRL 0x00 ++#define L1C_ANACTRL_CLK125M_DELAY_EN BIT(15) ++#define L1C_ANACTRL_VCO_FAST BIT(14) ++#define L1C_ANACTRL_VCO_SLOW BIT(13) ++#define L1C_ANACTRL_AFE_MODE_EN BIT(12) ++#define L1C_ANACTRL_LCKDET_PHY BIT(11) ++#define L1C_ANACTRL_LCKDET_EN BIT(10) ++#define L1C_ANACTRL_OEN_125M BIT(9) ++#define L1C_ANACTRL_HBIAS_EN BIT(8) ++#define L1C_ANACTRL_HB_EN BIT(7) ++#define L1C_ANACTRL_SEL_HSP BIT(6) ++#define L1C_ANACTRL_CLASSA_EN BIT(5) ++#define L1C_ANACTRL_MANUSWON_SWR_MASK ASHFT2(3U) ++#define L1C_ANACTRL_MANUSWON_SWR_SHIFT 2 ++#define L1C_ANACTRL_MANUSWON_SWR_2V 0 ++#define L1C_ANACTRL_MANUSWON_SWR_1P9V 1 ++#define L1C_ANACTRL_MANUSWON_SWR_1P8V 2 ++#define L1C_ANACTRL_MANUSWON_SWR_1P7V 3 ++#define L1C_ANACTRL_MANUSWON_BW3_4M BIT(1) ++#define L1C_ANACTRL_RESTART_CAL BIT(0) ++#define L1C_ANACTRL_DEF 0x02EF ++ ++ ++#define L1C_MIIDBG_SYSMODCTRL 0x04 ++#define L1C_SYSMODCTRL_IECHOADJ_PFMH_PHY BIT(15) ++#define L1C_SYSMODCTRL_IECHOADJ_BIASGEN BIT(14) ++#define L1C_SYSMODCTRL_IECHOADJ_PFML_PHY BIT(13) ++#define L1C_SYSMODCTRL_IECHOADJ_PS_MASK ASHFT10(3U) ++#define L1C_SYSMODCTRL_IECHOADJ_PS_SHIFT 10 ++#define L1C_SYSMODCTRL_IECHOADJ_PS_40 3 ++#define L1C_SYSMODCTRL_IECHOADJ_PS_20 2 ++#define L1C_SYSMODCTRL_IECHOADJ_PS_0 1 ++#define L1C_SYSMODCTRL_IECHOADJ_10BT_100MV BIT(6) /* 1:100mv, 0:200mv */ ++#define L1C_SYSMODCTRL_IECHOADJ_HLFAP_MASK ASHFT4(3U) ++#define L1C_SYSMODCTRL_IECHOADJ_HLFAP_SHIFT 4 ++#define L1C_SYSMODCTRL_IECHOADJ_VDFULBW BIT(3) ++#define L1C_SYSMODCTRL_IECHOADJ_VDBIASHLF BIT(2) ++#define L1C_SYSMODCTRL_IECHOADJ_VDAMPHLF BIT(1) ++#define L1C_SYSMODCTRL_IECHOADJ_VDLANSW BIT(0) ++#define L1C_SYSMODCTRL_IECHOADJ_DEF 0x88BB /* ???? */ ++ ++ ++ ++#define L1D_MIIDBG_SYSMODCTRL 0x04 /* l1d & l2cb */ ++#define L1D_SYSMODCTRL_IECHOADJ_CUR_ADD BIT(15) ++#define L1D_SYSMODCTRL_IECHOADJ_CUR_MASK ASHFT12(7U) ++#define L1D_SYSMODCTRL_IECHOADJ_CUR_SHIFT 12 ++#define L1D_SYSMODCTRL_IECHOADJ_VOL_MASK ASHFT8(0xFU) ++#define L1D_SYSMODCTRL_IECHOADJ_VOL_SHIFT 8 ++#define L1D_SYSMODCTRL_IECHOADJ_VOL_17ALL 3 ++#define L1D_SYSMODCTRL_IECHOADJ_VOL_100M15 1 ++#define L1D_SYSMODCTRL_IECHOADJ_VOL_10M17 0 ++#define L1D_SYSMODCTRL_IECHOADJ_BIAS1_MASK ASHFT4(0xFU) ++#define L1D_SYSMODCTRL_IECHOADJ_BIAS1_SHIFT 4 ++#define L1D_SYSMODCTRL_IECHOADJ_BIAS2_MASK ASHFT0(0xFU) ++#define L1D_SYSMODCTRL_IECHOADJ_BIAS2_SHIFT 0 ++#define L1D_SYSMODCTRL_IECHOADJ_DEF 0x4FBB ++ ++ ++#define L1C_MIIDBG_SRDSYSMOD 0x05 ++#define L1C_SRDSYSMOD_LCKDET_EN BIT(13) ++#define L1C_SRDSYSMOD_PLL_EN BIT(11) ++#define L1C_SRDSYSMOD_SEL_HSP BIT(10) ++#define L1C_SRDSYSMOD_HLFTXDR BIT(9) ++#define L1C_SRDSYSMOD_TXCLK_DELAY_EN BIT(8) ++#define L1C_SRDSYSMOD_TXELECIDLE BIT(7) ++#define L1C_SRDSYSMOD_DEEMP_EN BIT(6) ++#define L1C_SRDSYSMOD_MS_PAD BIT(2) ++#define L1C_SRDSYSMOD_CDR_ADC_VLTG BIT(1) ++#define L1C_SRDSYSMOD_CDR_DAC_1MA BIT(0) ++#define L1C_SRDSYSMOD_DEF 0x2C46 ++ ++#define L1C_MIIDBG_CFGLPSPD 0x0A ++#define L1C_CFGLPSPD_RSTCNT_MASK ASHFT(3U) ++#define L1C_CFGLPSPD_RSTCNT_SHIFT 14 ++#define L1C_CFGLPSPD_RSTCNT_CLK125SW BIT(13) ++ ++#define L1C_MIIDBG_HIBNEG 0x0B ++#define L1C_HIBNEG_PSHIB_EN BIT(15) ++#define L1C_HIBNEG_WAKE_BOTH BIT(14) ++#define L1C_HIBNEG_ONOFF_ANACHG_SUDEN BIT(13) ++#define L1C_HIBNEG_HIB_PULSE BIT(12) ++#define L1C_HIBNEG_GATE_25M_EN BIT(11) ++#define L1C_HIBNEG_RST_80U BIT(10) ++#define L1C_HIBNEG_RST_TIMER_MASK ASHFT8(3U) ++#define L1C_HIBNEG_RST_TIMER_SHIFT 8 ++#define L1C_HIBNEG_GTX_CLK_DELAY_MASK ASHFT5(3U) ++#define L1C_HIBNEG_GTX_CLK_DELAY_SHIFT 5 ++#define L1C_HIBNEG_BYPSS_BRKTIMER BIT(4) ++#define L1C_HIBNEG_DEF 0xBC40 ++ ++#define L1C_MIIDBG_TST10BTCFG 0x12 ++#define L1C_TST10BTCFG_INTV_TIMER_MASK ASHFT14(3U) ++#define L1C_TST10BTCFG_INTV_TIMER_SHIFT 14 ++#define L1C_TST10BTCFG_TRIGER_TIMER_MASK ASHFT12(3U) ++#define L1C_TST10BTCFG_TRIGER_TIMER_SHIFT 12 ++#define L1C_TST10BTCFG_DIV_MAN_MLT3_EN BIT(11) ++#define L1C_TST10BTCFG_OFF_DAC_IDLE BIT(10) ++#define L1C_TST10BTCFG_LPBK_DEEP BIT(2) /* 1:deep,0:shallow */ ++#define L1C_TST10BTCFG_DEF 0x4C04 ++ ++#define L1C_MIIDBG_AZ_ANADECT 0x15 ++#define L1C_AZ_ANADECT_10BTRX_TH BIT(15) ++#define L1C_AZ_ANADECT_BOTH_01CHNL BIT(14) ++#define L1C_AZ_ANADECT_INTV_MASK ASHFT8(0x3FU) ++#define L1C_AZ_ANADECT_INTV_SHIFT 8 ++#define L1C_AZ_ANADECT_THRESH_MASK ASHFT4(0xFU) ++#define L1C_AZ_ANADECT_THRESH_SHIFT 4 ++#define L1C_AZ_ANADECT_CHNL_MASK ASHFT0(0xFU) ++#define L1C_AZ_ANADECT_CHNL_SHIFT 0 ++#define L1C_AZ_ANADECT_DEF 0x3220 ++#define L1C_AZ_ANADECT_LONG 0xb210 ++ ++#define L1D_MIIDBG_MSE16DB 0x18 ++#define L1D_MSE16DB_UP 0x05EA ++#define L1D_MSE16DB_DOWN 0x02EA ++ ++ ++#define L1C_MIIDBG_LEGCYPS 0x29 ++#define L1C_LEGCYPS_EN BIT(15) ++#define L1C_LEGCYPS_DAC_AMP1000_MASK ASHFT12(7U) ++#define L1C_LEGCYPS_DAC_AMP1000_SHIFT 12 ++#define L1C_LEGCYPS_DAC_AMP100_MASK ASHFT9(7U) ++#define L1C_LEGCYPS_DAC_AMP100_SHIFT 9 ++#define L1C_LEGCYPS_DAC_AMP10_MASK ASHFT6(7U) ++#define L1C_LEGCYPS_DAC_AMP10_SHIFT 6 ++#define L1C_LEGCYPS_UNPLUG_TIMER_MASK ASHFT3(7U) ++#define L1C_LEGCYPS_UNPLUG_TIMER_SHIFT 3 ++#define L1C_LEGCYPS_UNPLUG_DECT_EN BIT(2) ++#define L1C_LEGCYPS_ECNC_PS_EN BIT(0) ++#define L1D_LEGCYPS_DEF 0x129D ++#define L1C_LEGCYPS_DEF 0x36DD ++ ++#define L1C_MIIDBG_TST100BTCFG 0x36 ++#define L1C_TST100BTCFG_NORMAL_BW_EN BIT(15) ++#define L1C_TST100BTCFG_BADLNK_BYPASS BIT(14) ++#define L1C_TST100BTCFG_SHORTCABL_TH_MASK ASHFT8(0x3FU) ++#define L1C_TST100BTCFG_SHORTCABL_TH_SHIFT 8 ++#define L1C_TST100BTCFG_LITCH_EN BIT(7) ++#define L1C_TST100BTCFG_VLT_SW BIT(6) ++#define L1C_TST100BTCFG_LONGCABL_TH_MASK ASHFT0(0x3FU) ++#define L1C_TST100BTCFG_LONGCABL_TH_SHIFT 0 ++#define L1C_TST100BTCFG_DEF 0xE12C ++ ++#define L1C_MIIDBG_VOLT_CTRL 0x3B ++#define L1C_VOLT_CTRL_CABLE1TH_MASK ASHFT7(0x1FFU) ++#define L1C_VOLT_CTRL_CABLE1TH_SHIFT 7 ++#define L1C_VOLT_CTRL_AMPCTRL_MASK ASHFT5(3U) ++#define L1C_VOLT_CTRL_AMPCTRL_SHIFT 5 ++#define L1C_VOLT_CTRL_SW_BYPASS BIT(4) ++#define L1C_VOLT_CTRL_SWLOWEST BIT(3) ++#define L1C_VOLT_CTRL_DACAMP10_MASK ASHFT0(7U) ++#define L1C_VOLT_CTRL_DACAMP10_SHIFT 0 ++ ++#define L1C_MIIDBG_CABLE1TH_DET 0x3E ++#define L1C_CABLE1TH_DET_EN BIT(15) ++ ++/***************************** extension **************************************/ ++ ++/******* dev 3 *********/ ++#define L1C_MIIEXT_PCS 3 ++ ++#define L1C_MIIEXT_CLDCTRL3 0x8003 ++#define L1C_CLDCTRL3_BP_CABLE1TH_DET_GT BIT(15) ++#define L1C_CLDCTRL3_AZ_DISAMP BIT(12) ++#define L1C_CLDCTRL3_L2CB 0x4D19 ++#define L1C_CLDCTRL3_L1D 0xDD19 ++ ++#define L1C_MIIEXT_CLDCTRL6 0x8006 ++#define L1C_CLDCTRL6_CAB_LEN_MASK ASHFT0(0x1FFU) ++#define L1C_CLDCTRL6_CAB_LEN_SHIFT 0 ++#define L1C_CLDCTRL6_CAB_LEN_SHORT 0x50 ++ ++#define L1C_MIIEXT_CLDCTRL7 0x8007 ++#define L1C_CLDCTRL7_VDHLF_BIAS_TH_MASK ASHFT9(0x7FU) ++#define L1C_CLDCTRL7_VDHLF_BIAS_TH_SHIFT 9 ++#define L1C_CLDCTRL7_AFE_AZ_MASK ASHFT4(0x1FU) ++#define L1C_CLDCTRL7_AFE_AZ_SHIFT 4 ++#define L1C_CLDCTRL7_SIDE_PEAK_TH_MASK ASHFT0(0xFU) ++#define L1C_CLDCTRL7_SIDE_PEAK_TH_SHIFT 0 ++#define L1C_CLDCTRL7_DEF 0x6BF6 /* ???? */ ++#define L1C_CLDCTRL7_FPGA_DEF 0x0005 ++#define L1C_CLDCTRL7_L2CB 0x0175 ++ ++#define L1C_MIIEXT_AZCTRL 0x8008 ++#define L1C_AZCTRL_SHORT_TH_MASK ASHFT8(0xFFU) ++#define L1C_AZCTRL_SHORT_TH_SHIFT 8 ++#define L1C_AZCTRL_LONG_TH_MASK ASHFT0(0xFFU) ++#define L1C_AZCTRL_LONG_TH_SHIFT 0 ++#define L1C_AZCTRL_DEF 0x1629 ++#define L1C_AZCTRL_FPGA_DEF 0x101D ++#define L1C_AZCTRL_L1D 0x2034 ++ ++#define L1C_MIIEXT_AZCTRL2 0x8009 ++#define L1C_AZCTRL2_WAKETRNING_MASK ASHFT8(0xFFU) ++#define L1C_AZCTRL2_WAKETRNING_SHIFT 8 ++#define L1C_AZCTRL2_QUIET_TIMER_MASH ASHFT6(3U) ++#define L1C_AZCTRL2_QUIET_TIMER_SHIFT 6 ++#define L1C_AZCTRL2_PHAS_JMP2 BIT(4) ++#define L1C_AZCTRL2_CLKTRCV_125MD16 BIT(3) ++#define L1C_AZCTRL2_GATE1000_EN BIT(2) ++#define L1C_AZCTRL2_AVRG_FREQ BIT(1) ++#define L1C_AZCTRL2_PHAS_JMP4 BIT(0) ++#define L1C_AZCTRL2_DEF 0x32C0 ++#define L1C_AZCTRL2_FPGA_DEF 0x40C8 ++#define L1C_AZCTRL2_L2CB 0xE003 ++#define L1C_AZCTRL2_L1D2 0x18C0 ++ ++ ++#define L1C_MIIEXT_AZCTRL4 0x800B ++#define L1C_AZCTRL4_WAKE_STH_L2CB 0x0094 ++ ++#define L1C_MIIEXT_AZCTRL5 0x800C ++#define L1C_AZCTRL5_WAKE_LTH_L2CB 0x00EB ++ ++#define L1C_MIIEXT_AZCTRL6 0x800D ++#define L1C_AZCTRL6_L1D2 0x003F ++ ++ ++ ++/********* dev 7 **********/ ++#define L1C_MIIEXT_ANEG 7 ++ ++#define L1C_MIIEXT_LOCAL_EEEADV 0x3C ++#define L1C_LOCAL_EEEADV_1000BT BIT(2) ++#define L1C_LOCAL_EEEADV_100BT BIT(1) ++ ++#define L1C_MIIEXT_REMOTE_EEEADV 0x3D ++#define L1C_REMOTE_EEEADV_1000BT BIT(2) ++#define L1C_REMOTE_EEEADV_100BT BIT(1) ++ ++#define L1C_MIIEXT_EEE_ANEG 0x8000 ++#define L1C_EEE_ANEG_1000M BIT(2) ++#define L1C_EEE_ANEG_100M BIT(1) ++ ++ ++ ++ ++/******************************************************************************/ ++ ++/* functions */ ++ ++/* get permanent mac address from ++ * return ++ * 0: success ++ * non-0:fail ++ */ ++u16 l1c_get_perm_macaddr(struct alx_hw *hw, u8 *addr); ++ ++ ++/* reset mac & dma ++ * return ++ * 0: success ++ * non-0:fail ++ */ ++u16 l1c_reset_mac(struct alx_hw *hw); ++ ++/* reset phy ++ * return ++ * 0: success ++ * non-0:fail ++ */ ++u16 l1c_reset_phy(struct alx_hw *hw, bool pws_en, bool az_en, bool ptp_en); ++ ++ ++/* reset pcie ++ * just reset pcie relative registers (pci command, clk, aspm...) ++ * return ++ * 0:success ++ * non-0:fail ++ */ ++u16 l1c_reset_pcie(struct alx_hw *hw, bool l0s_en, bool l1_en); ++ ++ ++/* disable/enable MAC/RXQ/TXQ ++ * en ++ * true:enable ++ * false:disable ++ * return ++ * 0:success ++ * non-0-fail ++ */ ++u16 l1c_enable_mac(struct alx_hw *hw, bool en, u16 en_ctrl); ++ ++/* enable/disable aspm support ++ * that will change settings for phy/mac/pcie ++ */ ++u16 l1c_enable_aspm(struct alx_hw *hw, bool l0s_en, bool l1_en, u8 lnk_stat); ++ ++ ++/* initialize phy for speed / flow control ++ * lnk_cap ++ * if autoNeg, is link capability to tell the peer ++ * if force mode, is forced speed/duplex ++ */ ++u16 l1c_init_phy_spdfc(struct alx_hw *hw, bool auto_neg, ++ u8 lnk_cap, bool fc_en); ++ ++/* do post setting on phy if link up/down event occur ++ */ ++u16 l1c_post_phy_link(struct alx_hw *hw, bool linkon, u8 wire_spd); ++ ++ ++/* do power saving setting befor enter suspend mode ++ * NOTE: ++ * 1. phy link must be established before calling this function ++ * 2. wol option (pattern,magic,link,etc.) is configed before call it. ++ */ ++u16 l1c_powersaving(struct alx_hw *hw, u8 wire_spd, bool wol_en, ++ bool mac_txen, bool mac_rxen, bool pws_en); ++ ++ ++/* read phy register */ ++u16 l1c_read_phy(struct alx_hw *hw, bool ext, u8 dev, bool fast, u16 reg, ++ u16 *data); ++ ++/* write phy register */ ++u16 l1c_write_phy(struct alx_hw *hw, bool ext, u8 dev, bool fast, u16 reg, ++ u16 data); ++ ++/* phy debug port */ ++u16 l1c_read_phydbg(struct alx_hw *hw, bool fast, u16 reg, u16 *data); ++u16 l1c_write_phydbg(struct alx_hw *hw, bool fast, u16 reg, u16 data); ++ ++/* check the configuration of the PHY */ ++u16 l1c_get_phy_config(struct alx_hw *hw); ++ ++/* ++ * initialize mac basically ++ * most of hi-feature no init ++ * MAC/PHY should be reset before call this function ++ */ ++u16 l1c_init_mac(struct alx_hw *hw, u8 *addr, u32 txmem_hi, ++ u32 *tx_mem_lo, u8 tx_qnum, u16 txring_sz, ++ u32 rxmem_hi, u32 rfdmem_lo, u32 rrdmem_lo, ++ u16 rxring_sz, u16 rxbuf_sz, u16 smb_timer, ++ u16 mtu, u16 int_mod, bool hash_legacy); ++ ++ ++ ++#endif/*L1C_HW_H_*/ ++ +diff --git a/drivers/net/ethernet/atheros/alx/alf_cb.c b/drivers/net/ethernet/atheros/alx/alf_cb.c +new file mode 100644 +index 0000000..d267760 +--- /dev/null ++++ b/drivers/net/ethernet/atheros/alx/alf_cb.c +@@ -0,0 +1,1187 @@ ++/* ++ * Copyright (c) 2012 Qualcomm Atheros, Inc. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++ ++#include "alf_hw.h" ++ ++ ++#define ALF_REV_ID_AR8161_B0 0x10 ++ ++/* definition for MSIX */ ++#define ALF_MSIX_ENTRY_BASE 0x2000 ++#define ALF_MSIX_ENTRY_SIZE 16 ++#define ALF_MSIX_MSG_LOADDR_OFF 0 ++#define ALF_MSIX_MSG_HIADDR_OFF 4 ++#define ALF_MSIX_MSG_DATA_OFF 8 ++#define ALF_MSIX_MSG_CTRL_OFF 12 ++ ++#define ALF_MSIX_INDEX_RXQ0 0 ++#define ALF_MSIX_INDEX_RXQ1 1 ++#define ALF_MSIX_INDEX_RXQ2 2 ++#define ALF_MSIX_INDEX_RXQ3 3 ++#define ALF_MSIX_INDEX_RXQ4 4 ++#define ALF_MSIX_INDEX_RXQ5 5 ++#define ALF_MSIX_INDEX_RXQ6 6 ++#define ALF_MSIX_INDEX_RXQ7 7 ++#define ALF_MSIX_INDEX_TXQ0 8 ++#define ALF_MSIX_INDEX_TXQ1 9 ++#define ALF_MSIX_INDEX_TXQ2 10 ++#define ALF_MSIX_INDEX_TXQ3 11 ++#define ALF_MSIX_INDEX_TIMER 12 ++#define ALF_MSIX_INDEX_ALERT 13 ++#define ALF_MSIX_INDEX_SMB 14 ++#define ALF_MSIX_INDEX_PHY 15 ++ ++ ++#define ALF_SRAM_BASE L1F_SRAM0 ++#define ALF_SRAM(_i, _type) \ ++ (ALF_SRAM_BASE + ((_i) * sizeof(_type))) ++ ++#define ALF_MIB_BASE L1F_MIB_BASE ++#define ALF_MIB(_i, _type) \ ++ (ALF_MIB_BASE + ((_i) * sizeof(_type))) ++ ++/* definition for RSS */ ++#define ALF_RSS_KEY_BASE L1F_RSS_KEY0 ++#define ALF_RSS_IDT_BASE L1F_RSS_IDT_TBL0 ++#define ALF_RSS_KEY(_i, _type) \ ++ (ALF_RSS_KEY_BASE + ((_i) * sizeof(_type))) ++#define ALF_RSS_TBL(_i, _type) \ ++ (L1F_RSS_IDT_TBL0 + ((_i) * sizeof(_type))) ++ ++ ++/* NIC */ ++static int alf_identify_nic(struct alx_hw *hw) ++{ ++ u32 drv; ++ ++ if (hw->pci_revid < ALX_REV_ID_AR8161_V2_0) ++ return 0; ++ ++ /* check from V2_0(b0) to ... */ ++ switch (hw->pci_revid) { ++ default: ++ alx_mem_r32(hw, L1F_DRV, &drv); ++ if (drv & LX_DRV_DISABLE) ++ return -EINVAL; ++ break; ++ } ++ return 0; ++} ++ ++ ++/* PHY */ ++static int alf_read_phy_reg(struct alx_hw *hw, u16 reg_addr, u16 *phy_data) ++{ ++ unsigned long flags; ++ int retval = 0; ++ ++ spin_lock_irqsave(&hw->mdio_lock, flags); ++ ++ if (l1f_read_phy(hw, false, ALX_MDIO_DEV_TYPE_NORM, false, reg_addr, ++ phy_data)) { ++ alx_hw_err(hw, "error when read phy reg\n"); ++ retval = -EINVAL; ++ } ++ ++ spin_unlock_irqrestore(&hw->mdio_lock, flags); ++ return retval; ++} ++ ++ ++static int alf_write_phy_reg(struct alx_hw *hw, u16 reg_addr, u16 phy_data) ++{ ++ unsigned long flags; ++ int retval = 0; ++ ++ spin_lock_irqsave(&hw->mdio_lock, flags); ++ ++ if (l1f_write_phy(hw, false, ALX_MDIO_DEV_TYPE_NORM, false, reg_addr, ++ phy_data)) { ++ alx_hw_err(hw, "error when write phy reg\n"); ++ retval = -EINVAL; ++ } ++ ++ spin_unlock_irqrestore(&hw->mdio_lock, flags); ++ return retval; ++} ++ ++ ++static int alf_init_phy(struct alx_hw *hw) ++{ ++ u16 phy_id[2]; ++ int retval; ++ ++ spin_lock_init(&hw->mdio_lock); ++ ++ retval = alf_read_phy_reg(hw, MII_PHYSID1, &phy_id[0]); ++ if (retval) ++ return retval; ++ retval = alf_read_phy_reg(hw, MII_PHYSID2, &phy_id[1]); ++ if (retval) ++ return retval; ++ memcpy(&hw->phy_id, phy_id, sizeof(hw->phy_id)); ++ ++ hw->autoneg_advertised = ALX_LINK_SPEED_1GB_FULL | ++ ALX_LINK_SPEED_10_HALF | ++ ALX_LINK_SPEED_10_FULL | ++ ALX_LINK_SPEED_100_HALF | ++ ALX_LINK_SPEED_100_FULL; ++ return retval; ++} ++ ++ ++static int alf_reset_phy(struct alx_hw *hw) ++{ ++ int retval = 0; ++ bool pws_en, az_en, ptp_en; ++ ++ pws_en = az_en = ptp_en = false; ++ CLI_HW_FLAG(PWSAVE_EN); ++ CLI_HW_FLAG(AZ_EN); ++ CLI_HW_FLAG(PTP_EN); ++ ++ if (CHK_HW_FLAG(PWSAVE_CAP)) { ++ pws_en = true; ++ SET_HW_FLAG(PWSAVE_EN); ++ } ++ ++ if (CHK_HW_FLAG(AZ_CAP)) { ++ az_en = true; ++ SET_HW_FLAG(AZ_EN); ++ } ++ ++ if (CHK_HW_FLAG(PTP_CAP)) { ++ ptp_en = true; ++ SET_HW_FLAG(PTP_EN); ++ } ++ ++ alx_hw_info(hw, "reset PHY, pws = %d, az = %d, ptp = %d\n", ++ pws_en, az_en, ptp_en); ++ if (l1f_reset_phy(hw, pws_en, az_en, ptp_en)) { ++ alx_hw_err(hw, "error when reset phy\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++/* LINK */ ++static int alf_setup_phy_link(struct alx_hw *hw, u32 speed, bool autoneg, ++ bool fc) ++{ ++ u8 link_cap = 0; ++ int retval = 0; ++ ++ alx_hw_info(hw, "speed = 0x%x, autoneg = %d\n", speed, autoneg); ++ if (speed & ALX_LINK_SPEED_1GB_FULL) ++ link_cap |= LX_LC_1000F; ++ ++ if (speed & ALX_LINK_SPEED_100_FULL) ++ link_cap |= LX_LC_100F; ++ ++ if (speed & ALX_LINK_SPEED_100_HALF) ++ link_cap |= LX_LC_100H; ++ ++ if (speed & ALX_LINK_SPEED_10_FULL) ++ link_cap |= LX_LC_10F; ++ ++ if (speed & ALX_LINK_SPEED_10_HALF) ++ link_cap |= LX_LC_10H; ++ ++ if (l1f_init_phy_spdfc(hw, autoneg, link_cap, fc)) { ++ alx_hw_err(hw, "error when init phy speed and fc\n"); ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++ ++static int alf_setup_phy_link_speed(struct alx_hw *hw, u32 speed, ++ bool autoneg, bool fc) ++{ ++ /* ++ * Clear autoneg_advertised and set new values based on input link ++ * speed. ++ */ ++ hw->autoneg_advertised = 0; ++ ++ if (speed & ALX_LINK_SPEED_1GB_FULL) ++ hw->autoneg_advertised |= ALX_LINK_SPEED_1GB_FULL; ++ ++ if (speed & ALX_LINK_SPEED_100_FULL) ++ hw->autoneg_advertised |= ALX_LINK_SPEED_100_FULL; ++ ++ if (speed & ALX_LINK_SPEED_100_HALF) ++ hw->autoneg_advertised |= ALX_LINK_SPEED_100_HALF; ++ ++ if (speed & ALX_LINK_SPEED_10_FULL) ++ hw->autoneg_advertised |= ALX_LINK_SPEED_10_FULL; ++ ++ if (speed & ALX_LINK_SPEED_10_HALF) ++ hw->autoneg_advertised |= ALX_LINK_SPEED_10_HALF; ++ ++ return alf_setup_phy_link(hw, hw->autoneg_advertised, ++ autoneg, fc); ++} ++ ++ ++static int alf_check_phy_link(struct alx_hw *hw, u32 *speed, bool *link_up) ++{ ++ u16 bmsr, giga; ++ int retval; ++ ++ alf_read_phy_reg(hw, MII_BMSR, &bmsr); ++ retval = alf_read_phy_reg(hw, MII_BMSR, &bmsr); ++ if (retval) ++ return retval; ++ ++ if (!(bmsr & BMSR_LSTATUS)) { ++ *link_up = false; ++ *speed = ALX_LINK_SPEED_UNKNOWN; ++ return 0; ++ } ++ *link_up = true; ++ ++ /* Read PHY Specific Status Register (17) */ ++ retval = alf_read_phy_reg(hw, L1F_MII_GIGA_PSSR, &giga); ++ if (retval) ++ return retval; ++ ++ ++ if (!(giga & L1F_GIGA_PSSR_SPD_DPLX_RESOLVED)) { ++ alx_hw_err(hw, "error for speed duplex resolved\n"); ++ return -EINVAL; ++ } ++ ++ switch (giga & L1F_GIGA_PSSR_SPEED) { ++ case L1F_GIGA_PSSR_1000MBS: ++ if (giga & L1F_GIGA_PSSR_DPLX) ++ *speed = ALX_LINK_SPEED_1GB_FULL; ++ else ++ alx_hw_err(hw, "1000M half is invalid"); ++ break; ++ case L1F_GIGA_PSSR_100MBS: ++ if (giga & L1F_GIGA_PSSR_DPLX) ++ *speed = ALX_LINK_SPEED_100_FULL; ++ else ++ *speed = ALX_LINK_SPEED_100_HALF; ++ break; ++ case L1F_GIGA_PSSR_10MBS: ++ if (giga & L1F_GIGA_PSSR_DPLX) ++ *speed = ALX_LINK_SPEED_10_FULL; ++ else ++ *speed = ALX_LINK_SPEED_10_HALF; ++ break; ++ default: ++ *speed = ALX_LINK_SPEED_UNKNOWN; ++ retval = -EINVAL; ++ break; ++ } ++ return retval; ++} ++ ++ ++/* ++ * 1. stop_mac ++ * 2. reset mac & dma by reg1400(MASTER) ++ * 3. control speed/duplex, hash-alg ++ * 4. clock switch setting ++ */ ++static int alf_reset_mac(struct alx_hw *hw) ++{ ++ int retval = 0; ++ ++ if (l1f_reset_mac(hw)) { ++ alx_hw_err(hw, "error when reset mac\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++static int alf_start_mac(struct alx_hw *hw) ++{ ++ u16 en_ctrl = 0; ++ int retval = 0; ++ ++ /* set link speed param */ ++ switch (hw->link_speed) { ++ case ALX_LINK_SPEED_1GB_FULL: ++ en_ctrl |= LX_MACSPEED_1000; ++ /* fall through */ ++ case ALX_LINK_SPEED_100_FULL: ++ case ALX_LINK_SPEED_10_FULL: ++ en_ctrl |= LX_MACDUPLEX_FULL; ++ break; ++ } ++ ++ /* set fc param*/ ++ switch (hw->cur_fc_mode) { ++ case alx_fc_full: ++ en_ctrl |= LX_FC_RXEN; /* Flow Control RX Enable */ ++ en_ctrl |= LX_FC_TXEN; /* Flow Control TX Enable */ ++ break; ++ case alx_fc_rx_pause: ++ en_ctrl |= LX_FC_RXEN; /* Flow Control RX Enable */ ++ break; ++ case alx_fc_tx_pause: ++ en_ctrl |= LX_FC_TXEN; /* Flow Control TX Enable */ ++ break; ++ default: ++ break; ++ } ++ ++ if (hw->fc_single_pause) ++ en_ctrl |= LX_SINGLE_PAUSE; ++ ++ en_ctrl |= LX_FLT_DIRECT; /* RX Enable; and TX Always Enable */ ++ en_ctrl |= LX_FLT_BROADCAST; /* RX Broadcast Enable */ ++ en_ctrl |= LX_ADD_FCS; ++ ++ if (CHK_HW_FLAG(VLANSTRIP_EN)) ++ en_ctrl |= LX_VLAN_STRIP; ++ ++ if (CHK_HW_FLAG(PROMISC_EN)) ++ en_ctrl |= LX_FLT_PROMISC; ++ ++ if (CHK_HW_FLAG(MULTIALL_EN)) ++ en_ctrl |= LX_FLT_MULTI_ALL; ++ ++ if (CHK_HW_FLAG(LOOPBACK_EN)) ++ en_ctrl |= LX_LOOPBACK; ++ ++ if (l1f_enable_mac(hw, true, en_ctrl)) { ++ alx_hw_err(hw, "error when start mac\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++/* ++ * 1. stop RXQ (reg15A0) and TXQ (reg1590) ++ * 2. stop MAC (reg1480) ++ */ ++static int alf_stop_mac(struct alx_hw *hw) ++{ ++ int retval = 0; ++ ++ if (l1f_enable_mac(hw, false, 0)) { ++ alx_hw_err(hw, "error when stop mac\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++static int alf_config_mac(struct alx_hw *hw, u16 rxbuf_sz, u16 rx_qnum, ++ u16 rxring_sz, u16 tx_qnum, u16 txring_sz) ++{ ++ u8 *addr; ++ u32 txmem_hi, txmem_lo[4]; ++ u32 rxmem_hi, rfdmem_lo, rrdmem_lo; ++ u16 smb_timer, mtu_with_eth, int_mod; ++ bool hash_legacy; ++ int i; ++ int retval = 0; ++ ++ addr = hw->mac_addr; ++ ++ txmem_hi = ALX_DMA_ADDR_HI(hw->tpdma[0]); ++ for (i = 0; i < tx_qnum; i++) ++ txmem_lo[i] = ALX_DMA_ADDR_LO(hw->tpdma[i]); ++ ++ ++ rxmem_hi = ALX_DMA_ADDR_HI(hw->rfdma[0]); ++ rfdmem_lo = ALX_DMA_ADDR_LO(hw->rfdma[0]); ++ rrdmem_lo = ALX_DMA_ADDR_LO(hw->rrdma[0]); ++ ++ smb_timer = (u16)hw->smb_timer; ++ mtu_with_eth = hw->mtu + ALX_ETH_LENGTH_OF_HEADER; ++ int_mod = hw->imt; ++ ++ hash_legacy = true; ++ ++ if (l1f_init_mac(hw, addr, txmem_hi, txmem_lo, tx_qnum, txring_sz, ++ rxmem_hi, rfdmem_lo, rrdmem_lo, rxring_sz, rxbuf_sz, ++ smb_timer, mtu_with_eth, int_mod, hash_legacy)) { ++ alx_hw_err(hw, "error when config mac\n"); ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++ ++/** ++ * alf_get_mac_addr ++ * @hw: pointer to hardware structure ++ **/ ++static int alf_get_mac_addr(struct alx_hw *hw, u8 *addr) ++{ ++ int retval = 0; ++ ++ if (l1f_get_perm_macaddr(hw, addr)) { ++ alx_hw_err(hw, "error when get permanent mac address\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++static int alf_reset_pcie(struct alx_hw *hw, bool l0s_en, bool l1_en) ++{ ++ int retval = 0; ++ ++ if (!CHK_HW_FLAG(L0S_CAP)) ++ l0s_en = false; ++ ++ if (l0s_en) ++ SET_HW_FLAG(L0S_EN); ++ else ++ CLI_HW_FLAG(L0S_EN); ++ ++ ++ if (!CHK_HW_FLAG(L1_CAP)) ++ l1_en = false; ++ ++ if (l1_en) ++ SET_HW_FLAG(L1_EN); ++ else ++ CLI_HW_FLAG(L1_EN); ++ ++ if (l1f_reset_pcie(hw, l0s_en, l1_en)) { ++ alx_hw_err(hw, "error when reset pcie\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++static int alf_config_aspm(struct alx_hw *hw, bool l0s_en, bool l1_en) ++{ ++ int retval = 0; ++ ++ if (!CHK_HW_FLAG(L0S_CAP)) ++ l0s_en = false; ++ ++ if (l0s_en) ++ SET_HW_FLAG(L0S_EN); ++ else ++ CLI_HW_FLAG(L0S_EN); ++ ++ if (!CHK_HW_FLAG(L1_CAP)) ++ l1_en = false; ++ ++ if (l1_en) ++ SET_HW_FLAG(L1_EN); ++ else ++ CLI_HW_FLAG(L1_EN); ++ ++ if (l1f_enable_aspm(hw, l0s_en, l1_en, 0)) { ++ alx_hw_err(hw, "error when enable aspm\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++static int alf_config_wol(struct alx_hw *hw, u32 wufc) ++{ ++ u32 wol; ++ int retval = 0; ++ ++ wol = 0; ++ /* turn on magic packet event */ ++ if (wufc & ALX_WOL_MAGIC) { ++ wol |= L1F_WOL0_MAGIC_EN | L1F_WOL0_PME_MAGIC_EN; ++ /* magic packet maybe Broadcast&multicast&Unicast frame */ ++ /* mac |= MAC_CTRL_BC_EN; */ ++ } ++ ++ /* turn on link up event */ ++ if (wufc & ALX_WOL_PHY) { ++ wol |= L1F_WOL0_LINK_EN | L1F_WOL0_PME_LINK; ++ /* only link up can wake up */ ++ retval = alf_write_phy_reg(hw, L1F_MII_IER, L1F_IER_LINK_UP); ++ } ++ alx_mem_w32(hw, L1F_WOL0, wol); ++ return retval; ++} ++ ++ ++static int alf_config_mac_ctrl(struct alx_hw *hw) ++{ ++ u32 mac; ++ ++ alx_mem_r32(hw, L1F_MAC_CTRL, &mac); ++ ++ /* enable/disable VLAN tag insert,strip */ ++ if (CHK_HW_FLAG(VLANSTRIP_EN)) ++ mac |= L1F_MAC_CTRL_VLANSTRIP; ++ else ++ mac &= ~L1F_MAC_CTRL_VLANSTRIP; ++ ++ if (CHK_HW_FLAG(PROMISC_EN)) ++ mac |= L1F_MAC_CTRL_PROMISC_EN; ++ else ++ mac &= ~L1F_MAC_CTRL_PROMISC_EN; ++ ++ if (CHK_HW_FLAG(MULTIALL_EN)) ++ mac |= L1F_MAC_CTRL_MULTIALL_EN; ++ else ++ mac &= ~L1F_MAC_CTRL_MULTIALL_EN; ++ ++ if (CHK_HW_FLAG(LOOPBACK_EN)) ++ mac |= L1F_MAC_CTRL_LPBACK_EN; ++ else ++ mac &= ~L1F_MAC_CTRL_LPBACK_EN; ++ ++ alx_mem_w32(hw, L1F_MAC_CTRL, mac); ++ return 0; ++} ++ ++ ++static int alf_config_pow_save(struct alx_hw *hw, u32 speed, bool wol_en, ++ bool tx_en, bool rx_en, bool pws_en) ++{ ++ u8 wire_spd = LX_LC_10H; ++ int retval = 0; ++ ++ switch (speed) { ++ case ALX_LINK_SPEED_UNKNOWN: ++ case ALX_LINK_SPEED_10_HALF: ++ wire_spd = LX_LC_10H; ++ break; ++ case ALX_LINK_SPEED_10_FULL: ++ wire_spd = LX_LC_10F; ++ break; ++ case ALX_LINK_SPEED_100_HALF: ++ wire_spd = LX_LC_100H; ++ break; ++ case ALX_LINK_SPEED_100_FULL: ++ wire_spd = LX_LC_100F; ++ break; ++ case ALX_LINK_SPEED_1GB_FULL: ++ wire_spd = LX_LC_1000F; ++ break; ++ } ++ ++ if (l1f_powersaving(hw, wire_spd, wol_en, tx_en, rx_en, pws_en)) { ++ alx_hw_err(hw, "error when set power saving\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++/* RAR, Multicast, VLAN */ ++static int alf_set_mac_addr(struct alx_hw *hw, u8 *addr) ++{ ++ u32 sta; ++ ++ /* ++ * for example: 00-0B-6A-F6-00-DC ++ * 0<-->6AF600DC, 1<-->000B. ++ */ ++ ++ /* low dword */ ++ sta = (((u32)addr[2]) << 24) | (((u32)addr[3]) << 16) | ++ (((u32)addr[4]) << 8) | (((u32)addr[5])) ; ++ alx_mem_w32(hw, L1F_STAD0, sta); ++ ++ /* hight dword */ ++ sta = (((u32)addr[0]) << 8) | (((u32)addr[1])) ; ++ alx_mem_w32(hw, L1F_STAD1, sta); ++ return 0; ++} ++ ++ ++static int alf_set_mc_addr(struct alx_hw *hw, u8 *addr) ++{ ++ u32 crc32, bit, reg, mta; ++ ++ /* ++ * set hash value for a multicast address hash calcu processing. ++ * 1. calcu 32bit CRC for multicast address ++ * 2. reverse crc with MSB to LSB ++ */ ++ crc32 = ALX_ETH_CRC(addr, ALX_ETH_LENGTH_OF_ADDRESS); ++ ++ /* ++ * The HASH Table is a register array of 2 32-bit registers. ++ * It is treated like an array of 64 bits. We want to set ++ * bit BitArray[hash_value]. So we figure out what register ++ * the bit is in, read it, OR in the new bit, then write ++ * back the new value. The register is determined by the ++ * upper 7 bits of the hash value and the bit within that ++ * register are determined by the lower 5 bits of the value. ++ */ ++ reg = (crc32 >> 31) & 0x1; ++ bit = (crc32 >> 26) & 0x1F; ++ ++ alx_mem_r32(hw, L1F_HASH_TBL0 + (reg<<2), &mta); ++ mta |= (0x1 << bit); ++ alx_mem_w32(hw, L1F_HASH_TBL0 + (reg<<2), mta); ++ return 0; ++} ++ ++ ++static int alf_clear_mc_addr(struct alx_hw *hw) ++{ ++ alx_mem_w32(hw, L1F_HASH_TBL0, 0); ++ alx_mem_w32(hw, L1F_HASH_TBL1, 0); ++ return 0; ++} ++ ++ ++/* RTX, IRQ */ ++static int alf_config_tx(struct alx_hw *hw) ++{ ++ u32 wrr; ++ ++ alx_mem_r32(hw, L1F_WRR, &wrr); ++ switch (hw->wrr_mode) { ++ case alx_wrr_mode_none: ++ FIELD_SETL(wrr, L1F_WRR_PRI, L1F_WRR_PRI_RESTRICT_NONE); ++ break; ++ case alx_wrr_mode_high: ++ FIELD_SETL(wrr, L1F_WRR_PRI, L1F_WRR_PRI_RESTRICT_HI); ++ break; ++ case alx_wrr_mode_high2: ++ FIELD_SETL(wrr, L1F_WRR_PRI, L1F_WRR_PRI_RESTRICT_HI2); ++ break; ++ case alx_wrr_mode_all: ++ FIELD_SETL(wrr, L1F_WRR_PRI, L1F_WRR_PRI_RESTRICT_ALL); ++ break; ++ } ++ FIELD_SETL(wrr, L1F_WRR_PRI0, hw->wrr_prio0); ++ FIELD_SETL(wrr, L1F_WRR_PRI1, hw->wrr_prio1); ++ FIELD_SETL(wrr, L1F_WRR_PRI2, hw->wrr_prio2); ++ FIELD_SETL(wrr, L1F_WRR_PRI3, hw->wrr_prio3); ++ alx_mem_w32(hw, L1F_WRR, wrr); ++ return 0; ++} ++ ++ ++static int alf_config_msix(struct alx_hw *hw, u16 num_intrs, ++ bool msix_en, bool msi_en) ++{ ++ u32 map[2]; ++ u32 type; ++ int msix_idx; ++ ++ if (!msix_en) ++ goto configure_legacy; ++ ++ memset(map, 0, sizeof(map)); ++ for (msix_idx = 0; msix_idx < num_intrs; msix_idx++) { ++ switch (msix_idx) { ++ case ALF_MSIX_INDEX_RXQ0: ++ FIELD_SETL(map[0], L1F_MSI_MAP_TBL1_RXQ0, ++ ALF_MSIX_INDEX_RXQ0); ++ break; ++ case ALF_MSIX_INDEX_RXQ1: ++ FIELD_SETL(map[0], L1F_MSI_MAP_TBL1_RXQ1, ++ ALF_MSIX_INDEX_RXQ1); ++ break; ++ case ALF_MSIX_INDEX_RXQ2: ++ FIELD_SETL(map[0], L1F_MSI_MAP_TBL1_RXQ2, ++ ALF_MSIX_INDEX_RXQ2); ++ break; ++ case ALF_MSIX_INDEX_RXQ3: ++ FIELD_SETL(map[0], L1F_MSI_MAP_TBL1_RXQ3, ++ ALF_MSIX_INDEX_RXQ3); ++ break; ++ case ALF_MSIX_INDEX_RXQ4: ++ FIELD_SETL(map[1], L1F_MSI_MAP_TBL2_RXQ4, ++ ALF_MSIX_INDEX_RXQ4); ++ break; ++ case ALF_MSIX_INDEX_RXQ5: ++ FIELD_SETL(map[1], L1F_MSI_MAP_TBL2_RXQ5, ++ ALF_MSIX_INDEX_RXQ5); ++ break; ++ case ALF_MSIX_INDEX_RXQ6: ++ FIELD_SETL(map[1], L1F_MSI_MAP_TBL2_RXQ6, ++ ALF_MSIX_INDEX_RXQ6); ++ break; ++ case ALF_MSIX_INDEX_RXQ7: ++ FIELD_SETL(map[1], L1F_MSI_MAP_TBL2_RXQ7, ++ ALF_MSIX_INDEX_RXQ7); ++ break; ++ case ALF_MSIX_INDEX_TXQ0: ++ FIELD_SETL(map[0], L1F_MSI_MAP_TBL1_TXQ0, ++ ALF_MSIX_INDEX_TXQ0); ++ break; ++ case ALF_MSIX_INDEX_TXQ1: ++ FIELD_SETL(map[0], L1F_MSI_MAP_TBL1_TXQ1, ++ ALF_MSIX_INDEX_TXQ1); ++ break; ++ case ALF_MSIX_INDEX_TXQ2: ++ FIELD_SETL(map[1], L1F_MSI_MAP_TBL2_TXQ2, ++ ALF_MSIX_INDEX_TXQ2); ++ break; ++ case ALF_MSIX_INDEX_TXQ3: ++ FIELD_SETL(map[1], L1F_MSI_MAP_TBL2_TXQ3, ++ ALF_MSIX_INDEX_TXQ3); ++ break; ++ case ALF_MSIX_INDEX_TIMER: ++ FIELD_SETL(map[0], L1F_MSI_MAP_TBL1_TIMER, ++ ALF_MSIX_INDEX_TIMER); ++ break; ++ case ALF_MSIX_INDEX_ALERT: ++ FIELD_SETL(map[0], L1F_MSI_MAP_TBL1_ALERT, ++ ALF_MSIX_INDEX_ALERT); ++ break; ++ case ALF_MSIX_INDEX_SMB: ++ FIELD_SETL(map[1], L1F_MSI_MAP_TBL2_SMB, ++ ALF_MSIX_INDEX_SMB); ++ break; ++ case ALF_MSIX_INDEX_PHY: ++ FIELD_SETL(map[1], L1F_MSI_MAP_TBL2_PHY, ++ ALF_MSIX_INDEX_PHY); ++ break; ++ default: ++ break; ++ ++ } ++ ++ } ++ ++ alx_mem_w32(hw, L1F_MSI_MAP_TBL1, map[0]); ++ alx_mem_w32(hw, L1F_MSI_MAP_TBL2, map[1]); ++ ++ /* 0 to alert, 1 to timer */ ++ type = (L1F_MSI_ID_MAP_DMAW | ++ L1F_MSI_ID_MAP_DMAR | ++ L1F_MSI_ID_MAP_PCIELNKDW | ++ L1F_MSI_ID_MAP_PCIECERR | ++ L1F_MSI_ID_MAP_PCIENFERR | ++ L1F_MSI_ID_MAP_PCIEFERR | ++ L1F_MSI_ID_MAP_PCIEUR); ++ ++ alx_mem_w32(hw, L1F_MSI_ID_MAP, type); ++ return 0; ++ ++configure_legacy: ++ alx_mem_w32(hw, L1F_MSI_MAP_TBL1, 0x0); ++ alx_mem_w32(hw, L1F_MSI_MAP_TBL2, 0x0); ++ alx_mem_w32(hw, L1F_MSI_ID_MAP, 0x0); ++ if (msi_en) { ++ u32 msi; ++ alx_mem_r32(hw, 0x1920, &msi); ++ msi |= 0x10000; ++ alx_mem_w32(hw, 0x1920, msi); ++ } ++ return 0; ++} ++ ++ ++/* ++ * Interrupt ++ */ ++static int alf_ack_phy_intr(struct alx_hw *hw) ++{ ++ u16 isr; ++ return alf_read_phy_reg(hw, L1F_MII_ISR, &isr); ++} ++ ++ ++static int alf_enable_legacy_intr(struct alx_hw *hw) ++{ ++ u16 cmd; ++ ++ alx_cfg_r16(hw, PCI_COMMAND, &cmd); ++ cmd &= ~PCI_COMMAND_INTX_DISABLE; ++ alx_cfg_w16(hw, PCI_COMMAND, cmd); ++ ++ alx_mem_w32(hw, L1F_ISR, ~((u32) L1F_ISR_DIS)); ++ alx_mem_w32(hw, L1F_IMR, hw->intr_mask); ++ return 0; ++} ++ ++ ++static int alf_disable_legacy_intr(struct alx_hw *hw) ++{ ++ alx_mem_w32(hw, L1F_ISR, L1F_ISR_DIS); ++ alx_mem_w32(hw, L1F_IMR, 0); ++ alx_mem_flush(hw); ++ return 0; ++} ++ ++ ++static int alf_enable_msix_intr(struct alx_hw *hw, u8 entry_idx) ++{ ++ u32 ctrl_reg; ++ ++ ctrl_reg = ALF_MSIX_ENTRY_BASE + (entry_idx * ALF_MSIX_ENTRY_SIZE) + ++ ALF_MSIX_MSG_CTRL_OFF; ++ ++ alx_mem_w32(hw, ctrl_reg, 0x0); ++ alx_mem_flush(hw); ++ return 0; ++} ++ ++ ++static int alf_disable_msix_intr(struct alx_hw *hw, u8 entry_idx) ++{ ++ u32 ctrl_reg; ++ ++ ctrl_reg = ALF_MSIX_ENTRY_BASE + (entry_idx * ALF_MSIX_ENTRY_SIZE) + ++ ALF_MSIX_MSG_CTRL_OFF; ++ ++ alx_mem_w32(hw, ctrl_reg, 0x1); ++ alx_mem_flush(hw); ++ return 0; ++} ++ ++ ++/* RSS */ ++static int alf_config_rss(struct alx_hw *hw, bool rss_en) ++{ ++ int key_len_by_u8 = sizeof(hw->rss_key); ++ int idt_len_by_u32 = sizeof(hw->rss_idt) / sizeof(u32); ++ u32 rxq0; ++ int i; ++ ++ /* Fill out hash function keys */ ++ for (i = 0; i < key_len_by_u8; i++) { ++ alx_mem_w8(hw, ALF_RSS_KEY(i, u8), ++ hw->rss_key[key_len_by_u8 - i - 1]); ++ } ++ ++ /* Fill out redirection table */ ++ for (i = 0; i < idt_len_by_u32; i++) ++ alx_mem_w32(hw, ALF_RSS_TBL(i, u32), hw->rss_idt[i]); ++ ++ alx_mem_w32(hw, L1F_RSS_BASE_CPU_NUM, hw->rss_base_cpu); ++ ++ alx_mem_r32(hw, L1F_RXQ0, &rxq0); ++ if (hw->rss_hstype & ALX_RSS_HSTYP_IPV4_EN) ++ rxq0 |= L1F_RXQ0_RSS_HSTYP_IPV4_EN; ++ else ++ rxq0 &= ~L1F_RXQ0_RSS_HSTYP_IPV4_EN; ++ ++ if (hw->rss_hstype & ALX_RSS_HSTYP_TCP4_EN) ++ rxq0 |= L1F_RXQ0_RSS_HSTYP_IPV4_TCP_EN; ++ else ++ rxq0 &= ~L1F_RXQ0_RSS_HSTYP_IPV4_TCP_EN; ++ ++ if (hw->rss_hstype & ALX_RSS_HSTYP_IPV6_EN) ++ rxq0 |= L1F_RXQ0_RSS_HSTYP_IPV6_EN; ++ else ++ rxq0 &= ~L1F_RXQ0_RSS_HSTYP_IPV6_EN; ++ ++ if (hw->rss_hstype & ALX_RSS_HSTYP_TCP6_EN) ++ rxq0 |= L1F_RXQ0_RSS_HSTYP_IPV6_TCP_EN; ++ else ++ rxq0 &= ~L1F_RXQ0_RSS_HSTYP_IPV6_TCP_EN; ++ ++ FIELD_SETL(rxq0, L1F_RXQ0_RSS_MODE, hw->rss_mode); ++ FIELD_SETL(rxq0, L1F_RXQ0_IDT_TBL_SIZE, hw->rss_idt_size); ++ ++ if (rss_en) ++ rxq0 |= L1F_RXQ0_RSS_HASH_EN; ++ else ++ rxq0 &= ~L1F_RXQ0_RSS_HASH_EN; ++ ++ alx_mem_w32(hw, L1F_RXQ0, rxq0); ++ return 0; ++} ++ ++ ++/* fc */ ++static int alf_get_fc_mode(struct alx_hw *hw, enum alx_fc_mode *mode) ++{ ++ u16 bmsr, giga; ++ int i; ++ int retval = 0; ++ ++ for (i = 0; i < ALX_MAX_SETUP_LNK_CYCLE; i++) { ++ alf_read_phy_reg(hw, MII_BMSR, &bmsr); ++ alf_read_phy_reg(hw, MII_BMSR, &bmsr); ++ if (bmsr & BMSR_LSTATUS) { ++ /* Read phy Specific Status Register (17) */ ++ retval = alf_read_phy_reg(hw, L1F_MII_GIGA_PSSR, &giga); ++ if (retval) ++ return retval; ++ ++ if (!(giga & L1F_GIGA_PSSR_SPD_DPLX_RESOLVED)) { ++ alx_hw_err(hw, ++ "error for speed duplex resolved\n"); ++ return -EINVAL; ++ } ++ ++ if ((giga & L1F_GIGA_PSSR_FC_TXEN) && ++ (giga & L1F_GIGA_PSSR_FC_RXEN)) { ++ *mode = alx_fc_full; ++ } else if (giga & L1F_GIGA_PSSR_FC_TXEN) { ++ *mode = alx_fc_tx_pause; ++ } else if (giga & L1F_GIGA_PSSR_FC_RXEN) { ++ *mode = alx_fc_rx_pause; ++ } else { ++ *mode = alx_fc_none; ++ } ++ break; ++ } ++ mdelay(100); ++ } ++ ++ if (i == ALX_MAX_SETUP_LNK_CYCLE) { ++ alx_hw_err(hw, "error when get flow control mode\n"); ++ retval = -EINVAL; ++ } ++ return retval; ++} ++ ++ ++static int alf_config_fc(struct alx_hw *hw) ++{ ++ u32 mac; ++ int retval = 0; ++ ++ if (hw->disable_fc_autoneg) { ++ hw->fc_was_autonegged = false; ++ hw->cur_fc_mode = hw->req_fc_mode; ++ } else { ++ hw->fc_was_autonegged = true; ++ retval = alf_get_fc_mode(hw, &hw->cur_fc_mode); ++ if (retval) ++ return retval; ++ } ++ ++ alx_mem_r32(hw, L1F_MAC_CTRL, &mac); ++ ++ switch (hw->cur_fc_mode) { ++ case alx_fc_none: /* 0 */ ++ mac &= ~(L1F_MAC_CTRL_RXFC_EN | L1F_MAC_CTRL_TXFC_EN); ++ break; ++ case alx_fc_rx_pause: /* 1 */ ++ mac &= ~L1F_MAC_CTRL_TXFC_EN; ++ mac |= L1F_MAC_CTRL_RXFC_EN; ++ break; ++ case alx_fc_tx_pause: /* 2 */ ++ mac |= L1F_MAC_CTRL_TXFC_EN; ++ mac &= ~L1F_MAC_CTRL_RXFC_EN; ++ break; ++ case alx_fc_full: /* 3 */ ++ case alx_fc_default: /* 4 */ ++ mac |= (L1F_MAC_CTRL_TXFC_EN | L1F_MAC_CTRL_RXFC_EN); ++ break; ++ default: ++ alx_hw_err(hw, "flow control param set incorrectly\n"); ++ return -EINVAL; ++ break; ++ } ++ ++ alx_mem_w32(hw, L1F_MAC_CTRL, mac); ++ ++ return retval; ++} ++ ++ ++/* ++ * NVRam ++ */ ++static int alf_check_nvram(struct alx_hw *hw, bool *exist) ++{ ++ *exist = false; ++ return 0; ++} ++ ++ ++/* ethtool */ ++static int alf_get_ethtool_regs(struct alx_hw *hw, void *buff) ++{ ++ int i; ++ u32 *val = buff; ++ static const u32 reg[] = { ++ /* 0 */ ++ L1F_DEV_CAP, L1F_DEV_CTRL, L1F_LNK_CAP, L1F_LNK_CTRL, ++ L1F_UE_SVRT, L1F_EFLD, L1F_SLD, L1F_PPHY_MISC1, ++ L1F_PPHY_MISC2, L1F_PDLL_TRNS1, ++ ++ /* 10 */ ++ L1F_TLEXTN_STATS, L1F_EFUSE_CTRL, L1F_EFUSE_DATA, L1F_SPI_OP1, ++ L1F_SPI_OP2, L1F_SPI_OP3, L1F_EF_CTRL, L1F_EF_ADDR, ++ L1F_EF_DATA, L1F_SPI_ID, ++ ++ /* 20 */ ++ L1F_SPI_CFG_START, L1F_PMCTRL, L1F_LTSSM_CTRL, L1F_MASTER, ++ L1F_MANU_TIMER, L1F_IRQ_MODU_TIMER, L1F_PHY_CTRL, L1F_MAC_STS, ++ L1F_MDIO, L1F_MDIO_EXTN, ++ ++ /* 30 */ ++ L1F_PHY_STS, L1F_BIST0, L1F_BIST1, L1F_SERDES, ++ L1F_LED_CTRL, L1F_LED_PATN, L1F_LED_PATN2, L1F_SYSALV, ++ L1F_PCIERR_INST, L1F_LPI_DECISN_TIMER, ++ ++ /* 40 */ ++ L1F_LPI_CTRL, L1F_LPI_WAIT, L1F_HRTBT_VLAN, L1F_HRTBT_CTRL, ++ L1F_RXPARSE, L1F_MAC_CTRL, L1F_GAP, L1F_STAD1, ++ L1F_LED_CTRL, L1F_HASH_TBL0, ++ ++ /* 50 */ ++ L1F_HASH_TBL1, L1F_HALFD, L1F_DMA, L1F_WOL0, ++ L1F_WOL1, L1F_WOL2, L1F_WRR, L1F_HQTPD, ++ L1F_CPUMAP1, L1F_CPUMAP2, ++ ++ /* 60 */ ++ L1F_MISC, L1F_RX_BASE_ADDR_HI, L1F_RFD_ADDR_LO, L1F_RFD_RING_SZ, ++ L1F_RFD_BUF_SZ, L1F_RRD_ADDR_LO, L1F_RRD_RING_SZ, ++ L1F_RFD_PIDX, L1F_RFD_CIDX, L1F_RXQ0, ++ ++ /* 70 */ ++ L1F_RXQ1, L1F_RXQ2, L1F_RXQ3, L1F_TX_BASE_ADDR_HI, ++ L1F_TPD_PRI0_ADDR_LO, L1F_TPD_PRI1_ADDR_LO, ++ L1F_TPD_PRI2_ADDR_LO, L1F_TPD_PRI3_ADDR_LO, ++ L1F_TPD_PRI0_PIDX, L1F_TPD_PRI1_PIDX, ++ ++ /* 80 */ ++ L1F_TPD_PRI2_PIDX, L1F_TPD_PRI3_PIDX, L1F_TPD_PRI0_CIDX, ++ L1F_TPD_PRI1_CIDX, L1F_TPD_PRI2_CIDX, L1F_TPD_PRI3_CIDX, ++ L1F_TPD_RING_SZ, L1F_TXQ0, L1F_TXQ1, L1F_TXQ2, ++ ++ /* 90 */ ++ L1F_MSI_MAP_TBL1, L1F_MSI_MAP_TBL2, L1F_MSI_ID_MAP, ++ L1F_MSIX_MASK, L1F_MSIX_PENDING, ++ }; ++ ++ for (i = 0; i < ARRAY_SIZE(reg); i++) ++ alx_mem_r32(hw, reg[i], &val[i]); ++ ++ /* SRAM */ ++ for (i = 0; i < 16; i++) ++ alx_mem_r32(hw, ALF_SRAM(i, u32), &val[100 + i]); ++ ++ /* RSS */ ++ for (i = 0; i < 10; i++) ++ alx_mem_r32(hw, ALF_RSS_KEY(i, u32), &val[120 + i]); ++ for (i = 0; i < 32; i++) ++ alx_mem_r32(hw, ALF_RSS_TBL(i, u32), &val[130 + i]); ++ alx_mem_r32(hw, L1F_RSS_HASH_VAL, &val[162]); ++ alx_mem_r32(hw, L1F_RSS_HASH_FLAG, &val[163]); ++ alx_mem_r32(hw, L1F_RSS_BASE_CPU_NUM, &val[164]); ++ ++ /* MIB */ ++ for (i = 0; i < 48; i++) ++ alx_mem_r32(hw, ALF_MIB(i, u32), &val[170 + i]); ++ return 0; ++} ++ ++ ++/******************************************************************************/ ++static int alf_set_hw_capabilities(struct alx_hw *hw) ++{ ++ SET_HW_FLAG(L0S_CAP); ++ SET_HW_FLAG(L1_CAP); ++ ++ if (hw->mac_type == alx_mac_l1f) ++ SET_HW_FLAG(GIGA_CAP); ++ ++ /* set flags of alx_phy_info */ ++ SET_HW_FLAG(PWSAVE_CAP); ++ return 0; ++} ++ ++ ++/* alc_set_hw_info */ ++static int alf_set_hw_infos(struct alx_hw *hw) ++{ ++ hw->rxstat_reg = L1F_MIB_RX_OK; ++ hw->rxstat_sz = 0x60; ++ hw->txstat_reg = L1F_MIB_TX_OK; ++ hw->txstat_sz = 0x68; ++ ++ hw->rx_prod_reg[0] = L1F_RFD_PIDX; ++ hw->rx_cons_reg[0] = L1F_RFD_CIDX; ++ ++ hw->tx_prod_reg[0] = L1F_TPD_PRI0_PIDX; ++ hw->tx_cons_reg[0] = L1F_TPD_PRI0_CIDX; ++ hw->tx_prod_reg[1] = L1F_TPD_PRI1_PIDX; ++ hw->tx_cons_reg[1] = L1F_TPD_PRI1_CIDX; ++ hw->tx_prod_reg[2] = L1F_TPD_PRI2_PIDX; ++ hw->tx_cons_reg[2] = L1F_TPD_PRI2_CIDX; ++ hw->tx_prod_reg[3] = L1F_TPD_PRI3_PIDX; ++ hw->tx_cons_reg[3] = L1F_TPD_PRI3_CIDX; ++ ++ hw->hwreg_sz = 0x200; ++ hw->eeprom_sz = 0; ++ ++ return 0; ++} ++ ++ ++/* ++ * alf_init_hw_callbacks ++ */ ++int alf_init_hw_callbacks(struct alx_hw *hw) ++{ ++ /* NIC */ ++ hw->cbs.identify_nic = &alf_identify_nic; ++ /* MAC */ ++ hw->cbs.reset_mac = &alf_reset_mac; ++ hw->cbs.start_mac = &alf_start_mac; ++ hw->cbs.stop_mac = &alf_stop_mac; ++ hw->cbs.config_mac = &alf_config_mac; ++ hw->cbs.get_mac_addr = &alf_get_mac_addr; ++ hw->cbs.set_mac_addr = &alf_set_mac_addr; ++ hw->cbs.set_mc_addr = &alf_set_mc_addr; ++ hw->cbs.clear_mc_addr = &alf_clear_mc_addr; ++ ++ /* PHY */ ++ hw->cbs.init_phy = &alf_init_phy; ++ hw->cbs.reset_phy = &alf_reset_phy; ++ hw->cbs.read_phy_reg = &alf_read_phy_reg; ++ hw->cbs.write_phy_reg = &alf_write_phy_reg; ++ hw->cbs.check_phy_link = &alf_check_phy_link; ++ hw->cbs.setup_phy_link = &alf_setup_phy_link; ++ hw->cbs.setup_phy_link_speed = &alf_setup_phy_link_speed; ++ ++ /* Interrupt */ ++ hw->cbs.ack_phy_intr = &alf_ack_phy_intr; ++ hw->cbs.enable_legacy_intr = &alf_enable_legacy_intr; ++ hw->cbs.disable_legacy_intr = &alf_disable_legacy_intr; ++ hw->cbs.enable_msix_intr = &alf_enable_msix_intr; ++ hw->cbs.disable_msix_intr = &alf_disable_msix_intr; ++ ++ /* Configure */ ++ hw->cbs.config_tx = &alf_config_tx; ++ hw->cbs.config_fc = &alf_config_fc; ++ hw->cbs.config_rss = &alf_config_rss; ++ hw->cbs.config_msix = &alf_config_msix; ++ hw->cbs.config_wol = &alf_config_wol; ++ hw->cbs.config_aspm = &alf_config_aspm; ++ hw->cbs.config_mac_ctrl = &alf_config_mac_ctrl; ++ hw->cbs.config_pow_save = &alf_config_pow_save; ++ hw->cbs.reset_pcie = &alf_reset_pcie; ++ ++ /* NVRam */ ++ hw->cbs.check_nvram = &alf_check_nvram; ++ ++ /* Others */ ++ hw->cbs.get_ethtool_regs = alf_get_ethtool_regs; ++ ++ alf_set_hw_capabilities(hw); ++ alf_set_hw_infos(hw); ++ ++ alx_hw_info(hw, "HW Flags = 0x%x\n", hw->flags); ++ return 0; ++} ++ +diff --git a/drivers/net/ethernet/atheros/alx/alf_hw.c b/drivers/net/ethernet/atheros/alx/alf_hw.c +new file mode 100644 +index 0000000..3301457 +--- /dev/null ++++ b/drivers/net/ethernet/atheros/alx/alf_hw.c +@@ -0,0 +1,918 @@ ++/* ++ * Copyright (c) 2012 Qualcomm Atheros, Inc. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "alf_hw.h" ++ ++ ++/* get permanent mac address from ++ * 0: success ++ * non-0:fail ++ */ ++u16 l1f_get_perm_macaddr(struct alx_hw *hw, u8 *addr) ++{ ++ u32 val, mac0, mac1; ++ u16 flag, i; ++ ++#define INTN_LOADED 0x1 ++#define EXTN_LOADED 0x2 ++ ++ flag = 0; ++ val = 0; ++ ++read_mcadr: ++ ++ /* get it from register first */ ++ alx_mem_r32(hw, L1F_STAD0, &mac0); ++ alx_mem_r32(hw, L1F_STAD1, &mac1); ++ ++ *(u32 *)(addr + 2) = LX_SWAP_DW(mac0); ++ *(u16 *)addr = (u16)LX_SWAP_W((u16)mac1); ++ ++ if (macaddr_valid(addr)) ++ return 0; ++ ++ if ((flag & INTN_LOADED) == 0) { ++ /* load from efuse ? */ ++ for (i = 0; i < L1F_SLD_MAX_TO; i++) { ++ alx_mem_r32(hw, L1F_SLD, &val); ++ if ((val & (L1F_SLD_STAT | L1F_SLD_START)) == 0) ++ break; ++ mdelay(1); ++ } ++ if (i == L1F_SLD_MAX_TO) ++ goto out; ++ alx_mem_w32(hw, L1F_SLD, val | L1F_SLD_START); ++ for (i = 0; i < L1F_SLD_MAX_TO; i++) { ++ mdelay(1); ++ alx_mem_r32(hw, L1F_SLD, &val); ++ if ((val & L1F_SLD_START) == 0) ++ break; ++ } ++ if (i == L1F_SLD_MAX_TO) ++ goto out; ++ flag |= INTN_LOADED; ++ goto read_mcadr; ++ } ++ ++ if ((flag & EXTN_LOADED) == 0) { ++ alx_mem_r32(hw, L1F_EFLD, &val); ++ if ((val & (L1F_EFLD_F_EXIST | L1F_EFLD_E_EXIST)) != 0) { ++ /* load from eeprom/flash ? */ ++ for (i = 0; i < L1F_SLD_MAX_TO; i++) { ++ alx_mem_r32(hw, L1F_EFLD, &val); ++ if ((val & (L1F_EFLD_STAT | ++ L1F_EFLD_START)) == 0) { ++ break; ++ } ++ mdelay(1); ++ } ++ if (i == L1F_SLD_MAX_TO) ++ goto out; ++ alx_mem_w32(hw, L1F_EFLD, val | L1F_EFLD_START); ++ for (i = 0; i < L1F_SLD_MAX_TO; i++) { ++ mdelay(1); ++ alx_mem_r32(hw, L1F_EFLD, &val); ++ if ((val & L1F_EFLD_START) == 0) ++ break; ++ } ++ if (i == L1F_SLD_MAX_TO) ++ goto out; ++ flag |= EXTN_LOADED; ++ goto read_mcadr; ++ } ++ } ++ ++out: ++ return LX_ERR_ALOAD; ++} ++ ++ ++/* reset mac & dma ++ * return ++ * 0: success ++ * non-0:fail ++ */ ++u16 l1f_reset_mac(struct alx_hw *hw) ++{ ++ u32 val, pmctrl = 0; ++ u16 ret; ++ u16 i; ++ u8 rev = (u8)(FIELD_GETX(hw->pci_revid, L1F_PCI_REVID)); ++ ++ /* disable all interrupts, RXQ/TXQ */ ++ alx_mem_w32(hw, L1F_MSIX_MASK, BIT_ALL); /* ???? msi-x */ ++ alx_mem_w32(hw, L1F_IMR, 0); ++ alx_mem_w32(hw, L1F_ISR, L1F_ISR_DIS); ++ ++ ret = l1f_enable_mac(hw, false, 0); ++ if (ret != 0) ++ return ret; ++ ++ /* mac reset workaroud */ ++ alx_mem_w32(hw, L1F_RFD_PIDX, 1); ++ ++ /* dis l0s/l1 before mac reset */ ++ if ((rev == L1F_REV_A0 || rev == L1F_REV_A1) && ++ (hw->pci_revid & L1F_PCI_REVID_WTH_CR) != 0) { ++ alx_mem_r32(hw, L1F_PMCTRL, &pmctrl); ++ if ((pmctrl & (L1F_PMCTRL_L1_EN | L1F_PMCTRL_L0S_EN)) != 0) { ++ alx_mem_w32(hw, L1F_PMCTRL, ++ pmctrl & ~(L1F_PMCTRL_L1_EN | ++ L1F_PMCTRL_L0S_EN)); ++ } ++ } ++ ++ /* reset whole mac safely */ ++ alx_mem_r32(hw, L1F_MASTER, &val); ++ alx_mem_w32(hw, L1F_MASTER, ++ val | L1F_MASTER_DMA_MAC_RST | L1F_MASTER_OOB_DIS); ++ ++ /* make sure it's real idle */ ++ udelay(10); ++ for (i = 0; i < L1F_DMA_MAC_RST_TO; i++) { ++ alx_mem_r32(hw, L1F_RFD_PIDX, &val); ++ if (val == 0) ++ break; ++ udelay(10); ++ } ++ for (; i < L1F_DMA_MAC_RST_TO; i++) { ++ alx_mem_r32(hw, L1F_MASTER, &val); ++ if ((val & L1F_MASTER_DMA_MAC_RST) == 0) ++ break; ++ udelay(10); ++ } ++ if (i == L1F_DMA_MAC_RST_TO) ++ return LX_ERR_RSTMAC; ++ udelay(10); ++ ++ if ((rev == L1F_REV_A0 || rev == L1F_REV_A1) && ++ (hw->pci_revid & L1F_PCI_REVID_WTH_CR) != 0) { ++ /* set L1F_MASTER_PCLKSEL_SRDS (affect by soft-rst, PERST) */ ++ alx_mem_w32(hw, L1F_MASTER, val | L1F_MASTER_PCLKSEL_SRDS); ++ /* resoter l0s / l1 */ ++ if ((pmctrl & (L1F_PMCTRL_L1_EN | L1F_PMCTRL_L0S_EN)) != 0) ++ alx_mem_w32(hw, L1F_PMCTRL, pmctrl); ++ } ++ ++ /* clear Internal OSC settings, switching OSC by hw itself, ++ * disable isoloate for A0 */ ++ alx_mem_r32(hw, L1F_MISC3, &val); ++ alx_mem_w32(hw, L1F_MISC3, ++ (val & ~L1F_MISC3_25M_BY_SW) | L1F_MISC3_25M_NOTO_INTNL); ++ alx_mem_r32(hw, L1F_MISC, &val); ++ val &= ~L1F_MISC_INTNLOSC_OPEN; ++ if (rev == L1F_REV_A0 || rev == L1F_REV_A1) ++ val &= ~L1F_MISC_ISO_EN; ++ alx_mem_w32(hw, L1F_MISC, val); ++ udelay(20); ++ ++ /* driver control speed/duplex, hash-alg */ ++ alx_mem_r32(hw, L1F_MAC_CTRL, &val); ++ alx_mem_w32(hw, L1F_MAC_CTRL, val | L1F_MAC_CTRL_WOLSPED_SWEN); ++ ++ /* clk sw */ ++ alx_mem_r32(hw, L1F_SERDES, &val); ++ alx_mem_w32(hw, L1F_SERDES, ++ val | L1F_SERDES_MACCLK_SLWDWN | L1F_SERDES_PHYCLK_SLWDWN); ++ ++ return 0; ++} ++ ++/* reset phy ++ * return ++ * 0: success ++ * non-0:fail ++ */ ++u16 l1f_reset_phy(struct alx_hw *hw, bool pws_en, bool az_en, bool ptp_en) ++{ ++ u32 val; ++ u16 i, phy_val; ++ ++ az_en = az_en; ++ ptp_en = ptp_en; ++ ++ /* reset PHY core */ ++ alx_mem_r32(hw, L1F_PHY_CTRL, &val); ++ val &= ~(L1F_PHY_CTRL_DSPRST_OUT | L1F_PHY_CTRL_IDDQ | ++ L1F_PHY_CTRL_GATE_25M | L1F_PHY_CTRL_POWER_DOWN | ++ L1F_PHY_CTRL_CLS); ++ val |= L1F_PHY_CTRL_RST_ANALOG; ++ ++ if (pws_en) ++ val |= (L1F_PHY_CTRL_HIB_PULSE | L1F_PHY_CTRL_HIB_EN); ++ else ++ val &= ~(L1F_PHY_CTRL_HIB_PULSE | L1F_PHY_CTRL_HIB_EN); ++ alx_mem_w32(hw, L1F_PHY_CTRL, val); ++ udelay(10); /* 5us is enough */ ++ alx_mem_w32(hw, L1F_PHY_CTRL, val | L1F_PHY_CTRL_DSPRST_OUT); ++ ++ for (i = 0; i < L1F_PHY_CTRL_DSPRST_TO; i++) { /* delay 800us */ ++ udelay(10); ++ } ++ ++ /* ???? phy power saving */ ++ ++ l1f_write_phydbg(hw, true, ++ L1F_MIIDBG_TST10BTCFG, L1F_TST10BTCFG_DEF); ++ l1f_write_phydbg(hw, true, L1F_MIIDBG_SRDSYSMOD, L1F_SRDSYSMOD_DEF); ++ l1f_write_phydbg(hw, true, ++ L1F_MIIDBG_TST100BTCFG, L1F_TST100BTCFG_DEF); ++ l1f_write_phydbg(hw, true, L1F_MIIDBG_ANACTRL, L1F_ANACTRL_DEF); ++ l1f_read_phydbg(hw, true, L1F_MIIDBG_GREENCFG2, &phy_val); ++ l1f_write_phydbg(hw, true, L1F_MIIDBG_GREENCFG2, ++ phy_val & ~L1F_GREENCFG2_GATE_DFSE_EN); ++ /* rtl8139c, 120m */ ++ l1f_write_phy(hw, true, L1F_MIIEXT_ANEG, true, ++ L1F_MIIEXT_NLP78, L1F_MIIEXT_NLP78_120M_DEF); ++ ++ /* set phy interrupt mask */ ++ l1f_write_phy(hw, false, 0, true, ++ L1F_MII_IER, L1F_IER_LINK_UP | L1F_IER_LINK_DOWN); ++ ++ ++ /* TODO *****???? */ ++ return 0; ++} ++ ++ ++/* reset pcie ++ * just reset pcie relative registers (pci command, clk, aspm...) ++ * return ++ * 0:success ++ * non-0:fail ++ */ ++u16 l1f_reset_pcie(struct alx_hw *hw, bool l0s_en, bool l1_en) ++{ ++ u32 val; ++ u16 val16; ++ u16 ret; ++ u8 rev = (u8)(FIELD_GETX(hw->pci_revid, L1F_PCI_REVID)); ++ ++ /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */ ++ alx_cfg_r16(hw, PCI_COMMAND, &val16); ++ if ((val16 & (PCI_COMMAND_IO | ++ PCI_COMMAND_MEMORY | ++ PCI_COMMAND_MASTER)) == 0 || ++ (val16 & PCI_COMMAND_INTX_DISABLE) != 0) { ++ val16 = (u16)((val16 | (PCI_COMMAND_IO | ++ PCI_COMMAND_MEMORY | ++ PCI_COMMAND_MASTER)) ++ & ~PCI_COMMAND_INTX_DISABLE); ++ alx_cfg_w16(hw, PCI_COMMAND, val16); ++ } ++ ++ /* Clear any PowerSaving Settings */ ++ alx_cfg_w16(hw, L1F_PM_CSR, 0); ++ ++ /* deflt val of PDLL D3PLLOFF */ ++ alx_mem_r32(hw, L1F_PDLL_TRNS1, &val); ++ alx_mem_w32(hw, L1F_PDLL_TRNS1, val & ~L1F_PDLL_TRNS1_D3PLLOFF_EN); ++ ++ /* mask some pcie error bits */ ++ alx_mem_r32(hw, L1F_UE_SVRT, &val); ++ val &= ~(L1F_UE_SVRT_DLPROTERR | L1F_UE_SVRT_FCPROTERR); ++ alx_mem_w32(hw, L1F_UE_SVRT, val); ++ ++ /* wol 25M & pclk */ ++ alx_mem_r32(hw, L1F_MASTER, &val); ++ if ((rev == L1F_REV_A0 || rev == L1F_REV_A1) && ++ (hw->pci_revid & L1F_PCI_REVID_WTH_CR) != 0) { ++ if ((val & L1F_MASTER_WAKEN_25M) == 0 || ++ (val & L1F_MASTER_PCLKSEL_SRDS) == 0) { ++ alx_mem_w32(hw, L1F_MASTER, ++ val | L1F_MASTER_PCLKSEL_SRDS | ++ L1F_MASTER_WAKEN_25M); ++ } ++ } else { ++ if ((val & L1F_MASTER_WAKEN_25M) == 0 || ++ (val & L1F_MASTER_PCLKSEL_SRDS) != 0) { ++ alx_mem_w32(hw, L1F_MASTER, ++ (val & ~L1F_MASTER_PCLKSEL_SRDS) | ++ L1F_MASTER_WAKEN_25M); ++ } ++ } ++ ++ /* l0s, l1 setting */ ++ ret = l1f_enable_aspm(hw, l0s_en, l1_en, 0); ++ ++ udelay(10); ++ ++ return ret; ++} ++ ++ ++/* disable/enable MAC/RXQ/TXQ ++ * en ++ * true:enable ++ * false:disable ++ * return ++ * 0:success ++ * non-0-fail ++ */ ++u16 l1f_enable_mac(struct alx_hw *hw, bool en, u16 en_ctrl) ++{ ++ u32 rxq, txq, mac, val; ++ u16 i; ++ ++ alx_mem_r32(hw, L1F_RXQ0, &rxq); ++ alx_mem_r32(hw, L1F_TXQ0, &txq); ++ alx_mem_r32(hw, L1F_MAC_CTRL, &mac); ++ ++ if (en) { /* enable */ ++ alx_mem_w32(hw, L1F_RXQ0, rxq | L1F_RXQ0_EN); ++ alx_mem_w32(hw, L1F_TXQ0, txq | L1F_TXQ0_EN); ++ if ((en_ctrl & LX_MACSPEED_1000) != 0) { ++ FIELD_SETL(mac, L1F_MAC_CTRL_SPEED, ++ L1F_MAC_CTRL_SPEED_1000); ++ } else { ++ FIELD_SETL(mac, L1F_MAC_CTRL_SPEED, ++ L1F_MAC_CTRL_SPEED_10_100); ++ } ++ ++ test_set_or_clear(mac, en_ctrl, LX_MACDUPLEX_FULL, ++ L1F_MAC_CTRL_FULLD); ++ /* rx filter */ ++ test_set_or_clear(mac, en_ctrl, LX_FLT_PROMISC, ++ L1F_MAC_CTRL_PROMISC_EN); ++ test_set_or_clear(mac, en_ctrl, LX_FLT_MULTI_ALL, ++ L1F_MAC_CTRL_MULTIALL_EN); ++ test_set_or_clear(mac, en_ctrl, LX_FLT_BROADCAST, ++ L1F_MAC_CTRL_BRD_EN); ++ test_set_or_clear(mac, en_ctrl, LX_FLT_DIRECT, ++ L1F_MAC_CTRL_RX_EN); ++ test_set_or_clear(mac, en_ctrl, LX_FC_TXEN, ++ L1F_MAC_CTRL_TXFC_EN); ++ test_set_or_clear(mac, en_ctrl, LX_FC_RXEN, ++ L1F_MAC_CTRL_RXFC_EN); ++ test_set_or_clear(mac, en_ctrl, LX_VLAN_STRIP, ++ L1F_MAC_CTRL_VLANSTRIP); ++ test_set_or_clear(mac, en_ctrl, LX_LOOPBACK, ++ L1F_MAC_CTRL_LPBACK_EN); ++ test_set_or_clear(mac, en_ctrl, LX_SINGLE_PAUSE, ++ L1F_MAC_CTRL_SPAUSE_EN); ++ test_set_or_clear(mac, en_ctrl, LX_ADD_FCS, ++ (L1F_MAC_CTRL_PCRCE | L1F_MAC_CTRL_CRCE)); ++ ++ alx_mem_w32(hw, L1F_MAC_CTRL, mac | L1F_MAC_CTRL_TX_EN); ++ } else { /* disable mac */ ++ alx_mem_w32(hw, L1F_RXQ0, rxq & ~L1F_RXQ0_EN); ++ alx_mem_w32(hw, L1F_TXQ0, txq & ~L1F_TXQ0_EN); ++ ++ /* waiting for rxq/txq be idle */ ++ udelay(40); ++ ++ /* stop mac tx/rx */ ++ alx_mem_w32(hw, L1F_MAC_CTRL, ++ mac & ~(L1F_MAC_CTRL_RX_EN | L1F_MAC_CTRL_TX_EN)); ++ ++ for (i = 0; i < L1F_DMA_MAC_RST_TO; i++) { ++ alx_mem_r32(hw, L1F_MAC_STS, &val); ++ if ((val & L1F_MAC_STS_IDLE) == 0) ++ break; ++ udelay(10); ++ } ++ if (L1F_DMA_MAC_RST_TO == i) ++ return LX_ERR_RSTMAC; ++ } ++ ++ return 0; ++} ++ ++/* enable/disable aspm support ++ * that will change settings for phy/mac/pcie ++ */ ++u16 l1f_enable_aspm(struct alx_hw *hw, bool l0s_en, bool l1_en, u8 lnk_stat) ++{ ++ u32 pmctrl; ++ u8 rev = (u8)(FIELD_GETX(hw->pci_revid, L1F_PCI_REVID)); ++ ++ lnk_stat = lnk_stat; ++ ++ ++ alx_mem_r32(hw, L1F_PMCTRL, &pmctrl); ++ ++ /* ????default */ ++ FIELD_SETL(pmctrl, L1F_PMCTRL_LCKDET_TIMER, ++ L1F_PMCTRL_LCKDET_TIMER_DEF); ++ pmctrl |= L1F_PMCTRL_RCVR_WT_1US | /* wait 1us */ ++ L1F_PMCTRL_L1_CLKSW_EN | /* pcie clk sw */ ++ L1F_PMCTRL_L1_SRDSRX_PWD ; /* pwd serdes ????default */ ++ /* ????default */ ++ FIELD_SETL(pmctrl, L1F_PMCTRL_L1REQ_TO, L1F_PMCTRL_L1REG_TO_DEF); ++ FIELD_SETL(pmctrl, L1F_PMCTRL_L1_TIMER, L1F_PMCTRL_L1_TIMER_16US); ++ pmctrl &= ~(L1F_PMCTRL_L1_SRDS_EN | ++ L1F_PMCTRL_L1_SRDSPLL_EN | ++ L1F_PMCTRL_L1_BUFSRX_EN | ++ L1F_PMCTRL_SADLY_EN | /* ???default */ ++ L1F_PMCTRL_HOTRST_WTEN| ++ L1F_PMCTRL_L0S_EN | ++ L1F_PMCTRL_L1_EN | ++ L1F_PMCTRL_ASPM_FCEN | ++ L1F_PMCTRL_TXL1_AFTER_L0S | ++ L1F_PMCTRL_RXL1_AFTER_L0S ++ ); ++ if ((rev == L1F_REV_A0 || rev == L1F_REV_A1) && ++ (hw->pci_revid & L1F_PCI_REVID_WTH_CR) != 0) { ++ pmctrl |= L1F_PMCTRL_L1_SRDS_EN | L1F_PMCTRL_L1_SRDSPLL_EN; ++ } ++ ++ /* on/off l0s only if bios/system enable l0s */ ++ if (/* sysl0s_en && */ l0s_en) ++ pmctrl |= (L1F_PMCTRL_L0S_EN | L1F_PMCTRL_ASPM_FCEN); ++ /* on/off l1 only if bios/system enable l1 */ ++ if (/* sysl1_en && */ l1_en) ++ pmctrl |= (L1F_PMCTRL_L1_EN | L1F_PMCTRL_ASPM_FCEN); ++ ++ alx_mem_w32(hw, L1F_PMCTRL, pmctrl); ++ ++ return 0; ++} ++ ++ ++/* initialize phy for speed / flow control ++ * lnk_cap ++ * if autoNeg, is link capability to tell the peer ++ * if force mode, is forced speed/duplex ++ */ ++u16 l1f_init_phy_spdfc(struct alx_hw *hw, bool auto_neg, ++ u8 lnk_cap, bool fc_en) ++{ ++ u16 adv, giga, cr; ++ u32 val; ++ u16 ret; ++ ++ /* clear flag */ ++ l1f_write_phy(hw, false, 0, false, L1F_MII_DBG_ADDR, 0); ++ alx_mem_r32(hw, L1F_DRV, &val); ++ FIELD_SETL(val, LX_DRV_PHY, 0); ++ ++ if (auto_neg) { ++ adv = L1F_ADVERTISE_DEFAULT_CAP & ~L1F_ADVERTISE_SPEED_MASK; ++ giga = L1F_GIGA_CR_1000T_DEFAULT_CAP & ++ ~L1F_GIGA_CR_1000T_SPEED_MASK; ++ val |= LX_DRV_PHY_AUTO; ++ if (!fc_en) ++ adv &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); ++ else ++ val |= LX_DRV_PHY_FC; ++ if ((LX_LC_10H & lnk_cap) != 0) { ++ adv |= ADVERTISE_10HALF; ++ val |= LX_DRV_PHY_10; ++ } ++ if ((LX_LC_10F & lnk_cap) != 0) { ++ adv |= ADVERTISE_10HALF | ++ ADVERTISE_10FULL; ++ val |= LX_DRV_PHY_10 | LX_DRV_PHY_DUPLEX; ++ } ++ if ((LX_LC_100H & lnk_cap) != 0) { ++ adv |= ADVERTISE_100HALF; ++ val |= LX_DRV_PHY_100; ++ } ++ if ((LX_LC_100F & lnk_cap) != 0) { ++ adv |= ADVERTISE_100HALF | ++ ADVERTISE_100FULL; ++ val |= LX_DRV_PHY_100 | LX_DRV_PHY_DUPLEX; ++ } ++ if ((LX_LC_1000F & lnk_cap) != 0) { ++ giga |= L1F_GIGA_CR_1000T_FD_CAPS; ++ val |= LX_DRV_PHY_1000 | LX_DRV_PHY_DUPLEX; ++ } ++ ++ ret = l1f_write_phy(hw, false, 0, false, MII_ADVERTISE, adv); ++ ret = l1f_write_phy(hw, false, 0, false, MII_CTRL1000, giga); ++ ++ cr = BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART; ++ ret = l1f_write_phy(hw, false, 0, false, MII_BMCR, cr); ++ } else { /* force mode */ ++ cr = BMCR_RESET; ++ switch (lnk_cap) { ++ case LX_LC_10H: ++ val |= LX_DRV_PHY_10; ++ break; ++ case LX_LC_10F: ++ cr |= BMCR_FULLDPLX; ++ val |= LX_DRV_PHY_10 | LX_DRV_PHY_DUPLEX; ++ break; ++ case LX_LC_100H: ++ cr |= BMCR_SPEED100; ++ val |= LX_DRV_PHY_100; ++ break; ++ case LX_LC_100F: ++ cr |= BMCR_SPEED100 | BMCR_FULLDPLX; ++ val |= LX_DRV_PHY_100 | LX_DRV_PHY_DUPLEX; ++ break; ++ default: ++ return LX_ERR_PARM; ++ } ++ ret = l1f_write_phy(hw, false, 0, false, MII_BMCR, cr); ++ } ++ ++ if (!ret) { ++ l1f_write_phy(hw, false, 0, false, ++ L1F_MII_DBG_ADDR, LX_PHY_INITED); ++ } ++ alx_mem_w32(hw, L1F_DRV, val); ++ ++ return ret; ++} ++ ++ ++/* do power saving setting befor enter suspend mode ++ * NOTE: ++ * 1. phy link must be established before calling this function ++ * 2. wol option (pattern,magic,link,etc.) is configed before call it. ++ */ ++u16 l1f_powersaving(struct alx_hw *hw, ++ u8 wire_spd, ++ bool wol_en, ++ bool mactx_en, ++ bool macrx_en, ++ bool pws_en) ++{ ++ u32 master_ctrl, mac_ctrl, phy_ctrl, val; ++ u16 pm_ctrl, ret = 0; ++ ++ master_ctrl = 0; ++ mac_ctrl = 0; ++ phy_ctrl = 0; ++ ++ pws_en = pws_en; ++ ++ alx_mem_r32(hw, L1F_MASTER, &master_ctrl); ++ master_ctrl &= ~L1F_MASTER_PCLKSEL_SRDS; ++ ++ alx_mem_r32(hw, L1F_MAC_CTRL, &mac_ctrl); ++ /* 10/100 half */ ++ FIELD_SETL(mac_ctrl, L1F_MAC_CTRL_SPEED, L1F_MAC_CTRL_SPEED_10_100); ++ mac_ctrl &= ~(L1F_MAC_CTRL_FULLD | ++ L1F_MAC_CTRL_RX_EN | ++ L1F_MAC_CTRL_TX_EN); ++ ++ alx_mem_r32(hw, L1F_PHY_CTRL, &phy_ctrl); ++ phy_ctrl &= ~(L1F_PHY_CTRL_DSPRST_OUT | L1F_PHY_CTRL_CLS); ++ /* if (pws_en) { */ ++ phy_ctrl |= (L1F_PHY_CTRL_RST_ANALOG | L1F_PHY_CTRL_HIB_PULSE | ++ L1F_PHY_CTRL_HIB_EN); ++ ++ if (wol_en) { /* enable rx packet or tx packet */ ++ if (macrx_en) ++ mac_ctrl |= (L1F_MAC_CTRL_RX_EN | L1F_MAC_CTRL_BRD_EN); ++ if (mactx_en) ++ mac_ctrl |= L1F_MAC_CTRL_TX_EN; ++ if (LX_LC_1000F == wire_spd) { ++ FIELD_SETL(mac_ctrl, L1F_MAC_CTRL_SPEED, ++ L1F_MAC_CTRL_SPEED_1000); ++ } ++ if (LX_LC_10F == wire_spd || ++ LX_LC_100F == wire_spd || ++ LX_LC_100F == wire_spd) { ++ mac_ctrl |= L1F_MAC_CTRL_FULLD; ++ } ++ phy_ctrl |= L1F_PHY_CTRL_DSPRST_OUT; ++ ret = l1f_write_phy(hw, false, 0, false, L1F_MII_IER, ++ L1F_IER_LINK_UP); ++ } else { ++ ret = l1f_write_phy(hw, false, 0, false, L1F_MII_IER, 0); ++ phy_ctrl |= (L1F_PHY_CTRL_IDDQ | L1F_PHY_CTRL_POWER_DOWN); ++ } ++ alx_mem_w32(hw, L1F_MASTER, master_ctrl); ++ alx_mem_w32(hw, L1F_MAC_CTRL, mac_ctrl); ++ alx_mem_w32(hw, L1F_PHY_CTRL, phy_ctrl); ++ ++ /* set val of PDLL D3PLLOFF */ ++ alx_mem_r32(hw, L1F_PDLL_TRNS1, &val); ++ alx_mem_w32(hw, L1F_PDLL_TRNS1, val | L1F_PDLL_TRNS1_D3PLLOFF_EN); ++ ++ /* set PME_EN */ ++ if (wol_en) { ++ alx_cfg_r16(hw, L1F_PM_CSR, &pm_ctrl); ++ pm_ctrl |= L1F_PM_CSR_PME_EN; ++ alx_cfg_w16(hw, L1F_PM_CSR, pm_ctrl); ++ } ++ ++ return ret; ++} ++ ++ ++/* read phy register */ ++u16 l1f_read_phy(struct alx_hw *hw, bool ext, u8 dev, bool fast, ++ u16 reg, u16 *data) ++{ ++ u32 val; ++ u16 clk_sel, i, ret = 0; ++ ++ *data = 0; ++ clk_sel = fast ? ++ (u16)L1F_MDIO_CLK_SEL_25MD4 : (u16)L1F_MDIO_CLK_SEL_25MD128; ++ ++ if (ext) { ++ val = FIELDL(L1F_MDIO_EXTN_DEVAD, dev) | ++ FIELDL(L1F_MDIO_EXTN_REG, reg); ++ alx_mem_w32(hw, L1F_MDIO_EXTN, val); ++ ++ val = L1F_MDIO_SPRES_PRMBL | ++ FIELDL(L1F_MDIO_CLK_SEL, clk_sel) | ++ L1F_MDIO_START | ++ L1F_MDIO_MODE_EXT | ++ L1F_MDIO_OP_READ; ++ } else { ++ val = L1F_MDIO_SPRES_PRMBL | ++ FIELDL(L1F_MDIO_CLK_SEL, clk_sel) | ++ FIELDL(L1F_MDIO_REG, reg) | ++ L1F_MDIO_START | ++ L1F_MDIO_OP_READ; ++ } ++ ++ alx_mem_w32(hw, L1F_MDIO, val); ++ ++ for (i = 0; i < L1F_MDIO_MAX_AC_TO; i++) { ++ alx_mem_r32(hw, L1F_MDIO, &val); ++ if ((val & L1F_MDIO_BUSY) == 0) { ++ *data = (u16)FIELD_GETX(val, L1F_MDIO_DATA); ++ break; ++ } ++ udelay(10); ++ } ++ ++ if (L1F_MDIO_MAX_AC_TO == i) ++ ret = LX_ERR_MIIBUSY; ++ ++ return ret; ++} ++ ++/* write phy register */ ++u16 l1f_write_phy(struct alx_hw *hw, bool ext, u8 dev, bool fast, ++ u16 reg, u16 data) ++{ ++ u32 val; ++ u16 clk_sel, i, ret = 0; ++ ++ clk_sel = fast ? ++ (u16)L1F_MDIO_CLK_SEL_25MD4 : (u16)L1F_MDIO_CLK_SEL_25MD128; ++ ++ if (ext) { ++ val = FIELDL(L1F_MDIO_EXTN_DEVAD, dev) | ++ FIELDL(L1F_MDIO_EXTN_REG, reg); ++ alx_mem_w32(hw, L1F_MDIO_EXTN, val); ++ ++ val = L1F_MDIO_SPRES_PRMBL | ++ FIELDL(L1F_MDIO_CLK_SEL, clk_sel) | ++ FIELDL(L1F_MDIO_DATA, data) | ++ L1F_MDIO_START | ++ L1F_MDIO_MODE_EXT; ++ } else { ++ val = L1F_MDIO_SPRES_PRMBL | ++ FIELDL(L1F_MDIO_CLK_SEL, clk_sel) | ++ FIELDL(L1F_MDIO_REG, reg) | ++ FIELDL(L1F_MDIO_DATA, data) | ++ L1F_MDIO_START; ++ } ++ ++ alx_mem_w32(hw, L1F_MDIO, val); ++ ++ for (i = 0; i < L1F_MDIO_MAX_AC_TO; i++) { ++ alx_mem_r32(hw, L1F_MDIO, &val); ++ if ((val & L1F_MDIO_BUSY) == 0) ++ break; ++ udelay(10); ++ } ++ ++ if (L1F_MDIO_MAX_AC_TO == i) ++ ret = LX_ERR_MIIBUSY; ++ ++ return ret; ++} ++ ++u16 l1f_read_phydbg(struct alx_hw *hw, bool fast, u16 reg, u16 *data) ++{ ++ u16 ret; ++ ++ ret = l1f_write_phy(hw, false, 0, fast, L1F_MII_DBG_ADDR, reg); ++ ret = l1f_read_phy(hw, false, 0, fast, L1F_MII_DBG_DATA, data); ++ ++ return ret; ++} ++ ++u16 l1f_write_phydbg(struct alx_hw *hw, bool fast, u16 reg, u16 data) ++{ ++ u16 ret; ++ ++ ret = l1f_write_phy(hw, false, 0, fast, L1F_MII_DBG_ADDR, reg); ++ ret = l1f_write_phy(hw, false, 0, fast, L1F_MII_DBG_DATA, data); ++ ++ return ret; ++} ++ ++/* ++ * initialize mac basically ++ * most of hi-feature no init ++ * MAC/PHY should be reset before call this function ++ * smb_timer : million-second ++ * int_mod : micro-second ++ * disable RSS as default ++ */ ++u16 l1f_init_mac(struct alx_hw *hw, u8 *addr, u32 txmem_hi, ++ u32 *tx_mem_lo, u8 tx_qnum, u16 txring_sz, ++ u32 rxmem_hi, u32 rfdmem_lo, u32 rrdmem_lo, ++ u16 rxring_sz, u16 rxbuf_sz, u16 smb_timer, ++ u16 mtu, u16 int_mod, bool hash_legacy) ++{ ++ u32 val; ++ u16 val16, devid; ++ u8 dmar_len; ++ ++ alx_cfg_r16(hw, PCI_DEVICE_ID, &devid); ++ ++ /* set mac-address */ ++ val = *(u32 *)(addr + 2); ++ alx_mem_w32(hw, L1F_STAD0, LX_SWAP_DW(val)); ++ val = *(u16 *)addr ; ++ alx_mem_w32(hw, L1F_STAD1, LX_SWAP_W((u16)val)); ++ ++ /* clear multicast hash table, algrithm */ ++ alx_mem_w32(hw, L1F_HASH_TBL0, 0); ++ alx_mem_w32(hw, L1F_HASH_TBL1, 0); ++ alx_mem_r32(hw, L1F_MAC_CTRL, &val); ++ if (hash_legacy) ++ val |= L1F_MAC_CTRL_MHASH_ALG_HI5B; ++ else ++ val &= ~L1F_MAC_CTRL_MHASH_ALG_HI5B; ++ alx_mem_w32(hw, L1F_MAC_CTRL, val); ++ ++ /* clear any wol setting/status */ ++ alx_mem_r32(hw, L1F_WOL0, &val); ++ alx_mem_w32(hw, L1F_WOL0, 0); ++ ++ /* clk gating */ ++ alx_mem_w32(hw, L1F_CLK_GATE, ++ (FIELD_GETX(hw->pci_revid, L1F_PCI_REVID) == L1F_REV_B0) ? ++ L1F_CLK_GATE_ALL_B0 : L1F_CLK_GATE_ALL_A0); ++ ++ /* idle timeout to switch clk_125M */ ++ if (FIELD_GETX(hw->pci_revid, L1F_PCI_REVID) == L1F_REV_B0) { ++ alx_mem_w32(hw, L1F_IDLE_DECISN_TIMER, ++ L1F_IDLE_DECISN_TIMER_DEF); ++ } ++ ++ /* descriptor ring base memory */ ++ alx_mem_w32(hw, L1F_TX_BASE_ADDR_HI, txmem_hi); ++ alx_mem_w32(hw, L1F_TPD_RING_SZ, txring_sz); ++ switch (tx_qnum) { ++ case 4: ++ alx_mem_w32(hw, L1F_TPD_PRI3_ADDR_LO, tx_mem_lo[3]); ++ /* fall through */ ++ case 3: ++ alx_mem_w32(hw, L1F_TPD_PRI2_ADDR_LO, tx_mem_lo[2]); ++ /* fall through */ ++ case 2: ++ alx_mem_w32(hw, L1F_TPD_PRI1_ADDR_LO, tx_mem_lo[1]); ++ /* fall through */ ++ case 1: ++ alx_mem_w32(hw, L1F_TPD_PRI0_ADDR_LO, tx_mem_lo[0]); ++ break; ++ default: ++ return LX_ERR_PARM; ++ } ++ alx_mem_w32(hw, L1F_RX_BASE_ADDR_HI, rxmem_hi); ++ alx_mem_w32(hw, L1F_RFD_ADDR_LO, rfdmem_lo); ++ alx_mem_w32(hw, L1F_RRD_ADDR_LO, rrdmem_lo); ++ alx_mem_w32(hw, L1F_RFD_BUF_SZ, rxbuf_sz); ++ alx_mem_w32(hw, L1F_RRD_RING_SZ, rxring_sz); ++ alx_mem_w32(hw, L1F_RFD_RING_SZ, rxring_sz); ++ alx_mem_w32(hw, L1F_SMB_TIMER, smb_timer * 500UL); ++ alx_mem_w32(hw, L1F_SRAM9, L1F_SRAM_LOAD_PTR); ++ ++ /* int moduration */ ++ alx_mem_r32(hw, L1F_MASTER, &val); ++/* val = (val & ~L1F_MASTER_IRQMOD2_EN) | */ ++ val = val | L1F_MASTER_IRQMOD2_EN | ++ L1F_MASTER_IRQMOD1_EN | ++ L1F_MASTER_SYSALVTIMER_EN; /* sysalive */ ++ alx_mem_w32(hw, L1F_MASTER, val); ++ alx_mem_w32(hw, L1F_IRQ_MODU_TIMER, ++ FIELDL(L1F_IRQ_MODU_TIMER1, int_mod >> 1)); ++ ++ /* tpd threshold to trig int */ ++ alx_mem_w32(hw, L1F_TINT_TPD_THRSHLD, (u32)txring_sz / 3); ++ alx_mem_w32(hw, L1F_TINT_TIMER, int_mod); ++ /* re-send int */ ++ alx_mem_w32(hw, L1F_INT_RETRIG, L1F_INT_RETRIG_TO); ++ ++ /* mtu */ ++ alx_mem_w32(hw, L1F_MTU, (u32)(mtu + 4 + 4)); /* crc + vlan */ ++ if (mtu > L1F_MTU_JUMBO_TH) { ++ alx_mem_r32(hw, L1F_MAC_CTRL, &val); ++ alx_mem_w32(hw, L1F_MAC_CTRL, val & ~L1F_MAC_CTRL_FAST_PAUSE); ++ } ++ ++ /* txq */ ++ if ((mtu + 8) < L1F_TXQ1_JUMBO_TSO_TH) ++ val = (u32)(mtu + 8 + 7) >> 3; /* 7 for QWORD align */ ++ else ++ val = L1F_TXQ1_JUMBO_TSO_TH >> 3; ++ alx_mem_w32(hw, L1F_TXQ1, val | L1F_TXQ1_ERRLGPKT_DROP_EN); ++ alx_mem_r32(hw, L1F_DEV_CTRL, &val); ++ dmar_len = (u8)FIELD_GETX(val, L1F_DEV_CTRL_MAXRRS); ++ /* if BIOS had changed the default dma read max length, ++ * restore it to default value */ ++ if (dmar_len < L1F_DEV_CTRL_MAXRRS_MIN) { ++ FIELD_SETL(val, L1F_DEV_CTRL_MAXRRS, L1F_DEV_CTRL_MAXRRS_MIN); ++ alx_mem_w32(hw, L1F_DEV_CTRL, val); ++ } ++ val = FIELDL(L1F_TXQ0_TPD_BURSTPREF, L1F_TXQ_TPD_BURSTPREF_DEF) | ++ L1F_TXQ0_MODE_ENHANCE | ++ L1F_TXQ0_LSO_8023_EN | ++ L1F_TXQ0_SUPT_IPOPT | ++ FIELDL(L1F_TXQ0_TXF_BURST_PREF, L1F_TXQ_TXF_BURST_PREF_DEF); ++ alx_mem_w32(hw, L1F_TXQ0, val); ++ val = FIELDL(L1F_HQTPD_Q1_NUMPREF, L1F_TXQ_TPD_BURSTPREF_DEF) | ++ FIELDL(L1F_HQTPD_Q2_NUMPREF, L1F_TXQ_TPD_BURSTPREF_DEF) | ++ FIELDL(L1F_HQTPD_Q3_NUMPREF, L1F_TXQ_TPD_BURSTPREF_DEF) | ++ L1F_HQTPD_BURST_EN; ++ alx_mem_w32(hw, L1F_HQTPD, val); ++ ++ /* rxq */ ++ alx_mem_r32(hw, L1F_SRAM5, &val); ++ val = FIELD_GETX(val, L1F_SRAM_RXF_LEN) << 3; /* bytes */ ++ if (val > L1F_SRAM_RXF_LEN_8K) { ++ val16 = L1F_MTU_STD_ALGN >> 3; ++ val = (val - (2 * L1F_MTU_STD_ALGN + L1F_MTU_MIN)) >> 3; ++ } else { ++ val16 = L1F_MTU_STD_ALGN >> 3; ++ val = (val - L1F_MTU_STD_ALGN) >> 3; ++ } ++ alx_mem_w32(hw, L1F_RXQ2, ++ FIELDL(L1F_RXQ2_RXF_XOFF_THRESH, val16) | ++ FIELDL(L1F_RXQ2_RXF_XON_THRESH, val)); ++ val = FIELDL(L1F_RXQ0_NUM_RFD_PREF, L1F_RXQ0_NUM_RFD_PREF_DEF) | ++ FIELDL(L1F_RXQ0_RSS_MODE, L1F_RXQ0_RSS_MODE_DIS) | ++ FIELDL(L1F_RXQ0_IDT_TBL_SIZE, L1F_RXQ0_IDT_TBL_SIZE_DEF) | ++ L1F_RXQ0_RSS_HSTYP_ALL | ++ L1F_RXQ0_RSS_HASH_EN | ++ L1F_RXQ0_IPV6_PARSE_EN; ++ if (mtu > L1F_MTU_JUMBO_TH) ++ val |= L1F_RXQ0_CUT_THRU_EN; ++ if ((devid & 1) != 0) { ++ FIELD_SETL(val, L1F_RXQ0_ASPM_THRESH, ++ L1F_RXQ0_ASPM_THRESH_100M); ++ } ++ alx_mem_w32(hw, L1F_RXQ0, val); ++ ++ /* rfd producer index */ ++ alx_mem_w32(hw, L1F_RFD_PIDX, (u32)rxring_sz - 1); ++ ++ /* DMA */ ++ alx_mem_r32(hw, L1F_DMA, &val); ++ val = FIELDL(L1F_DMA_RORDER_MODE, L1F_DMA_RORDER_MODE_OUT) | ++ L1F_DMA_RREQ_PRI_DATA | ++ FIELDL(L1F_DMA_RREQ_BLEN, dmar_len) | ++ FIELDL(L1F_DMA_WDLY_CNT, L1F_DMA_WDLY_CNT_DEF) | ++ FIELDL(L1F_DMA_RDLY_CNT, L1F_DMA_RDLY_CNT_DEF) | ++ FIELDL(L1F_DMA_RCHNL_SEL, hw->dma_chnl - 1); ++ alx_mem_w32(hw, L1F_DMA, val); ++ ++ return 0; ++} ++ ++ ++u16 l1f_get_phy_config(struct alx_hw *hw) ++{ ++ u32 val; ++ u16 phy_val; ++ ++ alx_mem_r32(hw, L1F_PHY_CTRL, &val); ++ ++ /* phy in rst */ ++ if ((val & L1F_PHY_CTRL_DSPRST_OUT) == 0) ++ return LX_DRV_PHY_UNKNOWN; ++ ++ alx_mem_r32(hw, L1F_DRV, &val); ++ val = FIELD_GETX(val, LX_DRV_PHY); ++ ++ if (LX_DRV_PHY_UNKNOWN == val) ++ return LX_DRV_PHY_UNKNOWN; ++ ++ l1f_read_phy(hw, false, 0, false, L1F_MII_DBG_ADDR, &phy_val); ++ ++ if (LX_PHY_INITED == phy_val) ++ return (u16) val; ++ ++ return LX_DRV_PHY_UNKNOWN; ++} ++ +diff --git a/drivers/net/ethernet/atheros/alx/alf_hw.h b/drivers/net/ethernet/atheros/alx/alf_hw.h +new file mode 100644 +index 0000000..384af9a +--- /dev/null ++++ b/drivers/net/ethernet/atheros/alx/alf_hw.h +@@ -0,0 +1,2098 @@ ++/* ++ * Copyright (c) 2012 Qualcomm Atheros, Inc. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef L1F_HW_H_ ++#define L1F_HW_H_ ++ ++/********************************************************************* ++ * some reqs for l1f_sw.h ++ * ++ * 1. some basic type must be defined if there are not defined by ++ * your compiler: ++ * u8, u16, u32, bool ++ * ++ * 2. PETHCONTEXT difinition should be in l1x_sw.h and it must contain ++ * pci_devid & pci_venid ++ * ++ *********************************************************************/ ++ ++#include "alx_hwcom.h" ++ ++/******************************************************************************/ ++#define L1F_DEV_ID 0x1091 ++#define L2F_DEV_ID 0x1090 ++ ++ ++#define L1F_PCI_REVID_WTH_CR BIT(1) ++#define L1F_PCI_REVID_WTH_XD BIT(0) ++#define L1F_PCI_REVID_MASK ASHFT3(0x1FU) ++#define L1F_PCI_REVID_SHIFT 3 ++#define L1F_REV_A0 0 ++#define L1F_REV_A1 1 ++#define L1F_REV_B0 2 ++ ++#define L1F_PM_CSR 0x0044 /* 16bit */ ++#define L1F_PM_CSR_PME_STAT BIT(15) ++#define L1F_PM_CSR_DSCAL_MASK ASHFT13(3U) ++#define L1F_PM_CSR_DSCAL_SHIFT 13 ++#define L1F_PM_CSR_DSEL_MASK ASHFT9(0xFU) ++#define L1F_PM_CSR_DSEL_SHIFT 9 ++#define L1F_PM_CSR_PME_EN BIT(8) ++#define L1F_PM_CSR_PWST_MASK ASHFT0(3U) ++#define L1F_PM_CSR_PWST_SHIFT 0 ++ ++#define L1F_PM_DATA 0x0047 /* 8bit */ ++ ++ ++#define L1F_DEV_CAP 0x005C ++#define L1F_DEV_CAP_SPLSL_MASK ASHFT26(3UL) ++#define L1F_DEV_CAP_SPLSL_SHIFT 26 ++#define L1F_DEV_CAP_SPLV_MASK ASHFT18(0xFFUL) ++#define L1F_DEV_CAP_SPLV_SHIFT 18 ++#define L1F_DEV_CAP_RBER BIT(15) ++#define L1F_DEV_CAP_PIPRS BIT(14) ++#define L1F_DEV_CAP_AIPRS BIT(13) ++#define L1F_DEV_CAP_ABPRS BIT(12) ++#define L1F_DEV_CAP_L1ACLAT_MASK ASHFT9(7UL) ++#define L1F_DEV_CAP_L1ACLAT_SHIFT 9 ++#define L1F_DEV_CAP_L0SACLAT_MASK ASHFT6(7UL) ++#define L1F_DEV_CAP_L0SACLAT_SHIFT 6 ++#define L1F_DEV_CAP_EXTAG BIT(5) ++#define L1F_DEV_CAP_PHANTOM BIT(4) ++#define L1F_DEV_CAP_MPL_MASK ASHFT0(7UL) ++#define L1F_DEV_CAP_MPL_SHIFT 0 ++#define L1F_DEV_CAP_MPL_128 1 ++#define L1F_DEV_CAP_MPL_256 2 ++#define L1F_DEV_CAP_MPL_512 3 ++#define L1F_DEV_CAP_MPL_1024 4 ++#define L1F_DEV_CAP_MPL_2048 5 ++#define L1F_DEV_CAP_MPL_4096 6 ++ ++#define L1F_DEV_CTRL 0x0060 /* 16bit */ ++#define L1F_DEV_CTRL_MAXRRS_MASK ASHFT12(7U) ++#define L1F_DEV_CTRL_MAXRRS_SHIFT 12 ++#define L1F_DEV_CTRL_MAXRRS_MIN 2 ++#define L1F_DEV_CTRL_NOSNP_EN BIT(11) ++#define L1F_DEV_CTRL_AUXPWR_EN BIT(10) ++#define L1F_DEV_CTRL_PHANTOM_EN BIT(9) ++#define L1F_DEV_CTRL_EXTAG_EN BIT(8) ++#define L1F_DEV_CTRL_MPL_MASK ASHFT5(7U) ++#define L1F_DEV_CTRL_MPL_SHIFT 5 ++#define L1F_DEV_CTRL_RELORD_EN BIT(4) ++#define L1F_DEV_CTRL_URR_EN BIT(3) ++#define L1F_DEV_CTRL_FERR_EN BIT(2) ++#define L1F_DEV_CTRL_NFERR_EN BIT(1) ++#define L1F_DEV_CTRL_CERR_EN BIT(0) ++ ++ ++#define L1F_DEV_STAT 0x0062 /* 16bit */ ++#define L1F_DEV_STAT_XS_PEND BIT(5) ++#define L1F_DEV_STAT_AUXPWR BIT(4) ++#define L1F_DEV_STAT_UR BIT(3) ++#define L1F_DEV_STAT_FERR BIT(2) ++#define L1F_DEV_STAT_NFERR BIT(1) ++#define L1F_DEV_STAT_CERR BIT(0) ++ ++#define L1F_LNK_CAP 0x0064 ++#define L1F_LNK_CAP_PRTNUM_MASK ASHFT24(0xFFUL) ++#define L1F_LNK_CAP_PRTNUM_SHIFT 24 ++#define L1F_LNK_CAP_CLK_PM BIT(18) ++#define L1F_LNK_CAP_L1EXTLAT_MASK ASHFT15(7UL) ++#define L1F_LNK_CAP_L1EXTLAT_SHIFT 15 ++#define L1F_LNK_CAP_L0SEXTLAT_MASK ASHFT12(7UL) ++#define L1F_LNK_CAP_L0SEXTLAT_SHIFT 12 ++#define L1F_LNK_CAP_ASPM_SUP_MASK ASHFT10(3UL) ++#define L1F_LNK_CAP_ASPM_SUP_SHIFT 10 ++#define L1F_LNK_CAP_ASPM_SUP_L0S 1 ++#define L1F_LNK_CAP_ASPM_SUP_L0SL1 3 ++#define L1F_LNK_CAP_MAX_LWH_MASK ASHFT4(0x3FUL) ++#define L1F_LNK_CAP_MAX_LWH_SHIFT 4 ++#define L1F_LNK_CAP_MAX_LSPD_MASH ASHFT0(0xFUL) ++#define L1F_LNK_CAP_MAX_LSPD_SHIFT 0 ++ ++#define L1F_LNK_CTRL 0x0068 /* 16bit */ ++#define L1F_LNK_CTRL_CLK_PM_EN BIT(8) ++#define L1F_LNK_CTRL_EXTSYNC BIT(7) ++#define L1F_LNK_CTRL_CMNCLK_CFG BIT(6) ++#define L1F_LNK_CTRL_RCB_128B BIT(3) /* 0:64b,1:128b */ ++#define L1F_LNK_CTRL_ASPM_MASK ASHFT0(3U) ++#define L1F_LNK_CTRL_ASPM_SHIFT 0 ++#define L1F_LNK_CTRL_ASPM_DIS 0 ++#define L1F_LNK_CTRL_ASPM_ENL0S 1 ++#define L1F_LNK_CTRL_ASPM_ENL1 2 ++#define L1F_LNK_CTRL_ASPM_ENL0SL1 3 ++ ++#define L1F_LNK_STAT 0x006A /* 16bit */ ++#define L1F_LNK_STAT_SCLKCFG BIT(12) ++#define L1F_LNK_STAT_LNKTRAIN BIT(11) ++#define L1F_LNK_STAT_TRNERR BIT(10) ++#define L1F_LNK_STAT_LNKSPD_MASK ASHFT0(0xFU) ++#define L1F_LNK_STAT_LNKSPD_SHIFT 0 ++#define L1F_LNK_STAT_NEGLW_MASK ASHFT4(0x3FU) ++#define L1F_LNK_STAT_NEGLW_SHIFT 4 ++ ++#define L1F_MSIX_MASK 0x0090 ++#define L1F_MSIX_PENDING 0x0094 ++ ++#define L1F_UE_SVRT 0x010C ++#define L1F_UE_SVRT_UR BIT(20) ++#define L1F_UE_SVRT_ECRCERR BIT(19) ++#define L1F_UE_SVRT_MTLP BIT(18) ++#define L1F_UE_SVRT_RCVOVFL BIT(17) ++#define L1F_UE_SVRT_UNEXPCPL BIT(16) ++#define L1F_UE_SVRT_CPLABRT BIT(15) ++#define L1F_UE_SVRT_CPLTO BIT(14) ++#define L1F_UE_SVRT_FCPROTERR BIT(13) ++#define L1F_UE_SVRT_PTLP BIT(12) ++#define L1F_UE_SVRT_DLPROTERR BIT(4) ++#define L1F_UE_SVRT_TRNERR BIT(0) ++ ++#define L1F_EFLD 0x0204 /* eeprom/flash load */ ++#define L1F_EFLD_F_ENDADDR_MASK ASHFT16(0x3FFUL) ++#define L1F_EFLD_F_ENDADDR_SHIFT 16 ++#define L1F_EFLD_F_EXIST BIT(10) ++#define L1F_EFLD_E_EXIST BIT(9) ++#define L1F_EFLD_EXIST BIT(8) ++#define L1F_EFLD_STAT BIT(5) /* 0:finish,1:in progress */ ++#define L1F_EFLD_IDLE BIT(4) ++#define L1F_EFLD_START BIT(0) ++ ++#define L1F_SLD 0x0218 /* efuse load */ ++#define L1F_SLD_FREQ_MASK ASHFT24(3UL) ++#define L1F_SLD_FREQ_SHIFT 24 ++#define L1F_SLD_FREQ_100K 0 ++#define L1F_SLD_FREQ_200K 1 ++#define L1F_SLD_FREQ_300K 2 ++#define L1F_SLD_FREQ_400K 3 ++#define L1F_SLD_EXIST BIT(23) ++#define L1F_SLD_SLVADDR_MASK ASHFT16(0x7FUL) ++#define L1F_SLD_SLVADDR_SHIFT 16 ++#define L1F_SLD_IDLE BIT(13) ++#define L1F_SLD_STAT BIT(12) /* 0:finish,1:in progress */ ++#define L1F_SLD_START BIT(11) ++#define L1F_SLD_STARTADDR_MASK ASHFT0(0xFFUL) ++#define L1F_SLD_STARTADDR_SHIFT 0 ++#define L1F_SLD_MAX_TO 100 ++ ++#define L1F_PCIE_MSIC 0x021C ++#define L1F_PCIE_MSIC_MSIX_DIS BIT(22) ++#define L1F_PCIE_MSIC_MSI_DIS BIT(21) ++ ++#define L1F_PPHY_MISC1 0x1000 ++#define L1F_PPHY_MISC1_RCVDET BIT(2) ++#define L1F_PPHY_MISC1_NFTS_MASK ASHFT16(0xFFUL) ++#define L1F_PPHY_MISC1_NFTS_SHIFT 16 ++#define L1F_PPHY_MISC1_NFTS_HIPERF 0xA0 /* ???? */ ++ ++#define L1F_PPHY_MISC2 0x1004 ++#define L1F_PPHY_MISC2_L0S_TH_MASK ASHFT18(0x3UL) ++#define L1F_PPHY_MISC2_L0S_TH_SHIFT 18 ++#define L1F_PPHY_MISC2_CDR_BW_MASK ASHFT16(0x3UL) ++#define L1F_PPHY_MISC2_CDR_BW_SHIFT 16 ++ ++#define L1F_PDLL_TRNS1 0x1104 ++#define L1F_PDLL_TRNS1_D3PLLOFF_EN BIT(11) ++#define L1F_PDLL_TRNS1_REGCLK_SEL_NORM BIT(10) ++#define L1F_PDLL_TRNS1_REPLY_TO_MASK ASHFT0(0x3FFUL) ++#define L1F_PDLL_TRNS1_REPLY_TO_SHIFT 0 ++ ++ ++#define L1F_TLEXTN_STATS 0x1208 ++#define L1F_TLEXTN_STATS_DEVNO_MASK ASHFT16(0x1FUL) ++#define L1F_TLEXTN_STATS_DEVNO_SHIFT 16 ++#define L1F_TLEXTN_STATS_BUSNO_MASK ASHFT8(0xFFUL) ++#define L1F_TLEXTN_STATS_BUSNO_SHIFT 8 ++ ++#define L1F_EFUSE_CTRL 0x12C0 ++#define L1F_EFUSE_CTRL_FLAG BIT(31) /* 0:read,1:write */ ++#define L1F_EUFSE_CTRL_ACK BIT(30) ++#define L1F_EFUSE_CTRL_ADDR_MASK ASHFT16(0x3FFUL) ++#define L1F_EFUSE_CTRL_ADDR_SHIFT 16 ++ ++#define L1F_EFUSE_DATA 0x12C4 ++ ++#define L1F_SPI_OP1 0x12C8 ++#define L1F_SPI_OP1_RDID_MASK ASHFT24(0xFFUL) ++#define L1F_SPI_OP1_RDID_SHIFT 24 ++#define L1F_SPI_OP1_CE_MASK ASHFT16(0xFFUL) ++#define L1F_SPI_OP1_CE_SHIFT 16 ++#define L1F_SPI_OP1_SE_MASK ASHFT8(0xFFUL) ++#define L1F_SPI_OP1_SE_SHIFT 8 ++#define L1F_SPI_OP1_PRGRM_MASK ASHFT0(0xFFUL) ++#define L1F_SPI_OP1_PRGRM_SHIFT 0 ++ ++#define L1F_SPI_OP2 0x12CC ++#define L1F_SPI_OP2_READ_MASK ASHFT24(0xFFUL) ++#define L1F_SPI_OP2_READ_SHIFT 24 ++#define L1F_SPI_OP2_WRSR_MASK ASHFT16(0xFFUL) ++#define L1F_SPI_OP2_WRSR_SHIFT 16 ++#define L1F_SPI_OP2_RDSR_MASK ASHFT8(0xFFUL) ++#define L1F_SPI_OP2_RDSR_SHIFT 8 ++#define L1F_SPI_OP2_WREN_MASK ASHFT0(0xFFUL) ++#define L1F_SPI_OP2_WREN_SHIFT 0 ++ ++#define L1F_SPI_OP3 0x12E4 ++#define L1F_SPI_OP3_WRDI_MASK ASHFT8(0xFFUL) ++#define L1F_SPI_OP3_WRDI_SHIFT 8 ++#define L1F_SPI_OP3_EWSR_MASK ASHFT0(0xFFUL) ++#define L1F_SPI_OP3_EWSR_SHIFT 0 ++ ++#define L1F_EF_CTRL 0x12D0 ++#define L1F_EF_CTRL_FSTS_MASK ASHFT20(0xFFUL) ++#define L1F_EF_CTRL_FSTS_SHIFT 20 ++#define L1F_EF_CTRL_CLASS_MASK ASHFT16(7UL) ++#define L1F_EF_CTRL_CLASS_SHIFT 16 ++#define L1F_EF_CTRL_CLASS_F_UNKNOWN 0 ++#define L1F_EF_CTRL_CLASS_F_STD 1 ++#define L1F_EF_CTRL_CLASS_F_SST 2 ++#define L1F_EF_CTRL_CLASS_E_UNKNOWN 0 ++#define L1F_EF_CTRL_CLASS_E_1K 1 ++#define L1F_EF_CTRL_CLASS_E_4K 2 ++#define L1F_EF_CTRL_FRET BIT(15) /* 0:OK,1:fail */ ++#define L1F_EF_CTRL_TYP_MASK ASHFT12(3UL) ++#define L1F_EF_CTRL_TYP_SHIFT 12 ++#define L1F_EF_CTRL_TYP_NONE 0 ++#define L1F_EF_CTRL_TYP_F 1 ++#define L1F_EF_CTRL_TYP_E 2 ++#define L1F_EF_CTRL_TYP_UNKNOWN 3 ++#define L1F_EF_CTRL_ONE_CLK BIT(10) ++#define L1F_EF_CTRL_ECLK_MASK ASHFT8(3UL) ++#define L1F_EF_CTRL_ECLK_SHIFT 8 ++#define L1F_EF_CTRL_ECLK_125K 0 ++#define L1F_EF_CTRL_ECLK_250K 1 ++#define L1F_EF_CTRL_ECLK_500K 2 ++#define L1F_EF_CTRL_ECLK_1M 3 ++#define L1F_EF_CTRL_FBUSY BIT(7) ++#define L1F_EF_CTRL_ACTION BIT(6) /* 1:start,0:stop */ ++#define L1F_EF_CTRL_AUTO_OP BIT(5) ++#define L1F_EF_CTRL_SST_MODE BIT(4) /* force using sst */ ++#define L1F_EF_CTRL_INST_MASK ASHFT0(0xFUL) ++#define L1F_EF_CTRL_INST_SHIFT 0 ++#define L1F_EF_CTRL_INST_NONE 0 ++#define L1F_EF_CTRL_INST_READ 1 /* for flash & eeprom */ ++#define L1F_EF_CTRL_INST_RDID 2 ++#define L1F_EF_CTRL_INST_RDSR 3 ++#define L1F_EF_CTRL_INST_WREN 4 ++#define L1F_EF_CTRL_INST_PRGRM 5 ++#define L1F_EF_CTRL_INST_SE 6 ++#define L1F_EF_CTRL_INST_CE 7 ++#define L1F_EF_CTRL_INST_WRSR 10 ++#define L1F_EF_CTRL_INST_EWSR 11 ++#define L1F_EF_CTRL_INST_WRDI 12 ++#define L1F_EF_CTRL_INST_WRITE 2 /* only for eeprom */ ++ ++#define L1F_EF_ADDR 0x12D4 ++#define L1F_EF_DATA 0x12D8 ++#define L1F_SPI_ID 0x12DC ++ ++#define L1F_SPI_CFG_START 0x12E0 ++ ++#define L1F_PMCTRL 0x12F8 ++#define L1F_PMCTRL_HOTRST_WTEN BIT(31) ++#define L1F_PMCTRL_ASPM_FCEN BIT(30) /* L0s/L1 dis by MAC based on ++ * thrghput(setting in 15A0) */ ++#define L1F_PMCTRL_SADLY_EN BIT(29) ++#define L1F_PMCTRL_L0S_BUFSRX_EN BIT(28) ++#define L1F_PMCTRL_LCKDET_TIMER_MASK ASHFT24(0xFUL) ++#define L1F_PMCTRL_LCKDET_TIMER_SHIFT 24 ++#define L1F_PMCTRL_LCKDET_TIMER_DEF 0xC ++#define L1F_PMCTRL_L1REQ_TO_MASK ASHFT20(0xFUL) ++#define L1F_PMCTRL_L1REQ_TO_SHIFT 20 /* pm_request_l1 time > @ ++ * ->L0s not L1 */ ++#define L1F_PMCTRL_L1REG_TO_DEF 0xC ++#define L1F_PMCTRL_TXL1_AFTER_L0S BIT(19) ++#define L1F_PMCTRL_L1_TIMER_MASK ASHFT16(7UL) ++#define L1F_PMCTRL_L1_TIMER_SHIFT 16 ++#define L1F_PMCTRL_L1_TIMER_DIS 0 ++#define L1F_PMCTRL_L1_TIMER_2US 1 ++#define L1F_PMCTRL_L1_TIMER_4US 2 ++#define L1F_PMCTRL_L1_TIMER_8US 3 ++#define L1F_PMCTRL_L1_TIMER_16US 4 ++#define L1F_PMCTRL_L1_TIMER_24US 5 ++#define L1F_PMCTRL_L1_TIMER_32US 6 ++#define L1F_PMCTRL_L1_TIMER_63US 7 ++#define L1F_PMCTRL_RCVR_WT_1US BIT(15) /* 1:1us, 0:2ms */ ++#define L1F_PMCTRL_PWM_VER_11 BIT(14) /* 0:1.0a,1:1.1 */ ++#define L1F_PMCTRL_L1_CLKSW_EN BIT(13) /* en pcie clk sw in L1 */ ++#define L1F_PMCTRL_L0S_EN BIT(12) ++#define L1F_PMCTRL_RXL1_AFTER_L0S BIT(11) ++#define L1F_PMCTRL_L0S_TIMER_MASK ASHFT8(7UL) ++#define L1F_PMCTRL_L0S_TIMER_SHIFT 8 ++#define L1F_PMCTRL_L1_BUFSRX_EN BIT(7) ++#define L1F_PMCTRL_L1_SRDSRX_PWD BIT(6) /* power down serdes rx */ ++#define L1F_PMCTRL_L1_SRDSPLL_EN BIT(5) ++#define L1F_PMCTRL_L1_SRDS_EN BIT(4) ++#define L1F_PMCTRL_L1_EN BIT(3) ++#define L1F_PMCTRL_CLKREQ_EN BIT(2) ++#define L1F_PMCTRL_RBER_EN BIT(1) ++#define L1F_PMCTRL_SPRSDWER_EN BIT(0) ++ ++#define L1F_LTSSM_CTRL 0x12FC ++#define L1F_LTSSM_WRO_EN BIT(12) ++ ++ ++/******************************************************************************/ ++ ++#define L1F_MASTER 0x1400 ++#define L1F_MASTER_OTP_FLG BIT(31) ++#define L1F_MASTER_DEV_NUM_MASK ASHFT24(0x7FUL) ++#define L1F_MASTER_DEV_NUM_SHIFT 24 ++#define L1F_MASTER_REV_NUM_MASK ASHFT16(0xFFUL) ++#define L1F_MASTER_REV_NUM_SHIFT 16 ++#define L1F_MASTER_DEASSRT BIT(15) /*ISSUE DE-ASSERT MSG */ ++#define L1F_MASTER_RDCLR_INT BIT(14) ++#define L1F_MASTER_DMA_RST BIT(13) ++#define L1F_MASTER_PCLKSEL_SRDS BIT(12) /* 1:alwys sel pclk from ++ * serdes, not sw to 25M */ ++#define L1F_MASTER_IRQMOD2_EN BIT(11) /* IRQ MODURATION FOR RX */ ++#define L1F_MASTER_IRQMOD1_EN BIT(10) /* MODURATION FOR TX/RX */ ++#define L1F_MASTER_MANU_INT BIT(9) /* SOFT MANUAL INT */ ++#define L1F_MASTER_MANUTIMER_EN BIT(8) ++#define L1F_MASTER_SYSALVTIMER_EN BIT(7) /* SYS ALIVE TIMER EN */ ++#define L1F_MASTER_OOB_DIS BIT(6) /* OUT OF BOX DIS */ ++#define L1F_MASTER_WAKEN_25M BIT(5) /* WAKE WO. PCIE CLK */ ++#define L1F_MASTER_BERT_START BIT(4) ++#define L1F_MASTER_PCIE_TSTMOD_MASK ASHFT2(3UL) ++#define L1F_MASTER_PCIE_TSTMOD_SHIFT 2 ++#define L1F_MASTER_PCIE_RST BIT(1) ++#define L1F_MASTER_DMA_MAC_RST BIT(0) /* RST MAC & DMA */ ++#define L1F_DMA_MAC_RST_TO 50 ++ ++#define L1F_MANU_TIMER 0x1404 ++ ++#define L1F_IRQ_MODU_TIMER 0x1408 ++#define L1F_IRQ_MODU_TIMER2_MASK ASHFT16(0xFFFFUL) ++#define L1F_IRQ_MODU_TIMER2_SHIFT 16 /* ONLY FOR RX */ ++#define L1F_IRQ_MODU_TIMER1_MASK ASHFT0(0xFFFFUL) ++#define L1F_IRQ_MODU_TIMER1_SHIFT 0 ++ ++#define L1F_PHY_CTRL 0x140C ++#define L1F_PHY_CTRL_ADDR_MASK ASHFT19(0x1FUL) ++#define L1F_PHY_CTRL_ADDR_SHIFT 19 ++#define L1F_PHY_CTRL_BP_VLTGSW BIT(18) ++#define L1F_PHY_CTRL_100AB_EN BIT(17) ++#define L1F_PHY_CTRL_10AB_EN BIT(16) ++#define L1F_PHY_CTRL_PLL_BYPASS BIT(15) ++#define L1F_PHY_CTRL_POWER_DOWN BIT(14) /* affect MAC & PHY, ++ * go to low power sts */ ++#define L1F_PHY_CTRL_PLL_ON BIT(13) /* 1:PLL ALWAYS ON ++ * 0:CAN SWITCH IN LPW */ ++#define L1F_PHY_CTRL_RST_ANALOG BIT(12) ++#define L1F_PHY_CTRL_HIB_PULSE BIT(11) ++#define L1F_PHY_CTRL_HIB_EN BIT(10) ++#define L1F_PHY_CTRL_GIGA_DIS BIT(9) ++#define L1F_PHY_CTRL_IDDQ_DIS BIT(8) /* POWER ON RST */ ++#define L1F_PHY_CTRL_IDDQ BIT(7) /* WHILE REBOOT, BIT8(1) ++ * EFFECTS BIT7 */ ++#define L1F_PHY_CTRL_LPW_EXIT BIT(6) ++#define L1F_PHY_CTRL_GATE_25M BIT(5) ++#define L1F_PHY_CTRL_RVRS_ANEG BIT(4) ++#define L1F_PHY_CTRL_ANEG_NOW BIT(3) ++#define L1F_PHY_CTRL_LED_MODE BIT(2) ++#define L1F_PHY_CTRL_RTL_MODE BIT(1) ++#define L1F_PHY_CTRL_DSPRST_OUT BIT(0) /* OUT OF DSP RST STATE */ ++#define L1F_PHY_CTRL_DSPRST_TO 80 ++#define L1F_PHY_CTRL_CLS (\ ++ L1F_PHY_CTRL_LED_MODE |\ ++ L1F_PHY_CTRL_100AB_EN |\ ++ L1F_PHY_CTRL_PLL_ON) ++ ++#define L1F_MAC_STS 0x1410 ++#define L1F_MAC_STS_SFORCE_MASK ASHFT14(0xFUL) ++#define L1F_MAC_STS_SFORCE_SHIFT 14 ++#define L1F_MAC_STS_CALIB_DONE BIT13 ++#define L1F_MAC_STS_CALIB_RES_MASK ASHFT8(0x1FUL) ++#define L1F_MAC_STS_CALIB_RES_SHIFT 8 ++#define L1F_MAC_STS_CALIBERR_MASK ASHFT4(0xFUL) ++#define L1F_MAC_STS_CALIBERR_SHIFT 4 ++#define L1F_MAC_STS_TXQ_BUSY BIT(3) ++#define L1F_MAC_STS_RXQ_BUSY BIT(2) ++#define L1F_MAC_STS_TXMAC_BUSY BIT(1) ++#define L1F_MAC_STS_RXMAC_BUSY BIT(0) ++#define L1F_MAC_STS_IDLE (\ ++ L1F_MAC_STS_TXQ_BUSY |\ ++ L1F_MAC_STS_RXQ_BUSY |\ ++ L1F_MAC_STS_TXMAC_BUSY |\ ++ L1F_MAC_STS_RXMAC_BUSY) ++ ++#define L1F_MDIO 0x1414 ++#define L1F_MDIO_MODE_EXT BIT(30) /* 0:normal,1:ext */ ++#define L1F_MDIO_POST_READ BIT(29) ++#define L1F_MDIO_AUTO_POLLING BIT(28) ++#define L1F_MDIO_BUSY BIT(27) ++#define L1F_MDIO_CLK_SEL_MASK ASHFT24(7UL) ++#define L1F_MDIO_CLK_SEL_SHIFT 24 ++#define L1F_MDIO_CLK_SEL_25MD4 0 /* 25M DIV 4 */ ++#define L1F_MDIO_CLK_SEL_25MD6 2 ++#define L1F_MDIO_CLK_SEL_25MD8 3 ++#define L1F_MDIO_CLK_SEL_25MD10 4 ++#define L1F_MDIO_CLK_SEL_25MD32 5 ++#define L1F_MDIO_CLK_SEL_25MD64 6 ++#define L1F_MDIO_CLK_SEL_25MD128 7 ++#define L1F_MDIO_START BIT(23) ++#define L1F_MDIO_SPRES_PRMBL BIT(22) ++#define L1F_MDIO_OP_READ BIT(21) /* 1:read,0:write */ ++#define L1F_MDIO_REG_MASK ASHFT16(0x1FUL) ++#define L1F_MDIO_REG_SHIFT 16 ++#define L1F_MDIO_DATA_MASK ASHFT0(0xFFFFUL) ++#define L1F_MDIO_DATA_SHIFT 0 ++#define L1F_MDIO_MAX_AC_TO 120 ++ ++#define L1F_MDIO_EXTN 0x1448 ++#define L1F_MDIO_EXTN_PORTAD_MASK ASHFT21(0x1FUL) ++#define L1F_MDIO_EXTN_PORTAD_SHIFT 21 ++#define L1F_MDIO_EXTN_DEVAD_MASK ASHFT16(0x1FUL) ++#define L1F_MDIO_EXTN_DEVAD_SHIFT 16 ++#define L1F_MDIO_EXTN_REG_MASK ASHFT0(0xFFFFUL) ++#define L1F_MDIO_EXTN_REG_SHIFT 0 ++ ++#define L1F_PHY_STS 0x1418 ++#define L1F_PHY_STS_LPW BIT(31) ++#define L1F_PHY_STS_LPI BIT(30) ++#define L1F_PHY_STS_PWON_STRIP_MASK ASHFT16(0xFFFUL) ++#define L1F_PHY_STS_PWON_STRIP_SHIFT 16 ++ ++#define L1F_PHY_STS_DUPLEX BIT(3) ++#define L1F_PHY_STS_LINKUP BIT(2) ++#define L1F_PHY_STS_SPEED_MASK ASHFT0(3UL) ++#define L1F_PHY_STS_SPEED_SHIFT 0 ++#define L1F_PHY_STS_SPEED_1000M 2 ++#define L1F_PHY_STS_SPEED_100M 1 ++#define L1F_PHY_STS_SPEED_10M 0 ++ ++#define L1F_BIST0 0x141C ++#define L1F_BIST0_COL_MASK ASHFT24(0x3FUL) ++#define L1F_BIST0_COL_SHIFT 24 ++#define L1F_BIST0_ROW_MASK ASHFT12(0xFFFUL) ++#define L1F_BIST0_ROW_SHIFT 12 ++#define L1F_BIST0_STEP_MASK ASHFT8(0xFUL) ++#define L1F_BIST0_STEP_SHIFT 8 ++#define L1F_BIST0_PATTERN_MASK ASHFT4(7UL) ++#define L1F_BIST0_PATTERN_SHIFT 4 ++#define L1F_BIST0_CRIT BIT(3) ++#define L1F_BIST0_FIXED BIT(2) ++#define L1F_BIST0_FAIL BIT(1) ++#define L1F_BIST0_START BIT(0) ++ ++#define L1F_BIST1 0x1420 ++#define L1F_BIST1_COL_MASK ASHFT24(0x3FUL) ++#define L1F_BIST1_COL_SHIFT 24 ++#define L1F_BIST1_ROW_MASK ASHFT12(0xFFFUL) ++#define L1F_BIST1_ROW_SHIFT 12 ++#define L1F_BIST1_STEP_MASK ASHFT8(0xFUL) ++#define L1F_BIST1_STEP_SHIFT 8 ++#define L1F_BIST1_PATTERN_MASK ASHFT4(7UL) ++#define L1F_BIST1_PATTERN_SHIFT 4 ++#define L1F_BIST1_CRIT BIT(3) ++#define L1F_BIST1_FIXED BIT(2) ++#define L1F_BIST1_FAIL BIT(1) ++#define L1F_BIST1_START BIT(0) ++ ++#define L1F_SERDES 0x1424 ++#define L1F_SERDES_PHYCLK_SLWDWN BIT(18) ++#define L1F_SERDES_MACCLK_SLWDWN BIT(17) ++#define L1F_SERDES_SELFB_PLL_MASK ASHFT14(3UL) ++#define L1F_SERDES_SELFB_PLL_SHIFT 14 ++#define L1F_SERDES_PHYCLK_SEL_GTX BIT(13) /* 1:gtx_clk, 0:25M */ ++#define L1F_SERDES_PCIECLK_SEL_SRDS BIT(12) /* 1:serdes,0:25M */ ++#define L1F_SERDES_BUFS_RX_EN BIT(11) ++#define L1F_SERDES_PD_RX BIT(10) ++#define L1F_SERDES_PLL_EN BIT(9) ++#define L1F_SERDES_EN BIT(8) ++#define L1F_SERDES_SELFB_PLL_SEL_CSR BIT(6) /* 0:state-machine,1:csr */ ++#define L1F_SERDES_SELFB_PLL_CSR_MASK ASHFT4(3UL) ++#define L1F_SERDES_SELFB_PLL_CSR_SHIFT 4 ++#define L1F_SERDES_SELFB_PLL_CSR_4 3 /* 4-12% OV-CLK */ ++#define L1F_SERDES_SELFB_PLL_CSR_0 2 /* 0-4% OV-CLK */ ++#define L1F_SERDES_SELFB_PLL_CSR_12 1 /* 12-18% OV-CLK */ ++#define L1F_SERDES_SELFB_PLL_CSR_18 0 /* 18-25% OV-CLK */ ++#define L1F_SERDES_VCO_SLOW BIT(3) ++#define L1F_SERDES_VCO_FAST BIT(2) ++#define L1F_SERDES_LOCKDCT_EN BIT(1) ++#define L1F_SERDES_LOCKDCTED BIT(0) ++ ++#define L1F_LED_CTRL 0x1428 ++#define L1F_LED_CTRL_PATMAP2_MASK ASHFT8(3UL) ++#define L1F_LED_CTRL_PATMAP2_SHIFT 8 ++#define L1F_LED_CTRL_PATMAP1_MASK ASHFT6(3UL) ++#define L1F_LED_CTRL_PATMAP1_SHIFT 6 ++#define L1F_LED_CTRL_PATMAP0_MASK ASHFT4(3UL) ++#define L1F_LED_CTRL_PATMAP0_SHIFT 4 ++#define L1F_LED_CTRL_D3_MODE_MASK ASHFT2(3UL) ++#define L1F_LED_CTRL_D3_MODE_SHIFT 2 ++#define L1F_LED_CTRL_D3_MODE_NORMAL 0 ++#define L1F_LED_CTRL_D3_MODE_WOL_DIS 1 ++#define L1F_LED_CTRL_D3_MODE_WOL_ANY 2 ++#define L1F_LED_CTRL_D3_MODE_WOL_EN 3 ++#define L1F_LED_CTRL_DUTY_CYCL_MASK ASHFT0(3UL) ++#define L1F_LED_CTRL_DUTY_CYCL_SHIFT 0 ++#define L1F_LED_CTRL_DUTY_CYCL_50 0 /* 50% */ ++#define L1F_LED_CTRL_DUTY_CYCL_125 1 /* 12.5% */ ++#define L1F_LED_CTRL_DUTY_CYCL_25 2 /* 25% */ ++#define L1F_LED_CTRL_DUTY_CYCL_75 3 /* 75% */ ++ ++#define L1F_LED_PATN 0x142C ++#define L1F_LED_PATN1_MASK ASHFT16(0xFFFFUL) ++#define L1F_LED_PATN1_SHIFT 16 ++#define L1F_LED_PATN0_MASK ASHFT0(0xFFFFUL) ++#define L1F_LED_PATN0_SHIFT 0 ++ ++#define L1F_LED_PATN2 0x1430 ++#define L1F_LED_PATN2_MASK ASHFT0(0xFFFFUL) ++#define L1F_LED_PATN2_SHIFT 0 ++ ++#define L1F_SYSALV 0x1434 ++#define L1F_SYSALV_FLAG BIT(0) ++ ++#define L1F_PCIERR_INST 0x1438 ++#define L1F_PCIERR_INST_TX_RATE_MASK ASHFT4(0xFUL) ++#define L1F_PCIERR_INST_TX_RATE_SHIFT 4 ++#define L1F_PCIERR_INST_RX_RATE_MASK ASHFT0(0xFUL) ++#define L1F_PCIERR_INST_RX_RATE_SHIFT 0 ++ ++#define L1F_LPI_DECISN_TIMER 0x143C ++ ++#define L1F_LPI_CTRL 0x1440 ++#define L1F_LPI_CTRL_CHK_DA BIT(31) ++#define L1F_LPI_CTRL_ENH_TO_MASK ASHFT12(0x1FFFUL) ++#define L1F_LPI_CTRL_ENH_TO_SHIFT 12 ++#define L1F_LPI_CTRL_ENH_TH_MASK ASHFT6(0x1FUL) ++#define L1F_LPI_CTRL_ENH_TH_SHIFT 6 ++#define L1F_LPI_CTRL_ENH_EN BIT(5) ++#define L1F_LPI_CTRL_CHK_RX BIT(4) ++#define L1F_LPI_CTRL_CHK_STATE BIT(3) ++#define L1F_LPI_CTRL_GMII BIT(2) ++#define L1F_LPI_CTRL_TO_PHY BIT(1) ++#define L1F_LPI_CTRL_EN BIT(0) ++ ++#define L1F_LPI_WAIT 0x1444 ++#define L1F_LPI_WAIT_TIMER_MASK ASHFT0(0xFFFFUL) ++#define L1F_LPI_WAIT_TIMER_SHIFT 0 ++ ++#define L1F_HRTBT_VLAN 0x1450 /* HEARTBEAT, FOR CIFS */ ++#define L1F_HRTBT_VLANID_MASK ASHFT0(0xFFFFUL) /* OR CLOUD */ ++#define L1F_HRRBT_VLANID_SHIFT 0 ++ ++#define L1F_HRTBT_CTRL 0x1454 ++#define L1F_HRTBT_CTRL_EN BIT(31) ++#define L1F_HRTBT_CTRL_PERIOD_MASK ASHFT25(0x3FUL) ++#define L1F_HRTBT_CTRL_PERIOD_SHIFT 25 ++#define L1F_HRTBT_CTRL_HASVLAN BIT(24) ++#define L1F_HRTBT_CTRL_HDRADDR_MASK ASHFT12(0xFFFUL) /* A0 */ ++#define L1F_HRTBT_CTRL_HDRADDR_SHIFT 12 ++#define L1F_HRTBT_CTRL_HDRADDRB0_MASK ASHFT13(0x7FFUL) /* B0 */ ++#define L1F_HRTBT_CTRL_HDRADDRB0_SHIFT 13 ++#define L1F_HRTBT_CTRL_PKT_FRAG BIT(12) /* B0 */ ++#define L1F_HRTBT_CTRL_PKTLEN_MASK ASHFT0(0xFFFUL) ++#define L1F_HRTBT_CTRL_PKTLEN_SHIFT 0 ++ ++#define L1F_HRTBT_EXT_CTRL 0x1AD0 /* B0 */ ++#define L1F_HRTBT_EXT_CTRL_NS_EN BIT(12) ++#define L1F_HRTBT_EXT_CTRL_FRAG_LEN_MASK ASHFT4(0xFFUL) ++#define L1F_HRTBT_EXT_CTRL_FRAG_LEN_SHIFT 4 ++#define L1F_HRTBT_EXT_CTRL_IS_8023 BIT(3) ++#define L1F_HRTBT_EXT_CTRL_IS_IPV6 BIT(2) ++#define L1F_HRTBT_EXT_CTRL_WAKEUP_EN BIT(1) ++#define L1F_HRTBT_EXT_CTRL_ARP_EN BIT(0) ++ ++#define L1F_HRTBT_REM_IPV4_ADDR 0x1AD4 ++#define L1F_HRTBT_HOST_IPV4_ADDR 0x1478/*use L1F_TRD_BUBBLE_DA_IP4*/ ++#define L1F_HRTBT_REM_IPV6_ADDR3 0x1AD8 ++#define L1F_HRTBT_REM_IPV6_ADDR2 0x1ADC ++#define L1F_HRTBT_REM_IPV6_ADDR1 0x1AE0 ++#define L1F_HRTBT_REM_IPV6_ADDR0 0x1AE4 ++/*SWOI_HOST_IPV6_ADDR reuse reg1a60-1a6c, 1a70-1a7c, 1aa0-1aac, 1ab0-1abc.*/ ++#define L1F_HRTBT_WAKEUP_PORT 0x1AE8 ++#define L1F_HRTBT_WAKEUP_PORT_SRC_MASK ASHFT16(0xFFFFUL) ++#define L1F_HRTBT_WAKEUP_PORT_SRC_SHIFT 16 ++#define L1F_HRTBT_WAKEUP_PORT_DEST_MASK ASHFT0(0xFFFFUL) ++#define L1F_HRTBT_WAKEUP_PORT_DEST_SHIFT 0 ++ ++#define L1F_HRTBT_WAKEUP_DATA7 0x1AEC ++#define L1F_HRTBT_WAKEUP_DATA6 0x1AF0 ++#define L1F_HRTBT_WAKEUP_DATA5 0x1AF4 ++#define L1F_HRTBT_WAKEUP_DATA4 0x1AF8 ++#define L1F_HRTBT_WAKEUP_DATA3 0x1AFC ++#define L1F_HRTBT_WAKEUP_DATA2 0x1B80 ++#define L1F_HRTBT_WAKEUP_DATA1 0x1B84 ++#define L1F_HRTBT_WAKEUP_DATA0 0x1B88 ++ ++#define L1F_RXPARSE 0x1458 ++#define L1F_RXPARSE_FLT6_L4_MASK ASHFT30(3UL) ++#define L1F_RXPARSE_FLT6_L4_SHIFT 30 ++#define L1F_RXPARSE_FLT6_L3_MASK ASHFT28(3UL) ++#define L1F_RXPARSE_FLT6_L3_SHIFT 28 ++#define L1F_RXPARSE_FLT5_L4_MASK ASHFT26(3UL) ++#define L1F_RXPARSE_FLT5_L4_SHIFT 26 ++#define L1F_RXPARSE_FLT5_L3_MASK ASHFT24(3UL) ++#define L1F_RXPARSE_FLT5_L3_SHIFT 24 ++#define L1F_RXPARSE_FLT4_L4_MASK ASHFT22(3UL) ++#define L1F_RXPARSE_FLT4_L4_SHIFT 22 ++#define L1F_RXPARSE_FLT4_L3_MASK ASHFT20(3UL) ++#define L1F_RXPARSE_FLT4_L3_SHIFT 20 ++#define L1F_RXPARSE_FLT3_L4_MASK ASHFT18(3UL) ++#define L1F_RXPARSE_FLT3_L4_SHIFT 18 ++#define L1F_RXPARSE_FLT3_L3_MASK ASHFT16(3UL) ++#define L1F_RXPARSE_FLT3_L3_SHIFT 16 ++#define L1F_RXPARSE_FLT2_L4_MASK ASHFT14(3UL) ++#define L1F_RXPARSE_FLT2_L4_SHIFT 14 ++#define L1F_RXPARSE_FLT2_L3_MASK ASHFT12(3UL) ++#define L1F_RXPARSE_FLT2_L3_SHIFT 12 ++#define L1F_RXPARSE_FLT1_L4_MASK ASHFT10(3UL) ++#define L1F_RXPARSE_FLT1_L4_SHIFT 10 ++#define L1F_RXPARSE_FLT1_L3_MASK ASHFT8(3UL) ++#define L1F_RXPARSE_FLT1_L3_SHIFT 8 ++#define L1F_RXPARSE_FLT6_EN BIT(5) ++#define L1F_RXPARSE_FLT5_EN BIT(4) ++#define L1F_RXPARSE_FLT4_EN BIT(3) ++#define L1F_RXPARSE_FLT3_EN BIT(2) ++#define L1F_RXPARSE_FLT2_EN BIT(1) ++#define L1F_RXPARSE_FLT1_EN BIT(0) ++#define L1F_RXPARSE_FLT_L4_UDP 0 ++#define L1F_RXPARSE_FLT_L4_TCP 1 ++#define L1F_RXPARSE_FLT_L4_BOTH 2 ++#define L1F_RXPARSE_FLT_L4_NONE 3 ++#define L1F_RXPARSE_FLT_L3_IPV6 0 ++#define L1F_RXPARSE_FLT_L3_IPV4 1 ++#define L1F_RXPARSE_FLT_L3_BOTH 2 ++ ++/* Terodo support */ ++#define L1F_TRD_CTRL 0x145C ++#define L1F_TRD_CTRL_EN BIT(31) ++#define L1F_TRD_CTRL_BUBBLE_WAKE_EN BIT(30) ++#define L1F_TRD_CTRL_PREFIX_CMP_HW BIT(28) ++#define L1F_TRD_CTRL_RSHDR_ADDR_MASK ASHFT16(0xFFFUL) ++#define L1F_TRD_CTRL_RSHDR_ADDR_SHIFT 16 ++#define L1F_TRD_CTRL_SINTV_MAX_MASK ASHFT8(0xFFUL) ++#define L1F_TRD_CTRL_SINTV_MAX_SHIFT 8 ++#define L1F_TRD_CTRL_SINTV_MIN_MASK ASHFT0(0xFFUL) ++#define L1F_TRD_CTRL_SINTV_MIN_SHIFT 0 ++ ++#define L1F_TRD_RS 0x1460 ++#define L1F_TRD_RS_SZ_MASK ASHFT20(0xFFFUL) ++#define L1F_TRD_RS_SZ_SHIFT 20 ++#define L1F_TRD_RS_NONCE_OFS_MASK ASHFT8(0xFFFUL) ++#define L1F_TRD_RS_NONCE_OFS_SHIFT 8 ++#define L1F_TRD_RS_SEQ_OFS_MASK ASHFT0(0xFFUL) ++#define L1F_TRD_RS_SEQ_OFS_SHIFT 0 ++ ++#define L1F_TRD_SRV_IP4 0x1464 ++ ++#define L1F_TRD_CLNT_EXTNL_IP4 0x1468 ++ ++#define L1F_TRD_PORT 0x146C ++#define L1F_TRD_PORT_CLNT_EXTNL_MASK ASHFT16(0xFFFFUL) ++#define L1F_TRD_PORT_CLNT_EXTNL_SHIFT 16 ++#define L1F_TRD_PORT_SRV_MASK ASHFT0(0xFFFFUL) ++#define L1F_TRD_PORT_SRV_SHIFT 0 ++ ++#define L1F_TRD_PREFIX 0x1470 ++ ++#define L1F_TRD_BUBBLE_DA_IP4 0x1478 ++ ++#define L1F_TRD_BUBBLE_DA_PORT 0x147C ++ ++ ++#define L1F_IDLE_DECISN_TIMER 0x1474 /* B0 */ ++#define L1F_IDLE_DECISN_TIMER_DEF 0x400 /* 1ms */ ++ ++ ++#define L1F_MAC_CTRL 0x1480 ++#define L1F_MAC_CTRL_FAST_PAUSE BIT(31) ++#define L1F_MAC_CTRL_WOLSPED_SWEN BIT(30) ++#define L1F_MAC_CTRL_MHASH_ALG_HI5B BIT(29) /* 1:legacy, 0:marvl(low5b)*/ ++#define L1F_MAC_CTRL_SPAUSE_EN BIT(28) ++#define L1F_MAC_CTRL_DBG_EN BIT(27) ++#define L1F_MAC_CTRL_BRD_EN BIT(26) ++#define L1F_MAC_CTRL_MULTIALL_EN BIT(25) ++#define L1F_MAC_CTRL_RX_XSUM_EN BIT(24) ++#define L1F_MAC_CTRL_THUGE BIT(23) ++#define L1F_MAC_CTRL_MBOF BIT(22) ++#define L1F_MAC_CTRL_SPEED_MASK ASHFT20(3UL) ++#define L1F_MAC_CTRL_SPEED_SHIFT 20 ++#define L1F_MAC_CTRL_SPEED_10_100 1 ++#define L1F_MAC_CTRL_SPEED_1000 2 ++#define L1F_MAC_CTRL_SIMR BIT(19) ++#define L1F_MAC_CTRL_SSTCT BIT(17) ++#define L1F_MAC_CTRL_TPAUSE BIT(16) ++#define L1F_MAC_CTRL_PROMISC_EN BIT(15) ++#define L1F_MAC_CTRL_VLANSTRIP BIT(14) ++#define L1F_MAC_CTRL_PRMBLEN_MASK ASHFT10(0xFUL) ++#define L1F_MAC_CTRL_PRMBLEN_SHIFT 10 ++#define L1F_MAC_CTRL_RHUGE_EN BIT(9) ++#define L1F_MAC_CTRL_FLCHK BIT(8) ++#define L1F_MAC_CTRL_PCRCE BIT(7) ++#define L1F_MAC_CTRL_CRCE BIT(6) ++#define L1F_MAC_CTRL_FULLD BIT(5) ++#define L1F_MAC_CTRL_LPBACK_EN BIT(4) ++#define L1F_MAC_CTRL_RXFC_EN BIT(3) ++#define L1F_MAC_CTRL_TXFC_EN BIT(2) ++#define L1F_MAC_CTRL_RX_EN BIT(1) ++#define L1F_MAC_CTRL_TX_EN BIT(0) ++ ++#define L1F_GAP 0x1484 ++#define L1F_GAP_IPGR2_MASK ASHFT24(0x7FUL) ++#define L1F_GAP_IPGR2_SHIFT 24 ++#define L1F_GAP_IPGR1_MASK ASHFT16(0x7FUL) ++#define L1F_GAP_IPGR1_SHIFT 16 ++#define L1F_GAP_MIN_IFG_MASK ASHFT8(0xFFUL) ++#define L1F_GAP_MIN_IFG_SHIFT 8 ++#define L1F_GAP_IPGT_MASK ASHFT0(0x7FUL) /* A0 diff with B0 */ ++#define L1F_GAP_IPGT_SHIFT 0 ++ ++#define L1F_STAD0 0x1488 ++#define L1F_STAD1 0x148C ++ ++#define L1F_HASH_TBL0 0x1490 ++#define L1F_HASH_TBL1 0x1494 ++ ++#define L1F_HALFD 0x1498 ++#define L1F_HALFD_JAM_IPG_MASK ASHFT24(0xFUL) ++#define L1F_HALFD_JAM_IPG_SHIFT 24 ++#define L1F_HALFD_ABEBT_MASK ASHFT20(0xFUL) ++#define L1F_HALFD_ABEBT_SHIFT 20 ++#define L1F_HALFD_ABEBE BIT(19) ++#define L1F_HALFD_BPNB BIT(18) ++#define L1F_HALFD_NOBO BIT(17) ++#define L1F_HALFD_EDXSDFR BIT(16) ++#define L1F_HALFD_RETRY_MASK ASHFT12(0xFUL) ++#define L1F_HALFD_RETRY_SHIFT 12 ++#define L1F_HALFD_LCOL_MASK ASHFT0(0x3FFUL) ++#define L1F_HALFD_LCOL_SHIFT 0 ++ ++#define L1F_MTU 0x149C ++#define L1F_MTU_JUMBO_TH 1514 ++#define L1F_MTU_STD_ALGN 1536 ++#define L1F_MTU_MIN 64 ++ ++#define L1F_SRAM0 0x1500 ++#define L1F_SRAM_RFD_TAIL_ADDR_MASK ASHFT16(0xFFFUL) ++#define L1F_SRAM_RFD_TAIL_ADDR_SHIFT 16 ++#define L1F_SRAM_RFD_HEAD_ADDR_MASK ASHFT0(0xFFFUL) ++#define L1F_SRAM_RFD_HEAD_ADDR_SHIFT 0 ++ ++#define L1F_SRAM1 0x1510 ++#define L1F_SRAM_RFD_LEN_MASK ASHFT0(0xFFFUL) /* 8BYTES UNIT */ ++#define L1F_SRAM_RFD_LEN_SHIFT 0 ++ ++#define L1F_SRAM2 0x1518 ++#define L1F_SRAM_TRD_TAIL_ADDR_MASK ASHFT16(0xFFFUL) ++#define L1F_SRAM_TRD_TAIL_ADDR_SHIFT 16 ++#define L1F_SRMA_TRD_HEAD_ADDR_MASK ASHFT0(0xFFFUL) ++#define L1F_SRAM_TRD_HEAD_ADDR_SHIFT 0 ++ ++#define L1F_SRAM3 0x151C ++#define L1F_SRAM_TRD_LEN_MASK ASHFT0(0xFFFUL) /* 8BYTES UNIT */ ++#define L1F_SRAM_TRD_LEN_SHIFT 0 ++ ++#define L1F_SRAM4 0x1520 ++#define L1F_SRAM_RXF_TAIL_ADDR_MASK ASHFT16(0xFFFUL) ++#define L1F_SRAM_RXF_TAIL_ADDR_SHIFT 16 ++#define L1F_SRAM_RXF_HEAD_ADDR_MASK ASHFT0(0xFFFUL) ++#define L1F_SRAM_RXF_HEAD_ADDR_SHIFT 0 ++ ++#define L1F_SRAM5 0x1524 ++#define L1F_SRAM_RXF_LEN_MASK ASHFT0(0xFFFUL) /* 8BYTES UNIT */ ++#define L1F_SRAM_RXF_LEN_SHIFT 0 ++#define L1F_SRAM_RXF_LEN_8K (8*1024) ++ ++#define L1F_SRAM6 0x1528 ++#define L1F_SRAM_TXF_TAIL_ADDR_MASK ASHFT16(0xFFFUL) ++#define L1F_SRAM_TXF_TAIL_ADDR_SHIFT 16 ++#define L1F_SRAM_TXF_HEAD_ADDR_MASK ASHFT0(0xFFFUL) ++#define L1F_SRAM_TXF_HEAD_ADDR_SHIFT 0 ++ ++#define L1F_SRAM7 0x152C ++#define L1F_SRAM_TXF_LEN_MASK ASHFT0(0xFFFUL) /* 8BYTES UNIT */ ++#define L1F_SRAM_TXF_LEN_SHIFT 0 ++ ++#define L1F_SRAM8 0x1530 ++#define L1F_SRAM_PATTERN_ADDR_MASK ASHFT16(0xFFFUL) ++#define L1F_SRAM_PATTERN_ADDR_SHIFT 16 ++#define L1F_SRAM_TSO_ADDR_MASK ASHFT0(0xFFFUL) ++#define L1F_SRAM_TSO_ADDR_SHIFT 0 ++ ++#define L1F_SRAM9 0x1534 ++#define L1F_SRAM_LOAD_PTR BIT(0) ++ ++#define L1F_RX_BASE_ADDR_HI 0x1540 ++ ++#define L1F_TX_BASE_ADDR_HI 0x1544 ++ ++#define L1F_RFD_ADDR_LO 0x1550 ++#define L1F_RFD_RING_SZ 0x1560 ++#define L1F_RFD_BUF_SZ 0x1564 ++#define L1F_RFD_BUF_SZ_MASK ASHFT0(0xFFFFUL) ++#define L1F_RFD_BUF_SZ_SHIFT 0 ++ ++#define L1F_RRD_ADDR_LO 0x1568 ++#define L1F_RRD_RING_SZ 0x1578 ++#define L1F_RRD_RING_SZ_MASK ASHFT0(0xFFFUL) ++#define L1F_RRD_RING_SZ_SHIFT 0 ++ ++#define L1F_TPD_PRI3_ADDR_LO 0x14E4 /* HIGHEST PRIORITY */ ++#define L1F_TPD_PRI2_ADDR_LO 0x14E0 ++#define L1F_TPD_PRI1_ADDR_LO 0x157C ++#define L1F_TPD_PRI0_ADDR_LO 0x1580 /* LOWEST PRORITY */ ++ ++#define L1F_TPD_PRI3_PIDX 0x1618 /* 16BIT */ ++#define L1F_TPD_PRI2_PIDX 0x161A /* 16BIT */ ++#define L1F_TPD_PRI1_PIDX 0x15F0 /* 16BIT */ ++#define L1F_TPD_PRI0_PIDX 0x15F2 /* 16BIT */ ++ ++#define L1F_TPD_PRI3_CIDX 0x161C /* 16BIT */ ++#define L1F_TPD_PRI2_CIDX 0x161E /* 16BIT */ ++#define L1F_TPD_PRI1_CIDX 0x15F4 /* 16BIT */ ++#define L1F_TPD_PRI0_CIDX 0x15F6 /* 16BIT */ ++ ++#define L1F_TPD_RING_SZ 0x1584 ++#define L1F_TPD_RING_SZ_MASK ASHFT0(0xFFFFUL) ++#define L1F_TPD_RING_SZ_SHIFT 0 ++ ++#define L1F_CMB_ADDR_LO 0x1588 /* NOT USED */ ++ ++#define L1F_TXQ0 0x1590 ++#define L1F_TXQ0_TXF_BURST_PREF_MASK ASHFT16(0xFFFFUL) ++#define L1F_TXQ0_TXF_BURST_PREF_SHIFT 16 ++#define L1F_TXQ_TXF_BURST_PREF_DEF 0x200 ++#define L1F_TXQ0_PEDING_CLR BIT(8) ++#define L1F_TXQ0_LSO_8023_EN BIT(7) ++#define L1F_TXQ0_MODE_ENHANCE BIT(6) ++#define L1F_TXQ0_EN BIT(5) ++#define L1F_TXQ0_SUPT_IPOPT BIT(4) ++#define L1F_TXQ0_TPD_BURSTPREF_MASK ASHFT0(0xFUL) ++#define L1F_TXQ0_TPD_BURSTPREF_SHIFT 0 ++#define L1F_TXQ_TPD_BURSTPREF_DEF 5 ++ ++#define L1F_TXQ1 0x1594 ++#define L1F_TXQ1_ERRLGPKT_DROP_EN BIT(11) /* drop error large ++ * (>rfd buf) packet */ ++#define L1F_TXQ1_JUMBO_TSOTHR_MASK ASHFT0(0x7FFUL) /* 8BYTES UNIT */ ++#define L1F_TXQ1_JUMBO_TSOTHR_SHIFT 0 ++#define L1F_TXQ1_JUMBO_TSO_TH (7*1024) /* byte */ ++ ++#define L1F_TXQ2 0x1598 /* ENTER L1 CONTROL */ ++#define L1F_TXQ2_BURST_EN BIT(31) ++#define L1F_TXQ2_BURST_HI_WM_MASK ASHFT16(0xFFFUL) ++#define L1F_TXQ2_BURST_HI_WM_SHIFT 16 ++#define L1F_TXQ2_BURST_LO_WM_MASK ASHFT0(0xFFFUL) ++#define L1F_TXQ2_BURST_LO_WM_SHIFT 0 ++ ++#define L1F_RXQ0 0x15A0 ++#define L1F_RXQ0_EN BIT(31) ++#define L1F_RXQ0_CUT_THRU_EN BIT(30) ++#define L1F_RXQ0_RSS_HASH_EN BIT(29) ++#define L1F_RXQ0_NON_IP_QTBL BIT(28) /* 0:q0,1:table */ ++#define L1F_RXQ0_RSS_MODE_MASK ASHFT26(3UL) ++#define L1F_RXQ0_RSS_MODE_SHIFT 26 ++#define L1F_RXQ0_RSS_MODE_DIS 0 ++#define L1F_RXQ0_RSS_MODE_SQSI 1 ++#define L1F_RXQ0_RSS_MODE_MQSI 2 ++#define L1F_RXQ0_RSS_MODE_MQMI 3 ++#define L1F_RXQ0_NUM_RFD_PREF_MASK ASHFT20(0x3FUL) ++#define L1F_RXQ0_NUM_RFD_PREF_SHIFT 20 ++#define L1F_RXQ0_NUM_RFD_PREF_DEF 8 ++#define L1F_RXQ0_IDT_TBL_SIZE_MASK ASHFT8(0x1FFUL) ++#define L1F_RXQ0_IDT_TBL_SIZE_SHIFT 8 ++#define L1F_RXQ0_IDT_TBL_SIZE_DEF 0x100 ++#define L1F_RXQ0_IPV6_PARSE_EN BIT(7) ++#define L1F_RXQ0_RSS_HSTYP_IPV6_TCP_EN BIT(5) ++#define L1F_RXQ0_RSS_HSTYP_IPV6_EN BIT(4) ++#define L1F_RXQ0_RSS_HSTYP_IPV4_TCP_EN BIT(3) ++#define L1F_RXQ0_RSS_HSTYP_IPV4_EN BIT(2) ++#define L1F_RXQ0_RSS_HSTYP_ALL (\ ++ L1F_RXQ0_RSS_HSTYP_IPV6_TCP_EN |\ ++ L1F_RXQ0_RSS_HSTYP_IPV4_TCP_EN |\ ++ L1F_RXQ0_RSS_HSTYP_IPV6_EN |\ ++ L1F_RXQ0_RSS_HSTYP_IPV4_EN) ++#define L1F_RXQ0_ASPM_THRESH_MASK ASHFT0(3UL) ++#define L1F_RXQ0_ASPM_THRESH_SHIFT 0 ++#define L1F_RXQ0_ASPM_THRESH_NO 0 ++#define L1F_RXQ0_ASPM_THRESH_1M 1 ++#define L1F_RXQ0_ASPM_THRESH_10M 2 ++#define L1F_RXQ0_ASPM_THRESH_100M 3 ++ ++#define L1F_RXQ1 0x15A4 ++#define L1F_RXQ1_JUMBO_LKAH_MASK ASHFT12(0xFUL) /* 32BYTES UNIT */ ++#define L1F_RXQ1_JUMBO_LKAH_SHIFT 12 ++#define L1F_RXQ1_RFD_PREF_DOWN_MASK ASHFT6(0x3FUL) ++#define L1F_RXQ1_RFD_PREF_DOWN_SHIFT 6 ++#define L1F_RXQ1_RFD_PREF_UP_MASK ASHFT0(0x3FUL) ++#define L1F_RXQ1_RFD_PREF_UP_SHIFT 0 ++ ++#define L1F_RXQ2 0x15A8 ++/* XOFF: USED SRAM LOWER THAN IT, THEN NOTIFY THE PEER TO SEND AGAIN */ ++#define L1F_RXQ2_RXF_XOFF_THRESH_MASK ASHFT16(0xFFFUL) ++#define L1F_RXQ2_RXF_XOFF_THRESH_SHIFT 16 ++#define L1F_RXQ2_RXF_XON_THRESH_MASK ASHFT0(0xFFFUL) ++#define L1F_RXQ2_RXF_XON_THRESH_SHIFT 0 ++ ++#define L1F_RXQ3 0x15AC ++#define L1F_RXQ3_RXD_TIMER_MASK ASHFT16(0x7FFFUL) ++#define L1F_RXQ3_RXD_TIMER_SHIFT 16 ++#define L1F_RXQ3_RXD_THRESH_MASK ASHFT0(0xFFFUL) /* 8BYTES UNIT */ ++#define L1F_RXQ3_RXD_THRESH_SHIFT 0 ++ ++#define L1F_DMA 0x15C0 ++#define L1F_DMA_SMB_NOW BIT(31) ++#define L1F_DMA_WPEND_CLR BIT(30) ++#define L1F_DMA_RPEND_CLR BIT(29) ++#define L1F_DMA_WSRAM_RDCTRL BIT(28) ++#define L1F_DMA_RCHNL_SEL_MASK ASHFT26(3UL) ++#define L1F_DMA_RCHNL_SEL_SHIFT 26 ++#define L1F_DMA_RCHNL_SEL_1 0 ++#define L1F_DMA_RCHNL_SEL_2 1 ++#define L1F_DMA_RCHNL_SEL_3 2 ++#define L1F_DMA_RCHNL_SEL_4 3 ++#define L1F_DMA_SMB_EN BIT(21) /* smb dma enable */ ++#define L1F_DMA_WDLY_CNT_MASK ASHFT16(0xFUL) ++#define L1F_DMA_WDLY_CNT_SHIFT 16 ++#define L1F_DMA_WDLY_CNT_DEF 4 ++#define L1F_DMA_RDLY_CNT_MASK ASHFT11(0x1FUL) ++#define L1F_DMA_RDLY_CNT_SHIFT 11 ++#define L1F_DMA_RDLY_CNT_DEF 15 ++#define L1F_DMA_RREQ_PRI_DATA BIT(10) /* 0:tpd, 1:data */ ++#define L1F_DMA_WREQ_BLEN_MASK ASHFT7(7UL) ++#define L1F_DMA_WREQ_BLEN_SHIFT 7 ++#define L1F_DMA_RREQ_BLEN_MASK ASHFT4(7UL) ++#define L1F_DMA_RREQ_BLEN_SHIFT 4 ++#define L1F_DMA_PENDING_AUTO_RST BIT(3) ++#define L1F_DMA_RORDER_MODE_MASK ASHFT0(7UL) ++#define L1F_DMA_RORDER_MODE_SHIFT 0 ++#define L1F_DMA_RORDER_MODE_OUT 4 ++#define L1F_DMA_RORDER_MODE_ENHANCE 2 ++#define L1F_DMA_RORDER_MODE_IN 1 ++ ++#define L1F_WOL0 0x14A0 ++#define L1F_WOL0_PT7_MATCH BIT(31) ++#define L1F_WOL0_PT6_MATCH BIT(30) ++#define L1F_WOL0_PT5_MATCH BIT(29) ++#define L1F_WOL0_PT4_MATCH BIT(28) ++#define L1F_WOL0_PT3_MATCH BIT(27) ++#define L1F_WOL0_PT2_MATCH BIT(26) ++#define L1F_WOL0_PT1_MATCH BIT(25) ++#define L1F_WOL0_PT0_MATCH BIT(24) ++#define L1F_WOL0_PT7_EN BIT(23) ++#define L1F_WOL0_PT6_EN BIT(22) ++#define L1F_WOL0_PT5_EN BIT(21) ++#define L1F_WOL0_PT4_EN BIT(20) ++#define L1F_WOL0_PT3_EN BIT(19) ++#define L1F_WOL0_PT2_EN BIT(18) ++#define L1F_WOL0_PT1_EN BIT(17) ++#define L1F_WOL0_PT0_EN BIT(16) ++#define L1F_WOL0_IPV4_SYNC_EVT BIT(14) ++#define L1F_WOL0_IPV6_SYNC_EVT BIT(13) ++#define L1F_WOL0_LINK_EVT BIT(10) ++#define L1F_WOL0_MAGIC_EVT BIT(9) ++#define L1F_WOL0_PATTERN_EVT BIT(8) ++#define L1F_WOL0_OOB_EN BIT(6) ++#define L1F_WOL0_PME_LINK BIT(5) ++#define L1F_WOL0_LINK_EN BIT(4) ++#define L1F_WOL0_PME_MAGIC_EN BIT(3) ++#define L1F_WOL0_MAGIC_EN BIT(2) ++#define L1F_WOL0_PME_PATTERN_EN BIT(1) ++#define L1F_WOL0_PATTERN_EN BIT(0) ++ ++#define L1F_WOL1 0x14A4 ++#define L1F_WOL1_PT3_LEN_MASK ASHFT24(0xFFUL) ++#define L1F_WOL1_PT3_LEN_SHIFT 24 ++#define L1F_WOL1_PT2_LEN_MASK ASHFT16(0xFFUL) ++#define L1F_WOL1_PT2_LEN_SHIFT 16 ++#define L1F_WOL1_PT1_LEN_MASK ASHFT8(0xFFUL) ++#define L1F_WOL1_PT1_LEN_SHIFT 8 ++#define L1F_WOL1_PT0_LEN_MASK ASHFT0(0xFFUL) ++#define L1F_WOL1_PT0_LEN_SHIFT 0 ++ ++#define L1F_WOL2 0x14A8 ++#define L1F_WOL2_PT7_LEN_MASK ASHFT24(0xFFUL) ++#define L1F_WOL2_PT7_LEN_SHIFT 24 ++#define L1F_WOL2_PT6_LEN_MASK ASHFT16(0xFFUL) ++#define L1F_WOL2_PT6_LEN_SHIFT 16 ++#define L1F_WOL2_PT5_LEN_MASK ASHFT8(0xFFUL) ++#define L1F_WOL2_PT5_LEN_SHIFT 8 ++#define L1F_WOL2_PT4_LEN_MASK ASHFT0(0xFFUL) ++#define L1F_WOL2_PT4_LEN_SHIFT 0 ++ ++#define L1F_RFD_PIDX 0x15E0 ++#define L1F_RFD_PIDX_MASK ASHFT0(0xFFFUL) ++#define L1F_RFD_PIDX_SHIFT 0 ++ ++#define L1F_RFD_CIDX 0x15F8 ++#define L1F_RFD_CIDX_MASK ASHFT0(0xFFFUL) ++#define L1F_RFD_CIDX_SHIFT 0 ++ ++/* MIB */ ++#define L1F_MIB_BASE 0x1700 ++#define L1F_MIB_RX_OK (L1F_MIB_BASE + 0) ++#define L1F_MIB_RX_BC (L1F_MIB_BASE + 4) ++#define L1F_MIB_RX_MC (L1F_MIB_BASE + 8) ++#define L1F_MIB_RX_PAUSE (L1F_MIB_BASE + 12) ++#define L1F_MIB_RX_CTRL (L1F_MIB_BASE + 16) ++#define L1F_MIB_RX_FCS (L1F_MIB_BASE + 20) ++#define L1F_MIB_RX_LENERR (L1F_MIB_BASE + 24) ++#define L1F_MIB_RX_BYTCNT (L1F_MIB_BASE + 28) ++#define L1F_MIB_RX_RUNT (L1F_MIB_BASE + 32) ++#define L1F_MIB_RX_FRAGMENT (L1F_MIB_BASE + 36) ++#define L1F_MIB_RX_64B (L1F_MIB_BASE + 40) ++#define L1F_MIB_RX_127B (L1F_MIB_BASE + 44) ++#define L1F_MIB_RX_255B (L1F_MIB_BASE + 48) ++#define L1F_MIB_RX_511B (L1F_MIB_BASE + 52) ++#define L1F_MIB_RX_1023B (L1F_MIB_BASE + 56) ++#define L1F_MIB_RX_1518B (L1F_MIB_BASE + 60) ++#define L1F_MIB_RX_SZMAX (L1F_MIB_BASE + 64) ++#define L1F_MIB_RX_OVSZ (L1F_MIB_BASE + 68) ++#define L1F_MIB_RXF_OV (L1F_MIB_BASE + 72) ++#define L1F_MIB_RRD_OV (L1F_MIB_BASE + 76) ++#define L1F_MIB_RX_ALIGN (L1F_MIB_BASE + 80) ++#define L1F_MIB_RX_BCCNT (L1F_MIB_BASE + 84) ++#define L1F_MIB_RX_MCCNT (L1F_MIB_BASE + 88) ++#define L1F_MIB_RX_ERRADDR (L1F_MIB_BASE + 92) ++#define L1F_MIB_TX_OK (L1F_MIB_BASE + 96) ++#define L1F_MIB_TX_BC (L1F_MIB_BASE + 100) ++#define L1F_MIB_TX_MC (L1F_MIB_BASE + 104) ++#define L1F_MIB_TX_PAUSE (L1F_MIB_BASE + 108) ++#define L1F_MIB_TX_EXCDEFER (L1F_MIB_BASE + 112) ++#define L1F_MIB_TX_CTRL (L1F_MIB_BASE + 116) ++#define L1F_MIB_TX_DEFER (L1F_MIB_BASE + 120) ++#define L1F_MIB_TX_BYTCNT (L1F_MIB_BASE + 124) ++#define L1F_MIB_TX_64B (L1F_MIB_BASE + 128) ++#define L1F_MIB_TX_127B (L1F_MIB_BASE + 132) ++#define L1F_MIB_TX_255B (L1F_MIB_BASE + 136) ++#define L1F_MIB_TX_511B (L1F_MIB_BASE + 140) ++#define L1F_MIB_TX_1023B (L1F_MIB_BASE + 144) ++#define L1F_MIB_TX_1518B (L1F_MIB_BASE + 148) ++#define L1F_MIB_TX_SZMAX (L1F_MIB_BASE + 152) ++#define L1F_MIB_TX_1COL (L1F_MIB_BASE + 156) ++#define L1F_MIB_TX_2COL (L1F_MIB_BASE + 160) ++#define L1F_MIB_TX_LATCOL (L1F_MIB_BASE + 164) ++#define L1F_MIB_TX_ABRTCOL (L1F_MIB_BASE + 168) ++#define L1F_MIB_TX_UNDRUN (L1F_MIB_BASE + 172) ++#define L1F_MIB_TX_TRDBEOP (L1F_MIB_BASE + 176) ++#define L1F_MIB_TX_LENERR (L1F_MIB_BASE + 180) ++#define L1F_MIB_TX_TRUNC (L1F_MIB_BASE + 184) ++#define L1F_MIB_TX_BCCNT (L1F_MIB_BASE + 188) ++#define L1F_MIB_TX_MCCNT (L1F_MIB_BASE + 192) ++#define L1F_MIB_UPDATE (L1F_MIB_BASE + 196) ++ ++/******************************************************************************/ ++ ++#define L1F_ISR 0x1600 ++#define L1F_ISR_DIS BIT(31) ++#define L1F_ISR_RX_Q7 BIT(30) ++#define L1F_ISR_RX_Q6 BIT(29) ++#define L1F_ISR_RX_Q5 BIT(28) ++#define L1F_ISR_RX_Q4 BIT(27) ++#define L1F_ISR_PCIE_LNKDOWN BIT(26) ++#define L1F_ISR_PCIE_CERR BIT(25) ++#define L1F_ISR_PCIE_NFERR BIT(24) ++#define L1F_ISR_PCIE_FERR BIT(23) ++#define L1F_ISR_PCIE_UR BIT(22) ++#define L1F_ISR_MAC_TX BIT(21) ++#define L1F_ISR_MAC_RX BIT(20) ++#define L1F_ISR_RX_Q3 BIT(19) ++#define L1F_ISR_RX_Q2 BIT(18) ++#define L1F_ISR_RX_Q1 BIT(17) ++#define L1F_ISR_RX_Q0 BIT(16) ++#define L1F_ISR_TX_Q0 BIT(15) ++#define L1F_ISR_TXQ_TO BIT(14) ++#define L1F_ISR_PHY_LPW BIT(13) ++#define L1F_ISR_PHY BIT(12) ++#define L1F_ISR_TX_CREDIT BIT(11) ++#define L1F_ISR_DMAW BIT(10) ++#define L1F_ISR_DMAR BIT(9) ++#define L1F_ISR_TXF_UR BIT(8) ++#define L1F_ISR_TX_Q3 BIT(7) ++#define L1F_ISR_TX_Q2 BIT(6) ++#define L1F_ISR_TX_Q1 BIT(5) ++#define L1F_ISR_RFD_UR BIT(4) ++#define L1F_ISR_RXF_OV BIT(3) ++#define L1F_ISR_MANU BIT(2) ++#define L1F_ISR_TIMER BIT(1) ++#define L1F_ISR_SMB BIT(0) ++ ++#define L1F_IMR 0x1604 ++ ++#define L1F_INT_RETRIG 0x1608 /* re-send deassrt/assert ++ * if sw no reflect */ ++#define L1F_INT_RETRIG_TIMER_MASK ASHFT0(0xFFFFUL) ++#define L1F_INT_RETRIG_TIMER_SHIFT 0 ++#define L1F_INT_RETRIG_TO 20000 /* 40ms */ ++ ++#define L1F_INT_DEASST_TIMER 0x1614 /* re-send deassert ++ * if sw no reflect */ ++ ++#define L1F_PATTERN_MASK 0x1620 /* 128bytes, sleep state */ ++#define L1F_PATTERN_MASK_LEN 128 ++ ++ ++#define L1F_FLT1_SRC_IP0 0x1A00 ++#define L1F_FLT1_SRC_IP1 0x1A04 ++#define L1F_FLT1_SRC_IP2 0x1A08 ++#define L1F_FLT1_SRC_IP3 0x1A0C ++#define L1F_FLT1_DST_IP0 0x1A10 ++#define L1F_FLT1_DST_IP1 0x1A14 ++#define L1F_FLT1_DST_IP2 0x1A18 ++#define L1F_FLT1_DST_IP3 0x1A1C ++#define L1F_FLT1_PORT 0x1A20 ++#define L1F_FLT1_PORT_DST_MASK ASHFT16(0xFFFFUL) ++#define L1F_FLT1_PORT_DST_SHIFT 16 ++#define L1F_FLT1_PORT_SRC_MASK ASHFT0(0xFFFFUL) ++#define L1F_FLT1_PORT_SRC_SHIFT 0 ++ ++#define L1F_FLT2_SRC_IP0 0x1A24 ++#define L1F_FLT2_SRC_IP1 0x1A28 ++#define L1F_FLT2_SRC_IP2 0x1A2C ++#define L1F_FLT2_SRC_IP3 0x1A30 ++#define L1F_FLT2_DST_IP0 0x1A34 ++#define L1F_FLT2_DST_IP1 0x1A38 ++#define L1F_FLT2_DST_IP2 0x1A40 ++#define L1F_FLT2_DST_IP3 0x1A44 ++#define L1F_FLT2_PORT 0x1A48 ++#define L1F_FLT2_PORT_DST_MASK ASHFT16(0xFFFFUL) ++#define L1F_FLT2_PORT_DST_SHIFT 16 ++#define L1F_FLT2_PORT_SRC_MASK ASHFT0(0xFFFFUL) ++#define L1F_FLT2_PORT_SRC_SHIFT 0 ++ ++#define L1F_FLT3_SRC_IP0 0x1A4C ++#define L1F_FLT3_SRC_IP1 0x1A50 ++#define L1F_FLT3_SRC_IP2 0x1A54 ++#define L1F_FLT3_SRC_IP3 0x1A58 ++#define L1F_FLT3_DST_IP0 0x1A5C ++#define L1F_FLT3_DST_IP1 0x1A60 ++#define L1F_FLT3_DST_IP2 0x1A64 ++#define L1F_FLT3_DST_IP3 0x1A68 ++#define L1F_FLT3_PORT 0x1A6C ++#define L1F_FLT3_PORT_DST_MASK ASHFT16(0xFFFFUL) ++#define L1F_FLT3_PORT_DST_SHIFT 16 ++#define L1F_FLT3_PORT_SRC_MASK ASHFT0(0xFFFFUL) ++#define L1F_FLT3_PORT_SRC_SHIFT 0 ++ ++#define L1F_FLT4_SRC_IP0 0x1A70 ++#define L1F_FLT4_SRC_IP1 0x1A74 ++#define L1F_FLT4_SRC_IP2 0x1A78 ++#define L1F_FLT4_SRC_IP3 0x1A7C ++#define L1F_FLT4_DST_IP0 0x1A80 ++#define L1F_FLT4_DST_IP1 0x1A84 ++#define L1F_FLT4_DST_IP2 0x1A88 ++#define L1F_FLT4_DST_IP3 0x1A8C ++#define L1F_FLT4_PORT 0x1A90 ++#define L1F_FLT4_PORT_DST_MASK ASHFT16(0xFFFFUL) ++#define L1F_FLT4_PORT_DST_SHIFT 16 ++#define L1F_FLT4_PORT_SRC_MASK ASHFT0(0xFFFFUL) ++#define L1F_FLT4_PORT_SRC_SHIFT 0 ++ ++#define L1F_FLT5_SRC_IP0 0x1A94 ++#define L1F_FLT5_SRC_IP1 0x1A98 ++#define L1F_FLT5_SRC_IP2 0x1A9C ++#define L1F_FLT5_SRC_IP3 0x1AA0 ++#define L1F_FLT5_DST_IP0 0x1AA4 ++#define L1F_FLT5_DST_IP1 0x1AA8 ++#define L1F_FLT5_DST_IP2 0x1AAC ++#define L1F_FLT5_DST_IP3 0x1AB0 ++#define L1F_FLT5_PORT 0x1AB4 ++#define L1F_FLT5_PORT_DST_MASK ASHFT16(0xFFFFUL) ++#define L1F_FLT5_PORT_DST_SHIFT 16 ++#define L1F_FLT5_PORT_SRC_MASK ASHFT0(0xFFFFUL) ++#define L1F_FLT5_PORT_SRC_SHIFT 0 ++ ++#define L1F_FLT6_SRC_IP0 0x1AB8 ++#define L1F_FLT6_SRC_IP1 0x1ABC ++#define L1F_FLT6_SRC_IP2 0x1AC0 ++#define L1F_FLT6_SRC_IP3 0x1AC8 ++#define L1F_FLT6_DST_IP0 0x1620 /* only S0 state */ ++#define L1F_FLT6_DST_IP1 0x1624 ++#define L1F_FLT6_DST_IP2 0x1628 ++#define L1F_FLT6_DST_IP3 0x162C ++#define L1F_FLT6_PORT 0x1630 ++#define L1F_FLT6_PORT_DST_MASK ASHFT16(0xFFFFUL) ++#define L1F_FLT6_PORT_DST_SHIFT 16 ++#define L1F_FLT6_PORT_SRC_MASK ASHFT0(0xFFFFUL) ++#define L1F_FLT6_PORT_SRC_SHIFT 0 ++ ++#define L1F_FLTCTRL 0x1634 ++#define L1F_FLTCTRL_PSTHR_TIMER_MASK ASHFT24(0xFFUL) ++#define L1F_FLTCTRL_PSTHR_TIMER_SHIFT 24 ++#define L1F_FLTCTRL_CHK_DSTPRT6 BIT(23) ++#define L1F_FLTCTRL_CHK_SRCPRT6 BIT(22) ++#define L1F_FLTCTRL_CHK_DSTIP6 BIT(21) ++#define L1F_FLTCTRL_CHK_SRCIP6 BIT(20) ++#define L1F_FLTCTRL_CHK_DSTPRT5 BIT(19) ++#define L1F_FLTCTRL_CHK_SRCPRT5 BIT(18) ++#define L1F_FLTCTRL_CHK_DSTIP5 BIT(17) ++#define L1F_FLTCTRL_CHK_SRCIP5 BIT(16) ++#define L1F_FLTCTRL_CHK_DSTPRT4 BIT(15) ++#define L1F_FLTCTRL_CHK_SRCPRT4 BIT(14) ++#define L1F_FLTCTRL_CHK_DSTIP4 BIT(13) ++#define L1F_FLTCTRL_CHK_SRCIP4 BIT(12) ++#define L1F_FLTCTRL_CHK_DSTPRT3 BIT(11) ++#define L1F_FLTCTRL_CHK_SRCPRT3 BIT(10) ++#define L1F_FLTCTRL_CHK_DSTIP3 BIT(9) ++#define L1F_FLTCTRL_CHK_SRCIP3 BIT(8) ++#define L1F_FLTCTRL_CHK_DSTPRT2 BIT(7) ++#define L1F_FLTCTRL_CHK_SRCPRT2 BIT(6) ++#define L1F_FLTCTRL_CHK_DSTIP2 BIT(5) ++#define L1F_FLTCTRL_CHK_SRCIP2 BIT(4) ++#define L1F_FLTCTRL_CHK_DSTPRT1 BIT(3) ++#define L1F_FLTCTRL_CHK_SRCPRT1 BIT(2) ++#define L1F_FLTCTRL_CHK_DSTIP1 BIT(1) ++#define L1F_FLTCTRL_CHK_SRCIP1 BIT(0) ++ ++#define L1F_DROP_ALG1 0x1638 ++#define L1F_DROP_ALG1_BWCHGVAL_MASK ASHFT12(0xFFFFFUL) ++#define L1F_DROP_ALG1_BWCHGVAL_SHIFT 12 ++#define L1F_DROP_ALG1_BWCHGSCL_6 BIT(11) /* 0:3.125%, 1:6.25% */ ++#define L1F_DROP_ALG1_ASUR_LWQ_EN BIT(10) ++#define L1F_DROP_ALG1_BWCHGVAL_EN BIT(9) ++#define L1F_DROP_ALG1_BWCHGSCL_EN BIT(8) ++#define L1F_DROP_ALG1_PSTHR_AUTO BIT(7) /* 0:manual, 1:auto */ ++#define L1F_DROP_ALG1_MIN_PSTHR_MASK ASHFT5(3UL) ++#define L1F_DROP_ALG1_MIN_PSTHR_SHIFT 5 ++#define L1F_DROP_ALG1_MIN_PSTHR_1_16 0 ++#define L1F_DROP_ALG1_MIN_PSTHR_1_8 1 ++#define L1F_DROP_ALG1_MIN_PSTHR_1_4 2 ++#define L1F_DROP_ALG1_MIN_PSTHR_1_2 3 ++#define L1F_DROP_ALG1_PSCL_MASK ASHFT3(3UL) ++#define L1F_DROP_ALG1_PSCL_SHIFT 3 ++#define L1F_DROP_ALG1_PSCL_1_4 0 ++#define L1F_DROP_ALG1_PSCL_1_8 1 ++#define L1F_DROP_ALG1_PSCL_1_16 2 ++#define L1F_DROP_ALG1_PSCL_1_32 3 ++#define L1F_DROP_ALG1_TIMESLOT_MASK ASHFT0(7UL) ++#define L1F_DROP_ALG1_TIMESLOT_SHIFT 0 ++#define L1F_DROP_ALG1_TIMESLOT_4MS 0 ++#define L1F_DROP_ALG1_TIMESLOT_8MS 1 ++#define L1F_DROP_ALG1_TIMESLOT_16MS 2 ++#define L1F_DROP_ALG1_TIMESLOT_32MS 3 ++#define L1F_DROP_ALG1_TIMESLOT_64MS 4 ++#define L1F_DROP_ALG1_TIMESLOT_128MS 5 ++#define L1F_DROP_ALG1_TIMESLOT_256MS 6 ++#define L1F_DROP_ALG1_TIMESLOT_512MS 7 ++ ++#define L1F_DROP_ALG2 0x163C ++#define L1F_DROP_ALG2_SMPLTIME_MASK ASHFT24(0xFUL) ++#define L1F_DROP_ALG2_SMPLTIME_SHIFT 24 ++#define L1F_DROP_ALG2_LWQBW_MASK ASHFT0(0xFFFFFFUL) ++#define L1F_DROP_ALG2_LWQBW_SHIFT 0 ++ ++#define L1F_SMB_TIMER 0x15C4 ++ ++#define L1F_TINT_TPD_THRSHLD 0x15C8 ++ ++#define L1F_TINT_TIMER 0x15CC ++ ++#define L1F_CLK_GATE 0x1814 ++#define L1F_CLK_GATE_125M_SW_DIS_CR BIT(8) /* B0 */ ++#define L1F_CLK_GATE_125M_SW_AZ BIT(7) /* B0 */ ++#define L1F_CLK_GATE_125M_SW_IDLE BIT(6) /* B0 */ ++#define L1F_CLK_GATE_RXMAC BIT(5) ++#define L1F_CLK_GATE_TXMAC BIT(4) ++#define L1F_CLK_GATE_RXQ BIT(3) ++#define L1F_CLK_GATE_TXQ BIT(2) ++#define L1F_CLK_GATE_DMAR BIT(1) ++#define L1F_CLK_GATE_DMAW BIT(0) ++#define L1F_CLK_GATE_ALL_A0 (\ ++ L1F_CLK_GATE_RXMAC |\ ++ L1F_CLK_GATE_TXMAC |\ ++ L1F_CLK_GATE_RXQ |\ ++ L1F_CLK_GATE_TXQ |\ ++ L1F_CLK_GATE_DMAR |\ ++ L1F_CLK_GATE_DMAW) ++#define L1F_CLK_GATE_ALL_B0 (\ ++ L1F_CLK_GATE_ALL_A0 |\ ++ L1F_CLK_GATE_125M_SW_AZ |\ ++ L1F_CLK_GATE_125M_SW_IDLE) ++ ++ ++ ++ ++ ++#define L1F_BTROM_CFG 0x1800 /* pwon rst */ ++ ++#define L1F_DRV 0x1804 ++/* bit definition is in lx_hwcomm.h */ ++ ++#define L1F_DRV_ERR1 0x1808 /* perst */ ++#define L1F_DRV_ERR1_GEN BIT(31) /* geneneral err */ ++#define L1F_DRV_ERR1_NOR BIT(30) /* rrd.nor */ ++#define L1F_DRV_ERR1_TRUNC BIT(29) ++#define L1F_DRV_ERR1_RES BIT(28) ++#define L1F_DRV_ERR1_INTFATAL BIT(27) ++#define L1F_DRV_ERR1_TXQPEND BIT(26) ++#define L1F_DRV_ERR1_DMAW BIT(25) ++#define L1F_DRV_ERR1_DMAR BIT(24) ++#define L1F_DRV_ERR1_PCIELNKDWN BIT(23) ++#define L1F_DRV_ERR1_PKTSIZE BIT(22) ++#define L1F_DRV_ERR1_FIFOFUL BIT(21) ++#define L1F_DRV_ERR1_RFDUR BIT(20) ++#define L1F_DRV_ERR1_RRDSI BIT(19) ++#define L1F_DRV_ERR1_UPDATE BIT(18) ++ ++#define L1F_DRV_ERR2 0x180C ++ ++#define L1F_DBG_ADDR 0x1900 /* DWORD reg */ ++#define L1F_DBG_DATA 0x1904 /* DWORD reg */ ++ ++#define L1F_SYNC_IPV4_SA 0x1A00 ++#define L1F_SYNC_IPV4_DA 0x1A04 ++ ++#define L1F_SYNC_V4PORT 0x1A08 ++#define L1F_SYNC_V4PORT_DST_MASK ASHFT16(0xFFFFUL) ++#define L1F_SYNC_V4PORT_DST_SHIFT 16 ++#define L1F_SYNC_V4PORT_SRC_MASK ASHFT0(0xFFFFUL) ++#define L1F_SYNC_V4PORT_SRC_SHIFT 0 ++ ++#define L1F_SYNC_IPV6_SA0 0x1A0C ++#define L1F_SYNC_IPV6_SA1 0x1A10 ++#define L1F_SYNC_IPV6_SA2 0x1A14 ++#define L1F_SYNC_IPV6_SA3 0x1A18 ++#define L1F_SYNC_IPV6_DA0 0x1A1C ++#define L1F_SYNC_IPV6_DA1 0x1A20 ++#define L1F_SYNC_IPV6_DA2 0x1A24 ++#define L1F_SYNC_IPV6_DA3 0x1A28 ++ ++#define L1F_SYNC_V6PORT 0x1A2C ++#define L1F_SYNC_V6PORT_DST_MASK ASHFT16(0xFFFFUL) ++#define L1F_SYNC_V6PORT_DST_SHIFT 16 ++#define L1F_SYNC_V6PORT_SRC_MASK ASHFT0(0xFFFFUL) ++#define L1F_SYNC_V6PORT_SRC_SHIFT 0 ++ ++#define L1F_ARP_REMOTE_IPV4 0x1A30 ++#define L1F_ARP_HOST_IPV4 0x1A34 ++#define L1F_ARP_MAC0 0x1A38 ++#define L1F_ARP_MAC1 0x1A3C ++ ++#define L1F_1ST_REMOTE_IPV6_0 0x1A40 ++#define L1F_1ST_REMOTE_IPV6_1 0x1A44 ++#define L1F_1ST_REMOTE_IPV6_2 0x1A48 ++#define L1F_1ST_REMOTE_IPV6_3 0x1A4C ++ ++#define L1F_1ST_SN_IPV6_0 0x1A50 ++#define L1F_1ST_SN_IPV6_1 0x1A54 ++#define L1F_1ST_SN_IPV6_2 0x1A58 ++#define L1F_1ST_SN_IPV6_3 0x1A5C ++ ++#define L1F_1ST_TAR_IPV6_1_0 0x1A60 ++#define L1F_1ST_TAR_IPV6_1_1 0x1A64 ++#define L1F_1ST_TAR_IPV6_1_2 0x1A68 ++#define L1F_1ST_TAR_IPV6_1_3 0x1A6C ++#define L1F_1ST_TAR_IPV6_2_0 0x1A70 ++#define L1F_1ST_TAR_IPV6_2_1 0x1A74 ++#define L1F_1ST_TAR_IPV6_2_2 0x1A78 ++#define L1F_1ST_TAR_IPV6_2_3 0x1A7C ++ ++#define L1F_2ND_REMOTE_IPV6_0 0x1A80 ++#define L1F_2ND_REMOTE_IPV6_1 0x1A84 ++#define L1F_2ND_REMOTE_IPV6_2 0x1A88 ++#define L1F_2ND_REMOTE_IPV6_3 0x1A8C ++ ++#define L1F_2ND_SN_IPV6_0 0x1A90 ++#define L1F_2ND_SN_IPV6_1 0x1A94 ++#define L1F_2ND_SN_IPV6_2 0x1A98 ++#define L1F_2ND_SN_IPV6_3 0x1A9C ++ ++#define L1F_2ND_TAR_IPV6_1_0 0x1AA0 ++#define L1F_2ND_TAR_IPV6_1_1 0x1AA4 ++#define L1F_2ND_TAR_IPV6_1_2 0x1AA8 ++#define L1F_2ND_TAR_IPV6_1_3 0x1AAC ++#define L1F_2ND_TAR_IPV6_2_0 0x1AB0 ++#define L1F_2ND_TAR_IPV6_2_1 0x1AB4 ++#define L1F_2ND_TAR_IPV6_2_2 0x1AB8 ++#define L1F_2ND_TAR_IPV6_2_3 0x1ABC ++ ++#define L1F_1ST_NS_MAC0 0x1AC0 ++#define L1F_1ST_NS_MAC1 0x1AC4 ++ ++#define L1F_2ND_NS_MAC0 0x1AC8 ++#define L1F_2ND_NS_MAC1 0x1ACC ++ ++#define L1F_PMOFLD 0x144C ++#define L1F_PMOFLD_ECMA_IGNR_FRG_SSSR BIT(11) /* B0 */ ++#define L1F_PMOFLD_ARP_CNFLCT_WAKEUP BIT(10) /* B0 */ ++#define L1F_PMOFLD_MULTI_SOLD BIT(9) ++#define L1F_PMOFLD_ICMP_XSUM BIT(8) ++#define L1F_PMOFLD_GARP_REPLY BIT(7) ++#define L1F_PMOFLD_SYNCV6_ANY BIT(6) ++#define L1F_PMOFLD_SYNCV4_ANY BIT(5) ++#define L1F_PMOFLD_BY_HW BIT(4) ++#define L1F_PMOFLD_NS_EN BIT(3) ++#define L1F_PMOFLD_ARP_EN BIT(2) ++#define L1F_PMOFLD_SYNCV6_EN BIT(1) ++#define L1F_PMOFLD_SYNCV4_EN BIT(0) ++ ++#define L1F_RSS_KEY0 0x14B0 ++#define L1F_RSS_KEY1 0x14B4 ++#define L1F_RSS_KEY2 0x14B8 ++#define L1F_RSS_KEY3 0x14BC ++#define L1F_RSS_KEY4 0x14C0 ++#define L1F_RSS_KEY5 0x14C4 ++#define L1F_RSS_KEY6 0x14C8 ++#define L1F_RSS_KEY7 0x14CC ++#define L1F_RSS_KEY8 0x14D0 ++#define L1F_RSS_KEY9 0x14D4 ++ ++#define L1F_RSS_IDT_TBL0 0x1B00 ++#define L1F_RSS_IDT_TBL1 0x1B04 ++#define L1F_RSS_IDT_TBL2 0x1B08 ++#define L1F_RSS_IDT_TBL3 0x1B0C ++#define L1F_RSS_IDT_TBL4 0x1B10 ++#define L1F_RSS_IDT_TBL5 0x1B14 ++#define L1F_RSS_IDT_TBL6 0x1B18 ++#define L1F_RSS_IDT_TBL7 0x1B1C ++#define L1F_RSS_IDT_TBL8 0x1B20 ++#define L1F_RSS_IDT_TBL9 0x1B24 ++#define L1F_RSS_IDT_TBL10 0x1B28 ++#define L1F_RSS_IDT_TBL11 0x1B2C ++#define L1F_RSS_IDT_TBL12 0x1B30 ++#define L1F_RSS_IDT_TBL13 0x1B34 ++#define L1F_RSS_IDT_TBL14 0x1B38 ++#define L1F_RSS_IDT_TBL15 0x1B3C ++#define L1F_RSS_IDT_TBL16 0x1B40 ++#define L1F_RSS_IDT_TBL17 0x1B44 ++#define L1F_RSS_IDT_TBL18 0x1B48 ++#define L1F_RSS_IDT_TBL19 0x1B4C ++#define L1F_RSS_IDT_TBL20 0x1B50 ++#define L1F_RSS_IDT_TBL21 0x1B54 ++#define L1F_RSS_IDT_TBL22 0x1B58 ++#define L1F_RSS_IDT_TBL23 0x1B5C ++#define L1F_RSS_IDT_TBL24 0x1B60 ++#define L1F_RSS_IDT_TBL25 0x1B64 ++#define L1F_RSS_IDT_TBL26 0x1B68 ++#define L1F_RSS_IDT_TBL27 0x1B6C ++#define L1F_RSS_IDT_TBL28 0x1B70 ++#define L1F_RSS_IDT_TBL29 0x1B74 ++#define L1F_RSS_IDT_TBL30 0x1B78 ++#define L1F_RSS_IDT_TBL31 0x1B7C ++ ++#define L1F_RSS_HASH_VAL 0x15B0 ++#define L1F_RSS_HASH_FLAG 0x15B4 ++ ++#define L1F_RSS_BASE_CPU_NUM 0x15B8 ++ ++#define L1F_MSI_MAP_TBL1 0x15D0 ++#define L1F_MSI_MAP_TBL1_ALERT_MASK ASHFT28(0xFUL) ++#define L1F_MSI_MAP_TBL1_ALERT_SHIFT 28 ++#define L1F_MSI_MAP_TBL1_TIMER_MASK ASHFT24(0xFUL) ++#define L1F_MSI_MAP_TBL1_TIMER_SHIFT 24 ++#define L1F_MSI_MAP_TBL1_TXQ1_MASK ASHFT20(0xFUL) ++#define L1F_MSI_MAP_TBL1_TXQ1_SHIFT 20 ++#define L1F_MSI_MAP_TBL1_TXQ0_MASK ASHFT16(0xFUL) ++#define L1F_MSI_MAP_TBL1_TXQ0_SHIFT 16 ++#define L1F_MSI_MAP_TBL1_RXQ3_MASK ASHFT12(0xFUL) ++#define L1F_MSI_MAP_TBL1_RXQ3_SHIFT 12 ++#define L1F_MSI_MAP_TBL1_RXQ2_MASK ASHFT8(0xFUL) ++#define L1F_MSI_MAP_TBL1_RXQ2_SHIFT 8 ++#define L1F_MSI_MAP_TBL1_RXQ1_MASK ASHFT4(0xFUL) ++#define L1F_MSI_MAP_TBL1_RXQ1_SHIFT 4 ++#define L1F_MSI_MAP_TBL1_RXQ0_MASK ASHFT0(0xFUL) ++#define L1F_MSI_MAP_TBL1_RXQ0_SHIFT 0 ++ ++#define L1F_MSI_MAP_TBL2 0x15D8 ++#define L1F_MSI_MAP_TBL2_PHY_MASK ASHFT28(0xFUL) ++#define L1F_MSI_MAP_TBL2_PHY_SHIFT 28 ++#define L1F_MSI_MAP_TBL2_SMB_MASK ASHFT24(0xFUL) ++#define L1F_MSI_MAP_TBL2_SMB_SHIFT 24 ++#define L1F_MSI_MAP_TBL2_TXQ3_MASK ASHFT20(0xFUL) ++#define L1F_MSI_MAP_TBL2_TXQ3_SHIFT 20 ++#define L1F_MSI_MAP_TBL2_TXQ2_MASK ASHFT16(0xFUL) ++#define L1F_MSI_MAP_TBL2_TXQ2_SHIFT 16 ++#define L1F_MSI_MAP_TBL2_RXQ7_MASK ASHFT12(0xFUL) ++#define L1F_MSI_MAP_TBL2_RXQ7_SHIFT 12 ++#define L1F_MSI_MAP_TBL2_RXQ6_MASK ASHFT8(0xFUL) ++#define L1F_MSI_MAP_TBL2_RXQ6_SHIFT 8 ++#define L1F_MSI_MAP_TBL2_RXQ5_MASK ASHFT4(0xFUL) ++#define L1F_MSI_MAP_TBL2_RXQ5_SHIFT 4 ++#define L1F_MSI_MAP_TBL2_RXQ4_MASK ASHFT0(0xFUL) ++#define L1F_MSI_MAP_TBL2_RXQ4_SHIFT 0 ++ ++#define L1F_MSI_ID_MAP 0x15D4 ++#define L1F_MSI_ID_MAP_RXQ7 BIT(30) ++#define L1F_MSI_ID_MAP_RXQ6 BIT(29) ++#define L1F_MSI_ID_MAP_RXQ5 BIT(28) ++#define L1F_MSI_ID_MAP_RXQ4 BIT(27) ++#define L1F_MSI_ID_MAP_PCIELNKDW BIT(26) /* 0:common,1:timer */ ++#define L1F_MSI_ID_MAP_PCIECERR BIT(25) ++#define L1F_MSI_ID_MAP_PCIENFERR BIT(24) ++#define L1F_MSI_ID_MAP_PCIEFERR BIT(23) ++#define L1F_MSI_ID_MAP_PCIEUR BIT(22) ++#define L1F_MSI_ID_MAP_MACTX BIT(21) ++#define L1F_MSI_ID_MAP_MACRX BIT(20) ++#define L1F_MSI_ID_MAP_RXQ3 BIT(19) ++#define L1F_MSI_ID_MAP_RXQ2 BIT(18) ++#define L1F_MSI_ID_MAP_RXQ1 BIT(17) ++#define L1F_MSI_ID_MAP_RXQ0 BIT(16) ++#define L1F_MSI_ID_MAP_TXQ0 BIT(15) ++#define L1F_MSI_ID_MAP_TXQTO BIT(14) ++#define L1F_MSI_ID_MAP_LPW BIT(13) ++#define L1F_MSI_ID_MAP_PHY BIT(12) ++#define L1F_MSI_ID_MAP_TXCREDIT BIT(11) ++#define L1F_MSI_ID_MAP_DMAW BIT(10) ++#define L1F_MSI_ID_MAP_DMAR BIT(9) ++#define L1F_MSI_ID_MAP_TXFUR BIT(8) ++#define L1F_MSI_ID_MAP_TXQ3 BIT(7) ++#define L1F_MSI_ID_MAP_TXQ2 BIT(6) ++#define L1F_MSI_ID_MAP_TXQ1 BIT(5) ++#define L1F_MSI_ID_MAP_RFDUR BIT(4) ++#define L1F_MSI_ID_MAP_RXFOV BIT(3) ++#define L1F_MSI_ID_MAP_MANU BIT(2) ++#define L1F_MSI_ID_MAP_TIMER BIT(1) ++#define L1F_MSI_ID_MAP_SMB BIT(0) ++ ++#define L1F_MSI_RETRANS_TIMER 0x1920 ++#define L1F_MSI_MASK_SEL_LINE BIT(16) /* 1:line,0:standard*/ ++#define L1F_MSI_RETRANS_TM_MASK ASHFT0(0xFFFFUL) ++#define L1F_MSI_RETRANS_TM_SHIFT 0 ++ ++#define L1F_CR_DMA_CTRL 0x1930 ++#define L1F_CR_DMA_CTRL_PRI BIT(22) ++#define L1F_CR_DMA_CTRL_RRDRXD_JOINT BIT(21) ++#define L1F_CR_DMA_CTRL_BWCREDIT_MASK ASHFT19(0x3UL) ++#define L1F_CR_DMA_CTRL_BWCREDIT_SHIFT 19 ++#define L1F_CR_DMA_CTRL_BWCREDIT_2KB 0 ++#define L1F_CR_DMA_CTRL_BWCREDIT_1KB 1 ++#define L1F_CR_DMA_CTRL_BWCREDIT_4KB 2 ++#define L1F_CR_DMA_CTRL_BWCREDIT_8KB 3 ++#define L1F_CR_DMA_CTRL_BW_EN BIT(18) ++#define L1F_CR_DMA_CTRL_BW_RATIO_MASK ASHFT16(0x3UL) ++#define L1F_CR_DMA_CTRL_BW_RATIO_1_2 0 ++#define L1F_CR_DMA_CTRL_BW_RATIO_1_4 1 ++#define L1F_CR_DMA_CTRL_BW_RATIO_1_8 2 ++#define L1F_CR_DMA_CTRL_BW_RATIO_2_1 3 ++#define L1F_CR_DMA_CTRL_SOFT_RST BIT(11) ++#define L1F_CR_DMA_CTRL_TXEARLY_EN BIT(10) ++#define L1F_CR_DMA_CTRL_RXEARLY_EN BIT(9) ++#define L1F_CR_DMA_CTRL_WEARLY_EN BIT(8) ++#define L1F_CR_DMA_CTRL_RXTH_MASK ASHFT4(0xFUL) ++#define L1F_CR_DMA_CTRL_WTH_MASK ASHFT0(0xFUL) ++ ++ ++#define L1F_EFUSE_BIST 0x1934 ++#define L1F_EFUSE_BIST_COL_MASK ASHFT24(0x3FUL) ++#define L1F_EFUSE_BIST_COL_SHIFT 24 ++#define L1F_EFUSE_BIST_ROW_MASK ASHFT12(0x7FUL) ++#define L1F_EFUSE_BIST_ROW_SHIFT 12 ++#define L1F_EFUSE_BIST_STEP_MASK ASHFT8(0xFUL) ++#define L1F_EFUSE_BIST_STEP_SHIFT 8 ++#define L1F_EFUSE_BIST_PAT_MASK ASHFT4(0x7UL) ++#define L1F_EFUSE_BIST_PAT_SHIFT 4 ++#define L1F_EFUSE_BIST_CRITICAL BIT(3) ++#define L1F_EFUSE_BIST_FIXED BIT(2) ++#define L1F_EFUSE_BIST_FAIL BIT(1) ++#define L1F_EFUSE_BIST_NOW BIT(0) ++ ++/* CR DMA ctrl */ ++ ++/* TX QoS */ ++#define L1F_WRR 0x1938 ++#define L1F_WRR_PRI_MASK ASHFT29(3UL) ++#define L1F_WRR_PRI_SHIFT 29 ++#define L1F_WRR_PRI_RESTRICT_ALL 0 ++#define L1F_WRR_PRI_RESTRICT_HI 1 ++#define L1F_WRR_PRI_RESTRICT_HI2 2 ++#define L1F_WRR_PRI_RESTRICT_NONE 3 ++#define L1F_WRR_PRI3_MASK ASHFT24(0x1FUL) ++#define L1F_WRR_PRI3_SHIFT 24 ++#define L1F_WRR_PRI2_MASK ASHFT16(0x1FUL) ++#define L1F_WRR_PRI2_SHIFT 16 ++#define L1F_WRR_PRI1_MASK ASHFT8(0x1FUL) ++#define L1F_WRR_PRI1_SHIFT 8 ++#define L1F_WRR_PRI0_MASK ASHFT0(0x1FUL) ++#define L1F_WRR_PRI0_SHIFT 0 ++ ++#define L1F_HQTPD 0x193C ++#define L1F_HQTPD_BURST_EN BIT(31) ++#define L1F_HQTPD_Q3_NUMPREF_MASK ASHFT8(0xFUL) ++#define L1F_HQTPD_Q3_NUMPREF_SHIFT 8 ++#define L1F_HQTPD_Q2_NUMPREF_MASK ASHFT4(0xFUL) ++#define L1F_HQTPD_Q2_NUMPREF_SHIFT 4 ++#define L1F_HQTPD_Q1_NUMPREF_MASK ASHFT0(0xFUL) ++#define L1F_HQTPD_Q1_NUMPREF_SHIFT 0 ++ ++#define L1F_CPUMAP1 0x19A0 ++#define L1F_CPUMAP1_VCT7_MASK ASHFT28(0xFUL) ++#define L1F_CPUMAP1_VCT7_SHIFT 28 ++#define L1F_CPUMAP1_VCT6_MASK ASHFT24(0xFUL) ++#define L1F_CPUMAP1_VCT6_SHIFT 24 ++#define L1F_CPUMAP1_VCT5_MASK ASHFT20(0xFUL) ++#define L1F_CPUMAP1_VCT5_SHIFT 20 ++#define L1F_CPUMAP1_VCT4_MASK ASHFT16(0xFUL) ++#define L1F_CPUMAP1_VCT4_SHIFT 16 ++#define L1F_CPUMAP1_VCT3_MASK ASHFT12(0xFUL) ++#define L1F_CPUMAP1_VCT3_SHIFT 12 ++#define L1F_CPUMAP1_VCT2_MASK ASHFT8(0xFUL) ++#define L1F_CPUMAP1_VCT2_SHIFT 8 ++#define L1F_CPUMAP1_VCT1_MASK ASHFT4(0xFUL) ++#define L1F_CPUMAP1_VCT1_SHIFT 4 ++#define L1F_CPUMAP1_VCT0_MASK ASHFT0(0xFUL) ++#define L1F_CPUMAP1_VCT0_SHIFT 0 ++ ++#define L1F_CPUMAP2 0x19A4 ++#define L1F_CPUMAP2_VCT15_MASK ASHFT28(0xFUL) ++#define L1F_CPUMAP2_VCT15_SHIFT 28 ++#define L1F_CPUMAP2_VCT14_MASK ASHFT24(0xFUL) ++#define L1F_CPUMAP2_VCT14_SHIFT 24 ++#define L1F_CPUMAP2_VCT13_MASK ASHFT20(0xFUL) ++#define L1F_CPUMAP2_VCT13_SHIFT 20 ++#define L1F_CPUMAP2_VCT12_MASK ASHFT16(0xFUL) ++#define L1F_CPUMAP2_VCT12_SHIFT 16 ++#define L1F_CPUMAP2_VCT11_MASK ASHFT12(0xFUL) ++#define L1F_CPUMAP2_VCT11_SHIFT 12 ++#define L1F_CPUMAP2_VCT10_MASK ASHFT8(0xFUL) ++#define L1F_CPUMAP2_VCT10_SHIFT 8 ++#define L1F_CPUMAP2_VCT9_MASK ASHFT4(0xFUL) ++#define L1F_CPUMAP2_VCT9_SHIFT 4 ++#define L1F_CPUMAP2_VCT8_MASK ASHFT0(0xFUL) ++#define L1F_CPUMAP2_VCT8_SHIFT 0 ++ ++#define L1F_MISC 0x19C0 ++#define L1F_MISC_MODU BIT(31) /* 0:vector,1:cpu */ ++#define L1F_MISC_OVERCUR BIT(29) ++#define L1F_MISC_PSWR_EN BIT(28) ++#define L1F_MISC_PSW_CTRL_MASK ASHFT24(0xFUL) ++#define L1F_MISC_PSW_CTRL_SHIFT 24 ++#define L1F_MISC_PSW_OCP_MASK ASHFT21(7UL) ++#define L1F_MISC_PSW_OCP_SHIFT 21 ++#define L1F_MISC_V18_HIGH BIT(20) ++#define L1F_MISC_LPO_CTRL_MASK ASHFT16(0xFUL) ++#define L1F_MISC_LPO_CTRL_SHIFT 16 ++#define L1F_MISC_ISO_EN BIT(12) ++#define L1F_MISC_XSTANA_ALWAYS_ON BIT(11) ++#define L1F_MISC_SYS25M_SEL_ADAPTIVE BIT(10) ++#define L1F_MISC_SPEED_SIM BIT(9) ++#define L1F_MISC_S1_LWP_EN BIT(8) ++#define L1F_MISC_MACLPW BIT(7) /* pcie/mac do pwsaving ++ * as phy in lpw state */ ++#define L1F_MISC_125M_SW BIT(6) ++#define L1F_MISC_INTNLOSC_OFF_EN BIT(5) ++#define L1F_MISC_EXTN25M_SEL BIT(4) /* 0:chipset,1:cystle */ ++#define L1F_MISC_INTNLOSC_OPEN BIT(3) ++#define L1F_MISC_SMBUS_AT_LED BIT(2) ++#define L1F_MISC_PPS_AT_LED_MASK ASHFT0(3UL) ++#define L1F_MISC_PPS_AT_LED_SHIFT 0 ++#define L1F_MISC_PPS_AT_LED_ACT 1 ++#define L1F_MISC_PPS_AT_LED_10_100 2 ++#define L1F_MISC_PPS_AT_LED_1000 3 ++ ++#define L1F_MISC1 0x19C4 ++#define L1F_MSC1_BLK_CRASPM_REQ BIT(15) ++ ++#define L1F_MISC3 0x19CC ++#define L1F_MISC3_25M_BY_SW BIT(1) /* 1:Software control 25M */ ++#define L1F_MISC3_25M_NOTO_INTNL BIT(0) /* 0:25M switch to intnl OSC */ ++ ++ ++ ++/***************************** IO mapping registers ***************************/ ++#define L1F_IO_ADDR 0x00 /* DWORD reg */ ++#define L1F_IO_DATA 0x04 /* DWORD reg */ ++#define L1F_IO_MASTER 0x08 /* DWORD same as reg0x1400 */ ++#define L1F_IO_MAC_CTRL 0x0C /* DWORD same as reg0x1480*/ ++#define L1F_IO_ISR 0x10 /* DWORD same as reg0x1600 */ ++#define L1F_IO_IMR 0x14 /* DWORD same as reg0x1604 */ ++#define L1F_IO_TPD_PRI1_PIDX 0x18 /* WORD same as reg0x15F0 */ ++#define L1F_IO_TPD_PRI0_PIDX 0x1A /* WORD same as reg0x15F2 */ ++#define L1F_IO_TPD_PRI1_CIDX 0x1C /* WORD same as reg0x15F4 */ ++#define L1F_IO_TPD_PRI0_CIDX 0x1E /* WORD same as reg0x15F6 */ ++#define L1F_IO_RFD_PIDX 0x20 /* WORD same as reg0x15E0 */ ++#define L1F_IO_RFD_CIDX 0x30 /* WORD same as reg0x15F8 */ ++#define L1F_IO_MDIO 0x38 /* WORD same as reg0x1414 */ ++#define L1F_IO_PHY_CTRL 0x3C /* DWORD same as reg0x140C */ ++ ++ ++/********************* PHY regs definition ***************************/ ++ ++/* Autoneg Advertisement Register */ ++#define L1F_ADVERTISE_SPEED_MASK 0x01E0 ++#define L1F_ADVERTISE_DEFAULT_CAP 0x1DE0 /* diff with L1C */ ++ ++/* 1000BASE-T Control Register (0x9) */ ++#define L1F_GIGA_CR_1000T_HD_CAPS 0x0100 ++#define L1F_GIGA_CR_1000T_FD_CAPS 0x0200 ++#define L1F_GIGA_CR_1000T_REPEATER_DTE 0x0400 ++ ++#define L1F_GIGA_CR_1000T_MS_VALUE 0x0800 ++ ++#define L1F_GIGA_CR_1000T_MS_ENABLE 0x1000 ++ ++#define L1F_GIGA_CR_1000T_TEST_MODE_NORMAL 0x0000 ++#define L1F_GIGA_CR_1000T_TEST_MODE_1 0x2000 ++#define L1F_GIGA_CR_1000T_TEST_MODE_2 0x4000 ++#define L1F_GIGA_CR_1000T_TEST_MODE_3 0x6000 ++#define L1F_GIGA_CR_1000T_TEST_MODE_4 0x8000 ++#define L1F_GIGA_CR_1000T_SPEED_MASK 0x0300 ++#define L1F_GIGA_CR_1000T_DEFAULT_CAP 0x0300 ++ ++/* 1000BASE-T Status Register */ ++#define L1F_MII_GIGA_SR 0x0A ++ ++/* PHY Specific Status Register */ ++#define L1F_MII_GIGA_PSSR 0x11 ++#define L1F_GIGA_PSSR_FC_RXEN 0x0004 ++#define L1F_GIGA_PSSR_FC_TXEN 0x0008 ++#define L1F_GIGA_PSSR_SPD_DPLX_RESOLVED 0x0800 ++#define L1F_GIGA_PSSR_DPLX 0x2000 ++#define L1F_GIGA_PSSR_SPEED 0xC000 ++#define L1F_GIGA_PSSR_10MBS 0x0000 ++#define L1F_GIGA_PSSR_100MBS 0x4000 ++#define L1F_GIGA_PSSR_1000MBS 0x8000 ++ ++/* PHY Interrupt Enable Register */ ++#define L1F_MII_IER 0x12 ++#define L1F_IER_LINK_UP 0x0400 ++#define L1F_IER_LINK_DOWN 0x0800 ++ ++/* PHY Interrupt Status Register */ ++#define L1F_MII_ISR 0x13 ++#define L1F_ISR_LINK_UP 0x0400 ++#define L1F_ISR_LINK_DOWN 0x0800 ++ ++/* Cable-Detect-Test Control Register */ ++#define L1F_MII_CDTC 0x16 ++#define L1F_CDTC_EN 1 /* sc */ ++#define L1F_CDTC_PAIR_MASK ASHFT8(3U) ++#define L1F_CDTC_PAIR_SHIFT 8 ++ ++ ++/* Cable-Detect-Test Status Register */ ++#define L1F_MII_CDTS 0x1C ++#define L1F_CDTS_STATUS_MASK ASHFT8(3U) ++#define L1F_CDTS_STATUS_SHIFT 8 ++#define L1F_CDTS_STATUS_NORMAL 0 ++#define L1F_CDTS_STATUS_SHORT 1 ++#define L1F_CDTS_STATUS_OPEN 2 ++#define L1F_CDTS_STATUS_INVALID 3 ++ ++#define L1F_MII_DBG_ADDR 0x1D ++#define L1F_MII_DBG_DATA 0x1E ++ ++/***************************** debug port *************************************/ ++ ++#define L1F_MIIDBG_ANACTRL 0x00 ++#define L1F_ANACTRL_CLK125M_DELAY_EN BIT(15) ++#define L1F_ANACTRL_VCO_FAST BIT(14) ++#define L1F_ANACTRL_VCO_SLOW BIT(13) ++#define L1F_ANACTRL_AFE_MODE_EN BIT(12) ++#define L1F_ANACTRL_LCKDET_PHY BIT(11) ++#define L1F_ANACTRL_LCKDET_EN BIT(10) ++#define L1F_ANACTRL_OEN_125M BIT(9) ++#define L1F_ANACTRL_HBIAS_EN BIT(8) ++#define L1F_ANACTRL_HB_EN BIT(7) ++#define L1F_ANACTRL_SEL_HSP BIT(6) ++#define L1F_ANACTRL_CLASSA_EN BIT(5) ++#define L1F_ANACTRL_MANUSWON_SWR_MASK ASHFT2(3U) ++#define L1F_ANACTRL_MANUSWON_SWR_SHIFT 2 ++#define L1F_ANACTRL_MANUSWON_SWR_2V 0 ++#define L1F_ANACTRL_MANUSWON_SWR_1P9V 1 ++#define L1F_ANACTRL_MANUSWON_SWR_1P8V 2 ++#define L1F_ANACTRL_MANUSWON_SWR_1P7V 3 ++#define L1F_ANACTRL_MANUSWON_BW3_4M BIT(1) ++#define L1F_ANACTRL_RESTART_CAL BIT(0) ++#define L1F_ANACTRL_DEF 0x02EF ++ ++ ++#define L1F_MIIDBG_SYSMODCTRL 0x04 ++#define L1F_SYSMODCTRL_IECHOADJ_PFMH_PHY BIT(15) ++#define L1F_SYSMODCTRL_IECHOADJ_BIASGEN BIT(14) ++#define L1F_SYSMODCTRL_IECHOADJ_PFML_PHY BIT(13) ++#define L1F_SYSMODCTRL_IECHOADJ_PS_MASK ASHFT10(3U) ++#define L1F_SYSMODCTRL_IECHOADJ_PS_SHIFT 10 ++#define L1F_SYSMODCTRL_IECHOADJ_PS_40 3 ++#define L1F_SYSMODCTRL_IECHOADJ_PS_20 2 ++#define L1F_SYSMODCTRL_IECHOADJ_PS_0 1 ++#define L1F_SYSMODCTRL_IECHOADJ_10BT_100MV BIT(6) /* 1:100mv, 0:200mv */ ++#define L1F_SYSMODCTRL_IECHOADJ_HLFAP_MASK ASHFT4(3U) ++#define L1F_SYSMODCTRL_IECHOADJ_HLFAP_SHIFT 4 ++#define L1F_SYSMODCTRL_IECHOADJ_VDFULBW BIT(3) ++#define L1F_SYSMODCTRL_IECHOADJ_VDBIASHLF BIT(2) ++#define L1F_SYSMODCTRL_IECHOADJ_VDAMPHLF BIT(1) ++#define L1F_SYSMODCTRL_IECHOADJ_VDLANSW BIT(0) ++#define L1F_SYSMODCTRL_IECHOADJ_DEF 0xBB8B /* en half bias */ ++ ++ ++#define L1F_MIIDBG_SRDSYSMOD 0x05 ++#define L1F_SRDSYSMOD_LCKDET_EN BIT(13) ++#define L1F_SRDSYSMOD_PLL_EN BIT(11) ++#define L1F_SRDSYSMOD_SEL_HSP BIT(10) ++#define L1F_SRDSYSMOD_HLFTXDR BIT(9) ++#define L1F_SRDSYSMOD_TXCLK_DELAY_EN BIT(8) ++#define L1F_SRDSYSMOD_TXELECIDLE BIT(7) ++#define L1F_SRDSYSMOD_DEEMP_EN BIT(6) ++#define L1F_SRDSYSMOD_MS_PAD BIT(2) ++#define L1F_SRDSYSMOD_CDR_ADC_VLTG BIT(1) ++#define L1F_SRDSYSMOD_CDR_DAC_1MA BIT(0) ++#define L1F_SRDSYSMOD_DEF 0x2C46 ++ ++ ++#define L1F_MIIDBG_HIBNEG 0x0B ++#define L1F_HIBNEG_PSHIB_EN BIT(15) ++#define L1F_HIBNEG_WAKE_BOTH BIT(14) ++#define L1F_HIBNEG_ONOFF_ANACHG_SUDEN BIT(13) ++#define L1F_HIBNEG_HIB_PULSE BIT(12) ++#define L1F_HIBNEG_GATE_25M_EN BIT(11) ++#define L1F_HIBNEG_RST_80U BIT(10) ++#define L1F_HIBNEG_RST_TIMER_MASK ASHFT8(3U) ++#define L1F_HIBNEG_RST_TIMER_SHIFT 8 ++#define L1F_HIBNEG_GTX_CLK_DELAY_MASK ASHFT5(3U) ++#define L1F_HIBNEG_GTX_CLK_DELAY_SHIFT 5 ++#define L1F_HIBNEG_BYPSS_BRKTIMER BIT(4) ++#define L1F_HIBNEG_DEF 0xBC40 ++ ++#define L1F_MIIDBG_TST10BTCFG 0x12 ++#define L1F_TST10BTCFG_INTV_TIMER_MASK ASHFT14(3U) ++#define L1F_TST10BTCFG_INTV_TIMER_SHIFT 14 ++#define L1F_TST10BTCFG_TRIGER_TIMER_MASK ASHFT12(3U) ++#define L1F_TST10BTCFG_TRIGER_TIMER_SHIFT 12 ++#define L1F_TST10BTCFG_DIV_MAN_MLT3_EN BIT(11) ++#define L1F_TST10BTCFG_OFF_DAC_IDLE BIT(10) ++#define L1F_TST10BTCFG_LPBK_DEEP BIT(2) /* 1:deep,0:shallow */ ++#define L1F_TST10BTCFG_DEF 0x4C04 ++ ++#define L1F_MIIDBG_AZ_ANADECT 0x15 ++#define L1F_AZ_ANADECT_10BTRX_TH BIT(15) ++#define L1F_AZ_ANADECT_BOTH_01CHNL BIT(14) ++#define L1F_AZ_ANADECT_INTV_MASK ASHFT8(0x3FU) ++#define L1F_AZ_ANADECT_INTV_SHIFT 8 ++#define L1F_AZ_ANADECT_THRESH_MASK ASHFT4(0xFU) ++#define L1F_AZ_ANADECT_THRESH_SHIFT 4 ++#define L1F_AZ_ANADECT_CHNL_MASK ASHFT0(0xFU) ++#define L1F_AZ_ANADECT_CHNL_SHIFT 0 ++#define L1F_AZ_ANADECT_DEF 0x3220 ++#define L1F_AZ_ANADECT_LONG 0x3210 ++ ++#define L1F_MIIDBG_AGC 0x23 ++#define L1F_AGC_2_VGA_MASK ASHFT8(0x3FU) ++#define L1F_AGC_2_VGA_SHIFT 8 ++#define L1F_AGC_LONG1G_LIMT 40 ++#define L1F_AGC_LONG100M_LIMT 44 ++ ++#define L1F_MIIDBG_LEGCYPS 0x29 ++#define L1F_LEGCYPS_EN BIT(15) ++#define L1F_LEGCYPS_DAC_AMP1000_MASK ASHFT12(7U) ++#define L1F_LEGCYPS_DAC_AMP1000_SHIFT 12 ++#define L1F_LEGCYPS_DAC_AMP100_MASK ASHFT9(7U) ++#define L1F_LEGCYPS_DAC_AMP100_SHIFT 9 ++#define L1F_LEGCYPS_DAC_AMP10_MASK ASHFT6(7U) ++#define L1F_LEGCYPS_DAC_AMP10_SHIFT 6 ++#define L1F_LEGCYPS_UNPLUG_TIMER_MASK ASHFT3(7U) ++#define L1F_LEGCYPS_UNPLUG_TIMER_SHIFT 3 ++#define L1F_LEGCYPS_UNPLUG_DECT_EN BIT(2) ++#define L1F_LEGCYPS_ECNC_PS_EN BIT(0) ++#define L1F_LEGCYPS_DEF 0x129D ++ ++#define L1F_MIIDBG_TST100BTCFG 0x36 ++#define L1F_TST100BTCFG_NORMAL_BW_EN BIT(15) ++#define L1F_TST100BTCFG_BADLNK_BYPASS BIT(14) ++#define L1F_TST100BTCFG_SHORTCABL_TH_MASK ASHFT8(0x3FU) ++#define L1F_TST100BTCFG_SHORTCABL_TH_SHIFT 8 ++#define L1F_TST100BTCFG_LITCH_EN BIT(7) ++#define L1F_TST100BTCFG_VLT_SW BIT(6) ++#define L1F_TST100BTCFG_LONGCABL_TH_MASK ASHFT0(0x3FU) ++#define L1F_TST100BTCFG_LONGCABL_TH_SHIFT 0 ++#define L1F_TST100BTCFG_DEF 0xE12C ++ ++#define L1F_MIIDBG_GREENCFG 0x3B ++#define L1F_GREENCFG_MSTPS_MSETH2_MASK ASHFT8(0xFFU) ++#define L1F_GREENCFG_MSTPS_MSETH2_SHIFT 8 ++#define L1F_GREENCFG_MSTPS_MSETH1_MASK ASHFT0(0xFFU) ++#define L1F_GREENCFG_MSTPS_MSETH1_SHIFT 0 ++#define L1F_GREENCFG_DEF 0x7078 ++ ++#define L1F_MIIDBG_GREENCFG2 0x3D ++#define L1F_GREENCFG2_GATE_DFSE_EN BIT(7) ++ ++ ++/***************************** extension **************************************/ ++ ++/******* dev 3 *********/ ++#define L1F_MIIEXT_PCS 3 ++ ++#define L1F_MIIEXT_CLDCTRL6 0x8006 ++#define L1F_CLDCTRL6_CAB_LEN_MASK ASHFT0(0xFFU) ++#define L1F_CLDCTRL6_CAB_LEN_SHIFT 0 ++#define L1F_CLDCTRL6_CAB_LEN_SHORT1G 116 ++#define L1F_CLDCTRL6_CAB_LEN_SHORT100M 152 ++ ++#define L1F_MIIEXT_CLDCTRL7 0x8007 ++#define L1F_CLDCTRL7_VDHLF_BIAS_TH_MASK ASHFT9(0x7FU) ++#define L1F_CLDCTRL7_VDHLF_BIAS_TH_SHIFT 9 ++#define L1F_CLDCTRL7_AFE_AZ_MASK ASHFT4(0x1FU) ++#define L1F_CLDCTRL7_AFE_AZ_SHIFT 4 ++#define L1F_CLDCTRL7_SIDE_PEAK_TH_MASK ASHFT0(0xFU) ++#define L1F_CLDCTRL7_SIDE_PEAK_TH_SHIFT 0 ++#define L1F_CLDCTRL7_DEF 0x6BF6 /* ???? */ ++ ++#define L1F_MIIEXT_AZCTRL 0x8008 ++#define L1F_AZCTRL_SHORT_TH_MASK ASHFT8(0xFFU) ++#define L1F_AZCTRL_SHORT_TH_SHIFT 8 ++#define L1F_AZCTRL_LONG_TH_MASK ASHFT0(0xFFU) ++#define L1F_AZCTRL_LONG_TH_SHIFT 0 ++#define L1F_AZCTRL_DEF 0x1629 ++ ++#define L1F_MIIEXT_AZCTRL2 0x8009 ++#define L1F_AZCTRL2_WAKETRNING_MASK ASHFT8(0xFFU) ++#define L1F_AZCTRL2_WAKETRNING_SHIFT 8 ++#define L1F_AZCTRL2_QUIET_TIMER_MASH ASHFT6(3U) ++#define L1F_AZCTRL2_QUIET_TIMER_SHIFT 6 ++#define L1F_AZCTRL2_PHAS_JMP2 BIT(4) ++#define L1F_AZCTRL2_CLKTRCV_125MD16 BIT(3) ++#define L1F_AZCTRL2_GATE1000_EN BIT(2) ++#define L1F_AZCTRL2_AVRG_FREQ BIT(1) ++#define L1F_AZCTRL2_PHAS_JMP4 BIT(0) ++#define L1F_AZCTRL2_DEF 0x32C0 ++ ++#define L1F_MIIEXT_AZCTRL6 0x800D ++ ++#define L1F_MIIEXT_VDRVBIAS 0x8062 ++#define L1F_VDRVBIAS_SEL_MASK ASHFT0(0x3U) ++#define L1F_VDRVBIAS_SEL_SHIFT 0 ++#define L1F_VDRVBIAS_DEF 0x3 ++ ++/********* dev 7 **********/ ++#define L1F_MIIEXT_ANEG 7 ++ ++#define L1F_MIIEXT_LOCAL_EEEADV 0x3C ++#define L1F_LOCAL_EEEADV_1000BT BIT(2) ++#define L1F_LOCAL_EEEADV_100BT BIT(1) ++ ++#define L1F_MIIEXT_REMOTE_EEEADV 0x3D ++#define L1F_REMOTE_EEEADV_1000BT BIT(2) ++#define L1F_REMOTE_EEEADV_100BT BIT(1) ++ ++#define L1F_MIIEXT_EEE_ANEG 0x8000 ++#define L1F_EEE_ANEG_1000M BIT(2) ++#define L1F_EEE_ANEG_100M BIT(1) ++ ++#define L1F_MIIEXT_AFE 0x801A ++#define L1F_AFE_10BT_100M_TH BIT(6) ++ ++ ++#define L1F_MIIEXT_NLP34 0x8025 ++#define L1F_MIIEXT_NLP34_DEF 0x1010 /* for 160m */ ++ ++#define L1F_MIIEXT_NLP56 0x8026 ++#define L1F_MIIEXT_NLP56_DEF 0x1010 /* for 160m */ ++ ++#define L1F_MIIEXT_NLP78 0x8027 ++#define L1F_MIIEXT_NLP78_160M_DEF 0x8D05 /* for 160m */ ++#define L1F_MIIEXT_NLP78_120M_DEF 0x8A05 /* for 120m */ ++ ++ ++ ++/******************************************************************************/ ++ ++/* functions */ ++ ++ ++/* get permanent mac address from ++ * return ++ * 0: success ++ * non-0:fail ++ */ ++u16 l1f_get_perm_macaddr(struct alx_hw *hw, u8 *addr); ++ ++ ++/* reset mac & dma ++ * return ++ * 0: success ++ * non-0:fail ++ */ ++u16 l1f_reset_mac(struct alx_hw *hw); ++ ++/* reset phy ++ * return ++ * 0: success ++ * non-0:fail ++ */ ++u16 l1f_reset_phy(struct alx_hw *hw, bool pws_en, bool az_en, bool ptp_en); ++ ++ ++/* reset pcie ++ * just reset pcie relative registers (pci command, clk, aspm...) ++ * return ++ * 0:success ++ * non-0:fail ++ */ ++u16 l1f_reset_pcie(struct alx_hw *hw, bool l0s_en, bool l1_en); ++ ++ ++/* disable/enable MAC/RXQ/TXQ ++ * en ++ * true:enable ++ * false:disable ++ * return ++ * 0:success ++ * non-0-fail ++ */ ++u16 l1f_enable_mac(struct alx_hw *hw, bool en, u16 en_ctrl); ++ ++ ++/* enable/disable aspm support ++ * that will change settings for phy/mac/pcie ++ */ ++u16 l1f_enable_aspm(struct alx_hw *hw, bool l0s_en, bool l1_en, u8 lnk_stat); ++ ++ ++/* initialize phy for speed / flow control ++ * lnk_cap ++ * if autoNeg, is link capability to tell the peer ++ * if force mode, is forced speed/duplex ++ */ ++u16 l1f_init_phy_spdfc(struct alx_hw *hw, bool auto_neg, ++ u8 lnk_cap, bool fc_en); ++ ++/* do post setting on phy if link up/down event occur ++ */ ++u16 l1f_post_phy_link(struct alx_hw *hw, bool linkon, u8 wire_spd); ++ ++ ++/* do power saving setting befor enter suspend mode ++ * NOTE: ++ * 1. phy link must be established before calling this function ++ * 2. wol option (pattern,magic,link,etc.) is configed before call it. ++ */ ++u16 l1f_powersaving(struct alx_hw *hw, u8 wire_spd, bool wol_en, ++ bool mahw_en, bool macrx_en, bool pws_en); ++ ++/* read phy register */ ++u16 l1f_read_phy(struct alx_hw *hw, bool ext, u8 dev, bool fast, u16 reg, ++ u16 *data); ++ ++/* write phy register */ ++u16 l1f_write_phy(struct alx_hw *hw, bool ext, u8 dev, bool fast, u16 reg, ++ u16 data); ++ ++/* phy debug port */ ++u16 l1f_read_phydbg(struct alx_hw *hw, bool fast, u16 reg, u16 *data); ++u16 l1f_write_phydbg(struct alx_hw *hw, bool fast, u16 reg, u16 data); ++ ++ ++/* check the configuration of the PHY */ ++u16 l1f_get_phy_config(struct alx_hw *hw); ++ ++/* ++ * initialize mac basically ++ * most of hi-feature no init ++ * MAC/PHY should be reset before call this function ++ */ ++u16 l1f_init_mac(struct alx_hw *hw, u8 *addr, u32 txmem_hi, ++ u32 *tx_mem_lo, u8 tx_qnum, u16 txring_sz, ++ u32 rxmem_hi, u32 rfdmem_lo, u32 rrdmem_lo, ++ u16 rxring_sz, u16 rxbuf_sz, u16 smb_timer, ++ u16 mtu, u16 int_mod, bool hash_legacy); ++ ++ ++ ++#endif/*L1F_HW_H_*/ ++ +diff --git a/drivers/net/ethernet/atheros/alx/alx.h b/drivers/net/ethernet/atheros/alx/alx.h +new file mode 100644 +index 0000000..6482bee +--- /dev/null ++++ b/drivers/net/ethernet/atheros/alx/alx.h +@@ -0,0 +1,670 @@ ++/* ++ * Copyright (c) 2012 Qualcomm Atheros, Inc. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _ALX_H_ ++#define _ALX_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "alx_sw.h" ++ ++/* ++ * Definition to enable some features ++ */ ++#undef CONFIG_ALX_MSIX ++#undef CONFIG_ALX_MSI ++#undef CONFIG_ALX_MTQ ++#undef CONFIG_ALX_MRQ ++#undef CONFIG_ALX_RSS ++/* #define CONFIG_ALX_MSIX */ ++#define CONFIG_ALX_MSI ++#define CONFIG_ALX_MTQ ++#define CONFIG_ALX_MRQ ++#ifdef CONFIG_ALX_MRQ ++#define CONFIG_ALX_RSS ++#endif ++ ++#define ALX_MSG_DEFAULT 0 ++ ++/* Logging functions and macros */ ++#define alx_err(adpt, fmt, ...) \ ++ netdev_err(adpt->netdev, fmt, ##__VA_ARGS__) ++ ++#define ALX_VLAN_TO_TAG(_vlan, _tag) \ ++ do { \ ++ _tag = ((((_vlan) >> 8) & 0xFF) | (((_vlan) & 0xFF) << 8)); \ ++ } while (0) ++ ++#define ALX_TAG_TO_VLAN(_tag, _vlan) \ ++ do { \ ++ _vlan = ((((_tag) >> 8) & 0xFF) | (((_tag) & 0xFF) << 8)) ; \ ++ } while (0) ++ ++/* Coalescing Message Block */ ++struct coals_msg_block { ++ int test; ++}; ++ ++ ++#define BAR_0 0 ++ ++#define ALX_DEF_RX_BUF_SIZE 1536 ++#define ALX_MAX_JUMBO_PKT_SIZE (9*1024) ++#define ALX_MAX_TSO_PKT_SIZE (7*1024) ++ ++#define ALX_MAX_ETH_FRAME_SIZE ALX_MAX_JUMBO_PKT_SIZE ++#define ALX_MIN_ETH_FRAME_SIZE 68 ++ ++ ++#define ALX_MAX_RX_QUEUES 8 ++#define ALX_MAX_TX_QUEUES 4 ++#define ALX_MAX_HANDLED_INTRS 5 ++ ++#define ALX_WATCHDOG_TIME (5 * HZ) ++ ++struct alx_cmb { ++ char name[IFNAMSIZ + 9]; ++ void *cmb; ++ dma_addr_t dma; ++}; ++struct alx_smb { ++ char name[IFNAMSIZ + 9]; ++ void *smb; ++ dma_addr_t dma; ++}; ++ ++ ++/* ++ * RRD : definition ++ */ ++ ++/* general parameter format of rrd */ ++struct alx_rrdes_general { ++ u32 xsum:16; ++ u32 nor:4; /* number of RFD */ ++ u32 si:12; /* start index of rfd-ring */ ++ ++ u32 hash; ++ ++ /* dword 3 */ ++ u32 vlan_tag:16; /* vlan-tag */ ++ u32 pid:8; /* Header Length of Header-Data Split. WORD unit */ ++ u32 reserve0:1; ++ u32 rss_cpu:3; /* CPU number used by RSS */ ++ u32 rss_flag:4; /* rss_flag 0, TCP(IPv6) flag for RSS hash algrithm ++ * rss_flag 1, IPv6 flag for RSS hash algrithm ++ * rss_flag 2, TCP(IPv4) flag for RSS hash algrithm ++ * rss_flag 3, IPv4 flag for RSS hash algrithm ++ */ ++ ++ /* dword 3 */ ++ u32 pkt_len:14; /* length of the packet */ ++ u32 l4f:1; /* L4(TCP/UDP) checksum failed */ ++ u32 ipf:1; /* IP checksum failed */ ++ u32 vlan_flag:1;/* vlan tag */ ++ u32 reserve:3; ++ u32 res:1; /* received error summary */ ++ u32 crc:1; /* crc error */ ++ u32 fae:1; /* frame alignment error */ ++ u32 trunc:1; /* truncated packet, larger than MTU */ ++ u32 runt:1; /* runt packet */ ++ u32 icmp:1; /* incomplete packet, ++ * due to insufficient rx-descriptor ++ */ ++ u32 bar:1; /* broadcast address received */ ++ u32 mar:1; /* multicast address received */ ++ u32 type:1; /* ethernet type */ ++ u32 fov:1; /* fifo overflow*/ ++ u32 lene:1; /* length error */ ++ u32 update:1; /* update*/ ++}; ++ ++union alx_rrdesc { ++ /* dword flat format */ ++ struct { ++ __le32 dw0; ++ __le32 dw1; ++ __le32 dw2; ++ __le32 dw3; ++ } dfmt; ++ ++ /* qword flat format */ ++ struct { ++ __le64 qw0; ++ __le64 qw1; ++ } qfmt; ++}; ++ ++/* ++ * XXX: we should not use this guy, best to just ++ * do all le32_to_cpu() conversions on the spot. ++ */ ++union alx_sw_rrdesc { ++ struct alx_rrdes_general genr; ++ ++ /* dword flat format */ ++ struct { ++ u32 dw0; ++ u32 dw1; ++ u32 dw2; ++ u32 dw3; ++ } dfmt; ++ ++ /* qword flat format */ ++ struct { ++ u64 qw0; ++ u64 qw1; ++ } qfmt; ++}; ++ ++/* ++ * RFD : definition ++ */ ++ ++/* general parameter format of rfd */ ++struct alx_rfdes_general { ++ u64 addr; ++}; ++ ++union alx_rfdesc { ++ /* dword flat format */ ++ struct { ++ __le32 dw0; ++ __le32 dw1; ++ } dfmt; ++ ++ /* qword flat format */ ++ struct { ++ __le64 qw0; ++ } qfmt; ++}; ++ ++/* ++ * XXX: we should not use this guy, best to just ++ * do all le32_to_cpu() conversions on the spot. ++ */ ++union alx_sw_rfdesc { ++ struct alx_rfdes_general genr; ++ ++ /* dword flat format */ ++ struct { ++ u32 dw0; ++ u32 dw1; ++ } dfmt; ++ ++ /* qword flat format */ ++ struct { ++ u64 qw0; ++ } qfmt; ++}; ++ ++/* ++ * TPD : definition ++ */ ++ ++/* general parameter format of tpd */ ++struct alx_tpdes_general { ++ u32 buffer_len:16; /* include 4-byte CRC */ ++ u32 vlan_tag:16; ++ ++ u32 l4hdr_offset:8; /* tcp/udp header offset to the 1st byte of ++ * the packet */ ++ u32 c_csum:1; /* must be 0 in this format */ ++ u32 ip_csum:1; /* do ip(v4) header checksum offload */ ++ u32 tcp_csum:1; /* do tcp checksum offload, both ipv4 and ipv6 */ ++ u32 udp_csum:1; /* do udp checksum offlaod, both ipv4 and ipv6 */ ++ u32 lso:1; ++ u32 lso_v2:1; /* must be 0 in this format */ ++ u32 vtagged:1; /* vlan-id tagged already */ ++ u32 instag:1; /* insert vlan tag */ ++ ++ u32 ipv4:1; /* ipv4 packet */ ++ u32 type:1; /* type of packet (ethernet_ii(1) or snap(0)) */ ++ u32 reserve:12; /* reserved, must be 0 */ ++ u32 epad:1; /* even byte padding when this packet */ ++ u32 last_frag:1; /* last fragment(buffer) of the packet */ ++ ++ u64 addr; ++}; ++ ++/* custom checksum parameter format of tpd */ ++struct alx_tpdes_checksum { ++ u32 buffer_len:16; /* include 4-byte CRC */ ++ u32 vlan_tag:16; ++ ++ u32 payld_offset:8; /* payload offset to the 1st byte of ++ * the packet ++ */ ++ u32 c_sum:1; /* do custom chekcusm offload, ++ * must be 1 in this format ++ */ ++ u32 ip_sum:1; /* must be 0 in thhis format */ ++ u32 tcp_sum:1; /* must be 0 in this format */ ++ u32 udp_sum:1; /* must be 0 in this format */ ++ u32 lso:1; /* must be 0 in this format */ ++ u32 lso_v2:1; /* must be 0 in this format */ ++ u32 vtagged:1; /* vlan-id tagged already */ ++ u32 instag:1; /* insert vlan tag */ ++ ++ u32 ipv4:1; /* ipv4 packet */ ++ u32 type:1; /* type of packet (ethernet_ii(1) or snap(0)) */ ++ u32 cxsum_offset:8; /* checksum offset to the 1st byte of ++ * the packet ++ */ ++ u32 reserve:4; /* reserved, must be 0 */ ++ u32 epad:1; /* even byte padding when this packet */ ++ u32 last_frag:1; /* last fragment(buffer) of the packet */ ++ ++ u64 addr; ++}; ++ ++ ++/* tcp large send format (v1/v2) of tpd */ ++struct alx_tpdes_tso { ++ u32 buffer_len:16; /* include 4-byte CRC */ ++ u32 vlan_tag:16; ++ ++ u32 tcphdr_offset:8; /* tcp hdr offset to the 1st byte of packet */ ++ u32 c_sum:1; /* must be 0 in this format */ ++ u32 ip_sum:1; /* must be 0 in thhis format */ ++ u32 tcp_sum:1; /* must be 0 in this format */ ++ u32 udp_sum:1; /* must be 0 in this format */ ++ u32 lso:1; /* do tcp large send (ipv4 only) */ ++ u32 lso_v2:1; /* must be 0 in this format */ ++ u32 vtagged:1; /* vlan-id tagged already */ ++ u32 instag:1; /* insert vlan tag */ ++ ++ u32 ipv4:1; /* ipv4 packet */ ++ u32 type:1; /* type of packet (ethernet_ii(1) or snap(0)) */ ++ u32 mss:13; /* MSS if do tcp large send */ ++ u32 last_frag:1; /* last fragment(buffer) of the packet */ ++ ++ u32 addr_lo; ++ u32 addr_hi; ++}; ++ ++union alx_tpdesc { ++ /* dword flat format */ ++ struct { ++ __le32 dw0; ++ __le32 dw1; ++ __le32 dw2; ++ __le32 dw3; ++ } dfmt; ++ ++ /* qword flat format */ ++ struct { ++ __le64 qw0; ++ __le64 qw1; ++ } qfmt; ++}; ++ ++/* ++ * XXX: we should not use this guy, best to just ++ * do all le32_to_cpu() conversions on the spot. ++ */ ++union alx_sw_tpdesc { ++ struct alx_tpdes_general genr; ++ struct alx_tpdes_checksum csum; ++ struct alx_tpdes_tso tso; ++ ++ /* dword flat format */ ++ struct { ++ u32 dw0; ++ u32 dw1; ++ u32 dw2; ++ u32 dw3; ++ } dfmt; ++ ++ /* qword flat format */ ++ struct { ++ u64 qw0; ++ u64 qw1; ++ } qfmt; ++}; ++ ++#define ALX_RRD(_que, _i) \ ++ (&(((union alx_rrdesc *)(_que)->rrq.rrdesc)[(_i)])) ++#define ALX_RFD(_que, _i) \ ++ (&(((union alx_rfdesc *)(_que)->rfq.rfdesc)[(_i)])) ++#define ALX_TPD(_que, _i) \ ++ (&(((union alx_tpdesc *)(_que)->tpq.tpdesc)[(_i)])) ++ ++ ++/* ++ * alx_ring_header represents a single, contiguous block of DMA space ++ * mapped for the three descriptor rings (tpd, rfd, rrd) and the two ++ * message blocks (cmb, smb) described below ++ */ ++struct alx_ring_header { ++ void *desc; /* virtual address */ ++ dma_addr_t dma; /* physical address*/ ++ unsigned int size; /* length in bytes */ ++ unsigned int used; ++}; ++ ++ ++/* ++ * alx_buffer is wrapper around a pointer to a socket buffer ++ * so a DMA handle can be stored along with the skb ++ */ ++struct alx_buffer { ++ struct sk_buff *skb; /* socket buffer */ ++ u16 length; /* rx buffer length */ ++ dma_addr_t dma; ++}; ++ ++struct alx_sw_buffer { ++ struct sk_buff *skb; /* socket buffer */ ++ u32 vlan_tag:16; ++ u32 vlan_flag:1; ++ u32 reserved:15; ++}; ++ ++/* receive free descriptor (rfd) queue */ ++struct alx_rfd_queue { ++ struct alx_buffer *rfbuff; ++ union alx_rfdesc *rfdesc; /* virtual address */ ++ dma_addr_t rfdma; /* physical address */ ++ u16 size; /* length in bytes */ ++ u16 count; /* number of descriptors in the ring */ ++ u16 produce_idx; /* it's written to rxque->produce_reg */ ++ u16 consume_idx; /* unused*/ ++}; ++ ++/* receive return desciptor (rrd) queue */ ++struct alx_rrd_queue { ++ union alx_rrdesc *rrdesc; /* virtual address */ ++ dma_addr_t rrdma; /* physical address */ ++ u16 size; /* length in bytes */ ++ u16 count; /* number of descriptors in the ring */ ++ u16 produce_idx; /* unused */ ++ u16 consume_idx; /* rxque->consume_reg */ ++}; ++ ++/* software desciptor (swd) queue */ ++struct alx_swd_queue { ++ struct alx_sw_buffer *swbuff; ++ u16 count; /* number of descriptors in the ring */ ++ u16 produce_idx; ++ u16 consume_idx; ++}; ++ ++/* rx queue */ ++struct alx_rx_queue { ++ struct device *dev; /* device for dma mapping */ ++ struct net_device *netdev; /* netdev ring belongs to */ ++ struct alx_msix_param *msix; ++ struct alx_rrd_queue rrq; ++ struct alx_rfd_queue rfq; ++ struct alx_swd_queue swq; ++ ++ u16 que_idx; /* index in multi rx queues*/ ++ u16 max_packets; /* max work per interrupt */ ++ u16 produce_reg; ++ u16 consume_reg; ++ u32 flags; ++}; ++#define ALX_RX_FLAG_SW_QUE 0x00000001 ++#define ALX_RX_FLAG_HW_QUE 0x00000002 ++#define CHK_RX_FLAG(_flag) CHK_FLAG(rxque, RX, _flag) ++#define SET_RX_FLAG(_flag) SET_FLAG(rxque, RX, _flag) ++#define CLI_RX_FLAG(_flag) CLI_FLAG(rxque, RX, _flag) ++ ++#define GET_RF_BUFFER(_rque, _i) (&((_rque)->rfq.rfbuff[(_i)])) ++#define GET_SW_BUFFER(_rque, _i) (&((_rque)->swq.swbuff[(_i)])) ++ ++ ++/* transimit packet descriptor (tpd) ring */ ++struct alx_tpd_queue { ++ struct alx_buffer *tpbuff; ++ union alx_tpdesc *tpdesc; /* virtual address */ ++ dma_addr_t tpdma; /* physical address */ ++ ++ u16 size; /* length in bytes */ ++ u16 count; /* number of descriptors in the ring */ ++ u16 produce_idx; ++ u16 consume_idx; ++ u16 last_produce_idx; ++}; ++ ++/* tx queue */ ++struct alx_tx_queue { ++ struct device *dev; /* device for dma mapping */ ++ struct net_device *netdev; /* netdev ring belongs to */ ++ struct alx_tpd_queue tpq; ++ struct alx_msix_param *msix; ++ ++ u16 que_idx; /* needed for multiqueue queue management */ ++ u16 max_packets; /* max packets per interrupt */ ++ u16 produce_reg; ++ u16 consume_reg; ++}; ++#define GET_TP_BUFFER(_tque, _i) (&((_tque)->tpq.tpbuff[(_i)])) ++ ++ ++/* ++ * definition for array allocations. ++ */ ++#define ALX_MAX_MSIX_INTRS 16 ++#define ALX_MAX_RX_QUEUES 8 ++#define ALX_MAX_TX_QUEUES 4 ++ ++enum alx_msix_type { ++ alx_msix_type_rx, ++ alx_msix_type_tx, ++ alx_msix_type_other, ++}; ++#define ALX_MSIX_TYPE_OTH_TIMER 0 ++#define ALX_MSIX_TYPE_OTH_ALERT 1 ++#define ALX_MSIX_TYPE_OTH_SMB 2 ++#define ALX_MSIX_TYPE_OTH_PHY 3 ++ ++/* ALX_MAX_MSIX_INTRS of these are allocated, ++ * but we only use one per queue-specific vector. ++ */ ++struct alx_msix_param { ++ struct alx_adapter *adpt; ++ unsigned int vec_idx; /* index in HW interrupt vector */ ++ char name[IFNAMSIZ + 9]; ++ ++ /* msix interrupts for queue */ ++ u8 rx_map[ALX_MAX_RX_QUEUES]; ++ u8 tx_map[ALX_MAX_TX_QUEUES]; ++ u8 rx_count; /* Rx ring count assigned to this vector */ ++ u8 tx_count; /* Tx ring count assigned to this vector */ ++ ++ struct napi_struct napi; ++ cpumask_var_t affinity_mask; ++ u32 flags; ++}; ++ ++#define ALX_MSIX_FLAG_RX0 0x00000001 ++#define ALX_MSIX_FLAG_RX1 0x00000002 ++#define ALX_MSIX_FLAG_RX2 0x00000004 ++#define ALX_MSIX_FLAG_RX3 0x00000008 ++#define ALX_MSIX_FLAG_RX4 0x00000010 ++#define ALX_MSIX_FLAG_RX5 0x00000020 ++#define ALX_MSIX_FLAG_RX6 0x00000040 ++#define ALX_MSIX_FLAG_RX7 0x00000080 ++#define ALX_MSIX_FLAG_TX0 0x00000100 ++#define ALX_MSIX_FLAG_TX1 0x00000200 ++#define ALX_MSIX_FLAG_TX2 0x00000400 ++#define ALX_MSIX_FLAG_TX3 0x00000800 ++#define ALX_MSIX_FLAG_TIMER 0x00001000 ++#define ALX_MSIX_FLAG_ALERT 0x00002000 ++#define ALX_MSIX_FLAG_SMB 0x00004000 ++#define ALX_MSIX_FLAG_PHY 0x00008000 ++ ++#define ALX_MSIX_FLAG_RXS (\ ++ ALX_MSIX_FLAG_RX0 |\ ++ ALX_MSIX_FLAG_RX1 |\ ++ ALX_MSIX_FLAG_RX2 |\ ++ ALX_MSIX_FLAG_RX3 |\ ++ ALX_MSIX_FLAG_RX4 |\ ++ ALX_MSIX_FLAG_RX5 |\ ++ ALX_MSIX_FLAG_RX6 |\ ++ ALX_MSIX_FLAG_RX7) ++#define ALX_MSIX_FLAG_TXS (\ ++ ALX_MSIX_FLAG_TX0 |\ ++ ALX_MSIX_FLAG_TX1 |\ ++ ALX_MSIX_FLAG_TX2 |\ ++ ALX_MSIX_FLAG_TX3) ++#define ALX_MSIX_FLAG_ALL (\ ++ ALX_MSIX_FLAG_RXS |\ ++ ALX_MSIX_FLAG_TXS |\ ++ ALX_MSIX_FLAG_TIMER |\ ++ ALX_MSIX_FLAG_ALERT |\ ++ ALX_MSIX_FLAG_SMB |\ ++ ALX_MSIX_FLAG_PHY) ++ ++#define CHK_MSIX_FLAG(_flag) CHK_FLAG(msix, MSIX, _flag) ++#define SET_MSIX_FLAG(_flag) SET_FLAG(msix, MSIX, _flag) ++#define CLI_MSIX_FLAG(_flag) CLI_FLAG(msix, MSIX, _flag) ++ ++/* ++ *board specific private data structure ++ */ ++struct alx_adapter { ++ struct net_device *netdev; ++ struct pci_dev *pdev; ++ struct net_device_stats net_stats; ++ bool netdev_registered; ++ u16 bd_number; /* board number;*/ ++ ++ struct alx_msix_param *msix[ALX_MAX_MSIX_INTRS]; ++ struct msix_entry *msix_entries; ++ int num_msix_rxques; ++ int num_msix_txques; ++ int num_msix_noques; /* true count of msix_noques for device */ ++ int num_msix_intrs; ++ ++ int min_msix_intrs; ++ int max_msix_intrs; ++ ++ /* All Descriptor memory */ ++ struct alx_ring_header ring_header; ++ ++ /* TX */ ++ struct alx_tx_queue *tx_queue[ALX_MAX_TX_QUEUES]; ++ /* RX */ ++ struct alx_rx_queue *rx_queue[ALX_MAX_RX_QUEUES]; ++ ++ u16 num_txques; ++ u16 num_rxques; /* equal max(num_hw_rxques, num_sw_rxques) */ ++ u16 num_hw_rxques; ++ u16 num_sw_rxques; ++ u16 max_rxques; ++ u16 max_txques; ++ ++ u16 num_txdescs; ++ u16 num_rxdescs; ++ ++ u32 rxbuf_size; ++ ++ struct alx_cmb cmb; ++ struct alx_smb smb; ++ ++ /* structs defined in alx_hw.h */ ++ struct alx_hw hw; ++ struct alx_hw_stats hw_stats; ++ ++ u32 *config_space; ++ ++ struct work_struct alx_task; ++ struct timer_list alx_timer; ++ ++ unsigned long link_jiffies; ++ ++ u32 wol; ++ spinlock_t tx_lock; ++ spinlock_t rx_lock; ++ atomic_t irq_sem; ++ ++ u16 msg_enable; ++ unsigned long flags[2]; ++}; ++ ++#define ALX_ADPT_FLAG_0_MSI_CAP 0x00000001 ++#define ALX_ADPT_FLAG_0_MSI_EN 0x00000002 ++#define ALX_ADPT_FLAG_0_MSIX_CAP 0x00000004 ++#define ALX_ADPT_FLAG_0_MSIX_EN 0x00000008 ++#define ALX_ADPT_FLAG_0_MRQ_CAP 0x00000010 ++#define ALX_ADPT_FLAG_0_MRQ_EN 0x00000020 ++#define ALX_ADPT_FLAG_0_MTQ_CAP 0x00000040 ++#define ALX_ADPT_FLAG_0_MTQ_EN 0x00000080 ++#define ALX_ADPT_FLAG_0_SRSS_CAP 0x00000100 ++#define ALX_ADPT_FLAG_0_SRSS_EN 0x00000200 ++#define ALX_ADPT_FLAG_0_FIXED_MSIX 0x00000400 ++ ++#define ALX_ADPT_FLAG_0_TASK_REINIT_REQ 0x00010000 /* reinit */ ++#define ALX_ADPT_FLAG_0_TASK_LSC_REQ 0x00020000 ++ ++#define ALX_ADPT_FLAG_1_STATE_TESTING 0x00000001 ++#define ALX_ADPT_FLAG_1_STATE_RESETTING 0x00000002 ++#define ALX_ADPT_FLAG_1_STATE_DOWN 0x00000004 ++#define ALX_ADPT_FLAG_1_STATE_WATCH_DOG 0x00000008 ++#define ALX_ADPT_FLAG_1_STATE_DIAG_RUNNING 0x00000010 ++#define ALX_ADPT_FLAG_1_STATE_INACTIVE 0x00000020 ++ ++ ++#define CHK_ADPT_FLAG(_idx, _flag) \ ++ CHK_FLAG_ARRAY(adpt, _idx, ADPT, _flag) ++#define SET_ADPT_FLAG(_idx, _flag) \ ++ SET_FLAG_ARRAY(adpt, _idx, ADPT, _flag) ++#define CLI_ADPT_FLAG(_idx, _flag) \ ++ CLI_FLAG_ARRAY(adpt, _idx, ADPT, _flag) ++ ++/* default to trying for four seconds */ ++#define ALX_TRY_LINK_TIMEOUT (4 * HZ) ++ ++ ++#define ALX_OPEN_CTRL_IRQ_EN 0x00000001 ++#define ALX_OPEN_CTRL_RESET_MAC 0x00000002 ++#define ALX_OPEN_CTRL_RESET_PHY 0x00000004 ++#define ALX_OPEN_CTRL_RESET_ALL (\ ++ ALX_OPEN_CTRL_RESET_MAC |\ ++ ALX_OPEN_CTRL_RESET_PHY) ++ ++/* needed by alx_ethtool.c */ ++extern char alx_drv_name[]; ++extern void alx_reinit_locked(struct alx_adapter *adpt); ++extern void alx_set_ethtool_ops(struct net_device *netdev); ++#ifdef ETHTOOL_OPS_COMPAT ++extern int ethtool_ioctl(struct ifreq *ifr); ++#endif ++ ++#endif /* _ALX_H_ */ +diff --git a/drivers/net/ethernet/atheros/alx/alx_ethtool.c b/drivers/net/ethernet/atheros/alx/alx_ethtool.c +new file mode 100644 +index 0000000..c044133 +--- /dev/null ++++ b/drivers/net/ethernet/atheros/alx/alx_ethtool.c +@@ -0,0 +1,519 @@ ++/* ++ * Copyright (c) 2012 Qualcomm Atheros, Inc. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include "alx.h" ++#include "alx_hwcom.h" ++ ++#ifdef ETHTOOL_OPS_COMPAT ++#include "alx_compat_ethtool.c" ++#endif ++ ++ ++static int alx_get_settings(struct net_device *netdev, ++ struct ethtool_cmd *ecmd) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ u32 link_speed = hw->link_speed; ++ bool link_up = hw->link_up; ++ ++ ecmd->supported = (SUPPORTED_10baseT_Half | ++ SUPPORTED_10baseT_Full | ++ SUPPORTED_100baseT_Half | ++ SUPPORTED_100baseT_Full | ++ SUPPORTED_Autoneg | ++ SUPPORTED_TP); ++ if (CHK_HW_FLAG(GIGA_CAP)) ++ ecmd->supported |= SUPPORTED_1000baseT_Full; ++ ++ ecmd->advertising = ADVERTISED_TP; ++ ++ ecmd->advertising |= ADVERTISED_Autoneg; ++ ecmd->advertising |= hw->autoneg_advertised; ++ ++ ecmd->port = PORT_TP; ++ ecmd->phy_address = 0; ++ ecmd->autoneg = AUTONEG_ENABLE; ++ ecmd->transceiver = XCVR_INTERNAL; ++ ++ if (!in_interrupt()) { ++ hw->cbs.check_phy_link(hw, &link_speed, &link_up); ++ hw->link_speed = link_speed; ++ hw->link_up = link_up; ++ } ++ ++ if (link_up) { ++ switch (link_speed) { ++ case ALX_LINK_SPEED_10_HALF: ++ ethtool_cmd_speed_set(ecmd, SPEED_10); ++ ecmd->duplex = DUPLEX_HALF; ++ break; ++ case ALX_LINK_SPEED_10_FULL: ++ ethtool_cmd_speed_set(ecmd, SPEED_10); ++ ecmd->duplex = DUPLEX_FULL; ++ break; ++ case ALX_LINK_SPEED_100_HALF: ++ ethtool_cmd_speed_set(ecmd, SPEED_100); ++ ecmd->duplex = DUPLEX_HALF; ++ break; ++ case ALX_LINK_SPEED_100_FULL: ++ ethtool_cmd_speed_set(ecmd, SPEED_100); ++ ecmd->duplex = DUPLEX_FULL; ++ break; ++ case ALX_LINK_SPEED_1GB_FULL: ++ ethtool_cmd_speed_set(ecmd, SPEED_1000); ++ ecmd->duplex = DUPLEX_FULL; ++ break; ++ default: ++ ecmd->speed = -1; ++ ecmd->duplex = -1; ++ break; ++ } ++ } else { ++ ethtool_cmd_speed_set(ecmd, -1); ++ ecmd->duplex = -1; ++ } ++ ++ return 0; ++} ++ ++ ++static int alx_set_settings(struct net_device *netdev, ++ struct ethtool_cmd *ecmd) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ u32 advertised, old; ++ int error = 0; ++ ++ while (CHK_ADPT_FLAG(1, STATE_RESETTING)) ++ msleep(20); ++ SET_ADPT_FLAG(1, STATE_RESETTING); ++ ++ old = hw->autoneg_advertised; ++ advertised = 0; ++ if (ecmd->autoneg == AUTONEG_ENABLE) { ++ advertised = ALX_LINK_SPEED_DEFAULT; ++ } else { ++ u32 speed = ethtool_cmd_speed(ecmd); ++ if (speed == SPEED_1000) { ++ if (ecmd->duplex != DUPLEX_FULL) { ++ dev_warn(&adpt->pdev->dev, ++ "1000M half is invalid\n"); ++ CLI_ADPT_FLAG(1, STATE_RESETTING); ++ return -EINVAL; ++ } ++ advertised = ALX_LINK_SPEED_1GB_FULL; ++ } else if (speed == SPEED_100) { ++ if (ecmd->duplex == DUPLEX_FULL) ++ advertised = ALX_LINK_SPEED_100_FULL; ++ else ++ advertised = ALX_LINK_SPEED_100_HALF; ++ } else { ++ if (ecmd->duplex == DUPLEX_FULL) ++ advertised = ALX_LINK_SPEED_10_FULL; ++ else ++ advertised = ALX_LINK_SPEED_10_HALF; ++ } ++ } ++ ++ if (hw->autoneg_advertised == advertised) { ++ CLI_ADPT_FLAG(1, STATE_RESETTING); ++ return error; ++ } ++ ++ error = hw->cbs.setup_phy_link_speed(hw, advertised, true, ++ !hw->disable_fc_autoneg); ++ if (error) { ++ dev_err(&adpt->pdev->dev, ++ "setup link failed with code %d\n", error); ++ hw->cbs.setup_phy_link_speed(hw, old, true, ++ !hw->disable_fc_autoneg); ++ } ++ CLI_ADPT_FLAG(1, STATE_RESETTING); ++ return error; ++} ++ ++ ++static void alx_get_pauseparam(struct net_device *netdev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ ++ ++ if (hw->disable_fc_autoneg || ++ hw->cur_fc_mode == alx_fc_none) ++ pause->autoneg = 0; ++ else ++ pause->autoneg = 1; ++ ++ if (hw->cur_fc_mode == alx_fc_rx_pause) { ++ pause->rx_pause = 1; ++ } else if (hw->cur_fc_mode == alx_fc_tx_pause) { ++ pause->tx_pause = 1; ++ } else if (hw->cur_fc_mode == alx_fc_full) { ++ pause->rx_pause = 1; ++ pause->tx_pause = 1; ++ } ++} ++ ++ ++static int alx_set_pauseparam(struct net_device *netdev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ enum alx_fc_mode req_fc_mode; ++ bool disable_fc_autoneg; ++ int retval; ++ ++ while (CHK_ADPT_FLAG(1, STATE_RESETTING)) ++ msleep(20); ++ SET_ADPT_FLAG(1, STATE_RESETTING); ++ ++ req_fc_mode = hw->req_fc_mode; ++ disable_fc_autoneg = hw->disable_fc_autoneg; ++ ++ ++ if (pause->autoneg != AUTONEG_ENABLE) ++ disable_fc_autoneg = true; ++ else ++ disable_fc_autoneg = false; ++ ++ if ((pause->rx_pause && pause->tx_pause) || pause->autoneg) ++ req_fc_mode = alx_fc_full; ++ else if (pause->rx_pause && !pause->tx_pause) ++ req_fc_mode = alx_fc_rx_pause; ++ else if (!pause->rx_pause && pause->tx_pause) ++ req_fc_mode = alx_fc_tx_pause; ++ else if (!pause->rx_pause && !pause->tx_pause) ++ req_fc_mode = alx_fc_none; ++ else ++ return -EINVAL; ++ ++ if ((hw->req_fc_mode != req_fc_mode) || ++ (hw->disable_fc_autoneg != disable_fc_autoneg)) { ++ hw->req_fc_mode = req_fc_mode; ++ hw->disable_fc_autoneg = disable_fc_autoneg; ++ if (!hw->disable_fc_autoneg) ++ retval = hw->cbs.setup_phy_link(hw, ++ hw->autoneg_advertised, true, true); ++ ++ if (hw->cbs.config_fc) ++ hw->cbs.config_fc(hw); ++ } ++ ++ CLI_ADPT_FLAG(1, STATE_RESETTING); ++ return 0; ++} ++ ++ ++static u32 alx_get_msglevel(struct net_device *netdev) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ return adpt->msg_enable; ++} ++ ++ ++static void alx_set_msglevel(struct net_device *netdev, u32 data) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ adpt->msg_enable = data; ++} ++ ++ ++static int alx_get_regs_len(struct net_device *netdev) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ return hw->hwreg_sz * sizeof(32); ++} ++ ++ ++static void alx_get_regs(struct net_device *netdev, ++ struct ethtool_regs *regs, void *buff) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ ++ regs->version = 0; ++ ++ memset(buff, 0, hw->hwreg_sz * sizeof(u32)); ++ if (hw->cbs.get_ethtool_regs) ++ hw->cbs.get_ethtool_regs(hw, buff); ++} ++ ++ ++static int alx_get_eeprom_len(struct net_device *netdev) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ return hw->eeprom_sz; ++} ++ ++ ++static int alx_get_eeprom(struct net_device *netdev, ++ struct ethtool_eeprom *eeprom, u8 *bytes) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ bool eeprom_exist = false; ++ u32 *eeprom_buff; ++ int first_dword, last_dword; ++ int retval = 0; ++ int i; ++ ++ if (eeprom->len == 0) ++ return -EINVAL; ++ ++ if (hw->cbs.check_nvram) ++ hw->cbs.check_nvram(hw, &eeprom_exist); ++ if (!eeprom_exist) ++ return -EOPNOTSUPP; ++ ++ eeprom->magic = adpt->pdev->vendor | ++ (adpt->pdev->device << 16); ++ ++ first_dword = eeprom->offset >> 2; ++ last_dword = (eeprom->offset + eeprom->len - 1) >> 2; ++ ++ eeprom_buff = kmalloc(sizeof(u32) * ++ (last_dword - first_dword + 1), GFP_KERNEL); ++ if (eeprom_buff == NULL) ++ return -ENOMEM; ++ ++ for (i = first_dword; i < last_dword; i++) { ++ if (hw->cbs.read_nvram) { ++ retval = hw->cbs.read_nvram(hw, i*4, ++ &(eeprom_buff[i-first_dword])); ++ if (retval) { ++ retval = -EIO; ++ goto out; ++ } ++ } ++ } ++ ++ /* Device's eeprom is always little-endian, word addressable */ ++ for (i = 0; i < last_dword - first_dword; i++) ++ le32_to_cpus(&eeprom_buff[i]); ++ ++ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3), eeprom->len); ++out: ++ kfree(eeprom_buff); ++ return retval; ++} ++ ++ ++static int alx_set_eeprom(struct net_device *netdev, ++ struct ethtool_eeprom *eeprom, u8 *bytes) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ bool eeprom_exist = false; ++ u32 *eeprom_buff; ++ u32 *ptr; ++ int first_dword, last_dword; ++ int retval = 0; ++ int i; ++ ++ if (eeprom->len == 0) ++ return -EINVAL; ++ ++ if (hw->cbs.check_nvram) ++ hw->cbs.check_nvram(hw, &eeprom_exist); ++ if (!eeprom_exist) ++ return -EOPNOTSUPP; ++ ++ ++ if (eeprom->magic != (adpt->pdev->vendor | ++ (adpt->pdev->device << 16))) ++ return -EINVAL; ++ ++ first_dword = eeprom->offset >> 2; ++ last_dword = (eeprom->offset + eeprom->len - 1) >> 2; ++ eeprom_buff = kmalloc(ALX_MAX_EEPROM_LEN, GFP_KERNEL); ++ if (eeprom_buff == NULL) ++ return -ENOMEM; ++ ++ ptr = (u32 *)eeprom_buff; ++ ++ if (eeprom->offset & 3) { ++ /* need read/modify/write of first changed EEPROM word */ ++ /* only the second byte of the word is being modified */ ++ if (hw->cbs.read_nvram) { ++ retval = hw->cbs.read_nvram(hw, first_dword * 4, ++ &(eeprom_buff[0])); ++ if (retval) { ++ retval = -EIO; ++ goto out; ++ } ++ } ++ ptr++; ++ } ++ ++ if (((eeprom->offset + eeprom->len) & 3)) { ++ /* need read/modify/write of last changed EEPROM word */ ++ /* only the first byte of the word is being modified */ ++ if (hw->cbs.read_nvram) { ++ retval = hw->cbs.read_nvram(hw, last_dword * 4, ++ &(eeprom_buff[last_dword - first_dword])); ++ if (retval) { ++ retval = -EIO; ++ goto out; ++ } ++ } ++ } ++ ++ /* Device's eeprom is always little-endian, word addressable */ ++ memcpy(ptr, bytes, eeprom->len); ++ for (i = 0; i < last_dword - first_dword + 1; i++) { ++ if (hw->cbs.write_nvram) { ++ retval = hw->cbs.write_nvram(hw, (first_dword + i) * 4, ++ eeprom_buff[i]); ++ if (retval) { ++ retval = -EIO; ++ goto out; ++ } ++ } ++ } ++out: ++ kfree(eeprom_buff); ++ return retval; ++} ++ ++ ++static void alx_get_drvinfo(struct net_device *netdev, ++ struct ethtool_drvinfo *drvinfo) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ ++ strlcpy(drvinfo->driver, alx_drv_name, sizeof(drvinfo->driver)); ++ strlcpy(drvinfo->fw_version, "alx", 32); ++ strlcpy(drvinfo->bus_info, pci_name(adpt->pdev), ++ sizeof(drvinfo->bus_info)); ++ drvinfo->n_stats = 0; ++ drvinfo->testinfo_len = 0; ++ drvinfo->regdump_len = adpt->hw.hwreg_sz; ++ drvinfo->eedump_len = adpt->hw.eeprom_sz; ++} ++ ++ ++static int alx_wol_exclusion(struct alx_adapter *adpt, ++ struct ethtool_wolinfo *wol) ++{ ++ struct alx_hw *hw = &adpt->hw; ++ int retval = 1; ++ ++ /* WOL not supported except for the following */ ++ switch (hw->pci_devid) { ++ case ALX_DEV_ID_AR8131: ++ case ALX_DEV_ID_AR8132: ++ case ALX_DEV_ID_AR8151_V1: ++ case ALX_DEV_ID_AR8151_V2: ++ case ALX_DEV_ID_AR8152_V1: ++ case ALX_DEV_ID_AR8152_V2: ++ case ALX_DEV_ID_AR8161: ++ case ALX_DEV_ID_AR8162: ++ retval = 0; ++ break; ++ default: ++ wol->supported = 0; ++ } ++ ++ return retval; ++} ++ ++ ++static void alx_get_wol(struct net_device *netdev, ++ struct ethtool_wolinfo *wol) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ ++ wol->supported = WAKE_MAGIC | WAKE_PHY; ++ wol->wolopts = 0; ++ ++ if (adpt->wol & ALX_WOL_MAGIC) ++ wol->wolopts |= WAKE_MAGIC; ++ if (adpt->wol & ALX_WOL_PHY) ++ wol->wolopts |= WAKE_PHY; ++ ++ netif_info(adpt, wol, adpt->netdev, ++ "wol->wolopts = %x\n", wol->wolopts); ++} ++ ++ ++static int alx_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ ++ if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | ++ WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)) ++ return -EOPNOTSUPP; ++ ++ if (alx_wol_exclusion(adpt, wol)) ++ return wol->wolopts ? -EOPNOTSUPP : 0; ++ ++ adpt->wol = 0; ++ ++ if (wol->wolopts & WAKE_MAGIC) ++ adpt->wol |= ALX_WOL_MAGIC; ++ if (wol->wolopts & WAKE_PHY) ++ adpt->wol |= ALX_WOL_PHY; ++ ++ device_set_wakeup_enable(&adpt->pdev->dev, adpt->wol); ++ ++ return 0; ++} ++ ++ ++static int alx_nway_reset(struct net_device *netdev) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ if (netif_running(netdev)) ++ alx_reinit_locked(adpt); ++ return 0; ++} ++ ++ ++static const struct ethtool_ops alx_ethtool_ops = { ++ .get_settings = alx_get_settings, ++ .set_settings = alx_set_settings, ++ .get_pauseparam = alx_get_pauseparam, ++ .set_pauseparam = alx_set_pauseparam, ++ .get_drvinfo = alx_get_drvinfo, ++ .get_regs_len = alx_get_regs_len, ++ .get_regs = alx_get_regs, ++ .get_wol = alx_get_wol, ++ .set_wol = alx_set_wol, ++ .get_msglevel = alx_get_msglevel, ++ .set_msglevel = alx_set_msglevel, ++ .nway_reset = alx_nway_reset, ++ .get_link = ethtool_op_get_link, ++ .get_eeprom_len = alx_get_eeprom_len, ++ .get_eeprom = alx_get_eeprom, ++ .set_eeprom = alx_set_eeprom, ++}; ++ ++ ++void alx_set_ethtool_ops(struct net_device *netdev) ++{ ++ SET_ETHTOOL_OPS(netdev, &alx_ethtool_ops); ++} +diff --git a/drivers/net/ethernet/atheros/alx/alx_hwcom.h b/drivers/net/ethernet/atheros/alx/alx_hwcom.h +new file mode 100644 +index 0000000..d3bd2f1 +--- /dev/null ++++ b/drivers/net/ethernet/atheros/alx/alx_hwcom.h +@@ -0,0 +1,187 @@ ++/* ++ * Copyright (c) 2012 Qualcomm Atheros, Inc. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _ALX_HWCOMMON_H_ ++#define _ALX_HWCOMMON_H_ ++ ++#include ++#include "alx_sw.h" ++ ++ ++#define BIT_ALL 0xffffffffUL ++ ++#define ASHFT31(_x) ((_x) << 31) ++#define ASHFT30(_x) ((_x) << 30) ++#define ASHFT29(_x) ((_x) << 29) ++#define ASHFT28(_x) ((_x) << 28) ++#define ASHFT27(_x) ((_x) << 27) ++#define ASHFT26(_x) ((_x) << 26) ++#define ASHFT25(_x) ((_x) << 25) ++#define ASHFT24(_x) ((_x) << 24) ++#define ASHFT23(_x) ((_x) << 23) ++#define ASHFT22(_x) ((_x) << 22) ++#define ASHFT21(_x) ((_x) << 21) ++#define ASHFT20(_x) ((_x) << 20) ++#define ASHFT19(_x) ((_x) << 19) ++#define ASHFT18(_x) ((_x) << 18) ++#define ASHFT17(_x) ((_x) << 17) ++#define ASHFT16(_x) ((_x) << 16) ++#define ASHFT15(_x) ((_x) << 15) ++#define ASHFT14(_x) ((_x) << 14) ++#define ASHFT13(_x) ((_x) << 13) ++#define ASHFT12(_x) ((_x) << 12) ++#define ASHFT11(_x) ((_x) << 11) ++#define ASHFT10(_x) ((_x) << 10) ++#define ASHFT9(_x) ((_x) << 9) ++#define ASHFT8(_x) ((_x) << 8) ++#define ASHFT7(_x) ((_x) << 7) ++#define ASHFT6(_x) ((_x) << 6) ++#define ASHFT5(_x) ((_x) << 5) ++#define ASHFT4(_x) ((_x) << 4) ++#define ASHFT3(_x) ((_x) << 3) ++#define ASHFT2(_x) ((_x) << 2) ++#define ASHFT1(_x) ((_x) << 1) ++#define ASHFT0(_x) ((_x) << 0) ++ ++ ++#define FIELD_GETX(_x, _name) (((_x) & (_name##_MASK)) >> (_name##_SHIFT)) ++#define FIELD_SETS(_x, _name, _v) (\ ++(_x) = \ ++((_x) & ~(_name##_MASK)) |\ ++(((u16)(_v) << (_name##_SHIFT)) & (_name##_MASK))) ++#define FIELD_SETL(_x, _name, _v) (\ ++(_x) = \ ++((_x) & ~(_name##_MASK)) |\ ++(((u32)(_v) << (_name##_SHIFT)) & (_name##_MASK))) ++#define FIELDL(_name, _v) (((u32)(_v) << (_name##_SHIFT)) & (_name##_MASK)) ++#define FIELDS(_name, _v) (((u16)(_v) << (_name##_SHIFT)) & (_name##_MASK)) ++ ++ ++ ++#define LX_SWAP_DW(_x) (\ ++ (((_x) << 24) & 0xFF000000UL) |\ ++ (((_x) << 8) & 0x00FF0000UL) |\ ++ (((_x) >> 8) & 0x0000FF00UL) |\ ++ (((_x) >> 24) & 0x000000FFUL)) ++ ++#define LX_SWAP_W(_x) (\ ++ (((_x) >> 8) & 0x00FFU) |\ ++ (((_x) << 8) & 0xFF00U)) ++ ++ ++#define LX_ERR_SUCCESS 0x0000 ++#define LX_ERR_ALOAD 0x0001 ++#define LX_ERR_RSTMAC 0x0002 ++#define LX_ERR_PARM 0x0003 ++#define LX_ERR_MIIBUSY 0x0004 ++ ++/* link capability */ ++#define LX_LC_10H 0x01 ++#define LX_LC_10F 0x02 ++#define LX_LC_100H 0x04 ++#define LX_LC_100F 0x08 ++#define LX_LC_1000F 0x10 ++#define LX_LC_ALL \ ++ (LX_LC_10H|LX_LC_10F|LX_LC_100H|LX_LC_100F|LX_LC_1000F) ++ ++/* options for MAC contrl */ ++#define LX_MACSPEED_1000 BIT(0) /* 1:1000M, 0:10/100M */ ++#define LX_MACDUPLEX_FULL BIT(1) /* 1:full, 0:half */ ++#define LX_FLT_BROADCAST BIT(2) /* 1:enable rx-broadcast */ ++#define LX_FLT_MULTI_ALL BIT(3) ++#define LX_FLT_DIRECT BIT(4) ++#define LX_FLT_PROMISC BIT(5) ++#define LX_FC_TXEN BIT(6) ++#define LX_FC_RXEN BIT(7) ++#define LX_VLAN_STRIP BIT(8) ++#define LX_LOOPBACK BIT(9) ++#define LX_ADD_FCS BIT(10) ++#define LX_SINGLE_PAUSE BIT(11) ++ ++ ++/* interop between drivers */ ++#define LX_DRV_TYPE_MASK ASHFT27(0x1FUL) ++#define LX_DRV_TYPE_SHIFT 27 ++#define LX_DRV_TYPE_UNKNOWN 0 ++#define LX_DRV_TYPE_BIOS 1 ++#define LX_DRV_TYPE_BTROM 2 ++#define LX_DRV_TYPE_PKT 3 ++#define LX_DRV_TYPE_NDS2 4 ++#define LX_DRV_TYPE_UEFI 5 ++#define LX_DRV_TYPE_NDS5 6 ++#define LX_DRV_TYPE_NDS62 7 ++#define LX_DRV_TYPE_NDS63 8 ++#define LX_DRV_TYPE_LNX 9 ++#define LX_DRV_TYPE_ODI16 10 ++#define LX_DRV_TYPE_ODI32 11 ++#define LX_DRV_TYPE_FRBSD 12 ++#define LX_DRV_TYPE_NTBSD 13 ++#define LX_DRV_TYPE_WCE 14 ++#define LX_DRV_PHY_AUTO BIT(26) /* 1:auto, 0:force */ ++#define LX_DRV_PHY_1000 BIT(25) ++#define LX_DRV_PHY_100 BIT(24) ++#define LX_DRV_PHY_10 BIT(23) ++#define LX_DRV_PHY_DUPLEX BIT(22) /* 1:full, 0:half */ ++#define LX_DRV_PHY_FC BIT(21) /* 1:en flow control */ ++#define LX_DRV_PHY_MASK ASHFT21(0x1FUL) ++#define LX_DRV_PHY_SHIFT 21 ++#define LX_DRV_PHY_UNKNOWN 0 ++#define LX_DRV_DISABLE BIT(18) ++#define LX_DRV_WOLS5_EN BIT(17) ++#define LX_DRV_WOLS5_BIOS_EN BIT(16) ++#define LX_DRV_AZ_EN BIT(12) ++#define LX_DRV_WOLPATTERN_EN BIT(11) ++#define LX_DRV_WOLLINKUP_EN BIT(10) ++#define LX_DRV_WOLMAGIC_EN BIT(9) ++#define LX_DRV_WOLCAP_BIOS_EN BIT(8) ++#define LX_DRV_ASPM_SPD1000LMT_MASK ASHFT4(3UL) ++#define LX_DRV_ASPM_SPD1000LMT_SHIFT 4 ++#define LX_DRV_ASPM_SPD1000LMT_100M 0 ++#define LX_DRV_ASPM_SPD1000LMT_NO 1 ++#define LX_DRV_ASPM_SPD1000LMT_1M 2 ++#define LX_DRV_ASPM_SPD1000LMT_10M 3 ++#define LX_DRV_ASPM_SPD100LMT_MASK ASHFT2(3UL) ++#define LX_DRV_ASPM_SPD100LMT_SHIFT 2 ++#define LX_DRV_ASPM_SPD100LMT_1M 0 ++#define LX_DRV_ASPM_SPD100LMT_10M 1 ++#define LX_DRV_ASPM_SPD100LMT_100M 2 ++#define LX_DRV_ASPM_SPD100LMT_NO 3 ++#define LX_DRV_ASPM_SPD10LMT_MASK ASHFT0(3UL) ++#define LX_DRV_ASPM_SPD10LMT_SHIFT 0 ++#define LX_DRV_ASPM_SPD10LMT_1M 0 ++#define LX_DRV_ASPM_SPD10LMT_10M 1 ++#define LX_DRV_ASPM_SPD10LMT_100M 2 ++#define LX_DRV_ASPM_SPD10LMT_NO 3 ++ ++/* flag of phy inited */ ++#define LX_PHY_INITED 0x003F ++ ++/* check if the mac address is valid */ ++#define macaddr_valid(_addr) (\ ++ ((*(u8 *)(_addr))&1) == 0 && \ ++ !(*(u32 *)(_addr) == 0 && *((u16 *)(_addr)+2) == 0)) ++ ++#define test_set_or_clear(_val, _ctrl, _flag, _bit) \ ++do { \ ++ if ((_ctrl) & (_flag)) \ ++ (_val) |= (_bit); \ ++ else \ ++ (_val) &= ~(_bit); \ ++} while (0) ++ ++ ++#endif/*_ALX_HWCOMMON_H_*/ ++ +diff --git a/drivers/net/ethernet/atheros/alx/alx_main.c b/drivers/net/ethernet/atheros/alx/alx_main.c +new file mode 100644 +index 0000000..b7ae2ab +--- /dev/null ++++ b/drivers/net/ethernet/atheros/alx/alx_main.c +@@ -0,0 +1,3894 @@ ++/* ++ * Copyright (c) 2012 Qualcomm Atheros, Inc. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include "alx.h" ++#include "alx_hwcom.h" ++ ++char alx_drv_name[] = "alx"; ++static const char alx_drv_description[] = ++ "Qualcomm Atheros(R) " ++ "AR813x/AR815x/AR816x PCI-E Ethernet Network Driver"; ++ ++/* alx_pci_tbl - PCI Device ID Table ++ * ++ * Wildcard entries (PCI_ANY_ID) should come last ++ * Last entry must be all 0s ++ * ++ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, ++ * Class, Class Mask, private data (not used) } ++ */ ++#define ALX_ETHER_DEVICE(device_id) {\ ++ PCI_DEVICE(ALX_VENDOR_ID, device_id)} ++static DEFINE_PCI_DEVICE_TABLE(alx_pci_tbl) = { ++ ALX_ETHER_DEVICE(ALX_DEV_ID_AR8161), ++ ALX_ETHER_DEVICE(ALX_DEV_ID_AR8162), ++ {0,} ++}; ++MODULE_DEVICE_TABLE(pci, alx_pci_tbl); ++MODULE_AUTHOR("Qualcomm Corporation, "); ++MODULE_DESCRIPTION("Qualcomm Atheros Gigabit Ethernet Driver"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_INFO(staging, "Y"); ++ ++static int alx_open_internal(struct alx_adapter *adpt, u32 ctrl); ++static void alx_stop_internal(struct alx_adapter *adpt, u32 ctrl); ++ ++int alx_cfg_r16(const struct alx_hw *hw, int reg, u16 *pval) ++{ ++ if (!(hw && hw->adpt && hw->adpt->pdev)) ++ return -EINVAL; ++ return pci_read_config_word(hw->adpt->pdev, reg, pval); ++} ++ ++ ++int alx_cfg_w16(const struct alx_hw *hw, int reg, u16 val) ++{ ++ if (!(hw && hw->adpt && hw->adpt->pdev)) ++ return -EINVAL; ++ return pci_write_config_word(hw->adpt->pdev, reg, val); ++} ++ ++ ++void alx_mem_flush(const struct alx_hw *hw) ++{ ++ readl(hw->hw_addr); ++} ++ ++ ++void alx_mem_r32(const struct alx_hw *hw, int reg, u32 *val) ++{ ++ if (unlikely(!hw->link_up)) ++ readl(hw->hw_addr + reg); ++ *(u32 *)val = readl(hw->hw_addr + reg); ++} ++ ++ ++void alx_mem_w32(const struct alx_hw *hw, int reg, u32 val) ++{ ++ if (hw->mac_type == alx_mac_l2cb_v20 && reg < 0x1400) ++ readl(hw->hw_addr + reg); ++ writel(val, hw->hw_addr + reg); ++} ++ ++ ++static void alx_mem_r16(const struct alx_hw *hw, int reg, u16 *val) ++{ ++ if (unlikely(!hw->link_up)) ++ readl(hw->hw_addr + reg); ++ *(u16 *)val = readw(hw->hw_addr + reg); ++} ++ ++ ++static void alx_mem_w16(const struct alx_hw *hw, int reg, u16 val) ++{ ++ if (hw->mac_type == alx_mac_l2cb_v20 && reg < 0x1400) ++ readl(hw->hw_addr + reg); ++ writew(val, hw->hw_addr + reg); ++} ++ ++ ++void alx_mem_w8(const struct alx_hw *hw, int reg, u8 val) ++{ ++ if (hw->mac_type == alx_mac_l2cb_v20 && reg < 0x1400) ++ readl(hw->hw_addr + reg); ++ writeb(val, hw->hw_addr + reg); ++} ++ ++ ++/* ++ * alx_hw_printk ++ */ ++void alx_hw_printk(const char *level, const struct alx_hw *hw, ++ const char *fmt, ...) ++{ ++ struct va_format vaf; ++ va_list args; ++ ++ va_start(args, fmt); ++ vaf.fmt = fmt; ++ vaf.va = &args; ++ ++ if (hw && hw->adpt && hw->adpt->netdev) ++ __netdev_printk(level, hw->adpt->netdev, &vaf); ++ else ++ printk("%salx_hw: %pV", level, &vaf); ++ ++ va_end(args); ++} ++ ++ ++/* ++ * alx_validate_mac_addr - Validate MAC address ++ */ ++static int alx_validate_mac_addr(u8 *mac_addr) ++{ ++ int retval = 0; ++ ++ if (mac_addr[0] & 0x01) { ++ printk(KERN_DEBUG "MAC address is multicast\n"); ++ retval = -EADDRNOTAVAIL; ++ } else if (mac_addr[0] == 0xff && mac_addr[1] == 0xff) { ++ printk(KERN_DEBUG "MAC address is broadcast\n"); ++ retval = -EADDRNOTAVAIL; ++ } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && ++ mac_addr[2] == 0 && mac_addr[3] == 0 && ++ mac_addr[4] == 0 && mac_addr[5] == 0) { ++ printk(KERN_DEBUG "MAC address is all zeros\n"); ++ retval = -EADDRNOTAVAIL; ++ } ++ return retval; ++} ++ ++ ++/* ++ * alx_set_mac_type - Sets MAC type ++ */ ++static int alx_set_mac_type(struct alx_adapter *adpt) ++{ ++ struct alx_hw *hw = &adpt->hw; ++ int retval = 0; ++ ++ if (hw->pci_venid == ALX_VENDOR_ID) { ++ switch (hw->pci_devid) { ++ case ALX_DEV_ID_AR8131: ++ hw->mac_type = alx_mac_l1c; ++ break; ++ case ALX_DEV_ID_AR8132: ++ hw->mac_type = alx_mac_l2c; ++ break; ++ case ALX_DEV_ID_AR8151_V1: ++ hw->mac_type = alx_mac_l1d_v1; ++ break; ++ case ALX_DEV_ID_AR8151_V2: ++ /* just use l1d configure */ ++ hw->mac_type = alx_mac_l1d_v2; ++ break; ++ case ALX_DEV_ID_AR8152_V1: ++ hw->mac_type = alx_mac_l2cb_v1; ++ break; ++ case ALX_DEV_ID_AR8152_V2: ++ if (hw->pci_revid == ALX_REV_ID_AR8152_V2_0) ++ hw->mac_type = alx_mac_l2cb_v20; ++ else ++ hw->mac_type = alx_mac_l2cb_v21; ++ break; ++ case ALX_DEV_ID_AR8161: ++ hw->mac_type = alx_mac_l1f; ++ break; ++ case ALX_DEV_ID_AR8162: ++ hw->mac_type = alx_mac_l2f; ++ break; ++ default: ++ retval = -EINVAL; ++ break; ++ } ++ } else { ++ retval = -EINVAL; ++ } ++ ++ netif_info(adpt, hw, adpt->netdev, ++ "found mac: %d, returns: %d\n", hw->mac_type, retval); ++ return retval; ++} ++ ++ ++/* ++ * alx_init_hw_callbacks ++ */ ++static int alx_init_hw_callbacks(struct alx_adapter *adpt) ++{ ++ struct alx_hw *hw = &adpt->hw; ++ int retval = 0; ++ ++ alx_set_mac_type(adpt); ++ ++ switch (hw->mac_type) { ++ case alx_mac_l1f: ++ case alx_mac_l2f: ++ retval = alf_init_hw_callbacks(hw); ++ break; ++ case alx_mac_l1c: ++ case alx_mac_l2c: ++ case alx_mac_l2cb_v1: ++ case alx_mac_l2cb_v20: ++ case alx_mac_l2cb_v21: ++ case alx_mac_l1d_v1: ++ case alx_mac_l1d_v2: ++ retval = alc_init_hw_callbacks(hw); ++ break; ++ default: ++ retval = -EINVAL; ++ break; ++ } ++ return retval; ++} ++ ++ ++void alx_reinit_locked(struct alx_adapter *adpt) ++{ ++ WARN_ON(in_interrupt()); ++ ++ while (CHK_ADPT_FLAG(1, STATE_RESETTING)) ++ msleep(20); ++ SET_ADPT_FLAG(1, STATE_RESETTING); ++ ++ alx_stop_internal(adpt, ALX_OPEN_CTRL_RESET_MAC); ++ alx_open_internal(adpt, ALX_OPEN_CTRL_RESET_MAC); ++ ++ CLI_ADPT_FLAG(1, STATE_RESETTING); ++} ++ ++ ++static void alx_task_schedule(struct alx_adapter *adpt) ++{ ++ if (!CHK_ADPT_FLAG(1, STATE_DOWN) && ++ !CHK_ADPT_FLAG(1, STATE_WATCH_DOG)) { ++ SET_ADPT_FLAG(1, STATE_WATCH_DOG); ++ schedule_work(&adpt->alx_task); ++ } ++} ++ ++ ++static void alx_check_lsc(struct alx_adapter *adpt) ++{ ++ SET_ADPT_FLAG(0, TASK_LSC_REQ); ++ adpt->link_jiffies = jiffies + ALX_TRY_LINK_TIMEOUT; ++ ++ if (!CHK_ADPT_FLAG(1, STATE_DOWN)) ++ alx_task_schedule(adpt); ++} ++ ++ ++/* ++ * alx_tx_timeout - Respond to a Tx Hang ++ */ ++static void alx_tx_timeout(struct net_device *netdev) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ ++ /* Do the reset outside of interrupt context */ ++ if (!CHK_ADPT_FLAG(1, STATE_DOWN)) { ++ SET_ADPT_FLAG(0, TASK_REINIT_REQ); ++ alx_task_schedule(adpt); ++ } ++} ++ ++ ++/* ++ * alx_set_multicase_list - Multicast and Promiscuous mode set ++ */ ++static void alx_set_multicase_list(struct net_device *netdev) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ struct netdev_hw_addr *ha; ++ ++ /* Check for Promiscuous and All Multicast modes */ ++ if (netdev->flags & IFF_PROMISC) { ++ SET_HW_FLAG(PROMISC_EN); ++ } else if (netdev->flags & IFF_ALLMULTI) { ++ SET_HW_FLAG(MULTIALL_EN); ++ CLI_HW_FLAG(PROMISC_EN); ++ } else { ++ CLI_HW_FLAG(MULTIALL_EN); ++ CLI_HW_FLAG(PROMISC_EN); ++ } ++ hw->cbs.config_mac_ctrl(hw); ++ ++ /* clear the old settings from the multicast hash table */ ++ hw->cbs.clear_mc_addr(hw); ++ ++ /* comoute mc addresses' hash value ,and put it into hash table */ ++ netdev_for_each_mc_addr(ha, netdev) ++ hw->cbs.set_mc_addr(hw, ha->addr); ++} ++ ++ ++/* ++ * alx_set_mac - Change the Ethernet Address of the NIC ++ */ ++static int alx_set_mac_address(struct net_device *netdev, void *data) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ struct sockaddr *addr = data; ++ ++ if (!is_valid_ether_addr(addr->sa_data)) ++ return -EADDRNOTAVAIL; ++ ++ if (netif_running(netdev)) ++ return -EBUSY; ++ ++ if (netdev->addr_assign_type & NET_ADDR_RANDOM) ++ netdev->addr_assign_type ^= NET_ADDR_RANDOM; ++ ++ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); ++ memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len); ++ ++ if (hw->cbs.set_mac_addr) ++ hw->cbs.set_mac_addr(hw, hw->mac_addr); ++ return 0; ++} ++ ++ ++/* ++ * Read / Write Ptr Initialize: ++ */ ++static void alx_init_ring_ptrs(struct alx_adapter *adpt) ++{ ++ int i, j; ++ ++ for (i = 0; i < adpt->num_txques; i++) { ++ struct alx_tx_queue *txque = adpt->tx_queue[i]; ++ struct alx_buffer *tpbuf = txque->tpq.tpbuff; ++ txque->tpq.produce_idx = 0; ++ txque->tpq.consume_idx = 0; ++ for (j = 0; j < txque->tpq.count; j++) ++ tpbuf[j].dma = 0; ++ } ++ ++ for (i = 0; i < adpt->num_hw_rxques; i++) { ++ struct alx_rx_queue *rxque = adpt->rx_queue[i]; ++ struct alx_buffer *rfbuf = rxque->rfq.rfbuff; ++ rxque->rrq.produce_idx = 0; ++ rxque->rrq.consume_idx = 0; ++ rxque->rfq.produce_idx = 0; ++ rxque->rfq.consume_idx = 0; ++ for (j = 0; j < rxque->rfq.count; j++) ++ rfbuf[j].dma = 0; ++ } ++ ++ if (CHK_ADPT_FLAG(0, SRSS_EN)) ++ goto srrs_enable; ++ ++ return; ++ ++srrs_enable: ++ for (i = 0; i < adpt->num_sw_rxques; i++) { ++ struct alx_rx_queue *rxque = adpt->rx_queue[i]; ++ rxque->swq.produce_idx = 0; ++ rxque->swq.consume_idx = 0; ++ } ++} ++ ++ ++static void alx_config_rss(struct alx_adapter *adpt) ++{ ++ static const u8 key[40] = { ++ 0xE2, 0x91, 0xD7, 0x3D, 0x18, 0x05, 0xEC, 0x6C, ++ 0x2A, 0x94, 0xB3, 0x0D, 0xA5, 0x4F, 0x2B, 0xEC, ++ 0xEA, 0x49, 0xAF, 0x7C, 0xE2, 0x14, 0xAD, 0x3D, ++ 0xB8, 0x55, 0xAA, 0xBE, 0x6A, 0x3E, 0x67, 0xEA, ++ 0x14, 0x36, 0x4D, 0x17, 0x3B, 0xED, 0x20, 0x0D}; ++ ++ struct alx_hw *hw = &adpt->hw; ++ u32 reta = 0; ++ int i, j; ++ ++ /* initialize rss hash type and idt table size */ ++ hw->rss_hstype = ALX_RSS_HSTYP_ALL_EN; ++ hw->rss_idt_size = 0x100; ++ ++ /* Fill out redirection table */ ++ memcpy(hw->rss_key, key, sizeof(hw->rss_key)); ++ ++ /* Fill out redirection table */ ++ memset(hw->rss_idt, 0x0, sizeof(hw->rss_idt)); ++ for (i = 0, j = 0; i < 256; i++, j++) { ++ if (j == adpt->max_rxques) ++ j = 0; ++ reta |= (j << ((i & 7) * 4)); ++ if ((i & 7) == 7) { ++ hw->rss_idt[i>>3] = reta; ++ reta = 0; ++ } ++ } ++ ++ if (hw->cbs.config_rss) ++ hw->cbs.config_rss(hw, CHK_ADPT_FLAG(0, SRSS_EN)); ++} ++ ++ ++/* ++ * alx_receive_skb ++ */ ++static void alx_receive_skb(struct alx_adapter *adpt, ++ struct sk_buff *skb, ++ u16 vlan_tag, bool vlan_flag) ++{ ++ if (vlan_flag) { ++ u16 vlan; ++ ALX_TAG_TO_VLAN(vlan_tag, vlan); ++ __vlan_hwaccel_put_tag(skb, vlan); ++ } ++ netif_receive_skb(skb); ++} ++ ++ ++static bool alx_get_rrdesc(struct alx_rx_queue *rxque, ++ union alx_sw_rrdesc *srrd) ++{ ++ union alx_rrdesc *hrrd = ++ ALX_RRD(rxque, rxque->rrq.consume_idx); ++ ++ srrd->dfmt.dw0 = le32_to_cpu(hrrd->dfmt.dw0); ++ srrd->dfmt.dw1 = le32_to_cpu(hrrd->dfmt.dw1); ++ srrd->dfmt.dw2 = le32_to_cpu(hrrd->dfmt.dw2); ++ srrd->dfmt.dw3 = le32_to_cpu(hrrd->dfmt.dw3); ++ ++ if (!srrd->genr.update) ++ return false; ++ ++ if (likely(srrd->genr.nor != 1)) { ++ /* TODO support mul rfd*/ ++ printk(KERN_EMERG "Multi rfd not support yet!\n"); ++ } ++ ++ srrd->genr.update = 0; ++ hrrd->dfmt.dw3 = cpu_to_le32(srrd->dfmt.dw3); ++ if (++rxque->rrq.consume_idx == rxque->rrq.count) ++ rxque->rrq.consume_idx = 0; ++ ++ return true; ++} ++ ++ ++static bool alx_set_rfdesc(struct alx_rx_queue *rxque, ++ union alx_sw_rfdesc *srfd) ++{ ++ union alx_rfdesc *hrfd = ++ ALX_RFD(rxque, rxque->rfq.produce_idx); ++ ++ hrfd->qfmt.qw0 = cpu_to_le64(srfd->qfmt.qw0); ++ ++ if (++rxque->rfq.produce_idx == rxque->rfq.count) ++ rxque->rfq.produce_idx = 0; ++ ++ return true; ++} ++ ++ ++static bool alx_set_tpdesc(struct alx_tx_queue *txque, ++ union alx_sw_tpdesc *stpd) ++{ ++ union alx_tpdesc *htpd; ++ ++ txque->tpq.last_produce_idx = txque->tpq.produce_idx; ++ htpd = ALX_TPD(txque, txque->tpq.produce_idx); ++ ++ if (++txque->tpq.produce_idx == txque->tpq.count) ++ txque->tpq.produce_idx = 0; ++ ++ htpd->dfmt.dw0 = cpu_to_le32(stpd->dfmt.dw0); ++ htpd->dfmt.dw1 = cpu_to_le32(stpd->dfmt.dw1); ++ htpd->qfmt.qw1 = cpu_to_le64(stpd->qfmt.qw1); ++ ++ return true; ++} ++ ++ ++static void alx_set_tpdesc_lastfrag(struct alx_tx_queue *txque) ++{ ++ union alx_tpdesc *htpd; ++#define ALX_TPD_LAST_FLAGMENT 0x80000000 ++ htpd = ALX_TPD(txque, txque->tpq.last_produce_idx); ++ htpd->dfmt.dw1 |= cpu_to_le32(ALX_TPD_LAST_FLAGMENT); ++} ++ ++ ++static int alx_refresh_rx_buffer(struct alx_rx_queue *rxque) ++{ ++ struct alx_adapter *adpt = netdev_priv(rxque->netdev); ++ struct alx_hw *hw = &adpt->hw; ++ struct alx_buffer *curr_rxbuf; ++ struct alx_buffer *next_rxbuf; ++ union alx_sw_rfdesc srfd; ++ struct sk_buff *skb; ++ void *skb_data = NULL; ++ u16 count = 0; ++ u16 next_produce_idx; ++ ++ next_produce_idx = rxque->rfq.produce_idx; ++ if (++next_produce_idx == rxque->rfq.count) ++ next_produce_idx = 0; ++ curr_rxbuf = GET_RF_BUFFER(rxque, rxque->rfq.produce_idx); ++ next_rxbuf = GET_RF_BUFFER(rxque, next_produce_idx); ++ ++ /* this always has a blank rx_buffer*/ ++ while (next_rxbuf->dma == 0) { ++ skb = dev_alloc_skb(adpt->rxbuf_size); ++ if (unlikely(!skb)) { ++ alx_err(adpt, "alloc rx buffer failed\n"); ++ break; ++ } ++ ++ /* ++ * Make buffer alignment 2 beyond a 16 byte boundary ++ * this will result in a 16 byte aligned IP header after ++ * the 14 byte MAC header is removed ++ */ ++ skb_data = skb->data; ++ /*skb_reserve(skb, NET_IP_ALIGN);*/ ++ curr_rxbuf->skb = skb; ++ curr_rxbuf->length = adpt->rxbuf_size; ++ curr_rxbuf->dma = dma_map_single(rxque->dev, ++ skb_data, ++ curr_rxbuf->length, ++ DMA_FROM_DEVICE); ++ srfd.genr.addr = curr_rxbuf->dma; ++ alx_set_rfdesc(rxque, &srfd); ++ ++ next_produce_idx = rxque->rfq.produce_idx; ++ if (++next_produce_idx == rxque->rfq.count) ++ next_produce_idx = 0; ++ curr_rxbuf = GET_RF_BUFFER(rxque, rxque->rfq.produce_idx); ++ next_rxbuf = GET_RF_BUFFER(rxque, next_produce_idx); ++ count++; ++ } ++ ++ if (count) { ++ wmb(); ++ alx_mem_w16(hw, rxque->produce_reg, rxque->rfq.produce_idx); ++ netif_info(adpt, rx_err, adpt->netdev, ++ "RX[%d]: prod_reg[%x] = 0x%x, rfq.prod_idx = 0x%x\n", ++ rxque->que_idx, rxque->produce_reg, ++ rxque->rfq.produce_idx, rxque->rfq.produce_idx); ++ } ++ return count; ++} ++ ++ ++static void alx_clean_rfdesc(struct alx_rx_queue *rxque, ++ union alx_sw_rrdesc *srrd) ++{ ++ struct alx_buffer *rfbuf = rxque->rfq.rfbuff; ++ u32 consume_idx = srrd->genr.si; ++ u32 i; ++ ++ for (i = 0; i < srrd->genr.nor; i++) { ++ rfbuf[consume_idx].skb = NULL; ++ if (++consume_idx == rxque->rfq.count) ++ consume_idx = 0; ++ } ++ rxque->rfq.consume_idx = consume_idx; ++} ++ ++ ++static bool alx_dispatch_rx_irq(struct alx_msix_param *msix, ++ struct alx_rx_queue *rxque) ++{ ++ struct alx_adapter *adpt = msix->adpt; ++ struct pci_dev *pdev = adpt->pdev; ++ struct net_device *netdev = adpt->netdev; ++ ++ union alx_sw_rrdesc srrd; ++ struct alx_buffer *rfbuf; ++ struct sk_buff *skb; ++ struct alx_rx_queue *swque; ++ struct alx_sw_buffer *curr_swbuf; ++ struct alx_sw_buffer *next_swbuf; ++ ++ u16 next_produce_idx; ++ u16 count = 0; ++ ++ while (1) { ++ if (!alx_get_rrdesc(rxque, &srrd)) ++ break; ++ ++ if (srrd.genr.res || srrd.genr.lene) { ++ alx_clean_rfdesc(rxque, &srrd); ++ netif_warn(adpt, rx_err, adpt->netdev, ++ "wrong packet! rrd->word3 is 0x%08x\n", ++ srrd.dfmt.dw3); ++ continue; ++ } ++ ++ /* Good Receive */ ++ if (likely(srrd.genr.nor == 1)) { ++ rfbuf = GET_RF_BUFFER(rxque, srrd.genr.si); ++ pci_unmap_single(pdev, rfbuf->dma, ++ rfbuf->length, DMA_FROM_DEVICE); ++ rfbuf->dma = 0; ++ skb = rfbuf->skb; ++ netif_info(adpt, rx_err, adpt->netdev, ++ "skb addr = %p, rxbuf_len = %x\n", ++ skb->data, rfbuf->length); ++ } else { ++ /* TODO */ ++ alx_err(adpt, "Multil rfd not support yet!\n"); ++ break; ++ } ++ alx_clean_rfdesc(rxque, &srrd); ++ ++ skb_put(skb, srrd.genr.pkt_len - ETH_FCS_LEN); ++ skb->protocol = eth_type_trans(skb, netdev); ++ skb_checksum_none_assert(skb); ++ ++ /* start to dispatch */ ++ swque = adpt->rx_queue[srrd.genr.rss_cpu]; ++ next_produce_idx = swque->swq.produce_idx; ++ if (++next_produce_idx == swque->swq.count) ++ next_produce_idx = 0; ++ ++ curr_swbuf = GET_SW_BUFFER(swque, swque->swq.produce_idx); ++ next_swbuf = GET_SW_BUFFER(swque, next_produce_idx); ++ ++ /* ++ * if full, will discard the packet, ++ * and at lease has a blank sw_buffer. ++ */ ++ if (!next_swbuf->skb) { ++ curr_swbuf->skb = skb; ++ curr_swbuf->vlan_tag = srrd.genr.vlan_tag; ++ curr_swbuf->vlan_flag = srrd.genr.vlan_flag; ++ if (++swque->swq.produce_idx == swque->swq.count) ++ swque->swq.produce_idx = 0; ++ } ++ ++ count++; ++ if (count == 32) ++ break; ++ } ++ if (count) ++ alx_refresh_rx_buffer(rxque); ++ return true; ++} ++ ++ ++static bool alx_handle_srx_irq(struct alx_msix_param *msix, ++ struct alx_rx_queue *rxque, ++ int *num_pkts, int max_pkts) ++{ ++ struct alx_adapter *adpt = msix->adpt; ++ struct alx_sw_buffer *swbuf; ++ bool retval = true; ++ ++ while (rxque->swq.consume_idx != rxque->swq.produce_idx) { ++ swbuf = GET_SW_BUFFER(rxque, rxque->swq.consume_idx); ++ ++ alx_receive_skb(adpt, swbuf->skb, (u16)swbuf->vlan_tag, ++ (bool)swbuf->vlan_flag); ++ swbuf->skb = NULL; ++ ++ if (++rxque->swq.consume_idx == rxque->swq.count) ++ rxque->swq.consume_idx = 0; ++ ++ (*num_pkts)++; ++ if (*num_pkts >= max_pkts) { ++ retval = false; ++ break; ++ } ++ } ++ return retval; ++} ++ ++ ++static bool alx_handle_rx_irq(struct alx_msix_param *msix, ++ struct alx_rx_queue *rxque, ++ int *num_pkts, int max_pkts) ++{ ++ struct alx_adapter *adpt = msix->adpt; ++ struct alx_hw *hw = &adpt->hw; ++ struct pci_dev *pdev = adpt->pdev; ++ struct net_device *netdev = adpt->netdev; ++ ++ union alx_sw_rrdesc srrd; ++ struct alx_buffer *rfbuf; ++ struct sk_buff *skb; ++ ++ u16 hw_consume_idx, num_consume_pkts; ++ u16 count = 0; ++ ++ alx_mem_r16(hw, rxque->consume_reg, &hw_consume_idx); ++ num_consume_pkts = (hw_consume_idx > rxque->rrq.consume_idx) ? ++ (hw_consume_idx - rxque->rrq.consume_idx) : ++ (hw_consume_idx + rxque->rrq.count - rxque->rrq.consume_idx); ++ ++ while (1) { ++ if (!num_consume_pkts) ++ break; ++ ++ if (!alx_get_rrdesc(rxque, &srrd)) ++ break; ++ ++ if (srrd.genr.res || srrd.genr.lene) { ++ alx_clean_rfdesc(rxque, &srrd); ++ netif_warn(adpt, rx_err, adpt->netdev, ++ "wrong packet! rrd->word3 is 0x%08x\n", ++ srrd.dfmt.dw3); ++ continue; ++ } ++ ++ /* TODO: Good Receive */ ++ if (likely(srrd.genr.nor == 1)) { ++ rfbuf = GET_RF_BUFFER(rxque, srrd.genr.si); ++ pci_unmap_single(pdev, rfbuf->dma, rfbuf->length, ++ DMA_FROM_DEVICE); ++ rfbuf->dma = 0; ++ skb = rfbuf->skb; ++ } else { ++ /* TODO */ ++ alx_err(adpt, "Multil rfd not support yet!\n"); ++ break; ++ } ++ alx_clean_rfdesc(rxque, &srrd); ++ ++ skb_put(skb, srrd.genr.pkt_len - ETH_FCS_LEN); ++ skb->protocol = eth_type_trans(skb, netdev); ++ skb_checksum_none_assert(skb); ++ alx_receive_skb(adpt, skb, (u16)srrd.genr.vlan_tag, ++ (bool)srrd.genr.vlan_flag); ++ ++ num_consume_pkts--; ++ count++; ++ (*num_pkts)++; ++ if (*num_pkts >= max_pkts) ++ break; ++ } ++ if (count) ++ alx_refresh_rx_buffer(rxque); ++ ++ return true; ++} ++ ++ ++static bool alx_handle_tx_irq(struct alx_msix_param *msix, ++ struct alx_tx_queue *txque) ++{ ++ struct alx_adapter *adpt = msix->adpt; ++ struct alx_hw *hw = &adpt->hw; ++ struct alx_buffer *tpbuf; ++ u16 consume_data; ++ ++ alx_mem_r16(hw, txque->consume_reg, &consume_data); ++ netif_info(adpt, tx_err, adpt->netdev, ++ "TX[%d]: consume_reg[0x%x] = 0x%x, tpq.consume_idx = 0x%x\n", ++ txque->que_idx, txque->consume_reg, consume_data, ++ txque->tpq.consume_idx); ++ ++ ++ while (txque->tpq.consume_idx != consume_data) { ++ tpbuf = GET_TP_BUFFER(txque, txque->tpq.consume_idx); ++ if (tpbuf->dma) { ++ pci_unmap_page(adpt->pdev, tpbuf->dma, tpbuf->length, ++ DMA_TO_DEVICE); ++ tpbuf->dma = 0; ++ } ++ ++ if (tpbuf->skb) { ++ dev_kfree_skb_irq(tpbuf->skb); ++ tpbuf->skb = NULL; ++ } ++ ++ if (++txque->tpq.consume_idx == txque->tpq.count) ++ txque->tpq.consume_idx = 0; ++ } ++ ++ if (netif_queue_stopped(adpt->netdev) && ++ netif_carrier_ok(adpt->netdev)) { ++ netif_wake_queue(adpt->netdev); ++ } ++ return true; ++} ++ ++ ++static irqreturn_t alx_msix_timer(int irq, void *data) ++{ ++ struct alx_msix_param *msix = data; ++ struct alx_adapter *adpt = msix->adpt; ++ struct alx_hw *hw = &adpt->hw; ++ u32 isr; ++ ++ hw->cbs.disable_msix_intr(hw, msix->vec_idx); ++ ++ alx_mem_r32(hw, ALX_ISR, &isr); ++ isr = isr & (ALX_ISR_TIMER | ALX_ISR_MANU); ++ ++ ++ if (isr == 0) { ++ hw->cbs.enable_msix_intr(hw, msix->vec_idx); ++ return IRQ_NONE; ++ } ++ ++ /* Ack ISR */ ++ alx_mem_w32(hw, ALX_ISR, isr); ++ ++ if (isr & ALX_ISR_MANU) { ++ adpt->net_stats.tx_carrier_errors++; ++ alx_check_lsc(adpt); ++ } ++ ++ hw->cbs.enable_msix_intr(hw, msix->vec_idx); ++ ++ return IRQ_HANDLED; ++} ++ ++ ++static irqreturn_t alx_msix_alert(int irq, void *data) ++{ ++ struct alx_msix_param *msix = data; ++ struct alx_adapter *adpt = msix->adpt; ++ struct alx_hw *hw = &adpt->hw; ++ u32 isr; ++ ++ hw->cbs.disable_msix_intr(hw, msix->vec_idx); ++ ++ alx_mem_r32(hw, ALX_ISR, &isr); ++ isr = isr & ALX_ISR_ALERT_MASK; ++ ++ if (isr == 0) { ++ hw->cbs.enable_msix_intr(hw, msix->vec_idx); ++ return IRQ_NONE; ++ } ++ alx_mem_w32(hw, ALX_ISR, isr); ++ ++ hw->cbs.enable_msix_intr(hw, msix->vec_idx); ++ ++ return IRQ_HANDLED; ++} ++ ++ ++static irqreturn_t alx_msix_smb(int irq, void *data) ++{ ++ struct alx_msix_param *msix = data; ++ struct alx_adapter *adpt = msix->adpt; ++ struct alx_hw *hw = &adpt->hw; ++ ++ hw->cbs.disable_msix_intr(hw, msix->vec_idx); ++ ++ hw->cbs.enable_msix_intr(hw, msix->vec_idx); ++ ++ return IRQ_HANDLED; ++} ++ ++ ++static irqreturn_t alx_msix_phy(int irq, void *data) ++{ ++ struct alx_msix_param *msix = data; ++ struct alx_adapter *adpt = msix->adpt; ++ struct alx_hw *hw = &adpt->hw; ++ ++ hw->cbs.disable_msix_intr(hw, msix->vec_idx); ++ ++ if (hw->cbs.ack_phy_intr) ++ hw->cbs.ack_phy_intr(hw); ++ ++ adpt->net_stats.tx_carrier_errors++; ++ alx_check_lsc(adpt); ++ ++ hw->cbs.enable_msix_intr(hw, msix->vec_idx); ++ ++ return IRQ_HANDLED; ++} ++ ++ ++/* ++ * alx_msix_rtx ++ */ ++static irqreturn_t alx_msix_rtx(int irq, void *data) ++{ ++ struct alx_msix_param *msix = data; ++ struct alx_adapter *adpt = msix->adpt; ++ struct alx_hw *hw = &adpt->hw; ++ ++ netif_info(adpt, intr, adpt->netdev, ++ "msix vec_idx = %d\n", msix->vec_idx); ++ ++ hw->cbs.disable_msix_intr(hw, msix->vec_idx); ++ if (!msix->rx_count && !msix->tx_count) { ++ hw->cbs.enable_msix_intr(hw, msix->vec_idx); ++ return IRQ_HANDLED; ++ } ++ ++ napi_schedule(&msix->napi); ++ return IRQ_HANDLED; ++} ++ ++ ++/* ++ * alx_napi_msix_rtx ++ */ ++static int alx_napi_msix_rtx(struct napi_struct *napi, int max_pkts) ++{ ++ struct alx_msix_param *msix = ++ container_of(napi, struct alx_msix_param, napi); ++ struct alx_adapter *adpt = msix->adpt; ++ struct alx_hw *hw = &adpt->hw; ++ struct alx_rx_queue *rxque; ++ struct alx_rx_queue *swque; ++ struct alx_tx_queue *txque; ++ unsigned long flags = 0; ++ bool complete = true; ++ int num_pkts = 0; ++ int rque_idx, tque_idx; ++ int i, j; ++ ++ netif_info(adpt, intr, adpt->netdev, ++ "NAPI: msix vec_idx = %d\n", msix->vec_idx); ++ ++ /* RX */ ++ for (i = 0; i < msix->rx_count; i++) { ++ rque_idx = msix->rx_map[i]; ++ num_pkts = 0; ++ if (CHK_ADPT_FLAG(0, SRSS_EN)) { ++ if (!spin_trylock_irqsave(&adpt->rx_lock, flags)) ++ goto clean_sw_irq; ++ ++ for (j = 0; j < adpt->num_hw_rxques; j++) ++ alx_dispatch_rx_irq(msix, adpt->rx_queue[j]); ++ ++ spin_unlock_irqrestore(&adpt->rx_lock, flags); ++clean_sw_irq: ++ swque = adpt->rx_queue[rque_idx]; ++ complete &= alx_handle_srx_irq(msix, swque, &num_pkts, ++ max_pkts); ++ ++ } else { ++ rxque = adpt->rx_queue[rque_idx]; ++ complete &= alx_handle_rx_irq(msix, rxque, &num_pkts, ++ max_pkts); ++ } ++ } ++ ++ ++ /* Handle TX */ ++ for (i = 0; i < msix->tx_count; i++) { ++ tque_idx = msix->tx_map[i]; ++ txque = adpt->tx_queue[tque_idx]; ++ complete &= alx_handle_tx_irq(msix, txque); ++ } ++ ++ if (!complete) { ++ netif_info(adpt, intr, adpt->netdev, ++ "Some packets in the queue are not handled!\n"); ++ num_pkts = max_pkts; ++ } ++ ++ netif_info(adpt, intr, adpt->netdev, ++ "num_pkts = %d, max_pkts = %d\n", num_pkts, max_pkts); ++ /* If all work done, exit the polling mode */ ++ if (num_pkts < max_pkts) { ++ napi_complete(napi); ++ if (!CHK_ADPT_FLAG(1, STATE_DOWN)) ++ hw->cbs.enable_msix_intr(hw, msix->vec_idx); ++ } ++ ++ return num_pkts; ++} ++ ++ ++ ++/* ++ * alx_napi_legacy_rtx - NAPI Rx polling callback ++ */ ++static int alx_napi_legacy_rtx(struct napi_struct *napi, int max_pkts) ++{ ++ struct alx_msix_param *msix = ++ container_of(napi, struct alx_msix_param, napi); ++ struct alx_adapter *adpt = msix->adpt; ++ struct alx_hw *hw = &adpt->hw; ++ int complete = true; ++ int num_pkts = 0; ++ int que_idx; ++ ++ netif_info(adpt, intr, adpt->netdev, ++ "NAPI: msix vec_idx = %d\n", msix->vec_idx); ++ ++ /* Keep link state information with original netdev */ ++ if (!netif_carrier_ok(adpt->netdev)) ++ goto enable_rtx_irq; ++ ++ for (que_idx = 0; que_idx < adpt->num_txques; que_idx++) ++ complete &= alx_handle_tx_irq(msix, adpt->tx_queue[que_idx]); ++ ++ for (que_idx = 0; que_idx < adpt->num_hw_rxques; que_idx++) { ++ num_pkts = 0; ++ complete &= alx_handle_rx_irq(msix, adpt->rx_queue[que_idx], ++ &num_pkts, max_pkts); ++ } ++ ++ if (!complete) ++ num_pkts = max_pkts; ++ ++ if (num_pkts < max_pkts) { ++enable_rtx_irq: ++ napi_complete(napi); ++ hw->intr_mask |= (ALX_ISR_RXQ | ALX_ISR_TXQ); ++ alx_mem_w32(hw, ALX_IMR, hw->intr_mask); ++ } ++ return num_pkts; ++} ++ ++ ++static void alx_set_msix_flags(struct alx_msix_param *msix, ++ enum alx_msix_type type, int index) ++{ ++ if (type == alx_msix_type_rx) { ++ switch (index) { ++ case 0: ++ SET_MSIX_FLAG(RX0); ++ break; ++ case 1: ++ SET_MSIX_FLAG(RX1); ++ break; ++ case 2: ++ SET_MSIX_FLAG(RX2); ++ break; ++ case 3: ++ SET_MSIX_FLAG(RX3); ++ break; ++ case 4: ++ SET_MSIX_FLAG(RX4); ++ break; ++ case 5: ++ SET_MSIX_FLAG(RX5); ++ break; ++ case 6: ++ SET_MSIX_FLAG(RX6); ++ break; ++ case 7: ++ SET_MSIX_FLAG(RX7); ++ break; ++ default: ++ printk(KERN_ERR "alx_set_msix_flags: rx error."); ++ break; ++ } ++ } else if (type == alx_msix_type_tx) { ++ switch (index) { ++ case 0: ++ SET_MSIX_FLAG(TX0); ++ break; ++ case 1: ++ SET_MSIX_FLAG(TX1); ++ break; ++ case 2: ++ SET_MSIX_FLAG(TX2); ++ break; ++ case 3: ++ SET_MSIX_FLAG(TX3); ++ break; ++ default: ++ printk(KERN_ERR "alx_set_msix_flags: tx error."); ++ break; ++ } ++ } else if (type == alx_msix_type_other) { ++ switch (index) { ++ case ALX_MSIX_TYPE_OTH_TIMER: ++ SET_MSIX_FLAG(TIMER); ++ break; ++ case ALX_MSIX_TYPE_OTH_ALERT: ++ SET_MSIX_FLAG(ALERT); ++ break; ++ case ALX_MSIX_TYPE_OTH_SMB: ++ SET_MSIX_FLAG(SMB); ++ break; ++ case ALX_MSIX_TYPE_OTH_PHY: ++ SET_MSIX_FLAG(PHY); ++ break; ++ default: ++ printk(KERN_ERR "alx_set_msix_flags: other error."); ++ break; ++ } ++ } ++} ++ ++ ++/* alx_setup_msix_maps */ ++static int alx_setup_msix_maps(struct alx_adapter *adpt) ++{ ++ int msix_idx = 0; ++ int que_idx = 0; ++ int num_rxques = adpt->num_rxques; ++ int num_txques = adpt->num_txques; ++ int num_msix_rxques = adpt->num_msix_rxques; ++ int num_msix_txques = adpt->num_msix_txques; ++ int num_msix_noques = adpt->num_msix_noques; ++ ++ if (CHK_ADPT_FLAG(0, FIXED_MSIX)) ++ goto fixed_msix_map; ++ ++ netif_warn(adpt, ifup, adpt->netdev, ++ "don't support non-fixed msix map\n"); ++ return -EINVAL; ++ ++fixed_msix_map: ++ /* ++ * For RX queue msix map ++ */ ++ msix_idx = 0; ++ for (que_idx = 0; que_idx < num_msix_rxques; que_idx++, msix_idx++) { ++ struct alx_msix_param *msix = adpt->msix[msix_idx]; ++ if (que_idx < num_rxques) { ++ adpt->rx_queue[que_idx]->msix = msix; ++ msix->rx_map[msix->rx_count] = que_idx; ++ msix->rx_count++; ++ alx_set_msix_flags(msix, alx_msix_type_rx, que_idx); ++ } ++ } ++ if (msix_idx != num_msix_rxques) ++ netif_warn(adpt, ifup, adpt->netdev, "msix_idx is wrong\n"); ++ ++ /* ++ * For TX queue msix map ++ */ ++ for (que_idx = 0; que_idx < num_msix_txques; que_idx++, msix_idx++) { ++ struct alx_msix_param *msix = adpt->msix[msix_idx]; ++ if (que_idx < num_txques) { ++ adpt->tx_queue[que_idx]->msix = msix; ++ msix->tx_map[msix->tx_count] = que_idx; ++ msix->tx_count++; ++ alx_set_msix_flags(msix, alx_msix_type_tx, que_idx); ++ } ++ } ++ if (msix_idx != (num_msix_rxques + num_msix_txques)) ++ netif_warn(adpt, ifup, adpt->netdev, "msix_idx is wrong\n"); ++ ++ ++ /* ++ * For NON queue msix map ++ */ ++ for (que_idx = 0; que_idx < num_msix_noques; que_idx++, msix_idx++) { ++ struct alx_msix_param *msix = adpt->msix[msix_idx]; ++ alx_set_msix_flags(msix, alx_msix_type_other, que_idx); ++ } ++ return 0; ++} ++ ++ ++static inline void alx_reset_msix_maps(struct alx_adapter *adpt) ++{ ++ int que_idx, msix_idx; ++ ++ for (que_idx = 0; que_idx < adpt->num_rxques; que_idx++) ++ adpt->rx_queue[que_idx]->msix = NULL; ++ for (que_idx = 0; que_idx < adpt->num_txques; que_idx++) ++ adpt->tx_queue[que_idx]->msix = NULL; ++ ++ for (msix_idx = 0; msix_idx < adpt->num_msix_intrs; msix_idx++) { ++ struct alx_msix_param *msix = adpt->msix[msix_idx]; ++ memset(msix->rx_map, 0, sizeof(msix->rx_map)); ++ memset(msix->tx_map, 0, sizeof(msix->tx_map)); ++ msix->rx_count = 0; ++ msix->tx_count = 0; ++ CLI_MSIX_FLAG(ALL); ++ } ++} ++ ++ ++/* ++ * alx_enable_intr - Enable default interrupt generation settings ++ */ ++static inline void alx_enable_intr(struct alx_adapter *adpt) ++{ ++ struct alx_hw *hw = &adpt->hw; ++ int i; ++ ++ if (!atomic_dec_and_test(&adpt->irq_sem)) ++ return; ++ ++ if (hw->cbs.enable_legacy_intr) ++ hw->cbs.enable_legacy_intr(hw); ++ ++ /* enable all MSIX IRQs */ ++ for (i = 0; i < adpt->num_msix_intrs; i++) { ++ if (hw->cbs.disable_msix_intr) ++ hw->cbs.disable_msix_intr(hw, i); ++ if (hw->cbs.enable_msix_intr) ++ hw->cbs.enable_msix_intr(hw, i); ++ } ++} ++ ++ ++/* alx_disable_intr - Mask off interrupt generation on the NIC */ ++static inline void alx_disable_intr(struct alx_adapter *adpt) ++{ ++ struct alx_hw *hw = &adpt->hw; ++ atomic_inc(&adpt->irq_sem); ++ ++ if (hw->cbs.disable_legacy_intr) ++ hw->cbs.disable_legacy_intr(hw); ++ ++ if (CHK_ADPT_FLAG(0, MSIX_EN)) { ++ int i; ++ for (i = 0; i < adpt->num_msix_intrs; i++) { ++ synchronize_irq(adpt->msix_entries[i].vector); ++ hw->cbs.disable_msix_intr(hw, i); ++ } ++ } else { ++ synchronize_irq(adpt->pdev->irq); ++ } ++ ++ ++} ++ ++ ++/* ++ * alx_interrupt - Interrupt Handler ++ */ ++static irqreturn_t alx_interrupt(int irq, void *data) ++{ ++ struct net_device *netdev = data; ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ struct alx_msix_param *msix = adpt->msix[0]; ++ int max_intrs = ALX_MAX_HANDLED_INTRS; ++ u32 isr, status; ++ ++ do { ++ alx_mem_r32(hw, ALX_ISR, &isr); ++ status = isr & hw->intr_mask; ++ ++ if (status == 0) { ++ alx_mem_w32(hw, ALX_ISR, 0); ++ if (max_intrs != ALX_MAX_HANDLED_INTRS) ++ return IRQ_HANDLED; ++ return IRQ_NONE; ++ } ++ ++ /* ack ISR to PHY register */ ++ if (status & ALX_ISR_PHY) ++ hw->cbs.ack_phy_intr(hw); ++ /* ack ISR to MAC register */ ++ alx_mem_w32(hw, ALX_ISR, status | ALX_ISR_DIS); ++ ++ if (status & ALX_ISR_ERROR) { ++ netif_warn(adpt, intr, adpt->netdev, ++ "isr error (status = 0x%x)\n", ++ status & ALX_ISR_ERROR); ++ if (status & ALX_ISR_PCIE_FERR) { ++ alx_mem_w16(hw, ALX_DEV_STAT, ++ ALX_DEV_STAT_FERR | ++ ALX_DEV_STAT_NFERR | ++ ALX_DEV_STAT_CERR); ++ } ++ /* reset MAC */ ++ SET_ADPT_FLAG(0, TASK_REINIT_REQ); ++ alx_task_schedule(adpt); ++ return IRQ_HANDLED; ++ } ++ ++ if (status & (ALX_ISR_RXQ | ALX_ISR_TXQ)) { ++ if (napi_schedule_prep(&(msix->napi))) { ++ hw->intr_mask &= ~(ALX_ISR_RXQ | ALX_ISR_TXQ); ++ alx_mem_w32(hw, ALX_IMR, hw->intr_mask); ++ __napi_schedule(&(msix->napi)); ++ } ++ } ++ ++ if (status & ALX_ISR_OVER) { ++ netif_warn(adpt, intr, adpt->netdev, ++ "TX/RX overflow (status = 0x%x)\n", ++ status & ALX_ISR_OVER); ++ } ++ ++ /* link event */ ++ if (status & (ALX_ISR_PHY | ALX_ISR_MANU)) { ++ netdev->stats.tx_carrier_errors++; ++ alx_check_lsc(adpt); ++ break; ++ } ++ ++ } while (--max_intrs > 0); ++ /* re-enable Interrupt*/ ++ alx_mem_w32(hw, ALX_ISR, 0); ++ return IRQ_HANDLED; ++} ++ ++ ++/* ++ * alx_request_msix_irqs - Initialize MSI-X interrupts ++ */ ++static int alx_request_msix_irq(struct alx_adapter *adpt) ++{ ++ struct net_device *netdev = adpt->netdev; ++ irqreturn_t (*handler)(int, void *); ++ int msix_idx; ++ int num_msix_intrs = adpt->num_msix_intrs; ++ int rx_idx = 0, tx_idx = 0; ++ int i; ++ int retval; ++ ++ retval = alx_setup_msix_maps(adpt); ++ if (retval) ++ return retval; ++ ++ for (msix_idx = 0; msix_idx < num_msix_intrs; msix_idx++) { ++ struct alx_msix_param *msix = adpt->msix[msix_idx]; ++ ++ if (CHK_MSIX_FLAG(RXS) && CHK_MSIX_FLAG(TXS)) { ++ handler = alx_msix_rtx; ++ sprintf(msix->name, "%s:%s%d", ++ netdev->name, "rtx", rx_idx); ++ rx_idx++; ++ tx_idx++; ++ } else if (CHK_MSIX_FLAG(RXS)) { ++ handler = alx_msix_rtx; ++ sprintf(msix->name, "%s:%s%d", ++ netdev->name, "rx", rx_idx); ++ rx_idx++; ++ } else if (CHK_MSIX_FLAG(TXS)) { ++ handler = alx_msix_rtx; ++ sprintf(msix->name, "%s:%s%d", ++ netdev->name, "tx", tx_idx); ++ tx_idx++; ++ } else if (CHK_MSIX_FLAG(TIMER)) { ++ handler = alx_msix_timer; ++ sprintf(msix->name, "%s:%s", netdev->name, "timer"); ++ } else if (CHK_MSIX_FLAG(ALERT)) { ++ handler = alx_msix_alert; ++ sprintf(msix->name, "%s:%s", netdev->name, "alert"); ++ } else if (CHK_MSIX_FLAG(SMB)) { ++ handler = alx_msix_smb; ++ sprintf(msix->name, "%s:%s", netdev->name, "smb"); ++ } else if (CHK_MSIX_FLAG(PHY)) { ++ handler = alx_msix_phy; ++ sprintf(msix->name, "%s:%s", netdev->name, "phy"); ++ } else { ++ netif_info(adpt, ifup, adpt->netdev, ++ "MSIX entry [%d] is blank\n", ++ msix->vec_idx); ++ continue; ++ } ++ netif_info(adpt, ifup, adpt->netdev, ++ "MSIX entry [%d] is %s\n", ++ msix->vec_idx, msix->name); ++ retval = request_irq(adpt->msix_entries[msix_idx].vector, ++ handler, 0, msix->name, msix); ++ if (retval) ++ goto free_msix_irq; ++ ++ /* assign the mask for this irq */ ++ irq_set_affinity_hint(adpt->msix_entries[msix_idx].vector, ++ msix->affinity_mask); ++ } ++ return retval; ++ ++ ++free_msix_irq: ++ for (i = 0; i < msix_idx; i++) { ++ irq_set_affinity_hint(adpt->msix_entries[i].vector, NULL); ++ free_irq(adpt->msix_entries[i].vector, adpt->msix[i]); ++ } ++ CLI_ADPT_FLAG(0, MSIX_EN); ++ pci_disable_msix(adpt->pdev); ++ kfree(adpt->msix_entries); ++ adpt->msix_entries = NULL; ++ return retval; ++} ++ ++ ++/* ++ * alx_request_irq - initialize interrupts ++ */ ++static int alx_request_irq(struct alx_adapter *adpt) ++{ ++ struct net_device *netdev = adpt->netdev; ++ int retval; ++ ++ /* request MSIX irq */ ++ if (CHK_ADPT_FLAG(0, MSIX_EN)) { ++ retval = alx_request_msix_irq(adpt); ++ if (retval) { ++ alx_err(adpt, "request msix irq failed, error = %d\n", ++ retval); ++ } ++ goto out; ++ } ++ ++ /* request MSI irq */ ++ if (CHK_ADPT_FLAG(0, MSI_EN)) { ++ retval = request_irq(adpt->pdev->irq, alx_interrupt, 0, ++ netdev->name, netdev); ++ if (retval) { ++ alx_err(adpt, "request msix irq failed, error = %d\n", ++ retval); ++ } ++ goto out; ++ } ++ ++ /* request shared irq */ ++ retval = request_irq(adpt->pdev->irq, alx_interrupt, IRQF_SHARED, ++ netdev->name, netdev); ++ if (retval) { ++ alx_err(adpt, "request shared irq failed, error = %d\n", ++ retval); ++ } ++out: ++ return retval; ++} ++ ++ ++static void alx_free_irq(struct alx_adapter *adpt) ++{ ++ struct net_device *netdev = adpt->netdev; ++ int i; ++ ++ if (CHK_ADPT_FLAG(0, MSIX_EN)) { ++ for (i = 0; i < adpt->num_msix_intrs; i++) { ++ struct alx_msix_param *msix = adpt->msix[i]; ++ netif_info(adpt, ifdown, adpt->netdev, ++ "msix entry = %d\n", i); ++ if (!CHK_MSIX_FLAG(ALL)) ++ continue; ++ if (CHK_MSIX_FLAG(RXS) || CHK_MSIX_FLAG(TXS)) { ++ irq_set_affinity_hint( ++ adpt->msix_entries[i].vector, NULL); ++ } ++ free_irq(adpt->msix_entries[i].vector, msix); ++ } ++ alx_reset_msix_maps(adpt); ++ } else { ++ free_irq(adpt->pdev->irq, netdev); ++ } ++} ++ ++ ++static void alx_vlan_mode(struct net_device *netdev, ++ netdev_features_t features) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ ++ if (!CHK_ADPT_FLAG(1, STATE_DOWN)) ++ alx_disable_intr(adpt); ++ ++ if (features & NETIF_F_HW_VLAN_RX) { ++ /* enable VLAN tag insert/strip */ ++ SET_HW_FLAG(VLANSTRIP_EN); ++ } else { ++ /* disable VLAN tag insert/strip */ ++ CLI_HW_FLAG(VLANSTRIP_EN); ++ } ++ hw->cbs.config_mac_ctrl(hw); ++ ++ if (!CHK_ADPT_FLAG(1, STATE_DOWN)) ++ alx_enable_intr(adpt); ++} ++ ++ ++static void alx_restore_vlan(struct alx_adapter *adpt) ++{ ++ alx_vlan_mode(adpt->netdev, adpt->netdev->features); ++} ++ ++ ++static void alx_napi_enable_all(struct alx_adapter *adpt) ++{ ++ struct alx_msix_param *msix; ++ int num_msix_intrs = adpt->num_msix_intrs; ++ int msix_idx; ++ ++ if (!CHK_ADPT_FLAG(0, MSIX_EN)) ++ num_msix_intrs = 1; ++ ++ for (msix_idx = 0; msix_idx < num_msix_intrs; msix_idx++) { ++ struct napi_struct *napi; ++ msix = adpt->msix[msix_idx]; ++ napi = &msix->napi; ++ napi_enable(napi); ++ } ++} ++ ++ ++static void alx_napi_disable_all(struct alx_adapter *adpt) ++{ ++ struct alx_msix_param *msix; ++ int num_msix_intrs = adpt->num_msix_intrs; ++ int msix_idx; ++ ++ if (!CHK_ADPT_FLAG(0, MSIX_EN)) ++ num_msix_intrs = 1; ++ ++ for (msix_idx = 0; msix_idx < num_msix_intrs; msix_idx++) { ++ msix = adpt->msix[msix_idx]; ++ napi_disable(&msix->napi); ++ } ++} ++ ++ ++static void alx_clean_tx_queue(struct alx_tx_queue *txque) ++{ ++ struct device *dev = txque->dev; ++ unsigned long size; ++ u16 i; ++ ++ /* ring already cleared, nothing to do */ ++ if (!txque->tpq.tpbuff) ++ return; ++ ++ for (i = 0; i < txque->tpq.count; i++) { ++ struct alx_buffer *tpbuf; ++ tpbuf = GET_TP_BUFFER(txque, i); ++ if (tpbuf->dma) { ++ pci_unmap_single(to_pci_dev(dev), ++ tpbuf->dma, ++ tpbuf->length, ++ DMA_TO_DEVICE); ++ tpbuf->dma = 0; ++ } ++ if (tpbuf->skb) { ++ dev_kfree_skb_any(tpbuf->skb); ++ tpbuf->skb = NULL; ++ } ++ } ++ ++ size = sizeof(struct alx_buffer) * txque->tpq.count; ++ memset(txque->tpq.tpbuff, 0, size); ++ ++ /* Zero out Tx-buffers */ ++ memset(txque->tpq.tpdesc, 0, txque->tpq.size); ++ ++ txque->tpq.consume_idx = 0; ++ txque->tpq.produce_idx = 0; ++} ++ ++ ++/* ++ * alx_clean_all_tx_queues ++ */ ++static void alx_clean_all_tx_queues(struct alx_adapter *adpt) ++{ ++ int i; ++ ++ for (i = 0; i < adpt->num_txques; i++) ++ alx_clean_tx_queue(adpt->tx_queue[i]); ++} ++ ++ ++static void alx_clean_rx_queue(struct alx_rx_queue *rxque) ++{ ++ struct device *dev = rxque->dev; ++ unsigned long size; ++ int i; ++ ++ if (CHK_RX_FLAG(HW_QUE)) { ++ /* ring already cleared, nothing to do */ ++ if (!rxque->rfq.rfbuff) ++ goto clean_sw_queue; ++ ++ for (i = 0; i < rxque->rfq.count; i++) { ++ struct alx_buffer *rfbuf; ++ rfbuf = GET_RF_BUFFER(rxque, i); ++ ++ if (rfbuf->dma) { ++ pci_unmap_single(to_pci_dev(dev), ++ rfbuf->dma, ++ rfbuf->length, ++ DMA_FROM_DEVICE); ++ rfbuf->dma = 0; ++ } ++ if (rfbuf->skb) { ++ dev_kfree_skb(rfbuf->skb); ++ rfbuf->skb = NULL; ++ } ++ } ++ size = sizeof(struct alx_buffer) * rxque->rfq.count; ++ memset(rxque->rfq.rfbuff, 0, size); ++ ++ /* zero out the descriptor ring */ ++ memset(rxque->rrq.rrdesc, 0, rxque->rrq.size); ++ rxque->rrq.produce_idx = 0; ++ rxque->rrq.consume_idx = 0; ++ ++ memset(rxque->rfq.rfdesc, 0, rxque->rfq.size); ++ rxque->rfq.produce_idx = 0; ++ rxque->rfq.consume_idx = 0; ++ } ++clean_sw_queue: ++ if (CHK_RX_FLAG(SW_QUE)) { ++ /* ring already cleared, nothing to do */ ++ if (!rxque->swq.swbuff) ++ return; ++ ++ for (i = 0; i < rxque->swq.count; i++) { ++ struct alx_sw_buffer *swbuf; ++ swbuf = GET_SW_BUFFER(rxque, i); ++ ++ /* swq doesn't map DMA*/ ++ ++ if (swbuf->skb) { ++ dev_kfree_skb(swbuf->skb); ++ swbuf->skb = NULL; ++ } ++ } ++ size = sizeof(struct alx_buffer) * rxque->swq.count; ++ memset(rxque->swq.swbuff, 0, size); ++ ++ /* swq doesn't have any descripter rings */ ++ rxque->swq.produce_idx = 0; ++ rxque->swq.consume_idx = 0; ++ } ++} ++ ++ ++/* ++ * alx_clean_all_rx_queues ++ */ ++static void alx_clean_all_rx_queues(struct alx_adapter *adpt) ++{ ++ int i; ++ for (i = 0; i < adpt->num_rxques; i++) ++ alx_clean_rx_queue(adpt->rx_queue[i]); ++} ++ ++ ++/* ++ * alx_set_rss_queues: Allocate queues for RSS ++ */ ++static inline void alx_set_num_txques(struct alx_adapter *adpt) ++{ ++ struct alx_hw *hw = &adpt->hw; ++ ++ if (hw->mac_type == alx_mac_l1f || hw->mac_type == alx_mac_l2f) ++ adpt->num_txques = 4; ++ else ++ adpt->num_txques = 2; ++} ++ ++ ++/* ++ * alx_set_rss_queues: Allocate queues for RSS ++ */ ++static inline void alx_set_num_rxques(struct alx_adapter *adpt) ++{ ++ if (CHK_ADPT_FLAG(0, SRSS_CAP)) { ++ adpt->num_hw_rxques = 1; ++ adpt->num_sw_rxques = adpt->max_rxques; ++ adpt->num_rxques = ++ max_t(u16, adpt->num_hw_rxques, adpt->num_sw_rxques); ++ } ++} ++ ++ ++/* ++ * alx_set_num_queues: Allocate queues for device, feature dependant ++ */ ++static void alx_set_num_queues(struct alx_adapter *adpt) ++{ ++ /* Start with default case */ ++ adpt->num_txques = 1; ++ adpt->num_rxques = 1; ++ adpt->num_hw_rxques = 1; ++ adpt->num_sw_rxques = 0; ++ ++ alx_set_num_rxques(adpt); ++ alx_set_num_txques(adpt); ++} ++ ++ ++/* alx_alloc_all_rtx_queue - allocate all queues */ ++static int alx_alloc_all_rtx_queue(struct alx_adapter *adpt) ++{ ++ int que_idx; ++ ++ for (que_idx = 0; que_idx < adpt->num_txques; que_idx++) { ++ struct alx_tx_queue *txque = adpt->tx_queue[que_idx]; ++ ++ txque = kzalloc(sizeof(struct alx_tx_queue), GFP_KERNEL); ++ if (!txque) ++ goto err_alloc_tx_queue; ++ txque->tpq.count = adpt->num_txdescs; ++ txque->que_idx = que_idx; ++ txque->dev = &adpt->pdev->dev; ++ txque->netdev = adpt->netdev; ++ ++ adpt->tx_queue[que_idx] = txque; ++ } ++ ++ for (que_idx = 0; que_idx < adpt->num_rxques; que_idx++) { ++ struct alx_rx_queue *rxque = adpt->rx_queue[que_idx]; ++ ++ rxque = kzalloc(sizeof(struct alx_rx_queue), GFP_KERNEL); ++ if (!rxque) ++ goto err_alloc_rx_queue; ++ rxque->rrq.count = adpt->num_rxdescs; ++ rxque->rfq.count = adpt->num_rxdescs; ++ rxque->swq.count = adpt->num_rxdescs; ++ rxque->que_idx = que_idx; ++ rxque->dev = &adpt->pdev->dev; ++ rxque->netdev = adpt->netdev; ++ ++ if (CHK_ADPT_FLAG(0, SRSS_EN)) { ++ if (que_idx < adpt->num_hw_rxques) ++ SET_RX_FLAG(HW_QUE); ++ if (que_idx < adpt->num_sw_rxques) ++ SET_RX_FLAG(SW_QUE); ++ } else { ++ SET_RX_FLAG(HW_QUE); ++ } ++ adpt->rx_queue[que_idx] = rxque; ++ } ++ netif_dbg(adpt, probe, adpt->netdev, ++ "num_tx_descs = %d, num_rx_descs = %d\n", ++ adpt->num_txdescs, adpt->num_rxdescs); ++ return 0; ++ ++err_alloc_rx_queue: ++ alx_err(adpt, "goto err_alloc_rx_queue"); ++ for (que_idx = 0; que_idx < adpt->num_rxques; que_idx++) ++ kfree(adpt->rx_queue[que_idx]); ++err_alloc_tx_queue: ++ alx_err(adpt, "goto err_alloc_tx_queue"); ++ for (que_idx = 0; que_idx < adpt->num_txques; que_idx++) ++ kfree(adpt->tx_queue[que_idx]); ++ return -ENOMEM; ++} ++ ++ ++/* alx_free_all_rtx_queue */ ++static void alx_free_all_rtx_queue(struct alx_adapter *adpt) ++{ ++ int que_idx; ++ ++ for (que_idx = 0; que_idx < adpt->num_txques; que_idx++) { ++ kfree(adpt->tx_queue[que_idx]); ++ adpt->tx_queue[que_idx] = NULL; ++ } ++ for (que_idx = 0; que_idx < adpt->num_rxques; que_idx++) { ++ kfree(adpt->rx_queue[que_idx]); ++ adpt->rx_queue[que_idx] = NULL; ++ } ++} ++ ++ ++/* alx_set_interrupt_param - set interrupt parameter */ ++static int alx_set_interrupt_param(struct alx_adapter *adpt) ++{ ++ struct alx_msix_param *msix; ++ int (*poll)(struct napi_struct *, int); ++ int msix_idx; ++ ++ if (CHK_ADPT_FLAG(0, MSIX_EN)) { ++ poll = &alx_napi_msix_rtx; ++ } else { ++ adpt->num_msix_intrs = 1; ++ poll = &alx_napi_legacy_rtx; ++ } ++ ++ for (msix_idx = 0; msix_idx < adpt->num_msix_intrs; msix_idx++) { ++ msix = kzalloc(sizeof(struct alx_msix_param), ++ GFP_KERNEL); ++ if (!msix) ++ goto err_alloc_msix; ++ msix->adpt = adpt; ++ msix->vec_idx = msix_idx; ++ /* Allocate the affinity_hint cpumask, configure the mask */ ++ if (!alloc_cpumask_var(&msix->affinity_mask, GFP_KERNEL)) ++ goto err_alloc_cpumask; ++ ++ cpumask_set_cpu((msix_idx % num_online_cpus()), ++ msix->affinity_mask); ++ ++ netif_napi_add(adpt->netdev, &msix->napi, (*poll), 64); ++ adpt->msix[msix_idx] = msix; ++ } ++ return 0; ++ ++err_alloc_cpumask: ++ kfree(msix); ++ adpt->msix[msix_idx] = NULL; ++err_alloc_msix: ++ for (msix_idx--; msix_idx >= 0; msix_idx--) { ++ msix = adpt->msix[msix_idx]; ++ netif_napi_del(&msix->napi); ++ free_cpumask_var(msix->affinity_mask); ++ kfree(msix); ++ adpt->msix[msix_idx] = NULL; ++ } ++ alx_err(adpt, "can't allocate memory\n"); ++ return -ENOMEM; ++} ++ ++ ++/* ++ * alx_reset_interrupt_param - Free memory allocated for interrupt vectors ++ */ ++static void alx_reset_interrupt_param(struct alx_adapter *adpt) ++{ ++ int msix_idx; ++ ++ for (msix_idx = 0; msix_idx < adpt->num_msix_intrs; msix_idx++) { ++ struct alx_msix_param *msix = adpt->msix[msix_idx]; ++ netif_napi_del(&msix->napi); ++ free_cpumask_var(msix->affinity_mask); ++ kfree(msix); ++ adpt->msix[msix_idx] = NULL; ++ } ++} ++ ++ ++/* set msix interrupt mode */ ++static int alx_set_msix_interrupt_mode(struct alx_adapter *adpt) ++{ ++ int msix_intrs, msix_idx; ++ int retval = 0; ++ ++ adpt->msix_entries = kcalloc(adpt->max_msix_intrs, ++ sizeof(struct msix_entry), GFP_KERNEL); ++ if (!adpt->msix_entries) { ++ netif_info(adpt, probe, adpt->netdev, ++ "can't allocate msix entry\n"); ++ CLI_ADPT_FLAG(0, MSIX_EN); ++ goto try_msi_mode; ++ } ++ ++ for (msix_idx = 0; msix_idx < adpt->max_msix_intrs; msix_idx++) ++ adpt->msix_entries[msix_idx].entry = msix_idx; ++ ++ ++ msix_intrs = adpt->max_msix_intrs; ++ while (msix_intrs >= adpt->min_msix_intrs) { ++ retval = pci_enable_msix(adpt->pdev, adpt->msix_entries, ++ msix_intrs); ++ if (!retval) /* Success in acquiring all requested vectors. */ ++ break; ++ else if (retval < 0) ++ msix_intrs = 0; /* Nasty failure, quit now */ ++ else /* error == number of vectors we should try again with */ ++ msix_intrs = retval; ++ } ++ if (msix_intrs < adpt->min_msix_intrs) { ++ netif_info(adpt, probe, adpt->netdev, ++ "can't enable MSI-X interrupts\n"); ++ CLI_ADPT_FLAG(0, MSIX_EN); ++ kfree(adpt->msix_entries); ++ adpt->msix_entries = NULL; ++ goto try_msi_mode; ++ } ++ ++ netif_info(adpt, probe, adpt->netdev, ++ "enable MSI-X interrupts, num_msix_intrs = %d\n", ++ msix_intrs); ++ SET_ADPT_FLAG(0, MSIX_EN); ++ if (CHK_ADPT_FLAG(0, SRSS_CAP)) ++ SET_ADPT_FLAG(0, SRSS_EN); ++ ++ adpt->num_msix_intrs = min_t(int, msix_intrs, adpt->max_msix_intrs); ++ retval = 0; ++ return retval; ++ ++try_msi_mode: ++ CLI_ADPT_FLAG(0, SRSS_CAP); ++ CLI_ADPT_FLAG(0, SRSS_EN); ++ alx_set_num_queues(adpt); ++ retval = -1; ++ return retval; ++} ++ ++ ++/* set msi interrupt mode */ ++static int alx_set_msi_interrupt_mode(struct alx_adapter *adpt) ++{ ++ int retval; ++ ++ retval = pci_enable_msi(adpt->pdev); ++ if (retval) { ++ netif_info(adpt, probe, adpt->netdev, ++ "can't enable MSI interrupt, error = %d\n", retval); ++ return retval; ++ } ++ SET_ADPT_FLAG(0, MSI_EN); ++ return retval; ++} ++ ++ ++/* set interrupt mode */ ++static int alx_set_interrupt_mode(struct alx_adapter *adpt) ++{ ++ int retval = 0; ++ ++ if (CHK_ADPT_FLAG(0, MSIX_CAP)) { ++ netif_info(adpt, probe, adpt->netdev, ++ "try to set MSIX interrupt\n"); ++ retval = alx_set_msix_interrupt_mode(adpt); ++ if (!retval) ++ return retval; ++ } ++ ++ if (CHK_ADPT_FLAG(0, MSI_CAP)) { ++ netif_info(adpt, probe, adpt->netdev, ++ "try to set MSI interrupt\n"); ++ retval = alx_set_msi_interrupt_mode(adpt); ++ if (!retval) ++ return retval; ++ } ++ ++ netif_info(adpt, probe, adpt->netdev, ++ "can't enable MSIX and MSI, will enable shared interrupt\n"); ++ retval = 0; ++ return retval; ++} ++ ++ ++static void alx_reset_interrupt_mode(struct alx_adapter *adpt) ++{ ++ if (CHK_ADPT_FLAG(0, MSIX_EN)) { ++ CLI_ADPT_FLAG(0, MSIX_EN); ++ pci_disable_msix(adpt->pdev); ++ kfree(adpt->msix_entries); ++ adpt->msix_entries = NULL; ++ } else if (CHK_ADPT_FLAG(0, MSI_EN)) { ++ CLI_ADPT_FLAG(0, MSI_EN); ++ pci_disable_msi(adpt->pdev); ++ } ++} ++ ++ ++static int __devinit alx_init_adapter_special(struct alx_adapter *adpt) ++{ ++ switch (adpt->hw.mac_type) { ++ case alx_mac_l1f: ++ case alx_mac_l2f: ++ goto init_alf_adapter; ++ break; ++ case alx_mac_l1c: ++ case alx_mac_l1d_v1: ++ case alx_mac_l1d_v2: ++ case alx_mac_l2c: ++ case alx_mac_l2cb_v1: ++ case alx_mac_l2cb_v20: ++ case alx_mac_l2cb_v21: ++ goto init_alc_adapter; ++ break; ++ default: ++ break; ++ } ++ return -1; ++ ++init_alc_adapter: ++ if (CHK_ADPT_FLAG(0, MSIX_CAP)) ++ alx_err(adpt, "ALC doesn't support MSIX\n"); ++ ++ /* msi for tx, rx and none queues */ ++ adpt->num_msix_txques = 0; ++ adpt->num_msix_rxques = 0; ++ adpt->num_msix_noques = 0; ++ return 0; ++ ++init_alf_adapter: ++ if (CHK_ADPT_FLAG(0, MSIX_CAP)) { ++ /* msix for tx, rx and none queues */ ++ adpt->num_msix_txques = 4; ++ adpt->num_msix_rxques = 8; ++ adpt->num_msix_noques = ALF_MAX_MSIX_NOQUE_INTRS; ++ ++ /* msix vector range */ ++ adpt->max_msix_intrs = ALF_MAX_MSIX_INTRS; ++ adpt->min_msix_intrs = ALF_MIN_MSIX_INTRS; ++ } else { ++ /* msi for tx, rx and none queues */ ++ adpt->num_msix_txques = 0; ++ adpt->num_msix_rxques = 0; ++ adpt->num_msix_noques = 0; ++ } ++ return 0; ++ ++} ++ ++ ++/* ++ * alx_init_adapter ++ */ ++static int __devinit alx_init_adapter(struct alx_adapter *adpt) ++{ ++ struct alx_hw *hw = &adpt->hw; ++ struct pci_dev *pdev = adpt->pdev; ++ u16 revision; ++ int max_frame; ++ ++ /* PCI config space info */ ++ hw->pci_venid = pdev->vendor; ++ hw->pci_devid = pdev->device; ++ alx_cfg_r16(hw, PCI_CLASS_REVISION, &revision); ++ hw->pci_revid = revision & 0xFF; ++ hw->pci_sub_venid = pdev->subsystem_vendor; ++ hw->pci_sub_devid = pdev->subsystem_device; ++ ++ if (alx_init_hw_callbacks(adpt) != 0) { ++ alx_err(adpt, "set HW function pointers failed\n"); ++ return -1; ++ } ++ ++ if (hw->cbs.identify_nic(hw) != 0) { ++ alx_err(adpt, "HW is disabled\n"); ++ return -1; ++ } ++ ++ /* Set adapter flags */ ++ switch (hw->mac_type) { ++ case alx_mac_l1f: ++ case alx_mac_l2f: ++#ifdef CONFIG_ALX_MSI ++ SET_ADPT_FLAG(0, MSI_CAP); ++#endif ++#ifdef CONFIG_ALX_MSIX ++ SET_ADPT_FLAG(0, MSIX_CAP); ++#endif ++ if (CHK_ADPT_FLAG(0, MSIX_CAP)) { ++ SET_ADPT_FLAG(0, FIXED_MSIX); ++ SET_ADPT_FLAG(0, MRQ_CAP); ++#ifdef CONFIG_ALX_RSS ++ SET_ADPT_FLAG(0, SRSS_CAP); ++#endif ++ } ++ pdev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG; ++ break; ++ case alx_mac_l1c: ++ case alx_mac_l1d_v1: ++ case alx_mac_l1d_v2: ++ case alx_mac_l2c: ++ case alx_mac_l2cb_v1: ++ case alx_mac_l2cb_v20: ++ case alx_mac_l2cb_v21: ++#ifdef CONFIG_ALX_MSI ++ SET_ADPT_FLAG(0, MSI_CAP); ++#endif ++ break; ++ default: ++ break; ++ } ++ ++ /* set default for alx_adapter */ ++ adpt->max_msix_intrs = 1; ++ adpt->min_msix_intrs = 1; ++ max_frame = adpt->netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; ++ adpt->rxbuf_size = adpt->netdev->mtu > ALX_DEF_RX_BUF_SIZE ? ++ ALIGN(max_frame, 8) : ALX_DEF_RX_BUF_SIZE; ++ adpt->wol = 0; ++ device_set_wakeup_enable(&pdev->dev, false); ++ ++ /* set default for alx_hw */ ++ hw->link_up = false; ++ hw->link_speed = ALX_LINK_SPEED_UNKNOWN; ++ hw->preamble = 7; ++ hw->intr_mask = ALX_IMR_NORMAL_MASK; ++ hw->smb_timer = 400; /* 400ms */ ++ hw->mtu = adpt->netdev->mtu; ++ hw->imt = 100; /* set to 200us */ ++ ++ /* set default for wrr */ ++ hw->wrr_prio0 = 4; ++ hw->wrr_prio1 = 4; ++ hw->wrr_prio2 = 4; ++ hw->wrr_prio3 = 4; ++ hw->wrr_mode = alx_wrr_mode_none; ++ ++ /* set default flow control settings */ ++ hw->req_fc_mode = alx_fc_full; ++ hw->cur_fc_mode = alx_fc_full; /* init for ethtool output */ ++ hw->disable_fc_autoneg = false; ++ hw->fc_was_autonegged = false; ++ hw->fc_single_pause = true; ++ ++ /* set default for rss info*/ ++ hw->rss_hstype = 0; ++ hw->rss_mode = alx_rss_mode_disable; ++ hw->rss_idt_size = 0; ++ hw->rss_base_cpu = 0; ++ memset(hw->rss_idt, 0x0, sizeof(hw->rss_idt)); ++ memset(hw->rss_key, 0x0, sizeof(hw->rss_key)); ++ ++ atomic_set(&adpt->irq_sem, 1); ++ spin_lock_init(&adpt->tx_lock); ++ spin_lock_init(&adpt->rx_lock); ++ ++ alx_init_adapter_special(adpt); ++ ++ if (hw->cbs.init_phy) { ++ if (hw->cbs.init_phy(hw)) ++ return -EINVAL; ++ } ++ ++ SET_ADPT_FLAG(1, STATE_DOWN); ++ return 0; ++} ++ ++ ++static int alx_set_register_info_special(struct alx_adapter *adpt) ++{ ++ struct alx_hw *hw = &adpt->hw; ++ int num_txques = adpt->num_txques; ++ ++ switch (adpt->hw.mac_type) { ++ case alx_mac_l1f: ++ case alx_mac_l2f: ++ goto cache_alf_register; ++ break; ++ case alx_mac_l1c: ++ case alx_mac_l1d_v1: ++ case alx_mac_l1d_v2: ++ case alx_mac_l2c: ++ case alx_mac_l2cb_v1: ++ case alx_mac_l2cb_v20: ++ case alx_mac_l2cb_v21: ++ goto cache_alc_register; ++ break; ++ default: ++ break; ++ } ++ return -1; ++ ++cache_alc_register: ++ /* setting for Produce Index and Consume Index */ ++ adpt->rx_queue[0]->produce_reg = hw->rx_prod_reg[0]; ++ adpt->rx_queue[0]->consume_reg = hw->rx_cons_reg[0]; ++ ++ switch (num_txques) { ++ case 2: ++ adpt->tx_queue[1]->produce_reg = hw->tx_prod_reg[1]; ++ adpt->tx_queue[1]->consume_reg = hw->tx_cons_reg[1]; ++ case 1: ++ adpt->tx_queue[0]->produce_reg = hw->tx_prod_reg[0]; ++ adpt->tx_queue[0]->consume_reg = hw->tx_cons_reg[0]; ++ break; ++ } ++ return 0; ++ ++cache_alf_register: ++ /* setting for Produce Index and Consume Index */ ++ adpt->rx_queue[0]->produce_reg = hw->rx_prod_reg[0]; ++ adpt->rx_queue[0]->consume_reg = hw->rx_cons_reg[0]; ++ ++ switch (num_txques) { ++ case 4: ++ adpt->tx_queue[3]->produce_reg = hw->tx_prod_reg[3]; ++ adpt->tx_queue[3]->consume_reg = hw->tx_cons_reg[3]; ++ case 3: ++ adpt->tx_queue[2]->produce_reg = hw->tx_prod_reg[2]; ++ adpt->tx_queue[2]->consume_reg = hw->tx_cons_reg[2]; ++ case 2: ++ adpt->tx_queue[1]->produce_reg = hw->tx_prod_reg[1]; ++ adpt->tx_queue[1]->consume_reg = hw->tx_cons_reg[1]; ++ case 1: ++ adpt->tx_queue[0]->produce_reg = hw->tx_prod_reg[0]; ++ adpt->tx_queue[0]->consume_reg = hw->tx_cons_reg[0]; ++ } ++ return 0; ++} ++ ++ ++/* alx_alloc_tx_descriptor - allocate Tx Descriptors */ ++static int alx_alloc_tx_descriptor(struct alx_adapter *adpt, ++ struct alx_tx_queue *txque) ++{ ++ struct alx_ring_header *ring_header = &adpt->ring_header; ++ int size; ++ ++ netif_info(adpt, ifup, adpt->netdev, ++ "tpq.count = %d\n", txque->tpq.count); ++ ++ size = sizeof(struct alx_buffer) * txque->tpq.count; ++ txque->tpq.tpbuff = kzalloc(size, GFP_KERNEL); ++ if (!txque->tpq.tpbuff) ++ goto err_alloc_tpq_buffer; ++ ++ /* round up to nearest 4K */ ++ txque->tpq.size = txque->tpq.count * sizeof(union alx_tpdesc); ++ ++ txque->tpq.tpdma = ring_header->dma + ring_header->used; ++ txque->tpq.tpdesc = ring_header->desc + ring_header->used; ++ adpt->hw.tpdma[txque->que_idx] = (u64)txque->tpq.tpdma; ++ ring_header->used += ALIGN(txque->tpq.size, 8); ++ ++ txque->tpq.produce_idx = 0; ++ txque->tpq.consume_idx = 0; ++ txque->max_packets = txque->tpq.count; ++ return 0; ++ ++err_alloc_tpq_buffer: ++ alx_err(adpt, "Unable to allocate memory for the Tx descriptor\n"); ++ return -ENOMEM; ++} ++ ++ ++/* alx_alloc_all_tx_descriptor - allocate all Tx Descriptors */ ++static int alx_alloc_all_tx_descriptor(struct alx_adapter *adpt) ++{ ++ int i, retval = 0; ++ netif_info(adpt, ifup, adpt->netdev, ++ "num_tques = %d\n", adpt->num_txques); ++ ++ for (i = 0; i < adpt->num_txques; i++) { ++ retval = alx_alloc_tx_descriptor(adpt, adpt->tx_queue[i]); ++ if (!retval) ++ continue; ++ ++ alx_err(adpt, "Allocation for Tx Queue %u failed\n", i); ++ break; ++ } ++ ++ return retval; ++} ++ ++ ++/* alx_alloc_rx_descriptor - allocate Rx Descriptors */ ++static int alx_alloc_rx_descriptor(struct alx_adapter *adpt, ++ struct alx_rx_queue *rxque) ++{ ++ struct alx_ring_header *ring_header = &adpt->ring_header; ++ int size; ++ ++ netif_info(adpt, ifup, adpt->netdev, ++ "RRD.count = %d, RFD.count = %d, SWD.count = %d\n", ++ rxque->rrq.count, rxque->rfq.count, rxque->swq.count); ++ ++ if (CHK_RX_FLAG(HW_QUE)) { ++ /* alloc buffer info */ ++ size = sizeof(struct alx_buffer) * rxque->rfq.count; ++ rxque->rfq.rfbuff = kzalloc(size, GFP_KERNEL); ++ if (!rxque->rfq.rfbuff) ++ goto err_alloc_rfq_buffer; ++ /* ++ * set dma's point of rrq and rfq ++ */ ++ ++ /* Round up to nearest 4K */ ++ rxque->rrq.size = ++ rxque->rrq.count * sizeof(union alx_rrdesc); ++ rxque->rfq.size = ++ rxque->rfq.count * sizeof(union alx_rfdesc); ++ ++ rxque->rrq.rrdma = ring_header->dma + ring_header->used; ++ rxque->rrq.rrdesc = ring_header->desc + ring_header->used; ++ adpt->hw.rrdma[rxque->que_idx] = (u64)rxque->rrq.rrdma; ++ ring_header->used += ALIGN(rxque->rrq.size, 8); ++ ++ rxque->rfq.rfdma = ring_header->dma + ring_header->used; ++ rxque->rfq.rfdesc = ring_header->desc + ring_header->used; ++ adpt->hw.rfdma[rxque->que_idx] = (u64)rxque->rfq.rfdma; ++ ring_header->used += ALIGN(rxque->rfq.size, 8); ++ ++ /* clean all counts within rxque */ ++ rxque->rrq.produce_idx = 0; ++ rxque->rrq.consume_idx = 0; ++ ++ rxque->rfq.produce_idx = 0; ++ rxque->rfq.consume_idx = 0; ++ } ++ ++ if (CHK_RX_FLAG(SW_QUE)) { ++ size = sizeof(struct alx_sw_buffer) * rxque->swq.count; ++ rxque->swq.swbuff = kzalloc(size, GFP_KERNEL); ++ if (!rxque->swq.swbuff) ++ goto err_alloc_swq_buffer; ++ ++ rxque->swq.consume_idx = 0; ++ rxque->swq.produce_idx = 0; ++ } ++ ++ rxque->max_packets = rxque->rrq.count / 2; ++ return 0; ++ ++err_alloc_swq_buffer: ++ kfree(rxque->rfq.rfbuff); ++ rxque->rfq.rfbuff = NULL; ++err_alloc_rfq_buffer: ++ alx_err(adpt, "Unable to allocate memory for the Rx descriptor\n"); ++ return -ENOMEM; ++} ++ ++ ++/* alx_alloc_all_rx_descriptor - allocate all Rx Descriptors */ ++static int alx_alloc_all_rx_descriptor(struct alx_adapter *adpt) ++{ ++ int i, error = 0; ++ ++ for (i = 0; i < adpt->num_rxques; i++) { ++ error = alx_alloc_rx_descriptor(adpt, adpt->rx_queue[i]); ++ if (!error) ++ continue; ++ alx_err(adpt, "Allocation for Rx Queue %u failed\n", i); ++ break; ++ } ++ ++ return error; ++} ++ ++ ++/* alx_free_tx_descriptor - Free Tx Descriptor */ ++static void alx_free_tx_descriptor(struct alx_tx_queue *txque) ++{ ++ alx_clean_tx_queue(txque); ++ ++ kfree(txque->tpq.tpbuff); ++ txque->tpq.tpbuff = NULL; ++ ++ /* if not set, then don't free */ ++ if (!txque->tpq.tpdesc) ++ return; ++ txque->tpq.tpdesc = NULL; ++} ++ ++ ++/* alx_free_all_tx_descriptor - Free all Tx Descriptor */ ++static void alx_free_all_tx_descriptor(struct alx_adapter *adpt) ++{ ++ int i; ++ ++ for (i = 0; i < adpt->num_txques; i++) ++ alx_free_tx_descriptor(adpt->tx_queue[i]); ++} ++ ++ ++/* alx_free_all_rx_descriptor - Free all Rx Descriptor */ ++static void alx_free_rx_descriptor(struct alx_rx_queue *rxque) ++{ ++ alx_clean_rx_queue(rxque); ++ ++ if (CHK_RX_FLAG(HW_QUE)) { ++ kfree(rxque->rfq.rfbuff); ++ rxque->rfq.rfbuff = NULL; ++ ++ /* if not set, then don't free */ ++ if (!rxque->rrq.rrdesc) ++ return; ++ rxque->rrq.rrdesc = NULL; ++ ++ if (!rxque->rfq.rfdesc) ++ return; ++ rxque->rfq.rfdesc = NULL; ++ } ++ ++ if (CHK_RX_FLAG(SW_QUE)) { ++ kfree(rxque->swq.swbuff); ++ rxque->swq.swbuff = NULL; ++ } ++} ++ ++ ++/* alx_free_all_rx_descriptor - Free all Rx Descriptor */ ++static void alx_free_all_rx_descriptor(struct alx_adapter *adpt) ++{ ++ int i; ++ for (i = 0; i < adpt->num_rxques; i++) ++ alx_free_rx_descriptor(adpt->rx_queue[i]); ++} ++ ++ ++/* ++ * alx_alloc_all_rtx_descriptor - allocate Tx / RX descriptor queues ++ */ ++static int alx_alloc_all_rtx_descriptor(struct alx_adapter *adpt) ++{ ++ struct device *dev = &adpt->pdev->dev; ++ struct alx_ring_header *ring_header = &adpt->ring_header; ++ int num_tques = adpt->num_txques; ++ int num_rques = adpt->num_hw_rxques; ++ unsigned int num_tx_descs = adpt->num_txdescs; ++ unsigned int num_rx_descs = adpt->num_rxdescs; ++ int retval; ++ ++ /* ++ * real ring DMA buffer ++ * each ring/block may need up to 8 bytes for alignment, hence the ++ * additional bytes tacked onto the end. ++ */ ++ ring_header->size = ++ num_tques * num_tx_descs * sizeof(union alx_tpdesc) + ++ num_rques * num_rx_descs * sizeof(union alx_rfdesc) + ++ num_rques * num_rx_descs * sizeof(union alx_rrdesc) + ++ sizeof(struct coals_msg_block) + ++ sizeof(struct alx_hw_stats) + ++ num_tques * 8 + num_rques * 2 * 8 + 8 * 2; ++ netif_info(adpt, ifup, adpt->netdev, ++ "num_tques = %d, num_tx_descs = %d\n", ++ num_tques, num_tx_descs); ++ netif_info(adpt, ifup, adpt->netdev, ++ "num_rques = %d, num_rx_descs = %d\n", ++ num_rques, num_rx_descs); ++ ++ ring_header->used = 0; ++ ring_header->desc = dma_alloc_coherent(dev, ring_header->size, ++ &ring_header->dma, GFP_KERNEL); ++ ++ if (!ring_header->desc) { ++ alx_err(adpt, "dma_alloc_coherent failed\n"); ++ retval = -ENOMEM; ++ goto err_alloc_dma; ++ } ++ memset(ring_header->desc, 0, ring_header->size); ++ ring_header->used = ALIGN(ring_header->dma, 8) - ring_header->dma; ++ ++ netif_info(adpt, ifup, adpt->netdev, ++ "ring header: size = %d, used= %d\n", ++ ring_header->size, ring_header->used); ++ ++ /* allocate receive descriptors */ ++ retval = alx_alloc_all_tx_descriptor(adpt); ++ if (retval) ++ goto err_alloc_tx; ++ ++ /* allocate receive descriptors */ ++ retval = alx_alloc_all_rx_descriptor(adpt); ++ if (retval) ++ goto err_alloc_rx; ++ ++ /* Init CMB dma address */ ++ adpt->cmb.dma = ring_header->dma + ring_header->used; ++ adpt->cmb.cmb = (u8 *) ring_header->desc + ring_header->used; ++ ring_header->used += ALIGN(sizeof(struct coals_msg_block), 8); ++ ++ adpt->smb.dma = ring_header->dma + ring_header->used; ++ adpt->smb.smb = (u8 *)ring_header->desc + ring_header->used; ++ ring_header->used += ALIGN(sizeof(struct alx_hw_stats), 8); ++ ++ return 0; ++ ++err_alloc_rx: ++ alx_free_all_rx_descriptor(adpt); ++err_alloc_tx: ++ alx_free_all_tx_descriptor(adpt); ++err_alloc_dma: ++ return retval; ++} ++ ++ ++/* ++ * alx_alloc_all_rtx_descriptor - allocate Tx / RX descriptor queues ++ */ ++static void alx_free_all_rtx_descriptor(struct alx_adapter *adpt) ++{ ++ struct pci_dev *pdev = adpt->pdev; ++ struct alx_ring_header *ring_header = &adpt->ring_header; ++ ++ alx_free_all_tx_descriptor(adpt); ++ alx_free_all_rx_descriptor(adpt); ++ ++ adpt->cmb.dma = 0; ++ adpt->cmb.cmb = NULL; ++ adpt->smb.dma = 0; ++ adpt->smb.smb = NULL; ++ ++ pci_free_consistent(pdev, ring_header->size, ring_header->desc, ++ ring_header->dma); ++ ring_header->desc = NULL; ++ ring_header->size = ring_header->used = 0; ++} ++ ++ ++static netdev_features_t alx_fix_features(struct net_device *netdev, ++ netdev_features_t features) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ /* ++ * Since there is no support for separate rx/tx vlan accel ++ * enable/disable make sure tx flag is always in same state as rx. ++ */ ++ if (features & NETIF_F_HW_VLAN_RX) ++ features |= NETIF_F_HW_VLAN_TX; ++ else ++ features &= ~NETIF_F_HW_VLAN_TX; ++ ++ if (netdev->mtu > ALX_MAX_TSO_PKT_SIZE || ++ adpt->hw.mac_type == alx_mac_l1c || ++ adpt->hw.mac_type == alx_mac_l2c) ++ features &= ~(NETIF_F_TSO | NETIF_F_TSO6); ++ ++ return features; ++} ++ ++ ++static int alx_set_features(struct net_device *netdev, ++ netdev_features_t features) ++{ ++ netdev_features_t changed = netdev->features ^ features; ++ ++ if (changed & NETIF_F_HW_VLAN_RX) ++ alx_vlan_mode(netdev, features); ++ return 0; ++} ++/* ++ * alx_change_mtu - Change the Maximum Transfer Unit ++ */ ++static int alx_change_mtu(struct net_device *netdev, int new_mtu) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ int old_mtu = netdev->mtu; ++ int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; ++ ++ if ((max_frame < ALX_MIN_ETH_FRAME_SIZE) || ++ (max_frame > ALX_MAX_ETH_FRAME_SIZE)) { ++ alx_err(adpt, "invalid MTU setting\n"); ++ return -EINVAL; ++ } ++ /* set MTU */ ++ if (old_mtu != new_mtu && netif_running(netdev)) { ++ netif_info(adpt, hw, adpt->netdev, ++ "changing MTU from %d to %d\n", ++ netdev->mtu, new_mtu); ++ netdev->mtu = new_mtu; ++ adpt->hw.mtu = new_mtu; ++ adpt->rxbuf_size = new_mtu > ALX_DEF_RX_BUF_SIZE ? ++ ALIGN(max_frame, 8) : ALX_DEF_RX_BUF_SIZE; ++ netdev_update_features(netdev); ++ alx_reinit_locked(adpt); ++ } ++ ++ return 0; ++} ++ ++ ++static int alx_open_internal(struct alx_adapter *adpt, u32 ctrl) ++{ ++ struct alx_hw *hw = &adpt->hw; ++ int retval = 0; ++ int i; ++ ++ alx_init_ring_ptrs(adpt); ++ ++ alx_set_multicase_list(adpt->netdev); ++ alx_restore_vlan(adpt); ++ ++ if (hw->cbs.config_mac) ++ retval = hw->cbs.config_mac(hw, adpt->rxbuf_size, ++ adpt->num_hw_rxques, adpt->num_rxdescs, ++ adpt->num_txques, adpt->num_txdescs); ++ ++ if (hw->cbs.config_tx) ++ retval = hw->cbs.config_tx(hw); ++ ++ if (hw->cbs.config_rx) ++ retval = hw->cbs.config_rx(hw); ++ ++ alx_config_rss(adpt); ++ ++ for (i = 0; i < adpt->num_hw_rxques; i++) ++ alx_refresh_rx_buffer(adpt->rx_queue[i]); ++ ++ /* configure HW regsiters of MSIX */ ++ if (hw->cbs.config_msix) ++ retval = hw->cbs.config_msix(hw, adpt->num_msix_intrs, ++ CHK_ADPT_FLAG(0, MSIX_EN), ++ CHK_ADPT_FLAG(0, MSI_EN)); ++ ++ if (ctrl & ALX_OPEN_CTRL_IRQ_EN) { ++ retval = alx_request_irq(adpt); ++ if (retval) ++ goto err_request_irq; ++ } ++ ++ /* enable NAPI, INTR and TX */ ++ alx_napi_enable_all(adpt); ++ ++ alx_enable_intr(adpt); ++ ++ netif_tx_start_all_queues(adpt->netdev); ++ ++ CLI_ADPT_FLAG(1, STATE_DOWN); ++ ++ /* check link status */ ++ SET_ADPT_FLAG(0, TASK_LSC_REQ); ++ adpt->link_jiffies = jiffies + ALX_TRY_LINK_TIMEOUT; ++ mod_timer(&adpt->alx_timer, jiffies); ++ ++ return retval; ++ ++err_request_irq: ++ alx_clean_all_rx_queues(adpt); ++ return retval; ++} ++ ++ ++static void alx_stop_internal(struct alx_adapter *adpt, u32 ctrl) ++{ ++ struct net_device *netdev = adpt->netdev; ++ struct alx_hw *hw = &adpt->hw; ++ ++ SET_ADPT_FLAG(1, STATE_DOWN); ++ ++ netif_tx_stop_all_queues(netdev); ++ /* call carrier off first to avoid false dev_watchdog timeouts */ ++ netif_carrier_off(netdev); ++ netif_tx_disable(netdev); ++ ++ alx_disable_intr(adpt); ++ ++ alx_napi_disable_all(adpt); ++ ++ if (ctrl & ALX_OPEN_CTRL_IRQ_EN) ++ alx_free_irq(adpt); ++ ++ CLI_ADPT_FLAG(0, TASK_LSC_REQ); ++ CLI_ADPT_FLAG(0, TASK_REINIT_REQ); ++ del_timer_sync(&adpt->alx_timer); ++ ++ if (ctrl & ALX_OPEN_CTRL_RESET_PHY) ++ hw->cbs.reset_phy(hw); ++ ++ if (ctrl & ALX_OPEN_CTRL_RESET_MAC) ++ hw->cbs.reset_mac(hw); ++ ++ adpt->hw.link_speed = ALX_LINK_SPEED_UNKNOWN; ++ ++ alx_clean_all_tx_queues(adpt); ++ alx_clean_all_rx_queues(adpt); ++} ++ ++ ++/* ++ * alx_open - Called when a network interface is made active ++ */ ++static int alx_open(struct net_device *netdev) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ int retval; ++ ++ /* disallow open during test */ ++ if (CHK_ADPT_FLAG(1, STATE_TESTING) || ++ CHK_ADPT_FLAG(1, STATE_DIAG_RUNNING)) ++ return -EBUSY; ++ ++ netif_carrier_off(netdev); ++ ++ /* allocate rx/tx dma buffer & descriptors */ ++ retval = alx_alloc_all_rtx_descriptor(adpt); ++ if (retval) { ++ alx_err(adpt, "error in alx_alloc_all_rtx_descriptor\n"); ++ goto err_alloc_rtx; ++ } ++ ++ retval = alx_open_internal(adpt, ALX_OPEN_CTRL_IRQ_EN); ++ if (retval) ++ goto err_open_internal; ++ ++ return retval; ++ ++err_open_internal: ++ alx_stop_internal(adpt, ALX_OPEN_CTRL_IRQ_EN); ++err_alloc_rtx: ++ alx_free_all_rtx_descriptor(adpt); ++ hw->cbs.reset_mac(hw); ++ return retval; ++} ++ ++ ++/* ++ * alx_stop - Disables a network interface ++ */ ++static int alx_stop(struct net_device *netdev) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ ++ if (CHK_ADPT_FLAG(1, STATE_RESETTING)) ++ netif_warn(adpt, ifdown, adpt->netdev, ++ "flag STATE_RESETTING has already set\n"); ++ ++ alx_stop_internal(adpt, ALX_OPEN_CTRL_IRQ_EN | ++ ALX_OPEN_CTRL_RESET_MAC); ++ alx_free_all_rtx_descriptor(adpt); ++ ++ return 0; ++} ++ ++ ++static int alx_shutdown_internal(struct pci_dev *pdev, bool *wakeup) ++{ ++ struct alx_adapter *adpt = pci_get_drvdata(pdev); ++ struct net_device *netdev = adpt->netdev; ++ struct alx_hw *hw = &adpt->hw; ++ u32 wufc = adpt->wol; ++ u16 lpa; ++ u32 speed, adv_speed, misc; ++ bool link_up; ++ int i; ++ int retval = 0; ++ ++ hw->cbs.config_aspm(hw, false, false); ++ ++ netif_device_detach(netdev); ++ if (netif_running(netdev)) ++ alx_stop_internal(adpt, 0); ++ ++#ifdef CONFIG_PM_SLEEP ++ retval = pci_save_state(pdev); ++ if (retval) ++ return retval; ++#endif ++ hw->cbs.check_phy_link(hw, &speed, &link_up); ++ ++ if (link_up) { ++ if (hw->mac_type == alx_mac_l1f || ++ hw->mac_type == alx_mac_l2f) { ++ alx_mem_r32(hw, ALX_MISC, &misc); ++ misc |= ALX_MISC_INTNLOSC_OPEN; ++ alx_mem_w32(hw, ALX_MISC, misc); ++ } ++ ++ retval = hw->cbs.read_phy_reg(hw, MII_LPA, &lpa); ++ if (retval) ++ return retval; ++ ++ adv_speed = ALX_LINK_SPEED_10_HALF; ++ if (lpa & LPA_10FULL) ++ adv_speed = ALX_LINK_SPEED_10_FULL; ++ else if (lpa & LPA_10HALF) ++ adv_speed = ALX_LINK_SPEED_10_HALF; ++ else if (lpa & LPA_100FULL) ++ adv_speed = ALX_LINK_SPEED_100_FULL; ++ else if (lpa & LPA_100HALF) ++ adv_speed = ALX_LINK_SPEED_100_HALF; ++ ++ retval = hw->cbs.setup_phy_link(hw, adv_speed, true, ++ !hw->disable_fc_autoneg); ++ if (retval) ++ return retval; ++ ++ for (i = 0; i < ALX_MAX_SETUP_LNK_CYCLE; i++) { ++ mdelay(100); ++ retval = hw->cbs.check_phy_link(hw, &speed, &link_up); ++ if (retval) ++ continue; ++ if (link_up) ++ break; ++ } ++ } else { ++ speed = ALX_LINK_SPEED_10_HALF; ++ link_up = false; ++ } ++ hw->link_speed = speed; ++ hw->link_up = link_up; ++ ++ retval = hw->cbs.config_wol(hw, wufc); ++ if (retval) ++ return retval; ++ ++ /* clear phy interrupt */ ++ retval = hw->cbs.ack_phy_intr(hw); ++ if (retval) ++ return retval; ++ ++ if (wufc) { ++ /* pcie patch */ ++ device_set_wakeup_enable(&pdev->dev, 1); ++ } ++ ++ retval = hw->cbs.config_pow_save(hw, adpt->hw.link_speed, ++ (wufc ? true : false), false, ++ (wufc & ALX_WOL_MAGIC ? true : false), true); ++ if (retval) ++ return retval; ++ ++ *wakeup = wufc ? true : false; ++ pci_disable_device(pdev); ++ return 0; ++} ++ ++ ++static void alx_shutdown(struct pci_dev *pdev) ++{ ++ bool wakeup; ++ alx_shutdown_internal(pdev, &wakeup); ++ ++ pci_wake_from_d3(pdev, wakeup); ++ pci_set_power_state(pdev, PCI_D3hot); ++} ++ ++ ++#ifdef CONFIG_PM_SLEEP ++static int alx_suspend(struct device *dev) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ int retval; ++ bool wakeup; ++ ++ retval = alx_shutdown_internal(pdev, &wakeup); ++ if (retval) ++ return retval; ++ ++ if (wakeup) { ++ pci_prepare_to_sleep(pdev); ++ } else { ++ pci_wake_from_d3(pdev, false); ++ pci_set_power_state(pdev, PCI_D3hot); ++ } ++ ++ return 0; ++} ++ ++ ++static int alx_resume(struct device *dev) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ struct alx_adapter *adpt = pci_get_drvdata(pdev); ++ struct net_device *netdev = adpt->netdev; ++ struct alx_hw *hw = &adpt->hw; ++ u32 retval; ++ ++ pci_set_power_state(pdev, PCI_D0); ++ pci_restore_state(pdev); ++ /* ++ * pci_restore_state clears dev->state_saved so call ++ * pci_save_state to restore it. ++ */ ++ pci_save_state(pdev); ++ ++ pci_enable_wake(pdev, PCI_D3hot, 0); ++ pci_enable_wake(pdev, PCI_D3cold, 0); ++ ++ retval = hw->cbs.reset_pcie(hw, true, true); ++ retval = hw->cbs.reset_phy(hw); ++ retval = hw->cbs.reset_mac(hw); ++ retval = hw->cbs.setup_phy_link(hw, hw->autoneg_advertised, true, ++ !hw->disable_fc_autoneg); ++ ++ retval = hw->cbs.config_wol(hw, 0); ++ ++ if (netif_running(netdev)) { ++ retval = alx_open_internal(adpt, 0); ++ if (retval) ++ return retval; ++ } ++ ++ netif_device_attach(netdev); ++ return 0; ++} ++#endif ++ ++ ++/* ++ * alx_update_hw_stats - Update the board statistics counters. ++ */ ++static void alx_update_hw_stats(struct alx_adapter *adpt) ++{ ++ struct net_device_stats *net_stats; ++ struct alx_hw *hw = &adpt->hw; ++ struct alx_hw_stats *hwstats = &adpt->hw_stats; ++ unsigned long *hwstat_item = NULL; ++ u32 hwstat_reg; ++ u32 hwstat_data; ++ ++ if (CHK_ADPT_FLAG(1, STATE_DOWN) || CHK_ADPT_FLAG(1, STATE_RESETTING)) ++ return; ++ ++ /* update RX status */ ++ hwstat_reg = hw->rxstat_reg; ++ hwstat_item = &hwstats->rx_ok; ++ while (hwstat_reg < hw->rxstat_reg + hw->rxstat_sz) { ++ alx_mem_r32(hw, hwstat_reg, &hwstat_data); ++ *hwstat_item += hwstat_data; ++ hwstat_reg += 4; ++ hwstat_item++; ++ } ++ ++ /* update TX status */ ++ hwstat_reg = hw->txstat_reg; ++ hwstat_item = &hwstats->tx_ok; ++ while (hwstat_reg < hw->txstat_reg + hw->txstat_sz) { ++ alx_mem_r32(hw, hwstat_reg, &hwstat_data); ++ *hwstat_item += hwstat_data; ++ hwstat_reg += 4; ++ hwstat_item++; ++ } ++ ++ net_stats = &adpt->netdev->stats; ++ net_stats->rx_packets = hwstats->rx_ok; ++ net_stats->tx_packets = hwstats->tx_ok; ++ net_stats->rx_bytes = hwstats->rx_byte_cnt; ++ net_stats->tx_bytes = hwstats->tx_byte_cnt; ++ net_stats->multicast = hwstats->rx_mcast; ++ net_stats->collisions = hwstats->tx_single_col + ++ hwstats->tx_multi_col * 2 + ++ hwstats->tx_late_col + hwstats->tx_abort_col; ++ ++ net_stats->rx_errors = hwstats->rx_frag + hwstats->rx_fcs_err + ++ hwstats->rx_len_err + hwstats->rx_ov_sz + ++ hwstats->rx_ov_rrd + hwstats->rx_align_err; ++ ++ net_stats->rx_fifo_errors = hwstats->rx_ov_rxf; ++ net_stats->rx_length_errors = hwstats->rx_len_err; ++ net_stats->rx_crc_errors = hwstats->rx_fcs_err; ++ net_stats->rx_frame_errors = hwstats->rx_align_err; ++ net_stats->rx_over_errors = hwstats->rx_ov_rrd + hwstats->rx_ov_rxf; ++ ++ net_stats->rx_missed_errors = hwstats->rx_ov_rrd + hwstats->rx_ov_rxf; ++ ++ net_stats->tx_errors = hwstats->tx_late_col + hwstats->tx_abort_col + ++ hwstats->tx_underrun + hwstats->tx_trunc; ++ net_stats->tx_fifo_errors = hwstats->tx_underrun; ++ net_stats->tx_aborted_errors = hwstats->tx_abort_col; ++ net_stats->tx_window_errors = hwstats->tx_late_col; ++} ++ ++ ++/* ++ * alx_get_stats - Get System Network Statistics ++ * ++ * Returns the address of the device statistics structure. ++ * The statistics are actually updated from the timer callback. ++ */ ++static struct net_device_stats *alx_get_stats(struct net_device *netdev) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ ++ alx_update_hw_stats(adpt); ++ return &netdev->stats; ++} ++ ++ ++static void alx_link_task_routine(struct alx_adapter *adpt) ++{ ++ struct net_device *netdev = adpt->netdev; ++ struct alx_hw *hw = &adpt->hw; ++ char *link_desc; ++ ++ if (!CHK_ADPT_FLAG(0, TASK_LSC_REQ)) ++ return; ++ CLI_ADPT_FLAG(0, TASK_LSC_REQ); ++ ++ if (CHK_ADPT_FLAG(1, STATE_DOWN)) ++ return; ++ ++ if (hw->cbs.check_phy_link) { ++ hw->cbs.check_phy_link(hw, ++ &hw->link_speed, &hw->link_up); ++ } else { ++ /* always assume link is up, if no check link function */ ++ hw->link_speed = ALX_LINK_SPEED_1GB_FULL; ++ hw->link_up = true; ++ } ++ netif_info(adpt, timer, adpt->netdev, ++ "link_speed = %d, link_up = %d\n", ++ hw->link_speed, hw->link_up); ++ ++ if (!hw->link_up && time_after(adpt->link_jiffies, jiffies)) ++ SET_ADPT_FLAG(0, TASK_LSC_REQ); ++ ++ if (hw->link_up) { ++ if (netif_carrier_ok(netdev)) ++ return; ++ ++ link_desc = (hw->link_speed == ALX_LINK_SPEED_1GB_FULL) ? ++ "1 Gbps Duplex Full" : ++ (hw->link_speed == ALX_LINK_SPEED_100_FULL ? ++ "100 Mbps Duplex Full" : ++ (hw->link_speed == ALX_LINK_SPEED_100_HALF ? ++ "100 Mbps Duplex Half" : ++ (hw->link_speed == ALX_LINK_SPEED_10_FULL ? ++ "10 Mbps Duplex Full" : ++ (hw->link_speed == ALX_LINK_SPEED_10_HALF ? ++ "10 Mbps Duplex HALF" : ++ "unknown speed")))); ++ netif_info(adpt, timer, adpt->netdev, ++ "NIC Link is Up %s\n", link_desc); ++ ++ hw->cbs.config_aspm(hw, true, true); ++ hw->cbs.start_mac(hw); ++ netif_carrier_on(netdev); ++ netif_tx_wake_all_queues(netdev); ++ } else { ++ /* only continue if link was up previously */ ++ if (!netif_carrier_ok(netdev)) ++ return; ++ ++ hw->link_speed = 0; ++ netif_info(adpt, timer, adpt->netdev, "NIC Link is Down\n"); ++ netif_carrier_off(netdev); ++ netif_tx_stop_all_queues(netdev); ++ ++ hw->cbs.stop_mac(hw); ++ hw->cbs.config_aspm(hw, false, true); ++ hw->cbs.setup_phy_link(hw, hw->autoneg_advertised, true, ++ !hw->disable_fc_autoneg); ++ } ++} ++ ++ ++static void alx_reinit_task_routine(struct alx_adapter *adpt) ++{ ++ if (!CHK_ADPT_FLAG(0, TASK_REINIT_REQ)) ++ return; ++ CLI_ADPT_FLAG(0, TASK_REINIT_REQ); ++ ++ if (CHK_ADPT_FLAG(1, STATE_DOWN) || CHK_ADPT_FLAG(1, STATE_RESETTING)) ++ return; ++ ++ alx_reinit_locked(adpt); ++} ++ ++ ++/* ++ * alx_timer_routine - Timer Call-back ++ */ ++static void alx_timer_routine(unsigned long data) ++{ ++ struct alx_adapter *adpt = (struct alx_adapter *)data; ++ unsigned long delay; ++ ++ /* poll faster when waiting for link */ ++ if (CHK_ADPT_FLAG(0, TASK_LSC_REQ)) ++ delay = HZ / 10; ++ else ++ delay = HZ * 2; ++ ++ /* Reset the timer */ ++ mod_timer(&adpt->alx_timer, delay + jiffies); ++ ++ alx_task_schedule(adpt); ++} ++ ++ ++/* ++ * alx_task_routine - manages and runs subtasks ++ */ ++static void alx_task_routine(struct work_struct *work) ++{ ++ struct alx_adapter *adpt = container_of(work, ++ struct alx_adapter, alx_task); ++ /* test state of adapter */ ++ if (!CHK_ADPT_FLAG(1, STATE_WATCH_DOG)) ++ netif_warn(adpt, timer, adpt->netdev, ++ "flag STATE_WATCH_DOG doesn't set\n"); ++ ++ /* reinit task */ ++ alx_reinit_task_routine(adpt); ++ ++ /* link task */ ++ alx_link_task_routine(adpt); ++ ++ /* flush memory to make sure state is correct before next watchog */ ++ smp_mb__before_clear_bit(); ++ ++ CLI_ADPT_FLAG(1, STATE_WATCH_DOG); ++} ++ ++ ++/* Calculate the transmit packet descript needed*/ ++static bool alx_check_num_tpdescs(struct alx_tx_queue *txque, ++ const struct sk_buff *skb) ++{ ++ u16 num_required = 1; ++ u16 num_available = 0; ++ u16 produce_idx = txque->tpq.produce_idx; ++ u16 consume_idx = txque->tpq.consume_idx; ++ int i = 0; ++ ++ u16 proto_hdr_len = 0; ++ if (skb_is_gso(skb)) { ++ proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); ++ if (proto_hdr_len < skb_headlen(skb)) ++ num_required++; ++ if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) ++ num_required++; ++ } ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) ++ num_required++; ++ num_available = (u16)(consume_idx > produce_idx) ? ++ (consume_idx - produce_idx - 1) : ++ (txque->tpq.count + consume_idx - produce_idx - 1); ++ ++ return num_required < num_available; ++} ++ ++ ++static int alx_tso_csum(struct alx_adapter *adpt, ++ struct alx_tx_queue *txque, ++ struct sk_buff *skb, ++ union alx_sw_tpdesc *stpd) ++{ ++ struct pci_dev *pdev = adpt->pdev; ++ u8 hdr_len; ++ int retval; ++ ++ if (skb_is_gso(skb)) { ++ if (skb_header_cloned(skb)) { ++ retval = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); ++ if (unlikely(retval)) ++ return retval; ++ } ++ ++ if (skb->protocol == htons(ETH_P_IP)) { ++ u32 pkt_len = ++ ((unsigned char *)ip_hdr(skb) - skb->data) + ++ ntohs(ip_hdr(skb)->tot_len); ++ if (skb->len > pkt_len) ++ pskb_trim(skb, pkt_len); ++ } ++ ++ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); ++ if (unlikely(skb->len == hdr_len)) { ++ /* we only need to do csum */ ++ dev_warn(&pdev->dev, ++ "tso doesn't need, if packet with 0 data\n"); ++ goto do_csum; ++ } ++ ++ if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) { ++ ip_hdr(skb)->check = 0; ++ tcp_hdr(skb)->check = ~csum_tcpudp_magic( ++ ip_hdr(skb)->saddr, ++ ip_hdr(skb)->daddr, ++ 0, IPPROTO_TCP, 0); ++ stpd->genr.ipv4 = 1; ++ } ++ ++ if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) { ++ /* ipv6 tso need an extra tpd */ ++ union alx_sw_tpdesc extra_tpd; ++ ++ memset(stpd, 0, sizeof(union alx_sw_tpdesc)); ++ memset(&extra_tpd, 0, sizeof(union alx_sw_tpdesc)); ++ ++ ipv6_hdr(skb)->payload_len = 0; ++ tcp_hdr(skb)->check = ~csum_ipv6_magic( ++ &ipv6_hdr(skb)->saddr, ++ &ipv6_hdr(skb)->daddr, ++ 0, IPPROTO_TCP, 0); ++ extra_tpd.tso.addr_lo = skb->len; ++ extra_tpd.tso.lso = 0x1; ++ extra_tpd.tso.lso_v2 = 0x1; ++ alx_set_tpdesc(txque, &extra_tpd); ++ stpd->tso.lso_v2 = 0x1; ++ } ++ ++ stpd->tso.lso = 0x1; ++ stpd->tso.tcphdr_offset = skb_transport_offset(skb); ++ stpd->tso.mss = skb_shinfo(skb)->gso_size; ++ return 0; ++ } ++ ++do_csum: ++ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { ++ u8 css, cso; ++ cso = skb_checksum_start_offset(skb); ++ ++ if (unlikely(cso & 0x1)) { ++ dev_err(&pdev->dev, "pay load offset should not be an " ++ "event number\n"); ++ return -1; ++ } else { ++ css = cso + skb->csum_offset; ++ ++ stpd->csum.payld_offset = cso >> 1; ++ stpd->csum.cxsum_offset = css >> 1; ++ stpd->csum.c_sum = 0x1; ++ } ++ } ++ return 0; ++} ++ ++ ++static void alx_tx_map(struct alx_adapter *adpt, ++ struct alx_tx_queue *txque, ++ struct sk_buff *skb, ++ union alx_sw_tpdesc *stpd) ++{ ++ struct alx_buffer *tpbuf = NULL; ++ ++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags; ++ ++ unsigned int len = skb_headlen(skb); ++ ++ u16 map_len = 0; ++ u16 mapped_len = 0; ++ u16 hdr_len = 0; ++ u16 f; ++ u32 tso = stpd->tso.lso; ++ ++ if (tso) { ++ /* TSO */ ++ map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); ++ ++ tpbuf = GET_TP_BUFFER(txque, txque->tpq.produce_idx); ++ tpbuf->length = map_len; ++ tpbuf->dma = dma_map_single(txque->dev, ++ skb->data, hdr_len, DMA_TO_DEVICE); ++ mapped_len += map_len; ++ stpd->genr.addr = tpbuf->dma; ++ stpd->genr.buffer_len = tpbuf->length; ++ ++ alx_set_tpdesc(txque, stpd); ++ } ++ ++ if (mapped_len < len) { ++ tpbuf = GET_TP_BUFFER(txque, txque->tpq.produce_idx); ++ tpbuf->length = len - mapped_len; ++ tpbuf->dma = ++ dma_map_single(txque->dev, skb->data + mapped_len, ++ tpbuf->length, DMA_TO_DEVICE); ++ stpd->genr.addr = tpbuf->dma; ++ stpd->genr.buffer_len = tpbuf->length; ++ alx_set_tpdesc(txque, stpd); ++ } ++ ++ for (f = 0; f < nr_frags; f++) { ++ struct skb_frag_struct *frag; ++ ++ frag = &skb_shinfo(skb)->frags[f]; ++ ++ tpbuf = GET_TP_BUFFER(txque, txque->tpq.produce_idx); ++ tpbuf->length = skb_frag_size(frag); ++ tpbuf->dma = skb_frag_dma_map(txque->dev, frag, 0, ++ tpbuf->length, DMA_TO_DEVICE); ++ stpd->genr.addr = tpbuf->dma; ++ stpd->genr.buffer_len = tpbuf->length; ++ alx_set_tpdesc(txque, stpd); ++ } ++ ++ ++ /* The last tpd */ ++ alx_set_tpdesc_lastfrag(txque); ++ /* ++ * The last buffer info contain the skb address, ++ * so it will be free after unmap ++ */ ++ tpbuf->skb = skb; ++} ++ ++ ++static netdev_tx_t alx_start_xmit_frame(struct alx_adapter *adpt, ++ struct alx_tx_queue *txque, ++ struct sk_buff *skb) ++{ ++ struct alx_hw *hw = &adpt->hw; ++ unsigned long flags = 0; ++ union alx_sw_tpdesc stpd; /* normal*/ ++ ++ if (CHK_ADPT_FLAG(1, STATE_DOWN) || ++ CHK_ADPT_FLAG(1, STATE_DIAG_RUNNING)) { ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } ++ ++ if (!spin_trylock_irqsave(&adpt->tx_lock, flags)) { ++ alx_err(adpt, "tx locked!\n"); ++ return NETDEV_TX_LOCKED; ++ } ++ ++ if (!alx_check_num_tpdescs(txque, skb)) { ++ /* no enough descriptor, just stop queue */ ++ netif_stop_queue(adpt->netdev); ++ spin_unlock_irqrestore(&adpt->tx_lock, flags); ++ return NETDEV_TX_BUSY; ++ } ++ ++ memset(&stpd, 0, sizeof(union alx_sw_tpdesc)); ++ /* do TSO and check sum */ ++ if (alx_tso_csum(adpt, txque, skb, &stpd) != 0) { ++ spin_unlock_irqrestore(&adpt->tx_lock, flags); ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } ++ ++ if (unlikely(vlan_tx_tag_present(skb))) { ++ u16 vlan = vlan_tx_tag_get(skb); ++ u16 tag; ++ ALX_VLAN_TO_TAG(vlan, tag); ++ stpd.genr.vlan_tag = tag; ++ stpd.genr.instag = 0x1; ++ } ++ ++ if (skb_network_offset(skb) != ETH_HLEN) ++ stpd.genr.type = 0x1; /* Ethernet frame */ ++ ++ alx_tx_map(adpt, txque, skb, &stpd); ++ ++ ++ /* update produce idx */ ++ wmb(); ++ alx_mem_w16(hw, txque->produce_reg, txque->tpq.produce_idx); ++ netif_info(adpt, tx_err, adpt->netdev, ++ "TX[%d]: tpq.consume_idx = 0x%x, tpq.produce_idx = 0x%x\n", ++ txque->que_idx, txque->tpq.consume_idx, ++ txque->tpq.produce_idx); ++ netif_info(adpt, tx_err, adpt->netdev, ++ "TX[%d]: Produce Reg[%x] = 0x%x\n", ++ txque->que_idx, txque->produce_reg, txque->tpq.produce_idx); ++ ++ spin_unlock_irqrestore(&adpt->tx_lock, flags); ++ return NETDEV_TX_OK; ++} ++ ++ ++static netdev_tx_t alx_start_xmit(struct sk_buff *skb, ++ struct net_device *netdev) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_tx_queue *txque; ++ ++ txque = adpt->tx_queue[0]; ++ return alx_start_xmit_frame(adpt, txque, skb); ++} ++ ++ ++/* ++ * alx_mii_ioctl ++ */ ++static int alx_mii_ioctl(struct net_device *netdev, ++ struct ifreq *ifr, int cmd) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ struct alx_hw *hw = &adpt->hw; ++ struct mii_ioctl_data *data = if_mii(ifr); ++ int retval = 0; ++ ++ if (!netif_running(netdev)) ++ return -EINVAL; ++ ++ switch (cmd) { ++ case SIOCGMIIPHY: ++ data->phy_id = 0; ++ break; ++ ++ case SIOCGMIIREG: ++ if (data->reg_num & ~(0x1F)) { ++ retval = -EFAULT; ++ goto out; ++ } ++ ++ retval = hw->cbs.read_phy_reg(hw, data->reg_num, ++ &data->val_out); ++ netif_dbg(adpt, hw, adpt->netdev, "read phy %02x %04x\n", ++ data->reg_num, data->val_out); ++ if (retval) { ++ retval = -EIO; ++ goto out; ++ } ++ break; ++ ++ case SIOCSMIIREG: ++ if (data->reg_num & ~(0x1F)) { ++ retval = -EFAULT; ++ goto out; ++ } ++ ++ retval = hw->cbs.write_phy_reg(hw, data->reg_num, data->val_in); ++ netif_dbg(adpt, hw, adpt->netdev, "write phy %02x %04x\n", ++ data->reg_num, data->val_in); ++ if (retval) { ++ retval = -EIO; ++ goto out; ++ } ++ break; ++ default: ++ retval = -EOPNOTSUPP; ++ break; ++ } ++out: ++ return retval; ++ ++} ++ ++ ++static int alx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) ++{ ++ switch (cmd) { ++ case SIOCGMIIPHY: ++ case SIOCGMIIREG: ++ case SIOCSMIIREG: ++ return alx_mii_ioctl(netdev, ifr, cmd); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++ ++#ifdef CONFIG_NET_POLL_CONTROLLER ++static void alx_poll_controller(struct net_device *netdev) ++{ ++ struct alx_adapter *adpt = netdev_priv(netdev); ++ int num_msix_intrs = adpt->num_msix_intrs; ++ int msix_idx; ++ ++ /* if interface is down do nothing */ ++ if (CHK_ADPT_FLAG(1, STATE_DOWN)) ++ return; ++ ++ if (CHK_ADPT_FLAG(0, MSIX_EN)) { ++ for (msix_idx = 0; msix_idx < num_msix_intrs; msix_idx++) { ++ struct alx_msix_param *msix = adpt->msix[msix_idx]; ++ if (CHK_MSIX_FLAG(RXS) || CHK_MSIX_FLAG(TXS)) ++ alx_msix_rtx(0, msix); ++ else if (CHK_MSIX_FLAG(TIMER)) ++ alx_msix_timer(0, msix); ++ else if (CHK_MSIX_FLAG(ALERT)) ++ alx_msix_alert(0, msix); ++ else if (CHK_MSIX_FLAG(SMB)) ++ alx_msix_smb(0, msix); ++ else if (CHK_MSIX_FLAG(PHY)) ++ alx_msix_phy(0, msix); ++ } ++ } else { ++ alx_interrupt(adpt->pdev->irq, netdev); ++ } ++} ++#endif ++ ++ ++static const struct net_device_ops alx_netdev_ops = { ++ .ndo_open = alx_open, ++ .ndo_stop = alx_stop, ++ .ndo_start_xmit = alx_start_xmit, ++ .ndo_get_stats = alx_get_stats, ++ .ndo_set_rx_mode = alx_set_multicase_list, ++ .ndo_validate_addr = eth_validate_addr, ++ .ndo_set_mac_address = alx_set_mac_address, ++ .ndo_change_mtu = alx_change_mtu, ++ .ndo_do_ioctl = alx_ioctl, ++ .ndo_tx_timeout = alx_tx_timeout, ++ .ndo_fix_features = alx_fix_features, ++ .ndo_set_features = alx_set_features, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = alx_poll_controller, ++#endif ++}; ++ ++ ++/* ++ * alx_init - Device Initialization Routine ++ */ ++static int __devinit alx_init(struct pci_dev *pdev, ++ const struct pci_device_id *ent) ++{ ++ struct net_device *netdev; ++ struct alx_adapter *adpt = NULL; ++ struct alx_hw *hw = NULL; ++ static int cards_found; ++ int retval; ++ ++ /* enable device (incl. PCI PM wakeup and hotplug setup) */ ++ retval = pci_enable_device_mem(pdev); ++ if (retval) { ++ dev_err(&pdev->dev, "cannot enable PCI device\n"); ++ goto err_alloc_device; ++ } ++ ++ /* ++ * The alx chip can DMA to 64-bit addresses, but it uses a single ++ * shared register for the high 32 bits, so only a single, aligned, ++ * 4 GB physical address range can be used at a time. ++ */ ++ if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) && ++ !dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64))) { ++ dev_info(&pdev->dev, "DMA to 64-BIT addresses\n"); ++ } else { ++ retval = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); ++ if (retval) { ++ retval = dma_set_coherent_mask(&pdev->dev, ++ DMA_BIT_MASK(32)); ++ if (retval) { ++ dev_err(&pdev->dev, ++ "No usable DMA config, aborting\n"); ++ goto err_alloc_pci_res_mem; ++ } ++ } ++ } ++ ++ retval = pci_request_selected_regions(pdev, pci_select_bars(pdev, ++ IORESOURCE_MEM), alx_drv_name); ++ if (retval) { ++ dev_err(&pdev->dev, ++ "pci_request_selected_regions failed 0x%x\n", retval); ++ goto err_alloc_pci_res_mem; ++ } ++ ++ ++ pci_enable_pcie_error_reporting(pdev); ++ pci_set_master(pdev); ++ ++ netdev = alloc_etherdev(sizeof(struct alx_adapter)); ++ if (netdev == NULL) { ++ dev_err(&pdev->dev, "etherdev alloc failed\n"); ++ retval = -ENOMEM; ++ goto err_alloc_netdev; ++ } ++ ++ SET_NETDEV_DEV(netdev, &pdev->dev); ++ netdev->irq = pdev->irq; ++ ++ adpt = netdev_priv(netdev); ++ pci_set_drvdata(pdev, adpt); ++ adpt->netdev = netdev; ++ adpt->pdev = pdev; ++ hw = &adpt->hw; ++ hw->adpt = adpt; ++ adpt->msg_enable = ALX_MSG_DEFAULT; ++ ++ adpt->hw.hw_addr = ioremap(pci_resource_start(pdev, BAR_0), ++ pci_resource_len(pdev, BAR_0)); ++ if (!adpt->hw.hw_addr) { ++ alx_err(adpt, "cannot map device registers\n"); ++ retval = -EIO; ++ goto err_iomap; ++ } ++ netdev->base_addr = (unsigned long)adpt->hw.hw_addr; ++ ++ /* set cb member of netdev structure*/ ++ netdev->netdev_ops = &alx_netdev_ops; ++ alx_set_ethtool_ops(netdev); ++ netdev->watchdog_timeo = ALX_WATCHDOG_TIME; ++ strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); ++ ++ adpt->bd_number = cards_found; ++ ++ /* init alx_adapte structure */ ++ retval = alx_init_adapter(adpt); ++ if (retval) { ++ alx_err(adpt, "net device private data init failed\n"); ++ goto err_init_adapter; ++ } ++ ++ /* reset pcie */ ++ retval = hw->cbs.reset_pcie(hw, true, true); ++ if (retval) { ++ alx_err(adpt, "PCIE Reset failed, error = %d\n", retval); ++ retval = -EIO; ++ goto err_init_adapter; ++ } ++ ++ /* Init GPHY as early as possible due to power saving issue */ ++ retval = hw->cbs.reset_phy(hw); ++ if (retval) { ++ alx_err(adpt, "PHY Reset failed, error = %d\n", retval); ++ retval = -EIO; ++ goto err_init_adapter; ++ } ++ ++ /* reset mac */ ++ retval = hw->cbs.reset_mac(hw); ++ if (retval) { ++ alx_err(adpt, "MAC Reset failed, error = %d\n", retval); ++ retval = -EIO; ++ goto err_init_adapter; ++ } ++ ++ /* setup link to put it in a known good starting state */ ++ retval = hw->cbs.setup_phy_link(hw, hw->autoneg_advertised, true, ++ !hw->disable_fc_autoneg); ++ ++ /* get user settings */ ++ adpt->num_txdescs = 1024; ++ adpt->num_rxdescs = 512; ++ adpt->max_rxques = min_t(int, ALX_MAX_RX_QUEUES, num_online_cpus()); ++ adpt->max_txques = min_t(int, ALX_MAX_TX_QUEUES, num_online_cpus()); ++ ++ netdev->hw_features = NETIF_F_SG | ++ NETIF_F_HW_CSUM | ++ NETIF_F_HW_VLAN_RX; ++ if (adpt->hw.mac_type != alx_mac_l1c && ++ adpt->hw.mac_type != alx_mac_l2c) { ++ netdev->hw_features = netdev->hw_features | ++ NETIF_F_TSO | ++ NETIF_F_TSO6; ++ } ++ netdev->features = netdev->hw_features | ++ NETIF_F_HW_VLAN_TX; ++ ++ /* get mac addr and perm mac addr, set to register */ ++ if (hw->cbs.get_mac_addr) ++ retval = hw->cbs.get_mac_addr(hw, hw->mac_perm_addr); ++ else ++ retval = -EINVAL; ++ ++ if (retval) { ++ eth_hw_addr_random(netdev); ++ memcpy(hw->mac_perm_addr, netdev->dev_addr, netdev->addr_len); ++ } ++ ++ memcpy(hw->mac_addr, hw->mac_perm_addr, netdev->addr_len); ++ if (hw->cbs.set_mac_addr) ++ hw->cbs.set_mac_addr(hw, hw->mac_addr); ++ ++ memcpy(netdev->dev_addr, hw->mac_perm_addr, netdev->addr_len); ++ memcpy(netdev->perm_addr, hw->mac_perm_addr, netdev->addr_len); ++ retval = alx_validate_mac_addr(netdev->perm_addr); ++ if (retval) { ++ alx_err(adpt, "invalid MAC address\n"); ++ goto err_init_adapter; ++ } ++ ++ setup_timer(&adpt->alx_timer, &alx_timer_routine, ++ (unsigned long)adpt); ++ INIT_WORK(&adpt->alx_task, alx_task_routine); ++ ++ /* Number of supported queues */ ++ alx_set_num_queues(adpt); ++ retval = alx_set_interrupt_mode(adpt); ++ if (retval) { ++ alx_err(adpt, "can't set interrupt mode\n"); ++ goto err_set_interrupt_mode; ++ } ++ ++ retval = alx_set_interrupt_param(adpt); ++ if (retval) { ++ alx_err(adpt, "can't set interrupt parameter\n"); ++ goto err_set_interrupt_param; ++ } ++ ++ retval = alx_alloc_all_rtx_queue(adpt); ++ if (retval) { ++ alx_err(adpt, "can't allocate memory for queues\n"); ++ goto err_alloc_rtx_queue; ++ } ++ ++ alx_set_register_info_special(adpt); ++ ++ netif_dbg(adpt, probe, adpt->netdev, ++ "num_msix_noque_intrs = %d, num_msix_rxque_intrs = %d, " ++ "num_msix_txque_intrs = %d\n", ++ adpt->num_msix_noques, adpt->num_msix_rxques, ++ adpt->num_msix_txques); ++ netif_dbg(adpt, probe, adpt->netdev, "num_msix_all_intrs = %d\n", ++ adpt->num_msix_intrs); ++ ++ netif_dbg(adpt, probe, adpt->netdev, ++ "RX Queue Count = %u, HRX Queue Count = %u, " ++ "SRX Queue Count = %u, TX Queue Count = %u\n", ++ adpt->num_rxques, adpt->num_hw_rxques, adpt->num_sw_rxques, ++ adpt->num_txques); ++ ++ /* WOL not supported for all but the following */ ++ switch (hw->pci_devid) { ++ case ALX_DEV_ID_AR8131: ++ case ALX_DEV_ID_AR8132: ++ case ALX_DEV_ID_AR8151_V1: ++ case ALX_DEV_ID_AR8151_V2: ++ case ALX_DEV_ID_AR8152_V1: ++ case ALX_DEV_ID_AR8152_V2: ++ adpt->wol = (ALX_WOL_MAGIC | ALX_WOL_PHY); ++ break; ++ case ALX_DEV_ID_AR8161: ++ case ALX_DEV_ID_AR8162: ++ adpt->wol = (ALX_WOL_MAGIC | ALX_WOL_PHY); ++ break; ++ default: ++ adpt->wol = 0; ++ break; ++ } ++ device_set_wakeup_enable(&adpt->pdev->dev, adpt->wol); ++ ++ SET_ADPT_FLAG(1, STATE_DOWN); ++ strcpy(netdev->name, "eth%d"); ++ retval = register_netdev(netdev); ++ if (retval) { ++ alx_err(adpt, "register netdevice failed\n"); ++ goto err_register_netdev; ++ } ++ adpt->netdev_registered = true; ++ ++ /* carrier off reporting is important to ethtool even BEFORE open */ ++ netif_carrier_off(netdev); ++ /* keep stopping all the transmit queues for older kernels */ ++ netif_tx_stop_all_queues(netdev); ++ ++ /* print the MAC address */ ++ netif_info(adpt, probe, adpt->netdev, "%pM\n", netdev->dev_addr); ++ ++ /* print the adapter capability */ ++ if (CHK_ADPT_FLAG(0, MSI_CAP)) { ++ netif_info(adpt, probe, adpt->netdev, ++ "MSI Capable: %s\n", ++ CHK_ADPT_FLAG(0, MSI_EN) ? "Enable" : "Disable"); ++ } ++ if (CHK_ADPT_FLAG(0, MSIX_CAP)) { ++ netif_info(adpt, probe, adpt->netdev, ++ "MSIX Capable: %s\n", ++ CHK_ADPT_FLAG(0, MSIX_EN) ? "Enable" : "Disable"); ++ } ++ if (CHK_ADPT_FLAG(0, MRQ_CAP)) { ++ netif_info(adpt, probe, adpt->netdev, ++ "MRQ Capable: %s\n", ++ CHK_ADPT_FLAG(0, MRQ_EN) ? "Enable" : "Disable"); ++ } ++ if (CHK_ADPT_FLAG(0, MRQ_CAP)) { ++ netif_info(adpt, probe, adpt->netdev, ++ "MTQ Capable: %s\n", ++ CHK_ADPT_FLAG(0, MTQ_EN) ? "Enable" : "Disable"); ++ } ++ if (CHK_ADPT_FLAG(0, SRSS_CAP)) { ++ netif_info(adpt, probe, adpt->netdev, ++ "RSS(SW) Capable: %s\n", ++ CHK_ADPT_FLAG(0, SRSS_EN) ? "Enable" : "Disable"); ++ } ++ ++ printk(KERN_INFO "alx: Atheros Gigabit Network Connection\n"); ++ cards_found++; ++ return 0; ++ ++err_register_netdev: ++ alx_free_all_rtx_queue(adpt); ++err_alloc_rtx_queue: ++ alx_reset_interrupt_param(adpt); ++err_set_interrupt_param: ++ alx_reset_interrupt_mode(adpt); ++err_set_interrupt_mode: ++err_init_adapter: ++ iounmap(adpt->hw.hw_addr); ++err_iomap: ++ free_netdev(netdev); ++err_alloc_netdev: ++ pci_release_selected_regions(pdev, ++ pci_select_bars(pdev, IORESOURCE_MEM)); ++err_alloc_pci_res_mem: ++ pci_disable_device(pdev); ++err_alloc_device: ++ dev_err(&pdev->dev, ++ "error when probe device, error = %d\n", retval); ++ return retval; ++} ++ ++ ++/* ++ * alx_remove - Device Removal Routine ++ */ ++static void __devexit alx_remove(struct pci_dev *pdev) ++{ ++ struct alx_adapter *adpt = pci_get_drvdata(pdev); ++ struct alx_hw *hw = &adpt->hw; ++ struct net_device *netdev = adpt->netdev; ++ ++ SET_ADPT_FLAG(1, STATE_DOWN); ++ cancel_work_sync(&adpt->alx_task); ++ ++ hw->cbs.config_pow_save(hw, ALX_LINK_SPEED_UNKNOWN, ++ false, false, false, false); ++ ++ /* resume permanent mac address */ ++ hw->cbs.set_mac_addr(hw, hw->mac_perm_addr); ++ ++ if (adpt->netdev_registered) { ++ unregister_netdev(netdev); ++ adpt->netdev_registered = false; ++ } ++ ++ alx_free_all_rtx_queue(adpt); ++ alx_reset_interrupt_param(adpt); ++ alx_reset_interrupt_mode(adpt); ++ ++ iounmap(adpt->hw.hw_addr); ++ pci_release_selected_regions(pdev, ++ pci_select_bars(pdev, IORESOURCE_MEM)); ++ ++ netif_info(adpt, probe, adpt->netdev, "complete\n"); ++ free_netdev(netdev); ++ ++ pci_disable_pcie_error_reporting(pdev); ++ ++ pci_disable_device(pdev); ++} ++ ++ ++/* ++ * alx_pci_error_detected ++ */ ++static pci_ers_result_t alx_pci_error_detected(struct pci_dev *pdev, ++ pci_channel_state_t state) ++{ ++ struct alx_adapter *adpt = pci_get_drvdata(pdev); ++ struct net_device *netdev = adpt->netdev; ++ pci_ers_result_t retval = PCI_ERS_RESULT_NEED_RESET; ++ ++ netif_device_detach(netdev); ++ ++ if (state == pci_channel_io_perm_failure) { ++ retval = PCI_ERS_RESULT_DISCONNECT; ++ goto out; ++ } ++ ++ if (netif_running(netdev)) ++ alx_stop_internal(adpt, ALX_OPEN_CTRL_RESET_MAC); ++ pci_disable_device(pdev); ++out: ++ return retval; ++} ++ ++ ++/* ++ * alx_pci_error_slot_reset ++ */ ++static pci_ers_result_t alx_pci_error_slot_reset(struct pci_dev *pdev) ++{ ++ struct alx_adapter *adpt = pci_get_drvdata(pdev); ++ pci_ers_result_t retval = PCI_ERS_RESULT_DISCONNECT; ++ ++ if (pci_enable_device(pdev)) { ++ alx_err(adpt, "cannot re-enable PCI device after reset\n"); ++ goto out; ++ } ++ ++ pci_set_master(pdev); ++ pci_enable_wake(pdev, PCI_D3hot, 0); ++ pci_enable_wake(pdev, PCI_D3cold, 0); ++ adpt->hw.cbs.reset_mac(&adpt->hw); ++ retval = PCI_ERS_RESULT_RECOVERED; ++out: ++ pci_cleanup_aer_uncorrect_error_status(pdev); ++ return retval; ++} ++ ++ ++/* ++ * alx_pci_error_resume ++ */ ++static void alx_pci_error_resume(struct pci_dev *pdev) ++{ ++ struct alx_adapter *adpt = pci_get_drvdata(pdev); ++ struct net_device *netdev = adpt->netdev; ++ ++ if (netif_running(netdev)) { ++ if (alx_open_internal(adpt, 0)) ++ return; ++ } ++ ++ netif_device_attach(netdev); ++} ++ ++ ++static struct pci_error_handlers alx_err_handler = { ++ .error_detected = alx_pci_error_detected, ++ .slot_reset = alx_pci_error_slot_reset, ++ .resume = alx_pci_error_resume, ++}; ++ ++ ++#ifdef CONFIG_PM_SLEEP ++static SIMPLE_DEV_PM_OPS(alx_pm_ops, alx_suspend, alx_resume); ++#define ALX_PM_OPS (&alx_pm_ops) ++#else ++#define ALX_PM_OPS NULL ++#endif ++ ++ ++static struct pci_driver alx_driver = { ++ .name = alx_drv_name, ++ .id_table = alx_pci_tbl, ++ .probe = alx_init, ++ .remove = __devexit_p(alx_remove), ++ .shutdown = alx_shutdown, ++ .err_handler = &alx_err_handler, ++ .driver.pm = ALX_PM_OPS, ++}; ++ ++ ++static int __init alx_init_module(void) ++{ ++ int retval; ++ ++ printk(KERN_INFO "%s\n", alx_drv_description); ++ retval = pci_register_driver(&alx_driver); ++ ++ return retval; ++} ++module_init(alx_init_module); ++ ++ ++static void __exit alx_exit_module(void) ++{ ++ pci_unregister_driver(&alx_driver); ++} ++ ++ ++module_exit(alx_exit_module); +diff --git a/drivers/net/ethernet/atheros/alx/alx_sw.h b/drivers/net/ethernet/atheros/alx/alx_sw.h +new file mode 100644 +index 0000000..3daa392 +--- /dev/null ++++ b/drivers/net/ethernet/atheros/alx/alx_sw.h +@@ -0,0 +1,493 @@ ++/* ++ * Copyright (c) 2012 Qualcomm Atheros, Inc. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _ALX_SW_H_ ++#define _ALX_SW_H_ ++ ++#include ++#include ++ ++/* Vendor ID */ ++#define ALX_VENDOR_ID 0x1969 ++ ++/* Device IDs */ ++#define ALX_DEV_ID_AR8131 0x1063 /* l1c */ ++#define ALX_DEV_ID_AR8132 0x1062 /* l2c */ ++#define ALX_DEV_ID_AR8151_V1 0x1073 /* l1d_v1 */ ++#define ALX_DEV_ID_AR8151_V2 0x1083 /* l1d_v2 */ ++#define ALX_DEV_ID_AR8152_V1 0x2060 /* l2cb_v1 */ ++#define ALX_DEV_ID_AR8152_V2 0x2062 /* l2cb_v2 */ ++#define ALX_DEV_ID_AR8161 0x1091 /* l1f */ ++#define ALX_DEV_ID_AR8162 0x1090 /* l2f */ ++ ++#define ALX_REV_ID_AR8152_V1_0 0xc0 ++#define ALX_REV_ID_AR8152_V1_1 0xc1 ++#define ALX_REV_ID_AR8152_V2_0 0xc0 ++#define ALX_REV_ID_AR8152_V2_1 0xc1 ++#define ALX_REV_ID_AR8161_V2_0 0x10 /* B0 */ ++ ++/* Generic Registers */ ++#define ALX_DEV_STAT 0x62 /* 16 bits */ ++#define ALX_DEV_STAT_CERR 0x0001 ++#define ALX_DEV_STAT_NFERR 0x0002 ++#define ALX_DEV_STAT_FERR 0x0004 ++ ++#define ALX_ISR 0x1600 ++#define ALX_IMR 0x1604 ++#define ALX_ISR_SMB 0x00000001 ++#define ALX_ISR_TIMER 0x00000002 ++#define ALX_ISR_MANU 0x00000004 ++#define ALX_ISR_RXF_OV 0x00000008 ++#define ALX_ISR_RFD_UR 0x00000010 ++#define ALX_ISR_TX_Q1 0x00000020 ++#define ALX_ISR_TX_Q2 0x00000040 ++#define ALX_ISR_TX_Q3 0x00000080 ++#define ALX_ISR_TXF_UR 0x00000100 ++#define ALX_ISR_DMAR 0x00000200 ++#define ALX_ISR_DMAW 0x00000400 ++#define ALX_ISR_TX_CREDIT 0x00000800 ++#define ALX_ISR_PHY 0x00001000 ++#define ALX_ISR_PHY_LPW 0x00002000 ++#define ALX_ISR_TXQ_TO 0x00004000 ++#define ALX_ISR_TX_Q0 0x00008000 ++#define ALX_ISR_RX_Q0 0x00010000 ++#define ALX_ISR_RX_Q1 0x00020000 ++#define ALX_ISR_RX_Q2 0x00040000 ++#define ALX_ISR_RX_Q3 0x00080000 ++#define ALX_ISR_MAC_RX 0x00100000 ++#define ALX_ISR_MAC_TX 0x00200000 ++#define ALX_ISR_PCIE_UR 0x00400000 ++#define ALX_ISR_PCIE_FERR 0x00800000 ++#define ALX_ISR_PCIE_NFERR 0x01000000 ++#define ALX_ISR_PCIE_CERR 0x02000000 ++#define ALX_ISR_PCIE_LNKDOWN 0x04000000 ++#define ALX_ISR_RX_Q4 0x08000000 ++#define ALX_ISR_RX_Q5 0x10000000 ++#define ALX_ISR_RX_Q6 0x20000000 ++#define ALX_ISR_RX_Q7 0x40000000 ++#define ALX_ISR_DIS 0x80000000 ++ ++ ++#define ALX_IMR_NORMAL_MASK (\ ++ ALX_ISR_MANU |\ ++ ALX_ISR_OVER |\ ++ ALX_ISR_TXQ |\ ++ ALX_ISR_RXQ |\ ++ ALX_ISR_PHY_LPW |\ ++ ALX_ISR_PHY |\ ++ ALX_ISR_ERROR) ++ ++#define ALX_ISR_ALERT_MASK (\ ++ ALX_ISR_DMAR |\ ++ ALX_ISR_DMAW |\ ++ ALX_ISR_TXQ_TO |\ ++ ALX_ISR_PCIE_FERR |\ ++ ALX_ISR_PCIE_LNKDOWN |\ ++ ALX_ISR_RFD_UR |\ ++ ALX_ISR_RXF_OV) ++ ++#define ALX_ISR_TXQ (\ ++ ALX_ISR_TX_Q0 |\ ++ ALX_ISR_TX_Q1 |\ ++ ALX_ISR_TX_Q2 |\ ++ ALX_ISR_TX_Q3) ++ ++#define ALX_ISR_RXQ (\ ++ ALX_ISR_RX_Q0 |\ ++ ALX_ISR_RX_Q1 |\ ++ ALX_ISR_RX_Q2 |\ ++ ALX_ISR_RX_Q3 |\ ++ ALX_ISR_RX_Q4 |\ ++ ALX_ISR_RX_Q5 |\ ++ ALX_ISR_RX_Q6 |\ ++ ALX_ISR_RX_Q7) ++ ++#define ALX_ISR_OVER (\ ++ ALX_ISR_RFD_UR |\ ++ ALX_ISR_RXF_OV |\ ++ ALX_ISR_TXF_UR) ++ ++#define ALX_ISR_ERROR (\ ++ ALX_ISR_DMAR |\ ++ ALX_ISR_TXQ_TO |\ ++ ALX_ISR_DMAW |\ ++ ALX_ISR_PCIE_ERROR) ++ ++#define ALX_ISR_PCIE_ERROR (\ ++ ALX_ISR_PCIE_FERR |\ ++ ALX_ISR_PCIE_LNKDOWN) ++ ++/* MISC Register */ ++#define ALX_MISC 0x19C0 ++#define ALX_MISC_INTNLOSC_OPEN 0x00000008 ++ ++#define ALX_CLK_GATE 0x1814 ++ ++/* DMA address */ ++#define DMA_ADDR_HI_MASK 0xffffffff00000000ULL ++#define DMA_ADDR_LO_MASK 0x00000000ffffffffULL ++ ++#define ALX_DMA_ADDR_HI(_addr) \ ++ ((u32)(((u64)(_addr) & DMA_ADDR_HI_MASK) >> 32)) ++#define ALX_DMA_ADDR_LO(_addr) \ ++ ((u32)((u64)(_addr) & DMA_ADDR_LO_MASK)) ++ ++/* mac address length */ ++#define ALX_ETH_LENGTH_OF_ADDRESS 6 ++#define ALX_ETH_LENGTH_OF_HEADER ETH_HLEN ++ ++#define ALX_ETH_CRC(_addr, _len) ether_crc((_len), (_addr)); ++ ++/* Autonegotiation advertised speeds */ ++/* Link speed */ ++#define ALX_LINK_SPEED_UNKNOWN 0x0 ++#define ALX_LINK_SPEED_10_HALF 0x0001 ++#define ALX_LINK_SPEED_10_FULL 0x0002 ++#define ALX_LINK_SPEED_100_HALF 0x0004 ++#define ALX_LINK_SPEED_100_FULL 0x0008 ++#define ALX_LINK_SPEED_1GB_FULL 0x0020 ++#define ALX_LINK_SPEED_DEFAULT (\ ++ ALX_LINK_SPEED_10_HALF |\ ++ ALX_LINK_SPEED_10_FULL |\ ++ ALX_LINK_SPEED_100_HALF |\ ++ ALX_LINK_SPEED_100_FULL |\ ++ ALX_LINK_SPEED_1GB_FULL) ++ ++#define ALX_MAX_SETUP_LNK_CYCLE 100 ++ ++/* Device Type definitions for new protocol MDIO commands */ ++#define ALX_MDIO_DEV_TYPE_NORM 0 ++ ++/* Wake On Lan */ ++#define ALX_WOL_PHY 0x00000001 /* PHY Status Change */ ++#define ALX_WOL_MAGIC 0x00000002 /* Magic Packet */ ++ ++#define ALX_MAX_EEPROM_LEN 0x200 ++#define ALX_MAX_HWREG_LEN 0x200 ++ ++/* RSS Settings */ ++enum alx_rss_mode { ++ alx_rss_mode_disable = 0, ++ alx_rss_sig_que = 1, ++ alx_rss_mul_que_sig_int = 2, ++ alx_rss_mul_que_mul_int = 4, ++}; ++ ++/* Flow Control Settings */ ++enum alx_fc_mode { ++ alx_fc_none = 0, ++ alx_fc_rx_pause, ++ alx_fc_tx_pause, ++ alx_fc_full, ++ alx_fc_default ++}; ++ ++/* WRR Restrict Settings */ ++enum alx_wrr_mode { ++ alx_wrr_mode_none = 0, ++ alx_wrr_mode_high, ++ alx_wrr_mode_high2, ++ alx_wrr_mode_all ++}; ++ ++enum alx_mac_type { ++ alx_mac_unknown = 0, ++ alx_mac_l1c, ++ alx_mac_l2c, ++ alx_mac_l1d_v1, ++ alx_mac_l1d_v2, ++ alx_mac_l2cb_v1, ++ alx_mac_l2cb_v20, ++ alx_mac_l2cb_v21, ++ alx_mac_l1f, ++ alx_mac_l2f, ++}; ++ ++ ++/* Statistics counters collected by the MAC */ ++struct alx_hw_stats { ++ /* rx */ ++ unsigned long rx_ok; ++ unsigned long rx_bcast; ++ unsigned long rx_mcast; ++ unsigned long rx_pause; ++ unsigned long rx_ctrl; ++ unsigned long rx_fcs_err; ++ unsigned long rx_len_err; ++ unsigned long rx_byte_cnt; ++ unsigned long rx_runt; ++ unsigned long rx_frag; ++ unsigned long rx_sz_64B; ++ unsigned long rx_sz_127B; ++ unsigned long rx_sz_255B; ++ unsigned long rx_sz_511B; ++ unsigned long rx_sz_1023B; ++ unsigned long rx_sz_1518B; ++ unsigned long rx_sz_max; ++ unsigned long rx_ov_sz; ++ unsigned long rx_ov_rxf; ++ unsigned long rx_ov_rrd; ++ unsigned long rx_align_err; ++ unsigned long rx_bc_byte_cnt; ++ unsigned long rx_mc_byte_cnt; ++ unsigned long rx_err_addr; ++ ++ /* tx */ ++ unsigned long tx_ok; ++ unsigned long tx_bcast; ++ unsigned long tx_mcast; ++ unsigned long tx_pause; ++ unsigned long tx_exc_defer; ++ unsigned long tx_ctrl; ++ unsigned long tx_defer; ++ unsigned long tx_byte_cnt; ++ unsigned long tx_sz_64B; ++ unsigned long tx_sz_127B; ++ unsigned long tx_sz_255B; ++ unsigned long tx_sz_511B; ++ unsigned long tx_sz_1023B; ++ unsigned long tx_sz_1518B; ++ unsigned long tx_sz_max; ++ unsigned long tx_single_col; ++ unsigned long tx_multi_col; ++ unsigned long tx_late_col; ++ unsigned long tx_abort_col; ++ unsigned long tx_underrun; ++ unsigned long tx_trd_eop; ++ unsigned long tx_len_err; ++ unsigned long tx_trunc; ++ unsigned long tx_bc_byte_cnt; ++ unsigned long tx_mc_byte_cnt; ++ unsigned long update; ++}; ++ ++/* HW callback function pointer table */ ++struct alx_hw; ++struct alx_hw_callbacks { ++ /* NIC */ ++ int (*identify_nic)(struct alx_hw *); ++ /* PHY */ ++ int (*init_phy)(struct alx_hw *); ++ int (*reset_phy)(struct alx_hw *); ++ int (*read_phy_reg)(struct alx_hw *, u16, u16 *); ++ int (*write_phy_reg)(struct alx_hw *, u16, u16); ++ /* Link */ ++ int (*setup_phy_link)(struct alx_hw *, u32, bool, bool); ++ int (*setup_phy_link_speed)(struct alx_hw *, u32, bool, bool); ++ int (*check_phy_link)(struct alx_hw *, u32 *, bool *); ++ ++ /* MAC */ ++ int (*reset_mac)(struct alx_hw *); ++ int (*start_mac)(struct alx_hw *); ++ int (*stop_mac)(struct alx_hw *); ++ int (*config_mac)(struct alx_hw *, u16, u16, u16, u16, u16); ++ int (*get_mac_addr)(struct alx_hw *, u8 *); ++ int (*set_mac_addr)(struct alx_hw *, u8 *); ++ int (*set_mc_addr)(struct alx_hw *, u8 *); ++ int (*clear_mc_addr)(struct alx_hw *); ++ ++ /* intr */ ++ int (*ack_phy_intr)(struct alx_hw *); ++ int (*enable_legacy_intr)(struct alx_hw *); ++ int (*disable_legacy_intr)(struct alx_hw *); ++ int (*enable_msix_intr)(struct alx_hw *, u8); ++ int (*disable_msix_intr)(struct alx_hw *, u8); ++ ++ /* Configure */ ++ int (*config_rx)(struct alx_hw *); ++ int (*config_tx)(struct alx_hw *); ++ int (*config_fc)(struct alx_hw *); ++ int (*config_rss)(struct alx_hw *, bool); ++ int (*config_msix)(struct alx_hw *, u16, bool, bool); ++ int (*config_wol)(struct alx_hw *, u32); ++ int (*config_aspm)(struct alx_hw *, bool, bool); ++ int (*config_mac_ctrl)(struct alx_hw *); ++ int (*config_pow_save)(struct alx_hw *, u32, ++ bool, bool, bool, bool); ++ int (*reset_pcie)(struct alx_hw *, bool, bool); ++ ++ /* NVRam function */ ++ int (*check_nvram)(struct alx_hw *, bool *); ++ int (*read_nvram)(struct alx_hw *, u16, u32 *); ++ int (*write_nvram)(struct alx_hw *, u16, u32); ++ ++ /* Others */ ++ int (*get_ethtool_regs)(struct alx_hw *, void *); ++}; ++ ++struct alx_hw { ++ struct alx_adapter *adpt; ++ struct alx_hw_callbacks cbs; ++ u8 __iomem *hw_addr; /* inner register address */ ++ u16 pci_venid; ++ u16 pci_devid; ++ u16 pci_sub_devid; ++ u16 pci_sub_venid; ++ u8 pci_revid; ++ ++ bool long_cable; ++ bool aps_en; ++ bool hi_txperf; ++ bool msi_lnkpatch; ++ u32 dma_chnl; ++ u32 hwreg_sz; ++ u32 eeprom_sz; ++ ++ /* PHY parameter */ ++ u32 phy_id; ++ u32 autoneg_advertised; ++ u32 link_speed; ++ bool link_up; ++ spinlock_t mdio_lock; ++ ++ /* MAC parameter */ ++ enum alx_mac_type mac_type; ++ u8 mac_addr[ALX_ETH_LENGTH_OF_ADDRESS]; ++ u8 mac_perm_addr[ALX_ETH_LENGTH_OF_ADDRESS]; ++ ++ u32 mtu; ++ u16 rxstat_reg; ++ u16 rxstat_sz; ++ u16 txstat_reg; ++ u16 txstat_sz; ++ ++ u16 tx_prod_reg[4]; ++ u16 tx_cons_reg[4]; ++ u16 rx_prod_reg[2]; ++ u16 rx_cons_reg[2]; ++ u64 tpdma[4]; ++ u64 rfdma[2]; ++ u64 rrdma[2]; ++ ++ /* WRR parameter */ ++ enum alx_wrr_mode wrr_mode; ++ u32 wrr_prio0; ++ u32 wrr_prio1; ++ u32 wrr_prio2; ++ u32 wrr_prio3; ++ ++ /* RSS parameter */ ++ enum alx_rss_mode rss_mode; ++ u8 rss_hstype; ++ u8 rss_base_cpu; ++ u16 rss_idt_size; ++ u32 rss_idt[32]; ++ u8 rss_key[40]; ++ ++ /* flow control parameter */ ++ enum alx_fc_mode cur_fc_mode; /* FC mode in effect */ ++ enum alx_fc_mode req_fc_mode; /* FC mode requested by caller */ ++ bool disable_fc_autoneg; /* Do not autonegotiate FC */ ++ bool fc_was_autonegged; /* the result of autonegging */ ++ bool fc_single_pause; ++ ++ /* Others */ ++ u32 preamble; ++ u32 intr_mask; ++ u16 smb_timer; ++ u16 imt; /* Interrupt Moderator timer (2us) */ ++ u32 flags; ++}; ++ ++#define ALX_HW_FLAG_L0S_CAP 0x00000001 ++#define ALX_HW_FLAG_L0S_EN 0x00000002 ++#define ALX_HW_FLAG_L1_CAP 0x00000004 ++#define ALX_HW_FLAG_L1_EN 0x00000008 ++#define ALX_HW_FLAG_PWSAVE_CAP 0x00000010 ++#define ALX_HW_FLAG_PWSAVE_EN 0x00000020 ++#define ALX_HW_FLAG_AZ_CAP 0x00000040 ++#define ALX_HW_FLAG_AZ_EN 0x00000080 ++#define ALX_HW_FLAG_PTP_CAP 0x00000100 ++#define ALX_HW_FLAG_PTP_EN 0x00000200 ++#define ALX_HW_FLAG_GIGA_CAP 0x00000400 ++ ++#define ALX_HW_FLAG_PROMISC_EN 0x00010000 /* for mac ctrl reg */ ++#define ALX_HW_FLAG_VLANSTRIP_EN 0x00020000 /* for mac ctrl reg */ ++#define ALX_HW_FLAG_MULTIALL_EN 0x00040000 /* for mac ctrl reg */ ++#define ALX_HW_FLAG_LOOPBACK_EN 0x00080000 /* for mac ctrl reg */ ++ ++#define CHK_HW_FLAG(_flag) CHK_FLAG(hw, HW, _flag) ++#define SET_HW_FLAG(_flag) SET_FLAG(hw, HW, _flag) ++#define CLI_HW_FLAG(_flag) CLI_FLAG(hw, HW, _flag) ++ ++ ++/* RSS hstype Definitions */ ++#define ALX_RSS_HSTYP_IPV4_EN 0x00000001 ++#define ALX_RSS_HSTYP_TCP4_EN 0x00000002 ++#define ALX_RSS_HSTYP_IPV6_EN 0x00000004 ++#define ALX_RSS_HSTYP_TCP6_EN 0x00000008 ++#define ALX_RSS_HSTYP_ALL_EN (\ ++ ALX_RSS_HSTYP_IPV4_EN |\ ++ ALX_RSS_HSTYP_TCP4_EN |\ ++ ALX_RSS_HSTYP_IPV6_EN |\ ++ ALX_RSS_HSTYP_TCP6_EN) ++ ++ ++/* definitions for flags */ ++ ++#define CHK_FLAG_ARRAY(_st, _idx, _type, _flag) \ ++ ((_st)->flags[_idx] & (ALX_##_type##_FLAG_##_idx##_##_flag)) ++#define CHK_FLAG(_st, _type, _flag) \ ++ ((_st)->flags & (ALX_##_type##_FLAG_##_flag)) ++ ++#define SET_FLAG_ARRAY(_st, _idx, _type, _flag) \ ++ ((_st)->flags[_idx] |= (ALX_##_type##_FLAG_##_idx##_##_flag)) ++#define SET_FLAG(_st, _type, _flag) \ ++ ((_st)->flags |= (ALX_##_type##_FLAG_##_flag)) ++ ++#define CLI_FLAG_ARRAY(_st, _idx, _type, _flag) \ ++ ((_st)->flags[_idx] &= ~(ALX_##_type##_FLAG_##_idx##_##_flag)) ++#define CLI_FLAG(_st, _type, _flag) \ ++ ((_st)->flags &= ~(ALX_##_type##_FLAG_##_flag)) ++ ++int alx_cfg_r16(const struct alx_hw *hw, int reg, u16 *pval); ++int alx_cfg_w16(const struct alx_hw *hw, int reg, u16 val); ++ ++ ++void alx_mem_flush(const struct alx_hw *hw); ++void alx_mem_r32(const struct alx_hw *hw, int reg, u32 *val); ++void alx_mem_w32(const struct alx_hw *hw, int reg, u32 val); ++void alx_mem_w8(const struct alx_hw *hw, int reg, u8 val); ++ ++ ++/* special definitions for hw */ ++#define ALF_MAX_MSIX_NOQUE_INTRS 4 ++#define ALF_MIN_MSIX_NOQUE_INTRS 4 ++#define ALF_MAX_MSIX_QUEUE_INTRS 12 ++#define ALF_MIN_MSIX_QUEUE_INTRS 12 ++#define ALF_MAX_MSIX_INTRS \ ++ (ALF_MAX_MSIX_QUEUE_INTRS + ALF_MAX_MSIX_NOQUE_INTRS) ++#define ALF_MIN_MSIX_INTRS \ ++ (ALF_MIN_MSIX_NOQUE_INTRS + ALF_MIN_MSIX_QUEUE_INTRS) ++ ++ ++/* function */ ++extern int alc_init_hw_callbacks(struct alx_hw *hw); ++extern int alf_init_hw_callbacks(struct alx_hw *hw); ++ ++/* Logging message functions */ ++void __printf(3, 4) alx_hw_printk(const char *level, const struct alx_hw *hw, ++ const char *fmt, ...); ++ ++#define alx_hw_err(_hw, _format, ...) \ ++ alx_hw_printk(KERN_ERR, _hw, _format, ##__VA_ARGS__) ++#define alx_hw_warn(_hw, _format, ...) \ ++ alx_hw_printk(KERN_WARNING, _hw, _format, ##__VA_ARGS__) ++#define alx_hw_info(_hw, _format, ...) \ ++ alx_hw_printk(KERN_INFO, _hw, _format, ##__VA_ARGS__) ++ ++#endif /* _ALX_SW_H_ */ ++ +diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c +index 721adfd..49b31d1 100644 +--- a/drivers/net/ethernet/broadcom/bnx2.c ++++ b/drivers/net/ethernet/broadcom/bnx2.c +@@ -2823,6 +2823,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) + struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; + u16 hw_cons, sw_cons, sw_ring_cons; + int tx_pkt = 0, index; ++ unsigned int tx_bytes = 0; + struct netdev_queue *txq; + + index = (bnapi - bp->bnx2_napi); +@@ -2877,6 +2878,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) + + sw_cons = NEXT_TX_BD(sw_cons); + ++ tx_bytes += skb->len; + dev_kfree_skb(skb); + tx_pkt++; + if (tx_pkt == budget) +@@ -2886,6 +2888,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) + hw_cons = bnx2_get_hw_tx_cons(bnapi); + } + ++ netdev_tx_completed_queue(txq, tx_pkt, tx_bytes); + txr->hw_tx_cons = hw_cons; + txr->tx_cons = sw_cons; + +@@ -3678,16 +3681,13 @@ static int bnx2_request_uncached_firmware(struct bnx2 *bp) + } + + rc = request_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev); +- if (rc) { +- pr_err("Can't load firmware file \"%s\"\n", mips_fw_file); ++ if (rc) + goto out; +- } + + rc = request_firmware(&bp->rv2p_firmware, rv2p_fw_file, &bp->pdev->dev); +- if (rc) { +- pr_err("Can't load firmware file \"%s\"\n", rv2p_fw_file); ++ if (rc) + goto err_release_mips_firmware; +- } ++ + mips_fw = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data; + rv2p_fw = (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data; + if (bp->mips_firmware->size < sizeof(*mips_fw) || +@@ -5400,6 +5400,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp) + } + dev_kfree_skb(skb); + } ++ netdev_tx_reset_queue(netdev_get_tx_queue(bp->dev, i)); + } + } + +@@ -6552,6 +6553,8 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) + } + txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END; + ++ netdev_tx_sent_queue(txq, skb->len); ++ + prod = NEXT_TX_BD(prod); + txr->tx_prod_bseq += skb->len; + +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +index e367ab1..d1e7ee8 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +@@ -100,7 +100,8 @@ int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */ + * return idx of last bd freed + */ + static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, +- u16 idx) ++ u16 idx, unsigned int *pkts_compl, ++ unsigned int *bytes_compl) + { + struct sw_tx_bd *tx_buf = &txdata->tx_buf_ring[idx]; + struct eth_tx_start_bd *tx_start_bd; +@@ -162,6 +163,10 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, + + /* release skb */ + WARN_ON(!skb); ++ if (skb) { ++ (*pkts_compl)++; ++ (*bytes_compl) += skb->len; ++ } + dev_kfree_skb_any(skb); + tx_buf->first_bd = 0; + tx_buf->skb = NULL; +@@ -173,6 +178,7 @@ int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata) + { + struct netdev_queue *txq; + u16 hw_cons, sw_cons, bd_cons = txdata->tx_bd_cons; ++ unsigned int pkts_compl = 0, bytes_compl = 0; + + #ifdef BNX2X_STOP_ON_ERROR + if (unlikely(bp->panic)) +@@ -192,10 +198,14 @@ int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata) + " pkt_cons %u\n", + txdata->txq_index, hw_cons, sw_cons, pkt_cons); + +- bd_cons = bnx2x_free_tx_pkt(bp, txdata, pkt_cons); ++ bd_cons = bnx2x_free_tx_pkt(bp, txdata, pkt_cons, ++ &pkts_compl, &bytes_compl); ++ + sw_cons++; + } + ++ netdev_tx_completed_queue(txq, pkts_compl, bytes_compl); ++ + txdata->tx_pkt_cons = sw_cons; + txdata->tx_bd_cons = bd_cons; + +@@ -1117,16 +1127,18 @@ static void bnx2x_free_tx_skbs(struct bnx2x *bp) + struct bnx2x_fastpath *fp = &bp->fp[i]; + for_each_cos_in_tx_queue(fp, cos) { + struct bnx2x_fp_txdata *txdata = &fp->txdata[cos]; ++ unsigned pkts_compl = 0, bytes_compl = 0; + +- u16 bd_cons = txdata->tx_bd_cons; + u16 sw_prod = txdata->tx_pkt_prod; + u16 sw_cons = txdata->tx_pkt_cons; + + while (sw_cons != sw_prod) { +- bd_cons = bnx2x_free_tx_pkt(bp, txdata, +- TX_BD(sw_cons)); ++ bnx2x_free_tx_pkt(bp, txdata, TX_BD(sw_cons), ++ &pkts_compl, &bytes_compl); + sw_cons++; + } ++ netdev_tx_reset_queue( ++ netdev_get_tx_queue(bp->dev, txdata->txq_index)); + } + } + } +@@ -2821,6 +2833,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + mapping = skb_frag_dma_map(&bp->pdev->dev, frag, 0, + skb_frag_size(frag), DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) { ++ unsigned int pkts_compl = 0, bytes_compl = 0; + + DP(NETIF_MSG_TX_QUEUED, "Unable to map page - " + "dropping packet...\n"); +@@ -2832,7 +2845,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + */ + first_bd->nbd = cpu_to_le16(nbd); + bnx2x_free_tx_pkt(bp, txdata, +- TX_BD(txdata->tx_pkt_prod)); ++ TX_BD(txdata->tx_pkt_prod), ++ &pkts_compl, &bytes_compl); + return NETDEV_TX_OK; + } + +@@ -2893,6 +2907,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + pbd_e2->parsing_data); + DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod); + ++ netdev_tx_sent_queue(txq, skb->len); ++ + txdata->tx_pkt_prod++; + /* + * Make sure that the BD data is updated before updating the producer +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +index f0ca8b2..8be81e3 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +@@ -1740,6 +1740,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) + struct sw_rx_bd *rx_buf; + u16 len; + int rc = -ENODEV; ++ struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txdata->txq_index); + + /* check the loopback mode */ + switch (loopback_mode) { +@@ -1784,6 +1785,8 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) + tx_start_idx = le16_to_cpu(*txdata->tx_cons_sb); + rx_start_idx = le16_to_cpu(*fp_rx->rx_cons_sb); + ++ netdev_tx_sent_queue(txq, skb->len); ++ + pkt_prod = txdata->tx_pkt_prod++; + tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)]; + tx_buf->first_bd = txdata->tx_bd_prod; +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +index 1042935..f2119ea 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +@@ -10573,11 +10573,8 @@ int bnx2x_init_firmware(struct bnx2x *bp) + + rc = request_firmware(&bp->firmware, fw_file_name, + &bp->pdev->dev); +- if (rc) { +- BNX2X_ERR("Can't load firmware file %s\n", +- fw_file_name); ++ if (rc) + goto request_firmware_exit; +- } + + rc = bnx2x_check_firmware(bp); + if (rc) { +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index d0ebf9c..32d4e7f 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -5362,6 +5362,7 @@ static void tg3_tx(struct tg3_napi *tnapi) + u32 sw_idx = tnapi->tx_cons; + struct netdev_queue *txq; + int index = tnapi - tp->napi; ++ unsigned int pkts_compl = 0, bytes_compl = 0; + + if (tg3_flag(tp, ENABLE_TSS)) + index--; +@@ -5420,6 +5421,8 @@ static void tg3_tx(struct tg3_napi *tnapi) + } + } + ++ netdev_tx_completed_queue(txq, pkts_compl, bytes_compl); ++ + tnapi->tx_cons = sw_idx; + + /* Need to make the tx_cons update visible to tg3_start_xmit() +@@ -6863,6 +6866,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) + } + + skb_tx_timestamp(skb); ++ netdev_tx_sent_queue(txq, skb->len); + + /* Packets are ready, update Tx producer idx local and on card. */ + tw32_tx_mbox(tnapi->prodmbox, entry); +@@ -7343,6 +7347,7 @@ static void tg3_free_rings(struct tg3 *tp) + + dev_kfree_skb_any(skb); + } ++ netdev_tx_reset_queue(netdev_get_tx_queue(tp->dev, j)); + } + } + +@@ -9595,11 +9600,8 @@ static int tg3_request_firmware(struct tg3 *tp) + { + const __be32 *fw_data; + +- if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) { +- netdev_err(tp->dev, "Failed to load firmware \"%s\"\n", +- tp->fw_needed); ++ if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) + return -ENOENT; +- } + + fw_data = (void *)tp->fw->data; + +diff --git a/drivers/net/ethernet/brocade/bna/cna_fwimg.c b/drivers/net/ethernet/brocade/bna/cna_fwimg.c +index 725b9ff..0c072b3 100644 +--- a/drivers/net/ethernet/brocade/bna/cna_fwimg.c ++++ b/drivers/net/ethernet/brocade/bna/cna_fwimg.c +@@ -29,10 +29,8 @@ cna_read_firmware(struct pci_dev *pdev, u32 **bfi_image, + { + const struct firmware *fw; + +- if (request_firmware(&fw, fw_name, &pdev->dev)) { +- pr_alert("Can't locate firmware %s\n", fw_name); ++ if (request_firmware(&fw, fw_name, &pdev->dev)) + goto error; +- } + + *bfi_image = (u32 *)fw->data; + *bfi_image_size = fw->size/sizeof(u32); +diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +index 4d15c8f..2ff3003 100644 +--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c ++++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +@@ -1030,12 +1030,8 @@ int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size) + snprintf(buf, sizeof(buf), get_edc_fw_name(edc_idx)); + + ret = request_firmware(&fw, buf, &adapter->pdev->dev); +- if (ret < 0) { +- dev_err(&adapter->pdev->dev, +- "could not upgrade firmware: unable to load %s\n", +- buf); ++ if (ret) + return ret; +- } + + /* check size, take checksum in account */ + if (fw->size > size + 4) { +@@ -1072,11 +1068,8 @@ static int upgrade_fw(struct adapter *adap) + struct device *dev = &adap->pdev->dev; + + ret = request_firmware(&fw, FW_FNAME, dev); +- if (ret < 0) { +- dev_err(dev, "could not upgrade firmware: unable to load %s\n", +- FW_FNAME); ++ if (ret) + return ret; +- } + ret = t3_load_fw(adap, fw->data, fw->size); + release_firmware(fw); + +@@ -1121,11 +1114,8 @@ static int update_tpsram(struct adapter *adap) + snprintf(buf, sizeof(buf), TPSRAM_NAME, rev); + + ret = request_firmware(&tpsram, buf, dev); +- if (ret < 0) { +- dev_err(dev, "could not load TP SRAM: unable to load %s\n", +- buf); ++ if (ret) + return ret; +- } + + ret = t3_check_tpsram(adap, tpsram->data, tpsram->size); + if (ret) +diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +index 4c8f42a..f65fd52 100644 +--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c ++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +@@ -830,11 +830,8 @@ static int upgrade_fw(struct adapter *adap) + struct device *dev = adap->pdev_dev; + + ret = request_firmware(&fw, FW_FNAME, dev); +- if (ret < 0) { +- dev_err(dev, "unable to load firmware image " FW_FNAME +- ", error %d\n", ret); ++ if (ret) + return ret; +- } + + hdr = (const struct fw_hdr *)fw->data; + vers = ntohl(hdr->fw_ver); +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 644e8fe..c648a40 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -33,13 +33,14 @@ + + #include "be_hw.h" + +-#define DRV_VER "4.0.100u" ++#define DRV_VER "4.2.220u" + #define DRV_NAME "be2net" + #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" + #define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" + #define OC_NAME "Emulex OneConnect 10Gbps NIC" + #define OC_NAME_BE OC_NAME "(be3)" + #define OC_NAME_LANCER OC_NAME "(Lancer)" ++#define OC_NAME_SH OC_NAME "(Skyhawk)" + #define DRV_DESC "ServerEngines BladeEngine 10Gbps NIC Driver" + + #define BE_VENDOR_ID 0x19a2 +@@ -50,6 +51,11 @@ + #define OC_DEVICE_ID2 0x710 /* Device Id for BE3 cards */ + #define OC_DEVICE_ID3 0xe220 /* Device id for Lancer cards */ + #define OC_DEVICE_ID4 0xe228 /* Device id for VF in Lancer */ ++#define OC_DEVICE_ID5 0x720 /* Device Id for Skyhawk cards */ ++#define OC_SUBSYS_DEVICE_ID1 0xE602 ++#define OC_SUBSYS_DEVICE_ID2 0xE642 ++#define OC_SUBSYS_DEVICE_ID3 0xE612 ++#define OC_SUBSYS_DEVICE_ID4 0xE652 + + static inline char *nic_name(struct pci_dev *pdev) + { +@@ -63,6 +69,8 @@ static inline char *nic_name(struct pci_dev *pdev) + return OC_NAME_LANCER; + case BE_DEVICE_ID2: + return BE3_NAME; ++ case OC_DEVICE_ID5: ++ return OC_NAME_SH; + default: + return BE_NAME; + } +@@ -70,11 +78,14 @@ static inline char *nic_name(struct pci_dev *pdev) + + /* Number of bytes of an RX frame that are copied to skb->data */ + #define BE_HDR_LEN ((u16) 64) ++/* allocate extra space to allow tunneling decapsulation without head reallocation */ ++#define BE_RX_SKB_ALLOC_SIZE (BE_HDR_LEN + 64) ++ + #define BE_MAX_JUMBO_FRAME_SIZE 9018 + #define BE_MIN_MTU 256 + + #define BE_NUM_VLANS_SUPPORTED 64 +-#define BE_MAX_EQD 96 ++#define BE_MAX_EQD 96u + #define BE_MAX_TX_FRAG_COUNT 30 + + #define EVNT_Q_LEN 1024 +@@ -85,12 +96,16 @@ static inline char *nic_name(struct pci_dev *pdev) + #define MCC_Q_LEN 128 /* total size not to exceed 8 pages */ + #define MCC_CQ_LEN 256 + +-#define MAX_RSS_QS 4 /* BE limit is 4 queues/port */ ++#define BE3_MAX_RSS_QS 8 ++#define BE2_MAX_RSS_QS 4 ++#define MAX_RSS_QS BE3_MAX_RSS_QS + #define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */ ++ + #define MAX_TX_QS 8 +-#define BE_MAX_MSIX_VECTORS (MAX_RX_QS + 1)/* RX + TX */ ++#define MAX_MSIX_VECTORS MAX_RSS_QS ++#define BE_TX_BUDGET 256 + #define BE_NAPI_WEIGHT 64 +-#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ ++#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ + #define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) + + #define FW_VER_LEN 32 +@@ -147,6 +162,11 @@ static inline void queue_head_inc(struct be_queue_info *q) + index_inc(&q->head, q->len); + } + ++static inline void index_dec(u16 *index, u16 limit) ++{ ++ *index = MODULO((*index - 1), limit); ++} ++ + static inline void queue_tail_inc(struct be_queue_info *q) + { + index_inc(&q->tail, q->len); +@@ -158,13 +178,16 @@ struct be_eq_obj { + + /* Adaptive interrupt coalescing (AIC) info */ + bool enable_aic; +- u16 min_eqd; /* in usecs */ +- u16 max_eqd; /* in usecs */ +- u16 cur_eqd; /* in usecs */ +- u8 eq_idx; ++ u32 min_eqd; /* in usecs */ ++ u32 max_eqd; /* in usecs */ ++ u32 eqd; /* configured val when aic is off */ ++ u32 cur_eqd; /* in usecs */ + ++ u8 idx; /* array index */ ++ u16 tx_budget; + struct napi_struct napi; +-}; ++ struct be_adapter *adapter; ++} ____cacheline_aligned_in_smp; + + struct be_mcc_obj { + struct be_queue_info q; +@@ -190,7 +213,7 @@ struct be_tx_obj { + /* Remember the skbs that were transmitted */ + struct sk_buff *sent_skb_list[TX_Q_LEN]; + struct be_tx_stats stats; +-}; ++} ____cacheline_aligned_in_smp; + + /* Struct to remember the pages posted for rx frags */ + struct be_rx_page_info { +@@ -208,8 +231,6 @@ struct be_rx_stats { + u32 rx_drops_no_skbs; /* skb allocation errors */ + u32 rx_drops_no_frags; /* HW has no fetched frags */ + u32 rx_post_fail; /* page post alloc failures */ +- u32 rx_polls; /* NAPI calls */ +- u32 rx_events; + u32 rx_compl; + u32 rx_mcast_pkts; + u32 rx_compl_err; /* completions with err set */ +@@ -242,23 +263,19 @@ struct be_rx_obj { + struct be_queue_info cq; + struct be_rx_compl_info rxcp; + struct be_rx_page_info page_info_tbl[RX_Q_LEN]; +- struct be_eq_obj rx_eq; + struct be_rx_stats stats; + u8 rss_id; + bool rx_post_starved; /* Zero rx frags have been posted to BE */ +- u32 cache_line_barrier[16]; +-}; ++} ____cacheline_aligned_in_smp; + + struct be_drv_stats { + u32 be_on_die_temperature; +- u32 tx_events; + u32 eth_red_drops; + u32 rx_drops_no_pbuf; + u32 rx_drops_no_txpb; + u32 rx_drops_no_erx_descr; + u32 rx_drops_no_tpre_descr; + u32 rx_drops_too_many_frags; +- u32 rx_drops_invalid_ring; + u32 forwarded_packets; + u32 rx_drops_mtu; + u32 rx_crc_errors; +@@ -269,7 +286,7 @@ struct be_drv_stats { + u32 rx_in_range_errors; + u32 rx_out_range_errors; + u32 rx_frame_too_long; +- u32 rx_address_match_errors; ++ u32 rx_address_mismatch_drops; + u32 rx_dropped_too_small; + u32 rx_dropped_too_short; + u32 rx_dropped_header_too_small; +@@ -288,14 +305,40 @@ struct be_drv_stats { + }; + + struct be_vf_cfg { +- unsigned char vf_mac_addr[ETH_ALEN]; +- u32 vf_if_handle; +- u32 vf_pmac_id; +- u16 vf_vlan_tag; +- u32 vf_tx_rate; ++ unsigned char mac_addr[ETH_ALEN]; ++ int if_handle; ++ int pmac_id; ++ u16 def_vid; ++ u16 vlan_tag; ++ u32 tx_rate; ++}; ++ ++enum vf_state { ++ ENABLED = 0, ++ ASSIGNED = 1 + }; + +-#define BE_INVALID_PMAC_ID 0xffffffff ++#define BE_FLAGS_LINK_STATUS_INIT 1 ++#define BE_FLAGS_WORKER_SCHEDULED (1 << 3) ++#define BE_UC_PMAC_COUNT 30 ++#define BE_VF_UC_PMAC_COUNT 2 ++ ++struct phy_info { ++ u8 transceiver; ++ u8 autoneg; ++ u8 fc_autoneg; ++ u8 port_type; ++ u16 phy_type; ++ u16 interface_type; ++ u32 misc_params; ++ u16 auto_speeds_supported; ++ u16 fixed_speeds_supported; ++ int link_speed; ++ int forced_port_speed; ++ u32 dac_cable_len; ++ u32 advertising; ++ u32 supported; ++}; + + struct be_adapter { + struct pci_dev *pdev; +@@ -314,20 +357,19 @@ struct be_adapter { + spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ + spinlock_t mcc_cq_lock; + +- struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS]; + u32 num_msix_vec; ++ u32 num_evt_qs; ++ struct be_eq_obj eq_obj[MAX_MSIX_VECTORS]; ++ struct msix_entry msix_entries[MAX_MSIX_VECTORS]; + bool isr_registered; + + /* TX Rings */ +- struct be_eq_obj tx_eq; ++ u32 num_tx_qs; + struct be_tx_obj tx_obj[MAX_TX_QS]; +- u8 num_tx_qs; +- +- u32 cache_line_break[8]; + + /* Rx rings */ +- struct be_rx_obj rx_obj[MAX_RX_QS]; + u32 num_rx_qs; ++ struct be_rx_obj rx_obj[MAX_RX_QS]; + u32 big_page_size; /* Compounded page size shared by rx wrbs */ + + u8 eq_next_idx; +@@ -345,40 +387,49 @@ struct be_adapter { + struct delayed_work work; + u16 work_counter; + ++ u32 flags; + /* Ethtool knobs and info */ + char fw_ver[FW_VER_LEN]; +- u32 if_handle; /* Used to configure filtering */ +- u32 pmac_id; /* MAC addr handle used by BE card */ ++ int if_handle; /* Used to configure filtering */ ++ u32 *pmac_id; /* MAC addr handle used by BE card */ + u32 beacon_state; /* for set_phys_id */ + + bool eeh_err; ++ bool ue_detected; ++ bool fw_timeout; + u32 port_num; + bool promiscuous; +- bool wol; + u32 function_mode; + u32 function_caps; + u32 rx_fc; /* Rx flow control */ + u32 tx_fc; /* Tx flow control */ +- bool ue_detected; + bool stats_cmd_sent; +- int link_speed; +- u8 port_type; +- u8 transceiver; +- u8 autoneg; + u8 generation; /* BladeEngine ASIC generation */ + u32 flash_status; + struct completion flash_compl; + +- bool be3_native; +- bool sriov_enabled; ++ u32 num_vfs; /* Number of VFs provisioned by PF driver */ ++ u32 dev_num_vfs; /* Number of VFs supported by HW */ ++ u8 virtfn; + struct be_vf_cfg *vf_cfg; +- u8 is_virtfn; ++ bool be3_native; + u32 sli_family; + u8 hba_port_num; + u16 pvid; ++ struct phy_info phy; ++ u8 wol_cap; ++ bool wol; ++ u32 max_pmac_cnt; /* Max secondary UC MACs programmable */ ++ u32 uc_macs; /* Count of secondary UC MAC programmed */ + }; + +-#define be_physfn(adapter) (!adapter->is_virtfn) ++#define be_physfn(adapter) (!adapter->virtfn) ++#define sriov_enabled(adapter) (adapter->num_vfs > 0) ++#define sriov_want(adapter) (adapter->dev_num_vfs && num_vfs && \ ++ be_physfn(adapter)) ++#define for_all_vfs(adapter, vf_cfg, i) \ ++ for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \ ++ i++, vf_cfg++) + + /* BladeEngine Generation numbers */ + #define BE_GEN2 2 +@@ -389,27 +440,41 @@ struct be_adapter { + #define lancer_chip(adapter) ((adapter->pdev->device == OC_DEVICE_ID3) || \ + (adapter->pdev->device == OC_DEVICE_ID4)) + ++#define skyhawk_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID5) ++ ++ ++ + extern const struct ethtool_ops be_ethtool_ops; + + #define msix_enabled(adapter) (adapter->num_msix_vec > 0) +-#define tx_stats(txo) (&txo->stats) +-#define rx_stats(rxo) (&rxo->stats) ++#define num_irqs(adapter) (msix_enabled(adapter) ? \ ++ adapter->num_msix_vec : 1) ++#define tx_stats(txo) (&(txo)->stats) ++#define rx_stats(rxo) (&(rxo)->stats) + +-#define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) ++/* The default RXQ is the last RXQ */ ++#define default_rxo(adpt) (&adpt->rx_obj[adpt->num_rx_qs - 1]) + + #define for_all_rx_queues(adapter, rxo, i) \ + for (i = 0, rxo = &adapter->rx_obj[i]; i < adapter->num_rx_qs; \ + i++, rxo++) + +-/* Just skip the first default non-rss queue */ ++/* Skip the default non-rss queue (last one)*/ + #define for_all_rss_queues(adapter, rxo, i) \ +- for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\ ++ for (i = 0, rxo = &adapter->rx_obj[i]; i < (adapter->num_rx_qs - 1);\ + i++, rxo++) + + #define for_all_tx_queues(adapter, txo, i) \ + for (i = 0, txo = &adapter->tx_obj[i]; i < adapter->num_tx_qs; \ + i++, txo++) + ++#define for_all_evt_queues(adapter, eqo, i) \ ++ for (i = 0, eqo = &adapter->eq_obj[i]; i < adapter->num_evt_qs; \ ++ i++, eqo++) ++ ++#define is_mcc_eqo(eqo) (eqo->idx == 0) ++#define mcc_eqo(adapter) (&adapter->eq_obj[0]) ++ + #define PAGE_SHIFT_4K 12 + #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) + +@@ -418,10 +483,6 @@ extern const struct ethtool_ops be_ethtool_ops; + ((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \ + (size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K)) + +-/* Byte offset into the page corresponding to given address */ +-#define OFFSET_IN_PAGE(addr) \ +- ((size_t)(addr) & (PAGE_SIZE_4K-1)) +- + /* Returns bit offset within a DWORD of a bitfield */ + #define AMAP_BIT_OFFSET(_struct, field) \ + (((size_t)&(((_struct *)0)->field))%32) +@@ -498,12 +559,9 @@ static inline u8 is_udp_pkt(struct sk_buff *skb) + return val; + } + +-static inline void be_check_sriov_fn_type(struct be_adapter *adapter) ++static inline bool is_ipv4_pkt(struct sk_buff *skb) + { +- u32 sli_intf; +- +- pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); +- adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; ++ return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4; + } + + static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac) +@@ -524,9 +582,34 @@ static inline bool be_multi_rxq(const struct be_adapter *adapter) + return adapter->num_rx_qs > 1; + } + ++static inline bool be_error(struct be_adapter *adapter) ++{ ++ return adapter->eeh_err || adapter->ue_detected || adapter->fw_timeout; ++} ++ ++static inline bool be_is_wol_excluded(struct be_adapter *adapter) ++{ ++ struct pci_dev *pdev = adapter->pdev; ++ ++ if (!be_physfn(adapter)) ++ return true; ++ ++ switch (pdev->subsystem_device) { ++ case OC_SUBSYS_DEVICE_ID1: ++ case OC_SUBSYS_DEVICE_ID2: ++ case OC_SUBSYS_DEVICE_ID3: ++ case OC_SUBSYS_DEVICE_ID4: ++ return true; ++ default: ++ return false; ++ } ++} ++ + extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, + u16 num_popped); +-extern void be_link_status_update(struct be_adapter *adapter, u32 link_status); ++extern void be_link_status_update(struct be_adapter *adapter, u8 link_status); + extern void be_parse_stats(struct be_adapter *adapter); + extern int be_load_fw(struct be_adapter *adapter, u8 *func); ++extern bool be_is_wol_supported(struct be_adapter *adapter); ++extern bool be_pause_supported(struct be_adapter *adapter); + #endif /* BE_H */ +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 2c7b366..5d42468 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -31,11 +31,8 @@ static void be_mcc_notify(struct be_adapter *adapter) + struct be_queue_info *mccq = &adapter->mcc_obj.q; + u32 val = 0; + +- if (adapter->eeh_err) { +- dev_info(&adapter->pdev->dev, +- "Error in Card Detected! Cannot issue commands\n"); ++ if (be_error(adapter)) + return; +- } + + val |= mccq->id & DB_MCCQ_RING_ID_MASK; + val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; +@@ -64,10 +61,21 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl) + compl->flags = 0; + } + ++static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1) ++{ ++ unsigned long addr; ++ ++ addr = tag1; ++ addr = ((addr << 16) << 16) | tag0; ++ return (void *)addr; ++} ++ + static int be_mcc_compl_process(struct be_adapter *adapter, +- struct be_mcc_compl *compl) ++ struct be_mcc_compl *compl) + { + u16 compl_status, extd_status; ++ struct be_cmd_resp_hdr *resp_hdr; ++ u8 opcode = 0, subsystem = 0; + + /* Just swap the status to host endian; mcc tag is opaquely copied + * from mcc_wrb */ +@@ -76,32 +84,36 @@ static int be_mcc_compl_process(struct be_adapter *adapter, + compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & + CQE_STATUS_COMPL_MASK; + +- if (((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) || +- (compl->tag0 == OPCODE_COMMON_WRITE_OBJECT)) && +- (compl->tag1 == CMD_SUBSYSTEM_COMMON)) { ++ resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1); ++ ++ if (resp_hdr) { ++ opcode = resp_hdr->opcode; ++ subsystem = resp_hdr->subsystem; ++ } ++ ++ if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) || ++ (opcode == OPCODE_COMMON_WRITE_OBJECT)) && ++ (subsystem == CMD_SUBSYSTEM_COMMON)) { + adapter->flash_status = compl_status; + complete(&adapter->flash_compl); + } + + if (compl_status == MCC_STATUS_SUCCESS) { +- if (((compl->tag0 == OPCODE_ETH_GET_STATISTICS) || +- (compl->tag0 == OPCODE_ETH_GET_PPORT_STATS)) && +- (compl->tag1 == CMD_SUBSYSTEM_ETH)) { ++ if (((opcode == OPCODE_ETH_GET_STATISTICS) || ++ (opcode == OPCODE_ETH_GET_PPORT_STATS)) && ++ (subsystem == CMD_SUBSYSTEM_ETH)) { + be_parse_stats(adapter); + adapter->stats_cmd_sent = false; + } +- if (compl->tag0 == +- OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) { +- struct be_mcc_wrb *mcc_wrb = +- queue_index_node(&adapter->mcc_obj.q, +- compl->tag1); ++ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES && ++ subsystem == CMD_SUBSYSTEM_COMMON) { + struct be_cmd_resp_get_cntl_addnl_attribs *resp = +- embedded_payload(mcc_wrb); ++ (void *)resp_hdr; + adapter->drv_stats.be_on_die_temperature = + resp->on_die_temperature; + } + } else { +- if (compl->tag0 == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) ++ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) + be_get_temp_freq = 0; + + if (compl_status == MCC_STATUS_NOT_SUPPORTED || +@@ -111,13 +123,13 @@ static int be_mcc_compl_process(struct be_adapter *adapter, + if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { + dev_warn(&adapter->pdev->dev, "This domain(VM) is not " + "permitted to execute this cmd (opcode %d)\n", +- compl->tag0); ++ opcode); + } else { + extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & + CQE_STATUS_EXTD_MASK; + dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:" + "status %d, extd-status %d\n", +- compl->tag0, compl_status, extd_status); ++ opcode, compl_status, extd_status); + } + } + done: +@@ -128,7 +140,14 @@ done: + static void be_async_link_state_process(struct be_adapter *adapter, + struct be_async_event_link_state *evt) + { +- be_link_status_update(adapter, evt->port_link_status); ++ /* When link status changes, link speed must be re-queried from FW */ ++ adapter->phy.link_speed = -1; ++ ++ /* For the initial link status do not rely on the ASYNC event as ++ * it may not be received in some cases. ++ */ ++ if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT) ++ be_link_status_update(adapter, evt->port_link_status); + } + + /* Grp5 CoS Priority evt */ +@@ -149,7 +168,7 @@ static void be_async_grp5_qos_speed_process(struct be_adapter *adapter, + { + if (evt->physical_port == adapter->port_num) { + /* qos_link_speed is in units of 10 Mbps */ +- adapter->link_speed = evt->qos_link_speed * 10; ++ adapter->phy.link_speed = evt->qos_link_speed * 10; + } + } + +@@ -231,13 +250,13 @@ void be_async_mcc_disable(struct be_adapter *adapter) + adapter->mcc_obj.rearm_cq = false; + } + +-int be_process_mcc(struct be_adapter *adapter, int *status) ++int be_process_mcc(struct be_adapter *adapter) + { + struct be_mcc_compl *compl; +- int num = 0; ++ int num = 0, status = 0; + struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; + +- spin_lock_bh(&adapter->mcc_cq_lock); ++ spin_lock(&adapter->mcc_cq_lock); + while ((compl = be_mcc_compl_get(adapter))) { + if (compl->flags & CQE_FLAGS_ASYNC_MASK) { + /* Interpret flags as an async trailer */ +@@ -248,40 +267,43 @@ int be_process_mcc(struct be_adapter *adapter, int *status) + be_async_grp5_evt_process(adapter, + compl->flags, compl); + } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { +- *status = be_mcc_compl_process(adapter, compl); ++ status = be_mcc_compl_process(adapter, compl); + atomic_dec(&mcc_obj->q.used); + } + be_mcc_compl_use(compl); + num++; + } + +- spin_unlock_bh(&adapter->mcc_cq_lock); +- return num; ++ if (num) ++ be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num); ++ ++ spin_unlock(&adapter->mcc_cq_lock); ++ return status; + } + + /* Wait till no more pending mcc requests are present */ + static int be_mcc_wait_compl(struct be_adapter *adapter) + { + #define mcc_timeout 120000 /* 12s timeout */ +- int i, num, status = 0; ++ int i, status = 0; + struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; + +- if (adapter->eeh_err) +- return -EIO; +- + for (i = 0; i < mcc_timeout; i++) { +- num = be_process_mcc(adapter, &status); +- if (num) +- be_cq_notify(adapter, mcc_obj->cq.id, +- mcc_obj->rearm_cq, num); ++ if (be_error(adapter)) ++ return -EIO; ++ ++ local_bh_disable(); ++ status = be_process_mcc(adapter); ++ local_bh_enable(); + + if (atomic_read(&mcc_obj->q.used) == 0) + break; + udelay(100); + } + if (i == mcc_timeout) { +- dev_err(&adapter->pdev->dev, "mccq poll timed out\n"); +- return -1; ++ dev_err(&adapter->pdev->dev, "FW not responding\n"); ++ adapter->fw_timeout = true; ++ return -EIO; + } + return status; + } +@@ -289,8 +311,26 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) + /* Notify MCC requests and wait for completion */ + static int be_mcc_notify_wait(struct be_adapter *adapter) + { ++ int status; ++ struct be_mcc_wrb *wrb; ++ struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; ++ u16 index = mcc_obj->q.head; ++ struct be_cmd_resp_hdr *resp; ++ ++ index_dec(&index, mcc_obj->q.len); ++ wrb = queue_index_node(&mcc_obj->q, index); ++ ++ resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1); ++ + be_mcc_notify(adapter); +- return be_mcc_wait_compl(adapter); ++ ++ status = be_mcc_wait_compl(adapter); ++ if (status == -EIO) ++ goto out; ++ ++ status = resp->status; ++out: ++ return status; + } + + static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) +@@ -298,26 +338,21 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) + int msecs = 0; + u32 ready; + +- if (adapter->eeh_err) { +- dev_err(&adapter->pdev->dev, +- "Error detected in card.Cannot issue commands\n"); +- return -EIO; +- } +- + do { ++ if (be_error(adapter)) ++ return -EIO; ++ + ready = ioread32(db); +- if (ready == 0xffffffff) { +- dev_err(&adapter->pdev->dev, +- "pci slot disconnected\n"); ++ if (ready == 0xffffffff) + return -1; +- } + + ready &= MPU_MAILBOX_DB_RDY_MASK; + if (ready) + break; + + if (msecs > 4000) { +- dev_err(&adapter->pdev->dev, "mbox poll timed out\n"); ++ dev_err(&adapter->pdev->dev, "FW not responding\n"); ++ adapter->fw_timeout = true; + be_detect_dump_ue(adapter); + return -1; + } +@@ -435,14 +470,17 @@ static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, + struct be_mcc_wrb *wrb, struct be_dma_mem *mem) + { + struct be_sge *sge; ++ unsigned long addr = (unsigned long)req_hdr; ++ u64 req_addr = addr; + + req_hdr->opcode = opcode; + req_hdr->subsystem = subsystem; + req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); + req_hdr->version = 0; + +- wrb->tag0 = opcode; +- wrb->tag1 = subsystem; ++ wrb->tag0 = req_addr & 0xFFFFFFFF; ++ wrb->tag1 = upper_32_bits(req_addr); ++ + wrb->payload_length = cmd_len; + if (mem) { + wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) << +@@ -555,9 +593,6 @@ int be_cmd_fw_clean(struct be_adapter *adapter) + u8 *wrb; + int status; + +- if (adapter->eeh_err) +- return -EIO; +- + if (mutex_lock_interruptible(&adapter->mbox_lock)) + return -1; + +@@ -619,7 +654,7 @@ int be_cmd_eq_create(struct be_adapter *adapter, + + /* Use MCC */ + int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, +- u8 type, bool permanent, u32 if_handle) ++ u8 type, bool permanent, u32 if_handle, u32 pmac_id) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_mac_query *req; +@@ -641,6 +676,7 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, + req->permanent = 1; + } else { + req->if_id = cpu_to_le16((u16) if_handle); ++ req->pmac_id = cpu_to_le32(pmac_id); + req->permanent = 0; + } + +@@ -695,12 +731,15 @@ err: + } + + /* Uses synchronous MCCQ */ +-int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id, u32 dom) ++int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_pmac_del *req; + int status; + ++ if (pmac_id == -1) ++ return 0; ++ + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); +@@ -725,9 +764,8 @@ err: + } + + /* Uses Mbox */ +-int be_cmd_cq_create(struct be_adapter *adapter, +- struct be_queue_info *cq, struct be_queue_info *eq, +- bool sol_evts, bool no_delay, int coalesce_wm) ++int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq, ++ struct be_queue_info *eq, bool no_delay, int coalesce_wm) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_cq_create *req; +@@ -758,7 +796,6 @@ int be_cmd_cq_create(struct be_adapter *adapter, + ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context_lancer, eqid, + ctxt, eq->id); +- AMAP_SET_BITS(struct amap_cq_context_lancer, armed, ctxt, 1); + } else { + AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt, + coalesce_wm); +@@ -767,11 +804,8 @@ int be_cmd_cq_create(struct be_adapter *adapter, + AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt, + __ilog2_u32(cq->len/256)); + AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1); +- AMAP_SET_BITS(struct amap_cq_context_be, solevent, +- ctxt, sol_evts); + AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id); +- AMAP_SET_BITS(struct amap_cq_context_be, armed, ctxt, 1); + } + + be_dws_cpu_to_le(ctxt, sizeof(req->context)); +@@ -923,10 +957,14 @@ int be_cmd_txq_create(struct be_adapter *adapter, + void *ctxt; + int status; + +- if (mutex_lock_interruptible(&adapter->mbox_lock)) +- return -1; ++ spin_lock_bh(&adapter->mcc_lock); ++ ++ wrb = wrb_from_mccq(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err; ++ } + +- wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); + ctxt = &req->context; + +@@ -952,14 +990,15 @@ int be_cmd_txq_create(struct be_adapter *adapter, + + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + +- status = be_mbox_notify_wait(adapter); ++ status = be_mcc_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb); + txq->id = le16_to_cpu(resp->cid); + txq->created = true; + } + +- mutex_unlock(&adapter->mbox_lock); ++err: ++ spin_unlock_bh(&adapter->mcc_lock); + + return status; + } +@@ -967,7 +1006,7 @@ int be_cmd_txq_create(struct be_adapter *adapter, + /* Uses MCC */ + int be_cmd_rxq_create(struct be_adapter *adapter, + struct be_queue_info *rxq, u16 cq_id, u16 frag_size, +- u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id) ++ u32 if_id, u32 rss, u8 *rss_id) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_eth_rx_create *req; +@@ -991,7 +1030,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter, + req->num_pages = 2; + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + req->interface_id = cpu_to_le32(if_id); +- req->max_frame_size = cpu_to_le16(max_frame_size); ++ req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE); + req->rss_queue = cpu_to_le32(rss); + + status = be_mcc_notify_wait(adapter); +@@ -1018,9 +1057,6 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, + u8 subsys = 0, opcode = 0; + int status; + +- if (adapter->eeh_err) +- return -EIO; +- + if (mutex_lock_interruptible(&adapter->mbox_lock)) + return -1; + +@@ -1136,16 +1172,13 @@ err: + } + + /* Uses MCCQ */ +-int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, u32 domain) ++int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_if_destroy *req; + int status; + +- if (adapter->eeh_err) +- return -EIO; +- +- if (!interface_id) ++ if (interface_id == -1) + return 0; + + spin_lock_bh(&adapter->mcc_lock); +@@ -1226,7 +1259,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, + OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size, wrb, + nonemb_cmd); + +- req->cmd_params.params.pport_num = cpu_to_le16(adapter->port_num); ++ req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num); + req->cmd_params.params.reset_stats = 0; + + be_mcc_notify(adapter); +@@ -1239,7 +1272,7 @@ err: + + /* Uses synchronous mcc */ + int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, +- u16 *link_speed, u32 dom) ++ u16 *link_speed, u8 *link_status, u32 dom) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_link_status *req; +@@ -1247,6 +1280,9 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, + + spin_lock_bh(&adapter->mcc_lock); + ++ if (link_status) ++ *link_status = LINK_DOWN; ++ + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; +@@ -1257,14 +1293,22 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL); + ++ if (adapter->generation == BE_GEN3 || lancer_chip(adapter)) ++ req->hdr.version = 1; ++ ++ req->hdr.domain = dom; ++ + status = be_mcc_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_link_status *resp = embedded_payload(wrb); + if (resp->mac_speed != PHY_LINK_SPEED_ZERO) { +- *link_speed = le16_to_cpu(resp->link_speed); ++ if (link_speed) ++ *link_speed = le16_to_cpu(resp->link_speed); + if (mac_speed) + *mac_speed = resp->mac_speed; + } ++ if (link_status) ++ *link_status = resp->logical_link_status; + } + + err: +@@ -1277,13 +1321,10 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_cntl_addnl_attribs *req; +- u16 mccq_index; + int status; + + spin_lock_bh(&adapter->mcc_lock); + +- mccq_index = adapter->mcc_obj.q.head; +- + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; +@@ -1295,8 +1336,6 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter) + OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req), + wrb, NULL); + +- wrb->tag1 = mccq_index; +- + be_mcc_notify(adapter); + + err: +@@ -1673,8 +1712,9 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_rss_config *req; +- u32 myhash[10] = {0x0123, 0x4567, 0x89AB, 0xCDEF, 0x01EF, +- 0x0123, 0x4567, 0x89AB, 0xCDEF, 0x01EF}; ++ u32 myhash[10] = {0x15d43fa5, 0x2534685a, 0x5f87693a, 0x5668494e, ++ 0x33cf6a53, 0x383334c6, 0x76ac4257, 0x59b242b2, ++ 0x3ea83c02, 0x4a110304}; + int status; + + if (mutex_lock_interruptible(&adapter->mbox_lock)) +@@ -1687,7 +1727,15 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size) + OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL); + + req->if_id = cpu_to_le32(adapter->if_handle); +- req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4); ++ req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4 | ++ RSS_ENABLE_TCP_IPV6 | RSS_ENABLE_IPV6); ++ ++ if (lancer_chip(adapter) || skyhawk_chip(adapter)) { ++ req->hdr.version = 1; ++ req->enable_rss |= cpu_to_le16(RSS_ENABLE_UDP_IPV4 | ++ RSS_ENABLE_UDP_IPV6); ++ } ++ + req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1); + memcpy(req->cpu_table, rsstable, table_size); + memcpy(req->hash, myhash, sizeof(myhash)); +@@ -1816,18 +1864,16 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, + spin_unlock_bh(&adapter->mcc_lock); + + if (!wait_for_completion_timeout(&adapter->flash_compl, +- msecs_to_jiffies(12000))) ++ msecs_to_jiffies(30000))) + status = -1; + else + status = adapter->flash_status; + + resp = embedded_payload(wrb); +- if (!status) { ++ if (!status) + *data_written = le32_to_cpu(resp->actual_write_len); +- } else { ++ else + *addn_status = resp->additional_status; +- status = resp->status; +- } + + return status; + +@@ -1836,6 +1882,53 @@ err_unlock: + return status; + } + ++int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, ++ u32 data_size, u32 data_offset, const char *obj_name, ++ u32 *data_read, u32 *eof, u8 *addn_status) ++{ ++ struct be_mcc_wrb *wrb; ++ struct lancer_cmd_req_read_object *req; ++ struct lancer_cmd_resp_read_object *resp; ++ int status; ++ ++ spin_lock_bh(&adapter->mcc_lock); ++ ++ wrb = wrb_from_mccq(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err_unlock; ++ } ++ ++ req = embedded_payload(wrb); ++ ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, ++ OPCODE_COMMON_READ_OBJECT, ++ sizeof(struct lancer_cmd_req_read_object), wrb, ++ NULL); ++ ++ req->desired_read_len = cpu_to_le32(data_size); ++ req->read_offset = cpu_to_le32(data_offset); ++ strcpy(req->object_name, obj_name); ++ req->descriptor_count = cpu_to_le32(1); ++ req->buf_len = cpu_to_le32(data_size); ++ req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF)); ++ req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma)); ++ ++ status = be_mcc_notify_wait(adapter); ++ ++ resp = embedded_payload(wrb); ++ if (!status) { ++ *data_read = le32_to_cpu(resp->actual_read_len); ++ *eof = le32_to_cpu(resp->eof); ++ } else { ++ *addn_status = resp->additional_status; ++ } ++ ++err_unlock: ++ spin_unlock_bh(&adapter->mcc_lock); ++ return status; ++} ++ + int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, + u32 flash_type, u32 flash_opcode, u32 buf_size) + { +@@ -1895,7 +1988,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4, wrb, NULL); + +- req->params.op_type = cpu_to_le32(IMG_TYPE_REDBOOT); ++ req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT); + req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); + req->params.offset = cpu_to_le32(offset); + req->params.data_buf_size = cpu_to_le32(0x4); +@@ -2081,8 +2174,7 @@ err: + return status; + } + +-int be_cmd_get_phy_info(struct be_adapter *adapter, +- struct be_phy_info *phy_info) ++int be_cmd_get_phy_info(struct be_adapter *adapter) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_phy_info *req; +@@ -2115,9 +2207,15 @@ int be_cmd_get_phy_info(struct be_adapter *adapter, + if (!status) { + struct be_phy_info *resp_phy_info = + cmd.va + sizeof(struct be_cmd_req_hdr); +- phy_info->phy_type = le16_to_cpu(resp_phy_info->phy_type); +- phy_info->interface_type = ++ adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type); ++ adapter->phy.interface_type = + le16_to_cpu(resp_phy_info->interface_type); ++ adapter->phy.auto_speeds_supported = ++ le16_to_cpu(resp_phy_info->auto_speeds_supported); ++ adapter->phy.fixed_speeds_supported = ++ le16_to_cpu(resp_phy_info->fixed_speeds_supported); ++ adapter->phy.misc_params = ++ le32_to_cpu(resp_phy_info->misc_params); + } + pci_free_consistent(adapter->pdev, cmd.size, + cmd.va, cmd.dma); +@@ -2238,3 +2336,266 @@ err: + mutex_unlock(&adapter->mbox_lock); + return status; + } ++ ++/* Uses synchronous MCCQ */ ++int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, ++ bool *pmac_id_active, u32 *pmac_id, u8 *mac) ++{ ++ struct be_mcc_wrb *wrb; ++ struct be_cmd_req_get_mac_list *req; ++ int status; ++ int mac_count; ++ struct be_dma_mem get_mac_list_cmd; ++ int i; ++ ++ memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem)); ++ get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list); ++ get_mac_list_cmd.va = pci_alloc_consistent(adapter->pdev, ++ get_mac_list_cmd.size, ++ &get_mac_list_cmd.dma); ++ ++ if (!get_mac_list_cmd.va) { ++ dev_err(&adapter->pdev->dev, ++ "Memory allocation failure during GET_MAC_LIST\n"); ++ return -ENOMEM; ++ } ++ ++ spin_lock_bh(&adapter->mcc_lock); ++ ++ wrb = wrb_from_mccq(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto out; ++ } ++ ++ req = get_mac_list_cmd.va; ++ ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, ++ OPCODE_COMMON_GET_MAC_LIST, sizeof(*req), ++ wrb, &get_mac_list_cmd); ++ ++ req->hdr.domain = domain; ++ req->mac_type = MAC_ADDRESS_TYPE_NETWORK; ++ req->perm_override = 1; ++ ++ status = be_mcc_notify_wait(adapter); ++ if (!status) { ++ struct be_cmd_resp_get_mac_list *resp = ++ get_mac_list_cmd.va; ++ mac_count = resp->true_mac_count + resp->pseudo_mac_count; ++ /* Mac list returned could contain one or more active mac_ids ++ * or one or more pseudo permanant mac addresses. If an active ++ * mac_id is present, return first active mac_id found ++ */ ++ for (i = 0; i < mac_count; i++) { ++ struct get_list_macaddr *mac_entry; ++ u16 mac_addr_size; ++ u32 mac_id; ++ ++ mac_entry = &resp->macaddr_list[i]; ++ mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size); ++ /* mac_id is a 32 bit value and mac_addr size ++ * is 6 bytes ++ */ ++ if (mac_addr_size == sizeof(u32)) { ++ *pmac_id_active = true; ++ mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id; ++ *pmac_id = le32_to_cpu(mac_id); ++ goto out; ++ } ++ } ++ /* If no active mac_id found, return first pseudo mac addr */ ++ *pmac_id_active = false; ++ memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr, ++ ETH_ALEN); ++ } ++ ++out: ++ spin_unlock_bh(&adapter->mcc_lock); ++ pci_free_consistent(adapter->pdev, get_mac_list_cmd.size, ++ get_mac_list_cmd.va, get_mac_list_cmd.dma); ++ return status; ++} ++ ++/* Uses synchronous MCCQ */ ++int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, ++ u8 mac_count, u32 domain) ++{ ++ struct be_mcc_wrb *wrb; ++ struct be_cmd_req_set_mac_list *req; ++ int status; ++ struct be_dma_mem cmd; ++ ++ memset(&cmd, 0, sizeof(struct be_dma_mem)); ++ cmd.size = sizeof(struct be_cmd_req_set_mac_list); ++ cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, ++ &cmd.dma, GFP_KERNEL); ++ if (!cmd.va) { ++ dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); ++ return -ENOMEM; ++ } ++ ++ spin_lock_bh(&adapter->mcc_lock); ++ ++ wrb = wrb_from_mccq(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err; ++ } ++ ++ req = cmd.va; ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, ++ OPCODE_COMMON_SET_MAC_LIST, sizeof(*req), ++ wrb, &cmd); ++ ++ req->hdr.domain = domain; ++ req->mac_count = mac_count; ++ if (mac_count) ++ memcpy(req->mac, mac_array, ETH_ALEN*mac_count); ++ ++ status = be_mcc_notify_wait(adapter); ++ ++err: ++ dma_free_coherent(&adapter->pdev->dev, cmd.size, ++ cmd.va, cmd.dma); ++ spin_unlock_bh(&adapter->mcc_lock); ++ return status; ++} ++ ++int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, ++ u32 domain, u16 intf_id) ++{ ++ struct be_mcc_wrb *wrb; ++ struct be_cmd_req_set_hsw_config *req; ++ void *ctxt; ++ int status; ++ ++ spin_lock_bh(&adapter->mcc_lock); ++ ++ wrb = wrb_from_mccq(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err; ++ } ++ ++ req = embedded_payload(wrb); ++ ctxt = &req->context; ++ ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, ++ OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb, NULL); ++ ++ req->hdr.domain = domain; ++ AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id); ++ if (pvid) { ++ AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1); ++ AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid); ++ } ++ ++ be_dws_cpu_to_le(req->context, sizeof(req->context)); ++ status = be_mcc_notify_wait(adapter); ++ ++err: ++ spin_unlock_bh(&adapter->mcc_lock); ++ return status; ++} ++ ++/* Get Hyper switch config */ ++int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, ++ u32 domain, u16 intf_id) ++{ ++ struct be_mcc_wrb *wrb; ++ struct be_cmd_req_get_hsw_config *req; ++ void *ctxt; ++ int status; ++ u16 vid; ++ ++ spin_lock_bh(&adapter->mcc_lock); ++ ++ wrb = wrb_from_mccq(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err; ++ } ++ ++ req = embedded_payload(wrb); ++ ctxt = &req->context; ++ ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, ++ OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb, NULL); ++ ++ req->hdr.domain = domain; ++ AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id, ctxt, ++ intf_id); ++ AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1); ++ be_dws_cpu_to_le(req->context, sizeof(req->context)); ++ ++ status = be_mcc_notify_wait(adapter); ++ if (!status) { ++ struct be_cmd_resp_get_hsw_config *resp = ++ embedded_payload(wrb); ++ be_dws_le_to_cpu(&resp->context, ++ sizeof(resp->context)); ++ vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context, ++ pvid, &resp->context); ++ *pvid = le16_to_cpu(vid); ++ } ++ ++err: ++ spin_unlock_bh(&adapter->mcc_lock); ++ return status; ++} ++ ++int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter) ++{ ++ struct be_mcc_wrb *wrb; ++ struct be_cmd_req_acpi_wol_magic_config_v1 *req; ++ int status; ++ int payload_len = sizeof(*req); ++ struct be_dma_mem cmd; ++ ++ memset(&cmd, 0, sizeof(struct be_dma_mem)); ++ cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1); ++ cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, ++ &cmd.dma); ++ if (!cmd.va) { ++ dev_err(&adapter->pdev->dev, ++ "Memory allocation failure\n"); ++ return -ENOMEM; ++ } ++ ++ if (mutex_lock_interruptible(&adapter->mbox_lock)) ++ return -1; ++ ++ wrb = wrb_from_mbox(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err; ++ } ++ ++ req = cmd.va; ++ ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, ++ OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, ++ payload_len, wrb, &cmd); ++ ++ req->hdr.version = 1; ++ req->query_options = BE_GET_WOL_CAP; ++ ++ status = be_mbox_notify_wait(adapter); ++ if (!status) { ++ struct be_cmd_resp_acpi_wol_magic_config_v1 *resp; ++ resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *) cmd.va; ++ ++ /* the command could succeed misleadingly on old f/w ++ * which is not aware of the V1 version. fake an error. */ ++ if (resp->hdr.response_length < payload_len) { ++ status = -1; ++ goto err; ++ } ++ adapter->wol_cap = resp->wol_settings; ++ } ++err: ++ mutex_unlock(&adapter->mbox_lock); ++ pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); ++ return status; ++} +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index a35cd03..d42b3b9 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -189,6 +189,11 @@ struct be_mcc_mailbox { + #define OPCODE_COMMON_GET_PHY_DETAILS 102 + #define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103 + #define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121 ++#define OPCODE_COMMON_GET_MAC_LIST 147 ++#define OPCODE_COMMON_SET_MAC_LIST 148 ++#define OPCODE_COMMON_GET_HSW_CONFIG 152 ++#define OPCODE_COMMON_SET_HSW_CONFIG 153 ++#define OPCODE_COMMON_READ_OBJECT 171 + #define OPCODE_COMMON_WRITE_OBJECT 172 + + #define OPCODE_ETH_RSS_CONFIG 1 +@@ -220,8 +225,12 @@ struct be_cmd_req_hdr { + #define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ + #define RESP_HDR_INFO_SUBSYS_SHIFT 8 /* bits 8 - 15 */ + struct be_cmd_resp_hdr { +- u32 info; /* dword 0 */ +- u32 status; /* dword 1 */ ++ u8 opcode; /* dword 0 */ ++ u8 subsystem; /* dword 0 */ ++ u8 rsvd[2]; /* dword 0 */ ++ u8 status; /* dword 1 */ ++ u8 add_status; /* dword 1 */ ++ u8 rsvd1[2]; /* dword 1 */ + u32 response_length; /* dword 2 */ + u32 actual_resp_len; /* dword 3 */ + }; +@@ -294,6 +303,7 @@ struct be_cmd_req_mac_query { + u8 type; + u8 permanent; + u16 if_id; ++ u32 pmac_id; + } __packed; + + struct be_cmd_resp_mac_query { +@@ -588,8 +598,8 @@ struct be_port_rxf_stats_v0 { + u32 rx_in_range_errors; /* dword 10*/ + u32 rx_out_range_errors; /* dword 11*/ + u32 rx_frame_too_long; /* dword 12*/ +- u32 rx_address_match_errors; /* dword 13*/ +- u32 rx_vlan_mismatch; /* dword 14*/ ++ u32 rx_address_mismatch_drops; /* dword 13*/ ++ u32 rx_vlan_mismatch_drops; /* dword 14*/ + u32 rx_dropped_too_small; /* dword 15*/ + u32 rx_dropped_too_short; /* dword 16*/ + u32 rx_dropped_header_too_small; /* dword 17*/ +@@ -795,8 +805,8 @@ struct lancer_pport_stats { + u32 rx_control_frames_unknown_opcode_hi; + u32 rx_in_range_errors; + u32 rx_out_of_range_errors; +- u32 rx_address_match_errors; +- u32 rx_vlan_mismatch_errors; ++ u32 rx_address_mismatch_drops; ++ u32 rx_vlan_mismatch_drops; + u32 rx_dropped_too_small; + u32 rx_dropped_too_short; + u32 rx_dropped_header_too_small; +@@ -956,7 +966,8 @@ struct be_cmd_resp_link_status { + u8 mgmt_mac_duplex; + u8 mgmt_mac_speed; + u16 link_speed; +- u32 rsvd0; ++ u8 logical_link_status; ++ u8 rsvd1[3]; + } __packed; + + /******************** Port Identification ***************************/ +@@ -1074,6 +1085,8 @@ struct be_cmd_resp_query_fw_cfg { + #define RSS_ENABLE_TCP_IPV4 0x2 + #define RSS_ENABLE_IPV6 0x4 + #define RSS_ENABLE_TCP_IPV6 0x8 ++#define RSS_ENABLE_UDP_IPV4 0x10 ++#define RSS_ENABLE_UDP_IPV6 0x20 + + struct be_cmd_req_rss_config { + struct be_cmd_req_hdr hdr; +@@ -1161,6 +1174,38 @@ struct lancer_cmd_resp_write_object { + u32 actual_write_len; + }; + ++/************************ Lancer Read FW info **************/ ++#define LANCER_READ_FILE_CHUNK (32*1024) ++#define LANCER_READ_FILE_EOF_MASK 0x80000000 ++ ++#define LANCER_FW_DUMP_FILE "/dbg/dump.bin" ++#define LANCER_VPD_PF_FILE "/vpd/ntr_pf.vpd" ++#define LANCER_VPD_VF_FILE "/vpd/ntr_vf.vpd" ++ ++struct lancer_cmd_req_read_object { ++ struct be_cmd_req_hdr hdr; ++ u32 desired_read_len; ++ u32 read_offset; ++ u8 object_name[104]; ++ u32 descriptor_count; ++ u32 buf_len; ++ u32 addr_low; ++ u32 addr_high; ++}; ++ ++struct lancer_cmd_resp_read_object { ++ u8 opcode; ++ u8 subsystem; ++ u8 rsvd1[2]; ++ u8 status; ++ u8 additional_status; ++ u8 rsvd2[2]; ++ u32 resp_len; ++ u32 actual_resp_len; ++ u32 actual_read_len; ++ u32 eof; ++}; ++ + /************************ WOL *******************************/ + struct be_cmd_req_acpi_wol_magic_config{ + struct be_cmd_req_hdr hdr; +@@ -1169,6 +1214,33 @@ struct be_cmd_req_acpi_wol_magic_config{ + u8 rsvd2[2]; + } __packed; + ++struct be_cmd_req_acpi_wol_magic_config_v1 { ++ struct be_cmd_req_hdr hdr; ++ u8 rsvd0[2]; ++ u8 query_options; ++ u8 rsvd1[5]; ++ u32 rsvd2[288]; ++ u8 magic_mac[6]; ++ u8 rsvd3[22]; ++} __packed; ++ ++struct be_cmd_resp_acpi_wol_magic_config_v1 { ++ struct be_cmd_resp_hdr hdr; ++ u8 rsvd0[2]; ++ u8 wol_settings; ++ u8 rsvd1[5]; ++ u32 rsvd2[295]; ++} __packed; ++ ++#define BE_GET_WOL_CAP 2 ++ ++#define BE_WOL_CAP 0x1 ++#define BE_PME_D0_CAP 0x8 ++#define BE_PME_D1_CAP 0x10 ++#define BE_PME_D2_CAP 0x20 ++#define BE_PME_D3HOT_CAP 0x40 ++#define BE_PME_D3COLD_CAP 0x80 ++ + /********************** LoopBack test *********************/ + struct be_cmd_req_loopback_test { + struct be_cmd_req_hdr hdr; +@@ -1243,9 +1315,36 @@ enum { + PHY_TYPE_KX4_10GB, + PHY_TYPE_BASET_10GB, + PHY_TYPE_BASET_1GB, ++ PHY_TYPE_BASEX_1GB, ++ PHY_TYPE_SGMII, + PHY_TYPE_DISABLED = 255 + }; + ++#define BE_SUPPORTED_SPEED_NONE 0 ++#define BE_SUPPORTED_SPEED_10MBPS 1 ++#define BE_SUPPORTED_SPEED_100MBPS 2 ++#define BE_SUPPORTED_SPEED_1GBPS 4 ++#define BE_SUPPORTED_SPEED_10GBPS 8 ++ ++#define BE_AN_EN 0x2 ++#define BE_PAUSE_SYM_EN 0x80 ++ ++/* MAC speed valid values */ ++#define SPEED_DEFAULT 0x0 ++#define SPEED_FORCED_10GB 0x1 ++#define SPEED_FORCED_1GB 0x2 ++#define SPEED_AUTONEG_10GB 0x3 ++#define SPEED_AUTONEG_1GB 0x4 ++#define SPEED_AUTONEG_100MB 0x5 ++#define SPEED_AUTONEG_10GB_1GB 0x6 ++#define SPEED_AUTONEG_10GB_1GB_100MB 0x7 ++#define SPEED_AUTONEG_1GB_100MB 0x8 ++#define SPEED_AUTONEG_10MB 0x9 ++#define SPEED_AUTONEG_1GB_100MB_10MB 0xa ++#define SPEED_AUTONEG_100MB_10MB 0xb ++#define SPEED_FORCED_100MB 0xc ++#define SPEED_FORCED_10MB 0xd ++ + struct be_cmd_req_get_phy_info { + struct be_cmd_req_hdr hdr; + u8 rsvd0[24]; +@@ -1255,7 +1354,11 @@ struct be_phy_info { + u16 phy_type; + u16 interface_type; + u32 misc_params; +- u32 future_use[4]; ++ u16 ext_phy_details; ++ u16 rsvd; ++ u16 auto_speeds_supported; ++ u16 fixed_speeds_supported; ++ u32 future_use[2]; + }; + + struct be_cmd_resp_get_phy_info { +@@ -1307,6 +1410,97 @@ struct be_cmd_resp_set_func_cap { + u8 rsvd[212]; + }; + ++/******************** GET/SET_MACLIST **************************/ ++#define BE_MAX_MAC 64 ++struct be_cmd_req_get_mac_list { ++ struct be_cmd_req_hdr hdr; ++ u8 mac_type; ++ u8 perm_override; ++ u16 iface_id; ++ u32 mac_id; ++ u32 rsvd[3]; ++} __packed; ++ ++struct get_list_macaddr { ++ u16 mac_addr_size; ++ union { ++ u8 macaddr[6]; ++ struct { ++ u8 rsvd[2]; ++ u32 mac_id; ++ } __packed s_mac_id; ++ } __packed mac_addr_id; ++} __packed; ++ ++struct be_cmd_resp_get_mac_list { ++ struct be_cmd_resp_hdr hdr; ++ struct get_list_macaddr fd_macaddr; /* Factory default mac */ ++ struct get_list_macaddr macid_macaddr; /* soft mac */ ++ u8 true_mac_count; ++ u8 pseudo_mac_count; ++ u8 mac_list_size; ++ u8 rsvd; ++ /* perm override mac */ ++ struct get_list_macaddr macaddr_list[BE_MAX_MAC]; ++} __packed; ++ ++struct be_cmd_req_set_mac_list { ++ struct be_cmd_req_hdr hdr; ++ u8 mac_count; ++ u8 rsvd1; ++ u16 rsvd2; ++ struct macaddr mac[BE_MAX_MAC]; ++} __packed; ++ ++/*********************** HSW Config ***********************/ ++struct amap_set_hsw_context { ++ u8 interface_id[16]; ++ u8 rsvd0[14]; ++ u8 pvid_valid; ++ u8 rsvd1; ++ u8 rsvd2[16]; ++ u8 pvid[16]; ++ u8 rsvd3[32]; ++ u8 rsvd4[32]; ++ u8 rsvd5[32]; ++} __packed; ++ ++struct be_cmd_req_set_hsw_config { ++ struct be_cmd_req_hdr hdr; ++ u8 context[sizeof(struct amap_set_hsw_context) / 8]; ++} __packed; ++ ++struct be_cmd_resp_set_hsw_config { ++ struct be_cmd_resp_hdr hdr; ++ u32 rsvd; ++}; ++ ++struct amap_get_hsw_req_context { ++ u8 interface_id[16]; ++ u8 rsvd0[14]; ++ u8 pvid_valid; ++ u8 pport; ++} __packed; ++ ++struct amap_get_hsw_resp_context { ++ u8 rsvd1[16]; ++ u8 pvid[16]; ++ u8 rsvd2[32]; ++ u8 rsvd3[32]; ++ u8 rsvd4[32]; ++} __packed; ++ ++struct be_cmd_req_get_hsw_config { ++ struct be_cmd_req_hdr hdr; ++ u8 context[sizeof(struct amap_get_hsw_req_context) / 8]; ++} __packed; ++ ++struct be_cmd_resp_get_hsw_config { ++ struct be_cmd_resp_hdr hdr; ++ u8 context[sizeof(struct amap_get_hsw_resp_context) / 8]; ++ u32 rsvd; ++}; ++ + /*************** HW Stats Get v1 **********************************/ + #define BE_TXP_SW_SZ 48 + struct be_port_rxf_stats_v1 { +@@ -1319,7 +1513,7 @@ struct be_port_rxf_stats_v1 { + u32 rx_in_range_errors; + u32 rx_out_range_errors; + u32 rx_frame_too_long; +- u32 rx_address_match_errors; ++ u32 rx_address_mismatch_drops; + u32 rx_dropped_too_small; + u32 rx_dropped_too_short; + u32 rx_dropped_header_too_small; +@@ -1371,7 +1565,7 @@ struct be_hw_stats_v1 { + u32 rsvd0[BE_TXP_SW_SZ]; + struct be_erx_stats_v1 erx; + struct be_pmem_stats pmem; +- u32 rsvd1[3]; ++ u32 rsvd1[18]; + }; + + struct be_cmd_req_get_stats_v1 { +@@ -1413,22 +1607,21 @@ static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter) + extern int be_pci_fnum_get(struct be_adapter *adapter); + extern int be_cmd_POST(struct be_adapter *adapter); + extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, +- u8 type, bool permanent, u32 if_handle); ++ u8 type, bool permanent, u32 if_handle, u32 pmac_id); + extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, + u32 if_id, u32 *pmac_id, u32 domain); + extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, +- u32 pmac_id, u32 domain); ++ int pmac_id, u32 domain); + extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, + u32 en_flags, u8 *mac, u32 *if_handle, u32 *pmac_id, + u32 domain); +-extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle, ++extern int be_cmd_if_destroy(struct be_adapter *adapter, int if_handle, + u32 domain); + extern int be_cmd_eq_create(struct be_adapter *adapter, + struct be_queue_info *eq, int eq_delay); + extern int be_cmd_cq_create(struct be_adapter *adapter, + struct be_queue_info *cq, struct be_queue_info *eq, +- bool sol_evts, bool no_delay, +- int num_cqe_dma_coalesce); ++ bool no_delay, int num_cqe_dma_coalesce); + extern int be_cmd_mccq_create(struct be_adapter *adapter, + struct be_queue_info *mccq, + struct be_queue_info *cq); +@@ -1437,14 +1630,13 @@ extern int be_cmd_txq_create(struct be_adapter *adapter, + struct be_queue_info *cq); + extern int be_cmd_rxq_create(struct be_adapter *adapter, + struct be_queue_info *rxq, u16 cq_id, +- u16 frag_size, u16 max_frame_size, u32 if_id, +- u32 rss, u8 *rss_id); ++ u16 frag_size, u32 if_id, u32 rss, u8 *rss_id); + extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, + int type); + extern int be_cmd_rxq_destroy(struct be_adapter *adapter, + struct be_queue_info *q); +-extern int be_cmd_link_status_query(struct be_adapter *adapter, +- u8 *mac_speed, u16 *link_speed, u32 dom); ++extern int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, ++ u16 *link_speed, u8 *link_status, u32 dom); + extern int be_cmd_reset(struct be_adapter *adapter); + extern int be_cmd_get_stats(struct be_adapter *adapter, + struct be_dma_mem *nonemb_cmd); +@@ -1467,7 +1659,7 @@ extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, + extern int be_cmd_reset_function(struct be_adapter *adapter); + extern int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, + u16 table_size); +-extern int be_process_mcc(struct be_adapter *adapter, int *status); ++extern int be_process_mcc(struct be_adapter *adapter); + extern int be_cmd_set_beacon_state(struct be_adapter *adapter, + u8 port_num, u8 beacon, u8 status, u8 state); + extern int be_cmd_get_beacon_state(struct be_adapter *adapter, +@@ -1480,6 +1672,9 @@ extern int lancer_cmd_write_object(struct be_adapter *adapter, + u32 data_size, u32 data_offset, + const char *obj_name, + u32 *data_written, u8 *addn_status); ++int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, ++ u32 data_size, u32 data_offset, const char *obj_name, ++ u32 *data_read, u32 *eof, u8 *addn_status); + int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, + int offset); + extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, +@@ -1497,8 +1692,7 @@ extern int be_cmd_get_seeprom_data(struct be_adapter *adapter, + struct be_dma_mem *nonemb_cmd); + extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, + u8 loopback_type, u8 enable); +-extern int be_cmd_get_phy_info(struct be_adapter *adapter, +- struct be_phy_info *phy_info); ++extern int be_cmd_get_phy_info(struct be_adapter *adapter); + extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); + extern void be_detect_dump_ue(struct be_adapter *adapter); + extern int be_cmd_get_die_temperature(struct be_adapter *adapter); +@@ -1506,4 +1700,13 @@ extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter); + extern int be_cmd_req_native_mode(struct be_adapter *adapter); + extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size); + extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf); ++extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, ++ bool *pmac_id_active, u32 *pmac_id, u8 *mac); ++extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, ++ u8 mac_count, u32 domain); ++extern int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, ++ u32 domain, u16 intf_id); ++extern int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, ++ u32 domain, u16 intf_id); ++extern int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter); + +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index 7570c1a..747f68f 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -37,20 +37,46 @@ enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT}; + FIELDINFO(struct be_drv_stats, field) + + static const struct be_ethtool_stat et_stats[] = { +- {DRVSTAT_INFO(tx_events)}, + {DRVSTAT_INFO(rx_crc_errors)}, + {DRVSTAT_INFO(rx_alignment_symbol_errors)}, + {DRVSTAT_INFO(rx_pause_frames)}, + {DRVSTAT_INFO(rx_control_frames)}, ++ /* Received packets dropped when the Ethernet length field ++ * is not equal to the actual Ethernet data length. ++ */ + {DRVSTAT_INFO(rx_in_range_errors)}, ++ /* Received packets dropped when their length field is >= 1501 bytes ++ * and <= 1535 bytes. ++ */ + {DRVSTAT_INFO(rx_out_range_errors)}, ++ /* Received packets dropped when they are longer than 9216 bytes */ + {DRVSTAT_INFO(rx_frame_too_long)}, +- {DRVSTAT_INFO(rx_address_match_errors)}, ++ /* Received packets dropped when they don't pass the unicast or ++ * multicast address filtering. ++ */ ++ {DRVSTAT_INFO(rx_address_mismatch_drops)}, ++ /* Received packets dropped when IP packet length field is less than ++ * the IP header length field. ++ */ + {DRVSTAT_INFO(rx_dropped_too_small)}, ++ /* Received packets dropped when IP length field is greater than ++ * the actual packet length. ++ */ + {DRVSTAT_INFO(rx_dropped_too_short)}, ++ /* Received packets dropped when the IP header length field is less ++ * than 5. ++ */ + {DRVSTAT_INFO(rx_dropped_header_too_small)}, ++ /* Received packets dropped when the TCP header length field is less ++ * than 5 or the TCP header length + IP header length is more ++ * than IP packet length. ++ */ + {DRVSTAT_INFO(rx_dropped_tcp_length)}, + {DRVSTAT_INFO(rx_dropped_runt)}, ++ /* Number of received packets dropped when a fifo for descriptors going ++ * into the packet demux block overflows. In normal operation, this ++ * fifo must never overflow. ++ */ + {DRVSTAT_INFO(rxpp_fifo_overflow_drop)}, + {DRVSTAT_INFO(rx_input_fifo_overflow_drop)}, + {DRVSTAT_INFO(rx_ip_checksum_errs)}, +@@ -59,16 +85,35 @@ static const struct be_ethtool_stat et_stats[] = { + {DRVSTAT_INFO(tx_pauseframes)}, + {DRVSTAT_INFO(tx_controlframes)}, + {DRVSTAT_INFO(rx_priority_pause_frames)}, ++ /* Received packets dropped when an internal fifo going into ++ * main packet buffer tank (PMEM) overflows. ++ */ + {DRVSTAT_INFO(pmem_fifo_overflow_drop)}, + {DRVSTAT_INFO(jabber_events)}, ++ /* Received packets dropped due to lack of available HW packet buffers ++ * used to temporarily hold the received packets. ++ */ + {DRVSTAT_INFO(rx_drops_no_pbuf)}, +- {DRVSTAT_INFO(rx_drops_no_txpb)}, ++ /* Received packets dropped due to input receive buffer ++ * descriptor fifo overflowing. ++ */ + {DRVSTAT_INFO(rx_drops_no_erx_descr)}, ++ /* Packets dropped because the internal FIFO to the offloaded TCP ++ * receive processing block is full. This could happen only for ++ * offloaded iSCSI or FCoE trarffic. ++ */ + {DRVSTAT_INFO(rx_drops_no_tpre_descr)}, ++ /* Received packets dropped when they need more than 8 ++ * receive buffers. This cannot happen as the driver configures ++ * 2048 byte receive buffers. ++ */ + {DRVSTAT_INFO(rx_drops_too_many_frags)}, +- {DRVSTAT_INFO(rx_drops_invalid_ring)}, + {DRVSTAT_INFO(forwarded_packets)}, ++ /* Received packets dropped when the frame length ++ * is more than 9018 bytes ++ */ + {DRVSTAT_INFO(rx_drops_mtu)}, ++ /* Number of packets dropped due to random early drop function */ + {DRVSTAT_INFO(eth_red_drops)}, + {DRVSTAT_INFO(be_on_die_temperature)} + }; +@@ -80,12 +125,17 @@ static const struct be_ethtool_stat et_stats[] = { + static const struct be_ethtool_stat et_rx_stats[] = { + {DRVSTAT_RX_INFO(rx_bytes)},/* If moving this member see above note */ + {DRVSTAT_RX_INFO(rx_pkts)}, /* If moving this member see above note */ +- {DRVSTAT_RX_INFO(rx_polls)}, +- {DRVSTAT_RX_INFO(rx_events)}, + {DRVSTAT_RX_INFO(rx_compl)}, + {DRVSTAT_RX_INFO(rx_mcast_pkts)}, ++ /* Number of page allocation failures while posting receive buffers ++ * to HW. ++ */ + {DRVSTAT_RX_INFO(rx_post_fail)}, ++ /* Recevied packets dropped due to skb allocation failure */ + {DRVSTAT_RX_INFO(rx_drops_no_skbs)}, ++ /* Received packets dropped due to lack of available fetched buffers ++ * posted by the driver. ++ */ + {DRVSTAT_RX_INFO(rx_drops_no_frags)} + }; + #define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats)) +@@ -97,9 +147,13 @@ static const struct be_ethtool_stat et_tx_stats[] = { + {DRVSTAT_TX_INFO(tx_compl)}, /* If moving this member see above note */ + {DRVSTAT_TX_INFO(tx_bytes)}, + {DRVSTAT_TX_INFO(tx_pkts)}, ++ /* Number of skbs queued for trasmission by the driver */ + {DRVSTAT_TX_INFO(tx_reqs)}, ++ /* Number of TX work request blocks DMAed to HW */ + {DRVSTAT_TX_INFO(tx_wrbs)}, +- {DRVSTAT_TX_INFO(tx_compl)}, ++ /* Number of times the TX queue was stopped due to lack ++ * of spaces in the TXQ. ++ */ + {DRVSTAT_TX_INFO(tx_stops)} + }; + #define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats)) +@@ -127,8 +181,8 @@ static void be_get_drvinfo(struct net_device *netdev, + memset(fw_on_flash, 0 , sizeof(fw_on_flash)); + be_cmd_get_fw_ver(adapter, adapter->fw_ver, fw_on_flash); + +- strcpy(drvinfo->driver, DRV_NAME); +- strcpy(drvinfo->version, DRV_VER); ++ strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); ++ strlcpy(drvinfo->version, DRV_VER, sizeof(drvinfo->version)); + strncpy(drvinfo->fw_version, adapter->fw_ver, FW_VER_LEN); + if (memcmp(adapter->fw_ver, fw_on_flash, FW_VER_LEN) != 0) { + strcat(drvinfo->fw_version, " ["); +@@ -136,21 +190,84 @@ static void be_get_drvinfo(struct net_device *netdev, + strcat(drvinfo->fw_version, "]"); + } + +- strcpy(drvinfo->bus_info, pci_name(adapter->pdev)); ++ strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), ++ sizeof(drvinfo->bus_info)); + drvinfo->testinfo_len = 0; + drvinfo->regdump_len = 0; + drvinfo->eedump_len = 0; + } + ++static u32 ++lancer_cmd_get_file_len(struct be_adapter *adapter, u8 *file_name) ++{ ++ u32 data_read = 0, eof; ++ u8 addn_status; ++ struct be_dma_mem data_len_cmd; ++ int status; ++ ++ memset(&data_len_cmd, 0, sizeof(data_len_cmd)); ++ /* data_offset and data_size should be 0 to get reg len */ ++ status = lancer_cmd_read_object(adapter, &data_len_cmd, 0, 0, ++ file_name, &data_read, &eof, &addn_status); ++ ++ return data_read; ++} ++ ++static int ++lancer_cmd_read_file(struct be_adapter *adapter, u8 *file_name, ++ u32 buf_len, void *buf) ++{ ++ struct be_dma_mem read_cmd; ++ u32 read_len = 0, total_read_len = 0, chunk_size; ++ u32 eof = 0; ++ u8 addn_status; ++ int status = 0; ++ ++ read_cmd.size = LANCER_READ_FILE_CHUNK; ++ read_cmd.va = pci_alloc_consistent(adapter->pdev, read_cmd.size, ++ &read_cmd.dma); ++ ++ if (!read_cmd.va) { ++ dev_err(&adapter->pdev->dev, ++ "Memory allocation failure while reading dump\n"); ++ return -ENOMEM; ++ } ++ ++ while ((total_read_len < buf_len) && !eof) { ++ chunk_size = min_t(u32, (buf_len - total_read_len), ++ LANCER_READ_FILE_CHUNK); ++ chunk_size = ALIGN(chunk_size, 4); ++ status = lancer_cmd_read_object(adapter, &read_cmd, chunk_size, ++ total_read_len, file_name, &read_len, ++ &eof, &addn_status); ++ if (!status) { ++ memcpy(buf + total_read_len, read_cmd.va, read_len); ++ total_read_len += read_len; ++ eof &= LANCER_READ_FILE_EOF_MASK; ++ } else { ++ status = -EIO; ++ break; ++ } ++ } ++ pci_free_consistent(adapter->pdev, read_cmd.size, read_cmd.va, ++ read_cmd.dma); ++ ++ return status; ++} ++ + static int + be_get_reg_len(struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); + u32 log_size = 0; + +- if (be_physfn(adapter)) +- be_cmd_get_reg_len(adapter, &log_size); +- ++ if (be_physfn(adapter)) { ++ if (lancer_chip(adapter)) ++ log_size = lancer_cmd_get_file_len(adapter, ++ LANCER_FW_DUMP_FILE); ++ else ++ be_cmd_get_reg_len(adapter, &log_size); ++ } + return log_size; + } + +@@ -161,90 +278,50 @@ be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf) + + if (be_physfn(adapter)) { + memset(buf, 0, regs->len); +- be_cmd_get_regs(adapter, regs->len, buf); ++ if (lancer_chip(adapter)) ++ lancer_cmd_read_file(adapter, LANCER_FW_DUMP_FILE, ++ regs->len, buf); ++ else ++ be_cmd_get_regs(adapter, regs->len, buf); + } + } + +-static int +-be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) ++static int be_get_coalesce(struct net_device *netdev, ++ struct ethtool_coalesce *et) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_eq_obj *rx_eq = &adapter->rx_obj[0].rx_eq; +- struct be_eq_obj *tx_eq = &adapter->tx_eq; ++ struct be_eq_obj *eqo = &adapter->eq_obj[0]; ++ + +- coalesce->rx_coalesce_usecs = rx_eq->cur_eqd; +- coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd; +- coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd; ++ et->rx_coalesce_usecs = eqo->cur_eqd; ++ et->rx_coalesce_usecs_high = eqo->max_eqd; ++ et->rx_coalesce_usecs_low = eqo->min_eqd; + +- coalesce->tx_coalesce_usecs = tx_eq->cur_eqd; +- coalesce->tx_coalesce_usecs_high = tx_eq->max_eqd; +- coalesce->tx_coalesce_usecs_low = tx_eq->min_eqd; ++ et->tx_coalesce_usecs = eqo->cur_eqd; ++ et->tx_coalesce_usecs_high = eqo->max_eqd; ++ et->tx_coalesce_usecs_low = eqo->min_eqd; + +- coalesce->use_adaptive_rx_coalesce = rx_eq->enable_aic; +- coalesce->use_adaptive_tx_coalesce = tx_eq->enable_aic; ++ et->use_adaptive_rx_coalesce = eqo->enable_aic; ++ et->use_adaptive_tx_coalesce = eqo->enable_aic; + + return 0; + } + +-/* +- * This routine is used to set interrup coalescing delay ++/* TX attributes are ignored. Only RX attributes are considered ++ * eqd cmd is issued in the worker thread. + */ +-static int +-be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) ++static int be_set_coalesce(struct net_device *netdev, ++ struct ethtool_coalesce *et) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_rx_obj *rxo; +- struct be_eq_obj *rx_eq; +- struct be_eq_obj *tx_eq = &adapter->tx_eq; +- u32 rx_max, rx_min, rx_cur; +- int status = 0, i; +- u32 tx_cur; +- +- if (coalesce->use_adaptive_tx_coalesce == 1) +- return -EINVAL; +- +- for_all_rx_queues(adapter, rxo, i) { +- rx_eq = &rxo->rx_eq; +- +- if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce) +- rx_eq->cur_eqd = 0; +- rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce; +- +- rx_max = coalesce->rx_coalesce_usecs_high; +- rx_min = coalesce->rx_coalesce_usecs_low; +- rx_cur = coalesce->rx_coalesce_usecs; +- +- if (rx_eq->enable_aic) { +- if (rx_max > BE_MAX_EQD) +- rx_max = BE_MAX_EQD; +- if (rx_min > rx_max) +- rx_min = rx_max; +- rx_eq->max_eqd = rx_max; +- rx_eq->min_eqd = rx_min; +- if (rx_eq->cur_eqd > rx_max) +- rx_eq->cur_eqd = rx_max; +- if (rx_eq->cur_eqd < rx_min) +- rx_eq->cur_eqd = rx_min; +- } else { +- if (rx_cur > BE_MAX_EQD) +- rx_cur = BE_MAX_EQD; +- if (rx_eq->cur_eqd != rx_cur) { +- status = be_cmd_modify_eqd(adapter, rx_eq->q.id, +- rx_cur); +- if (!status) +- rx_eq->cur_eqd = rx_cur; +- } +- } +- } +- +- tx_cur = coalesce->tx_coalesce_usecs; +- +- if (tx_cur > BE_MAX_EQD) +- tx_cur = BE_MAX_EQD; +- if (tx_eq->cur_eqd != tx_cur) { +- status = be_cmd_modify_eqd(adapter, tx_eq->q.id, tx_cur); +- if (!status) +- tx_eq->cur_eqd = tx_cur; ++ struct be_eq_obj *eqo; ++ int i; ++ ++ for_all_evt_queues(adapter, eqo, i) { ++ eqo->enable_aic = et->use_adaptive_rx_coalesce; ++ eqo->max_eqd = min(et->rx_coalesce_usecs_high, BE_MAX_EQD); ++ eqo->min_eqd = min(et->rx_coalesce_usecs_low, eqo->max_eqd); ++ eqo->eqd = et->rx_coalesce_usecs; + } + + return 0; +@@ -356,113 +433,204 @@ static int be_get_sset_count(struct net_device *netdev, int stringset) + } + } + ++static u32 be_get_port_type(u32 phy_type, u32 dac_cable_len) ++{ ++ u32 port; ++ ++ switch (phy_type) { ++ case PHY_TYPE_BASET_1GB: ++ case PHY_TYPE_BASEX_1GB: ++ case PHY_TYPE_SGMII: ++ port = PORT_TP; ++ break; ++ case PHY_TYPE_SFP_PLUS_10GB: ++ port = dac_cable_len ? PORT_DA : PORT_FIBRE; ++ break; ++ case PHY_TYPE_XFP_10GB: ++ case PHY_TYPE_SFP_1GB: ++ port = PORT_FIBRE; ++ break; ++ case PHY_TYPE_BASET_10GB: ++ port = PORT_TP; ++ break; ++ default: ++ port = PORT_OTHER; ++ } ++ ++ return port; ++} ++ ++static u32 convert_to_et_setting(u32 if_type, u32 if_speeds) ++{ ++ u32 val = 0; ++ ++ switch (if_type) { ++ case PHY_TYPE_BASET_1GB: ++ case PHY_TYPE_BASEX_1GB: ++ case PHY_TYPE_SGMII: ++ val |= SUPPORTED_TP; ++ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS) ++ val |= SUPPORTED_1000baseT_Full; ++ if (if_speeds & BE_SUPPORTED_SPEED_100MBPS) ++ val |= SUPPORTED_100baseT_Full; ++ if (if_speeds & BE_SUPPORTED_SPEED_10MBPS) ++ val |= SUPPORTED_10baseT_Full; ++ break; ++ case PHY_TYPE_KX4_10GB: ++ val |= SUPPORTED_Backplane; ++ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS) ++ val |= SUPPORTED_1000baseKX_Full; ++ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS) ++ val |= SUPPORTED_10000baseKX4_Full; ++ break; ++ case PHY_TYPE_KR_10GB: ++ val |= SUPPORTED_Backplane | ++ SUPPORTED_10000baseKR_Full; ++ break; ++ case PHY_TYPE_SFP_PLUS_10GB: ++ case PHY_TYPE_XFP_10GB: ++ case PHY_TYPE_SFP_1GB: ++ val |= SUPPORTED_FIBRE; ++ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS) ++ val |= SUPPORTED_10000baseT_Full; ++ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS) ++ val |= SUPPORTED_1000baseT_Full; ++ break; ++ case PHY_TYPE_BASET_10GB: ++ val |= SUPPORTED_TP; ++ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS) ++ val |= SUPPORTED_10000baseT_Full; ++ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS) ++ val |= SUPPORTED_1000baseT_Full; ++ if (if_speeds & BE_SUPPORTED_SPEED_100MBPS) ++ val |= SUPPORTED_100baseT_Full; ++ break; ++ default: ++ val |= SUPPORTED_TP; ++ } ++ ++ return val; ++} ++ ++static int convert_to_et_speed(u32 be_speed) ++{ ++ int et_speed = SPEED_10000; ++ ++ switch (be_speed) { ++ case PHY_LINK_SPEED_10MBPS: ++ et_speed = SPEED_10; ++ break; ++ case PHY_LINK_SPEED_100MBPS: ++ et_speed = SPEED_100; ++ break; ++ case PHY_LINK_SPEED_1GBPS: ++ et_speed = SPEED_1000; ++ break; ++ case PHY_LINK_SPEED_10GBPS: ++ et_speed = SPEED_10000; ++ break; ++ } ++ ++ return et_speed; ++} ++ ++bool be_pause_supported(struct be_adapter *adapter) ++{ ++ return (adapter->phy.interface_type == PHY_TYPE_SFP_PLUS_10GB || ++ adapter->phy.interface_type == PHY_TYPE_XFP_10GB) ? ++ false : true; ++} ++ + static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_phy_info phy_info; +- u8 mac_speed = 0; ++ u8 port_speed = 0; + u16 link_speed = 0; ++ u8 link_status; ++ u32 et_speed = 0; + int status; + +- if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) { +- status = be_cmd_link_status_query(adapter, &mac_speed, +- &link_speed, 0); +- +- /* link_speed is in units of 10 Mbps */ +- if (link_speed) { +- ethtool_cmd_speed_set(ecmd, link_speed*10); ++ if (adapter->phy.link_speed < 0 || !(netdev->flags & IFF_UP)) { ++ if (adapter->phy.forced_port_speed < 0) { ++ status = be_cmd_link_status_query(adapter, &port_speed, ++ &link_speed, &link_status, 0); ++ if (!status) ++ be_link_status_update(adapter, link_status); ++ if (link_speed) ++ et_speed = link_speed * 10; ++ else if (link_status) ++ et_speed = convert_to_et_speed(port_speed); + } else { +- switch (mac_speed) { +- case PHY_LINK_SPEED_10MBPS: +- ethtool_cmd_speed_set(ecmd, SPEED_10); +- break; +- case PHY_LINK_SPEED_100MBPS: +- ethtool_cmd_speed_set(ecmd, SPEED_100); +- break; +- case PHY_LINK_SPEED_1GBPS: +- ethtool_cmd_speed_set(ecmd, SPEED_1000); +- break; +- case PHY_LINK_SPEED_10GBPS: +- ethtool_cmd_speed_set(ecmd, SPEED_10000); +- break; +- case PHY_LINK_SPEED_ZERO: +- ethtool_cmd_speed_set(ecmd, 0); +- break; +- } ++ et_speed = adapter->phy.forced_port_speed; + } + +- status = be_cmd_get_phy_info(adapter, &phy_info); +- if (!status) { +- switch (phy_info.interface_type) { +- case PHY_TYPE_XFP_10GB: +- case PHY_TYPE_SFP_1GB: +- case PHY_TYPE_SFP_PLUS_10GB: +- ecmd->port = PORT_FIBRE; +- break; +- default: +- ecmd->port = PORT_TP; +- break; +- } ++ ethtool_cmd_speed_set(ecmd, et_speed); ++ ++ status = be_cmd_get_phy_info(adapter); ++ if (status) ++ return status; ++ ++ ecmd->supported = ++ convert_to_et_setting(adapter->phy.interface_type, ++ adapter->phy.auto_speeds_supported | ++ adapter->phy.fixed_speeds_supported); ++ ecmd->advertising = ++ convert_to_et_setting(adapter->phy.interface_type, ++ adapter->phy.auto_speeds_supported); + +- switch (phy_info.interface_type) { +- case PHY_TYPE_KR_10GB: +- case PHY_TYPE_KX4_10GB: +- ecmd->autoneg = AUTONEG_ENABLE; ++ ecmd->port = be_get_port_type(adapter->phy.interface_type, ++ adapter->phy.dac_cable_len); ++ ++ if (adapter->phy.auto_speeds_supported) { ++ ecmd->supported |= SUPPORTED_Autoneg; ++ ecmd->autoneg = AUTONEG_ENABLE; ++ ecmd->advertising |= ADVERTISED_Autoneg; ++ } ++ ++ if (be_pause_supported(adapter)) { ++ ecmd->supported |= SUPPORTED_Pause; ++ ecmd->advertising |= ADVERTISED_Pause; ++ } ++ ++ switch (adapter->phy.interface_type) { ++ case PHY_TYPE_KR_10GB: ++ case PHY_TYPE_KX4_10GB: + ecmd->transceiver = XCVR_INTERNAL; +- break; +- default: +- ecmd->autoneg = AUTONEG_DISABLE; +- ecmd->transceiver = XCVR_EXTERNAL; +- break; +- } ++ break; ++ default: ++ ecmd->transceiver = XCVR_EXTERNAL; ++ break; + } + + /* Save for future use */ +- adapter->link_speed = ethtool_cmd_speed(ecmd); +- adapter->port_type = ecmd->port; +- adapter->transceiver = ecmd->transceiver; +- adapter->autoneg = ecmd->autoneg; ++ adapter->phy.link_speed = ethtool_cmd_speed(ecmd); ++ adapter->phy.port_type = ecmd->port; ++ adapter->phy.transceiver = ecmd->transceiver; ++ adapter->phy.autoneg = ecmd->autoneg; ++ adapter->phy.advertising = ecmd->advertising; ++ adapter->phy.supported = ecmd->supported; + } else { +- ethtool_cmd_speed_set(ecmd, adapter->link_speed); +- ecmd->port = adapter->port_type; +- ecmd->transceiver = adapter->transceiver; +- ecmd->autoneg = adapter->autoneg; ++ ethtool_cmd_speed_set(ecmd, adapter->phy.link_speed); ++ ecmd->port = adapter->phy.port_type; ++ ecmd->transceiver = adapter->phy.transceiver; ++ ecmd->autoneg = adapter->phy.autoneg; ++ ecmd->advertising = adapter->phy.advertising; ++ ecmd->supported = adapter->phy.supported; + } + +- ecmd->duplex = DUPLEX_FULL; ++ ecmd->duplex = netif_carrier_ok(netdev) ? DUPLEX_FULL : DUPLEX_UNKNOWN; + ecmd->phy_address = adapter->port_num; +- switch (ecmd->port) { +- case PORT_FIBRE: +- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); +- break; +- case PORT_TP: +- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP); +- break; +- case PORT_AUI: +- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_AUI); +- break; +- } +- +- if (ecmd->autoneg) { +- ecmd->supported |= SUPPORTED_1000baseT_Full; +- ecmd->supported |= SUPPORTED_Autoneg; +- ecmd->advertising |= (ADVERTISED_10000baseT_Full | +- ADVERTISED_1000baseT_Full); +- } + + return 0; + } + +-static void +-be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) ++static void be_get_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ring) + { + struct be_adapter *adapter = netdev_priv(netdev); + +- ring->rx_max_pending = adapter->rx_obj[0].q.len; +- ring->tx_max_pending = adapter->tx_obj[0].q.len; +- +- ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used); +- ring->tx_pending = atomic_read(&adapter->tx_obj[0].q.used); ++ ring->rx_max_pending = ring->rx_pending = adapter->rx_obj[0].q.len; ++ ring->tx_max_pending = ring->tx_pending = adapter->tx_obj[0].q.len; + } + + static void +@@ -471,7 +639,7 @@ be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) + struct be_adapter *adapter = netdev_priv(netdev); + + be_cmd_get_flow_control(adapter, &ecmd->tx_pause, &ecmd->rx_pause); +- ecmd->autoneg = 0; ++ ecmd->autoneg = adapter->phy.fc_autoneg; + } + + static int +@@ -523,26 +691,16 @@ be_set_phys_id(struct net_device *netdev, + return 0; + } + +-static bool +-be_is_wol_supported(struct be_adapter *adapter) +-{ +- if (!be_physfn(adapter)) +- return false; +- else +- return true; +-} + + static void + be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) + { + struct be_adapter *adapter = netdev_priv(netdev); + +- if (be_is_wol_supported(adapter)) +- wol->supported = WAKE_MAGIC; +- +- if (adapter->wol) +- wol->wolopts = WAKE_MAGIC; +- else ++ if (be_is_wol_supported(adapter)) { ++ wol->supported |= WAKE_MAGIC; ++ wol->wolopts |= WAKE_MAGIC; ++ } else + wol->wolopts = 0; + memset(&wol->sopass, 0, sizeof(wol->sopass)); + } +@@ -553,9 +711,14 @@ be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) + struct be_adapter *adapter = netdev_priv(netdev); + + if (wol->wolopts & ~WAKE_MAGIC) +- return -EINVAL; ++ return -EOPNOTSUPP; + +- if ((wol->wolopts & WAKE_MAGIC) && be_is_wol_supported(adapter)) ++ if (!be_is_wol_supported(adapter)) { ++ dev_warn(&adapter->pdev->dev, "WOL not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (wol->wolopts & WAKE_MAGIC) + adapter->wol = true; + else + adapter->wol = false; +@@ -630,13 +793,13 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) + } + } + +- if (be_test_ddr_dma(adapter) != 0) { ++ if (!lancer_chip(adapter) && be_test_ddr_dma(adapter) != 0) { + data[3] = 1; + test->flags |= ETH_TEST_FL_FAILED; + } + + if (be_cmd_link_status_query(adapter, &mac_speed, +- &qos_link_speed, 0) != 0) { ++ &qos_link_speed, NULL, 0) != 0) { + test->flags |= ETH_TEST_FL_FAILED; + data[4] = -1; + } else if (!mac_speed) { +@@ -656,7 +819,17 @@ be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) + static int + be_get_eeprom_len(struct net_device *netdev) + { +- return BE_READ_SEEPROM_LEN; ++ struct be_adapter *adapter = netdev_priv(netdev); ++ if (lancer_chip(adapter)) { ++ if (be_physfn(adapter)) ++ return lancer_cmd_get_file_len(adapter, ++ LANCER_VPD_PF_FILE); ++ else ++ return lancer_cmd_get_file_len(adapter, ++ LANCER_VPD_VF_FILE); ++ } else { ++ return BE_READ_SEEPROM_LEN; ++ } + } + + static int +@@ -671,6 +844,15 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, + if (!eeprom->len) + return -EINVAL; + ++ if (lancer_chip(adapter)) { ++ if (be_physfn(adapter)) ++ return lancer_cmd_read_file(adapter, LANCER_VPD_PF_FILE, ++ eeprom->len, data); ++ else ++ return lancer_cmd_read_file(adapter, LANCER_VPD_VF_FILE, ++ eeprom->len, data); ++ } ++ + eeprom->magic = BE_VENDOR_ID | (adapter->pdev->device<<16); + + memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem)); +diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h +index f2c89e3..0949aa6 100644 +--- a/drivers/net/ethernet/emulex/benet/be_hw.h ++++ b/drivers/net/ethernet/emulex/benet/be_hw.h +@@ -162,22 +162,23 @@ + #define QUERY_FAT 1 + + /* Flashrom related descriptors */ ++#define MAX_FLASH_COMP 32 + #define IMAGE_TYPE_FIRMWARE 160 + #define IMAGE_TYPE_BOOTCODE 224 + #define IMAGE_TYPE_OPTIONROM 32 + + #define NUM_FLASHDIR_ENTRIES 32 + +-#define IMG_TYPE_ISCSI_ACTIVE 0 +-#define IMG_TYPE_REDBOOT 1 +-#define IMG_TYPE_BIOS 2 +-#define IMG_TYPE_PXE_BIOS 3 +-#define IMG_TYPE_FCOE_BIOS 8 +-#define IMG_TYPE_ISCSI_BACKUP 9 +-#define IMG_TYPE_FCOE_FW_ACTIVE 10 +-#define IMG_TYPE_FCOE_FW_BACKUP 11 +-#define IMG_TYPE_NCSI_FW 13 +-#define IMG_TYPE_PHY_FW 99 ++#define OPTYPE_ISCSI_ACTIVE 0 ++#define OPTYPE_REDBOOT 1 ++#define OPTYPE_BIOS 2 ++#define OPTYPE_PXE_BIOS 3 ++#define OPTYPE_FCOE_BIOS 8 ++#define OPTYPE_ISCSI_BACKUP 9 ++#define OPTYPE_FCOE_FW_ACTIVE 10 ++#define OPTYPE_FCOE_FW_BACKUP 11 ++#define OPTYPE_NCSI_FW 13 ++#define OPTYPE_PHY_FW 99 + #define TN_8022 13 + + #define ILLEGAL_IOCTL_REQ 2 +@@ -223,6 +224,24 @@ + #define FLASH_REDBOOT_START_g3 (262144) + #define FLASH_PHY_FW_START_g3 1310720 + ++#define IMAGE_NCSI 16 ++#define IMAGE_OPTION_ROM_PXE 32 ++#define IMAGE_OPTION_ROM_FCoE 33 ++#define IMAGE_OPTION_ROM_ISCSI 34 ++#define IMAGE_FLASHISM_JUMPVECTOR 48 ++#define IMAGE_FLASH_ISM 49 ++#define IMAGE_JUMP_VECTOR 50 ++#define IMAGE_FIRMWARE_iSCSI 160 ++#define IMAGE_FIRMWARE_COMP_iSCSI 161 ++#define IMAGE_FIRMWARE_FCoE 162 ++#define IMAGE_FIRMWARE_COMP_FCoE 163 ++#define IMAGE_FIRMWARE_BACKUP_iSCSI 176 ++#define IMAGE_FIRMWARE_BACKUP_COMP_iSCSI 177 ++#define IMAGE_FIRMWARE_BACKUP_FCoE 178 ++#define IMAGE_FIRMWARE_BACKUP_COMP_FCoE 179 ++#define IMAGE_FIRMWARE_PHY 192 ++#define IMAGE_BOOT_CODE 224 ++ + /************* Rx Packet Type Encoding **************/ + #define BE_UNICAST_PACKET 0 + #define BE_MULTICAST_PACKET 1 +@@ -445,6 +464,7 @@ struct flash_comp { + unsigned long offset; + int optype; + int size; ++ int img_type; + }; + + struct image_hdr { +@@ -481,17 +501,19 @@ struct flash_section_hdr { + u32 format_rev; + u32 cksum; + u32 antidote; +- u32 build_no; +- u8 id_string[64]; +- u32 active_entry_mask; +- u32 valid_entry_mask; +- u32 org_content_mask; +- u32 rsvd0; +- u32 rsvd1; +- u32 rsvd2; +- u32 rsvd3; +- u32 rsvd4; +-}; ++ u32 num_images; ++ u8 id_string[128]; ++ u32 rsvd[4]; ++} __packed; ++ ++struct flash_section_hdr_g2 { ++ u32 format_rev; ++ u32 cksum; ++ u32 antidote; ++ u32 build_num; ++ u8 id_string[128]; ++ u32 rsvd[8]; ++} __packed; + + struct flash_section_entry { + u32 type; +@@ -503,10 +525,16 @@ struct flash_section_entry { + u32 rsvd0; + u32 rsvd1; + u8 ver_data[32]; +-}; ++} __packed; + + struct flash_section_info { + u8 cookie[32]; + struct flash_section_hdr fsec_hdr; + struct flash_section_entry fsec_entry[32]; +-}; ++} __packed; ++ ++struct flash_section_info_g2 { ++ u8 cookie[32]; ++ struct flash_section_hdr_g2 fsec_hdr; ++ struct flash_section_entry fsec_entry[32]; ++} __packed; +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 10c9acf..a3522c5 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -27,13 +27,14 @@ MODULE_DESCRIPTION(DRV_DESC " " DRV_VER); + MODULE_AUTHOR("ServerEngines Corporation"); + MODULE_LICENSE("GPL"); + +-static ushort rx_frag_size = 2048; + static unsigned int num_vfs; +-module_param(rx_frag_size, ushort, S_IRUGO); + module_param(num_vfs, uint, S_IRUGO); +-MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data."); + MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize"); + ++static ushort rx_frag_size = 2048; ++module_param(rx_frag_size, ushort, S_IRUGO); ++MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data."); ++ + static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { + { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, + { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, +@@ -41,6 +42,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { + { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, + { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)}, + { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID4)}, ++ { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID5)}, + { 0 } + }; + MODULE_DEVICE_TABLE(pci, be_dev_ids); +@@ -125,9 +127,11 @@ static inline bool be_is_mc(struct be_adapter *adapter) { + static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q) + { + struct be_dma_mem *mem = &q->dma_mem; +- if (mem->va) ++ if (mem->va) { + dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va, + mem->dma); ++ mem->va = NULL; ++ } + } + + static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q, +@@ -142,7 +146,7 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q, + mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma, + GFP_KERNEL); + if (!mem->va) +- return -1; ++ return -ENOMEM; + memset(mem->va, 0, mem->size); + return 0; + } +@@ -231,19 +235,20 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) + struct sockaddr *addr = p; + int status = 0; + u8 current_mac[ETH_ALEN]; +- u32 pmac_id = adapter->pmac_id; ++ u32 pmac_id = adapter->pmac_id[0]; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + status = be_cmd_mac_addr_query(adapter, current_mac, +- MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle); ++ MAC_ADDRESS_TYPE_NETWORK, false, ++ adapter->if_handle, 0); + if (status) + goto err; + + if (memcmp(addr->sa_data, current_mac, ETH_ALEN)) { + status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data, +- adapter->if_handle, &adapter->pmac_id, 0); ++ adapter->if_handle, &adapter->pmac_id[0], 0); + if (status) + goto err; + +@@ -283,7 +288,9 @@ static void populate_be2_stats(struct be_adapter *adapter) + drvs->rx_input_fifo_overflow_drop = port_stats->rx_input_fifo_overflow; + drvs->rx_dropped_header_too_small = + port_stats->rx_dropped_header_too_small; +- drvs->rx_address_match_errors = port_stats->rx_address_match_errors; ++ drvs->rx_address_mismatch_drops = ++ port_stats->rx_address_mismatch_drops + ++ port_stats->rx_vlan_mismatch_drops; + drvs->rx_alignment_symbol_errors = + port_stats->rx_alignment_symbol_errors; + +@@ -295,9 +302,7 @@ static void populate_be2_stats(struct be_adapter *adapter) + else + drvs->jabber_events = rxf_stats->port0_jabber_events; + drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; +- drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb; + drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; +- drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring; + drvs->forwarded_packets = rxf_stats->forwarded_packets; + drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu; + drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr; +@@ -315,6 +320,8 @@ static void populate_be3_stats(struct be_adapter *adapter) + struct be_drv_stats *drvs = &adapter->drv_stats; + + be_dws_le_to_cpu(hw_stats, sizeof(*hw_stats)); ++ drvs->pmem_fifo_overflow_drop = port_stats->pmem_fifo_overflow_drop; ++ drvs->rx_priority_pause_frames = port_stats->rx_priority_pause_frames; + drvs->rx_pause_frames = port_stats->rx_pause_frames; + drvs->rx_crc_errors = port_stats->rx_crc_errors; + drvs->rx_control_frames = port_stats->rx_control_frames; +@@ -332,7 +339,7 @@ static void populate_be3_stats(struct be_adapter *adapter) + port_stats->rx_dropped_header_too_small; + drvs->rx_input_fifo_overflow_drop = + port_stats->rx_input_fifo_overflow_drop; +- drvs->rx_address_match_errors = port_stats->rx_address_match_errors; ++ drvs->rx_address_mismatch_drops = port_stats->rx_address_mismatch_drops; + drvs->rx_alignment_symbol_errors = + port_stats->rx_alignment_symbol_errors; + drvs->rxpp_fifo_overflow_drop = port_stats->rxpp_fifo_overflow_drop; +@@ -340,9 +347,7 @@ static void populate_be3_stats(struct be_adapter *adapter) + drvs->tx_controlframes = port_stats->tx_controlframes; + drvs->jabber_events = port_stats->jabber_events; + drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; +- drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb; + drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; +- drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring; + drvs->forwarded_packets = rxf_stats->forwarded_packets; + drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu; + drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr; +@@ -375,13 +380,14 @@ static void populate_lancer_stats(struct be_adapter *adapter) + drvs->rx_dropped_header_too_small = + pport_stats->rx_dropped_header_too_small; + drvs->rx_input_fifo_overflow_drop = pport_stats->rx_fifo_overflow; +- drvs->rx_address_match_errors = pport_stats->rx_address_match_errors; ++ drvs->rx_address_mismatch_drops = ++ pport_stats->rx_address_mismatch_drops + ++ pport_stats->rx_vlan_mismatch_drops; + drvs->rx_alignment_symbol_errors = pport_stats->rx_symbol_errors_lo; + drvs->rxpp_fifo_overflow_drop = pport_stats->rx_fifo_overflow; + drvs->tx_pauseframes = pport_stats->tx_pause_frames_lo; + drvs->tx_controlframes = pport_stats->tx_control_frames_lo; + drvs->jabber_events = pport_stats->rx_jabbers; +- drvs->rx_drops_invalid_ring = pport_stats->rx_drops_invalid_queue; + drvs->forwarded_packets = pport_stats->num_forwards_lo; + drvs->rx_drops_mtu = pport_stats->rx_drops_mtu_lo; + drvs->rx_drops_too_many_frags = +@@ -415,6 +421,9 @@ void be_parse_stats(struct be_adapter *adapter) + populate_be2_stats(adapter); + } + ++ if (lancer_chip(adapter)) ++ goto done; ++ + /* as erx_v1 is longer than v0, ok to use v1 defn for v0 access */ + for_all_rx_queues(adapter, rxo, i) { + /* below erx HW counter can actually wrap around after +@@ -423,6 +432,8 @@ void be_parse_stats(struct be_adapter *adapter) + accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags, + (u16)erx->rx_drops_no_fragments[rxo->q.id]); + } ++done: ++ return; + } + + static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev, +@@ -491,19 +502,19 @@ static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev, + return stats; + } + +-void be_link_status_update(struct be_adapter *adapter, u32 link_status) ++void be_link_status_update(struct be_adapter *adapter, u8 link_status) + { + struct net_device *netdev = adapter->netdev; + +- /* when link status changes, link speed must be re-queried from card */ +- adapter->link_speed = -1; +- if ((link_status & LINK_STATUS_MASK) == LINK_UP) { +- netif_carrier_on(netdev); +- dev_info(&adapter->pdev->dev, "%s: Link up\n", netdev->name); +- } else { ++ if (!(adapter->flags & BE_FLAGS_LINK_STATUS_INIT)) { + netif_carrier_off(netdev); +- dev_info(&adapter->pdev->dev, "%s: Link down\n", netdev->name); ++ adapter->flags |= BE_FLAGS_LINK_STATUS_INIT; + } ++ ++ if ((link_status & LINK_STATUS_MASK) == LINK_UP) ++ netif_carrier_on(netdev); ++ else ++ netif_carrier_off(netdev); + } + + static void be_tx_stats_update(struct be_tx_obj *txo, +@@ -547,13 +558,34 @@ static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len) + wrb->frag_pa_hi = upper_32_bits(addr); + wrb->frag_pa_lo = addr & 0xFFFFFFFF; + wrb->frag_len = len & ETH_WRB_FRAG_LEN_MASK; ++ wrb->rsvd0 = 0; ++} ++ ++static inline u16 be_get_tx_vlan_tag(struct be_adapter *adapter, ++ struct sk_buff *skb) ++{ ++ u8 vlan_prio; ++ u16 vlan_tag; ++ ++ vlan_tag = vlan_tx_tag_get(skb); ++ vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; ++ /* If vlan priority provided by OS is NOT in available bmap */ ++ if (!(adapter->vlan_prio_bmap & (1 << vlan_prio))) ++ vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) | ++ adapter->recommended_prio; ++ ++ return vlan_tag; ++} ++ ++static int be_vlan_tag_chk(struct be_adapter *adapter, struct sk_buff *skb) ++{ ++ return vlan_tx_tag_present(skb) || adapter->pvid; + } + + static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, + struct sk_buff *skb, u32 wrb_cnt, u32 len) + { +- u8 vlan_prio = 0; +- u16 vlan_tag = 0; ++ u16 vlan_tag; + + memset(hdr, 0, sizeof(*hdr)); + +@@ -584,12 +616,7 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, + + if (vlan_tx_tag_present(skb)) { + AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1); +- vlan_tag = vlan_tx_tag_get(skb); +- vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; +- /* If vlan priority provided by OS is NOT in available bmap */ +- if (!(adapter->vlan_prio_bmap & (1 << vlan_prio))) +- vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) | +- adapter->recommended_prio; ++ vlan_tag = be_get_tx_vlan_tag(adapter, skb); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, hdr, vlan_tag); + } + +@@ -682,16 +709,59 @@ dma_err: + return 0; + } + ++static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter, ++ struct sk_buff *skb) ++{ ++ u16 vlan_tag = 0; ++ ++ skb = skb_share_check(skb, GFP_ATOMIC); ++ if (unlikely(!skb)) ++ return skb; ++ ++ if (vlan_tx_tag_present(skb)) { ++ vlan_tag = be_get_tx_vlan_tag(adapter, skb); ++ __vlan_put_tag(skb, vlan_tag); ++ skb->vlan_tci = 0; ++ } ++ ++ return skb; ++} ++ ++ + static netdev_tx_t be_xmit(struct sk_buff *skb, + struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); + struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)]; + struct be_queue_info *txq = &txo->q; ++ struct iphdr *ip = NULL; + u32 wrb_cnt = 0, copied = 0; +- u32 start = txq->head; ++ u32 start = txq->head, eth_hdr_len; + bool dummy_wrb, stopped = false; + ++ eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ? ++ VLAN_ETH_HLEN : ETH_HLEN; ++ ++ /* HW has a bug which considers padding bytes as legal ++ * and modifies the IPv4 hdr's 'tot_len' field ++ */ ++ if (skb->len <= 60 && be_vlan_tag_chk(adapter, skb) && ++ is_ipv4_pkt(skb)) { ++ ip = (struct iphdr *)ip_hdr(skb); ++ pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len)); ++ } ++ ++ /* HW has a bug wherein it will calculate CSUM for VLAN ++ * pkts even though it is disabled. ++ * Manually insert VLAN in pkt. ++ */ ++ if (skb->ip_summed != CHECKSUM_PARTIAL && ++ be_vlan_tag_chk(adapter, skb)) { ++ skb = be_insert_vlan_in_pkt(adapter, skb); ++ if (unlikely(!skb)) ++ goto tx_drop; ++ } ++ + wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); + + copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb); +@@ -720,6 +790,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, + txq->head = start; + dev_kfree_skb_any(skb); + } ++tx_drop: + return NETDEV_TX_OK; + } + +@@ -747,69 +818,87 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) + */ + static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) + { ++ struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf_num]; + u16 vtag[BE_NUM_VLANS_SUPPORTED]; + u16 ntags = 0, i; + int status = 0; +- u32 if_handle; + + if (vf) { +- if_handle = adapter->vf_cfg[vf_num].vf_if_handle; +- vtag[0] = cpu_to_le16(adapter->vf_cfg[vf_num].vf_vlan_tag); +- status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0); ++ vtag[0] = cpu_to_le16(vf_cfg->vlan_tag); ++ status = be_cmd_vlan_config(adapter, vf_cfg->if_handle, vtag, ++ 1, 1, 0); + } + + /* No need to further configure vids if in promiscuous mode */ + if (adapter->promiscuous) + return 0; + +- if (adapter->vlans_added <= adapter->max_vlans) { +- /* Construct VLAN Table to give to HW */ +- for (i = 0; i < VLAN_N_VID; i++) { +- if (adapter->vlan_tag[i]) { +- vtag[ntags] = cpu_to_le16(i); +- ntags++; +- } +- } +- status = be_cmd_vlan_config(adapter, adapter->if_handle, +- vtag, ntags, 1, 0); +- } else { +- status = be_cmd_vlan_config(adapter, adapter->if_handle, +- NULL, 0, 1, 1); ++ if (adapter->vlans_added > adapter->max_vlans) ++ goto set_vlan_promisc; ++ ++ /* Construct VLAN Table to give to HW */ ++ for (i = 0; i < VLAN_N_VID; i++) ++ if (adapter->vlan_tag[i]) ++ vtag[ntags++] = cpu_to_le16(i); ++ ++ status = be_cmd_vlan_config(adapter, adapter->if_handle, ++ vtag, ntags, 1, 0); ++ ++ /* Set to VLAN promisc mode as setting VLAN filter failed */ ++ if (status) { ++ dev_info(&adapter->pdev->dev, "Exhausted VLAN HW filters.\n"); ++ dev_info(&adapter->pdev->dev, "Disabling HW VLAN filtering.\n"); ++ goto set_vlan_promisc; + } + + return status; ++ ++set_vlan_promisc: ++ status = be_cmd_vlan_config(adapter, adapter->if_handle, ++ NULL, 0, 1, 1); ++ return status; + } + + static void be_vlan_add_vid(struct net_device *netdev, u16 vid) + { + struct be_adapter *adapter = netdev_priv(netdev); ++ int status = 0; + +- adapter->vlans_added++; + if (!be_physfn(adapter)) + return; + + adapter->vlan_tag[vid] = 1; + if (adapter->vlans_added <= (adapter->max_vlans + 1)) +- be_vid_config(adapter, false, 0); ++ status = be_vid_config(adapter, false, 0); ++ ++ if (!status) ++ adapter->vlans_added++; ++ else ++ adapter->vlan_tag[vid] = 0; + } + + static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) + { + struct be_adapter *adapter = netdev_priv(netdev); +- +- adapter->vlans_added--; ++ int status = 0; + + if (!be_physfn(adapter)) + return; + + adapter->vlan_tag[vid] = 0; + if (adapter->vlans_added <= adapter->max_vlans) +- be_vid_config(adapter, false, 0); ++ status = be_vid_config(adapter, false, 0); ++ ++ if (!status) ++ adapter->vlans_added--; ++ else ++ adapter->vlan_tag[vid] = 1; + } + + static void be_set_rx_mode(struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); ++ int status; + + if (netdev->flags & IFF_PROMISC) { + be_cmd_rx_filter(adapter, IFF_PROMISC, ON); +@@ -833,7 +922,37 @@ static void be_set_rx_mode(struct net_device *netdev) + goto done; + } + +- be_cmd_rx_filter(adapter, IFF_MULTICAST, ON); ++ if (netdev_uc_count(netdev) != adapter->uc_macs) { ++ struct netdev_hw_addr *ha; ++ int i = 1; /* First slot is claimed by the Primary MAC */ ++ ++ for (; adapter->uc_macs > 0; adapter->uc_macs--, i++) { ++ be_cmd_pmac_del(adapter, adapter->if_handle, ++ adapter->pmac_id[i], 0); ++ } ++ ++ if (netdev_uc_count(netdev) > adapter->max_pmac_cnt) { ++ be_cmd_rx_filter(adapter, IFF_PROMISC, ON); ++ adapter->promiscuous = true; ++ goto done; ++ } ++ ++ netdev_for_each_uc_addr(ha, adapter->netdev) { ++ adapter->uc_macs++; /* First slot is for Primary MAC */ ++ be_cmd_pmac_add(adapter, (u8 *)ha->addr, ++ adapter->if_handle, ++ &adapter->pmac_id[adapter->uc_macs], 0); ++ } ++ } ++ ++ status = be_cmd_rx_filter(adapter, IFF_MULTICAST, ON); ++ ++ /* Set to MCAST promisc mode if setting MULTICAST address fails */ ++ if (status) { ++ dev_info(&adapter->pdev->dev, "Exhausted multicast HW filters.\n"); ++ dev_info(&adapter->pdev->dev, "Disabling HW multicast filtering.\n"); ++ be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); ++ } + done: + return; + } +@@ -841,28 +960,30 @@ done: + static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) + { + struct be_adapter *adapter = netdev_priv(netdev); ++ struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; + int status; + +- if (!adapter->sriov_enabled) ++ if (!sriov_enabled(adapter)) + return -EPERM; + +- if (!is_valid_ether_addr(mac) || (vf >= num_vfs)) ++ if (!is_valid_ether_addr(mac) || vf >= adapter->num_vfs) + return -EINVAL; + +- if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID) +- status = be_cmd_pmac_del(adapter, +- adapter->vf_cfg[vf].vf_if_handle, +- adapter->vf_cfg[vf].vf_pmac_id, vf + 1); ++ if (lancer_chip(adapter)) { ++ status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1); ++ } else { ++ status = be_cmd_pmac_del(adapter, vf_cfg->if_handle, ++ vf_cfg->pmac_id, vf + 1); + +- status = be_cmd_pmac_add(adapter, mac, +- adapter->vf_cfg[vf].vf_if_handle, +- &adapter->vf_cfg[vf].vf_pmac_id, vf + 1); ++ status = be_cmd_pmac_add(adapter, mac, vf_cfg->if_handle, ++ &vf_cfg->pmac_id, vf + 1); ++ } + + if (status) + dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n", + mac, vf); + else +- memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN); ++ memcpy(vf_cfg->mac_addr, mac, ETH_ALEN); + + return status; + } +@@ -871,18 +992,19 @@ static int be_get_vf_config(struct net_device *netdev, int vf, + struct ifla_vf_info *vi) + { + struct be_adapter *adapter = netdev_priv(netdev); ++ struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; + +- if (!adapter->sriov_enabled) ++ if (!sriov_enabled(adapter)) + return -EPERM; + +- if (vf >= num_vfs) ++ if (vf >= adapter->num_vfs) + return -EINVAL; + + vi->vf = vf; +- vi->tx_rate = adapter->vf_cfg[vf].vf_tx_rate; +- vi->vlan = adapter->vf_cfg[vf].vf_vlan_tag; ++ vi->tx_rate = vf_cfg->tx_rate; ++ vi->vlan = vf_cfg->vlan_tag; + vi->qos = 0; +- memcpy(&vi->mac, adapter->vf_cfg[vf].vf_mac_addr, ETH_ALEN); ++ memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN); + + return 0; + } +@@ -893,21 +1015,28 @@ static int be_set_vf_vlan(struct net_device *netdev, + struct be_adapter *adapter = netdev_priv(netdev); + int status = 0; + +- if (!adapter->sriov_enabled) ++ if (!sriov_enabled(adapter)) + return -EPERM; + +- if ((vf >= num_vfs) || (vlan > 4095)) ++ if (vf >= adapter->num_vfs || vlan > 4095) + return -EINVAL; + + if (vlan) { +- adapter->vf_cfg[vf].vf_vlan_tag = vlan; +- adapter->vlans_added++; ++ if (adapter->vf_cfg[vf].vlan_tag != vlan) { ++ /* If this is new value, program it. Else skip. */ ++ adapter->vf_cfg[vf].vlan_tag = vlan; ++ ++ status = be_cmd_set_hsw_config(adapter, vlan, ++ vf + 1, adapter->vf_cfg[vf].if_handle); ++ } + } else { +- adapter->vf_cfg[vf].vf_vlan_tag = 0; +- adapter->vlans_added--; ++ /* Reset Transparent Vlan Tagging. */ ++ adapter->vf_cfg[vf].vlan_tag = 0; ++ vlan = adapter->vf_cfg[vf].def_vid; ++ status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, ++ adapter->vf_cfg[vf].if_handle); + } + +- status = be_vid_config(adapter, true, vf); + + if (status) + dev_info(&adapter->pdev->dev, +@@ -921,36 +1050,72 @@ static int be_set_vf_tx_rate(struct net_device *netdev, + struct be_adapter *adapter = netdev_priv(netdev); + int status = 0; + +- if (!adapter->sriov_enabled) ++ if (!sriov_enabled(adapter)) + return -EPERM; + +- if ((vf >= num_vfs) || (rate < 0)) ++ if (vf >= adapter->num_vfs) + return -EINVAL; + +- if (rate > 10000) +- rate = 10000; ++ if (rate < 100 || rate > 10000) { ++ dev_err(&adapter->pdev->dev, ++ "tx rate must be between 100 and 10000 Mbps\n"); ++ return -EINVAL; ++ } + +- adapter->vf_cfg[vf].vf_tx_rate = rate; + status = be_cmd_set_qos(adapter, rate / 10, vf + 1); + + if (status) +- dev_info(&adapter->pdev->dev, ++ dev_err(&adapter->pdev->dev, + "tx rate %d on VF %d failed\n", rate, vf); ++ else ++ adapter->vf_cfg[vf].tx_rate = rate; + return status; + } + +-static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo) ++static int be_find_vfs(struct be_adapter *adapter, int vf_state) + { +- struct be_eq_obj *rx_eq = &rxo->rx_eq; +- struct be_rx_stats *stats = rx_stats(rxo); ++ struct pci_dev *dev, *pdev = adapter->pdev; ++ int vfs = 0, assigned_vfs = 0, pos, vf_fn; ++ u16 offset, stride; ++ ++ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); ++ if (!pos) ++ return 0; ++ pci_read_config_word(pdev, pos + PCI_SRIOV_VF_OFFSET, &offset); ++ pci_read_config_word(pdev, pos + PCI_SRIOV_VF_STRIDE, &stride); ++ ++ dev = pci_get_device(pdev->vendor, PCI_ANY_ID, NULL); ++ while (dev) { ++ vf_fn = (pdev->devfn + offset + stride * vfs) & 0xFFFF; ++ if (dev->is_virtfn && dev->devfn == vf_fn && ++ dev->bus->number == pdev->bus->number) { ++ vfs++; ++ if (dev->dev_flags & PCI_DEV_FLAGS_ASSIGNED) ++ assigned_vfs++; ++ } ++ dev = pci_get_device(pdev->vendor, PCI_ANY_ID, dev); ++ } ++ return (vf_state == ASSIGNED) ? assigned_vfs : vfs; ++} ++ ++static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo) ++{ ++ struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]); + ulong now = jiffies; + ulong delta = now - stats->rx_jiffies; + u64 pkts; + unsigned int start, eqd; + +- if (!rx_eq->enable_aic) ++ if (!eqo->enable_aic) { ++ eqd = eqo->eqd; ++ goto modify_eqd; ++ } ++ ++ if (eqo->idx >= adapter->num_rx_qs) + return; + ++ stats = rx_stats(&adapter->rx_obj[eqo->idx]); ++ + /* Wrapped around */ + if (time_before(now, stats->rx_jiffies)) { + stats->rx_jiffies = now; +@@ -969,17 +1134,16 @@ static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo) + stats->rx_pps = (unsigned long)(pkts - stats->rx_pkts_prev) / (delta / HZ); + stats->rx_pkts_prev = pkts; + stats->rx_jiffies = now; +- eqd = stats->rx_pps / 110000; +- eqd = eqd << 3; +- if (eqd > rx_eq->max_eqd) +- eqd = rx_eq->max_eqd; +- if (eqd < rx_eq->min_eqd) +- eqd = rx_eq->min_eqd; ++ eqd = (stats->rx_pps / 110000) << 3; ++ eqd = min(eqd, eqo->max_eqd); ++ eqd = max(eqd, eqo->min_eqd); + if (eqd < 10) + eqd = 0; +- if (eqd != rx_eq->cur_eqd) { +- be_cmd_modify_eqd(adapter, rx_eq->q.id, eqd); +- rx_eq->cur_eqd = eqd; ++ ++modify_eqd: ++ if (eqd != eqo->cur_eqd) { ++ be_cmd_modify_eqd(adapter, eqo->q.id, eqd); ++ eqo->cur_eqd = eqd; + } + } + +@@ -1007,11 +1171,10 @@ static inline bool csum_passed(struct be_rx_compl_info *rxcp) + (rxcp->ip_csum || rxcp->ipv6); + } + +-static struct be_rx_page_info * +-get_rx_page_info(struct be_adapter *adapter, +- struct be_rx_obj *rxo, +- u16 frag_idx) ++static struct be_rx_page_info *get_rx_page_info(struct be_rx_obj *rxo, ++ u16 frag_idx) + { ++ struct be_adapter *adapter = rxo->adapter; + struct be_rx_page_info *rx_page_info; + struct be_queue_info *rxq = &rxo->q; + +@@ -1030,16 +1193,15 @@ get_rx_page_info(struct be_adapter *adapter, + } + + /* Throwaway the data in the Rx completion */ +-static void be_rx_compl_discard(struct be_adapter *adapter, +- struct be_rx_obj *rxo, +- struct be_rx_compl_info *rxcp) ++static void be_rx_compl_discard(struct be_rx_obj *rxo, ++ struct be_rx_compl_info *rxcp) + { + struct be_queue_info *rxq = &rxo->q; + struct be_rx_page_info *page_info; + u16 i, num_rcvd = rxcp->num_rcvd; + + for (i = 0; i < num_rcvd; i++) { +- page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx); ++ page_info = get_rx_page_info(rxo, rxcp->rxq_idx); + put_page(page_info->page); + memset(page_info, 0, sizeof(*page_info)); + index_inc(&rxcp->rxq_idx, rxq->len); +@@ -1050,8 +1212,8 @@ static void be_rx_compl_discard(struct be_adapter *adapter, + * skb_fill_rx_data forms a complete skb for an ether frame + * indicated by rxcp. + */ +-static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo, +- struct sk_buff *skb, struct be_rx_compl_info *rxcp) ++static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb, ++ struct be_rx_compl_info *rxcp) + { + struct be_queue_info *rxq = &rxo->q; + struct be_rx_page_info *page_info; +@@ -1059,23 +1221,23 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo, + u16 hdr_len, curr_frag_len, remaining; + u8 *start; + +- page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx); ++ page_info = get_rx_page_info(rxo, rxcp->rxq_idx); + start = page_address(page_info->page) + page_info->page_offset; + prefetch(start); + + /* Copy data in the first descriptor of this completion */ + curr_frag_len = min(rxcp->pkt_size, rx_frag_size); + +- /* Copy the header portion into skb_data */ +- hdr_len = min(BE_HDR_LEN, curr_frag_len); +- memcpy(skb->data, start, hdr_len); + skb->len = curr_frag_len; + if (curr_frag_len <= BE_HDR_LEN) { /* tiny packet */ ++ memcpy(skb->data, start, curr_frag_len); + /* Complete packet has now been moved to data */ + put_page(page_info->page); + skb->data_len = 0; + skb->tail += curr_frag_len; + } else { ++ hdr_len = ETH_HLEN; ++ memcpy(skb->data, start, hdr_len); + skb_shinfo(skb)->nr_frags = 1; + skb_frag_set_page(skb, 0, page_info->page); + skb_shinfo(skb)->frags[0].page_offset = +@@ -1096,7 +1258,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo, + index_inc(&rxcp->rxq_idx, rxq->len); + remaining = rxcp->pkt_size - curr_frag_len; + for (i = 1, j = 0; i < rxcp->num_rcvd; i++) { +- page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx); ++ page_info = get_rx_page_info(rxo, rxcp->rxq_idx); + curr_frag_len = min(remaining, rx_frag_size); + + /* Coalesce all frags from the same physical page in one slot */ +@@ -1124,21 +1286,21 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo, + } + + /* Process the RX completion indicated by rxcp when GRO is disabled */ +-static void be_rx_compl_process(struct be_adapter *adapter, +- struct be_rx_obj *rxo, +- struct be_rx_compl_info *rxcp) ++static void be_rx_compl_process(struct be_rx_obj *rxo, ++ struct be_rx_compl_info *rxcp) + { ++ struct be_adapter *adapter = rxo->adapter; + struct net_device *netdev = adapter->netdev; + struct sk_buff *skb; + +- skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN); ++ skb = netdev_alloc_skb_ip_align(netdev, BE_RX_SKB_ALLOC_SIZE); + if (unlikely(!skb)) { + rx_stats(rxo)->rx_drops_no_skbs++; +- be_rx_compl_discard(adapter, rxo, rxcp); ++ be_rx_compl_discard(rxo, rxcp); + return; + } + +- skb_fill_rx_data(adapter, rxo, skb, rxcp); ++ skb_fill_rx_data(rxo, skb, rxcp); + + if (likely((netdev->features & NETIF_F_RXCSUM) && csum_passed(rxcp))) + skb->ip_summed = CHECKSUM_UNNECESSARY; +@@ -1146,7 +1308,8 @@ static void be_rx_compl_process(struct be_adapter *adapter, + skb_checksum_none_assert(skb); + + skb->protocol = eth_type_trans(skb, netdev); +- if (adapter->netdev->features & NETIF_F_RXHASH) ++ skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]); ++ if (netdev->features & NETIF_F_RXHASH) + skb->rxhash = rxcp->rss_hash; + + +@@ -1157,26 +1320,25 @@ static void be_rx_compl_process(struct be_adapter *adapter, + } + + /* Process the RX completion indicated by rxcp when GRO is enabled */ +-static void be_rx_compl_process_gro(struct be_adapter *adapter, +- struct be_rx_obj *rxo, +- struct be_rx_compl_info *rxcp) ++void be_rx_compl_process_gro(struct be_rx_obj *rxo, struct napi_struct *napi, ++ struct be_rx_compl_info *rxcp) + { ++ struct be_adapter *adapter = rxo->adapter; + struct be_rx_page_info *page_info; + struct sk_buff *skb = NULL; + struct be_queue_info *rxq = &rxo->q; +- struct be_eq_obj *eq_obj = &rxo->rx_eq; + u16 remaining, curr_frag_len; + u16 i, j; + +- skb = napi_get_frags(&eq_obj->napi); ++ skb = napi_get_frags(napi); + if (!skb) { +- be_rx_compl_discard(adapter, rxo, rxcp); ++ be_rx_compl_discard(rxo, rxcp); + return; + } + + remaining = rxcp->pkt_size; + for (i = 0, j = -1; i < rxcp->num_rcvd; i++) { +- page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx); ++ page_info = get_rx_page_info(rxo, rxcp->rxq_idx); + + curr_frag_len = min(remaining, rx_frag_size); + +@@ -1203,18 +1365,18 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, + skb->len = rxcp->pkt_size; + skb->data_len = rxcp->pkt_size; + skb->ip_summed = CHECKSUM_UNNECESSARY; ++ skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]); + if (adapter->netdev->features & NETIF_F_RXHASH) + skb->rxhash = rxcp->rss_hash; + + if (rxcp->vlanf) + __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); + +- napi_gro_frags(&eq_obj->napi); ++ napi_gro_frags(napi); + } + +-static void be_parse_rx_compl_v1(struct be_adapter *adapter, +- struct be_eth_rx_compl *compl, +- struct be_rx_compl_info *rxcp) ++static void be_parse_rx_compl_v1(struct be_eth_rx_compl *compl, ++ struct be_rx_compl_info *rxcp) + { + rxcp->pkt_size = + AMAP_GET_BITS(struct amap_eth_rx_compl_v1, pktsize, compl); +@@ -1235,7 +1397,7 @@ static void be_parse_rx_compl_v1(struct be_adapter *adapter, + rxcp->pkt_type = + AMAP_GET_BITS(struct amap_eth_rx_compl_v1, cast_enc, compl); + rxcp->rss_hash = +- AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, rxcp); ++ AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, compl); + if (rxcp->vlanf) { + rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm, + compl); +@@ -1245,9 +1407,8 @@ static void be_parse_rx_compl_v1(struct be_adapter *adapter, + rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, port, compl); + } + +-static void be_parse_rx_compl_v0(struct be_adapter *adapter, +- struct be_eth_rx_compl *compl, +- struct be_rx_compl_info *rxcp) ++static void be_parse_rx_compl_v0(struct be_eth_rx_compl *compl, ++ struct be_rx_compl_info *rxcp) + { + rxcp->pkt_size = + AMAP_GET_BITS(struct amap_eth_rx_compl_v0, pktsize, compl); +@@ -1268,7 +1429,7 @@ static void be_parse_rx_compl_v0(struct be_adapter *adapter, + rxcp->pkt_type = + AMAP_GET_BITS(struct amap_eth_rx_compl_v0, cast_enc, compl); + rxcp->rss_hash = +- AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, rxcp); ++ AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, compl); + if (rxcp->vlanf) { + rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm, + compl); +@@ -1293,9 +1454,9 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo) + be_dws_le_to_cpu(compl, sizeof(*compl)); + + if (adapter->be3_native) +- be_parse_rx_compl_v1(adapter, compl, rxcp); ++ be_parse_rx_compl_v1(compl, rxcp); + else +- be_parse_rx_compl_v0(adapter, compl, rxcp); ++ be_parse_rx_compl_v0(compl, rxcp); + + if (rxcp->vlanf) { + /* vlanf could be wrongly set in some cards. +@@ -1334,7 +1495,6 @@ static inline struct page *be_alloc_pages(u32 size, gfp_t gfp) + static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp) + { + struct be_adapter *adapter = rxo->adapter; +- struct be_rx_page_info *page_info_tbl = rxo->page_info_tbl; + struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL; + struct be_queue_info *rxq = &rxo->q; + struct page *pagep = NULL; +@@ -1376,7 +1536,7 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp) + + prev_page_info = page_info; + queue_head_inc(rxq); +- page_info = &page_info_tbl[rxq->head]; ++ page_info = &rxo->page_info_tbl[rxq->head]; + } + if (pagep) + prev_page_info->last_page_user = true; +@@ -1438,62 +1598,53 @@ static u16 be_tx_compl_process(struct be_adapter *adapter, + return num_wrbs; + } + +-static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj) ++/* Return the number of events in the event queue */ ++static inline int events_get(struct be_eq_obj *eqo) + { +- struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q); ++ struct be_eq_entry *eqe; ++ int num = 0; + +- if (!eqe->evt) +- return NULL; ++ do { ++ eqe = queue_tail_node(&eqo->q); ++ if (eqe->evt == 0) ++ break; + +- rmb(); +- eqe->evt = le32_to_cpu(eqe->evt); +- queue_tail_inc(&eq_obj->q); +- return eqe; ++ rmb(); ++ eqe->evt = 0; ++ num++; ++ queue_tail_inc(&eqo->q); ++ } while (true); ++ ++ return num; + } + +-static int event_handle(struct be_adapter *adapter, +- struct be_eq_obj *eq_obj, +- bool rearm) ++static int event_handle(struct be_eq_obj *eqo) + { +- struct be_eq_entry *eqe; +- u16 num = 0; +- +- while ((eqe = event_get(eq_obj)) != NULL) { +- eqe->evt = 0; +- num++; +- } ++ bool rearm = false; ++ int num = events_get(eqo); + +- /* Deal with any spurious interrupts that come +- * without events +- */ ++ /* Deal with any spurious interrupts that come without events */ + if (!num) + rearm = true; + +- be_eq_notify(adapter, eq_obj->q.id, rearm, true, num); ++ if (num || msix_enabled(eqo->adapter)) ++ be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num); ++ + if (num) +- napi_schedule(&eq_obj->napi); ++ napi_schedule(&eqo->napi); + + return num; + } + +-/* Just read and notify events without processing them. +- * Used at the time of destroying event queues */ +-static void be_eq_clean(struct be_adapter *adapter, +- struct be_eq_obj *eq_obj) ++/* Leaves the EQ is disarmed state */ ++static void be_eq_clean(struct be_eq_obj *eqo) + { +- struct be_eq_entry *eqe; +- u16 num = 0; +- +- while ((eqe = event_get(eq_obj)) != NULL) { +- eqe->evt = 0; +- num++; +- } ++ int num = events_get(eqo); + +- if (num) +- be_eq_notify(adapter, eq_obj->q.id, false, true, num); ++ be_eq_notify(eqo->adapter, eqo->q.id, false, true, num); + } + +-static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo) ++static void be_rx_cq_clean(struct be_rx_obj *rxo) + { + struct be_rx_page_info *page_info; + struct be_queue_info *rxq = &rxo->q; +@@ -1503,14 +1654,14 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo) + + /* First cleanup pending rx completions */ + while ((rxcp = be_rx_compl_get(rxo)) != NULL) { +- be_rx_compl_discard(adapter, rxo, rxcp); +- be_cq_notify(adapter, rx_cq->id, false, 1); ++ be_rx_compl_discard(rxo, rxcp); ++ be_cq_notify(rxo->adapter, rx_cq->id, false, 1); + } + + /* Then free posted rx buffer that were not used */ + tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len; + for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) { +- page_info = get_rx_page_info(adapter, rxo, tail); ++ page_info = get_rx_page_info(rxo, tail); + put_page(page_info->page); + memset(page_info, 0, sizeof(*page_info)); + } +@@ -1518,52 +1669,104 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo) + rxq->tail = rxq->head = 0; + } + +-static void be_tx_compl_clean(struct be_adapter *adapter, +- struct be_tx_obj *txo) ++static void be_tx_compl_clean(struct be_adapter *adapter) + { +- struct be_queue_info *tx_cq = &txo->cq; +- struct be_queue_info *txq = &txo->q; ++ struct be_tx_obj *txo; ++ struct be_queue_info *txq; + struct be_eth_tx_compl *txcp; + u16 end_idx, cmpl = 0, timeo = 0, num_wrbs = 0; +- struct sk_buff **sent_skbs = txo->sent_skb_list; + struct sk_buff *sent_skb; + bool dummy_wrb; ++ int i, pending_txqs; + + /* Wait for a max of 200ms for all the tx-completions to arrive. */ + do { +- while ((txcp = be_tx_compl_get(tx_cq))) { +- end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, +- wrb_index, txcp); +- num_wrbs += be_tx_compl_process(adapter, txo, end_idx); +- cmpl++; +- } +- if (cmpl) { +- be_cq_notify(adapter, tx_cq->id, false, cmpl); +- atomic_sub(num_wrbs, &txq->used); +- cmpl = 0; +- num_wrbs = 0; ++ pending_txqs = adapter->num_tx_qs; ++ ++ for_all_tx_queues(adapter, txo, i) { ++ txq = &txo->q; ++ while ((txcp = be_tx_compl_get(&txo->cq))) { ++ end_idx = ++ AMAP_GET_BITS(struct amap_eth_tx_compl, ++ wrb_index, txcp); ++ num_wrbs += be_tx_compl_process(adapter, txo, ++ end_idx); ++ cmpl++; ++ } ++ if (cmpl) { ++ be_cq_notify(adapter, txo->cq.id, false, cmpl); ++ atomic_sub(num_wrbs, &txq->used); ++ cmpl = 0; ++ num_wrbs = 0; ++ } ++ if (atomic_read(&txq->used) == 0) ++ pending_txqs--; + } + +- if (atomic_read(&txq->used) == 0 || ++timeo > 200) ++ if (pending_txqs == 0 || ++timeo > 200) + break; + + mdelay(1); + } while (true); + +- if (atomic_read(&txq->used)) +- dev_err(&adapter->pdev->dev, "%d pending tx-completions\n", +- atomic_read(&txq->used)); ++ for_all_tx_queues(adapter, txo, i) { ++ txq = &txo->q; ++ if (atomic_read(&txq->used)) ++ dev_err(&adapter->pdev->dev, "%d pending tx-compls\n", ++ atomic_read(&txq->used)); ++ ++ /* free posted tx for which compls will never arrive */ ++ while (atomic_read(&txq->used)) { ++ sent_skb = txo->sent_skb_list[txq->tail]; ++ end_idx = txq->tail; ++ num_wrbs = wrb_cnt_for_skb(adapter, sent_skb, ++ &dummy_wrb); ++ index_adv(&end_idx, num_wrbs - 1, txq->len); ++ num_wrbs = be_tx_compl_process(adapter, txo, end_idx); ++ atomic_sub(num_wrbs, &txq->used); ++ } ++ } ++} ++ ++static void be_evt_queues_destroy(struct be_adapter *adapter) ++{ ++ struct be_eq_obj *eqo; ++ int i; ++ ++ for_all_evt_queues(adapter, eqo, i) { ++ be_eq_clean(eqo); ++ if (eqo->q.created) ++ be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ); ++ be_queue_free(adapter, &eqo->q); ++ } ++} ++ ++static int be_evt_queues_create(struct be_adapter *adapter) ++{ ++ struct be_queue_info *eq; ++ struct be_eq_obj *eqo; ++ int i, rc; ++ ++ adapter->num_evt_qs = num_irqs(adapter); ++ ++ for_all_evt_queues(adapter, eqo, i) { ++ eqo->adapter = adapter; ++ eqo->tx_budget = BE_TX_BUDGET; ++ eqo->idx = i; ++ eqo->max_eqd = BE_MAX_EQD; ++ eqo->enable_aic = true; ++ ++ eq = &eqo->q; ++ rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN, ++ sizeof(struct be_eq_entry)); ++ if (rc) ++ return rc; + +- /* free posted tx for which compls will never arrive */ +- while (atomic_read(&txq->used)) { +- sent_skb = sent_skbs[txq->tail]; +- end_idx = txq->tail; +- index_adv(&end_idx, +- wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1, +- txq->len); +- num_wrbs = be_tx_compl_process(adapter, txo, end_idx); +- atomic_sub(num_wrbs, &txq->used); ++ rc = be_cmd_eq_create(adapter, eq, eqo->cur_eqd); ++ if (rc) ++ return rc; + } ++ return 0; + } + + static void be_mcc_queues_destroy(struct be_adapter *adapter) +@@ -1586,22 +1789,19 @@ static int be_mcc_queues_create(struct be_adapter *adapter) + { + struct be_queue_info *q, *cq; + +- /* Alloc MCC compl queue */ + cq = &adapter->mcc_obj.cq; + if (be_queue_alloc(adapter, cq, MCC_CQ_LEN, + sizeof(struct be_mcc_compl))) + goto err; + +- /* Ask BE to create MCC compl queue; share TX's eq */ +- if (be_cmd_cq_create(adapter, cq, &adapter->tx_eq.q, false, true, 0)) ++ /* Use the default EQ for MCC completions */ ++ if (be_cmd_cq_create(adapter, cq, &mcc_eqo(adapter)->q, true, 0)) + goto mcc_cq_free; + +- /* Alloc MCC queue */ + q = &adapter->mcc_obj.q; + if (be_queue_alloc(adapter, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb))) + goto mcc_cq_destroy; + +- /* Ask BE to create MCC queue */ + if (be_cmd_mccq_create(adapter, q, cq)) + goto mcc_q_free; + +@@ -1634,229 +1834,142 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) + be_cmd_q_destroy(adapter, q, QTYPE_CQ); + be_queue_free(adapter, q); + } +- +- /* Clear any residual events */ +- be_eq_clean(adapter, &adapter->tx_eq); +- +- q = &adapter->tx_eq.q; +- if (q->created) +- be_cmd_q_destroy(adapter, q, QTYPE_EQ); +- be_queue_free(adapter, q); + } + + static int be_num_txqs_want(struct be_adapter *adapter) + { +- if ((num_vfs && adapter->sriov_enabled) || +- be_is_mc(adapter) || +- lancer_chip(adapter) || !be_physfn(adapter) || +- adapter->generation == BE_GEN2) ++ if (sriov_want(adapter) || be_is_mc(adapter) || ++ lancer_chip(adapter) || !be_physfn(adapter) || ++ adapter->generation == BE_GEN2) + return 1; + else + return MAX_TX_QS; + } + +-/* One TX event queue is shared by all TX compl qs */ +-static int be_tx_queues_create(struct be_adapter *adapter) ++static int be_tx_cqs_create(struct be_adapter *adapter) + { +- struct be_queue_info *eq, *q, *cq; ++ struct be_queue_info *cq, *eq; ++ int status; + struct be_tx_obj *txo; + u8 i; + + adapter->num_tx_qs = be_num_txqs_want(adapter); +- if (adapter->num_tx_qs != MAX_TX_QS) ++ if (adapter->num_tx_qs != MAX_TX_QS) { ++ rtnl_lock(); + netif_set_real_num_tx_queues(adapter->netdev, + adapter->num_tx_qs); +- +- adapter->tx_eq.max_eqd = 0; +- adapter->tx_eq.min_eqd = 0; +- adapter->tx_eq.cur_eqd = 96; +- adapter->tx_eq.enable_aic = false; +- +- eq = &adapter->tx_eq.q; +- if (be_queue_alloc(adapter, eq, EVNT_Q_LEN, +- sizeof(struct be_eq_entry))) +- return -1; +- +- if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd)) +- goto err; +- adapter->tx_eq.eq_idx = adapter->eq_next_idx++; ++ rtnl_unlock(); ++ } + + for_all_tx_queues(adapter, txo, i) { + cq = &txo->cq; +- if (be_queue_alloc(adapter, cq, TX_CQ_LEN, +- sizeof(struct be_eth_tx_compl))) +- goto err; ++ status = be_queue_alloc(adapter, cq, TX_CQ_LEN, ++ sizeof(struct be_eth_tx_compl)); ++ if (status) ++ return status; + +- if (be_cmd_cq_create(adapter, cq, eq, false, false, 3)) +- goto err; ++ /* If num_evt_qs is less than num_tx_qs, then more than ++ * one txq share an eq ++ */ ++ eq = &adapter->eq_obj[i % adapter->num_evt_qs].q; ++ status = be_cmd_cq_create(adapter, cq, eq, false, 3); ++ if (status) ++ return status; ++ } ++ return 0; ++} + +- q = &txo->q; +- if (be_queue_alloc(adapter, q, TX_Q_LEN, +- sizeof(struct be_eth_wrb))) +- goto err; ++static int be_tx_qs_create(struct be_adapter *adapter) ++{ ++ struct be_tx_obj *txo; ++ int i, status; + +- if (be_cmd_txq_create(adapter, q, cq)) +- goto err; ++ for_all_tx_queues(adapter, txo, i) { ++ status = be_queue_alloc(adapter, &txo->q, TX_Q_LEN, ++ sizeof(struct be_eth_wrb)); ++ if (status) ++ return status; ++ ++ status = be_cmd_txq_create(adapter, &txo->q, &txo->cq); ++ if (status) ++ return status; + } +- return 0; + +-err: +- be_tx_queues_destroy(adapter); +- return -1; ++ return 0; + } + +-static void be_rx_queues_destroy(struct be_adapter *adapter) ++static void be_rx_cqs_destroy(struct be_adapter *adapter) + { + struct be_queue_info *q; + struct be_rx_obj *rxo; + int i; + + for_all_rx_queues(adapter, rxo, i) { +- be_queue_free(adapter, &rxo->q); +- + q = &rxo->cq; + if (q->created) + be_cmd_q_destroy(adapter, q, QTYPE_CQ); + be_queue_free(adapter, q); +- +- q = &rxo->rx_eq.q; +- if (q->created) +- be_cmd_q_destroy(adapter, q, QTYPE_EQ); +- be_queue_free(adapter, q); +- } +-} +- +-static u32 be_num_rxqs_want(struct be_adapter *adapter) +-{ +- if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && +- !adapter->sriov_enabled && be_physfn(adapter) && +- !be_is_mc(adapter)) { +- return 1 + MAX_RSS_QS; /* one default non-RSS queue */ +- } else { +- dev_warn(&adapter->pdev->dev, +- "No support for multiple RX queues\n"); +- return 1; + } + } + +-static int be_rx_queues_create(struct be_adapter *adapter) ++static int be_rx_cqs_create(struct be_adapter *adapter) + { +- struct be_queue_info *eq, *q, *cq; ++ struct be_queue_info *eq, *cq; + struct be_rx_obj *rxo; + int rc, i; + +- adapter->num_rx_qs = min(be_num_rxqs_want(adapter), +- msix_enabled(adapter) ? +- adapter->num_msix_vec - 1 : 1); +- if (adapter->num_rx_qs != MAX_RX_QS) +- dev_warn(&adapter->pdev->dev, +- "Can create only %d RX queues", adapter->num_rx_qs); ++ /* We'll create as many RSS rings as there are irqs. ++ * But when there's only one irq there's no use creating RSS rings ++ */ ++ adapter->num_rx_qs = (num_irqs(adapter) > 1) ? ++ num_irqs(adapter) + 1 : 1; ++ if (adapter->num_rx_qs != MAX_RX_QS) { ++ rtnl_lock(); ++ netif_set_real_num_rx_queues(adapter->netdev, ++ adapter->num_rx_qs); ++ rtnl_unlock(); ++ } + + adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; + for_all_rx_queues(adapter, rxo, i) { + rxo->adapter = adapter; +- rxo->rx_eq.max_eqd = BE_MAX_EQD; +- rxo->rx_eq.enable_aic = true; +- +- /* EQ */ +- eq = &rxo->rx_eq.q; +- rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN, +- sizeof(struct be_eq_entry)); +- if (rc) +- goto err; +- +- rc = be_cmd_eq_create(adapter, eq, rxo->rx_eq.cur_eqd); +- if (rc) +- goto err; +- +- rxo->rx_eq.eq_idx = adapter->eq_next_idx++; +- +- /* CQ */ + cq = &rxo->cq; + rc = be_queue_alloc(adapter, cq, RX_CQ_LEN, + sizeof(struct be_eth_rx_compl)); + if (rc) +- goto err; +- +- rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3); +- if (rc) +- goto err; ++ return rc; + +- /* Rx Q - will be created in be_open() */ +- q = &rxo->q; +- rc = be_queue_alloc(adapter, q, RX_Q_LEN, +- sizeof(struct be_eth_rx_d)); ++ eq = &adapter->eq_obj[i % adapter->num_evt_qs].q; ++ rc = be_cmd_cq_create(adapter, cq, eq, false, 3); + if (rc) +- goto err; +- ++ return rc; + } + ++ if (adapter->num_rx_qs != MAX_RX_QS) ++ dev_info(&adapter->pdev->dev, ++ "Created only %d receive queues", adapter->num_rx_qs); ++ + return 0; +-err: +- be_rx_queues_destroy(adapter); +- return -1; + } + +-static bool event_peek(struct be_eq_obj *eq_obj) ++static irqreturn_t be_intx(int irq, void *dev) + { +- struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q); +- if (!eqe->evt) +- return false; ++ struct be_adapter *adapter = dev; ++ int num_evts; ++ ++ /* With INTx only one EQ is used */ ++ num_evts = event_handle(&adapter->eq_obj[0]); ++ if (num_evts) ++ return IRQ_HANDLED; + else +- return true; ++ return IRQ_NONE; + } + +-static irqreturn_t be_intx(int irq, void *dev) ++static irqreturn_t be_msix(int irq, void *dev) + { +- struct be_adapter *adapter = dev; +- struct be_rx_obj *rxo; +- int isr, i, tx = 0 , rx = 0; +- +- if (lancer_chip(adapter)) { +- if (event_peek(&adapter->tx_eq)) +- tx = event_handle(adapter, &adapter->tx_eq, false); +- for_all_rx_queues(adapter, rxo, i) { +- if (event_peek(&rxo->rx_eq)) +- rx |= event_handle(adapter, &rxo->rx_eq, true); +- } +- +- if (!(tx || rx)) +- return IRQ_NONE; +- +- } else { +- isr = ioread32(adapter->csr + CEV_ISR0_OFFSET + +- (adapter->tx_eq.q.id / 8) * CEV_ISR_SIZE); +- if (!isr) +- return IRQ_NONE; +- +- if ((1 << adapter->tx_eq.eq_idx & isr)) +- event_handle(adapter, &adapter->tx_eq, false); +- +- for_all_rx_queues(adapter, rxo, i) { +- if ((1 << rxo->rx_eq.eq_idx & isr)) +- event_handle(adapter, &rxo->rx_eq, true); +- } +- } +- +- return IRQ_HANDLED; +-} +- +-static irqreturn_t be_msix_rx(int irq, void *dev) +-{ +- struct be_rx_obj *rxo = dev; +- struct be_adapter *adapter = rxo->adapter; +- +- event_handle(adapter, &rxo->rx_eq, true); +- +- return IRQ_HANDLED; +-} +- +-static irqreturn_t be_msix_tx_mcc(int irq, void *dev) +-{ +- struct be_adapter *adapter = dev; +- +- event_handle(adapter, &adapter->tx_eq, false); ++ struct be_eq_obj *eqo = dev; + ++ event_handle(eqo); + return IRQ_HANDLED; + } + +@@ -1865,16 +1978,14 @@ static inline bool do_gro(struct be_rx_compl_info *rxcp) + return (rxcp->tcpf && !rxcp->err) ? true : false; + } + +-static int be_poll_rx(struct napi_struct *napi, int budget) ++static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi, ++ int budget) + { +- struct be_eq_obj *rx_eq = container_of(napi, struct be_eq_obj, napi); +- struct be_rx_obj *rxo = container_of(rx_eq, struct be_rx_obj, rx_eq); + struct be_adapter *adapter = rxo->adapter; + struct be_queue_info *rx_cq = &rxo->cq; + struct be_rx_compl_info *rxcp; + u32 work_done; + +- rx_stats(rxo)->rx_polls++; + for (work_done = 0; work_done < budget; work_done++) { + rxcp = be_rx_compl_get(rxo); + if (!rxcp) +@@ -1886,7 +1997,7 @@ static int be_poll_rx(struct napi_struct *napi, int budget) + + /* Discard compl with partial DMA Lancer B0 */ + if (unlikely(!rxcp->pkt_size)) { +- be_rx_compl_discard(adapter, rxo, rxcp); ++ be_rx_compl_discard(rxo, rxcp); + goto loop_continue; + } + +@@ -1895,86 +2006,96 @@ static int be_poll_rx(struct napi_struct *napi, int budget) + */ + if (unlikely(rxcp->port != adapter->port_num && + !lancer_chip(adapter))) { +- be_rx_compl_discard(adapter, rxo, rxcp); ++ be_rx_compl_discard(rxo, rxcp); + goto loop_continue; + } + + if (do_gro(rxcp)) +- be_rx_compl_process_gro(adapter, rxo, rxcp); ++ be_rx_compl_process_gro(rxo, napi, rxcp); + else +- be_rx_compl_process(adapter, rxo, rxcp); ++ be_rx_compl_process(rxo, rxcp); + loop_continue: + be_rx_stats_update(rxo, rxcp); + } + +- be_cq_notify(adapter, rx_cq->id, false, work_done); +- +- /* Refill the queue */ +- if (work_done && atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM) +- be_post_rx_frags(rxo, GFP_ATOMIC); ++ if (work_done) { ++ be_cq_notify(adapter, rx_cq->id, true, work_done); + +- /* All consumed */ +- if (work_done < budget) { +- napi_complete(napi); +- /* Arm CQ */ +- be_cq_notify(adapter, rx_cq->id, true, 0); ++ if (atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM) ++ be_post_rx_frags(rxo, GFP_ATOMIC); + } ++ + return work_done; + } + +-/* As TX and MCC share the same EQ check for both TX and MCC completions. +- * For TX/MCC we don't honour budget; consume everything +- */ +-static int be_poll_tx_mcc(struct napi_struct *napi, int budget) ++static bool be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo, ++ int budget, int idx) + { +- struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); +- struct be_adapter *adapter = +- container_of(tx_eq, struct be_adapter, tx_eq); +- struct be_tx_obj *txo; + struct be_eth_tx_compl *txcp; +- int tx_compl, mcc_compl, status = 0; +- u8 i; +- u16 num_wrbs; ++ int num_wrbs = 0, work_done; + +- for_all_tx_queues(adapter, txo, i) { +- tx_compl = 0; +- num_wrbs = 0; +- while ((txcp = be_tx_compl_get(&txo->cq))) { +- num_wrbs += be_tx_compl_process(adapter, txo, ++ for (work_done = 0; work_done < budget; work_done++) { ++ txcp = be_tx_compl_get(&txo->cq); ++ if (!txcp) ++ break; ++ num_wrbs += be_tx_compl_process(adapter, txo, + AMAP_GET_BITS(struct amap_eth_tx_compl, + wrb_index, txcp)); +- tx_compl++; +- } +- if (tx_compl) { +- be_cq_notify(adapter, txo->cq.id, true, tx_compl); +- +- atomic_sub(num_wrbs, &txo->q.used); ++ } + +- /* As Tx wrbs have been freed up, wake up netdev queue +- * if it was stopped due to lack of tx wrbs. */ +- if (__netif_subqueue_stopped(adapter->netdev, i) && +- atomic_read(&txo->q.used) < txo->q.len / 2) { +- netif_wake_subqueue(adapter->netdev, i); +- } ++ if (work_done) { ++ be_cq_notify(adapter, txo->cq.id, true, work_done); ++ atomic_sub(num_wrbs, &txo->q.used); + +- u64_stats_update_begin(&tx_stats(txo)->sync_compl); +- tx_stats(txo)->tx_compl += tx_compl; +- u64_stats_update_end(&tx_stats(txo)->sync_compl); ++ /* As Tx wrbs have been freed up, wake up netdev queue ++ * if it was stopped due to lack of tx wrbs. */ ++ if (__netif_subqueue_stopped(adapter->netdev, idx) && ++ atomic_read(&txo->q.used) < txo->q.len / 2) { ++ netif_wake_subqueue(adapter->netdev, idx); + } ++ ++ u64_stats_update_begin(&tx_stats(txo)->sync_compl); ++ tx_stats(txo)->tx_compl += work_done; ++ u64_stats_update_end(&tx_stats(txo)->sync_compl); + } ++ return (work_done < budget); /* Done */ ++} + +- mcc_compl = be_process_mcc(adapter, &status); ++int be_poll(struct napi_struct *napi, int budget) ++{ ++ struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi); ++ struct be_adapter *adapter = eqo->adapter; ++ int max_work = 0, work, i; ++ bool tx_done; + +- if (mcc_compl) { +- struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; +- be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl); ++ /* Process all TXQs serviced by this EQ */ ++ for (i = eqo->idx; i < adapter->num_tx_qs; i += adapter->num_evt_qs) { ++ tx_done = be_process_tx(adapter, &adapter->tx_obj[i], ++ eqo->tx_budget, i); ++ if (!tx_done) ++ max_work = budget; ++ } ++ ++ /* This loop will iterate twice for EQ0 in which ++ * completions of the last RXQ (default one) are also processed ++ * For other EQs the loop iterates only once ++ */ ++ for (i = eqo->idx; i < adapter->num_rx_qs; i += adapter->num_evt_qs) { ++ work = be_process_rx(&adapter->rx_obj[i], napi, budget); ++ max_work = max(work, max_work); + } + +- napi_complete(napi); ++ if (is_mcc_eqo(eqo)) ++ be_process_mcc(adapter); + +- be_eq_notify(adapter, tx_eq->q.id, true, false, 0); +- adapter->drv_stats.tx_events++; +- return 1; ++ if (max_work < budget) { ++ napi_complete(napi); ++ be_eq_notify(adapter, eqo->q.id, true, false, 0); ++ } else { ++ /* As we'll continue in polling mode, count and clear events */ ++ be_eq_notify(adapter, eqo->q.id, false, false, events_get(eqo)); ++ } ++ return max_work; + } + + void be_detect_dump_ue(struct be_adapter *adapter) +@@ -1983,6 +2104,9 @@ void be_detect_dump_ue(struct be_adapter *adapter) + u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0; + u32 i; + ++ if (adapter->eeh_err || adapter->ue_detected) ++ return; ++ + if (lancer_chip(adapter)) { + sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); + if (sliport_status & SLIPORT_STATUS_ERR_MASK) { +@@ -2009,7 +2133,8 @@ void be_detect_dump_ue(struct be_adapter *adapter) + sliport_status & SLIPORT_STATUS_ERR_MASK) { + adapter->ue_detected = true; + adapter->eeh_err = true; +- dev_err(&adapter->pdev->dev, "UE Detected!!\n"); ++ dev_err(&adapter->pdev->dev, ++ "Unrecoverable error in the card\n"); + } + + if (ue_lo) { +@@ -2037,53 +2162,6 @@ void be_detect_dump_ue(struct be_adapter *adapter) + } + } + +-static void be_worker(struct work_struct *work) +-{ +- struct be_adapter *adapter = +- container_of(work, struct be_adapter, work.work); +- struct be_rx_obj *rxo; +- int i; +- +- if (!adapter->ue_detected) +- be_detect_dump_ue(adapter); +- +- /* when interrupts are not yet enabled, just reap any pending +- * mcc completions */ +- if (!netif_running(adapter->netdev)) { +- int mcc_compl, status = 0; +- +- mcc_compl = be_process_mcc(adapter, &status); +- +- if (mcc_compl) { +- struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; +- be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl); +- } +- +- goto reschedule; +- } +- +- if (!adapter->stats_cmd_sent) { +- if (lancer_chip(adapter)) +- lancer_cmd_get_pport_stats(adapter, +- &adapter->stats_cmd); +- else +- be_cmd_get_stats(adapter, &adapter->stats_cmd); +- } +- +- for_all_rx_queues(adapter, rxo, i) { +- be_rx_eqd_update(adapter, rxo); +- +- if (rxo->rx_post_starved) { +- rxo->rx_post_starved = false; +- be_post_rx_frags(rxo, GFP_KERNEL); +- } +- } +- +-reschedule: +- adapter->work_counter++; +- schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); +-} +- + static void be_msix_disable(struct be_adapter *adapter) + { + if (msix_enabled(adapter)) { +@@ -2092,12 +2170,24 @@ static void be_msix_disable(struct be_adapter *adapter) + } + } + ++static uint be_num_rss_want(struct be_adapter *adapter) ++{ ++ if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && ++ !sriov_want(adapter) && be_physfn(adapter) && ++ !be_is_mc(adapter)) ++ return (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; ++ else ++ return 0; ++} ++ + static void be_msix_enable(struct be_adapter *adapter) + { +-#define BE_MIN_MSIX_VECTORS (1 + 1) /* Rx + Tx */ ++#define BE_MIN_MSIX_VECTORS 1 + int i, status, num_vec; + +- num_vec = be_num_rxqs_want(adapter) + 1; ++ /* If RSS queues are not used, need a vec for default RX Q */ ++ num_vec = min(be_num_rss_want(adapter), num_online_cpus()); ++ num_vec = max(num_vec, BE_MIN_MSIX_VECTORS); + + for (i = 0; i < num_vec; i++) + adapter->msix_entries[i].entry = i; +@@ -2117,107 +2207,32 @@ done: + return; + } + +-static int be_sriov_enable(struct be_adapter *adapter) +-{ +- be_check_sriov_fn_type(adapter); +-#ifdef CONFIG_PCI_IOV +- if (be_physfn(adapter) && num_vfs) { +- int status, pos; +- u16 nvfs; +- +- pos = pci_find_ext_capability(adapter->pdev, +- PCI_EXT_CAP_ID_SRIOV); +- pci_read_config_word(adapter->pdev, +- pos + PCI_SRIOV_TOTAL_VF, &nvfs); +- +- if (num_vfs > nvfs) { +- dev_info(&adapter->pdev->dev, +- "Device supports %d VFs and not %d\n", +- nvfs, num_vfs); +- num_vfs = nvfs; +- } +- +- status = pci_enable_sriov(adapter->pdev, num_vfs); +- adapter->sriov_enabled = status ? false : true; +- +- if (adapter->sriov_enabled) { +- adapter->vf_cfg = kcalloc(num_vfs, +- sizeof(struct be_vf_cfg), +- GFP_KERNEL); +- if (!adapter->vf_cfg) +- return -ENOMEM; +- } +- } +-#endif +- return 0; +-} +- +-static void be_sriov_disable(struct be_adapter *adapter) +-{ +-#ifdef CONFIG_PCI_IOV +- if (adapter->sriov_enabled) { +- pci_disable_sriov(adapter->pdev); +- kfree(adapter->vf_cfg); +- adapter->sriov_enabled = false; +- } +-#endif +-} +- + static inline int be_msix_vec_get(struct be_adapter *adapter, +- struct be_eq_obj *eq_obj) +-{ +- return adapter->msix_entries[eq_obj->eq_idx].vector; +-} +- +-static int be_request_irq(struct be_adapter *adapter, +- struct be_eq_obj *eq_obj, +- void *handler, char *desc, void *context) +-{ +- struct net_device *netdev = adapter->netdev; +- int vec; +- +- sprintf(eq_obj->desc, "%s-%s", netdev->name, desc); +- vec = be_msix_vec_get(adapter, eq_obj); +- return request_irq(vec, handler, 0, eq_obj->desc, context); +-} +- +-static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj, +- void *context) ++ struct be_eq_obj *eqo) + { +- int vec = be_msix_vec_get(adapter, eq_obj); +- free_irq(vec, context); ++ return adapter->msix_entries[eqo->idx].vector; + } + + static int be_msix_register(struct be_adapter *adapter) + { +- struct be_rx_obj *rxo; +- int status, i; +- char qname[10]; +- +- status = be_request_irq(adapter, &adapter->tx_eq, be_msix_tx_mcc, "tx", +- adapter); +- if (status) +- goto err; ++ struct net_device *netdev = adapter->netdev; ++ struct be_eq_obj *eqo; ++ int status, i, vec; + +- for_all_rx_queues(adapter, rxo, i) { +- sprintf(qname, "rxq%d", i); +- status = be_request_irq(adapter, &rxo->rx_eq, be_msix_rx, +- qname, rxo); ++ for_all_evt_queues(adapter, eqo, i) { ++ sprintf(eqo->desc, "%s-q%d", netdev->name, i); ++ vec = be_msix_vec_get(adapter, eqo); ++ status = request_irq(vec, be_msix, 0, eqo->desc, eqo); + if (status) + goto err_msix; + } + + return 0; +- + err_msix: +- be_free_irq(adapter, &adapter->tx_eq, adapter); +- +- for (i--, rxo = &adapter->rx_obj[i]; i >= 0; i--, rxo--) +- be_free_irq(adapter, &rxo->rx_eq, rxo); +- +-err: +- dev_warn(&adapter->pdev->dev, +- "MSIX Request IRQ failed - err %d\n", status); ++ for (i--, eqo = &adapter->eq_obj[i]; i >= 0; i--, eqo--) ++ free_irq(be_msix_vec_get(adapter, eqo), eqo); ++ dev_warn(&adapter->pdev->dev, "MSIX Request IRQ failed - err %d\n", ++ status); + be_msix_disable(adapter); + return status; + } +@@ -2253,7 +2268,7 @@ done: + static void be_irq_unregister(struct be_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; +- struct be_rx_obj *rxo; ++ struct be_eq_obj *eqo; + int i; + + if (!adapter->isr_registered) +@@ -2266,16 +2281,14 @@ static void be_irq_unregister(struct be_adapter *adapter) + } + + /* MSIx */ +- be_free_irq(adapter, &adapter->tx_eq, adapter); +- +- for_all_rx_queues(adapter, rxo, i) +- be_free_irq(adapter, &rxo->rx_eq, rxo); ++ for_all_evt_queues(adapter, eqo, i) ++ free_irq(be_msix_vec_get(adapter, eqo), eqo); + + done: + adapter->isr_registered = false; + } + +-static void be_rx_queues_clear(struct be_adapter *adapter) ++static void be_rx_qs_destroy(struct be_adapter *adapter) + { + struct be_queue_info *q; + struct be_rx_obj *rxo; +@@ -2290,126 +2303,126 @@ static void be_rx_queues_clear(struct be_adapter *adapter) + * arrive + */ + mdelay(1); +- be_rx_q_clean(adapter, rxo); ++ be_rx_cq_clean(rxo); + } +- +- /* Clear any residual events */ +- q = &rxo->rx_eq.q; +- if (q->created) +- be_eq_clean(adapter, &rxo->rx_eq); ++ be_queue_free(adapter, q); + } + } + + static int be_close(struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_rx_obj *rxo; +- struct be_tx_obj *txo; +- struct be_eq_obj *tx_eq = &adapter->tx_eq; +- int vec, i; ++ struct be_eq_obj *eqo; ++ int i; + + be_async_mcc_disable(adapter); + + if (!lancer_chip(adapter)) + be_intr_set(adapter, false); + +- for_all_rx_queues(adapter, rxo, i) +- napi_disable(&rxo->rx_eq.napi); +- +- napi_disable(&tx_eq->napi); +- +- if (lancer_chip(adapter)) { +- be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0); +- for_all_rx_queues(adapter, rxo, i) +- be_cq_notify(adapter, rxo->cq.id, false, 0); +- for_all_tx_queues(adapter, txo, i) +- be_cq_notify(adapter, txo->cq.id, false, 0); ++ for_all_evt_queues(adapter, eqo, i) { ++ napi_disable(&eqo->napi); ++ if (msix_enabled(adapter)) ++ synchronize_irq(be_msix_vec_get(adapter, eqo)); ++ else ++ synchronize_irq(netdev->irq); ++ be_eq_clean(eqo); + } + +- if (msix_enabled(adapter)) { +- vec = be_msix_vec_get(adapter, tx_eq); +- synchronize_irq(vec); +- +- for_all_rx_queues(adapter, rxo, i) { +- vec = be_msix_vec_get(adapter, &rxo->rx_eq); +- synchronize_irq(vec); +- } +- } else { +- synchronize_irq(netdev->irq); +- } + be_irq_unregister(adapter); + + /* Wait for all pending tx completions to arrive so that + * all tx skbs are freed. + */ +- for_all_tx_queues(adapter, txo, i) +- be_tx_compl_clean(adapter, txo); ++ be_tx_compl_clean(adapter); + +- be_rx_queues_clear(adapter); ++ be_rx_qs_destroy(adapter); + return 0; + } + +-static int be_rx_queues_setup(struct be_adapter *adapter) ++static int be_rx_qs_create(struct be_adapter *adapter) + { + struct be_rx_obj *rxo; +- int rc, i; +- u8 rsstable[MAX_RSS_QS]; ++ int rc, i, j; ++ u8 rsstable[128]; + + for_all_rx_queues(adapter, rxo, i) { ++ rc = be_queue_alloc(adapter, &rxo->q, RX_Q_LEN, ++ sizeof(struct be_eth_rx_d)); ++ if (rc) ++ return rc; ++ } ++ ++ /* The FW would like the default RXQ to be created first */ ++ rxo = default_rxo(adapter); ++ rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id, rx_frag_size, ++ adapter->if_handle, false, &rxo->rss_id); ++ if (rc) ++ return rc; ++ ++ for_all_rss_queues(adapter, rxo, i) { + rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id, +- rx_frag_size, BE_MAX_JUMBO_FRAME_SIZE, +- adapter->if_handle, +- (i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id); ++ rx_frag_size, adapter->if_handle, ++ true, &rxo->rss_id); + if (rc) + return rc; + } + + if (be_multi_rxq(adapter)) { +- for_all_rss_queues(adapter, rxo, i) +- rsstable[i] = rxo->rss_id; +- +- rc = be_cmd_rss_config(adapter, rsstable, +- adapter->num_rx_qs - 1); ++ for (j = 0; j < 128; j += adapter->num_rx_qs - 1) { ++ for_all_rss_queues(adapter, rxo, i) { ++ if ((j + i) >= 128) ++ break; ++ rsstable[j + i] = rxo->rss_id; ++ } ++ } ++ rc = be_cmd_rss_config(adapter, rsstable, 128); + if (rc) + return rc; + } + + /* First time posting */ +- for_all_rx_queues(adapter, rxo, i) { ++ for_all_rx_queues(adapter, rxo, i) + be_post_rx_frags(rxo, GFP_KERNEL); +- napi_enable(&rxo->rx_eq.napi); +- } + return 0; + } + + static int be_open(struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_eq_obj *tx_eq = &adapter->tx_eq; ++ struct be_eq_obj *eqo; + struct be_rx_obj *rxo; ++ struct be_tx_obj *txo; ++ u8 link_status; + int status, i; + +- status = be_rx_queues_setup(adapter); ++ status = be_rx_qs_create(adapter); + if (status) + goto err; + +- napi_enable(&tx_eq->napi); +- + be_irq_register(adapter); + + if (!lancer_chip(adapter)) + be_intr_set(adapter, true); + +- /* The evt queues are created in unarmed state; arm them */ +- for_all_rx_queues(adapter, rxo, i) { +- be_eq_notify(adapter, rxo->rx_eq.q.id, true, false, 0); ++ for_all_rx_queues(adapter, rxo, i) + be_cq_notify(adapter, rxo->cq.id, true, 0); +- } +- be_eq_notify(adapter, tx_eq->q.id, true, false, 0); + +- /* Now that interrupts are on we can process async mcc */ ++ for_all_tx_queues(adapter, txo, i) ++ be_cq_notify(adapter, txo->cq.id, true, 0); ++ + be_async_mcc_enable(adapter); + ++ for_all_evt_queues(adapter, eqo, i) { ++ napi_enable(&eqo->napi); ++ be_eq_notify(adapter, eqo->q.id, true, false, 0); ++ } ++ ++ status = be_cmd_link_status_query(adapter, NULL, NULL, ++ &link_status, 0); ++ if (!status) ++ be_link_status_update(adapter, link_status); ++ + return 0; + err: + be_close(adapter->netdev); +@@ -2466,19 +2479,24 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter) + u32 vf; + int status = 0; + u8 mac[ETH_ALEN]; ++ struct be_vf_cfg *vf_cfg; + + be_vf_eth_addr_generate(adapter, mac); + +- for (vf = 0; vf < num_vfs; vf++) { +- status = be_cmd_pmac_add(adapter, mac, +- adapter->vf_cfg[vf].vf_if_handle, +- &adapter->vf_cfg[vf].vf_pmac_id, +- vf + 1); ++ for_all_vfs(adapter, vf_cfg, vf) { ++ if (lancer_chip(adapter)) { ++ status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1); ++ } else { ++ status = be_cmd_pmac_add(adapter, mac, ++ vf_cfg->if_handle, ++ &vf_cfg->pmac_id, vf + 1); ++ } ++ + if (status) + dev_err(&adapter->pdev->dev, +- "Mac address add failed for VF %d\n", vf); ++ "Mac address assignment failed for VF %d\n", vf); + else +- memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN); ++ memcpy(vf_cfg->mac_addr, mac, ETH_ALEN); + + mac[5] += 1; + } +@@ -2487,104 +2505,231 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter) + + static void be_vf_clear(struct be_adapter *adapter) + { ++ struct be_vf_cfg *vf_cfg; + u32 vf; + +- for (vf = 0; vf < num_vfs; vf++) { +- if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID) +- be_cmd_pmac_del(adapter, +- adapter->vf_cfg[vf].vf_if_handle, +- adapter->vf_cfg[vf].vf_pmac_id, vf + 1); ++ if (be_find_vfs(adapter, ASSIGNED)) { ++ dev_warn(&adapter->pdev->dev, "VFs are assigned to VMs\n"); ++ goto done; + } + +- for (vf = 0; vf < num_vfs; vf++) +- if (adapter->vf_cfg[vf].vf_if_handle) +- be_cmd_if_destroy(adapter, +- adapter->vf_cfg[vf].vf_if_handle, vf + 1); ++ for_all_vfs(adapter, vf_cfg, vf) { ++ if (lancer_chip(adapter)) ++ be_cmd_set_mac_list(adapter, NULL, 0, vf + 1); ++ else ++ be_cmd_pmac_del(adapter, vf_cfg->if_handle, ++ vf_cfg->pmac_id, vf + 1); ++ ++ be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1); ++ } ++ pci_disable_sriov(adapter->pdev); ++done: ++ kfree(adapter->vf_cfg); ++ adapter->num_vfs = 0; + } + + static int be_clear(struct be_adapter *adapter) + { +- if (be_physfn(adapter) && adapter->sriov_enabled) ++ int i = 1; ++ ++ if (adapter->flags & BE_FLAGS_WORKER_SCHEDULED) { ++ cancel_delayed_work_sync(&adapter->work); ++ adapter->flags &= ~BE_FLAGS_WORKER_SCHEDULED; ++ } ++ ++ if (sriov_enabled(adapter)) + be_vf_clear(adapter); + ++ for (; adapter->uc_macs > 0; adapter->uc_macs--, i++) ++ be_cmd_pmac_del(adapter, adapter->if_handle, ++ adapter->pmac_id[i], 0); ++ + be_cmd_if_destroy(adapter, adapter->if_handle, 0); + + be_mcc_queues_destroy(adapter); +- be_rx_queues_destroy(adapter); ++ be_rx_cqs_destroy(adapter); + be_tx_queues_destroy(adapter); +- adapter->eq_next_idx = 0; +- +- adapter->be3_native = false; +- adapter->promiscuous = false; ++ be_evt_queues_destroy(adapter); + + /* tell fw we're done with firing cmds */ + be_cmd_fw_clean(adapter); ++ ++ be_msix_disable(adapter); ++ return 0; ++} ++ ++static int be_vf_setup_init(struct be_adapter *adapter) ++{ ++ struct be_vf_cfg *vf_cfg; ++ int vf; ++ ++ adapter->vf_cfg = kcalloc(adapter->num_vfs, sizeof(*vf_cfg), ++ GFP_KERNEL); ++ if (!adapter->vf_cfg) ++ return -ENOMEM; ++ ++ for_all_vfs(adapter, vf_cfg, vf) { ++ vf_cfg->if_handle = -1; ++ vf_cfg->pmac_id = -1; ++ } + return 0; + } + + static int be_vf_setup(struct be_adapter *adapter) + { ++ struct be_vf_cfg *vf_cfg; ++ struct device *dev = &adapter->pdev->dev; + u32 cap_flags, en_flags, vf; +- u16 lnk_speed; +- int status; ++ u16 def_vlan, lnk_speed; ++ int status, enabled_vfs; ++ ++ enabled_vfs = be_find_vfs(adapter, ENABLED); ++ if (enabled_vfs) { ++ dev_warn(dev, "%d VFs are already enabled\n", enabled_vfs); ++ dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs); ++ return 0; ++ } ++ ++ if (num_vfs > adapter->dev_num_vfs) { ++ dev_warn(dev, "Device supports %d VFs and not %d\n", ++ adapter->dev_num_vfs, num_vfs); ++ num_vfs = adapter->dev_num_vfs; ++ } + +- cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST; +- for (vf = 0; vf < num_vfs; vf++) { ++ status = pci_enable_sriov(adapter->pdev, num_vfs); ++ if (!status) { ++ adapter->num_vfs = num_vfs; ++ } else { ++ /* Platform doesn't support SRIOV though device supports it */ ++ dev_warn(dev, "SRIOV enable failed\n"); ++ return 0; ++ } ++ ++ status = be_vf_setup_init(adapter); ++ if (status) ++ goto err; ++ ++ cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | ++ BE_IF_FLAGS_MULTICAST; ++ for_all_vfs(adapter, vf_cfg, vf) { + status = be_cmd_if_create(adapter, cap_flags, en_flags, NULL, +- &adapter->vf_cfg[vf].vf_if_handle, +- NULL, vf+1); ++ &vf_cfg->if_handle, NULL, vf + 1); + if (status) + goto err; +- adapter->vf_cfg[vf].vf_pmac_id = BE_INVALID_PMAC_ID; + } + +- if (!lancer_chip(adapter)) { ++ if (!enabled_vfs) { + status = be_vf_eth_addr_config(adapter); + if (status) + goto err; + } + +- for (vf = 0; vf < num_vfs; vf++) { ++ for_all_vfs(adapter, vf_cfg, vf) { + status = be_cmd_link_status_query(adapter, NULL, &lnk_speed, +- vf + 1); ++ NULL, vf + 1); + if (status) + goto err; +- adapter->vf_cfg[vf].vf_tx_rate = lnk_speed * 10; ++ vf_cfg->tx_rate = lnk_speed * 10; ++ ++ status = be_cmd_get_hsw_config(adapter, &def_vlan, ++ vf + 1, vf_cfg->if_handle); ++ if (status) ++ goto err; ++ vf_cfg->def_vid = def_vlan; + } + return 0; + err: + return status; + } + ++static void be_setup_init(struct be_adapter *adapter) ++{ ++ adapter->vlan_prio_bmap = 0xff; ++ adapter->phy.link_speed = -1; ++ adapter->if_handle = -1; ++ adapter->be3_native = false; ++ adapter->promiscuous = false; ++ adapter->eq_next_idx = 0; ++ adapter->phy.forced_port_speed = -1; ++} ++ ++static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac) ++{ ++ u32 pmac_id; ++ int status; ++ bool pmac_id_active; ++ ++ status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id_active, ++ &pmac_id, mac); ++ if (status != 0) ++ goto do_none; ++ ++ if (pmac_id_active) { ++ status = be_cmd_mac_addr_query(adapter, mac, ++ MAC_ADDRESS_TYPE_NETWORK, ++ false, adapter->if_handle, pmac_id); ++ ++ if (!status) ++ adapter->pmac_id[0] = pmac_id; ++ } else { ++ status = be_cmd_pmac_add(adapter, mac, ++ adapter->if_handle, &adapter->pmac_id[0], 0); ++ } ++do_none: ++ return status; ++} ++ ++/* Routine to query per function resource limits */ ++static int be_get_config(struct be_adapter *adapter) ++{ ++ int pos; ++ u16 dev_num_vfs; ++ ++ pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV); ++ if (pos) { ++ pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF, ++ &dev_num_vfs); ++ adapter->dev_num_vfs = dev_num_vfs; ++ } ++ return 0; ++} ++ + static int be_setup(struct be_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; ++ struct device *dev = &adapter->pdev->dev; + u32 cap_flags, en_flags; + u32 tx_fc, rx_fc; + int status; + u8 mac[ETH_ALEN]; + +- /* Allow all priorities by default. A GRP5 evt may modify this */ +- adapter->vlan_prio_bmap = 0xff; +- adapter->link_speed = -1; ++ be_setup_init(adapter); ++ ++ be_get_config(adapter); + + be_cmd_req_native_mode(adapter); + +- status = be_tx_queues_create(adapter); +- if (status != 0) ++ be_msix_enable(adapter); ++ ++ status = be_evt_queues_create(adapter); ++ if (status) + goto err; + +- status = be_rx_queues_create(adapter); +- if (status != 0) ++ status = be_tx_cqs_create(adapter); ++ if (status) ++ goto err; ++ ++ status = be_rx_cqs_create(adapter); ++ if (status) + goto err; + + status = be_mcc_queues_create(adapter); +- if (status != 0) ++ if (status) + goto err; + + memset(mac, 0, ETH_ALEN); + status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK, +- true /*permanent */, 0); ++ true /*permanent */, 0, 0); + if (status) + return status; + memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); +@@ -2593,62 +2738,87 @@ static int be_setup(struct be_adapter *adapter) + en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS; + cap_flags = en_flags | BE_IF_FLAGS_MCAST_PROMISCUOUS | +- BE_IF_FLAGS_PROMISCUOUS; ++ BE_IF_FLAGS_VLAN_PROMISCUOUS | BE_IF_FLAGS_PROMISCUOUS; ++ + if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) { + cap_flags |= BE_IF_FLAGS_RSS; + en_flags |= BE_IF_FLAGS_RSS; + } + status = be_cmd_if_create(adapter, cap_flags, en_flags, + netdev->dev_addr, &adapter->if_handle, +- &adapter->pmac_id, 0); ++ &adapter->pmac_id[0], 0); + if (status != 0) + goto err; + +- /* For BEx, the VF's permanent mac queried from card is incorrect. +- * Query the mac configued by the PF using if_handle +- */ +- if (!be_physfn(adapter) && !lancer_chip(adapter)) { +- status = be_cmd_mac_addr_query(adapter, mac, +- MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle); ++ /* The VF's permanent mac queried from card is incorrect. ++ * For BEx: Query the mac configued by the PF using if_handle ++ * For Lancer: Get and use mac_list to obtain mac address. ++ */ ++ if (!be_physfn(adapter)) { ++ if (lancer_chip(adapter)) ++ status = be_add_mac_from_list(adapter, mac); ++ else ++ status = be_cmd_mac_addr_query(adapter, mac, ++ MAC_ADDRESS_TYPE_NETWORK, false, ++ adapter->if_handle, 0); + if (!status) { + memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); + memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN); + } + } + +- be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL); +- +- status = be_vid_config(adapter, false, 0); ++ status = be_tx_qs_create(adapter); + if (status) + goto err; + ++ be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL); ++ ++ be_vid_config(adapter, false, 0); ++ + be_set_rx_mode(adapter->netdev); + +- status = be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc); +- if (status) +- goto err; +- if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc) { +- status = be_cmd_set_flow_control(adapter, adapter->tx_fc, +- adapter->rx_fc); +- if (status) +- goto err; +- } ++ be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc); + +- pcie_set_readrq(adapter->pdev, 4096); ++ if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc) ++ be_cmd_set_flow_control(adapter, adapter->tx_fc, ++ adapter->rx_fc); + +- if (be_physfn(adapter) && adapter->sriov_enabled) { +- status = be_vf_setup(adapter); +- if (status) +- goto err; ++ if (be_physfn(adapter) && num_vfs) { ++ if (adapter->dev_num_vfs) ++ be_vf_setup(adapter); ++ else ++ dev_warn(dev, "device doesn't support SRIOV\n"); + } + ++ be_cmd_get_phy_info(adapter); ++ if (be_pause_supported(adapter)) ++ adapter->phy.fc_autoneg = 1; ++ ++ schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); ++ adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; + return 0; + err: + be_clear(adapter); + return status; + } + ++#ifdef CONFIG_NET_POLL_CONTROLLER ++static void be_netpoll(struct net_device *netdev) ++{ ++ struct be_adapter *adapter = netdev_priv(netdev); ++ struct be_eq_obj *eqo; ++ int i; ++ ++ for_all_evt_queues(adapter, eqo, i) ++ event_handle(eqo); ++ ++ return; ++} ++#endif ++ + #define FW_FILE_HDR_SIGN "ServerEngines Corp. " ++char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; ++ + static bool be_flash_redboot(struct be_adapter *adapter, + const u8 *p, u32 img_start, int image_size, + int hdr_size) +@@ -2678,71 +2848,105 @@ static bool be_flash_redboot(struct be_adapter *adapter, + + static bool phy_flashing_required(struct be_adapter *adapter) + { +- int status = 0; +- struct be_phy_info phy_info; ++ return (adapter->phy.phy_type == TN_8022 && ++ adapter->phy.interface_type == PHY_TYPE_BASET_10GB); ++} + +- status = be_cmd_get_phy_info(adapter, &phy_info); +- if (status) +- return false; +- if ((phy_info.phy_type == TN_8022) && +- (phy_info.interface_type == PHY_TYPE_BASET_10GB)) { +- return true; ++static bool is_comp_in_ufi(struct be_adapter *adapter, ++ struct flash_section_info *fsec, int type) ++{ ++ int i = 0, img_type = 0; ++ struct flash_section_info_g2 *fsec_g2 = NULL; ++ ++ if (adapter->generation != BE_GEN3) ++ fsec_g2 = (struct flash_section_info_g2 *)fsec; ++ ++ for (i = 0; i < MAX_FLASH_COMP; i++) { ++ if (fsec_g2) ++ img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type); ++ else ++ img_type = le32_to_cpu(fsec->fsec_entry[i].type); ++ ++ if (img_type == type) ++ return true; + } + return false; ++ ++} ++ ++struct flash_section_info *get_fsec_info(struct be_adapter *adapter, ++ int header_size, ++ const struct firmware *fw) ++{ ++ struct flash_section_info *fsec = NULL; ++ const u8 *p = fw->data; ++ ++ p += header_size; ++ while (p < (fw->data + fw->size)) { ++ fsec = (struct flash_section_info *)p; ++ if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) ++ return fsec; ++ p += 32; ++ } ++ return NULL; + } + + static int be_flash_data(struct be_adapter *adapter, +- const struct firmware *fw, +- struct be_dma_mem *flash_cmd, int num_of_images) ++ const struct firmware *fw, ++ struct be_dma_mem *flash_cmd, ++ int num_of_images) + + { + int status = 0, i, filehdr_size = 0; ++ int img_hdrs_size = (num_of_images * sizeof(struct image_hdr)); + u32 total_bytes = 0, flash_op; + int num_bytes; + const u8 *p = fw->data; + struct be_cmd_write_flashrom *req = flash_cmd->va; + const struct flash_comp *pflashcomp; +- int num_comp; +- +- static const struct flash_comp gen3_flash_types[10] = { +- { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE, +- FLASH_IMAGE_MAX_SIZE_g3}, +- { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT, +- FLASH_REDBOOT_IMAGE_MAX_SIZE_g3}, +- { FLASH_iSCSI_BIOS_START_g3, IMG_TYPE_BIOS, +- FLASH_BIOS_IMAGE_MAX_SIZE_g3}, +- { FLASH_PXE_BIOS_START_g3, IMG_TYPE_PXE_BIOS, +- FLASH_BIOS_IMAGE_MAX_SIZE_g3}, +- { FLASH_FCoE_BIOS_START_g3, IMG_TYPE_FCOE_BIOS, +- FLASH_BIOS_IMAGE_MAX_SIZE_g3}, +- { FLASH_iSCSI_BACKUP_IMAGE_START_g3, IMG_TYPE_ISCSI_BACKUP, +- FLASH_IMAGE_MAX_SIZE_g3}, +- { FLASH_FCoE_PRIMARY_IMAGE_START_g3, IMG_TYPE_FCOE_FW_ACTIVE, +- FLASH_IMAGE_MAX_SIZE_g3}, +- { FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP, +- FLASH_IMAGE_MAX_SIZE_g3}, +- { FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW, +- FLASH_NCSI_IMAGE_MAX_SIZE_g3}, +- { FLASH_PHY_FW_START_g3, IMG_TYPE_PHY_FW, +- FLASH_PHY_FW_IMAGE_MAX_SIZE_g3} ++ int num_comp, hdr_size; ++ struct flash_section_info *fsec = NULL; ++ ++ struct flash_comp gen3_flash_types[] = { ++ { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE, ++ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_iSCSI}, ++ { FLASH_REDBOOT_START_g3, OPTYPE_REDBOOT, ++ FLASH_REDBOOT_IMAGE_MAX_SIZE_g3, IMAGE_BOOT_CODE}, ++ { FLASH_iSCSI_BIOS_START_g3, OPTYPE_BIOS, ++ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_ISCSI}, ++ { FLASH_PXE_BIOS_START_g3, OPTYPE_PXE_BIOS, ++ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_PXE}, ++ { FLASH_FCoE_BIOS_START_g3, OPTYPE_FCOE_BIOS, ++ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_FCoE}, ++ { FLASH_iSCSI_BACKUP_IMAGE_START_g3, OPTYPE_ISCSI_BACKUP, ++ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_iSCSI}, ++ { FLASH_FCoE_PRIMARY_IMAGE_START_g3, OPTYPE_FCOE_FW_ACTIVE, ++ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_FCoE}, ++ { FLASH_FCoE_BACKUP_IMAGE_START_g3, OPTYPE_FCOE_FW_BACKUP, ++ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_FCoE}, ++ { FLASH_NCSI_START_g3, OPTYPE_NCSI_FW, ++ FLASH_NCSI_IMAGE_MAX_SIZE_g3, IMAGE_NCSI}, ++ { FLASH_PHY_FW_START_g3, OPTYPE_PHY_FW, ++ FLASH_PHY_FW_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_PHY} + }; +- static const struct flash_comp gen2_flash_types[8] = { +- { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE, +- FLASH_IMAGE_MAX_SIZE_g2}, +- { FLASH_REDBOOT_START_g2, IMG_TYPE_REDBOOT, +- FLASH_REDBOOT_IMAGE_MAX_SIZE_g2}, +- { FLASH_iSCSI_BIOS_START_g2, IMG_TYPE_BIOS, +- FLASH_BIOS_IMAGE_MAX_SIZE_g2}, +- { FLASH_PXE_BIOS_START_g2, IMG_TYPE_PXE_BIOS, +- FLASH_BIOS_IMAGE_MAX_SIZE_g2}, +- { FLASH_FCoE_BIOS_START_g2, IMG_TYPE_FCOE_BIOS, +- FLASH_BIOS_IMAGE_MAX_SIZE_g2}, +- { FLASH_iSCSI_BACKUP_IMAGE_START_g2, IMG_TYPE_ISCSI_BACKUP, +- FLASH_IMAGE_MAX_SIZE_g2}, +- { FLASH_FCoE_PRIMARY_IMAGE_START_g2, IMG_TYPE_FCOE_FW_ACTIVE, +- FLASH_IMAGE_MAX_SIZE_g2}, +- { FLASH_FCoE_BACKUP_IMAGE_START_g2, IMG_TYPE_FCOE_FW_BACKUP, +- FLASH_IMAGE_MAX_SIZE_g2} ++ ++ struct flash_comp gen2_flash_types[] = { ++ { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, OPTYPE_ISCSI_ACTIVE, ++ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_iSCSI}, ++ { FLASH_REDBOOT_START_g2, OPTYPE_REDBOOT, ++ FLASH_REDBOOT_IMAGE_MAX_SIZE_g2, IMAGE_BOOT_CODE}, ++ { FLASH_iSCSI_BIOS_START_g2, OPTYPE_BIOS, ++ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_ISCSI}, ++ { FLASH_PXE_BIOS_START_g2, OPTYPE_PXE_BIOS, ++ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_PXE}, ++ { FLASH_FCoE_BIOS_START_g2, OPTYPE_FCOE_BIOS, ++ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_FCoE}, ++ { FLASH_iSCSI_BACKUP_IMAGE_START_g2, OPTYPE_ISCSI_BACKUP, ++ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_iSCSI}, ++ { FLASH_FCoE_PRIMARY_IMAGE_START_g2, OPTYPE_FCOE_FW_ACTIVE, ++ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_FCoE}, ++ { FLASH_FCoE_BACKUP_IMAGE_START_g2, OPTYPE_FCOE_FW_BACKUP, ++ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_FCoE} + }; + + if (adapter->generation == BE_GEN3) { +@@ -2754,22 +2958,37 @@ static int be_flash_data(struct be_adapter *adapter, + filehdr_size = sizeof(struct flash_file_hdr_g2); + num_comp = ARRAY_SIZE(gen2_flash_types); + } ++ /* Get flash section info*/ ++ fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); ++ if (!fsec) { ++ dev_err(&adapter->pdev->dev, ++ "Invalid Cookie. UFI corrupted ?\n"); ++ return -1; ++ } + for (i = 0; i < num_comp; i++) { +- if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) && +- memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) ++ if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type)) ++ continue; ++ ++ if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) && ++ memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) + continue; +- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW) { ++ ++ if (pflashcomp[i].optype == OPTYPE_PHY_FW) { + if (!phy_flashing_required(adapter)) + continue; + } +- if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) && +- (!be_flash_redboot(adapter, fw->data, +- pflashcomp[i].offset, pflashcomp[i].size, filehdr_size + +- (num_of_images * sizeof(struct image_hdr))))) ++ ++ hdr_size = filehdr_size + ++ (num_of_images * sizeof(struct image_hdr)); ++ ++ if ((pflashcomp[i].optype == OPTYPE_REDBOOT) && ++ (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset, ++ pflashcomp[i].size, hdr_size))) + continue; ++ ++ /* Flash the component */ + p = fw->data; +- p += filehdr_size + pflashcomp[i].offset +- + (num_of_images * sizeof(struct image_hdr)); ++ p += filehdr_size + pflashcomp[i].offset + img_hdrs_size; + if (p + pflashcomp[i].size > fw->data + fw->size) + return -1; + total_bytes = pflashcomp[i].size; +@@ -2780,12 +2999,12 @@ static int be_flash_data(struct be_adapter *adapter, + num_bytes = total_bytes; + total_bytes -= num_bytes; + if (!total_bytes) { +- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW) ++ if (pflashcomp[i].optype == OPTYPE_PHY_FW) + flash_op = FLASHROM_OPER_PHY_FLASH; + else + flash_op = FLASHROM_OPER_FLASH; + } else { +- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW) ++ if (pflashcomp[i].optype == OPTYPE_PHY_FW) + flash_op = FLASHROM_OPER_PHY_SAVE; + else + flash_op = FLASHROM_OPER_SAVE; +@@ -2797,7 +3016,7 @@ static int be_flash_data(struct be_adapter *adapter, + if (status) { + if ((status == ILLEGAL_IOCTL_REQ) && + (pflashcomp[i].optype == +- IMG_TYPE_PHY_FW)) ++ OPTYPE_PHY_FW)) + break; + dev_err(&adapter->pdev->dev, + "cmd to write to flash rom failed.\n"); +@@ -2982,7 +3201,7 @@ fw_exit: + return status; + } + +-static struct net_device_ops be_netdev_ops = { ++static const struct net_device_ops be_netdev_ops = { + .ndo_open = be_open, + .ndo_stop = be_close, + .ndo_start_xmit = be_xmit, +@@ -2996,13 +3215,16 @@ static struct net_device_ops be_netdev_ops = { + .ndo_set_vf_mac = be_set_vf_mac, + .ndo_set_vf_vlan = be_set_vf_vlan, + .ndo_set_vf_tx_rate = be_set_vf_tx_rate, +- .ndo_get_vf_config = be_get_vf_config ++ .ndo_get_vf_config = be_get_vf_config, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = be_netpoll, ++#endif + }; + + static void be_netdev_init(struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_rx_obj *rxo; ++ struct be_eq_obj *eqo; + int i; + + netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | +@@ -3017,20 +3239,18 @@ static void be_netdev_init(struct net_device *netdev) + netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + ++ netdev->priv_flags |= IFF_UNICAST_FLT; ++ + netdev->flags |= IFF_MULTICAST; + +- netif_set_gso_max_size(netdev, 65535); ++ netif_set_gso_max_size(netdev, 65535 - ETH_HLEN); + +- BE_SET_NETDEV_OPS(netdev, &be_netdev_ops); ++ netdev->netdev_ops = &be_netdev_ops; + + SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); + +- for_all_rx_queues(adapter, rxo, i) +- netif_napi_add(netdev, &rxo->rx_eq.napi, be_poll_rx, +- BE_NAPI_WEIGHT); +- +- netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc, +- BE_NAPI_WEIGHT); ++ for_all_evt_queues(adapter, eqo, i) ++ netif_napi_add(netdev, &eqo->napi, be_poll, BE_NAPI_WEIGHT); + } + + static void be_unmap_pci_bars(struct be_adapter *adapter) +@@ -3189,8 +3409,6 @@ static void __devexit be_remove(struct pci_dev *pdev) + if (!adapter) + return; + +- cancel_delayed_work_sync(&adapter->work); +- + unregister_netdev(adapter->netdev); + + be_clear(adapter); +@@ -3199,10 +3417,6 @@ static void __devexit be_remove(struct pci_dev *pdev) + + be_ctrl_cleanup(adapter); + +- be_sriov_disable(adapter); +- +- be_msix_disable(adapter); +- + pci_set_drvdata(pdev, NULL); + pci_release_regions(pdev); + pci_disable_device(pdev); +@@ -3210,7 +3424,13 @@ static void __devexit be_remove(struct pci_dev *pdev) + free_netdev(adapter->netdev); + } + +-static int be_get_config(struct be_adapter *adapter) ++bool be_is_wol_supported(struct be_adapter *adapter) ++{ ++ return ((adapter->wol_cap & BE_WOL_CAP) && ++ !be_is_wol_excluded(adapter)) ? true : false; ++} ++ ++static int be_get_initial_config(struct be_adapter *adapter) + { + int status; + +@@ -3220,18 +3440,40 @@ static int be_get_config(struct be_adapter *adapter) + return status; + + if (adapter->function_mode & FLEX10_MODE) +- adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/4; ++ adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8; + else + adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; + ++ if (be_physfn(adapter)) ++ adapter->max_pmac_cnt = BE_UC_PMAC_COUNT; ++ else ++ adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT; ++ ++ /* primary mac needs 1 pmac entry */ ++ adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1, ++ sizeof(u32), GFP_KERNEL); ++ if (!adapter->pmac_id) ++ return -ENOMEM; ++ + status = be_cmd_get_cntl_attributes(adapter); + if (status) + return status; + ++ status = be_cmd_get_acpi_wol_cap(adapter); ++ if (status) { ++ /* in case of a failure to get wol capabillities ++ * check the exclusion list to determine WOL capability */ ++ if (!be_is_wol_excluded(adapter)) ++ adapter->wol_cap |= BE_WOL_CAP; ++ } ++ ++ if (be_is_wol_supported(adapter)) ++ adapter->wol = true; ++ + return 0; + } + +-static int be_dev_family_check(struct be_adapter *adapter) ++static int be_dev_type_check(struct be_adapter *adapter) + { + struct pci_dev *pdev = adapter->pdev; + u32 sli_intf = 0, if_type; +@@ -3243,6 +3485,7 @@ static int be_dev_family_check(struct be_adapter *adapter) + break; + case BE_DEVICE_ID2: + case OC_DEVICE_ID2: ++ case OC_DEVICE_ID5: + adapter->generation = BE_GEN3; + break; + case OC_DEVICE_ID3: +@@ -3263,12 +3506,15 @@ static int be_dev_family_check(struct be_adapter *adapter) + default: + adapter->generation = 0; + } ++ ++ pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); ++ adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; + return 0; + } + + static int lancer_wait_ready(struct be_adapter *adapter) + { +-#define SLIPORT_READY_TIMEOUT 500 ++#define SLIPORT_READY_TIMEOUT 30 + u32 sliport_status; + int status = 0, i; + +@@ -3277,7 +3523,7 @@ static int lancer_wait_ready(struct be_adapter *adapter) + if (sliport_status & SLIPORT_STATUS_RDY_MASK) + break; + +- msleep(20); ++ msleep(1000); + } + + if (i == SLIPORT_READY_TIMEOUT) +@@ -3314,6 +3560,105 @@ static int lancer_test_and_set_rdy_state(struct be_adapter *adapter) + return status; + } + ++static void lancer_test_and_recover_fn_err(struct be_adapter *adapter) ++{ ++ int status; ++ u32 sliport_status; ++ ++ if (adapter->eeh_err || adapter->ue_detected) ++ return; ++ ++ sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); ++ ++ if (sliport_status & SLIPORT_STATUS_ERR_MASK) { ++ dev_err(&adapter->pdev->dev, ++ "Adapter in error state." ++ "Trying to recover.\n"); ++ ++ status = lancer_test_and_set_rdy_state(adapter); ++ if (status) ++ goto err; ++ ++ netif_device_detach(adapter->netdev); ++ ++ if (netif_running(adapter->netdev)) ++ be_close(adapter->netdev); ++ ++ be_clear(adapter); ++ ++ adapter->fw_timeout = false; ++ ++ status = be_setup(adapter); ++ if (status) ++ goto err; ++ ++ if (netif_running(adapter->netdev)) { ++ status = be_open(adapter->netdev); ++ if (status) ++ goto err; ++ } ++ ++ netif_device_attach(adapter->netdev); ++ ++ dev_err(&adapter->pdev->dev, ++ "Adapter error recovery succeeded\n"); ++ } ++ return; ++err: ++ dev_err(&adapter->pdev->dev, ++ "Adapter error recovery failed\n"); ++} ++ ++static void be_worker(struct work_struct *work) ++{ ++ struct be_adapter *adapter = ++ container_of(work, struct be_adapter, work.work); ++ struct be_rx_obj *rxo; ++ struct be_eq_obj *eqo; ++ int i; ++ ++ if (lancer_chip(adapter)) ++ lancer_test_and_recover_fn_err(adapter); ++ ++ be_detect_dump_ue(adapter); ++ ++ /* when interrupts are not yet enabled, just reap any pending ++ * mcc completions */ ++ if (!netif_running(adapter->netdev)) { ++ local_bh_disable(); ++ be_process_mcc(adapter); ++ local_bh_enable(); ++ goto reschedule; ++ } ++ ++ if (!adapter->stats_cmd_sent) { ++ if (lancer_chip(adapter)) ++ lancer_cmd_get_pport_stats(adapter, ++ &adapter->stats_cmd); ++ else ++ be_cmd_get_stats(adapter, &adapter->stats_cmd); ++ } ++ ++ for_all_rx_queues(adapter, rxo, i) { ++ if (rxo->rx_post_starved) { ++ rxo->rx_post_starved = false; ++ be_post_rx_frags(rxo, GFP_KERNEL); ++ } ++ } ++ ++ for_all_evt_queues(adapter, eqo, i) ++ be_eqd_update(adapter, eqo); ++ ++reschedule: ++ adapter->work_counter++; ++ schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); ++} ++ ++static bool be_reset_required(struct be_adapter *adapter) ++{ ++ return be_find_vfs(adapter, ENABLED) > 0 ? false : true; ++} ++ + static int __devinit be_probe(struct pci_dev *pdev, + const struct pci_device_id *pdev_id) + { +@@ -3330,7 +3675,7 @@ static int __devinit be_probe(struct pci_dev *pdev, + goto disable_dev; + pci_set_master(pdev); + +- netdev = alloc_etherdev_mq(sizeof(struct be_adapter), MAX_TX_QS); ++ netdev = alloc_etherdev_mqs(sizeof(*adapter), MAX_TX_QS, MAX_RX_QS); + if (netdev == NULL) { + status = -ENOMEM; + goto rel_reg; +@@ -3339,7 +3684,7 @@ static int __devinit be_probe(struct pci_dev *pdev, + adapter->pdev = pdev; + pci_set_drvdata(pdev, adapter); + +- status = be_dev_family_check(adapter); ++ status = be_dev_type_check(adapter); + if (status) + goto free_netdev; + +@@ -3357,16 +3702,17 @@ static int __devinit be_probe(struct pci_dev *pdev, + } + } + +- status = be_sriov_enable(adapter); +- if (status) +- goto free_netdev; +- + status = be_ctrl_init(adapter); + if (status) +- goto disable_sriov; ++ goto free_netdev; + + if (lancer_chip(adapter)) { +- status = lancer_test_and_set_rdy_state(adapter); ++ status = lancer_wait_ready(adapter); ++ if (!status) { ++ iowrite32(SLI_PORT_CONTROL_IP_MASK, ++ adapter->db + SLIPORT_CONTROL_OFFSET); ++ status = lancer_test_and_set_rdy_state(adapter); ++ } + if (status) { + dev_err(&pdev->dev, "Adapter in non recoverable error\n"); + goto ctrl_clean; +@@ -3385,17 +3731,11 @@ static int __devinit be_probe(struct pci_dev *pdev, + if (status) + goto ctrl_clean; + +- status = be_cmd_reset_function(adapter); +- if (status) +- goto ctrl_clean; +- +- status = be_stats_init(adapter); +- if (status) +- goto ctrl_clean; +- +- status = be_get_config(adapter); +- if (status) +- goto stats_clean; ++ if (be_reset_required(adapter)) { ++ status = be_cmd_reset_function(adapter); ++ if (status) ++ goto ctrl_clean; ++ } + + /* The INTR bit may be set in the card when probed by a kdump kernel + * after a crash. +@@ -3403,7 +3743,13 @@ static int __devinit be_probe(struct pci_dev *pdev, + if (!lancer_chip(adapter)) + be_intr_set(adapter, false); + +- be_msix_enable(adapter); ++ status = be_stats_init(adapter); ++ if (status) ++ goto ctrl_clean; ++ ++ status = be_get_initial_config(adapter); ++ if (status) ++ goto stats_clean; + + INIT_DELAYED_WORK(&adapter->work, be_worker); + adapter->rx_fc = adapter->tx_fc = true; +@@ -3417,9 +3763,9 @@ static int __devinit be_probe(struct pci_dev *pdev, + if (status != 0) + goto unsetup; + +- dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num); ++ dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev), ++ adapter->port_num); + +- schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); + return 0; + + unsetup: +@@ -3430,8 +3776,6 @@ stats_clean: + be_stats_cleanup(adapter); + ctrl_clean: + be_ctrl_cleanup(adapter); +-disable_sriov: +- be_sriov_disable(adapter); + free_netdev: + free_netdev(netdev); + pci_set_drvdata(pdev, NULL); +@@ -3449,7 +3793,6 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + +- cancel_delayed_work_sync(&adapter->work); + if (adapter->wol) + be_setup_wol(adapter, true); + +@@ -3461,7 +3804,6 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) + } + be_clear(adapter); + +- be_msix_disable(adapter); + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); +@@ -3483,7 +3825,6 @@ static int be_resume(struct pci_dev *pdev) + pci_set_power_state(pdev, 0); + pci_restore_state(pdev); + +- be_msix_enable(adapter); + /* tell fw we're ready to fire cmds */ + status = be_cmd_fw_init(adapter); + if (status) +@@ -3500,7 +3841,6 @@ static int be_resume(struct pci_dev *pdev) + if (adapter->wol) + be_setup_wol(adapter, false); + +- schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); + return 0; + } + +@@ -3550,6 +3890,11 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, + + pci_disable_device(pdev); + ++ /* The error could cause the FW to trigger a flash debug dump. ++ * Resetting the card while flash dump is in progress ++ * can cause it not to recover; wait for it to finish ++ */ ++ ssleep(30); + return PCI_ERS_RESULT_NEED_RESET; + } + +@@ -3560,6 +3905,8 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) + + dev_info(&adapter->pdev->dev, "EEH reset\n"); + adapter->eeh_err = false; ++ adapter->ue_detected = false; ++ adapter->fw_timeout = false; + + status = pci_enable_device(pdev); + if (status) +diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c +index ada234a..9e3df77 100644 +--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c ++++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c +@@ -5,7 +5,7 @@ + * Author: Andy Fleming + * Modifier: Sandeep Gopalpet + * +- * Copyright 2002-2004, 2008-2009 Freescale Semiconductor, Inc. ++ * Copyright 2002-2004, 2008-2009, 2012 Freescale Semiconductor, Inc. + * + * Based on gianfar_mii.c and ucc_geth_mii.c (Li Yang, Kim Phillips) + * +@@ -50,8 +50,13 @@ + struct fsl_pq_mdio_priv { + void __iomem *map; + struct fsl_pq_mdio __iomem *regs; ++ struct mutex mdio_lock; + }; + ++/* pointer to bus, to be used by the fsl_pq_mdio locking functions when called ++ * with a null parameter */ ++struct mii_bus *fsl_pq_mdio_bus; ++ + /* + * Write value to the PHY at mii_id at register regnum, + * on the bus attached to the local interface, which may be different from the +@@ -62,7 +67,7 @@ struct fsl_pq_mdio_priv { + * controlling the external PHYs, for example. + */ + int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id, +- int regnum, u16 value) ++ int regnum, u16 value) + { + /* Set the PHY address and the register address we want to write */ + out_be32(®s->miimadd, (mii_id << 8) | regnum); +@@ -87,8 +92,8 @@ int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id, + * and are always tied to the local mdio pins, which may not be the + * same as system mdio bus, used for controlling the external PHYs, for eg. + */ +-int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, +- int mii_id, int regnum) ++int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, int mii_id, ++ int regnum) + { + u16 value; + +@@ -116,28 +121,63 @@ static struct fsl_pq_mdio __iomem *fsl_pq_mdio_get_regs(struct mii_bus *bus) + return priv->regs; + } + ++void fsl_pq_mdio_lock(struct mii_bus *bus) ++{ ++ struct fsl_pq_mdio_priv *priv; ++ ++ priv = (bus) ? bus->priv : fsl_pq_mdio_bus->priv; ++ ++ mutex_lock(&priv->mdio_lock); ++} ++EXPORT_SYMBOL(fsl_pq_mdio_lock); ++ ++void fsl_pq_mdio_unlock(struct mii_bus *bus) ++{ ++ struct fsl_pq_mdio_priv *priv; ++ ++ priv = (bus) ? bus->priv : fsl_pq_mdio_bus->priv; ++ ++ mutex_unlock(&priv->mdio_lock); ++} ++EXPORT_SYMBOL(fsl_pq_mdio_unlock); ++ + /* + * Write value to the PHY at mii_id at register regnum, + * on the bus, waiting until the write is done before returning. + */ +-int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) ++int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int devad, int regnum, ++ u16 value) + { + struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus); ++ int result; ++ ++ fsl_pq_mdio_lock(bus); + + /* Write to the local MII regs */ +- return fsl_pq_local_mdio_write(regs, mii_id, regnum, value); ++ result = fsl_pq_local_mdio_write(regs, mii_id, regnum, value); ++ ++ fsl_pq_mdio_unlock(bus); ++ ++ return result; + } + + /* + * Read the bus for PHY at addr mii_id, register regnum, and + * return the value. Clears miimcom first. + */ +-int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ++int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int devad, int regnum) + { + struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus); ++ int result; ++ ++ fsl_pq_mdio_lock(bus); + + /* Read the local MII regs */ +- return fsl_pq_local_mdio_read(regs, mii_id, regnum); ++ result = fsl_pq_local_mdio_read(regs, mii_id, regnum); ++ ++ fsl_pq_mdio_unlock(bus); ++ ++ return result; + } + + /* Reset the MIIM registers, and wait for the bus to free */ +@@ -183,10 +223,28 @@ void fsl_pq_mdio_bus_name(char *name, struct device_node *np) + } + EXPORT_SYMBOL_GPL(fsl_pq_mdio_bus_name); + ++/* Scan the bus in reverse, looking for an empty spot */ ++static int fsl_pq_mdio_find_free(struct mii_bus *new_bus) ++{ ++ int i; ++ ++ for (i = PHY_MAX_ADDR; i > 0; i--) { ++ u32 phy_id; ++ ++ if (get_phy_id(new_bus, i, &phy_id)) ++ return -1; ++ ++ if (phy_id == 0xffffffff) ++ break; ++ } ++ ++ return i; ++} + ++ ++#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) + static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct device_node *np) + { +-#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) + struct gfar __iomem *enet_regs; + + /* +@@ -202,15 +260,15 @@ static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct devi + } else if (of_device_is_compatible(np, "fsl,etsec2-mdio") || + of_device_is_compatible(np, "fsl,etsec2-tbi")) { + return of_iomap(np, 1); +- } +-#endif +- return NULL; ++ } else ++ return NULL; + } ++#endif + + ++#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) + static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) + { +-#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) + struct device_node *np = NULL; + int err = 0; + +@@ -243,10 +301,9 @@ static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) + return err; + else + return -EINVAL; +-#else +- return -ENODEV; +-#endif + } ++#endif ++ + + static int fsl_pq_mdio_probe(struct platform_device *ofdev) + { +@@ -266,6 +323,8 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) + if (!priv) + return -ENOMEM; + ++ mutex_init(&priv->mdio_lock); ++ + new_bus = mdiobus_alloc(); + if (!new_bus) { + err = -ENOMEM; +@@ -301,6 +360,7 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) + + if (of_device_is_compatible(np, "fsl,gianfar-mdio") || + of_device_is_compatible(np, "fsl,gianfar-tbi") || ++ of_device_is_compatible(np, "fsl,fman-mdio") || + of_device_is_compatible(np, "fsl,ucc-mdio") || + of_device_is_compatible(np, "ucc_geth_phy")) + map -= offsetof(struct fsl_pq_mdio, miimcfg); +@@ -322,13 +382,19 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) + of_device_is_compatible(np, "fsl,etsec2-mdio") || + of_device_is_compatible(np, "fsl,etsec2-tbi") || + of_device_is_compatible(np, "gianfar")) { ++#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) + tbipa = get_gfar_tbipa(regs, np); + if (!tbipa) { + err = -EINVAL; + goto err_free_irqs; + } ++#else ++ err = -ENODEV; ++ goto err_free_irqs; ++#endif + } else if (of_device_is_compatible(np, "fsl,ucc-mdio") || + of_device_is_compatible(np, "ucc_geth_phy")) { ++#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) + u32 id; + static u32 mii_mng_master; + +@@ -341,6 +407,18 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) + mii_mng_master = id; + ucc_set_qe_mux_mii_mng(id - 1); + } ++#else ++ err = -ENODEV; ++ goto err_free_irqs; ++#endif ++ } else if (of_device_is_compatible(np, "fsl,fman-mdio")) { ++#ifdef CONFIG_FSL_FMAN ++ pr_debug("fsl_pq_mdio: found fsl,fman-mdio\n"); ++ tbiaddr = 5; ++#else ++ err = -ENODEV; ++ goto err_free_irqs; ++#endif + } else { + err = -ENODEV; + goto err_free_irqs; +@@ -356,15 +434,32 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) + + if (prop) + tbiaddr = *prop; ++ } + +- if (tbiaddr == -1) { +- err = -EBUSY; +- goto err_free_irqs; +- } else { +- out_be32(tbipa, tbiaddr); +- } ++ if (tbiaddr == -1) { ++#ifndef CONFIG_FSL_FMAN ++ out_be32(tbipa, 0); ++#endif ++ ++ tbiaddr = fsl_pq_mdio_find_free(new_bus); + } + ++ /* ++ * We define TBIPA at 0 to be illegal, opting to fail for boards that ++ * have PHYs at 1-31, rather than change tbipa and rescan. ++ */ ++ if (tbiaddr == 0) { ++ err = -EBUSY; ++ ++ goto err_free_irqs; ++ } ++ ++#ifndef CONFIG_FSL_FMAN ++ out_be32(tbipa, tbiaddr); ++#endif ++ ++ fsl_pq_mdio_bus = new_bus; ++ + err = of_mdiobus_register(new_bus, np); + if (err) { + printk (KERN_ERR "%s: Cannot register as MDIO bus\n", +@@ -428,6 +523,9 @@ static struct of_device_id fsl_pq_mdio_match[] = { + { + .compatible = "fsl,etsec2-mdio", + }, ++ { ++ .compatible = "fsl,fman-mdio", ++ }, + {}, + }; + MODULE_DEVICE_TABLE(of, fsl_pq_mdio_match); +diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.h b/drivers/net/ethernet/freescale/fsl_pq_mdio.h +index bd17a2a..898a042 100644 +--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.h ++++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.h +@@ -41,12 +41,17 @@ struct fsl_pq_mdio { + u8 res4[2728]; + } __packed; + +-int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum); +-int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value); ++ ++int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int devad, int regnum); ++int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int devad, int regnum, ++ u16 value); + int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id, +- int regnum, u16 value); +-int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, int mii_id, int regnum); ++ int regnum, u16 value); ++int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, int mii_id, ++ int regnum); + int __init fsl_pq_mdio_init(void); + void fsl_pq_mdio_exit(void); + void fsl_pq_mdio_bus_name(char *name, struct device_node *np); ++void fsl_pq_mdio_lock(struct mii_bus *bus); ++void fsl_pq_mdio_unlock(struct mii_bus *bus); + #endif /* FSL_PQ_MDIO_H */ +diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig +index 7621316..9b696f7 100644 +--- a/drivers/net/ethernet/intel/Kconfig ++++ b/drivers/net/ethernet/intel/Kconfig +@@ -90,9 +90,24 @@ config E1000E + To compile this driver as a module, choose M here. The module + will be called e1000e. + ++config E1000E_PTP ++ bool "PTP Hardware Clock (PHC)" ++ default n ++ depends on E1000E && EXPERIMENTAL ++ select PPS ++ select PTP_1588_CLOCK ++ ---help--- ++ Say Y here if you want to use PTP Hardware Clock (PHC) in the ++ driver. Only the basic clock operations have been implemented. ++ ++ Every timestamp and clock read operations must consult the ++ overflow counter to form a correct time value. ++ + config IGB + tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support" + depends on PCI ++ select I2C ++ select I2C_ALGOBIT + ---help--- + This driver supports Intel(R) 82575/82576 gigabit ethernet family of + adapters. For more information on how to identify your adapter, go +@@ -111,6 +126,17 @@ config IGB + To compile this driver as a module, choose M here. The module + will be called igb. + ++config IGB_HWMON ++ bool "Intel(R) PCI-Express Gigabit adapters HWMON support" ++ default y ++ depends on IGB && HWMON && !(IGB=y && HWMON=m) ++ ---help--- ++ Say Y if you want to expose thermal sensor data on Intel devices. ++ ++ Some of our devices contain thermal sensors, both external and internal. ++ This data is available via the hwmon sysfs interface and exposes ++ the onboard sensors. ++ + config IGB_DCA + bool "Direct Cache Access (DCA) Support" + default y +@@ -120,6 +146,19 @@ config IGB_DCA + driver. DCA is a method for warming the CPU cache before data + is used, with the intent of lessening the impact of cache misses. + ++config IGB_PTP ++ bool "PTP Hardware Clock (PHC)" ++ default n ++ depends on IGB && EXPERIMENTAL ++ select PPS ++ select PTP_1588_CLOCK ++ ---help--- ++ Say Y here if you want to use PTP Hardware Clock (PHC) in the ++ driver. Only the basic clock operations have been implemented. ++ ++ Every timestamp and clock read operations must consult the ++ overflow counter to form a correct time value. ++ + config IGBVF + tristate "Intel(R) 82576 Virtual Function Ethernet support" + depends on PCI +diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c +index 5a2fdf7..85e42d7 100644 +--- a/drivers/net/ethernet/intel/e100.c ++++ b/drivers/net/ethernet/intel/e100.c +@@ -1233,20 +1233,35 @@ static const struct firmware *e100_request_firmware(struct nic *nic) + const struct firmware *fw = nic->fw; + u8 timer, bundle, min_size; + int err = 0; ++ bool required = false; + + /* do not load u-code for ICH devices */ + if (nic->flags & ich) + return NULL; + +- /* Search for ucode match against h/w revision */ +- if (nic->mac == mac_82559_D101M) ++ /* Search for ucode match against h/w revision ++ * ++ * Based on comments in the source code for the FreeBSD fxp ++ * driver, the FIRMWARE_D102E ucode includes both CPUSaver and ++ * ++ * "fixes for bugs in the B-step hardware (specifically, bugs ++ * with Inline Receive)." ++ * ++ * So we must fail if it cannot be loaded. ++ * ++ * The other microcode files are only required for the optional ++ * CPUSaver feature. Nice to have, but no reason to fail. ++ */ ++ if (nic->mac == mac_82559_D101M) { + fw_name = FIRMWARE_D101M; +- else if (nic->mac == mac_82559_D101S) ++ } else if (nic->mac == mac_82559_D101S) { + fw_name = FIRMWARE_D101S; +- else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) ++ } else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) { + fw_name = FIRMWARE_D102E; +- else /* No ucode on other devices */ ++ required = true; ++ } else { /* No ucode on other devices */ + return NULL; ++ } + + /* If the firmware has not previously been loaded, request a pointer + * to it. If it was previously loaded, we are reinitializing the +@@ -1257,10 +1272,14 @@ static const struct firmware *e100_request_firmware(struct nic *nic) + err = request_firmware(&fw, fw_name, &nic->pdev->dev); + + if (err) { +- netif_err(nic, probe, nic->netdev, +- "Failed to load firmware \"%s\": %d\n", +- fw_name, err); +- return ERR_PTR(err); ++ if (required) { ++ return ERR_PTR(err); ++ } else { ++ netif_info(nic, probe, nic->netdev, ++ "CPUSaver disabled. Needs \"%s\": %d\n", ++ fw_name, err); ++ return NULL; ++ } + } + + /* Firmware should be precisely UCODE_SIZE (words) plus three bytes +diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c +index e1159e5..ff2d806 100644 +--- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c ++++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel PRO/1000 Linux driver +- Copyright(c) 1999 - 2011 Intel Corporation. ++ Copyright(c) 1999 - 2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -26,82 +26,20 @@ + + *******************************************************************************/ + +-/* +- * 80003ES2LAN Gigabit Ethernet Controller (Copper) ++/* 80003ES2LAN Gigabit Ethernet Controller (Copper) + * 80003ES2LAN Gigabit Ethernet Controller (Serdes) + */ + + #include "e1000.h" + +-#define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL 0x00 +-#define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL 0x02 +-#define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL 0x10 +-#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE 0x1F +- +-#define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008 +-#define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800 +-#define E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING 0x0010 +- +-#define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004 +-#define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000 +-#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000 +- +-#define E1000_KMRNCTRLSTA_OPMODE_MASK 0x000C +-#define E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO 0x0004 +- +-#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */ +-#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000 +- +-#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN 0x8 +-#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN 0x9 +- +-/* GG82563 PHY Specific Status Register (Page 0, Register 16 */ +-#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Reversal Disab. */ +-#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060 +-#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI */ +-#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX */ +-#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Auto crossover */ +- +-/* PHY Specific Control Register 2 (Page 0, Register 26) */ +-#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 +- /* 1=Reverse Auto-Negotiation */ +- +-/* MAC Specific Control Register (Page 2, Register 21) */ +-/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */ +-#define GG82563_MSCR_TX_CLK_MASK 0x0007 +-#define GG82563_MSCR_TX_CLK_10MBPS_2_5 0x0004 +-#define GG82563_MSCR_TX_CLK_100MBPS_25 0x0005 +-#define GG82563_MSCR_TX_CLK_1000MBPS_25 0x0007 +- +-#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */ +- +-/* DSP Distance Register (Page 5, Register 26) */ +-#define GG82563_DSPD_CABLE_LENGTH 0x0007 /* 0 = <50M +- 1 = 50-80M +- 2 = 80-110M +- 3 = 110-140M +- 4 = >140M */ +- +-/* Kumeran Mode Control Register (Page 193, Register 16) */ +-#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 +- +-/* Max number of times Kumeran read/write should be validated */ +-#define GG82563_MAX_KMRN_RETRY 0x5 +- +-/* Power Management Control Register (Page 193, Register 20) */ +-#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 +- /* 1=Enable SERDES Electrical Idle */ +- +-/* In-Band Control Register (Page 194, Register 18) */ +-#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding */ +- +-/* +- * A table for the GG82563 cable length where the range is defined ++/* A table for the GG82563 cable length where the range is defined + * with a lower bound at "index" and the upper bound at + * "index + 5". + */ + static const u16 e1000_gg82563_cable_length_table[] = { +- 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF }; ++ 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF ++}; ++ + #define GG82563_CABLE_LENGTH_TABLE_SIZE \ + ARRAY_SIZE(e1000_gg82563_cable_length_table) + +@@ -112,11 +50,10 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw); + static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw); + static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw); + static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex); +-static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw); +-static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, +- u16 *data); +-static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, +- u16 data); ++static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, ++ u16 *data); ++static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, ++ u16 data); + static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw); + + /** +@@ -129,17 +66,17 @@ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw) + s32 ret_val; + + if (hw->phy.media_type != e1000_media_type_copper) { +- phy->type = e1000_phy_none; ++ phy->type = e1000_phy_none; + return 0; + } else { + phy->ops.power_up = e1000_power_up_phy_copper; + phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan; + } + +- phy->addr = 1; +- phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; +- phy->reset_delay_us = 100; +- phy->type = e1000_phy_gg82563; ++ phy->addr = 1; ++ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; ++ phy->reset_delay_us = 100; ++ phy->type = e1000_phy_gg82563; + + /* This can only be done after all function pointers are setup. */ + ret_val = e1000e_get_phy_id(hw); +@@ -161,19 +98,19 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) + u32 eecd = er32(EECD); + u16 size; + +- nvm->opcode_bits = 8; +- nvm->delay_usec = 1; ++ nvm->opcode_bits = 8; ++ nvm->delay_usec = 1; + switch (nvm->override) { + case e1000_nvm_override_spi_large: +- nvm->page_size = 32; ++ nvm->page_size = 32; + nvm->address_bits = 16; + break; + case e1000_nvm_override_spi_small: +- nvm->page_size = 8; ++ nvm->page_size = 8; + nvm->address_bits = 8; + break; + default: +- nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; ++ nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; + nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; + break; + } +@@ -181,10 +118,9 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) + nvm->type = e1000_nvm_eeprom_spi; + + size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> +- E1000_EECD_SIZE_EX_SHIFT); ++ E1000_EECD_SIZE_EX_SHIFT); + +- /* +- * Added to a constant, "size" becomes the left-shift value ++ /* Added to a constant, "size" becomes the left-shift value + * for setting word_size. + */ + size += NVM_WORD_SIZE_BASE_SHIFT; +@@ -192,7 +128,7 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) + /* EEPROM access above 16k is unsupported */ + if (size > 14) + size = 14; +- nvm->word_size = 1 << size; ++ nvm->word_size = 1 << size; + + return 0; + } +@@ -201,19 +137,23 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) + * e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs. + * @hw: pointer to the HW structure + **/ +-static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter) ++static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw) + { +- struct e1000_hw *hw = &adapter->hw; + struct e1000_mac_info *mac = &hw->mac; +- struct e1000_mac_operations *func = &mac->ops; + +- /* Set media type */ +- switch (adapter->pdev->device) { ++ /* Set media type and media-dependent function pointers */ ++ switch (hw->adapter->pdev->device) { + case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: + hw->phy.media_type = e1000_media_type_internal_serdes; ++ mac->ops.check_for_link = e1000e_check_for_serdes_link; ++ mac->ops.setup_physical_interface = ++ e1000e_setup_fiber_serdes_link; + break; + default: + hw->phy.media_type = e1000_media_type_copper; ++ mac->ops.check_for_link = e1000e_check_for_copper_link; ++ mac->ops.setup_physical_interface = ++ e1000_setup_copper_link_80003es2lan; + break; + } + +@@ -224,31 +164,10 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter) + /* FWSM register */ + mac->has_fwsm = true; + /* ARC supported; valid only if manageability features are enabled. */ +- mac->arc_subsystem_valid = +- (er32(FWSM) & E1000_FWSM_MODE_MASK) +- ? true : false; ++ mac->arc_subsystem_valid = !!(er32(FWSM) & E1000_FWSM_MODE_MASK); + /* Adaptive IFS not supported */ + mac->adaptive_ifs = false; + +- /* check for link */ +- switch (hw->phy.media_type) { +- case e1000_media_type_copper: +- func->setup_physical_interface = e1000_setup_copper_link_80003es2lan; +- func->check_for_link = e1000e_check_for_copper_link; +- break; +- case e1000_media_type_fiber: +- func->setup_physical_interface = e1000e_setup_fiber_serdes_link; +- func->check_for_link = e1000e_check_for_fiber_link; +- break; +- case e1000_media_type_internal_serdes: +- func->setup_physical_interface = e1000e_setup_fiber_serdes_link; +- func->check_for_link = e1000e_check_for_serdes_link; +- break; +- default: +- return -E1000_ERR_CONFIG; +- break; +- } +- + /* set lan id for port to determine which phy lock to use */ + hw->mac.ops.set_lan_id(hw); + +@@ -260,7 +179,7 @@ static s32 e1000_get_variants_80003es2lan(struct e1000_adapter *adapter) + struct e1000_hw *hw = &adapter->hw; + s32 rc; + +- rc = e1000_init_mac_params_80003es2lan(adapter); ++ rc = e1000_init_mac_params_80003es2lan(hw); + if (rc) + return rc; + +@@ -304,7 +223,7 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw) + } + + /** +- * e1000_acquire_mac_csr_80003es2lan - Acquire rights to access Kumeran register ++ * e1000_acquire_mac_csr_80003es2lan - Acquire right to access Kumeran register + * @hw: pointer to the HW structure + * + * Acquire the semaphore to access the Kumeran interface. +@@ -320,7 +239,7 @@ static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw) + } + + /** +- * e1000_release_mac_csr_80003es2lan - Release rights to access Kumeran Register ++ * e1000_release_mac_csr_80003es2lan - Release right to access Kumeran Register + * @hw: pointer to the HW structure + * + * Release the semaphore used to access the Kumeran interface +@@ -392,8 +311,7 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) + if (!(swfw_sync & (fwmask | swmask))) + break; + +- /* +- * Firmware currently using resource (fwmask) ++ /* Firmware currently using resource (fwmask) + * or other software thread using resource (swmask) + */ + e1000e_put_hw_semaphore(hw); +@@ -459,8 +377,7 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, + if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { + page_select = GG82563_PHY_PAGE_SELECT; + } else { +- /* +- * Use Alternative Page Select register to access ++ /* Use Alternative Page Select register to access + * registers 30 and 31 + */ + page_select = GG82563_PHY_PAGE_SELECT_ALT; +@@ -473,34 +390,32 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, + return ret_val; + } + +- if (hw->dev_spec.e80003es2lan.mdic_wa_enable == true) { +- /* +- * The "ready" bit in the MDIC register may be incorrectly set ++ if (hw->dev_spec.e80003es2lan.mdic_wa_enable) { ++ /* The "ready" bit in the MDIC register may be incorrectly set + * before the device has completed the "Page Select" MDI + * transaction. So we wait 200us after each MDI command... + */ +- udelay(200); ++ usleep_range(200, 400); + + /* ...and verify the command was successful. */ + ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); + + if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { +- ret_val = -E1000_ERR_PHY; + e1000_release_phy_80003es2lan(hw); +- return ret_val; ++ return -E1000_ERR_PHY; + } + +- udelay(200); ++ usleep_range(200, 400); + + ret_val = e1000e_read_phy_reg_mdic(hw, +- MAX_PHY_REG_ADDRESS & offset, +- data); ++ MAX_PHY_REG_ADDRESS & offset, ++ data); + +- udelay(200); ++ usleep_range(200, 400); + } else { + ret_val = e1000e_read_phy_reg_mdic(hw, +- MAX_PHY_REG_ADDRESS & offset, +- data); ++ MAX_PHY_REG_ADDRESS & offset, ++ data); + } + + e1000_release_phy_80003es2lan(hw); +@@ -531,8 +446,7 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, + if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { + page_select = GG82563_PHY_PAGE_SELECT; + } else { +- /* +- * Use Alternative Page Select register to access ++ /* Use Alternative Page Select register to access + * registers 30 and 31 + */ + page_select = GG82563_PHY_PAGE_SELECT_ALT; +@@ -545,13 +459,12 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, + return ret_val; + } + +- if (hw->dev_spec.e80003es2lan.mdic_wa_enable == true) { +- /* +- * The "ready" bit in the MDIC register may be incorrectly set ++ if (hw->dev_spec.e80003es2lan.mdic_wa_enable) { ++ /* The "ready" bit in the MDIC register may be incorrectly set + * before the device has completed the "Page Select" MDI + * transaction. So we wait 200us after each MDI command... + */ +- udelay(200); ++ usleep_range(200, 400); + + /* ...and verify the command was successful. */ + ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); +@@ -561,17 +474,17 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, + return -E1000_ERR_PHY; + } + +- udelay(200); ++ usleep_range(200, 400); + + ret_val = e1000e_write_phy_reg_mdic(hw, +- MAX_PHY_REG_ADDRESS & offset, +- data); ++ MAX_PHY_REG_ADDRESS & ++ offset, data); + +- udelay(200); ++ usleep_range(200, 400); + } else { + ret_val = e1000e_write_phy_reg_mdic(hw, +- MAX_PHY_REG_ADDRESS & offset, +- data); ++ MAX_PHY_REG_ADDRESS & ++ offset, data); + } + + e1000_release_phy_80003es2lan(hw); +@@ -636,8 +549,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) + u16 phy_data; + bool link; + +- /* +- * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI ++ /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI + * forced whenever speed and duplex are forced. + */ + ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); +@@ -651,33 +563,31 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) + + e_dbg("GG82563 PSCR: %X\n", phy_data); + +- ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); ++ ret_val = e1e_rphy(hw, MII_BMCR, &phy_data); + if (ret_val) + return ret_val; + + e1000e_phy_force_speed_duplex_setup(hw, &phy_data); + + /* Reset the phy to commit changes. */ +- phy_data |= MII_CR_RESET; ++ phy_data |= BMCR_RESET; + +- ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); ++ ret_val = e1e_wphy(hw, MII_BMCR, phy_data); + if (ret_val) + return ret_val; + + udelay(1); + + if (hw->phy.autoneg_wait_to_complete) { +- e_dbg("Waiting for forced speed/duplex link " +- "on GG82563 phy.\n"); ++ e_dbg("Waiting for forced speed/duplex link on GG82563 phy.\n"); + + ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, +- 100000, &link); ++ 100000, &link); + if (ret_val) + return ret_val; + + if (!link) { +- /* +- * We didn't get link. ++ /* We didn't get link. + * Reset the DSP and cross our fingers. + */ + ret_val = e1000e_phy_reset_dsp(hw); +@@ -687,7 +597,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) + + /* Try once more */ + ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, +- 100000, &link); ++ 100000, &link); + if (ret_val) + return ret_val; + } +@@ -696,8 +606,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) + if (ret_val) + return ret_val; + +- /* +- * Resetting the phy means we need to verify the TX_CLK corresponds ++ /* Resetting the phy means we need to verify the TX_CLK corresponds + * to the link speed. 10Mbps -> 2.5MHz, else 25MHz. + */ + phy_data &= ~GG82563_MSCR_TX_CLK_MASK; +@@ -706,8 +615,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) + else + phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25; + +- /* +- * In addition, we must re-enable CRS on Tx for both half and full ++ /* In addition, we must re-enable CRS on Tx for both half and full + * duplex. + */ + phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; +@@ -726,27 +634,24 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) + static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw) + { + struct e1000_phy_info *phy = &hw->phy; +- s32 ret_val = 0; ++ s32 ret_val; + u16 phy_data, index; + + ret_val = e1e_rphy(hw, GG82563_PHY_DSP_DISTANCE, &phy_data); + if (ret_val) +- goto out; ++ return ret_val; + + index = phy_data & GG82563_DSPD_CABLE_LENGTH; + +- if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5) { +- ret_val = -E1000_ERR_PHY; +- goto out; +- } ++ if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5) ++ return -E1000_ERR_PHY; + + phy->min_cable_length = e1000_gg82563_cable_length_table[index]; + phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5]; + + phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; + +-out: +- return ret_val; ++ return 0; + } + + /** +@@ -763,14 +668,12 @@ static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, + s32 ret_val; + + if (hw->phy.media_type == e1000_media_type_copper) { +- ret_val = e1000e_get_speed_and_duplex_copper(hw, +- speed, +- duplex); ++ ret_val = e1000e_get_speed_and_duplex_copper(hw, speed, duplex); + hw->phy.ops.cfg_on_link_up(hw); + } else { + ret_val = e1000e_get_speed_and_duplex_fiber_serdes(hw, +- speed, +- duplex); ++ speed, ++ duplex); + } + + return ret_val; +@@ -786,9 +689,9 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) + { + u32 ctrl; + s32 ret_val; ++ u16 kum_reg_data; + +- /* +- * Prevent the PCI-E bus from sticking if there is no TLP connection ++ /* Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ + ret_val = e1000e_disable_pcie_master(hw); +@@ -807,10 +710,23 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) + ctrl = er32(CTRL); + + ret_val = e1000_acquire_phy_80003es2lan(hw); ++ if (ret_val) ++ return ret_val; ++ + e_dbg("Issuing a global reset to MAC\n"); + ew32(CTRL, ctrl | E1000_CTRL_RST); + e1000_release_phy_80003es2lan(hw); + ++ /* Disable IBIST slave mode (far-end loopback) */ ++ ret_val = ++ e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, ++ &kum_reg_data); ++ if (ret_val) ++ return ret_val; ++ kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; ++ e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, ++ kum_reg_data); ++ + ret_val = e1000e_get_auto_rd_done(hw); + if (ret_val) + /* We don't want to continue accessing MAC registers. */ +@@ -820,9 +736,7 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) + ew32(IMC, 0xffffffff); + er32(ICR); + +- ret_val = e1000_check_alt_mac_addr_generic(hw); +- +- return ret_val; ++ return e1000_check_alt_mac_addr_generic(hw); + } + + /** +@@ -842,10 +756,10 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) + e1000_initialize_hw_bits_80003es2lan(hw); + + /* Initialize identification LED */ +- ret_val = e1000e_id_led_init(hw); ++ ret_val = mac->ops.id_led_init(hw); ++ /* An error is not fatal and we should not stop init due to this */ + if (ret_val) + e_dbg("Error initializing identification LED\n"); +- /* This is not fatal and we should not stop init due to this */ + + /* Disabling VLAN filtering */ + e_dbg("Initializing the IEEE VLAN\n"); +@@ -860,7 +774,9 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + + /* Setup link and flow control */ +- ret_val = e1000e_setup_link(hw); ++ ret_val = mac->ops.setup_link(hw); ++ if (ret_val) ++ return ret_val; + + /* Disable IBIST slave mode (far-end loopback) */ + e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, +@@ -871,14 +787,14 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) + + /* Set the transmit descriptor write-back policy */ + reg_data = er32(TXDCTL(0)); +- reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | +- E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC; ++ reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | ++ E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); + ew32(TXDCTL(0), reg_data); + + /* ...for both queues. */ + reg_data = er32(TXDCTL(1)); +- reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | +- E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC; ++ reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | ++ E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); + ew32(TXDCTL(1), reg_data); + + /* Enable retransmit on late collisions */ +@@ -905,18 +821,16 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) + /* default to true to enable the MDIC W/A */ + hw->dev_spec.e80003es2lan.mdic_wa_enable = true; + +- ret_val = e1000_read_kmrn_reg_80003es2lan(hw, +- E1000_KMRNCTRLSTA_OFFSET >> +- E1000_KMRNCTRLSTA_OFFSET_SHIFT, +- &i); ++ ret_val = ++ e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET >> ++ E1000_KMRNCTRLSTA_OFFSET_SHIFT, &i); + if (!ret_val) { + if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) == +- E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO) ++ E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO) + hw->dev_spec.e80003es2lan.mdic_wa_enable = false; + } + +- /* +- * Clear all of the statistics registers (clear on read). It is ++ /* Clear all of the statistics registers (clear on read). It is + * important that we do this after we have tried to establish link + * because the symbol error count will increment wildly if there + * is no link. +@@ -948,7 +862,7 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw) + + /* Transmit Arbitration Control 0 */ + reg = er32(TARC(0)); +- reg &= ~(0xF << 27); /* 30:27 */ ++ reg &= ~(0xF << 27); /* 30:27 */ + if (hw->phy.media_type != e1000_media_type_copper) + reg &= ~(1 << 20); + ew32(TARC(0), reg); +@@ -960,6 +874,13 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw) + else + reg |= (1 << 28); + ew32(TARC(1), reg); ++ ++ /* Disable IPv6 extension header parsing because some malformed ++ * IPv6 headers can hang the Rx. ++ */ ++ reg = er32(RFCTL); ++ reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); ++ ew32(RFCTL, reg); + } + + /** +@@ -972,7 +893,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) + { + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; +- u32 ctrl_ext; ++ u32 reg; + u16 data; + + ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data); +@@ -987,8 +908,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) + if (ret_val) + return ret_val; + +- /* +- * Options: ++ /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode +@@ -1014,8 +934,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) + break; + } + +- /* +- * Options: ++ /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled +@@ -1030,29 +949,26 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) + return ret_val; + + /* SW Reset the PHY so all changes take effect */ +- ret_val = e1000e_commit_phy(hw); ++ ret_val = hw->phy.ops.commit(hw); + if (ret_val) { + e_dbg("Error Resetting the PHY\n"); + return ret_val; + } + + /* Bypass Rx and Tx FIFO's */ +- ret_val = e1000_write_kmrn_reg_80003es2lan(hw, +- E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL, +- E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | +- E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); ++ reg = E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL; ++ data = (E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | ++ E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); ++ ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data); + if (ret_val) + return ret_val; + +- ret_val = e1000_read_kmrn_reg_80003es2lan(hw, +- E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, +- &data); ++ reg = E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE; ++ ret_val = e1000_read_kmrn_reg_80003es2lan(hw, reg, &data); + if (ret_val) + return ret_val; + data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE; +- ret_val = e1000_write_kmrn_reg_80003es2lan(hw, +- E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, +- data); ++ ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data); + if (ret_val) + return ret_val; + +@@ -1065,20 +981,19 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) + if (ret_val) + return ret_val; + +- ctrl_ext = er32(CTRL_EXT); +- ctrl_ext &= ~(E1000_CTRL_EXT_LINK_MODE_MASK); +- ew32(CTRL_EXT, ctrl_ext); ++ reg = er32(CTRL_EXT); ++ reg &= ~E1000_CTRL_EXT_LINK_MODE_MASK; ++ ew32(CTRL_EXT, reg); + + ret_val = e1e_rphy(hw, GG82563_PHY_PWR_MGMT_CTRL, &data); + if (ret_val) + return ret_val; + +- /* +- * Do not init these registers when the HW is in IAMT mode, since the ++ /* Do not init these registers when the HW is in IAMT mode, since the + * firmware will have already initialized them. We only initialize + * them if the HW is not in IAMT mode. + */ +- if (!e1000e_check_mng_mode(hw)) { ++ if (!hw->mac.ops.check_mng_mode(hw)) { + /* Enable Electrical Idle on the PHY */ + data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; + ret_val = e1e_wphy(hw, GG82563_PHY_PWR_MGMT_CTRL, data); +@@ -1095,8 +1010,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) + return ret_val; + } + +- /* +- * Workaround: Disable padding in Kumeran interface in the MAC ++ /* Workaround: Disable padding in Kumeran interface in the MAC + * and in the PHY to avoid CRC errors. + */ + ret_val = e1e_rphy(hw, GG82563_PHY_INBAND_CTRL, &data); +@@ -1129,33 +1043,34 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw) + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); + ew32(CTRL, ctrl); + +- /* +- * Set the mac to wait the maximum time between each ++ /* Set the mac to wait the maximum time between each + * iteration and increase the max iterations when + * polling the phy; this fixes erroneous timeouts at 10Mbps. + */ + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4), +- 0xFFFF); ++ 0xFFFF); + if (ret_val) + return ret_val; + ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), +- ®_data); ++ ®_data); + if (ret_val) + return ret_val; + reg_data |= 0x3F; + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), +- reg_data); ++ reg_data); + if (ret_val) + return ret_val; +- ret_val = e1000_read_kmrn_reg_80003es2lan(hw, +- E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, +- ®_data); ++ ret_val = ++ e1000_read_kmrn_reg_80003es2lan(hw, ++ E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, ++ ®_data); + if (ret_val) + return ret_val; + reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING; +- ret_val = e1000_write_kmrn_reg_80003es2lan(hw, +- E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, +- reg_data); ++ ret_val = ++ e1000_write_kmrn_reg_80003es2lan(hw, ++ E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, ++ reg_data); + if (ret_val) + return ret_val; + +@@ -1163,9 +1078,7 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw) + if (ret_val) + return ret_val; + +- ret_val = e1000e_setup_copper_link(hw); +- +- return 0; ++ return e1000e_setup_copper_link(hw); + } + + /** +@@ -1184,7 +1097,7 @@ static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw) + + if (hw->phy.media_type == e1000_media_type_copper) { + ret_val = e1000e_get_speed_and_duplex_copper(hw, &speed, +- &duplex); ++ &duplex); + if (ret_val) + return ret_val; + +@@ -1213,9 +1126,10 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) + u16 reg_data, reg_data2; + + reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; +- ret_val = e1000_write_kmrn_reg_80003es2lan(hw, +- E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, +- reg_data); ++ ret_val = ++ e1000_write_kmrn_reg_80003es2lan(hw, ++ E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, ++ reg_data); + if (ret_val) + return ret_val; + +@@ -1241,9 +1155,7 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) + else + reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; + +- ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); +- +- return 0; ++ return e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); + } + + /** +@@ -1261,9 +1173,10 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) + u32 i = 0; + + reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; +- ret_val = e1000_write_kmrn_reg_80003es2lan(hw, +- E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, +- reg_data); ++ ret_val = ++ e1000_write_kmrn_reg_80003es2lan(hw, ++ E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, ++ reg_data); + if (ret_val) + return ret_val; + +@@ -1285,9 +1198,8 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) + } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); + + reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; +- ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); + +- return ret_val; ++ return e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); + } + + /** +@@ -1304,14 +1216,14 @@ static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, + u16 *data) + { + u32 kmrnctrlsta; +- s32 ret_val = 0; ++ s32 ret_val; + + ret_val = e1000_acquire_mac_csr_80003es2lan(hw); + if (ret_val) + return ret_val; + + kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & +- E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; ++ E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; + ew32(KMRNCTRLSTA, kmrnctrlsta); + e1e_flush(); + +@@ -1339,14 +1251,14 @@ static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, + u16 data) + { + u32 kmrnctrlsta; +- s32 ret_val = 0; ++ s32 ret_val; + + ret_val = e1000_acquire_mac_csr_80003es2lan(hw); + if (ret_val) + return ret_val; + + kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & +- E1000_KMRNCTRLSTA_OFFSET) | data; ++ E1000_KMRNCTRLSTA_OFFSET) | data; + ew32(KMRNCTRLSTA, kmrnctrlsta); + e1e_flush(); + +@@ -1363,21 +1275,17 @@ static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, + **/ + static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw) + { +- s32 ret_val = 0; ++ s32 ret_val; + +- /* +- * If there's an alternate MAC address place it in RAR0 ++ /* If there's an alternate MAC address place it in RAR0 + * so that it will override the Si installed default perm + * address. + */ + ret_val = e1000_check_alt_mac_addr_generic(hw); + if (ret_val) +- goto out; +- +- ret_val = e1000_read_mac_addr_generic(hw); ++ return ret_val; + +-out: +- return ret_val; ++ return e1000_read_mac_addr_generic(hw); + } + + /** +@@ -1443,7 +1351,7 @@ static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw) + + static const struct e1000_mac_operations es2_mac_ops = { + .read_mac_addr = e1000_read_mac_addr_80003es2lan, +- .id_led_init = e1000e_id_led_init, ++ .id_led_init = e1000e_id_led_init_generic, + .blink_led = e1000e_blink_led_generic, + .check_mng_mode = e1000e_check_mng_mode_generic, + /* check_for_link dependent on media type */ +@@ -1459,33 +1367,36 @@ static const struct e1000_mac_operations es2_mac_ops = { + .clear_vfta = e1000_clear_vfta_generic, + .reset_hw = e1000_reset_hw_80003es2lan, + .init_hw = e1000_init_hw_80003es2lan, +- .setup_link = e1000e_setup_link, ++ .setup_link = e1000e_setup_link_generic, + /* setup_physical_interface dependent on media type */ + .setup_led = e1000e_setup_led_generic, ++ .config_collision_dist = e1000e_config_collision_dist_generic, ++ .rar_set = e1000e_rar_set_generic, + }; + + static const struct e1000_phy_operations es2_phy_ops = { + .acquire = e1000_acquire_phy_80003es2lan, + .check_polarity = e1000_check_polarity_m88, + .check_reset_block = e1000e_check_reset_block_generic, +- .commit = e1000e_phy_sw_reset, +- .force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan, +- .get_cfg_done = e1000_get_cfg_done_80003es2lan, +- .get_cable_length = e1000_get_cable_length_80003es2lan, +- .get_info = e1000e_get_phy_info_m88, +- .read_reg = e1000_read_phy_reg_gg82563_80003es2lan, ++ .commit = e1000e_phy_sw_reset, ++ .force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan, ++ .get_cfg_done = e1000_get_cfg_done_80003es2lan, ++ .get_cable_length = e1000_get_cable_length_80003es2lan, ++ .get_info = e1000e_get_phy_info_m88, ++ .read_reg = e1000_read_phy_reg_gg82563_80003es2lan, + .release = e1000_release_phy_80003es2lan, +- .reset = e1000e_phy_hw_reset_generic, +- .set_d0_lplu_state = NULL, +- .set_d3_lplu_state = e1000e_set_d3_lplu_state, +- .write_reg = e1000_write_phy_reg_gg82563_80003es2lan, +- .cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan, ++ .reset = e1000e_phy_hw_reset_generic, ++ .set_d0_lplu_state = NULL, ++ .set_d3_lplu_state = e1000e_set_d3_lplu_state, ++ .write_reg = e1000_write_phy_reg_gg82563_80003es2lan, ++ .cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan, + }; + + static const struct e1000_nvm_operations es2_nvm_ops = { + .acquire = e1000_acquire_nvm_80003es2lan, + .read = e1000e_read_nvm_eerd, + .release = e1000_release_nvm_80003es2lan, ++ .reload = e1000e_reload_nvm_generic, + .update = e1000e_update_nvm_checksum_generic, + .valid_led_default = e1000e_valid_led_default, + .validate = e1000e_validate_nvm_checksum_generic, +@@ -1502,8 +1413,7 @@ const struct e1000_info e1000_es2_info = { + | FLAG_RX_NEEDS_RESTART /* errata */ + | FLAG_TARC_SET_BIT_ZERO /* errata */ + | FLAG_APME_CHECK_PORT_B +- | FLAG_DISABLE_FC_PAUSE_TIME /* errata */ +- | FLAG_TIPG_MEDIUM_FOR_80003ESLAN, ++ | FLAG_DISABLE_FC_PAUSE_TIME, /* errata */ + .flags2 = FLAG2_DMA_BURST, + .pba = 38, + .max_hw_frame_size = DEFAULT_JUMBO, +@@ -1512,4 +1422,3 @@ const struct e1000_info e1000_es2_info = { + .phy_ops = &es2_phy_ops, + .nvm_ops = &es2_nvm_ops, + }; +- +diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.h b/drivers/net/ethernet/intel/e1000e/80003es2lan.h +new file mode 100644 +index 0000000..90d363b +--- /dev/null ++++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.h +@@ -0,0 +1,95 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#ifndef _E1000E_80003ES2LAN_H_ ++#define _E1000E_80003ES2LAN_H_ ++ ++#define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL 0x00 ++#define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL 0x02 ++#define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL 0x10 ++#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE 0x1F ++ ++#define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008 ++#define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800 ++#define E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING 0x0010 ++ ++#define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004 ++#define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000 ++#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000 ++ ++#define E1000_KMRNCTRLSTA_OPMODE_MASK 0x000C ++#define E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO 0x0004 ++ ++#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gig Carry Extend Padding */ ++#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000 ++ ++#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN 0x8 ++#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN 0x9 ++ ++/* GG82563 PHY Specific Status Register (Page 0, Register 16 */ ++#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Reversal Dis */ ++#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060 ++#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI */ ++#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX */ ++#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Auto crossover */ ++ ++/* PHY Specific Control Register 2 (Page 0, Register 26) */ ++#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 /* 1=Reverse Auto-Neg */ ++ ++/* MAC Specific Control Register (Page 2, Register 21) */ ++/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */ ++#define GG82563_MSCR_TX_CLK_MASK 0x0007 ++#define GG82563_MSCR_TX_CLK_10MBPS_2_5 0x0004 ++#define GG82563_MSCR_TX_CLK_100MBPS_25 0x0005 ++#define GG82563_MSCR_TX_CLK_1000MBPS_25 0x0007 ++ ++#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */ ++ ++/* DSP Distance Register (Page 5, Register 26) ++ * 0 = <50M ++ * 1 = 50-80M ++ * 2 = 80-100M ++ * 3 = 110-140M ++ * 4 = >140M ++ */ ++#define GG82563_DSPD_CABLE_LENGTH 0x0007 ++ ++/* Kumeran Mode Control Register (Page 193, Register 16) */ ++#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 ++ ++/* Max number of times Kumeran read/write should be validated */ ++#define GG82563_MAX_KMRN_RETRY 0x5 ++ ++/* Power Management Control Register (Page 193, Register 20) */ ++/* 1=Enable SERDES Electrical Idle */ ++#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 ++ ++/* In-Band Control Register (Page 194, Register 18) */ ++#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding */ ++ ++#endif +diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c +index 4f4d52a..8f393d4 100644 +--- a/drivers/net/ethernet/intel/e1000e/82571.c ++++ b/drivers/net/ethernet/intel/e1000e/82571.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel PRO/1000 Linux driver +- Copyright(c) 1999 - 2011 Intel Corporation. ++ Copyright(c) 1999 - 2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -26,8 +26,7 @@ + + *******************************************************************************/ + +-/* +- * 82571EB Gigabit Ethernet Controller ++/* 82571EB Gigabit Ethernet Controller + * 82571EB Gigabit Ethernet Controller (Copper) + * 82571EB Gigabit Ethernet Controller (Fiber) + * 82571EB Dual Port Gigabit Mezzanine Adapter +@@ -45,21 +44,6 @@ + + #include "e1000.h" + +-#define ID_LED_RESERVED_F746 0xF746 +-#define ID_LED_DEFAULT_82573 ((ID_LED_DEF1_DEF2 << 12) | \ +- (ID_LED_OFF1_ON2 << 8) | \ +- (ID_LED_DEF1_DEF2 << 4) | \ +- (ID_LED_DEF1_DEF2)) +- +-#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 +-#define AN_RETRY_COUNT 5 /* Autoneg Retry Count value */ +-#define E1000_BASE1000T_STATUS 10 +-#define E1000_IDLE_ERROR_COUNT_MASK 0xFF +-#define E1000_RECEIVE_ERROR_COUNTER 21 +-#define E1000_RECEIVE_ERROR_MAX 0xFFFF +- +-#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */ +- + static s32 e1000_get_phy_id_82571(struct e1000_hw *hw); + static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw); + static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw); +@@ -68,9 +52,7 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data); + static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw); + static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw); +-static s32 e1000_setup_link_82571(struct e1000_hw *hw); + static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw); +-static void e1000_clear_vfta_82571(struct e1000_hw *hw); + static bool e1000_check_mng_mode_82574(struct e1000_hw *hw); + static s32 e1000_led_on_82574(struct e1000_hw *hw); + static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw); +@@ -95,24 +77,24 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) + return 0; + } + +- phy->addr = 1; +- phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; +- phy->reset_delay_us = 100; ++ phy->addr = 1; ++ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; ++ phy->reset_delay_us = 100; + +- phy->ops.power_up = e1000_power_up_phy_copper; +- phy->ops.power_down = e1000_power_down_phy_copper_82571; ++ phy->ops.power_up = e1000_power_up_phy_copper; ++ phy->ops.power_down = e1000_power_down_phy_copper_82571; + + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: +- phy->type = e1000_phy_igp_2; ++ phy->type = e1000_phy_igp_2; + break; + case e1000_82573: +- phy->type = e1000_phy_m88; ++ phy->type = e1000_phy_m88; + break; + case e1000_82574: + case e1000_82583: +- phy->type = e1000_phy_bm; ++ phy->type = e1000_phy_bm; + phy->ops.acquire = e1000_get_hw_semaphore_82574; + phy->ops.release = e1000_put_hw_semaphore_82574; + phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82574; +@@ -191,8 +173,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) + if (((eecd >> 15) & 0x3) == 0x3) { + nvm->type = e1000_nvm_flash_hw; + nvm->word_size = 2048; +- /* +- * Autonomous Flash update bit must be cleared due ++ /* Autonomous Flash update bit must be cleared due + * to Flash update issue. + */ + eecd &= ~E1000_EECD_AUPDEN; +@@ -203,9 +184,8 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) + default: + nvm->type = e1000_nvm_eeprom_spi; + size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> +- E1000_EECD_SIZE_EX_SHIFT); +- /* +- * Added to a constant, "size" becomes the left-shift value ++ E1000_EECD_SIZE_EX_SHIFT); ++ /* Added to a constant, "size" becomes the left-shift value + * for setting word_size. + */ + size += NVM_WORD_SIZE_BASE_SHIFT; +@@ -213,7 +193,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) + /* EEPROM access above 16k is unsupported */ + if (size > 14) + size = 14; +- nvm->word_size = 1 << size; ++ nvm->word_size = 1 << size; + break; + } + +@@ -235,30 +215,42 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) + * e1000_init_mac_params_82571 - Init MAC func ptrs. + * @hw: pointer to the HW structure + **/ +-static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) ++static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) + { +- struct e1000_hw *hw = &adapter->hw; + struct e1000_mac_info *mac = &hw->mac; +- struct e1000_mac_operations *func = &mac->ops; + u32 swsm = 0; + u32 swsm2 = 0; + bool force_clear_smbi = false; + +- /* Set media type */ +- switch (adapter->pdev->device) { ++ /* Set media type and media-dependent function pointers */ ++ switch (hw->adapter->pdev->device) { + case E1000_DEV_ID_82571EB_FIBER: + case E1000_DEV_ID_82572EI_FIBER: + case E1000_DEV_ID_82571EB_QUAD_FIBER: + hw->phy.media_type = e1000_media_type_fiber; ++ mac->ops.setup_physical_interface = ++ e1000_setup_fiber_serdes_link_82571; ++ mac->ops.check_for_link = e1000e_check_for_fiber_link; ++ mac->ops.get_link_up_info = ++ e1000e_get_speed_and_duplex_fiber_serdes; + break; + case E1000_DEV_ID_82571EB_SERDES: +- case E1000_DEV_ID_82572EI_SERDES: + case E1000_DEV_ID_82571EB_SERDES_DUAL: + case E1000_DEV_ID_82571EB_SERDES_QUAD: ++ case E1000_DEV_ID_82572EI_SERDES: + hw->phy.media_type = e1000_media_type_internal_serdes; ++ mac->ops.setup_physical_interface = ++ e1000_setup_fiber_serdes_link_82571; ++ mac->ops.check_for_link = e1000_check_for_serdes_link_82571; ++ mac->ops.get_link_up_info = ++ e1000e_get_speed_and_duplex_fiber_serdes; + break; + default: + hw->phy.media_type = e1000_media_type_copper; ++ mac->ops.setup_physical_interface = ++ e1000_setup_copper_link_82571; ++ mac->ops.check_for_link = e1000e_check_for_copper_link; ++ mac->ops.get_link_up_info = e1000e_get_speed_and_duplex_copper; + break; + } + +@@ -269,67 +261,39 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) + /* Adaptive IFS supported */ + mac->adaptive_ifs = true; + +- /* check for link */ +- switch (hw->phy.media_type) { +- case e1000_media_type_copper: +- func->setup_physical_interface = e1000_setup_copper_link_82571; +- func->check_for_link = e1000e_check_for_copper_link; +- func->get_link_up_info = e1000e_get_speed_and_duplex_copper; +- break; +- case e1000_media_type_fiber: +- func->setup_physical_interface = +- e1000_setup_fiber_serdes_link_82571; +- func->check_for_link = e1000e_check_for_fiber_link; +- func->get_link_up_info = +- e1000e_get_speed_and_duplex_fiber_serdes; +- break; +- case e1000_media_type_internal_serdes: +- func->setup_physical_interface = +- e1000_setup_fiber_serdes_link_82571; +- func->check_for_link = e1000_check_for_serdes_link_82571; +- func->get_link_up_info = +- e1000e_get_speed_and_duplex_fiber_serdes; +- break; +- default: +- return -E1000_ERR_CONFIG; +- break; +- } +- ++ /* MAC-specific function pointers */ + switch (hw->mac.type) { + case e1000_82573: +- func->set_lan_id = e1000_set_lan_id_single_port; +- func->check_mng_mode = e1000e_check_mng_mode_generic; +- func->led_on = e1000e_led_on_generic; +- func->blink_led = e1000e_blink_led_generic; ++ mac->ops.set_lan_id = e1000_set_lan_id_single_port; ++ mac->ops.check_mng_mode = e1000e_check_mng_mode_generic; ++ mac->ops.led_on = e1000e_led_on_generic; ++ mac->ops.blink_led = e1000e_blink_led_generic; + + /* FWSM register */ + mac->has_fwsm = true; +- /* +- * ARC supported; valid only if manageability features are ++ /* ARC supported; valid only if manageability features are + * enabled. + */ +- mac->arc_subsystem_valid = +- (er32(FWSM) & E1000_FWSM_MODE_MASK) +- ? true : false; ++ mac->arc_subsystem_valid = !!(er32(FWSM) & ++ E1000_FWSM_MODE_MASK); + break; + case e1000_82574: + case e1000_82583: +- func->set_lan_id = e1000_set_lan_id_single_port; +- func->check_mng_mode = e1000_check_mng_mode_82574; +- func->led_on = e1000_led_on_82574; ++ mac->ops.set_lan_id = e1000_set_lan_id_single_port; ++ mac->ops.check_mng_mode = e1000_check_mng_mode_82574; ++ mac->ops.led_on = e1000_led_on_82574; + break; + default: +- func->check_mng_mode = e1000e_check_mng_mode_generic; +- func->led_on = e1000e_led_on_generic; +- func->blink_led = e1000e_blink_led_generic; ++ mac->ops.check_mng_mode = e1000e_check_mng_mode_generic; ++ mac->ops.led_on = e1000e_led_on_generic; ++ mac->ops.blink_led = e1000e_blink_led_generic; + + /* FWSM register */ + mac->has_fwsm = true; + break; + } + +- /* +- * Ensure that the inter-port SWSM.SMBI lock bit is clear before ++ /* Ensure that the inter-port SWSM.SMBI lock bit is clear before + * first NVM or PHY access. This should be done for single-port + * devices, and for one port only on dual-port devices so that + * for those devices we can still use the SMBI lock to synchronize +@@ -342,11 +306,11 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) + + if (!(swsm2 & E1000_SWSM2_LOCK)) { + /* Only do this for the first interface on this card */ +- ew32(SWSM2, +- swsm2 | E1000_SWSM2_LOCK); ++ ew32(SWSM2, swsm2 | E1000_SWSM2_LOCK); + force_clear_smbi = true; +- } else ++ } else { + force_clear_smbi = false; ++ } + break; + default: + force_clear_smbi = true; +@@ -366,11 +330,8 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) + ew32(SWSM, swsm & ~E1000_SWSM_SMBI); + } + +- /* +- * Initialize device specific counter of SMBI acquisition +- * timeouts. +- */ +- hw->dev_spec.e82571.smb_counter = 0; ++ /* Initialize device specific counter of SMBI acquisition timeouts. */ ++ hw->dev_spec.e82571.smb_counter = 0; + + return 0; + } +@@ -378,12 +339,12 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) + static s32 e1000_get_variants_82571(struct e1000_adapter *adapter) + { + struct e1000_hw *hw = &adapter->hw; +- static int global_quad_port_a; /* global port a indication */ ++ static int global_quad_port_a; /* global port a indication */ + struct pci_dev *pdev = adapter->pdev; + int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1; + s32 rc; + +- rc = e1000_init_mac_params_82571(adapter); ++ rc = e1000_init_mac_params_82571(hw); + if (rc) + return rc; + +@@ -459,8 +420,7 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw) + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: +- /* +- * The 82571 firmware may still be configuring the PHY. ++ /* The 82571 firmware may still be configuring the PHY. + * In this case, we cannot access the PHY until the + * configuration is done. So we explicitly set the + * PHY ID. +@@ -472,13 +432,13 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw) + break; + case e1000_82574: + case e1000_82583: +- ret_val = e1e_rphy(hw, PHY_ID1, &phy_id); ++ ret_val = e1e_rphy(hw, MII_PHYSID1, &phy_id); + if (ret_val) + return ret_val; + + phy->id = (u32)(phy_id << 16); +- udelay(20); +- ret_val = e1e_rphy(hw, PHY_ID2, &phy_id); ++ usleep_range(20, 40); ++ ret_val = e1e_rphy(hw, MII_PHYSID2, &phy_id); + if (ret_val) + return ret_val; + +@@ -506,8 +466,7 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) + s32 fw_timeout = hw->nvm.word_size + 1; + s32 i = 0; + +- /* +- * If we have timedout 3 times on trying to acquire ++ /* If we have timedout 3 times on trying to acquire + * the inter-port SMBI semaphore, there is old code + * operating on the other port, and it is not + * releasing SMBI. Modify the number of times that +@@ -523,7 +482,7 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) + if (!(swsm & E1000_SWSM_SMBI)) + break; + +- udelay(50); ++ usleep_range(50, 100); + i++; + } + +@@ -540,7 +499,7 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) + if (er32(SWSM) & E1000_SWSM_SWESMBI) + break; + +- udelay(50); ++ usleep_range(50, 100); + } + + if (i == fw_timeout) { +@@ -567,6 +526,7 @@ static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw) + swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); + ew32(SWSM, swsm); + } ++ + /** + * e1000_get_hw_semaphore_82573 - Acquire hardware semaphore + * @hw: pointer to the HW structure +@@ -577,20 +537,17 @@ static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw) + static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw) + { + u32 extcnf_ctrl; +- s32 ret_val = 0; + s32 i = 0; + + extcnf_ctrl = er32(EXTCNF_CTRL); +- extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; + do { ++ extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; + ew32(EXTCNF_CTRL, extcnf_ctrl); + extcnf_ctrl = er32(EXTCNF_CTRL); + + if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) + break; + +- extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; +- + usleep_range(2000, 4000); + i++; + } while (i < MDIO_OWNERSHIP_TIMEOUT); +@@ -599,12 +556,10 @@ static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw) + /* Release semaphores */ + e1000_put_hw_semaphore_82573(hw); + e_dbg("Driver can't access the PHY\n"); +- ret_val = -E1000_ERR_PHY; +- goto out; ++ return -E1000_ERR_PHY; + } + +-out: +- return ret_val; ++ return 0; + } + + /** +@@ -670,7 +625,7 @@ static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw) + **/ + static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active) + { +- u16 data = er32(POEMB); ++ u32 data = er32(POEMB); + + if (active) + data |= E1000_PHY_CTRL_D0A_LPLU; +@@ -694,7 +649,7 @@ static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active) + **/ + static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active) + { +- u16 data = er32(POEMB); ++ u32 data = er32(POEMB); + + if (!active) { + data &= ~E1000_PHY_CTRL_NOND0A_LPLU; +@@ -804,17 +759,16 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) + if (ret_val) + return ret_val; + +- /* +- * If our nvm is an EEPROM, then we're done ++ /* If our nvm is an EEPROM, then we're done + * otherwise, commit the checksum to the flash NVM. + */ + if (hw->nvm.type != e1000_nvm_flash_hw) +- return ret_val; ++ return 0; + + /* Check for pending operations. */ + for (i = 0; i < E1000_FLASH_UPDATES; i++) { + usleep_range(1000, 2000); +- if ((er32(EECD) & E1000_EECD_FLUPD) == 0) ++ if (!(er32(EECD) & E1000_EECD_FLUPD)) + break; + } + +@@ -823,8 +777,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) + + /* Reset the firmware if using STM opcode. */ + if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) { +- /* +- * The enabling of and the actual reset must be done ++ /* The enabling of and the actual reset must be done + * in two write cycles. + */ + ew32(HICR, E1000_HICR_FW_RESET_ENABLE); +@@ -838,7 +791,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) + + for (i = 0; i < E1000_FLASH_UPDATES; i++) { + usleep_range(1000, 2000); +- if ((er32(EECD) & E1000_EECD_FLUPD) == 0) ++ if (!(er32(EECD) & E1000_EECD_FLUPD)) + break; + } + +@@ -884,8 +837,7 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, + u32 i, eewr = 0; + s32 ret_val = 0; + +- /* +- * A check for invalid values: offset too large, too many words, ++ /* A check for invalid values: offset too large, too many words, + * and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || +@@ -895,9 +847,9 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, + } + + for (i = 0; i < words; i++) { +- eewr = (data[i] << E1000_NVM_RW_REG_DATA) | +- ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | +- E1000_NVM_RW_REG_START; ++ eewr = ((data[i] << E1000_NVM_RW_REG_DATA) | ++ ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) | ++ E1000_NVM_RW_REG_START); + + ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); + if (ret_val) +@@ -924,8 +876,7 @@ static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw) + s32 timeout = PHY_CFG_TIMEOUT; + + while (timeout) { +- if (er32(EEMNGCTL) & +- E1000_NVM_CFG_DONE_PORT_0) ++ if (er32(EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0) + break; + usleep_range(1000, 2000); + timeout--; +@@ -967,6 +918,8 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) + + /* When LPLU is enabled, we should disable SmartSpeed */ + ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data); ++ if (ret_val) ++ return ret_val; + data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data); + if (ret_val) +@@ -974,8 +927,7 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) + } else { + data &= ~IGP02E1000_PM_D0_LPLU; + ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); +- /* +- * LPLU and SmartSpeed are mutually exclusive. LPLU is used ++ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used + * during Dx states where the power conservation is most + * important. During driver activity we should enable + * SmartSpeed, so performance is maintained. +@@ -1016,11 +968,10 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) + **/ + static s32 e1000_reset_hw_82571(struct e1000_hw *hw) + { +- u32 ctrl, ctrl_ext; ++ u32 ctrl, ctrl_ext, eecd, tctl; + s32 ret_val; + +- /* +- * Prevent the PCI-E bus from sticking if there is no TLP connection ++ /* Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ + ret_val = e1000e_disable_pcie_master(hw); +@@ -1031,13 +982,14 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) + ew32(IMC, 0xffffffff); + + ew32(RCTL, 0); +- ew32(TCTL, E1000_TCTL_PSP); ++ tctl = er32(TCTL); ++ tctl &= ~E1000_TCTL_EN; ++ ew32(TCTL, tctl); + e1e_flush(); + + usleep_range(10000, 20000); + +- /* +- * Must acquire the MDIO ownership before MAC reset. ++ /* Must acquire the MDIO ownership before MAC reset. + * Ownership defaults to firmware after a reset. + */ + switch (hw->mac.type) { +@@ -1051,8 +1003,6 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) + default: + break; + } +- if (ret_val) +- e_dbg("Cannot acquire MDIO ownership\n"); + + ctrl = er32(CTRL); + +@@ -1061,16 +1011,23 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) + + /* Must release MDIO ownership and mutex after MAC reset. */ + switch (hw->mac.type) { ++ case e1000_82573: ++ /* Release mutex only if the hw semaphore is acquired */ ++ if (!ret_val) ++ e1000_put_hw_semaphore_82573(hw); ++ break; + case e1000_82574: + case e1000_82583: +- e1000_put_hw_semaphore_82574(hw); ++ /* Release mutex only if the hw semaphore is acquired */ ++ if (!ret_val) ++ e1000_put_hw_semaphore_82574(hw); + break; + default: + break; + } + + if (hw->nvm.type == e1000_nvm_flash_hw) { +- udelay(10); ++ usleep_range(10, 20); + ctrl_ext = er32(CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_EE_RST; + ew32(CTRL_EXT, ctrl_ext); +@@ -1082,13 +1039,21 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) + /* We don't want to continue accessing MAC registers. */ + return ret_val; + +- /* +- * Phy configuration from NVM just starts after EECD_AUTO_RD is set. ++ /* Phy configuration from NVM just starts after EECD_AUTO_RD is set. + * Need to wait for Phy configuration completion before accessing + * NVM and Phy. + */ + + switch (hw->mac.type) { ++ case e1000_82571: ++ case e1000_82572: ++ /* REQ and GNT bits need to be cleared when using AUTO_RD ++ * to access the EEPROM. ++ */ ++ eecd = er32(EECD); ++ eecd &= ~(E1000_EECD_REQ | E1000_EECD_GNT); ++ ew32(EECD, eecd); ++ break; + case e1000_82573: + case e1000_82574: + case e1000_82583: +@@ -1134,17 +1099,16 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw) + e1000_initialize_hw_bits_82571(hw); + + /* Initialize identification LED */ +- ret_val = e1000e_id_led_init(hw); ++ ret_val = mac->ops.id_led_init(hw); ++ /* An error is not fatal and we should not stop init due to this */ + if (ret_val) + e_dbg("Error initializing identification LED\n"); +- /* This is not fatal and we should not stop init due to this */ + + /* Disabling VLAN filtering */ + e_dbg("Initializing the IEEE VLAN\n"); + mac->ops.clear_vfta(hw); + +- /* Setup the receive address. */ +- /* ++ /* Setup the receive address. + * If, however, a locally administered address was assigned to the + * 82571, we must reserve a RAR for it to work around an issue where + * resetting one port will reload the MAC on the other port. +@@ -1159,13 +1123,12 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw) + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + + /* Setup link and flow control */ +- ret_val = e1000_setup_link_82571(hw); ++ ret_val = mac->ops.setup_link(hw); + + /* Set the transmit descriptor write-back policy */ + reg_data = er32(TXDCTL(0)); +- reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | +- E1000_TXDCTL_FULL_TX_DESC_WB | +- E1000_TXDCTL_COUNT_DESC; ++ reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | ++ E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); + ew32(TXDCTL(0), reg_data); + + /* ...for both queues. */ +@@ -1181,15 +1144,14 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw) + break; + default: + reg_data = er32(TXDCTL(1)); +- reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | +- E1000_TXDCTL_FULL_TX_DESC_WB | +- E1000_TXDCTL_COUNT_DESC; ++ reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | ++ E1000_TXDCTL_FULL_TX_DESC_WB | ++ E1000_TXDCTL_COUNT_DESC); + ew32(TXDCTL(1), reg_data); + break; + } + +- /* +- * Clear all of the statistics registers (clear on read). It is ++ /* Clear all of the statistics registers (clear on read). It is + * important that we do this after we have tried to establish link + * because the symbol error count will increment wildly if there + * is no link. +@@ -1221,12 +1183,16 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) + + /* Transmit Arbitration Control 0 */ + reg = er32(TARC(0)); +- reg &= ~(0xF << 27); /* 30:27 */ ++ reg &= ~(0xF << 27); /* 30:27 */ + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: + reg |= (1 << 23) | (1 << 24) | (1 << 25) | (1 << 26); + break; ++ case e1000_82574: ++ case e1000_82583: ++ reg |= (1 << 26); ++ break; + default: + break; + } +@@ -1281,18 +1247,24 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) + reg |= E1000_PBA_ECC_CORR_EN; + ew32(PBA_ECC, reg); + } +- /* +- * Workaround for hardware errata. ++ ++ /* Workaround for hardware errata. + * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572 + */ ++ if ((hw->mac.type == e1000_82571) || (hw->mac.type == e1000_82572)) { ++ reg = er32(CTRL_EXT); ++ reg &= ~E1000_CTRL_EXT_DMA_DYN_CLK_EN; ++ ew32(CTRL_EXT, reg); ++ } + +- if ((hw->mac.type == e1000_82571) || +- (hw->mac.type == e1000_82572)) { +- reg = er32(CTRL_EXT); +- reg &= ~E1000_CTRL_EXT_DMA_DYN_CLK_EN; +- ew32(CTRL_EXT, reg); +- } +- ++ /* Disable IPv6 extension header parsing because some malformed ++ * IPv6 headers can hang the Rx. ++ */ ++ if (hw->mac.type <= e1000_82573) { ++ reg = er32(RFCTL); ++ reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); ++ ew32(RFCTL, reg); ++ } + + /* PCI-Ex Control Registers */ + switch (hw->mac.type) { +@@ -1302,8 +1274,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) + reg |= (1 << 22); + ew32(GCR, reg); + +- /* +- * Workaround for hardware errata. ++ /* Workaround for hardware errata. + * apply workaround for hardware errata documented in errata + * docs Fixes issue where some error prone or unreliable PCIe + * completions are occurring, particularly with ASPM enabled. +@@ -1337,8 +1308,7 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw) + case e1000_82574: + case e1000_82583: + if (hw->mng_cookie.vlan_id != 0) { +- /* +- * The VFTA is a 4096b bit-field, each identifying ++ /* The VFTA is a 4096b bit-field, each identifying + * a single VLAN ID. The following operations + * determine which 32b entry (i.e. offset) into the + * array we want to set the VLAN ID (i.e. bit) of +@@ -1346,17 +1316,17 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw) + */ + vfta_offset = (hw->mng_cookie.vlan_id >> + E1000_VFTA_ENTRY_SHIFT) & +- E1000_VFTA_ENTRY_MASK; +- vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id & +- E1000_VFTA_ENTRY_BIT_SHIFT_MASK); ++ E1000_VFTA_ENTRY_MASK; ++ vfta_bit_in_reg = ++ 1 << (hw->mng_cookie.vlan_id & ++ E1000_VFTA_ENTRY_BIT_SHIFT_MASK); + } + break; + default: + break; + } + for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { +- /* +- * If the offset we want to clear is the same offset of the ++ /* If the offset we want to clear is the same offset of the + * manageability VLAN ID, then clear all bits except that of + * the manageability unit. + */ +@@ -1394,8 +1364,7 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw) + + ctrl = hw->mac.ledctl_mode2; + if (!(E1000_STATUS_LU & er32(STATUS))) { +- /* +- * If no link, then turn LED on by setting the invert bit ++ /* If no link, then turn LED on by setting the invert bit + * for each LED that's "on" (0x0E) in ledctl_mode2. + */ + for (i = 0; i < 4; i++) +@@ -1418,27 +1387,24 @@ bool e1000_check_phy_82574(struct e1000_hw *hw) + { + u16 status_1kbt = 0; + u16 receive_errors = 0; +- bool phy_hung = false; +- s32 ret_val = 0; ++ s32 ret_val; + +- /* +- * Read PHY Receive Error counter first, if its is max - all F's then ++ /* Read PHY Receive Error counter first, if its is max - all F's then + * read the Base1000T status register If both are max then PHY is hung. + */ + ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors); +- + if (ret_val) +- goto out; +- if (receive_errors == E1000_RECEIVE_ERROR_MAX) { ++ return false; ++ if (receive_errors == E1000_RECEIVE_ERROR_MAX) { + ret_val = e1e_rphy(hw, E1000_BASE1000T_STATUS, &status_1kbt); + if (ret_val) +- goto out; ++ return false; + if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) == + E1000_IDLE_ERROR_COUNT_MASK) +- phy_hung = true; ++ return true; + } +-out: +- return phy_hung; ++ ++ return false; + } + + /** +@@ -1453,8 +1419,7 @@ out: + **/ + static s32 e1000_setup_link_82571(struct e1000_hw *hw) + { +- /* +- * 82573 does not have a word in the NVM to determine ++ /* 82573 does not have a word in the NVM to determine + * the default flow control setting, so we explicitly + * set it to full. + */ +@@ -1469,7 +1434,7 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw) + break; + } + +- return e1000e_setup_link(hw); ++ return e1000e_setup_link_generic(hw); + } + + /** +@@ -1506,9 +1471,7 @@ static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw) + if (ret_val) + return ret_val; + +- ret_val = e1000e_setup_copper_link(hw); +- +- return ret_val; ++ return e1000e_setup_copper_link(hw); + } + + /** +@@ -1523,8 +1486,7 @@ static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw) + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: +- /* +- * If SerDes loopback mode is entered, there is no form ++ /* If SerDes loopback mode is entered, there is no form + * of reset to take the adapter out of that mode. So we + * have to explicitly take the adapter out of loopback + * mode. This prevents drivers from twiddling their thumbs +@@ -1570,19 +1532,17 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) + + ctrl = er32(CTRL); + status = er32(STATUS); +- rxcw = er32(RXCW); ++ er32(RXCW); + /* SYNCH bit and IV bit are sticky */ +- udelay(10); ++ usleep_range(10, 20); + rxcw = er32(RXCW); + + if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) { +- + /* Receiver is synchronized with no invalid bits. */ + switch (mac->serdes_link_state) { + case e1000_serdes_link_autoneg_complete: + if (!(status & E1000_STATUS_LU)) { +- /* +- * We have lost link, retry autoneg before ++ /* We have lost link, retry autoneg before + * reporting link failure + */ + mac->serdes_link_state = +@@ -1595,8 +1555,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) + break; + + case e1000_serdes_link_forced_up: +- /* +- * If we are receiving /C/ ordered sets, re-enable ++ /* If we are receiving /C/ ordered sets, re-enable + * auto-negotiation in the TXCW register and disable + * forced link in the Device Control register in an + * attempt to auto-negotiate with our link partner. +@@ -1616,8 +1575,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) + + case e1000_serdes_link_autoneg_progress: + if (rxcw & E1000_RXCW_C) { +- /* +- * We received /C/ ordered sets, meaning the ++ /* We received /C/ ordered sets, meaning the + * link partner has autonegotiated, and we can + * trust the Link Up (LU) status bit. + */ +@@ -1633,8 +1591,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) + e_dbg("AN_PROG -> DOWN\n"); + } + } else { +- /* +- * The link partner did not autoneg. ++ /* The link partner did not autoneg. + * Force link up and full duplex, and change + * state to forced. + */ +@@ -1657,8 +1614,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) + + case e1000_serdes_link_down: + default: +- /* +- * The link was down but the receiver has now gained ++ /* The link was down but the receiver has now gained + * valid sync, so lets see if we can bring the link + * up. + */ +@@ -1676,17 +1632,18 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) + mac->serdes_link_state = e1000_serdes_link_down; + e_dbg("ANYSTATE -> DOWN\n"); + } else { +- /* +- * Check several times, if Sync and Config +- * both are consistently 1 then simply ignore +- * the Invalid bit and restart Autoneg ++ /* Check several times, if SYNCH bit and CONFIG ++ * bit both are consistently 1 then simply ignore ++ * the IV bit and restart Autoneg + */ + for (i = 0; i < AN_RETRY_COUNT; i++) { +- udelay(10); ++ usleep_range(10, 20); + rxcw = er32(RXCW); +- if ((rxcw & E1000_RXCW_IV) && +- !((rxcw & E1000_RXCW_SYNCH) && +- (rxcw & E1000_RXCW_C))) { ++ if ((rxcw & E1000_RXCW_SYNCH) && ++ (rxcw & E1000_RXCW_C)) ++ continue; ++ ++ if (rxcw & E1000_RXCW_IV) { + mac->serdes_has_link = false; + mac->serdes_link_state = + e1000_serdes_link_down; +@@ -1775,14 +1732,14 @@ void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state) + + /* If workaround is activated... */ + if (state) +- /* +- * Hold a copy of the LAA in RAR[14] This is done so that ++ /* Hold a copy of the LAA in RAR[14] This is done so that + * between the time RAR[0] gets clobbered and the time it + * gets fixed, the actual LAA is in one of the RARs and no + * incoming packets directed to this port are dropped. + * Eventually the LAA will be in RAR[0] and RAR[14]. + */ +- e1000e_rar_set(hw, hw->mac.addr, hw->mac.rar_entry_count - 1); ++ hw->mac.ops.rar_set(hw, hw->mac.addr, ++ hw->mac.rar_entry_count - 1); + } + + /** +@@ -1804,8 +1761,7 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) + if (nvm->type != e1000_nvm_flash_hw) + return 0; + +- /* +- * Check bit 4 of word 10h. If it is 0, firmware is done updating ++ /* Check bit 4 of word 10h. If it is 0, firmware is done updating + * 10h-12h. Checksum may need to be fixed. + */ + ret_val = e1000_read_nvm(hw, 0x10, 1, &data); +@@ -1813,8 +1769,7 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) + return ret_val; + + if (!(data & 0x10)) { +- /* +- * Read 0x23 and check bit 15. This bit is a 1 ++ /* Read 0x23 and check bit 15. This bit is a 1 + * when the checksum has already been fixed. If + * the checksum is still wrong and this bit is a + * 1, we need to return bad checksum. Otherwise, +@@ -1831,6 +1786,8 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) + if (ret_val) + return ret_val; + ret_val = e1000e_update_nvm_checksum(hw); ++ if (ret_val) ++ return ret_val; + } + } + +@@ -1843,23 +1800,19 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) + **/ + static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw) + { +- s32 ret_val = 0; +- + if (hw->mac.type == e1000_82571) { +- /* +- * If there's an alternate MAC address place it in RAR0 ++ s32 ret_val; ++ ++ /* If there's an alternate MAC address place it in RAR0 + * so that it will override the Si installed default perm + * address. + */ + ret_val = e1000_check_alt_mac_addr_generic(hw); + if (ret_val) +- goto out; ++ return ret_val; + } + +- ret_val = e1000_read_mac_addr_generic(hw); +- +-out: +- return ret_val; ++ return e1000_read_mac_addr_generic(hw); + } + + /** +@@ -1874,7 +1827,7 @@ static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw) + struct e1000_phy_info *phy = &hw->phy; + struct e1000_mac_info *mac = &hw->mac; + +- if (!(phy->ops.check_reset_block)) ++ if (!phy->ops.check_reset_block) + return; + + /* If the management interface is not enabled, then power down */ +@@ -1931,7 +1884,7 @@ static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw) + static const struct e1000_mac_operations e82571_mac_ops = { + /* .check_mng_mode: mac type dependent */ + /* .check_for_link: media type dependent */ +- .id_led_init = e1000e_id_led_init, ++ .id_led_init = e1000e_id_led_init_generic, + .cleanup_led = e1000e_cleanup_led_generic, + .clear_hw_cntrs = e1000_clear_hw_cntrs_82571, + .get_bus_info = e1000e_get_bus_info_pcie, +@@ -1947,7 +1900,9 @@ static const struct e1000_mac_operations e82571_mac_ops = { + .setup_link = e1000_setup_link_82571, + /* .setup_physical_interface: media type dependent */ + .setup_led = e1000e_setup_led_generic, ++ .config_collision_dist = e1000e_config_collision_dist_generic, + .read_mac_addr = e1000_read_mac_addr_82571, ++ .rar_set = e1000e_rar_set_generic, + }; + + static const struct e1000_phy_operations e82_phy_ops_igp = { +@@ -1965,7 +1920,7 @@ static const struct e1000_phy_operations e82_phy_ops_igp = { + .set_d0_lplu_state = e1000_set_d0_lplu_state_82571, + .set_d3_lplu_state = e1000e_set_d3_lplu_state, + .write_reg = e1000e_write_phy_reg_igp, +- .cfg_on_link_up = NULL, ++ .cfg_on_link_up = NULL, + }; + + static const struct e1000_phy_operations e82_phy_ops_m88 = { +@@ -1974,7 +1929,7 @@ static const struct e1000_phy_operations e82_phy_ops_m88 = { + .check_reset_block = e1000e_check_reset_block_generic, + .commit = e1000e_phy_sw_reset, + .force_speed_duplex = e1000e_phy_force_speed_duplex_m88, +- .get_cfg_done = e1000e_get_cfg_done, ++ .get_cfg_done = e1000e_get_cfg_done_generic, + .get_cable_length = e1000e_get_cable_length_m88, + .get_info = e1000e_get_phy_info_m88, + .read_reg = e1000e_read_phy_reg_m88, +@@ -1983,7 +1938,7 @@ static const struct e1000_phy_operations e82_phy_ops_m88 = { + .set_d0_lplu_state = e1000_set_d0_lplu_state_82571, + .set_d3_lplu_state = e1000e_set_d3_lplu_state, + .write_reg = e1000e_write_phy_reg_m88, +- .cfg_on_link_up = NULL, ++ .cfg_on_link_up = NULL, + }; + + static const struct e1000_phy_operations e82_phy_ops_bm = { +@@ -1992,7 +1947,7 @@ static const struct e1000_phy_operations e82_phy_ops_bm = { + .check_reset_block = e1000e_check_reset_block_generic, + .commit = e1000e_phy_sw_reset, + .force_speed_duplex = e1000e_phy_force_speed_duplex_m88, +- .get_cfg_done = e1000e_get_cfg_done, ++ .get_cfg_done = e1000e_get_cfg_done_generic, + .get_cable_length = e1000e_get_cable_length_m88, + .get_info = e1000e_get_phy_info_m88, + .read_reg = e1000e_read_phy_reg_bm2, +@@ -2001,13 +1956,14 @@ static const struct e1000_phy_operations e82_phy_ops_bm = { + .set_d0_lplu_state = e1000_set_d0_lplu_state_82571, + .set_d3_lplu_state = e1000e_set_d3_lplu_state, + .write_reg = e1000e_write_phy_reg_bm2, +- .cfg_on_link_up = NULL, ++ .cfg_on_link_up = NULL, + }; + + static const struct e1000_nvm_operations e82571_nvm_ops = { + .acquire = e1000_acquire_nvm_82571, + .read = e1000e_read_nvm_eerd, + .release = e1000_release_nvm_82571, ++ .reload = e1000e_reload_nvm_generic, + .update = e1000_update_nvm_checksum_82571, + .valid_led_default = e1000_valid_led_default_82571, + .validate = e1000_validate_nvm_checksum_82571, +@@ -2077,6 +2033,7 @@ const struct e1000_info e1000_82574_info = { + | FLAG_HAS_MSIX + | FLAG_HAS_JUMBO_FRAMES + | FLAG_HAS_WOL ++ | FLAG_HAS_HW_TIMESTAMP + | FLAG_APME_IN_CTRL3 + | FLAG_HAS_SMART_POWER_DOWN + | FLAG_HAS_AMT +@@ -2084,7 +2041,8 @@ const struct e1000_info e1000_82574_info = { + .flags2 = FLAG2_CHECK_PHY_HANG + | FLAG2_DISABLE_ASPM_L0S + | FLAG2_DISABLE_ASPM_L1 +- | FLAG2_NO_DISABLE_RX, ++ | FLAG2_NO_DISABLE_RX ++ | FLAG2_DMA_BURST, + .pba = 32, + .max_hw_frame_size = DEFAULT_JUMBO, + .get_variants = e1000_get_variants_82571, +@@ -2097,12 +2055,14 @@ const struct e1000_info e1000_82583_info = { + .mac = e1000_82583, + .flags = FLAG_HAS_HW_VLAN_FILTER + | FLAG_HAS_WOL ++ | FLAG_HAS_HW_TIMESTAMP + | FLAG_APME_IN_CTRL3 + | FLAG_HAS_SMART_POWER_DOWN + | FLAG_HAS_AMT + | FLAG_HAS_JUMBO_FRAMES + | FLAG_HAS_CTRLEXT_ON_LOAD, + .flags2 = FLAG2_DISABLE_ASPM_L0S ++ | FLAG2_DISABLE_ASPM_L1 + | FLAG2_NO_DISABLE_RX, + .pba = 32, + .max_hw_frame_size = DEFAULT_JUMBO, +@@ -2111,4 +2071,3 @@ const struct e1000_info e1000_82583_info = { + .phy_ops = &e82_phy_ops_bm, + .nvm_ops = &e82571_nvm_ops, + }; +- +diff --git a/drivers/net/ethernet/intel/e1000e/82571.h b/drivers/net/ethernet/intel/e1000e/82571.h +new file mode 100644 +index 0000000..08e24dc +--- /dev/null ++++ b/drivers/net/ethernet/intel/e1000e/82571.h +@@ -0,0 +1,60 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#ifndef _E1000E_82571_H_ ++#define _E1000E_82571_H_ ++ ++#define ID_LED_RESERVED_F746 0xF746 ++#define ID_LED_DEFAULT_82573 ((ID_LED_DEF1_DEF2 << 12) | \ ++ (ID_LED_OFF1_ON2 << 8) | \ ++ (ID_LED_DEF1_DEF2 << 4) | \ ++ (ID_LED_DEF1_DEF2)) ++ ++#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 ++#define AN_RETRY_COUNT 5 /* Autoneg Retry Count value */ ++ ++/* Intr Throttling - RW */ ++#define E1000_EITR_82574(_n) (0x000E8 + (0x4 * (_n))) ++ ++#define E1000_EIAC_82574 0x000DC /* Ext. Interrupt Auto Clear - RW */ ++#define E1000_EIAC_MASK_82574 0x01F00000 ++ ++#define E1000_IVAR_INT_ALLOC_VALID 0x8 ++ ++/* Manageability Operation Mode mask */ ++#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 ++ ++#define E1000_BASE1000T_STATUS 10 ++#define E1000_IDLE_ERROR_COUNT_MASK 0xFF ++#define E1000_RECEIVE_ERROR_COUNTER 21 ++#define E1000_RECEIVE_ERROR_MAX 0xFFFF ++bool e1000_check_phy_82574(struct e1000_hw *hw); ++bool e1000e_get_laa_state_82571(struct e1000_hw *hw); ++void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state); ++ ++#endif +diff --git a/drivers/net/ethernet/intel/e1000e/Makefile b/drivers/net/ethernet/intel/e1000e/Makefile +index 948c05d..3fd01f5 100644 +--- a/drivers/net/ethernet/intel/e1000e/Makefile ++++ b/drivers/net/ethernet/intel/e1000e/Makefile +@@ -1,7 +1,7 @@ + ################################################################################ + # + # Intel PRO/1000 Linux driver +-# Copyright(c) 1999 - 2011 Intel Corporation. ++# Copyright(c) 1999 - 2013 Intel Corporation. + # + # This program is free software; you can redistribute it and/or modify it + # under the terms and conditions of the GNU General Public License, +@@ -33,5 +33,7 @@ + obj-$(CONFIG_E1000E) += e1000e.o + + e1000e-objs := 82571.o ich8lan.o 80003es2lan.o \ +- lib.o phy.o param.o ethtool.o netdev.o ++ mac.o manage.o nvm.o phy.o \ ++ param.o ethtool.o netdev.o + ++e1000e-$(CONFIG_E1000E_PTP) += ptp.o +diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h +index c516a74..980a3f0 100644 +--- a/drivers/net/ethernet/intel/e1000e/defines.h ++++ b/drivers/net/ethernet/intel/e1000e/defines.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel PRO/1000 Linux driver +- Copyright(c) 1999 - 2011 Intel Corporation. ++ Copyright(c) 1999 - 2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -29,25 +29,6 @@ + #ifndef _E1000_DEFINES_H_ + #define _E1000_DEFINES_H_ + +-#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ +-#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ +-#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ +-#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ +-#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */ +-#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */ +-#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */ +-#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */ +-#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ +-#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */ +-#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */ +-#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */ +-#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */ +-#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */ +-#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */ +-#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ +-#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ +-#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ +- + /* Number of Transmit and Receive Descriptors must be a multiple of 8 */ + #define REQ_TX_DESCRIPTOR_MULTIPLE 8 + #define REQ_RX_DESCRIPTOR_MULTIPLE 8 +@@ -74,7 +55,9 @@ + #define E1000_WUS_BC E1000_WUFC_BC + + /* Extended Device Control */ ++#define E1000_CTRL_EXT_LPCD 0x00000004 /* LCD Power Cycle Done */ + #define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */ ++#define E1000_CTRL_EXT_FORCE_SMBUS 0x00000800 /* Force SMBus mode */ + #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ + #define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ + #define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ +@@ -83,8 +66,7 @@ + #define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 + #define E1000_CTRL_EXT_EIAME 0x01000000 + #define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ +-#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ +-#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ ++#define E1000_CTRL_EXT_IAME 0x08000000 /* Int ACK Auto-mask */ + #define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ + #define E1000_CTRL_EXT_LSECCK 0x00001000 + #define E1000_CTRL_EXT_PHYPDEN 0x00100000 +@@ -101,9 +83,11 @@ + #define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ + #define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ + #define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ ++#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ + #define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ + #define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ + ++#define E1000_RXDEXT_STATERR_TST 0x00000100 /* Time Stamp taken */ + #define E1000_RXDEXT_STATERR_CE 0x01000000 + #define E1000_RXDEXT_STATERR_SE 0x02000000 + #define E1000_RXDEXT_STATERR_SEQ 0x04000000 +@@ -112,19 +96,26 @@ + + /* mask to determine if packets should be dropped due to frame errors */ + #define E1000_RXD_ERR_FRAME_ERR_MASK ( \ +- E1000_RXD_ERR_CE | \ +- E1000_RXD_ERR_SE | \ +- E1000_RXD_ERR_SEQ | \ +- E1000_RXD_ERR_CXE | \ +- E1000_RXD_ERR_RXE) ++ E1000_RXD_ERR_CE | \ ++ E1000_RXD_ERR_SE | \ ++ E1000_RXD_ERR_SEQ | \ ++ E1000_RXD_ERR_CXE | \ ++ E1000_RXD_ERR_RXE) + + /* Same mask, but for extended and packet split descriptors */ + #define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \ +- E1000_RXDEXT_STATERR_CE | \ +- E1000_RXDEXT_STATERR_SE | \ +- E1000_RXDEXT_STATERR_SEQ | \ +- E1000_RXDEXT_STATERR_CXE | \ +- E1000_RXDEXT_STATERR_RXE) ++ E1000_RXDEXT_STATERR_CE | \ ++ E1000_RXDEXT_STATERR_SE | \ ++ E1000_RXDEXT_STATERR_SEQ | \ ++ E1000_RXDEXT_STATERR_CXE | \ ++ E1000_RXDEXT_STATERR_RXE) ++ ++#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000 ++#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 ++#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000 ++#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 ++#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000 ++#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 + + #define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000 + +@@ -174,8 +165,7 @@ + #define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ + #define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ + +-/* +- * Use byte values for the following shift parameters ++/* Use byte values for the following shift parameters + * Usage: + * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) & + * E1000_PSRCTL_BSIZE0_MASK) | +@@ -222,8 +212,11 @@ + #define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ + #define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */ + #define E1000_CTRL_LANPHYPC_VALUE 0x00020000 /* SW value of LANPHYPC */ ++#define E1000_CTRL_MEHE 0x00080000 /* Memory Error Handling Enable */ + #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ + #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ ++#define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */ ++#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 /* PHY PM enable */ + #define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ + #define E1000_CTRL_RST 0x04000000 /* Global reset */ + #define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ +@@ -231,10 +224,9 @@ + #define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ + #define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ + +-/* +- * Bit definitions for the Management Data IO (MDIO) and Management Data +- * Clock (MDC) pins in the Device Control Register. +- */ ++#define E1000_PCS_LCTL_FORCE_FCTRL 0x80 ++ ++#define E1000_PCS_LSTS_AN_COMPLETE 0x10000 + + /* Device Status */ + #define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ +@@ -243,19 +235,17 @@ + #define E1000_STATUS_FUNC_SHIFT 2 + #define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ + #define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ ++#define E1000_STATUS_SPEED_MASK 0x000000C0 + #define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ + #define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ + #define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ + #define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ + #define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */ +-#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ +- +-/* Constants used to interpret the masked PCI-X bus speed. */ ++#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master Req status */ + + #define HALF_DUPLEX 1 + #define FULL_DUPLEX 2 + +- + #define ADVERTISE_10_HALF 0x0001 + #define ADVERTISE_10_FULL 0x0002 + #define ADVERTISE_100_HALF 0x0004 +@@ -264,14 +254,15 @@ + #define ADVERTISE_1000_FULL 0x0020 + + /* 1000/H is not supported, nor spec-compliant. */ +-#define E1000_ALL_SPEED_DUPLEX ( ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ +- ADVERTISE_100_HALF | ADVERTISE_100_FULL | \ +- ADVERTISE_1000_FULL) +-#define E1000_ALL_NOT_GIG ( ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ +- ADVERTISE_100_HALF | ADVERTISE_100_FULL) +-#define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL) +-#define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL) +-#define E1000_ALL_HALF_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_100_HALF) ++#define E1000_ALL_SPEED_DUPLEX ( \ ++ ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \ ++ ADVERTISE_100_FULL | ADVERTISE_1000_FULL) ++#define E1000_ALL_NOT_GIG ( \ ++ ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \ ++ ADVERTISE_100_FULL) ++#define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL) ++#define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL) ++#define E1000_ALL_HALF_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_100_HALF) + + #define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX + +@@ -309,6 +300,7 @@ + #define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ + #define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ + #define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ ++#define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */ + + /* Transmit Control */ + #define E1000_TCTL_EN 0x00000002 /* enable Tx */ +@@ -318,14 +310,14 @@ + #define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ + #define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ + +-/* Transmit Arbitration Count */ +- + /* SerDes Control */ + #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 ++#define E1000_SCTL_ENABLE_SERDES_LOOPBACK 0x0410 + + /* Receive Checksum Control */ + #define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ + #define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ ++#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ + + /* Header split receive */ + #define E1000_RFCTL_NFSW_DIS 0x00000040 +@@ -373,12 +365,23 @@ + + #define E1000_KABGTXD_BGSQLBIAS 0x00050000 + ++/* Low Power IDLE Control */ ++#define E1000_LPIC_LPIET_SHIFT 24 /* Low Power Idle Entry Time */ ++ + /* PBA constants */ + #define E1000_PBA_8K 0x0008 /* 8KB */ + #define E1000_PBA_16K 0x0010 /* 16KB */ + ++#define E1000_PBA_RXA_MASK 0xFFFF ++ + #define E1000_PBS_16K E1000_PBA_16K + ++/* Uncorrectable/correctable ECC Error counts and enable bits */ ++#define E1000_PBECCSTS_CORR_ERR_CNT_MASK 0x000000FF ++#define E1000_PBECCSTS_UNCORR_ERR_CNT_MASK 0x0000FF00 ++#define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT 8 ++#define E1000_PBECCSTS_ECC_ENABLE 0x00010000 ++ + #define IFS_MAX 80 + #define IFS_MIN 40 + #define IFS_RATIO 4 +@@ -398,7 +401,9 @@ + #define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */ + #define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */ + #define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */ +-#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ ++#define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */ ++/* If this bit asserted, the driver should claim the interrupt */ ++#define E1000_ICR_INT_ASSERTED 0x80000000 + #define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ + #define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ + #define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */ +@@ -412,8 +417,7 @@ + #define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */ + #define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 for ECC */ + +-/* +- * This defines the bits that are set in the Interrupt Mask ++/* This defines the bits that are set in the Interrupt Mask + * Set/Read Register. Each bit is documented below: + * o RXT0 = Receiver Timer Interrupt (ring 0) + * o TXDW = Transmit Descriptor Written Back +@@ -422,11 +426,11 @@ + * o LSC = Link Status Change + */ + #define IMS_ENABLE_MASK ( \ +- E1000_IMS_RXT0 | \ +- E1000_IMS_TXDW | \ +- E1000_IMS_RXDMT0 | \ +- E1000_IMS_RXSEQ | \ +- E1000_IMS_LSC) ++ E1000_IMS_RXT0 | \ ++ E1000_IMS_TXDW | \ ++ E1000_IMS_RXDMT0 | \ ++ E1000_IMS_RXSEQ | \ ++ E1000_IMS_LSC) + + /* Interrupt Mask Set */ + #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ +@@ -434,6 +438,7 @@ + #define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ + #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ + #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ ++#define E1000_IMS_ECCER E1000_ICR_ECCER /* Uncorrectable ECC Error */ + #define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ + #define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ + #define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */ +@@ -463,8 +468,7 @@ + /* 802.1q VLAN Packet Size */ + #define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ + +-/* Receive Address */ +-/* ++/* Receive Address + * Number of high/low register pairs in the RAR. The RAR (Receive Address + * Registers) holds the directed and multicast addresses that we monitor. + * Technically, we have 16 spots. However, we reserve one of these spots +@@ -525,6 +529,28 @@ + #define E1000_RXCW_C 0x20000000 /* Receive config */ + #define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ + ++#define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */ ++#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ ++ ++#define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */ ++#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */ ++#define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00 ++#define E1000_TSYNCRXCTL_TYPE_L4_V1 0x02 ++#define E1000_TSYNCRXCTL_TYPE_L2_L4_V2 0x04 ++#define E1000_TSYNCRXCTL_TYPE_ALL 0x08 ++#define E1000_TSYNCRXCTL_TYPE_EVENT_V2 0x0A ++#define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */ ++#define E1000_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */ ++ ++#define E1000_RXMTRL_PTP_V1_SYNC_MESSAGE 0x00000000 ++#define E1000_RXMTRL_PTP_V1_DELAY_REQ_MESSAGE 0x00010000 ++ ++#define E1000_RXMTRL_PTP_V2_SYNC_MESSAGE 0x00000000 ++#define E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE 0x01000000 ++ ++#define E1000_TIMINCA_INCPERIOD_SHIFT 24 ++#define E1000_TIMINCA_INCVALUE_MASK 0x00FFFFFF ++ + /* PCI Express Control */ + #define E1000_GCR_RXD_NO_SNOOP 0x00000001 + #define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 +@@ -540,65 +566,6 @@ + E1000_GCR_TXDSCW_NO_SNOOP | \ + E1000_GCR_TXDSCR_NO_SNOOP) + +-/* PHY Control Register */ +-#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ +-#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ +-#define MII_CR_POWER_DOWN 0x0800 /* Power down */ +-#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ +-#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ +-#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ +-#define MII_CR_SPEED_1000 0x0040 +-#define MII_CR_SPEED_100 0x2000 +-#define MII_CR_SPEED_10 0x0000 +- +-/* PHY Status Register */ +-#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ +-#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ +- +-/* Autoneg Advertisement Register */ +-#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ +-#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ +-#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ +-#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ +-#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ +-#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ +- +-/* Link Partner Ability Register (Base Page) */ +-#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ +-#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */ +- +-/* Autoneg Expansion Register */ +-#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */ +- +-/* 1000BASE-T Control Register */ +-#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ +-#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ +- /* 0=DTE device */ +-#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */ +- /* 0=Configure PHY as Slave */ +-#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ +- /* 0=Automatic Master/Slave config */ +- +-/* 1000BASE-T Status Register */ +-#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ +-#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ +- +- +-/* PHY 1000 MII Register/Bit Definitions */ +-/* PHY Registers defined by IEEE */ +-#define PHY_CONTROL 0x00 /* Control Register */ +-#define PHY_STATUS 0x01 /* Status Register */ +-#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ +-#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ +-#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ +-#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ +-#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ +-#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ +-#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ +-#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ +- +-#define PHY_CONTROL_LB 0x4000 /* PHY Loopback bit */ +- + /* NVM Control */ + #define E1000_EECD_SK 0x00000001 /* NVM Clock */ + #define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ +@@ -619,17 +586,21 @@ + #define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */ + #define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES) + +-#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write registers */ +-#define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ +-#define E1000_NVM_RW_REG_START 1 /* Start operation */ +-#define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ +-#define E1000_NVM_POLL_WRITE 1 /* Flag for polling for write complete */ +-#define E1000_NVM_POLL_READ 0 /* Flag for polling for read complete */ +-#define E1000_FLASH_UPDATES 2000 ++#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM r/w regs */ ++#define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ ++#define E1000_NVM_RW_REG_START 1 /* Start operation */ ++#define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ ++#define E1000_NVM_POLL_WRITE 1 /* Flag for polling write complete */ ++#define E1000_NVM_POLL_READ 0 /* Flag for polling read complete */ ++#define E1000_FLASH_UPDATES 2000 + + /* NVM Word Offsets */ + #define NVM_COMPAT 0x0003 + #define NVM_ID_LED_SETTINGS 0x0004 ++#define NVM_FUTURE_INIT_WORD1 0x0019 ++#define NVM_COMPAT_VALID_CSUM 0x0001 ++#define NVM_FUTURE_INIT_WORD1_VALID_CSUM 0x0040 ++ + #define NVM_INIT_CONTROL2_REG 0x000F + #define NVM_INIT_CONTROL3_PORT_B 0x0014 + #define NVM_INIT_3GIO_3 0x001A +@@ -638,8 +609,6 @@ + #define NVM_ALT_MAC_ADDR_PTR 0x0037 + #define NVM_CHECKSUM_REG 0x003F + +-#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */ +- + #define E1000_NVM_CFG_DONE_PORT_0 0x40000 /* MNG config cycle done */ + #define E1000_NVM_CFG_DONE_PORT_1 0x80000 /* ...for second port */ + +@@ -710,8 +679,7 @@ + #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ + #define MAX_PHY_MULTI_PAGE_REG 0xF + +-/* Bit definitions for valid PHY IDs. */ +-/* ++/* Bit definitions for valid PHY IDs. + * I = Integrated + * E = External + */ +@@ -730,6 +698,7 @@ + #define I82577_E_PHY_ID 0x01540050 + #define I82578_E_PHY_ID 0x004DD040 + #define I82579_E_PHY_ID 0x01540090 ++#define I217_E_PHY_ID 0x015400A0 + + /* M88E1000 Specific Registers */ + #define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ +@@ -748,10 +717,6 @@ + #define M88E1000_PSCR_AUTO_X_1000T 0x0040 + /* Auto crossover enabled all speeds */ + #define M88E1000_PSCR_AUTO_X_MODE 0x0060 +-/* +- * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold) +- * 0=Normal 10BASE-T Rx Threshold +- */ + #define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ + + /* M88E1000 PHY Specific Status Register */ +@@ -765,14 +730,12 @@ + + #define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 + +-/* +- * Number of times we will attempt to autonegotiate before downshifting if we ++/* Number of times we will attempt to autonegotiate before downshifting if we + * are the master + */ + #define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 + #define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 +-/* +- * Number of times we will attempt to autonegotiate before downshifting if we ++/* Number of times we will attempt to autonegotiate before downshifting if we + * are the slave + */ + #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 +@@ -789,13 +752,7 @@ + /* BME1000 PHY Specific Control Register */ + #define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */ + +- +-#define PHY_PAGE_SHIFT 5 +-#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \ +- ((reg) & MAX_PHY_REG_ADDRESS)) +- +-/* +- * Bits... ++/* Bits... + * 15-5: page + * 4-0: register offset + */ +@@ -831,6 +788,7 @@ + GG82563_REG(194, 18) /* Inband Control */ + + /* MDI Control */ ++#define E1000_MDIC_REG_MASK 0x001F0000 + #define E1000_MDIC_REG_SHIFT 16 + #define E1000_MDIC_PHY_SHIFT 21 + #define E1000_MDIC_OP_WRITE 0x04000000 +diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h +index 8e362bb..dcecaa6 100644 +--- a/drivers/net/ethernet/intel/e1000e/e1000.h ++++ b/drivers/net/ethernet/intel/e1000e/e1000.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel PRO/1000 Linux driver +- Copyright(c) 1999 - 2011 Intel Corporation. ++ Copyright(c) 1999 - 2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -41,7 +41,12 @@ + #include + #include + #include +- ++#include ++#include ++#include ++#include ++#include ++#include + #include "hw.h" + + struct e1000_info; +@@ -57,7 +62,6 @@ struct e1000_info; + #define e_notice(format, arg...) \ + netdev_notice(adapter->netdev, format, ## arg) + +- + /* Interrupt modes, as used by the IntMode parameter */ + #define E1000E_INT_MODE_LEGACY 0 + #define E1000E_INT_MODE_MSI 1 +@@ -75,9 +79,6 @@ struct e1000_info; + #define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */ + #define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */ + +-/* Early Receive defines */ +-#define E1000_ERT_2048 0x100 +- + #define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */ + + /* How many Tx Descriptors do we need to call netif_wake_queue ? */ +@@ -89,93 +90,30 @@ struct e1000_info; + + #define E1000_MNG_VLAN_NONE (-1) + +-/* Number of packet split data buffers (not including the header buffer) */ +-#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) +- + #define DEFAULT_JUMBO 9234 + +-/* BM/HV Specific Registers */ +-#define BM_PORT_CTRL_PAGE 769 +- +-#define PHY_UPPER_SHIFT 21 +-#define BM_PHY_REG(page, reg) \ +- (((reg) & MAX_PHY_REG_ADDRESS) |\ +- (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\ +- (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT))) +- +-/* PHY Wakeup Registers and defines */ +-#define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17) +-#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0) +-#define BM_WUC PHY_REG(BM_WUC_PAGE, 1) +-#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2) +-#define BM_WUS PHY_REG(BM_WUC_PAGE, 3) +-#define BM_RAR_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2))) +-#define BM_RAR_M(_i) (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2))) +-#define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2))) +-#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2))) +-#define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1))) +- +-#define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */ +-#define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */ +-#define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */ +-#define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */ +-#define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */ +-#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */ +-#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */ +- +-#define HV_STATS_PAGE 778 +-#define HV_SCC_UPPER PHY_REG(HV_STATS_PAGE, 16) /* Single Collision Count */ +-#define HV_SCC_LOWER PHY_REG(HV_STATS_PAGE, 17) +-#define HV_ECOL_UPPER PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. Count */ +-#define HV_ECOL_LOWER PHY_REG(HV_STATS_PAGE, 19) +-#define HV_MCC_UPPER PHY_REG(HV_STATS_PAGE, 20) /* Multiple Coll. Count */ +-#define HV_MCC_LOWER PHY_REG(HV_STATS_PAGE, 21) +-#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision Count */ +-#define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24) +-#define HV_COLC_UPPER PHY_REG(HV_STATS_PAGE, 25) /* Collision Count */ +-#define HV_COLC_LOWER PHY_REG(HV_STATS_PAGE, 26) +-#define HV_DC_UPPER PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */ +-#define HV_DC_LOWER PHY_REG(HV_STATS_PAGE, 28) +-#define HV_TNCRS_UPPER PHY_REG(HV_STATS_PAGE, 29) /* Transmit with no CRS */ +-#define HV_TNCRS_LOWER PHY_REG(HV_STATS_PAGE, 30) +- +-#define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */ +- +-/* BM PHY Copper Specific Status */ +-#define BM_CS_STATUS 17 +-#define BM_CS_STATUS_LINK_UP 0x0400 +-#define BM_CS_STATUS_RESOLVED 0x0800 +-#define BM_CS_STATUS_SPEED_MASK 0xC000 +-#define BM_CS_STATUS_SPEED_1000 0x8000 +- +-/* 82577 Mobile Phy Status Register */ +-#define HV_M_STATUS 26 +-#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 +-#define HV_M_STATUS_SPEED_MASK 0x0300 +-#define HV_M_STATUS_SPEED_1000 0x0200 +-#define HV_M_STATUS_LINK_UP 0x0040 +- +-#define E1000_ICH_FWSM_PCIM2PCI 0x01000000 /* ME PCIm-to-PCI active */ +-#define E1000_ICH_FWSM_PCIM2PCI_COUNT 2000 +- + /* Time to wait before putting the device into D3 if there's no link (in ms). */ + #define LINK_TIMEOUT 100 + ++/* Count for polling __E1000_RESET condition every 10-20msec. ++ * Experimentation has shown the reset can take approximately 210msec. ++ */ ++#define E1000_CHECK_RESET_COUNT 25 ++ + #define DEFAULT_RDTR 0 + #define DEFAULT_RADV 8 + #define BURST_RDTR 0x20 + #define BURST_RADV 0x20 + +-/* +- * in the case of WTHRESH, it appears at least the 82571/2 hardware ++/* in the case of WTHRESH, it appears at least the 82571/2 hardware + * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when +- * WTHRESH=4, and since we want 64 bytes at a time written back, set +- * it to 5 ++ * WTHRESH=4, so a setting of 5 gives the most efficient bus ++ * utilization but to avoid possible Tx stalls, set it to 1 + */ + #define E1000_TXDCTL_DMA_BURST_ENABLE \ + (E1000_TXDCTL_GRAN | /* set descriptor granularity */ \ + E1000_TXDCTL_COUNT_DESC | \ +- (5 << 16) | /* wthresh must be +1 more than desired */\ ++ (1 << 16) | /* wthresh must be +1 more than desired */\ + (1 << 8) | /* hthresh */ \ + 0x1f) /* pthresh */ + +@@ -200,6 +138,7 @@ enum e1000_boards { + board_ich10lan, + board_pchlan, + board_pch2lan, ++ board_pch_lpt, + }; + + struct e1000_ps_page { +@@ -207,8 +146,7 @@ struct e1000_ps_page { + u64 dma; /* must be u64 - written to hw */ + }; + +-/* +- * wrappers around a pointer to a socket buffer, ++/* wrappers around a pointer to a socket buffer, + * so a DMA handle can be stored along with the buffer + */ + struct e1000_buffer { +@@ -234,6 +172,7 @@ struct e1000_buffer { + }; + + struct e1000_ring { ++ struct e1000_adapter *adapter; /* back pointer to adapter */ + void *desc; /* pointer to ring memory */ + dma_addr_t dma; /* phys address of ring */ + unsigned int size; /* length of ring in bytes */ +@@ -242,8 +181,8 @@ struct e1000_ring { + u16 next_to_use; + u16 next_to_clean; + +- u16 head; +- u16 tail; ++ void __iomem *head; ++ void __iomem *tail; + + /* array of buffer information structs */ + struct e1000_buffer *buffer_info; +@@ -251,7 +190,7 @@ struct e1000_ring { + char name[IFNAMSIZ + 5]; + u32 ims_val; + u32 itr_val; +- u16 itr_register; ++ void __iomem *itr_register; + int set_itr; + + struct sk_buff *rx_skb_top; +@@ -297,15 +236,14 @@ struct e1000_adapter { + u16 tx_itr; + u16 rx_itr; + +- /* +- * Tx +- */ +- struct e1000_ring *tx_ring /* One per active queue */ +- ____cacheline_aligned_in_smp; ++ /* Tx - one ring per active queue */ ++ struct e1000_ring *tx_ring ____cacheline_aligned_in_smp; + u32 tx_fifo_limit; + + struct napi_struct napi; + ++ unsigned int uncorr_errors; /* uncorrectable ECC errors */ ++ unsigned int corr_errors; /* correctable ECC errors */ + unsigned int restart_queue; + u32 txd_cmd; + +@@ -332,14 +270,11 @@ struct e1000_adapter { + u32 tx_fifo_size; + u32 tx_dma_failed; + +- /* +- * Rx +- */ +- bool (*clean_rx) (struct e1000_adapter *adapter, +- int *work_done, int work_to_do) +- ____cacheline_aligned_in_smp; +- void (*alloc_rx_buf) (struct e1000_adapter *adapter, +- int cleaned_count, gfp_t gfp); ++ /* Rx */ ++ bool (*clean_rx) (struct e1000_ring *ring, int *work_done, ++ int work_to_do) ____cacheline_aligned_in_smp; ++ void (*alloc_rx_buf) (struct e1000_ring *ring, int cleaned_count, ++ gfp_t gfp); + struct e1000_ring *rx_ring; + + u32 rx_int_delay; +@@ -353,6 +288,7 @@ struct e1000_adapter { + u64 gorc_old; + u32 alloc_rx_buff_failed; + u32 rx_dma_failed; ++ u32 rx_hwtstamp_cleared; + + unsigned int rx_ps_pages; + u16 rx_ps_bsize0; +@@ -366,7 +302,7 @@ struct e1000_adapter { + /* structs defined in e1000_hw.h */ + struct e1000_hw hw; + +- spinlock_t stats64_lock; ++ spinlock_t stats64_lock; /* protects statistics counters */ + struct e1000_hw_stats stats; + struct e1000_phy_info phy_info; + struct e1000_phy_stats phy_stats; +@@ -399,6 +335,23 @@ struct e1000_adapter { + + bool idle_check; + int phy_hang_count; ++ ++ u16 tx_ring_count; ++ u16 rx_ring_count; ++ ++#ifdef CONFIG_E1000E_PTP ++ struct hwtstamp_config hwtstamp_config; ++ struct delayed_work systim_overflow_work; ++ struct sk_buff *tx_hwtstamp_skb; ++ struct work_struct tx_hwtstamp_work; ++ spinlock_t systim_lock; /* protects SYSTIML/H regsters */ ++ struct cyclecounter cc; ++ struct timecounter tc; ++ struct ptp_clock *ptp_clock; ++ struct ptp_clock_info ptp_clock_info; ++#endif ++ ++ u16 eee_advert; + }; + + struct e1000_info { +@@ -413,12 +366,46 @@ struct e1000_info { + const struct e1000_nvm_operations *nvm_ops; + }; + ++s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca); ++ ++/* The system time is maintained by a 64-bit counter comprised of the 32-bit ++ * SYSTIMH and SYSTIML registers. How the counter increments (and therefore ++ * its resolution) is based on the contents of the TIMINCA register - it ++ * increments every incperiod (bits 31:24) clock ticks by incvalue (bits 23:0). ++ * For the best accuracy, the incperiod should be as small as possible. The ++ * incvalue is scaled by a factor as large as possible (while still fitting ++ * in bits 23:0) so that relatively small clock corrections can be made. ++ * ++ * As a result, a shift of INCVALUE_SHIFT_n is used to fit a value of ++ * INCVALUE_n into the TIMINCA register allowing 32+8+(24-INCVALUE_SHIFT_n) ++ * bits to count nanoseconds leaving the rest for fractional nonseconds. ++ */ ++#define INCVALUE_96MHz 125 ++#define INCVALUE_SHIFT_96MHz 17 ++#define INCPERIOD_SHIFT_96MHz 2 ++#define INCPERIOD_96MHz (12 >> INCPERIOD_SHIFT_96MHz) ++ ++#define INCVALUE_25MHz 40 ++#define INCVALUE_SHIFT_25MHz 18 ++#define INCPERIOD_25MHz 1 ++ ++/* Another drawback of scaling the incvalue by a large factor is the ++ * 64-bit SYSTIM register overflows more quickly. This is dealt with ++ * by simply reading the clock before it overflows. ++ * ++ * Clock ns bits Overflows after ++ * ~~~~~~ ~~~~~~~ ~~~~~~~~~~~~~~~ ++ * 96MHz 47-bit 2^(47-INCPERIOD_SHIFT_96MHz) / 10^9 / 3600 = 9.77 hrs ++ * 25MHz 46-bit 2^46 / 10^9 / 3600 = 19.55 hours ++ */ ++#define E1000_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 60 * 4) ++ + /* hardware capability, feature, and workaround flags */ + #define FLAG_HAS_AMT (1 << 0) + #define FLAG_HAS_FLASH (1 << 1) + #define FLAG_HAS_HW_VLAN_FILTER (1 << 2) + #define FLAG_HAS_WOL (1 << 3) +-#define FLAG_HAS_ERT (1 << 4) ++/* reserved bit4 */ + #define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5) + #define FLAG_HAS_SWSM_ON_LOAD (1 << 6) + #define FLAG_HAS_JUMBO_FRAMES (1 << 7) +@@ -428,7 +415,7 @@ struct e1000_info { + #define FLAG_HAS_SMART_POWER_DOWN (1 << 11) + #define FLAG_IS_QUAD_PORT_A (1 << 12) + #define FLAG_IS_QUAD_PORT (1 << 13) +-#define FLAG_TIPG_MEDIUM_FOR_80003ESLAN (1 << 14) ++#define FLAG_HAS_HW_TIMESTAMP (1 << 14) + #define FLAG_APME_IN_WUC (1 << 15) + #define FLAG_APME_IN_CTRL3 (1 << 16) + #define FLAG_APME_CHECK_PORT_B (1 << 17) +@@ -444,7 +431,7 @@ struct e1000_info { + #define FLAG_MSI_ENABLED (1 << 27) + /* reserved (1 << 28) */ + #define FLAG_TSO_FORCE (1 << 29) +-#define FLAG_RX_RESTART_NOW (1 << 30) ++#define FLAG_RESTART_NOW (1 << 30) + #define FLAG_MSI_TEST_FAILED (1 << 31) + + #define FLAG2_CRC_STRIPPING (1 << 0) +@@ -459,6 +446,7 @@ struct e1000_info { + #define FLAG2_CHECK_PHY_HANG (1 << 9) + #define FLAG2_NO_DISABLE_RX (1 << 10) + #define FLAG2_PCIM2PCI_ARBITER_WA (1 << 11) ++#define FLAG2_CHECK_RX_HWTSTAMP (1 << 13) + + #define E1000_RX_DESC_PS(R, i) \ + (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) +@@ -485,30 +473,28 @@ enum latency_range { + extern char e1000e_driver_name[]; + extern const char e1000e_driver_version[]; + +-extern void e1000e_check_options(struct e1000_adapter *adapter); +-extern void e1000e_set_ethtool_ops(struct net_device *netdev); +- +-extern int e1000e_up(struct e1000_adapter *adapter); +-extern void e1000e_down(struct e1000_adapter *adapter); +-extern void e1000e_reinit_locked(struct e1000_adapter *adapter); +-extern void e1000e_reset(struct e1000_adapter *adapter); +-extern void e1000e_power_up_phy(struct e1000_adapter *adapter); +-extern int e1000e_setup_rx_resources(struct e1000_adapter *adapter); +-extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter); +-extern void e1000e_free_rx_resources(struct e1000_adapter *adapter); +-extern void e1000e_free_tx_resources(struct e1000_adapter *adapter); +-extern struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, +- struct rtnl_link_stats64 +- *stats); +-extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); +-extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); +-extern void e1000e_get_hw_control(struct e1000_adapter *adapter); +-extern void e1000e_release_hw_control(struct e1000_adapter *adapter); ++void e1000e_check_options(struct e1000_adapter *adapter); ++void e1000e_set_ethtool_ops(struct net_device *netdev); ++ ++int e1000e_up(struct e1000_adapter *adapter); ++void e1000e_down(struct e1000_adapter *adapter); ++void e1000e_reinit_locked(struct e1000_adapter *adapter); ++void e1000e_reset(struct e1000_adapter *adapter); ++void e1000e_power_up_phy(struct e1000_adapter *adapter); ++int e1000e_setup_rx_resources(struct e1000_ring *ring); ++int e1000e_setup_tx_resources(struct e1000_ring *ring); ++void e1000e_free_rx_resources(struct e1000_ring *ring); ++void e1000e_free_tx_resources(struct e1000_ring *ring); ++struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, ++ struct rtnl_link_stats64 *stats); ++void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); ++void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); ++void e1000e_get_hw_control(struct e1000_adapter *adapter); ++void e1000e_release_hw_control(struct e1000_adapter *adapter); ++void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr); + + extern unsigned int copybreak; + +-extern char *e1000e_get_hw_dev_name(struct e1000_hw *hw); +- + extern const struct e1000_info e1000_82571_info; + extern const struct e1000_info e1000_82572_info; + extern const struct e1000_info e1000_82573_info; +@@ -519,154 +505,25 @@ extern const struct e1000_info e1000_ich9_info; + extern const struct e1000_info e1000_ich10_info; + extern const struct e1000_info e1000_pch_info; + extern const struct e1000_info e1000_pch2_info; ++extern const struct e1000_info e1000_pch_lpt_info; + extern const struct e1000_info e1000_es2_info; + +-extern s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, +- u32 pba_num_size); +- +-extern s32 e1000e_commit_phy(struct e1000_hw *hw); +- +-extern bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw); +- +-extern bool e1000e_get_laa_state_82571(struct e1000_hw *hw); +-extern void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state); +- +-extern void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw); +-extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, +- bool state); +-extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); +-extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); +-extern void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw); +-extern void e1000_resume_workarounds_pchlan(struct e1000_hw *hw); +-extern s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); +-extern s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable); +-extern void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw); +- +-extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw); +-extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw); +-extern s32 e1000e_check_for_serdes_link(struct e1000_hw *hw); +-extern s32 e1000e_setup_led_generic(struct e1000_hw *hw); +-extern s32 e1000e_cleanup_led_generic(struct e1000_hw *hw); +-extern s32 e1000e_led_on_generic(struct e1000_hw *hw); +-extern s32 e1000e_led_off_generic(struct e1000_hw *hw); +-extern s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw); +-extern void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); +-extern void e1000_set_lan_id_single_port(struct e1000_hw *hw); +-extern s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex); +-extern s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex); +-extern s32 e1000e_disable_pcie_master(struct e1000_hw *hw); +-extern s32 e1000e_get_auto_rd_done(struct e1000_hw *hw); +-extern s32 e1000e_id_led_init(struct e1000_hw *hw); +-extern void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw); +-extern s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw); +-extern s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw); +-extern s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw); +-extern s32 e1000e_setup_link(struct e1000_hw *hw); +-extern void e1000_clear_vfta_generic(struct e1000_hw *hw); +-extern void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); +-extern void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, +- u8 *mc_addr_list, +- u32 mc_addr_count); +-extern void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); +-extern s32 e1000e_set_fc_watermarks(struct e1000_hw *hw); +-extern void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop); +-extern s32 e1000e_get_hw_semaphore(struct e1000_hw *hw); +-extern s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data); +-extern void e1000e_config_collision_dist(struct e1000_hw *hw); +-extern s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw); +-extern s32 e1000e_force_mac_fc(struct e1000_hw *hw); +-extern s32 e1000e_blink_led_generic(struct e1000_hw *hw); +-extern void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); +-extern s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); +-extern void e1000e_reset_adaptive(struct e1000_hw *hw); +-extern void e1000e_update_adaptive(struct e1000_hw *hw); +- +-extern s32 e1000e_setup_copper_link(struct e1000_hw *hw); +-extern s32 e1000e_get_phy_id(struct e1000_hw *hw); +-extern void e1000e_put_hw_semaphore(struct e1000_hw *hw); +-extern s32 e1000e_check_reset_block_generic(struct e1000_hw *hw); +-extern s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw); +-extern s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw); +-extern s32 e1000e_get_phy_info_igp(struct e1000_hw *hw); +-extern s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page); +-extern s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); +-extern s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, +- u16 *data); +-extern s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw); +-extern s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active); +-extern s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); +-extern s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, +- u16 data); +-extern s32 e1000e_phy_sw_reset(struct e1000_hw *hw); +-extern s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw); +-extern s32 e1000e_get_cfg_done(struct e1000_hw *hw); +-extern s32 e1000e_get_cable_length_m88(struct e1000_hw *hw); +-extern s32 e1000e_get_phy_info_m88(struct e1000_hw *hw); +-extern s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); +-extern s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); +-extern s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw); +-extern enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id); +-extern s32 e1000e_determine_phy_address(struct e1000_hw *hw); +-extern s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); +-extern s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); +-extern s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, +- u16 *phy_reg); +-extern s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, +- u16 *phy_reg); +-extern s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data); +-extern s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data); +-extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); +-extern s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); +-extern s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, +- u16 data); +-extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); +-extern s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, +- u16 *data); +-extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, +- u32 usec_interval, bool *success); +-extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); +-extern void e1000_power_up_phy_copper(struct e1000_hw *hw); +-extern void e1000_power_down_phy_copper(struct e1000_hw *hw); +-extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); +-extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); +-extern s32 e1000e_check_downshift(struct e1000_hw *hw); +-extern s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data); +-extern s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, +- u16 *data); +-extern s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, +- u16 *data); +-extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data); +-extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, +- u16 data); +-extern s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, +- u16 data); +-extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw); +-extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); +-extern s32 e1000_check_polarity_82577(struct e1000_hw *hw); +-extern s32 e1000_get_phy_info_82577(struct e1000_hw *hw); +-extern s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw); +-extern s32 e1000_get_cable_length_82577(struct e1000_hw *hw); +- +-extern s32 e1000_check_polarity_m88(struct e1000_hw *hw); +-extern s32 e1000_get_phy_info_ife(struct e1000_hw *hw); +-extern s32 e1000_check_polarity_ife(struct e1000_hw *hw); +-extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); +-extern s32 e1000_check_polarity_igp(struct e1000_hw *hw); +-extern bool e1000_check_phy_82574(struct e1000_hw *hw); ++void e1000e_ptp_init(struct e1000_adapter *adapter); ++void e1000e_ptp_remove(struct e1000_adapter *adapter); + + static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) + { + return hw->phy.ops.reset(hw); + } + +-static inline s32 e1000_check_reset_block(struct e1000_hw *hw) ++static inline s32 e1e_rphy(struct e1000_hw *hw, u32 offset, u16 *data) + { +- return hw->phy.ops.check_reset_block(hw); ++ return hw->phy.ops.read_reg(hw, offset, data); + } + +-static inline s32 e1e_rphy(struct e1000_hw *hw, u32 offset, u16 *data) ++static inline s32 e1e_rphy_locked(struct e1000_hw *hw, u32 offset, u16 *data) + { +- return hw->phy.ops.read_reg(hw, offset, data); ++ return hw->phy.ops.read_reg_locked(hw, offset, data); + } + + static inline s32 e1e_wphy(struct e1000_hw *hw, u32 offset, u16 data) +@@ -674,20 +531,12 @@ static inline s32 e1e_wphy(struct e1000_hw *hw, u32 offset, u16 data) + return hw->phy.ops.write_reg(hw, offset, data); + } + +-static inline s32 e1000_get_cable_length(struct e1000_hw *hw) ++static inline s32 e1e_wphy_locked(struct e1000_hw *hw, u32 offset, u16 data) + { +- return hw->phy.ops.get_cable_length(hw); ++ return hw->phy.ops.write_reg_locked(hw, offset, data); + } + +-extern s32 e1000e_acquire_nvm(struct e1000_hw *hw); +-extern s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); +-extern s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw); +-extern s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); +-extern s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); +-extern s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw); +-extern void e1000e_release_nvm(struct e1000_hw *hw); +-extern void e1000e_reload_nvm(struct e1000_hw *hw); +-extern s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); ++void e1000e_reload_nvm_generic(struct e1000_hw *hw); + + static inline s32 e1000e_read_mac_addr(struct e1000_hw *hw) + { +@@ -707,12 +556,14 @@ static inline s32 e1000e_update_nvm_checksum(struct e1000_hw *hw) + return hw->nvm.ops.update(hw); + } + +-static inline s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) ++static inline s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, ++ u16 *data) + { + return hw->nvm.ops.read(hw, offset, words, data); + } + +-static inline s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) ++static inline s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, ++ u16 *data) + { + return hw->nvm.ops.write(hw, offset, words, data); + } +@@ -722,23 +573,51 @@ static inline s32 e1000_get_phy_info(struct e1000_hw *hw) + return hw->phy.ops.get_info(hw); + } + +-static inline s32 e1000e_check_mng_mode(struct e1000_hw *hw) ++static inline u32 __er32(struct e1000_hw *hw, unsigned long reg) + { +- return hw->mac.ops.check_mng_mode(hw); ++ return readl(hw->hw_addr + reg); + } + +-extern bool e1000e_check_mng_mode_generic(struct e1000_hw *hw); +-extern bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw); +-extern s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length); +- +-static inline u32 __er32(struct e1000_hw *hw, unsigned long reg) ++#define er32(reg) __er32(hw, E1000_##reg) ++ ++/** ++ * __ew32_prepare - prepare to write to MAC CSR register on certain parts ++ * @hw: pointer to the HW structure ++ * ++ * When updating the MAC CSR registers, the Manageability Engine (ME) could ++ * be accessing the registers at the same time. Normally, this is handled in ++ * h/w by an arbiter but on some parts there is a bug that acknowledges Host ++ * accesses later than it should which could result in the register to have ++ * an incorrect value. Workaround this by checking the FWSM register which ++ * has bit 24 set while ME is accessing MAC CSR registers, wait if it is set ++ * and try again a number of times. ++ **/ ++static inline s32 __ew32_prepare(struct e1000_hw *hw) + { +- return readl(hw->hw_addr + reg); ++ s32 i = E1000_ICH_FWSM_PCIM2PCI_COUNT; ++ ++ while ((er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI) && --i) ++ udelay(50); ++ ++ return i; + } + + static inline void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val) + { ++ if (hw->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) ++ __ew32_prepare(hw); ++ + writel(val, hw->hw_addr + reg); + } + ++#define ew32(reg, val) __ew32(hw, E1000_##reg, (val)) ++ ++#define e1e_flush() er32(STATUS) ++ ++#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \ ++ (__ew32((a), (reg + ((offset) << 2)), (value))) ++ ++#define E1000_READ_REG_ARRAY(a, reg, offset) \ ++ (readl((a)->hw_addr + reg + ((offset) << 2))) ++ + #endif /* _E1000_H_ */ +diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c +index 69c9d21..1cba3e1 100644 +--- a/drivers/net/ethernet/intel/e1000e/ethtool.c ++++ b/drivers/net/ethernet/intel/e1000e/ethtool.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel PRO/1000 Linux driver +- Copyright(c) 1999 - 2011 Intel Corporation. ++ Copyright(c) 1999 - 2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -34,10 +34,12 @@ + #include + #include + #include ++#include ++#include + + #include "e1000.h" + +-enum {NETDEV_STATS, E1000_STATS}; ++enum { NETDEV_STATS, E1000_STATS }; + + struct e1000_stats { + char stat_string[ETH_GSTRING_LEN]; +@@ -97,7 +99,6 @@ static const struct e1000_stats e1000_gstrings_stats[] = { + E1000_STAT("rx_flow_control_xoff", stats.xoffrxc), + E1000_STAT("tx_flow_control_xon", stats.xontxc), + E1000_STAT("tx_flow_control_xoff", stats.xofftxc), +- E1000_STAT("rx_long_byte_count", stats.gorc), + E1000_STAT("rx_csum_offload_good", hw_csum_good), + E1000_STAT("rx_csum_offload_errors", hw_csum_err), + E1000_STAT("rx_header_split", rx_hdr_split), +@@ -107,6 +108,11 @@ static const struct e1000_stats e1000_gstrings_stats[] = { + E1000_STAT("dropped_smbus", stats.mgpdc), + E1000_STAT("rx_dma_failed", rx_dma_failed), + E1000_STAT("tx_dma_failed", tx_dma_failed), ++#ifdef CONFIG_E1000E_PTP ++ E1000_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared), ++#endif ++ E1000_STAT("uncorr_ecc_errors", uncorr_errors), ++ E1000_STAT("corr_ecc_errors", corr_errors), + }; + + #define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats) +@@ -116,6 +122,7 @@ static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { + "Interrupt test (offline)", "Loopback test (offline)", + "Link test (on/offline)" + }; ++ + #define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test) + + static int e1000_get_settings(struct net_device *netdev, +@@ -126,7 +133,6 @@ static int e1000_get_settings(struct net_device *netdev, + u32 speed; + + if (hw->phy.media_type == e1000_media_type_copper) { +- + ecmd->supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | +@@ -169,7 +175,7 @@ static int e1000_get_settings(struct net_device *netdev, + speed = adapter->link_speed; + ecmd->duplex = adapter->link_duplex - 1; + } +- } else { ++ } else if (!pm_runtime_suspended(netdev->dev.parent)) { + u32 status = er32(STATUS); + if (status & E1000_STATUS_LU) { + if (status & E1000_STATUS_SPEED_1000) +@@ -193,8 +199,7 @@ static int e1000_get_settings(struct net_device *netdev, + /* MDI-X => 2; MDI =>1; Invalid =>0 */ + if ((hw->phy.media_type == e1000_media_type_copper) && + netif_carrier_ok(netdev)) +- ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : +- ETH_TP_MDI; ++ ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : ETH_TP_MDI; + else + ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; + +@@ -208,14 +213,14 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx) + mac->autoneg = 0; + + /* Make sure dplx is at most 1 bit and lsb of speed is not set +- * for the switch() below to work */ ++ * for the switch() below to work ++ */ + if ((spd & 1) || (dplx & ~1)) + goto err_inval; + + /* Fiber NICs only allow 1000 gbps Full duplex */ + if ((adapter->hw.phy.media_type == e1000_media_type_fiber) && +- spd != SPEED_1000 && +- dplx != DUPLEX_FULL) { ++ (spd != SPEED_1000) && (dplx != DUPLEX_FULL)) { + goto err_inval; + } + +@@ -236,7 +241,7 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx) + mac->autoneg = 1; + adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; + break; +- case SPEED_1000 + DUPLEX_HALF: /* not supported */ ++ case SPEED_1000 + DUPLEX_HALF: /* not supported */ + default: + goto err_inval; + } +@@ -252,15 +257,18 @@ static int e1000_set_settings(struct net_device *netdev, + { + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; ++ int ret_val = 0; ++ ++ pm_runtime_get_sync(netdev->dev.parent); + +- /* +- * When SoL/IDER sessions are active, autoneg/speed/duplex ++ /* When SoL/IDER sessions are active, autoneg/speed/duplex + * cannot be changed + */ +- if (e1000_check_reset_block(hw)) { +- e_err("Cannot change link characteristics when SoL/IDER is " +- "active.\n"); +- return -EINVAL; ++ if (hw->phy.ops.check_reset_block && ++ hw->phy.ops.check_reset_block(hw)) { ++ e_err("Cannot change link characteristics when SoL/IDER is active.\n"); ++ ret_val = -EINVAL; ++ goto out; + } + + while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) +@@ -270,20 +278,18 @@ static int e1000_set_settings(struct net_device *netdev, + hw->mac.autoneg = 1; + if (hw->phy.media_type == e1000_media_type_fiber) + hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full | +- ADVERTISED_FIBRE | +- ADVERTISED_Autoneg; ++ ADVERTISED_FIBRE | ADVERTISED_Autoneg; + else + hw->phy.autoneg_advertised = ecmd->advertising | +- ADVERTISED_TP | +- ADVERTISED_Autoneg; ++ ADVERTISED_TP | ADVERTISED_Autoneg; + ecmd->advertising = hw->phy.autoneg_advertised; + if (adapter->fc_autoneg) + hw->fc.requested_mode = e1000_fc_default; + } else { + u32 speed = ethtool_cmd_speed(ecmd); + if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) { +- clear_bit(__E1000_RESETTING, &adapter->state); +- return -EINVAL; ++ ret_val = -EINVAL; ++ goto out; + } + } + +@@ -296,8 +302,10 @@ static int e1000_set_settings(struct net_device *netdev, + e1000e_reset(adapter); + } + ++out: ++ pm_runtime_put_sync(netdev->dev.parent); + clear_bit(__E1000_RESETTING, &adapter->state); +- return 0; ++ return ret_val; + } + + static void e1000_get_pauseparam(struct net_device *netdev, +@@ -307,7 +315,7 @@ static void e1000_get_pauseparam(struct net_device *netdev, + struct e1000_hw *hw = &adapter->hw; + + pause->autoneg = +- (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); ++ (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + + if (hw->fc.current_mode == e1000_fc_rx_pause) { + pause->rx_pause = 1; +@@ -331,6 +339,8 @@ static int e1000_set_pauseparam(struct net_device *netdev, + while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) + usleep_range(1000, 2000); + ++ pm_runtime_get_sync(netdev->dev.parent); ++ + if (adapter->fc_autoneg == AUTONEG_ENABLE) { + hw->fc.requested_mode = e1000_fc_default; + if (netif_running(adapter->netdev)) { +@@ -363,6 +373,7 @@ static int e1000_set_pauseparam(struct net_device *netdev, + } + + out: ++ pm_runtime_put_sync(netdev->dev.parent); + clear_bit(__E1000_RESETTING, &adapter->state); + return retval; + } +@@ -379,9 +390,9 @@ static void e1000_set_msglevel(struct net_device *netdev, u32 data) + adapter->msg_enable = data; + } + +-static int e1000_get_regs_len(struct net_device *netdev) ++static int e1000_get_regs_len(struct net_device __always_unused *netdev) + { +-#define E1000_REGS_LEN 32 /* overestimate */ ++#define E1000_REGS_LEN 32 /* overestimate */ + return E1000_REGS_LEN * sizeof(u32); + } + +@@ -393,31 +404,33 @@ static void e1000_get_regs(struct net_device *netdev, + u32 *regs_buff = p; + u16 phy_data; + ++ pm_runtime_get_sync(netdev->dev.parent); ++ + memset(p, 0, E1000_REGS_LEN * sizeof(u32)); + + regs->version = (1 << 24) | (adapter->pdev->revision << 16) | +- adapter->pdev->device; ++ adapter->pdev->device; + +- regs_buff[0] = er32(CTRL); +- regs_buff[1] = er32(STATUS); ++ regs_buff[0] = er32(CTRL); ++ regs_buff[1] = er32(STATUS); + +- regs_buff[2] = er32(RCTL); +- regs_buff[3] = er32(RDLEN); +- regs_buff[4] = er32(RDH); +- regs_buff[5] = er32(RDT); +- regs_buff[6] = er32(RDTR); ++ regs_buff[2] = er32(RCTL); ++ regs_buff[3] = er32(RDLEN(0)); ++ regs_buff[4] = er32(RDH(0)); ++ regs_buff[5] = er32(RDT(0)); ++ regs_buff[6] = er32(RDTR); + +- regs_buff[7] = er32(TCTL); +- regs_buff[8] = er32(TDLEN); +- regs_buff[9] = er32(TDH); +- regs_buff[10] = er32(TDT); ++ regs_buff[7] = er32(TCTL); ++ regs_buff[8] = er32(TDLEN(0)); ++ regs_buff[9] = er32(TDH(0)); ++ regs_buff[10] = er32(TDT(0)); + regs_buff[11] = er32(TIDV); + +- regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ ++ regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ + + /* ethtool doesn't use anything past this point, so all this +- * code is likely legacy junk for apps that may or may not +- * exist */ ++ * code is likely legacy junk for apps that may or may not exist ++ */ + if (hw->phy.type == e1000_phy_m88) { + e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); + regs_buff[13] = (u32)phy_data; /* cable length */ +@@ -433,10 +446,12 @@ static void e1000_get_regs(struct net_device *netdev, + regs_buff[22] = adapter->phy_stats.receive_errors; + regs_buff[23] = regs_buff[13]; /* mdix mode */ + } +- regs_buff[21] = 0; /* was idle_errors */ +- e1e_rphy(hw, PHY_1000T_STATUS, &phy_data); +- regs_buff[24] = (u32)phy_data; /* phy local receiver status */ +- regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ ++ regs_buff[21] = 0; /* was idle_errors */ ++ e1e_rphy(hw, MII_STAT1000, &phy_data); ++ regs_buff[24] = (u32)phy_data; /* phy local receiver status */ ++ regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ ++ ++ pm_runtime_put_sync(netdev->dev.parent); + } + + static int e1000_get_eeprom_len(struct net_device *netdev) +@@ -464,11 +479,13 @@ static int e1000_get_eeprom(struct net_device *netdev, + first_word = eeprom->offset >> 1; + last_word = (eeprom->offset + eeprom->len - 1) >> 1; + +- eeprom_buff = kmalloc(sizeof(u16) * +- (last_word - first_word + 1), GFP_KERNEL); ++ eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1), ++ GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + ++ pm_runtime_get_sync(netdev->dev.parent); ++ + if (hw->nvm.type == e1000_nvm_eeprom_spi) { + ret_val = e1000_read_nvm(hw, first_word, + last_word - first_word + 1, +@@ -476,12 +493,14 @@ static int e1000_get_eeprom(struct net_device *netdev, + } else { + for (i = 0; i < last_word - first_word + 1; i++) { + ret_val = e1000_read_nvm(hw, first_word + i, 1, +- &eeprom_buff[i]); ++ &eeprom_buff[i]); + if (ret_val) + break; + } + } + ++ pm_runtime_put_sync(netdev->dev.parent); ++ + if (ret_val) { + /* a read error occurred, throw away the result */ + memset(eeprom_buff, 0xff, sizeof(u16) * +@@ -514,7 +533,8 @@ static int e1000_set_eeprom(struct net_device *netdev, + if (eeprom->len == 0) + return -EOPNOTSUPP; + +- if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16))) ++ if (eeprom->magic != ++ (adapter->pdev->vendor | (adapter->pdev->device << 16))) + return -EFAULT; + + if (adapter->flags & FLAG_READ_ONLY_NVM) +@@ -530,17 +550,19 @@ static int e1000_set_eeprom(struct net_device *netdev, + + ptr = (void *)eeprom_buff; + ++ pm_runtime_get_sync(netdev->dev.parent); ++ + if (eeprom->offset & 1) { + /* need read/modify/write of first changed EEPROM word */ + /* only the second byte of the word is being modified */ + ret_val = e1000_read_nvm(hw, first_word, 1, &eeprom_buff[0]); + ptr++; + } +- if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) ++ if (((eeprom->offset + eeprom->len) & 1) && (!ret_val)) + /* need read/modify/write of last changed EEPROM word */ + /* only the first byte of the word is being modified */ + ret_val = e1000_read_nvm(hw, last_word, 1, +- &eeprom_buff[last_word - first_word]); ++ &eeprom_buff[last_word - first_word]); + + if (ret_val) + goto out; +@@ -552,7 +574,7 @@ static int e1000_set_eeprom(struct net_device *netdev, + memcpy(ptr, bytes, eeprom->len); + + for (i = 0; i < last_word - first_word + 1; i++) +- eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); ++ cpu_to_le16s(&eeprom_buff[i]); + + ret_val = e1000_write_nvm(hw, first_word, + last_word - first_word + 1, eeprom_buff); +@@ -560,8 +582,7 @@ static int e1000_set_eeprom(struct net_device *netdev, + if (ret_val) + goto out; + +- /* +- * Update the checksum over the first part of the EEPROM if needed ++ /* Update the checksum over the first part of the EEPROM if needed + * and flush shadow RAM for applicable controllers + */ + if ((first_word <= NVM_CHECKSUM_REG) || +@@ -571,6 +592,7 @@ static int e1000_set_eeprom(struct net_device *netdev, + ret_val = e1000e_update_nvm_checksum(hw); + + out: ++ pm_runtime_put_sync(netdev->dev.parent); + kfree(eeprom_buff); + return ret_val; + } +@@ -579,26 +601,22 @@ static void e1000_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) + { + struct e1000_adapter *adapter = netdev_priv(netdev); +- char firmware_version[32]; + +- strncpy(drvinfo->driver, e1000e_driver_name, +- sizeof(drvinfo->driver) - 1); +- strncpy(drvinfo->version, e1000e_driver_version, +- sizeof(drvinfo->version) - 1); ++ strlcpy(drvinfo->driver, e1000e_driver_name, sizeof(drvinfo->driver)); ++ strlcpy(drvinfo->version, e1000e_driver_version, ++ sizeof(drvinfo->version)); + +- /* +- * EEPROM image version # is reported as firmware version # for ++ /* EEPROM image version # is reported as firmware version # for + * PCI-E controllers + */ +- snprintf(firmware_version, sizeof(firmware_version), "%d.%d-%d", +- (adapter->eeprom_vers & 0xF000) >> 12, +- (adapter->eeprom_vers & 0x0FF0) >> 4, +- (adapter->eeprom_vers & 0x000F)); +- +- strncpy(drvinfo->fw_version, firmware_version, +- sizeof(drvinfo->fw_version) - 1); +- strncpy(drvinfo->bus_info, pci_name(adapter->pdev), +- sizeof(drvinfo->bus_info) - 1); ++ snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), ++ "%d.%d-%d", ++ (adapter->eeprom_vers & 0xF000) >> 12, ++ (adapter->eeprom_vers & 0x0FF0) >> 4, ++ (adapter->eeprom_vers & 0x000F)); ++ ++ strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), ++ sizeof(drvinfo->bus_info)); + drvinfo->regdump_len = e1000_get_regs_len(netdev); + drvinfo->eedump_len = e1000_get_eeprom_len(netdev); + } +@@ -607,94 +625,114 @@ static void e1000_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) + { + struct e1000_adapter *adapter = netdev_priv(netdev); +- struct e1000_ring *tx_ring = adapter->tx_ring; +- struct e1000_ring *rx_ring = adapter->rx_ring; + + ring->rx_max_pending = E1000_MAX_RXD; + ring->tx_max_pending = E1000_MAX_TXD; +- ring->rx_pending = rx_ring->count; +- ring->tx_pending = tx_ring->count; ++ ring->rx_pending = adapter->rx_ring_count; ++ ring->tx_pending = adapter->tx_ring_count; + } + + static int e1000_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) + { + struct e1000_adapter *adapter = netdev_priv(netdev); +- struct e1000_ring *tx_ring, *tx_old; +- struct e1000_ring *rx_ring, *rx_old; +- int err; ++ struct e1000_ring *temp_tx = NULL, *temp_rx = NULL; ++ int err = 0, size = sizeof(struct e1000_ring); ++ bool set_tx = false, set_rx = false; ++ u16 new_rx_count, new_tx_count; + + if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) + return -EINVAL; + +- while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) +- usleep_range(1000, 2000); ++ new_rx_count = clamp_t(u32, ring->rx_pending, E1000_MIN_RXD, ++ E1000_MAX_RXD); ++ new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE); + +- if (netif_running(adapter->netdev)) +- e1000e_down(adapter); ++ new_tx_count = clamp_t(u32, ring->tx_pending, E1000_MIN_TXD, ++ E1000_MAX_TXD); ++ new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE); + +- tx_old = adapter->tx_ring; +- rx_old = adapter->rx_ring; ++ if ((new_tx_count == adapter->tx_ring_count) && ++ (new_rx_count == adapter->rx_ring_count)) ++ /* nothing to do */ ++ return 0; ++ ++ while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) ++ usleep_range(1000, 2000); + +- err = -ENOMEM; +- tx_ring = kmemdup(tx_old, sizeof(struct e1000_ring), GFP_KERNEL); +- if (!tx_ring) +- goto err_alloc_tx; ++ if (!netif_running(adapter->netdev)) { ++ /* Set counts now and allocate resources during open() */ ++ adapter->tx_ring->count = new_tx_count; ++ adapter->rx_ring->count = new_rx_count; ++ adapter->tx_ring_count = new_tx_count; ++ adapter->rx_ring_count = new_rx_count; ++ goto clear_reset; ++ } + +- rx_ring = kmemdup(rx_old, sizeof(struct e1000_ring), GFP_KERNEL); +- if (!rx_ring) +- goto err_alloc_rx; ++ set_tx = (new_tx_count != adapter->tx_ring_count); ++ set_rx = (new_rx_count != adapter->rx_ring_count); + +- adapter->tx_ring = tx_ring; +- adapter->rx_ring = rx_ring; ++ /* Allocate temporary storage for ring updates */ ++ if (set_tx) { ++ temp_tx = vmalloc(size); ++ if (!temp_tx) { ++ err = -ENOMEM; ++ goto free_temp; ++ } ++ } ++ if (set_rx) { ++ temp_rx = vmalloc(size); ++ if (!temp_rx) { ++ err = -ENOMEM; ++ goto free_temp; ++ } ++ } + +- rx_ring->count = max(ring->rx_pending, (u32)E1000_MIN_RXD); +- rx_ring->count = min(rx_ring->count, (u32)(E1000_MAX_RXD)); +- rx_ring->count = ALIGN(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE); ++ pm_runtime_get_sync(netdev->dev.parent); + +- tx_ring->count = max(ring->tx_pending, (u32)E1000_MIN_TXD); +- tx_ring->count = min(tx_ring->count, (u32)(E1000_MAX_TXD)); +- tx_ring->count = ALIGN(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE); ++ e1000e_down(adapter); + +- if (netif_running(adapter->netdev)) { +- /* Try to get new resources before deleting old */ +- err = e1000e_setup_rx_resources(adapter); ++ /* We can't just free everything and then setup again, because the ++ * ISRs in MSI-X mode get passed pointers to the Tx and Rx ring ++ * structs. First, attempt to allocate new resources... ++ */ ++ if (set_tx) { ++ memcpy(temp_tx, adapter->tx_ring, size); ++ temp_tx->count = new_tx_count; ++ err = e1000e_setup_tx_resources(temp_tx); + if (err) +- goto err_setup_rx; +- err = e1000e_setup_tx_resources(adapter); ++ goto err_setup; ++ } ++ if (set_rx) { ++ memcpy(temp_rx, adapter->rx_ring, size); ++ temp_rx->count = new_rx_count; ++ err = e1000e_setup_rx_resources(temp_rx); + if (err) +- goto err_setup_tx; ++ goto err_setup_rx; ++ } + +- /* +- * restore the old in order to free it, +- * then add in the new +- */ +- adapter->rx_ring = rx_old; +- adapter->tx_ring = tx_old; +- e1000e_free_rx_resources(adapter); +- e1000e_free_tx_resources(adapter); +- kfree(tx_old); +- kfree(rx_old); +- adapter->rx_ring = rx_ring; +- adapter->tx_ring = tx_ring; +- err = e1000e_up(adapter); +- if (err) +- goto err_setup; ++ /* ...then free the old resources and copy back any new ring data */ ++ if (set_tx) { ++ e1000e_free_tx_resources(adapter->tx_ring); ++ memcpy(adapter->tx_ring, temp_tx, size); ++ adapter->tx_ring_count = new_tx_count; ++ } ++ if (set_rx) { ++ e1000e_free_rx_resources(adapter->rx_ring); ++ memcpy(adapter->rx_ring, temp_rx, size); ++ adapter->rx_ring_count = new_rx_count; + } + +- clear_bit(__E1000_RESETTING, &adapter->state); +- return 0; +-err_setup_tx: +- e1000e_free_rx_resources(adapter); + err_setup_rx: +- adapter->rx_ring = rx_old; +- adapter->tx_ring = tx_old; +- kfree(rx_ring); +-err_alloc_rx: +- kfree(tx_ring); +-err_alloc_tx: +- e1000e_up(adapter); ++ if (err && set_tx) ++ e1000e_free_tx_resources(temp_tx); + err_setup: ++ e1000e_up(adapter); ++ pm_runtime_put_sync(netdev->dev.parent); ++free_temp: ++ vfree(temp_tx); ++ vfree(temp_rx); ++clear_reset: + clear_bit(__E1000_RESETTING, &adapter->state); + return err; + } +@@ -704,14 +742,15 @@ static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, + { + u32 pat, val; + static const u32 test[] = { +- 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; ++ 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF ++ }; + for (pat = 0; pat < ARRAY_SIZE(test); pat++) { + E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset, + (test[pat] & write)); + val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset); + if (val != (test[pat] & write & mask)) { +- e_err("pattern test reg %04X failed: got 0x%08X " +- "expected 0x%08X\n", reg + offset, val, ++ e_err("pattern test failed (reg 0x%05X): got 0x%08X expected 0x%08X\n", ++ reg + (offset << 2), val, + (test[pat] & write & mask)); + *data = reg; + return 1; +@@ -727,13 +766,14 @@ static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, + __ew32(&adapter->hw, reg, write & mask); + val = __er32(&adapter->hw, reg); + if ((write & mask) != (val & mask)) { +- e_err("set/check reg %04X test failed: got 0x%08X " +- "expected 0x%08X\n", reg, (val & mask), (write & mask)); ++ e_err("set/check test failed (reg 0x%05X): got 0x%08X expected 0x%08X\n", ++ reg, (val & mask), (write & mask)); + *data = reg; + return 1; + } + return 0; + } ++ + #define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write) \ + do { \ + if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \ +@@ -758,19 +798,19 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) + u32 i; + u32 toggle; + u32 mask; ++ u32 wlock_mac = 0; + +- /* +- * The status register is Read Only, so a write should fail. +- * Some bits that get toggled are ignored. ++ /* The status register is Read Only, so a write should fail. ++ * Some bits that get toggled are ignored. There are several bits ++ * on newer hardware that are r/w. + */ + switch (mac->type) { +- /* there are several bits on newer hardware that are r/w */ + case e1000_82571: + case e1000_82572: + case e1000_80003es2lan: + toggle = 0x7FFFF3FF; + break; +- default: ++ default: + toggle = 0x7FFFF033; + break; + } +@@ -780,8 +820,8 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) + ew32(STATUS, toggle); + after = er32(STATUS) & toggle; + if (value != after) { +- e_err("failed STATUS register test got: 0x%08X expected: " +- "0x%08X\n", after, value); ++ e_err("failed STATUS register test got: 0x%08X expected: 0x%08X\n", ++ after, value); + *data = 1; + return 1; + } +@@ -796,15 +836,15 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) + } + + REG_PATTERN_TEST(E1000_RDTR, 0x0000FFFF, 0xFFFFFFFF); +- REG_PATTERN_TEST(E1000_RDBAH, 0xFFFFFFFF, 0xFFFFFFFF); +- REG_PATTERN_TEST(E1000_RDLEN, 0x000FFF80, 0x000FFFFF); +- REG_PATTERN_TEST(E1000_RDH, 0x0000FFFF, 0x0000FFFF); +- REG_PATTERN_TEST(E1000_RDT, 0x0000FFFF, 0x0000FFFF); ++ REG_PATTERN_TEST(E1000_RDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF); ++ REG_PATTERN_TEST(E1000_RDLEN(0), 0x000FFF80, 0x000FFFFF); ++ REG_PATTERN_TEST(E1000_RDH(0), 0x0000FFFF, 0x0000FFFF); ++ REG_PATTERN_TEST(E1000_RDT(0), 0x0000FFFF, 0x0000FFFF); + REG_PATTERN_TEST(E1000_FCRTH, 0x0000FFF8, 0x0000FFF8); + REG_PATTERN_TEST(E1000_FCTTV, 0x0000FFFF, 0x0000FFFF); + REG_PATTERN_TEST(E1000_TIPG, 0x3FFFFFFF, 0x3FFFFFFF); +- REG_PATTERN_TEST(E1000_TDBAH, 0xFFFFFFFF, 0xFFFFFFFF); +- REG_PATTERN_TEST(E1000_TDLEN, 0x000FFF80, 0x000FFFFF); ++ REG_PATTERN_TEST(E1000_TDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF); ++ REG_PATTERN_TEST(E1000_TDLEN(0), 0x000FFF80, 0x000FFFFF); + + REG_SET_AND_CHECK(E1000_RCTL, 0xFFFFFFFF, 0x00000000); + +@@ -813,29 +853,57 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) + REG_SET_AND_CHECK(E1000_TCTL, 0xFFFFFFFF, 0x00000000); + + REG_SET_AND_CHECK(E1000_RCTL, before, 0xFFFFFFFF); +- REG_PATTERN_TEST(E1000_RDBAL, 0xFFFFFFF0, 0xFFFFFFFF); ++ REG_PATTERN_TEST(E1000_RDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); + if (!(adapter->flags & FLAG_IS_ICH)) + REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF); +- REG_PATTERN_TEST(E1000_TDBAL, 0xFFFFFFF0, 0xFFFFFFFF); ++ REG_PATTERN_TEST(E1000_TDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); + REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF); + mask = 0x8003FFFF; + switch (mac->type) { + case e1000_ich10lan: + case e1000_pchlan: + case e1000_pch2lan: ++ case e1000_pch_lpt: + mask |= (1 << 18); + break; + default: + break; + } +- for (i = 0; i < mac->rar_entry_count; i++) +- REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), +- mask, 0xFFFFFFFF); ++ ++ if (mac->type == e1000_pch_lpt) ++ wlock_mac = (er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK) >> ++ E1000_FWSM_WLOCK_MAC_SHIFT; ++ ++ for (i = 0; i < mac->rar_entry_count; i++) { ++ if (mac->type == e1000_pch_lpt) { ++ /* Cannot test write-protected SHRAL[n] registers */ ++ if ((wlock_mac == 1) || (wlock_mac && (i > wlock_mac))) ++ continue; ++ ++ /* SHRAH[9] different than the others */ ++ if (i == 10) ++ mask |= (1 << 30); ++ else ++ mask &= ~(1 << 30); ++ } ++ if (mac->type == e1000_pch2lan) { ++ /* SHRAH[0,1,2] different than previous */ ++ if (i == 7) ++ mask &= 0xFFF4FFFF; ++ /* SHRAH[3] different than SHRAH[0,1,2] */ ++ if (i == 10) ++ mask |= (1 << 30); ++ } ++ ++ REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), mask, ++ 0xFFFFFFFF); ++ } + + for (i = 0; i < mac->mta_reg_count; i++) + REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF); + + *data = 0; ++ + return 0; + } + +@@ -856,15 +924,15 @@ static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data) + } + + /* If Checksum is not Correct return error else test passed */ +- if ((checksum != (u16) NVM_SUM) && !(*data)) ++ if ((checksum != (u16)NVM_SUM) && !(*data)) + *data = 2; + + return *data; + } + +-static irqreturn_t e1000_test_intr(int irq, void *data) ++static irqreturn_t e1000_test_intr(int __always_unused irq, void *data) + { +- struct net_device *netdev = (struct net_device *) data; ++ struct net_device *netdev = (struct net_device *)data; + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + +@@ -897,8 +965,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) + if (!request_irq(irq, e1000_test_intr, IRQF_PROBE_SHARED, netdev->name, + netdev)) { + shared_int = 0; +- } else if (request_irq(irq, e1000_test_intr, IRQF_SHARED, +- netdev->name, netdev)) { ++ } else if (request_irq(irq, e1000_test_intr, IRQF_SHARED, netdev->name, ++ netdev)) { + *data = 1; + ret_val = -1; + goto out; +@@ -930,8 +998,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) + } + + if (!shared_int) { +- /* +- * Disable the interrupt to be reported in ++ /* Disable the interrupt to be reported in + * the cause register and then force the same + * interrupt and see if one gets posted. If + * an interrupt was posted to the bus, the +@@ -949,8 +1016,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) + } + } + +- /* +- * Enable the interrupt to be reported in ++ /* Enable the interrupt to be reported in + * the cause register and then force the same + * interrupt and see if one gets posted. If + * an interrupt was not posted to the bus, the +@@ -968,8 +1034,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) + } + + if (!shared_int) { +- /* +- * Disable the other interrupts to be reported in ++ /* Disable the other interrupts to be reported in + * the cause register and then force the other + * interrupts and see if any get posted. If + * an interrupt was posted to the bus, the +@@ -1011,28 +1076,33 @@ static void e1000_free_desc_rings(struct e1000_adapter *adapter) + struct e1000_ring *tx_ring = &adapter->test_tx_ring; + struct e1000_ring *rx_ring = &adapter->test_rx_ring; + struct pci_dev *pdev = adapter->pdev; ++ struct e1000_buffer *buffer_info; + int i; + + if (tx_ring->desc && tx_ring->buffer_info) { + for (i = 0; i < tx_ring->count; i++) { +- if (tx_ring->buffer_info[i].dma) ++ buffer_info = &tx_ring->buffer_info[i]; ++ ++ if (buffer_info->dma) + dma_unmap_single(&pdev->dev, +- tx_ring->buffer_info[i].dma, +- tx_ring->buffer_info[i].length, +- DMA_TO_DEVICE); +- if (tx_ring->buffer_info[i].skb) +- dev_kfree_skb(tx_ring->buffer_info[i].skb); ++ buffer_info->dma, ++ buffer_info->length, ++ DMA_TO_DEVICE); ++ if (buffer_info->skb) ++ dev_kfree_skb(buffer_info->skb); + } + } + + if (rx_ring->desc && rx_ring->buffer_info) { + for (i = 0; i < rx_ring->count; i++) { +- if (rx_ring->buffer_info[i].dma) ++ buffer_info = &rx_ring->buffer_info[i]; ++ ++ if (buffer_info->dma) + dma_unmap_single(&pdev->dev, +- rx_ring->buffer_info[i].dma, +- 2048, DMA_FROM_DEVICE); +- if (rx_ring->buffer_info[i].skb) +- dev_kfree_skb(rx_ring->buffer_info[i].skb); ++ buffer_info->dma, ++ 2048, DMA_FROM_DEVICE); ++ if (buffer_info->skb) ++ dev_kfree_skb(buffer_info->skb); + } + } + +@@ -1069,9 +1139,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) + tx_ring->count = E1000_DEFAULT_TXD; + + tx_ring->buffer_info = kcalloc(tx_ring->count, +- sizeof(struct e1000_buffer), +- GFP_KERNEL); +- if (!(tx_ring->buffer_info)) { ++ sizeof(struct e1000_buffer), GFP_KERNEL); ++ if (!tx_ring->buffer_info) { + ret_val = 1; + goto err_nomem; + } +@@ -1087,11 +1156,11 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; + +- ew32(TDBAL, ((u64) tx_ring->dma & 0x00000000FFFFFFFF)); +- ew32(TDBAH, ((u64) tx_ring->dma >> 32)); +- ew32(TDLEN, tx_ring->count * sizeof(struct e1000_tx_desc)); +- ew32(TDH, 0); +- ew32(TDT, 0); ++ ew32(TDBAL(0), ((u64)tx_ring->dma & 0x00000000FFFFFFFF)); ++ ew32(TDBAH(0), ((u64)tx_ring->dma >> 32)); ++ ew32(TDLEN(0), tx_ring->count * sizeof(struct e1000_tx_desc)); ++ ew32(TDH(0), 0); ++ ew32(TDT(0), 0); + ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR | + E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | + E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT); +@@ -1110,8 +1179,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) + tx_ring->buffer_info[i].skb = skb; + tx_ring->buffer_info[i].length = skb->len; + tx_ring->buffer_info[i].dma = +- dma_map_single(&pdev->dev, skb->data, skb->len, +- DMA_TO_DEVICE); ++ dma_map_single(&pdev->dev, skb->data, skb->len, ++ DMA_TO_DEVICE); + if (dma_mapping_error(&pdev->dev, + tx_ring->buffer_info[i].dma)) { + ret_val = 4; +@@ -1131,9 +1200,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) + rx_ring->count = E1000_DEFAULT_RXD; + + rx_ring->buffer_info = kcalloc(rx_ring->count, +- sizeof(struct e1000_buffer), +- GFP_KERNEL); +- if (!(rx_ring->buffer_info)) { ++ sizeof(struct e1000_buffer), GFP_KERNEL); ++ if (!rx_ring->buffer_info) { + ret_val = 5; + goto err_nomem; + } +@@ -1151,16 +1219,16 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) + rctl = er32(RCTL); + if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX)) + ew32(RCTL, rctl & ~E1000_RCTL_EN); +- ew32(RDBAL, ((u64) rx_ring->dma & 0xFFFFFFFF)); +- ew32(RDBAH, ((u64) rx_ring->dma >> 32)); +- ew32(RDLEN, rx_ring->size); +- ew32(RDH, 0); +- ew32(RDT, 0); ++ ew32(RDBAL(0), ((u64)rx_ring->dma & 0xFFFFFFFF)); ++ ew32(RDBAH(0), ((u64)rx_ring->dma >> 32)); ++ ew32(RDLEN(0), rx_ring->size); ++ ew32(RDH(0), 0); ++ ew32(RDT(0), 0); + rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | +- E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE | +- E1000_RCTL_SBP | E1000_RCTL_SECRC | +- E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | +- (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); ++ E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE | ++ E1000_RCTL_SBP | E1000_RCTL_SECRC | ++ E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | ++ (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); + ew32(RCTL, rctl); + + for (i = 0; i < rx_ring->count; i++) { +@@ -1175,8 +1243,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) + skb_reserve(skb, NET_IP_ALIGN); + rx_ring->buffer_info[i].skb = skb; + rx_ring->buffer_info[i].dma = +- dma_map_single(&pdev->dev, skb->data, 2048, +- DMA_FROM_DEVICE); ++ dma_map_single(&pdev->dev, skb->data, 2048, ++ DMA_FROM_DEVICE); + if (dma_mapping_error(&pdev->dev, + rx_ring->buffer_info[i].dma)) { + ret_val = 8; +@@ -1215,7 +1283,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) + + if (hw->phy.type == e1000_phy_ife) { + /* force 100, set loopback */ +- e1e_wphy(hw, PHY_CONTROL, 0x6100); ++ e1e_wphy(hw, MII_BMCR, 0x6100); + + /* Now set up the MAC to the same speed/duplex as the PHY. */ + ctrl_reg = er32(CTRL); +@@ -1227,7 +1295,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) + + ew32(CTRL, ctrl_reg); + e1e_flush(); +- udelay(500); ++ usleep_range(500, 1000); + + return 0; + } +@@ -1238,9 +1306,9 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) + /* Auto-MDI/MDIX Off */ + e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); + /* reset to update Auto-MDI/MDIX */ +- e1e_wphy(hw, PHY_CONTROL, 0x9140); ++ e1e_wphy(hw, MII_BMCR, 0x9140); + /* autoneg off */ +- e1e_wphy(hw, PHY_CONTROL, 0x8140); ++ e1e_wphy(hw, MII_BMCR, 0x8140); + break; + case e1000_phy_gg82563: + e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC); +@@ -1252,8 +1320,8 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) + phy_reg |= 0x006; + e1e_wphy(hw, PHY_REG(2, 21), phy_reg); + /* Assert SW reset for above settings to take effect */ +- e1000e_commit_phy(hw); +- mdelay(1); ++ hw->phy.ops.commit(hw); ++ usleep_range(1000, 2000); + /* Force Full Duplex */ + e1e_rphy(hw, PHY_REG(769, 16), &phy_reg); + e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x000C); +@@ -1286,7 +1354,6 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) + e1e_rphy(hw, PHY_REG(776, 18), &phy_reg); + e1e_wphy(hw, PHY_REG(776, 18), phy_reg | 1); + /* Enable loopback on the PHY */ +-#define I82577_PHY_LBK_CTRL 19 + e1e_wphy(hw, I82577_PHY_LBK_CTRL, 0x8001); + break; + default: +@@ -1294,8 +1361,8 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) + } + + /* force 1000, set loopback */ +- e1e_wphy(hw, PHY_CONTROL, 0x4140); +- mdelay(250); ++ e1e_wphy(hw, MII_BMCR, 0x4140); ++ msleep(250); + + /* Now set up the MAC to the same speed/duplex as the PHY. */ + ctrl_reg = er32(CTRL); +@@ -1310,10 +1377,9 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) + + if (hw->phy.media_type == e1000_media_type_copper && + hw->phy.type == e1000_phy_m88) { +- ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ ++ ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ + } else { +- /* +- * Set the ILOS bit on the fiber Nic if half duplex link is ++ /* Set the ILOS bit on the fiber Nic if half duplex link is + * detected. + */ + if ((er32(STATUS) & E1000_STATUS_FD) == 0) +@@ -1322,14 +1388,13 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) + + ew32(CTRL, ctrl_reg); + +- /* +- * Disable the receiver on the PHY so when a cable is plugged in, the ++ /* Disable the receiver on the PHY so when a cable is plugged in, the + * PHY does not begin to autoneg when a cable is reconnected to the NIC. + */ + if (hw->phy.type == e1000_phy_m88) + e1000_phy_disable_receiver(adapter); + +- udelay(500); ++ usleep_range(500, 1000); + + return 0; + } +@@ -1338,12 +1403,11 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter) + { + struct e1000_hw *hw = &adapter->hw; + u32 ctrl = er32(CTRL); +- int link = 0; ++ int link; + + /* special requirements for 82571/82572 fiber adapters */ + +- /* +- * jump through hoops to make sure link is up because serdes ++ /* jump through hoops to make sure link is up because serdes + * link is hardwired up + */ + ctrl |= E1000_CTRL_SLU; +@@ -1363,12 +1427,10 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter) + ew32(CTRL, ctrl); + } + +- /* +- * special write to serdes control register to enable SerDes analog ++ /* special write to serdes control register to enable SerDes analog + * loopback + */ +-#define E1000_SERDES_LB_ON 0x410 +- ew32(SCTL, E1000_SERDES_LB_ON); ++ ew32(SCTL, E1000_SCTL_ENABLE_SERDES_LOOPBACK); + e1e_flush(); + usleep_range(10000, 20000); + +@@ -1382,8 +1444,7 @@ static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter) + u32 ctrlext = er32(CTRL_EXT); + u32 ctrl = er32(CTRL); + +- /* +- * save CTRL_EXT to restore later, reuse an empty variable (unused ++ /* save CTRL_EXT to restore later, reuse an empty variable (unused + * on mac_type 80003es2lan) + */ + adapter->tx_fifo_head = ctrlext; +@@ -1463,8 +1524,7 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter) + case e1000_82572: + if (hw->phy.media_type == e1000_media_type_fiber || + hw->phy.media_type == e1000_media_type_internal_serdes) { +-#define E1000_SERDES_LB_OFF 0x400 +- ew32(SCTL, E1000_SERDES_LB_OFF); ++ ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); + e1e_flush(); + usleep_range(10000, 20000); + break; +@@ -1474,11 +1534,12 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter) + hw->mac.autoneg = 1; + if (hw->phy.type == e1000_phy_gg82563) + e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x180); +- e1e_rphy(hw, PHY_CONTROL, &phy_reg); +- if (phy_reg & MII_CR_LOOPBACK) { +- phy_reg &= ~MII_CR_LOOPBACK; +- e1e_wphy(hw, PHY_CONTROL, phy_reg); +- e1000e_commit_phy(hw); ++ e1e_rphy(hw, MII_BMCR, &phy_reg); ++ if (phy_reg & BMCR_LOOPBACK) { ++ phy_reg &= ~BMCR_LOOPBACK; ++ e1e_wphy(hw, MII_BMCR, phy_reg); ++ if (hw->phy.ops.commit) ++ hw->phy.ops.commit(hw); + } + break; + } +@@ -1500,7 +1561,7 @@ static int e1000_check_lbtest_frame(struct sk_buff *skb, + frame_size &= ~1; + if (*(skb->data + 3) == 0xFF) + if ((*(skb->data + frame_size / 2 + 10) == 0xBE) && +- (*(skb->data + frame_size / 2 + 12) == 0xAF)) ++ (*(skb->data + frame_size / 2 + 12) == 0xAF)) + return 0; + return 13; + } +@@ -1511,16 +1572,16 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter) + struct e1000_ring *rx_ring = &adapter->test_rx_ring; + struct pci_dev *pdev = adapter->pdev; + struct e1000_hw *hw = &adapter->hw; ++ struct e1000_buffer *buffer_info; + int i, j, k, l; + int lc; + int good_cnt; + int ret_val = 0; + unsigned long time; + +- ew32(RDT, rx_ring->count - 1); ++ ew32(RDT(0), rx_ring->count - 1); + +- /* +- * Calculate the loop count based on the largest descriptor ring ++ /* Calculate the loop count based on the largest descriptor ring + * The idea is to wrap the largest ring a number of times using 64 + * send/receive pairs during each loop + */ +@@ -1532,60 +1593,65 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter) + + k = 0; + l = 0; +- for (j = 0; j <= lc; j++) { /* loop count loop */ +- for (i = 0; i < 64; i++) { /* send the packets */ +- e1000_create_lbtest_frame(tx_ring->buffer_info[k].skb, +- 1024); ++ /* loop count loop */ ++ for (j = 0; j <= lc; j++) { ++ /* send the packets */ ++ for (i = 0; i < 64; i++) { ++ buffer_info = &tx_ring->buffer_info[k]; ++ ++ e1000_create_lbtest_frame(buffer_info->skb, 1024); + dma_sync_single_for_device(&pdev->dev, +- tx_ring->buffer_info[k].dma, +- tx_ring->buffer_info[k].length, +- DMA_TO_DEVICE); ++ buffer_info->dma, ++ buffer_info->length, ++ DMA_TO_DEVICE); + k++; + if (k == tx_ring->count) + k = 0; + } +- ew32(TDT, k); ++ ew32(TDT(0), k); + e1e_flush(); + msleep(200); +- time = jiffies; /* set the start time for the receive */ ++ time = jiffies; /* set the start time for the receive */ + good_cnt = 0; +- do { /* receive the sent packets */ ++ /* receive the sent packets */ ++ do { ++ buffer_info = &rx_ring->buffer_info[l]; ++ + dma_sync_single_for_cpu(&pdev->dev, +- rx_ring->buffer_info[l].dma, 2048, +- DMA_FROM_DEVICE); ++ buffer_info->dma, 2048, ++ DMA_FROM_DEVICE); + +- ret_val = e1000_check_lbtest_frame( +- rx_ring->buffer_info[l].skb, 1024); ++ ret_val = e1000_check_lbtest_frame(buffer_info->skb, ++ 1024); + if (!ret_val) + good_cnt++; + l++; + if (l == rx_ring->count) + l = 0; +- /* +- * time + 20 msecs (200 msecs on 2.4) is more than ++ /* time + 20 msecs (200 msecs on 2.4) is more than + * enough time to complete the receives, if it's + * exceeded, break and error off + */ + } while ((good_cnt < 64) && !time_after(jiffies, time + 20)); + if (good_cnt != 64) { +- ret_val = 13; /* ret_val is the same as mis-compare */ ++ ret_val = 13; /* ret_val is the same as mis-compare */ + break; + } +- if (jiffies >= (time + 20)) { +- ret_val = 14; /* error code for time out error */ ++ if (time_after(jiffies, time + 20)) { ++ ret_val = 14; /* error code for time out error */ + break; + } +- } /* end loop count loop */ ++ } + return ret_val; + } + + static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) + { +- /* +- * PHY loopback cannot be performed if SoL/IDER +- * sessions are active +- */ +- if (e1000_check_reset_block(&adapter->hw)) { ++ struct e1000_hw *hw = &adapter->hw; ++ ++ /* PHY loopback cannot be performed if SoL/IDER sessions are active */ ++ if (hw->phy.ops.check_reset_block && ++ hw->phy.ops.check_reset_block(hw)) { + e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); + *data = 0; + goto out; +@@ -1617,8 +1683,7 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) + int i = 0; + hw->mac.serdes_has_link = false; + +- /* +- * On some blade server designs, link establishment ++ /* On some blade server designs, link establishment + * could take as long as 2-3 minutes + */ + do { +@@ -1632,11 +1697,10 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) + } else { + hw->mac.ops.check_for_link(hw); + if (hw->mac.autoneg) +- /* +- * On some Phy/switch combinations, link establishment ++ /* On some Phy/switch combinations, link establishment + * can take a few seconds more than expected. + */ +- msleep(5000); ++ msleep_interruptible(5000); + + if (!(er32(STATUS) & E1000_STATUS_LU)) + *data = 1; +@@ -1644,7 +1708,8 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) + return *data; + } + +-static int e1000e_get_sset_count(struct net_device *netdev, int sset) ++static int e1000e_get_sset_count(struct net_device __always_unused *netdev, ++ int sset) + { + switch (sset) { + case ETH_SS_TEST: +@@ -1665,6 +1730,8 @@ static void e1000_diag_test(struct net_device *netdev, + u8 autoneg; + bool if_running = netif_running(netdev); + ++ pm_runtime_get_sync(netdev->dev.parent); ++ + set_bit(__E1000_TESTING, &adapter->state); + + if (!if_running) { +@@ -1750,6 +1817,8 @@ static void e1000_diag_test(struct net_device *netdev, + } + + msleep_interruptible(4 * 1000); ++ ++ pm_runtime_put_sync(netdev->dev.parent); + } + + static void e1000_get_wol(struct net_device *netdev, +@@ -1772,8 +1841,7 @@ static void e1000_get_wol(struct net_device *netdev, + wol->supported &= ~WAKE_UCAST; + + if (adapter->wol & E1000_WUFC_EX) +- e_err("Interface does not support directed (unicast) " +- "frame wake-up packets\n"); ++ e_err("Interface does not support directed (unicast) frame wake-up packets\n"); + } + + if (adapter->wol & E1000_WUFC_EX) +@@ -1825,6 +1893,8 @@ static int e1000_set_phys_id(struct net_device *netdev, + + switch (state) { + case ETHTOOL_ID_ACTIVE: ++ pm_runtime_get_sync(netdev->dev.parent); ++ + if (!hw->mac.ops.blink_led) + return 2; /* cycle on/off twice per second */ + +@@ -1836,16 +1906,18 @@ static int e1000_set_phys_id(struct net_device *netdev, + e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0); + hw->mac.ops.led_off(hw); + hw->mac.ops.cleanup_led(hw); ++ pm_runtime_put_sync(netdev->dev.parent); + break; + + case ETHTOOL_ID_ON: +- adapter->hw.mac.ops.led_on(&adapter->hw); ++ hw->mac.ops.led_on(hw); + break; + + case ETHTOOL_ID_OFF: +- adapter->hw.mac.ops.led_off(&adapter->hw); ++ hw->mac.ops.led_off(hw); + break; + } ++ + return 0; + } + +@@ -1866,7 +1938,6 @@ static int e1000_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) + { + struct e1000_adapter *adapter = netdev_priv(netdev); +- struct e1000_hw *hw = &adapter->hw; + + if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || + ((ec->rx_coalesce_usecs > 4) && +@@ -1875,7 +1946,8 @@ static int e1000_set_coalesce(struct net_device *netdev, + return -EINVAL; + + if (ec->rx_coalesce_usecs == 4) { +- adapter->itr = adapter->itr_setting = 4; ++ adapter->itr_setting = 4; ++ adapter->itr = adapter->itr_setting; + } else if (ec->rx_coalesce_usecs <= 3) { + adapter->itr = 20000; + adapter->itr_setting = ec->rx_coalesce_usecs; +@@ -1884,10 +1956,14 @@ static int e1000_set_coalesce(struct net_device *netdev, + adapter->itr_setting = adapter->itr & ~3; + } + ++ pm_runtime_get_sync(netdev->dev.parent); ++ + if (adapter->itr_setting != 0) +- ew32(ITR, 1000000000 / (adapter->itr * 256)); ++ e1000e_write_itr(adapter, adapter->itr); + else +- ew32(ITR, 0); ++ e1000e_write_itr(adapter, 0); ++ ++ pm_runtime_put_sync(netdev->dev.parent); + + return 0; + } +@@ -1902,13 +1978,15 @@ static int e1000_nway_reset(struct net_device *netdev) + if (!adapter->hw.mac.autoneg) + return -EINVAL; + ++ pm_runtime_get_sync(netdev->dev.parent); + e1000e_reinit_locked(adapter); ++ pm_runtime_put_sync(netdev->dev.parent); + + return 0; + } + + static void e1000_get_ethtool_stats(struct net_device *netdev, +- struct ethtool_stats *stats, ++ struct ethtool_stats __always_unused *stats, + u64 *data) + { + struct e1000_adapter *adapter = netdev_priv(netdev); +@@ -1916,16 +1994,21 @@ static void e1000_get_ethtool_stats(struct net_device *netdev, + int i; + char *p = NULL; + ++ pm_runtime_get_sync(netdev->dev.parent); ++ + e1000e_get_stats64(netdev, &net_stats); ++ ++ pm_runtime_put_sync(netdev->dev.parent); ++ + for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { + switch (e1000_gstrings_stats[i].type) { + case NETDEV_STATS: +- p = (char *) &net_stats + +- e1000_gstrings_stats[i].stat_offset; ++ p = (char *)&net_stats + ++ e1000_gstrings_stats[i].stat_offset; + break; + case E1000_STATS: +- p = (char *) adapter + +- e1000_gstrings_stats[i].stat_offset; ++ p = (char *)adapter + ++ e1000_gstrings_stats[i].stat_offset; + break; + default: + data[i] = 0; +@@ -1933,12 +2016,12 @@ static void e1000_get_ethtool_stats(struct net_device *netdev, + } + + data[i] = (e1000_gstrings_stats[i].sizeof_stat == +- sizeof(u64)) ? *(u64 *)p : *(u32 *)p; ++ sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + } + +-static void e1000_get_strings(struct net_device *netdev, u32 stringset, +- u8 *data) ++static void e1000_get_strings(struct net_device __always_unused *netdev, ++ u32 stringset, u8 *data) + { + u8 *p = data; + int i; +@@ -1957,6 +2040,58 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset, + } + } + ++static int e1000_get_rxnfc(struct net_device *netdev, ++ struct ethtool_rxnfc *info, ++ u32 __always_unused *rule_locs) ++{ ++ info->data = 0; ++ ++ switch (info->cmd) { ++ case ETHTOOL_GRXFH: { ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ u32 mrqc; ++ ++ pm_runtime_get_sync(netdev->dev.parent); ++ mrqc = er32(MRQC); ++ pm_runtime_put_sync(netdev->dev.parent); ++ ++ if (!(mrqc & E1000_MRQC_RSS_FIELD_MASK)) ++ return 0; ++ ++ switch (info->flow_type) { ++ case TCP_V4_FLOW: ++ if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_TCP) ++ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ /* fall through */ ++ case UDP_V4_FLOW: ++ case SCTP_V4_FLOW: ++ case AH_ESP_V4_FLOW: ++ case IPV4_FLOW: ++ if (mrqc & E1000_MRQC_RSS_FIELD_IPV4) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ break; ++ case TCP_V6_FLOW: ++ if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP) ++ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ /* fall through */ ++ case UDP_V6_FLOW: ++ case SCTP_V6_FLOW: ++ case AH_ESP_V6_FLOW: ++ case IPV6_FLOW: ++ if (mrqc & E1000_MRQC_RSS_FIELD_IPV6) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ break; ++ default: ++ break; ++ } ++ return 0; ++ } ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ + static const struct ethtool_ops e1000_ethtool_ops = { + .get_settings = e1000_get_settings, + .set_settings = e1000_set_settings, +@@ -1983,6 +2118,7 @@ static const struct ethtool_ops e1000_ethtool_ops = { + .get_sset_count = e1000e_get_sset_count, + .get_coalesce = e1000_get_coalesce, + .set_coalesce = e1000_set_coalesce, ++ .get_rxnfc = e1000_get_rxnfc, + }; + + void e1000e_set_ethtool_ops(struct net_device *netdev) +diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h +index 2967039..b7f3843 100644 +--- a/drivers/net/ethernet/intel/e1000e/hw.h ++++ b/drivers/net/ethernet/intel/e1000e/hw.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel PRO/1000 Linux driver +- Copyright(c) 1999 - 2011 Intel Corporation. ++ Copyright(c) 1999 - 2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -29,319 +29,10 @@ + #ifndef _E1000_HW_H_ + #define _E1000_HW_H_ + +-#include +- +-struct e1000_hw; +-struct e1000_adapter; +- ++#include "regs.h" + #include "defines.h" + +-#define er32(reg) __er32(hw, E1000_##reg) +-#define ew32(reg,val) __ew32(hw, E1000_##reg, (val)) +-#define e1e_flush() er32(STATUS) +- +-#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \ +- (writel((value), ((a)->hw_addr + reg + ((offset) << 2)))) +- +-#define E1000_READ_REG_ARRAY(a, reg, offset) \ +- (readl((a)->hw_addr + reg + ((offset) << 2))) +- +-enum e1e_registers { +- E1000_CTRL = 0x00000, /* Device Control - RW */ +- E1000_STATUS = 0x00008, /* Device Status - RO */ +- E1000_EECD = 0x00010, /* EEPROM/Flash Control - RW */ +- E1000_EERD = 0x00014, /* EEPROM Read - RW */ +- E1000_CTRL_EXT = 0x00018, /* Extended Device Control - RW */ +- E1000_FLA = 0x0001C, /* Flash Access - RW */ +- E1000_MDIC = 0x00020, /* MDI Control - RW */ +- E1000_SCTL = 0x00024, /* SerDes Control - RW */ +- E1000_FCAL = 0x00028, /* Flow Control Address Low - RW */ +- E1000_FCAH = 0x0002C, /* Flow Control Address High -RW */ +- E1000_FEXTNVM4 = 0x00024, /* Future Extended NVM 4 - RW */ +- E1000_FEXTNVM = 0x00028, /* Future Extended NVM - RW */ +- E1000_FCT = 0x00030, /* Flow Control Type - RW */ +- E1000_VET = 0x00038, /* VLAN Ether Type - RW */ +- E1000_ICR = 0x000C0, /* Interrupt Cause Read - R/clr */ +- E1000_ITR = 0x000C4, /* Interrupt Throttling Rate - RW */ +- E1000_ICS = 0x000C8, /* Interrupt Cause Set - WO */ +- E1000_IMS = 0x000D0, /* Interrupt Mask Set - RW */ +- E1000_IMC = 0x000D8, /* Interrupt Mask Clear - WO */ +- E1000_EIAC_82574 = 0x000DC, /* Ext. Interrupt Auto Clear - RW */ +- E1000_IAM = 0x000E0, /* Interrupt Acknowledge Auto Mask */ +- E1000_IVAR = 0x000E4, /* Interrupt Vector Allocation - RW */ +- E1000_EITR_82574_BASE = 0x000E8, /* Interrupt Throttling - RW */ +-#define E1000_EITR_82574(_n) (E1000_EITR_82574_BASE + (_n << 2)) +- E1000_RCTL = 0x00100, /* Rx Control - RW */ +- E1000_FCTTV = 0x00170, /* Flow Control Transmit Timer Value - RW */ +- E1000_TXCW = 0x00178, /* Tx Configuration Word - RW */ +- E1000_RXCW = 0x00180, /* Rx Configuration Word - RO */ +- E1000_TCTL = 0x00400, /* Tx Control - RW */ +- E1000_TCTL_EXT = 0x00404, /* Extended Tx Control - RW */ +- E1000_TIPG = 0x00410, /* Tx Inter-packet gap -RW */ +- E1000_AIT = 0x00458, /* Adaptive Interframe Spacing Throttle -RW */ +- E1000_LEDCTL = 0x00E00, /* LED Control - RW */ +- E1000_EXTCNF_CTRL = 0x00F00, /* Extended Configuration Control */ +- E1000_EXTCNF_SIZE = 0x00F08, /* Extended Configuration Size */ +- E1000_PHY_CTRL = 0x00F10, /* PHY Control Register in CSR */ +-#define E1000_POEMB E1000_PHY_CTRL /* PHY OEM Bits */ +- E1000_PBA = 0x01000, /* Packet Buffer Allocation - RW */ +- E1000_PBS = 0x01008, /* Packet Buffer Size */ +- E1000_EEMNGCTL = 0x01010, /* MNG EEprom Control */ +- E1000_EEWR = 0x0102C, /* EEPROM Write Register - RW */ +- E1000_FLOP = 0x0103C, /* FLASH Opcode Register */ +- E1000_PBA_ECC = 0x01100, /* PBA ECC Register */ +- E1000_ERT = 0x02008, /* Early Rx Threshold - RW */ +- E1000_FCRTL = 0x02160, /* Flow Control Receive Threshold Low - RW */ +- E1000_FCRTH = 0x02168, /* Flow Control Receive Threshold High - RW */ +- E1000_PSRCTL = 0x02170, /* Packet Split Receive Control - RW */ +- E1000_RDBAL = 0x02800, /* Rx Descriptor Base Address Low - RW */ +- E1000_RDBAH = 0x02804, /* Rx Descriptor Base Address High - RW */ +- E1000_RDLEN = 0x02808, /* Rx Descriptor Length - RW */ +- E1000_RDH = 0x02810, /* Rx Descriptor Head - RW */ +- E1000_RDT = 0x02818, /* Rx Descriptor Tail - RW */ +- E1000_RDTR = 0x02820, /* Rx Delay Timer - RW */ +- E1000_RXDCTL_BASE = 0x02828, /* Rx Descriptor Control - RW */ +-#define E1000_RXDCTL(_n) (E1000_RXDCTL_BASE + (_n << 8)) +- E1000_RADV = 0x0282C, /* Rx Interrupt Absolute Delay Timer - RW */ +- +-/* Convenience macros +- * +- * Note: "_n" is the queue number of the register to be written to. +- * +- * Example usage: +- * E1000_RDBAL_REG(current_rx_queue) +- * +- */ +-#define E1000_RDBAL_REG(_n) (E1000_RDBAL + (_n << 8)) +- E1000_KABGTXD = 0x03004, /* AFE Band Gap Transmit Ref Data */ +- E1000_TDBAL = 0x03800, /* Tx Descriptor Base Address Low - RW */ +- E1000_TDBAH = 0x03804, /* Tx Descriptor Base Address High - RW */ +- E1000_TDLEN = 0x03808, /* Tx Descriptor Length - RW */ +- E1000_TDH = 0x03810, /* Tx Descriptor Head - RW */ +- E1000_TDT = 0x03818, /* Tx Descriptor Tail - RW */ +- E1000_TIDV = 0x03820, /* Tx Interrupt Delay Value - RW */ +- E1000_TXDCTL_BASE = 0x03828, /* Tx Descriptor Control - RW */ +-#define E1000_TXDCTL(_n) (E1000_TXDCTL_BASE + (_n << 8)) +- E1000_TADV = 0x0382C, /* Tx Interrupt Absolute Delay Val - RW */ +- E1000_TARC_BASE = 0x03840, /* Tx Arbitration Count (0) */ +-#define E1000_TARC(_n) (E1000_TARC_BASE + (_n << 8)) +- E1000_CRCERRS = 0x04000, /* CRC Error Count - R/clr */ +- E1000_ALGNERRC = 0x04004, /* Alignment Error Count - R/clr */ +- E1000_SYMERRS = 0x04008, /* Symbol Error Count - R/clr */ +- E1000_RXERRC = 0x0400C, /* Receive Error Count - R/clr */ +- E1000_MPC = 0x04010, /* Missed Packet Count - R/clr */ +- E1000_SCC = 0x04014, /* Single Collision Count - R/clr */ +- E1000_ECOL = 0x04018, /* Excessive Collision Count - R/clr */ +- E1000_MCC = 0x0401C, /* Multiple Collision Count - R/clr */ +- E1000_LATECOL = 0x04020, /* Late Collision Count - R/clr */ +- E1000_COLC = 0x04028, /* Collision Count - R/clr */ +- E1000_DC = 0x04030, /* Defer Count - R/clr */ +- E1000_TNCRS = 0x04034, /* Tx-No CRS - R/clr */ +- E1000_SEC = 0x04038, /* Sequence Error Count - R/clr */ +- E1000_CEXTERR = 0x0403C, /* Carrier Extension Error Count - R/clr */ +- E1000_RLEC = 0x04040, /* Receive Length Error Count - R/clr */ +- E1000_XONRXC = 0x04048, /* XON Rx Count - R/clr */ +- E1000_XONTXC = 0x0404C, /* XON Tx Count - R/clr */ +- E1000_XOFFRXC = 0x04050, /* XOFF Rx Count - R/clr */ +- E1000_XOFFTXC = 0x04054, /* XOFF Tx Count - R/clr */ +- E1000_FCRUC = 0x04058, /* Flow Control Rx Unsupported Count- R/clr */ +- E1000_PRC64 = 0x0405C, /* Packets Rx (64 bytes) - R/clr */ +- E1000_PRC127 = 0x04060, /* Packets Rx (65-127 bytes) - R/clr */ +- E1000_PRC255 = 0x04064, /* Packets Rx (128-255 bytes) - R/clr */ +- E1000_PRC511 = 0x04068, /* Packets Rx (255-511 bytes) - R/clr */ +- E1000_PRC1023 = 0x0406C, /* Packets Rx (512-1023 bytes) - R/clr */ +- E1000_PRC1522 = 0x04070, /* Packets Rx (1024-1522 bytes) - R/clr */ +- E1000_GPRC = 0x04074, /* Good Packets Rx Count - R/clr */ +- E1000_BPRC = 0x04078, /* Broadcast Packets Rx Count - R/clr */ +- E1000_MPRC = 0x0407C, /* Multicast Packets Rx Count - R/clr */ +- E1000_GPTC = 0x04080, /* Good Packets Tx Count - R/clr */ +- E1000_GORCL = 0x04088, /* Good Octets Rx Count Low - R/clr */ +- E1000_GORCH = 0x0408C, /* Good Octets Rx Count High - R/clr */ +- E1000_GOTCL = 0x04090, /* Good Octets Tx Count Low - R/clr */ +- E1000_GOTCH = 0x04094, /* Good Octets Tx Count High - R/clr */ +- E1000_RNBC = 0x040A0, /* Rx No Buffers Count - R/clr */ +- E1000_RUC = 0x040A4, /* Rx Undersize Count - R/clr */ +- E1000_RFC = 0x040A8, /* Rx Fragment Count - R/clr */ +- E1000_ROC = 0x040AC, /* Rx Oversize Count - R/clr */ +- E1000_RJC = 0x040B0, /* Rx Jabber Count - R/clr */ +- E1000_MGTPRC = 0x040B4, /* Management Packets Rx Count - R/clr */ +- E1000_MGTPDC = 0x040B8, /* Management Packets Dropped Count - R/clr */ +- E1000_MGTPTC = 0x040BC, /* Management Packets Tx Count - R/clr */ +- E1000_TORL = 0x040C0, /* Total Octets Rx Low - R/clr */ +- E1000_TORH = 0x040C4, /* Total Octets Rx High - R/clr */ +- E1000_TOTL = 0x040C8, /* Total Octets Tx Low - R/clr */ +- E1000_TOTH = 0x040CC, /* Total Octets Tx High - R/clr */ +- E1000_TPR = 0x040D0, /* Total Packets Rx - R/clr */ +- E1000_TPT = 0x040D4, /* Total Packets Tx - R/clr */ +- E1000_PTC64 = 0x040D8, /* Packets Tx (64 bytes) - R/clr */ +- E1000_PTC127 = 0x040DC, /* Packets Tx (65-127 bytes) - R/clr */ +- E1000_PTC255 = 0x040E0, /* Packets Tx (128-255 bytes) - R/clr */ +- E1000_PTC511 = 0x040E4, /* Packets Tx (256-511 bytes) - R/clr */ +- E1000_PTC1023 = 0x040E8, /* Packets Tx (512-1023 bytes) - R/clr */ +- E1000_PTC1522 = 0x040EC, /* Packets Tx (1024-1522 Bytes) - R/clr */ +- E1000_MPTC = 0x040F0, /* Multicast Packets Tx Count - R/clr */ +- E1000_BPTC = 0x040F4, /* Broadcast Packets Tx Count - R/clr */ +- E1000_TSCTC = 0x040F8, /* TCP Segmentation Context Tx - R/clr */ +- E1000_TSCTFC = 0x040FC, /* TCP Segmentation Context Tx Fail - R/clr */ +- E1000_IAC = 0x04100, /* Interrupt Assertion Count */ +- E1000_ICRXPTC = 0x04104, /* Irq Cause Rx Packet Timer Expire Count */ +- E1000_ICRXATC = 0x04108, /* Irq Cause Rx Abs Timer Expire Count */ +- E1000_ICTXPTC = 0x0410C, /* Irq Cause Tx Packet Timer Expire Count */ +- E1000_ICTXATC = 0x04110, /* Irq Cause Tx Abs Timer Expire Count */ +- E1000_ICTXQEC = 0x04118, /* Irq Cause Tx Queue Empty Count */ +- E1000_ICTXQMTC = 0x0411C, /* Irq Cause Tx Queue MinThreshold Count */ +- E1000_ICRXDMTC = 0x04120, /* Irq Cause Rx Desc MinThreshold Count */ +- E1000_ICRXOC = 0x04124, /* Irq Cause Receiver Overrun Count */ +- E1000_RXCSUM = 0x05000, /* Rx Checksum Control - RW */ +- E1000_RFCTL = 0x05008, /* Receive Filter Control */ +- E1000_MTA = 0x05200, /* Multicast Table Array - RW Array */ +- E1000_RAL_BASE = 0x05400, /* Receive Address Low - RW */ +-#define E1000_RAL(_n) (E1000_RAL_BASE + ((_n) * 8)) +-#define E1000_RA (E1000_RAL(0)) +- E1000_RAH_BASE = 0x05404, /* Receive Address High - RW */ +-#define E1000_RAH(_n) (E1000_RAH_BASE + ((_n) * 8)) +- E1000_VFTA = 0x05600, /* VLAN Filter Table Array - RW Array */ +- E1000_WUC = 0x05800, /* Wakeup Control - RW */ +- E1000_WUFC = 0x05808, /* Wakeup Filter Control - RW */ +- E1000_WUS = 0x05810, /* Wakeup Status - RO */ +- E1000_MANC = 0x05820, /* Management Control - RW */ +- E1000_FFLT = 0x05F00, /* Flexible Filter Length Table - RW Array */ +- E1000_HOST_IF = 0x08800, /* Host Interface */ +- +- E1000_KMRNCTRLSTA = 0x00034, /* MAC-PHY interface - RW */ +- E1000_MANC2H = 0x05860, /* Management Control To Host - RW */ +- E1000_MDEF_BASE = 0x05890, /* Management Decision Filters */ +-#define E1000_MDEF(_n) (E1000_MDEF_BASE + ((_n) * 4)) +- E1000_SW_FW_SYNC = 0x05B5C, /* Software-Firmware Synchronization - RW */ +- E1000_GCR = 0x05B00, /* PCI-Ex Control */ +- E1000_GCR2 = 0x05B64, /* PCI-Ex Control #2 */ +- E1000_FACTPS = 0x05B30, /* Function Active and Power State to MNG */ +- E1000_SWSM = 0x05B50, /* SW Semaphore */ +- E1000_FWSM = 0x05B54, /* FW Semaphore */ +- E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */ +- E1000_FFLT_DBG = 0x05F04, /* Debug Register */ +- E1000_PCH_RAICC_BASE = 0x05F50, /* Receive Address Initial CRC */ +-#define E1000_PCH_RAICC(_n) (E1000_PCH_RAICC_BASE + ((_n) * 4)) +-#define E1000_CRC_OFFSET E1000_PCH_RAICC_BASE +- E1000_HICR = 0x08F00, /* Host Interface Control */ +-}; +- +-#define E1000_MAX_PHY_ADDR 4 +- +-/* IGP01E1000 Specific Registers */ +-#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ +-#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */ +-#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ +-#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ +-#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ +-#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ +-#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ +-#define IGP_PAGE_SHIFT 5 +-#define PHY_REG_MASK 0x1F +- +-#define BM_WUC_PAGE 800 +-#define BM_WUC_ADDRESS_OPCODE 0x11 +-#define BM_WUC_DATA_OPCODE 0x12 +-#define BM_WUC_ENABLE_PAGE 769 +-#define BM_WUC_ENABLE_REG 17 +-#define BM_WUC_ENABLE_BIT (1 << 2) +-#define BM_WUC_HOST_WU_BIT (1 << 4) +-#define BM_WUC_ME_WU_BIT (1 << 5) +- +-#define BM_WUC PHY_REG(BM_WUC_PAGE, 1) +-#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2) +-#define BM_WUS PHY_REG(BM_WUC_PAGE, 3) +- +-#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 +-#define IGP01E1000_PHY_POLARITY_MASK 0x0078 +- +-#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 +-#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ +- +-#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 +- +-#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ +-#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ +-#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ +- +-#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 +- +-#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 +-#define IGP01E1000_PSSR_MDIX 0x0800 +-#define IGP01E1000_PSSR_SPEED_MASK 0xC000 +-#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 +- +-#define IGP02E1000_PHY_CHANNEL_NUM 4 +-#define IGP02E1000_PHY_AGC_A 0x11B1 +-#define IGP02E1000_PHY_AGC_B 0x12B1 +-#define IGP02E1000_PHY_AGC_C 0x14B1 +-#define IGP02E1000_PHY_AGC_D 0x18B1 +- +-#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */ +-#define IGP02E1000_AGC_LENGTH_MASK 0x7F +-#define IGP02E1000_AGC_RANGE 15 +- +-/* manage.c */ +-#define E1000_VFTA_ENTRY_SHIFT 5 +-#define E1000_VFTA_ENTRY_MASK 0x7F +-#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F +- +-#define E1000_HICR_EN 0x01 /* Enable bit - RO */ +-/* Driver sets this bit when done to put command in RAM */ +-#define E1000_HICR_C 0x02 +-#define E1000_HICR_FW_RESET_ENABLE 0x40 +-#define E1000_HICR_FW_RESET 0x80 +- +-#define E1000_FWSM_MODE_MASK 0xE +-#define E1000_FWSM_MODE_SHIFT 1 +- +-#define E1000_MNG_IAMT_MODE 0x3 +-#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 +-#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 +-#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 +-#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 +-#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1 +-#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 +- +-/* nvm.c */ +-#define E1000_STM_OPCODE 0xDB00 +- +-#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 +-#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 +-#define E1000_KMRNCTRLSTA_REN 0x00200000 +-#define E1000_KMRNCTRLSTA_CTRL_OFFSET 0x1 /* Kumeran Control */ +-#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ +-#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ +-#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ +-#define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */ +-#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ +-#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 +-#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002 +-#define E1000_KMRNCTRLSTA_HD_CTRL 0x10 /* Kumeran HD Control */ +- +-#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 +-#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ +-#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Control */ +-#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */ +- +-/* IFE PHY Extended Status Control */ +-#define IFE_PESC_POLARITY_REVERSED 0x0100 +- +-/* IFE PHY Special Control */ +-#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 +-#define IFE_PSC_FORCE_POLARITY 0x0020 +- +-/* IFE PHY Special Control and LED Control */ +-#define IFE_PSCL_PROBE_MODE 0x0020 +-#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ +-#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ +- +-/* IFE PHY MDIX Control */ +-#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ +-#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */ +-#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto MDI/MDI-X, 0=disable */ +- +-#define E1000_CABLE_LENGTH_UNDEFINED 0xFF ++struct e1000_hw; + + #define E1000_DEV_ID_82571EB_COPPER 0x105E + #define E1000_DEV_ID_82571EB_FIBER 0x105F +@@ -361,13 +52,11 @@ enum e1e_registers { + #define E1000_DEV_ID_82573L 0x109A + #define E1000_DEV_ID_82574L 0x10D3 + #define E1000_DEV_ID_82574LA 0x10F6 +-#define E1000_DEV_ID_82583V 0x150C +- ++#define E1000_DEV_ID_82583V 0x150C + #define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 + #define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 + #define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA + #define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB +- + #define E1000_DEV_ID_ICH8_82567V_3 0x1501 + #define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049 + #define E1000_DEV_ID_ICH8_IGP_AMT 0x104A +@@ -397,13 +86,21 @@ enum e1e_registers { + #define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 + #define E1000_DEV_ID_PCH2_LV_LM 0x1502 + #define E1000_DEV_ID_PCH2_LV_V 0x1503 ++#define E1000_DEV_ID_PCH_LPT_I217_LM 0x153A ++#define E1000_DEV_ID_PCH_LPT_I217_V 0x153B ++#define E1000_DEV_ID_PCH_LPTLP_I218_LM 0x155A ++#define E1000_DEV_ID_PCH_LPTLP_I218_V 0x1559 ++#define E1000_DEV_ID_PCH_I218_LM2 0x15A0 ++#define E1000_DEV_ID_PCH_I218_V2 0x15A1 ++#define E1000_DEV_ID_PCH_I218_LM3 0x15A2 /* Wildcat Point PCH */ ++#define E1000_DEV_ID_PCH_I218_V3 0x15A3 /* Wildcat Point PCH */ + +-#define E1000_REVISION_4 4 ++#define E1000_REVISION_4 4 + +-#define E1000_FUNC_1 1 ++#define E1000_FUNC_1 1 + +-#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 +-#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 ++#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 ++#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 + + enum e1000_mac_type { + e1000_82571, +@@ -417,6 +114,7 @@ enum e1000_mac_type { + e1000_ich10lan, + e1000_pchlan, + e1000_pch2lan, ++ e1000_pch_lpt, + }; + + enum e1000_media_type { +@@ -454,6 +152,7 @@ enum e1000_phy_type { + e1000_phy_82578, + e1000_phy_82577, + e1000_phy_82579, ++ e1000_phy_i217, + }; + + enum e1000_bus_width { +@@ -472,7 +171,7 @@ enum e1000_1000t_rx_status { + e1000_1000t_rx_status_undefined = 0xFF + }; + +-enum e1000_rev_polarity{ ++enum e1000_rev_polarity { + e1000_rev_polarity_normal = 0, + e1000_rev_polarity_reversed, + e1000_rev_polarity_undefined = 0xFF +@@ -506,16 +205,6 @@ enum e1000_serdes_link_state { + e1000_serdes_link_forced_up + }; + +-/* Receive Descriptor */ +-struct e1000_rx_desc { +- __le64 buffer_addr; /* Address of the descriptor's data buffer */ +- __le16 length; /* Length of data DMAed into data buffer */ +- __le16 csum; /* Packet checksum */ +- u8 status; /* Descriptor status */ +- u8 errors; /* Descriptor Errors */ +- __le16 special; +-}; +- + /* Receive Descriptor - Extended */ + union e1000_rx_desc_extended { + struct { +@@ -542,6 +231,10 @@ union e1000_rx_desc_extended { + }; + + #define MAX_PS_BUFFERS 4 ++ ++/* Number of packet split data buffers (not including the header buffer) */ ++#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) ++ + /* Receive Descriptor - Packet Split */ + union e1000_rx_desc_packet_split { + struct { +@@ -566,7 +259,8 @@ union e1000_rx_desc_packet_split { + } middle; + struct { + __le16 header_status; +- __le16 length[3]; /* length of buffers 1-3 */ ++ /* length of buffers 1-3 */ ++ __le16 length[PS_PAGE_BUFFERS]; + } upper; + __le64 reserved; + } wb; /* writeback */ +@@ -638,7 +332,7 @@ struct e1000_data_desc { + struct { + u8 status; /* Descriptor status */ + u8 popts; /* Packet Options */ +- __le16 special; /* */ ++ __le16 special; + } fields; + } upper; + }; +@@ -717,13 +411,13 @@ struct e1000_phy_stats { + + struct e1000_host_mng_dhcp_cookie { + u32 signature; +- u8 status; +- u8 reserved0; ++ u8 status; ++ u8 reserved0; + u16 vlan_id; + u32 reserved1; + u16 reserved2; +- u8 reserved3; +- u8 checksum; ++ u8 reserved3; ++ u8 checksum; + }; + + /* Host Interface "Rev 1" */ +@@ -734,7 +428,7 @@ struct e1000_host_command_header { + u8 checksum; + }; + +-#define E1000_HI_MAX_DATA_LENGTH 252 ++#define E1000_HI_MAX_DATA_LENGTH 252 + struct e1000_host_command_info { + struct e1000_host_command_header command_header; + u8 command_data[E1000_HI_MAX_DATA_LENGTH]; +@@ -742,20 +436,25 @@ struct e1000_host_command_info { + + /* Host Interface "Rev 2" */ + struct e1000_host_mng_command_header { +- u8 command_id; +- u8 checksum; ++ u8 command_id; ++ u8 checksum; + u16 reserved1; + u16 reserved2; + u16 command_length; + }; + +-#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 ++#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 + struct e1000_host_mng_command_info { + struct e1000_host_mng_command_header command_header; + u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; + }; + +-/* Function pointers and static data for the MAC. */ ++#include "mac.h" ++#include "phy.h" ++#include "nvm.h" ++#include "manage.h" ++ ++/* Function pointers for the MAC. */ + struct e1000_mac_operations { + s32 (*id_led_init)(struct e1000_hw *); + s32 (*blink_led)(struct e1000_hw *); +@@ -776,11 +475,12 @@ struct e1000_mac_operations { + s32 (*setup_physical_interface)(struct e1000_hw *); + s32 (*setup_led)(struct e1000_hw *); + void (*write_vfta)(struct e1000_hw *, u32, u32); ++ void (*config_collision_dist)(struct e1000_hw *); ++ void (*rar_set)(struct e1000_hw *, u8 *, u32); + s32 (*read_mac_addr)(struct e1000_hw *); + }; + +-/* +- * When to use various PHY register access functions: ++/* When to use various PHY register access functions: + * + * Func Caller + * Function Does Does When to use +@@ -824,6 +524,7 @@ struct e1000_nvm_operations { + s32 (*acquire)(struct e1000_hw *); + s32 (*read)(struct e1000_hw *, u16, u16, u16 *); + void (*release)(struct e1000_hw *); ++ void (*reload)(struct e1000_hw *); + s32 (*update)(struct e1000_hw *); + s32 (*valid_led_default)(struct e1000_hw *, u16 *); + s32 (*validate)(struct e1000_hw *); +@@ -853,11 +554,11 @@ struct e1000_mac_info { + u16 mta_reg_count; + + /* Maximum size of the MTA register table in all supported adapters */ +- #define MAX_MTA_REG 128 ++#define MAX_MTA_REG 128 + u32 mta_shadow[MAX_MTA_REG]; + u16 rar_entry_count; + +- u8 forced_speed_duplex; ++ u8 forced_speed_duplex; + + bool adaptive_ifs; + bool has_fwsm; +@@ -885,7 +586,7 @@ struct e1000_phy_info { + + u32 addr; + u32 id; +- u32 reset_delay_us; /* in usec */ ++ u32 reset_delay_us; /* in usec */ + u32 revision; + + enum e1000_media_type media_type; +@@ -944,11 +645,11 @@ struct e1000_dev_spec_82571 { + }; + + struct e1000_dev_spec_80003es2lan { +- bool mdic_wa_enable; ++ bool mdic_wa_enable; + }; + + struct e1000_shadow_ram { +- u16 value; ++ u16 value; + bool modified; + }; + +@@ -959,26 +660,31 @@ struct e1000_dev_spec_ich8lan { + struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS]; + bool nvm_k1_enabled; + bool eee_disable; ++ u16 eee_lp_ability; + }; + + struct e1000_hw { + struct e1000_adapter *adapter; + +- u8 __iomem *hw_addr; +- u8 __iomem *flash_address; ++ void __iomem *hw_addr; ++ void __iomem *flash_address; + +- struct e1000_mac_info mac; +- struct e1000_fc_info fc; +- struct e1000_phy_info phy; +- struct e1000_nvm_info nvm; +- struct e1000_bus_info bus; ++ struct e1000_mac_info mac; ++ struct e1000_fc_info fc; ++ struct e1000_phy_info phy; ++ struct e1000_nvm_info nvm; ++ struct e1000_bus_info bus; + struct e1000_host_mng_dhcp_cookie mng_cookie; + + union { +- struct e1000_dev_spec_82571 e82571; ++ struct e1000_dev_spec_82571 e82571; + struct e1000_dev_spec_80003es2lan e80003es2lan; +- struct e1000_dev_spec_ich8lan ich8lan; ++ struct e1000_dev_spec_ich8lan ich8lan; + } dev_spec; + }; + ++#include "82571.h" ++#include "80003es2lan.h" ++#include "ich8lan.h" ++ + #endif +diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c +index e2a80a2..0479f4d 100644 +--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c ++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel PRO/1000 Linux driver +- Copyright(c) 1999 - 2011 Intel Corporation. ++ Copyright(c) 1999 - 2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -26,8 +26,7 @@ + + *******************************************************************************/ + +-/* +- * 82562G 10/100 Network Connection ++/* 82562G 10/100 Network Connection + * 82562G-2 10/100 Network Connection + * 82562GT 10/100 Network Connection + * 82562GT-2 10/100 Network Connection +@@ -58,130 +57,19 @@ + + #include "e1000.h" + +-#define ICH_FLASH_GFPREG 0x0000 +-#define ICH_FLASH_HSFSTS 0x0004 +-#define ICH_FLASH_HSFCTL 0x0006 +-#define ICH_FLASH_FADDR 0x0008 +-#define ICH_FLASH_FDATA0 0x0010 +-#define ICH_FLASH_PR0 0x0074 +- +-#define ICH_FLASH_READ_COMMAND_TIMEOUT 500 +-#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 500 +-#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 3000000 +-#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF +-#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 +- +-#define ICH_CYCLE_READ 0 +-#define ICH_CYCLE_WRITE 2 +-#define ICH_CYCLE_ERASE 3 +- +-#define FLASH_GFPREG_BASE_MASK 0x1FFF +-#define FLASH_SECTOR_ADDR_SHIFT 12 +- +-#define ICH_FLASH_SEG_SIZE_256 256 +-#define ICH_FLASH_SEG_SIZE_4K 4096 +-#define ICH_FLASH_SEG_SIZE_8K 8192 +-#define ICH_FLASH_SEG_SIZE_64K 65536 +- +- +-#define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */ +-/* FW established a valid mode */ +-#define E1000_ICH_FWSM_FW_VALID 0x00008000 +- +-#define E1000_ICH_MNG_IAMT_MODE 0x2 +- +-#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \ +- (ID_LED_DEF1_OFF2 << 8) | \ +- (ID_LED_DEF1_ON2 << 4) | \ +- (ID_LED_DEF1_DEF2)) +- +-#define E1000_ICH_NVM_SIG_WORD 0x13 +-#define E1000_ICH_NVM_SIG_MASK 0xC000 +-#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0 +-#define E1000_ICH_NVM_SIG_VALUE 0x80 +- +-#define E1000_ICH8_LAN_INIT_TIMEOUT 1500 +- +-#define E1000_FEXTNVM_SW_CONFIG 1 +-#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M :/ */ +- +-#define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7 +-#define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 +-#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 +- +-#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL +- +-#define E1000_ICH_RAR_ENTRIES 7 +- +-#define PHY_PAGE_SHIFT 5 +-#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \ +- ((reg) & MAX_PHY_REG_ADDRESS)) +-#define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */ +-#define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */ +- +-#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 +-#define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300 +-#define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200 +- +-#define HV_LED_CONFIG PHY_REG(768, 30) /* LED Configuration */ +- +-#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in milliseconds */ +- +-/* SMBus Address Phy Register */ +-#define HV_SMB_ADDR PHY_REG(768, 26) +-#define HV_SMB_ADDR_MASK 0x007F +-#define HV_SMB_ADDR_PEC_EN 0x0200 +-#define HV_SMB_ADDR_VALID 0x0080 +- +-/* PHY Power Management Control */ +-#define HV_PM_CTRL PHY_REG(770, 17) +- +-/* PHY Low Power Idle Control */ +-#define I82579_LPI_CTRL PHY_REG(772, 20) +-#define I82579_LPI_CTRL_ENABLE_MASK 0x6000 +-#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80 +- +-/* EMI Registers */ +-#define I82579_EMI_ADDR 0x10 +-#define I82579_EMI_DATA 0x11 +-#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */ +- +-/* Strapping Option Register - RO */ +-#define E1000_STRAP 0x0000C +-#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000 +-#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17 +- +-/* OEM Bits Phy Register */ +-#define HV_OEM_BITS PHY_REG(768, 25) +-#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */ +-#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ +-#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ +- +-#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ +-#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ +- +-/* KMRN Mode Control */ +-#define HV_KMRN_MODE_CTRL PHY_REG(769, 16) +-#define HV_KMRN_MDIO_SLOW 0x0400 +- +-/* KMRN FIFO Control and Status */ +-#define HV_KMRN_FIFO_CTRLSTA PHY_REG(770, 16) +-#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK 0x7000 +-#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT 12 +- + /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ + /* Offset 04h HSFSTS */ + union ich8_hws_flash_status { + struct ich8_hsfsts { +- u16 flcdone :1; /* bit 0 Flash Cycle Done */ +- u16 flcerr :1; /* bit 1 Flash Cycle Error */ +- u16 dael :1; /* bit 2 Direct Access error Log */ +- u16 berasesz :2; /* bit 4:3 Sector Erase Size */ +- u16 flcinprog :1; /* bit 5 flash cycle in Progress */ +- u16 reserved1 :2; /* bit 13:6 Reserved */ +- u16 reserved2 :6; /* bit 13:6 Reserved */ +- u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */ +- u16 flockdn :1; /* bit 15 Flash Config Lock-Down */ ++ u16 flcdone:1; /* bit 0 Flash Cycle Done */ ++ u16 flcerr:1; /* bit 1 Flash Cycle Error */ ++ u16 dael:1; /* bit 2 Direct Access error Log */ ++ u16 berasesz:2; /* bit 4:3 Sector Erase Size */ ++ u16 flcinprog:1; /* bit 5 flash cycle in Progress */ ++ u16 reserved1:2; /* bit 13:6 Reserved */ ++ u16 reserved2:6; /* bit 13:6 Reserved */ ++ u16 fldesvalid:1; /* bit 14 Flash Descriptor Valid */ ++ u16 flockdn:1; /* bit 15 Flash Config Lock-Down */ + } hsf_status; + u16 regval; + }; +@@ -190,11 +78,11 @@ union ich8_hws_flash_status { + /* Offset 06h FLCTL */ + union ich8_hws_flash_ctrl { + struct ich8_hsflctl { +- u16 flcgo :1; /* 0 Flash Cycle Go */ +- u16 flcycle :2; /* 2:1 Flash Cycle */ +- u16 reserved :5; /* 7:3 Reserved */ +- u16 fldbcount :2; /* 9:8 Flash Data Byte Count */ +- u16 flockdn :6; /* 15:10 Reserved */ ++ u16 flcgo:1; /* 0 Flash Cycle Go */ ++ u16 flcycle:2; /* 2:1 Flash Cycle */ ++ u16 reserved:5; /* 7:3 Reserved */ ++ u16 fldbcount:2; /* 9:8 Flash Data Byte Count */ ++ u16 flockdn:6; /* 15:10 Reserved */ + } hsf_ctrl; + u16 regval; + }; +@@ -202,10 +90,10 @@ union ich8_hws_flash_ctrl { + /* ICH Flash Region Access Permissions */ + union ich8_hws_flash_regacc { + struct ich8_flracc { +- u32 grra :8; /* 0:7 GbE region Read Access */ +- u32 grwa :8; /* 8:15 GbE region Write Access */ +- u32 gmrag :8; /* 23:16 GbE Master Read Access Grant */ +- u32 gmwag :8; /* 31:24 GbE Master Write Access Grant */ ++ u32 grra:8; /* 0:7 GbE region Read Access */ ++ u32 grwa:8; /* 8:15 GbE region Write Access */ ++ u32 gmrag:8; /* 23:16 GbE Master Read Access Grant */ ++ u32 gmwag:8; /* 31:24 GbE Master Write Access Grant */ + } hsf_flregacc; + u16 regval; + }; +@@ -213,17 +101,16 @@ union ich8_hws_flash_regacc { + /* ICH Flash Protected Region */ + union ich8_flash_protected_range { + struct ich8_pr { +- u32 base:13; /* 0:12 Protected Range Base */ +- u32 reserved1:2; /* 13:14 Reserved */ +- u32 rpe:1; /* 15 Read Protection Enable */ +- u32 limit:13; /* 16:28 Protected Range Limit */ +- u32 reserved2:2; /* 29:30 Reserved */ +- u32 wpe:1; /* 31 Write Protection Enable */ ++ u32 base:13; /* 0:12 Protected Range Base */ ++ u32 reserved1:2; /* 13:14 Reserved */ ++ u32 rpe:1; /* 15 Read Protection Enable */ ++ u32 limit:13; /* 16:28 Protected Range Limit */ ++ u32 reserved2:2; /* 29:30 Reserved */ ++ u32 wpe:1; /* 31 Write Protection Enable */ + } range; + u32 regval; + }; + +-static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw); + static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); + static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); + static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank); +@@ -235,9 +122,7 @@ static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, + u16 *data); + static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, + u8 size, u16 *data); +-static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw); + static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); +-static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw); + static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw); + static s32 e1000_led_on_ich8lan(struct e1000_hw *hw); + static s32 e1000_led_off_ich8lan(struct e1000_hw *hw); +@@ -249,12 +134,15 @@ static s32 e1000_led_off_pchlan(struct e1000_hw *hw); + static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); + static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); + static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); +-static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); ++static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); + static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); + static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); + static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); ++static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index); ++static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index); + static s32 e1000_k1_workaround_lv(struct e1000_hw *hw); + static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate); ++static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw); + + static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) + { +@@ -278,80 +166,198 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val) + + #define er16flash(reg) __er16flash(hw, (reg)) + #define er32flash(reg) __er32flash(hw, (reg)) +-#define ew16flash(reg,val) __ew16flash(hw, (reg), (val)) +-#define ew32flash(reg,val) __ew32flash(hw, (reg), (val)) ++#define ew16flash(reg, val) __ew16flash(hw, (reg), (val)) ++#define ew32flash(reg, val) __ew32flash(hw, (reg), (val)) + +-static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw) ++/** ++ * e1000_phy_is_accessible_pchlan - Check if able to access PHY registers ++ * @hw: pointer to the HW structure ++ * ++ * Test access to the PHY registers by reading the PHY ID registers. If ++ * the PHY ID is already known (e.g. resume path) compare it with known ID, ++ * otherwise assume the read PHY ID is correct if it is valid. ++ * ++ * Assumes the sw/fw/hw semaphore is already acquired. ++ **/ ++static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) + { +- u32 ctrl; ++ u16 phy_reg = 0; ++ u32 phy_id = 0; ++ s32 ret_val; ++ u16 retry_count; ++ u32 mac_reg = 0; + +- ctrl = er32(CTRL); +- ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE; +- ctrl &= ~E1000_CTRL_LANPHYPC_VALUE; +- ew32(CTRL, ctrl); +- e1e_flush(); +- udelay(10); +- ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE; +- ew32(CTRL, ctrl); ++ for (retry_count = 0; retry_count < 2; retry_count++) { ++ ret_val = e1e_rphy_locked(hw, MII_PHYSID1, &phy_reg); ++ if (ret_val || (phy_reg == 0xFFFF)) ++ continue; ++ phy_id = (u32)(phy_reg << 16); ++ ++ ret_val = e1e_rphy_locked(hw, MII_PHYSID2, &phy_reg); ++ if (ret_val || (phy_reg == 0xFFFF)) { ++ phy_id = 0; ++ continue; ++ } ++ phy_id |= (u32)(phy_reg & PHY_REVISION_MASK); ++ break; ++ } ++ ++ if (hw->phy.id) { ++ if (hw->phy.id == phy_id) ++ goto out; ++ } else if (phy_id) { ++ hw->phy.id = phy_id; ++ hw->phy.revision = (u32)(phy_reg & ~PHY_REVISION_MASK); ++ goto out; ++ } ++ ++ /* In case the PHY needs to be in mdio slow mode, ++ * set slow mode and try to get the PHY id again. ++ */ ++ hw->phy.ops.release(hw); ++ ret_val = e1000_set_mdio_slow_mode_hv(hw); ++ if (!ret_val) ++ ret_val = e1000e_get_phy_id(hw); ++ hw->phy.ops.acquire(hw); ++ ++ if (ret_val) ++ return false; ++out: ++ if (hw->mac.type == e1000_pch_lpt) { ++ /* Unforce SMBus mode in PHY */ ++ e1e_rphy_locked(hw, CV_SMB_CTRL, &phy_reg); ++ phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; ++ e1e_wphy_locked(hw, CV_SMB_CTRL, phy_reg); ++ ++ /* Unforce SMBus mode in MAC */ ++ mac_reg = er32(CTRL_EXT); ++ mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; ++ ew32(CTRL_EXT, mac_reg); ++ } ++ ++ return true; + } + + /** +- * e1000_init_phy_params_pchlan - Initialize PHY function pointers ++ * e1000_init_phy_workarounds_pchlan - PHY initialization workarounds + * @hw: pointer to the HW structure + * +- * Initialize family-specific PHY parameters and function pointers. ++ * Workarounds/flow necessary for PHY initialization during driver load ++ * and resume paths. + **/ +-static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) ++static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) + { +- struct e1000_phy_info *phy = &hw->phy; +- u32 fwsm; +- s32 ret_val = 0; ++ u32 mac_reg, fwsm = er32(FWSM); ++ s32 ret_val; + +- phy->addr = 1; +- phy->reset_delay_us = 100; +- +- phy->ops.set_page = e1000_set_page_igp; +- phy->ops.read_reg = e1000_read_phy_reg_hv; +- phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked; +- phy->ops.read_reg_page = e1000_read_phy_reg_page_hv; +- phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan; +- phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan; +- phy->ops.write_reg = e1000_write_phy_reg_hv; +- phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked; +- phy->ops.write_reg_page = e1000_write_phy_reg_page_hv; +- phy->ops.power_up = e1000_power_up_phy_copper; +- phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; +- phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; +- +- /* +- * The MAC-PHY interconnect may still be in SMBus mode +- * after Sx->S0. If the manageability engine (ME) is +- * disabled, then toggle the LANPHYPC Value bit to force +- * the interconnect to PCIe mode. ++ /* Gate automatic PHY configuration by hardware on managed and ++ * non-managed 82579 and newer adapters. + */ +- fwsm = er32(FWSM); +- if (!(fwsm & E1000_ICH_FWSM_FW_VALID) && !e1000_check_reset_block(hw)) { +- e1000_toggle_lanphypc_value_ich8lan(hw); +- msleep(50); ++ e1000_gate_hw_phy_config_ich8lan(hw, true); + +- /* +- * Gate automatic PHY configuration by hardware on +- * non-managed 82579 +- */ +- if (hw->mac.type == e1000_pch2lan) +- e1000_gate_hw_phy_config_ich8lan(hw, true); ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) { ++ e_dbg("Failed to initialize PHY flow\n"); ++ goto out; + } + +- /* +- * Reset the PHY before any access to it. Doing so, ensures that +- * the PHY is in a known good state before we read/write PHY registers. +- * The generic reset is sufficient here, because we haven't determined +- * the PHY type yet. ++ /* The MAC-PHY interconnect may be in SMBus mode. If the PHY is ++ * inaccessible and resetting the PHY is not blocked, toggle the ++ * LANPHYPC Value bit to force the interconnect to PCIe mode. + */ +- ret_val = e1000e_phy_hw_reset_generic(hw); +- if (ret_val) +- goto out; ++ switch (hw->mac.type) { ++ case e1000_pch_lpt: ++ if (e1000_phy_is_accessible_pchlan(hw)) ++ break; ++ ++ /* Before toggling LANPHYPC, see if PHY is accessible by ++ * forcing MAC to SMBus mode first. ++ */ ++ mac_reg = er32(CTRL_EXT); ++ mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; ++ ew32(CTRL_EXT, mac_reg); ++ ++ /* Wait 50 milliseconds for MAC to finish any retries ++ * that it might be trying to perform from previous ++ * attempts to acknowledge any phy read requests. ++ */ ++ msleep(50); ++ ++ /* fall-through */ ++ case e1000_pch2lan: ++ if (e1000_phy_is_accessible_pchlan(hw)) ++ break; + ++ /* fall-through */ ++ case e1000_pchlan: ++ if ((hw->mac.type == e1000_pchlan) && ++ (fwsm & E1000_ICH_FWSM_FW_VALID)) ++ break; ++ ++ if (hw->phy.ops.check_reset_block(hw)) { ++ e_dbg("Required LANPHYPC toggle blocked by ME\n"); ++ ret_val = -E1000_ERR_PHY; ++ break; ++ } ++ ++ e_dbg("Toggling LANPHYPC\n"); ++ ++ /* Set Phy Config Counter to 50msec */ ++ mac_reg = er32(FEXTNVM3); ++ mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; ++ mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; ++ ew32(FEXTNVM3, mac_reg); ++ ++ /* Toggle LANPHYPC Value bit */ ++ mac_reg = er32(CTRL); ++ mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE; ++ mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE; ++ ew32(CTRL, mac_reg); ++ e1e_flush(); ++ usleep_range(10, 20); ++ mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE; ++ ew32(CTRL, mac_reg); ++ e1e_flush(); ++ if (hw->mac.type < e1000_pch_lpt) { ++ msleep(50); ++ } else { ++ u16 count = 20; ++ do { ++ usleep_range(5000, 10000); ++ } while (!(er32(CTRL_EXT) & ++ E1000_CTRL_EXT_LPCD) && count--); ++ usleep_range(30000, 60000); ++ if (e1000_phy_is_accessible_pchlan(hw)) ++ break; ++ ++ /* Toggling LANPHYPC brings the PHY out of SMBus mode ++ * so ensure that the MAC is also out of SMBus mode ++ */ ++ mac_reg = er32(CTRL_EXT); ++ mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; ++ ew32(CTRL_EXT, mac_reg); ++ ++ if (e1000_phy_is_accessible_pchlan(hw)) ++ break; ++ ++ ret_val = -E1000_ERR_PHY; ++ } ++ break; ++ default: ++ break; ++ } ++ ++ hw->phy.ops.release(hw); ++ if (!ret_val) { ++ /* Reset the PHY before any access to it. Doing so, ensures ++ * that the PHY is in a known good state before we read/write ++ * PHY registers. The generic reset is sufficient here, ++ * because we haven't determined the PHY type yet. ++ */ ++ ret_val = e1000e_phy_hw_reset_generic(hw); ++ } ++ ++out: + /* Ungate automatic PHY configuration on non-managed 82579 */ + if ((hw->mac.type == e1000_pch2lan) && + !(fwsm & E1000_ICH_FWSM_FW_VALID)) { +@@ -359,33 +365,70 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) + e1000_gate_hw_phy_config_ich8lan(hw, false); + } + ++ return ret_val; ++} ++ ++/** ++ * e1000_init_phy_params_pchlan - Initialize PHY function pointers ++ * @hw: pointer to the HW structure ++ * ++ * Initialize family-specific PHY parameters and function pointers. ++ **/ ++static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ ++ phy->addr = 1; ++ phy->reset_delay_us = 100; ++ ++ phy->ops.set_page = e1000_set_page_igp; ++ phy->ops.read_reg = e1000_read_phy_reg_hv; ++ phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked; ++ phy->ops.read_reg_page = e1000_read_phy_reg_page_hv; ++ phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan; ++ phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan; ++ phy->ops.write_reg = e1000_write_phy_reg_hv; ++ phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked; ++ phy->ops.write_reg_page = e1000_write_phy_reg_page_hv; ++ phy->ops.power_up = e1000_power_up_phy_copper; ++ phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; ++ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; ++ + phy->id = e1000_phy_unknown; +- switch (hw->mac.type) { +- default: +- ret_val = e1000e_get_phy_id(hw); +- if (ret_val) +- goto out; +- if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK)) ++ ++ ret_val = e1000_init_phy_workarounds_pchlan(hw); ++ if (ret_val) ++ return ret_val; ++ ++ if (phy->id == e1000_phy_unknown) ++ switch (hw->mac.type) { ++ default: ++ ret_val = e1000e_get_phy_id(hw); ++ if (ret_val) ++ return ret_val; ++ if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK)) ++ break; ++ /* fall-through */ ++ case e1000_pch2lan: ++ case e1000_pch_lpt: ++ /* In case the PHY needs to be in mdio slow mode, ++ * set slow mode and try to get the PHY id again. ++ */ ++ ret_val = e1000_set_mdio_slow_mode_hv(hw); ++ if (ret_val) ++ return ret_val; ++ ret_val = e1000e_get_phy_id(hw); ++ if (ret_val) ++ return ret_val; + break; +- /* fall-through */ +- case e1000_pch2lan: +- /* +- * In case the PHY needs to be in mdio slow mode, +- * set slow mode and try to get the PHY id again. +- */ +- ret_val = e1000_set_mdio_slow_mode_hv(hw); +- if (ret_val) +- goto out; +- ret_val = e1000e_get_phy_id(hw); +- if (ret_val) +- goto out; +- break; +- } ++ } + phy->type = e1000e_get_phy_type_from_id(phy->id); + + switch (phy->type) { + case e1000_phy_82577: + case e1000_phy_82579: ++ case e1000_phy_i217: + phy->ops.check_polarity = e1000_check_polarity_82577; + phy->ops.force_speed_duplex = + e1000_phy_force_speed_duplex_82577; +@@ -404,7 +447,6 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) + break; + } + +-out: + return ret_val; + } + +@@ -420,20 +462,19 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) + s32 ret_val; + u16 i = 0; + +- phy->addr = 1; +- phy->reset_delay_us = 100; ++ phy->addr = 1; ++ phy->reset_delay_us = 100; + +- phy->ops.power_up = e1000_power_up_phy_copper; +- phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; ++ phy->ops.power_up = e1000_power_up_phy_copper; ++ phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; + +- /* +- * We may need to do this twice - once for IGP and if that fails, ++ /* We may need to do this twice - once for IGP and if that fails, + * we'll set BM func pointers and try again + */ + ret_val = e1000e_determine_phy_address(hw); + if (ret_val) { + phy->ops.write_reg = e1000e_write_phy_reg_bm; +- phy->ops.read_reg = e1000e_read_phy_reg_bm; ++ phy->ops.read_reg = e1000e_read_phy_reg_bm; + ret_val = e1000e_determine_phy_address(hw); + if (ret_val) { + e_dbg("Cannot determine PHY addr. Erroring out\n"); +@@ -512,8 +553,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) + + gfpreg = er32flash(ICH_FLASH_GFPREG); + +- /* +- * sector_X_addr is a "sector"-aligned address (4096 bytes) ++ /* sector_X_addr is a "sector"-aligned address (4096 bytes) + * Add 1 to sector_end_addr since this sector is included in + * the overall size. + */ +@@ -523,12 +563,11 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) + /* flash_base_addr is byte-aligned */ + nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; + +- /* +- * find total size of the NVM, then cut in half since the total ++ /* find total size of the NVM, then cut in half since the total + * size represents two separate NVM banks. + */ +- nvm->flash_bank_size = (sector_end_addr - sector_base_addr) +- << FLASH_SECTOR_ADDR_SHIFT; ++ nvm->flash_bank_size = ((sector_end_addr - sector_base_addr) ++ << FLASH_SECTOR_ADDR_SHIFT); + nvm->flash_bank_size /= 2; + /* Adjust to word count */ + nvm->flash_bank_size /= sizeof(u16); +@@ -538,7 +577,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) + /* Clear shadow ram */ + for (i = 0; i < nvm->word_size; i++) { + dev_spec->shadow_ram[i].modified = false; +- dev_spec->shadow_ram[i].value = 0xFFFF; ++ dev_spec->shadow_ram[i].value = 0xFFFF; + } + + return 0; +@@ -551,9 +590,8 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) + * Initialize family-specific MAC parameters and function + * pointers. + **/ +-static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) ++static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) + { +- struct e1000_hw *hw = &adapter->hw; + struct e1000_mac_info *mac = &hw->mac; + + /* Set media type function pointer */ +@@ -572,7 +610,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) + /* Adaptive IFS supported */ + mac->adaptive_ifs = true; + +- /* LED operations */ ++ /* LED and other operations */ + switch (mac->type) { + case e1000_ich8lan: + case e1000_ich9lan: +@@ -580,7 +618,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) + /* check management mode */ + mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan; + /* ID LED init */ +- mac->ops.id_led_init = e1000e_id_led_init; ++ mac->ops.id_led_init = e1000e_id_led_init_generic; + /* blink LED */ + mac->ops.blink_led = e1000e_blink_led_generic; + /* setup LED */ +@@ -591,8 +629,12 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) + mac->ops.led_on = e1000_led_on_ich8lan; + mac->ops.led_off = e1000_led_off_ich8lan; + break; +- case e1000_pchlan: + case e1000_pch2lan: ++ mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES; ++ mac->ops.rar_set = e1000_rar_set_pch2lan; ++ /* fall-through */ ++ case e1000_pch_lpt: ++ case e1000_pchlan: + /* check management mode */ + mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan; + /* ID LED init */ +@@ -609,48 +651,334 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) + break; + } + ++ if (mac->type == e1000_pch_lpt) { ++ mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES; ++ mac->ops.rar_set = e1000_rar_set_pch_lpt; ++ mac->ops.setup_physical_interface = ++ e1000_setup_copper_link_pch_lpt; ++ } ++ + /* Enable PCS Lock-loss workaround for ICH8 */ + if (mac->type == e1000_ich8lan) + e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true); + +- /* Gate automatic PHY configuration by hardware on managed 82579 */ +- if ((mac->type == e1000_pch2lan) && +- (er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) +- e1000_gate_hw_phy_config_ich8lan(hw, true); +- + return 0; + } + + /** ++ * __e1000_access_emi_reg_locked - Read/write EMI register ++ * @hw: pointer to the HW structure ++ * @addr: EMI address to program ++ * @data: pointer to value to read/write from/to the EMI address ++ * @read: boolean flag to indicate read or write ++ * ++ * This helper function assumes the SW/FW/HW Semaphore is already acquired. ++ **/ ++static s32 __e1000_access_emi_reg_locked(struct e1000_hw *hw, u16 address, ++ u16 *data, bool read) ++{ ++ s32 ret_val; ++ ++ ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR, address); ++ if (ret_val) ++ return ret_val; ++ ++ if (read) ++ ret_val = e1e_rphy_locked(hw, I82579_EMI_DATA, data); ++ else ++ ret_val = e1e_wphy_locked(hw, I82579_EMI_DATA, *data); ++ ++ return ret_val; ++} ++ ++/** ++ * e1000_read_emi_reg_locked - Read Extended Management Interface register ++ * @hw: pointer to the HW structure ++ * @addr: EMI address to program ++ * @data: value to be read from the EMI address ++ * ++ * Assumes the SW/FW/HW Semaphore is already acquired. ++ **/ ++s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data) ++{ ++ return __e1000_access_emi_reg_locked(hw, addr, data, true); ++} ++ ++/** ++ * e1000_write_emi_reg_locked - Write Extended Management Interface register ++ * @hw: pointer to the HW structure ++ * @addr: EMI address to program ++ * @data: value to be written to the EMI address ++ * ++ * Assumes the SW/FW/HW Semaphore is already acquired. ++ **/ ++s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data) ++{ ++ return __e1000_access_emi_reg_locked(hw, addr, &data, false); ++} ++ ++/** + * e1000_set_eee_pchlan - Enable/disable EEE support + * @hw: pointer to the HW structure + * +- * Enable/disable EEE based on setting in dev_spec structure. The bits in +- * the LPI Control register will remain set only if/when link is up. ++ * Enable/disable EEE based on setting in dev_spec structure, the duplex of ++ * the link and the EEE capabilities of the link partner. The LPI Control ++ * register bits will remain set only if/when link is up. + **/ + static s32 e1000_set_eee_pchlan(struct e1000_hw *hw) + { +- s32 ret_val = 0; +- u16 phy_reg; ++ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; ++ s32 ret_val; ++ u16 lpa, pcs_status, adv, adv_addr, lpi_ctrl, data; + +- if (hw->phy.type != e1000_phy_82579) +- goto out; ++ switch (hw->phy.type) { ++ case e1000_phy_82579: ++ lpa = I82579_EEE_LP_ABILITY; ++ pcs_status = I82579_EEE_PCS_STATUS; ++ adv_addr = I82579_EEE_ADVERTISEMENT; ++ break; ++ case e1000_phy_i217: ++ lpa = I217_EEE_LP_ABILITY; ++ pcs_status = I217_EEE_PCS_STATUS; ++ adv_addr = I217_EEE_ADVERTISEMENT; ++ break; ++ default: ++ return 0; ++ } + +- ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg); ++ ret_val = hw->phy.ops.acquire(hw); + if (ret_val) +- goto out; ++ return ret_val; + +- if (hw->dev_spec.ich8lan.eee_disable) +- phy_reg &= ~I82579_LPI_CTRL_ENABLE_MASK; +- else +- phy_reg |= I82579_LPI_CTRL_ENABLE_MASK; ++ ret_val = e1e_rphy_locked(hw, I82579_LPI_CTRL, &lpi_ctrl); ++ if (ret_val) ++ goto release; ++ ++ /* Clear bits that enable EEE in various speeds */ ++ lpi_ctrl &= ~I82579_LPI_CTRL_ENABLE_MASK; ++ ++ /* Enable EEE if not disabled by user */ ++ if (!dev_spec->eee_disable) { ++ /* Save off link partner's EEE ability */ ++ ret_val = e1000_read_emi_reg_locked(hw, lpa, ++ &dev_spec->eee_lp_ability); ++ if (ret_val) ++ goto release; ++ ++ /* Read EEE advertisement */ ++ ret_val = e1000_read_emi_reg_locked(hw, adv_addr, &adv); ++ if (ret_val) ++ goto release; ++ ++ /* Enable EEE only for speeds in which the link partner is ++ * EEE capable and for which we advertise EEE. ++ */ ++ if (adv & dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED) ++ lpi_ctrl |= I82579_LPI_CTRL_1000_ENABLE; ++ ++ if (adv & dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) { ++ e1e_rphy_locked(hw, MII_LPA, &data); ++ if (data & LPA_100FULL) ++ lpi_ctrl |= I82579_LPI_CTRL_100_ENABLE; ++ else ++ /* EEE is not supported in 100Half, so ignore ++ * partner's EEE in 100 ability if full-duplex ++ * is not advertised. ++ */ ++ dev_spec->eee_lp_ability &= ++ ~I82579_EEE_100_SUPPORTED; ++ } ++ } ++ ++ /* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */ ++ ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data); ++ if (ret_val) ++ goto release; ++ ++ ret_val = e1e_wphy_locked(hw, I82579_LPI_CTRL, lpi_ctrl); ++release: ++ hw->phy.ops.release(hw); + +- ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg); +-out: + return ret_val; + } + + /** ++ * e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP ++ * @hw: pointer to the HW structure ++ * @link: link up bool flag ++ * ++ * When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications ++ * preventing further DMA write requests. Workaround the issue by disabling ++ * the de-assertion of the clock request when in 1Gpbs mode. ++ * Also, set appropriate Tx re-transmission timeouts for 10 and 100Half link ++ * speeds in order to avoid Tx hangs. ++ **/ ++static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link) ++{ ++ u32 fextnvm6 = er32(FEXTNVM6); ++ u32 status = er32(STATUS); ++ s32 ret_val = 0; ++ u16 reg; ++ ++ if (link && (status & E1000_STATUS_SPEED_1000)) { ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ return ret_val; ++ ++ ret_val = ++ e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, ++ ®); ++ if (ret_val) ++ goto release; ++ ++ ret_val = ++ e1000e_write_kmrn_reg_locked(hw, ++ E1000_KMRNCTRLSTA_K1_CONFIG, ++ reg & ++ ~E1000_KMRNCTRLSTA_K1_ENABLE); ++ if (ret_val) ++ goto release; ++ ++ usleep_range(10, 20); ++ ++ ew32(FEXTNVM6, fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK); ++ ++ ret_val = ++ e1000e_write_kmrn_reg_locked(hw, ++ E1000_KMRNCTRLSTA_K1_CONFIG, ++ reg); ++release: ++ hw->phy.ops.release(hw); ++ } else { ++ /* clear FEXTNVM6 bit 8 on link down or 10/100 */ ++ fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK; ++ ++ if (!link || ((status & E1000_STATUS_SPEED_100) && ++ (status & E1000_STATUS_FD))) ++ goto update_fextnvm6; ++ ++ ret_val = e1e_rphy(hw, I217_INBAND_CTRL, ®); ++ if (ret_val) ++ return ret_val; ++ ++ /* Clear link status transmit timeout */ ++ reg &= ~I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK; ++ ++ if (status & E1000_STATUS_SPEED_100) { ++ /* Set inband Tx timeout to 5x10us for 100Half */ ++ reg |= 5 << I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT; ++ ++ /* Do not extend the K1 entry latency for 100Half */ ++ fextnvm6 &= ~E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION; ++ } else { ++ /* Set inband Tx timeout to 50x10us for 10Full/Half */ ++ reg |= 50 << ++ I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT; ++ ++ /* Extend the K1 entry latency for 10 Mbps */ ++ fextnvm6 |= E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION; ++ } ++ ++ ret_val = e1e_wphy(hw, I217_INBAND_CTRL, reg); ++ if (ret_val) ++ return ret_val; ++ ++update_fextnvm6: ++ ew32(FEXTNVM6, fextnvm6); ++ } ++ ++ return ret_val; ++} ++ ++/** ++ * e1000_platform_pm_pch_lpt - Set platform power management values ++ * @hw: pointer to the HW structure ++ * @link: bool indicating link status ++ * ++ * Set the Latency Tolerance Reporting (LTR) values for the "PCIe-like" ++ * GbE MAC in the Lynx Point PCH based on Rx buffer size and link speed ++ * when link is up (which must not exceed the maximum latency supported ++ * by the platform), otherwise specify there is no LTR requirement. ++ * Unlike true-PCIe devices which set the LTR maximum snoop/no-snoop ++ * latencies in the LTR Extended Capability Structure in the PCIe Extended ++ * Capability register set, on this device LTR is set by writing the ++ * equivalent snoop/no-snoop latencies in the LTRV register in the MAC and ++ * set the SEND bit to send an Intel On-chip System Fabric sideband (IOSF-SB) ++ * message to the PMC. ++ **/ ++static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link) ++{ ++ u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) | ++ link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND; ++ u16 lat_enc = 0; /* latency encoded */ ++ ++ if (link) { ++ u16 speed, duplex, scale = 0; ++ u16 max_snoop, max_nosnoop; ++ u16 max_ltr_enc; /* max LTR latency encoded */ ++ s64 lat_ns; /* latency (ns) */ ++ s64 value; ++ u32 rxa; ++ ++ if (!hw->adapter->max_frame_size) { ++ e_dbg("max_frame_size not set.\n"); ++ return -E1000_ERR_CONFIG; ++ } ++ ++ hw->mac.ops.get_link_up_info(hw, &speed, &duplex); ++ if (!speed) { ++ e_dbg("Speed not set.\n"); ++ return -E1000_ERR_CONFIG; ++ } ++ ++ /* Rx Packet Buffer Allocation size (KB) */ ++ rxa = er32(PBA) & E1000_PBA_RXA_MASK; ++ ++ /* Determine the maximum latency tolerated by the device. ++ * ++ * Per the PCIe spec, the tolerated latencies are encoded as ++ * a 3-bit encoded scale (only 0-5 are valid) multiplied by ++ * a 10-bit value (0-1023) to provide a range from 1 ns to ++ * 2^25*(2^10-1) ns. The scale is encoded as 0=2^0ns, ++ * 1=2^5ns, 2=2^10ns,...5=2^25ns. ++ */ ++ lat_ns = ((s64)rxa * 1024 - ++ (2 * (s64)hw->adapter->max_frame_size)) * 8 * 1000; ++ if (lat_ns < 0) ++ lat_ns = 0; ++ else ++ do_div(lat_ns, speed); ++ ++ value = lat_ns; ++ while (value > PCI_LTR_VALUE_MASK) { ++ scale++; ++ value = DIV_ROUND_UP(value, (1 << 5)); ++ } ++ if (scale > E1000_LTRV_SCALE_MAX) { ++ e_dbg("Invalid LTR latency scale %d\n", scale); ++ return -E1000_ERR_CONFIG; ++ } ++ lat_enc = (u16)((scale << PCI_LTR_SCALE_SHIFT) | value); ++ ++ /* Determine the maximum latency tolerated by the platform */ ++ pci_read_config_word(hw->adapter->pdev, E1000_PCI_LTR_CAP_LPT, ++ &max_snoop); ++ pci_read_config_word(hw->adapter->pdev, ++ E1000_PCI_LTR_CAP_LPT + 2, &max_nosnoop); ++ max_ltr_enc = max_t(u16, max_snoop, max_nosnoop); ++ ++ if (lat_enc > max_ltr_enc) ++ lat_enc = max_ltr_enc; ++ } ++ ++ /* Set Snoop and No-Snoop latencies the same */ ++ reg |= lat_enc | (lat_enc << E1000_LTRV_NOSNOOP_SHIFT); ++ ew32(LTRV, reg); ++ ++ return 0; ++} ++ ++/** + * e1000_check_for_copper_link_ich8lan - Check for link (Copper) + * @hw: pointer to the HW structure + * +@@ -665,34 +993,80 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) + bool link; + u16 phy_reg; + +- /* +- * We only want to go out to the PHY registers to see if Auto-Neg ++ /* We only want to go out to the PHY registers to see if Auto-Neg + * has completed and/or if our link status has changed. The + * get_link_status flag is set upon receiving a Link Status + * Change or Rx Sequence Error interrupt. + */ +- if (!mac->get_link_status) { +- ret_val = 0; +- goto out; +- } ++ if (!mac->get_link_status) ++ return 0; + +- /* +- * First we want to see if the MII Status Register reports ++ /* First we want to see if the MII Status Register reports + * link. If so, then we want to get the current speed/duplex + * of the PHY. + */ + ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) +- goto out; ++ return ret_val; + + if (hw->mac.type == e1000_pchlan) { + ret_val = e1000_k1_gig_workaround_hv(hw, link); + if (ret_val) +- goto out; ++ return ret_val; + } + ++ /* When connected at 10Mbps half-duplex, 82579 parts are excessively ++ * aggressive resulting in many collisions. To avoid this, increase ++ * the IPG and reduce Rx latency in the PHY. ++ */ ++ if ((hw->mac.type == e1000_pch2lan) && link) { ++ u32 reg; ++ reg = er32(STATUS); ++ if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) { ++ reg = er32(TIPG); ++ reg &= ~E1000_TIPG_IPGT_MASK; ++ reg |= 0xFF; ++ ew32(TIPG, reg); ++ ++ /* Reduce Rx latency in analog PHY */ ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ return ret_val; ++ ++ ret_val = ++ e1000_write_emi_reg_locked(hw, I82579_RX_CONFIG, 0); ++ ++ hw->phy.ops.release(hw); ++ ++ if (ret_val) ++ return ret_val; ++ } ++ } ++ ++ /* Work-around I218 hang issue */ ++ if ((hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_LM) || ++ (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V) || ++ (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_LM3) || ++ (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V3)) { ++ ret_val = e1000_k1_workaround_lpt_lp(hw, link); ++ if (ret_val) ++ return ret_val; ++ } ++ ++ if (hw->mac.type == e1000_pch_lpt) { ++ /* Set platform power management values for ++ * Latency Tolerance Reporting (LTR) ++ */ ++ ret_val = e1000_platform_pm_pch_lpt(hw, link); ++ if (ret_val) ++ return ret_val; ++ } ++ ++ /* Clear link partner's EEE ability */ ++ hw->dev_spec.ich8lan.eee_lp_ability = 0; ++ + if (!link) +- goto out; /* No link detected */ ++ return 0; /* No link detected */ + + mac->get_link_status = false; + +@@ -700,17 +1074,16 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) + case e1000_pch2lan: + ret_val = e1000_k1_workaround_lv(hw); + if (ret_val) +- goto out; ++ return ret_val; + /* fall-thru */ + case e1000_pchlan: + if (hw->phy.type == e1000_phy_82578) { + ret_val = e1000_link_stall_workaround_hv(hw); + if (ret_val) +- goto out; ++ return ret_val; + } + +- /* +- * Workaround for PCHx parts in half-duplex: ++ /* Workaround for PCHx parts in half-duplex: + * Set the number of preambles removed from the packet + * when it is passed from the PHY to the MAC to prevent + * the MAC from misinterpreting the packet type. +@@ -727,8 +1100,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) + break; + } + +- /* +- * Check if there was DownShift, must be checked ++ /* Check if there was DownShift, must be checked + * immediately after link-up + */ + e1000e_check_downshift(hw); +@@ -736,26 +1108,21 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) + /* Enable/Disable EEE after link up */ + ret_val = e1000_set_eee_pchlan(hw); + if (ret_val) +- goto out; ++ return ret_val; + +- /* +- * If we are forcing speed/duplex, then we simply return since ++ /* If we are forcing speed/duplex, then we simply return since + * we have already determined whether we have link or not. + */ +- if (!mac->autoneg) { +- ret_val = -E1000_ERR_CONFIG; +- goto out; +- } ++ if (!mac->autoneg) ++ return -E1000_ERR_CONFIG; + +- /* +- * Auto-Neg is enabled. Auto Speed Detection takes care ++ /* Auto-Neg is enabled. Auto Speed Detection takes care + * of MAC speed/duplex configuration. So we only need to + * configure Collision Distance in the MAC. + */ +- e1000e_config_collision_dist(hw); ++ mac->ops.config_collision_dist(hw); + +- /* +- * Configure Flow Control now that Auto-Neg has completed. ++ /* Configure Flow Control now that Auto-Neg has completed. + * First, we need to restore the desired flow control + * settings because we may have had to re-autoneg with a + * different link partner. +@@ -764,7 +1131,6 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) + if (ret_val) + e_dbg("Error configuring flow control\n"); + +-out: + return ret_val; + } + +@@ -773,7 +1139,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) + struct e1000_hw *hw = &adapter->hw; + s32 rc; + +- rc = e1000_init_mac_params_ich8lan(adapter); ++ rc = e1000_init_mac_params_ich8lan(hw); + if (rc) + return rc; + +@@ -789,6 +1155,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) + break; + case e1000_pchlan: + case e1000_pch2lan: ++ case e1000_pch_lpt: + rc = e1000_init_phy_params_pchlan(hw); + break; + default: +@@ -797,8 +1164,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) + if (rc) + return rc; + +- /* +- * Disable Jumbo Frame support on parts with Intel 10/100 PHY or ++ /* Disable Jumbo Frame support on parts with Intel 10/100 PHY or + * on parts with MACsec enabled in NVM (reflected in CTRL_EXT). + */ + if ((adapter->hw.phy.type == e1000_phy_ife) || +@@ -834,7 +1200,7 @@ static DEFINE_MUTEX(nvm_mutex); + * + * Acquires the mutex for performing NVM operations. + **/ +-static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw) ++static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw __always_unused *hw) + { + mutex_lock(&nvm_mutex); + +@@ -847,7 +1213,7 @@ static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw) + * + * Releases the mutex used while performing NVM operations. + **/ +-static void e1000_release_nvm_ich8lan(struct e1000_hw *hw) ++static void e1000_release_nvm_ich8lan(struct e1000_hw __always_unused *hw) + { + mutex_unlock(&nvm_mutex); + } +@@ -900,8 +1266,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) + } + + if (!timeout) { +- e_dbg("Failed to acquire the semaphore, FW or HW has it: " +- "FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n", ++ e_dbg("Failed to acquire the semaphore, FW or HW has it: FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n", + er32(FWSM), extcnf_ctrl); + extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; + ew32(EXTCNF_CTRL, extcnf_ctrl); +@@ -952,9 +1317,9 @@ static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw) + u32 fwsm; + + fwsm = er32(FWSM); +- return (fwsm & E1000_ICH_FWSM_FW_VALID) && +- ((fwsm & E1000_FWSM_MODE_MASK) == +- (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); ++ return ((fwsm & E1000_ICH_FWSM_FW_VALID) && ++ ((fwsm & E1000_FWSM_MODE_MASK) == ++ (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT))); + } + + /** +@@ -971,7 +1336,146 @@ static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw) + + fwsm = er32(FWSM); + return (fwsm & E1000_ICH_FWSM_FW_VALID) && +- (fwsm & (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); ++ (fwsm & (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); ++} ++ ++/** ++ * e1000_rar_set_pch2lan - Set receive address register ++ * @hw: pointer to the HW structure ++ * @addr: pointer to the receive address ++ * @index: receive address array register ++ * ++ * Sets the receive address array register at index to the address passed ++ * in by addr. For 82579, RAR[0] is the base address register that is to ++ * contain the MAC address but RAR[1-6] are reserved for manageability (ME). ++ * Use SHRA[0-3] in place of those reserved for ME. ++ **/ ++static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) ++{ ++ u32 rar_low, rar_high; ++ ++ /* HW expects these in little endian so we reverse the byte order ++ * from network order (big endian) to little endian ++ */ ++ rar_low = ((u32)addr[0] | ++ ((u32)addr[1] << 8) | ++ ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); ++ ++ rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); ++ ++ /* If MAC address zero, no need to set the AV bit */ ++ if (rar_low || rar_high) ++ rar_high |= E1000_RAH_AV; ++ ++ if (index == 0) { ++ ew32(RAL(index), rar_low); ++ e1e_flush(); ++ ew32(RAH(index), rar_high); ++ e1e_flush(); ++ return; ++ } ++ ++ /* RAR[1-6] are owned by manageability. Skip those and program the ++ * next address into the SHRA register array. ++ */ ++ if (index < (u32)(hw->mac.rar_entry_count - 6)) { ++ s32 ret_val; ++ ++ ret_val = e1000_acquire_swflag_ich8lan(hw); ++ if (ret_val) ++ goto out; ++ ++ ew32(SHRAL(index - 1), rar_low); ++ e1e_flush(); ++ ew32(SHRAH(index - 1), rar_high); ++ e1e_flush(); ++ ++ e1000_release_swflag_ich8lan(hw); ++ ++ /* verify the register updates */ ++ if ((er32(SHRAL(index - 1)) == rar_low) && ++ (er32(SHRAH(index - 1)) == rar_high)) ++ return; ++ ++ e_dbg("SHRA[%d] might be locked by ME - FWSM=0x%8.8x\n", ++ (index - 1), er32(FWSM)); ++ } ++ ++out: ++ e_dbg("Failed to write receive address at index %d\n", index); ++} ++ ++/** ++ * e1000_rar_set_pch_lpt - Set receive address registers ++ * @hw: pointer to the HW structure ++ * @addr: pointer to the receive address ++ * @index: receive address array register ++ * ++ * Sets the receive address register array at index to the address passed ++ * in by addr. For LPT, RAR[0] is the base address register that is to ++ * contain the MAC address. SHRA[0-10] are the shared receive address ++ * registers that are shared between the Host and manageability engine (ME). ++ **/ ++static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index) ++{ ++ u32 rar_low, rar_high; ++ u32 wlock_mac; ++ ++ /* HW expects these in little endian so we reverse the byte order ++ * from network order (big endian) to little endian ++ */ ++ rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) | ++ ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); ++ ++ rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); ++ ++ /* If MAC address zero, no need to set the AV bit */ ++ if (rar_low || rar_high) ++ rar_high |= E1000_RAH_AV; ++ ++ if (index == 0) { ++ ew32(RAL(index), rar_low); ++ e1e_flush(); ++ ew32(RAH(index), rar_high); ++ e1e_flush(); ++ return; ++ } ++ ++ /* The manageability engine (ME) can lock certain SHRAR registers that ++ * it is using - those registers are unavailable for use. ++ */ ++ if (index < hw->mac.rar_entry_count) { ++ wlock_mac = er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK; ++ wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT; ++ ++ /* Check if all SHRAR registers are locked */ ++ if (wlock_mac == 1) ++ goto out; ++ ++ if ((wlock_mac == 0) || (index <= wlock_mac)) { ++ s32 ret_val; ++ ++ ret_val = e1000_acquire_swflag_ich8lan(hw); ++ ++ if (ret_val) ++ goto out; ++ ++ ew32(SHRAL_PCH_LPT(index - 1), rar_low); ++ e1e_flush(); ++ ew32(SHRAH_PCH_LPT(index - 1), rar_high); ++ e1e_flush(); ++ ++ e1000_release_swflag_ich8lan(hw); ++ ++ /* verify the register updates */ ++ if ((er32(SHRAL_PCH_LPT(index - 1)) == rar_low) && ++ (er32(SHRAH_PCH_LPT(index - 1)) == rar_high)) ++ return; ++ } ++ } ++ ++out: ++ e_dbg("Failed to write receive address at index %d\n", index); + } + + /** +@@ -1002,21 +1506,34 @@ static s32 e1000_write_smbus_addr(struct e1000_hw *hw) + { + u16 phy_data; + u32 strap = er32(STRAP); +- s32 ret_val = 0; ++ u32 freq = (strap & E1000_STRAP_SMT_FREQ_MASK) >> ++ E1000_STRAP_SMT_FREQ_SHIFT; ++ s32 ret_val; + + strap &= E1000_STRAP_SMBUS_ADDRESS_MASK; + + ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data); + if (ret_val) +- goto out; ++ return ret_val; + + phy_data &= ~HV_SMB_ADDR_MASK; + phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT); + phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; +- ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data); + +-out: +- return ret_val; ++ if (hw->phy.type == e1000_phy_i217) { ++ /* Restore SMBus frequency */ ++ if (freq--) { ++ phy_data &= ~HV_SMB_ADDR_FREQ_MASK; ++ phy_data |= (freq & (1 << 0)) << ++ HV_SMB_ADDR_FREQ_LOW_SHIFT; ++ phy_data |= (freq & (1 << 1)) << ++ (HV_SMB_ADDR_FREQ_HIGH_SHIFT - 1); ++ } else { ++ e_dbg("Unsupported SMB frequency in PHY\n"); ++ } ++ } ++ ++ return e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data); + } + + /** +@@ -1033,8 +1550,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) + s32 ret_val = 0; + u16 word_addr, reg_data, reg_addr, phy_page = 0; + +- /* +- * Initialize the PHY from the NVM on ICH platforms. This ++ /* Initialize the PHY from the NVM on ICH platforms. This + * is needed due to an issue where the NVM configuration is + * not properly autoloaded after power transitions. + * Therefore, after each PHY reset, we will load the +@@ -1053,6 +1569,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) + /* Fall-thru */ + case e1000_pchlan: + case e1000_pch2lan: ++ case e1000_pch_lpt: + sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; + break; + default: +@@ -1065,45 +1582,42 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) + + data = er32(FEXTNVM); + if (!(data & sw_cfg_mask)) +- goto out; ++ goto release; + +- /* +- * Make sure HW does not configure LCD from PHY ++ /* Make sure HW does not configure LCD from PHY + * extended configuration before SW configuration + */ + data = er32(EXTCNF_CTRL); +- if (!(hw->mac.type == e1000_pch2lan)) { +- if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) +- goto out; +- } ++ if ((hw->mac.type < e1000_pch2lan) && ++ (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)) ++ goto release; + + cnf_size = er32(EXTCNF_SIZE); + cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; + cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; + if (!cnf_size) +- goto out; ++ goto release; + + cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; + cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; + +- if ((!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && +- (hw->mac.type == e1000_pchlan)) || +- (hw->mac.type == e1000_pch2lan)) { +- /* +- * HW configures the SMBus address and LEDs when the ++ if (((hw->mac.type == e1000_pchlan) && ++ !(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) || ++ (hw->mac.type > e1000_pchlan)) { ++ /* HW configures the SMBus address and LEDs when the + * OEM and LCD Write Enable bits are set in the NVM. + * When both NVM bits are cleared, SW will configure + * them instead. + */ + ret_val = e1000_write_smbus_addr(hw); + if (ret_val) +- goto out; ++ goto release; + + data = er32(LEDCTL); + ret_val = e1000_write_phy_reg_hv_locked(hw, HV_LED_CONFIG, + (u16)data); + if (ret_val) +- goto out; ++ goto release; + } + + /* Configure LCD from extended configuration region. */ +@@ -1112,15 +1626,14 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) + word_addr = (u16)(cnf_base_addr << 1); + + for (i = 0; i < cnf_size; i++) { +- ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1, +- ®_data); ++ ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1, ®_data); + if (ret_val) +- goto out; ++ goto release; + + ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1), + 1, ®_addr); + if (ret_val) +- goto out; ++ goto release; + + /* Save off the PHY page for future writes. */ + if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { +@@ -1131,13 +1644,12 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) + reg_addr &= PHY_REG_MASK; + reg_addr |= phy_page; + +- ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr, +- reg_data); ++ ret_val = e1e_wphy_locked(hw, (u32)reg_addr, reg_data); + if (ret_val) +- goto out; ++ goto release; + } + +-out: ++release: + hw->phy.ops.release(hw); + return ret_val; + } +@@ -1159,57 +1671,54 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) + bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled; + + if (hw->mac.type != e1000_pchlan) +- goto out; ++ return 0; + + /* Wrap the whole flow with the sw flag */ + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) +- goto out; ++ return ret_val; + + /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */ + if (link) { + if (hw->phy.type == e1000_phy_82578) { +- ret_val = hw->phy.ops.read_reg_locked(hw, BM_CS_STATUS, +- &status_reg); ++ ret_val = e1e_rphy_locked(hw, BM_CS_STATUS, ++ &status_reg); + if (ret_val) + goto release; + +- status_reg &= BM_CS_STATUS_LINK_UP | +- BM_CS_STATUS_RESOLVED | +- BM_CS_STATUS_SPEED_MASK; ++ status_reg &= (BM_CS_STATUS_LINK_UP | ++ BM_CS_STATUS_RESOLVED | ++ BM_CS_STATUS_SPEED_MASK); + + if (status_reg == (BM_CS_STATUS_LINK_UP | +- BM_CS_STATUS_RESOLVED | +- BM_CS_STATUS_SPEED_1000)) ++ BM_CS_STATUS_RESOLVED | ++ BM_CS_STATUS_SPEED_1000)) + k1_enable = false; + } + + if (hw->phy.type == e1000_phy_82577) { +- ret_val = hw->phy.ops.read_reg_locked(hw, HV_M_STATUS, +- &status_reg); ++ ret_val = e1e_rphy_locked(hw, HV_M_STATUS, &status_reg); + if (ret_val) + goto release; + +- status_reg &= HV_M_STATUS_LINK_UP | +- HV_M_STATUS_AUTONEG_COMPLETE | +- HV_M_STATUS_SPEED_MASK; ++ status_reg &= (HV_M_STATUS_LINK_UP | ++ HV_M_STATUS_AUTONEG_COMPLETE | ++ HV_M_STATUS_SPEED_MASK); + + if (status_reg == (HV_M_STATUS_LINK_UP | +- HV_M_STATUS_AUTONEG_COMPLETE | +- HV_M_STATUS_SPEED_1000)) ++ HV_M_STATUS_AUTONEG_COMPLETE | ++ HV_M_STATUS_SPEED_1000)) + k1_enable = false; + } + + /* Link stall fix for link up */ +- ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19), +- 0x0100); ++ ret_val = e1e_wphy_locked(hw, PHY_REG(770, 19), 0x0100); + if (ret_val) + goto release; + + } else { + /* Link stall fix for link down */ +- ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19), +- 0x4100); ++ ret_val = e1e_wphy_locked(hw, PHY_REG(770, 19), 0x4100); + if (ret_val) + goto release; + } +@@ -1218,7 +1727,7 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) + + release: + hw->phy.ops.release(hw); +-out: ++ + return ret_val; + } + +@@ -1234,30 +1743,28 @@ out: + **/ + s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) + { +- s32 ret_val = 0; ++ s32 ret_val; + u32 ctrl_reg = 0; + u32 ctrl_ext = 0; + u32 reg = 0; + u16 kmrn_reg = 0; + +- ret_val = e1000e_read_kmrn_reg_locked(hw, +- E1000_KMRNCTRLSTA_K1_CONFIG, +- &kmrn_reg); ++ ret_val = e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, ++ &kmrn_reg); + if (ret_val) +- goto out; ++ return ret_val; + + if (k1_enable) + kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE; + else + kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE; + +- ret_val = e1000e_write_kmrn_reg_locked(hw, +- E1000_KMRNCTRLSTA_K1_CONFIG, +- kmrn_reg); ++ ret_val = e1000e_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, ++ kmrn_reg); + if (ret_val) +- goto out; ++ return ret_val; + +- udelay(20); ++ usleep_range(20, 40); + ctrl_ext = er32(CTRL_EXT); + ctrl_reg = er32(CTRL); + +@@ -1267,14 +1774,13 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) + + ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS); + e1e_flush(); +- udelay(20); ++ usleep_range(20, 40); + ew32(CTRL, ctrl_reg); + ew32(CTRL_EXT, ctrl_ext); + e1e_flush(); +- udelay(20); ++ usleep_range(20, 40); + +-out: +- return ret_val; ++ return 0; + } + + /** +@@ -1292,28 +1798,28 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) + u32 mac_reg; + u16 oem_reg; + +- if ((hw->mac.type != e1000_pch2lan) && (hw->mac.type != e1000_pchlan)) ++ if (hw->mac.type < e1000_pchlan) + return ret_val; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + +- if (!(hw->mac.type == e1000_pch2lan)) { ++ if (hw->mac.type == e1000_pchlan) { + mac_reg = er32(EXTCNF_CTRL); + if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) +- goto out; ++ goto release; + } + + mac_reg = er32(FEXTNVM); + if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M)) +- goto out; ++ goto release; + + mac_reg = er32(PHY_CTRL); + +- ret_val = hw->phy.ops.read_reg_locked(hw, HV_OEM_BITS, &oem_reg); ++ ret_val = e1e_rphy_locked(hw, HV_OEM_BITS, &oem_reg); + if (ret_val) +- goto out; ++ goto release; + + oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU); + +@@ -1323,10 +1829,6 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) + + if (mac_reg & E1000_PHY_CTRL_D0A_LPLU) + oem_reg |= HV_OEM_BITS_LPLU; +- +- /* Set Restart auto-neg to activate the bits */ +- if (!e1000_check_reset_block(hw)) +- oem_reg |= HV_OEM_BITS_RESTART_AN; + } else { + if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE | + E1000_PHY_CTRL_NOND0A_GBE_DISABLE)) +@@ -1337,15 +1839,19 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) + oem_reg |= HV_OEM_BITS_LPLU; + } + +- ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg); ++ /* Set Restart auto-neg to activate the bits */ ++ if ((d0_state || (hw->mac.type != e1000_pchlan)) && ++ !hw->phy.ops.check_reset_block(hw)) ++ oem_reg |= HV_OEM_BITS_RESTART_AN; + +-out: ++ ret_val = e1e_wphy_locked(hw, HV_OEM_BITS, oem_reg); ++ ++release: + hw->phy.ops.release(hw); + + return ret_val; + } + +- + /** + * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode + * @hw: pointer to the HW structure +@@ -1376,13 +1882,13 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) + u16 phy_data; + + if (hw->mac.type != e1000_pchlan) +- return ret_val; ++ return 0; + + /* Set MDIO slow mode before any other MDIO access */ + if (hw->phy.type == e1000_phy_82577) { + ret_val = e1000_set_mdio_slow_mode_hv(hw); + if (ret_val) +- goto out; ++ return ret_val; + } + + if (((hw->phy.type == e1000_phy_82577) && +@@ -1400,13 +1906,12 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) + } + + if (hw->phy.type == e1000_phy_82578) { +- /* +- * Return registers to default by doing a soft reset then ++ /* Return registers to default by doing a soft reset then + * writing 0x3140 to the control register. + */ + if (hw->phy.revision < 2) { + e1000e_phy_sw_reset(hw); +- ret_val = e1e_wphy(hw, PHY_CONTROL, 0x3140); ++ ret_val = e1e_wphy(hw, MII_BMCR, 0x3140); + } + } + +@@ -1419,28 +1924,31 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) + ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); + hw->phy.ops.release(hw); + if (ret_val) +- goto out; ++ return ret_val; + +- /* +- * Configure the K1 Si workaround during phy reset assuming there is ++ /* Configure the K1 Si workaround during phy reset assuming there is + * link so that it disables K1 if link is in 1Gbps. + */ + ret_val = e1000_k1_gig_workaround_hv(hw, true); + if (ret_val) +- goto out; ++ return ret_val; + + /* Workaround for link disconnects on a busy hub in half duplex */ + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) +- goto out; +- ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data); ++ return ret_val; ++ ret_val = e1e_rphy_locked(hw, BM_PORT_GEN_CFG, &phy_data); ++ if (ret_val) ++ goto release; ++ ret_val = e1e_wphy_locked(hw, BM_PORT_GEN_CFG, phy_data & 0x00FF); + if (ret_val) + goto release; +- ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG, +- phy_data & 0x00FF); ++ ++ /* set MSE higher to enable link to stay up when noise is high */ ++ ret_val = e1000_write_emi_reg_locked(hw, I82577_MSE_THRESHOLD, 0x0034); + release: + hw->phy.ops.release(hw); +-out: ++ + return ret_val; + } + +@@ -1461,8 +1969,8 @@ void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw) + if (ret_val) + goto release; + +- /* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */ +- for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { ++ /* Copy both RAL/H (rar_entry_count) and SHRAL/H to PHY */ ++ for (i = 0; i < (hw->mac.rar_entry_count); i++) { + mac_reg = er32(RAL(i)); + hw->phy.ops.write_reg_page(hw, BM_RAR_L(i), + (u16)(mac_reg & 0xFFFF)); +@@ -1496,22 +2004,21 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) + u32 mac_reg; + u16 i; + +- if (hw->mac.type != e1000_pch2lan) +- goto out; ++ if (hw->mac.type < e1000_pch2lan) ++ return 0; + + /* disable Rx path while enabling/disabling workaround */ + e1e_rphy(hw, PHY_REG(769, 20), &phy_reg); + ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg | (1 << 14)); + if (ret_val) +- goto out; ++ return ret_val; + + if (enable) { +- /* +- * Write Rx addresses (rar_entry_count for RAL/H, +4 for ++ /* Write Rx addresses (rar_entry_count for RAL/H, and + * SHRAL/H) and initial CRC values to the MAC + */ +- for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { +- u8 mac_addr[ETH_ALEN] = {0}; ++ for (i = 0; i < hw->mac.rar_entry_count; i++) { ++ u8 mac_addr[ETH_ALEN] = { 0 }; + u32 addr_high, addr_low; + + addr_high = er32(RAH(i)); +@@ -1542,27 +2049,27 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) + ew32(RCTL, mac_reg); + + ret_val = e1000e_read_kmrn_reg(hw, +- E1000_KMRNCTRLSTA_CTRL_OFFSET, +- &data); ++ E1000_KMRNCTRLSTA_CTRL_OFFSET, ++ &data); + if (ret_val) +- goto out; ++ return ret_val; + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_CTRL_OFFSET, + data | (1 << 0)); + if (ret_val) +- goto out; ++ return ret_val; + ret_val = e1000e_read_kmrn_reg(hw, +- E1000_KMRNCTRLSTA_HD_CTRL, +- &data); ++ E1000_KMRNCTRLSTA_HD_CTRL, ++ &data); + if (ret_val) +- goto out; ++ return ret_val; + data &= ~(0xF << 8); + data |= (0xB << 8); + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_HD_CTRL, + data); + if (ret_val) +- goto out; ++ return ret_val; + + /* Enable jumbo frame workaround in the PHY */ + e1e_rphy(hw, PHY_REG(769, 23), &data); +@@ -1570,25 +2077,25 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) + data |= (0x37 << 5); + ret_val = e1e_wphy(hw, PHY_REG(769, 23), data); + if (ret_val) +- goto out; ++ return ret_val; + e1e_rphy(hw, PHY_REG(769, 16), &data); + data &= ~(1 << 13); + ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); + if (ret_val) +- goto out; ++ return ret_val; + e1e_rphy(hw, PHY_REG(776, 20), &data); + data &= ~(0x3FF << 2); + data |= (0x1A << 2); + ret_val = e1e_wphy(hw, PHY_REG(776, 20), data); + if (ret_val) +- goto out; ++ return ret_val; + ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0xF100); + if (ret_val) +- goto out; ++ return ret_val; + e1e_rphy(hw, HV_PM_CTRL, &data); + ret_val = e1e_wphy(hw, HV_PM_CTRL, data | (1 << 10)); + if (ret_val) +- goto out; ++ return ret_val; + } else { + /* Write MAC register values back to h/w defaults */ + mac_reg = er32(FFLT_DBG); +@@ -1600,59 +2107,56 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) + ew32(RCTL, mac_reg); + + ret_val = e1000e_read_kmrn_reg(hw, +- E1000_KMRNCTRLSTA_CTRL_OFFSET, +- &data); ++ E1000_KMRNCTRLSTA_CTRL_OFFSET, ++ &data); + if (ret_val) +- goto out; ++ return ret_val; + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_CTRL_OFFSET, + data & ~(1 << 0)); + if (ret_val) +- goto out; ++ return ret_val; + ret_val = e1000e_read_kmrn_reg(hw, +- E1000_KMRNCTRLSTA_HD_CTRL, +- &data); ++ E1000_KMRNCTRLSTA_HD_CTRL, ++ &data); + if (ret_val) +- goto out; ++ return ret_val; + data &= ~(0xF << 8); + data |= (0xB << 8); + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_HD_CTRL, + data); + if (ret_val) +- goto out; ++ return ret_val; + + /* Write PHY register values back to h/w defaults */ + e1e_rphy(hw, PHY_REG(769, 23), &data); + data &= ~(0x7F << 5); + ret_val = e1e_wphy(hw, PHY_REG(769, 23), data); + if (ret_val) +- goto out; ++ return ret_val; + e1e_rphy(hw, PHY_REG(769, 16), &data); + data |= (1 << 13); + ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); + if (ret_val) +- goto out; ++ return ret_val; + e1e_rphy(hw, PHY_REG(776, 20), &data); + data &= ~(0x3FF << 2); + data |= (0x8 << 2); + ret_val = e1e_wphy(hw, PHY_REG(776, 20), data); + if (ret_val) +- goto out; ++ return ret_val; + ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0x7E00); + if (ret_val) +- goto out; ++ return ret_val; + e1e_rphy(hw, HV_PM_CTRL, &data); + ret_val = e1e_wphy(hw, HV_PM_CTRL, data & ~(1 << 10)); + if (ret_val) +- goto out; ++ return ret_val; + } + + /* re-enable Rx path after enabling/disabling workaround */ +- ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14)); +- +-out: +- return ret_val; ++ return e1e_wphy(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14)); + } + + /** +@@ -1664,12 +2168,25 @@ static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw) + s32 ret_val = 0; + + if (hw->mac.type != e1000_pch2lan) +- goto out; ++ return 0; + + /* Set MDIO slow mode before any other MDIO access */ + ret_val = e1000_set_mdio_slow_mode_hv(hw); ++ if (ret_val) ++ return ret_val; ++ ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ return ret_val; ++ /* set MSE higher to enable link to stay up when noise is high */ ++ ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_THRESHOLD, 0x0034); ++ if (ret_val) ++ goto release; ++ /* drop link after 5 times MSE threshold was reached */ ++ ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_LINK_DOWN, 0x0005); ++release: ++ hw->phy.ops.release(hw); + +-out: + return ret_val; + } + +@@ -1687,12 +2204,12 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) + u16 phy_reg; + + if (hw->mac.type != e1000_pch2lan) +- goto out; ++ return 0; + + /* Set K1 beacon duration based on 1Gbps speed or otherwise */ + ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg); + if (ret_val) +- goto out; ++ return ret_val; + + if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) + == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) { +@@ -1701,11 +2218,21 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) + + ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg); + if (ret_val) +- goto out; ++ return ret_val; + + if (status_reg & HV_M_STATUS_SPEED_1000) { ++ u16 pm_phy_reg; ++ + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; + phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; ++ /* LV 1G Packet drop issue wa */ ++ ret_val = e1e_rphy(hw, HV_PM_CTRL, &pm_phy_reg); ++ if (ret_val) ++ return ret_val; ++ pm_phy_reg &= ~HV_PM_CTRL_PLL_STOP_IN_K1_GIGA; ++ ret_val = e1e_wphy(hw, HV_PM_CTRL, pm_phy_reg); ++ if (ret_val) ++ return ret_val; + } else { + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; + phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; +@@ -1714,7 +2241,6 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) + ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg); + } + +-out: + return ret_val; + } + +@@ -1730,7 +2256,7 @@ static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate) + { + u32 extcnf_ctrl; + +- if (hw->mac.type != e1000_pch2lan) ++ if (hw->mac.type < e1000_pch2lan) + return; + + extcnf_ctrl = er32(EXTCNF_CTRL); +@@ -1741,7 +2267,6 @@ static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate) + extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG; + + ew32(EXTCNF_CTRL, extcnf_ctrl); +- return; + } + + /** +@@ -1759,11 +2284,10 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) + do { + data = er32(STATUS); + data &= E1000_STATUS_LAN_INIT_DONE; +- udelay(100); ++ usleep_range(100, 200); + } while ((!data) && --loop); + +- /* +- * If basic configuration is incomplete before the above loop ++ /* If basic configuration is incomplete before the above loop + * count reaches 0, loading the configuration from NVM will + * leave the PHY in a bad state possibly resulting in no link. + */ +@@ -1785,8 +2309,8 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) + s32 ret_val = 0; + u16 reg; + +- if (e1000_check_reset_block(hw)) +- goto out; ++ if (hw->phy.ops.check_reset_block(hw)) ++ return 0; + + /* Allow time for h/w to get to quiescent state after reset */ + usleep_range(10000, 20000); +@@ -1796,12 +2320,12 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) + case e1000_pchlan: + ret_val = e1000_hv_phy_workarounds_ich8lan(hw); + if (ret_val) +- goto out; ++ return ret_val; + break; + case e1000_pch2lan: + ret_val = e1000_lv_phy_workarounds_ich8lan(hw); + if (ret_val) +- goto out; ++ return ret_val; + break; + default: + break; +@@ -1817,7 +2341,7 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) + /* Configure the LCD with the extended configuration region in NVM */ + ret_val = e1000_sw_lcd_config_ich8lan(hw); + if (ret_val) +- goto out; ++ return ret_val; + + /* Configure the LCD with the OEM bits in NVM */ + ret_val = e1000_oem_bits_config_ich8lan(hw, true); +@@ -1832,18 +2356,13 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) + /* Set EEE LPI Update Timer to 200usec */ + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) +- goto out; +- ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR, +- I82579_LPI_UPDATE_TIMER); +- if (ret_val) +- goto release; +- ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, +- 0x1387); +-release: ++ return ret_val; ++ ret_val = e1000_write_emi_reg_locked(hw, ++ I82579_LPI_UPDATE_TIMER, ++ 0x1387); + hw->phy.ops.release(hw); + } + +-out: + return ret_val; + } + +@@ -1866,12 +2385,9 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) + + ret_val = e1000e_phy_hw_reset_generic(hw); + if (ret_val) +- goto out; +- +- ret_val = e1000_post_phy_reset_ich8lan(hw); ++ return ret_val; + +-out: +- return ret_val; ++ return e1000_post_phy_reset_ich8lan(hw); + } + + /** +@@ -1887,23 +2403,22 @@ out: + **/ + static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active) + { +- s32 ret_val = 0; ++ s32 ret_val; + u16 oem_reg; + + ret_val = e1e_rphy(hw, HV_OEM_BITS, &oem_reg); + if (ret_val) +- goto out; ++ return ret_val; + + if (active) + oem_reg |= HV_OEM_BITS_LPLU; + else + oem_reg &= ~HV_OEM_BITS_LPLU; + +- oem_reg |= HV_OEM_BITS_RESTART_AN; +- ret_val = e1e_wphy(hw, HV_OEM_BITS, oem_reg); ++ if (!hw->phy.ops.check_reset_block(hw)) ++ oem_reg |= HV_OEM_BITS_RESTART_AN; + +-out: +- return ret_val; ++ return e1e_wphy(hw, HV_OEM_BITS, oem_reg); + } + + /** +@@ -1927,7 +2442,7 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) + u16 data; + + if (phy->type == e1000_phy_ife) +- return ret_val; ++ return 0; + + phy_ctrl = er32(PHY_CTRL); + +@@ -1938,8 +2453,7 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) + if (phy->type != e1000_phy_igp_3) + return 0; + +- /* +- * Call gig speed drop workaround on LPLU before accessing ++ /* Call gig speed drop workaround on LPLU before accessing + * any PHY registers + */ + if (hw->mac.type == e1000_ich8lan) +@@ -1947,6 +2461,8 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) + + /* When LPLU is enabled, we should disable SmartSpeed */ + ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data); ++ if (ret_val) ++ return ret_val; + data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data); + if (ret_val) +@@ -1958,8 +2474,7 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) + if (phy->type != e1000_phy_igp_3) + return 0; + +- /* +- * LPLU and SmartSpeed are mutually exclusive. LPLU is used ++ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used + * during Dx states where the power conservation is most + * important. During driver activity we should enable + * SmartSpeed, so performance is maintained. +@@ -2009,7 +2524,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) + { + struct e1000_phy_info *phy = &hw->phy; + u32 phy_ctrl; +- s32 ret_val; ++ s32 ret_val = 0; + u16 data; + + phy_ctrl = er32(PHY_CTRL); +@@ -2021,8 +2536,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) + if (phy->type != e1000_phy_igp_3) + return 0; + +- /* +- * LPLU and SmartSpeed are mutually exclusive. LPLU is used ++ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used + * during Dx states where the power conservation is most + * important. During driver activity we should enable + * SmartSpeed, so performance is maintained. +@@ -2059,8 +2573,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) + if (phy->type != e1000_phy_igp_3) + return 0; + +- /* +- * Call gig speed drop workaround on LPLU before accessing ++ /* Call gig speed drop workaround on LPLU before accessing + * any PHY registers + */ + if (hw->mac.type == e1000_ich8lan) +@@ -2075,7 +2588,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) + ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data); + } + +- return 0; ++ return ret_val; + } + + /** +@@ -2093,7 +2606,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) + u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); + u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; + u8 sig_byte = 0; +- s32 ret_val = 0; ++ s32 ret_val; + + switch (hw->mac.type) { + case e1000_ich8lan: +@@ -2108,8 +2621,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) + + return 0; + } +- e_dbg("Unable to determine valid NVM bank via EEC - " +- "reading flash signature\n"); ++ e_dbg("Unable to determine valid NVM bank via EEC - reading flash signature\n"); + /* fall-thru */ + default: + /* set bank to 0 in case flash read fails */ +@@ -2117,7 +2629,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) + + /* Check bank 0 */ + ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset, +- &sig_byte); ++ &sig_byte); + if (ret_val) + return ret_val; + if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == +@@ -2128,8 +2640,8 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) + + /* Check bank 1 */ + ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset + +- bank1_offset, +- &sig_byte); ++ bank1_offset, ++ &sig_byte); + if (ret_val) + return ret_val; + if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == +@@ -2141,8 +2653,6 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) + e_dbg("ERROR: No valid NVM bank present\n"); + return -E1000_ERR_NVM; + } +- +- return 0; + } + + /** +@@ -2184,8 +2694,8 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, + + ret_val = 0; + for (i = 0; i < words; i++) { +- if (dev_spec->shadow_ram[offset+i].modified) { +- data[i] = dev_spec->shadow_ram[offset+i].value; ++ if (dev_spec->shadow_ram[offset + i].modified) { ++ data[i] = dev_spec->shadow_ram[offset + i].value; + } else { + ret_val = e1000_read_flash_word_ich8lan(hw, + act_offset + i, +@@ -2220,9 +2730,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) + hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); + + /* Check if the flash descriptor is valid */ +- if (hsfsts.hsf_status.fldesvalid == 0) { +- e_dbg("Flash descriptor invalid. " +- "SW Sequencing must be used.\n"); ++ if (!hsfsts.hsf_status.fldesvalid) { ++ e_dbg("Flash descriptor invalid. SW Sequencing must be used.\n"); + return -E1000_ERR_NVM; + } + +@@ -2232,8 +2741,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) + + ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); + +- /* +- * Either we should have a hardware SPI cycle in progress ++ /* Either we should have a hardware SPI cycle in progress + * bit to check against, in order to start a new cycle or + * FDONE bit should be changed in the hardware so that it + * is 1 after hardware reset, which can then be used as an +@@ -2241,9 +2749,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) + * completed. + */ + +- if (hsfsts.hsf_status.flcinprog == 0) { +- /* +- * There is no cycle running at present, ++ if (!hsfsts.hsf_status.flcinprog) { ++ /* There is no cycle running at present, + * so we can start a cycle. + * Begin by setting Flash Cycle Done. + */ +@@ -2251,23 +2758,21 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) + ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); + ret_val = 0; + } else { +- s32 i = 0; ++ s32 i; + +- /* +- * Otherwise poll for sometime so the current ++ /* Otherwise poll for sometime so the current + * cycle has a chance to end before giving up. + */ + for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) { +- hsfsts.regval = __er16flash(hw, ICH_FLASH_HSFSTS); +- if (hsfsts.hsf_status.flcinprog == 0) { ++ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); ++ if (!hsfsts.hsf_status.flcinprog) { + ret_val = 0; + break; + } + udelay(1); + } +- if (ret_val == 0) { +- /* +- * Successful in waiting for previous cycle to timeout, ++ if (!ret_val) { ++ /* Successful in waiting for previous cycle to timeout, + * now set the Flash Cycle Done. + */ + hsfsts.hsf_status.flcdone = 1; +@@ -2291,7 +2796,6 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) + { + union ich8_hws_flash_ctrl hsflctl; + union ich8_hws_flash_status hsfsts; +- s32 ret_val = -E1000_ERR_NVM; + u32 i = 0; + + /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ +@@ -2302,15 +2806,15 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) + /* wait till FDONE bit is set to 1 */ + do { + hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); +- if (hsfsts.hsf_status.flcdone == 1) ++ if (hsfsts.hsf_status.flcdone) + break; + udelay(1); + } while (i++ < timeout); + +- if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0) ++ if (hsfsts.hsf_status.flcdone && !hsfsts.hsf_status.flcerr) + return 0; + +- return ret_val; ++ return -E1000_ERR_NVM; + } + + /** +@@ -2373,17 +2877,17 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, + s32 ret_val = -E1000_ERR_NVM; + u8 count = 0; + +- if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) ++ if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) + return -E1000_ERR_NVM; + +- flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + +- hw->nvm.flash_base_addr; ++ flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + ++ hw->nvm.flash_base_addr); + + do { + udelay(1); + /* Steps */ + ret_val = e1000_flash_cycle_init_ich8lan(hw); +- if (ret_val != 0) ++ if (ret_val) + break; + + hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); +@@ -2394,16 +2898,16 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, + + ew32flash(ICH_FLASH_FADDR, flash_linear_addr); + +- ret_val = e1000_flash_cycle_ich8lan(hw, +- ICH_FLASH_READ_COMMAND_TIMEOUT); ++ ret_val = ++ e1000_flash_cycle_ich8lan(hw, ++ ICH_FLASH_READ_COMMAND_TIMEOUT); + +- /* +- * Check if FCERR is set to 1, if set to 1, clear it ++ /* Check if FCERR is set to 1, if set to 1, clear it + * and try the whole sequence a few more times, else + * read in (shift in) the Flash Data0, the order is + * least significant byte first msb to lsb + */ +- if (ret_val == 0) { ++ if (!ret_val) { + flash_data = er32flash(ICH_FLASH_FDATA0); + if (size == 1) + *data = (u8)(flash_data & 0x000000FF); +@@ -2411,19 +2915,17 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, + *data = (u16)(flash_data & 0x0000FFFF); + break; + } else { +- /* +- * If we've gotten here, then things are probably ++ /* If we've gotten here, then things are probably + * completely hosed, but if the error condition is + * detected, it won't hurt to give it another try... + * ICH_FLASH_CYCLE_REPEAT_COUNT times. + */ + hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); +- if (hsfsts.hsf_status.flcerr == 1) { ++ if (hsfsts.hsf_status.flcerr) { + /* Repeat for some time before giving up. */ + continue; +- } else if (hsfsts.hsf_status.flcdone == 0) { +- e_dbg("Timeout error - flash cycle " +- "did not complete.\n"); ++ } else if (!hsfsts.hsf_status.flcdone) { ++ e_dbg("Timeout error - flash cycle did not complete.\n"); + break; + } + } +@@ -2457,8 +2959,8 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, + nvm->ops.acquire(hw); + + for (i = 0; i < words; i++) { +- dev_spec->shadow_ram[offset+i].modified = true; +- dev_spec->shadow_ram[offset+i].value = data[i]; ++ dev_spec->shadow_ram[offset + i].modified = true; ++ dev_spec->shadow_ram[offset + i].value = data[i]; + } + + nvm->ops.release(hw); +@@ -2494,12 +2996,11 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) + + nvm->ops.acquire(hw); + +- /* +- * We're writing to the opposite bank so if we're on bank 1, ++ /* We're writing to the opposite bank so if we're on bank 1, + * write to bank 0 etc. We also need to erase the segment that + * is going to be written + */ +- ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); ++ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); + if (ret_val) { + e_dbg("Could not detect valid bank, assuming bank 0\n"); + bank = 0; +@@ -2520,8 +3021,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) + } + + for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) { +- /* +- * Determine whether to write the value stored ++ /* Determine whether to write the value stored + * in the other NVM bank or a modified value stored + * in the shadow RAM + */ +@@ -2529,14 +3029,13 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) + data = dev_spec->shadow_ram[i].value; + } else { + ret_val = e1000_read_flash_word_ich8lan(hw, i + +- old_bank_offset, +- &data); ++ old_bank_offset, ++ &data); + if (ret_val) + break; + } + +- /* +- * If the word is 0x13, then make sure the signature bits ++ /* If the word is 0x13, then make sure the signature bits + * (15:14) are 11b until the commit has completed. + * This will allow us to write 10b which indicates the + * signature is valid. We want to do this after the write +@@ -2549,7 +3048,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) + /* Convert offset to bytes. */ + act_offset = (i + new_bank_offset) << 1; + +- udelay(100); ++ usleep_range(100, 200); + /* Write the bytes to the new bank. */ + ret_val = e1000_retry_write_flash_byte_ich8lan(hw, + act_offset, +@@ -2557,16 +3056,15 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) + if (ret_val) + break; + +- udelay(100); ++ usleep_range(100, 200); + ret_val = e1000_retry_write_flash_byte_ich8lan(hw, +- act_offset + 1, +- (u8)(data >> 8)); ++ act_offset + 1, ++ (u8)(data >> 8)); + if (ret_val) + break; + } + +- /* +- * Don't bother writing the segment valid bits if sector ++ /* Don't bother writing the segment valid bits if sector + * programming failed. + */ + if (ret_val) { +@@ -2575,8 +3073,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) + goto release; + } + +- /* +- * Finally validate the new segment by setting bit 15:14 ++ /* Finally validate the new segment by setting bit 15:14 + * to 10b in word 0x13 , this can be done without an + * erase as well since these bits are 11 to start with + * and we need to change bit 14 to 0b +@@ -2593,8 +3090,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) + if (ret_val) + goto release; + +- /* +- * And invalidate the previously valid segment by setting ++ /* And invalidate the previously valid segment by setting + * its signature word (0x13) high_byte to 0b. This can be + * done without an erase because flash erase sets all bits + * to 1's. We can write 1's to 0's without an erase +@@ -2613,12 +3109,11 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) + release: + nvm->ops.release(hw); + +- /* +- * Reload the EEPROM, or else modifications will not appear ++ /* Reload the EEPROM, or else modifications will not appear + * until after the next adapter reset. + */ + if (!ret_val) { +- e1000e_reload_nvm(hw); ++ nvm->ops.reload(hw); + usleep_range(10000, 20000); + } + +@@ -2641,20 +3136,32 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) + { + s32 ret_val; + u16 data; ++ u16 word; ++ u16 valid_csum_mask; + +- /* +- * Read 0x19 and check bit 6. If this bit is 0, the checksum +- * needs to be fixed. This bit is an indication that the NVM +- * was prepared by OEM software and did not calculate the +- * checksum...a likely scenario. ++ /* Read NVM and check Invalid Image CSUM bit. If this bit is 0, ++ * the checksum needs to be fixed. This bit is an indication that ++ * the NVM was prepared by OEM software and did not calculate ++ * the checksum...a likely scenario. + */ +- ret_val = e1000_read_nvm(hw, 0x19, 1, &data); ++ switch (hw->mac.type) { ++ case e1000_pch_lpt: ++ word = NVM_COMPAT; ++ valid_csum_mask = NVM_COMPAT_VALID_CSUM; ++ break; ++ default: ++ word = NVM_FUTURE_INIT_WORD1; ++ valid_csum_mask = NVM_FUTURE_INIT_WORD1_VALID_CSUM; ++ break; ++ } ++ ++ ret_val = e1000_read_nvm(hw, word, 1, &data); + if (ret_val) + return ret_val; + +- if ((data & 0x40) == 0) { +- data |= 0x40; +- ret_val = e1000_write_nvm(hw, 0x19, 1, &data); ++ if (!(data & valid_csum_mask)) { ++ data |= valid_csum_mask; ++ ret_val = e1000_write_nvm(hw, word, 1, &data); + if (ret_val) + return ret_val; + ret_val = e1000e_update_nvm_checksum(hw); +@@ -2693,8 +3200,7 @@ void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw) + pr0.range.wpe = true; + ew32flash(ICH_FLASH_PR0, pr0.regval); + +- /* +- * Lock down a subset of GbE Flash Control Registers, e.g. ++ /* Lock down a subset of GbE Flash Control Registers, e.g. + * PR0 to prevent the write-protection from being lifted. + * Once FLOCKDN is set, the registers protected by it cannot + * be written until FLOCKDN is cleared by a hardware reset. +@@ -2729,8 +3235,8 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, + offset > ICH_FLASH_LINEAR_ADDR_MASK) + return -E1000_ERR_NVM; + +- flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + +- hw->nvm.flash_base_addr; ++ flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + ++ hw->nvm.flash_base_addr); + + do { + udelay(1); +@@ -2741,7 +3247,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, + + hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); + /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ +- hsflctl.hsf_ctrl.fldbcount = size -1; ++ hsflctl.hsf_ctrl.fldbcount = size - 1; + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; + ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); + +@@ -2754,28 +3260,26 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, + + ew32flash(ICH_FLASH_FDATA0, flash_data); + +- /* +- * check if FCERR is set to 1 , if set to 1, clear it ++ /* check if FCERR is set to 1 , if set to 1, clear it + * and try the whole sequence a few more times else done + */ +- ret_val = e1000_flash_cycle_ich8lan(hw, +- ICH_FLASH_WRITE_COMMAND_TIMEOUT); ++ ret_val = ++ e1000_flash_cycle_ich8lan(hw, ++ ICH_FLASH_WRITE_COMMAND_TIMEOUT); + if (!ret_val) + break; + +- /* +- * If we're here, then things are most likely ++ /* If we're here, then things are most likely + * completely hosed, but if the error condition + * is detected, it won't hurt to give it another + * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. + */ + hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); +- if (hsfsts.hsf_status.flcerr == 1) ++ if (hsfsts.hsf_status.flcerr) + /* Repeat for some time before giving up. */ + continue; +- if (hsfsts.hsf_status.flcdone == 0) { +- e_dbg("Timeout error - flash cycle " +- "did not complete."); ++ if (!hsfsts.hsf_status.flcdone) { ++ e_dbg("Timeout error - flash cycle did not complete.\n"); + break; + } + } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); +@@ -2820,7 +3324,7 @@ static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, + + for (program_retries = 0; program_retries < 100; program_retries++) { + e_dbg("Retrying Byte %2.2X at offset %u\n", byte, offset); +- udelay(100); ++ usleep_range(100, 200); + ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); + if (!ret_val) + break; +@@ -2853,8 +3357,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) + + hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); + +- /* +- * Determine HW Sector size: Read BERASE bits of hw flash status ++ /* Determine HW Sector size: Read BERASE bits of hw flash status + * register + * 00: The Hw sector is 256 bytes, hence we need to erase 16 + * consecutive sectors. The start index for the nth Hw sector +@@ -2892,44 +3395,42 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) + flash_linear_addr = hw->nvm.flash_base_addr; + flash_linear_addr += (bank) ? flash_bank_size : 0; + +- for (j = 0; j < iteration ; j++) { ++ for (j = 0; j < iteration; j++) { + do { ++ u32 timeout = ICH_FLASH_ERASE_COMMAND_TIMEOUT; ++ + /* Steps */ + ret_val = e1000_flash_cycle_init_ich8lan(hw); + if (ret_val) + return ret_val; + +- /* +- * Write a value 11 (block Erase) in Flash ++ /* Write a value 11 (block Erase) in Flash + * Cycle field in hw flash control + */ + hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; + ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); + +- /* +- * Write the last 24 bits of an index within the ++ /* Write the last 24 bits of an index within the + * block into Flash Linear address field in Flash + * Address. + */ + flash_linear_addr += (j * sector_size); + ew32flash(ICH_FLASH_FADDR, flash_linear_addr); + +- ret_val = e1000_flash_cycle_ich8lan(hw, +- ICH_FLASH_ERASE_COMMAND_TIMEOUT); +- if (ret_val == 0) ++ ret_val = e1000_flash_cycle_ich8lan(hw, timeout); ++ if (!ret_val) + break; + +- /* +- * Check if FCERR is set to 1. If 1, ++ /* Check if FCERR is set to 1. If 1, + * clear it and try the whole sequence + * a few more times else Done + */ + hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); +- if (hsfsts.hsf_status.flcerr == 1) ++ if (hsfsts.hsf_status.flcerr) + /* repeat for some time before giving up */ + continue; +- else if (hsfsts.hsf_status.flcdone == 0) ++ else if (!hsfsts.hsf_status.flcdone) + return ret_val; + } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT); + } +@@ -2956,8 +3457,7 @@ static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data) + return ret_val; + } + +- if (*data == ID_LED_RESERVED_0000 || +- *data == ID_LED_RESERVED_FFFF) ++ if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) + *data = ID_LED_DEFAULT_ICH8LAN; + + return 0; +@@ -2972,7 +3472,7 @@ static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data) + * + * PCH also does not have an "always on" or "always off" mode which + * complicates the ID feature. Instead of using the "on" mode to indicate +- * in ledctl_mode2 the LEDs to use for ID (see e1000e_id_led_init()), ++ * in ledctl_mode2 the LEDs to use for ID (see e1000e_id_led_init_generic()), + * use "link_up" mode. The LEDs will still ID on request if there is no + * link based on logic in e1000_led_[on|off]_pchlan(). + **/ +@@ -2987,7 +3487,7 @@ static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw) + /* Get default ID LED modes */ + ret_val = hw->nvm.ops.valid_led_default(hw, &data); + if (ret_val) +- goto out; ++ return ret_val; + + mac->ledctl_default = er32(LEDCTL); + mac->ledctl_mode1 = mac->ledctl_default; +@@ -3032,8 +3532,7 @@ static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw) + } + } + +-out: +- return ret_val; ++ return 0; + } + + /** +@@ -3050,8 +3549,7 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) + + ret_val = e1000e_get_bus_info_pcie(hw); + +- /* +- * ICH devices are "PCI Express"-ish. They have ++ /* ICH devices are "PCI Express"-ish. They have + * a configuration space, but do not contain + * PCI Express Capability registers, so bus width + * must be hardcoded. +@@ -3072,12 +3570,11 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) + static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) + { + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; +- u16 reg; +- u32 ctrl, kab; ++ u16 kum_cfg; ++ u32 ctrl, reg; + s32 ret_val; + +- /* +- * Prevent the PCI-E bus from sticking if there is no TLP connection ++ /* Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ + ret_val = e1000e_disable_pcie_master(hw); +@@ -3087,8 +3584,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) + e_dbg("Masking off all interrupts\n"); + ew32(IMC, 0xffffffff); + +- /* +- * Disable the Transmit and Receive units. Then delay to allow ++ /* Disable the Transmit and Receive units. Then delay to allow + * any pending transactions to complete before we hit the MAC + * with the global reset. + */ +@@ -3107,12 +3603,12 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) + } + + if (hw->mac.type == e1000_pchlan) { +- /* Save the NVM K1 bit setting*/ +- ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, ®); ++ /* Save the NVM K1 bit setting */ ++ ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &kum_cfg); + if (ret_val) + return ret_val; + +- if (reg & E1000_NVM_K1_ENABLE) ++ if (kum_cfg & E1000_NVM_K1_ENABLE) + dev_spec->nvm_k1_enabled = true; + else + dev_spec->nvm_k1_enabled = false; +@@ -3120,16 +3616,14 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) + + ctrl = er32(CTRL); + +- if (!e1000_check_reset_block(hw)) { +- /* +- * Full-chip reset requires MAC and PHY reset at the same ++ if (!hw->phy.ops.check_reset_block(hw)) { ++ /* Full-chip reset requires MAC and PHY reset at the same + * time to make sure the interface between MAC and the + * external PHY is reset. + */ + ctrl |= E1000_CTRL_PHY_RST; + +- /* +- * Gate automatic PHY configuration by hardware on ++ /* Gate automatic PHY configuration by hardware on + * non-managed 82579 + */ + if ((hw->mac.type == e1000_pch2lan) && +@@ -3142,21 +3636,28 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) + /* cannot issue a flush here because it hangs the hardware */ + msleep(20); + ++ /* Set Phy Config Counter to 50msec */ ++ if (hw->mac.type == e1000_pch2lan) { ++ reg = er32(FEXTNVM3); ++ reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; ++ reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; ++ ew32(FEXTNVM3, reg); ++ } ++ + if (!ret_val) + clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state); + + if (ctrl & E1000_CTRL_PHY_RST) { + ret_val = hw->phy.ops.get_cfg_done(hw); + if (ret_val) +- goto out; ++ return ret_val; + + ret_val = e1000_post_phy_reset_ich8lan(hw); + if (ret_val) +- goto out; ++ return ret_val; + } + +- /* +- * For PCH, this write will make sure that any noise ++ /* For PCH, this write will make sure that any noise + * will be detected as a CRC error and be dropped rather than show up + * as a bad packet to the DMA engine. + */ +@@ -3166,12 +3667,11 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) + ew32(IMC, 0xffffffff); + er32(ICR); + +- kab = er32(KABGTXD); +- kab |= E1000_KABGTXD_BGSQLBIAS; +- ew32(KABGTXD, kab); ++ reg = er32(KABGTXD); ++ reg |= E1000_KABGTXD_BGSQLBIAS; ++ ew32(KABGTXD, reg); + +-out: +- return ret_val; ++ return 0; + } + + /** +@@ -3197,9 +3697,9 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) + + /* Initialize identification LED */ + ret_val = mac->ops.id_led_init(hw); ++ /* An error is not fatal and we should not stop init due to this */ + if (ret_val) + e_dbg("Error initializing identification LED\n"); +- /* This is not fatal and we should not stop init due to this */ + + /* Setup the receive address. */ + e1000e_init_rx_addrs(hw, mac->rar_entry_count); +@@ -3209,8 +3709,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) + for (i = 0; i < mac->mta_reg_count; i++) + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + +- /* +- * The 82578 Rx buffer will stall if wakeup is enabled in host and ++ /* The 82578 Rx buffer will stall if wakeup is enabled in host and + * the ME. Disable wakeup by clearing the host wakeup bit. + * Reset the phy after disabling host wakeup to reset the Rx buffer. + */ +@@ -3224,46 +3723,45 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) + } + + /* Setup link and flow control */ +- ret_val = e1000_setup_link_ich8lan(hw); ++ ret_val = mac->ops.setup_link(hw); + + /* Set the transmit descriptor write-back policy for both queues */ + txdctl = er32(TXDCTL(0)); +- txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | +- E1000_TXDCTL_FULL_TX_DESC_WB; +- txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) | +- E1000_TXDCTL_MAX_TX_DESC_PREFETCH; ++ txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) | ++ E1000_TXDCTL_FULL_TX_DESC_WB); ++ txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) | ++ E1000_TXDCTL_MAX_TX_DESC_PREFETCH); + ew32(TXDCTL(0), txdctl); + txdctl = er32(TXDCTL(1)); +- txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | +- E1000_TXDCTL_FULL_TX_DESC_WB; +- txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) | +- E1000_TXDCTL_MAX_TX_DESC_PREFETCH; ++ txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) | ++ E1000_TXDCTL_FULL_TX_DESC_WB); ++ txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) | ++ E1000_TXDCTL_MAX_TX_DESC_PREFETCH); + ew32(TXDCTL(1), txdctl); + +- /* +- * ICH8 has opposite polarity of no_snoop bits. ++ /* ICH8 has opposite polarity of no_snoop bits. + * By default, we should use snoop behavior. + */ + if (mac->type == e1000_ich8lan) + snoop = PCIE_ICH8_SNOOP_ALL; + else +- snoop = (u32) ~(PCIE_NO_SNOOP_ALL); ++ snoop = (u32)~(PCIE_NO_SNOOP_ALL); + e1000e_set_pcie_no_snoop(hw, snoop); + + ctrl_ext = er32(CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_RO_DIS; + ew32(CTRL_EXT, ctrl_ext); + +- /* +- * Clear all of the statistics registers (clear on read). It is ++ /* Clear all of the statistics registers (clear on read). It is + * important that we do this after we have tried to establish link + * because the symbol error count will increment wildly if there + * is no link. + */ + e1000_clear_hw_cntrs_ich8lan(hw); + +- return 0; ++ return ret_val; + } ++ + /** + * e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits + * @hw: pointer to the HW structure +@@ -3316,13 +3814,29 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) + ew32(STATUS, reg); + } + +- /* +- * work-around descriptor data corruption issue during nfs v2 udp ++ /* work-around descriptor data corruption issue during nfs v2 udp + * traffic, just disable the nfs filtering capability + */ + reg = er32(RFCTL); + reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS); ++ ++ /* Disable IPv6 extension header parsing because some malformed ++ * IPv6 headers can hang the Rx. ++ */ ++ if (hw->mac.type == e1000_ich8lan) ++ reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); + ew32(RFCTL, reg); ++ ++ /* Enable ECC on Lynxpoint */ ++ if (hw->mac.type == e1000_pch_lpt) { ++ reg = er32(PBECCSTS); ++ reg |= E1000_PBECCSTS_ECC_ENABLE; ++ ew32(PBECCSTS, reg); ++ ++ reg = er32(CTRL); ++ reg |= E1000_CTRL_MEHE; ++ ew32(CTRL, reg); ++ } + } + + /** +@@ -3339,11 +3853,10 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) + { + s32 ret_val; + +- if (e1000_check_reset_block(hw)) ++ if (hw->phy.ops.check_reset_block(hw)) + return 0; + +- /* +- * ICH parts do not have a word in the NVM to determine ++ /* ICH parts do not have a word in the NVM to determine + * the default flow control setting, so we explicitly + * set it to full. + */ +@@ -3355,23 +3868,22 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) + hw->fc.requested_mode = e1000_fc_full; + } + +- /* +- * Save off the requested flow control mode for use later. Depending ++ /* Save off the requested flow control mode for use later. Depending + * on the link partner's capabilities, we may or may not use this mode. + */ + hw->fc.current_mode = hw->fc.requested_mode; + +- e_dbg("After fix-ups FlowControl is now = %x\n", +- hw->fc.current_mode); ++ e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); + + /* Continue to configure the copper link. */ +- ret_val = e1000_setup_copper_link_ich8lan(hw); ++ ret_val = hw->mac.ops.setup_physical_interface(hw); + if (ret_val) + return ret_val; + + ew32(FCTTV, hw->fc.pause_time); + if ((hw->phy.type == e1000_phy_82578) || + (hw->phy.type == e1000_phy_82579) || ++ (hw->phy.type == e1000_phy_i217) || + (hw->phy.type == e1000_phy_82577)) { + ew32(FCRTV_PCH, hw->fc.refresh_time); + +@@ -3403,8 +3915,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); + ew32(CTRL, ctrl); + +- /* +- * Set the mac to wait the maximum time between each iteration ++ /* Set the mac to wait the maximum time between each iteration + * and increase the max iterations when polling the phy; + * this fixes erroneous timeouts at 10Mbps. + */ +@@ -3412,12 +3923,12 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) + if (ret_val) + return ret_val; + ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, +- ®_data); ++ ®_data); + if (ret_val) + return ret_val; + reg_data |= 0x3F; + ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, +- reg_data); ++ reg_data); + if (ret_val) + return ret_val; + +@@ -3465,6 +3976,32 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) + default: + break; + } ++ ++ return e1000e_setup_copper_link(hw); ++} ++ ++/** ++ * e1000_setup_copper_link_pch_lpt - Configure MAC/PHY interface ++ * @hw: pointer to the HW structure ++ * ++ * Calls the PHY specific link setup function and then calls the ++ * generic setup_copper_link to finish configuring the link for ++ * Lynxpoint PCH devices ++ **/ ++static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw) ++{ ++ u32 ctrl; ++ s32 ret_val; ++ ++ ctrl = er32(CTRL); ++ ctrl |= E1000_CTRL_SLU; ++ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); ++ ew32(CTRL, ctrl); ++ ++ ret_val = e1000_copper_link_setup_82577(hw); ++ if (ret_val) ++ return ret_val; ++ + return e1000e_setup_copper_link(hw); + } + +@@ -3488,8 +4025,7 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, + return ret_val; + + if ((hw->mac.type == e1000_ich8lan) && +- (hw->phy.type == e1000_phy_igp_3) && +- (*speed == SPEED_1000)) { ++ (hw->phy.type == e1000_phy_igp_3) && (*speed == SPEED_1000)) { + ret_val = e1000_kmrn_lock_loss_workaround_ich8lan(hw); + } + +@@ -3522,8 +4058,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) + if (!dev_spec->kmrn_lock_loss_workaround_enabled) + return 0; + +- /* +- * Make sure link is up before proceeding. If not just return. ++ /* Make sure link is up before proceeding. If not just return. + * Attempting this while link is negotiating fouled up link + * stability + */ +@@ -3555,8 +4090,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) + E1000_PHY_CTRL_NOND0A_GBE_DISABLE); + ew32(PHY_CTRL, phy_ctrl); + +- /* +- * Call gig speed drop workaround on Gig disable before accessing ++ /* Call gig speed drop workaround on Gig disable before accessing + * any PHY registers + */ + e1000e_gig_downshift_workaround_ich8lan(hw); +@@ -3566,7 +4100,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) + } + + /** +- * e1000_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state ++ * e1000e_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state + * @hw: pointer to the HW structure + * @state: boolean value used to set the current Kumeran workaround state + * +@@ -3574,7 +4108,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) + * /disabled - false). + **/ + void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, +- bool state) ++ bool state) + { + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; + +@@ -3600,7 +4134,7 @@ void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) + { + u32 reg; + u16 data; +- u8 retry = 0; ++ u8 retry = 0; + + if (hw->phy.type != e1000_phy_igp_3) + return; +@@ -3613,8 +4147,7 @@ void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) + E1000_PHY_CTRL_NOND0A_GBE_DISABLE); + ew32(PHY_CTRL, reg); + +- /* +- * Call gig speed drop workaround on Gig disable before ++ /* Call gig speed drop workaround on Gig disable before + * accessing any PHY registers + */ + if (hw->mac.type == e1000_ich8lan) +@@ -3657,17 +4190,16 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) + return; + + ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, +- ®_data); ++ ®_data); + if (ret_val) + return; + reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK; + ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, +- reg_data); ++ reg_data); + if (ret_val) + return; + reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK; +- ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, +- reg_data); ++ e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, reg_data); + } + + /** +@@ -3676,17 +4208,98 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) + * + * During S0 to Sx transition, it is possible the link remains at gig + * instead of negotiating to a lower speed. Before going to Sx, set +- * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation +- * to a lower speed. For PCH and newer parts, the OEM bits PHY register +- * (LED, GbE disable and LPLU configurations) also needs to be written. ++ * 'Gig Disable' to force link speed negotiation to a lower speed based on ++ * the LPLU setting in the NVM or custom setting. For PCH and newer parts, ++ * the OEM bits PHY register (LED, GbE disable and LPLU configurations) also ++ * needs to be written. ++ * Parts that support (and are linked to a partner which support) EEE in ++ * 100Mbps should disable LPLU since 100Mbps w/ EEE requires less power ++ * than 10Mbps w/o EEE. + **/ + void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) + { ++ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; + u32 phy_ctrl; + s32 ret_val; + + phy_ctrl = er32(PHY_CTRL); +- phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE; ++ phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE; ++ ++ if (hw->phy.type == e1000_phy_i217) { ++ u16 phy_reg, device_id = hw->adapter->pdev->device; ++ ++ if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) || ++ (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) || ++ (device_id == E1000_DEV_ID_PCH_I218_LM3) || ++ (device_id == E1000_DEV_ID_PCH_I218_V3)) { ++ u32 fextnvm6 = er32(FEXTNVM6); ++ ++ ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK); ++ } ++ ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ goto out; ++ ++ if (!dev_spec->eee_disable) { ++ u16 eee_advert; ++ ++ ret_val = ++ e1000_read_emi_reg_locked(hw, ++ I217_EEE_ADVERTISEMENT, ++ &eee_advert); ++ if (ret_val) ++ goto release; ++ ++ /* Disable LPLU if both link partners support 100BaseT ++ * EEE and 100Full is advertised on both ends of the ++ * link. ++ */ ++ if ((eee_advert & I82579_EEE_100_SUPPORTED) && ++ (dev_spec->eee_lp_ability & ++ I82579_EEE_100_SUPPORTED) && ++ (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)) ++ phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU | ++ E1000_PHY_CTRL_NOND0A_LPLU); ++ } ++ ++ /* For i217 Intel Rapid Start Technology support, ++ * when the system is going into Sx and no manageability engine ++ * is present, the driver must configure proxy to reset only on ++ * power good. LPI (Low Power Idle) state must also reset only ++ * on power good, as well as the MTA (Multicast table array). ++ * The SMBus release must also be disabled on LCD reset. ++ */ ++ if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { ++ /* Enable proxy to reset only on power good. */ ++ e1e_rphy_locked(hw, I217_PROXY_CTRL, &phy_reg); ++ phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE; ++ e1e_wphy_locked(hw, I217_PROXY_CTRL, phy_reg); ++ ++ /* Set bit enable LPI (EEE) to reset only on ++ * power good. ++ */ ++ e1e_rphy_locked(hw, I217_SxCTRL, &phy_reg); ++ phy_reg |= I217_SxCTRL_ENABLE_LPI_RESET; ++ e1e_wphy_locked(hw, I217_SxCTRL, phy_reg); ++ ++ /* Disable the SMB release on LCD reset. */ ++ e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg); ++ phy_reg &= ~I217_MEMPWR_DISABLE_SMB_RELEASE; ++ e1e_wphy_locked(hw, I217_MEMPWR, phy_reg); ++ } ++ ++ /* Enable MTA to reset for Intel Rapid Start Technology ++ * Support ++ */ ++ e1e_rphy_locked(hw, I217_CGFREG, &phy_reg); ++ phy_reg |= I217_CGFREG_ENABLE_MTA_RESET; ++ e1e_wphy_locked(hw, I217_CGFREG, phy_reg); ++ ++release: ++ hw->phy.ops.release(hw); ++ } ++out: + ew32(PHY_CTRL, phy_ctrl); + + if (hw->mac.type == e1000_ich8lan) +@@ -3694,7 +4307,11 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) + + if (hw->mac.type >= e1000_pchlan) { + e1000_oem_bits_config_ich8lan(hw, false); +- e1000_phy_hw_reset_ich8lan(hw); ++ ++ /* Reset PHY to activate OEM bits on 82577/8 */ ++ if (hw->mac.type == e1000_pchlan) ++ e1000e_phy_hw_reset_generic(hw); ++ + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return; +@@ -3711,50 +4328,59 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) + * on which PHY resets are not blocked, if the PHY registers cannot be + * accessed properly by the s/w toggle the LANPHYPC value to power cycle + * the PHY. ++ * On i217, setup Intel Rapid Start Technology. + **/ + void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) + { +- u32 fwsm; ++ s32 ret_val; + +- if (hw->mac.type != e1000_pch2lan) ++ if (hw->mac.type < e1000_pch2lan) + return; + +- fwsm = er32(FWSM); +- if (!(fwsm & E1000_ICH_FWSM_FW_VALID) || !e1000_check_reset_block(hw)) { +- u16 phy_id1, phy_id2; +- s32 ret_val; ++ ret_val = e1000_init_phy_workarounds_pchlan(hw); ++ if (ret_val) { ++ e_dbg("Failed to init PHY flow ret_val=%d\n", ret_val); ++ return; ++ } ++ ++ /* For i217 Intel Rapid Start Technology support when the system ++ * is transitioning from Sx and no manageability engine is present ++ * configure SMBus to restore on reset, disable proxy, and enable ++ * the reset on MTA (Multicast table array). ++ */ ++ if (hw->phy.type == e1000_phy_i217) { ++ u16 phy_reg; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) { +- e_dbg("Failed to acquire PHY semaphore in resume\n"); ++ e_dbg("Failed to setup iRST\n"); + return; + } + +- /* Test access to the PHY registers by reading the ID regs */ +- ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1); ++ if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { ++ /* Restore clear on SMB if no manageability engine ++ * is present ++ */ ++ ret_val = e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg); ++ if (ret_val) ++ goto release; ++ phy_reg |= I217_MEMPWR_DISABLE_SMB_RELEASE; ++ e1e_wphy_locked(hw, I217_MEMPWR, phy_reg); ++ ++ /* Disable Proxy */ ++ e1e_wphy_locked(hw, I217_PROXY_CTRL, 0); ++ } ++ /* Enable reset on MTA */ ++ ret_val = e1e_rphy_locked(hw, I217_CGFREG, &phy_reg); + if (ret_val) + goto release; +- ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2); ++ phy_reg &= ~I217_CGFREG_ENABLE_MTA_RESET; ++ e1e_wphy_locked(hw, I217_CGFREG, phy_reg); ++release: + if (ret_val) +- goto release; +- +- if (hw->phy.id == ((u32)(phy_id1 << 16) | +- (u32)(phy_id2 & PHY_REVISION_MASK))) +- goto release; +- +- e1000_toggle_lanphypc_value_ich8lan(hw); +- ++ e_dbg("Error %d in resume workarounds\n", ret_val); + hw->phy.ops.release(hw); +- msleep(50); +- e1000_phy_hw_reset(hw); +- msleep(50); +- return; + } +- +-release: +- hw->phy.ops.release(hw); +- +- return; + } + + /** +@@ -3838,8 +4464,7 @@ static s32 e1000_led_on_pchlan(struct e1000_hw *hw) + u16 data = (u16)hw->mac.ledctl_mode2; + u32 i, led; + +- /* +- * If no link, then turn LED on by setting the invert bit ++ /* If no link, then turn LED on by setting the invert bit + * for each LED that's mode is "link_up" in ledctl_mode2. + */ + if (!(er32(STATUS) & E1000_STATUS_LU)) { +@@ -3869,8 +4494,7 @@ static s32 e1000_led_off_pchlan(struct e1000_hw *hw) + u16 data = (u16)hw->mac.ledctl_mode1; + u32 i, led; + +- /* +- * If no link, then turn LED off by clearing the invert bit ++ /* If no link, then turn LED off by clearing the invert bit + * for each LED that's mode is "link_up" in ledctl_mode1. + */ + if (!(er32(STATUS) & E1000_STATUS_LU)) { +@@ -3907,7 +4531,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) + u32 bank = 0; + u32 status; + +- e1000e_get_cfg_done(hw); ++ e1000e_get_cfg_done_generic(hw); + + /* Wait for indication from h/w that it has completed basic config */ + if (hw->mac.type >= e1000_ich10lan) { +@@ -3915,8 +4539,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) + } else { + ret_val = e1000e_get_auto_rd_done(hw); + if (ret_val) { +- /* +- * When auto config read does not complete, do not ++ /* When auto config read does not complete, do not + * return with an error. This can happen in situations + * where there is no eeprom and prevents getting link. + */ +@@ -3934,7 +4557,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) + + /* If EEPROM is not marked present, init the IGP 3 PHY manually */ + if (hw->mac.type <= e1000_ich9lan) { +- if (((er32(EECD) & E1000_EECD_PRES) == 0) && ++ if (!(er32(EECD) & E1000_EECD_PRES) && + (hw->phy.type == e1000_phy_igp_3)) { + e1000e_phy_init_script_igp3(hw); + } +@@ -3995,6 +4618,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) + /* Clear PHY statistics registers */ + if ((hw->phy.type == e1000_phy_82578) || + (hw->phy.type == e1000_phy_82579) || ++ (hw->phy.type == e1000_phy_i217) || + (hw->phy.type == e1000_phy_82577)) { + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) +@@ -4023,7 +4647,6 @@ release: + } + + static const struct e1000_mac_operations ich8_mac_ops = { +- .id_led_init = e1000e_id_led_init, + /* check_mng_mode dependent on mac type */ + .check_for_link = e1000_check_for_copper_link_ich8lan, + /* cleanup_led dependent on mac type */ +@@ -4037,8 +4660,10 @@ static const struct e1000_mac_operations ich8_mac_ops = { + .reset_hw = e1000_reset_hw_ich8lan, + .init_hw = e1000_init_hw_ich8lan, + .setup_link = e1000_setup_link_ich8lan, +- .setup_physical_interface= e1000_setup_copper_link_ich8lan, ++ .setup_physical_interface = e1000_setup_copper_link_ich8lan, + /* id_led_init dependent on mac type */ ++ .config_collision_dist = e1000e_config_collision_dist_generic, ++ .rar_set = e1000e_rar_set_generic, + }; + + static const struct e1000_phy_operations ich8_phy_ops = { +@@ -4057,8 +4682,9 @@ static const struct e1000_phy_operations ich8_phy_ops = { + + static const struct e1000_nvm_operations ich8_nvm_ops = { + .acquire = e1000_acquire_nvm_ich8lan, +- .read = e1000_read_nvm_ich8lan, ++ .read = e1000_read_nvm_ich8lan, + .release = e1000_release_nvm_ich8lan, ++ .reload = e1000e_reload_nvm_generic, + .update = e1000_update_nvm_checksum_ich8lan, + .valid_led_default = e1000_valid_led_default_ich8lan, + .validate = e1000_validate_nvm_checksum_ich8lan, +@@ -4088,10 +4714,9 @@ const struct e1000_info e1000_ich9_info = { + | FLAG_HAS_WOL + | FLAG_HAS_CTRLEXT_ON_LOAD + | FLAG_HAS_AMT +- | FLAG_HAS_ERT + | FLAG_HAS_FLASH + | FLAG_APME_IN_WUC, +- .pba = 10, ++ .pba = 18, + .max_hw_frame_size = DEFAULT_JUMBO, + .get_variants = e1000_get_variants_ich8lan, + .mac_ops = &ich8_mac_ops, +@@ -4106,10 +4731,9 @@ const struct e1000_info e1000_ich10_info = { + | FLAG_HAS_WOL + | FLAG_HAS_CTRLEXT_ON_LOAD + | FLAG_HAS_AMT +- | FLAG_HAS_ERT + | FLAG_HAS_FLASH + | FLAG_APME_IN_WUC, +- .pba = 10, ++ .pba = 18, + .max_hw_frame_size = DEFAULT_JUMBO, + .get_variants = e1000_get_variants_ich8lan, + .mac_ops = &ich8_mac_ops, +@@ -4140,6 +4764,7 @@ const struct e1000_info e1000_pch2_info = { + .mac = e1000_pch2lan, + .flags = FLAG_IS_ICH + | FLAG_HAS_WOL ++ | FLAG_HAS_HW_TIMESTAMP + | FLAG_HAS_CTRLEXT_ON_LOAD + | FLAG_HAS_AMT + | FLAG_HAS_FLASH +@@ -4148,7 +4773,27 @@ const struct e1000_info e1000_pch2_info = { + .flags2 = FLAG2_HAS_PHY_STATS + | FLAG2_HAS_EEE, + .pba = 26, +- .max_hw_frame_size = DEFAULT_JUMBO, ++ .max_hw_frame_size = 9018, ++ .get_variants = e1000_get_variants_ich8lan, ++ .mac_ops = &ich8_mac_ops, ++ .phy_ops = &ich8_phy_ops, ++ .nvm_ops = &ich8_nvm_ops, ++}; ++ ++const struct e1000_info e1000_pch_lpt_info = { ++ .mac = e1000_pch_lpt, ++ .flags = FLAG_IS_ICH ++ | FLAG_HAS_WOL ++ | FLAG_HAS_HW_TIMESTAMP ++ | FLAG_HAS_CTRLEXT_ON_LOAD ++ | FLAG_HAS_AMT ++ | FLAG_HAS_FLASH ++ | FLAG_HAS_JUMBO_FRAMES ++ | FLAG_APME_IN_WUC, ++ .flags2 = FLAG2_HAS_PHY_STATS ++ | FLAG2_HAS_EEE, ++ .pba = 26, ++ .max_hw_frame_size = 9018, + .get_variants = e1000_get_variants_ich8lan, + .mac_ops = &ich8_mac_ops, + .phy_ops = &ich8_phy_ops, +diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h +new file mode 100644 +index 0000000..217090d +--- /dev/null ++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h +@@ -0,0 +1,271 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#ifndef _E1000E_ICH8LAN_H_ ++#define _E1000E_ICH8LAN_H_ ++ ++#define ICH_FLASH_GFPREG 0x0000 ++#define ICH_FLASH_HSFSTS 0x0004 ++#define ICH_FLASH_HSFCTL 0x0006 ++#define ICH_FLASH_FADDR 0x0008 ++#define ICH_FLASH_FDATA0 0x0010 ++#define ICH_FLASH_PR0 0x0074 ++ ++/* Requires up to 10 seconds when MNG might be accessing part. */ ++#define ICH_FLASH_READ_COMMAND_TIMEOUT 10000000 ++#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 10000000 ++#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 10000000 ++#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF ++#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 ++ ++#define ICH_CYCLE_READ 0 ++#define ICH_CYCLE_WRITE 2 ++#define ICH_CYCLE_ERASE 3 ++ ++#define FLASH_GFPREG_BASE_MASK 0x1FFF ++#define FLASH_SECTOR_ADDR_SHIFT 12 ++ ++#define ICH_FLASH_SEG_SIZE_256 256 ++#define ICH_FLASH_SEG_SIZE_4K 4096 ++#define ICH_FLASH_SEG_SIZE_8K 8192 ++#define ICH_FLASH_SEG_SIZE_64K 65536 ++ ++#define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */ ++/* FW established a valid mode */ ++#define E1000_ICH_FWSM_FW_VALID 0x00008000 ++#define E1000_ICH_FWSM_PCIM2PCI 0x01000000 /* ME PCIm-to-PCI active */ ++#define E1000_ICH_FWSM_PCIM2PCI_COUNT 2000 ++ ++#define E1000_ICH_MNG_IAMT_MODE 0x2 ++ ++#define E1000_FWSM_WLOCK_MAC_MASK 0x0380 ++#define E1000_FWSM_WLOCK_MAC_SHIFT 7 ++ ++/* Shared Receive Address Registers */ ++#define E1000_SHRAL_PCH_LPT(_i) (0x05408 + ((_i) * 8)) ++#define E1000_SHRAH_PCH_LPT(_i) (0x0540C + ((_i) * 8)) ++ ++#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \ ++ (ID_LED_OFF1_OFF2 << 8) | \ ++ (ID_LED_OFF1_ON2 << 4) | \ ++ (ID_LED_DEF1_DEF2)) ++ ++#define E1000_ICH_NVM_SIG_WORD 0x13 ++#define E1000_ICH_NVM_SIG_MASK 0xC000 ++#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0 ++#define E1000_ICH_NVM_SIG_VALUE 0x80 ++ ++#define E1000_ICH8_LAN_INIT_TIMEOUT 1500 ++ ++#define E1000_FEXTNVM_SW_CONFIG 1 ++#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* different on ICH8M */ ++ ++#define E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK 0x0C000000 ++#define E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC 0x08000000 ++ ++#define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7 ++#define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 ++#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 ++ ++#define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100 ++#define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION 0x00000200 ++ ++#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL ++ ++#define E1000_ICH_RAR_ENTRIES 7 ++#define E1000_PCH2_RAR_ENTRIES 11 /* RAR[0-6], SHRA[0-3] */ ++#define E1000_PCH_LPT_RAR_ENTRIES 12 /* RAR[0], SHRA[0-10] */ ++ ++#define PHY_PAGE_SHIFT 5 ++#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \ ++ ((reg) & MAX_PHY_REG_ADDRESS)) ++#define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */ ++#define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */ ++ ++#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 ++#define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300 ++#define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200 ++ ++/* PHY Wakeup Registers and defines */ ++#define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17) ++#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0) ++#define BM_WUC PHY_REG(BM_WUC_PAGE, 1) ++#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2) ++#define BM_WUS PHY_REG(BM_WUC_PAGE, 3) ++#define BM_RAR_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2))) ++#define BM_RAR_M(_i) (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2))) ++#define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2))) ++#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2))) ++#define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1))) ++ ++#define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */ ++#define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */ ++#define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */ ++#define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */ ++#define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */ ++#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */ ++#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */ ++ ++#define HV_LED_CONFIG PHY_REG(768, 30) /* LED Configuration */ ++#define HV_MUX_DATA_CTRL PHY_REG(776, 16) ++#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 ++#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 ++#define HV_STATS_PAGE 778 ++/* Half-duplex collision counts */ ++#define HV_SCC_UPPER PHY_REG(HV_STATS_PAGE, 16) /* Single Collision */ ++#define HV_SCC_LOWER PHY_REG(HV_STATS_PAGE, 17) ++#define HV_ECOL_UPPER PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. */ ++#define HV_ECOL_LOWER PHY_REG(HV_STATS_PAGE, 19) ++#define HV_MCC_UPPER PHY_REG(HV_STATS_PAGE, 20) /* Multiple Collision */ ++#define HV_MCC_LOWER PHY_REG(HV_STATS_PAGE, 21) ++#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision */ ++#define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24) ++#define HV_COLC_UPPER PHY_REG(HV_STATS_PAGE, 25) /* Collision */ ++#define HV_COLC_LOWER PHY_REG(HV_STATS_PAGE, 26) ++#define HV_DC_UPPER PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */ ++#define HV_DC_LOWER PHY_REG(HV_STATS_PAGE, 28) ++#define HV_TNCRS_UPPER PHY_REG(HV_STATS_PAGE, 29) /* Tx with no CRS */ ++#define HV_TNCRS_LOWER PHY_REG(HV_STATS_PAGE, 30) ++ ++#define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */ ++ ++#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ ++#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ ++ ++/* SMBus Control Phy Register */ ++#define CV_SMB_CTRL PHY_REG(769, 23) ++#define CV_SMB_CTRL_FORCE_SMBUS 0x0001 ++ ++/* SMBus Address Phy Register */ ++#define HV_SMB_ADDR PHY_REG(768, 26) ++#define HV_SMB_ADDR_MASK 0x007F ++#define HV_SMB_ADDR_PEC_EN 0x0200 ++#define HV_SMB_ADDR_VALID 0x0080 ++#define HV_SMB_ADDR_FREQ_MASK 0x1100 ++#define HV_SMB_ADDR_FREQ_LOW_SHIFT 8 ++#define HV_SMB_ADDR_FREQ_HIGH_SHIFT 12 ++ ++/* Strapping Option Register - RO */ ++#define E1000_STRAP 0x0000C ++#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000 ++#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17 ++#define E1000_STRAP_SMT_FREQ_MASK 0x00003000 ++#define E1000_STRAP_SMT_FREQ_SHIFT 12 ++ ++/* OEM Bits Phy Register */ ++#define HV_OEM_BITS PHY_REG(768, 25) ++#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */ ++#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ ++#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ ++ ++/* KMRN Mode Control */ ++#define HV_KMRN_MODE_CTRL PHY_REG(769, 16) ++#define HV_KMRN_MDIO_SLOW 0x0400 ++ ++/* KMRN FIFO Control and Status */ ++#define HV_KMRN_FIFO_CTRLSTA PHY_REG(770, 16) ++#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK 0x7000 ++#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT 12 ++ ++/* PHY Power Management Control */ ++#define HV_PM_CTRL PHY_REG(770, 17) ++#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 ++ ++#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */ ++ ++/* Inband Control */ ++#define I217_INBAND_CTRL PHY_REG(770, 18) ++#define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK 0x3F00 ++#define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT 8 ++ ++/* PHY Low Power Idle Control */ ++#define I82579_LPI_CTRL PHY_REG(772, 20) ++#define I82579_LPI_CTRL_100_ENABLE 0x2000 ++#define I82579_LPI_CTRL_1000_ENABLE 0x4000 ++#define I82579_LPI_CTRL_ENABLE_MASK 0x6000 ++#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80 ++ ++/* Extended Management Interface (EMI) Registers */ ++#define I82579_EMI_ADDR 0x10 ++#define I82579_EMI_DATA 0x11 ++#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */ ++#define I82579_MSE_THRESHOLD 0x084F /* 82579 Mean Square Error Threshold */ ++#define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */ ++#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */ ++#define I82579_RX_CONFIG 0x3412 /* Receive configuration */ ++#define I82579_EEE_PCS_STATUS 0x182E /* IEEE MMD Register 3.1 >> 8 */ ++#define I82579_EEE_CAPABILITY 0x0410 /* IEEE MMD Register 3.20 */ ++#define I82579_EEE_ADVERTISEMENT 0x040E /* IEEE MMD Register 7.60 */ ++#define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */ ++#define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE */ ++#define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE */ ++#define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */ ++#define I217_EEE_CAPABILITY 0x8000 /* IEEE MMD Register 3.20 */ ++#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */ ++#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */ ++ ++#define E1000_EEE_RX_LPI_RCVD 0x0400 /* Tx LP idle received */ ++#define E1000_EEE_TX_LPI_RCVD 0x0800 /* Rx LP idle received */ ++ ++/* Intel Rapid Start Technology Support */ ++#define I217_PROXY_CTRL BM_PHY_REG(BM_WUC_PAGE, 70) ++#define I217_PROXY_CTRL_AUTO_DISABLE 0x0080 ++#define I217_SxCTRL PHY_REG(BM_PORT_CTRL_PAGE, 28) ++#define I217_SxCTRL_ENABLE_LPI_RESET 0x1000 ++#define I217_CGFREG PHY_REG(772, 29) ++#define I217_CGFREG_ENABLE_MTA_RESET 0x0002 ++#define I217_MEMPWR PHY_REG(772, 26) ++#define I217_MEMPWR_DISABLE_SMB_RELEASE 0x0010 ++ ++/* Receive Address Initial CRC Calculation */ ++#define E1000_PCH_RAICC(_n) (0x05F50 + ((_n) * 4)) ++ ++/* Latency Tolerance Reporting */ ++#define E1000_LTRV 0x000F8 ++#define E1000_LTRV_SCALE_MAX 5 ++#define E1000_LTRV_SCALE_FACTOR 5 ++#define E1000_LTRV_REQ_SHIFT 15 ++#define E1000_LTRV_NOSNOOP_SHIFT 16 ++#define E1000_LTRV_SEND (1 << 30) ++ ++/* Proprietary Latency Tolerance Reporting PCI Capability */ ++#define E1000_PCI_LTR_CAP_LPT 0xA8 ++ ++void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw); ++void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, ++ bool state); ++void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); ++void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); ++void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw); ++void e1000_resume_workarounds_pchlan(struct e1000_hw *hw); ++s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); ++void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw); ++s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable); ++s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data); ++s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data); ++#endif /* _E1000E_ICH8LAN_H_ */ +diff --git a/drivers/net/ethernet/intel/e1000e/lib.c b/drivers/net/ethernet/intel/e1000e/lib.c +deleted file mode 100644 +index 0893ab1..0000000 +--- a/drivers/net/ethernet/intel/e1000e/lib.c ++++ /dev/null +@@ -1,2693 +0,0 @@ +-/******************************************************************************* +- +- Intel PRO/1000 Linux driver +- Copyright(c) 1999 - 2011 Intel Corporation. +- +- 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. +- +- This program is distributed in the hope it will be useful, but WITHOUT +- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- more details. +- +- You should have received a copy of the GNU General Public License along with +- this program; if not, write to the Free Software Foundation, Inc., +- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- +- The full GNU General Public License is included in this distribution in +- the file called "COPYING". +- +- Contact Information: +- Linux NICS +- e1000-devel Mailing List +- Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- +-*******************************************************************************/ +- +-#include "e1000.h" +- +-enum e1000_mng_mode { +- e1000_mng_mode_none = 0, +- e1000_mng_mode_asf, +- e1000_mng_mode_pt, +- e1000_mng_mode_ipmi, +- e1000_mng_mode_host_if_only +-}; +- +-#define E1000_FACTPS_MNGCG 0x20000000 +- +-/* Intel(R) Active Management Technology signature */ +-#define E1000_IAMT_SIGNATURE 0x544D4149 +- +-/** +- * e1000e_get_bus_info_pcie - Get PCIe bus information +- * @hw: pointer to the HW structure +- * +- * Determines and stores the system bus information for a particular +- * network interface. The following bus information is determined and stored: +- * bus speed, bus width, type (PCIe), and PCIe function. +- **/ +-s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw) +-{ +- struct e1000_mac_info *mac = &hw->mac; +- struct e1000_bus_info *bus = &hw->bus; +- struct e1000_adapter *adapter = hw->adapter; +- u16 pcie_link_status, cap_offset; +- +- cap_offset = adapter->pdev->pcie_cap; +- if (!cap_offset) { +- bus->width = e1000_bus_width_unknown; +- } else { +- pci_read_config_word(adapter->pdev, +- cap_offset + PCIE_LINK_STATUS, +- &pcie_link_status); +- bus->width = (enum e1000_bus_width)((pcie_link_status & +- PCIE_LINK_WIDTH_MASK) >> +- PCIE_LINK_WIDTH_SHIFT); +- } +- +- mac->ops.set_lan_id(hw); +- +- return 0; +-} +- +-/** +- * e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices +- * +- * @hw: pointer to the HW structure +- * +- * Determines the LAN function id by reading memory-mapped registers +- * and swaps the port value if requested. +- **/ +-void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) +-{ +- struct e1000_bus_info *bus = &hw->bus; +- u32 reg; +- +- /* +- * The status register reports the correct function number +- * for the device regardless of function swap state. +- */ +- reg = er32(STATUS); +- bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; +-} +- +-/** +- * e1000_set_lan_id_single_port - Set LAN id for a single port device +- * @hw: pointer to the HW structure +- * +- * Sets the LAN function id to zero for a single port device. +- **/ +-void e1000_set_lan_id_single_port(struct e1000_hw *hw) +-{ +- struct e1000_bus_info *bus = &hw->bus; +- +- bus->func = 0; +-} +- +-/** +- * e1000_clear_vfta_generic - Clear VLAN filter table +- * @hw: pointer to the HW structure +- * +- * Clears the register array which contains the VLAN filter table by +- * setting all the values to 0. +- **/ +-void e1000_clear_vfta_generic(struct e1000_hw *hw) +-{ +- u32 offset; +- +- for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { +- E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); +- e1e_flush(); +- } +-} +- +-/** +- * e1000_write_vfta_generic - Write value to VLAN filter table +- * @hw: pointer to the HW structure +- * @offset: register offset in VLAN filter table +- * @value: register value written to VLAN filter table +- * +- * Writes value at the given offset in the register array which stores +- * the VLAN filter table. +- **/ +-void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) +-{ +- E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); +- e1e_flush(); +-} +- +-/** +- * e1000e_init_rx_addrs - Initialize receive address's +- * @hw: pointer to the HW structure +- * @rar_count: receive address registers +- * +- * Setup the receive address registers by setting the base receive address +- * register to the devices MAC address and clearing all the other receive +- * address registers to 0. +- **/ +-void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count) +-{ +- u32 i; +- u8 mac_addr[ETH_ALEN] = {0}; +- +- /* Setup the receive address */ +- e_dbg("Programming MAC Address into RAR[0]\n"); +- +- e1000e_rar_set(hw, hw->mac.addr, 0); +- +- /* Zero out the other (rar_entry_count - 1) receive addresses */ +- e_dbg("Clearing RAR[1-%u]\n", rar_count-1); +- for (i = 1; i < rar_count; i++) +- e1000e_rar_set(hw, mac_addr, i); +-} +- +-/** +- * e1000_check_alt_mac_addr_generic - Check for alternate MAC addr +- * @hw: pointer to the HW structure +- * +- * Checks the nvm for an alternate MAC address. An alternate MAC address +- * can be setup by pre-boot software and must be treated like a permanent +- * address and must override the actual permanent MAC address. If an +- * alternate MAC address is found it is programmed into RAR0, replacing +- * the permanent address that was installed into RAR0 by the Si on reset. +- * This function will return SUCCESS unless it encounters an error while +- * reading the EEPROM. +- **/ +-s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) +-{ +- u32 i; +- s32 ret_val = 0; +- u16 offset, nvm_alt_mac_addr_offset, nvm_data; +- u8 alt_mac_addr[ETH_ALEN]; +- +- ret_val = e1000_read_nvm(hw, NVM_COMPAT, 1, &nvm_data); +- if (ret_val) +- goto out; +- +- /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */ +- if (!((nvm_data & NVM_COMPAT_LOM) || +- (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) || +- (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) || +- (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES))) +- goto out; +- +- ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, +- &nvm_alt_mac_addr_offset); +- if (ret_val) { +- e_dbg("NVM Read Error\n"); +- goto out; +- } +- +- if ((nvm_alt_mac_addr_offset == 0xFFFF) || +- (nvm_alt_mac_addr_offset == 0x0000)) +- /* There is no Alternate MAC Address */ +- goto out; +- +- if (hw->bus.func == E1000_FUNC_1) +- nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; +- for (i = 0; i < ETH_ALEN; i += 2) { +- offset = nvm_alt_mac_addr_offset + (i >> 1); +- ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data); +- if (ret_val) { +- e_dbg("NVM Read Error\n"); +- goto out; +- } +- +- alt_mac_addr[i] = (u8)(nvm_data & 0xFF); +- alt_mac_addr[i + 1] = (u8)(nvm_data >> 8); +- } +- +- /* if multicast bit is set, the alternate address will not be used */ +- if (is_multicast_ether_addr(alt_mac_addr)) { +- e_dbg("Ignoring Alternate Mac Address with MC bit set\n"); +- goto out; +- } +- +- /* +- * We have a valid alternate MAC address, and we want to treat it the +- * same as the normal permanent MAC address stored by the HW into the +- * RAR. Do this by mapping this address into RAR0. +- */ +- e1000e_rar_set(hw, alt_mac_addr, 0); +- +-out: +- return ret_val; +-} +- +-/** +- * e1000e_rar_set - Set receive address register +- * @hw: pointer to the HW structure +- * @addr: pointer to the receive address +- * @index: receive address array register +- * +- * Sets the receive address array register at index to the address passed +- * in by addr. +- **/ +-void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) +-{ +- u32 rar_low, rar_high; +- +- /* +- * HW expects these in little endian so we reverse the byte order +- * from network order (big endian) to little endian +- */ +- rar_low = ((u32) addr[0] | +- ((u32) addr[1] << 8) | +- ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); +- +- rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); +- +- /* If MAC address zero, no need to set the AV bit */ +- if (rar_low || rar_high) +- rar_high |= E1000_RAH_AV; +- +- /* +- * Some bridges will combine consecutive 32-bit writes into +- * a single burst write, which will malfunction on some parts. +- * The flushes avoid this. +- */ +- ew32(RAL(index), rar_low); +- e1e_flush(); +- ew32(RAH(index), rar_high); +- e1e_flush(); +-} +- +-/** +- * e1000_hash_mc_addr - Generate a multicast hash value +- * @hw: pointer to the HW structure +- * @mc_addr: pointer to a multicast address +- * +- * Generates a multicast address hash value which is used to determine +- * the multicast filter table array address and new table value. See +- * e1000_mta_set_generic() +- **/ +-static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) +-{ +- u32 hash_value, hash_mask; +- u8 bit_shift = 0; +- +- /* Register count multiplied by bits per register */ +- hash_mask = (hw->mac.mta_reg_count * 32) - 1; +- +- /* +- * For a mc_filter_type of 0, bit_shift is the number of left-shifts +- * where 0xFF would still fall within the hash mask. +- */ +- while (hash_mask >> bit_shift != 0xFF) +- bit_shift++; +- +- /* +- * The portion of the address that is used for the hash table +- * is determined by the mc_filter_type setting. +- * The algorithm is such that there is a total of 8 bits of shifting. +- * The bit_shift for a mc_filter_type of 0 represents the number of +- * left-shifts where the MSB of mc_addr[5] would still fall within +- * the hash_mask. Case 0 does this exactly. Since there are a total +- * of 8 bits of shifting, then mc_addr[4] will shift right the +- * remaining number of bits. Thus 8 - bit_shift. The rest of the +- * cases are a variation of this algorithm...essentially raising the +- * number of bits to shift mc_addr[5] left, while still keeping the +- * 8-bit shifting total. +- * +- * For example, given the following Destination MAC Address and an +- * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask), +- * we can see that the bit_shift for case 0 is 4. These are the hash +- * values resulting from each mc_filter_type... +- * [0] [1] [2] [3] [4] [5] +- * 01 AA 00 12 34 56 +- * LSB MSB +- * +- * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563 +- * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6 +- * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163 +- * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 +- */ +- switch (hw->mac.mc_filter_type) { +- default: +- case 0: +- break; +- case 1: +- bit_shift += 1; +- break; +- case 2: +- bit_shift += 2; +- break; +- case 3: +- bit_shift += 4; +- break; +- } +- +- hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | +- (((u16) mc_addr[5]) << bit_shift))); +- +- return hash_value; +-} +- +-/** +- * e1000e_update_mc_addr_list_generic - Update Multicast addresses +- * @hw: pointer to the HW structure +- * @mc_addr_list: array of multicast addresses to program +- * @mc_addr_count: number of multicast addresses to program +- * +- * Updates entire Multicast Table Array. +- * The caller must have a packed mc_addr_list of multicast addresses. +- **/ +-void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, +- u8 *mc_addr_list, u32 mc_addr_count) +-{ +- u32 hash_value, hash_bit, hash_reg; +- int i; +- +- /* clear mta_shadow */ +- memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); +- +- /* update mta_shadow from mc_addr_list */ +- for (i = 0; (u32) i < mc_addr_count; i++) { +- hash_value = e1000_hash_mc_addr(hw, mc_addr_list); +- +- hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); +- hash_bit = hash_value & 0x1F; +- +- hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); +- mc_addr_list += (ETH_ALEN); +- } +- +- /* replace the entire MTA table */ +- for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) +- E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); +- e1e_flush(); +-} +- +-/** +- * e1000e_clear_hw_cntrs_base - Clear base hardware counters +- * @hw: pointer to the HW structure +- * +- * Clears the base hardware counters by reading the counter registers. +- **/ +-void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw) +-{ +- er32(CRCERRS); +- er32(SYMERRS); +- er32(MPC); +- er32(SCC); +- er32(ECOL); +- er32(MCC); +- er32(LATECOL); +- er32(COLC); +- er32(DC); +- er32(SEC); +- er32(RLEC); +- er32(XONRXC); +- er32(XONTXC); +- er32(XOFFRXC); +- er32(XOFFTXC); +- er32(FCRUC); +- er32(GPRC); +- er32(BPRC); +- er32(MPRC); +- er32(GPTC); +- er32(GORCL); +- er32(GORCH); +- er32(GOTCL); +- er32(GOTCH); +- er32(RNBC); +- er32(RUC); +- er32(RFC); +- er32(ROC); +- er32(RJC); +- er32(TORL); +- er32(TORH); +- er32(TOTL); +- er32(TOTH); +- er32(TPR); +- er32(TPT); +- er32(MPTC); +- er32(BPTC); +-} +- +-/** +- * e1000e_check_for_copper_link - Check for link (Copper) +- * @hw: pointer to the HW structure +- * +- * Checks to see of the link status of the hardware has changed. If a +- * change in link status has been detected, then we read the PHY registers +- * to get the current speed/duplex if link exists. +- **/ +-s32 e1000e_check_for_copper_link(struct e1000_hw *hw) +-{ +- struct e1000_mac_info *mac = &hw->mac; +- s32 ret_val; +- bool link; +- +- /* +- * We only want to go out to the PHY registers to see if Auto-Neg +- * has completed and/or if our link status has changed. The +- * get_link_status flag is set upon receiving a Link Status +- * Change or Rx Sequence Error interrupt. +- */ +- if (!mac->get_link_status) +- return 0; +- +- /* +- * First we want to see if the MII Status Register reports +- * link. If so, then we want to get the current speed/duplex +- * of the PHY. +- */ +- ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); +- if (ret_val) +- return ret_val; +- +- if (!link) +- return ret_val; /* No link detected */ +- +- mac->get_link_status = false; +- +- /* +- * Check if there was DownShift, must be checked +- * immediately after link-up +- */ +- e1000e_check_downshift(hw); +- +- /* +- * If we are forcing speed/duplex, then we simply return since +- * we have already determined whether we have link or not. +- */ +- if (!mac->autoneg) { +- ret_val = -E1000_ERR_CONFIG; +- return ret_val; +- } +- +- /* +- * Auto-Neg is enabled. Auto Speed Detection takes care +- * of MAC speed/duplex configuration. So we only need to +- * configure Collision Distance in the MAC. +- */ +- e1000e_config_collision_dist(hw); +- +- /* +- * Configure Flow Control now that Auto-Neg has completed. +- * First, we need to restore the desired flow control +- * settings because we may have had to re-autoneg with a +- * different link partner. +- */ +- ret_val = e1000e_config_fc_after_link_up(hw); +- if (ret_val) +- e_dbg("Error configuring flow control\n"); +- +- return ret_val; +-} +- +-/** +- * e1000e_check_for_fiber_link - Check for link (Fiber) +- * @hw: pointer to the HW structure +- * +- * Checks for link up on the hardware. If link is not up and we have +- * a signal, then we need to force link up. +- **/ +-s32 e1000e_check_for_fiber_link(struct e1000_hw *hw) +-{ +- struct e1000_mac_info *mac = &hw->mac; +- u32 rxcw; +- u32 ctrl; +- u32 status; +- s32 ret_val; +- +- ctrl = er32(CTRL); +- status = er32(STATUS); +- rxcw = er32(RXCW); +- +- /* +- * If we don't have link (auto-negotiation failed or link partner +- * cannot auto-negotiate), the cable is plugged in (we have signal), +- * and our link partner is not trying to auto-negotiate with us (we +- * are receiving idles or data), we need to force link up. We also +- * need to give auto-negotiation time to complete, in case the cable +- * was just plugged in. The autoneg_failed flag does this. +- */ +- /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ +- if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) && +- (!(rxcw & E1000_RXCW_C))) { +- if (mac->autoneg_failed == 0) { +- mac->autoneg_failed = 1; +- return 0; +- } +- e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); +- +- /* Disable auto-negotiation in the TXCW register */ +- ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); +- +- /* Force link-up and also force full-duplex. */ +- ctrl = er32(CTRL); +- ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); +- ew32(CTRL, ctrl); +- +- /* Configure Flow Control after forcing link up. */ +- ret_val = e1000e_config_fc_after_link_up(hw); +- if (ret_val) { +- e_dbg("Error configuring flow control\n"); +- return ret_val; +- } +- } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { +- /* +- * If we are forcing link and we are receiving /C/ ordered +- * sets, re-enable auto-negotiation in the TXCW register +- * and disable forced link in the Device Control register +- * in an attempt to auto-negotiate with our link partner. +- */ +- e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); +- ew32(TXCW, mac->txcw); +- ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); +- +- mac->serdes_has_link = true; +- } +- +- return 0; +-} +- +-/** +- * e1000e_check_for_serdes_link - Check for link (Serdes) +- * @hw: pointer to the HW structure +- * +- * Checks for link up on the hardware. If link is not up and we have +- * a signal, then we need to force link up. +- **/ +-s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) +-{ +- struct e1000_mac_info *mac = &hw->mac; +- u32 rxcw; +- u32 ctrl; +- u32 status; +- s32 ret_val; +- +- ctrl = er32(CTRL); +- status = er32(STATUS); +- rxcw = er32(RXCW); +- +- /* +- * If we don't have link (auto-negotiation failed or link partner +- * cannot auto-negotiate), and our link partner is not trying to +- * auto-negotiate with us (we are receiving idles or data), +- * we need to force link up. We also need to give auto-negotiation +- * time to complete. +- */ +- /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ +- if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) { +- if (mac->autoneg_failed == 0) { +- mac->autoneg_failed = 1; +- return 0; +- } +- e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); +- +- /* Disable auto-negotiation in the TXCW register */ +- ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); +- +- /* Force link-up and also force full-duplex. */ +- ctrl = er32(CTRL); +- ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); +- ew32(CTRL, ctrl); +- +- /* Configure Flow Control after forcing link up. */ +- ret_val = e1000e_config_fc_after_link_up(hw); +- if (ret_val) { +- e_dbg("Error configuring flow control\n"); +- return ret_val; +- } +- } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { +- /* +- * If we are forcing link and we are receiving /C/ ordered +- * sets, re-enable auto-negotiation in the TXCW register +- * and disable forced link in the Device Control register +- * in an attempt to auto-negotiate with our link partner. +- */ +- e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); +- ew32(TXCW, mac->txcw); +- ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); +- +- mac->serdes_has_link = true; +- } else if (!(E1000_TXCW_ANE & er32(TXCW))) { +- /* +- * If we force link for non-auto-negotiation switch, check +- * link status based on MAC synchronization for internal +- * serdes media type. +- */ +- /* SYNCH bit and IV bit are sticky. */ +- udelay(10); +- rxcw = er32(RXCW); +- if (rxcw & E1000_RXCW_SYNCH) { +- if (!(rxcw & E1000_RXCW_IV)) { +- mac->serdes_has_link = true; +- e_dbg("SERDES: Link up - forced.\n"); +- } +- } else { +- mac->serdes_has_link = false; +- e_dbg("SERDES: Link down - force failed.\n"); +- } +- } +- +- if (E1000_TXCW_ANE & er32(TXCW)) { +- status = er32(STATUS); +- if (status & E1000_STATUS_LU) { +- /* SYNCH bit and IV bit are sticky, so reread rxcw. */ +- udelay(10); +- rxcw = er32(RXCW); +- if (rxcw & E1000_RXCW_SYNCH) { +- if (!(rxcw & E1000_RXCW_IV)) { +- mac->serdes_has_link = true; +- e_dbg("SERDES: Link up - autoneg " +- "completed successfully.\n"); +- } else { +- mac->serdes_has_link = false; +- e_dbg("SERDES: Link down - invalid" +- "codewords detected in autoneg.\n"); +- } +- } else { +- mac->serdes_has_link = false; +- e_dbg("SERDES: Link down - no sync.\n"); +- } +- } else { +- mac->serdes_has_link = false; +- e_dbg("SERDES: Link down - autoneg failed\n"); +- } +- } +- +- return 0; +-} +- +-/** +- * e1000_set_default_fc_generic - Set flow control default values +- * @hw: pointer to the HW structure +- * +- * Read the EEPROM for the default values for flow control and store the +- * values. +- **/ +-static s32 e1000_set_default_fc_generic(struct e1000_hw *hw) +-{ +- s32 ret_val; +- u16 nvm_data; +- +- /* +- * Read and store word 0x0F of the EEPROM. This word contains bits +- * that determine the hardware's default PAUSE (flow control) mode, +- * a bit that determines whether the HW defaults to enabling or +- * disabling auto-negotiation, and the direction of the +- * SW defined pins. If there is no SW over-ride of the flow +- * control setting, then the variable hw->fc will +- * be initialized based on a value in the EEPROM. +- */ +- ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); +- +- if (ret_val) { +- e_dbg("NVM Read Error\n"); +- return ret_val; +- } +- +- if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0) +- hw->fc.requested_mode = e1000_fc_none; +- else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == +- NVM_WORD0F_ASM_DIR) +- hw->fc.requested_mode = e1000_fc_tx_pause; +- else +- hw->fc.requested_mode = e1000_fc_full; +- +- return 0; +-} +- +-/** +- * e1000e_setup_link - Setup flow control and link settings +- * @hw: pointer to the HW structure +- * +- * Determines which flow control settings to use, then configures flow +- * control. Calls the appropriate media-specific link configuration +- * function. Assuming the adapter has a valid link partner, a valid link +- * should be established. Assumes the hardware has previously been reset +- * and the transmitter and receiver are not enabled. +- **/ +-s32 e1000e_setup_link(struct e1000_hw *hw) +-{ +- struct e1000_mac_info *mac = &hw->mac; +- s32 ret_val; +- +- /* +- * In the case of the phy reset being blocked, we already have a link. +- * We do not need to set it up again. +- */ +- if (e1000_check_reset_block(hw)) +- return 0; +- +- /* +- * If requested flow control is set to default, set flow control +- * based on the EEPROM flow control settings. +- */ +- if (hw->fc.requested_mode == e1000_fc_default) { +- ret_val = e1000_set_default_fc_generic(hw); +- if (ret_val) +- return ret_val; +- } +- +- /* +- * Save off the requested flow control mode for use later. Depending +- * on the link partner's capabilities, we may or may not use this mode. +- */ +- hw->fc.current_mode = hw->fc.requested_mode; +- +- e_dbg("After fix-ups FlowControl is now = %x\n", +- hw->fc.current_mode); +- +- /* Call the necessary media_type subroutine to configure the link. */ +- ret_val = mac->ops.setup_physical_interface(hw); +- if (ret_val) +- return ret_val; +- +- /* +- * Initialize the flow control address, type, and PAUSE timer +- * registers to their default values. This is done even if flow +- * control is disabled, because it does not hurt anything to +- * initialize these registers. +- */ +- e_dbg("Initializing the Flow Control address, type and timer regs\n"); +- ew32(FCT, FLOW_CONTROL_TYPE); +- ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH); +- ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW); +- +- ew32(FCTTV, hw->fc.pause_time); +- +- return e1000e_set_fc_watermarks(hw); +-} +- +-/** +- * e1000_commit_fc_settings_generic - Configure flow control +- * @hw: pointer to the HW structure +- * +- * Write the flow control settings to the Transmit Config Word Register (TXCW) +- * base on the flow control settings in e1000_mac_info. +- **/ +-static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) +-{ +- struct e1000_mac_info *mac = &hw->mac; +- u32 txcw; +- +- /* +- * Check for a software override of the flow control settings, and +- * setup the device accordingly. If auto-negotiation is enabled, then +- * software will have to set the "PAUSE" bits to the correct value in +- * the Transmit Config Word Register (TXCW) and re-start auto- +- * negotiation. However, if auto-negotiation is disabled, then +- * software will have to manually configure the two flow control enable +- * bits in the CTRL register. +- * +- * The possible values of the "fc" parameter are: +- * 0: Flow control is completely disabled +- * 1: Rx flow control is enabled (we can receive pause frames, +- * but not send pause frames). +- * 2: Tx flow control is enabled (we can send pause frames but we +- * do not support receiving pause frames). +- * 3: Both Rx and Tx flow control (symmetric) are enabled. +- */ +- switch (hw->fc.current_mode) { +- case e1000_fc_none: +- /* Flow control completely disabled by a software over-ride. */ +- txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); +- break; +- case e1000_fc_rx_pause: +- /* +- * Rx Flow control is enabled and Tx Flow control is disabled +- * by a software over-ride. Since there really isn't a way to +- * advertise that we are capable of Rx Pause ONLY, we will +- * advertise that we support both symmetric and asymmetric Rx +- * PAUSE. Later, we will disable the adapter's ability to send +- * PAUSE frames. +- */ +- txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); +- break; +- case e1000_fc_tx_pause: +- /* +- * Tx Flow control is enabled, and Rx Flow control is disabled, +- * by a software over-ride. +- */ +- txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); +- break; +- case e1000_fc_full: +- /* +- * Flow control (both Rx and Tx) is enabled by a software +- * over-ride. +- */ +- txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); +- break; +- default: +- e_dbg("Flow control param set incorrectly\n"); +- return -E1000_ERR_CONFIG; +- break; +- } +- +- ew32(TXCW, txcw); +- mac->txcw = txcw; +- +- return 0; +-} +- +-/** +- * e1000_poll_fiber_serdes_link_generic - Poll for link up +- * @hw: pointer to the HW structure +- * +- * Polls for link up by reading the status register, if link fails to come +- * up with auto-negotiation, then the link is forced if a signal is detected. +- **/ +-static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) +-{ +- struct e1000_mac_info *mac = &hw->mac; +- u32 i, status; +- s32 ret_val; +- +- /* +- * If we have a signal (the cable is plugged in, or assumed true for +- * serdes media) then poll for a "Link-Up" indication in the Device +- * Status Register. Time-out if a link isn't seen in 500 milliseconds +- * seconds (Auto-negotiation should complete in less than 500 +- * milliseconds even if the other end is doing it in SW). +- */ +- for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { +- usleep_range(10000, 20000); +- status = er32(STATUS); +- if (status & E1000_STATUS_LU) +- break; +- } +- if (i == FIBER_LINK_UP_LIMIT) { +- e_dbg("Never got a valid link from auto-neg!!!\n"); +- mac->autoneg_failed = 1; +- /* +- * AutoNeg failed to achieve a link, so we'll call +- * mac->check_for_link. This routine will force the +- * link up if we detect a signal. This will allow us to +- * communicate with non-autonegotiating link partners. +- */ +- ret_val = mac->ops.check_for_link(hw); +- if (ret_val) { +- e_dbg("Error while checking for link\n"); +- return ret_val; +- } +- mac->autoneg_failed = 0; +- } else { +- mac->autoneg_failed = 0; +- e_dbg("Valid Link Found\n"); +- } +- +- return 0; +-} +- +-/** +- * e1000e_setup_fiber_serdes_link - Setup link for fiber/serdes +- * @hw: pointer to the HW structure +- * +- * Configures collision distance and flow control for fiber and serdes +- * links. Upon successful setup, poll for link. +- **/ +-s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw) +-{ +- u32 ctrl; +- s32 ret_val; +- +- ctrl = er32(CTRL); +- +- /* Take the link out of reset */ +- ctrl &= ~E1000_CTRL_LRST; +- +- e1000e_config_collision_dist(hw); +- +- ret_val = e1000_commit_fc_settings_generic(hw); +- if (ret_val) +- return ret_val; +- +- /* +- * Since auto-negotiation is enabled, take the link out of reset (the +- * link will be in reset, because we previously reset the chip). This +- * will restart auto-negotiation. If auto-negotiation is successful +- * then the link-up status bit will be set and the flow control enable +- * bits (RFCE and TFCE) will be set according to their negotiated value. +- */ +- e_dbg("Auto-negotiation enabled\n"); +- +- ew32(CTRL, ctrl); +- e1e_flush(); +- usleep_range(1000, 2000); +- +- /* +- * For these adapters, the SW definable pin 1 is set when the optics +- * detect a signal. If we have a signal, then poll for a "Link-Up" +- * indication. +- */ +- if (hw->phy.media_type == e1000_media_type_internal_serdes || +- (er32(CTRL) & E1000_CTRL_SWDPIN1)) { +- ret_val = e1000_poll_fiber_serdes_link_generic(hw); +- } else { +- e_dbg("No signal detected\n"); +- } +- +- return 0; +-} +- +-/** +- * e1000e_config_collision_dist - Configure collision distance +- * @hw: pointer to the HW structure +- * +- * Configures the collision distance to the default value and is used +- * during link setup. Currently no func pointer exists and all +- * implementations are handled in the generic version of this function. +- **/ +-void e1000e_config_collision_dist(struct e1000_hw *hw) +-{ +- u32 tctl; +- +- tctl = er32(TCTL); +- +- tctl &= ~E1000_TCTL_COLD; +- tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; +- +- ew32(TCTL, tctl); +- e1e_flush(); +-} +- +-/** +- * e1000e_set_fc_watermarks - Set flow control high/low watermarks +- * @hw: pointer to the HW structure +- * +- * Sets the flow control high/low threshold (watermark) registers. If +- * flow control XON frame transmission is enabled, then set XON frame +- * transmission as well. +- **/ +-s32 e1000e_set_fc_watermarks(struct e1000_hw *hw) +-{ +- u32 fcrtl = 0, fcrth = 0; +- +- /* +- * Set the flow control receive threshold registers. Normally, +- * these registers will be set to a default threshold that may be +- * adjusted later by the driver's runtime code. However, if the +- * ability to transmit pause frames is not enabled, then these +- * registers will be set to 0. +- */ +- if (hw->fc.current_mode & e1000_fc_tx_pause) { +- /* +- * We need to set up the Receive Threshold high and low water +- * marks as well as (optionally) enabling the transmission of +- * XON frames. +- */ +- fcrtl = hw->fc.low_water; +- fcrtl |= E1000_FCRTL_XONE; +- fcrth = hw->fc.high_water; +- } +- ew32(FCRTL, fcrtl); +- ew32(FCRTH, fcrth); +- +- return 0; +-} +- +-/** +- * e1000e_force_mac_fc - Force the MAC's flow control settings +- * @hw: pointer to the HW structure +- * +- * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the +- * device control register to reflect the adapter settings. TFCE and RFCE +- * need to be explicitly set by software when a copper PHY is used because +- * autonegotiation is managed by the PHY rather than the MAC. Software must +- * also configure these bits when link is forced on a fiber connection. +- **/ +-s32 e1000e_force_mac_fc(struct e1000_hw *hw) +-{ +- u32 ctrl; +- +- ctrl = er32(CTRL); +- +- /* +- * Because we didn't get link via the internal auto-negotiation +- * mechanism (we either forced link or we got link via PHY +- * auto-neg), we have to manually enable/disable transmit an +- * receive flow control. +- * +- * The "Case" statement below enables/disable flow control +- * according to the "hw->fc.current_mode" parameter. +- * +- * The possible values of the "fc" parameter are: +- * 0: Flow control is completely disabled +- * 1: Rx flow control is enabled (we can receive pause +- * frames but not send pause frames). +- * 2: Tx flow control is enabled (we can send pause frames +- * frames but we do not receive pause frames). +- * 3: Both Rx and Tx flow control (symmetric) is enabled. +- * other: No other values should be possible at this point. +- */ +- e_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode); +- +- switch (hw->fc.current_mode) { +- case e1000_fc_none: +- ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); +- break; +- case e1000_fc_rx_pause: +- ctrl &= (~E1000_CTRL_TFCE); +- ctrl |= E1000_CTRL_RFCE; +- break; +- case e1000_fc_tx_pause: +- ctrl &= (~E1000_CTRL_RFCE); +- ctrl |= E1000_CTRL_TFCE; +- break; +- case e1000_fc_full: +- ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); +- break; +- default: +- e_dbg("Flow control param set incorrectly\n"); +- return -E1000_ERR_CONFIG; +- } +- +- ew32(CTRL, ctrl); +- +- return 0; +-} +- +-/** +- * e1000e_config_fc_after_link_up - Configures flow control after link +- * @hw: pointer to the HW structure +- * +- * Checks the status of auto-negotiation after link up to ensure that the +- * speed and duplex were not forced. If the link needed to be forced, then +- * flow control needs to be forced also. If auto-negotiation is enabled +- * and did not fail, then we configure flow control based on our link +- * partner. +- **/ +-s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) +-{ +- struct e1000_mac_info *mac = &hw->mac; +- s32 ret_val = 0; +- u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; +- u16 speed, duplex; +- +- /* +- * Check for the case where we have fiber media and auto-neg failed +- * so we had to force link. In this case, we need to force the +- * configuration of the MAC to match the "fc" parameter. +- */ +- if (mac->autoneg_failed) { +- if (hw->phy.media_type == e1000_media_type_fiber || +- hw->phy.media_type == e1000_media_type_internal_serdes) +- ret_val = e1000e_force_mac_fc(hw); +- } else { +- if (hw->phy.media_type == e1000_media_type_copper) +- ret_val = e1000e_force_mac_fc(hw); +- } +- +- if (ret_val) { +- e_dbg("Error forcing flow control settings\n"); +- return ret_val; +- } +- +- /* +- * Check for the case where we have copper media and auto-neg is +- * enabled. In this case, we need to check and see if Auto-Neg +- * has completed, and if so, how the PHY and link partner has +- * flow control configured. +- */ +- if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { +- /* +- * Read the MII Status Register and check to see if AutoNeg +- * has completed. We read this twice because this reg has +- * some "sticky" (latched) bits. +- */ +- ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg); +- if (ret_val) +- return ret_val; +- ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg); +- if (ret_val) +- return ret_val; +- +- if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { +- e_dbg("Copper PHY and Auto Neg " +- "has not completed.\n"); +- return ret_val; +- } +- +- /* +- * The AutoNeg process has completed, so we now need to +- * read both the Auto Negotiation Advertisement +- * Register (Address 4) and the Auto_Negotiation Base +- * Page Ability Register (Address 5) to determine how +- * flow control was negotiated. +- */ +- ret_val = e1e_rphy(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg); +- if (ret_val) +- return ret_val; +- ret_val = +- e1e_rphy(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg); +- if (ret_val) +- return ret_val; +- +- /* +- * Two bits in the Auto Negotiation Advertisement Register +- * (Address 4) and two bits in the Auto Negotiation Base +- * Page Ability Register (Address 5) determine flow control +- * for both the PHY and the link partner. The following +- * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, +- * 1999, describes these PAUSE resolution bits and how flow +- * control is determined based upon these settings. +- * NOTE: DC = Don't Care +- * +- * LOCAL DEVICE | LINK PARTNER +- * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution +- *-------|---------|-------|---------|-------------------- +- * 0 | 0 | DC | DC | e1000_fc_none +- * 0 | 1 | 0 | DC | e1000_fc_none +- * 0 | 1 | 1 | 0 | e1000_fc_none +- * 0 | 1 | 1 | 1 | e1000_fc_tx_pause +- * 1 | 0 | 0 | DC | e1000_fc_none +- * 1 | DC | 1 | DC | e1000_fc_full +- * 1 | 1 | 0 | 0 | e1000_fc_none +- * 1 | 1 | 0 | 1 | e1000_fc_rx_pause +- * +- * Are both PAUSE bits set to 1? If so, this implies +- * Symmetric Flow Control is enabled at both ends. The +- * ASM_DIR bits are irrelevant per the spec. +- * +- * For Symmetric Flow Control: +- * +- * LOCAL DEVICE | LINK PARTNER +- * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result +- *-------|---------|-------|---------|-------------------- +- * 1 | DC | 1 | DC | E1000_fc_full +- * +- */ +- if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && +- (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { +- /* +- * Now we need to check if the user selected Rx ONLY +- * of pause frames. In this case, we had to advertise +- * FULL flow control because we could not advertise Rx +- * ONLY. Hence, we must now check to see if we need to +- * turn OFF the TRANSMISSION of PAUSE frames. +- */ +- if (hw->fc.requested_mode == e1000_fc_full) { +- hw->fc.current_mode = e1000_fc_full; +- e_dbg("Flow Control = FULL.\r\n"); +- } else { +- hw->fc.current_mode = e1000_fc_rx_pause; +- e_dbg("Flow Control = " +- "Rx PAUSE frames only.\r\n"); +- } +- } +- /* +- * For receiving PAUSE frames ONLY. +- * +- * LOCAL DEVICE | LINK PARTNER +- * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result +- *-------|---------|-------|---------|-------------------- +- * 0 | 1 | 1 | 1 | e1000_fc_tx_pause +- */ +- else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && +- (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && +- (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && +- (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { +- hw->fc.current_mode = e1000_fc_tx_pause; +- e_dbg("Flow Control = Tx PAUSE frames only.\r\n"); +- } +- /* +- * For transmitting PAUSE frames ONLY. +- * +- * LOCAL DEVICE | LINK PARTNER +- * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result +- *-------|---------|-------|---------|-------------------- +- * 1 | 1 | 0 | 1 | e1000_fc_rx_pause +- */ +- else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && +- (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && +- !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && +- (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { +- hw->fc.current_mode = e1000_fc_rx_pause; +- e_dbg("Flow Control = Rx PAUSE frames only.\r\n"); +- } else { +- /* +- * Per the IEEE spec, at this point flow control +- * should be disabled. +- */ +- hw->fc.current_mode = e1000_fc_none; +- e_dbg("Flow Control = NONE.\r\n"); +- } +- +- /* +- * Now we need to do one last check... If we auto- +- * negotiated to HALF DUPLEX, flow control should not be +- * enabled per IEEE 802.3 spec. +- */ +- ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); +- if (ret_val) { +- e_dbg("Error getting link speed and duplex\n"); +- return ret_val; +- } +- +- if (duplex == HALF_DUPLEX) +- hw->fc.current_mode = e1000_fc_none; +- +- /* +- * Now we call a subroutine to actually force the MAC +- * controller to use the correct flow control settings. +- */ +- ret_val = e1000e_force_mac_fc(hw); +- if (ret_val) { +- e_dbg("Error forcing flow control settings\n"); +- return ret_val; +- } +- } +- +- return 0; +-} +- +-/** +- * e1000e_get_speed_and_duplex_copper - Retrieve current speed/duplex +- * @hw: pointer to the HW structure +- * @speed: stores the current speed +- * @duplex: stores the current duplex +- * +- * Read the status register for the current speed/duplex and store the current +- * speed and duplex for copper connections. +- **/ +-s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex) +-{ +- u32 status; +- +- status = er32(STATUS); +- if (status & E1000_STATUS_SPEED_1000) +- *speed = SPEED_1000; +- else if (status & E1000_STATUS_SPEED_100) +- *speed = SPEED_100; +- else +- *speed = SPEED_10; +- +- if (status & E1000_STATUS_FD) +- *duplex = FULL_DUPLEX; +- else +- *duplex = HALF_DUPLEX; +- +- e_dbg("%u Mbps, %s Duplex\n", +- *speed == SPEED_1000 ? 1000 : *speed == SPEED_100 ? 100 : 10, +- *duplex == FULL_DUPLEX ? "Full" : "Half"); +- +- return 0; +-} +- +-/** +- * e1000e_get_speed_and_duplex_fiber_serdes - Retrieve current speed/duplex +- * @hw: pointer to the HW structure +- * @speed: stores the current speed +- * @duplex: stores the current duplex +- * +- * Sets the speed and duplex to gigabit full duplex (the only possible option) +- * for fiber/serdes links. +- **/ +-s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex) +-{ +- *speed = SPEED_1000; +- *duplex = FULL_DUPLEX; +- +- return 0; +-} +- +-/** +- * e1000e_get_hw_semaphore - Acquire hardware semaphore +- * @hw: pointer to the HW structure +- * +- * Acquire the HW semaphore to access the PHY or NVM +- **/ +-s32 e1000e_get_hw_semaphore(struct e1000_hw *hw) +-{ +- u32 swsm; +- s32 timeout = hw->nvm.word_size + 1; +- s32 i = 0; +- +- /* Get the SW semaphore */ +- while (i < timeout) { +- swsm = er32(SWSM); +- if (!(swsm & E1000_SWSM_SMBI)) +- break; +- +- udelay(50); +- i++; +- } +- +- if (i == timeout) { +- e_dbg("Driver can't access device - SMBI bit is set.\n"); +- return -E1000_ERR_NVM; +- } +- +- /* Get the FW semaphore. */ +- for (i = 0; i < timeout; i++) { +- swsm = er32(SWSM); +- ew32(SWSM, swsm | E1000_SWSM_SWESMBI); +- +- /* Semaphore acquired if bit latched */ +- if (er32(SWSM) & E1000_SWSM_SWESMBI) +- break; +- +- udelay(50); +- } +- +- if (i == timeout) { +- /* Release semaphores */ +- e1000e_put_hw_semaphore(hw); +- e_dbg("Driver can't access the NVM\n"); +- return -E1000_ERR_NVM; +- } +- +- return 0; +-} +- +-/** +- * e1000e_put_hw_semaphore - Release hardware semaphore +- * @hw: pointer to the HW structure +- * +- * Release hardware semaphore used to access the PHY or NVM +- **/ +-void e1000e_put_hw_semaphore(struct e1000_hw *hw) +-{ +- u32 swsm; +- +- swsm = er32(SWSM); +- swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); +- ew32(SWSM, swsm); +-} +- +-/** +- * e1000e_get_auto_rd_done - Check for auto read completion +- * @hw: pointer to the HW structure +- * +- * Check EEPROM for Auto Read done bit. +- **/ +-s32 e1000e_get_auto_rd_done(struct e1000_hw *hw) +-{ +- s32 i = 0; +- +- while (i < AUTO_READ_DONE_TIMEOUT) { +- if (er32(EECD) & E1000_EECD_AUTO_RD) +- break; +- usleep_range(1000, 2000); +- i++; +- } +- +- if (i == AUTO_READ_DONE_TIMEOUT) { +- e_dbg("Auto read by HW from NVM has not completed.\n"); +- return -E1000_ERR_RESET; +- } +- +- return 0; +-} +- +-/** +- * e1000e_valid_led_default - Verify a valid default LED config +- * @hw: pointer to the HW structure +- * @data: pointer to the NVM (EEPROM) +- * +- * Read the EEPROM for the current default LED configuration. If the +- * LED configuration is not valid, set to a valid LED configuration. +- **/ +-s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data) +-{ +- s32 ret_val; +- +- ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); +- if (ret_val) { +- e_dbg("NVM Read Error\n"); +- return ret_val; +- } +- +- if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) +- *data = ID_LED_DEFAULT; +- +- return 0; +-} +- +-/** +- * e1000e_id_led_init - +- * @hw: pointer to the HW structure +- * +- **/ +-s32 e1000e_id_led_init(struct e1000_hw *hw) +-{ +- struct e1000_mac_info *mac = &hw->mac; +- s32 ret_val; +- const u32 ledctl_mask = 0x000000FF; +- const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; +- const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; +- u16 data, i, temp; +- const u16 led_mask = 0x0F; +- +- ret_val = hw->nvm.ops.valid_led_default(hw, &data); +- if (ret_val) +- return ret_val; +- +- mac->ledctl_default = er32(LEDCTL); +- mac->ledctl_mode1 = mac->ledctl_default; +- mac->ledctl_mode2 = mac->ledctl_default; +- +- for (i = 0; i < 4; i++) { +- temp = (data >> (i << 2)) & led_mask; +- switch (temp) { +- case ID_LED_ON1_DEF2: +- case ID_LED_ON1_ON2: +- case ID_LED_ON1_OFF2: +- mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); +- mac->ledctl_mode1 |= ledctl_on << (i << 3); +- break; +- case ID_LED_OFF1_DEF2: +- case ID_LED_OFF1_ON2: +- case ID_LED_OFF1_OFF2: +- mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); +- mac->ledctl_mode1 |= ledctl_off << (i << 3); +- break; +- default: +- /* Do nothing */ +- break; +- } +- switch (temp) { +- case ID_LED_DEF1_ON2: +- case ID_LED_ON1_ON2: +- case ID_LED_OFF1_ON2: +- mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); +- mac->ledctl_mode2 |= ledctl_on << (i << 3); +- break; +- case ID_LED_DEF1_OFF2: +- case ID_LED_ON1_OFF2: +- case ID_LED_OFF1_OFF2: +- mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); +- mac->ledctl_mode2 |= ledctl_off << (i << 3); +- break; +- default: +- /* Do nothing */ +- break; +- } +- } +- +- return 0; +-} +- +-/** +- * e1000e_setup_led_generic - Configures SW controllable LED +- * @hw: pointer to the HW structure +- * +- * This prepares the SW controllable LED for use and saves the current state +- * of the LED so it can be later restored. +- **/ +-s32 e1000e_setup_led_generic(struct e1000_hw *hw) +-{ +- u32 ledctl; +- +- if (hw->mac.ops.setup_led != e1000e_setup_led_generic) +- return -E1000_ERR_CONFIG; +- +- if (hw->phy.media_type == e1000_media_type_fiber) { +- ledctl = er32(LEDCTL); +- hw->mac.ledctl_default = ledctl; +- /* Turn off LED0 */ +- ledctl &= ~(E1000_LEDCTL_LED0_IVRT | +- E1000_LEDCTL_LED0_BLINK | +- E1000_LEDCTL_LED0_MODE_MASK); +- ledctl |= (E1000_LEDCTL_MODE_LED_OFF << +- E1000_LEDCTL_LED0_MODE_SHIFT); +- ew32(LEDCTL, ledctl); +- } else if (hw->phy.media_type == e1000_media_type_copper) { +- ew32(LEDCTL, hw->mac.ledctl_mode1); +- } +- +- return 0; +-} +- +-/** +- * e1000e_cleanup_led_generic - Set LED config to default operation +- * @hw: pointer to the HW structure +- * +- * Remove the current LED configuration and set the LED configuration +- * to the default value, saved from the EEPROM. +- **/ +-s32 e1000e_cleanup_led_generic(struct e1000_hw *hw) +-{ +- ew32(LEDCTL, hw->mac.ledctl_default); +- return 0; +-} +- +-/** +- * e1000e_blink_led_generic - Blink LED +- * @hw: pointer to the HW structure +- * +- * Blink the LEDs which are set to be on. +- **/ +-s32 e1000e_blink_led_generic(struct e1000_hw *hw) +-{ +- u32 ledctl_blink = 0; +- u32 i; +- +- if (hw->phy.media_type == e1000_media_type_fiber) { +- /* always blink LED0 for PCI-E fiber */ +- ledctl_blink = E1000_LEDCTL_LED0_BLINK | +- (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); +- } else { +- /* +- * set the blink bit for each LED that's "on" (0x0E) +- * in ledctl_mode2 +- */ +- ledctl_blink = hw->mac.ledctl_mode2; +- for (i = 0; i < 4; i++) +- if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == +- E1000_LEDCTL_MODE_LED_ON) +- ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << +- (i * 8)); +- } +- +- ew32(LEDCTL, ledctl_blink); +- +- return 0; +-} +- +-/** +- * e1000e_led_on_generic - Turn LED on +- * @hw: pointer to the HW structure +- * +- * Turn LED on. +- **/ +-s32 e1000e_led_on_generic(struct e1000_hw *hw) +-{ +- u32 ctrl; +- +- switch (hw->phy.media_type) { +- case e1000_media_type_fiber: +- ctrl = er32(CTRL); +- ctrl &= ~E1000_CTRL_SWDPIN0; +- ctrl |= E1000_CTRL_SWDPIO0; +- ew32(CTRL, ctrl); +- break; +- case e1000_media_type_copper: +- ew32(LEDCTL, hw->mac.ledctl_mode2); +- break; +- default: +- break; +- } +- +- return 0; +-} +- +-/** +- * e1000e_led_off_generic - Turn LED off +- * @hw: pointer to the HW structure +- * +- * Turn LED off. +- **/ +-s32 e1000e_led_off_generic(struct e1000_hw *hw) +-{ +- u32 ctrl; +- +- switch (hw->phy.media_type) { +- case e1000_media_type_fiber: +- ctrl = er32(CTRL); +- ctrl |= E1000_CTRL_SWDPIN0; +- ctrl |= E1000_CTRL_SWDPIO0; +- ew32(CTRL, ctrl); +- break; +- case e1000_media_type_copper: +- ew32(LEDCTL, hw->mac.ledctl_mode1); +- break; +- default: +- break; +- } +- +- return 0; +-} +- +-/** +- * e1000e_set_pcie_no_snoop - Set PCI-express capabilities +- * @hw: pointer to the HW structure +- * @no_snoop: bitmap of snoop events +- * +- * Set the PCI-express register to snoop for events enabled in 'no_snoop'. +- **/ +-void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop) +-{ +- u32 gcr; +- +- if (no_snoop) { +- gcr = er32(GCR); +- gcr &= ~(PCIE_NO_SNOOP_ALL); +- gcr |= no_snoop; +- ew32(GCR, gcr); +- } +-} +- +-/** +- * e1000e_disable_pcie_master - Disables PCI-express master access +- * @hw: pointer to the HW structure +- * +- * Returns 0 if successful, else returns -10 +- * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused +- * the master requests to be disabled. +- * +- * Disables PCI-Express master access and verifies there are no pending +- * requests. +- **/ +-s32 e1000e_disable_pcie_master(struct e1000_hw *hw) +-{ +- u32 ctrl; +- s32 timeout = MASTER_DISABLE_TIMEOUT; +- +- ctrl = er32(CTRL); +- ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; +- ew32(CTRL, ctrl); +- +- while (timeout) { +- if (!(er32(STATUS) & +- E1000_STATUS_GIO_MASTER_ENABLE)) +- break; +- udelay(100); +- timeout--; +- } +- +- if (!timeout) { +- e_dbg("Master requests are pending.\n"); +- return -E1000_ERR_MASTER_REQUESTS_PENDING; +- } +- +- return 0; +-} +- +-/** +- * e1000e_reset_adaptive - Reset Adaptive Interframe Spacing +- * @hw: pointer to the HW structure +- * +- * Reset the Adaptive Interframe Spacing throttle to default values. +- **/ +-void e1000e_reset_adaptive(struct e1000_hw *hw) +-{ +- struct e1000_mac_info *mac = &hw->mac; +- +- if (!mac->adaptive_ifs) { +- e_dbg("Not in Adaptive IFS mode!\n"); +- goto out; +- } +- +- mac->current_ifs_val = 0; +- mac->ifs_min_val = IFS_MIN; +- mac->ifs_max_val = IFS_MAX; +- mac->ifs_step_size = IFS_STEP; +- mac->ifs_ratio = IFS_RATIO; +- +- mac->in_ifs_mode = false; +- ew32(AIT, 0); +-out: +- return; +-} +- +-/** +- * e1000e_update_adaptive - Update Adaptive Interframe Spacing +- * @hw: pointer to the HW structure +- * +- * Update the Adaptive Interframe Spacing Throttle value based on the +- * time between transmitted packets and time between collisions. +- **/ +-void e1000e_update_adaptive(struct e1000_hw *hw) +-{ +- struct e1000_mac_info *mac = &hw->mac; +- +- if (!mac->adaptive_ifs) { +- e_dbg("Not in Adaptive IFS mode!\n"); +- goto out; +- } +- +- if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { +- if (mac->tx_packet_delta > MIN_NUM_XMITS) { +- mac->in_ifs_mode = true; +- if (mac->current_ifs_val < mac->ifs_max_val) { +- if (!mac->current_ifs_val) +- mac->current_ifs_val = mac->ifs_min_val; +- else +- mac->current_ifs_val += +- mac->ifs_step_size; +- ew32(AIT, mac->current_ifs_val); +- } +- } +- } else { +- if (mac->in_ifs_mode && +- (mac->tx_packet_delta <= MIN_NUM_XMITS)) { +- mac->current_ifs_val = 0; +- mac->in_ifs_mode = false; +- ew32(AIT, 0); +- } +- } +-out: +- return; +-} +- +-/** +- * e1000_raise_eec_clk - Raise EEPROM clock +- * @hw: pointer to the HW structure +- * @eecd: pointer to the EEPROM +- * +- * Enable/Raise the EEPROM clock bit. +- **/ +-static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) +-{ +- *eecd = *eecd | E1000_EECD_SK; +- ew32(EECD, *eecd); +- e1e_flush(); +- udelay(hw->nvm.delay_usec); +-} +- +-/** +- * e1000_lower_eec_clk - Lower EEPROM clock +- * @hw: pointer to the HW structure +- * @eecd: pointer to the EEPROM +- * +- * Clear/Lower the EEPROM clock bit. +- **/ +-static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) +-{ +- *eecd = *eecd & ~E1000_EECD_SK; +- ew32(EECD, *eecd); +- e1e_flush(); +- udelay(hw->nvm.delay_usec); +-} +- +-/** +- * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM +- * @hw: pointer to the HW structure +- * @data: data to send to the EEPROM +- * @count: number of bits to shift out +- * +- * We need to shift 'count' bits out to the EEPROM. So, the value in the +- * "data" parameter will be shifted out to the EEPROM one bit at a time. +- * In order to do this, "data" must be broken down into bits. +- **/ +-static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) +-{ +- struct e1000_nvm_info *nvm = &hw->nvm; +- u32 eecd = er32(EECD); +- u32 mask; +- +- mask = 0x01 << (count - 1); +- if (nvm->type == e1000_nvm_eeprom_spi) +- eecd |= E1000_EECD_DO; +- +- do { +- eecd &= ~E1000_EECD_DI; +- +- if (data & mask) +- eecd |= E1000_EECD_DI; +- +- ew32(EECD, eecd); +- e1e_flush(); +- +- udelay(nvm->delay_usec); +- +- e1000_raise_eec_clk(hw, &eecd); +- e1000_lower_eec_clk(hw, &eecd); +- +- mask >>= 1; +- } while (mask); +- +- eecd &= ~E1000_EECD_DI; +- ew32(EECD, eecd); +-} +- +-/** +- * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM +- * @hw: pointer to the HW structure +- * @count: number of bits to shift in +- * +- * In order to read a register from the EEPROM, we need to shift 'count' bits +- * in from the EEPROM. Bits are "shifted in" by raising the clock input to +- * the EEPROM (setting the SK bit), and then reading the value of the data out +- * "DO" bit. During this "shifting in" process the data in "DI" bit should +- * always be clear. +- **/ +-static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) +-{ +- u32 eecd; +- u32 i; +- u16 data; +- +- eecd = er32(EECD); +- +- eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); +- data = 0; +- +- for (i = 0; i < count; i++) { +- data <<= 1; +- e1000_raise_eec_clk(hw, &eecd); +- +- eecd = er32(EECD); +- +- eecd &= ~E1000_EECD_DI; +- if (eecd & E1000_EECD_DO) +- data |= 1; +- +- e1000_lower_eec_clk(hw, &eecd); +- } +- +- return data; +-} +- +-/** +- * e1000e_poll_eerd_eewr_done - Poll for EEPROM read/write completion +- * @hw: pointer to the HW structure +- * @ee_reg: EEPROM flag for polling +- * +- * Polls the EEPROM status bit for either read or write completion based +- * upon the value of 'ee_reg'. +- **/ +-s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) +-{ +- u32 attempts = 100000; +- u32 i, reg = 0; +- +- for (i = 0; i < attempts; i++) { +- if (ee_reg == E1000_NVM_POLL_READ) +- reg = er32(EERD); +- else +- reg = er32(EEWR); +- +- if (reg & E1000_NVM_RW_REG_DONE) +- return 0; +- +- udelay(5); +- } +- +- return -E1000_ERR_NVM; +-} +- +-/** +- * e1000e_acquire_nvm - Generic request for access to EEPROM +- * @hw: pointer to the HW structure +- * +- * Set the EEPROM access request bit and wait for EEPROM access grant bit. +- * Return successful if access grant bit set, else clear the request for +- * EEPROM access and return -E1000_ERR_NVM (-1). +- **/ +-s32 e1000e_acquire_nvm(struct e1000_hw *hw) +-{ +- u32 eecd = er32(EECD); +- s32 timeout = E1000_NVM_GRANT_ATTEMPTS; +- +- ew32(EECD, eecd | E1000_EECD_REQ); +- eecd = er32(EECD); +- +- while (timeout) { +- if (eecd & E1000_EECD_GNT) +- break; +- udelay(5); +- eecd = er32(EECD); +- timeout--; +- } +- +- if (!timeout) { +- eecd &= ~E1000_EECD_REQ; +- ew32(EECD, eecd); +- e_dbg("Could not acquire NVM grant\n"); +- return -E1000_ERR_NVM; +- } +- +- return 0; +-} +- +-/** +- * e1000_standby_nvm - Return EEPROM to standby state +- * @hw: pointer to the HW structure +- * +- * Return the EEPROM to a standby state. +- **/ +-static void e1000_standby_nvm(struct e1000_hw *hw) +-{ +- struct e1000_nvm_info *nvm = &hw->nvm; +- u32 eecd = er32(EECD); +- +- if (nvm->type == e1000_nvm_eeprom_spi) { +- /* Toggle CS to flush commands */ +- eecd |= E1000_EECD_CS; +- ew32(EECD, eecd); +- e1e_flush(); +- udelay(nvm->delay_usec); +- eecd &= ~E1000_EECD_CS; +- ew32(EECD, eecd); +- e1e_flush(); +- udelay(nvm->delay_usec); +- } +-} +- +-/** +- * e1000_stop_nvm - Terminate EEPROM command +- * @hw: pointer to the HW structure +- * +- * Terminates the current command by inverting the EEPROM's chip select pin. +- **/ +-static void e1000_stop_nvm(struct e1000_hw *hw) +-{ +- u32 eecd; +- +- eecd = er32(EECD); +- if (hw->nvm.type == e1000_nvm_eeprom_spi) { +- /* Pull CS high */ +- eecd |= E1000_EECD_CS; +- e1000_lower_eec_clk(hw, &eecd); +- } +-} +- +-/** +- * e1000e_release_nvm - Release exclusive access to EEPROM +- * @hw: pointer to the HW structure +- * +- * Stop any current commands to the EEPROM and clear the EEPROM request bit. +- **/ +-void e1000e_release_nvm(struct e1000_hw *hw) +-{ +- u32 eecd; +- +- e1000_stop_nvm(hw); +- +- eecd = er32(EECD); +- eecd &= ~E1000_EECD_REQ; +- ew32(EECD, eecd); +-} +- +-/** +- * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write +- * @hw: pointer to the HW structure +- * +- * Setups the EEPROM for reading and writing. +- **/ +-static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) +-{ +- struct e1000_nvm_info *nvm = &hw->nvm; +- u32 eecd = er32(EECD); +- u8 spi_stat_reg; +- +- if (nvm->type == e1000_nvm_eeprom_spi) { +- u16 timeout = NVM_MAX_RETRY_SPI; +- +- /* Clear SK and CS */ +- eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); +- ew32(EECD, eecd); +- e1e_flush(); +- udelay(1); +- +- /* +- * Read "Status Register" repeatedly until the LSB is cleared. +- * The EEPROM will signal that the command has been completed +- * by clearing bit 0 of the internal status register. If it's +- * not cleared within 'timeout', then error out. +- */ +- while (timeout) { +- e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, +- hw->nvm.opcode_bits); +- spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); +- if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) +- break; +- +- udelay(5); +- e1000_standby_nvm(hw); +- timeout--; +- } +- +- if (!timeout) { +- e_dbg("SPI NVM Status error\n"); +- return -E1000_ERR_NVM; +- } +- } +- +- return 0; +-} +- +-/** +- * e1000e_read_nvm_eerd - Reads EEPROM using EERD register +- * @hw: pointer to the HW structure +- * @offset: offset of word in the EEPROM to read +- * @words: number of words to read +- * @data: word read from the EEPROM +- * +- * Reads a 16 bit word from the EEPROM using the EERD register. +- **/ +-s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +-{ +- struct e1000_nvm_info *nvm = &hw->nvm; +- u32 i, eerd = 0; +- s32 ret_val = 0; +- +- /* +- * A check for invalid values: offset too large, too many words, +- * too many words for the offset, and not enough words. +- */ +- if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || +- (words == 0)) { +- e_dbg("nvm parameter(s) out of bounds\n"); +- return -E1000_ERR_NVM; +- } +- +- for (i = 0; i < words; i++) { +- eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + +- E1000_NVM_RW_REG_START; +- +- ew32(EERD, eerd); +- ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); +- if (ret_val) +- break; +- +- data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA); +- } +- +- return ret_val; +-} +- +-/** +- * e1000e_write_nvm_spi - Write to EEPROM using SPI +- * @hw: pointer to the HW structure +- * @offset: offset within the EEPROM to be written to +- * @words: number of words to write +- * @data: 16 bit word(s) to be written to the EEPROM +- * +- * Writes data to EEPROM at offset using SPI interface. +- * +- * If e1000e_update_nvm_checksum is not called after this function , the +- * EEPROM will most likely contain an invalid checksum. +- **/ +-s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +-{ +- struct e1000_nvm_info *nvm = &hw->nvm; +- s32 ret_val; +- u16 widx = 0; +- +- /* +- * A check for invalid values: offset too large, too many words, +- * and not enough words. +- */ +- if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || +- (words == 0)) { +- e_dbg("nvm parameter(s) out of bounds\n"); +- return -E1000_ERR_NVM; +- } +- +- ret_val = nvm->ops.acquire(hw); +- if (ret_val) +- return ret_val; +- +- while (widx < words) { +- u8 write_opcode = NVM_WRITE_OPCODE_SPI; +- +- ret_val = e1000_ready_nvm_eeprom(hw); +- if (ret_val) { +- nvm->ops.release(hw); +- return ret_val; +- } +- +- e1000_standby_nvm(hw); +- +- /* Send the WRITE ENABLE command (8 bit opcode) */ +- e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, +- nvm->opcode_bits); +- +- e1000_standby_nvm(hw); +- +- /* +- * Some SPI eeproms use the 8th address bit embedded in the +- * opcode +- */ +- if ((nvm->address_bits == 8) && (offset >= 128)) +- write_opcode |= NVM_A8_OPCODE_SPI; +- +- /* Send the Write command (8-bit opcode + addr) */ +- e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); +- e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), +- nvm->address_bits); +- +- /* Loop to allow for up to whole page write of eeprom */ +- while (widx < words) { +- u16 word_out = data[widx]; +- word_out = (word_out >> 8) | (word_out << 8); +- e1000_shift_out_eec_bits(hw, word_out, 16); +- widx++; +- +- if ((((offset + widx) * 2) % nvm->page_size) == 0) { +- e1000_standby_nvm(hw); +- break; +- } +- } +- } +- +- usleep_range(10000, 20000); +- nvm->ops.release(hw); +- return 0; +-} +- +-/** +- * e1000_read_pba_string_generic - Read device part number +- * @hw: pointer to the HW structure +- * @pba_num: pointer to device part number +- * @pba_num_size: size of part number buffer +- * +- * Reads the product board assembly (PBA) number from the EEPROM and stores +- * the value in pba_num. +- **/ +-s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, +- u32 pba_num_size) +-{ +- s32 ret_val; +- u16 nvm_data; +- u16 pba_ptr; +- u16 offset; +- u16 length; +- +- if (pba_num == NULL) { +- e_dbg("PBA string buffer was null\n"); +- ret_val = E1000_ERR_INVALID_ARGUMENT; +- goto out; +- } +- +- ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); +- if (ret_val) { +- e_dbg("NVM Read Error\n"); +- goto out; +- } +- +- ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr); +- if (ret_val) { +- e_dbg("NVM Read Error\n"); +- goto out; +- } +- +- /* +- * if nvm_data is not ptr guard the PBA must be in legacy format which +- * means pba_ptr is actually our second data word for the PBA number +- * and we can decode it into an ascii string +- */ +- if (nvm_data != NVM_PBA_PTR_GUARD) { +- e_dbg("NVM PBA number is not stored as string\n"); +- +- /* we will need 11 characters to store the PBA */ +- if (pba_num_size < 11) { +- e_dbg("PBA string buffer too small\n"); +- return E1000_ERR_NO_SPACE; +- } +- +- /* extract hex string from data and pba_ptr */ +- pba_num[0] = (nvm_data >> 12) & 0xF; +- pba_num[1] = (nvm_data >> 8) & 0xF; +- pba_num[2] = (nvm_data >> 4) & 0xF; +- pba_num[3] = nvm_data & 0xF; +- pba_num[4] = (pba_ptr >> 12) & 0xF; +- pba_num[5] = (pba_ptr >> 8) & 0xF; +- pba_num[6] = '-'; +- pba_num[7] = 0; +- pba_num[8] = (pba_ptr >> 4) & 0xF; +- pba_num[9] = pba_ptr & 0xF; +- +- /* put a null character on the end of our string */ +- pba_num[10] = '\0'; +- +- /* switch all the data but the '-' to hex char */ +- for (offset = 0; offset < 10; offset++) { +- if (pba_num[offset] < 0xA) +- pba_num[offset] += '0'; +- else if (pba_num[offset] < 0x10) +- pba_num[offset] += 'A' - 0xA; +- } +- +- goto out; +- } +- +- ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length); +- if (ret_val) { +- e_dbg("NVM Read Error\n"); +- goto out; +- } +- +- if (length == 0xFFFF || length == 0) { +- e_dbg("NVM PBA number section invalid length\n"); +- ret_val = E1000_ERR_NVM_PBA_SECTION; +- goto out; +- } +- /* check if pba_num buffer is big enough */ +- if (pba_num_size < (((u32)length * 2) - 1)) { +- e_dbg("PBA string buffer too small\n"); +- ret_val = E1000_ERR_NO_SPACE; +- goto out; +- } +- +- /* trim pba length from start of string */ +- pba_ptr++; +- length--; +- +- for (offset = 0; offset < length; offset++) { +- ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data); +- if (ret_val) { +- e_dbg("NVM Read Error\n"); +- goto out; +- } +- pba_num[offset * 2] = (u8)(nvm_data >> 8); +- pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF); +- } +- pba_num[offset * 2] = '\0'; +- +-out: +- return ret_val; +-} +- +-/** +- * e1000_read_mac_addr_generic - Read device MAC address +- * @hw: pointer to the HW structure +- * +- * Reads the device MAC address from the EEPROM and stores the value. +- * Since devices with two ports use the same EEPROM, we increment the +- * last bit in the MAC address for the second port. +- **/ +-s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) +-{ +- u32 rar_high; +- u32 rar_low; +- u16 i; +- +- rar_high = er32(RAH(0)); +- rar_low = er32(RAL(0)); +- +- for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) +- hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8)); +- +- for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) +- hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8)); +- +- for (i = 0; i < ETH_ALEN; i++) +- hw->mac.addr[i] = hw->mac.perm_addr[i]; +- +- return 0; +-} +- +-/** +- * e1000e_validate_nvm_checksum_generic - Validate EEPROM checksum +- * @hw: pointer to the HW structure +- * +- * Calculates the EEPROM checksum by reading/adding each word of the EEPROM +- * and then verifies that the sum of the EEPROM is equal to 0xBABA. +- **/ +-s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw) +-{ +- s32 ret_val; +- u16 checksum = 0; +- u16 i, nvm_data; +- +- for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { +- ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); +- if (ret_val) { +- e_dbg("NVM Read Error\n"); +- return ret_val; +- } +- checksum += nvm_data; +- } +- +- if (checksum != (u16) NVM_SUM) { +- e_dbg("NVM Checksum Invalid\n"); +- return -E1000_ERR_NVM; +- } +- +- return 0; +-} +- +-/** +- * e1000e_update_nvm_checksum_generic - Update EEPROM checksum +- * @hw: pointer to the HW structure +- * +- * Updates the EEPROM checksum by reading/adding each word of the EEPROM +- * up to the checksum. Then calculates the EEPROM checksum and writes the +- * value to the EEPROM. +- **/ +-s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw) +-{ +- s32 ret_val; +- u16 checksum = 0; +- u16 i, nvm_data; +- +- for (i = 0; i < NVM_CHECKSUM_REG; i++) { +- ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); +- if (ret_val) { +- e_dbg("NVM Read Error while updating checksum.\n"); +- return ret_val; +- } +- checksum += nvm_data; +- } +- checksum = (u16) NVM_SUM - checksum; +- ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum); +- if (ret_val) +- e_dbg("NVM Write Error while updating checksum.\n"); +- +- return ret_val; +-} +- +-/** +- * e1000e_reload_nvm - Reloads EEPROM +- * @hw: pointer to the HW structure +- * +- * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the +- * extended control register. +- **/ +-void e1000e_reload_nvm(struct e1000_hw *hw) +-{ +- u32 ctrl_ext; +- +- udelay(10); +- ctrl_ext = er32(CTRL_EXT); +- ctrl_ext |= E1000_CTRL_EXT_EE_RST; +- ew32(CTRL_EXT, ctrl_ext); +- e1e_flush(); +-} +- +-/** +- * e1000_calculate_checksum - Calculate checksum for buffer +- * @buffer: pointer to EEPROM +- * @length: size of EEPROM to calculate a checksum for +- * +- * Calculates the checksum for some buffer on a specified length. The +- * checksum calculated is returned. +- **/ +-static u8 e1000_calculate_checksum(u8 *buffer, u32 length) +-{ +- u32 i; +- u8 sum = 0; +- +- if (!buffer) +- return 0; +- +- for (i = 0; i < length; i++) +- sum += buffer[i]; +- +- return (u8) (0 - sum); +-} +- +-/** +- * e1000_mng_enable_host_if - Checks host interface is enabled +- * @hw: pointer to the HW structure +- * +- * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND +- * +- * This function checks whether the HOST IF is enabled for command operation +- * and also checks whether the previous command is completed. It busy waits +- * in case of previous command is not completed. +- **/ +-static s32 e1000_mng_enable_host_if(struct e1000_hw *hw) +-{ +- u32 hicr; +- u8 i; +- +- if (!(hw->mac.arc_subsystem_valid)) { +- e_dbg("ARC subsystem not valid.\n"); +- return -E1000_ERR_HOST_INTERFACE_COMMAND; +- } +- +- /* Check that the host interface is enabled. */ +- hicr = er32(HICR); +- if ((hicr & E1000_HICR_EN) == 0) { +- e_dbg("E1000_HOST_EN bit disabled.\n"); +- return -E1000_ERR_HOST_INTERFACE_COMMAND; +- } +- /* check the previous command is completed */ +- for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { +- hicr = er32(HICR); +- if (!(hicr & E1000_HICR_C)) +- break; +- mdelay(1); +- } +- +- if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { +- e_dbg("Previous command timeout failed .\n"); +- return -E1000_ERR_HOST_INTERFACE_COMMAND; +- } +- +- return 0; +-} +- +-/** +- * e1000e_check_mng_mode_generic - check management mode +- * @hw: pointer to the HW structure +- * +- * Reads the firmware semaphore register and returns true (>0) if +- * manageability is enabled, else false (0). +- **/ +-bool e1000e_check_mng_mode_generic(struct e1000_hw *hw) +-{ +- u32 fwsm = er32(FWSM); +- +- return (fwsm & E1000_FWSM_MODE_MASK) == +- (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); +-} +- +-/** +- * e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx +- * @hw: pointer to the HW structure +- * +- * Enables packet filtering on transmit packets if manageability is enabled +- * and host interface is enabled. +- **/ +-bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw) +-{ +- struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; +- u32 *buffer = (u32 *)&hw->mng_cookie; +- u32 offset; +- s32 ret_val, hdr_csum, csum; +- u8 i, len; +- +- hw->mac.tx_pkt_filtering = true; +- +- /* No manageability, no filtering */ +- if (!e1000e_check_mng_mode(hw)) { +- hw->mac.tx_pkt_filtering = false; +- goto out; +- } +- +- /* +- * If we can't read from the host interface for whatever +- * reason, disable filtering. +- */ +- ret_val = e1000_mng_enable_host_if(hw); +- if (ret_val) { +- hw->mac.tx_pkt_filtering = false; +- goto out; +- } +- +- /* Read in the header. Length and offset are in dwords. */ +- len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; +- offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; +- for (i = 0; i < len; i++) +- *(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset + i); +- hdr_csum = hdr->checksum; +- hdr->checksum = 0; +- csum = e1000_calculate_checksum((u8 *)hdr, +- E1000_MNG_DHCP_COOKIE_LENGTH); +- /* +- * If either the checksums or signature don't match, then +- * the cookie area isn't considered valid, in which case we +- * take the safe route of assuming Tx filtering is enabled. +- */ +- if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) { +- hw->mac.tx_pkt_filtering = true; +- goto out; +- } +- +- /* Cookie area is valid, make the final check for filtering. */ +- if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) { +- hw->mac.tx_pkt_filtering = false; +- goto out; +- } +- +-out: +- return hw->mac.tx_pkt_filtering; +-} +- +-/** +- * e1000_mng_write_cmd_header - Writes manageability command header +- * @hw: pointer to the HW structure +- * @hdr: pointer to the host interface command header +- * +- * Writes the command header after does the checksum calculation. +- **/ +-static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, +- struct e1000_host_mng_command_header *hdr) +-{ +- u16 i, length = sizeof(struct e1000_host_mng_command_header); +- +- /* Write the whole command header structure with new checksum. */ +- +- hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); +- +- length >>= 2; +- /* Write the relevant command block into the ram area. */ +- for (i = 0; i < length; i++) { +- E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i, +- *((u32 *) hdr + i)); +- e1e_flush(); +- } +- +- return 0; +-} +- +-/** +- * e1000_mng_host_if_write - Write to the manageability host interface +- * @hw: pointer to the HW structure +- * @buffer: pointer to the host interface buffer +- * @length: size of the buffer +- * @offset: location in the buffer to write to +- * @sum: sum of the data (not checksum) +- * +- * This function writes the buffer content at the offset given on the host if. +- * It also does alignment considerations to do the writes in most efficient +- * way. Also fills up the sum of the buffer in *buffer parameter. +- **/ +-static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, +- u16 length, u16 offset, u8 *sum) +-{ +- u8 *tmp; +- u8 *bufptr = buffer; +- u32 data = 0; +- u16 remaining, i, j, prev_bytes; +- +- /* sum = only sum of the data and it is not checksum */ +- +- if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) +- return -E1000_ERR_PARAM; +- +- tmp = (u8 *)&data; +- prev_bytes = offset & 0x3; +- offset >>= 2; +- +- if (prev_bytes) { +- data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset); +- for (j = prev_bytes; j < sizeof(u32); j++) { +- *(tmp + j) = *bufptr++; +- *sum += *(tmp + j); +- } +- E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data); +- length -= j - prev_bytes; +- offset++; +- } +- +- remaining = length & 0x3; +- length -= remaining; +- +- /* Calculate length in DWORDs */ +- length >>= 2; +- +- /* +- * The device driver writes the relevant command block into the +- * ram area. +- */ +- for (i = 0; i < length; i++) { +- for (j = 0; j < sizeof(u32); j++) { +- *(tmp + j) = *bufptr++; +- *sum += *(tmp + j); +- } +- +- E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data); +- } +- if (remaining) { +- for (j = 0; j < sizeof(u32); j++) { +- if (j < remaining) +- *(tmp + j) = *bufptr++; +- else +- *(tmp + j) = 0; +- +- *sum += *(tmp + j); +- } +- E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data); +- } +- +- return 0; +-} +- +-/** +- * e1000e_mng_write_dhcp_info - Writes DHCP info to host interface +- * @hw: pointer to the HW structure +- * @buffer: pointer to the host interface +- * @length: size of the buffer +- * +- * Writes the DHCP information to the host interface. +- **/ +-s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length) +-{ +- struct e1000_host_mng_command_header hdr; +- s32 ret_val; +- u32 hicr; +- +- hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; +- hdr.command_length = length; +- hdr.reserved1 = 0; +- hdr.reserved2 = 0; +- hdr.checksum = 0; +- +- /* Enable the host interface */ +- ret_val = e1000_mng_enable_host_if(hw); +- if (ret_val) +- return ret_val; +- +- /* Populate the host interface with the contents of "buffer". */ +- ret_val = e1000_mng_host_if_write(hw, buffer, length, +- sizeof(hdr), &(hdr.checksum)); +- if (ret_val) +- return ret_val; +- +- /* Write the manageability command header */ +- ret_val = e1000_mng_write_cmd_header(hw, &hdr); +- if (ret_val) +- return ret_val; +- +- /* Tell the ARC a new command is pending. */ +- hicr = er32(HICR); +- ew32(HICR, hicr | E1000_HICR_C); +- +- return 0; +-} +- +-/** +- * e1000e_enable_mng_pass_thru - Check if management passthrough is needed +- * @hw: pointer to the HW structure +- * +- * Verifies the hardware needs to leave interface enabled so that frames can +- * be directed to and from the management interface. +- **/ +-bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw) +-{ +- u32 manc; +- u32 fwsm, factps; +- bool ret_val = false; +- +- manc = er32(MANC); +- +- if (!(manc & E1000_MANC_RCV_TCO_EN)) +- goto out; +- +- if (hw->mac.has_fwsm) { +- fwsm = er32(FWSM); +- factps = er32(FACTPS); +- +- if (!(factps & E1000_FACTPS_MNGCG) && +- ((fwsm & E1000_FWSM_MODE_MASK) == +- (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { +- ret_val = true; +- goto out; +- } +- } else if ((hw->mac.type == e1000_82574) || +- (hw->mac.type == e1000_82583)) { +- u16 data; +- +- factps = er32(FACTPS); +- e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); +- +- if (!(factps & E1000_FACTPS_MNGCG) && +- ((data & E1000_NVM_INIT_CTRL2_MNGM) == +- (e1000_mng_mode_pt << 13))) { +- ret_val = true; +- goto out; +- } +- } else if ((manc & E1000_MANC_SMBUS_EN) && +- !(manc & E1000_MANC_ASF_EN)) { +- ret_val = true; +- goto out; +- } +- +-out: +- return ret_val; +-} +diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c +new file mode 100644 +index 0000000..2480c10 +--- /dev/null ++++ b/drivers/net/ethernet/intel/e1000e/mac.c +@@ -0,0 +1,1801 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#include "e1000.h" ++ ++/** ++ * e1000e_get_bus_info_pcie - Get PCIe bus information ++ * @hw: pointer to the HW structure ++ * ++ * Determines and stores the system bus information for a particular ++ * network interface. The following bus information is determined and stored: ++ * bus speed, bus width, type (PCIe), and PCIe function. ++ **/ ++s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ struct e1000_bus_info *bus = &hw->bus; ++ struct e1000_adapter *adapter = hw->adapter; ++ u16 pcie_link_status, cap_offset; ++ ++ cap_offset = adapter->pdev->pcie_cap; ++ if (!cap_offset) { ++ bus->width = e1000_bus_width_unknown; ++ } else { ++ pci_read_config_word(adapter->pdev, ++ cap_offset + PCIE_LINK_STATUS, ++ &pcie_link_status); ++ bus->width = (enum e1000_bus_width)((pcie_link_status & ++ PCIE_LINK_WIDTH_MASK) >> ++ PCIE_LINK_WIDTH_SHIFT); ++ } ++ ++ mac->ops.set_lan_id(hw); ++ ++ return 0; ++} ++ ++/** ++ * e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices ++ * ++ * @hw: pointer to the HW structure ++ * ++ * Determines the LAN function id by reading memory-mapped registers ++ * and swaps the port value if requested. ++ **/ ++void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) ++{ ++ struct e1000_bus_info *bus = &hw->bus; ++ u32 reg; ++ ++ /* The status register reports the correct function number ++ * for the device regardless of function swap state. ++ */ ++ reg = er32(STATUS); ++ bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; ++} ++ ++/** ++ * e1000_set_lan_id_single_port - Set LAN id for a single port device ++ * @hw: pointer to the HW structure ++ * ++ * Sets the LAN function id to zero for a single port device. ++ **/ ++void e1000_set_lan_id_single_port(struct e1000_hw *hw) ++{ ++ struct e1000_bus_info *bus = &hw->bus; ++ ++ bus->func = 0; ++} ++ ++/** ++ * e1000_clear_vfta_generic - Clear VLAN filter table ++ * @hw: pointer to the HW structure ++ * ++ * Clears the register array which contains the VLAN filter table by ++ * setting all the values to 0. ++ **/ ++void e1000_clear_vfta_generic(struct e1000_hw *hw) ++{ ++ u32 offset; ++ ++ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { ++ E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); ++ e1e_flush(); ++ } ++} ++ ++/** ++ * e1000_write_vfta_generic - Write value to VLAN filter table ++ * @hw: pointer to the HW structure ++ * @offset: register offset in VLAN filter table ++ * @value: register value written to VLAN filter table ++ * ++ * Writes value at the given offset in the register array which stores ++ * the VLAN filter table. ++ **/ ++void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) ++{ ++ E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); ++ e1e_flush(); ++} ++ ++/** ++ * e1000e_init_rx_addrs - Initialize receive address's ++ * @hw: pointer to the HW structure ++ * @rar_count: receive address registers ++ * ++ * Setup the receive address registers by setting the base receive address ++ * register to the devices MAC address and clearing all the other receive ++ * address registers to 0. ++ **/ ++void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count) ++{ ++ u32 i; ++ u8 mac_addr[ETH_ALEN] = { 0 }; ++ ++ /* Setup the receive address */ ++ e_dbg("Programming MAC Address into RAR[0]\n"); ++ ++ hw->mac.ops.rar_set(hw, hw->mac.addr, 0); ++ ++ /* Zero out the other (rar_entry_count - 1) receive addresses */ ++ e_dbg("Clearing RAR[1-%u]\n", rar_count - 1); ++ for (i = 1; i < rar_count; i++) ++ hw->mac.ops.rar_set(hw, mac_addr, i); ++} ++ ++/** ++ * e1000_check_alt_mac_addr_generic - Check for alternate MAC addr ++ * @hw: pointer to the HW structure ++ * ++ * Checks the nvm for an alternate MAC address. An alternate MAC address ++ * can be setup by pre-boot software and must be treated like a permanent ++ * address and must override the actual permanent MAC address. If an ++ * alternate MAC address is found it is programmed into RAR0, replacing ++ * the permanent address that was installed into RAR0 by the Si on reset. ++ * This function will return SUCCESS unless it encounters an error while ++ * reading the EEPROM. ++ **/ ++s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) ++{ ++ u32 i; ++ s32 ret_val; ++ u16 offset, nvm_alt_mac_addr_offset, nvm_data; ++ u8 alt_mac_addr[ETH_ALEN]; ++ ++ ret_val = e1000_read_nvm(hw, NVM_COMPAT, 1, &nvm_data); ++ if (ret_val) ++ return ret_val; ++ ++ /* not supported on 82573 */ ++ if (hw->mac.type == e1000_82573) ++ return 0; ++ ++ ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, ++ &nvm_alt_mac_addr_offset); ++ if (ret_val) { ++ e_dbg("NVM Read Error\n"); ++ return ret_val; ++ } ++ ++ if ((nvm_alt_mac_addr_offset == 0xFFFF) || ++ (nvm_alt_mac_addr_offset == 0x0000)) ++ /* There is no Alternate MAC Address */ ++ return 0; ++ ++ if (hw->bus.func == E1000_FUNC_1) ++ nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; ++ for (i = 0; i < ETH_ALEN; i += 2) { ++ offset = nvm_alt_mac_addr_offset + (i >> 1); ++ ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data); ++ if (ret_val) { ++ e_dbg("NVM Read Error\n"); ++ return ret_val; ++ } ++ ++ alt_mac_addr[i] = (u8)(nvm_data & 0xFF); ++ alt_mac_addr[i + 1] = (u8)(nvm_data >> 8); ++ } ++ ++ /* if multicast bit is set, the alternate address will not be used */ ++ if (is_multicast_ether_addr(alt_mac_addr)) { ++ e_dbg("Ignoring Alternate Mac Address with MC bit set\n"); ++ return 0; ++ } ++ ++ /* We have a valid alternate MAC address, and we want to treat it the ++ * same as the normal permanent MAC address stored by the HW into the ++ * RAR. Do this by mapping this address into RAR0. ++ */ ++ hw->mac.ops.rar_set(hw, alt_mac_addr, 0); ++ ++ return 0; ++} ++ ++/** ++ * e1000e_rar_set_generic - Set receive address register ++ * @hw: pointer to the HW structure ++ * @addr: pointer to the receive address ++ * @index: receive address array register ++ * ++ * Sets the receive address array register at index to the address passed ++ * in by addr. ++ **/ ++void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) ++{ ++ u32 rar_low, rar_high; ++ ++ /* HW expects these in little endian so we reverse the byte order ++ * from network order (big endian) to little endian ++ */ ++ rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) | ++ ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); ++ ++ rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); ++ ++ /* If MAC address zero, no need to set the AV bit */ ++ if (rar_low || rar_high) ++ rar_high |= E1000_RAH_AV; ++ ++ /* Some bridges will combine consecutive 32-bit writes into ++ * a single burst write, which will malfunction on some parts. ++ * The flushes avoid this. ++ */ ++ ew32(RAL(index), rar_low); ++ e1e_flush(); ++ ew32(RAH(index), rar_high); ++ e1e_flush(); ++} ++ ++/** ++ * e1000_hash_mc_addr - Generate a multicast hash value ++ * @hw: pointer to the HW structure ++ * @mc_addr: pointer to a multicast address ++ * ++ * Generates a multicast address hash value which is used to determine ++ * the multicast filter table array address and new table value. ++ **/ ++static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) ++{ ++ u32 hash_value, hash_mask; ++ u8 bit_shift = 0; ++ ++ /* Register count multiplied by bits per register */ ++ hash_mask = (hw->mac.mta_reg_count * 32) - 1; ++ ++ /* For a mc_filter_type of 0, bit_shift is the number of left-shifts ++ * where 0xFF would still fall within the hash mask. ++ */ ++ while (hash_mask >> bit_shift != 0xFF) ++ bit_shift++; ++ ++ /* The portion of the address that is used for the hash table ++ * is determined by the mc_filter_type setting. ++ * The algorithm is such that there is a total of 8 bits of shifting. ++ * The bit_shift for a mc_filter_type of 0 represents the number of ++ * left-shifts where the MSB of mc_addr[5] would still fall within ++ * the hash_mask. Case 0 does this exactly. Since there are a total ++ * of 8 bits of shifting, then mc_addr[4] will shift right the ++ * remaining number of bits. Thus 8 - bit_shift. The rest of the ++ * cases are a variation of this algorithm...essentially raising the ++ * number of bits to shift mc_addr[5] left, while still keeping the ++ * 8-bit shifting total. ++ * ++ * For example, given the following Destination MAC Address and an ++ * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask), ++ * we can see that the bit_shift for case 0 is 4. These are the hash ++ * values resulting from each mc_filter_type... ++ * [0] [1] [2] [3] [4] [5] ++ * 01 AA 00 12 34 56 ++ * LSB MSB ++ * ++ * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563 ++ * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6 ++ * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163 ++ * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 ++ */ ++ switch (hw->mac.mc_filter_type) { ++ default: ++ case 0: ++ break; ++ case 1: ++ bit_shift += 1; ++ break; ++ case 2: ++ bit_shift += 2; ++ break; ++ case 3: ++ bit_shift += 4; ++ break; ++ } ++ ++ hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | ++ (((u16)mc_addr[5]) << bit_shift))); ++ ++ return hash_value; ++} ++ ++/** ++ * e1000e_update_mc_addr_list_generic - Update Multicast addresses ++ * @hw: pointer to the HW structure ++ * @mc_addr_list: array of multicast addresses to program ++ * @mc_addr_count: number of multicast addresses to program ++ * ++ * Updates entire Multicast Table Array. ++ * The caller must have a packed mc_addr_list of multicast addresses. ++ **/ ++void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, ++ u8 *mc_addr_list, u32 mc_addr_count) ++{ ++ u32 hash_value, hash_bit, hash_reg; ++ int i; ++ ++ /* clear mta_shadow */ ++ memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); ++ ++ /* update mta_shadow from mc_addr_list */ ++ for (i = 0; (u32)i < mc_addr_count; i++) { ++ hash_value = e1000_hash_mc_addr(hw, mc_addr_list); ++ ++ hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); ++ hash_bit = hash_value & 0x1F; ++ ++ hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); ++ mc_addr_list += (ETH_ALEN); ++ } ++ ++ /* replace the entire MTA table */ ++ for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) ++ E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); ++ e1e_flush(); ++} ++ ++/** ++ * e1000e_clear_hw_cntrs_base - Clear base hardware counters ++ * @hw: pointer to the HW structure ++ * ++ * Clears the base hardware counters by reading the counter registers. ++ **/ ++void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw) ++{ ++ er32(CRCERRS); ++ er32(SYMERRS); ++ er32(MPC); ++ er32(SCC); ++ er32(ECOL); ++ er32(MCC); ++ er32(LATECOL); ++ er32(COLC); ++ er32(DC); ++ er32(SEC); ++ er32(RLEC); ++ er32(XONRXC); ++ er32(XONTXC); ++ er32(XOFFRXC); ++ er32(XOFFTXC); ++ er32(FCRUC); ++ er32(GPRC); ++ er32(BPRC); ++ er32(MPRC); ++ er32(GPTC); ++ er32(GORCL); ++ er32(GORCH); ++ er32(GOTCL); ++ er32(GOTCH); ++ er32(RNBC); ++ er32(RUC); ++ er32(RFC); ++ er32(ROC); ++ er32(RJC); ++ er32(TORL); ++ er32(TORH); ++ er32(TOTL); ++ er32(TOTH); ++ er32(TPR); ++ er32(TPT); ++ er32(MPTC); ++ er32(BPTC); ++} ++ ++/** ++ * e1000e_check_for_copper_link - Check for link (Copper) ++ * @hw: pointer to the HW structure ++ * ++ * Checks to see of the link status of the hardware has changed. If a ++ * change in link status has been detected, then we read the PHY registers ++ * to get the current speed/duplex if link exists. ++ **/ ++s32 e1000e_check_for_copper_link(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ s32 ret_val; ++ bool link; ++ ++ /* We only want to go out to the PHY registers to see if Auto-Neg ++ * has completed and/or if our link status has changed. The ++ * get_link_status flag is set upon receiving a Link Status ++ * Change or Rx Sequence Error interrupt. ++ */ ++ if (!mac->get_link_status) ++ return 0; ++ ++ /* First we want to see if the MII Status Register reports ++ * link. If so, then we want to get the current speed/duplex ++ * of the PHY. ++ */ ++ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); ++ if (ret_val) ++ return ret_val; ++ ++ if (!link) ++ return 0; /* No link detected */ ++ ++ mac->get_link_status = false; ++ ++ /* Check if there was DownShift, must be checked ++ * immediately after link-up ++ */ ++ e1000e_check_downshift(hw); ++ ++ /* If we are forcing speed/duplex, then we simply return since ++ * we have already determined whether we have link or not. ++ */ ++ if (!mac->autoneg) ++ return -E1000_ERR_CONFIG; ++ ++ /* Auto-Neg is enabled. Auto Speed Detection takes care ++ * of MAC speed/duplex configuration. So we only need to ++ * configure Collision Distance in the MAC. ++ */ ++ mac->ops.config_collision_dist(hw); ++ ++ /* Configure Flow Control now that Auto-Neg has completed. ++ * First, we need to restore the desired flow control ++ * settings because we may have had to re-autoneg with a ++ * different link partner. ++ */ ++ ret_val = e1000e_config_fc_after_link_up(hw); ++ if (ret_val) ++ e_dbg("Error configuring flow control\n"); ++ ++ return ret_val; ++} ++ ++/** ++ * e1000e_check_for_fiber_link - Check for link (Fiber) ++ * @hw: pointer to the HW structure ++ * ++ * Checks for link up on the hardware. If link is not up and we have ++ * a signal, then we need to force link up. ++ **/ ++s32 e1000e_check_for_fiber_link(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ u32 rxcw; ++ u32 ctrl; ++ u32 status; ++ s32 ret_val; ++ ++ ctrl = er32(CTRL); ++ status = er32(STATUS); ++ rxcw = er32(RXCW); ++ ++ /* If we don't have link (auto-negotiation failed or link partner ++ * cannot auto-negotiate), the cable is plugged in (we have signal), ++ * and our link partner is not trying to auto-negotiate with us (we ++ * are receiving idles or data), we need to force link up. We also ++ * need to give auto-negotiation time to complete, in case the cable ++ * was just plugged in. The autoneg_failed flag does this. ++ */ ++ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ ++ if ((ctrl & E1000_CTRL_SWDPIN1) && !(status & E1000_STATUS_LU) && ++ !(rxcw & E1000_RXCW_C)) { ++ if (!mac->autoneg_failed) { ++ mac->autoneg_failed = true; ++ return 0; ++ } ++ e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); ++ ++ /* Disable auto-negotiation in the TXCW register */ ++ ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); ++ ++ /* Force link-up and also force full-duplex. */ ++ ctrl = er32(CTRL); ++ ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); ++ ew32(CTRL, ctrl); ++ ++ /* Configure Flow Control after forcing link up. */ ++ ret_val = e1000e_config_fc_after_link_up(hw); ++ if (ret_val) { ++ e_dbg("Error configuring flow control\n"); ++ return ret_val; ++ } ++ } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { ++ /* If we are forcing link and we are receiving /C/ ordered ++ * sets, re-enable auto-negotiation in the TXCW register ++ * and disable forced link in the Device Control register ++ * in an attempt to auto-negotiate with our link partner. ++ */ ++ e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); ++ ew32(TXCW, mac->txcw); ++ ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); ++ ++ mac->serdes_has_link = true; ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_check_for_serdes_link - Check for link (Serdes) ++ * @hw: pointer to the HW structure ++ * ++ * Checks for link up on the hardware. If link is not up and we have ++ * a signal, then we need to force link up. ++ **/ ++s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ u32 rxcw; ++ u32 ctrl; ++ u32 status; ++ s32 ret_val; ++ ++ ctrl = er32(CTRL); ++ status = er32(STATUS); ++ rxcw = er32(RXCW); ++ ++ /* If we don't have link (auto-negotiation failed or link partner ++ * cannot auto-negotiate), and our link partner is not trying to ++ * auto-negotiate with us (we are receiving idles or data), ++ * we need to force link up. We also need to give auto-negotiation ++ * time to complete. ++ */ ++ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ ++ if (!(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) { ++ if (!mac->autoneg_failed) { ++ mac->autoneg_failed = true; ++ return 0; ++ } ++ e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); ++ ++ /* Disable auto-negotiation in the TXCW register */ ++ ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); ++ ++ /* Force link-up and also force full-duplex. */ ++ ctrl = er32(CTRL); ++ ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); ++ ew32(CTRL, ctrl); ++ ++ /* Configure Flow Control after forcing link up. */ ++ ret_val = e1000e_config_fc_after_link_up(hw); ++ if (ret_val) { ++ e_dbg("Error configuring flow control\n"); ++ return ret_val; ++ } ++ } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { ++ /* If we are forcing link and we are receiving /C/ ordered ++ * sets, re-enable auto-negotiation in the TXCW register ++ * and disable forced link in the Device Control register ++ * in an attempt to auto-negotiate with our link partner. ++ */ ++ e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); ++ ew32(TXCW, mac->txcw); ++ ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); ++ ++ mac->serdes_has_link = true; ++ } else if (!(E1000_TXCW_ANE & er32(TXCW))) { ++ /* If we force link for non-auto-negotiation switch, check ++ * link status based on MAC synchronization for internal ++ * serdes media type. ++ */ ++ /* SYNCH bit and IV bit are sticky. */ ++ usleep_range(10, 20); ++ rxcw = er32(RXCW); ++ if (rxcw & E1000_RXCW_SYNCH) { ++ if (!(rxcw & E1000_RXCW_IV)) { ++ mac->serdes_has_link = true; ++ e_dbg("SERDES: Link up - forced.\n"); ++ } ++ } else { ++ mac->serdes_has_link = false; ++ e_dbg("SERDES: Link down - force failed.\n"); ++ } ++ } ++ ++ if (E1000_TXCW_ANE & er32(TXCW)) { ++ status = er32(STATUS); ++ if (status & E1000_STATUS_LU) { ++ /* SYNCH bit and IV bit are sticky, so reread rxcw. */ ++ usleep_range(10, 20); ++ rxcw = er32(RXCW); ++ if (rxcw & E1000_RXCW_SYNCH) { ++ if (!(rxcw & E1000_RXCW_IV)) { ++ mac->serdes_has_link = true; ++ e_dbg("SERDES: Link up - autoneg completed successfully.\n"); ++ } else { ++ mac->serdes_has_link = false; ++ e_dbg("SERDES: Link down - invalid codewords detected in autoneg.\n"); ++ } ++ } else { ++ mac->serdes_has_link = false; ++ e_dbg("SERDES: Link down - no sync.\n"); ++ } ++ } else { ++ mac->serdes_has_link = false; ++ e_dbg("SERDES: Link down - autoneg failed\n"); ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000_set_default_fc_generic - Set flow control default values ++ * @hw: pointer to the HW structure ++ * ++ * Read the EEPROM for the default values for flow control and store the ++ * values. ++ **/ ++static s32 e1000_set_default_fc_generic(struct e1000_hw *hw) ++{ ++ s32 ret_val; ++ u16 nvm_data; ++ ++ /* Read and store word 0x0F of the EEPROM. This word contains bits ++ * that determine the hardware's default PAUSE (flow control) mode, ++ * a bit that determines whether the HW defaults to enabling or ++ * disabling auto-negotiation, and the direction of the ++ * SW defined pins. If there is no SW over-ride of the flow ++ * control setting, then the variable hw->fc will ++ * be initialized based on a value in the EEPROM. ++ */ ++ ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); ++ ++ if (ret_val) { ++ e_dbg("NVM Read Error\n"); ++ return ret_val; ++ } ++ ++ if (!(nvm_data & NVM_WORD0F_PAUSE_MASK)) ++ hw->fc.requested_mode = e1000_fc_none; ++ else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == NVM_WORD0F_ASM_DIR) ++ hw->fc.requested_mode = e1000_fc_tx_pause; ++ else ++ hw->fc.requested_mode = e1000_fc_full; ++ ++ return 0; ++} ++ ++/** ++ * e1000e_setup_link_generic - Setup flow control and link settings ++ * @hw: pointer to the HW structure ++ * ++ * Determines which flow control settings to use, then configures flow ++ * control. Calls the appropriate media-specific link configuration ++ * function. Assuming the adapter has a valid link partner, a valid link ++ * should be established. Assumes the hardware has previously been reset ++ * and the transmitter and receiver are not enabled. ++ **/ ++s32 e1000e_setup_link_generic(struct e1000_hw *hw) ++{ ++ s32 ret_val; ++ ++ /* In the case of the phy reset being blocked, we already have a link. ++ * We do not need to set it up again. ++ */ ++ if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) ++ return 0; ++ ++ /* If requested flow control is set to default, set flow control ++ * based on the EEPROM flow control settings. ++ */ ++ if (hw->fc.requested_mode == e1000_fc_default) { ++ ret_val = e1000_set_default_fc_generic(hw); ++ if (ret_val) ++ return ret_val; ++ } ++ ++ /* Save off the requested flow control mode for use later. Depending ++ * on the link partner's capabilities, we may or may not use this mode. ++ */ ++ hw->fc.current_mode = hw->fc.requested_mode; ++ ++ e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); ++ ++ /* Call the necessary media_type subroutine to configure the link. */ ++ ret_val = hw->mac.ops.setup_physical_interface(hw); ++ if (ret_val) ++ return ret_val; ++ ++ /* Initialize the flow control address, type, and PAUSE timer ++ * registers to their default values. This is done even if flow ++ * control is disabled, because it does not hurt anything to ++ * initialize these registers. ++ */ ++ e_dbg("Initializing the Flow Control address, type and timer regs\n"); ++ ew32(FCT, FLOW_CONTROL_TYPE); ++ ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH); ++ ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW); ++ ++ ew32(FCTTV, hw->fc.pause_time); ++ ++ return e1000e_set_fc_watermarks(hw); ++} ++ ++/** ++ * e1000_commit_fc_settings_generic - Configure flow control ++ * @hw: pointer to the HW structure ++ * ++ * Write the flow control settings to the Transmit Config Word Register (TXCW) ++ * base on the flow control settings in e1000_mac_info. ++ **/ ++static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ u32 txcw; ++ ++ /* Check for a software override of the flow control settings, and ++ * setup the device accordingly. If auto-negotiation is enabled, then ++ * software will have to set the "PAUSE" bits to the correct value in ++ * the Transmit Config Word Register (TXCW) and re-start auto- ++ * negotiation. However, if auto-negotiation is disabled, then ++ * software will have to manually configure the two flow control enable ++ * bits in the CTRL register. ++ * ++ * The possible values of the "fc" parameter are: ++ * 0: Flow control is completely disabled ++ * 1: Rx flow control is enabled (we can receive pause frames, ++ * but not send pause frames). ++ * 2: Tx flow control is enabled (we can send pause frames but we ++ * do not support receiving pause frames). ++ * 3: Both Rx and Tx flow control (symmetric) are enabled. ++ */ ++ switch (hw->fc.current_mode) { ++ case e1000_fc_none: ++ /* Flow control completely disabled by a software over-ride. */ ++ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); ++ break; ++ case e1000_fc_rx_pause: ++ /* Rx Flow control is enabled and Tx Flow control is disabled ++ * by a software over-ride. Since there really isn't a way to ++ * advertise that we are capable of Rx Pause ONLY, we will ++ * advertise that we support both symmetric and asymmetric Rx ++ * PAUSE. Later, we will disable the adapter's ability to send ++ * PAUSE frames. ++ */ ++ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); ++ break; ++ case e1000_fc_tx_pause: ++ /* Tx Flow control is enabled, and Rx Flow control is disabled, ++ * by a software over-ride. ++ */ ++ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); ++ break; ++ case e1000_fc_full: ++ /* Flow control (both Rx and Tx) is enabled by a software ++ * over-ride. ++ */ ++ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); ++ break; ++ default: ++ e_dbg("Flow control param set incorrectly\n"); ++ return -E1000_ERR_CONFIG; ++ break; ++ } ++ ++ ew32(TXCW, txcw); ++ mac->txcw = txcw; ++ ++ return 0; ++} ++ ++/** ++ * e1000_poll_fiber_serdes_link_generic - Poll for link up ++ * @hw: pointer to the HW structure ++ * ++ * Polls for link up by reading the status register, if link fails to come ++ * up with auto-negotiation, then the link is forced if a signal is detected. ++ **/ ++static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ u32 i, status; ++ s32 ret_val; ++ ++ /* If we have a signal (the cable is plugged in, or assumed true for ++ * serdes media) then poll for a "Link-Up" indication in the Device ++ * Status Register. Time-out if a link isn't seen in 500 milliseconds ++ * seconds (Auto-negotiation should complete in less than 500 ++ * milliseconds even if the other end is doing it in SW). ++ */ ++ for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { ++ usleep_range(10000, 20000); ++ status = er32(STATUS); ++ if (status & E1000_STATUS_LU) ++ break; ++ } ++ if (i == FIBER_LINK_UP_LIMIT) { ++ e_dbg("Never got a valid link from auto-neg!!!\n"); ++ mac->autoneg_failed = true; ++ /* AutoNeg failed to achieve a link, so we'll call ++ * mac->check_for_link. This routine will force the ++ * link up if we detect a signal. This will allow us to ++ * communicate with non-autonegotiating link partners. ++ */ ++ ret_val = mac->ops.check_for_link(hw); ++ if (ret_val) { ++ e_dbg("Error while checking for link\n"); ++ return ret_val; ++ } ++ mac->autoneg_failed = false; ++ } else { ++ mac->autoneg_failed = false; ++ e_dbg("Valid Link Found\n"); ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_setup_fiber_serdes_link - Setup link for fiber/serdes ++ * @hw: pointer to the HW structure ++ * ++ * Configures collision distance and flow control for fiber and serdes ++ * links. Upon successful setup, poll for link. ++ **/ ++s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw) ++{ ++ u32 ctrl; ++ s32 ret_val; ++ ++ ctrl = er32(CTRL); ++ ++ /* Take the link out of reset */ ++ ctrl &= ~E1000_CTRL_LRST; ++ ++ hw->mac.ops.config_collision_dist(hw); ++ ++ ret_val = e1000_commit_fc_settings_generic(hw); ++ if (ret_val) ++ return ret_val; ++ ++ /* Since auto-negotiation is enabled, take the link out of reset (the ++ * link will be in reset, because we previously reset the chip). This ++ * will restart auto-negotiation. If auto-negotiation is successful ++ * then the link-up status bit will be set and the flow control enable ++ * bits (RFCE and TFCE) will be set according to their negotiated value. ++ */ ++ e_dbg("Auto-negotiation enabled\n"); ++ ++ ew32(CTRL, ctrl); ++ e1e_flush(); ++ usleep_range(1000, 2000); ++ ++ /* For these adapters, the SW definable pin 1 is set when the optics ++ * detect a signal. If we have a signal, then poll for a "Link-Up" ++ * indication. ++ */ ++ if (hw->phy.media_type == e1000_media_type_internal_serdes || ++ (er32(CTRL) & E1000_CTRL_SWDPIN1)) { ++ ret_val = e1000_poll_fiber_serdes_link_generic(hw); ++ } else { ++ e_dbg("No signal detected\n"); ++ } ++ ++ return ret_val; ++} ++ ++/** ++ * e1000e_config_collision_dist_generic - Configure collision distance ++ * @hw: pointer to the HW structure ++ * ++ * Configures the collision distance to the default value and is used ++ * during link setup. ++ **/ ++void e1000e_config_collision_dist_generic(struct e1000_hw *hw) ++{ ++ u32 tctl; ++ ++ tctl = er32(TCTL); ++ ++ tctl &= ~E1000_TCTL_COLD; ++ tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; ++ ++ ew32(TCTL, tctl); ++ e1e_flush(); ++} ++ ++/** ++ * e1000e_set_fc_watermarks - Set flow control high/low watermarks ++ * @hw: pointer to the HW structure ++ * ++ * Sets the flow control high/low threshold (watermark) registers. If ++ * flow control XON frame transmission is enabled, then set XON frame ++ * transmission as well. ++ **/ ++s32 e1000e_set_fc_watermarks(struct e1000_hw *hw) ++{ ++ u32 fcrtl = 0, fcrth = 0; ++ ++ /* Set the flow control receive threshold registers. Normally, ++ * these registers will be set to a default threshold that may be ++ * adjusted later by the driver's runtime code. However, if the ++ * ability to transmit pause frames is not enabled, then these ++ * registers will be set to 0. ++ */ ++ if (hw->fc.current_mode & e1000_fc_tx_pause) { ++ /* We need to set up the Receive Threshold high and low water ++ * marks as well as (optionally) enabling the transmission of ++ * XON frames. ++ */ ++ fcrtl = hw->fc.low_water; ++ if (hw->fc.send_xon) ++ fcrtl |= E1000_FCRTL_XONE; ++ ++ fcrth = hw->fc.high_water; ++ } ++ ew32(FCRTL, fcrtl); ++ ew32(FCRTH, fcrth); ++ ++ return 0; ++} ++ ++/** ++ * e1000e_force_mac_fc - Force the MAC's flow control settings ++ * @hw: pointer to the HW structure ++ * ++ * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the ++ * device control register to reflect the adapter settings. TFCE and RFCE ++ * need to be explicitly set by software when a copper PHY is used because ++ * autonegotiation is managed by the PHY rather than the MAC. Software must ++ * also configure these bits when link is forced on a fiber connection. ++ **/ ++s32 e1000e_force_mac_fc(struct e1000_hw *hw) ++{ ++ u32 ctrl; ++ ++ ctrl = er32(CTRL); ++ ++ /* Because we didn't get link via the internal auto-negotiation ++ * mechanism (we either forced link or we got link via PHY ++ * auto-neg), we have to manually enable/disable transmit an ++ * receive flow control. ++ * ++ * The "Case" statement below enables/disable flow control ++ * according to the "hw->fc.current_mode" parameter. ++ * ++ * The possible values of the "fc" parameter are: ++ * 0: Flow control is completely disabled ++ * 1: Rx flow control is enabled (we can receive pause ++ * frames but not send pause frames). ++ * 2: Tx flow control is enabled (we can send pause frames ++ * frames but we do not receive pause frames). ++ * 3: Both Rx and Tx flow control (symmetric) is enabled. ++ * other: No other values should be possible at this point. ++ */ ++ e_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode); ++ ++ switch (hw->fc.current_mode) { ++ case e1000_fc_none: ++ ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); ++ break; ++ case e1000_fc_rx_pause: ++ ctrl &= (~E1000_CTRL_TFCE); ++ ctrl |= E1000_CTRL_RFCE; ++ break; ++ case e1000_fc_tx_pause: ++ ctrl &= (~E1000_CTRL_RFCE); ++ ctrl |= E1000_CTRL_TFCE; ++ break; ++ case e1000_fc_full: ++ ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); ++ break; ++ default: ++ e_dbg("Flow control param set incorrectly\n"); ++ return -E1000_ERR_CONFIG; ++ } ++ ++ ew32(CTRL, ctrl); ++ ++ return 0; ++} ++ ++/** ++ * e1000e_config_fc_after_link_up - Configures flow control after link ++ * @hw: pointer to the HW structure ++ * ++ * Checks the status of auto-negotiation after link up to ensure that the ++ * speed and duplex were not forced. If the link needed to be forced, then ++ * flow control needs to be forced also. If auto-negotiation is enabled ++ * and did not fail, then we configure flow control based on our link ++ * partner. ++ **/ ++s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ s32 ret_val = 0; ++ u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg; ++ u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; ++ u16 speed, duplex; ++ ++ /* Check for the case where we have fiber media and auto-neg failed ++ * so we had to force link. In this case, we need to force the ++ * configuration of the MAC to match the "fc" parameter. ++ */ ++ if (mac->autoneg_failed) { ++ if (hw->phy.media_type == e1000_media_type_fiber || ++ hw->phy.media_type == e1000_media_type_internal_serdes) ++ ret_val = e1000e_force_mac_fc(hw); ++ } else { ++ if (hw->phy.media_type == e1000_media_type_copper) ++ ret_val = e1000e_force_mac_fc(hw); ++ } ++ ++ if (ret_val) { ++ e_dbg("Error forcing flow control settings\n"); ++ return ret_val; ++ } ++ ++ /* Check for the case where we have copper media and auto-neg is ++ * enabled. In this case, we need to check and see if Auto-Neg ++ * has completed, and if so, how the PHY and link partner has ++ * flow control configured. ++ */ ++ if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { ++ /* Read the MII Status Register and check to see if AutoNeg ++ * has completed. We read this twice because this reg has ++ * some "sticky" (latched) bits. ++ */ ++ ret_val = e1e_rphy(hw, MII_BMSR, &mii_status_reg); ++ if (ret_val) ++ return ret_val; ++ ret_val = e1e_rphy(hw, MII_BMSR, &mii_status_reg); ++ if (ret_val) ++ return ret_val; ++ ++ if (!(mii_status_reg & BMSR_ANEGCOMPLETE)) { ++ e_dbg("Copper PHY and Auto Neg has not completed.\n"); ++ return ret_val; ++ } ++ ++ /* The AutoNeg process has completed, so we now need to ++ * read both the Auto Negotiation Advertisement ++ * Register (Address 4) and the Auto_Negotiation Base ++ * Page Ability Register (Address 5) to determine how ++ * flow control was negotiated. ++ */ ++ ret_val = e1e_rphy(hw, MII_ADVERTISE, &mii_nway_adv_reg); ++ if (ret_val) ++ return ret_val; ++ ret_val = e1e_rphy(hw, MII_LPA, &mii_nway_lp_ability_reg); ++ if (ret_val) ++ return ret_val; ++ ++ /* Two bits in the Auto Negotiation Advertisement Register ++ * (Address 4) and two bits in the Auto Negotiation Base ++ * Page Ability Register (Address 5) determine flow control ++ * for both the PHY and the link partner. The following ++ * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, ++ * 1999, describes these PAUSE resolution bits and how flow ++ * control is determined based upon these settings. ++ * NOTE: DC = Don't Care ++ * ++ * LOCAL DEVICE | LINK PARTNER ++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution ++ *-------|---------|-------|---------|-------------------- ++ * 0 | 0 | DC | DC | e1000_fc_none ++ * 0 | 1 | 0 | DC | e1000_fc_none ++ * 0 | 1 | 1 | 0 | e1000_fc_none ++ * 0 | 1 | 1 | 1 | e1000_fc_tx_pause ++ * 1 | 0 | 0 | DC | e1000_fc_none ++ * 1 | DC | 1 | DC | e1000_fc_full ++ * 1 | 1 | 0 | 0 | e1000_fc_none ++ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause ++ * ++ * Are both PAUSE bits set to 1? If so, this implies ++ * Symmetric Flow Control is enabled at both ends. The ++ * ASM_DIR bits are irrelevant per the spec. ++ * ++ * For Symmetric Flow Control: ++ * ++ * LOCAL DEVICE | LINK PARTNER ++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result ++ *-------|---------|-------|---------|-------------------- ++ * 1 | DC | 1 | DC | E1000_fc_full ++ * ++ */ ++ if ((mii_nway_adv_reg & ADVERTISE_PAUSE_CAP) && ++ (mii_nway_lp_ability_reg & LPA_PAUSE_CAP)) { ++ /* Now we need to check if the user selected Rx ONLY ++ * of pause frames. In this case, we had to advertise ++ * FULL flow control because we could not advertise Rx ++ * ONLY. Hence, we must now check to see if we need to ++ * turn OFF the TRANSMISSION of PAUSE frames. ++ */ ++ if (hw->fc.requested_mode == e1000_fc_full) { ++ hw->fc.current_mode = e1000_fc_full; ++ e_dbg("Flow Control = FULL.\n"); ++ } else { ++ hw->fc.current_mode = e1000_fc_rx_pause; ++ e_dbg("Flow Control = Rx PAUSE frames only.\n"); ++ } ++ } ++ /* For receiving PAUSE frames ONLY. ++ * ++ * LOCAL DEVICE | LINK PARTNER ++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result ++ *-------|---------|-------|---------|-------------------- ++ * 0 | 1 | 1 | 1 | e1000_fc_tx_pause ++ */ ++ else if (!(mii_nway_adv_reg & ADVERTISE_PAUSE_CAP) && ++ (mii_nway_adv_reg & ADVERTISE_PAUSE_ASYM) && ++ (mii_nway_lp_ability_reg & LPA_PAUSE_CAP) && ++ (mii_nway_lp_ability_reg & LPA_PAUSE_ASYM)) { ++ hw->fc.current_mode = e1000_fc_tx_pause; ++ e_dbg("Flow Control = Tx PAUSE frames only.\n"); ++ } ++ /* For transmitting PAUSE frames ONLY. ++ * ++ * LOCAL DEVICE | LINK PARTNER ++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result ++ *-------|---------|-------|---------|-------------------- ++ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause ++ */ ++ else if ((mii_nway_adv_reg & ADVERTISE_PAUSE_CAP) && ++ (mii_nway_adv_reg & ADVERTISE_PAUSE_ASYM) && ++ !(mii_nway_lp_ability_reg & LPA_PAUSE_CAP) && ++ (mii_nway_lp_ability_reg & LPA_PAUSE_ASYM)) { ++ hw->fc.current_mode = e1000_fc_rx_pause; ++ e_dbg("Flow Control = Rx PAUSE frames only.\n"); ++ } else { ++ /* Per the IEEE spec, at this point flow control ++ * should be disabled. ++ */ ++ hw->fc.current_mode = e1000_fc_none; ++ e_dbg("Flow Control = NONE.\n"); ++ } ++ ++ /* Now we need to do one last check... If we auto- ++ * negotiated to HALF DUPLEX, flow control should not be ++ * enabled per IEEE 802.3 spec. ++ */ ++ ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); ++ if (ret_val) { ++ e_dbg("Error getting link speed and duplex\n"); ++ return ret_val; ++ } ++ ++ if (duplex == HALF_DUPLEX) ++ hw->fc.current_mode = e1000_fc_none; ++ ++ /* Now we call a subroutine to actually force the MAC ++ * controller to use the correct flow control settings. ++ */ ++ ret_val = e1000e_force_mac_fc(hw); ++ if (ret_val) { ++ e_dbg("Error forcing flow control settings\n"); ++ return ret_val; ++ } ++ } ++ ++ /* Check for the case where we have SerDes media and auto-neg is ++ * enabled. In this case, we need to check and see if Auto-Neg ++ * has completed, and if so, how the PHY and link partner has ++ * flow control configured. ++ */ ++ if ((hw->phy.media_type == e1000_media_type_internal_serdes) && ++ mac->autoneg) { ++ /* Read the PCS_LSTS and check to see if AutoNeg ++ * has completed. ++ */ ++ pcs_status_reg = er32(PCS_LSTAT); ++ ++ if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) { ++ e_dbg("PCS Auto Neg has not completed.\n"); ++ return ret_val; ++ } ++ ++ /* The AutoNeg process has completed, so we now need to ++ * read both the Auto Negotiation Advertisement ++ * Register (PCS_ANADV) and the Auto_Negotiation Base ++ * Page Ability Register (PCS_LPAB) to determine how ++ * flow control was negotiated. ++ */ ++ pcs_adv_reg = er32(PCS_ANADV); ++ pcs_lp_ability_reg = er32(PCS_LPAB); ++ ++ /* Two bits in the Auto Negotiation Advertisement Register ++ * (PCS_ANADV) and two bits in the Auto Negotiation Base ++ * Page Ability Register (PCS_LPAB) determine flow control ++ * for both the PHY and the link partner. The following ++ * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, ++ * 1999, describes these PAUSE resolution bits and how flow ++ * control is determined based upon these settings. ++ * NOTE: DC = Don't Care ++ * ++ * LOCAL DEVICE | LINK PARTNER ++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution ++ *-------|---------|-------|---------|-------------------- ++ * 0 | 0 | DC | DC | e1000_fc_none ++ * 0 | 1 | 0 | DC | e1000_fc_none ++ * 0 | 1 | 1 | 0 | e1000_fc_none ++ * 0 | 1 | 1 | 1 | e1000_fc_tx_pause ++ * 1 | 0 | 0 | DC | e1000_fc_none ++ * 1 | DC | 1 | DC | e1000_fc_full ++ * 1 | 1 | 0 | 0 | e1000_fc_none ++ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause ++ * ++ * Are both PAUSE bits set to 1? If so, this implies ++ * Symmetric Flow Control is enabled at both ends. The ++ * ASM_DIR bits are irrelevant per the spec. ++ * ++ * For Symmetric Flow Control: ++ * ++ * LOCAL DEVICE | LINK PARTNER ++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result ++ *-------|---------|-------|---------|-------------------- ++ * 1 | DC | 1 | DC | e1000_fc_full ++ * ++ */ ++ if ((pcs_adv_reg & E1000_TXCW_PAUSE) && ++ (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) { ++ /* Now we need to check if the user selected Rx ONLY ++ * of pause frames. In this case, we had to advertise ++ * FULL flow control because we could not advertise Rx ++ * ONLY. Hence, we must now check to see if we need to ++ * turn OFF the TRANSMISSION of PAUSE frames. ++ */ ++ if (hw->fc.requested_mode == e1000_fc_full) { ++ hw->fc.current_mode = e1000_fc_full; ++ e_dbg("Flow Control = FULL.\n"); ++ } else { ++ hw->fc.current_mode = e1000_fc_rx_pause; ++ e_dbg("Flow Control = Rx PAUSE frames only.\n"); ++ } ++ } ++ /* For receiving PAUSE frames ONLY. ++ * ++ * LOCAL DEVICE | LINK PARTNER ++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result ++ *-------|---------|-------|---------|-------------------- ++ * 0 | 1 | 1 | 1 | e1000_fc_tx_pause ++ */ ++ else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) && ++ (pcs_adv_reg & E1000_TXCW_ASM_DIR) && ++ (pcs_lp_ability_reg & E1000_TXCW_PAUSE) && ++ (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { ++ hw->fc.current_mode = e1000_fc_tx_pause; ++ e_dbg("Flow Control = Tx PAUSE frames only.\n"); ++ } ++ /* For transmitting PAUSE frames ONLY. ++ * ++ * LOCAL DEVICE | LINK PARTNER ++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result ++ *-------|---------|-------|---------|-------------------- ++ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause ++ */ ++ else if ((pcs_adv_reg & E1000_TXCW_PAUSE) && ++ (pcs_adv_reg & E1000_TXCW_ASM_DIR) && ++ !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) && ++ (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { ++ hw->fc.current_mode = e1000_fc_rx_pause; ++ e_dbg("Flow Control = Rx PAUSE frames only.\n"); ++ } else { ++ /* Per the IEEE spec, at this point flow control ++ * should be disabled. ++ */ ++ hw->fc.current_mode = e1000_fc_none; ++ e_dbg("Flow Control = NONE.\n"); ++ } ++ ++ /* Now we call a subroutine to actually force the MAC ++ * controller to use the correct flow control settings. ++ */ ++ pcs_ctrl_reg = er32(PCS_LCTL); ++ pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL; ++ ew32(PCS_LCTL, pcs_ctrl_reg); ++ ++ ret_val = e1000e_force_mac_fc(hw); ++ if (ret_val) { ++ e_dbg("Error forcing flow control settings\n"); ++ return ret_val; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_get_speed_and_duplex_copper - Retrieve current speed/duplex ++ * @hw: pointer to the HW structure ++ * @speed: stores the current speed ++ * @duplex: stores the current duplex ++ * ++ * Read the status register for the current speed/duplex and store the current ++ * speed and duplex for copper connections. ++ **/ ++s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, ++ u16 *duplex) ++{ ++ u32 status; ++ ++ status = er32(STATUS); ++ if (status & E1000_STATUS_SPEED_1000) ++ *speed = SPEED_1000; ++ else if (status & E1000_STATUS_SPEED_100) ++ *speed = SPEED_100; ++ else ++ *speed = SPEED_10; ++ ++ if (status & E1000_STATUS_FD) ++ *duplex = FULL_DUPLEX; ++ else ++ *duplex = HALF_DUPLEX; ++ ++ e_dbg("%u Mbps, %s Duplex\n", ++ *speed == SPEED_1000 ? 1000 : *speed == SPEED_100 ? 100 : 10, ++ *duplex == FULL_DUPLEX ? "Full" : "Half"); ++ ++ return 0; ++} ++ ++/** ++ * e1000e_get_speed_and_duplex_fiber_serdes - Retrieve current speed/duplex ++ * @hw: pointer to the HW structure ++ * @speed: stores the current speed ++ * @duplex: stores the current duplex ++ * ++ * Sets the speed and duplex to gigabit full duplex (the only possible option) ++ * for fiber/serdes links. ++ **/ ++s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw __always_unused ++ *hw, u16 *speed, u16 *duplex) ++{ ++ *speed = SPEED_1000; ++ *duplex = FULL_DUPLEX; ++ ++ return 0; ++} ++ ++/** ++ * e1000e_get_hw_semaphore - Acquire hardware semaphore ++ * @hw: pointer to the HW structure ++ * ++ * Acquire the HW semaphore to access the PHY or NVM ++ **/ ++s32 e1000e_get_hw_semaphore(struct e1000_hw *hw) ++{ ++ u32 swsm; ++ s32 timeout = hw->nvm.word_size + 1; ++ s32 i = 0; ++ ++ /* Get the SW semaphore */ ++ while (i < timeout) { ++ swsm = er32(SWSM); ++ if (!(swsm & E1000_SWSM_SMBI)) ++ break; ++ ++ usleep_range(50, 100); ++ i++; ++ } ++ ++ if (i == timeout) { ++ e_dbg("Driver can't access device - SMBI bit is set.\n"); ++ return -E1000_ERR_NVM; ++ } ++ ++ /* Get the FW semaphore. */ ++ for (i = 0; i < timeout; i++) { ++ swsm = er32(SWSM); ++ ew32(SWSM, swsm | E1000_SWSM_SWESMBI); ++ ++ /* Semaphore acquired if bit latched */ ++ if (er32(SWSM) & E1000_SWSM_SWESMBI) ++ break; ++ ++ usleep_range(50, 100); ++ } ++ ++ if (i == timeout) { ++ /* Release semaphores */ ++ e1000e_put_hw_semaphore(hw); ++ e_dbg("Driver can't access the NVM\n"); ++ return -E1000_ERR_NVM; ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_put_hw_semaphore - Release hardware semaphore ++ * @hw: pointer to the HW structure ++ * ++ * Release hardware semaphore used to access the PHY or NVM ++ **/ ++void e1000e_put_hw_semaphore(struct e1000_hw *hw) ++{ ++ u32 swsm; ++ ++ swsm = er32(SWSM); ++ swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); ++ ew32(SWSM, swsm); ++} ++ ++/** ++ * e1000e_get_auto_rd_done - Check for auto read completion ++ * @hw: pointer to the HW structure ++ * ++ * Check EEPROM for Auto Read done bit. ++ **/ ++s32 e1000e_get_auto_rd_done(struct e1000_hw *hw) ++{ ++ s32 i = 0; ++ ++ while (i < AUTO_READ_DONE_TIMEOUT) { ++ if (er32(EECD) & E1000_EECD_AUTO_RD) ++ break; ++ usleep_range(1000, 2000); ++ i++; ++ } ++ ++ if (i == AUTO_READ_DONE_TIMEOUT) { ++ e_dbg("Auto read by HW from NVM has not completed.\n"); ++ return -E1000_ERR_RESET; ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_valid_led_default - Verify a valid default LED config ++ * @hw: pointer to the HW structure ++ * @data: pointer to the NVM (EEPROM) ++ * ++ * Read the EEPROM for the current default LED configuration. If the ++ * LED configuration is not valid, set to a valid LED configuration. ++ **/ ++s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data) ++{ ++ s32 ret_val; ++ ++ ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); ++ if (ret_val) { ++ e_dbg("NVM Read Error\n"); ++ return ret_val; ++ } ++ ++ if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) ++ *data = ID_LED_DEFAULT; ++ ++ return 0; ++} ++ ++/** ++ * e1000e_id_led_init_generic - ++ * @hw: pointer to the HW structure ++ * ++ **/ ++s32 e1000e_id_led_init_generic(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ s32 ret_val; ++ const u32 ledctl_mask = 0x000000FF; ++ const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; ++ const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; ++ u16 data, i, temp; ++ const u16 led_mask = 0x0F; ++ ++ ret_val = hw->nvm.ops.valid_led_default(hw, &data); ++ if (ret_val) ++ return ret_val; ++ ++ mac->ledctl_default = er32(LEDCTL); ++ mac->ledctl_mode1 = mac->ledctl_default; ++ mac->ledctl_mode2 = mac->ledctl_default; ++ ++ for (i = 0; i < 4; i++) { ++ temp = (data >> (i << 2)) & led_mask; ++ switch (temp) { ++ case ID_LED_ON1_DEF2: ++ case ID_LED_ON1_ON2: ++ case ID_LED_ON1_OFF2: ++ mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); ++ mac->ledctl_mode1 |= ledctl_on << (i << 3); ++ break; ++ case ID_LED_OFF1_DEF2: ++ case ID_LED_OFF1_ON2: ++ case ID_LED_OFF1_OFF2: ++ mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); ++ mac->ledctl_mode1 |= ledctl_off << (i << 3); ++ break; ++ default: ++ /* Do nothing */ ++ break; ++ } ++ switch (temp) { ++ case ID_LED_DEF1_ON2: ++ case ID_LED_ON1_ON2: ++ case ID_LED_OFF1_ON2: ++ mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); ++ mac->ledctl_mode2 |= ledctl_on << (i << 3); ++ break; ++ case ID_LED_DEF1_OFF2: ++ case ID_LED_ON1_OFF2: ++ case ID_LED_OFF1_OFF2: ++ mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); ++ mac->ledctl_mode2 |= ledctl_off << (i << 3); ++ break; ++ default: ++ /* Do nothing */ ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_setup_led_generic - Configures SW controllable LED ++ * @hw: pointer to the HW structure ++ * ++ * This prepares the SW controllable LED for use and saves the current state ++ * of the LED so it can be later restored. ++ **/ ++s32 e1000e_setup_led_generic(struct e1000_hw *hw) ++{ ++ u32 ledctl; ++ ++ if (hw->mac.ops.setup_led != e1000e_setup_led_generic) ++ return -E1000_ERR_CONFIG; ++ ++ if (hw->phy.media_type == e1000_media_type_fiber) { ++ ledctl = er32(LEDCTL); ++ hw->mac.ledctl_default = ledctl; ++ /* Turn off LED0 */ ++ ledctl &= ~(E1000_LEDCTL_LED0_IVRT | E1000_LEDCTL_LED0_BLINK | ++ E1000_LEDCTL_LED0_MODE_MASK); ++ ledctl |= (E1000_LEDCTL_MODE_LED_OFF << ++ E1000_LEDCTL_LED0_MODE_SHIFT); ++ ew32(LEDCTL, ledctl); ++ } else if (hw->phy.media_type == e1000_media_type_copper) { ++ ew32(LEDCTL, hw->mac.ledctl_mode1); ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_cleanup_led_generic - Set LED config to default operation ++ * @hw: pointer to the HW structure ++ * ++ * Remove the current LED configuration and set the LED configuration ++ * to the default value, saved from the EEPROM. ++ **/ ++s32 e1000e_cleanup_led_generic(struct e1000_hw *hw) ++{ ++ ew32(LEDCTL, hw->mac.ledctl_default); ++ return 0; ++} ++ ++/** ++ * e1000e_blink_led_generic - Blink LED ++ * @hw: pointer to the HW structure ++ * ++ * Blink the LEDs which are set to be on. ++ **/ ++s32 e1000e_blink_led_generic(struct e1000_hw *hw) ++{ ++ u32 ledctl_blink = 0; ++ u32 i; ++ ++ if (hw->phy.media_type == e1000_media_type_fiber) { ++ /* always blink LED0 for PCI-E fiber */ ++ ledctl_blink = E1000_LEDCTL_LED0_BLINK | ++ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); ++ } else { ++ /* Set the blink bit for each LED that's "on" (0x0E) ++ * (or "off" if inverted) in ledctl_mode2. The blink ++ * logic in hardware only works when mode is set to "on" ++ * so it must be changed accordingly when the mode is ++ * "off" and inverted. ++ */ ++ ledctl_blink = hw->mac.ledctl_mode2; ++ for (i = 0; i < 32; i += 8) { ++ u32 mode = (hw->mac.ledctl_mode2 >> i) & ++ E1000_LEDCTL_LED0_MODE_MASK; ++ u32 led_default = hw->mac.ledctl_default >> i; ++ ++ if ((!(led_default & E1000_LEDCTL_LED0_IVRT) && ++ (mode == E1000_LEDCTL_MODE_LED_ON)) || ++ ((led_default & E1000_LEDCTL_LED0_IVRT) && ++ (mode == E1000_LEDCTL_MODE_LED_OFF))) { ++ ledctl_blink &= ++ ~(E1000_LEDCTL_LED0_MODE_MASK << i); ++ ledctl_blink |= (E1000_LEDCTL_LED0_BLINK | ++ E1000_LEDCTL_MODE_LED_ON) << i; ++ } ++ } ++ } ++ ++ ew32(LEDCTL, ledctl_blink); ++ ++ return 0; ++} ++ ++/** ++ * e1000e_led_on_generic - Turn LED on ++ * @hw: pointer to the HW structure ++ * ++ * Turn LED on. ++ **/ ++s32 e1000e_led_on_generic(struct e1000_hw *hw) ++{ ++ u32 ctrl; ++ ++ switch (hw->phy.media_type) { ++ case e1000_media_type_fiber: ++ ctrl = er32(CTRL); ++ ctrl &= ~E1000_CTRL_SWDPIN0; ++ ctrl |= E1000_CTRL_SWDPIO0; ++ ew32(CTRL, ctrl); ++ break; ++ case e1000_media_type_copper: ++ ew32(LEDCTL, hw->mac.ledctl_mode2); ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_led_off_generic - Turn LED off ++ * @hw: pointer to the HW structure ++ * ++ * Turn LED off. ++ **/ ++s32 e1000e_led_off_generic(struct e1000_hw *hw) ++{ ++ u32 ctrl; ++ ++ switch (hw->phy.media_type) { ++ case e1000_media_type_fiber: ++ ctrl = er32(CTRL); ++ ctrl |= E1000_CTRL_SWDPIN0; ++ ctrl |= E1000_CTRL_SWDPIO0; ++ ew32(CTRL, ctrl); ++ break; ++ case e1000_media_type_copper: ++ ew32(LEDCTL, hw->mac.ledctl_mode1); ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_set_pcie_no_snoop - Set PCI-express capabilities ++ * @hw: pointer to the HW structure ++ * @no_snoop: bitmap of snoop events ++ * ++ * Set the PCI-express register to snoop for events enabled in 'no_snoop'. ++ **/ ++void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop) ++{ ++ u32 gcr; ++ ++ if (no_snoop) { ++ gcr = er32(GCR); ++ gcr &= ~(PCIE_NO_SNOOP_ALL); ++ gcr |= no_snoop; ++ ew32(GCR, gcr); ++ } ++} ++ ++/** ++ * e1000e_disable_pcie_master - Disables PCI-express master access ++ * @hw: pointer to the HW structure ++ * ++ * Returns 0 if successful, else returns -10 ++ * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused ++ * the master requests to be disabled. ++ * ++ * Disables PCI-Express master access and verifies there are no pending ++ * requests. ++ **/ ++s32 e1000e_disable_pcie_master(struct e1000_hw *hw) ++{ ++ u32 ctrl; ++ s32 timeout = MASTER_DISABLE_TIMEOUT; ++ ++ ctrl = er32(CTRL); ++ ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; ++ ew32(CTRL, ctrl); ++ ++ while (timeout) { ++ if (!(er32(STATUS) & E1000_STATUS_GIO_MASTER_ENABLE)) ++ break; ++ usleep_range(100, 200); ++ timeout--; ++ } ++ ++ if (!timeout) { ++ e_dbg("Master requests are pending.\n"); ++ return -E1000_ERR_MASTER_REQUESTS_PENDING; ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_reset_adaptive - Reset Adaptive Interframe Spacing ++ * @hw: pointer to the HW structure ++ * ++ * Reset the Adaptive Interframe Spacing throttle to default values. ++ **/ ++void e1000e_reset_adaptive(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ ++ if (!mac->adaptive_ifs) { ++ e_dbg("Not in Adaptive IFS mode!\n"); ++ return; ++ } ++ ++ mac->current_ifs_val = 0; ++ mac->ifs_min_val = IFS_MIN; ++ mac->ifs_max_val = IFS_MAX; ++ mac->ifs_step_size = IFS_STEP; ++ mac->ifs_ratio = IFS_RATIO; ++ ++ mac->in_ifs_mode = false; ++ ew32(AIT, 0); ++} ++ ++/** ++ * e1000e_update_adaptive - Update Adaptive Interframe Spacing ++ * @hw: pointer to the HW structure ++ * ++ * Update the Adaptive Interframe Spacing Throttle value based on the ++ * time between transmitted packets and time between collisions. ++ **/ ++void e1000e_update_adaptive(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ ++ if (!mac->adaptive_ifs) { ++ e_dbg("Not in Adaptive IFS mode!\n"); ++ return; ++ } ++ ++ if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { ++ if (mac->tx_packet_delta > MIN_NUM_XMITS) { ++ mac->in_ifs_mode = true; ++ if (mac->current_ifs_val < mac->ifs_max_val) { ++ if (!mac->current_ifs_val) ++ mac->current_ifs_val = mac->ifs_min_val; ++ else ++ mac->current_ifs_val += ++ mac->ifs_step_size; ++ ew32(AIT, mac->current_ifs_val); ++ } ++ } ++ } else { ++ if (mac->in_ifs_mode && ++ (mac->tx_packet_delta <= MIN_NUM_XMITS)) { ++ mac->current_ifs_val = 0; ++ mac->in_ifs_mode = false; ++ ew32(AIT, 0); ++ } ++ } ++} +diff --git a/drivers/net/ethernet/intel/e1000e/mac.h b/drivers/net/ethernet/intel/e1000e/mac.h +new file mode 100644 +index 0000000..a61fee4 +--- /dev/null ++++ b/drivers/net/ethernet/intel/e1000e/mac.h +@@ -0,0 +1,74 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#ifndef _E1000E_MAC_H_ ++#define _E1000E_MAC_H_ ++ ++s32 e1000e_blink_led_generic(struct e1000_hw *hw); ++s32 e1000e_check_for_copper_link(struct e1000_hw *hw); ++s32 e1000e_check_for_fiber_link(struct e1000_hw *hw); ++s32 e1000e_check_for_serdes_link(struct e1000_hw *hw); ++s32 e1000e_cleanup_led_generic(struct e1000_hw *hw); ++s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw); ++s32 e1000e_disable_pcie_master(struct e1000_hw *hw); ++s32 e1000e_force_mac_fc(struct e1000_hw *hw); ++s32 e1000e_get_auto_rd_done(struct e1000_hw *hw); ++s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw); ++void e1000_set_lan_id_single_port(struct e1000_hw *hw); ++s32 e1000e_get_hw_semaphore(struct e1000_hw *hw); ++s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, ++ u16 *duplex); ++s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, ++ u16 *speed, u16 *duplex); ++s32 e1000e_id_led_init_generic(struct e1000_hw *hw); ++s32 e1000e_led_on_generic(struct e1000_hw *hw); ++s32 e1000e_led_off_generic(struct e1000_hw *hw); ++void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, ++ u8 *mc_addr_list, u32 mc_addr_count); ++s32 e1000e_set_fc_watermarks(struct e1000_hw *hw); ++s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw); ++s32 e1000e_setup_led_generic(struct e1000_hw *hw); ++s32 e1000e_setup_link_generic(struct e1000_hw *hw); ++s32 e1000e_validate_mdi_setting_generic(struct e1000_hw *hw); ++s32 e1000e_validate_mdi_setting_crossover_generic(struct e1000_hw *hw); ++ ++void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw); ++void e1000_clear_vfta_generic(struct e1000_hw *hw); ++void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); ++void e1000e_put_hw_semaphore(struct e1000_hw *hw); ++s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); ++void e1000e_reset_adaptive(struct e1000_hw *hw); ++void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop); ++void e1000e_update_adaptive(struct e1000_hw *hw); ++void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); ++ ++void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); ++void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); ++void e1000e_config_collision_dist_generic(struct e1000_hw *hw); ++ ++#endif +diff --git a/drivers/net/ethernet/intel/e1000e/manage.c b/drivers/net/ethernet/intel/e1000e/manage.c +new file mode 100644 +index 0000000..e4b0f1e +--- /dev/null ++++ b/drivers/net/ethernet/intel/e1000e/manage.c +@@ -0,0 +1,351 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#include "e1000.h" ++ ++/** ++ * e1000_calculate_checksum - Calculate checksum for buffer ++ * @buffer: pointer to EEPROM ++ * @length: size of EEPROM to calculate a checksum for ++ * ++ * Calculates the checksum for some buffer on a specified length. The ++ * checksum calculated is returned. ++ **/ ++static u8 e1000_calculate_checksum(u8 *buffer, u32 length) ++{ ++ u32 i; ++ u8 sum = 0; ++ ++ if (!buffer) ++ return 0; ++ ++ for (i = 0; i < length; i++) ++ sum += buffer[i]; ++ ++ return (u8)(0 - sum); ++} ++ ++/** ++ * e1000_mng_enable_host_if - Checks host interface is enabled ++ * @hw: pointer to the HW structure ++ * ++ * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND ++ * ++ * This function checks whether the HOST IF is enabled for command operation ++ * and also checks whether the previous command is completed. It busy waits ++ * in case of previous command is not completed. ++ **/ ++static s32 e1000_mng_enable_host_if(struct e1000_hw *hw) ++{ ++ u32 hicr; ++ u8 i; ++ ++ if (!hw->mac.arc_subsystem_valid) { ++ e_dbg("ARC subsystem not valid.\n"); ++ return -E1000_ERR_HOST_INTERFACE_COMMAND; ++ } ++ ++ /* Check that the host interface is enabled. */ ++ hicr = er32(HICR); ++ if (!(hicr & E1000_HICR_EN)) { ++ e_dbg("E1000_HOST_EN bit disabled.\n"); ++ return -E1000_ERR_HOST_INTERFACE_COMMAND; ++ } ++ /* check the previous command is completed */ ++ for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { ++ hicr = er32(HICR); ++ if (!(hicr & E1000_HICR_C)) ++ break; ++ mdelay(1); ++ } ++ ++ if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { ++ e_dbg("Previous command timeout failed .\n"); ++ return -E1000_ERR_HOST_INTERFACE_COMMAND; ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_check_mng_mode_generic - Generic check management mode ++ * @hw: pointer to the HW structure ++ * ++ * Reads the firmware semaphore register and returns true (>0) if ++ * manageability is enabled, else false (0). ++ **/ ++bool e1000e_check_mng_mode_generic(struct e1000_hw *hw) ++{ ++ u32 fwsm = er32(FWSM); ++ ++ return (fwsm & E1000_FWSM_MODE_MASK) == ++ (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); ++} ++ ++/** ++ * e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx ++ * @hw: pointer to the HW structure ++ * ++ * Enables packet filtering on transmit packets if manageability is enabled ++ * and host interface is enabled. ++ **/ ++bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw) ++{ ++ struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; ++ u32 *buffer = (u32 *)&hw->mng_cookie; ++ u32 offset; ++ s32 ret_val, hdr_csum, csum; ++ u8 i, len; ++ ++ hw->mac.tx_pkt_filtering = true; ++ ++ /* No manageability, no filtering */ ++ if (!hw->mac.ops.check_mng_mode(hw)) { ++ hw->mac.tx_pkt_filtering = false; ++ return hw->mac.tx_pkt_filtering; ++ } ++ ++ /* If we can't read from the host interface for whatever ++ * reason, disable filtering. ++ */ ++ ret_val = e1000_mng_enable_host_if(hw); ++ if (ret_val) { ++ hw->mac.tx_pkt_filtering = false; ++ return hw->mac.tx_pkt_filtering; ++ } ++ ++ /* Read in the header. Length and offset are in dwords. */ ++ len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; ++ offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; ++ for (i = 0; i < len; i++) ++ *(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, ++ offset + i); ++ hdr_csum = hdr->checksum; ++ hdr->checksum = 0; ++ csum = e1000_calculate_checksum((u8 *)hdr, ++ E1000_MNG_DHCP_COOKIE_LENGTH); ++ /* If either the checksums or signature don't match, then ++ * the cookie area isn't considered valid, in which case we ++ * take the safe route of assuming Tx filtering is enabled. ++ */ ++ if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) { ++ hw->mac.tx_pkt_filtering = true; ++ return hw->mac.tx_pkt_filtering; ++ } ++ ++ /* Cookie area is valid, make the final check for filtering. */ ++ if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) ++ hw->mac.tx_pkt_filtering = false; ++ ++ return hw->mac.tx_pkt_filtering; ++} ++ ++/** ++ * e1000_mng_write_cmd_header - Writes manageability command header ++ * @hw: pointer to the HW structure ++ * @hdr: pointer to the host interface command header ++ * ++ * Writes the command header after does the checksum calculation. ++ **/ ++static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, ++ struct e1000_host_mng_command_header *hdr) ++{ ++ u16 i, length = sizeof(struct e1000_host_mng_command_header); ++ ++ /* Write the whole command header structure with new checksum. */ ++ ++ hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); ++ ++ length >>= 2; ++ /* Write the relevant command block into the ram area. */ ++ for (i = 0; i < length; i++) { ++ E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i, *((u32 *)hdr + i)); ++ e1e_flush(); ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000_mng_host_if_write - Write to the manageability host interface ++ * @hw: pointer to the HW structure ++ * @buffer: pointer to the host interface buffer ++ * @length: size of the buffer ++ * @offset: location in the buffer to write to ++ * @sum: sum of the data (not checksum) ++ * ++ * This function writes the buffer content at the offset given on the host if. ++ * It also does alignment considerations to do the writes in most efficient ++ * way. Also fills up the sum of the buffer in *buffer parameter. ++ **/ ++static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, ++ u16 length, u16 offset, u8 *sum) ++{ ++ u8 *tmp; ++ u8 *bufptr = buffer; ++ u32 data = 0; ++ u16 remaining, i, j, prev_bytes; ++ ++ /* sum = only sum of the data and it is not checksum */ ++ ++ if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) ++ return -E1000_ERR_PARAM; ++ ++ tmp = (u8 *)&data; ++ prev_bytes = offset & 0x3; ++ offset >>= 2; ++ ++ if (prev_bytes) { ++ data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset); ++ for (j = prev_bytes; j < sizeof(u32); j++) { ++ *(tmp + j) = *bufptr++; ++ *sum += *(tmp + j); ++ } ++ E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data); ++ length -= j - prev_bytes; ++ offset++; ++ } ++ ++ remaining = length & 0x3; ++ length -= remaining; ++ ++ /* Calculate length in DWORDs */ ++ length >>= 2; ++ ++ /* The device driver writes the relevant command block into the ++ * ram area. ++ */ ++ for (i = 0; i < length; i++) { ++ for (j = 0; j < sizeof(u32); j++) { ++ *(tmp + j) = *bufptr++; ++ *sum += *(tmp + j); ++ } ++ ++ E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data); ++ } ++ if (remaining) { ++ for (j = 0; j < sizeof(u32); j++) { ++ if (j < remaining) ++ *(tmp + j) = *bufptr++; ++ else ++ *(tmp + j) = 0; ++ ++ *sum += *(tmp + j); ++ } ++ E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data); ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_mng_write_dhcp_info - Writes DHCP info to host interface ++ * @hw: pointer to the HW structure ++ * @buffer: pointer to the host interface ++ * @length: size of the buffer ++ * ++ * Writes the DHCP information to the host interface. ++ **/ ++s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length) ++{ ++ struct e1000_host_mng_command_header hdr; ++ s32 ret_val; ++ u32 hicr; ++ ++ hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; ++ hdr.command_length = length; ++ hdr.reserved1 = 0; ++ hdr.reserved2 = 0; ++ hdr.checksum = 0; ++ ++ /* Enable the host interface */ ++ ret_val = e1000_mng_enable_host_if(hw); ++ if (ret_val) ++ return ret_val; ++ ++ /* Populate the host interface with the contents of "buffer". */ ++ ret_val = e1000_mng_host_if_write(hw, buffer, length, ++ sizeof(hdr), &(hdr.checksum)); ++ if (ret_val) ++ return ret_val; ++ ++ /* Write the manageability command header */ ++ ret_val = e1000_mng_write_cmd_header(hw, &hdr); ++ if (ret_val) ++ return ret_val; ++ ++ /* Tell the ARC a new command is pending. */ ++ hicr = er32(HICR); ++ ew32(HICR, hicr | E1000_HICR_C); ++ ++ return 0; ++} ++ ++/** ++ * e1000e_enable_mng_pass_thru - Check if management passthrough is needed ++ * @hw: pointer to the HW structure ++ * ++ * Verifies the hardware needs to leave interface enabled so that frames can ++ * be directed to and from the management interface. ++ **/ ++bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw) ++{ ++ u32 manc; ++ u32 fwsm, factps; ++ ++ manc = er32(MANC); ++ ++ if (!(manc & E1000_MANC_RCV_TCO_EN)) ++ return false; ++ ++ if (hw->mac.has_fwsm) { ++ fwsm = er32(FWSM); ++ factps = er32(FACTPS); ++ ++ if (!(factps & E1000_FACTPS_MNGCG) && ++ ((fwsm & E1000_FWSM_MODE_MASK) == ++ (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) ++ return true; ++ } else if ((hw->mac.type == e1000_82574) || ++ (hw->mac.type == e1000_82583)) { ++ u16 data; ++ ++ factps = er32(FACTPS); ++ e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); ++ ++ if (!(factps & E1000_FACTPS_MNGCG) && ++ ((data & E1000_NVM_INIT_CTRL2_MNGM) == ++ (e1000_mng_mode_pt << 13))) ++ return true; ++ } else if ((manc & E1000_MANC_SMBUS_EN) && ++ !(manc & E1000_MANC_ASF_EN)) { ++ return true; ++ } ++ ++ return false; ++} +diff --git a/drivers/net/ethernet/intel/e1000e/manage.h b/drivers/net/ethernet/intel/e1000e/manage.h +new file mode 100644 +index 0000000..326897c +--- /dev/null ++++ b/drivers/net/ethernet/intel/e1000e/manage.h +@@ -0,0 +1,72 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#ifndef _E1000E_MANAGE_H_ ++#define _E1000E_MANAGE_H_ ++ ++bool e1000e_check_mng_mode_generic(struct e1000_hw *hw); ++bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw); ++s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length); ++bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw); ++ ++enum e1000_mng_mode { ++ e1000_mng_mode_none = 0, ++ e1000_mng_mode_asf, ++ e1000_mng_mode_pt, ++ e1000_mng_mode_ipmi, ++ e1000_mng_mode_host_if_only ++}; ++ ++#define E1000_FACTPS_MNGCG 0x20000000 ++ ++#define E1000_FWSM_MODE_MASK 0xE ++#define E1000_FWSM_MODE_SHIFT 1 ++ ++#define E1000_MNG_IAMT_MODE 0x3 ++#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 ++#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 ++#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 ++#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 ++#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1 ++#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 ++ ++#define E1000_VFTA_ENTRY_SHIFT 5 ++#define E1000_VFTA_ENTRY_MASK 0x7F ++#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F ++ ++#define E1000_HICR_EN 0x01 /* Enable bit - RO */ ++/* Driver sets this bit when done to put command in RAM */ ++#define E1000_HICR_C 0x02 ++#define E1000_HICR_SV 0x04 /* Status Validity */ ++#define E1000_HICR_FW_RESET_ENABLE 0x40 ++#define E1000_HICR_FW_RESET 0x80 ++ ++/* Intel(R) Active Management Technology signature */ ++#define E1000_IAMT_SIGNATURE 0x544D4149 ++ ++#endif +diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c +index a783530..2201ce1 100644 +--- a/drivers/net/ethernet/intel/e1000e/netdev.c ++++ b/drivers/net/ethernet/intel/e1000e/netdev.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel PRO/1000 Linux driver +- Copyright(c) 1999 - 2011 Intel Corporation. ++ Copyright(c) 1999 - 2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -42,7 +42,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -56,11 +55,14 @@ + + #define DRV_EXTRAVERSION "-k" + +-#define DRV_VERSION "1.5.1" DRV_EXTRAVERSION ++#define DRV_VERSION "2.3.2" DRV_EXTRAVERSION + char e1000e_driver_name[] = "e1000e"; + const char e1000e_driver_version[] = DRV_VERSION; + +-static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state); ++#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) ++static int debug = -1; ++module_param(debug, int, 0); ++MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + + static const struct e1000_info *e1000_info_tbl[] = { + [board_82571] = &e1000_82571_info, +@@ -74,6 +76,7 @@ static const struct e1000_info *e1000_info_tbl[] = { + [board_ich10lan] = &e1000_ich10_info, + [board_pchlan] = &e1000_pch_info, + [board_pch2lan] = &e1000_pch2_info, ++ [board_pch_lpt] = &e1000_pch_lpt_info, + }; + + struct e1000_reg_info { +@@ -81,20 +84,7 @@ struct e1000_reg_info { + char *name; + }; + +-#define E1000_RDFH 0x02410 /* Rx Data FIFO Head - RW */ +-#define E1000_RDFT 0x02418 /* Rx Data FIFO Tail - RW */ +-#define E1000_RDFHS 0x02420 /* Rx Data FIFO Head Saved - RW */ +-#define E1000_RDFTS 0x02428 /* Rx Data FIFO Tail Saved - RW */ +-#define E1000_RDFPC 0x02430 /* Rx Data FIFO Packet Count - RW */ +- +-#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ +-#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ +-#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ +-#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */ +-#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */ +- + static const struct e1000_reg_info e1000_reg_info_tbl[] = { +- + /* General Registers */ + {E1000_CTRL, "CTRL"}, + {E1000_STATUS, "STATUS"}, +@@ -105,14 +95,14 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = { + + /* Rx Registers */ + {E1000_RCTL, "RCTL"}, +- {E1000_RDLEN, "RDLEN"}, +- {E1000_RDH, "RDH"}, +- {E1000_RDT, "RDT"}, ++ {E1000_RDLEN(0), "RDLEN"}, ++ {E1000_RDH(0), "RDH"}, ++ {E1000_RDT(0), "RDT"}, + {E1000_RDTR, "RDTR"}, + {E1000_RXDCTL(0), "RXDCTL"}, + {E1000_ERT, "ERT"}, +- {E1000_RDBAL, "RDBAL"}, +- {E1000_RDBAH, "RDBAH"}, ++ {E1000_RDBAL(0), "RDBAL"}, ++ {E1000_RDBAH(0), "RDBAH"}, + {E1000_RDFH, "RDFH"}, + {E1000_RDFT, "RDFT"}, + {E1000_RDFHS, "RDFHS"}, +@@ -121,11 +111,11 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = { + + /* Tx Registers */ + {E1000_TCTL, "TCTL"}, +- {E1000_TDBAL, "TDBAL"}, +- {E1000_TDBAH, "TDBAH"}, +- {E1000_TDLEN, "TDLEN"}, +- {E1000_TDH, "TDH"}, +- {E1000_TDT, "TDT"}, ++ {E1000_TDBAL(0), "TDBAL"}, ++ {E1000_TDBAH(0), "TDBAH"}, ++ {E1000_TDLEN(0), "TDLEN"}, ++ {E1000_TDH(0), "TDH"}, ++ {E1000_TDT(0), "TDT"}, + {E1000_TIDV, "TIDV"}, + {E1000_TXDCTL(0), "TXDCTL"}, + {E1000_TADV, "TADV"}, +@@ -137,12 +127,14 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = { + {E1000_TDFPC, "TDFPC"}, + + /* List Terminator */ +- {} ++ {0, NULL} + }; + +-/* ++/** + * e1000_regdump - register printout routine +- */ ++ * @hw: pointer to the HW structure ++ * @reginfo: pointer to the register info table ++ **/ + static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo) + { + int n = 0; +@@ -163,21 +155,37 @@ static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo) + regs[n] = __er32(hw, E1000_TARC(n)); + break; + default: +- printk(KERN_INFO "%-15s %08x\n", +- reginfo->name, __er32(hw, reginfo->ofs)); ++ pr_info("%-15s %08x\n", ++ reginfo->name, __er32(hw, reginfo->ofs)); + return; + } + + snprintf(rname, 16, "%s%s", reginfo->name, "[0-1]"); +- printk(KERN_INFO "%-15s ", rname); +- for (n = 0; n < 2; n++) +- printk(KERN_CONT "%08x ", regs[n]); +- printk(KERN_CONT "\n"); ++ pr_info("%-15s %08x %08x\n", rname, regs[0], regs[1]); ++} ++ ++static void e1000e_dump_ps_pages(struct e1000_adapter *adapter, ++ struct e1000_buffer *bi) ++{ ++ int i; ++ struct e1000_ps_page *ps_page; ++ ++ for (i = 0; i < adapter->rx_ps_pages; i++) { ++ ps_page = &bi->ps_pages[i]; ++ ++ if (ps_page->page) { ++ pr_info("packet dump for ps_page %d:\n", i); ++ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, ++ 16, 1, page_address(ps_page->page), ++ PAGE_SIZE, true); ++ } ++ } + } + +-/* ++/** + * e1000e_dump - Print registers, Tx-ring and Rx-ring +- */ ++ * @adapter: board private structure ++ **/ + static void e1000e_dump(struct e1000_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; +@@ -186,18 +194,18 @@ static void e1000e_dump(struct e1000_adapter *adapter) + struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_tx_desc *tx_desc; + struct my_u0 { +- u64 a; +- u64 b; ++ __le64 a; ++ __le64 b; + } *u0; + struct e1000_buffer *buffer_info; + struct e1000_ring *rx_ring = adapter->rx_ring; + union e1000_rx_desc_packet_split *rx_desc_ps; + union e1000_rx_desc_extended *rx_desc; + struct my_u1 { +- u64 a; +- u64 b; +- u64 c; +- u64 d; ++ __le64 a; ++ __le64 b; ++ __le64 c; ++ __le64 d; + } *u1; + u32 staterr; + int i = 0; +@@ -208,16 +216,14 @@ static void e1000e_dump(struct e1000_adapter *adapter) + /* Print netdevice Info */ + if (netdev) { + dev_info(&adapter->pdev->dev, "Net device Info\n"); +- printk(KERN_INFO "Device Name state " +- "trans_start last_rx\n"); +- printk(KERN_INFO "%-15s %016lX %016lX %016lX\n", +- netdev->name, netdev->state, netdev->trans_start, +- netdev->last_rx); ++ pr_info("Device Name state trans_start last_rx\n"); ++ pr_info("%-15s %016lX %016lX %016lX\n", netdev->name, ++ netdev->state, netdev->trans_start, netdev->last_rx); + } + + /* Print Registers */ + dev_info(&adapter->pdev->dev, "Register Dump\n"); +- printk(KERN_INFO " Register Name Value\n"); ++ pr_info(" Register Name Value\n"); + for (reginfo = (struct e1000_reg_info *)e1000_reg_info_tbl; + reginfo->name; reginfo++) { + e1000_regdump(hw, reginfo); +@@ -225,18 +231,17 @@ static void e1000e_dump(struct e1000_adapter *adapter) + + /* Print Tx Ring Summary */ + if (!netdev || !netif_running(netdev)) +- goto exit; ++ return; + + dev_info(&adapter->pdev->dev, "Tx Ring Summary\n"); +- printk(KERN_INFO "Queue [NTU] [NTC] [bi(ntc)->dma ]" +- " leng ntw timestamp\n"); ++ pr_info("Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n"); + buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean]; +- printk(KERN_INFO " %5d %5X %5X %016llX %04X %3X %016llX\n", +- 0, tx_ring->next_to_use, tx_ring->next_to_clean, +- (unsigned long long)buffer_info->dma, +- buffer_info->length, +- buffer_info->next_to_watch, +- (unsigned long long)buffer_info->time_stamp); ++ pr_info(" %5d %5X %5X %016llX %04X %3X %016llX\n", ++ 0, tx_ring->next_to_use, tx_ring->next_to_clean, ++ (unsigned long long)buffer_info->dma, ++ buffer_info->length, ++ buffer_info->next_to_watch, ++ (unsigned long long)buffer_info->time_stamp); + + /* Print Tx Ring */ + if (!netif_msg_tx_done(adapter)) +@@ -271,54 +276,49 @@ static void e1000e_dump(struct e1000_adapter *adapter) + * +----------------------------------------------------------------+ + * 63 48 47 40 39 36 35 32 31 24 23 20 19 0 + */ +- printk(KERN_INFO "Tl[desc] [address 63:0 ] [SpeCssSCmCsLen]" +- " [bi->dma ] leng ntw timestamp bi->skb " +- "<-- Legacy format\n"); +- printk(KERN_INFO "Tc[desc] [Ce CoCsIpceCoS] [MssHlRSCm0Plen]" +- " [bi->dma ] leng ntw timestamp bi->skb " +- "<-- Ext Context format\n"); +- printk(KERN_INFO "Td[desc] [address 63:0 ] [VlaPoRSCm1Dlen]" +- " [bi->dma ] leng ntw timestamp bi->skb " +- "<-- Ext Data format\n"); ++ pr_info("Tl[desc] [address 63:0 ] [SpeCssSCmCsLen] [bi->dma ] leng ntw timestamp bi->skb <-- Legacy format\n"); ++ pr_info("Tc[desc] [Ce CoCsIpceCoS] [MssHlRSCm0Plen] [bi->dma ] leng ntw timestamp bi->skb <-- Ext Context format\n"); ++ pr_info("Td[desc] [address 63:0 ] [VlaPoRSCm1Dlen] [bi->dma ] leng ntw timestamp bi->skb <-- Ext Data format\n"); + for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { ++ const char *next_desc; + tx_desc = E1000_TX_DESC(*tx_ring, i); + buffer_info = &tx_ring->buffer_info[i]; + u0 = (struct my_u0 *)tx_desc; +- printk(KERN_INFO "T%c[0x%03X] %016llX %016llX %016llX " +- "%04X %3X %016llX %p", +- (!(le64_to_cpu(u0->b) & (1 << 29)) ? 'l' : +- ((le64_to_cpu(u0->b) & (1 << 20)) ? 'd' : 'c')), i, +- (unsigned long long)le64_to_cpu(u0->a), +- (unsigned long long)le64_to_cpu(u0->b), +- (unsigned long long)buffer_info->dma, +- buffer_info->length, buffer_info->next_to_watch, +- (unsigned long long)buffer_info->time_stamp, +- buffer_info->skb); + if (i == tx_ring->next_to_use && i == tx_ring->next_to_clean) +- printk(KERN_CONT " NTC/U\n"); ++ next_desc = " NTC/U"; + else if (i == tx_ring->next_to_use) +- printk(KERN_CONT " NTU\n"); ++ next_desc = " NTU"; + else if (i == tx_ring->next_to_clean) +- printk(KERN_CONT " NTC\n"); ++ next_desc = " NTC"; + else +- printk(KERN_CONT "\n"); +- +- if (netif_msg_pktdata(adapter) && buffer_info->dma != 0) ++ next_desc = ""; ++ pr_info("T%c[0x%03X] %016llX %016llX %016llX %04X %3X %016llX %p%s\n", ++ (!(le64_to_cpu(u0->b) & (1 << 29)) ? 'l' : ++ ((le64_to_cpu(u0->b) & (1 << 20)) ? 'd' : 'c')), ++ i, ++ (unsigned long long)le64_to_cpu(u0->a), ++ (unsigned long long)le64_to_cpu(u0->b), ++ (unsigned long long)buffer_info->dma, ++ buffer_info->length, buffer_info->next_to_watch, ++ (unsigned long long)buffer_info->time_stamp, ++ buffer_info->skb, next_desc); ++ ++ if (netif_msg_pktdata(adapter) && buffer_info->skb) + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, +- 16, 1, phys_to_virt(buffer_info->dma), +- buffer_info->length, true); ++ 16, 1, buffer_info->skb->data, ++ buffer_info->skb->len, true); + } + + /* Print Rx Ring Summary */ + rx_ring_summary: + dev_info(&adapter->pdev->dev, "Rx Ring Summary\n"); +- printk(KERN_INFO "Queue [NTU] [NTC]\n"); +- printk(KERN_INFO " %5d %5X %5X\n", 0, +- rx_ring->next_to_use, rx_ring->next_to_clean); ++ pr_info("Queue [NTU] [NTC]\n"); ++ pr_info(" %5d %5X %5X\n", ++ 0, rx_ring->next_to_use, rx_ring->next_to_clean); + + /* Print Rx Ring */ + if (!netif_msg_rx_status(adapter)) +- goto exit; ++ return; + + dev_info(&adapter->pdev->dev, "Rx Ring Dump\n"); + switch (adapter->rx_ps_pages) { +@@ -337,10 +337,7 @@ rx_ring_summary: + * 24 | Buffer Address 3 [63:0] | + * +-----------------------------------------------------+ + */ +- printk(KERN_INFO "R [desc] [buffer 0 63:0 ] " +- "[buffer 1 63:0 ] " +- "[buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma ] " +- "[bi->skb] <-- Ext Pkt Split format\n"); ++ pr_info("R [desc] [buffer 0 63:0 ] [buffer 1 63:0 ] [buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma ] [bi->skb] <-- Ext Pkt Split format\n"); + /* [Extended] Receive Descriptor (Write-Back) Format + * + * 63 48 47 32 31 13 12 8 7 4 3 0 +@@ -352,49 +349,45 @@ rx_ring_summary: + * +------------------------------------------------------+ + * 63 48 47 32 31 20 19 0 + */ +- printk(KERN_INFO "RWB[desc] [ck ipid mrqhsh] " +- "[vl l0 ee es] " +- "[ l3 l2 l1 hs] [reserved ] ---------------- " +- "[bi->skb] <-- Ext Rx Write-Back format\n"); ++ pr_info("RWB[desc] [ck ipid mrqhsh] [vl l0 ee es] [ l3 l2 l1 hs] [reserved ] ---------------- [bi->skb] <-- Ext Rx Write-Back format\n"); + for (i = 0; i < rx_ring->count; i++) { ++ const char *next_desc; + buffer_info = &rx_ring->buffer_info[i]; + rx_desc_ps = E1000_RX_DESC_PS(*rx_ring, i); + u1 = (struct my_u1 *)rx_desc_ps; + staterr = + le32_to_cpu(rx_desc_ps->wb.middle.status_error); ++ ++ if (i == rx_ring->next_to_use) ++ next_desc = " NTU"; ++ else if (i == rx_ring->next_to_clean) ++ next_desc = " NTC"; ++ else ++ next_desc = ""; ++ + if (staterr & E1000_RXD_STAT_DD) { + /* Descriptor Done */ +- printk(KERN_INFO "RWB[0x%03X] %016llX " +- "%016llX %016llX %016llX " +- "---------------- %p", i, +- (unsigned long long)le64_to_cpu(u1->a), +- (unsigned long long)le64_to_cpu(u1->b), +- (unsigned long long)le64_to_cpu(u1->c), +- (unsigned long long)le64_to_cpu(u1->d), +- buffer_info->skb); ++ pr_info("%s[0x%03X] %016llX %016llX %016llX %016llX ---------------- %p%s\n", ++ "RWB", i, ++ (unsigned long long)le64_to_cpu(u1->a), ++ (unsigned long long)le64_to_cpu(u1->b), ++ (unsigned long long)le64_to_cpu(u1->c), ++ (unsigned long long)le64_to_cpu(u1->d), ++ buffer_info->skb, next_desc); + } else { +- printk(KERN_INFO "R [0x%03X] %016llX " +- "%016llX %016llX %016llX %016llX %p", i, +- (unsigned long long)le64_to_cpu(u1->a), +- (unsigned long long)le64_to_cpu(u1->b), +- (unsigned long long)le64_to_cpu(u1->c), +- (unsigned long long)le64_to_cpu(u1->d), +- (unsigned long long)buffer_info->dma, +- buffer_info->skb); ++ pr_info("%s[0x%03X] %016llX %016llX %016llX %016llX %016llX %p%s\n", ++ "R ", i, ++ (unsigned long long)le64_to_cpu(u1->a), ++ (unsigned long long)le64_to_cpu(u1->b), ++ (unsigned long long)le64_to_cpu(u1->c), ++ (unsigned long long)le64_to_cpu(u1->d), ++ (unsigned long long)buffer_info->dma, ++ buffer_info->skb, next_desc); + + if (netif_msg_pktdata(adapter)) +- print_hex_dump(KERN_INFO, "", +- DUMP_PREFIX_ADDRESS, 16, 1, +- phys_to_virt(buffer_info->dma), +- adapter->rx_ps_bsize0, true); ++ e1000e_dump_ps_pages(adapter, ++ buffer_info); + } +- +- if (i == rx_ring->next_to_use) +- printk(KERN_CONT " NTU\n"); +- else if (i == rx_ring->next_to_clean) +- printk(KERN_CONT " NTC\n"); +- else +- printk(KERN_CONT "\n"); + } + break; + default: +@@ -407,9 +400,7 @@ rx_ring_summary: + * 8 | Reserved | + * +-----------------------------------------------------+ + */ +- printk(KERN_INFO "R [desc] [buf addr 63:0 ] " +- "[reserved 63:0 ] [bi->dma ] " +- "[bi->skb] <-- Ext (Read) format\n"); ++ pr_info("R [desc] [buf addr 63:0 ] [reserved 63:0 ] [bi->dma ] [bi->skb] <-- Ext (Read) format\n"); + /* Extended Receive Descriptor (Write-Back) Format + * + * 63 48 47 32 31 24 23 4 3 0 +@@ -423,51 +414,49 @@ rx_ring_summary: + * +------------------------------------------------------+ + * 63 48 47 32 31 20 19 0 + */ +- printk(KERN_INFO "RWB[desc] [cs ipid mrq] " +- "[vt ln xe xs] " +- "[bi->skb] <-- Ext (Write-Back) format\n"); ++ pr_info("RWB[desc] [cs ipid mrq] [vt ln xe xs] [bi->skb] <-- Ext (Write-Back) format\n"); + + for (i = 0; i < rx_ring->count; i++) { ++ const char *next_desc; ++ + buffer_info = &rx_ring->buffer_info[i]; + rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); + u1 = (struct my_u1 *)rx_desc; + staterr = le32_to_cpu(rx_desc->wb.upper.status_error); ++ ++ if (i == rx_ring->next_to_use) ++ next_desc = " NTU"; ++ else if (i == rx_ring->next_to_clean) ++ next_desc = " NTC"; ++ else ++ next_desc = ""; ++ + if (staterr & E1000_RXD_STAT_DD) { + /* Descriptor Done */ +- printk(KERN_INFO "RWB[0x%03X] %016llX " +- "%016llX ---------------- %p", i, +- (unsigned long long)le64_to_cpu(u1->a), +- (unsigned long long)le64_to_cpu(u1->b), +- buffer_info->skb); ++ pr_info("%s[0x%03X] %016llX %016llX ---------------- %p%s\n", ++ "RWB", i, ++ (unsigned long long)le64_to_cpu(u1->a), ++ (unsigned long long)le64_to_cpu(u1->b), ++ buffer_info->skb, next_desc); + } else { +- printk(KERN_INFO "R [0x%03X] %016llX " +- "%016llX %016llX %p", i, +- (unsigned long long)le64_to_cpu(u1->a), +- (unsigned long long)le64_to_cpu(u1->b), +- (unsigned long long)buffer_info->dma, +- buffer_info->skb); +- +- if (netif_msg_pktdata(adapter)) ++ pr_info("%s[0x%03X] %016llX %016llX %016llX %p%s\n", ++ "R ", i, ++ (unsigned long long)le64_to_cpu(u1->a), ++ (unsigned long long)le64_to_cpu(u1->b), ++ (unsigned long long)buffer_info->dma, ++ buffer_info->skb, next_desc); ++ ++ if (netif_msg_pktdata(adapter) && ++ buffer_info->skb) + print_hex_dump(KERN_INFO, "", + DUMP_PREFIX_ADDRESS, 16, + 1, +- phys_to_virt +- (buffer_info->dma), ++ buffer_info->skb->data, + adapter->rx_buffer_len, + true); + } +- +- if (i == rx_ring->next_to_use) +- printk(KERN_CONT " NTU\n"); +- else if (i == rx_ring->next_to_clean) +- printk(KERN_CONT " NTC\n"); +- else +- printk(KERN_CONT "\n"); + } + } +- +-exit: +- return; + } + + /** +@@ -481,21 +470,94 @@ static int e1000_desc_unused(struct e1000_ring *ring) + return ring->count + ring->next_to_clean - ring->next_to_use - 1; + } + ++#ifdef CONFIG_E1000E_PTP ++/** ++ * e1000e_systim_to_hwtstamp - convert system time value to hw time stamp ++ * @adapter: board private structure ++ * @hwtstamps: time stamp structure to update ++ * @systim: unsigned 64bit system time value. ++ * ++ * Convert the system time value stored in the RX/TXSTMP registers into a ++ * hwtstamp which can be used by the upper level time stamping functions. ++ * ++ * The 'systim_lock' spinlock is used to protect the consistency of the ++ * system time value. This is needed because reading the 64 bit time ++ * value involves reading two 32 bit registers. The first read latches the ++ * value. ++ **/ ++static void e1000e_systim_to_hwtstamp(struct e1000_adapter *adapter, ++ struct skb_shared_hwtstamps *hwtstamps, ++ u64 systim) ++{ ++ u64 ns; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&adapter->systim_lock, flags); ++ ns = timecounter_cyc2time(&adapter->tc, systim); ++ spin_unlock_irqrestore(&adapter->systim_lock, flags); ++ ++ memset(hwtstamps, 0, sizeof(*hwtstamps)); ++ hwtstamps->hwtstamp = ns_to_ktime(ns); ++} ++ ++/** ++ * e1000e_rx_hwtstamp - utility function which checks for Rx time stamp ++ * @adapter: board private structure ++ * @status: descriptor extended error and status field ++ * @skb: particular skb to include time stamp ++ * ++ * If the time stamp is valid, convert it into the timecounter ns value ++ * and store that result into the shhwtstamps structure which is passed ++ * up the network stack. ++ **/ ++static void e1000e_rx_hwtstamp(struct e1000_adapter *adapter, u32 status, ++ struct sk_buff *skb) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u64 rxstmp; ++ ++ if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP) || ++ !(status & E1000_RXDEXT_STATERR_TST) || ++ !(er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) ++ return; ++ ++ /* The Rx time stamp registers contain the time stamp. No other ++ * received packet will be time stamped until the Rx time stamp ++ * registers are read. Because only one packet can be time stamped ++ * at a time, the register values must belong to this packet and ++ * therefore none of the other additional attributes need to be ++ * compared. ++ */ ++ rxstmp = (u64)er32(RXSTMPL); ++ rxstmp |= (u64)er32(RXSTMPH) << 32; ++ e1000e_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), rxstmp); ++ ++ adapter->flags2 &= ~FLAG2_CHECK_RX_HWTSTAMP; ++} ++#else ++static void e1000e_rx_hwtstamp(struct e1000_adapter *adapter, u32 status, ++ struct sk_buff *skb) ++{} ++#endif ++ + /** + * e1000_receive_skb - helper function to handle Rx indications + * @adapter: board private structure +- * @status: descriptor status field as written by hardware ++ * @staterr: descriptor extended error and status field as written by hardware + * @vlan: descriptor vlan field as written by hardware (no le/be conversion) + * @skb: pointer to sk_buff to be indicated to stack + **/ + static void e1000_receive_skb(struct e1000_adapter *adapter, + struct net_device *netdev, struct sk_buff *skb, +- u8 status, __le16 vlan) ++ u32 staterr, __le16 vlan) + { + u16 tag = le16_to_cpu(vlan); ++ ++ e1000e_rx_hwtstamp(adapter, staterr, skb); ++ + skb->protocol = eth_type_trans(skb, netdev); + +- if (status & E1000_RXD_STAT_VP) ++ if (staterr & E1000_RXD_STAT_VP) + __vlan_hwaccel_put_tag(skb, tag); + + napi_gro_receive(&adapter->napi, skb); +@@ -503,24 +565,29 @@ static void e1000_receive_skb(struct e1000_adapter *adapter, + + /** + * e1000_rx_checksum - Receive Checksum Offload +- * @adapter: board private structure +- * @status_err: receive descriptor status and error fields +- * @csum: receive descriptor csum field +- * @sk_buff: socket buffer with received data ++ * @adapter: board private structure ++ * @status_err: receive descriptor status and error fields ++ * @csum: receive descriptor csum field ++ * @sk_buff: socket buffer with received data + **/ + static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, +- u32 csum, struct sk_buff *skb) ++ struct sk_buff *skb) + { + u16 status = (u16)status_err; + u8 errors = (u8)(status_err >> 24); + + skb_checksum_none_assert(skb); + ++ /* Rx checksum disabled */ ++ if (!(adapter->netdev->features & NETIF_F_RXCSUM)) ++ return; ++ + /* Ignore Checksum bit is set */ + if (status & E1000_RXD_STAT_IXSM) + return; +- /* TCP/UDP checksum error bit is set */ +- if (errors & E1000_RXD_ERR_TCPE) { ++ ++ /* TCP/UDP checksum error bit or IP checksum error bit is set */ ++ if (errors & (E1000_RXD_ERR_TCPE | E1000_RXD_ERR_IPE)) { + /* let the stack verify checksum errors */ + adapter->hw_csum_err++; + return; +@@ -531,59 +598,19 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, + return; + + /* It must be a TCP or UDP packet with a valid checksum */ +- if (status & E1000_RXD_STAT_TCPCS) { +- /* TCP checksum is good */ +- skb->ip_summed = CHECKSUM_UNNECESSARY; +- } else { +- /* +- * IP fragment with UDP payload +- * Hardware complements the payload checksum, so we undo it +- * and then put the value in host order for further stack use. +- */ +- __sum16 sum = (__force __sum16)htons(csum); +- skb->csum = csum_unfold(~sum); +- skb->ip_summed = CHECKSUM_COMPLETE; +- } ++ skb->ip_summed = CHECKSUM_UNNECESSARY; + adapter->hw_csum_good++; + } + +-/** +- * e1000e_update_tail_wa - helper function for e1000e_update_[rt]dt_wa() +- * @hw: pointer to the HW structure +- * @tail: address of tail descriptor register +- * @i: value to write to tail descriptor register +- * +- * When updating the tail register, the ME could be accessing Host CSR +- * registers at the same time. Normally, this is handled in h/w by an +- * arbiter but on some parts there is a bug that acknowledges Host accesses +- * later than it should which could result in the descriptor register to +- * have an incorrect value. Workaround this by checking the FWSM register +- * which has bit 24 set while ME is accessing Host CSR registers, wait +- * if it is set and try again a number of times. +- **/ +-static inline s32 e1000e_update_tail_wa(struct e1000_hw *hw, u8 __iomem * tail, +- unsigned int i) ++static void e1000e_update_rdt_wa(struct e1000_ring *rx_ring, unsigned int i) + { +- unsigned int j = 0; +- +- while ((j++ < E1000_ICH_FWSM_PCIM2PCI_COUNT) && +- (er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI)) +- udelay(50); +- +- writel(i, tail); +- +- if ((j == E1000_ICH_FWSM_PCIM2PCI_COUNT) && (i != readl(tail))) +- return E1000_ERR_SWFW_SYNC; +- +- return 0; +-} +- +-static void e1000e_update_rdt_wa(struct e1000_adapter *adapter, unsigned int i) +-{ +- u8 __iomem *tail = (adapter->hw.hw_addr + adapter->rx_ring->tail); ++ struct e1000_adapter *adapter = rx_ring->adapter; + struct e1000_hw *hw = &adapter->hw; ++ s32 ret_val = __ew32_prepare(hw); + +- if (e1000e_update_tail_wa(hw, tail, i)) { ++ writel(i, rx_ring->tail); ++ ++ if (unlikely(!ret_val && (i != readl(rx_ring->tail)))) { + u32 rctl = er32(RCTL); + ew32(RCTL, rctl & ~E1000_RCTL_EN); + e_err("ME firmware caused invalid RDT - resetting\n"); +@@ -591,12 +618,15 @@ static void e1000e_update_rdt_wa(struct e1000_adapter *adapter, unsigned int i) + } + } + +-static void e1000e_update_tdt_wa(struct e1000_adapter *adapter, unsigned int i) ++static void e1000e_update_tdt_wa(struct e1000_ring *tx_ring, unsigned int i) + { +- u8 __iomem *tail = (adapter->hw.hw_addr + adapter->tx_ring->tail); ++ struct e1000_adapter *adapter = tx_ring->adapter; + struct e1000_hw *hw = &adapter->hw; ++ s32 ret_val = __ew32_prepare(hw); ++ ++ writel(i, tx_ring->tail); + +- if (e1000e_update_tail_wa(hw, tail, i)) { ++ if (unlikely(!ret_val && (i != readl(tx_ring->tail)))) { + u32 tctl = er32(TCTL); + ew32(TCTL, tctl & ~E1000_TCTL_EN); + e_err("ME firmware caused invalid TDT - resetting\n"); +@@ -606,14 +636,14 @@ static void e1000e_update_tdt_wa(struct e1000_adapter *adapter, unsigned int i) + + /** + * e1000_alloc_rx_buffers - Replace used receive buffers +- * @adapter: address of board private structure ++ * @rx_ring: Rx descriptor ring + **/ +-static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, ++static void e1000_alloc_rx_buffers(struct e1000_ring *rx_ring, + int cleaned_count, gfp_t gfp) + { ++ struct e1000_adapter *adapter = rx_ring->adapter; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; +- struct e1000_ring *rx_ring = adapter->rx_ring; + union e1000_rx_desc_extended *rx_desc; + struct e1000_buffer *buffer_info; + struct sk_buff *skb; +@@ -652,17 +682,16 @@ map_skb: + rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma); + + if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) { +- /* +- * Force memory writes to complete before letting h/w ++ /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) +- e1000e_update_rdt_wa(adapter, i); ++ e1000e_update_rdt_wa(rx_ring, i); + else +- writel(i, adapter->hw.hw_addr + rx_ring->tail); ++ writel(i, rx_ring->tail); + } + i++; + if (i == rx_ring->count) +@@ -675,15 +704,15 @@ map_skb: + + /** + * e1000_alloc_rx_buffers_ps - Replace used receive buffers; packet split +- * @adapter: address of board private structure ++ * @rx_ring: Rx descriptor ring + **/ +-static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, ++static void e1000_alloc_rx_buffers_ps(struct e1000_ring *rx_ring, + int cleaned_count, gfp_t gfp) + { ++ struct e1000_adapter *adapter = rx_ring->adapter; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + union e1000_rx_desc_packet_split *rx_desc; +- struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_buffer *buffer_info; + struct e1000_ps_page *ps_page; + struct sk_buff *skb; +@@ -721,8 +750,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, + goto no_buffers; + } + } +- /* +- * Refresh the desc even if buffer_addrs ++ /* Refresh the desc even if buffer_addrs + * didn't change because each write-back + * erases this info. + */ +@@ -730,8 +758,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, + cpu_to_le64(ps_page->dma); + } + +- skb = __netdev_alloc_skb_ip_align(netdev, +- adapter->rx_ps_bsize0, ++ skb = __netdev_alloc_skb_ip_align(netdev, adapter->rx_ps_bsize0, + gfp); + + if (!skb) { +@@ -755,18 +782,16 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, + rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma); + + if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) { +- /* +- * Force memory writes to complete before letting h/w ++ /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) +- e1000e_update_rdt_wa(adapter, i << 1); ++ e1000e_update_rdt_wa(rx_ring, i << 1); + else +- writel(i << 1, +- adapter->hw.hw_addr + rx_ring->tail); ++ writel(i << 1, rx_ring->tail); + } + + i++; +@@ -781,21 +806,21 @@ no_buffers: + + /** + * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers +- * @adapter: address of board private structure ++ * @rx_ring: Rx descriptor ring + * @cleaned_count: number of buffers to allocate this pass + **/ + +-static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter, ++static void e1000_alloc_jumbo_rx_buffers(struct e1000_ring *rx_ring, + int cleaned_count, gfp_t gfp) + { ++ struct e1000_adapter *adapter = rx_ring->adapter; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + union e1000_rx_desc_extended *rx_desc; +- struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_buffer *buffer_info; + struct sk_buff *skb; + unsigned int i; +- unsigned int bufsz = 256 - 16 /* for skb_reserve */; ++ unsigned int bufsz = 256 - 16; /* for skb_reserve */ + + i = rx_ring->next_to_use; + buffer_info = &rx_ring->buffer_info[i]; +@@ -825,11 +850,16 @@ check_page: + } + } + +- if (!buffer_info->dma) ++ if (!buffer_info->dma) { + buffer_info->dma = dma_map_page(&pdev->dev, +- buffer_info->page, 0, +- PAGE_SIZE, ++ buffer_info->page, 0, ++ PAGE_SIZE, + DMA_FROM_DEVICE); ++ if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { ++ adapter->alloc_rx_buff_failed++; ++ break; ++ } ++ } + + rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); + rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma); +@@ -847,35 +877,43 @@ check_page: + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, +- * such as IA-64). */ ++ * such as IA-64). ++ */ + wmb(); + if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) +- e1000e_update_rdt_wa(adapter, i); ++ e1000e_update_rdt_wa(rx_ring, i); + else +- writel(i, adapter->hw.hw_addr + rx_ring->tail); ++ writel(i, rx_ring->tail); + } + } + ++static inline void e1000_rx_hash(struct net_device *netdev, __le32 rss, ++ struct sk_buff *skb) ++{ ++ if (netdev->features & NETIF_F_RXHASH) ++ skb->rxhash = le32_to_cpu(rss); ++} ++ + /** +- * e1000_clean_rx_irq - Send received data up the network stack; legacy +- * @adapter: board private structure ++ * e1000_clean_rx_irq - Send received data up the network stack ++ * @rx_ring: Rx descriptor ring + * + * the return value indicates whether actual cleaning was done, there + * is no guarantee that everything was cleaned + **/ +-static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, +- int *work_done, int work_to_do) ++static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done, ++ int work_to_do) + { ++ struct e1000_adapter *adapter = rx_ring->adapter; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + struct e1000_hw *hw = &adapter->hw; +- struct e1000_ring *rx_ring = adapter->rx_ring; + union e1000_rx_desc_extended *rx_desc, *next_rxd; + struct e1000_buffer *buffer_info, *next_buffer; + u32 length, staterr; + unsigned int i; + int cleaned_count = 0; +- bool cleaned = 0; ++ bool cleaned = false; + unsigned int total_rx_bytes = 0, total_rx_packets = 0; + + i = rx_ring->next_to_clean; +@@ -904,18 +942,15 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, + + next_buffer = &rx_ring->buffer_info[i]; + +- cleaned = 1; ++ cleaned = true; + cleaned_count++; +- dma_unmap_single(&pdev->dev, +- buffer_info->dma, +- adapter->rx_buffer_len, +- DMA_FROM_DEVICE); ++ dma_unmap_single(&pdev->dev, buffer_info->dma, ++ adapter->rx_buffer_len, DMA_FROM_DEVICE); + buffer_info->dma = 0; + + length = le16_to_cpu(rx_desc->wb.upper.length); + +- /* +- * !EOP means multiple descriptors were used to store a single ++ /* !EOP means multiple descriptors were used to store a single + * packet, if that's the case we need to toss it. In fact, we + * need to toss every packet with the EOP bit clear and the + * next frame that _does_ have the EOP bit set, as it is by +@@ -947,8 +982,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, + total_rx_bytes += length; + total_rx_packets++; + +- /* +- * code added for copybreak, this should improve ++ /* code added for copybreak, this should improve + * performance for small packets with large amounts + * of reassembly being done in the stack + */ +@@ -972,9 +1006,9 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, + skb_put(skb, length); + + /* Receive Checksum Offload */ +- e1000_rx_checksum(adapter, staterr, +- le16_to_cpu(rx_desc->wb.lower.hi_dword. +- csum_ip.csum), skb); ++ e1000_rx_checksum(adapter, staterr, skb); ++ ++ e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); + + e1000_receive_skb(adapter, netdev, skb, staterr, + rx_desc->wb.upper.vlan); +@@ -984,7 +1018,7 @@ next_desc: + + /* return some buffers to hardware, one at a time is too slow */ + if (cleaned_count >= E1000_RX_BUFFER_WRITE) { +- adapter->alloc_rx_buf(adapter, cleaned_count, ++ adapter->alloc_rx_buf(rx_ring, cleaned_count, + GFP_ATOMIC); + cleaned_count = 0; + } +@@ -999,16 +1033,18 @@ next_desc: + + cleaned_count = e1000_desc_unused(rx_ring); + if (cleaned_count) +- adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC); ++ adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); + + adapter->total_rx_bytes += total_rx_bytes; + adapter->total_rx_packets += total_rx_packets; + return cleaned; + } + +-static void e1000_put_txbuf(struct e1000_adapter *adapter, +- struct e1000_buffer *buffer_info) ++static void e1000_put_txbuf(struct e1000_ring *tx_ring, ++ struct e1000_buffer *buffer_info) + { ++ struct e1000_adapter *adapter = tx_ring->adapter; ++ + if (buffer_info->dma) { + if (buffer_info->mapped_as_page) + dma_unmap_page(&adapter->pdev->dev, buffer_info->dma, +@@ -1028,8 +1064,8 @@ static void e1000_put_txbuf(struct e1000_adapter *adapter, + static void e1000_print_hw_hang(struct work_struct *work) + { + struct e1000_adapter *adapter = container_of(work, +- struct e1000_adapter, +- print_hang_task); ++ struct e1000_adapter, ++ print_hang_task); + struct net_device *netdev = adapter->netdev; + struct e1000_ring *tx_ring = adapter->tx_ring; + unsigned int i = tx_ring->next_to_clean; +@@ -1042,14 +1078,19 @@ static void e1000_print_hw_hang(struct work_struct *work) + if (test_bit(__E1000_DOWN, &adapter->state)) + return; + +- if (!adapter->tx_hang_recheck && +- (adapter->flags2 & FLAG2_DMA_BURST)) { ++ if (!adapter->tx_hang_recheck && (adapter->flags2 & FLAG2_DMA_BURST)) { + /* May be block on write-back, flush and detect again + * flush pending descriptor writebacks to memory + */ + ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); + /* execute the writes immediately */ + e1e_flush(); ++ /* Due to rare timing issues, write to TIDV again to ensure ++ * the write is successful ++ */ ++ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); ++ /* execute the writes immediately */ ++ e1e_flush(); + adapter->tx_hang_recheck = true; + return; + } +@@ -1057,9 +1098,9 @@ static void e1000_print_hw_hang(struct work_struct *work) + adapter->tx_hang_recheck = false; + netif_stop_queue(netdev); + +- e1e_rphy(hw, PHY_STATUS, &phy_status); +- e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status); +- e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status); ++ e1e_rphy(hw, MII_BMSR, &phy_status); ++ e1e_rphy(hw, MII_STAT1000, &phy_1000t_status); ++ e1e_rphy(hw, MII_ESTATUS, &phy_ext_status); + + pci_read_config_word(adapter->pdev, PCI_STATUS, &pci_status); + +@@ -1079,38 +1120,71 @@ static void e1000_print_hw_hang(struct work_struct *work) + "PHY 1000BASE-T Status <%x>\n" + "PHY Extended Status <%x>\n" + "PCI Status <%x>\n", +- readl(adapter->hw.hw_addr + tx_ring->head), +- readl(adapter->hw.hw_addr + tx_ring->tail), +- tx_ring->next_to_use, +- tx_ring->next_to_clean, +- tx_ring->buffer_info[eop].time_stamp, +- eop, +- jiffies, +- eop_desc->upper.fields.status, +- er32(STATUS), +- phy_status, +- phy_1000t_status, +- phy_ext_status, +- pci_status); ++ readl(tx_ring->head), readl(tx_ring->tail), tx_ring->next_to_use, ++ tx_ring->next_to_clean, tx_ring->buffer_info[eop].time_stamp, ++ eop, jiffies, eop_desc->upper.fields.status, er32(STATUS), ++ phy_status, phy_1000t_status, phy_ext_status, pci_status); ++ ++ /* Suggest workaround for known h/w issue */ ++ if ((hw->mac.type == e1000_pchlan) && (er32(CTRL) & E1000_CTRL_TFCE)) ++ e_err("Try turning off Tx pause (flow control) via ethtool\n"); + } + ++#ifdef CONFIG_E1000E_PTP ++/** ++ * e1000e_tx_hwtstamp_work - check for Tx time stamp ++ * @work: pointer to work struct ++ * ++ * This work function polls the TSYNCTXCTL valid bit to determine when a ++ * timestamp has been taken for the current stored skb. The timestamp must ++ * be for this skb because only one such packet is allowed in the queue. ++ */ ++static void e1000e_tx_hwtstamp_work(struct work_struct *work) ++{ ++ struct e1000_adapter *adapter = container_of(work, struct e1000_adapter, ++ tx_hwtstamp_work); ++ struct e1000_hw *hw = &adapter->hw; ++ ++ if (!adapter->tx_hwtstamp_skb) ++ return; ++ ++ if (er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID) { ++ struct skb_shared_hwtstamps shhwtstamps; ++ u64 txstmp; ++ ++ txstmp = er32(TXSTMPL); ++ txstmp |= (u64)er32(TXSTMPH) << 32; ++ ++ e1000e_systim_to_hwtstamp(adapter, &shhwtstamps, txstmp); ++ ++ skb_tstamp_tx(adapter->tx_hwtstamp_skb, &shhwtstamps); ++ dev_kfree_skb_any(adapter->tx_hwtstamp_skb); ++ adapter->tx_hwtstamp_skb = NULL; ++ } else { ++ /* reschedule to check later */ ++ schedule_work(&adapter->tx_hwtstamp_work); ++ } ++} ++#endif ++ + /** + * e1000_clean_tx_irq - Reclaim resources after transmit completes +- * @adapter: board private structure ++ * @tx_ring: Tx descriptor ring + * + * the return value indicates whether actual cleaning was done, there + * is no guarantee that everything was cleaned + **/ +-static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) ++static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring) + { ++ struct e1000_adapter *adapter = tx_ring->adapter; + struct net_device *netdev = adapter->netdev; + struct e1000_hw *hw = &adapter->hw; +- struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_tx_desc *tx_desc, *eop_desc; + struct e1000_buffer *buffer_info; + unsigned int i, eop; + unsigned int count = 0; + unsigned int total_tx_bytes = 0, total_tx_packets = 0; ++ unsigned int bytes_compl = 0, pkts_compl = 0; + + i = tx_ring->next_to_clean; + eop = tx_ring->buffer_info[i].next_to_watch; +@@ -1119,7 +1193,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) + while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && + (count < tx_ring->count)) { + bool cleaned = false; +- rmb(); /* read buffer_info after eop_desc */ ++ rmb(); /* read buffer_info after eop_desc */ + for (; !cleaned; count++) { + tx_desc = E1000_TX_DESC(*tx_ring, i); + buffer_info = &tx_ring->buffer_info[i]; +@@ -1128,9 +1202,13 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) + if (cleaned) { + total_tx_packets += buffer_info->segs; + total_tx_bytes += buffer_info->bytecount; ++ if (buffer_info->skb) { ++ bytes_compl += buffer_info->skb->len; ++ pkts_compl++; ++ } + } + +- e1000_put_txbuf(adapter, buffer_info); ++ e1000_put_txbuf(tx_ring, buffer_info); + tx_desc->upper.data = 0; + + i++; +@@ -1146,6 +1224,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) + + tx_ring->next_to_clean = i; + ++ netdev_completed_queue(netdev, pkts_compl, bytes_compl); ++ + #define TX_WAKE_THRESHOLD 32 + if (count && netif_carrier_ok(netdev) && + e1000_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD) { +@@ -1162,11 +1242,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) + } + + if (adapter->detect_tx_hung) { +- /* +- * Detect a transmit hang in hardware, this serializes the ++ /* Detect a transmit hang in hardware, this serializes the + * check with the clearing of time_stamp and movement of i + */ +- adapter->detect_tx_hung = 0; ++ adapter->detect_tx_hung = false; + if (tx_ring->buffer_info[i].time_stamp && + time_after(jiffies, tx_ring->buffer_info[i].time_stamp + + (adapter->tx_timeout_factor * HZ)) && +@@ -1182,26 +1261,26 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) + + /** + * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split +- * @adapter: board private structure ++ * @rx_ring: Rx descriptor ring + * + * the return value indicates whether actual cleaning was done, there + * is no guarantee that everything was cleaned + **/ +-static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, +- int *work_done, int work_to_do) ++static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done, ++ int work_to_do) + { ++ struct e1000_adapter *adapter = rx_ring->adapter; + struct e1000_hw *hw = &adapter->hw; + union e1000_rx_desc_packet_split *rx_desc, *next_rxd; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; +- struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_buffer *buffer_info, *next_buffer; + struct e1000_ps_page *ps_page; + struct sk_buff *skb; + unsigned int i, j; + u32 length, staterr; + int cleaned_count = 0; +- bool cleaned = 0; ++ bool cleaned = false; + unsigned int total_rx_bytes = 0, total_rx_packets = 0; + + i = rx_ring->next_to_clean; +@@ -1227,7 +1306,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, + + next_buffer = &rx_ring->buffer_info[i]; + +- cleaned = 1; ++ cleaned = true; + cleaned_count++; + dma_unmap_single(&pdev->dev, buffer_info->dma, + adapter->rx_ps_bsize0, DMA_FROM_DEVICE); +@@ -1238,8 +1317,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, + adapter->flags2 |= FLAG2_IS_DISCARDING; + + if (adapter->flags2 & FLAG2_IS_DISCARDING) { +- e_dbg("Packet Split buffers didn't pick up the full " +- "packet\n"); ++ e_dbg("Packet Split buffers didn't pick up the full packet\n"); + dev_kfree_skb_irq(skb); + if (staterr & E1000_RXD_STAT_EOP) + adapter->flags2 &= ~FLAG2_IS_DISCARDING; +@@ -1254,8 +1332,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, + length = le16_to_cpu(rx_desc->wb.middle.length0); + + if (!length) { +- e_dbg("Last part of the packet spanning multiple " +- "descriptors\n"); ++ e_dbg("Last part of the packet spanning multiple descriptors\n"); + dev_kfree_skb_irq(skb); + goto next_desc; + } +@@ -1264,43 +1341,45 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, + skb_put(skb, length); + + { +- /* +- * this looks ugly, but it seems compiler issues make it +- * more efficient than reusing j +- */ +- int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); +- +- /* +- * page alloc/put takes too long and effects small packet +- * throughput, so unsplit small packets and save the alloc/put +- * only valid in softirq (napi) context to call kmap_* +- */ +- if (l1 && (l1 <= copybreak) && +- ((length + l1) <= adapter->rx_ps_bsize0)) { +- u8 *vaddr; +- +- ps_page = &buffer_info->ps_pages[0]; ++ /* this looks ugly, but it seems compiler issues make ++ * it more efficient than reusing j ++ */ ++ int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); + +- /* +- * there is no documentation about how to call +- * kmap_atomic, so we can't hold the mapping +- * very long ++ /* page alloc/put takes too long and effects small ++ * packet throughput, so unsplit small packets and ++ * save the alloc/put only valid in softirq (napi) ++ * context to call kmap_* + */ +- dma_sync_single_for_cpu(&pdev->dev, ps_page->dma, +- PAGE_SIZE, DMA_FROM_DEVICE); +- vaddr = kmap_atomic(ps_page->page, KM_SKB_DATA_SOFTIRQ); +- memcpy(skb_tail_pointer(skb), vaddr, l1); +- kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); +- dma_sync_single_for_device(&pdev->dev, ps_page->dma, +- PAGE_SIZE, DMA_FROM_DEVICE); +- +- /* remove the CRC */ +- if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) +- l1 -= 4; +- +- skb_put(skb, l1); +- goto copydone; +- } /* if */ ++ if (l1 && (l1 <= copybreak) && ++ ((length + l1) <= adapter->rx_ps_bsize0)) { ++ u8 *vaddr; ++ ++ ps_page = &buffer_info->ps_pages[0]; ++ ++ /* there is no documentation about how to call ++ * kmap_atomic, so we can't hold the mapping ++ * very long ++ */ ++ dma_sync_single_for_cpu(&pdev->dev, ++ ps_page->dma, ++ PAGE_SIZE, ++ DMA_FROM_DEVICE); ++ vaddr = kmap_atomic(ps_page->page); ++ memcpy(skb_tail_pointer(skb), vaddr, l1); ++ kunmap_atomic(vaddr); ++ dma_sync_single_for_device(&pdev->dev, ++ ps_page->dma, ++ PAGE_SIZE, ++ DMA_FROM_DEVICE); ++ ++ /* remove the CRC */ ++ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) ++ l1 -= 4; ++ ++ skb_put(skb, l1); ++ goto copydone; ++ } /* if */ + } + + for (j = 0; j < PS_PAGE_BUFFERS; j++) { +@@ -1329,15 +1408,16 @@ copydone: + total_rx_bytes += skb->len; + total_rx_packets++; + +- e1000_rx_checksum(adapter, staterr, le16_to_cpu( +- rx_desc->wb.lower.hi_dword.csum_ip.csum), skb); ++ e1000_rx_checksum(adapter, staterr, skb); ++ ++ e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); + + if (rx_desc->wb.upper.header_status & +- cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)) ++ cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)) + adapter->rx_hdr_split++; + +- e1000_receive_skb(adapter, netdev, skb, +- staterr, rx_desc->wb.middle.vlan); ++ e1000_receive_skb(adapter, netdev, skb, staterr, ++ rx_desc->wb.middle.vlan); + + next_desc: + rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF); +@@ -1345,7 +1425,7 @@ next_desc: + + /* return some buffers to hardware, one at a time is too slow */ + if (cleaned_count >= E1000_RX_BUFFER_WRITE) { +- adapter->alloc_rx_buf(adapter, cleaned_count, ++ adapter->alloc_rx_buf(rx_ring, cleaned_count, + GFP_ATOMIC); + cleaned_count = 0; + } +@@ -1360,7 +1440,7 @@ next_desc: + + cleaned_count = e1000_desc_unused(rx_ring); + if (cleaned_count) +- adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC); ++ adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); + + adapter->total_rx_bytes += total_rx_bytes; + adapter->total_rx_packets += total_rx_packets; +@@ -1371,7 +1451,7 @@ next_desc: + * e1000_consume_page - helper function + **/ + static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb, +- u16 length) ++ u16 length) + { + bi->page = NULL; + skb->len += length; +@@ -1386,20 +1466,20 @@ static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb, + * the return value indicates whether actual cleaning was done, there + * is no guarantee that everything was cleaned + **/ +- +-static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, +- int *work_done, int work_to_do) ++static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done, ++ int work_to_do) + { ++ struct e1000_adapter *adapter = rx_ring->adapter; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; +- struct e1000_ring *rx_ring = adapter->rx_ring; + union e1000_rx_desc_extended *rx_desc, *next_rxd; + struct e1000_buffer *buffer_info, *next_buffer; + u32 length, staterr; + unsigned int i; + int cleaned_count = 0; + bool cleaned = false; +- unsigned int total_rx_bytes=0, total_rx_packets=0; ++ unsigned int total_rx_bytes = 0, total_rx_packets = 0; ++ struct skb_shared_info *shinfo; + + i = rx_ring->next_to_clean; + rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); +@@ -1444,7 +1524,6 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, + rx_ring->rx_skb_top = NULL; + goto next_desc; + } +- + #define rxtop (rx_ring->rx_skb_top) + if (!(staterr & E1000_RXD_STAT_EOP)) { + /* this descriptor is only the beginning (or middle) */ +@@ -1452,12 +1531,13 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, + /* this is the beginning of a chain */ + rxtop = skb; + skb_fill_page_desc(rxtop, 0, buffer_info->page, +- 0, length); ++ 0, length); + } else { + /* this is the middle of a chain */ +- skb_fill_page_desc(rxtop, +- skb_shinfo(rxtop)->nr_frags, +- buffer_info->page, 0, length); ++ shinfo = skb_shinfo(rxtop); ++ skb_fill_page_desc(rxtop, shinfo->nr_frags, ++ buffer_info->page, 0, ++ length); + /* re-use the skb, only consumed the page */ + buffer_info->skb = skb; + } +@@ -1466,44 +1546,46 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, + } else { + if (rxtop) { + /* end of the chain */ +- skb_fill_page_desc(rxtop, +- skb_shinfo(rxtop)->nr_frags, +- buffer_info->page, 0, length); ++ shinfo = skb_shinfo(rxtop); ++ skb_fill_page_desc(rxtop, shinfo->nr_frags, ++ buffer_info->page, 0, ++ length); + /* re-use the current skb, we only consumed the +- * page */ ++ * page ++ */ + buffer_info->skb = skb; + skb = rxtop; + rxtop = NULL; + e1000_consume_page(buffer_info, skb, length); + } else { + /* no chain, got EOP, this buf is the packet +- * copybreak to save the put_page/alloc_page */ ++ * copybreak to save the put_page/alloc_page ++ */ + if (length <= copybreak && + skb_tailroom(skb) >= length) { + u8 *vaddr; +- vaddr = kmap_atomic(buffer_info->page, +- KM_SKB_DATA_SOFTIRQ); ++ vaddr = kmap_atomic(buffer_info->page); + memcpy(skb_tail_pointer(skb), vaddr, + length); +- kunmap_atomic(vaddr, +- KM_SKB_DATA_SOFTIRQ); ++ kunmap_atomic(vaddr); + /* re-use the page, so don't erase +- * buffer_info->page */ ++ * buffer_info->page ++ */ + skb_put(skb, length); + } else { + skb_fill_page_desc(skb, 0, +- buffer_info->page, 0, +- length); ++ buffer_info->page, 0, ++ length); + e1000_consume_page(buffer_info, skb, +- length); ++ length); + } + } + } + +- /* Receive Checksum Offload XXX recompute due to CRC strip? */ +- e1000_rx_checksum(adapter, staterr, +- le16_to_cpu(rx_desc->wb.lower.hi_dword. +- csum_ip.csum), skb); ++ /* Receive Checksum Offload */ ++ e1000_rx_checksum(adapter, staterr, skb); ++ ++ e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); + + /* probably a little skewed due to removing CRC */ + total_rx_bytes += skb->len; +@@ -1524,7 +1606,7 @@ next_desc: + + /* return some buffers to hardware, one at a time is too slow */ + if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { +- adapter->alloc_rx_buf(adapter, cleaned_count, ++ adapter->alloc_rx_buf(rx_ring, cleaned_count, + GFP_ATOMIC); + cleaned_count = 0; + } +@@ -1539,7 +1621,7 @@ next_desc: + + cleaned_count = e1000_desc_unused(rx_ring); + if (cleaned_count) +- adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC); ++ adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); + + adapter->total_rx_bytes += total_rx_bytes; + adapter->total_rx_packets += total_rx_packets; +@@ -1548,11 +1630,11 @@ next_desc: + + /** + * e1000_clean_rx_ring - Free Rx Buffers per Queue +- * @adapter: board private structure ++ * @rx_ring: Rx descriptor ring + **/ +-static void e1000_clean_rx_ring(struct e1000_adapter *adapter) ++static void e1000_clean_rx_ring(struct e1000_ring *rx_ring) + { +- struct e1000_ring *rx_ring = adapter->rx_ring; ++ struct e1000_adapter *adapter = rx_ring->adapter; + struct e1000_buffer *buffer_info; + struct e1000_ps_page *ps_page; + struct pci_dev *pdev = adapter->pdev; +@@ -1568,8 +1650,7 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) + DMA_FROM_DEVICE); + else if (adapter->clean_rx == e1000_clean_jumbo_rx_irq) + dma_unmap_page(&pdev->dev, buffer_info->dma, +- PAGE_SIZE, +- DMA_FROM_DEVICE); ++ PAGE_SIZE, DMA_FROM_DEVICE); + else if (adapter->clean_rx == e1000_clean_rx_irq_ps) + dma_unmap_single(&pdev->dev, buffer_info->dma, + adapter->rx_ps_bsize0, +@@ -1612,14 +1693,18 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) + rx_ring->next_to_use = 0; + adapter->flags2 &= ~FLAG2_IS_DISCARDING; + +- writel(0, adapter->hw.hw_addr + rx_ring->head); +- writel(0, adapter->hw.hw_addr + rx_ring->tail); ++ writel(0, rx_ring->head); ++ if (rx_ring->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) ++ e1000e_update_rdt_wa(rx_ring, 0); ++ else ++ writel(0, rx_ring->tail); + } + + static void e1000e_downshift_workaround(struct work_struct *work) + { + struct e1000_adapter *adapter = container_of(work, +- struct e1000_adapter, downshift_task); ++ struct e1000_adapter, ++ downshift_task); + + if (test_bit(__E1000_DOWN, &adapter->state)) + return; +@@ -1632,29 +1717,24 @@ static void e1000e_downshift_workaround(struct work_struct *work) + * @irq: interrupt number + * @data: pointer to a network interface device structure + **/ +-static irqreturn_t e1000_intr_msi(int irq, void *data) ++static irqreturn_t e1000_intr_msi(int __always_unused irq, void *data) + { + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 icr = er32(ICR); + +- /* +- * read ICR disables interrupts using IAM +- */ +- ++ /* read ICR disables interrupts using IAM */ + if (icr & E1000_ICR_LSC) { +- hw->mac.get_link_status = 1; +- /* +- * ICH8 workaround-- Call gig speed drop workaround on cable ++ hw->mac.get_link_status = true; ++ /* ICH8 workaround-- Call gig speed drop workaround on cable + * disconnect (LSC) before accessing any PHY registers + */ + if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && + (!(er32(STATUS) & E1000_STATUS_LU))) + schedule_work(&adapter->downshift_task); + +- /* +- * 80003ES2LAN workaround-- For packet buffer work-around on ++ /* 80003ES2LAN workaround-- For packet buffer work-around on + * link down event; disable receives here in the ISR and reset + * adapter in watchdog + */ +@@ -1663,13 +1743,30 @@ static irqreturn_t e1000_intr_msi(int irq, void *data) + /* disable receives */ + u32 rctl = er32(RCTL); + ew32(RCTL, rctl & ~E1000_RCTL_EN); +- adapter->flags |= FLAG_RX_RESTART_NOW; ++ adapter->flags |= FLAG_RESTART_NOW; + } + /* guard against interrupt when we're going down */ + if (!test_bit(__E1000_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + ++ /* Reset on uncorrectable ECC error */ ++ if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) { ++ u32 pbeccsts = er32(PBECCSTS); ++ ++ adapter->corr_errors += ++ pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; ++ adapter->uncorr_errors += ++ (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> ++ E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; ++ ++ /* Do the reset outside of interrupt context */ ++ schedule_work(&adapter->reset_task); ++ ++ /* return immediately since reset is imminent */ ++ return IRQ_HANDLED; ++ } ++ + if (napi_schedule_prep(&adapter->napi)) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; +@@ -1686,7 +1783,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data) + * @irq: interrupt number + * @data: pointer to a network interface device structure + **/ +-static irqreturn_t e1000_intr(int irq, void *data) ++static irqreturn_t e1000_intr(int __always_unused irq, void *data) + { + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); +@@ -1694,33 +1791,29 @@ static irqreturn_t e1000_intr(int irq, void *data) + u32 rctl, icr = er32(ICR); + + if (!icr || test_bit(__E1000_DOWN, &adapter->state)) +- return IRQ_NONE; /* Not our interrupt */ ++ return IRQ_NONE; /* Not our interrupt */ + +- /* +- * IMS will not auto-mask if INT_ASSERTED is not set, and if it is ++ /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is + * not set, then the adapter didn't send an interrupt + */ + if (!(icr & E1000_ICR_INT_ASSERTED)) + return IRQ_NONE; + +- /* +- * Interrupt Auto-Mask...upon reading ICR, ++ /* Interrupt Auto-Mask...upon reading ICR, + * interrupts are masked. No need for the + * IMC write + */ + + if (icr & E1000_ICR_LSC) { +- hw->mac.get_link_status = 1; +- /* +- * ICH8 workaround-- Call gig speed drop workaround on cable ++ hw->mac.get_link_status = true; ++ /* ICH8 workaround-- Call gig speed drop workaround on cable + * disconnect (LSC) before accessing any PHY registers + */ + if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && + (!(er32(STATUS) & E1000_STATUS_LU))) + schedule_work(&adapter->downshift_task); + +- /* +- * 80003ES2LAN workaround-- ++ /* 80003ES2LAN workaround-- + * For packet buffer work-around on link down event; + * disable receives here in the ISR and + * reset adapter in watchdog +@@ -1730,13 +1823,30 @@ static irqreturn_t e1000_intr(int irq, void *data) + /* disable receives */ + rctl = er32(RCTL); + ew32(RCTL, rctl & ~E1000_RCTL_EN); +- adapter->flags |= FLAG_RX_RESTART_NOW; ++ adapter->flags |= FLAG_RESTART_NOW; + } + /* guard against interrupt when we're going down */ + if (!test_bit(__E1000_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + ++ /* Reset on uncorrectable ECC error */ ++ if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) { ++ u32 pbeccsts = er32(PBECCSTS); ++ ++ adapter->corr_errors += ++ pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; ++ adapter->uncorr_errors += ++ (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> ++ E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; ++ ++ /* Do the reset outside of interrupt context */ ++ schedule_work(&adapter->reset_task); ++ ++ /* return immediately since reset is imminent */ ++ return IRQ_HANDLED; ++ } ++ + if (napi_schedule_prep(&adapter->napi)) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; +@@ -1748,7 +1858,7 @@ static irqreturn_t e1000_intr(int irq, void *data) + return IRQ_HANDLED; + } + +-static irqreturn_t e1000_msix_other(int irq, void *data) ++static irqreturn_t e1000_msix_other(int __always_unused irq, void *data) + { + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); +@@ -1767,7 +1877,7 @@ static irqreturn_t e1000_msix_other(int irq, void *data) + if (icr & E1000_ICR_OTHER) { + if (!(icr & E1000_ICR_LSC)) + goto no_link_interrupt; +- hw->mac.get_link_status = 1; ++ hw->mac.get_link_status = true; + /* guard against interrupt when we're going down */ + if (!test_bit(__E1000_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, jiffies + 1); +@@ -1780,37 +1890,36 @@ no_link_interrupt: + return IRQ_HANDLED; + } + +- +-static irqreturn_t e1000_intr_msix_tx(int irq, void *data) ++static irqreturn_t e1000_intr_msix_tx(int __always_unused irq, void *data) + { + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + struct e1000_ring *tx_ring = adapter->tx_ring; + +- + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + +- if (!e1000_clean_tx_irq(adapter)) ++ if (!e1000_clean_tx_irq(tx_ring)) + /* Ring was not completely cleaned, so fire another interrupt */ + ew32(ICS, tx_ring->ims_val); + + return IRQ_HANDLED; + } + +-static irqreturn_t e1000_intr_msix_rx(int irq, void *data) ++static irqreturn_t e1000_intr_msix_rx(int __always_unused irq, void *data) + { + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct e1000_ring *rx_ring = adapter->rx_ring; + + /* Write the ITR value calculated at the end of the + * previous interrupt. + */ +- if (adapter->rx_ring->set_itr) { +- writel(1000000000 / (adapter->rx_ring->itr_val * 256), +- adapter->hw.hw_addr + adapter->rx_ring->itr_register); +- adapter->rx_ring->set_itr = 0; ++ if (rx_ring->set_itr) { ++ writel(1000000000 / (rx_ring->itr_val * 256), ++ rx_ring->itr_register); ++ rx_ring->set_itr = 0; + } + + if (napi_schedule_prep(&adapter->napi)) { +@@ -1844,15 +1953,14 @@ static void e1000_configure_msix(struct e1000_adapter *adapter) + ew32(RFCTL, rfctl); + } + +-#define E1000_IVAR_INT_ALLOC_VALID 0x8 + /* Configure Rx vector */ + rx_ring->ims_val = E1000_IMS_RXQ0; + adapter->eiac_mask |= rx_ring->ims_val; + if (rx_ring->itr_val) + writel(1000000000 / (rx_ring->itr_val * 256), +- hw->hw_addr + rx_ring->itr_register); ++ rx_ring->itr_register); + else +- writel(1, hw->hw_addr + rx_ring->itr_register); ++ writel(1, rx_ring->itr_register); + ivar = E1000_IVAR_INT_ALLOC_VALID | vector; + + /* Configure Tx vector */ +@@ -1860,9 +1968,9 @@ static void e1000_configure_msix(struct e1000_adapter *adapter) + vector++; + if (tx_ring->itr_val) + writel(1000000000 / (tx_ring->itr_val * 256), +- hw->hw_addr + tx_ring->itr_register); ++ tx_ring->itr_register); + else +- writel(1, hw->hw_addr + tx_ring->itr_register); ++ writel(1, tx_ring->itr_register); + adapter->eiac_mask |= tx_ring->ims_val; + ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 8); + +@@ -1885,7 +1993,6 @@ static void e1000_configure_msix(struct e1000_adapter *adapter) + ctrl_ext |= E1000_CTRL_EXT_PBA_CLR; + + /* Auto-Mask Other interrupts upon ICR read */ +-#define E1000_EIAC_MASK_82574 0x01F00000 + ew32(IAM, ~E1000_EIAC_MASK_82574 | E1000_IMS_OTHER); + ctrl_ext |= E1000_CTRL_EXT_EIAME; + ew32(CTRL_EXT, ctrl_ext); +@@ -1920,8 +2027,9 @@ void e1000e_set_interrupt_capability(struct e1000_adapter *adapter) + if (adapter->flags & FLAG_HAS_MSIX) { + adapter->num_vectors = 3; /* RxQ0, TxQ0 and other */ + adapter->msix_entries = kcalloc(adapter->num_vectors, +- sizeof(struct msix_entry), +- GFP_KERNEL); ++ sizeof(struct ++ msix_entry), ++ GFP_KERNEL); + if (adapter->msix_entries) { + for (i = 0; i < adapter->num_vectors; i++) + adapter->msix_entries[i].entry = i; +@@ -1933,8 +2041,7 @@ void e1000e_set_interrupt_capability(struct e1000_adapter *adapter) + return; + } + /* MSI-X failed, so fall through and try MSI */ +- e_err("Failed to initialize MSI-X interrupts. " +- "Falling back to MSI interrupts.\n"); ++ e_err("Failed to initialize MSI-X interrupts. Falling back to MSI interrupts.\n"); + e1000e_reset_interrupt_capability(adapter); + } + adapter->int_mode = E1000E_INT_MODE_MSI; +@@ -1944,8 +2051,7 @@ void e1000e_set_interrupt_capability(struct e1000_adapter *adapter) + adapter->flags |= FLAG_MSI_ENABLED; + } else { + adapter->int_mode = E1000E_INT_MODE_LEGACY; +- e_err("Failed to initialize MSI interrupts. Falling " +- "back to legacy interrupts.\n"); ++ e_err("Failed to initialize MSI interrupts. Falling back to legacy interrupts.\n"); + } + /* Fall through */ + case E1000E_INT_MODE_LEGACY: +@@ -1978,8 +2084,9 @@ static int e1000_request_msix(struct e1000_adapter *adapter) + e1000_intr_msix_rx, 0, adapter->rx_ring->name, + netdev); + if (err) +- goto out; +- adapter->rx_ring->itr_register = E1000_EITR_82574(vector); ++ return err; ++ adapter->rx_ring->itr_register = adapter->hw.hw_addr + ++ E1000_EITR_82574(vector); + adapter->rx_ring->itr_val = adapter->itr; + vector++; + +@@ -1993,20 +2100,20 @@ static int e1000_request_msix(struct e1000_adapter *adapter) + e1000_intr_msix_tx, 0, adapter->tx_ring->name, + netdev); + if (err) +- goto out; +- adapter->tx_ring->itr_register = E1000_EITR_82574(vector); ++ return err; ++ adapter->tx_ring->itr_register = adapter->hw.hw_addr + ++ E1000_EITR_82574(vector); + adapter->tx_ring->itr_val = adapter->itr; + vector++; + + err = request_irq(adapter->msix_entries[vector].vector, + e1000_msix_other, 0, netdev->name, netdev); + if (err) +- goto out; ++ return err; + + e1000_configure_msix(adapter); ++ + return 0; +-out: +- return err; + } + + /** +@@ -2100,6 +2207,8 @@ static void e1000_irq_enable(struct e1000_adapter *adapter) + if (adapter->msix_entries) { + ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574); + ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC); ++ } else if (hw->mac.type == e1000_pch_lpt) { ++ ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER); + } else { + ew32(IMS, IMS_ENABLE_MASK); + } +@@ -2158,7 +2267,7 @@ void e1000e_release_hw_control(struct e1000_adapter *adapter) + } + + /** +- * @e1000_alloc_ring - allocate memory for a ring structure ++ * e1000_alloc_ring_dma - allocate memory for a ring structure + **/ + static int e1000_alloc_ring_dma(struct e1000_adapter *adapter, + struct e1000_ring *ring) +@@ -2175,13 +2284,13 @@ static int e1000_alloc_ring_dma(struct e1000_adapter *adapter, + + /** + * e1000e_setup_tx_resources - allocate Tx resources (Descriptors) +- * @adapter: board private structure ++ * @tx_ring: Tx descriptor ring + * + * Return 0 on success, negative on failure + **/ +-int e1000e_setup_tx_resources(struct e1000_adapter *adapter) ++int e1000e_setup_tx_resources(struct e1000_ring *tx_ring) + { +- struct e1000_ring *tx_ring = adapter->tx_ring; ++ struct e1000_adapter *adapter = tx_ring->adapter; + int err = -ENOMEM, size; + + size = sizeof(struct e1000_buffer) * tx_ring->count; +@@ -2209,13 +2318,13 @@ err: + + /** + * e1000e_setup_rx_resources - allocate Rx resources (Descriptors) +- * @adapter: board private structure ++ * @rx_ring: Rx descriptor ring + * + * Returns 0 on success, negative on failure + **/ +-int e1000e_setup_rx_resources(struct e1000_adapter *adapter) ++int e1000e_setup_rx_resources(struct e1000_ring *rx_ring) + { +- struct e1000_ring *rx_ring = adapter->rx_ring; ++ struct e1000_adapter *adapter = rx_ring->adapter; + struct e1000_buffer *buffer_info; + int i, size, desc_len, err = -ENOMEM; + +@@ -2262,20 +2371,21 @@ err: + + /** + * e1000_clean_tx_ring - Free Tx Buffers +- * @adapter: board private structure ++ * @tx_ring: Tx descriptor ring + **/ +-static void e1000_clean_tx_ring(struct e1000_adapter *adapter) ++static void e1000_clean_tx_ring(struct e1000_ring *tx_ring) + { +- struct e1000_ring *tx_ring = adapter->tx_ring; ++ struct e1000_adapter *adapter = tx_ring->adapter; + struct e1000_buffer *buffer_info; + unsigned long size; + unsigned int i; + + for (i = 0; i < tx_ring->count; i++) { + buffer_info = &tx_ring->buffer_info[i]; +- e1000_put_txbuf(adapter, buffer_info); ++ e1000_put_txbuf(tx_ring, buffer_info); + } + ++ netdev_reset_queue(adapter->netdev); + size = sizeof(struct e1000_buffer) * tx_ring->count; + memset(tx_ring->buffer_info, 0, size); + +@@ -2284,22 +2394,25 @@ static void e1000_clean_tx_ring(struct e1000_adapter *adapter) + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; + +- writel(0, adapter->hw.hw_addr + tx_ring->head); +- writel(0, adapter->hw.hw_addr + tx_ring->tail); ++ writel(0, tx_ring->head); ++ if (tx_ring->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) ++ e1000e_update_tdt_wa(tx_ring, 0); ++ else ++ writel(0, tx_ring->tail); + } + + /** + * e1000e_free_tx_resources - Free Tx Resources per Queue +- * @adapter: board private structure ++ * @tx_ring: Tx descriptor ring + * + * Free all transmit software resources + **/ +-void e1000e_free_tx_resources(struct e1000_adapter *adapter) ++void e1000e_free_tx_resources(struct e1000_ring *tx_ring) + { ++ struct e1000_adapter *adapter = tx_ring->adapter; + struct pci_dev *pdev = adapter->pdev; +- struct e1000_ring *tx_ring = adapter->tx_ring; + +- e1000_clean_tx_ring(adapter); ++ e1000_clean_tx_ring(tx_ring); + + vfree(tx_ring->buffer_info); + tx_ring->buffer_info = NULL; +@@ -2311,18 +2424,17 @@ void e1000e_free_tx_resources(struct e1000_adapter *adapter) + + /** + * e1000e_free_rx_resources - Free Rx Resources +- * @adapter: board private structure ++ * @rx_ring: Rx descriptor ring + * + * Free all receive software resources + **/ +- +-void e1000e_free_rx_resources(struct e1000_adapter *adapter) ++void e1000e_free_rx_resources(struct e1000_ring *rx_ring) + { ++ struct e1000_adapter *adapter = rx_ring->adapter; + struct pci_dev *pdev = adapter->pdev; +- struct e1000_ring *rx_ring = adapter->rx_ring; + int i; + +- e1000_clean_rx_ring(adapter); ++ e1000_clean_rx_ring(rx_ring); + + for (i = 0; i < rx_ring->count; i++) + kfree(rx_ring->buffer_info[i].ps_pages); +@@ -2351,39 +2463,37 @@ void e1000e_free_rx_resources(struct e1000_adapter *adapter) + * while increasing bulk throughput. This functionality is controlled + * by the InterruptThrottleRate module parameter. + **/ +-static unsigned int e1000_update_itr(struct e1000_adapter *adapter, +- u16 itr_setting, int packets, +- int bytes) ++static unsigned int e1000_update_itr(u16 itr_setting, int packets, int bytes) + { + unsigned int retval = itr_setting; + + if (packets == 0) +- goto update_itr_done; ++ return itr_setting; + + switch (itr_setting) { + case lowest_latency: + /* handle TSO and jumbo frames */ +- if (bytes/packets > 8000) ++ if (bytes / packets > 8000) + retval = bulk_latency; + else if ((packets < 5) && (bytes > 512)) + retval = low_latency; + break; +- case low_latency: /* 50 usec aka 20000 ints/s */ ++ case low_latency: /* 50 usec aka 20000 ints/s */ + if (bytes > 10000) { + /* this if handles the TSO accounting */ +- if (bytes/packets > 8000) ++ if (bytes / packets > 8000) + retval = bulk_latency; +- else if ((packets < 10) || ((bytes/packets) > 1200)) ++ else if ((packets < 10) || ((bytes / packets) > 1200)) + retval = bulk_latency; + else if ((packets > 35)) + retval = lowest_latency; +- } else if (bytes/packets > 2000) { ++ } else if (bytes / packets > 2000) { + retval = bulk_latency; + } else if (packets <= 2 && bytes < 512) { + retval = lowest_latency; + } + break; +- case bulk_latency: /* 250 usec aka 4000 ints/s */ ++ case bulk_latency: /* 250 usec aka 4000 ints/s */ + if (bytes > 25000) { + if (packets > 35) + retval = low_latency; +@@ -2393,13 +2503,11 @@ static unsigned int e1000_update_itr(struct e1000_adapter *adapter, + break; + } + +-update_itr_done: + return retval; + } + + static void e1000_set_itr(struct e1000_adapter *adapter) + { +- struct e1000_hw *hw = &adapter->hw; + u16 current_itr; + u32 new_itr = adapter->itr; + +@@ -2415,31 +2523,29 @@ static void e1000_set_itr(struct e1000_adapter *adapter) + goto set_itr_now; + } + +- adapter->tx_itr = e1000_update_itr(adapter, +- adapter->tx_itr, +- adapter->total_tx_packets, +- adapter->total_tx_bytes); ++ adapter->tx_itr = e1000_update_itr(adapter->tx_itr, ++ adapter->total_tx_packets, ++ adapter->total_tx_bytes); + /* conservative mode (itr 3) eliminates the lowest_latency setting */ + if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) + adapter->tx_itr = low_latency; + +- adapter->rx_itr = e1000_update_itr(adapter, +- adapter->rx_itr, +- adapter->total_rx_packets, +- adapter->total_rx_bytes); ++ adapter->rx_itr = e1000_update_itr(adapter->rx_itr, ++ adapter->total_rx_packets, ++ adapter->total_rx_bytes); + /* conservative mode (itr 3) eliminates the lowest_latency setting */ + if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) + adapter->rx_itr = low_latency; + + current_itr = max(adapter->rx_itr, adapter->tx_itr); + +- switch (current_itr) { + /* counts and packets in update_itr are dependent on these numbers */ ++ switch (current_itr) { + case lowest_latency: + new_itr = 70000; + break; + case low_latency: +- new_itr = 20000; /* aka hwitr = ~200 */ ++ new_itr = 20000; /* aka hwitr = ~200 */ + break; + case bulk_latency: + new_itr = 4000; +@@ -2450,23 +2556,42 @@ static void e1000_set_itr(struct e1000_adapter *adapter) + + set_itr_now: + if (new_itr != adapter->itr) { +- /* +- * this attempts to bias the interrupt rate towards Bulk ++ /* this attempts to bias the interrupt rate towards Bulk + * by adding intermediate steps when interrupt rate is + * increasing + */ + new_itr = new_itr > adapter->itr ? +- min(adapter->itr + (new_itr >> 2), new_itr) : +- new_itr; ++ min(adapter->itr + (new_itr >> 2), new_itr) : new_itr; + adapter->itr = new_itr; + adapter->rx_ring->itr_val = new_itr; + if (adapter->msix_entries) + adapter->rx_ring->set_itr = 1; + else +- if (new_itr) +- ew32(ITR, 1000000000 / (new_itr * 256)); +- else +- ew32(ITR, 0); ++ e1000e_write_itr(adapter, new_itr); ++ } ++} ++ ++/** ++ * e1000e_write_itr - write the ITR value to the appropriate registers ++ * @adapter: address of board private structure ++ * @itr: new ITR value to program ++ * ++ * e1000e_write_itr determines if the adapter is in MSI-X mode ++ * and, if so, writes the EITR registers with the ITR value. ++ * Otherwise, it writes the ITR value into the ITR register. ++ **/ ++void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 new_itr = itr ? 1000000000 / (itr * 256) : 0; ++ ++ if (adapter->msix_entries) { ++ int vector; ++ ++ for (vector = 0; vector < adapter->num_vectors; vector++) ++ writel(new_itr, hw->hw_addr + E1000_EITR_82574(vector)); ++ } else { ++ ew32(ITR, new_itr); + } + } + +@@ -2474,15 +2599,21 @@ set_itr_now: + * e1000_alloc_queues - Allocate memory for all rings + * @adapter: board private structure to initialize + **/ +-static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter) ++static int e1000_alloc_queues(struct e1000_adapter *adapter) + { +- adapter->tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); ++ int size = sizeof(struct e1000_ring); ++ ++ adapter->tx_ring = kzalloc(size, GFP_KERNEL); + if (!adapter->tx_ring) + goto err; ++ adapter->tx_ring->count = adapter->tx_ring_count; ++ adapter->tx_ring->adapter = adapter; + +- adapter->rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); ++ adapter->rx_ring = kzalloc(size, GFP_KERNEL); + if (!adapter->rx_ring) + goto err; ++ adapter->rx_ring->count = adapter->rx_ring_count; ++ adapter->rx_ring->adapter = adapter; + + return 0; + err: +@@ -2493,33 +2624,31 @@ err: + } + + /** +- * e1000_clean - NAPI Rx polling callback ++ * e1000e_poll - NAPI Rx polling callback + * @napi: struct associated with this polling callback +- * @budget: amount of packets driver is allowed to process this poll ++ * @weight: number of packets driver is allowed to process this poll + **/ +-static int e1000_clean(struct napi_struct *napi, int budget) ++static int e1000e_poll(struct napi_struct *napi, int weight) + { +- struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi); ++ struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, ++ napi); + struct e1000_hw *hw = &adapter->hw; + struct net_device *poll_dev = adapter->netdev; + int tx_cleaned = 1, work_done = 0; + + adapter = netdev_priv(poll_dev); + +- if (adapter->msix_entries && +- !(adapter->rx_ring->ims_val & adapter->tx_ring->ims_val)) +- goto clean_rx; +- +- tx_cleaned = e1000_clean_tx_irq(adapter); ++ if (!adapter->msix_entries || ++ (adapter->rx_ring->ims_val & adapter->tx_ring->ims_val)) ++ tx_cleaned = e1000_clean_tx_irq(adapter->tx_ring); + +-clean_rx: +- adapter->clean_rx(adapter, &work_done, budget); ++ adapter->clean_rx(adapter->rx_ring, &work_done, weight); + + if (!tx_cleaned) +- work_done = budget; ++ work_done = weight; + +- /* If budget not fully consumed, exit the polling mode */ +- if (work_done < budget) { ++ /* If weight not fully consumed, exit the polling mode */ ++ if (work_done < weight) { + if (adapter->itr_setting & 3) + e1000_set_itr(adapter); + napi_complete(napi); +@@ -2659,8 +2788,7 @@ static void e1000_update_mng_vlan(struct e1000_adapter *adapter) + u16 vid = adapter->hw.mng_cookie.vlan_id; + u16 old_vid = adapter->mng_vlan_id; + +- if (adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN) { ++ if (adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) { + e1000_vlan_rx_add_vid(netdev, vid); + adapter->mng_vlan_id = vid; + } +@@ -2676,7 +2804,7 @@ static void e1000_restore_vlan(struct e1000_adapter *adapter) + e1000_vlan_rx_add_vid(adapter->netdev, 0); + + for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) +- e1000_vlan_rx_add_vid(adapter->netdev, vid); ++ e1000_vlan_rx_add_vid(adapter->netdev, vid); + } + + static void e1000_init_manageability_pt(struct e1000_adapter *adapter) +@@ -2689,8 +2817,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter) + + manc = er32(MANC); + +- /* +- * enable receiving management packets to the host. this will probably ++ /* enable receiving management packets to the host. this will probably + * generate destination unreachable messages from the host OS, but + * the packets will be handled on SMBUS + */ +@@ -2703,8 +2830,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter) + break; + case e1000_82574: + case e1000_82583: +- /* +- * Check if IPMI pass-through decision filter already exists; ++ /* Check if IPMI pass-through decision filter already exists; + * if so, enable it. + */ + for (i = 0, j = 0; i < 8; i++) { +@@ -2754,31 +2880,18 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) + struct e1000_hw *hw = &adapter->hw; + struct e1000_ring *tx_ring = adapter->tx_ring; + u64 tdba; +- u32 tdlen, tctl, tipg, tarc; +- u32 ipgr1, ipgr2; ++ u32 tdlen, tarc; + + /* Setup the HW Tx Head and Tail descriptor pointers */ + tdba = tx_ring->dma; + tdlen = tx_ring->count * sizeof(struct e1000_tx_desc); +- ew32(TDBAL, (tdba & DMA_BIT_MASK(32))); +- ew32(TDBAH, (tdba >> 32)); +- ew32(TDLEN, tdlen); +- ew32(TDH, 0); +- ew32(TDT, 0); +- tx_ring->head = E1000_TDH; +- tx_ring->tail = E1000_TDT; +- +- /* Set the default values for the Tx Inter Packet Gap timer */ +- tipg = DEFAULT_82543_TIPG_IPGT_COPPER; /* 8 */ +- ipgr1 = DEFAULT_82543_TIPG_IPGR1; /* 8 */ +- ipgr2 = DEFAULT_82543_TIPG_IPGR2; /* 6 */ +- +- if (adapter->flags & FLAG_TIPG_MEDIUM_FOR_80003ESLAN) +- ipgr2 = DEFAULT_80003ES2LAN_TIPG_IPGR2; /* 7 */ +- +- tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT; +- tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT; +- ew32(TIPG, tipg); ++ ew32(TDBAL(0), (tdba & DMA_BIT_MASK(32))); ++ ew32(TDBAH(0), (tdba >> 32)); ++ ew32(TDLEN(0), tdlen); ++ ew32(TDH(0), 0); ++ ew32(TDT(0), 0); ++ tx_ring->head = adapter->hw.hw_addr + E1000_TDH(0); ++ tx_ring->tail = adapter->hw.hw_addr + E1000_TDT(0); + + /* Set the Tx Interrupt Delay register */ + ew32(TIDV, adapter->tx_int_delay); +@@ -2789,11 +2902,10 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) + u32 txdctl = er32(TXDCTL(0)); + txdctl &= ~(E1000_TXDCTL_PTHRESH | E1000_TXDCTL_HTHRESH | + E1000_TXDCTL_WTHRESH); +- /* +- * set up some performance related parameters to encourage the ++ /* set up some performance related parameters to encourage the + * hardware to use the bus more efficiently in bursts, depends + * on the tx_int_delay to be enabled, +- * wthresh = 5 ==> burst write a cacheline (64 bytes) at a time ++ * wthresh = 1 ==> burst write is disabled to avoid Tx stalls + * hthresh = 1 ==> prefetch when one or more available + * pthresh = 0x1f ==> prefetch if internal cache 31 or less + * BEWARE: this seems to work but should be considered first if +@@ -2801,20 +2913,13 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) + */ + txdctl |= E1000_TXDCTL_DMA_BURST_ENABLE; + ew32(TXDCTL(0), txdctl); +- /* erratum work around: set txdctl the same for both queues */ +- ew32(TXDCTL(1), txdctl); + } +- +- /* Program the Transmit Control Register */ +- tctl = er32(TCTL); +- tctl &= ~E1000_TCTL_CT; +- tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | +- (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); ++ /* erratum work around: set txdctl the same for both queues */ ++ ew32(TXDCTL(1), er32(TXDCTL(0))); + + if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) { + tarc = er32(TARC(0)); +- /* +- * set the speed mode bit, we'll clear it if we're not at ++ /* set the speed mode bit, we'll clear it if we're not at + * gigabit link later + */ + #define SPEED_MODE_BIT (1 << 21) +@@ -2842,9 +2947,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) + /* enable Report Status bit */ + adapter->txd_cmd |= E1000_TXD_CMD_RS; + +- ew32(TCTL, tctl); +- +- e1000e_config_collision_dist(hw); ++ hw->mac.ops.config_collision_dist(hw); + } + + /** +@@ -2859,25 +2962,18 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) + u32 rctl, rfctl; + u32 pages = 0; + +- /* Workaround Si errata on 82579 - configure jumbo frame flow */ +- if (hw->mac.type == e1000_pch2lan) { +- s32 ret_val; +- +- if (adapter->netdev->mtu > ETH_DATA_LEN) +- ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); +- else +- ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); +- +- if (ret_val) +- e_dbg("failed to enable jumbo frame workaround mode\n"); +- } ++ /* Workaround Si errata on PCHx - configure jumbo frame flow */ ++ if ((hw->mac.type >= e1000_pch2lan) && ++ (adapter->netdev->mtu > ETH_DATA_LEN) && ++ e1000_lv_jumbo_workaround_ich8lan(hw, true)) ++ e_dbg("failed to enable jumbo frame workaround mode\n"); + + /* Program MC offset vector base */ + rctl = er32(RCTL); + rctl &= ~(3 << E1000_RCTL_MO_SHIFT); + rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | +- E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | +- (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); ++ E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | ++ (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); + + /* Do not Store bad packets */ + rctl &= ~E1000_RCTL_SBP; +@@ -2935,9 +3031,9 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) + /* Enable Extended Status in all Receive Descriptors */ + rfctl = er32(RFCTL); + rfctl |= E1000_RFCTL_EXTEN; ++ ew32(RFCTL, rfctl); + +- /* +- * 82571 and greater support packet-split where the protocol ++ /* 82571 and greater support packet-split where the protocol + * header is placed in skb->data and the packet data is + * placed in pages hanging off of skb_shinfo(skb)->nr_frags. + * In the case of a non-split, skb->data is linearly filled, +@@ -2952,8 +3048,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) + * per packet. + */ + pages = PAGE_USE_COUNT(adapter->netdev->mtu); +- if (!(adapter->flags & FLAG_HAS_ERT) && (pages <= 3) && +- (PAGE_SIZE <= 16384) && (rctl & E1000_RCTL_LPE)) ++ if ((pages <= 3) && (PAGE_SIZE <= 16384) && (rctl & E1000_RCTL_LPE)) + adapter->rx_ps_pages = pages; + else + adapter->rx_ps_pages = 0; +@@ -2961,39 +3056,29 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) + if (adapter->rx_ps_pages) { + u32 psrctl = 0; + +- /* +- * disable packet split support for IPv6 extension headers, +- * because some malformed IPv6 headers can hang the Rx +- */ +- rfctl |= (E1000_RFCTL_IPV6_EX_DIS | +- E1000_RFCTL_NEW_IPV6_EXT_DIS); +- + /* Enable Packet split descriptors */ + rctl |= E1000_RCTL_DTYP_PS; + +- psrctl |= adapter->rx_ps_bsize0 >> +- E1000_PSRCTL_BSIZE0_SHIFT; ++ psrctl |= adapter->rx_ps_bsize0 >> E1000_PSRCTL_BSIZE0_SHIFT; + + switch (adapter->rx_ps_pages) { + case 3: +- psrctl |= PAGE_SIZE << +- E1000_PSRCTL_BSIZE3_SHIFT; ++ psrctl |= PAGE_SIZE << E1000_PSRCTL_BSIZE3_SHIFT; ++ /* fall-through */ + case 2: +- psrctl |= PAGE_SIZE << +- E1000_PSRCTL_BSIZE2_SHIFT; ++ psrctl |= PAGE_SIZE << E1000_PSRCTL_BSIZE2_SHIFT; ++ /* fall-through */ + case 1: +- psrctl |= PAGE_SIZE >> +- E1000_PSRCTL_BSIZE1_SHIFT; ++ psrctl |= PAGE_SIZE >> E1000_PSRCTL_BSIZE1_SHIFT; + break; + } + + ew32(PSRCTL, psrctl); + } + +- ew32(RFCTL, rfctl); + ew32(RCTL, rctl); + /* just started the receive unit, no need to restart */ +- adapter->flags &= ~FLAG_RX_RESTART_NOW; ++ adapter->flags &= ~FLAG_RESTART_NOW; + } + + /** +@@ -3033,8 +3118,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) + usleep_range(10000, 20000); + + if (adapter->flags2 & FLAG2_DMA_BURST) { +- /* +- * set the writeback threshold (only takes effect if the RDTR ++ /* set the writeback threshold (only takes effect if the RDTR + * is set). set GRAN=1 and write back up to 0x4 worth, and + * enable prefetching of 0x20 Rx descriptors + * granularity = 01 +@@ -3045,8 +3129,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) + ew32(RXDCTL(0), E1000_RXDCTL_DMA_BURST_ENABLE); + ew32(RXDCTL(1), E1000_RXDCTL_DMA_BURST_ENABLE); + +- /* +- * override the delay timers for enabling bursting, only if ++ /* override the delay timers for enabling bursting, only if + * the value was not set by the user via module options + */ + if (adapter->rx_int_delay == DEFAULT_RDTR) +@@ -3061,7 +3144,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) + /* irq moderation */ + ew32(RADV, adapter->rx_abs_int_delay); + if ((adapter->itr_setting != 0) && (adapter->itr != 0)) +- ew32(ITR, 1000000000 / (adapter->itr * 256)); ++ e1000e_write_itr(adapter, adapter->itr); + + ctrl_ext = er32(CTRL_EXT); + /* Auto-Mask interrupts upon ICR access */ +@@ -3070,58 +3153,43 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) + ew32(CTRL_EXT, ctrl_ext); + e1e_flush(); + +- /* +- * Setup the HW Rx Head and Tail Descriptor Pointers and ++ /* Setup the HW Rx Head and Tail Descriptor Pointers and + * the Base and Length of the Rx Descriptor Ring + */ + rdba = rx_ring->dma; +- ew32(RDBAL, (rdba & DMA_BIT_MASK(32))); +- ew32(RDBAH, (rdba >> 32)); +- ew32(RDLEN, rdlen); +- ew32(RDH, 0); +- ew32(RDT, 0); +- rx_ring->head = E1000_RDH; +- rx_ring->tail = E1000_RDT; ++ ew32(RDBAL(0), (rdba & DMA_BIT_MASK(32))); ++ ew32(RDBAH(0), (rdba >> 32)); ++ ew32(RDLEN(0), rdlen); ++ ew32(RDH(0), 0); ++ ew32(RDT(0), 0); ++ rx_ring->head = adapter->hw.hw_addr + E1000_RDH(0); ++ rx_ring->tail = adapter->hw.hw_addr + E1000_RDT(0); + + /* Enable Receive Checksum Offload for TCP and UDP */ + rxcsum = er32(RXCSUM); +- if (adapter->netdev->features & NETIF_F_RXCSUM) { ++ if (adapter->netdev->features & NETIF_F_RXCSUM) + rxcsum |= E1000_RXCSUM_TUOFL; +- +- /* +- * IPv4 payload checksum for UDP fragments must be +- * used in conjunction with packet-split. +- */ +- if (adapter->rx_ps_pages) +- rxcsum |= E1000_RXCSUM_IPPCSE; +- } else { ++ else + rxcsum &= ~E1000_RXCSUM_TUOFL; +- /* no need to clear IPPCSE as it defaults to 0 */ +- } + ew32(RXCSUM, rxcsum); + +- /* +- * Enable early receives on supported devices, only takes effect when +- * packet size is equal or larger than the specified value (in 8 byte +- * units), e.g. using jumbo frames when setting to E1000_ERT_2048 ++ /* With jumbo frames, excessive C-state transition latencies result ++ * in dropped transactions. + */ +- if ((adapter->flags & FLAG_HAS_ERT) || +- (adapter->hw.mac.type == e1000_pch2lan)) { +- if (adapter->netdev->mtu > ETH_DATA_LEN) { ++ if (adapter->netdev->mtu > ETH_DATA_LEN) { ++ u32 lat = ++ ((er32(PBA) & E1000_PBA_RXA_MASK) * 1024 - ++ adapter->max_frame_size) * 8 / 1000; ++ ++ if (adapter->flags & FLAG_IS_ICH) { + u32 rxdctl = er32(RXDCTL(0)); + ew32(RXDCTL(0), rxdctl | 0x3); +- if (adapter->flags & FLAG_HAS_ERT) +- ew32(ERT, E1000_ERT_2048 | (1 << 13)); +- /* +- * With jumbo frames and early-receive enabled, +- * excessive C-state transition latencies result in +- * dropped transactions. +- */ +- pm_qos_update_request(&adapter->netdev->pm_qos_req, 55); +- } else { +- pm_qos_update_request(&adapter->netdev->pm_qos_req, +- PM_QOS_DEFAULT_VALUE); + } ++ ++ pm_qos_update_request(&adapter->netdev->pm_qos_req, lat); ++ } else { ++ pm_qos_update_request(&adapter->netdev->pm_qos_req, ++ PM_QOS_DEFAULT_VALUE); + } + + /* Enable Receives */ +@@ -3129,84 +3197,424 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) + } + + /** +- * e1000_update_mc_addr_list - Update Multicast addresses +- * @hw: pointer to the HW structure +- * @mc_addr_list: array of multicast addresses to program +- * @mc_addr_count: number of multicast addresses to program ++ * e1000e_write_mc_addr_list - write multicast addresses to MTA ++ * @netdev: network interface device structure + * +- * Updates the Multicast Table Array. +- * The caller must have a packed mc_addr_list of multicast addresses. ++ * Writes multicast address list to the MTA hash table. ++ * Returns: -ENOMEM on failure ++ * 0 on no addresses written ++ * X on writing X addresses to MTA ++ */ ++static int e1000e_write_mc_addr_list(struct net_device *netdev) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ struct netdev_hw_addr *ha; ++ u8 *mta_list; ++ int i; ++ ++ if (netdev_mc_empty(netdev)) { ++ /* nothing to program, so clear mc list */ ++ hw->mac.ops.update_mc_addr_list(hw, NULL, 0); ++ return 0; ++ } ++ ++ mta_list = kzalloc(netdev_mc_count(netdev) * ETH_ALEN, GFP_ATOMIC); ++ if (!mta_list) ++ return -ENOMEM; ++ ++ /* update_mc_addr_list expects a packed array of only addresses. */ ++ i = 0; ++ netdev_for_each_mc_addr(ha, netdev) ++ memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); ++ ++ hw->mac.ops.update_mc_addr_list(hw, mta_list, i); ++ kfree(mta_list); ++ ++ return netdev_mc_count(netdev); ++} ++ ++/** ++ * e1000e_write_uc_addr_list - write unicast addresses to RAR table ++ * @netdev: network interface device structure ++ * ++ * Writes unicast address list to the RAR table. ++ * Returns: -ENOMEM on failure/insufficient address space ++ * 0 on no addresses written ++ * X on writing X addresses to the RAR table + **/ +-static void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list, +- u32 mc_addr_count) ++static int e1000e_write_uc_addr_list(struct net_device *netdev) + { +- hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count); ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ unsigned int rar_entries = hw->mac.rar_entry_count; ++ int count = 0; ++ ++ /* save a rar entry for our hardware address */ ++ rar_entries--; ++ ++ /* save a rar entry for the LAA workaround */ ++ if (adapter->flags & FLAG_RESET_OVERWRITES_LAA) ++ rar_entries--; ++ ++ /* return ENOMEM indicating insufficient memory for addresses */ ++ if (netdev_uc_count(netdev) > rar_entries) ++ return -ENOMEM; ++ ++ if (!netdev_uc_empty(netdev) && rar_entries) { ++ struct netdev_hw_addr *ha; ++ ++ /* write the addresses in reverse order to avoid write ++ * combining ++ */ ++ netdev_for_each_uc_addr(ha, netdev) { ++ if (!rar_entries) ++ break; ++ hw->mac.ops.rar_set(hw, ha->addr, rar_entries--); ++ count++; ++ } ++ } ++ ++ /* zero out the remaining RAR entries not used above */ ++ for (; rar_entries > 0; rar_entries--) { ++ ew32(RAH(rar_entries), 0); ++ ew32(RAL(rar_entries), 0); ++ } ++ e1e_flush(); ++ ++ return count; + } + + /** +- * e1000_set_multi - Multicast and Promiscuous mode set ++ * e1000e_set_rx_mode - secondary unicast, Multicast and Promiscuous mode set + * @netdev: network interface device structure + * +- * The set_multi entry point is called whenever the multicast address +- * list or the network interface flags are updated. This routine is +- * responsible for configuring the hardware for proper multicast, ++ * The ndo_set_rx_mode entry point is called whenever the unicast or multicast ++ * address list or the network interface flags are updated. This routine is ++ * responsible for configuring the hardware for proper unicast, multicast, + * promiscuous mode, and all-multi behavior. + **/ +-static void e1000_set_multi(struct net_device *netdev) ++static void e1000e_set_rx_mode(struct net_device *netdev) + { + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; +- struct netdev_hw_addr *ha; +- u8 *mta_list; + u32 rctl; + + /* Check for Promiscuous and All Multicast modes */ +- + rctl = er32(RCTL); + ++ /* clear the affected bits */ ++ rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); ++ + if (netdev->flags & IFF_PROMISC) { + rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); +- rctl &= ~E1000_RCTL_VFE; + /* Do not hardware filter VLANs in promisc mode */ + e1000e_vlan_filter_disable(adapter); + } else { ++ int count; ++ + if (netdev->flags & IFF_ALLMULTI) { + rctl |= E1000_RCTL_MPE; +- rctl &= ~E1000_RCTL_UPE; + } else { +- rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); ++ /* Write addresses to the MTA, if the attempt fails ++ * then we should just turn on promiscuous mode so ++ * that we can at least receive multicast traffic ++ */ ++ count = e1000e_write_mc_addr_list(netdev); ++ if (count < 0) ++ rctl |= E1000_RCTL_MPE; + } + e1000e_vlan_filter_enable(adapter); ++ /* Write addresses to available RAR registers, if there is not ++ * sufficient space to store all the addresses then enable ++ * unicast promiscuous mode ++ */ ++ count = e1000e_write_uc_addr_list(netdev); ++ if (count < 0) ++ rctl |= E1000_RCTL_UPE; + } + + ew32(RCTL, rctl); + +- if (!netdev_mc_empty(netdev)) { +- int i = 0; ++ if (netdev->features & NETIF_F_HW_VLAN_RX) ++ e1000e_vlan_strip_enable(adapter); ++ else ++ e1000e_vlan_strip_disable(adapter); ++} ++ ++static void e1000e_setup_rss_hash(struct e1000_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 mrqc, rxcsum; ++ int i; ++ static const u32 rsskey[10] = { ++ 0xda565a6d, 0xc20e5b25, 0x3d256741, 0xb08fa343, 0xcb2bcad0, ++ 0xb4307bae, 0xa32dcb77, 0x0cf23080, 0x3bb7426a, 0xfa01acbe ++ }; ++ ++ /* Fill out hash function seed */ ++ for (i = 0; i < 10; i++) ++ ew32(RSSRK(i), rsskey[i]); ++ ++ /* Direct all traffic to queue 0 */ ++ for (i = 0; i < 32; i++) ++ ew32(RETA(i), 0); ++ ++ /* Disable raw packet checksumming so that RSS hash is placed in ++ * descriptor on writeback. ++ */ ++ rxcsum = er32(RXCSUM); ++ rxcsum |= E1000_RXCSUM_PCSD; ++ ++ ew32(RXCSUM, rxcsum); ++ ++ mrqc = (E1000_MRQC_RSS_FIELD_IPV4 | ++ E1000_MRQC_RSS_FIELD_IPV4_TCP | ++ E1000_MRQC_RSS_FIELD_IPV6 | ++ E1000_MRQC_RSS_FIELD_IPV6_TCP | ++ E1000_MRQC_RSS_FIELD_IPV6_TCP_EX); ++ ++ ew32(MRQC, mrqc); ++} ++ ++#ifdef CONFIG_E1000E_PTP ++/** ++ * e1000e_get_base_timinca - get default SYSTIM time increment attributes ++ * @adapter: board private structure ++ * @timinca: pointer to returned time increment attributes ++ * ++ * Get attributes for incrementing the System Time Register SYSTIML/H at ++ * the default base frequency, and set the cyclecounter shift value. ++ **/ ++s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 incvalue, incperiod, shift; ++ ++ /* Make sure clock is enabled on I217 before checking the frequency */ ++ if ((hw->mac.type == e1000_pch_lpt) && ++ !(er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_ENABLED) && ++ !(er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_ENABLED)) { ++ u32 fextnvm7 = er32(FEXTNVM7); ++ ++ if (!(fextnvm7 & (1 << 0))) { ++ ew32(FEXTNVM7, fextnvm7 | (1 << 0)); ++ e1e_flush(); ++ } ++ } ++ ++ switch (hw->mac.type) { ++ case e1000_pch2lan: ++ case e1000_pch_lpt: ++ /* On I217, the clock frequency is 25MHz or 96MHz as ++ * indicated by the System Clock Frequency Indication ++ */ ++ if ((hw->mac.type != e1000_pch_lpt) || ++ (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) { ++ /* Stable 96MHz frequency */ ++ incperiod = INCPERIOD_96MHz; ++ incvalue = INCVALUE_96MHz; ++ shift = INCVALUE_SHIFT_96MHz; ++ adapter->cc.shift = shift + INCPERIOD_SHIFT_96MHz; ++ break; ++ } ++ /* fall-through */ ++ case e1000_82574: ++ case e1000_82583: ++ /* Stable 25MHz frequency */ ++ incperiod = INCPERIOD_25MHz; ++ incvalue = INCVALUE_25MHz; ++ shift = INCVALUE_SHIFT_25MHz; ++ adapter->cc.shift = shift; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ *timinca = ((incperiod << E1000_TIMINCA_INCPERIOD_SHIFT) | ++ ((incvalue << shift) & E1000_TIMINCA_INCVALUE_MASK)); ++ ++ return 0; ++} ++ ++/** ++ * e1000e_config_hwtstamp - configure the hwtstamp registers and enable/disable ++ * @adapter: board private structure ++ * ++ * Outgoing time stamping can be enabled and disabled. Play nice and ++ * disable it when requested, although it shouldn't cause any overhead ++ * when no packet needs it. At most one packet in the queue may be ++ * marked for time stamping, otherwise it would be impossible to tell ++ * for sure to which packet the hardware time stamp belongs. ++ * ++ * Incoming time stamping has to be configured via the hardware filters. ++ * Not all combinations are supported, in particular event type has to be ++ * specified. Matching the kind of event packet is not supported, with the ++ * exception of "all V2 events regardless of level 2 or 4". ++ **/ ++static int e1000e_config_hwtstamp(struct e1000_adapter *adapter, ++ struct hwtstamp_config *config) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED; ++ u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; ++ u32 rxmtrl = 0; ++ u16 rxudp = 0; ++ bool is_l4 = false; ++ bool is_l2 = false; ++ u32 regval; ++ s32 ret_val; ++ ++ if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP)) ++ return -EINVAL; ++ ++ /* flags reserved for future extensions - must be zero */ ++ if (config->flags) ++ return -EINVAL; ++ ++ switch (config->tx_type) { ++ case HWTSTAMP_TX_OFF: ++ tsync_tx_ctl = 0; ++ break; ++ case HWTSTAMP_TX_ON: ++ break; ++ default: ++ return -ERANGE; ++ } ++ ++ switch (config->rx_filter) { ++ case HWTSTAMP_FILTER_NONE: ++ tsync_rx_ctl = 0; ++ break; ++ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; ++ rxmtrl = E1000_RXMTRL_PTP_V1_SYNC_MESSAGE; ++ is_l4 = true; ++ break; ++ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; ++ rxmtrl = E1000_RXMTRL_PTP_V1_DELAY_REQ_MESSAGE; ++ is_l4 = true; ++ break; ++ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: ++ /* Also time stamps V2 L2 Path Delay Request/Response */ ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_V2; ++ rxmtrl = E1000_RXMTRL_PTP_V2_SYNC_MESSAGE; ++ is_l2 = true; ++ break; ++ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: ++ /* Also time stamps V2 L2 Path Delay Request/Response. */ ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_V2; ++ rxmtrl = E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE; ++ is_l2 = true; ++ break; ++ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: ++ /* Hardware cannot filter just V2 L4 Sync messages; ++ * fall-through to V2 (both L2 and L4) Sync. ++ */ ++ case HWTSTAMP_FILTER_PTP_V2_SYNC: ++ /* Also time stamps V2 Path Delay Request/Response. */ ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; ++ rxmtrl = E1000_RXMTRL_PTP_V2_SYNC_MESSAGE; ++ is_l2 = true; ++ is_l4 = true; ++ break; ++ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: ++ /* Hardware cannot filter just V2 L4 Delay Request messages; ++ * fall-through to V2 (both L2 and L4) Delay Request. ++ */ ++ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: ++ /* Also time stamps V2 Path Delay Request/Response. */ ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; ++ rxmtrl = E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE; ++ is_l2 = true; ++ is_l4 = true; ++ break; ++ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: ++ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: ++ /* Hardware cannot filter just V2 L4 or L2 Event messages; ++ * fall-through to all V2 (both L2 and L4) Events. ++ */ ++ case HWTSTAMP_FILTER_PTP_V2_EVENT: ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2; ++ config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; ++ is_l2 = true; ++ is_l4 = true; ++ break; ++ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: ++ /* For V1, the hardware can only filter Sync messages or ++ * Delay Request messages but not both so fall-through to ++ * time stamp all packets. ++ */ ++ case HWTSTAMP_FILTER_ALL: ++ is_l2 = true; ++ is_l4 = true; ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; ++ config->rx_filter = HWTSTAMP_FILTER_ALL; ++ break; ++ default: ++ return -ERANGE; ++ } ++ ++ adapter->hwtstamp_config = *config; ++ ++ /* enable/disable Tx h/w time stamping */ ++ regval = er32(TSYNCTXCTL); ++ regval &= ~E1000_TSYNCTXCTL_ENABLED; ++ regval |= tsync_tx_ctl; ++ ew32(TSYNCTXCTL, regval); ++ if ((er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_ENABLED) != ++ (regval & E1000_TSYNCTXCTL_ENABLED)) { ++ e_err("Timesync Tx Control register not set as expected\n"); ++ return -EAGAIN; ++ } ++ ++ /* enable/disable Rx h/w time stamping */ ++ regval = er32(TSYNCRXCTL); ++ regval &= ~(E1000_TSYNCRXCTL_ENABLED | E1000_TSYNCRXCTL_TYPE_MASK); ++ regval |= tsync_rx_ctl; ++ ew32(TSYNCRXCTL, regval); ++ if ((er32(TSYNCRXCTL) & (E1000_TSYNCRXCTL_ENABLED | ++ E1000_TSYNCRXCTL_TYPE_MASK)) != ++ (regval & (E1000_TSYNCRXCTL_ENABLED | ++ E1000_TSYNCRXCTL_TYPE_MASK))) { ++ e_err("Timesync Rx Control register not set as expected\n"); ++ return -EAGAIN; ++ } ++ ++ /* L2: define ethertype filter for time stamped packets */ ++ if (is_l2) ++ rxmtrl |= ETH_P_1588; ++ ++ /* define which PTP packets get time stamped */ ++ ew32(RXMTRL, rxmtrl); ++ ++ /* Filter by destination port */ ++ if (is_l4) { ++ rxudp = PTP_EV_PORT; ++ cpu_to_be16s(&rxudp); ++ } ++ ew32(RXUDP, rxudp); ++ ++ e1e_flush(); + +- mta_list = kmalloc(netdev_mc_count(netdev) * 6, GFP_ATOMIC); +- if (!mta_list) +- return; ++ /* Clear TSYNCRXCTL_VALID & TSYNCTXCTL_VALID bit */ ++ er32(RXSTMPH); ++ er32(TXSTMPH); + +- /* prepare a packed array of only addresses. */ +- netdev_for_each_mc_addr(ha, netdev) +- memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); ++ /* Get and set the System Time Register SYSTIM base frequency */ ++ ret_val = e1000e_get_base_timinca(adapter, ®val); ++ if (ret_val) ++ return ret_val; ++ ew32(TIMINCA, regval); + +- e1000_update_mc_addr_list(hw, mta_list, i); +- kfree(mta_list); +- } else { +- /* +- * if we're called from probe, we might not have +- * anything to do here, so clear out the list +- */ +- e1000_update_mc_addr_list(hw, NULL, 0); +- } ++ /* reset the ns time counter */ ++ timecounter_init(&adapter->tc, &adapter->cc, ++ ktime_to_ns(ktime_get_real())); + +- if (netdev->features & NETIF_F_HW_VLAN_RX) +- e1000e_vlan_strip_enable(adapter); +- else +- e1000e_vlan_strip_disable(adapter); ++ return 0; + } ++#endif + + /** + * e1000_configure - configure the hardware for Rx and Tx +@@ -3214,16 +3622,20 @@ static void e1000_set_multi(struct net_device *netdev) + **/ + static void e1000_configure(struct e1000_adapter *adapter) + { +- e1000_set_multi(adapter->netdev); ++ struct e1000_ring *rx_ring = adapter->rx_ring; ++ ++ e1000e_set_rx_mode(adapter->netdev); + + e1000_restore_vlan(adapter); + e1000_init_manageability_pt(adapter); + + e1000_configure_tx(adapter); ++ ++ if (adapter->netdev->features & NETIF_F_RXHASH) ++ e1000e_setup_rss_hash(adapter); + e1000_setup_rctl(adapter); + e1000_configure_rx(adapter); +- adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring), +- GFP_KERNEL); ++ adapter->alloc_rx_buf(rx_ring, e1000_desc_unused(rx_ring), GFP_KERNEL); + } + + /** +@@ -3279,8 +3691,7 @@ void e1000e_reset(struct e1000_adapter *adapter) + ew32(PBA, pba); + + if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) { +- /* +- * To maintain wire speed transmits, the Tx FIFO should be ++ /* To maintain wire speed transmits, the Tx FIFO should be + * large enough to accommodate two full transmit packets, + * rounded up to the next 1KB and expressed in KB. Likewise, + * the Rx FIFO should be large enough to accommodate at least +@@ -3292,13 +3703,11 @@ void e1000e_reset(struct e1000_adapter *adapter) + tx_space = pba >> 16; + /* lower 16 bits has Rx packet buffer allocation size in KB */ + pba &= 0xffff; +- /* +- * the Tx fifo also stores 16 bytes of information about the Tx ++ /* the Tx fifo also stores 16 bytes of information about the Tx + * but don't include ethernet FCS because hardware appends it + */ + min_tx_space = (adapter->max_frame_size + +- sizeof(struct e1000_tx_desc) - +- ETH_FCS_LEN) * 2; ++ sizeof(struct e1000_tx_desc) - ETH_FCS_LEN) * 2; + min_tx_space = ALIGN(min_tx_space, 1024); + min_tx_space >>= 10; + /* software strips receive CRC, so leave room for it */ +@@ -3306,8 +3715,7 @@ void e1000e_reset(struct e1000_adapter *adapter) + min_rx_space = ALIGN(min_rx_space, 1024); + min_rx_space >>= 10; + +- /* +- * If current Tx allocation is less than the min Tx FIFO size, ++ /* If current Tx allocation is less than the min Tx FIFO size, + * and the min Tx FIFO size is less than the current Rx FIFO + * allocation, take space away from current Rx allocation + */ +@@ -3315,78 +3723,81 @@ void e1000e_reset(struct e1000_adapter *adapter) + ((min_tx_space - tx_space) < pba)) { + pba -= min_tx_space - tx_space; + +- /* +- * if short on Rx space, Rx wins and must trump Tx +- * adjustment or use Early Receive if available ++ /* if short on Rx space, Rx wins and must trump Tx ++ * adjustment + */ +- if ((pba < min_rx_space) && +- (!(adapter->flags & FLAG_HAS_ERT))) +- /* ERT enabled in e1000_configure_rx */ ++ if (pba < min_rx_space) + pba = min_rx_space; + } + + ew32(PBA, pba); + } + +- /* +- * flow control settings ++ /* flow control settings + * + * The high water mark must be low enough to fit one full frame + * (or the size used for early receive) above it in the Rx FIFO. + * Set it to the lower of: + * - 90% of the Rx FIFO size, and +- * - the full Rx FIFO size minus the early receive size (for parts +- * with ERT support assuming ERT set to E1000_ERT_2048), or + * - the full Rx FIFO size minus one full frame + */ + if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME) + fc->pause_time = 0xFFFF; + else + fc->pause_time = E1000_FC_PAUSE_TIME; +- fc->send_xon = 1; ++ fc->send_xon = true; + fc->current_mode = fc->requested_mode; + + switch (hw->mac.type) { ++ case e1000_ich9lan: ++ case e1000_ich10lan: ++ if (adapter->netdev->mtu > ETH_DATA_LEN) { ++ pba = 14; ++ ew32(PBA, pba); ++ fc->high_water = 0x2800; ++ fc->low_water = fc->high_water - 8; ++ break; ++ } ++ /* fall-through */ + default: +- if ((adapter->flags & FLAG_HAS_ERT) && +- (adapter->netdev->mtu > ETH_DATA_LEN)) +- hwm = min(((pba << 10) * 9 / 10), +- ((pba << 10) - (E1000_ERT_2048 << 3))); +- else +- hwm = min(((pba << 10) * 9 / 10), +- ((pba << 10) - adapter->max_frame_size)); ++ hwm = min(((pba << 10) * 9 / 10), ++ ((pba << 10) - adapter->max_frame_size)); + +- fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ ++ fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ + fc->low_water = fc->high_water - 8; + break; + case e1000_pchlan: +- /* +- * Workaround PCH LOM adapter hangs with certain network ++ /* Workaround PCH LOM adapter hangs with certain network + * loads. If hangs persist, try disabling Tx flow control. + */ + if (adapter->netdev->mtu > ETH_DATA_LEN) { + fc->high_water = 0x3500; +- fc->low_water = 0x1500; ++ fc->low_water = 0x1500; + } else { + fc->high_water = 0x5000; +- fc->low_water = 0x3000; ++ fc->low_water = 0x3000; + } + fc->refresh_time = 0x1000; + break; + case e1000_pch2lan: +- fc->high_water = 0x05C20; +- fc->low_water = 0x05048; +- fc->pause_time = 0x0650; ++ case e1000_pch_lpt: + fc->refresh_time = 0x0400; +- if (adapter->netdev->mtu > ETH_DATA_LEN) { +- pba = 14; +- ew32(PBA, pba); ++ ++ if (adapter->netdev->mtu <= ETH_DATA_LEN) { ++ fc->high_water = 0x05C20; ++ fc->low_water = 0x05048; ++ fc->pause_time = 0x0650; ++ break; + } ++ ++ pba = 14; ++ ew32(PBA, pba); ++ fc->high_water = ((pba << 10) * 9 / 10) & E1000_FCRTH_RTH; ++ fc->low_water = ((pba << 10) * 8 / 10) & E1000_FCRTL_RTL; + break; + } + +- /* +- * Alignment of Tx data is on an arbitrary byte boundary with the ++ /* Alignment of Tx data is on an arbitrary byte boundary with the + * maximum size per Tx descriptor limited only to the transmit + * allocation of the packet buffer minus 96 bytes with an upper + * limit of 24KB due to receive synchronization limitations. +@@ -3394,33 +3805,30 @@ void e1000e_reset(struct e1000_adapter *adapter) + adapter->tx_fifo_limit = min_t(u32, ((er32(PBA) >> 16) << 10) - 96, + 24 << 10); + +- /* +- * Disable Adaptive Interrupt Moderation if 2 full packets cannot +- * fit in receive buffer and early-receive not supported. ++ /* Disable Adaptive Interrupt Moderation if 2 full packets cannot ++ * fit in receive buffer. + */ + if (adapter->itr_setting & 0x3) { +- if (((adapter->max_frame_size * 2) > (pba << 10)) && +- !(adapter->flags & FLAG_HAS_ERT)) { ++ if ((adapter->max_frame_size * 2) > (pba << 10)) { + if (!(adapter->flags2 & FLAG2_DISABLE_AIM)) { + dev_info(&adapter->pdev->dev, +- "Interrupt Throttle Rate turned off\n"); ++ "Interrupt Throttle Rate off\n"); + adapter->flags2 |= FLAG2_DISABLE_AIM; +- ew32(ITR, 0); ++ e1000e_write_itr(adapter, 0); + } + } else if (adapter->flags2 & FLAG2_DISABLE_AIM) { + dev_info(&adapter->pdev->dev, +- "Interrupt Throttle Rate turned on\n"); ++ "Interrupt Throttle Rate on\n"); + adapter->flags2 &= ~FLAG2_DISABLE_AIM; + adapter->itr = 20000; +- ew32(ITR, 1000000000 / (adapter->itr * 256)); ++ e1000e_write_itr(adapter, adapter->itr); + } + } + + /* Allow time for pending master requests to run */ + mac->ops.reset_hw(hw); + +- /* +- * For parts with AMT enabled, let the firmware know ++ /* For parts with AMT enabled, let the firmware know + * that the network interface is in control + */ + if (adapter->flags & FLAG_HAS_AMT) +@@ -3438,6 +3846,43 @@ void e1000e_reset(struct e1000_adapter *adapter) + + e1000e_reset_adaptive(hw); + ++#ifdef CONFIG_E1000E_PTP ++ /* initialize systim and reset the ns time counter */ ++ e1000e_config_hwtstamp(adapter, &adapter->hwtstamp_config); ++#endif ++ ++ /* Set EEE advertisement as appropriate */ ++ if (adapter->flags2 & FLAG2_HAS_EEE) { ++ s32 ret_val; ++ u16 adv_addr; ++ ++ switch (hw->phy.type) { ++ case e1000_phy_82579: ++ adv_addr = I82579_EEE_ADVERTISEMENT; ++ break; ++ case e1000_phy_i217: ++ adv_addr = I217_EEE_ADVERTISEMENT; ++ break; ++ default: ++ dev_err(&adapter->pdev->dev, ++ "Invalid PHY type setting EEE advertisement\n"); ++ return; ++ } ++ ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) { ++ dev_err(&adapter->pdev->dev, ++ "EEE advertisement - unable to acquire PHY\n"); ++ return; ++ } ++ ++ e1000_write_emi_reg_locked(hw, adv_addr, ++ hw->dev_spec.ich8lan.eee_disable ? ++ 0 : adapter->eee_advert); ++ ++ hw->phy.ops.release(hw); ++ } ++ + if (!netif_running(adapter->netdev) && + !test_bit(__E1000_TESTING, &adapter->state)) { + e1000_power_down_phy(adapter); +@@ -3449,8 +3894,7 @@ void e1000e_reset(struct e1000_adapter *adapter) + if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && + !(adapter->flags & FLAG_SMART_POWER_DOWN)) { + u16 phy_data = 0; +- /* +- * speed up time to link by disabling smart power down, ignore ++ /* speed up time to link by disabling smart power down, ignore + * the return value of this function because there is nothing + * different we would do if it failed + */ +@@ -3469,7 +3913,6 @@ int e1000e_up(struct e1000_adapter *adapter) + + clear_bit(__E1000_DOWN, &adapter->state); + +- napi_enable(&adapter->napi); + if (adapter->msix_entries) + e1000_configure_msix(adapter); + e1000_irq_enable(adapter); +@@ -3498,6 +3941,15 @@ static void e1000e_flush_descriptors(struct e1000_adapter *adapter) + + /* execute the writes immediately */ + e1e_flush(); ++ ++ /* due to rare timing issues, write to TIDV/RDTR again to ensure the ++ * write is successful ++ */ ++ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); ++ ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD); ++ ++ /* execute the writes immediately */ ++ e1e_flush(); + } + + static void e1000e_update_stats(struct e1000_adapter *adapter); +@@ -3508,8 +3960,7 @@ void e1000e_down(struct e1000_adapter *adapter) + struct e1000_hw *hw = &adapter->hw; + u32 tctl, rctl; + +- /* +- * signal that we're down so the interrupt handler does not ++ /* signal that we're down so the interrupt handler does not + * reschedule our watchdog timer + */ + set_bit(__E1000_DOWN, &adapter->state); +@@ -3531,9 +3982,10 @@ void e1000e_down(struct e1000_adapter *adapter) + e1e_flush(); + usleep_range(10000, 20000); + +- napi_disable(&adapter->napi); + e1000_irq_disable(adapter); + ++ napi_synchronize(&adapter->napi); ++ + del_timer_sync(&adapter->watchdog_timer); + del_timer_sync(&adapter->phy_info_timer); + +@@ -3544,17 +3996,22 @@ void e1000e_down(struct e1000_adapter *adapter) + spin_unlock(&adapter->stats64_lock); + + e1000e_flush_descriptors(adapter); +- e1000_clean_tx_ring(adapter); +- e1000_clean_rx_ring(adapter); ++ e1000_clean_tx_ring(adapter->tx_ring); ++ e1000_clean_rx_ring(adapter->rx_ring); + + adapter->link_speed = 0; + adapter->link_duplex = 0; + ++ /* Disable Si errata workaround on PCHx for jumbo frame flow */ ++ if ((hw->mac.type >= e1000_pch2lan) && ++ (adapter->netdev->mtu > ETH_DATA_LEN) && ++ e1000_lv_jumbo_workaround_ich8lan(hw, false)) ++ e_dbg("failed to disable jumbo frame workaround mode\n"); ++ + if (!pci_channel_offline(adapter->pdev)) + e1000e_reset(adapter); + +- /* +- * TODO: for power management, we could drop the link and ++ /* TODO: for power management, we could drop the link and + * pci_disable_device here. + */ + } +@@ -3569,6 +4026,26 @@ void e1000e_reinit_locked(struct e1000_adapter *adapter) + clear_bit(__E1000_RESETTING, &adapter->state); + } + ++#ifdef CONFIG_E1000E_PTP ++/** ++ * e1000e_cyclecounter_read - read raw cycle counter (used by time counter) ++ * @cc: cyclecounter structure ++ **/ ++static cycle_t e1000e_cyclecounter_read(const struct cyclecounter *cc) ++{ ++ struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter, ++ cc); ++ struct e1000_hw *hw = &adapter->hw; ++ cycle_t systim; ++ ++ /* latch SYSTIMH on read of SYSTIML */ ++ systim = (cycle_t)er32(SYSTIML); ++ systim |= (cycle_t)er32(SYSTIMH) << 32; ++ ++ return systim; ++} ++#endif ++ + /** + * e1000_sw_init - Initialize general software structures (struct e1000_adapter) + * @adapter: board private structure to initialize +@@ -3577,7 +4054,7 @@ void e1000e_reinit_locked(struct e1000_adapter *adapter) + * Fields are initialized based on PCI device information and + * OS network device settings (MTU size). + **/ +-static int __devinit e1000_sw_init(struct e1000_adapter *adapter) ++static int e1000_sw_init(struct e1000_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; + +@@ -3585,6 +4062,8 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) + adapter->rx_ps_bsize0 = 128; + adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; + adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; ++ adapter->tx_ring_count = E1000_DEFAULT_TXD; ++ adapter->rx_ring_count = E1000_DEFAULT_RXD; + + spin_lock_init(&adapter->stats64_lock); + +@@ -3593,6 +4072,19 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) + if (e1000_alloc_queues(adapter)) + return -ENOMEM; + ++#ifdef CONFIG_E1000E_PTP ++ /* Setup hardware time stamping cyclecounter */ ++ if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) { ++ adapter->cc.read = e1000e_cyclecounter_read; ++ adapter->cc.mask = CLOCKSOURCE_MASK(64); ++ adapter->cc.mult = 1; ++ /* cc.shift set in e1000e_get_base_tininca() */ ++ ++ spin_lock_init(&adapter->systim_lock); ++ INIT_WORK(&adapter->tx_hwtstamp_work, e1000e_tx_hwtstamp_work); ++ } ++#endif ++ + /* Explicitly disable IRQ since the NIC can be in any state. */ + e1000_irq_disable(adapter); + +@@ -3605,7 +4097,7 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) + * @irq: interrupt number + * @data: pointer to a network interface device structure + **/ +-static irqreturn_t e1000_intr_msi_test(int irq, void *data) ++static irqreturn_t e1000_intr_msi_test(int __always_unused irq, void *data) + { + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); +@@ -3615,6 +4107,9 @@ static irqreturn_t e1000_intr_msi_test(int irq, void *data) + e_dbg("icr is %08X\n", icr); + if (icr & E1000_ICR_RXSEQ) { + adapter->flags &= ~FLAG_MSI_TEST_FAILED; ++ /* Force memory writes to complete before acknowledging the ++ * interrupt is handled. ++ */ + wmb(); + } + +@@ -3642,7 +4137,8 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) + e1000e_reset_interrupt_capability(adapter); + + /* Assume that the test fails, if it succeeds then the test +- * MSI irq handler will unset this flag */ ++ * MSI irq handler will unset this flag ++ */ + adapter->flags |= FLAG_MSI_TEST_FAILED; + + err = pci_enable_msi(adapter->pdev); +@@ -3656,6 +4152,9 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) + goto msi_test_failed; + } + ++ /* Force memory writes to complete before enabling and firing an ++ * interrupt. ++ */ + wmb(); + + e1000_irq_enable(adapter); +@@ -3663,17 +4162,18 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) + /* fire an unusual interrupt on the test handler */ + ew32(ICS, E1000_ICS_RXSEQ); + e1e_flush(); +- msleep(50); ++ msleep(100); + + e1000_irq_disable(adapter); + +- rmb(); ++ rmb(); /* read flags after interrupt has been fired */ + + if (adapter->flags & FLAG_MSI_TEST_FAILED) { + adapter->int_mode = E1000E_INT_MODE_LEGACY; + e_info("MSI interrupt test failed, using legacy interrupt.\n"); +- } else ++ } else { + e_dbg("MSI interrupt test succeeded!\n"); ++ } + + free_irq(adapter->pdev->irq, netdev); + pci_disable_msi(adapter->pdev); +@@ -3743,17 +4243,16 @@ static int e1000_open(struct net_device *netdev) + netif_carrier_off(netdev); + + /* allocate transmit descriptors */ +- err = e1000e_setup_tx_resources(adapter); ++ err = e1000e_setup_tx_resources(adapter->tx_ring); + if (err) + goto err_setup_tx; + + /* allocate receive descriptors */ +- err = e1000e_setup_rx_resources(adapter); ++ err = e1000e_setup_rx_resources(adapter->rx_ring); + if (err) + goto err_setup_rx; + +- /* +- * If AMT is enabled, let the firmware know that the network ++ /* If AMT is enabled, let the firmware know that the network + * interface is now open and reset the part to a known state. + */ + if (adapter->flags & FLAG_HAS_AMT) { +@@ -3764,19 +4263,14 @@ static int e1000_open(struct net_device *netdev) + e1000e_power_up_phy(adapter); + + adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; +- if ((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN)) ++ if ((adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN)) + e1000_update_mng_vlan(adapter); + +- /* DMA latency requirement to workaround early-receive/jumbo issue */ +- if ((adapter->flags & FLAG_HAS_ERT) || +- (adapter->hw.mac.type == e1000_pch2lan)) +- pm_qos_add_request(&adapter->netdev->pm_qos_req, +- PM_QOS_CPU_DMA_LATENCY, +- PM_QOS_DEFAULT_VALUE); ++ /* DMA latency requirement to workaround jumbo issue */ ++ pm_qos_add_request(&adapter->netdev->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, ++ PM_QOS_DEFAULT_VALUE); + +- /* +- * before we allocate an interrupt, we must be ready to handle it. ++ /* before we allocate an interrupt, we must be ready to handle it. + * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt + * as soon as we call pci_request_irq, so we have to setup our + * clean_rx handler before we do so. +@@ -3787,8 +4281,7 @@ static int e1000_open(struct net_device *netdev) + if (err) + goto err_req_irq; + +- /* +- * Work around PCIe errata with MSI interrupts causing some chipsets to ++ /* Work around PCIe errata with MSI interrupts causing some chipsets to + * ignore e1000e MSI messages, which means we need to test our MSI + * interrupt now + */ +@@ -3811,6 +4304,7 @@ static int e1000_open(struct net_device *netdev) + netif_start_queue(netdev); + + adapter->idle_check = true; ++ hw->mac.get_link_status = true; + pm_runtime_put(&pdev->dev); + + /* fire a link status change interrupt to start the watchdog */ +@@ -3824,9 +4318,9 @@ static int e1000_open(struct net_device *netdev) + err_req_irq: + e1000e_release_hw_control(adapter); + e1000_power_down_phy(adapter); +- e1000e_free_rx_resources(adapter); ++ e1000e_free_rx_resources(adapter->rx_ring); + err_setup_rx: +- e1000e_free_tx_resources(adapter); ++ e1000e_free_tx_resources(adapter->tx_ring); + err_setup_tx: + e1000e_reset(adapter); + pm_runtime_put_sync(&pdev->dev); +@@ -3849,6 +4343,10 @@ static int e1000_close(struct net_device *netdev) + { + struct e1000_adapter *adapter = netdev_priv(netdev); + struct pci_dev *pdev = adapter->pdev; ++ int count = E1000_CHECK_RESET_COUNT; ++ ++ while (test_bit(__E1000_RESETTING, &adapter->state) && count--) ++ usleep_range(10000, 20000); + + WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); + +@@ -3858,35 +4356,34 @@ static int e1000_close(struct net_device *netdev) + e1000e_down(adapter); + e1000_free_irq(adapter); + } ++ ++ napi_disable(&adapter->napi); ++ + e1000_power_down_phy(adapter); + +- e1000e_free_tx_resources(adapter); +- e1000e_free_rx_resources(adapter); ++ e1000e_free_tx_resources(adapter->tx_ring); ++ e1000e_free_rx_resources(adapter->rx_ring); + +- /* +- * kill manageability vlan ID if supported, but not if a vlan with ++ /* kill manageability vlan ID if supported, but not if a vlan with + * the same ID is registered on the host OS (let 8021q kill it) + */ +- if (adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN) ++ if (adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) + e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); + +- /* +- * If AMT is enabled, let the firmware know that the network ++ /* If AMT is enabled, let the firmware know that the network + * interface is now closed + */ + if ((adapter->flags & FLAG_HAS_AMT) && + !test_bit(__E1000_TESTING, &adapter->state)) + e1000e_release_hw_control(adapter); + +- if ((adapter->flags & FLAG_HAS_ERT) || +- (adapter->hw.mac.type == e1000_pch2lan)) +- pm_qos_remove_request(&adapter->netdev->pm_qos_req); ++ pm_qos_remove_request(&adapter->netdev->pm_qos_req); + + pm_runtime_put_sync(&pdev->dev); + + return 0; + } ++ + /** + * e1000_set_mac - Change the Ethernet Address of the NIC + * @netdev: network interface device structure +@@ -3897,6 +4394,7 @@ static int e1000_close(struct net_device *netdev) + static int e1000_set_mac(struct net_device *netdev, void *p) + { + struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) +@@ -3905,23 +4403,21 @@ static int e1000_set_mac(struct net_device *netdev, void *p) + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len); + +- e1000e_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); ++ hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, 0); + + if (adapter->flags & FLAG_RESET_OVERWRITES_LAA) { + /* activate the work around */ + e1000e_set_laa_state_82571(&adapter->hw, 1); + +- /* +- * Hold a copy of the LAA in RAR[14] This is done so that ++ /* Hold a copy of the LAA in RAR[14] This is done so that + * between the time RAR[0] gets clobbered and the time it + * gets fixed (in e1000_watchdog), the actual LAA is in one + * of the RARs and no incoming packets directed to this port + * are dropped. Eventually the LAA will be in RAR[0] and + * RAR[14] + */ +- e1000e_rar_set(&adapter->hw, +- adapter->hw.mac.addr, +- adapter->hw.mac.rar_entry_count - 1); ++ hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, ++ adapter->hw.mac.rar_entry_count - 1); + } + + return 0; +@@ -3938,7 +4434,8 @@ static int e1000_set_mac(struct net_device *netdev, void *p) + static void e1000e_update_phy_task(struct work_struct *work) + { + struct e1000_adapter *adapter = container_of(work, +- struct e1000_adapter, update_phy_task); ++ struct e1000_adapter, ++ update_phy_task); + + if (test_bit(__E1000_DOWN, &adapter->state)) + return; +@@ -3946,13 +4443,16 @@ static void e1000e_update_phy_task(struct work_struct *work) + e1000_get_phy_info(&adapter->hw); + } + +-/* ++/** ++ * e1000_update_phy_info - timre call-back to update PHY info ++ * @data: pointer to adapter cast into an unsigned long ++ * + * Need to wait a few seconds after link up to get diagnostic information from + * the phy +- */ ++ **/ + static void e1000_update_phy_info(unsigned long data) + { +- struct e1000_adapter *adapter = (struct e1000_adapter *) data; ++ struct e1000_adapter *adapter = (struct e1000_adapter *)data; + + if (test_bit(__E1000_DOWN, &adapter->state)) + return; +@@ -3976,8 +4476,7 @@ static void e1000e_update_phy_stats(struct e1000_adapter *adapter) + if (ret_val) + return; + +- /* +- * A page set is expensive so check if already on desired page. ++ /* A page set is expensive so check if already on desired page. + * If not, set to the page with the PHY status registers. + */ + hw->phy.addr = 1; +@@ -4048,8 +4547,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter) + struct e1000_hw *hw = &adapter->hw; + struct pci_dev *pdev = adapter->pdev; + +- /* +- * Prevent stats update while adapter is being reset, or if the pci ++ /* Prevent stats update while adapter is being reset, or if the pci + * connection is down. + */ + if (adapter->link_speed == 0) +@@ -4060,7 +4558,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter) + adapter->stats.crcerrs += er32(CRCERRS); + adapter->stats.gprc += er32(GPRC); + adapter->stats.gorc += er32(GORCL); +- er32(GORCH); /* Clear gorc */ ++ er32(GORCH); /* Clear gorc */ + adapter->stats.bprc += er32(BPRC); + adapter->stats.mprc += er32(MPRC); + adapter->stats.roc += er32(ROC); +@@ -4093,7 +4591,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter) + adapter->stats.xofftxc += er32(XOFFTXC); + adapter->stats.gptc += er32(GPTC); + adapter->stats.gotc += er32(GOTCL); +- er32(GOTCH); /* Clear gotc */ ++ er32(GOTCH); /* Clear gotc */ + adapter->stats.rnbc += er32(RNBC); + adapter->stats.ruc += er32(RUC); + +@@ -4117,23 +4615,20 @@ static void e1000e_update_stats(struct e1000_adapter *adapter) + + /* Rx Errors */ + +- /* +- * RLEC on some newer hardware can be incorrect so build ++ /* RLEC on some newer hardware can be incorrect so build + * our own version based on RUC and ROC + */ + netdev->stats.rx_errors = adapter->stats.rxerrc + +- adapter->stats.crcerrs + adapter->stats.algnerrc + +- adapter->stats.ruc + adapter->stats.roc + +- adapter->stats.cexterr; ++ adapter->stats.crcerrs + adapter->stats.algnerrc + ++ adapter->stats.ruc + adapter->stats.roc + adapter->stats.cexterr; + netdev->stats.rx_length_errors = adapter->stats.ruc + +- adapter->stats.roc; ++ adapter->stats.roc; + netdev->stats.rx_crc_errors = adapter->stats.crcerrs; + netdev->stats.rx_frame_errors = adapter->stats.algnerrc; + netdev->stats.rx_missed_errors = adapter->stats.mpc; + + /* Tx Errors */ +- netdev->stats.tx_errors = adapter->stats.ecol + +- adapter->stats.latecol; ++ netdev->stats.tx_errors = adapter->stats.ecol + adapter->stats.latecol; + netdev->stats.tx_aborted_errors = adapter->stats.ecol; + netdev->stats.tx_window_errors = adapter->stats.latecol; + netdev->stats.tx_carrier_errors = adapter->stats.tncrs; +@@ -4144,6 +4639,16 @@ static void e1000e_update_stats(struct e1000_adapter *adapter) + adapter->stats.mgptc += er32(MGTPTC); + adapter->stats.mgprc += er32(MGTPRC); + adapter->stats.mgpdc += er32(MGTPDC); ++ ++ /* Correctable ECC Errors */ ++ if (hw->mac.type == e1000_pch_lpt) { ++ u32 pbeccsts = er32(PBECCSTS); ++ adapter->corr_errors += ++ pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; ++ adapter->uncorr_errors += ++ (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> ++ E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; ++ } + } + + /** +@@ -4155,23 +4660,23 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter) + struct e1000_hw *hw = &adapter->hw; + struct e1000_phy_regs *phy = &adapter->phy_regs; + +- if ((er32(STATUS) & E1000_STATUS_LU) && ++ if (!pm_runtime_suspended((&adapter->pdev->dev)->parent) && ++ (er32(STATUS) & E1000_STATUS_LU) && + (adapter->hw.phy.media_type == e1000_media_type_copper)) { + int ret_val; + +- ret_val = e1e_rphy(hw, PHY_CONTROL, &phy->bmcr); +- ret_val |= e1e_rphy(hw, PHY_STATUS, &phy->bmsr); +- ret_val |= e1e_rphy(hw, PHY_AUTONEG_ADV, &phy->advertise); +- ret_val |= e1e_rphy(hw, PHY_LP_ABILITY, &phy->lpa); +- ret_val |= e1e_rphy(hw, PHY_AUTONEG_EXP, &phy->expansion); +- ret_val |= e1e_rphy(hw, PHY_1000T_CTRL, &phy->ctrl1000); +- ret_val |= e1e_rphy(hw, PHY_1000T_STATUS, &phy->stat1000); +- ret_val |= e1e_rphy(hw, PHY_EXT_STATUS, &phy->estatus); ++ ret_val = e1e_rphy(hw, MII_BMCR, &phy->bmcr); ++ ret_val |= e1e_rphy(hw, MII_BMSR, &phy->bmsr); ++ ret_val |= e1e_rphy(hw, MII_ADVERTISE, &phy->advertise); ++ ret_val |= e1e_rphy(hw, MII_LPA, &phy->lpa); ++ ret_val |= e1e_rphy(hw, MII_EXPANSION, &phy->expansion); ++ ret_val |= e1e_rphy(hw, MII_CTRL1000, &phy->ctrl1000); ++ ret_val |= e1e_rphy(hw, MII_STAT1000, &phy->stat1000); ++ ret_val |= e1e_rphy(hw, MII_ESTATUS, &phy->estatus); + if (ret_val) + e_warn("Error reading PHY register\n"); + } else { +- /* +- * Do not read PHY registers if link is not up ++ /* Do not read PHY registers if link is not up + * Set values to typical power-on defaults + */ + phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX); +@@ -4194,26 +4699,21 @@ static void e1000_print_link_info(struct e1000_adapter *adapter) + u32 ctrl = er32(CTRL); + + /* Link status message must follow this format for user tools */ +- printk(KERN_INFO "e1000e: %s NIC Link is Up %d Mbps %s, " +- "Flow Control: %s\n", +- adapter->netdev->name, +- adapter->link_speed, +- (adapter->link_duplex == FULL_DUPLEX) ? +- "Full Duplex" : "Half Duplex", +- ((ctrl & E1000_CTRL_TFCE) && (ctrl & E1000_CTRL_RFCE)) ? +- "Rx/Tx" : +- ((ctrl & E1000_CTRL_RFCE) ? "Rx" : +- ((ctrl & E1000_CTRL_TFCE) ? "Tx" : "None"))); ++ pr_info("%s NIC Link is Up %d Mbps %s Duplex, Flow Control: %s\n", ++ adapter->netdev->name, adapter->link_speed, ++ adapter->link_duplex == FULL_DUPLEX ? "Full" : "Half", ++ (ctrl & E1000_CTRL_TFCE) && (ctrl & E1000_CTRL_RFCE) ? "Rx/Tx" : ++ (ctrl & E1000_CTRL_RFCE) ? "Rx" : ++ (ctrl & E1000_CTRL_TFCE) ? "Tx" : "None"); + } + + static bool e1000e_has_link(struct e1000_adapter *adapter) + { + struct e1000_hw *hw = &adapter->hw; +- bool link_active = 0; ++ bool link_active = false; + s32 ret_val = 0; + +- /* +- * get_link_status is set on LSC (link status) interrupt or ++ /* get_link_status is set on LSC (link status) interrupt or + * Rx sequence error interrupt. get_link_status will stay + * false until the check_for_link establishes link + * for copper adapters ONLY +@@ -4224,7 +4724,7 @@ static bool e1000e_has_link(struct e1000_adapter *adapter) + ret_val = hw->mac.ops.check_for_link(hw); + link_active = !hw->mac.get_link_status; + } else { +- link_active = 1; ++ link_active = true; + } + break; + case e1000_media_type_fiber: +@@ -4253,11 +4753,11 @@ static void e1000e_enable_receives(struct e1000_adapter *adapter) + { + /* make sure the receive unit is started */ + if ((adapter->flags & FLAG_RX_NEEDS_RESTART) && +- (adapter->flags & FLAG_RX_RESTART_NOW)) { ++ (adapter->flags & FLAG_RESTART_NOW)) { + struct e1000_hw *hw = &adapter->hw; + u32 rctl = er32(RCTL); + ew32(RCTL, rctl | E1000_RCTL_EN); +- adapter->flags &= ~FLAG_RX_RESTART_NOW; ++ adapter->flags &= ~FLAG_RESTART_NOW; + } + } + +@@ -4265,8 +4765,7 @@ static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter) + { + struct e1000_hw *hw = &adapter->hw; + +- /* +- * With 82574 controllers, PHY needs to be checked periodically ++ /* With 82574 controllers, PHY needs to be checked periodically + * for hung state and reset, if two calls return true + */ + if (e1000_check_phy_82574(hw)) +@@ -4286,7 +4785,7 @@ static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter) + **/ + static void e1000_watchdog(unsigned long data) + { +- struct e1000_adapter *adapter = (struct e1000_adapter *) data; ++ struct e1000_adapter *adapter = (struct e1000_adapter *)data; + + /* Do the rest outside of interrupt context */ + schedule_work(&adapter->watchdog_task); +@@ -4297,7 +4796,8 @@ static void e1000_watchdog(unsigned long data) + static void e1000_watchdog_task(struct work_struct *work) + { + struct e1000_adapter *adapter = container_of(work, +- struct e1000_adapter, watchdog_task); ++ struct e1000_adapter, ++ watchdog_task); + struct net_device *netdev = adapter->netdev; + struct e1000_mac_info *mac = &adapter->hw.mac; + struct e1000_phy_info *phy = &adapter->hw.phy; +@@ -4323,7 +4823,7 @@ static void e1000_watchdog_task(struct work_struct *work) + + if (link) { + if (!netif_carrier_ok(netdev)) { +- bool txb2b = 1; ++ bool txb2b = true; + + /* Cancel scheduled suspend requests. */ + pm_runtime_resume(netdev->dev.parent); +@@ -4331,45 +4831,47 @@ static void e1000_watchdog_task(struct work_struct *work) + /* update snapshot of PHY registers on LSC */ + e1000_phy_read_status(adapter); + mac->ops.get_link_up_info(&adapter->hw, +- &adapter->link_speed, +- &adapter->link_duplex); ++ &adapter->link_speed, ++ &adapter->link_duplex); + e1000_print_link_info(adapter); +- /* +- * On supported PHYs, check for duplex mismatch only ++ ++ /* check if SmartSpeed worked */ ++ e1000e_check_downshift(hw); ++ if (phy->speed_downgraded) ++ netdev_warn(netdev, ++ "Link Speed was downgraded by SmartSpeed\n"); ++ ++ /* On supported PHYs, check for duplex mismatch only + * if link has autonegotiated at 10/100 half + */ + if ((hw->phy.type == e1000_phy_igp_3 || + hw->phy.type == e1000_phy_bm) && +- (hw->mac.autoneg == true) && ++ hw->mac.autoneg && + (adapter->link_speed == SPEED_10 || + adapter->link_speed == SPEED_100) && + (adapter->link_duplex == HALF_DUPLEX)) { + u16 autoneg_exp; + +- e1e_rphy(hw, PHY_AUTONEG_EXP, &autoneg_exp); ++ e1e_rphy(hw, MII_EXPANSION, &autoneg_exp); + +- if (!(autoneg_exp & NWAY_ER_LP_NWAY_CAPS)) +- e_info("Autonegotiated half duplex but" +- " link partner cannot autoneg. " +- " Try forcing full duplex if " +- "link gets many collisions.\n"); ++ if (!(autoneg_exp & EXPANSION_NWAY)) ++ e_info("Autonegotiated half duplex but link partner cannot autoneg. Try forcing full duplex if link gets many collisions.\n"); + } + + /* adjust timeout factor according to speed/duplex */ + adapter->tx_timeout_factor = 1; + switch (adapter->link_speed) { + case SPEED_10: +- txb2b = 0; ++ txb2b = false; + adapter->tx_timeout_factor = 16; + break; + case SPEED_100: +- txb2b = 0; ++ txb2b = false; + adapter->tx_timeout_factor = 10; + break; + } + +- /* +- * workaround: re-program speed mode bit after ++ /* workaround: re-program speed mode bit after + * link-up event + */ + if ((adapter->flags & FLAG_TARC_SPEED_MODE_BIT) && +@@ -4380,8 +4882,7 @@ static void e1000_watchdog_task(struct work_struct *work) + ew32(TARC(0), tarc0); + } + +- /* +- * disable TSO for pcie and 10/100 speeds, to avoid ++ /* disable TSO for pcie and 10/100 speeds, to avoid + * some hardware issues + */ + if (!(adapter->flags & FLAG_TSO_FORCE)) { +@@ -4402,16 +4903,14 @@ static void e1000_watchdog_task(struct work_struct *work) + } + } + +- /* +- * enable transmits in the hardware, need to do this ++ /* enable transmits in the hardware, need to do this + * after setting TARC(0) + */ + tctl = er32(TCTL); + tctl |= E1000_TCTL_EN; + ew32(TCTL, tctl); + +- /* +- * Perform any post-link-up configuration before ++ /* Perform any post-link-up configuration before + * reporting link up. + */ + if (phy->ops.cfg_on_link_up) +@@ -4428,18 +4927,25 @@ static void e1000_watchdog_task(struct work_struct *work) + adapter->link_speed = 0; + adapter->link_duplex = 0; + /* Link status message must follow this format */ +- printk(KERN_INFO "e1000e: %s NIC Link is Down\n", +- adapter->netdev->name); ++ pr_info("%s NIC Link is Down\n", adapter->netdev->name); + netif_carrier_off(netdev); + if (!test_bit(__E1000_DOWN, &adapter->state)) + mod_timer(&adapter->phy_info_timer, + round_jiffies(jiffies + 2 * HZ)); + +- if (adapter->flags & FLAG_RX_NEEDS_RESTART) +- schedule_work(&adapter->reset_task); ++ /* The link is lost so the controller stops DMA. ++ * If there is queued Tx work that cannot be done ++ * or if on an 8000ES2LAN which requires a Rx packet ++ * buffer work-around on link down event, reset the ++ * controller to flush the Tx/Rx packet buffers. ++ * (Do the reset outside of interrupt context). ++ */ ++ if ((adapter->flags & FLAG_RX_NEEDS_RESTART) || ++ (e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) ++ adapter->flags |= FLAG_RESTART_NOW; + else + pm_schedule_suspend(netdev->dev.parent, +- LINK_TIMEOUT); ++ LINK_TIMEOUT); + } + } + +@@ -4458,35 +4964,27 @@ link_up: + adapter->gotc_old = adapter->stats.gotc; + spin_unlock(&adapter->stats64_lock); + +- e1000e_update_adaptive(&adapter->hw); +- +- if (!netif_carrier_ok(netdev) && +- (e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) { +- /* +- * We've lost link, so the controller stops DMA, +- * but we've got queued Tx work that's never going +- * to get done, so reset controller to flush Tx. +- * (Do the reset outside of interrupt context). +- */ ++ if (adapter->flags & FLAG_RESTART_NOW) { + schedule_work(&adapter->reset_task); + /* return immediately since reset is imminent */ + return; + } + ++ e1000e_update_adaptive(&adapter->hw); ++ + /* Simple mode for Interrupt Throttle Rate (ITR) */ + if (adapter->itr_setting == 4) { +- /* +- * Symmetric Tx/Rx gets a reduced ITR=2000; ++ /* Symmetric Tx/Rx gets a reduced ITR=2000; + * Total asymmetrical Tx or Rx gets ITR=8000; + * everyone else is between 2000-8000. + */ + u32 goc = (adapter->gotc + adapter->gorc) / 10000; + u32 dif = (adapter->gotc > adapter->gorc ? +- adapter->gotc - adapter->gorc : +- adapter->gorc - adapter->gotc) / 10000; ++ adapter->gotc - adapter->gorc : ++ adapter->gorc - adapter->gotc) / 10000; + u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000; + +- ew32(ITR, 1000000000 / (itr * 256)); ++ e1000e_write_itr(adapter, itr); + } + + /* Cause software interrupt to ensure Rx ring is cleaned */ +@@ -4499,18 +4997,30 @@ link_up: + e1000e_flush_descriptors(adapter); + + /* Force detection of hung controller every watchdog period */ +- adapter->detect_tx_hung = 1; ++ adapter->detect_tx_hung = true; + +- /* +- * With 82571 controllers, LAA may be overwritten due to controller ++ /* With 82571 controllers, LAA may be overwritten due to controller + * reset from the other port. Set the appropriate LAA in RAR[0] + */ + if (e1000e_get_laa_state_82571(hw)) +- e1000e_rar_set(hw, adapter->hw.mac.addr, 0); ++ hw->mac.ops.rar_set(hw, adapter->hw.mac.addr, 0); + + if (adapter->flags2 & FLAG2_CHECK_PHY_HANG) + e1000e_check_82574_phy_workaround(adapter); + ++#ifdef CONFIG_E1000E_PTP ++ /* Clear valid timestamp stuck in RXSTMPL/H due to a Rx error */ ++ if (adapter->hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE) { ++ if ((adapter->flags2 & FLAG2_CHECK_RX_HWTSTAMP) && ++ (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) { ++ er32(RXSTMPH); ++ adapter->rx_hwtstamp_cleared++; ++ } else { ++ adapter->flags2 |= FLAG2_CHECK_RX_HWTSTAMP; ++ } ++ } ++#endif ++ + /* Reset the timer */ + if (!test_bit(__E1000_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, +@@ -4521,18 +5031,17 @@ link_up: + #define E1000_TX_FLAGS_VLAN 0x00000002 + #define E1000_TX_FLAGS_TSO 0x00000004 + #define E1000_TX_FLAGS_IPV4 0x00000008 ++#define E1000_TX_FLAGS_HWTSTAMP 0x00000020 + #define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 + #define E1000_TX_FLAGS_VLAN_SHIFT 16 + +-static int e1000_tso(struct e1000_adapter *adapter, +- struct sk_buff *skb) ++static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb) + { +- struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_context_desc *context_desc; + struct e1000_buffer *buffer_info; + unsigned int i; + u32 cmd_length = 0; +- u16 ipcse = 0, tucse, mss; ++ u16 ipcse = 0, mss; + u8 ipcss, ipcso, tucss, tucso, hdr_len; + + if (!skb_is_gso(skb)) +@@ -4552,36 +5061,35 @@ static int e1000_tso(struct e1000_adapter *adapter, + iph->tot_len = 0; + iph->check = 0; + tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, +- 0, IPPROTO_TCP, 0); ++ 0, IPPROTO_TCP, 0); + cmd_length = E1000_TXD_CMD_IP; + ipcse = skb_transport_offset(skb) - 1; + } else if (skb_is_gso_v6(skb)) { + ipv6_hdr(skb)->payload_len = 0; + tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, +- &ipv6_hdr(skb)->daddr, +- 0, IPPROTO_TCP, 0); ++ &ipv6_hdr(skb)->daddr, ++ 0, IPPROTO_TCP, 0); + ipcse = 0; + } + ipcss = skb_network_offset(skb); + ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data; + tucss = skb_transport_offset(skb); + tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data; +- tucse = 0; + + cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | +- E1000_TXD_CMD_TCP | (skb->len - (hdr_len))); ++ E1000_TXD_CMD_TCP | (skb->len - (hdr_len))); + + i = tx_ring->next_to_use; + context_desc = E1000_CONTEXT_DESC(*tx_ring, i); + buffer_info = &tx_ring->buffer_info[i]; + +- context_desc->lower_setup.ip_fields.ipcss = ipcss; +- context_desc->lower_setup.ip_fields.ipcso = ipcso; +- context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse); ++ context_desc->lower_setup.ip_fields.ipcss = ipcss; ++ context_desc->lower_setup.ip_fields.ipcso = ipcso; ++ context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse); + context_desc->upper_setup.tcp_fields.tucss = tucss; + context_desc->upper_setup.tcp_fields.tucso = tucso; +- context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse); +- context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); ++ context_desc->upper_setup.tcp_fields.tucse = 0; ++ context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); + context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; + context_desc->cmd_and_length = cpu_to_le32(cmd_length); + +@@ -4596,9 +5104,9 @@ static int e1000_tso(struct e1000_adapter *adapter, + return 1; + } + +-static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) ++static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb) + { +- struct e1000_ring *tx_ring = adapter->tx_ring; ++ struct e1000_adapter *adapter = tx_ring->adapter; + struct e1000_context_desc *context_desc; + struct e1000_buffer *buffer_info; + unsigned int i; +@@ -4639,8 +5147,7 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) + + context_desc->lower_setup.ip_config = 0; + context_desc->upper_setup.tcp_fields.tucss = css; +- context_desc->upper_setup.tcp_fields.tucso = +- css + skb->csum_offset; ++ context_desc->upper_setup.tcp_fields.tucso = css + skb->csum_offset; + context_desc->upper_setup.tcp_fields.tucse = 0; + context_desc->tcp_seg_setup.data = 0; + context_desc->cmd_and_length = cpu_to_le32(cmd_len); +@@ -4656,11 +5163,11 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) + return 1; + } + +-static int e1000_tx_map(struct e1000_adapter *adapter, +- struct sk_buff *skb, unsigned int first, +- unsigned int max_per_txd, unsigned int nr_frags) ++static int e1000_tx_map(struct e1000_ring *tx_ring, struct sk_buff *skb, ++ unsigned int first, unsigned int max_per_txd, ++ unsigned int nr_frags) + { +- struct e1000_ring *tx_ring = adapter->tx_ring; ++ struct e1000_adapter *adapter = tx_ring->adapter; + struct pci_dev *pdev = adapter->pdev; + struct e1000_buffer *buffer_info; + unsigned int len = skb_headlen(skb); +@@ -4713,7 +5220,8 @@ static int e1000_tx_map(struct e1000_adapter *adapter, + buffer_info->time_stamp = jiffies; + buffer_info->next_to_watch = i; + buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag, +- offset, size, DMA_TO_DEVICE); ++ offset, size, ++ DMA_TO_DEVICE); + buffer_info->mapped_as_page = true; + if (dma_mapping_error(&pdev->dev, buffer_info->dma)) + goto dma_error; +@@ -4746,16 +5254,15 @@ dma_error: + i += tx_ring->count; + i--; + buffer_info = &tx_ring->buffer_info[i]; +- e1000_put_txbuf(adapter, buffer_info); ++ e1000_put_txbuf(tx_ring, buffer_info); + } + + return 0; + } + +-static void e1000_tx_queue(struct e1000_adapter *adapter, +- int tx_flags, int count) ++static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count) + { +- struct e1000_ring *tx_ring = adapter->tx_ring; ++ struct e1000_adapter *adapter = tx_ring->adapter; + struct e1000_tx_desc *tx_desc = NULL; + struct e1000_buffer *buffer_info; + u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; +@@ -4763,7 +5270,7 @@ static void e1000_tx_queue(struct e1000_adapter *adapter, + + if (tx_flags & E1000_TX_FLAGS_TSO) { + txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | +- E1000_TXD_CMD_TSE; ++ E1000_TXD_CMD_TSE; + txd_upper |= E1000_TXD_POPTS_TXSM << 8; + + if (tx_flags & E1000_TX_FLAGS_IPV4) +@@ -4780,14 +5287,19 @@ static void e1000_tx_queue(struct e1000_adapter *adapter, + txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); + } + ++ if (unlikely(tx_flags & E1000_TX_FLAGS_HWTSTAMP)) { ++ txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; ++ txd_upper |= E1000_TXD_EXTCMD_TSTAMP; ++ } ++ + i = tx_ring->next_to_use; + + do { + buffer_info = &tx_ring->buffer_info[i]; + tx_desc = E1000_TX_DESC(*tx_ring, i); + tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); +- tx_desc->lower.data = +- cpu_to_le32(txd_lower | buffer_info->length); ++ tx_desc->lower.data = cpu_to_le32(txd_lower | ++ buffer_info->length); + tx_desc->upper.data = cpu_to_le32(txd_upper); + + i++; +@@ -4797,8 +5309,7 @@ static void e1000_tx_queue(struct e1000_adapter *adapter, + + tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); + +- /* +- * Force memory writes to complete before letting h/w ++ /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). +@@ -4808,12 +5319,11 @@ static void e1000_tx_queue(struct e1000_adapter *adapter, + tx_ring->next_to_use = i; + + if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) +- e1000e_update_tdt_wa(adapter, i); ++ e1000e_update_tdt_wa(tx_ring, i); + else +- writel(i, adapter->hw.hw_addr + tx_ring->tail); ++ writel(i, tx_ring->tail); + +- /* +- * we need this if more than one processor can write to our tail ++ /* we need this if more than one processor can write to our tail + * at a time, it synchronizes IO on IA64/Altix systems + */ + mmiowb(); +@@ -4823,24 +5333,23 @@ static void e1000_tx_queue(struct e1000_adapter *adapter, + static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter, + struct sk_buff *skb) + { +- struct e1000_hw *hw = &adapter->hw; ++ struct e1000_hw *hw = &adapter->hw; + u16 length, offset; + +- if (vlan_tx_tag_present(skb)) { +- if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) && +- (adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN))) +- return 0; +- } ++ if (vlan_tx_tag_present(skb) && ++ !((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) && ++ (adapter->hw.mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN))) ++ return 0; + + if (skb->len <= MINIMUM_DHCP_PACKET_SIZE) + return 0; + +- if (((struct ethhdr *) skb->data)->h_proto != htons(ETH_P_IP)) ++ if (((struct ethhdr *)skb->data)->h_proto != htons(ETH_P_IP)) + return 0; + + { +- const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14); ++ const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data + 14); + struct udphdr *udp; + + if (ip->protocol != IPPROTO_UDP) +@@ -4858,40 +5367,36 @@ static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter, + return 0; + } + +-static int __e1000_maybe_stop_tx(struct net_device *netdev, int size) ++static int __e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) + { +- struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct e1000_adapter *adapter = tx_ring->adapter; + +- netif_stop_queue(netdev); +- /* +- * Herbert's original patch had: ++ netif_stop_queue(adapter->netdev); ++ /* Herbert's original patch had: + * smp_mb__after_netif_stop_queue(); + * but since that doesn't exist yet, just open code it. + */ + smp_mb(); + +- /* +- * We need to check again in a case another CPU has just ++ /* We need to check again in a case another CPU has just + * made room available. + */ +- if (e1000_desc_unused(adapter->tx_ring) < size) ++ if (e1000_desc_unused(tx_ring) < size) + return -EBUSY; + + /* A reprieve! */ +- netif_start_queue(netdev); ++ netif_start_queue(adapter->netdev); + ++adapter->restart_queue; + return 0; + } + +-static int e1000_maybe_stop_tx(struct net_device *netdev, int size) ++static int e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) + { +- struct e1000_adapter *adapter = netdev_priv(netdev); ++ BUG_ON(size > tx_ring->count); + +- BUG_ON(size > adapter->tx_ring->count); +- +- if (e1000_desc_unused(adapter->tx_ring) >= size) ++ if (e1000_desc_unused(tx_ring) >= size) + return 0; +- return __e1000_maybe_stop_tx(netdev, size); ++ return __e1000_maybe_stop_tx(tx_ring, size); + } + + static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, +@@ -4918,24 +5423,32 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, + return NETDEV_TX_OK; + } + ++ /* The minimum packet size with TCTL.PSP set is 17 bytes so ++ * pad skb in order to meet this minimum size requirement ++ */ ++ if (unlikely(skb->len < 17)) { ++ if (skb_pad(skb, 17 - skb->len)) ++ return NETDEV_TX_OK; ++ skb->len = 17; ++ skb_set_tail_pointer(skb, 17); ++ } ++ + mss = skb_shinfo(skb)->gso_size; + if (mss) { + u8 hdr_len; + +- /* +- * TSO Workaround for 82571/2/3 Controllers -- if skb->data ++ /* TSO Workaround for 82571/2/3 Controllers -- if skb->data + * points to just header, pull a few bytes of payload from + * frags into skb->data + */ + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); +- /* +- * we do this workaround for ES2LAN, but it is un-necessary, ++ /* we do this workaround for ES2LAN, but it is un-necessary, + * avoiding it could save a lot of cycles + */ + if (skb->data_len && (hdr_len == len)) { + unsigned int pull_size; + +- pull_size = min((unsigned int)4, skb->data_len); ++ pull_size = min_t(unsigned int, 4, skb->data_len); + if (!__pskb_pull_tail(skb, pull_size)) { + e_err("__pskb_pull_tail failed.\n"); + dev_kfree_skb_any(skb); +@@ -4960,11 +5473,10 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, + if (adapter->hw.mac.tx_pkt_filtering) + e1000_transfer_dhcp_info(adapter, skb); + +- /* +- * need: count + 2 desc gap to keep tail from touching ++ /* need: count + 2 desc gap to keep tail from touching + * head, otherwise try next time + */ +- if (e1000_maybe_stop_tx(netdev, count + 2)) ++ if (e1000_maybe_stop_tx(tx_ring, count + 2)) + return NETDEV_TX_BUSY; + + if (vlan_tx_tag_present(skb)) { +@@ -4974,7 +5486,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, + + first = tx_ring->next_to_use; + +- tso = e1000_tso(adapter, skb); ++ tso = e1000_tso(tx_ring, skb); + if (tso < 0) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +@@ -4982,11 +5494,10 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, + + if (tso) + tx_flags |= E1000_TX_FLAGS_TSO; +- else if (e1000_tx_csum(adapter, skb)) ++ else if (e1000_tx_csum(tx_ring, skb)) + tx_flags |= E1000_TX_FLAGS_CSUM; + +- /* +- * Old method was to assume IPv4 packet by default if TSO was enabled. ++ /* Old method was to assume IPv4 packet by default if TSO was enabled. + * 82571 hardware supports TSO capabilities for IPv6 as well... + * no longer assume, we must. + */ +@@ -4994,12 +5505,26 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, + tx_flags |= E1000_TX_FLAGS_IPV4; + + /* if count is 0 then mapping error has occurred */ +- count = e1000_tx_map(adapter, skb, first, adapter->tx_fifo_limit, ++ count = e1000_tx_map(tx_ring, skb, first, adapter->tx_fifo_limit, + nr_frags); + if (count) { +- e1000_tx_queue(adapter, tx_flags, count); ++#ifdef CONFIG_E1000E_PTP ++ if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && ++ !adapter->tx_hwtstamp_skb)) { ++ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; ++ tx_flags |= E1000_TX_FLAGS_HWTSTAMP; ++ adapter->tx_hwtstamp_skb = skb_get(skb); ++ schedule_work(&adapter->tx_hwtstamp_work); ++ } else ++#endif ++ { ++ skb_tx_timestamp(skb); ++ } ++ ++ netdev_sent_queue(netdev, skb->len); ++ e1000_tx_queue(tx_ring, tx_flags, count); + /* Make sure there is space in the ring for the next send. */ +- e1000_maybe_stop_tx(netdev, ++ e1000_maybe_stop_tx(tx_ring, + (MAX_SKB_FRAGS * + DIV_ROUND_UP(PAGE_SIZE, + adapter->tx_fifo_limit) + 2)); +@@ -5034,10 +5559,9 @@ static void e1000_reset_task(struct work_struct *work) + if (test_bit(__E1000_DOWN, &adapter->state)) + return; + +- if (!((adapter->flags & FLAG_RX_NEEDS_RESTART) && +- (adapter->flags & FLAG_RX_RESTART_NOW))) { ++ if (!(adapter->flags & FLAG_RESTART_NOW)) { + e1000e_dump(adapter); +- e_err("Reset adapter\n"); ++ e_err("Reset adapter unexpectedly\n"); + } + e1000e_reinit_locked(adapter); + } +@@ -5050,7 +5574,7 @@ static void e1000_reset_task(struct work_struct *work) + * Returns the address of the device statistics structure. + **/ + struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, +- struct rtnl_link_stats64 *stats) ++ struct rtnl_link_stats64 *stats) + { + struct e1000_adapter *adapter = netdev_priv(netdev); + +@@ -5067,23 +5591,19 @@ struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, + + /* Rx Errors */ + +- /* +- * RLEC on some newer hardware can be incorrect so build ++ /* RLEC on some newer hardware can be incorrect so build + * our own version based on RUC and ROC + */ + stats->rx_errors = adapter->stats.rxerrc + +- adapter->stats.crcerrs + adapter->stats.algnerrc + +- adapter->stats.ruc + adapter->stats.roc + +- adapter->stats.cexterr; +- stats->rx_length_errors = adapter->stats.ruc + +- adapter->stats.roc; ++ adapter->stats.crcerrs + adapter->stats.algnerrc + ++ adapter->stats.ruc + adapter->stats.roc + adapter->stats.cexterr; ++ stats->rx_length_errors = adapter->stats.ruc + adapter->stats.roc; + stats->rx_crc_errors = adapter->stats.crcerrs; + stats->rx_frame_errors = adapter->stats.algnerrc; + stats->rx_missed_errors = adapter->stats.mpc; + + /* Tx Errors */ +- stats->tx_errors = adapter->stats.ecol + +- adapter->stats.latecol; ++ stats->tx_errors = adapter->stats.ecol + adapter->stats.latecol; + stats->tx_aborted_errors = adapter->stats.ecol; + stats->tx_window_errors = adapter->stats.latecol; + stats->tx_carrier_errors = adapter->stats.tncrs; +@@ -5120,12 +5640,11 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) + return -EINVAL; + } + +- /* Jumbo frame workaround on 82579 requires CRC be stripped */ +- if ((adapter->hw.mac.type == e1000_pch2lan) && ++ /* Jumbo frame workaround on 82579 and newer requires CRC be stripped */ ++ if ((adapter->hw.mac.type >= e1000_pch2lan) && + !(adapter->flags2 & FLAG2_CRC_STRIPPING) && + (new_mtu > ETH_DATA_LEN)) { +- e_err("Jumbo Frames not supported on 82579 when CRC " +- "stripping is disabled.\n"); ++ e_err("Jumbo Frames not supported on this device when CRC stripping is disabled.\n"); + return -EINVAL; + } + +@@ -5138,8 +5657,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) + if (netif_running(netdev)) + e1000e_down(adapter); + +- /* +- * NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN ++ /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN + * means we reserve 2 more, this pushes us to allocate from the next + * larger slab size. + * i.e. RXBUFFER_2048 --> size-4096 slab +@@ -5154,9 +5672,9 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) + + /* adjust allocation if LPE protects us, and we aren't using SBP */ + if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) || +- (max_frame == ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)) ++ (max_frame == ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)) + adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN +- + ETH_FCS_LEN; ++ + ETH_FCS_LEN; + + if (netif_running(netdev)) + e1000e_up(adapter); +@@ -5226,6 +5744,64 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, + return 0; + } + ++#ifdef CONFIG_E1000E_PTP ++/** ++ * e1000e_hwtstamp_ioctl - control hardware time stamping ++ * @netdev: network interface device structure ++ * @ifreq: interface request ++ * ++ * Outgoing time stamping can be enabled and disabled. Play nice and ++ * disable it when requested, although it shouldn't cause any overhead ++ * when no packet needs it. At most one packet in the queue may be ++ * marked for time stamping, otherwise it would be impossible to tell ++ * for sure to which packet the hardware time stamp belongs. ++ * ++ * Incoming time stamping has to be configured via the hardware filters. ++ * Not all combinations are supported, in particular event type has to be ++ * specified. Matching the kind of event packet is not supported, with the ++ * exception of "all V2 events regardless of level 2 or 4". ++ **/ ++static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) ++{ ++ struct e1000_adapter *adapter = netdev_priv(netdev); ++ struct hwtstamp_config config; ++ int ret_val; ++ ++ if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) ++ return -EFAULT; ++ ++ ret_val = e1000e_config_hwtstamp(adapter, &config); ++ if (ret_val) ++ return ret_val; ++ ++ switch (config.rx_filter) { ++ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: ++ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: ++ case HWTSTAMP_FILTER_PTP_V2_SYNC: ++ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: ++ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: ++ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: ++ /* With V2 type filters which specify a Sync or Delay Request, ++ * Path Delay Request/Response messages are also time stamped ++ * by hardware so notify the caller the requested packets plus ++ * some others are time stamped. ++ */ ++ config.rx_filter = HWTSTAMP_FILTER_SOME; ++ break; ++ default: ++ break; ++ } ++ ++ return copy_to_user(ifr->ifr_data, &config, ++ sizeof(config)) ? -EFAULT : 0; ++} ++#else ++static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) ++{ ++ return -EOPNOTSUPP; ++} ++#endif ++ + static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + { + switch (cmd) { +@@ -5233,6 +5809,8 @@ static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + case SIOCGMIIREG: + case SIOCSMIIREG: + return e1000_mii_ioctl(netdev, ifr, cmd); ++ case SIOCSHWTSTAMP: ++ return e1000e_hwtstamp_ioctl(netdev, ifr); + default: + return -EOPNOTSUPP; + } +@@ -5243,7 +5821,7 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) + struct e1000_hw *hw = &adapter->hw; + u32 i, mac_reg; + u16 phy_reg, wuc_enable; +- int retval = 0; ++ int retval; + + /* copy MAC RARs to PHY RARs */ + e1000_copy_rx_addrs_to_phy_ich8lan(hw); +@@ -5257,7 +5835,7 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) + /* Enable access to wakeup registers on and set page to BM_WUC_PAGE */ + retval = e1000_enable_phy_wakeup_reg_access_bm(hw, &wuc_enable); + if (retval) +- goto out; ++ goto release; + + /* copy MAC MTA to PHY MTA - only needed for pchlan */ + for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) { +@@ -5278,7 +5856,7 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) + phy_reg &= ~(BM_RCTL_MO_MASK); + if (mac_reg & E1000_RCTL_MO_3) + phy_reg |= (((mac_reg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT) +- << BM_RCTL_MO_SHIFT); ++ << BM_RCTL_MO_SHIFT); + if (mac_reg & E1000_RCTL_BAM) + phy_reg |= BM_RCTL_BAM; + if (mac_reg & E1000_RCTL_PMCF) +@@ -5301,14 +5879,13 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) + retval = e1000_disable_phy_wakeup_reg_access_bm(hw, &wuc_enable); + if (retval) + e_err("Could not set PHY Host Wakeup bit\n"); +-out: ++release: + hw->phy.ops.release(hw); + + return retval; + } + +-static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, +- bool runtime) ++static int __e1000_shutdown(struct pci_dev *pdev, bool runtime) + { + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev_priv(netdev); +@@ -5321,23 +5898,24 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, + netif_device_detach(netdev); + + if (netif_running(netdev)) { ++ int count = E1000_CHECK_RESET_COUNT; ++ ++ while (test_bit(__E1000_RESETTING, &adapter->state) && count--) ++ usleep_range(10000, 20000); ++ + WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); + e1000e_down(adapter); + e1000_free_irq(adapter); + } + e1000e_reset_interrupt_capability(adapter); + +- retval = pci_save_state(pdev); +- if (retval) +- return retval; +- + status = er32(STATUS); + if (status & E1000_STATUS_LU) + wufc &= ~E1000_WUFC_LNKC; + + if (wufc) { + e1000_setup_rctl(adapter); +- e1000_set_multi(netdev); ++ e1000e_set_rx_mode(netdev); + + /* turn on all-multi mode if wake on multicast is enabled */ + if (wufc & E1000_WUFC_MC) { +@@ -5347,10 +5925,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, + } + + ctrl = er32(CTRL); +- /* advertise wake from D3Cold */ +- #define E1000_CTRL_ADVD3WUC 0x00100000 +- /* phy power management enable */ +- #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 + ctrl |= E1000_CTRL_ADVD3WUC; + if (!(adapter->flags2 & FLAG2_HAS_PHY_WAKEUP)) + ctrl |= E1000_CTRL_EN_PHY_PWR_MGMT; +@@ -5386,103 +5960,112 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, + ew32(WUFC, 0); + } + +- *enable_wake = !!wufc; +- +- /* make sure adapter isn't asleep if manageability is enabled */ +- if ((adapter->flags & FLAG_MNG_PT_ENABLED) || +- (hw->mac.ops.check_mng_mode(hw))) +- *enable_wake = true; +- + if (adapter->hw.phy.type == e1000_phy_igp_3) + e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); + +- /* +- * Release control of h/w to f/w. If f/w is AMT enabled, this ++ /* Release control of h/w to f/w. If f/w is AMT enabled, this + * would have already happened in close and is redundant. + */ + e1000e_release_hw_control(adapter); + + pci_clear_master(pdev); + +- return 0; +-} +- +-static void e1000_power_off(struct pci_dev *pdev, bool sleep, bool wake) +-{ +- if (sleep && wake) { +- pci_prepare_to_sleep(pdev); +- return; +- } +- +- pci_wake_from_d3(pdev, wake); +- pci_set_power_state(pdev, PCI_D3hot); +-} +- +-static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep, +- bool wake) +-{ +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct e1000_adapter *adapter = netdev_priv(netdev); +- +- /* +- * The pci-e switch on some quad port adapters will report a ++ /* The pci-e switch on some quad port adapters will report a + * correctable error when the MAC transitions from D0 to D3. To + * prevent this we need to mask off the correctable errors on the + * downstream port of the pci-e switch. ++ * ++ * We don't have the associated upstream bridge while assigning ++ * the PCI device into guest. For example, the KVM on power is ++ * one of the cases. + */ + if (adapter->flags & FLAG_IS_QUAD_PORT) { + struct pci_dev *us_dev = pdev->bus->self; +- int pos = pci_pcie_cap(us_dev); + u16 devctl; + +- pci_read_config_word(us_dev, pos + PCI_EXP_DEVCTL, &devctl); +- pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL, +- (devctl & ~PCI_EXP_DEVCTL_CERE)); ++ if (!us_dev) ++ return 0; + +- e1000_power_off(pdev, sleep, wake); ++ pcie_capability_read_word(us_dev, PCI_EXP_DEVCTL, &devctl); ++ pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, ++ (devctl & ~PCI_EXP_DEVCTL_CERE)); + +- pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL, devctl); +- } else { +- e1000_power_off(pdev, sleep, wake); ++ pci_save_state(pdev); ++ pci_prepare_to_sleep(pdev); ++ ++ pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, devctl); + } ++ ++ return 0; + } + +-#ifdef CONFIG_PCIEASPM +-static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) ++/** ++ * e1000e_disable_aspm - Disable ASPM states ++ * @pdev: pointer to PCI device struct ++ * @state: bit-mask of ASPM states to disable ++ * ++ * Some devices *must* have certain ASPM states disabled per hardware errata. ++ **/ ++static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) + { ++ struct pci_dev *parent = pdev->bus->self; ++ u16 aspm_dis_mask = 0; ++ u16 pdev_aspmc, parent_aspmc; ++ ++ switch (state) { ++ case PCIE_LINK_STATE_L0S: ++ case PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1: ++ aspm_dis_mask |= PCI_EXP_LNKCTL_ASPM_L0S; ++ /* fall-through - can't have L1 without L0s */ ++ case PCIE_LINK_STATE_L1: ++ aspm_dis_mask |= PCI_EXP_LNKCTL_ASPM_L1; ++ break; ++ default: ++ return; ++ } ++ ++ pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &pdev_aspmc); ++ pdev_aspmc &= PCI_EXP_LNKCTL_ASPMC; ++ ++ if (parent) { ++ pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ++ &parent_aspmc); ++ parent_aspmc &= PCI_EXP_LNKCTL_ASPMC; ++ } ++ ++ /* Nothing to do if the ASPM states to be disabled already are */ ++ if (!(pdev_aspmc & aspm_dis_mask) && ++ (!parent || !(parent_aspmc & aspm_dis_mask))) ++ return; ++ ++ dev_info(&pdev->dev, "Disabling ASPM %s %s\n", ++ (aspm_dis_mask & pdev_aspmc & PCI_EXP_LNKCTL_ASPM_L0S) ? ++ "L0s" : "", ++ (aspm_dis_mask & pdev_aspmc & PCI_EXP_LNKCTL_ASPM_L1) ? ++ "L1" : ""); ++ ++#ifdef CONFIG_PCIEASPM + pci_disable_link_state_locked(pdev, state); +-} +-#else +-static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) +-{ +- int pos; +- u16 reg16; + +- /* +- * Both device and parent should have the same ASPM setting. +- * Disable ASPM in downstream component first and then upstream. ++ /* Double-check ASPM control. If not disabled by the above, the ++ * BIOS is preventing that from happening (or CONFIG_PCIEASPM is ++ * not enabled); override by writing PCI config space directly. + */ +- pos = pci_pcie_cap(pdev); +- pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); +- reg16 &= ~state; +- pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); ++ pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &pdev_aspmc); ++ pdev_aspmc &= PCI_EXP_LNKCTL_ASPMC; + +- if (!pdev->bus->self) ++ if (!(aspm_dis_mask & pdev_aspmc)) + return; +- +- pos = pci_pcie_cap(pdev->bus->self); +- pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, ®16); +- reg16 &= ~state; +- pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16); +-} + #endif +-static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) +-{ +- dev_info(&pdev->dev, "Disabling ASPM %s %s\n", +- (state & PCIE_LINK_STATE_L0S) ? "L0s" : "", +- (state & PCIE_LINK_STATE_L1) ? "L1" : ""); + +- __e1000e_disable_aspm(pdev, state); ++ /* Both device and parent should have the same ASPM setting. ++ * Disable ASPM in downstream component first and then upstream. ++ */ ++ pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, aspm_dis_mask); ++ ++ if (parent) ++ pcie_capability_clear_word(parent, PCI_EXP_LNKCTL, ++ aspm_dis_mask); + } + + #ifdef CONFIG_PM +@@ -5506,9 +6089,7 @@ static int __e1000_resume(struct pci_dev *pdev) + if (aspm_disable_flag) + e1000e_disable_aspm(pdev, aspm_disable_flag); + +- pci_set_power_state(pdev, PCI_D0); +- pci_restore_state(pdev); +- pci_save_state(pdev); ++ pci_set_master(pdev); + + e1000e_set_interrupt_capability(adapter); + if (netif_running(netdev)) { +@@ -5517,7 +6098,7 @@ static int __e1000_resume(struct pci_dev *pdev) + return err; + } + +- if (hw->mac.type == e1000_pch2lan) ++ if (hw->mac.type >= e1000_pch2lan) + e1000_resume_workarounds_pchlan(&adapter->hw); + + e1000e_power_up_phy(adapter); +@@ -5529,24 +6110,24 @@ static int __e1000_resume(struct pci_dev *pdev) + e1e_rphy(&adapter->hw, BM_WUS, &phy_data); + if (phy_data) { + e_info("PHY Wakeup cause - %s\n", +- phy_data & E1000_WUS_EX ? "Unicast Packet" : +- phy_data & E1000_WUS_MC ? "Multicast Packet" : +- phy_data & E1000_WUS_BC ? "Broadcast Packet" : +- phy_data & E1000_WUS_MAG ? "Magic Packet" : +- phy_data & E1000_WUS_LNKC ? "Link Status " +- " Change" : "other"); ++ phy_data & E1000_WUS_EX ? "Unicast Packet" : ++ phy_data & E1000_WUS_MC ? "Multicast Packet" : ++ phy_data & E1000_WUS_BC ? "Broadcast Packet" : ++ phy_data & E1000_WUS_MAG ? "Magic Packet" : ++ phy_data & E1000_WUS_LNKC ? ++ "Link Status Change" : "other"); + } + e1e_wphy(&adapter->hw, BM_WUS, ~0); + } else { + u32 wus = er32(WUS); + if (wus) { + e_info("MAC Wakeup cause - %s\n", +- wus & E1000_WUS_EX ? "Unicast Packet" : +- wus & E1000_WUS_MC ? "Multicast Packet" : +- wus & E1000_WUS_BC ? "Broadcast Packet" : +- wus & E1000_WUS_MAG ? "Magic Packet" : +- wus & E1000_WUS_LNKC ? "Link Status Change" : +- "other"); ++ wus & E1000_WUS_EX ? "Unicast Packet" : ++ wus & E1000_WUS_MC ? "Multicast Packet" : ++ wus & E1000_WUS_BC ? "Broadcast Packet" : ++ wus & E1000_WUS_MAG ? "Magic Packet" : ++ wus & E1000_WUS_LNKC ? "Link Status Change" : ++ "other"); + } + ew32(WUS, ~0); + } +@@ -5560,8 +6141,7 @@ static int __e1000_resume(struct pci_dev *pdev) + + netif_device_attach(netdev); + +- /* +- * If the controller has AMT, do not set DRV_LOAD until the interface ++ /* If the controller has AMT, do not set DRV_LOAD until the interface + * is up. For all other cases, let the f/w know that the h/w is now + * under the control of the driver. + */ +@@ -5575,14 +6155,8 @@ static int __e1000_resume(struct pci_dev *pdev) + static int e1000_suspend(struct device *dev) + { + struct pci_dev *pdev = to_pci_dev(dev); +- int retval; +- bool wake; +- +- retval = __e1000_shutdown(pdev, &wake, false); +- if (!retval) +- e1000_complete_shutdown(pdev, true, wake); + +- return retval; ++ return __e1000_shutdown(pdev, false); + } + + static int e1000_resume(struct device *dev) +@@ -5605,13 +6179,10 @@ static int e1000_runtime_suspend(struct device *dev) + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev_priv(netdev); + +- if (e1000e_pm_ready(adapter)) { +- bool wake; +- +- __e1000_shutdown(pdev, &wake, true); +- } ++ if (!e1000e_pm_ready(adapter)) ++ return 0; + +- return 0; ++ return __e1000_shutdown(pdev, true); + } + + static int e1000_idle(struct device *dev) +@@ -5649,17 +6220,12 @@ static int e1000_runtime_resume(struct device *dev) + + static void e1000_shutdown(struct pci_dev *pdev) + { +- bool wake = false; +- +- __e1000_shutdown(pdev, &wake, false); +- +- if (system_state == SYSTEM_POWER_OFF) +- e1000_complete_shutdown(pdev, false, wake); ++ __e1000_shutdown(pdev, false); + } + + #ifdef CONFIG_NET_POLL_CONTROLLER + +-static irqreturn_t e1000_intr_msix(int irq, void *data) ++static irqreturn_t e1000_intr_msix(int __always_unused irq, void *data) + { + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); +@@ -5689,7 +6255,10 @@ static irqreturn_t e1000_intr_msix(int irq, void *data) + return IRQ_HANDLED; + } + +-/* ++/** ++ * e1000_netpoll ++ * @netdev: network interface device structure ++ * + * Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. +@@ -5707,7 +6276,7 @@ static void e1000_netpoll(struct net_device *netdev) + e1000_intr_msi(adapter->pdev->irq, netdev); + enable_irq(adapter->pdev->irq); + break; +- default: /* E1000E_INT_MODE_LEGACY */ ++ default: /* E1000E_INT_MODE_LEGACY */ + disable_irq(adapter->pdev->irq); + e1000_intr(adapter->pdev->irq, netdev); + enable_irq(adapter->pdev->irq); +@@ -5772,9 +6341,9 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) + "Cannot re-enable PCI device after reset.\n"); + result = PCI_ERS_RESULT_DISCONNECT; + } else { +- pci_set_master(pdev); + pdev->state_saved = true; + pci_restore_state(pdev); ++ pci_set_master(pdev); + + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); +@@ -5814,14 +6383,12 @@ static void e1000_io_resume(struct pci_dev *pdev) + + netif_device_attach(netdev); + +- /* +- * If the controller has AMT, do not set DRV_LOAD until the interface ++ /* If the controller has AMT, do not set DRV_LOAD until the interface + * is up. For all other cases, let the f/w know that the h/w is now + * under the control of the driver. + */ + if (!(adapter->flags & FLAG_HAS_AMT)) + e1000e_get_hw_control(adapter); +- + } + + static void e1000_print_device_info(struct e1000_adapter *adapter) +@@ -5835,7 +6402,7 @@ static void e1000_print_device_info(struct e1000_adapter *adapter) + e_info("(PCI Express:2.5GT/s:%s) %pM\n", + /* bus width */ + ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" : +- "Width x1"), ++ "Width x1"), + /* MAC address */ + netdev->dev_addr); + e_info("Intel(R) PRO/%s Network Connection\n", +@@ -5843,7 +6410,7 @@ static void e1000_print_device_info(struct e1000_adapter *adapter) + ret_val = e1000_read_pba_string_generic(hw, pba_str, + E1000_PBANUM_LENGTH); + if (ret_val) +- strncpy((char *)pba_str, "Unknown", sizeof(pba_str) - 1); ++ strlcpy((char *)pba_str, "Unknown", sizeof(pba_str)); + e_info("MAC: %d, PHY: %d, PBA No: %s\n", + hw->mac.type, hw->phy.type, pba_str); + } +@@ -5858,25 +6425,29 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter) + return; + + ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &buf); +- if (!ret_val && (!(le16_to_cpu(buf) & (1 << 0)))) { ++ le16_to_cpus(&buf); ++ if (!ret_val && (!(buf & (1 << 0)))) { + /* Deep Smart Power Down (DSPD) */ + dev_warn(&adapter->pdev->dev, + "Warning: detected DSPD enabled in EEPROM\n"); + } + } + +-static int e1000_set_features(struct net_device *netdev, u32 features) ++static int e1000_set_features(struct net_device *netdev, ++ netdev_features_t features) + { + struct e1000_adapter *adapter = netdev_priv(netdev); +- u32 changed = features ^ netdev->features; ++ netdev_features_t changed = features ^ netdev->features; + + if (changed & (NETIF_F_TSO | NETIF_F_TSO6)) + adapter->flags |= FLAG_TSO_FORCE; + + if (!(changed & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX | +- NETIF_F_RXCSUM))) ++ NETIF_F_RXCSUM | NETIF_F_RXHASH))) + return 0; + ++ netdev->features = features; ++ + if (netif_running(netdev)) + e1000e_reinit_locked(adapter); + else +@@ -5890,7 +6461,7 @@ static const struct net_device_ops e1000e_netdev_ops = { + .ndo_stop = e1000_close, + .ndo_start_xmit = e1000_xmit_frame, + .ndo_get_stats64 = e1000e_get_stats64, +- .ndo_set_rx_mode = e1000_set_multi, ++ .ndo_set_rx_mode = e1000e_set_rx_mode, + .ndo_set_mac_address = e1000_set_mac, + .ndo_change_mtu = e1000_change_mtu, + .ndo_do_ioctl = e1000_ioctl, +@@ -5916,8 +6487,7 @@ static const struct net_device_ops e1000e_netdev_ops = { + * The OS initialization, configuring of the adapter private structure, + * and a hardware reset occur. + **/ +-static int __devinit e1000_probe(struct pci_dev *pdev, +- const struct pci_device_id *ent) ++static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + { + struct net_device *netdev; + struct e1000_adapter *adapter; +@@ -5925,10 +6495,9 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + const struct e1000_info *ei = e1000_info_tbl[ent->driver_data]; + resource_size_t mmio_start, mmio_len; + resource_size_t flash_start, flash_len; +- + static int cards_found; + u16 aspm_disable_flag = 0; +- int i, err, pci_using_dac; ++ int bars, i, err, pci_using_dac; + u16 eeprom_data = 0; + u16 eeprom_apme_mask = E1000_EEPROM_APME; + +@@ -5944,27 +6513,21 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + return err; + + pci_using_dac = 0; +- err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); ++ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (!err) { +- err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); +- if (!err) +- pci_using_dac = 1; ++ pci_using_dac = 1; + } else { +- err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); ++ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (err) { +- err = dma_set_coherent_mask(&pdev->dev, +- DMA_BIT_MASK(32)); +- if (err) { +- dev_err(&pdev->dev, "No usable DMA " +- "configuration, aborting\n"); +- goto err_dma; +- } ++ dev_err(&pdev->dev, ++ "No usable DMA configuration, aborting\n"); ++ goto err_dma; + } + } + +- err = pci_request_selected_regions_exclusive(pdev, +- pci_select_bars(pdev, IORESOURCE_MEM), +- e1000e_driver_name); ++ bars = pci_select_bars(pdev, IORESOURCE_MEM); ++ err = pci_request_selected_regions_exclusive(pdev, bars, ++ e1000e_driver_name); + if (err) + goto err_pci_reg; + +@@ -5998,7 +6561,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + adapter->hw.adapter = adapter; + adapter->hw.mac.type = ei->mac; + adapter->max_hw_frame_size = ei->max_hw_frame_size; +- adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1; ++ adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); + + mmio_start = pci_resource_start(pdev, 0); + mmio_len = pci_resource_len(pdev, 0); +@@ -6017,12 +6580,16 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + goto err_flashmap; + } + ++ /* Set default EEE advertisement */ ++ if (adapter->flags2 & FLAG2_HAS_EEE) ++ adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T; ++ + /* construct the net_device struct */ +- netdev->netdev_ops = &e1000e_netdev_ops; ++ netdev->netdev_ops = &e1000e_netdev_ops; + e1000e_set_ethtool_ops(netdev); +- netdev->watchdog_timeo = 5 * HZ; +- netif_napi_add(netdev, &adapter->napi, e1000_clean, 64); +- strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); ++ netdev->watchdog_timeo = 5 * HZ; ++ netif_napi_add(netdev, &adapter->napi, e1000e_poll, 64); ++ strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name)); + + netdev->mem_start = mmio_start; + netdev->mem_end = mmio_start + mmio_len; +@@ -6059,8 +6626,9 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + adapter->hw.phy.ms_type = e1000_ms_hw_default; + } + +- if (e1000_check_reset_block(&adapter->hw)) +- e_info("PHY reset is blocked due to SOL/IDER session.\n"); ++ if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) ++ dev_info(&pdev->dev, ++ "PHY reset is blocked due to SOL/IDER session.\n"); + + /* Set initial default active device features */ + netdev->features = (NETIF_F_SG | +@@ -6068,6 +6636,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + NETIF_F_HW_VLAN_TX | + NETIF_F_TSO | + NETIF_F_TSO6 | ++ NETIF_F_RXHASH | + NETIF_F_RXCSUM | + NETIF_F_HW_CSUM); + +@@ -6082,6 +6651,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + NETIF_F_TSO6 | + NETIF_F_HW_CSUM); + ++ netdev->priv_flags |= IFF_UNICAST_FLT; ++ + if (pci_using_dac) { + netdev->features |= NETIF_F_HIGHDMA; + netdev->vlan_features |= NETIF_F_HIGHDMA; +@@ -6090,21 +6661,19 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + if (e1000e_enable_mng_pass_thru(&adapter->hw)) + adapter->flags |= FLAG_MNG_PT_ENABLED; + +- /* +- * before reading the NVM, reset the controller to ++ /* before reading the NVM, reset the controller to + * put the device in a known good starting state + */ + adapter->hw.mac.ops.reset_hw(&adapter->hw); + +- /* +- * systems with ASPM and others may see the checksum fail on the first ++ /* systems with ASPM and others may see the checksum fail on the first + * attempt. Let's give it a few tries + */ + for (i = 0;; i++) { + if (e1000_validate_nvm_checksum(&adapter->hw) >= 0) + break; + if (i == 2) { +- e_err("The NVM Checksum Is Not Valid\n"); ++ dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); + err = -EIO; + goto err_eeprom; + } +@@ -6114,24 +6683,26 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + + /* copy the MAC address */ + if (e1000e_read_mac_addr(&adapter->hw)) +- e_err("NVM Read Error while reading MAC address\n"); ++ dev_err(&pdev->dev, ++ "NVM Read Error while reading MAC address\n"); + + memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len); + memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len); + + if (!is_valid_ether_addr(netdev->perm_addr)) { +- e_err("Invalid MAC Address: %pM\n", netdev->perm_addr); ++ dev_err(&pdev->dev, "Invalid MAC Address: %pM\n", ++ netdev->perm_addr); + err = -EIO; + goto err_eeprom; + } + + init_timer(&adapter->watchdog_timer); + adapter->watchdog_timer.function = e1000_watchdog; +- adapter->watchdog_timer.data = (unsigned long) adapter; ++ adapter->watchdog_timer.data = (unsigned long)adapter; + + init_timer(&adapter->phy_info_timer); + adapter->phy_info_timer.function = e1000_update_phy_info; +- adapter->phy_info_timer.data = (unsigned long) adapter; ++ adapter->phy_info_timer.data = (unsigned long)adapter; + + INIT_WORK(&adapter->reset_task, e1000_reset_task); + INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task); +@@ -6141,17 +6712,12 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + + /* Initialize link parameters. User can change them with ethtool */ + adapter->hw.mac.autoneg = 1; +- adapter->fc_autoneg = 1; ++ adapter->fc_autoneg = true; + adapter->hw.fc.requested_mode = e1000_fc_default; + adapter->hw.fc.current_mode = e1000_fc_default; + adapter->hw.phy.autoneg_advertised = 0x2f; + +- /* ring size defaults */ +- adapter->rx_ring->count = E1000_DEFAULT_RXD; +- adapter->tx_ring->count = E1000_DEFAULT_TXD; +- +- /* +- * Initial Wake on LAN setting - If APM wake is enabled in ++ /* Initial Wake on LAN setting - If APM wake is enabled in + * the EEPROM, enable the ACPI Magic Packet filter + */ + if (adapter->flags & FLAG_APME_IN_WUC) { +@@ -6164,19 +6730,18 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + } else if (adapter->flags & FLAG_APME_IN_CTRL3) { + if (adapter->flags & FLAG_APME_CHECK_PORT_B && + (adapter->hw.bus.func == 1)) +- e1000_read_nvm(&adapter->hw, +- NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); ++ e1000_read_nvm(&adapter->hw, NVM_INIT_CONTROL3_PORT_B, ++ 1, &eeprom_data); + else +- e1000_read_nvm(&adapter->hw, +- NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); ++ e1000_read_nvm(&adapter->hw, NVM_INIT_CONTROL3_PORT_A, ++ 1, &eeprom_data); + } + + /* fetch WoL from EEPROM */ + if (eeprom_data & eeprom_apme_mask) + adapter->eeprom_wol |= E1000_WUFC_MAG; + +- /* +- * now that we have the eeprom settings, apply the special cases ++ /* now that we have the eeprom settings, apply the special cases + * where the eeprom may be wrong or the board simply won't support + * wake on lan on a particular port + */ +@@ -6185,7 +6750,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + + /* initialize the wol settings based on the eeprom settings */ + adapter->wol = adapter->eeprom_wol; +- device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); ++ ++ /* make sure adapter isn't asleep if manageability is enabled */ ++ if (adapter->wol || (adapter->flags & FLAG_MNG_PT_ENABLED) || ++ (hw->mac.ops.check_mng_mode(hw))) ++ device_wakeup_enable(&pdev->dev); + + /* save off EEPROM version number */ + e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers); +@@ -6193,15 +6762,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + /* reset the hardware with the new settings */ + e1000e_reset(adapter); + +- /* +- * If the controller has AMT, do not set DRV_LOAD until the interface ++ /* If the controller has AMT, do not set DRV_LOAD until the interface + * is up. For all other cases, let the f/w know that the h/w is now + * under the control of the driver. + */ + if (!(adapter->flags & FLAG_HAS_AMT)) + e1000e_get_hw_control(adapter); + +- strncpy(netdev->name, "eth%d", sizeof(netdev->name) - 1); ++ strlcpy(netdev->name, "eth%d", sizeof(netdev->name)); + err = register_netdev(netdev); + if (err) + goto err_register; +@@ -6209,6 +6777,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev, + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(netdev); + ++#ifdef CONFIG_E1000E_PTP ++ /* init PTP hardware clock */ ++ e1000e_ptp_init(adapter); ++#endif ++ + e1000_print_device_info(adapter); + + if (pci_dev_run_wake(pdev)) +@@ -6220,7 +6793,7 @@ err_register: + if (!(adapter->flags & FLAG_HAS_AMT)) + e1000e_release_hw_control(adapter); + err_eeprom: +- if (!e1000_check_reset_block(&adapter->hw)) ++ if (hw->phy.ops.check_reset_block && !hw->phy.ops.check_reset_block(hw)) + e1000_phy_hw_reset(&adapter->hw); + err_hw_init: + kfree(adapter->tx_ring); +@@ -6235,7 +6808,7 @@ err_ioremap: + free_netdev(netdev); + err_alloc_etherdev: + pci_release_selected_regions(pdev, +- pci_select_bars(pdev, IORESOURCE_MEM)); ++ pci_select_bars(pdev, IORESOURCE_MEM)); + err_pci_reg: + err_dma: + pci_disable_device(pdev); +@@ -6251,14 +6824,17 @@ err_dma: + * Hot-Plug event, or because the driver is going to be removed from + * memory. + **/ +-static void __devexit e1000_remove(struct pci_dev *pdev) ++static void e1000_remove(struct pci_dev *pdev) + { + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev_priv(netdev); + bool down = test_bit(__E1000_DOWN, &adapter->state); + +- /* +- * The timers may be rescheduled, so explicitly disable them ++#ifdef CONFIG_E1000E_PTP ++ e1000e_ptp_remove(adapter); ++#endif ++ ++ /* The timers may be rescheduled, so explicitly disable them + * from being rescheduled. + */ + if (!down) +@@ -6272,6 +6848,16 @@ static void __devexit e1000_remove(struct pci_dev *pdev) + cancel_work_sync(&adapter->update_phy_task); + cancel_work_sync(&adapter->print_hang_task); + ++#ifdef CONFIG_E1000E_PTP ++ if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) { ++ cancel_work_sync(&adapter->tx_hwtstamp_work); ++ if (adapter->tx_hwtstamp_skb) { ++ dev_kfree_skb_any(adapter->tx_hwtstamp_skb); ++ adapter->tx_hwtstamp_skb = NULL; ++ } ++ } ++#endif ++ + if (!(netdev->flags & IFF_UP)) + e1000_power_down_phy(adapter); + +@@ -6283,8 +6869,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev) + if (pci_dev_run_wake(pdev)) + pm_runtime_get_noresume(&pdev->dev); + +- /* +- * Release control of h/w to f/w. If f/w is AMT enabled, this ++ /* Release control of h/w to f/w. If f/w is AMT enabled, this + * would have already happened in close and is redundant. + */ + e1000e_release_hw_control(adapter); +@@ -6297,7 +6882,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev) + if (adapter->hw.flash_address) + iounmap(adapter->hw.flash_address); + pci_release_selected_regions(pdev, +- pci_select_bars(pdev, IORESOURCE_MEM)); ++ pci_select_bars(pdev, IORESOURCE_MEM)); + + free_netdev(netdev); + +@@ -6318,7 +6903,8 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_COPPER), board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_FIBER), board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER), board_82571 }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP), board_82571 }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP), ++ board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_FIBER), board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES), board_82571 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL), board_82571 }, +@@ -6382,27 +6968,34 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_LM), board_pch2lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_V), board_pch2lan }, + +- { } /* terminate list */ ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_LM), board_pch_lpt }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_V), board_pch_lpt }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPTLP_I218_LM), board_pch_lpt }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPTLP_I218_V), board_pch_lpt }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_LM2), board_pch_lpt }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_V2), board_pch_lpt }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_LM3), board_pch_lpt }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_V3), board_pch_lpt }, ++ ++ { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */ + }; + MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); + +-#ifdef CONFIG_PM + static const struct dev_pm_ops e1000_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume) +- SET_RUNTIME_PM_OPS(e1000_runtime_suspend, +- e1000_runtime_resume, e1000_idle) ++ SET_RUNTIME_PM_OPS(e1000_runtime_suspend, e1000_runtime_resume, ++ e1000_idle) + }; +-#endif + + /* PCI Device API Driver */ + static struct pci_driver e1000_driver = { + .name = e1000e_driver_name, + .id_table = e1000_pci_tbl, + .probe = e1000_probe, +- .remove = __devexit_p(e1000_remove), +-#ifdef CONFIG_PM +- .driver.pm = &e1000_pm_ops, +-#endif ++ .remove = e1000_remove, ++ .driver = { ++ .pm = &e1000_pm_ops, ++ }, + .shutdown = e1000_shutdown, + .err_handler = &e1000_err_handler + }; +@@ -6418,7 +7011,7 @@ static int __init e1000_init_module(void) + int ret; + pr_info("Intel(R) PRO/1000 Network Driver - %s\n", + e1000e_driver_version); +- pr_info("Copyright(c) 1999 - 2011 Intel Corporation.\n"); ++ pr_info("Copyright(c) 1999 - 2013 Intel Corporation.\n"); + ret = pci_register_driver(&e1000_driver); + + return ret; +@@ -6437,10 +7030,9 @@ static void __exit e1000_exit_module(void) + } + module_exit(e1000_exit_module); + +- + MODULE_AUTHOR("Intel Corporation, "); + MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver"); + MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_VERSION); + +-/* e1000_main.c */ ++/* netdev.c */ +diff --git a/drivers/net/ethernet/intel/e1000e/nvm.c b/drivers/net/ethernet/intel/e1000e/nvm.c +new file mode 100644 +index 0000000..d70a039 +--- /dev/null ++++ b/drivers/net/ethernet/intel/e1000e/nvm.c +@@ -0,0 +1,637 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#include "e1000.h" ++ ++/** ++ * e1000_raise_eec_clk - Raise EEPROM clock ++ * @hw: pointer to the HW structure ++ * @eecd: pointer to the EEPROM ++ * ++ * Enable/Raise the EEPROM clock bit. ++ **/ ++static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) ++{ ++ *eecd = *eecd | E1000_EECD_SK; ++ ew32(EECD, *eecd); ++ e1e_flush(); ++ udelay(hw->nvm.delay_usec); ++} ++ ++/** ++ * e1000_lower_eec_clk - Lower EEPROM clock ++ * @hw: pointer to the HW structure ++ * @eecd: pointer to the EEPROM ++ * ++ * Clear/Lower the EEPROM clock bit. ++ **/ ++static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) ++{ ++ *eecd = *eecd & ~E1000_EECD_SK; ++ ew32(EECD, *eecd); ++ e1e_flush(); ++ udelay(hw->nvm.delay_usec); ++} ++ ++/** ++ * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM ++ * @hw: pointer to the HW structure ++ * @data: data to send to the EEPROM ++ * @count: number of bits to shift out ++ * ++ * We need to shift 'count' bits out to the EEPROM. So, the value in the ++ * "data" parameter will be shifted out to the EEPROM one bit at a time. ++ * In order to do this, "data" must be broken down into bits. ++ **/ ++static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) ++{ ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ u32 eecd = er32(EECD); ++ u32 mask; ++ ++ mask = 0x01 << (count - 1); ++ if (nvm->type == e1000_nvm_eeprom_spi) ++ eecd |= E1000_EECD_DO; ++ ++ do { ++ eecd &= ~E1000_EECD_DI; ++ ++ if (data & mask) ++ eecd |= E1000_EECD_DI; ++ ++ ew32(EECD, eecd); ++ e1e_flush(); ++ ++ udelay(nvm->delay_usec); ++ ++ e1000_raise_eec_clk(hw, &eecd); ++ e1000_lower_eec_clk(hw, &eecd); ++ ++ mask >>= 1; ++ } while (mask); ++ ++ eecd &= ~E1000_EECD_DI; ++ ew32(EECD, eecd); ++} ++ ++/** ++ * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM ++ * @hw: pointer to the HW structure ++ * @count: number of bits to shift in ++ * ++ * In order to read a register from the EEPROM, we need to shift 'count' bits ++ * in from the EEPROM. Bits are "shifted in" by raising the clock input to ++ * the EEPROM (setting the SK bit), and then reading the value of the data out ++ * "DO" bit. During this "shifting in" process the data in "DI" bit should ++ * always be clear. ++ **/ ++static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) ++{ ++ u32 eecd; ++ u32 i; ++ u16 data; ++ ++ eecd = er32(EECD); ++ eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); ++ data = 0; ++ ++ for (i = 0; i < count; i++) { ++ data <<= 1; ++ e1000_raise_eec_clk(hw, &eecd); ++ ++ eecd = er32(EECD); ++ ++ eecd &= ~E1000_EECD_DI; ++ if (eecd & E1000_EECD_DO) ++ data |= 1; ++ ++ e1000_lower_eec_clk(hw, &eecd); ++ } ++ ++ return data; ++} ++ ++/** ++ * e1000e_poll_eerd_eewr_done - Poll for EEPROM read/write completion ++ * @hw: pointer to the HW structure ++ * @ee_reg: EEPROM flag for polling ++ * ++ * Polls the EEPROM status bit for either read or write completion based ++ * upon the value of 'ee_reg'. ++ **/ ++s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) ++{ ++ u32 attempts = 100000; ++ u32 i, reg = 0; ++ ++ for (i = 0; i < attempts; i++) { ++ if (ee_reg == E1000_NVM_POLL_READ) ++ reg = er32(EERD); ++ else ++ reg = er32(EEWR); ++ ++ if (reg & E1000_NVM_RW_REG_DONE) ++ return 0; ++ ++ udelay(5); ++ } ++ ++ return -E1000_ERR_NVM; ++} ++ ++/** ++ * e1000e_acquire_nvm - Generic request for access to EEPROM ++ * @hw: pointer to the HW structure ++ * ++ * Set the EEPROM access request bit and wait for EEPROM access grant bit. ++ * Return successful if access grant bit set, else clear the request for ++ * EEPROM access and return -E1000_ERR_NVM (-1). ++ **/ ++s32 e1000e_acquire_nvm(struct e1000_hw *hw) ++{ ++ u32 eecd = er32(EECD); ++ s32 timeout = E1000_NVM_GRANT_ATTEMPTS; ++ ++ ew32(EECD, eecd | E1000_EECD_REQ); ++ eecd = er32(EECD); ++ ++ while (timeout) { ++ if (eecd & E1000_EECD_GNT) ++ break; ++ udelay(5); ++ eecd = er32(EECD); ++ timeout--; ++ } ++ ++ if (!timeout) { ++ eecd &= ~E1000_EECD_REQ; ++ ew32(EECD, eecd); ++ e_dbg("Could not acquire NVM grant\n"); ++ return -E1000_ERR_NVM; ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000_standby_nvm - Return EEPROM to standby state ++ * @hw: pointer to the HW structure ++ * ++ * Return the EEPROM to a standby state. ++ **/ ++static void e1000_standby_nvm(struct e1000_hw *hw) ++{ ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ u32 eecd = er32(EECD); ++ ++ if (nvm->type == e1000_nvm_eeprom_spi) { ++ /* Toggle CS to flush commands */ ++ eecd |= E1000_EECD_CS; ++ ew32(EECD, eecd); ++ e1e_flush(); ++ udelay(nvm->delay_usec); ++ eecd &= ~E1000_EECD_CS; ++ ew32(EECD, eecd); ++ e1e_flush(); ++ udelay(nvm->delay_usec); ++ } ++} ++ ++/** ++ * e1000_stop_nvm - Terminate EEPROM command ++ * @hw: pointer to the HW structure ++ * ++ * Terminates the current command by inverting the EEPROM's chip select pin. ++ **/ ++static void e1000_stop_nvm(struct e1000_hw *hw) ++{ ++ u32 eecd; ++ ++ eecd = er32(EECD); ++ if (hw->nvm.type == e1000_nvm_eeprom_spi) { ++ /* Pull CS high */ ++ eecd |= E1000_EECD_CS; ++ e1000_lower_eec_clk(hw, &eecd); ++ } ++} ++ ++/** ++ * e1000e_release_nvm - Release exclusive access to EEPROM ++ * @hw: pointer to the HW structure ++ * ++ * Stop any current commands to the EEPROM and clear the EEPROM request bit. ++ **/ ++void e1000e_release_nvm(struct e1000_hw *hw) ++{ ++ u32 eecd; ++ ++ e1000_stop_nvm(hw); ++ ++ eecd = er32(EECD); ++ eecd &= ~E1000_EECD_REQ; ++ ew32(EECD, eecd); ++} ++ ++/** ++ * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write ++ * @hw: pointer to the HW structure ++ * ++ * Setups the EEPROM for reading and writing. ++ **/ ++static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) ++{ ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ u32 eecd = er32(EECD); ++ u8 spi_stat_reg; ++ ++ if (nvm->type == e1000_nvm_eeprom_spi) { ++ u16 timeout = NVM_MAX_RETRY_SPI; ++ ++ /* Clear SK and CS */ ++ eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); ++ ew32(EECD, eecd); ++ e1e_flush(); ++ udelay(1); ++ ++ /* Read "Status Register" repeatedly until the LSB is cleared. ++ * The EEPROM will signal that the command has been completed ++ * by clearing bit 0 of the internal status register. If it's ++ * not cleared within 'timeout', then error out. ++ */ ++ while (timeout) { ++ e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, ++ hw->nvm.opcode_bits); ++ spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); ++ if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) ++ break; ++ ++ udelay(5); ++ e1000_standby_nvm(hw); ++ timeout--; ++ } ++ ++ if (!timeout) { ++ e_dbg("SPI NVM Status error\n"); ++ return -E1000_ERR_NVM; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_read_nvm_eerd - Reads EEPROM using EERD register ++ * @hw: pointer to the HW structure ++ * @offset: offset of word in the EEPROM to read ++ * @words: number of words to read ++ * @data: word read from the EEPROM ++ * ++ * Reads a 16 bit word from the EEPROM using the EERD register. ++ **/ ++s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) ++{ ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ u32 i, eerd = 0; ++ s32 ret_val = 0; ++ ++ /* A check for invalid values: offset too large, too many words, ++ * too many words for the offset, and not enough words. ++ */ ++ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || ++ (words == 0)) { ++ e_dbg("nvm parameter(s) out of bounds\n"); ++ return -E1000_ERR_NVM; ++ } ++ ++ for (i = 0; i < words; i++) { ++ eerd = ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) + ++ E1000_NVM_RW_REG_START; ++ ++ ew32(EERD, eerd); ++ ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); ++ if (ret_val) ++ break; ++ ++ data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA); ++ } ++ ++ return ret_val; ++} ++ ++/** ++ * e1000e_write_nvm_spi - Write to EEPROM using SPI ++ * @hw: pointer to the HW structure ++ * @offset: offset within the EEPROM to be written to ++ * @words: number of words to write ++ * @data: 16 bit word(s) to be written to the EEPROM ++ * ++ * Writes data to EEPROM at offset using SPI interface. ++ * ++ * If e1000e_update_nvm_checksum is not called after this function , the ++ * EEPROM will most likely contain an invalid checksum. ++ **/ ++s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) ++{ ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ s32 ret_val = -E1000_ERR_NVM; ++ u16 widx = 0; ++ ++ /* A check for invalid values: offset too large, too many words, ++ * and not enough words. ++ */ ++ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || ++ (words == 0)) { ++ e_dbg("nvm parameter(s) out of bounds\n"); ++ return -E1000_ERR_NVM; ++ } ++ ++ while (widx < words) { ++ u8 write_opcode = NVM_WRITE_OPCODE_SPI; ++ ++ ret_val = nvm->ops.acquire(hw); ++ if (ret_val) ++ return ret_val; ++ ++ ret_val = e1000_ready_nvm_eeprom(hw); ++ if (ret_val) { ++ nvm->ops.release(hw); ++ return ret_val; ++ } ++ ++ e1000_standby_nvm(hw); ++ ++ /* Send the WRITE ENABLE command (8 bit opcode) */ ++ e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, ++ nvm->opcode_bits); ++ ++ e1000_standby_nvm(hw); ++ ++ /* Some SPI eeproms use the 8th address bit embedded in the ++ * opcode ++ */ ++ if ((nvm->address_bits == 8) && (offset >= 128)) ++ write_opcode |= NVM_A8_OPCODE_SPI; ++ ++ /* Send the Write command (8-bit opcode + addr) */ ++ e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); ++ e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), ++ nvm->address_bits); ++ ++ /* Loop to allow for up to whole page write of eeprom */ ++ while (widx < words) { ++ u16 word_out = data[widx]; ++ word_out = (word_out >> 8) | (word_out << 8); ++ e1000_shift_out_eec_bits(hw, word_out, 16); ++ widx++; ++ ++ if ((((offset + widx) * 2) % nvm->page_size) == 0) { ++ e1000_standby_nvm(hw); ++ break; ++ } ++ } ++ usleep_range(10000, 20000); ++ nvm->ops.release(hw); ++ } ++ ++ return ret_val; ++} ++ ++/** ++ * e1000_read_pba_string_generic - Read device part number ++ * @hw: pointer to the HW structure ++ * @pba_num: pointer to device part number ++ * @pba_num_size: size of part number buffer ++ * ++ * Reads the product board assembly (PBA) number from the EEPROM and stores ++ * the value in pba_num. ++ **/ ++s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, ++ u32 pba_num_size) ++{ ++ s32 ret_val; ++ u16 nvm_data; ++ u16 pba_ptr; ++ u16 offset; ++ u16 length; ++ ++ if (pba_num == NULL) { ++ e_dbg("PBA string buffer was null\n"); ++ return -E1000_ERR_INVALID_ARGUMENT; ++ } ++ ++ ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); ++ if (ret_val) { ++ e_dbg("NVM Read Error\n"); ++ return ret_val; ++ } ++ ++ ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr); ++ if (ret_val) { ++ e_dbg("NVM Read Error\n"); ++ return ret_val; ++ } ++ ++ /* if nvm_data is not ptr guard the PBA must be in legacy format which ++ * means pba_ptr is actually our second data word for the PBA number ++ * and we can decode it into an ascii string ++ */ ++ if (nvm_data != NVM_PBA_PTR_GUARD) { ++ e_dbg("NVM PBA number is not stored as string\n"); ++ ++ /* make sure callers buffer is big enough to store the PBA */ ++ if (pba_num_size < E1000_PBANUM_LENGTH) { ++ e_dbg("PBA string buffer too small\n"); ++ return E1000_ERR_NO_SPACE; ++ } ++ ++ /* extract hex string from data and pba_ptr */ ++ pba_num[0] = (nvm_data >> 12) & 0xF; ++ pba_num[1] = (nvm_data >> 8) & 0xF; ++ pba_num[2] = (nvm_data >> 4) & 0xF; ++ pba_num[3] = nvm_data & 0xF; ++ pba_num[4] = (pba_ptr >> 12) & 0xF; ++ pba_num[5] = (pba_ptr >> 8) & 0xF; ++ pba_num[6] = '-'; ++ pba_num[7] = 0; ++ pba_num[8] = (pba_ptr >> 4) & 0xF; ++ pba_num[9] = pba_ptr & 0xF; ++ ++ /* put a null character on the end of our string */ ++ pba_num[10] = '\0'; ++ ++ /* switch all the data but the '-' to hex char */ ++ for (offset = 0; offset < 10; offset++) { ++ if (pba_num[offset] < 0xA) ++ pba_num[offset] += '0'; ++ else if (pba_num[offset] < 0x10) ++ pba_num[offset] += 'A' - 0xA; ++ } ++ ++ return 0; ++ } ++ ++ ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length); ++ if (ret_val) { ++ e_dbg("NVM Read Error\n"); ++ return ret_val; ++ } ++ ++ if (length == 0xFFFF || length == 0) { ++ e_dbg("NVM PBA number section invalid length\n"); ++ return -E1000_ERR_NVM_PBA_SECTION; ++ } ++ /* check if pba_num buffer is big enough */ ++ if (pba_num_size < (((u32)length * 2) - 1)) { ++ e_dbg("PBA string buffer too small\n"); ++ return -E1000_ERR_NO_SPACE; ++ } ++ ++ /* trim pba length from start of string */ ++ pba_ptr++; ++ length--; ++ ++ for (offset = 0; offset < length; offset++) { ++ ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data); ++ if (ret_val) { ++ e_dbg("NVM Read Error\n"); ++ return ret_val; ++ } ++ pba_num[offset * 2] = (u8)(nvm_data >> 8); ++ pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF); ++ } ++ pba_num[offset * 2] = '\0'; ++ ++ return 0; ++} ++ ++/** ++ * e1000_read_mac_addr_generic - Read device MAC address ++ * @hw: pointer to the HW structure ++ * ++ * Reads the device MAC address from the EEPROM and stores the value. ++ * Since devices with two ports use the same EEPROM, we increment the ++ * last bit in the MAC address for the second port. ++ **/ ++s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) ++{ ++ u32 rar_high; ++ u32 rar_low; ++ u16 i; ++ ++ rar_high = er32(RAH(0)); ++ rar_low = er32(RAL(0)); ++ ++ for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) ++ hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8)); ++ ++ for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) ++ hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8)); ++ ++ for (i = 0; i < ETH_ALEN; i++) ++ hw->mac.addr[i] = hw->mac.perm_addr[i]; ++ ++ return 0; ++} ++ ++/** ++ * e1000e_validate_nvm_checksum_generic - Validate EEPROM checksum ++ * @hw: pointer to the HW structure ++ * ++ * Calculates the EEPROM checksum by reading/adding each word of the EEPROM ++ * and then verifies that the sum of the EEPROM is equal to 0xBABA. ++ **/ ++s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw) ++{ ++ s32 ret_val; ++ u16 checksum = 0; ++ u16 i, nvm_data; ++ ++ for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { ++ ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); ++ if (ret_val) { ++ e_dbg("NVM Read Error\n"); ++ return ret_val; ++ } ++ checksum += nvm_data; ++ } ++ ++ if (checksum != (u16)NVM_SUM) { ++ e_dbg("NVM Checksum Invalid\n"); ++ return -E1000_ERR_NVM; ++ } ++ ++ return 0; ++} ++ ++/** ++ * e1000e_update_nvm_checksum_generic - Update EEPROM checksum ++ * @hw: pointer to the HW structure ++ * ++ * Updates the EEPROM checksum by reading/adding each word of the EEPROM ++ * up to the checksum. Then calculates the EEPROM checksum and writes the ++ * value to the EEPROM. ++ **/ ++s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw) ++{ ++ s32 ret_val; ++ u16 checksum = 0; ++ u16 i, nvm_data; ++ ++ for (i = 0; i < NVM_CHECKSUM_REG; i++) { ++ ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); ++ if (ret_val) { ++ e_dbg("NVM Read Error while updating checksum.\n"); ++ return ret_val; ++ } ++ checksum += nvm_data; ++ } ++ checksum = (u16)NVM_SUM - checksum; ++ ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum); ++ if (ret_val) ++ e_dbg("NVM Write Error while updating checksum.\n"); ++ ++ return ret_val; ++} ++ ++/** ++ * e1000e_reload_nvm_generic - Reloads EEPROM ++ * @hw: pointer to the HW structure ++ * ++ * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the ++ * extended control register. ++ **/ ++void e1000e_reload_nvm_generic(struct e1000_hw *hw) ++{ ++ u32 ctrl_ext; ++ ++ usleep_range(10, 20); ++ ctrl_ext = er32(CTRL_EXT); ++ ctrl_ext |= E1000_CTRL_EXT_EE_RST; ++ ew32(CTRL_EXT, ctrl_ext); ++ e1e_flush(); ++} +diff --git a/drivers/net/ethernet/intel/e1000e/nvm.h b/drivers/net/ethernet/intel/e1000e/nvm.h +new file mode 100644 +index 0000000..45fc695 +--- /dev/null ++++ b/drivers/net/ethernet/intel/e1000e/nvm.h +@@ -0,0 +1,47 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#ifndef _E1000E_NVM_H_ ++#define _E1000E_NVM_H_ ++ ++s32 e1000e_acquire_nvm(struct e1000_hw *hw); ++ ++s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); ++s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); ++s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, ++ u32 pba_num_size); ++s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); ++s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data); ++s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw); ++s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); ++s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw); ++void e1000e_release_nvm(struct e1000_hw *hw); ++ ++#define E1000_STM_OPCODE 0xDB00 ++ ++#endif +diff --git a/drivers/net/ethernet/intel/e1000e/param.c b/drivers/net/ethernet/intel/e1000e/param.c +index 20e93b0..fc23589 100644 +--- a/drivers/net/ethernet/intel/e1000e/param.c ++++ b/drivers/net/ethernet/intel/e1000e/param.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel PRO/1000 Linux driver +- Copyright(c) 1999 - 2011 Intel Corporation. ++ Copyright(c) 1999 - 2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -32,11 +32,9 @@ + + #include "e1000.h" + +-/* +- * This is the only thing that needs to be changed to adjust the ++/* This is the only thing that needs to be changed to adjust the + * maximum number of ports that the driver can manage. + */ +- + #define E1000_MAX_NIC 32 + + #define OPTION_UNSET -1 +@@ -47,24 +45,20 @@ + unsigned int copybreak = COPYBREAK_DEFAULT; + module_param(copybreak, uint, 0644); + MODULE_PARM_DESC(copybreak, +- "Maximum size of packet that is copied to a new buffer on receive"); ++ "Maximum size of packet that is copied to a new buffer on receive"); + +-/* +- * All parameters are treated the same, as an integer array of values. ++/* All parameters are treated the same, as an integer array of values. + * This macro just reduces the need to repeat the same declaration code + * over and over (plus this helps to avoid typo bugs). + */ +- + #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } + #define E1000_PARAM(X, desc) \ +- static int __devinitdata X[E1000_MAX_NIC+1] \ +- = E1000_PARAM_INIT; \ ++ static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ + static unsigned int num_##X; \ + module_param_array_named(X, X, int, &num_##X, 0); \ + MODULE_PARM_DESC(X, desc); + +-/* +- * Transmit Interrupt Delay in units of 1.024 microseconds ++/* Transmit Interrupt Delay in units of 1.024 microseconds + * Tx interrupt delay needs to typically be set to something non-zero + * + * Valid Range: 0-65535 +@@ -74,8 +68,7 @@ E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay"); + #define MAX_TXDELAY 0xFFFF + #define MIN_TXDELAY 0 + +-/* +- * Transmit Absolute Interrupt Delay in units of 1.024 microseconds ++/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds + * + * Valid Range: 0-65535 + */ +@@ -84,8 +77,7 @@ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); + #define MAX_TXABSDELAY 0xFFFF + #define MIN_TXABSDELAY 0 + +-/* +- * Receive Interrupt Delay in units of 1.024 microseconds ++/* Receive Interrupt Delay in units of 1.024 microseconds + * hardware will likely hang if you set this to anything but zero. + * + * Valid Range: 0-65535 +@@ -94,8 +86,7 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); + #define MAX_RXDELAY 0xFFFF + #define MIN_RXDELAY 0 + +-/* +- * Receive Absolute Interrupt Delay in units of 1.024 microseconds ++/* Receive Absolute Interrupt Delay in units of 1.024 microseconds + * + * Valid Range: 0-65535 + */ +@@ -103,10 +94,9 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); + #define MAX_RXABSDELAY 0xFFFF + #define MIN_RXABSDELAY 0 + +-/* +- * Interrupt Throttle Rate (interrupts/sec) ++/* Interrupt Throttle Rate (interrupts/sec) + * +- * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative) ++ * Valid Range: 100-100000 or one of: 0=off, 1=dynamic, 3=dynamic conservative + */ + E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); + #define DEFAULT_ITR 3 +@@ -115,16 +105,23 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); + + /* IntMode (Interrupt Mode) + * +- * Valid Range: 0 - 2 ++ * Valid Range: varies depending on kernel configuration & hardware support ++ * ++ * legacy=0, MSI=1, MSI-X=2 + * +- * Default Value: 2 (MSI-X) ++ * When MSI/MSI-X support is enabled in kernel- ++ * Default Value: 2 (MSI-X) when supported by hardware, 1 (MSI) otherwise ++ * When MSI/MSI-X support is not enabled in kernel- ++ * Default Value: 0 (legacy) ++ * ++ * When a mode is specified that is not allowed/supported, it will be ++ * demoted to the most advanced interrupt mode available. + */ + E1000_PARAM(IntMode, "Interrupt Mode"); + #define MAX_INTMODE 2 + #define MIN_INTMODE 0 + +-/* +- * Enable Smart Power Down of the PHY ++/* Enable Smart Power Down of the PHY + * + * Valid Range: 0, 1 + * +@@ -132,8 +129,7 @@ E1000_PARAM(IntMode, "Interrupt Mode"); + */ + E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down"); + +-/* +- * Enable Kumeran Lock Loss workaround ++/* Enable Kumeran Lock Loss workaround + * + * Valid Range: 0, 1 + * +@@ -141,24 +137,23 @@ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down"); + */ + E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); + +-/* +- * Write Protect NVM ++/* Write Protect NVM + * + * Valid Range: 0, 1 + * + * Default Value: 1 (enabled) + */ +-E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]"); ++E1000_PARAM(WriteProtectNVM, ++ "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]"); + +-/* +- * Enable CRC Stripping ++/* Enable CRC Stripping + * + * Valid Range: 0, 1 + * + * Default Value: 1 (enabled) + */ +-E1000_PARAM(CrcStripping, "Enable CRC Stripping, disable if your BMC needs " \ +- "the CRC"); ++E1000_PARAM(CrcStripping, ++ "Enable CRC Stripping, disable if your BMC needs the CRC"); + + struct e1000_option { + enum { enable_option, range_option, list_option } type; +@@ -166,20 +161,25 @@ struct e1000_option { + const char *err; + int def; + union { +- struct { /* range_option info */ ++ /* range_option info */ ++ struct { + int min; + int max; + } r; +- struct { /* list_option info */ ++ /* list_option info */ ++ struct { + int nr; +- struct e1000_opt_list { int i; char *str; } *p; ++ struct e1000_opt_list { ++ int i; ++ char *str; ++ } *p; + } l; + } arg; + }; + +-static int __devinit e1000_validate_option(unsigned int *value, +- const struct e1000_option *opt, +- struct e1000_adapter *adapter) ++static int e1000_validate_option(unsigned int *value, ++ const struct e1000_option *opt, ++ struct e1000_adapter *adapter) + { + if (*value == OPTION_UNSET) { + *value = opt->def; +@@ -190,16 +190,19 @@ static int __devinit e1000_validate_option(unsigned int *value, + case enable_option: + switch (*value) { + case OPTION_ENABLED: +- e_info("%s Enabled\n", opt->name); ++ dev_info(&adapter->pdev->dev, "%s Enabled\n", ++ opt->name); + return 0; + case OPTION_DISABLED: +- e_info("%s Disabled\n", opt->name); ++ dev_info(&adapter->pdev->dev, "%s Disabled\n", ++ opt->name); + return 0; + } + break; + case range_option: + if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { +- e_info("%s set to %i\n", opt->name, *value); ++ dev_info(&adapter->pdev->dev, "%s set to %i\n", ++ opt->name, *value); + return 0; + } + break; +@@ -211,7 +214,8 @@ static int __devinit e1000_validate_option(unsigned int *value, + ent = &opt->arg.l.p[i]; + if (*value == ent->i) { + if (ent->str[0] != '\0') +- e_info("%s\n", ent->str); ++ dev_info(&adapter->pdev->dev, "%s\n", ++ ent->str); + return 0; + } + } +@@ -221,8 +225,8 @@ static int __devinit e1000_validate_option(unsigned int *value, + BUG(); + } + +- e_info("Invalid %s value specified (%i) %s\n", opt->name, *value, +- opt->err); ++ dev_info(&adapter->pdev->dev, "Invalid %s value specified (%i) %s\n", ++ opt->name, *value, opt->err); + *value = opt->def; + return -1; + } +@@ -236,17 +240,20 @@ static int __devinit e1000_validate_option(unsigned int *value, + * value exists, a default value is used. The final value is stored + * in a variable in the adapter structure. + **/ +-void __devinit e1000e_check_options(struct e1000_adapter *adapter) ++void e1000e_check_options(struct e1000_adapter *adapter) + { + struct e1000_hw *hw = &adapter->hw; + int bd = adapter->bd_number; + + if (bd >= E1000_MAX_NIC) { +- e_notice("Warning: no configuration for board #%i\n", bd); +- e_notice("Using defaults for all values\n"); ++ dev_notice(&adapter->pdev->dev, ++ "Warning: no configuration for board #%i\n", bd); ++ dev_notice(&adapter->pdev->dev, ++ "Using defaults for all values\n"); + } + +- { /* Transmit Interrupt Delay */ ++ /* Transmit Interrupt Delay */ ++ { + static const struct e1000_option opt = { + .type = range_option, + .name = "Transmit Interrupt Delay", +@@ -265,7 +272,8 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) + adapter->tx_int_delay = opt.def; + } + } +- { /* Transmit Absolute Interrupt Delay */ ++ /* Transmit Absolute Interrupt Delay */ ++ { + static const struct e1000_option opt = { + .type = range_option, + .name = "Transmit Absolute Interrupt Delay", +@@ -284,7 +292,8 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) + adapter->tx_abs_int_delay = opt.def; + } + } +- { /* Receive Interrupt Delay */ ++ /* Receive Interrupt Delay */ ++ { + static struct e1000_option opt = { + .type = range_option, + .name = "Receive Interrupt Delay", +@@ -303,7 +312,8 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) + adapter->rx_int_delay = opt.def; + } + } +- { /* Receive Absolute Interrupt Delay */ ++ /* Receive Absolute Interrupt Delay */ ++ { + static const struct e1000_option opt = { + .type = range_option, + .name = "Receive Absolute Interrupt Delay", +@@ -322,7 +332,8 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) + adapter->rx_abs_int_delay = opt.def; + } + } +- { /* Interrupt Throttling Rate */ ++ /* Interrupt Throttling Rate */ ++ { + static const struct e1000_option opt = { + .type = range_option, + .name = "Interrupt Throttling Rate (ints/sec)", +@@ -335,65 +346,95 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) + + if (num_InterruptThrottleRate > bd) { + adapter->itr = InterruptThrottleRate[bd]; +- switch (adapter->itr) { +- case 0: +- e_info("%s turned off\n", opt.name); +- break; +- case 1: +- e_info("%s set to dynamic mode\n", opt.name); +- adapter->itr_setting = adapter->itr; +- adapter->itr = 20000; +- break; +- case 3: +- e_info("%s set to dynamic conservative mode\n", +- opt.name); +- adapter->itr_setting = adapter->itr; +- adapter->itr = 20000; +- break; +- case 4: +- e_info("%s set to simplified (2000-8000 ints) " +- "mode\n", opt.name); +- adapter->itr_setting = 4; +- break; +- default: +- /* +- * Save the setting, because the dynamic bits +- * change itr. +- */ +- if (e1000_validate_option(&adapter->itr, &opt, +- adapter) && +- (adapter->itr == 3)) { +- /* +- * In case of invalid user value, +- * default to conservative mode. +- */ +- adapter->itr_setting = adapter->itr; +- adapter->itr = 20000; +- } else { +- /* +- * Clear the lower two bits because +- * they are used as control. +- */ +- adapter->itr_setting = +- adapter->itr & ~3; +- } +- break; +- } ++ ++ /* Make sure a message is printed for non-special ++ * values. And in case of an invalid option, display ++ * warning, use default and go through itr/itr_setting ++ * adjustment logic below ++ */ ++ if ((adapter->itr > 4) && ++ e1000_validate_option(&adapter->itr, &opt, adapter)) ++ adapter->itr = opt.def; + } else { +- adapter->itr_setting = opt.def; ++ /* If no option specified, use default value and go ++ * through the logic below to adjust itr/itr_setting ++ */ ++ adapter->itr = opt.def; ++ ++ /* Make sure a message is printed for non-special ++ * default values ++ */ ++ if (adapter->itr > 4) ++ dev_info(&adapter->pdev->dev, ++ "%s set to default %d\n", opt.name, ++ adapter->itr); ++ } ++ ++ adapter->itr_setting = adapter->itr; ++ switch (adapter->itr) { ++ case 0: ++ dev_info(&adapter->pdev->dev, "%s turned off\n", ++ opt.name); ++ break; ++ case 1: ++ dev_info(&adapter->pdev->dev, ++ "%s set to dynamic mode\n", opt.name); ++ adapter->itr = 20000; ++ break; ++ case 3: ++ dev_info(&adapter->pdev->dev, ++ "%s set to dynamic conservative mode\n", ++ opt.name); + adapter->itr = 20000; ++ break; ++ case 4: ++ dev_info(&adapter->pdev->dev, ++ "%s set to simplified (2000-8000 ints) mode\n", ++ opt.name); ++ break; ++ default: ++ /* Save the setting, because the dynamic bits ++ * change itr. ++ * ++ * Clear the lower two bits because ++ * they are used as control. ++ */ ++ adapter->itr_setting &= ~3; ++ break; + } + } +- { /* Interrupt Mode */ ++ /* Interrupt Mode */ ++ { + static struct e1000_option opt = { + .type = range_option, + .name = "Interrupt Mode", +- .err = "defaulting to 2 (MSI-X)", +- .def = E1000E_INT_MODE_MSIX, +- .arg = { .r = { .min = MIN_INTMODE, +- .max = MAX_INTMODE } } ++#ifndef CONFIG_PCI_MSI ++ .err = "defaulting to 0 (legacy)", ++ .def = E1000E_INT_MODE_LEGACY, ++ .arg = { .r = { .min = 0, ++ .max = 0 } } ++#endif + }; + ++#ifdef CONFIG_PCI_MSI ++ if (adapter->flags & FLAG_HAS_MSIX) { ++ opt.err = kstrdup("defaulting to 2 (MSI-X)", ++ GFP_KERNEL); ++ opt.def = E1000E_INT_MODE_MSIX; ++ opt.arg.r.max = E1000E_INT_MODE_MSIX; ++ } else { ++ opt.err = kstrdup("defaulting to 1 (MSI)", GFP_KERNEL); ++ opt.def = E1000E_INT_MODE_MSI; ++ opt.arg.r.max = E1000E_INT_MODE_MSI; ++ } ++ ++ if (!opt.err) { ++ dev_err(&adapter->pdev->dev, ++ "Failed to allocate memory\n"); ++ return; ++ } ++#endif ++ + if (num_IntMode > bd) { + unsigned int int_mode = IntMode[bd]; + e1000_validate_option(&int_mode, &opt, adapter); +@@ -401,8 +442,13 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) + } else { + adapter->int_mode = opt.def; + } ++ ++#ifdef CONFIG_PCI_MSI ++ kfree(opt.err); ++#endif + } +- { /* Smart Power Down */ ++ /* Smart Power Down */ ++ { + static const struct e1000_option opt = { + .type = enable_option, + .name = "PHY Smart Power Down", +@@ -413,12 +459,12 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) + if (num_SmartPowerDownEnable > bd) { + unsigned int spd = SmartPowerDownEnable[bd]; + e1000_validate_option(&spd, &opt, adapter); +- if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) +- && spd) ++ if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && spd) + adapter->flags |= FLAG_SMART_POWER_DOWN; + } + } +- { /* CRC Stripping */ ++ /* CRC Stripping */ ++ { + static const struct e1000_option opt = { + .type = enable_option, + .name = "CRC Stripping", +@@ -435,27 +481,28 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) + adapter->flags2 |= FLAG2_CRC_STRIPPING; + } + } +- { /* Kumeran Lock Loss Workaround */ ++ /* Kumeran Lock Loss Workaround */ ++ { + static const struct e1000_option opt = { + .type = enable_option, + .name = "Kumeran Lock Loss Workaround", + .err = "defaulting to Enabled", + .def = OPTION_ENABLED + }; ++ bool enabled = opt.def; + + if (num_KumeranLockLoss > bd) { + unsigned int kmrn_lock_loss = KumeranLockLoss[bd]; + e1000_validate_option(&kmrn_lock_loss, &opt, adapter); +- if (hw->mac.type == e1000_ich8lan) +- e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, +- kmrn_lock_loss); +- } else { +- if (hw->mac.type == e1000_ich8lan) +- e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, +- opt.def); ++ enabled = kmrn_lock_loss; + } ++ ++ if (hw->mac.type == e1000_ich8lan) ++ e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, ++ enabled); + } +- { /* Write-protect NVM */ ++ /* Write-protect NVM */ ++ { + static const struct e1000_option opt = { + .type = enable_option, + .name = "Write-protect NVM", +@@ -465,7 +512,8 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) + + if (adapter->flags & FLAG_IS_ICH) { + if (num_WriteProtectNVM > bd) { +- unsigned int write_protect_nvm = WriteProtectNVM[bd]; ++ unsigned int write_protect_nvm = ++ WriteProtectNVM[bd]; + e1000_validate_option(&write_protect_nvm, &opt, + adapter); + if (write_protect_nvm) +diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c +index 8666476..20e71f4 100644 +--- a/drivers/net/ethernet/intel/e1000e/phy.c ++++ b/drivers/net/ethernet/intel/e1000e/phy.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel PRO/1000 Linux driver +- Copyright(c) 1999 - 2011 Intel Corporation. ++ Copyright(c) 1999 - 2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -26,24 +26,20 @@ + + *******************************************************************************/ + +-#include +- + #include "e1000.h" + +-static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw); +-static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw); +-static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active); + static s32 e1000_wait_autoneg(struct e1000_hw *hw); +-static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg); + static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, + u16 *data, bool read, bool page_set); + static u32 e1000_get_phy_addr_for_hv_page(u32 page); + static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, +- u16 *data, bool read); ++ u16 *data, bool read); + + /* Cable length tables */ + static const u16 e1000_m88_cable_length_table[] = { +- 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; ++ 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED ++}; ++ + #define M88E1000_CABLE_LENGTH_TABLE_SIZE \ + ARRAY_SIZE(e1000_m88_cable_length_table) + +@@ -55,51 +51,12 @@ static const u16 e1000_igp_2_cable_length_table[] = { + 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82, + 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95, + 100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121, +- 124}; ++ 124 ++}; ++ + #define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ + ARRAY_SIZE(e1000_igp_2_cable_length_table) + +-#define BM_PHY_REG_PAGE(offset) \ +- ((u16)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF)) +-#define BM_PHY_REG_NUM(offset) \ +- ((u16)(((offset) & MAX_PHY_REG_ADDRESS) |\ +- (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\ +- ~MAX_PHY_REG_ADDRESS))) +- +-#define HV_INTC_FC_PAGE_START 768 +-#define I82578_ADDR_REG 29 +-#define I82577_ADDR_REG 16 +-#define I82577_CFG_REG 22 +-#define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15) +-#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift 100/10 */ +-#define I82577_CTRL_REG 23 +- +-/* 82577 specific PHY registers */ +-#define I82577_PHY_CTRL_2 18 +-#define I82577_PHY_STATUS_2 26 +-#define I82577_PHY_DIAG_STATUS 31 +- +-/* I82577 PHY Status 2 */ +-#define I82577_PHY_STATUS2_REV_POLARITY 0x0400 +-#define I82577_PHY_STATUS2_MDIX 0x0800 +-#define I82577_PHY_STATUS2_SPEED_MASK 0x0300 +-#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 +- +-/* I82577 PHY Control 2 */ +-#define I82577_PHY_CTRL2_AUTO_MDIX 0x0400 +-#define I82577_PHY_CTRL2_FORCE_MDI_MDIX 0x0200 +- +-/* I82577 PHY Diagnostics Status */ +-#define I82577_DSTATUS_CABLE_LENGTH 0x03FC +-#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2 +- +-/* BM PHY Copper Specific Control 1 */ +-#define BM_CS_CTRL1 16 +- +-#define HV_MUX_DATA_CTRL PHY_REG(776, 16) +-#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 +-#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 +- + /** + * e1000e_check_reset_block_generic - Check if PHY reset is blocked + * @hw: pointer to the HW structure +@@ -114,8 +71,7 @@ s32 e1000e_check_reset_block_generic(struct e1000_hw *hw) + + manc = er32(MANC); + +- return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? +- E1000_BLK_PHY_RESET : 0; ++ return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? E1000_BLK_PHY_RESET : 0; + } + + /** +@@ -132,30 +88,30 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw) + u16 phy_id; + u16 retry_count = 0; + +- if (!(phy->ops.read_reg)) +- goto out; ++ if (!phy->ops.read_reg) ++ return 0; + + while (retry_count < 2) { +- ret_val = e1e_rphy(hw, PHY_ID1, &phy_id); ++ ret_val = e1e_rphy(hw, MII_PHYSID1, &phy_id); + if (ret_val) +- goto out; ++ return ret_val; + + phy->id = (u32)(phy_id << 16); +- udelay(20); +- ret_val = e1e_rphy(hw, PHY_ID2, &phy_id); ++ usleep_range(20, 40); ++ ret_val = e1e_rphy(hw, MII_PHYSID2, &phy_id); + if (ret_val) +- goto out; ++ return ret_val; + + phy->id |= (u32)(phy_id & PHY_REVISION_MASK); + phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); + + if (phy->id != 0 && phy->id != PHY_REVISION_MASK) +- goto out; ++ return 0; + + retry_count++; + } +-out: +- return ret_val; ++ ++ return 0; + } + + /** +@@ -194,8 +150,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) + return -E1000_ERR_PARAM; + } + +- /* +- * Set up Op-code, Phy Address, and register offset in the MDI ++ /* Set up Op-code, Phy Address, and register offset in the MDI + * Control register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ +@@ -205,8 +160,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) + + ew32(MDIC, mdic); + +- /* +- * Poll the ready bit to see if the MDI read completed ++ /* Poll the ready bit to see if the MDI read completed + * Increasing the time out as testing showed failures with + * the lower time out + */ +@@ -224,10 +178,15 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) + e_dbg("MDI Error\n"); + return -E1000_ERR_PHY; + } +- *data = (u16) mdic; ++ if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) { ++ e_dbg("MDI Read offset error - requested %d, returned %d\n", ++ offset, ++ (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); ++ return -E1000_ERR_PHY; ++ } ++ *data = (u16)mdic; + +- /* +- * Allow some time after each MDIC transaction to avoid ++ /* Allow some time after each MDIC transaction to avoid + * reading duplicate data in the next MDIC transaction. + */ + if (hw->mac.type == e1000_pch2lan) +@@ -254,8 +213,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) + return -E1000_ERR_PARAM; + } + +- /* +- * Set up Op-code, Phy Address, and register offset in the MDI ++ /* Set up Op-code, Phy Address, and register offset in the MDI + * Control register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ +@@ -266,8 +224,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) + + ew32(MDIC, mdic); + +- /* +- * Poll the ready bit to see if the MDI read completed ++ /* Poll the ready bit to see if the MDI read completed + * Increasing the time out as testing showed failures with + * the lower time out + */ +@@ -285,9 +242,14 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) + e_dbg("MDI Error\n"); + return -E1000_ERR_PHY; + } ++ if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) { ++ e_dbg("MDI Write offset error - requested %d, returned %d\n", ++ offset, ++ (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); ++ return -E1000_ERR_PHY; ++ } + +- /* +- * Allow some time after each MDIC transaction to avoid ++ /* Allow some time after each MDIC transaction to avoid + * reading duplicate data in the next MDIC transaction. + */ + if (hw->mac.type == e1000_pch2lan) +@@ -377,34 +339,30 @@ s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page) + * semaphores before exiting. + **/ + static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data, +- bool locked) ++ bool locked) + { + s32 ret_val = 0; + + if (!locked) { +- if (!(hw->phy.ops.acquire)) +- goto out; ++ if (!hw->phy.ops.acquire) ++ return 0; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) +- goto out; ++ return ret_val; + } + +- if (offset > MAX_PHY_MULTI_PAGE_REG) { ++ if (offset > MAX_PHY_MULTI_PAGE_REG) + ret_val = e1000e_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (u16)offset); +- if (ret_val) +- goto release; +- } +- +- ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, +- data); +- +-release: ++ if (!ret_val) ++ ret_val = e1000e_read_phy_reg_mdic(hw, ++ MAX_PHY_REG_ADDRESS & offset, ++ data); + if (!locked) + hw->phy.ops.release(hw); +-out: ++ + return ret_val; + } + +@@ -448,35 +406,29 @@ s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data) + * at the offset. Release any acquired semaphores before exiting. + **/ + static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data, +- bool locked) ++ bool locked) + { + s32 ret_val = 0; + + if (!locked) { +- if (!(hw->phy.ops.acquire)) +- goto out; ++ if (!hw->phy.ops.acquire) ++ return 0; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) +- goto out; ++ return ret_val; + } + +- if (offset > MAX_PHY_MULTI_PAGE_REG) { ++ if (offset > MAX_PHY_MULTI_PAGE_REG) + ret_val = e1000e_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (u16)offset); +- if (ret_val) +- goto release; +- } +- +- ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, +- data); +- +-release: ++ if (!ret_val) ++ ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & ++ offset, data); + if (!locked) + hw->phy.ops.release(hw); + +-out: + return ret_val; + } + +@@ -520,18 +472,19 @@ s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data) + * Release any acquired semaphores before exiting. + **/ + static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, +- bool locked) ++ bool locked) + { + u32 kmrnctrlsta; +- s32 ret_val = 0; + + if (!locked) { +- if (!(hw->phy.ops.acquire)) +- goto out; ++ s32 ret_val = 0; ++ ++ if (!hw->phy.ops.acquire) ++ return 0; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) +- goto out; ++ return ret_val; + } + + kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & +@@ -547,8 +500,7 @@ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, + if (!locked) + hw->phy.ops.release(hw); + +-out: +- return ret_val; ++ return 0; + } + + /** +@@ -593,18 +545,19 @@ s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) + * before exiting. + **/ + static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, +- bool locked) ++ bool locked) + { + u32 kmrnctrlsta; +- s32 ret_val = 0; + + if (!locked) { +- if (!(hw->phy.ops.acquire)) +- goto out; ++ s32 ret_val = 0; ++ ++ if (!hw->phy.ops.acquire) ++ return 0; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) +- goto out; ++ return ret_val; + } + + kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & +@@ -617,8 +570,7 @@ static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, + if (!locked) + hw->phy.ops.release(hw); + +-out: +- return ret_val; ++ return 0; + } + + /** +@@ -650,6 +602,45 @@ s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) + } + + /** ++ * e1000_set_master_slave_mode - Setup PHY for Master/slave mode ++ * @hw: pointer to the HW structure ++ * ++ * Sets up Master/slave mode ++ **/ ++static s32 e1000_set_master_slave_mode(struct e1000_hw *hw) ++{ ++ s32 ret_val; ++ u16 phy_data; ++ ++ /* Resolve Master/Slave mode */ ++ ret_val = e1e_rphy(hw, MII_CTRL1000, &phy_data); ++ if (ret_val) ++ return ret_val; ++ ++ /* load defaults for future use */ ++ hw->phy.original_ms_type = (phy_data & CTL1000_ENABLE_MASTER) ? ++ ((phy_data & CTL1000_AS_MASTER) ? ++ e1000_ms_force_master : e1000_ms_force_slave) : e1000_ms_auto; ++ ++ switch (hw->phy.ms_type) { ++ case e1000_ms_force_master: ++ phy_data |= (CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); ++ break; ++ case e1000_ms_force_slave: ++ phy_data |= CTL1000_ENABLE_MASTER; ++ phy_data &= ~(CTL1000_AS_MASTER); ++ break; ++ case e1000_ms_auto: ++ phy_data &= ~CTL1000_ENABLE_MASTER; ++ /* fall-through */ ++ default: ++ break; ++ } ++ ++ return e1e_wphy(hw, MII_CTRL1000, phy_data); ++} ++ ++/** + * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link + * @hw: pointer to the HW structure + * +@@ -663,7 +654,7 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) + /* Enable CRS on Tx. This must be set for half-duplex operation. */ + ret_val = e1e_rphy(hw, I82577_CFG_REG, &phy_data); + if (ret_val) +- goto out; ++ return ret_val; + + phy_data |= I82577_CFG_ASSERT_CRS_ON_TX; + +@@ -671,9 +662,35 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) + phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; + + ret_val = e1e_wphy(hw, I82577_CFG_REG, phy_data); ++ if (ret_val) ++ return ret_val; + +-out: +- return ret_val; ++ /* Set MDI/MDIX mode */ ++ ret_val = e1e_rphy(hw, I82577_PHY_CTRL_2, &phy_data); ++ if (ret_val) ++ return ret_val; ++ phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK; ++ /* Options: ++ * 0 - Auto (default) ++ * 1 - MDI mode ++ * 2 - MDI-X mode ++ */ ++ switch (hw->phy.mdix) { ++ case 1: ++ break; ++ case 2: ++ phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX; ++ break; ++ case 0: ++ default: ++ phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX; ++ break; ++ } ++ ret_val = e1e_wphy(hw, I82577_PHY_CTRL_2, phy_data); ++ if (ret_val) ++ return ret_val; ++ ++ return e1000_set_master_slave_mode(hw); + } + + /** +@@ -698,8 +715,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) + if (phy->type != e1000_phy_bm) + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + +- /* +- * Options: ++ /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode +@@ -724,20 +740,35 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) + break; + } + +- /* +- * Options: ++ /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled + */ + phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; +- if (phy->disable_polarity_correction == 1) ++ if (phy->disable_polarity_correction) + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; + + /* Enable downshift on BM (disabled by default) */ +- if (phy->type == e1000_phy_bm) ++ if (phy->type == e1000_phy_bm) { ++ /* For 82574/82583, first disable then enable downshift */ ++ if (phy->id == BME1000_E_PHY_ID_R2) { ++ phy_data &= ~BME1000_PSCR_ENABLE_DOWNSHIFT; ++ ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, ++ phy_data); ++ if (ret_val) ++ return ret_val; ++ /* Commit the changes. */ ++ ret_val = phy->ops.commit(hw); ++ if (ret_val) { ++ e_dbg("Error committing the PHY changes\n"); ++ return ret_val; ++ } ++ } ++ + phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT; ++ } + + ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if (ret_val) +@@ -746,8 +777,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) + if ((phy->type == e1000_phy_m88) && + (phy->revision < E1000_REVISION_4) && + (phy->id != BME1000_E_PHY_ID_R2)) { +- /* +- * Force TX_CLK in the Extended PHY Specific Control Register ++ /* Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ + ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); +@@ -756,8 +786,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) + + phy_data |= M88E1000_EPSCR_TX_CLK_25; + +- if ((phy->revision == 2) && +- (phy->id == M88E1111_I_PHY_ID)) { ++ if ((phy->revision == 2) && (phy->id == M88E1111_I_PHY_ID)) { + /* 82573L PHY - set the downshift counter to 5x. */ + phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK; + phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; +@@ -786,10 +815,12 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) + } + + /* Commit the changes. */ +- ret_val = e1000e_commit_phy(hw); +- if (ret_val) { +- e_dbg("Error committing the PHY changes\n"); +- return ret_val; ++ if (phy->ops.commit) { ++ ret_val = phy->ops.commit(hw); ++ if (ret_val) { ++ e_dbg("Error committing the PHY changes\n"); ++ return ret_val; ++ } + } + + if (phy->type == e1000_phy_82578) { +@@ -827,17 +858,18 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw) + return ret_val; + } + +- /* +- * Wait 100ms for MAC to configure PHY from NVM settings, to avoid ++ /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid + * timeout issues when LFS is enabled. + */ + msleep(100); + + /* disable lplu d0 during driver init */ +- ret_val = e1000_set_d0_lplu_state(hw, false); +- if (ret_val) { +- e_dbg("Error Disabling LPLU D0\n"); +- return ret_val; ++ if (hw->phy.ops.set_d0_lplu_state) { ++ ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); ++ if (ret_val) { ++ e_dbg("Error Disabling LPLU D0\n"); ++ return ret_val; ++ } + } + /* Configure mdi-mdix settings */ + ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &data); +@@ -864,8 +896,7 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw) + + /* set auto-master slave resolution settings */ + if (hw->mac.autoneg) { +- /* +- * when autonegotiation advertisement is only 1000Mbps then we ++ /* when autonegotiation advertisement is only 1000Mbps then we + * should disable SmartSpeed and enable Auto MasterSlave + * resolution as hardware default. + */ +@@ -883,41 +914,17 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw) + return ret_val; + + /* Set auto Master/Slave resolution process */ +- ret_val = e1e_rphy(hw, PHY_1000T_CTRL, &data); ++ ret_val = e1e_rphy(hw, MII_CTRL1000, &data); + if (ret_val) + return ret_val; + +- data &= ~CR_1000T_MS_ENABLE; +- ret_val = e1e_wphy(hw, PHY_1000T_CTRL, data); ++ data &= ~CTL1000_ENABLE_MASTER; ++ ret_val = e1e_wphy(hw, MII_CTRL1000, data); + if (ret_val) + return ret_val; + } + +- ret_val = e1e_rphy(hw, PHY_1000T_CTRL, &data); +- if (ret_val) +- return ret_val; +- +- /* load defaults for future use */ +- phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ? +- ((data & CR_1000T_MS_VALUE) ? +- e1000_ms_force_master : +- e1000_ms_force_slave) : +- e1000_ms_auto; +- +- switch (phy->ms_type) { +- case e1000_ms_force_master: +- data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); +- break; +- case e1000_ms_force_slave: +- data |= CR_1000T_MS_ENABLE; +- data &= ~(CR_1000T_MS_VALUE); +- break; +- case e1000_ms_auto: +- data &= ~CR_1000T_MS_ENABLE; +- default: +- break; +- } +- ret_val = e1e_wphy(hw, PHY_1000T_CTRL, data); ++ ret_val = e1000_set_master_slave_mode(hw); + } + + return ret_val; +@@ -942,60 +949,57 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) + phy->autoneg_advertised &= phy->autoneg_mask; + + /* Read the MII Auto-Neg Advertisement Register (Address 4). */ +- ret_val = e1e_rphy(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); ++ ret_val = e1e_rphy(hw, MII_ADVERTISE, &mii_autoneg_adv_reg); + if (ret_val) + return ret_val; + + if (phy->autoneg_mask & ADVERTISE_1000_FULL) { + /* Read the MII 1000Base-T Control Register (Address 9). */ +- ret_val = e1e_rphy(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); ++ ret_val = e1e_rphy(hw, MII_CTRL1000, &mii_1000t_ctrl_reg); + if (ret_val) + return ret_val; + } + +- /* +- * Need to parse both autoneg_advertised and fc and set up ++ /* Need to parse both autoneg_advertised and fc and set up + * the appropriate PHY registers. First we will parse for + * autoneg_advertised software override. Since we can advertise + * a plethora of combinations, we need to check each bit + * individually. + */ + +- /* +- * First we clear all the 10/100 mb speed bits in the Auto-Neg ++ /* First we clear all the 10/100 mb speed bits in the Auto-Neg + * Advertisement Register (Address 4) and the 1000 mb speed bits in + * the 1000Base-T Control Register (Address 9). + */ +- mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS | +- NWAY_AR_100TX_HD_CAPS | +- NWAY_AR_10T_FD_CAPS | +- NWAY_AR_10T_HD_CAPS); +- mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS); ++ mii_autoneg_adv_reg &= ~(ADVERTISE_100FULL | ++ ADVERTISE_100HALF | ++ ADVERTISE_10FULL | ADVERTISE_10HALF); ++ mii_1000t_ctrl_reg &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); + + e_dbg("autoneg_advertised %x\n", phy->autoneg_advertised); + + /* Do we want to advertise 10 Mb Half Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_10_HALF) { + e_dbg("Advertise 10mb Half duplex\n"); +- mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; ++ mii_autoneg_adv_reg |= ADVERTISE_10HALF; + } + + /* Do we want to advertise 10 Mb Full Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_10_FULL) { + e_dbg("Advertise 10mb Full duplex\n"); +- mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; ++ mii_autoneg_adv_reg |= ADVERTISE_10FULL; + } + + /* Do we want to advertise 100 Mb Half Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_100_HALF) { + e_dbg("Advertise 100mb Half duplex\n"); +- mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; ++ mii_autoneg_adv_reg |= ADVERTISE_100HALF; + } + + /* Do we want to advertise 100 Mb Full Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_100_FULL) { + e_dbg("Advertise 100mb Full duplex\n"); +- mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; ++ mii_autoneg_adv_reg |= ADVERTISE_100FULL; + } + + /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ +@@ -1005,38 +1009,36 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) + /* Do we want to advertise 1000 Mb Full Duplex? */ + if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { + e_dbg("Advertise 1000mb Full duplex\n"); +- mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; ++ mii_1000t_ctrl_reg |= ADVERTISE_1000FULL; + } + +- /* +- * Check for a software override of the flow control settings, and ++ /* Check for a software override of the flow control settings, and + * setup the PHY advertisement registers accordingly. If + * auto-negotiation is enabled, then software will have to set the + * "PAUSE" bits to the correct value in the Auto-Negotiation +- * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto- ++ * Advertisement Register (MII_ADVERTISE) and re-start auto- + * negotiation. + * + * The possible values of the "fc" parameter are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames +- * but not send pause frames). ++ * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames +- * but we do not support receiving pause frames). ++ * but we do not support receiving pause frames). + * 3: Both Rx and Tx flow control (symmetric) are enabled. + * other: No software override. The flow control configuration +- * in the EEPROM is used. ++ * in the EEPROM is used. + */ + switch (hw->fc.current_mode) { + case e1000_fc_none: +- /* +- * Flow control (Rx & Tx) is completely disabled by a ++ /* Flow control (Rx & Tx) is completely disabled by a + * software over-ride. + */ +- mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); ++ mii_autoneg_adv_reg &= ++ ~(ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); + break; + case e1000_fc_rx_pause: +- /* +- * Rx Flow control is enabled, and Tx Flow control is ++ /* Rx Flow control is enabled, and Tx Flow control is + * disabled, by a software over-ride. + * + * Since there really isn't a way to advertise that we are +@@ -1045,37 +1047,36 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) + * (in e1000e_config_fc_after_link_up) we will disable the + * hw's ability to send PAUSE frames. + */ +- mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); ++ mii_autoneg_adv_reg |= ++ (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); + break; + case e1000_fc_tx_pause: +- /* +- * Tx Flow control is enabled, and Rx Flow control is ++ /* Tx Flow control is enabled, and Rx Flow control is + * disabled, by a software over-ride. + */ +- mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; +- mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; ++ mii_autoneg_adv_reg |= ADVERTISE_PAUSE_ASYM; ++ mii_autoneg_adv_reg &= ~ADVERTISE_PAUSE_CAP; + break; + case e1000_fc_full: +- /* +- * Flow control (both Rx and Tx) is enabled by a software ++ /* Flow control (both Rx and Tx) is enabled by a software + * over-ride. + */ +- mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); ++ mii_autoneg_adv_reg |= ++ (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); + break; + default: + e_dbg("Flow control param set incorrectly\n"); +- ret_val = -E1000_ERR_CONFIG; +- return ret_val; ++ return -E1000_ERR_CONFIG; + } + +- ret_val = e1e_wphy(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); ++ ret_val = e1e_wphy(hw, MII_ADVERTISE, mii_autoneg_adv_reg); + if (ret_val) + return ret_val; + + e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); + + if (phy->autoneg_mask & ADVERTISE_1000_FULL) +- ret_val = e1e_wphy(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg); ++ ret_val = e1e_wphy(hw, MII_CTRL1000, mii_1000t_ctrl_reg); + + return ret_val; + } +@@ -1095,17 +1096,15 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) + s32 ret_val; + u16 phy_ctrl; + +- /* +- * Perform some bounds checking on the autoneg advertisement ++ /* Perform some bounds checking on the autoneg advertisement + * parameter. + */ + phy->autoneg_advertised &= phy->autoneg_mask; + +- /* +- * If autoneg_advertised is zero, we assume it was not defaulted ++ /* If autoneg_advertised is zero, we assume it was not defaulted + * by the calling code so we set to advertise full capability. + */ +- if (phy->autoneg_advertised == 0) ++ if (!phy->autoneg_advertised) + phy->autoneg_advertised = phy->autoneg_mask; + + e_dbg("Reconfiguring auto-neg advertisement params\n"); +@@ -1116,33 +1115,30 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) + } + e_dbg("Restarting Auto-Neg\n"); + +- /* +- * Restart auto-negotiation by setting the Auto Neg Enable bit and ++ /* Restart auto-negotiation by setting the Auto Neg Enable bit and + * the Auto Neg Restart bit in the PHY control register. + */ +- ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_ctrl); ++ ret_val = e1e_rphy(hw, MII_BMCR, &phy_ctrl); + if (ret_val) + return ret_val; + +- phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); +- ret_val = e1e_wphy(hw, PHY_CONTROL, phy_ctrl); ++ phy_ctrl |= (BMCR_ANENABLE | BMCR_ANRESTART); ++ ret_val = e1e_wphy(hw, MII_BMCR, phy_ctrl); + if (ret_val) + return ret_val; + +- /* +- * Does the user want to wait for Auto-Neg to complete here, or ++ /* Does the user want to wait for Auto-Neg to complete here, or + * check at a later time (for example, callback routine). + */ + if (phy->autoneg_wait_to_complete) { + ret_val = e1000_wait_autoneg(hw); + if (ret_val) { +- e_dbg("Error while waiting for " +- "autoneg to complete\n"); ++ e_dbg("Error while waiting for autoneg to complete\n"); + return ret_val; + } + } + +- hw->mac.get_link_status = 1; ++ hw->mac.get_link_status = true; + + return ret_val; + } +@@ -1162,40 +1158,35 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw) + bool link; + + if (hw->mac.autoneg) { +- /* +- * Setup autoneg and flow control advertisement and perform ++ /* Setup autoneg and flow control advertisement and perform + * autonegotiation. + */ + ret_val = e1000_copper_link_autoneg(hw); + if (ret_val) + return ret_val; + } else { +- /* +- * PHY will be set to 10H, 10F, 100H or 100F ++ /* PHY will be set to 10H, 10F, 100H or 100F + * depending on user settings. + */ + e_dbg("Forcing Speed and Duplex\n"); +- ret_val = e1000_phy_force_speed_duplex(hw); ++ ret_val = hw->phy.ops.force_speed_duplex(hw); + if (ret_val) { + e_dbg("Error Forcing Speed and Duplex\n"); + return ret_val; + } + } + +- /* +- * Check link status. Wait up to 100 microseconds for link to become ++ /* Check link status. Wait up to 100 microseconds for link to become + * valid. + */ +- ret_val = e1000e_phy_has_link_generic(hw, +- COPPER_LINK_UP_LIMIT, +- 10, +- &link); ++ ret_val = e1000e_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10, ++ &link); + if (ret_val) + return ret_val; + + if (link) { + e_dbg("Valid link established!!!\n"); +- e1000e_config_collision_dist(hw); ++ hw->mac.ops.config_collision_dist(hw); + ret_val = e1000e_config_fc_after_link_up(hw); + } else { + e_dbg("Unable to establish link!!!\n"); +@@ -1219,18 +1210,17 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw) + u16 phy_data; + bool link; + +- ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); ++ ret_val = e1e_rphy(hw, MII_BMCR, &phy_data); + if (ret_val) + return ret_val; + + e1000e_phy_force_speed_duplex_setup(hw, &phy_data); + +- ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); ++ ret_val = e1e_wphy(hw, MII_BMCR, phy_data); + if (ret_val) + return ret_val; + +- /* +- * Clear Auto-Crossover to force MDI manually. IGP requires MDI ++ /* Clear Auto-Crossover to force MDI manually. IGP requires MDI + * forced whenever speed and duplex are forced. + */ + ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); +@@ -1251,10 +1241,8 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw) + if (phy->autoneg_wait_to_complete) { + e_dbg("Waiting for forced speed/duplex link on IGP phy.\n"); + +- ret_val = e1000e_phy_has_link_generic(hw, +- PHY_FORCE_LIMIT, +- 100000, +- &link); ++ ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, ++ 100000, &link); + if (ret_val) + return ret_val; + +@@ -1262,12 +1250,8 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw) + e_dbg("Link taking longer than expected.\n"); + + /* Try once more */ +- ret_val = e1000e_phy_has_link_generic(hw, +- PHY_FORCE_LIMIT, +- 100000, +- &link); +- if (ret_val) +- return ret_val; ++ ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, ++ 100000, &link); + } + + return ret_val; +@@ -1290,8 +1274,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) + u16 phy_data; + bool link; + +- /* +- * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI ++ /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI + * forced whenever speed and duplex are forced. + */ + ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); +@@ -1305,26 +1288,28 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) + + e_dbg("M88E1000 PSCR: %X\n", phy_data); + +- ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); ++ ret_val = e1e_rphy(hw, MII_BMCR, &phy_data); + if (ret_val) + return ret_val; + + e1000e_phy_force_speed_duplex_setup(hw, &phy_data); + +- ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); ++ ret_val = e1e_wphy(hw, MII_BMCR, phy_data); + if (ret_val) + return ret_val; + + /* Reset the phy to commit changes. */ +- ret_val = e1000e_commit_phy(hw); +- if (ret_val) +- return ret_val; ++ if (hw->phy.ops.commit) { ++ ret_val = hw->phy.ops.commit(hw); ++ if (ret_val) ++ return ret_val; ++ } + + if (phy->autoneg_wait_to_complete) { + e_dbg("Waiting for forced speed/duplex link on M88 phy.\n"); + + ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, +- 100000, &link); ++ 100000, &link); + if (ret_val) + return ret_val; + +@@ -1332,8 +1317,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) + if (hw->phy.type != e1000_phy_m88) { + e_dbg("Link taking longer than expected.\n"); + } else { +- /* +- * We didn't get link. ++ /* We didn't get link. + * Reset the DSP and cross our fingers. + */ + ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT, +@@ -1348,7 +1332,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) + + /* Try once more */ + ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, +- 100000, &link); ++ 100000, &link); + if (ret_val) + return ret_val; + } +@@ -1360,8 +1344,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) + if (ret_val) + return ret_val; + +- /* +- * Resetting the phy means we need to re-force TX_CLK in the ++ /* Resetting the phy means we need to re-force TX_CLK in the + * Extended PHY Specific Control Register to 25MHz clock from + * the reset value of 2.5MHz. + */ +@@ -1370,8 +1353,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) + if (ret_val) + return ret_val; + +- /* +- * In addition, we must re-enable CRS on Tx for both half and full ++ /* In addition, we must re-enable CRS on Tx for both half and full + * duplex. + */ + ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); +@@ -1399,27 +1381,27 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw) + u16 data; + bool link; + +- ret_val = e1e_rphy(hw, PHY_CONTROL, &data); ++ ret_val = e1e_rphy(hw, MII_BMCR, &data); + if (ret_val) +- goto out; ++ return ret_val; + + e1000e_phy_force_speed_duplex_setup(hw, &data); + +- ret_val = e1e_wphy(hw, PHY_CONTROL, data); ++ ret_val = e1e_wphy(hw, MII_BMCR, data); + if (ret_val) +- goto out; ++ return ret_val; + + /* Disable MDI-X support for 10/100 */ + ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data); + if (ret_val) +- goto out; ++ return ret_val; + + data &= ~IFE_PMC_AUTO_MDIX; + data &= ~IFE_PMC_FORCE_MDIX; + + ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, data); + if (ret_val) +- goto out; ++ return ret_val; + + e_dbg("IFE PMC: %X\n", data); + +@@ -1428,39 +1410,34 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw) + if (phy->autoneg_wait_to_complete) { + e_dbg("Waiting for forced speed/duplex link on IFE phy.\n"); + +- ret_val = e1000e_phy_has_link_generic(hw, +- PHY_FORCE_LIMIT, +- 100000, +- &link); ++ ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, ++ 100000, &link); + if (ret_val) +- goto out; ++ return ret_val; + + if (!link) + e_dbg("Link taking longer than expected.\n"); + + /* Try once more */ +- ret_val = e1000e_phy_has_link_generic(hw, +- PHY_FORCE_LIMIT, +- 100000, +- &link); ++ ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, ++ 100000, &link); + if (ret_val) +- goto out; ++ return ret_val; + } + +-out: +- return ret_val; ++ return 0; + } + + /** + * e1000e_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex + * @hw: pointer to the HW structure +- * @phy_ctrl: pointer to current value of PHY_CONTROL ++ * @phy_ctrl: pointer to current value of MII_BMCR + * + * Forces speed and duplex on the PHY by doing the following: disable flow + * control, force speed/duplex on the MAC, disable auto speed detection, + * disable auto-negotiation, configure duplex, configure speed, configure + * the collision distance, write configuration to CTRL register. The +- * caller must write to the PHY_CONTROL register for these settings to ++ * caller must write to the MII_BMCR register for these settings to + * take affect. + **/ + void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) +@@ -1480,33 +1457,32 @@ void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) + ctrl &= ~E1000_CTRL_ASDE; + + /* Disable autoneg on the phy */ +- *phy_ctrl &= ~MII_CR_AUTO_NEG_EN; ++ *phy_ctrl &= ~BMCR_ANENABLE; + + /* Forcing Full or Half Duplex? */ + if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { + ctrl &= ~E1000_CTRL_FD; +- *phy_ctrl &= ~MII_CR_FULL_DUPLEX; ++ *phy_ctrl &= ~BMCR_FULLDPLX; + e_dbg("Half Duplex\n"); + } else { + ctrl |= E1000_CTRL_FD; +- *phy_ctrl |= MII_CR_FULL_DUPLEX; ++ *phy_ctrl |= BMCR_FULLDPLX; + e_dbg("Full Duplex\n"); + } + + /* Forcing 10mb or 100mb? */ + if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { + ctrl |= E1000_CTRL_SPD_100; +- *phy_ctrl |= MII_CR_SPEED_100; +- *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); ++ *phy_ctrl |= BMCR_SPEED100; ++ *phy_ctrl &= ~BMCR_SPEED1000; + e_dbg("Forcing 100mb\n"); + } else { + ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); +- *phy_ctrl |= MII_CR_SPEED_10; +- *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); ++ *phy_ctrl &= ~(BMCR_SPEED1000 | BMCR_SPEED100); + e_dbg("Forcing 10mb\n"); + } + +- e1000e_config_collision_dist(hw); ++ hw->mac.ops.config_collision_dist(hw); + + ew32(CTRL, ctrl); + } +@@ -1540,8 +1516,7 @@ s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active) + ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); + if (ret_val) + return ret_val; +- /* +- * LPLU and SmartSpeed are mutually exclusive. LPLU is used ++ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used + * during Dx states where the power conservation is most + * important. During driver activity we should enable + * SmartSpeed, so performance is maintained. +@@ -1608,13 +1583,13 @@ s32 e1000e_check_downshift(struct e1000_hw *hw) + case e1000_phy_gg82563: + case e1000_phy_bm: + case e1000_phy_82578: +- offset = M88E1000_PHY_SPEC_STATUS; +- mask = M88E1000_PSSR_DOWNSHIFT; ++ offset = M88E1000_PHY_SPEC_STATUS; ++ mask = M88E1000_PSSR_DOWNSHIFT; + break; + case e1000_phy_igp_2: + case e1000_phy_igp_3: +- offset = IGP01E1000_PHY_LINK_HEALTH; +- mask = IGP01E1000_PLHR_SS_DOWNGRADE; ++ offset = IGP01E1000_PHY_LINK_HEALTH; ++ mask = IGP01E1000_PLHR_SS_DOWNGRADE; + break; + default: + /* speed downshift not supported */ +@@ -1625,7 +1600,7 @@ s32 e1000e_check_downshift(struct e1000_hw *hw) + ret_val = e1e_rphy(hw, offset, &phy_data); + + if (!ret_val) +- phy->speed_downgraded = (phy_data & mask); ++ phy->speed_downgraded = !!(phy_data & mask); + + return ret_val; + } +@@ -1647,9 +1622,9 @@ s32 e1000_check_polarity_m88(struct e1000_hw *hw) + ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &data); + + if (!ret_val) +- phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY) +- ? e1000_rev_polarity_reversed +- : e1000_rev_polarity_normal; ++ phy->cable_polarity = ((data & M88E1000_PSSR_REV_POLARITY) ++ ? e1000_rev_polarity_reversed ++ : e1000_rev_polarity_normal); + + return ret_val; + } +@@ -1669,8 +1644,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw) + s32 ret_val; + u16 data, offset, mask; + +- /* +- * Polarity is determined based on the speed of ++ /* Polarity is determined based on the speed of + * our connection. + */ + ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data); +@@ -1679,23 +1653,22 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw) + + if ((data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_1000MBPS) { +- offset = IGP01E1000_PHY_PCS_INIT_REG; +- mask = IGP01E1000_PHY_POLARITY_MASK; ++ offset = IGP01E1000_PHY_PCS_INIT_REG; ++ mask = IGP01E1000_PHY_POLARITY_MASK; + } else { +- /* +- * This really only applies to 10Mbps since ++ /* This really only applies to 10Mbps since + * there is no polarity for 100Mbps (always 0). + */ +- offset = IGP01E1000_PHY_PORT_STATUS; +- mask = IGP01E1000_PSSR_POLARITY_REVERSED; ++ offset = IGP01E1000_PHY_PORT_STATUS; ++ mask = IGP01E1000_PSSR_POLARITY_REVERSED; + } + + ret_val = e1e_rphy(hw, offset, &data); + + if (!ret_val) +- phy->cable_polarity = (data & mask) +- ? e1000_rev_polarity_reversed +- : e1000_rev_polarity_normal; ++ phy->cable_polarity = ((data & mask) ++ ? e1000_rev_polarity_reversed ++ : e1000_rev_polarity_normal); + + return ret_val; + } +@@ -1712,8 +1685,7 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw) + s32 ret_val; + u16 phy_data, offset, mask; + +- /* +- * Polarity is determined based on the reversal feature being enabled. ++ /* Polarity is determined based on the reversal feature being enabled. + */ + if (phy->polarity_correction) { + offset = IFE_PHY_EXTENDED_STATUS_CONTROL; +@@ -1726,9 +1698,9 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw) + ret_val = e1e_rphy(hw, offset, &phy_data); + + if (!ret_val) +- phy->cable_polarity = (phy_data & mask) +- ? e1000_rev_polarity_reversed +- : e1000_rev_polarity_normal; ++ phy->cable_polarity = ((phy_data & mask) ++ ? e1000_rev_polarity_reversed ++ : e1000_rev_polarity_normal); + + return ret_val; + } +@@ -1747,19 +1719,18 @@ static s32 e1000_wait_autoneg(struct e1000_hw *hw) + + /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ + for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { +- ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); ++ ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); + if (ret_val) + break; +- ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); ++ ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); + if (ret_val) + break; +- if (phy_status & MII_SR_AUTONEG_COMPLETE) ++ if (phy_status & BMSR_ANEGCOMPLETE) + break; + msleep(100); + } + +- /* +- * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation ++ /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation + * has completed. + */ + return ret_val; +@@ -1775,32 +1746,34 @@ static s32 e1000_wait_autoneg(struct e1000_hw *hw) + * Polls the PHY status register for link, 'iterations' number of times. + **/ + s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, +- u32 usec_interval, bool *success) ++ u32 usec_interval, bool *success) + { + s32 ret_val = 0; + u16 i, phy_status; + + for (i = 0; i < iterations; i++) { +- /* +- * Some PHYs require the PHY_STATUS register to be read ++ /* Some PHYs require the MII_BMSR register to be read + * twice due to the link bit being sticky. No harm doing + * it across the board. + */ +- ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); +- if (ret_val) +- /* +- * If the first read fails, another entity may have ++ ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); ++ if (ret_val) { ++ /* If the first read fails, another entity may have + * ownership of the resources, wait and try again to + * see if they have relinquished the resources yet. + */ +- udelay(usec_interval); +- ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); ++ if (usec_interval >= 1000) ++ msleep(usec_interval / 1000); ++ else ++ udelay(usec_interval); ++ } ++ ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); + if (ret_val) + break; +- if (phy_status & MII_SR_LINK_STATUS) ++ if (phy_status & BMSR_LSTATUS) + break; + if (usec_interval >= 1000) +- mdelay(usec_interval/1000); ++ msleep(usec_interval / 1000); + else + udelay(usec_interval); + } +@@ -1833,22 +1806,20 @@ s32 e1000e_get_cable_length_m88(struct e1000_hw *hw) + + ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); + if (ret_val) +- goto out; ++ return ret_val; + +- index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> +- M88E1000_PSSR_CABLE_LENGTH_SHIFT; +- if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) { +- ret_val = -E1000_ERR_PHY; +- goto out; +- } ++ index = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> ++ M88E1000_PSSR_CABLE_LENGTH_SHIFT); ++ ++ if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) ++ return -E1000_ERR_PHY; + + phy->min_cable_length = e1000_m88_cable_length_table[index]; + phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; + + phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; + +-out: +- return ret_val; ++ return 0; + } + + /** +@@ -1870,10 +1841,10 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw) + u16 cur_agc_index, max_agc_index = 0; + u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; + static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = { +- IGP02E1000_PHY_AGC_A, +- IGP02E1000_PHY_AGC_B, +- IGP02E1000_PHY_AGC_C, +- IGP02E1000_PHY_AGC_D ++ IGP02E1000_PHY_AGC_A, ++ IGP02E1000_PHY_AGC_B, ++ IGP02E1000_PHY_AGC_C, ++ IGP02E1000_PHY_AGC_D + }; + + /* Read the AGC registers for all channels */ +@@ -1882,14 +1853,13 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw) + if (ret_val) + return ret_val; + +- /* +- * Getting bits 15:9, which represent the combination of ++ /* Getting bits 15:9, which represent the combination of + * coarse and fine gain values. The result is a number + * that can be put into the lookup table to obtain the + * approximate cable length. + */ +- cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & +- IGP02E1000_AGC_LENGTH_MASK; ++ cur_agc_index = ((phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & ++ IGP02E1000_AGC_LENGTH_MASK); + + /* Array index bound check. */ + if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) || +@@ -1912,13 +1882,13 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw) + agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); + + /* Calculate cable length with the error range of +/- 10 meters. */ +- phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ? +- (agc_value - IGP02E1000_AGC_RANGE) : 0; ++ phy->min_cable_length = (((agc_value - IGP02E1000_AGC_RANGE) > 0) ? ++ (agc_value - IGP02E1000_AGC_RANGE) : 0); + phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE; + + phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; + +- return ret_val; ++ return 0; + } + + /** +@@ -1934,7 +1904,7 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw) + s32 e1000e_get_phy_info_m88(struct e1000_hw *hw) + { + struct e1000_phy_info *phy = &hw->phy; +- s32 ret_val; ++ s32 ret_val; + u16 phy_data; + bool link; + +@@ -1956,8 +1926,8 @@ s32 e1000e_get_phy_info_m88(struct e1000_hw *hw) + if (ret_val) + return ret_val; + +- phy->polarity_correction = (phy_data & +- M88E1000_PSCR_POLARITY_REVERSAL); ++ phy->polarity_correction = !!(phy_data & ++ M88E1000_PSCR_POLARITY_REVERSAL); + + ret_val = e1000_check_polarity_m88(hw); + if (ret_val) +@@ -1967,24 +1937,22 @@ s32 e1000e_get_phy_info_m88(struct e1000_hw *hw) + if (ret_val) + return ret_val; + +- phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX); ++ phy->is_mdix = !!(phy_data & M88E1000_PSSR_MDIX); + + if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { +- ret_val = e1000_get_cable_length(hw); ++ ret_val = hw->phy.ops.get_cable_length(hw); + if (ret_val) + return ret_val; + +- ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &phy_data); ++ ret_val = e1e_rphy(hw, MII_STAT1000, &phy_data); + if (ret_val) + return ret_val; + +- phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) +- ? e1000_1000t_rx_status_ok +- : e1000_1000t_rx_status_not_ok; ++ phy->local_rx = (phy_data & LPA_1000LOCALRXOK) ++ ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; + +- phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) +- ? e1000_1000t_rx_status_ok +- : e1000_1000t_rx_status_not_ok; ++ phy->remote_rx = (phy_data & LPA_1000REMRXOK) ++ ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; + } else { + /* Set values to "undefined" */ + phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; +@@ -2030,25 +1998,23 @@ s32 e1000e_get_phy_info_igp(struct e1000_hw *hw) + if (ret_val) + return ret_val; + +- phy->is_mdix = (data & IGP01E1000_PSSR_MDIX); ++ phy->is_mdix = !!(data & IGP01E1000_PSSR_MDIX); + + if ((data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_1000MBPS) { +- ret_val = e1000_get_cable_length(hw); ++ ret_val = phy->ops.get_cable_length(hw); + if (ret_val) + return ret_val; + +- ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &data); ++ ret_val = e1e_rphy(hw, MII_STAT1000, &data); + if (ret_val) + return ret_val; + +- phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) +- ? e1000_1000t_rx_status_ok +- : e1000_1000t_rx_status_not_ok; ++ phy->local_rx = (data & LPA_1000LOCALRXOK) ++ ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; + +- phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) +- ? e1000_1000t_rx_status_ok +- : e1000_1000t_rx_status_not_ok; ++ phy->remote_rx = (data & LPA_1000REMRXOK) ++ ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; + } else { + phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; + phy->local_rx = e1000_1000t_rx_status_undefined; +@@ -2073,44 +2039,41 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw) + + ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) +- goto out; ++ return ret_val; + + if (!link) { + e_dbg("Phy info is only valid if link is up\n"); +- ret_val = -E1000_ERR_CONFIG; +- goto out; ++ return -E1000_ERR_CONFIG; + } + + ret_val = e1e_rphy(hw, IFE_PHY_SPECIAL_CONTROL, &data); + if (ret_val) +- goto out; +- phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE) +- ? false : true; ++ return ret_val; ++ phy->polarity_correction = !(data & IFE_PSC_AUTO_POLARITY_DISABLE); + + if (phy->polarity_correction) { + ret_val = e1000_check_polarity_ife(hw); + if (ret_val) +- goto out; ++ return ret_val; + } else { + /* Polarity is forced */ +- phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY) +- ? e1000_rev_polarity_reversed +- : e1000_rev_polarity_normal; ++ phy->cable_polarity = ((data & IFE_PSC_FORCE_POLARITY) ++ ? e1000_rev_polarity_reversed ++ : e1000_rev_polarity_normal); + } + + ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data); + if (ret_val) +- goto out; ++ return ret_val; + +- phy->is_mdix = (data & IFE_PMC_MDIX_STATUS) ? true : false; ++ phy->is_mdix = !!(data & IFE_PMC_MDIX_STATUS); + + /* The following parameters are undefined for 10/100 operation. */ + phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; + phy->local_rx = e1000_1000t_rx_status_undefined; + phy->remote_rx = e1000_1000t_rx_status_undefined; + +-out: +- return ret_val; ++ return 0; + } + + /** +@@ -2125,12 +2088,12 @@ s32 e1000e_phy_sw_reset(struct e1000_hw *hw) + s32 ret_val; + u16 phy_ctrl; + +- ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_ctrl); ++ ret_val = e1e_rphy(hw, MII_BMCR, &phy_ctrl); + if (ret_val) + return ret_val; + +- phy_ctrl |= MII_CR_RESET; +- ret_val = e1e_wphy(hw, PHY_CONTROL, phy_ctrl); ++ phy_ctrl |= BMCR_RESET; ++ ret_val = e1e_wphy(hw, MII_BMCR, phy_ctrl); + if (ret_val) + return ret_val; + +@@ -2154,9 +2117,11 @@ s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw) + s32 ret_val; + u32 ctrl; + +- ret_val = e1000_check_reset_block(hw); +- if (ret_val) +- return 0; ++ if (phy->ops.check_reset_block) { ++ ret_val = phy->ops.check_reset_block(hw); ++ if (ret_val) ++ return 0; ++ } + + ret_val = phy->ops.acquire(hw); + if (ret_val) +@@ -2171,23 +2136,24 @@ s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw) + ew32(CTRL, ctrl); + e1e_flush(); + +- udelay(150); ++ usleep_range(150, 300); + + phy->ops.release(hw); + +- return e1000_get_phy_cfg_done(hw); ++ return phy->ops.get_cfg_done(hw); + } + + /** +- * e1000e_get_cfg_done - Generic configuration done ++ * e1000e_get_cfg_done_generic - Generic configuration done + * @hw: pointer to the HW structure + * + * Generic function to wait 10 milli-seconds for configuration to complete + * and return success. + **/ +-s32 e1000e_get_cfg_done(struct e1000_hw *hw) ++s32 e1000e_get_cfg_done_generic(struct e1000_hw __always_unused *hw) + { + mdelay(10); ++ + return 0; + } + +@@ -2254,15 +2220,13 @@ s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw) + e1e_wphy(hw, 0x1796, 0x0008); + /* Change cg_icount + enable integbp for channels BCD */ + e1e_wphy(hw, 0x1798, 0xD008); +- /* +- * Change cg_icount + enable integbp + change prop_factor_master ++ /* Change cg_icount + enable integbp + change prop_factor_master + * to 8 for channel A + */ + e1e_wphy(hw, 0x1898, 0xD918); + /* Disable AHT in Slave mode on channel A */ + e1e_wphy(hw, 0x187A, 0x0800); +- /* +- * Enable LPLU and disable AN to 1000 in non-D0a states, ++ /* Enable LPLU and disable AN to 1000 in non-D0a states, + * Enable SPD+B2B + */ + e1e_wphy(hw, 0x0019, 0x008D); +@@ -2276,38 +2240,6 @@ s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw) + return 0; + } + +-/* Internal function pointers */ +- +-/** +- * e1000_get_phy_cfg_done - Generic PHY configuration done +- * @hw: pointer to the HW structure +- * +- * Return success if silicon family did not implement a family specific +- * get_cfg_done function. +- **/ +-static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw) +-{ +- if (hw->phy.ops.get_cfg_done) +- return hw->phy.ops.get_cfg_done(hw); +- +- return 0; +-} +- +-/** +- * e1000_phy_force_speed_duplex - Generic force PHY speed/duplex +- * @hw: pointer to the HW structure +- * +- * When the silicon family has not implemented a forced speed/duplex +- * function for the PHY, simply return 0. +- **/ +-static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw) +-{ +- if (hw->phy.ops.force_speed_duplex) +- return hw->phy.ops.force_speed_duplex(hw); +- +- return 0; +-} +- + /** + * e1000e_get_phy_type_from_id - Get PHY type from id + * @phy_id: phy_id read from the phy +@@ -2325,7 +2257,7 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id) + case M88E1011_I_PHY_ID: + phy_type = e1000_phy_m88; + break; +- case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ ++ case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ + phy_type = e1000_phy_igp_2; + break; + case GG82563_E_PHY_ID: +@@ -2352,6 +2284,9 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id) + case I82579_E_PHY_ID: + phy_type = e1000_phy_82579; + break; ++ case I217_E_PHY_ID: ++ phy_type = e1000_phy_i217; ++ break; + default: + phy_type = e1000_phy_unknown; + break; +@@ -2369,7 +2304,6 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id) + **/ + s32 e1000e_determine_phy_address(struct e1000_hw *hw) + { +- s32 ret_val = -E1000_ERR_PHY_TYPE; + u32 phy_addr = 0; + u32 i; + enum e1000_phy_type phy_type = e1000_phy_unknown; +@@ -2384,21 +2318,18 @@ s32 e1000e_determine_phy_address(struct e1000_hw *hw) + e1000e_get_phy_id(hw); + phy_type = e1000e_get_phy_type_from_id(hw->phy.id); + +- /* +- * If phy_type is valid, break - we found our ++ /* If phy_type is valid, break - we found our + * PHY address + */ +- if (phy_type != e1000_phy_unknown) { +- ret_val = 0; +- goto out; +- } ++ if (phy_type != e1000_phy_unknown) ++ return 0; ++ + usleep_range(1000, 2000); + i++; + } while (i < 10); + } + +-out: +- return ret_val; ++ return -E1000_ERR_PHY_TYPE; + } + + /** +@@ -2439,7 +2370,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) + if (page == BM_WUC_PAGE) { + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, + false, false); +- goto out; ++ goto release; + } + + hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); +@@ -2447,8 +2378,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) + if (offset > MAX_PHY_MULTI_PAGE_REG) { + u32 page_shift, page_select; + +- /* +- * Page select is register 31 for phy address 1 and 22 for ++ /* Page select is register 31 for phy address 1 and 22 for + * phy address 2 and 3. Page select is shifted only for + * phy address 1. + */ +@@ -2462,15 +2392,15 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) + + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000e_write_phy_reg_mdic(hw, page_select, +- (page << page_shift)); ++ (page << page_shift)); + if (ret_val) +- goto out; ++ goto release; + } + + ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, +- data); ++ data); + +-out: ++release: + hw->phy.ops.release(hw); + return ret_val; + } +@@ -2498,7 +2428,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) + if (page == BM_WUC_PAGE) { + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, + true, false); +- goto out; ++ goto release; + } + + hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); +@@ -2506,8 +2436,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) + if (offset > MAX_PHY_MULTI_PAGE_REG) { + u32 page_shift, page_select; + +- /* +- * Page select is register 31 for phy address 1 and 22 for ++ /* Page select is register 31 for phy address 1 and 22 for + * phy address 2 and 3. Page select is shifted only for + * phy address 1. + */ +@@ -2521,14 +2450,14 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) + + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000e_write_phy_reg_mdic(hw, page_select, +- (page << page_shift)); ++ (page << page_shift)); + if (ret_val) +- goto out; ++ goto release; + } + + ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, +- data); +-out: ++ data); ++release: + hw->phy.ops.release(hw); + return ret_val; + } +@@ -2556,24 +2485,23 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) + if (page == BM_WUC_PAGE) { + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, + true, false); +- goto out; ++ goto release; + } + + hw->phy.addr = 1; + + if (offset > MAX_PHY_MULTI_PAGE_REG) { +- + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, + page); + + if (ret_val) +- goto out; ++ goto release; + } + + ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); +-out: ++release: + hw->phy.ops.release(hw); + return ret_val; + } +@@ -2600,7 +2528,7 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) + if (page == BM_WUC_PAGE) { + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, + false, false); +- goto out; ++ goto release; + } + + hw->phy.addr = 1; +@@ -2611,13 +2539,13 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) + page); + + if (ret_val) +- goto out; ++ goto release; + } + + ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); + +-out: ++release: + hw->phy.ops.release(hw); + return ret_val; + } +@@ -2642,18 +2570,17 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) + ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); + if (ret_val) { + e_dbg("Could not set Port Control page\n"); +- goto out; ++ return ret_val; + } + + ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); + if (ret_val) { + e_dbg("Could not read PHY register %d.%d\n", + BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); +- goto out; ++ return ret_val; + } + +- /* +- * Enable both PHY wakeup mode and Wakeup register page writes. ++ /* Enable both PHY wakeup mode and Wakeup register page writes. + * Prevent a power state change by disabling ME and Host PHY wakeup. + */ + temp = *phy_reg; +@@ -2664,15 +2591,13 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) + if (ret_val) { + e_dbg("Could not write PHY register %d.%d\n", + BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); +- goto out; ++ return ret_val; + } + +- /* Select Host Wakeup Registers page */ +- ret_val = e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT)); +- +- /* caller now able to write registers on the Wakeup registers page */ +-out: +- return ret_val; ++ /* Select Host Wakeup Registers page - caller now able to write ++ * registers on the Wakeup registers page ++ */ ++ return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT)); + } + + /** +@@ -2688,13 +2613,13 @@ out: + **/ + s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) + { +- s32 ret_val = 0; ++ s32 ret_val; + + /* Select Port Control Registers page */ + ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); + if (ret_val) { + e_dbg("Could not set Port Control page\n"); +- goto out; ++ return ret_val; + } + + /* Restore 769.17 to its original value */ +@@ -2702,7 +2627,7 @@ s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) + if (ret_val) + e_dbg("Could not restore PHY register %d.%d\n", + BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); +-out: ++ + return ret_val; + } + +@@ -2750,7 +2675,7 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, + ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg); + if (ret_val) { + e_dbg("Could not enable PHY wakeup reg access\n"); +- goto out; ++ return ret_val; + } + } + +@@ -2760,13 +2685,13 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, + ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); + if (ret_val) { + e_dbg("Could not write address opcode to page %d\n", page); +- goto out; ++ return ret_val; + } + + if (read) { + /* Read the Wakeup register page value using opcode 0x12 */ + ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, +- data); ++ data); + } else { + /* Write the Wakeup register page value using opcode 0x12 */ + ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, +@@ -2775,13 +2700,12 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, + + if (ret_val) { + e_dbg("Could not access PHY reg %d.%d\n", page, reg); +- goto out; ++ return ret_val; + } + + if (!page_set) + ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg); + +-out: + return ret_val; + } + +@@ -2798,9 +2722,9 @@ void e1000_power_up_phy_copper(struct e1000_hw *hw) + u16 mii_reg = 0; + + /* The PHY will retain its settings across a power down/up cycle */ +- e1e_rphy(hw, PHY_CONTROL, &mii_reg); +- mii_reg &= ~MII_CR_POWER_DOWN; +- e1e_wphy(hw, PHY_CONTROL, mii_reg); ++ e1e_rphy(hw, MII_BMCR, &mii_reg); ++ mii_reg &= ~BMCR_PDOWN; ++ e1e_wphy(hw, MII_BMCR, mii_reg); + } + + /** +@@ -2816,50 +2740,13 @@ void e1000_power_down_phy_copper(struct e1000_hw *hw) + u16 mii_reg = 0; + + /* The PHY will retain its settings across a power down/up cycle */ +- e1e_rphy(hw, PHY_CONTROL, &mii_reg); +- mii_reg |= MII_CR_POWER_DOWN; +- e1e_wphy(hw, PHY_CONTROL, mii_reg); ++ e1e_rphy(hw, MII_BMCR, &mii_reg); ++ mii_reg |= BMCR_PDOWN; ++ e1e_wphy(hw, MII_BMCR, mii_reg); + usleep_range(1000, 2000); + } + + /** +- * e1000e_commit_phy - Soft PHY reset +- * @hw: pointer to the HW structure +- * +- * Performs a soft PHY reset on those that apply. This is a function pointer +- * entry point called by drivers. +- **/ +-s32 e1000e_commit_phy(struct e1000_hw *hw) +-{ +- if (hw->phy.ops.commit) +- return hw->phy.ops.commit(hw); +- +- return 0; +-} +- +-/** +- * e1000_set_d0_lplu_state - Sets low power link up state for D0 +- * @hw: pointer to the HW structure +- * @active: boolean used to enable/disable lplu +- * +- * Success returns 0, Failure returns 1 +- * +- * The low power link up (lplu) state is set to the power management level D0 +- * and SmartSpeed is disabled when active is true, else clear lplu for D0 +- * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU +- * is used during Dx states where the power conservation is most important. +- * During driver activity, SmartSpeed should be enabled so performance is +- * maintained. This is a function pointer entry point called by drivers. +- **/ +-static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) +-{ +- if (hw->phy.ops.set_d0_lplu_state) +- return hw->phy.ops.set_d0_lplu_state(hw, active); +- +- return 0; +-} +- +-/** + * __e1000_read_phy_reg_hv - Read HV PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read +@@ -2893,7 +2780,7 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, + + if (page > 0 && page < HV_INTC_FC_PAGE_START) { + ret_val = e1000_access_phy_debug_regs_hv(hw, offset, +- data, true); ++ data, true); + goto out; + } + +@@ -2916,8 +2803,7 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, + e_dbg("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page, + page << IGP_PAGE_SHIFT, reg); + +- ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, +- data); ++ ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data); + out: + if (!locked) + hw->phy.ops.release(hw); +@@ -3001,7 +2887,7 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, + + if (page > 0 && page < HV_INTC_FC_PAGE_START) { + ret_val = e1000_access_phy_debug_regs_hv(hw, offset, +- &data, false); ++ &data, false); + goto out; + } + +@@ -3009,14 +2895,13 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, + if (page == HV_INTC_FC_PAGE_START) + page = 0; + +- /* +- * Workaround MDIO accesses being disabled after entering IEEE ++ /* Workaround MDIO accesses being disabled after entering IEEE + * Power Down (when bit 11 of the PHY Control register is set) + */ + if ((hw->phy.type == e1000_phy_82578) && + (hw->phy.revision >= 1) && + (hw->phy.addr == 2) && +- ((MAX_PHY_REG_ADDRESS & reg) == 0) && (data & (1 << 11))) { ++ !(MAX_PHY_REG_ADDRESS & reg) && (data & (1 << 11))) { + u16 data2 = 0x7EFF; + ret_val = e1000_access_phy_debug_regs_hv(hw, + (1 << 6) | 0x3, +@@ -3041,7 +2926,7 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, + page << IGP_PAGE_SHIFT, reg); + + ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, +- data); ++ data); + + out: + if (!locked) +@@ -3119,15 +3004,15 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page) + * These accesses done with PHY address 2 and without using pages. + **/ + static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, +- u16 *data, bool read) ++ u16 *data, bool read) + { + s32 ret_val; +- u32 addr_reg = 0; +- u32 data_reg = 0; ++ u32 addr_reg; ++ u32 data_reg; + + /* This takes care of the difference with desktop vs mobile phy */ +- addr_reg = (hw->phy.type == e1000_phy_82578) ? +- I82578_ADDR_REG : I82577_ADDR_REG; ++ addr_reg = ((hw->phy.type == e1000_phy_82578) ? ++ I82578_ADDR_REG : I82577_ADDR_REG); + data_reg = addr_reg + 1; + + /* All operations in this function are phy address 2 */ +@@ -3137,7 +3022,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, + ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F); + if (ret_val) { + e_dbg("Could not write the Address Offset port register\n"); +- goto out; ++ return ret_val; + } + + /* Read or write the data value next */ +@@ -3146,12 +3031,9 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, + else + ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data); + +- if (ret_val) { ++ if (ret_val) + e_dbg("Could not access the Data port register\n"); +- goto out; +- } + +-out: + return ret_val; + } + +@@ -3172,39 +3054,35 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw) + u16 data; + + if (hw->phy.type != e1000_phy_82578) +- goto out; ++ return 0; + + /* Do not apply workaround if in PHY loopback bit 14 set */ +- e1e_rphy(hw, PHY_CONTROL, &data); +- if (data & PHY_CONTROL_LB) +- goto out; ++ e1e_rphy(hw, MII_BMCR, &data); ++ if (data & BMCR_LOOPBACK) ++ return 0; + + /* check if link is up and at 1Gbps */ + ret_val = e1e_rphy(hw, BM_CS_STATUS, &data); + if (ret_val) +- goto out; ++ return ret_val; + +- data &= BM_CS_STATUS_LINK_UP | +- BM_CS_STATUS_RESOLVED | +- BM_CS_STATUS_SPEED_MASK; ++ data &= (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED | ++ BM_CS_STATUS_SPEED_MASK); + +- if (data != (BM_CS_STATUS_LINK_UP | +- BM_CS_STATUS_RESOLVED | +- BM_CS_STATUS_SPEED_1000)) +- goto out; ++ if (data != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED | ++ BM_CS_STATUS_SPEED_1000)) ++ return 0; + +- mdelay(200); ++ msleep(200); + + /* flush the packets in the fifo buffer */ +- ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC | +- HV_MUX_DATA_CTRL_FORCE_SPEED); ++ ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, ++ (HV_MUX_DATA_CTRL_GEN_TO_MAC | ++ HV_MUX_DATA_CTRL_FORCE_SPEED)); + if (ret_val) +- goto out; +- +- ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC); ++ return ret_val; + +-out: +- return ret_val; ++ return e1e_wphy(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC); + } + + /** +@@ -3224,9 +3102,9 @@ s32 e1000_check_polarity_82577(struct e1000_hw *hw) + ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data); + + if (!ret_val) +- phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY) +- ? e1000_rev_polarity_reversed +- : e1000_rev_polarity_normal; ++ phy->cable_polarity = ((data & I82577_PHY_STATUS2_REV_POLARITY) ++ ? e1000_rev_polarity_reversed ++ : e1000_rev_polarity_normal); + + return ret_val; + } +@@ -3244,41 +3122,34 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw) + u16 phy_data; + bool link; + +- ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); ++ ret_val = e1e_rphy(hw, MII_BMCR, &phy_data); + if (ret_val) +- goto out; ++ return ret_val; + + e1000e_phy_force_speed_duplex_setup(hw, &phy_data); + +- ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); ++ ret_val = e1e_wphy(hw, MII_BMCR, phy_data); + if (ret_val) +- goto out; ++ return ret_val; + + udelay(1); + + if (phy->autoneg_wait_to_complete) { + e_dbg("Waiting for forced speed/duplex link on 82577 phy\n"); + +- ret_val = e1000e_phy_has_link_generic(hw, +- PHY_FORCE_LIMIT, +- 100000, +- &link); ++ ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, ++ 100000, &link); + if (ret_val) +- goto out; ++ return ret_val; + + if (!link) + e_dbg("Link taking longer than expected.\n"); + + /* Try once more */ +- ret_val = e1000e_phy_has_link_generic(hw, +- PHY_FORCE_LIMIT, +- 100000, +- &link); +- if (ret_val) +- goto out; ++ ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, ++ 100000, &link); + } + +-out: + return ret_val; + } + +@@ -3300,51 +3171,47 @@ s32 e1000_get_phy_info_82577(struct e1000_hw *hw) + + ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) +- goto out; ++ return ret_val; + + if (!link) { + e_dbg("Phy info is only valid if link is up\n"); +- ret_val = -E1000_ERR_CONFIG; +- goto out; ++ return -E1000_ERR_CONFIG; + } + + phy->polarity_correction = true; + + ret_val = e1000_check_polarity_82577(hw); + if (ret_val) +- goto out; ++ return ret_val; + + ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data); + if (ret_val) +- goto out; ++ return ret_val; + +- phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? true : false; ++ phy->is_mdix = !!(data & I82577_PHY_STATUS2_MDIX); + + if ((data & I82577_PHY_STATUS2_SPEED_MASK) == + I82577_PHY_STATUS2_SPEED_1000MBPS) { + ret_val = hw->phy.ops.get_cable_length(hw); + if (ret_val) +- goto out; ++ return ret_val; + +- ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &data); ++ ret_val = e1e_rphy(hw, MII_STAT1000, &data); + if (ret_val) +- goto out; ++ return ret_val; + +- phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) +- ? e1000_1000t_rx_status_ok +- : e1000_1000t_rx_status_not_ok; ++ phy->local_rx = (data & LPA_1000LOCALRXOK) ++ ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; + +- phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) +- ? e1000_1000t_rx_status_ok +- : e1000_1000t_rx_status_not_ok; ++ phy->remote_rx = (data & LPA_1000REMRXOK) ++ ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; + } else { + phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; + phy->local_rx = e1000_1000t_rx_status_undefined; + phy->remote_rx = e1000_1000t_rx_status_undefined; + } + +-out: +- return ret_val; ++ return 0; + } + + /** +@@ -3362,16 +3229,15 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw) + + ret_val = e1e_rphy(hw, I82577_PHY_DIAG_STATUS, &phy_data); + if (ret_val) +- goto out; ++ return ret_val; + +- length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >> +- I82577_DSTATUS_CABLE_LENGTH_SHIFT; ++ length = ((phy_data & I82577_DSTATUS_CABLE_LENGTH) >> ++ I82577_DSTATUS_CABLE_LENGTH_SHIFT); + + if (length == E1000_CABLE_LENGTH_UNDEFINED) +- ret_val = -E1000_ERR_PHY; ++ return -E1000_ERR_PHY; + + phy->cable_length = length; + +-out: +- return ret_val; ++ return 0; + } +diff --git a/drivers/net/ethernet/intel/e1000e/phy.h b/drivers/net/ethernet/intel/e1000e/phy.h +new file mode 100644 +index 0000000..f4f71b9 +--- /dev/null ++++ b/drivers/net/ethernet/intel/e1000e/phy.h +@@ -0,0 +1,242 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#ifndef _E1000E_PHY_H_ ++#define _E1000E_PHY_H_ ++ ++s32 e1000e_check_downshift(struct e1000_hw *hw); ++s32 e1000_check_polarity_m88(struct e1000_hw *hw); ++s32 e1000_check_polarity_igp(struct e1000_hw *hw); ++s32 e1000_check_polarity_ife(struct e1000_hw *hw); ++s32 e1000e_check_reset_block_generic(struct e1000_hw *hw); ++s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw); ++s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw); ++s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw); ++s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw); ++s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); ++s32 e1000e_get_cable_length_m88(struct e1000_hw *hw); ++s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw); ++s32 e1000e_get_cfg_done_generic(struct e1000_hw *hw); ++s32 e1000e_get_phy_id(struct e1000_hw *hw); ++s32 e1000e_get_phy_info_igp(struct e1000_hw *hw); ++s32 e1000e_get_phy_info_m88(struct e1000_hw *hw); ++s32 e1000_get_phy_info_ife(struct e1000_hw *hw); ++s32 e1000e_phy_sw_reset(struct e1000_hw *hw); ++void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); ++s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw); ++s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); ++s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page); ++s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active); ++s32 e1000e_setup_copper_link(struct e1000_hw *hw); ++s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, ++ u32 usec_interval, bool *success); ++s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw); ++enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id); ++s32 e1000e_determine_phy_address(struct e1000_hw *hw); ++s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg); ++s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg); ++s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data); ++void e1000_power_up_phy_copper(struct e1000_hw *hw); ++void e1000_power_down_phy_copper(struct e1000_hw *hw); ++s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data); ++s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw); ++s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); ++s32 e1000_check_polarity_82577(struct e1000_hw *hw); ++s32 e1000_get_phy_info_82577(struct e1000_hw *hw); ++s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw); ++s32 e1000_get_cable_length_82577(struct e1000_hw *hw); ++ ++#define E1000_MAX_PHY_ADDR 8 ++ ++/* IGP01E1000 Specific Registers */ ++#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ ++#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */ ++#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ ++#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ ++#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ ++#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ ++#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ ++#define IGP_PAGE_SHIFT 5 ++#define PHY_REG_MASK 0x1F ++ ++/* BM/HV Specific Registers */ ++#define BM_PORT_CTRL_PAGE 769 ++#define BM_WUC_PAGE 800 ++#define BM_WUC_ADDRESS_OPCODE 0x11 ++#define BM_WUC_DATA_OPCODE 0x12 ++#define BM_WUC_ENABLE_PAGE BM_PORT_CTRL_PAGE ++#define BM_WUC_ENABLE_REG 17 ++#define BM_WUC_ENABLE_BIT (1 << 2) ++#define BM_WUC_HOST_WU_BIT (1 << 4) ++#define BM_WUC_ME_WU_BIT (1 << 5) ++ ++#define PHY_UPPER_SHIFT 21 ++#define BM_PHY_REG(page, reg) \ ++ (((reg) & MAX_PHY_REG_ADDRESS) |\ ++ (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\ ++ (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT))) ++#define BM_PHY_REG_PAGE(offset) \ ++ ((u16)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF)) ++#define BM_PHY_REG_NUM(offset) \ ++ ((u16)(((offset) & MAX_PHY_REG_ADDRESS) |\ ++ (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\ ++ ~MAX_PHY_REG_ADDRESS))) ++ ++#define HV_INTC_FC_PAGE_START 768 ++#define I82578_ADDR_REG 29 ++#define I82577_ADDR_REG 16 ++#define I82577_CFG_REG 22 ++#define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15) ++#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift */ ++#define I82577_CTRL_REG 23 ++ ++/* 82577 specific PHY registers */ ++#define I82577_PHY_CTRL_2 18 ++#define I82577_PHY_LBK_CTRL 19 ++#define I82577_PHY_STATUS_2 26 ++#define I82577_PHY_DIAG_STATUS 31 ++ ++/* I82577 PHY Status 2 */ ++#define I82577_PHY_STATUS2_REV_POLARITY 0x0400 ++#define I82577_PHY_STATUS2_MDIX 0x0800 ++#define I82577_PHY_STATUS2_SPEED_MASK 0x0300 ++#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 ++ ++/* I82577 PHY Control 2 */ ++#define I82577_PHY_CTRL2_MANUAL_MDIX 0x0200 ++#define I82577_PHY_CTRL2_AUTO_MDI_MDIX 0x0400 ++#define I82577_PHY_CTRL2_MDIX_CFG_MASK 0x0600 ++ ++/* I82577 PHY Diagnostics Status */ ++#define I82577_DSTATUS_CABLE_LENGTH 0x03FC ++#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2 ++ ++/* BM PHY Copper Specific Control 1 */ ++#define BM_CS_CTRL1 16 ++ ++/* BM PHY Copper Specific Status */ ++#define BM_CS_STATUS 17 ++#define BM_CS_STATUS_LINK_UP 0x0400 ++#define BM_CS_STATUS_RESOLVED 0x0800 ++#define BM_CS_STATUS_SPEED_MASK 0xC000 ++#define BM_CS_STATUS_SPEED_1000 0x8000 ++ ++/* 82577 Mobile Phy Status Register */ ++#define HV_M_STATUS 26 ++#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 ++#define HV_M_STATUS_SPEED_MASK 0x0300 ++#define HV_M_STATUS_SPEED_1000 0x0200 ++#define HV_M_STATUS_LINK_UP 0x0040 ++ ++#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 ++#define IGP01E1000_PHY_POLARITY_MASK 0x0078 ++ ++#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 ++#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ ++ ++#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 ++ ++#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ ++#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ ++#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ ++ ++#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 ++ ++#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 ++#define IGP01E1000_PSSR_MDIX 0x0800 ++#define IGP01E1000_PSSR_SPEED_MASK 0xC000 ++#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 ++ ++#define IGP02E1000_PHY_CHANNEL_NUM 4 ++#define IGP02E1000_PHY_AGC_A 0x11B1 ++#define IGP02E1000_PHY_AGC_B 0x12B1 ++#define IGP02E1000_PHY_AGC_C 0x14B1 ++#define IGP02E1000_PHY_AGC_D 0x18B1 ++ ++#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course=15:13, Fine=12:9 */ ++#define IGP02E1000_AGC_LENGTH_MASK 0x7F ++#define IGP02E1000_AGC_RANGE 15 ++ ++#define E1000_CABLE_LENGTH_UNDEFINED 0xFF ++ ++#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 ++#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 ++#define E1000_KMRNCTRLSTA_REN 0x00200000 ++#define E1000_KMRNCTRLSTA_CTRL_OFFSET 0x1 /* Kumeran Control */ ++#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ ++#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ ++#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ ++#define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */ ++#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ ++#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 ++#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002 /* enable K1 */ ++#define E1000_KMRNCTRLSTA_HD_CTRL 0x10 /* Kumeran HD Control */ ++ ++#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 ++#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Ctrl */ ++#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Ctrl */ ++#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */ ++ ++/* IFE PHY Extended Status Control */ ++#define IFE_PESC_POLARITY_REVERSED 0x0100 ++ ++/* IFE PHY Special Control */ ++#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 ++#define IFE_PSC_FORCE_POLARITY 0x0020 ++ ++/* IFE PHY Special Control and LED Control */ ++#define IFE_PSCL_PROBE_MODE 0x0020 ++#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ ++#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ ++ ++/* IFE PHY MDIX Control */ ++#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ ++#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */ ++#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto, 0=disable */ ++ ++#endif +diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c +new file mode 100644 +index 0000000..0e4a7b0 +--- /dev/null ++++ b/drivers/net/ethernet/intel/e1000e/ptp.c +@@ -0,0 +1,277 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++/* PTP 1588 Hardware Clock (PHC) ++ * Derived from PTP Hardware Clock driver for Intel 82576 and 82580 (igb) ++ * Copyright (C) 2011 Richard Cochran ++ */ ++ ++#include ++ ++#include "e1000.h" ++ ++/** ++ * e1000e_phc_adjfreq - adjust the frequency of the hardware clock ++ * @ptp: ptp clock structure ++ * @delta: Desired frequency change in parts per billion ++ * ++ * Adjust the frequency of the PHC cycle counter by the indicated delta from ++ * the base frequency. ++ **/ ++static int e1000e_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) ++{ ++ struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, ++ ptp_clock_info); ++ struct e1000_hw *hw = &adapter->hw; ++ bool neg_adj = false; ++ u64 adjustment; ++ u32 timinca, incvalue; ++ s32 ret_val; ++ ++ if ((delta > ptp->max_adj) || (delta <= -1000000000)) ++ return -EINVAL; ++ ++ if (delta < 0) { ++ neg_adj = true; ++ delta = -delta; ++ } ++ ++ /* Get the System Time Register SYSTIM base frequency */ ++ ret_val = e1000e_get_base_timinca(adapter, &timinca); ++ if (ret_val) ++ return ret_val; ++ ++ incvalue = timinca & E1000_TIMINCA_INCVALUE_MASK; ++ ++ adjustment = incvalue; ++ adjustment *= delta; ++ adjustment = div_u64(adjustment, 1000000000); ++ ++ incvalue = neg_adj ? (incvalue - adjustment) : (incvalue + adjustment); ++ ++ timinca &= ~E1000_TIMINCA_INCVALUE_MASK; ++ timinca |= incvalue; ++ ++ ew32(TIMINCA, timinca); ++ ++ return 0; ++} ++ ++/** ++ * e1000e_phc_adjtime - Shift the time of the hardware clock ++ * @ptp: ptp clock structure ++ * @delta: Desired change in nanoseconds ++ * ++ * Adjust the timer by resetting the timecounter structure. ++ **/ ++static int e1000e_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) ++{ ++ struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, ++ ptp_clock_info); ++ unsigned long flags; ++ s64 now; ++ ++ spin_lock_irqsave(&adapter->systim_lock, flags); ++ now = timecounter_read(&adapter->tc); ++ now += delta; ++ timecounter_init(&adapter->tc, &adapter->cc, now); ++ spin_unlock_irqrestore(&adapter->systim_lock, flags); ++ ++ return 0; ++} ++ ++/** ++ * e1000e_phc_gettime - Reads the current time from the hardware clock ++ * @ptp: ptp clock structure ++ * @ts: timespec structure to hold the current time value ++ * ++ * Read the timecounter and return the correct value in ns after converting ++ * it into a struct timespec. ++ **/ ++static int e1000e_phc_gettime(struct ptp_clock_info *ptp, struct timespec *ts) ++{ ++ struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, ++ ptp_clock_info); ++ unsigned long flags; ++ u32 remainder; ++ u64 ns; ++ ++ spin_lock_irqsave(&adapter->systim_lock, flags); ++ ns = timecounter_read(&adapter->tc); ++ spin_unlock_irqrestore(&adapter->systim_lock, flags); ++ ++ ts->tv_sec = div_u64_rem(ns, NSEC_PER_SEC, &remainder); ++ ts->tv_nsec = remainder; ++ ++ return 0; ++} ++ ++/** ++ * e1000e_phc_settime - Set the current time on the hardware clock ++ * @ptp: ptp clock structure ++ * @ts: timespec containing the new time for the cycle counter ++ * ++ * Reset the timecounter to use a new base value instead of the kernel ++ * wall timer value. ++ **/ ++static int e1000e_phc_settime(struct ptp_clock_info *ptp, ++ const struct timespec *ts) ++{ ++ struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, ++ ptp_clock_info); ++ unsigned long flags; ++ u64 ns; ++ ++ ns = timespec_to_ns(ts); ++ ++ /* reset the timecounter */ ++ spin_lock_irqsave(&adapter->systim_lock, flags); ++ timecounter_init(&adapter->tc, &adapter->cc, ns); ++ spin_unlock_irqrestore(&adapter->systim_lock, flags); ++ ++ return 0; ++} ++ ++/** ++ * e1000e_phc_enable - enable or disable an ancillary feature ++ * @ptp: ptp clock structure ++ * @request: Desired resource to enable or disable ++ * @on: Caller passes one to enable or zero to disable ++ * ++ * Enable (or disable) ancillary features of the PHC subsystem. ++ * Currently, no ancillary features are supported. ++ **/ ++static int e1000e_phc_enable(struct ptp_clock_info __always_unused *ptp, ++ struct ptp_clock_request __always_unused *request, ++ int __always_unused on) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static void e1000e_systim_overflow_work(struct work_struct *work) ++{ ++ struct e1000_adapter *adapter = container_of(work, struct e1000_adapter, ++ systim_overflow_work.work); ++ struct e1000_hw *hw = &adapter->hw; ++ struct timespec ts; ++ ++ adapter->ptp_clock_info.gettime(&adapter->ptp_clock_info, &ts); ++ ++ e_dbg("SYSTIM overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec); ++ ++ schedule_delayed_work(&adapter->systim_overflow_work, ++ E1000_SYSTIM_OVERFLOW_PERIOD); ++} ++ ++static const struct ptp_clock_info e1000e_ptp_clock_info = { ++ .owner = THIS_MODULE, ++ .n_alarm = 0, ++ .n_ext_ts = 0, ++ .n_per_out = 0, ++ .pps = 0, ++ .adjfreq = e1000e_phc_adjfreq, ++ .adjtime = e1000e_phc_adjtime, ++ .gettime = e1000e_phc_gettime, ++ .settime = e1000e_phc_settime, ++ .enable = e1000e_phc_enable, ++}; ++ ++/** ++ * e1000e_ptp_init - initialize PTP for devices which support it ++ * @adapter: board private structure ++ * ++ * This function performs the required steps for enabling PTP support. ++ * If PTP support has already been loaded it simply calls the cyclecounter ++ * init routine and exits. ++ **/ ++void e1000e_ptp_init(struct e1000_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ ++ adapter->ptp_clock = NULL; ++ ++ if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP)) ++ return; ++ ++ adapter->ptp_clock_info = e1000e_ptp_clock_info; ++ ++ snprintf(adapter->ptp_clock_info.name, ++ sizeof(adapter->ptp_clock_info.name), "%pm", ++ adapter->netdev->perm_addr); ++ ++ switch (hw->mac.type) { ++ case e1000_pch2lan: ++ case e1000_pch_lpt: ++ if ((hw->mac.type != e1000_pch_lpt) || ++ (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) { ++ adapter->ptp_clock_info.max_adj = 24000000 - 1; ++ break; ++ } ++ /* fall-through */ ++ case e1000_82574: ++ case e1000_82583: ++ adapter->ptp_clock_info.max_adj = 600000000 - 1; ++ break; ++ default: ++ break; ++ } ++ ++ INIT_DELAYED_WORK(&adapter->systim_overflow_work, ++ e1000e_systim_overflow_work); ++ ++ schedule_delayed_work(&adapter->systim_overflow_work, ++ E1000_SYSTIM_OVERFLOW_PERIOD); ++ ++ adapter->ptp_clock = ptp_clock_register(&adapter->ptp_clock_info); ++ if (IS_ERR(adapter->ptp_clock)) { ++ adapter->ptp_clock = NULL; ++ e_err("ptp_clock_register failed\n"); ++ } else { ++ e_info("registered PHC clock\n"); ++ } ++} ++ ++/** ++ * e1000e_ptp_remove - disable PTP device and stop the overflow check ++ * @adapter: board private structure ++ * ++ * Stop the PTP support, and cancel the delayed work. ++ **/ ++void e1000e_ptp_remove(struct e1000_adapter *adapter) ++{ ++ if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP)) ++ return; ++ ++ cancel_delayed_work_sync(&adapter->systim_overflow_work); ++ ++ if (adapter->ptp_clock) { ++ ptp_clock_unregister(adapter->ptp_clock); ++ adapter->ptp_clock = NULL; ++ e_info("removed PHC\n"); ++ } ++} +diff --git a/drivers/net/ethernet/intel/e1000e/regs.h b/drivers/net/ethernet/intel/e1000e/regs.h +new file mode 100644 +index 0000000..a7e6a3e +--- /dev/null ++++ b/drivers/net/ethernet/intel/e1000e/regs.h +@@ -0,0 +1,253 @@ ++/******************************************************************************* ++ ++ Intel PRO/1000 Linux driver ++ Copyright(c) 1999 - 2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ Linux NICS ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#ifndef _E1000E_REGS_H_ ++#define _E1000E_REGS_H_ ++ ++#define E1000_CTRL 0x00000 /* Device Control - RW */ ++#define E1000_STATUS 0x00008 /* Device Status - RO */ ++#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ ++#define E1000_EERD 0x00014 /* EEPROM Read - RW */ ++#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ ++#define E1000_FLA 0x0001C /* Flash Access - RW */ ++#define E1000_MDIC 0x00020 /* MDI Control - RW */ ++#define E1000_SCTL 0x00024 /* SerDes Control - RW */ ++#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ ++#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ ++#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ ++#define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */ ++#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ ++#define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */ ++#define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */ ++#define E1000_FCT 0x00030 /* Flow Control Type - RW */ ++#define E1000_VET 0x00038 /* VLAN Ether Type - RW */ ++#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ ++#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ ++#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ ++#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ ++#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ ++#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ ++#define E1000_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */ ++#define E1000_SVCR 0x000F0 ++#define E1000_SVT 0x000F4 ++#define E1000_LPIC 0x000FC /* Low Power IDLE control */ ++#define E1000_RCTL 0x00100 /* Rx Control - RW */ ++#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ ++#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */ ++#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */ ++#define E1000_PBA_ECC 0x01100 /* PBA ECC Register */ ++#define E1000_TCTL 0x00400 /* Tx Control - RW */ ++#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */ ++#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */ ++#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ ++#define E1000_LEDCTL 0x00E00 /* LED Control - RW */ ++#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */ ++#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */ ++#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */ ++#define E1000_POEMB E1000_PHY_CTRL /* PHY OEM Bits */ ++#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ ++#define E1000_PBS 0x01008 /* Packet Buffer Size */ ++#define E1000_PBECCSTS 0x0100C /* Packet Buffer ECC Status - RW */ ++#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ ++#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ ++#define E1000_FLOP 0x0103C /* FLASH Opcode Register */ ++#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ ++#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ ++#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ ++#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ ++#define E1000_RDFH 0x02410 /* Rx Data FIFO Head - RW */ ++#define E1000_RDFT 0x02418 /* Rx Data FIFO Tail - RW */ ++#define E1000_RDFHS 0x02420 /* Rx Data FIFO Head Saved - RW */ ++#define E1000_RDFTS 0x02428 /* Rx Data FIFO Tail Saved - RW */ ++#define E1000_RDFPC 0x02430 /* Rx Data FIFO Packet Count - RW */ ++/* Split and Replication Rx Control - RW */ ++#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */ ++#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */ ++/* Convenience macros ++ * ++ * Note: "_n" is the queue number of the register to be written to. ++ * ++ * Example usage: ++ * E1000_RDBAL_REG(current_rx_queue) ++ */ ++#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \ ++ (0x0C000 + ((_n) * 0x40))) ++#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \ ++ (0x0C004 + ((_n) * 0x40))) ++#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \ ++ (0x0C008 + ((_n) * 0x40))) ++#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \ ++ (0x0C010 + ((_n) * 0x40))) ++#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \ ++ (0x0C018 + ((_n) * 0x40))) ++#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \ ++ (0x0C028 + ((_n) * 0x40))) ++#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \ ++ (0x0E000 + ((_n) * 0x40))) ++#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \ ++ (0x0E004 + ((_n) * 0x40))) ++#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \ ++ (0x0E008 + ((_n) * 0x40))) ++#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \ ++ (0x0E010 + ((_n) * 0x40))) ++#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \ ++ (0x0E018 + ((_n) * 0x40))) ++#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \ ++ (0x0E028 + ((_n) * 0x40))) ++#define E1000_TARC(_n) (0x03840 + ((_n) * 0x100)) ++#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */ ++#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \ ++ (0x054E0 + ((_i - 16) * 8))) ++#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \ ++ (0x054E4 + ((_i - 16) * 8))) ++#define E1000_SHRAL(_i) (0x05438 + ((_i) * 8)) ++#define E1000_SHRAH(_i) (0x0543C + ((_i) * 8)) ++#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ ++#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ ++#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ ++#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */ ++#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */ ++#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */ ++#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */ ++#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ ++#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ ++#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ ++#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ ++#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ ++#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ ++#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ ++#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ ++#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ ++#define E1000_COLC 0x04028 /* Collision Count - R/clr */ ++#define E1000_DC 0x04030 /* Defer Count - R/clr */ ++#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */ ++#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ ++#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ ++#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ ++#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */ ++#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */ ++#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */ ++#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */ ++#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */ ++#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */ ++#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */ ++#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */ ++#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */ ++#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */ ++#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */ ++#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */ ++#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */ ++#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */ ++#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */ ++#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */ ++#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */ ++#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */ ++#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */ ++#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */ ++#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */ ++#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */ ++#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */ ++#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */ ++#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */ ++#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ ++#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */ ++#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */ ++#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */ ++#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */ ++#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */ ++#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */ ++#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */ ++#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */ ++#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */ ++#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */ ++#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */ ++#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */ ++#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */ ++#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */ ++#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */ ++#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */ ++#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */ ++#define E1000_IAC 0x04100 /* Interrupt Assertion Count */ ++#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */ ++#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */ ++#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */ ++#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */ ++#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */ ++#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */ ++#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */ ++#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */ ++#define E1000_CRC_OFFSET 0x05F50 /* CRC Offset register */ ++ ++#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */ ++#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */ ++#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */ ++#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */ ++#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */ ++#define E1000_RFCTL 0x05008 /* Receive Filter Control */ ++#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ ++#define E1000_RA 0x05400 /* Receive Address - RW Array */ ++#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ ++#define E1000_WUC 0x05800 /* Wakeup Control - RW */ ++#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ ++#define E1000_WUS 0x05810 /* Wakeup Status - RO */ ++#define E1000_MANC 0x05820 /* Management Control - RW */ ++#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ ++#define E1000_HOST_IF 0x08800 /* Host Interface */ ++ ++#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */ ++#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ ++/* Management Decision Filters */ ++#define E1000_MDEF(_n) (0x05890 + (4 * (_n))) ++#define E1000_SW_FW_SYNC 0x05B5C /* SW-FW Synchronization - RW */ ++#define E1000_GCR 0x05B00 /* PCI-Ex Control */ ++#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */ ++#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ ++#define E1000_SWSM 0x05B50 /* SW Semaphore */ ++#define E1000_FWSM 0x05B54 /* FW Semaphore */ ++/* Driver-only SW semaphore (not used by BOOT agents) */ ++#define E1000_SWSM2 0x05B58 ++#define E1000_FFLT_DBG 0x05F04 /* Debug Register */ ++#define E1000_HICR 0x08F00 /* Host Interface Control */ ++ ++/* RSS registers */ ++#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */ ++#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */ ++#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */ ++#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */ ++#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */ ++#define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */ ++#define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */ ++#define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */ ++#define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */ ++#define E1000_SYSTIML 0x0B600 /* System time register Low - RO */ ++#define E1000_SYSTIMH 0x0B604 /* System time register High - RO */ ++#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */ ++#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */ ++#define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */ ++ ++#endif +diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile +index c6e4621..2bb560f 100644 +--- a/drivers/net/ethernet/intel/igb/Makefile ++++ b/drivers/net/ethernet/intel/igb/Makefile +@@ -1,7 +1,7 @@ + ################################################################################ + # + # Intel 82575 PCI-Express Ethernet Linux driver +-# Copyright(c) 1999 - 2011 Intel Corporation. ++# Copyright(c) 1999 - 2013 Intel Corporation. + # + # This program is free software; you can redistribute it and/or modify it + # under the terms and conditions of the GNU General Public License, +@@ -33,5 +33,7 @@ + obj-$(CONFIG_IGB) += igb.o + + igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \ +- e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o ++ e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \ ++ e1000_i210.o igb_hwmon.o + ++igb-$(CONFIG_IGB_PTP) += igb_ptp.o +diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c +index 7881fb9..d05abb2 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_82575.c ++++ b/drivers/net/ethernet/intel/igb/e1000_82575.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -29,11 +29,15 @@ + * e1000_82576 + */ + ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ + #include + #include ++#include + + #include "e1000_mac.h" + #include "e1000_82575.h" ++#include "e1000_i210.h" + + static s32 igb_get_invariants_82575(struct e1000_hw *); + static s32 igb_acquire_phy_82575(struct e1000_hw *); +@@ -50,6 +54,8 @@ static s32 igb_write_phy_reg_82580(struct e1000_hw *, u32, u16); + static s32 igb_reset_hw_82575(struct e1000_hw *); + static s32 igb_reset_hw_82580(struct e1000_hw *); + static s32 igb_set_d0_lplu_state_82575(struct e1000_hw *, bool); ++static s32 igb_set_d0_lplu_state_82580(struct e1000_hw *, bool); ++static s32 igb_set_d3_lplu_state_82580(struct e1000_hw *, bool); + static s32 igb_setup_copper_link_82575(struct e1000_hw *); + static s32 igb_setup_serdes_link_82575(struct e1000_hw *); + static s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16); +@@ -94,6 +100,9 @@ static bool igb_sgmii_uses_mdio_82575(struct e1000_hw *hw) + break; + case e1000_82580: + case e1000_i350: ++ case e1000_i354: ++ case e1000_i210: ++ case e1000_i211: + reg = rd32(E1000_MDICNFG); + ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO); + break; +@@ -103,267 +112,501 @@ static bool igb_sgmii_uses_mdio_82575(struct e1000_hw *hw) + return ext_mdio; + } + +-static s32 igb_get_invariants_82575(struct e1000_hw *hw) ++/** ++ * igb_init_phy_params_82575 - Init PHY func ptrs. ++ * @hw: pointer to the HW structure ++ **/ ++static s32 igb_init_phy_params_82575(struct e1000_hw *hw) + { + struct e1000_phy_info *phy = &hw->phy; +- struct e1000_nvm_info *nvm = &hw->nvm; +- struct e1000_mac_info *mac = &hw->mac; +- struct e1000_dev_spec_82575 * dev_spec = &hw->dev_spec._82575; +- u32 eecd; +- s32 ret_val; +- u16 size; +- u32 ctrl_ext = 0; ++ s32 ret_val = 0; ++ u32 ctrl_ext; + +- switch (hw->device_id) { +- case E1000_DEV_ID_82575EB_COPPER: +- case E1000_DEV_ID_82575EB_FIBER_SERDES: +- case E1000_DEV_ID_82575GB_QUAD_COPPER: +- mac->type = e1000_82575; +- break; +- case E1000_DEV_ID_82576: +- case E1000_DEV_ID_82576_NS: +- case E1000_DEV_ID_82576_NS_SERDES: +- case E1000_DEV_ID_82576_FIBER: +- case E1000_DEV_ID_82576_SERDES: +- case E1000_DEV_ID_82576_QUAD_COPPER: +- case E1000_DEV_ID_82576_QUAD_COPPER_ET2: +- case E1000_DEV_ID_82576_SERDES_QUAD: +- mac->type = e1000_82576; +- break; +- case E1000_DEV_ID_82580_COPPER: +- case E1000_DEV_ID_82580_FIBER: +- case E1000_DEV_ID_82580_QUAD_FIBER: +- case E1000_DEV_ID_82580_SERDES: +- case E1000_DEV_ID_82580_SGMII: +- case E1000_DEV_ID_82580_COPPER_DUAL: +- case E1000_DEV_ID_DH89XXCC_SGMII: +- case E1000_DEV_ID_DH89XXCC_SERDES: +- case E1000_DEV_ID_DH89XXCC_BACKPLANE: +- case E1000_DEV_ID_DH89XXCC_SFP: +- mac->type = e1000_82580; +- break; +- case E1000_DEV_ID_I350_COPPER: +- case E1000_DEV_ID_I350_FIBER: +- case E1000_DEV_ID_I350_SERDES: +- case E1000_DEV_ID_I350_SGMII: +- mac->type = e1000_i350; +- break; +- default: +- return -E1000_ERR_MAC_INIT; +- break; ++ if (hw->phy.media_type != e1000_media_type_copper) { ++ phy->type = e1000_phy_none; ++ goto out; + } + +- /* Set media type */ +- /* +- * The 82575 uses bits 22:23 for link mode. The mode can be changed +- * based on the EEPROM. We cannot rely upon device ID. There +- * is no distinguishable difference between fiber and internal +- * SerDes mode on the 82575. There can be an external PHY attached +- * on the SGMII interface. For this, we'll set sgmii_active to true. +- */ +- phy->media_type = e1000_media_type_copper; +- dev_spec->sgmii_active = false; ++ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; ++ phy->reset_delay_us = 100; + + ctrl_ext = rd32(E1000_CTRL_EXT); +- switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) { +- case E1000_CTRL_EXT_LINK_MODE_SGMII: +- dev_spec->sgmii_active = true; +- break; +- case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: +- case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: +- hw->phy.media_type = e1000_media_type_internal_serdes; +- break; +- default: +- break; ++ ++ if (igb_sgmii_active_82575(hw)) { ++ if(phy->type == e1000_phy_bcm5461s) ++ phy->ops.reset = igb_phy_hw_reset; ++ else ++ phy->ops.reset = igb_phy_hw_reset_sgmii_82575; ++ ctrl_ext |= E1000_CTRL_I2C_ENA; ++ } else { ++ phy->ops.reset = igb_phy_hw_reset; ++ ctrl_ext &= ~E1000_CTRL_I2C_ENA; + } + +- /* Set mta register count */ +- mac->mta_reg_count = 128; +- /* Set rar entry count */ +- mac->rar_entry_count = E1000_RAR_ENTRIES_82575; +- if (mac->type == e1000_82576) +- mac->rar_entry_count = E1000_RAR_ENTRIES_82576; +- if (mac->type == e1000_82580) +- mac->rar_entry_count = E1000_RAR_ENTRIES_82580; +- if (mac->type == e1000_i350) +- mac->rar_entry_count = E1000_RAR_ENTRIES_I350; +- /* reset */ +- if (mac->type >= e1000_82580) +- mac->ops.reset_hw = igb_reset_hw_82580; +- else +- mac->ops.reset_hw = igb_reset_hw_82575; +- /* Set if part includes ASF firmware */ +- mac->asf_firmware_present = true; +- /* Set if manageability features are enabled. */ +- mac->arc_subsystem_valid = +- (rd32(E1000_FWSM) & E1000_FWSM_MODE_MASK) +- ? true : false; +- /* enable EEE on i350 parts */ +- if (mac->type == e1000_i350) +- dev_spec->eee_disable = false; +- else +- dev_spec->eee_disable = true; +- /* physical interface link setup */ +- mac->ops.setup_physical_interface = +- (hw->phy.media_type == e1000_media_type_copper) +- ? igb_setup_copper_link_82575 +- : igb_setup_serdes_link_82575; ++ wr32(E1000_CTRL_EXT, ctrl_ext); ++ igb_reset_mdicnfg_82580(hw); + +- /* NVM initialization */ +- eecd = rd32(E1000_EECD); ++ if (igb_sgmii_active_82575(hw) && !igb_sgmii_uses_mdio_82575(hw)) { ++ phy->ops.read_reg = igb_read_phy_reg_sgmii_82575; ++ phy->ops.write_reg = igb_write_phy_reg_sgmii_82575; ++ } else { ++ switch (hw->mac.type) { ++ case e1000_82580: ++ case e1000_i350: ++ case e1000_i354: ++ phy->ops.read_reg = igb_read_phy_reg_82580; ++ phy->ops.write_reg = igb_write_phy_reg_82580; ++ break; ++ case e1000_i210: ++ case e1000_i211: ++ phy->ops.read_reg = igb_read_phy_reg_gs40g; ++ phy->ops.write_reg = igb_write_phy_reg_gs40g; ++ break; ++ default: ++ phy->ops.read_reg = igb_read_phy_reg_igp; ++ phy->ops.write_reg = igb_write_phy_reg_igp; ++ } ++ } + +- nvm->opcode_bits = 8; +- nvm->delay_usec = 1; +- switch (nvm->override) { +- case e1000_nvm_override_spi_large: +- nvm->page_size = 32; +- nvm->address_bits = 16; ++ /* set lan id */ ++ hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >> ++ E1000_STATUS_FUNC_SHIFT; ++ ++ /* Set phy->phy_addr and phy->id. */ ++ ret_val = igb_get_phy_id_82575(hw); ++ if (ret_val) ++ return ret_val; ++ ++ /* Verify phy id and set remaining function pointers */ ++ switch (phy->id) { ++ case M88E1543_E_PHY_ID: ++ case I347AT4_E_PHY_ID: ++ case M88E1112_E_PHY_ID: ++ case M88E1111_I_PHY_ID: ++ phy->type = e1000_phy_m88; ++ phy->ops.check_polarity = igb_check_polarity_m88; ++ phy->ops.get_phy_info = igb_get_phy_info_m88; ++ if (phy->id != M88E1111_I_PHY_ID) ++ phy->ops.get_cable_length = ++ igb_get_cable_length_m88_gen2; ++ else ++ phy->ops.get_cable_length = igb_get_cable_length_m88; ++ phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88; + break; +- case e1000_nvm_override_spi_small: +- nvm->page_size = 8; +- nvm->address_bits = 8; ++ case IGP03E1000_E_PHY_ID: ++ phy->type = e1000_phy_igp_3; ++ phy->ops.get_phy_info = igb_get_phy_info_igp; ++ phy->ops.get_cable_length = igb_get_cable_length_igp_2; ++ phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_igp; ++ phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82575; ++ phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state; + break; +- default: +- nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; +- nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; ++ case I82580_I_PHY_ID: ++ case I350_I_PHY_ID: ++ phy->type = e1000_phy_82580; ++ phy->ops.force_speed_duplex = ++ igb_phy_force_speed_duplex_82580; ++ phy->ops.get_cable_length = igb_get_cable_length_82580; ++ phy->ops.get_phy_info = igb_get_phy_info_82580; ++ phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82580; ++ phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580; ++ break; ++ case I210_I_PHY_ID: ++ phy->type = e1000_phy_i210; ++ phy->ops.check_polarity = igb_check_polarity_m88; ++ phy->ops.get_phy_info = igb_get_phy_info_m88; ++ phy->ops.get_cable_length = igb_get_cable_length_m88_gen2; ++ phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82580; ++ phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580; ++ phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88; ++ break; ++ case BCM54616_E_PHY_ID: ++ phy->type = e1000_phy_bcm54616; + break; ++ case BCM5461S_PHY_ID: ++ phy->type = e1000_phy_bcm5461s; ++ phy->ops.check_polarity = NULL; ++ phy->ops.get_phy_info = igb_get_phy_info_5461s; ++ phy->ops.get_cable_length = NULL; ++ phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_82580; ++ break; ++ default: ++ ret_val = -E1000_ERR_PHY; ++ goto out; + } + +- nvm->type = e1000_nvm_eeprom_spi; ++out: ++ return ret_val; ++} ++ ++/** ++ * igb_init_nvm_params_82575 - Init NVM func ptrs. ++ * @hw: pointer to the HW structure ++ **/ ++static s32 igb_init_nvm_params_82575(struct e1000_hw *hw) ++{ ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ u32 eecd = rd32(E1000_EECD); ++ u16 size; + + size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> + E1000_EECD_SIZE_EX_SHIFT); + +- /* +- * Added to a constant, "size" becomes the left-shift value ++ /* Added to a constant, "size" becomes the left-shift value + * for setting word_size. + */ + size += NVM_WORD_SIZE_BASE_SHIFT; + +- /* +- * Check for invalid size ++ /* Just in case size is out of range, cap it to the largest ++ * EEPROM size supported + */ +- if ((hw->mac.type == e1000_82576) && (size > 15)) { +- printk("igb: The NVM size is not valid, " +- "defaulting to 32K.\n"); ++ if (size > 15) + size = 15; +- } ++ + nvm->word_size = 1 << size; ++ nvm->opcode_bits = 8; ++ nvm->delay_usec = 1; ++ ++ switch (nvm->override) { ++ case e1000_nvm_override_spi_large: ++ nvm->page_size = 32; ++ nvm->address_bits = 16; ++ break; ++ case e1000_nvm_override_spi_small: ++ nvm->page_size = 8; ++ nvm->address_bits = 8; ++ break; ++ default: ++ nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; ++ nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? ++ 16 : 8; ++ break; ++ } + if (nvm->word_size == (1 << 15)) + nvm->page_size = 128; + ++ nvm->type = e1000_nvm_eeprom_spi; ++ + /* NVM Function Pointers */ + nvm->ops.acquire = igb_acquire_nvm_82575; ++ nvm->ops.release = igb_release_nvm_82575; ++ nvm->ops.write = igb_write_nvm_spi; ++ nvm->ops.validate = igb_validate_nvm_checksum; ++ nvm->ops.update = igb_update_nvm_checksum; + if (nvm->word_size < (1 << 15)) + nvm->ops.read = igb_read_nvm_eerd; + else + nvm->ops.read = igb_read_nvm_spi; + +- nvm->ops.release = igb_release_nvm_82575; ++ /* override generic family function pointers for specific descendants */ + switch (hw->mac.type) { + case e1000_82580: + nvm->ops.validate = igb_validate_nvm_checksum_82580; + nvm->ops.update = igb_update_nvm_checksum_82580; + break; ++ case e1000_i354: + case e1000_i350: + nvm->ops.validate = igb_validate_nvm_checksum_i350; + nvm->ops.update = igb_update_nvm_checksum_i350; + break; + default: +- nvm->ops.validate = igb_validate_nvm_checksum; +- nvm->ops.update = igb_update_nvm_checksum; ++ break; + } +- nvm->ops.write = igb_write_nvm_spi; + +- /* if part supports SR-IOV then initialize mailbox parameters */ ++ return 0; ++} ++ ++/** ++ * igb_init_mac_params_82575 - Init MAC func ptrs. ++ * @hw: pointer to the HW structure ++ **/ ++static s32 igb_init_mac_params_82575(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; ++ ++ /* Set mta register count */ ++ mac->mta_reg_count = 128; ++ /* Set rar entry count */ + switch (mac->type) { + case e1000_82576: ++ mac->rar_entry_count = E1000_RAR_ENTRIES_82576; ++ break; ++ case e1000_82580: ++ mac->rar_entry_count = E1000_RAR_ENTRIES_82580; ++ break; + case e1000_i350: +- igb_init_mbx_params_pf(hw); ++ case e1000_i354: ++ mac->rar_entry_count = E1000_RAR_ENTRIES_I350; + break; + default: ++ mac->rar_entry_count = E1000_RAR_ENTRIES_82575; + break; + } ++ /* reset */ ++ if (mac->type >= e1000_82580) ++ mac->ops.reset_hw = igb_reset_hw_82580; ++ else ++ mac->ops.reset_hw = igb_reset_hw_82575; + +- /* setup PHY parameters */ +- if (phy->media_type != e1000_media_type_copper) { +- phy->type = e1000_phy_none; +- return 0; ++ if (mac->type >= e1000_i210) { ++ mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_i210; ++ mac->ops.release_swfw_sync = igb_release_swfw_sync_i210; ++ ++ } else { ++ mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_82575; ++ mac->ops.release_swfw_sync = igb_release_swfw_sync_82575; + } + +- phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; +- phy->reset_delay_us = 100; ++ /* Set if part includes ASF firmware */ ++ mac->asf_firmware_present = true; ++ /* Set if manageability features are enabled. */ ++ mac->arc_subsystem_valid = ++ (rd32(E1000_FWSM) & E1000_FWSM_MODE_MASK) ++ ? true : false; ++ /* bwh: disable EEE as it can't be controlled through ethtool */ ++ dev_spec->eee_disable = true; ++ /* Allow a single clear of the SW semaphore on I210 and newer */ ++ if (mac->type >= e1000_i210) ++ dev_spec->clear_semaphore_once = true; ++ /* physical interface link setup */ ++ mac->ops.setup_physical_interface = ++ (hw->phy.media_type == e1000_media_type_copper) ++ ? igb_setup_copper_link_82575 ++ : igb_setup_serdes_link_82575; ++ ++ return 0; ++} ++ ++/** ++ * igb_set_sfp_media_type_82575 - derives SFP module media type. ++ * @hw: pointer to the HW structure ++ * ++ * The media type is chosen based on SFP module. ++ * compatibility flags retrieved from SFP ID EEPROM. ++ **/ ++static s32 igb_set_sfp_media_type_82575(struct e1000_hw *hw) ++{ ++ s32 ret_val = E1000_ERR_CONFIG; ++ u32 ctrl_ext = 0; ++ struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; ++ struct e1000_sfp_flags *eth_flags = &dev_spec->eth_flags; ++ u8 tranceiver_type = 0; ++ s32 timeout = 3; + ++ /* Turn I2C interface ON and power on sfp cage */ + ctrl_ext = rd32(E1000_CTRL_EXT); ++ ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; ++ wr32(E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA); + +- /* PHY function pointers */ +- if (igb_sgmii_active_82575(hw)) { +- phy->ops.reset = igb_phy_hw_reset_sgmii_82575; +- ctrl_ext |= E1000_CTRL_I2C_ENA; +- } else { +- phy->ops.reset = igb_phy_hw_reset; +- ctrl_ext &= ~E1000_CTRL_I2C_ENA; ++ wrfl(); ++ ++ /* Read SFP module data */ ++ while (timeout) { ++ ret_val = igb_read_sfp_data_byte(hw, ++ E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET), ++ &tranceiver_type); ++ if (ret_val == 0) ++ break; ++ msleep(100); ++ timeout--; + } ++ if (ret_val != 0) ++ goto out; + +- wr32(E1000_CTRL_EXT, ctrl_ext); +- igb_reset_mdicnfg_82580(hw); ++ ret_val = igb_read_sfp_data_byte(hw, ++ E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET), ++ (u8 *)eth_flags); ++ if (ret_val != 0) ++ goto out; + +- if (igb_sgmii_active_82575(hw) && !igb_sgmii_uses_mdio_82575(hw)) { +- phy->ops.read_reg = igb_read_phy_reg_sgmii_82575; +- phy->ops.write_reg = igb_write_phy_reg_sgmii_82575; +- } else if (hw->mac.type >= e1000_82580) { +- phy->ops.read_reg = igb_read_phy_reg_82580; +- phy->ops.write_reg = igb_write_phy_reg_82580; ++ /* Check if there is some SFP module plugged and powered */ ++ if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) || ++ (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) { ++ dev_spec->module_plugged = true; ++ if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) { ++ hw->phy.media_type = e1000_media_type_internal_serdes; ++ } else if (eth_flags->e100_base_fx) { ++ dev_spec->sgmii_active = true; ++ hw->phy.media_type = e1000_media_type_internal_serdes; ++ } else if (eth_flags->e1000_base_t) { ++ dev_spec->sgmii_active = true; ++ hw->phy.media_type = e1000_media_type_copper; ++ } else { ++ hw->phy.media_type = e1000_media_type_unknown; ++ hw_dbg("PHY module has not been recognized\n"); ++ goto out; ++ } + } else { +- phy->ops.read_reg = igb_read_phy_reg_igp; +- phy->ops.write_reg = igb_write_phy_reg_igp; ++ hw->phy.media_type = e1000_media_type_unknown; + } ++ ret_val = 0; ++out: ++ /* Restore I2C interface setting */ ++ wr32(E1000_CTRL_EXT, ctrl_ext); ++ return ret_val; ++} + +- /* set lan id */ +- hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >> +- E1000_STATUS_FUNC_SHIFT; ++static s32 igb_get_invariants_82575(struct e1000_hw *hw) ++{ ++ struct e1000_mac_info *mac = &hw->mac; ++ struct e1000_dev_spec_82575 * dev_spec = &hw->dev_spec._82575; ++ s32 ret_val; ++ u32 ctrl_ext = 0; ++ u32 link_mode = 0; + +- /* Set phy->phy_addr and phy->id. */ +- ret_val = igb_get_phy_id_82575(hw); +- if (ret_val) +- return ret_val; ++ switch (hw->device_id) { ++ case E1000_DEV_ID_82575EB_COPPER: ++ case E1000_DEV_ID_82575EB_FIBER_SERDES: ++ case E1000_DEV_ID_82575GB_QUAD_COPPER: ++ mac->type = e1000_82575; ++ break; ++ case E1000_DEV_ID_82576: ++ case E1000_DEV_ID_82576_NS: ++ case E1000_DEV_ID_82576_NS_SERDES: ++ case E1000_DEV_ID_82576_FIBER: ++ case E1000_DEV_ID_82576_SERDES: ++ case E1000_DEV_ID_82576_QUAD_COPPER: ++ case E1000_DEV_ID_82576_QUAD_COPPER_ET2: ++ case E1000_DEV_ID_82576_SERDES_QUAD: ++ mac->type = e1000_82576; ++ break; ++ case E1000_DEV_ID_82580_COPPER: ++ case E1000_DEV_ID_82580_FIBER: ++ case E1000_DEV_ID_82580_QUAD_FIBER: ++ case E1000_DEV_ID_82580_SERDES: ++ case E1000_DEV_ID_82580_SGMII: ++ case E1000_DEV_ID_82580_COPPER_DUAL: ++ case E1000_DEV_ID_DH89XXCC_SGMII: ++ case E1000_DEV_ID_DH89XXCC_SERDES: ++ case E1000_DEV_ID_DH89XXCC_BACKPLANE: ++ case E1000_DEV_ID_DH89XXCC_SFP: ++ mac->type = e1000_82580; ++ break; ++ case E1000_DEV_ID_I350_COPPER: ++ case E1000_DEV_ID_I350_FIBER: ++ case E1000_DEV_ID_I350_SERDES: ++ case E1000_DEV_ID_I350_SGMII: ++ mac->type = e1000_i350; ++ break; ++ case E1000_DEV_ID_I210_COPPER: ++ case E1000_DEV_ID_I210_FIBER: ++ case E1000_DEV_ID_I210_SERDES: ++ case E1000_DEV_ID_I210_SGMII: ++ case E1000_DEV_ID_I210_COPPER_FLASHLESS: ++ case E1000_DEV_ID_I210_SERDES_FLASHLESS: ++ mac->type = e1000_i210; ++ break; ++ case E1000_DEV_ID_I211_COPPER: ++ mac->type = e1000_i211; ++ break; ++ case E1000_DEV_ID_I354_BACKPLANE_1GBPS: ++ case E1000_DEV_ID_I354_SGMII: ++ case E1000_DEV_ID_I354_BACKPLANE_2_5GBPS: ++ mac->type = e1000_i354; ++ break; ++ default: ++ return -E1000_ERR_MAC_INIT; ++ break; ++ } + +- /* Verify phy id and set remaining function pointers */ +- switch (phy->id) { +- case I347AT4_E_PHY_ID: +- case M88E1112_E_PHY_ID: +- case M88E1111_I_PHY_ID: +- phy->type = e1000_phy_m88; +- phy->ops.get_phy_info = igb_get_phy_info_m88; ++ /* Set media type */ ++ /* The 82575 uses bits 22:23 for link mode. The mode can be changed ++ * based on the EEPROM. We cannot rely upon device ID. There ++ * is no distinguishable difference between fiber and internal ++ * SerDes mode on the 82575. There can be an external PHY attached ++ * on the SGMII interface. For this, we'll set sgmii_active to true. ++ */ ++ hw->phy.media_type = e1000_media_type_copper; ++ dev_spec->sgmii_active = false; ++ dev_spec->module_plugged = false; ++ ++ ctrl_ext = rd32(E1000_CTRL_EXT); ++ ++ link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; ++ switch (link_mode) { ++ case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: ++ hw->phy.media_type = e1000_media_type_internal_serdes; ++ break; ++ case E1000_CTRL_EXT_LINK_MODE_SGMII: ++ /* Get phy control interface type set (MDIO vs. I2C)*/ ++ if (igb_sgmii_uses_mdio_82575(hw)) { ++ hw->phy.media_type = e1000_media_type_copper; ++ dev_spec->sgmii_active = true; ++ break; ++ } ++ /* fall through for I2C based SGMII */ ++ case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: ++ /* read media type from SFP EEPROM */ ++ ret_val = igb_set_sfp_media_type_82575(hw); ++ if ((ret_val != 0) || ++ (hw->phy.media_type == e1000_media_type_unknown)) { ++ /* If media type was not identified then return media ++ * type defined by the CTRL_EXT settings. ++ */ ++ hw->phy.media_type = e1000_media_type_internal_serdes; ++ ++ if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) { ++ hw->phy.media_type = e1000_media_type_copper; ++ dev_spec->sgmii_active = true; ++ } ++ ++ break; ++ } ++ ++ /* do not change link mode for 100BaseFX */ ++ if (dev_spec->eth_flags.e100_base_fx) ++ break; ++ ++ /* change current link mode setting */ ++ ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK; ++ ++ if (hw->phy.media_type == e1000_media_type_copper) ++ ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII; ++ else ++ ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; ++ ++ wr32(E1000_CTRL_EXT, ctrl_ext); ++ ++ break; ++ default: ++ break; ++ } + +- if (phy->id == I347AT4_E_PHY_ID || +- phy->id == M88E1112_E_PHY_ID) +- phy->ops.get_cable_length = igb_get_cable_length_m88_gen2; +- else +- phy->ops.get_cable_length = igb_get_cable_length_m88; ++ /* mac initialization and operations */ ++ ret_val = igb_init_mac_params_82575(hw); ++ if (ret_val) ++ goto out; + +- phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88; ++ /* NVM initialization */ ++ ret_val = igb_init_nvm_params_82575(hw); ++ switch (hw->mac.type) { ++ case e1000_i210: ++ case e1000_i211: ++ ret_val = igb_init_nvm_params_i210(hw); + break; +- case IGP03E1000_E_PHY_ID: +- phy->type = e1000_phy_igp_3; +- phy->ops.get_phy_info = igb_get_phy_info_igp; +- phy->ops.get_cable_length = igb_get_cable_length_igp_2; +- phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_igp; +- phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82575; +- phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state; ++ default: + break; +- case I82580_I_PHY_ID: +- case I350_I_PHY_ID: +- phy->type = e1000_phy_82580; +- phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_82580; +- phy->ops.get_cable_length = igb_get_cable_length_82580; +- phy->ops.get_phy_info = igb_get_phy_info_82580; ++ } ++ ++ if (ret_val) ++ goto out; ++ ++ /* if part supports SR-IOV then initialize mailbox parameters */ ++ switch (mac->type) { ++ case e1000_82576: ++ case e1000_i350: ++ igb_init_mbx_params_pf(hw); + break; + default: +- return -E1000_ERR_PHY; ++ break; + } + +- return 0; ++ /* setup PHY parameters */ ++ ret_val = igb_init_phy_params_82575(hw); ++ ++out: ++ return ret_val; + } + + /** +@@ -384,7 +627,7 @@ static s32 igb_acquire_phy_82575(struct e1000_hw *hw) + else if (hw->bus.func == E1000_FUNC_3) + mask = E1000_SWFW_PHY3_SM; + +- return igb_acquire_swfw_sync_82575(hw, mask); ++ return hw->mac.ops.acquire_swfw_sync(hw, mask); + } + + /** +@@ -405,7 +648,7 @@ static void igb_release_phy_82575(struct e1000_hw *hw) + else if (hw->bus.func == E1000_FUNC_3) + mask = E1000_SWFW_PHY3_SM; + +- igb_release_swfw_sync_82575(hw, mask); ++ hw->mac.ops.release_swfw_sync(hw, mask); + } + + /** +@@ -486,8 +729,11 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) + u32 ctrl_ext; + u32 mdic; + +- /* +- * For SGMII PHYs, we try the list of possible addresses until ++ /* Extra read required for some PHY's on i354 */ ++ if (hw->mac.type == e1000_i354) ++ igb_get_phy_id(hw); ++ ++ /* For SGMII PHYs, we try the list of possible addresses until + * we find one that works. For non-SGMII PHYs + * (e.g. integrated copper PHYs), an address of 1 should + * work. The result of this function should mean phy->phy_addr +@@ -509,6 +755,9 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) + break; + case e1000_82580: + case e1000_i350: ++ case e1000_i354: ++ case e1000_i210: ++ case e1000_i211: + mdic = rd32(E1000_MDICNFG); + mdic &= E1000_MDICNFG_PHY_MASK; + phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT; +@@ -519,6 +768,16 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) + break; + } + ret_val = igb_get_phy_id(hw); ++ if (ret_val && hw->mac.type == e1000_i354) { ++ /* we do a special check for bcm5461s phy by setting ++ * the phy->addr to 5 and doing the phy check again. This ++ * call will succeed and retrieve a valid phy id if we have ++ * the bcm5461s phy ++ */ ++ phy->addr = 5; ++ phy->type = e1000_phy_bcm5461s; ++ ret_val = igb_get_phy_id(hw); ++ } + goto out; + } + +@@ -528,8 +787,7 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) + wrfl(); + msleep(300); + +- /* +- * The address field in the I2CCMD register is 3 bits and 0 is invalid. ++ /* The address field in the I2CCMD register is 3 bits and 0 is invalid. + * Therefore, we need to test 1-7 + */ + for (phy->addr = 1; phy->addr < 8; phy->addr++) { +@@ -537,8 +795,7 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) + if (ret_val == 0) { + hw_dbg("Vendor ID 0x%08X read at address %u\n", + phy_id, phy->addr); +- /* +- * At the time of this writing, The M88 part is ++ /* At the time of this writing, The M88 part is + * the only supported SGMII PHY product. + */ + if (phy_id == M88_VENDOR) +@@ -574,15 +831,13 @@ static s32 igb_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) + { + s32 ret_val; + +- /* +- * This isn't a true "hard" reset, but is the only reset ++ /* This isn't a true "hard" reset, but is the only reset + * available to us at this time. + */ + + hw_dbg("Soft resetting SGMII attached PHY...\n"); + +- /* +- * SFP documentation requires the following to configure the SPF module ++ /* SFP documentation requires the following to configure the SPF module + * to work on SGMII. No further documentation is given. + */ + ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084); +@@ -637,8 +892,7 @@ static s32 igb_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) + data &= ~IGP02E1000_PM_D0_LPLU; + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, + data); +- /* +- * LPLU and SmartSpeed are mutually exclusive. LPLU is used ++ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used + * during Dx states where the power conservation is most + * important. During driver activity we should enable + * SmartSpeed, so performance is maintained. +@@ -673,6 +927,94 @@ out: + } + + /** ++ * igb_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state ++ * @hw: pointer to the HW structure ++ * @active: true to enable LPLU, false to disable ++ * ++ * Sets the LPLU D0 state according to the active flag. When ++ * activating LPLU this function also disables smart speed ++ * and vice versa. LPLU will not be activated unless the ++ * device autonegotiation advertisement meets standards of ++ * either 10 or 10/100 or 10/100/1000 at all duplexes. ++ * This is a function pointer entry point only called by ++ * PHY setup routines. ++ **/ ++static s32 igb_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val = 0; ++ u16 data; ++ ++ data = rd32(E1000_82580_PHY_POWER_MGMT); ++ ++ if (active) { ++ data |= E1000_82580_PM_D0_LPLU; ++ ++ /* When LPLU is enabled, we should disable SmartSpeed */ ++ data &= ~E1000_82580_PM_SPD; ++ } else { ++ data &= ~E1000_82580_PM_D0_LPLU; ++ ++ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used ++ * during Dx states where the power conservation is most ++ * important. During driver activity we should enable ++ * SmartSpeed, so performance is maintained. ++ */ ++ if (phy->smart_speed == e1000_smart_speed_on) ++ data |= E1000_82580_PM_SPD; ++ else if (phy->smart_speed == e1000_smart_speed_off) ++ data &= ~E1000_82580_PM_SPD; } ++ ++ wr32(E1000_82580_PHY_POWER_MGMT, data); ++ return ret_val; ++} ++ ++/** ++ * igb_set_d3_lplu_state_82580 - Sets low power link up state for D3 ++ * @hw: pointer to the HW structure ++ * @active: boolean used to enable/disable lplu ++ * ++ * Success returns 0, Failure returns 1 ++ * ++ * The low power link up (lplu) state is set to the power management level D3 ++ * and SmartSpeed is disabled when active is true, else clear lplu for D3 ++ * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU ++ * is used during Dx states where the power conservation is most important. ++ * During driver activity, SmartSpeed should be enabled so performance is ++ * maintained. ++ **/ ++static s32 igb_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val = 0; ++ u16 data; ++ ++ data = rd32(E1000_82580_PHY_POWER_MGMT); ++ ++ if (!active) { ++ data &= ~E1000_82580_PM_D3_LPLU; ++ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used ++ * during Dx states where the power conservation is most ++ * important. During driver activity we should enable ++ * SmartSpeed, so performance is maintained. ++ */ ++ if (phy->smart_speed == e1000_smart_speed_on) ++ data |= E1000_82580_PM_SPD; ++ else if (phy->smart_speed == e1000_smart_speed_off) ++ data &= ~E1000_82580_PM_SPD; ++ } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || ++ (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || ++ (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { ++ data |= E1000_82580_PM_D3_LPLU; ++ /* When LPLU is enabled, we should disable SmartSpeed */ ++ data &= ~E1000_82580_PM_SPD; ++ } ++ ++ wr32(E1000_82580_PHY_POWER_MGMT, data); ++ return ret_val; ++} ++ ++/** + * igb_acquire_nvm_82575 - Request for access to EEPROM + * @hw: pointer to the HW structure + * +@@ -685,14 +1027,14 @@ static s32 igb_acquire_nvm_82575(struct e1000_hw *hw) + { + s32 ret_val; + +- ret_val = igb_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); ++ ret_val = hw->mac.ops.acquire_swfw_sync(hw, E1000_SWFW_EEP_SM); + if (ret_val) + goto out; + + ret_val = igb_acquire_nvm(hw); + + if (ret_val) +- igb_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); ++ hw->mac.ops.release_swfw_sync(hw, E1000_SWFW_EEP_SM); + + out: + return ret_val; +@@ -708,7 +1050,7 @@ out: + static void igb_release_nvm_82575(struct e1000_hw *hw) + { + igb_release_nvm(hw); +- igb_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); ++ hw->mac.ops.release_swfw_sync(hw, E1000_SWFW_EEP_SM); + } + + /** +@@ -737,8 +1079,7 @@ static s32 igb_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask) + if (!(swfw_sync & (fwmask | swmask))) + break; + +- /* +- * Firmware currently using resource (fwmask) ++ /* Firmware currently using resource (fwmask) + * or other software thread using resource (swmask) + */ + igb_put_hw_semaphore(hw); +@@ -820,6 +1161,34 @@ static s32 igb_get_cfg_done_82575(struct e1000_hw *hw) + (hw->phy.type == e1000_phy_igp_3)) + igb_phy_init_script_igp3(hw); + ++ if (hw->phy.type == e1000_phy_bcm5461s) ++ igb_phy_init_script_5461s(hw); ++ ++ return ret_val; ++} ++ ++/** ++ * igb_get_link_up_info_82575 - Get link speed/duplex info ++ * @hw: pointer to the HW structure ++ * @speed: stores the current speed ++ * @duplex: stores the current duplex ++ * ++ * This is a wrapper function, if using the serial gigabit media independent ++ * interface, use PCS to retrieve the link speed and duplex information. ++ * Otherwise, use the generic function to get the link speed and duplex info. ++ **/ ++static s32 igb_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, ++ u16 *duplex) ++{ ++ s32 ret_val; ++ ++ if (hw->phy.media_type != e1000_media_type_copper) ++ ret_val = igb_get_pcs_speed_and_duplex_82575(hw, speed, ++ duplex); ++ else ++ ret_val = igb_get_speed_and_duplex_copper(hw, speed, ++ duplex); ++ + return ret_val; + } + +@@ -838,12 +1207,20 @@ static s32 igb_check_for_link_82575(struct e1000_hw *hw) + if (hw->phy.media_type != e1000_media_type_copper) { + ret_val = igb_get_pcs_speed_and_duplex_82575(hw, &speed, + &duplex); +- /* +- * Use this flag to determine if link needs to be checked or ++ /* Use this flag to determine if link needs to be checked or + * not. If we have link clear the flag so that we do not + * continue to check for link. + */ + hw->mac.get_link_status = !hw->mac.serdes_has_link; ++ ++ /* Configure Flow Control now that Auto-Neg has completed. ++ * First, we need to restore the desired flow control ++ * settings because we may have had to re-autoneg with a ++ * different link partner. ++ */ ++ ret_val = igb_config_fc_after_link_up(hw); ++ if (ret_val) ++ hw_dbg("Error configuring flow control\n"); + } else { + ret_val = igb_check_for_copper_link(hw); + } +@@ -892,22 +1269,20 @@ static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed, + u16 *duplex) + { + struct e1000_mac_info *mac = &hw->mac; +- u32 pcs; ++ u32 pcs, status; + + /* Set up defaults for the return values of this function */ + mac->serdes_has_link = false; + *speed = 0; + *duplex = 0; + +- /* +- * Read the PCS Status register for link state. For non-copper mode, ++ /* Read the PCS Status register for link state. For non-copper mode, + * the status register is not accurate. The PCS status register is + * used instead. + */ + pcs = rd32(E1000_PCS_LSTAT); + +- /* +- * The link up bit determines when link is up on autoneg. The sync ok ++ /* The link up bit determines when link is up on autoneg. The sync ok + * gets set once both sides sync up and agree upon link. Stable link + * can be determined by checking for both link up and link sync ok + */ +@@ -915,20 +1290,31 @@ static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed, + mac->serdes_has_link = true; + + /* Detect and store PCS speed */ +- if (pcs & E1000_PCS_LSTS_SPEED_1000) { ++ if (pcs & E1000_PCS_LSTS_SPEED_1000) + *speed = SPEED_1000; +- } else if (pcs & E1000_PCS_LSTS_SPEED_100) { ++ else if (pcs & E1000_PCS_LSTS_SPEED_100) + *speed = SPEED_100; +- } else { ++ else + *speed = SPEED_10; +- } + + /* Detect and store PCS duplex */ +- if (pcs & E1000_PCS_LSTS_DUPLEX_FULL) { ++ if (pcs & E1000_PCS_LSTS_DUPLEX_FULL) + *duplex = FULL_DUPLEX; +- } else { ++ else + *duplex = HALF_DUPLEX; ++ ++ /* Check if it is an I354 2.5Gb backplane connection. */ ++ if (mac->type == e1000_i354) { ++ status = rd32(E1000_STATUS); ++ if ((status & E1000_STATUS_2P5_SKU) && ++ !(status & E1000_STATUS_2P5_SKU_OVER)) { ++ *speed = SPEED_2500; ++ *duplex = FULL_DUPLEX; ++ hw_dbg("2500 Mbs, "); ++ hw_dbg("Full Duplex\n"); ++ } + } ++ + } + + return 0; +@@ -975,11 +1361,10 @@ void igb_shutdown_serdes_link_82575(struct e1000_hw *hw) + **/ + static s32 igb_reset_hw_82575(struct e1000_hw *hw) + { +- u32 ctrl, icr; ++ u32 ctrl; + s32 ret_val; + +- /* +- * Prevent the PCI-E bus from sticking if there is no TLP connection ++ /* Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ + ret_val = igb_disable_pcie_master(hw); +@@ -1008,8 +1393,7 @@ static s32 igb_reset_hw_82575(struct e1000_hw *hw) + + ret_val = igb_get_auto_rd_done(hw); + if (ret_val) { +- /* +- * When auto config read does not complete, do not ++ /* When auto config read does not complete, do not + * return with an error. This can happen in situations + * where there is no eeprom and prevents getting link. + */ +@@ -1022,7 +1406,7 @@ static s32 igb_reset_hw_82575(struct e1000_hw *hw) + + /* Clear any pending interrupt events. */ + wr32(E1000_IMC, 0xffffffff); +- icr = rd32(E1000_ICR); ++ rd32(E1000_ICR); + + /* Install any alternate MAC address into RAR0 */ + ret_val = igb_check_alt_mac_addr(hw); +@@ -1051,7 +1435,7 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw) + + /* Disabling VLAN filtering */ + hw_dbg("Initializing the IEEE VLAN\n"); +- if (hw->mac.type == e1000_i350) ++ if ((hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i354)) + igb_clear_vfta_i350(hw); + else + igb_clear_vfta(hw); +@@ -1072,14 +1456,12 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw) + /* Setup link and flow control */ + ret_val = igb_setup_link(hw); + +- /* +- * Clear all of the statistics registers (clear on read). It is ++ /* Clear all of the statistics registers (clear on read). It is + * important that we do this after we have tried to establish link + * because the symbol error count will increment wildly if there + * is no link. + */ + igb_clear_hw_cntrs_82575(hw); +- + return ret_val; + } + +@@ -1095,12 +1477,28 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) + { + u32 ctrl; + s32 ret_val; ++ u32 phpm_reg; + + ctrl = rd32(E1000_CTRL); + ctrl |= E1000_CTRL_SLU; + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); + wr32(E1000_CTRL, ctrl); + ++ /* Clear Go Link Disconnect bit on supported devices */ ++ switch (hw->mac.type) { ++ case e1000_82580: ++ case e1000_i350: ++ case e1000_i210: ++ case e1000_i211: ++ case e1000_i354: ++ phpm_reg = rd32(E1000_82580_PHY_POWER_MGMT); ++ phpm_reg &= ~E1000_82580_PM_GO_LINKD; ++ wr32(E1000_82580_PHY_POWER_MGMT, phpm_reg); ++ break; ++ default: ++ break; ++ } ++ + ret_val = igb_setup_serdes_link_82575(hw); + if (ret_val) + goto out; +@@ -1116,12 +1514,19 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) + } + } + switch (hw->phy.type) { ++ case e1000_phy_i210: + case e1000_phy_m88: +- if (hw->phy.id == I347AT4_E_PHY_ID || +- hw->phy.id == M88E1112_E_PHY_ID) ++ switch (hw->phy.id) { ++ case I347AT4_E_PHY_ID: ++ case M88E1112_E_PHY_ID: ++ case M88E1543_E_PHY_ID: ++ case I210_I_PHY_ID: + ret_val = igb_copper_link_setup_m88_gen2(hw); +- else ++ break; ++ default: + ret_val = igb_copper_link_setup_m88(hw); ++ break; ++ } + break; + case e1000_phy_igp_3: + ret_val = igb_copper_link_setup_igp(hw); +@@ -1129,6 +1534,9 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) + case e1000_phy_82580: + ret_val = igb_copper_link_setup_82580(hw); + break; ++ case e1000_phy_bcm54616: ++ case e1000_phy_bcm5461s: ++ break; + default: + ret_val = -E1000_ERR_PHY; + break; +@@ -1153,7 +1561,7 @@ out: + **/ + static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) + { +- u32 ctrl_ext, ctrl_reg, reg; ++ u32 ctrl_ext, ctrl_reg, reg, anadv_reg; + bool pcs_autoneg; + s32 ret_val = E1000_SUCCESS; + u16 data; +@@ -1163,17 +1571,17 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) + return ret_val; + + +- /* +- * On the 82575, SerDes loopback mode persists until it is ++ /* On the 82575, SerDes loopback mode persists until it is + * explicitly turned off or a power cycle is performed. A read to + * the register does not indicate its status. Therefore, we ensure + * loopback mode is disabled during initialization. + */ + wr32(E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); + +- /* power on the sfp cage if present */ ++ /* power on the sfp cage if present and turn on I2C */ + ctrl_ext = rd32(E1000_CTRL_EXT); + ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; ++ ctrl_ext |= E1000_CTRL_I2C_ENA; + wr32(E1000_CTRL_EXT, ctrl_ext); + + ctrl_reg = rd32(E1000_CTRL); +@@ -1217,8 +1625,7 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) + pcs_autoneg = false; + } + +- /* +- * non-SGMII modes only supports a speed of 1000/Full for the ++ /* non-SGMII modes only supports a speed of 1000/Full for the + * link so it is best to just force the MAC and let the pcs + * link either autoneg or be forced to 1000/Full + */ +@@ -1232,8 +1639,7 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) + + wr32(E1000_CTRL, ctrl_reg); + +- /* +- * New SerDes mode allows for forcing speed or autonegotiating speed ++ /* New SerDes mode allows for forcing speed or autonegotiating speed + * at 1gb. Autoneg should be default set by most drivers. This is the + * mode that will be compatible with older link partners and switches. + * However, both are supported by the hardware and some drivers/tools. +@@ -1241,27 +1647,45 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) + reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | + E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); + +- /* +- * We force flow control to prevent the CTRL register values from being +- * overwritten by the autonegotiated flow control values +- */ +- reg |= E1000_PCS_LCTL_FORCE_FCTRL; +- + if (pcs_autoneg) { + /* Set PCS register for autoneg */ + reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ + E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ ++ ++ /* Disable force flow control for autoneg */ ++ reg &= ~E1000_PCS_LCTL_FORCE_FCTRL; ++ ++ /* Configure flow control advertisement for autoneg */ ++ anadv_reg = rd32(E1000_PCS_ANADV); ++ anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE); ++ switch (hw->fc.requested_mode) { ++ case e1000_fc_full: ++ case e1000_fc_rx_pause: ++ anadv_reg |= E1000_TXCW_ASM_DIR; ++ anadv_reg |= E1000_TXCW_PAUSE; ++ break; ++ case e1000_fc_tx_pause: ++ anadv_reg |= E1000_TXCW_ASM_DIR; ++ break; ++ default: ++ break; ++ } ++ wr32(E1000_PCS_ANADV, anadv_reg); ++ + hw_dbg("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); + } else { + /* Set PCS register for forced link */ + reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ + ++ /* Force flow control for forced link */ ++ reg |= E1000_PCS_LCTL_FORCE_FCTRL; ++ + hw_dbg("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); + } + + wr32(E1000_PCS_LCTL, reg); + +- if (!igb_sgmii_active_82575(hw)) ++ if (!pcs_autoneg && !igb_sgmii_active_82575(hw)) + igb_force_mac_fc(hw); + + return ret_val; +@@ -1325,8 +1749,7 @@ static s32 igb_read_mac_addr_82575(struct e1000_hw *hw) + { + s32 ret_val = 0; + +- /* +- * If there's an alternate MAC address place it in RAR0 ++ /* If there's an alternate MAC address place it in RAR0 + * so that it will override the Si installed default perm + * address. + */ +@@ -1510,8 +1933,7 @@ static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw) + if (gcr & E1000_GCR_CMPL_TMOUT_MASK) + goto out; + +- /* +- * if capababilities version is type 1 we can write the ++ /* if capabilities version is type 1 we can write the + * timeout of 10ms to 200ms through the GCR register + */ + if (!(gcr & E1000_GCR_CAP_VER2)) { +@@ -1519,8 +1941,7 @@ static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw) + goto out; + } + +- /* +- * for version 2 capabilities we need to write the config space ++ /* for version 2 capabilities we need to write the config space + * directly in order to set the completion timeout value for + * 16ms to 55ms + */ +@@ -1551,27 +1972,33 @@ out: + **/ + void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf) + { +- u32 dtxswc; ++ u32 reg_val, reg_offset; + + switch (hw->mac.type) { + case e1000_82576: ++ reg_offset = E1000_DTXSWC; ++ break; + case e1000_i350: +- dtxswc = rd32(E1000_DTXSWC); +- if (enable) { +- dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK | +- E1000_DTXSWC_VLAN_SPOOF_MASK); +- /* The PF can spoof - it has to in order to +- * support emulation mode NICs */ +- dtxswc ^= (1 << pf | 1 << (pf + MAX_NUM_VFS)); +- } else { +- dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | +- E1000_DTXSWC_VLAN_SPOOF_MASK); +- } +- wr32(E1000_DTXSWC, dtxswc); ++ case e1000_i354: ++ reg_offset = E1000_TXSWC; + break; + default: +- break; ++ return; + } ++ ++ reg_val = rd32(reg_offset); ++ if (enable) { ++ reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK | ++ E1000_DTXSWC_VLAN_SPOOF_MASK); ++ /* The PF can spoof - it has to in order to ++ * support emulation mode NICs ++ */ ++ reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS)); ++ } else { ++ reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | ++ E1000_DTXSWC_VLAN_SPOOF_MASK); ++ } ++ wr32(reg_offset, reg_val); + } + + /** +@@ -1594,6 +2021,7 @@ void igb_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) + dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; + wr32(E1000_DTXSWC, dtxswc); + break; ++ case e1000_i354: + case e1000_i350: + dtxswc = rd32(E1000_TXSWC); + if (enable) +@@ -1607,7 +2035,6 @@ void igb_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) + break; + } + +- + } + + /** +@@ -1642,7 +2069,6 @@ static s32 igb_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data) + { + s32 ret_val; + +- + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; +@@ -1729,17 +2155,21 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw) + s32 ret_val = 0; + /* BH SW mailbox bit in SW_FW_SYNC */ + u16 swmbsw_mask = E1000_SW_SYNCH_MB; +- u32 ctrl, icr; ++ u32 ctrl; + bool global_device_reset = hw->dev_spec._82575.global_device_reset; + +- + hw->dev_spec._82575.global_device_reset = false; + ++ /* due to hw errata, global device reset doesn't always ++ * work on 82580 ++ */ ++ if (hw->mac.type == e1000_82580) ++ global_device_reset = false; ++ + /* Get current control state. */ + ctrl = rd32(E1000_CTRL); + +- /* +- * Prevent the PCI-E bus from sticking if there is no TLP connection ++ /* Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ + ret_val = igb_disable_pcie_master(hw); +@@ -1756,7 +2186,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw) + + /* Determine whether or not a global dev reset is requested */ + if (global_device_reset && +- igb_acquire_swfw_sync_82575(hw, swmbsw_mask)) ++ hw->mac.ops.acquire_swfw_sync(hw, swmbsw_mask)) + global_device_reset = false; + + if (global_device_reset && +@@ -1774,24 +2204,19 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw) + + ret_val = igb_get_auto_rd_done(hw); + if (ret_val) { +- /* +- * When auto config read does not complete, do not ++ /* When auto config read does not complete, do not + * return with an error. This can happen in situations + * where there is no eeprom and prevents getting link. + */ + hw_dbg("Auto Read Done did not complete\n"); + } + +- /* If EEPROM is not present, run manual init scripts */ +- if ((rd32(E1000_EECD) & E1000_EECD_PRES) == 0) +- igb_reset_init_script_82575(hw); +- + /* clear global device reset status bit */ + wr32(E1000_STATUS, E1000_STAT_DEV_RST_SET); + + /* Clear any pending interrupt events. */ + wr32(E1000_IMC, 0xffffffff); +- icr = rd32(E1000_ICR); ++ rd32(E1000_ICR); + + ret_val = igb_reset_mdicnfg_82580(hw); + if (ret_val) +@@ -1802,7 +2227,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw) + + /* Release semaphore */ + if (global_device_reset) +- igb_release_swfw_sync_82575(hw, swmbsw_mask); ++ hw->mac.ops.release_swfw_sync(hw, swmbsw_mask); + + return ret_val; + } +@@ -1919,7 +2344,8 @@ static s32 igb_validate_nvm_checksum_82580(struct e1000_hw *hw) + + if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) { + /* if checksums compatibility bit is set validate checksums +- * for all 4 ports. */ ++ * for all 4 ports. ++ */ + eeprom_regions_count = 4; + } + +@@ -2031,6 +2457,41 @@ out: + } + + /** ++ * __igb_access_emi_reg - Read/write EMI register ++ * @hw: pointer to the HW structure ++ * @addr: EMI address to program ++ * @data: pointer to value to read/write from/to the EMI address ++ * @read: boolean flag to indicate read or write ++ **/ ++static s32 __igb_access_emi_reg(struct e1000_hw *hw, u16 address, ++ u16 *data, bool read) ++{ ++ s32 ret_val = E1000_SUCCESS; ++ ++ ret_val = hw->phy.ops.write_reg(hw, E1000_EMIADD, address); ++ if (ret_val) ++ return ret_val; ++ ++ if (read) ++ ret_val = hw->phy.ops.read_reg(hw, E1000_EMIDATA, data); ++ else ++ ret_val = hw->phy.ops.write_reg(hw, E1000_EMIDATA, *data); ++ ++ return ret_val; ++} ++ ++/** ++ * igb_read_emi_reg - Read Extended Management Interface register ++ * @hw: pointer to the HW structure ++ * @addr: EMI address to program ++ * @data: value to be read from the EMI address ++ **/ ++s32 igb_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data) ++{ ++ return __igb_access_emi_reg(hw, addr, data, true); ++} ++ ++/** + * igb_set_eee_i350 - Enable/disable EEE support + * @hw: pointer to the HW structure + * +@@ -2040,23 +2501,26 @@ out: + s32 igb_set_eee_i350(struct e1000_hw *hw) + { + s32 ret_val = 0; +- u32 ipcnfg, eeer, ctrl_ext; ++ u32 ipcnfg, eeer; + +- ctrl_ext = rd32(E1000_CTRL_EXT); +- if ((hw->mac.type != e1000_i350) || +- (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK)) ++ if ((hw->mac.type < e1000_i350) || ++ (hw->phy.media_type != e1000_media_type_copper)) + goto out; + ipcnfg = rd32(E1000_IPCNFG); + eeer = rd32(E1000_EEER); + + /* enable or disable per user setting */ + if (!(hw->dev_spec._82575.eee_disable)) { +- ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | +- E1000_IPCNFG_EEE_100M_AN); +- eeer |= (E1000_EEER_TX_LPI_EN | +- E1000_EEER_RX_LPI_EN | ++ u32 eee_su = rd32(E1000_EEE_SU); ++ ++ ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); ++ eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | + E1000_EEER_LPI_FC); + ++ /* This bit should not be set in normal operation. */ ++ if (eee_su & E1000_EEE_SU_LPI_CLK_STP) ++ hw_dbg("LPI Clock Stop Bit should not be set!\n"); ++ + } else { + ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | + E1000_IPCNFG_EEE_100M_AN); +@@ -2066,23 +2530,268 @@ s32 igb_set_eee_i350(struct e1000_hw *hw) + } + wr32(E1000_IPCNFG, ipcnfg); + wr32(E1000_EEER, eeer); ++ rd32(E1000_IPCNFG); ++ rd32(E1000_EEER); ++out: ++ ++ return ret_val; ++} ++ ++/** ++ * igb_set_eee_i354 - Enable/disable EEE support ++ * @hw: pointer to the HW structure ++ * ++ * Enable/disable EEE legacy mode based on setting in dev_spec structure. ++ * ++ **/ ++s32 igb_set_eee_i354(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val = 0; ++ u16 phy_data; ++ ++ if ((hw->phy.media_type != e1000_media_type_copper) || ++ (phy->id != M88E1543_E_PHY_ID)) ++ goto out; ++ ++ if (!hw->dev_spec._82575.eee_disable) { ++ /* Switch to PHY page 18. */ ++ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 18); ++ if (ret_val) ++ goto out; ++ ++ ret_val = phy->ops.read_reg(hw, E1000_M88E1543_EEE_CTRL_1, ++ &phy_data); ++ if (ret_val) ++ goto out; ++ ++ phy_data |= E1000_M88E1543_EEE_CTRL_1_MS; ++ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_EEE_CTRL_1, ++ phy_data); ++ if (ret_val) ++ goto out; ++ ++ /* Return the PHY to page 0. */ ++ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); ++ if (ret_val) ++ goto out; ++ ++ /* Turn on EEE advertisement. */ ++ ret_val = igb_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, ++ E1000_EEE_ADV_DEV_I354, ++ &phy_data); ++ if (ret_val) ++ goto out; ++ ++ phy_data |= E1000_EEE_ADV_100_SUPPORTED | ++ E1000_EEE_ADV_1000_SUPPORTED; ++ ret_val = igb_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, ++ E1000_EEE_ADV_DEV_I354, ++ phy_data); ++ } else { ++ /* Turn off EEE advertisement. */ ++ ret_val = igb_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, ++ E1000_EEE_ADV_DEV_I354, ++ &phy_data); ++ if (ret_val) ++ goto out; ++ ++ phy_data &= ~(E1000_EEE_ADV_100_SUPPORTED | ++ E1000_EEE_ADV_1000_SUPPORTED); ++ ret_val = igb_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, ++ E1000_EEE_ADV_DEV_I354, ++ phy_data); ++ } ++ + out: ++ return ret_val; ++} ++ ++/** ++ * igb_get_eee_status_i354 - Get EEE status ++ * @hw: pointer to the HW structure ++ * @status: EEE status ++ * ++ * Get EEE status by guessing based on whether Tx or Rx LPI indications have ++ * been received. ++ **/ ++s32 igb_get_eee_status_i354(struct e1000_hw *hw, bool *status) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val = 0; ++ u16 phy_data; ++ ++ /* Check if EEE is supported on this device. */ ++ if ((hw->phy.media_type != e1000_media_type_copper) || ++ (phy->id != M88E1543_E_PHY_ID)) ++ goto out; ++ ++ ret_val = igb_read_xmdio_reg(hw, E1000_PCS_STATUS_ADDR_I354, ++ E1000_PCS_STATUS_DEV_I354, ++ &phy_data); ++ if (ret_val) ++ goto out; + ++ *status = phy_data & (E1000_PCS_STATUS_TX_LPI_RCVD | ++ E1000_PCS_STATUS_RX_LPI_RCVD) ? true : false; ++ ++out: + return ret_val; + } + ++static const u8 e1000_emc_temp_data[4] = { ++ E1000_EMC_INTERNAL_DATA, ++ E1000_EMC_DIODE1_DATA, ++ E1000_EMC_DIODE2_DATA, ++ E1000_EMC_DIODE3_DATA ++}; ++static const u8 e1000_emc_therm_limit[4] = { ++ E1000_EMC_INTERNAL_THERM_LIMIT, ++ E1000_EMC_DIODE1_THERM_LIMIT, ++ E1000_EMC_DIODE2_THERM_LIMIT, ++ E1000_EMC_DIODE3_THERM_LIMIT ++}; ++ ++/** ++ * igb_get_thermal_sensor_data_generic - Gathers thermal sensor data ++ * @hw: pointer to hardware structure ++ * ++ * Updates the temperatures in mac.thermal_sensor_data ++ **/ ++s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw) ++{ ++ s32 status = E1000_SUCCESS; ++ u16 ets_offset; ++ u16 ets_cfg; ++ u16 ets_sensor; ++ u8 num_sensors; ++ u8 sensor_index; ++ u8 sensor_location; ++ u8 i; ++ struct e1000_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; ++ ++ if ((hw->mac.type != e1000_i350) || (hw->bus.func != 0)) ++ return E1000_NOT_IMPLEMENTED; ++ ++ data->sensor[0].temp = (rd32(E1000_THMJT) & 0xFF); ++ ++ /* Return the internal sensor only if ETS is unsupported */ ++ hw->nvm.ops.read(hw, NVM_ETS_CFG, 1, &ets_offset); ++ if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) ++ return status; ++ ++ hw->nvm.ops.read(hw, ets_offset, 1, &ets_cfg); ++ if (((ets_cfg & NVM_ETS_TYPE_MASK) >> NVM_ETS_TYPE_SHIFT) ++ != NVM_ETS_TYPE_EMC) ++ return E1000_NOT_IMPLEMENTED; ++ ++ num_sensors = (ets_cfg & NVM_ETS_NUM_SENSORS_MASK); ++ if (num_sensors > E1000_MAX_SENSORS) ++ num_sensors = E1000_MAX_SENSORS; ++ ++ for (i = 1; i < num_sensors; i++) { ++ hw->nvm.ops.read(hw, (ets_offset + i), 1, &ets_sensor); ++ sensor_index = ((ets_sensor & NVM_ETS_DATA_INDEX_MASK) >> ++ NVM_ETS_DATA_INDEX_SHIFT); ++ sensor_location = ((ets_sensor & NVM_ETS_DATA_LOC_MASK) >> ++ NVM_ETS_DATA_LOC_SHIFT); ++ ++ if (sensor_location != 0) ++ hw->phy.ops.read_i2c_byte(hw, ++ e1000_emc_temp_data[sensor_index], ++ E1000_I2C_THERMAL_SENSOR_ADDR, ++ &data->sensor[i].temp); ++ } ++ return status; ++} ++ ++/** ++ * igb_init_thermal_sensor_thresh_generic - Sets thermal sensor thresholds ++ * @hw: pointer to hardware structure ++ * ++ * Sets the thermal sensor thresholds according to the NVM map ++ * and save off the threshold and location values into mac.thermal_sensor_data ++ **/ ++s32 igb_init_thermal_sensor_thresh_generic(struct e1000_hw *hw) ++{ ++ s32 status = E1000_SUCCESS; ++ u16 ets_offset; ++ u16 ets_cfg; ++ u16 ets_sensor; ++ u8 low_thresh_delta; ++ u8 num_sensors; ++ u8 sensor_index; ++ u8 sensor_location; ++ u8 therm_limit; ++ u8 i; ++ struct e1000_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; ++ ++ if ((hw->mac.type != e1000_i350) || (hw->bus.func != 0)) ++ return E1000_NOT_IMPLEMENTED; ++ ++ memset(data, 0, sizeof(struct e1000_thermal_sensor_data)); ++ ++ data->sensor[0].location = 0x1; ++ data->sensor[0].caution_thresh = ++ (rd32(E1000_THHIGHTC) & 0xFF); ++ data->sensor[0].max_op_thresh = ++ (rd32(E1000_THLOWTC) & 0xFF); ++ ++ /* Return the internal sensor only if ETS is unsupported */ ++ hw->nvm.ops.read(hw, NVM_ETS_CFG, 1, &ets_offset); ++ if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) ++ return status; ++ ++ hw->nvm.ops.read(hw, ets_offset, 1, &ets_cfg); ++ if (((ets_cfg & NVM_ETS_TYPE_MASK) >> NVM_ETS_TYPE_SHIFT) ++ != NVM_ETS_TYPE_EMC) ++ return E1000_NOT_IMPLEMENTED; ++ ++ low_thresh_delta = ((ets_cfg & NVM_ETS_LTHRES_DELTA_MASK) >> ++ NVM_ETS_LTHRES_DELTA_SHIFT); ++ num_sensors = (ets_cfg & NVM_ETS_NUM_SENSORS_MASK); ++ ++ for (i = 1; i <= num_sensors; i++) { ++ hw->nvm.ops.read(hw, (ets_offset + i), 1, &ets_sensor); ++ sensor_index = ((ets_sensor & NVM_ETS_DATA_INDEX_MASK) >> ++ NVM_ETS_DATA_INDEX_SHIFT); ++ sensor_location = ((ets_sensor & NVM_ETS_DATA_LOC_MASK) >> ++ NVM_ETS_DATA_LOC_SHIFT); ++ therm_limit = ets_sensor & NVM_ETS_DATA_HTHRESH_MASK; ++ ++ hw->phy.ops.write_i2c_byte(hw, ++ e1000_emc_therm_limit[sensor_index], ++ E1000_I2C_THERMAL_SENSOR_ADDR, ++ therm_limit); ++ ++ if ((i < E1000_MAX_SENSORS) && (sensor_location != 0)) { ++ data->sensor[i].location = sensor_location; ++ data->sensor[i].caution_thresh = therm_limit; ++ data->sensor[i].max_op_thresh = therm_limit - ++ low_thresh_delta; ++ } ++ } ++ return status; ++} ++ + static struct e1000_mac_operations e1000_mac_ops_82575 = { + .init_hw = igb_init_hw_82575, + .check_for_link = igb_check_for_link_82575, + .rar_set = igb_rar_set, + .read_mac_addr = igb_read_mac_addr_82575, +- .get_speed_and_duplex = igb_get_speed_and_duplex_copper, ++ .get_speed_and_duplex = igb_get_link_up_info_82575, ++#ifdef CONFIG_IGB_HWMON ++ .get_thermal_sensor_data = igb_get_thermal_sensor_data_generic, ++ .init_thermal_sensor_thresh = igb_init_thermal_sensor_thresh_generic, ++#endif + }; + + static struct e1000_phy_operations e1000_phy_ops_82575 = { + .acquire = igb_acquire_phy_82575, + .get_cfg_done = igb_get_cfg_done_82575, + .release = igb_release_phy_82575, ++ .write_i2c_byte = igb_write_i2c_byte, ++ .read_i2c_byte = igb_read_i2c_byte, + }; + + static struct e1000_nvm_operations e1000_nvm_ops_82575 = { +diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h +index 08a757e..8c24377 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_82575.h ++++ b/drivers/net/ethernet/intel/igb/e1000_82575.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -28,10 +28,14 @@ + #ifndef _E1000_82575_H_ + #define _E1000_82575_H_ + +-extern void igb_shutdown_serdes_link_82575(struct e1000_hw *hw); +-extern void igb_power_up_serdes_link_82575(struct e1000_hw *hw); +-extern void igb_power_down_phy_copper_82575(struct e1000_hw *hw); +-extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw); ++void igb_shutdown_serdes_link_82575(struct e1000_hw *hw); ++void igb_power_up_serdes_link_82575(struct e1000_hw *hw); ++void igb_power_down_phy_copper_82575(struct e1000_hw *hw); ++void igb_rx_fifo_flush_82575(struct e1000_hw *hw); ++s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, ++ u8 *data); ++s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, ++ u8 data); + + #define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \ + (ID_LED_DEF1_DEF2 << 8) | \ +@@ -55,10 +59,11 @@ extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw); + #define E1000_SRRCTL_DROP_EN 0x80000000 + #define E1000_SRRCTL_TIMESTAMP 0x40000000 + ++ + #define E1000_MRQC_ENABLE_RSS_4Q 0x00000002 + #define E1000_MRQC_ENABLE_VMDQ 0x00000003 +-#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005 + #define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 ++#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005 + #define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 + #define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000 + +@@ -171,10 +176,13 @@ struct e1000_adv_tx_context_desc { + #define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */ + #define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */ + #define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */ ++#define E1000_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx rd Desc Relax Order */ + + #define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ + #define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ ++#define E1000_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */ + #define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */ ++#define E1000_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */ + + /* Additional DCA related definitions, note change in position of CPUID */ + #define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */ +@@ -255,6 +263,19 @@ void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *, bool, int); + void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool); + void igb_vmdq_set_replication_pf(struct e1000_hw *, bool); + u16 igb_rxpbs_adjust_82580(u32 data); ++s32 igb_read_emi_reg(struct e1000_hw *, u16 addr, u16 *data); + s32 igb_set_eee_i350(struct e1000_hw *); +- ++s32 igb_set_eee_i354(struct e1000_hw *); ++s32 igb_init_thermal_sensor_thresh_generic(struct e1000_hw *); ++s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw); ++ ++#define E1000_I2C_THERMAL_SENSOR_ADDR 0xF8 ++#define E1000_EMC_INTERNAL_DATA 0x00 ++#define E1000_EMC_INTERNAL_THERM_LIMIT 0x20 ++#define E1000_EMC_DIODE1_DATA 0x01 ++#define E1000_EMC_DIODE1_THERM_LIMIT 0x19 ++#define E1000_EMC_DIODE2_DATA 0x23 ++#define E1000_EMC_DIODE2_THERM_LIMIT 0x1A ++#define E1000_EMC_DIODE3_DATA 0x2A ++#define E1000_EMC_DIODE3_THERM_LIMIT 0x30 + #endif +diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h +index f5fc572..bee365f 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_defines.h ++++ b/drivers/net/ethernet/intel/igb/e1000_defines.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -61,20 +61,22 @@ + /* Clear Interrupt timers after IMS clear */ + /* packet buffer parity error detection enabled */ + /* descriptor FIFO parity error detection enable */ +-#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ +-#define E1000_I2CCMD_REG_ADDR_SHIFT 16 +-#define E1000_I2CCMD_PHY_ADDR_SHIFT 24 +-#define E1000_I2CCMD_OPCODE_READ 0x08000000 +-#define E1000_I2CCMD_OPCODE_WRITE 0x00000000 +-#define E1000_I2CCMD_READY 0x20000000 +-#define E1000_I2CCMD_ERROR 0x80000000 +-#define E1000_MAX_SGMII_PHY_REG_ADDR 255 +-#define E1000_I2CCMD_PHY_TIMEOUT 200 +-#define E1000_IVAR_VALID 0x80 +-#define E1000_GPIE_NSICR 0x00000001 +-#define E1000_GPIE_MSIX_MODE 0x00000010 +-#define E1000_GPIE_EIAME 0x40000000 +-#define E1000_GPIE_PBA 0x80000000 ++#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ ++#define E1000_I2CCMD_REG_ADDR_SHIFT 16 ++#define E1000_I2CCMD_PHY_ADDR_SHIFT 24 ++#define E1000_I2CCMD_OPCODE_READ 0x08000000 ++#define E1000_I2CCMD_OPCODE_WRITE 0x00000000 ++#define E1000_I2CCMD_READY 0x20000000 ++#define E1000_I2CCMD_ERROR 0x80000000 ++#define E1000_I2CCMD_SFP_DATA_ADDR(a) (0x0000 + (a)) ++#define E1000_I2CCMD_SFP_DIAG_ADDR(a) (0x0100 + (a)) ++#define E1000_MAX_SGMII_PHY_REG_ADDR 255 ++#define E1000_I2CCMD_PHY_TIMEOUT 200 ++#define E1000_IVAR_VALID 0x80 ++#define E1000_GPIE_NSICR 0x00000001 ++#define E1000_GPIE_MSIX_MODE 0x00000010 ++#define E1000_GPIE_EIAME 0x40000000 ++#define E1000_GPIE_PBA 0x80000000 + + /* Receive Descriptor bit definitions */ + #define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ +@@ -136,8 +138,7 @@ + #define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ + #define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ + +-/* +- * Use byte values for the following shift parameters ++/* Use byte values for the following shift parameters + * Usage: + * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) & + * E1000_PSRCTL_BSIZE0_MASK) | +@@ -235,11 +236,14 @@ + #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 + /* BMC external code execution disabled */ + ++#define E1000_STATUS_2P5_SKU 0x00001000 /* Val of 2.5GBE SKU strap */ ++#define E1000_STATUS_2P5_SKU_OVER 0x00002000 /* Val of 2.5GBE SKU Over */ + /* Constants used to intrepret the masked PCI-X bus speed. */ + + #define SPEED_10 10 + #define SPEED_100 100 + #define SPEED_1000 1000 ++#define SPEED_2500 2500 + #define HALF_DUPLEX 1 + #define FULL_DUPLEX 2 + +@@ -266,8 +270,10 @@ + #define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX + + /* LED Control */ +-#define E1000_LEDCTL_LED0_MODE_SHIFT 0 +-#define E1000_LEDCTL_LED0_BLINK 0x00000080 ++#define E1000_LEDCTL_LED0_MODE_SHIFT 0 ++#define E1000_LEDCTL_LED0_BLINK 0x00000080 ++#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F ++#define E1000_LEDCTL_LED0_IVRT 0x00000040 + + #define E1000_LEDCTL_MODE_LED_ON 0xE + #define E1000_LEDCTL_MODE_LED_OFF 0xF +@@ -299,6 +305,8 @@ + * transactions */ + #define E1000_DMACR_DMAC_LX_SHIFT 28 + #define E1000_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */ ++/* DMA Coalescing BMC-to-OS Watchdog Enable */ ++#define E1000_DMACR_DC_BMC2OSW_EN 0x00008000 + + #define E1000_DMCTXTH_DMCTTHR_MASK 0x00000FFF /* DMA Coalescing Transmit + * Threshold */ +@@ -318,6 +326,9 @@ + #define E1000_FCRTC_RTH_COAL_SHIFT 4 + #define E1000_PCIEMISC_LX_DECISION 0x00000080 /* Lx power decision */ + ++/* Timestamp in Rx buffer */ ++#define E1000_RXPBS_CFG_TS_EN 0x80000000 ++ + /* SerDes Control */ + #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 + +@@ -356,6 +367,7 @@ + #define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ + #define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ + #define E1000_ICR_VMMB 0x00000100 /* VM MB event */ ++#define E1000_ICR_TS 0x00080000 /* Time Sync Interrupt */ + #define E1000_ICR_DRSTA 0x40000000 /* Device Reset Asserted */ + /* If this bit asserted, the driver should claim the interrupt */ + #define E1000_ICR_INT_ASSERTED 0x80000000 +@@ -374,8 +386,7 @@ + #define E1000_EICR_OTHER 0x80000000 /* Interrupt Cause Active */ + /* TCP Timer */ + +-/* +- * This defines the bits that are set in the Interrupt Mask ++/* This defines the bits that are set in the Interrupt Mask + * Set/Read Register. Each bit is documented below: + * o RXT0 = Receiver Timer Interrupt (ring 0) + * o TXDW = Transmit Descriptor Written Back +@@ -395,6 +406,7 @@ + #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ + #define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ + #define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */ ++#define E1000_IMS_TS E1000_ICR_TS /* Time Sync Interrupt */ + #define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ + #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ + #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +@@ -422,13 +434,16 @@ + #define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 + #define FLOW_CONTROL_TYPE 0x8808 + ++/* Transmit Config Word */ ++#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ ++#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ ++ + /* 802.1q VLAN Packet Size */ + #define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */ + #define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ + + /* Receive Address */ +-/* +- * Number of high/low register pairs in the RAR. The RAR (Receive Address ++/* Number of high/low register pairs in the RAR. The RAR (Receive Address + * Registers) holds the directed and multicast addresses that we monitor. + * Technically, we have 16 spots. However, we reserve one of these spots + * (RAR[15]) for our directed address used by controllers with +@@ -456,6 +471,8 @@ + #define E1000_ERR_INVALID_ARGUMENT 16 + #define E1000_ERR_NO_SPACE 17 + #define E1000_ERR_NVM_PBA_SECTION 18 ++#define E1000_ERR_INVM_VALUE_NOT_FOUND 19 ++#define E1000_ERR_I2C 20 + + /* Loop limit on how long we wait for auto-negotiation to complete */ + #define COPPER_LINK_UP_LIMIT 10 +@@ -505,6 +522,9 @@ + + #define E1000_TIMINCA_16NS_SHIFT 24 + ++#define E1000_TSICR_TXTS 0x00000002 ++#define E1000_TSIM_TXTS 0x00000002 ++ + #define E1000_MDICNFG_EXT_MDIO 0x80000000 /* MDI ext/int destination */ + #define E1000_MDICNFG_COM_MDIO 0x40000000 /* MDI shared w/ lan 0 */ + #define E1000_MDICNFG_PHY_MASK 0x03E00000 +@@ -526,6 +546,9 @@ + /* mPHY Near End Digital Loopback Override Bit */ + #define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10 + ++#define E1000_PCS_LCTL_FORCE_FCTRL 0x80 ++#define E1000_PCS_LSTS_AN_COMPLETE 0x10000 ++ + /* PHY Control Register */ + #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ + #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ +@@ -593,6 +616,31 @@ + #define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ + #define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */ + #define E1000_EECD_SIZE_EX_SHIFT 11 ++#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */ ++#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/ ++#define E1000_EECD_FLASH_DETECTED_I210 0x00080000 /* FLASH detected */ ++#define E1000_FLUDONE_ATTEMPTS 20000 ++#define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */ ++#define E1000_I210_FIFO_SEL_RX 0x00 ++#define E1000_I210_FIFO_SEL_TX_QAV(_i) (0x02 + (_i)) ++#define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0) ++#define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06 ++#define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01 ++#define E1000_I210_FLASH_SECTOR_SIZE 0x1000 /* 4KB FLASH sector unit size */ ++/* Secure FLASH mode requires removing MSb */ ++#define E1000_I210_FW_PTR_MASK 0x7FFF ++/* Firmware code revision field word offset*/ ++#define E1000_I210_FW_VER_OFFSET 328 ++#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */ ++#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/ ++#define E1000_FLUDONE_ATTEMPTS 20000 ++#define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */ ++#define E1000_I210_FIFO_SEL_RX 0x00 ++#define E1000_I210_FIFO_SEL_TX_QAV(_i) (0x02 + (_i)) ++#define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0) ++#define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06 ++#define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01 ++ + + /* Offset to data in NVM read/write registers */ + #define E1000_NVM_RW_REG_DATA 16 +@@ -604,6 +652,7 @@ + /* NVM Word Offsets */ + #define NVM_COMPAT 0x0003 + #define NVM_ID_LED_SETTINGS 0x0004 /* SERDES output amplitude */ ++#define NVM_VERSION 0x0005 + #define NVM_INIT_CONTROL2_REG 0x000F + #define NVM_INIT_CONTROL3_PORT_B 0x0014 + #define NVM_INIT_CONTROL3_PORT_A 0x0024 +@@ -611,6 +660,47 @@ + #define NVM_CHECKSUM_REG 0x003F + #define NVM_COMPATIBILITY_REG_3 0x0003 + #define NVM_COMPATIBILITY_BIT_MASK 0x8000 ++#define NVM_MAC_ADDR 0x0000 ++#define NVM_SUB_DEV_ID 0x000B ++#define NVM_SUB_VEN_ID 0x000C ++#define NVM_DEV_ID 0x000D ++#define NVM_VEN_ID 0x000E ++#define NVM_INIT_CTRL_2 0x000F ++#define NVM_INIT_CTRL_4 0x0013 ++#define NVM_LED_1_CFG 0x001C ++#define NVM_LED_0_2_CFG 0x001F ++#define NVM_ETRACK_WORD 0x0042 ++#define NVM_ETRACK_HIWORD 0x0043 ++#define NVM_COMB_VER_OFF 0x0083 ++#define NVM_COMB_VER_PTR 0x003d ++ ++/* NVM version defines */ ++#define NVM_MAJOR_MASK 0xF000 ++#define NVM_MINOR_MASK 0x0FF0 ++#define NVM_IMAGE_ID_MASK 0x000F ++#define NVM_COMB_VER_MASK 0x00FF ++#define NVM_MAJOR_SHIFT 12 ++#define NVM_MINOR_SHIFT 4 ++#define NVM_COMB_VER_SHFT 8 ++#define NVM_VER_INVALID 0xFFFF ++#define NVM_ETRACK_SHIFT 16 ++#define NVM_ETRACK_VALID 0x8000 ++#define NVM_NEW_DEC_MASK 0x0F00 ++#define NVM_HEX_CONV 16 ++#define NVM_HEX_TENS 10 ++ ++#define NVM_ETS_CFG 0x003E ++#define NVM_ETS_LTHRES_DELTA_MASK 0x07C0 ++#define NVM_ETS_LTHRES_DELTA_SHIFT 6 ++#define NVM_ETS_TYPE_MASK 0x0038 ++#define NVM_ETS_TYPE_SHIFT 3 ++#define NVM_ETS_TYPE_EMC 0x000 ++#define NVM_ETS_NUM_SENSORS_MASK 0x0007 ++#define NVM_ETS_DATA_LOC_MASK 0x3C00 ++#define NVM_ETS_DATA_LOC_SHIFT 10 ++#define NVM_ETS_DATA_INDEX_MASK 0x0300 ++#define NVM_ETS_DATA_INDEX_SHIFT 8 ++#define NVM_ETS_DATA_HTHRESH_MASK 0x00FF + + #define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */ + #define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */ +@@ -637,6 +727,7 @@ + + #define NVM_PBA_OFFSET_0 8 + #define NVM_PBA_OFFSET_1 9 ++#define NVM_RESERVED_WORD 0xFFFF + #define NVM_PBA_PTR_GUARD 0xFAFA + #define NVM_WORD_SIZE_BASE_SHIFT 6 + +@@ -683,8 +774,7 @@ + #define MAX_PHY_MULTI_PAGE_REG 0xF + + /* Bit definitions for valid PHY IDs. */ +-/* +- * I = Integrated ++/* I = Integrated + * E = External + */ + #define M88E1111_I_PHY_ID 0x01410CC0 +@@ -694,6 +784,10 @@ + #define I82580_I_PHY_ID 0x015403A0 + #define I350_I_PHY_ID 0x015403B0 + #define M88_VENDOR 0x0141 ++#define I210_I_PHY_ID 0x01410C00 ++#define M88E1543_E_PHY_ID 0x01410EA0 ++#define BCM54616_E_PHY_ID 0x3625D10 ++#define BCM5461S_PHY_ID 0x002060C0 + + /* M88E1000 Specific Registers */ + #define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ +@@ -713,8 +807,7 @@ + #define M88E1000_PSCR_AUTO_X_1000T 0x0040 + /* Auto crossover enabled all speeds */ + #define M88E1000_PSCR_AUTO_X_MODE 0x0060 +-/* +- * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold ++/* 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold + * 0=Normal 10BASE-T Rx Threshold + */ + /* 1=5-bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */ +@@ -724,8 +817,7 @@ + #define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ + #define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */ + #define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ +-/* +- * 0 = <50M ++/* 0 = <50M + * 1 = 50-80M + * 2 = 80-110M + * 3 = 110-140M +@@ -738,20 +830,17 @@ + #define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 + + /* M88E1000 Extended PHY Specific Control Register */ +-/* +- * 1 = Lost lock detect enabled. ++/* 1 = Lost lock detect enabled. + * Will assert lost lock and bring + * link down if idle not seen + * within 1ms in 1000BASE-T + */ +-/* +- * Number of times we will attempt to autonegotiate before downshifting if we ++/* Number of times we will attempt to autonegotiate before downshifting if we + * are the master + */ + #define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 + #define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 +-/* +- * Number of times we will attempt to autonegotiate before downshifting if we ++/* Number of times we will attempt to autonegotiate before downshifting if we + * are the slave + */ + #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 +@@ -766,8 +855,7 @@ + + /* i347-AT4 Extended PHY Specific Control Register */ + +-/* +- * Number of times we will attempt to autonegotiate before downshifting if we ++/* Number of times we will attempt to autonegotiate before downshifting if we + * are the master + */ + #define I347AT4_PSCR_DOWNSHIFT_ENABLE 0x0800 +@@ -813,7 +901,25 @@ + #define E1000_IPCNFG_EEE_100M_AN 0x00000004 /* EEE Enable 100M AN */ + #define E1000_EEER_TX_LPI_EN 0x00010000 /* EEE Tx LPI Enable */ + #define E1000_EEER_RX_LPI_EN 0x00020000 /* EEE Rx LPI Enable */ ++#define E1000_EEER_FRC_AN 0x10000000 /* Enable EEE in loopback */ + #define E1000_EEER_LPI_FC 0x00040000 /* EEE Enable on FC */ ++#define E1000_EEE_SU_LPI_CLK_STP 0X00800000 /* EEE LPI Clock Stop */ ++#define E1000_EEE_LP_ADV_ADDR_I350 0x040F /* EEE LP Advertisement */ ++#define E1000_EEE_LP_ADV_DEV_I210 7 /* EEE LP Adv Device */ ++#define E1000_EEE_LP_ADV_ADDR_I210 61 /* EEE LP Adv Register */ ++#define E1000_MMDAC_FUNC_DATA 0x4000 /* Data, no post increment */ ++#define E1000_M88E1543_PAGE_ADDR 0x16 /* Page Offset Register */ ++#define E1000_M88E1543_EEE_CTRL_1 0x0 ++#define E1000_M88E1543_EEE_CTRL_1_MS 0x0001 /* EEE Master/Slave */ ++#define E1000_EEE_ADV_DEV_I354 7 ++#define E1000_EEE_ADV_ADDR_I354 60 ++#define E1000_EEE_ADV_100_SUPPORTED (1 << 1) /* 100BaseTx EEE Supported */ ++#define E1000_EEE_ADV_1000_SUPPORTED (1 << 2) /* 1000BaseT EEE Supported */ ++#define E1000_PCS_STATUS_DEV_I354 3 ++#define E1000_PCS_STATUS_ADDR_I354 1 ++#define E1000_PCS_STATUS_TX_LPI_IND 0x0200 /* Tx in LPI state */ ++#define E1000_PCS_STATUS_RX_LPI_RCVD 0x0400 ++#define E1000_PCS_STATUS_TX_LPI_RCVD 0x0800 + + /* SerDes Control */ + #define E1000_GEN_CTL_READY 0x80000000 +diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h +index 4519a13..d7d3504 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_hw.h ++++ b/drivers/net/ethernet/intel/igb/e1000_hw.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -38,31 +38,41 @@ + + struct e1000_hw; + +-#define E1000_DEV_ID_82576 0x10C9 +-#define E1000_DEV_ID_82576_FIBER 0x10E6 +-#define E1000_DEV_ID_82576_SERDES 0x10E7 +-#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8 +-#define E1000_DEV_ID_82576_QUAD_COPPER_ET2 0x1526 +-#define E1000_DEV_ID_82576_NS 0x150A +-#define E1000_DEV_ID_82576_NS_SERDES 0x1518 +-#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D +-#define E1000_DEV_ID_82575EB_COPPER 0x10A7 +-#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 +-#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 +-#define E1000_DEV_ID_82580_COPPER 0x150E +-#define E1000_DEV_ID_82580_FIBER 0x150F +-#define E1000_DEV_ID_82580_SERDES 0x1510 +-#define E1000_DEV_ID_82580_SGMII 0x1511 +-#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516 +-#define E1000_DEV_ID_82580_QUAD_FIBER 0x1527 +-#define E1000_DEV_ID_DH89XXCC_SGMII 0x0438 +-#define E1000_DEV_ID_DH89XXCC_SERDES 0x043A +-#define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C +-#define E1000_DEV_ID_DH89XXCC_SFP 0x0440 +-#define E1000_DEV_ID_I350_COPPER 0x1521 +-#define E1000_DEV_ID_I350_FIBER 0x1522 +-#define E1000_DEV_ID_I350_SERDES 0x1523 +-#define E1000_DEV_ID_I350_SGMII 0x1524 ++#define E1000_DEV_ID_82576 0x10C9 ++#define E1000_DEV_ID_82576_FIBER 0x10E6 ++#define E1000_DEV_ID_82576_SERDES 0x10E7 ++#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8 ++#define E1000_DEV_ID_82576_QUAD_COPPER_ET2 0x1526 ++#define E1000_DEV_ID_82576_NS 0x150A ++#define E1000_DEV_ID_82576_NS_SERDES 0x1518 ++#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D ++#define E1000_DEV_ID_82575EB_COPPER 0x10A7 ++#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 ++#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 ++#define E1000_DEV_ID_82580_COPPER 0x150E ++#define E1000_DEV_ID_82580_FIBER 0x150F ++#define E1000_DEV_ID_82580_SERDES 0x1510 ++#define E1000_DEV_ID_82580_SGMII 0x1511 ++#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516 ++#define E1000_DEV_ID_82580_QUAD_FIBER 0x1527 ++#define E1000_DEV_ID_DH89XXCC_SGMII 0x0438 ++#define E1000_DEV_ID_DH89XXCC_SERDES 0x043A ++#define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C ++#define E1000_DEV_ID_DH89XXCC_SFP 0x0440 ++#define E1000_DEV_ID_I350_COPPER 0x1521 ++#define E1000_DEV_ID_I350_FIBER 0x1522 ++#define E1000_DEV_ID_I350_SERDES 0x1523 ++#define E1000_DEV_ID_I350_SGMII 0x1524 ++#define E1000_DEV_ID_I210_COPPER 0x1533 ++#define E1000_DEV_ID_I210_FIBER 0x1536 ++#define E1000_DEV_ID_I210_SERDES 0x1537 ++#define E1000_DEV_ID_I210_SGMII 0x1538 ++#define E1000_DEV_ID_I210_COPPER_FLASHLESS 0x157B ++#define E1000_DEV_ID_I210_SERDES_FLASHLESS 0x157C ++#define E1000_DEV_ID_I211_COPPER 0x1539 ++#define E1000_DEV_ID_I354_BACKPLANE_1GBPS 0x1F40 ++#define E1000_DEV_ID_I354_SGMII 0x1F41 ++#define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS 0x1F45 + + #define E1000_REVISION_2 2 + #define E1000_REVISION_4 4 +@@ -83,13 +93,17 @@ enum e1000_mac_type { + e1000_82576, + e1000_82580, + e1000_i350, ++ e1000_i354, ++ e1000_i210, ++ e1000_i211, + e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ + }; + + enum e1000_media_type { + e1000_media_type_unknown = 0, + e1000_media_type_copper = 1, +- e1000_media_type_internal_serdes = 2, ++ e1000_media_type_fiber = 2, ++ e1000_media_type_internal_serdes = 3, + e1000_num_media_types + }; + +@@ -98,6 +112,7 @@ enum e1000_nvm_type { + e1000_nvm_none, + e1000_nvm_eeprom_spi, + e1000_nvm_flash_hw, ++ e1000_nvm_invm, + e1000_nvm_flash_sw + }; + +@@ -117,6 +132,9 @@ enum e1000_phy_type { + e1000_phy_igp_3, + e1000_phy_ife, + e1000_phy_82580, ++ e1000_phy_i210, ++ e1000_phy_bcm54616, ++ e1000_phy_bcm5461s, + }; + + enum e1000_bus_type { +@@ -313,6 +331,13 @@ struct e1000_mac_operations { + void (*rar_set)(struct e1000_hw *, u8 *, u32); + s32 (*read_mac_addr)(struct e1000_hw *); + s32 (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *); ++ s32 (*acquire_swfw_sync)(struct e1000_hw *, u16); ++ void (*release_swfw_sync)(struct e1000_hw *, u16); ++#ifdef CONFIG_IGB_HWMON ++ s32 (*get_thermal_sensor_data)(struct e1000_hw *); ++ s32 (*init_thermal_sensor_thresh)(struct e1000_hw *); ++#endif ++ + }; + + struct e1000_phy_operations { +@@ -329,6 +354,8 @@ struct e1000_phy_operations { + s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); + s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); + s32 (*write_reg)(struct e1000_hw *, u32, u16); ++ s32 (*read_i2c_byte)(struct e1000_hw *, u8, u8, u8 *); ++ s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8); + }; + + struct e1000_nvm_operations { +@@ -338,6 +365,20 @@ struct e1000_nvm_operations { + s32 (*write)(struct e1000_hw *, u16, u16, u16 *); + s32 (*update)(struct e1000_hw *); + s32 (*validate)(struct e1000_hw *); ++ s32 (*valid_led_default)(struct e1000_hw *, u16 *); ++}; ++ ++#define E1000_MAX_SENSORS 3 ++ ++struct e1000_thermal_diode_data { ++ u8 location; ++ u8 temp; ++ u8 caution_thresh; ++ u8 max_op_thresh; ++}; ++ ++struct e1000_thermal_sensor_data { ++ struct e1000_thermal_diode_data sensor[E1000_MAX_SENSORS]; + }; + + struct e1000_info { +@@ -385,6 +426,7 @@ struct e1000_mac_info { + bool report_tx_early; + bool serdes_has_link; + bool tx_pkt_filtering; ++ struct e1000_thermal_sensor_data thermal_sensor_data; + }; + + struct e1000_phy_info { +@@ -490,6 +532,9 @@ struct e1000_dev_spec_82575 { + bool sgmii_active; + bool global_device_reset; + bool eee_disable; ++ bool clear_semaphore_once; ++ struct e1000_sfp_flags eth_flags; ++ bool module_plugged; + }; + + struct e1000_hw { +@@ -519,11 +564,11 @@ struct e1000_hw { + u8 revision_id; + }; + +-extern struct net_device *igb_get_hw_dev(struct e1000_hw *hw); ++struct net_device *igb_get_hw_dev(struct e1000_hw *hw); + #define hw_dbg(format, arg...) \ + netdev_dbg(igb_get_hw_dev(hw), format, ##arg) + + /* These functions must be implemented by drivers */ +-s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); +-s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); ++s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); ++s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); + #endif /* _E1000_HW_H_ */ +diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c +new file mode 100644 +index 0000000..0c03933 +--- /dev/null ++++ b/drivers/net/ethernet/intel/igb/e1000_i210.c +@@ -0,0 +1,837 @@ ++/******************************************************************************* ++ ++ Intel(R) Gigabit Ethernet Linux driver ++ Copyright(c) 2007-2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++******************************************************************************/ ++ ++/* e1000_i210 ++ * e1000_i211 ++ */ ++ ++#include ++#include ++ ++#include "e1000_hw.h" ++#include "e1000_i210.h" ++ ++/** ++ * igb_get_hw_semaphore_i210 - Acquire hardware semaphore ++ * @hw: pointer to the HW structure ++ * ++ * Acquire the HW semaphore to access the PHY or NVM ++ */ ++static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw) ++{ ++ u32 swsm; ++ s32 timeout = hw->nvm.word_size + 1; ++ s32 i = 0; ++ ++ /* Get the SW semaphore */ ++ while (i < timeout) { ++ swsm = rd32(E1000_SWSM); ++ if (!(swsm & E1000_SWSM_SMBI)) ++ break; ++ ++ udelay(50); ++ i++; ++ } ++ ++ if (i == timeout) { ++ /* In rare circumstances, the SW semaphore may already be held ++ * unintentionally. Clear the semaphore once before giving up. ++ */ ++ if (hw->dev_spec._82575.clear_semaphore_once) { ++ hw->dev_spec._82575.clear_semaphore_once = false; ++ igb_put_hw_semaphore(hw); ++ for (i = 0; i < timeout; i++) { ++ swsm = rd32(E1000_SWSM); ++ if (!(swsm & E1000_SWSM_SMBI)) ++ break; ++ ++ udelay(50); ++ } ++ } ++ ++ /* If we do not have the semaphore here, we have to give up. */ ++ if (i == timeout) { ++ hw_dbg("Driver can't access device - SMBI bit is set.\n"); ++ return -E1000_ERR_NVM; ++ } ++ } ++ ++ /* Get the FW semaphore. */ ++ for (i = 0; i < timeout; i++) { ++ swsm = rd32(E1000_SWSM); ++ wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI); ++ ++ /* Semaphore acquired if bit latched */ ++ if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI) ++ break; ++ ++ udelay(50); ++ } ++ ++ if (i == timeout) { ++ /* Release semaphores */ ++ igb_put_hw_semaphore(hw); ++ hw_dbg("Driver can't access the NVM\n"); ++ return -E1000_ERR_NVM; ++ } ++ ++ return E1000_SUCCESS; ++} ++ ++/** ++ * igb_acquire_nvm_i210 - Request for access to EEPROM ++ * @hw: pointer to the HW structure ++ * ++ * Acquire the necessary semaphores for exclusive access to the EEPROM. ++ * Set the EEPROM access request bit and wait for EEPROM access grant bit. ++ * Return successful if access grant bit set, else clear the request for ++ * EEPROM access and return -E1000_ERR_NVM (-1). ++ **/ ++s32 igb_acquire_nvm_i210(struct e1000_hw *hw) ++{ ++ return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); ++} ++ ++/** ++ * igb_release_nvm_i210 - Release exclusive access to EEPROM ++ * @hw: pointer to the HW structure ++ * ++ * Stop any current commands to the EEPROM and clear the EEPROM request bit, ++ * then release the semaphores acquired. ++ **/ ++void igb_release_nvm_i210(struct e1000_hw *hw) ++{ ++ igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); ++} ++ ++/** ++ * igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore ++ * @hw: pointer to the HW structure ++ * @mask: specifies which semaphore to acquire ++ * ++ * Acquire the SW/FW semaphore to access the PHY or NVM. The mask ++ * will also specify which port we're acquiring the lock for. ++ **/ ++s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) ++{ ++ u32 swfw_sync; ++ u32 swmask = mask; ++ u32 fwmask = mask << 16; ++ s32 ret_val = E1000_SUCCESS; ++ s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ ++ ++ while (i < timeout) { ++ if (igb_get_hw_semaphore_i210(hw)) { ++ ret_val = -E1000_ERR_SWFW_SYNC; ++ goto out; ++ } ++ ++ swfw_sync = rd32(E1000_SW_FW_SYNC); ++ if (!(swfw_sync & (fwmask | swmask))) ++ break; ++ ++ /* Firmware currently using resource (fwmask) */ ++ igb_put_hw_semaphore(hw); ++ mdelay(5); ++ i++; ++ } ++ ++ if (i == timeout) { ++ hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); ++ ret_val = -E1000_ERR_SWFW_SYNC; ++ goto out; ++ } ++ ++ swfw_sync |= swmask; ++ wr32(E1000_SW_FW_SYNC, swfw_sync); ++ ++ igb_put_hw_semaphore(hw); ++out: ++ return ret_val; ++} ++ ++/** ++ * igb_release_swfw_sync_i210 - Release SW/FW semaphore ++ * @hw: pointer to the HW structure ++ * @mask: specifies which semaphore to acquire ++ * ++ * Release the SW/FW semaphore used to access the PHY or NVM. The mask ++ * will also specify which port we're releasing the lock for. ++ **/ ++void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) ++{ ++ u32 swfw_sync; ++ ++ while (igb_get_hw_semaphore_i210(hw) != E1000_SUCCESS) ++ ; /* Empty */ ++ ++ swfw_sync = rd32(E1000_SW_FW_SYNC); ++ swfw_sync &= ~mask; ++ wr32(E1000_SW_FW_SYNC, swfw_sync); ++ ++ igb_put_hw_semaphore(hw); ++} ++ ++/** ++ * igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register ++ * @hw: pointer to the HW structure ++ * @offset: offset of word in the Shadow Ram to read ++ * @words: number of words to read ++ * @data: word read from the Shadow Ram ++ * ++ * Reads a 16 bit word from the Shadow Ram using the EERD register. ++ * Uses necessary synchronization semaphores. ++ **/ ++s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, ++ u16 *data) ++{ ++ s32 status = E1000_SUCCESS; ++ u16 i, count; ++ ++ /* We cannot hold synchronization semaphores for too long, ++ * because of forceful takeover procedure. However it is more efficient ++ * to read in bursts than synchronizing access for each word. ++ */ ++ for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { ++ count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? ++ E1000_EERD_EEWR_MAX_COUNT : (words - i); ++ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { ++ status = igb_read_nvm_eerd(hw, offset, count, ++ data + i); ++ hw->nvm.ops.release(hw); ++ } else { ++ status = E1000_ERR_SWFW_SYNC; ++ } ++ ++ if (status != E1000_SUCCESS) ++ break; ++ } ++ ++ return status; ++} ++ ++/** ++ * igb_write_nvm_srwr - Write to Shadow Ram using EEWR ++ * @hw: pointer to the HW structure ++ * @offset: offset within the Shadow Ram to be written to ++ * @words: number of words to write ++ * @data: 16 bit word(s) to be written to the Shadow Ram ++ * ++ * Writes data to Shadow Ram at offset using EEWR register. ++ * ++ * If igb_update_nvm_checksum is not called after this function , the ++ * Shadow Ram will most likely contain an invalid checksum. ++ **/ ++static s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, ++ u16 *data) ++{ ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ u32 i, k, eewr = 0; ++ u32 attempts = 100000; ++ s32 ret_val = E1000_SUCCESS; ++ ++ /* A check for invalid values: offset too large, too many words, ++ * too many words for the offset, and not enough words. ++ */ ++ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || ++ (words == 0)) { ++ hw_dbg("nvm parameter(s) out of bounds\n"); ++ ret_val = -E1000_ERR_NVM; ++ goto out; ++ } ++ ++ for (i = 0; i < words; i++) { ++ eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | ++ (data[i] << E1000_NVM_RW_REG_DATA) | ++ E1000_NVM_RW_REG_START; ++ ++ wr32(E1000_SRWR, eewr); ++ ++ for (k = 0; k < attempts; k++) { ++ if (E1000_NVM_RW_REG_DONE & ++ rd32(E1000_SRWR)) { ++ ret_val = E1000_SUCCESS; ++ break; ++ } ++ udelay(5); ++ } ++ ++ if (ret_val != E1000_SUCCESS) { ++ hw_dbg("Shadow RAM write EEWR timed out\n"); ++ break; ++ } ++ } ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR ++ * @hw: pointer to the HW structure ++ * @offset: offset within the Shadow RAM to be written to ++ * @words: number of words to write ++ * @data: 16 bit word(s) to be written to the Shadow RAM ++ * ++ * Writes data to Shadow RAM at offset using EEWR register. ++ * ++ * If e1000_update_nvm_checksum is not called after this function , the ++ * data will not be committed to FLASH and also Shadow RAM will most likely ++ * contain an invalid checksum. ++ * ++ * If error code is returned, data and Shadow RAM may be inconsistent - buffer ++ * partially written. ++ **/ ++s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, ++ u16 *data) ++{ ++ s32 status = E1000_SUCCESS; ++ u16 i, count; ++ ++ /* We cannot hold synchronization semaphores for too long, ++ * because of forceful takeover procedure. However it is more efficient ++ * to write in bursts than synchronizing access for each word. ++ */ ++ for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { ++ count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? ++ E1000_EERD_EEWR_MAX_COUNT : (words - i); ++ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { ++ status = igb_write_nvm_srwr(hw, offset, count, ++ data + i); ++ hw->nvm.ops.release(hw); ++ } else { ++ status = E1000_ERR_SWFW_SYNC; ++ } ++ ++ if (status != E1000_SUCCESS) ++ break; ++ } ++ ++ return status; ++} ++ ++/** ++ * igb_read_invm_word_i210 - Reads OTP ++ * @hw: pointer to the HW structure ++ * @address: the word address (aka eeprom offset) to read ++ * @data: pointer to the data read ++ * ++ * Reads 16-bit words from the OTP. Return error when the word is not ++ * stored in OTP. ++ **/ ++static s32 igb_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data) ++{ ++ s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; ++ u32 invm_dword; ++ u16 i; ++ u8 record_type, word_address; ++ ++ for (i = 0; i < E1000_INVM_SIZE; i++) { ++ invm_dword = rd32(E1000_INVM_DATA_REG(i)); ++ /* Get record type */ ++ record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword); ++ if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE) ++ break; ++ if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE) ++ i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS; ++ if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE) ++ i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS; ++ if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) { ++ word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword); ++ if (word_address == address) { ++ *data = INVM_DWORD_TO_WORD_DATA(invm_dword); ++ hw_dbg("Read INVM Word 0x%02x = %x", ++ address, *data); ++ status = E1000_SUCCESS; ++ break; ++ } ++ } ++ } ++ if (status != E1000_SUCCESS) ++ hw_dbg("Requested word 0x%02x not found in OTP\n", address); ++ return status; ++} ++ ++/** ++ * igb_read_invm_i210 - Read invm wrapper function for I210/I211 ++ * @hw: pointer to the HW structure ++ * @words: number of words to read ++ * @data: pointer to the data read ++ * ++ * Wrapper function to return data formerly found in the NVM. ++ **/ ++static s32 igb_read_invm_i210(struct e1000_hw *hw, u16 offset, ++ u16 words __always_unused, u16 *data) ++{ ++ s32 ret_val = E1000_SUCCESS; ++ ++ /* Only the MAC addr is required to be present in the iNVM */ ++ switch (offset) { ++ case NVM_MAC_ADDR: ++ ret_val = igb_read_invm_word_i210(hw, (u8)offset, &data[0]); ++ ret_val |= igb_read_invm_word_i210(hw, (u8)offset+1, ++ &data[1]); ++ ret_val |= igb_read_invm_word_i210(hw, (u8)offset+2, ++ &data[2]); ++ if (ret_val != E1000_SUCCESS) ++ hw_dbg("MAC Addr not found in iNVM\n"); ++ break; ++ case NVM_INIT_CTRL_2: ++ ret_val = igb_read_invm_word_i210(hw, (u8)offset, data); ++ if (ret_val != E1000_SUCCESS) { ++ *data = NVM_INIT_CTRL_2_DEFAULT_I211; ++ ret_val = E1000_SUCCESS; ++ } ++ break; ++ case NVM_INIT_CTRL_4: ++ ret_val = igb_read_invm_word_i210(hw, (u8)offset, data); ++ if (ret_val != E1000_SUCCESS) { ++ *data = NVM_INIT_CTRL_4_DEFAULT_I211; ++ ret_val = E1000_SUCCESS; ++ } ++ break; ++ case NVM_LED_1_CFG: ++ ret_val = igb_read_invm_word_i210(hw, (u8)offset, data); ++ if (ret_val != E1000_SUCCESS) { ++ *data = NVM_LED_1_CFG_DEFAULT_I211; ++ ret_val = E1000_SUCCESS; ++ } ++ break; ++ case NVM_LED_0_2_CFG: ++ ret_val = igb_read_invm_word_i210(hw, (u8)offset, data); ++ if (ret_val != E1000_SUCCESS) { ++ *data = NVM_LED_0_2_CFG_DEFAULT_I211; ++ ret_val = E1000_SUCCESS; ++ } ++ break; ++ case NVM_ID_LED_SETTINGS: ++ ret_val = igb_read_invm_word_i210(hw, (u8)offset, data); ++ if (ret_val != E1000_SUCCESS) { ++ *data = ID_LED_RESERVED_FFFF; ++ ret_val = E1000_SUCCESS; ++ } ++ case NVM_SUB_DEV_ID: ++ *data = hw->subsystem_device_id; ++ break; ++ case NVM_SUB_VEN_ID: ++ *data = hw->subsystem_vendor_id; ++ break; ++ case NVM_DEV_ID: ++ *data = hw->device_id; ++ break; ++ case NVM_VEN_ID: ++ *data = hw->vendor_id; ++ break; ++ default: ++ hw_dbg("NVM word 0x%02x is not mapped.\n", offset); ++ *data = NVM_RESERVED_WORD; ++ break; ++ } ++ return ret_val; ++} ++ ++/** ++ * igb_read_invm_version - Reads iNVM version and image type ++ * @hw: pointer to the HW structure ++ * @invm_ver: version structure for the version read ++ * ++ * Reads iNVM version and image type. ++ **/ ++s32 igb_read_invm_version(struct e1000_hw *hw, ++ struct e1000_fw_version *invm_ver) { ++ u32 *record = NULL; ++ u32 *next_record = NULL; ++ u32 i = 0; ++ u32 invm_dword = 0; ++ u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE / ++ E1000_INVM_RECORD_SIZE_IN_BYTES); ++ u32 buffer[E1000_INVM_SIZE]; ++ s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; ++ u16 version = 0; ++ ++ /* Read iNVM memory */ ++ for (i = 0; i < E1000_INVM_SIZE; i++) { ++ invm_dword = rd32(E1000_INVM_DATA_REG(i)); ++ buffer[i] = invm_dword; ++ } ++ ++ /* Read version number */ ++ for (i = 1; i < invm_blocks; i++) { ++ record = &buffer[invm_blocks - i]; ++ next_record = &buffer[invm_blocks - i + 1]; ++ ++ /* Check if we have first version location used */ ++ if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) { ++ version = 0; ++ status = E1000_SUCCESS; ++ break; ++ } ++ /* Check if we have second version location used */ ++ else if ((i == 1) && ++ ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) { ++ version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; ++ status = E1000_SUCCESS; ++ break; ++ } ++ /* Check if we have odd version location ++ * used and it is the last one used ++ */ ++ else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) && ++ ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) && ++ (i != 1))) { ++ version = (*next_record & E1000_INVM_VER_FIELD_TWO) ++ >> 13; ++ status = E1000_SUCCESS; ++ break; ++ } ++ /* Check if we have even version location ++ * used and it is the last one used ++ */ ++ else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) && ++ ((*record & 0x3) == 0)) { ++ version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; ++ status = E1000_SUCCESS; ++ break; ++ } ++ } ++ ++ if (status == E1000_SUCCESS) { ++ invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK) ++ >> E1000_INVM_MAJOR_SHIFT; ++ invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK; ++ } ++ /* Read Image Type */ ++ for (i = 1; i < invm_blocks; i++) { ++ record = &buffer[invm_blocks - i]; ++ next_record = &buffer[invm_blocks - i + 1]; ++ ++ /* Check if we have image type in first location used */ ++ if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) { ++ invm_ver->invm_img_type = 0; ++ status = E1000_SUCCESS; ++ break; ++ } ++ /* Check if we have image type in first location used */ ++ else if ((((*record & 0x3) == 0) && ++ ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) || ++ ((((*record & 0x3) != 0) && (i != 1)))) { ++ invm_ver->invm_img_type = ++ (*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23; ++ status = E1000_SUCCESS; ++ break; ++ } ++ } ++ return status; ++} ++ ++/** ++ * igb_validate_nvm_checksum_i210 - Validate EEPROM checksum ++ * @hw: pointer to the HW structure ++ * ++ * Calculates the EEPROM checksum by reading/adding each word of the EEPROM ++ * and then verifies that the sum of the EEPROM is equal to 0xBABA. ++ **/ ++s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw) ++{ ++ s32 status = E1000_SUCCESS; ++ s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *); ++ ++ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { ++ ++ /* Replace the read function with semaphore grabbing with ++ * the one that skips this for a while. ++ * We have semaphore taken already here. ++ */ ++ read_op_ptr = hw->nvm.ops.read; ++ hw->nvm.ops.read = igb_read_nvm_eerd; ++ ++ status = igb_validate_nvm_checksum(hw); ++ ++ /* Revert original read operation. */ ++ hw->nvm.ops.read = read_op_ptr; ++ ++ hw->nvm.ops.release(hw); ++ } else { ++ status = E1000_ERR_SWFW_SYNC; ++ } ++ ++ return status; ++} ++ ++/** ++ * igb_update_nvm_checksum_i210 - Update EEPROM checksum ++ * @hw: pointer to the HW structure ++ * ++ * Updates the EEPROM checksum by reading/adding each word of the EEPROM ++ * up to the checksum. Then calculates the EEPROM checksum and writes the ++ * value to the EEPROM. Next commit EEPROM data onto the Flash. ++ **/ ++s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw) ++{ ++ s32 ret_val = E1000_SUCCESS; ++ u16 checksum = 0; ++ u16 i, nvm_data; ++ ++ /* Read the first word from the EEPROM. If this times out or fails, do ++ * not continue or we could be in for a very long wait while every ++ * EEPROM read fails ++ */ ++ ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data); ++ if (ret_val != E1000_SUCCESS) { ++ hw_dbg("EEPROM read failed\n"); ++ goto out; ++ } ++ ++ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { ++ /* Do not use hw->nvm.ops.write, hw->nvm.ops.read ++ * because we do not want to take the synchronization ++ * semaphores twice here. ++ */ ++ ++ for (i = 0; i < NVM_CHECKSUM_REG; i++) { ++ ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data); ++ if (ret_val) { ++ hw->nvm.ops.release(hw); ++ hw_dbg("NVM Read Error while updating checksum.\n"); ++ goto out; ++ } ++ checksum += nvm_data; ++ } ++ checksum = (u16) NVM_SUM - checksum; ++ ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1, ++ &checksum); ++ if (ret_val != E1000_SUCCESS) { ++ hw->nvm.ops.release(hw); ++ hw_dbg("NVM Write Error while updating checksum.\n"); ++ goto out; ++ } ++ ++ hw->nvm.ops.release(hw); ++ ++ ret_val = igb_update_flash_i210(hw); ++ } else { ++ ret_val = -E1000_ERR_SWFW_SYNC; ++ } ++out: ++ return ret_val; ++} ++ ++/** ++ * igb_pool_flash_update_done_i210 - Pool FLUDONE status. ++ * @hw: pointer to the HW structure ++ * ++ **/ ++static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw) ++{ ++ s32 ret_val = -E1000_ERR_NVM; ++ u32 i, reg; ++ ++ for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) { ++ reg = rd32(E1000_EECD); ++ if (reg & E1000_EECD_FLUDONE_I210) { ++ ret_val = E1000_SUCCESS; ++ break; ++ } ++ udelay(5); ++ } ++ ++ return ret_val; ++} ++ ++/** ++ * igb_get_flash_presence_i210 - Check if flash device is detected. ++ * @hw: pointer to the HW structure ++ * ++ **/ ++bool igb_get_flash_presence_i210(struct e1000_hw *hw) ++{ ++ u32 eec = 0; ++ bool ret_val = false; ++ ++ eec = rd32(E1000_EECD); ++ if (eec & E1000_EECD_FLASH_DETECTED_I210) ++ ret_val = true; ++ ++ return ret_val; ++} ++ ++/** ++ * igb_update_flash_i210 - Commit EEPROM to the flash ++ * @hw: pointer to the HW structure ++ * ++ **/ ++s32 igb_update_flash_i210(struct e1000_hw *hw) ++{ ++ s32 ret_val = E1000_SUCCESS; ++ u32 flup; ++ ++ ret_val = igb_pool_flash_update_done_i210(hw); ++ if (ret_val == -E1000_ERR_NVM) { ++ hw_dbg("Flash update time out\n"); ++ goto out; ++ } ++ ++ flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210; ++ wr32(E1000_EECD, flup); ++ ++ ret_val = igb_pool_flash_update_done_i210(hw); ++ if (ret_val == E1000_SUCCESS) ++ hw_dbg("Flash update complete\n"); ++ else ++ hw_dbg("Flash update time out\n"); ++ ++out: ++ return ret_val; ++} ++ ++/** ++ * igb_valid_led_default_i210 - Verify a valid default LED config ++ * @hw: pointer to the HW structure ++ * @data: pointer to the NVM (EEPROM) ++ * ++ * Read the EEPROM for the current default LED configuration. If the ++ * LED configuration is not valid, set to a valid LED configuration. ++ **/ ++s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data) ++{ ++ s32 ret_val; ++ ++ ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); ++ if (ret_val) { ++ hw_dbg("NVM Read Error\n"); ++ goto out; ++ } ++ ++ if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { ++ switch (hw->phy.media_type) { ++ case e1000_media_type_internal_serdes: ++ *data = ID_LED_DEFAULT_I210_SERDES; ++ break; ++ case e1000_media_type_copper: ++ default: ++ *data = ID_LED_DEFAULT_I210; ++ break; ++ } ++ } ++out: ++ return ret_val; ++} ++ ++/** ++ * __igb_access_xmdio_reg - Read/write XMDIO register ++ * @hw: pointer to the HW structure ++ * @address: XMDIO address to program ++ * @dev_addr: device address to program ++ * @data: pointer to value to read/write from/to the XMDIO address ++ * @read: boolean flag to indicate read or write ++ **/ ++static s32 __igb_access_xmdio_reg(struct e1000_hw *hw, u16 address, ++ u8 dev_addr, u16 *data, bool read) ++{ ++ s32 ret_val = E1000_SUCCESS; ++ ++ ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr); ++ if (ret_val) ++ return ret_val; ++ ++ ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address); ++ if (ret_val) ++ return ret_val; ++ ++ ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA | ++ dev_addr); ++ if (ret_val) ++ return ret_val; ++ ++ if (read) ++ ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data); ++ else ++ ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data); ++ if (ret_val) ++ return ret_val; ++ ++ /* Recalibrate the device back to 0 */ ++ ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0); ++ if (ret_val) ++ return ret_val; ++ ++ return ret_val; ++} ++ ++/** ++ * igb_read_xmdio_reg - Read XMDIO register ++ * @hw: pointer to the HW structure ++ * @addr: XMDIO address to program ++ * @dev_addr: device address to program ++ * @data: value to be read from the EMI address ++ **/ ++s32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data) ++{ ++ return __igb_access_xmdio_reg(hw, addr, dev_addr, data, true); ++} ++ ++/** ++ * igb_write_xmdio_reg - Write XMDIO register ++ * @hw: pointer to the HW structure ++ * @addr: XMDIO address to program ++ * @dev_addr: device address to program ++ * @data: value to be written to the XMDIO address ++ **/ ++s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data) ++{ ++ return __igb_access_xmdio_reg(hw, addr, dev_addr, &data, false); ++} ++ ++/** ++ * igb_init_nvm_params_i210 - Init NVM func ptrs. ++ * @hw: pointer to the HW structure ++ **/ ++s32 igb_init_nvm_params_i210(struct e1000_hw *hw) ++{ ++ s32 ret_val = 0; ++ struct e1000_nvm_info *nvm = &hw->nvm; ++ ++ nvm->ops.acquire = igb_acquire_nvm_i210; ++ nvm->ops.release = igb_release_nvm_i210; ++ nvm->ops.valid_led_default = igb_valid_led_default_i210; ++ ++ /* NVM Function Pointers */ ++ if (igb_get_flash_presence_i210(hw)) { ++ hw->nvm.type = e1000_nvm_flash_hw; ++ nvm->ops.read = igb_read_nvm_srrd_i210; ++ nvm->ops.write = igb_write_nvm_srwr_i210; ++ nvm->ops.validate = igb_validate_nvm_checksum_i210; ++ nvm->ops.update = igb_update_nvm_checksum_i210; ++ } else { ++ hw->nvm.type = e1000_nvm_invm; ++ nvm->ops.read = igb_read_invm_i210; ++ nvm->ops.write = NULL; ++ nvm->ops.validate = NULL; ++ nvm->ops.update = NULL; ++ } ++ return ret_val; ++} +diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.h b/drivers/net/ethernet/intel/igb/e1000_i210.h +new file mode 100644 +index 0000000..2d91371 +--- /dev/null ++++ b/drivers/net/ethernet/intel/igb/e1000_i210.h +@@ -0,0 +1,94 @@ ++/******************************************************************************* ++ ++ Intel(R) Gigabit Ethernet Linux driver ++ Copyright(c) 2007-2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#ifndef _E1000_I210_H_ ++#define _E1000_I210_H_ ++ ++s32 igb_update_flash_i210(struct e1000_hw *hw); ++s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw); ++s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw); ++s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, ++ u16 *data); ++s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, ++ u16 *data); ++s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask); ++void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask); ++s32 igb_acquire_nvm_i210(struct e1000_hw *hw); ++void igb_release_nvm_i210(struct e1000_hw *hw); ++s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data); ++s32 igb_read_invm_version(struct e1000_hw *hw, ++ struct e1000_fw_version *invm_ver); ++s32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data); ++s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data); ++s32 igb_init_nvm_params_i210(struct e1000_hw *hw); ++bool igb_get_flash_presence_i210(struct e1000_hw *hw); ++ ++#define E1000_STM_OPCODE 0xDB00 ++#define E1000_EEPROM_FLASH_SIZE_WORD 0x11 ++ ++#define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \ ++ (u8)((invm_dword) & 0x7) ++#define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \ ++ (u8)(((invm_dword) & 0x0000FE00) >> 9) ++#define INVM_DWORD_TO_WORD_DATA(invm_dword) \ ++ (u16)(((invm_dword) & 0xFFFF0000) >> 16) ++ ++enum E1000_INVM_STRUCTURE_TYPE { ++ E1000_INVM_UNINITIALIZED_STRUCTURE = 0x00, ++ E1000_INVM_WORD_AUTOLOAD_STRUCTURE = 0x01, ++ E1000_INVM_CSR_AUTOLOAD_STRUCTURE = 0x02, ++ E1000_INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE = 0x03, ++ E1000_INVM_RSA_KEY_SHA256_STRUCTURE = 0x04, ++ E1000_INVM_INVALIDATED_STRUCTURE = 0x0F, ++}; ++ ++#define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8 ++#define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1 ++#define E1000_INVM_ULT_BYTES_SIZE 8 ++#define E1000_INVM_RECORD_SIZE_IN_BYTES 4 ++#define E1000_INVM_VER_FIELD_ONE 0x1FF8 ++#define E1000_INVM_VER_FIELD_TWO 0x7FE000 ++#define E1000_INVM_IMGTYPE_FIELD 0x1F800000 ++ ++#define E1000_INVM_MAJOR_MASK 0x3F0 ++#define E1000_INVM_MINOR_MASK 0xF ++#define E1000_INVM_MAJOR_SHIFT 4 ++ ++#define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \ ++ (ID_LED_DEF1_DEF2 << 4) | \ ++ (ID_LED_OFF1_OFF2)) ++#define ID_LED_DEFAULT_I210_SERDES ((ID_LED_DEF1_DEF2 << 8) | \ ++ (ID_LED_DEF1_DEF2 << 4) | \ ++ (ID_LED_OFF1_ON2)) ++ ++/* NVM offset defaults for i211 device */ ++#define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243 ++#define NVM_INIT_CTRL_4_DEFAULT_I211 0x00C1 ++#define NVM_LED_1_CFG_DEFAULT_I211 0x0184 ++#define NVM_LED_0_2_CFG_DEFAULT_I211 0x200C ++ ++#endif +diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c +index 73aac08..298f0ed 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_mac.c ++++ b/drivers/net/ethernet/intel/igb/e1000_mac.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -151,7 +151,7 @@ void igb_clear_vfta_i350(struct e1000_hw *hw) + * Writes value at the given offset in the register array which stores + * the VLAN filter table. + **/ +-void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value) ++static void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value) + { + int i; + +@@ -214,7 +214,7 @@ s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) + else + vfta &= ~mask; + } +- if (hw->mac.type == e1000_i350) ++ if ((hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i354)) + igb_write_vfta_i350(hw, index, vfta); + else + igb_write_vfta(hw, index, vfta); +@@ -230,8 +230,8 @@ s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) + * Checks the nvm for an alternate MAC address. An alternate MAC address + * can be setup by pre-boot software and must be treated like a permanent + * address and must override the actual permanent MAC address. If an +- * alternate MAC address is fopund it is saved in the hw struct and +- * prgrammed into RAR0 and the cuntion returns success, otherwise the ++ * alternate MAC address is found it is saved in the hw struct and ++ * programmed into RAR0 and the function returns success, otherwise the + * function returns an error. + **/ + s32 igb_check_alt_mac_addr(struct e1000_hw *hw) +@@ -241,8 +241,7 @@ s32 igb_check_alt_mac_addr(struct e1000_hw *hw) + u16 offset, nvm_alt_mac_addr_offset, nvm_data; + u8 alt_mac_addr[ETH_ALEN]; + +- /* +- * Alternate MAC address is handled by the option ROM for 82580 ++ /* Alternate MAC address is handled by the option ROM for 82580 + * and newer. SW support not required. + */ + if (hw->mac.type >= e1000_82580) +@@ -285,8 +284,7 @@ s32 igb_check_alt_mac_addr(struct e1000_hw *hw) + goto out; + } + +- /* +- * We have a valid alternate MAC address, and we want to treat it the ++ /* We have a valid alternate MAC address, and we want to treat it the + * same as the normal permanent MAC address stored by the HW into the + * RAR. Do this by mapping this address into RAR0. + */ +@@ -309,8 +307,7 @@ void igb_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) + { + u32 rar_low, rar_high; + +- /* +- * HW expects these in little endian so we reverse the byte order ++ /* HW expects these in little endian so we reverse the byte order + * from network order (big endian) to little endian + */ + rar_low = ((u32) addr[0] | +@@ -323,8 +320,7 @@ void igb_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) + if (rar_low || rar_high) + rar_high |= E1000_RAH_AV; + +- /* +- * Some bridges will combine consecutive 32-bit writes into ++ /* Some bridges will combine consecutive 32-bit writes into + * a single burst write, which will malfunction on some parts. + * The flushes avoid this. + */ +@@ -348,8 +344,7 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value) + { + u32 hash_bit, hash_reg, mta; + +- /* +- * The MTA is a register array of 32-bit registers. It is ++ /* The MTA is a register array of 32-bit registers. It is + * treated like an array of (32*mta_reg_count) bits. We want to + * set bit BitArray[hash_value]. So we figure out what register + * the bit is in, read it, OR in the new bit, then write +@@ -386,15 +381,13 @@ static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) + /* Register count multiplied by bits per register */ + hash_mask = (hw->mac.mta_reg_count * 32) - 1; + +- /* +- * For a mc_filter_type of 0, bit_shift is the number of left-shifts ++ /* For a mc_filter_type of 0, bit_shift is the number of left-shifts + * where 0xFF would still fall within the hash mask. + */ + while (hash_mask >> bit_shift != 0xFF) + bit_shift++; + +- /* +- * The portion of the address that is used for the hash table ++ /* The portion of the address that is used for the hash table + * is determined by the mc_filter_type setting. + * The algorithm is such that there is a total of 8 bits of shifting. + * The bit_shift for a mc_filter_type of 0 represents the number of +@@ -536,8 +529,7 @@ s32 igb_check_for_copper_link(struct e1000_hw *hw) + s32 ret_val; + bool link; + +- /* +- * We only want to go out to the PHY registers to see if Auto-Neg ++ /* We only want to go out to the PHY registers to see if Auto-Neg + * has completed and/or if our link status has changed. The + * get_link_status flag is set upon receiving a Link Status + * Change or Rx Sequence Error interrupt. +@@ -547,8 +539,7 @@ s32 igb_check_for_copper_link(struct e1000_hw *hw) + goto out; + } + +- /* +- * First we want to see if the MII Status Register reports ++ /* First we want to see if the MII Status Register reports + * link. If so, then we want to get the current speed/duplex + * of the PHY. + */ +@@ -561,14 +552,12 @@ s32 igb_check_for_copper_link(struct e1000_hw *hw) + + mac->get_link_status = false; + +- /* +- * Check if there was DownShift, must be checked ++ /* Check if there was DownShift, must be checked + * immediately after link-up + */ + igb_check_downshift(hw); + +- /* +- * If we are forcing speed/duplex, then we simply return since ++ /* If we are forcing speed/duplex, then we simply return since + * we have already determined whether we have link or not. + */ + if (!mac->autoneg) { +@@ -576,15 +565,13 @@ s32 igb_check_for_copper_link(struct e1000_hw *hw) + goto out; + } + +- /* +- * Auto-Neg is enabled. Auto Speed Detection takes care ++ /* Auto-Neg is enabled. Auto Speed Detection takes care + * of MAC speed/duplex configuration. So we only need to + * configure Collision Distance in the MAC. + */ + igb_config_collision_dist(hw); + +- /* +- * Configure Flow Control now that Auto-Neg has completed. ++ /* Configure Flow Control now that Auto-Neg has completed. + * First, we need to restore the desired flow control + * settings because we may have had to re-autoneg with a + * different link partner. +@@ -611,15 +598,13 @@ s32 igb_setup_link(struct e1000_hw *hw) + { + s32 ret_val = 0; + +- /* +- * In the case of the phy reset being blocked, we already have a link. ++ /* In the case of the phy reset being blocked, we already have a link. + * We do not need to set it up again. + */ + if (igb_check_reset_block(hw)) + goto out; + +- /* +- * If requested flow control is set to default, set flow control ++ /* If requested flow control is set to default, set flow control + * based on the EEPROM flow control settings. + */ + if (hw->fc.requested_mode == e1000_fc_default) { +@@ -628,8 +613,7 @@ s32 igb_setup_link(struct e1000_hw *hw) + goto out; + } + +- /* +- * We want to save off the original Flow Control configuration just ++ /* We want to save off the original Flow Control configuration just + * in case we get disconnected and then reconnected into a different + * hub or switch with different Flow Control capabilities. + */ +@@ -642,8 +626,7 @@ s32 igb_setup_link(struct e1000_hw *hw) + if (ret_val) + goto out; + +- /* +- * Initialize the flow control address, type, and PAUSE timer ++ /* Initialize the flow control address, type, and PAUSE timer + * registers to their default values. This is done even if flow + * control is disabled, because it does not hurt anything to + * initialize these registers. +@@ -658,6 +641,7 @@ s32 igb_setup_link(struct e1000_hw *hw) + ret_val = igb_set_fc_watermarks(hw); + + out: ++ + return ret_val; + } + +@@ -695,16 +679,14 @@ static s32 igb_set_fc_watermarks(struct e1000_hw *hw) + s32 ret_val = 0; + u32 fcrtl = 0, fcrth = 0; + +- /* +- * Set the flow control receive threshold registers. Normally, ++ /* Set the flow control receive threshold registers. Normally, + * these registers will be set to a default threshold that may be + * adjusted later by the driver's runtime code. However, if the + * ability to transmit pause frames is not enabled, then these + * registers will be set to 0. + */ + if (hw->fc.current_mode & e1000_fc_tx_pause) { +- /* +- * We need to set up the Receive Threshold high and low water ++ /* We need to set up the Receive Threshold high and low water + * marks as well as (optionally) enabling the transmission of + * XON frames. + */ +@@ -730,10 +712,10 @@ static s32 igb_set_fc_watermarks(struct e1000_hw *hw) + static s32 igb_set_default_fc(struct e1000_hw *hw) + { + s32 ret_val = 0; ++ u16 lan_offset; + u16 nvm_data; + +- /* +- * Read and store word 0x0F of the EEPROM. This word contains bits ++ /* Read and store word 0x0F of the EEPROM. This word contains bits + * that determine the hardware's default PAUSE (flow control) mode, + * a bit that determines whether the HW defaults to enabling or + * disabling auto-negotiation, and the direction of the +@@ -741,7 +723,14 @@ static s32 igb_set_default_fc(struct e1000_hw *hw) + * control setting, then the variable hw->fc will + * be initialized based on a value in the EEPROM. + */ +- ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); ++ if (hw->mac.type == e1000_i350) { ++ lan_offset = NVM_82580_LAN_FUNC_OFFSET(hw->bus.func); ++ ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG ++ + lan_offset, 1, &nvm_data); ++ } else { ++ ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, ++ 1, &nvm_data); ++ } + + if (ret_val) { + hw_dbg("NVM Read Error\n"); +@@ -777,8 +766,7 @@ s32 igb_force_mac_fc(struct e1000_hw *hw) + + ctrl = rd32(E1000_CTRL); + +- /* +- * Because we didn't get link via the internal auto-negotiation ++ /* Because we didn't get link via the internal auto-negotiation + * mechanism (we either forced link or we got link via PHY + * auto-neg), we have to manually enable/disable transmit an + * receive flow control. +@@ -838,11 +826,11 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) + { + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val = 0; ++ u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg; + u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; + u16 speed, duplex; + +- /* +- * Check for the case where we have fiber media and auto-neg failed ++ /* Check for the case where we have fiber media and auto-neg failed + * so we had to force link. In this case, we need to force the + * configuration of the MAC to match the "fc" parameter. + */ +@@ -859,15 +847,13 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) + goto out; + } + +- /* +- * Check for the case where we have copper media and auto-neg is ++ /* Check for the case where we have copper media and auto-neg is + * enabled. In this case, we need to check and see if Auto-Neg + * has completed, and if so, how the PHY and link partner has + * flow control configured. + */ + if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { +- /* +- * Read the MII Status Register and check to see if AutoNeg ++ /* Read the MII Status Register and check to see if AutoNeg + * has completed. We read this twice because this reg has + * some "sticky" (latched) bits. + */ +@@ -886,8 +872,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) + goto out; + } + +- /* +- * The AutoNeg process has completed, so we now need to ++ /* The AutoNeg process has completed, so we now need to + * read both the Auto Negotiation Advertisement + * Register (Address 4) and the Auto_Negotiation Base + * Page Ability Register (Address 5) to determine how +@@ -902,8 +887,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) + if (ret_val) + goto out; + +- /* +- * Two bits in the Auto Negotiation Advertisement Register ++ /* Two bits in the Auto Negotiation Advertisement Register + * (Address 4) and two bits in the Auto Negotiation Base + * Page Ability Register (Address 5) determine flow control + * for both the PHY and the link partner. The following +@@ -938,8 +922,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) + */ + if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { +- /* +- * Now we need to check if the user selected RX ONLY ++ /* Now we need to check if the user selected RX ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise RX + * ONLY. Hence, we must now check to see if we need to +@@ -954,8 +937,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) + "RX PAUSE frames only.\r\n"); + } + } +- /* +- * For receiving PAUSE frames ONLY. ++ /* For receiving PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result +@@ -969,8 +951,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) + hw->fc.current_mode = e1000_fc_tx_pause; + hw_dbg("Flow Control = TX PAUSE frames only.\r\n"); + } +- /* +- * For transmitting PAUSE frames ONLY. ++ /* For transmitting PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result +@@ -984,8 +965,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) + hw->fc.current_mode = e1000_fc_rx_pause; + hw_dbg("Flow Control = RX PAUSE frames only.\r\n"); + } +- /* +- * Per the IEEE spec, at this point flow control should be ++ /* Per the IEEE spec, at this point flow control should be + * disabled. However, we want to consider that we could + * be connected to a legacy switch that doesn't advertise + * desired flow control, but can be forced on the link +@@ -1005,9 +985,9 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) + * be asked to delay transmission of packets than asking + * our link partner to pause transmission of frames. + */ +- else if ((hw->fc.requested_mode == e1000_fc_none || +- hw->fc.requested_mode == e1000_fc_tx_pause) || +- hw->fc.strict_ieee) { ++ else if ((hw->fc.requested_mode == e1000_fc_none) || ++ (hw->fc.requested_mode == e1000_fc_tx_pause) || ++ (hw->fc.strict_ieee)) { + hw->fc.current_mode = e1000_fc_none; + hw_dbg("Flow Control = NONE.\r\n"); + } else { +@@ -1015,8 +995,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) + hw_dbg("Flow Control = RX PAUSE frames only.\r\n"); + } + +- /* +- * Now we need to do one last check... If we auto- ++ /* Now we need to do one last check... If we auto- + * negotiated to HALF DUPLEX, flow control should not be + * enabled per IEEE 802.3 spec. + */ +@@ -1029,8 +1008,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) + if (duplex == HALF_DUPLEX) + hw->fc.current_mode = e1000_fc_none; + +- /* +- * Now we call a subroutine to actually force the MAC ++ /* Now we call a subroutine to actually force the MAC + * controller to use the correct flow control settings. + */ + ret_val = igb_force_mac_fc(hw); +@@ -1039,6 +1017,129 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) + goto out; + } + } ++ /* Check for the case where we have SerDes media and auto-neg is ++ * enabled. In this case, we need to check and see if Auto-Neg ++ * has completed, and if so, how the PHY and link partner has ++ * flow control configured. ++ */ ++ if ((hw->phy.media_type == e1000_media_type_internal_serdes) ++ && mac->autoneg) { ++ /* Read the PCS_LSTS and check to see if AutoNeg ++ * has completed. ++ */ ++ pcs_status_reg = rd32(E1000_PCS_LSTAT); ++ ++ if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) { ++ hw_dbg("PCS Auto Neg has not completed.\n"); ++ return ret_val; ++ } ++ ++ /* The AutoNeg process has completed, so we now need to ++ * read both the Auto Negotiation Advertisement ++ * Register (PCS_ANADV) and the Auto_Negotiation Base ++ * Page Ability Register (PCS_LPAB) to determine how ++ * flow control was negotiated. ++ */ ++ pcs_adv_reg = rd32(E1000_PCS_ANADV); ++ pcs_lp_ability_reg = rd32(E1000_PCS_LPAB); ++ ++ /* Two bits in the Auto Negotiation Advertisement Register ++ * (PCS_ANADV) and two bits in the Auto Negotiation Base ++ * Page Ability Register (PCS_LPAB) determine flow control ++ * for both the PHY and the link partner. The following ++ * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, ++ * 1999, describes these PAUSE resolution bits and how flow ++ * control is determined based upon these settings. ++ * NOTE: DC = Don't Care ++ * ++ * LOCAL DEVICE | LINK PARTNER ++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution ++ *-------|---------|-------|---------|-------------------- ++ * 0 | 0 | DC | DC | e1000_fc_none ++ * 0 | 1 | 0 | DC | e1000_fc_none ++ * 0 | 1 | 1 | 0 | e1000_fc_none ++ * 0 | 1 | 1 | 1 | e1000_fc_tx_pause ++ * 1 | 0 | 0 | DC | e1000_fc_none ++ * 1 | DC | 1 | DC | e1000_fc_full ++ * 1 | 1 | 0 | 0 | e1000_fc_none ++ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause ++ * ++ * Are both PAUSE bits set to 1? If so, this implies ++ * Symmetric Flow Control is enabled at both ends. The ++ * ASM_DIR bits are irrelevant per the spec. ++ * ++ * For Symmetric Flow Control: ++ * ++ * LOCAL DEVICE | LINK PARTNER ++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result ++ *-------|---------|-------|---------|-------------------- ++ * 1 | DC | 1 | DC | e1000_fc_full ++ * ++ */ ++ if ((pcs_adv_reg & E1000_TXCW_PAUSE) && ++ (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) { ++ /* Now we need to check if the user selected Rx ONLY ++ * of pause frames. In this case, we had to advertise ++ * FULL flow control because we could not advertise Rx ++ * ONLY. Hence, we must now check to see if we need to ++ * turn OFF the TRANSMISSION of PAUSE frames. ++ */ ++ if (hw->fc.requested_mode == e1000_fc_full) { ++ hw->fc.current_mode = e1000_fc_full; ++ hw_dbg("Flow Control = FULL.\n"); ++ } else { ++ hw->fc.current_mode = e1000_fc_rx_pause; ++ hw_dbg("Flow Control = Rx PAUSE frames only.\n"); ++ } ++ } ++ /* For receiving PAUSE frames ONLY. ++ * ++ * LOCAL DEVICE | LINK PARTNER ++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result ++ *-------|---------|-------|---------|-------------------- ++ * 0 | 1 | 1 | 1 | e1000_fc_tx_pause ++ */ ++ else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) && ++ (pcs_adv_reg & E1000_TXCW_ASM_DIR) && ++ (pcs_lp_ability_reg & E1000_TXCW_PAUSE) && ++ (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { ++ hw->fc.current_mode = e1000_fc_tx_pause; ++ hw_dbg("Flow Control = Tx PAUSE frames only.\n"); ++ } ++ /* For transmitting PAUSE frames ONLY. ++ * ++ * LOCAL DEVICE | LINK PARTNER ++ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result ++ *-------|---------|-------|---------|-------------------- ++ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause ++ */ ++ else if ((pcs_adv_reg & E1000_TXCW_PAUSE) && ++ (pcs_adv_reg & E1000_TXCW_ASM_DIR) && ++ !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) && ++ (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { ++ hw->fc.current_mode = e1000_fc_rx_pause; ++ hw_dbg("Flow Control = Rx PAUSE frames only.\n"); ++ } else { ++ /* Per the IEEE spec, at this point flow control ++ * should be disabled. ++ */ ++ hw->fc.current_mode = e1000_fc_none; ++ hw_dbg("Flow Control = NONE.\n"); ++ } ++ ++ /* Now we call a subroutine to actually force the MAC ++ * controller to use the correct flow control settings. ++ */ ++ pcs_ctrl_reg = rd32(E1000_PCS_LCTL); ++ pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL; ++ wr32(E1000_PCS_LCTL, pcs_ctrl_reg); ++ ++ ret_val = igb_force_mac_fc(hw); ++ if (ret_val) { ++ hw_dbg("Error forcing flow control settings\n"); ++ return ret_val; ++ } ++ } + + out: + return ret_val; +@@ -1228,7 +1329,13 @@ s32 igb_id_led_init(struct e1000_hw *hw) + u16 data, i, temp; + const u16 led_mask = 0x0F; + +- ret_val = igb_valid_led_default(hw, &data); ++ /* i210 and i211 devices have different LED mechanism */ ++ if ((hw->mac.type == e1000_i210) || ++ (hw->mac.type == e1000_i211)) ++ ret_val = igb_valid_led_default_i210(hw, &data); ++ else ++ ret_val = igb_valid_led_default(hw, &data); ++ + if (ret_val) + goto out; + +@@ -1302,16 +1409,34 @@ s32 igb_blink_led(struct e1000_hw *hw) + u32 ledctl_blink = 0; + u32 i; + +- /* +- * set the blink bit for each LED that's "on" (0x0E) +- * in ledctl_mode2 +- */ +- ledctl_blink = hw->mac.ledctl_mode2; +- for (i = 0; i < 4; i++) +- if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == +- E1000_LEDCTL_MODE_LED_ON) +- ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << +- (i * 8)); ++ if (hw->phy.media_type == e1000_media_type_fiber) { ++ /* always blink LED0 for PCI-E fiber */ ++ ledctl_blink = E1000_LEDCTL_LED0_BLINK | ++ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); ++ } else { ++ /* Set the blink bit for each LED that's "on" (0x0E) ++ * (or "off" if inverted) in ledctl_mode2. The blink ++ * logic in hardware only works when mode is set to "on" ++ * so it must be changed accordingly when the mode is ++ * "off" and inverted. ++ */ ++ ledctl_blink = hw->mac.ledctl_mode2; ++ for (i = 0; i < 32; i += 8) { ++ u32 mode = (hw->mac.ledctl_mode2 >> i) & ++ E1000_LEDCTL_LED0_MODE_MASK; ++ u32 led_default = hw->mac.ledctl_default >> i; ++ ++ if ((!(led_default & E1000_LEDCTL_LED0_IVRT) && ++ (mode == E1000_LEDCTL_MODE_LED_ON)) || ++ ((led_default & E1000_LEDCTL_LED0_IVRT) && ++ (mode == E1000_LEDCTL_MODE_LED_OFF))) { ++ ledctl_blink &= ++ ~(E1000_LEDCTL_LED0_MODE_MASK << i); ++ ledctl_blink |= (E1000_LEDCTL_LED0_BLINK | ++ E1000_LEDCTL_MODE_LED_ON) << i; ++ } ++ } ++ } + + wr32(E1000_LEDCTL, ledctl_blink); + +@@ -1342,7 +1467,7 @@ s32 igb_led_off(struct e1000_hw *hw) + * @hw: pointer to the HW structure + * + * Returns 0 (0) if successful, else returns -10 +- * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not casued ++ * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused + * the master requests to be disabled. + * + * Disables PCI-Express master access and verifies there are no pending +@@ -1390,6 +1515,10 @@ s32 igb_validate_mdi_setting(struct e1000_hw *hw) + { + s32 ret_val = 0; + ++ /* All MDI settings are supported on 82580 and newer. */ ++ if (hw->mac.type >= e1000_82580) ++ goto out; ++ + if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) { + hw_dbg("Invalid MDI setting detected\n"); + hw->phy.mdix = 1; +diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.h b/drivers/net/ethernet/intel/igb/e1000_mac.h +index e45996b..e4cbe8e 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_mac.h ++++ b/drivers/net/ethernet/intel/igb/e1000_mac.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -33,9 +33,9 @@ + #include "e1000_phy.h" + #include "e1000_nvm.h" + #include "e1000_defines.h" ++#include "e1000_i210.h" + +-/* +- * Functions that should not be called directly from drivers but can be used ++/* Functions that should not be called directly from drivers but can be used + * by other files in this 'shared code' + */ + s32 igb_blink_led(struct e1000_hw *hw); +@@ -48,15 +48,15 @@ s32 igb_get_auto_rd_done(struct e1000_hw *hw); + s32 igb_get_bus_info_pcie(struct e1000_hw *hw); + s32 igb_get_hw_semaphore(struct e1000_hw *hw); + s32 igb_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, +- u16 *duplex); ++ u16 *duplex); + s32 igb_id_led_init(struct e1000_hw *hw); + s32 igb_led_off(struct e1000_hw *hw); + void igb_update_mc_addr_list(struct e1000_hw *hw, +- u8 *mc_addr_list, u32 mc_addr_count); ++ u8 *mc_addr_list, u32 mc_addr_count); + s32 igb_setup_link(struct e1000_hw *hw); + s32 igb_validate_mdi_setting(struct e1000_hw *hw); + s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, +- u32 offset, u8 data); ++ u32 offset, u8 data); + + void igb_clear_hw_cntrs_base(struct e1000_hw *hw); + void igb_clear_vfta(struct e1000_hw *hw); +@@ -79,13 +79,13 @@ enum e1000_mng_mode { + e1000_mng_mode_host_if_only + }; + +-#define E1000_FACTPS_MNGCG 0x20000000 ++#define E1000_FACTPS_MNGCG 0x20000000 + +-#define E1000_FWSM_MODE_MASK 0xE +-#define E1000_FWSM_MODE_SHIFT 1 ++#define E1000_FWSM_MODE_MASK 0xE ++#define E1000_FWSM_MODE_SHIFT 1 + +-#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 ++#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 + +-extern void e1000_init_function_pointers_82575(struct e1000_hw *hw); ++void e1000_init_function_pointers_82575(struct e1000_hw *hw); + + #endif +diff --git a/drivers/net/ethernet/intel/igb/e1000_mbx.c b/drivers/net/ethernet/intel/igb/e1000_mbx.c +index 469d95e..dac1447 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_mbx.c ++++ b/drivers/net/ethernet/intel/igb/e1000_mbx.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -196,7 +196,8 @@ out: + * returns SUCCESS if it successfully received a message notification and + * copied it into the receive buffer. + **/ +-static s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) ++static s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, ++ u16 mbx_id) + { + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; +@@ -222,7 +223,8 @@ out: + * returns SUCCESS if it successfully copied message into the buffer and + * received an ack to that message within delay * timeout period + **/ +-static s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) ++static s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, ++ u16 mbx_id) + { + struct e1000_mbx_info *mbx = &hw->mbx; + s32 ret_val = -E1000_ERR_MBX; +@@ -325,7 +327,6 @@ static s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) + s32 ret_val = -E1000_ERR_MBX; + u32 p2v_mailbox; + +- + /* Take ownership of the buffer */ + wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); + +@@ -347,7 +348,7 @@ static s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) + * returns SUCCESS if it successfully copied message into the buffer + **/ + static s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, +- u16 vf_number) ++ u16 vf_number) + { + s32 ret_val; + u16 i; +@@ -388,7 +389,7 @@ out_no_write: + * a message due to a VF request so no polling for message is needed. + **/ + static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, +- u16 vf_number) ++ u16 vf_number) + { + s32 ret_val; + u16 i; +diff --git a/drivers/net/ethernet/intel/igb/e1000_mbx.h b/drivers/net/ethernet/intel/igb/e1000_mbx.h +index eddb0f8..de9bba4 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_mbx.h ++++ b/drivers/net/ethernet/intel/igb/e1000_mbx.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -30,42 +30,42 @@ + + #include "e1000_hw.h" + +-#define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */ +-#define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ +-#define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ +-#define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ +-#define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ ++#define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */ ++#define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ ++#define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ ++#define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ ++#define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ + +-#define E1000_MBVFICR_VFREQ_MASK 0x000000FF /* bits for VF messages */ +-#define E1000_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */ +-#define E1000_MBVFICR_VFACK_MASK 0x00FF0000 /* bits for VF acks */ +-#define E1000_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */ ++#define E1000_MBVFICR_VFREQ_MASK 0x000000FF /* bits for VF messages */ ++#define E1000_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */ ++#define E1000_MBVFICR_VFACK_MASK 0x00FF0000 /* bits for VF acks */ ++#define E1000_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */ + +-#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */ ++#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */ + + /* If it's a E1000_VF_* msg then it originates in the VF and is sent to the + * PF. The reverse is true if it is E1000_PF_*. + * Message ACK's are the value or'd with 0xF0000000 + */ +-#define E1000_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with +- * this are the ACK */ +-#define E1000_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with +- * this are the NACK */ +-#define E1000_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still +- clear to send requests */ +-#define E1000_VT_MSGINFO_SHIFT 16 ++/* Messages below or'd with this are the ACK */ ++#define E1000_VT_MSGTYPE_ACK 0x80000000 ++/* Messages below or'd with this are the NACK */ ++#define E1000_VT_MSGTYPE_NACK 0x40000000 ++/* Indicates that VF is still clear to send requests */ ++#define E1000_VT_MSGTYPE_CTS 0x20000000 ++#define E1000_VT_MSGINFO_SHIFT 16 + /* bits 23:16 are used for exra info for certain messages */ +-#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT) ++#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT) + +-#define E1000_VF_RESET 0x01 /* VF requests reset */ +-#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests to set MAC addr */ +-#define E1000_VF_SET_MULTICAST 0x03 /* VF requests to set MC addr */ +-#define E1000_VF_SET_VLAN 0x04 /* VF requests to set VLAN */ +-#define E1000_VF_SET_LPE 0x05 /* VF requests to set VMOLR.LPE */ +-#define E1000_VF_SET_PROMISC 0x06 /*VF requests to clear VMOLR.ROPE/MPME*/ +-#define E1000_VF_SET_PROMISC_MULTICAST (0x02 << E1000_VT_MSGINFO_SHIFT) ++#define E1000_VF_RESET 0x01 /* VF requests reset */ ++#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests to set MAC addr */ ++#define E1000_VF_SET_MULTICAST 0x03 /* VF requests to set MC addr */ ++#define E1000_VF_SET_VLAN 0x04 /* VF requests to set VLAN */ ++#define E1000_VF_SET_LPE 0x05 /* VF requests to set VMOLR.LPE */ ++#define E1000_VF_SET_PROMISC 0x06 /*VF requests to clear VMOLR.ROPE/MPME*/ ++#define E1000_VF_SET_PROMISC_MULTICAST (0x02 << E1000_VT_MSGINFO_SHIFT) + +-#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */ ++#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */ + + s32 igb_read_mbx(struct e1000_hw *, u32 *, u16, u16); + s32 igb_write_mbx(struct e1000_hw *, u32 *, u16, u16); +diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.c b/drivers/net/ethernet/intel/igb/e1000_nvm.c +index 4040712..a7db7f3 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_nvm.c ++++ b/drivers/net/ethernet/intel/igb/e1000_nvm.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -289,15 +289,14 @@ static s32 igb_ready_nvm_eeprom(struct e1000_hw *hw) + udelay(1); + timeout = NVM_MAX_RETRY_SPI; + +- /* +- * Read "Status Register" repeatedly until the LSB is cleared. ++ /* Read "Status Register" repeatedly until the LSB is cleared. + * The EEPROM will signal that the command has been completed + * by clearing bit 0 of the internal status register. If it's + * not cleared within 'timeout', then error out. + */ + while (timeout) { + igb_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, +- hw->nvm.opcode_bits); ++ hw->nvm.opcode_bits); + spi_stat_reg = (u8)igb_shift_in_eec_bits(hw, 8); + if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) + break; +@@ -335,8 +334,7 @@ s32 igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) + u16 word_in; + u8 read_opcode = NVM_READ_OPCODE_SPI; + +- /* +- * A check for invalid values: offset too large, too many words, ++ /* A check for invalid values: offset too large, too many words, + * and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || +@@ -363,8 +361,7 @@ s32 igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) + igb_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); + igb_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits); + +- /* +- * Read the data. SPI NVMs increment the address with each byte ++ /* Read the data. SPI NVMs increment the address with each byte + * read and will roll over if reading beyond the end. This allows + * us to read the whole NVM from any offset + */ +@@ -395,8 +392,7 @@ s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) + u32 i, eerd = 0; + s32 ret_val = 0; + +- /* +- * A check for invalid values: offset too large, too many words, ++ /* A check for invalid values: offset too large, too many words, + * and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || +@@ -408,7 +404,7 @@ s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) + + for (i = 0; i < words; i++) { + eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + +- E1000_NVM_RW_REG_START; ++ E1000_NVM_RW_REG_START; + + wr32(E1000_EERD, eerd); + ret_val = igb_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); +@@ -438,32 +434,30 @@ out: + s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) + { + struct e1000_nvm_info *nvm = &hw->nvm; +- s32 ret_val; ++ s32 ret_val = -E1000_ERR_NVM; + u16 widx = 0; + +- /* +- * A check for invalid values: offset too large, too many words, ++ /* A check for invalid values: offset too large, too many words, + * and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || + (words == 0)) { + hw_dbg("nvm parameter(s) out of bounds\n"); +- ret_val = -E1000_ERR_NVM; +- goto out; ++ return ret_val; + } + +- ret_val = hw->nvm.ops.acquire(hw); +- if (ret_val) +- goto out; +- +- msleep(10); +- + while (widx < words) { + u8 write_opcode = NVM_WRITE_OPCODE_SPI; + +- ret_val = igb_ready_nvm_eeprom(hw); ++ ret_val = nvm->ops.acquire(hw); + if (ret_val) +- goto release; ++ return ret_val; ++ ++ ret_val = igb_ready_nvm_eeprom(hw); ++ if (ret_val) { ++ nvm->ops.release(hw); ++ return ret_val; ++ } + + igb_standby_nvm(hw); + +@@ -473,8 +467,7 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) + + igb_standby_nvm(hw); + +- /* +- * Some SPI eeproms use the 8th address bit embedded in the ++ /* Some SPI eeproms use the 8th address bit embedded in the + * opcode + */ + if ((nvm->address_bits == 8) && (offset >= 128)) +@@ -497,13 +490,10 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) + break; + } + } ++ usleep_range(1000, 2000); ++ nvm->ops.release(hw); + } + +- msleep(10); +-release: +- hw->nvm.ops.release(hw); +- +-out: + return ret_val; + } + +@@ -542,8 +532,7 @@ s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num, u32 part_num_size) + goto out; + } + +- /* +- * if nvm_data is not ptr guard the PBA must be in legacy format which ++ /* if nvm_data is not ptr guard the PBA must be in legacy format which + * means pointer is actually our second data word for the PBA number + * and we can decode it into an ascii string + */ +@@ -711,3 +700,107 @@ out: + return ret_val; + } + ++/** ++ * igb_get_fw_version - Get firmware version information ++ * @hw: pointer to the HW structure ++ * @fw_vers: pointer to output structure ++ * ++ * unsupported MAC types will return all 0 version structure ++ **/ ++void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers) ++{ ++ u16 eeprom_verh, eeprom_verl, etrack_test, fw_version; ++ u8 q, hval, rem, result; ++ u16 comb_verh, comb_verl, comb_offset; ++ ++ memset(fw_vers, 0, sizeof(struct e1000_fw_version)); ++ ++ /* basic eeprom version numbers and bits used vary by part and by tool ++ * used to create the nvm images. Check which data format we have. ++ */ ++ hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test); ++ switch (hw->mac.type) { ++ case e1000_i211: ++ igb_read_invm_version(hw, fw_vers); ++ return; ++ case e1000_82575: ++ case e1000_82576: ++ case e1000_82580: ++ /* Use this format, unless EETRACK ID exists, ++ * then use alternate format ++ */ ++ if ((etrack_test & NVM_MAJOR_MASK) != NVM_ETRACK_VALID) { ++ hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version); ++ fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) ++ >> NVM_MAJOR_SHIFT; ++ fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK) ++ >> NVM_MINOR_SHIFT; ++ fw_vers->eep_build = (fw_version & NVM_IMAGE_ID_MASK); ++ goto etrack_id; ++ } ++ break; ++ case e1000_i210: ++ if (!(igb_get_flash_presence_i210(hw))) { ++ igb_read_invm_version(hw, fw_vers); ++ return; ++ } ++ /* fall through */ ++ case e1000_i350: ++ /* find combo image version */ ++ hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset); ++ if ((comb_offset != 0x0) && ++ (comb_offset != NVM_VER_INVALID)) { ++ ++ hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset ++ + 1), 1, &comb_verh); ++ hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset), ++ 1, &comb_verl); ++ ++ /* get Option Rom version if it exists and is valid */ ++ if ((comb_verh && comb_verl) && ++ ((comb_verh != NVM_VER_INVALID) && ++ (comb_verl != NVM_VER_INVALID))) { ++ ++ fw_vers->or_valid = true; ++ fw_vers->or_major = ++ comb_verl >> NVM_COMB_VER_SHFT; ++ fw_vers->or_build = ++ (comb_verl << NVM_COMB_VER_SHFT) ++ | (comb_verh >> NVM_COMB_VER_SHFT); ++ fw_vers->or_patch = ++ comb_verh & NVM_COMB_VER_MASK; ++ } ++ } ++ break; ++ default: ++ return; ++ } ++ hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version); ++ fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) ++ >> NVM_MAJOR_SHIFT; ++ ++ /* check for old style version format in newer images*/ ++ if ((fw_version & NVM_NEW_DEC_MASK) == 0x0) { ++ eeprom_verl = (fw_version & NVM_COMB_VER_MASK); ++ } else { ++ eeprom_verl = (fw_version & NVM_MINOR_MASK) ++ >> NVM_MINOR_SHIFT; ++ } ++ /* Convert minor value to hex before assigning to output struct ++ * Val to be converted will not be higher than 99, per tool output ++ */ ++ q = eeprom_verl / NVM_HEX_CONV; ++ hval = q * NVM_HEX_TENS; ++ rem = eeprom_verl % NVM_HEX_CONV; ++ result = hval + rem; ++ fw_vers->eep_minor = result; ++ ++etrack_id: ++ if ((etrack_test & NVM_MAJOR_MASK) == NVM_ETRACK_VALID) { ++ hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl); ++ hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh); ++ fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) ++ | eeprom_verl; ++ } ++ return; ++} +diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.h b/drivers/net/ethernet/intel/igb/e1000_nvm.h +index a2a7ca9..433b741 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_nvm.h ++++ b/drivers/net/ethernet/intel/igb/e1000_nvm.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2011 Intel Corporation. ++ Copyright(c) 2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -40,4 +40,21 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); + s32 igb_validate_nvm_checksum(struct e1000_hw *hw); + s32 igb_update_nvm_checksum(struct e1000_hw *hw); + ++struct e1000_fw_version { ++ u32 etrack_id; ++ u16 eep_major; ++ u16 eep_minor; ++ u16 eep_build; ++ ++ u8 invm_major; ++ u8 invm_minor; ++ u8 invm_img_type; ++ ++ bool or_valid; ++ u16 or_major; ++ u16 or_build; ++ u16 or_patch; ++}; ++void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers); ++ + #endif +diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c +index b17d7c2..0df0346 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_phy.c ++++ b/drivers/net/ethernet/intel/igb/e1000_phy.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -33,28 +33,29 @@ + + static s32 igb_phy_setup_autoneg(struct e1000_hw *hw); + static void igb_phy_force_speed_duplex_setup(struct e1000_hw *hw, +- u16 *phy_ctrl); ++ u16 *phy_ctrl); + static s32 igb_wait_autoneg(struct e1000_hw *hw); ++static s32 igb_set_master_slave_mode(struct e1000_hw *hw); + + /* Cable length tables */ +-static const u16 e1000_m88_cable_length_table[] = +- { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; ++static const u16 e1000_m88_cable_length_table[] = { ++ 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; + #define M88E1000_CABLE_LENGTH_TABLE_SIZE \ +- (sizeof(e1000_m88_cable_length_table) / \ +- sizeof(e1000_m88_cable_length_table[0])) +- +-static const u16 e1000_igp_2_cable_length_table[] = +- { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, +- 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, +- 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, +- 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, +- 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, +- 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, +- 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, +- 104, 109, 114, 118, 121, 124}; ++ (sizeof(e1000_m88_cable_length_table) / \ ++ sizeof(e1000_m88_cable_length_table[0])) ++ ++static const u16 e1000_igp_2_cable_length_table[] = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, ++ 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, ++ 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, ++ 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, ++ 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, ++ 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, ++ 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, ++ 104, 109, 114, 118, 121, 124}; + #define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ +- (sizeof(e1000_igp_2_cable_length_table) / \ +- sizeof(e1000_igp_2_cable_length_table[0])) ++ (sizeof(e1000_igp_2_cable_length_table) / \ ++ sizeof(e1000_igp_2_cable_length_table[0])) + + /** + * igb_check_reset_block - Check if PHY reset is blocked +@@ -70,8 +71,7 @@ s32 igb_check_reset_block(struct e1000_hw *hw) + + manc = rd32(E1000_MANC); + +- return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? +- E1000_BLK_PHY_RESET : 0; ++ return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? E1000_BLK_PHY_RESET : 0; + } + + /** +@@ -148,19 +148,24 @@ s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) + goto out; + } + +- /* +- * Set up Op-code, Phy Address, and register offset in the MDI ++ /* Set up Op-code, Phy Address, and register offset in the MDI + * Control register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ ++ if (phy->type == e1000_phy_bcm5461s) { ++ mdic = rd32(E1000_MDICNFG); ++ mdic &= ~E1000_MDICNFG_PHY_MASK; ++ mdic |= (phy->addr << E1000_MDICNFG_PHY_SHIFT); ++ wr32(E1000_MDICNFG, mdic); ++ } ++ + mdic = ((offset << E1000_MDIC_REG_SHIFT) | + (phy->addr << E1000_MDIC_PHY_SHIFT) | + (E1000_MDIC_OP_READ)); + + wr32(E1000_MDIC, mdic); + +- /* +- * Poll the ready bit to see if the MDI read completed ++ /* Poll the ready bit to see if the MDI read completed + * Increasing the time out as testing showed failures with + * the lower time out + */ +@@ -206,11 +211,17 @@ s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) + goto out; + } + +- /* +- * Set up Op-code, Phy Address, and register offset in the MDI ++ /* Set up Op-code, Phy Address, and register offset in the MDI + * Control register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ ++ if (phy->type == e1000_phy_bcm5461s) { ++ mdic = rd32(E1000_MDICNFG); ++ mdic &= ~E1000_MDICNFG_PHY_MASK; ++ mdic |= (phy->addr << E1000_MDICNFG_PHY_SHIFT); ++ wr32(E1000_MDICNFG, mdic); ++ } ++ + mdic = (((u32)data) | + (offset << E1000_MDIC_REG_SHIFT) | + (phy->addr << E1000_MDIC_PHY_SHIFT) | +@@ -218,8 +229,7 @@ s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) + + wr32(E1000_MDIC, mdic); + +- /* +- * Poll the ready bit to see if the MDI read completed ++ /* Poll the ready bit to see if the MDI read completed + * Increasing the time out as testing showed failures with + * the lower time out + */ +@@ -258,15 +268,13 @@ s32 igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data) + struct e1000_phy_info *phy = &hw->phy; + u32 i, i2ccmd = 0; + +- +- /* +- * Set up Op-code, Phy Address, and register address in the I2CCMD ++ /* Set up Op-code, Phy Address, and register address in the I2CCMD + * register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ + i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | +- (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | +- (E1000_I2CCMD_OPCODE_READ)); ++ (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | ++ (E1000_I2CCMD_OPCODE_READ)); + + wr32(E1000_I2CCMD, i2ccmd); + +@@ -316,15 +324,14 @@ s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data) + /* Swap the data bytes for the I2C interface */ + phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00); + +- /* +- * Set up Op-code, Phy Address, and register address in the I2CCMD ++ /* Set up Op-code, Phy Address, and register address in the I2CCMD + * register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ + i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | +- (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | +- E1000_I2CCMD_OPCODE_WRITE | +- phy_data_swapped); ++ (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | ++ E1000_I2CCMD_OPCODE_WRITE | ++ phy_data_swapped); + + wr32(E1000_I2CCMD, i2ccmd); + +@@ -348,6 +355,130 @@ s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data) + } + + /** ++ * igb_read_sfp_data_byte - Reads SFP module data. ++ * @hw: pointer to the HW structure ++ * @offset: byte location offset to be read ++ * @data: read data buffer pointer ++ * ++ * Reads one byte from SFP module data stored ++ * in SFP resided EEPROM memory or SFP diagnostic area. ++ * Function should be called with ++ * E1000_I2CCMD_SFP_DATA_ADDR() for SFP module database access ++ * E1000_I2CCMD_SFP_DIAG_ADDR() for SFP diagnostics parameters ++ * access ++ **/ ++s32 igb_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data) ++{ ++ u32 i = 0; ++ u32 i2ccmd = 0; ++ u32 data_local = 0; ++ ++ if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) { ++ hw_dbg("I2CCMD command address exceeds upper limit\n"); ++ return -E1000_ERR_PHY; ++ } ++ ++ /* Set up Op-code, EEPROM Address,in the I2CCMD ++ * register. The MAC will take care of interfacing with the ++ * EEPROM to retrieve the desired data. ++ */ ++ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | ++ E1000_I2CCMD_OPCODE_READ); ++ ++ wr32(E1000_I2CCMD, i2ccmd); ++ ++ /* Poll the ready bit to see if the I2C read completed */ ++ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { ++ udelay(50); ++ data_local = rd32(E1000_I2CCMD); ++ if (data_local & E1000_I2CCMD_READY) ++ break; ++ } ++ if (!(data_local & E1000_I2CCMD_READY)) { ++ hw_dbg("I2CCMD Read did not complete\n"); ++ return -E1000_ERR_PHY; ++ } ++ if (data_local & E1000_I2CCMD_ERROR) { ++ hw_dbg("I2CCMD Error bit set\n"); ++ return -E1000_ERR_PHY; ++ } ++ *data = (u8) data_local & 0xFF; ++ ++ return 0; ++} ++ ++/** ++ * e1000_write_sfp_data_byte - Writes SFP module data. ++ * @hw: pointer to the HW structure ++ * @offset: byte location offset to write to ++ * @data: data to write ++ * ++ * Writes one byte to SFP module data stored ++ * in SFP resided EEPROM memory or SFP diagnostic area. ++ * Function should be called with ++ * E1000_I2CCMD_SFP_DATA_ADDR() for SFP module database access ++ * E1000_I2CCMD_SFP_DIAG_ADDR() for SFP diagnostics parameters ++ * access ++ **/ ++s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data) ++{ ++ u32 i = 0; ++ u32 i2ccmd = 0; ++ u32 data_local = 0; ++ ++ if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) { ++ hw_dbg("I2CCMD command address exceeds upper limit\n"); ++ return -E1000_ERR_PHY; ++ } ++ /* The programming interface is 16 bits wide ++ * so we need to read the whole word first ++ * then update appropriate byte lane and write ++ * the updated word back. ++ */ ++ /* Set up Op-code, EEPROM Address,in the I2CCMD ++ * register. The MAC will take care of interfacing ++ * with an EEPROM to write the data given. ++ */ ++ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | ++ E1000_I2CCMD_OPCODE_READ); ++ /* Set a command to read single word */ ++ wr32(E1000_I2CCMD, i2ccmd); ++ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { ++ udelay(50); ++ /* Poll the ready bit to see if lastly ++ * launched I2C operation completed ++ */ ++ i2ccmd = rd32(E1000_I2CCMD); ++ if (i2ccmd & E1000_I2CCMD_READY) { ++ /* Check if this is READ or WRITE phase */ ++ if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) == ++ E1000_I2CCMD_OPCODE_READ) { ++ /* Write the selected byte ++ * lane and update whole word ++ */ ++ data_local = i2ccmd & 0xFF00; ++ data_local |= data; ++ i2ccmd = ((offset << ++ E1000_I2CCMD_REG_ADDR_SHIFT) | ++ E1000_I2CCMD_OPCODE_WRITE | data_local); ++ wr32(E1000_I2CCMD, i2ccmd); ++ } else { ++ break; ++ } ++ } ++ } ++ if (!(i2ccmd & E1000_I2CCMD_READY)) { ++ hw_dbg("I2CCMD Write did not complete\n"); ++ return -E1000_ERR_PHY; ++ } ++ if (i2ccmd & E1000_I2CCMD_ERROR) { ++ hw_dbg("I2CCMD Error bit set\n"); ++ return -E1000_ERR_PHY; ++ } ++ return 0; ++} ++ ++/** + * igb_read_phy_reg_igp - Read igp PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read +@@ -370,8 +501,8 @@ s32 igb_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) + + if (offset > MAX_PHY_MULTI_PAGE_REG) { + ret_val = igb_write_phy_reg_mdic(hw, +- IGP01E1000_PHY_PAGE_SELECT, +- (u16)offset); ++ IGP01E1000_PHY_PAGE_SELECT, ++ (u16)offset); + if (ret_val) { + hw->phy.ops.release(hw); + goto out; +@@ -409,8 +540,8 @@ s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) + + if (offset > MAX_PHY_MULTI_PAGE_REG) { + ret_val = igb_write_phy_reg_mdic(hw, +- IGP01E1000_PHY_PAGE_SELECT, +- (u16)offset); ++ IGP01E1000_PHY_PAGE_SELECT, ++ (u16)offset); + if (ret_val) { + hw->phy.ops.release(hw); + goto out; +@@ -418,7 +549,7 @@ s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) + } + + ret_val = igb_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, +- data); ++ data); + + hw->phy.ops.release(hw); + +@@ -438,7 +569,6 @@ s32 igb_copper_link_setup_82580(struct e1000_hw *hw) + s32 ret_val; + u16 phy_data; + +- + if (phy->reset_disable) { + ret_val = 0; + goto out; +@@ -463,6 +593,31 @@ s32 igb_copper_link_setup_82580(struct e1000_hw *hw) + phy_data |= I82580_CFG_ENABLE_DOWNSHIFT; + + ret_val = phy->ops.write_reg(hw, I82580_CFG_REG, phy_data); ++ if (ret_val) ++ goto out; ++ ++ /* Set MDI/MDIX mode */ ++ ret_val = phy->ops.read_reg(hw, I82580_PHY_CTRL_2, &phy_data); ++ if (ret_val) ++ goto out; ++ phy_data &= ~I82580_PHY_CTRL2_MDIX_CFG_MASK; ++ /* Options: ++ * 0 - Auto (default) ++ * 1 - MDI mode ++ * 2 - MDI-X mode ++ */ ++ switch (hw->phy.mdix) { ++ case 1: ++ break; ++ case 2: ++ phy_data |= I82580_PHY_CTRL2_MANUAL_MDIX; ++ break; ++ case 0: ++ default: ++ phy_data |= I82580_PHY_CTRL2_AUTO_MDI_MDIX; ++ break; ++ } ++ ret_val = hw->phy.ops.write_reg(hw, I82580_PHY_CTRL_2, phy_data); + + out: + return ret_val; +@@ -493,8 +648,7 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw) + + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + +- /* +- * Options: ++ /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode +@@ -519,8 +673,7 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw) + break; + } + +- /* +- * Options: ++ /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled +@@ -535,12 +688,11 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw) + goto out; + + if (phy->revision < E1000_REVISION_4) { +- /* +- * Force TX_CLK in the Extended PHY Specific Control Register ++ /* Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ + ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, +- &phy_data); ++ &phy_data); + if (ret_val) + goto out; + +@@ -588,18 +740,15 @@ s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw) + s32 ret_val; + u16 phy_data; + +- if (phy->reset_disable) { +- ret_val = 0; +- goto out; +- } ++ if (phy->reset_disable) ++ return 0; + + /* Enable CRS on Tx. This must be set for half-duplex operation. */ + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if (ret_val) +- goto out; ++ return ret_val; + +- /* +- * Options: ++ /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode +@@ -627,8 +776,7 @@ s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw) + break; + } + +- /* +- * Options: ++ /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled +@@ -639,23 +787,39 @@ s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw) + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; + + /* Enable downshift and setting it to X6 */ ++ if (phy->id == M88E1543_E_PHY_ID) { ++ phy_data &= ~I347AT4_PSCR_DOWNSHIFT_ENABLE; ++ ret_val = ++ phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); ++ if (ret_val) ++ return ret_val; ++ ++ ret_val = igb_phy_sw_reset(hw); ++ if (ret_val) { ++ hw_dbg("Error committing the PHY changes\n"); ++ return ret_val; ++ } ++ } ++ + phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK; + phy_data |= I347AT4_PSCR_DOWNSHIFT_6X; + phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE; + + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if (ret_val) +- goto out; ++ return ret_val; + + /* Commit the changes. */ + ret_val = igb_phy_sw_reset(hw); + if (ret_val) { + hw_dbg("Error committing the PHY changes\n"); +- goto out; ++ return ret_val; + } ++ ret_val = igb_set_master_slave_mode(hw); ++ if (ret_val) ++ return ret_val; + +-out: +- return ret_val; ++ return 0; + } + + /** +@@ -682,14 +846,12 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) + goto out; + } + +- /* +- * Wait 100ms for MAC to configure PHY from NVM settings, to avoid ++ /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid + * timeout issues when LFS is enabled. + */ + msleep(100); + +- /* +- * The NVM settings will configure LPLU in D3 for ++ /* The NVM settings will configure LPLU in D3 for + * non-IGP1 PHYs. + */ + if (phy->type == e1000_phy_igp) { +@@ -733,8 +895,7 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) + + /* set auto-master slave resolution settings */ + if (hw->mac.autoneg) { +- /* +- * when autonegotiation advertisement is only 1000Mbps then we ++ /* when autonegotiation advertisement is only 1000Mbps then we + * should disable SmartSpeed and enable Auto MasterSlave + * resolution as hardware default. + */ +@@ -812,14 +973,12 @@ static s32 igb_copper_link_autoneg(struct e1000_hw *hw) + s32 ret_val; + u16 phy_ctrl; + +- /* +- * Perform some bounds checking on the autoneg advertisement ++ /* Perform some bounds checking on the autoneg advertisement + * parameter. + */ + phy->autoneg_advertised &= phy->autoneg_mask; + +- /* +- * If autoneg_advertised is zero, we assume it was not defaulted ++ /* If autoneg_advertised is zero, we assume it was not defaulted + * by the calling code so we set to advertise full capability. + */ + if (phy->autoneg_advertised == 0) +@@ -833,8 +992,7 @@ static s32 igb_copper_link_autoneg(struct e1000_hw *hw) + } + hw_dbg("Restarting Auto-Neg\n"); + +- /* +- * Restart auto-negotiation by setting the Auto Neg Enable bit and ++ /* Restart auto-negotiation by setting the Auto Neg Enable bit and + * the Auto Neg Restart bit in the PHY control register. + */ + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); +@@ -846,8 +1004,7 @@ static s32 igb_copper_link_autoneg(struct e1000_hw *hw) + if (ret_val) + goto out; + +- /* +- * Does the user want to wait for Auto-Neg to complete here, or ++ /* Does the user want to wait for Auto-Neg to complete here, or + * check at a later time (for example, callback routine). + */ + if (phy->autoneg_wait_to_complete) { +@@ -896,16 +1053,14 @@ static s32 igb_phy_setup_autoneg(struct e1000_hw *hw) + goto out; + } + +- /* +- * Need to parse both autoneg_advertised and fc and set up ++ /* Need to parse both autoneg_advertised and fc and set up + * the appropriate PHY registers. First we will parse for + * autoneg_advertised software override. Since we can advertise + * a plethora of combinations, we need to check each bit + * individually. + */ + +- /* +- * First we clear all the 10/100 mb speed bits in the Auto-Neg ++ /* First we clear all the 10/100 mb speed bits in the Auto-Neg + * Advertisement Register (Address 4) and the 1000 mb speed bits in + * the 1000Base-T Control Register (Address 9). + */ +@@ -951,8 +1106,7 @@ static s32 igb_phy_setup_autoneg(struct e1000_hw *hw) + mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; + } + +- /* +- * Check for a software override of the flow control settings, and ++ /* Check for a software override of the flow control settings, and + * setup the PHY advertisement registers accordingly. If + * auto-negotiation is enabled, then software will have to set the + * "PAUSE" bits to the correct value in the Auto-Negotiation +@@ -971,15 +1125,13 @@ static s32 igb_phy_setup_autoneg(struct e1000_hw *hw) + */ + switch (hw->fc.current_mode) { + case e1000_fc_none: +- /* +- * Flow control (RX & TX) is completely disabled by a ++ /* Flow control (RX & TX) is completely disabled by a + * software over-ride. + */ + mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); + break; + case e1000_fc_rx_pause: +- /* +- * RX Flow control is enabled, and TX Flow control is ++ /* RX Flow control is enabled, and TX Flow control is + * disabled, by a software over-ride. + * + * Since there really isn't a way to advertise that we are +@@ -991,16 +1143,14 @@ static s32 igb_phy_setup_autoneg(struct e1000_hw *hw) + mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); + break; + case e1000_fc_tx_pause: +- /* +- * TX Flow control is enabled, and RX Flow control is ++ /* TX Flow control is enabled, and RX Flow control is + * disabled, by a software over-ride. + */ + mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; + mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; + break; + case e1000_fc_full: +- /* +- * Flow control (both RX and TX) is enabled by a software ++ /* Flow control (both RX and TX) is enabled by a software + * over-ride. + */ + mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); +@@ -1043,18 +1193,15 @@ s32 igb_setup_copper_link(struct e1000_hw *hw) + s32 ret_val; + bool link; + +- + if (hw->mac.autoneg) { +- /* +- * Setup autoneg and flow control advertisement and perform ++ /* Setup autoneg and flow control advertisement and perform + * autonegotiation. + */ + ret_val = igb_copper_link_autoneg(hw); + if (ret_val) + goto out; + } else { +- /* +- * PHY will be set to 10H, 10F, 100H or 100F ++ /* PHY will be set to 10H, 10F, 100H or 100F + * depending on user settings. + */ + hw_dbg("Forcing Speed and Duplex\n"); +@@ -1065,14 +1212,10 @@ s32 igb_setup_copper_link(struct e1000_hw *hw) + } + } + +- /* +- * Check link status. Wait up to 100 microseconds for link to become ++ /* Check link status. Wait up to 100 microseconds for link to become + * valid. + */ +- ret_val = igb_phy_has_link(hw, +- COPPER_LINK_UP_LIMIT, +- 10, +- &link); ++ ret_val = igb_phy_has_link(hw, COPPER_LINK_UP_LIMIT, 10, &link); + if (ret_val) + goto out; + +@@ -1113,8 +1256,7 @@ s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw) + if (ret_val) + goto out; + +- /* +- * Clear Auto-Crossover to force MDI manually. IGP requires MDI ++ /* Clear Auto-Crossover to force MDI manually. IGP requires MDI + * forced whenever speed and duplex are forced. + */ + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); +@@ -1135,10 +1277,7 @@ s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw) + if (phy->autoneg_wait_to_complete) { + hw_dbg("Waiting for forced speed/duplex link on IGP phy.\n"); + +- ret_val = igb_phy_has_link(hw, +- PHY_FORCE_LIMIT, +- 100000, +- &link); ++ ret_val = igb_phy_has_link(hw, PHY_FORCE_LIMIT, 10000, &link); + if (ret_val) + goto out; + +@@ -1146,10 +1285,7 @@ s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw) + hw_dbg("Link taking longer than expected.\n"); + + /* Try once more */ +- ret_val = igb_phy_has_link(hw, +- PHY_FORCE_LIMIT, +- 100000, +- &link); ++ ret_val = igb_phy_has_link(hw, PHY_FORCE_LIMIT, 10000, &link); + if (ret_val) + goto out; + } +@@ -1175,20 +1311,24 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) + u16 phy_data; + bool link; + +- /* +- * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI +- * forced whenever speed and duplex are forced. +- */ +- ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); +- if (ret_val) +- goto out; ++ /* I210 and I211 devices support Auto-Crossover in forced operation. */ ++ if (phy->type != e1000_phy_i210) { ++ /* Clear Auto-Crossover to force MDI manually. M88E1000 ++ * requires MDI forced whenever speed and duplex are forced. ++ */ ++ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, ++ &phy_data); ++ if (ret_val) ++ goto out; + +- phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; +- ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); +- if (ret_val) +- goto out; ++ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; ++ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, ++ phy_data); ++ if (ret_val) ++ goto out; + +- hw_dbg("M88E1000 PSCR: %X\n", phy_data); ++ hw_dbg("M88E1000 PSCR: %X\n", phy_data); ++ } + + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); + if (ret_val) +@@ -1213,19 +1353,28 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) + goto out; + + if (!link) { +- if (hw->phy.type != e1000_phy_m88 || +- hw->phy.id == I347AT4_E_PHY_ID || +- hw->phy.id == M88E1112_E_PHY_ID) { ++ bool reset_dsp = true; ++ ++ switch (hw->phy.id) { ++ case I347AT4_E_PHY_ID: ++ case M88E1112_E_PHY_ID: ++ case I210_I_PHY_ID: ++ reset_dsp = false; ++ break; ++ default: ++ if (hw->phy.type != e1000_phy_m88) ++ reset_dsp = false; ++ break; ++ } ++ if (!reset_dsp) + hw_dbg("Link taking longer than expected.\n"); +- } else { +- +- /* +- * We didn't get link. ++ else { ++ /* We didn't get link. + * Reset the DSP and cross our fingers. + */ + ret_val = phy->ops.write_reg(hw, +- M88E1000_PHY_PAGE_SELECT, +- 0x001d); ++ M88E1000_PHY_PAGE_SELECT, ++ 0x001d); + if (ret_val) + goto out; + ret_val = igb_phy_reset_dsp(hw); +@@ -1243,15 +1392,15 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) + + if (hw->phy.type != e1000_phy_m88 || + hw->phy.id == I347AT4_E_PHY_ID || +- hw->phy.id == M88E1112_E_PHY_ID) ++ hw->phy.id == M88E1112_E_PHY_ID || ++ hw->phy.id == I210_I_PHY_ID) + goto out; + + ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); + if (ret_val) + goto out; + +- /* +- * Resetting the phy means we need to re-force TX_CLK in the ++ /* Resetting the phy means we need to re-force TX_CLK in the + * Extended PHY Specific Control Register to 25MHz clock from + * the reset value of 2.5MHz. + */ +@@ -1260,8 +1409,7 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) + if (ret_val) + goto out; + +- /* +- * In addition, we must re-enable CRS on Tx for both half and full ++ /* In addition, we must re-enable CRS on Tx for both half and full + * duplex. + */ + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); +@@ -1288,7 +1436,7 @@ out: + * take affect. + **/ + static void igb_phy_force_speed_duplex_setup(struct e1000_hw *hw, +- u16 *phy_ctrl) ++ u16 *phy_ctrl) + { + struct e1000_mac_info *mac = &hw->mac; + u32 ctrl; +@@ -1369,8 +1517,7 @@ s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active) + data); + if (ret_val) + goto out; +- /* +- * LPLU and SmartSpeed are mutually exclusive. LPLU is used ++ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used + * during Dx states where the power conservation is most + * important. During driver activity we should enable + * SmartSpeed, so performance is maintained. +@@ -1413,13 +1560,13 @@ s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active) + + /* When LPLU is enabled, we should disable SmartSpeed */ + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, +- &data); ++ &data); + if (ret_val) + goto out; + + data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, +- data); ++ data); + } + + out: +@@ -1441,6 +1588,7 @@ s32 igb_check_downshift(struct e1000_hw *hw) + u16 phy_data, offset, mask; + + switch (phy->type) { ++ case e1000_phy_i210: + case e1000_phy_m88: + case e1000_phy_gg82563: + offset = M88E1000_PHY_SPEC_STATUS; +@@ -1476,7 +1624,7 @@ out: + * + * Polarity is determined based on the PHY specific status register. + **/ +-static s32 igb_check_polarity_m88(struct e1000_hw *hw) ++s32 igb_check_polarity_m88(struct e1000_hw *hw) + { + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; +@@ -1507,8 +1655,7 @@ static s32 igb_check_polarity_igp(struct e1000_hw *hw) + s32 ret_val; + u16 data, offset, mask; + +- /* +- * Polarity is determined based on the speed of ++ /* Polarity is determined based on the speed of + * our connection. + */ + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); +@@ -1520,8 +1667,7 @@ static s32 igb_check_polarity_igp(struct e1000_hw *hw) + offset = IGP01E1000_PHY_PCS_INIT_REG; + mask = IGP01E1000_PHY_POLARITY_MASK; + } else { +- /* +- * This really only applies to 10Mbps since ++ /* This really only applies to 10Mbps since + * there is no polarity for 100Mbps (always 0). + */ + offset = IGP01E1000_PHY_PORT_STATUS; +@@ -1540,7 +1686,7 @@ out: + } + + /** +- * igb_wait_autoneg - Wait for auto-neg compeletion ++ * igb_wait_autoneg - Wait for auto-neg completion + * @hw: pointer to the HW structure + * + * Waits for auto-negotiation to complete or for the auto-negotiation time +@@ -1564,8 +1710,7 @@ static s32 igb_wait_autoneg(struct e1000_hw *hw) + msleep(100); + } + +- /* +- * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation ++ /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation + * has completed. + */ + return ret_val; +@@ -1581,25 +1726,26 @@ static s32 igb_wait_autoneg(struct e1000_hw *hw) + * Polls the PHY status register for link, 'iterations' number of times. + **/ + s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations, +- u32 usec_interval, bool *success) ++ u32 usec_interval, bool *success) + { + s32 ret_val = 0; + u16 i, phy_status; + + for (i = 0; i < iterations; i++) { +- /* +- * Some PHYs require the PHY_STATUS register to be read ++ /* Some PHYs require the PHY_STATUS register to be read + * twice due to the link bit being sticky. No harm doing + * it across the board. + */ + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); +- if (ret_val) { +- /* +- * If the first read fails, another entity may have ++ if (ret_val && usec_interval > 0) { ++ /* If the first read fails, another entity may have + * ownership of the resources, wait and try again to + * see if they have relinquished the resources yet. + */ +- udelay(usec_interval); ++ if (usec_interval >= 1000) ++ mdelay(usec_interval/1000); ++ else ++ udelay(usec_interval); + } + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); + if (ret_val) +@@ -1665,6 +1811,28 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw) + u16 phy_data, phy_data2, index, default_page, is_cm; + + switch (hw->phy.id) { ++ case I210_I_PHY_ID: ++ /* Get cable length from PHY Cable Diagnostics Control Reg */ ++ ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) + ++ (I347AT4_PCDL + phy->addr), ++ &phy_data); ++ if (ret_val) ++ return ret_val; ++ ++ /* Check if the unit of cable length is meters or cm */ ++ ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) + ++ I347AT4_PCDC, &phy_data2); ++ if (ret_val) ++ return ret_val; ++ ++ is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT); ++ ++ /* Populate the phy structure with cable length in meters */ ++ phy->min_cable_length = phy_data / (is_cm ? 100 : 1); ++ phy->max_cable_length = phy_data / (is_cm ? 100 : 1); ++ phy->cable_length = phy_data / (is_cm ? 100 : 1); ++ break; ++ case M88E1543_E_PHY_ID: + case I347AT4_E_PHY_ID: + /* Remember the original page select and set it to 7 */ + ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT, +@@ -1764,10 +1932,10 @@ s32 igb_get_cable_length_igp_2(struct e1000_hw *hw) + u16 cur_agc_index, max_agc_index = 0; + u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; + static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = { +- IGP02E1000_PHY_AGC_A, +- IGP02E1000_PHY_AGC_B, +- IGP02E1000_PHY_AGC_C, +- IGP02E1000_PHY_AGC_D ++ IGP02E1000_PHY_AGC_A, ++ IGP02E1000_PHY_AGC_B, ++ IGP02E1000_PHY_AGC_C, ++ IGP02E1000_PHY_AGC_D + }; + + /* Read the AGC registers for all channels */ +@@ -1776,8 +1944,7 @@ s32 igb_get_cable_length_igp_2(struct e1000_hw *hw) + if (ret_val) + goto out; + +- /* +- * Getting bits 15:9, which represent the combination of ++ /* Getting bits 15:9, which represent the combination of + * coarse and fine gain values. The result is a number + * that can be put into the lookup table to obtain the + * approximate cable length. +@@ -1997,7 +2164,7 @@ out: + * Verify the reset block is not blocking us from resetting. Acquire + * semaphore (if necessary) and read/set/write the device control reset + * bit in the PHY. Wait the appropriate delay time for the device to +- * reset and relase the semaphore (if necessary). ++ * reset and release the semaphore (if necessary). + **/ + s32 igb_phy_hw_reset(struct e1000_hw *hw) + { +@@ -2097,15 +2264,13 @@ s32 igb_phy_init_script_igp3(struct e1000_hw *hw) + hw->phy.ops.write_reg(hw, 0x1796, 0x0008); + /* Change cg_icount + enable integbp for channels BCD */ + hw->phy.ops.write_reg(hw, 0x1798, 0xD008); +- /* +- * Change cg_icount + enable integbp + change prop_factor_master ++ /* Change cg_icount + enable integbp + change prop_factor_master + * to 8 for channel A + */ + hw->phy.ops.write_reg(hw, 0x1898, 0xD918); + /* Disable AHT in Slave mode on channel A */ + hw->phy.ops.write_reg(hw, 0x187A, 0x0800); +- /* +- * Enable LPLU and disable AN to 1000 in non-D0a states, ++ /* Enable LPLU and disable AN to 1000 in non-D0a states, + * Enable SPD+B2B + */ + hw->phy.ops.write_reg(hw, 0x0019, 0x008D); +@@ -2129,10 +2294,16 @@ s32 igb_phy_init_script_igp3(struct e1000_hw *hw) + void igb_power_up_phy_copper(struct e1000_hw *hw) + { + u16 mii_reg = 0; ++ u16 power_reg = 0; + + /* The PHY will retain its settings across a power down/up cycle */ + hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); + mii_reg &= ~MII_CR_POWER_DOWN; ++ if (hw->phy.type == e1000_phy_i210) { ++ hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg); ++ power_reg &= ~GS40G_CS_POWER_DOWN; ++ hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg); ++ } + hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); + } + +@@ -2146,10 +2317,18 @@ void igb_power_up_phy_copper(struct e1000_hw *hw) + void igb_power_down_phy_copper(struct e1000_hw *hw) + { + u16 mii_reg = 0; ++ u16 power_reg = 0; + + /* The PHY will retain its settings across a power down/up cycle */ + hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); + mii_reg |= MII_CR_POWER_DOWN; ++ ++ /* i210 Phy requires an additional bit for power up/down */ ++ if (hw->phy.type == e1000_phy_i210) { ++ hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg); ++ power_reg |= GS40G_CS_POWER_DOWN; ++ hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg); ++ } + hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); + msleep(1); + } +@@ -2173,8 +2352,8 @@ static s32 igb_check_polarity_82580(struct e1000_hw *hw) + + if (!ret_val) + phy->cable_polarity = (data & I82580_PHY_STATUS2_REV_POLARITY) +- ? e1000_rev_polarity_reversed +- : e1000_rev_polarity_normal; ++ ? e1000_rev_polarity_reversed ++ : e1000_rev_polarity_normal; + + return ret_val; + } +@@ -2194,7 +2373,6 @@ s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw) + u16 phy_data; + bool link; + +- + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); + if (ret_val) + goto out; +@@ -2205,16 +2383,14 @@ s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw) + if (ret_val) + goto out; + +- /* +- * Clear Auto-Crossover to force MDI manually. 82580 requires MDI ++ /* Clear Auto-Crossover to force MDI manually. 82580 requires MDI + * forced whenever speed and duplex are forced. + */ + ret_val = phy->ops.read_reg(hw, I82580_PHY_CTRL_2, &phy_data); + if (ret_val) + goto out; + +- phy_data &= ~I82580_PHY_CTRL2_AUTO_MDIX; +- phy_data &= ~I82580_PHY_CTRL2_FORCE_MDI_MDIX; ++ phy_data &= ~I82580_PHY_CTRL2_MDIX_CFG_MASK; + + ret_val = phy->ops.write_reg(hw, I82580_PHY_CTRL_2, phy_data); + if (ret_val) +@@ -2227,10 +2403,7 @@ s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw) + if (phy->autoneg_wait_to_complete) { + hw_dbg("Waiting for forced speed/duplex link on 82580 phy\n"); + +- ret_val = igb_phy_has_link(hw, +- PHY_FORCE_LIMIT, +- 100000, +- &link); ++ ret_val = igb_phy_has_link(hw, PHY_FORCE_LIMIT, 100000, &link); + if (ret_val) + goto out; + +@@ -2238,10 +2411,7 @@ s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw) + hw_dbg("Link taking longer than expected.\n"); + + /* Try once more */ +- ret_val = igb_phy_has_link(hw, +- PHY_FORCE_LIMIT, +- 100000, +- &link); ++ ret_val = igb_phy_has_link(hw, PHY_FORCE_LIMIT, 100000, &link); + if (ret_val) + goto out; + } +@@ -2266,7 +2436,6 @@ s32 igb_get_phy_info_82580(struct e1000_hw *hw) + u16 data; + bool link; + +- + ret_val = igb_phy_has_link(hw, 1, 0, &link); + if (ret_val) + goto out; +@@ -2300,12 +2469,12 @@ s32 igb_get_phy_info_82580(struct e1000_hw *hw) + goto out; + + phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) +- ? e1000_1000t_rx_status_ok +- : e1000_1000t_rx_status_not_ok; ++ ? e1000_1000t_rx_status_ok ++ : e1000_1000t_rx_status_not_ok; + + phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) +- ? e1000_1000t_rx_status_ok +- : e1000_1000t_rx_status_not_ok; ++ ? e1000_1000t_rx_status_ok ++ : e1000_1000t_rx_status_not_ok; + } else { + phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; + phy->local_rx = e1000_1000t_rx_status_undefined; +@@ -2329,13 +2498,12 @@ s32 igb_get_cable_length_82580(struct e1000_hw *hw) + s32 ret_val; + u16 phy_data, length; + +- + ret_val = phy->ops.read_reg(hw, I82580_PHY_DIAG_STATUS, &phy_data); + if (ret_val) + goto out; + + length = (phy_data & I82580_DSTATUS_CABLE_LENGTH) >> +- I82580_DSTATUS_CABLE_LENGTH_SHIFT; ++ I82580_DSTATUS_CABLE_LENGTH_SHIFT; + + if (length == E1000_CABLE_LENGTH_UNDEFINED) + ret_val = -E1000_ERR_PHY; +@@ -2345,3 +2513,168 @@ s32 igb_get_cable_length_82580(struct e1000_hw *hw) + out: + return ret_val; + } ++ ++/** ++ * igb_write_phy_reg_gs40g - Write GS40G PHY register ++ * @hw: pointer to the HW structure ++ * @offset: lower half is register offset to write to ++ * upper half is page to use. ++ * @data: data to write at register offset ++ * ++ * Acquires semaphore, if necessary, then writes the data to PHY register ++ * at the offset. Release any acquired semaphores before exiting. ++ **/ ++s32 igb_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data) ++{ ++ s32 ret_val; ++ u16 page = offset >> GS40G_PAGE_SHIFT; ++ ++ offset = offset & GS40G_OFFSET_MASK; ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ return ret_val; ++ ++ ret_val = igb_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page); ++ if (ret_val) ++ goto release; ++ ret_val = igb_write_phy_reg_mdic(hw, offset, data); ++ ++release: ++ hw->phy.ops.release(hw); ++ return ret_val; ++} ++ ++/** ++ * igb_read_phy_reg_gs40g - Read GS40G PHY register ++ * @hw: pointer to the HW structure ++ * @offset: lower half is register offset to read to ++ * upper half is page to use. ++ * @data: data to read at register offset ++ * ++ * Acquires semaphore, if necessary, then reads the data in the PHY register ++ * at the offset. Release any acquired semaphores before exiting. ++ **/ ++s32 igb_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data) ++{ ++ s32 ret_val; ++ u16 page = offset >> GS40G_PAGE_SHIFT; ++ ++ offset = offset & GS40G_OFFSET_MASK; ++ ret_val = hw->phy.ops.acquire(hw); ++ if (ret_val) ++ return ret_val; ++ ++ ret_val = igb_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page); ++ if (ret_val) ++ goto release; ++ ret_val = igb_read_phy_reg_mdic(hw, offset, data); ++ ++release: ++ hw->phy.ops.release(hw); ++ return ret_val; ++} ++ ++/** ++ * igb_set_master_slave_mode - Setup PHY for Master/slave mode ++ * @hw: pointer to the HW structure ++ * ++ * Sets up Master/slave mode ++ **/ ++static s32 igb_set_master_slave_mode(struct e1000_hw *hw) ++{ ++ s32 ret_val; ++ u16 phy_data; ++ ++ /* Resolve Master/Slave mode */ ++ ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data); ++ if (ret_val) ++ return ret_val; ++ ++ /* load defaults for future use */ ++ hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ? ++ ((phy_data & CR_1000T_MS_VALUE) ? ++ e1000_ms_force_master : ++ e1000_ms_force_slave) : e1000_ms_auto; ++ ++ switch (hw->phy.ms_type) { ++ case e1000_ms_force_master: ++ phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); ++ break; ++ case e1000_ms_force_slave: ++ phy_data |= CR_1000T_MS_ENABLE; ++ phy_data &= ~(CR_1000T_MS_VALUE); ++ break; ++ case e1000_ms_auto: ++ phy_data &= ~CR_1000T_MS_ENABLE; ++ /* fall-through */ ++ default: ++ break; ++ } ++ ++ return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data); ++} ++ ++ ++/** ++ * igb_phy_init_script_5461s - Inits the BCM5461S PHY ++ * @hw: pointer to the HW structure ++ * ++ * Initializes a Broadcom Gigabit PHY. ++ **/ ++s32 igb_phy_init_script_5461s(struct e1000_hw *hw) ++{ ++ u16 mii_reg_led = 0; ++ ++ /* 1. Speed LED (Set the Link LED mode), Shadow 00010, 0x1C.bit2=1 */ ++ hw->phy.ops.write_reg(hw, 0x1C, 0x0800); ++ hw->phy.ops.read_reg(hw, 0x1C, &mii_reg_led); ++ mii_reg_led |= 0x0004; ++ hw->phy.ops.write_reg(hw, 0x1C, mii_reg_led | 0x8000); ++ ++ /* 2. Active LED (Set the Link LED mode), Shadow 01001, 0x1C.bit4=1, 0x10.bit5=0 */ ++ hw->phy.ops.write_reg(hw, 0x1C, 0x2400); ++ hw->phy.ops.read_reg(hw, 0x1C, &mii_reg_led); ++ mii_reg_led |= 0x0010; ++ hw->phy.ops.write_reg(hw, 0x1C, mii_reg_led | 0x8000); ++ hw->phy.ops.read_reg(hw, 0x10, &mii_reg_led); ++ mii_reg_led &= 0xffdf; ++ hw->phy.ops.write_reg(hw, 0x10, mii_reg_led); ++ ++ return 0; ++} ++ ++ ++/** ++ * igb_get_phy_info_5461s - Retrieve 5461s PHY information ++ * @hw: pointer to the HW structure ++ * ++ * Read PHY status to determine if link is up. If link is up, then ++ * set/determine 10base-T extended distance and polarity correction. Read ++ * PHY port status to determine MDI/MDIx and speed. Based on the speed, ++ * determine on the cable length, local and remote receiver. ++ **/ ++s32 igb_get_phy_info_5461s(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ bool link; ++ ++ ret_val = igb_phy_has_link(hw, 1, 0, &link); ++ if (ret_val) ++ goto out; ++ ++ if (!link) { ++ ret_val = -E1000_ERR_CONFIG; ++ goto out; ++ } ++ ++ phy->polarity_correction = true; ++ ++ phy->is_mdix = true; ++ phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; ++ phy->local_rx = e1000_1000t_rx_status_ok; ++ phy->remote_rx = e1000_1000t_rx_status_ok; ++ ++out: ++ return ret_val; ++} +diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h +index 8510797..ca60225 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_phy.h ++++ b/drivers/net/ethernet/intel/igb/e1000_phy.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -65,14 +65,21 @@ s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations, + void igb_power_up_phy_copper(struct e1000_hw *hw); + void igb_power_down_phy_copper(struct e1000_hw *hw); + s32 igb_phy_init_script_igp3(struct e1000_hw *hw); ++s32 igb_phy_init_script_5461s(struct e1000_hw *hw); ++s32 igb_get_phy_info_5461s(struct e1000_hw *hw); + s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); + s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); + s32 igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data); + s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data); ++s32 igb_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data); ++s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data); + s32 igb_copper_link_setup_82580(struct e1000_hw *hw); + s32 igb_get_phy_info_82580(struct e1000_hw *hw); + s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw); + s32 igb_get_cable_length_82580(struct e1000_hw *hw); ++s32 igb_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); ++s32 igb_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data); ++s32 igb_check_polarity_m88(struct e1000_hw *hw); + + /* IGP01E1000 Specific Registers */ + #define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ +@@ -108,12 +115,21 @@ s32 igb_get_cable_length_82580(struct e1000_hw *hw); + #define I82580_PHY_STATUS2_SPEED_100MBPS 0x0100 + + /* I82580 PHY Control 2 */ +-#define I82580_PHY_CTRL2_AUTO_MDIX 0x0400 +-#define I82580_PHY_CTRL2_FORCE_MDI_MDIX 0x0200 ++#define I82580_PHY_CTRL2_MANUAL_MDIX 0x0200 ++#define I82580_PHY_CTRL2_AUTO_MDI_MDIX 0x0400 ++#define I82580_PHY_CTRL2_MDIX_CFG_MASK 0x0600 + + /* I82580 PHY Diagnostics Status */ + #define I82580_DSTATUS_CABLE_LENGTH 0x03FC + #define I82580_DSTATUS_CABLE_LENGTH_SHIFT 2 ++ ++/* 82580 PHY Power Management */ ++#define E1000_82580_PHY_POWER_MGMT 0xE14 ++#define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */ ++#define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */ ++#define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */ ++#define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */ ++ + /* Enable flexible speed on link-up */ + #define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ + #define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ +@@ -133,4 +149,34 @@ s32 igb_get_cable_length_82580(struct e1000_hw *hw); + + #define E1000_CABLE_LENGTH_UNDEFINED 0xFF + ++/* GS40G - I210 PHY defines */ ++#define GS40G_PAGE_SELECT 0x16 ++#define GS40G_PAGE_SHIFT 16 ++#define GS40G_OFFSET_MASK 0xFFFF ++#define GS40G_PAGE_2 0x20000 ++#define GS40G_MAC_REG2 0x15 ++#define GS40G_MAC_LB 0x4140 ++#define GS40G_MAC_SPEED_1G 0X0006 ++#define GS40G_COPPER_SPEC 0x0010 ++#define GS40G_CS_POWER_DOWN 0x0002 ++#define GS40G_LINE_LB 0x4000 ++ ++/* SFP modules ID memory locations */ ++#define E1000_SFF_IDENTIFIER_OFFSET 0x00 ++#define E1000_SFF_IDENTIFIER_SFF 0x02 ++#define E1000_SFF_IDENTIFIER_SFP 0x03 ++ ++#define E1000_SFF_ETH_FLAGS_OFFSET 0x06 ++/* Flags for SFP modules compatible with ETH up to 1Gb */ ++struct e1000_sfp_flags { ++ u8 e1000_base_sx:1; ++ u8 e1000_base_lx:1; ++ u8 e1000_base_cx:1; ++ u8 e1000_base_t:1; ++ u8 e100_base_lx:1; ++ u8 e100_base_fx:1; ++ u8 e10_base_bx10:1; ++ u8 e10_base_px:1; ++}; ++ + #endif +diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h +index 0a860bc..82632c6 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_regs.h ++++ b/drivers/net/ethernet/intel/igb/e1000_regs.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -65,6 +65,7 @@ + #define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */ + #define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ + #define E1000_LEDCTL 0x00E00 /* LED Control - RW */ ++#define E1000_LEDMUX 0x08130 /* LED MUX Control */ + #define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ + #define E1000_PBS 0x01008 /* Packet Buffer Size */ + #define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ +@@ -75,6 +76,17 @@ + #define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ + #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ + #define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ ++#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */ ++#define E1000_I2CBB_EN 0x00000100 /* I2C - Bit Bang Enable */ ++#define E1000_I2C_CLK_OUT 0x00000200 /* I2C- Clock */ ++#define E1000_I2C_DATA_OUT 0x00000400 /* I2C- Data Out */ ++#define E1000_I2C_DATA_OE_N 0x00000800 /* I2C- Data Output Enable */ ++#define E1000_I2C_DATA_IN 0x00001000 /* I2C- Data In */ ++#define E1000_I2C_CLK_OE_N 0x00002000 /* I2C- Clock Output Enable */ ++#define E1000_I2C_CLK_IN 0x00004000 /* I2C- Clock In */ ++#define E1000_MPHY_ADDR_CTRL 0x0024 /* GbE MPHY Address Control */ ++#define E1000_MPHY_DATA 0x0E10 /* GBE MPHY Data */ ++#define E1000_MPHY_STAT 0x0E0C /* GBE MPHY Statistics */ + + /* IEEE 1588 TIMESYNCH */ + #define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */ +@@ -91,6 +103,8 @@ + #define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */ + #define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */ + #define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */ ++#define E1000_TSICR 0x0B66C /* Interrupt Cause Register */ ++#define E1000_TSIM 0x0B674 /* Interrupt Mask Register */ + + /* Filtering Registers */ + #define E1000_SAQF(_n) (0x5980 + 4 * (_n)) +@@ -107,22 +121,30 @@ + #define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40)) + + /* DMA Coalescing registers */ +-#define E1000_DMACR 0x02508 /* Control Register */ +-#define E1000_DMCTXTH 0x03550 /* Transmit Threshold */ +-#define E1000_DMCTLX 0x02514 /* Time to Lx Request */ +-#define E1000_DMCRTRH 0x05DD0 /* Receive Packet Rate Threshold */ +-#define E1000_DMCCNT 0x05DD4 /* Current Rx Count */ +-#define E1000_FCRTC 0x02170 /* Flow Control Rx high watermark */ +-#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */ ++#define E1000_DMACR 0x02508 /* Control Register */ ++#define E1000_DMCTXTH 0x03550 /* Transmit Threshold */ ++#define E1000_DMCTLX 0x02514 /* Time to Lx Request */ ++#define E1000_DMCRTRH 0x05DD0 /* Receive Packet Rate Threshold */ ++#define E1000_DMCCNT 0x05DD4 /* Current Rx Count */ ++#define E1000_FCRTC 0x02170 /* Flow Control Rx high watermark */ ++#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */ + + /* TX Rate Limit Registers */ +-#define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select - WO */ +-#define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config - WO */ ++#define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select - WO */ ++#define E1000_RTTBCNRM 0x3690 /* Tx BCN Rate-scheduler MMW */ ++#define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config - WO */ + + /* Split and Replication RX Control - RW */ +-#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ +-/* +- * Convenience macros ++#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ ++ ++/* Thermal sensor configuration and status registers */ ++#define E1000_THMJT 0x08100 /* Junction Temperature */ ++#define E1000_THLOWTC 0x08104 /* Low Threshold Control */ ++#define E1000_THMIDTC 0x08108 /* Mid Threshold Control */ ++#define E1000_THHIGHTC 0x0810C /* High Threshold Control */ ++#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */ ++ ++/* Convenience macros + * + * Note: "_n" is the queue number of the register to be written to. + * +@@ -155,8 +177,12 @@ + : (0x0E018 + ((_n) * 0x40))) + #define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) \ + : (0x0E028 + ((_n) * 0x40))) +-#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8)) +-#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8)) ++#define E1000_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \ ++ (0x0C014 + ((_n) * 0x40))) ++#define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n) ++#define E1000_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \ ++ (0x0E014 + ((_n) * 0x40))) ++#define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n) + #define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) \ + : (0x0E038 + ((_n) * 0x40))) + #define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) \ +@@ -264,7 +290,7 @@ + #define E1000_RFCTL 0x05008 /* Receive Filter Control*/ + #define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ + #define E1000_RA 0x05400 /* Receive Address - RW Array */ +-#define E1000_RA2 0x054E0 /* 2nd half of receive address array - RW Array */ ++#define E1000_RA2 0x054E0 /* 2nd half of Rx address array - RW Array */ + #define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4)) + #define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \ + (0x054E0 + ((_i - 16) * 8))) +@@ -337,19 +363,38 @@ + (readl(hw->hw_addr + reg + ((offset) << 2))) + + /* DMA Coalescing registers */ +-#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */ ++#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */ + + /* Energy Efficient Ethernet "EEE" register */ +-#define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */ +-#define E1000_EEER 0x0E30 /* Energy Efficient Ethernet */ ++#define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */ ++#define E1000_EEER 0x0E30 /* Energy Efficient Ethernet */ ++#define E1000_EEE_SU 0X0E34 /* EEE Setup */ ++#define E1000_EMIADD 0x10 /* Extended Memory Indirect Address */ ++#define E1000_EMIDATA 0x11 /* Extended Memory Indirect Data */ ++#define E1000_MMDAC 13 /* MMD Access Control */ ++#define E1000_MMDAAD 14 /* MMD Access Address/Data */ + + /* Thermal Sensor Register */ +-#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */ ++#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */ + + /* OS2BMC Registers */ +-#define E1000_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */ +-#define E1000_B2OGPRC 0x04158 /* BMC2OS packets received by host */ +-#define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */ +-#define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */ ++#define E1000_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */ ++#define E1000_B2OGPRC 0x04158 /* BMC2OS packets received by host */ ++#define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */ ++#define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */ ++ ++#define E1000_SRWR 0x12018 /* Shadow Ram Write Register - RW */ ++#define E1000_I210_FLMNGCTL 0x12038 ++#define E1000_I210_FLMNGDATA 0x1203C ++#define E1000_I210_FLMNGCNT 0x12040 ++ ++#define E1000_I210_FLSWCTL 0x12048 ++#define E1000_I210_FLSWDATA 0x1204C ++#define E1000_I210_FLSWCNT 0x12050 ++ ++#define E1000_I210_FLA 0x1201C ++ ++#define E1000_INVM_DATA_REG(_n) (0x12120 + 4*(_n)) ++#define E1000_INVM_SIZE 64 /* Number of INVM Data Registers */ + + #endif +diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h +index c69feeb..c421c35 100644 +--- a/drivers/net/ethernet/intel/igb/igb.h ++++ b/drivers/net/ethernet/intel/igb/igb.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -34,46 +34,66 @@ + #include "e1000_mac.h" + #include "e1000_82575.h" + ++#ifdef CONFIG_IGB_PTP + #include +-#include + #include ++#include ++#endif /* CONFIG_IGB_PTP */ + #include + #include ++#include ++#include + + struct igb_adapter; + ++#define E1000_PCS_CFG_IGN_SD 1 ++ + /* Interrupt defines */ +-#define IGB_START_ITR 648 /* ~6000 ints/sec */ +-#define IGB_4K_ITR 980 +-#define IGB_20K_ITR 196 +-#define IGB_70K_ITR 56 ++#define IGB_START_ITR 648 /* ~6000 ints/sec */ ++#define IGB_4K_ITR 980 ++#define IGB_20K_ITR 196 ++#define IGB_70K_ITR 56 + + /* TX/RX descriptor defines */ +-#define IGB_DEFAULT_TXD 256 +-#define IGB_DEFAULT_TX_WORK 128 +-#define IGB_MIN_TXD 80 +-#define IGB_MAX_TXD 4096 ++#define IGB_DEFAULT_TXD 256 ++#define IGB_DEFAULT_TX_WORK 128 ++#define IGB_MIN_TXD 80 ++#define IGB_MAX_TXD 4096 + +-#define IGB_DEFAULT_RXD 256 +-#define IGB_MIN_RXD 80 +-#define IGB_MAX_RXD 4096 ++#define IGB_DEFAULT_RXD 256 ++#define IGB_MIN_RXD 80 ++#define IGB_MAX_RXD 4096 + +-#define IGB_DEFAULT_ITR 3 /* dynamic */ +-#define IGB_MAX_ITR_USECS 10000 +-#define IGB_MIN_ITR_USECS 10 +-#define NON_Q_VECTORS 1 +-#define MAX_Q_VECTORS 8 ++#define IGB_DEFAULT_ITR 3 /* dynamic */ ++#define IGB_MAX_ITR_USECS 10000 ++#define IGB_MIN_ITR_USECS 10 ++#define NON_Q_VECTORS 1 ++#define MAX_Q_VECTORS 8 + + /* Transmit and receive queues */ +-#define IGB_MAX_RX_QUEUES (adapter->vfs_allocated_count ? 2 : \ +- (hw->mac.type > e1000_82575 ? 8 : 4)) +-#define IGB_MAX_TX_QUEUES 16 +- +-#define IGB_MAX_VF_MC_ENTRIES 30 +-#define IGB_MAX_VF_FUNCTIONS 8 +-#define IGB_MAX_VFTA_ENTRIES 128 +-#define IGB_82576_VF_DEV_ID 0x10CA +-#define IGB_I350_VF_DEV_ID 0x1520 ++#define IGB_MAX_RX_QUEUES 8 ++#define IGB_MAX_RX_QUEUES_82575 4 ++#define IGB_MAX_RX_QUEUES_I211 2 ++#define IGB_MAX_TX_QUEUES 8 ++#define IGB_MAX_VF_MC_ENTRIES 30 ++#define IGB_MAX_VF_FUNCTIONS 8 ++#define IGB_MAX_VFTA_ENTRIES 128 ++#define IGB_82576_VF_DEV_ID 0x10CA ++#define IGB_I350_VF_DEV_ID 0x1520 ++ ++/* NVM version defines */ ++#define IGB_MAJOR_MASK 0xF000 ++#define IGB_MINOR_MASK 0x0FF0 ++#define IGB_BUILD_MASK 0x000F ++#define IGB_COMB_VER_MASK 0x00FF ++#define IGB_MAJOR_SHIFT 12 ++#define IGB_MINOR_SHIFT 4 ++#define IGB_COMB_VER_SHFT 8 ++#define IGB_NVM_VER_INVALID 0xFFFF ++#define IGB_ETRACK_SHIFT 16 ++#define NVM_ETRACK_WORD 0x0042 ++#define NVM_COMB_VER_OFF 0x0083 ++#define NVM_COMB_VER_PTR 0x003d + + struct vf_data_storage { + unsigned char vf_mac_addresses[ETH_ALEN]; +@@ -85,7 +105,7 @@ struct vf_data_storage { + u16 pf_vlan; /* When set, guest VLAN config not allowed. */ + u16 pf_qos; + u16 tx_rate; +- struct pci_dev *vfdev; ++ bool spoofchk_enabled; + }; + + #define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ +@@ -104,48 +124,65 @@ struct vf_data_storage { + * descriptors until either it has this many to write back, or the + * ITR timer expires. + */ +-#define IGB_RX_PTHRESH 8 +-#define IGB_RX_HTHRESH 8 +-#define IGB_TX_PTHRESH 8 +-#define IGB_TX_HTHRESH 1 +-#define IGB_RX_WTHRESH ((hw->mac.type == e1000_82576 && \ +- adapter->msix_entries) ? 1 : 4) +-#define IGB_TX_WTHRESH ((hw->mac.type == e1000_82576 && \ +- adapter->msix_entries) ? 1 : 16) ++#define IGB_RX_PTHRESH ((hw->mac.type == e1000_i354) ? 12 : 8) ++#define IGB_RX_HTHRESH 8 ++#define IGB_TX_PTHRESH ((hw->mac.type == e1000_i354) ? 20 : 8) ++#define IGB_TX_HTHRESH 1 ++#define IGB_RX_WTHRESH ((hw->mac.type == e1000_82576 && \ ++ adapter->msix_entries) ? 1 : 4) ++#define IGB_TX_WTHRESH ((hw->mac.type == e1000_82576 && \ ++ adapter->msix_entries) ? 1 : 16) + + /* this is the size past which hardware will drop packets when setting LPE=0 */ + #define MAXIMUM_ETHERNET_VLAN_SIZE 1522 + + /* Supported Rx Buffer Sizes */ +-#define IGB_RXBUFFER_512 512 +-#define IGB_RXBUFFER_16384 16384 +-#define IGB_RX_HDR_LEN IGB_RXBUFFER_512 ++#define IGB_RXBUFFER_256 256 ++#define IGB_RXBUFFER_2048 2048 ++#define IGB_RX_HDR_LEN IGB_RXBUFFER_256 ++#define IGB_RX_BUFSZ IGB_RXBUFFER_2048 + +-/* How many Tx Descriptors do we need to call netif_wake_queue ? */ +-#define IGB_TX_QUEUE_WAKE 16 + /* How many Rx Buffers do we bundle into one write to the hardware ? */ +-#define IGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */ ++#define IGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */ + +-#define AUTO_ALL_MODES 0 +-#define IGB_EEPROM_APME 0x0400 ++#define AUTO_ALL_MODES 0 ++#define IGB_EEPROM_APME 0x0400 + + #ifndef IGB_MASTER_SLAVE + /* Switch to override PHY master/slave setting */ + #define IGB_MASTER_SLAVE e1000_ms_hw_default + #endif + +-#define IGB_MNG_VLAN_NONE -1 ++#define IGB_MNG_VLAN_NONE -1 ++ ++enum igb_tx_flags { ++ /* cmd_type flags */ ++ IGB_TX_FLAGS_VLAN = 0x01, ++ IGB_TX_FLAGS_TSO = 0x02, ++ IGB_TX_FLAGS_TSTAMP = 0x04, ++ ++ /* olinfo flags */ ++ IGB_TX_FLAGS_IPV4 = 0x10, ++ IGB_TX_FLAGS_CSUM = 0x20, ++}; + +-#define IGB_TX_FLAGS_CSUM 0x00000001 +-#define IGB_TX_FLAGS_VLAN 0x00000002 +-#define IGB_TX_FLAGS_TSO 0x00000004 +-#define IGB_TX_FLAGS_IPV4 0x00000008 +-#define IGB_TX_FLAGS_TSTAMP 0x00000010 +-#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000 ++/* VLAN info */ ++#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000 + #define IGB_TX_FLAGS_VLAN_SHIFT 16 + ++/* The largest size we can write to the descriptor is 65535. In order to ++ * maintain a power of two alignment we have to limit ourselves to 32K. ++ */ ++#define IGB_MAX_TXD_PWR 15 ++#define IGB_MAX_DATA_PER_TXD (1 << IGB_MAX_TXD_PWR) ++ ++/* Tx Descriptors needed, worst case */ ++#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGB_MAX_DATA_PER_TXD) ++#define DESC_NEEDED (MAX_SKB_FRAGS + 4) ++ + /* wrapper around a pointer to a socket buffer, +- * so a DMA handle can be stored along with the buffer */ ++ * so a DMA handle can be stored along with the buffer ++ */ + struct igb_tx_buffer { + union e1000_adv_tx_desc *next_to_watch; + unsigned long time_stamp; +@@ -153,17 +190,15 @@ struct igb_tx_buffer { + unsigned int bytecount; + u16 gso_segs; + __be16 protocol; +- dma_addr_t dma; +- u32 length; ++ DEFINE_DMA_UNMAP_ADDR(dma); ++ DEFINE_DMA_UNMAP_LEN(len); + u32 tx_flags; + }; + + struct igb_rx_buffer { +- struct sk_buff *skb; + dma_addr_t dma; + struct page *page; +- dma_addr_t page_dma; +- u32 page_offset; ++ unsigned int page_offset; + }; + + struct igb_tx_queue_stats { +@@ -190,23 +225,6 @@ struct igb_ring_container { + u8 itr; /* current ITR setting for ring */ + }; + +-struct igb_q_vector { +- struct igb_adapter *adapter; /* backlink */ +- int cpu; /* CPU for DCA */ +- u32 eims_value; /* EIMS mask value */ +- +- struct igb_ring_container rx, tx; +- +- struct napi_struct napi; +- int numa_node; +- +- u16 itr_val; +- u8 set_itr; +- void __iomem *itr_register; +- +- char name[IFNAMSIZ + 9]; +-}; +- + struct igb_ring { + struct igb_q_vector *q_vector; /* backlink to q_vector */ + struct net_device *netdev; /* back pointer to net_device */ +@@ -215,18 +233,21 @@ struct igb_ring { + struct igb_tx_buffer *tx_buffer_info; + struct igb_rx_buffer *rx_buffer_info; + }; ++ unsigned long last_rx_timestamp; + void *desc; /* descriptor ring memory */ + unsigned long flags; /* ring specific flags */ + void __iomem *tail; /* pointer to ring tail register */ ++ dma_addr_t dma; /* phys address of the ring */ ++ unsigned int size; /* length of desc. ring in bytes */ + + u16 count; /* number of desc. in the ring */ + u8 queue_index; /* logical index of the ring*/ + u8 reg_idx; /* physical index of the ring */ +- u32 size; /* length of desc. ring in bytes */ + + /* everything past this point are written often */ +- u16 next_to_clean ____cacheline_aligned_in_smp; ++ u16 next_to_clean; + u16 next_to_use; ++ u16 next_to_alloc; + + union { + /* TX */ +@@ -237,13 +258,30 @@ struct igb_ring { + }; + /* RX */ + struct { ++ struct sk_buff *skb; + struct igb_rx_queue_stats rx_stats; + struct u64_stats_sync rx_syncp; + }; + }; +- /* Items past this point are only used during ring alloc / free */ +- dma_addr_t dma; /* phys address of the ring */ +- int numa_node; /* node to alloc ring memory on */ ++} ____cacheline_internodealigned_in_smp; ++ ++struct igb_q_vector { ++ struct igb_adapter *adapter; /* backlink */ ++ int cpu; /* CPU for DCA */ ++ u32 eims_value; /* EIMS mask value */ ++ ++ u16 itr_val; ++ u8 set_itr; ++ void __iomem *itr_register; ++ ++ struct igb_ring_container rx, tx; ++ ++ struct napi_struct napi; ++ struct rcu_head rcu; /* to avoid race with update stats on free */ ++ char name[IFNAMSIZ + 9]; ++ ++ /* for dynamic allocation of rings associated with this q_vector */ ++ struct igb_ring ring[0] ____cacheline_internodealigned_in_smp; + }; + + enum e1000_ring_flags_t { +@@ -255,11 +293,11 @@ enum e1000_ring_flags_t { + + #define IGB_TXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS) + +-#define IGB_RX_DESC(R, i) \ ++#define IGB_RX_DESC(R, i) \ + (&(((union e1000_adv_rx_desc *)((R)->desc))[i])) +-#define IGB_TX_DESC(R, i) \ ++#define IGB_TX_DESC(R, i) \ + (&(((union e1000_adv_tx_desc *)((R)->desc))[i])) +-#define IGB_TX_CTXTDESC(R, i) \ ++#define IGB_TX_CTXTDESC(R, i) \ + (&(((struct e1000_adv_tx_context_desc *)((R)->desc))[i])) + + /* igb_test_staterr - tests bits within Rx descriptor status and error fields */ +@@ -278,6 +316,29 @@ static inline int igb_desc_unused(struct igb_ring *ring) + return ring->count + ring->next_to_clean - ring->next_to_use - 1; + } + ++#ifdef CONFIG_IGB_HWMON ++ ++#define IGB_HWMON_TYPE_LOC 0 ++#define IGB_HWMON_TYPE_TEMP 1 ++#define IGB_HWMON_TYPE_CAUTION 2 ++#define IGB_HWMON_TYPE_MAX 3 ++ ++struct hwmon_attr { ++ struct device_attribute dev_attr; ++ struct e1000_hw *hw; ++ struct e1000_thermal_diode_data *sensor; ++ char name[12]; ++ }; ++ ++struct hwmon_buff { ++ struct device *device; ++ struct hwmon_attr *hwmon_list; ++ unsigned int n_hwmon; ++ }; ++#endif ++ ++#define IGB_RETA_SIZE 128 ++ + /* board specific private data structure */ + struct igb_adapter { + unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; +@@ -328,10 +389,6 @@ struct igb_adapter { + + /* OS defined structs */ + struct pci_dev *pdev; +- struct cyclecounter cycles; +- struct timecounter clock; +- struct timecompare compare; +- struct hwtstamp_config hwtstamp_config; + + spinlock_t stats64_lock; + struct rtnl_link_stats64 stats64; +@@ -353,8 +410,6 @@ struct igb_adapter { + u32 eims_other; + + /* to not mess up cache alignment, always add to the bottom */ +- u32 eeprom_wol; +- + u16 tx_ring_count; + u16 rx_ring_count; + unsigned int vfs_allocated_count; +@@ -362,24 +417,55 @@ struct igb_adapter { + int vf_rate_link_speed; + u32 rss_queues; + u32 wvbr; +- int node; + u32 *shadow_vfta; ++ ++#ifdef CONFIG_IGB_PTP ++ struct ptp_clock *ptp_clock; ++ struct ptp_clock_info ptp_caps; ++ struct delayed_work ptp_overflow_work; ++ struct work_struct ptp_tx_work; ++ struct sk_buff *ptp_tx_skb; ++ unsigned long ptp_tx_start; ++ unsigned long last_rx_ptp_check; ++ spinlock_t tmreg_lock; ++ struct cyclecounter cc; ++ struct timecounter tc; ++ u32 tx_hwtstamp_timeouts; ++ u32 rx_hwtstamp_cleared; ++#endif /* CONFIG_IGB_PTP */ ++ ++ char fw_version[32]; ++#ifdef CONFIG_IGB_HWMON ++ struct hwmon_buff igb_hwmon_buff; ++ bool ets; ++#endif ++ struct i2c_algo_bit_data i2c_algo; ++ struct i2c_adapter i2c_adap; ++ struct i2c_client *i2c_client; ++ u32 rss_indir_tbl_init; ++ u8 rss_indir_tbl[IGB_RETA_SIZE]; ++ ++ unsigned long link_check_timeout; + }; + +-#define IGB_FLAG_HAS_MSI (1 << 0) +-#define IGB_FLAG_DCA_ENABLED (1 << 1) +-#define IGB_FLAG_QUAD_PORT_A (1 << 2) +-#define IGB_FLAG_QUEUE_PAIRS (1 << 3) +-#define IGB_FLAG_DMAC (1 << 4) ++#define IGB_FLAG_HAS_MSI (1 << 0) ++#define IGB_FLAG_DCA_ENABLED (1 << 1) ++#define IGB_FLAG_QUAD_PORT_A (1 << 2) ++#define IGB_FLAG_QUEUE_PAIRS (1 << 3) ++#define IGB_FLAG_DMAC (1 << 4) ++#define IGB_FLAG_PTP (1 << 5) ++#define IGB_FLAG_RSS_FIELD_IPV4_UDP (1 << 6) ++#define IGB_FLAG_RSS_FIELD_IPV6_UDP (1 << 7) ++#define IGB_FLAG_WOL_SUPPORTED (1 << 8) ++#define IGB_FLAG_NEED_LINK_UPDATE (1 << 9) + + /* DMA Coalescing defines */ +-#define IGB_MIN_TXPBSIZE 20408 +-#define IGB_TX_BUF_4096 4096 +-#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coal Flush */ ++#define IGB_MIN_TXPBSIZE 20408 ++#define IGB_TX_BUF_4096 4096 ++#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coal Flush */ + +-#define IGB_82576_TSYNC_SHIFT 19 +-#define IGB_82580_TSYNC_SHIFT 24 +-#define IGB_TS_HDR_LEN 16 ++#define IGB_82576_TSYNC_SHIFT 19 ++#define IGB_TS_HDR_LEN 16 + enum e1000_state_t { + __IGB_TESTING, + __IGB_RESETTING, +@@ -393,28 +479,60 @@ enum igb_boards { + extern char igb_driver_name[]; + extern char igb_driver_version[]; + +-extern int igb_up(struct igb_adapter *); +-extern void igb_down(struct igb_adapter *); +-extern void igb_reinit_locked(struct igb_adapter *); +-extern void igb_reset(struct igb_adapter *); +-extern int igb_set_spd_dplx(struct igb_adapter *, u32, u8); +-extern int igb_setup_tx_resources(struct igb_ring *); +-extern int igb_setup_rx_resources(struct igb_ring *); +-extern void igb_free_tx_resources(struct igb_ring *); +-extern void igb_free_rx_resources(struct igb_ring *); +-extern void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *); +-extern void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *); +-extern void igb_setup_tctl(struct igb_adapter *); +-extern void igb_setup_rctl(struct igb_adapter *); +-extern netdev_tx_t igb_xmit_frame_ring(struct sk_buff *, struct igb_ring *); +-extern void igb_unmap_and_free_tx_resource(struct igb_ring *, +- struct igb_tx_buffer *); +-extern void igb_alloc_rx_buffers(struct igb_ring *, u16); +-extern void igb_update_stats(struct igb_adapter *, struct rtnl_link_stats64 *); +-extern bool igb_has_link(struct igb_adapter *adapter); +-extern void igb_set_ethtool_ops(struct net_device *); +-extern void igb_power_up_link(struct igb_adapter *); ++int igb_up(struct igb_adapter *); ++void igb_down(struct igb_adapter *); ++void igb_reinit_locked(struct igb_adapter *); ++void igb_reset(struct igb_adapter *); ++int igb_reinit_queues(struct igb_adapter *); ++void igb_write_rss_indir_tbl(struct igb_adapter *); ++int igb_set_spd_dplx(struct igb_adapter *, u32, u8); ++int igb_setup_tx_resources(struct igb_ring *); ++int igb_setup_rx_resources(struct igb_ring *); ++void igb_free_tx_resources(struct igb_ring *); ++void igb_free_rx_resources(struct igb_ring *); ++void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *); ++void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *); ++void igb_setup_tctl(struct igb_adapter *); ++void igb_setup_rctl(struct igb_adapter *); ++netdev_tx_t igb_xmit_frame_ring(struct sk_buff *, struct igb_ring *); ++void igb_unmap_and_free_tx_resource(struct igb_ring *, struct igb_tx_buffer *); ++void igb_alloc_rx_buffers(struct igb_ring *, u16); ++void igb_update_stats(struct igb_adapter *, struct rtnl_link_stats64 *); ++bool igb_has_link(struct igb_adapter *adapter); ++void igb_set_ethtool_ops(struct net_device *); ++void igb_power_up_link(struct igb_adapter *); ++void igb_set_fw_version(struct igb_adapter *); ++#ifdef CONFIG_IGB_PTP ++void igb_ptp_init(struct igb_adapter *adapter); ++void igb_ptp_stop(struct igb_adapter *adapter); ++void igb_ptp_reset(struct igb_adapter *adapter); ++void igb_ptp_tx_work(struct work_struct *work); ++void igb_ptp_rx_hang(struct igb_adapter *adapter); ++void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter); ++void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb); ++void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, unsigned char *va, ++ struct sk_buff *skb); ++static inline void igb_ptp_rx_hwtstamp(struct igb_ring *rx_ring, ++ union e1000_adv_rx_desc *rx_desc, ++ struct sk_buff *skb) ++{ ++ if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS) && ++ !igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) ++ igb_ptp_rx_rgtstamp(rx_ring->q_vector, skb); ++ ++ /* Update the last_rx_timestamp timer in order to enable watchdog check ++ * for error case of latched timestamp on a dropped packet. ++ */ ++ rx_ring->last_rx_timestamp = jiffies; ++} + ++int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, ++ int cmd); ++#endif /* CONFIG_IGB_PTP */ ++#ifdef CONFIG_IGB_HWMON ++void igb_sysfs_exit(struct igb_adapter *adapter); ++int igb_sysfs_init(struct igb_adapter *adapter); ++#endif + static inline s32 igb_reset_phy(struct e1000_hw *hw) + { + if (hw->phy.ops.reset) +@@ -447,4 +565,9 @@ static inline s32 igb_get_phy_info(struct e1000_hw *hw) + return 0; + } + ++static inline struct netdev_queue *txring_txq(const struct igb_ring *tx_ring) ++{ ++ return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index); ++} ++ + #endif /* _IGB_H_ */ +diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c +index 43873eb..3cad9bb 100644 +--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c ++++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -36,6 +36,8 @@ + #include + #include + #include ++#include ++#include + + #include "igb.h" + +@@ -90,6 +92,10 @@ static const struct igb_stats igb_gstrings_stats[] = { + IGB_STAT("os2bmc_tx_by_bmc", stats.b2ospc), + IGB_STAT("os2bmc_tx_by_host", stats.o2bspc), + IGB_STAT("os2bmc_rx_by_host", stats.b2ogprc), ++#ifdef CONFIG_IGB_PTP ++ IGB_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts), ++ IGB_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared), ++#endif /* CONFIG_IGB_PTP */ + }; + + #define IGB_NETDEV_STAT(_net_stat) { \ +@@ -137,8 +143,11 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + { + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; ++ struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; ++ struct e1000_sfp_flags *eth_flags = &dev_spec->eth_flags; + u32 status; + ++ status = rd32(E1000_STATUS); + if (hw->phy.media_type == e1000_media_type_copper) { + + ecmd->supported = (SUPPORTED_10baseT_Half | +@@ -147,7 +156,8 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full| + SUPPORTED_Autoneg | +- SUPPORTED_TP); ++ SUPPORTED_TP | ++ SUPPORTED_Pause); + ecmd->advertising = ADVERTISED_TP; + + if (hw->mac.autoneg == 1) { +@@ -158,43 +168,80 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + + ecmd->port = PORT_TP; + ecmd->phy_address = hw->phy.addr; ++ ecmd->transceiver = XCVR_INTERNAL; + } else { +- ecmd->supported = (SUPPORTED_1000baseT_Full | +- SUPPORTED_FIBRE | +- SUPPORTED_Autoneg); +- +- ecmd->advertising = (ADVERTISED_1000baseT_Full | +- ADVERTISED_FIBRE | +- ADVERTISED_Autoneg); ++ ecmd->supported = (SUPPORTED_FIBRE | ++ SUPPORTED_1000baseKX_Full | ++ SUPPORTED_Autoneg | ++ SUPPORTED_Pause); ++ ecmd->advertising = (ADVERTISED_FIBRE | ++ ADVERTISED_1000baseKX_Full); ++ if (hw->mac.type == e1000_i354) { ++ if ((hw->device_id == ++ E1000_DEV_ID_I354_BACKPLANE_2_5GBPS) && ++ !(status & E1000_STATUS_2P5_SKU_OVER)) { ++ ecmd->supported |= SUPPORTED_2500baseX_Full; ++ ecmd->supported &= ++ ~SUPPORTED_1000baseKX_Full; ++ ecmd->advertising |= ADVERTISED_2500baseX_Full; ++ ecmd->advertising &= ++ ~ADVERTISED_1000baseKX_Full; ++ } ++ } ++ if (eth_flags->e100_base_fx) { ++ ecmd->supported |= SUPPORTED_100baseT_Full; ++ ecmd->advertising |= ADVERTISED_100baseT_Full; ++ } ++ if (hw->mac.autoneg == 1) ++ ecmd->advertising |= ADVERTISED_Autoneg; + + ecmd->port = PORT_FIBRE; ++ ecmd->transceiver = XCVR_EXTERNAL; + } ++ if (hw->mac.autoneg != 1) ++ ecmd->advertising &= ~(ADVERTISED_Pause | ++ ADVERTISED_Asym_Pause); + +- ecmd->transceiver = XCVR_INTERNAL; +- +- status = rd32(E1000_STATUS); +- ++ switch (hw->fc.requested_mode) { ++ case e1000_fc_full: ++ ecmd->advertising |= ADVERTISED_Pause; ++ break; ++ case e1000_fc_rx_pause: ++ ecmd->advertising |= (ADVERTISED_Pause | ++ ADVERTISED_Asym_Pause); ++ break; ++ case e1000_fc_tx_pause: ++ ecmd->advertising |= ADVERTISED_Asym_Pause; ++ break; ++ default: ++ ecmd->advertising &= ~(ADVERTISED_Pause | ++ ADVERTISED_Asym_Pause); ++ } + if (status & E1000_STATUS_LU) { +- +- if ((status & E1000_STATUS_SPEED_1000) || +- hw->phy.media_type != e1000_media_type_copper) +- ethtool_cmd_speed_set(ecmd, SPEED_1000); +- else if (status & E1000_STATUS_SPEED_100) +- ethtool_cmd_speed_set(ecmd, SPEED_100); +- else +- ethtool_cmd_speed_set(ecmd, SPEED_10); +- ++ if ((status & E1000_STATUS_2P5_SKU) && ++ !(status & E1000_STATUS_2P5_SKU_OVER)) { ++ ecmd->speed = SPEED_2500; ++ } else if (status & E1000_STATUS_SPEED_1000) { ++ ecmd->speed = SPEED_1000; ++ } else if (status & E1000_STATUS_SPEED_100) { ++ ecmd->speed = SPEED_100; ++ } else { ++ ecmd->speed = SPEED_10; ++ } + if ((status & E1000_STATUS_FD) || + hw->phy.media_type != e1000_media_type_copper) + ecmd->duplex = DUPLEX_FULL; + else + ecmd->duplex = DUPLEX_HALF; + } else { +- ethtool_cmd_speed_set(ecmd, -1); ++ ecmd->speed = -1; + ecmd->duplex = -1; + } +- +- ecmd->autoneg = hw->mac.autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; ++ if ((hw->phy.media_type == e1000_media_type_fiber) || ++ hw->mac.autoneg) ++ ecmd->autoneg = AUTONEG_ENABLE; ++ else ++ ecmd->autoneg = AUTONEG_DISABLE; + return 0; + } + +@@ -204,10 +251,11 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + struct e1000_hw *hw = &adapter->hw; + + /* When SoL/IDER sessions are active, autoneg/speed/duplex +- * cannot be changed */ ++ * cannot be changed ++ */ + if (igb_check_reset_block(hw)) { +- dev_err(&adapter->pdev->dev, "Cannot change link " +- "characteristics when SoL/IDER is active.\n"); ++ dev_err(&adapter->pdev->dev, ++ "Cannot change link characteristics when SoL/IDER is active.\n"); + return -EINVAL; + } + +@@ -216,9 +264,31 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + + if (ecmd->autoneg == AUTONEG_ENABLE) { + hw->mac.autoneg = 1; +- hw->phy.autoneg_advertised = ecmd->advertising | +- ADVERTISED_TP | +- ADVERTISED_Autoneg; ++ if (hw->phy.media_type == e1000_media_type_fiber) { ++ hw->phy.autoneg_advertised = ecmd->advertising | ++ ADVERTISED_FIBRE | ++ ADVERTISED_Autoneg; ++ switch (adapter->link_speed) { ++ case SPEED_2500: ++ hw->phy.autoneg_advertised = ++ ADVERTISED_2500baseX_Full; ++ break; ++ case SPEED_1000: ++ hw->phy.autoneg_advertised = ++ ADVERTISED_1000baseT_Full; ++ break; ++ case SPEED_100: ++ hw->phy.autoneg_advertised = ++ ADVERTISED_100baseT_Full; ++ break; ++ default: ++ break; ++ } ++ } else { ++ hw->phy.autoneg_advertised = ecmd->advertising | ++ ADVERTISED_TP | ++ ADVERTISED_Autoneg; ++ } + ecmd->advertising = hw->phy.autoneg_advertised; + if (adapter->fc_autoneg) + hw->fc.requested_mode = e1000_fc_default; +@@ -246,8 +316,7 @@ static u32 igb_get_link(struct net_device *netdev) + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_mac_info *mac = &adapter->hw.mac; + +- /* +- * If the link is not reported up to netdev, interrupts are disabled, ++ /* If the link is not reported up to netdev, interrupts are disabled, + * and so the physical link state may have changed since we last + * looked. Set get_link_status to make sure that the true link + * state is interrogated, rather than pulling a cached and possibly +@@ -285,6 +354,10 @@ static int igb_set_pauseparam(struct net_device *netdev, + struct e1000_hw *hw = &adapter->hw; + int retval = 0; + ++ /* 100basefx does not support setting link flow control */ ++ if (hw->dev_spec._82575.eth_flags.e100_base_fx) ++ return -EINVAL; ++ + adapter->fc_autoneg = pause->autoneg; + + while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) +@@ -332,7 +405,7 @@ static void igb_set_msglevel(struct net_device *netdev, u32 data) + + static int igb_get_regs_len(struct net_device *netdev) + { +-#define IGB_REGS_LEN 551 ++#define IGB_REGS_LEN 739 + return IGB_REGS_LEN * sizeof(u32); + } + +@@ -367,7 +440,8 @@ static void igb_get_regs(struct net_device *netdev, + + /* Interrupt */ + /* Reading EICS for EICR because they read the +- * same but EICS does not clear on read */ ++ * same but EICS does not clear on read ++ */ + regs_buff[13] = rd32(E1000_EICS); + regs_buff[14] = rd32(E1000_EICS); + regs_buff[15] = rd32(E1000_EIMS); +@@ -375,7 +449,8 @@ static void igb_get_regs(struct net_device *netdev, + regs_buff[17] = rd32(E1000_EIAC); + regs_buff[18] = rd32(E1000_EIAM); + /* Reading ICS for ICR because they read the +- * same but ICS does not clear on read */ ++ * same but ICS does not clear on read ++ */ + regs_buff[19] = rd32(E1000_ICS); + regs_buff[20] = rd32(E1000_ICS); + regs_buff[21] = rd32(E1000_IMS); +@@ -549,10 +624,49 @@ static void igb_get_regs(struct net_device *netdev, + regs_buff[548] = rd32(E1000_TDFT); + regs_buff[549] = rd32(E1000_TDFHS); + regs_buff[550] = rd32(E1000_TDFPC); +- regs_buff[551] = adapter->stats.o2bgptc; +- regs_buff[552] = adapter->stats.b2ospc; +- regs_buff[553] = adapter->stats.o2bspc; +- regs_buff[554] = adapter->stats.b2ogprc; ++ ++ if (hw->mac.type > e1000_82580) { ++ regs_buff[551] = adapter->stats.o2bgptc; ++ regs_buff[552] = adapter->stats.b2ospc; ++ regs_buff[553] = adapter->stats.o2bspc; ++ regs_buff[554] = adapter->stats.b2ogprc; ++ } ++ ++ if (hw->mac.type != e1000_82576) ++ return; ++ for (i = 0; i < 12; i++) ++ regs_buff[555 + i] = rd32(E1000_SRRCTL(i + 4)); ++ for (i = 0; i < 4; i++) ++ regs_buff[567 + i] = rd32(E1000_PSRTYPE(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[571 + i] = rd32(E1000_RDBAL(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[583 + i] = rd32(E1000_RDBAH(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[595 + i] = rd32(E1000_RDLEN(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[607 + i] = rd32(E1000_RDH(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[619 + i] = rd32(E1000_RDT(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[631 + i] = rd32(E1000_RXDCTL(i + 4)); ++ ++ for (i = 0; i < 12; i++) ++ regs_buff[643 + i] = rd32(E1000_TDBAL(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[655 + i] = rd32(E1000_TDBAH(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[667 + i] = rd32(E1000_TDLEN(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[679 + i] = rd32(E1000_TDH(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[691 + i] = rd32(E1000_TDT(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[703 + i] = rd32(E1000_TXDCTL(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[715 + i] = rd32(E1000_TDWBAL(i + 4)); ++ for (i = 0; i < 12; i++) ++ regs_buff[727 + i] = rd32(E1000_TDWBAH(i + 4)); + } + + static int igb_get_eeprom_len(struct net_device *netdev) +@@ -586,12 +700,12 @@ static int igb_get_eeprom(struct net_device *netdev, + + if (hw->nvm.type == e1000_nvm_eeprom_spi) + ret_val = hw->nvm.ops.read(hw, first_word, +- last_word - first_word + 1, +- eeprom_buff); ++ last_word - first_word + 1, ++ eeprom_buff); + else { + for (i = 0; i < last_word - first_word + 1; i++) { + ret_val = hw->nvm.ops.read(hw, first_word + i, 1, +- &eeprom_buff[i]); ++ &eeprom_buff[i]); + if (ret_val) + break; + } +@@ -621,6 +735,11 @@ static int igb_set_eeprom(struct net_device *netdev, + if (eeprom->len == 0) + return -EOPNOTSUPP; + ++ if ((hw->mac.type >= e1000_i210) && ++ !igb_get_flash_presence_i210(hw)) { ++ return -EOPNOTSUPP; ++ } ++ + if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) + return -EFAULT; + +@@ -635,15 +754,17 @@ static int igb_set_eeprom(struct net_device *netdev, + ptr = (void *)eeprom_buff; + + if (eeprom->offset & 1) { +- /* need read/modify/write of first changed EEPROM word */ +- /* only the second byte of the word is being modified */ ++ /* need read/modify/write of first changed EEPROM word ++ * only the second byte of the word is being modified ++ */ + ret_val = hw->nvm.ops.read(hw, first_word, 1, + &eeprom_buff[0]); + ptr++; + } + if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { +- /* need read/modify/write of last changed EEPROM word */ +- /* only the first byte of the word is being modified */ ++ /* need read/modify/write of last changed EEPROM word ++ * only the first byte of the word is being modified ++ */ + ret_val = hw->nvm.ops.read(hw, last_word, 1, + &eeprom_buff[last_word - first_word]); + } +@@ -658,13 +779,13 @@ static int igb_set_eeprom(struct net_device *netdev, + eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); + + ret_val = hw->nvm.ops.write(hw, first_word, +- last_word - first_word + 1, eeprom_buff); ++ last_word - first_word + 1, eeprom_buff); + +- /* Update the checksum over the first part of the EEPROM if needed +- * and flush shadow RAM for 82573 controllers */ +- if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG))) ++ /* Update the checksum if nvm write succeeded */ ++ if (ret_val == 0) + hw->nvm.ops.update(hw); + ++ igb_set_fw_version(adapter); + kfree(eeprom_buff); + return ret_val; + } +@@ -673,25 +794,17 @@ static void igb_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) + { + struct igb_adapter *adapter = netdev_priv(netdev); +- char firmware_version[32]; +- u16 eeprom_data; + +- strncpy(drvinfo->driver, igb_driver_name, sizeof(drvinfo->driver) - 1); +- strncpy(drvinfo->version, igb_driver_version, +- sizeof(drvinfo->version) - 1); ++ strlcpy(drvinfo->driver, igb_driver_name, sizeof(drvinfo->driver)); ++ strlcpy(drvinfo->version, igb_driver_version, sizeof(drvinfo->version)); + + /* EEPROM image version # is reported as firmware version # for +- * 82575 controllers */ +- adapter->hw.nvm.ops.read(&adapter->hw, 5, 1, &eeprom_data); +- sprintf(firmware_version, "%d.%d-%d", +- (eeprom_data & 0xF000) >> 12, +- (eeprom_data & 0x0FF0) >> 4, +- eeprom_data & 0x000F); +- +- strncpy(drvinfo->fw_version, firmware_version, +- sizeof(drvinfo->fw_version) - 1); +- strncpy(drvinfo->bus_info, pci_name(adapter->pdev), +- sizeof(drvinfo->bus_info) - 1); ++ * 82575 controllers ++ */ ++ strlcpy(drvinfo->fw_version, adapter->fw_version, ++ sizeof(drvinfo->fw_version)); ++ strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), ++ sizeof(drvinfo->bus_info)); + drvinfo->n_stats = IGB_STATS_LEN; + drvinfo->testinfo_len = IGB_TEST_LEN; + drvinfo->regdump_len = igb_get_regs_len(netdev); +@@ -748,9 +861,11 @@ static int igb_set_ringparam(struct net_device *netdev, + } + + if (adapter->num_tx_queues > adapter->num_rx_queues) +- temp_ring = vmalloc(adapter->num_tx_queues * sizeof(struct igb_ring)); ++ temp_ring = vmalloc(adapter->num_tx_queues * ++ sizeof(struct igb_ring)); + else +- temp_ring = vmalloc(adapter->num_rx_queues * sizeof(struct igb_ring)); ++ temp_ring = vmalloc(adapter->num_rx_queues * ++ sizeof(struct igb_ring)); + + if (!temp_ring) { + err = -ENOMEM; +@@ -759,10 +874,9 @@ static int igb_set_ringparam(struct net_device *netdev, + + igb_down(adapter); + +- /* +- * We can't just free everything and then setup again, ++ /* We can't just free everything and then setup again, + * because the ISRs in MSI-X mode get passed pointers +- * to the tx and rx ring structs. ++ * to the Tx and Rx ring structs. + */ + if (new_tx_count != adapter->tx_ring_count) { + for (i = 0; i < adapter->num_tx_queues; i++) { +@@ -851,6 +965,36 @@ struct igb_reg_test { + #define TABLE64_TEST_LO 5 + #define TABLE64_TEST_HI 6 + ++/* i210 reg test */ ++static struct igb_reg_test reg_test_i210[] = { ++ { E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, ++ { E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, ++ { E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, ++ { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, ++ { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, ++ { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, ++ /* RDH is read-only for i210, only test RDT. */ ++ { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, ++ { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 }, ++ { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, ++ { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, ++ { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, ++ { E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, ++ { E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, ++ { E1000_TDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, ++ { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, ++ { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB }, ++ { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF }, ++ { E1000_TCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, ++ { E1000_RA, 0, 16, TABLE64_TEST_LO, ++ 0xFFFFFFFF, 0xFFFFFFFF }, ++ { E1000_RA, 0, 16, TABLE64_TEST_HI, ++ 0x900FFFFF, 0xFFFFFFFF }, ++ { E1000_MTA, 0, 128, TABLE32_TEST, ++ 0xFFFFFFFF, 0xFFFFFFFF }, ++ { 0, 0, 0, 0, 0 } ++}; ++ + /* i350 reg test */ + static struct igb_reg_test reg_test_i350[] = { + { E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, +@@ -1020,8 +1164,8 @@ static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data, + wr32(reg, (_test[pat] & write)); + val = rd32(reg) & mask; + if (val != (_test[pat] & write & mask)) { +- dev_err(&adapter->pdev->dev, "pattern test reg %04X " +- "failed: got 0x%08X expected 0x%08X\n", ++ dev_err(&adapter->pdev->dev, ++ "pattern test reg %04X failed: got 0x%08X expected 0x%08X\n", + reg, val, (_test[pat] & write & mask)); + *data = reg; + return 1; +@@ -1039,8 +1183,8 @@ static bool reg_set_and_check(struct igb_adapter *adapter, u64 *data, + wr32(reg, write & mask); + val = rd32(reg); + if ((write & mask) != (val & mask)) { +- dev_err(&adapter->pdev->dev, "set/check reg %04X test failed:" +- " got 0x%08X expected 0x%08X\n", reg, ++ dev_err(&adapter->pdev->dev, ++ "set/check reg %04X test failed: got 0x%08X expected 0x%08X\n", reg, + (val & mask), (write & mask)); + *data = reg; + return 1; +@@ -1070,9 +1214,15 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data) + + switch (adapter->hw.mac.type) { + case e1000_i350: ++ case e1000_i354: + test = reg_test_i350; + toggle = 0x7FEFF3FF; + break; ++ case e1000_i210: ++ case e1000_i211: ++ test = reg_test_i210; ++ toggle = 0x7FEFF3FF; ++ break; + case e1000_82580: + test = reg_test_82580; + toggle = 0x7FEFF3FF; +@@ -1097,8 +1247,9 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data) + wr32(E1000_STATUS, toggle); + after = rd32(E1000_STATUS) & toggle; + if (value != after) { +- dev_err(&adapter->pdev->dev, "failed STATUS register test " +- "got: 0x%08X expected: 0x%08X\n", after, value); ++ dev_err(&adapter->pdev->dev, ++ "failed STATUS register test got: 0x%08X expected: 0x%08X\n", ++ after, value); + *data = 1; + return 1; + } +@@ -1154,24 +1305,25 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data) + + static int igb_eeprom_test(struct igb_adapter *adapter, u64 *data) + { +- u16 temp; +- u16 checksum = 0; +- u16 i; ++ struct e1000_hw *hw = &adapter->hw; + + *data = 0; +- /* Read and add up the contents of the EEPROM */ +- for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { +- if ((adapter->hw.nvm.ops.read(&adapter->hw, i, 1, &temp)) < 0) { +- *data = 1; +- break; ++ ++ /* Validate eeprom on all parts but flashless */ ++ switch (hw->mac.type) { ++ case e1000_i210: ++ case e1000_i211: ++ if (igb_get_flash_presence_i210(hw)) { ++ if (adapter->hw.nvm.ops.validate(&adapter->hw) < 0) ++ *data = 2; + } +- checksum += temp; ++ break; ++ default: ++ if (adapter->hw.nvm.ops.validate(&adapter->hw) < 0) ++ *data = 2; ++ break; + } + +- /* If Checksum is not Correct return error else test passed */ +- if ((checksum != (u16) NVM_SUM) && !(*data)) +- *data = 2; +- + return *data; + } + +@@ -1236,6 +1388,9 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) + ics_mask = 0x77DCFED5; + break; + case e1000_i350: ++ case e1000_i354: ++ case e1000_i210: ++ case e1000_i211: + ics_mask = 0x77DCFED5; + break; + default: +@@ -1406,18 +1561,25 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter) + hw->mac.autoneg = false; + + if (hw->phy.type == e1000_phy_m88) { +- /* Auto-MDI/MDIX Off */ +- igb_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); +- /* reset to update Auto-MDI/MDIX */ +- igb_write_phy_reg(hw, PHY_CONTROL, 0x9140); +- /* autoneg off */ +- igb_write_phy_reg(hw, PHY_CONTROL, 0x8140); ++ if (hw->phy.id != I210_I_PHY_ID) { ++ /* Auto-MDI/MDIX Off */ ++ igb_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); ++ /* reset to update Auto-MDI/MDIX */ ++ igb_write_phy_reg(hw, PHY_CONTROL, 0x9140); ++ /* autoneg off */ ++ igb_write_phy_reg(hw, PHY_CONTROL, 0x8140); ++ } else { ++ /* force 1000, set loopback */ ++ igb_write_phy_reg(hw, I347AT4_PAGE_SELECT, 0); ++ igb_write_phy_reg(hw, PHY_CONTROL, 0x4140); ++ } + } else if (hw->phy.type == e1000_phy_82580) { + /* enable MII loopback */ + igb_write_phy_reg(hw, I82580_PHY_LBK_CTRL, 0x8041); + } + +- ctrl_reg = rd32(E1000_CTRL); ++ /* add small delay to avoid loopback test failure */ ++ msleep(50); + + /* force 1000, set loopback */ + igb_write_phy_reg(hw, PHY_CONTROL, 0x4140); +@@ -1442,8 +1604,7 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter) + if (hw->phy.type == e1000_phy_m88) + igb_phy_disable_receiver(adapter); + +- udelay(500); +- ++ mdelay(500); + return 0; + } + +@@ -1464,7 +1625,8 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter) + if ((hw->device_id == E1000_DEV_ID_DH89XXCC_SGMII) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_SERDES) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_BACKPLANE) || +- (hw->device_id == E1000_DEV_ID_DH89XXCC_SFP)) { ++ (hw->device_id == E1000_DEV_ID_DH89XXCC_SFP) || ++ (hw->device_id == E1000_DEV_ID_I354_SGMII)) { + + /* Enable DH89xxCC MPHY for near end loopback */ + reg = rd32(E1000_MPHY_ADDR_CTL); +@@ -1496,6 +1658,15 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter) + reg &= ~E1000_CONNSW_ENRGSRC; + wr32(E1000_CONNSW, reg); + ++ /* Unset sigdetect for SERDES loopback on ++ * 82580 and newer devices. ++ */ ++ if (hw->mac.type >= e1000_82580) { ++ reg = rd32(E1000_PCS_CFG0); ++ reg |= E1000_PCS_CFG_IGN_SD; ++ wr32(E1000_PCS_CFG0, reg); ++ } ++ + /* Set PCS register for forced speed */ + reg = rd32(E1000_PCS_LCTL); + reg &= ~E1000_PCS_LCTL_AN_ENABLE; /* Disable Autoneg*/ +@@ -1521,7 +1692,8 @@ static void igb_loopback_cleanup(struct igb_adapter *adapter) + if ((hw->device_id == E1000_DEV_ID_DH89XXCC_SGMII) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_SERDES) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_BACKPLANE) || +- (hw->device_id == E1000_DEV_ID_DH89XXCC_SFP)) { ++ (hw->device_id == E1000_DEV_ID_DH89XXCC_SFP) || ++ (hw->device_id == E1000_DEV_ID_I354_SGMII)) { + u32 reg; + + /* Disable near end loopback on DH89xxCC */ +@@ -1558,21 +1730,29 @@ static void igb_create_lbtest_frame(struct sk_buff *skb, + memset(&skb->data[frame_size + 12], 0xAF, 1); + } + +-static int igb_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size) ++static int igb_check_lbtest_frame(struct igb_rx_buffer *rx_buffer, ++ unsigned int frame_size) + { +- frame_size /= 2; +- if (*(skb->data + 3) == 0xFF) { +- if ((*(skb->data + frame_size + 10) == 0xBE) && +- (*(skb->data + frame_size + 12) == 0xAF)) { +- return 0; +- } +- } +- return 13; ++ unsigned char *data; ++ bool match = true; ++ ++ frame_size >>= 1; ++ ++ data = kmap(rx_buffer->page); ++ ++ if (data[3] != 0xFF || ++ data[frame_size + 10] != 0xBE || ++ data[frame_size + 12] != 0xAF) ++ match = false; ++ ++ kunmap(rx_buffer->page); ++ ++ return match; + } + + static int igb_clean_test_rings(struct igb_ring *rx_ring, +- struct igb_ring *tx_ring, +- unsigned int size) ++ struct igb_ring *tx_ring, ++ unsigned int size) + { + union e1000_adv_rx_desc *rx_desc; + struct igb_rx_buffer *rx_buffer_info; +@@ -1585,25 +1765,30 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring, + rx_desc = IGB_RX_DESC(rx_ring, rx_ntc); + + while (igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) { +- /* check rx buffer */ ++ /* check Rx buffer */ + rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc]; + +- /* unmap rx buffer, will be remapped by alloc_rx_buffers */ +- dma_unmap_single(rx_ring->dev, +- rx_buffer_info->dma, +- IGB_RX_HDR_LEN, +- DMA_FROM_DEVICE); +- rx_buffer_info->dma = 0; ++ /* sync Rx buffer for CPU read */ ++ dma_sync_single_for_cpu(rx_ring->dev, ++ rx_buffer_info->dma, ++ IGB_RX_BUFSZ, ++ DMA_FROM_DEVICE); + + /* verify contents of skb */ +- if (!igb_check_lbtest_frame(rx_buffer_info->skb, size)) ++ if (igb_check_lbtest_frame(rx_buffer_info, size)) + count++; + +- /* unmap buffer on tx side */ ++ /* sync Rx buffer for device write */ ++ dma_sync_single_for_device(rx_ring->dev, ++ rx_buffer_info->dma, ++ IGB_RX_BUFSZ, ++ DMA_FROM_DEVICE); ++ ++ /* unmap buffer on Tx side */ + tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc]; + igb_unmap_and_free_tx_resource(tx_ring, tx_buffer_info); + +- /* increment rx/tx next to clean counters */ ++ /* increment Rx/Tx next to clean counters */ + rx_ntc++; + if (rx_ntc == rx_ring->count) + rx_ntc = 0; +@@ -1615,6 +1800,8 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring, + rx_desc = IGB_RX_DESC(rx_ring, rx_ntc); + } + ++ netdev_tx_reset_queue(txring_txq(tx_ring)); ++ + /* re-map buffers to ring, store next to clean values */ + igb_alloc_rx_buffers(rx_ring, count); + rx_ring->next_to_clean = rx_ntc; +@@ -1642,8 +1829,7 @@ static int igb_run_loopback_test(struct igb_adapter *adapter) + igb_create_lbtest_frame(skb, size); + skb_put(skb, size); + +- /* +- * Calculate the loop count based on the largest descriptor ring ++ /* Calculate the loop count based on the largest descriptor ring + * The idea is to wrap the largest ring a number of times using 64 + * send/receive pairs during each loop + */ +@@ -1670,7 +1856,7 @@ static int igb_run_loopback_test(struct igb_adapter *adapter) + break; + } + +- /* allow 200 milliseconds for packets to go from tx to rx */ ++ /* allow 200 milliseconds for packets to go from Tx to Rx */ + msleep(200); + + good_cnt = igb_clean_test_rings(rx_ring, tx_ring, size); +@@ -1689,11 +1875,18 @@ static int igb_run_loopback_test(struct igb_adapter *adapter) + static int igb_loopback_test(struct igb_adapter *adapter, u64 *data) + { + /* PHY loopback cannot be performed if SoL/IDER +- * sessions are active */ ++ * sessions are active ++ */ + if (igb_check_reset_block(&adapter->hw)) { + dev_err(&adapter->pdev->dev, +- "Cannot do PHY loopback test " +- "when SoL/IDER is active.\n"); ++ "Cannot do PHY loopback test when SoL/IDER is active.\n"); ++ *data = 0; ++ goto out; ++ } ++ ++ if (adapter->hw.mac.type == e1000_i354) { ++ dev_info(&adapter->pdev->dev, ++ "Loopback test not supported on i354.\n"); + *data = 0; + goto out; + } +@@ -1721,7 +1914,8 @@ static int igb_link_test(struct igb_adapter *adapter, u64 *data) + hw->mac.serdes_has_link = false; + + /* On some blade server designs, link establishment +- * could take as long as 2-3 minutes */ ++ * could take as long as 2-3 minutes ++ */ + do { + hw->mac.ops.check_for_link(&adapter->hw); + if (hw->mac.serdes_has_link) +@@ -1733,7 +1927,7 @@ static int igb_link_test(struct igb_adapter *adapter, u64 *data) + } else { + hw->mac.ops.check_for_link(&adapter->hw); + if (hw->mac.autoneg) +- msleep(4000); ++ msleep(5000); + + if (!(rd32(E1000_STATUS) & E1000_STATUS_LU)) + *data = 1; +@@ -1764,7 +1958,8 @@ static void igb_diag_test(struct net_device *netdev, + igb_power_up_link(adapter); + + /* Link test performed before hardware reset so autoneg doesn't +- * interfere with test result */ ++ * interfere with test result ++ */ + if (igb_link_test(adapter, &data[4])) + eth_test->flags |= ETH_TEST_FL_FAILED; + +@@ -1824,69 +2019,19 @@ static void igb_diag_test(struct net_device *netdev, + msleep_interruptible(4 * 1000); + } + +-static int igb_wol_exclusion(struct igb_adapter *adapter, +- struct ethtool_wolinfo *wol) +-{ +- struct e1000_hw *hw = &adapter->hw; +- int retval = 1; /* fail by default */ +- +- switch (hw->device_id) { +- case E1000_DEV_ID_82575GB_QUAD_COPPER: +- /* WoL not supported */ +- wol->supported = 0; +- break; +- case E1000_DEV_ID_82575EB_FIBER_SERDES: +- case E1000_DEV_ID_82576_FIBER: +- case E1000_DEV_ID_82576_SERDES: +- /* Wake events not supported on port B */ +- if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1) { +- wol->supported = 0; +- break; +- } +- /* return success for non excluded adapter ports */ +- retval = 0; +- break; +- case E1000_DEV_ID_82576_QUAD_COPPER: +- case E1000_DEV_ID_82576_QUAD_COPPER_ET2: +- /* quad port adapters only support WoL on port A */ +- if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) { +- wol->supported = 0; +- break; +- } +- /* return success for non excluded adapter ports */ +- retval = 0; +- break; +- default: +- /* dual port cards only support WoL on port A from now on +- * unless it was enabled in the eeprom for port B +- * so exclude FUNC_1 ports from having WoL enabled */ +- if ((rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) && +- !adapter->eeprom_wol) { +- wol->supported = 0; +- break; +- } +- +- retval = 0; +- } +- +- return retval; +-} +- + static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) + { + struct igb_adapter *adapter = netdev_priv(netdev); + +- wol->supported = WAKE_UCAST | WAKE_MCAST | +- WAKE_BCAST | WAKE_MAGIC | +- WAKE_PHY; + wol->wolopts = 0; + +- /* this function will set ->supported = 0 and return 1 if wol is not +- * supported by this hardware */ +- if (igb_wol_exclusion(adapter, wol) || +- !device_can_wakeup(&adapter->pdev->dev)) ++ if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED)) + return; + ++ wol->supported = WAKE_UCAST | WAKE_MCAST | ++ WAKE_BCAST | WAKE_MAGIC | ++ WAKE_PHY; ++ + /* apply any specific unsupported masks here */ + switch (adapter->hw.device_id) { + default: +@@ -1912,8 +2057,7 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) + if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)) + return -EOPNOTSUPP; + +- if (igb_wol_exclusion(adapter, wol) || +- !device_can_wakeup(&adapter->pdev->dev)) ++ if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED)) + return wol->wolopts ? -EOPNOTSUPP : 0; + + /* these settings will always override what we currently have */ +@@ -2157,37 +2301,413 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data) + sprintf(p, "rx_queue_%u_alloc_failed", i); + p += ETH_GSTRING_LEN; + } +-/* BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */ ++ /* BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */ ++ break; ++ } ++} ++ ++static int igb_get_rss_hash_opts(struct igb_adapter *adapter, ++ struct ethtool_rxnfc *cmd) ++{ ++ cmd->data = 0; ++ ++ /* Report default options for RSS on igb */ ++ switch (cmd->flow_type) { ++ case TCP_V4_FLOW: ++ cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ case UDP_V4_FLOW: ++ if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP) ++ cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ case SCTP_V4_FLOW: ++ case AH_ESP_V4_FLOW: ++ case AH_V4_FLOW: ++ case ESP_V4_FLOW: ++ case IPV4_FLOW: ++ cmd->data |= RXH_IP_SRC | RXH_IP_DST; ++ break; ++ case TCP_V6_FLOW: ++ cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ case UDP_V6_FLOW: ++ if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP) ++ cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ case SCTP_V6_FLOW: ++ case AH_ESP_V6_FLOW: ++ case AH_V6_FLOW: ++ case ESP_V6_FLOW: ++ case IPV6_FLOW: ++ cmd->data |= RXH_IP_SRC | RXH_IP_DST; + break; ++ default: ++ return -EINVAL; + } ++ ++ return 0; ++} ++ ++static int igb_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, ++ u32 *rule_locs) ++{ ++ struct igb_adapter *adapter = netdev_priv(dev); ++ int ret = -EOPNOTSUPP; ++ ++ switch (cmd->cmd) { ++ case ETHTOOL_GRXRINGS: ++ cmd->data = adapter->num_rx_queues; ++ ret = 0; ++ break; ++ case ETHTOOL_GRXFH: ++ ret = igb_get_rss_hash_opts(adapter, cmd); ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++#define UDP_RSS_FLAGS (IGB_FLAG_RSS_FIELD_IPV4_UDP | \ ++ IGB_FLAG_RSS_FIELD_IPV6_UDP) ++static int igb_set_rss_hash_opt(struct igb_adapter *adapter, ++ struct ethtool_rxnfc *nfc) ++{ ++ u32 flags = adapter->flags; ++ ++ /* RSS does not support anything other than hashing ++ * to queues on src and dst IPs and ports ++ */ ++ if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | ++ RXH_L4_B_0_1 | RXH_L4_B_2_3)) ++ return -EINVAL; ++ ++ switch (nfc->flow_type) { ++ case TCP_V4_FLOW: ++ case TCP_V6_FLOW: ++ if (!(nfc->data & RXH_IP_SRC) || ++ !(nfc->data & RXH_IP_DST) || ++ !(nfc->data & RXH_L4_B_0_1) || ++ !(nfc->data & RXH_L4_B_2_3)) ++ return -EINVAL; ++ break; ++ case UDP_V4_FLOW: ++ if (!(nfc->data & RXH_IP_SRC) || ++ !(nfc->data & RXH_IP_DST)) ++ return -EINVAL; ++ switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { ++ case 0: ++ flags &= ~IGB_FLAG_RSS_FIELD_IPV4_UDP; ++ break; ++ case (RXH_L4_B_0_1 | RXH_L4_B_2_3): ++ flags |= IGB_FLAG_RSS_FIELD_IPV4_UDP; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case UDP_V6_FLOW: ++ if (!(nfc->data & RXH_IP_SRC) || ++ !(nfc->data & RXH_IP_DST)) ++ return -EINVAL; ++ switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { ++ case 0: ++ flags &= ~IGB_FLAG_RSS_FIELD_IPV6_UDP; ++ break; ++ case (RXH_L4_B_0_1 | RXH_L4_B_2_3): ++ flags |= IGB_FLAG_RSS_FIELD_IPV6_UDP; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case AH_ESP_V4_FLOW: ++ case AH_V4_FLOW: ++ case ESP_V4_FLOW: ++ case SCTP_V4_FLOW: ++ case AH_ESP_V6_FLOW: ++ case AH_V6_FLOW: ++ case ESP_V6_FLOW: ++ case SCTP_V6_FLOW: ++ if (!(nfc->data & RXH_IP_SRC) || ++ !(nfc->data & RXH_IP_DST) || ++ (nfc->data & RXH_L4_B_0_1) || ++ (nfc->data & RXH_L4_B_2_3)) ++ return -EINVAL; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* if we changed something we need to update flags */ ++ if (flags != adapter->flags) { ++ struct e1000_hw *hw = &adapter->hw; ++ u32 mrqc = rd32(E1000_MRQC); ++ ++ if ((flags & UDP_RSS_FLAGS) && ++ !(adapter->flags & UDP_RSS_FLAGS)) ++ dev_err(&adapter->pdev->dev, ++ "enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n"); ++ ++ adapter->flags = flags; ++ ++ /* Perform hash on these packet types */ ++ mrqc |= E1000_MRQC_RSS_FIELD_IPV4 | ++ E1000_MRQC_RSS_FIELD_IPV4_TCP | ++ E1000_MRQC_RSS_FIELD_IPV6 | ++ E1000_MRQC_RSS_FIELD_IPV6_TCP; ++ ++ mrqc &= ~(E1000_MRQC_RSS_FIELD_IPV4_UDP | ++ E1000_MRQC_RSS_FIELD_IPV6_UDP); ++ ++ if (flags & IGB_FLAG_RSS_FIELD_IPV4_UDP) ++ mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP; ++ ++ if (flags & IGB_FLAG_RSS_FIELD_IPV6_UDP) ++ mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP; ++ ++ wr32(E1000_MRQC, mrqc); ++ } ++ ++ return 0; ++} ++ ++static int igb_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) ++{ ++ struct igb_adapter *adapter = netdev_priv(dev); ++ int ret = -EOPNOTSUPP; ++ ++ switch (cmd->cmd) { ++ case ETHTOOL_SRXFH: ++ ret = igb_set_rss_hash_opt(adapter, cmd); ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++static int igb_ethtool_begin(struct net_device *netdev) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ pm_runtime_get_sync(&adapter->pdev->dev); ++ return 0; ++} ++ ++static void igb_ethtool_complete(struct net_device *netdev) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ pm_runtime_put(&adapter->pdev->dev); ++} ++ ++static int igb_get_rxfh_indir(struct net_device *netdev, ++ struct ethtool_rxfh_indir *indir) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ int i; ++ ++ /* Handle size query */ ++ if (indir->size == 0) { ++ indir->size = IGB_RETA_SIZE; ++ return 0; ++ } ++ ++ /* Check buffer size */ ++ if (indir->size < IGB_RETA_SIZE) ++ return -EINVAL; ++ ++ indir->size = IGB_RETA_SIZE; ++ for (i = 0; i < IGB_RETA_SIZE; i++) ++ indir->ring_index[i] = adapter->rss_indir_tbl[i]; ++ ++ return 0; ++} ++ ++void igb_write_rss_indir_tbl(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 reg = E1000_RETA(0); ++ u32 shift = 0; ++ int i = 0; ++ ++ switch (hw->mac.type) { ++ case e1000_82575: ++ shift = 6; ++ break; ++ case e1000_82576: ++ /* 82576 supports 2 RSS queues for SR-IOV */ ++ if (adapter->vfs_allocated_count) ++ shift = 3; ++ break; ++ default: ++ break; ++ } ++ ++ while (i < IGB_RETA_SIZE) { ++ u32 val = 0; ++ int j; ++ ++ for (j = 3; j >= 0; j--) { ++ val <<= 8; ++ val |= adapter->rss_indir_tbl[i + j]; ++ } ++ ++ wr32(reg, val << shift); ++ reg += 4; ++ i += 4; ++ } ++} ++ ++static int igb_set_rxfh_indir(struct net_device *netdev, ++ const struct ethtool_rxfh_indir *indir) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ int i; ++ u32 num_queues; ++ ++ num_queues = adapter->rss_queues; ++ ++ switch (hw->mac.type) { ++ case e1000_82576: ++ /* 82576 supports 2 RSS queues for SR-IOV */ ++ if (adapter->vfs_allocated_count) ++ num_queues = 2; ++ break; ++ default: ++ break; ++ } ++ ++ /* Verify user input. */ ++ if (indir->size != IGB_RETA_SIZE) ++ return -EINVAL; ++ for (i = 0; i < IGB_RETA_SIZE; i++) ++ if (indir->ring_index[i] >= num_queues) ++ return -EINVAL; ++ ++ ++ for (i = 0; i < IGB_RETA_SIZE; i++) ++ adapter->rss_indir_tbl[i] = indir->ring_index[i]; ++ ++ igb_write_rss_indir_tbl(adapter); ++ ++ return 0; ++} ++ ++static unsigned int igb_max_channels(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ unsigned int max_combined = 0; ++ ++ switch (hw->mac.type) { ++ case e1000_i211: ++ max_combined = IGB_MAX_RX_QUEUES_I211; ++ break; ++ case e1000_82575: ++ case e1000_i210: ++ max_combined = IGB_MAX_RX_QUEUES_82575; ++ break; ++ case e1000_i350: ++ if (!!adapter->vfs_allocated_count) { ++ max_combined = 1; ++ break; ++ } ++ /* fall through */ ++ case e1000_82576: ++ if (!!adapter->vfs_allocated_count) { ++ max_combined = 2; ++ break; ++ } ++ /* fall through */ ++ case e1000_82580: ++ case e1000_i354: ++ default: ++ max_combined = IGB_MAX_RX_QUEUES; ++ break; ++ } ++ ++ return max_combined; ++} ++ ++static void igb_get_channels(struct net_device *netdev, ++ struct ethtool_channels *ch) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ ++ /* Report maximum channels */ ++ ch->max_combined = igb_max_channels(adapter); ++ ++ /* Report info for other vector */ ++ if (adapter->msix_entries) { ++ ch->max_other = NON_Q_VECTORS; ++ ch->other_count = NON_Q_VECTORS; ++ } ++ ++ ch->combined_count = adapter->rss_queues; ++} ++ ++static int igb_set_channels(struct net_device *netdev, ++ struct ethtool_channels *ch) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ unsigned int count = ch->combined_count; ++ ++ /* Verify they are not requesting separate vectors */ ++ if (!count || ch->rx_count || ch->tx_count) ++ return -EINVAL; ++ ++ /* Verify other_count is valid and has not been changed */ ++ if (ch->other_count != NON_Q_VECTORS) ++ return -EINVAL; ++ ++ /* Verify the number of channels doesn't exceed hw limits */ ++ if (count > igb_max_channels(adapter)) ++ return -EINVAL; ++ ++ if (count != adapter->rss_queues) { ++ adapter->rss_queues = count; ++ ++ /* Hardware has to reinitialize queues and interrupts to ++ * match the new configuration. ++ */ ++ return igb_reinit_queues(adapter); ++ } ++ ++ return 0; + } + + static const struct ethtool_ops igb_ethtool_ops = { +- .get_settings = igb_get_settings, +- .set_settings = igb_set_settings, +- .get_drvinfo = igb_get_drvinfo, +- .get_regs_len = igb_get_regs_len, +- .get_regs = igb_get_regs, +- .get_wol = igb_get_wol, +- .set_wol = igb_set_wol, +- .get_msglevel = igb_get_msglevel, +- .set_msglevel = igb_set_msglevel, +- .nway_reset = igb_nway_reset, +- .get_link = igb_get_link, +- .get_eeprom_len = igb_get_eeprom_len, +- .get_eeprom = igb_get_eeprom, +- .set_eeprom = igb_set_eeprom, +- .get_ringparam = igb_get_ringparam, +- .set_ringparam = igb_set_ringparam, +- .get_pauseparam = igb_get_pauseparam, +- .set_pauseparam = igb_set_pauseparam, +- .self_test = igb_diag_test, +- .get_strings = igb_get_strings, +- .set_phys_id = igb_set_phys_id, +- .get_sset_count = igb_get_sset_count, +- .get_ethtool_stats = igb_get_ethtool_stats, +- .get_coalesce = igb_get_coalesce, +- .set_coalesce = igb_set_coalesce, ++ .get_settings = igb_get_settings, ++ .set_settings = igb_set_settings, ++ .get_drvinfo = igb_get_drvinfo, ++ .get_regs_len = igb_get_regs_len, ++ .get_regs = igb_get_regs, ++ .get_wol = igb_get_wol, ++ .set_wol = igb_set_wol, ++ .get_msglevel = igb_get_msglevel, ++ .set_msglevel = igb_set_msglevel, ++ .nway_reset = igb_nway_reset, ++ .get_link = igb_get_link, ++ .get_eeprom_len = igb_get_eeprom_len, ++ .get_eeprom = igb_get_eeprom, ++ .set_eeprom = igb_set_eeprom, ++ .get_ringparam = igb_get_ringparam, ++ .set_ringparam = igb_set_ringparam, ++ .get_pauseparam = igb_get_pauseparam, ++ .set_pauseparam = igb_set_pauseparam, ++ .self_test = igb_diag_test, ++ .get_strings = igb_get_strings, ++ .set_phys_id = igb_set_phys_id, ++ .get_sset_count = igb_get_sset_count, ++ .get_ethtool_stats = igb_get_ethtool_stats, ++ .get_coalesce = igb_get_coalesce, ++ .set_coalesce = igb_set_coalesce, ++ .get_rxnfc = igb_get_rxnfc, ++ .set_rxnfc = igb_set_rxnfc, ++ .get_rxfh_indir = igb_get_rxfh_indir, ++ .set_rxfh_indir = igb_set_rxfh_indir, ++ .get_channels = igb_get_channels, ++ .set_channels = igb_set_channels, ++ .begin = igb_ethtool_begin, ++ .complete = igb_ethtool_complete, + }; + + void igb_set_ethtool_ops(struct net_device *netdev) +diff --git a/drivers/net/ethernet/intel/igb/igb_hwmon.c b/drivers/net/ethernet/intel/igb/igb_hwmon.c +new file mode 100644 +index 0000000..58f1ce9 +--- /dev/null ++++ b/drivers/net/ethernet/intel/igb/igb_hwmon.c +@@ -0,0 +1,257 @@ ++/******************************************************************************* ++ ++ Intel(R) Gigabit Ethernet Linux driver ++ Copyright(c) 2007-2013 Intel Corporation. ++ ++ 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. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ e1000-devel Mailing List ++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ ++*******************************************************************************/ ++ ++#include "igb.h" ++#include "e1000_82575.h" ++#include "e1000_hw.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_IGB_HWMON ++static struct i2c_board_info i350_sensor_info = { ++ I2C_BOARD_INFO("i350bb", (0Xf8 >> 1)), ++}; ++ ++/* hwmon callback functions */ ++static ssize_t igb_hwmon_show_location(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr, ++ dev_attr); ++ return sprintf(buf, "loc%u\n", ++ igb_attr->sensor->location); ++} ++ ++static ssize_t igb_hwmon_show_temp(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr, ++ dev_attr); ++ unsigned int value; ++ ++ /* reset the temp field */ ++ igb_attr->hw->mac.ops.get_thermal_sensor_data(igb_attr->hw); ++ ++ value = igb_attr->sensor->temp; ++ ++ /* display millidegree */ ++ value *= 1000; ++ ++ return sprintf(buf, "%u\n", value); ++} ++ ++static ssize_t igb_hwmon_show_cautionthresh(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr, ++ dev_attr); ++ unsigned int value = igb_attr->sensor->caution_thresh; ++ ++ /* display millidegree */ ++ value *= 1000; ++ ++ return sprintf(buf, "%u\n", value); ++} ++ ++static ssize_t igb_hwmon_show_maxopthresh(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr, ++ dev_attr); ++ unsigned int value = igb_attr->sensor->max_op_thresh; ++ ++ /* display millidegree */ ++ value *= 1000; ++ ++ return sprintf(buf, "%u\n", value); ++} ++ ++/* igb_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file. ++ * @ adapter: pointer to the adapter structure ++ * @ offset: offset in the eeprom sensor data table ++ * @ type: type of sensor data to display ++ * ++ * For each file we want in hwmon's sysfs interface we need a device_attribute ++ * This is included in our hwmon_attr struct that contains the references to ++ * the data structures we need to get the data to display. ++ */ ++static int igb_add_hwmon_attr(struct igb_adapter *adapter, ++ unsigned int offset, int type) ++{ ++ int rc; ++ unsigned int n_attr; ++ struct hwmon_attr *igb_attr; ++ ++ n_attr = adapter->igb_hwmon_buff.n_hwmon; ++ igb_attr = &adapter->igb_hwmon_buff.hwmon_list[n_attr]; ++ ++ switch (type) { ++ case IGB_HWMON_TYPE_LOC: ++ igb_attr->dev_attr.show = igb_hwmon_show_location; ++ snprintf(igb_attr->name, sizeof(igb_attr->name), ++ "temp%u_label", offset); ++ break; ++ case IGB_HWMON_TYPE_TEMP: ++ igb_attr->dev_attr.show = igb_hwmon_show_temp; ++ snprintf(igb_attr->name, sizeof(igb_attr->name), ++ "temp%u_input", offset); ++ break; ++ case IGB_HWMON_TYPE_CAUTION: ++ igb_attr->dev_attr.show = igb_hwmon_show_cautionthresh; ++ snprintf(igb_attr->name, sizeof(igb_attr->name), ++ "temp%u_max", offset); ++ break; ++ case IGB_HWMON_TYPE_MAX: ++ igb_attr->dev_attr.show = igb_hwmon_show_maxopthresh; ++ snprintf(igb_attr->name, sizeof(igb_attr->name), ++ "temp%u_crit", offset); ++ break; ++ default: ++ rc = -EPERM; ++ return rc; ++ } ++ ++ /* These always the same regardless of type */ ++ igb_attr->sensor = ++ &adapter->hw.mac.thermal_sensor_data.sensor[offset]; ++ igb_attr->hw = &adapter->hw; ++ igb_attr->dev_attr.store = NULL; ++ igb_attr->dev_attr.attr.mode = S_IRUGO; ++ igb_attr->dev_attr.attr.name = igb_attr->name; ++ sysfs_attr_init(&igb_attr->dev_attr.attr); ++ rc = device_create_file(&adapter->pdev->dev, ++ &igb_attr->dev_attr); ++ if (rc == 0) ++ ++adapter->igb_hwmon_buff.n_hwmon; ++ ++ return rc; ++} ++ ++static void igb_sysfs_del_adapter(struct igb_adapter *adapter) ++{ ++ int i; ++ ++ if (adapter == NULL) ++ return; ++ ++ for (i = 0; i < adapter->igb_hwmon_buff.n_hwmon; i++) { ++ device_remove_file(&adapter->pdev->dev, ++ &adapter->igb_hwmon_buff.hwmon_list[i].dev_attr); ++ } ++ ++ kfree(adapter->igb_hwmon_buff.hwmon_list); ++ ++ if (adapter->igb_hwmon_buff.device) ++ hwmon_device_unregister(adapter->igb_hwmon_buff.device); ++} ++ ++/* called from igb_main.c */ ++void igb_sysfs_exit(struct igb_adapter *adapter) ++{ ++ igb_sysfs_del_adapter(adapter); ++} ++ ++/* called from igb_main.c */ ++int igb_sysfs_init(struct igb_adapter *adapter) ++{ ++ struct hwmon_buff *igb_hwmon = &adapter->igb_hwmon_buff; ++ unsigned int i; ++ int n_attrs; ++ int rc = 0; ++ struct i2c_client *client = NULL; ++ ++ /* If this method isn't defined we don't support thermals */ ++ if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) ++ goto exit; ++ ++ /* Don't create thermal hwmon interface if no sensors present */ ++ rc = (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw)); ++ if (rc) ++ goto exit; ++ ++ /* init i2c_client */ ++ client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info); ++ if (client == NULL) { ++ dev_info(&adapter->pdev->dev, ++ "Failed to create new i2c device..\n"); ++ goto exit; ++ } ++ adapter->i2c_client = client; ++ ++ /* Allocation space for max attributes ++ * max num sensors * values (loc, temp, max, caution) ++ */ ++ n_attrs = E1000_MAX_SENSORS * 4; ++ igb_hwmon->hwmon_list = kcalloc(n_attrs, sizeof(struct hwmon_attr), ++ GFP_KERNEL); ++ if (!igb_hwmon->hwmon_list) { ++ rc = -ENOMEM; ++ goto err; ++ } ++ ++ igb_hwmon->device = hwmon_device_register(&adapter->pdev->dev); ++ if (IS_ERR(igb_hwmon->device)) { ++ rc = PTR_ERR(igb_hwmon->device); ++ goto err; ++ } ++ ++ for (i = 0; i < E1000_MAX_SENSORS; i++) { ++ ++ /* Only create hwmon sysfs entries for sensors that have ++ * meaningful data. ++ */ ++ if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0) ++ continue; ++ ++ /* Bail if any hwmon attr struct fails to initialize */ ++ rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_CAUTION); ++ rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_LOC); ++ rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_TEMP); ++ rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_MAX); ++ if (rc) ++ goto err; ++ } ++ ++ goto exit; ++ ++err: ++ igb_sysfs_del_adapter(adapter); ++exit: ++ return rc; ++} ++#endif +diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c +index b555be0..6de564e 100644 +--- a/drivers/net/ethernet/intel/igb/igb_main.c ++++ b/drivers/net/ethernet/intel/igb/igb_main.c +@@ -1,7 +1,7 @@ + /******************************************************************************* + + Intel(R) Gigabit Ethernet Linux driver +- Copyright(c) 2007-2011 Intel Corporation. ++ Copyright(c) 2007-2013 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, +@@ -25,6 +25,8 @@ + + *******************************************************************************/ + ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ + #include + #include + #include +@@ -51,27 +53,40 @@ + #include + #include + #include ++#include + #ifdef CONFIG_IGB_DCA + #include + #endif ++#include + #include "igb.h" + +-#define MAJ 3 +-#define MIN 2 +-#define BUILD 10 ++#define MAJ 5 ++#define MIN 0 ++#define BUILD 5 + #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ + __stringify(BUILD) "-k" + char igb_driver_name[] = "igb"; + char igb_driver_version[] = DRV_VERSION; + static const char igb_driver_string[] = + "Intel(R) Gigabit Ethernet Network Driver"; +-static const char igb_copyright[] = "Copyright (c) 2007-2011 Intel Corporation."; ++static const char igb_copyright[] = ++ "Copyright (c) 2007-2013 Intel Corporation."; + + static const struct e1000_info *igb_info_tbl[] = { + [board_82575] = &e1000_82575_info, + }; + + static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = { ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_1GBPS) }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_SGMII) }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_2_5GBPS) }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I211_COPPER), board_82575 }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER), board_82575 }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_FIBER), board_82575 }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES), board_82575 }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SGMII), board_82575 }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER_FLASHLESS), board_82575 }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES_FLASHLESS), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_COPPER), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_FIBER), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SERDES), board_82575 }, +@@ -97,6 +112,7 @@ static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = { + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER), board_82575 }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_SGMII), board_82575 }, + /* required last entry */ + {0, } + }; +@@ -110,11 +126,11 @@ static void igb_free_all_tx_resources(struct igb_adapter *); + static void igb_free_all_rx_resources(struct igb_adapter *); + static void igb_setup_mrqc(struct igb_adapter *); + static int igb_probe(struct pci_dev *, const struct pci_device_id *); +-static void __devexit igb_remove(struct pci_dev *pdev); +-static void igb_init_hw_timer(struct igb_adapter *adapter); ++static void igb_remove(struct pci_dev *pdev); + static int igb_sw_init(struct igb_adapter *); + static int igb_open(struct net_device *); + static int igb_close(struct net_device *); ++static void igb_configure(struct igb_adapter *); + static void igb_configure_tx(struct igb_adapter *); + static void igb_configure_rx(struct igb_adapter *); + static void igb_clean_all_tx_rings(struct igb_adapter *); +@@ -145,7 +161,7 @@ static bool igb_clean_rx_irq(struct igb_q_vector *, int); + static int igb_ioctl(struct net_device *, struct ifreq *, int cmd); + static void igb_tx_timeout(struct net_device *); + static void igb_reset_task(struct work_struct *); +-static void igb_vlan_mode(struct net_device *netdev, u32 features); ++static void igb_vlan_mode(struct net_device *netdev, netdev_features_t features); + static void igb_vlan_rx_add_vid(struct net_device *, u16); + static void igb_vlan_rx_kill_vid(struct net_device *, u16); + static void igb_restore_vlan(struct igb_adapter *); +@@ -159,19 +175,32 @@ static int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac); + static int igb_ndo_set_vf_vlan(struct net_device *netdev, + int vf, u16 vlan, u8 qos); + static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate); ++static int igb_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, ++ bool setting); + static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, + struct ifla_vf_info *ivi); + static void igb_check_vf_rate_limit(struct igb_adapter *); + + #ifdef CONFIG_PCI_IOV + static int igb_vf_configure(struct igb_adapter *adapter, int vf); +-static int igb_find_enabled_vfs(struct igb_adapter *adapter); +-static int igb_check_vf_assignment(struct igb_adapter *adapter); ++static bool igb_vfs_are_assigned(struct igb_adapter *adapter); + #endif + + #ifdef CONFIG_PM +-static int igb_suspend(struct pci_dev *, pm_message_t); +-static int igb_resume(struct pci_dev *); ++#ifdef CONFIG_PM_SLEEP ++static int igb_suspend(struct device *); ++#endif ++static int igb_resume(struct device *); ++#ifdef CONFIG_PM_RUNTIME ++static int igb_runtime_suspend(struct device *dev); ++static int igb_runtime_resume(struct device *dev); ++static int igb_runtime_idle(struct device *dev); ++#endif ++static const struct dev_pm_ops igb_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(igb_suspend, igb_resume) ++ SET_RUNTIME_PM_OPS(igb_runtime_suspend, igb_runtime_resume, ++ igb_runtime_idle) ++}; + #endif + static void igb_shutdown(struct pci_dev *); + #ifdef CONFIG_IGB_DCA +@@ -210,11 +239,9 @@ static struct pci_driver igb_driver = { + .name = igb_driver_name, + .id_table = igb_pci_tbl, + .probe = igb_probe, +- .remove = __devexit_p(igb_remove), ++ .remove = igb_remove, + #ifdef CONFIG_PM +- /* Power Management Hooks */ +- .suspend = igb_suspend, +- .resume = igb_resume, ++ .driver.pm = &igb_pm_ops, + #endif + .shutdown = igb_shutdown, + .err_handler = &igb_err_handler +@@ -225,6 +252,11 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver"); + MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_VERSION); + ++#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) ++static int debug = -1; ++module_param(debug, int, 0); ++MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); ++ + struct igb_reg_info { + u32 ofs; + char *name; +@@ -266,9 +298,7 @@ static const struct igb_reg_info igb_reg_info_tbl[] = { + {} + }; + +-/* +- * igb_regdump - register printout routine +- */ ++/* igb_regdump - register printout routine */ + static void igb_regdump(struct e1000_hw *hw, struct igb_reg_info *reginfo) + { + int n = 0; +@@ -325,21 +355,16 @@ static void igb_regdump(struct e1000_hw *hw, struct igb_reg_info *reginfo) + regs[n] = rd32(E1000_TXDCTL(n)); + break; + default: +- printk(KERN_INFO "%-15s %08x\n", +- reginfo->name, rd32(reginfo->ofs)); ++ pr_info("%-15s %08x\n", reginfo->name, rd32(reginfo->ofs)); + return; + } + + snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]"); +- printk(KERN_INFO "%-15s ", rname); +- for (n = 0; n < 4; n++) +- printk(KERN_CONT "%08x ", regs[n]); +- printk(KERN_CONT "\n"); ++ pr_info("%-15s %08x %08x %08x %08x\n", rname, regs[0], regs[1], ++ regs[2], regs[3]); + } + +-/* +- * igb_dump - Print registers, tx-rings and rx-rings +- */ ++/* igb_dump - Print registers, Tx-rings and Rx-rings */ + static void igb_dump(struct igb_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; +@@ -359,18 +384,15 @@ static void igb_dump(struct igb_adapter *adapter) + /* Print netdevice Info */ + if (netdev) { + dev_info(&adapter->pdev->dev, "Net device Info\n"); +- printk(KERN_INFO "Device Name state " +- "trans_start last_rx\n"); +- printk(KERN_INFO "%-15s %016lX %016lX %016lX\n", +- netdev->name, +- netdev->state, +- netdev->trans_start, +- netdev->last_rx); ++ pr_info("Device Name state trans_start " ++ "last_rx\n"); ++ pr_info("%-15s %016lX %016lX %016lX\n", netdev->name, ++ netdev->state, netdev->trans_start, netdev->last_rx); + } + + /* Print Registers */ + dev_info(&adapter->pdev->dev, "Register Dump\n"); +- printk(KERN_INFO " Register Name Value\n"); ++ pr_info(" Register Name Value\n"); + for (reginfo = (struct igb_reg_info *)igb_reg_info_tbl; + reginfo->name; reginfo++) { + igb_regdump(hw, reginfo); +@@ -381,18 +403,17 @@ static void igb_dump(struct igb_adapter *adapter) + goto exit; + + dev_info(&adapter->pdev->dev, "TX Rings Summary\n"); +- printk(KERN_INFO "Queue [NTU] [NTC] [bi(ntc)->dma ]" +- " leng ntw timestamp\n"); ++ pr_info("Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n"); + for (n = 0; n < adapter->num_tx_queues; n++) { + struct igb_tx_buffer *buffer_info; + tx_ring = adapter->tx_ring[n]; + buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean]; +- printk(KERN_INFO " %5d %5X %5X %016llX %04X %p %016llX\n", +- n, tx_ring->next_to_use, tx_ring->next_to_clean, +- (u64)buffer_info->dma, +- buffer_info->length, +- buffer_info->next_to_watch, +- (u64)buffer_info->time_stamp); ++ pr_info(" %5d %5X %5X %016llX %04X %p %016llX\n", ++ n, tx_ring->next_to_use, tx_ring->next_to_clean, ++ (u64)dma_unmap_addr(buffer_info, dma), ++ dma_unmap_len(buffer_info, len), ++ buffer_info->next_to_watch, ++ (u64)buffer_info->time_stamp); + } + + /* Print TX Rings */ +@@ -414,53 +435,56 @@ static void igb_dump(struct igb_adapter *adapter) + + for (n = 0; n < adapter->num_tx_queues; n++) { + tx_ring = adapter->tx_ring[n]; +- printk(KERN_INFO "------------------------------------\n"); +- printk(KERN_INFO "TX QUEUE INDEX = %d\n", tx_ring->queue_index); +- printk(KERN_INFO "------------------------------------\n"); +- printk(KERN_INFO "T [desc] [address 63:0 ] " +- "[PlPOCIStDDM Ln] [bi->dma ] " +- "leng ntw timestamp bi->skb\n"); ++ pr_info("------------------------------------\n"); ++ pr_info("TX QUEUE INDEX = %d\n", tx_ring->queue_index); ++ pr_info("------------------------------------\n"); ++ pr_info("T [desc] [address 63:0 ] [PlPOCIStDDM Ln] " ++ "[bi->dma ] leng ntw timestamp " ++ "bi->skb\n"); + + for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { ++ const char *next_desc; + struct igb_tx_buffer *buffer_info; + tx_desc = IGB_TX_DESC(tx_ring, i); + buffer_info = &tx_ring->tx_buffer_info[i]; + u0 = (struct my_u0 *)tx_desc; +- printk(KERN_INFO "T [0x%03X] %016llX %016llX %016llX" +- " %04X %p %016llX %p", i, +- le64_to_cpu(u0->a), +- le64_to_cpu(u0->b), +- (u64)buffer_info->dma, +- buffer_info->length, +- buffer_info->next_to_watch, +- (u64)buffer_info->time_stamp, +- buffer_info->skb); + if (i == tx_ring->next_to_use && +- i == tx_ring->next_to_clean) +- printk(KERN_CONT " NTC/U\n"); ++ i == tx_ring->next_to_clean) ++ next_desc = " NTC/U"; + else if (i == tx_ring->next_to_use) +- printk(KERN_CONT " NTU\n"); ++ next_desc = " NTU"; + else if (i == tx_ring->next_to_clean) +- printk(KERN_CONT " NTC\n"); ++ next_desc = " NTC"; + else +- printk(KERN_CONT "\n"); ++ next_desc = ""; ++ ++ pr_info("T [0x%03X] %016llX %016llX %016llX" ++ " %04X %p %016llX %p%s\n", i, ++ le64_to_cpu(u0->a), ++ le64_to_cpu(u0->b), ++ (u64)dma_unmap_addr(buffer_info, dma), ++ dma_unmap_len(buffer_info, len), ++ buffer_info->next_to_watch, ++ (u64)buffer_info->time_stamp, ++ buffer_info->skb, next_desc); + +- if (netif_msg_pktdata(adapter) && buffer_info->dma != 0) ++ if (netif_msg_pktdata(adapter) && buffer_info->skb) + print_hex_dump(KERN_INFO, "", + DUMP_PREFIX_ADDRESS, +- 16, 1, phys_to_virt(buffer_info->dma), +- buffer_info->length, true); ++ 16, 1, buffer_info->skb->data, ++ dma_unmap_len(buffer_info, len), ++ true); + } + } + + /* Print RX Rings Summary */ + rx_ring_summary: + dev_info(&adapter->pdev->dev, "RX Rings Summary\n"); +- printk(KERN_INFO "Queue [NTU] [NTC]\n"); ++ pr_info("Queue [NTU] [NTC]\n"); + for (n = 0; n < adapter->num_rx_queues; n++) { + rx_ring = adapter->rx_ring[n]; +- printk(KERN_INFO " %5d %5X %5X\n", n, +- rx_ring->next_to_use, rx_ring->next_to_clean); ++ pr_info(" %5d %5X %5X\n", ++ n, rx_ring->next_to_use, rx_ring->next_to_clean); + } + + /* Print RX Rings */ +@@ -492,60 +516,54 @@ rx_ring_summary: + + for (n = 0; n < adapter->num_rx_queues; n++) { + rx_ring = adapter->rx_ring[n]; +- printk(KERN_INFO "------------------------------------\n"); +- printk(KERN_INFO "RX QUEUE INDEX = %d\n", rx_ring->queue_index); +- printk(KERN_INFO "------------------------------------\n"); +- printk(KERN_INFO "R [desc] [ PktBuf A0] " +- "[ HeadBuf DD] [bi->dma ] [bi->skb] " +- "<-- Adv Rx Read format\n"); +- printk(KERN_INFO "RWB[desc] [PcsmIpSHl PtRs] " +- "[vl er S cks ln] ---------------- [bi->skb] " +- "<-- Adv Rx Write-Back format\n"); ++ pr_info("------------------------------------\n"); ++ pr_info("RX QUEUE INDEX = %d\n", rx_ring->queue_index); ++ pr_info("------------------------------------\n"); ++ pr_info("R [desc] [ PktBuf A0] [ HeadBuf DD] " ++ "[bi->dma ] [bi->skb] <-- Adv Rx Read format\n"); ++ pr_info("RWB[desc] [PcsmIpSHl PtRs] [vl er S cks ln] -----" ++ "----------- [bi->skb] <-- Adv Rx Write-Back format\n"); + + for (i = 0; i < rx_ring->count; i++) { ++ const char *next_desc; + struct igb_rx_buffer *buffer_info; + buffer_info = &rx_ring->rx_buffer_info[i]; + rx_desc = IGB_RX_DESC(rx_ring, i); + u0 = (struct my_u0 *)rx_desc; + staterr = le32_to_cpu(rx_desc->wb.upper.status_error); ++ ++ if (i == rx_ring->next_to_use) ++ next_desc = " NTU"; ++ else if (i == rx_ring->next_to_clean) ++ next_desc = " NTC"; ++ else ++ next_desc = ""; ++ + if (staterr & E1000_RXD_STAT_DD) { + /* Descriptor Done */ +- printk(KERN_INFO "RWB[0x%03X] %016llX " +- "%016llX ---------------- %p", i, ++ pr_info("%s[0x%03X] %016llX %016llX ---------------- %s\n", ++ "RWB", i, + le64_to_cpu(u0->a), + le64_to_cpu(u0->b), +- buffer_info->skb); ++ next_desc); + } else { +- printk(KERN_INFO "R [0x%03X] %016llX " +- "%016llX %016llX %p", i, ++ pr_info("%s[0x%03X] %016llX %016llX %016llX %s\n", ++ "R ", i, + le64_to_cpu(u0->a), + le64_to_cpu(u0->b), + (u64)buffer_info->dma, +- buffer_info->skb); ++ next_desc); + +- if (netif_msg_pktdata(adapter)) { +- print_hex_dump(KERN_INFO, "", +- DUMP_PREFIX_ADDRESS, +- 16, 1, +- phys_to_virt(buffer_info->dma), +- IGB_RX_HDR_LEN, true); ++ if (netif_msg_pktdata(adapter) && ++ buffer_info->dma && buffer_info->page) { + print_hex_dump(KERN_INFO, "", + DUMP_PREFIX_ADDRESS, + 16, 1, +- phys_to_virt( +- buffer_info->page_dma + +- buffer_info->page_offset), +- PAGE_SIZE/2, true); ++ page_address(buffer_info->page) + ++ buffer_info->page_offset, ++ IGB_RX_BUFSZ, true); + } + } +- +- if (i == rx_ring->next_to_use) +- printk(KERN_CONT " NTU\n"); +- else if (i == rx_ring->next_to_clean) +- printk(KERN_CONT " NTC\n"); +- else +- printk(KERN_CONT "\n"); +- + } + } + +@@ -553,36 +571,100 @@ exit: + return; + } + ++/** ++ * igb_get_i2c_data - Reads the I2C SDA data bit ++ * @hw: pointer to hardware structure ++ * @i2cctl: Current value of I2CCTL register ++ * ++ * Returns the I2C data bit value ++ **/ ++static int igb_get_i2c_data(void *data) ++{ ++ struct igb_adapter *adapter = (struct igb_adapter *)data; ++ struct e1000_hw *hw = &adapter->hw; ++ s32 i2cctl = rd32(E1000_I2CPARAMS); ++ ++ return ((i2cctl & E1000_I2C_DATA_IN) != 0); ++} ++ ++/** ++ * igb_set_i2c_data - Sets the I2C data bit ++ * @data: pointer to hardware structure ++ * @state: I2C data value (0 or 1) to set ++ * ++ * Sets the I2C data bit ++ **/ ++static void igb_set_i2c_data(void *data, int state) ++{ ++ struct igb_adapter *adapter = (struct igb_adapter *)data; ++ struct e1000_hw *hw = &adapter->hw; ++ s32 i2cctl = rd32(E1000_I2CPARAMS); ++ ++ if (state) ++ i2cctl |= E1000_I2C_DATA_OUT; ++ else ++ i2cctl &= ~E1000_I2C_DATA_OUT; ++ ++ i2cctl &= ~E1000_I2C_DATA_OE_N; ++ i2cctl |= E1000_I2C_CLK_OE_N; ++ wr32(E1000_I2CPARAMS, i2cctl); ++ wrfl(); ++ ++} + + /** +- * igb_read_clock - read raw cycle counter (to be used by time counter) +- */ +-static cycle_t igb_read_clock(const struct cyclecounter *tc) ++ * igb_set_i2c_clk - Sets the I2C SCL clock ++ * @data: pointer to hardware structure ++ * @state: state to set clock ++ * ++ * Sets the I2C clock line to state ++ **/ ++static void igb_set_i2c_clk(void *data, int state) + { +- struct igb_adapter *adapter = +- container_of(tc, struct igb_adapter, cycles); ++ struct igb_adapter *adapter = (struct igb_adapter *)data; + struct e1000_hw *hw = &adapter->hw; +- u64 stamp = 0; +- int shift = 0; ++ s32 i2cctl = rd32(E1000_I2CPARAMS); + +- /* +- * The timestamp latches on lowest register read. For the 82580 +- * the lowest register is SYSTIMR instead of SYSTIML. However we never +- * adjusted TIMINCA so SYSTIMR will just read as all 0s so ignore it. +- */ +- if (hw->mac.type >= e1000_82580) { +- stamp = rd32(E1000_SYSTIMR) >> 8; +- shift = IGB_82580_TSYNC_SHIFT; ++ if (state) { ++ i2cctl |= E1000_I2C_CLK_OUT; ++ i2cctl &= ~E1000_I2C_CLK_OE_N; ++ } else { ++ i2cctl &= ~E1000_I2C_CLK_OUT; ++ i2cctl &= ~E1000_I2C_CLK_OE_N; + } ++ wr32(E1000_I2CPARAMS, i2cctl); ++ wrfl(); ++} ++ ++/** ++ * igb_get_i2c_clk - Gets the I2C SCL clock state ++ * @data: pointer to hardware structure ++ * ++ * Gets the I2C clock state ++ **/ ++static int igb_get_i2c_clk(void *data) ++{ ++ struct igb_adapter *adapter = (struct igb_adapter *)data; ++ struct e1000_hw *hw = &adapter->hw; ++ s32 i2cctl = rd32(E1000_I2CPARAMS); + +- stamp |= (u64)rd32(E1000_SYSTIML) << shift; +- stamp |= (u64)rd32(E1000_SYSTIMH) << (shift + 32); +- return stamp; ++ return ((i2cctl & E1000_I2C_CLK_IN) != 0); + } + ++static const struct i2c_algo_bit_data igb_i2c_algo = { ++ .setsda = igb_set_i2c_data, ++ .setscl = igb_set_i2c_clk, ++ .getsda = igb_get_i2c_data, ++ .getscl = igb_get_i2c_clk, ++ .udelay = 5, ++ .timeout = 20, ++}; ++ + /** +- * igb_get_hw_dev - return device +- * used by hardware layer to print debugging information ++ * igb_get_hw_dev - return device ++ * @hw: pointer to hardware structure ++ * ++ * used by hardware layer to print debugging information + **/ + struct net_device *igb_get_hw_dev(struct e1000_hw *hw) + { +@@ -591,18 +673,18 @@ struct net_device *igb_get_hw_dev(struct e1000_hw *hw) + } + + /** +- * igb_init_module - Driver Registration Routine ++ * igb_init_module - Driver Registration Routine + * +- * igb_init_module is the first routine called when the driver is +- * loaded. All it does is register with the PCI subsystem. ++ * igb_init_module is the first routine called when the driver is ++ * loaded. All it does is register with the PCI subsystem. + **/ + static int __init igb_init_module(void) + { + int ret; +- printk(KERN_INFO "%s - version %s\n", ++ pr_info("%s - version %s\n", + igb_driver_string, igb_driver_version); + +- printk(KERN_INFO "%s\n", igb_copyright); ++ pr_info("%s\n", igb_copyright); + + #ifdef CONFIG_IGB_DCA + dca_register_notify(&dca_notifier); +@@ -614,10 +696,10 @@ static int __init igb_init_module(void) + module_init(igb_init_module); + + /** +- * igb_exit_module - Driver Exit Cleanup Routine ++ * igb_exit_module - Driver Exit Cleanup Routine + * +- * igb_exit_module is called just before the driver is removed +- * from memory. ++ * igb_exit_module is called just before the driver is removed ++ * from memory. + **/ + static void __exit igb_exit_module(void) + { +@@ -631,11 +713,11 @@ module_exit(igb_exit_module); + + #define Q_IDX_82576(i) (((i & 0x1) << 3) + (i >> 1)) + /** +- * igb_cache_ring_register - Descriptor ring to register mapping +- * @adapter: board private structure to initialize ++ * igb_cache_ring_register - Descriptor ring to register mapping ++ * @adapter: board private structure to initialize + * +- * Once we know the feature-set enabled for the device, we'll cache +- * the register offset the descriptor ring is assigned to. ++ * Once we know the feature-set enabled for the device, we'll cache ++ * the register offset the descriptor ring is assigned to. + **/ + static void igb_cache_ring_register(struct igb_adapter *adapter) + { +@@ -652,11 +734,14 @@ static void igb_cache_ring_register(struct igb_adapter *adapter) + if (adapter->vfs_allocated_count) { + for (; i < adapter->rss_queues; i++) + adapter->rx_ring[i]->reg_idx = rbase_offset + +- Q_IDX_82576(i); ++ Q_IDX_82576(i); + } + case e1000_82575: + case e1000_82580: + case e1000_i350: ++ case e1000_i354: ++ case e1000_i210: ++ case e1000_i211: + default: + for (; i < adapter->num_rx_queues; i++) + adapter->rx_ring[i]->reg_idx = rbase_offset + i; +@@ -666,104 +751,6 @@ static void igb_cache_ring_register(struct igb_adapter *adapter) + } + } + +-static void igb_free_queues(struct igb_adapter *adapter) +-{ +- int i; +- +- for (i = 0; i < adapter->num_tx_queues; i++) { +- kfree(adapter->tx_ring[i]); +- adapter->tx_ring[i] = NULL; +- } +- for (i = 0; i < adapter->num_rx_queues; i++) { +- kfree(adapter->rx_ring[i]); +- adapter->rx_ring[i] = NULL; +- } +- adapter->num_rx_queues = 0; +- adapter->num_tx_queues = 0; +-} +- +-/** +- * igb_alloc_queues - Allocate memory for all rings +- * @adapter: board private structure to initialize +- * +- * We allocate one ring per queue at run-time since we don't know the +- * number of queues at compile-time. +- **/ +-static int igb_alloc_queues(struct igb_adapter *adapter) +-{ +- struct igb_ring *ring; +- int i; +- int orig_node = adapter->node; +- +- for (i = 0; i < adapter->num_tx_queues; i++) { +- if (orig_node == -1) { +- int cur_node = next_online_node(adapter->node); +- if (cur_node == MAX_NUMNODES) +- cur_node = first_online_node; +- adapter->node = cur_node; +- } +- ring = kzalloc_node(sizeof(struct igb_ring), GFP_KERNEL, +- adapter->node); +- if (!ring) +- ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); +- if (!ring) +- goto err; +- ring->count = adapter->tx_ring_count; +- ring->queue_index = i; +- ring->dev = &adapter->pdev->dev; +- ring->netdev = adapter->netdev; +- ring->numa_node = adapter->node; +- /* For 82575, context index must be unique per ring. */ +- if (adapter->hw.mac.type == e1000_82575) +- set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags); +- adapter->tx_ring[i] = ring; +- } +- /* Restore the adapter's original node */ +- adapter->node = orig_node; +- +- for (i = 0; i < adapter->num_rx_queues; i++) { +- if (orig_node == -1) { +- int cur_node = next_online_node(adapter->node); +- if (cur_node == MAX_NUMNODES) +- cur_node = first_online_node; +- adapter->node = cur_node; +- } +- ring = kzalloc_node(sizeof(struct igb_ring), GFP_KERNEL, +- adapter->node); +- if (!ring) +- ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); +- if (!ring) +- goto err; +- ring->count = adapter->rx_ring_count; +- ring->queue_index = i; +- ring->dev = &adapter->pdev->dev; +- ring->netdev = adapter->netdev; +- ring->numa_node = adapter->node; +- /* set flag indicating ring supports SCTP checksum offload */ +- if (adapter->hw.mac.type >= e1000_82576) +- set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags); +- +- /* On i350, loopback VLAN packets have the tag byte-swapped. */ +- if (adapter->hw.mac.type == e1000_i350) +- set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags); +- +- adapter->rx_ring[i] = ring; +- } +- /* Restore the adapter's original node */ +- adapter->node = orig_node; +- +- igb_cache_ring_register(adapter); +- +- return 0; +- +-err: +- /* Restore the adapter's original node */ +- adapter->node = orig_node; +- igb_free_queues(adapter); +- +- return -ENOMEM; +-} +- + /** + * igb_write_ivar - configure ivar for given MSI-X vector + * @hw: pointer to the HW structure +@@ -807,9 +794,10 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) + switch (hw->mac.type) { + case e1000_82575: + /* The 82575 assigns vectors using a bitmask, which matches the +- bitmask for the EICR/EIMS/EIMC registers. To assign one +- or more queues to a vector, we write the appropriate bits +- into the MSIXBM register for that vector. */ ++ * bitmask for the EICR/EIMS/EIMC registers. To assign one ++ * or more queues to a vector, we write the appropriate bits ++ * into the MSIXBM register for that vector. ++ */ + if (rx_queue > IGB_N0_QUEUE) + msixbm = E1000_EICR_RX_QUEUE0 << rx_queue; + if (tx_queue > IGB_N0_QUEUE) +@@ -820,8 +808,7 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) + q_vector->eims_value = msixbm; + break; + case e1000_82576: +- /* +- * 82576 uses a table that essentially consists of 2 columns ++ /* 82576 uses a table that essentially consists of 2 columns + * with 8 rows. The ordering is column-major so we use the + * lower 3 bits as the row index, and the 4th bit as the + * column offset. +@@ -838,8 +825,10 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) + break; + case e1000_82580: + case e1000_i350: +- /* +- * On 82580 and newer adapters the scheme is similar to 82576 ++ case e1000_i354: ++ case e1000_i210: ++ case e1000_i211: ++ /* On 82580 and newer adapters the scheme is similar to 82576 + * however instead of ordering column-major we have things + * ordered row-major. So we traverse the table by using + * bit 0 as the column offset, and the remaining bits as the +@@ -868,10 +857,11 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) + } + + /** +- * igb_configure_msix - Configure MSI-X hardware ++ * igb_configure_msix - Configure MSI-X hardware ++ * @adapter: board private structure to initialize + * +- * igb_configure_msix sets up the hardware to properly +- * generate MSI-X interrupts. ++ * igb_configure_msix sets up the hardware to properly ++ * generate MSI-X interrupts. + **/ + static void igb_configure_msix(struct igb_adapter *adapter) + { +@@ -895,8 +885,7 @@ static void igb_configure_msix(struct igb_adapter *adapter) + wr32(E1000_CTRL_EXT, tmp); + + /* enable msix_other interrupt */ +- array_wr32(E1000_MSIXBM(0), vector++, +- E1000_EIMS_OTHER); ++ array_wr32(E1000_MSIXBM(0), vector++, E1000_EIMS_OTHER); + adapter->eims_other = E1000_EIMS_OTHER; + + break; +@@ -904,11 +893,15 @@ static void igb_configure_msix(struct igb_adapter *adapter) + case e1000_82576: + case e1000_82580: + case e1000_i350: ++ case e1000_i354: ++ case e1000_i210: ++ case e1000_i211: + /* Turn on MSI-X capability first, or our settings +- * won't stick. And it will take days to debug. */ ++ * won't stick. And it will take days to debug. ++ */ + wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE | +- E1000_GPIE_PBA | E1000_GPIE_EIAME | +- E1000_GPIE_NSICR); ++ E1000_GPIE_PBA | E1000_GPIE_EIAME | ++ E1000_GPIE_NSICR); + + /* enable msix_other interrupt */ + adapter->eims_other = 1 << vector; +@@ -930,10 +923,11 @@ static void igb_configure_msix(struct igb_adapter *adapter) + } + + /** +- * igb_request_msix - Initialize MSI-X interrupts ++ * igb_request_msix - Initialize MSI-X interrupts ++ * @adapter: board private structure to initialize + * +- * igb_request_msix allocates MSI-X vectors and requests interrupts from the +- * kernel. ++ * igb_request_msix allocates MSI-X vectors and requests interrupts from the ++ * kernel. + **/ + static int igb_request_msix(struct igb_adapter *adapter) + { +@@ -942,7 +936,7 @@ static int igb_request_msix(struct igb_adapter *adapter) + int i, err = 0, vector = 0, free_vector = 0; + + err = request_irq(adapter->msix_entries[vector].vector, +- igb_msix_other, 0, netdev->name, adapter); ++ igb_msix_other, 0, netdev->name, adapter); + if (err) + goto err_out; + +@@ -966,8 +960,8 @@ static int igb_request_msix(struct igb_adapter *adapter) + sprintf(q_vector->name, "%s-unused", netdev->name); + + err = request_irq(adapter->msix_entries[vector].vector, +- igb_msix_ring, 0, q_vector->name, +- q_vector); ++ igb_msix_ring, 0, q_vector->name, ++ q_vector); + if (err) + goto err_free; + } +@@ -1000,52 +994,82 @@ static void igb_reset_interrupt_capability(struct igb_adapter *adapter) + } + + /** +- * igb_free_q_vectors - Free memory allocated for interrupt vectors +- * @adapter: board private structure to initialize ++ * igb_free_q_vector - Free memory allocated for specific interrupt vector ++ * @adapter: board private structure to initialize ++ * @v_idx: Index of vector to be freed ++ * ++ * This function frees the memory allocated to the q_vector. In addition if ++ * NAPI is enabled it will delete any references to the NAPI struct prior ++ * to freeing the q_vector. ++ **/ ++static void igb_free_q_vector(struct igb_adapter *adapter, int v_idx) ++{ ++ struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; ++ ++ if (q_vector->tx.ring) ++ adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL; ++ ++ if (q_vector->rx.ring) ++ adapter->tx_ring[q_vector->rx.ring->queue_index] = NULL; ++ ++ adapter->q_vector[v_idx] = NULL; ++ netif_napi_del(&q_vector->napi); ++ ++ /* igb_get_stats64() might access the rings on this vector, ++ * we must wait a grace period before freeing it. ++ */ ++ kfree_rcu(q_vector, rcu); ++} ++ ++/** ++ * igb_free_q_vectors - Free memory allocated for interrupt vectors ++ * @adapter: board private structure to initialize + * +- * This function frees the memory allocated to the q_vectors. In addition if +- * NAPI is enabled it will delete any references to the NAPI struct prior +- * to freeing the q_vector. ++ * This function frees the memory allocated to the q_vectors. In addition if ++ * NAPI is enabled it will delete any references to the NAPI struct prior ++ * to freeing the q_vector. + **/ + static void igb_free_q_vectors(struct igb_adapter *adapter) + { +- int v_idx; ++ int v_idx = adapter->num_q_vectors; + +- for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) { +- struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; +- adapter->q_vector[v_idx] = NULL; +- if (!q_vector) +- continue; +- netif_napi_del(&q_vector->napi); +- kfree(q_vector); +- } ++ adapter->num_tx_queues = 0; ++ adapter->num_rx_queues = 0; + adapter->num_q_vectors = 0; ++ ++ while (v_idx--) ++ igb_free_q_vector(adapter, v_idx); + } + + /** +- * igb_clear_interrupt_scheme - reset the device to a state of no interrupts ++ * igb_clear_interrupt_scheme - reset the device to a state of no interrupts ++ * @adapter: board private structure to initialize + * +- * This function resets the device so that it has 0 rx queues, tx queues, and +- * MSI-X interrupts allocated. ++ * This function resets the device so that it has 0 Rx queues, Tx queues, and ++ * MSI-X interrupts allocated. + */ + static void igb_clear_interrupt_scheme(struct igb_adapter *adapter) + { +- igb_free_queues(adapter); + igb_free_q_vectors(adapter); + igb_reset_interrupt_capability(adapter); + } + + /** +- * igb_set_interrupt_capability - set MSI or MSI-X if supported ++ * igb_set_interrupt_capability - set MSI or MSI-X if supported ++ * @adapter: board private structure to initialize ++ * @msix: boolean value of MSIX capability + * +- * Attempt to configure interrupts using the best available +- * capabilities of the hardware and kernel. ++ * Attempt to configure interrupts using the best available ++ * capabilities of the hardware and kernel. + **/ +-static int igb_set_interrupt_capability(struct igb_adapter *adapter) ++static void igb_set_interrupt_capability(struct igb_adapter *adapter, bool msix) + { + int err; + int numvecs, i; + ++ if (!msix) ++ goto msi_only; ++ + /* Number of supported queues. */ + adapter->num_rx_queues = adapter->rss_queues; + if (adapter->vfs_allocated_count) +@@ -1053,10 +1077,10 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter) + else + adapter->num_tx_queues = adapter->rss_queues; + +- /* start with one vector for every rx queue */ ++ /* start with one vector for every Rx queue */ + numvecs = adapter->num_rx_queues; + +- /* if tx handler is separate add 1 for every tx queue */ ++ /* if Tx handler is separate add 1 for every Tx queue */ + if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS)) + numvecs += adapter->num_tx_queues; + +@@ -1067,6 +1091,7 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter) + numvecs++; + adapter->msix_entries = kcalloc(numvecs, sizeof(struct msix_entry), + GFP_KERNEL); ++ + if (!adapter->msix_entries) + goto msi_only; + +@@ -1077,7 +1102,7 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter) + adapter->msix_entries, + numvecs); + if (err == 0) +- goto out; ++ return; + + igb_reset_interrupt_capability(adapter); + +@@ -1107,135 +1132,209 @@ msi_only: + adapter->num_q_vectors = 1; + if (!pci_enable_msi(adapter->pdev)) + adapter->flags |= IGB_FLAG_HAS_MSI; +-out: +- /* Notify the stack of the (possibly) reduced queue counts. */ +- netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues); +- return netif_set_real_num_rx_queues(adapter->netdev, +- adapter->num_rx_queues); ++} ++ ++static void igb_add_ring(struct igb_ring *ring, ++ struct igb_ring_container *head) ++{ ++ head->ring = ring; ++ head->count++; + } + + /** +- * igb_alloc_q_vectors - Allocate memory for interrupt vectors +- * @adapter: board private structure to initialize ++ * igb_alloc_q_vector - Allocate memory for a single interrupt vector ++ * @adapter: board private structure to initialize ++ * @v_count: q_vectors allocated on adapter, used for ring interleaving ++ * @v_idx: index of vector in adapter struct ++ * @txr_count: total number of Tx rings to allocate ++ * @txr_idx: index of first Tx ring to allocate ++ * @rxr_count: total number of Rx rings to allocate ++ * @rxr_idx: index of first Rx ring to allocate + * +- * We allocate one q_vector per queue interrupt. If allocation fails we +- * return -ENOMEM. ++ * We allocate one q_vector. If allocation fails we return -ENOMEM. + **/ +-static int igb_alloc_q_vectors(struct igb_adapter *adapter) ++static int igb_alloc_q_vector(struct igb_adapter *adapter, ++ int v_count, int v_idx, ++ int txr_count, int txr_idx, ++ int rxr_count, int rxr_idx) + { + struct igb_q_vector *q_vector; +- struct e1000_hw *hw = &adapter->hw; +- int v_idx; +- int orig_node = adapter->node; +- +- for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) { +- if ((adapter->num_q_vectors == (adapter->num_rx_queues + +- adapter->num_tx_queues)) && +- (adapter->num_rx_queues == v_idx)) +- adapter->node = orig_node; +- if (orig_node == -1) { +- int cur_node = next_online_node(adapter->node); +- if (cur_node == MAX_NUMNODES) +- cur_node = first_online_node; +- adapter->node = cur_node; +- } +- q_vector = kzalloc_node(sizeof(struct igb_q_vector), GFP_KERNEL, +- adapter->node); +- if (!q_vector) +- q_vector = kzalloc(sizeof(struct igb_q_vector), +- GFP_KERNEL); +- if (!q_vector) +- goto err_out; +- q_vector->adapter = adapter; +- q_vector->itr_register = hw->hw_addr + E1000_EITR(0); +- q_vector->itr_val = IGB_START_ITR; +- netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64); +- adapter->q_vector[v_idx] = q_vector; +- } +- /* Restore the adapter's original node */ +- adapter->node = orig_node; ++ struct igb_ring *ring; ++ int ring_count, size; + +- return 0; ++ /* igb only supports 1 Tx and/or 1 Rx queue per vector */ ++ if (txr_count > 1 || rxr_count > 1) ++ return -ENOMEM; + +-err_out: +- /* Restore the adapter's original node */ +- adapter->node = orig_node; +- igb_free_q_vectors(adapter); +- return -ENOMEM; +-} ++ ring_count = txr_count + rxr_count; ++ size = sizeof(struct igb_q_vector) + ++ (sizeof(struct igb_ring) * ring_count); + +-static void igb_map_rx_ring_to_vector(struct igb_adapter *adapter, +- int ring_idx, int v_idx) +-{ +- struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; ++ /* allocate q_vector and rings */ ++ q_vector = kzalloc(size, GFP_KERNEL); ++ if (!q_vector) ++ return -ENOMEM; + +- q_vector->rx.ring = adapter->rx_ring[ring_idx]; +- q_vector->rx.ring->q_vector = q_vector; +- q_vector->rx.count++; +- q_vector->itr_val = adapter->rx_itr_setting; +- if (q_vector->itr_val && q_vector->itr_val <= 3) +- q_vector->itr_val = IGB_START_ITR; +-} ++ /* initialize NAPI */ ++ netif_napi_add(adapter->netdev, &q_vector->napi, ++ igb_poll, 64); + +-static void igb_map_tx_ring_to_vector(struct igb_adapter *adapter, +- int ring_idx, int v_idx) +-{ +- struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; ++ /* tie q_vector and adapter together */ ++ adapter->q_vector[v_idx] = q_vector; ++ q_vector->adapter = adapter; + +- q_vector->tx.ring = adapter->tx_ring[ring_idx]; +- q_vector->tx.ring->q_vector = q_vector; +- q_vector->tx.count++; +- q_vector->itr_val = adapter->tx_itr_setting; ++ /* initialize work limits */ + q_vector->tx.work_limit = adapter->tx_work_limit; +- if (q_vector->itr_val && q_vector->itr_val <= 3) +- q_vector->itr_val = IGB_START_ITR; ++ ++ /* initialize ITR configuration */ ++ q_vector->itr_register = adapter->hw.hw_addr + E1000_EITR(0); ++ q_vector->itr_val = IGB_START_ITR; ++ ++ /* initialize pointer to rings */ ++ ring = q_vector->ring; ++ ++ /* intialize ITR */ ++ if (rxr_count) { ++ /* rx or rx/tx vector */ ++ if (!adapter->rx_itr_setting || adapter->rx_itr_setting > 3) ++ q_vector->itr_val = adapter->rx_itr_setting; ++ } else { ++ /* tx only vector */ ++ if (!adapter->tx_itr_setting || adapter->tx_itr_setting > 3) ++ q_vector->itr_val = adapter->tx_itr_setting; ++ } ++ ++ if (txr_count) { ++ /* assign generic ring traits */ ++ ring->dev = &adapter->pdev->dev; ++ ring->netdev = adapter->netdev; ++ ++ /* configure backlink on ring */ ++ ring->q_vector = q_vector; ++ ++ /* update q_vector Tx values */ ++ igb_add_ring(ring, &q_vector->tx); ++ ++ /* For 82575, context index must be unique per ring. */ ++ if (adapter->hw.mac.type == e1000_82575) ++ set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags); ++ ++ /* apply Tx specific ring traits */ ++ ring->count = adapter->tx_ring_count; ++ ring->queue_index = txr_idx; ++ ++ /* assign ring to adapter */ ++ adapter->tx_ring[txr_idx] = ring; ++ ++ /* push pointer to next ring */ ++ ring++; ++ } ++ ++ if (rxr_count) { ++ /* assign generic ring traits */ ++ ring->dev = &adapter->pdev->dev; ++ ring->netdev = adapter->netdev; ++ ++ /* configure backlink on ring */ ++ ring->q_vector = q_vector; ++ ++ /* update q_vector Rx values */ ++ igb_add_ring(ring, &q_vector->rx); ++ ++ /* set flag indicating ring supports SCTP checksum offload */ ++ if (adapter->hw.mac.type >= e1000_82576) ++ set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags); ++ ++ /* ++ * On i350, i354, i210, and i211, loopback VLAN packets ++ * have the tag byte-swapped. ++ */ ++ if (adapter->hw.mac.type >= e1000_i350) ++ set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags); ++ ++ /* apply Rx specific ring traits */ ++ ring->count = adapter->rx_ring_count; ++ ring->queue_index = rxr_idx; ++ ++ /* assign ring to adapter */ ++ adapter->rx_ring[rxr_idx] = ring; ++ } ++ ++ return 0; + } + ++ + /** +- * igb_map_ring_to_vector - maps allocated queues to vectors ++ * igb_alloc_q_vectors - Allocate memory for interrupt vectors ++ * @adapter: board private structure to initialize + * +- * This function maps the recently allocated queues to vectors. ++ * We allocate one q_vector per queue interrupt. If allocation fails we ++ * return -ENOMEM. + **/ +-static int igb_map_ring_to_vector(struct igb_adapter *adapter) ++static int igb_alloc_q_vectors(struct igb_adapter *adapter) + { +- int i; +- int v_idx = 0; ++ int q_vectors = adapter->num_q_vectors; ++ int rxr_remaining = adapter->num_rx_queues; ++ int txr_remaining = adapter->num_tx_queues; ++ int rxr_idx = 0, txr_idx = 0, v_idx = 0; ++ int err; + +- if ((adapter->num_q_vectors < adapter->num_rx_queues) || +- (adapter->num_q_vectors < adapter->num_tx_queues)) +- return -ENOMEM; ++ if (q_vectors >= (rxr_remaining + txr_remaining)) { ++ for (; rxr_remaining; v_idx++) { ++ err = igb_alloc_q_vector(adapter, q_vectors, v_idx, ++ 0, 0, 1, rxr_idx); + +- if (adapter->num_q_vectors >= +- (adapter->num_rx_queues + adapter->num_tx_queues)) { +- for (i = 0; i < adapter->num_rx_queues; i++) +- igb_map_rx_ring_to_vector(adapter, i, v_idx++); +- for (i = 0; i < adapter->num_tx_queues; i++) +- igb_map_tx_ring_to_vector(adapter, i, v_idx++); +- } else { +- for (i = 0; i < adapter->num_rx_queues; i++) { +- if (i < adapter->num_tx_queues) +- igb_map_tx_ring_to_vector(adapter, i, v_idx); +- igb_map_rx_ring_to_vector(adapter, i, v_idx++); ++ if (err) ++ goto err_out; ++ ++ /* update counts and index */ ++ rxr_remaining--; ++ rxr_idx++; + } +- for (; i < adapter->num_tx_queues; i++) +- igb_map_tx_ring_to_vector(adapter, i, v_idx++); + } ++ ++ for (; v_idx < q_vectors; v_idx++) { ++ int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx); ++ int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx); ++ err = igb_alloc_q_vector(adapter, q_vectors, v_idx, ++ tqpv, txr_idx, rqpv, rxr_idx); ++ ++ if (err) ++ goto err_out; ++ ++ /* update counts and index */ ++ rxr_remaining -= rqpv; ++ txr_remaining -= tqpv; ++ rxr_idx++; ++ txr_idx++; ++ } ++ + return 0; ++ ++err_out: ++ adapter->num_tx_queues = 0; ++ adapter->num_rx_queues = 0; ++ adapter->num_q_vectors = 0; ++ ++ while (v_idx--) ++ igb_free_q_vector(adapter, v_idx); ++ ++ return -ENOMEM; + } + + /** +- * igb_init_interrupt_scheme - initialize interrupts, allocate queues/vectors ++ * igb_init_interrupt_scheme - initialize interrupts, allocate queues/vectors ++ * @adapter: board private structure to initialize ++ * @msix: boolean value of MSIX capability + * +- * This function initializes the interrupts and allocates all of the queues. ++ * This function initializes the interrupts and allocates all of the queues. + **/ +-static int igb_init_interrupt_scheme(struct igb_adapter *adapter) ++static int igb_init_interrupt_scheme(struct igb_adapter *adapter, bool msix) + { + struct pci_dev *pdev = adapter->pdev; + int err; + +- err = igb_set_interrupt_capability(adapter); +- if (err) +- return err; ++ igb_set_interrupt_capability(adapter, msix); + + err = igb_alloc_q_vectors(adapter); + if (err) { +@@ -1243,34 +1342,21 @@ static int igb_init_interrupt_scheme(struct igb_adapter *adapter) + goto err_alloc_q_vectors; + } + +- err = igb_alloc_queues(adapter); +- if (err) { +- dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); +- goto err_alloc_queues; +- } +- +- err = igb_map_ring_to_vector(adapter); +- if (err) { +- dev_err(&pdev->dev, "Invalid q_vector to ring mapping\n"); +- goto err_map_queues; +- } +- ++ igb_cache_ring_register(adapter); + + return 0; +-err_map_queues: +- igb_free_queues(adapter); +-err_alloc_queues: +- igb_free_q_vectors(adapter); ++ + err_alloc_q_vectors: + igb_reset_interrupt_capability(adapter); + return err; + } + + /** +- * igb_request_irq - initialize interrupts ++ * igb_request_irq - initialize interrupts ++ * @adapter: board private structure to initialize + * +- * Attempts to configure interrupts using the best available +- * capabilities of the hardware and kernel. ++ * Attempts to configure interrupts using the best available ++ * capabilities of the hardware and kernel. + **/ + static int igb_request_irq(struct igb_adapter *adapter) + { +@@ -1283,29 +1369,17 @@ static int igb_request_irq(struct igb_adapter *adapter) + if (!err) + goto request_done; + /* fall back to MSI */ +- igb_clear_interrupt_scheme(adapter); +- if (!pci_enable_msi(pdev)) +- adapter->flags |= IGB_FLAG_HAS_MSI; + igb_free_all_tx_resources(adapter); + igb_free_all_rx_resources(adapter); +- adapter->num_tx_queues = 1; +- adapter->num_rx_queues = 1; +- adapter->num_q_vectors = 1; +- err = igb_alloc_q_vectors(adapter); +- if (err) { +- dev_err(&pdev->dev, +- "Unable to allocate memory for vectors\n"); +- goto request_done; +- } +- err = igb_alloc_queues(adapter); +- if (err) { +- dev_err(&pdev->dev, +- "Unable to allocate memory for queues\n"); +- igb_free_q_vectors(adapter); ++ ++ igb_clear_interrupt_scheme(adapter); ++ err = igb_init_interrupt_scheme(adapter, false); ++ if (err) + goto request_done; +- } ++ + igb_setup_all_tx_resources(adapter); + igb_setup_all_rx_resources(adapter); ++ igb_configure(adapter); + } + + igb_assign_vector(adapter->q_vector[0], 0); +@@ -1348,15 +1422,14 @@ static void igb_free_irq(struct igb_adapter *adapter) + } + + /** +- * igb_irq_disable - Mask off interrupt generation on the NIC +- * @adapter: board private structure ++ * igb_irq_disable - Mask off interrupt generation on the NIC ++ * @adapter: board private structure + **/ + static void igb_irq_disable(struct igb_adapter *adapter) + { + struct e1000_hw *hw = &adapter->hw; + +- /* +- * we need to be careful when disabling interrupts. The VFs are also ++ /* we need to be careful when disabling interrupts. The VFs are also + * mapped into these registers and so clearing the bits can cause + * issues on the VF drivers so we only need to clear what we set + */ +@@ -1381,8 +1454,8 @@ static void igb_irq_disable(struct igb_adapter *adapter) + } + + /** +- * igb_irq_enable - Enable default interrupt generation settings +- * @adapter: board private structure ++ * igb_irq_enable - Enable default interrupt generation settings ++ * @adapter: board private structure + **/ + static void igb_irq_enable(struct igb_adapter *adapter) + { +@@ -1431,13 +1504,12 @@ static void igb_update_mng_vlan(struct igb_adapter *adapter) + } + + /** +- * igb_release_hw_control - release control of the h/w to f/w +- * @adapter: address of board private structure +- * +- * igb_release_hw_control resets CTRL_EXT:DRV_LOAD bit. +- * For ASF and Pass Through versions of f/w this means that the +- * driver is no longer loaded. ++ * igb_release_hw_control - release control of the h/w to f/w ++ * @adapter: address of board private structure + * ++ * igb_release_hw_control resets CTRL_EXT:DRV_LOAD bit. ++ * For ASF and Pass Through versions of f/w this means that the ++ * driver is no longer loaded. + **/ + static void igb_release_hw_control(struct igb_adapter *adapter) + { +@@ -1451,13 +1523,12 @@ static void igb_release_hw_control(struct igb_adapter *adapter) + } + + /** +- * igb_get_hw_control - get control of the h/w from f/w +- * @adapter: address of board private structure +- * +- * igb_get_hw_control sets CTRL_EXT:DRV_LOAD bit. +- * For ASF and Pass Through versions of f/w this means that +- * the driver is loaded. ++ * igb_get_hw_control - get control of the h/w from f/w ++ * @adapter: address of board private structure + * ++ * igb_get_hw_control sets CTRL_EXT:DRV_LOAD bit. ++ * For ASF and Pass Through versions of f/w this means that ++ * the driver is loaded. + **/ + static void igb_get_hw_control(struct igb_adapter *adapter) + { +@@ -1471,8 +1542,8 @@ static void igb_get_hw_control(struct igb_adapter *adapter) + } + + /** +- * igb_configure - configure the hardware for RX and TX +- * @adapter: private board structure ++ * igb_configure - configure the hardware for RX and TX ++ * @adapter: private board structure + **/ + static void igb_configure(struct igb_adapter *adapter) + { +@@ -1495,7 +1566,8 @@ static void igb_configure(struct igb_adapter *adapter) + + /* call igb_desc_unused which always leaves + * at least 1 descriptor unused to make sure +- * next_to_use != next_to_clean */ ++ * next_to_use != next_to_clean ++ */ + for (i = 0; i < adapter->num_rx_queues; i++) { + struct igb_ring *ring = adapter->rx_ring[i]; + igb_alloc_rx_buffers(ring, igb_desc_unused(ring)); +@@ -1503,20 +1575,23 @@ static void igb_configure(struct igb_adapter *adapter) + } + + /** +- * igb_power_up_link - Power up the phy/serdes link +- * @adapter: address of board private structure ++ * igb_power_up_link - Power up the phy/serdes link ++ * @adapter: address of board private structure + **/ + void igb_power_up_link(struct igb_adapter *adapter) + { ++ igb_reset_phy(&adapter->hw); ++ + if (adapter->hw.phy.media_type == e1000_media_type_copper) + igb_power_up_phy_copper(&adapter->hw); + else + igb_power_up_serdes_link_82575(&adapter->hw); ++ igb_setup_link(&adapter->hw); + } + + /** +- * igb_power_down_link - Power down the phy/serdes link +- * @adapter: address of board private structure ++ * igb_power_down_link - Power down the phy/serdes link ++ * @adapter: address of board private structure + */ + static void igb_power_down_link(struct igb_adapter *adapter) + { +@@ -1527,8 +1602,8 @@ static void igb_power_down_link(struct igb_adapter *adapter) + } + + /** +- * igb_up - Open the interface and prepare it to handle traffic +- * @adapter: board private structure ++ * igb_up - Open the interface and prepare it to handle traffic ++ * @adapter: board private structure + **/ + int igb_up(struct igb_adapter *adapter) + { +@@ -1576,7 +1651,8 @@ void igb_down(struct igb_adapter *adapter) + int i; + + /* signal that we're down so the interrupt handler does not +- * reschedule our watchdog timer */ ++ * reschedule our watchdog timer ++ */ + set_bit(__IGB_DOWN, &adapter->state); + + /* disable receives in the hardware */ +@@ -1594,10 +1670,15 @@ void igb_down(struct igb_adapter *adapter) + wrfl(); + msleep(10); + +- for (i = 0; i < adapter->num_q_vectors; i++) ++ igb_irq_disable(adapter); ++ ++ adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; ++ ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ napi_synchronize(&(adapter->q_vector[i]->napi)); + napi_disable(&(adapter->q_vector[i]->napi)); ++ } + +- igb_irq_disable(adapter); + + del_timer_sync(&adapter->watchdog_timer); + del_timer_sync(&adapter->phy_info_timer); +@@ -1639,14 +1720,14 @@ void igb_reset(struct igb_adapter *adapter) + struct e1000_hw *hw = &adapter->hw; + struct e1000_mac_info *mac = &hw->mac; + struct e1000_fc_info *fc = &hw->fc; +- u32 pba = 0, tx_space, min_tx_space, min_rx_space; +- u16 hwm; ++ u32 pba = 0, tx_space, min_tx_space, min_rx_space, hwm; + + /* Repartition Pba for greater than 9k mtu + * To take effect CTRL.RST is required. + */ + switch (mac->type) { + case e1000_i350: ++ case e1000_i354: + case e1000_82580: + pba = rd32(E1000_RXPBS); + pba = igb_rxpbs_adjust_82580(pba); +@@ -1656,6 +1737,8 @@ void igb_reset(struct igb_adapter *adapter) + pba &= E1000_RXPBS_SIZE_MASK_82576; + break; + case e1000_82575: ++ case e1000_i210: ++ case e1000_i211: + default: + pba = E1000_PBA_34K; + break; +@@ -1671,14 +1754,16 @@ void igb_reset(struct igb_adapter *adapter) + * rounded up to the next 1KB and expressed in KB. Likewise, + * the Rx FIFO should be large enough to accommodate at least + * one full receive packet and is similarly rounded up and +- * expressed in KB. */ ++ * expressed in KB. ++ */ + pba = rd32(E1000_PBA); + /* upper 16 bits has Tx packet buffer allocation size in KB */ + tx_space = pba >> 16; + /* lower 16 bits has Rx packet buffer allocation size in KB */ + pba &= 0xffff; +- /* the tx fifo also stores 16 bytes of information about the tx +- * but don't include ethernet FCS because hardware appends it */ ++ /* the Tx fifo also stores 16 bytes of information about the Tx ++ * but don't include ethernet FCS because hardware appends it ++ */ + min_tx_space = (adapter->max_frame_size + + sizeof(union e1000_adv_tx_desc) - + ETH_FCS_LEN) * 2; +@@ -1691,13 +1776,15 @@ void igb_reset(struct igb_adapter *adapter) + + /* If current Tx allocation is less than the min Tx FIFO size, + * and the min Tx FIFO size is less than the current Rx FIFO +- * allocation, take space away from current Rx allocation */ ++ * allocation, take space away from current Rx allocation ++ */ + if (tx_space < min_tx_space && + ((min_tx_space - tx_space) < pba)) { + pba = pba - (min_tx_space - tx_space); + +- /* if short on rx space, rx wins and must trump tx +- * adjustment */ ++ /* if short on Rx space, Rx wins and must trump Tx ++ * adjustment ++ */ + if (pba < min_rx_space) + pba = min_rx_space; + } +@@ -1709,11 +1796,12 @@ void igb_reset(struct igb_adapter *adapter) + * (or the size used for early receive) above it in the Rx FIFO. + * Set it to the lower of: + * - 90% of the Rx FIFO size, or +- * - the full Rx FIFO size minus one full frame */ ++ * - the full Rx FIFO size minus one full frame ++ */ + hwm = min(((pba << 10) * 9 / 10), + ((pba << 10) - 2 * adapter->max_frame_size)); + +- fc->high_water = hwm & 0xFFF0; /* 16-byte granularity */ ++ fc->high_water = hwm & 0xFFFFFFF0; /* 16-byte granularity */ + fc->low_water = fc->high_water - 16; + fc->pause_time = 0xFFFF; + fc->send_xon = 1; +@@ -1740,7 +1828,25 @@ void igb_reset(struct igb_adapter *adapter) + if (hw->mac.ops.init_hw(hw)) + dev_err(&pdev->dev, "Hardware Error\n"); + ++ /* Flow control settings reset on hardware reset, so guarantee flow ++ * control is off when forcing speed. ++ */ ++ if (!hw->mac.autoneg) ++ igb_force_mac_fc(hw); ++ + igb_init_dmac(adapter, pba); ++#ifdef CONFIG_IGB_HWMON ++ /* Re-initialize the thermal sensor on i350 devices. */ ++ if (!test_bit(__IGB_DOWN, &adapter->state)) { ++ if (mac->type == e1000_i350 && hw->bus.func == 0) { ++ /* If present, re-initialize the external thermal sensor ++ * interface. ++ */ ++ if (adapter->ets) ++ mac->ops.init_thermal_sensor_thresh(hw); ++ } ++ } ++#endif + if (!netif_running(adapter->netdev)) + igb_power_down_link(adapter); + +@@ -1749,14 +1855,19 @@ void igb_reset(struct igb_adapter *adapter) + /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ + wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE); + ++#ifdef CONFIG_IGB_PTP ++ /* Re-enable PTP, where applicable. */ ++ igb_ptp_reset(adapter); ++#endif /* CONFIG_IGB_PTP */ ++ + igb_get_phy_info(hw); + } + +-static u32 igb_fix_features(struct net_device *netdev, u32 features) ++static netdev_features_t igb_fix_features(struct net_device *netdev, ++ netdev_features_t features) + { +- /* +- * Since there is no support for separate rx/tx vlan accel +- * enable/disable make sure tx flag is always in same state as rx. ++ /* Since there is no support for separate Rx/Tx vlan accel ++ * enable/disable make sure Tx flag is always in same state as Rx. + */ + if (features & NETIF_F_HW_VLAN_RX) + features |= NETIF_F_HW_VLAN_TX; +@@ -1766,9 +1877,10 @@ static u32 igb_fix_features(struct net_device *netdev, u32 features) + return features; + } + +-static int igb_set_features(struct net_device *netdev, u32 features) ++static int igb_set_features(struct net_device *netdev, ++ netdev_features_t features) + { +- u32 changed = netdev->features ^ features; ++ netdev_features_t changed = netdev->features ^ features; + + if (changed & NETIF_F_HW_VLAN_RX) + igb_vlan_mode(netdev, features); +@@ -1792,6 +1904,7 @@ static const struct net_device_ops igb_netdev_ops = { + .ndo_set_vf_mac = igb_ndo_set_vf_mac, + .ndo_set_vf_vlan = igb_ndo_set_vf_vlan, + .ndo_set_vf_tx_rate = igb_ndo_set_vf_bw, ++ .ndo_set_vf_spoofchk = igb_ndo_set_vf_spoofchk, + .ndo_get_vf_config = igb_ndo_get_vf_config, + #ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = igb_netpoll, +@@ -1801,18 +1914,92 @@ static const struct net_device_ops igb_netdev_ops = { + }; + + /** +- * igb_probe - Device Initialization Routine +- * @pdev: PCI device information struct +- * @ent: entry in igb_pci_tbl ++ * igb_set_fw_version - Configure version string for ethtool ++ * @adapter: adapter struct ++ **/ ++void igb_set_fw_version(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ struct e1000_fw_version fw; ++ ++ igb_get_fw_version(hw, &fw); ++ ++ switch (hw->mac.type) { ++ case e1000_i210: ++ case e1000_i211: ++ if (!(igb_get_flash_presence_i210(hw))) { ++ snprintf(adapter->fw_version, ++ sizeof(adapter->fw_version), ++ "%2d.%2d-%d", ++ fw.invm_major, fw.invm_minor, ++ fw.invm_img_type); ++ break; ++ } ++ /* fall through */ ++ default: ++ /* if option is rom valid, display its version too */ ++ if (fw.or_valid) { ++ snprintf(adapter->fw_version, ++ sizeof(adapter->fw_version), ++ "%d.%d, 0x%08x, %d.%d.%d", ++ fw.eep_major, fw.eep_minor, fw.etrack_id, ++ fw.or_major, fw.or_build, fw.or_patch); ++ /* no option rom */ ++ } else if (fw.etrack_id != 0X0000) { ++ snprintf(adapter->fw_version, ++ sizeof(adapter->fw_version), ++ "%d.%d, 0x%08x", ++ fw.eep_major, fw.eep_minor, fw.etrack_id); ++ } else { ++ snprintf(adapter->fw_version, ++ sizeof(adapter->fw_version), ++ "%d.%d.%d", ++ fw.eep_major, fw.eep_minor, fw.eep_build); ++ } ++ break; ++ } ++ return; ++} ++ ++/** ++ * igb_init_i2c - Init I2C interface ++ * @adapter: pointer to adapter structure ++ **/ ++static s32 igb_init_i2c(struct igb_adapter *adapter) ++{ ++ s32 status = E1000_SUCCESS; ++ ++ /* I2C interface supported on i350 devices */ ++ if (adapter->hw.mac.type != e1000_i350) ++ return E1000_SUCCESS; ++ ++ /* Initialize the i2c bus which is controlled by the registers. ++ * This bus will use the i2c_algo_bit structue that implements ++ * the protocol through toggling of the 4 bits in the register. ++ */ ++ adapter->i2c_adap.owner = THIS_MODULE; ++ adapter->i2c_algo = igb_i2c_algo; ++ adapter->i2c_algo.data = adapter; ++ adapter->i2c_adap.algo_data = &adapter->i2c_algo; ++ adapter->i2c_adap.dev.parent = &adapter->pdev->dev; ++ strlcpy(adapter->i2c_adap.name, "igb BB", ++ sizeof(adapter->i2c_adap.name)); ++ status = i2c_bit_add_bus(&adapter->i2c_adap); ++ return status; ++} ++ ++/** ++ * igb_probe - Device Initialization Routine ++ * @pdev: PCI device information struct ++ * @ent: entry in igb_pci_tbl + * +- * Returns 0 on success, negative on failure ++ * Returns 0 on success, negative on failure + * +- * igb_probe initializes an adapter identified by a pci_dev structure. +- * The OS initialization, configuring of the adapter private structure, +- * and a hardware reset occur. ++ * igb_probe initializes an adapter identified by a pci_dev structure. ++ * The OS initialization, configuring of the adapter private structure, ++ * and a hardware reset occur. + **/ +-static int __devinit igb_probe(struct pci_dev *pdev, +- const struct pci_device_id *ent) ++static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + { + struct net_device *netdev; + struct igb_adapter *adapter; +@@ -1823,7 +2010,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, + const struct e1000_info *ei = igb_info_tbl[ent->driver_data]; + unsigned long mmio_start, mmio_len; + int err, pci_using_dac; +- u16 eeprom_apme_mask = IGB_EEPROM_APME; + u8 part_str[E1000_PBANUM_LENGTH]; + + /* Catch broken hardware that put the wrong VF device ID in +@@ -1831,7 +2017,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, + */ + if (pdev->is_virtfn) { + WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n", +- pci_name(pdev), pdev->vendor, pdev->device); ++ pci_name(pdev), pdev->vendor, pdev->device); + return -EINVAL; + } + +@@ -1840,26 +2026,21 @@ static int __devinit igb_probe(struct pci_dev *pdev, + return err; + + pci_using_dac = 0; +- err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); ++ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (!err) { +- err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); +- if (!err) +- pci_using_dac = 1; ++ pci_using_dac = 1; + } else { +- err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); ++ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (err) { +- err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); +- if (err) { +- dev_err(&pdev->dev, "No usable DMA " +- "configuration, aborting\n"); +- goto err_dma; +- } ++ dev_err(&pdev->dev, ++ "No usable DMA configuration, aborting\n"); ++ goto err_dma; + } + } + + err = pci_request_selected_regions(pdev, pci_select_bars(pdev, +- IORESOURCE_MEM), +- igb_driver_name); ++ IORESOURCE_MEM), ++ igb_driver_name); + if (err) + goto err_pci_reg; + +@@ -1882,7 +2063,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, + adapter->pdev = pdev; + hw = &adapter->hw; + hw->back = adapter; +- adapter->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE; ++ adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); + + mmio_start = pci_resource_start(pdev, 0); + mmio_len = pci_resource_len(pdev, 0); +@@ -1937,8 +2118,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, + dev_info(&pdev->dev, + "PHY reset is blocked due to SOL/IDER session.\n"); + +- /* +- * features is initialized to 0 in allocation, it might have bits ++ /* features is initialized to 0 in allocation, it might have bits + * set by igb_sw_init so we should use an or instead of an + * assignment. + */ +@@ -1979,14 +2159,32 @@ static int __devinit igb_probe(struct pci_dev *pdev, + adapter->en_mng_pt = igb_enable_mng_pass_thru(hw); + + /* before reading the NVM, reset the controller to put the device in a +- * known good starting state */ ++ * known good starting state ++ */ + hw->mac.ops.reset_hw(hw); + +- /* make sure the NVM is good */ +- if (hw->nvm.ops.validate(hw) < 0) { +- dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); +- err = -EIO; +- goto err_eeprom; ++ /* make sure the NVM is good , i211/i210 parts can have special NVM ++ * that doesn't contain a checksum ++ */ ++ switch (hw->mac.type) { ++ case e1000_i210: ++ case e1000_i211: ++ if (igb_get_flash_presence_i210(hw)) { ++ if (hw->nvm.ops.validate(hw) < 0) { ++ dev_err(&pdev->dev, ++ "The NVM Checksum Is Not Valid\n"); ++ err = -EIO; ++ goto err_eeprom; ++ } ++ } ++ break; ++ default: ++ if (hw->nvm.ops.validate(hw) < 0) { ++ dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); ++ err = -EIO; ++ goto err_eeprom; ++ } ++ break; + } + + /* copy the MAC address out of the NVM */ +@@ -2002,10 +2200,13 @@ static int __devinit igb_probe(struct pci_dev *pdev, + goto err_eeprom; + } + ++ /* get firmware version for ethtool -i */ ++ igb_set_fw_version(adapter); ++ + setup_timer(&adapter->watchdog_timer, igb_watchdog, +- (unsigned long) adapter); ++ (unsigned long) adapter); + setup_timer(&adapter->phy_info_timer, igb_update_phy_info, +- (unsigned long) adapter); ++ (unsigned long) adapter); + + INIT_WORK(&adapter->reset_task, igb_reset_task); + INIT_WORK(&adapter->watchdog_task, igb_watchdog_task); +@@ -2020,57 +2221,79 @@ static int __devinit igb_probe(struct pci_dev *pdev, + + igb_validate_mdi_setting(hw); + +- /* Initial Wake on LAN setting If APM wake is enabled in the EEPROM, +- * enable the ACPI Magic Packet filter +- */ +- ++ /* By default, support wake on port A */ + if (hw->bus.func == 0) +- hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); +- else if (hw->mac.type >= e1000_82580) ++ adapter->flags |= IGB_FLAG_WOL_SUPPORTED; ++ ++ /* Check the NVM for wake support on non-port A ports */ ++ if (hw->mac.type >= e1000_82580) + hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + +- NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, +- &eeprom_data); ++ NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, ++ &eeprom_data); + else if (hw->bus.func == 1) + hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); + +- if (eeprom_data & eeprom_apme_mask) +- adapter->eeprom_wol |= E1000_WUFC_MAG; ++ if (eeprom_data & IGB_EEPROM_APME) ++ adapter->flags |= IGB_FLAG_WOL_SUPPORTED; + + /* now that we have the eeprom settings, apply the special cases where + * the eeprom may be wrong or the board simply won't support wake on +- * lan on a particular port */ ++ * lan on a particular port ++ */ + switch (pdev->device) { + case E1000_DEV_ID_82575GB_QUAD_COPPER: +- adapter->eeprom_wol = 0; ++ adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; + break; + case E1000_DEV_ID_82575EB_FIBER_SERDES: + case E1000_DEV_ID_82576_FIBER: + case E1000_DEV_ID_82576_SERDES: + /* Wake events only supported on port A for dual fiber +- * regardless of eeprom setting */ ++ * regardless of eeprom setting ++ */ + if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1) +- adapter->eeprom_wol = 0; ++ adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; + break; + case E1000_DEV_ID_82576_QUAD_COPPER: + case E1000_DEV_ID_82576_QUAD_COPPER_ET2: + /* if quad port adapter, disable WoL on all but port A */ + if (global_quad_port_a != 0) +- adapter->eeprom_wol = 0; ++ adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; + else + adapter->flags |= IGB_FLAG_QUAD_PORT_A; + /* Reset for multiple quad port adapters */ + if (++global_quad_port_a == 4) + global_quad_port_a = 0; + break; ++ default: ++ /* If the device can't wake, don't set software support */ ++ if (!device_can_wakeup(&adapter->pdev->dev)) ++ adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; + } + + /* initialize the wol settings based on the eeprom settings */ +- adapter->wol = adapter->eeprom_wol; +- device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); ++ if (adapter->flags & IGB_FLAG_WOL_SUPPORTED) ++ adapter->wol |= E1000_WUFC_MAG; ++ ++ /* Some vendors want WoL disabled by default, but still supported */ ++ if ((hw->mac.type == e1000_i350) && ++ (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)) { ++ adapter->flags |= IGB_FLAG_WOL_SUPPORTED; ++ adapter->wol = 0; ++ } ++ ++ device_set_wakeup_enable(&adapter->pdev->dev, ++ adapter->flags & IGB_FLAG_WOL_SUPPORTED); + + /* reset the hardware with the new settings */ + igb_reset(adapter); + ++ /* Init the I2C interface */ ++ err = igb_init_i2c(adapter); ++ if (err) { ++ dev_err(&pdev->dev, "failed to init i2c interface\n"); ++ goto err_eeprom; ++ } ++ + /* let the f/w know that the h/w is now under the control of the + * driver. */ + igb_get_hw_control(adapter); +@@ -2091,23 +2314,55 @@ static int __devinit igb_probe(struct pci_dev *pdev, + } + + #endif ++#ifdef CONFIG_IGB_HWMON ++ /* Initialize the thermal sensor on i350 devices. */ ++ if (hw->mac.type == e1000_i350 && hw->bus.func == 0) { ++ u16 ets_word; ++ ++ /* Read the NVM to determine if this i350 device supports an ++ * external thermal sensor. ++ */ ++ hw->nvm.ops.read(hw, NVM_ETS_CFG, 1, &ets_word); ++ if (ets_word != 0x0000 && ets_word != 0xFFFF) ++ adapter->ets = true; ++ else ++ adapter->ets = false; ++ if (igb_sysfs_init(adapter)) ++ dev_err(&pdev->dev, ++ "failed to allocate sysfs resources\n"); ++ } else { ++ adapter->ets = false; ++ } ++#endif ++#ifdef CONFIG_IGB_PTP + /* do hw tstamp init after resetting */ +- igb_init_hw_timer(adapter); ++ igb_ptp_init(adapter); ++#endif /* CONFIG_IGB_PTP */ + + dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n"); +- /* print bus type/speed/width info */ +- dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n", +- netdev->name, +- ((hw->bus.speed == e1000_bus_speed_2500) ? "2.5Gb/s" : +- (hw->bus.speed == e1000_bus_speed_5000) ? "5.0Gb/s" : +- "unknown"), +- ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" : +- (hw->bus.width == e1000_bus_width_pcie_x2) ? "Width x2" : +- (hw->bus.width == e1000_bus_width_pcie_x1) ? "Width x1" : +- "unknown"), +- netdev->dev_addr); +- +- ret_val = igb_read_part_string(hw, part_str, E1000_PBANUM_LENGTH); ++ /* print bus type/speed/width info, not applicable to i354 */ ++ if (hw->mac.type != e1000_i354) { ++ dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n", ++ netdev->name, ++ ((hw->bus.speed == e1000_bus_speed_2500) ? "2.5Gb/s" : ++ (hw->bus.speed == e1000_bus_speed_5000) ? "5.0Gb/s" : ++ "unknown"), ++ ((hw->bus.width == e1000_bus_width_pcie_x4) ? ++ "Width x4" : ++ (hw->bus.width == e1000_bus_width_pcie_x2) ? ++ "Width x2" : ++ (hw->bus.width == e1000_bus_width_pcie_x1) ? ++ "Width x1" : "unknown"), netdev->dev_addr); ++ } ++ ++ if ((hw->mac.type >= e1000_i210 || ++ igb_get_flash_presence_i210(hw))) { ++ ret_val = igb_read_part_string(hw, part_str, ++ E1000_PBANUM_LENGTH); ++ } else { ++ ret_val = -E1000_ERR_INVM_VALUE_NOT_FOUND; ++ } ++ + if (ret_val) + strcpy(part_str, "Unknown"); + dev_info(&pdev->dev, "%s: PBA No: %s\n", netdev->name, part_str); +@@ -2118,15 +2373,27 @@ static int __devinit igb_probe(struct pci_dev *pdev, + adapter->num_rx_queues, adapter->num_tx_queues); + switch (hw->mac.type) { + case e1000_i350: ++ case e1000_i210: ++ case e1000_i211: + igb_set_eee_i350(hw); + break; ++ case e1000_i354: ++ if (hw->phy.media_type == e1000_media_type_copper) { ++ if ((rd32(E1000_CTRL_EXT) & ++ E1000_CTRL_EXT_LINK_MODE_SGMII)) ++ igb_set_eee_i354(hw); ++ } ++ break; + default: + break; + } ++ ++ pm_runtime_put_noidle(&pdev->dev); + return 0; + + err_register: + igb_release_hw_control(adapter); ++ memset(&adapter->i2c_adap, 0, sizeof(adapter->i2c_adap)); + err_eeprom: + if (!igb_check_reset_block(hw)) + igb_reset_phy(hw); +@@ -2140,7 +2407,7 @@ err_ioremap: + free_netdev(netdev); + err_alloc_etherdev: + pci_release_selected_regions(pdev, +- pci_select_bars(pdev, IORESOURCE_MEM)); ++ pci_select_bars(pdev, IORESOURCE_MEM)); + err_pci_reg: + err_dma: + pci_disable_device(pdev); +@@ -2148,22 +2415,39 @@ err_dma: + } + + /** +- * igb_remove - Device Removal Routine +- * @pdev: PCI device information struct ++ * igb_remove_i2c - Cleanup I2C interface ++ * @adapter: pointer to adapter structure ++ **/ ++static void igb_remove_i2c(struct igb_adapter *adapter) ++{ ++ /* free the adapter bus structure */ ++ i2c_del_adapter(&adapter->i2c_adap); ++} ++ ++/** ++ * igb_remove - Device Removal Routine ++ * @pdev: PCI device information struct + * +- * igb_remove is called by the PCI subsystem to alert the driver +- * that it should release a PCI device. The could be caused by a +- * Hot-Plug event, or because the driver is going to be removed from +- * memory. ++ * igb_remove is called by the PCI subsystem to alert the driver ++ * that it should release a PCI device. The could be caused by a ++ * Hot-Plug event, or because the driver is going to be removed from ++ * memory. + **/ +-static void __devexit igb_remove(struct pci_dev *pdev) ++static void igb_remove(struct pci_dev *pdev) + { + struct net_device *netdev = pci_get_drvdata(pdev); + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + +- /* +- * The watchdog timer may be rescheduled, so explicitly ++ pm_runtime_get_noresume(&pdev->dev); ++#ifdef CONFIG_IGB_HWMON ++ igb_sysfs_exit(adapter); ++#endif ++ igb_remove_i2c(adapter); ++#ifdef CONFIG_IGB_PTP ++ igb_ptp_stop(adapter); ++#endif /* CONFIG_IGB_PTP */ ++ /* The watchdog timer may be rescheduled, so explicitly + * disable watchdog from being rescheduled. + */ + set_bit(__IGB_DOWN, &adapter->state); +@@ -2183,7 +2467,8 @@ static void __devexit igb_remove(struct pci_dev *pdev) + #endif + + /* Release control of h/w to f/w. If f/w is AMT enabled, this +- * would have already happened in close and is redundant. */ ++ * would have already happened in close and is redundant. ++ */ + igb_release_hw_control(adapter); + + unregister_netdev(netdev); +@@ -2194,11 +2479,11 @@ static void __devexit igb_remove(struct pci_dev *pdev) + /* reclaim resources allocated to VFs */ + if (adapter->vf_data) { + /* disable iov and allow time for transactions to clear */ +- if (!igb_check_vf_assignment(adapter)) { ++ if (igb_vfs_are_assigned(adapter)) { ++ dev_info(&pdev->dev, "Unloading driver while VFs are assigned - VFs will not be deallocated\n"); ++ } else { + pci_disable_sriov(pdev); + msleep(500); +- } else { +- dev_info(&pdev->dev, "VF(s) assigned to guests!\n"); + } + + kfree(adapter->vf_data); +@@ -2214,7 +2499,7 @@ static void __devexit igb_remove(struct pci_dev *pdev) + if (hw->flash_address) + iounmap(hw->flash_address); + pci_release_selected_regions(pdev, +- pci_select_bars(pdev, IORESOURCE_MEM)); ++ pci_select_bars(pdev, IORESOURCE_MEM)); + + kfree(adapter->shadow_vfta); + free_netdev(netdev); +@@ -2225,21 +2510,26 @@ static void __devexit igb_remove(struct pci_dev *pdev) + } + + /** +- * igb_probe_vfs - Initialize vf data storage and add VFs to pci config space +- * @adapter: board private structure to initialize ++ * igb_probe_vfs - Initialize vf data storage and add VFs to pci config space ++ * @adapter: board private structure to initialize + * +- * This function initializes the vf specific data storage and then attempts to +- * allocate the VFs. The reason for ordering it this way is because it is much +- * mor expensive time wise to disable SR-IOV than it is to allocate and free +- * the memory for the VFs. ++ * This function initializes the vf specific data storage and then attempts to ++ * allocate the VFs. The reason for ordering it this way is because it is much ++ * mor expensive time wise to disable SR-IOV than it is to allocate and free ++ * the memory for the VFs. + **/ +-static void __devinit igb_probe_vfs(struct igb_adapter * adapter) ++static void igb_probe_vfs(struct igb_adapter *adapter) + { + #ifdef CONFIG_PCI_IOV + struct pci_dev *pdev = adapter->pdev; +- int old_vfs = igb_find_enabled_vfs(adapter); ++ struct e1000_hw *hw = &adapter->hw; ++ int old_vfs = pci_num_vf(adapter->pdev); + int i; + ++ /* Virtualization features not supported on i210 family. */ ++ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) ++ return; ++ + if (old_vfs) { + dev_info(&pdev->dev, "%d pre-allocated VFs found - override " + "max_vfs setting of %d\n", old_vfs, max_vfs); +@@ -2251,6 +2541,7 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter) + + adapter->vf_data = kcalloc(adapter->vfs_allocated_count, + sizeof(struct vf_data_storage), GFP_KERNEL); ++ + /* if allocation failed then we do not support SR-IOV */ + if (!adapter->vf_data) { + adapter->vfs_allocated_count = 0; +@@ -2281,124 +2572,19 @@ out: + } + + /** +- * igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp +- * @adapter: board private structure to initialize +- * +- * igb_init_hw_timer initializes the function pointer and values for the hw +- * timer found in hardware. +- **/ +-static void igb_init_hw_timer(struct igb_adapter *adapter) +-{ +- struct e1000_hw *hw = &adapter->hw; +- +- switch (hw->mac.type) { +- case e1000_i350: +- case e1000_82580: +- memset(&adapter->cycles, 0, sizeof(adapter->cycles)); +- adapter->cycles.read = igb_read_clock; +- adapter->cycles.mask = CLOCKSOURCE_MASK(64); +- adapter->cycles.mult = 1; +- /* +- * The 82580 timesync updates the system timer every 8ns by 8ns +- * and the value cannot be shifted. Instead we need to shift +- * the registers to generate a 64bit timer value. As a result +- * SYSTIMR/L/H, TXSTMPL/H, RXSTMPL/H all have to be shifted by +- * 24 in order to generate a larger value for synchronization. +- */ +- adapter->cycles.shift = IGB_82580_TSYNC_SHIFT; +- /* disable system timer temporarily by setting bit 31 */ +- wr32(E1000_TSAUXC, 0x80000000); +- wrfl(); +- +- /* Set registers so that rollover occurs soon to test this. */ +- wr32(E1000_SYSTIMR, 0x00000000); +- wr32(E1000_SYSTIML, 0x80000000); +- wr32(E1000_SYSTIMH, 0x000000FF); +- wrfl(); +- +- /* enable system timer by clearing bit 31 */ +- wr32(E1000_TSAUXC, 0x0); +- wrfl(); +- +- timecounter_init(&adapter->clock, +- &adapter->cycles, +- ktime_to_ns(ktime_get_real())); +- /* +- * Synchronize our NIC clock against system wall clock. NIC +- * time stamp reading requires ~3us per sample, each sample +- * was pretty stable even under load => only require 10 +- * samples for each offset comparison. +- */ +- memset(&adapter->compare, 0, sizeof(adapter->compare)); +- adapter->compare.source = &adapter->clock; +- adapter->compare.target = ktime_get_real; +- adapter->compare.num_samples = 10; +- timecompare_update(&adapter->compare, 0); +- break; +- case e1000_82576: +- /* +- * Initialize hardware timer: we keep it running just in case +- * that some program needs it later on. +- */ +- memset(&adapter->cycles, 0, sizeof(adapter->cycles)); +- adapter->cycles.read = igb_read_clock; +- adapter->cycles.mask = CLOCKSOURCE_MASK(64); +- adapter->cycles.mult = 1; +- /** +- * Scale the NIC clock cycle by a large factor so that +- * relatively small clock corrections can be added or +- * subtracted at each clock tick. The drawbacks of a large +- * factor are a) that the clock register overflows more quickly +- * (not such a big deal) and b) that the increment per tick has +- * to fit into 24 bits. As a result we need to use a shift of +- * 19 so we can fit a value of 16 into the TIMINCA register. +- */ +- adapter->cycles.shift = IGB_82576_TSYNC_SHIFT; +- wr32(E1000_TIMINCA, +- (1 << E1000_TIMINCA_16NS_SHIFT) | +- (16 << IGB_82576_TSYNC_SHIFT)); +- +- /* Set registers so that rollover occurs soon to test this. */ +- wr32(E1000_SYSTIML, 0x00000000); +- wr32(E1000_SYSTIMH, 0xFF800000); +- wrfl(); +- +- timecounter_init(&adapter->clock, +- &adapter->cycles, +- ktime_to_ns(ktime_get_real())); +- /* +- * Synchronize our NIC clock against system wall clock. NIC +- * time stamp reading requires ~3us per sample, each sample +- * was pretty stable even under load => only require 10 +- * samples for each offset comparison. +- */ +- memset(&adapter->compare, 0, sizeof(adapter->compare)); +- adapter->compare.source = &adapter->clock; +- adapter->compare.target = ktime_get_real; +- adapter->compare.num_samples = 10; +- timecompare_update(&adapter->compare, 0); +- break; +- case e1000_82575: +- /* 82575 does not support timesync */ +- default: +- break; +- } +- +-} +- +-/** +- * igb_sw_init - Initialize general software structures (struct igb_adapter) +- * @adapter: board private structure to initialize ++ * igb_sw_init - Initialize general software structures (struct igb_adapter) ++ * @adapter: board private structure to initialize + * +- * igb_sw_init initializes the Adapter private data structure. +- * Fields are initialized based on PCI device information and +- * OS network device settings (MTU size). ++ * igb_sw_init initializes the Adapter private data structure. ++ * Fields are initialized based on PCI device information and ++ * OS network device settings (MTU size). + **/ +-static int __devinit igb_sw_init(struct igb_adapter *adapter) ++static int igb_sw_init(struct igb_adapter *adapter) + { + struct e1000_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; ++ u32 max_rss_queues; + + pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); + +@@ -2417,8 +2603,6 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) + VLAN_HLEN; + adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; + +- adapter->node = -1; +- + spin_lock_init(&adapter->stats64_lock); + #ifdef CONFIG_PCI_IOV + switch (hw->mac.type) { +@@ -2427,7 +2611,7 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) + if (max_vfs > 7) { + dev_warn(&pdev->dev, + "Maximum of 7 VFs per PF, using max\n"); +- adapter->vfs_allocated_count = 7; ++ max_vfs = adapter->vfs_allocated_count = 7; + } else + adapter->vfs_allocated_count = max_vfs; + break; +@@ -2435,27 +2619,72 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) + break; + } + #endif /* CONFIG_PCI_IOV */ +- adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus()); +- /* i350 cannot do RSS and SR-IOV at the same time */ +- if (hw->mac.type == e1000_i350 && adapter->vfs_allocated_count) +- adapter->rss_queues = 1; + +- /* +- * if rss_queues > 4 or vfs are going to be allocated with rss_queues +- * then we should combine the queues into a queue pair in order to +- * conserve interrupts due to limited supply +- */ +- if ((adapter->rss_queues > 4) || +- ((adapter->rss_queues > 1) && (adapter->vfs_allocated_count > 6))) +- adapter->flags |= IGB_FLAG_QUEUE_PAIRS; ++ /* Determine the maximum number of RSS queues supported. */ ++ switch (hw->mac.type) { ++ case e1000_i211: ++ max_rss_queues = IGB_MAX_RX_QUEUES_I211; ++ break; ++ case e1000_82575: ++ case e1000_i210: ++ max_rss_queues = IGB_MAX_RX_QUEUES_82575; ++ break; ++ case e1000_i350: ++ /* I350 cannot do RSS and SR-IOV at the same time */ ++ if (!!adapter->vfs_allocated_count) { ++ max_rss_queues = 1; ++ break; ++ } ++ /* fall through */ ++ case e1000_82576: ++ if (!!adapter->vfs_allocated_count) { ++ max_rss_queues = 2; ++ break; ++ } ++ /* fall through */ ++ case e1000_82580: ++ case e1000_i354: ++ default: ++ max_rss_queues = IGB_MAX_RX_QUEUES; ++ break; ++ } ++ ++ adapter->rss_queues = min_t(u32, max_rss_queues, num_online_cpus()); ++ ++ /* Determine if we need to pair queues. */ ++ switch (hw->mac.type) { ++ case e1000_82575: ++ case e1000_i211: ++ /* Device supports enough interrupts without queue pairing. */ ++ break; ++ case e1000_82576: ++ /* If VFs are going to be allocated with RSS queues then we ++ * should pair the queues in order to conserve interrupts due ++ * to limited supply. ++ */ ++ if ((adapter->rss_queues > 1) && ++ (adapter->vfs_allocated_count > 6)) ++ adapter->flags |= IGB_FLAG_QUEUE_PAIRS; ++ /* fall through */ ++ case e1000_82580: ++ case e1000_i350: ++ case e1000_i354: ++ case e1000_i210: ++ default: ++ /* If rss_queues > half of max_rss_queues, pair the queues in ++ * order to conserve interrupts due to limited supply. ++ */ ++ if (adapter->rss_queues > (max_rss_queues / 2)) ++ adapter->flags |= IGB_FLAG_QUEUE_PAIRS; ++ break; ++ } + + /* Setup and initialize a copy of the hw vlan table array */ +- adapter->shadow_vfta = kzalloc(sizeof(u32) * +- E1000_VLAN_FILTER_TBL_SIZE, +- GFP_ATOMIC); ++ adapter->shadow_vfta = kcalloc(E1000_VLAN_FILTER_TBL_SIZE, sizeof(u32), ++ GFP_ATOMIC); + + /* This call may decrease the number of queues */ +- if (igb_init_interrupt_scheme(adapter)) { ++ if (igb_init_interrupt_scheme(adapter, true)) { + dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } +@@ -2465,7 +2694,7 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) + /* Explicitly disable IRQ since the NIC can be in any state. */ + igb_irq_disable(adapter); + +- if (hw->mac.type == e1000_i350) ++ if (hw->mac.type >= e1000_i350) + adapter->flags &= ~IGB_FLAG_DMAC; + + set_bit(__IGB_DOWN, &adapter->state); +@@ -2473,27 +2702,33 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) + } + + /** +- * igb_open - Called when a network interface is made active +- * @netdev: network interface device structure ++ * igb_open - Called when a network interface is made active ++ * @netdev: network interface device structure + * +- * Returns 0 on success, negative value on failure ++ * Returns 0 on success, negative value on failure + * +- * The open entry point is called when a network interface is made +- * active by the system (IFF_UP). At this point all resources needed +- * for transmit and receive operations are allocated, the interrupt +- * handler is registered with the OS, the watchdog timer is started, +- * and the stack is notified that the interface is ready. ++ * The open entry point is called when a network interface is made ++ * active by the system (IFF_UP). At this point all resources needed ++ * for transmit and receive operations are allocated, the interrupt ++ * handler is registered with the OS, the watchdog timer is started, ++ * and the stack is notified that the interface is ready. + **/ +-static int igb_open(struct net_device *netdev) ++static int __igb_open(struct net_device *netdev, bool resuming) + { + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; ++ struct pci_dev *pdev = adapter->pdev; + int err; + int i; + + /* disallow open during test */ +- if (test_bit(__IGB_TESTING, &adapter->state)) ++ if (test_bit(__IGB_TESTING, &adapter->state)) { ++ WARN_ON(resuming); + return -EBUSY; ++ } ++ ++ if (!resuming) ++ pm_runtime_get_sync(&pdev->dev); + + netif_carrier_off(netdev); + +@@ -2512,13 +2747,25 @@ static int igb_open(struct net_device *netdev) + /* before we allocate an interrupt, we must be ready to handle it. + * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt + * as soon as we call pci_request_irq, so we have to setup our +- * clean_rx handler before we do so. */ ++ * clean_rx handler before we do so. ++ */ + igb_configure(adapter); + + err = igb_request_irq(adapter); + if (err) + goto err_req_irq; + ++ /* Notify the stack of the actual queue counts. */ ++ err = netif_set_real_num_tx_queues(adapter->netdev, ++ adapter->num_tx_queues); ++ if (err) ++ goto err_set_queues; ++ ++ err = netif_set_real_num_rx_queues(adapter->netdev, ++ adapter->num_rx_queues); ++ if (err) ++ goto err_set_queues; ++ + /* From here on the code is the same as igb_up() */ + clear_bit(__IGB_DOWN, &adapter->state); + +@@ -2539,12 +2786,17 @@ static int igb_open(struct net_device *netdev) + + netif_tx_start_all_queues(netdev); + ++ if (!resuming) ++ pm_runtime_put(&pdev->dev); ++ + /* start the watchdog. */ + hw->mac.get_link_status = 1; + schedule_work(&adapter->watchdog_task); + + return 0; + ++err_set_queues: ++ igb_free_irq(adapter); + err_req_irq: + igb_release_hw_control(adapter); + igb_power_down_link(adapter); +@@ -2553,52 +2805,68 @@ err_setup_rx: + igb_free_all_tx_resources(adapter); + err_setup_tx: + igb_reset(adapter); ++ if (!resuming) ++ pm_runtime_put(&pdev->dev); + + return err; + } + ++static int igb_open(struct net_device *netdev) ++{ ++ return __igb_open(netdev, false); ++} ++ + /** +- * igb_close - Disables a network interface +- * @netdev: network interface device structure ++ * igb_close - Disables a network interface ++ * @netdev: network interface device structure + * +- * Returns 0, this is not allowed to fail ++ * Returns 0, this is not allowed to fail + * +- * The close entry point is called when an interface is de-activated +- * by the OS. The hardware is still under the driver's control, but +- * needs to be disabled. A global MAC reset is issued to stop the +- * hardware, and all transmit and receive resources are freed. ++ * The close entry point is called when an interface is de-activated ++ * by the OS. The hardware is still under the driver's control, but ++ * needs to be disabled. A global MAC reset is issued to stop the ++ * hardware, and all transmit and receive resources are freed. + **/ +-static int igb_close(struct net_device *netdev) ++static int __igb_close(struct net_device *netdev, bool suspending) + { + struct igb_adapter *adapter = netdev_priv(netdev); ++ struct pci_dev *pdev = adapter->pdev; + + WARN_ON(test_bit(__IGB_RESETTING, &adapter->state)); +- igb_down(adapter); + ++ if (!suspending) ++ pm_runtime_get_sync(&pdev->dev); ++ ++ igb_down(adapter); + igb_free_irq(adapter); + + igb_free_all_tx_resources(adapter); + igb_free_all_rx_resources(adapter); + ++ if (!suspending) ++ pm_runtime_put_sync(&pdev->dev); + return 0; + } + ++static int igb_close(struct net_device *netdev) ++{ ++ return __igb_close(netdev, false); ++} ++ + /** +- * igb_setup_tx_resources - allocate Tx resources (Descriptors) +- * @tx_ring: tx descriptor ring (for a specific queue) to setup ++ * igb_setup_tx_resources - allocate Tx resources (Descriptors) ++ * @tx_ring: tx descriptor ring (for a specific queue) to setup + * +- * Return 0 on success, negative on failure ++ * Return 0 on success, negative on failure + **/ + int igb_setup_tx_resources(struct igb_ring *tx_ring) + { + struct device *dev = tx_ring->dev; +- int orig_node = dev_to_node(dev); + int size; + + size = sizeof(struct igb_tx_buffer) * tx_ring->count; +- tx_ring->tx_buffer_info = vzalloc_node(size, tx_ring->numa_node); +- if (!tx_ring->tx_buffer_info) +- tx_ring->tx_buffer_info = vzalloc(size); ++ ++ tx_ring->tx_buffer_info = vzalloc(size); + if (!tx_ring->tx_buffer_info) + goto err; + +@@ -2606,18 +2874,8 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring) + tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc); + tx_ring->size = ALIGN(tx_ring->size, 4096); + +- set_dev_node(dev, tx_ring->numa_node); +- tx_ring->desc = dma_alloc_coherent(dev, +- tx_ring->size, +- &tx_ring->dma, +- GFP_KERNEL); +- set_dev_node(dev, orig_node); +- if (!tx_ring->desc) +- tx_ring->desc = dma_alloc_coherent(dev, +- tx_ring->size, +- &tx_ring->dma, +- GFP_KERNEL); +- ++ tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size, ++ &tx_ring->dma, GFP_KERNEL); + if (!tx_ring->desc) + goto err; + +@@ -2628,17 +2886,17 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring) + + err: + vfree(tx_ring->tx_buffer_info); +- dev_err(dev, +- "Unable to allocate memory for the transmit descriptor ring\n"); ++ tx_ring->tx_buffer_info = NULL; ++ dev_err(dev, "Unable to allocate memory for the Tx descriptor ring\n"); + return -ENOMEM; + } + + /** +- * igb_setup_all_tx_resources - wrapper to allocate Tx resources +- * (Descriptors) for all queues +- * @adapter: board private structure ++ * igb_setup_all_tx_resources - wrapper to allocate Tx resources ++ * (Descriptors) for all queues ++ * @adapter: board private structure + * +- * Return 0 on success, negative on failure ++ * Return 0 on success, negative on failure + **/ + static int igb_setup_all_tx_resources(struct igb_adapter *adapter) + { +@@ -2660,8 +2918,8 @@ static int igb_setup_all_tx_resources(struct igb_adapter *adapter) + } + + /** +- * igb_setup_tctl - configure the transmit control registers +- * @adapter: Board private structure ++ * igb_setup_tctl - configure the transmit control registers ++ * @adapter: Board private structure + **/ + void igb_setup_tctl(struct igb_adapter *adapter) + { +@@ -2686,11 +2944,11 @@ void igb_setup_tctl(struct igb_adapter *adapter) + } + + /** +- * igb_configure_tx_ring - Configure transmit ring after Reset +- * @adapter: board private structure +- * @ring: tx ring to configure ++ * igb_configure_tx_ring - Configure transmit ring after Reset ++ * @adapter: board private structure ++ * @ring: tx ring to configure + * +- * Configure a transmit ring after a reset. ++ * Configure a transmit ring after a reset. + **/ + void igb_configure_tx_ring(struct igb_adapter *adapter, + struct igb_ring *ring) +@@ -2706,9 +2964,9 @@ void igb_configure_tx_ring(struct igb_adapter *adapter, + mdelay(10); + + wr32(E1000_TDLEN(reg_idx), +- ring->count * sizeof(union e1000_adv_tx_desc)); ++ ring->count * sizeof(union e1000_adv_tx_desc)); + wr32(E1000_TDBAL(reg_idx), +- tdba & 0x00000000ffffffffULL); ++ tdba & 0x00000000ffffffffULL); + wr32(E1000_TDBAH(reg_idx), tdba >> 32); + + ring->tail = hw->hw_addr + E1000_TDT(reg_idx); +@@ -2724,10 +2982,10 @@ void igb_configure_tx_ring(struct igb_adapter *adapter, + } + + /** +- * igb_configure_tx - Configure transmit Unit after Reset +- * @adapter: board private structure ++ * igb_configure_tx - Configure transmit Unit after Reset ++ * @adapter: board private structure + * +- * Configure the Tx unit of the MAC after a reset. ++ * Configure the Tx unit of the MAC after a reset. + **/ + static void igb_configure_tx(struct igb_adapter *adapter) + { +@@ -2738,45 +2996,32 @@ static void igb_configure_tx(struct igb_adapter *adapter) + } + + /** +- * igb_setup_rx_resources - allocate Rx resources (Descriptors) +- * @rx_ring: rx descriptor ring (for a specific queue) to setup ++ * igb_setup_rx_resources - allocate Rx resources (Descriptors) ++ * @rx_ring: Rx descriptor ring (for a specific queue) to setup + * +- * Returns 0 on success, negative on failure ++ * Returns 0 on success, negative on failure + **/ + int igb_setup_rx_resources(struct igb_ring *rx_ring) + { + struct device *dev = rx_ring->dev; +- int orig_node = dev_to_node(dev); +- int size, desc_len; ++ int size; + + size = sizeof(struct igb_rx_buffer) * rx_ring->count; +- rx_ring->rx_buffer_info = vzalloc_node(size, rx_ring->numa_node); +- if (!rx_ring->rx_buffer_info) +- rx_ring->rx_buffer_info = vzalloc(size); ++ ++ rx_ring->rx_buffer_info = vzalloc(size); + if (!rx_ring->rx_buffer_info) + goto err; + +- desc_len = sizeof(union e1000_adv_rx_desc); +- + /* Round up to nearest 4K */ +- rx_ring->size = rx_ring->count * desc_len; ++ rx_ring->size = rx_ring->count * sizeof(union e1000_adv_rx_desc); + rx_ring->size = ALIGN(rx_ring->size, 4096); + +- set_dev_node(dev, rx_ring->numa_node); +- rx_ring->desc = dma_alloc_coherent(dev, +- rx_ring->size, +- &rx_ring->dma, +- GFP_KERNEL); +- set_dev_node(dev, orig_node); +- if (!rx_ring->desc) +- rx_ring->desc = dma_alloc_coherent(dev, +- rx_ring->size, +- &rx_ring->dma, +- GFP_KERNEL); +- ++ rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size, ++ &rx_ring->dma, GFP_KERNEL); + if (!rx_ring->desc) + goto err; + ++ rx_ring->next_to_alloc = 0; + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + +@@ -2785,17 +3030,16 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring) + err: + vfree(rx_ring->rx_buffer_info); + rx_ring->rx_buffer_info = NULL; +- dev_err(dev, "Unable to allocate memory for the receive descriptor" +- " ring\n"); ++ dev_err(dev, "Unable to allocate memory for the Rx descriptor ring\n"); + return -ENOMEM; + } + + /** +- * igb_setup_all_rx_resources - wrapper to allocate Rx resources +- * (Descriptors) for all queues +- * @adapter: board private structure ++ * igb_setup_all_rx_resources - wrapper to allocate Rx resources ++ * (Descriptors) for all queues ++ * @adapter: board private structure + * +- * Return 0 on success, negative on failure ++ * Return 0 on success, negative on failure + **/ + static int igb_setup_all_rx_resources(struct igb_adapter *adapter) + { +@@ -2817,68 +3061,43 @@ static int igb_setup_all_rx_resources(struct igb_adapter *adapter) + } + + /** +- * igb_setup_mrqc - configure the multiple receive queue control registers +- * @adapter: Board private structure ++ * igb_setup_mrqc - configure the multiple receive queue control registers ++ * @adapter: Board private structure + **/ + static void igb_setup_mrqc(struct igb_adapter *adapter) + { + struct e1000_hw *hw = &adapter->hw; + u32 mrqc, rxcsum; +- u32 j, num_rx_queues, shift = 0, shift2 = 0; +- union e1000_reta { +- u32 dword; +- u8 bytes[4]; +- } reta; +- static const u8 rsshash[40] = { +- 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, 0x41, 0x67, +- 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, 0xd0, 0xca, 0x2b, 0xcb, +- 0xae, 0x7b, 0x30, 0xb4, 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, +- 0xf2, 0x0c, 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa }; ++ u32 j, num_rx_queues; ++ static const u32 rsskey[10] = { 0xDA565A6D, 0xC20E5B25, 0x3D256741, ++ 0xB08FA343, 0xCB2BCAD0, 0xB4307BAE, ++ 0xA32DCB77, 0x0CF23080, 0x3BB7426A, ++ 0xFA01ACBE }; + + /* Fill out hash function seeds */ +- for (j = 0; j < 10; j++) { +- u32 rsskey = rsshash[(j * 4)]; +- rsskey |= rsshash[(j * 4) + 1] << 8; +- rsskey |= rsshash[(j * 4) + 2] << 16; +- rsskey |= rsshash[(j * 4) + 3] << 24; +- array_wr32(E1000_RSSRK(0), j, rsskey); +- } ++ for (j = 0; j < 10; j++) ++ wr32(E1000_RSSRK(j), rsskey[j]); + + num_rx_queues = adapter->rss_queues; + +- if (adapter->vfs_allocated_count) { +- /* 82575 and 82576 supports 2 RSS queues for VMDq */ +- switch (hw->mac.type) { +- case e1000_i350: +- case e1000_82580: +- num_rx_queues = 1; +- shift = 0; +- break; +- case e1000_82576: +- shift = 3; ++ switch (hw->mac.type) { ++ case e1000_82576: ++ /* 82576 supports 2 RSS queues for SR-IOV */ ++ if (adapter->vfs_allocated_count) + num_rx_queues = 2; +- break; +- case e1000_82575: +- shift = 2; +- shift2 = 6; +- default: +- break; +- } +- } else { +- if (hw->mac.type == e1000_82575) +- shift = 6; ++ break; ++ default: ++ break; + } + +- for (j = 0; j < (32 * 4); j++) { +- reta.bytes[j & 3] = (j % num_rx_queues) << shift; +- if (shift2) +- reta.bytes[j & 3] |= num_rx_queues << shift2; +- if ((j & 3) == 3) +- wr32(E1000_RETA(j >> 2), reta.dword); ++ if (adapter->rss_indir_tbl_init != num_rx_queues) { ++ for (j = 0; j < IGB_RETA_SIZE; j++) ++ adapter->rss_indir_tbl[j] = (j * num_rx_queues) / IGB_RETA_SIZE; ++ adapter->rss_indir_tbl_init = num_rx_queues; + } ++ igb_write_rss_indir_tbl(adapter); + +- /* +- * Disable raw packet checksumming so that RSS hash is placed in ++ /* Disable raw packet checksumming so that RSS hash is placed in + * descriptor on writeback. No need to enable TCP/UDP/IP checksum + * offloads as they are enabled by default + */ +@@ -2892,9 +3111,24 @@ static void igb_setup_mrqc(struct igb_adapter *adapter) + /* Don't need to set TUOFL or IPOFL, they default to 1 */ + wr32(E1000_RXCSUM, rxcsum); + ++ /* Generate RSS hash based on packet types, TCP/UDP ++ * port numbers and/or IPv4/v6 src and dst addresses ++ */ ++ mrqc = E1000_MRQC_RSS_FIELD_IPV4 | ++ E1000_MRQC_RSS_FIELD_IPV4_TCP | ++ E1000_MRQC_RSS_FIELD_IPV6 | ++ E1000_MRQC_RSS_FIELD_IPV6_TCP | ++ E1000_MRQC_RSS_FIELD_IPV6_TCP_EX; ++ ++ if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP) ++ mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP; ++ if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP) ++ mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP; ++ + /* If VMDq is enabled then we set the appropriate mode for that, else + * we default to RSS so that an RSS hash is calculated per packet even +- * if we are only using one queue */ ++ * if we are only using one queue ++ */ + if (adapter->vfs_allocated_count) { + if (hw->mac.type > e1000_82575) { + /* Set the default pool for the PF's first queue */ +@@ -2906,31 +3140,21 @@ static void igb_setup_mrqc(struct igb_adapter *adapter) + wr32(E1000_VT_CTL, vtctl); + } + if (adapter->rss_queues > 1) +- mrqc = E1000_MRQC_ENABLE_VMDQ_RSS_2Q; ++ mrqc |= E1000_MRQC_ENABLE_VMDQ_RSS_2Q; + else +- mrqc = E1000_MRQC_ENABLE_VMDQ; ++ mrqc |= E1000_MRQC_ENABLE_VMDQ; + } else { +- mrqc = E1000_MRQC_ENABLE_RSS_4Q; ++ if (hw->mac.type != e1000_i211) ++ mrqc |= E1000_MRQC_ENABLE_RSS_4Q; + } + igb_vmm_control(adapter); + +- /* +- * Generate RSS hash based on TCP port numbers and/or +- * IPv4/v6 src and dst addresses since UDP cannot be +- * hashed reliably due to IP fragmentation +- */ +- mrqc |= E1000_MRQC_RSS_FIELD_IPV4 | +- E1000_MRQC_RSS_FIELD_IPV4_TCP | +- E1000_MRQC_RSS_FIELD_IPV6 | +- E1000_MRQC_RSS_FIELD_IPV6_TCP | +- E1000_MRQC_RSS_FIELD_IPV6_TCP_EX; +- + wr32(E1000_MRQC, mrqc); + } + + /** +- * igb_setup_rctl - configure the receive control registers +- * @adapter: Board private structure ++ * igb_setup_rctl - configure the receive control registers ++ * @adapter: Board private structure + **/ + void igb_setup_rctl(struct igb_adapter *adapter) + { +@@ -2945,8 +3169,7 @@ void igb_setup_rctl(struct igb_adapter *adapter) + rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF | + (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT); + +- /* +- * enable stripping of CRC. It's unlikely this will break BMC ++ /* enable stripping of CRC. It's unlikely this will break BMC + * redirection as it did with e1000. Newer features require + * that the HW strips the CRC. + */ +@@ -2980,7 +3203,8 @@ static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size, + u32 vmolr; + + /* if it isn't the PF check to see if VFs are enabled and +- * increase the size to support vlan tags */ ++ * increase the size to support vlan tags ++ */ + if (vfn < adapter->vfs_allocated_count && + adapter->vf_data[vfn].vlans_enabled) + size += VLAN_TAG_SIZE; +@@ -2994,10 +3218,10 @@ static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size, + } + + /** +- * igb_rlpml_set - set maximum receive packet size +- * @adapter: board private structure ++ * igb_rlpml_set - set maximum receive packet size ++ * @adapter: board private structure + * +- * Configure maximum receivable packet size. ++ * Configure maximum receivable packet size. + **/ + static void igb_rlpml_set(struct igb_adapter *adapter) + { +@@ -3007,8 +3231,7 @@ static void igb_rlpml_set(struct igb_adapter *adapter) + + if (pf_id) { + igb_set_vf_rlpml(adapter, max_frame_size, pf_id); +- /* +- * If we're in VMDQ or SR-IOV mode, then set global RLPML ++ /* If we're in VMDQ or SR-IOV mode, then set global RLPML + * to our max jumbo frame size, in case we need to enable + * jumbo frames on one of the rings later. + * This will not pass over-length frames into the default +@@ -3026,17 +3249,16 @@ static inline void igb_set_vmolr(struct igb_adapter *adapter, + struct e1000_hw *hw = &adapter->hw; + u32 vmolr; + +- /* +- * This register exists only on 82576 and newer so if we are older then ++ /* This register exists only on 82576 and newer so if we are older then + * we should exit and do nothing + */ + if (hw->mac.type < e1000_82576) + return; + + vmolr = rd32(E1000_VMOLR(vfn)); +- vmolr |= E1000_VMOLR_STRVLAN; /* Strip vlan tags */ ++ vmolr |= E1000_VMOLR_STRVLAN; /* Strip vlan tags */ + if (aupe) +- vmolr |= E1000_VMOLR_AUPE; /* Accept untagged packets */ ++ vmolr |= E1000_VMOLR_AUPE; /* Accept untagged packets */ + else + vmolr &= ~(E1000_VMOLR_AUPE); /* Tagged packets ONLY */ + +@@ -3045,25 +3267,24 @@ static inline void igb_set_vmolr(struct igb_adapter *adapter, + + if (adapter->rss_queues > 1 && vfn == adapter->vfs_allocated_count) + vmolr |= E1000_VMOLR_RSSE; /* enable RSS */ +- /* +- * for VMDq only allow the VFs and pool 0 to accept broadcast and ++ /* for VMDq only allow the VFs and pool 0 to accept broadcast and + * multicast packets + */ + if (vfn <= adapter->vfs_allocated_count) +- vmolr |= E1000_VMOLR_BAM; /* Accept broadcast */ ++ vmolr |= E1000_VMOLR_BAM; /* Accept broadcast */ + + wr32(E1000_VMOLR(vfn), vmolr); + } + + /** +- * igb_configure_rx_ring - Configure a receive ring after Reset +- * @adapter: board private structure +- * @ring: receive ring to be configured ++ * igb_configure_rx_ring - Configure a receive ring after Reset ++ * @adapter: board private structure ++ * @ring: receive ring to be configured + * +- * Configure the Rx unit of the MAC after a reset. ++ * Configure the Rx unit of the MAC after a reset. + **/ + void igb_configure_rx_ring(struct igb_adapter *adapter, +- struct igb_ring *ring) ++ struct igb_ring *ring) + { + struct e1000_hw *hw = &adapter->hw; + u64 rdba = ring->dma; +@@ -3078,7 +3299,7 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, + rdba & 0x00000000ffffffffULL); + wr32(E1000_RDBAH(reg_idx), rdba >> 32); + wr32(E1000_RDLEN(reg_idx), +- ring->count * sizeof(union e1000_adv_rx_desc)); ++ ring->count * sizeof(union e1000_adv_rx_desc)); + + /* initialize head and tail */ + ring->tail = hw->hw_addr + E1000_RDT(reg_idx); +@@ -3087,14 +3308,12 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, + + /* set descriptor configuration */ + srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT; +-#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384 +- srrctl |= IGB_RXBUFFER_16384 >> E1000_SRRCTL_BSIZEPKT_SHIFT; +-#else +- srrctl |= (PAGE_SIZE / 2) >> E1000_SRRCTL_BSIZEPKT_SHIFT; +-#endif +- srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS; ++ srrctl |= IGB_RX_BUFSZ >> E1000_SRRCTL_BSIZEPKT_SHIFT; ++ srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; ++#ifdef CONFIG_IGB_PTP + if (hw->mac.type >= e1000_82580) + srrctl |= E1000_SRRCTL_TIMESTAMP; ++#endif /* CONFIG_IGB_PTP */ + /* Only set Drop Enable if we are supporting multiple queues */ + if (adapter->vfs_allocated_count || adapter->num_rx_queues > 1) + srrctl |= E1000_SRRCTL_DROP_EN; +@@ -3114,10 +3333,10 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, + } + + /** +- * igb_configure_rx - Configure receive Unit after Reset +- * @adapter: board private structure ++ * igb_configure_rx - Configure receive Unit after Reset ++ * @adapter: board private structure + * +- * Configure the Rx unit of the MAC after a reset. ++ * Configure the Rx unit of the MAC after a reset. + **/ + static void igb_configure_rx(struct igb_adapter *adapter) + { +@@ -3128,19 +3347,20 @@ static void igb_configure_rx(struct igb_adapter *adapter) + + /* set the correct pool for the PF default MAC address in entry 0 */ + igb_rar_set_qsel(adapter, adapter->hw.mac.addr, 0, +- adapter->vfs_allocated_count); ++ adapter->vfs_allocated_count); + + /* Setup the HW Rx Head and Tail Descriptor Pointers and +- * the Base and Length of the Rx Descriptor Ring */ ++ * the Base and Length of the Rx Descriptor Ring ++ */ + for (i = 0; i < adapter->num_rx_queues; i++) + igb_configure_rx_ring(adapter, adapter->rx_ring[i]); + } + + /** +- * igb_free_tx_resources - Free Tx Resources per Queue +- * @tx_ring: Tx descriptor ring for a specific queue ++ * igb_free_tx_resources - Free Tx Resources per Queue ++ * @tx_ring: Tx descriptor ring for a specific queue + * +- * Free all transmit software resources ++ * Free all transmit software resources + **/ + void igb_free_tx_resources(struct igb_ring *tx_ring) + { +@@ -3160,10 +3380,10 @@ void igb_free_tx_resources(struct igb_ring *tx_ring) + } + + /** +- * igb_free_all_tx_resources - Free Tx Resources for All Queues +- * @adapter: board private structure ++ * igb_free_all_tx_resources - Free Tx Resources for All Queues ++ * @adapter: board private structure + * +- * Free all transmit software resources ++ * Free all transmit software resources + **/ + static void igb_free_all_tx_resources(struct igb_adapter *adapter) + { +@@ -3178,26 +3398,26 @@ void igb_unmap_and_free_tx_resource(struct igb_ring *ring, + { + if (tx_buffer->skb) { + dev_kfree_skb_any(tx_buffer->skb); +- if (tx_buffer->dma) ++ if (dma_unmap_len(tx_buffer, len)) + dma_unmap_single(ring->dev, +- tx_buffer->dma, +- tx_buffer->length, ++ dma_unmap_addr(tx_buffer, dma), ++ dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); +- } else if (tx_buffer->dma) { ++ } else if (dma_unmap_len(tx_buffer, len)) { + dma_unmap_page(ring->dev, +- tx_buffer->dma, +- tx_buffer->length, ++ dma_unmap_addr(tx_buffer, dma), ++ dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); + } + tx_buffer->next_to_watch = NULL; + tx_buffer->skb = NULL; +- tx_buffer->dma = 0; ++ dma_unmap_len_set(tx_buffer, len, 0); + /* buffer_info must be completely set up in the transmit path */ + } + + /** +- * igb_clean_tx_ring - Free Tx Buffers +- * @tx_ring: ring to be cleaned ++ * igb_clean_tx_ring - Free Tx Buffers ++ * @tx_ring: ring to be cleaned + **/ + static void igb_clean_tx_ring(struct igb_ring *tx_ring) + { +@@ -3214,6 +3434,8 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring) + igb_unmap_and_free_tx_resource(tx_ring, buffer_info); + } + ++ netdev_tx_reset_queue(txring_txq(tx_ring)); ++ + size = sizeof(struct igb_tx_buffer) * tx_ring->count; + memset(tx_ring->tx_buffer_info, 0, size); + +@@ -3225,8 +3447,8 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring) + } + + /** +- * igb_clean_all_tx_rings - Free Tx Buffers for all queues +- * @adapter: board private structure ++ * igb_clean_all_tx_rings - Free Tx Buffers for all queues ++ * @adapter: board private structure + **/ + static void igb_clean_all_tx_rings(struct igb_adapter *adapter) + { +@@ -3237,10 +3459,10 @@ static void igb_clean_all_tx_rings(struct igb_adapter *adapter) + } + + /** +- * igb_free_rx_resources - Free Rx Resources +- * @rx_ring: ring to clean the resources from ++ * igb_free_rx_resources - Free Rx Resources ++ * @rx_ring: ring to clean the resources from + * +- * Free all receive software resources ++ * Free all receive software resources + **/ + void igb_free_rx_resources(struct igb_ring *rx_ring) + { +@@ -3260,10 +3482,10 @@ void igb_free_rx_resources(struct igb_ring *rx_ring) + } + + /** +- * igb_free_all_rx_resources - Free Rx Resources for All Queues +- * @adapter: board private structure ++ * igb_free_all_rx_resources - Free Rx Resources for All Queues ++ * @adapter: board private structure + * +- * Free all receive software resources ++ * Free all receive software resources + **/ + static void igb_free_all_rx_resources(struct igb_adapter *adapter) + { +@@ -3274,44 +3496,35 @@ static void igb_free_all_rx_resources(struct igb_adapter *adapter) + } + + /** +- * igb_clean_rx_ring - Free Rx Buffers per Queue +- * @rx_ring: ring to free buffers from ++ * igb_clean_rx_ring - Free Rx Buffers per Queue ++ * @rx_ring: ring to free buffers from + **/ + static void igb_clean_rx_ring(struct igb_ring *rx_ring) + { + unsigned long size; + u16 i; + ++ if (rx_ring->skb) ++ dev_kfree_skb(rx_ring->skb); ++ rx_ring->skb = NULL; ++ + if (!rx_ring->rx_buffer_info) + return; + + /* Free all the Rx ring sk_buffs */ + for (i = 0; i < rx_ring->count; i++) { + struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i]; +- if (buffer_info->dma) { +- dma_unmap_single(rx_ring->dev, +- buffer_info->dma, +- IGB_RX_HDR_LEN, +- DMA_FROM_DEVICE); +- buffer_info->dma = 0; +- } + +- if (buffer_info->skb) { +- dev_kfree_skb(buffer_info->skb); +- buffer_info->skb = NULL; +- } +- if (buffer_info->page_dma) { +- dma_unmap_page(rx_ring->dev, +- buffer_info->page_dma, +- PAGE_SIZE / 2, +- DMA_FROM_DEVICE); +- buffer_info->page_dma = 0; +- } +- if (buffer_info->page) { +- put_page(buffer_info->page); +- buffer_info->page = NULL; +- buffer_info->page_offset = 0; +- } ++ if (!buffer_info->page) ++ continue; ++ ++ dma_unmap_page(rx_ring->dev, ++ buffer_info->dma, ++ PAGE_SIZE, ++ DMA_FROM_DEVICE); ++ __free_page(buffer_info->page); ++ ++ buffer_info->page = NULL; + } + + size = sizeof(struct igb_rx_buffer) * rx_ring->count; +@@ -3320,13 +3533,14 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring) + /* Zero out the descriptor ring */ + memset(rx_ring->desc, 0, rx_ring->size); + ++ rx_ring->next_to_alloc = 0; + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + } + + /** +- * igb_clean_all_rx_rings - Free Rx Buffers for all queues +- * @adapter: board private structure ++ * igb_clean_all_rx_rings - Free Rx Buffers for all queues ++ * @adapter: board private structure + **/ + static void igb_clean_all_rx_rings(struct igb_adapter *adapter) + { +@@ -3337,11 +3551,11 @@ static void igb_clean_all_rx_rings(struct igb_adapter *adapter) + } + + /** +- * igb_set_mac - Change the Ethernet Address of the NIC +- * @netdev: network interface device structure +- * @p: pointer to an address structure ++ * igb_set_mac - Change the Ethernet Address of the NIC ++ * @netdev: network interface device structure ++ * @p: pointer to an address structure + * +- * Returns 0 on success, negative on failure ++ * Returns 0 on success, negative on failure + **/ + static int igb_set_mac(struct net_device *netdev, void *p) + { +@@ -3357,19 +3571,19 @@ static int igb_set_mac(struct net_device *netdev, void *p) + + /* set the correct pool for the new PF MAC address in entry 0 */ + igb_rar_set_qsel(adapter, hw->mac.addr, 0, +- adapter->vfs_allocated_count); ++ adapter->vfs_allocated_count); + + return 0; + } + + /** +- * igb_write_mc_addr_list - write multicast addresses to MTA +- * @netdev: network interface device structure ++ * igb_write_mc_addr_list - write multicast addresses to MTA ++ * @netdev: network interface device structure + * +- * Writes multicast address list to the MTA hash table. +- * Returns: -ENOMEM on failure +- * 0 on no addresses written +- * X on writing X addresses to MTA ++ * Writes multicast address list to the MTA hash table. ++ * Returns: -ENOMEM on failure ++ * 0 on no addresses written ++ * X on writing X addresses to MTA + **/ + static int igb_write_mc_addr_list(struct net_device *netdev) + { +@@ -3402,13 +3616,13 @@ static int igb_write_mc_addr_list(struct net_device *netdev) + } + + /** +- * igb_write_uc_addr_list - write unicast addresses to RAR table +- * @netdev: network interface device structure ++ * igb_write_uc_addr_list - write unicast addresses to RAR table ++ * @netdev: network interface device structure + * +- * Writes unicast address list to the RAR table. +- * Returns: -ENOMEM on failure/insufficient address space +- * 0 on no addresses written +- * X on writing X addresses to the RAR table ++ * Writes unicast address list to the RAR table. ++ * Returns: -ENOMEM on failure/insufficient address space ++ * 0 on no addresses written ++ * X on writing X addresses to the RAR table + **/ + static int igb_write_uc_addr_list(struct net_device *netdev) + { +@@ -3429,8 +3643,8 @@ static int igb_write_uc_addr_list(struct net_device *netdev) + if (!rar_entries) + break; + igb_rar_set_qsel(adapter, ha->addr, +- rar_entries--, +- vfn); ++ rar_entries--, ++ vfn); + count++; + } + } +@@ -3445,13 +3659,13 @@ static int igb_write_uc_addr_list(struct net_device *netdev) + } + + /** +- * igb_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set +- * @netdev: network interface device structure ++ * igb_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set ++ * @netdev: network interface device structure + * +- * The set_rx_mode entry point is called whenever the unicast or multicast +- * address lists or the network interface flags are updated. This routine is +- * responsible for configuring the hardware for proper unicast, multicast, +- * promiscuous mode, and all-multi behavior. ++ * The set_rx_mode entry point is called whenever the unicast or multicast ++ * address lists or the network interface flags are updated. This routine is ++ * responsible for configuring the hardware for proper unicast, multicast, ++ * promiscuous mode, and all-multi behavior. + **/ + static void igb_set_rx_mode(struct net_device *netdev) + { +@@ -3468,6 +3682,9 @@ static void igb_set_rx_mode(struct net_device *netdev) + rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_VFE); + + if (netdev->flags & IFF_PROMISC) { ++ /* retain VLAN HW filtering if in VT mode */ ++ if (adapter->vfs_allocated_count) ++ rctl |= E1000_RCTL_VFE; + rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); + vmolr |= (E1000_VMOLR_ROPE | E1000_VMOLR_MPME); + } else { +@@ -3475,8 +3692,7 @@ static void igb_set_rx_mode(struct net_device *netdev) + rctl |= E1000_RCTL_MPE; + vmolr |= E1000_VMOLR_MPME; + } else { +- /* +- * Write addresses to the MTA, if the attempt fails ++ /* Write addresses to the MTA, if the attempt fails + * then we should just turn on promiscuous mode so + * that we can at least receive multicast traffic + */ +@@ -3488,8 +3704,7 @@ static void igb_set_rx_mode(struct net_device *netdev) + vmolr |= E1000_VMOLR_ROMPE; + } + } +- /* +- * Write addresses to available RAR registers, if there is not ++ /* Write addresses to available RAR registers, if there is not + * sufficient space to store all the addresses then enable + * unicast promiscuous mode + */ +@@ -3502,17 +3717,16 @@ static void igb_set_rx_mode(struct net_device *netdev) + } + wr32(E1000_RCTL, rctl); + +- /* +- * In order to support SR-IOV and eventually VMDq it is necessary to set ++ /* In order to support SR-IOV and eventually VMDq it is necessary to set + * the VMOLR to enable the appropriate modes. Without this workaround + * we will have issues with VLAN tag stripping not being done for frames + * that are only arriving because we are the default pool + */ +- if (hw->mac.type < e1000_82576) ++ if ((hw->mac.type < e1000_82576) || (hw->mac.type > e1000_i350)) + return; + + vmolr |= rd32(E1000_VMOLR(vfn)) & +- ~(E1000_VMOLR_ROPE | E1000_VMOLR_MPME | E1000_VMOLR_ROMPE); ++ ~(E1000_VMOLR_ROPE | E1000_VMOLR_MPME | E1000_VMOLR_ROMPE); + wr32(E1000_VMOLR(vfn), vmolr); + igb_restore_vf_multicasts(adapter); + } +@@ -3557,7 +3771,8 @@ static void igb_spoof_check(struct igb_adapter *adapter) + } + + /* Need to wait a few seconds after link up to get diagnostic information from +- * the phy */ ++ * the phy ++ */ + static void igb_update_phy_info(unsigned long data) + { + struct igb_adapter *adapter = (struct igb_adapter *) data; +@@ -3565,14 +3780,13 @@ static void igb_update_phy_info(unsigned long data) + } + + /** +- * igb_has_link - check shared code for link and determine up/down +- * @adapter: pointer to driver private info ++ * igb_has_link - check shared code for link and determine up/down ++ * @adapter: pointer to driver private info + **/ + bool igb_has_link(struct igb_adapter *adapter) + { + struct e1000_hw *hw = &adapter->hw; + bool link_active = false; +- s32 ret_val = 0; + + /* get_link_status is set on LSC (link status) interrupt or + * rx sequence error interrupt. get_link_status will stay +@@ -3581,22 +3795,28 @@ bool igb_has_link(struct igb_adapter *adapter) + */ + switch (hw->phy.media_type) { + case e1000_media_type_copper: +- if (hw->mac.get_link_status) { +- ret_val = hw->mac.ops.check_for_link(hw); +- link_active = !hw->mac.get_link_status; +- } else { +- link_active = true; +- } +- break; ++ if (!hw->mac.get_link_status) ++ return true; + case e1000_media_type_internal_serdes: +- ret_val = hw->mac.ops.check_for_link(hw); +- link_active = hw->mac.serdes_has_link; ++ hw->mac.ops.check_for_link(hw); ++ link_active = !hw->mac.get_link_status; + break; + default: + case e1000_media_type_unknown: + break; + } + ++ if (((hw->mac.type == e1000_i210) || ++ (hw->mac.type == e1000_i211)) && ++ (hw->phy.id == I210_I_PHY_ID)) { ++ if (!netif_carrier_ok(adapter->netdev)) { ++ adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; ++ } else if (!(adapter->flags & IGB_FLAG_NEED_LINK_UPDATE)) { ++ adapter->flags |= IGB_FLAG_NEED_LINK_UPDATE; ++ adapter->link_check_timeout = jiffies; ++ } ++ } ++ + return link_active; + } + +@@ -3605,23 +3825,22 @@ static bool igb_thermal_sensor_event(struct e1000_hw *hw, u32 event) + bool ret = false; + u32 ctrl_ext, thstat; + +- /* check for thermal sensor event on i350, copper only */ ++ /* check for thermal sensor event on i350 copper only */ + if (hw->mac.type == e1000_i350) { + thstat = rd32(E1000_THSTAT); + ctrl_ext = rd32(E1000_CTRL_EXT); + + if ((hw->phy.media_type == e1000_media_type_copper) && +- !(ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII)) { ++ !(ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII)) + ret = !!(thstat & event); +- } + } + + return ret; + } + + /** +- * igb_watchdog - Timer Call-back +- * @data: pointer to adapter cast into an unsigned long ++ * igb_watchdog - Timer Call-back ++ * @data: pointer to adapter cast into an unsigned long + **/ + static void igb_watchdog(unsigned long data) + { +@@ -3633,40 +3852,57 @@ static void igb_watchdog(unsigned long data) + static void igb_watchdog_task(struct work_struct *work) + { + struct igb_adapter *adapter = container_of(work, +- struct igb_adapter, +- watchdog_task); ++ struct igb_adapter, ++ watchdog_task); + struct e1000_hw *hw = &adapter->hw; ++ struct e1000_phy_info *phy = &hw->phy; + struct net_device *netdev = adapter->netdev; + u32 link; + int i; + + link = igb_has_link(adapter); ++ ++ if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) { ++ if (time_after(jiffies, (adapter->link_check_timeout + HZ))) ++ adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; ++ else ++ link = false; ++ } ++ + if (link) { ++ /* Cancel scheduled suspend requests. */ ++ pm_runtime_resume(netdev->dev.parent); ++ + if (!netif_carrier_ok(netdev)) { + u32 ctrl; + hw->mac.ops.get_speed_and_duplex(hw, +- &adapter->link_speed, +- &adapter->link_duplex); ++ &adapter->link_speed, ++ &adapter->link_duplex); + + ctrl = rd32(E1000_CTRL); + /* Links status message must follow this format */ +- printk(KERN_INFO "igb: %s NIC Link is Up %d Mbps %s, " +- "Flow Control: %s\n", ++ printk(KERN_INFO "igb: %s NIC Link is Up %d Mbps %s " ++ "Duplex, Flow Control: %s\n", + netdev->name, + adapter->link_speed, + adapter->link_duplex == FULL_DUPLEX ? +- "Full Duplex" : "Half Duplex", +- ((ctrl & E1000_CTRL_TFCE) && +- (ctrl & E1000_CTRL_RFCE)) ? "RX/TX" : +- ((ctrl & E1000_CTRL_RFCE) ? "RX" : +- ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None"))); ++ "Full" : "Half", ++ (ctrl & E1000_CTRL_TFCE) && ++ (ctrl & E1000_CTRL_RFCE) ? "RX/TX" : ++ (ctrl & E1000_CTRL_RFCE) ? "RX" : ++ (ctrl & E1000_CTRL_TFCE) ? "TX" : "None"); ++ ++ /* check if SmartSpeed worked */ ++ igb_check_downshift(hw); ++ if (phy->speed_downgraded) ++ netdev_warn(netdev, "Link Speed was downgraded by SmartSpeed\n"); + + /* check for thermal sensor event */ +- if (igb_thermal_sensor_event(hw, E1000_THSTAT_LINK_THROTTLE)) { +- printk(KERN_INFO "igb: %s The network adapter " +- "link speed was downshifted " +- "because it overheated.\n", +- netdev->name); ++ if (igb_thermal_sensor_event(hw, ++ E1000_THSTAT_LINK_THROTTLE)) { ++ netdev_info(netdev, "The network adapter link " ++ "speed was downshifted because it " ++ "overheated\n"); + } + + /* adjust timeout factor according to speed/duplex */ +@@ -3696,11 +3932,10 @@ static void igb_watchdog_task(struct work_struct *work) + adapter->link_duplex = 0; + + /* check for thermal sensor event */ +- if (igb_thermal_sensor_event(hw, E1000_THSTAT_PWR_DOWN)) { +- printk(KERN_ERR "igb: %s The network adapter " +- "was stopped because it " +- "overheated.\n", +- netdev->name); ++ if (igb_thermal_sensor_event(hw, ++ E1000_THSTAT_PWR_DOWN)) { ++ netdev_err(netdev, "The network adapter was " ++ "stopped because it overheated\n"); + } + + /* Links status message must follow this format */ +@@ -3714,6 +3949,9 @@ static void igb_watchdog_task(struct work_struct *work) + if (!test_bit(__IGB_DOWN, &adapter->state)) + mod_timer(&adapter->phy_info_timer, + round_jiffies(jiffies + 2 * HZ)); ++ ++ pm_schedule_suspend(netdev->dev.parent, ++ MSEC_PER_SEC * 5); + } + } + +@@ -3727,7 +3965,8 @@ static void igb_watchdog_task(struct work_struct *work) + /* We've lost link, so the controller stops DMA, + * but we've got queued Tx work that's never going + * to get done, so reset controller to flush Tx. +- * (Do the reset outside of interrupt context). */ ++ * (Do the reset outside of interrupt context). ++ */ + if (igb_desc_unused(tx_ring) + 1 < tx_ring->count) { + adapter->tx_timeout_count++; + schedule_work(&adapter->reset_task); +@@ -3740,7 +3979,7 @@ static void igb_watchdog_task(struct work_struct *work) + set_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); + } + +- /* Cause software interrupt to ensure rx ring is cleaned */ ++ /* Cause software interrupt to ensure Rx ring is cleaned */ + if (adapter->msix_entries) { + u32 eics = 0; + for (i = 0; i < adapter->num_q_vectors; i++) +@@ -3751,11 +3990,19 @@ static void igb_watchdog_task(struct work_struct *work) + } + + igb_spoof_check(adapter); ++#ifdef CONFIG_IGB_PTP ++ igb_ptp_rx_hang(adapter); ++#endif + + /* Reset the timer */ +- if (!test_bit(__IGB_DOWN, &adapter->state)) +- mod_timer(&adapter->watchdog_timer, +- round_jiffies(jiffies + 2 * HZ)); ++ if (!test_bit(__IGB_DOWN, &adapter->state)) { ++ if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) ++ mod_timer(&adapter->watchdog_timer, ++ round_jiffies(jiffies + HZ)); ++ else ++ mod_timer(&adapter->watchdog_timer, ++ round_jiffies(jiffies + 2 * HZ)); ++ } + } + + enum latency_range { +@@ -3766,20 +4013,20 @@ enum latency_range { + }; + + /** +- * igb_update_ring_itr - update the dynamic ITR value based on packet size ++ * igb_update_ring_itr - update the dynamic ITR value based on packet size ++ * @q_vector: pointer to q_vector + * +- * Stores a new ITR value based on strictly on packet size. This +- * algorithm is less sophisticated than that used in igb_update_itr, +- * due to the difficulty of synchronizing statistics across multiple +- * receive rings. The divisors and thresholds used by this function +- * were determined based on theoretical maximum wire speed and testing +- * data, in order to minimize response time while increasing bulk +- * throughput. +- * This functionality is controlled by the InterruptThrottleRate module +- * parameter (see igb_param.c) +- * NOTE: This function is called only when operating in a multiqueue +- * receive environment. +- * @q_vector: pointer to q_vector ++ * Stores a new ITR value based on strictly on packet size. This ++ * algorithm is less sophisticated than that used in igb_update_itr, ++ * due to the difficulty of synchronizing statistics across multiple ++ * receive rings. The divisors and thresholds used by this function ++ * were determined based on theoretical maximum wire speed and testing ++ * data, in order to minimize response time while increasing bulk ++ * throughput. ++ * This functionality is controlled by the InterruptThrottleRate module ++ * parameter (see igb_param.c) ++ * NOTE: This function is called only when operating in a multiqueue ++ * receive environment. + **/ + static void igb_update_ring_itr(struct igb_q_vector *q_vector) + { +@@ -3840,20 +4087,21 @@ clear_counts: + } + + /** +- * igb_update_itr - update the dynamic ITR value based on statistics +- * Stores a new ITR value based on packets and byte +- * counts during the last interrupt. The advantage of per interrupt +- * computation is faster updates and more accurate ITR for the current +- * traffic pattern. Constants in this function were computed +- * based on theoretical maximum wire speed and thresholds were set based +- * on testing data as well as attempting to minimize response time +- * while increasing bulk throughput. +- * this functionality is controlled by the InterruptThrottleRate module +- * parameter (see igb_param.c) +- * NOTE: These calculations are only valid when operating in a single- +- * queue environment. +- * @q_vector: pointer to q_vector +- * @ring_container: ring info to update the itr for ++ * igb_update_itr - update the dynamic ITR value based on statistics ++ * @q_vector: pointer to q_vector ++ * @ring_container: ring info to update the itr for ++ * ++ * Stores a new ITR value based on packets and byte ++ * counts during the last interrupt. The advantage of per interrupt ++ * computation is faster updates and more accurate ITR for the current ++ * traffic pattern. Constants in this function were computed ++ * based on theoretical maximum wire speed and thresholds were set based ++ * on testing data as well as attempting to minimize response time ++ * while increasing bulk throughput. ++ * this functionality is controlled by the InterruptThrottleRate module ++ * parameter (see igb_param.c) ++ * NOTE: These calculations are only valid when operating in a single- ++ * queue environment. + **/ + static void igb_update_itr(struct igb_q_vector *q_vector, + struct igb_ring_container *ring_container) +@@ -3951,12 +4199,12 @@ set_itr_now: + if (new_itr != q_vector->itr_val) { + /* this attempts to bias the interrupt rate towards Bulk + * by adding intermediate steps when interrupt rate is +- * increasing */ ++ * increasing ++ */ + new_itr = new_itr > q_vector->itr_val ? +- max((new_itr * q_vector->itr_val) / +- (new_itr + (q_vector->itr_val >> 2)), +- new_itr) : +- new_itr; ++ max((new_itr * q_vector->itr_val) / ++ (new_itr + (q_vector->itr_val >> 2)), ++ new_itr) : new_itr; + /* Don't write the value here; it resets the adapter's + * internal timer, and causes us to delay far longer than + * we should between interrupts. Instead, we write the ITR +@@ -3968,8 +4216,8 @@ set_itr_now: + } + } + +-void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens, +- u32 type_tucmd, u32 mss_l4len_idx) ++static void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens, ++ u32 type_tucmd, u32 mss_l4len_idx) + { + struct e1000_adv_tx_context_desc *context_desc; + u16 i = tx_ring->next_to_use; +@@ -4000,6 +4248,9 @@ static int igb_tso(struct igb_ring *tx_ring, + u32 vlan_macip_lens, type_tucmd; + u32 mss_l4len_idx, l4len; + ++ if (skb->ip_summed != CHECKSUM_PARTIAL) ++ return 0; ++ + if (!skb_is_gso(skb)) + return 0; + +@@ -4080,8 +4331,8 @@ static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first) + default: + if (unlikely(net_ratelimit())) { + dev_warn(tx_ring->dev, +- "partial checksum but proto=%x!\n", +- first->protocol); ++ "partial checksum but proto=%x!\n", ++ first->protocol); + } + break; + } +@@ -4104,8 +4355,8 @@ static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first) + default: + if (unlikely(net_ratelimit())) { + dev_warn(tx_ring->dev, +- "partial checksum but l4 proto=%x!\n", +- l4_hdr); ++ "partial checksum but l4 proto=%x!\n", ++ l4_hdr); + } + break; + } +@@ -4120,24 +4371,32 @@ static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first) + igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx); + } + +-static __le32 igb_tx_cmd_type(u32 tx_flags) ++#define IGB_SET_FLAG(_input, _flag, _result) \ ++ ((_flag <= _result) ? \ ++ ((u32)(_input & _flag) * (_result / _flag)) : \ ++ ((u32)(_input & _flag) / (_flag / _result))) ++ ++static u32 igb_tx_cmd_type(struct sk_buff *skb, u32 tx_flags) + { + /* set type for advanced descriptor with frame checksum insertion */ +- __le32 cmd_type = cpu_to_le32(E1000_ADVTXD_DTYP_DATA | +- E1000_ADVTXD_DCMD_IFCS | +- E1000_ADVTXD_DCMD_DEXT); ++ u32 cmd_type = E1000_ADVTXD_DTYP_DATA | ++ E1000_ADVTXD_DCMD_DEXT | ++ E1000_ADVTXD_DCMD_IFCS; + + /* set HW vlan bit if vlan is present */ +- if (tx_flags & IGB_TX_FLAGS_VLAN) +- cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_VLE); ++ cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_VLAN, ++ (E1000_ADVTXD_DCMD_VLE)); ++ ++ /* set segmentation bits for TSO */ ++ cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSO, ++ (E1000_ADVTXD_DCMD_TSE)); + ++#ifdef CONFIG_IGB_PTP + /* set timestamp bit if present */ +- if (tx_flags & IGB_TX_FLAGS_TSTAMP) +- cmd_type |= cpu_to_le32(E1000_ADVTXD_MAC_TSTAMP); ++ cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSTAMP, ++ (E1000_ADVTXD_MAC_TSTAMP)); ++#endif /* CONFIG_IGB_PTP */ + +- /* set segmentation bits for TSO */ +- if (tx_flags & IGB_TX_FLAGS_TSO) +- cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_TSE); + + return cmd_type; + } +@@ -4148,64 +4407,61 @@ static void igb_tx_olinfo_status(struct igb_ring *tx_ring, + { + u32 olinfo_status = paylen << E1000_ADVTXD_PAYLEN_SHIFT; + +- /* 82575 requires a unique index per ring if any offload is enabled */ +- if ((tx_flags & (IGB_TX_FLAGS_CSUM | IGB_TX_FLAGS_VLAN)) && +- test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) ++ /* 82575 requires a unique index per ring */ ++ if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) + olinfo_status |= tx_ring->reg_idx << 4; + + /* insert L4 checksum */ +- if (tx_flags & IGB_TX_FLAGS_CSUM) { +- olinfo_status |= E1000_TXD_POPTS_TXSM << 8; ++ olinfo_status |= IGB_SET_FLAG(tx_flags, ++ IGB_TX_FLAGS_CSUM, ++ (E1000_TXD_POPTS_TXSM << 8)); + +- /* insert IPv4 checksum */ +- if (tx_flags & IGB_TX_FLAGS_IPV4) +- olinfo_status |= E1000_TXD_POPTS_IXSM << 8; +- } ++ /* insert IPv4 checksum */ ++ olinfo_status |= IGB_SET_FLAG(tx_flags, ++ IGB_TX_FLAGS_IPV4, ++ (E1000_TXD_POPTS_IXSM << 8)); + + tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); + } + +-/* +- * The largest size we can write to the descriptor is 65535. In order to +- * maintain a power of two alignment we have to limit ourselves to 32K. +- */ +-#define IGB_MAX_TXD_PWR 15 +-#define IGB_MAX_DATA_PER_TXD (1<skb; +- struct igb_tx_buffer *tx_buffer_info; ++ struct igb_tx_buffer *tx_buffer; + union e1000_adv_tx_desc *tx_desc; ++ struct skb_frag_struct *frag; + dma_addr_t dma; +- struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; +- unsigned int data_len = skb->data_len; +- unsigned int size = skb_headlen(skb); +- unsigned int paylen = skb->len - hdr_len; +- __le32 cmd_type; ++ unsigned int data_len, size; + u32 tx_flags = first->tx_flags; ++ u32 cmd_type = igb_tx_cmd_type(skb, tx_flags); + u16 i = tx_ring->next_to_use; + + tx_desc = IGB_TX_DESC(tx_ring, i); + +- igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, paylen); +- cmd_type = igb_tx_cmd_type(tx_flags); ++ igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, skb->len - hdr_len); ++ ++ size = skb_headlen(skb); ++ data_len = skb->data_len; + + dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE); +- if (dma_mapping_error(tx_ring->dev, dma)) +- goto dma_error; + +- /* record length, and DMA address */ +- first->length = size; +- first->dma = dma; +- tx_desc->read.buffer_addr = cpu_to_le64(dma); ++ tx_buffer = first; ++ ++ for (frag = &skb_shinfo(skb)->frags[0];; frag++) { ++ if (dma_mapping_error(tx_ring->dev, dma)) ++ goto dma_error; ++ ++ /* record length, and DMA address */ ++ dma_unmap_len_set(tx_buffer, len, size); ++ dma_unmap_addr_set(tx_buffer, dma, dma); ++ ++ tx_desc->read.buffer_addr = cpu_to_le64(dma); + +- for (;;) { + while (unlikely(size > IGB_MAX_DATA_PER_TXD)) { + tx_desc->read.cmd_type_len = +- cmd_type | cpu_to_le32(IGB_MAX_DATA_PER_TXD); ++ cpu_to_le32(cmd_type ^ IGB_MAX_DATA_PER_TXD); + + i++; + tx_desc++; +@@ -4213,18 +4469,18 @@ static void igb_tx_map(struct igb_ring *tx_ring, + tx_desc = IGB_TX_DESC(tx_ring, 0); + i = 0; + } ++ tx_desc->read.olinfo_status = 0; + + dma += IGB_MAX_DATA_PER_TXD; + size -= IGB_MAX_DATA_PER_TXD; + +- tx_desc->read.olinfo_status = 0; + tx_desc->read.buffer_addr = cpu_to_le64(dma); + } + + if (likely(!data_len)) + break; + +- tx_desc->read.cmd_type_len = cmd_type | cpu_to_le32(size); ++ tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type ^ size); + + i++; + tx_desc++; +@@ -4232,34 +4488,27 @@ static void igb_tx_map(struct igb_ring *tx_ring, + tx_desc = IGB_TX_DESC(tx_ring, 0); + i = 0; + } ++ tx_desc->read.olinfo_status = 0; + + size = skb_frag_size(frag); + data_len -= size; + + dma = skb_frag_dma_map(tx_ring->dev, frag, 0, +- size, DMA_TO_DEVICE); +- if (dma_mapping_error(tx_ring->dev, dma)) +- goto dma_error; ++ size, DMA_TO_DEVICE); + +- tx_buffer_info = &tx_ring->tx_buffer_info[i]; +- tx_buffer_info->length = size; +- tx_buffer_info->dma = dma; +- +- tx_desc->read.olinfo_status = 0; +- tx_desc->read.buffer_addr = cpu_to_le64(dma); +- +- frag++; ++ tx_buffer = &tx_ring->tx_buffer_info[i]; + } + + /* write last descriptor with RS and EOP bits */ +- cmd_type |= cpu_to_le32(size) | cpu_to_le32(IGB_TXD_DCMD); +- tx_desc->read.cmd_type_len = cmd_type; ++ cmd_type |= size | IGB_TXD_DCMD; ++ tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); ++ ++ netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); + + /* set the timestamp */ + first->time_stamp = jiffies; + +- /* +- * Force memory writes to complete before letting h/w know there ++ /* Force memory writes to complete before letting h/w know there + * are new descriptors to fetch. (Only applicable for weak-ordered + * memory model archs, such as IA-64). + * +@@ -4280,7 +4529,8 @@ static void igb_tx_map(struct igb_ring *tx_ring, + writel(i, tx_ring->tail); + + /* we need this if more than one processor can write to our tail +- * at a time, it syncronizes IO on IA64/Altix systems */ ++ * at a time, it synchronizes IO on IA64/Altix systems ++ */ + mmiowb(); + + return; +@@ -4290,9 +4540,9 @@ dma_error: + + /* clear dma mappings for failed tx_buffer_info map */ + for (;;) { +- tx_buffer_info = &tx_ring->tx_buffer_info[i]; +- igb_unmap_and_free_tx_resource(tx_ring, tx_buffer_info); +- if (tx_buffer_info == first) ++ tx_buffer = &tx_ring->tx_buffer_info[i]; ++ igb_unmap_and_free_tx_resource(tx_ring, tx_buffer); ++ if (tx_buffer == first) + break; + if (i == 0) + i = tx_ring->count; +@@ -4310,11 +4560,13 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size) + + /* Herbert's original patch had: + * smp_mb__after_netif_stop_queue(); +- * but since that doesn't exist yet, just open code it. */ ++ * but since that doesn't exist yet, just open code it. ++ */ + smp_mb(); + + /* We need to check again in a case another CPU has just +- * made room available. */ ++ * made room available. ++ */ + if (igb_desc_unused(tx_ring) < size) + return -EBUSY; + +@@ -4341,15 +4593,25 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, + struct igb_tx_buffer *first; + int tso; + u32 tx_flags = 0; ++ u16 count = TXD_USE_COUNT(skb_headlen(skb)); + __be16 protocol = vlan_get_protocol(skb); + u8 hdr_len = 0; + +- /* need: 1 descriptor per page, ++ /* need: 1 descriptor per page * PAGE_SIZE/IGB_MAX_DATA_PER_TXD, ++ * + 1 desc for skb_headlen/IGB_MAX_DATA_PER_TXD, + * + 2 desc gap to keep tail from touching head, +- * + 1 desc for skb->data, + * + 1 desc for context descriptor, +- * otherwise try next time */ +- if (igb_maybe_stop_tx(tx_ring, skb_shinfo(skb)->nr_frags + 4)) { ++ * otherwise try next time ++ */ ++ if (PAGE_SIZE > IGB_MAX_DATA_PER_TXD) { ++ unsigned short f; ++ for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) ++ count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); ++ } else { ++ count += skb_shinfo(skb)->nr_frags; ++ } ++ ++ if (igb_maybe_stop_tx(tx_ring, count + 3)) { + /* this is a hard error */ + return NETDEV_TX_BUSY; + } +@@ -4360,10 +4622,23 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, + first->bytecount = skb->len; + first->gso_segs = 1; + ++ skb_tx_timestamp(skb); ++ ++#ifdef CONFIG_IGB_PTP + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { +- skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; +- tx_flags |= IGB_TX_FLAGS_TSTAMP; ++ struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); ++ ++ if (!(adapter->ptp_tx_skb)) { ++ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; ++ tx_flags |= IGB_TX_FLAGS_TSTAMP; ++ ++ adapter->ptp_tx_skb = skb_get(skb); ++ adapter->ptp_tx_start = jiffies; ++ if (adapter->hw.mac.type == e1000_82576) ++ schedule_work(&adapter->ptp_tx_work); ++ } + } ++#endif /* CONFIG_IGB_PTP */ + + if (vlan_tx_tag_present(skb)) { + tx_flags |= IGB_TX_FLAGS_VLAN; +@@ -4383,7 +4658,7 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, + igb_tx_map(tx_ring, first, hdr_len); + + /* Make sure there is space in the ring for the next send. */ +- igb_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 4); ++ igb_maybe_stop_tx(tx_ring, DESC_NEEDED); + + return NETDEV_TX_OK; + +@@ -4419,22 +4694,22 @@ static netdev_tx_t igb_xmit_frame(struct sk_buff *skb, + return NETDEV_TX_OK; + } + +- /* +- * The minimum packet size with TCTL.PSP set is 17 so pad the skb ++ /* The minimum packet size with TCTL.PSP set is 17 so pad the skb + * in order to meet this minimum size requirement. + */ +- if (skb->len < 17) { +- if (skb_padto(skb, 17)) ++ if (unlikely(skb->len < 17)) { ++ if (skb_pad(skb, 17 - skb->len)) + return NETDEV_TX_OK; + skb->len = 17; ++ skb_set_tail_pointer(skb, 17); + } + + return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb)); + } + + /** +- * igb_tx_timeout - Respond to a Tx Hang +- * @netdev: network interface device structure ++ * igb_tx_timeout - Respond to a Tx Hang ++ * @netdev: network interface device structure + **/ + static void igb_tx_timeout(struct net_device *netdev) + { +@@ -4463,13 +4738,12 @@ static void igb_reset_task(struct work_struct *work) + } + + /** +- * igb_get_stats64 - Get System Network Statistics +- * @netdev: network interface device structure +- * @stats: rtnl_link_stats64 pointer +- * ++ * igb_get_stats64 - Get System Network Statistics ++ * @netdev: network interface device structure ++ * @stats: rtnl_link_stats64 pointer + **/ + static struct rtnl_link_stats64 *igb_get_stats64(struct net_device *netdev, +- struct rtnl_link_stats64 *stats) ++ struct rtnl_link_stats64 *stats) + { + struct igb_adapter *adapter = netdev_priv(netdev); + +@@ -4482,11 +4756,11 @@ static struct rtnl_link_stats64 *igb_get_stats64(struct net_device *netdev, + } + + /** +- * igb_change_mtu - Change the Maximum Transfer Unit +- * @netdev: network interface device structure +- * @new_mtu: new value for maximum frame size ++ * igb_change_mtu - Change the Maximum Transfer Unit ++ * @netdev: network interface device structure ++ * @new_mtu: new value for maximum frame size + * +- * Returns 0 on success, negative on failure ++ * Returns 0 on success, negative on failure + **/ + static int igb_change_mtu(struct net_device *netdev, int new_mtu) + { +@@ -4505,6 +4779,10 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu) + return -EINVAL; + } + ++ /* adjust max frame to be at least the size of a standard frame */ ++ if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN)) ++ max_frame = ETH_FRAME_LEN + ETH_FCS_LEN; ++ + while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) + msleep(1); + +@@ -4529,10 +4807,9 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu) + } + + /** +- * igb_update_stats - Update the board statistics counters +- * @adapter: board private structure ++ * igb_update_stats - Update the board statistics counters ++ * @adapter: board private structure + **/ +- + void igb_update_stats(struct igb_adapter *adapter, + struct rtnl_link_stats64 *net_stats) + { +@@ -4547,8 +4824,7 @@ void igb_update_stats(struct igb_adapter *adapter, + + #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF + +- /* +- * Prevent stats update while adapter is being reset, or if the pci ++ /* Prevent stats update while adapter is being reset, or if the pci + * connection is down. + */ + if (adapter->link_speed == 0) +@@ -4558,6 +4834,8 @@ void igb_update_stats(struct igb_adapter *adapter, + + bytes = 0; + packets = 0; ++ ++ rcu_read_lock(); + for (i = 0; i < adapter->num_rx_queues; i++) { + u32 rqdpc = rd32(E1000_RQDPC(i)); + struct igb_ring *ring = adapter->rx_ring[i]; +@@ -4593,6 +4871,7 @@ void igb_update_stats(struct igb_adapter *adapter, + } + net_stats->tx_bytes = bytes; + net_stats->tx_packets = packets; ++ rcu_read_unlock(); + + /* read stats registers */ + adapter->stats.crcerrs += rd32(E1000_CRCERRS); +@@ -4655,7 +4934,11 @@ void igb_update_stats(struct igb_adapter *adapter, + reg = rd32(E1000_CTRL_EXT); + if (!(reg & E1000_CTRL_EXT_LINK_MODE_MASK)) { + adapter->stats.rxerrc += rd32(E1000_RXERRC); +- adapter->stats.tncrs += rd32(E1000_TNCRS); ++ ++ /* this stat has invalid values on i210/i211 */ ++ if ((hw->mac.type != e1000_i210) && ++ (hw->mac.type != e1000_i211)) ++ adapter->stats.tncrs += rd32(E1000_TNCRS); + } + + adapter->stats.tsctc += rd32(E1000_TSCTC); +@@ -4678,7 +4961,8 @@ void igb_update_stats(struct igb_adapter *adapter, + /* Rx Errors */ + + /* RLEC on some newer hardware can be incorrect so build +- * our own version based on RUC and ROC */ ++ * our own version based on RUC and ROC ++ */ + net_stats->rx_errors = adapter->stats.rxerrc + + adapter->stats.crcerrs + adapter->stats.algnerrc + + adapter->stats.ruc + adapter->stats.roc + +@@ -4737,7 +5021,8 @@ static irqreturn_t igb_msix_other(int irq, void *data) + adapter->stats.doosync++; + /* The DMA Out of Sync is also indication of a spoof event + * in IOV mode. Check the Wrong VM Behavior register to +- * see if it is really a spoof event. */ ++ * see if it is really a spoof event. ++ */ + igb_check_wvbr(adapter); + } + +@@ -4752,6 +5037,19 @@ static irqreturn_t igb_msix_other(int irq, void *data) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + ++#ifdef CONFIG_IGB_PTP ++ if (icr & E1000_ICR_TS) { ++ u32 tsicr = rd32(E1000_TSICR); ++ ++ if (tsicr & E1000_TSICR_TXTS) { ++ /* acknowledge the interrupt */ ++ wr32(E1000_TSICR, E1000_TSICR_TXTS); ++ /* retrieve hardware timestamp */ ++ schedule_work(&adapter->ptp_tx_work); ++ } ++ } ++#endif /* CONFIG_IGB_PTP */ ++ + wr32(E1000_EIMS, adapter->eims_other); + + return IRQ_HANDLED; +@@ -4790,45 +5088,61 @@ static irqreturn_t igb_msix_ring(int irq, void *data) + } + + #ifdef CONFIG_IGB_DCA ++static void igb_update_tx_dca(struct igb_adapter *adapter, ++ struct igb_ring *tx_ring, ++ int cpu) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 txctrl = dca3_get_tag(tx_ring->dev, cpu); ++ ++ if (hw->mac.type != e1000_82575) ++ txctrl <<= E1000_DCA_TXCTRL_CPUID_SHIFT; ++ ++ /* We can enable relaxed ordering for reads, but not writes when ++ * DCA is enabled. This is due to a known issue in some chipsets ++ * which will cause the DCA tag to be cleared. ++ */ ++ txctrl |= E1000_DCA_TXCTRL_DESC_RRO_EN | ++ E1000_DCA_TXCTRL_DATA_RRO_EN | ++ E1000_DCA_TXCTRL_DESC_DCA_EN; ++ ++ wr32(E1000_DCA_TXCTRL(tx_ring->reg_idx), txctrl); ++} ++ ++static void igb_update_rx_dca(struct igb_adapter *adapter, ++ struct igb_ring *rx_ring, ++ int cpu) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 rxctrl = dca3_get_tag(&adapter->pdev->dev, cpu); ++ ++ if (hw->mac.type != e1000_82575) ++ rxctrl <<= E1000_DCA_RXCTRL_CPUID_SHIFT; ++ ++ /* We can enable relaxed ordering for reads, but not writes when ++ * DCA is enabled. This is due to a known issue in some chipsets ++ * which will cause the DCA tag to be cleared. ++ */ ++ rxctrl |= E1000_DCA_RXCTRL_DESC_RRO_EN | ++ E1000_DCA_RXCTRL_DESC_DCA_EN; ++ ++ wr32(E1000_DCA_RXCTRL(rx_ring->reg_idx), rxctrl); ++} ++ + static void igb_update_dca(struct igb_q_vector *q_vector) + { + struct igb_adapter *adapter = q_vector->adapter; +- struct e1000_hw *hw = &adapter->hw; + int cpu = get_cpu(); + + if (q_vector->cpu == cpu) + goto out_no_update; + +- if (q_vector->tx.ring) { +- int q = q_vector->tx.ring->reg_idx; +- u32 dca_txctrl = rd32(E1000_DCA_TXCTRL(q)); +- if (hw->mac.type == e1000_82575) { +- dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK; +- dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); +- } else { +- dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK_82576; +- dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) << +- E1000_DCA_TXCTRL_CPUID_SHIFT; +- } +- dca_txctrl |= E1000_DCA_TXCTRL_DESC_DCA_EN; +- wr32(E1000_DCA_TXCTRL(q), dca_txctrl); +- } +- if (q_vector->rx.ring) { +- int q = q_vector->rx.ring->reg_idx; +- u32 dca_rxctrl = rd32(E1000_DCA_RXCTRL(q)); +- if (hw->mac.type == e1000_82575) { +- dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK; +- dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); +- } else { +- dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576; +- dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) << +- E1000_DCA_RXCTRL_CPUID_SHIFT; +- } +- dca_rxctrl |= E1000_DCA_RXCTRL_DESC_DCA_EN; +- dca_rxctrl |= E1000_DCA_RXCTRL_HEAD_DCA_EN; +- dca_rxctrl |= E1000_DCA_RXCTRL_DATA_DCA_EN; +- wr32(E1000_DCA_RXCTRL(q), dca_rxctrl); +- } ++ if (q_vector->tx.ring) ++ igb_update_tx_dca(adapter, q_vector->tx.ring, cpu); ++ ++ if (q_vector->rx.ring) ++ igb_update_rx_dca(adapter, q_vector->rx.ring, cpu); ++ + q_vector->cpu = cpu; + out_no_update: + put_cpu(); +@@ -4874,7 +5188,8 @@ static int __igb_notify_dca(struct device *dev, void *data) + case DCA_PROVIDER_REMOVE: + if (adapter->flags & IGB_FLAG_DCA_ENABLED) { + /* without this a class_device is left +- * hanging around in the sysfs model */ ++ * hanging around in the sysfs model ++ */ + dca_remove_requester(dev); + dev_info(&pdev->dev, "DCA disabled\n"); + adapter->flags &= ~IGB_FLAG_DCA_ENABLED; +@@ -4887,12 +5202,12 @@ static int __igb_notify_dca(struct device *dev, void *data) + } + + static int igb_notify_dca(struct notifier_block *nb, unsigned long event, +- void *p) ++ void *p) + { + int ret_val; + + ret_val = driver_for_each_device(&igb_driver.driver, NULL, &event, +- __igb_notify_dca); ++ __igb_notify_dca); + + return ret_val ? NOTIFY_BAD : NOTIFY_DONE; + } +@@ -4902,102 +5217,46 @@ static int igb_notify_dca(struct notifier_block *nb, unsigned long event, + static int igb_vf_configure(struct igb_adapter *adapter, int vf) + { + unsigned char mac_addr[ETH_ALEN]; +- struct pci_dev *pdev = adapter->pdev; +- struct e1000_hw *hw = &adapter->hw; +- struct pci_dev *pvfdev; +- unsigned int device_id; +- u16 thisvf_devfn; + +- random_ether_addr(mac_addr); ++ eth_zero_addr(mac_addr); + igb_set_vf_mac(adapter, vf, mac_addr); + +- switch (adapter->hw.mac.type) { +- case e1000_82576: +- device_id = IGB_82576_VF_DEV_ID; +- /* VF Stride for 82576 is 2 */ +- thisvf_devfn = (pdev->devfn + 0x80 + (vf << 1)) | +- (pdev->devfn & 1); +- break; +- case e1000_i350: +- device_id = IGB_I350_VF_DEV_ID; +- /* VF Stride for I350 is 4 */ +- thisvf_devfn = (pdev->devfn + 0x80 + (vf << 2)) | +- (pdev->devfn & 3); +- break; +- default: +- device_id = 0; +- thisvf_devfn = 0; +- break; +- } +- +- pvfdev = pci_get_device(hw->vendor_id, device_id, NULL); +- while (pvfdev) { +- if (pvfdev->devfn == thisvf_devfn) +- break; +- pvfdev = pci_get_device(hw->vendor_id, +- device_id, pvfdev); +- } ++ /* By default spoof check is enabled for all VFs */ ++ adapter->vf_data[vf].spoofchk_enabled = true; + +- if (pvfdev) +- adapter->vf_data[vf].vfdev = pvfdev; +- else +- dev_err(&pdev->dev, +- "Couldn't find pci dev ptr for VF %4.4x\n", +- thisvf_devfn); +- return pvfdev != NULL; ++ return 0; + } + +-static int igb_find_enabled_vfs(struct igb_adapter *adapter) ++static bool igb_vfs_are_assigned(struct igb_adapter *adapter) + { +- struct e1000_hw *hw = &adapter->hw; + struct pci_dev *pdev = adapter->pdev; +- struct pci_dev *pvfdev; +- u16 vf_devfn = 0; +- u16 vf_stride; +- unsigned int device_id; +- int vfs_found = 0; ++ struct pci_dev *vfdev; ++ int dev_id; + + switch (adapter->hw.mac.type) { + case e1000_82576: +- device_id = IGB_82576_VF_DEV_ID; +- /* VF Stride for 82576 is 2 */ +- vf_stride = 2; ++ dev_id = IGB_82576_VF_DEV_ID; + break; + case e1000_i350: +- device_id = IGB_I350_VF_DEV_ID; +- /* VF Stride for I350 is 4 */ +- vf_stride = 4; ++ dev_id = IGB_I350_VF_DEV_ID; + break; + default: +- device_id = 0; +- vf_stride = 0; +- break; +- } +- +- vf_devfn = pdev->devfn + 0x80; +- pvfdev = pci_get_device(hw->vendor_id, device_id, NULL); +- while (pvfdev) { +- if (pvfdev->devfn == vf_devfn && +- (pvfdev->bus->number >= pdev->bus->number)) +- vfs_found++; +- vf_devfn += vf_stride; +- pvfdev = pci_get_device(hw->vendor_id, +- device_id, pvfdev); ++ return false; + } + +- return vfs_found; +-} +- +-static int igb_check_vf_assignment(struct igb_adapter *adapter) +-{ +- int i; +- for (i = 0; i < adapter->vfs_allocated_count; i++) { +- if (adapter->vf_data[i].vfdev) { +- if (adapter->vf_data[i].vfdev->dev_flags & +- PCI_DEV_FLAGS_ASSIGNED) ++ /* loop through all the VFs to see if we own any that are assigned */ ++ vfdev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL); ++ while (vfdev) { ++ /* if we don't own it we don't care */ ++ if (vfdev->is_virtfn && vfdev->physfn == pdev) { ++ /* if it is assigned we cannot release it */ ++ if (vfdev->dev_flags & PCI_DEV_FLAGS_ASSIGNED) + return true; + } ++ ++ vfdev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, vfdev); + } ++ + return false; + } + +@@ -5023,7 +5282,7 @@ static int igb_set_vf_promisc(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) + struct vf_data_storage *vf_data = &adapter->vf_data[vf]; + + vf_data->flags &= ~(IGB_VF_FLAG_UNI_PROMISC | +- IGB_VF_FLAG_MULTI_PROMISC); ++ IGB_VF_FLAG_MULTI_PROMISC); + vmolr &= ~(E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE | E1000_VMOLR_MPME); + + if (*msgbuf & E1000_VF_SET_PROMISC_MULTICAST) { +@@ -5031,8 +5290,7 @@ static int igb_set_vf_promisc(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) + vf_data->flags |= IGB_VF_FLAG_MULTI_PROMISC; + *msgbuf &= ~E1000_VF_SET_PROMISC_MULTICAST; + } else { +- /* +- * if we have hashes and we are clearing a multicast promisc ++ /* if we have hashes and we are clearing a multicast promisc + * flag we need to write the hashes to the MTA as this step + * was previously skipped + */ +@@ -5053,7 +5311,6 @@ static int igb_set_vf_promisc(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) + return -EINVAL; + + return 0; +- + } + + static int igb_set_vf_multicasts(struct igb_adapter *adapter, +@@ -5260,30 +5517,91 @@ static int igb_ndo_set_vf_vlan(struct net_device *netdev, + "Setting VLAN %d, QOS 0x%x on VF %d\n", vlan, qos, vf); + if (test_bit(__IGB_DOWN, &adapter->state)) { + dev_warn(&adapter->pdev->dev, +- "The VF VLAN has been set," +- " but the PF device is not up.\n"); ++ "The VF VLAN has been set, but the PF device is not up.\n"); + dev_warn(&adapter->pdev->dev, +- "Bring the PF device up before" +- " attempting to use the VF device.\n"); ++ "Bring the PF device up before attempting to use the VF device.\n"); + } + } else { + igb_vlvf_set(adapter, adapter->vf_data[vf].pf_vlan, +- false, vf); ++ false, vf); + igb_set_vmvir(adapter, vlan, vf); + igb_set_vmolr(adapter, vf, true); + adapter->vf_data[vf].pf_vlan = 0; + adapter->vf_data[vf].pf_qos = 0; +- } ++ } + out: +- return err; ++ return err; ++} ++ ++static int igb_find_vlvf_entry(struct igb_adapter *adapter, int vid) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ int i; ++ u32 reg; ++ ++ /* Find the vlan filter for this id */ ++ for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) { ++ reg = rd32(E1000_VLVF(i)); ++ if ((reg & E1000_VLVF_VLANID_ENABLE) && ++ vid == (reg & E1000_VLVF_VLANID_MASK)) ++ break; ++ } ++ ++ if (i >= E1000_VLVF_ARRAY_SIZE) ++ i = -1; ++ ++ return i; + } + + static int igb_set_vf_vlan(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) + { ++ struct e1000_hw *hw = &adapter->hw; + int add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; + int vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK); ++ int err = 0; ++ ++ /* If in promiscuous mode we need to make sure the PF also has ++ * the VLAN filter set. ++ */ ++ if (add && (adapter->netdev->flags & IFF_PROMISC)) ++ err = igb_vlvf_set(adapter, vid, add, ++ adapter->vfs_allocated_count); ++ if (err) ++ goto out; ++ ++ err = igb_vlvf_set(adapter, vid, add, vf); ++ ++ if (err) ++ goto out; ++ ++ /* Go through all the checks to see if the VLAN filter should ++ * be wiped completely. ++ */ ++ if (!add && (adapter->netdev->flags & IFF_PROMISC)) { ++ u32 vlvf, bits; ++ ++ int regndx = igb_find_vlvf_entry(adapter, vid); ++ if (regndx < 0) ++ goto out; ++ /* See if any other pools are set for this VLAN filter ++ * entry other than the PF. ++ */ ++ vlvf = bits = rd32(E1000_VLVF(regndx)); ++ bits &= 1 << (E1000_VLVF_POOLSEL_SHIFT + ++ adapter->vfs_allocated_count); ++ /* If the filter was removed then ensure PF pool bit ++ * is cleared if the PF only added itself to the pool ++ * because the PF is in promiscuous mode. ++ */ ++ if ((vlvf & VLAN_VID_MASK) == vid && ++ !test_bit(vid, adapter->active_vlans) && ++ !bits) ++ igb_vlvf_set(adapter, vid, add, ++ adapter->vfs_allocated_count); ++ } + +- return igb_vlvf_set(adapter, vid, add, vf); ++out: ++ return err; + } + + static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf) +@@ -5315,9 +5633,9 @@ static void igb_vf_reset_event(struct igb_adapter *adapter, u32 vf) + { + unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; + +- /* generate a new mac address as we were hotplug removed/added */ ++ /* clear mac address as we were hotplug removed/added */ + if (!(adapter->vf_data[vf].flags & IGB_VF_FLAG_PF_SET_MAC)) +- random_ether_addr(vf_mac); ++ eth_zero_addr(vf_mac); + + /* process remaining reset events */ + igb_vf_reset(adapter, vf); +@@ -5347,14 +5665,13 @@ static void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) + + /* reply to reset with ack and vf mac address */ + msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; +- memcpy(addr, vf_mac, 6); ++ memcpy(addr, vf_mac, ETH_ALEN); + igb_write_mbx(hw, msgbuf, 3, vf); + } + + static int igb_set_vf_mac_addr(struct igb_adapter *adapter, u32 *msg, int vf) + { +- /* +- * The VF MAC Address is stored in a packed array of bytes ++ /* The VF MAC Address is stored in a packed array of bytes + * starting at the second 32 bit word of the msg array + */ + unsigned char *addr = (char *)&msg[1]; +@@ -5403,11 +5720,9 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) + if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK)) + return; + +- /* +- * until the vf completes a reset it should not be ++ /* until the vf completes a reset it should not be + * allowed to start any configuration. + */ +- + if (msgbuf[0] == E1000_VF_RESET) { + igb_vf_reset_msg(adapter, vf); + return; +@@ -5427,9 +5742,8 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) + retval = igb_set_vf_mac_addr(adapter, msgbuf, vf); + else + dev_warn(&pdev->dev, +- "VF %d attempted to override administratively " +- "set MAC address\nReload the VF driver to " +- "resume operations\n", vf); ++ "VF %d attempted to override administratively set MAC address\nReload the VF driver to resume operations\n", ++ vf); + break; + case E1000_VF_SET_PROMISC: + retval = igb_set_vf_promisc(adapter, msgbuf, vf); +@@ -5444,9 +5758,8 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) + retval = -1; + if (vf_data->pf_vlan) + dev_warn(&pdev->dev, +- "VF %d attempted to override administratively " +- "set VLAN tag\nReload the VF driver to " +- "resume operations\n", vf); ++ "VF %d attempted to override administratively set VLAN tag\nReload the VF driver to resume operations\n", ++ vf); + else + retval = igb_set_vf_vlan(adapter, msgbuf, vf); + break; +@@ -5515,9 +5828,9 @@ static void igb_set_uta(struct igb_adapter *adapter) + } + + /** +- * igb_intr_msi - Interrupt Handler +- * @irq: interrupt number +- * @data: pointer to a network interface device structure ++ * igb_intr_msi - Interrupt Handler ++ * @irq: interrupt number ++ * @data: pointer to a network interface device structure + **/ + static irqreturn_t igb_intr_msi(int irq, void *data) + { +@@ -5543,15 +5856,28 @@ static irqreturn_t igb_intr_msi(int irq, void *data) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + ++#ifdef CONFIG_IGB_PTP ++ if (icr & E1000_ICR_TS) { ++ u32 tsicr = rd32(E1000_TSICR); ++ ++ if (tsicr & E1000_TSICR_TXTS) { ++ /* acknowledge the interrupt */ ++ wr32(E1000_TSICR, E1000_TSICR_TXTS); ++ /* retrieve hardware timestamp */ ++ schedule_work(&adapter->ptp_tx_work); ++ } ++ } ++#endif /* CONFIG_IGB_PTP */ ++ + napi_schedule(&q_vector->napi); + + return IRQ_HANDLED; + } + + /** +- * igb_intr - Legacy Interrupt Handler +- * @irq: interrupt number +- * @data: pointer to a network interface device structure ++ * igb_intr - Legacy Interrupt Handler ++ * @irq: interrupt number ++ * @data: pointer to a network interface device structure + **/ + static irqreturn_t igb_intr(int irq, void *data) + { +@@ -5559,11 +5885,13 @@ static irqreturn_t igb_intr(int irq, void *data) + struct igb_q_vector *q_vector = adapter->q_vector[0]; + struct e1000_hw *hw = &adapter->hw; + /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No +- * need for the IMC write */ ++ * need for the IMC write ++ */ + u32 icr = rd32(E1000_ICR); + + /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is +- * not set, then the adapter didn't send an interrupt */ ++ * not set, then the adapter didn't send an interrupt ++ */ + if (!(icr & E1000_ICR_INT_ASSERTED)) + return IRQ_NONE; + +@@ -5584,12 +5912,25 @@ static irqreturn_t igb_intr(int irq, void *data) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + ++#ifdef CONFIG_IGB_PTP ++ if (icr & E1000_ICR_TS) { ++ u32 tsicr = rd32(E1000_TSICR); ++ ++ if (tsicr & E1000_TSICR_TXTS) { ++ /* acknowledge the interrupt */ ++ wr32(E1000_TSICR, E1000_TSICR_TXTS); ++ /* retrieve hardware timestamp */ ++ schedule_work(&adapter->ptp_tx_work); ++ } ++ } ++#endif /* CONFIG_IGB_PTP */ ++ + napi_schedule(&q_vector->napi); + + return IRQ_HANDLED; + } + +-void igb_ring_irq_enable(struct igb_q_vector *q_vector) ++static void igb_ring_irq_enable(struct igb_q_vector *q_vector) + { + struct igb_adapter *adapter = q_vector->adapter; + struct e1000_hw *hw = &adapter->hw; +@@ -5611,15 +5952,15 @@ void igb_ring_irq_enable(struct igb_q_vector *q_vector) + } + + /** +- * igb_poll - NAPI Rx polling callback +- * @napi: napi polling structure +- * @budget: count of how many packets we should handle ++ * igb_poll - NAPI Rx polling callback ++ * @napi: napi polling structure ++ * @budget: count of how many packets we should handle + **/ + static int igb_poll(struct napi_struct *napi, int budget) + { + struct igb_q_vector *q_vector = container_of(napi, +- struct igb_q_vector, +- napi); ++ struct igb_q_vector, ++ napi); + bool clean_complete = true; + + #ifdef CONFIG_IGB_DCA +@@ -5644,74 +5985,17 @@ static int igb_poll(struct napi_struct *napi, int budget) + } + + /** +- * igb_systim_to_hwtstamp - convert system time value to hw timestamp +- * @adapter: board private structure +- * @shhwtstamps: timestamp structure to update +- * @regval: unsigned 64bit system time value. +- * +- * We need to convert the system time value stored in the RX/TXSTMP registers +- * into a hwtstamp which can be used by the upper level timestamping functions +- */ +-static void igb_systim_to_hwtstamp(struct igb_adapter *adapter, +- struct skb_shared_hwtstamps *shhwtstamps, +- u64 regval) +-{ +- u64 ns; +- +- /* +- * The 82580 starts with 1ns at bit 0 in RX/TXSTMPL, shift this up to +- * 24 to match clock shift we setup earlier. +- */ +- if (adapter->hw.mac.type >= e1000_82580) +- regval <<= IGB_82580_TSYNC_SHIFT; +- +- ns = timecounter_cyc2time(&adapter->clock, regval); +- timecompare_update(&adapter->compare, ns); +- memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); +- shhwtstamps->hwtstamp = ns_to_ktime(ns); +- shhwtstamps->syststamp = timecompare_transform(&adapter->compare, ns); +-} +- +-/** +- * igb_tx_hwtstamp - utility function which checks for TX time stamp +- * @q_vector: pointer to q_vector containing needed info +- * @buffer: pointer to igb_tx_buffer structure ++ * igb_clean_tx_irq - Reclaim resources after transmit completes ++ * @q_vector: pointer to q_vector containing needed info + * +- * If we were asked to do hardware stamping and such a time stamp is +- * available, then it must have been for this skb here because we only +- * allow only one such packet into the queue. +- */ +-static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, +- struct igb_tx_buffer *buffer_info) +-{ +- struct igb_adapter *adapter = q_vector->adapter; +- struct e1000_hw *hw = &adapter->hw; +- struct skb_shared_hwtstamps shhwtstamps; +- u64 regval; +- +- /* if skb does not support hw timestamp or TX stamp not valid exit */ +- if (likely(!(buffer_info->tx_flags & IGB_TX_FLAGS_TSTAMP)) || +- !(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID)) +- return; +- +- regval = rd32(E1000_TXSTMPL); +- regval |= (u64)rd32(E1000_TXSTMPH) << 32; +- +- igb_systim_to_hwtstamp(adapter, &shhwtstamps, regval); +- skb_tstamp_tx(buffer_info->skb, &shhwtstamps); +-} +- +-/** +- * igb_clean_tx_irq - Reclaim resources after transmit completes +- * @q_vector: pointer to q_vector containing needed info +- * returns true if ring is completely cleaned ++ * returns true if ring is completely cleaned + **/ + static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) + { + struct igb_adapter *adapter = q_vector->adapter; + struct igb_ring *tx_ring = q_vector->tx.ring; + struct igb_tx_buffer *tx_buffer; +- union e1000_adv_tx_desc *tx_desc, *eop_desc; ++ union e1000_adv_tx_desc *tx_desc; + unsigned int total_bytes = 0, total_packets = 0; + unsigned int budget = q_vector->tx.work_limit; + unsigned int i = tx_ring->next_to_clean; +@@ -5723,16 +6007,16 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) + tx_desc = IGB_TX_DESC(tx_ring, i); + i -= tx_ring->count; + +- for (; budget; budget--) { +- eop_desc = tx_buffer->next_to_watch; +- +- /* prevent any other reads prior to eop_desc */ +- rmb(); ++ do { ++ union e1000_adv_tx_desc *eop_desc = tx_buffer->next_to_watch; + + /* if next_to_watch is not set then there is no work pending */ + if (!eop_desc) + break; + ++ /* prevent any other reads prior to eop_desc */ ++ read_barrier_depends(); ++ + /* if DD is not set pending work has not been completed */ + if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) + break; +@@ -5744,23 +6028,21 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) + total_bytes += tx_buffer->bytecount; + total_packets += tx_buffer->gso_segs; + +- /* retrieve hardware timestamp */ +- igb_tx_hwtstamp(q_vector, tx_buffer); +- + /* free the skb */ + dev_kfree_skb_any(tx_buffer->skb); +- tx_buffer->skb = NULL; + + /* unmap skb header data */ + dma_unmap_single(tx_ring->dev, +- tx_buffer->dma, +- tx_buffer->length, ++ dma_unmap_addr(tx_buffer, dma), ++ dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); + ++ /* clear tx_buffer data */ ++ tx_buffer->skb = NULL; ++ dma_unmap_len_set(tx_buffer, len, 0); ++ + /* clear last DMA location and unmap remaining buffers */ + while (tx_desc != eop_desc) { +- tx_buffer->dma = 0; +- + tx_buffer++; + tx_desc++; + i++; +@@ -5771,17 +6053,15 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) + } + + /* unmap any remaining paged data */ +- if (tx_buffer->dma) { ++ if (dma_unmap_len(tx_buffer, len)) { + dma_unmap_page(tx_ring->dev, +- tx_buffer->dma, +- tx_buffer->length, ++ dma_unmap_addr(tx_buffer, dma), ++ dma_unmap_len(tx_buffer, len), + DMA_TO_DEVICE); ++ dma_unmap_len_set(tx_buffer, len, 0); + } + } + +- /* clear last DMA location */ +- tx_buffer->dma = 0; +- + /* move us one more past the eop_desc for start of next pkt */ + tx_buffer++; + tx_desc++; +@@ -5791,8 +6071,16 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) + tx_buffer = tx_ring->tx_buffer_info; + tx_desc = IGB_TX_DESC(tx_ring, 0); + } +- } + ++ /* issue prefetch for next Tx descriptor */ ++ prefetch(tx_desc); ++ ++ /* update budget accounting */ ++ budget--; ++ } while (likely(budget)); ++ ++ netdev_tx_completed_queue(txring_txq(tx_ring), ++ total_packets, total_bytes); + i += tx_ring->count; + tx_ring->next_to_clean = i; + u64_stats_update_begin(&tx_ring->tx_syncp); +@@ -5805,12 +6093,11 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) + if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { + struct e1000_hw *hw = &adapter->hw; + +- eop_desc = tx_buffer->next_to_watch; +- + /* Detect a transmit hang in hardware, this serializes the +- * check with the clearing of time_stamp and movement of i */ ++ * check with the clearing of time_stamp and movement of i ++ */ + clear_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); +- if (eop_desc && ++ if (tx_buffer->next_to_watch && + time_after(jiffies, tx_buffer->time_stamp + + (adapter->tx_timeout_factor * HZ)) && + !(rd32(E1000_STATUS) & E1000_STATUS_TXOFF)) { +@@ -5834,9 +6121,9 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) + tx_ring->next_to_use, + tx_ring->next_to_clean, + tx_buffer->time_stamp, +- eop_desc, ++ tx_buffer->next_to_watch, + jiffies, +- eop_desc->wb.status); ++ tx_buffer->next_to_watch->wb.status); + netif_stop_subqueue(tx_ring->netdev, + tx_ring->queue_index); + +@@ -5845,9 +6132,10 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) + } + } + ++#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) + if (unlikely(total_packets && +- netif_carrier_ok(tx_ring->netdev) && +- igb_desc_unused(tx_ring) >= IGB_TX_QUEUE_WAKE)) { ++ netif_carrier_ok(tx_ring->netdev) && ++ igb_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) { + /* Make sure that anybody stopping the queue after this + * sees the new next_to_clean. + */ +@@ -5867,32 +6155,207 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) + return !!budget; + } + +-static inline void igb_rx_checksum(struct igb_ring *ring, +- union e1000_adv_rx_desc *rx_desc, +- struct sk_buff *skb) ++/** ++ * igb_reuse_rx_page - page flip buffer and store it back on the ring ++ * @rx_ring: rx descriptor ring to store buffers on ++ * @old_buff: donor buffer to have page reused ++ * ++ * Synchronizes page for reuse by the adapter ++ **/ ++static void igb_reuse_rx_page(struct igb_ring *rx_ring, ++ struct igb_rx_buffer *old_buff) + { +- skb_checksum_none_assert(skb); ++ struct igb_rx_buffer *new_buff; ++ u16 nta = rx_ring->next_to_alloc; + +- /* Ignore Checksum bit is set */ +- if (igb_test_staterr(rx_desc, E1000_RXD_STAT_IXSM)) +- return; ++ new_buff = &rx_ring->rx_buffer_info[nta]; + +- /* Rx checksum disabled via ethtool */ +- if (!(ring->netdev->features & NETIF_F_RXCSUM)) +- return; ++ /* update, and store next to alloc */ ++ nta++; ++ rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0; + +- /* TCP/UDP checksum error bit is set */ +- if (igb_test_staterr(rx_desc, +- E1000_RXDEXT_STATERR_TCPE | +- E1000_RXDEXT_STATERR_IPE)) { +- /* +- * work around errata with sctp packets where the TCPE aka +- * L4E bit is set incorrectly on 64 byte (60 byte w/o crc) +- * packets, (aka let the stack check the crc32c) +- */ +- if (!((skb->len == 60) && +- test_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags))) { +- u64_stats_update_begin(&ring->rx_syncp); ++ /* transfer page from old buffer to new buffer */ ++ memcpy(new_buff, old_buff, sizeof(struct igb_rx_buffer)); ++ ++ /* sync the buffer for use by the device */ ++ dma_sync_single_range_for_device(rx_ring->dev, old_buff->dma, ++ old_buff->page_offset, ++ IGB_RX_BUFSZ, ++ DMA_FROM_DEVICE); ++} ++ ++/** ++ * igb_add_rx_frag - Add contents of Rx buffer to sk_buff ++ * @rx_ring: rx descriptor ring to transact packets on ++ * @rx_buffer: buffer containing page to add ++ * @rx_desc: descriptor containing length of buffer written by hardware ++ * @skb: sk_buff to place the data into ++ * ++ * This function will add the data contained in rx_buffer->page to the skb. ++ * This is done either through a direct copy if the data in the buffer is ++ * less than the skb header size, otherwise it will just attach the page as ++ * a frag to the skb. ++ * ++ * The function will then update the page offset if necessary and return ++ * true if the buffer can be reused by the adapter. ++ **/ ++static bool igb_add_rx_frag(struct igb_ring *rx_ring, ++ struct igb_rx_buffer *rx_buffer, ++ union e1000_adv_rx_desc *rx_desc, ++ struct sk_buff *skb) ++{ ++ struct page *page = rx_buffer->page; ++ unsigned int size = le16_to_cpu(rx_desc->wb.upper.length); ++ ++ if ((size <= IGB_RX_HDR_LEN) && !skb_is_nonlinear(skb)) { ++ unsigned char *va = page_address(page) + rx_buffer->page_offset; ++ ++#ifdef CONFIG_IGB_PTP ++ if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { ++ igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb); ++ va += IGB_TS_HDR_LEN; ++ size -= IGB_TS_HDR_LEN; ++ } ++ ++#endif ++ memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long))); ++ ++ /* we can reuse buffer as-is, just make sure it is local */ ++ if (likely(page_to_nid(page) == numa_node_id())) ++ return true; ++ ++ /* this page cannot be reused so discard it */ ++ put_page(page); ++ return false; ++ } ++ ++ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, ++ rx_buffer->page_offset, size); ++ ++ /* avoid re-using remote pages */ ++ if (unlikely(page_to_nid(page) != numa_node_id())) ++ return false; ++ ++#if (PAGE_SIZE < 8192) ++ /* if we are only owner of page we can reuse it */ ++ if (unlikely(page_count(page) != 1)) ++ return false; ++ ++ /* flip page offset to other buffer */ ++ rx_buffer->page_offset ^= IGB_RX_BUFSZ; ++ ++ /* ++ * since we are the only owner of the page and we need to ++ * increment it, just set the value to 2 in order to avoid ++ * an unnecessary locked operation ++ */ ++ atomic_set(&page->_count, 2); ++#else ++ /* move offset up to the next cache line */ ++ rx_buffer->page_offset += SKB_DATA_ALIGN(size); ++ ++ if (rx_buffer->page_offset > (PAGE_SIZE - IGB_RX_BUFSZ)) ++ return false; ++ ++ /* bump ref count on page before it is given to the stack */ ++ get_page(page); ++#endif ++ ++ return true; ++} ++ ++static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring, ++ union e1000_adv_rx_desc *rx_desc, ++ struct sk_buff *skb) ++{ ++ struct igb_rx_buffer *rx_buffer; ++ struct page *page; ++ ++ rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; ++ ++ /* ++ * This memory barrier is needed to keep us from reading ++ * any other fields out of the rx_desc until we know the ++ * RXD_STAT_DD bit is set ++ */ ++ rmb(); ++ ++ page = rx_buffer->page; ++ prefetchw(page); ++ ++ if (likely(!skb)) { ++ void *page_addr = page_address(page) + ++ rx_buffer->page_offset; ++ ++ /* prefetch first cache line of first page */ ++ prefetch(page_addr); ++#if L1_CACHE_BYTES < 128 ++ prefetch(page_addr + L1_CACHE_BYTES); ++#endif ++ ++ /* allocate a skb to store the frags */ ++ skb = netdev_alloc_skb_ip_align(rx_ring->netdev, ++ IGB_RX_HDR_LEN); ++ if (unlikely(!skb)) { ++ rx_ring->rx_stats.alloc_failed++; ++ return NULL; ++ } ++ ++ /* we will be copying header into skb->data in ++ * pskb_may_pull so it is in our interest to prefetch ++ * it now to avoid a possible cache miss ++ */ ++ prefetchw(skb->data); ++ } ++ ++ /* we are reusing so sync this buffer for CPU use */ ++ dma_sync_single_range_for_cpu(rx_ring->dev, ++ rx_buffer->dma, ++ rx_buffer->page_offset, ++ IGB_RX_BUFSZ, ++ DMA_FROM_DEVICE); ++ ++ /* pull page into skb */ ++ if (igb_add_rx_frag(rx_ring, rx_buffer, rx_desc, skb)) { ++ /* hand second half of page back to the ring */ ++ igb_reuse_rx_page(rx_ring, rx_buffer); ++ } else { ++ /* we are not reusing the buffer so unmap it */ ++ dma_unmap_page(rx_ring->dev, rx_buffer->dma, ++ PAGE_SIZE, DMA_FROM_DEVICE); ++ } ++ ++ /* clear contents of rx_buffer */ ++ rx_buffer->page = NULL; ++ ++ return skb; ++} ++ ++static inline void igb_rx_checksum(struct igb_ring *ring, ++ union e1000_adv_rx_desc *rx_desc, ++ struct sk_buff *skb) ++{ ++ skb_checksum_none_assert(skb); ++ ++ /* Ignore Checksum bit is set */ ++ if (igb_test_staterr(rx_desc, E1000_RXD_STAT_IXSM)) ++ return; ++ ++ /* Rx checksum disabled via ethtool */ ++ if (!(ring->netdev->features & NETIF_F_RXCSUM)) ++ return; ++ ++ /* TCP/UDP checksum error bit is set */ ++ if (igb_test_staterr(rx_desc, ++ E1000_RXDEXT_STATERR_TCPE | ++ E1000_RXDEXT_STATERR_IPE)) { ++ /* work around errata with sctp packets where the TCPE aka ++ * L4E bit is set incorrectly on 64 byte (60 byte w/o crc) ++ * packets, (aka let the stack check the crc32c) ++ */ ++ if (!((skb->len == 60) && ++ test_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags))) { ++ u64_stats_update_begin(&ring->rx_syncp); + ring->rx_stats.csum_err++; + u64_stats_update_end(&ring->rx_syncp); + } +@@ -5916,183 +6379,338 @@ static inline void igb_rx_hash(struct igb_ring *ring, + skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss); + } + +-static void igb_rx_hwtstamp(struct igb_q_vector *q_vector, +- union e1000_adv_rx_desc *rx_desc, +- struct sk_buff *skb) ++/** ++ * igb_is_non_eop - process handling of non-EOP buffers ++ * @rx_ring: Rx ring being processed ++ * @rx_desc: Rx descriptor for current buffer ++ * @skb: current socket buffer containing buffer in progress ++ * ++ * This function updates next to clean. If the buffer is an EOP buffer ++ * this function exits returning false, otherwise it will place the ++ * sk_buff in the next buffer to be chained and return true indicating ++ * that this is in fact a non-EOP buffer. ++ **/ ++static bool igb_is_non_eop(struct igb_ring *rx_ring, ++ union e1000_adv_rx_desc *rx_desc) + { +- struct igb_adapter *adapter = q_vector->adapter; +- struct e1000_hw *hw = &adapter->hw; +- u64 regval; ++ u32 ntc = rx_ring->next_to_clean + 1; + +- if (!igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP | +- E1000_RXDADV_STAT_TS)) +- return; ++ /* fetch, update, and store next to clean */ ++ ntc = (ntc < rx_ring->count) ? ntc : 0; ++ rx_ring->next_to_clean = ntc; + +- /* +- * If this bit is set, then the RX registers contain the time stamp. No +- * other packet will be time stamped until we read these registers, so +- * read the registers to make them available again. Because only one +- * packet can be time stamped at a time, we know that the register +- * values must belong to this one here and therefore we don't need to +- * compare any of the additional attributes stored for it. +- * +- * If nothing went wrong, then it should have a shared tx_flags that we +- * can turn into a skb_shared_hwtstamps. ++ prefetch(IGB_RX_DESC(rx_ring, ntc)); ++ ++ if (likely(igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP))) ++ return false; ++ ++ return true; ++} ++ ++/** ++ * igb_get_headlen - determine size of header for LRO/GRO ++ * @data: pointer to the start of the headers ++ * @max_len: total length of section to find headers in ++ * ++ * This function is meant to determine the length of headers that will ++ * be recognized by hardware for LRO, and GRO offloads. The main ++ * motivation of doing this is to only perform one pull for IPv4 TCP ++ * packets so that we can do basic things like calculating the gso_size ++ * based on the average data per packet. ++ **/ ++static unsigned int igb_get_headlen(unsigned char *data, ++ unsigned int max_len) ++{ ++ union { ++ unsigned char *network; ++ /* l2 headers */ ++ struct ethhdr *eth; ++ struct vlan_hdr *vlan; ++ /* l3 headers */ ++ struct iphdr *ipv4; ++ struct ipv6hdr *ipv6; ++ } hdr; ++ __be16 protocol; ++ u8 nexthdr = 0; /* default to not TCP */ ++ u8 hlen; ++ ++ /* this should never happen, but better safe than sorry */ ++ if (max_len < ETH_HLEN) ++ return max_len; ++ ++ /* initialize network frame pointer */ ++ hdr.network = data; ++ ++ /* set first protocol and move network header forward */ ++ protocol = hdr.eth->h_proto; ++ hdr.network += ETH_HLEN; ++ ++ /* handle any vlan tag if present */ ++ if (protocol == __constant_htons(ETH_P_8021Q)) { ++ if ((hdr.network - data) > (max_len - VLAN_HLEN)) ++ return max_len; ++ ++ protocol = hdr.vlan->h_vlan_encapsulated_proto; ++ hdr.network += VLAN_HLEN; ++ } ++ ++ /* handle L3 protocols */ ++ if (protocol == __constant_htons(ETH_P_IP)) { ++ if ((hdr.network - data) > (max_len - sizeof(struct iphdr))) ++ return max_len; ++ ++ /* access ihl as a u8 to avoid unaligned access on ia64 */ ++ hlen = (hdr.network[0] & 0x0F) << 2; ++ ++ /* verify hlen meets minimum size requirements */ ++ if (hlen < sizeof(struct iphdr)) ++ return hdr.network - data; ++ ++ /* record next protocol if header is present */ ++ if (!(hdr.ipv4->frag_off & htons(IP_OFFSET))) ++ nexthdr = hdr.ipv4->protocol; ++ } else if (protocol == __constant_htons(ETH_P_IPV6)) { ++ if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr))) ++ return max_len; ++ ++ /* record next protocol */ ++ nexthdr = hdr.ipv6->nexthdr; ++ hlen = sizeof(struct ipv6hdr); ++ } else { ++ return hdr.network - data; ++ } ++ ++ /* relocate pointer to start of L4 header */ ++ hdr.network += hlen; ++ ++ /* finally sort out TCP */ ++ if (nexthdr == IPPROTO_TCP) { ++ if ((hdr.network - data) > (max_len - sizeof(struct tcphdr))) ++ return max_len; ++ ++ /* access doff as a u8 to avoid unaligned access on ia64 */ ++ hlen = (hdr.network[12] & 0xF0) >> 2; ++ ++ /* verify hlen meets minimum size requirements */ ++ if (hlen < sizeof(struct tcphdr)) ++ return hdr.network - data; ++ ++ hdr.network += hlen; ++ } else if (nexthdr == IPPROTO_UDP) { ++ if ((hdr.network - data) > (max_len - sizeof(struct udphdr))) ++ return max_len; ++ ++ hdr.network += sizeof(struct udphdr); ++ } ++ ++ /* If everything has gone correctly hdr.network should be the ++ * data section of the packet and will be the end of the header. ++ * If not then it probably represents the end of the last recognized ++ * header. ++ */ ++ if ((hdr.network - data) < max_len) ++ return hdr.network - data; ++ else ++ return max_len; ++} ++ ++/** ++ * igb_pull_tail - igb specific version of skb_pull_tail ++ * @rx_ring: rx descriptor ring packet is being transacted on ++ * @rx_desc: pointer to the EOP Rx descriptor ++ * @skb: pointer to current skb being adjusted ++ * ++ * This function is an igb specific version of __pskb_pull_tail. The ++ * main difference between this version and the original function is that ++ * this function can make several assumptions about the state of things ++ * that allow for significant optimizations versus the standard function. ++ * As a result we can do things like drop a frag and maintain an accurate ++ * truesize for the skb. ++ */ ++static void igb_pull_tail(struct igb_ring *rx_ring, ++ union e1000_adv_rx_desc *rx_desc, ++ struct sk_buff *skb) ++{ ++ struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; ++ unsigned char *va; ++ unsigned int pull_len; ++ ++ /* it is valid to use page_address instead of kmap since we are ++ * working with pages allocated out of the lomem pool per ++ * alloc_page(GFP_ATOMIC) + */ ++ va = skb_frag_address(frag); ++ ++#ifdef CONFIG_IGB_PTP + if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { +- u32 *stamp = (u32 *)skb->data; +- regval = le32_to_cpu(*(stamp + 2)); +- regval |= (u64)le32_to_cpu(*(stamp + 3)) << 32; +- skb_pull(skb, IGB_TS_HDR_LEN); +- } else { +- if(!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) +- return; ++ /* retrieve timestamp from buffer */ ++ igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb); ++ ++ /* update pointers to remove timestamp header */ ++ skb_frag_size_sub(frag, IGB_TS_HDR_LEN); ++ frag->page_offset += IGB_TS_HDR_LEN; ++ skb->data_len -= IGB_TS_HDR_LEN; ++ skb->len -= IGB_TS_HDR_LEN; + +- regval = rd32(E1000_RXSTMPL); +- regval |= (u64)rd32(E1000_RXSTMPH) << 32; ++ /* move va to start of packet data */ ++ va += IGB_TS_HDR_LEN; + } + +- igb_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); ++#endif ++ /* we need the header to contain the greater of either ETH_HLEN or ++ * 60 bytes if the skb->len is less than 60 for skb_pad. ++ */ ++ pull_len = igb_get_headlen(va, IGB_RX_HDR_LEN); ++ ++ /* align pull length to size of long to optimize memcpy performance */ ++ skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long))); ++ ++ /* update all of the pointers */ ++ skb_frag_size_sub(frag, pull_len); ++ frag->page_offset += pull_len; ++ skb->data_len -= pull_len; ++ skb->tail += pull_len; + } + +-static void igb_rx_vlan(struct igb_ring *ring, +- union e1000_adv_rx_desc *rx_desc, +- struct sk_buff *skb) ++/** ++ * igb_cleanup_headers - Correct corrupted or empty headers ++ * @rx_ring: rx descriptor ring packet is being transacted on ++ * @rx_desc: pointer to the EOP Rx descriptor ++ * @skb: pointer to current skb being fixed ++ * ++ * Address the case where we are pulling data in on pages only ++ * and as such no data is present in the skb header. ++ * ++ * In addition if skb is not at least 60 bytes we need to pad it so that ++ * it is large enough to qualify as a valid Ethernet frame. ++ * ++ * Returns true if an error was encountered and skb was freed. ++ **/ ++static bool igb_cleanup_headers(struct igb_ring *rx_ring, ++ union e1000_adv_rx_desc *rx_desc, ++ struct sk_buff *skb) + { +- if (igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) { ++ if (unlikely((igb_test_staterr(rx_desc, ++ E1000_RXDEXT_ERR_FRAME_ERR_MASK)))) { ++ dev_kfree_skb_any(skb); ++ return true; ++ } ++ ++ /* place header in linear portion of buffer */ ++ if (skb_is_nonlinear(skb)) ++ igb_pull_tail(rx_ring, rx_desc, skb); ++ ++ /* if skb_pad returns an error the skb was freed */ ++ if (unlikely(skb->len < 60)) { ++ int pad_len = 60 - skb->len; ++ ++ if (skb_pad(skb, pad_len)) ++ return true; ++ __skb_put(skb, pad_len); ++ } ++ ++ return false; ++} ++ ++/** ++ * igb_process_skb_fields - Populate skb header fields from Rx descriptor ++ * @rx_ring: rx descriptor ring packet is being transacted on ++ * @rx_desc: pointer to the EOP Rx descriptor ++ * @skb: pointer to current skb being populated ++ * ++ * This function checks the ring, descriptor, and packet information in ++ * order to populate the hash, checksum, VLAN, timestamp, protocol, and ++ * other fields within the skb. ++ **/ ++static void igb_process_skb_fields(struct igb_ring *rx_ring, ++ union e1000_adv_rx_desc *rx_desc, ++ struct sk_buff *skb) ++{ ++ struct net_device *dev = rx_ring->netdev; ++ ++ igb_rx_hash(rx_ring, rx_desc, skb); ++ ++ igb_rx_checksum(rx_ring, rx_desc, skb); ++ ++#ifdef CONFIG_IGB_PTP ++ igb_ptp_rx_hwtstamp(rx_ring, rx_desc, skb); ++#endif /* CONFIG_IGB_PTP */ ++ ++ if ((dev->features & NETIF_F_HW_VLAN_RX) && ++ igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) { + u16 vid; + if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) && +- test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags)) ++ test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags)) + vid = be16_to_cpu(rx_desc->wb.upper.vlan); + else + vid = le16_to_cpu(rx_desc->wb.upper.vlan); + + __vlan_hwaccel_put_tag(skb, vid); + } +-} + +-static inline u16 igb_get_hlen(union e1000_adv_rx_desc *rx_desc) +-{ +- /* HW will not DMA in data larger than the given buffer, even if it +- * parses the (NFS, of course) header to be larger. In that case, it +- * fills the header buffer and spills the rest into the page. +- */ +- u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) & +- E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT; +- if (hlen > IGB_RX_HDR_LEN) +- hlen = IGB_RX_HDR_LEN; +- return hlen; ++ skb_record_rx_queue(skb, rx_ring->queue_index); ++ ++ skb->protocol = eth_type_trans(skb, rx_ring->netdev); + } + +-static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget) ++static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) + { + struct igb_ring *rx_ring = q_vector->rx.ring; +- union e1000_adv_rx_desc *rx_desc; +- const int current_node = numa_node_id(); ++ struct sk_buff *skb = rx_ring->skb; + unsigned int total_bytes = 0, total_packets = 0; + u16 cleaned_count = igb_desc_unused(rx_ring); +- u16 i = rx_ring->next_to_clean; +- +- rx_desc = IGB_RX_DESC(rx_ring, i); +- +- while (igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) { +- struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i]; +- struct sk_buff *skb = buffer_info->skb; +- union e1000_adv_rx_desc *next_rxd; + +- buffer_info->skb = NULL; +- prefetch(skb->data); +- +- i++; +- if (i == rx_ring->count) +- i = 0; +- +- next_rxd = IGB_RX_DESC(rx_ring, i); +- prefetch(next_rxd); +- +- /* +- * This memory barrier is needed to keep us from reading +- * any other fields out of the rx_desc until we know the +- * RXD_STAT_DD bit is set +- */ +- rmb(); ++ do { ++ union e1000_adv_rx_desc *rx_desc; + +- if (!skb_is_nonlinear(skb)) { +- __skb_put(skb, igb_get_hlen(rx_desc)); +- dma_unmap_single(rx_ring->dev, buffer_info->dma, +- IGB_RX_HDR_LEN, +- DMA_FROM_DEVICE); +- buffer_info->dma = 0; ++ /* return some buffers to hardware, one at a time is too slow */ ++ if (cleaned_count >= IGB_RX_BUFFER_WRITE) { ++ igb_alloc_rx_buffers(rx_ring, cleaned_count); ++ cleaned_count = 0; + } + +- if (rx_desc->wb.upper.length) { +- u16 length = le16_to_cpu(rx_desc->wb.upper.length); ++ rx_desc = IGB_RX_DESC(rx_ring, rx_ring->next_to_clean); + +- skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, +- buffer_info->page, +- buffer_info->page_offset, +- length); ++ if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) ++ break; + +- skb->len += length; +- skb->data_len += length; +- skb->truesize += PAGE_SIZE / 2; ++ /* retrieve a buffer from the ring */ ++ skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb); + +- if ((page_count(buffer_info->page) != 1) || +- (page_to_nid(buffer_info->page) != current_node)) +- buffer_info->page = NULL; +- else +- get_page(buffer_info->page); ++ /* exit if we failed to retrieve a buffer */ ++ if (!skb) ++ break; + +- dma_unmap_page(rx_ring->dev, buffer_info->page_dma, +- PAGE_SIZE / 2, DMA_FROM_DEVICE); +- buffer_info->page_dma = 0; +- } ++ cleaned_count++; + +- if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)) { +- struct igb_rx_buffer *next_buffer; +- next_buffer = &rx_ring->rx_buffer_info[i]; +- buffer_info->skb = next_buffer->skb; +- buffer_info->dma = next_buffer->dma; +- next_buffer->skb = skb; +- next_buffer->dma = 0; +- goto next_desc; +- } ++ /* fetch next buffer in frame if non-eop */ ++ if (igb_is_non_eop(rx_ring, rx_desc)) ++ continue; + +- if (igb_test_staterr(rx_desc, +- E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { +- dev_kfree_skb_any(skb); +- goto next_desc; ++ /* verify the packet layout is correct */ ++ if (igb_cleanup_headers(rx_ring, rx_desc, skb)) { ++ skb = NULL; ++ continue; + } + +- igb_rx_hwtstamp(q_vector, rx_desc, skb); +- igb_rx_hash(rx_ring, rx_desc, skb); +- igb_rx_checksum(rx_ring, rx_desc, skb); +- igb_rx_vlan(rx_ring, rx_desc, skb); +- ++ /* probably a little skewed due to removing CRC */ + total_bytes += skb->len; +- total_packets++; + +- skb->protocol = eth_type_trans(skb, rx_ring->netdev); ++ /* populate checksum, timestamp, VLAN, and protocol */ ++ igb_process_skb_fields(rx_ring, rx_desc, skb); + + napi_gro_receive(&q_vector->napi, skb); + +- budget--; +-next_desc: +- if (!budget) +- break; ++ /* reset skb pointer */ ++ skb = NULL; + +- cleaned_count++; +- /* return some buffers to hardware, one at a time is too slow */ +- if (cleaned_count >= IGB_RX_BUFFER_WRITE) { +- igb_alloc_rx_buffers(rx_ring, cleaned_count); +- cleaned_count = 0; +- } ++ /* update budget accounting */ ++ total_packets++; ++ } while (likely(total_packets < budget)); + +- /* use prefetched values */ +- rx_desc = next_rxd; +- } ++ /* place incomplete frames back on ring for completion */ ++ rx_ring->skb = skb; + +- rx_ring->next_to_clean = i; + u64_stats_update_begin(&rx_ring->rx_syncp); + rx_ring->rx_stats.packets += total_packets; + rx_ring->rx_stats.bytes += total_bytes; +@@ -6103,79 +6721,49 @@ next_desc: + if (cleaned_count) + igb_alloc_rx_buffers(rx_ring, cleaned_count); + +- return !!budget; +-} +- +-static bool igb_alloc_mapped_skb(struct igb_ring *rx_ring, +- struct igb_rx_buffer *bi) +-{ +- struct sk_buff *skb = bi->skb; +- dma_addr_t dma = bi->dma; +- +- if (dma) +- return true; +- +- if (likely(!skb)) { +- skb = netdev_alloc_skb_ip_align(rx_ring->netdev, +- IGB_RX_HDR_LEN); +- bi->skb = skb; +- if (!skb) { +- rx_ring->rx_stats.alloc_failed++; +- return false; +- } +- +- /* initialize skb for ring */ +- skb_record_rx_queue(skb, rx_ring->queue_index); +- } +- +- dma = dma_map_single(rx_ring->dev, skb->data, +- IGB_RX_HDR_LEN, DMA_FROM_DEVICE); +- +- if (dma_mapping_error(rx_ring->dev, dma)) { +- rx_ring->rx_stats.alloc_failed++; +- return false; +- } +- +- bi->dma = dma; +- return true; ++ return (total_packets < budget); + } + + static bool igb_alloc_mapped_page(struct igb_ring *rx_ring, + struct igb_rx_buffer *bi) + { + struct page *page = bi->page; +- dma_addr_t page_dma = bi->page_dma; +- unsigned int page_offset = bi->page_offset ^ (PAGE_SIZE / 2); ++ dma_addr_t dma; + +- if (page_dma) ++ /* since we are recycling buffers we should seldom need to alloc */ ++ if (likely(page)) + return true; + +- if (!page) { +- page = netdev_alloc_page(rx_ring->netdev); +- bi->page = page; +- if (unlikely(!page)) { +- rx_ring->rx_stats.alloc_failed++; +- return false; +- } ++ /* alloc new page for storage */ ++ page = alloc_page(GFP_ATOMIC | __GFP_COLD); ++ if (unlikely(!page)) { ++ rx_ring->rx_stats.alloc_failed++; ++ return false; + } + +- page_dma = dma_map_page(rx_ring->dev, page, +- page_offset, PAGE_SIZE / 2, +- DMA_FROM_DEVICE); ++ /* map page for use */ ++ dma = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); ++ ++ /* if mapping failed free memory back to system since ++ * there isn't much point in holding memory we can't use ++ */ ++ if (dma_mapping_error(rx_ring->dev, dma)) { ++ __free_page(page); + +- if (dma_mapping_error(rx_ring->dev, page_dma)) { + rx_ring->rx_stats.alloc_failed++; + return false; + } + +- bi->page_dma = page_dma; +- bi->page_offset = page_offset; ++ bi->dma = dma; ++ bi->page = page; ++ bi->page_offset = 0; ++ + return true; + } + + /** +- * igb_alloc_rx_buffers - Replace used receive buffers; packet split +- * @adapter: address of board private structure ++ * igb_alloc_rx_buffers - Replace used receive buffers; packet split ++ * @adapter: address of board private structure + **/ + void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count) + { +@@ -6183,22 +6771,22 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count) + struct igb_rx_buffer *bi; + u16 i = rx_ring->next_to_use; + ++ /* nothing to do */ ++ if (!cleaned_count) ++ return; ++ + rx_desc = IGB_RX_DESC(rx_ring, i); + bi = &rx_ring->rx_buffer_info[i]; + i -= rx_ring->count; + +- while (cleaned_count--) { +- if (!igb_alloc_mapped_skb(rx_ring, bi)) +- break; +- +- /* Refresh the desc even if buffer_addrs didn't change +- * because each write-back erases this info. */ +- rx_desc->read.hdr_addr = cpu_to_le64(bi->dma); +- ++ do { + if (!igb_alloc_mapped_page(rx_ring, bi)) + break; + +- rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma); ++ /* Refresh the desc even if buffer_addrs didn't change ++ * because each write-back erases this info. ++ */ ++ rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); + + rx_desc++; + bi++; +@@ -6211,17 +6799,24 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count) + + /* clear the hdr_addr for the next_to_use descriptor */ + rx_desc->read.hdr_addr = 0; +- } ++ ++ cleaned_count--; ++ } while (cleaned_count); + + i += rx_ring->count; + + if (rx_ring->next_to_use != i) { ++ /* record the next descriptor to use */ + rx_ring->next_to_use = i; + ++ /* update next to alloc since we have filled the ring */ ++ rx_ring->next_to_alloc = i; ++ + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, +- * such as IA-64). */ ++ * such as IA-64). ++ */ + wmb(); + writel(i, rx_ring->tail); + } +@@ -6246,11 +6841,19 @@ static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + data->phy_id = adapter->hw.phy.addr; + break; + case SIOCGMIIREG: ++ adapter->hw.phy.addr = data->phy_id; + if (igb_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, + &data->val_out)) + return -EIO; + break; + case SIOCSMIIREG: ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ adapter->hw.phy.addr = data->phy_id; ++ if (igb_write_phy_reg(&adapter->hw, data->reg_num & 0x1F, ++ data->val_in)) ++ return -EIO; ++ break; + default: + return -EOPNOTSUPP; + } +@@ -6258,181 +6861,6 @@ static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + } + + /** +- * igb_hwtstamp_ioctl - control hardware time stamping +- * @netdev: +- * @ifreq: +- * @cmd: +- * +- * Outgoing time stamping can be enabled and disabled. Play nice and +- * disable it when requested, although it shouldn't case any overhead +- * when no packet needs it. At most one packet in the queue may be +- * marked for time stamping, otherwise it would be impossible to tell +- * for sure to which packet the hardware time stamp belongs. +- * +- * Incoming time stamping has to be configured via the hardware +- * filters. Not all combinations are supported, in particular event +- * type has to be specified. Matching the kind of event packet is +- * not supported, with the exception of "all V2 events regardless of +- * level 2 or 4". +- * +- **/ +-static int igb_hwtstamp_ioctl(struct net_device *netdev, +- struct ifreq *ifr, int cmd) +-{ +- struct igb_adapter *adapter = netdev_priv(netdev); +- struct e1000_hw *hw = &adapter->hw; +- struct hwtstamp_config config; +- u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED; +- u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; +- u32 tsync_rx_cfg = 0; +- bool is_l4 = false; +- bool is_l2 = false; +- u32 regval; +- +- if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) +- return -EFAULT; +- +- /* reserved for future extensions */ +- if (config.flags) +- return -EINVAL; +- +- switch (config.tx_type) { +- case HWTSTAMP_TX_OFF: +- tsync_tx_ctl = 0; +- case HWTSTAMP_TX_ON: +- break; +- default: +- return -ERANGE; +- } +- +- switch (config.rx_filter) { +- case HWTSTAMP_FILTER_NONE: +- tsync_rx_ctl = 0; +- break; +- case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: +- case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: +- case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: +- case HWTSTAMP_FILTER_ALL: +- /* +- * register TSYNCRXCFG must be set, therefore it is not +- * possible to time stamp both Sync and Delay_Req messages +- * => fall back to time stamping all packets +- */ +- tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; +- config.rx_filter = HWTSTAMP_FILTER_ALL; +- break; +- case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: +- tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; +- tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE; +- is_l4 = true; +- break; +- case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: +- tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; +- tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE; +- is_l4 = true; +- break; +- case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: +- case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: +- tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; +- tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE; +- is_l2 = true; +- is_l4 = true; +- config.rx_filter = HWTSTAMP_FILTER_SOME; +- break; +- case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: +- case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: +- tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; +- tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE; +- is_l2 = true; +- is_l4 = true; +- config.rx_filter = HWTSTAMP_FILTER_SOME; +- break; +- case HWTSTAMP_FILTER_PTP_V2_EVENT: +- case HWTSTAMP_FILTER_PTP_V2_SYNC: +- case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: +- tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2; +- config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; +- is_l2 = true; +- is_l4 = true; +- break; +- default: +- return -ERANGE; +- } +- +- if (hw->mac.type == e1000_82575) { +- if (tsync_rx_ctl | tsync_tx_ctl) +- return -EINVAL; +- return 0; +- } +- +- /* +- * Per-packet timestamping only works if all packets are +- * timestamped, so enable timestamping in all packets as +- * long as one rx filter was configured. +- */ +- if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) { +- tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; +- tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; +- } +- +- /* enable/disable TX */ +- regval = rd32(E1000_TSYNCTXCTL); +- regval &= ~E1000_TSYNCTXCTL_ENABLED; +- regval |= tsync_tx_ctl; +- wr32(E1000_TSYNCTXCTL, regval); +- +- /* enable/disable RX */ +- regval = rd32(E1000_TSYNCRXCTL); +- regval &= ~(E1000_TSYNCRXCTL_ENABLED | E1000_TSYNCRXCTL_TYPE_MASK); +- regval |= tsync_rx_ctl; +- wr32(E1000_TSYNCRXCTL, regval); +- +- /* define which PTP packets are time stamped */ +- wr32(E1000_TSYNCRXCFG, tsync_rx_cfg); +- +- /* define ethertype filter for timestamped packets */ +- if (is_l2) +- wr32(E1000_ETQF(3), +- (E1000_ETQF_FILTER_ENABLE | /* enable filter */ +- E1000_ETQF_1588 | /* enable timestamping */ +- ETH_P_1588)); /* 1588 eth protocol type */ +- else +- wr32(E1000_ETQF(3), 0); +- +-#define PTP_PORT 319 +- /* L4 Queue Filter[3]: filter by destination port and protocol */ +- if (is_l4) { +- u32 ftqf = (IPPROTO_UDP /* UDP */ +- | E1000_FTQF_VF_BP /* VF not compared */ +- | E1000_FTQF_1588_TIME_STAMP /* Enable Timestamping */ +- | E1000_FTQF_MASK); /* mask all inputs */ +- ftqf &= ~E1000_FTQF_MASK_PROTO_BP; /* enable protocol check */ +- +- wr32(E1000_IMIR(3), htons(PTP_PORT)); +- wr32(E1000_IMIREXT(3), +- (E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_BP)); +- if (hw->mac.type == e1000_82576) { +- /* enable source port check */ +- wr32(E1000_SPQF(3), htons(PTP_PORT)); +- ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP; +- } +- wr32(E1000_FTQF(3), ftqf); +- } else { +- wr32(E1000_FTQF(3), E1000_FTQF_MASK); +- } +- wrfl(); +- +- adapter->hwtstamp_config = config; +- +- /* clear TX/RX time stamp registers, just to be sure */ +- regval = rd32(E1000_TXSTMPH); +- regval = rd32(E1000_RXSTMPH); +- +- return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? +- -EFAULT : 0; +-} +- +-/** + * igb_ioctl - + * @netdev: + * @ifreq: +@@ -6445,8 +6873,10 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + case SIOCGMIIREG: + case SIOCSMIIREG: + return igb_mii_ioctl(netdev, ifr, cmd); ++#ifdef CONFIG_IGB_PTP + case SIOCSHWTSTAMP: +- return igb_hwtstamp_ioctl(netdev, ifr, cmd); ++ return igb_ptp_hwtstamp_ioctl(netdev, ifr, cmd); ++#endif /* CONFIG_IGB_PTP */ + default: + return -EOPNOTSUPP; + } +@@ -6455,32 +6885,24 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) + { + struct igb_adapter *adapter = hw->back; +- u16 cap_offset; + +- cap_offset = adapter->pdev->pcie_cap; +- if (!cap_offset) ++ if (pcie_capability_read_word(adapter->pdev, reg, value)) + return -E1000_ERR_CONFIG; + +- pci_read_config_word(adapter->pdev, cap_offset + reg, value); +- + return 0; + } + + s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) + { + struct igb_adapter *adapter = hw->back; +- u16 cap_offset; + +- cap_offset = adapter->pdev->pcie_cap; +- if (!cap_offset) ++ if (pcie_capability_write_word(adapter->pdev, reg, *value)) + return -E1000_ERR_CONFIG; + +- pci_write_config_word(adapter->pdev, cap_offset + reg, *value); +- + return 0; + } + +-static void igb_vlan_mode(struct net_device *netdev, u32 features) ++static void igb_vlan_mode(struct net_device *netdev, netdev_features_t features) + { + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; +@@ -6557,15 +6979,24 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u32 spd, u8 dplx) + mac->autoneg = 0; + + /* Make sure dplx is at most 1 bit and lsb of speed is not set +- * for the switch() below to work */ ++ * for the switch() below to work ++ */ + if ((spd & 1) || (dplx & ~1)) + goto err_inval; + +- /* Fiber NIC's only allow 1000 Gbps Full duplex */ +- if ((adapter->hw.phy.media_type == e1000_media_type_internal_serdes) && +- spd != SPEED_1000 && +- dplx != DUPLEX_FULL) +- goto err_inval; ++ /* Fiber NIC's only allow 1000 gbps Full duplex ++ * and 100Mbps Full duplex for 100baseFx sfp ++ */ ++ if (adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { ++ switch (spd + dplx) { ++ case SPEED_10 + DUPLEX_HALF: ++ case SPEED_10 + DUPLEX_FULL: ++ case SPEED_100 + DUPLEX_HALF: ++ goto err_inval; ++ default: ++ break; ++ } ++ } + + switch (spd + dplx) { + case SPEED_10 + DUPLEX_HALF: +@@ -6595,13 +7026,14 @@ err_inval: + return -EINVAL; + } + +-static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake) ++static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, ++ bool runtime) + { + struct net_device *netdev = pci_get_drvdata(pdev); + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 ctrl, rctl, status; +- u32 wufc = adapter->wol; ++ u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol; + #ifdef CONFIG_PM + int retval = 0; + #endif +@@ -6609,7 +7041,7 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake) + netif_device_detach(netdev); + + if (netif_running(netdev)) +- igb_close(netdev); ++ __igb_close(netdev, true); + else + igb_reset(adapter); + +@@ -6661,7 +7093,8 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake) + igb_power_up_link(adapter); + + /* Release control of h/w to f/w. If f/w is AMT enabled, this +- * would have already happened in close and is redundant. */ ++ * would have already happened in close and is redundant. ++ */ + igb_release_hw_control(adapter); + + pci_disable_device(pdev); +@@ -6670,12 +7103,14 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake) + } + + #ifdef CONFIG_PM +-static int igb_suspend(struct pci_dev *pdev, pm_message_t state) ++#ifdef CONFIG_PM_SLEEP ++static int igb_suspend(struct device *dev) + { + int retval; + bool wake; ++ struct pci_dev *pdev = to_pci_dev(dev); + +- retval = __igb_shutdown(pdev, &wake); ++ retval = __igb_shutdown(pdev, &wake, 0); + if (retval) + return retval; + +@@ -6688,9 +7123,11 @@ static int igb_suspend(struct pci_dev *pdev, pm_message_t state) + + return 0; + } ++#endif /* CONFIG_PM_SLEEP */ + +-static int igb_resume(struct pci_dev *pdev) ++static int igb_resume(struct device *dev) + { ++ struct pci_dev *pdev = to_pci_dev(dev); + struct net_device *netdev = pci_get_drvdata(pdev); + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; +@@ -6711,7 +7148,7 @@ static int igb_resume(struct pci_dev *pdev) + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + +- if (igb_init_interrupt_scheme(adapter)) { ++ if (igb_init_interrupt_scheme(adapter, true)) { + dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } +@@ -6719,28 +7156,69 @@ static int igb_resume(struct pci_dev *pdev) + igb_reset(adapter); + + /* let the f/w know that the h/w is now under the control of the +- * driver. */ ++ * driver. ++ */ + igb_get_hw_control(adapter); + + wr32(E1000_WUS, ~0); + +- if (netif_running(netdev)) { +- err = igb_open(netdev); ++ if (netdev->flags & IFF_UP) { ++ rtnl_lock(); ++ err = __igb_open(netdev, true); ++ rtnl_unlock(); + if (err) + return err; + } + + netif_device_attach(netdev); ++ return 0; ++} ++ ++#ifdef CONFIG_PM_RUNTIME ++static int igb_runtime_idle(struct device *dev) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ ++ if (!igb_has_link(adapter)) ++ pm_schedule_suspend(dev, MSEC_PER_SEC * 5); ++ ++ return -EBUSY; ++} ++ ++static int igb_runtime_suspend(struct device *dev) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ int retval; ++ bool wake; ++ ++ retval = __igb_shutdown(pdev, &wake, 1); ++ if (retval) ++ return retval; ++ ++ if (wake) { ++ pci_prepare_to_sleep(pdev); ++ } else { ++ pci_wake_from_d3(pdev, false); ++ pci_set_power_state(pdev, PCI_D3hot); ++ } + + return 0; + } ++ ++static int igb_runtime_resume(struct device *dev) ++{ ++ return igb_resume(dev); ++} ++#endif /* CONFIG_PM_RUNTIME */ + #endif + + static void igb_shutdown(struct pci_dev *pdev) + { + bool wake; + +- __igb_shutdown(pdev, &wake); ++ __igb_shutdown(pdev, &wake, 0); + + if (system_state == SYSTEM_POWER_OFF) { + pci_wake_from_d3(pdev, wake); +@@ -6749,8 +7227,7 @@ static void igb_shutdown(struct pci_dev *pdev) + } + + #ifdef CONFIG_NET_POLL_CONTROLLER +-/* +- * Polling 'interrupt' - used by things like netconsole to send skbs ++/* Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ +@@ -6773,13 +7250,13 @@ static void igb_netpoll(struct net_device *netdev) + #endif /* CONFIG_NET_POLL_CONTROLLER */ + + /** +- * igb_io_error_detected - called when PCI error is detected +- * @pdev: Pointer to PCI device +- * @state: The current pci connection state ++ * igb_io_error_detected - called when PCI error is detected ++ * @pdev: Pointer to PCI device ++ * @state: The current pci connection state + * +- * This function is called after a PCI bus error affecting +- * this device has been detected. +- */ ++ * This function is called after a PCI bus error affecting ++ * this device has been detected. ++ **/ + static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) + { +@@ -6800,12 +7277,12 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev, + } + + /** +- * igb_io_slot_reset - called after the pci bus has been reset. +- * @pdev: Pointer to PCI device ++ * igb_io_slot_reset - called after the pci bus has been reset. ++ * @pdev: Pointer to PCI device + * +- * Restart the card from scratch, as if from a cold-boot. Implementation +- * resembles the first-half of the igb_resume routine. +- */ ++ * Restart the card from scratch, as if from a cold-boot. Implementation ++ * resembles the first-half of the igb_resume routine. ++ **/ + static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) + { + struct net_device *netdev = pci_get_drvdata(pdev); +@@ -6833,8 +7310,9 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) + + err = pci_cleanup_aer_uncorrect_error_status(pdev); + if (err) { +- dev_err(&pdev->dev, "pci_cleanup_aer_uncorrect_error_status " +- "failed 0x%0x\n", err); ++ dev_err(&pdev->dev, ++ "pci_cleanup_aer_uncorrect_error_status failed 0x%0x\n", ++ err); + /* non-fatal, continue */ + } + +@@ -6842,12 +7320,12 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) + } + + /** +- * igb_io_resume - called when traffic can start flowing again. +- * @pdev: Pointer to PCI device ++ * igb_io_resume - called when traffic can start flowing again. ++ * @pdev: Pointer to PCI device + * +- * This callback is called when the error recovery driver tells us that +- * its OK to resume normal operation. Implementation resembles the +- * second-half of the igb_resume routine. ++ * This callback is called when the error recovery driver tells us that ++ * its OK to resume normal operation. Implementation resembles the ++ * second-half of the igb_resume routine. + */ + static void igb_io_resume(struct pci_dev *pdev) + { +@@ -6864,12 +7342,13 @@ static void igb_io_resume(struct pci_dev *pdev) + netif_device_attach(netdev); + + /* let the f/w know that the h/w is now under the control of the +- * driver. */ ++ * driver. ++ */ + igb_get_hw_control(adapter); + } + + static void igb_rar_set_qsel(struct igb_adapter *adapter, u8 *addr, u32 index, +- u8 qsel) ++ u8 qsel) + { + u32 rar_low, rar_high; + struct e1000_hw *hw = &adapter->hw; +@@ -6878,7 +7357,7 @@ static void igb_rar_set_qsel(struct igb_adapter *adapter, u8 *addr, u32 index, + * from network order (big endian) to little endian + */ + rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) | +- ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); ++ ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); + rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); + + /* Indicate to hardware the Address is Valid. */ +@@ -6896,11 +7375,12 @@ static void igb_rar_set_qsel(struct igb_adapter *adapter, u8 *addr, u32 index, + } + + static int igb_set_vf_mac(struct igb_adapter *adapter, +- int vf, unsigned char *mac_addr) ++ int vf, unsigned char *mac_addr) + { + struct e1000_hw *hw = &adapter->hw; + /* VF MAC addresses start at end of receive addresses and moves +- * torwards the first, as a result a collision should not be possible */ ++ * towards the first, as a result a collision should not be possible ++ */ + int rar_entry = hw->mac.rar_entry_count - (vf + 1); + + memcpy(adapter->vf_data[vf].vf_mac_addresses, mac_addr, ETH_ALEN); +@@ -6917,13 +7397,13 @@ static int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) + return -EINVAL; + adapter->vf_data[vf].flags |= IGB_VF_FLAG_PF_SET_MAC; + dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n", mac, vf); +- dev_info(&adapter->pdev->dev, "Reload the VF driver to make this" +- " change effective."); ++ dev_info(&adapter->pdev->dev, ++ "Reload the VF driver to make this change effective."); + if (test_bit(__IGB_DOWN, &adapter->state)) { +- dev_warn(&adapter->pdev->dev, "The VF MAC address has been set," +- " but the PF device is not up.\n"); +- dev_warn(&adapter->pdev->dev, "Bring the PF device up before" +- " attempting to use the VF device.\n"); ++ dev_warn(&adapter->pdev->dev, ++ "The VF MAC address has been set, but the PF device is not up.\n"); ++ dev_warn(&adapter->pdev->dev, ++ "Bring the PF device up before attempting to use the VF device.\n"); + } + return igb_set_vf_mac(adapter, vf, mac); + } +@@ -6950,17 +7430,22 @@ static void igb_set_vf_rate_limit(struct e1000_hw *hw, int vf, int tx_rate, + /* Calculate the rate factor values to set */ + rf_int = link_speed / tx_rate; + rf_dec = (link_speed - (rf_int * tx_rate)); +- rf_dec = (rf_dec * (1<vf_rate_link_speed = 0; + dev_info(&adapter->pdev->dev, +- "Link speed has been changed. VF Transmit " +- "rate is disabled\n"); ++ "Link speed has been changed. VF Transmit rate is disabled\n"); + } + + for (i = 0; i < adapter->vfs_allocated_count; i++) { +@@ -6988,8 +7472,8 @@ static void igb_check_vf_rate_limit(struct igb_adapter *adapter) + adapter->vf_data[i].tx_rate = 0; + + igb_set_vf_rate_limit(&adapter->hw, i, +- adapter->vf_data[i].tx_rate, +- actual_link_speed); ++ adapter->vf_data[i].tx_rate, ++ actual_link_speed); + } + } + +@@ -7015,6 +7499,33 @@ static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate) + return 0; + } + ++static int igb_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, ++ bool setting) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ u32 reg_val, reg_offset; ++ ++ if (!adapter->vfs_allocated_count) ++ return -EOPNOTSUPP; ++ ++ if (vf >= adapter->vfs_allocated_count) ++ return -EINVAL; ++ ++ reg_offset = (hw->mac.type == e1000_82576) ? E1000_DTXSWC : E1000_TXSWC; ++ reg_val = rd32(reg_offset); ++ if (setting) ++ reg_val |= ((1 << vf) | ++ (1 << (vf + E1000_DTXSWC_VLAN_SPOOF_SHIFT))); ++ else ++ reg_val &= ~((1 << vf) | ++ (1 << (vf + E1000_DTXSWC_VLAN_SPOOF_SHIFT))); ++ wr32(reg_offset, reg_val); ++ ++ adapter->vf_data[vf].spoofchk_enabled = setting; ++ return E1000_SUCCESS; ++} ++ + static int igb_ndo_get_vf_config(struct net_device *netdev, + int vf, struct ifla_vf_info *ivi) + { +@@ -7026,6 +7537,7 @@ static int igb_ndo_get_vf_config(struct net_device *netdev, + ivi->tx_rate = adapter->vf_data[vf].tx_rate; + ivi->vlan = adapter->vf_data[vf].pf_vlan; + ivi->qos = adapter->vf_data[vf].pf_qos; ++ ivi->spoofchk = adapter->vf_data[vf].spoofchk_enabled; + return 0; + } + +@@ -7036,6 +7548,9 @@ static void igb_vmm_control(struct igb_adapter *adapter) + + switch (hw->mac.type) { + case e1000_82575: ++ case e1000_i210: ++ case e1000_i211: ++ case e1000_i354: + default: + /* replication is not supported for 82575 */ + return; +@@ -7058,7 +7573,7 @@ static void igb_vmm_control(struct igb_adapter *adapter) + igb_vmdq_set_loopback_pf(hw, true); + igb_vmdq_set_replication_pf(hw, true); + igb_vmdq_set_anti_spoofing_pf(hw, true, +- adapter->vfs_allocated_count); ++ adapter->vfs_allocated_count); + } else { + igb_vmdq_set_loopback_pf(hw, false); + igb_vmdq_set_replication_pf(hw, false); +@@ -7078,16 +7593,27 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba) + /* force threshold to 0. */ + wr32(E1000_DMCTXTH, 0); + +- /* +- * DMA Coalescing high water mark needs to be higher +- * than the RX threshold. set hwm to PBA - 2 * max +- * frame size ++ /* DMA Coalescing high water mark needs to be greater ++ * than the Rx threshold. Set hwm to PBA - max frame ++ * size in 16B units, capping it at PBA - 6KB. + */ +- hwm = pba - (2 * adapter->max_frame_size); ++ hwm = 64 * pba - adapter->max_frame_size / 16; ++ if (hwm < 64 * (pba - 6)) ++ hwm = 64 * (pba - 6); ++ reg = rd32(E1000_FCRTC); ++ reg &= ~E1000_FCRTC_RTH_COAL_MASK; ++ reg |= ((hwm << E1000_FCRTC_RTH_COAL_SHIFT) ++ & E1000_FCRTC_RTH_COAL_MASK); ++ wr32(E1000_FCRTC, reg); ++ ++ /* Set the DMA Coalescing Rx threshold to PBA - 2 * max ++ * frame size, capping it at PBA - 10KB. ++ */ ++ dmac_thr = pba - adapter->max_frame_size / 512; ++ if (dmac_thr < pba - 10) ++ dmac_thr = pba - 10; + reg = rd32(E1000_DMACR); + reg &= ~E1000_DMACR_DMACTHR_MASK; +- dmac_thr = pba - 4; +- + reg |= ((dmac_thr << E1000_DMACR_DMACTHR_SHIFT) + & E1000_DMACR_DMACTHR_MASK); + +@@ -7096,28 +7622,29 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba) + + /* watchdog timer= +-1000 usec in 32usec intervals */ + reg |= (1000 >> 5); ++ ++ /* Disable BMC-to-OS Watchdog Enable */ ++ if (hw->mac.type != e1000_i354) ++ reg &= ~E1000_DMACR_DC_BMC2OSW_EN; ++ + wr32(E1000_DMACR, reg); + +- /* +- * no lower threshold to disable ++ /* no lower threshold to disable + * coalescing(smart fifb)-UTRESH=0 + */ + wr32(E1000_DMCRTRH, 0); +- wr32(E1000_FCRTC, hwm); + + reg = (IGB_DMCTLX_DCFLUSH_DIS | 0x4); + + wr32(E1000_DMCTLX, reg); + +- /* +- * free space in tx packet buffer to wake from ++ /* free space in tx packet buffer to wake from + * DMA coal + */ + wr32(E1000_DMCTXTH, (IGB_MIN_TXPBSIZE - + (IGB_TX_BUF_4096 + adapter->max_frame_size)) >> 6); + +- /* +- * make low power state decision controlled ++ /* make low power state decision controlled + * by DMA coal + */ + reg = rd32(E1000_PCIEMISC); +@@ -7131,4 +7658,96 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba) + } + } + ++/** ++ * igb_read_i2c_byte - Reads 8 bit word over I2C ++ * @hw: pointer to hardware structure ++ * @byte_offset: byte offset to read ++ * @dev_addr: device address ++ * @data: value read ++ * ++ * Performs byte read operation over I2C interface at ++ * a specified device address. ++ **/ ++s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset, ++ u8 dev_addr, u8 *data) ++{ ++ struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); ++ struct i2c_client *this_client = adapter->i2c_client; ++ s32 status; ++ u16 swfw_mask = 0; ++ ++ if (!this_client) ++ return E1000_ERR_I2C; ++ ++ swfw_mask = E1000_SWFW_PHY0_SM; ++ ++ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) ++ != E1000_SUCCESS) ++ return E1000_ERR_SWFW_SYNC; ++ ++ status = i2c_smbus_read_byte_data(this_client, byte_offset); ++ hw->mac.ops.release_swfw_sync(hw, swfw_mask); ++ ++ if (status < 0) ++ return E1000_ERR_I2C; ++ else { ++ *data = status; ++ return E1000_SUCCESS; ++ } ++} ++ ++/** ++ * igb_write_i2c_byte - Writes 8 bit word over I2C ++ * @hw: pointer to hardware structure ++ * @byte_offset: byte offset to write ++ * @dev_addr: device address ++ * @data: value to write ++ * ++ * Performs byte write operation over I2C interface at ++ * a specified device address. ++ **/ ++s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, ++ u8 dev_addr, u8 data) ++{ ++ struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); ++ struct i2c_client *this_client = adapter->i2c_client; ++ s32 status; ++ u16 swfw_mask = E1000_SWFW_PHY0_SM; ++ ++ if (!this_client) ++ return E1000_ERR_I2C; ++ ++ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) ++ return E1000_ERR_SWFW_SYNC; ++ status = i2c_smbus_write_byte_data(this_client, byte_offset, data); ++ hw->mac.ops.release_swfw_sync(hw, swfw_mask); ++ ++ if (status) ++ return E1000_ERR_I2C; ++ else ++ return E1000_SUCCESS; ++ ++} ++ ++int igb_reinit_queues(struct igb_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ int err = 0; ++ ++ if (netif_running(netdev)) ++ igb_close(netdev); ++ ++ igb_clear_interrupt_scheme(adapter); ++ ++ if (igb_init_interrupt_scheme(adapter, true)) { ++ dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); ++ return -ENOMEM; ++ } ++ ++ if (netif_running(netdev)) ++ err = igb_open(netdev); ++ ++ return err; ++} + /* igb_main.c */ +diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c +new file mode 100644 +index 0000000..5d36bd9 +--- /dev/null ++++ b/drivers/net/ethernet/intel/igb/igb_ptp.c +@@ -0,0 +1,895 @@ ++/* PTP Hardware Clock (PHC) driver for the Intel 82576 and 82580 ++ * ++ * Copyright (C) 2011 Richard Cochran ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++#include ++#include ++#include ++#include ++ ++#include "igb.h" ++ ++#define INCVALUE_MASK 0x7fffffff ++#define ISGN 0x80000000 ++ ++/* The 82580 timesync updates the system timer every 8ns by 8ns, ++ * and this update value cannot be reprogrammed. ++ * ++ * Neither the 82576 nor the 82580 offer registers wide enough to hold ++ * nanoseconds time values for very long. For the 82580, SYSTIM always ++ * counts nanoseconds, but the upper 24 bits are not availible. The ++ * frequency is adjusted by changing the 32 bit fractional nanoseconds ++ * register, TIMINCA. ++ * ++ * For the 82576, the SYSTIM register time unit is affect by the ++ * choice of the 24 bit TININCA:IV (incvalue) field. Five bits of this ++ * field are needed to provide the nominal 16 nanosecond period, ++ * leaving 19 bits for fractional nanoseconds. ++ * ++ * We scale the NIC clock cycle by a large factor so that relatively ++ * small clock corrections can be added or subtracted at each clock ++ * tick. The drawbacks of a large factor are a) that the clock ++ * register overflows more quickly (not such a big deal) and b) that ++ * the increment per tick has to fit into 24 bits. As a result we ++ * need to use a shift of 19 so we can fit a value of 16 into the ++ * TIMINCA register. ++ * ++ * ++ * SYSTIMH SYSTIML ++ * +--------------+ +---+---+------+ ++ * 82576 | 32 | | 8 | 5 | 19 | ++ * +--------------+ +---+---+------+ ++ * \________ 45 bits _______/ fract ++ * ++ * +----------+---+ +--------------+ ++ * 82580 | 24 | 8 | | 32 | ++ * +----------+---+ +--------------+ ++ * reserved \______ 40 bits _____/ ++ * ++ * ++ * The 45 bit 82576 SYSTIM overflows every ++ * 2^45 * 10^-9 / 3600 = 9.77 hours. ++ * ++ * The 40 bit 82580 SYSTIM overflows every ++ * 2^40 * 10^-9 / 60 = 18.3 minutes. ++ */ ++ ++#define IGB_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 9) ++#define IGB_PTP_TX_TIMEOUT (HZ * 15) ++#define INCPERIOD_82576 (1 << E1000_TIMINCA_16NS_SHIFT) ++#define INCVALUE_82576_MASK ((1 << E1000_TIMINCA_16NS_SHIFT) - 1) ++#define INCVALUE_82576 (16 << IGB_82576_TSYNC_SHIFT) ++#define IGB_NBITS_82580 40 ++ ++/* SYSTIM read access for the 82576 */ ++static cycle_t igb_ptp_read_82576(const struct cyclecounter *cc) ++{ ++ struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc); ++ struct e1000_hw *hw = &igb->hw; ++ u64 val; ++ u32 lo, hi; ++ ++ lo = rd32(E1000_SYSTIML); ++ hi = rd32(E1000_SYSTIMH); ++ ++ val = ((u64) hi) << 32; ++ val |= lo; ++ ++ return val; ++} ++ ++/* SYSTIM read access for the 82580 */ ++static cycle_t igb_ptp_read_82580(const struct cyclecounter *cc) ++{ ++ struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc); ++ struct e1000_hw *hw = &igb->hw; ++ u32 lo, hi; ++ u64 val; ++ ++ /* The timestamp latches on lowest register read. For the 82580 ++ * the lowest register is SYSTIMR instead of SYSTIML. However we only ++ * need to provide nanosecond resolution, so we just ignore it. ++ */ ++ rd32(E1000_SYSTIMR); ++ lo = rd32(E1000_SYSTIML); ++ hi = rd32(E1000_SYSTIMH); ++ ++ val = ((u64) hi) << 32; ++ val |= lo; ++ ++ return val; ++} ++ ++/* SYSTIM read access for I210/I211 */ ++static void igb_ptp_read_i210(struct igb_adapter *adapter, struct timespec *ts) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ u32 sec, nsec; ++ ++ /* The timestamp latches on lowest register read. For I210/I211, the ++ * lowest register is SYSTIMR. Since we only need to provide nanosecond ++ * resolution, we can ignore it. ++ */ ++ rd32(E1000_SYSTIMR); ++ nsec = rd32(E1000_SYSTIML); ++ sec = rd32(E1000_SYSTIMH); ++ ++ ts->tv_sec = sec; ++ ts->tv_nsec = nsec; ++} ++ ++static void igb_ptp_write_i210(struct igb_adapter *adapter, ++ const struct timespec *ts) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ ++ /* Writing the SYSTIMR register is not necessary as it only provides ++ * sub-nanosecond resolution. ++ */ ++ wr32(E1000_SYSTIML, ts->tv_nsec); ++ wr32(E1000_SYSTIMH, ts->tv_sec); ++} ++ ++/** ++ * igb_ptp_systim_to_hwtstamp - convert system time value to hw timestamp ++ * @adapter: board private structure ++ * @hwtstamps: timestamp structure to update ++ * @systim: unsigned 64bit system time value. ++ * ++ * We need to convert the system time value stored in the RX/TXSTMP registers ++ * into a hwtstamp which can be used by the upper level timestamping functions. ++ * ++ * The 'tmreg_lock' spinlock is used to protect the consistency of the ++ * system time value. This is needed because reading the 64 bit time ++ * value involves reading two (or three) 32 bit registers. The first ++ * read latches the value. Ditto for writing. ++ * ++ * In addition, here have extended the system time with an overflow ++ * counter in software. ++ **/ ++static void igb_ptp_systim_to_hwtstamp(struct igb_adapter *adapter, ++ struct skb_shared_hwtstamps *hwtstamps, ++ u64 systim) ++{ ++ unsigned long flags; ++ u64 ns; ++ ++ switch (adapter->hw.mac.type) { ++ case e1000_82576: ++ case e1000_82580: ++ case e1000_i354: ++ case e1000_i350: ++ spin_lock_irqsave(&adapter->tmreg_lock, flags); ++ ++ ns = timecounter_cyc2time(&adapter->tc, systim); ++ ++ spin_unlock_irqrestore(&adapter->tmreg_lock, flags); ++ ++ memset(hwtstamps, 0, sizeof(*hwtstamps)); ++ hwtstamps->hwtstamp = ns_to_ktime(ns); ++ break; ++ case e1000_i210: ++ case e1000_i211: ++ memset(hwtstamps, 0, sizeof(*hwtstamps)); ++ /* Upper 32 bits contain s, lower 32 bits contain ns. */ ++ hwtstamps->hwtstamp = ktime_set(systim >> 32, ++ systim & 0xFFFFFFFF); ++ break; ++ default: ++ break; ++ } ++} ++ ++/* PTP clock operations */ ++static int igb_ptp_adjfreq_82576(struct ptp_clock_info *ptp, s32 ppb) ++{ ++ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ++ ptp_caps); ++ struct e1000_hw *hw = &igb->hw; ++ int neg_adj = 0; ++ u64 rate; ++ u32 incvalue; ++ ++ if (ppb < 0) { ++ neg_adj = 1; ++ ppb = -ppb; ++ } ++ rate = ppb; ++ rate <<= 14; ++ rate = div_u64(rate, 1953125); ++ ++ incvalue = 16 << IGB_82576_TSYNC_SHIFT; ++ ++ if (neg_adj) ++ incvalue -= rate; ++ else ++ incvalue += rate; ++ ++ wr32(E1000_TIMINCA, INCPERIOD_82576 | (incvalue & INCVALUE_82576_MASK)); ++ ++ return 0; ++} ++ ++static int igb_ptp_adjfreq_82580(struct ptp_clock_info *ptp, s32 ppb) ++{ ++ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ++ ptp_caps); ++ struct e1000_hw *hw = &igb->hw; ++ int neg_adj = 0; ++ u64 rate; ++ u32 inca; ++ ++ if (ppb < 0) { ++ neg_adj = 1; ++ ppb = -ppb; ++ } ++ rate = ppb; ++ rate <<= 26; ++ rate = div_u64(rate, 1953125); ++ ++ inca = rate & INCVALUE_MASK; ++ if (neg_adj) ++ inca |= ISGN; ++ ++ wr32(E1000_TIMINCA, inca); ++ ++ return 0; ++} ++ ++static int igb_ptp_adjtime_82576(struct ptp_clock_info *ptp, s64 delta) ++{ ++ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ++ ptp_caps); ++ unsigned long flags; ++ s64 now; ++ ++ spin_lock_irqsave(&igb->tmreg_lock, flags); ++ ++ now = timecounter_read(&igb->tc); ++ now += delta; ++ timecounter_init(&igb->tc, &igb->cc, now); ++ ++ spin_unlock_irqrestore(&igb->tmreg_lock, flags); ++ ++ return 0; ++} ++ ++static int igb_ptp_adjtime_i210(struct ptp_clock_info *ptp, s64 delta) ++{ ++ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ++ ptp_caps); ++ unsigned long flags; ++ struct timespec now, then = ns_to_timespec(delta); ++ ++ spin_lock_irqsave(&igb->tmreg_lock, flags); ++ ++ igb_ptp_read_i210(igb, &now); ++ now = timespec_add(now, then); ++ igb_ptp_write_i210(igb, (const struct timespec *)&now); ++ ++ spin_unlock_irqrestore(&igb->tmreg_lock, flags); ++ ++ return 0; ++} ++ ++static int igb_ptp_gettime_82576(struct ptp_clock_info *ptp, ++ struct timespec *ts) ++{ ++ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ++ ptp_caps); ++ unsigned long flags; ++ u64 ns; ++ u32 remainder; ++ ++ spin_lock_irqsave(&igb->tmreg_lock, flags); ++ ++ ns = timecounter_read(&igb->tc); ++ ++ spin_unlock_irqrestore(&igb->tmreg_lock, flags); ++ ++ ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder); ++ ts->tv_nsec = remainder; ++ ++ return 0; ++} ++ ++static int igb_ptp_gettime_i210(struct ptp_clock_info *ptp, ++ struct timespec *ts) ++{ ++ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ++ ptp_caps); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&igb->tmreg_lock, flags); ++ ++ igb_ptp_read_i210(igb, ts); ++ ++ spin_unlock_irqrestore(&igb->tmreg_lock, flags); ++ ++ return 0; ++} ++ ++static int igb_ptp_settime_82576(struct ptp_clock_info *ptp, ++ const struct timespec *ts) ++{ ++ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ++ ptp_caps); ++ unsigned long flags; ++ u64 ns; ++ ++ ns = ts->tv_sec * 1000000000ULL; ++ ns += ts->tv_nsec; ++ ++ spin_lock_irqsave(&igb->tmreg_lock, flags); ++ ++ timecounter_init(&igb->tc, &igb->cc, ns); ++ ++ spin_unlock_irqrestore(&igb->tmreg_lock, flags); ++ ++ return 0; ++} ++ ++static int igb_ptp_settime_i210(struct ptp_clock_info *ptp, ++ const struct timespec *ts) ++{ ++ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ++ ptp_caps); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&igb->tmreg_lock, flags); ++ ++ igb_ptp_write_i210(igb, ts); ++ ++ spin_unlock_irqrestore(&igb->tmreg_lock, flags); ++ ++ return 0; ++} ++ ++static int igb_ptp_enable(struct ptp_clock_info *ptp, ++ struct ptp_clock_request *rq, int on) ++{ ++ return -EOPNOTSUPP; ++} ++ ++/** ++ * igb_ptp_tx_work ++ * @work: pointer to work struct ++ * ++ * This work function polls the TSYNCTXCTL valid bit to determine when a ++ * timestamp has been taken for the current stored skb. ++ **/ ++void igb_ptp_tx_work(struct work_struct *work) ++{ ++ struct igb_adapter *adapter = container_of(work, struct igb_adapter, ++ ptp_tx_work); ++ struct e1000_hw *hw = &adapter->hw; ++ u32 tsynctxctl; ++ ++ if (!adapter->ptp_tx_skb) ++ return; ++ ++ if (time_is_before_jiffies(adapter->ptp_tx_start + ++ IGB_PTP_TX_TIMEOUT)) { ++ dev_kfree_skb_any(adapter->ptp_tx_skb); ++ adapter->ptp_tx_skb = NULL; ++ adapter->tx_hwtstamp_timeouts++; ++ dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang"); ++ return; ++ } ++ ++ tsynctxctl = rd32(E1000_TSYNCTXCTL); ++ if (tsynctxctl & E1000_TSYNCTXCTL_VALID) ++ igb_ptp_tx_hwtstamp(adapter); ++ else ++ /* reschedule to check later */ ++ schedule_work(&adapter->ptp_tx_work); ++} ++ ++static void igb_ptp_overflow_check(struct work_struct *work) ++{ ++ struct igb_adapter *igb = ++ container_of(work, struct igb_adapter, ptp_overflow_work.work); ++ struct timespec ts; ++ ++ igb->ptp_caps.gettime(&igb->ptp_caps, &ts); ++ ++ pr_debug("igb overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec); ++ ++ schedule_delayed_work(&igb->ptp_overflow_work, ++ IGB_SYSTIM_OVERFLOW_PERIOD); ++} ++ ++/** ++ * igb_ptp_rx_hang - detect error case when Rx timestamp registers latched ++ * @adapter: private network adapter structure ++ * ++ * This watchdog task is scheduled to detect error case where hardware has ++ * dropped an Rx packet that was timestamped when the ring is full. The ++ * particular error is rare but leaves the device in a state unable to timestamp ++ * any future packets. ++ **/ ++void igb_ptp_rx_hang(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ struct igb_ring *rx_ring; ++ u32 tsyncrxctl = rd32(E1000_TSYNCRXCTL); ++ unsigned long rx_event; ++ int n; ++ ++ if (hw->mac.type != e1000_82576) ++ return; ++ ++ /* If we don't have a valid timestamp in the registers, just update the ++ * timeout counter and exit ++ */ ++ if (!(tsyncrxctl & E1000_TSYNCRXCTL_VALID)) { ++ adapter->last_rx_ptp_check = jiffies; ++ return; ++ } ++ ++ /* Determine the most recent watchdog or rx_timestamp event */ ++ rx_event = adapter->last_rx_ptp_check; ++ for (n = 0; n < adapter->num_rx_queues; n++) { ++ rx_ring = adapter->rx_ring[n]; ++ if (time_after(rx_ring->last_rx_timestamp, rx_event)) ++ rx_event = rx_ring->last_rx_timestamp; ++ } ++ ++ /* Only need to read the high RXSTMP register to clear the lock */ ++ if (time_is_before_jiffies(rx_event + 5 * HZ)) { ++ rd32(E1000_RXSTMPH); ++ adapter->last_rx_ptp_check = jiffies; ++ adapter->rx_hwtstamp_cleared++; ++ dev_warn(&adapter->pdev->dev, "clearing Rx timestamp hang"); ++ } ++} ++ ++/** ++ * igb_ptp_tx_hwtstamp - utility function which checks for TX time stamp ++ * @adapter: Board private structure. ++ * ++ * If we were asked to do hardware stamping and such a time stamp is ++ * available, then it must have been for this skb here because we only ++ * allow only one such packet into the queue. ++ **/ ++void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ struct skb_shared_hwtstamps shhwtstamps; ++ u64 regval; ++ ++ regval = rd32(E1000_TXSTMPL); ++ regval |= (u64)rd32(E1000_TXSTMPH) << 32; ++ ++ igb_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval); ++ skb_tstamp_tx(adapter->ptp_tx_skb, &shhwtstamps); ++ dev_kfree_skb_any(adapter->ptp_tx_skb); ++ adapter->ptp_tx_skb = NULL; ++} ++ ++/** ++ * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp ++ * @q_vector: Pointer to interrupt specific structure ++ * @va: Pointer to address containing Rx buffer ++ * @skb: Buffer containing timestamp and packet ++ * ++ * This function is meant to retrieve a timestamp from the first buffer of an ++ * incoming frame. The value is stored in little endian format starting on ++ * byte 8. ++ **/ ++void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, ++ unsigned char *va, ++ struct sk_buff *skb) ++{ ++ __le64 *regval = (__le64 *)va; ++ ++ /* The timestamp is recorded in little endian format. ++ * DWORD: 0 1 2 3 ++ * Field: Reserved Reserved SYSTIML SYSTIMH ++ */ ++ igb_ptp_systim_to_hwtstamp(q_vector->adapter, skb_hwtstamps(skb), ++ le64_to_cpu(regval[1])); ++} ++ ++/** ++ * igb_ptp_rx_rgtstamp - retrieve Rx timestamp stored in register ++ * @q_vector: Pointer to interrupt specific structure ++ * @skb: Buffer containing timestamp and packet ++ * ++ * This function is meant to retrieve a timestamp from the internal registers ++ * of the adapter and store it in the skb. ++ **/ ++void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, ++ struct sk_buff *skb) ++{ ++ struct igb_adapter *adapter = q_vector->adapter; ++ struct e1000_hw *hw = &adapter->hw; ++ u64 regval; ++ ++ /* If this bit is set, then the RX registers contain the time stamp. No ++ * other packet will be time stamped until we read these registers, so ++ * read the registers to make them available again. Because only one ++ * packet can be time stamped at a time, we know that the register ++ * values must belong to this one here and therefore we don't need to ++ * compare any of the additional attributes stored for it. ++ * ++ * If nothing went wrong, then it should have a shared tx_flags that we ++ * can turn into a skb_shared_hwtstamps. ++ */ ++ if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) ++ return; ++ ++ regval = rd32(E1000_RXSTMPL); ++ regval |= (u64)rd32(E1000_RXSTMPH) << 32; ++ ++ igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); ++} ++ ++/** ++ * igb_ptp_hwtstamp_ioctl - control hardware time stamping ++ * @netdev: ++ * @ifreq: ++ * @cmd: ++ * ++ * Outgoing time stamping can be enabled and disabled. Play nice and ++ * disable it when requested, although it shouldn't case any overhead ++ * when no packet needs it. At most one packet in the queue may be ++ * marked for time stamping, otherwise it would be impossible to tell ++ * for sure to which packet the hardware time stamp belongs. ++ * ++ * Incoming time stamping has to be configured via the hardware ++ * filters. Not all combinations are supported, in particular event ++ * type has to be specified. Matching the kind of event packet is ++ * not supported, with the exception of "all V2 events regardless of ++ * level 2 or 4". ++ **/ ++int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, ++ struct ifreq *ifr, int cmd) ++{ ++ struct igb_adapter *adapter = netdev_priv(netdev); ++ struct e1000_hw *hw = &adapter->hw; ++ struct hwtstamp_config config; ++ u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED; ++ u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; ++ u32 tsync_rx_cfg = 0; ++ bool is_l4 = false; ++ bool is_l2 = false; ++ u32 regval; ++ ++ if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) ++ return -EFAULT; ++ ++ /* reserved for future extensions */ ++ if (config.flags) ++ return -EINVAL; ++ ++ switch (config.tx_type) { ++ case HWTSTAMP_TX_OFF: ++ tsync_tx_ctl = 0; ++ case HWTSTAMP_TX_ON: ++ break; ++ default: ++ return -ERANGE; ++ } ++ ++ switch (config.rx_filter) { ++ case HWTSTAMP_FILTER_NONE: ++ tsync_rx_ctl = 0; ++ break; ++ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; ++ tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE; ++ is_l4 = true; ++ break; ++ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; ++ tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE; ++ is_l4 = true; ++ break; ++ case HWTSTAMP_FILTER_PTP_V2_EVENT: ++ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: ++ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: ++ case HWTSTAMP_FILTER_PTP_V2_SYNC: ++ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: ++ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: ++ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: ++ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: ++ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2; ++ config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; ++ is_l2 = true; ++ is_l4 = true; ++ break; ++ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: ++ case HWTSTAMP_FILTER_ALL: ++ /* 82576 cannot timestamp all packets, which it needs to do to ++ * support both V1 Sync and Delay_Req messages ++ */ ++ if (hw->mac.type != e1000_82576) { ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; ++ config.rx_filter = HWTSTAMP_FILTER_ALL; ++ break; ++ } ++ /* fall through */ ++ default: ++ config.rx_filter = HWTSTAMP_FILTER_NONE; ++ return -ERANGE; ++ } ++ ++ if (hw->mac.type == e1000_82575) { ++ if (tsync_rx_ctl | tsync_tx_ctl) ++ return -EINVAL; ++ return 0; ++ } ++ ++ /* Per-packet timestamping only works if all packets are ++ * timestamped, so enable timestamping in all packets as ++ * long as one Rx filter was configured. ++ */ ++ if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) { ++ tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; ++ tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; ++ config.rx_filter = HWTSTAMP_FILTER_ALL; ++ is_l2 = true; ++ is_l4 = true; ++ ++ if ((hw->mac.type == e1000_i210) || ++ (hw->mac.type == e1000_i211)) { ++ regval = rd32(E1000_RXPBS); ++ regval |= E1000_RXPBS_CFG_TS_EN; ++ wr32(E1000_RXPBS, regval); ++ } ++ } ++ ++ /* enable/disable TX */ ++ regval = rd32(E1000_TSYNCTXCTL); ++ regval &= ~E1000_TSYNCTXCTL_ENABLED; ++ regval |= tsync_tx_ctl; ++ wr32(E1000_TSYNCTXCTL, regval); ++ ++ /* enable/disable RX */ ++ regval = rd32(E1000_TSYNCRXCTL); ++ regval &= ~(E1000_TSYNCRXCTL_ENABLED | E1000_TSYNCRXCTL_TYPE_MASK); ++ regval |= tsync_rx_ctl; ++ wr32(E1000_TSYNCRXCTL, regval); ++ ++ /* define which PTP packets are time stamped */ ++ wr32(E1000_TSYNCRXCFG, tsync_rx_cfg); ++ ++ /* define ethertype filter for timestamped packets */ ++ if (is_l2) ++ wr32(E1000_ETQF(3), ++ (E1000_ETQF_FILTER_ENABLE | /* enable filter */ ++ E1000_ETQF_1588 | /* enable timestamping */ ++ ETH_P_1588)); /* 1588 eth protocol type */ ++ else ++ wr32(E1000_ETQF(3), 0); ++ ++ /* L4 Queue Filter[3]: filter by destination port and protocol */ ++ if (is_l4) { ++ u32 ftqf = (IPPROTO_UDP /* UDP */ ++ | E1000_FTQF_VF_BP /* VF not compared */ ++ | E1000_FTQF_1588_TIME_STAMP /* Enable Timestamping */ ++ | E1000_FTQF_MASK); /* mask all inputs */ ++ ftqf &= ~E1000_FTQF_MASK_PROTO_BP; /* enable protocol check */ ++ ++ wr32(E1000_IMIR(3), htons(PTP_EV_PORT)); ++ wr32(E1000_IMIREXT(3), ++ (E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_BP)); ++ if (hw->mac.type == e1000_82576) { ++ /* enable source port check */ ++ wr32(E1000_SPQF(3), htons(PTP_EV_PORT)); ++ ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP; ++ } ++ wr32(E1000_FTQF(3), ftqf); ++ } else { ++ wr32(E1000_FTQF(3), E1000_FTQF_MASK); ++ } ++ wrfl(); ++ ++ /* clear TX/RX time stamp registers, just to be sure */ ++ regval = rd32(E1000_TXSTMPL); ++ regval = rd32(E1000_TXSTMPH); ++ regval = rd32(E1000_RXSTMPL); ++ regval = rd32(E1000_RXSTMPH); ++ ++ return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? ++ -EFAULT : 0; ++} ++ ++void igb_ptp_init(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ ++ switch (hw->mac.type) { ++ case e1000_82576: ++ snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); ++ adapter->ptp_caps.owner = THIS_MODULE; ++ adapter->ptp_caps.max_adj = 999999881; ++ adapter->ptp_caps.n_ext_ts = 0; ++ adapter->ptp_caps.pps = 0; ++ adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82576; ++ adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576; ++ adapter->ptp_caps.gettime = igb_ptp_gettime_82576; ++ adapter->ptp_caps.settime = igb_ptp_settime_82576; ++ adapter->ptp_caps.enable = igb_ptp_enable; ++ adapter->cc.read = igb_ptp_read_82576; ++ adapter->cc.mask = CLOCKSOURCE_MASK(64); ++ adapter->cc.mult = 1; ++ adapter->cc.shift = IGB_82576_TSYNC_SHIFT; ++ /* Dial the nominal frequency. */ ++ wr32(E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); ++ break; ++ case e1000_82580: ++ case e1000_i354: ++ case e1000_i350: ++ snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); ++ adapter->ptp_caps.owner = THIS_MODULE; ++ adapter->ptp_caps.max_adj = 62499999; ++ adapter->ptp_caps.n_ext_ts = 0; ++ adapter->ptp_caps.pps = 0; ++ adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; ++ adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576; ++ adapter->ptp_caps.gettime = igb_ptp_gettime_82576; ++ adapter->ptp_caps.settime = igb_ptp_settime_82576; ++ adapter->ptp_caps.enable = igb_ptp_enable; ++ adapter->cc.read = igb_ptp_read_82580; ++ adapter->cc.mask = CLOCKSOURCE_MASK(IGB_NBITS_82580); ++ adapter->cc.mult = 1; ++ adapter->cc.shift = 0; ++ /* Enable the timer functions by clearing bit 31. */ ++ wr32(E1000_TSAUXC, 0x0); ++ break; ++ case e1000_i210: ++ case e1000_i211: ++ snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); ++ adapter->ptp_caps.owner = THIS_MODULE; ++ adapter->ptp_caps.max_adj = 62499999; ++ adapter->ptp_caps.n_ext_ts = 0; ++ adapter->ptp_caps.pps = 0; ++ adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; ++ adapter->ptp_caps.adjtime = igb_ptp_adjtime_i210; ++ adapter->ptp_caps.gettime = igb_ptp_gettime_i210; ++ adapter->ptp_caps.settime = igb_ptp_settime_i210; ++ adapter->ptp_caps.enable = igb_ptp_enable; ++ /* Enable the timer functions by clearing bit 31. */ ++ wr32(E1000_TSAUXC, 0x0); ++ break; ++ default: ++ adapter->ptp_clock = NULL; ++ return; ++ } ++ ++ wrfl(); ++ ++ spin_lock_init(&adapter->tmreg_lock); ++ INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work); ++ ++ /* Initialize the clock and overflow work for devices that need it. */ ++ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { ++ struct timespec ts = ktime_to_timespec(ktime_get_real()); ++ ++ igb_ptp_settime_i210(&adapter->ptp_caps, &ts); ++ } else { ++ timecounter_init(&adapter->tc, &adapter->cc, ++ ktime_to_ns(ktime_get_real())); ++ ++ INIT_DELAYED_WORK(&adapter->ptp_overflow_work, ++ igb_ptp_overflow_check); ++ ++ schedule_delayed_work(&adapter->ptp_overflow_work, ++ IGB_SYSTIM_OVERFLOW_PERIOD); ++ } ++ ++ /* Initialize the time sync interrupts for devices that support it. */ ++ if (hw->mac.type >= e1000_82580) { ++ wr32(E1000_TSIM, E1000_TSIM_TXTS); ++ wr32(E1000_IMS, E1000_IMS_TS); ++ } ++ ++ adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps); ++ if (IS_ERR(adapter->ptp_clock)) { ++ adapter->ptp_clock = NULL; ++ dev_err(&adapter->pdev->dev, "ptp_clock_register failed\n"); ++ } else { ++ dev_info(&adapter->pdev->dev, "added PHC on %s\n", ++ adapter->netdev->name); ++ adapter->flags |= IGB_FLAG_PTP; ++ } ++} ++ ++/** ++ * igb_ptp_stop - Disable PTP device and stop the overflow check. ++ * @adapter: Board private structure. ++ * ++ * This function stops the PTP support and cancels the delayed work. ++ **/ ++void igb_ptp_stop(struct igb_adapter *adapter) ++{ ++ switch (adapter->hw.mac.type) { ++ case e1000_82576: ++ case e1000_82580: ++ case e1000_i354: ++ case e1000_i350: ++ cancel_delayed_work_sync(&adapter->ptp_overflow_work); ++ break; ++ case e1000_i210: ++ case e1000_i211: ++ /* No delayed work to cancel. */ ++ break; ++ default: ++ return; ++ } ++ ++ cancel_work_sync(&adapter->ptp_tx_work); ++ if (adapter->ptp_tx_skb) { ++ dev_kfree_skb_any(adapter->ptp_tx_skb); ++ adapter->ptp_tx_skb = NULL; ++ } ++ ++ if (adapter->ptp_clock) { ++ ptp_clock_unregister(adapter->ptp_clock); ++ dev_info(&adapter->pdev->dev, "removed PHC on %s\n", ++ adapter->netdev->name); ++ adapter->flags &= ~IGB_FLAG_PTP; ++ } ++} ++ ++/** ++ * igb_ptp_reset - Re-enable the adapter for PTP following a reset. ++ * @adapter: Board private structure. ++ * ++ * This function handles the reset work required to re-enable the PTP device. ++ **/ ++void igb_ptp_reset(struct igb_adapter *adapter) ++{ ++ struct e1000_hw *hw = &adapter->hw; ++ ++ if (!(adapter->flags & IGB_FLAG_PTP)) ++ return; ++ ++ switch (adapter->hw.mac.type) { ++ case e1000_82576: ++ /* Dial the nominal frequency. */ ++ wr32(E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); ++ break; ++ case e1000_82580: ++ case e1000_i354: ++ case e1000_i350: ++ case e1000_i210: ++ case e1000_i211: ++ /* Enable the timer functions and interrupts. */ ++ wr32(E1000_TSAUXC, 0x0); ++ wr32(E1000_TSIM, E1000_TSIM_TXTS); ++ wr32(E1000_IMS, E1000_IMS_TS); ++ break; ++ default: ++ /* No work to do. */ ++ return; ++ } ++ ++ /* Re-initialize the timer. */ ++ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { ++ struct timespec ts = ktime_to_timespec(ktime_get_real()); ++ ++ igb_ptp_settime_i210(&adapter->ptp_caps, &ts); ++ } else { ++ timecounter_init(&adapter->tc, &adapter->cc, ++ ktime_to_ns(ktime_get_real())); ++ } ++} +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h +index a8368d5..2aa247f 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h +@@ -629,4 +629,9 @@ extern u8 ixgbe_fcoe_setapp(struct ixgbe_adapter *adapter, u8 up); + extern int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type); + #endif /* IXGBE_FCOE */ + ++static inline struct netdev_queue *txring_txq(const struct ixgbe_ring *ring) ++{ ++ return netdev_get_tx_queue(ring->netdev, ring->queue_index); ++} ++ + #endif /* _IXGBE_H_ */ +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +index 70d58c3..ea7d2c3 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +@@ -1764,6 +1764,8 @@ static u16 ixgbe_clean_test_rings(struct ixgbe_ring *rx_ring, + staterr = le32_to_cpu(rx_desc->wb.upper.status_error); + } + ++ netdev_tx_reset_queue(txring_txq(tx_ring)); ++ + /* re-map buffers to ring, store next to clean values */ + ixgbe_alloc_rx_buffers(rx_ring, count); + rx_ring->next_to_clean = rx_ntc; +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +index d93eee1..7c4914b 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +@@ -834,6 +834,9 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, + return true; + } + ++ netdev_tx_completed_queue(txring_txq(tx_ring), ++ total_packets, total_bytes); ++ + #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) + if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) && + (ixgbe_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD))) { +@@ -3937,6 +3940,8 @@ static void ixgbe_clean_tx_ring(struct ixgbe_ring *tx_ring) + ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info); + } + ++ netdev_tx_reset_queue(txring_txq(tx_ring)); ++ + size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count; + memset(tx_ring->tx_buffer_info, 0, size); + +@@ -6595,6 +6600,8 @@ static void ixgbe_tx_map(struct ixgbe_ring *tx_ring, + tx_buffer_info->gso_segs = gso_segs; + tx_buffer_info->skb = skb; + ++ netdev_tx_sent_queue(txring_txq(tx_ring), tx_buffer_info->bytecount); ++ + /* set the timestamp */ + first->time_stamp = jiffies; + +diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c +index 57be855..c8ef11b 100644 +--- a/drivers/net/ethernet/marvell/skge.c ++++ b/drivers/net/ethernet/marvell/skge.c +@@ -2797,6 +2797,8 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, + td->control = BMU_OWN | BMU_SW | BMU_STF | control | len; + wmb(); + ++ netdev_sent_queue(dev, skb->len); ++ + skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START); + + netif_printk(skge, tx_queued, KERN_DEBUG, skge->netdev, +@@ -2816,11 +2818,9 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, + + + /* Free resources associated with this reing element */ +-static void skge_tx_free(struct skge_port *skge, struct skge_element *e, +- u32 control) ++static inline void skge_tx_unmap(struct pci_dev *pdev, struct skge_element *e, ++ u32 control) + { +- struct pci_dev *pdev = skge->hw->pdev; +- + /* skb header vs. fragment */ + if (control & BMU_STF) + pci_unmap_single(pdev, dma_unmap_addr(e, mapaddr), +@@ -2830,13 +2830,6 @@ static void skge_tx_free(struct skge_port *skge, struct skge_element *e, + pci_unmap_page(pdev, dma_unmap_addr(e, mapaddr), + dma_unmap_len(e, maplen), + PCI_DMA_TODEVICE); +- +- if (control & BMU_EOF) { +- netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev, +- "tx done slot %td\n", e - skge->tx_ring.start); +- +- dev_kfree_skb(e->skb); +- } + } + + /* Free all buffers in transmit ring */ +@@ -2847,10 +2840,15 @@ static void skge_tx_clean(struct net_device *dev) + + for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { + struct skge_tx_desc *td = e->desc; +- skge_tx_free(skge, e, td->control); ++ ++ skge_tx_unmap(skge->hw->pdev, e, td->control); ++ ++ if (td->control & BMU_EOF) ++ dev_kfree_skb(e->skb); + td->control = 0; + } + ++ netdev_reset_queue(dev); + skge->tx_ring.to_clean = e; + } + +@@ -3111,6 +3109,7 @@ static void skge_tx_done(struct net_device *dev) + struct skge_port *skge = netdev_priv(dev); + struct skge_ring *ring = &skge->tx_ring; + struct skge_element *e; ++ unsigned int bytes_compl = 0, pkts_compl = 0; + + skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); + +@@ -3120,8 +3119,20 @@ static void skge_tx_done(struct net_device *dev) + if (control & BMU_OWN) + break; + +- skge_tx_free(skge, e, control); ++ skge_tx_unmap(skge->hw->pdev, e, control); ++ ++ if (control & BMU_EOF) { ++ netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev, ++ "tx done slot %td\n", ++ e - skge->tx_ring.start); ++ ++ pkts_compl++; ++ bytes_compl += e->skb->len; ++ ++ dev_kfree_skb(e->skb); ++ } + } ++ netdev_completed_queue(dev, pkts_compl, bytes_compl); + skge->tx_ring.to_clean = e; + + /* Can run lockless until we need to synchronize to restart queue. */ +diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c +index 94f9a8f..e1faff8 100644 +--- a/drivers/net/ethernet/marvell/sky2.c ++++ b/drivers/net/ethernet/marvell/sky2.c +@@ -1121,6 +1121,7 @@ static void tx_init(struct sky2_port *sky2) + sky2->tx_prod = sky2->tx_cons = 0; + sky2->tx_tcpsum = 0; + sky2->tx_last_mss = 0; ++ netdev_reset_queue(sky2->netdev); + + le = get_tx_le(sky2, &sky2->tx_prod); + le->addr = 0; +@@ -1983,6 +1984,7 @@ static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb, + if (tx_avail(sky2) <= MAX_SKB_TX_LE) + netif_stop_queue(dev); + ++ netdev_sent_queue(dev, skb->len); + sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod); + + return NETDEV_TX_OK; +@@ -2014,7 +2016,8 @@ mapping_error: + static void sky2_tx_complete(struct sky2_port *sky2, u16 done) + { + struct net_device *dev = sky2->netdev; +- unsigned idx; ++ u16 idx; ++ unsigned int bytes_compl = 0, pkts_compl = 0; + + BUG_ON(done >= sky2->tx_ring_size); + +@@ -2029,10 +2032,8 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) + netif_printk(sky2, tx_done, KERN_DEBUG, dev, + "tx done %u\n", idx); + +- u64_stats_update_begin(&sky2->tx_stats.syncp); +- ++sky2->tx_stats.packets; +- sky2->tx_stats.bytes += skb->len; +- u64_stats_update_end(&sky2->tx_stats.syncp); ++ pkts_compl++; ++ bytes_compl += skb->len; + + re->skb = NULL; + dev_kfree_skb_any(skb); +@@ -2043,6 +2044,13 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) + + sky2->tx_cons = idx; + smp_mb(); ++ ++ netdev_completed_queue(dev, pkts_compl, bytes_compl); ++ ++ u64_stats_update_begin(&sky2->tx_stats.syncp); ++ sky2->tx_stats.packets += pkts_compl; ++ sky2->tx_stats.bytes += bytes_compl; ++ u64_stats_update_end(&sky2->tx_stats.syncp); + } + + static void sky2_tx_reset(struct sky2_hw *hw, unsigned port) +diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +index 0778edc..944b5b2 100644 +--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c ++++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +@@ -594,8 +594,6 @@ static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size) + unsigned i; + + if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) { +- dev_err(dev, "Unable to load %s firmware image via hotplug\n", +- mgp->fw_name); + status = -EINVAL; + goto abort_with_nothing; + } +diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c +index 1c61d36..659e394 100644 +--- a/drivers/net/ethernet/nvidia/forcedeth.c ++++ b/drivers/net/ethernet/nvidia/forcedeth.c +@@ -1849,6 +1849,7 @@ static void nv_init_tx(struct net_device *dev) + np->last_tx.ex = &np->tx_ring.ex[np->tx_ring_size-1]; + np->get_tx_ctx = np->put_tx_ctx = np->first_tx_ctx = np->tx_skb; + np->last_tx_ctx = &np->tx_skb[np->tx_ring_size-1]; ++ netdev_reset_queue(np->dev); + np->tx_pkts_in_progress = 0; + np->tx_change_owner = NULL; + np->tx_end_flip = NULL; +@@ -2194,6 +2195,9 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) + + /* set tx flags */ + start_tx->flaglen |= cpu_to_le32(tx_flags | tx_flags_extra); ++ ++ netdev_sent_queue(np->dev, skb->len); ++ + np->put_tx.orig = put_tx; + + spin_unlock_irqrestore(&np->lock, flags); +@@ -2338,6 +2342,9 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, + + /* set tx flags */ + start_tx->flaglen |= cpu_to_le32(tx_flags | tx_flags_extra); ++ ++ netdev_sent_queue(np->dev, skb->len); ++ + np->put_tx.ex = put_tx; + + spin_unlock_irqrestore(&np->lock, flags); +@@ -2375,6 +2382,7 @@ static int nv_tx_done(struct net_device *dev, int limit) + u32 flags; + int tx_work = 0; + struct ring_desc *orig_get_tx = np->get_tx.orig; ++ unsigned int bytes_compl = 0; + + while ((np->get_tx.orig != np->put_tx.orig) && + !((flags = le32_to_cpu(np->get_tx.orig->flaglen)) & NV_TX_VALID) && +@@ -2391,6 +2399,7 @@ static int nv_tx_done(struct net_device *dev, int limit) + dev->stats.tx_packets++; + dev->stats.tx_bytes += np->get_tx_ctx->skb->len; + } ++ bytes_compl += np->get_tx_ctx->skb->len; + dev_kfree_skb_any(np->get_tx_ctx->skb); + np->get_tx_ctx->skb = NULL; + tx_work++; +@@ -2404,6 +2413,7 @@ static int nv_tx_done(struct net_device *dev, int limit) + dev->stats.tx_packets++; + dev->stats.tx_bytes += np->get_tx_ctx->skb->len; + } ++ bytes_compl += np->get_tx_ctx->skb->len; + dev_kfree_skb_any(np->get_tx_ctx->skb); + np->get_tx_ctx->skb = NULL; + tx_work++; +@@ -2414,6 +2424,9 @@ static int nv_tx_done(struct net_device *dev, int limit) + if (unlikely(np->get_tx_ctx++ == np->last_tx_ctx)) + np->get_tx_ctx = np->first_tx_ctx; + } ++ ++ netdev_completed_queue(np->dev, tx_work, bytes_compl); ++ + if (unlikely((np->tx_stop == 1) && (np->get_tx.orig != orig_get_tx))) { + np->tx_stop = 0; + netif_wake_queue(dev); +@@ -2427,6 +2440,7 @@ static int nv_tx_done_optimized(struct net_device *dev, int limit) + u32 flags; + int tx_work = 0; + struct ring_desc_ex *orig_get_tx = np->get_tx.ex; ++ unsigned long bytes_cleaned = 0; + + while ((np->get_tx.ex != np->put_tx.ex) && + !((flags = le32_to_cpu(np->get_tx.ex->flaglen)) & NV_TX2_VALID) && +@@ -2447,6 +2461,7 @@ static int nv_tx_done_optimized(struct net_device *dev, int limit) + dev->stats.tx_bytes += np->get_tx_ctx->skb->len; + } + ++ bytes_cleaned += np->get_tx_ctx->skb->len; + dev_kfree_skb_any(np->get_tx_ctx->skb); + np->get_tx_ctx->skb = NULL; + tx_work++; +@@ -2454,11 +2469,15 @@ static int nv_tx_done_optimized(struct net_device *dev, int limit) + if (np->tx_limit) + nv_tx_flip_ownership(dev); + } ++ + if (unlikely(np->get_tx.ex++ == np->last_tx.ex)) + np->get_tx.ex = np->first_tx.ex; + if (unlikely(np->get_tx_ctx++ == np->last_tx_ctx)) + np->get_tx_ctx = np->first_tx_ctx; + } ++ ++ netdev_completed_queue(np->dev, tx_work, bytes_cleaned); ++ + if (unlikely((np->tx_stop == 1) && (np->get_tx.ex != orig_get_tx))) { + np->tx_stop = 0; + netif_wake_queue(dev); +diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c +index 807d515..3b19bf6 100644 +--- a/drivers/net/ethernet/sfc/tx.c ++++ b/drivers/net/ethernet/sfc/tx.c +@@ -31,7 +31,9 @@ + #define EFX_TXQ_THRESHOLD(_efx) ((_efx)->txq_entries / 2u) + + static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue, +- struct efx_tx_buffer *buffer) ++ struct efx_tx_buffer *buffer, ++ unsigned int *pkts_compl, ++ unsigned int *bytes_compl) + { + if (buffer->unmap_len) { + struct pci_dev *pci_dev = tx_queue->efx->pci_dev; +@@ -48,6 +50,8 @@ static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue, + } + + if (buffer->skb) { ++ (*pkts_compl)++; ++ (*bytes_compl) += buffer->skb->len; + dev_kfree_skb_any((struct sk_buff *) buffer->skb); + buffer->skb = NULL; + netif_vdbg(tx_queue->efx, tx_done, tx_queue->efx->net_dev, +@@ -269,6 +273,8 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb) + buffer->skb = skb; + buffer->continuation = false; + ++ netdev_tx_sent_queue(tx_queue->core_txq, skb->len); ++ + /* Pass off to hardware */ + efx_nic_push_buffers(tx_queue); + +@@ -286,10 +292,11 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb) + unwind: + /* Work backwards until we hit the original insert pointer value */ + while (tx_queue->insert_count != tx_queue->write_count) { ++ unsigned int pkts_compl = 0, bytes_compl = 0; + --tx_queue->insert_count; + insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask; + buffer = &tx_queue->buffer[insert_ptr]; +- efx_dequeue_buffer(tx_queue, buffer); ++ efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl); + buffer->len = 0; + } + +@@ -312,7 +319,9 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb) + * specified index. + */ + static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue, +- unsigned int index) ++ unsigned int index, ++ unsigned int *pkts_compl, ++ unsigned int *bytes_compl) + { + struct efx_nic *efx = tx_queue->efx; + unsigned int stop_index, read_ptr; +@@ -330,7 +339,7 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue, + return; + } + +- efx_dequeue_buffer(tx_queue, buffer); ++ efx_dequeue_buffer(tx_queue, buffer, pkts_compl, bytes_compl); + buffer->continuation = true; + buffer->len = 0; + +@@ -441,10 +450,12 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) + { + unsigned fill_level; + struct efx_nic *efx = tx_queue->efx; ++ unsigned int pkts_compl = 0, bytes_compl = 0; + + EFX_BUG_ON_PARANOID(index > tx_queue->ptr_mask); + +- efx_dequeue_buffers(tx_queue, index); ++ efx_dequeue_buffers(tx_queue, index, &pkts_compl, &bytes_compl); ++ netdev_tx_completed_queue(tx_queue->core_txq, pkts_compl, bytes_compl); + + /* See if we need to restart the netif queue. This barrier + * separates the update of read_count from the test of the +@@ -534,13 +545,15 @@ void efx_release_tx_buffers(struct efx_tx_queue *tx_queue) + + /* Free any buffers left in the ring */ + while (tx_queue->read_count != tx_queue->write_count) { ++ unsigned int pkts_compl = 0, bytes_compl = 0; + buffer = &tx_queue->buffer[tx_queue->read_count & tx_queue->ptr_mask]; +- efx_dequeue_buffer(tx_queue, buffer); ++ efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl); + buffer->continuation = true; + buffer->len = 0; + + ++tx_queue->read_count; + } ++ netdev_tx_reset_queue(tx_queue->core_txq); + } + + void efx_fini_tx_queue(struct efx_tx_queue *tx_queue) +@@ -1179,6 +1192,8 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, + goto mem_err; + } + ++ netdev_tx_sent_queue(tx_queue->core_txq, skb->len); ++ + /* Pass off to hardware */ + efx_nic_push_buffers(tx_queue); + +diff --git a/drivers/net/ethernet/smsc/smc91c92_cs.c b/drivers/net/ethernet/smsc/smc91c92_cs.c +index cbfa981..41da081 100644 +--- a/drivers/net/ethernet/smsc/smc91c92_cs.c ++++ b/drivers/net/ethernet/smsc/smc91c92_cs.c +@@ -649,10 +649,8 @@ static int osi_load_firmware(struct pcmcia_device *link) + int i, err; + + err = request_firmware(&fw, FIRMWARE_NAME, &link->dev); +- if (err) { +- pr_err("Failed to load firmware \"%s\"\n", FIRMWARE_NAME); ++ if (err) + return err; +- } + + /* Download the Seven of Diamonds firmware */ + for (i = 0; i < fw->size; i++) { +diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c +index fd40988..b8fda6e 100644 +--- a/drivers/net/ethernet/sun/cassini.c ++++ b/drivers/net/ethernet/sun/cassini.c +@@ -809,45 +809,42 @@ static int cas_reset_mii_phy(struct cas *cp) + return limit <= 0; + } + +-static int cas_saturn_firmware_init(struct cas *cp) ++static void cas_saturn_firmware_init(struct cas *cp) + { + const struct firmware *fw; + const char fw_name[] = "sun/cassini.bin"; + int err; + + if (PHY_NS_DP83065 != cp->phy_id) +- return 0; ++ return; + + err = request_firmware(&fw, fw_name, &cp->pdev->dev); +- if (err) { +- pr_err("Failed to load firmware \"%s\"\n", +- fw_name); +- return err; +- } ++ if (err) ++ return; + if (fw->size < 2) { + pr_err("bogus length %zu in \"%s\"\n", + fw->size, fw_name); +- err = -EINVAL; + goto out; + } + cp->fw_load_addr= fw->data[1] << 8 | fw->data[0]; + cp->fw_size = fw->size - 2; + cp->fw_data = vmalloc(cp->fw_size); + if (!cp->fw_data) { +- err = -ENOMEM; + pr_err("\"%s\" Failed %d\n", fw_name, err); + goto out; + } + memcpy(cp->fw_data, &fw->data[2], cp->fw_size); + out: + release_firmware(fw); +- return err; + } + + static void cas_saturn_firmware_load(struct cas *cp) + { + int i; + ++ if (!cp->fw_data) ++ return; ++ + cas_phy_powerdown(cp); + + /* expanded memory access mode */ +@@ -5088,8 +5085,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, + if (cas_check_invariants(cp)) + goto err_out_iounmap; + if (cp->cas_flags & CAS_FLAG_SATURN) +- if (cas_saturn_firmware_init(cp)) +- goto err_out_iounmap; ++ cas_saturn_firmware_init(cp); + + cp->init_block = (struct cas_init_block *) + pci_alloc_consistent(pdev, sizeof(struct cas_init_block), +diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c +index e4260ab..8832f3d 100644 +--- a/drivers/net/hamradio/yam.c ++++ b/drivers/net/hamradio/yam.c +@@ -373,11 +373,8 @@ static unsigned char *add_mcs(unsigned char *bits, int bitrate, + } + err = request_firmware(&fw, fw_name[predef], &pdev->dev); + platform_device_unregister(pdev); +- if (err) { +- printk(KERN_ERR "Failed to load firmware \"%s\"\n", +- fw_name[predef]); ++ if (err) + return NULL; +- } + if (fw->size != YAM_FPGA_SIZE) { + printk(KERN_ERR "Bogus length %zu in firmware \"%s\"\n", + fw->size, fw_name[predef]); +diff --git a/drivers/net/hyperv/Kconfig b/drivers/net/hyperv/Kconfig +new file mode 100644 +index 0000000..936968d +--- /dev/null ++++ b/drivers/net/hyperv/Kconfig +@@ -0,0 +1,5 @@ ++config HYPERV_NET ++ tristate "Microsoft Hyper-V virtual network driver" ++ depends on HYPERV ++ help ++ Select this option to enable the Hyper-V virtual network driver. +diff --git a/drivers/net/hyperv/Makefile b/drivers/net/hyperv/Makefile +new file mode 100644 +index 0000000..c8a6682 +--- /dev/null ++++ b/drivers/net/hyperv/Makefile +@@ -0,0 +1,3 @@ ++obj-$(CONFIG_HYPERV_NET) += hv_netvsc.o ++ ++hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o +diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h +new file mode 100644 +index 0000000..c358245 +--- /dev/null ++++ b/drivers/net/hyperv/hyperv_net.h +@@ -0,0 +1,1197 @@ ++/* ++ * ++ * Copyright (c) 2011, Microsoft Corporation. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple ++ * Place - Suite 330, Boston, MA 02111-1307 USA. ++ * ++ * Authors: ++ * Haiyang Zhang ++ * Hank Janssen ++ * K. Y. Srinivasan ++ * ++ */ ++ ++#ifndef _HYPERV_NET_H ++#define _HYPERV_NET_H ++ ++#include ++#include ++ ++/* Fwd declaration */ ++struct hv_netvsc_packet; ++ ++/* Represent the xfer page packet which contains 1 or more netvsc packet */ ++struct xferpage_packet { ++ struct list_head list_ent; ++ ++ /* # of netvsc packets this xfer packet contains */ ++ u32 count; ++}; ++ ++/* ++ * Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame ++ * within the RNDIS ++ */ ++struct hv_netvsc_packet { ++ /* Bookkeeping stuff */ ++ struct list_head list_ent; ++ ++ struct hv_device *device; ++ bool is_data_pkt; ++ u16 vlan_tci; ++ ++ /* ++ * Valid only for receives when we break a xfer page packet ++ * into multiple netvsc packets ++ */ ++ struct xferpage_packet *xfer_page_pkt; ++ ++ union { ++ struct { ++ u64 recv_completion_tid; ++ void *recv_completion_ctx; ++ void (*recv_completion)(void *context); ++ } recv; ++ struct { ++ u64 send_completion_tid; ++ void *send_completion_ctx; ++ void (*send_completion)(void *context); ++ } send; ++ } completion; ++ ++ /* This points to the memory after page_buf */ ++ void *extension; ++ ++ u32 total_data_buflen; ++ /* Points to the send/receive buffer where the ethernet frame is */ ++ void *data; ++ u32 page_buf_cnt; ++ struct hv_page_buffer page_buf[0]; ++}; ++ ++struct netvsc_device_info { ++ unsigned char mac_adr[6]; ++ bool link_state; /* 0 - link up, 1 - link down */ ++ int ring_size; ++}; ++ ++enum rndis_device_state { ++ RNDIS_DEV_UNINITIALIZED = 0, ++ RNDIS_DEV_INITIALIZING, ++ RNDIS_DEV_INITIALIZED, ++ RNDIS_DEV_DATAINITIALIZED, ++}; ++ ++struct rndis_device { ++ struct netvsc_device *net_dev; ++ ++ enum rndis_device_state state; ++ bool link_state; ++ atomic_t new_req_id; ++ ++ spinlock_t request_lock; ++ struct list_head req_list; ++ ++ unsigned char hw_mac_adr[ETH_ALEN]; ++}; ++ ++ ++/* Interface */ ++int netvsc_device_add(struct hv_device *device, void *additional_info); ++int netvsc_device_remove(struct hv_device *device); ++int netvsc_send(struct hv_device *device, ++ struct hv_netvsc_packet *packet); ++void netvsc_linkstatus_callback(struct hv_device *device_obj, ++ unsigned int status); ++int netvsc_recv_callback(struct hv_device *device_obj, ++ struct hv_netvsc_packet *packet); ++int rndis_filter_open(struct hv_device *dev); ++int rndis_filter_close(struct hv_device *dev); ++int rndis_filter_device_add(struct hv_device *dev, ++ void *additional_info); ++void rndis_filter_device_remove(struct hv_device *dev); ++int rndis_filter_receive(struct hv_device *dev, ++ struct hv_netvsc_packet *pkt); ++ ++ ++ ++int rndis_filter_send(struct hv_device *dev, ++ struct hv_netvsc_packet *pkt); ++ ++int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter); ++ ++ ++#define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF) ++ ++#define NVSP_PROTOCOL_VERSION_1 2 ++#define NVSP_PROTOCOL_VERSION_2 0x30002 ++ ++enum { ++ NVSP_MSG_TYPE_NONE = 0, ++ ++ /* Init Messages */ ++ NVSP_MSG_TYPE_INIT = 1, ++ NVSP_MSG_TYPE_INIT_COMPLETE = 2, ++ ++ NVSP_VERSION_MSG_START = 100, ++ ++ /* Version 1 Messages */ ++ NVSP_MSG1_TYPE_SEND_NDIS_VER = NVSP_VERSION_MSG_START, ++ ++ NVSP_MSG1_TYPE_SEND_RECV_BUF, ++ NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE, ++ NVSP_MSG1_TYPE_REVOKE_RECV_BUF, ++ ++ NVSP_MSG1_TYPE_SEND_SEND_BUF, ++ NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE, ++ NVSP_MSG1_TYPE_REVOKE_SEND_BUF, ++ ++ NVSP_MSG1_TYPE_SEND_RNDIS_PKT, ++ NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE, ++ ++ /* Version 2 messages */ ++ NVSP_MSG2_TYPE_SEND_CHIMNEY_DELEGATED_BUF, ++ NVSP_MSG2_TYPE_SEND_CHIMNEY_DELEGATED_BUF_COMP, ++ NVSP_MSG2_TYPE_REVOKE_CHIMNEY_DELEGATED_BUF, ++ ++ NVSP_MSG2_TYPE_RESUME_CHIMNEY_RX_INDICATION, ++ ++ NVSP_MSG2_TYPE_TERMINATE_CHIMNEY, ++ NVSP_MSG2_TYPE_TERMINATE_CHIMNEY_COMP, ++ ++ NVSP_MSG2_TYPE_INDICATE_CHIMNEY_EVENT, ++ ++ NVSP_MSG2_TYPE_SEND_CHIMNEY_PKT, ++ NVSP_MSG2_TYPE_SEND_CHIMNEY_PKT_COMP, ++ ++ NVSP_MSG2_TYPE_POST_CHIMNEY_RECV_REQ, ++ NVSP_MSG2_TYPE_POST_CHIMNEY_RECV_REQ_COMP, ++ ++ NVSP_MSG2_TYPE_ALLOC_RXBUF, ++ NVSP_MSG2_TYPE_ALLOC_RXBUF_COMP, ++ ++ NVSP_MSG2_TYPE_FREE_RXBUF, ++ ++ NVSP_MSG2_TYPE_SEND_VMQ_RNDIS_PKT, ++ NVSP_MSG2_TYPE_SEND_VMQ_RNDIS_PKT_COMP, ++ ++ NVSP_MSG2_TYPE_SEND_NDIS_CONFIG, ++ ++ NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE, ++ NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP, ++}; ++ ++enum { ++ NVSP_STAT_NONE = 0, ++ NVSP_STAT_SUCCESS, ++ NVSP_STAT_FAIL, ++ NVSP_STAT_PROTOCOL_TOO_NEW, ++ NVSP_STAT_PROTOCOL_TOO_OLD, ++ NVSP_STAT_INVALID_RNDIS_PKT, ++ NVSP_STAT_BUSY, ++ NVSP_STAT_PROTOCOL_UNSUPPORTED, ++ NVSP_STAT_MAX, ++}; ++ ++struct nvsp_message_header { ++ u32 msg_type; ++}; ++ ++/* Init Messages */ ++ ++/* ++ * This message is used by the VSC to initialize the channel after the channels ++ * has been opened. This message should never include anything other then ++ * versioning (i.e. this message will be the same for ever). ++ */ ++struct nvsp_message_init { ++ u32 min_protocol_ver; ++ u32 max_protocol_ver; ++} __packed; ++ ++/* ++ * This message is used by the VSP to complete the initialization of the ++ * channel. This message should never include anything other then versioning ++ * (i.e. this message will be the same for ever). ++ */ ++struct nvsp_message_init_complete { ++ u32 negotiated_protocol_ver; ++ u32 max_mdl_chain_len; ++ u32 status; ++} __packed; ++ ++union nvsp_message_init_uber { ++ struct nvsp_message_init init; ++ struct nvsp_message_init_complete init_complete; ++} __packed; ++ ++/* Version 1 Messages */ ++ ++/* ++ * This message is used by the VSC to send the NDIS version to the VSP. The VSP ++ * can use this information when handling OIDs sent by the VSC. ++ */ ++struct nvsp_1_message_send_ndis_version { ++ u32 ndis_major_ver; ++ u32 ndis_minor_ver; ++} __packed; ++ ++/* ++ * This message is used by the VSC to send a receive buffer to the VSP. The VSP ++ * can then use the receive buffer to send data to the VSC. ++ */ ++struct nvsp_1_message_send_receive_buffer { ++ u32 gpadl_handle; ++ u16 id; ++} __packed; ++ ++struct nvsp_1_receive_buffer_section { ++ u32 offset; ++ u32 sub_alloc_size; ++ u32 num_sub_allocs; ++ u32 end_offset; ++} __packed; ++ ++/* ++ * This message is used by the VSP to acknowledge a receive buffer send by the ++ * VSC. This message must be sent by the VSP before the VSP uses the receive ++ * buffer. ++ */ ++struct nvsp_1_message_send_receive_buffer_complete { ++ u32 status; ++ u32 num_sections; ++ ++ /* ++ * The receive buffer is split into two parts, a large suballocation ++ * section and a small suballocation section. These sections are then ++ * suballocated by a certain size. ++ */ ++ ++ /* ++ * For example, the following break up of the receive buffer has 6 ++ * large suballocations and 10 small suballocations. ++ */ ++ ++ /* ++ * | Large Section | | Small Section | ++ * ------------------------------------------------------------ ++ * | | | | | | | | | | | | | | | | | | ++ * | | ++ * LargeOffset SmallOffset ++ */ ++ ++ struct nvsp_1_receive_buffer_section sections[1]; ++} __packed; ++ ++/* ++ * This message is sent by the VSC to revoke the receive buffer. After the VSP ++ * completes this transaction, the vsp should never use the receive buffer ++ * again. ++ */ ++struct nvsp_1_message_revoke_receive_buffer { ++ u16 id; ++}; ++ ++/* ++ * This message is used by the VSC to send a send buffer to the VSP. The VSC ++ * can then use the send buffer to send data to the VSP. ++ */ ++struct nvsp_1_message_send_send_buffer { ++ u32 gpadl_handle; ++ u16 id; ++} __packed; ++ ++/* ++ * This message is used by the VSP to acknowledge a send buffer sent by the ++ * VSC. This message must be sent by the VSP before the VSP uses the sent ++ * buffer. ++ */ ++struct nvsp_1_message_send_send_buffer_complete { ++ u32 status; ++ ++ /* ++ * The VSC gets to choose the size of the send buffer and the VSP gets ++ * to choose the sections size of the buffer. This was done to enable ++ * dynamic reconfigurations when the cost of GPA-direct buffers ++ * decreases. ++ */ ++ u32 section_size; ++} __packed; ++ ++/* ++ * This message is sent by the VSC to revoke the send buffer. After the VSP ++ * completes this transaction, the vsp should never use the send buffer again. ++ */ ++struct nvsp_1_message_revoke_send_buffer { ++ u16 id; ++}; ++ ++/* ++ * This message is used by both the VSP and the VSC to send a RNDIS message to ++ * the opposite channel endpoint. ++ */ ++struct nvsp_1_message_send_rndis_packet { ++ /* ++ * This field is specified by RNIDS. They assume there's two different ++ * channels of communication. However, the Network VSP only has one. ++ * Therefore, the channel travels with the RNDIS packet. ++ */ ++ u32 channel_type; ++ ++ /* ++ * This field is used to send part or all of the data through a send ++ * buffer. This values specifies an index into the send buffer. If the ++ * index is 0xFFFFFFFF, then the send buffer is not being used and all ++ * of the data was sent through other VMBus mechanisms. ++ */ ++ u32 send_buf_section_index; ++ u32 send_buf_section_size; ++} __packed; ++ ++/* ++ * This message is used by both the VSP and the VSC to complete a RNDIS message ++ * to the opposite channel endpoint. At this point, the initiator of this ++ * message cannot use any resources associated with the original RNDIS packet. ++ */ ++struct nvsp_1_message_send_rndis_packet_complete { ++ u32 status; ++}; ++ ++union nvsp_1_message_uber { ++ struct nvsp_1_message_send_ndis_version send_ndis_ver; ++ ++ struct nvsp_1_message_send_receive_buffer send_recv_buf; ++ struct nvsp_1_message_send_receive_buffer_complete ++ send_recv_buf_complete; ++ struct nvsp_1_message_revoke_receive_buffer revoke_recv_buf; ++ ++ struct nvsp_1_message_send_send_buffer send_send_buf; ++ struct nvsp_1_message_send_send_buffer_complete send_send_buf_complete; ++ struct nvsp_1_message_revoke_send_buffer revoke_send_buf; ++ ++ struct nvsp_1_message_send_rndis_packet send_rndis_pkt; ++ struct nvsp_1_message_send_rndis_packet_complete ++ send_rndis_pkt_complete; ++} __packed; ++ ++ ++/* ++ * Network VSP protocol version 2 messages: ++ */ ++struct nvsp_2_vsc_capability { ++ union { ++ u64 data; ++ struct { ++ u64 vmq:1; ++ u64 chimney:1; ++ u64 sriov:1; ++ u64 ieee8021q:1; ++ u64 correlation_id:1; ++ }; ++ }; ++} __packed; ++ ++struct nvsp_2_send_ndis_config { ++ u32 mtu; ++ u32 reserved; ++ struct nvsp_2_vsc_capability capability; ++} __packed; ++ ++/* Allocate receive buffer */ ++struct nvsp_2_alloc_rxbuf { ++ /* Allocation ID to match the allocation request and response */ ++ u32 alloc_id; ++ ++ /* Length of the VM shared memory receive buffer that needs to ++ * be allocated ++ */ ++ u32 len; ++} __packed; ++ ++/* Allocate receive buffer complete */ ++struct nvsp_2_alloc_rxbuf_comp { ++ /* The NDIS_STATUS code for buffer allocation */ ++ u32 status; ++ ++ u32 alloc_id; ++ ++ /* GPADL handle for the allocated receive buffer */ ++ u32 gpadl_handle; ++ ++ /* Receive buffer ID */ ++ u64 recv_buf_id; ++} __packed; ++ ++struct nvsp_2_free_rxbuf { ++ u64 recv_buf_id; ++} __packed; ++ ++union nvsp_2_message_uber { ++ struct nvsp_2_send_ndis_config send_ndis_config; ++ struct nvsp_2_alloc_rxbuf alloc_rxbuf; ++ struct nvsp_2_alloc_rxbuf_comp alloc_rxbuf_comp; ++ struct nvsp_2_free_rxbuf free_rxbuf; ++} __packed; ++ ++union nvsp_all_messages { ++ union nvsp_message_init_uber init_msg; ++ union nvsp_1_message_uber v1_msg; ++ union nvsp_2_message_uber v2_msg; ++} __packed; ++ ++/* ALL Messages */ ++struct nvsp_message { ++ struct nvsp_message_header hdr; ++ union nvsp_all_messages msg; ++} __packed; ++ ++ ++#define NETVSC_MTU 65536 ++ ++#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*2) /* 2MB */ ++ ++#define NETVSC_RECEIVE_BUFFER_ID 0xcafe ++ ++#define NETVSC_RECEIVE_SG_COUNT 1 ++ ++/* Preallocated receive packets */ ++#define NETVSC_RECEIVE_PACKETLIST_COUNT 256 ++ ++#define NETVSC_PACKET_SIZE 2048 ++ ++/* Per netvsc channel-specific */ ++struct netvsc_device { ++ struct hv_device *dev; ++ ++ u32 nvsp_version; ++ ++ atomic_t num_outstanding_sends; ++ bool start_remove; ++ bool destroy; ++ /* ++ * List of free preallocated hv_netvsc_packet to represent receive ++ * packet ++ */ ++ struct list_head recv_pkt_list; ++ spinlock_t recv_pkt_list_lock; ++ ++ /* Receive buffer allocated by us but manages by NetVSP */ ++ void *recv_buf; ++ u32 recv_buf_size; ++ u32 recv_buf_gpadl_handle; ++ u32 recv_section_cnt; ++ struct nvsp_1_receive_buffer_section *recv_section; ++ ++ /* Used for NetVSP initialization protocol */ ++ struct completion channel_init_wait; ++ struct nvsp_message channel_init_pkt; ++ ++ struct nvsp_message revoke_packet; ++ /* unsigned char HwMacAddr[HW_MACADDR_LEN]; */ ++ ++ struct net_device *ndev; ++ ++ /* Holds rndis device info */ ++ void *extension; ++}; ++ ++ ++/* Status codes */ ++ ++ ++#ifndef STATUS_SUCCESS ++#define STATUS_SUCCESS (0x00000000L) ++#endif ++ ++#ifndef STATUS_UNSUCCESSFUL ++#define STATUS_UNSUCCESSFUL (0xC0000001L) ++#endif ++ ++#ifndef STATUS_PENDING ++#define STATUS_PENDING (0x00000103L) ++#endif ++ ++#ifndef STATUS_INSUFFICIENT_RESOURCES ++#define STATUS_INSUFFICIENT_RESOURCES (0xC000009AL) ++#endif ++ ++#ifndef STATUS_BUFFER_OVERFLOW ++#define STATUS_BUFFER_OVERFLOW (0x80000005L) ++#endif ++ ++#ifndef STATUS_NOT_SUPPORTED ++#define STATUS_NOT_SUPPORTED (0xC00000BBL) ++#endif ++ ++#define RNDIS_STATUS_SUCCESS (STATUS_SUCCESS) ++#define RNDIS_STATUS_PENDING (STATUS_PENDING) ++#define RNDIS_STATUS_NOT_RECOGNIZED (0x00010001L) ++#define RNDIS_STATUS_NOT_COPIED (0x00010002L) ++#define RNDIS_STATUS_NOT_ACCEPTED (0x00010003L) ++#define RNDIS_STATUS_CALL_ACTIVE (0x00010007L) ++ ++#define RNDIS_STATUS_ONLINE (0x40010003L) ++#define RNDIS_STATUS_RESET_START (0x40010004L) ++#define RNDIS_STATUS_RESET_END (0x40010005L) ++#define RNDIS_STATUS_RING_STATUS (0x40010006L) ++#define RNDIS_STATUS_CLOSED (0x40010007L) ++#define RNDIS_STATUS_WAN_LINE_UP (0x40010008L) ++#define RNDIS_STATUS_WAN_LINE_DOWN (0x40010009L) ++#define RNDIS_STATUS_WAN_FRAGMENT (0x4001000AL) ++#define RNDIS_STATUS_MEDIA_CONNECT (0x4001000BL) ++#define RNDIS_STATUS_MEDIA_DISCONNECT (0x4001000CL) ++#define RNDIS_STATUS_HARDWARE_LINE_UP (0x4001000DL) ++#define RNDIS_STATUS_HARDWARE_LINE_DOWN (0x4001000EL) ++#define RNDIS_STATUS_INTERFACE_UP (0x4001000FL) ++#define RNDIS_STATUS_INTERFACE_DOWN (0x40010010L) ++#define RNDIS_STATUS_MEDIA_BUSY (0x40010011L) ++#define RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION (0x40010012L) ++#define RNDIS_STATUS_WW_INDICATION RDIA_SPECIFIC_INDICATION ++#define RNDIS_STATUS_LINK_SPEED_CHANGE (0x40010013L) ++ ++#define RNDIS_STATUS_NOT_RESETTABLE (0x80010001L) ++#define RNDIS_STATUS_SOFT_ERRORS (0x80010003L) ++#define RNDIS_STATUS_HARD_ERRORS (0x80010004L) ++#define RNDIS_STATUS_BUFFER_OVERFLOW (STATUS_BUFFER_OVERFLOW) ++ ++#define RNDIS_STATUS_FAILURE (STATUS_UNSUCCESSFUL) ++#define RNDIS_STATUS_RESOURCES (STATUS_INSUFFICIENT_RESOURCES) ++#define RNDIS_STATUS_CLOSING (0xC0010002L) ++#define RNDIS_STATUS_BAD_VERSION (0xC0010004L) ++#define RNDIS_STATUS_BAD_CHARACTERISTICS (0xC0010005L) ++#define RNDIS_STATUS_ADAPTER_NOT_FOUND (0xC0010006L) ++#define RNDIS_STATUS_OPEN_FAILED (0xC0010007L) ++#define RNDIS_STATUS_DEVICE_FAILED (0xC0010008L) ++#define RNDIS_STATUS_MULTICAST_FULL (0xC0010009L) ++#define RNDIS_STATUS_MULTICAST_EXISTS (0xC001000AL) ++#define RNDIS_STATUS_MULTICAST_NOT_FOUND (0xC001000BL) ++#define RNDIS_STATUS_REQUEST_ABORTED (0xC001000CL) ++#define RNDIS_STATUS_RESET_IN_PROGRESS (0xC001000DL) ++#define RNDIS_STATUS_CLOSING_INDICATING (0xC001000EL) ++#define RNDIS_STATUS_NOT_SUPPORTED (STATUS_NOT_SUPPORTED) ++#define RNDIS_STATUS_INVALID_PACKET (0xC001000FL) ++#define RNDIS_STATUS_OPEN_LIST_FULL (0xC0010010L) ++#define RNDIS_STATUS_ADAPTER_NOT_READY (0xC0010011L) ++#define RNDIS_STATUS_ADAPTER_NOT_OPEN (0xC0010012L) ++#define RNDIS_STATUS_NOT_INDICATING (0xC0010013L) ++#define RNDIS_STATUS_INVALID_LENGTH (0xC0010014L) ++#define RNDIS_STATUS_INVALID_DATA (0xC0010015L) ++#define RNDIS_STATUS_BUFFER_TOO_SHORT (0xC0010016L) ++#define RNDIS_STATUS_INVALID_OID (0xC0010017L) ++#define RNDIS_STATUS_ADAPTER_REMOVED (0xC0010018L) ++#define RNDIS_STATUS_UNSUPPORTED_MEDIA (0xC0010019L) ++#define RNDIS_STATUS_GROUP_ADDRESS_IN_USE (0xC001001AL) ++#define RNDIS_STATUS_FILE_NOT_FOUND (0xC001001BL) ++#define RNDIS_STATUS_ERROR_READING_FILE (0xC001001CL) ++#define RNDIS_STATUS_ALREADY_MAPPED (0xC001001DL) ++#define RNDIS_STATUS_RESOURCE_CONFLICT (0xC001001EL) ++#define RNDIS_STATUS_NO_CABLE (0xC001001FL) ++ ++#define RNDIS_STATUS_INVALID_SAP (0xC0010020L) ++#define RNDIS_STATUS_SAP_IN_USE (0xC0010021L) ++#define RNDIS_STATUS_INVALID_ADDRESS (0xC0010022L) ++#define RNDIS_STATUS_VC_NOT_ACTIVATED (0xC0010023L) ++#define RNDIS_STATUS_DEST_OUT_OF_ORDER (0xC0010024L) ++#define RNDIS_STATUS_VC_NOT_AVAILABLE (0xC0010025L) ++#define RNDIS_STATUS_CELLRATE_NOT_AVAILABLE (0xC0010026L) ++#define RNDIS_STATUS_INCOMPATABLE_QOS (0xC0010027L) ++#define RNDIS_STATUS_AAL_PARAMS_UNSUPPORTED (0xC0010028L) ++#define RNDIS_STATUS_NO_ROUTE_TO_DESTINATION (0xC0010029L) ++ ++#define RNDIS_STATUS_TOKEN_RING_OPEN_ERROR (0xC0011000L) ++ ++/* Object Identifiers used by NdisRequest Query/Set Information */ ++/* General Objects */ ++#define RNDIS_OID_GEN_SUPPORTED_LIST 0x00010101 ++#define RNDIS_OID_GEN_HARDWARE_STATUS 0x00010102 ++#define RNDIS_OID_GEN_MEDIA_SUPPORTED 0x00010103 ++#define RNDIS_OID_GEN_MEDIA_IN_USE 0x00010104 ++#define RNDIS_OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 ++#define RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 ++#define RNDIS_OID_GEN_LINK_SPEED 0x00010107 ++#define RNDIS_OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 ++#define RNDIS_OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 ++#define RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A ++#define RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B ++#define RNDIS_OID_GEN_VENDOR_ID 0x0001010C ++#define RNDIS_OID_GEN_VENDOR_DESCRIPTION 0x0001010D ++#define RNDIS_OID_GEN_CURRENT_PACKET_FILTER 0x0001010E ++#define RNDIS_OID_GEN_CURRENT_LOOKAHEAD 0x0001010F ++#define RNDIS_OID_GEN_DRIVER_VERSION 0x00010110 ++#define RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 ++#define RNDIS_OID_GEN_PROTOCOL_OPTIONS 0x00010112 ++#define RNDIS_OID_GEN_MAC_OPTIONS 0x00010113 ++#define RNDIS_OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 ++#define RNDIS_OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 ++#define RNDIS_OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 ++#define RNDIS_OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 ++#define RNDIS_OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 ++#define RNDIS_OID_GEN_MACHINE_NAME 0x0001021A ++#define RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B ++ ++#define RNDIS_OID_GEN_XMIT_OK 0x00020101 ++#define RNDIS_OID_GEN_RCV_OK 0x00020102 ++#define RNDIS_OID_GEN_XMIT_ERROR 0x00020103 ++#define RNDIS_OID_GEN_RCV_ERROR 0x00020104 ++#define RNDIS_OID_GEN_RCV_NO_BUFFER 0x00020105 ++ ++#define RNDIS_OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 ++#define RNDIS_OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 ++#define RNDIS_OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 ++#define RNDIS_OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 ++#define RNDIS_OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 ++#define RNDIS_OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 ++#define RNDIS_OID_GEN_DIRECTED_BYTES_RCV 0x00020207 ++#define RNDIS_OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 ++#define RNDIS_OID_GEN_MULTICAST_BYTES_RCV 0x00020209 ++#define RNDIS_OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A ++#define RNDIS_OID_GEN_BROADCAST_BYTES_RCV 0x0002020B ++#define RNDIS_OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C ++ ++#define RNDIS_OID_GEN_RCV_CRC_ERROR 0x0002020D ++#define RNDIS_OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E ++ ++#define RNDIS_OID_GEN_GET_TIME_CAPS 0x0002020F ++#define RNDIS_OID_GEN_GET_NETCARD_TIME 0x00020210 ++ ++/* These are connection-oriented general OIDs. */ ++/* These replace the above OIDs for connection-oriented media. */ ++#define RNDIS_OID_GEN_CO_SUPPORTED_LIST 0x00010101 ++#define RNDIS_OID_GEN_CO_HARDWARE_STATUS 0x00010102 ++#define RNDIS_OID_GEN_CO_MEDIA_SUPPORTED 0x00010103 ++#define RNDIS_OID_GEN_CO_MEDIA_IN_USE 0x00010104 ++#define RNDIS_OID_GEN_CO_LINK_SPEED 0x00010105 ++#define RNDIS_OID_GEN_CO_VENDOR_ID 0x00010106 ++#define RNDIS_OID_GEN_CO_VENDOR_DESCRIPTION 0x00010107 ++#define RNDIS_OID_GEN_CO_DRIVER_VERSION 0x00010108 ++#define RNDIS_OID_GEN_CO_PROTOCOL_OPTIONS 0x00010109 ++#define RNDIS_OID_GEN_CO_MAC_OPTIONS 0x0001010A ++#define RNDIS_OID_GEN_CO_MEDIA_CONNECT_STATUS 0x0001010B ++#define RNDIS_OID_GEN_CO_VENDOR_DRIVER_VERSION 0x0001010C ++#define RNDIS_OID_GEN_CO_MINIMUM_LINK_SPEED 0x0001010D ++ ++#define RNDIS_OID_GEN_CO_GET_TIME_CAPS 0x00010201 ++#define RNDIS_OID_GEN_CO_GET_NETCARD_TIME 0x00010202 ++ ++/* These are connection-oriented statistics OIDs. */ ++#define RNDIS_OID_GEN_CO_XMIT_PDUS_OK 0x00020101 ++#define RNDIS_OID_GEN_CO_RCV_PDUS_OK 0x00020102 ++#define RNDIS_OID_GEN_CO_XMIT_PDUS_ERROR 0x00020103 ++#define RNDIS_OID_GEN_CO_RCV_PDUS_ERROR 0x00020104 ++#define RNDIS_OID_GEN_CO_RCV_PDUS_NO_BUFFER 0x00020105 ++ ++ ++#define RNDIS_OID_GEN_CO_RCV_CRC_ERROR 0x00020201 ++#define RNDIS_OID_GEN_CO_TRANSMIT_QUEUE_LENGTH 0x00020202 ++#define RNDIS_OID_GEN_CO_BYTES_XMIT 0x00020203 ++#define RNDIS_OID_GEN_CO_BYTES_RCV 0x00020204 ++#define RNDIS_OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020205 ++#define RNDIS_OID_GEN_CO_NETCARD_LOAD 0x00020206 ++ ++/* These are objects for Connection-oriented media call-managers. */ ++#define RNDIS_OID_CO_ADD_PVC 0xFF000001 ++#define RNDIS_OID_CO_DELETE_PVC 0xFF000002 ++#define RNDIS_OID_CO_GET_CALL_INFORMATION 0xFF000003 ++#define RNDIS_OID_CO_ADD_ADDRESS 0xFF000004 ++#define RNDIS_OID_CO_DELETE_ADDRESS 0xFF000005 ++#define RNDIS_OID_CO_GET_ADDRESSES 0xFF000006 ++#define RNDIS_OID_CO_ADDRESS_CHANGE 0xFF000007 ++#define RNDIS_OID_CO_SIGNALING_ENABLED 0xFF000008 ++#define RNDIS_OID_CO_SIGNALING_DISABLED 0xFF000009 ++ ++/* 802.3 Objects (Ethernet) */ ++#define RNDIS_OID_802_3_PERMANENT_ADDRESS 0x01010101 ++#define RNDIS_OID_802_3_CURRENT_ADDRESS 0x01010102 ++#define RNDIS_OID_802_3_MULTICAST_LIST 0x01010103 ++#define RNDIS_OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 ++#define RNDIS_OID_802_3_MAC_OPTIONS 0x01010105 ++ ++#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 ++ ++#define RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 ++#define RNDIS_OID_802_3_XMIT_ONE_COLLISION 0x01020102 ++#define RNDIS_OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 ++ ++#define RNDIS_OID_802_3_XMIT_DEFERRED 0x01020201 ++#define RNDIS_OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 ++#define RNDIS_OID_802_3_RCV_OVERRUN 0x01020203 ++#define RNDIS_OID_802_3_XMIT_UNDERRUN 0x01020204 ++#define RNDIS_OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 ++#define RNDIS_OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 ++#define RNDIS_OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 ++ ++/* Remote NDIS message types */ ++#define REMOTE_NDIS_PACKET_MSG 0x00000001 ++#define REMOTE_NDIS_INITIALIZE_MSG 0x00000002 ++#define REMOTE_NDIS_HALT_MSG 0x00000003 ++#define REMOTE_NDIS_QUERY_MSG 0x00000004 ++#define REMOTE_NDIS_SET_MSG 0x00000005 ++#define REMOTE_NDIS_RESET_MSG 0x00000006 ++#define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007 ++#define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008 ++ ++#define REMOTE_CONDIS_MP_CREATE_VC_MSG 0x00008001 ++#define REMOTE_CONDIS_MP_DELETE_VC_MSG 0x00008002 ++#define REMOTE_CONDIS_MP_ACTIVATE_VC_MSG 0x00008005 ++#define REMOTE_CONDIS_MP_DEACTIVATE_VC_MSG 0x00008006 ++#define REMOTE_CONDIS_INDICATE_STATUS_MSG 0x00008007 ++ ++/* Remote NDIS message completion types */ ++#define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002 ++#define REMOTE_NDIS_QUERY_CMPLT 0x80000004 ++#define REMOTE_NDIS_SET_CMPLT 0x80000005 ++#define REMOTE_NDIS_RESET_CMPLT 0x80000006 ++#define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008 ++ ++#define REMOTE_CONDIS_MP_CREATE_VC_CMPLT 0x80008001 ++#define REMOTE_CONDIS_MP_DELETE_VC_CMPLT 0x80008002 ++#define REMOTE_CONDIS_MP_ACTIVATE_VC_CMPLT 0x80008005 ++#define REMOTE_CONDIS_MP_DEACTIVATE_VC_CMPLT 0x80008006 ++ ++/* ++ * Reserved message type for private communication between lower-layer host ++ * driver and remote device, if necessary. ++ */ ++#define REMOTE_NDIS_BUS_MSG 0xff000001 ++ ++/* Defines for DeviceFlags in struct rndis_initialize_complete */ ++#define RNDIS_DF_CONNECTIONLESS 0x00000001 ++#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002 ++#define RNDIS_DF_RAW_DATA 0x00000004 ++ ++/* Remote NDIS medium types. */ ++#define RNDIS_MEDIUM_802_3 0x00000000 ++#define RNDIS_MEDIUM_802_5 0x00000001 ++#define RNDIS_MEDIUM_FDDI 0x00000002 ++#define RNDIS_MEDIUM_WAN 0x00000003 ++#define RNDIS_MEDIUM_LOCAL_TALK 0x00000004 ++#define RNDIS_MEDIUM_ARCNET_RAW 0x00000006 ++#define RNDIS_MEDIUM_ARCNET_878_2 0x00000007 ++#define RNDIS_MEDIUM_ATM 0x00000008 ++#define RNDIS_MEDIUM_WIRELESS_WAN 0x00000009 ++#define RNDIS_MEDIUM_IRDA 0x0000000a ++#define RNDIS_MEDIUM_CO_WAN 0x0000000b ++/* Not a real medium, defined as an upper-bound */ ++#define RNDIS_MEDIUM_MAX 0x0000000d ++ ++ ++/* Remote NDIS medium connection states. */ ++#define RNDIS_MEDIA_STATE_CONNECTED 0x00000000 ++#define RNDIS_MEDIA_STATE_DISCONNECTED 0x00000001 ++ ++/* Remote NDIS version numbers */ ++#define RNDIS_MAJOR_VERSION 0x00000001 ++#define RNDIS_MINOR_VERSION 0x00000000 ++ ++ ++/* NdisInitialize message */ ++struct rndis_initialize_request { ++ u32 req_id; ++ u32 major_ver; ++ u32 minor_ver; ++ u32 max_xfer_size; ++}; ++ ++/* Response to NdisInitialize */ ++struct rndis_initialize_complete { ++ u32 req_id; ++ u32 status; ++ u32 major_ver; ++ u32 minor_ver; ++ u32 dev_flags; ++ u32 medium; ++ u32 max_pkt_per_msg; ++ u32 max_xfer_size; ++ u32 pkt_alignment_factor; ++ u32 af_list_offset; ++ u32 af_list_size; ++}; ++ ++/* Call manager devices only: Information about an address family */ ++/* supported by the device is appended to the response to NdisInitialize. */ ++struct rndis_co_address_family { ++ u32 address_family; ++ u32 major_ver; ++ u32 minor_ver; ++}; ++ ++/* NdisHalt message */ ++struct rndis_halt_request { ++ u32 req_id; ++}; ++ ++/* NdisQueryRequest message */ ++struct rndis_query_request { ++ u32 req_id; ++ u32 oid; ++ u32 info_buflen; ++ u32 info_buf_offset; ++ u32 dev_vc_handle; ++}; ++ ++/* Response to NdisQueryRequest */ ++struct rndis_query_complete { ++ u32 req_id; ++ u32 status; ++ u32 info_buflen; ++ u32 info_buf_offset; ++}; ++ ++/* NdisSetRequest message */ ++struct rndis_set_request { ++ u32 req_id; ++ u32 oid; ++ u32 info_buflen; ++ u32 info_buf_offset; ++ u32 dev_vc_handle; ++}; ++ ++/* Response to NdisSetRequest */ ++struct rndis_set_complete { ++ u32 req_id; ++ u32 status; ++}; ++ ++/* NdisReset message */ ++struct rndis_reset_request { ++ u32 reserved; ++}; ++ ++/* Response to NdisReset */ ++struct rndis_reset_complete { ++ u32 status; ++ u32 addressing_reset; ++}; ++ ++/* NdisMIndicateStatus message */ ++struct rndis_indicate_status { ++ u32 status; ++ u32 status_buflen; ++ u32 status_buf_offset; ++}; ++ ++/* Diagnostic information passed as the status buffer in */ ++/* struct rndis_indicate_status messages signifying error conditions. */ ++struct rndis_diagnostic_info { ++ u32 diag_status; ++ u32 error_offset; ++}; ++ ++/* NdisKeepAlive message */ ++struct rndis_keepalive_request { ++ u32 req_id; ++}; ++ ++/* Response to NdisKeepAlive */ ++struct rndis_keepalive_complete { ++ u32 req_id; ++ u32 status; ++}; ++ ++/* ++ * Data message. All Offset fields contain byte offsets from the beginning of ++ * struct rndis_packet. All Length fields are in bytes. VcHandle is set ++ * to 0 for connectionless data, otherwise it contains the VC handle. ++ */ ++struct rndis_packet { ++ u32 data_offset; ++ u32 data_len; ++ u32 oob_data_offset; ++ u32 oob_data_len; ++ u32 num_oob_data_elements; ++ u32 per_pkt_info_offset; ++ u32 per_pkt_info_len; ++ u32 vc_handle; ++ u32 reserved; ++}; ++ ++/* Optional Out of Band data associated with a Data message. */ ++struct rndis_oobd { ++ u32 size; ++ u32 type; ++ u32 class_info_offset; ++}; ++ ++/* Packet extension field contents associated with a Data message. */ ++struct rndis_per_packet_info { ++ u32 size; ++ u32 type; ++ u32 ppi_offset; ++}; ++ ++enum ndis_per_pkt_info_type { ++ TCPIP_CHKSUM_PKTINFO, ++ IPSEC_PKTINFO, ++ TCP_LARGESEND_PKTINFO, ++ CLASSIFICATION_HANDLE_PKTINFO, ++ NDIS_RESERVED, ++ SG_LIST_PKTINFO, ++ IEEE_8021Q_INFO, ++ ORIGINAL_PKTINFO, ++ PACKET_CANCEL_ID, ++ ORIGINAL_NET_BUFLIST, ++ CACHED_NET_BUFLIST, ++ SHORT_PKT_PADINFO, ++ MAX_PER_PKT_INFO ++}; ++ ++struct ndis_pkt_8021q_info { ++ union { ++ struct { ++ u32 pri:3; /* User Priority */ ++ u32 cfi:1; /* Canonical Format ID */ ++ u32 vlanid:12; /* VLAN ID */ ++ u32 reserved:16; ++ }; ++ u32 value; ++ }; ++}; ++ ++#define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \ ++ sizeof(struct ndis_pkt_8021q_info)) ++ ++/* Format of Information buffer passed in a SetRequest for the OID */ ++/* OID_GEN_RNDIS_CONFIG_PARAMETER. */ ++struct rndis_config_parameter_info { ++ u32 parameter_name_offset; ++ u32 parameter_name_length; ++ u32 parameter_type; ++ u32 parameter_value_offset; ++ u32 parameter_value_length; ++}; ++ ++/* Values for ParameterType in struct rndis_config_parameter_info */ ++#define RNDIS_CONFIG_PARAM_TYPE_INTEGER 0 ++#define RNDIS_CONFIG_PARAM_TYPE_STRING 2 ++ ++/* CONDIS Miniport messages for connection oriented devices */ ++/* that do not implement a call manager. */ ++ ++/* CoNdisMiniportCreateVc message */ ++struct rcondis_mp_create_vc { ++ u32 req_id; ++ u32 ndis_vc_handle; ++}; ++ ++/* Response to CoNdisMiniportCreateVc */ ++struct rcondis_mp_create_vc_complete { ++ u32 req_id; ++ u32 dev_vc_handle; ++ u32 status; ++}; ++ ++/* CoNdisMiniportDeleteVc message */ ++struct rcondis_mp_delete_vc { ++ u32 req_id; ++ u32 dev_vc_handle; ++}; ++ ++/* Response to CoNdisMiniportDeleteVc */ ++struct rcondis_mp_delete_vc_complete { ++ u32 req_id; ++ u32 status; ++}; ++ ++/* CoNdisMiniportQueryRequest message */ ++struct rcondis_mp_query_request { ++ u32 req_id; ++ u32 request_type; ++ u32 oid; ++ u32 dev_vc_handle; ++ u32 info_buflen; ++ u32 info_buf_offset; ++}; ++ ++/* CoNdisMiniportSetRequest message */ ++struct rcondis_mp_set_request { ++ u32 req_id; ++ u32 request_type; ++ u32 oid; ++ u32 dev_vc_handle; ++ u32 info_buflen; ++ u32 info_buf_offset; ++}; ++ ++/* CoNdisIndicateStatus message */ ++struct rcondis_indicate_status { ++ u32 ndis_vc_handle; ++ u32 status; ++ u32 status_buflen; ++ u32 status_buf_offset; ++}; ++ ++/* CONDIS Call/VC parameters */ ++struct rcondis_specific_parameters { ++ u32 parameter_type; ++ u32 parameter_length; ++ u32 parameter_lffset; ++}; ++ ++struct rcondis_media_parameters { ++ u32 flags; ++ u32 reserved1; ++ u32 reserved2; ++ struct rcondis_specific_parameters media_specific; ++}; ++ ++struct rndis_flowspec { ++ u32 token_rate; ++ u32 token_bucket_size; ++ u32 peak_bandwidth; ++ u32 latency; ++ u32 delay_variation; ++ u32 service_type; ++ u32 max_sdu_size; ++ u32 minimum_policed_size; ++}; ++ ++struct rcondis_call_manager_parameters { ++ struct rndis_flowspec transmit; ++ struct rndis_flowspec receive; ++ struct rcondis_specific_parameters call_mgr_specific; ++}; ++ ++/* CoNdisMiniportActivateVc message */ ++struct rcondis_mp_activate_vc_request { ++ u32 req_id; ++ u32 flags; ++ u32 dev_vc_handle; ++ u32 media_params_offset; ++ u32 media_params_length; ++ u32 call_mgr_params_offset; ++ u32 call_mgr_params_length; ++}; ++ ++/* Response to CoNdisMiniportActivateVc */ ++struct rcondis_mp_activate_vc_complete { ++ u32 req_id; ++ u32 status; ++}; ++ ++/* CoNdisMiniportDeactivateVc message */ ++struct rcondis_mp_deactivate_vc_request { ++ u32 req_id; ++ u32 flags; ++ u32 dev_vc_handle; ++}; ++ ++/* Response to CoNdisMiniportDeactivateVc */ ++struct rcondis_mp_deactivate_vc_complete { ++ u32 req_id; ++ u32 status; ++}; ++ ++ ++/* union with all of the RNDIS messages */ ++union rndis_message_container { ++ struct rndis_packet pkt; ++ struct rndis_initialize_request init_req; ++ struct rndis_halt_request halt_req; ++ struct rndis_query_request query_req; ++ struct rndis_set_request set_req; ++ struct rndis_reset_request reset_req; ++ struct rndis_keepalive_request keep_alive_req; ++ struct rndis_indicate_status indicate_status; ++ struct rndis_initialize_complete init_complete; ++ struct rndis_query_complete query_complete; ++ struct rndis_set_complete set_complete; ++ struct rndis_reset_complete reset_complete; ++ struct rndis_keepalive_complete keep_alive_complete; ++ struct rcondis_mp_create_vc co_miniport_create_vc; ++ struct rcondis_mp_delete_vc co_miniport_delete_vc; ++ struct rcondis_indicate_status co_indicate_status; ++ struct rcondis_mp_activate_vc_request co_miniport_activate_vc; ++ struct rcondis_mp_deactivate_vc_request co_miniport_deactivate_vc; ++ struct rcondis_mp_create_vc_complete co_miniport_create_vc_complete; ++ struct rcondis_mp_delete_vc_complete co_miniport_delete_vc_complete; ++ struct rcondis_mp_activate_vc_complete co_miniport_activate_vc_complete; ++ struct rcondis_mp_deactivate_vc_complete ++ co_miniport_deactivate_vc_complete; ++}; ++ ++/* Remote NDIS message format */ ++struct rndis_message { ++ u32 ndis_msg_type; ++ ++ /* Total length of this message, from the beginning */ ++ /* of the sruct rndis_message, in bytes. */ ++ u32 msg_len; ++ ++ /* Actual message */ ++ union rndis_message_container msg; ++}; ++ ++ ++struct rndis_filter_packet { ++ void *completion_ctx; ++ void (*completion)(void *context); ++ struct rndis_message msg; ++}; ++ ++/* Handy macros */ ++ ++/* get the size of an RNDIS message. Pass in the message type, */ ++/* struct rndis_set_request, struct rndis_packet for example */ ++#define RNDIS_MESSAGE_SIZE(msg) \ ++ (sizeof(msg) + (sizeof(struct rndis_message) - \ ++ sizeof(union rndis_message_container))) ++ ++/* get pointer to info buffer with message pointer */ ++#define MESSAGE_TO_INFO_BUFFER(msg) \ ++ (((unsigned char *)(msg)) + msg->info_buf_offset) ++ ++/* get pointer to status buffer with message pointer */ ++#define MESSAGE_TO_STATUS_BUFFER(msg) \ ++ (((unsigned char *)(msg)) + msg->status_buf_offset) ++ ++/* get pointer to OOBD buffer with message pointer */ ++#define MESSAGE_TO_OOBD_BUFFER(msg) \ ++ (((unsigned char *)(msg)) + msg->oob_data_offset) ++ ++/* get pointer to data buffer with message pointer */ ++#define MESSAGE_TO_DATA_BUFFER(msg) \ ++ (((unsigned char *)(msg)) + msg->per_pkt_info_offset) ++ ++/* get pointer to contained message from NDIS_MESSAGE pointer */ ++#define RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(rndis_msg) \ ++ ((void *) &rndis_msg->msg) ++ ++/* get pointer to contained message from NDIS_MESSAGE pointer */ ++#define RNDIS_MESSAGE_RAW_PTR_TO_MESSAGE_PTR(rndis_msg) \ ++ ((void *) rndis_msg) ++ ++ ++#define __struct_bcount(x) ++ ++ ++ ++#define RNDIS_HEADER_SIZE (sizeof(struct rndis_message) - \ ++ sizeof(union rndis_message_container)) ++ ++#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 ++#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 ++#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 ++#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 ++#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 ++#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 ++#define NDIS_PACKET_TYPE_SMT 0x00000040 ++#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 ++#define NDIS_PACKET_TYPE_GROUP 0x00000100 ++#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200 ++#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400 ++#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800 ++ ++ ++ ++#endif /* _HYPERV_NET_H */ +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +new file mode 100644 +index 0000000..d025c83 +--- /dev/null ++++ b/drivers/net/hyperv/netvsc.c +@@ -0,0 +1,933 @@ ++/* ++ * Copyright (c) 2009, Microsoft Corporation. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple ++ * Place - Suite 330, Boston, MA 02111-1307 USA. ++ * ++ * Authors: ++ * Haiyang Zhang ++ * Hank Janssen ++ */ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hyperv_net.h" ++ ++ ++static struct netvsc_device *alloc_net_device(struct hv_device *device) ++{ ++ struct netvsc_device *net_device; ++ struct net_device *ndev = hv_get_drvdata(device); ++ ++ net_device = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL); ++ if (!net_device) ++ return NULL; ++ ++ net_device->start_remove = false; ++ net_device->destroy = false; ++ net_device->dev = device; ++ net_device->ndev = ndev; ++ ++ hv_set_drvdata(device, net_device); ++ return net_device; ++} ++ ++static struct netvsc_device *get_outbound_net_device(struct hv_device *device) ++{ ++ struct netvsc_device *net_device; ++ ++ net_device = hv_get_drvdata(device); ++ if (net_device && net_device->destroy) ++ net_device = NULL; ++ ++ return net_device; ++} ++ ++static struct netvsc_device *get_inbound_net_device(struct hv_device *device) ++{ ++ struct netvsc_device *net_device; ++ ++ net_device = hv_get_drvdata(device); ++ ++ if (!net_device) ++ goto get_in_err; ++ ++ if (net_device->destroy && ++ atomic_read(&net_device->num_outstanding_sends) == 0) ++ net_device = NULL; ++ ++get_in_err: ++ return net_device; ++} ++ ++ ++static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) ++{ ++ struct nvsp_message *revoke_packet; ++ int ret = 0; ++ struct net_device *ndev = net_device->ndev; ++ ++ /* ++ * If we got a section count, it means we received a ++ * SendReceiveBufferComplete msg (ie sent ++ * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need ++ * to send a revoke msg here ++ */ ++ if (net_device->recv_section_cnt) { ++ /* Send the revoke receive buffer */ ++ revoke_packet = &net_device->revoke_packet; ++ memset(revoke_packet, 0, sizeof(struct nvsp_message)); ++ ++ revoke_packet->hdr.msg_type = ++ NVSP_MSG1_TYPE_REVOKE_RECV_BUF; ++ revoke_packet->msg.v1_msg. ++ revoke_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID; ++ ++ ret = vmbus_sendpacket(net_device->dev->channel, ++ revoke_packet, ++ sizeof(struct nvsp_message), ++ (unsigned long)revoke_packet, ++ VM_PKT_DATA_INBAND, 0); ++ /* ++ * If we failed here, we might as well return and ++ * have a leak rather than continue and a bugchk ++ */ ++ if (ret != 0) { ++ netdev_err(ndev, "unable to send " ++ "revoke receive buffer to netvsp\n"); ++ return ret; ++ } ++ } ++ ++ /* Teardown the gpadl on the vsp end */ ++ if (net_device->recv_buf_gpadl_handle) { ++ ret = vmbus_teardown_gpadl(net_device->dev->channel, ++ net_device->recv_buf_gpadl_handle); ++ ++ /* If we failed here, we might as well return and have a leak ++ * rather than continue and a bugchk ++ */ ++ if (ret != 0) { ++ netdev_err(ndev, ++ "unable to teardown receive buffer's gpadl\n"); ++ return ret; ++ } ++ net_device->recv_buf_gpadl_handle = 0; ++ } ++ ++ if (net_device->recv_buf) { ++ /* Free up the receive buffer */ ++ free_pages((unsigned long)net_device->recv_buf, ++ get_order(net_device->recv_buf_size)); ++ net_device->recv_buf = NULL; ++ } ++ ++ if (net_device->recv_section) { ++ net_device->recv_section_cnt = 0; ++ kfree(net_device->recv_section); ++ net_device->recv_section = NULL; ++ } ++ ++ return ret; ++} ++ ++static int netvsc_init_recv_buf(struct hv_device *device) ++{ ++ int ret = 0; ++ int t; ++ struct netvsc_device *net_device; ++ struct nvsp_message *init_packet; ++ struct net_device *ndev; ++ ++ net_device = get_outbound_net_device(device); ++ if (!net_device) ++ return -ENODEV; ++ ndev = net_device->ndev; ++ ++ net_device->recv_buf = ++ (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, ++ get_order(net_device->recv_buf_size)); ++ if (!net_device->recv_buf) { ++ netdev_err(ndev, "unable to allocate receive " ++ "buffer of size %d\n", net_device->recv_buf_size); ++ ret = -ENOMEM; ++ goto cleanup; ++ } ++ ++ /* ++ * Establish the gpadl handle for this buffer on this ++ * channel. Note: This call uses the vmbus connection rather ++ * than the channel to establish the gpadl handle. ++ */ ++ ret = vmbus_establish_gpadl(device->channel, net_device->recv_buf, ++ net_device->recv_buf_size, ++ &net_device->recv_buf_gpadl_handle); ++ if (ret != 0) { ++ netdev_err(ndev, ++ "unable to establish receive buffer's gpadl\n"); ++ goto cleanup; ++ } ++ ++ ++ /* Notify the NetVsp of the gpadl handle */ ++ init_packet = &net_device->channel_init_pkt; ++ ++ memset(init_packet, 0, sizeof(struct nvsp_message)); ++ ++ init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF; ++ init_packet->msg.v1_msg.send_recv_buf. ++ gpadl_handle = net_device->recv_buf_gpadl_handle; ++ init_packet->msg.v1_msg. ++ send_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID; ++ ++ /* Send the gpadl notification request */ ++ ret = vmbus_sendpacket(device->channel, init_packet, ++ sizeof(struct nvsp_message), ++ (unsigned long)init_packet, ++ VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ if (ret != 0) { ++ netdev_err(ndev, ++ "unable to send receive buffer's gpadl to netvsp\n"); ++ goto cleanup; ++ } ++ ++ t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ); ++ BUG_ON(t == 0); ++ ++ ++ /* Check the response */ ++ if (init_packet->msg.v1_msg. ++ send_recv_buf_complete.status != NVSP_STAT_SUCCESS) { ++ netdev_err(ndev, "Unable to complete receive buffer " ++ "initialization with NetVsp - status %d\n", ++ init_packet->msg.v1_msg. ++ send_recv_buf_complete.status); ++ ret = -EINVAL; ++ goto cleanup; ++ } ++ ++ /* Parse the response */ ++ ++ net_device->recv_section_cnt = init_packet->msg. ++ v1_msg.send_recv_buf_complete.num_sections; ++ ++ net_device->recv_section = kmemdup( ++ init_packet->msg.v1_msg.send_recv_buf_complete.sections, ++ net_device->recv_section_cnt * ++ sizeof(struct nvsp_1_receive_buffer_section), ++ GFP_KERNEL); ++ if (net_device->recv_section == NULL) { ++ ret = -EINVAL; ++ goto cleanup; ++ } ++ ++ /* ++ * For 1st release, there should only be 1 section that represents the ++ * entire receive buffer ++ */ ++ if (net_device->recv_section_cnt != 1 || ++ net_device->recv_section->offset != 0) { ++ ret = -EINVAL; ++ goto cleanup; ++ } ++ ++ goto exit; ++ ++cleanup: ++ netvsc_destroy_recv_buf(net_device); ++ ++exit: ++ return ret; ++} ++ ++ ++/* Negotiate NVSP protocol version */ ++static int negotiate_nvsp_ver(struct hv_device *device, ++ struct netvsc_device *net_device, ++ struct nvsp_message *init_packet, ++ u32 nvsp_ver) ++{ ++ int ret, t; ++ ++ memset(init_packet, 0, sizeof(struct nvsp_message)); ++ init_packet->hdr.msg_type = NVSP_MSG_TYPE_INIT; ++ init_packet->msg.init_msg.init.min_protocol_ver = nvsp_ver; ++ init_packet->msg.init_msg.init.max_protocol_ver = nvsp_ver; ++ ++ /* Send the init request */ ++ ret = vmbus_sendpacket(device->channel, init_packet, ++ sizeof(struct nvsp_message), ++ (unsigned long)init_packet, ++ VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ ++ if (ret != 0) ++ return ret; ++ ++ t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ); ++ ++ if (t == 0) ++ return -ETIMEDOUT; ++ ++ if (init_packet->msg.init_msg.init_complete.status != ++ NVSP_STAT_SUCCESS) ++ return -EINVAL; ++ ++ if (nvsp_ver != NVSP_PROTOCOL_VERSION_2) ++ return 0; ++ ++ /* NVSPv2 only: Send NDIS config */ ++ memset(init_packet, 0, sizeof(struct nvsp_message)); ++ init_packet->hdr.msg_type = NVSP_MSG2_TYPE_SEND_NDIS_CONFIG; ++ init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu; ++ init_packet->msg.v2_msg.send_ndis_config.capability.ieee8021q = 1; ++ ++ ret = vmbus_sendpacket(device->channel, init_packet, ++ sizeof(struct nvsp_message), ++ (unsigned long)init_packet, ++ VM_PKT_DATA_INBAND, 0); ++ ++ return ret; ++} ++ ++static int netvsc_connect_vsp(struct hv_device *device) ++{ ++ int ret; ++ struct netvsc_device *net_device; ++ struct nvsp_message *init_packet; ++ int ndis_version; ++ struct net_device *ndev; ++ ++ net_device = get_outbound_net_device(device); ++ if (!net_device) ++ return -ENODEV; ++ ndev = net_device->ndev; ++ ++ init_packet = &net_device->channel_init_pkt; ++ ++ /* Negotiate the latest NVSP protocol supported */ ++ if (negotiate_nvsp_ver(device, net_device, init_packet, ++ NVSP_PROTOCOL_VERSION_2) == 0) { ++ net_device->nvsp_version = NVSP_PROTOCOL_VERSION_2; ++ } else if (negotiate_nvsp_ver(device, net_device, init_packet, ++ NVSP_PROTOCOL_VERSION_1) == 0) { ++ net_device->nvsp_version = NVSP_PROTOCOL_VERSION_1; ++ } else { ++ ret = -EPROTO; ++ goto cleanup; ++ } ++ ++ pr_debug("Negotiated NVSP version:%x\n", net_device->nvsp_version); ++ ++ /* Send the ndis version */ ++ memset(init_packet, 0, sizeof(struct nvsp_message)); ++ ++ ndis_version = 0x00050001; ++ ++ init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER; ++ init_packet->msg.v1_msg. ++ send_ndis_ver.ndis_major_ver = ++ (ndis_version & 0xFFFF0000) >> 16; ++ init_packet->msg.v1_msg. ++ send_ndis_ver.ndis_minor_ver = ++ ndis_version & 0xFFFF; ++ ++ /* Send the init request */ ++ ret = vmbus_sendpacket(device->channel, init_packet, ++ sizeof(struct nvsp_message), ++ (unsigned long)init_packet, ++ VM_PKT_DATA_INBAND, 0); ++ if (ret != 0) ++ goto cleanup; ++ ++ /* Post the big receive buffer to NetVSP */ ++ ret = netvsc_init_recv_buf(device); ++ ++cleanup: ++ return ret; ++} ++ ++static void netvsc_disconnect_vsp(struct netvsc_device *net_device) ++{ ++ netvsc_destroy_recv_buf(net_device); ++} ++ ++/* ++ * netvsc_device_remove - Callback when the root bus device is removed ++ */ ++int netvsc_device_remove(struct hv_device *device) ++{ ++ struct netvsc_device *net_device; ++ struct hv_netvsc_packet *netvsc_packet, *pos; ++ unsigned long flags; ++ ++ net_device = hv_get_drvdata(device); ++ spin_lock_irqsave(&device->channel->inbound_lock, flags); ++ net_device->destroy = true; ++ spin_unlock_irqrestore(&device->channel->inbound_lock, flags); ++ ++ /* Wait for all send completions */ ++ while (atomic_read(&net_device->num_outstanding_sends)) { ++ dev_info(&device->device, ++ "waiting for %d requests to complete...\n", ++ atomic_read(&net_device->num_outstanding_sends)); ++ udelay(100); ++ } ++ ++ netvsc_disconnect_vsp(net_device); ++ ++ /* ++ * Since we have already drained, we don't need to busy wait ++ * as was done in final_release_stor_device() ++ * Note that we cannot set the ext pointer to NULL until ++ * we have drained - to drain the outgoing packets, we need to ++ * allow incoming packets. ++ */ ++ ++ spin_lock_irqsave(&device->channel->inbound_lock, flags); ++ hv_set_drvdata(device, NULL); ++ spin_unlock_irqrestore(&device->channel->inbound_lock, flags); ++ ++ /* ++ * At this point, no one should be accessing net_device ++ * except in here ++ */ ++ dev_notice(&device->device, "net device safe to remove\n"); ++ ++ /* Now, we can close the channel safely */ ++ vmbus_close(device->channel); ++ ++ /* Release all resources */ ++ list_for_each_entry_safe(netvsc_packet, pos, ++ &net_device->recv_pkt_list, list_ent) { ++ list_del(&netvsc_packet->list_ent); ++ kfree(netvsc_packet); ++ } ++ ++ kfree(net_device); ++ return 0; ++} ++ ++static void netvsc_send_completion(struct hv_device *device, ++ struct vmpacket_descriptor *packet) ++{ ++ struct netvsc_device *net_device; ++ struct nvsp_message *nvsp_packet; ++ struct hv_netvsc_packet *nvsc_packet; ++ struct net_device *ndev; ++ ++ net_device = get_inbound_net_device(device); ++ if (!net_device) ++ return; ++ ndev = net_device->ndev; ++ ++ nvsp_packet = (struct nvsp_message *)((unsigned long)packet + ++ (packet->offset8 << 3)); ++ ++ if ((nvsp_packet->hdr.msg_type == NVSP_MSG_TYPE_INIT_COMPLETE) || ++ (nvsp_packet->hdr.msg_type == ++ NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE) || ++ (nvsp_packet->hdr.msg_type == ++ NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE)) { ++ /* Copy the response back */ ++ memcpy(&net_device->channel_init_pkt, nvsp_packet, ++ sizeof(struct nvsp_message)); ++ complete(&net_device->channel_init_wait); ++ } else if (nvsp_packet->hdr.msg_type == ++ NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) { ++ /* Get the send context */ ++ nvsc_packet = (struct hv_netvsc_packet *)(unsigned long) ++ packet->trans_id; ++ ++ /* Notify the layer above us */ ++ nvsc_packet->completion.send.send_completion( ++ nvsc_packet->completion.send.send_completion_ctx); ++ ++ atomic_dec(&net_device->num_outstanding_sends); ++ ++ if (netif_queue_stopped(ndev) && !net_device->start_remove) ++ netif_wake_queue(ndev); ++ } else { ++ netdev_err(ndev, "Unknown send completion packet type- " ++ "%d received!!\n", nvsp_packet->hdr.msg_type); ++ } ++ ++} ++ ++int netvsc_send(struct hv_device *device, ++ struct hv_netvsc_packet *packet) ++{ ++ struct netvsc_device *net_device; ++ int ret = 0; ++ struct nvsp_message sendMessage; ++ struct net_device *ndev; ++ ++ net_device = get_outbound_net_device(device); ++ if (!net_device) ++ return -ENODEV; ++ ndev = net_device->ndev; ++ ++ sendMessage.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT; ++ if (packet->is_data_pkt) { ++ /* 0 is RMC_DATA; */ ++ sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 0; ++ } else { ++ /* 1 is RMC_CONTROL; */ ++ sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 1; ++ } ++ ++ /* Not using send buffer section */ ++ sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_index = ++ 0xFFFFFFFF; ++ sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = 0; ++ ++ if (packet->page_buf_cnt) { ++ ret = vmbus_sendpacket_pagebuffer(device->channel, ++ packet->page_buf, ++ packet->page_buf_cnt, ++ &sendMessage, ++ sizeof(struct nvsp_message), ++ (unsigned long)packet); ++ } else { ++ ret = vmbus_sendpacket(device->channel, &sendMessage, ++ sizeof(struct nvsp_message), ++ (unsigned long)packet, ++ VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ ++ } ++ ++ if (ret == 0) { ++ atomic_inc(&net_device->num_outstanding_sends); ++ } else if (ret == -EAGAIN) { ++ netif_stop_queue(ndev); ++ if (atomic_read(&net_device->num_outstanding_sends) < 1) ++ netif_wake_queue(ndev); ++ } else { ++ netdev_err(ndev, "Unable to send packet %p ret %d\n", ++ packet, ret); ++ } ++ ++ return ret; ++} ++ ++static void netvsc_send_recv_completion(struct hv_device *device, ++ u64 transaction_id) ++{ ++ struct nvsp_message recvcompMessage; ++ int retries = 0; ++ int ret; ++ struct net_device *ndev; ++ struct netvsc_device *net_device = hv_get_drvdata(device); ++ ++ ndev = net_device->ndev; ++ ++ recvcompMessage.hdr.msg_type = ++ NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE; ++ ++ /* FIXME: Pass in the status */ ++ recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status = ++ NVSP_STAT_SUCCESS; ++ ++retry_send_cmplt: ++ /* Send the completion */ ++ ret = vmbus_sendpacket(device->channel, &recvcompMessage, ++ sizeof(struct nvsp_message), transaction_id, ++ VM_PKT_COMP, 0); ++ if (ret == 0) { ++ /* success */ ++ /* no-op */ ++ } else if (ret == -EAGAIN) { ++ /* no more room...wait a bit and attempt to retry 3 times */ ++ retries++; ++ netdev_err(ndev, "unable to send receive completion pkt" ++ " (tid %llx)...retrying %d\n", transaction_id, retries); ++ ++ if (retries < 4) { ++ udelay(100); ++ goto retry_send_cmplt; ++ } else { ++ netdev_err(ndev, "unable to send receive " ++ "completion pkt (tid %llx)...give up retrying\n", ++ transaction_id); ++ } ++ } else { ++ netdev_err(ndev, "unable to send receive " ++ "completion pkt - %llx\n", transaction_id); ++ } ++} ++ ++/* Send a receive completion packet to RNDIS device (ie NetVsp) */ ++static void netvsc_receive_completion(void *context) ++{ ++ struct hv_netvsc_packet *packet = context; ++ struct hv_device *device = (struct hv_device *)packet->device; ++ struct netvsc_device *net_device; ++ u64 transaction_id = 0; ++ bool fsend_receive_comp = false; ++ unsigned long flags; ++ struct net_device *ndev; ++ ++ /* ++ * Even though it seems logical to do a GetOutboundNetDevice() here to ++ * send out receive completion, we are using GetInboundNetDevice() ++ * since we may have disable outbound traffic already. ++ */ ++ net_device = get_inbound_net_device(device); ++ if (!net_device) ++ return; ++ ndev = net_device->ndev; ++ ++ /* Overloading use of the lock. */ ++ spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags); ++ ++ packet->xfer_page_pkt->count--; ++ ++ /* ++ * Last one in the line that represent 1 xfer page packet. ++ * Return the xfer page packet itself to the freelist ++ */ ++ if (packet->xfer_page_pkt->count == 0) { ++ fsend_receive_comp = true; ++ transaction_id = packet->completion.recv.recv_completion_tid; ++ list_add_tail(&packet->xfer_page_pkt->list_ent, ++ &net_device->recv_pkt_list); ++ ++ } ++ ++ /* Put the packet back */ ++ list_add_tail(&packet->list_ent, &net_device->recv_pkt_list); ++ spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags); ++ ++ /* Send a receive completion for the xfer page packet */ ++ if (fsend_receive_comp) ++ netvsc_send_recv_completion(device, transaction_id); ++ ++} ++ ++static void netvsc_receive(struct hv_device *device, ++ struct vmpacket_descriptor *packet) ++{ ++ struct netvsc_device *net_device; ++ struct vmtransfer_page_packet_header *vmxferpage_packet; ++ struct nvsp_message *nvsp_packet; ++ struct hv_netvsc_packet *netvsc_packet = NULL; ++ /* struct netvsc_driver *netvscDriver; */ ++ struct xferpage_packet *xferpage_packet = NULL; ++ int i; ++ int count = 0; ++ unsigned long flags; ++ struct net_device *ndev; ++ ++ LIST_HEAD(listHead); ++ ++ net_device = get_inbound_net_device(device); ++ if (!net_device) ++ return; ++ ndev = net_device->ndev; ++ ++ /* ++ * All inbound packets other than send completion should be xfer page ++ * packet ++ */ ++ if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) { ++ netdev_err(ndev, "Unknown packet type received - %d\n", ++ packet->type); ++ return; ++ } ++ ++ nvsp_packet = (struct nvsp_message *)((unsigned long)packet + ++ (packet->offset8 << 3)); ++ ++ /* Make sure this is a valid nvsp packet */ ++ if (nvsp_packet->hdr.msg_type != ++ NVSP_MSG1_TYPE_SEND_RNDIS_PKT) { ++ netdev_err(ndev, "Unknown nvsp packet type received-" ++ " %d\n", nvsp_packet->hdr.msg_type); ++ return; ++ } ++ ++ vmxferpage_packet = (struct vmtransfer_page_packet_header *)packet; ++ ++ if (vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID) { ++ netdev_err(ndev, "Invalid xfer page set id - " ++ "expecting %x got %x\n", NETVSC_RECEIVE_BUFFER_ID, ++ vmxferpage_packet->xfer_pageset_id); ++ return; ++ } ++ ++ /* ++ * Grab free packets (range count + 1) to represent this xfer ++ * page packet. +1 to represent the xfer page packet itself. ++ * We grab it here so that we know exactly how many we can ++ * fulfil ++ */ ++ spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags); ++ while (!list_empty(&net_device->recv_pkt_list)) { ++ list_move_tail(net_device->recv_pkt_list.next, &listHead); ++ if (++count == vmxferpage_packet->range_cnt + 1) ++ break; ++ } ++ spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags); ++ ++ /* ++ * We need at least 2 netvsc pkts (1 to represent the xfer ++ * page and at least 1 for the range) i.e. we can handled ++ * some of the xfer page packet ranges... ++ */ ++ if (count < 2) { ++ netdev_err(ndev, "Got only %d netvsc pkt...needed " ++ "%d pkts. Dropping this xfer page packet completely!\n", ++ count, vmxferpage_packet->range_cnt + 1); ++ ++ /* Return it to the freelist */ ++ spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags); ++ for (i = count; i != 0; i--) { ++ list_move_tail(listHead.next, ++ &net_device->recv_pkt_list); ++ } ++ spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, ++ flags); ++ ++ netvsc_send_recv_completion(device, ++ vmxferpage_packet->d.trans_id); ++ ++ return; ++ } ++ ++ /* Remove the 1st packet to represent the xfer page packet itself */ ++ xferpage_packet = (struct xferpage_packet *)listHead.next; ++ list_del(&xferpage_packet->list_ent); ++ ++ /* This is how much we can satisfy */ ++ xferpage_packet->count = count - 1; ++ ++ if (xferpage_packet->count != vmxferpage_packet->range_cnt) { ++ netdev_err(ndev, "Needed %d netvsc pkts to satisfy " ++ "this xfer page...got %d\n", ++ vmxferpage_packet->range_cnt, xferpage_packet->count); ++ } ++ ++ /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */ ++ for (i = 0; i < (count - 1); i++) { ++ netvsc_packet = (struct hv_netvsc_packet *)listHead.next; ++ list_del(&netvsc_packet->list_ent); ++ ++ /* Initialize the netvsc packet */ ++ netvsc_packet->xfer_page_pkt = xferpage_packet; ++ netvsc_packet->completion.recv.recv_completion = ++ netvsc_receive_completion; ++ netvsc_packet->completion.recv.recv_completion_ctx = ++ netvsc_packet; ++ netvsc_packet->device = device; ++ /* Save this so that we can send it back */ ++ netvsc_packet->completion.recv.recv_completion_tid = ++ vmxferpage_packet->d.trans_id; ++ ++ netvsc_packet->data = (void *)((unsigned long)net_device-> ++ recv_buf + vmxferpage_packet->ranges[i].byte_offset); ++ netvsc_packet->total_data_buflen = ++ vmxferpage_packet->ranges[i].byte_count; ++ ++ /* Pass it to the upper layer */ ++ rndis_filter_receive(device, netvsc_packet); ++ ++ netvsc_receive_completion(netvsc_packet-> ++ completion.recv.recv_completion_ctx); ++ } ++ ++} ++ ++static void netvsc_channel_cb(void *context) ++{ ++ int ret; ++ struct hv_device *device = context; ++ struct netvsc_device *net_device; ++ u32 bytes_recvd; ++ u64 request_id; ++ unsigned char *packet; ++ struct vmpacket_descriptor *desc; ++ unsigned char *buffer; ++ int bufferlen = NETVSC_PACKET_SIZE; ++ struct net_device *ndev; ++ ++ packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char), ++ GFP_ATOMIC); ++ if (!packet) ++ return; ++ buffer = packet; ++ ++ net_device = get_inbound_net_device(device); ++ if (!net_device) ++ goto out; ++ ndev = net_device->ndev; ++ ++ do { ++ ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen, ++ &bytes_recvd, &request_id); ++ if (ret == 0) { ++ if (bytes_recvd > 0) { ++ desc = (struct vmpacket_descriptor *)buffer; ++ switch (desc->type) { ++ case VM_PKT_COMP: ++ netvsc_send_completion(device, desc); ++ break; ++ ++ case VM_PKT_DATA_USING_XFER_PAGES: ++ netvsc_receive(device, desc); ++ break; ++ ++ default: ++ netdev_err(ndev, ++ "unhandled packet type %d, " ++ "tid %llx len %d\n", ++ desc->type, request_id, ++ bytes_recvd); ++ break; ++ } ++ ++ /* reset */ ++ if (bufferlen > NETVSC_PACKET_SIZE) { ++ kfree(buffer); ++ buffer = packet; ++ bufferlen = NETVSC_PACKET_SIZE; ++ } ++ } else { ++ /* reset */ ++ if (bufferlen > NETVSC_PACKET_SIZE) { ++ kfree(buffer); ++ buffer = packet; ++ bufferlen = NETVSC_PACKET_SIZE; ++ } ++ ++ break; ++ } ++ } else if (ret == -ENOBUFS) { ++ /* Handle large packet */ ++ buffer = kmalloc(bytes_recvd, GFP_ATOMIC); ++ if (buffer == NULL) { ++ /* Try again next time around */ ++ netdev_err(ndev, ++ "unable to allocate buffer of size " ++ "(%d)!!\n", bytes_recvd); ++ break; ++ } ++ ++ bufferlen = bytes_recvd; ++ } ++ } while (1); ++ ++out: ++ kfree(buffer); ++ return; ++} ++ ++/* ++ * netvsc_device_add - Callback when the device belonging to this ++ * driver is added ++ */ ++int netvsc_device_add(struct hv_device *device, void *additional_info) ++{ ++ int ret = 0; ++ int i; ++ int ring_size = ++ ((struct netvsc_device_info *)additional_info)->ring_size; ++ struct netvsc_device *net_device; ++ struct hv_netvsc_packet *packet, *pos; ++ struct net_device *ndev; ++ ++ net_device = alloc_net_device(device); ++ if (!net_device) { ++ ret = -ENOMEM; ++ goto cleanup; ++ } ++ ++ /* ++ * Coming into this function, struct net_device * is ++ * registered as the driver private data. ++ * In alloc_net_device(), we register struct netvsc_device * ++ * as the driver private data and stash away struct net_device * ++ * in struct netvsc_device *. ++ */ ++ ndev = net_device->ndev; ++ ++ /* Initialize the NetVSC channel extension */ ++ net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; ++ spin_lock_init(&net_device->recv_pkt_list_lock); ++ ++ INIT_LIST_HEAD(&net_device->recv_pkt_list); ++ ++ for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) { ++ packet = kzalloc(sizeof(struct hv_netvsc_packet) + ++ (NETVSC_RECEIVE_SG_COUNT * ++ sizeof(struct hv_page_buffer)), GFP_KERNEL); ++ if (!packet) ++ break; ++ ++ list_add_tail(&packet->list_ent, ++ &net_device->recv_pkt_list); ++ } ++ init_completion(&net_device->channel_init_wait); ++ ++ /* Open the channel */ ++ ret = vmbus_open(device->channel, ring_size * PAGE_SIZE, ++ ring_size * PAGE_SIZE, NULL, 0, ++ netvsc_channel_cb, device); ++ ++ if (ret != 0) { ++ netdev_err(ndev, "unable to open channel: %d\n", ret); ++ goto cleanup; ++ } ++ ++ /* Channel is opened */ ++ pr_info("hv_netvsc channel opened successfully\n"); ++ ++ /* Connect with the NetVsp */ ++ ret = netvsc_connect_vsp(device); ++ if (ret != 0) { ++ netdev_err(ndev, ++ "unable to connect to NetVSP - %d\n", ret); ++ goto close; ++ } ++ ++ return ret; ++ ++close: ++ /* Now, we can close the channel safely */ ++ vmbus_close(device->channel); ++ ++cleanup: ++ ++ if (net_device) { ++ list_for_each_entry_safe(packet, pos, ++ &net_device->recv_pkt_list, ++ list_ent) { ++ list_del(&packet->list_ent); ++ kfree(packet); ++ } ++ ++ kfree(net_device); ++ } ++ ++ return ret; ++} +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +new file mode 100644 +index 0000000..dd29478 +--- /dev/null ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -0,0 +1,507 @@ ++/* ++ * Copyright (c) 2009, Microsoft Corporation. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple ++ * Place - Suite 330, Boston, MA 02111-1307 USA. ++ * ++ * Authors: ++ * Haiyang Zhang ++ * Hank Janssen ++ */ ++#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 "hyperv_net.h" ++ ++struct net_device_context { ++ /* point back to our device context */ ++ struct hv_device *device_ctx; ++ struct delayed_work dwork; ++}; ++ ++ ++static int ring_size = 128; ++module_param(ring_size, int, S_IRUGO); ++MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); ++ ++struct set_multicast_work { ++ struct work_struct work; ++ struct net_device *net; ++}; ++ ++static void do_set_multicast(struct work_struct *w) ++{ ++ struct set_multicast_work *swk = ++ container_of(w, struct set_multicast_work, work); ++ struct net_device *net = swk->net; ++ ++ struct net_device_context *ndevctx = netdev_priv(net); ++ struct netvsc_device *nvdev; ++ struct rndis_device *rdev; ++ ++ nvdev = hv_get_drvdata(ndevctx->device_ctx); ++ if (nvdev == NULL) ++ goto out; ++ ++ rdev = nvdev->extension; ++ if (rdev == NULL) ++ goto out; ++ ++ if (net->flags & IFF_PROMISC) ++ rndis_filter_set_packet_filter(rdev, ++ NDIS_PACKET_TYPE_PROMISCUOUS); ++ else ++ rndis_filter_set_packet_filter(rdev, ++ NDIS_PACKET_TYPE_BROADCAST | ++ NDIS_PACKET_TYPE_ALL_MULTICAST | ++ NDIS_PACKET_TYPE_DIRECTED); ++ ++out: ++ kfree(w); ++} ++ ++static void netvsc_set_multicast_list(struct net_device *net) ++{ ++ struct set_multicast_work *swk = ++ kmalloc(sizeof(struct set_multicast_work), GFP_ATOMIC); ++ if (swk == NULL) ++ return; ++ ++ swk->net = net; ++ INIT_WORK(&swk->work, do_set_multicast); ++ schedule_work(&swk->work); ++} ++ ++static int netvsc_open(struct net_device *net) ++{ ++ struct net_device_context *net_device_ctx = netdev_priv(net); ++ struct hv_device *device_obj = net_device_ctx->device_ctx; ++ int ret = 0; ++ ++ /* Open up the device */ ++ ret = rndis_filter_open(device_obj); ++ if (ret != 0) { ++ netdev_err(net, "unable to open device (ret %d).\n", ret); ++ return ret; ++ } ++ ++ netif_start_queue(net); ++ ++ return ret; ++} ++ ++static int netvsc_close(struct net_device *net) ++{ ++ struct net_device_context *net_device_ctx = netdev_priv(net); ++ struct hv_device *device_obj = net_device_ctx->device_ctx; ++ int ret; ++ ++ netif_tx_disable(net); ++ ++ ret = rndis_filter_close(device_obj); ++ if (ret != 0) ++ netdev_err(net, "unable to close device (ret %d).\n", ret); ++ ++ return ret; ++} ++ ++static void netvsc_xmit_completion(void *context) ++{ ++ struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context; ++ struct sk_buff *skb = (struct sk_buff *) ++ (unsigned long)packet->completion.send.send_completion_tid; ++ ++ kfree(packet); ++ ++ if (skb) ++ dev_kfree_skb_any(skb); ++} ++ ++static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) ++{ ++ struct net_device_context *net_device_ctx = netdev_priv(net); ++ struct hv_netvsc_packet *packet; ++ int ret; ++ unsigned int i, num_pages, npg_data; ++ ++ /* Add multipages for skb->data and additional 2 for RNDIS */ ++ npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1) ++ >> PAGE_SHIFT) - ((unsigned long)skb->data >> PAGE_SHIFT) + 1; ++ num_pages = skb_shinfo(skb)->nr_frags + npg_data + 2; ++ ++ /* Allocate a netvsc packet based on # of frags. */ ++ packet = kzalloc(sizeof(struct hv_netvsc_packet) + ++ (num_pages * sizeof(struct hv_page_buffer)) + ++ sizeof(struct rndis_filter_packet) + ++ NDIS_VLAN_PPI_SIZE, GFP_ATOMIC); ++ if (!packet) { ++ /* out of memory, drop packet */ ++ netdev_err(net, "unable to allocate hv_netvsc_packet\n"); ++ ++ dev_kfree_skb(skb); ++ net->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ ++ packet->vlan_tci = skb->vlan_tci; ++ ++ packet->extension = (void *)(unsigned long)packet + ++ sizeof(struct hv_netvsc_packet) + ++ (num_pages * sizeof(struct hv_page_buffer)); ++ ++ /* If the rndis msg goes beyond 1 page, we will add 1 later */ ++ packet->page_buf_cnt = num_pages - 1; ++ ++ /* Initialize it from the skb */ ++ packet->total_data_buflen = skb->len; ++ ++ /* Start filling in the page buffers starting after RNDIS buffer. */ ++ packet->page_buf[1].pfn = virt_to_phys(skb->data) >> PAGE_SHIFT; ++ packet->page_buf[1].offset ++ = (unsigned long)skb->data & (PAGE_SIZE - 1); ++ if (npg_data == 1) ++ packet->page_buf[1].len = skb_headlen(skb); ++ else ++ packet->page_buf[1].len = PAGE_SIZE ++ - packet->page_buf[1].offset; ++ ++ for (i = 2; i <= npg_data; i++) { ++ packet->page_buf[i].pfn = virt_to_phys(skb->data ++ + PAGE_SIZE * (i-1)) >> PAGE_SHIFT; ++ packet->page_buf[i].offset = 0; ++ packet->page_buf[i].len = PAGE_SIZE; ++ } ++ if (npg_data > 1) ++ packet->page_buf[npg_data].len = (((unsigned long)skb->data ++ + skb_headlen(skb) - 1) & (PAGE_SIZE - 1)) + 1; ++ ++ /* Additional fragments are after SKB data */ ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ const skb_frag_t *f = &skb_shinfo(skb)->frags[i]; ++ ++ packet->page_buf[i+npg_data+1].pfn = ++ page_to_pfn(skb_frag_page(f)); ++ packet->page_buf[i+npg_data+1].offset = f->page_offset; ++ packet->page_buf[i+npg_data+1].len = skb_frag_size(f); ++ } ++ ++ /* Set the completion routine */ ++ packet->completion.send.send_completion = netvsc_xmit_completion; ++ packet->completion.send.send_completion_ctx = packet; ++ packet->completion.send.send_completion_tid = (unsigned long)skb; ++ ++ ret = rndis_filter_send(net_device_ctx->device_ctx, ++ packet); ++ if (ret == 0) { ++ net->stats.tx_bytes += skb->len; ++ net->stats.tx_packets++; ++ } else { ++ kfree(packet); ++ } ++ ++ return ret ? NETDEV_TX_BUSY : NETDEV_TX_OK; ++} ++ ++/* ++ * netvsc_linkstatus_callback - Link up/down notification ++ */ ++void netvsc_linkstatus_callback(struct hv_device *device_obj, ++ unsigned int status) ++{ ++ struct net_device *net; ++ struct net_device_context *ndev_ctx; ++ struct netvsc_device *net_device; ++ ++ net_device = hv_get_drvdata(device_obj); ++ net = net_device->ndev; ++ ++ if (!net) { ++ netdev_err(net, "got link status but net device " ++ "not initialized yet\n"); ++ return; ++ } ++ ++ if (status == 1) { ++ netif_carrier_on(net); ++ netif_wake_queue(net); ++ ndev_ctx = netdev_priv(net); ++ schedule_delayed_work(&ndev_ctx->dwork, 0); ++ schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20)); ++ } else { ++ netif_carrier_off(net); ++ netif_tx_disable(net); ++ } ++} ++ ++/* ++ * netvsc_recv_callback - Callback when we receive a packet from the ++ * "wire" on the specified device. ++ */ ++int netvsc_recv_callback(struct hv_device *device_obj, ++ struct hv_netvsc_packet *packet) ++{ ++ struct net_device *net; ++ struct sk_buff *skb; ++ ++ net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev; ++ if (!net) { ++ netdev_err(net, "got receive callback but net device" ++ " not initialized yet\n"); ++ return 0; ++ } ++ ++ /* Allocate a skb - TODO direct I/O to pages? */ ++ skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen); ++ if (unlikely(!skb)) { ++ ++net->stats.rx_dropped; ++ return 0; ++ } ++ ++ /* ++ * Copy to skb. This copy is needed here since the memory pointed by ++ * hv_netvsc_packet cannot be deallocated ++ */ ++ memcpy(skb_put(skb, packet->total_data_buflen), packet->data, ++ packet->total_data_buflen); ++ ++ skb->protocol = eth_type_trans(skb, net); ++ skb->ip_summed = CHECKSUM_NONE; ++ skb->vlan_tci = packet->vlan_tci; ++ ++ net->stats.rx_packets++; ++ net->stats.rx_bytes += packet->total_data_buflen; ++ ++ /* ++ * Pass the skb back up. Network stack will deallocate the skb when it ++ * is done. ++ * TODO - use NAPI? ++ */ ++ netif_rx(skb); ++ ++ return 0; ++} ++ ++static void netvsc_get_drvinfo(struct net_device *net, ++ struct ethtool_drvinfo *info) ++{ ++ strcpy(info->driver, KBUILD_MODNAME); ++ strcpy(info->version, HV_DRV_VERSION); ++ strcpy(info->fw_version, "N/A"); ++} ++ ++static int netvsc_change_mtu(struct net_device *ndev, int mtu) ++{ ++ struct net_device_context *ndevctx = netdev_priv(ndev); ++ struct hv_device *hdev = ndevctx->device_ctx; ++ struct netvsc_device *nvdev = hv_get_drvdata(hdev); ++ struct netvsc_device_info device_info; ++ int limit = ETH_DATA_LEN; ++ ++ if (nvdev == NULL || nvdev->destroy) ++ return -ENODEV; ++ ++ if (nvdev->nvsp_version == NVSP_PROTOCOL_VERSION_2) ++ limit = NETVSC_MTU; ++ ++ if (mtu < 68 || mtu > limit) ++ return -EINVAL; ++ ++ nvdev->start_remove = true; ++ cancel_delayed_work_sync(&ndevctx->dwork); ++ netif_tx_disable(ndev); ++ rndis_filter_device_remove(hdev); ++ ++ ndev->mtu = mtu; ++ ++ ndevctx->device_ctx = hdev; ++ hv_set_drvdata(hdev, ndev); ++ device_info.ring_size = ring_size; ++ rndis_filter_device_add(hdev, &device_info); ++ netif_wake_queue(ndev); ++ ++ return 0; ++} ++ ++static const struct ethtool_ops ethtool_ops = { ++ .get_drvinfo = netvsc_get_drvinfo, ++ .get_link = ethtool_op_get_link, ++}; ++ ++static const struct net_device_ops device_ops = { ++ .ndo_open = netvsc_open, ++ .ndo_stop = netvsc_close, ++ .ndo_start_xmit = netvsc_start_xmit, ++ .ndo_set_rx_mode = netvsc_set_multicast_list, ++ .ndo_change_mtu = netvsc_change_mtu, ++ .ndo_validate_addr = eth_validate_addr, ++ .ndo_set_mac_address = eth_mac_addr, ++}; ++ ++/* ++ * Send GARP packet to network peers after migrations. ++ * After Quick Migration, the network is not immediately operational in the ++ * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add ++ * another netif_notify_peers() into a delayed work, otherwise GARP packet ++ * will not be sent after quick migration, and cause network disconnection. ++ */ ++static void netvsc_send_garp(struct work_struct *w) ++{ ++ struct net_device_context *ndev_ctx; ++ struct net_device *net; ++ struct netvsc_device *net_device; ++ ++ ndev_ctx = container_of(w, struct net_device_context, dwork.work); ++ net_device = hv_get_drvdata(ndev_ctx->device_ctx); ++ net = net_device->ndev; ++ netif_notify_peers(net); ++} ++ ++ ++static int netvsc_probe(struct hv_device *dev, ++ const struct hv_vmbus_device_id *dev_id) ++{ ++ struct net_device *net = NULL; ++ struct net_device_context *net_device_ctx; ++ struct netvsc_device_info device_info; ++ int ret; ++ ++ net = alloc_etherdev(sizeof(struct net_device_context)); ++ if (!net) ++ return -ENOMEM; ++ ++ /* Set initial state */ ++ netif_carrier_off(net); ++ ++ net_device_ctx = netdev_priv(net); ++ net_device_ctx->device_ctx = dev; ++ hv_set_drvdata(dev, net); ++ INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp); ++ ++ net->netdev_ops = &device_ops; ++ ++ /* TODO: Add GSO and Checksum offload */ ++ net->hw_features = NETIF_F_SG; ++ net->features = NETIF_F_SG | NETIF_F_HW_VLAN_TX; ++ ++ SET_ETHTOOL_OPS(net, ðtool_ops); ++ SET_NETDEV_DEV(net, &dev->device); ++ ++ ret = register_netdev(net); ++ if (ret != 0) { ++ pr_err("Unable to register netdev.\n"); ++ free_netdev(net); ++ goto out; ++ } ++ ++ /* Notify the netvsc driver of the new device */ ++ device_info.ring_size = ring_size; ++ ret = rndis_filter_device_add(dev, &device_info); ++ if (ret != 0) { ++ netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); ++ unregister_netdev(net); ++ free_netdev(net); ++ hv_set_drvdata(dev, NULL); ++ return ret; ++ } ++ memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); ++ ++ netif_carrier_on(net); ++ ++out: ++ return ret; ++} ++ ++static int netvsc_remove(struct hv_device *dev) ++{ ++ struct net_device *net; ++ struct net_device_context *ndev_ctx; ++ struct netvsc_device *net_device; ++ ++ net_device = hv_get_drvdata(dev); ++ net = net_device->ndev; ++ ++ if (net == NULL) { ++ dev_err(&dev->device, "No net device to remove\n"); ++ return 0; ++ } ++ ++ net_device->start_remove = true; ++ ++ ndev_ctx = netdev_priv(net); ++ cancel_delayed_work_sync(&ndev_ctx->dwork); ++ ++ /* Stop outbound asap */ ++ netif_tx_disable(net); ++ ++ unregister_netdev(net); ++ ++ /* ++ * Call to the vsc driver to let it know that the device is being ++ * removed ++ */ ++ rndis_filter_device_remove(dev); ++ ++ free_netdev(net); ++ return 0; ++} ++ ++static const struct hv_vmbus_device_id id_table[] = { ++ /* Network guid */ ++ { VMBUS_DEVICE(0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, ++ 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E) }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(vmbus, id_table); ++ ++/* The one and only one */ ++static struct hv_driver netvsc_drv = { ++ .name = KBUILD_MODNAME, ++ .id_table = id_table, ++ .probe = netvsc_probe, ++ .remove = netvsc_remove, ++}; ++ ++static void __exit netvsc_drv_exit(void) ++{ ++ vmbus_driver_unregister(&netvsc_drv); ++} ++ ++static int __init netvsc_drv_init(void) ++{ ++ return vmbus_driver_register(&netvsc_drv); ++} ++ ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(HV_DRV_VERSION); ++MODULE_DESCRIPTION("Microsoft Hyper-V network driver"); ++ ++module_init(netvsc_drv_init); ++module_exit(netvsc_drv_exit); +diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c +new file mode 100644 +index 0000000..d6be64b +--- /dev/null ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -0,0 +1,892 @@ ++/* ++ * Copyright (c) 2009, Microsoft Corporation. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple ++ * Place - Suite 330, Boston, MA 02111-1307 USA. ++ * ++ * Authors: ++ * Haiyang Zhang ++ * Hank Janssen ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hyperv_net.h" ++ ++ ++struct rndis_request { ++ struct list_head list_ent; ++ struct completion wait_event; ++ ++ /* ++ * FIXME: We assumed a fixed size response here. If we do ever need to ++ * handle a bigger response, we can either define a max response ++ * message or add a response buffer variable above this field ++ */ ++ struct rndis_message response_msg; ++ ++ /* Simplify allocation by having a netvsc packet inline */ ++ struct hv_netvsc_packet pkt; ++ struct hv_page_buffer buf; ++ /* FIXME: We assumed a fixed size request here. */ ++ struct rndis_message request_msg; ++}; ++ ++static void rndis_filter_send_completion(void *ctx); ++ ++static void rndis_filter_send_request_completion(void *ctx); ++ ++ ++ ++static struct rndis_device *get_rndis_device(void) ++{ ++ struct rndis_device *device; ++ ++ device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL); ++ if (!device) ++ return NULL; ++ ++ spin_lock_init(&device->request_lock); ++ ++ INIT_LIST_HEAD(&device->req_list); ++ ++ device->state = RNDIS_DEV_UNINITIALIZED; ++ ++ return device; ++} ++ ++static struct rndis_request *get_rndis_request(struct rndis_device *dev, ++ u32 msg_type, ++ u32 msg_len) ++{ ++ struct rndis_request *request; ++ struct rndis_message *rndis_msg; ++ struct rndis_set_request *set; ++ unsigned long flags; ++ ++ request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL); ++ if (!request) ++ return NULL; ++ ++ init_completion(&request->wait_event); ++ ++ rndis_msg = &request->request_msg; ++ rndis_msg->ndis_msg_type = msg_type; ++ rndis_msg->msg_len = msg_len; ++ ++ /* ++ * Set the request id. This field is always after the rndis header for ++ * request/response packet types so we just used the SetRequest as a ++ * template ++ */ ++ set = &rndis_msg->msg.set_req; ++ set->req_id = atomic_inc_return(&dev->new_req_id); ++ ++ /* Add to the request list */ ++ spin_lock_irqsave(&dev->request_lock, flags); ++ list_add_tail(&request->list_ent, &dev->req_list); ++ spin_unlock_irqrestore(&dev->request_lock, flags); ++ ++ return request; ++} ++ ++static void put_rndis_request(struct rndis_device *dev, ++ struct rndis_request *req) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev->request_lock, flags); ++ list_del(&req->list_ent); ++ spin_unlock_irqrestore(&dev->request_lock, flags); ++ ++ kfree(req); ++} ++ ++static void dump_rndis_message(struct hv_device *hv_dev, ++ struct rndis_message *rndis_msg) ++{ ++ struct net_device *netdev; ++ struct netvsc_device *net_device; ++ ++ net_device = hv_get_drvdata(hv_dev); ++ netdev = net_device->ndev; ++ ++ switch (rndis_msg->ndis_msg_type) { ++ case REMOTE_NDIS_PACKET_MSG: ++ netdev_dbg(netdev, "REMOTE_NDIS_PACKET_MSG (len %u, " ++ "data offset %u data len %u, # oob %u, " ++ "oob offset %u, oob len %u, pkt offset %u, " ++ "pkt len %u\n", ++ rndis_msg->msg_len, ++ rndis_msg->msg.pkt.data_offset, ++ rndis_msg->msg.pkt.data_len, ++ rndis_msg->msg.pkt.num_oob_data_elements, ++ rndis_msg->msg.pkt.oob_data_offset, ++ rndis_msg->msg.pkt.oob_data_len, ++ rndis_msg->msg.pkt.per_pkt_info_offset, ++ rndis_msg->msg.pkt.per_pkt_info_len); ++ break; ++ ++ case REMOTE_NDIS_INITIALIZE_CMPLT: ++ netdev_dbg(netdev, "REMOTE_NDIS_INITIALIZE_CMPLT " ++ "(len %u, id 0x%x, status 0x%x, major %d, minor %d, " ++ "device flags %d, max xfer size 0x%x, max pkts %u, " ++ "pkt aligned %u)\n", ++ rndis_msg->msg_len, ++ rndis_msg->msg.init_complete.req_id, ++ rndis_msg->msg.init_complete.status, ++ rndis_msg->msg.init_complete.major_ver, ++ rndis_msg->msg.init_complete.minor_ver, ++ rndis_msg->msg.init_complete.dev_flags, ++ rndis_msg->msg.init_complete.max_xfer_size, ++ rndis_msg->msg.init_complete. ++ max_pkt_per_msg, ++ rndis_msg->msg.init_complete. ++ pkt_alignment_factor); ++ break; ++ ++ case REMOTE_NDIS_QUERY_CMPLT: ++ netdev_dbg(netdev, "REMOTE_NDIS_QUERY_CMPLT " ++ "(len %u, id 0x%x, status 0x%x, buf len %u, " ++ "buf offset %u)\n", ++ rndis_msg->msg_len, ++ rndis_msg->msg.query_complete.req_id, ++ rndis_msg->msg.query_complete.status, ++ rndis_msg->msg.query_complete. ++ info_buflen, ++ rndis_msg->msg.query_complete. ++ info_buf_offset); ++ break; ++ ++ case REMOTE_NDIS_SET_CMPLT: ++ netdev_dbg(netdev, ++ "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)\n", ++ rndis_msg->msg_len, ++ rndis_msg->msg.set_complete.req_id, ++ rndis_msg->msg.set_complete.status); ++ break; ++ ++ case REMOTE_NDIS_INDICATE_STATUS_MSG: ++ netdev_dbg(netdev, "REMOTE_NDIS_INDICATE_STATUS_MSG " ++ "(len %u, status 0x%x, buf len %u, buf offset %u)\n", ++ rndis_msg->msg_len, ++ rndis_msg->msg.indicate_status.status, ++ rndis_msg->msg.indicate_status.status_buflen, ++ rndis_msg->msg.indicate_status.status_buf_offset); ++ break; ++ ++ default: ++ netdev_dbg(netdev, "0x%x (len %u)\n", ++ rndis_msg->ndis_msg_type, ++ rndis_msg->msg_len); ++ break; ++ } ++} ++ ++static int rndis_filter_send_request(struct rndis_device *dev, ++ struct rndis_request *req) ++{ ++ int ret; ++ struct hv_netvsc_packet *packet; ++ ++ /* Setup the packet to send it */ ++ packet = &req->pkt; ++ ++ packet->is_data_pkt = false; ++ packet->total_data_buflen = req->request_msg.msg_len; ++ packet->page_buf_cnt = 1; ++ ++ packet->page_buf[0].pfn = virt_to_phys(&req->request_msg) >> ++ PAGE_SHIFT; ++ packet->page_buf[0].len = req->request_msg.msg_len; ++ packet->page_buf[0].offset = ++ (unsigned long)&req->request_msg & (PAGE_SIZE - 1); ++ ++ packet->completion.send.send_completion_ctx = req;/* packet; */ ++ packet->completion.send.send_completion = ++ rndis_filter_send_request_completion; ++ packet->completion.send.send_completion_tid = (unsigned long)dev; ++ ++ ret = netvsc_send(dev->net_dev->dev, packet); ++ return ret; ++} ++ ++static void rndis_filter_receive_response(struct rndis_device *dev, ++ struct rndis_message *resp) ++{ ++ struct rndis_request *request = NULL; ++ bool found = false; ++ unsigned long flags; ++ struct net_device *ndev; ++ ++ ndev = dev->net_dev->ndev; ++ ++ spin_lock_irqsave(&dev->request_lock, flags); ++ list_for_each_entry(request, &dev->req_list, list_ent) { ++ /* ++ * All request/response message contains RequestId as the 1st ++ * field ++ */ ++ if (request->request_msg.msg.init_req.req_id ++ == resp->msg.init_complete.req_id) { ++ found = true; ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&dev->request_lock, flags); ++ ++ if (found) { ++ if (resp->msg_len <= sizeof(struct rndis_message)) { ++ memcpy(&request->response_msg, resp, ++ resp->msg_len); ++ } else { ++ netdev_err(ndev, ++ "rndis response buffer overflow " ++ "detected (size %u max %zu)\n", ++ resp->msg_len, ++ sizeof(struct rndis_filter_packet)); ++ ++ if (resp->ndis_msg_type == ++ REMOTE_NDIS_RESET_CMPLT) { ++ /* does not have a request id field */ ++ request->response_msg.msg.reset_complete. ++ status = STATUS_BUFFER_OVERFLOW; ++ } else { ++ request->response_msg.msg. ++ init_complete.status = ++ STATUS_BUFFER_OVERFLOW; ++ } ++ } ++ ++ complete(&request->wait_event); ++ } else { ++ netdev_err(ndev, ++ "no rndis request found for this response " ++ "(id 0x%x res type 0x%x)\n", ++ resp->msg.init_complete.req_id, ++ resp->ndis_msg_type); ++ } ++} ++ ++static void rndis_filter_receive_indicate_status(struct rndis_device *dev, ++ struct rndis_message *resp) ++{ ++ struct rndis_indicate_status *indicate = ++ &resp->msg.indicate_status; ++ ++ if (indicate->status == RNDIS_STATUS_MEDIA_CONNECT) { ++ netvsc_linkstatus_callback( ++ dev->net_dev->dev, 1); ++ } else if (indicate->status == RNDIS_STATUS_MEDIA_DISCONNECT) { ++ netvsc_linkstatus_callback( ++ dev->net_dev->dev, 0); ++ } else { ++ /* ++ * TODO: ++ */ ++ } ++} ++ ++/* ++ * Get the Per-Packet-Info with the specified type ++ * return NULL if not found. ++ */ ++static inline void *rndis_get_ppi(struct rndis_packet *rpkt, u32 type) ++{ ++ struct rndis_per_packet_info *ppi; ++ int len; ++ ++ if (rpkt->per_pkt_info_offset == 0) ++ return NULL; ++ ++ ppi = (struct rndis_per_packet_info *)((ulong)rpkt + ++ rpkt->per_pkt_info_offset); ++ len = rpkt->per_pkt_info_len; ++ ++ while (len > 0) { ++ if (ppi->type == type) ++ return (void *)((ulong)ppi + ppi->ppi_offset); ++ len -= ppi->size; ++ ppi = (struct rndis_per_packet_info *)((ulong)ppi + ppi->size); ++ } ++ ++ return NULL; ++} ++ ++static void rndis_filter_receive_data(struct rndis_device *dev, ++ struct rndis_message *msg, ++ struct hv_netvsc_packet *pkt) ++{ ++ struct rndis_packet *rndis_pkt; ++ u32 data_offset; ++ struct ndis_pkt_8021q_info *vlan; ++ ++ rndis_pkt = &msg->msg.pkt; ++ ++ /* ++ * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this ++ * netvsc packet (ie TotalDataBufferLength != MessageLength) ++ */ ++ ++ /* Remove the rndis header and pass it back up the stack */ ++ data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset; ++ ++ pkt->total_data_buflen -= data_offset; ++ ++ /* ++ * Make sure we got a valid RNDIS message, now total_data_buflen ++ * should be the data packet size plus the trailer padding size ++ */ ++ if (pkt->total_data_buflen < rndis_pkt->data_len) { ++ netdev_err(dev->net_dev->ndev, "rndis message buffer " ++ "overflow detected (got %u, min %u)" ++ "...dropping this message!\n", ++ pkt->total_data_buflen, rndis_pkt->data_len); ++ return; ++ } ++ ++ /* ++ * Remove the rndis trailer padding from rndis packet message ++ * rndis_pkt->data_len tell us the real data length, we only copy ++ * the data packet to the stack, without the rndis trailer padding ++ */ ++ pkt->total_data_buflen = rndis_pkt->data_len; ++ pkt->data = (void *)((unsigned long)pkt->data + data_offset); ++ ++ pkt->is_data_pkt = true; ++ ++ vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO); ++ if (vlan) { ++ pkt->vlan_tci = VLAN_TAG_PRESENT | vlan->vlanid | ++ (vlan->pri << VLAN_PRIO_SHIFT); ++ } else { ++ pkt->vlan_tci = 0; ++ } ++ ++ netvsc_recv_callback(dev->net_dev->dev, pkt); ++} ++ ++int rndis_filter_receive(struct hv_device *dev, ++ struct hv_netvsc_packet *pkt) ++{ ++ struct netvsc_device *net_dev = hv_get_drvdata(dev); ++ struct rndis_device *rndis_dev; ++ struct rndis_message *rndis_msg; ++ struct net_device *ndev; ++ ++ if (!net_dev) ++ return -EINVAL; ++ ++ ndev = net_dev->ndev; ++ ++ /* Make sure the rndis device state is initialized */ ++ if (!net_dev->extension) { ++ netdev_err(ndev, "got rndis message but no rndis device - " ++ "dropping this message!\n"); ++ return -ENODEV; ++ } ++ ++ rndis_dev = (struct rndis_device *)net_dev->extension; ++ if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) { ++ netdev_err(ndev, "got rndis message but rndis device " ++ "uninitialized...dropping this message!\n"); ++ return -ENODEV; ++ } ++ ++ rndis_msg = pkt->data; ++ ++ dump_rndis_message(dev, rndis_msg); ++ ++ switch (rndis_msg->ndis_msg_type) { ++ case REMOTE_NDIS_PACKET_MSG: ++ /* data msg */ ++ rndis_filter_receive_data(rndis_dev, rndis_msg, pkt); ++ break; ++ ++ case REMOTE_NDIS_INITIALIZE_CMPLT: ++ case REMOTE_NDIS_QUERY_CMPLT: ++ case REMOTE_NDIS_SET_CMPLT: ++ /* completion msgs */ ++ rndis_filter_receive_response(rndis_dev, rndis_msg); ++ break; ++ ++ case REMOTE_NDIS_INDICATE_STATUS_MSG: ++ /* notification msgs */ ++ rndis_filter_receive_indicate_status(rndis_dev, rndis_msg); ++ break; ++ default: ++ netdev_err(ndev, ++ "unhandled rndis message (type %u len %u)\n", ++ rndis_msg->ndis_msg_type, ++ rndis_msg->msg_len); ++ break; ++ } ++ ++ return 0; ++} ++ ++static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, ++ void *result, u32 *result_size) ++{ ++ struct rndis_request *request; ++ u32 inresult_size = *result_size; ++ struct rndis_query_request *query; ++ struct rndis_query_complete *query_complete; ++ int ret = 0; ++ int t; ++ ++ if (!result) ++ return -EINVAL; ++ ++ *result_size = 0; ++ request = get_rndis_request(dev, REMOTE_NDIS_QUERY_MSG, ++ RNDIS_MESSAGE_SIZE(struct rndis_query_request)); ++ if (!request) { ++ ret = -ENOMEM; ++ goto cleanup; ++ } ++ ++ /* Setup the rndis query */ ++ query = &request->request_msg.msg.query_req; ++ query->oid = oid; ++ query->info_buf_offset = sizeof(struct rndis_query_request); ++ query->info_buflen = 0; ++ query->dev_vc_handle = 0; ++ ++ ret = rndis_filter_send_request(dev, request); ++ if (ret != 0) ++ goto cleanup; ++ ++ t = wait_for_completion_timeout(&request->wait_event, 5*HZ); ++ if (t == 0) { ++ ret = -ETIMEDOUT; ++ goto cleanup; ++ } ++ ++ /* Copy the response back */ ++ query_complete = &request->response_msg.msg.query_complete; ++ ++ if (query_complete->info_buflen > inresult_size) { ++ ret = -1; ++ goto cleanup; ++ } ++ ++ memcpy(result, ++ (void *)((unsigned long)query_complete + ++ query_complete->info_buf_offset), ++ query_complete->info_buflen); ++ ++ *result_size = query_complete->info_buflen; ++ ++cleanup: ++ if (request) ++ put_rndis_request(dev, request); ++ ++ return ret; ++} ++ ++static int rndis_filter_query_device_mac(struct rndis_device *dev) ++{ ++ u32 size = ETH_ALEN; ++ ++ return rndis_filter_query_device(dev, ++ RNDIS_OID_802_3_PERMANENT_ADDRESS, ++ dev->hw_mac_adr, &size); ++} ++ ++static int rndis_filter_query_device_link_status(struct rndis_device *dev) ++{ ++ u32 size = sizeof(u32); ++ u32 link_status; ++ int ret; ++ ++ ret = rndis_filter_query_device(dev, ++ RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, ++ &link_status, &size); ++ dev->link_state = (link_status != 0) ? true : false; ++ ++ return ret; ++} ++ ++int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter) ++{ ++ struct rndis_request *request; ++ struct rndis_set_request *set; ++ struct rndis_set_complete *set_complete; ++ u32 status; ++ int ret, t; ++ struct net_device *ndev; ++ ++ ndev = dev->net_dev->ndev; ++ ++ request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG, ++ RNDIS_MESSAGE_SIZE(struct rndis_set_request) + ++ sizeof(u32)); ++ if (!request) { ++ ret = -ENOMEM; ++ goto cleanup; ++ } ++ ++ /* Setup the rndis set */ ++ set = &request->request_msg.msg.set_req; ++ set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER; ++ set->info_buflen = sizeof(u32); ++ set->info_buf_offset = sizeof(struct rndis_set_request); ++ ++ memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request), ++ &new_filter, sizeof(u32)); ++ ++ ret = rndis_filter_send_request(dev, request); ++ if (ret != 0) ++ goto cleanup; ++ ++ t = wait_for_completion_timeout(&request->wait_event, 5*HZ); ++ ++ if (t == 0) { ++ netdev_err(ndev, ++ "timeout before we got a set response...\n"); ++ /* ++ * We can't deallocate the request since we may still receive a ++ * send completion for it. ++ */ ++ goto exit; ++ } else { ++ set_complete = &request->response_msg.msg.set_complete; ++ status = set_complete->status; ++ } ++ ++cleanup: ++ if (request) ++ put_rndis_request(dev, request); ++exit: ++ return ret; ++} ++ ++ ++static int rndis_filter_init_device(struct rndis_device *dev) ++{ ++ struct rndis_request *request; ++ struct rndis_initialize_request *init; ++ struct rndis_initialize_complete *init_complete; ++ u32 status; ++ int ret, t; ++ ++ request = get_rndis_request(dev, REMOTE_NDIS_INITIALIZE_MSG, ++ RNDIS_MESSAGE_SIZE(struct rndis_initialize_request)); ++ if (!request) { ++ ret = -ENOMEM; ++ goto cleanup; ++ } ++ ++ /* Setup the rndis set */ ++ init = &request->request_msg.msg.init_req; ++ init->major_ver = RNDIS_MAJOR_VERSION; ++ init->minor_ver = RNDIS_MINOR_VERSION; ++ /* FIXME: Use 1536 - rounded ethernet frame size */ ++ init->max_xfer_size = 2048; ++ ++ dev->state = RNDIS_DEV_INITIALIZING; ++ ++ ret = rndis_filter_send_request(dev, request); ++ if (ret != 0) { ++ dev->state = RNDIS_DEV_UNINITIALIZED; ++ goto cleanup; ++ } ++ ++ ++ t = wait_for_completion_timeout(&request->wait_event, 5*HZ); ++ ++ if (t == 0) { ++ ret = -ETIMEDOUT; ++ goto cleanup; ++ } ++ ++ init_complete = &request->response_msg.msg.init_complete; ++ status = init_complete->status; ++ if (status == RNDIS_STATUS_SUCCESS) { ++ dev->state = RNDIS_DEV_INITIALIZED; ++ ret = 0; ++ } else { ++ dev->state = RNDIS_DEV_UNINITIALIZED; ++ ret = -EINVAL; ++ } ++ ++cleanup: ++ if (request) ++ put_rndis_request(dev, request); ++ ++ return ret; ++} ++ ++static void rndis_filter_halt_device(struct rndis_device *dev) ++{ ++ struct rndis_request *request; ++ struct rndis_halt_request *halt; ++ ++ /* Attempt to do a rndis device halt */ ++ request = get_rndis_request(dev, REMOTE_NDIS_HALT_MSG, ++ RNDIS_MESSAGE_SIZE(struct rndis_halt_request)); ++ if (!request) ++ goto cleanup; ++ ++ /* Setup the rndis set */ ++ halt = &request->request_msg.msg.halt_req; ++ halt->req_id = atomic_inc_return(&dev->new_req_id); ++ ++ /* Ignore return since this msg is optional. */ ++ rndis_filter_send_request(dev, request); ++ ++ dev->state = RNDIS_DEV_UNINITIALIZED; ++ ++cleanup: ++ if (request) ++ put_rndis_request(dev, request); ++ return; ++} ++ ++static int rndis_filter_open_device(struct rndis_device *dev) ++{ ++ int ret; ++ ++ if (dev->state != RNDIS_DEV_INITIALIZED) ++ return 0; ++ ++ ret = rndis_filter_set_packet_filter(dev, ++ NDIS_PACKET_TYPE_BROADCAST | ++ NDIS_PACKET_TYPE_ALL_MULTICAST | ++ NDIS_PACKET_TYPE_DIRECTED); ++ if (ret == 0) ++ dev->state = RNDIS_DEV_DATAINITIALIZED; ++ ++ return ret; ++} ++ ++static int rndis_filter_close_device(struct rndis_device *dev) ++{ ++ int ret; ++ ++ if (dev->state != RNDIS_DEV_DATAINITIALIZED) ++ return 0; ++ ++ ret = rndis_filter_set_packet_filter(dev, 0); ++ if (ret == 0) ++ dev->state = RNDIS_DEV_INITIALIZED; ++ ++ return ret; ++} ++ ++int rndis_filter_device_add(struct hv_device *dev, ++ void *additional_info) ++{ ++ int ret; ++ struct netvsc_device *net_device; ++ struct rndis_device *rndis_device; ++ struct netvsc_device_info *device_info = additional_info; ++ ++ rndis_device = get_rndis_device(); ++ if (!rndis_device) ++ return -ENODEV; ++ ++ /* ++ * Let the inner driver handle this first to create the netvsc channel ++ * NOTE! Once the channel is created, we may get a receive callback ++ * (RndisFilterOnReceive()) before this call is completed ++ */ ++ ret = netvsc_device_add(dev, additional_info); ++ if (ret != 0) { ++ kfree(rndis_device); ++ return ret; ++ } ++ ++ ++ /* Initialize the rndis device */ ++ net_device = hv_get_drvdata(dev); ++ ++ net_device->extension = rndis_device; ++ rndis_device->net_dev = net_device; ++ ++ /* Send the rndis initialization message */ ++ ret = rndis_filter_init_device(rndis_device); ++ if (ret != 0) { ++ /* ++ * TODO: If rndis init failed, we will need to shut down the ++ * channel ++ */ ++ } ++ ++ /* Get the mac address */ ++ ret = rndis_filter_query_device_mac(rndis_device); ++ if (ret != 0) { ++ /* ++ * TODO: shutdown rndis device and the channel ++ */ ++ } ++ ++ memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN); ++ ++ rndis_filter_query_device_link_status(rndis_device); ++ ++ device_info->link_state = rndis_device->link_state; ++ ++ dev_info(&dev->device, "Device MAC %pM link state %s\n", ++ rndis_device->hw_mac_adr, ++ device_info->link_state ? "down" : "up"); ++ ++ return ret; ++} ++ ++void rndis_filter_device_remove(struct hv_device *dev) ++{ ++ struct netvsc_device *net_dev = hv_get_drvdata(dev); ++ struct rndis_device *rndis_dev = net_dev->extension; ++ ++ /* Halt and release the rndis device */ ++ rndis_filter_halt_device(rndis_dev); ++ ++ kfree(rndis_dev); ++ net_dev->extension = NULL; ++ ++ netvsc_device_remove(dev); ++} ++ ++ ++int rndis_filter_open(struct hv_device *dev) ++{ ++ struct netvsc_device *net_device = hv_get_drvdata(dev); ++ ++ if (!net_device) ++ return -EINVAL; ++ ++ return rndis_filter_open_device(net_device->extension); ++} ++ ++int rndis_filter_close(struct hv_device *dev) ++{ ++ struct netvsc_device *nvdev = hv_get_drvdata(dev); ++ ++ if (!nvdev) ++ return -EINVAL; ++ ++ return rndis_filter_close_device(nvdev->extension); ++} ++ ++int rndis_filter_send(struct hv_device *dev, ++ struct hv_netvsc_packet *pkt) ++{ ++ int ret; ++ struct rndis_filter_packet *filter_pkt; ++ struct rndis_message *rndis_msg; ++ struct rndis_packet *rndis_pkt; ++ u32 rndis_msg_size; ++ bool isvlan = pkt->vlan_tci & VLAN_TAG_PRESENT; ++ ++ /* Add the rndis header */ ++ filter_pkt = (struct rndis_filter_packet *)pkt->extension; ++ ++ rndis_msg = &filter_pkt->msg; ++ rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet); ++ if (isvlan) ++ rndis_msg_size += NDIS_VLAN_PPI_SIZE; ++ ++ rndis_msg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG; ++ rndis_msg->msg_len = pkt->total_data_buflen + ++ rndis_msg_size; ++ ++ rndis_pkt = &rndis_msg->msg.pkt; ++ rndis_pkt->data_offset = sizeof(struct rndis_packet); ++ if (isvlan) ++ rndis_pkt->data_offset += NDIS_VLAN_PPI_SIZE; ++ rndis_pkt->data_len = pkt->total_data_buflen; ++ ++ if (isvlan) { ++ struct rndis_per_packet_info *ppi; ++ struct ndis_pkt_8021q_info *vlan; ++ ++ rndis_pkt->per_pkt_info_offset = sizeof(struct rndis_packet); ++ rndis_pkt->per_pkt_info_len = NDIS_VLAN_PPI_SIZE; ++ ++ ppi = (struct rndis_per_packet_info *)((ulong)rndis_pkt + ++ rndis_pkt->per_pkt_info_offset); ++ ppi->size = NDIS_VLAN_PPI_SIZE; ++ ppi->type = IEEE_8021Q_INFO; ++ ppi->ppi_offset = sizeof(struct rndis_per_packet_info); ++ ++ vlan = (struct ndis_pkt_8021q_info *)((ulong)ppi + ++ ppi->ppi_offset); ++ vlan->vlanid = pkt->vlan_tci & VLAN_VID_MASK; ++ vlan->pri = (pkt->vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; ++ } ++ ++ pkt->is_data_pkt = true; ++ pkt->page_buf[0].pfn = virt_to_phys(rndis_msg) >> PAGE_SHIFT; ++ pkt->page_buf[0].offset = ++ (unsigned long)rndis_msg & (PAGE_SIZE-1); ++ pkt->page_buf[0].len = rndis_msg_size; ++ ++ /* Add one page_buf if the rndis msg goes beyond page boundary */ ++ if (pkt->page_buf[0].offset + rndis_msg_size > PAGE_SIZE) { ++ int i; ++ for (i = pkt->page_buf_cnt; i > 1; i--) ++ pkt->page_buf[i] = pkt->page_buf[i-1]; ++ pkt->page_buf_cnt++; ++ pkt->page_buf[0].len = PAGE_SIZE - pkt->page_buf[0].offset; ++ pkt->page_buf[1].pfn = virt_to_phys((void *)((ulong) ++ rndis_msg + pkt->page_buf[0].len)) >> PAGE_SHIFT; ++ pkt->page_buf[1].offset = 0; ++ pkt->page_buf[1].len = rndis_msg_size - pkt->page_buf[0].len; ++ } ++ ++ /* Save the packet send completion and context */ ++ filter_pkt->completion = pkt->completion.send.send_completion; ++ filter_pkt->completion_ctx = ++ pkt->completion.send.send_completion_ctx; ++ ++ /* Use ours */ ++ pkt->completion.send.send_completion = rndis_filter_send_completion; ++ pkt->completion.send.send_completion_ctx = filter_pkt; ++ ++ ret = netvsc_send(dev, pkt); ++ if (ret != 0) { ++ /* ++ * Reset the completion to originals to allow retries from ++ * above ++ */ ++ pkt->completion.send.send_completion = ++ filter_pkt->completion; ++ pkt->completion.send.send_completion_ctx = ++ filter_pkt->completion_ctx; ++ } ++ ++ return ret; ++} ++ ++static void rndis_filter_send_completion(void *ctx) ++{ ++ struct rndis_filter_packet *filter_pkt = ctx; ++ ++ /* Pass it back to the original handler */ ++ filter_pkt->completion(filter_pkt->completion_ctx); ++} ++ ++ ++static void rndis_filter_send_request_completion(void *ctx) ++{ ++ /* Noop */ ++} +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index 7300447..f29aed0 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -15,7 +15,9 @@ + #include + #include + ++#ifndef __GENKSYMS__ + #include ++#endif + #include + #include + #include +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index 6c58da2..2be6a54 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -75,6 +75,38 @@ static struct class mdio_bus_class = { + .dev_release = mdiobus_release, + }; + ++#ifdef CONFIG_OF_MDIO ++/* Helper function for of_mdio_find_bus */ ++static int of_mdio_bus_match(struct device *dev, void *mdio_bus_np) ++{ ++ return dev->of_node == mdio_bus_np; ++} ++/** ++ * of_mdio_find_bus - Given an mii_bus node, find the mii_bus. ++ * @mdio_np: Pointer to the mii_bus. ++ * ++ * Returns a pointer to the mii_bus, or NULL if none found. ++ * ++ * Because the association of a device_node and mii_bus is made via ++ * of_mdiobus_register(), the mii_bus cannot be found before it is ++ * registered with of_mdiobus_register(). ++ * ++ */ ++struct mii_bus *of_mdio_find_bus(struct device_node *mdio_bus_np) ++{ ++ struct device *d; ++ ++ if (!mdio_bus_np) ++ return NULL; ++ ++ d = class_find_device(&mdio_bus_class, NULL, mdio_bus_np, ++ of_mdio_bus_match); ++ ++ return d ? to_mii_bus(d) : NULL; ++} ++EXPORT_SYMBOL(of_mdio_find_bus); ++#endif ++ + /** + * mdiobus_register - bring up all the PHYs on a given bus and attach them to bus + * @bus: target mii_bus +@@ -208,14 +240,14 @@ EXPORT_SYMBOL(mdiobus_scan); + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +-int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) ++int mdiobus_read(struct mii_bus *bus, int addr, int devad, u16 regnum) + { + int retval; + + BUG_ON(in_interrupt()); + + mutex_lock(&bus->mdio_lock); +- retval = bus->read(bus, addr, regnum); ++ retval = bus->read(bus, addr, devad, regnum); + mutex_unlock(&bus->mdio_lock); + + return retval; +@@ -233,14 +265,14 @@ EXPORT_SYMBOL(mdiobus_read); + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +-int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) ++int mdiobus_write(struct mii_bus *bus, int addr, int devad, u16 regnum, u16 val) + { + int err; + + BUG_ON(in_interrupt()); + + mutex_lock(&bus->mdio_lock); +- err = bus->write(bus, addr, regnum, val); ++ err = bus->write(bus, addr, devad, regnum, val); + mutex_unlock(&bus->mdio_lock); + + return err; +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index 3cbda08..0825a78 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -6,7 +6,7 @@ + * + * Author: Andy Fleming + * +- * Copyright (c) 2004 Freescale Semiconductor, Inc. ++ * Copyright (c) 2004,2011 Freescale Semiconductor, Inc. + * Copyright (c) 2006, 2007 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or modify it +@@ -322,7 +322,7 @@ int phy_mii_ioctl(struct phy_device *phydev, + + case SIOCGMIIREG: + mii_data->val_out = mdiobus_read(phydev->bus, mii_data->phy_id, +- mii_data->reg_num); ++ 0, mii_data->reg_num); + break; + + case SIOCSMIIREG: +@@ -353,7 +353,7 @@ int phy_mii_ioctl(struct phy_device *phydev, + } + } + +- mdiobus_write(phydev->bus, mii_data->phy_id, ++ mdiobus_write(phydev->bus, mii_data->phy_id, 0, + mii_data->reg_num, val); + + if (mii_data->reg_num == MII_BMCR && +@@ -479,6 +479,10 @@ static void phy_force_reduction(struct phy_device *phydev) + + idx = phy_find_valid(idx, phydev->supported); + ++ /* Avoid reaching an invalid speed and duplex combination */ ++ if (!(settings[idx].setting & phydev->supported)) ++ return; ++ + phydev->speed = settings[idx].speed; + phydev->duplex = settings[idx].duplex; + +@@ -869,6 +873,8 @@ void phy_state_machine(struct work_struct *work) + if (0 == phydev->link_timeout--) { + phy_force_reduction(phydev); + needs_aneg = 1; ++ phydev->link_timeout = ++ PHY_FORCE_TIMEOUT; + } + } + +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index 83a5a5a..e88f49a 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -6,7 +6,7 @@ + * + * Author: Andy Fleming + * +- * Copyright (c) 2004 Freescale Semiconductor, Inc. ++ * Copyright (c) 2004-2006, 2008-2011 Freescale Semiconductor, 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 +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -51,15 +52,13 @@ static void phy_device_release(struct device *dev) + } + + static struct phy_driver genphy_driver; ++static struct phy_driver gen10g_driver; + extern int mdio_bus_init(void); + extern void mdio_bus_exit(void); + + static LIST_HEAD(phy_fixup_list); + static DEFINE_MUTEX(phy_fixup_lock); + +-static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, +- u32 flags, phy_interface_t interface); +- + /* + * Creates a new phy_fixup and adds it to the list + * @bus_id: A string which matches phydev->dev.bus_id (or PHY_ANY_ID) +@@ -210,23 +209,29 @@ static struct phy_device* phy_device_create(struct mii_bus *bus, + int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id) + { + int phy_reg; ++ int i; ++ ++ for (i = 1; i < 5; i++) { ++ /* Grab the bits from PHYIR1, and put them ++ * in the upper half */ ++ phy_reg = bus->read(bus, addr, i, MII_PHYSID1); + +- /* Grab the bits from PHYIR1, and put them +- * in the upper half */ +- phy_reg = mdiobus_read(bus, addr, MII_PHYSID1); ++ if (phy_reg < 0) ++ return -EIO; + +- if (phy_reg < 0) +- return -EIO; ++ *phy_id = (phy_reg & 0xffff) << 16; + +- *phy_id = (phy_reg & 0xffff) << 16; ++ /* Grab the bits from PHYIR2, and put them in the lower half */ ++ phy_reg = bus->read(bus, addr, i, MII_PHYSID2); + +- /* Grab the bits from PHYIR2, and put them in the lower half */ +- phy_reg = mdiobus_read(bus, addr, MII_PHYSID2); ++ if (phy_reg < 0) ++ return -EIO; + +- if (phy_reg < 0) +- return -EIO; ++ *phy_id |= (phy_reg & 0xffff); + +- *phy_id |= (phy_reg & 0xffff); ++ if (*phy_id != 0xffffffff) ++ break; ++ } + + return 0; + } +@@ -433,12 +438,12 @@ int phy_init_hw(struct phy_device *phydev) + * + * Description: Called by drivers to attach to a particular PHY + * device. The phy_device is found, and properly hooked up +- * to the phy_driver. If no driver is attached, then the +- * genphy_driver is used. The phy_device is given a ptr to ++ * to the phy_driver. If no driver is attached, then a ++ * generic driver is used. The phy_device is given a ptr to + * the attaching device, and given a callback for link status + * change. The phy_device is returned to the attaching driver. + */ +-static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, ++int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, + u32 flags, phy_interface_t interface) + { + struct device *d = &phydev->dev; +@@ -447,7 +452,11 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, + /* Assume that if there is no driver, that it doesn't + * exist, and we should use the genphy driver. */ + if (NULL == d->driver) { +- d->driver = &genphy_driver.driver; ++ int err; ++ if (interface == PHY_INTERFACE_MODE_XGMII) ++ d->driver = &gen10g_driver.driver; ++ else ++ d->driver = &genphy_driver.driver; + + err = d->driver->probe(d); + if (err >= 0) +@@ -531,6 +540,8 @@ void phy_detach(struct phy_device *phydev) + * real driver could be loaded */ + if (phydev->dev.driver == &genphy_driver.driver) + device_release_driver(&phydev->dev); ++ else if (phydev->dev.driver == &gen10g_driver.driver) ++ device_release_driver(&phydev->dev); + } + EXPORT_SYMBOL(phy_detach); + +@@ -612,6 +623,12 @@ static int genphy_config_advert(struct phy_device *phydev) + return changed; + } + ++int gen10g_config_advert(struct phy_device *dev) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(gen10g_config_advert); ++ + /** + * genphy_setup_forced - configures/forces speed/duplex from @phydev + * @phydev: target phy_device struct +@@ -620,7 +637,7 @@ static int genphy_config_advert(struct phy_device *phydev) + * to the values in phydev. Assumes that the values are valid. + * Please see phy_sanitize_settings(). + */ +-static int genphy_setup_forced(struct phy_device *phydev) ++int genphy_setup_forced(struct phy_device *phydev) + { + int err; + int ctl = 0; +@@ -639,7 +656,12 @@ static int genphy_setup_forced(struct phy_device *phydev) + + return err; + } ++EXPORT_SYMBOL(genphy_setup_forced); + ++int gen10g_setup_forced(struct phy_device *phydev) ++{ ++ return 0; ++} + + /** + * genphy_restart_aneg - Enable and Restart Autonegotiation +@@ -665,6 +687,12 @@ int genphy_restart_aneg(struct phy_device *phydev) + } + EXPORT_SYMBOL(genphy_restart_aneg); + ++int gen10g_restart_aneg(struct phy_device *phydev) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(gen10g_restart_aneg); ++ + + /** + * genphy_config_aneg - restart auto-negotiation or write BMCR +@@ -707,6 +735,12 @@ int genphy_config_aneg(struct phy_device *phydev) + } + EXPORT_SYMBOL(genphy_config_aneg); + ++int gen10g_config_aneg(struct phy_device *phydev) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(gen10g_config_aneg); ++ + /** + * genphy_update_link - update link status in @phydev + * @phydev: target phy_device struct +@@ -790,6 +824,16 @@ int genphy_read_status(struct phy_device *phydev) + + lpa &= adv; + ++ err = phy_read(phydev, MII_BMSR); ++ ++ if (err < 0) ++ return err; ++ ++ /* if the link changed while reading speed and duplex ++ * abort the speed and duplex update */ ++ if (((err & BMSR_LSTATUS) == 0) != (phydev->link == 0)) ++ return 0; ++ + phydev->speed = SPEED_10; + phydev->duplex = DUPLEX_HALF; + phydev->pause = phydev->asym_pause = 0; +@@ -836,6 +880,33 @@ int genphy_read_status(struct phy_device *phydev) + } + EXPORT_SYMBOL(genphy_read_status); + ++int gen10g_read_status(struct phy_device *phydev) ++{ ++ int devad, reg; ++ u32 mmd_mask = phydev->mmds; ++ ++ phydev->link = 1; ++ ++ /* For now just lie and say it's 10G all the time */ ++ phydev->speed = 10000; ++ phydev->duplex = DUPLEX_FULL; ++ ++ for (devad = 0; mmd_mask; devad++, mmd_mask = mmd_mask >> 1) { ++ if (!mmd_mask & 1) ++ continue; ++ ++ /* Read twice because link state is latched and a ++ * read moves the current state into the register */ ++ phy45_read(phydev, devad, MDIO_STAT1); ++ reg = phy45_read(phydev, devad, MDIO_STAT1); ++ if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS)) ++ phydev->link = 0; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(gen10g_read_status); ++ + static int genphy_config_init(struct phy_device *phydev) + { + int val; +@@ -882,6 +953,36 @@ static int genphy_config_init(struct phy_device *phydev) + + return 0; + } ++ ++/* Replicate mdio45_probe */ ++int gen10g_config_init(struct phy_device *phydev) ++{ ++ int mmd, stat2, devs1, devs2; ++ ++ phydev->supported = phydev->advertising = SUPPORTED_10000baseT_Full; ++ ++ /* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY ++ * XS or DTE XS; give up if none is present. */ ++ for (mmd = 1; mmd <= 5; mmd++) { ++ /* Is this MMD present? */ ++ stat2 = phy45_read(phydev, mmd, MDIO_STAT2); ++ if (stat2 < 0 || ++ (stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) ++ continue; ++ ++ /* It should tell us about all the other MMDs */ ++ devs1 = phy45_read(phydev, mmd, MDIO_DEVS1); ++ devs2 = phy45_read(phydev, mmd, MDIO_DEVS2); ++ if (devs1 < 0 || devs2 < 0) ++ continue; ++ ++ phydev->mmds = devs1 | (devs2 << 16); ++ return 0; ++ } ++ ++ return -ENODEV; ++} ++ + int genphy_suspend(struct phy_device *phydev) + { + int value; +@@ -897,6 +998,12 @@ int genphy_suspend(struct phy_device *phydev) + } + EXPORT_SYMBOL(genphy_suspend); + ++int gen10g_suspend(struct phy_device *phydev) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(gen10g_suspend); ++ + int genphy_resume(struct phy_device *phydev) + { + int value; +@@ -912,6 +1019,13 @@ int genphy_resume(struct phy_device *phydev) + } + EXPORT_SYMBOL(genphy_resume); + ++int gen10g_resume(struct phy_device *phydev) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(gen10g_resume); ++ ++ + /** + * phy_probe - probe and init a PHY device + * @dev: device to probe and init +@@ -1022,7 +1136,20 @@ static struct phy_driver genphy_driver = { + .read_status = genphy_read_status, + .suspend = genphy_suspend, + .resume = genphy_resume, +- .driver = {.owner= THIS_MODULE, }, ++ .driver = {.owner = THIS_MODULE, }, ++}; ++ ++static struct phy_driver gen10g_driver = { ++ .phy_id = 0xffffffff, ++ .phy_id_mask = 0xffffffff, ++ .name = "Generic 10G PHY", ++ .config_init = gen10g_config_init, ++ .features = 0, ++ .config_aneg = gen10g_config_aneg, ++ .read_status = gen10g_read_status, ++ .suspend = gen10g_suspend, ++ .resume = gen10g_resume, ++ .driver = {.owner = THIS_MODULE, }, + }; + + static int __init phy_init(void) +@@ -1035,13 +1162,25 @@ static int __init phy_init(void) + + rc = phy_driver_register(&genphy_driver); + if (rc) +- mdio_bus_exit(); ++ goto genphy_register_failed; ++ ++ rc = phy_driver_register(&gen10g_driver); ++ if (rc) ++ goto gen10g_register_failed; ++ ++ return rc; ++ ++gen10g_register_failed: ++ phy_driver_unregister(&genphy_driver); ++genphy_register_failed: ++ mdio_bus_exit(); + + return rc; + } + + static void __exit phy_exit(void) + { ++ phy_driver_unregister(&gen10g_driver); + phy_driver_unregister(&genphy_driver); + mdio_bus_exit(); + } +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index 2fbbca6..acb7e2c 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -54,6 +54,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -64,7 +65,10 @@ + #include + #include + #include ++#include ++#ifndef __GENKSYMS__ + #include ++#endif + #include + #include + #include +@@ -126,7 +130,7 @@ struct tun_struct { + struct net_device *dev; + u32 set_features; + #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ +- NETIF_F_TSO6|NETIF_F_UFO) ++ NETIF_F_TSO6|NETIF_F_UFO | NETIF_F_HW_SWITCH_OFFLOAD) + struct fasync_struct *fasync; + + struct tap_filter txflt; +@@ -135,6 +139,10 @@ struct tun_struct { + + int vnet_hdr_sz; + ++ spinlock_t stat_lock; ++ struct u64_stats_sync stat_sync; ++ struct rtnl_link_stats64 stats; ++ + #ifdef TUN_DEBUG + int debug; + #endif +@@ -171,7 +179,8 @@ static int tun_attach(struct tun_struct *tun, struct file *file) + tfile->tun = tun; + tun->tfile = tfile; + tun->socket.file = file; +- netif_carrier_on(tun->dev); ++ if (!(tun->flags & TUN_SET_CARRIER)) ++ netif_carrier_on(tun->dev); + dev_hold(tun->dev); + sock_hold(tun->socket.sk); + atomic_inc(&tfile->count); +@@ -185,7 +194,8 @@ static void __tun_detach(struct tun_struct *tun) + { + /* Detach from net device */ + netif_tx_lock_bh(tun->dev); +- netif_carrier_off(tun->dev); ++ if (!(tun->flags & TUN_SET_CARRIER)) ++ netif_carrier_off(tun->dev); + tun->tfile = NULL; + tun->socket.file = NULL; + netif_tx_unlock_bh(tun->dev); +@@ -347,6 +357,8 @@ static void tun_net_uninit(struct net_device *dev) + struct tun_struct *tun = netdev_priv(dev); + struct tun_file *tfile = tun->tfile; + ++ port_uninit_ethtool_stats(dev); ++ + /* Inform the methods they need to stop using the dev. + */ + if (tfile) { +@@ -377,6 +389,15 @@ static int tun_net_close(struct net_device *dev) + return 0; + } + ++static inline void tun_stat64_inc(struct tun_struct *tun, u64 *stat) ++{ ++ spin_lock_bh(&tun->stat_lock); ++ u64_stats_update_begin(&tun->stat_sync); ++ (*stat)++; ++ u64_stats_update_end(&tun->stat_sync); ++ spin_unlock_bh(&tun->stat_lock); ++} ++ + /* Net device start xmit */ + static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) + { +@@ -406,7 +427,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) + + /* We won't see all dropped packets individually, so overrun + * error is more appropriate. */ +- dev->stats.tx_fifo_errors++; ++ tun_stat64_inc(tun, &tun->stats.tx_fifo_errors); + } else { + /* Single queue mode. + * Driver handles dropping of all packets itself. */ +@@ -431,7 +452,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) + return NETDEV_TX_OK; + + drop: +- dev->stats.tx_dropped++; ++ tun_stat64_inc(tun, &tun->stats.tx_dropped); + kfree_skb(skb); + return NETDEV_TX_OK; + } +@@ -446,12 +467,12 @@ static void tun_net_mclist(struct net_device *dev) + } + + #define MIN_MTU 68 +-#define MAX_MTU 65535 ++#define MAX_MTU 9216 + + static int + tun_net_change_mtu(struct net_device *dev, int new_mtu) + { +- if (new_mtu < MIN_MTU || new_mtu + dev->hard_header_len > MAX_MTU) ++ if (new_mtu < MIN_MTU || new_mtu > MAX_MTU) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +@@ -461,6 +482,8 @@ static u32 tun_net_fix_features(struct net_device *dev, u32 features) + { + struct tun_struct *tun = netdev_priv(dev); + ++ port_init_ethtool_stats(dev); ++ + return (features & tun->set_features) | (features & ~TUN_USER_FEATURES); + } + #ifdef CONFIG_NET_POLL_CONTROLLER +@@ -480,6 +503,62 @@ static void tun_poll_controller(struct net_device *dev) + return; + } + #endif ++ ++struct rtnl_link_stats64* tun_net_get_stats64(struct net_device *dev, ++ struct rtnl_link_stats64 *stats) ++{ ++ struct tun_struct *tun = netdev_priv(dev); ++ struct rtnl_link_stats64 tun_stats; ++ struct ethtool_stats estats = { 0, }; ++ unsigned int start; ++ int count; ++ u64 *hw_stats; ++ ++ do { ++ start = u64_stats_fetch_begin(&tun->stat_sync); ++ memcpy(&tun_stats, &tun->stats, sizeof(struct rtnl_link_stats64)); ++ } while (u64_stats_fetch_retry(&tun->stat_sync, start)); ++ ++ ++ count = port_get_sset_count(dev, ETH_SS_STATS); ++ if (count <= 0) ++ goto err_out; ++ ++ hw_stats = kcalloc(count, sizeof(u64), GFP_ATOMIC); ++ if (!hw_stats) ++ goto err_out; ++ ++ estats.n_stats = count; ++ port_get_ethtool_stats(dev, &estats, hw_stats); ++ ++ stats->rx_packets = hw_stats[1] + hw_stats[2] + hw_stats[3]; ++ stats->rx_bytes = hw_stats[0]; ++ stats->multicast = hw_stats[3]; ++ stats->rx_errors = hw_stats[12] + hw_stats[13]; ++ stats->rx_dropped = hw_stats[8] + tun_stats.rx_dropped; ++ stats->rx_frame_errors = tun_stats.rx_frame_errors; ++ ++ stats->tx_packets = hw_stats[5] + hw_stats[6] + hw_stats[7]; ++ stats->tx_bytes = hw_stats[4]; ++ stats->tx_errors = hw_stats[18] + tun_stats.tx_fifo_errors; ++ stats->tx_dropped = hw_stats[17] + tun_stats.tx_dropped; ++ ++ kfree(hw_stats); ++ ++err_out: ++ return stats; ++} ++ ++static int tun_change_proto_down(struct net_device *dev, bool proto_down) ++{ ++ struct tun_struct *tun = netdev_priv(dev); ++ ++ if (!(tun->flags & TUN_SET_CARRIER)) ++ return -EOPNOTSUPP; ++ dev->proto_down = proto_down; ++ return 0; ++} ++ + static const struct net_device_ops tun_netdev_ops = { + .ndo_uninit = tun_net_uninit, + .ndo_open = tun_net_open, +@@ -490,6 +569,7 @@ static const struct net_device_ops tun_netdev_ops = { + #ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tun_poll_controller, + #endif ++ .ndo_get_stats64 = tun_net_get_stats64, + }; + + static const struct net_device_ops tap_netdev_ops = { +@@ -505,6 +585,8 @@ static const struct net_device_ops tap_netdev_ops = { + #ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tun_poll_controller, + #endif ++ .ndo_get_stats64 = tun_net_get_stats64, ++ .ndo_change_proto_down = tun_change_proto_down, + }; + + /* Initialize net device. */ +@@ -651,12 +733,12 @@ static ssize_t tun_get_user(struct tun_struct *tun, + skb = tun_alloc_skb(tun, align, len, gso.hdr_len, noblock); + if (IS_ERR(skb)) { + if (PTR_ERR(skb) != -EAGAIN) +- tun->dev->stats.rx_dropped++; ++ tun_stat64_inc(tun, &tun->stats.rx_dropped); + return PTR_ERR(skb); + } + + if (skb_copy_datagram_from_iovec(skb, 0, iv, offset, len)) { +- tun->dev->stats.rx_dropped++; ++ tun_stat64_inc(tun, &tun->stats.rx_dropped); + kfree_skb(skb); + return -EFAULT; + } +@@ -664,7 +746,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, + if (gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { + if (!skb_partial_csum_set(skb, gso.csum_start, + gso.csum_offset)) { +- tun->dev->stats.rx_frame_errors++; ++ tun_stat64_inc(tun, &tun->stats.rx_frame_errors); + kfree_skb(skb); + return -EINVAL; + } +@@ -681,7 +763,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, + pi.proto = htons(ETH_P_IPV6); + break; + default: +- tun->dev->stats.rx_dropped++; ++ tun_stat64_inc(tun, &tun->stats.rx_dropped); + kfree_skb(skb); + return -EINVAL; + } +@@ -713,7 +795,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, + ipv6_proxy_select_ident(skb); + break; + default: +- tun->dev->stats.rx_frame_errors++; ++ tun_stat64_inc(tun, &tun->stats.rx_frame_errors); + kfree_skb(skb); + return -EINVAL; + } +@@ -723,7 +805,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, + + skb_shinfo(skb)->gso_size = gso.gso_size; + if (skb_shinfo(skb)->gso_size == 0) { +- tun->dev->stats.rx_frame_errors++; ++ tun_stat64_inc(tun, &tun->stats.rx_frame_errors); + kfree_skb(skb); + return -EINVAL; + } +@@ -735,9 +817,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, + + netif_rx_ni(skb); + +- tun->dev->stats.rx_packets++; +- tun->dev->stats.rx_bytes += len; +- + return count; + } + +@@ -835,9 +914,6 @@ static ssize_t tun_put_user(struct tun_struct *tun, + skb_copy_datagram_const_iovec(skb, 0, iv, total, len); + total += skb->len; + +- tun->dev->stats.tx_packets++; +- tun->dev->stats.tx_bytes += len; +- + return total; + } + +@@ -1138,6 +1214,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) + dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | + TUN_USER_FEATURES; + dev->features = dev->hw_features; ++ dev->vlan_features = dev->features; + + err = register_netdevice(tun->dev); + if (err < 0) +@@ -1153,6 +1230,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) + err = tun_attach(tun, file); + if (err < 0) + goto failed; ++ ++ if (tun->flags & TUN_SET_CARRIER) ++ netif_carrier_off(tun->dev); + } + + tun_debug(KERN_INFO, tun, "tun_set_iff\n"); +@@ -1172,6 +1252,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) + else + tun->flags &= ~TUN_VNET_HDR; + ++ if (ifr->ifr_flags & IFF_TUN_SET_CARRIER) ++ tun->flags |= TUN_SET_CARRIER; ++ else ++ tun->flags &= ~TUN_SET_CARRIER; ++ + /* Make sure persistent devices do not get stuck in + * xoff state. + */ +@@ -1229,6 +1314,11 @@ static int set_offload(struct tun_struct *tun, unsigned long arg) + } + } + ++ if (arg & TUN_F_HW_SWITCH_OFFLOAD) { ++ features |= NETIF_F_HW_SWITCH_OFFLOAD; ++ arg &= ~TUN_F_HW_SWITCH_OFFLOAD; ++ } ++ + /* This gives the user a way to test for new features in future by + * trying to set them. */ + if (arg) +@@ -1581,21 +1671,6 @@ static struct miscdevice tun_miscdev = { + + /* ethtool interface */ + +-static int tun_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +-{ +- cmd->supported = 0; +- cmd->advertising = 0; +- ethtool_cmd_speed_set(cmd, SPEED_10); +- cmd->duplex = DUPLEX_FULL; +- cmd->port = PORT_TP; +- cmd->phy_address = 0; +- cmd->transceiver = XCVR_INTERNAL; +- cmd->autoneg = AUTONEG_DISABLE; +- cmd->maxtxpkt = 0; +- cmd->maxrxpkt = 0; +- return 0; +-} +- + static void tun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) + { + struct tun_struct *tun = netdev_priv(dev); +@@ -1620,7 +1695,7 @@ static u32 tun_get_msglevel(struct net_device *dev) + struct tun_struct *tun = netdev_priv(dev); + return tun->debug; + #else +- return -EOPNOTSUPP; ++ return 0; + #endif + } + +@@ -1632,12 +1707,46 @@ static void tun_set_msglevel(struct net_device *dev, u32 value) + #endif + } + ++static void tun_get_ethtool_stats(struct net_device *dev, ++ struct ethtool_stats *stats, ++ u64 *data) ++{ ++ port_get_ethtool_stats(dev, stats, data); ++} ++ ++static void tun_get_ethtool_stats_clear(struct net_device *dev, ++ struct ethtool_stats *stats, ++ u64 *data) ++{ ++ struct tun_struct *tun = netdev_priv(dev); ++ ++ port_get_ethtool_stats_clear(dev, stats, data); ++ ++ spin_lock_bh(&tun->stat_lock); ++ u64_stats_update_begin(&tun->stat_sync); ++ tun->stats.rx_dropped = 0; ++ tun->stats.rx_frame_errors = 0; ++ tun->stats.tx_fifo_errors = 0; ++ tun->stats.tx_dropped = 0; ++ u64_stats_update_end(&tun->stat_sync); ++ spin_unlock_bh(&tun->stat_lock); ++ atomic_long_set(&dev->rx_dropped, 0); ++} ++ + static const struct ethtool_ops tun_ethtool_ops = { +- .get_settings = tun_get_settings, +- .get_drvinfo = tun_get_drvinfo, +- .get_msglevel = tun_get_msglevel, +- .set_msglevel = tun_set_msglevel, +- .get_link = ethtool_op_get_link, ++ .get_settings = port_get_settings, ++ .set_settings = port_set_settings, ++ .get_drvinfo = tun_get_drvinfo, ++ .get_msglevel = tun_get_msglevel, ++ .set_msglevel = tun_set_msglevel, ++ .get_link = ethtool_op_get_link, ++ .get_strings = port_get_strings, ++ .get_ethtool_stats = tun_get_ethtool_stats, ++ .get_ethtool_stats_clear = tun_get_ethtool_stats_clear, ++ .get_sset_count = port_get_sset_count, ++ .set_phys_id = port_set_phys_id, ++ .get_module_info = port_get_module_info, ++ .get_module_eeprom = port_get_module_eeprom, + }; + + +diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c +index 98ab759..ebc4b6e 100644 +--- a/drivers/net/usb/asix.c ++++ b/drivers/net/usb/asix.c +@@ -1636,6 +1636,10 @@ static const struct usb_device_id products [] = { + USB_DEVICE (0x04f1, 0x3008), + .driver_info = (unsigned long) &ax8817x_info, + }, { ++ // Lenovo U2L100P 10/100 ++ USB_DEVICE (0x17ef, 0x7203), ++ .driver_info = (unsigned long) &ax88772_info, ++}, { + // ASIX AX88772B 10/100 + USB_DEVICE (0x0b95, 0x772b), + .driver_info = (unsigned long) &ax88772_info, +diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c +index c4c6a73..16d4a1a 100644 +--- a/drivers/net/usb/kaweth.c ++++ b/drivers/net/usb/kaweth.c +@@ -399,10 +399,8 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth, + int ret; + + ret = request_firmware(&fw, fwname, &kaweth->dev->dev); +- if (ret) { +- err("Firmware request failed\n"); ++ if (ret) + return ret; +- } + + if (fw->size > KAWETH_FIRMWARE_BUF_SIZE) { + err("Firmware too big: %zu", fw->size); +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index f13a673..f3435e9 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -77,6 +77,11 @@ struct virtnet_info { + /* fragments + linear part + virtio header */ + struct scatterlist rx_sg[MAX_SKB_FRAGS + 2]; + struct scatterlist tx_sg[MAX_SKB_FRAGS + 2]; ++ ++ /* ethtool settings */ ++ __u32 speed; ++ __u8 duplex; ++ __u8 autoneg; + }; + + struct skb_vnet_hdr { +@@ -878,6 +883,34 @@ static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) + dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid); + } + ++static int virtnet_get_settings(struct net_device *dev, ++ struct ethtool_cmd *ecmd) ++{ ++ struct virtnet_info *vi = netdev_priv(dev); ++ ++ ethtool_cmd_speed_set(ecmd, vi->speed); ++ ecmd->duplex = vi->duplex; ++ ecmd->autoneg = vi->autoneg; ++ ++ return 0; ++} ++ ++static int virtnet_set_settings(struct net_device *dev, ++ struct ethtool_cmd *ecmd) ++{ ++ struct virtnet_info *vi = netdev_priv(dev); ++ int speed = ethtool_cmd_speed(ecmd); ++ ++ if (speed < SPEED_10 || speed > SPEED_10000) ++ return -EINVAL; ++ ++ vi->speed = speed; ++ vi->duplex = ecmd->duplex; ++ vi->autoneg = ecmd->autoneg; ++ ++ return 0; ++} ++ + static void virtnet_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) + { +@@ -890,7 +923,19 @@ static void virtnet_get_ringparam(struct net_device *dev, + + } + ++static void virtnet_init_settings(struct net_device *dev) ++{ ++ struct virtnet_info *vi = netdev_priv(dev); ++ ++ /* XXX: Set init speed to SPEED_10 the default virtio net speed; */ ++ vi->speed = SPEED_10000; ++ vi->duplex = DUPLEX_FULL; ++ vi->autoneg = 0; ++} ++ + static const struct ethtool_ops virtnet_ethtool_ops = { ++ .get_settings = virtnet_get_settings, ++ .set_settings = virtnet_set_settings, + .get_link = ethtool_op_get_link, + .get_ringparam = virtnet_get_ringparam, + }; +@@ -906,6 +951,24 @@ static int virtnet_change_mtu(struct net_device *dev, int new_mtu) + return 0; + } + ++static int virtnet_change_proto_down(struct net_device *dev, bool proto_down) ++{ ++ struct virtnet_info *vi = netdev_priv(dev); ++ ++ if (vi->status & VIRTIO_NET_S_LINK_UP) { ++ if (proto_down) { ++ netif_carrier_off(dev); ++ } else { ++ if (!netif_carrier_ok(dev)) { ++ netif_carrier_on(dev); ++ netif_wake_queue(dev); ++ } ++ } ++ } ++ dev->proto_down = proto_down; ++ return 0; ++} ++ + static const struct net_device_ops virtnet_netdev = { + .ndo_open = virtnet_open, + .ndo_stop = virtnet_close, +@@ -920,6 +983,7 @@ static const struct net_device_ops virtnet_netdev = { + #ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = virtnet_netpoll, + #endif ++ .ndo_change_proto_down = virtnet_change_proto_down, + }; + + static void virtnet_update_status(struct virtnet_info *vi) +@@ -940,8 +1004,10 @@ static void virtnet_update_status(struct virtnet_info *vi) + vi->status = v; + + if (vi->status & VIRTIO_NET_S_LINK_UP) { +- netif_carrier_on(vi->dev); +- netif_wake_queue(vi->dev); ++ if (!(vi->dev->proto_down)) { ++ netif_carrier_on(vi->dev); ++ netif_wake_queue(vi->dev); ++ } + } else { + netif_carrier_off(vi->dev); + netif_stop_queue(vi->dev); +@@ -981,9 +1047,9 @@ static int virtnet_probe(struct virtio_device *vdev) + /* Do we support "hardware" checksums? */ + if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) { + /* This opens up the world of extra features. */ +- dev->hw_features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; ++ dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG; + if (csum) +- dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; ++ dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; + + if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { + dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO +@@ -1054,6 +1120,8 @@ static int virtnet_probe(struct virtio_device *vdev) + dev->features |= NETIF_F_HW_VLAN_FILTER; + } + ++ virtnet_init_settings(dev); ++ + err = register_netdev(dev); + if (err) { + pr_debug("virtio_net: registering device failed\n"); +@@ -1076,7 +1144,8 @@ static int virtnet_probe(struct virtio_device *vdev) + virtnet_update_status(vi); + } else { + vi->status = VIRTIO_NET_S_LINK_UP; +- netif_carrier_on(dev); ++ if (!(dev->proto_down)) ++ netif_carrier_on(dev); + } + + pr_debug("virtnet: registered device %s\n", dev->name); +diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c +new file mode 100644 +index 0000000..40f2b24 +--- /dev/null ++++ b/drivers/net/vxlan.c +@@ -0,0 +1,1753 @@ ++/* ++ * VXLAN: Virtual eXtensiable Local Area Network ++ * ++ * Copyright (c) 2012 Vyatta Inc. ++ * ++ * 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. ++ * ++ * TODO ++ * - use IANA UDP port number (when defined) ++ * - IPv6 (not in RFC) ++ */ ++ ++#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 ++ ++#define VXLAN_VERSION "0.1" ++ ++#define VNI_HASH_BITS 10 ++#define VNI_HASH_SIZE (1<vni_list[hash_32(id, VNI_HASH_BITS)]; ++} ++ ++/* Look up VNI in a per net namespace table */ ++static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id) ++{ ++ struct vxlan_dev *vxlan; ++ struct hlist_node *node; ++ ++ hlist_for_each_entry_rcu(vxlan, node, vni_head(net, id), hlist) { ++ if (vxlan->vni == id) ++ return vxlan; ++ } ++ ++ return NULL; ++} ++ ++/* Fill in neighbour message in skbuff. */ ++static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan, ++ const struct vxlan_fdb *fdb, ++ u32 portid, u32 seq, int type, unsigned int flags) ++{ ++ unsigned long now = jiffies; ++ struct nda_cacheinfo ci; ++ struct nlmsghdr *nlh; ++ struct ndmsg *ndm; ++ ++ nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags); ++ if (nlh == NULL) ++ return -EMSGSIZE; ++ ++ ndm = nlmsg_data(nlh); ++ memset(ndm, 0, sizeof(*ndm)); ++ ndm->ndm_family = AF_BRIDGE; ++ ndm->ndm_state = fdb->state; ++ ndm->ndm_ifindex = vxlan->dev->ifindex; ++ ndm->ndm_flags = NTF_SELF; ++ ndm->ndm_type = NDA_DST; ++ ++ if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr)) ++ goto nla_put_failure; ++ ++ /* ++ if (nla_put_be32(skb, NDA_DST, fdb->remote_ip)) ++ goto nla_put_failure; ++ */ ++ NLA_PUT(skb, NDA_DST, 4, (u8 *)(&fdb->remote_ip)); ++ ++ ci.ndm_used = jiffies_to_clock_t(now - fdb->used); ++ ci.ndm_confirmed = 0; ++ ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); ++ ci.ndm_refcnt = 0; ++ ++ if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) ++ goto nla_put_failure; ++ ++ return nlmsg_end(skb, nlh); ++ ++nla_put_failure: ++ nlmsg_cancel(skb, nlh); ++ return -EMSGSIZE; ++} ++ ++static inline size_t vxlan_nlmsg_size(void) ++{ ++ return NLMSG_ALIGN(sizeof(struct ndmsg)) ++ + nla_total_size(ETH_ALEN) /* NDA_LLADDR */ ++ + nla_total_size(sizeof(__be32)) /* NDA_DST */ ++ + nla_total_size(sizeof(struct nda_cacheinfo)); ++} ++ ++static void vxlan_fdb_notify(struct vxlan_dev *vxlan, ++ const struct vxlan_fdb *fdb, int type) ++{ ++ struct net *net = dev_net(vxlan->dev); ++ struct sk_buff *skb; ++ int err = -ENOBUFS; ++ ++ skb = nlmsg_new(vxlan_nlmsg_size(), GFP_ATOMIC); ++ if (skb == NULL) ++ goto errout; ++ ++ err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0); ++ if (err < 0) { ++ /* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */ ++ WARN_ON(err == -EMSGSIZE); ++ kfree_skb(skb); ++ goto errout; ++ } ++ ++ rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); ++ return; ++errout: ++ if (err < 0) ++ rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); ++} ++ ++/* Hash Ethernet address */ ++static u32 eth_hash(const unsigned char *addr) ++{ ++ u64 value = get_unaligned((u64 *)addr); ++ ++ /* only want 6 bytes */ ++#ifdef __BIG_ENDIAN ++ value >>= 16; ++#else ++ value <<= 16; ++#endif ++ return hash_64(value, FDB_HASH_BITS); ++} ++ ++/* Hash chain to use given mac address */ ++static inline struct hlist_head *vxlan_fdb_head(struct vxlan_dev *vxlan, ++ const u8 *mac) ++{ ++ return &vxlan->fdb_head[eth_hash(mac)]; ++} ++ ++/* Look up Ethernet address in forwarding table */ ++static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan, ++ const u8 *mac) ++ ++{ ++ struct hlist_head *head = vxlan_fdb_head(vxlan, mac); ++ struct vxlan_fdb *f; ++ struct hlist_node *node; ++ ++ hlist_for_each_entry_rcu(f, node, head, hlist) { ++ if (compare_ether_addr(mac, f->eth_addr) == 0) ++ return f; ++ } ++ ++ return NULL; ++} ++ ++static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, ++ const u8 *mac) ++{ ++ struct vxlan_fdb *f; ++ ++ f = __vxlan_find_mac(vxlan, mac); ++ if (f) ++ f->used = jiffies; ++ ++ return f; ++} ++ ++/* Replace destination of unicast mac */ ++static int vxlan_fdb_replace(struct vxlan_fdb *f, __be32 ip) ++{ ++ /* In case of hardware forwarding with aging in kernel, update ++ * fdb when the corresponding entry in hardware gets used. As ++ * there is no flag to identify hardware or software forwarding, ++ * this has the side effect of updating "used" in software forwarding ++ * as well if there is any change in the entry. Also, update happens ++ * for mac move from one remote node to another. ++ */ ++ f->used = jiffies; ++ ++ /* Like bridge driver, do not send notification if fdb replace is to ++ * refresh entry and there is no change in content. ++ */ ++ if (f->remote_ip == ip) ++ return 0; ++ ++ f->remote_ip = ip; ++ return 1; ++} ++ ++/* Add new entry to forwarding table -- assumes lock held */ ++static int vxlan_fdb_create(struct vxlan_dev *vxlan, ++ const u8 *mac, __be32 ip, ++ __u16 state, __u16 flags) ++{ ++ struct vxlan_fdb *f; ++ int notify = 0; ++ ++ f = __vxlan_find_mac(vxlan, mac); ++ if (f) { ++ if (flags & NLM_F_EXCL) { ++ netdev_dbg(vxlan->dev, ++ "lost race to create %pM\n", mac); ++ return -EEXIST; ++ } ++ if (f->state != state) { ++ if ((f->state & NUD_PERMANENT) && ++ !(state & NUD_PERMANENT)) ++ return -EINVAL; ++ ++ f->state = state; ++ f->updated = jiffies; ++ notify = 1; ++ } ++ if ((flags & NLM_F_REPLACE)) { ++ /* Only change unicasts */ ++ if (!(is_multicast_ether_addr(f->eth_addr) || ++ is_zero_ether_addr(f->eth_addr))) { ++ int rc = vxlan_fdb_replace(f, ip); ++ ++ if (rc < 0) ++ return rc; ++ notify |= rc; ++ } else ++ return -EOPNOTSUPP; ++ } ++ } else { ++ if (!(flags & NLM_F_CREATE)) ++ return -ENOENT; ++ ++ if (vxlan->addrmax && vxlan->addrcnt >= vxlan->addrmax) ++ return -ENOSPC; ++ ++ netdev_dbg(vxlan->dev, "add %pM -> %pI4\n", mac, &ip); ++ f = kmalloc(sizeof(*f), GFP_ATOMIC); ++ if (!f) ++ return -ENOMEM; ++ ++ notify = 1; ++ f->remote_ip = ip; ++ f->state = state; ++ f->updated = f->used = jiffies; ++ memcpy(f->eth_addr, mac, ETH_ALEN); ++ ++ ++vxlan->addrcnt; ++ hlist_add_head_rcu(&f->hlist, ++ vxlan_fdb_head(vxlan, mac)); ++ } ++ ++ if (notify) ++ vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH); ++ ++ return 0; ++} ++ ++static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f) ++{ ++ netdev_dbg(vxlan->dev, ++ "delete %pM\n", f->eth_addr); ++ ++ --vxlan->addrcnt; ++ vxlan_fdb_notify(vxlan, f, RTM_DELNEIGH); ++ ++ hlist_del_rcu(&f->hlist); ++ kfree_rcu(f, rcu); ++} ++ ++static int vxlan_add_repl_node(struct vxlan_dev *vxlan, __be32 ip) ++{ ++ int i; ++ ++ if (ip == vxlan->saddr) ++ return 1; ++ ++ if (vxlan->repl_type != VXLAN_REPLICATION_SELF && ++ vxlan->repl_type != VXLAN_REPLICATION_NONE) ++ return 0; ++ ++ for (i = 0; i < MAX_VXLAN_REPLICATION_NODE_ADDRS; i++) { ++ if (vxlan->repl_nodes[i] == ip) ++ return 1; ++ ++ if (vxlan->repl_nodes[i] == 0) { ++ vxlan->repl_type = VXLAN_REPLICATION_SELF; ++ vxlan->repl_nodes[i] = ip; ++ return 1; ++ } ++ } ++ return 0; ++} ++ ++static int vxlan_del_repl_node(struct vxlan_dev *vxlan, __be32 ip) ++{ ++ int i; ++ bool found = false; ++ ++ if (vxlan->repl_type != VXLAN_REPLICATION_SELF && ++ vxlan->repl_type != VXLAN_REPLICATION_NONE) ++ return 1; ++ ++ for (i = 0; i < MAX_VXLAN_REPLICATION_NODE_ADDRS; i++) { ++ if (vxlan->repl_nodes[i] == ip) { ++ vxlan->repl_nodes[i] = 0; ++ found = true; ++ continue; ++ } ++ if (found && vxlan->repl_nodes[i] != 0) { ++ vxlan->repl_nodes[i - 1] = vxlan->repl_nodes[i]; ++ vxlan->repl_nodes[i] = 0; ++ } ++ } ++ if (found) ++ return 1; ++ ++ return 0; ++} ++ ++/* Add static entry (via netlink) */ ++static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], ++ struct net_device *dev, ++ const unsigned char *addr, u16 flags) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ __be32 ip; ++ int err; ++ ++ if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_REACHABLE))) { ++ pr_info("RTM_NEWNEIGH with invalid state %#x\n", ++ ndm->ndm_state); ++ return -EINVAL; ++ } ++ ++ if (tb[NDA_DST] == NULL) ++ return -EINVAL; ++ ++ if (nla_len(tb[NDA_DST]) != sizeof(__be32)) ++ return -EAFNOSUPPORT; ++ ++ ip = nla_get_be32(tb[NDA_DST]); ++ ++ if ((flags & NLM_F_APPEND) && ++ is_zero_ether_addr(addr)) { ++ if (vxlan_add_repl_node(vxlan, ip)) { ++ netdev_state_change(vxlan->dev); ++ return 0; ++ } ++ return -EINVAL; ++ } ++ ++ spin_lock_bh(&vxlan->hash_lock); ++ err = vxlan_fdb_create(vxlan, addr, ip, ndm->ndm_state, flags); ++ spin_unlock_bh(&vxlan->hash_lock); ++ ++ return err; ++} ++ ++/* Delete entry (via netlink) */ ++static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], ++ struct net_device *dev, ++ const unsigned char *addr) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ struct vxlan_fdb *f; ++ int err = -ENOENT; ++ __be32 ip; ++ ++ if (is_zero_ether_addr(addr)) { ++ if (!tb) ++ return -EINVAL; ++ if (tb[NDA_DST] == NULL) ++ return -EINVAL; ++ ++ if (nla_len(tb[NDA_DST]) != sizeof(__be32)) ++ return -EAFNOSUPPORT; ++ ++ ip = nla_get_be32(tb[NDA_DST]); ++ if (vxlan_del_repl_node(vxlan, ip)) { ++ netdev_state_change(vxlan->dev); ++ return 0; ++ } ++ } ++ ++ spin_lock_bh(&vxlan->hash_lock); ++ f = vxlan_find_mac(vxlan, addr); ++ if (f) { ++ vxlan_fdb_destroy(vxlan, f); ++ err = 0; ++ } ++ spin_unlock_bh(&vxlan->hash_lock); ++ ++ return err; ++} ++ ++/* Dump forwarding table */ ++static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, ++ struct net_device *dev, struct net_device *filter_dev, int *idx) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ unsigned int h; ++ ++ for (h = 0; h < FDB_HASH_SIZE; ++h) { ++ struct vxlan_fdb *f; ++ struct hlist_node *n; ++ int err; ++ ++ hlist_for_each_entry_rcu(f, n, &vxlan->fdb_head[h], hlist) { ++ if (*idx < cb->args[0]) ++ goto skip; ++ ++ err = vxlan_fdb_info(skb, vxlan, f, ++ NETLINK_CB(cb->skb).pid, ++ cb->nlh->nlmsg_seq, ++ RTM_NEWNEIGH, ++ NLM_F_MULTI); ++ if (err < 0) ++ return err; ++skip: ++ ++*idx; ++ } ++ } ++ ++ if (vxlan->repl_type != VXLAN_REPLICATION_SELF) ++ return 0; ++ ++ for (h = 0; h < MAX_VXLAN_REPLICATION_NODE_ADDRS; h++) { ++ int err; ++ ++ if (vxlan->repl_nodes[h] != 0) { ++ struct vxlan_fdb f; ++ ++ if (*idx < cb->args[0]) ++ goto skip1; ++ ++ memset(&f, 0, sizeof(f)); ++ f.remote_ip = vxlan->repl_nodes[h]; ++ f.state = NUD_PERMANENT|NUD_REACHABLE; ++ err = vxlan_fdb_info(skb, vxlan, &f, ++ NETLINK_CB(cb->skb).pid, ++ cb->nlh->nlmsg_seq, ++ RTM_NEWNEIGH, ++ NLM_F_MULTI); ++ if (err < 0) ++ return err; ++skip1: ++ ++*idx; ++ } ++ } ++ ++ return 0; ++} ++ ++/* Watch incoming packets to learn mapping between Ethernet address ++ * and Tunnel endpoint. ++ */ ++static void vxlan_snoop(struct net_device *dev, ++ __be32 src_ip, const u8 *src_mac) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ struct vxlan_fdb *f; ++ int err; ++ ++ f = vxlan_find_mac(vxlan, src_mac); ++ if (likely(f)) { ++ if (likely(f->remote_ip == src_ip)) ++ return; ++ ++ if (net_ratelimit()) ++ netdev_info(dev, ++ "%pM migrated from %pI4 to %pI4\n", ++ src_mac, &f->remote_ip, &src_ip); ++ ++ f->remote_ip = src_ip; ++ f->updated = jiffies; ++ vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH); ++ } else { ++ /* learned new entry */ ++ spin_lock(&vxlan->hash_lock); ++ err = vxlan_fdb_create(vxlan, src_mac, src_ip, ++ NUD_REACHABLE, ++ NLM_F_EXCL|NLM_F_CREATE); ++ spin_unlock(&vxlan->hash_lock); ++ } ++} ++ ++ ++/* See if multicast group is already in use by other ID */ ++static bool vxlan_group_used(struct vxlan_net *vn, ++ const struct vxlan_dev *this) ++{ ++ const struct vxlan_dev *vxlan; ++ struct hlist_node *node; ++ unsigned h; ++ ++ for (h = 0; h < VNI_HASH_SIZE; ++h) ++ hlist_for_each_entry(vxlan, node, &vn->vni_list[h], hlist) { ++ if (vxlan == this) ++ continue; ++ ++ if (!netif_running(vxlan->dev)) ++ continue; ++ ++ if (vxlan->gaddr == this->gaddr) ++ return true; ++ } ++ ++ return false; ++} ++ ++/* kernel equivalent to IP_ADD_MEMBERSHIP */ ++static int vxlan_join_group(struct net_device *dev) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); ++ struct sock *sk = vn->sock->sk; ++ struct ip_mreqn mreq = { ++ .imr_multiaddr.s_addr = vxlan->gaddr, ++ }; ++ int err; ++ ++ /* Already a member of group */ ++ if (vxlan_group_used(vn, vxlan)) ++ return 0; ++ ++ /* Need to drop RTNL to call multicast join */ ++ rtnl_unlock(); ++ lock_sock(sk); ++ err = ip_mc_join_group(sk, &mreq); ++ release_sock(sk); ++ rtnl_lock(); ++ ++ return err; ++} ++ ++ ++/* kernel equivalent to IP_DROP_MEMBERSHIP */ ++static int vxlan_leave_group(struct net_device *dev) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); ++ int err = 0; ++ struct sock *sk = vn->sock->sk; ++ struct ip_mreqn mreq = { ++ .imr_multiaddr.s_addr = vxlan->gaddr, ++ }; ++ ++ /* Only leave group when last vxlan is done. */ ++ if (vxlan_group_used(vn, vxlan)) ++ return 0; ++ ++ /* Need to drop RTNL to call multicast leave */ ++ rtnl_unlock(); ++ lock_sock(sk); ++ err = ip_mc_leave_group(sk, &mreq); ++ release_sock(sk); ++ rtnl_lock(); ++ ++ return err; ++} ++ ++/* Callback from net/ipv4/udp.c to receive packets */ ++static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) ++{ ++ struct iphdr *oip; ++ struct vxlanhdr *vxh; ++ struct vxlan_dev *vxlan; ++ struct vxlan_stats *stats; ++ __u32 vni; ++ int err; ++ ++ /* pop off outer UDP header */ ++ __skb_pull(skb, sizeof(struct udphdr)); ++ ++ /* Need Vxlan and inner Ethernet header to be present */ ++ if (!pskb_may_pull(skb, sizeof(struct vxlanhdr))) ++ goto error; ++ ++ /* Drop packets with reserved bits set */ ++ vxh = (struct vxlanhdr *) skb->data; ++ if (vxh->vx_flags != htonl(VXLAN_FLAGS) || ++ (vxh->vx_vni & htonl(0xff))) { ++ netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n", ++ ntohl(vxh->vx_flags), ntohl(vxh->vx_vni)); ++ goto error; ++ } ++ ++ __skb_pull(skb, sizeof(struct vxlanhdr)); ++ ++ /* Is this VNI defined? */ ++ vni = ntohl(vxh->vx_vni) >> 8; ++ vxlan = vxlan_find_vni(sock_net(sk), vni); ++ if (!vxlan) { ++ netdev_dbg(skb->dev, "unknown vni %d\n", vni); ++ goto drop; ++ } ++ ++ if (!pskb_may_pull(skb, ETH_HLEN)) { ++ vxlan->dev->stats.rx_length_errors++; ++ vxlan->dev->stats.rx_errors++; ++ goto drop; ++ } ++ ++ /* Re-examine inner Ethernet packet */ ++ oip = ip_hdr(skb); ++ skb->protocol = eth_type_trans(skb, vxlan->dev); ++ ++ /* Ignore packet loops (and multicast echo) */ ++ if (compare_ether_addr(eth_hdr(skb)->h_source, ++ vxlan->dev->dev_addr) == 0) ++ goto drop; ++ ++ if (vxlan->learn) ++ vxlan_snoop(skb->dev, oip->saddr, eth_hdr(skb)->h_source); ++ ++ __skb_tunnel_rx(skb, vxlan->dev); ++ skb_reset_network_header(skb); ++ skb->ip_summed = CHECKSUM_NONE; ++ ++ err = IP_ECN_decapsulate(oip, skb); ++ if (unlikely(err)) { ++ if (log_ecn_error) ++ net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", ++ &oip->saddr, oip->tos); ++ if (err > 1) { ++ ++vxlan->dev->stats.rx_frame_errors; ++ ++vxlan->dev->stats.rx_errors; ++ goto drop; ++ } ++ } ++ ++ stats = this_cpu_ptr(vxlan->stats); ++ u64_stats_update_begin(&stats->syncp); ++ stats->rx_packets++; ++ stats->rx_bytes += skb->len; ++ u64_stats_update_end(&stats->syncp); ++ ++ netif_rx(skb); ++ ++ return 0; ++error: ++ /* Put UDP header back */ ++ __skb_push(skb, sizeof(struct udphdr)); ++ ++ return 1; ++drop: ++ /* Consume bad packet */ ++ kfree_skb(skb); ++ return 0; ++} ++ ++/* Extract dsfield from inner protocol */ ++static inline u8 vxlan_get_dsfield(const struct iphdr *iph, ++ const struct sk_buff *skb) ++{ ++ if (skb->protocol == htons(ETH_P_IP)) ++ return iph->tos; ++ else if (skb->protocol == htons(ETH_P_IPV6)) ++ return ipv6_get_dsfield((const struct ipv6hdr *)iph); ++ else ++ return 0; ++} ++ ++/* Propogate ECN bits out */ ++static inline u8 vxlan_ecn_encap(u8 tos, ++ const struct iphdr *iph, ++ const struct sk_buff *skb) ++{ ++ u8 inner = vxlan_get_dsfield(iph, skb); ++ ++ return INET_ECN_encapsulate(tos, inner); ++} ++ ++static void vxlan_sock_free(struct sk_buff *skb) ++{ ++ sock_put(skb->sk); ++} ++ ++/* On transmit, associate with the tunnel socket */ ++static void vxlan_set_owner(struct net_device *dev, struct sk_buff *skb) ++{ ++ struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); ++ struct sock *sk = vn->sock->sk; ++ ++ skb_orphan(skb); ++ sock_hold(sk); ++ skb->sk = sk; ++ skb->destructor = vxlan_sock_free; ++} ++ ++/* Compute source port for outgoing packet ++ * first choice to use L4 flow hash since it will spread ++ * better and maybe available from hardware ++ * secondary choice is to use jhash on the Ethernet header ++ */ ++static u16 vxlan_src_port(const struct vxlan_dev *vxlan, struct sk_buff *skb) ++{ ++ unsigned int range = (vxlan->port_max - vxlan->port_min) + 1; ++ u32 hash; ++ ++ hash = skb_get_rxhash(skb); ++ if (!hash) ++ hash = jhash(skb->data, 2 * ETH_ALEN, ++ (__force u32) skb->protocol); ++ ++ return (((u64) hash * range) >> 32) + vxlan->port_min; ++} ++ ++static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, __be32 dst) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ struct rtable *rt; ++ const struct iphdr *old_iph; ++ struct iphdr *iph; ++ struct vxlanhdr *vxh; ++ struct udphdr *uh; ++ struct flowi4 fl4; ++ unsigned int pkt_len = skb->len; ++ __u16 src_port; ++ __be16 df = 0; ++ __u8 tos, ttl; ++ int err; ++ ++ if (!dst) ++ goto drop; ++ ++ /* Need space for new headers (invalidates iph ptr) */ ++ if (skb_cow_head(skb, VXLAN_HEADROOM)) ++ goto drop; ++ ++ old_iph = ip_hdr(skb); ++ ++ ttl = vxlan->ttl; ++ if (!ttl && IN_MULTICAST(ntohl(dst))) ++ ttl = 1; ++ ++ tos = vxlan->tos; ++ if (tos == 1) ++ tos = vxlan_get_dsfield(old_iph, skb); ++ ++ src_port = vxlan_src_port(vxlan, skb); ++ ++ memset(&fl4, 0, sizeof(fl4)); ++ fl4.flowi4_oif = vxlan->link; ++ fl4.flowi4_tos = RT_TOS(tos); ++ fl4.daddr = dst; ++ fl4.saddr = vxlan->saddr; ++ ++ rt = ip_route_output_key(dev_net(dev), &fl4); ++ if (IS_ERR(rt)) { ++ netdev_dbg(dev, "no route to %pI4\n", &dst); ++ dev->stats.tx_carrier_errors++; ++ goto tx_error; ++ } ++ ++ if (rt->dst.dev == dev) { ++ netdev_dbg(dev, "circular route to %pI4\n", &dst); ++ ip_rt_put(rt); ++ dev->stats.collisions++; ++ goto tx_error; ++ } ++ ++ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); ++ IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | ++ IPSKB_REROUTED); ++ skb_dst_drop(skb); ++ skb_dst_set(skb, &rt->dst); ++ ++ vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); ++ vxh->vx_flags = htonl(VXLAN_FLAGS); ++ vxh->vx_vni = htonl(vxlan->vni << 8); ++ ++ __skb_push(skb, sizeof(*uh)); ++ skb_reset_transport_header(skb); ++ uh = udp_hdr(skb); ++ ++ uh->dest = htons(vxlan_port); ++ uh->source = htons(src_port); ++ ++ uh->len = htons(skb->len); ++ uh->check = 0; ++ ++ __skb_push(skb, sizeof(*iph)); ++ skb_reset_network_header(skb); ++ iph = ip_hdr(skb); ++ iph->version = 4; ++ iph->ihl = sizeof(struct iphdr) >> 2; ++ iph->frag_off = df; ++ iph->protocol = IPPROTO_UDP; ++ iph->tos = vxlan_ecn_encap(tos, old_iph, skb); ++ iph->daddr = dst; ++ iph->saddr = fl4.saddr; ++ iph->ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); ++ ++ vxlan_set_owner(dev, skb); ++ ++ /* See __IPTUNNEL_XMIT */ ++ skb->ip_summed = CHECKSUM_NONE; ++ ip_select_ident(skb, NULL); ++ ++ err = ip_local_out(skb); ++ if (likely(net_xmit_eval(err) == 0)) { ++ struct vxlan_stats *stats = this_cpu_ptr(vxlan->stats); ++ ++ u64_stats_update_begin(&stats->syncp); ++ stats->tx_packets++; ++ stats->tx_bytes += pkt_len; ++ u64_stats_update_end(&stats->syncp); ++ } else { ++ dev->stats.tx_errors++; ++ dev->stats.tx_aborted_errors++; ++ } ++ return NETDEV_TX_OK; ++ ++drop: ++ dev->stats.tx_dropped++; ++ goto tx_free; ++ ++tx_error: ++ dev->stats.tx_errors++; ++tx_free: ++ dev_kfree_skb(skb); ++ return NETDEV_TX_OK; ++} ++ ++ ++/* Transmit local packets over Vxlan ++ * ++ * Outer IP header inherits ECN and DF from inner header. ++ * Outer UDP destination is the VXLAN assigned port. ++ * source port is based on hash of flow ++ */ ++static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ const struct ethhdr *eth = (struct ethhdr *) skb->data; ++ const struct vxlan_fdb *f; ++ struct sk_buff* nskb; ++ int i; ++ netdev_tx_t ret = NETDEV_TX_OK; ++ ++ if (is_multicast_ether_addr(eth->h_dest)) { ++ /* XXX */ ++ netdev_dbg(dev, "%s, repl_type: %d gaddr: %x, vxlan port %d\n", __FUNCTION__, vxlan->repl_type, vxlan->gaddr, vxlan_port); ++ if (vxlan->gaddr) ++ return (vxlan_xmit_one(skb, dev, vxlan->gaddr)); ++ ++ if (vxlan->repl_type == VXLAN_REPLICATION_SERVICE_NODE) { ++ /* no group address defined, try service nodes */ ++ /* TBD: we should do some flow hash to spread, and also ++ * consider bfd status. for now just pick the first one ++ */ ++ return (vxlan_xmit_one(skb, dev, vxlan->repl_nodes[0])); ++ } ++ else if (vxlan->repl_type == VXLAN_REPLICATION_SELF) { ++ /* self replication so replicate packets to each of the peer nodes ++ * in the list ++ */ ++ for (i = 0; i < MAX_VXLAN_REPLICATION_NODE_ADDRS; i++) { ++ /* XXX */ ++ netdev_dbg(dev, " repl node: %d, addr: %x\n", ++ i, vxlan->repl_nodes[i]); ++ if (vxlan->repl_nodes[i] == 0) ++ break; ++ nskb = skb_clone(skb, GFP_ATOMIC); ++ ret = vxlan_xmit_one(nskb, dev, vxlan->repl_nodes[i]); ++ } ++ goto tx_free; ++ } ++ else ++ goto drop; ++ } ++ ++ f = vxlan_find_mac(vxlan, eth->h_dest); ++ if (f) ++ return (vxlan_xmit_one(skb, dev, f->remote_ip)); ++ else { ++ if (vxlan->repl_type == VXLAN_REPLICATION_SERVICE_NODE) ++ return (vxlan_xmit_one(skb, dev, vxlan->repl_nodes[0])); ++ else if (vxlan->repl_type == VXLAN_REPLICATION_SELF) { ++ /* self replication so replicate packets to each of the peer nodes ++ * in the list. If list is empty, send to gaddr ++ */ ++ for (i = 0; i < MAX_VXLAN_REPLICATION_NODE_ADDRS; i++) { ++ if (vxlan->repl_nodes[i] == 0) ++ break; ++ nskb = skb_clone(skb, GFP_ATOMIC); ++ ret = vxlan_xmit_one(nskb, dev, vxlan->repl_nodes[i]); ++ } ++ goto tx_free; ++ } ++ else { ++ /* use service node first for unknown unicast, if not xmit to gaddr */ ++ return (vxlan_xmit_one(skb, dev, vxlan->gaddr)); ++ } ++ } ++drop: ++ dev->stats.tx_dropped++; ++ ++tx_free: ++ dev_kfree_skb(skb); ++ return ret; ++} ++ ++/* Walk the forwarding table and purge stale entries */ ++static void vxlan_cleanup(unsigned long arg) ++{ ++ struct vxlan_dev *vxlan = (struct vxlan_dev *) arg; ++ unsigned long next_timer = jiffies + FDB_AGE_INTERVAL; ++ unsigned int h; ++ ++ if (!netif_running(vxlan->dev)) ++ return; ++ ++ spin_lock_bh(&vxlan->hash_lock); ++ for (h = 0; h < FDB_HASH_SIZE; ++h) { ++ struct hlist_node *p, *n; ++ hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { ++ struct vxlan_fdb *f ++ = container_of(p, struct vxlan_fdb, hlist); ++ unsigned long timeout; ++ ++ if (f->state & NUD_PERMANENT) ++ continue; ++ ++ timeout = f->used + vxlan->age_interval * HZ; ++ if (time_before_eq(timeout, jiffies)) { ++ netdev_dbg(vxlan->dev, ++ "garbage collect %pM\n", ++ f->eth_addr); ++ f->state = NUD_STALE; ++ vxlan_fdb_destroy(vxlan, f); ++ } else if (time_before(timeout, next_timer)) ++ next_timer = timeout; ++ } ++ } ++ spin_unlock_bh(&vxlan->hash_lock); ++ ++ mod_timer(&vxlan->age_timer, next_timer); ++} ++ ++/* Setup stats when device is created */ ++static int vxlan_init(struct net_device *dev) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ ++ vxlan->stats = alloc_percpu(struct vxlan_stats); ++ if (!vxlan->stats) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static void vxlan_uninit(struct net_device *dev) ++{ ++ port_uninit_ethtool_stats(dev); ++} ++ ++/* Start ageing timer and join group when device is brought up */ ++static int vxlan_open(struct net_device *dev) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ int err; ++ ++ if (vxlan->gaddr) { ++ err = vxlan_join_group(dev); ++ if (err) ++ return err; ++ } ++ ++ if (vxlan->age_interval) ++ mod_timer(&vxlan->age_timer, jiffies + FDB_AGE_INTERVAL); ++ ++ return 0; ++} ++ ++/* Purge the forwarding table */ ++static void vxlan_flush(struct vxlan_dev *vxlan) ++{ ++ unsigned h; ++ ++ spin_lock_bh(&vxlan->hash_lock); ++ for (h = 0; h < FDB_HASH_SIZE; ++h) { ++ struct hlist_node *p, *n; ++ hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { ++ struct vxlan_fdb *f ++ = container_of(p, struct vxlan_fdb, hlist); ++ vxlan_fdb_destroy(vxlan, f); ++ } ++ } ++ spin_unlock_bh(&vxlan->hash_lock); ++} ++ ++/* Cleanup timer and forwarding table on shutdown */ ++static int vxlan_stop(struct net_device *dev) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ ++ if (vxlan->gaddr) ++ vxlan_leave_group(dev); ++ ++ del_timer_sync(&vxlan->age_timer); ++ ++ vxlan_flush(vxlan); ++ ++ return 0; ++} ++ ++static void vxlan_dev_get_hw_stats64(struct net_device *dev, ++ struct rtnl_link_stats64 *stats, int count) ++{ ++ u64 *hw_stats; ++ struct ethtool_stats estats = { 0, }; ++ ++ hw_stats = kmalloc(count * sizeof(u64), GFP_ATOMIC); ++ if (!hw_stats) ++ return; ++ ++ estats.n_stats = count; ++ port_get_ethtool_stats(dev, &estats, hw_stats); ++ ++ stats->rx_bytes = hw_stats[0]; ++ stats->rx_packets = hw_stats[1]; ++ stats->tx_bytes = hw_stats[2]; ++ stats->tx_packets = hw_stats[3]; ++ kfree(hw_stats); ++} ++ ++/* Merge per-cpu statistics */ ++static struct rtnl_link_stats64 *vxlan_stats64(struct net_device *dev, ++ struct rtnl_link_stats64 *stats) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ struct vxlan_stats tmp, sum = { 0 }; ++ unsigned int cpu; ++ int count; ++ ++ count = port_get_sset_count(dev, ETH_SS_STATS); ++ if (count > 0) ++ vxlan_dev_get_hw_stats64(dev, stats, count); ++ ++ for_each_possible_cpu(cpu) { ++ unsigned int start; ++ const struct vxlan_stats *stats ++ = per_cpu_ptr(vxlan->stats, cpu); ++ ++ do { ++ start = u64_stats_fetch_begin_bh(&stats->syncp); ++ memcpy(&tmp, stats, sizeof(tmp)); ++ } while (u64_stats_fetch_retry_bh(&stats->syncp, start)); ++ ++ sum.tx_bytes += tmp.tx_bytes; ++ sum.tx_packets += tmp.tx_packets; ++ } ++ ++ stats->tx_bytes += sum.tx_bytes; ++ stats->tx_packets += sum.tx_packets; ++ ++ stats->multicast = dev->stats.multicast; ++ stats->rx_length_errors = dev->stats.rx_length_errors; ++ stats->rx_frame_errors = dev->stats.rx_frame_errors; ++ stats->rx_errors = dev->stats.rx_errors; ++ ++ stats->tx_dropped = dev->stats.tx_dropped; ++ stats->tx_carrier_errors = dev->stats.tx_carrier_errors; ++ stats->tx_aborted_errors = dev->stats.tx_aborted_errors; ++ stats->collisions = dev->stats.collisions; ++ stats->tx_errors = dev->stats.tx_errors; ++ ++ return stats; ++} ++ ++/* Stub, nothing needs to be done. */ ++static void vxlan_set_multicast_list(struct net_device *dev) ++{ ++} ++ ++static int vxlan_change_mtu(struct net_device *dev, int new_mtu) ++{ ++#define VXLAN_MAX_MTU 9000 ++ ++ if (new_mtu < 68 || new_mtu > VXLAN_MAX_MTU) ++ return -EINVAL; ++ ++ dev->mtu = new_mtu; ++ return 0; ++} ++ ++static int vxlan_change_proto_down(struct net_device *dev, bool proto_down) ++{ ++ if (proto_down) ++ netif_carrier_off(dev); ++ else ++ netif_carrier_on(dev); ++ dev->proto_down = proto_down; ++ return 0; ++} ++ ++static const struct net_device_ops vxlan_netdev_ops = { ++ .ndo_init = vxlan_init, ++ .ndo_uninit = vxlan_uninit, ++ .ndo_open = vxlan_open, ++ .ndo_stop = vxlan_stop, ++ .ndo_start_xmit = vxlan_xmit, ++ .ndo_get_stats64 = vxlan_stats64, ++ .ndo_set_rx_mode = vxlan_set_multicast_list, ++ .ndo_change_mtu = vxlan_change_mtu, ++ .ndo_validate_addr = eth_validate_addr, ++ .ndo_set_mac_address = eth_mac_addr, ++ .ndo_fdb_add = vxlan_fdb_add, ++ .ndo_fdb_del = vxlan_fdb_delete, ++ .ndo_fdb_dump = vxlan_fdb_dump, ++ .ndo_change_proto_down = vxlan_change_proto_down, ++}; ++ ++/* Info for udev, that this is a virtual tunnel endpoint */ ++static struct device_type vxlan_type = { ++ .name = "vxlan", ++}; ++ ++static void vxlan_free(struct net_device *dev) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ ++ free_percpu(vxlan->stats); ++ free_netdev(dev); ++} ++ ++/* Initialize the device structure. */ ++static void vxlan_setup(struct net_device *dev) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ unsigned h; ++ int low, high; ++ ++ eth_hw_addr_random(dev); ++ ether_setup(dev); ++ dev->hard_header_len = ETH_HLEN + VXLAN_HEADROOM; ++ ++ dev->netdev_ops = &vxlan_netdev_ops; ++ dev->destructor = vxlan_free; ++ SET_NETDEV_DEVTYPE(dev, &vxlan_type); ++ ++ dev->tx_queue_len = 0; ++ dev->features |= NETIF_F_LLTX; ++ dev->features |= NETIF_F_NETNS_LOCAL; ++ dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; ++ ++ spin_lock_init(&vxlan->hash_lock); ++ ++ init_timer_deferrable(&vxlan->age_timer); ++ vxlan->age_timer.function = vxlan_cleanup; ++ vxlan->age_timer.data = (unsigned long) vxlan; ++ ++ inet_get_local_port_range(&low, &high); ++ vxlan->port_min = low; ++ vxlan->port_max = high; ++ ++ vxlan->dev = dev; ++ ++ for (h = 0; h < FDB_HASH_SIZE; ++h) ++ INIT_HLIST_HEAD(&vxlan->fdb_head[h]); ++} ++ ++static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { ++ [IFLA_VXLAN_ID] = { .type = NLA_U32 }, ++ [IFLA_VXLAN_GROUP] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, ++ [IFLA_VXLAN_LINK] = { .type = NLA_U32 }, ++ [IFLA_VXLAN_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, ++ [IFLA_VXLAN_TOS] = { .type = NLA_U8 }, ++ [IFLA_VXLAN_TTL] = { .type = NLA_U8 }, ++ [IFLA_VXLAN_LEARNING] = { .type = NLA_U8 }, ++ [IFLA_VXLAN_AGEING] = { .type = NLA_U32 }, ++ [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 }, ++ [IFLA_VXLAN_PORT_RANGE] = { .len = sizeof(struct ifla_vxlan_port_range) }, ++ [IFLA_VXLAN_PROXY] = { .type = NLA_U8 }, ++ [IFLA_VXLAN_RSC] = { .type = NLA_U8 }, ++ [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 }, ++ [IFLA_VXLAN_L3MISS] = { .type = NLA_U8 }, ++ [IFLA_VXLAN_PORT] = { .type = NLA_U16 }, ++ [IFLA_VXLAN_UDP_CSUM] = { .type = NLA_U8 }, ++ [IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 }, ++ [IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 }, ++ [IFLA_VXLAN_REMCSUM_TX] = { .type = NLA_U8 }, ++ [IFLA_VXLAN_REMCSUM_RX] = { .type = NLA_U8 }, ++ [IFLA_VXLAN_GBP] = { .type = NLA_FLAG, }, ++ [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG }, ++ [IFLA_VXLAN_REPLICATION_NODE] = { .len = sizeof(struct ifla_vxlan_repl_node_addrs) }, ++ [IFLA_VXLAN_REPLICATION_TYPE] = { .type = NLA_U8 }, ++}; ++ ++static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) ++{ ++ if (tb[IFLA_ADDRESS]) { ++ if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) { ++ pr_debug("invalid link address (not ethernet)\n"); ++ return -EINVAL; ++ } ++ ++ if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) { ++ pr_debug("invalid all zero ethernet address\n"); ++ return -EADDRNOTAVAIL; ++ } ++ } ++ ++ if (!data) ++ return -EINVAL; ++ ++ if (data[IFLA_VXLAN_ID]) { ++ __u32 id = nla_get_u32(data[IFLA_VXLAN_ID]); ++ if (id >= VXLAN_VID_MASK) ++ return -ERANGE; ++ } ++ ++ /* XXX ++ if (data[IFLA_VXLAN_GROUP]) { ++ __be32 gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]); ++ if (!IN_MULTICAST(ntohl(gaddr))) { ++ pr_debug("group address is not IPv4 multicast\n"); ++ return -EADDRNOTAVAIL; ++ } ++ } ++ */ ++ ++ if (data[IFLA_VXLAN_PORT_RANGE]) { ++ const struct ifla_vxlan_port_range *p ++ = nla_data(data[IFLA_VXLAN_PORT_RANGE]); ++ ++ if (ntohs(p->high) < ntohs(p->low)) { ++ pr_debug("port range %u .. %u not valid\n", ++ ntohs(p->low), ntohs(p->high)); ++ return -EINVAL; ++ } ++ } ++ if (data[IFLA_VXLAN_REPLICATION_TYPE]) { ++ u8 repl_type = nla_get_u8(data[IFLA_VXLAN_REPLICATION_TYPE]); ++ if ((repl_type != VXLAN_REPLICATION_SERVICE_NODE) ++ && (repl_type != VXLAN_REPLICATION_SELF) ++ && (repl_type != VXLAN_REPLICATION_NONE)) { ++ pr_debug("invalid replication type\n"); ++ return -EINVAL; ++ } ++ } ++#if 0 ++ if (data[IFLA_VXLAN_REPLICATION_NODE]) { ++ const struct ifla_vxlan_repl_node_addrs *p ++ = nla_data(data[IFLA_VXLAN_REPLICATION_NODE]); ++ /* TBD: check for mcast and bcast */ ++ } ++#endif ++ return 0; ++} ++ ++static int vxlan_newlink(struct net *net, struct net_device *dev, ++ struct nlattr *tb[], struct nlattr *data[]) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ __u32 vni; ++ int err; ++ ++ if (!data[IFLA_VXLAN_ID]) ++ return -EINVAL; ++ ++ vni = nla_get_u32(data[IFLA_VXLAN_ID]); ++ if (vxlan_find_vni(net, vni)) { ++ pr_info("duplicate VNI %u\n", vni); ++ return -EEXIST; ++ } ++ vxlan->vni = vni; ++ ++ if (data[IFLA_VXLAN_GROUP]) { ++ __be32 addr = nla_get_be32(data[IFLA_VXLAN_GROUP]); ++ if (IN_MULTICAST(ntohl(addr))) ++ vxlan->gaddr = addr; ++ else ++ if (!vxlan_add_repl_node(vxlan, addr)) ++ return -EINVAL; ++ } ++ ++ if (data[IFLA_VXLAN_LOCAL]) ++ vxlan->saddr = nla_get_be32(data[IFLA_VXLAN_LOCAL]); ++ ++ if (data[IFLA_VXLAN_LINK] && ++ (vxlan->link = nla_get_u32(data[IFLA_VXLAN_LINK]))) { ++ struct net_device *lowerdev ++ = __dev_get_by_index(net, vxlan->link); ++ ++ if (!lowerdev) { ++ pr_info("ifindex %d does not exist\n", vxlan->link); ++ return -ENODEV; ++ } ++ ++ if (!tb[IFLA_MTU]) ++ dev->mtu = lowerdev->mtu - VXLAN_HEADROOM; ++ } ++ ++ if (data[IFLA_VXLAN_TOS]) ++ vxlan->tos = nla_get_u8(data[IFLA_VXLAN_TOS]); ++ ++ if (!data[IFLA_VXLAN_LEARNING] || nla_get_u8(data[IFLA_VXLAN_LEARNING])) ++ vxlan->learn = true; ++ ++ if (data[IFLA_VXLAN_AGEING]) ++ vxlan->age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]); ++ else ++ vxlan->age_interval = FDB_AGE_DEFAULT; ++ ++ if (data[IFLA_VXLAN_LIMIT]) ++ vxlan->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]); ++ ++ if (data[IFLA_VXLAN_PORT_RANGE]) { ++ const struct ifla_vxlan_port_range *p ++ = nla_data(data[IFLA_VXLAN_PORT_RANGE]); ++ vxlan->port_min = ntohs(p->low); ++ vxlan->port_max = ntohs(p->high); ++ } ++ ++ if (data[IFLA_VXLAN_PORT]) ++ vxlan_port = ntohs(nla_get_be16(data[IFLA_VXLAN_PORT])); ++ ++ if (data[IFLA_VXLAN_REPLICATION_TYPE] && data[IFLA_VXLAN_REPLICATION_NODE]) { ++ const struct ifla_vxlan_repl_node_addrs *p ++ = nla_data(data[IFLA_VXLAN_REPLICATION_NODE]); ++ ++ memcpy(vxlan->repl_nodes, p, sizeof(*p)); ++ vxlan->repl_type = nla_get_u8(data[IFLA_VXLAN_REPLICATION_TYPE]); ++ } else ++ vxlan->repl_type = VXLAN_REPLICATION_NONE; ++ ++ err = register_netdevice(dev); ++ if (!err) { ++ hlist_add_head_rcu(&vxlan->hlist, vni_head(net, vxlan->vni)); ++ port_init_ethtool_stats(dev); ++ } ++ ++ return err; ++} ++ ++static void vxlan_dellink(struct net_device *dev, struct list_head *head) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ ++ vxlan_stop(dev); ++ ++ hlist_del_rcu(&vxlan->hlist); ++ ++ unregister_netdevice_queue(dev, head); ++} ++ ++static size_t vxlan_get_size(const struct net_device *dev) ++{ ++ ++ return nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_ID */ ++ nla_total_size(sizeof(__be32)) +/* IFLA_VXLAN_GROUP */ ++ nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LINK */ ++ nla_total_size(sizeof(__be32))+ /* IFLA_VXLAN_LOCAL */ ++ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL */ ++ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TOS */ ++ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LEARNING */ ++ nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */ ++ nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */ ++ nla_total_size(sizeof(struct ifla_vxlan_port_range)) + ++ nla_total_size(sizeof(__be16)) + /* IFLA_VXLAN_PORT */ ++ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_CSUM */ ++ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_TX */ ++ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_RX */ ++ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_TX */ ++ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_RX */ ++ nla_total_size(sizeof(struct ifla_vxlan_repl_node_addrs)) + ++ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REPLICATION_TYPE */ ++ 0; ++} ++ ++static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) ++{ ++ const struct vxlan_dev *vxlan = netdev_priv(dev); ++ struct ifla_vxlan_port_range ports = { ++ .low = htons(vxlan->port_min), ++ .high = htons(vxlan->port_max), ++ }; ++ struct ifla_vxlan_repl_node_addrs repladdrs; ++ ++ if (nla_put_u32(skb, IFLA_VXLAN_ID, vxlan->vni)) ++ goto nla_put_failure; ++ ++ if (vxlan->gaddr && nla_put_be32(skb, IFLA_VXLAN_GROUP, vxlan->gaddr)) ++ goto nla_put_failure; ++ ++ if (vxlan->repl_nodes[0] && ++ nla_put_be32(skb, IFLA_VXLAN_GROUP, vxlan->repl_nodes[0])) ++ goto nla_put_failure; ++ ++ if (vxlan->link && nla_put_u32(skb, IFLA_VXLAN_LINK, vxlan->link)) ++ goto nla_put_failure; ++ ++ if (vxlan->saddr && nla_put_be32(skb, IFLA_VXLAN_LOCAL, vxlan->saddr)) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->ttl) || ++ nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->tos) || ++ nla_put_u8(skb, IFLA_VXLAN_LEARNING, vxlan->learn) || ++ nla_put_u8(skb, IFLA_VXLAN_PROXY, 0) || ++ nla_put_u8(skb, IFLA_VXLAN_RSC, 0) || ++ nla_put_u8(skb, IFLA_VXLAN_L2MISS, 0) || ++ nla_put_u8(skb, IFLA_VXLAN_L3MISS, 0) || ++ nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->age_interval) || ++ nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax) || ++ nla_put_be16(skb, IFLA_VXLAN_PORT, htons(vxlan_port)) || ++ nla_put_u8(skb, IFLA_VXLAN_UDP_CSUM, 0) || ++ nla_put_u8(skb, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, 0) || ++ nla_put_u8(skb, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, 0) || ++ nla_put_u8(skb, IFLA_VXLAN_REMCSUM_TX, 0) || ++ nla_put_u8(skb, IFLA_VXLAN_REMCSUM_RX, 0)) ++ goto nla_put_failure; ++ ++ if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports)) ++ goto nla_put_failure; ++ ++ if ((vxlan->repl_type != VXLAN_REPLICATION_NONE) && vxlan->repl_nodes[0]) { ++ if (nla_put_u8(skb, IFLA_VXLAN_REPLICATION_TYPE, vxlan->repl_type)) ++ goto nla_put_failure; ++ ++ memcpy(&repladdrs, vxlan->repl_nodes, sizeof(repladdrs)); ++ if (nla_put(skb, IFLA_VXLAN_REPLICATION_NODE, sizeof(repladdrs), &repladdrs)) ++ goto nla_put_failure; ++ } ++ ++ return 0; ++ ++nla_put_failure: ++ return -EMSGSIZE; ++} ++ ++static int vxlan_changelink(struct net_device *dev, ++ struct nlattr *tb[], struct nlattr *data[]) ++{ ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ ++ if (data[IFLA_VXLAN_ID] || data[IFLA_VXLAN_LINK]) { ++ pr_err("cannot change VNI or phys dev \n"); ++ return -EINVAL; ++ } ++ ++ if (data[IFLA_VXLAN_GROUP]) { ++ __be32 gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]); ++ if (IN_MULTICAST(ntohl(gaddr))) ++ vxlan->gaddr = gaddr; ++ else ++ if (!vxlan_add_repl_node(vxlan, gaddr)) ++ return -EINVAL; ++ } ++ ++ if (data[IFLA_VXLAN_LOCAL]) ++ vxlan->saddr = nla_get_be32(data[IFLA_VXLAN_LOCAL]); ++ ++ if (data[IFLA_VXLAN_TOS]) ++ vxlan->tos = nla_get_u8(data[IFLA_VXLAN_TOS]); ++ ++ if (data[IFLA_VXLAN_LEARNING]) { ++ if (nla_get_u8(data[IFLA_VXLAN_LEARNING])) ++ vxlan->learn = true; ++ else ++ vxlan->learn = false; ++ } ++ ++ if (data[IFLA_VXLAN_AGEING]) ++ vxlan->age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]); ++ ++ if (data[IFLA_VXLAN_LIMIT]) ++ vxlan->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]); ++ ++ if (data[IFLA_VXLAN_PORT_RANGE]) { ++ const struct ifla_vxlan_port_range *p ++ = nla_data(data[IFLA_VXLAN_PORT_RANGE]); ++ vxlan->port_min = ntohs(p->low); ++ vxlan->port_max = ntohs(p->high); ++ } ++ ++ if (data[IFLA_VXLAN_REPLICATION_TYPE] && data[IFLA_VXLAN_REPLICATION_NODE]) { ++ const struct ifla_vxlan_repl_node_addrs *p ++ = nla_data(data[IFLA_VXLAN_REPLICATION_NODE]); ++ ++ memcpy(vxlan->repl_nodes, p, sizeof(*p)); ++ vxlan->repl_type = nla_get_u8(data[IFLA_VXLAN_REPLICATION_TYPE]); ++ } ++ ++ /* call notifier chains and send link msg */ ++ netdev_state_change(dev); ++ return 0; ++} ++ ++static struct rtnl_link_ops vxlan_link_ops __read_mostly = { ++ .kind = "vxlan", ++ .maxtype = IFLA_VXLAN_MAX, ++ .policy = vxlan_policy, ++ .priv_size = sizeof(struct vxlan_dev), ++ .setup = vxlan_setup, ++ .validate = vxlan_validate, ++ .newlink = vxlan_newlink, ++ .changelink = vxlan_changelink, ++ .dellink = vxlan_dellink, ++ .get_size = vxlan_get_size, ++ .fill_info = vxlan_fill_info, ++}; ++ ++static __net_init int vxlan_init_net(struct net *net) ++{ ++ struct vxlan_net *vn = net_generic(net, vxlan_net_id); ++ struct sock *sk; ++ struct sockaddr_in vxlan_addr = { ++ .sin_family = AF_INET, ++ .sin_addr.s_addr = htonl(INADDR_ANY), ++ }; ++ int rc; ++ unsigned h; ++ ++ /* Create UDP socket for encapsulation receive. */ ++ rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &vn->sock); ++ if (rc < 0) { ++ pr_debug("UDP socket create failed\n"); ++ return rc; ++ } ++ /* Put in proper namespace */ ++ sk = vn->sock->sk; ++ sk_change_net(sk, net); ++ ++ vxlan_addr.sin_port = htons(vxlan_port); ++ ++ rc = kernel_bind(vn->sock, (struct sockaddr *) &vxlan_addr, ++ sizeof(vxlan_addr)); ++ if (rc < 0) { ++ pr_debug("bind for UDP socket %pI4:%u (%d)\n", ++ &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc); ++ sk_release_kernel(sk); ++ vn->sock = NULL; ++ return rc; ++ } ++ ++ /* Disable multicast loopback */ ++ inet_sk(sk)->mc_loop = 0; ++ ++ /* Mark socket as an encapsulation socket. */ ++ udp_sk(sk)->encap_type = 1; ++ udp_sk(sk)->encap_rcv = vxlan_udp_encap_recv; ++// udp_encap_enable(); ++ ++ for (h = 0; h < VNI_HASH_SIZE; ++h) ++ INIT_HLIST_HEAD(&vn->vni_list[h]); ++ ++ return 0; ++} ++ ++static __net_exit void vxlan_exit_net(struct net *net) ++{ ++ struct vxlan_net *vn = net_generic(net, vxlan_net_id); ++ ++ if (vn->sock) { ++ sk_release_kernel(vn->sock->sk); ++ vn->sock = NULL; ++ } ++} ++ ++static struct pernet_operations vxlan_net_ops = { ++ .init = vxlan_init_net, ++ .exit = vxlan_exit_net, ++ .id = &vxlan_net_id, ++ .size = sizeof(struct vxlan_net), ++}; ++ ++static int vxlan_netdev_event(struct notifier_block *this, ++ unsigned long event, ++ void *ptr) ++{ ++ struct net_device *dev = (struct net_device *)ptr; ++ struct vxlan_dev *vxlan; ++ ++ if (dev->netdev_ops != &vxlan_netdev_ops) ++ return NOTIFY_DONE; ++ ++ vxlan = netdev_priv(dev); ++ switch(event) { ++ case NETDEV_CHANGE: ++ if (netif_running(dev) && !netif_oper_up(dev)) ++ vxlan_flush(vxlan); ++ break; ++ default: ++ break; ++ } ++ ++ return NOTIFY_DONE; ++} ++ ++static int __init vxlan_init_module(void) ++{ ++ int rc; ++ ++ get_random_bytes(&vxlan_salt, sizeof(vxlan_salt)); ++ ++ rc = register_pernet_device(&vxlan_net_ops); ++ if (rc) ++ goto out1; ++ ++ rc = rtnl_link_register(&vxlan_link_ops); ++ if (rc) ++ goto out2; ++ ++ rc = register_netdevice_notifier(&vxlan_netdev_notifier); ++ if (rc) ++ goto out3; ++ ++ return 0; ++ ++out3: ++ rtnl_link_unregister(&vxlan_link_ops); ++out2: ++ unregister_pernet_device(&vxlan_net_ops); ++out1: ++ return rc; ++} ++module_init(vxlan_init_module); ++ ++static void __exit vxlan_cleanup_module(void) ++{ ++ unregister_netdevice_notifier(&vxlan_netdev_notifier); ++ rtnl_link_unregister(&vxlan_link_ops); ++ unregister_pernet_device(&vxlan_net_ops); ++} ++module_exit(vxlan_cleanup_module); ++ ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(VXLAN_VERSION); ++MODULE_AUTHOR("Stephen Hemminger "); ++MODULE_ALIAS_RTNL_LINK("vxlan"); +diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c +index 7cbd7d2..c9335ea 100644 +--- a/drivers/net/wimax/i2400m/fw.c ++++ b/drivers/net/wimax/i2400m/fw.c +@@ -1582,11 +1582,8 @@ int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags) + } + d_printf(1, dev, "trying firmware %s (%d)\n", fw_name, itr); + ret = request_firmware(&fw, fw_name, dev); +- if (ret < 0) { +- dev_err(dev, "fw %s: cannot load file: %d\n", +- fw_name, ret); ++ if (ret) + continue; +- } + i2400m->fw_name = fw_name; + ret = i2400m_fw_bootstrap(i2400m, fw, flags); + release_firmware(fw); +@@ -1629,8 +1626,6 @@ void i2400m_fw_cache(struct i2400m *i2400m) + kref_init(&i2400m_fw->kref); + result = request_firmware(&i2400m_fw->fw, i2400m->fw_name, dev); + if (result < 0) { +- dev_err(dev, "firmware %s: failed to cache: %d\n", +- i2400m->fw_name, result); + kfree(i2400m_fw); + i2400m_fw = (void *) ~0; + } else +diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c +index 4045e5a..5cdee9e 100644 +--- a/drivers/net/wireless/at76c50x-usb.c ++++ b/drivers/net/wireless/at76c50x-usb.c +@@ -1584,14 +1584,8 @@ static struct fwentry *at76_load_firmware(struct usb_device *udev, + + at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname); + ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev); +- if (ret < 0) { +- dev_printk(KERN_ERR, &udev->dev, "firmware %s not found!\n", +- fwe->fwname); +- dev_printk(KERN_ERR, &udev->dev, +- "you may need to download the firmware from " +- "http://developer.berlios.de/projects/at76c503a/\n"); ++ if (ret) + goto exit; +- } + + at76_dbg(DBG_FW, "got it."); + fwh = (struct at76_fw_header *)(fwe->fw->data); +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index 77c8ded..a0b0650 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -1030,11 +1030,8 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info) + /* Request firmware */ + ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name, + &hif_dev->udev->dev); +- if (ret) { +- dev_err(&hif_dev->udev->dev, +- "ath9k_htc: Firmware - %s not found\n", hif_dev->fw_name); ++ if (ret) + goto err_fw_req; +- } + + /* Download firmware */ + ret = ath9k_hif_usb_download_fw(hif_dev, drv_info); +diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c +index 5538596..88dc0e4 100644 +--- a/drivers/net/wireless/ath/carl9170/usb.c ++++ b/drivers/net/wireless/ath/carl9170/usb.c +@@ -1025,7 +1025,6 @@ static void carl9170_usb_firmware_step2(const struct firmware *fw, + return; + } + +- dev_err(&ar->udev->dev, "firmware not found.\n"); + carl9170_usb_firmware_failed(ar); + } + +diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c +index 7e45ca2..0bbc412 100644 +--- a/drivers/net/wireless/atmel.c ++++ b/drivers/net/wireless/atmel.c +@@ -3937,12 +3937,8 @@ static int reset_atmel_card(struct net_device *dev) + strcpy(priv->firmware_id, "atmel_at76c502.bin"); + } + err = request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev); +- if (err != 0) { +- printk(KERN_ALERT +- "%s: firmware %s is missing, cannot continue.\n", +- dev->name, priv->firmware_id); ++ if (err != 0) + return err; +- } + } else { + int fw_index = 0; + int success = 0; +diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c +index b0c2801..3ba1f80 100644 +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -2131,18 +2131,8 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, + return -ENOSYS; + } + err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); +- if (err == -ENOENT) { +- snprintf(ctx->errors[ctx->req_type], +- sizeof(ctx->errors[ctx->req_type]), +- "Firmware file \"%s\" not found\n", ctx->fwname); +- return err; +- } else if (err) { +- snprintf(ctx->errors[ctx->req_type], +- sizeof(ctx->errors[ctx->req_type]), +- "Firmware file \"%s\" request failed (err=%d)\n", +- ctx->fwname, err); ++ if (err) + return err; +- } + if (blob->size < sizeof(struct b43_fw_header)) + goto err_format; + hdr = (struct b43_fw_header *)(blob->data); +diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c +index 71195cb..f5e55b4 100644 +--- a/drivers/net/wireless/b43legacy/main.c ++++ b/drivers/net/wireless/b43legacy/main.c +@@ -1527,11 +1527,8 @@ static int do_request_fw(struct b43legacy_wldev *dev, + "b43legacy%s/%s.fw", + modparam_fwpostfix, name); + err = request_firmware(fw, path, dev->dev->dev); +- if (err) { +- b43legacyerr(dev->wl, "Firmware file \"%s\" not found " +- "or load failed.\n", path); ++ if (err) + return err; +- } + if ((*fw)->size < sizeof(struct b43legacy_fw_header)) + goto err_format; + hdr = (struct b43legacy_fw_header *)((*fw)->data); +diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig +index 2069fc8..d5784ee 100644 +--- a/drivers/net/wireless/brcm80211/Kconfig ++++ b/drivers/net/wireless/brcm80211/Kconfig +@@ -5,7 +5,6 @@ config BRCMSMAC + tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" + depends on PCI + depends on MAC80211 +- depends on BCMA=n + select BRCMUTIL + select FW_LOADER + select CRC_CCITT +diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +index 313b8bf..da75db0 100644 +--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +@@ -3413,10 +3413,8 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus) + bus->fw_name = BCM4329_FW_NAME; + ret = request_firmware(&bus->firmware, bus->fw_name, + &bus->sdiodev->func[2]->dev); +- if (ret) { +- brcmf_dbg(ERROR, "Fail to request firmware %d\n", ret); ++ if (ret) + return ret; +- } + bus->fw_ptr = 0; + + memptr = memblock = kmalloc(MEMBLOCK + BRCMF_SDALIGN, GFP_ATOMIC); +@@ -3511,10 +3509,8 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus) + bus->nv_name = BCM4329_NV_NAME; + ret = request_firmware(&bus->firmware, bus->nv_name, + &bus->sdiodev->func[2]->dev); +- if (ret) { +- brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret); ++ if (ret) + return ret; +- } + bus->fw_ptr = 0; + + memblock = kmalloc(MEMBLOCK, GFP_ATOMIC); +diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +index 78c16eb..d2861fc 100644 +--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +@@ -785,19 +785,13 @@ static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev) + sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i], + UCODE_LOADER_API_VER); + status = request_firmware(&wl->fw.fw_bin[i], fw_name, device); +- if (status) { +- wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n", +- KBUILD_MODNAME, fw_name); ++ if (status) + return status; +- } + sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i], + UCODE_LOADER_API_VER); + status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device); +- if (status) { +- wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n", +- KBUILD_MODNAME, fw_name); ++ if (status) + return status; +- } + wl->fw.hdr_num_entries[i] = + wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr)); + } +diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c +index 10862d4..eeb8bed 100644 +--- a/drivers/net/wireless/ipw2x00/ipw2100.c ++++ b/drivers/net/wireless/ipw2x00/ipw2100.c +@@ -1900,14 +1900,6 @@ static void ipw2100_down(struct ipw2100_priv *priv) + netif_stop_queue(priv->net_dev); + } + +-/* Called by register_netdev() */ +-static int ipw2100_net_init(struct net_device *dev) +-{ +- struct ipw2100_priv *priv = libipw_priv(dev); +- +- return ipw2100_up(priv, 1); +-} +- + static int ipw2100_wdev_init(struct net_device *dev) + { + struct ipw2100_priv *priv = libipw_priv(dev); +@@ -1960,10 +1952,8 @@ static int ipw2100_wdev_init(struct net_device *dev) + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); + + set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); +- if (wiphy_register(wdev->wiphy)) { +- ipw2100_down(priv); ++ if (wiphy_register(wdev->wiphy)) + return -EIO; +- } + return 0; + } + +@@ -6088,7 +6078,6 @@ static const struct net_device_ops ipw2100_netdev_ops = { + .ndo_stop = ipw2100_close, + .ndo_start_xmit = libipw_xmit, + .ndo_change_mtu = libipw_change_mtu, +- .ndo_init = ipw2100_net_init, + .ndo_tx_timeout = ipw2100_tx_timeout, + .ndo_set_mac_address = ipw2100_set_address, + .ndo_validate_addr = eth_validate_addr, +@@ -6340,27 +6329,27 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + printk(KERN_INFO DRV_NAME + ": Detected Intel PRO/Wireless 2100 Network Connection\n"); + ++ err = ipw2100_up(priv, 1); ++ if (err) ++ goto fail; ++ ++ err = ipw2100_wdev_init(dev); ++ if (err) ++ goto fail; ++ registered = 1; ++ + /* Bring up the interface. Pre 0.46, after we registered the + * network device we would call ipw2100_up. This introduced a race + * condition with newer hotplug configurations (network was coming + * up and making calls before the device was initialized). +- * +- * If we called ipw2100_up before we registered the device, then the +- * device name wasn't registered. So, we instead use the net_dev->init +- * member to call a function that then just turns and calls ipw2100_up. +- * net_dev->init is called after name allocation but before the +- * notifier chain is called */ ++ */ + err = register_netdev(dev); + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling register_netdev.\n"); + goto fail; + } +- registered = 1; +- +- err = ipw2100_wdev_init(dev); +- if (err) +- goto fail; ++ registered = 2; + + mutex_lock(&priv->action_mutex); + +@@ -6399,13 +6388,16 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + + fail_unlock: + mutex_unlock(&priv->action_mutex); +- wiphy_unregister(priv->ieee->wdev.wiphy); +- kfree(priv->ieee->bg_band.channels); + fail: + if (dev) { +- if (registered) ++ if (registered >= 2) + unregister_netdev(dev); + ++ if (registered) { ++ wiphy_unregister(priv->ieee->wdev.wiphy); ++ kfree(priv->ieee->bg_band.channels); ++ } ++ + ipw2100_hw_stop_adapter(priv); + + ipw2100_disable_interrupts(priv); +@@ -8519,12 +8511,8 @@ static int ipw2100_get_firmware(struct ipw2100_priv *priv, + + rc = request_firmware(&fw->fw_entry, fw_name, &priv->pci_dev->dev); + +- if (rc < 0) { +- printk(KERN_ERR DRV_NAME ": " +- "%s: Firmware '%s' not available or load failed.\n", +- priv->net_dev->name, fw_name); ++ if (rc) + return rc; +- } + IPW_DEBUG_INFO("firmware data %p size %zd\n", fw->fw_entry->data, + fw->fw_entry->size); + +diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c +index da567f0..8b647a3 100644 +--- a/drivers/net/wireless/ipw2x00/ipw2200.c ++++ b/drivers/net/wireless/ipw2x00/ipw2200.c +@@ -3401,10 +3401,8 @@ static int ipw_get_fw(struct ipw_priv *priv, + + /* ask firmware_class module to get the boot firmware off disk */ + rc = request_firmware(raw, name, &priv->pci_dev->dev); +- if (rc < 0) { +- IPW_ERROR("%s request_firmware failed: Reason %d\n", name, rc); ++ if (rc) + return rc; +- } + + if ((*raw)->size < sizeof(*fw)) { + IPW_ERROR("%s is too small (%zd)\n", name, (*raw)->size); +@@ -11435,20 +11433,6 @@ static void ipw_bg_down(struct work_struct *work) + mutex_unlock(&priv->mutex); + } + +-/* Called by register_netdev() */ +-static int ipw_net_init(struct net_device *dev) +-{ +- int rc = 0; +- struct ipw_priv *priv = libipw_priv(dev); +- +- mutex_lock(&priv->mutex); +- if (ipw_up(priv)) +- rc = -EIO; +- mutex_unlock(&priv->mutex); +- +- return rc; +-} +- + static int ipw_wdev_init(struct net_device *dev) + { + int i, rc = 0; +@@ -11717,7 +11701,6 @@ static void ipw_prom_free(struct ipw_priv *priv) + #endif + + static const struct net_device_ops ipw_netdev_ops = { +- .ndo_init = ipw_net_init, + .ndo_open = ipw_net_open, + .ndo_stop = ipw_net_stop, + .ndo_set_rx_mode = ipw_net_set_multicast_list, +@@ -11844,17 +11827,24 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, + goto out_release_irq; + } + +- mutex_unlock(&priv->mutex); +- err = register_netdev(net_dev); +- if (err) { +- IPW_ERROR("failed to register network device\n"); ++ if (ipw_up(priv)) { ++ mutex_unlock(&priv->mutex); ++ err = -EIO; + goto out_remove_sysfs; + } + ++ mutex_unlock(&priv->mutex); ++ + err = ipw_wdev_init(net_dev); + if (err) { + IPW_ERROR("failed to register wireless device\n"); +- goto out_unregister_netdev; ++ goto out_remove_sysfs; ++ } ++ ++ err = register_netdev(net_dev); ++ if (err) { ++ IPW_ERROR("failed to register network device\n"); ++ goto out_unregister_wiphy; + } + + #ifdef CONFIG_IPW2200_PROMISCUOUS +@@ -11863,10 +11853,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, + if (err) { + IPW_ERROR("Failed to register promiscuous network " + "device (error %d).\n", err); +- wiphy_unregister(priv->ieee->wdev.wiphy); +- kfree(priv->ieee->a_band.channels); +- kfree(priv->ieee->bg_band.channels); +- goto out_unregister_netdev; ++ unregister_netdev(priv->net_dev); ++ goto out_unregister_wiphy; + } + } + #endif +@@ -11878,8 +11866,10 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, + + return 0; + +- out_unregister_netdev: +- unregister_netdev(priv->net_dev); ++ out_unregister_wiphy: ++ wiphy_unregister(priv->ieee->wdev.wiphy); ++ kfree(priv->ieee->a_band.channels); ++ kfree(priv->ieee->bg_band.channels); + out_remove_sysfs: + sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); + out_release_irq: +diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c +index b3d9f3f..1db238b 100644 +--- a/drivers/net/wireless/iwlegacy/iwl3945-base.c ++++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c +@@ -1870,8 +1870,6 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) + sprintf(buf, "%s%u%s", name_pre, index, ".ucode"); + ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev); + if (ret < 0) { +- IWL_ERR(priv, "%s firmware file req failed: %d\n", +- buf, ret); + if (ret == -ENOENT) + continue; + else +diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c +index e1a43c4..2390269 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-6000.c ++++ b/drivers/net/wireless/iwlwifi/iwl-6000.c +@@ -46,9 +46,10 @@ + #include "iwl-cfg.h" + + /* Highest firmware API version supported */ +-#define IWL6000_UCODE_API_MAX 6 ++#define IWL6000_UCODE_API_MAX 4 /* v5-6 are supported but not released */ ++#define IWL6000G2_UCODE_API_MAX 5 /* v6 was released too late */ + #define IWL6050_UCODE_API_MAX 5 +-#define IWL6000G2_UCODE_API_MAX 6 ++#define IWL6000G2B_UCODE_API_MAX 6 + #define IWL6035_UCODE_API_MAX 6 + + /* Oldest version we won't warn about */ +@@ -424,7 +425,7 @@ struct iwl_cfg iwl6005_2agn_mow2_cfg = { + + #define IWL_DEVICE_6030 \ + .fw_name_pre = IWL6030_FW_PRE, \ +- .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ ++ .ucode_api_max = IWL6000G2B_UCODE_API_MAX, \ + .ucode_api_ok = IWL6000G2B_UCODE_API_OK, \ + .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ + .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c +index 4a36973..b4b7ec8 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c +@@ -913,13 +913,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) + + memset(&pieces, 0, sizeof(pieces)); + +- if (!ucode_raw) { +- if (priv->fw_index <= api_ok) +- IWL_ERR(priv, +- "request for firmware file '%s' failed.\n", +- priv->firmware_name); ++ if (!ucode_raw) + goto try_again; +- } + + IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", + priv->firmware_name, ucode_raw->size); +diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c +index 6f1afe6..3dfb902 100644 +--- a/drivers/net/wireless/iwmc3200wifi/fw.c ++++ b/drivers/net/wireless/iwmc3200wifi/fw.c +@@ -168,10 +168,8 @@ static int iwm_load_img(struct iwm_priv *iwm, const char *img_name) + char *build_tag; + + ret = request_firmware(&fw, img_name, iwm_to_dev(iwm)); +- if (ret) { +- IWM_ERR(iwm, "Request firmware failed"); ++ if (ret) + return ret; +- } + + IWM_DBG_FW(iwm, INFO, "Start to load FW %s\n", img_name); + +diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c +index 957681d..aaaf85f 100644 +--- a/drivers/net/wireless/libertas/main.c ++++ b/drivers/net/wireless/libertas/main.c +@@ -1207,19 +1207,13 @@ int lbs_get_firmware(struct device *dev, const char *user_helper, + /* Try user-specified firmware first */ + if (user_helper) { + ret = request_firmware(helper, user_helper, dev); +- if (ret) { +- dev_err(dev, "couldn't find helper firmware %s\n", +- user_helper); ++ if (ret) + goto fail; +- } + } + if (user_mainfw) { + ret = request_firmware(mainfw, user_mainfw, dev); +- if (ret) { +- dev_err(dev, "couldn't find main firmware %s\n", +- user_mainfw); ++ if (ret) + goto fail; +- } + } + + if (*helper && *mainfw) +diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c +index 68202e6..51a7673 100644 +--- a/drivers/net/wireless/libertas_tf/if_usb.c ++++ b/drivers/net/wireless/libertas_tf/if_usb.c +@@ -827,8 +827,6 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp) + kparam_block_sysfs_write(fw_name); + ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev); + if (ret < 0) { +- pr_err("request_firmware() failed with %#x\n", ret); +- pr_err("firmware %s not found\n", lbtf_fw_name); + kparam_unblock_sysfs_write(fw_name); + goto done; + } +diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c +index 018276f..bc7e969 100644 +--- a/drivers/net/wireless/mwifiex/main.c ++++ b/drivers/net/wireless/mwifiex/main.c +@@ -311,8 +311,6 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) + err = request_firmware(&adapter->firmware, adapter->fw_name, + adapter->dev); + if (err < 0) { +- dev_err(adapter->dev, "request_firmware() returned" +- " error code %#x\n", err); + ret = -1; + goto done; + } +diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c +index 995695c..69c4d45 100644 +--- a/drivers/net/wireless/mwl8k.c ++++ b/drivers/net/wireless/mwl8k.c +@@ -5191,16 +5191,12 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv); + static void mwl8k_fw_state_machine(const struct firmware *fw, void *context) + { + struct mwl8k_priv *priv = context; +- struct mwl8k_device_info *di = priv->device_info; + int rc; + + switch (priv->fw_state) { + case FW_STATE_INIT: +- if (!fw) { +- printk(KERN_ERR "%s: Error requesting helper fw %s\n", +- pci_name(priv->pdev), di->helper_image); ++ if (!fw) + goto fail; +- } + priv->fw_helper = fw; + rc = mwl8k_request_fw(priv, priv->fw_pref, &priv->fw_ucode, + true); +@@ -5235,11 +5231,8 @@ static void mwl8k_fw_state_machine(const struct firmware *fw, void *context) + break; + + case FW_STATE_LOADING_ALT: +- if (!fw) { +- printk(KERN_ERR "%s: Error requesting alt fw %s\n", +- pci_name(priv->pdev), di->helper_image); ++ if (!fw) + goto fail; +- } + priv->fw_ucode = fw; + rc = mwl8k_firmware_load_success(priv); + if (rc) +@@ -5274,10 +5267,8 @@ static int mwl8k_init_firmware(struct ieee80211_hw *hw, char *fw_image, + + /* Ask userland hotplug daemon for the device firmware */ + rc = mwl8k_request_firmware(priv, fw_image, nowait); +- if (rc) { +- wiphy_err(hw->wiphy, "Firmware files not found\n"); ++ if (rc) + return rc; +- } + + if (nowait) + return rc; +diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c +index 4df8cf6..3c1dc78 100644 +--- a/drivers/net/wireless/orinoco/fw.c ++++ b/drivers/net/wireless/orinoco/fw.c +@@ -132,7 +132,6 @@ orinoco_dl_firmware(struct orinoco_private *priv, + err = request_firmware(&fw_entry, firmware, priv->dev); + + if (err) { +- dev_err(dev, "Cannot find firmware %s\n", firmware); + err = -ENOENT; + goto free; + } +@@ -292,10 +291,8 @@ symbol_dl_firmware(struct orinoco_private *priv, + const struct firmware *fw_entry; + + if (!orinoco_cached_fw_get(priv, true)) { +- if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) { +- dev_err(dev, "Cannot find firmware: %s\n", fw->pri_fw); ++ if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) + return -ENOENT; +- } + } else + fw_entry = orinoco_cached_fw_get(priv, true); + +@@ -311,10 +308,8 @@ symbol_dl_firmware(struct orinoco_private *priv, + } + + if (!orinoco_cached_fw_get(priv, false)) { +- if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) { +- dev_err(dev, "Cannot find firmware: %s\n", fw->sta_fw); ++ if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) + return -ENOENT; +- } + } else + fw_entry = orinoco_cached_fw_get(priv, false); + +diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c +index 0793e42..046d10e 100644 +--- a/drivers/net/wireless/orinoco/orinoco_usb.c ++++ b/drivers/net/wireless/orinoco/orinoco_usb.c +@@ -1684,7 +1684,6 @@ static int ezusb_probe(struct usb_interface *interface, + if (firmware.size && firmware.code) { + ezusb_firmware_download(upriv, &firmware); + } else { +- err("No firmware to download"); + goto error; + } + +diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c +index b1f51a2..6fee1ed 100644 +--- a/drivers/net/wireless/p54/p54pci.c ++++ b/drivers/net/wireless/p54/p54pci.c +@@ -564,7 +564,6 @@ static int __devinit p54p_probe(struct pci_dev *pdev, + err = request_firmware(&priv->firmware, "isl3886pci", + &priv->pdev->dev); + if (err) { +- dev_err(&pdev->dev, "Cannot find firmware (isl3886pci)\n"); + err = request_firmware(&priv->firmware, "isl3886", + &priv->pdev->dev); + if (err) +diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c +index 428401b..2e0567a 100644 +--- a/drivers/net/wireless/p54/p54spi.c ++++ b/drivers/net/wireless/p54/p54spi.c +@@ -171,10 +171,8 @@ static int p54spi_request_firmware(struct ieee80211_hw *dev) + /* FIXME: should driver use it's own struct device? */ + ret = request_firmware(&priv->firmware, "3826.arm", &priv->spi->dev); + +- if (ret < 0) { +- dev_err(&priv->spi->dev, "request_firmware() failed: %d", ret); ++ if (ret) + return ret; +- } + + ret = p54_parse_firmware(dev, priv->firmware); + if (ret) { +diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c +index 0784493..3fcb8abc 100644 +--- a/drivers/net/wireless/p54/p54usb.c ++++ b/drivers/net/wireless/p54/p54usb.c +@@ -857,9 +857,6 @@ static int p54u_load_firmware(struct ieee80211_hw *dev) + + err = request_firmware(&priv->fw, p54u_fwlist[i].fw, &priv->udev->dev); + if (err) { +- dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s " +- "(%d)!\n", p54u_fwlist[i].fw, err); +- + err = request_firmware(&priv->fw, p54u_fwlist[i].fw_legacy, + &priv->udev->dev); + if (err) +diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c +index e2fa538..c805c99 100644 +--- a/drivers/net/wireless/prism54/islpci_dev.c ++++ b/drivers/net/wireless/prism54/islpci_dev.c +@@ -93,12 +93,9 @@ isl_upload_firmware(islpci_private *priv) + const u32 *fw_ptr; + + rc = request_firmware(&fw_entry, priv->firmware, PRISM_FW_PDEV); +- if (rc) { +- printk(KERN_ERR +- "%s: request_firmware() failed for '%s'\n", +- "prism54", priv->firmware); ++ if (rc) + return rc; +- } ++ + /* prepare the Direct Memory Base register */ + reg = ISL38XX_DEV_FIRMWARE_ADDRES; + +diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h +index 5396e3b..d329001 100644 +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -68,6 +68,7 @@ + #define RF3322 0x000c + #define RF3853 0x000d + #define RF5370 0x5370 ++#define RF5372 0x5372 + #define RF5390 0x5390 + + /* +@@ -82,6 +83,7 @@ + #define REV_RT3090E 0x0211 + #define REV_RT3390E 0x0211 + #define REV_RT5390F 0x0502 ++#define REV_RT5390R 0x1502 + + /* + * Signal information. +diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c +index 8fb8c9e..4da3592 100644 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -402,7 +402,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, + + if (rt2x00_is_pci(rt2x00dev)) { + if (rt2x00_rt(rt2x00dev, RT3572) || +- rt2x00_rt(rt2x00dev, RT5390)) { ++ rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) { + rt2800_register_read(rt2x00dev, AUX_CTRL, ®); + rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); + rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); +@@ -1904,7 +1905,8 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, + r55_nonbt_rev[idx]); + rt2800_rfcsr_write(rt2x00dev, 59, + r59_nonbt_rev[idx]); +- } else if (rt2x00_rt(rt2x00dev, RT5390)) { ++ } else if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) { + static const char r59_non_bt[] = {0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d, + 0x8a, 0x88, 0x88, 0x87, 0x87, 0x86}; +@@ -1951,6 +1953,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + else if (rt2x00_rf(rt2x00dev, RF3052)) + rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info); + else if (rt2x00_rf(rt2x00dev, RF5370) || ++ rt2x00_rf(rt2x00dev, RF5372) || + rt2x00_rf(rt2x00dev, RF5390)) + rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); + else +@@ -1965,7 +1968,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + rt2800_bbp_write(rt2x00dev, 86, 0); + + if (rf->channel <= 14) { +- if (!rt2x00_rt(rt2x00dev, RT5390)) { ++ if (!rt2x00_rt(rt2x00dev, RT5390) && ++ !rt2x00_rt(rt2x00dev, RT5392)) { + if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, + &rt2x00dev->cap_flags)) { + rt2800_bbp_write(rt2x00dev, 82, 0x62); +@@ -2502,7 +2506,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) + rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3390) || +- rt2x00_rt(rt2x00dev, RT5390)) ++ rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) + return 0x1c + (2 * rt2x00dev->lna_gain); + else + return 0x2e + rt2x00dev->lna_gain; +@@ -2637,7 +2642,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) + } else if (rt2x00_rt(rt2x00dev, RT3572)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); +- } else if (rt2x00_rt(rt2x00dev, RT5390)) { ++ } else if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); +@@ -3013,7 +3019,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) + rt2800_wait_bbp_ready(rt2x00dev))) + return -EACCES; + +- if (rt2x00_rt(rt2x00dev, RT5390)) { ++ if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) { + rt2800_bbp_read(rt2x00dev, 4, &value); + rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1); + rt2800_bbp_write(rt2x00dev, 4, value); +@@ -3021,19 +3028,22 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) + + if (rt2800_is_305x_soc(rt2x00dev) || + rt2x00_rt(rt2x00dev, RT3572) || +- rt2x00_rt(rt2x00dev, RT5390)) ++ rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) + rt2800_bbp_write(rt2x00dev, 31, 0x08); + + rt2800_bbp_write(rt2x00dev, 65, 0x2c); + rt2800_bbp_write(rt2x00dev, 66, 0x38); + +- if (rt2x00_rt(rt2x00dev, RT5390)) ++ if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) + rt2800_bbp_write(rt2x00dev, 68, 0x0b); + + if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { + rt2800_bbp_write(rt2x00dev, 69, 0x16); + rt2800_bbp_write(rt2x00dev, 73, 0x12); +- } else if (rt2x00_rt(rt2x00dev, RT5390)) { ++ } else if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) { + rt2800_bbp_write(rt2x00dev, 69, 0x12); + rt2800_bbp_write(rt2x00dev, 73, 0x13); + rt2800_bbp_write(rt2x00dev, 75, 0x46); +@@ -3051,7 +3061,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) + rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3390) || + rt2x00_rt(rt2x00dev, RT3572) || +- rt2x00_rt(rt2x00dev, RT5390)) { ++ rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) { + rt2800_bbp_write(rt2x00dev, 79, 0x13); + rt2800_bbp_write(rt2x00dev, 80, 0x05); + rt2800_bbp_write(rt2x00dev, 81, 0x33); +@@ -3063,64 +3074,88 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) + } + + rt2800_bbp_write(rt2x00dev, 82, 0x62); +- if (rt2x00_rt(rt2x00dev, RT5390)) ++ if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) + rt2800_bbp_write(rt2x00dev, 83, 0x7a); + else + rt2800_bbp_write(rt2x00dev, 83, 0x6a); + + if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D)) + rt2800_bbp_write(rt2x00dev, 84, 0x19); +- else if (rt2x00_rt(rt2x00dev, RT5390)) ++ else if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) + rt2800_bbp_write(rt2x00dev, 84, 0x9a); + else + rt2800_bbp_write(rt2x00dev, 84, 0x99); + +- if (rt2x00_rt(rt2x00dev, RT5390)) ++ if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) + rt2800_bbp_write(rt2x00dev, 86, 0x38); + else + rt2800_bbp_write(rt2x00dev, 86, 0x00); + ++ if (rt2x00_rt(rt2x00dev, RT5392)) ++ rt2800_bbp_write(rt2x00dev, 88, 0x90); ++ + rt2800_bbp_write(rt2x00dev, 91, 0x04); + +- if (rt2x00_rt(rt2x00dev, RT5390)) ++ if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) + rt2800_bbp_write(rt2x00dev, 92, 0x02); + else + rt2800_bbp_write(rt2x00dev, 92, 0x00); + ++ if (rt2x00_rt(rt2x00dev, RT5392)) { ++ rt2800_bbp_write(rt2x00dev, 95, 0x9a); ++ rt2800_bbp_write(rt2x00dev, 98, 0x12); ++ } ++ + if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) || + rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) || + rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || + rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) || + rt2x00_rt(rt2x00dev, RT3572) || + rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392) || + rt2800_is_305x_soc(rt2x00dev)) + rt2800_bbp_write(rt2x00dev, 103, 0xc0); + else + rt2800_bbp_write(rt2x00dev, 103, 0x00); + +- if (rt2x00_rt(rt2x00dev, RT5390)) ++ if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) + rt2800_bbp_write(rt2x00dev, 104, 0x92); + + if (rt2800_is_305x_soc(rt2x00dev)) + rt2800_bbp_write(rt2x00dev, 105, 0x01); +- else if (rt2x00_rt(rt2x00dev, RT5390)) ++ else if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) + rt2800_bbp_write(rt2x00dev, 105, 0x3c); + else + rt2800_bbp_write(rt2x00dev, 105, 0x05); + + if (rt2x00_rt(rt2x00dev, RT5390)) + rt2800_bbp_write(rt2x00dev, 106, 0x03); ++ else if (rt2x00_rt(rt2x00dev, RT5392)) ++ rt2800_bbp_write(rt2x00dev, 106, 0x12); + else + rt2800_bbp_write(rt2x00dev, 106, 0x35); + +- if (rt2x00_rt(rt2x00dev, RT5390)) ++ if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) + rt2800_bbp_write(rt2x00dev, 128, 0x12); + ++ if (rt2x00_rt(rt2x00dev, RT5392)) { ++ rt2800_bbp_write(rt2x00dev, 134, 0xd0); ++ rt2800_bbp_write(rt2x00dev, 135, 0xf6); ++ } ++ + if (rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3090) || + rt2x00_rt(rt2x00dev, RT3390) || + rt2x00_rt(rt2x00dev, RT3572) || +- rt2x00_rt(rt2x00dev, RT5390)) { ++ rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) { + rt2800_bbp_read(rt2x00dev, 138, &value); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); +@@ -3132,7 +3167,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) + rt2800_bbp_write(rt2x00dev, 138, value); + } + +- if (rt2x00_rt(rt2x00dev, RT5390)) { ++ if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) { + int ant, div_mode; + + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); +@@ -3156,6 +3192,13 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) + rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + } + ++ /* This chip has hardware antenna diversity*/ ++ if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) { ++ rt2800_bbp_write(rt2x00dev, 150, 0); /* Disable Antenna Software OFDM */ ++ rt2800_bbp_write(rt2x00dev, 151, 0); /* Disable Antenna Software CCK */ ++ rt2800_bbp_write(rt2x00dev, 154, 0); /* Clear previously selected antenna */ ++ } ++ + rt2800_bbp_read(rt2x00dev, 152, &value); + if (ant == 0) + rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1); +@@ -3258,13 +3301,15 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) + !rt2x00_rt(rt2x00dev, RT3390) && + !rt2x00_rt(rt2x00dev, RT3572) && + !rt2x00_rt(rt2x00dev, RT5390) && ++ !rt2x00_rt(rt2x00dev, RT5392) && + !rt2800_is_305x_soc(rt2x00dev)) + return 0; + + /* + * Init RF calibration. + */ +- if (rt2x00_rt(rt2x00dev, RT5390)) { ++ if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) { + rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1); + rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); +@@ -3482,6 +3527,66 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) + rt2800_rfcsr_write(rt2x00dev, 61, 0xdd); + rt2800_rfcsr_write(rt2x00dev, 62, 0x00); + rt2800_rfcsr_write(rt2x00dev, 63, 0x00); ++ } else if (rt2x00_rt(rt2x00dev, RT5392)) { ++ rt2800_rfcsr_write(rt2x00dev, 1, 0x17); ++ rt2800_rfcsr_write(rt2x00dev, 2, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 3, 0x88); ++ rt2800_rfcsr_write(rt2x00dev, 5, 0x10); ++ rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); ++ rt2800_rfcsr_write(rt2x00dev, 7, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 10, 0x53); ++ rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); ++ rt2800_rfcsr_write(rt2x00dev, 12, 0x46); ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); ++ rt2800_rfcsr_write(rt2x00dev, 14, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 15, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 16, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 18, 0x03); ++ rt2800_rfcsr_write(rt2x00dev, 19, 0x4d); ++ rt2800_rfcsr_write(rt2x00dev, 20, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 21, 0x8d); ++ rt2800_rfcsr_write(rt2x00dev, 22, 0x20); ++ rt2800_rfcsr_write(rt2x00dev, 23, 0x0b); ++ rt2800_rfcsr_write(rt2x00dev, 24, 0x44); ++ rt2800_rfcsr_write(rt2x00dev, 25, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 26, 0x82); ++ rt2800_rfcsr_write(rt2x00dev, 27, 0x09); ++ rt2800_rfcsr_write(rt2x00dev, 28, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 29, 0x10); ++ rt2800_rfcsr_write(rt2x00dev, 30, 0x10); ++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 32, 0x20); ++ rt2800_rfcsr_write(rt2x00dev, 33, 0xC0); ++ rt2800_rfcsr_write(rt2x00dev, 34, 0x07); ++ rt2800_rfcsr_write(rt2x00dev, 35, 0x12); ++ rt2800_rfcsr_write(rt2x00dev, 36, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 37, 0x08); ++ rt2800_rfcsr_write(rt2x00dev, 38, 0x89); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); ++ rt2800_rfcsr_write(rt2x00dev, 40, 0x0f); ++ rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); ++ rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); ++ rt2800_rfcsr_write(rt2x00dev, 43, 0x9b); ++ rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); ++ rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); ++ rt2800_rfcsr_write(rt2x00dev, 46, 0x73); ++ rt2800_rfcsr_write(rt2x00dev, 47, 0x0c); ++ rt2800_rfcsr_write(rt2x00dev, 48, 0x10); ++ rt2800_rfcsr_write(rt2x00dev, 49, 0x94); ++ rt2800_rfcsr_write(rt2x00dev, 50, 0x94); ++ rt2800_rfcsr_write(rt2x00dev, 51, 0x3a); ++ rt2800_rfcsr_write(rt2x00dev, 52, 0x48); ++ rt2800_rfcsr_write(rt2x00dev, 53, 0x44); ++ rt2800_rfcsr_write(rt2x00dev, 54, 0x38); ++ rt2800_rfcsr_write(rt2x00dev, 55, 0x43); ++ rt2800_rfcsr_write(rt2x00dev, 56, 0xa1); ++ rt2800_rfcsr_write(rt2x00dev, 57, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 58, 0x39); ++ rt2800_rfcsr_write(rt2x00dev, 59, 0x07); ++ rt2800_rfcsr_write(rt2x00dev, 60, 0x45); ++ rt2800_rfcsr_write(rt2x00dev, 61, 0x91); ++ rt2800_rfcsr_write(rt2x00dev, 62, 0x39); ++ rt2800_rfcsr_write(rt2x00dev, 63, 0x07); + } + + if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { +@@ -3549,7 +3654,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) + rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15); + } + +- if (!rt2x00_rt(rt2x00dev, RT5390)) { ++ if (!rt2x00_rt(rt2x00dev, RT5390) && ++ !rt2x00_rt(rt2x00dev, RT5392)) { + /* + * Set back to initial state + */ +@@ -3577,7 +3683,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) + rt2x00_set_field32(®, OPT_14_CSR_BIT0, 1); + rt2800_register_write(rt2x00dev, OPT_14_CSR, reg); + +- if (!rt2x00_rt(rt2x00dev, RT5390)) { ++ if (!rt2x00_rt(rt2x00dev, RT5390) && ++ !rt2x00_rt(rt2x00dev, RT5392)) { + rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0); + if (rt2x00_rt(rt2x00dev, RT3070) || +@@ -3645,7 +3752,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) + rt2800_rfcsr_write(rt2x00dev, 27, rfcsr); + } + +- if (rt2x00_rt(rt2x00dev, RT5390)) { ++ if (rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392)) { + rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0); + rt2800_rfcsr_write(rt2x00dev, 38, rfcsr); +@@ -3929,7 +4037,8 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) + * RT53xx: defined in "EEPROM_CHIP_ID" field + */ + rt2800_register_read(rt2x00dev, MAC_CSR0, ®); +- if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390) ++ if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 || ++ rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392) + rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value); + else + value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); +@@ -3945,8 +4054,9 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) + !rt2x00_rt(rt2x00dev, RT3090) && + !rt2x00_rt(rt2x00dev, RT3390) && + !rt2x00_rt(rt2x00dev, RT3572) && +- !rt2x00_rt(rt2x00dev, RT5390)) { +- ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); ++ !rt2x00_rt(rt2x00dev, RT5390) && ++ !rt2x00_rt(rt2x00dev, RT5392)) { ++ ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt); + return -ENODEV; + } + +@@ -3962,10 +4072,11 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) + case RF3052: + case RF3320: + case RF5370: ++ case RF5372: + case RF5390: + break; + default: +- ERROR(rt2x00dev, "Invalid RF chipset 0x%x detected.\n", ++ ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", + rt2x00dev->chip.rf); + return -ENODEV; + } +@@ -4002,6 +4113,11 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) + rt2x00dev->default_ant.rx = ANTENNA_A; + } + ++ if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) { ++ rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY; /* Unused */ ++ rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY; /* Unused */ ++ } ++ + /* + * Determine external LNA informations. + */ +@@ -4269,6 +4385,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + rt2x00_rf(rt2x00dev, RF3022) || + rt2x00_rf(rt2x00dev, RF3320) || + rt2x00_rf(rt2x00dev, RF5370) || ++ rt2x00_rf(rt2x00dev, RF5372) || + rt2x00_rf(rt2x00dev, RF5390)) { + spec->num_channels = 14; + spec->channels = rf_vals_3x; +diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c +index 518157d..1fc8cdc 100644 +--- a/drivers/net/wireless/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/rt2x00/rt2800pci.c +@@ -480,7 +480,8 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) + + if (rt2x00_is_pcie(rt2x00dev) && + (rt2x00_rt(rt2x00dev, RT3572) || +- rt2x00_rt(rt2x00dev, RT5390))) { ++ rt2x00_rt(rt2x00dev, RT5390) || ++ rt2x00_rt(rt2x00dev, RT5392))) { + rt2x00pci_register_read(rt2x00dev, AUX_CTRL, ®); + rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); + rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); +@@ -1153,8 +1154,11 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { + { PCI_DEVICE(0x1814, 0x3593) }, + #endif + #ifdef CONFIG_RT2800PCI_RT53XX ++ { PCI_DEVICE(0x1814, 0x5362) }, + { PCI_DEVICE(0x1814, 0x5390) }, ++ { PCI_DEVICE(0x1814, 0x5392) }, + { PCI_DEVICE(0x1814, 0x539a) }, ++ { PCI_DEVICE(0x1814, 0x539b) }, + { PCI_DEVICE(0x1814, 0x539f) }, + #endif + { 0, } +diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c +index ee7efd2..db5c003 100644 +--- a/drivers/net/wireless/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -1156,15 +1156,29 @@ static struct usb_device_id rt2800usb_device_table[] = { + { USB_DEVICE(0x5a57, 0x0284) }, + #endif + #ifdef CONFIG_RT2800USB_RT53XX ++ /* Alpha */ ++ { USB_DEVICE(0x2001, 0x3c15) }, ++ { USB_DEVICE(0x2001, 0x3c19) }, ++ /* Arcadyan */ ++ { USB_DEVICE(0x043e, 0x7a12) }, + /* Azurewave */ + { USB_DEVICE(0x13d3, 0x3329) }, + { USB_DEVICE(0x13d3, 0x3365) }, + /* D-Link */ + { USB_DEVICE(0x2001, 0x3c1c) }, + { USB_DEVICE(0x2001, 0x3c1d) }, ++ /* LG innotek */ ++ { USB_DEVICE(0x043e, 0x7a22) }, ++ /* Panasonic */ ++ { USB_DEVICE(0x04da, 0x1801) }, ++ { USB_DEVICE(0x04da, 0x1800) }, ++ /* Philips */ ++ { USB_DEVICE(0x0471, 0x2104) }, + /* Ralink */ + { USB_DEVICE(0x148f, 0x5370) }, + { USB_DEVICE(0x148f, 0x5372) }, ++ /* Unknown */ ++ { USB_DEVICE(0x04da, 0x23f6) }, + #endif + #ifdef CONFIG_RT2800USB_UNKNOWN + /* +diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h +index c778164..b811056 100644 +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -192,6 +192,7 @@ struct rt2x00_chip { + #define RT3593 0x3593 /* PCIe */ + #define RT3883 0x3883 /* WSOC */ + #define RT5390 0x5390 /* 2.4GHz */ ++#define RT5392 0x5392 /* 2.4GHz */ + + u16 rf; + u16 rev; +diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c +index f316aad..6cd44f7 100644 +--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c ++++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c +@@ -51,10 +51,8 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) + INFO(rt2x00dev, "Loading firmware file '%s'.\n", fw_name); + + retval = request_firmware(&fw, fw_name, device); +- if (retval) { +- ERROR(rt2x00dev, "Failed to request Firmware.\n"); ++ if (retval) + return retval; +- } + + if (!fw || !fw->size || !fw->data) { + ERROR(rt2x00dev, "Failed to read Firmware.\n"); +diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +index df852e8..8b8f8c9 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +@@ -174,11 +174,8 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) + fw_name = rtlpriv->cfg->fw_name; + } + err = request_firmware(&firmware, fw_name, rtlpriv->io.dev); +- if (err) { +- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +- ("Failed to request firmware!\n")); ++ if (err) + return 1; +- } + if (firmware->size > 0x4000) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is too big!\n")); +diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +index ec347d2..a0fb759 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -71,11 +71,8 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) + /* request fw */ + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); +- if (err) { +- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +- ("Failed to request firmware!\n")); ++ if (err) + return 1; +- } + if (firmware->size > 0x4000) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is too big!\n")); +diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +index 149493f..fd83f8b 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +@@ -186,11 +186,8 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) + /* request fw */ + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); +- if (err) { +- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +- ("Failed to request firmware!\n")); ++ if (err) + return 1; +- } + if (firmware->size > 0x8000) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is too big!\n")); +diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +index 92f49d5..225e54d 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +@@ -197,11 +197,8 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) + /* request fw */ + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); +- if (err) { +- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +- ("Failed to request firmware!\n")); ++ if (err) + return 1; +- } + if (firmware->size > sizeof(struct rt_firmware)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is too big!\n")); +diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c +index 40c1574..d912985 100644 +--- a/drivers/net/wireless/wl1251/main.c ++++ b/drivers/net/wireless/wl1251/main.c +@@ -70,10 +70,8 @@ static int wl1251_fetch_firmware(struct wl1251 *wl) + + ret = request_firmware(&fw, WL1251_FW_NAME, dev); + +- if (ret < 0) { +- wl1251_error("could not get firmware: %d", ret); ++ if (ret) + return ret; +- } + + if (fw->size % 4) { + wl1251_error("firmware size is not multiple of 32 bits: %zu", +@@ -109,10 +107,8 @@ static int wl1251_fetch_nvs(struct wl1251 *wl) + + ret = request_firmware(&fw, WL1251_NVS_NAME, dev); + +- if (ret < 0) { +- wl1251_error("could not get nvs file: %d", ret); ++ if (ret) + return ret; +- } + + if (fw->size % 4) { + wl1251_error("nvs size is not multiple of 32 bits: %zu", +diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c +index 884f82b..feb84e4 100644 +--- a/drivers/net/wireless/wl12xx/main.c ++++ b/drivers/net/wireless/wl12xx/main.c +@@ -1071,10 +1071,8 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) + + ret = request_firmware(&fw, fw_name, wl1271_wl_to_dev(wl)); + +- if (ret < 0) { +- wl1271_error("could not get firmware: %d", ret); ++ if (ret) + return ret; +- } + + if (fw->size % 4) { + wl1271_error("firmware size is not multiple of 32 bits: %zu", +@@ -1109,10 +1107,8 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) + + ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); + +- if (ret < 0) { +- wl1271_error("could not get nvs file: %d", ret); ++ if (ret) + return ret; +- } + + wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); + +diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c +index f25d5d9..20c5578 100644 +--- a/drivers/net/wireless/wl12xx/sdio_test.c ++++ b/drivers/net/wireless/wl12xx/sdio_test.c +@@ -206,10 +206,8 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) + ret = request_firmware(&fw, WL127X_FW_NAME, + wl1271_wl_to_dev(wl)); + +- if (ret < 0) { +- wl1271_error("could not get firmware: %d", ret); ++ if (ret) + return ret; +- } + + if (fw->size % 4) { + wl1271_error("firmware size is not multiple of 32 bits: %zu", +@@ -244,10 +242,8 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) + + ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); + +- if (ret < 0) { +- wl1271_error("could not get nvs file: %d", ret); ++ if (ret) + return ret; +- } + + wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); + +diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c +index f8c319c..ee1e097 100644 +--- a/drivers/net/wireless/zd1201.c ++++ b/drivers/net/wireless/zd1201.c +@@ -65,8 +65,6 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw) + + err = request_firmware(&fw_entry, fwfile, &dev->dev); + if (err) { +- dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile); +- dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n"); + dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info.\n"); + return err; + } +diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c +index 785bdbe..6a7f33b 100644 +--- a/drivers/net/wireless/zd1211rw/zd_usb.c ++++ b/drivers/net/wireless/zd1211rw/zd_usb.c +@@ -121,16 +121,9 @@ static void int_urb_complete(struct urb *urb); + static int request_fw_file( + const struct firmware **fw, const char *name, struct device *device) + { +- int r; +- + dev_dbg_f(device, "fw name %s\n", name); + +- r = request_firmware(fw, name, device); +- if (r) +- dev_err(device, +- "Could not load firmware file %s. Error number %d\n", +- name, r); +- return r; ++ return request_firmware(fw, name, device); + } + + static inline u16 get_bcdDevice(const struct usb_device *udev) +diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c +index 980c079..5f3f65a 100644 +--- a/drivers/of/of_mdio.c ++++ b/drivers/of/of_mdio.c +@@ -45,6 +45,8 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) + for (i=0; iirq[i] = PHY_POLL; + ++ mdio->dev.of_node = np; ++ + /* Register the MDIO bus */ + rc = mdiobus_register(mdio); + if (rc) +@@ -77,12 +79,16 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) + mdio->irq[addr] = PHY_POLL; + } + ++ mdio->is_c45 = of_device_is_compatible(child, ++ "ethernet-phy-ieee802.3-c45"); ++ + phy = get_phy_device(mdio, addr); + if (!phy || IS_ERR(phy)) { + dev_err(&mdio->dev, "error probing PHY at address %i\n", + addr); + continue; + } ++ phy_scan_fixups(phy); + + /* Associate the OF node with the device structure so it + * can be looked up later */ +@@ -188,3 +194,17 @@ struct phy_device *of_phy_connect_fixed_link(struct net_device *dev, + return IS_ERR(phy) ? NULL : phy; + } + EXPORT_SYMBOL(of_phy_connect_fixed_link); ++ ++/* XXX add comment */ ++struct phy_device *of_phy_attach(struct net_device *dev, ++ struct device_node *phy_np, u32 flags, ++ phy_interface_t iface) ++{ ++ struct phy_device *phy = of_phy_find_device(phy_np); ++ ++ if (!phy) ++ return NULL; ++ ++ return phy_attach_direct(dev, phy, flags, iface) ? NULL : phy; ++} ++EXPORT_SYMBOL(of_phy_attach); +diff --git a/drivers/of/platform.c b/drivers/of/platform.c +index 63b3ec4..fb3762c 100644 +--- a/drivers/of/platform.c ++++ b/drivers/of/platform.c +@@ -139,6 +139,18 @@ struct platform_device *of_device_alloc(struct device_node *np, + if (!dev) + return NULL; + ++ dev->dev.of_node = of_node_get(np); ++ if (bus_id) ++ dev_set_name(&dev->dev, "%s", bus_id); ++ else ++ of_device_make_bus_id(&dev->dev); ++ ++ if (kset_find_obj(dev->dev.kobj.kset, kobject_name(&dev->dev.kobj))) { ++ kfree(dev); ++ of_node_put(np); ++ return NULL; ++ } ++ + /* count the io and irq resources */ + while (of_address_to_resource(np, num_reg, &temp_res) == 0) + num_reg++; +@@ -161,17 +173,11 @@ struct platform_device *of_device_alloc(struct device_node *np, + WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq); + } + +- dev->dev.of_node = of_node_get(np); + #if defined(CONFIG_MICROBLAZE) + dev->dev.dma_mask = &dev->archdata.dma_mask; + #endif + dev->dev.parent = parent; + +- if (bus_id) +- dev_set_name(&dev->dev, "%s", bus_id); +- else +- of_device_make_bus_id(&dev->dev); +- + return dev; + } + EXPORT_SYMBOL(of_device_alloc); +diff --git a/drivers/pci/access.c b/drivers/pci/access.c +index fdaa42a..bbde7d0 100644 +--- a/drivers/pci/access.c ++++ b/drivers/pci/access.c +@@ -445,3 +445,205 @@ void pci_unblock_user_cfg_access(struct pci_dev *dev) + raw_spin_unlock_irqrestore(&pci_lock, flags); + } + EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access); ++ ++static inline int pcie_cap_version(const struct pci_dev *dev) ++{ ++ return dev->pcie_flags_reg & PCI_EXP_FLAGS_VERS; ++} ++ ++static inline bool pcie_cap_has_devctl(const struct pci_dev *dev) ++{ ++ return true; ++} ++ ++static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev) ++{ ++ int type = pci_pcie_type(dev); ++ ++ return pcie_cap_version(dev) > 1 || ++ type == PCI_EXP_TYPE_ROOT_PORT || ++ type == PCI_EXP_TYPE_ENDPOINT || ++ type == PCI_EXP_TYPE_LEG_END; ++} ++ ++static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev) ++{ ++ int type = pci_pcie_type(dev); ++ ++ return pcie_cap_version(dev) > 1 || ++ type == PCI_EXP_TYPE_ROOT_PORT || ++ (type == PCI_EXP_TYPE_DOWNSTREAM && ++ dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT); ++} ++ ++static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev) ++{ ++ int type = pci_pcie_type(dev); ++ ++ return pcie_cap_version(dev) > 1 || ++ type == PCI_EXP_TYPE_ROOT_PORT || ++ type == PCI_EXP_TYPE_RC_EC; ++} ++ ++static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos) ++{ ++ if (!pci_is_pcie(dev)) ++ return false; ++ ++ switch (pos) { ++ case PCI_EXP_FLAGS_TYPE: ++ return true; ++ case PCI_EXP_DEVCAP: ++ case PCI_EXP_DEVCTL: ++ case PCI_EXP_DEVSTA: ++ return pcie_cap_has_devctl(dev); ++ case PCI_EXP_LNKCAP: ++ case PCI_EXP_LNKCTL: ++ case PCI_EXP_LNKSTA: ++ return pcie_cap_has_lnkctl(dev); ++ case PCI_EXP_SLTCAP: ++ case PCI_EXP_SLTCTL: ++ case PCI_EXP_SLTSTA: ++ return pcie_cap_has_sltctl(dev); ++ case PCI_EXP_RTCTL: ++ case PCI_EXP_RTCAP: ++ case PCI_EXP_RTSTA: ++ return pcie_cap_has_rtctl(dev); ++ case PCI_EXP_DEVCAP2: ++ case PCI_EXP_DEVCTL2: ++ case PCI_EXP_LNKCAP2: ++ case PCI_EXP_LNKCTL2: ++ case PCI_EXP_LNKSTA2: ++ return pcie_cap_version(dev) > 1; ++ default: ++ return false; ++ } ++} ++ ++/* ++ * Note that these accessor functions are only for the "PCI Express ++ * Capability" (see PCIe spec r3.0, sec 7.8). They do not apply to the ++ * other "PCI Express Extended Capabilities" (AER, VC, ACS, MFVC, etc.) ++ */ ++int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val) ++{ ++ int ret; ++ ++ *val = 0; ++ if (pos & 1) ++ return -EINVAL; ++ ++ if (pcie_capability_reg_implemented(dev, pos)) { ++ ret = pci_read_config_word(dev, pci_pcie_cap(dev) + pos, val); ++ /* ++ * Reset *val to 0 if pci_read_config_word() fails, it may ++ * have been written as 0xFFFF if hardware error happens ++ * during pci_read_config_word(). ++ */ ++ if (ret) ++ *val = 0; ++ return ret; ++ } ++ ++ /* ++ * For Functions that do not implement the Slot Capabilities, ++ * Slot Status, and Slot Control registers, these spaces must ++ * be hardwired to 0b, with the exception of the Presence Detect ++ * State bit in the Slot Status register of Downstream Ports, ++ * which must be hardwired to 1b. (PCIe Base Spec 3.0, sec 7.8) ++ */ ++ if (pci_is_pcie(dev) && pos == PCI_EXP_SLTSTA && ++ pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) { ++ *val = PCI_EXP_SLTSTA_PDS; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(pcie_capability_read_word); ++ ++int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val) ++{ ++ int ret; ++ ++ *val = 0; ++ if (pos & 3) ++ return -EINVAL; ++ ++ if (pcie_capability_reg_implemented(dev, pos)) { ++ ret = pci_read_config_dword(dev, pci_pcie_cap(dev) + pos, val); ++ /* ++ * Reset *val to 0 if pci_read_config_dword() fails, it may ++ * have been written as 0xFFFFFFFF if hardware error happens ++ * during pci_read_config_dword(). ++ */ ++ if (ret) ++ *val = 0; ++ return ret; ++ } ++ ++ if (pci_is_pcie(dev) && pos == PCI_EXP_SLTCTL && ++ pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) { ++ *val = PCI_EXP_SLTSTA_PDS; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(pcie_capability_read_dword); ++ ++int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val) ++{ ++ if (pos & 1) ++ return -EINVAL; ++ ++ if (!pcie_capability_reg_implemented(dev, pos)) ++ return 0; ++ ++ return pci_write_config_word(dev, pci_pcie_cap(dev) + pos, val); ++} ++EXPORT_SYMBOL(pcie_capability_write_word); ++ ++int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val) ++{ ++ if (pos & 3) ++ return -EINVAL; ++ ++ if (!pcie_capability_reg_implemented(dev, pos)) ++ return 0; ++ ++ return pci_write_config_dword(dev, pci_pcie_cap(dev) + pos, val); ++} ++EXPORT_SYMBOL(pcie_capability_write_dword); ++ ++int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, ++ u16 clear, u16 set) ++{ ++ int ret; ++ u16 val; ++ ++ ret = pcie_capability_read_word(dev, pos, &val); ++ if (!ret) { ++ val &= ~clear; ++ val |= set; ++ ret = pcie_capability_write_word(dev, pos, val); ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(pcie_capability_clear_and_set_word); ++ ++int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos, ++ u32 clear, u32 set) ++{ ++ int ret; ++ u32 val; ++ ++ ret = pcie_capability_read_dword(dev, pos, &val); ++ if (!ret) { ++ val &= ~clear; ++ val |= set; ++ ret = pcie_capability_write_dword(dev, pos, val); ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(pcie_capability_clear_and_set_dword); +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index e3efb43..b99d888 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -306,6 +306,9 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg) + static void free_msi_irqs(struct pci_dev *dev) + { + struct msi_desc *entry, *tmp; ++ struct attribute **msi_attrs; ++ struct device_attribute *dev_attr; ++ int count = 0; + + list_for_each_entry(entry, &dev->msi_list, list) { + int i, nvec; +@@ -323,9 +326,25 @@ static void free_msi_irqs(struct pci_dev *dev) + if (list_is_last(&entry->list, &dev->msi_list)) + iounmap(entry->mask_base); + } ++ + list_del(&entry->list); + kfree(entry); + } ++ ++ if (dev->msi_irq_group) { ++ sysfs_remove_group(&dev->dev.kobj, dev->msi_irq_group); ++ msi_attrs = dev->msi_irq_group->attrs; ++ while (msi_attrs[count]) { ++ dev_attr = container_of(msi_attrs[count], ++ struct device_attribute, attr); ++ kfree(dev_attr->attr.name); ++ kfree(dev_attr); ++ ++count; ++ } ++ kfree(msi_attrs); ++ kfree(dev->msi_irq_group); ++ dev->msi_irq_group = NULL; ++ } + } + + static struct msi_desc *alloc_msi_entry(struct pci_dev *dev) +@@ -403,6 +422,98 @@ void pci_restore_msi_state(struct pci_dev *dev) + } + EXPORT_SYMBOL_GPL(pci_restore_msi_state); + ++static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ struct msi_desc *entry; ++ unsigned long irq; ++ int retval; ++ ++ retval = kstrtoul(attr->attr.name, 10, &irq); ++ if (retval) ++ return retval; ++ ++ list_for_each_entry(entry, &pdev->msi_list, list) { ++ if (entry->irq == irq) { ++ return sprintf(buf, "%s\n", ++ entry->msi_attrib.is_msix ? "msix" : "msi"); ++ } ++ } ++ return -ENODEV; ++} ++ ++static int populate_msi_sysfs(struct pci_dev *pdev) ++{ ++ struct attribute **msi_attrs; ++ struct attribute *msi_attr; ++ struct device_attribute *msi_dev_attr; ++ struct attribute_group *msi_irq_group; ++ struct msi_desc *entry; ++ int ret = -ENOMEM; ++ int num_msi = 0; ++ int count = 0; ++ ++ /* Determine how many msi entries we have */ ++ list_for_each_entry(entry, &pdev->msi_list, list) { ++ ++num_msi; ++ } ++ if (!num_msi) ++ return 0; ++ ++ /* Dynamically create the MSI attributes for the PCI device */ ++ msi_attrs = kzalloc(sizeof(void *) * (num_msi + 1), GFP_KERNEL); ++ if (!msi_attrs) ++ return -ENOMEM; ++ list_for_each_entry(entry, &pdev->msi_list, list) { ++ char *name = kmalloc(20, GFP_KERNEL); ++ if (!name) ++ goto error_attrs; ++ ++ msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL); ++ if (!msi_dev_attr) { ++ kfree(name); ++ goto error_attrs; ++ } ++ ++ sprintf(name, "%d", entry->irq); ++ sysfs_attr_init(&msi_dev_attr->attr); ++ msi_dev_attr->attr.name = name; ++ msi_dev_attr->attr.mode = S_IRUGO; ++ msi_dev_attr->show = msi_mode_show; ++ msi_attrs[count] = &msi_dev_attr->attr; ++ ++count; ++ } ++ ++ msi_irq_group = kzalloc(sizeof(*msi_irq_group), GFP_KERNEL); ++ if (!msi_irq_group) ++ goto error_attrs; ++ msi_irq_group->name = "msi_irqs"; ++ msi_irq_group->attrs = msi_attrs; ++ ++ ret = sysfs_create_group(&pdev->dev.kobj, msi_irq_group); ++ if (ret) ++ goto error_irq_group; ++ pdev->msi_irq_group = msi_irq_group; ++ ++ return 0; ++ ++error_irq_group: ++ kfree(msi_irq_group); ++error_attrs: ++ count = 0; ++ msi_attr = msi_attrs[count]; ++ while (msi_attr) { ++ msi_dev_attr = container_of(msi_attr, struct device_attribute, attr); ++ kfree(msi_attr->name); ++ kfree(msi_dev_attr); ++ ++count; ++ msi_attr = msi_attrs[count]; ++ } ++ kfree(msi_attrs); ++ return ret; ++} ++ + /** + * msi_capability_init - configure device's MSI capability structure + * @dev: pointer to the pci_dev data structure of MSI device function +@@ -454,6 +565,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) + return ret; + } + ++ ret = populate_msi_sysfs(dev); ++ if (ret) { ++ msi_mask_irq(entry, mask, ~mask); ++ free_msi_irqs(dev); ++ return ret; ++ } ++ + /* Set MSI enabled bits */ + pci_intx_for_msi(dev, 0); + msi_set_enable(dev, pos, 1); +@@ -562,7 +680,7 @@ static int msix_capability_init(struct pci_dev *dev, + + ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); + if (ret) +- goto error; ++ goto out_avail; + + /* + * Some devices require MSI-X to be enabled before we can touch the +@@ -574,6 +692,10 @@ static int msix_capability_init(struct pci_dev *dev, + + msix_program_entries(dev, entries); + ++ ret = populate_msi_sysfs(dev); ++ if (ret) ++ goto out_free; ++ + /* Set MSI-X enabled bits and unmask the function */ + pci_intx_for_msi(dev, 0); + dev->msix_enabled = 1; +@@ -583,7 +705,7 @@ static int msix_capability_init(struct pci_dev *dev, + + return 0; + +-error: ++out_avail: + if (ret < 0) { + /* + * If we had some success, report the number of irqs +@@ -600,6 +722,7 @@ error: + ret = avail; + } + ++out_free: + free_msi_irqs(dev); + + return ret; +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index 4c3a9e9..e4823bf 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -963,7 +963,7 @@ void pci_restore_state(struct pci_dev *dev) + for (i = 15; i >= 0; i--) { + pci_read_config_dword(dev, i * 4, &val); + if (val != dev->saved_config_space[i]) { +- dev_printk(KERN_DEBUG, &dev->dev, "restoring config " ++ dev_dbg(&dev->dev, "restoring config " + "space at offset %#x (was %#x, writing %#x)\n", + i, val, (int)dev->saved_config_space[i]); + pci_write_config_dword(dev,i * 4, +@@ -1545,8 +1545,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable) + } + + out: +- dev_printk(KERN_DEBUG, &dev->dev, "PME# %s\n", +- enable ? "enabled" : "disabled"); ++ dev_dbg(&dev->dev, "PME# %s\n", enable ? "enabled" : "disabled"); + } + + /** +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index c73ed00..31668af 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -440,7 +440,7 @@ static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) + int pos = pci_pcie_cap(pdev); + + pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); +- reg16 &= ~0x3; ++ reg16 &= ~PCI_EXP_LNKCTL_ASPMC; + reg16 |= val; + pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); + } +@@ -457,12 +457,12 @@ static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) + return; + /* Convert ASPM state to upstream/downstream ASPM register state */ + if (state & ASPM_STATE_L0S_UP) +- dwstream |= PCIE_LINK_STATE_L0S; ++ dwstream |= PCI_EXP_LNKCTL_ASPM_L0S; + if (state & ASPM_STATE_L0S_DW) +- upstream |= PCIE_LINK_STATE_L0S; ++ upstream |= PCI_EXP_LNKCTL_ASPM_L0S; + if (state & ASPM_STATE_L1) { +- upstream |= PCIE_LINK_STATE_L1; +- dwstream |= PCIE_LINK_STATE_L1; ++ upstream |= PCI_EXP_LNKCTL_ASPM_L1; ++ dwstream |= PCI_EXP_LNKCTL_ASPM_L1; + } + /* + * Spec 2.0 suggests all functions should be configured the +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index bc92c47..757c9d2 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -865,7 +865,8 @@ void set_pcie_port_type(struct pci_dev *pdev) + pdev->is_pcie = 1; + pdev->pcie_cap = pos; + pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); +- pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; ++ pdev->pcie_flags_reg = reg16; ++ pdev->pcie_type = pci_pcie_type(pdev); + pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, ®16); + pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD; + } +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 481b184..1351477 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -2256,6 +2256,58 @@ static void __devinit quirk_tile_plx_gen1(struct pci_dev *dev) + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1); + #endif /* CONFIG_TILE */ + ++/* Uncorrectable PCIe errors are generated when using the BCM56150 ++ * operating at Gen2 (5GT/s) link speed on the E1050 platform ++ * These errors are not observed when operating at Gen1 (2.5GT/s) ++ * link speed. There are two BCM56150 devices on the E1050 ++ * platform (bus 1 and 2), force both to Gen1 speed. This is ++ * done via the root complex since that is the only way to force ++ * the link to retrain. 0x50 is the Link Control PCIe capability ++ * register on the root complex, 0x70 is the Link Control2 PCIe ++ * PCIe capability register on the root complex. ++ * ++ * NOTE: This patch is a workaround and is not intended to be ++ * upstreamed. This specific issue is not seen with Linux kernel ++ * 3.16 and may be specific to backported (or lack of backported) ++ * Intel Bay Trail patches from 3.16 to 3.2 ++ */ ++static void __devinit quirk_bcm56150_gen1(struct pci_dev *dev) ++{ ++ u16 config; ++ struct pci_dev *pdev = NULL; ++ ++ /* Only interested in BCM56150 function 0 */ ++ if (PCI_FUNC(dev->devfn)) ++ return; ++ /* Find Intel PCIe root complex function 0 */ ++ pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0f48, NULL); ++ if (!pdev) { ++ printk(KERN_INFO "E1050: Could not find Intel PCIe-RC fn 0\n"); ++ return; ++ } ++ if (dev->bus->number == 2) { ++ /* If this is the second BCM56150, then find Intel PCIe RC function 1 */ ++ pdev = pci_get_slot(pdev->bus, ++ PCI_DEVFN(PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)+1)); ++ if (!pdev) { ++ printk(KERN_INFO "E1050: Could not find Intel PCIe-RC fn 1\n"); ++ return; ++ } ++ } ++ /* Set link speed to 2.5GT/s */ ++ pci_read_config_word(pdev, 0x70, &config); ++ config &= ~0xf; ++ config |= 0x1; ++ pci_write_config_word(pdev, 0x70, config); ++ /* Initiate link re-training */ ++ pci_read_config_word(pdev, 0x50, &config); ++ config |= PCI_EXP_LNKCTL_RL; ++ pci_write_config_word(pdev, 0x50, config); ++ mdelay(50); ++} ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, 0xb150, quirk_bcm56150_gen1); ++DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_BROADCOM, 0xb150, quirk_bcm56150_gen1); ++ + #ifdef CONFIG_PCI_MSI + /* Some chipsets do not support MSI. We cannot easily rely on setting + * PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually +diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c +index 41f08e5..8d1ee41 100644 +--- a/drivers/pci/setup-res.c ++++ b/drivers/pci/setup-res.c +@@ -85,9 +85,9 @@ void pci_update_resource(struct pci_dev *dev, int resno) + } + } + res->flags &= ~IORESOURCE_UNSET; +- dev_info(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n", +- resno, res, (unsigned long long)region.start, +- (unsigned long long)region.end); ++ dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n", ++ resno, res, (unsigned long long)region.start, ++ (unsigned long long)region.end); + } + + int pci_claim_resource(struct pci_dev *dev, int resource) +diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig +index 7f43cf8..cb2c255 100644 +--- a/drivers/platform/x86/Kconfig ++++ b/drivers/platform/x86/Kconfig +@@ -143,6 +143,13 @@ config FUJITSU_LAPTOP_DEBUG + + If you are not sure, say N here. + ++config AMILO_RFKILL ++ tristate "Fujitsu-Siemens Amilo rfkill support" ++ depends on RFKILL ++ ---help--- ++ This is a driver for enabling wifi on some Fujitsu-Siemens Amilo ++ laptops. ++ + config TC1100_WMI + tristate "HP Compaq TC1100 Tablet WMI Extras (EXPERIMENTAL)" + depends on !X86_64 +diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile +index 293a320..3acbaad 100644 +--- a/drivers/platform/x86/Makefile ++++ b/drivers/platform/x86/Makefile +@@ -17,6 +17,7 @@ obj-$(CONFIG_ACER_WMI) += acer-wmi.o + obj-$(CONFIG_ACERHDF) += acerhdf.o + obj-$(CONFIG_HP_ACCEL) += hp_accel.o + obj-$(CONFIG_HP_WMI) += hp-wmi.o ++obj-$(CONFIG_AMILO_RFKILL) += amilo-rfkill.o + obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o + obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o + obj-$(CONFIG_IDEAPAD_LAPTOP) += ideapad-laptop.o +diff --git a/drivers/platform/x86/amilo-rfkill.c b/drivers/platform/x86/amilo-rfkill.c +new file mode 100644 +index 0000000..19170bb +--- /dev/null ++++ b/drivers/platform/x86/amilo-rfkill.c +@@ -0,0 +1,173 @@ ++/* ++ * Support for rfkill on some Fujitsu-Siemens Amilo laptops. ++ * Copyright 2011 Ben Hutchings. ++ * ++ * Based in part on the fsam7440 driver, which is: ++ * Copyright 2005 Alejandro Vidal Mata & Javier Vidal Mata. ++ * and on the fsaa1655g driver, which is: ++ * Copyright 2006 Martin VeÄeÅ™a. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the 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 ++ ++/* ++ * These values were obtained from disassembling and debugging the ++ * PM.exe program installed in the Fujitsu-Siemens AMILO A1655G ++ */ ++#define A1655_WIFI_COMMAND 0x10C5 ++#define A1655_WIFI_ON 0x25 ++#define A1655_WIFI_OFF 0x45 ++ ++static int amilo_a1655_rfkill_set_block(void *data, bool blocked) ++{ ++ u8 param = blocked ? A1655_WIFI_OFF : A1655_WIFI_ON; ++ int rc; ++ ++ i8042_lock_chip(); ++ rc = i8042_command(¶m, A1655_WIFI_COMMAND); ++ i8042_unlock_chip(); ++ return rc; ++} ++ ++static const struct rfkill_ops amilo_a1655_rfkill_ops = { ++ .set_block = amilo_a1655_rfkill_set_block ++}; ++ ++/* ++ * These values were obtained from disassembling the PM.exe program ++ * installed in the Fujitsu-Siemens AMILO M 7440 ++ */ ++#define M7440_PORT1 0x118f ++#define M7440_PORT2 0x118e ++#define M7440_RADIO_ON1 0x12 ++#define M7440_RADIO_ON2 0x80 ++#define M7440_RADIO_OFF1 0x10 ++#define M7440_RADIO_OFF2 0x00 ++ ++static int amilo_m7440_rfkill_set_block(void *data, bool blocked) ++{ ++ u8 val1 = blocked ? M7440_RADIO_OFF1 : M7440_RADIO_ON1; ++ u8 val2 = blocked ? M7440_RADIO_OFF2 : M7440_RADIO_ON2; ++ ++ outb(val1, M7440_PORT1); ++ outb(val2, M7440_PORT2); ++ ++ /* Check whether the state has changed correctly */ ++ if (inb(M7440_PORT1) != val1 || inb(M7440_PORT2) != val2) ++ return -EIO; ++ ++ return 0; ++} ++ ++static const struct rfkill_ops amilo_m7440_rfkill_ops = { ++ .set_block = amilo_m7440_rfkill_set_block ++}; ++ ++static const struct dmi_system_id __devinitdata amilo_rfkill_id_table[] = { ++ { ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), ++ DMI_MATCH(DMI_BOARD_NAME, "AMILO A1655"), ++ }, ++ .driver_data = (void *)&amilo_a1655_rfkill_ops ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), ++ DMI_MATCH(DMI_BOARD_NAME, "AMILO M7440"), ++ }, ++ .driver_data = (void *)&amilo_m7440_rfkill_ops ++ }, ++ {} ++}; ++ ++static struct platform_device *amilo_rfkill_pdev; ++static struct rfkill *amilo_rfkill_dev; ++ ++static int __devinit amilo_rfkill_probe(struct platform_device *device) ++{ ++ const struct dmi_system_id *system_id = ++ dmi_first_match(amilo_rfkill_id_table); ++ int rc; ++ ++ amilo_rfkill_dev = rfkill_alloc(KBUILD_MODNAME, &device->dev, ++ RFKILL_TYPE_WLAN, ++ system_id->driver_data, NULL); ++ if (!amilo_rfkill_dev) ++ return -ENOMEM; ++ ++ rc = rfkill_register(amilo_rfkill_dev); ++ if (rc) ++ goto fail; ++ ++ return 0; ++ ++fail: ++ rfkill_destroy(amilo_rfkill_dev); ++ return rc; ++} ++ ++static int amilo_rfkill_remove(struct platform_device *device) ++{ ++ rfkill_unregister(amilo_rfkill_dev); ++ rfkill_destroy(amilo_rfkill_dev); ++ return 0; ++} ++ ++static struct platform_driver amilo_rfkill_driver = { ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = amilo_rfkill_probe, ++ .remove = amilo_rfkill_remove, ++}; ++ ++static int __init amilo_rfkill_init(void) ++{ ++ int rc; ++ ++ if (dmi_first_match(amilo_rfkill_id_table) == NULL) ++ return -ENODEV; ++ ++ rc = platform_driver_register(&amilo_rfkill_driver); ++ if (rc) ++ return rc; ++ ++ amilo_rfkill_pdev = platform_device_register_simple(KBUILD_MODNAME, -1, ++ NULL, 0); ++ if (IS_ERR(amilo_rfkill_pdev)) { ++ rc = PTR_ERR(amilo_rfkill_pdev); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ platform_driver_unregister(&amilo_rfkill_driver); ++ return rc; ++} ++ ++static void __exit amilo_rfkill_exit(void) ++{ ++ platform_device_unregister(amilo_rfkill_pdev); ++ platform_driver_unregister(&amilo_rfkill_driver); ++} ++ ++MODULE_AUTHOR("Ben Hutchings "); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(dmi, amilo_rfkill_id_table); ++ ++module_init(amilo_rfkill_init); ++module_exit(amilo_rfkill_exit); +diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c +index bc90b09..b7bb5ca 100644 +--- a/drivers/rtc/hctosys.c ++++ b/drivers/rtc/hctosys.c +@@ -24,6 +24,57 @@ + + int rtc_hctosys_ret = -ENODEV; + ++// Approximately the number of seconds in a 42 year span ++#define SECONDS_IN_42_YEARS (42 * 365 * 24 * 3600) ++ ++static int __init rtc_hc_fixup(struct rtc_device *rtc, struct rtc_time *p_tm) ++{ ++ int err = 0; ++ ++ /* ++ * rtc_time_to_tm() converts seconds since 1970-01-01 to a ++ * struct rtc_time. ++ * ++ * Some RTC drivers only store (year % 100) and assume 2000 on ++ * read back. For example when storing 1970, only 70 is ++ * stored in the hardware, but on read back it would be 2070. ++ * ++ * To work around this, pick a default date/time with the ++ * year > 2000. ++ * ++ * Adding 42 years worth of seconds puts the default date/time ++ * near 2012. ++ * ++ * As this code is being written in 2013, a default time ++ * around 2012 is safe to assume. ++ * ++ */ ++ rtc_time_to_tm(SECONDS_IN_42_YEARS, p_tm); ++ err = rtc_set_time(rtc, p_tm); ++ ++ if (err) { ++ dev_err(rtc->dev.parent, ++ "hc_fixup: unable to set hardware clock date/time\n"); ++ return err; ++ } ++ ++ err = rtc_read_time(rtc, p_tm); ++ if (err) { ++ dev_err(rtc->dev.parent, ++ "hc_fixup: unable to read the hardware clock\n"); ++ return err; ++ } ++ ++ err = rtc_valid_tm(p_tm); ++ if (err) { ++ dev_err(rtc->dev.parent, ++ "hc_fixup: unable to fix-up invalid date/time\n"); ++ return err; ++ } ++ ++ return err; ++} ++ + static int __init rtc_hctosys(void) + { + int err = -ENODEV; +@@ -43,15 +94,20 @@ static int __init rtc_hctosys(void) + if (err) { + dev_err(rtc->dev.parent, + "hctosys: unable to read the hardware clock\n"); +- goto err_read; +- ++ err = rtc_hc_fixup(rtc, &tm); ++ if (err) { ++ goto err_read; ++ } + } + + err = rtc_valid_tm(&tm); + if (err) { + dev_err(rtc->dev.parent, + "hctosys: invalid date/time\n"); +- goto err_invalid; ++ err = rtc_hc_fixup(rtc, &tm); ++ if (err) { ++ goto err_invalid; ++ } + } + + rtc_tm_to_time(&tm, &tv.tv_sec); +diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c +index 64aedd8..51a6298 100644 +--- a/drivers/rtc/rtc-m41t80.c ++++ b/drivers/rtc/rtc-m41t80.c +@@ -93,25 +93,32 @@ static int m41t80_get_datetime(struct i2c_client *client, + struct rtc_time *tm) + { + u8 buf[M41T80_DATETIME_REG_SIZE], dt_addr[1] = { M41T80_REG_SEC }; +- struct i2c_msg msgs[] = { +- { +- .addr = client->addr, +- .flags = 0, +- .len = 1, +- .buf = dt_addr, +- }, +- { +- .addr = client->addr, +- .flags = I2C_M_RD, +- .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, +- .buf = buf + M41T80_REG_SEC, +- }, +- }; +- +- if (i2c_transfer(client->adapter, msgs, 2) < 0) { +- dev_err(&client->dev, "read error\n"); +- return -EIO; +- } ++ /* struct i2c_msg msgs[] = { */ ++ /* { */ ++ /* .addr = client->addr, */ ++ /* .flags = 0, */ ++ /* .len = 1, */ ++ /* .buf = dt_addr, */ ++ /* }, */ ++ /* { */ ++ /* .addr = client->addr, */ ++ /* .flags = I2C_M_RD, */ ++ /* .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, */ ++ /* .buf = buf + M41T80_REG_SEC, */ ++ /* }, */ ++ /* }; */ ++ ++ /* if (i2c_transfer(client->adapter, msgs, 2) < 0) { */ ++ /* dev_err(&client->dev, "read error\n"); */ ++ /* return -EIO; */ ++ /* } */ ++ buf[M41T80_REG_YEAR] = i2c_smbus_read_byte_data(client, M41T80_REG_YEAR); ++ buf[M41T80_REG_MON] = i2c_smbus_read_byte_data(client, M41T80_REG_MON); ++ buf[M41T80_REG_WDAY] = i2c_smbus_read_byte_data(client, M41T80_REG_WDAY); ++ buf[M41T80_REG_DAY] = i2c_smbus_read_byte_data(client, M41T80_REG_DAY); ++ buf[M41T80_REG_HOUR] = i2c_smbus_read_byte_data(client, M41T80_REG_HOUR); ++ buf[M41T80_REG_MIN] = i2c_smbus_read_byte_data(client, M41T80_REG_MIN); ++ buf[M41T80_REG_SEC] = i2c_smbus_read_byte_data(client, M41T80_REG_SEC); + + tm->tm_sec = bcd2bin(buf[M41T80_REG_SEC] & 0x7f); + tm->tm_min = bcd2bin(buf[M41T80_REG_MIN] & 0x7f); +@@ -129,36 +136,46 @@ static int m41t80_get_datetime(struct i2c_client *client, + static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm) + { + u8 wbuf[1 + M41T80_DATETIME_REG_SIZE]; ++ int rc = 0; + u8 *buf = &wbuf[1]; + u8 dt_addr[1] = { M41T80_REG_SEC }; +- struct i2c_msg msgs_in[] = { +- { +- .addr = client->addr, +- .flags = 0, +- .len = 1, +- .buf = dt_addr, +- }, +- { +- .addr = client->addr, +- .flags = I2C_M_RD, +- .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, +- .buf = buf + M41T80_REG_SEC, +- }, +- }; +- struct i2c_msg msgs[] = { +- { +- .addr = client->addr, +- .flags = 0, +- .len = 1 + M41T80_DATETIME_REG_SIZE, +- .buf = wbuf, +- }, +- }; ++ /* struct i2c_msg msgs_in[] = { */ ++ /* { */ ++ /* .addr = client->addr, */ ++ /* .flags = 0, */ ++ /* .len = 1, */ ++ /* .buf = dt_addr, */ ++ /* }, */ ++ /* { */ ++ /* .addr = client->addr, */ ++ /* .flags = I2C_M_RD, */ ++ /* .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, */ ++ /* .buf = buf + M41T80_REG_SEC, */ ++ /* }, */ ++ /* }; */ ++ /* struct i2c_msg msgs[] = { */ ++ /* { */ ++ /* .addr = client->addr, */ ++ /* .flags = 0, */ ++ /* .len = 1 + M41T80_DATETIME_REG_SIZE, */ ++ /* .buf = wbuf, */ ++ /* }, */ ++ /* }; */ ++ ++ /* /\* Read current reg values into buf[1..7] *\/ */ ++ /* if (i2c_transfer(client->adapter, msgs_in, 2) < 0) { */ ++ /* dev_err(&client->dev, "read error\n"); */ ++ /* return -EIO; */ ++ /* } */ ++ buf[M41T80_REG_YEAR] = i2c_smbus_read_byte_data(client, M41T80_REG_YEAR); ++ buf[M41T80_REG_MON] = i2c_smbus_read_byte_data(client, M41T80_REG_MON); ++ buf[M41T80_REG_WDAY] = i2c_smbus_read_byte_data(client, M41T80_REG_WDAY); ++ buf[M41T80_REG_DAY] = i2c_smbus_read_byte_data(client, M41T80_REG_DAY); ++ buf[M41T80_REG_HOUR] = i2c_smbus_read_byte_data(client, M41T80_REG_HOUR); ++ buf[M41T80_REG_MIN] = i2c_smbus_read_byte_data(client, M41T80_REG_MIN); ++ buf[M41T80_REG_SEC] = i2c_smbus_read_byte_data(client, M41T80_REG_SEC); ++ + +- /* Read current reg values into buf[1..7] */ +- if (i2c_transfer(client->adapter, msgs_in, 2) < 0) { +- dev_err(&client->dev, "read error\n"); +- return -EIO; +- } + + wbuf[0] = 0; /* offset into rtc's regs */ + /* Merge time-data and register flags into buf[0..7] */ +@@ -178,10 +195,25 @@ static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm) + /* assume 20YY not 19YY */ + buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year % 100); + +- if (i2c_transfer(client->adapter, msgs, 1) != 1) { +- dev_err(&client->dev, "write error\n"); ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_YEAR, buf[M41T80_REG_YEAR]) < 0) + return -EIO; +- } ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_MON, buf[M41T80_REG_MON]) < 0) ++ return -EIO; ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_DAY, buf[M41T80_REG_DAY]) < 0) ++ return -EIO; ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_WDAY, buf[M41T80_REG_WDAY]) < 0) ++ return -EIO; ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_HOUR, buf[M41T80_REG_HOUR]) < 0) ++ return -EIO; ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_MIN, buf[M41T80_REG_MIN]) < 0) ++ return -EIO; ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_SEC, buf[M41T80_REG_SEC]) < 0) ++ return -EIO; ++ ++ /* if (i2c_transfer(client->adapter, msgs, 1) != 1) { */ ++ /* dev_err(&client->dev, "write error\n"); */ ++ /* return -EIO; */ ++ /* } */ + return 0; + } + +@@ -777,8 +809,8 @@ static int m41t80_probe(struct i2c_client *client, + struct rtc_time tm; + struct m41t80_data *clientdata = NULL; + +- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C +- | I2C_FUNC_SMBUS_BYTE_DATA)) { ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { ++ + rc = -ENODEV; + goto exit; + } +diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c +index 768e2ed..0dd8421 100644 +--- a/drivers/rtc/rtc-mv.c ++++ b/drivers/rtc/rtc-mv.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -294,11 +295,19 @@ static int __exit mv_rtc_remove(struct platform_device *pdev) + return 0; + } + ++#ifdef CONFIG_OF ++static struct of_device_id rtc_mv_of_match_table[] = { ++ { .compatible = "mrvl,orion-rtc", }, ++ {} ++}; ++#endif ++ + static struct platform_driver mv_rtc_driver = { + .remove = __exit_p(mv_rtc_remove), + .driver = { + .name = "rtc-mv", + .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(rtc_mv_of_match_table), + }, + }; + +diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c +index f789e00..5208bec 100644 +--- a/drivers/rtc/rtc-s35390a.c ++++ b/drivers/rtc/rtc-s35390a.c +@@ -19,6 +19,8 @@ + #define S35390A_CMD_STATUS1 0 + #define S35390A_CMD_STATUS2 1 + #define S35390A_CMD_TIME1 2 ++#define S35390A_CMD_TIME2 3 ++#define S35390A_CMD_INT2_REG1 5 + + #define S35390A_BYTE_YEAR 0 + #define S35390A_BYTE_MONTH 1 +@@ -28,12 +30,23 @@ + #define S35390A_BYTE_MINS 5 + #define S35390A_BYTE_SECS 6 + ++#define S35390A_ALRM_BYTE_WDAY 0 ++#define S35390A_ALRM_BYTE_HOURS 1 ++#define S35390A_ALRM_BYTE_MINS 2 ++ + #define S35390A_FLAG_POC 0x01 + #define S35390A_FLAG_BLD 0x02 + #define S35390A_FLAG_24H 0x40 + #define S35390A_FLAG_RESET 0x80 + #define S35390A_FLAG_TEST 0x01 + ++#define S35390A_INT2_MODE_MASK 0xF0 ++ ++#define S35390A_INT2_MODE_NOINTR 0x00 ++#define S35390A_INT2_MODE_FREQ 0x10 ++#define S35390A_INT2_MODE_ALARM 0x40 ++#define S35390A_INT2_MODE_PMIN_EDG 0x20 ++ + static const struct i2c_device_id s35390a_id[] = { + { "s35390a", 0 }, + { } +@@ -184,6 +197,104 @@ static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm) + return rtc_valid_tm(tm); + } + ++static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) ++{ ++ struct s35390a *s35390a = i2c_get_clientdata(client); ++ char buf[3], sts = 0; ++ int err, i; ++ ++ dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\ ++ "mon=%d, year=%d, wday=%d\n", __func__, alm->time.tm_sec, ++ alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday, ++ alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); ++ ++ /* disable interrupt */ ++ err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); ++ if (err < 0) ++ return err; ++ ++ /* clear pending interrupt, if any */ ++ err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts)); ++ if (err < 0) ++ return err; ++ ++ if (alm->enabled) ++ sts = S35390A_INT2_MODE_ALARM; ++ else ++ sts = S35390A_INT2_MODE_NOINTR; ++ ++ /* This chip expects the bits of each byte to be in reverse order */ ++ sts = bitrev8(sts); ++ ++ /* set interupt mode*/ ++ err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); ++ if (err < 0) ++ return err; ++ ++ if (alm->time.tm_wday != -1) ++ buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80; ++ ++ buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a, ++ alm->time.tm_hour) | 0x80; ++ buf[S35390A_ALRM_BYTE_MINS] = bin2bcd(alm->time.tm_min) | 0x80; ++ ++ if (alm->time.tm_hour >= 12) ++ buf[S35390A_ALRM_BYTE_HOURS] |= 0x40; ++ ++ for (i = 0; i < 3; ++i) ++ buf[i] = bitrev8(buf[i]); ++ ++ err = s35390a_set_reg(s35390a, S35390A_CMD_INT2_REG1, buf, ++ sizeof(buf)); ++ ++ return err; ++} ++ ++static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) ++{ ++ struct s35390a *s35390a = i2c_get_clientdata(client); ++ char buf[3], sts; ++ int i, err; ++ ++ err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); ++ if (err < 0) ++ return err; ++ ++ if (bitrev8(sts) != S35390A_INT2_MODE_ALARM) ++ return -EINVAL; ++ ++ err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf)); ++ if (err < 0) ++ return err; ++ ++ /* This chip returns the bits of each byte in reverse order */ ++ for (i = 0; i < 3; ++i) { ++ buf[i] = bitrev8(buf[i]); ++ buf[i] &= ~0x80; ++ } ++ ++ alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]); ++ alm->time.tm_hour = s35390a_reg2hr(s35390a, ++ buf[S35390A_ALRM_BYTE_HOURS]); ++ alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]); ++ ++ dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n", ++ __func__, alm->time.tm_min, alm->time.tm_hour, ++ alm->time.tm_wday); ++ ++ return 0; ++} ++ ++static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) ++{ ++ return s35390a_read_alarm(to_i2c_client(dev), alm); ++} ++ ++static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) ++{ ++ return s35390a_set_alarm(to_i2c_client(dev), alm); ++} ++ + static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) + { + return s35390a_get_datetime(to_i2c_client(dev), tm); +@@ -197,6 +308,9 @@ static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm) + static const struct rtc_class_ops s35390a_rtc_ops = { + .read_time = s35390a_rtc_read_time, + .set_time = s35390a_rtc_set_time, ++ .set_alarm = s35390a_rtc_set_alarm, ++ .read_alarm = s35390a_rtc_read_alarm, ++ + }; + + static struct i2c_driver s35390a_driver; +@@ -261,6 +375,8 @@ static int s35390a_probe(struct i2c_client *client, + if (s35390a_get_datetime(client, &tm) < 0) + dev_warn(&client->dev, "clock needs to be set\n"); + ++ device_set_wakeup_capable(&client->dev, 1); ++ + s35390a->rtc = rtc_device_register(s35390a_driver.driver.name, + &client->dev, &s35390a_rtc_ops, THIS_MODULE); + +diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c +index 95b909a..3c03c10 100644 +--- a/drivers/s390/char/sclp_config.c ++++ b/drivers/s390/char/sclp_config.c +@@ -11,7 +11,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + +@@ -31,14 +31,14 @@ static struct work_struct sclp_cpu_change_work; + static void sclp_cpu_capability_notify(struct work_struct *work) + { + int cpu; +- struct sys_device *sysdev; ++ struct device *dev; + + s390_adjust_jiffies(); + pr_warning("cpu capability changed.\n"); + get_online_cpus(); + for_each_online_cpu(cpu) { +- sysdev = get_cpu_sysdev(cpu); +- kobject_uevent(&sysdev->kobj, KOBJ_CHANGE); ++ dev = get_cpu_device(cpu); ++ kobject_uevent(&dev->kobj, KOBJ_CHANGE); + } + put_online_cpus(); + } +diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig +index 06ea3bc..ce6cfd5 100644 +--- a/drivers/scsi/Kconfig ++++ b/drivers/scsi/Kconfig +@@ -584,6 +584,7 @@ config SCSI_ADVANSYS + tristate "AdvanSys SCSI support" + depends on SCSI && VIRT_TO_BUS + depends on ISA || EISA || PCI ++ depends on (!MIPS && !ARM) || BROKEN + help + This is a driver for all SCSI host adapters manufactured by + AdvanSys. It is documented in the kernel source in +@@ -662,6 +663,13 @@ config VMWARE_PVSCSI + To compile this driver as a module, choose M here: the + module will be called vmw_pvscsi. + ++config HYPERV_STORAGE ++ tristate "Microsoft Hyper-V virtual storage driver" ++ depends on SCSI && HYPERV ++ default HYPERV ++ help ++ Select this option to enable the Hyper-V virtual storage driver. ++ + config LIBFC + tristate "LibFC module" + select SCSI_FC_ATTRS +@@ -1902,6 +1910,14 @@ config SCSI_BFA_FC + To compile this driver as a module, choose M here. The module will + be called bfa. + ++config SCSI_VIRTIO ++ tristate "virtio-scsi support (EXPERIMENTAL)" ++ depends on EXPERIMENTAL && VIRTIO ++ help ++ This is the virtual HBA driver for virtio. If the kernel will ++ be used in a virtual machine, say Y or M. ++ ++ + endif # SCSI_LOWLEVEL + + source "drivers/scsi/pcmcia/Kconfig" +diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile +index 2b88749..ad24e06 100644 +--- a/drivers/scsi/Makefile ++++ b/drivers/scsi/Makefile +@@ -141,7 +141,9 @@ obj-$(CONFIG_SCSI_CXGB4_ISCSI) += libiscsi.o libiscsi_tcp.o cxgbi/ + obj-$(CONFIG_SCSI_BNX2_ISCSI) += libiscsi.o bnx2i/ + obj-$(CONFIG_BE2ISCSI) += libiscsi.o be2iscsi/ + obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o ++obj-$(CONFIG_SCSI_VIRTIO) += virtio_scsi.o + obj-$(CONFIG_VMWARE_PVSCSI) += vmw_pvscsi.o ++obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o + + obj-$(CONFIG_ARM) += arm/ + +@@ -170,6 +172,8 @@ scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o + scsi_mod-y += scsi_trace.o + scsi_mod-$(CONFIG_PM) += scsi_pm.o + ++hv_storvsc-y := storvsc_drv.o ++ + scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o + + sd_mod-objs := sd.o +diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c +index bfd618a..6802c7a 100644 +--- a/drivers/scsi/advansys.c ++++ b/drivers/scsi/advansys.c +@@ -4792,8 +4792,6 @@ static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) + + err = request_firmware(&fw, fwname, asc_dvc->drv_ptr->dev); + if (err) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fwname, err); + asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; + return err; + } +@@ -5125,8 +5123,6 @@ static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc) + + err = request_firmware(&fw, fwname, asc_dvc->drv_ptr->dev); + if (err) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fwname, err); + asc_dvc->err_code = ASC_IERR_MCODE_CHKSUM; + return err; + } +@@ -5641,8 +5637,6 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc) + + err = request_firmware(&fw, fwname, asc_dvc->drv_ptr->dev); + if (err) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fwname, err); + asc_dvc->err_code = ASC_IERR_MCODE_CHKSUM; + return err; + } +@@ -6143,8 +6137,6 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) + + err = request_firmware(&fw, fwname, asc_dvc->drv_ptr->dev); + if (err) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fwname, err); + asc_dvc->err_code = ASC_IERR_MCODE_CHKSUM; + return err; + } +diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c +index d5ff142..048be02 100644 +--- a/drivers/scsi/aic94xx/aic94xx_init.c ++++ b/drivers/scsi/aic94xx/aic94xx_init.c +@@ -399,8 +399,6 @@ static ssize_t asd_store_update_bios(struct device *dev, + filename_ptr, + &asd_ha->pcidev->dev); + if (err) { +- asd_printk("Failed to load bios image file %s, error %d\n", +- filename_ptr, err); + err = FAIL_OPEN_BIOS_FILE; + goto out1; + } +diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c +index 390168f..9599edf 100644 +--- a/drivers/scsi/aic94xx/aic94xx_seq.c ++++ b/drivers/scsi/aic94xx/aic94xx_seq.c +@@ -1318,11 +1318,8 @@ int asd_init_seqs(struct asd_ha_struct *asd_ha) + + err = asd_request_firmware(asd_ha); + +- if (err) { +- asd_printk("Failed to load sequencer firmware file %s, error %d\n", +- SAS_RAZOR_SEQUENCER_FW_FILE, err); ++ if (err) + return err; +- } + + err = asd_seq_download_seqs(asd_ha); + if (err) { +diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c +index 633048b..d020f67 100644 +--- a/drivers/scsi/bfa/bfad.c ++++ b/drivers/scsi/bfa/bfad.c +@@ -1592,7 +1592,6 @@ bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image, + const struct firmware *fw; + + if (request_firmware(&fw, fw_name, &pdev->dev)) { +- printk(KERN_ALERT "Can't locate firmware %s\n", fw_name); + *bfi_image = NULL; + goto out; + } +diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c +index 64c8a80..6e8805c 100644 +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -88,8 +88,8 @@ static const struct pci_device_id hpsa_pci_device_id[] = { + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, +- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324a}, +- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324b}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324A}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324B}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3233}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3350}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3351}, +@@ -98,15 +98,36 @@ static const struct pci_device_id hpsa_pci_device_id[] = { + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3354}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3355}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3356}, +- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1920}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1921}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1922}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1923}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1924}, +- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1925}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1926}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1928}, +- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x334d}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1929}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21BD}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21BE}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21BF}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C0}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C1}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C2}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C3}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C4}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C5}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C6}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C7}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C8}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C9}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21CA}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21CB}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21CC}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21CD}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21CE}, ++ {PCI_VENDOR_ID_HP_3PAR, 0x0075, 0x1590, 0x0076}, ++ {PCI_VENDOR_ID_HP_3PAR, 0x0075, 0x1590, 0x0087}, ++ {PCI_VENDOR_ID_HP_3PAR, 0x0075, 0x1590, 0x007D}, ++ {PCI_VENDOR_ID_HP_3PAR, 0x0075, 0x1590, 0x0088}, ++ {PCI_VENDOR_ID_HP, 0x333f, 0x103c, 0x333f}, + {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, + {0,} +@@ -124,8 +145,9 @@ static struct board_type products[] = { + {0x3245103C, "Smart Array P410i", &SA5_access}, + {0x3247103C, "Smart Array P411", &SA5_access}, + {0x3249103C, "Smart Array P812", &SA5_access}, +- {0x324a103C, "Smart Array P712m", &SA5_access}, +- {0x324b103C, "Smart Array P711m", &SA5_access}, ++ {0x324A103C, "Smart Array P712m", &SA5_access}, ++ {0x324B103C, "Smart Array P711m", &SA5_access}, ++ {0x3233103C, "HP StorageWorks 1210m", &SA5_access}, /* alias of 333f */ + {0x3350103C, "Smart Array P222", &SA5_access}, + {0x3351103C, "Smart Array P420", &SA5_access}, + {0x3352103C, "Smart Array P421", &SA5_access}, +@@ -133,15 +155,36 @@ static struct board_type products[] = { + {0x3354103C, "Smart Array P420i", &SA5_access}, + {0x3355103C, "Smart Array P220i", &SA5_access}, + {0x3356103C, "Smart Array P721m", &SA5_access}, +- {0x1920103C, "Smart Array", &SA5_access}, +- {0x1921103C, "Smart Array", &SA5_access}, +- {0x1922103C, "Smart Array", &SA5_access}, +- {0x1923103C, "Smart Array", &SA5_access}, +- {0x1924103C, "Smart Array", &SA5_access}, +- {0x1925103C, "Smart Array", &SA5_access}, +- {0x1926103C, "Smart Array", &SA5_access}, +- {0x1928103C, "Smart Array", &SA5_access}, +- {0x334d103C, "Smart Array P822se", &SA5_access}, ++ {0x1921103C, "Smart Array P830i", &SA5_access}, ++ {0x1922103C, "Smart Array P430", &SA5_access}, ++ {0x1923103C, "Smart Array P431", &SA5_access}, ++ {0x1924103C, "Smart Array P830", &SA5_access}, ++ {0x1926103C, "Smart Array P731m", &SA5_access}, ++ {0x1928103C, "Smart Array P230i", &SA5_access}, ++ {0x1929103C, "Smart Array P530", &SA5_access}, ++ {0x21BD103C, "Smart Array P244br", &SA5_access}, ++ {0x21BE103C, "Smart Array P741m", &SA5_access}, ++ {0x21BF103C, "Smart HBA H240ar", &SA5_access}, ++ {0x21C0103C, "Smart Array P440ar", &SA5_access}, ++ {0x21C1103C, "Smart Array P840ar", &SA5_access}, ++ {0x21C2103C, "Smart Array P440", &SA5_access}, ++ {0x21C3103C, "Smart Array P441", &SA5_access}, ++ {0x21C4103C, "Smart Array", &SA5_access}, ++ {0x21C5103C, "Smart Array P841", &SA5_access}, ++ {0x21C6103C, "Smart HBA H244br", &SA5_access}, ++ {0x21C7103C, "Smart HBA H240", &SA5_access}, ++ {0x21C8103C, "Smart HBA H241", &SA5_access}, ++ {0x21C9103C, "Smart Array", &SA5_access}, ++ {0x21CA103C, "Smart Array P246br", &SA5_access}, ++ {0x21CB103C, "Smart Array P840", &SA5_access}, ++ {0x21CC103C, "Smart Array", &SA5_access}, ++ {0x21CD103C, "Smart Array", &SA5_access}, ++ {0x21CE103C, "Smart HBA", &SA5_access}, ++ {0x00761590, "HP Storage P1224 Array Controller", &SA5_access}, ++ {0x00871590, "HP Storage P1224e Array Controller", &SA5_access}, ++ {0x007D1590, "HP Storage P1228 Array Controller", &SA5_access}, ++ {0x00881590, "HP Storage P1228e Array Controller", &SA5_access}, ++ {0x333f103c, "HP StorageWorks 1210m Array Controller", &SA5_access}, + {0xFFFF103C, "Unknown Smart Array", &SA5_access}, + }; + +diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c +index fd860d9..3422507 100644 +--- a/drivers/scsi/ipr.c ++++ b/drivers/scsi/ipr.c +@@ -3744,10 +3744,8 @@ static ssize_t ipr_store_update_fw(struct device *dev, + len = snprintf(fname, 99, "%s", buf); + fname[len-1] = '\0'; + +- if(request_firmware(&fw_entry, fname, &ioa_cfg->pdev->dev)) { +- dev_err(&ioa_cfg->pdev->dev, "Firmware file %s not found\n", fname); ++ if (request_firmware(&fw_entry, fname, &ioa_cfg->pdev->dev)) + return -EIO; +- } + + image_hdr = (struct ipr_ucode_image_header *)fw_entry->data; + +diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c +index 6f58919..292f3d9 100644 +--- a/drivers/scsi/mvsas/mv_init.c ++++ b/drivers/scsi/mvsas/mv_init.c +@@ -732,6 +732,15 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = { + .class_mask = 0, + .driver_data = chip_9485, + }, ++ { ++ .vendor = 0x1b4b, ++ .device = 0x9485, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = 0x9485, ++ .class = 0, ++ .class_mask = 0, ++ .driver_data = chip_9485, ++ }, + { PCI_VDEVICE(OCZ, 0x1021), chip_9485}, /* OCZ RevoDrive3 */ + { PCI_VDEVICE(OCZ, 0x1022), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ + { PCI_VDEVICE(OCZ, 0x1040), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */ +diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c +index 45bc197..1e5a782 100644 +--- a/drivers/scsi/pm8001/pm8001_ctl.c ++++ b/drivers/scsi/pm8001/pm8001_ctl.c +@@ -502,9 +502,6 @@ static ssize_t pm8001_store_update_fw(struct device *cdev, + pm8001_ha->dev); + + if (err) { +- PM8001_FAIL_DBG(pm8001_ha, +- pm8001_printk("Failed to load firmware image file %s," +- " error %d\n", filename_ptr, err)); + err = FAIL_OPEN_BIOS_FILE; + goto out1; + } +diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c +index d838205..1d68408 100644 +--- a/drivers/scsi/qla1280.c ++++ b/drivers/scsi/qla1280.c +@@ -1561,8 +1561,6 @@ qla1280_request_firmware(struct scsi_qla_host *ha) + err = request_firmware(&fw, fwname, &ha->pdev->dev); + + if (err) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fwname, err); + fw = ERR_PTR(err); + goto unlock; + } +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index 54ea68c..42ddc24 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -4725,8 +4725,6 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) + /* Load firmware blob. */ + blob = qla2x00_request_firmware(vha); + if (!blob) { +- ql_log(ql_log_info, vha, 0x0083, +- "Fimware image unavailable.\n"); + ql_log(ql_log_info, vha, 0x0084, + "Firmware images can be retrieved from: "QLA_FW_URL ".\n"); + return QLA_FUNCTION_FAILED; +@@ -4827,8 +4825,6 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) + /* Load firmware blob. */ + blob = qla2x00_request_firmware(vha); + if (!blob) { +- ql_log(ql_log_warn, vha, 0x0090, +- "Fimware image unavailable.\n"); + ql_log(ql_log_warn, vha, 0x0091, + "Firmware images can be retrieved from: " + QLA_FW_URL ".\n"); +diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c +index 0355493..fac6eab 100644 +--- a/drivers/scsi/qla2xxx/qla_nx.c ++++ b/drivers/scsi/qla2xxx/qla_nx.c +@@ -2466,11 +2466,8 @@ try_blob_fw: + + /* Load firmware blob. */ + blob = ha->hablob = qla2x00_request_firmware(vha); +- if (!blob) { +- ql_log(ql_log_fatal, vha, 0x00a3, +- "Firmware image not preset.\n"); ++ if (!blob) + goto fw_load_failed; +- } + + /* Validating firmware blob */ + if (qla82xx_validate_firmware_blob(vha, +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index 82a5ca6..8ac361d 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -3967,8 +3967,6 @@ qla2x00_request_firmware(scsi_qla_host_t *vha) + goto out; + + if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) { +- ql_log(ql_log_warn, vha, 0x0063, +- "Failed to load firmware image (%s).\n", blob->name); + blob->fw = NULL; + blob = NULL; + goto out; +diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c +index e40dc1c..960504c 100644 +--- a/drivers/scsi/qlogicpti.c ++++ b/drivers/scsi/qlogicpti.c +@@ -476,11 +476,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) + int i, timeout; + + err = request_firmware(&fw, fwname, &qpti->op->dev); +- if (err) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fwname, err); ++ if (err) + return err; +- } + if (fw->size % 2) { + printk(KERN_ERR "Bogus length %zu in image \"%s\"\n", + fw->size, fwname); +diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c +index 29f5751..8a713d1 100644 +--- a/drivers/scsi/scsi_scan.c ++++ b/drivers/scsi/scsi_scan.c +@@ -445,6 +445,8 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, + } + dev = &starget->dev; + device_initialize(dev); ++ /* bwh: assert binary compatibility */ ++ BUILD_BUG_ON(sizeof(starget->reap_ref) != sizeof(unsigned int)); + kref_init(&starget->reap_ref); + dev->parent = get_device(parent); + dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id); +diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c +new file mode 100644 +index 0000000..860786b +--- /dev/null ++++ b/drivers/scsi/storvsc_drv.c +@@ -0,0 +1,1566 @@ ++/* ++ * Copyright (c) 2009, Microsoft Corporation. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple ++ * Place - Suite 330, Boston, MA 02111-1307 USA. ++ * ++ * Authors: ++ * Haiyang Zhang ++ * Hank Janssen ++ * K. Y. Srinivasan ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * All wire protocol details (storage protocol between the guest and the host) ++ * are consolidated here. ++ * ++ * Begin protocol definitions. ++ */ ++ ++/* ++ * Version history: ++ * V1 Beta: 0.1 ++ * V1 RC < 2008/1/31: 1.0 ++ * V1 RC > 2008/1/31: 2.0 ++ * Win7: 4.2 ++ */ ++ ++#define VMSTOR_CURRENT_MAJOR 4 ++#define VMSTOR_CURRENT_MINOR 2 ++ ++ ++/* Packet structure describing virtual storage requests. */ ++enum vstor_packet_operation { ++ VSTOR_OPERATION_COMPLETE_IO = 1, ++ VSTOR_OPERATION_REMOVE_DEVICE = 2, ++ VSTOR_OPERATION_EXECUTE_SRB = 3, ++ VSTOR_OPERATION_RESET_LUN = 4, ++ VSTOR_OPERATION_RESET_ADAPTER = 5, ++ VSTOR_OPERATION_RESET_BUS = 6, ++ VSTOR_OPERATION_BEGIN_INITIALIZATION = 7, ++ VSTOR_OPERATION_END_INITIALIZATION = 8, ++ VSTOR_OPERATION_QUERY_PROTOCOL_VERSION = 9, ++ VSTOR_OPERATION_QUERY_PROPERTIES = 10, ++ VSTOR_OPERATION_ENUMERATE_BUS = 11, ++ VSTOR_OPERATION_MAXIMUM = 11 ++}; ++ ++/* ++ * Platform neutral description of a scsi request - ++ * this remains the same across the write regardless of 32/64 bit ++ * note: it's patterned off the SCSI_PASS_THROUGH structure ++ */ ++#define STORVSC_MAX_CMD_LEN 0x10 ++#define STORVSC_SENSE_BUFFER_SIZE 0x12 ++#define STORVSC_MAX_BUF_LEN_WITH_PADDING 0x14 ++ ++struct vmscsi_request { ++ u16 length; ++ u8 srb_status; ++ u8 scsi_status; ++ ++ u8 port_number; ++ u8 path_id; ++ u8 target_id; ++ u8 lun; ++ ++ u8 cdb_length; ++ u8 sense_info_length; ++ u8 data_in; ++ u8 reserved; ++ ++ u32 data_transfer_length; ++ ++ union { ++ u8 cdb[STORVSC_MAX_CMD_LEN]; ++ u8 sense_data[STORVSC_SENSE_BUFFER_SIZE]; ++ u8 reserved_array[STORVSC_MAX_BUF_LEN_WITH_PADDING]; ++ }; ++} __attribute((packed)); ++ ++ ++/* ++ * This structure is sent during the intialization phase to get the different ++ * properties of the channel. ++ */ ++struct vmstorage_channel_properties { ++ u16 protocol_version; ++ u8 path_id; ++ u8 target_id; ++ ++ /* Note: port number is only really known on the client side */ ++ u32 port_number; ++ u32 flags; ++ u32 max_transfer_bytes; ++ ++ /* ++ * This id is unique for each channel and will correspond with ++ * vendor specific data in the inquiry data. ++ */ ++ ++ u64 unique_id; ++} __packed; ++ ++/* This structure is sent during the storage protocol negotiations. */ ++struct vmstorage_protocol_version { ++ /* Major (MSW) and minor (LSW) version numbers. */ ++ u16 major_minor; ++ ++ /* ++ * Revision number is auto-incremented whenever this file is changed ++ * (See FILL_VMSTOR_REVISION macro above). Mismatch does not ++ * definitely indicate incompatibility--but it does indicate mismatched ++ * builds. ++ * This is only used on the windows side. Just set it to 0. ++ */ ++ u16 revision; ++} __packed; ++ ++/* Channel Property Flags */ ++#define STORAGE_CHANNEL_REMOVABLE_FLAG 0x1 ++#define STORAGE_CHANNEL_EMULATED_IDE_FLAG 0x2 ++ ++struct vstor_packet { ++ /* Requested operation type */ ++ enum vstor_packet_operation operation; ++ ++ /* Flags - see below for values */ ++ u32 flags; ++ ++ /* Status of the request returned from the server side. */ ++ u32 status; ++ ++ /* Data payload area */ ++ union { ++ /* ++ * Structure used to forward SCSI commands from the ++ * client to the server. ++ */ ++ struct vmscsi_request vm_srb; ++ ++ /* Structure used to query channel properties. */ ++ struct vmstorage_channel_properties storage_channel_properties; ++ ++ /* Used during version negotiations. */ ++ struct vmstorage_protocol_version version; ++ }; ++} __packed; ++ ++/* ++ * Packet Flags: ++ * ++ * This flag indicates that the server should send back a completion for this ++ * packet. ++ */ ++ ++#define REQUEST_COMPLETION_FLAG 0x1 ++ ++/* Matches Windows-end */ ++enum storvsc_request_type { ++ WRITE_TYPE = 0, ++ READ_TYPE, ++ UNKNOWN_TYPE, ++}; ++ ++/* ++ * SRB status codes and masks; a subset of the codes used here. ++ */ ++ ++#define SRB_STATUS_AUTOSENSE_VALID 0x80 ++#define SRB_STATUS_INVALID_LUN 0x20 ++#define SRB_STATUS_SUCCESS 0x01 ++#define SRB_STATUS_ERROR 0x04 ++ ++/* ++ * This is the end of Protocol specific defines. ++ */ ++ ++ ++/* ++ * We setup a mempool to allocate request structures for this driver ++ * on a per-lun basis. The following define specifies the number of ++ * elements in the pool. ++ */ ++ ++#define STORVSC_MIN_BUF_NR 64 ++static int storvsc_ringbuffer_size = (20 * PAGE_SIZE); ++ ++module_param(storvsc_ringbuffer_size, int, S_IRUGO); ++MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); ++ ++#define STORVSC_MAX_IO_REQUESTS 128 ++ ++/* ++ * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In ++ * reality, the path/target is not used (ie always set to 0) so our ++ * scsi host adapter essentially has 1 bus with 1 target that contains ++ * up to 256 luns. ++ */ ++#define STORVSC_MAX_LUNS_PER_TARGET 64 ++#define STORVSC_MAX_TARGETS 1 ++#define STORVSC_MAX_CHANNELS 1 ++ ++ ++ ++struct storvsc_cmd_request { ++ struct list_head entry; ++ struct scsi_cmnd *cmd; ++ ++ unsigned int bounce_sgl_count; ++ struct scatterlist *bounce_sgl; ++ ++ struct hv_device *device; ++ ++ /* Synchronize the request/response if needed */ ++ struct completion wait_event; ++ ++ unsigned char *sense_buffer; ++ struct hv_multipage_buffer data_buffer; ++ struct vstor_packet vstor_packet; ++}; ++ ++ ++/* A storvsc device is a device object that contains a vmbus channel */ ++struct storvsc_device { ++ struct hv_device *device; ++ ++ bool destroy; ++ bool drain_notify; ++ atomic_t num_outstanding_req; ++ struct Scsi_Host *host; ++ ++ wait_queue_head_t waiting_to_drain; ++ ++ /* ++ * Each unique Port/Path/Target represents 1 channel ie scsi ++ * controller. In reality, the pathid, targetid is always 0 ++ * and the port is set by us ++ */ ++ unsigned int port_number; ++ unsigned char path_id; ++ unsigned char target_id; ++ ++ /* Used for vsc/vsp channel reset process */ ++ struct storvsc_cmd_request init_request; ++ struct storvsc_cmd_request reset_request; ++}; ++ ++struct stor_mem_pools { ++ struct kmem_cache *request_pool; ++ mempool_t *request_mempool; ++}; ++ ++struct hv_host_device { ++ struct hv_device *dev; ++ unsigned int port; ++ unsigned char path; ++ unsigned char target; ++}; ++ ++struct storvsc_scan_work { ++ struct work_struct work; ++ struct Scsi_Host *host; ++ uint lun; ++}; ++ ++static void storvsc_bus_scan(struct work_struct *work) ++{ ++ struct storvsc_scan_work *wrk; ++ int id, order_id; ++ ++ wrk = container_of(work, struct storvsc_scan_work, work); ++ for (id = 0; id < wrk->host->max_id; ++id) { ++ if (wrk->host->reverse_ordering) ++ order_id = wrk->host->max_id - id - 1; ++ else ++ order_id = id; ++ ++ scsi_scan_target(&wrk->host->shost_gendev, 0, ++ order_id, SCAN_WILD_CARD, 1); ++ } ++ kfree(wrk); ++} ++ ++static void storvsc_remove_lun(struct work_struct *work) ++{ ++ struct storvsc_scan_work *wrk; ++ struct scsi_device *sdev; ++ ++ wrk = container_of(work, struct storvsc_scan_work, work); ++ if (!scsi_host_get(wrk->host)) ++ goto done; ++ ++ sdev = scsi_device_lookup(wrk->host, 0, 0, wrk->lun); ++ ++ if (sdev) { ++ scsi_remove_device(sdev); ++ scsi_device_put(sdev); ++ } ++ scsi_host_put(wrk->host); ++ ++done: ++ kfree(wrk); ++} ++ ++/* ++ * Major/minor macros. Minor version is in LSB, meaning that earlier flat ++ * version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). ++ */ ++ ++static inline u16 storvsc_get_version(u8 major, u8 minor) ++{ ++ u16 version; ++ ++ version = ((major << 8) | minor); ++ return version; ++} ++ ++/* ++ * We can get incoming messages from the host that are not in response to ++ * messages that we have sent out. An example of this would be messages ++ * received by the guest to notify dynamic addition/removal of LUNs. To ++ * deal with potential race conditions where the driver may be in the ++ * midst of being unloaded when we might receive an unsolicited message ++ * from the host, we have implemented a mechanism to gurantee sequential ++ * consistency: ++ * ++ * 1) Once the device is marked as being destroyed, we will fail all ++ * outgoing messages. ++ * 2) We permit incoming messages when the device is being destroyed, ++ * only to properly account for messages already sent out. ++ */ ++ ++static inline struct storvsc_device *get_out_stor_device( ++ struct hv_device *device) ++{ ++ struct storvsc_device *stor_device; ++ ++ stor_device = hv_get_drvdata(device); ++ ++ if (stor_device && stor_device->destroy) ++ stor_device = NULL; ++ ++ return stor_device; ++} ++ ++ ++static inline void storvsc_wait_to_drain(struct storvsc_device *dev) ++{ ++ dev->drain_notify = true; ++ wait_event(dev->waiting_to_drain, ++ atomic_read(&dev->num_outstanding_req) == 0); ++ dev->drain_notify = false; ++} ++ ++static inline struct storvsc_device *get_in_stor_device( ++ struct hv_device *device) ++{ ++ struct storvsc_device *stor_device; ++ ++ stor_device = hv_get_drvdata(device); ++ ++ if (!stor_device) ++ goto get_in_err; ++ ++ /* ++ * If the device is being destroyed; allow incoming ++ * traffic only to cleanup outstanding requests. ++ */ ++ ++ if (stor_device->destroy && ++ (atomic_read(&stor_device->num_outstanding_req) == 0)) ++ stor_device = NULL; ++ ++get_in_err: ++ return stor_device; ++ ++} ++ ++static void destroy_bounce_buffer(struct scatterlist *sgl, ++ unsigned int sg_count) ++{ ++ int i; ++ struct page *page_buf; ++ ++ for (i = 0; i < sg_count; i++) { ++ page_buf = sg_page((&sgl[i])); ++ if (page_buf != NULL) ++ __free_page(page_buf); ++ } ++ ++ kfree(sgl); ++} ++ ++static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count) ++{ ++ int i; ++ ++ /* No need to check */ ++ if (sg_count < 2) ++ return -1; ++ ++ /* We have at least 2 sg entries */ ++ for (i = 0; i < sg_count; i++) { ++ if (i == 0) { ++ /* make sure 1st one does not have hole */ ++ if (sgl[i].offset + sgl[i].length != PAGE_SIZE) ++ return i; ++ } else if (i == sg_count - 1) { ++ /* make sure last one does not have hole */ ++ if (sgl[i].offset != 0) ++ return i; ++ } else { ++ /* make sure no hole in the middle */ ++ if (sgl[i].length != PAGE_SIZE || sgl[i].offset != 0) ++ return i; ++ } ++ } ++ return -1; ++} ++ ++static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl, ++ unsigned int sg_count, ++ unsigned int len, ++ int write) ++{ ++ int i; ++ int num_pages; ++ struct scatterlist *bounce_sgl; ++ struct page *page_buf; ++ unsigned int buf_len = ((write == WRITE_TYPE) ? 0 : PAGE_SIZE); ++ ++ num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT; ++ ++ bounce_sgl = kcalloc(num_pages, sizeof(struct scatterlist), GFP_ATOMIC); ++ if (!bounce_sgl) ++ return NULL; ++ ++ sg_init_table(bounce_sgl, num_pages); ++ for (i = 0; i < num_pages; i++) { ++ page_buf = alloc_page(GFP_ATOMIC); ++ if (!page_buf) ++ goto cleanup; ++ sg_set_page(&bounce_sgl[i], page_buf, buf_len, 0); ++ } ++ ++ return bounce_sgl; ++ ++cleanup: ++ destroy_bounce_buffer(bounce_sgl, num_pages); ++ return NULL; ++} ++ ++/* Disgusting wrapper functions */ ++static inline unsigned long sg_kmap_atomic(struct scatterlist *sgl, int idx) ++{ ++ void *addr = kmap_atomic(sg_page(sgl + idx)); ++ return (unsigned long)addr; ++} ++ ++static inline void sg_kunmap_atomic(unsigned long addr) ++{ ++ kunmap_atomic((void *)addr); ++} ++ ++ ++/* Assume the original sgl has enough room */ ++static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, ++ struct scatterlist *bounce_sgl, ++ unsigned int orig_sgl_count, ++ unsigned int bounce_sgl_count) ++{ ++ int i; ++ int j = 0; ++ unsigned long src, dest; ++ unsigned int srclen, destlen, copylen; ++ unsigned int total_copied = 0; ++ unsigned long bounce_addr = 0; ++ unsigned long dest_addr = 0; ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ for (i = 0; i < orig_sgl_count; i++) { ++ dest_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset; ++ dest = dest_addr; ++ destlen = orig_sgl[i].length; ++ ++ if (bounce_addr == 0) ++ bounce_addr = sg_kmap_atomic(bounce_sgl,j); ++ ++ while (destlen) { ++ src = bounce_addr + bounce_sgl[j].offset; ++ srclen = bounce_sgl[j].length - bounce_sgl[j].offset; ++ ++ copylen = min(srclen, destlen); ++ memcpy((void *)dest, (void *)src, copylen); ++ ++ total_copied += copylen; ++ bounce_sgl[j].offset += copylen; ++ destlen -= copylen; ++ dest += copylen; ++ ++ if (bounce_sgl[j].offset == bounce_sgl[j].length) { ++ /* full */ ++ sg_kunmap_atomic(bounce_addr); ++ j++; ++ ++ /* ++ * It is possible that the number of elements ++ * in the bounce buffer may not be equal to ++ * the number of elements in the original ++ * scatter list. Handle this correctly. ++ */ ++ ++ if (j == bounce_sgl_count) { ++ /* ++ * We are done; cleanup and return. ++ */ ++ sg_kunmap_atomic(dest_addr - orig_sgl[i].offset); ++ local_irq_restore(flags); ++ return total_copied; ++ } ++ ++ /* if we need to use another bounce buffer */ ++ if (destlen || i != orig_sgl_count - 1) ++ bounce_addr = sg_kmap_atomic(bounce_sgl,j); ++ } else if (destlen == 0 && i == orig_sgl_count - 1) { ++ /* unmap the last bounce that is < PAGE_SIZE */ ++ sg_kunmap_atomic(bounce_addr); ++ } ++ } ++ ++ sg_kunmap_atomic(dest_addr - orig_sgl[i].offset); ++ } ++ ++ local_irq_restore(flags); ++ ++ return total_copied; ++} ++ ++/* Assume the bounce_sgl has enough room ie using the create_bounce_buffer() */ ++static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, ++ struct scatterlist *bounce_sgl, ++ unsigned int orig_sgl_count) ++{ ++ int i; ++ int j = 0; ++ unsigned long src, dest; ++ unsigned int srclen, destlen, copylen; ++ unsigned int total_copied = 0; ++ unsigned long bounce_addr = 0; ++ unsigned long src_addr = 0; ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ for (i = 0; i < orig_sgl_count; i++) { ++ src_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset; ++ src = src_addr; ++ srclen = orig_sgl[i].length; ++ ++ if (bounce_addr == 0) ++ bounce_addr = sg_kmap_atomic(bounce_sgl,j); ++ ++ while (srclen) { ++ /* assume bounce offset always == 0 */ ++ dest = bounce_addr + bounce_sgl[j].length; ++ destlen = PAGE_SIZE - bounce_sgl[j].length; ++ ++ copylen = min(srclen, destlen); ++ memcpy((void *)dest, (void *)src, copylen); ++ ++ total_copied += copylen; ++ bounce_sgl[j].length += copylen; ++ srclen -= copylen; ++ src += copylen; ++ ++ if (bounce_sgl[j].length == PAGE_SIZE) { ++ /* full..move to next entry */ ++ sg_kunmap_atomic(bounce_addr); ++ j++; ++ ++ /* if we need to use another bounce buffer */ ++ if (srclen || i != orig_sgl_count - 1) ++ bounce_addr = sg_kmap_atomic(bounce_sgl,j); ++ ++ } else if (srclen == 0 && i == orig_sgl_count - 1) { ++ /* unmap the last bounce that is < PAGE_SIZE */ ++ sg_kunmap_atomic(bounce_addr); ++ } ++ } ++ ++ sg_kunmap_atomic(src_addr - orig_sgl[i].offset); ++ } ++ ++ local_irq_restore(flags); ++ ++ return total_copied; ++} ++ ++static int storvsc_channel_init(struct hv_device *device) ++{ ++ struct storvsc_device *stor_device; ++ struct storvsc_cmd_request *request; ++ struct vstor_packet *vstor_packet; ++ int ret, t; ++ ++ stor_device = get_out_stor_device(device); ++ if (!stor_device) ++ return -ENODEV; ++ ++ request = &stor_device->init_request; ++ vstor_packet = &request->vstor_packet; ++ ++ /* ++ * Now, initiate the vsc/vsp initialization protocol on the open ++ * channel ++ */ ++ memset(request, 0, sizeof(struct storvsc_cmd_request)); ++ init_completion(&request->wait_event); ++ vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; ++ vstor_packet->flags = REQUEST_COMPLETION_FLAG; ++ ++ ret = vmbus_sendpacket(device->channel, vstor_packet, ++ sizeof(struct vstor_packet), ++ (unsigned long)request, ++ VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ if (ret != 0) ++ goto cleanup; ++ ++ t = wait_for_completion_timeout(&request->wait_event, 5*HZ); ++ if (t == 0) { ++ ret = -ETIMEDOUT; ++ goto cleanup; ++ } ++ ++ if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || ++ vstor_packet->status != 0) ++ goto cleanup; ++ ++ ++ /* reuse the packet for version range supported */ ++ memset(vstor_packet, 0, sizeof(struct vstor_packet)); ++ vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; ++ vstor_packet->flags = REQUEST_COMPLETION_FLAG; ++ ++ vstor_packet->version.major_minor = ++ storvsc_get_version(VMSTOR_CURRENT_MAJOR, VMSTOR_CURRENT_MINOR); ++ ++ /* ++ * The revision number is only used in Windows; set it to 0. ++ */ ++ vstor_packet->version.revision = 0; ++ ++ ret = vmbus_sendpacket(device->channel, vstor_packet, ++ sizeof(struct vstor_packet), ++ (unsigned long)request, ++ VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ if (ret != 0) ++ goto cleanup; ++ ++ t = wait_for_completion_timeout(&request->wait_event, 5*HZ); ++ if (t == 0) { ++ ret = -ETIMEDOUT; ++ goto cleanup; ++ } ++ ++ if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || ++ vstor_packet->status != 0) ++ goto cleanup; ++ ++ ++ memset(vstor_packet, 0, sizeof(struct vstor_packet)); ++ vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES; ++ vstor_packet->flags = REQUEST_COMPLETION_FLAG; ++ vstor_packet->storage_channel_properties.port_number = ++ stor_device->port_number; ++ ++ ret = vmbus_sendpacket(device->channel, vstor_packet, ++ sizeof(struct vstor_packet), ++ (unsigned long)request, ++ VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ ++ if (ret != 0) ++ goto cleanup; ++ ++ t = wait_for_completion_timeout(&request->wait_event, 5*HZ); ++ if (t == 0) { ++ ret = -ETIMEDOUT; ++ goto cleanup; ++ } ++ ++ if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || ++ vstor_packet->status != 0) ++ goto cleanup; ++ ++ stor_device->path_id = vstor_packet->storage_channel_properties.path_id; ++ stor_device->target_id ++ = vstor_packet->storage_channel_properties.target_id; ++ ++ memset(vstor_packet, 0, sizeof(struct vstor_packet)); ++ vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION; ++ vstor_packet->flags = REQUEST_COMPLETION_FLAG; ++ ++ ret = vmbus_sendpacket(device->channel, vstor_packet, ++ sizeof(struct vstor_packet), ++ (unsigned long)request, ++ VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ ++ if (ret != 0) ++ goto cleanup; ++ ++ t = wait_for_completion_timeout(&request->wait_event, 5*HZ); ++ if (t == 0) { ++ ret = -ETIMEDOUT; ++ goto cleanup; ++ } ++ ++ if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || ++ vstor_packet->status != 0) ++ goto cleanup; ++ ++ ++cleanup: ++ return ret; ++} ++ ++ ++static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) ++{ ++ struct scsi_cmnd *scmnd = cmd_request->cmd; ++ struct hv_host_device *host_dev = shost_priv(scmnd->device->host); ++ void (*scsi_done_fn)(struct scsi_cmnd *); ++ struct scsi_sense_hdr sense_hdr; ++ struct vmscsi_request *vm_srb; ++ struct storvsc_scan_work *wrk; ++ struct stor_mem_pools *memp = scmnd->device->hostdata; ++ ++ vm_srb = &cmd_request->vstor_packet.vm_srb; ++ if (cmd_request->bounce_sgl_count) { ++ if (vm_srb->data_in == READ_TYPE) ++ copy_from_bounce_buffer(scsi_sglist(scmnd), ++ cmd_request->bounce_sgl, ++ scsi_sg_count(scmnd), ++ cmd_request->bounce_sgl_count); ++ destroy_bounce_buffer(cmd_request->bounce_sgl, ++ cmd_request->bounce_sgl_count); ++ } ++ ++ /* ++ * If there is an error; offline the device since all ++ * error recovery strategies would have already been ++ * deployed on the host side. ++ */ ++ if (vm_srb->srb_status == SRB_STATUS_ERROR) ++ scmnd->result = DID_TARGET_FAILURE << 16; ++ else ++ scmnd->result = vm_srb->scsi_status; ++ ++ /* ++ * If the LUN is invalid; remove the device. ++ */ ++ if (vm_srb->srb_status == SRB_STATUS_INVALID_LUN) { ++ struct storvsc_device *stor_dev; ++ struct hv_device *dev = host_dev->dev; ++ struct Scsi_Host *host; ++ ++ stor_dev = get_in_stor_device(dev); ++ host = stor_dev->host; ++ ++ wrk = kmalloc(sizeof(struct storvsc_scan_work), ++ GFP_ATOMIC); ++ if (!wrk) { ++ scmnd->result = DID_TARGET_FAILURE << 16; ++ } else { ++ wrk->host = host; ++ wrk->lun = vm_srb->lun; ++ INIT_WORK(&wrk->work, storvsc_remove_lun); ++ schedule_work(&wrk->work); ++ } ++ } ++ ++ if (scmnd->result) { ++ if (scsi_normalize_sense(scmnd->sense_buffer, ++ SCSI_SENSE_BUFFERSIZE, &sense_hdr)) ++ scsi_print_sense_hdr("storvsc", &sense_hdr); ++ } ++ ++ scsi_set_resid(scmnd, ++ cmd_request->data_buffer.len - ++ vm_srb->data_transfer_length); ++ ++ scsi_done_fn = scmnd->scsi_done; ++ ++ scmnd->host_scribble = NULL; ++ scmnd->scsi_done = NULL; ++ ++ scsi_done_fn(scmnd); ++ ++ mempool_free(cmd_request, memp->request_mempool); ++} ++ ++static void storvsc_on_io_completion(struct hv_device *device, ++ struct vstor_packet *vstor_packet, ++ struct storvsc_cmd_request *request) ++{ ++ struct storvsc_device *stor_device; ++ struct vstor_packet *stor_pkt; ++ ++ stor_device = hv_get_drvdata(device); ++ stor_pkt = &request->vstor_packet; ++ ++ /* ++ * The current SCSI handling on the host side does ++ * not correctly handle: ++ * INQUIRY command with page code parameter set to 0x80 ++ * MODE_SENSE command with cmd[2] == 0x1c ++ * ++ * Setup srb and scsi status so this won't be fatal. ++ * We do this so we can distinguish truly fatal failues ++ * (srb status == 0x4) and off-line the device in that case. ++ */ ++ ++ if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) || ++ (stor_pkt->vm_srb.cdb[0] == MODE_SENSE)) { ++ vstor_packet->vm_srb.scsi_status = 0; ++ vstor_packet->vm_srb.srb_status = SRB_STATUS_SUCCESS; ++ } ++ ++ ++ /* Copy over the status...etc */ ++ stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status; ++ stor_pkt->vm_srb.srb_status = vstor_packet->vm_srb.srb_status; ++ stor_pkt->vm_srb.sense_info_length = ++ vstor_packet->vm_srb.sense_info_length; ++ ++ if (vstor_packet->vm_srb.scsi_status != 0 || ++ vstor_packet->vm_srb.srb_status != SRB_STATUS_SUCCESS){ ++ dev_warn(&device->device, ++ "cmd 0x%x scsi status 0x%x srb status 0x%x\n", ++ stor_pkt->vm_srb.cdb[0], ++ vstor_packet->vm_srb.scsi_status, ++ vstor_packet->vm_srb.srb_status); ++ } ++ ++ if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) { ++ /* CHECK_CONDITION */ ++ if (vstor_packet->vm_srb.srb_status & ++ SRB_STATUS_AUTOSENSE_VALID) { ++ /* autosense data available */ ++ dev_warn(&device->device, ++ "stor pkt %p autosense data valid - len %d\n", ++ request, ++ vstor_packet->vm_srb.sense_info_length); ++ ++ memcpy(request->sense_buffer, ++ vstor_packet->vm_srb.sense_data, ++ vstor_packet->vm_srb.sense_info_length); ++ ++ } ++ } ++ ++ stor_pkt->vm_srb.data_transfer_length = ++ vstor_packet->vm_srb.data_transfer_length; ++ ++ storvsc_command_completion(request); ++ ++ if (atomic_dec_and_test(&stor_device->num_outstanding_req) && ++ stor_device->drain_notify) ++ wake_up(&stor_device->waiting_to_drain); ++ ++ ++} ++ ++static void storvsc_on_receive(struct hv_device *device, ++ struct vstor_packet *vstor_packet, ++ struct storvsc_cmd_request *request) ++{ ++ struct storvsc_scan_work *work; ++ struct storvsc_device *stor_device; ++ ++ switch (vstor_packet->operation) { ++ case VSTOR_OPERATION_COMPLETE_IO: ++ storvsc_on_io_completion(device, vstor_packet, request); ++ break; ++ ++ case VSTOR_OPERATION_REMOVE_DEVICE: ++ case VSTOR_OPERATION_ENUMERATE_BUS: ++ stor_device = get_in_stor_device(device); ++ work = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC); ++ if (!work) ++ return; ++ ++ INIT_WORK(&work->work, storvsc_bus_scan); ++ work->host = stor_device->host; ++ schedule_work(&work->work); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static void storvsc_on_channel_callback(void *context) ++{ ++ struct hv_device *device = (struct hv_device *)context; ++ struct storvsc_device *stor_device; ++ u32 bytes_recvd; ++ u64 request_id; ++ unsigned char packet[ALIGN(sizeof(struct vstor_packet), 8)]; ++ struct storvsc_cmd_request *request; ++ int ret; ++ ++ ++ stor_device = get_in_stor_device(device); ++ if (!stor_device) ++ return; ++ ++ do { ++ ret = vmbus_recvpacket(device->channel, packet, ++ ALIGN(sizeof(struct vstor_packet), 8), ++ &bytes_recvd, &request_id); ++ if (ret == 0 && bytes_recvd > 0) { ++ ++ request = (struct storvsc_cmd_request *) ++ (unsigned long)request_id; ++ ++ if ((request == &stor_device->init_request) || ++ (request == &stor_device->reset_request)) { ++ ++ memcpy(&request->vstor_packet, packet, ++ sizeof(struct vstor_packet)); ++ complete(&request->wait_event); ++ } else { ++ storvsc_on_receive(device, ++ (struct vstor_packet *)packet, ++ request); ++ } ++ } else { ++ break; ++ } ++ } while (1); ++ ++ return; ++} ++ ++static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size) ++{ ++ struct vmstorage_channel_properties props; ++ int ret; ++ ++ memset(&props, 0, sizeof(struct vmstorage_channel_properties)); ++ ++ ret = vmbus_open(device->channel, ++ ring_size, ++ ring_size, ++ (void *)&props, ++ sizeof(struct vmstorage_channel_properties), ++ storvsc_on_channel_callback, device); ++ ++ if (ret != 0) ++ return ret; ++ ++ ret = storvsc_channel_init(device); ++ ++ return ret; ++} ++ ++static int storvsc_dev_remove(struct hv_device *device) ++{ ++ struct storvsc_device *stor_device; ++ unsigned long flags; ++ ++ stor_device = hv_get_drvdata(device); ++ ++ spin_lock_irqsave(&device->channel->inbound_lock, flags); ++ stor_device->destroy = true; ++ spin_unlock_irqrestore(&device->channel->inbound_lock, flags); ++ ++ /* ++ * At this point, all outbound traffic should be disable. We ++ * only allow inbound traffic (responses) to proceed so that ++ * outstanding requests can be completed. ++ */ ++ ++ storvsc_wait_to_drain(stor_device); ++ ++ /* ++ * Since we have already drained, we don't need to busy wait ++ * as was done in final_release_stor_device() ++ * Note that we cannot set the ext pointer to NULL until ++ * we have drained - to drain the outgoing packets, we need to ++ * allow incoming packets. ++ */ ++ spin_lock_irqsave(&device->channel->inbound_lock, flags); ++ hv_set_drvdata(device, NULL); ++ spin_unlock_irqrestore(&device->channel->inbound_lock, flags); ++ ++ /* Close the channel */ ++ vmbus_close(device->channel); ++ ++ kfree(stor_device); ++ return 0; ++} ++ ++static int storvsc_do_io(struct hv_device *device, ++ struct storvsc_cmd_request *request) ++{ ++ struct storvsc_device *stor_device; ++ struct vstor_packet *vstor_packet; ++ int ret = 0; ++ ++ vstor_packet = &request->vstor_packet; ++ stor_device = get_out_stor_device(device); ++ ++ if (!stor_device) ++ return -ENODEV; ++ ++ ++ request->device = device; ++ ++ ++ vstor_packet->flags |= REQUEST_COMPLETION_FLAG; ++ ++ vstor_packet->vm_srb.length = sizeof(struct vmscsi_request); ++ ++ ++ vstor_packet->vm_srb.sense_info_length = STORVSC_SENSE_BUFFER_SIZE; ++ ++ ++ vstor_packet->vm_srb.data_transfer_length = ++ request->data_buffer.len; ++ ++ vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB; ++ ++ if (request->data_buffer.len) { ++ ret = vmbus_sendpacket_multipagebuffer(device->channel, ++ &request->data_buffer, ++ vstor_packet, ++ sizeof(struct vstor_packet), ++ (unsigned long)request); ++ } else { ++ ret = vmbus_sendpacket(device->channel, vstor_packet, ++ sizeof(struct vstor_packet), ++ (unsigned long)request, ++ VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ } ++ ++ if (ret != 0) ++ return ret; ++ ++ atomic_inc(&stor_device->num_outstanding_req); ++ ++ return ret; ++} ++ ++static int storvsc_device_alloc(struct scsi_device *sdevice) ++{ ++ struct stor_mem_pools *memp; ++ int number = STORVSC_MIN_BUF_NR; ++ ++ memp = kzalloc(sizeof(struct stor_mem_pools), GFP_KERNEL); ++ if (!memp) ++ return -ENOMEM; ++ ++ memp->request_pool = ++ kmem_cache_create(dev_name(&sdevice->sdev_dev), ++ sizeof(struct storvsc_cmd_request), 0, ++ SLAB_HWCACHE_ALIGN, NULL); ++ ++ if (!memp->request_pool) ++ goto err0; ++ ++ memp->request_mempool = mempool_create(number, mempool_alloc_slab, ++ mempool_free_slab, ++ memp->request_pool); ++ ++ if (!memp->request_mempool) ++ goto err1; ++ ++ sdevice->hostdata = memp; ++ ++ return 0; ++ ++err1: ++ kmem_cache_destroy(memp->request_pool); ++ ++err0: ++ kfree(memp); ++ return -ENOMEM; ++} ++ ++static void storvsc_device_destroy(struct scsi_device *sdevice) ++{ ++ struct stor_mem_pools *memp = sdevice->hostdata; ++ ++ mempool_destroy(memp->request_mempool); ++ kmem_cache_destroy(memp->request_pool); ++ kfree(memp); ++ sdevice->hostdata = NULL; ++} ++ ++static int storvsc_device_configure(struct scsi_device *sdevice) ++{ ++ scsi_adjust_queue_depth(sdevice, MSG_SIMPLE_TAG, ++ STORVSC_MAX_IO_REQUESTS); ++ ++ blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE); ++ ++ blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY); ++ ++ return 0; ++} ++ ++static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev, ++ sector_t capacity, int *info) ++{ ++ sector_t nsect = capacity; ++ sector_t cylinders = nsect; ++ int heads, sectors_pt; ++ ++ /* ++ * We are making up these values; let us keep it simple. ++ */ ++ heads = 0xff; ++ sectors_pt = 0x3f; /* Sectors per track */ ++ sector_div(cylinders, heads * sectors_pt); ++ if ((sector_t)(cylinders + 1) * heads * sectors_pt < nsect) ++ cylinders = 0xffff; ++ ++ info[0] = heads; ++ info[1] = sectors_pt; ++ info[2] = (int)cylinders; ++ ++ return 0; ++} ++ ++static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) ++{ ++ struct hv_host_device *host_dev = shost_priv(scmnd->device->host); ++ struct hv_device *device = host_dev->dev; ++ ++ struct storvsc_device *stor_device; ++ struct storvsc_cmd_request *request; ++ struct vstor_packet *vstor_packet; ++ int ret, t; ++ ++ ++ stor_device = get_out_stor_device(device); ++ if (!stor_device) ++ return FAILED; ++ ++ request = &stor_device->reset_request; ++ vstor_packet = &request->vstor_packet; ++ ++ init_completion(&request->wait_event); ++ ++ vstor_packet->operation = VSTOR_OPERATION_RESET_BUS; ++ vstor_packet->flags = REQUEST_COMPLETION_FLAG; ++ vstor_packet->vm_srb.path_id = stor_device->path_id; ++ ++ ret = vmbus_sendpacket(device->channel, vstor_packet, ++ sizeof(struct vstor_packet), ++ (unsigned long)&stor_device->reset_request, ++ VM_PKT_DATA_INBAND, ++ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); ++ if (ret != 0) ++ return FAILED; ++ ++ t = wait_for_completion_timeout(&request->wait_event, 5*HZ); ++ if (t == 0) ++ return TIMEOUT_ERROR; ++ ++ ++ /* ++ * At this point, all outstanding requests in the adapter ++ * should have been flushed out and return to us ++ * There is a potential race here where the host may be in ++ * the process of responding when we return from here. ++ * Just wait for all in-transit packets to be accounted for ++ * before we return from here. ++ */ ++ storvsc_wait_to_drain(stor_device); ++ ++ return SUCCESS; ++} ++ ++/* ++ * The host guarantees to respond to each command, although I/O latencies might ++ * be unbounded on Azure. Reset the timer unconditionally to give the host a ++ * chance to perform EH. ++ */ ++static enum blk_eh_timer_return storvsc_eh_timed_out(struct scsi_cmnd *scmnd) ++{ ++ return BLK_EH_RESET_TIMER; ++} ++ ++static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd) ++{ ++ bool allowed = true; ++ u8 scsi_op = scmnd->cmnd[0]; ++ ++ switch (scsi_op) { ++ /* ++ * smartd sends this command and the host does not handle ++ * this. So, don't send it. ++ */ ++ case SET_WINDOW: ++ scmnd->result = ILLEGAL_REQUEST << 16; ++ allowed = false; ++ break; ++ default: ++ break; ++ } ++ return allowed; ++} ++ ++static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) ++{ ++ int ret; ++ struct hv_host_device *host_dev = shost_priv(host); ++ struct hv_device *dev = host_dev->dev; ++ struct storvsc_cmd_request *cmd_request; ++ unsigned int request_size = 0; ++ int i; ++ struct scatterlist *sgl; ++ unsigned int sg_count = 0; ++ struct vmscsi_request *vm_srb; ++ struct stor_mem_pools *memp = scmnd->device->hostdata; ++ ++ if (!storvsc_scsi_cmd_ok(scmnd)) { ++ scmnd->scsi_done(scmnd); ++ return 0; ++ } ++ ++ request_size = sizeof(struct storvsc_cmd_request); ++ ++ cmd_request = mempool_alloc(memp->request_mempool, ++ GFP_ATOMIC); ++ ++ /* ++ * We might be invoked in an interrupt context; hence ++ * mempool_alloc() can fail. ++ */ ++ if (!cmd_request) ++ return SCSI_MLQUEUE_DEVICE_BUSY; ++ ++ memset(cmd_request, 0, sizeof(struct storvsc_cmd_request)); ++ ++ /* Setup the cmd request */ ++ cmd_request->cmd = scmnd; ++ ++ scmnd->host_scribble = (unsigned char *)cmd_request; ++ ++ vm_srb = &cmd_request->vstor_packet.vm_srb; ++ ++ ++ /* Build the SRB */ ++ switch (scmnd->sc_data_direction) { ++ case DMA_TO_DEVICE: ++ vm_srb->data_in = WRITE_TYPE; ++ break; ++ case DMA_FROM_DEVICE: ++ vm_srb->data_in = READ_TYPE; ++ break; ++ default: ++ vm_srb->data_in = UNKNOWN_TYPE; ++ break; ++ } ++ ++ ++ vm_srb->port_number = host_dev->port; ++ vm_srb->path_id = scmnd->device->channel; ++ vm_srb->target_id = scmnd->device->id; ++ vm_srb->lun = scmnd->device->lun; ++ ++ vm_srb->cdb_length = scmnd->cmd_len; ++ ++ memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length); ++ ++ cmd_request->sense_buffer = scmnd->sense_buffer; ++ ++ ++ cmd_request->data_buffer.len = scsi_bufflen(scmnd); ++ if (scsi_sg_count(scmnd)) { ++ sgl = (struct scatterlist *)scsi_sglist(scmnd); ++ sg_count = scsi_sg_count(scmnd); ++ ++ /* check if we need to bounce the sgl */ ++ if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) { ++ cmd_request->bounce_sgl = ++ create_bounce_buffer(sgl, scsi_sg_count(scmnd), ++ scsi_bufflen(scmnd), ++ vm_srb->data_in); ++ if (!cmd_request->bounce_sgl) { ++ ret = SCSI_MLQUEUE_HOST_BUSY; ++ goto queue_error; ++ } ++ ++ cmd_request->bounce_sgl_count = ++ ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >> ++ PAGE_SHIFT; ++ ++ if (vm_srb->data_in == WRITE_TYPE) ++ copy_to_bounce_buffer(sgl, ++ cmd_request->bounce_sgl, ++ scsi_sg_count(scmnd)); ++ ++ sgl = cmd_request->bounce_sgl; ++ sg_count = cmd_request->bounce_sgl_count; ++ } ++ ++ cmd_request->data_buffer.offset = sgl[0].offset; ++ ++ for (i = 0; i < sg_count; i++) ++ cmd_request->data_buffer.pfn_array[i] = ++ page_to_pfn(sg_page((&sgl[i]))); ++ ++ } else if (scsi_sglist(scmnd)) { ++ cmd_request->data_buffer.offset = ++ virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1); ++ cmd_request->data_buffer.pfn_array[0] = ++ virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT; ++ } ++ ++ /* Invokes the vsc to start an IO */ ++ ret = storvsc_do_io(dev, cmd_request); ++ ++ if (ret == -EAGAIN) { ++ /* no more space */ ++ ++ if (cmd_request->bounce_sgl_count) { ++ destroy_bounce_buffer(cmd_request->bounce_sgl, ++ cmd_request->bounce_sgl_count); ++ ++ ret = SCSI_MLQUEUE_DEVICE_BUSY; ++ goto queue_error; ++ } ++ } ++ ++ return 0; ++ ++queue_error: ++ mempool_free(cmd_request, memp->request_mempool); ++ scmnd->host_scribble = NULL; ++ return ret; ++} ++ ++static struct scsi_host_template scsi_driver = { ++ .module = THIS_MODULE, ++ .name = "storvsc_host_t", ++ .bios_param = storvsc_get_chs, ++ .queuecommand = storvsc_queuecommand, ++ .eh_host_reset_handler = storvsc_host_reset_handler, ++ .eh_timed_out = storvsc_eh_timed_out, ++ .slave_alloc = storvsc_device_alloc, ++ .slave_destroy = storvsc_device_destroy, ++ .slave_configure = storvsc_device_configure, ++ .cmd_per_lun = 1, ++ /* 64 max_queue * 1 target */ ++ .can_queue = STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS, ++ .this_id = -1, ++ /* no use setting to 0 since ll_blk_rw reset it to 1 */ ++ /* currently 32 */ ++ .sg_tablesize = MAX_MULTIPAGE_BUFFER_COUNT, ++ .use_clustering = DISABLE_CLUSTERING, ++ /* Make sure we dont get a sg segment crosses a page boundary */ ++ .dma_boundary = PAGE_SIZE-1, ++}; ++ ++enum { ++ SCSI_GUID, ++ IDE_GUID, ++}; ++ ++static const struct hv_vmbus_device_id id_table[] = { ++ /* SCSI guid */ ++ { VMBUS_DEVICE(0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, ++ 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f) ++ .driver_data = SCSI_GUID }, ++ /* IDE guid */ ++ { VMBUS_DEVICE(0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, ++ 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5) ++ .driver_data = IDE_GUID }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(vmbus, id_table); ++ ++static int storvsc_probe(struct hv_device *device, ++ const struct hv_vmbus_device_id *dev_id) ++{ ++ int ret; ++ struct Scsi_Host *host; ++ struct hv_host_device *host_dev; ++ bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false); ++ int target = 0; ++ struct storvsc_device *stor_device; ++ ++ host = scsi_host_alloc(&scsi_driver, ++ sizeof(struct hv_host_device)); ++ if (!host) ++ return -ENOMEM; ++ ++ host_dev = shost_priv(host); ++ memset(host_dev, 0, sizeof(struct hv_host_device)); ++ ++ host_dev->port = host->host_no; ++ host_dev->dev = device; ++ ++ ++ stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL); ++ if (!stor_device) { ++ ret = -ENOMEM; ++ goto err_out0; ++ } ++ ++ stor_device->destroy = false; ++ init_waitqueue_head(&stor_device->waiting_to_drain); ++ stor_device->device = device; ++ stor_device->host = host; ++ hv_set_drvdata(device, stor_device); ++ ++ stor_device->port_number = host->host_no; ++ ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size); ++ if (ret) ++ goto err_out1; ++ ++ host_dev->path = stor_device->path_id; ++ host_dev->target = stor_device->target_id; ++ ++ /* max # of devices per target */ ++ host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; ++ /* max # of targets per channel */ ++ host->max_id = STORVSC_MAX_TARGETS; ++ /* max # of channels */ ++ host->max_channel = STORVSC_MAX_CHANNELS - 1; ++ /* max cmd length */ ++ host->max_cmd_len = STORVSC_MAX_CMD_LEN; ++ ++ /* Register the HBA and start the scsi bus scan */ ++ ret = scsi_add_host(host, &device->device); ++ if (ret != 0) ++ goto err_out2; ++ ++ if (!dev_is_ide) { ++ scsi_scan_host(host); ++ } else { ++ target = (device->dev_instance.b[5] << 8 | ++ device->dev_instance.b[4]); ++ ret = scsi_add_device(host, 0, target, 0); ++ if (ret) { ++ scsi_remove_host(host); ++ goto err_out2; ++ } ++ } ++ return 0; ++ ++err_out2: ++ /* ++ * Once we have connected with the host, we would need to ++ * to invoke storvsc_dev_remove() to rollback this state and ++ * this call also frees up the stor_device; hence the jump around ++ * err_out1 label. ++ */ ++ storvsc_dev_remove(device); ++ goto err_out0; ++ ++err_out1: ++ kfree(stor_device); ++ ++err_out0: ++ scsi_host_put(host); ++ return ret; ++} ++ ++static int storvsc_remove(struct hv_device *dev) ++{ ++ struct storvsc_device *stor_device = hv_get_drvdata(dev); ++ struct Scsi_Host *host = stor_device->host; ++ ++ scsi_remove_host(host); ++ storvsc_dev_remove(dev); ++ scsi_host_put(host); ++ ++ return 0; ++} ++ ++static struct hv_driver storvsc_drv = { ++ .name = KBUILD_MODNAME, ++ .id_table = id_table, ++ .probe = storvsc_probe, ++ .remove = storvsc_remove, ++}; ++ ++static int __init storvsc_drv_init(void) ++{ ++ u32 max_outstanding_req_per_channel; ++ ++ /* ++ * Divide the ring buffer data size (which is 1 page less ++ * than the ring buffer size since that page is reserved for ++ * the ring buffer indices) by the max request size (which is ++ * vmbus_channel_packet_multipage_buffer + struct vstor_packet + u64) ++ */ ++ max_outstanding_req_per_channel = ++ ((storvsc_ringbuffer_size - PAGE_SIZE) / ++ ALIGN(MAX_MULTIPAGE_BUFFER_PACKET + ++ sizeof(struct vstor_packet) + sizeof(u64), ++ sizeof(u64))); ++ ++ if (max_outstanding_req_per_channel < ++ STORVSC_MAX_IO_REQUESTS) ++ return -EINVAL; ++ ++ return vmbus_driver_register(&storvsc_drv); ++} ++ ++static void __exit storvsc_drv_exit(void) ++{ ++ vmbus_driver_unregister(&storvsc_drv); ++} ++ ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(HV_DRV_VERSION); ++MODULE_DESCRIPTION("Microsoft Hyper-V virtual storage driver"); ++module_init(storvsc_drv_init); ++module_exit(storvsc_drv_exit); +diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c +new file mode 100644 +index 0000000..06c9d30 +--- /dev/null ++++ b/drivers/scsi/virtio_scsi.c +@@ -0,0 +1,838 @@ ++/* ++ * Virtio SCSI HBA driver ++ * ++ * Copyright IBM Corp. 2010 ++ * Copyright Red Hat, Inc. 2011 ++ * ++ * Authors: ++ * Stefan Hajnoczi ++ * Paolo Bonzini ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define VIRTIO_SCSI_MEMPOOL_SZ 64 ++#define VIRTIO_SCSI_EVENT_LEN 8 ++ ++/* Command queue element */ ++struct virtio_scsi_cmd { ++ struct scsi_cmnd *sc; ++ struct completion *comp; ++ union { ++ struct virtio_scsi_cmd_req cmd; ++ struct virtio_scsi_ctrl_tmf_req tmf; ++ struct virtio_scsi_ctrl_an_req an; ++ } req; ++ union { ++ struct virtio_scsi_cmd_resp cmd; ++ struct virtio_scsi_ctrl_tmf_resp tmf; ++ struct virtio_scsi_ctrl_an_resp an; ++ struct virtio_scsi_event evt; ++ } resp; ++} ____cacheline_aligned_in_smp; ++ ++struct virtio_scsi_event_node { ++ struct virtio_scsi *vscsi; ++ struct virtio_scsi_event event; ++ struct work_struct work; ++}; ++ ++struct virtio_scsi_vq { ++ /* Protects vq */ ++ spinlock_t vq_lock; ++ ++ struct virtqueue *vq; ++}; ++ ++/* Per-target queue state */ ++struct virtio_scsi_target_state { ++ /* Protects sg. Lock hierarchy is tgt_lock -> vq_lock. */ ++ spinlock_t tgt_lock; ++ ++ /* For sglist construction when adding commands to the virtqueue. */ ++ struct scatterlist sg[]; ++}; ++ ++/* Driver instance state */ ++struct virtio_scsi { ++ struct virtio_device *vdev; ++ ++ struct virtio_scsi_vq ctrl_vq; ++ struct virtio_scsi_vq event_vq; ++ struct virtio_scsi_vq req_vq; ++ ++ /* Get some buffers ready for event vq */ ++ struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN]; ++ ++ struct virtio_scsi_target_state *tgt[]; ++}; ++ ++static struct kmem_cache *virtscsi_cmd_cache; ++static mempool_t *virtscsi_cmd_pool; ++ ++static inline struct Scsi_Host *virtio_scsi_host(struct virtio_device *vdev) ++{ ++ return vdev->priv; ++} ++ ++static void virtscsi_compute_resid(struct scsi_cmnd *sc, u32 resid) ++{ ++ if (!resid) ++ return; ++ ++ if (!scsi_bidi_cmnd(sc)) { ++ scsi_set_resid(sc, resid); ++ return; ++ } ++ ++ scsi_in(sc)->resid = min(resid, scsi_in(sc)->length); ++ scsi_out(sc)->resid = resid - scsi_in(sc)->resid; ++} ++ ++/** ++ * virtscsi_complete_cmd - finish a scsi_cmd and invoke scsi_done ++ * ++ * Called with vq_lock held. ++ */ ++static void virtscsi_complete_cmd(void *buf) ++{ ++ struct virtio_scsi_cmd *cmd = buf; ++ struct scsi_cmnd *sc = cmd->sc; ++ struct virtio_scsi_cmd_resp *resp = &cmd->resp.cmd; ++ ++ dev_dbg(&sc->device->sdev_gendev, ++ "cmd %p response %u status %#02x sense_len %u\n", ++ sc, resp->response, resp->status, resp->sense_len); ++ ++ sc->result = resp->status; ++ virtscsi_compute_resid(sc, resp->resid); ++ switch (resp->response) { ++ case VIRTIO_SCSI_S_OK: ++ set_host_byte(sc, DID_OK); ++ break; ++ case VIRTIO_SCSI_S_OVERRUN: ++ set_host_byte(sc, DID_ERROR); ++ break; ++ case VIRTIO_SCSI_S_ABORTED: ++ set_host_byte(sc, DID_ABORT); ++ break; ++ case VIRTIO_SCSI_S_BAD_TARGET: ++ set_host_byte(sc, DID_BAD_TARGET); ++ break; ++ case VIRTIO_SCSI_S_RESET: ++ set_host_byte(sc, DID_RESET); ++ break; ++ case VIRTIO_SCSI_S_BUSY: ++ set_host_byte(sc, DID_BUS_BUSY); ++ break; ++ case VIRTIO_SCSI_S_TRANSPORT_FAILURE: ++ set_host_byte(sc, DID_TRANSPORT_DISRUPTED); ++ break; ++ case VIRTIO_SCSI_S_TARGET_FAILURE: ++ set_host_byte(sc, DID_TARGET_FAILURE); ++ break; ++ case VIRTIO_SCSI_S_NEXUS_FAILURE: ++ set_host_byte(sc, DID_NEXUS_FAILURE); ++ break; ++ default: ++ scmd_printk(KERN_WARNING, sc, "Unknown response %d", ++ resp->response); ++ /* fall through */ ++ case VIRTIO_SCSI_S_FAILURE: ++ set_host_byte(sc, DID_ERROR); ++ break; ++ } ++ ++ WARN_ON(resp->sense_len > VIRTIO_SCSI_SENSE_SIZE); ++ if (sc->sense_buffer) { ++ memcpy(sc->sense_buffer, resp->sense, ++ min_t(u32, resp->sense_len, VIRTIO_SCSI_SENSE_SIZE)); ++ if (resp->sense_len) ++ set_driver_byte(sc, DRIVER_SENSE); ++ } ++ ++ mempool_free(cmd, virtscsi_cmd_pool); ++ sc->scsi_done(sc); ++} ++ ++static void virtscsi_vq_done(struct virtqueue *vq, void (*fn)(void *buf)) ++{ ++ void *buf; ++ unsigned int len; ++ ++ do { ++ virtqueue_disable_cb(vq); ++ while ((buf = virtqueue_get_buf(vq, &len)) != NULL) ++ fn(buf); ++ } while (!virtqueue_enable_cb(vq)); ++} ++ ++static void virtscsi_req_done(struct virtqueue *vq) ++{ ++ struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); ++ struct virtio_scsi *vscsi = shost_priv(sh); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vscsi->req_vq.vq_lock, flags); ++ virtscsi_vq_done(vq, virtscsi_complete_cmd); ++ spin_unlock_irqrestore(&vscsi->req_vq.vq_lock, flags); ++}; ++ ++static void virtscsi_complete_free(void *buf) ++{ ++ struct virtio_scsi_cmd *cmd = buf; ++ ++ if (cmd->comp) ++ complete_all(cmd->comp); ++ else ++ mempool_free(cmd, virtscsi_cmd_pool); ++} ++ ++static void virtscsi_ctrl_done(struct virtqueue *vq) ++{ ++ struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); ++ struct virtio_scsi *vscsi = shost_priv(sh); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vscsi->ctrl_vq.vq_lock, flags); ++ virtscsi_vq_done(vq, virtscsi_complete_free); ++ spin_unlock_irqrestore(&vscsi->ctrl_vq.vq_lock, flags); ++}; ++ ++static int virtscsi_kick_event(struct virtio_scsi *vscsi, ++ struct virtio_scsi_event_node *event_node) ++{ ++ int ret; ++ struct scatterlist sg; ++ unsigned long flags; ++ ++ sg_init_one(&sg, &event_node->event, sizeof(struct virtio_scsi_event)); ++ ++ spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags); ++ ++ ret = virtqueue_add_buf_gfp(vscsi->event_vq.vq, &sg, 0, 1, event_node, GFP_ATOMIC); ++ if (ret >= 0) ++ virtqueue_kick(vscsi->event_vq.vq); ++ ++ spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags); ++ ++ return ret; ++} ++ ++static int virtscsi_kick_event_all(struct virtio_scsi *vscsi) ++{ ++ int i; ++ ++ for (i = 0; i < VIRTIO_SCSI_EVENT_LEN; i++) { ++ vscsi->event_list[i].vscsi = vscsi; ++ virtscsi_kick_event(vscsi, &vscsi->event_list[i]); ++ } ++ ++ return 0; ++} ++ ++static void virtscsi_cancel_event_work(struct virtio_scsi *vscsi) ++{ ++ int i; ++ ++ for (i = 0; i < VIRTIO_SCSI_EVENT_LEN; i++) ++ cancel_work_sync(&vscsi->event_list[i].work); ++} ++ ++static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi, ++ struct virtio_scsi_event *event) ++{ ++ struct scsi_device *sdev; ++ struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); ++ unsigned int target = event->lun[1]; ++ unsigned int lun = (event->lun[2] << 8) | event->lun[3]; ++ ++ switch (event->reason) { ++ case VIRTIO_SCSI_EVT_RESET_RESCAN: ++ scsi_add_device(shost, 0, target, lun); ++ break; ++ case VIRTIO_SCSI_EVT_RESET_REMOVED: ++ sdev = scsi_device_lookup(shost, 0, target, lun); ++ if (sdev) { ++ scsi_remove_device(sdev); ++ scsi_device_put(sdev); ++ } else { ++ pr_err("SCSI device %d 0 %d %d not found\n", ++ shost->host_no, target, lun); ++ } ++ break; ++ default: ++ pr_info("Unsupport virtio scsi event reason %x\n", event->reason); ++ } ++} ++ ++static void virtscsi_handle_param_change(struct virtio_scsi *vscsi, ++ struct virtio_scsi_event *event) ++{ ++ struct scsi_device *sdev; ++ struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); ++ unsigned int target = event->lun[1]; ++ unsigned int lun = (event->lun[2] << 8) | event->lun[3]; ++ u8 asc = event->reason & 255; ++ u8 ascq = event->reason >> 8; ++ ++ sdev = scsi_device_lookup(shost, 0, target, lun); ++ if (!sdev) { ++ pr_err("SCSI device %d 0 %d %d not found\n", ++ shost->host_no, target, lun); ++ return; ++ } ++ ++ /* Handle "Parameters changed", "Mode parameters changed", and ++ "Capacity data has changed". */ ++ if (asc == 0x2a && (ascq == 0x00 || ascq == 0x01 || ascq == 0x09)) ++ scsi_rescan_device(&sdev->sdev_gendev); ++ ++ scsi_device_put(sdev); ++} ++ ++static void virtscsi_handle_event(struct work_struct *work) ++{ ++ struct virtio_scsi_event_node *event_node = ++ container_of(work, struct virtio_scsi_event_node, work); ++ struct virtio_scsi *vscsi = event_node->vscsi; ++ struct virtio_scsi_event *event = &event_node->event; ++ ++ if (event->event & VIRTIO_SCSI_T_EVENTS_MISSED) { ++ event->event &= ~VIRTIO_SCSI_T_EVENTS_MISSED; ++ scsi_scan_host(virtio_scsi_host(vscsi->vdev)); ++ } ++ ++ switch (event->event) { ++ case VIRTIO_SCSI_T_NO_EVENT: ++ break; ++ case VIRTIO_SCSI_T_TRANSPORT_RESET: ++ virtscsi_handle_transport_reset(vscsi, event); ++ break; ++ case VIRTIO_SCSI_T_PARAM_CHANGE: ++ virtscsi_handle_param_change(vscsi, event); ++ break; ++ default: ++ pr_err("Unsupport virtio scsi event %x\n", event->event); ++ } ++ virtscsi_kick_event(vscsi, event_node); ++} ++ ++static void virtscsi_complete_event(void *buf) ++{ ++ struct virtio_scsi_event_node *event_node = buf; ++ ++ INIT_WORK(&event_node->work, virtscsi_handle_event); ++ schedule_work(&event_node->work); ++} ++ ++static void virtscsi_event_done(struct virtqueue *vq) ++{ ++ struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); ++ struct virtio_scsi *vscsi = shost_priv(sh); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags); ++ virtscsi_vq_done(vq, virtscsi_complete_event); ++ spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags); ++}; ++ ++static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx, ++ struct scsi_data_buffer *sdb) ++{ ++ struct sg_table *table = &sdb->table; ++ struct scatterlist *sg_elem; ++ unsigned int idx = *p_idx; ++ int i; ++ ++ for_each_sg(table->sgl, sg_elem, table->nents, i) ++ sg[idx++] = *sg_elem; ++ ++ *p_idx = idx; ++} ++ ++/** ++ * virtscsi_map_cmd - map a scsi_cmd to a virtqueue scatterlist ++ * @vscsi : virtio_scsi state ++ * @cmd : command structure ++ * @out_num : number of read-only elements ++ * @in_num : number of write-only elements ++ * @req_size : size of the request buffer ++ * @resp_size : size of the response buffer ++ * ++ * Called with tgt_lock held. ++ */ ++static void virtscsi_map_cmd(struct virtio_scsi_target_state *tgt, ++ struct virtio_scsi_cmd *cmd, ++ unsigned *out_num, unsigned *in_num, ++ size_t req_size, size_t resp_size) ++{ ++ struct scsi_cmnd *sc = cmd->sc; ++ struct scatterlist *sg = tgt->sg; ++ unsigned int idx = 0; ++ ++ /* Request header. */ ++ sg_set_buf(&sg[idx++], &cmd->req, req_size); ++ ++ /* Data-out buffer. */ ++ if (sc && sc->sc_data_direction != DMA_FROM_DEVICE) ++ virtscsi_map_sgl(sg, &idx, scsi_out(sc)); ++ ++ *out_num = idx; ++ ++ /* Response header. */ ++ sg_set_buf(&sg[idx++], &cmd->resp, resp_size); ++ ++ /* Data-in buffer */ ++ if (sc && sc->sc_data_direction != DMA_TO_DEVICE) ++ virtscsi_map_sgl(sg, &idx, scsi_in(sc)); ++ ++ *in_num = idx - *out_num; ++} ++ ++static int virtscsi_kick_cmd(struct virtio_scsi_target_state *tgt, ++ struct virtio_scsi_vq *vq, ++ struct virtio_scsi_cmd *cmd, ++ size_t req_size, size_t resp_size, gfp_t gfp) ++{ ++ unsigned int out_num, in_num; ++ unsigned long flags; ++ int ret; ++ ++ spin_lock_irqsave(&tgt->tgt_lock, flags); ++ virtscsi_map_cmd(tgt, cmd, &out_num, &in_num, req_size, resp_size); ++ ++ spin_lock(&vq->vq_lock); ++ ret = virtqueue_add_buf_gfp(vq->vq, tgt->sg, out_num, in_num, cmd, gfp); ++ spin_unlock(&tgt->tgt_lock); ++ if (ret >= 0) ++ ret = virtqueue_kick_prepare(vq->vq); ++ ++ spin_unlock_irqrestore(&vq->vq_lock, flags); ++ ++ if (ret > 0) ++ virtqueue_notify(vq->vq); ++ return ret; ++} ++ ++static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) ++{ ++ struct virtio_scsi *vscsi = shost_priv(sh); ++ struct virtio_scsi_target_state *tgt = vscsi->tgt[sc->device->id]; ++ struct virtio_scsi_cmd *cmd; ++ int ret; ++ ++ struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); ++ BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize); ++ ++ /* TODO: check feature bit and fail if unsupported? */ ++ BUG_ON(sc->sc_data_direction == DMA_BIDIRECTIONAL); ++ ++ dev_dbg(&sc->device->sdev_gendev, ++ "cmd %p CDB: %#02x\n", sc, sc->cmnd[0]); ++ ++ ret = SCSI_MLQUEUE_HOST_BUSY; ++ cmd = mempool_alloc(virtscsi_cmd_pool, GFP_ATOMIC); ++ if (!cmd) ++ goto out; ++ ++ memset(cmd, 0, sizeof(*cmd)); ++ cmd->sc = sc; ++ cmd->req.cmd = (struct virtio_scsi_cmd_req){ ++ .lun[0] = 1, ++ .lun[1] = sc->device->id, ++ .lun[2] = (sc->device->lun >> 8) | 0x40, ++ .lun[3] = sc->device->lun & 0xff, ++ .tag = (unsigned long)sc, ++ .task_attr = VIRTIO_SCSI_S_SIMPLE, ++ .prio = 0, ++ .crn = 0, ++ }; ++ ++ BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE); ++ memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); ++ ++ if (virtscsi_kick_cmd(tgt, &vscsi->req_vq, cmd, ++ sizeof cmd->req.cmd, sizeof cmd->resp.cmd, ++ GFP_ATOMIC) >= 0) ++ ret = 0; ++ else ++ mempool_free(cmd, virtscsi_cmd_pool); ++ ++out: ++ return ret; ++} ++ ++static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd) ++{ ++ DECLARE_COMPLETION_ONSTACK(comp); ++ struct virtio_scsi_target_state *tgt = vscsi->tgt[cmd->sc->device->id]; ++ int ret = FAILED; ++ ++ cmd->comp = ∁ ++ if (virtscsi_kick_cmd(tgt, &vscsi->ctrl_vq, cmd, ++ sizeof cmd->req.tmf, sizeof cmd->resp.tmf, ++ GFP_NOIO) < 0) ++ goto out; ++ ++ wait_for_completion(&comp); ++ if (cmd->resp.tmf.response == VIRTIO_SCSI_S_OK || ++ cmd->resp.tmf.response == VIRTIO_SCSI_S_FUNCTION_SUCCEEDED) ++ ret = SUCCESS; ++ ++out: ++ mempool_free(cmd, virtscsi_cmd_pool); ++ return ret; ++} ++ ++static int virtscsi_device_reset(struct scsi_cmnd *sc) ++{ ++ struct virtio_scsi *vscsi = shost_priv(sc->device->host); ++ struct virtio_scsi_cmd *cmd; ++ ++ sdev_printk(KERN_INFO, sc->device, "device reset\n"); ++ cmd = mempool_alloc(virtscsi_cmd_pool, GFP_NOIO); ++ if (!cmd) ++ return FAILED; ++ ++ memset(cmd, 0, sizeof(*cmd)); ++ cmd->sc = sc; ++ cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){ ++ .type = VIRTIO_SCSI_T_TMF, ++ .subtype = VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET, ++ .lun[0] = 1, ++ .lun[1] = sc->device->id, ++ .lun[2] = (sc->device->lun >> 8) | 0x40, ++ .lun[3] = sc->device->lun & 0xff, ++ }; ++ return virtscsi_tmf(vscsi, cmd); ++} ++ ++static int virtscsi_abort(struct scsi_cmnd *sc) ++{ ++ struct virtio_scsi *vscsi = shost_priv(sc->device->host); ++ struct virtio_scsi_cmd *cmd; ++ ++ scmd_printk(KERN_INFO, sc, "abort\n"); ++ cmd = mempool_alloc(virtscsi_cmd_pool, GFP_NOIO); ++ if (!cmd) ++ return FAILED; ++ ++ memset(cmd, 0, sizeof(*cmd)); ++ cmd->sc = sc; ++ cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){ ++ .type = VIRTIO_SCSI_T_TMF, ++ .subtype = VIRTIO_SCSI_T_TMF_ABORT_TASK, ++ .lun[0] = 1, ++ .lun[1] = sc->device->id, ++ .lun[2] = (sc->device->lun >> 8) | 0x40, ++ .lun[3] = sc->device->lun & 0xff, ++ .tag = (unsigned long)sc, ++ }; ++ return virtscsi_tmf(vscsi, cmd); ++} ++ ++static struct scsi_host_template virtscsi_host_template = { ++ .module = THIS_MODULE, ++ .name = "Virtio SCSI HBA", ++ .proc_name = "virtio_scsi", ++ .queuecommand = virtscsi_queuecommand, ++ .this_id = -1, ++ .eh_abort_handler = virtscsi_abort, ++ .eh_device_reset_handler = virtscsi_device_reset, ++ ++ .can_queue = 1024, ++ .dma_boundary = UINT_MAX, ++ .use_clustering = ENABLE_CLUSTERING, ++}; ++ ++#define virtscsi_config_get(vdev, fld) \ ++ ({ \ ++ typeof(((struct virtio_scsi_config *)0)->fld) __val; \ ++ vdev->config->get(vdev, \ ++ offsetof(struct virtio_scsi_config, fld), \ ++ &__val, sizeof(__val)); \ ++ __val; \ ++ }) ++ ++#define virtscsi_config_set(vdev, fld, val) \ ++ (void)({ \ ++ typeof(((struct virtio_scsi_config *)0)->fld) __val = (val); \ ++ vdev->config->set(vdev, \ ++ offsetof(struct virtio_scsi_config, fld), \ ++ &__val, sizeof(__val)); \ ++ }) ++ ++static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq, ++ struct virtqueue *vq) ++{ ++ spin_lock_init(&virtscsi_vq->vq_lock); ++ virtscsi_vq->vq = vq; ++} ++ ++static struct virtio_scsi_target_state *virtscsi_alloc_tgt( ++ struct virtio_device *vdev, int sg_elems) ++{ ++ struct virtio_scsi_target_state *tgt; ++ gfp_t gfp_mask = GFP_KERNEL; ++ ++ /* We need extra sg elements at head and tail. */ ++ tgt = kmalloc(sizeof(*tgt) + sizeof(tgt->sg[0]) * (sg_elems + 2), ++ gfp_mask); ++ ++ if (!tgt) ++ return NULL; ++ ++ spin_lock_init(&tgt->tgt_lock); ++ sg_init_table(tgt->sg, sg_elems + 2); ++ return tgt; ++} ++ ++static void virtscsi_scan(struct virtio_device *vdev) ++{ ++ struct Scsi_Host *shost = (struct Scsi_Host *)vdev->priv; ++ ++ scsi_scan_host(shost); ++} ++ ++static void virtscsi_remove_vqs(struct virtio_device *vdev) ++{ ++ struct Scsi_Host *sh = virtio_scsi_host(vdev); ++ struct virtio_scsi *vscsi = shost_priv(sh); ++ u32 i, num_targets; ++ ++ /* Stop all the virtqueues. */ ++ vdev->config->reset(vdev); ++ ++ num_targets = sh->max_id; ++ for (i = 0; i < num_targets; i++) { ++ kfree(vscsi->tgt[i]); ++ vscsi->tgt[i] = NULL; ++ } ++ ++ vdev->config->del_vqs(vdev); ++} ++ ++static int virtscsi_init(struct virtio_device *vdev, ++ struct virtio_scsi *vscsi, int num_targets) ++{ ++ int err; ++ struct virtqueue *vqs[3]; ++ u32 i, sg_elems; ++ ++ vq_callback_t *callbacks[] = { ++ virtscsi_ctrl_done, ++ virtscsi_event_done, ++ virtscsi_req_done ++ }; ++ const char *names[] = { ++ "control", ++ "event", ++ "request" ++ }; ++ ++ /* Discover virtqueues and write information to configuration. */ ++ err = vdev->config->find_vqs(vdev, 3, vqs, callbacks, names); ++ if (err) ++ return err; ++ ++ virtscsi_init_vq(&vscsi->ctrl_vq, vqs[0]); ++ virtscsi_init_vq(&vscsi->event_vq, vqs[1]); ++ virtscsi_init_vq(&vscsi->req_vq, vqs[2]); ++ ++ virtscsi_config_set(vdev, cdb_size, VIRTIO_SCSI_CDB_SIZE); ++ virtscsi_config_set(vdev, sense_size, VIRTIO_SCSI_SENSE_SIZE); ++ ++ if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) ++ virtscsi_kick_event_all(vscsi); ++ ++ /* We need to know how many segments before we allocate. */ ++ sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1; ++ ++ for (i = 0; i < num_targets; i++) { ++ vscsi->tgt[i] = virtscsi_alloc_tgt(vdev, sg_elems); ++ if (!vscsi->tgt[i]) { ++ err = -ENOMEM; ++ goto out; ++ } ++ } ++ err = 0; ++ ++out: ++ if (err) ++ virtscsi_remove_vqs(vdev); ++ return err; ++} ++ ++static int __devinit virtscsi_probe(struct virtio_device *vdev) ++{ ++ struct Scsi_Host *shost; ++ struct virtio_scsi *vscsi; ++ int err; ++ u32 sg_elems, num_targets; ++ u32 cmd_per_lun; ++ ++ /* Allocate memory and link the structs together. */ ++ num_targets = virtscsi_config_get(vdev, max_target) + 1; ++ shost = scsi_host_alloc(&virtscsi_host_template, ++ sizeof(*vscsi) ++ + num_targets * sizeof(struct virtio_scsi_target_state)); ++ ++ if (!shost) ++ return -ENOMEM; ++ ++ sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1; ++ shost->sg_tablesize = sg_elems; ++ vscsi = shost_priv(shost); ++ vscsi->vdev = vdev; ++ vdev->priv = shost; ++ ++ err = virtscsi_init(vdev, vscsi, num_targets); ++ if (err) ++ goto virtscsi_init_failed; ++ ++ cmd_per_lun = virtscsi_config_get(vdev, cmd_per_lun) ?: 1; ++ shost->cmd_per_lun = min_t(u32, cmd_per_lun, shost->can_queue); ++ shost->max_sectors = virtscsi_config_get(vdev, max_sectors) ?: 0xFFFF; ++ ++ /* LUNs > 256 are reported with format 1, so they go in the range ++ * 16640-32767. ++ */ ++ shost->max_lun = virtscsi_config_get(vdev, max_lun) + 1 + 0x4000; ++ shost->max_id = num_targets; ++ shost->max_channel = 0; ++ shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE; ++ err = scsi_add_host(shost, &vdev->dev); ++ if (err) ++ goto scsi_add_host_failed; ++ /* ++ * scsi_scan_host() happens in virtscsi_scan() via virtio_driver->scan() ++ * after VIRTIO_CONFIG_S_DRIVER_OK has been set.. ++ */ ++ return 0; ++ ++scsi_add_host_failed: ++ vdev->config->del_vqs(vdev); ++virtscsi_init_failed: ++ scsi_host_put(shost); ++ return err; ++} ++ ++static void __devexit virtscsi_remove(struct virtio_device *vdev) ++{ ++ struct Scsi_Host *shost = virtio_scsi_host(vdev); ++ struct virtio_scsi *vscsi = shost_priv(shost); ++ ++ if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) ++ virtscsi_cancel_event_work(vscsi); ++ ++ scsi_remove_host(shost); ++ ++ virtscsi_remove_vqs(vdev); ++ scsi_host_put(shost); ++} ++ ++#if 0 ++static int virtscsi_freeze(struct virtio_device *vdev) ++{ ++ virtscsi_remove_vqs(vdev); ++ return 0; ++} ++ ++static int virtscsi_restore(struct virtio_device *vdev) ++{ ++ struct Scsi_Host *sh = virtio_scsi_host(vdev); ++ struct virtio_scsi *vscsi = shost_priv(sh); ++ ++ return virtscsi_init(vdev, vscsi, sh->max_id); ++} ++#endif ++ ++static struct virtio_device_id id_table[] = { ++ { VIRTIO_ID_SCSI, VIRTIO_DEV_ANY_ID }, ++ { 0 }, ++}; ++ ++static unsigned int features[] = { ++ VIRTIO_SCSI_F_HOTPLUG, ++ VIRTIO_SCSI_F_CHANGE, ++}; ++ ++static struct virtio_driver virtio_scsi_driver = { ++ .feature_table = features, ++ .feature_table_size = ARRAY_SIZE(features), ++ .driver.name = KBUILD_MODNAME, ++ .driver.owner = THIS_MODULE, ++ .id_table = id_table, ++ .probe = virtscsi_probe, ++ .scan = virtscsi_scan, ++#if 0 ++ .freeze = virtscsi_freeze, ++ .restore = virtscsi_restore, ++#endif ++ .remove = __devexit_p(virtscsi_remove), ++}; ++ ++static int __init init(void) ++{ ++ int ret = -ENOMEM; ++ ++ virtscsi_cmd_cache = KMEM_CACHE(virtio_scsi_cmd, 0); ++ if (!virtscsi_cmd_cache) { ++ printk(KERN_ERR "kmem_cache_create() for " ++ "virtscsi_cmd_cache failed\n"); ++ goto error; ++ } ++ ++ ++ virtscsi_cmd_pool = ++ mempool_create_slab_pool(VIRTIO_SCSI_MEMPOOL_SZ, ++ virtscsi_cmd_cache); ++ if (!virtscsi_cmd_pool) { ++ printk(KERN_ERR "mempool_create() for" ++ "virtscsi_cmd_pool failed\n"); ++ goto error; ++ } ++ ret = register_virtio_driver(&virtio_scsi_driver); ++ if (ret < 0) ++ goto error; ++ ++ return 0; ++ ++error: ++ if (virtscsi_cmd_pool) { ++ mempool_destroy(virtscsi_cmd_pool); ++ virtscsi_cmd_pool = NULL; ++ } ++ if (virtscsi_cmd_cache) { ++ kmem_cache_destroy(virtscsi_cmd_cache); ++ virtscsi_cmd_cache = NULL; ++ } ++ return ret; ++} ++ ++static void __exit fini(void) ++{ ++ unregister_virtio_driver(&virtio_scsi_driver); ++ mempool_destroy(virtscsi_cmd_pool); ++ kmem_cache_destroy(virtscsi_cmd_cache); ++} ++module_init(init); ++module_exit(fini); ++ ++MODULE_DEVICE_TABLE(virtio, id_table); ++MODULE_DESCRIPTION("Virtio SCSI HBA driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig +index 25cdff3..632fa9d 100644 +--- a/drivers/staging/Kconfig ++++ b/drivers/staging/Kconfig +@@ -80,8 +80,6 @@ source "drivers/staging/vt6655/Kconfig" + + source "drivers/staging/vt6656/Kconfig" + +-source "drivers/staging/hv/Kconfig" +- + source "drivers/staging/vme/Kconfig" + + source "drivers/staging/sep/Kconfig" +@@ -124,12 +122,16 @@ source "drivers/staging/cptm1217/Kconfig" + + source "drivers/staging/ste_rmi4/Kconfig" + +-source "drivers/staging/gma500/Kconfig" +- + source "drivers/staging/mei/Kconfig" + + source "drivers/staging/nvec/Kconfig" + + source "drivers/staging/media/Kconfig" + ++source "drivers/staging/fsl_qbman/Kconfig" ++ ++source "drivers/staging/fsl_pme2/Kconfig" ++ ++source "drivers/staging/fsl_rman/Kconfig" ++ + endif # STAGING +diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile +index a25f3f2..c19d40c 100644 +--- a/drivers/staging/Makefile ++++ b/drivers/staging/Makefile +@@ -31,7 +31,6 @@ obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/ + obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ + obj-$(CONFIG_VT6655) += vt6655/ + obj-$(CONFIG_VT6656) += vt6656/ +-obj-$(CONFIG_HYPERV) += hv/ + obj-$(CONFIG_VME_BUS) += vme/ + obj-$(CONFIG_DX_SEP) += sep/ + obj-$(CONFIG_IIO) += iio/ +@@ -54,6 +53,8 @@ obj-$(CONFIG_SND_INTEL_SST) += intel_sst/ + obj-$(CONFIG_SPEAKUP) += speakup/ + obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/ + obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ +-obj-$(CONFIG_DRM_PSB) += gma500/ + obj-$(CONFIG_INTEL_MEI) += mei/ + obj-$(CONFIG_MFD_NVEC) += nvec/ ++obj-$(CONFIG_FSL_DPA) += fsl_qbman/ ++obj-$(CONFIG_FSL_PME2) += fsl_pme2/ ++obj-$(CONFIG_FSL_RMAN_UIO) += fsl_rman/ +diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c +index bf62e0d..1b1ad1d 100644 +--- a/drivers/staging/comedi/drivers/usbdux.c ++++ b/drivers/staging/comedi/drivers/usbdux.c +@@ -2307,11 +2307,8 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw, + struct usb_device *usbdev = usbduxsub_tmp->usbdev; + int ret; + +- if (fw == NULL) { +- dev_err(&usbdev->dev, +- "Firmware complete handler without firmware!\n"); ++ if (fw == NULL) + return; +- } + + /* + * we need to upload the firmware here because fw will be +diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c +index 6144afb..50dd651 100644 +--- a/drivers/staging/comedi/drivers/usbduxsigma.c ++++ b/drivers/staging/comedi/drivers/usbduxsigma.c +@@ -2312,11 +2312,8 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw, + struct usb_device *usbdev = usbduxsub_tmp->usbdev; + int ret; + +- if (fw == NULL) { +- dev_err(&usbdev->dev, +- "Firmware complete handler without firmware!\n"); ++ if (fw == NULL) + return; +- } + + /* + * we need to upload the firmware here because fw will be +diff --git a/drivers/staging/fsl_pme2/Kconfig b/drivers/staging/fsl_pme2/Kconfig +new file mode 100644 +index 0000000..58c5f2d +--- /dev/null ++++ b/drivers/staging/fsl_pme2/Kconfig +@@ -0,0 +1,226 @@ ++config FSL_PME2 ++ bool "Freescale Datapath Pattern Matcher support" ++ depends on FSL_QMAN ++ ++menu "Freescale Datapath PME options" ++ depends on FSL_PME2 ++ ++config FSL_PME2_CTRL ++ bool "Freescale PME2 (p4080, etc) device control" ++ default y ++ ---help--- ++ This compiles device support for the Freescale PME2 pattern matching ++ part contained in datapath-enabled SoCs (ie. accessed via Qman and ++ Bman portal functionality). At least one guest operating system must ++ have this driver support, together with the appropriate device-tree ++ entry, for PME2 functionality to be available. It is responsible for ++ allocating system memory to the device and configuring it for ++ operation. For this reason, it must be built into the kernel and will ++ initialise during early kernel boot. ++ ++config FSL_PME2_PDSRSIZE ++ int "Pattern Description and Stateful Rule default table size" ++ depends on FSL_PME2_CTRL ++ range 74240 1048573 ++ default 131072 ++ help ++ Select the default size of the Pattern Description and Stateful Rule ++ table as the number of 128 byte entries. This only takes effect if ++ the device tree node doesn't have the 'fsl,pme-pdsr' property. ++ range 74240-1048573 (9.5MB-134MB) ++ default 131072 (16MB) ++ ++if FSL_PME2_CTRL ++comment "Statefule Rule Engine" ++endif ++ ++config FSL_PME2_SRESIZE ++ int "SRE Session Context Entries table default table size" ++ depends on FSL_PME2_CTRL ++ range 0 134217727 ++ default 327680 ++ help ++ Select the default size of the SRE Context Table as the number of 32 ++ byte entries. This only takes effect if the device tree node doesn't ++ have the 'fsl,pme-sre' property. ++ range 0-134217727 (0-4GB) ++ default 327680 (10MB) ++ ++config FSL_PME2_SRE_AIM ++ bool "Alternate Inconclusive Mode" ++ depends on FSL_PME2_CTRL ++ default n ++ help ++ Select the inconclusive match mode treatment. When true the ++ “alternate†inconclusive mode is used. When false the “default†++ inconclusive mode is used. ++ ++config FSL_PME2_SRE_ESR ++ bool "End of SUI Simple Report" ++ depends on FSL_PME2_CTRL ++ default n ++ help ++ Select if an End of SUI will produce a Simple End of SUI report. ++ ++config FSL_PME2_SRE_CTX_SIZE_PER_SESSION ++ int "Default SRE Context Size per Session (16 => 64KB, 17 => 128KB)" ++ depends on FSL_PME2_CTRL ++ range 5 17 ++ default 17 ++ help ++ Select SRE context size per session as a power of 2. ++ range 5-17 ++ Examples: ++ 5 => 32 B ++ 6 => 64 B ++ 7 => 128 B ++ 8 => 256 B ++ 9 => 512 B ++ 10 => 1 KB ++ 11 => 2 KB ++ 12 => 4 KB ++ 13 => 8 KB ++ 14 => 16 KB ++ 15 => 32 KB ++ 16 => 64 KB ++ 17 => 128 KB ++ ++config FSL_PME2_SRE_CNR ++ int "Configured Number of Stateful Rules as a multiple of 256 (128 => 32768 )" ++ depends on FSL_PME2_CTRL ++ range 0 128 ++ default 128 ++ help ++ Select number of stateful rules as a multiple of 256. ++ range 0-128 ++ Examples: ++ 0 => 0 ++ 1 => 256 ++ 2 => 512 ++ ... ++ 127 => 32512 ++ 128 => 32768 ++ ++config FSL_PME2_SRE_MAX_INSTRUCTION_LIMIT ++ int "Maximum number of SRE instructions to be executed per reaction." ++ depends on FSL_PME2_CTRL ++ range 0 65535 ++ default 65535 ++ help ++ Select the maximum number of SRE instructions to be executed per ++ reaction. ++ range 0 65535 ++ ++config FSL_PME2_SRE_MAX_BLOCK_NUMBER ++ int "Maximum number of Reaction Head blocks to be traversed per pattern match event" ++ depends on FSL_PME2_CTRL ++ range 0 32767 ++ default 32767 ++ help ++ Select the maximum number of reaction head blocks to be traversed per ++ pattern match event (e.g. a matched pattern or an End of SUI event). ++ range 0-32767 ++ ++config FSL_PME2_PORTAL ++ tristate "Freescale PME2 (p4080, etc) device usage" ++ default y ++ ---help--- ++ This compiles I/O support for the Freescale PME2 pattern matching ++ part contained in datapath-enabled SoCs (ie. accessed via Qman and ++ Bman portal functionality). ++ ++if FSL_PME2_PORTAL ++ ++config FSL_PME2_TEST_HIGH ++ tristate "PME2 high-level self-test" ++ default n ++ ---help--- ++ This uses the high-level Qman driver (and the cpu-affine portals it ++ manages) to perform high-level PME2 API testing with it. ++ ++config FSL_PME2_TEST_SCAN ++ tristate "PME2 scan self-test" ++ depends on FSL_PME2_CTRL ++ default n ++ ---help--- ++ This uses the high-level Qman driver (and the cpu-affine portals it ++ manages) to perform scan PME2 API testing with it. ++ ++config FSL_PME2_TEST_SCAN_WITH_BPID ++ bool "PME2 scan self-test with buffer pool" ++ depends on FSL_PME2_TEST_SCAN && FSL_BMAN ++ default y ++ ---help--- ++ This uses a buffer pool id for scan test ++ ++config FSL_PME2_TEST_SCAN_WITH_BPID_SIZE ++ int "Buffer Pool size." ++ depends on FSL_PME2_TEST_SCAN_WITH_BPID ++ range 0 11 ++ default 3 ++ ---help--- ++ This uses the specified buffer pool size. ++ ++config FSL_PME2_DB ++ tristate "PME2 Database support" ++ depends on FSL_PME2_CTRL ++ default y ++ ---help--- ++ This compiles the database driver for PME2. ++ ++config FSL_PME2_DB_QOSOUT_PRIORITY ++ int "PME DB output frame queue priority." ++ depends on FSL_PME2_DB ++ range 0 7 ++ default 2 ++ ---help--- ++ The PME DB has a scheduled output frame queue. The qos priority level is configurable. ++ range 0-7 ++ 0 => High Priority 0 ++ 1 => High Priority 1 ++ 2 => Medium Priority ++ 3 => Medium Priority ++ 4 => Medium Priority ++ 5 => Low Priority ++ 6 => Low Priority ++ 7 => Low Priority ++ ++config FSL_PME2_SCAN ++ tristate "PME2 Scan support" ++ default y ++ ---help--- ++ This compiles the scan driver for PME2. ++ ++config FSL_PME2_SCAN_DEBUG ++ bool "Debug Statements" ++ default n ++ depends on FSL_PME2_SCAN ++ ---help--- ++ The PME2_SCAN driver can optionally trace with more verbosity ++ of verbosity. ++ ++config FSL_PME_BUG_4K_SCAN_REV_2_1_4 ++ bool "workaround for errata in PME version 2.1.4" ++ default y ++ ---help--- ++ If this option is selected, the driver will be compiled with a ++ workaround for this errata. This prevents scans of SUIs greater ++ than 4095 - 127 bytes when this revision of HW is detected. ++ ++ If in doubt, say Y. ++ ++ ++endif ++ ++config FSL_PME2_STAT_ACCUMULATOR_UPDATE_INTERVAL ++ int "Configure the pme2 statistics update interval in milliseconds" ++ depends on FSL_PME2_CTRL ++ range 0 10000 ++ default 3400 ++ help ++ The pme accumulator reads the current device statistics and add it ++ to a running counter. The frequency of these updates may be ++ controlled. If 0 is specified, no automatic updates is done. ++ range 0-10000 ++ ++endmenu +diff --git a/drivers/staging/fsl_pme2/Makefile b/drivers/staging/fsl_pme2/Makefile +new file mode 100644 +index 0000000..694513b +--- /dev/null ++++ b/drivers/staging/fsl_pme2/Makefile +@@ -0,0 +1,9 @@ ++# PME ++obj-$(CONFIG_FSL_PME2_CTRL) += pme2_ctrl.o pme2_sysfs.o ++obj-$(CONFIG_FSL_PME2_PORTAL) += pme2.o ++pme2-y := pme2_low.o pme2_high.o ++obj-$(CONFIG_FSL_PME2_TEST_HIGH) += pme2_test_high.o ++obj-$(CONFIG_FSL_PME2_TEST_SCAN) += pme2_test_scanning.o ++pme2_test_scanning-y = pme2_test_scan.o pme2_sample_db.o ++obj-$(CONFIG_FSL_PME2_DB) += pme2_db.o ++obj-$(CONFIG_FSL_PME2_SCAN) += pme2_scan.o +diff --git a/drivers/staging/fsl_pme2/pme2_ctrl.c b/drivers/staging/fsl_pme2/pme2_ctrl.c +new file mode 100644 +index 0000000..4022c72 +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_ctrl.c +@@ -0,0 +1,1331 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "pme2_private.h" ++#include "pme2_regs.h" ++ ++/* PME HW Revision */ ++#define PME_REV(rev1_reg) (rev1_reg & 0x0000FFFF) ++#define PME_REV_2_0 0x00000200 ++#define PME_REV_2_1 0x00000201 ++#define DEC1_MAX_REV_2_0 0x000FFFFC ++#define DEC1_MAX_REV_2_1 0x0007FFFC ++ ++ ++/* Driver Name is used in naming the sysfs directory ++ * /sys/bus/of_platform/drivers/DRV_NAME ++ */ ++#define DRV_NAME "fsl-pme" ++ ++#define DEFAULT_PDSR_SZ (CONFIG_FSL_PME2_PDSRSIZE << 7) ++#define DEFAULT_SRE_SZ (CONFIG_FSL_PME2_SRESIZE << 5) ++#define PDSR_TBL_ALIGN (1 << 7) ++#define SRE_TBL_ALIGN (1 << 5) ++#define DEFAULT_SRFCC 400 ++ ++/* Defaults */ ++#define DEFAULT_DEC0_MTE 0x3FFF ++#define DEFAULT_DLC_MPM 0xFFFF ++#define DEFAULT_DLC_MPE 0xFFFF ++/* Boot parameters */ ++DECLARE_GLOBAL(max_test_line_per_pat, unsigned int, uint, ++ DEFAULT_DEC0_MTE, ++ "Maximum allowed Test Line Executions per pattern, " ++ "scaled by a factor of 8"); ++DECLARE_GLOBAL(max_pat_eval_per_sui, unsigned int, uint, ++ DEFAULT_DLC_MPE, ++ "Maximum Pattern Evaluations per SUI, scaled by a factor of 8") ++DECLARE_GLOBAL(max_pat_matches_per_sui, unsigned int, uint, ++ DEFAULT_DLC_MPM, ++ "Maximum Pattern Matches per SUI"); ++/* SRE */ ++DECLARE_GLOBAL(sre_rule_num, unsigned int, uint, ++ CONFIG_FSL_PME2_SRE_CNR, ++ "Configured Number of Stateful Rules"); ++DECLARE_GLOBAL(sre_session_ctx_size, unsigned int, uint, ++ 1 << CONFIG_FSL_PME2_SRE_CTX_SIZE_PER_SESSION, ++ "SRE Context Size per Session"); ++ ++/************ ++ * Section 1 ++ ************ ++ * This code is called during kernel early-boot and could never be made ++ * loadable. ++ */ ++static dma_addr_t dxe_a, sre_a; ++static size_t dxe_sz = DEFAULT_PDSR_SZ, sre_sz = DEFAULT_SRE_SZ; ++ ++/* Parse the property to extract the memory location and size and ++ * memblock_reserve() it. If it isn't supplied, memblock_alloc() the default size. */ ++static __init int parse_mem_property(struct device_node *node, const char *name, ++ dma_addr_t *addr, size_t *sz, u64 align, int zero) ++{ ++ const u32 *pint; ++ int ret; ++ ++ pint = of_get_property(node, name, &ret); ++ if (!pint || (ret != 16)) { ++ pr_info("pme: No %s property '%s', using memblock_alloc(0x%016zx)\n", ++ node->full_name, name, *sz); ++ *addr = memblock_alloc(*sz, align); ++ if (zero) ++ memset(phys_to_virt(*addr), 0, *sz); ++ return 0; ++ } ++ pr_info("pme: Using %s property '%s'\n", node->full_name, name); ++ /* If using a "zero-pma", don't try to zero it, even if you asked */ ++ if (zero && of_find_property(node, "zero-pma", &ret)) { ++ pr_info(" it's a 'zero-pma', not zeroing from s/w\n"); ++ zero = 0; ++ } ++ *addr = ((u64)pint[0] << 32) | (u64)pint[1]; ++ *sz = ((u64)pint[2] << 32) | (u64)pint[3]; ++ if((u64)*addr & (align - 1)) { ++ pr_err("pme: Invalid alignment, address %016llx\n",(u64)*addr); ++ return -EINVAL; ++ } ++ /* Keep things simple, it's either all in the DRAM range or it's all ++ * outside. */ ++ if (*addr < memblock_end_of_DRAM()) { ++ if ((u64)*addr + (u64)*sz > memblock_end_of_DRAM()){ ++ pr_err("pme: outside DRAM range\n"); ++ return -EINVAL; ++ } ++ if (memblock_reserve(*addr, *sz) < 0) { ++ pr_err("pme: Failed to reserve %s\n", name); ++ return -ENOMEM; ++ } ++ if (zero) ++ memset(phys_to_virt(*addr), 0, *sz); ++ } else if (zero) { ++ /* map as cacheable, non-guarded */ ++ void *tmpp = ioremap_prot(*addr, *sz, 0); ++ memset(tmpp, 0, *sz); ++ iounmap(tmpp); ++ } ++ return 0; ++} ++ ++/* No errors/interrupts. Physical addresses are assumed <= 32bits. */ ++static int __init fsl_pme2_init(struct device_node *node) ++{ ++ const char *s; ++ int ret = 0; ++ ++ s = of_get_property(node, "fsl,hv-claimable", &ret); ++ if (s && !strcmp(s, "standby")) { ++ pr_info(" -> in standby mode\n"); ++ return 0; ++ } ++ /* Check if pdsr memory already allocated */ ++ if (dxe_a) { ++ pr_err("pme: Error fsl_pme2_init already done\n"); ++ return -EINVAL; ++ } ++ ret = parse_mem_property(node, "fsl,pme-pdsr", &dxe_a, &dxe_sz, ++ PDSR_TBL_ALIGN, 0); ++ if (ret) ++ return ret; ++ ret = parse_mem_property(node, "fsl,pme-sre", &sre_a, &sre_sz, ++ SRE_TBL_ALIGN, 0); ++ return ret; ++} ++ ++__init void pme2_init_early(void) ++{ ++ struct device_node *dn; ++ int ret; ++ for_each_compatible_node(dn, NULL, "fsl,pme") { ++ ret = fsl_pme2_init(dn); ++ if (ret) ++ pr_err("pme: Error fsl_pme2_init\n"); ++ } ++} ++ ++/************ ++ * Section 2 ++ *********** ++ * This code is called during driver initialisation. It doesn't do anything with ++ * the device-tree entries nor the PME device, it simply creates the sysfs stuff ++ * and gives the user something to hold. This could be made loadable, if there ++ * was any benefit to doing so - but as the device is already "bound" by static ++ * code, there's little point to hiding the fact. ++ */ ++ ++MODULE_AUTHOR("Geoff Thorpe"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("FSL PME2 (p4080) device control"); ++ ++/* Opaque pointer target used to represent the PME CCSR map, ... */ ++struct pme; ++ ++/* ... and the instance of it. */ ++static struct pme *global_pme; ++static int pme_err_irq; ++ ++static inline void __pme_out(struct pme *p, u32 offset, u32 val) ++{ ++ u32 __iomem *regs = (void *)p; ++ out_be32(regs + (offset >> 2), val); ++} ++#define pme_out(p, r, v) __pme_out(p, PME_REG_##r, v) ++static inline u32 __pme_in(struct pme *p, u32 offset) ++{ ++ u32 __iomem *regs = (void *)p; ++ return in_be32(regs + (offset >> 2)); ++} ++#define pme_in(p, r) __pme_in(p, PME_REG_##r) ++ ++#define PME_EFQC(en, fq) \ ++ ({ \ ++ /* Assume a default delay of 64 cycles */ \ ++ u8 __i419 = 0x1; \ ++ u32 __fq419 = (fq) & 0x00ffffff; \ ++ ((en) ? 0x80000000 : 0) | (__i419 << 28) | __fq419; \ ++ }) ++ ++#define PME_FACONF_ENABLE 0x00000002 ++#define PME_FACONF_RESET 0x00000001 ++ ++/* pme stats accumulator work */ ++static void accumulator_update(struct work_struct *work); ++void accumulator_update_interval(u32 interval); ++static DECLARE_DELAYED_WORK(accumulator_work, accumulator_update); ++u32 pme_stat_interval = CONFIG_FSL_PME2_STAT_ACCUMULATOR_UPDATE_INTERVAL; ++#define PME_SBE_ERR 0x01000000 ++#define PME_DBE_ERR 0x00080000 ++#define PME_PME_ERR 0x00000100 ++#define PME_ALL_ERR (PME_SBE_ERR | PME_DBE_ERR | PME_PME_ERR) ++ ++static struct of_device_id of_fsl_pme_ids[] = { ++ { ++ .compatible = "fsl,pme", ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, of_fsl_pme_ids); ++ ++/* Pme interrupt handler */ ++static irqreturn_t pme_isr(int irq, void *ptr) ++{ ++ static u32 last_isrstate; ++ u32 isrstate = pme_in(global_pme, ISR) ^ last_isrstate; ++ ++ /* What new ISR state has been raise */ ++ if (!isrstate) ++ return IRQ_NONE; ++ if (isrstate & PME_SBE_ERR) ++ pr_crit("PME: SBE detected\n"); ++ if (isrstate & PME_DBE_ERR) ++ pr_crit("PME: DBE detected\n"); ++ if (isrstate & PME_PME_ERR) ++ pr_crit("PME: PME serious detected\n"); ++ /* Clear the ier interrupt bit */ ++ last_isrstate |= isrstate; ++ pme_out(global_pme, IER, ~last_isrstate); ++ return IRQ_HANDLED; ++} ++ ++static int of_fsl_pme_remove(struct platform_device *ofdev) ++{ ++ /* Cancel pme accumulator */ ++ accumulator_update_interval(0); ++ cancel_delayed_work_sync(&accumulator_work); ++ /* Disable PME..TODO need to wait till it's quiet */ ++ pme_out(global_pme, FACONF, PME_FACONF_RESET); ++ /* Release interrupt */ ++ if (likely(pme_err_irq != NO_IRQ)) ++ free_irq(pme_err_irq, &ofdev->dev); ++ /* Remove sysfs attribute */ ++ pme2_remove_sysfs_dev_files(ofdev); ++ /* Unmap controller region */ ++ iounmap(global_pme); ++ global_pme = NULL; ++ return 0; ++} ++ ++static int __devinit of_fsl_pme_probe(struct platform_device *ofdev) ++{ ++ int ret, err = 0; ++ void __iomem *regs; ++ struct device *dev = &ofdev->dev; ++ struct device_node *nprop = dev->of_node; ++ u32 clkfreq = DEFAULT_SRFCC * 1000000; ++ const u32 *value; ++ const char *s; ++ int srec_aim = 0, srec_esr = 0; ++ u32 srecontextsize_code; ++ u32 dec1; ++ ++ /* TODO: This standby handling won't work properly after failover, it's ++ * just to allow bring up for now. */ ++ s = of_get_property(nprop, "fsl,hv-claimable", &ret); ++ if (s && !strcmp(s, "standby")) ++ return 0; ++ pme_err_irq = of_irq_to_resource(nprop, 0, NULL); ++ if (unlikely(pme_err_irq == NO_IRQ)) ++ dev_warn(dev, "Can't get %s property '%s'\n", nprop->full_name, ++ "interrupts"); ++ ++ /* Get configuration properties from device tree */ ++ /* First, get register page */ ++ regs = of_iomap(nprop, 0); ++ if (regs == NULL) { ++ dev_err(dev, "of_iomap() failed\n"); ++ err = -EINVAL; ++ goto out; ++ } ++ ++ /* Global configuration, leave pme disabled */ ++ global_pme = (struct pme *)regs; ++ pme_out(global_pme, FACONF, 0); ++ pme_out(global_pme, EFQC, PME_EFQC(0, 0)); ++ ++ /* TODO: these coherency settings for PMFA, DXE, and SRE force all ++ * transactions to snoop, as the kernel does not yet support flushing in ++ * dma_map_***() APIs (ie. h/w can not treat otherwise coherent memory ++ * in a non-coherent manner, temporarily or otherwise). When the kernel ++ * supports this, we should tune these settings back to; ++ * FAMCR = 0x00010001 ++ * DMCR = 0x00000000 ++ * SMCR = 0x00000000 ++ */ ++ /* PME HW rev 2.1: Added TWC field in FAMCR */ ++ pme_out(global_pme, FAMCR, 0x11010101); ++ pme_out(global_pme, DMCR, 0x00000001); ++ pme_out(global_pme, SMCR, 0x00000211); ++ ++ if (likely(pme_err_irq != NO_IRQ)) { ++ /* Register the pme ISR handler */ ++ err = request_irq(pme_err_irq, pme_isr, IRQF_SHARED, "pme-err", ++ dev); ++ if (err) { ++ dev_err(dev, "request_irq() failed\n"); ++ goto out_unmap_ctrl_region; ++ } ++ } ++ ++#ifdef CONFIG_FSL_PME2_SRE_AIM ++ srec_aim = 1; ++#endif ++#ifdef CONFIG_FSL_PME2_SRE_ESR ++ srec_esr = 1; ++#endif ++ /* Validate some parameters */ ++ if (!sre_session_ctx_size || !is_power_of_2(sre_session_ctx_size) || ++ (sre_session_ctx_size < 32) || ++ (sre_session_ctx_size > (131072))) { ++ dev_err(dev, "invalid sre_session_ctx_size\n"); ++ err = -EINVAL; ++ goto out_free_irq; ++ } ++ srecontextsize_code = ilog2(sre_session_ctx_size); ++ srecontextsize_code -= 4; ++ ++ /* Configure Clock Frequency */ ++ value = of_get_property(nprop, "clock-frequency", NULL); ++ if (value) ++ clkfreq = *value; ++ pme_out(global_pme, SFRCC, DIV_ROUND_UP(clkfreq, 1000000)); ++ ++ pme_out(global_pme, PDSRBAH, upper_32_bits(dxe_a)); ++ pme_out(global_pme, PDSRBAL, lower_32_bits(dxe_a)); ++ pme_out(global_pme, SCBARH, upper_32_bits(sre_a)); ++ pme_out(global_pme, SCBARL, lower_32_bits(sre_a)); ++ /* Maximum allocated index into the PDSR table available to the DXE ++ * Rev 2.0: Max 0xF_FFFC ++ * Rev 2.1: Max 0x7_FFFC ++ */ ++ if (PME_REV(pme_in(global_pme, PM_IP_REV1)) == PME_REV_2_0) { ++ if (((dxe_sz/PDSR_TBL_ALIGN)-1) > DEC1_MAX_REV_2_0) ++ dec1 = DEC1_MAX_REV_2_0; ++ else ++ dec1 = (dxe_sz/PDSR_TBL_ALIGN)-1; ++ } else { ++ if (((dxe_sz/PDSR_TBL_ALIGN)-1) > DEC1_MAX_REV_2_1) ++ dec1 = DEC1_MAX_REV_2_1; ++ else ++ dec1 = (dxe_sz/PDSR_TBL_ALIGN)-1; ++ } ++ pme_out(global_pme, DEC1, dec1); ++ /* Maximum allocated index into the PDSR table available to the SRE */ ++ pme_out(global_pme, SEC2, dec1); ++ /* Maximum allocated 32-byte offset into SRE Context Table.*/ ++ if (sre_sz) ++ pme_out(global_pme, SEC3, (sre_sz/SRE_TBL_ALIGN)-1); ++ /* Max test line execution */ ++ pme_out(global_pme, DEC0, max_test_line_per_pat); ++ pme_out(global_pme, DLC, ++ (max_pat_eval_per_sui << 16) | max_pat_matches_per_sui); ++ ++ /* SREC - SRE Config */ ++ pme_out(global_pme, SREC, ++ /* Number of rules in database */ ++ (sre_rule_num << 0) | ++ /* Simple Report Enabled */ ++ ((srec_esr ? 1 : 0) << 18) | ++ /* Context Size per Session */ ++ (srecontextsize_code << 19) | ++ /* Alternate Inclusive Mode */ ++ ((srec_aim ? 1 : 0) << 29)); ++ pme_out(global_pme, SEC1, ++ (CONFIG_FSL_PME2_SRE_MAX_INSTRUCTION_LIMIT << 16) | ++ CONFIG_FSL_PME2_SRE_MAX_BLOCK_NUMBER); ++ ++ /* Setup Accumulator */ ++ if (pme_stat_interval) ++ schedule_delayed_work(&accumulator_work, ++ msecs_to_jiffies(pme_stat_interval)); ++ /* Create sysfs entries */ ++ err = pme2_create_sysfs_dev_files(ofdev); ++ if (err) ++ goto out_stop_accumulator; ++ ++ /* Enable interrupts */ ++ pme_out(global_pme, IER, PME_ALL_ERR); ++ dev_info(dev, "ver: 0x%08x\n", pme_in(global_pme, PM_IP_REV1)); ++ ++ /* Enable pme */ ++ pme_out(global_pme, FACONF, PME_FACONF_ENABLE); ++ return 0; ++ ++out_stop_accumulator: ++ if (pme_stat_interval) { ++ accumulator_update_interval(0); ++ cancel_delayed_work_sync(&accumulator_work); ++ } ++out_free_irq: ++ if (likely(pme_err_irq != NO_IRQ)) ++ free_irq(pme_err_irq, &ofdev->dev); ++out_unmap_ctrl_region: ++ pme_out(global_pme, FACONF, PME_FACONF_RESET); ++ iounmap(global_pme); ++ global_pme = NULL; ++out: ++ return err; ++} ++ ++static struct platform_driver of_fsl_pme_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = DRV_NAME, ++ .of_match_table = of_fsl_pme_ids, ++ }, ++ .probe = of_fsl_pme_probe, ++ .remove = __devexit_p(of_fsl_pme_remove), ++}; ++ ++static int pme2_ctrl_init(void) ++{ ++ return platform_driver_register(&of_fsl_pme_driver); ++} ++ ++static void pme2_ctrl_exit(void) ++{ ++ platform_driver_unregister(&of_fsl_pme_driver); ++} ++ ++module_init(pme2_ctrl_init); ++module_exit(pme2_ctrl_exit); ++ ++/************ ++ * Section 3 ++ ************ ++ * These APIs are the only functional hooks into the control driver, besides the ++ * sysfs attributes. ++ */ ++ ++int pme2_have_control(void) ++{ ++ return global_pme ? 1 : 0; ++} ++EXPORT_SYMBOL(pme2_have_control); ++ ++int pme2_exclusive_set(struct qman_fq *fq) ++{ ++ if (!pme2_have_control()) ++ return -ENODEV; ++ pme_out(global_pme, EFQC, PME_EFQC(1, qman_fq_fqid(fq))); ++ return 0; ++} ++EXPORT_SYMBOL(pme2_exclusive_set); ++ ++int pme2_exclusive_unset(void) ++{ ++ if (!pme2_have_control()) ++ return -ENODEV; ++ pme_out(global_pme, EFQC, PME_EFQC(0, 0)); ++ return 0; ++} ++EXPORT_SYMBOL(pme2_exclusive_unset); ++ ++int pme_attr_set(enum pme_attr attr, u32 val) ++{ ++ u32 mask; ++ u32 attr_val; ++ ++ if (!pme2_have_control()) ++ return -ENODEV; ++ ++ /* Check if Buffer size configuration */ ++ if (attr >= pme_attr_bsc_first && attr <= pme_attr_bsc_last) { ++ u32 bsc_pool_id = attr - pme_attr_bsc_first; ++ u32 bsc_pool_offset = bsc_pool_id % 8; ++ u32 bsc_pool_mask = ~(0xF << ((7-bsc_pool_offset)*4)); ++ /* range for val 0..0xB */ ++ if (val > 0xb) ++ return -EINVAL; ++ /* calculate which sky-blue reg */ ++ /* 0..7 -> bsc_(0..7), PME_REG_BSC0 */ ++ /* 8..15 -> bsc_(8..15) PME_REG_BSC1*/ ++ /* ... */ ++ /* 56..63 -> bsc_(56..63) PME_REG_BSC7*/ ++ attr_val = pme_in(global_pme, BSC0 + ((bsc_pool_id/8)*4)); ++ /* Now mask in the new value */ ++ attr_val = attr_val & bsc_pool_mask; ++ attr_val = attr_val | (val << ((7-bsc_pool_offset)*4)); ++ pme_out(global_pme, BSC0 + ((bsc_pool_id/8)*4), attr_val); ++ return 0; ++ } ++ ++ switch (attr) { ++ case pme_attr_efqc_int: ++ if (val > 4) ++ return -EINVAL; ++ mask = 0x8FFFFFFF; ++ attr_val = pme_in(global_pme, EFQC); ++ /* clear efqc_int */ ++ attr_val &= mask; ++ val <<= 28; ++ val |= attr_val; ++ pme_out(global_pme, EFQC, val); ++ break; ++ ++ case pme_attr_sw_db: ++ pme_out(global_pme, SWDB, val); ++ break; ++ ++ case pme_attr_dmcr: ++ pme_out(global_pme, DMCR, val); ++ break; ++ ++ case pme_attr_smcr: ++ pme_out(global_pme, SMCR, val); ++ break; ++ ++ case pme_attr_famcr: ++ pme_out(global_pme, FAMCR, val); ++ break; ++ ++ case pme_attr_kvlts: ++ if (val < 2 || val > 16) ++ return -EINVAL; ++ /* HW range: 1..15, SW range: 2..16 */ ++ pme_out(global_pme, KVLTS, --val); ++ break; ++ ++ case pme_attr_max_chain_length: ++ if (val > 0x7FFF) ++ val = 0x7FFF; ++ pme_out(global_pme, KEC, val); ++ break; ++ ++ case pme_attr_pattern_range_counter_idx: ++ if (val > 0x1FFFF) ++ val = 0x1FFFF; ++ pme_out(global_pme, DRCIC, val); ++ break; ++ ++ case pme_attr_pattern_range_counter_mask: ++ if (val > 0x1FFFF) ++ val = 0x1FFFF; ++ pme_out(global_pme, DRCMC, val); ++ break; ++ ++ case pme_attr_max_allowed_test_line_per_pattern: ++ if (val > 0x3FFF) ++ val = 0x3FFF; ++ pme_out(global_pme, DEC0, val); ++ break; ++ ++ case pme_attr_max_pattern_matches_per_sui: ++ /* mpe, mpm */ ++ if (val > 0xFFFF) ++ val = 0xFFFF; ++ mask = 0xFFFF0000; ++ attr_val = pme_in(global_pme, DLC); ++ /* clear mpm */ ++ attr_val &= mask; ++ val &= ~mask; ++ val |= attr_val; ++ pme_out(global_pme, DLC, val); ++ break; ++ ++ case pme_attr_max_pattern_evaluations_per_sui: ++ /* mpe, mpm */ ++ if (val > 0xFFFF) ++ val = 0xFFFF; ++ mask = 0x0000FFFF; ++ attr_val = pme_in(global_pme, DLC); ++ /* clear mpe */ ++ attr_val &= mask; ++ /* clear unwanted bits in val*/ ++ val &= mask; ++ val <<= 16; ++ val |= attr_val; ++ pme_out(global_pme, DLC, val); ++ break; ++ ++ case pme_attr_report_length_limit: ++ if (val > 0xFFFF) ++ val = 0xFFFF; ++ pme_out(global_pme, RLL, val); ++ break; ++ ++ case pme_attr_end_of_simple_sui_report: ++ /* bit 13 */ ++ mask = 0x00040000; ++ attr_val = pme_in(global_pme, SREC); ++ if (val) ++ attr_val |= mask; ++ else ++ attr_val &= ~mask; ++ pme_out(global_pme, SREC, attr_val); ++ break; ++ ++ case pme_attr_aim: ++ /* bit 2 */ ++ mask = 0x20000000; ++ attr_val = pme_in(global_pme, SREC); ++ if (val) ++ attr_val |= mask; ++ else ++ attr_val &= ~mask; ++ pme_out(global_pme, SREC, attr_val); ++ break; ++ ++ case pme_attr_end_of_sui_reaction_ptr: ++ if (val > 0xFFFFF) ++ val = 0xFFFFF; ++ pme_out(global_pme, ESRP, val); ++ break; ++ ++ case pme_attr_sre_pscl: ++ pme_out(global_pme, SFRCC, val); ++ break; ++ ++ case pme_attr_sre_max_block_num: ++ /* bits 17..31 */ ++ if (val > 0x7FFF) ++ val = 0x7FFF; ++ mask = 0xFFFF8000; ++ attr_val = pme_in(global_pme, SEC1); ++ /* clear mbn */ ++ attr_val &= mask; ++ /* clear unwanted bits in val*/ ++ val &= ~mask; ++ val |= attr_val; ++ pme_out(global_pme, SEC1, val); ++ break; ++ ++ case pme_attr_sre_max_instruction_limit: ++ /* bits 0..15 */ ++ if (val > 0xFFFF) ++ val = 0xFFFF; ++ mask = 0x0000FFFF; ++ attr_val = pme_in(global_pme, SEC1); ++ /* clear mil */ ++ attr_val &= mask; ++ /* clear unwanted bits in val*/ ++ val &= mask; ++ val <<= 16; ++ val |= attr_val; ++ pme_out(global_pme, SEC1, val); ++ break; ++ ++ case pme_attr_srrv0: ++ pme_out(global_pme, SRRV0, val); ++ break; ++ case pme_attr_srrv1: ++ pme_out(global_pme, SRRV1, val); ++ break; ++ case pme_attr_srrv2: ++ pme_out(global_pme, SRRV2, val); ++ break; ++ case pme_attr_srrv3: ++ pme_out(global_pme, SRRV3, val); ++ break; ++ case pme_attr_srrv4: ++ pme_out(global_pme, SRRV4, val); ++ break; ++ case pme_attr_srrv5: ++ pme_out(global_pme, SRRV5, val); ++ break; ++ case pme_attr_srrv6: ++ pme_out(global_pme, SRRV6, val); ++ break; ++ case pme_attr_srrv7: ++ pme_out(global_pme, SRRV7, val); ++ break; ++ case pme_attr_srrfi: ++ pme_out(global_pme, SRRFI, val); ++ break; ++ case pme_attr_srri: ++ pme_out(global_pme, SRRI, val); ++ break; ++ case pme_attr_srrwc: ++ pme_out(global_pme, SRRWC, val); ++ break; ++ case pme_attr_srrr: ++ pme_out(global_pme, SRRR, val); ++ break; ++ case pme_attr_tbt0ecc1th: ++ pme_out(global_pme, TBT0ECC1TH, val); ++ break; ++ case pme_attr_tbt1ecc1th: ++ pme_out(global_pme, TBT1ECC1TH, val); ++ break; ++ case pme_attr_vlt0ecc1th: ++ pme_out(global_pme, VLT0ECC1TH, val); ++ break; ++ case pme_attr_vlt1ecc1th: ++ pme_out(global_pme, VLT1ECC1TH, val); ++ break; ++ case pme_attr_cmecc1th: ++ pme_out(global_pme, CMECC1TH, val); ++ break; ++ case pme_attr_dxcmecc1th: ++ pme_out(global_pme, DXCMECC1TH, val); ++ break; ++ case pme_attr_dxemecc1th: ++ pme_out(global_pme, DXEMECC1TH, val); ++ break; ++ case pme_attr_esr: ++ pme_out(global_pme, ESR, val); ++ break; ++ case pme_attr_pehd: ++ pme_out(global_pme, PEHD, val); ++ break; ++ case pme_attr_ecc1bes: ++ pme_out(global_pme, ECC1BES, val); ++ break; ++ case pme_attr_ecc2bes: ++ pme_out(global_pme, ECC2BES, val); ++ break; ++ case pme_attr_miace: ++ pme_out(global_pme, MIA_CE, val); ++ break; ++ case pme_attr_miacr: ++ pme_out(global_pme, MIA_CR, val); ++ break; ++ case pme_attr_cdcr: ++ pme_out(global_pme, CDCR, val); ++ break; ++ case pme_attr_pmtr: ++ pme_out(global_pme, PMTR, val); ++ break; ++ ++ default: ++ pr_err("pme: Unknown attr %u\n", attr); ++ return -EINVAL; ++ }; ++ return 0; ++} ++EXPORT_SYMBOL(pme_attr_set); ++ ++int pme_attr_get(enum pme_attr attr, u32 *val) ++{ ++ u32 mask; ++ u32 attr_val; ++ ++ if (!pme2_have_control()) ++ return -ENODEV; ++ ++ /* Check if Buffer size configuration */ ++ if (attr >= pme_attr_bsc_first && attr <= pme_attr_bsc_last) { ++ u32 bsc_pool_id = attr - pme_attr_bsc_first; ++ u32 bsc_pool_offset = bsc_pool_id % 8; ++ /* calculate which sky-blue reg */ ++ /* 0..7 -> bsc_(0..7), PME_REG_BSC0 */ ++ /* 8..15 -> bsc_(8..15) PME_REG_BSC1*/ ++ /* ... */ ++ /* 56..63 -> bsc_(56..63) PME_REG_BSC7*/ ++ attr_val = pme_in(global_pme, BSC0 + ((bsc_pool_id/8)*4)); ++ attr_val = attr_val >> ((7-bsc_pool_offset)*4); ++ attr_val = attr_val & 0x0000000F; ++ *val = attr_val; ++ return 0; ++ } ++ ++ switch (attr) { ++ case pme_attr_efqc_int: ++ mask = 0x8FFFFFFF; ++ attr_val = pme_in(global_pme, EFQC); ++ attr_val &= ~mask; ++ attr_val >>= 28; ++ break; ++ ++ case pme_attr_sw_db: ++ attr_val = pme_in(global_pme, SWDB); ++ break; ++ ++ case pme_attr_dmcr: ++ attr_val = pme_in(global_pme, DMCR); ++ break; ++ ++ case pme_attr_smcr: ++ attr_val = pme_in(global_pme, SMCR); ++ break; ++ ++ case pme_attr_famcr: ++ attr_val = pme_in(global_pme, FAMCR); ++ break; ++ ++ case pme_attr_kvlts: ++ /* bit 28-31 */ ++ attr_val = pme_in(global_pme, KVLTS); ++ attr_val &= 0x0000000F; ++ /* HW range: 1..15, SW range: 2..16 */ ++ attr_val += 1; ++ break; ++ ++ case pme_attr_max_chain_length: ++ /* bit 17-31 */ ++ attr_val = pme_in(global_pme, KEC); ++ attr_val &= 0x00007FFF; ++ break; ++ ++ case pme_attr_pattern_range_counter_idx: ++ /* bit 15-31 */ ++ attr_val = pme_in(global_pme, DRCIC); ++ attr_val &= 0x0001FFFF; ++ break; ++ ++ case pme_attr_pattern_range_counter_mask: ++ /* bit 15-31 */ ++ attr_val = pme_in(global_pme, DRCMC); ++ attr_val &= 0x0001FFFF; ++ break; ++ ++ case pme_attr_max_allowed_test_line_per_pattern: ++ /* bit 18-31 */ ++ attr_val = pme_in(global_pme, DEC0); ++ attr_val &= 0x00003FFF; ++ break; ++ ++ case pme_attr_max_pdsr_index: ++ /* bit 12-31 */ ++ attr_val = pme_in(global_pme, DEC1); ++ attr_val &= 0x000FFFFF; ++ break; ++ ++ case pme_attr_max_pattern_matches_per_sui: ++ attr_val = pme_in(global_pme, DLC); ++ attr_val &= 0x0000FFFF; ++ break; ++ ++ case pme_attr_max_pattern_evaluations_per_sui: ++ attr_val = pme_in(global_pme, DLC); ++ attr_val >>= 16; ++ break; ++ ++ case pme_attr_report_length_limit: ++ attr_val = pme_in(global_pme, RLL); ++ /* clear unwanted bits in val*/ ++ attr_val &= 0x0000FFFF; ++ break; ++ ++ case pme_attr_end_of_simple_sui_report: ++ /* bit 13 */ ++ attr_val = pme_in(global_pme, SREC); ++ attr_val >>= 18; ++ /* clear unwanted bits in val*/ ++ attr_val &= 0x00000001; ++ break; ++ ++ case pme_attr_aim: ++ /* bit 2 */ ++ attr_val = pme_in(global_pme, SREC); ++ attr_val >>= 29; ++ /* clear unwanted bits in val*/ ++ attr_val &= 0x00000001; ++ break; ++ ++ case pme_attr_sre_context_size: ++ /* bits 9..12 */ ++ attr_val = pme_in(global_pme, SREC); ++ attr_val >>= 19; ++ /* clear unwanted bits in val*/ ++ attr_val &= 0x0000000F; ++ attr_val += 4; ++ attr_val = 1 << attr_val; ++ break; ++ ++ case pme_attr_sre_rule_num: ++ /* bits 24..31 */ ++ attr_val = pme_in(global_pme, SREC); ++ /* clear unwanted bits in val*/ ++ attr_val &= 0x000000FF; ++ /* Multiply by 256 */ ++ attr_val <<= 8; ++ break; ++ ++ case pme_attr_sre_session_ctx_num: { ++ u32 ctx_sz = 0; ++ /* = sre_table_size / sre_session_ctx_size */ ++ attr_val = pme_in(global_pme, SEC3); ++ /* clear unwanted bits in val*/ ++ attr_val &= 0x07FFFFFF; ++ attr_val += 1; ++ attr_val *= 32; ++ ctx_sz = pme_in(global_pme, SREC); ++ ctx_sz >>= 19; ++ /* clear unwanted bits in val*/ ++ ctx_sz &= 0x0000000F; ++ ctx_sz += 4; ++ attr_val /= (1 << ctx_sz); ++ } ++ break; ++ ++ case pme_attr_end_of_sui_reaction_ptr: ++ /* bits 12..31 */ ++ attr_val = pme_in(global_pme, ESRP); ++ /* clear unwanted bits in val*/ ++ attr_val &= 0x000FFFFF; ++ break; ++ ++ case pme_attr_sre_pscl: ++ /* bits 22..31 */ ++ attr_val = pme_in(global_pme, SFRCC); ++ break; ++ ++ case pme_attr_sre_max_block_num: ++ /* bits 17..31 */ ++ attr_val = pme_in(global_pme, SEC1); ++ /* clear unwanted bits in val*/ ++ attr_val &= 0x00007FFF; ++ break; ++ ++ case pme_attr_sre_max_instruction_limit: ++ /* bits 0..15 */ ++ attr_val = pme_in(global_pme, SEC1); ++ attr_val >>= 16; ++ break; ++ ++ case pme_attr_sre_max_index_size: ++ /* bits 12..31 */ ++ attr_val = pme_in(global_pme, SEC2); ++ /* clear unwanted bits in val*/ ++ attr_val &= 0x000FFFFF; ++ break; ++ ++ case pme_attr_sre_max_offset_ctrl: ++ /* bits 5..31 */ ++ attr_val = pme_in(global_pme, SEC3); ++ /* clear unwanted bits in val*/ ++ attr_val &= 0x07FFFFFF; ++ break; ++ ++ case pme_attr_src_id: ++ /* bits 24..31 */ ++ attr_val = pme_in(global_pme, SRCIDR); ++ /* clear unwanted bits in val*/ ++ attr_val &= 0x000000FF; ++ break; ++ ++ case pme_attr_liodnr: ++ /* bits 20..31 */ ++ attr_val = pme_in(global_pme, LIODNR); ++ /* clear unwanted bits in val*/ ++ attr_val &= 0x00000FFF; ++ break; ++ ++ case pme_attr_rev1: ++ /* bits 0..31 */ ++ attr_val = pme_in(global_pme, PM_IP_REV1); ++ break; ++ ++ case pme_attr_rev2: ++ /* bits 0..31 */ ++ attr_val = pme_in(global_pme, PM_IP_REV2); ++ break; ++ ++ case pme_attr_srrr: ++ attr_val = pme_in(global_pme, SRRR); ++ break; ++ ++ case pme_attr_trunci: ++ attr_val = pme_in(global_pme, TRUNCI); ++ break; ++ ++ case pme_attr_rbc: ++ attr_val = pme_in(global_pme, RBC); ++ break; ++ ++ case pme_attr_tbt0ecc1ec: ++ attr_val = pme_in(global_pme, TBT0ECC1EC); ++ break; ++ ++ case pme_attr_tbt1ecc1ec: ++ attr_val = pme_in(global_pme, TBT1ECC1EC); ++ break; ++ ++ case pme_attr_vlt0ecc1ec: ++ attr_val = pme_in(global_pme, VLT0ECC1EC); ++ break; ++ ++ case pme_attr_vlt1ecc1ec: ++ attr_val = pme_in(global_pme, VLT1ECC1EC); ++ break; ++ ++ case pme_attr_cmecc1ec: ++ attr_val = pme_in(global_pme, CMECC1EC); ++ break; ++ ++ case pme_attr_dxcmecc1ec: ++ attr_val = pme_in(global_pme, DXCMECC1EC); ++ break; ++ ++ case pme_attr_dxemecc1ec: ++ attr_val = pme_in(global_pme, DXEMECC1EC); ++ break; ++ ++ case pme_attr_tbt0ecc1th: ++ attr_val = pme_in(global_pme, TBT0ECC1TH); ++ break; ++ ++ case pme_attr_tbt1ecc1th: ++ attr_val = pme_in(global_pme, TBT1ECC1TH); ++ break; ++ ++ case pme_attr_vlt0ecc1th: ++ attr_val = pme_in(global_pme, VLT0ECC1TH); ++ break; ++ ++ case pme_attr_vlt1ecc1th: ++ attr_val = pme_in(global_pme, VLT1ECC1TH); ++ break; ++ ++ case pme_attr_cmecc1th: ++ attr_val = pme_in(global_pme, CMECC1TH); ++ break; ++ ++ case pme_attr_dxcmecc1th: ++ attr_val = pme_in(global_pme, DXCMECC1TH); ++ break; ++ ++ case pme_attr_dxemecc1th: ++ attr_val = pme_in(global_pme, DXEMECC1TH); ++ break; ++ ++ case pme_attr_stnib: ++ attr_val = pme_in(global_pme, STNIB); ++ break; ++ ++ case pme_attr_stnis: ++ attr_val = pme_in(global_pme, STNIS); ++ break; ++ ++ case pme_attr_stnth1: ++ attr_val = pme_in(global_pme, STNTH1); ++ break; ++ ++ case pme_attr_stnth2: ++ attr_val = pme_in(global_pme, STNTH2); ++ break; ++ ++ case pme_attr_stnthv: ++ attr_val = pme_in(global_pme, STNTHV); ++ break; ++ ++ case pme_attr_stnths: ++ attr_val = pme_in(global_pme, STNTHS); ++ break; ++ ++ case pme_attr_stnch: ++ attr_val = pme_in(global_pme, STNCH); ++ break; ++ ++ case pme_attr_stnpm: ++ attr_val = pme_in(global_pme, STNPM); ++ break; ++ ++ case pme_attr_stns1m: ++ attr_val = pme_in(global_pme, STNS1M); ++ break; ++ ++ case pme_attr_stnpmr: ++ attr_val = pme_in(global_pme, STNPMR); ++ break; ++ ++ case pme_attr_stndsr: ++ attr_val = pme_in(global_pme, STNDSR); ++ break; ++ ++ case pme_attr_stnesr: ++ attr_val = pme_in(global_pme, STNESR); ++ break; ++ ++ case pme_attr_stns1r: ++ attr_val = pme_in(global_pme, STNS1R); ++ break; ++ ++ case pme_attr_stnob: ++ attr_val = pme_in(global_pme, STNOB); ++ break; ++ ++ case pme_attr_mia_byc: ++ attr_val = pme_in(global_pme, MIA_BYC); ++ break; ++ ++ case pme_attr_mia_blc: ++ attr_val = pme_in(global_pme, MIA_BLC); ++ break; ++ ++ case pme_attr_isr: ++ attr_val = pme_in(global_pme, ISR); ++ break; ++ ++ case pme_attr_ecr0: ++ attr_val = pme_in(global_pme, ECR0); ++ break; ++ ++ case pme_attr_ecr1: ++ attr_val = pme_in(global_pme, ECR1); ++ break; ++ ++ case pme_attr_esr: ++ attr_val = pme_in(global_pme, ESR); ++ break; ++ ++ case pme_attr_pmstat: ++ attr_val = pme_in(global_pme, PMSTAT); ++ break; ++ ++ case pme_attr_pehd: ++ attr_val = pme_in(global_pme, PEHD); ++ break; ++ ++ case pme_attr_ecc1bes: ++ attr_val = pme_in(global_pme, ECC1BES); ++ break; ++ ++ case pme_attr_ecc2bes: ++ attr_val = pme_in(global_pme, ECC2BES); ++ break; ++ ++ case pme_attr_eccaddr: ++ attr_val = pme_in(global_pme, ECCADDR); ++ break; ++ ++ case pme_attr_ecccode: ++ attr_val = pme_in(global_pme, ECCCODE); ++ break; ++ ++ case pme_attr_miace: ++ attr_val = pme_in(global_pme, MIA_CE); ++ break; ++ ++ case pme_attr_miacr: ++ attr_val = pme_in(global_pme, MIA_CR); ++ break; ++ ++ case pme_attr_cdcr: ++ attr_val = pme_in(global_pme, CDCR); ++ break; ++ ++ case pme_attr_pmtr: ++ attr_val = pme_in(global_pme, PMTR); ++ break; ++ ++ case pme_attr_faconf: ++ attr_val = pme_in(global_pme, FACONF); ++ break; ++ ++ case pme_attr_pdsrbah: ++ attr_val = pme_in(global_pme, PDSRBAH); ++ break; ++ ++ case pme_attr_pdsrbal: ++ attr_val = pme_in(global_pme, PDSRBAL); ++ break; ++ ++ case pme_attr_scbarh: ++ attr_val = pme_in(global_pme, SCBARH); ++ break; ++ ++ case pme_attr_scbarl: ++ attr_val = pme_in(global_pme, SCBARL); ++ break; ++ ++ case pme_attr_srrv0: ++ attr_val = pme_in(global_pme, SRRV0); ++ break; ++ ++ case pme_attr_srrv1: ++ attr_val = pme_in(global_pme, SRRV1); ++ break; ++ ++ case pme_attr_srrv2: ++ attr_val = pme_in(global_pme, SRRV2); ++ break; ++ ++ case pme_attr_srrv3: ++ attr_val = pme_in(global_pme, SRRV3); ++ break; ++ ++ case pme_attr_srrv4: ++ attr_val = pme_in(global_pme, SRRV4); ++ break; ++ ++ case pme_attr_srrv5: ++ attr_val = pme_in(global_pme, SRRV5); ++ break; ++ ++ case pme_attr_srrv6: ++ attr_val = pme_in(global_pme, SRRV6); ++ break; ++ ++ case pme_attr_srrv7: ++ attr_val = pme_in(global_pme, SRRV7); ++ break; ++ ++ case pme_attr_srrfi: ++ attr_val = pme_in(global_pme, SRRFI); ++ break; ++ ++ case pme_attr_srri: ++ attr_val = pme_in(global_pme, SRRI); ++ break; ++ ++ case pme_attr_srrwc: ++ attr_val = pme_in(global_pme, SRRWC); ++ break; ++ ++ default: ++ pr_err("pme: Unknown attr %u\n", attr); ++ return -EINVAL; ++ }; ++ *val = attr_val; ++ return 0; ++} ++EXPORT_SYMBOL(pme_attr_get); ++ ++static enum pme_attr stat_list[] = { ++ pme_attr_trunci, ++ pme_attr_rbc, ++ pme_attr_tbt0ecc1ec, ++ pme_attr_tbt1ecc1ec, ++ pme_attr_vlt0ecc1ec, ++ pme_attr_vlt1ecc1ec, ++ pme_attr_cmecc1ec, ++ pme_attr_dxcmecc1ec, ++ pme_attr_dxemecc1ec, ++ pme_attr_stnib, ++ pme_attr_stnis, ++ pme_attr_stnth1, ++ pme_attr_stnth2, ++ pme_attr_stnthv, ++ pme_attr_stnths, ++ pme_attr_stnch, ++ pme_attr_stnpm, ++ pme_attr_stns1m, ++ pme_attr_stnpmr, ++ pme_attr_stndsr, ++ pme_attr_stnesr, ++ pme_attr_stns1r, ++ pme_attr_stnob, ++ pme_attr_mia_byc, ++ pme_attr_mia_blc ++}; ++ ++static u64 pme_stats[sizeof(stat_list)/sizeof(enum pme_attr)]; ++static DEFINE_SPINLOCK(stat_lock); ++ ++int pme_stat_get(enum pme_attr stat, u64 *value, int reset) ++{ ++ int i, ret = 0; ++ int value_set = 0; ++ u32 val; ++ ++ spin_lock_irq(&stat_lock); ++ for (i = 0; i < sizeof(stat_list)/sizeof(enum pme_attr); i++) { ++ if (stat_list[i] == stat) { ++ ret = pme_attr_get(stat_list[i], &val); ++ /* Do I need to check ret */ ++ pme_stats[i] += val; ++ *value = pme_stats[i]; ++ value_set = 1; ++ if (reset) ++ pme_stats[i] = 0; ++ break; ++ } ++ } ++ if (!value_set) { ++ pr_err("pme: Invalid stat request %d\n", stat); ++ ret = -EINVAL; ++ } ++ spin_unlock_irq(&stat_lock); ++ return ret; ++} ++EXPORT_SYMBOL(pme_stat_get); ++ ++void accumulator_update_interval(u32 interval) ++{ ++ int schedule = 0; ++ ++ spin_lock_irq(&stat_lock); ++ if (!pme_stat_interval && interval) ++ schedule = 1; ++ pme_stat_interval = interval; ++ spin_unlock_irq(&stat_lock); ++ if (schedule) ++ schedule_delayed_work(&accumulator_work, ++ msecs_to_jiffies(interval)); ++} ++ ++static void accumulator_update(struct work_struct *work) ++{ ++ int i, ret; ++ u32 local_interval; ++ u32 val; ++ ++ spin_lock_irq(&stat_lock); ++ local_interval = pme_stat_interval; ++ for (i = 0; i < sizeof(stat_list)/sizeof(enum pme_attr); i++) { ++ ret = pme_attr_get(stat_list[i], &val); ++ pme_stats[i] += val; ++ } ++ spin_unlock_irq(&stat_lock); ++ if (local_interval) ++ schedule_delayed_work(&accumulator_work, ++ msecs_to_jiffies(local_interval)); ++} +diff --git a/drivers/staging/fsl_pme2/pme2_db.c b/drivers/staging/fsl_pme2/pme2_db.c +new file mode 100644 +index 0000000..4c9cd21 +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_db.c +@@ -0,0 +1,572 @@ ++/* Copyright 2009-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "pme2_private.h" ++#include ++ ++/* Forward declaration */ ++static struct miscdevice fsl_pme2_db_dev; ++ ++/* Global spinlock for handling exclusive inc/dec */ ++static DEFINE_SPINLOCK(exclusive_lock); ++ ++/* Private structure that is allocated for each open that is done on the ++ * pme_db device. This is used to maintain the state of a database session */ ++struct db_session { ++ /* The ctx that is needed to communicate with the pme high level */ ++ struct pme_ctx ctx; ++ /* Used to track the EXCLUSIVE_INC and EXCLUSIVE_DEC ioctls */ ++ unsigned int exclusive_counter; ++}; ++ ++struct cmd_token { ++ /* pme high level token */ ++ struct pme_ctx_token hl_token; ++ /* data */ ++ struct qm_fd rx_fd; ++ /* Completion interface */ ++ struct completion cb_done; ++ u8 ern; ++}; ++ ++#ifdef CONFIG_COMPAT ++static void compat_to_db(struct pme_db *dst, struct compat_pme_db *src) ++{ ++ dst->flags = src->flags; ++ dst->status = src->status; ++ dst->input.data = compat_ptr(src->input.data); ++ dst->input.size = src->input.size; ++ dst->output.data = compat_ptr(src->output.data); ++ dst->output.size = src->output.size; ++} ++ ++static void db_to_compat(struct compat_pme_db *dst, struct pme_db *src) ++{ ++ dst->flags = src->flags; ++ dst->status = src->status; ++ dst->output.data = ptr_to_compat(src->output.data); ++ dst->output.size = src->output.size; ++ dst->input.data = ptr_to_compat(src->input.data); ++ dst->input.size = src->input.size; ++} ++#endif ++ ++/* PME Compound Frame Index */ ++#define INPUT_FRM 1 ++#define OUTPUT_FRM 0 ++ ++/* Callback for database operations */ ++static void db_cb(struct pme_ctx *ctx, const struct qm_fd *fd, ++ struct pme_ctx_token *ctx_token) ++{ ++ struct cmd_token *token = (struct cmd_token *)ctx_token; ++ token->rx_fd = *fd; ++ complete(&token->cb_done); ++} ++ ++static void db_ern_cb(struct pme_ctx *ctx, const struct qm_mr_entry *mr, ++ struct pme_ctx_token *ctx_token) ++{ ++ struct cmd_token *token = (struct cmd_token *)ctx_token; ++ token->ern = 1; ++ token->rx_fd = mr->ern.fd; ++ complete(&token->cb_done); ++} ++ ++struct ctrl_op { ++ struct pme_ctx_ctrl_token ctx_ctr; ++ struct completion cb_done; ++ enum pme_status cmd_status; ++ u8 res_flag; ++ u8 ern; ++}; ++ ++static void ctrl_cb(struct pme_ctx *ctx, const struct qm_fd *fd, ++ struct pme_ctx_ctrl_token *token) ++{ ++ struct ctrl_op *ctrl = (struct ctrl_op *)token; ++ ctrl->cmd_status = pme_fd_res_status(fd); ++ ctrl->res_flag = pme_fd_res_flags(fd) & PME_STATUS_UNRELIABLE; ++ complete(&ctrl->cb_done); ++} ++ ++static void ctrl_ern_cb(struct pme_ctx *ctx, const struct qm_mr_entry *mr, ++ struct pme_ctx_ctrl_token *token) ++{ ++ struct ctrl_op *ctrl = (struct ctrl_op *)token; ++ ctrl->ern = 1; ++ complete(&ctrl->cb_done); ++} ++ ++static int exclusive_inc(struct file *fp, struct db_session *db) ++{ ++ int ret; ++ ++ BUG_ON(!db); ++ BUG_ON(!(db->ctx.flags & PME_CTX_FLAG_EXCLUSIVE)); ++ spin_lock(&exclusive_lock); ++ ret = pme_ctx_exclusive_inc(&db->ctx, ++ (PME_CTX_OP_WAIT | PME_CTX_OP_WAIT_INT)); ++ if (!ret) ++ db->exclusive_counter++; ++ spin_unlock(&exclusive_lock); ++ return ret; ++} ++ ++static int exclusive_dec(struct file *fp, struct db_session *db) ++{ ++ int ret = 0; ++ ++ BUG_ON(!db); ++ BUG_ON(!(db->ctx.flags & PME_CTX_FLAG_EXCLUSIVE)); ++ spin_lock(&exclusive_lock); ++ if (!db->exclusive_counter) { ++ PMEPRERR("exclusivity counter already zero\n"); ++ ret = -EINVAL; ++ } else { ++ pme_ctx_exclusive_dec(&db->ctx); ++ db->exclusive_counter--; ++ } ++ spin_unlock(&exclusive_lock); ++ return ret; ++} ++ ++static int execute_cmd(struct file *fp, struct db_session *db, ++ struct pme_db *db_cmd) ++{ ++ int ret = 0; ++ struct cmd_token token; ++ struct qm_sg_entry tx_comp[2]; ++ struct qm_fd tx_fd; ++ void *tx_data = NULL; ++ void *rx_data = NULL; ++ u32 src_sz, dst_sz; ++ dma_addr_t dma_addr; ++ ++ memset(&token, 0, sizeof(struct cmd_token)); ++ memset(tx_comp, 0, sizeof(tx_comp)); ++ memset(&tx_fd, 0, sizeof(struct qm_fd)); ++ init_completion(&token.cb_done); ++ ++ PMEPRINFO("Received User Space Contiguous mem\n"); ++ PMEPRINFO("length = %d\n", db_cmd->input.size); ++ tx_data = kmalloc(db_cmd->input.size, GFP_KERNEL); ++ if (!tx_data) { ++ PMEPRERR("Err alloc %zd byte\n", db_cmd->input.size); ++ return -ENOMEM; ++ } ++ ++ if (copy_from_user(tx_data, ++ (void __user *)db_cmd->input.data, ++ db_cmd->input.size)) { ++ PMEPRERR("Error copying contigous user data\n"); ++ ret = -EFAULT; ++ goto free_tx_data; ++ } ++ ++ /* Setup input frame */ ++ tx_comp[INPUT_FRM].final = 1; ++ tx_comp[INPUT_FRM].length = db_cmd->input.size; ++ dma_addr = pme_map(tx_data); ++ if (pme_map_error(dma_addr)) { ++ PMEPRERR("Error pme_map_error\n"); ++ ret = -EIO; ++ goto free_tx_data; ++ } ++ set_sg_addr(&tx_comp[INPUT_FRM], dma_addr); ++ /* setup output frame, if output is expected */ ++ if (db_cmd->output.size) { ++ PMEPRINFO("expect output %d\n", db_cmd->output.size); ++ rx_data = kmalloc(db_cmd->output.size, GFP_KERNEL); ++ if (!rx_data) { ++ PMEPRERR("Err alloc %zd byte", db_cmd->output.size); ++ ret = -ENOMEM; ++ goto unmap_input_frame; ++ } ++ /* Setup output frame */ ++ tx_comp[OUTPUT_FRM].length = db_cmd->output.size; ++ dma_addr = pme_map(rx_data); ++ if (pme_map_error(dma_addr)) { ++ PMEPRERR("Error pme_map_error\n"); ++ ret = -EIO; ++ goto comp_frame_free_rx; ++ } ++ set_sg_addr(&tx_comp[OUTPUT_FRM], dma_addr); ++ tx_fd.format = qm_fd_compound; ++ /* Build compound frame */ ++ dma_addr = pme_map(tx_comp); ++ if (pme_map_error(dma_addr)) { ++ PMEPRERR("Error pme_map_error\n"); ++ ret = -EIO; ++ goto comp_frame_unmap_output; ++ } ++ set_fd_addr(&tx_fd, dma_addr); ++ } else { ++ tx_fd.format = qm_fd_sg_big; ++ tx_fd.length29 = db_cmd->input.size; ++ /* Build sg frame */ ++ dma_addr = pme_map(&tx_comp[INPUT_FRM]); ++ if (pme_map_error(dma_addr)) { ++ PMEPRERR("Error pme_map_error\n"); ++ ret = -EIO; ++ goto unmap_input_frame; ++ } ++ set_fd_addr(&tx_fd, dma_addr); ++ } ++ ret = pme_ctx_pmtcc(&db->ctx, PME_CTX_OP_WAIT, &tx_fd, ++ (struct pme_ctx_token *)&token); ++ if (unlikely(ret)) { ++ PMEPRINFO("pme_ctx_pmtcc error %d\n", ret); ++ goto unmap_frame; ++ } ++ PMEPRINFO("Wait for completion\n"); ++ /* Wait for the command to complete */ ++ wait_for_completion(&token.cb_done); ++ ++ if (token.ern) { ++ ret = -EIO; ++ goto unmap_frame; ++ } ++ ++ PMEPRINFO("pme2_db: process_completed_token\n"); ++ PMEPRINFO("pme2_db: received %d frame type\n", token.rx_fd.format); ++ if (token.rx_fd.format == qm_fd_compound) { ++ /* Need to copy output */ ++ src_sz = tx_comp[OUTPUT_FRM].length; ++ dst_sz = db_cmd->output.size; ++ PMEPRINFO("pme gen %u data, have space for %u\n", ++ src_sz, dst_sz); ++ db_cmd->output.size = min(dst_sz, src_sz); ++ /* Doesn't make sense we generated more than available space ++ * should have got truncation. ++ */ ++ BUG_ON(dst_sz < src_sz); ++ if (copy_to_user((void __user *)db_cmd->output.data, rx_data, ++ db_cmd->output.size)) { ++ PMEPRERR("Error copying to user data\n"); ++ ret = -EFAULT; ++ goto comp_frame_unmap_cf; ++ } ++ } else if (token.rx_fd.format == qm_fd_sg_big) ++ db_cmd->output.size = 0; ++ else ++ panic("unexpected frame type received %d\n", ++ token.rx_fd.format); ++ ++ db_cmd->flags = pme_fd_res_flags(&token.rx_fd); ++ db_cmd->status = pme_fd_res_status(&token.rx_fd); ++ ++unmap_frame: ++ if (token.rx_fd.format == qm_fd_sg_big) ++ goto single_frame_unmap_frame; ++ ++comp_frame_unmap_cf: ++comp_frame_unmap_output: ++comp_frame_free_rx: ++ kfree(rx_data); ++ goto unmap_input_frame; ++single_frame_unmap_frame: ++unmap_input_frame: ++free_tx_data: ++ kfree(tx_data); ++ ++ return ret; ++} ++ ++static int execute_nop(struct file *fp, struct db_session *db) ++{ ++ int ret = 0; ++ struct ctrl_op ctx_ctrl = { ++ .ctx_ctr.cb = ctrl_cb, ++ .ctx_ctr.ern_cb = ctrl_ern_cb ++ }; ++ init_completion(&ctx_ctrl.cb_done); ++ ++ ret = pme_ctx_ctrl_nop(&db->ctx, PME_CTX_OP_WAIT|PME_CTX_OP_WAIT_INT, ++ &ctx_ctrl.ctx_ctr); ++ if (!ret) ++ wait_for_completion(&ctx_ctrl.cb_done); ++ ++ if (ctx_ctrl.ern) ++ ret = -EIO; ++ return ret; ++} ++ ++static atomic_t sre_reset_lock = ATOMIC_INIT(1); ++static int ioctl_sre_reset(unsigned long arg) ++{ ++ struct pme_db_sre_reset reset_vals; ++ int i; ++ u32 srrr_val; ++ int ret = 0; ++ ++ if (copy_from_user(&reset_vals, (struct pme_db_sre_reset __user *)arg, ++ sizeof(struct pme_db_sre_reset))) ++ return -EFAULT; ++ PMEPRINFO("sre_reset:\n"); ++ PMEPRINFO(" rule_index = 0x%x:\n", reset_vals.rule_index); ++ PMEPRINFO(" rule_increment = 0x%x:\n", reset_vals.rule_increment); ++ PMEPRINFO(" rule_repetitions = 0x%x:\n", reset_vals.rule_repetitions); ++ PMEPRINFO(" rule_reset_interval = 0x%x:\n", ++ reset_vals.rule_reset_interval); ++ PMEPRINFO(" rule_reset_priority = 0x%x:\n", ++ reset_vals.rule_reset_priority); ++ ++ /* Validate ranges */ ++ if ((reset_vals.rule_index >= PME_PMFA_SRE_INDEX_MAX) || ++ (reset_vals.rule_increment > PME_PMFA_SRE_INC_MAX) || ++ (reset_vals.rule_repetitions >= PME_PMFA_SRE_REP_MAX) || ++ (reset_vals.rule_reset_interval >= ++ PME_PMFA_SRE_INTERVAL_MAX)) ++ return -ERANGE; ++ /* Check and make sure only one caller is present */ ++ if (!atomic_dec_and_test(&sre_reset_lock)) { ++ /* Someone else is already in this call */ ++ atomic_inc(&sre_reset_lock); ++ return -EBUSY; ++ }; ++ /* All validated. Run the command */ ++ for (i = 0; i < PME_SRE_RULE_VECTOR_SIZE; i++) ++ pme_attr_set(pme_attr_srrv0 + i, reset_vals.rule_vector[i]); ++ pme_attr_set(pme_attr_srrfi, reset_vals.rule_index); ++ pme_attr_set(pme_attr_srri, reset_vals.rule_increment); ++ pme_attr_set(pme_attr_srrwc, ++ (0xFFF & reset_vals.rule_reset_interval) << 1 | ++ (reset_vals.rule_reset_priority ? 1 : 0)); ++ /* Need to set SRRR last */ ++ pme_attr_set(pme_attr_srrr, reset_vals.rule_repetitions); ++ do { ++ mdelay(PME_PMFA_SRE_POLL_MS); ++ ret = pme_attr_get(pme_attr_srrr, &srrr_val); ++ if (ret) { ++ PMEPRCRIT("pme2: Error reading srrr\n"); ++ /* bail */ ++ break; ++ } ++ /* Check for error */ ++ else if (srrr_val & 0x10000000) { ++ PMEPRERR("pme2: Error in SRRR\n"); ++ ret = -EIO; ++ } ++ PMEPRINFO("pme2: srrr count %d\n", srrr_val); ++ } while (srrr_val); ++ atomic_inc(&sre_reset_lock); ++ return ret; ++} ++ ++/** ++ * fsl_pme2_db_open - open the driver ++ * ++ * Open the driver and prepare for requests. ++ * ++ * Every time an application opens the driver, we create a db_session object ++ * for that file handle. ++ */ ++static int fsl_pme2_db_open(struct inode *node, struct file *fp) ++{ ++ int ret; ++ struct db_session *db = NULL; ++ ++ db = kzalloc(sizeof(struct db_session), GFP_KERNEL); ++ if (!db) ++ return -ENOMEM; ++ fp->private_data = db; ++ db->ctx.cb = db_cb; ++ db->ctx.ern_cb = db_ern_cb; ++ ++ ret = pme_ctx_init(&db->ctx, ++ PME_CTX_FLAG_EXCLUSIVE | ++ PME_CTX_FLAG_PMTCC | ++ PME_CTX_FLAG_DIRECT| ++ PME_CTX_FLAG_LOCAL, ++ 0, 4, CONFIG_FSL_PME2_DB_QOSOUT_PRIORITY, 0, NULL); ++ if (ret) { ++ PMEPRERR("pme_ctx_init %d\n", ret); ++ goto free_data; ++ } ++ ++ /* enable the context */ ++ ret = pme_ctx_enable(&db->ctx); ++ if (ret) { ++ PMEPRERR("error enabling ctx %d\n", ret); ++ pme_ctx_finish(&db->ctx); ++ goto free_data; ++ } ++ PMEPRINFO("pme2_db: Finish pme_db open %d\n", smp_processor_id()); ++ return 0; ++free_data: ++ kfree(fp->private_data); ++ fp->private_data = NULL; ++ return ret; ++} ++ ++static int fsl_pme2_db_close(struct inode *node, struct file *fp) ++{ ++ int ret = 0; ++ struct db_session *db = fp->private_data; ++ ++ PMEPRINFO("Start pme_db close\n"); ++ while (db->exclusive_counter) { ++ pme_ctx_exclusive_dec(&db->ctx); ++ db->exclusive_counter--; ++ } ++ ++ /* Disable context. */ ++ ret = pme_ctx_disable(&db->ctx, PME_CTX_OP_WAIT, NULL); ++ if (ret) ++ PMEPRCRIT("Error disabling ctx %d\n", ret); ++ pme_ctx_finish(&db->ctx); ++ kfree(db); ++ PMEPRINFO("Finish pme_db close\n"); ++ return 0; ++} ++ ++/* Main switch loop for ioctl operations */ ++static long fsl_pme2_db_ioctl(struct file *fp, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct db_session *db = fp->private_data; ++ int ret = 0; ++ ++ switch (cmd) { ++ ++ case PMEIO_PMTCC: { ++ int ret; ++ struct pme_db db_cmd; ++ ++ /* Copy the command to kernel space */ ++ if (copy_from_user(&db_cmd, (void __user *)arg, ++ sizeof(db_cmd))) ++ return -EFAULT; ++ ret = execute_cmd(fp, db, &db_cmd); ++ if (!ret) ++ ret = copy_to_user((struct pme_db __user *)arg, ++ &db_cmd, sizeof(db_cmd)); ++ return ret; ++ } ++ break; ++ ++ case PMEIO_EXL_INC: ++ return exclusive_inc(fp, db); ++ case PMEIO_EXL_DEC: ++ return exclusive_dec(fp, db); ++ case PMEIO_EXL_GET: ++ BUG_ON(!db); ++ BUG_ON(!(db->ctx.flags & PME_CTX_FLAG_EXCLUSIVE)); ++ if (copy_to_user((void __user *)arg, ++ &db->exclusive_counter, ++ sizeof(db->exclusive_counter))) ++ ret = -EFAULT; ++ return ret; ++ case PMEIO_NOP: ++ return execute_nop(fp, db); ++ case PMEIO_SRE_RESET: ++ return ioctl_sre_reset(arg); ++ ++#ifdef CONFIG_COMPAT ++ case PMEIO_PMTCC32: { ++ int ret; ++ struct pme_db db_cmd; ++ struct compat_pme_db db_cmd32; ++ struct compat_pme_db __user *user_db_cmd = compat_ptr(arg); ++ ++ /* Copy the command to kernel space */ ++ if (copy_from_user(&db_cmd32, user_db_cmd, sizeof(db_cmd32))) ++ return -EFAULT; ++ /* Convert to 64-bit struct */ ++ compat_to_db(&db_cmd, &db_cmd32); ++ ret = execute_cmd(fp, db, &db_cmd); ++ if (!ret) { ++ /* Convert to compat struct */ ++ db_to_compat(&db_cmd32, &db_cmd); ++ ret = copy_to_user(user_db_cmd, &db_cmd32, ++ sizeof(*user_db_cmd)); ++ } ++ return ret; ++ } ++ break; ++#endif ++ } ++ pr_info("Unknown pme_db ioctl cmd %u\n", cmd); ++ return -EINVAL; ++} ++ ++static const struct file_operations fsl_pme2_db_fops = { ++ .owner = THIS_MODULE, ++ .open = fsl_pme2_db_open, ++ .release = fsl_pme2_db_close, ++ .unlocked_ioctl = fsl_pme2_db_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = fsl_pme2_db_ioctl, ++#endif ++}; ++ ++static struct miscdevice fsl_pme2_db_dev = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = PME_DEV_DB_NODE, ++ .fops = &fsl_pme2_db_fops ++}; ++ ++static int __init fsl_pme2_db_init(void) ++{ ++ int err = 0; ++ ++ pr_info("Freescale pme2 db driver\n"); ++ if (!pme2_have_control()) { ++ PMEPRERR("not on ctrl-plane\n"); ++ return -ENODEV; ++ } ++ err = misc_register(&fsl_pme2_db_dev); ++ if (err) { ++ PMEPRERR("cannot register device\n"); ++ return err; ++ } ++ PMEPRINFO("device %s registered\n", fsl_pme2_db_dev.name); ++ return 0; ++} ++ ++static void __exit fsl_pme2_db_exit(void) ++{ ++ int err = misc_deregister(&fsl_pme2_db_dev); ++ if (err) { ++ PMEPRERR("Failed to deregister device %s, " ++ "code %d\n", fsl_pme2_db_dev.name, err); ++ return; ++ } ++ PMEPRINFO("device %s deregistered\n", fsl_pme2_db_dev.name); ++} ++ ++module_init(fsl_pme2_db_init); ++module_exit(fsl_pme2_db_exit); ++ ++MODULE_AUTHOR("Freescale Semiconductor - OTC"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("FSL PME2 db driver"); +diff --git a/drivers/staging/fsl_pme2/pme2_high.c b/drivers/staging/fsl_pme2/pme2_high.c +new file mode 100644 +index 0000000..14dacd3 +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_high.c +@@ -0,0 +1,997 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "pme2_private.h" ++ ++/* The pme_ctx state machine is described via the following list of ++ * internal PME_CTX_FLAG_*** bits and cross-referenced to the APIs (and ++ * functionality) they track. ++ * ++ * DEAD: set at any point, an error has been hit, doesn't "cause" disabling or ++ * any autonomous ref-decrement (been there, hit the gotchas, won't do it ++ * again). ++ * ++ * DISABLING: set by pme_ctx_disable() at any point that is not already ++ * disabling, disabled, or in ctrl, and the ref is decremented. DISABLING is ++ * unset by pme_ctx_enable(). ++ * ++ * DISABLED: once pme_ctx_disable() has set DISABLING and refs==0, DISABLED is ++ * set before returning. (Any failure will clear DISABLING and increment the ref ++ * count.) DISABLING is unset by pme_ctx_enable(). ++ * ++ * ENABLING: set by pme_ctx_enable() provided the context is disabled, not dead, ++ * not in RECONFIG, and not already enabling. Once set, the ref is incremented ++ * and the tx FQ is scheduled (for non-exclusive flows). If this fails, the ref ++ * is decremented and the context is re-disabled. ENABLING is unset once ++ * pme_ctx_enable() completes. ++ * ++ * RECONFIG: set by pme_ctx_reconfigure_[rt]x() provided the context is ++ * disabled, not dead, and not already in reconfig. RECONFIG is cleared prior to ++ * the function returning. ++ * ++ * Simplifications: the do_flag() wrapper provides synchronised modifications of ++ * the ctx 'flags', and callers can rely on the following implications to reduce ++ * the number of flags in the masks being passed in; ++ * DISABLED implies DISABLING (and enable will clear both) ++ */ ++ ++/* Internal-only ctx flags, mustn't conflict with exported ones */ ++#define PME_CTX_FLAG_DEAD 0x80000000 ++#define PME_CTX_FLAG_DISABLING 0x40000000 ++#define PME_CTX_FLAG_DISABLED 0x20000000 ++#define PME_CTX_FLAG_ENABLING 0x10000000 ++#define PME_CTX_FLAG_RECONFIG 0x08000000 ++#define PME_CTX_FLAG_PRIVATE 0xf8000000 /* mask of them all */ ++ ++/* Internal-only cmd flags, musn't conflict with exported ones */ ++#define PME_CTX_OP_INSIDE_DISABLE 0x80000000 ++#define PME_CTX_OP_PRIVATE 0x80000000 /* mask of them all */ ++ ++struct pme_nostash { ++ struct qman_fq fqin; ++ struct pme_ctx *parent; ++}; ++ ++/* This wrapper simplifies conditional (and locked) read-modify-writes to ++ * 'flags'. Inlining should allow the compiler to optimise it based on the ++ * parameters, eg. if 'must_be_set'/'must_not_be_set' are zero it will ++ * degenerate to an unconditional read-modify-write, if 'to_set'/'to_unset' are ++ * zero it will degenerate to a read-only flag-check, etc. */ ++static inline int do_flags(struct pme_ctx *ctx, ++ u32 must_be_set, u32 must_not_be_set, ++ u32 to_set, u32 to_unset) ++{ ++ int err = -EBUSY; ++ unsigned long irqflags; ++ ++ spin_lock_irqsave(&ctx->lock, irqflags); ++ if (((ctx->flags & must_be_set) == must_be_set) && ++ !(ctx->flags & must_not_be_set)) { ++ ctx->flags |= to_set; ++ ctx->flags &= ~to_unset; ++ err = 0; ++ } ++ spin_unlock_irqrestore(&ctx->lock, irqflags); ++ return err; ++} ++ ++static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *, struct qman_fq *, ++ const struct qm_dqrr_entry *); ++static void cb_ern(struct qman_portal *, struct qman_fq *, ++ const struct qm_mr_entry *); ++static void cb_fqs(struct qman_portal *, struct qman_fq *, ++ const struct qm_mr_entry *); ++static const struct qman_fq_cb pme_fq_base_in = { ++ .fqs = cb_fqs, ++ .ern = cb_ern ++}; ++static const struct qman_fq_cb pme_fq_base_out = { ++ .dqrr = cb_dqrr, ++ .fqs = cb_fqs ++}; ++ ++/* Globals related to competition for PME_EFQC, ie. exclusivity */ ++static DECLARE_WAIT_QUEUE_HEAD(exclusive_queue); ++static spinlock_t exclusive_lock = __SPIN_LOCK_UNLOCKED(exclusive_lock); ++static unsigned int exclusive_refs; ++static struct pme_ctx *exclusive_ctx; ++ ++/* Index 0..255, bools do indicated which errors are serious ++ * 0x40, 0x41, 0x48, 0x49, 0x4c, 0x4e, 0x4f, 0x50, 0x51, 0x59, 0x5a, 0x5b, ++ * 0x5c, 0x5d, 0x5f, 0x60, 0x80, 0xc0, 0xc1, 0xc2, 0xc4, 0xd2, ++ * 0xd4, 0xd5, 0xd7, 0xd9, 0xda, 0xe0, 0xe7 ++ */ ++static u8 serious_error_vec[] = { ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, ++ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ++ 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++}; ++ ++/* TODO: this is hitting the rx FQ with a large blunt instrument, ie. park() ++ * does a retire, query, oos, and (re)init. It's possible to force-eligible the ++ * rx FQ instead, then use a DCA_PK within the cb_dqrr() callback to park it. ++ * Implement this optimisation later if it's an issue (and incur the additional ++ * complexity in the state-machine). */ ++static int park(struct qman_fq *fq, struct qm_mcc_initfq *initfq) ++{ ++ int ret; ++ u32 flags; ++ ++ ret = qman_retire_fq(fq, &flags); ++ if (ret) ++ return ret; ++ BUG_ON(flags & QMAN_FQ_STATE_BLOCKOOS); ++ /* We can't revert from now on */ ++ ret = qman_query_fq(fq, &initfq->fqd); ++ BUG_ON(ret); ++ ret = qman_oos_fq(fq); ++ BUG_ON(ret); ++ /* can't set QM_INITFQ_WE_OAC and QM_INITFQ_WE_TDTHRESH ++ * at the same time */ ++ initfq->we_mask = QM_INITFQ_WE_MASK & ~QM_INITFQ_WE_TDTHRESH; ++ ret = qman_init_fq(fq, 0, initfq); ++ BUG_ON(ret); ++ initfq->we_mask = QM_INITFQ_WE_TDTHRESH; ++ ret = qman_init_fq(fq, 0, initfq); ++ BUG_ON(ret); ++ return 0; ++} ++ ++static inline int reconfigure_rx(struct pme_ctx *ctx, int to_park, u8 qosout, ++ u16 dest, ++ const struct qm_fqd_stashing *stashing) ++{ ++ struct qm_mcc_initfq initfq; ++ u32 flags = QMAN_INITFQ_FLAG_SCHED; ++ int ret; ++ ++ ret = do_flags(ctx, PME_CTX_FLAG_DISABLED, ++ PME_CTX_FLAG_DEAD | PME_CTX_FLAG_RECONFIG, ++ PME_CTX_FLAG_RECONFIG, 0); ++ if (ret) ++ return ret; ++ if (to_park) { ++ ret = park(&ctx->fq, &initfq); ++ if (ret) ++ goto done; ++ } ++ initfq.we_mask = QM_INITFQ_WE_DESTWQ | QM_INITFQ_WE_FQCTRL; ++ initfq.fqd.dest.wq = qosout; ++ if (stashing) { ++ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; ++ initfq.fqd.context_a.stashing = *stashing; ++ initfq.fqd.fq_ctrl = QM_FQCTRL_CTXASTASHING; ++ } else ++ initfq.fqd.fq_ctrl = 0; /* disable stashing */ ++ if (ctx->flags & PME_CTX_FLAG_LOCAL) ++ flags |= QMAN_INITFQ_FLAG_LOCAL; ++ else { ++ initfq.fqd.dest.channel = dest; ++ /* Set hold-active *IFF* it's a pool channel */ ++ if (dest >= qm_channel_pool1) ++ initfq.fqd.fq_ctrl |= QM_FQCTRL_HOLDACTIVE; ++ } ++ ret = qman_init_fq(&ctx->fq, flags, &initfq); ++done: ++ do_flags(ctx, 0, 0, 0, PME_CTX_FLAG_RECONFIG); ++ return ret; ++} ++ ++/* this code is factored out of pme_ctx_disable() and get_ctrl() */ ++static int empty_pipeline(struct pme_ctx *ctx, __maybe_unused u32 flags) ++{ ++ int ret; ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & PME_CTX_OP_WAIT) { ++ if (flags & PME_CTX_OP_WAIT_INT) { ++ ret = -EINTR; ++ wait_event_interruptible(ctx->queue, ++ !(ret = atomic_read(&ctx->refs))); ++ } else ++ wait_event(ctx->queue, ++ !(ret = atomic_read(&ctx->refs))); ++ } else ++#endif ++ ret = atomic_read(&ctx->refs); ++ if (ret) ++ /* convert a +ve ref-count to a -ve error code */ ++ ret = -EBUSY; ++ return ret; ++} ++ ++/** ++ * set_pme_revision - set the pme revision in the ctx ++ * ++ * In order to make decisions based on PME HW version, read this ++ * information and store it on the ctx object. ++ */ ++static int set_pme_revision(struct pme_ctx *ctx) ++{ ++ int ret = 0; ++ u32 rev1, rev2; ++ struct device_node *dn; ++ const u32 *dt_rev; ++ int len; ++ ++#ifdef CONFIG_FSL_PME2_CTRL ++ /* Can try and read it from CCSR */ ++ if (pme2_have_control()) { ++ ret = pme_attr_get(pme_attr_rev1, &rev1); ++ if (ret) ++ return ret; ++ ret = pme_attr_get(pme_attr_rev2, &rev2); ++ if (ret) ++ return ret; ++ ctx->pme_rev1 = rev1; ++ ctx->pme_rev2 = rev2; ++ return 0; ++ } ++#endif ++ ++ /* Not on control-plane, try and get it from pme portal node */ ++ dn = of_find_node_with_property(NULL, "fsl,pme-rev1"); ++ if (!dn) ++ return -ENODEV; ++ dt_rev = of_get_property(dn, "fsl,pme-rev1", &len); ++ if (!dt_rev || len != 4) { ++ of_node_put(dn); ++ return -ENODEV; ++ } ++ rev1 = *dt_rev; ++ ++ dt_rev = of_get_property(dn, "fsl,pme-rev2", &len); ++ if (!dt_rev || len != 4) { ++ of_node_put(dn); ++ return -ENODEV; ++ } ++ rev2 = *dt_rev; ++ of_node_put(dn); ++ ctx->pme_rev1 = rev1; ++ ctx->pme_rev2 = rev2; ++ return ret; ++} ++ ++int pme_ctx_init(struct pme_ctx *ctx, u32 flags, u32 bpid, u8 qosin, ++ u8 qosout, u16 dest, ++ const struct qm_fqd_stashing *stashing) ++{ ++ int rxinit = 0, ret = -ENOMEM, fqin_inited = 0; ++ ++ ctx->fq.cb = pme_fq_base_out; ++ atomic_set(&ctx->refs, 0); ++ ctx->flags = (flags & ~PME_CTX_FLAG_PRIVATE) | PME_CTX_FLAG_DISABLED | ++ PME_CTX_FLAG_DISABLING; ++ if (ctx->flags & PME_CTX_FLAG_PMTCC) ++ ctx->flags |= PME_CTX_FLAG_DIRECT | PME_CTX_FLAG_EXCLUSIVE; ++ spin_lock_init(&ctx->lock); ++ init_waitqueue_head(&ctx->queue); ++ INIT_LIST_HEAD(&ctx->tokens); ++ ctx->hw_flow = NULL; ++ ctx->hw_residue = NULL; ++ ret = set_pme_revision(ctx); ++ if (ret) ++ goto err; ++#ifdef CONFIG_FSL_PME_BUG_4K_SCAN_REV_2_1_4 ++ if (is_version_2_1_4(ctx->pme_rev1, ctx->pme_rev2)) ++ ctx->max_scan_size = PME_MAX_SCAN_SIZE_BUG_2_1_4; ++#endif ++ ctx->us_data = kzalloc(sizeof(struct pme_nostash), GFP_KERNEL); ++ if (!ctx->us_data) ++ goto err; ++ ctx->us_data->parent = ctx; ++ if (!ctx->us_data) ++ goto err; ++ ctx->us_data->fqin.cb = pme_fq_base_in; ++ if (qman_create_fq(0, QMAN_FQ_FLAG_TO_DCPORTAL | ++ QMAN_FQ_FLAG_DYNAMIC_FQID | ++ ((flags & PME_CTX_FLAG_LOCKED) ? ++ QMAN_FQ_FLAG_LOCKED : 0), ++ &ctx->us_data->fqin)) ++ goto err; ++ fqin_inited = 1; ++ if (qman_create_fq(0, QMAN_FQ_FLAG_NO_ENQUEUE | ++ QMAN_FQ_FLAG_DYNAMIC_FQID | ++ ((flags & PME_CTX_FLAG_LOCKED) ? ++ QMAN_FQ_FLAG_LOCKED : 0), &ctx->fq)) ++ goto err; ++ rxinit = 1; ++ /* Input FQ */ ++ if (!(flags & PME_CTX_FLAG_DIRECT)) { ++ ctx->hw_flow = pme_hw_flow_new(); ++ if (!ctx->hw_flow) ++ goto err; ++ } ++ ret = pme_ctx_reconfigure_tx(ctx, bpid, qosin); ++ if (ret) ++ goto err; ++ /* Output FQ */ ++ ret = reconfigure_rx(ctx, 0, qosout, dest, stashing); ++ if (ret) { ++ /* Need to OOS the FQ before it gets free'd */ ++ ret = qman_oos_fq(&ctx->us_data->fqin); ++ BUG_ON(ret); ++ goto err; ++ } ++ return 0; ++err: ++ if (ctx->hw_flow) ++ pme_hw_flow_free(ctx->hw_flow); ++ if (ctx->us_data) { ++ if (fqin_inited) ++ qman_destroy_fq(&ctx->us_data->fqin, 0); ++ kfree(ctx->us_data); ++ } ++ if (rxinit) ++ qman_destroy_fq(&ctx->fq, 0); ++ return ret; ++} ++EXPORT_SYMBOL(pme_ctx_init); ++ ++/* NB, we don't lock here because there must be no other callers (even if we ++ * locked, what does the loser do after we win?) */ ++void pme_ctx_finish(struct pme_ctx *ctx) ++{ ++ u32 flags; ++ int ret; ++ ++ ret = do_flags(ctx, PME_CTX_FLAG_DISABLED, PME_CTX_FLAG_RECONFIG, 0, 0); ++ BUG_ON(ret); ++ /* Rx/Tx are empty (coz ctx is disabled) so retirement should be ++ * immediate */ ++ ret = qman_retire_fq(&ctx->us_data->fqin, &flags); ++ BUG_ON(ret); ++ BUG_ON(flags & QMAN_FQ_STATE_BLOCKOOS); ++ ret = qman_retire_fq(&ctx->fq, &flags); ++ BUG_ON(ret); ++ BUG_ON(flags & QMAN_FQ_STATE_BLOCKOOS); ++ /* OOS and free (don't kfree fq, it's a static ctx member) */ ++ ret = qman_oos_fq(&ctx->us_data->fqin); ++ BUG_ON(ret); ++ ret = qman_oos_fq(&ctx->fq); ++ BUG_ON(ret); ++ qman_destroy_fq(&ctx->us_data->fqin, 0); ++ qman_destroy_fq(&ctx->fq, 0); ++ kfree(ctx->us_data); ++ if (ctx->hw_flow) ++ pme_hw_flow_free(ctx->hw_flow); ++ if (ctx->hw_residue) ++ pme_hw_residue_free(ctx->hw_residue); ++} ++EXPORT_SYMBOL(pme_ctx_finish); ++ ++int pme_ctx_is_disabled(struct pme_ctx *ctx) ++{ ++ return (ctx->flags & PME_CTX_FLAG_DISABLED); ++} ++EXPORT_SYMBOL(pme_ctx_is_disabled); ++ ++int pme_ctx_is_dead(struct pme_ctx *ctx) ++{ ++ return (ctx->flags & PME_CTX_FLAG_DEAD); ++} ++EXPORT_SYMBOL(pme_ctx_is_dead); ++ ++/* predeclare this here because pme_ctx_disable() may invoke it in "privileged ++ * mode". The code is down with the other ctrl commands, where it belongs. */ ++static inline int __update_flow(struct pme_ctx *ctx, u32 flags, ++ struct pme_flow *params, struct pme_ctx_ctrl_token *token, ++ int is_disabling); ++ ++/* This gets invoked by pme_ctx_disable() if it runs to completion, otherwise ++ * it's called from cb_helper. */ ++static inline void __disable_done(struct pme_ctx *ctx) ++{ ++ struct qm_mcc_initfq initfq; ++ int ret = 0; ++ if (!(ctx->flags & PME_CTX_FLAG_EXCLUSIVE)) { ++ /* Park fqin (exclusive is always parked) */ ++ ret = park(&ctx->us_data->fqin, &initfq); ++ /* All the conditions for park() to succeed should be met. If ++ * this fails, there's a bug (s/w or h/w). */ ++ if (ret) ++ pr_crit("pme2: park() should never fail! (%d)\n", ret); ++ } ++ do_flags(ctx, 0, 0, PME_CTX_FLAG_DISABLED, 0); ++} ++ ++int pme_ctx_disable(struct pme_ctx *ctx, u32 flags, ++ struct pme_ctx_ctrl_token *token) ++{ ++ int ret; ++ ++ /* We must not (already) be DISABLING */ ++ ret = do_flags(ctx, 0, PME_CTX_FLAG_DISABLING, ++ PME_CTX_FLAG_DISABLING, 0); ++ if (ret) ++ return ret; ++ /* Make sure the pipeline is empty */ ++ atomic_dec(&ctx->refs); ++ ret = empty_pipeline(ctx, flags); ++ if (ret) ++ goto err; ++ /* We're idle, but is the flow context flushed from PME onboard cache? ++ * If it's not flushed when the system deallocates it, that 32 bytes ++ * could be in use later when PME decides to flush a write to it. Need ++ * to make it coherent again... */ ++ if (!(ctx->flags & PME_CTX_FLAG_DIRECT)) { ++ /* Pass on wait flags (if any) but cancel any flow-context field ++ * writes (this is not the pme_ctx_ctrl_update_flow() API). */ ++ ret = __update_flow(ctx, flags & ~PME_CMD_FCW_ALL, NULL, ++ token, 1); ++ if (ret) ++ goto err; ++ return 1; ++ } ++ __disable_done(ctx); ++ return 0; ++err: ++ atomic_inc(&ctx->refs); ++ do_flags(ctx, 0, 0, 0, PME_CTX_FLAG_DISABLING); ++ wake_up(&ctx->queue); ++ return ret; ++} ++EXPORT_SYMBOL(pme_ctx_disable); ++ ++int pme_ctx_enable(struct pme_ctx *ctx) ++{ ++ int ret; ++ ret = do_flags(ctx, PME_CTX_FLAG_DISABLED, ++ PME_CTX_FLAG_DEAD | PME_CTX_FLAG_RECONFIG | ++ PME_CTX_FLAG_ENABLING, ++ PME_CTX_FLAG_ENABLING, 0); ++ if (ret) ++ return ret; ++ if (!(ctx->flags & PME_CTX_FLAG_EXCLUSIVE)) { ++ ret = qman_init_fq(&ctx->us_data->fqin, ++ QMAN_INITFQ_FLAG_SCHED, NULL); ++ if (ret) { ++ do_flags(ctx, 0, 0, 0, PME_CTX_FLAG_ENABLING); ++ return ret; ++ } ++ } ++ atomic_inc(&ctx->refs); ++ do_flags(ctx, 0, 0, 0, PME_CTX_FLAG_DISABLED | PME_CTX_FLAG_DISABLING | ++ PME_CTX_FLAG_ENABLING); ++ return 0; ++} ++EXPORT_SYMBOL(pme_ctx_enable); ++ ++int pme_ctx_reconfigure_tx(struct pme_ctx *ctx, u32 bpid, u8 qosin) ++{ ++ struct qm_mcc_initfq initfq; ++ int ret; ++ ++ ret = do_flags(ctx, PME_CTX_FLAG_DISABLED, ++ PME_CTX_FLAG_DEAD | PME_CTX_FLAG_RECONFIG, ++ PME_CTX_FLAG_RECONFIG, 0); ++ if (ret) ++ return ret; ++ memset(&initfq,0,sizeof(initfq)); ++ pme_initfq(&initfq, ctx->hw_flow, qosin, bpid, qman_fq_fqid(&ctx->fq)); ++ ret = qman_init_fq(&ctx->us_data->fqin, 0, &initfq); ++ do_flags(ctx, 0, 0, 0, PME_CTX_FLAG_RECONFIG); ++ return ret; ++} ++EXPORT_SYMBOL(pme_ctx_reconfigure_tx); ++ ++int pme_ctx_reconfigure_rx(struct pme_ctx *ctx, u8 qosout, ++ u16 dest, const struct qm_fqd_stashing *stashing) ++{ ++ return reconfigure_rx(ctx, 1, qosout, dest, stashing); ++} ++EXPORT_SYMBOL(pme_ctx_reconfigure_rx); ++ ++/* Helpers for 'ctrl' and 'work' APIs. These are used when the 'ctx' in question ++ * is EXCLUSIVE. */ ++static inline void release_exclusive(__maybe_unused struct pme_ctx *ctx) ++{ ++ unsigned long irqflags; ++ ++ BUG_ON(exclusive_ctx != ctx); ++ BUG_ON(!exclusive_refs); ++ spin_lock_irqsave(&exclusive_lock, irqflags); ++ if (!(--exclusive_refs)) { ++ exclusive_ctx = NULL; ++ pme2_exclusive_unset(); ++ wake_up(&exclusive_queue); ++ } ++ spin_unlock_irqrestore(&exclusive_lock, irqflags); ++} ++static int __try_exclusive(struct pme_ctx *ctx) ++{ ++ int ret = 0; ++ unsigned long irqflags; ++ ++ spin_lock_irqsave(&exclusive_lock, irqflags); ++ if (exclusive_refs) { ++ /* exclusivity already held, continue if we're the owner */ ++ if (exclusive_ctx != ctx) ++ ret = -EBUSY; ++ } else { ++ /* it's not currently held */ ++ ret = pme2_exclusive_set(&ctx->us_data->fqin); ++ if (!ret) ++ exclusive_ctx = ctx; ++ } ++ if (!ret) ++ exclusive_refs++; ++ spin_unlock_irqrestore(&exclusive_lock, irqflags); ++ return ret; ++} ++/* Use this macro as the wait expression because we don't want to continue ++ * looping if the reason we're failing is that we don't have CCSR access ++ * (-ENODEV). */ ++#define try_exclusive(ret, ctx) \ ++ (!(ret = __try_exclusive(ctx)) || (ret == -ENODEV)) ++static inline int get_exclusive(struct pme_ctx *ctx, __maybe_unused u32 flags) ++{ ++ int ret; ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & PME_CTX_OP_WAIT) { ++ if (flags & PME_CTX_OP_WAIT_INT) { ++ ret = -EINTR; ++ wait_event_interruptible(exclusive_queue, ++ try_exclusive(ret, ctx)); ++ } else ++ wait_event(exclusive_queue, ++ try_exclusive(ret, ctx)); ++ } else ++#endif ++ ret = __try_exclusive(ctx); ++ return ret; ++} ++ ++/* Used for 'work' APIs, convert PME->QMAN wait flags. The PME and ++ * QMAN "wait" flags have been aligned so that the below conversion should ++ * compile with good straight-line speed. */ ++static inline u32 ctrl2eq(u32 flags) ++{ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ return flags & (QMAN_ENQUEUE_FLAG_WAIT | QMAN_ENQUEUE_FLAG_WAIT_INT); ++#else ++ return flags; ++#endif ++} ++ ++static inline void release_work(struct pme_ctx *ctx) ++{ ++ if (atomic_dec_and_test(&ctx->refs)) ++ wake_up(&ctx->queue); ++} ++ ++#define BLOCK_NORMAL_WORK (PME_CTX_FLAG_DEAD | PME_CTX_FLAG_DISABLING) ++static int try_work(struct pme_ctx *ctx, u32 flags) ++{ ++ atomic_inc(&ctx->refs); ++ if (unlikely(!(flags & PME_CTX_OP_INSIDE_DISABLE) && ++ (ctx->flags & BLOCK_NORMAL_WORK))) { ++ release_work(ctx); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int get_work(struct pme_ctx *ctx, u32 flags) ++{ ++ int ret = 0; ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & PME_CTX_OP_WAIT) { ++ if (flags & PME_CTX_OP_WAIT_INT) { ++ ret = -EINTR; ++ wait_event_interruptible(ctx->queue, ++ !(ret = try_work(ctx, flags))); ++ } else ++ wait_event(ctx->queue, !try_work(ctx, flags)); ++ } else ++#endif ++ ret = try_work(ctx, flags); ++ return ret; ++} ++ ++static inline int do_work(struct pme_ctx *ctx, u32 flags, struct qm_fd *fd, ++ struct pme_ctx_token *token, struct qman_fq *orp_fq, u16 seqnum) ++{ ++ unsigned long irqflags; ++ int ret = get_work(ctx, flags); ++ if (ret) ++ return ret; ++ if (ctx->flags & PME_CTX_FLAG_EXCLUSIVE) { ++ ret = get_exclusive(ctx, flags); ++ if (ret) { ++ release_work(ctx); ++ return ret; ++ } ++ } ++ BUG_ON(sizeof(*fd) != sizeof(token->blob)); ++ memcpy(&token->blob, fd, sizeof(*fd)); ++ ++ spin_lock_irqsave(&ctx->lock, irqflags); ++ list_add_tail(&token->node, &ctx->tokens); ++ spin_unlock_irqrestore(&ctx->lock, irqflags); ++ ++ if (!orp_fq) ++ ret = qman_enqueue(&ctx->us_data->fqin, fd, ctrl2eq(flags)); ++ else ++ ret = qman_enqueue_orp(&ctx->us_data->fqin, fd, ctrl2eq(flags), ++ orp_fq, seqnum); ++ if (ret) { ++ spin_lock_irqsave(&ctx->lock, irqflags); ++ list_del(&token->node); ++ spin_unlock_irqrestore(&ctx->lock, irqflags); ++ if (ctx->flags & PME_CTX_FLAG_EXCLUSIVE) ++ release_exclusive(ctx); ++ release_work(ctx); ++ } ++ return ret; ++} ++ ++static inline int __update_flow(struct pme_ctx *ctx, u32 flags, ++ struct pme_flow *params, struct pme_ctx_ctrl_token *token, ++ int is_disabling) ++{ ++ struct qm_fd fd; ++ int ret; ++ int hw_res_used = 0; ++ struct pme_hw_residue *hw_res = pme_hw_residue_new(); ++ unsigned long irqflags; ++ ++ BUG_ON(ctx->flags & PME_CTX_FLAG_DIRECT); ++ if (!hw_res) ++ return -ENOMEM; ++ token->internal_flow_ptr = pme_hw_flow_new(); ++ if (!token->internal_flow_ptr) { ++ pme_hw_residue_free(hw_res); ++ return -ENOMEM; ++ } ++ token->base_token.cmd_type = pme_cmd_flow_write; ++ ++ flags &= ~PME_CTX_OP_PRIVATE; ++ /* The callback will want to know this */ ++ token->base_token.is_disable_flush = is_disabling ? 1 : 0; ++ flags |= (is_disabling ? PME_CTX_OP_INSIDE_DISABLE : 0); ++ spin_lock_irqsave(&ctx->lock, irqflags); ++ if (flags & PME_CTX_OP_RESETRESLEN) { ++ if (ctx->hw_residue) { ++ params->ren = 1; ++ flags |= PME_CMD_FCW_RES; ++ } else ++ flags &= ~PME_CMD_FCW_RES; ++ } ++ /* allocate residue memory if it is being added */ ++ if ((flags & PME_CMD_FCW_RES) && params->ren && !ctx->hw_residue) { ++ ctx->hw_residue = hw_res; ++ hw_res_used = 1; ++ } ++ spin_unlock_irqrestore(&ctx->lock, irqflags); ++ if (!hw_res_used) ++ pme_hw_residue_free(hw_res); ++ /* enqueue the FCW command to PME */ ++ memset(&fd, 0, sizeof(fd)); ++ if (params) ++ memcpy(token->internal_flow_ptr, params, ++ sizeof(struct pme_flow)); ++ pme_fd_cmd_fcw(&fd, flags & PME_CMD_FCW_ALL, ++ (struct pme_flow *)token->internal_flow_ptr, ++ ctx->hw_residue); ++ ret = do_work(ctx, flags, &fd, &token->base_token, NULL, 0); ++ return ret; ++} ++ ++int pme_ctx_ctrl_update_flow(struct pme_ctx *ctx, u32 flags, ++ struct pme_flow *params, struct pme_ctx_ctrl_token *token) ++{ ++ return __update_flow(ctx, flags, params, token, 0); ++} ++EXPORT_SYMBOL(pme_ctx_ctrl_update_flow); ++ ++int pme_ctx_ctrl_read_flow(struct pme_ctx *ctx, u32 flags, ++ struct pme_flow *params, struct pme_ctx_ctrl_token *token) ++{ ++ struct qm_fd fd; ++ ++ BUG_ON(ctx->flags & (PME_CTX_FLAG_DIRECT | PME_CTX_FLAG_PMTCC)); ++ token->base_token.cmd_type = pme_cmd_flow_read; ++ /* enqueue the FCR command to PME */ ++ token->usr_flow_ptr = params; ++ token->internal_flow_ptr = pme_hw_flow_new(); ++ if (!token->internal_flow_ptr) ++ return -ENOMEM; ++ memset(&fd, 0, sizeof(fd)); ++ pme_fd_cmd_fcr(&fd, (struct pme_flow *)token->internal_flow_ptr); ++ return do_work(ctx, flags, &fd, &token->base_token, NULL, 0); ++} ++EXPORT_SYMBOL(pme_ctx_ctrl_read_flow); ++ ++int pme_ctx_ctrl_nop(struct pme_ctx *ctx, u32 flags, ++ struct pme_ctx_ctrl_token *token) ++{ ++ struct qm_fd fd; ++ ++ token->base_token.cmd_type = pme_cmd_nop; ++ /* enqueue the NOP command to PME */ ++ memset(&fd, 0, sizeof(fd)); ++ qm_fd_addr_set64(&fd, (unsigned long)token); ++ pme_fd_cmd_nop(&fd); ++ return do_work(ctx, flags, &fd, &token->base_token, NULL, 0); ++} ++EXPORT_SYMBOL(pme_ctx_ctrl_nop); ++ ++static inline int __prep_scan(__maybe_unused struct pme_ctx *ctx, ++ struct qm_fd *fd, u32 args, struct pme_ctx_token *token) ++{ ++ BUG_ON(ctx->flags & PME_CTX_FLAG_PMTCC); ++ token->cmd_type = pme_cmd_scan; ++ pme_fd_cmd_scan(fd, args); ++#ifdef CONFIG_FSL_PME_BUG_4K_SCAN_REV_2_1_4 ++ if (ctx->max_scan_size) { ++ if (fd->format == qm_fd_contig || fd->format == qm_fd_sg) { ++ if (fd->length20 > ctx->max_scan_size) { ++ return -EINVAL; ++ } ++ } else if (fd->format == qm_fd_contig_big || ++ fd->format == qm_fd_sg_big) { ++ if (fd->length29 > ctx->max_scan_size) { ++ return -EINVAL; ++ } ++ } ++ } ++#endif ++ return 0; ++} ++ ++int pme_ctx_scan(struct pme_ctx *ctx, u32 flags, struct qm_fd *fd, u32 args, ++ struct pme_ctx_token *token) ++{ ++ int ret; ++ ++ ret = __prep_scan(ctx, fd, args, token); ++ if (ret) ++ return ret; ++ return do_work(ctx, flags, fd, token, NULL, 0); ++} ++EXPORT_SYMBOL(pme_ctx_scan); ++ ++int pme_ctx_scan_orp(struct pme_ctx *ctx, u32 flags, struct qm_fd *fd, u32 args, ++ struct pme_ctx_token *token, struct qman_fq *orp_fq, u16 seqnum) ++{ ++ __prep_scan(ctx, fd, args, token); ++ return do_work(ctx, flags, fd, token, orp_fq, seqnum); ++} ++EXPORT_SYMBOL(pme_ctx_scan_orp); ++ ++int pme_ctx_pmtcc(struct pme_ctx *ctx, u32 flags, struct qm_fd *fd, ++ struct pme_ctx_token *token) ++{ ++ BUG_ON(!(ctx->flags & PME_CTX_FLAG_PMTCC)); ++ token->cmd_type = pme_cmd_pmtcc; ++ pme_fd_cmd_pmtcc(fd); ++ return do_work(ctx, flags, fd, token, NULL, 0); ++} ++EXPORT_SYMBOL(pme_ctx_pmtcc); ++ ++int pme_ctx_exclusive_inc(struct pme_ctx *ctx, u32 flags) ++{ ++ return get_exclusive(ctx, flags); ++} ++EXPORT_SYMBOL(pme_ctx_exclusive_inc); ++ ++void pme_ctx_exclusive_dec(struct pme_ctx *ctx) ++{ ++ release_exclusive(ctx); ++} ++EXPORT_SYMBOL(pme_ctx_exclusive_dec); ++ ++/* The 99.99% case is that enqueues happen in order or they get order-restored ++ * by the ORP, and so dequeues of responses happen in order too, so our FIFO ++ * linked-list of tokens is append-on-enqueue and pop-on-dequeue, and all's ++ * well. ++ * ++ * *EXCEPT*, if ever an enqueue gets rejected ... what then happens is that we ++ * have dequeues and ERNs to deal with, and the order we see them in is not ++ * necessarily the linked-list order. So we need to handle this in DQRR and MR ++ * callbacks, without sacrificing fast-path performance. Ouch. ++ * ++ * We use pop_matching_token() to take care of the mess (inlined, of course). */ ++#define MATCH(fd1,fd2) \ ++ ((qm_fd_addr_get64(fd1) == qm_fd_addr_get64(fd2)) && \ ++ ((fd1)->opaque == (fd2)->opaque)) ++static inline struct pme_ctx_token *pop_matching_token(struct pme_ctx *ctx, ++ const struct qm_fd *fd) ++{ ++ struct pme_ctx_token *token; ++ const struct qm_fd *t_fd; ++ unsigned long irqflags; ++ ++ /* The fast-path case is that the for() loop actually degenerates into; ++ * token = list_first_entry(); ++ * if (likely(MATCH())) ++ * [done] ++ * The penalty of the slow-path case is the for() loop plus the fact ++ * we're optimising for a "likely" match first time, which might hurt ++ * when that assumption is wrong a few times in succession. */ ++ spin_lock_irqsave(&ctx->lock, irqflags); ++ list_for_each_entry(token, &ctx->tokens, node) { ++ t_fd = (const struct qm_fd *)&token->blob[0]; ++ if (likely(MATCH(t_fd, fd))) { ++ list_del(&token->node); ++ goto found; ++ } ++ } ++ token = NULL; ++ pr_err("PME2 Could not find matching token!\n"); ++ BUG(); ++found: ++ spin_unlock_irqrestore(&ctx->lock, irqflags); ++ return token; ++} ++ ++static inline void cb_helper(__always_unused struct qman_portal *portal, ++ struct pme_ctx *ctx, const struct qm_fd *fd, int error) ++{ ++ struct pme_ctx_token *token; ++ struct pme_ctx_ctrl_token *ctrl_token; ++ ++ /* Resist the urge to use "unlikely" - 'error' is a constant param to an ++ * inline fn, so the compiler can collapse this completely. */ ++ if (error) ++ do_flags(ctx, 0, 0, PME_CTX_FLAG_DEAD, 0); ++ token = pop_matching_token(ctx, fd); ++ if (likely(token->cmd_type == pme_cmd_scan)) ++ ctx->cb(ctx, fd, token); ++ else if (token->cmd_type == pme_cmd_pmtcc) ++ ctx->cb(ctx, fd, token); ++ else { ++ /* outcast ctx and call supplied callback */ ++ ctrl_token = container_of(token, struct pme_ctx_ctrl_token, ++ base_token); ++ if (token->cmd_type == pme_cmd_flow_write) { ++ /* Release the allocated flow context */ ++ pme_hw_flow_free(ctrl_token->internal_flow_ptr); ++ /* Is this pme_ctx_disable() completion? */ ++ if (token->is_disable_flush) ++ __disable_done(ctx); ++ } else if (token->cmd_type == pme_cmd_flow_read) { ++ /* Copy read result */ ++ memcpy(ctrl_token->usr_flow_ptr, ++ ctrl_token->internal_flow_ptr, ++ sizeof(struct pme_flow)); ++ /* Release the allocated flow context */ ++ pme_hw_flow_free(ctrl_token->internal_flow_ptr); ++ } ++ ctrl_token->cb(ctx, fd, ctrl_token); ++ } ++ /* Consume the frame */ ++ if (ctx->flags & PME_CTX_FLAG_EXCLUSIVE) ++ release_exclusive(ctx); ++ if (atomic_dec_and_test(&ctx->refs)) ++ wake_up(&ctx->queue); ++} ++ ++/* TODO: this scheme does not allow PME receivers to use held-active at all. Eg. ++ * there's no configuration of held-active for 'fq', and if there was, there's ++ * (a) nothing in the cb_dqrr() to support "park" or "defer" logic, and (b) ++ * nothing in cb_fqs() to support a delayed FQPN (DCAP_PK) notification. */ ++static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, const struct qm_dqrr_entry *dq) ++{ ++ u8 status = (u8)pme_fd_res_status(&dq->fd); ++ u8 flags = pme_fd_res_flags(&dq->fd); ++ struct pme_ctx *ctx = (struct pme_ctx *)fq; ++ ++ /* Put context into dead state is an unreliable or serious error is ++ * received ++ */ ++ if (unlikely(flags & PME_STATUS_UNRELIABLE)) ++ cb_helper(portal, ctx, &dq->fd, 1); ++ else if (unlikely((serious_error_vec[status]))) ++ cb_helper(portal, ctx, &dq->fd, 1); ++ else ++ cb_helper(portal, ctx, &dq->fd, 0); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static void cb_ern(__always_unused struct qman_portal *portal, ++ struct qman_fq *fq, const struct qm_mr_entry *mr) ++{ ++ struct pme_ctx *ctx; ++ struct pme_nostash *data; ++ struct pme_ctx_token *token; ++ ++ data = container_of(fq, struct pme_nostash, fqin); ++ ctx = data->parent; ++ ++ token = pop_matching_token(ctx, &mr->ern.fd); ++ if (likely(token->cmd_type == pme_cmd_scan)) { ++ BUG_ON(!ctx->ern_cb); ++ ctx->ern_cb(ctx, mr, token); ++ } else if (token->cmd_type == pme_cmd_pmtcc) { ++ BUG_ON(!ctx->ern_cb); ++ ctx->ern_cb(ctx, mr, token); ++ } else { ++ struct pme_ctx_ctrl_token *ctrl_token; ++ /* outcast ctx and call supplied callback */ ++ ctrl_token = container_of(token, struct pme_ctx_ctrl_token, ++ base_token); ++ if (token->cmd_type == pme_cmd_flow_write) { ++ /* Release the allocated flow context */ ++ pme_hw_flow_free(ctrl_token->internal_flow_ptr); ++ } else if (token->cmd_type == pme_cmd_flow_read) { ++ /* Copy read result */ ++ memcpy(ctrl_token->usr_flow_ptr, ++ ctrl_token->internal_flow_ptr, ++ sizeof(struct pme_flow)); ++ /* Release the allocated flow context */ ++ pme_hw_flow_free(ctrl_token->internal_flow_ptr); ++ } ++ BUG_ON(!ctrl_token->ern_cb); ++ ctrl_token->ern_cb(ctx, mr, ctrl_token); ++ } ++ /* Consume the frame */ ++ if (ctx->flags & PME_CTX_FLAG_EXCLUSIVE) ++ release_exclusive(ctx); ++ if (atomic_dec_and_test(&ctx->refs)) ++ wake_up(&ctx->queue); ++} ++ ++static void cb_fqs(__always_unused struct qman_portal *portal, ++ __always_unused struct qman_fq *fq, ++ const struct qm_mr_entry *mr) ++{ ++ u8 verb = mr->verb & QM_MR_VERB_TYPE_MASK; ++ if (verb == QM_MR_VERB_FQRNI) ++ return; ++ /* nothing else is supposed to occur */ ++ BUG(); ++} +diff --git a/drivers/staging/fsl_pme2/pme2_low.c b/drivers/staging/fsl_pme2/pme2_low.c +new file mode 100644 +index 0000000..cb54cf4 +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_low.c +@@ -0,0 +1,275 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "pme2_private.h" ++ ++MODULE_AUTHOR("Geoff Thorpe"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("FSL PME2 (p4080) device usage"); ++ ++#define PME_RESIDUE_SIZE 128 ++#define PME_RESIDUE_ALIGN 64 ++#define PME_FLOW_SIZE sizeof(struct pme_flow) ++#define PME_FLOW_ALIGN 32 ++static struct kmem_cache *slab_residue; ++static struct kmem_cache *slab_flow; ++static struct kmem_cache *slab_fq; ++ ++/* Hack to support "pme_map()". The point of this is that dma_map_single() now ++ * requires a non-NULL device, so the idea is that address mapping must be ++ * device-sensitive. Now the PAMU IO-MMU already takes care of this, as can be ++ * seen by the device-tree structure generated by the hypervisor (each portal ++ * node has sub-nodes for each h/w end-point it provides access to, and each ++ * sub-node has its own LIODN configuration). So we just need to map cpu ++ * pointers to (guest-)physical address and the PAMU takes care of the rest, so ++ * this doesn't need to be portal-sensitive nor device-sensitive. */ ++static struct platform_device *pdev; ++ ++static int pme2_low_init(void) ++{ ++ int ret = -ENOMEM; ++ ++ slab_residue = kmem_cache_create("pme2_residue", PME_RESIDUE_SIZE, ++ PME_RESIDUE_ALIGN, SLAB_HWCACHE_ALIGN, NULL); ++ if (!slab_residue) ++ goto end; ++ slab_flow = kmem_cache_create("pme2_flow", PME_FLOW_SIZE, ++ PME_FLOW_ALIGN, 0, NULL); ++ if (!slab_flow) ++ goto end; ++ slab_fq = kmem_cache_create("pme2_fqslab", sizeof(struct qman_fq), ++ __alignof__(struct qman_fq), SLAB_HWCACHE_ALIGN, NULL); ++ if (!slab_fq) ++ goto end; ++ ret = -ENODEV; ++ pdev = platform_device_alloc("pme", -1); ++ if (!pdev) ++ goto end; ++ if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(40))) ++ goto end; ++ if (platform_device_add(pdev)) ++ goto end; ++ return 0; ++end: ++ if (pdev) { ++ platform_device_put(pdev); ++ pdev = NULL; ++ } ++ if (slab_flow) { ++ kmem_cache_destroy(slab_flow); ++ slab_flow = NULL; ++ } ++ if (slab_residue) { ++ kmem_cache_destroy(slab_residue); ++ slab_residue = NULL; ++ } ++ if (slab_fq) { ++ kmem_cache_destroy(slab_fq); ++ slab_fq = NULL; ++ } ++ return ret; ++} ++ ++static void pme2_low_exit(void) ++{ ++ platform_device_del(pdev); ++ platform_device_put(pdev); ++ pdev = NULL; ++ kmem_cache_destroy(slab_fq); ++ kmem_cache_destroy(slab_flow); ++ kmem_cache_destroy(slab_residue); ++ slab_fq = slab_flow = slab_residue = NULL; ++} ++ ++module_init(pme2_low_init); ++module_exit(pme2_low_exit); ++ ++struct qman_fq *slabfq_alloc(void) ++{ ++ return kmem_cache_alloc(slab_fq, GFP_KERNEL); ++} ++ ++void slabfq_free(struct qman_fq *fq) ++{ ++ kmem_cache_free(slab_fq, fq); ++} ++ ++/***********************/ ++/* low-level functions */ ++/***********************/ ++ ++struct pme_hw_residue *pme_hw_residue_new(void) ++{ ++ return kmem_cache_alloc(slab_residue, GFP_KERNEL); ++} ++EXPORT_SYMBOL(pme_hw_residue_new); ++ ++void pme_hw_residue_free(struct pme_hw_residue *p) ++{ ++ kmem_cache_free(slab_residue, p); ++} ++EXPORT_SYMBOL(pme_hw_residue_free); ++ ++struct pme_hw_flow *pme_hw_flow_new(void) ++{ ++ struct pme_flow *flow = kmem_cache_zalloc(slab_flow, GFP_KERNEL); ++ return (struct pme_hw_flow *)flow; ++} ++EXPORT_SYMBOL(pme_hw_flow_new); ++ ++void pme_hw_flow_free(struct pme_hw_flow *p) ++{ ++ kmem_cache_free(slab_flow, p); ++} ++EXPORT_SYMBOL(pme_hw_flow_free); ++ ++static const struct pme_flow default_sw_flow = { ++ .sos = 1, ++ .srvm = 0, ++ .esee = 1, ++ .ren = 0, ++ .rlen = 0, ++ .seqnum_hi = 0, ++ .seqnum_lo = 0, ++ .sessionid = 0x7ffffff, ++ .rptr_hi = 0, ++ .rptr_lo = 0, ++ .clim = 0xffff, ++ .mlim = 0xffff ++}; ++ ++void pme_sw_flow_init(struct pme_flow *flow) ++{ ++ memcpy(flow, &default_sw_flow, sizeof(*flow)); ++} ++EXPORT_SYMBOL(pme_sw_flow_init); ++ ++void pme_initfq(struct qm_mcc_initfq *initfq, struct pme_hw_flow *flow, u8 qos, ++ u8 rbpid, u32 rfqid) ++{ ++ struct pme_context_a *pme_a = ++ (struct pme_context_a *)&initfq->fqd.context_a; ++ struct pme_context_b *pme_b = ++ (struct pme_context_b *)&initfq->fqd.context_b; ++ ++ initfq->we_mask = QM_INITFQ_WE_DESTWQ | QM_INITFQ_WE_CONTEXTA | ++ QM_INITFQ_WE_CONTEXTB; ++ initfq->fqd.dest.channel = qm_channel_pme; ++ initfq->fqd.dest.wq = qos; ++ if (flow) { ++ dma_addr_t fcp = flow_map((struct pme_flow *)flow); ++ pme_a->mode = pme_mode_flow; ++ pme_context_a_set64(pme_a, fcp); ++ } else { ++ pme_a->mode = pme_mode_direct; ++ pme_context_a_set64(pme_a, 0); ++ } ++ pme_b->rbpid = rbpid; ++ pme_b->rfqid = rfqid; ++} ++EXPORT_SYMBOL(pme_initfq); ++ ++void pme_fd_cmd_nop(struct qm_fd *fd) ++{ ++ struct pme_cmd_nop *nop = (struct pme_cmd_nop *)&fd->cmd; ++ nop->cmd = pme_cmd_nop; ++} ++EXPORT_SYMBOL(pme_fd_cmd_nop); ++ ++void pme_fd_cmd_fcw(struct qm_fd *fd, u8 flags, struct pme_flow *flow, ++ struct pme_hw_residue *residue) ++{ ++ dma_addr_t f; ++ struct pme_cmd_flow_write *fcw = (struct pme_cmd_flow_write *)&fd->cmd; ++ ++ BUG_ON(!flow); ++ BUG_ON((unsigned long)flow & 31); ++ fcw->cmd = pme_cmd_flow_write; ++ fcw->flags = flags; ++ if (flags & PME_CMD_FCW_RES) { ++ if (residue) { ++ dma_addr_t rptr = residue_map(residue); ++ BUG_ON(!residue); ++ BUG_ON((unsigned long)residue & 63); ++ pme_flow_rptr_set64(flow, rptr); ++ } else ++ pme_flow_rptr_set64(flow, 0); ++ } ++ f = flow_map(flow); ++ qm_fd_addr_set64(fd, f); ++ fd->format = qm_fd_contig; ++ fd->offset = 0; ++ fd->length20 = sizeof(*flow); ++} ++EXPORT_SYMBOL(pme_fd_cmd_fcw); ++ ++void pme_fd_cmd_fcr(struct qm_fd *fd, struct pme_flow *flow) ++{ ++ dma_addr_t f; ++ struct pme_cmd_flow_read *fcr = (struct pme_cmd_flow_read *)&fd->cmd; ++ ++ BUG_ON(!flow); ++ BUG_ON((unsigned long)flow & 31); ++ fcr->cmd = pme_cmd_flow_read; ++ f = flow_map(flow); ++ qm_fd_addr_set64(fd, f); ++ fd->format = qm_fd_contig; ++ fd->offset = 0; ++ fd->length20 = sizeof(*flow); ++} ++EXPORT_SYMBOL(pme_fd_cmd_fcr); ++ ++void pme_fd_cmd_pmtcc(struct qm_fd *fd) ++{ ++ struct pme_cmd_pmtcc *pmtcc = (struct pme_cmd_pmtcc *)&fd->cmd; ++ pmtcc->cmd = pme_cmd_pmtcc; ++} ++EXPORT_SYMBOL(pme_fd_cmd_pmtcc); ++ ++void pme_fd_cmd_scan(struct qm_fd *fd, u32 args) ++{ ++ struct pme_cmd_scan *scan = (struct pme_cmd_scan *)&fd->cmd; ++ fd->cmd = args; ++ scan->cmd = pme_cmd_scan; ++} ++EXPORT_SYMBOL(pme_fd_cmd_scan); ++ ++dma_addr_t pme_map(void *ptr) ++{ ++ return dma_map_single(&pdev->dev, ptr, 1, DMA_BIDIRECTIONAL); ++} ++EXPORT_SYMBOL(pme_map); ++ ++int pme_map_error(dma_addr_t dma_addr) ++{ ++ return dma_mapping_error(&pdev->dev, dma_addr); ++} ++EXPORT_SYMBOL(pme_map_error); +diff --git a/drivers/staging/fsl_pme2/pme2_private.h b/drivers/staging/fsl_pme2/pme2_private.h +new file mode 100644 +index 0000000..1a9cb03 +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_private.h +@@ -0,0 +1,214 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "pme2_sys.h" ++#include ++ ++#undef PME2_DEBUG ++ ++#ifdef PME2_DEBUG ++#define PMEPRINFO(fmt, args...) pr_info("PME2: %s: " fmt, __func__, ## args) ++#else ++#define PMEPRINFO(fmt, args...) ++#endif ++ ++#define PMEPRERR(fmt, args...) pr_err("PME2: %s: " fmt, __func__, ## args) ++#define PMEPRCRIT(fmt, args...) pr_crit("PME2: %s: " fmt, __func__, ## args) ++ ++#ifdef CONFIG_FSL_PME2_CTRL ++/* Hooks */ ++int pme2_create_sysfs_dev_files(struct platform_device *ofdev); ++void pme2_remove_sysfs_dev_files(struct platform_device *ofdev); ++void accumulator_update_interval(u32 interval); ++#endif ++ ++static inline void set_fd_addr(struct qm_fd *fd, dma_addr_t addr) ++{ ++ qm_fd_addr_set64(fd, addr); ++} ++static inline dma_addr_t get_fd_addr(const struct qm_fd *fd) ++{ ++ return (dma_addr_t)qm_fd_addr_get64(fd); ++} ++static inline void set_sg_addr(struct qm_sg_entry *sg, dma_addr_t addr) ++{ ++ qm_sg_entry_set64(sg, addr); ++} ++static inline dma_addr_t get_sg_addr(const struct qm_sg_entry *sg) ++{ ++ return (dma_addr_t)qm_sg_entry_get64(sg); ++} ++ ++/******************/ ++/* Datapath types */ ++/******************/ ++ ++enum pme_mode { ++ pme_mode_direct = 0x00, ++ pme_mode_flow = 0x80 ++}; ++ ++struct pme_context_a { ++ enum pme_mode mode:8; ++ u8 __reserved; ++ /* Flow Context pointer (48-bit), ignored if mode==direct */ ++ u16 flow_hi; ++ u32 flow_lo; ++} __packed; ++static inline u64 pme_context_a_get64(const struct pme_context_a *p) ++{ ++ return ((u64)p->flow_hi << 32) | (u64)p->flow_lo; ++} ++/* Macro, so we compile better if 'v' isn't always 64-bit */ ++#define pme_context_a_set64(p, v) \ ++ do { \ ++ struct pme_context_a *__p931 = (p); \ ++ __p931->flow_hi = upper_32_bits(v); \ ++ __p931->flow_lo = lower_32_bits(v); \ ++ } while (0) ++ ++struct pme_context_b { ++ u32 rbpid:8; ++ u32 rfqid:24; ++} __packed; ++ ++ ++/* This is the 32-bit frame "cmd/status" field, sent to PME */ ++union pme_cmd { ++ struct pme_cmd_nop { ++ enum pme_cmd_type cmd:3; ++ } nop; ++ struct pme_cmd_flow_read { ++ enum pme_cmd_type cmd:3; ++ } fcr; ++ struct pme_cmd_flow_write { ++ enum pme_cmd_type cmd:3; ++ u8 __reserved:5; ++ u8 flags; /* See PME_CMD_FCW_*** */ ++ } __packed fcw; ++ struct pme_cmd_pmtcc { ++ enum pme_cmd_type cmd:3; ++ } pmtcc; ++ struct pme_cmd_scan { ++ union { ++ struct { ++ enum pme_cmd_type cmd:3; ++ u8 flags:5; /* See PME_CMD_SCAN_*** */ ++ } __packed; ++ }; ++ u8 set; ++ u16 subset; ++ } __packed scan; ++}; ++ ++/* The exported macro forms a "scan_args" u32 from 3 inputs, these private ++ * inlines do the inverse, if you need to crack one apart. */ ++static inline u8 scan_args_get_flags(u32 args) ++{ ++ return args >> 24; ++} ++static inline u8 scan_args_get_set(u32 args) ++{ ++ return (args >> 16) & 0xff; ++} ++static inline u16 scan_args_get_subset(u32 args) ++{ ++ return args & 0xffff; ++} ++ ++/* Hook from pme2_high to pme2_low */ ++struct qman_fq *slabfq_alloc(void); ++void slabfq_free(struct qman_fq *fq); ++ ++/* Hook from pme2_high to pme2_ctrl */ ++int pme2_have_control(void); ++int pme2_exclusive_set(struct qman_fq *fq); ++int pme2_exclusive_unset(void); ++ ++#define DECLARE_GLOBAL(name, t, mt, def, desc) \ ++ static t name = def; \ ++ module_param(name, mt, 0644); \ ++ MODULE_PARM_DESC(name, desc ", default: " __stringify(def)); ++ ++/* Constants used by the SRE ioctl. */ ++#define PME_PMFA_SRE_POLL_MS 100 ++#define PME_PMFA_SRE_INDEX_MAX (1 << 27) ++#define PME_PMFA_SRE_INC_MAX (1 << 12) ++#define PME_PMFA_SRE_REP_MAX (1 << 28) ++#define PME_PMFA_SRE_INTERVAL_MAX (1 << 12) ++ ++/* Encapsulations for mapping */ ++#define flow_map(flow) \ ++({ \ ++ struct pme_flow *__f913 = (flow); \ ++ pme_map(__f913); \ ++}) ++ ++#define residue_map(residue) \ ++({ \ ++ struct pme_hw_residue *__f913 = (residue); \ ++ pme_map(__f913); \ ++}) ++ ++/* 4k minus residue */ ++#define PME_MAX_SCAN_SIZE_BUG_2_1_4 (4095 - 127) ++ ++#define PME_PM_IP_REV_1_IP_MJ_MASK 0x0000ff00UL ++#define PME_PM_IP_REV_1_IP_MJ_SHIFT 8UL ++#define PME_PM_IP_REV_1_IP_MN_MASK 0x000000ffUL ++#define PME_PM_IP_REV_1_IP_MN_SHIFT 0UL ++#define PME_PM_IP_REV_2_IP_ERR_MASK 0x0000ff00UL ++#define PME_PM_IP_REV_2_IP_ERR_SHIFT 8UL ++ ++static inline int get_major_rev(u32 pme_rev1) ++{ ++ return (pme_rev1 & PME_PM_IP_REV_1_IP_MJ_MASK) >> ++ PME_PM_IP_REV_1_IP_MJ_SHIFT; ++} ++ ++static inline int get_minor_rev(u32 pme_rev1) ++{ ++ return (pme_rev1 & PME_PM_IP_REV_1_IP_MN_MASK) >> ++ PME_PM_IP_REV_1_IP_MN_SHIFT; ++} ++ ++static inline int get_errata_rev(u32 pme_rev2) ++{ ++ return (pme_rev2 & PME_PM_IP_REV_2_IP_ERR_MASK) >> ++ PME_PM_IP_REV_2_IP_ERR_SHIFT; ++} ++ ++static inline int is_version_2_1_4(u32 pme_rev1, u32 pme_rev2) ++{ ++ return (get_major_rev(pme_rev1) == 2) && ++ (get_minor_rev(pme_rev1) == 1) && ++ (get_errata_rev(pme_rev2) == 4); ++} +diff --git a/drivers/staging/fsl_pme2/pme2_regs.h b/drivers/staging/fsl_pme2/pme2_regs.h +new file mode 100644 +index 0000000..1894b02 +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_regs.h +@@ -0,0 +1,173 @@ ++/* Copyright 2009-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 PME2_REGS_H ++#define PME2_REGS_H ++ ++#define PME_REG_ISR 0x000 ++#define PME_REG_IER 0x004 ++#define PME_REG_ISDR 0x008 ++#define PME_REG_IIR 0x00C ++#define PME_REG_RLL 0x014 ++#define PME_REG_CDCR 0x018 ++#define PME_REG_TRUNCI 0x024 ++#define PME_REG_RBC 0x028 ++#define PME_REG_ESR 0x02C ++#define PME_REG_ECR0 0x030 ++#define PME_REG_ECR1 0x034 ++#define PME_REG_EFQC 0x050 ++#define PME_REG_FACONF 0x060 ++#define PME_REG_PMSTAT 0x064 ++#define PME_REG_FAMCR 0x068 ++#define PME_REG_PMTR 0x06C ++#define PME_REG_PEHD 0x074 ++#define PME_REG_BSC0 0x080 ++#define PME_REG_BSC1 0x084 ++#define PME_REG_BSC2 0x088 ++#define PME_REG_BSC3 0x08C ++#define PME_REG_BSC4 0x090 ++#define PME_REG_BSC5 0x094 ++#define PME_REG_BSC6 0x098 ++#define PME_REG_BSC7 0x09C ++#define PME_REG_QMBFD0 0x0E0 ++#define PME_REG_QMBFD1 0x0E4 ++#define PME_REG_QMBFD2 0x0E8 ++#define PME_REG_QMBFD3 0x0EC ++#define PME_REG_QMBCTXTAH 0x0F0 ++#define PME_REG_QMBCTXTAL 0x0F4 ++#define PME_REG_QMBCTXTB 0x0F8 ++#define PME_REG_QMBCTL 0x0FC ++#define PME_REG_ECC1BES 0x100 ++#define PME_REG_ECC2BES 0x104 ++#define PME_REG_ECCADDR 0x110 ++#define PME_REG_ECCCODE 0x118 ++#define PME_REG_TBT0ECC1TH 0x180 ++#define PME_REG_TBT0ECC1EC 0x184 ++#define PME_REG_TBT1ECC1TH 0x188 ++#define PME_REG_TBT1ECC1EC 0x18C ++#define PME_REG_VLT0ECC1TH 0x190 ++#define PME_REG_VLT0ECC1EC 0x194 ++#define PME_REG_VLT1ECC1TH 0x198 ++#define PME_REG_VLT1ECC1EC 0x19C ++#define PME_REG_CMECC1TH 0x1A0 ++#define PME_REG_CMECC1EC 0x1A4 ++#define PME_REG_DXCMECC1TH 0x1B0 ++#define PME_REG_DXCMECC1EC 0x1B4 ++#define PME_REG_DXEMECC1TH 0x1C0 ++#define PME_REG_DXEMECC1EC 0x1C4 ++#define PME_REG_STNIB 0x200 ++#define PME_REG_STNIS 0x204 ++#define PME_REG_STNTH1 0x208 ++#define PME_REG_STNTH2 0x20C ++#define PME_REG_STNTHV 0x210 ++#define PME_REG_STNTHS 0x214 ++#define PME_REG_STNCH 0x218 ++#define PME_REG_SWDB 0x21C ++#define PME_REG_KVLTS 0x220 ++#define PME_REG_KEC 0x224 ++#define PME_REG_STNPM 0x280 ++#define PME_REG_STNS1M 0x284 ++#define PME_REG_DRCIC 0x288 ++#define PME_REG_DRCMC 0x28C ++#define PME_REG_STNPMR 0x290 ++#define PME_REG_PDSRBAH 0x2A0 ++#define PME_REG_PDSRBAL 0x2A4 ++#define PME_REG_DMCR 0x2A8 ++#define PME_REG_DEC0 0x2AC ++#define PME_REG_DEC1 0x2B0 ++#define PME_REG_DLC 0x2C0 ++#define PME_REG_STNDSR 0x300 ++#define PME_REG_STNESR 0x304 ++#define PME_REG_STNS1R 0x308 ++#define PME_REG_STNOB 0x30C ++#define PME_REG_SCBARH 0x310 ++#define PME_REG_SCBARL 0x314 ++#define PME_REG_SMCR 0x318 ++#define PME_REG_SREC 0x320 ++#define PME_REG_ESRP 0x328 ++#define PME_REG_SRRV0 0x338 ++#define PME_REG_SRRV1 0x33C ++#define PME_REG_SRRV2 0x340 ++#define PME_REG_SRRV3 0x344 ++#define PME_REG_SRRV4 0x348 ++#define PME_REG_SRRV5 0x34C ++#define PME_REG_SRRV6 0x350 ++#define PME_REG_SRRV7 0x354 ++#define PME_REG_SRRFI 0x358 ++#define PME_REG_SRRI 0x360 ++#define PME_REG_SRRR 0x364 ++#define PME_REG_SRRWC 0x368 ++#define PME_REG_SFRCC 0x36C ++#define PME_REG_SEC1 0x370 ++#define PME_REG_SEC2 0x374 ++#define PME_REG_SEC3 0x378 ++#define PME_REG_MIA_BYC 0x380 ++#define PME_REG_MIA_BLC 0x384 ++#define PME_REG_MIA_CE 0x388 ++#define PME_REG_MIA_CR 0x390 ++#define PME_REG_PPIDMR0 0x800 ++#define PME_REG_PPIDMR1 0x804 ++#define PME_REG_PPIDMR2 0x808 ++#define PME_REG_PPIDMR3 0x80C ++#define PME_REG_PPIDMR4 0x810 ++#define PME_REG_PPIDMR5 0x814 ++#define PME_REG_PPIDMR6 0x818 ++#define PME_REG_PPIDMR7 0x81C ++#define PME_REG_PPIDMR8 0x820 ++#define PME_REG_PPIDMR9 0x824 ++#define PME_REG_PPIDMR10 0x828 ++#define PME_REG_PPIDMR11 0x82C ++#define PME_REG_PPIDMR12 0x830 ++#define PME_REG_PPIDMR13 0x834 ++#define PME_REG_PPIDMR14 0x838 ++#define PME_REG_PPIDMR15 0x83C ++#define PME_REG_PPIDMR16 0x840 ++#define PME_REG_PPIDMR17 0x844 ++#define PME_REG_PPIDMR18 0x848 ++#define PME_REG_PPIDMR19 0x84C ++#define PME_REG_PPIDMR20 0x850 ++#define PME_REG_PPIDMR21 0x854 ++#define PME_REG_PPIDMR22 0x858 ++#define PME_REG_PPIDMR23 0x85C ++#define PME_REG_PPIDMR24 0x860 ++#define PME_REG_PPIDMR25 0x864 ++#define PME_REG_PPIDMR26 0x868 ++#define PME_REG_PPIDMR27 0x86C ++#define PME_REG_PPIDMR28 0x870 ++#define PME_REG_PPIDMR29 0x874 ++#define PME_REG_PPIDMR30 0x878 ++#define PME_REG_PPIDMR31 0x87C ++#define PME_REG_SRCIDR 0xA00 ++#define PME_REG_LIODNR 0xA0C ++#define PME_REG_PM_IP_REV1 0xBF8 ++#define PME_REG_PM_IP_REV2 0xBFC ++ ++#endif /* REGS_H */ +diff --git a/drivers/staging/fsl_pme2/pme2_sample_db.c b/drivers/staging/fsl_pme2/pme2_sample_db.c +new file mode 100644 +index 0000000..75fef4e +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_sample_db.c +@@ -0,0 +1,453 @@ ++/* Copyright 2009-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "pme2_test.h" ++ ++static u8 pme_db[] = { ++ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, ++ 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* Rev 2.2 */ ++/* 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, ++ 0x48, 0x41, 0x40, 0x20, 0x00, 0x11, */ ++/* Rev 2.1 */ ++ 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, ++ 0x90, 0x41, 0x40, 0x20, 0x00, 0x11, ++/* Rev 2.0 */ ++/* 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, ++ 0x20, 0x41, 0x40, 0x20, 0x00, 0x11, */ ++ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* Rev 2.0 */ ++/* 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, ++ 0x48, 0x41, 0xff, 0x81, 0x00, 0x00, */ ++/* Rev 2.1 */ ++ 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, ++ 0x90, 0x41, 0xff, 0x81, 0x00, 0x00, ++/* Rev 2.0 */ ++/* 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, ++ 0x20, 0x41, 0xff, 0x81, 0x00, 0x00, */ ++ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, ++ 0x01, 0xff, 0x80, 0x00, 0x41, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, ++ 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x06, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, ++ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, ++ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, ++ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, ++ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, ++ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, ++ 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, ++ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, ++ 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, ++ 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, ++ 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, ++ 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, ++ 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x41, 0x42, 0x43, ++ 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, ++ 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, ++ 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, ++ 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, ++ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, ++ 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, ++ 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, ++ 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, ++ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, ++ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, ++ 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, ++ 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, ++ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, ++ 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, ++ 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, ++ 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, ++ 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, ++ 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, ++ 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, ++ 0xfc, 0xfd, 0xfe, 0xff ++}; ++ ++static u8 db_read[] = { ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, ++ 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* Rev 2.2 */ ++/* 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, ++ 0x48, 0x41 */ ++/* Rev 2.1 */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, ++ 0x90, 0x41 ++/* Rev 2.0 */ ++/* 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, ++ 0x20, 0x41 */ ++}; ++ ++static u8 db_read_expected_result[] = { ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, ++ 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* Rev 2.2 */ ++/* 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, ++ 0x48, 0x41, 0x40, 0x20, 0x00, 0x11*/ ++/* Rev 2.1 */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, ++ 0x90, 0x41, 0x40, 0x20, 0x00, 0x11 ++/* Rev 2.0 */ ++/* 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, ++ 0x20, 0x41, 0x40, 0x20, 0x00, 0x11*/ ++}; ++ ++struct pmtcc_ctx { ++ struct pme_ctx base_ctx; ++ struct qm_fd result_fd; ++ struct completion done; ++ u8 ern; ++}; ++ ++static void pmtcc_cb(struct pme_ctx *ctx, const struct qm_fd *fd, ++ struct pme_ctx_token *ctx_token) ++{ ++ struct pmtcc_ctx *my_ctx = (struct pmtcc_ctx *)ctx; ++ memcpy(&my_ctx->result_fd, fd, sizeof(*fd)); ++ complete(&my_ctx->done); ++} ++ ++static void pmtcc_ern_cb(struct pme_ctx *ctx, const struct qm_mr_entry *mr, ++ struct pme_ctx_token *ctx_token) ++{ ++ struct pmtcc_ctx *my_ctx = (struct pmtcc_ctx *)ctx; ++ my_ctx->result_fd = mr->ern.fd; ++ my_ctx->ern = 1; ++ complete(&my_ctx->done); ++} ++ ++#define FIRST_PMTCC 56 ++int pme2_clear_sample_db(void) ++{ ++ struct pmtcc_ctx ctx = { ++ .base_ctx.cb = pmtcc_cb, ++ .base_ctx.ern_cb = pmtcc_ern_cb, ++ .ern = 0 ++ }; ++ struct qm_fd fd; ++ int ret = 0; ++ enum pme_status status; ++ struct pme_ctx_token token; ++ void *mem; ++ struct cpumask backup_mask = current->cpus_allowed; ++ struct cpumask new_mask = *qman_affine_cpus(); ++ ++ cpumask_and(&new_mask, &new_mask, bman_affine_cpus()); ++ ret = set_cpus_allowed_ptr(current, &new_mask); ++ if (ret) { ++ pr_info("cleanr_sample_db: can't set cpumask\n"); ++ goto _clear_0; ++ } ++ init_completion(&ctx.done); ++ ret = pme_ctx_init(&ctx.base_ctx, ++ PME_CTX_FLAG_EXCLUSIVE | ++ PME_CTX_FLAG_PMTCC | ++ PME_CTX_FLAG_LOCAL, 0, 4, 4, 0, NULL); ++ if (ret) { ++ pr_err("clear_sample_db: can't init ctx\n"); ++ goto _clear_1; ++ } ++ ++ /* enable the context */ ++ ret = pme_ctx_enable(&ctx.base_ctx); ++ if (ret) { ++ pr_err("clear_sample_db: can't enable ctx\n"); ++ goto _clear_2; ++ } ++ ++ /* Write the database */ ++ memset(&fd, 0, sizeof(struct qm_fd)); ++ mem = kmalloc(FIRST_PMTCC, GFP_KERNEL); ++ if (!mem) ++ goto _clear_3; ++ memcpy(mem, pme_db, FIRST_PMTCC); ++ ++ fd.length20 = FIRST_PMTCC; ++ qm_fd_addr_set64(&fd, pme_map(mem)); ++ ++ ret = pme_ctx_pmtcc(&ctx.base_ctx, PME_CTX_OP_WAIT, &fd, &token); ++ if (ret == -ENODEV) { ++ pr_err("clear_sample_db: not the control plane, bailing\n"); ++ goto _clear_4; ++ } ++ if (ret) { ++ pr_err("clear_sample_db: error with pmtcc\n"); ++ goto _clear_4; ++ } ++ wait_for_completion(&ctx.done); ++ if (ctx.ern) { ++ pr_err("clear_sample_db: Rx ERN from pmtcc\n"); ++ goto _clear_4; ++ } ++ status = pme_fd_res_status(&ctx.result_fd); ++ if (status) { ++ pr_info("clear_sample_db: PMTCC write status failed %d\n", ++ status); ++ goto _clear_4; ++ } ++_clear_4: ++ kfree(mem); ++_clear_3: ++ /* Disable */ ++ ret = pme_ctx_disable(&ctx.base_ctx, ++ PME_CTX_OP_WAIT | PME_CTX_OP_WAIT_INT, NULL); ++_clear_2: ++ pme_ctx_finish(&ctx.base_ctx); ++_clear_1: ++ ret = set_cpus_allowed_ptr(current, &backup_mask); ++ if (ret) ++ pr_info("clear_sample_db: can't restore cpumask"); ++_clear_0: ++ if (!ret) ++ pr_info("clear_sample_db: Done\n"); ++ else ++ pr_info("clear_sample_db: Error 0x%x\n", ret); ++ return ret; ++ ++} ++ ++int pme2_sample_db(void) ++{ ++ struct pmtcc_ctx ctx = { ++ .base_ctx.cb = pmtcc_cb, ++ .base_ctx.ern_cb = pmtcc_ern_cb, ++ .ern = 0 ++ }; ++ struct qm_fd fd; ++ struct qm_sg_entry *sg_table = NULL; ++ int ret = 0; ++ enum pme_status status; ++ struct pme_ctx_token token; ++ void *mem = NULL, *mem_result = NULL; ++ u32 pme_rev; ++ struct cpumask backup_mask = current->cpus_allowed; ++ struct cpumask new_mask = *qman_affine_cpus(); ++ ++ cpumask_and(&new_mask, &new_mask, bman_affine_cpus()); ++ ret = set_cpus_allowed_ptr(current, &new_mask); ++ if (ret) { ++ pr_info("sample_db: can't set cpumask\n"); ++ goto _finish_0; ++ } ++ ret = pme_attr_get(pme_attr_rev1, &pme_rev); ++ if (ret) { ++ pr_err("sample_db: can't read pme revision %d\n", ret); ++ goto _finish_1; ++ } ++ /* If Rev 2.0, Rev 2.2...update database */ ++ switch (pme_rev & 0x0000FFFF) { ++ case 0x00000200: ++ pr_info("sample_db: db for pme ver 2.0\n"); ++ pme_db[133] = 0x01; ++ pme_db[134] = 0x20; ++ pme_db[161] = 0x01; ++ pme_db[162] = 0x20; ++ db_read[21] = 0x01; ++ db_read[22] = 0x20; ++ db_read_expected_result[21] = 0x01; ++ db_read_expected_result[22] = 0x20; ++ break; ++ case 0x00000201: ++ pr_info("sample_db: db for pme ver 2.1\n"); ++ break; ++ case 0x00000202: ++ pr_info("sample_db: db for pme ver 2.2\n"); ++ pme_db[134] = 0x48; ++ pme_db[162] = 0x48; ++ db_read[22] = 0x48; ++ db_read_expected_result[22] = 0x48; ++ break; ++ default: ++ pr_err("sample_db: Unknown pme hw ver 0x%x\n", ++ pme_rev & 0x0000FFFF); ++ ret = -ENODEV; ++ goto _finish_1; ++ } ++ init_completion(&ctx.done); ++ ret = pme_ctx_init(&ctx.base_ctx, ++ PME_CTX_FLAG_EXCLUSIVE | ++ PME_CTX_FLAG_PMTCC | ++ PME_CTX_FLAG_LOCAL, 0, 4, 4, 0, NULL); ++ if (ret) { ++ pr_err("sample_db: can't init ctx\n"); ++ goto _finish_1; ++ } ++ ++ /* enable the context */ ++ ret = pme_ctx_enable(&ctx.base_ctx); ++ if (ret) { ++ pr_err("sample_db: can't enable ctx\n"); ++ goto _finish_2; ++ } ++ ++ /* Write the database */ ++ memset(&fd, 0, sizeof(struct qm_fd)); ++ mem = kmalloc(sizeof(pme_db), GFP_KERNEL); ++ if (!mem) ++ goto _finish_3; ++ memcpy(mem, pme_db, sizeof(pme_db)); ++ ++ fd.length20 = sizeof(pme_db); ++ qm_fd_addr_set64(&fd, pme_map(mem)); ++ ++ ret = pme_ctx_pmtcc(&ctx.base_ctx, PME_CTX_OP_WAIT, &fd, &token); ++ if (ret == -ENODEV) { ++ pr_err("sample_db: not the control plane, bailing\n"); ++ goto _finish_4; ++ } ++ if (ret) { ++ pr_err("sample_db: error with pmtcc\n"); ++ goto _finish_4; ++ } ++ wait_for_completion(&ctx.done); ++ if (ctx.ern) { ++ pr_err("sample_db: Rx ERN from pmtcc\n"); ++ goto _finish_4; ++ } ++ status = pme_fd_res_status(&ctx.result_fd); ++ if (status) { ++ pr_info("sample_db: PMTCC write status failed %d\n", status); ++ goto _finish_4; ++ } ++ kfree(mem); ++ mem = NULL; ++ /* Read back the database */ ++ init_completion(&ctx.done); ++ memset(&fd, 0, sizeof(struct qm_fd)); ++ sg_table = kzalloc(2 * sizeof(*sg_table), GFP_KERNEL | GFP_DMA); ++ mem_result = kmalloc(28, GFP_KERNEL); ++ mem = kmalloc(sizeof(db_read), GFP_KERNEL); ++ if (!sg_table || !mem || !mem_result) { ++ pr_err("sample_db: out of memory\n"); ++ ret = -ENOMEM; ++ goto _finish_4; ++ } ++ memcpy(mem, db_read, sizeof(db_read)); ++ qm_sg_entry_set64(&sg_table[0], pme_map(mem_result)); ++ sg_table[0].length = 28; ++ qm_sg_entry_set64(&sg_table[1], pme_map(mem)); ++ sg_table[1].length = sizeof(db_read); ++ sg_table[1].final = 1; ++ fd.format = qm_fd_compound; ++ qm_fd_addr_set64(&fd, pme_map(sg_table)); ++ ret = pme_ctx_pmtcc(&ctx.base_ctx, PME_CTX_OP_WAIT, &fd, &token); ++ if (ret) { ++ pr_err("sample_db: error with pmtcc\n"); ++ goto _finish_4; ++ } ++ wait_for_completion(&ctx.done); ++ if (ctx.ern) { ++ ret = -EINVAL; ++ pr_err("sample_db: Rx ERN from pmtcc\n"); ++ goto _finish_4; ++ } ++ status = pme_fd_res_status(&ctx.result_fd); ++ if (status) { ++ ret = -EINVAL; ++ pr_err("sample_db: PMTCC read status failed %d\n", status); ++ goto _finish_4; ++ } ++ if (pme_fd_res_flags(&ctx.result_fd) & PME_STATUS_UNRELIABLE) { ++ pr_err("sample_db: flags result set %x\n", ++ pme_fd_res_flags(&ctx.result_fd)); ++ ret = -EINVAL; ++ goto _finish_4; ++ } ++ if (memcmp(db_read_expected_result, mem_result, 28) != 0) { ++ pr_err("sample_db: DB read result not expected\n"); ++ pr_err("Expected\n"); ++ hexdump(db_read_expected_result, ++ sizeof(db_read_expected_result)); ++ pr_info("Received\n"); ++ hexdump(mem_result, 28); ++ ret = -EINVAL; ++ } ++_finish_4: ++ kfree(mem_result); ++ kfree(sg_table); ++ kfree(mem); ++_finish_3: ++ /* Disable */ ++ ret = pme_ctx_disable(&ctx.base_ctx, ++ PME_CTX_OP_WAIT | PME_CTX_OP_WAIT_INT, NULL); ++_finish_2: ++ pme_ctx_finish(&ctx.base_ctx); ++_finish_1: ++ if (ret) ++ set_cpus_allowed_ptr(current, &backup_mask); ++ else { ++ ret = set_cpus_allowed_ptr(current, &backup_mask); ++ if (ret) ++ pr_info("sample_db: can't restore cpumask"); ++ } ++ ++_finish_0: ++ if (!ret) ++ pr_info("pme: sample DB initialised\n"); ++ else ++ pr_info("pme: Error during sample DB 0x%x\n", ret); ++ return ret; ++} +diff --git a/drivers/staging/fsl_pme2/pme2_scan.c b/drivers/staging/fsl_pme2/pme2_scan.c +new file mode 100644 +index 0000000..f00081e +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_scan.c +@@ -0,0 +1,1123 @@ ++/* Copyright 2009-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "pme2_private.h" ++#include ++#include ++#include ++#include ++ ++#define WAIT_AND_INTERRUPTABLE (PME_CTX_OP_WAIT|PME_CTX_OP_WAIT_INT) ++#define INPUT_FRM 1 ++#define OUTPUT_FRM 0 ++/* Private structure that is allocated for each open that is done on the ++ * pme_scan device. */ ++struct scan_session { ++ /* The ctx that is needed to communicate with the pme high level */ ++ struct pme_ctx ctx; ++ /* Locks completed_commands */ ++ spinlock_t set_subset_lock; ++ __u8 set; ++ __u16 subset; ++ /* For asynchronous processing */ ++ wait_queue_head_t waiting_for_completion; ++ struct list_head completed_commands; ++ /* Locks completed_commands */ ++ spinlock_t completed_commands_lock; ++ u32 completed_count; ++}; ++ ++/* Command Token for scan operations. One of these is created for every ++ * operation on a context. When the context operation is complete cleanup ++ * is done */ ++struct cmd_token { ++ /* pme high level token */ ++ struct pme_ctx_token hl_token; ++ /* The kernels copy of the user op structure */ ++ struct pme_scan_cmd kernel_op; ++ /* Set to non zero if this is a synchronous request */ ++ u8 synchronous; ++ /* data */ ++ struct qm_fd tx_fd; ++ struct qm_sg_entry tx_comp[2]; ++ struct qm_fd rx_fd; ++ void *tx_data; ++ size_t tx_size; ++ void *rx_data; ++ size_t rx_size; ++ /* For blocking requests, we need a wait point and condition */ ++ wait_queue_head_t *queue; ++ /* List management for completed async requests */ ++ struct list_head completed_list; ++ u8 done; ++ u8 ern; ++}; ++ ++struct ctrl_op { ++ struct pme_ctx_ctrl_token ctx_ctr; ++ struct completion cb_done; ++ enum pme_status cmd_status; ++ u8 res_flag; ++ u8 ern; ++}; ++ ++#ifdef CONFIG_COMPAT ++static void compat_to_scan_cmd(struct pme_scan_cmd *dst, ++ struct compat_pme_scan_cmd *src) ++{ ++ dst->flags = src->flags; ++ dst->opaque = compat_ptr(src->opaque); ++ dst->input.data = compat_ptr(src->input.data); ++ dst->input.size = src->input.size; ++ dst->output.data = compat_ptr(src->output.data); ++ dst->output.size = src->output.size; ++} ++ ++static void scan_result_to_compat(struct compat_pme_scan_result *dst, ++ struct pme_scan_result *src) ++{ ++ dst->flags = src->flags; ++ dst->opaque = ptr_to_compat(src->opaque); ++ dst->status = src->status; ++ dst->output.data = ptr_to_compat(src->output.data); ++ dst->output.size = src->output.size; ++} ++ ++static void compat_to_scan_result(struct pme_scan_result *dst, ++ struct compat_pme_scan_result *src) ++{ ++ dst->flags = src->flags; ++ dst->opaque = compat_ptr(src->opaque); ++ dst->status = src->status; ++ dst->output.data = compat_ptr(src->output.data); ++ dst->output.size = src->output.size; ++} ++#endif ++ ++static void ctrl_cb(struct pme_ctx *ctx, const struct qm_fd *fd, ++ struct pme_ctx_ctrl_token *token) ++{ ++ struct ctrl_op *ctrl = (struct ctrl_op *)token; ++ ctrl->cmd_status = pme_fd_res_status(fd); ++ ctrl->res_flag = pme_fd_res_flags(fd) & PME_STATUS_UNRELIABLE; ++ complete(&ctrl->cb_done); ++} ++ ++static void ctrl_ern_cb(struct pme_ctx *ctx, const struct qm_mr_entry *mr, ++ struct pme_ctx_ctrl_token *token) ++{ ++ struct ctrl_op *ctrl = (struct ctrl_op *)token; ++ ctrl->ern = 1; ++ complete(&ctrl->cb_done); ++} ++ ++static inline int scan_data_empty(struct scan_session *session) ++{ ++ return list_empty(&session->completed_commands); ++} ++ ++/* Cleanup for the execute_cmd method */ ++static inline void cleanup_token(struct cmd_token *token_p) ++{ ++ kfree(token_p->tx_data); ++ kfree(token_p->rx_data); ++ return; ++} ++ ++/* Callback for scan operations */ ++static void scan_cb(struct pme_ctx *ctx, const struct qm_fd *fd, ++ struct pme_ctx_token *ctx_token) ++{ ++ struct cmd_token *token = (struct cmd_token *)ctx_token; ++ struct scan_session *session = (struct scan_session *)ctx; ++ ++ token->rx_fd = *fd; ++ /* If this is a asynchronous command, queue the token */ ++ if (!token->synchronous) { ++ spin_lock(&session->completed_commands_lock); ++ list_add_tail(&token->completed_list, ++ &session->completed_commands); ++ session->completed_count++; ++ spin_unlock(&session->completed_commands_lock); ++ } ++ /* Wake up the thread that's waiting for us */ ++ token->done = 1; ++ wake_up(token->queue); ++ return; ++} ++ ++static void scan_ern_cb(struct pme_ctx *ctx, const struct qm_mr_entry *mr, ++ struct pme_ctx_token *ctx_token) ++{ ++ struct cmd_token *token = (struct cmd_token *)ctx_token; ++ struct scan_session *session = (struct scan_session *)ctx; ++ ++ token->ern = 1; ++ token->rx_fd = mr->ern.fd; ++ /* If this is a asynchronous command, queue the token */ ++ if (!token->synchronous) { ++ spin_lock(&session->completed_commands_lock); ++ list_add_tail(&token->completed_list, ++ &session->completed_commands); ++ session->completed_count++; ++ spin_unlock(&session->completed_commands_lock); ++ } ++ /* Wake up the thread that's waiting for us */ ++ token->done = 1; ++ wake_up(token->queue); ++ return; ++} ++ ++static int process_completed_token(struct file *fp, struct cmd_token *token_p, ++ struct pme_scan_result *scan_result) ++{ ++ int ret = 0; ++ u32 src_sz, dst_sz; ++ ++ memset(scan_result, 0, sizeof(struct pme_scan_result)); ++ if (token_p->ern) { ++ ret = -EIO; ++ goto done; ++ } ++ scan_result->output.data = token_p->kernel_op.output.data; ++ ++ if (token_p->rx_fd.format == qm_fd_compound) { ++ /* Need to copy output */ ++ src_sz = token_p->tx_comp[OUTPUT_FRM].length; ++ dst_sz = token_p->kernel_op.output.size; ++ scan_result->output.size = min(dst_sz, src_sz); ++ /* Doesn't make sense we generated more than available space ++ * should have got truncation. ++ */ ++ BUG_ON(dst_sz < src_sz); ++ if (copy_to_user(scan_result->output.data, token_p->rx_data, ++ scan_result->output.size)) { ++ pr_err("Error copying to user data\n"); ++ cleanup_token(token_p); ++ return -EFAULT; ++ } ++ } else if (token_p->rx_fd.format == qm_fd_sg_big) ++ scan_result->output.size = 0; ++ else ++ pr_err("pme2_scan: unexpected frame type received\n"); ++ ++ scan_result->flags |= pme_fd_res_flags(&token_p->rx_fd); ++ scan_result->status |= pme_fd_res_status(&token_p->rx_fd); ++done: ++ scan_result->opaque = token_p->kernel_op.opaque; ++ cleanup_token(token_p); ++ return ret; ++} ++ ++static int getscan_cmd(struct file *fp, struct scan_session *session, ++ struct pme_scan_params __user *user_scan_params) ++{ ++ int ret = 0; ++ struct pme_flow params; ++ struct pme_scan_params local_scan_params; ++ struct ctrl_op ctx_ctrl = { ++ .ctx_ctr.cb = ctrl_cb, ++ .ctx_ctr.ern_cb = ctrl_ern_cb, ++ .cmd_status = 0, ++ .res_flag = 0, ++ .ern = 0 ++ }; ++ init_completion(&ctx_ctrl.cb_done); ++ ++ memset(&local_scan_params, 0, sizeof(local_scan_params)); ++ ++ /* must be enabled */ ++ if (pme_ctx_is_disabled(&session->ctx)) { ++ pr_err("pme2_scan: ctx is disabled\n"); ++ ret = -EINVAL; ++ goto done; ++ } ++ ret = pme_ctx_ctrl_read_flow(&session->ctx, WAIT_AND_INTERRUPTABLE, ++ ¶ms, &ctx_ctrl.ctx_ctr); ++ if (ret) { ++ PMEPRINFO("read flow error %d\n", ret); ++ goto done; ++ } ++ wait_for_completion(&ctx_ctrl.cb_done); ++ ++ if (ctx_ctrl.ern || ctx_ctrl.cmd_status || ctx_ctrl.res_flag) { ++ PMEPRINFO("read flow error %d\n", ctx_ctrl.cmd_status); ++ ret = -EFAULT; ++ goto done; ++ } ++ local_scan_params.residue.enable = params.ren; ++ local_scan_params.residue.length = params.rlen; ++ local_scan_params.sre.sessionid = params.sessionid; ++ local_scan_params.sre.verbose = params.srvm; ++ local_scan_params.sre.esee = params.esee; ++ local_scan_params.dxe.clim = params.clim; ++ local_scan_params.dxe.mlim = params.mlim; ++ spin_lock(&session->set_subset_lock); ++ local_scan_params.pattern.set = session->set; ++ local_scan_params.pattern.subset = session->subset; ++ spin_unlock(&session->set_subset_lock); ++ ++ if (copy_to_user(user_scan_params, &local_scan_params, ++ sizeof(local_scan_params))) { ++ pr_err("Error copying to user data\n"); ++ ret = -EFAULT; ++ } ++done: ++ return ret; ++} ++ ++static int setscan_cmd(struct file *fp, struct scan_session *session, ++ struct pme_scan_params __user *user_params) ++{ ++ int ret = 0; ++ u32 flag = WAIT_AND_INTERRUPTABLE; ++ struct ctrl_op ctx_ctrl = { ++ .ctx_ctr.cb = ctrl_cb, ++ .ctx_ctr.ern_cb = ctrl_ern_cb, ++ .cmd_status = 0, ++ .res_flag = 0, ++ .ern = 0 ++ }; ++ struct pme_flow params; ++ struct pme_scan_params local_params; ++ ++ pme_sw_flow_init(¶ms); ++ init_completion(&ctx_ctrl.cb_done); ++ if (copy_from_user(&local_params, user_params, sizeof(local_params))) ++ return -EFAULT; ++ ++ /* must be enabled */ ++ if (pme_ctx_is_disabled(&session->ctx)) { ++ ret = -EINVAL; ++ goto done; ++ } ++ /* Only send a flw_ctx_w if PME_SCAN_PARAMS_{RESIDUE, SRE or DXE} ++ * is being done */ ++ if (local_params.flags == PME_SCAN_PARAMS_PATTERN) ++ goto set_subset; ++ if (local_params.flags & PME_SCAN_PARAMS_RESIDUE) ++ flag |= PME_CMD_FCW_RES; ++ if (local_params.flags & PME_SCAN_PARAMS_SRE) ++ flag |= PME_CMD_FCW_SRE; ++ if (local_params.flags & PME_SCAN_PARAMS_DXE) ++ flag |= PME_CMD_FCW_DXE; ++ params.ren = local_params.residue.enable; ++ params.sessionid = local_params.sre.sessionid; ++ params.srvm = local_params.sre.verbose; ++ params.esee = local_params.sre.esee; ++ params.clim = local_params.dxe.clim; ++ params.mlim = local_params.dxe.mlim; ++ ++ ret = pme_ctx_ctrl_update_flow(&session->ctx, flag, ¶ms, ++ &ctx_ctrl.ctx_ctr); ++ if (ret) { ++ PMEPRINFO("update flow error %d\n", ret); ++ goto done; ++ } ++ wait_for_completion(&ctx_ctrl.cb_done); ++ if (ctx_ctrl.ern || ctx_ctrl.cmd_status || ctx_ctrl.res_flag) { ++ PMEPRINFO("update flow err %d\n", ctx_ctrl.cmd_status); ++ ret = -EFAULT; ++ goto done; ++ } ++ ++set_subset: ++ if (local_params.flags & PME_SCAN_PARAMS_PATTERN) { ++ spin_lock(&session->set_subset_lock); ++ session->set = local_params.pattern.set; ++ session->subset = local_params.pattern.subset; ++ spin_unlock(&session->set_subset_lock); ++ goto done; ++ } ++done: ++ return ret; ++} ++ ++static int resetseq_cmd(struct file *fp, struct scan_session *session) ++{ ++ int ret = 0; ++ struct pme_flow params; ++ struct ctrl_op ctx_ctrl = { ++ .ctx_ctr.cb = ctrl_cb, ++ .ctx_ctr.ern_cb = ctrl_ern_cb, ++ .cmd_status = 0, ++ .res_flag = 0, ++ .ern = 0 ++ }; ++ init_completion(&ctx_ctrl.cb_done); ++ pme_sw_flow_init(¶ms); ++ ++ /* must be enabled */ ++ if (pme_ctx_is_disabled(&session->ctx)) { ++ pr_err("pme2_scan: ctx is disabled\n"); ++ ret = -EINVAL; ++ goto done; ++ } ++ pme_flow_seqnum_set64(¶ms, 0); ++ params.sos = 1; ++ ++ ret = pme_ctx_ctrl_update_flow(&session->ctx, PME_CMD_FCW_SEQ, ¶ms, ++ &ctx_ctrl.ctx_ctr); ++ if (ret) { ++ pr_err("pme2_scan: update flow error %d\n", ret); ++ return ret; ++ } ++ wait_for_completion(&ctx_ctrl.cb_done); ++ if (ctx_ctrl.ern || ctx_ctrl.cmd_status || ctx_ctrl.res_flag) { ++ PMEPRINFO("update flow err %d\n", ctx_ctrl.cmd_status); ++ ret = -EFAULT; ++ } ++done: ++ return ret; ++} ++ ++static int resetresidue_cmd(struct file *fp, struct scan_session *session) ++{ ++ int ret = 0; ++ struct pme_flow params; ++ struct ctrl_op ctx_ctrl = { ++ .ctx_ctr.cb = ctrl_cb, ++ .ctx_ctr.ern_cb = ctrl_ern_cb, ++ .cmd_status = 0, ++ .res_flag = 0, ++ .ern = 0 ++ }; ++ ++ init_completion(&ctx_ctrl.cb_done); ++ pme_sw_flow_init(¶ms); ++ /* must be enabled */ ++ if (pme_ctx_is_disabled(&session->ctx)) { ++ pr_err("pme2_scan: ctx is disabled\n"); ++ ret = -EINVAL; ++ goto done; ++ } ++ params.rlen = 0; ++ ret = pme_ctx_ctrl_update_flow(&session->ctx, ++ WAIT_AND_INTERRUPTABLE | PME_CTX_OP_RESETRESLEN, ++ ¶ms, &ctx_ctrl.ctx_ctr); ++ if (ret) ++ pr_info("pme2_scan: update flow error %d\n", ret); ++ wait_for_completion(&ctx_ctrl.cb_done); ++ if (ctx_ctrl.ern || ctx_ctrl.cmd_status || ctx_ctrl.res_flag) { ++ PMEPRINFO("update flow err %d\n", ctx_ctrl.cmd_status); ++ ret = -EFAULT; ++ } ++done: ++ return ret; ++} ++ ++static int process_scan_cmd( ++ struct file *fp, ++ struct scan_session *session, ++ struct pme_scan_cmd *user_cmd, ++ struct pme_scan_result *user_ret, ++ u8 synchronous) ++{ ++ int ret = 0; ++ struct cmd_token local_token; ++ struct cmd_token *token_p = NULL; ++ DECLARE_WAIT_QUEUE_HEAD(local_waitqueue); ++ u8 scan_flags = 0; ++ ++ BUG_ON(synchronous && !user_ret); ++ ++ /* If synchronous, use a local token (from the stack) ++ * If asynchronous, allocate a token to use */ ++ if (synchronous) ++ token_p = &local_token; ++ else { ++ token_p = kmalloc(sizeof(*token_p), GFP_KERNEL); ++ if (!token_p) ++ return -ENOMEM; ++ } ++ memset(token_p, 0, sizeof(*token_p)); ++ /* Copy the command to kernel space */ ++ memcpy(&token_p->kernel_op, user_cmd, sizeof(struct pme_scan_cmd)); ++ ++#ifdef CONFIG_FSL_PME_BUG_4K_SCAN_REV_2_1_4 ++ if (session->ctx.max_scan_size) { ++ if (token_p->kernel_op.input.size > ++ session->ctx.max_scan_size) { ++ if (!synchronous) ++ kfree(token_p); ++ return -EINVAL; ++ } ++ } ++#endif ++ ++ /* Copy the input */ ++ token_p->synchronous = synchronous; ++ token_p->tx_size = token_p->kernel_op.input.size; ++ token_p->tx_data = kmalloc(token_p->kernel_op.input.size, GFP_KERNEL); ++ if (!token_p->tx_data) { ++ pr_err("pme2_scan: Err alloc %zd byte", token_p->tx_size); ++ cleanup_token(token_p); ++ return -ENOMEM; ++ } ++ if (copy_from_user(token_p->tx_data, ++ token_p->kernel_op.input.data, ++ token_p->kernel_op.input.size)) { ++ pr_err("Error copying contigous user data\n"); ++ cleanup_token(token_p); ++ return -EFAULT; ++ } ++ /* Setup input frame */ ++ token_p->tx_comp[INPUT_FRM].final = 1; ++ token_p->tx_comp[INPUT_FRM].length = token_p->tx_size; ++ qm_sg_entry_set64(&token_p->tx_comp[INPUT_FRM], ++ pme_map(token_p->tx_data)); ++ /* setup output frame, if output is expected */ ++ if (token_p->kernel_op.output.size) { ++ token_p->rx_size = token_p->kernel_op.output.size; ++ PMEPRINFO("pme2_scan: expect output %d\n", token_p->rx_size); ++ token_p->rx_data = kmalloc(token_p->rx_size, GFP_KERNEL); ++ if (!token_p->rx_data) { ++ pr_err("pme2_scan: Err alloc %zd byte", ++ token_p->rx_size); ++ cleanup_token(token_p); ++ return -ENOMEM; ++ } ++ /* Setup output frame */ ++ token_p->tx_comp[OUTPUT_FRM].length = token_p->rx_size; ++ qm_sg_entry_set64(&token_p->tx_comp[OUTPUT_FRM], ++ pme_map(token_p->rx_data)); ++ token_p->tx_fd.format = qm_fd_compound; ++ /* Build compound frame */ ++ qm_fd_addr_set64(&token_p->tx_fd, ++ pme_map(token_p->tx_comp)); ++ } else { ++ token_p->tx_fd.format = qm_fd_sg_big; ++ /* Build sg frame */ ++ qm_fd_addr_set64(&token_p->tx_fd, ++ pme_map(&token_p->tx_comp[INPUT_FRM])); ++ token_p->tx_fd.length29 = token_p->tx_size; ++ } ++ ++ /* use the local wait queue if synchronous, the shared ++ * queue if asynchronous */ ++ if (synchronous) ++ token_p->queue = &local_waitqueue; ++ else ++ token_p->queue = &session->waiting_for_completion; ++ token_p->done = 0; ++ ++ if (token_p->kernel_op.flags & PME_SCAN_CMD_STARTRESET) ++ scan_flags |= PME_CMD_SCAN_SR; ++ if (token_p->kernel_op.flags & PME_SCAN_CMD_END) ++ scan_flags |= PME_CMD_SCAN_E; ++ ret = pme_ctx_scan(&session->ctx, WAIT_AND_INTERRUPTABLE, ++ &token_p->tx_fd, ++ PME_SCAN_ARGS(scan_flags, session->set, session->subset), ++ &token_p->hl_token); ++ if (unlikely(ret)) { ++ cleanup_token(token_p); ++ return ret; ++ } ++ ++ if (!synchronous) ++ /* Don't wait. The command is away */ ++ return 0; ++ ++ PMEPRINFO("Wait for completion\n"); ++ /* Wait for the command to complete */ ++ /* TODO: Should this be wait_event_interruptible ? ++ * If so, will need logic to indicate */ ++ wait_event(*token_p->queue, token_p->done == 1); ++ return process_completed_token(fp, token_p, user_ret); ++} ++ ++/** ++ * fsl_pme2_scan_open - open the driver ++ * ++ * Open the driver and prepare for requests. ++ * ++ * Every time an application opens the driver, we create a scan_session object ++ * for that file handle. ++ */ ++static int fsl_pme2_scan_open(struct inode *node, struct file *fp) ++{ ++ int ret; ++ struct scan_session *session; ++ struct pme_flow flow; ++ struct ctrl_op ctx_ctrl = { ++ .ctx_ctr.cb = ctrl_cb, ++ .ctx_ctr.ern_cb = ctrl_ern_cb, ++ .cmd_status = 0, ++ .res_flag = 0, ++ .ern = 0 ++ }; ++ ++ pme_sw_flow_init(&flow); ++ init_completion(&ctx_ctrl.cb_done); ++ PMEPRINFO("pme2_scan: open %d\n", smp_processor_id()); ++ fp->private_data = kzalloc(sizeof(*session), GFP_KERNEL); ++ if (!fp->private_data) ++ return -ENOMEM; ++ session = (struct scan_session *)fp->private_data; ++ /* Set up the structures used for asynchronous requests */ ++ init_waitqueue_head(&session->waiting_for_completion); ++ INIT_LIST_HEAD(&session->completed_commands); ++ spin_lock_init(&session->completed_commands_lock); ++ spin_lock_init(&session->set_subset_lock); ++ PMEPRINFO("kmalloc session %p\n", fp->private_data); ++ session = fp->private_data; ++ session->ctx.cb = scan_cb; ++ session->ctx.ern_cb = scan_ern_cb; ++ ++ /* qosin, qosout should be driver attributes */ ++ ret = pme_ctx_init(&session->ctx, PME_CTX_FLAG_LOCAL, 0, 4, 4, 0, NULL); ++ if (ret) { ++ pr_err("pme2_scan: pme_ctx_init %d\n", ret); ++ goto exit; ++ } ++ /* enable the context */ ++ ret = pme_ctx_enable(&session->ctx); ++ if (ret) { ++ PMEPRINFO("error enabling ctx %d\n", ret); ++ pme_ctx_finish(&session->ctx); ++ goto exit; ++ } ++ /* Update flow to set sane defaults in the flow context */ ++ ret = pme_ctx_ctrl_update_flow(&session->ctx, ++ PME_CTX_OP_WAIT | PME_CMD_FCW_ALL, &flow, &ctx_ctrl.ctx_ctr); ++ if (!ret) { ++ wait_for_completion(&ctx_ctrl.cb_done); ++ if (ctx_ctrl.ern || ctx_ctrl.cmd_status || ctx_ctrl.res_flag) ++ ret = -EFAULT; ++ } ++ if (ret) { ++ int my_ret; ++ PMEPRINFO("error updating flow ctx %d\n", ret); ++ my_ret = pme_ctx_disable(&session->ctx, PME_CTX_OP_WAIT, ++ &ctx_ctrl.ctx_ctr); ++ if (my_ret > 0) ++ wait_for_completion(&ctx_ctrl.cb_done); ++ else if (my_ret < 0) ++ PMEPRINFO("error disabling ctx %d\n", ret); ++ pme_ctx_finish(&session->ctx); ++ goto exit; ++ } ++ /* Set up the structures used for asynchronous requests */ ++ PMEPRINFO("pme2_scan: Finish pme_scan open %d\n", smp_processor_id()); ++ return 0; ++exit: ++ kfree(fp->private_data); ++ fp->private_data = NULL; ++ return ret; ++} ++ ++static int fsl_pme2_scan_close(struct inode *node, struct file *fp) ++{ ++ struct ctrl_op ctx_ctrl = { ++ .ctx_ctr.cb = ctrl_cb, ++ .ctx_ctr.ern_cb = ctrl_ern_cb, ++ .cmd_status = 0, ++ .res_flag = 0, ++ .ern = 0 ++ }; ++ int ret = 0; ++ struct scan_session *session = fp->private_data; ++ ++ init_completion(&ctx_ctrl.cb_done); ++ /* Before disabling check to see if it's already disabled. This can ++ * happen if a pme serious error has occurred for instance.*/ ++ if (!pme_ctx_is_disabled(&session->ctx)) { ++ ret = pme_ctx_disable(&session->ctx, PME_CTX_OP_WAIT, ++ &ctx_ctrl.ctx_ctr); ++ if (ret > 0) { ++ wait_for_completion(&ctx_ctrl.cb_done); ++ if (ctx_ctrl.ern) ++ PMEPRCRIT("Unexpected ERN\n"); ++ } else if (ret < 0) { ++ pr_err("pme2_scan: Error disabling ctx %d\n", ret); ++ return ret; ++ } ++ } ++ pme_ctx_finish(&session->ctx); ++ kfree(session); ++ PMEPRINFO("pme2_scan: Finish pme_session close\n"); ++ return 0; ++} ++ ++static unsigned int fsl_pme2_scan_poll(struct file *fp, ++ struct poll_table_struct *wait) ++{ ++ struct scan_session *session; ++ unsigned int mask = POLLOUT | POLLWRNORM; ++ ++ if (!fp->private_data) ++ return -EINVAL; ++ ++ session = (struct scan_session *)fp->private_data; ++ ++ poll_wait(fp, &session->waiting_for_completion, wait); ++ ++ if (!scan_data_empty(session)) ++ mask |= (POLLIN | POLLRDNORM); ++ return mask; ++} ++ ++ ++/* Main switch loop for ioctl operations */ ++static long fsl_pme2_scan_ioctl(struct file *fp, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct scan_session *session = fp->private_data; ++ int ret = 0; ++ ++ switch (cmd) { ++ ++ case PMEIO_GETSCAN: ++ return getscan_cmd(fp, session, (struct pme_scan_params *)arg); ++ break; ++ ++ case PMEIO_SETSCAN: ++ return setscan_cmd(fp, session, (struct pme_scan_params *)arg); ++ break; ++ ++ case PMEIO_RESETSEQ: ++ return resetseq_cmd(fp, session); ++ break; ++ ++ case PMEIO_RESETRES: ++ return resetresidue_cmd(fp, session); ++ break; ++ ++ case PMEIO_SCAN: ++ { ++ int ret; ++ struct pme_scan scan; ++ ++ if (copy_from_user(&scan, (void __user *)arg, sizeof(scan))) ++ return -EFAULT; ++ ret = process_scan_cmd(fp, session, &scan.cmd, &scan.result, 1); ++ if (!ret) { ++ struct pme_scan_result __user *user_result = ++ &((struct pme_scan __user *)arg)->result; ++ ret = copy_to_user(user_result, &scan.result, ++ sizeof(*user_result)); ++ } ++ return ret; ++ } ++ break; ++ ++ case PMEIO_SCAN_W1: ++ { ++ struct pme_scan_cmd scan_cmd; ++ ++ if (copy_from_user(&scan_cmd, (void __user *)arg, ++ sizeof(scan_cmd))) ++ return -EFAULT; ++ return process_scan_cmd(fp, session, &scan_cmd, NULL, 0); ++ } ++ break; ++ ++ case PMEIO_SCAN_R1: ++ { ++ struct pme_scan_result result; ++ struct cmd_token *completed_cmd = NULL; ++ struct pme_scan_result __user *ur = ++ (struct pme_scan_result __user *)arg; ++ int ret; ++ ++ if (copy_from_user(&result, (void __user *)arg, ++ sizeof(result))) ++ return -EFAULT; ++ ++ /* Check to see if any results */ ++ spin_lock(&session->completed_commands_lock); ++ if (!list_empty(&session->completed_commands)) { ++ completed_cmd = list_first_entry( ++ &session->completed_commands, ++ struct cmd_token, ++ completed_list); ++ list_del(&completed_cmd->completed_list); ++ session->completed_count--; ++ } ++ spin_unlock(&session->completed_commands_lock); ++ if (completed_cmd) { ++ ret = process_completed_token(fp, completed_cmd, ++ &result); ++ if (!ret) ++ ret = copy_to_user(ur, &result, sizeof(result)); ++ return ret; ++ } else ++ return -EIO; ++ } ++ break; ++ ++ case PMEIO_SCAN_Wn: ++ { ++ struct pme_scan_cmds scan_cmds; ++ int i, ret = 0; ++ ++ /* Copy the command to kernel space */ ++ if (copy_from_user(&scan_cmds, (void __user *)arg, ++ sizeof(scan_cmds))) ++ return -EFAULT; ++ PMEPRINFO("Received Wn for %d cmds\n", scan_cmds.num); ++ for (i = 0; i < scan_cmds.num; i++) { ++ struct pme_scan_cmd scan_cmd; ++ ++ if (copy_from_user(&scan_cmd, &scan_cmds.cmds[i], ++ sizeof(scan_cmd))) { ++ pr_err("pme2_scan: Err with %d\n", i); ++ scan_cmds.num = i; ++ if (copy_to_user((void __user *)arg, &scan_cmds, ++ sizeof(scan_cmds))) { ++ return -EFAULT; ++ } ++ return -EFAULT; ++ } ++ ret = process_scan_cmd(fp, session, &scan_cmd, NULL, 0); ++ if (ret) { ++ pr_err("pme2_scan: Err with %d cmd %d\n", ++ i, ret); ++ scan_cmds.num = i; ++ if (copy_to_user((void *)arg, &scan_cmds, ++ sizeof(scan_cmds))) { ++ pr_err("Error copying to user data\n"); ++ return -EFAULT; ++ } ++ return -EINTR; ++ } ++ } ++ return ret; ++ } ++ break; ++ ++ case PMEIO_SCAN_Rn: ++ { ++ struct pme_scan_results results; ++ struct pme_scan_result result; ++ struct pme_scan_result __user *ur; ++ int i = 0, ret = 0; ++ struct cmd_token *completed_cmd = NULL; ++ ++ /* Copy the command to kernel space */ ++ if (copy_from_user(&results, (void __user *)arg, ++ sizeof(results))) ++ return -EFAULT; ++ ur = ((struct pme_scan_results __user *)arg)->results ++ PMEPRINFO("pme2_scan: Received Rn for %d res\n", results.num); ++ if (!results.num) ++ return 0; ++ do { ++ completed_cmd = NULL; ++ ret = 0; ++ /* Check to see if any results */ ++ spin_lock(&session->completed_commands_lock); ++ if (!list_empty(&session->completed_commands)) { ++ /* Move to a different list */ ++ PMEPRINFO("pme2_scan: Pop response\n"); ++ completed_cmd = list_first_entry( ++ &session->completed_commands, ++ struct cmd_token, ++ completed_list); ++ list_del(&completed_cmd->completed_list); ++ session->completed_count--; ++ } ++ spin_unlock(&session->completed_commands_lock); ++ if (completed_cmd) { ++ if (copy_from_user(&result, (void __user *)ur+i, ++ sizeof(result))) ++ return -EFAULT; ++ ret = process_completed_token(fp, completed_cmd, ++ &result); ++ if (!ret) ++ ret = copy_to_user(ur, &result, ++ sizeof(struct pme_scan_result)); ++ if (!ret) { ++ i++; ++ ur++; ++ } ++ } ++ } while (!ret && completed_cmd && (i != results.num)); ++ ++ if (i != results.num) { ++ PMEPRINFO("pme2_scan: Only filled %d responses\n", i); ++ results.num = i; ++ PMEPRINFO("pme2_scan: results.num = %d\n", results.num); ++ if (copy_to_user((void __user *)arg, &results, ++ sizeof(struct pme_scan_results))) { ++ pr_err("Error copying to user data\n"); ++ return -EFAULT; ++ } ++ } ++ return ret; ++ } ++ break; ++ ++ case PMEIO_RELEASE_BUFS: ++ return -EINVAL; ++ break; ++ ++#ifdef CONFIG_COMPAT ++ case PMEIO_SCAN32: ++ { ++ int ret; ++ struct compat_pme_scan scan32; ++ struct compat_pme_scan __user *user_scan = compat_ptr(arg); ++ struct pme_scan scan; ++ ++ if (copy_from_user(&scan32, user_scan, sizeof(scan32))) ++ return -EFAULT; ++ /* Convert to 64-bit structs */ ++ compat_to_scan_cmd(&scan.cmd, &scan32.cmd); ++ compat_to_scan_result(&scan.result, &scan32.result); ++ ++ ret = process_scan_cmd(fp, session, &scan.cmd, &scan.result, 1); ++ if (!ret) { ++ struct compat_pme_scan_result __user *user_result = ++ &user_scan->result; ++ /* Convert to 32-bit struct */ ++ scan_result_to_compat(&scan32.result, &scan.result); ++ ret = copy_to_user(user_result, &scan32.result, ++ sizeof(*user_result)); ++ } ++ return ret; ++ } ++ break; ++ ++ case PMEIO_SCAN_W132: ++ { ++ struct compat_pme_scan_cmd scan_cmd32; ++ struct pme_scan_cmd scan_cmd; ++ ++ if (copy_from_user(&scan_cmd32, compat_ptr(arg), ++ sizeof(scan_cmd32))) ++ return -EFAULT; ++ /* Convert to 64-bit struct */ ++ compat_to_scan_cmd(&scan_cmd, &scan_cmd32); ++ return process_scan_cmd(fp, session, &scan_cmd, NULL, 0); ++ } ++ break; ++ ++ case PMEIO_SCAN_R132: ++ { ++ struct compat_pme_scan_result result32; ++ struct pme_scan_result result; ++ struct cmd_token *completed_cmd = NULL; ++ struct compat_pme_scan_result __user *ur = compat_ptr(arg); ++ int ret; ++ ++ if (copy_from_user(&result32, (void __user *)arg, ++ sizeof(result32))) ++ return -EFAULT; ++ /* copy to 64-bit structure */ ++ compat_to_scan_result(&result, &result32); ++ ++ /* Check to see if any results */ ++ spin_lock(&session->completed_commands_lock); ++ if (!list_empty(&session->completed_commands)) { ++ completed_cmd = list_first_entry( ++ &session->completed_commands, ++ struct cmd_token, ++ completed_list); ++ list_del(&completed_cmd->completed_list); ++ session->completed_count--; ++ } ++ spin_unlock(&session->completed_commands_lock); ++ if (completed_cmd) { ++ ret = process_completed_token(fp, completed_cmd, ++ &result); ++ scan_result_to_compat(&result32, &result); ++ ret = copy_to_user(ur, &result32, sizeof(result32)); ++ } else ++ return -EIO; ++ } ++ break; ++ ++ case PMEIO_SCAN_Wn32: ++ { ++ struct compat_pme_scan_cmds scan_cmds32; ++ int i, ret = 0; ++ ++ /* Copy the command to kernel space */ ++ if (copy_from_user(&scan_cmds32, compat_ptr(arg), ++ sizeof(scan_cmds32))) ++ return -EFAULT; ++ PMEPRINFO("Received Wn for %d cmds\n", scan_cmds32.num); ++ for (i = 0; i < scan_cmds32.num; i++) { ++ struct pme_scan_cmd scan_cmd; ++ struct compat_pme_scan_cmd __user *u_scan_cmd32; ++ struct compat_pme_scan_cmd scan_cmd32; ++ ++ u_scan_cmd32 = compat_ptr(scan_cmds32.cmds); ++ u_scan_cmd32 += i; ++ ++ if (copy_from_user(&scan_cmd32, u_scan_cmd32, ++ sizeof(scan_cmd32))) { ++ pr_err("pme2_scan: Err with %d\n", i); ++ scan_cmds32.num = i; ++ if (copy_to_user(compat_ptr(arg), &scan_cmds32, ++ sizeof(scan_cmds32))) ++ return -EFAULT; ++ return -EFAULT; ++ } ++ compat_to_scan_cmd(&scan_cmd, &scan_cmd32); ++ ret = process_scan_cmd(fp, session, &scan_cmd, NULL, 0); ++ if (ret) { ++ pr_err("pme2_scan: Err with %d cmd %d\n", ++ i, ret); ++ scan_cmds32.num = i; ++ if (copy_to_user(compat_ptr(arg), &scan_cmds32, ++ sizeof(scan_cmds32))) ++ return -EFAULT; ++ return -EINTR; ++ } ++ } ++ return ret; ++ } ++ break; ++ ++ case PMEIO_SCAN_Rn32: ++ { ++ struct compat_pme_scan_results results32; ++ int i = 0, ret = 0; ++ struct cmd_token *completed_cmd = NULL; ++ struct compat_pme_scan_result __user *ur; ++ ++ /* Copy the command to kernel space */ ++ if (copy_from_user(&results32, compat_ptr(arg), ++ sizeof(results32))) ++ return -EFAULT; ++ ur = compat_ptr(results32.results); ++ PMEPRINFO("pme2_scan: Rx Rn for %d res\n", results32.num); ++ if (!results32.num) ++ return 0; ++ do { ++ completed_cmd = NULL; ++ ret = 0; ++ /* Check to see if any results */ ++ spin_lock(&session->completed_commands_lock); ++ if (!list_empty(&session->completed_commands)) { ++ /* Move to a different list */ ++ PMEPRINFO("pme2_scan: Pop response\n"); ++ completed_cmd = list_first_entry( ++ &session->completed_commands, ++ struct cmd_token, ++ completed_list); ++ list_del(&completed_cmd->completed_list); ++ session->completed_count--; ++ } ++ spin_unlock(&session->completed_commands_lock); ++ if (completed_cmd) { ++ struct compat_pme_scan_result l_result32; ++ struct pme_scan_result result; ++ ++ if (copy_from_user(&l_result32, ur+i, ++ sizeof(l_result32))) ++ return -EFAULT; ++ compat_to_scan_result(&result, &l_result32); ++ ret = process_completed_token(fp, completed_cmd, ++ &result); ++ scan_result_to_compat(&l_result32, &result); ++ ret = copy_to_user(ur+i, &l_result32, ++ sizeof(l_result32)); ++ if (!ret) ++ i++; ++ } ++ } while (!ret && completed_cmd && (i != results32.num)); ++ ++ if (i != results32.num) { ++ PMEPRINFO("pme2_scan: Only filled %d responses\n", i); ++ results32.num = i; ++ PMEPRINFO("pme2_scan: results32.num = %d\n", ++ results32.num); ++ if (copy_to_user(compat_ptr(arg), &results32, ++ sizeof(struct pme_scan_results))) { ++ pr_err("Error copying to user data\n"); ++ return -EFAULT; ++ } ++ } ++ return ret; ++ } ++ break; ++#endif /* CONFIG_COMPAT */ ++ ++ default: ++ pr_err("UNKNOWN IOCTL cmd 0x%x\n", cmd); ++ return -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct file_operations fsl_pme2_scan_fops = { ++ .owner = THIS_MODULE, ++ .open = fsl_pme2_scan_open, ++ .release = fsl_pme2_scan_close, ++ .poll = fsl_pme2_scan_poll, ++ .unlocked_ioctl = fsl_pme2_scan_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = fsl_pme2_scan_ioctl, ++#endif ++}; ++ ++static struct miscdevice fsl_pme2_scan_dev = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = PME_DEV_SCAN_NODE, ++ .fops = &fsl_pme2_scan_fops ++}; ++ ++static int __init fsl_pme2_scan_init(void) ++{ ++ int err = 0; ++ ++ pr_info("Freescale pme2 scan driver\n"); ++ err = misc_register(&fsl_pme2_scan_dev); ++ if (err) { ++ pr_err("fsl-pme2-scan: cannot register device\n"); ++ return err; ++ } ++ pr_info("fsl-pme2-scan: device %s registered\n", ++ fsl_pme2_scan_dev.name); ++ return 0; ++} ++ ++static void __exit fsl_pme2_scan_exit(void) ++{ ++ int err = misc_deregister(&fsl_pme2_scan_dev); ++ if (err) ++ pr_err("fsl-pme2-scan: Failed to deregister device %s, " ++ "code %d\n", fsl_pme2_scan_dev.name, err); ++ pr_info("fsl-pme2-scan: device %s deregistered\n", ++ fsl_pme2_scan_dev.name); ++} ++ ++module_init(fsl_pme2_scan_init); ++module_exit(fsl_pme2_scan_exit); ++ ++MODULE_AUTHOR("Jeffrey Ladouceur "); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("Freescale PME2 scan driver"); +diff --git a/drivers/staging/fsl_pme2/pme2_sys.h b/drivers/staging/fsl_pme2/pme2_sys.h +new file mode 100644 +index 0000000..fefe1f5 +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_sys.h +@@ -0,0 +1,63 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 ++#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 ++ ++int pme2_create_sysfs_dev_files(struct platform_device *ofdev); ++void pme2_remove_sysfs_dev_files(struct platform_device *ofdev); ++void accumulator_update_interval(u32 interval); +diff --git a/drivers/staging/fsl_pme2/pme2_sysfs.c b/drivers/staging/fsl_pme2/pme2_sysfs.c +new file mode 100644 +index 0000000..07e6e64 +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_sysfs.c +@@ -0,0 +1,563 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "pme2_regs.h" ++#include "pme2_private.h" ++ ++#define MAX_ACCUMULATOR_INTERVAL 10000 ++extern u32 pme_stat_interval; ++ ++/* The pme sysfs contains the following types of attributes ++ * 1) root level: general pme confuration ++ * 2) bsc: bufferpool size configuration ++ * 3) stats: pme statistics ++ */ ++static ssize_t pme_store(struct device *dev, struct device_attribute *dev_attr, ++ const char *buf, size_t count, enum pme_attr attr) ++{ ++ unsigned long val; ++ size_t ret; ++ if (strict_strtoul(buf, 0, &val)) { ++ dev_dbg(dev, "invalid input %s\n",buf); ++ return -EINVAL; ++ } ++ ret = pme_attr_set(attr, val); ++ if (ret) { ++ dev_err(dev, "attr_set err attr=%u, val=%lu\n", attr, val); ++ return ret; ++ } ++ return count; ++} ++ ++static ssize_t pme_show(struct device *dev, struct device_attribute *dev_attr, ++ char *buf, enum pme_attr attr, const char *fmt) ++{ ++ u32 data; ++ int ret; ++ ++ ret = pme_attr_get(attr, &data); ++ if (!ret) ++ return snprintf(buf, PAGE_SIZE, fmt, data); ++ return ret; ++} ++ ++ ++static ssize_t pme_stat_show(struct device *dev, ++ struct device_attribute *dev_attr, char *buf, enum pme_attr attr) ++{ ++ u64 data = 0; ++ int ret = 0; ++ ++ ret = pme_stat_get(attr, &data, 0); ++ if (!ret) ++ return snprintf(buf, PAGE_SIZE, "%llu\n", data); ++ else ++ return ret; ++} ++ ++static ssize_t pme_stat_store(struct device *dev, ++ struct device_attribute *dev_attr, const char *buf, ++ size_t count, enum pme_attr attr) ++{ ++ unsigned long val; ++ u64 data = 0; ++ size_t ret = 0; ++ if (strict_strtoul(buf, 0, &val)) { ++ pr_err("pme: invalid input %s\n", buf); ++ return -EINVAL; ++ } ++ if (val) { ++ pr_err("pme: invalid input %s\n", buf); ++ return -EINVAL; ++ } ++ ret = pme_stat_get(attr, &data, 1); ++ return count; ++} ++ ++ ++#define PME_SYSFS_ATTR(pme_attr, perm, showhex) \ ++static ssize_t pme_store_##pme_attr(struct device *dev, \ ++ struct device_attribute *attr, const char *buf, size_t count) \ ++{ \ ++ return pme_store(dev, attr, buf, count, pme_attr_##pme_attr);\ ++} \ ++static ssize_t pme_show_##pme_attr(struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ ++{ \ ++ return pme_show(dev, attr, buf, pme_attr_##pme_attr, showhex);\ ++} \ ++static DEVICE_ATTR( pme_attr, perm, pme_show_##pme_attr, pme_store_##pme_attr); ++ ++ ++#define PME_SYSFS_STAT_ATTR(pme_attr, perm) \ ++static ssize_t pme_store_##pme_attr(struct device *dev, \ ++ struct device_attribute *attr, const char *buf, size_t count) \ ++{ \ ++ return pme_stat_store(dev, attr, buf, count, pme_attr_##pme_attr);\ ++} \ ++static ssize_t pme_show_##pme_attr(struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ ++{ \ ++ return pme_stat_show(dev, attr, buf, pme_attr_##pme_attr);\ ++} \ ++static DEVICE_ATTR(pme_attr, perm, pme_show_##pme_attr, pme_store_##pme_attr); ++ ++ ++#define PME_SYSFS_BSC_ATTR(bsc_id, perm, showhex) \ ++static ssize_t pme_store_bsc_##bsc_id(struct device *dev,\ ++ struct device_attribute *attr, const char *buf, size_t count) \ ++{ \ ++ return pme_store(dev, attr, buf, count, pme_attr_bsc(bsc_id));\ ++} \ ++static ssize_t pme_show_bsc_##bsc_id(struct device *dev,\ ++ struct device_attribute *attr, char *buf) \ ++{ \ ++ return pme_show(dev, attr, buf, pme_attr_bsc(bsc_id), showhex);\ ++} \ ++static DEVICE_ATTR(bsc_id, perm, pme_show_bsc_##bsc_id, \ ++ pme_store_bsc_##bsc_id); ++ ++/* Statistics Ctrl: update interval */ ++static ssize_t pme_store_update_interval(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ unsigned long val; ++ ++ if (!pme2_have_control()) { ++ PMEPRERR("not on ctrl-plane\n"); ++ return -ENODEV; ++ } ++ if (strict_strtoul(buf, 0, &val)) { ++ dev_info(dev, "invalid input %s\n", buf); ++ return -EINVAL; ++ } ++ if (val > MAX_ACCUMULATOR_INTERVAL) { ++ dev_info(dev, "invalid input %s\n", buf); ++ return -ERANGE; ++ } ++ accumulator_update_interval(val); ++ return count; ++} ++static ssize_t pme_show_update_interval(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ if (!pme2_have_control()) ++ return -ENODEV; ++ return snprintf(buf, PAGE_SIZE, "%u\n", pme_stat_interval); ++} ++ ++#define FMT_0HEX "0x%08x\n" ++#define FMT_HEX "0x%x\n" ++#define FMT_DEC "%u\n" ++#define PRIV_RO S_IRUSR ++#define PRIV_RW (S_IRUSR | S_IWUSR) ++ ++/* Register Interfaces */ ++/* read-write; */ ++PME_SYSFS_ATTR(efqc_int, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(sw_db, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(dmcr, PRIV_RW, FMT_0HEX); ++PME_SYSFS_ATTR(smcr, PRIV_RW, FMT_0HEX); ++PME_SYSFS_ATTR(famcr, PRIV_RW, FMT_0HEX); ++PME_SYSFS_ATTR(kvlts, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(max_chain_length, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(pattern_range_counter_idx, PRIV_RW, FMT_0HEX); ++PME_SYSFS_ATTR(pattern_range_counter_mask, PRIV_RW, FMT_0HEX); ++PME_SYSFS_ATTR(max_allowed_test_line_per_pattern, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(max_pattern_matches_per_sui, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(max_pattern_evaluations_per_sui, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(report_length_limit, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(end_of_simple_sui_report, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(aim, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(end_of_sui_reaction_ptr, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(sre_pscl, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(sre_max_block_num, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(sre_max_instruction_limit, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(esr, PRIV_RW, FMT_0HEX); ++PME_SYSFS_ATTR(pehd, PRIV_RW, FMT_0HEX); ++PME_SYSFS_ATTR(ecc1bes, PRIV_RW, FMT_0HEX); ++PME_SYSFS_ATTR(ecc2bes, PRIV_RW, FMT_0HEX); ++PME_SYSFS_ATTR(miace, PRIV_RW, FMT_0HEX); ++PME_SYSFS_ATTR(miacr, PRIV_RW, FMT_0HEX); ++PME_SYSFS_ATTR(cdcr, PRIV_RW, FMT_0HEX); ++PME_SYSFS_ATTR(pmtr, PRIV_RW, FMT_DEC); ++ ++/* read-only; */ ++PME_SYSFS_ATTR(max_pdsr_index, PRIV_RO, FMT_DEC); ++PME_SYSFS_ATTR(sre_context_size, PRIV_RO, FMT_DEC); ++PME_SYSFS_ATTR(sre_rule_num, PRIV_RO, FMT_DEC); ++PME_SYSFS_ATTR(sre_session_ctx_num, PRIV_RO, FMT_DEC); ++PME_SYSFS_ATTR(sre_max_index_size, PRIV_RO, FMT_DEC); ++PME_SYSFS_ATTR(sre_max_offset_ctrl, PRIV_RO, FMT_DEC); ++PME_SYSFS_ATTR(src_id, PRIV_RO, FMT_DEC); ++PME_SYSFS_ATTR(liodnr, PRIV_RO, FMT_DEC); ++PME_SYSFS_ATTR(rev1, PRIV_RO, FMT_0HEX); ++PME_SYSFS_ATTR(rev2, PRIV_RO, FMT_0HEX); ++PME_SYSFS_ATTR(isr, PRIV_RO, FMT_0HEX); ++PME_SYSFS_ATTR(ecr0, PRIV_RO, FMT_0HEX); ++PME_SYSFS_ATTR(ecr1, PRIV_RO, FMT_0HEX); ++PME_SYSFS_ATTR(pmstat, PRIV_RO, FMT_0HEX); ++PME_SYSFS_ATTR(eccaddr, PRIV_RO, FMT_0HEX); ++PME_SYSFS_ATTR(ecccode, PRIV_RO, FMT_0HEX); ++PME_SYSFS_ATTR(faconf, PRIV_RO, FMT_0HEX); ++PME_SYSFS_ATTR(pdsrbah, PRIV_RO, FMT_0HEX); ++PME_SYSFS_ATTR(pdsrbal, PRIV_RO, FMT_0HEX); ++PME_SYSFS_ATTR(scbarh, PRIV_RO, FMT_0HEX); ++PME_SYSFS_ATTR(scbarl, PRIV_RO, FMT_0HEX); ++ ++ ++/* Buffer Pool Size Configuration */ ++PME_SYSFS_BSC_ATTR(0, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(1, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(2, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(3, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(4, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(5, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(6, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(7, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(8, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(9, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(10, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(11, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(12, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(13, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(14, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(15, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(16, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(17, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(18, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(19, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(20, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(21, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(22, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(23, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(24, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(25, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(26, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(27, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(28, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(29, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(30, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(31, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(32, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(33, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(34, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(35, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(36, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(37, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(38, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(39, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(40, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(41, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(42, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(43, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(44, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(45, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(46, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(47, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(48, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(49, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(50, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(51, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(52, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(53, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(54, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(55, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(56, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(57, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(58, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(59, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(60, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(61, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(62, PRIV_RW, FMT_DEC); ++PME_SYSFS_BSC_ATTR(63, PRIV_RW, FMT_DEC); ++ ++/* Stats Counters*/ ++PME_SYSFS_STAT_ATTR(trunci, PRIV_RW); ++PME_SYSFS_STAT_ATTR(rbc, PRIV_RW); ++PME_SYSFS_STAT_ATTR(tbt0ecc1ec, PRIV_RW); ++PME_SYSFS_STAT_ATTR(tbt1ecc1ec, PRIV_RW); ++PME_SYSFS_STAT_ATTR(vlt0ecc1ec, PRIV_RW); ++PME_SYSFS_STAT_ATTR(vlt1ecc1ec, PRIV_RW); ++PME_SYSFS_STAT_ATTR(cmecc1ec, PRIV_RW); ++PME_SYSFS_STAT_ATTR(dxcmecc1ec, PRIV_RW); ++PME_SYSFS_STAT_ATTR(dxemecc1ec, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stnib, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stnis, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stnth1, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stnth2, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stnthv, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stnths, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stnch, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stnpm, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stns1m, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stnpmr, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stndsr, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stnesr, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stns1r, PRIV_RW); ++PME_SYSFS_STAT_ATTR(stnob, PRIV_RW); ++PME_SYSFS_STAT_ATTR(mia_byc, PRIV_RW); ++PME_SYSFS_STAT_ATTR(mia_blc, PRIV_RW); ++ ++/* Stats Control */ ++PME_SYSFS_ATTR(tbt0ecc1th, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(tbt1ecc1th, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(vlt0ecc1th, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(vlt1ecc1th, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(cmecc1th, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(dxcmecc1th, PRIV_RW, FMT_DEC); ++PME_SYSFS_ATTR(dxemecc1th, PRIV_RW, FMT_DEC); ++ ++static DEVICE_ATTR(update_interval, (S_IRUSR | S_IWUSR), ++ pme_show_update_interval, pme_store_update_interval); ++ ++static struct attribute *pme_dev_bsc_attributes[] = { ++ &dev_attr_0.attr, ++ &dev_attr_1.attr, ++ &dev_attr_2.attr, ++ &dev_attr_3.attr, ++ &dev_attr_4.attr, ++ &dev_attr_5.attr, ++ &dev_attr_6.attr, ++ &dev_attr_7.attr, ++ &dev_attr_8.attr, ++ &dev_attr_9.attr, ++ &dev_attr_10.attr, ++ &dev_attr_11.attr, ++ &dev_attr_12.attr, ++ &dev_attr_13.attr, ++ &dev_attr_14.attr, ++ &dev_attr_15.attr, ++ &dev_attr_16.attr, ++ &dev_attr_17.attr, ++ &dev_attr_18.attr, ++ &dev_attr_19.attr, ++ &dev_attr_20.attr, ++ &dev_attr_21.attr, ++ &dev_attr_22.attr, ++ &dev_attr_23.attr, ++ &dev_attr_24.attr, ++ &dev_attr_25.attr, ++ &dev_attr_26.attr, ++ &dev_attr_27.attr, ++ &dev_attr_28.attr, ++ &dev_attr_29.attr, ++ &dev_attr_30.attr, ++ &dev_attr_31.attr, ++ &dev_attr_32.attr, ++ &dev_attr_33.attr, ++ &dev_attr_34.attr, ++ &dev_attr_35.attr, ++ &dev_attr_36.attr, ++ &dev_attr_37.attr, ++ &dev_attr_38.attr, ++ &dev_attr_39.attr, ++ &dev_attr_40.attr, ++ &dev_attr_41.attr, ++ &dev_attr_42.attr, ++ &dev_attr_43.attr, ++ &dev_attr_44.attr, ++ &dev_attr_45.attr, ++ &dev_attr_46.attr, ++ &dev_attr_47.attr, ++ &dev_attr_48.attr, ++ &dev_attr_49.attr, ++ &dev_attr_50.attr, ++ &dev_attr_51.attr, ++ &dev_attr_52.attr, ++ &dev_attr_53.attr, ++ &dev_attr_54.attr, ++ &dev_attr_55.attr, ++ &dev_attr_56.attr, ++ &dev_attr_57.attr, ++ &dev_attr_58.attr, ++ &dev_attr_59.attr, ++ &dev_attr_60.attr, ++ &dev_attr_61.attr, ++ &dev_attr_62.attr, ++ &dev_attr_63.attr, ++ NULL ++}; ++ ++static struct attribute *pme_dev_attributes[] = { ++ &dev_attr_efqc_int.attr, ++ &dev_attr_sw_db.attr, ++ &dev_attr_dmcr.attr, ++ &dev_attr_smcr.attr, ++ &dev_attr_famcr.attr, ++ &dev_attr_kvlts.attr, ++ &dev_attr_max_chain_length.attr, ++ &dev_attr_pattern_range_counter_idx.attr, ++ &dev_attr_pattern_range_counter_mask.attr, ++ &dev_attr_max_allowed_test_line_per_pattern.attr, ++ &dev_attr_max_pdsr_index.attr, ++ &dev_attr_max_pattern_matches_per_sui.attr, ++ &dev_attr_max_pattern_evaluations_per_sui.attr, ++ &dev_attr_report_length_limit.attr, ++ &dev_attr_end_of_simple_sui_report.attr, ++ &dev_attr_aim.attr, ++ &dev_attr_sre_context_size.attr, ++ &dev_attr_sre_rule_num.attr, ++ &dev_attr_sre_session_ctx_num.attr, ++ &dev_attr_end_of_sui_reaction_ptr.attr, ++ &dev_attr_sre_pscl.attr, ++ &dev_attr_sre_max_block_num.attr, ++ &dev_attr_sre_max_instruction_limit.attr, ++ &dev_attr_sre_max_index_size.attr, ++ &dev_attr_sre_max_offset_ctrl.attr, ++ &dev_attr_src_id.attr, ++ &dev_attr_liodnr.attr, ++ &dev_attr_rev1.attr, ++ &dev_attr_rev2.attr, ++ &dev_attr_isr.attr, ++ &dev_attr_ecr0.attr, ++ &dev_attr_ecr1.attr, ++ &dev_attr_esr.attr, ++ &dev_attr_pmstat.attr, ++ &dev_attr_pehd.attr, ++ &dev_attr_ecc1bes.attr, ++ &dev_attr_ecc2bes.attr, ++ &dev_attr_eccaddr.attr, ++ &dev_attr_ecccode.attr, ++ &dev_attr_miace.attr, ++ &dev_attr_miacr.attr, ++ &dev_attr_cdcr.attr, ++ &dev_attr_pmtr.attr, ++ &dev_attr_faconf.attr, ++ &dev_attr_pdsrbah.attr, ++ &dev_attr_pdsrbal.attr, ++ &dev_attr_scbarh.attr, ++ &dev_attr_scbarl.attr, ++ NULL ++}; ++ ++static struct attribute *pme_dev_stats_counter_attributes[] = { ++ &dev_attr_trunci.attr, ++ &dev_attr_rbc.attr, ++ &dev_attr_tbt0ecc1ec.attr, ++ &dev_attr_tbt1ecc1ec.attr, ++ &dev_attr_vlt0ecc1ec.attr, ++ &dev_attr_vlt1ecc1ec.attr, ++ &dev_attr_cmecc1ec.attr, ++ &dev_attr_dxcmecc1ec.attr, ++ &dev_attr_dxemecc1ec.attr, ++ &dev_attr_stnib.attr, ++ &dev_attr_stnis.attr, ++ &dev_attr_stnth1.attr, ++ &dev_attr_stnth2.attr, ++ &dev_attr_stnthv.attr, ++ &dev_attr_stnths.attr, ++ &dev_attr_stnch.attr, ++ &dev_attr_stnpm.attr, ++ &dev_attr_stns1m.attr, ++ &dev_attr_stnpmr.attr, ++ &dev_attr_stndsr.attr, ++ &dev_attr_stnesr.attr, ++ &dev_attr_stns1r.attr, ++ &dev_attr_stnob.attr, ++ &dev_attr_mia_byc.attr, ++ &dev_attr_mia_blc.attr, ++ NULL ++}; ++ ++static struct attribute *pme_dev_stats_ctrl_attributes[] = { ++ &dev_attr_update_interval.attr, ++ &dev_attr_tbt0ecc1th.attr, ++ &dev_attr_tbt1ecc1th.attr, ++ &dev_attr_vlt0ecc1th.attr, ++ &dev_attr_vlt1ecc1th.attr, ++ &dev_attr_cmecc1th.attr, ++ &dev_attr_dxcmecc1th.attr, ++ &dev_attr_dxemecc1th.attr, ++ NULL ++}; ++ ++/* root level */ ++static const struct attribute_group pme_dev_attr_grp = { ++ .name = NULL, /* put in device directory */ ++ .attrs = pme_dev_attributes ++}; ++ ++/* root/bsc */ ++static struct attribute_group pme_dev_bsc_attr_grp = { ++ .name = "bsc", ++ .attrs = pme_dev_bsc_attributes ++}; ++ ++/* root/stats */ ++static struct attribute_group pme_dev_stats_counters_attr_grp = { ++ .name = "stats", ++ .attrs = pme_dev_stats_counter_attributes ++}; ++ ++/* root/stats_ctrl */ ++static struct attribute_group pme_dev_stats_ctrl_attr_grp = { ++ .name = "stats_ctrl", ++ .attrs = pme_dev_stats_ctrl_attributes ++}; ++ ++ ++int pme2_create_sysfs_dev_files(struct platform_device *ofdev) ++{ ++ int ret; ++ ++ ret = sysfs_create_group(&ofdev->dev.kobj, &pme_dev_attr_grp); ++ if (ret) ++ goto done; ++ ret = sysfs_create_group(&ofdev->dev.kobj, &pme_dev_bsc_attr_grp); ++ if (ret) ++ goto del_group_1; ++ ret = sysfs_create_group(&ofdev->dev.kobj, &pme_dev_stats_counters_attr_grp); ++ if (ret) ++ goto del_group_2; ++ ret = sysfs_create_group(&ofdev->dev.kobj, &pme_dev_stats_ctrl_attr_grp); ++ if (ret) ++ goto del_group_3; ++ goto done; ++del_group_3: ++ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_stats_counters_attr_grp); ++del_group_2: ++ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_bsc_attr_grp); ++del_group_1: ++ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_attr_grp); ++done: ++ if (ret) ++ dev_err(&ofdev->dev, ++ "Cannot create dev attributes ret=%d\n", ret); ++ return ret; ++} ++ ++void pme2_remove_sysfs_dev_files(struct platform_device *ofdev) ++{ ++ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_stats_ctrl_attr_grp); ++ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_stats_counters_attr_grp); ++ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_bsc_attr_grp); ++ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_attr_grp); ++} +diff --git a/drivers/staging/fsl_pme2/pme2_test.h b/drivers/staging/fsl_pme2/pme2_test.h +new file mode 100644 +index 0000000..994ca26 +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_test.h +@@ -0,0 +1,74 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "pme2_sys.h" ++ ++static inline void __hexdump(unsigned long start, unsigned long end, ++ unsigned long p, size_t sz, const unsigned char *c) ++{ ++ while (start < end) { ++ unsigned int pos = 0; ++ char buf[64]; ++ int nl = 0; ++ pos += sprintf(buf + pos, "%08lx: ", start); ++ do { ++ if ((start < p) || (start >= (p + sz))) ++ pos += sprintf(buf + pos, ".."); ++ else ++ pos += sprintf(buf + pos, "%02x", *(c++)); ++ if (!(++start & 15)) { ++ buf[pos++] = '\n'; ++ nl = 1; ++ } else { ++ nl = 0; ++ if(!(start & 1)) ++ buf[pos++] = ' '; ++ if(!(start & 3)) ++ buf[pos++] = ' '; ++ } ++ } while (start & 15); ++ if (!nl) ++ buf[pos++] = '\n'; ++ buf[pos] = '\0'; ++ pr_info("%s", buf); ++ } ++} ++static inline void hexdump(const void *ptr, size_t sz) ++{ ++ unsigned long p = (unsigned long)ptr; ++ unsigned long start = p & ~(unsigned long)15; ++ unsigned long end = (p + sz + 15) & ~(unsigned long)15; ++ const unsigned char *c = ptr; ++ __hexdump(start, end, p, sz, c); ++} ++ ++int pme2_sample_db(void); ++int pme2_clear_sample_db(void); +diff --git a/drivers/staging/fsl_pme2/pme2_test_high.c b/drivers/staging/fsl_pme2/pme2_test_high.c +new file mode 100644 +index 0000000..a54cf0f +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_test_high.c +@@ -0,0 +1,237 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "pme2_test.h" ++ ++MODULE_AUTHOR("Geoff Thorpe"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("FSL PME2 (p4080) high-level self-test"); ++ ++/* Default Flow Context State */ ++static u8 fl_ctx_exp[]={ ++ 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe0, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 ++}; ++ ++void scan_cb(struct pme_ctx *ctx, const struct qm_fd *fd, ++ struct pme_ctx_token *token) ++{ ++ hexdump(fd, sizeof(*fd)); ++} ++ ++struct ctrl_op { ++ struct pme_ctx_ctrl_token ctx_ctr; ++ struct completion cb_done; ++ enum pme_status cmd_status; ++ u8 res_flag; ++}; ++ ++static void ctrl_cb(struct pme_ctx *ctx, const struct qm_fd *fd, ++ struct pme_ctx_ctrl_token *token) ++{ ++ struct ctrl_op *ctrl = (struct ctrl_op *)token; ++ pr_info("pme2_test_high: ctrl_cb() invoked, fd;!\n"); ++ ctrl->cmd_status = pme_fd_res_status(fd); ++ ctrl->res_flag = pme_fd_res_flags(fd); ++ hexdump(fd, sizeof(*fd)); ++ complete(&ctrl->cb_done); ++} ++ ++ ++#define POST_CTRL(val) \ ++do { \ ++ if (ret) \ ++ val = -1;\ ++ else if (pme_ctx_is_dead(&ctx))\ ++ val = -1;\ ++ else if (ctx_ctrl.cmd_status)\ ++ val = -1;\ ++ else if (ctx_ctrl.res_flag)\ ++ val = -1;\ ++} while (0) ++ ++void pme2_test_high(void) ++{ ++ int post_ctrl = 0; ++ struct pme_flow flow; ++ struct qm_fqd_stashing stashing; ++ struct pme_ctx ctx = { ++ .cb = scan_cb ++ }; ++ int ret; ++ struct ctrl_op ctx_ctrl = { ++ .ctx_ctr.cb = ctrl_cb, ++ .cmd_status = 0, ++ .res_flag = 0 ++ }; ++ struct cpumask backup_mask = current->cpus_allowed; ++ struct cpumask new_mask = *qman_affine_cpus(); ++ ++ pr_info("PME2: high-level test starting\n"); ++ ++ cpumask_and(&new_mask, &new_mask, bman_affine_cpus()); ++ ret = set_cpus_allowed_ptr(current, &new_mask); ++ if (ret) { ++ post_ctrl = -1; ++ pr_info("PME2: test high: can't set cpumask\n"); ++ goto done; ++ } ++ ++ pme_sw_flow_init(&flow); ++ init_completion(&ctx_ctrl.cb_done); ++ ret = pme_ctx_init(&ctx, PME_CTX_FLAG_LOCAL, 0, 4, 4, 0, NULL); ++ POST_CTRL(post_ctrl); ++ if (post_ctrl) ++ goto restore_mask; ++ ++ /* enable the context */ ++ pme_ctx_enable(&ctx); ++ pr_info("PME2: pme_ctx_enable done\n"); ++ ret = pme_ctx_ctrl_update_flow(&ctx, PME_CTX_OP_WAIT | PME_CMD_FCW_ALL, ++ &flow, &ctx_ctrl.ctx_ctr); ++ pr_info("PME2: pme_ctx_ctrl_update_flow done\n"); ++ wait_for_completion(&ctx_ctrl.cb_done); ++ POST_CTRL(post_ctrl); ++ if (post_ctrl) ++ goto disable_ctx; ++ /* read back flow settings */ ++ ret = pme_ctx_ctrl_read_flow(&ctx, PME_CTX_OP_WAIT, &flow, ++ &ctx_ctrl.ctx_ctr); ++ pr_info("PME2: pme_ctx_ctrl_read_flow done\n"); ++ wait_for_completion(&ctx_ctrl.cb_done); ++ POST_CTRL(post_ctrl); ++ if (post_ctrl) ++ goto disable_ctx; ++ if (memcmp(&flow, fl_ctx_exp, sizeof(flow))) { ++ pr_info("Default Flow Context Read FAIL\n"); ++ pr_info("Expected:\n"); ++ hexdump(fl_ctx_exp, sizeof(fl_ctx_exp)); ++ pr_info("Received:\n"); ++ hexdump(&flow, sizeof(flow)); ++ post_ctrl = -1; ++ goto disable_ctx; ++ } else ++ pr_info("Default Flow Context Read OK\n"); ++ /* start a NOP */ ++ ret = pme_ctx_ctrl_nop(&ctx, 0, &ctx_ctrl.ctx_ctr); ++ pr_info("PME2: pme_ctx_ctrl_nop done\n"); ++ wait_for_completion(&ctx_ctrl.cb_done); ++ POST_CTRL(post_ctrl); ++ if (post_ctrl) ++ goto disable_ctx; ++ /* start an update to add residue to the context */ ++ flow.ren = 1; ++ ret = pme_ctx_ctrl_update_flow(&ctx, PME_CTX_OP_WAIT | PME_CMD_FCW_RES, ++ &flow, &ctx_ctrl.ctx_ctr); ++ pr_info("PME2: pme_ctx_ctrl_update_flow done\n"); ++ wait_for_completion(&ctx_ctrl.cb_done); ++ POST_CTRL(post_ctrl); ++ if (post_ctrl) ++ goto disable_ctx; ++ /* start a blocking disable */ ++ ret = pme_ctx_disable(&ctx, PME_CTX_OP_WAIT, &ctx_ctrl.ctx_ctr); ++ if (ret < 1) { ++ post_ctrl = -1; ++ goto finish_ctx; ++ } ++ wait_for_completion(&ctx_ctrl.cb_done); ++ /* do some reconfiguration */ ++ ret = pme_ctx_reconfigure_tx(&ctx, 63, 7); ++ if (ret) { ++ post_ctrl = -1; ++ goto finish_ctx; ++ } ++ stashing.exclusive = 0; ++ stashing.annotation_cl = 0; ++ stashing.data_cl = 2; ++ stashing.context_cl = 2; ++ ret = pme_ctx_reconfigure_rx(&ctx, 7, 0, &stashing); ++ if (ret) { ++ post_ctrl = -1; ++ goto finish_ctx; ++ } ++ /* reenable */ ++ ret = pme_ctx_enable(&ctx); ++ if (ret) { ++ post_ctrl = -1; ++ goto finish_ctx; ++ } ++ /* read back flow settings */ ++ ret = pme_ctx_ctrl_read_flow(&ctx, ++ PME_CTX_OP_WAIT | PME_CTX_OP_WAIT_INT | PME_CMD_FCW_RES, &flow, ++ &ctx_ctrl.ctx_ctr); ++ pr_info("PME2: pme_ctx_ctrl_read_flow done\n"); ++ wait_for_completion(&ctx_ctrl.cb_done); ++ POST_CTRL(post_ctrl); ++ if (post_ctrl) ++ goto disable_ctx; ++ /* blocking NOP */ ++ ret = pme_ctx_ctrl_nop(&ctx, PME_CTX_OP_WAIT | PME_CTX_OP_WAIT_INT, ++ &ctx_ctrl.ctx_ctr); ++ pr_info("PME2: pme_ctx_ctrl_nop done\n"); ++ wait_for_completion(&ctx_ctrl.cb_done); ++ POST_CTRL(post_ctrl); ++ /* Disable, and done */ ++disable_ctx: ++ ret = pme_ctx_disable(&ctx, PME_CTX_OP_WAIT, &ctx_ctrl.ctx_ctr); ++ BUG_ON(ret < 1); ++ wait_for_completion(&ctx_ctrl.cb_done); ++finish_ctx: ++ pme_ctx_finish(&ctx); ++restore_mask: ++ ret = set_cpus_allowed_ptr(current, &backup_mask); ++ if (ret) { ++ pr_err("PME2 test high: can't restore cpumask"); ++ post_ctrl = -1; ++ } ++done: ++ if (post_ctrl) ++ pr_info("PME2: high-level test failed\n"); ++ else ++ pr_info("PME2: high-level test passed\n"); ++} ++ ++static int pme2_test_high_init(void) ++{ ++ int big_loop = 2; ++ while (big_loop--) ++ pme2_test_high(); ++ return 0; ++} ++ ++static void pme2_test_high_exit(void) ++{ ++} ++ ++module_init(pme2_test_high_init); ++module_exit(pme2_test_high_exit); +diff --git a/drivers/staging/fsl_pme2/pme2_test_scan.c b/drivers/staging/fsl_pme2/pme2_test_scan.c +new file mode 100644 +index 0000000..65608db +--- /dev/null ++++ b/drivers/staging/fsl_pme2/pme2_test_scan.c +@@ -0,0 +1,653 @@ ++/* Copyright 2009-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "pme2_test.h" ++ ++enum scan_ctrl_mode { ++ no_scan = 0, ++ do_scan = 1, ++}; ++ ++enum db_ctrl_mode { ++ create_destroy = 0, ++ create = 1, ++ destroy = 2, ++ nothing = 3 ++}; ++ ++MODULE_AUTHOR("Jeffrey Ladouceur"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("PME scan testing"); ++ ++static enum db_ctrl_mode db_ctrl; ++module_param(db_ctrl, uint, 0644); ++MODULE_PARM_DESC(db_ctrl, "PME Database control"); ++ ++static enum scan_ctrl_mode scan_ctrl = 1; ++module_param(scan_ctrl, uint, 0644); ++MODULE_PARM_DESC(scan_ctrl, "Scan control"); ++ ++static u8 scan_result_direct_mode_inc_mode[] = { ++ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 ++}; ++ ++static u8 fl_ctx_exp[] = { ++ 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe0, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 ++}; ++ ++/* same again with 'sos' bit cleared */ ++static u8 fl_ctx_exp_post_scan[] = { ++ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe0, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 ++}; ++ ++struct scan_ctx { ++ struct pme_ctx base_ctx; ++ struct qm_fd result_fd; ++}; ++ ++struct ctrl_op { ++ struct pme_ctx_ctrl_token ctx_ctr; ++ struct completion cb_done; ++ enum pme_status cmd_status; ++ u8 res_flag; ++}; ++ ++static void ctrl_cb(struct pme_ctx *ctx, const struct qm_fd *fd, ++ struct pme_ctx_ctrl_token *token) ++{ ++ struct ctrl_op *ctrl = (struct ctrl_op *)token; ++ ctrl->cmd_status = pme_fd_res_status(fd); ++ ctrl->res_flag = pme_fd_res_flags(fd) & PME_STATUS_UNRELIABLE; ++ /* hexdump(fd, sizeof(*fd)); */ ++ complete(&ctrl->cb_done); ++} ++ ++static DECLARE_COMPLETION(scan_comp); ++ ++static void scan_cb(struct pme_ctx *ctx, const struct qm_fd *fd, ++ struct pme_ctx_token *ctx_token) ++{ ++ struct scan_ctx *my_ctx = (struct scan_ctx *)ctx; ++ memcpy(&my_ctx->result_fd, fd, sizeof(*fd)); ++ complete(&scan_comp); ++} ++ ++#ifdef CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID ++ ++static struct bman_pool *pool; ++static u32 pme_bpid; ++static void *bman_buffers_virt_base; ++static dma_addr_t bman_buffers_phys_base; ++ ++static void release_buffer(dma_addr_t addr) ++{ ++ struct bm_buffer bufs_in; ++ bm_buffer_set64(&bufs_in, addr); ++ if (bman_release(pool, &bufs_in, 1, BMAN_RELEASE_FLAG_WAIT)) ++ panic("bman_release() failed\n"); ++} ++ ++static void empty_buffer(void) ++{ ++ struct bm_buffer bufs_in; ++ int ret; ++ ++ do { ++ ret = bman_acquire(pool, &bufs_in, 1, 0); ++ } while (!ret); ++} ++#endif /*CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID*/ ++ ++static int scan_test_direct(int trunc, int use_bp) ++{ ++ struct scan_ctx a_scan_ctx = { ++ .base_ctx = { ++ .cb = scan_cb ++ } ++ }; ++ struct ctrl_op ctx_ctrl = { ++ .ctx_ctr.cb = ctrl_cb, ++ .cmd_status = 0, ++ .res_flag = 0 ++ }; ++ struct qm_fd fd; ++ struct qm_sg_entry sg_table[2]; ++ int ret; ++ enum pme_status status; ++ struct pme_ctx_token token; ++ u8 *scan_result; ++ u32 scan_result_size; ++ u8 scan_data[] = { ++ 0x41, 0x42, 0x43, 0x44, 0x45 ++ }; ++ u8 result_data[] = { ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00 ++ }; ++ ++ init_completion(&ctx_ctrl.cb_done); ++ scan_result = scan_result_direct_mode_inc_mode; ++ scan_result_size = sizeof(scan_result_direct_mode_inc_mode); ++ ++ ret = pme_ctx_init(&a_scan_ctx.base_ctx, ++ PME_CTX_FLAG_DIRECT | PME_CTX_FLAG_LOCAL, ++ 0, 4, 4, 0, NULL); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ return ret; ++ } ++ /* enable the context */ ++ ret = pme_ctx_enable(&a_scan_ctx.base_ctx); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto ctx_finish; ++ } ++ ++ /* Do a pre-built output, scan with match test */ ++ /* Build a frame descriptor */ ++ memset(&fd, 0, sizeof(struct qm_fd)); ++ memset(&sg_table, 0, sizeof(sg_table)); ++ ++ if (trunc) { ++ fd.length20 = sizeof(scan_data); ++ qm_fd_addr_set64(&fd, pme_map(scan_data)); ++ } else { ++ /* build the result */ ++ qm_sg_entry_set64(&sg_table[0], pme_map(result_data)); ++ sg_table[0].length = sizeof(result_data); ++ qm_sg_entry_set64(&sg_table[1], pme_map(scan_data)); ++ sg_table[1].length = sizeof(scan_data); ++ sg_table[1].final = 1; ++ fd._format2 = qm_fd_compound; ++ qm_fd_addr_set64(&fd, pme_map(sg_table)); ++ } ++ ++ ret = pme_ctx_scan(&a_scan_ctx.base_ctx, 0, &fd, ++ PME_SCAN_ARGS(PME_CMD_SCAN_SR | PME_CMD_SCAN_E, 0, 0xff00), ++ &token); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto ctx_disable; ++ } ++ wait_for_completion(&scan_comp); ++ ++ status = pme_fd_res_status(&a_scan_ctx.result_fd); ++ if (status) { ++ pr_err("pme scan test failed 0x%x\n", status); ++ goto ctx_disable; ++ } ++ if (trunc) { ++ int res_flag = pme_fd_res_flags(&a_scan_ctx.result_fd); ++ /* Check the response...expect truncation bit to be set */ ++ if (!(res_flag & PME_STATUS_TRUNCATED)) { ++ pr_err("pme scan test failed, expected truncation\n"); ++ goto ctx_disable; ++ } ++ } else { ++ if (memcmp(scan_result, result_data, scan_result_size) != 0) { ++ pr_err("pme scan test result not expected\n"); ++ hexdump(scan_result, scan_result_size); ++ pr_err("Received...\n"); ++ hexdump(result_data, sizeof(result_data)); ++ goto ctx_disable; ++ } ++ } ++ ++ ret = pme_ctx_disable(&a_scan_ctx.base_ctx, PME_CTX_OP_WAIT, NULL); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto ctx_finish; ++ } ++ if (!use_bp) { ++ pme_ctx_finish(&a_scan_ctx.base_ctx); ++ return 0; ++ } ++ /* use buffer pool */ ++ /* Check with bman */ ++ /* reconfigure */ ++ ++#ifdef CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID ++ ret = pme_ctx_reconfigure_tx(&a_scan_ctx.base_ctx, pme_bpid, 5); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto ctx_finish; ++ } ++ ret = pme_ctx_enable(&a_scan_ctx.base_ctx); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto ctx_finish; ++ } ++ /* Do a pre-built output, scan with match test */ ++ /* Build a frame descriptor */ ++ memset(&fd, 0, sizeof(struct qm_fd)); ++ memset(&sg_table, 0, sizeof(sg_table)); ++ ++ /* build the result */ ++ /* result is all zero...use bman */ ++ qm_sg_entry_set64(&sg_table[1], pme_map(scan_data)); ++ sg_table[1].length = sizeof(scan_data); ++ sg_table[1].final = 1; ++ ++ fd._format2 = qm_fd_compound; ++ qm_fd_addr_set64(&fd, pme_map(sg_table)); ++ ++ ret = pme_ctx_scan(&a_scan_ctx.base_ctx, 0, &fd, ++ PME_SCAN_ARGS(PME_CMD_SCAN_SR | PME_CMD_SCAN_E, 0, 0xff00), ++ &token); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto ctx_disable; ++ } ++ wait_for_completion(&scan_comp); ++ ++ status = pme_fd_res_status(&a_scan_ctx.result_fd); ++ if (status) { ++ pr_err("pme scan test failed 0x%x\n", status); ++ goto ctx_disable; ++ } ++ /* sg result should point to bman buffer */ ++ if (!qm_sg_entry_get64(&sg_table[0])) { ++ pr_err("pme scan test failed, sg result not bman buffer\n"); ++ goto ctx_disable; ++ } ++ if (memcmp(scan_result, bman_buffers_virt_base, scan_result_size) ++ != 0) { ++ pr_err("pme scan test not expected, Expected\n"); ++ hexdump(scan_result, scan_result_size); ++ pr_err("Received...\n"); ++ hexdump(bman_buffers_virt_base, scan_result_size); ++ release_buffer(qm_sg_entry_get64(&sg_table[0])); ++ goto ctx_disable; ++ } ++ release_buffer(qm_sg_entry_get64(&sg_table[0])); ++ ret = pme_ctx_disable(&a_scan_ctx.base_ctx, PME_CTX_OP_WAIT, NULL); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto ctx_finish; ++ } ++ pme_ctx_finish(&a_scan_ctx.base_ctx); ++ return 0; ++#endif ++ ++/* failure path */ ++ctx_disable: ++ ret = pme_ctx_disable(&a_scan_ctx.base_ctx, PME_CTX_OP_WAIT, NULL); ++ctx_finish: ++ pme_ctx_finish(&a_scan_ctx.base_ctx); ++ return (!ret) ? -EINVAL : ret; ++} ++ ++static int scan_test_flow(void) ++{ ++ struct pme_flow flow; ++ struct pme_flow rb_flow; ++ struct scan_ctx a_scan_ctx = { ++ .base_ctx = { ++ .cb = scan_cb ++ } ++ }; ++ struct ctrl_op ctx_ctrl = { ++ .ctx_ctr.cb = ctrl_cb, ++ .cmd_status = 0, ++ .res_flag = 0 ++ }; ++ struct qm_fd fd; ++ struct qm_sg_entry sg_table[2]; ++ int ret; ++ enum pme_status status; ++ struct pme_ctx_token token; ++ u8 *scan_result; ++ u32 scan_result_size; ++ u8 scan_data[] = { ++ 0x41, 0x42, 0x43, 0x44, 0x45 ++ }; ++ u8 result_data[] = { ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00 ++ }; ++ ++ pme_sw_flow_init(&flow); ++ init_completion(&ctx_ctrl.cb_done); ++ scan_result = scan_result_direct_mode_inc_mode; ++ scan_result_size = sizeof(scan_result_direct_mode_inc_mode); ++ ++ ret = pme_ctx_init(&a_scan_ctx.base_ctx, ++ PME_CTX_FLAG_LOCAL, 0, 4, 4, 0, NULL); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ return ret; ++ } ++ /* enable the context */ ++ ret = pme_ctx_enable(&a_scan_ctx.base_ctx); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto flow_ctx_finish; ++ } ++ ret = pme_ctx_ctrl_update_flow(&a_scan_ctx.base_ctx, ++ PME_CTX_OP_WAIT | PME_CMD_FCW_ALL, &flow, &ctx_ctrl.ctx_ctr); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto flow_ctx_disable; ++ } ++ wait_for_completion(&ctx_ctrl.cb_done); ++ if (ctx_ctrl.cmd_status || ctx_ctrl.res_flag) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto flow_ctx_disable; ++ } ++ /* read back flow settings */ ++ ret = pme_ctx_ctrl_read_flow(&a_scan_ctx.base_ctx, ++ PME_CTX_OP_WAIT, &rb_flow, &ctx_ctrl.ctx_ctr); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto flow_ctx_disable; ++ } ++ wait_for_completion(&ctx_ctrl.cb_done); ++ if (ctx_ctrl.cmd_status || ctx_ctrl.res_flag) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto flow_ctx_disable; ++ } ++ if (memcmp(&rb_flow, fl_ctx_exp, sizeof(rb_flow)) != 0) { ++ pr_err("pme scan test Flow Context Read FAIL\n"); ++ pr_err("Expected\n"); ++ hexdump(fl_ctx_exp, sizeof(fl_ctx_exp)); ++ pr_err("Received...\n"); ++ hexdump(&rb_flow, sizeof(rb_flow)); ++ goto flow_ctx_disable; ++ } ++ ++ /* Do a pre-built output, scan with match test */ ++ /* Build a frame descriptor */ ++ memset(&fd, 0, sizeof(struct qm_fd)); ++ memset(&sg_table, 0, sizeof(sg_table)); ++ ++ /* build the result */ ++ qm_sg_entry_set64(&sg_table[0], pme_map(result_data)); ++ sg_table[0].length = sizeof(result_data); ++ qm_sg_entry_set64(&sg_table[1], pme_map(scan_data)); ++ sg_table[1].length = sizeof(scan_data); ++ sg_table[1].final = 1; ++ ++ fd._format2 = qm_fd_compound; ++ qm_fd_addr_set64(&fd, pme_map(sg_table)); ++ ++ ret = pme_ctx_scan(&a_scan_ctx.base_ctx, 0, &fd, ++ PME_SCAN_ARGS(PME_CMD_SCAN_SR | PME_CMD_SCAN_E, 0, 0xff00), ++ &token); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto flow_ctx_disable; ++ } ++ wait_for_completion(&scan_comp); ++ ++ status = pme_fd_res_status(&a_scan_ctx.result_fd); ++ if (status) { ++ pr_err("pme scan test failed 0x%x\n", status); ++ goto flow_ctx_disable; ++ } ++ ++ if (memcmp(scan_result, result_data, scan_result_size) != 0) { ++ pr_err("pme scan test result not expected\n"); ++ hexdump(scan_result, scan_result_size); ++ pr_err("Received...\n"); ++ hexdump(result_data, sizeof(result_data)); ++ goto flow_ctx_disable; ++ } ++ ++ /* read back flow settings */ ++ ret = pme_ctx_ctrl_read_flow(&a_scan_ctx.base_ctx, ++ PME_CTX_OP_WAIT, &rb_flow, &ctx_ctrl.ctx_ctr); ++ if (ret) { ++ pr_err("pme scan test failed 0x%x\n", status); ++ goto flow_ctx_disable; ++ } ++ wait_for_completion(&ctx_ctrl.cb_done); ++ if (ctx_ctrl.cmd_status || ctx_ctrl.res_flag) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto flow_ctx_disable; ++ } ++ if (memcmp(&rb_flow, fl_ctx_exp_post_scan, sizeof(rb_flow)) != 0) { ++ pr_err("pme scan test Flow Context Read FAIL\n"); ++ pr_err("Expected\n"); ++ hexdump(fl_ctx_exp_post_scan, sizeof(fl_ctx_exp_post_scan)); ++ pr_err("Received\n"); ++ hexdump(&rb_flow, sizeof(rb_flow)); ++ goto flow_ctx_disable; ++ } ++ ++ /* Test truncation test */ ++ /* Build a frame descriptor */ ++ memset(&fd, 0, sizeof(struct qm_fd)); ++ ++ fd.length20 = sizeof(scan_data); ++ qm_fd_addr_set64(&fd, pme_map(scan_data)); ++ ++ ret = pme_ctx_scan(&a_scan_ctx.base_ctx, 0, &fd, ++ PME_SCAN_ARGS(PME_CMD_SCAN_SR | PME_CMD_SCAN_E, 0, 0xff00), ++ &token); ++ if (ret) { ++ pr_err("pme scan test failed 0x%x\n", status); ++ goto flow_ctx_disable; ++ } ++ wait_for_completion(&scan_comp); ++ ++ status = pme_fd_res_status(&a_scan_ctx.result_fd); ++ if (status) { ++ pr_err("pme scan test failed 0x%x\n", status); ++ goto flow_ctx_disable; ++ } ++ /* Check the response...expect truncation bit to be set */ ++ if (!(pme_fd_res_flags(&a_scan_ctx.result_fd) & PME_STATUS_TRUNCATED)) { ++ pr_err("st: Scan result failed...expected trunc\n"); ++ goto flow_ctx_disable; ++ } ++ ++ /* read back flow settings */ ++ ret = pme_ctx_ctrl_read_flow(&a_scan_ctx.base_ctx, ++ PME_CTX_OP_WAIT, &rb_flow, &ctx_ctrl.ctx_ctr); ++ if (ret) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto flow_ctx_disable; ++ } ++ wait_for_completion(&ctx_ctrl.cb_done); ++ if (ctx_ctrl.cmd_status || ctx_ctrl.res_flag) { ++ pr_err("pme scan test failed: 0x%x\n", ret); ++ goto flow_ctx_disable; ++ } ++ if (memcmp(&rb_flow, fl_ctx_exp_post_scan, sizeof(rb_flow)) != 0) { ++ pr_err("pme scan test Flow Context Read FAIL\n"); ++ pr_err("Expected\n"); ++ hexdump(fl_ctx_exp_post_scan, sizeof(fl_ctx_exp_post_scan)); ++ pr_err("Received\n"); ++ hexdump(&rb_flow, sizeof(rb_flow)); ++ goto flow_ctx_disable; ++ } ++ ++ /* Disable */ ++ ret = pme_ctx_disable(&a_scan_ctx.base_ctx, PME_CTX_OP_WAIT, ++ &ctx_ctrl.ctx_ctr); ++ if (ret < 1) { ++ pr_err("pme scan test failed 0x%x\n", ret); ++ goto flow_ctx_finish; ++ } ++ wait_for_completion(&ctx_ctrl.cb_done); ++ pme_ctx_finish(&a_scan_ctx.base_ctx); ++ return 0; ++ /* error path */ ++/* failure path */ ++flow_ctx_disable: ++ ret = pme_ctx_disable(&a_scan_ctx.base_ctx, PME_CTX_OP_WAIT, NULL); ++flow_ctx_finish: ++ pme_ctx_finish(&a_scan_ctx.base_ctx); ++ return (!ret) ? -EINVAL : ret; ++} ++ ++void pme2_test_scan(void) ++{ ++ int ret; ++ ++ ret = scan_test_direct(0, 0); ++ if (ret) ++ goto done; ++ ret = scan_test_direct(1, 0); ++ if (ret) ++ goto done; ++#ifdef CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID ++ ret = scan_test_direct(0, 1); ++ if (ret) ++ goto done; ++#endif ++ ret = scan_test_flow(); ++done: ++ if (ret) ++ pr_info("pme scan test FAILED 0x%x\n", ret); ++ else ++ pr_info("pme Scan Test Passed\n"); ++} ++ ++static int setup_buffer_pool(void) ++{ ++#ifdef CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID ++ u32 bpid_size = CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID_SIZE; ++ struct bman_pool_params pparams = { ++ .flags = BMAN_POOL_FLAG_DYNAMIC_BPID, ++ .thresholds = { ++ 0, ++ 0, ++ 0, ++ 0 ++ } ++ }; ++ ++ if (!pme2_have_control()) { ++ pr_err("pme scan test: Not the ctrl-plane\n"); ++ return -EINVAL; ++ } ++ pool = bman_new_pool(&pparams); ++ if (!pool) { ++ pr_err("pme scan test: can't get buffer pool\n"); ++ return -EINVAL; ++ } ++ pme_bpid = bman_get_params(pool)->bpid; ++ bman_buffers_virt_base = kmalloc(1<<(bpid_size+5), GFP_KERNEL); ++ bman_buffers_phys_base = pme_map(bman_buffers_virt_base); ++ if (pme_map_error(bman_buffers_phys_base)) { ++ pr_info("pme scan test: pme_map_error\n"); ++ bman_free_pool(pool); ++ kfree(bman_buffers_virt_base); ++ return -ENODEV; ++ } ++ release_buffer(bman_buffers_phys_base); ++ /* Configure the buffer pool */ ++ pme_attr_set(pme_attr_bsc(pme_bpid), bpid_size); ++ /* realease to the specified buffer pool */ ++ return 0; ++#endif ++ return 0; ++} ++ ++static int teardown_buffer_pool(void) ++{ ++#ifdef CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID ++ pme_attr_set(pme_attr_bsc(pme_bpid), 0); ++ empty_buffer(); ++ bman_free_pool(pool); ++ kfree(bman_buffers_virt_base); ++#endif ++ return 0; ++} ++ ++static int pme2_test_scan_init(void) ++{ ++ int big_loop = 2; ++ int ret = 0; ++ struct cpumask backup_mask = current->cpus_allowed; ++ struct cpumask new_mask = *qman_affine_cpus(); ++ ++ cpumask_and(&new_mask, &new_mask, bman_affine_cpus()); ++ ret = set_cpus_allowed_ptr(current, &new_mask); ++ if (ret) { ++ pr_info("pme scan test: can't set cpumask\n"); ++ goto done_all; ++ } ++ ++ ret = setup_buffer_pool(); ++ if (ret) ++ goto done_cpu_mask; ++ ++ /* create sample database */ ++ if (db_ctrl == create_destroy || db_ctrl == create) { ++ if (!pme2_have_control()) { ++ pr_err("pme scan test: Not the ctrl-plane\n"); ++ ret = -EINVAL; ++ goto done_scan; ++ } ++ if (pme2_sample_db()) { ++ pr_err("pme scan test: error creating db\n"); ++ goto done_scan; ++ } ++ } ++ ++ if (scan_ctrl == do_scan) { ++ while (big_loop--) ++ pme2_test_scan(); ++ } ++ ++ if (db_ctrl == create_destroy || db_ctrl == destroy) { ++ /* Clear database */ ++ if (pme2_clear_sample_db()) ++ pr_err("pme scan test: error clearing db\n"); ++ } ++ ++done_scan: ++ teardown_buffer_pool(); ++done_cpu_mask: ++ ret = set_cpus_allowed_ptr(current, &backup_mask); ++ if (ret) ++ pr_err("PME2 test high: can't restore cpumask"); ++done_all: ++ return ret; ++} ++ ++static void pme2_test_scan_exit(void) ++{ ++} ++ ++module_init(pme2_test_scan_init); ++module_exit(pme2_test_scan_exit); +diff --git a/drivers/staging/fsl_qbman/Kconfig b/drivers/staging/fsl_qbman/Kconfig +new file mode 100644 +index 0000000..1c3906b +--- /dev/null ++++ b/drivers/staging/fsl_qbman/Kconfig +@@ -0,0 +1,232 @@ ++config FSL_DPA ++ bool "Freescale Datapath Queue and Buffer management" ++ depends on HAS_FSL_QBMAN ++ default y ++ select FSL_QMAN_FQ_LOOKUP if PPC64 ++ ++menu "Freescale Datapath QMan/BMan options" ++ depends on FSL_DPA ++ ++config FSL_DPA_CHECKING ++ bool "additional driver checking" ++ default n ++ ---help--- ++ Compiles in additional checks to sanity-check the drivers and any ++ use of it by other code. Not recommended for performance. ++ ++config FSL_DPA_CAN_WAIT ++ bool ++ default y ++ ++config FSL_DPA_CAN_WAIT_SYNC ++ bool ++ default y ++ ++config FSL_DPA_PIRQ_FAST ++ bool ++ default y ++ ++config FSL_DPA_PIRQ_SLOW ++ bool ++ default y ++ ++config FSL_DPA_PORTAL_SHARE ++ bool ++ default y ++ ++config FSL_DPA_UIO ++ tristate "export USDPAA portals via UIO" ++ depends on UIO ++ default y ++ ---help--- ++ Any portals unused by the kernel are exported as UIO devices for ++ use by USDPAA (User Space DataPath Acceleration Architecture) ++ applications. ++ ++config FSL_BMAN ++ bool "Freescale Buffer Manager (BMan) support" ++ default y ++ ++if FSL_BMAN ++ ++config FSL_BMAN_CONFIG ++ bool "BMan device management" ++ default y ++ ---help--- ++ If this linux image is running natively, you need this option. If this ++ linux image is running as a guest OS under the hypervisor, only one ++ guest OS ("the control plane") needs this option. ++ ++config FSL_BMAN_TEST ++ tristate "BMan self-tests" ++ default n ++ ---help--- ++ This option compiles self-test code for BMan. ++ ++config FSL_BMAN_TEST_HIGH ++ bool "BMan high-level self-test" ++ depends on FSL_BMAN_TEST ++ default y ++ ---help--- ++ This requires the presence of cpu-affine portals, and performs ++ high-level API testing with them (whichever portal(s) are affine to ++ the cpu(s) the test executes on). ++ ++config FSL_BMAN_TEST_THRESH ++ bool "BMan threshold test" ++ depends on FSL_BMAN_TEST ++ default y ++ ---help--- ++ Multi-threaded (SMP) test of BMan pool depletion. A pool is seeded ++ before multiple threads (one per cpu) create pool objects to track ++ depletion state changes. The pool is then drained to empty by a ++ "drainer" thread, and the other threads that they observe exactly ++ the depletion state changes that are expected. ++ ++config FSL_BMAN_DEBUGFS ++ tristate "BMan debugfs interface" ++ depends on DEBUG_FS ++ default y ++ ---help--- ++ This option compiles debugfs code for BMan. ++ ++endif # FSL_BMAN ++ ++config FSL_QMAN ++ bool "Freescale Queue Manager (QMan) support" ++ default y ++ ++if FSL_QMAN ++ ++config FSL_QMAN_BUG_AND_FEATURE_REV1 ++ bool "workarounds for errata and missing features in p4080 rev1" ++ default y ++ ---help--- ++ If this option is selected, the driver will be compiled with ++ workarounds for errata as well as feature limitations (relative to ++ more recent parts) of p4080 rev1. On unaffected revisions, this ++ support incurs only a negligable overhead, typically only a couple of ++ instructions per non-fast-path operation (the fast-path operations are ++ unaffected). ++ ++ If in doubt, say Y. ++ ++config FSL_QMAN_POLL_LIMIT ++ int ++ default 32 ++ ++config FSL_QMAN_CONFIG ++ bool "QMan device management" ++ default y ++ ---help--- ++ If this linux image is running natively, you need this option. If this ++ linux image is running as a guest OS under the hypervisor, only one ++ guest OS ("the control plane") needs this option. ++ ++config FSL_QMAN_TEST ++ tristate "QMan self-tests" ++ default n ++ ---help--- ++ This option compiles self-test code for QMan. ++ ++config FSL_QMAN_TEST_STASH_POTATO ++ bool "QMan 'hot potato' data-stashing self-test" ++ depends on FSL_QMAN_TEST ++ default y ++ ---help--- ++ This performs a "hot potato" style test enqueuing/dequeuing a frame ++ across a series of FQs scheduled to different portals (and cpus), with ++ DQRR, data and context stashing always on. ++ ++config FSL_QMAN_TEST_HIGH ++ bool "QMan high-level self-test" ++ depends on FSL_QMAN_TEST ++ default y ++ ---help--- ++ This requires the presence of cpu-affine portals, and performs ++ high-level API testing with them (whichever portal(s) are affine to ++ the cpu(s) the test executes on). ++ ++config FSL_QMAN_TEST_ERRATA ++ bool "QMan errata-handling self-test" ++ depends on FSL_QMAN_TEST ++ default y ++ ---help--- ++ This requires the presence of cpu-affine portals, and performs ++ testing that handling for known hardware-errata is correct. ++ ++config FSL_QMAN_DEBUGFS ++ tristate "QMan debugfs interface" ++ depends on DEBUG_FS ++ default y ++ ---help--- ++ This option compiles debugfs code for QMan. ++ ++# H/w settings that can be hard-coded for now. ++config FSL_QMAN_FQD_SZ ++ int "size of Frame Queue Descriptor region" ++ default 10 ++ ---help--- ++ This is the size of the FQD region defined as: PAGE_SIZE * (2^value) ++ ex: 10 => PAGE_SIZE * (2^10) ++ Note: Default device-trees now require minimum Kconfig setting of 10. ++ ++config FSL_QMAN_PFDR_SZ ++ int "size of the PFDR pool" ++ default 13 ++ ---help--- ++ This is the size of the PFDR pool defined as: PAGE_SIZE * (2^value) ++ ex: 13 => PAGE_SIZE * (2^13) ++ ++# Corenet initiator settings. Stash request queues are 4-deep to match cores' ++# ability to snart. Stash priority is 3, other priorities are 2. ++config FSL_QMAN_CI_SCHED_CFG_SRCCIV ++ int ++ depends on FSL_QMAN_CONFIG ++ default 4 ++config FSL_QMAN_CI_SCHED_CFG_SRQ_W ++ int ++ depends on FSL_QMAN_CONFIG ++ default 3 ++config FSL_QMAN_CI_SCHED_CFG_RW_W ++ int ++ depends on FSL_QMAN_CONFIG ++ default 2 ++config FSL_QMAN_CI_SCHED_CFG_BMAN_W ++ int ++ depends on FSL_QMAN_CONFIG ++ default 2 ++ ++# portal interrupt settings ++config FSL_QMAN_PIRQ_DQRR_ITHRESH ++ int ++ default 12 ++config FSL_QMAN_PIRQ_MR_ITHRESH ++ int ++ default 4 ++config FSL_QMAN_PIRQ_IPERIOD ++ int ++ default 100 ++ ++# 64 bit kernel support ++config FSL_QMAN_FQ_LOOKUP ++ bool ++ default n ++ ++config QMAN_CEETM_UPDATE_PERIOD ++ int "Token update period for shaping, in nanoseconds" ++ default 1000 ++ ---help--- ++ Traffic shaping works by performing token calculations (using ++ credits) on shaper instances periodically. This update period ++ sets the granularity for how often those token rate credit ++ updates are performed, and thus determines the accuracy and ++ range of traffic rates that can be configured by users. The ++ reference manual recommends a 1 microsecond period as providing ++ a good balance between granularity and range. ++ ++ Unless you know what you are doing, leave this value at its default. ++ ++endif # FSL_QMAN ++ ++endmenu +diff --git a/drivers/staging/fsl_qbman/Makefile b/drivers/staging/fsl_qbman/Makefile +new file mode 100644 +index 0000000..330cdfb +--- /dev/null ++++ b/drivers/staging/fsl_qbman/Makefile +@@ -0,0 +1,25 @@ ++# Common ++obj-$(CONFIG_FSL_DPA) += dpa_alloc.o ++ ++# Bman ++obj-$(CONFIG_FSL_BMAN) += bman_high.o ++obj-$(CONFIG_FSL_BMAN_CONFIG) += bman_config.o bman_driver.o ++obj-$(CONFIG_FSL_BMAN_TEST) += bman_tester.o ++obj-$(CONFIG_FSL_BMAN_DEBUGFS) += bman_debugfs_interface.o ++bman_tester-y = bman_test.o ++bman_tester-$(CONFIG_FSL_BMAN_TEST_HIGH) += bman_test_high.o ++bman_tester-$(CONFIG_FSL_BMAN_TEST_THRESH) += bman_test_thresh.o ++bman_debugfs_interface-y = bman_debugfs.o ++ ++# Qman ++obj-$(CONFIG_FSL_QMAN) += qman_high.o qman_utility.o ++obj-$(CONFIG_FSL_QMAN_CONFIG) += qman_config.o qman_driver.o ++obj-$(CONFIG_FSL_QMAN_TEST) += qman_tester.o ++qman_tester-y = qman_test.o qman_test_hotpotato.o \ ++ qman_test_high.o ++qman_tester-$(CONFIG_FSL_QMAN_TEST_ERRATA) += qman_test_errata.o ++obj-$(CONFIG_FSL_QMAN_DEBUGFS) += qman_debugfs_interface.o ++qman_debugfs_interface-y = qman_debugfs.o ++ ++# USDPAA ++obj-$(CONFIG_FSL_DPA_UIO) += dpa_uio.o +diff --git a/drivers/staging/fsl_qbman/bman_config.c b/drivers/staging/fsl_qbman/bman_config.c +new file mode 100644 +index 0000000..4ea7418 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_config.c +@@ -0,0 +1,718 @@ ++/* Copyright (c) 2009-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 CONFIG_SMP ++#include /* get_hard_smp_processor_id() */ ++#endif ++ ++#include ++#include "bman_private.h" ++ ++/* Last updated for v00.79 of the BG */ ++ ++struct bman; ++ ++/* Register offsets */ ++#define REG_POOL_SWDET(n) (0x0000 + ((n) * 0x04)) ++#define REG_POOL_HWDET(n) (0x0100 + ((n) * 0x04)) ++#define REG_POOL_SWDXT(n) (0x0200 + ((n) * 0x04)) ++#define REG_POOL_HWDXT(n) (0x0300 + ((n) * 0x04)) ++#define REG_POOL_CONTENT(n) (0x0600 + ((n) * 0x04)) ++#define REG_FBPR_FPC 0x0800 ++#define REG_ECSR 0x0a00 ++#define REG_ECIR 0x0a04 ++#define REG_EADR 0x0a08 ++#define REG_EDATA(n) (0x0a10 + ((n) * 0x04)) ++#define REG_SBEC(n) (0x0a80 + ((n) * 0x04)) ++#define REG_IP_REV_1 0x0bf8 ++#define REG_IP_REV_2 0x0bfc ++#define REG_FBPR_BARE 0x0c00 ++#define REG_FBPR_BAR 0x0c04 ++#define REG_FBPR_AR 0x0c10 ++#define REG_SRCIDR 0x0d04 ++#define REG_LIODNR 0x0d08 ++#define REG_ERR_ISR 0x0e00 /* + "enum bm_isr_reg" */ ++ ++/* Used by all error interrupt registers except 'inhibit' */ ++#define BM_EIRQ_IVCI 0x00000010 /* Invalid Command Verb */ ++#define BM_EIRQ_FLWI 0x00000008 /* FBPR Low Watermark */ ++#define BM_EIRQ_MBEI 0x00000004 /* Multi-bit ECC Error */ ++#define BM_EIRQ_SBEI 0x00000002 /* Single-bit ECC Error */ ++#define BM_EIRQ_BSCN 0x00000001 /* pool State Change Notification */ ++ ++/* BMAN_ECIR valid error bit */ ++#define PORTAL_ECSR_ERR (BM_EIRQ_IVCI) ++ ++union bman_ecir { ++ u32 ecir_raw; ++ struct { ++ u32 __reserved1:4; ++ u32 portal_num:4; ++ u32 __reserved2:12; ++ u32 numb:4; ++ u32 __reserved3:2; ++ u32 pid:6; ++ } __packed info; ++}; ++ ++union bman_eadr { ++ u32 eadr_raw; ++ struct { ++ u32 __reserved1:5; ++ u32 memid:3; ++ u32 __reserved2:14; ++ u32 eadr:10; ++ } __packed info; ++}; ++ ++struct bman_hwerr_txt { ++ u32 mask; ++ const char *txt; ++}; ++ ++#define BMAN_HWE_TXT(a, b) { .mask = BM_EIRQ_##a, .txt = b } ++ ++static const struct bman_hwerr_txt bman_hwerr_txts[] = { ++ BMAN_HWE_TXT(IVCI, "Invalid Command Verb"), ++ BMAN_HWE_TXT(FLWI, "FBPR Low Watermark"), ++ BMAN_HWE_TXT(MBEI, "Multi-bit ECC Error"), ++ BMAN_HWE_TXT(SBEI, "Single-bit ECC Error"), ++ BMAN_HWE_TXT(BSCN, "Pool State Change Notification"), ++}; ++#define BMAN_HWE_COUNT (sizeof(bman_hwerr_txts)/sizeof(struct bman_hwerr_txt)) ++ ++struct bman_error_info_mdata { ++ u16 addr_mask; ++ u16 bits; ++ const char *txt; ++}; ++ ++#define BMAN_ERR_MDATA(a, b, c) { .addr_mask = a, .bits = b, .txt = c} ++static const struct bman_error_info_mdata error_mdata[] = { ++ BMAN_ERR_MDATA(0x03FF, 192, "Stockpile memory"), ++ BMAN_ERR_MDATA(0x00FF, 256, "SW portal ring memory port 1"), ++ BMAN_ERR_MDATA(0x00FF, 256, "SW portal ring memory port 2"), ++}; ++#define BMAN_ERR_MDATA_COUNT \ ++ (sizeof(error_mdata)/sizeof(struct bman_error_info_mdata)) ++ ++/* Add this in Kconfig */ ++#define BMAN_ERRS_TO_UNENABLE (BM_EIRQ_FLWI) ++ ++/** ++ * bm_err_isr__ - Manipulate global interrupt registers ++ * @v: for accessors that write values, this is the 32-bit value ++ * ++ * Manipulates BMAN_ERR_ISR, BMAN_ERR_IER, BMAN_ERR_ISDR, BMAN_ERR_IIR. All ++ * manipulations except bm_err_isr_[un]inhibit() use 32-bit masks composed of ++ * the BM_EIRQ_*** definitions. Note that "bm_err_isr_enable_write" means ++ * "write the enable register" rather than "enable the write register"! ++ */ ++#define bm_err_isr_status_read(bm) __bm_err_isr_read(bm, bm_isr_status) ++#define bm_err_isr_status_clear(bm, m) __bm_err_isr_write(bm, bm_isr_status,m) ++#define bm_err_isr_enable_read(bm) __bm_err_isr_read(bm, bm_isr_enable) ++#define bm_err_isr_enable_write(bm, v) __bm_err_isr_write(bm, bm_isr_enable,v) ++#define bm_err_isr_disable_read(bm) __bm_err_isr_read(bm, bm_isr_disable) ++#define bm_err_isr_disable_write(bm, v) __bm_err_isr_write(bm, bm_isr_disable,v) ++#define bm_err_isr_inhibit(bm) __bm_err_isr_write(bm, bm_isr_inhibit,1) ++#define bm_err_isr_uninhibit(bm) __bm_err_isr_write(bm, bm_isr_inhibit,0) ++ ++/* ++ * TODO: unimplemented registers ++ * ++ * BMAN_POOLk_SDCNT, BMAN_POOLk_HDCNT, BMAN_FULT, ++ * BMAN_VLDPL, BMAN_EECC, BMAN_SBET, BMAN_EINJ ++ */ ++ ++/* Encapsulate "struct bman *" as a cast of the register space address. */ ++ ++static struct bman *bm_create(void *regs) ++{ ++ return (struct bman *)regs; ++} ++ ++static inline u32 __bm_in(struct bman *bm, u32 offset) ++{ ++ return in_be32((void *)bm + offset); ++} ++static inline void __bm_out(struct bman *bm, u32 offset, u32 val) ++{ ++ out_be32((void *)bm + offset, val); ++} ++#define bm_in(reg) __bm_in(bm, REG_##reg) ++#define bm_out(reg, val) __bm_out(bm, REG_##reg, val) ++ ++static u32 __bm_err_isr_read(struct bman *bm, enum bm_isr_reg n) ++{ ++ return __bm_in(bm, REG_ERR_ISR + (n << 2)); ++} ++ ++static void __bm_err_isr_write(struct bman *bm, enum bm_isr_reg n, u32 val) ++{ ++ __bm_out(bm, REG_ERR_ISR + (n << 2), val); ++} ++ ++#if 0 ++static void bm_get_details(struct bman *bm, u8 *int_options, u8 *errata, ++ u8 *conf_options) ++{ ++ u32 v = bm_in(IP_REV_1); ++ *int_options = (v >> 16) & 0xff; ++ *errata = (v >> 8) & 0xff; ++ *conf_options = v & 0xff; ++} ++ ++static u8 bm_get_corenet_sourceid(struct bman *bm) ++{ ++ return bm_in(SRCIDR); ++} ++ ++static void bm_set_liodn(struct bman *bm, u16 liodn) ++{ ++ bm_out(LIODNR, liodn & 0xfff); ++} ++ ++#endif ++ ++static void bm_get_version(struct bman *bm, u16 *id, u8 *major, u8 *minor) ++{ ++ u32 v = bm_in(IP_REV_1); ++ *id = (v >> 16); ++ *major = (v >> 8) & 0xff; ++ *minor = v & 0xff; ++} ++ ++static u32 __generate_thresh(u32 val, int roundup) ++{ ++ u32 e = 0; /* co-efficient, exponent */ ++ int oddbit = 0; ++ while(val > 0xff) { ++ oddbit = val & 1; ++ val >>= 1; ++ e++; ++ if(roundup && oddbit) ++ val++; ++ } ++ DPA_ASSERT(e < 0x10); ++ return (val | (e << 8)); ++} ++ ++static void bm_set_pool(struct bman *bm, u8 pool, u32 swdet, u32 swdxt, ++ u32 hwdet, u32 hwdxt) ++{ ++ DPA_ASSERT(pool < bman_pool_max); ++ bm_out(POOL_SWDET(pool), __generate_thresh(swdet, 0)); ++ bm_out(POOL_SWDXT(pool), __generate_thresh(swdxt, 1)); ++ bm_out(POOL_HWDET(pool), __generate_thresh(hwdet, 0)); ++ bm_out(POOL_HWDXT(pool), __generate_thresh(hwdxt, 1)); ++} ++ ++static void bm_set_memory(struct bman *bm, u64 ba, int prio, u32 size) ++{ ++ u32 exp = ilog2(size); ++ /* choke if size isn't within range */ ++ DPA_ASSERT((size >= 4096) && (size <= 1073741824) && ++ is_power_of_2(size)); ++ /* choke if '[e]ba' has lower-alignment than 'size' */ ++ DPA_ASSERT(!(ba & (size - 1))); ++ bm_out(FBPR_BARE, upper_32_bits(ba)); ++ bm_out(FBPR_BAR, lower_32_bits(ba)); ++ bm_out(FBPR_AR, (prio ? 0x40000000 : 0) | (exp - 1)); ++} ++ ++/*****************/ ++/* Config driver */ ++/*****************/ ++ ++/* TODO: Kconfig these? */ ++#define DEFAULT_FBPR_SZ (PAGE_SIZE << 12) ++ ++/* We support only one of these. */ ++static struct bman *bm; ++static struct device_node *bm_node; ++ ++/* And this state belongs to 'bm'. It is set during fsl_bman_init(), but used ++ * during bman_init_ccsr(). */ ++static dma_addr_t fbpr_a; ++static size_t fbpr_sz = DEFAULT_FBPR_SZ; ++ ++/* Parse the property to extract the memory location and size and ++ * memblock_reserve() it. If it isn't supplied, memblock_alloc() the default ++ * size. Also flush this memory range from data cache so that BMAN originated ++ * transactions for this memory region could be marked non-coherent. ++ */ ++static __init int parse_mem_property(struct device_node *node, const char *name, ++ dma_addr_t *addr, size_t *sz, int zero) ++{ ++ const u32 *pint; ++ int ret; ++ unsigned long vaddr; ++ ++ pint = of_get_property(node, name, &ret); ++ if (!pint || (ret != 16)) { ++ pr_info("No %s property '%s', using memblock_alloc(%016zx)\n", ++ node->full_name, name, *sz); ++ *addr = memblock_alloc(*sz, *sz); ++ vaddr = (unsigned long)phys_to_virt(*addr); ++ if (zero) ++ memset((void *)vaddr, 0, *sz); ++ flush_dcache_range(vaddr, vaddr + *sz); ++ return 0; ++ } ++ pr_info("Using %s property '%s'\n", node->full_name, name); ++ /* If using a "zero-pma", don't try to zero it, even if you asked */ ++ if (zero && of_find_property(node, "zero-pma", &ret)) { ++ pr_info(" it's a 'zero-pma', not zeroing from s/w\n"); ++ zero = 0; ++ } ++ *addr = ((u64)pint[0] << 32) | (u64)pint[1]; ++ *sz = ((u64)pint[2] << 32) | (u64)pint[3]; ++ /* Keep things simple, it's either all in the DRAM range or it's all ++ * outside. */ ++ if (*addr < memblock_end_of_DRAM()) { ++ BUG_ON((u64)*addr + (u64)*sz > memblock_end_of_DRAM()); ++ if (memblock_reserve(*addr, *sz) < 0) { ++ pr_err("Failed to reserve %s\n", name); ++ return -ENOMEM; ++ } ++ vaddr = (unsigned long)phys_to_virt(*addr); ++ if (zero) ++ memset((void *)vaddr, 0, *sz); ++ flush_dcache_range(vaddr, vaddr + *sz); ++ } else if (zero) { ++ /* map as cacheable, non-guarded */ ++ void *tmpp = ioremap_prot(*addr, *sz, 0); ++ memset(tmpp, 0, *sz); ++ vaddr = (unsigned long)tmpp; ++ flush_dcache_range(vaddr, vaddr + *sz); ++ iounmap(tmpp); ++ } ++ return 0; ++} ++ ++static int __init fsl_bman_init(struct device_node *node) ++{ ++ struct resource res; ++ u32 __iomem *regs; ++ const char *s; ++ int ret, standby = 0; ++ u16 id; ++ u8 major, minor; ++ ++ ret = of_address_to_resource(node, 0, &res); ++ if (ret) { ++ pr_err("Can't get %s property 'reg'\n", ++ node->full_name); ++ return ret; ++ } ++ s = of_get_property(node, "fsl,hv-claimable", &ret); ++ if (s && !strcmp(s, "standby")) ++ standby = 1; ++ if (!standby) { ++ ret = parse_mem_property(node, "fsl,bman-fbpr", ++ &fbpr_a, &fbpr_sz, 0); ++ BUG_ON(ret); ++ } ++ /* Global configuration */ ++ regs = ioremap(res.start, res.end - res.start + 1); ++ bm = bm_create(regs); ++ BUG_ON(!bm); ++ bm_node = node; ++ bm_get_version(bm, &id, &major, &minor); ++ pr_info("Bman ver:%04x,%02x,%02x\n", id, major, minor); ++ if ((major == 1) && (minor == 0)) { ++ bman_ip_rev = BMAN_REV10; ++ bman_pool_max = 64; ++ } else if ((major == 2) && (minor == 0)) { ++ bman_ip_rev = BMAN_REV20; ++ bman_pool_max = 8; ++ } else if ((major == 2) && (minor == 1)) { ++ bman_ip_rev = BMAN_REV21; ++ bman_pool_max = 64; ++ } else { ++ pr_warning("unknown Bman version, default to rev1.0\n"); ++ } ++ ++ if (standby) { ++ pr_info(" -> in standby mode\n"); ++ return 0; ++ } ++ return 0; ++} ++ ++int bman_have_ccsr(void) ++{ ++ return (bm ? 1 : 0); ++} ++ ++int bm_pool_set(u32 bpid, const u32 *thresholds) ++{ ++ if (!bm) ++ return -ENODEV; ++ bm_set_pool(bm, bpid, thresholds[0], thresholds[1], ++ thresholds[2], thresholds[3]); ++ return 0; ++} ++EXPORT_SYMBOL(bm_pool_set); ++ ++__init void bman_init_early(void) ++{ ++ struct device_node *dn; ++ int ret; ++ ++ for_each_compatible_node(dn, NULL, "fsl,bman") { ++ if (bm) ++ pr_err("%s: only one 'fsl,bman' allowed\n", ++ dn->full_name); ++ else { ++ if (!of_device_is_available(dn)) ++ continue; ++ ++ ret = fsl_bman_init(dn); ++ BUG_ON(ret); ++ } ++ } ++} ++ ++static void log_edata_bits(u32 bit_count) ++{ ++ u32 i, j, mask = 0xffffffff; ++ ++ pr_warning("Bman ErrInt, EDATA:\n"); ++ i = bit_count/32; ++ if (bit_count%32) { ++ i++; ++ mask = ~(mask << bit_count%32); ++ } ++ j = 16-i; ++ pr_warning(" 0x%08x\n", bm_in(EDATA(j)) & mask); ++ j++; ++ for (; j < 16; j++) ++ pr_warning(" 0x%08x\n", bm_in(EDATA(j))); ++} ++ ++static void log_additional_error_info(u32 isr_val, u32 ecsr_val) ++{ ++ union bman_ecir ecir_val; ++ union bman_eadr eadr_val; ++ ++ ecir_val.ecir_raw = bm_in(ECIR); ++ /* Is portal info valid */ ++ if (ecsr_val & PORTAL_ECSR_ERR) { ++ pr_warning("Bman ErrInt: SWP id %d, numb %d, pid %d\n", ++ ecir_val.info.portal_num, ecir_val.info.numb, ++ ecir_val.info.pid); ++ } ++ if (ecsr_val & (BM_EIRQ_SBEI|BM_EIRQ_MBEI)) { ++ eadr_val.eadr_raw = bm_in(EADR); ++ pr_warning("Bman ErrInt: EADR Memory: %s, 0x%x\n", ++ error_mdata[eadr_val.info.memid].txt, ++ error_mdata[eadr_val.info.memid].addr_mask ++ & eadr_val.info.eadr); ++ log_edata_bits(error_mdata[eadr_val.info.memid].bits); ++ } ++} ++ ++/* Bman interrupt handler */ ++static irqreturn_t bman_isr(int irq, void *ptr) ++{ ++ u32 isr_val, ier_val, ecsr_val, isr_mask, i; ++ ++ ier_val = bm_err_isr_enable_read(bm); ++ isr_val = bm_err_isr_status_read(bm); ++ ecsr_val = bm_in(ECSR); ++ isr_mask = isr_val & ier_val; ++ ++ if (!isr_mask) ++ return IRQ_NONE; ++ for (i = 0; i < BMAN_HWE_COUNT; i++) { ++ if (bman_hwerr_txts[i].mask & isr_mask) { ++ pr_warning("Bman ErrInt: %s\n", bman_hwerr_txts[i].txt); ++ if (bman_hwerr_txts[i].mask & ecsr_val) { ++ log_additional_error_info(isr_mask, ecsr_val); ++ /* Re-arm error capture registers */ ++ bm_out(ECSR, ecsr_val); ++ } ++ if (bman_hwerr_txts[i].mask & BMAN_ERRS_TO_UNENABLE) { ++ pr_devel("Bman un-enabling error 0x%x\n", ++ bman_hwerr_txts[i].mask); ++ ier_val &= ~bman_hwerr_txts[i].mask; ++ bm_err_isr_enable_write(bm, ier_val); ++ } ++ } ++ } ++ bm_err_isr_status_clear(bm, isr_val); ++ return IRQ_HANDLED; ++} ++ ++static int __bind_irq(void) ++{ ++ int ret, err_irq; ++ ++ err_irq = of_irq_to_resource(bm_node, 0, NULL); ++ if (err_irq == NO_IRQ) { ++ pr_info("Can't get %s property '%s'\n", bm_node->full_name, ++ "interrupts"); ++ return -ENODEV; ++ } ++ ret = request_irq(err_irq, bman_isr, IRQF_SHARED, "bman-err", bm_node); ++ if (ret) { ++ pr_err("request_irq() failed %d for '%s'\n", ret, ++ bm_node->full_name); ++ return -ENODEV; ++ } ++ /* Disable Buffer Pool State Change */ ++ bm_err_isr_disable_write(bm, BM_EIRQ_BSCN); ++ /* Write-to-clear any stale bits, (eg. starvation being asserted prior ++ * to resource allocation during driver init). */ ++ bm_err_isr_status_clear(bm, 0xffffffff); ++ /* Enable Error Interrupts */ ++ bm_err_isr_enable_write(bm, 0xffffffff); ++ return 0; ++} ++ ++int bman_init_ccsr(struct device_node *node) ++{ ++ int ret; ++ if (!bman_have_ccsr()) ++ return 0; ++ if (node != bm_node) ++ return -EINVAL; ++ /* FBPR memory */ ++ bm_set_memory(bm, fbpr_a, 0, fbpr_sz); ++ ret = __bind_irq(); ++ if (ret) ++ return ret; ++ return 0; ++} ++ ++u32 bm_pool_free_buffers(u32 bpid) ++{ ++ return bm_in(POOL_CONTENT(bpid)); ++} ++ ++#ifdef CONFIG_SYSFS ++ ++#define DRV_NAME "fsl-bman" ++ ++static ssize_t show_fbpr_fpc(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%u\n", bm_in(FBPR_FPC)); ++}; ++ ++static ssize_t show_pool_count(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ u32 data; ++ int i; ++ ++ if (!sscanf(dev_attr->attr.name, "%d", &i)) ++ return -EINVAL; ++ data = bm_in(POOL_CONTENT(i)); ++ return snprintf(buf, PAGE_SIZE, "%d\n", data); ++}; ++ ++static ssize_t show_err_isr(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "0x%08x\n", bm_in(ERR_ISR)); ++}; ++ ++static ssize_t show_sbec(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ int i; ++ ++ if (!sscanf(dev_attr->attr.name, "sbec_%d", &i)) ++ return -EINVAL; ++ return snprintf(buf, PAGE_SIZE, "%u\n", bm_in(SBEC(i))); ++}; ++ ++static DEVICE_ATTR(err_isr, S_IRUSR, show_err_isr, NULL); ++static DEVICE_ATTR(fbpr_fpc, S_IRUSR, show_fbpr_fpc, NULL); ++ ++/* Didn't use DEVICE_ATTR as 64 of this would be required. ++ * Initialize them when needed. */ ++static char *name_attrs_pool_count; /* "xx" + null-terminator */ ++static struct device_attribute *dev_attr_buffer_pool_count; ++ ++static DEVICE_ATTR(sbec_0, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_1, S_IRUSR, show_sbec, NULL); ++ ++static struct attribute *bman_dev_attributes[] = { ++ &dev_attr_fbpr_fpc.attr, ++ &dev_attr_err_isr.attr, ++ NULL ++}; ++ ++static struct attribute *bman_dev_ecr_attributes[] = { ++ &dev_attr_sbec_0.attr, ++ &dev_attr_sbec_1.attr, ++ NULL ++}; ++ ++static struct attribute **bman_dev_pool_count_attributes; ++ ++ ++/* root level */ ++static const struct attribute_group bman_dev_attr_grp = { ++ .name = NULL, ++ .attrs = bman_dev_attributes ++}; ++static const struct attribute_group bman_dev_ecr_grp = { ++ .name = "error_capture", ++ .attrs = bman_dev_ecr_attributes ++}; ++static struct attribute_group bman_dev_pool_countent_grp = { ++ .name = "pool_count", ++}; ++ ++static int of_fsl_bman_remove(struct platform_device *ofdev) ++{ ++ sysfs_remove_group(&ofdev->dev.kobj, &bman_dev_attr_grp); ++ return 0; ++}; ++ ++static int __devinit of_fsl_bman_probe(struct platform_device *ofdev) ++{ ++ int ret, i; ++ ++ ret = sysfs_create_group(&ofdev->dev.kobj, &bman_dev_attr_grp); ++ if (ret) ++ goto done; ++ ret = sysfs_create_group(&ofdev->dev.kobj, &bman_dev_ecr_grp); ++ if (ret) ++ goto del_group_0; ++ ++ name_attrs_pool_count = kmalloc(sizeof(char) * bman_pool_max * 3, ++ GFP_KERNEL); ++ if (!name_attrs_pool_count) { ++ pr_err("Can't alloc name_attrs_pool_count\n"); ++ goto del_group_1; ++ } ++ ++ dev_attr_buffer_pool_count = kmalloc(sizeof(struct device_attribute) * ++ bman_pool_max, GFP_KERNEL); ++ if (!dev_attr_buffer_pool_count) { ++ pr_err("Can't alloc dev_attr-buffer_pool_count\n"); ++ goto del_group_2; ++ } ++ ++ bman_dev_pool_count_attributes = kmalloc(sizeof(struct attribute *) * ++ (bman_pool_max + 1), GFP_KERNEL); ++ if (!bman_dev_pool_count_attributes) { ++ pr_err("can't alloc bman_dev_pool_count_attributes\n"); ++ goto del_group_3; ++ } ++ ++ for (i = 0; i < (bman_pool_max + 1); i++) { ++ bman_dev_pool_count_attributes[i] = ++ kmalloc(sizeof(struct attribute), GFP_KERNEL); ++ if (!bman_dev_pool_count_attributes[i]) { ++ pr_err("cannot alloc for each" ++ " bman_dev_pool_count_attributes\n"); ++ goto del_group_3; ++ } ++ } ++ ++ for (i = 0; i < bman_pool_max; i++) { ++ ret = scnprintf((name_attrs_pool_count + i * 3), 3, "%d", i); ++ if (!ret) ++ goto del_group_4; ++ dev_attr_buffer_pool_count[i].attr.name = ++ (name_attrs_pool_count + i * 3); ++ dev_attr_buffer_pool_count[i].attr.mode = S_IRUSR; ++ dev_attr_buffer_pool_count[i].show = show_pool_count; ++ bman_dev_pool_count_attributes[i] = ++ &dev_attr_buffer_pool_count[i].attr; ++ } ++ bman_dev_pool_count_attributes[bman_pool_max] = NULL; ++ ++ bman_dev_pool_countent_grp.attrs = bman_dev_pool_count_attributes; ++ ++ ret = sysfs_create_group(&ofdev->dev.kobj, &bman_dev_pool_countent_grp); ++ if (ret) ++ goto del_group_4; ++ ++ goto done; ++ ++del_group_4: ++ for (i = 0; i < (bman_pool_max + 1); i++) ++ kfree(bman_dev_pool_count_attributes[i]); ++ kfree(bman_dev_pool_count_attributes); ++del_group_3: ++ kfree(dev_attr_buffer_pool_count); ++del_group_2: ++ kfree(name_attrs_pool_count); ++del_group_1: ++ sysfs_remove_group(&ofdev->dev.kobj, &bman_dev_ecr_grp); ++del_group_0: ++ sysfs_remove_group(&ofdev->dev.kobj, &bman_dev_attr_grp); ++done: ++ if (ret) ++ dev_err(&ofdev->dev, ++ "Cannot create dev attributes ret=%d\n", ret); ++ return ret; ++}; ++ ++static struct of_device_id of_fsl_bman_ids[] = { ++ { ++ .compatible = "fsl,bman", ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, of_fsl_bman_ids); ++ ++static struct platform_driver of_fsl_bman_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = DRV_NAME, ++ .of_match_table = of_fsl_bman_ids, ++ }, ++ .probe = of_fsl_bman_probe, ++ .remove = __devexit_p(of_fsl_bman_remove), ++}; ++ ++static int bman_ctrl_init(void) ++{ ++ return platform_driver_register(&of_fsl_bman_driver); ++} ++ ++static void bman_ctrl_exit(void) ++{ ++ platform_driver_unregister(&of_fsl_bman_driver); ++} ++ ++module_init(bman_ctrl_init); ++module_exit(bman_ctrl_exit); ++ ++#endif /* CONFIG_SYSFS */ +diff --git a/drivers/staging/fsl_qbman/bman_debugfs.c b/drivers/staging/fsl_qbman/bman_debugfs.c +new file mode 100644 +index 0000000..2c3d771 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_debugfs.c +@@ -0,0 +1,120 @@ ++/* Copyright 2010-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 ++#include ++#include ++#include ++#include ++ ++static struct dentry *dfs_root; /* debugfs root directory */ ++ ++/******************************************************************************* ++ * Query Buffer Pool State ++ ******************************************************************************/ ++static int query_bp_state_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct bm_pool_state state; ++ int i, j; ++ u32 mask; ++ ++ memset(&state, 0, sizeof(struct bm_pool_state)); ++ ret = bman_query_pools(&state); ++ if (ret) { ++ seq_printf(file, "Error %d\n", ret); ++ return 0; ++ } ++ seq_printf(file, "bp_id free_buffers_avail bp_depleted\n"); ++ for (i = 0; i < 2; i++) { ++ mask = 0x80000000; ++ for (j = 0; j < 32; j++) { ++ seq_printf(file, ++ " %-2u %-3s %-3s\n", ++ (i*32)+j, ++ (state.as.state.__state[i] & mask) ? "no" : "yes", ++ (state.ds.state.__state[i] & mask) ? "yes" : "no"); ++ mask >>= 1; ++ } ++ } ++ return 0; ++} ++ ++static int query_bp_state_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, query_bp_state_show, NULL); ++} ++ ++static const struct file_operations query_bp_state_fops = { ++ .owner = THIS_MODULE, ++ .open = query_bp_state_open, ++ .read = seq_read, ++ .release = single_release, ++}; ++ ++static int __init bman_debugfs_module_init(void) ++{ ++ int ret = 0; ++ struct dentry *d; ++ ++ dfs_root = debugfs_create_dir("bman", NULL); ++ ++ if (dfs_root == NULL) { ++ ret = -ENOMEM; ++ pr_err("Cannot create bman debugfs dir\n"); ++ goto _return; ++ } ++ d = debugfs_create_file("query_bp_state", ++ S_IRUGO, ++ dfs_root, ++ NULL, ++ &query_bp_state_fops); ++ if (d == NULL) { ++ ret = -ENOMEM; ++ pr_err("Cannot create query_bp_state\n"); ++ goto _return; ++ } ++ return 0; ++ ++_return: ++ if (dfs_root) ++ debugfs_remove_recursive(dfs_root); ++ return ret; ++} ++ ++static void __exit bman_debugfs_module_exit(void) ++{ ++ debugfs_remove_recursive(dfs_root); ++} ++ ++ ++module_init(bman_debugfs_module_init); ++module_exit(bman_debugfs_module_exit); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/staging/fsl_qbman/bman_driver.c b/drivers/staging/fsl_qbman/bman_driver.c +new file mode 100644 +index 0000000..805dbd0 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_driver.c +@@ -0,0 +1,471 @@ ++/* Copyright 2008-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "bman_private.h" ++ ++/* ++ * Global variables of the max portal/pool number this bman version supported ++ */ ++u16 bman_ip_rev; ++EXPORT_SYMBOL(bman_ip_rev); ++u16 bman_pool_max; ++EXPORT_SYMBOL(bman_pool_max); ++u16 bman_portal_max; ++ ++/* After initialising cpus that own shared portal configs, we cache the ++ * resulting portals (ie. not just the configs) in this array. Then we ++ * initialise slave cpus that don't have their own portals, redirecting them to ++ * portals from this cache in a round-robin assignment. */ ++static struct bman_portal *shared_portals[NR_CPUS]; ++static int num_shared_portals; ++static int shared_portals_idx; ++ ++static int __init fsl_bpool_init(struct device_node *node) ++{ ++ int ret; ++ u32 *thresh, *bpid = (u32 *)of_get_property(node, "fsl,bpid", &ret); ++ if (!bpid || (ret != 4)) { ++ pr_err("Can't get %s property 'fsl,bpid'\n", node->full_name); ++ return -ENODEV; ++ } ++ thresh = (u32 *)of_get_property(node, "fsl,bpool-thresholds", &ret); ++ if (thresh) { ++ if (ret != 16) { ++ pr_err("Invalid %s property '%s'\n", ++ node->full_name, "fsl,bpool-thresholds"); ++ return -ENODEV; ++ } ++ } ++ if (thresh) { ++#ifdef CONFIG_FSL_BMAN_CONFIG ++ ret = bm_pool_set(*bpid, thresh); ++ if (ret) ++ pr_err("No CCSR node for %s property '%s'\n", ++ node->full_name, "fsl,bpool-thresholds"); ++ return ret; ++#else ++ pr_err("Ignoring %s property '%s', no CCSR support\n", ++ node->full_name, "fsl,bpool-thresholds"); ++#endif ++ } ++ return 0; ++} ++ ++static int __init fsl_bpid_range_init(struct device_node *node) ++{ ++ int ret; ++ u32 *range = (u32 *)of_get_property(node, "fsl,bpid-range", &ret); ++ if (!range) { ++ pr_err("No 'fsl,bpid-range' property in node %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err("'fsl,bpid-range' is not a 2-cell range in node %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ bman_release_bpid_range(range[0], range[1]); ++ pr_info("Bman: BPID allocator includes range %d:%d\n", ++ range[0], range[1]); ++ return 0; ++} ++ ++static struct bm_portal_config * __init parse_pcfg(struct device_node *node) ++{ ++ struct bm_portal_config *pcfg; ++ const u32 *index; ++ int irq, ret; ++ ++ pcfg = kmalloc(sizeof(*pcfg), GFP_KERNEL); ++ if (!pcfg) { ++ pr_err("can't allocate portal config"); ++ return NULL; ++ } ++ ++ if (of_device_is_compatible(node, "fsl,bman-portal-1.0") || ++ of_device_is_compatible(node, "fsl,bman-portal-1.0.0")) { ++ bman_ip_rev = BMAN_REV10; ++ bman_pool_max = 64; ++ bman_portal_max = 10; ++ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.0") || ++ of_device_is_compatible(node, "fsl,bman-portal-2.0.8")) { ++ bman_ip_rev = BMAN_REV20; ++ bman_pool_max = 8; ++ bman_portal_max = 3; ++ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.1.0")) { ++ bman_ip_rev = BMAN_REV21; ++ bman_pool_max = 64; ++ bman_portal_max = 50; ++ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.1.1")) { ++ bman_ip_rev = BMAN_REV21; ++ bman_pool_max = 64; ++ bman_portal_max = 25; ++ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.1.2")) { ++ bman_ip_rev = BMAN_REV21; ++ bman_pool_max = 64; ++ bman_portal_max = 10; ++ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.1.3")) { ++ bman_ip_rev = BMAN_REV21; ++ bman_pool_max = 64; ++ bman_portal_max = 18; ++ } ++ ++ ret = of_address_to_resource(node, DPA_PORTAL_CE, ++ &pcfg->addr_phys[DPA_PORTAL_CE]); ++ if (ret) { ++ pr_err("Can't get %s property 'reg::CE'\n", node->full_name); ++ goto err; ++ } ++ ret = of_address_to_resource(node, DPA_PORTAL_CI, ++ &pcfg->addr_phys[DPA_PORTAL_CI]); ++ if (ret) { ++ pr_err("Can't get %s property 'reg::CI'\n", node->full_name); ++ goto err; ++ } ++ ++ index = of_get_property(node, "cell-index", &ret); ++ if (!index || (ret != 4)) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, ++ "cell-index"); ++ goto err; ++ } ++ if (*index >= bman_portal_max) ++ goto err; ++ ++ pcfg->public_cfg.cpu = -1; ++ ++ irq = irq_of_parse_and_map(node, 0); ++ if (irq == NO_IRQ) { ++ pr_err("Can't get %s property 'interrupts'\n", node->full_name); ++ goto err; ++ } ++ pcfg->public_cfg.irq = irq; ++ pcfg->public_cfg.index = *index; ++ bman_depletion_fill(&pcfg->public_cfg.mask); ++ ++ pcfg->addr_virt[DPA_PORTAL_CE] = ioremap_prot( ++ pcfg->addr_phys[DPA_PORTAL_CE].start, ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CE]), ++ 0); ++ pcfg->addr_virt[DPA_PORTAL_CI] = ioremap_prot( ++ pcfg->addr_phys[DPA_PORTAL_CI].start, ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CI]), ++ _PAGE_GUARDED | _PAGE_NO_CACHE); ++ return pcfg; ++err: ++ kfree(pcfg); ++ return NULL; ++} ++ ++static void destroy_pcfg(struct bm_portal_config *pcfg) ++{ ++ iounmap(pcfg->addr_virt[DPA_PORTAL_CI]); ++ iounmap(pcfg->addr_virt[DPA_PORTAL_CE]); ++ kfree(pcfg); ++} ++ ++static struct bm_portal_config *get_pcfg(struct list_head *list) ++{ ++ struct bm_portal_config *pcfg; ++ if (list_empty(list)) ++ return NULL; ++ pcfg = list_entry(list->prev, struct bm_portal_config, list); ++ list_del(&pcfg->list); ++ return pcfg; ++} ++ ++/* UIO handling callbacks */ ++#define BMAN_UIO_PREAMBLE() \ ++ const struct bm_portal_config *pcfg = \ ++ container_of(__p, struct bm_portal_config, list) ++static int bman_uio_cb_init(const struct list_head *__p, struct uio_info *info) ++{ ++ BMAN_UIO_PREAMBLE(); ++ /* big enough for "bman-uio-xx" */ ++ char *name = kzalloc(16, GFP_KERNEL); ++ if (!name) ++ return -ENOMEM; ++ sprintf(name, "bman-uio-%x", pcfg->public_cfg.index); ++ info->name = name; ++ info->mem[DPA_PORTAL_CE].name = "cena"; ++ info->mem[DPA_PORTAL_CE].addr = pcfg->addr_phys[DPA_PORTAL_CE].start; ++ info->mem[DPA_PORTAL_CE].size = ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CE]); ++ info->mem[DPA_PORTAL_CE].memtype = UIO_MEM_PHYS; ++ info->mem[DPA_PORTAL_CI].name = "cinh"; ++ info->mem[DPA_PORTAL_CI].addr = pcfg->addr_phys[DPA_PORTAL_CI].start; ++ info->mem[DPA_PORTAL_CI].size = ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CI]); ++ info->mem[DPA_PORTAL_CI].memtype = UIO_MEM_PHYS; ++ info->irq = pcfg->public_cfg.irq; ++ return 0; ++} ++static void bman_uio_cb_destroy(const struct list_head *__p, ++ struct uio_info *info) ++{ ++ BMAN_UIO_PREAMBLE(); ++ kfree(info->name); ++ /* We own this struct but had passed it to the dpa_uio layer as a const ++ * so that we don't accidentally meddle with it in the dpa_uio code. ++ * Here it's passed back to us for final clean it up, so de-constify. */ ++ destroy_pcfg((struct bm_portal_config *)pcfg); ++} ++static void bman_uio_cb_interrupt(const struct list_head *__p) ++{ ++ BMAN_UIO_PREAMBLE(); ++ /* This is the only manipulation of a portal register that isn't in the ++ * regular kernel portal driver (_high.c/_low.h). It is also the only ++ * time the kernel touches a register on a portal that is otherwise ++ * being driven by a user-space driver. So rather than messing up ++ * encapsulation for one trivial call, I am hard-coding the offset to ++ * the inhibit register and writing it directly from here. */ ++ out_be32(pcfg->addr_virt[DPA_PORTAL_CI] + 0xe0c, ~(u32)0); ++} ++static const struct dpa_uio_vtable bman_uio = { ++ .init_uio = bman_uio_cb_init, ++ .destroy = bman_uio_cb_destroy, ++ .on_interrupt = bman_uio_cb_interrupt ++}; ++ ++static struct bman_portal *init_pcfg(struct bm_portal_config *pcfg) ++{ ++ struct bman_portal *p; ++ struct cpumask oldmask = *tsk_cpus_allowed(current); ++ set_cpus_allowed_ptr(current, get_cpu_mask(pcfg->public_cfg.cpu)); ++ p = bman_create_affine_portal(pcfg); ++ if (p) { ++#ifdef CONFIG_FSL_DPA_PIRQ_SLOW ++ bman_irqsource_add(BM_PIRQ_RCRI | BM_PIRQ_BSCN); ++#endif ++ pr_info("Bman portal %sinitialised, cpu %d\n", ++ pcfg->public_cfg.is_shared ? "(shared) " : "", ++ pcfg->public_cfg.cpu); ++ } else ++ pr_crit("Bman portal failure on cpu %d\n", ++ pcfg->public_cfg.cpu); ++ set_cpus_allowed_ptr(current, &oldmask); ++ return p; ++} ++ ++static void init_slave(int cpu) ++{ ++ struct bman_portal *p; ++ struct cpumask oldmask = *tsk_cpus_allowed(current); ++ set_cpus_allowed_ptr(current, get_cpu_mask(cpu)); ++ p = bman_create_affine_slave(shared_portals[shared_portals_idx++]); ++ if (!p) ++ pr_err("Bman slave portal failure on cpu %d\n", cpu); ++ else ++ pr_info("Bman portal %sinitialised, cpu %d\n", "(slave) ", cpu); ++ set_cpus_allowed_ptr(current, &oldmask); ++ if (shared_portals_idx >= num_shared_portals) ++ shared_portals_idx = 0; ++} ++ ++/* Bootarg "bportals=[...]" has the same syntax as "qportals=", and so the ++ * parsing is in dpa_sys.h. The syntax is a comma-separated list of indexes ++ * and/or ranges of indexes, with each being optionally prefixed by "s" to ++ * explicitly mark it or them for sharing. ++ * Eg; ++ * bportals=s0,1-3,s4 ++ * means that cpus 1,2,3 get "unshared" portals, cpus 0 and 4 get "shared" ++ * portals, and any remaining cpus share the portals that are assigned to cpus 0 ++ * or 4, selected in a round-robin fashion. (In this example, cpu 5 would share ++ * cpu 0's portal, cpu 6 would share cpu4's portal, and cpu 7 would share cpu ++ * 0's portal.) */ ++static struct cpumask want_unshared __initdata; /* cpus requested without "s" */ ++static struct cpumask want_shared __initdata; /* cpus requested with "s" */ ++ ++static int __init parse_bportals(char *str) ++{ ++ return parse_portals_bootarg(str, &want_shared, &want_unshared, ++ "bportals"); ++} ++__setup("bportals=", parse_bportals); ++ ++/* Initialise the Bman driver. The meat of this function deals with portals. The ++ * following describes the flow of portal-handling, the code "steps" refer to ++ * this description; ++ * 1. Portal configs are parsed from the device-tree into 'unused_pcfgs', with ++ * ::cpu==-1. Regions and interrupts are mapped (but interrupts are not ++ * bound). ++ * 2. The "want_shared" and "want_unshared" lists (as filled by the ++ * "bportals=[...]" bootarg) are processed, allocating portals and assigning ++ * them to cpus, placing them in the relevant list and setting ::cpu as ++ * appropriate. If no "bportals" bootarg was present, the defaut is to try to ++ * assign portals to all online cpus at the time of driver initialisation. ++ * Any failure to allocate portals (when parsing the "want" lists or when ++ * using default behaviour) will be silently tolerated (the "fixup" logic in ++ * step 3 will determine what happens in this case). ++ * 3. Do fixups relative to cpu_online_mask(). If no portals are marked for ++ * sharing and sharing is required (because not all cpus have been assigned ++ * portals), then one portal will marked for sharing. Conversely if no ++ * sharing is required, any portals marked for sharing will not be shared. It ++ * may be that sharing occurs when it wasn't expected, if portal allocation ++ * failed to honour all the requested assignments (including the default ++ * assignments if no bootarg is present). ++ * 4. Unshared portals are initialised on their respective cpus. ++ * 5. Shared portals are initialised on their respective cpus. ++ * 6. Each remaining cpu is initialised to slave to one of the shared portals, ++ * which are selected in a round-robin fashion. ++ * Any portal configs left unused are exported as UIO devices. ++ */ ++static __init int bman_init(void) ++{ ++ struct cpumask slave_cpus; ++ struct cpumask unshared_cpus = *cpu_none_mask; ++ struct cpumask shared_cpus = *cpu_none_mask; ++ LIST_HEAD(unused_pcfgs); ++ LIST_HEAD(unshared_pcfgs); ++ LIST_HEAD(shared_pcfgs); ++ struct device_node *dn; ++ struct bm_portal_config *pcfg; ++ struct bman_portal *p; ++ int cpu, ret; ++ ++ /* Initialise the Bman (CCSR) device */ ++ for_each_compatible_node(dn, NULL, "fsl,bman") { ++ if (!bman_init_ccsr(dn)) ++ pr_info("Bman err interrupt handler present\n"); ++ else ++ pr_err("Bman CCSR setup failed\n"); ++ } ++ /* Initialise any declared buffer pools */ ++ for_each_compatible_node(dn, NULL, "fsl,bpool") { ++ ret = fsl_bpool_init(dn); ++ if (ret) ++ return ret; ++ } ++ /* Step 1. See comments at the beginning of the file. */ ++ for_each_compatible_node(dn, NULL, "fsl,bman-portal") { ++ if (!of_device_is_available(dn)) ++ continue; ++ pcfg = parse_pcfg(dn); ++ if (pcfg) ++ list_add_tail(&pcfg->list, &unused_pcfgs); ++ } ++ /* Step 2. */ ++ for_each_cpu(cpu, &want_shared) { ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ pcfg->public_cfg.cpu = cpu; ++ list_add_tail(&pcfg->list, &shared_pcfgs); ++ cpumask_set_cpu(cpu, &shared_cpus); ++ } ++ for_each_cpu(cpu, &want_unshared) { ++ if (cpumask_test_cpu(cpu, &shared_cpus)) ++ continue; ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ pcfg->public_cfg.cpu = cpu; ++ list_add_tail(&pcfg->list, &unshared_pcfgs); ++ cpumask_set_cpu(cpu, &unshared_cpus); ++ } ++ if (list_empty(&shared_pcfgs) && list_empty(&unshared_pcfgs)) { ++ /* Default, give an unshared portal to each online cpu */ ++ for_each_online_cpu(cpu) { ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ pcfg->public_cfg.cpu = cpu; ++ list_add_tail(&pcfg->list, &unshared_pcfgs); ++ cpumask_set_cpu(cpu, &unshared_cpus); ++ } ++ } ++ /* Step 3. */ ++ cpumask_andnot(&slave_cpus, cpu_online_mask, &shared_cpus); ++ cpumask_andnot(&slave_cpus, &slave_cpus, &unshared_cpus); ++ if (cpumask_empty(&slave_cpus)) { ++ /* No sharing required */ ++ if (!list_empty(&shared_pcfgs)) { ++ /* Migrate "shared" to "unshared" */ ++ cpumask_or(&unshared_cpus, &unshared_cpus, ++ &shared_cpus); ++ cpumask_clear(&shared_cpus); ++ list_splice_tail(&shared_pcfgs, &unshared_pcfgs); ++ INIT_LIST_HEAD(&shared_pcfgs); ++ } ++ } else { ++ /* Sharing required */ ++ if (list_empty(&shared_pcfgs)) { ++ /* Migrate one "unshared" to "shared" */ ++ pcfg = get_pcfg(&unshared_pcfgs); ++ if (!pcfg) { ++ pr_crit("No BMan portals available!\n"); ++ return 0; ++ } ++ cpumask_clear_cpu(pcfg->public_cfg.cpu, &unshared_cpus); ++ cpumask_set_cpu(pcfg->public_cfg.cpu, &shared_cpus); ++ list_add_tail(&pcfg->list, &shared_pcfgs); ++ } ++ } ++ /* Step 4. */ ++ list_for_each_entry(pcfg, &unshared_pcfgs, list) { ++ pcfg->public_cfg.is_shared = 0; ++ p = init_pcfg(pcfg); ++ } ++ /* Step 5. */ ++ list_for_each_entry(pcfg, &shared_pcfgs, list) { ++ pcfg->public_cfg.is_shared = 1; ++ p = init_pcfg(pcfg); ++ if (p) ++ shared_portals[num_shared_portals++] = p; ++ } ++ /* Step 6. */ ++ if (!cpumask_empty(&slave_cpus)) ++ for_each_cpu(cpu, &slave_cpus) ++ init_slave(cpu); ++ pr_info("Bman portals initialised\n"); ++#ifdef CONFIG_FSL_DPA_UIO ++ /* Export any left over portals as UIO devices */ ++ do { ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ ret = dpa_uio_register(&pcfg->list, &bman_uio); ++ if (ret) { ++ pr_err("Failure registering BMan UIO portal\n"); ++ destroy_pcfg(pcfg); ++ } ++ } while (1); ++#endif ++ /* Initialise BPID allocation ranges */ ++ for_each_compatible_node(dn, NULL, "fsl,bpid-range") { ++ ret = fsl_bpid_range_init(dn); ++ if (ret) ++ return ret; ++ } ++ return 0; ++} ++subsys_initcall(bman_init); +diff --git a/drivers/staging/fsl_qbman/bman_high.c b/drivers/staging/fsl_qbman/bman_high.c +new file mode 100644 +index 0000000..ecdfae7 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_high.c +@@ -0,0 +1,1009 @@ ++/* Copyright 2008-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "bman_low.h" ++ ++/* Compilation constants */ ++#define RCR_THRESH 2 /* reread h/w CI when running out of space */ ++#define IRQNAME "BMan portal %d" ++#define MAX_IRQNAME 16 /* big enough for "BMan portal %d" */ ++ ++struct bman_portal { ++ struct bm_portal p; ++ /* 2-element array. pools[0] is mask, pools[1] is snapshot. */ ++ struct bman_depletion *pools; ++ int thresh_set; ++ unsigned long irq_sources; ++ u32 slowpoll; /* only used when interrupts are off */ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ struct bman_pool *rcri_owned; /* only 1 release WAIT_SYNC at a time */ ++#endif ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ raw_spinlock_t sharing_lock; /* only used if is_shared */ ++ int is_shared; ++ struct bman_portal *sharing_redirect; ++#endif ++ /* When the cpu-affine portal is activated, this is non-NULL */ ++ const struct bm_portal_config *config; ++ /* 64-entry hash-table of pool objects that are tracking depletion ++ * entry/exit (ie. BMAN_POOL_FLAG_DEPLETION). This isn't fast-path, so ++ * we're not fussy about cache-misses and so forth - whereas the above ++ * members should all fit in one cacheline. ++ * BTW, with 64 entries in the hash table and 64 buffer pools to track, ++ * you'll never guess the hash-function ... */ ++ struct bman_pool *cb[64]; ++ char irqname[MAX_IRQNAME]; ++}; ++ ++/* For an explanation of the locking, redirection, or affine-portal logic, ++ * please consult the Qman driver for details. This is the same, only simpler ++ * (no fiddly Qman-specific bits.) */ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++#define PORTAL_IRQ_LOCK(p, irqflags) \ ++ do { \ ++ if ((p)->is_shared) \ ++ raw_spin_lock_irqsave(&(p)->sharing_lock, irqflags); \ ++ else \ ++ local_irq_save(irqflags); \ ++ } while (0) ++#define PORTAL_IRQ_UNLOCK(p, irqflags) \ ++ do { \ ++ if ((p)->is_shared) \ ++ raw_spin_unlock_irqrestore(&(p)->sharing_lock, \ ++ irqflags); \ ++ else \ ++ local_irq_restore(irqflags); \ ++ } while (0) ++#else ++#define PORTAL_IRQ_LOCK(p, irqflags) local_irq_save(irqflags) ++#define PORTAL_IRQ_UNLOCK(p, irqflags) local_irq_restore(irqflags) ++#endif ++ ++static cpumask_t affine_mask; ++static DEFINE_SPINLOCK(affine_mask_lock); ++static DEFINE_PER_CPU(struct bman_portal, bman_affine_portal); ++static inline struct bman_portal *get_raw_affine_portal(void) ++{ ++ return &get_cpu_var(bman_affine_portal); ++} ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++static inline struct bman_portal *get_affine_portal(void) ++{ ++ struct bman_portal *p = get_raw_affine_portal(); ++ if (p->sharing_redirect) ++ return p->sharing_redirect; ++ return p; ++} ++#else ++#define get_affine_portal() get_raw_affine_portal() ++#endif ++static inline void put_affine_portal(void) ++{ ++ put_cpu_var(bman_affine_portal); ++} ++static inline struct bman_portal *get_poll_portal(void) ++{ ++ return &__get_cpu_var(bman_affine_portal); ++} ++#define put_poll_portal() do { ; } while (0) ++ ++/* GOTCHA: this object type refers to a pool, it isn't *the* pool. There may be ++ * more than one such object per Bman buffer pool, eg. if different users of the ++ * pool are operating via different portals. */ ++struct bman_pool { ++ struct bman_pool_params params; ++ /* Used for hash-table admin when using depletion notifications. */ ++ struct bman_portal *portal; ++ struct bman_pool *next; ++ /* stockpile state - NULL unless BMAN_POOL_FLAG_STOCKPILE is set */ ++ struct bm_buffer *sp; ++ unsigned int sp_fill; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ atomic_t in_use; ++#endif ++}; ++ ++/* (De)Registration of depletion notification callbacks */ ++static void depletion_link(struct bman_portal *portal, struct bman_pool *pool) ++{ ++ __maybe_unused unsigned long irqflags; ++ pool->portal = portal; ++ PORTAL_IRQ_LOCK(portal, irqflags); ++ pool->next = portal->cb[pool->params.bpid]; ++ portal->cb[pool->params.bpid] = pool; ++ if (!pool->next) ++ /* First object for that bpid on this portal, enable the BSCN ++ * mask bit. */ ++ bm_isr_bscn_mask(&portal->p, pool->params.bpid, 1); ++ PORTAL_IRQ_UNLOCK(portal, irqflags); ++} ++static void depletion_unlink(struct bman_pool *pool) ++{ ++ struct bman_pool *it, *last = NULL; ++ struct bman_pool **base = &pool->portal->cb[pool->params.bpid]; ++ __maybe_unused unsigned long irqflags; ++ PORTAL_IRQ_LOCK(pool->portal, irqflags); ++ it = *base; /* <-- gotcha, don't do this prior to the irq_save */ ++ while (it != pool) { ++ last = it; ++ it = it->next; ++ } ++ if (!last) ++ *base = pool->next; ++ else ++ last->next = pool->next; ++ if (!last && !pool->next) { ++ /* Last object for that bpid on this portal, disable the BSCN ++ * mask bit. */ ++ bm_isr_bscn_mask(&pool->portal->p, pool->params.bpid, 0); ++ /* And "forget" that we last saw this pool as depleted */ ++ bman_depletion_unset(&pool->portal->pools[1], ++ pool->params.bpid); ++ } ++ PORTAL_IRQ_UNLOCK(pool->portal, irqflags); ++} ++ ++/* In the case that the application's core loop calls qman_poll() and ++ * bman_poll(), we ought to balance how often we incur the overheads of the ++ * slow-path poll. We'll use two decrementer sources. The idle decrementer ++ * constant is used when the last slow-poll detected no work to do, and the busy ++ * decrementer constant when the last slow-poll had work to do. */ ++#define SLOW_POLL_IDLE 1000 ++#define SLOW_POLL_BUSY 10 ++static u32 __poll_portal_slow(struct bman_portal *p, u32 is); ++ ++/* Portal interrupt handler */ ++static irqreturn_t portal_isr(__always_unused int irq, void *ptr) ++{ ++ struct bman_portal *p = ptr; ++ u32 clear = p->irq_sources; ++ u32 is = bm_isr_status_read(&p->p) & p->irq_sources; ++ clear |= __poll_portal_slow(p, is); ++ bm_isr_status_clear(&p->p, clear); ++ return IRQ_HANDLED; ++} ++ ++struct bman_portal *bman_create_affine_portal( ++ const struct bm_portal_config *config) ++{ ++ struct bman_portal *portal = get_raw_affine_portal(); ++ struct bm_portal *__p = &portal->p; ++ const struct bman_depletion *pools = &config->public_cfg.mask; ++ int ret; ++ u8 bpid = 0; ++ ++ /* A criteria for calling this function (from bman_driver.c) is that ++ * we're already affine to the cpu and won't schedule onto another cpu. ++ * This means we can put_affine_portal() and yet continue to use ++ * "portal", which in turn means aspects of this routine can sleep. */ ++ put_affine_portal(); ++ ++ /* prep the low-level portal struct with the mapped addresses from the ++ * config, everything that follows depends on it and "config" is more ++ * for (de)reference... */ ++ __p->addr.addr_ce = config->addr_virt[DPA_PORTAL_CE]; ++ __p->addr.addr_ci = config->addr_virt[DPA_PORTAL_CI]; ++ if (bm_rcr_init(__p, bm_rcr_pvb, bm_rcr_cce)) { ++ pr_err("Bman RCR initialisation failed\n"); ++ goto fail_rcr; ++ } ++ if (bm_mc_init(__p)) { ++ pr_err("Bman MC initialisation failed\n"); ++ goto fail_mc; ++ } ++ if (bm_isr_init(__p)) { ++ pr_err("Bman ISR initialisation failed\n"); ++ goto fail_isr; ++ } ++ portal->pools = kmalloc(2 * sizeof(*pools), GFP_KERNEL); ++ if (!portal->pools) ++ goto fail_pools; ++ portal->pools[0] = *pools; ++ bman_depletion_init(portal->pools + 1); ++ while (bpid < bman_pool_max) { ++ /* Default to all BPIDs disabled, we enable as required at ++ * run-time. */ ++ bm_isr_bscn_mask(__p, bpid, 0); ++ bpid++; ++ } ++ portal->slowpoll = 0; ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ portal->rcri_owned = NULL; ++#endif ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ raw_spin_lock_init(&portal->sharing_lock); ++ portal->is_shared = config->public_cfg.is_shared; ++ portal->sharing_redirect = NULL; ++#endif ++ memset(&portal->cb, 0, sizeof(portal->cb)); ++ /* Write-to-clear any stale interrupt status bits */ ++ bm_isr_disable_write(__p, 0xffffffff); ++ portal->irq_sources = 0; ++ bm_isr_enable_write(__p, portal->irq_sources); ++ bm_isr_status_clear(__p, 0xffffffff); ++ snprintf(portal->irqname, MAX_IRQNAME, IRQNAME, config->public_cfg.cpu); ++ if (request_irq(config->public_cfg.irq, portal_isr, 0, portal->irqname, ++ portal)) { ++ pr_err("request_irq() failed\n"); ++ goto fail_irq; ++ } ++ if ((config->public_cfg.cpu != -1) && ++ irq_can_set_affinity(config->public_cfg.irq) && ++ irq_set_affinity(config->public_cfg.irq, ++ cpumask_of(config->public_cfg.cpu))) { ++ pr_err("irq_set_affinity() failed\n"); ++ goto fail_affinity; ++ } ++ /* Need RCR to be empty before continuing */ ++ ret = bm_rcr_get_fill(__p); ++ if (ret) { ++ pr_err("Bman RCR unclean\n"); ++ goto fail_rcr_empty; ++ } ++ /* Success */ ++ portal->config = config; ++ spin_lock(&affine_mask_lock); ++ cpumask_set_cpu(config->public_cfg.cpu, &affine_mask); ++ spin_unlock(&affine_mask_lock); ++ bm_isr_disable_write(__p, 0); ++ bm_isr_uninhibit(__p); ++ return portal; ++fail_rcr_empty: ++fail_affinity: ++ free_irq(config->public_cfg.irq, portal); ++fail_irq: ++ if (portal->pools) ++ kfree(portal->pools); ++fail_pools: ++ bm_isr_finish(__p); ++fail_isr: ++ bm_mc_finish(__p); ++fail_mc: ++ bm_rcr_finish(__p); ++fail_rcr: ++ return NULL; ++} ++ ++struct bman_portal *bman_create_affine_slave(struct bman_portal *redirect) ++{ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ struct bman_portal *p = get_raw_affine_portal(); ++ BUG_ON(p->config); ++ BUG_ON(p->is_shared); ++ BUG_ON(!redirect->config->public_cfg.is_shared); ++ p->irq_sources = 0; ++ p->sharing_redirect = redirect; ++ put_affine_portal(); ++ return p; ++#else ++ BUG(); ++ return NULL; ++#endif ++} ++ ++const struct bm_portal_config *bman_destroy_affine_portal(void) ++{ ++ struct bman_portal *bm = get_raw_affine_portal(); ++ const struct bm_portal_config *pcfg; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (bm->sharing_redirect) { ++ bm->sharing_redirect = NULL; ++ put_affine_portal(); ++ return NULL; ++ } ++ bm->is_shared = 0; ++#endif ++ pcfg = bm->config; ++ bm_rcr_cce_update(&bm->p); ++ bm_rcr_cce_update(&bm->p); ++ free_irq(pcfg->public_cfg.irq, bm); ++ kfree(bm->pools); ++ bm_isr_finish(&bm->p); ++ bm_mc_finish(&bm->p); ++ bm_rcr_finish(&bm->p); ++ bm->config = NULL; ++ spin_lock(&affine_mask_lock); ++ cpumask_clear_cpu(pcfg->public_cfg.cpu, &affine_mask); ++ spin_unlock(&affine_mask_lock); ++ put_affine_portal(); ++ return pcfg; ++} ++ ++/* When release logic waits on available RCR space, we need a global waitqueue ++ * in the case of "affine" use (as the waits wake on different cpus which means ++ * different portals - so we can't wait on any per-portal waitqueue). */ ++static DECLARE_WAIT_QUEUE_HEAD(affine_queue); ++ ++static u32 __poll_portal_slow(struct bman_portal *p, u32 is) ++{ ++ struct bman_depletion tmp; ++ u32 ret = is; ++ ++ /* There is a gotcha to be aware of. If we do the query before clearing ++ * the status register, we may miss state changes that occur between the ++ * two. If we write to clear the status register before the query, the ++ * cache-enabled query command may overtake the status register write ++ * unless we use a heavyweight sync (which we don't want). Instead, we ++ * write-to-clear the status register then *read it back* before doing ++ * the query, hence the odd while loop with the 'is' accumulation. */ ++ if (is & BM_PIRQ_BSCN) { ++ struct bm_mc_result *mcr; ++ __maybe_unused unsigned long irqflags; ++ unsigned int i, j; ++ u32 __is; ++ bm_isr_status_clear(&p->p, BM_PIRQ_BSCN); ++ while ((__is = bm_isr_status_read(&p->p)) & BM_PIRQ_BSCN) { ++ is |= __is; ++ bm_isr_status_clear(&p->p, BM_PIRQ_BSCN); ++ } ++ is &= ~BM_PIRQ_BSCN; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ bm_mc_start(&p->p); ++ bm_mc_commit(&p->p, BM_MCC_VERB_CMD_QUERY); ++ while (!(mcr = bm_mc_result(&p->p))) ++ cpu_relax(); ++ tmp = mcr->query.ds.state; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ for (i = 0; i < 2; i++) { ++ int idx = i * 32; ++ /* tmp is a mask of currently-depleted pools. ++ * pools[0] is mask of those we care about. ++ * pools[1] is our previous view (we only want to ++ * be told about changes). */ ++ tmp.__state[i] &= p->pools[0].__state[i]; ++ if (tmp.__state[i] == p->pools[1].__state[i]) ++ /* fast-path, nothing to see, move along */ ++ continue; ++ for (j = 0; j <= 31; j++, idx++) { ++ struct bman_pool *pool = p->cb[idx]; ++ int b4 = bman_depletion_get(&p->pools[1], idx); ++ int af = bman_depletion_get(&tmp, idx); ++ if (b4 == af) ++ continue; ++ while (pool) { ++ pool->params.cb(p, pool, ++ pool->params.cb_ctx, af); ++ pool = pool->next; ++ } ++ } ++ } ++ p->pools[1] = tmp; ++ } ++ ++ if (is & BM_PIRQ_RCRI) { ++ __maybe_unused unsigned long irqflags; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ bm_rcr_cce_update(&p->p); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ /* If waiting for sync, we only cancel the interrupt threshold ++ * when the ring utilisation hits zero. */ ++ if (p->rcri_owned) { ++ if (!bm_rcr_get_fill(&p->p)) { ++ p->rcri_owned = NULL; ++ bm_rcr_set_ithresh(&p->p, 0); ++ } ++ } else ++#endif ++ bm_rcr_set_ithresh(&p->p, 0); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ wake_up(&affine_queue); ++ bm_isr_status_clear(&p->p, BM_PIRQ_RCRI); ++ is &= ~BM_PIRQ_RCRI; ++ } ++ ++ /* There should be no status register bits left undefined */ ++ DPA_ASSERT(!is); ++ return ret; ++} ++ ++const struct bman_portal_config *bman_get_portal_config(void) ++{ ++ struct bman_portal *p = get_affine_portal(); ++ const struct bman_portal_config *ret = &p->config->public_cfg; ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(bman_get_portal_config); ++ ++u32 bman_irqsource_get(void) ++{ ++ struct bman_portal *p = get_raw_affine_portal(); ++ u32 ret = p->irq_sources & BM_PIRQ_VISIBLE; ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(bman_irqsource_get); ++ ++int bman_irqsource_add(__maybe_unused u32 bits) ++{ ++ struct bman_portal *p = get_raw_affine_portal(); ++ int ret = 0; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (p->sharing_redirect) ++ ret = -EINVAL; ++ else ++#endif ++ { ++ __maybe_unused unsigned long irqflags; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ set_bits(bits & BM_PIRQ_VISIBLE, &p->irq_sources); ++ bm_isr_enable_write(&p->p, p->irq_sources); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ } ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(bman_irqsource_add); ++ ++int bman_irqsource_remove(u32 bits) ++{ ++ struct bman_portal *p = get_raw_affine_portal(); ++ __maybe_unused unsigned long irqflags; ++ u32 ier; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (p->sharing_redirect) { ++ put_affine_portal(); ++ return -EINVAL; ++ } ++#endif ++ /* Our interrupt handler only processes+clears status register bits that ++ * are in p->irq_sources. As we're trimming that mask, if one of them ++ * were to assert in the status register just before we remove it from ++ * the enable register, there would be an interrupt-storm when we ++ * release the IRQ lock. So we wait for the enable register update to ++ * take effect in h/w (by reading it back) and then clear all other bits ++ * in the status register. Ie. we clear them from ISR once it's certain ++ * IER won't allow them to reassert. */ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ bits &= BM_PIRQ_VISIBLE; ++ clear_bits(bits, &p->irq_sources); ++ bm_isr_enable_write(&p->p, p->irq_sources); ++ ier = bm_isr_enable_read(&p->p); ++ /* Using "~ier" (rather than "bits" or "~p->irq_sources") creates a ++ * data-dependency, ie. to protect against re-ordering. */ ++ bm_isr_status_clear(&p->p, ~ier); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return 0; ++} ++EXPORT_SYMBOL(bman_irqsource_remove); ++ ++const cpumask_t *bman_affine_cpus(void) ++{ ++ return &affine_mask; ++} ++EXPORT_SYMBOL(bman_affine_cpus); ++ ++u32 bman_poll_slow(void) ++{ ++ struct bman_portal *p = get_poll_portal(); ++ u32 ret; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (unlikely(p->sharing_redirect)) ++ ret = (u32)-1; ++ else ++#endif ++ { ++ u32 is = bm_isr_status_read(&p->p) & ~p->irq_sources; ++ ret = __poll_portal_slow(p, is); ++ bm_isr_status_clear(&p->p, ret); ++ } ++ put_poll_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(bman_poll_slow); ++ ++/* Legacy wrapper */ ++void bman_poll(void) ++{ ++ struct bman_portal *p = get_poll_portal(); ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (unlikely(p->sharing_redirect)) ++ goto done; ++#endif ++ if (!(p->slowpoll--)) { ++ u32 is = bm_isr_status_read(&p->p) & ~p->irq_sources; ++ u32 active = __poll_portal_slow(p, is); ++ if (active) ++ p->slowpoll = SLOW_POLL_BUSY; ++ else ++ p->slowpoll = SLOW_POLL_IDLE; ++ } ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++done: ++#endif ++ put_poll_portal(); ++} ++EXPORT_SYMBOL(bman_poll); ++ ++static const u32 zero_thresholds[4] = {0, 0, 0, 0}; ++ ++struct bman_pool *bman_new_pool(const struct bman_pool_params *params) ++{ ++ struct bman_pool *pool = NULL; ++ u32 bpid; ++ ++ if (params->flags & BMAN_POOL_FLAG_DYNAMIC_BPID) { ++ int ret = bman_alloc_bpid(&bpid); ++ if (ret) ++ return NULL; ++ } else { ++ if (params->bpid >= bman_pool_max) ++ return NULL; ++ bpid = params->bpid; ++ } ++#ifdef CONFIG_FSL_BMAN_CONFIG ++ if (params->flags & BMAN_POOL_FLAG_THRESH) { ++ int ret = bm_pool_set(bpid, params->thresholds); ++ if (ret) ++ goto err; ++ } ++#else ++ if (params->flags & BMAN_POOL_FLAG_THRESH) ++ goto err; ++#endif ++ pool = kmalloc(sizeof(*pool), GFP_KERNEL); ++ if (!pool) ++ goto err; ++ pool->sp = NULL; ++ pool->sp_fill = 0; ++ pool->params = *params; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ atomic_set(&pool->in_use, 1); ++#endif ++ if (params->flags & BMAN_POOL_FLAG_DYNAMIC_BPID) ++ pool->params.bpid = bpid; ++ if (params->flags & BMAN_POOL_FLAG_STOCKPILE) { ++ pool->sp = kmalloc(sizeof(struct bm_buffer) * BMAN_STOCKPILE_SZ, ++ GFP_KERNEL); ++ if (!pool->sp) ++ goto err; ++ } ++ if (pool->params.flags & BMAN_POOL_FLAG_DEPLETION) { ++ struct bman_portal *p = get_affine_portal(); ++ if (!p->pools || !bman_depletion_get(&p->pools[0], bpid)) { ++ pr_err("Depletion events disabled for bpid %d\n", bpid); ++ goto err; ++ } ++ depletion_link(p, pool); ++ put_affine_portal(); ++ } ++ return pool; ++err: ++#ifdef CONFIG_FSL_BMAN_CONFIG ++ if (params->flags & BMAN_POOL_FLAG_THRESH) ++ bm_pool_set(bpid, zero_thresholds); ++#endif ++ if (params->flags & BMAN_POOL_FLAG_DYNAMIC_BPID) ++ bman_release_bpid(bpid); ++ if (pool) { ++ if (pool->sp) ++ kfree(pool->sp); ++ kfree(pool); ++ } ++ return NULL; ++} ++EXPORT_SYMBOL(bman_new_pool); ++ ++void bman_free_pool(struct bman_pool *pool) ++{ ++#ifdef CONFIG_FSL_BMAN_CONFIG ++ if (pool->params.flags & BMAN_POOL_FLAG_THRESH) ++ bm_pool_set(pool->params.bpid, zero_thresholds); ++#endif ++ if (pool->params.flags & BMAN_POOL_FLAG_DEPLETION) ++ depletion_unlink(pool); ++ if (pool->params.flags & BMAN_POOL_FLAG_STOCKPILE) { ++ if (pool->sp_fill) ++ pr_err("Stockpile not flushed, has %u in bpid %u.\n", ++ pool->sp_fill, pool->params.bpid); ++ kfree(pool->sp); ++ pool->sp = NULL; ++ pool->params.flags ^= BMAN_POOL_FLAG_STOCKPILE; ++ } ++ if (pool->params.flags & BMAN_POOL_FLAG_DYNAMIC_BPID) { ++ /* When releasing a BPID to the dynamic allocator, that pool ++ * must be *empty*. This code makes it so by dropping everything ++ * into the bit-bucket. This ignores whether or not it was a ++ * mistake (or a leak) on the caller's part not to drain the ++ * pool beforehand. */ ++ struct bm_buffer bufs[8]; ++ int ret = 0; ++ do { ++ /* Acquire is all-or-nothing, so we drain in 8s, then in ++ * 1s for the remainder. */ ++ if (ret != 1) ++ ret = bman_acquire(pool, bufs, 8, 0); ++ if (ret < 8) ++ ret = bman_acquire(pool, bufs, 1, 0); ++ } while (ret > 0); ++ bman_release_bpid(pool->params.bpid); ++ } ++ kfree(pool); ++} ++EXPORT_SYMBOL(bman_free_pool); ++ ++const struct bman_pool_params *bman_get_params(const struct bman_pool *pool) ++{ ++ return &pool->params; ++} ++EXPORT_SYMBOL(bman_get_params); ++ ++static noinline void update_rcr_ci(struct bman_portal *p, u8 avail) ++{ ++ if (avail) ++ bm_rcr_cce_prefetch(&p->p); ++ else ++ bm_rcr_cce_update(&p->p); ++} ++ ++int bman_rcr_is_empty(void) ++{ ++ __maybe_unused unsigned long irqflags; ++ struct bman_portal *p = get_affine_portal(); ++ u8 avail; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ update_rcr_ci(p, 0); ++ avail = bm_rcr_get_fill(&p->p); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return (avail == 0); ++} ++EXPORT_SYMBOL(bman_rcr_is_empty); ++ ++static inline struct bm_rcr_entry *try_rel_start(struct bman_portal **p, ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ __maybe_unused struct bman_pool *pool, ++#endif ++ __maybe_unused unsigned long *irqflags, ++ __maybe_unused u32 flags) ++{ ++ struct bm_rcr_entry *r; ++ u8 avail; ++ ++ *p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(*p, (*irqflags)); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & BMAN_RELEASE_FLAG_WAIT) && ++ (flags & BMAN_RELEASE_FLAG_WAIT_SYNC))) { ++ if ((*p)->rcri_owned) { ++ PORTAL_IRQ_UNLOCK(*p, (*irqflags)); ++ put_affine_portal(); ++ return NULL; ++ } ++ (*p)->rcri_owned = pool; ++ } ++#endif ++ avail = bm_rcr_get_avail(&(*p)->p); ++ if (avail < 2) ++ update_rcr_ci(*p, avail); ++ r = bm_rcr_start(&(*p)->p); ++ if (unlikely(!r)) { ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & BMAN_RELEASE_FLAG_WAIT) && ++ (flags & BMAN_RELEASE_FLAG_WAIT_SYNC))) ++ (*p)->rcri_owned = NULL; ++#endif ++ PORTAL_IRQ_UNLOCK(*p, (*irqflags)); ++ put_affine_portal(); ++ } ++ return r; ++} ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++static noinline struct bm_rcr_entry *__wait_rel_start(struct bman_portal **p, ++ struct bman_pool *pool, ++ __maybe_unused unsigned long *irqflags, ++ u32 flags) ++{ ++ struct bm_rcr_entry *rcr = try_rel_start(p, pool, irqflags, flags); ++ if (!rcr) ++ bm_rcr_set_ithresh(&(*p)->p, 1); ++ return rcr; ++} ++ ++static noinline struct bm_rcr_entry *wait_rel_start(struct bman_portal **p, ++ struct bman_pool *pool, ++ __maybe_unused unsigned long *irqflags, ++ u32 flags) ++{ ++ struct bm_rcr_entry *rcr; ++#ifndef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ pool = NULL; ++#endif ++ if (flags & BMAN_RELEASE_FLAG_WAIT_INT) ++ wait_event_interruptible(affine_queue, ++ (rcr = __wait_rel_start(p, pool, irqflags, flags))); ++ else ++ wait_event(affine_queue, ++ (rcr = __wait_rel_start(p, pool, irqflags, flags))); ++ return rcr; ++} ++#endif ++ ++/* to facilitate better copying of bufs into the ring without either (a) copying ++ * noise into the first byte (prematurely triggering the command), nor (b) being ++ * very inefficient by copying small fields using read-modify-write */ ++struct overlay_bm_buffer { ++ u32 first; ++ u32 second; ++}; ++ ++static inline int __bman_release(struct bman_pool *pool, ++ const struct bm_buffer *bufs, u8 num, u32 flags) ++{ ++ struct bman_portal *p; ++ struct bm_rcr_entry *r; ++ struct overlay_bm_buffer *o_dest; ++ struct overlay_bm_buffer *o_src = (struct overlay_bm_buffer *)&bufs[0]; ++ __maybe_unused unsigned long irqflags; ++ u32 i = num - 1; ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & BMAN_RELEASE_FLAG_WAIT) ++ r = wait_rel_start(&p, pool, &irqflags, flags); ++ else ++ r = try_rel_start(&p, pool, &irqflags, flags); ++#else ++ r = try_rel_start(&p, &irqflags, flags); ++#endif ++ if (!r) ++ return -EBUSY; ++ /* We can copy all but the first entry, as this can trigger badness ++ * with the valid-bit. Use the overlay to mask the verb byte. */ ++ o_dest = (struct overlay_bm_buffer *)&r->bufs[0]; ++ o_dest->first = (o_src->first & 0x0000ffff) | ++ (((u32)pool->params.bpid << 16) & 0x00ff0000); ++ o_dest->second = o_src->second; ++ if (i) ++ copy_words(&r->bufs[1], &bufs[1], i * sizeof(bufs[0])); ++ bm_rcr_pvb_commit(&p->p, BM_RCR_VERB_CMD_BPID_SINGLE | ++ (num & BM_RCR_VERB_BUFCOUNT_MASK)); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ /* if we wish to sync we need to set the threshold after h/w sees the ++ * new ring entry. As we're mixing cache-enabled and cache-inhibited ++ * accesses, this requires a heavy-weight sync. */ ++ if (unlikely((flags & BMAN_RELEASE_FLAG_WAIT) && ++ (flags & BMAN_RELEASE_FLAG_WAIT_SYNC))) { ++ hwsync(); ++ bm_rcr_set_ithresh(&p->p, 1); ++ } ++#endif ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & BMAN_RELEASE_FLAG_WAIT) && ++ (flags & BMAN_RELEASE_FLAG_WAIT_SYNC))) { ++ if (flags & BMAN_RELEASE_FLAG_WAIT_INT) ++ wait_event_interruptible(affine_queue, ++ (p->rcri_owned != pool)); ++ else ++ wait_event(affine_queue, (p->rcri_owned != pool)); ++ } ++#endif ++ return 0; ++} ++ ++int bman_release(struct bman_pool *pool, const struct bm_buffer *bufs, u8 num, ++ u32 flags) ++{ ++ int ret = 0; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (!num || (num > 8)) ++ return -EINVAL; ++ if (pool->params.flags & BMAN_POOL_FLAG_NO_RELEASE) ++ return -EINVAL; ++#endif ++ /* Without stockpile, this API is a pass-through to the h/w operation */ ++ if (!(pool->params.flags & BMAN_POOL_FLAG_STOCKPILE)) ++ return __bman_release(pool, bufs, num, flags); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (!atomic_dec_and_test(&pool->in_use)) { ++ pr_crit("Parallel attempts to enter bman_released() detected."); ++ panic("only one instance of bman_released/acquired allowed"); ++ } ++#endif ++ /* This needs some explanation. Adding the given buffers may take the ++ * stockpile over the threshold, but in fact the stockpile may already ++ * *be* over the threshold if a previous release-to-hw attempt had ++ * failed. So we have 3 cases to cover; ++ * 1. we add to the stockpile and don't hit the threshold, ++ * 2. we add to the stockpile, hit the threshold and release-to-hw, ++ * 3. we have to release-to-hw before adding to the stockpile ++ * (not enough room in the stockpile for case 2). ++ * Our constraints on thresholds guarantee that in case 3, there must be ++ * at least 8 bufs already in the stockpile, so all release-to-hw ops ++ * are for 8 bufs. Despite all this, the API must indicate whether the ++ * given buffers were taken off the caller's hands, irrespective of ++ * whether a release-to-hw was attempted. */ ++ while (num) { ++ /* Add buffers to stockpile if they fit */ ++ if ((pool->sp_fill + num) < BMAN_STOCKPILE_SZ) { ++ copy_words(pool->sp + pool->sp_fill, bufs, ++ sizeof(struct bm_buffer) * num); ++ pool->sp_fill += num; ++ num = 0; /* --> will return success no matter what */ ++ } ++ /* Do hw op if hitting the high-water threshold */ ++ if ((pool->sp_fill + num) >= BMAN_STOCKPILE_HIGH) { ++ ret = __bman_release(pool, ++ pool->sp + (pool->sp_fill - 8), 8, flags); ++ if (ret) { ++ ret = (num ? ret : 0); ++ goto release_done; ++ } ++ pool->sp_fill -= 8; ++ } ++ } ++release_done: ++#ifdef CONFIG_FSL_DPA_CHECKING ++ atomic_inc(&pool->in_use); ++#endif ++ return ret; ++} ++EXPORT_SYMBOL(bman_release); ++ ++static inline int __bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, ++ u8 num) ++{ ++ struct bman_portal *p = get_affine_portal(); ++ struct bm_mc_command *mcc; ++ struct bm_mc_result *mcr; ++ __maybe_unused unsigned long irqflags; ++ int ret; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = bm_mc_start(&p->p); ++ mcc->acquire.bpid = pool->params.bpid; ++ bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE | ++ (num & BM_MCC_VERB_ACQUIRE_BUFCOUNT)); ++ while (!(mcr = bm_mc_result(&p->p))) ++ cpu_relax(); ++ ret = mcr->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT; ++ if (bufs) ++ copy_words(&bufs[0], &mcr->acquire.bufs[0], ++ num * sizeof(bufs[0])); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (ret != num) ++ ret = -ENOMEM; ++ return ret; ++} ++ ++int bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, u8 num, ++ u32 flags) ++{ ++ int ret = 0; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (!num || (num > 8)) ++ return -EINVAL; ++ if (pool->params.flags & BMAN_POOL_FLAG_ONLY_RELEASE) ++ return -EINVAL; ++#endif ++ /* Without stockpile, this API is a pass-through to the h/w operation */ ++ if (!(pool->params.flags & BMAN_POOL_FLAG_STOCKPILE)) ++ return __bman_acquire(pool, bufs, num); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (!atomic_dec_and_test(&pool->in_use)) { ++ pr_crit("Parallel attempts to enter bman_acquire() detected."); ++ panic("only one instance of bman_released/acquired allowed"); ++ } ++#endif ++ /* Only need a h/w op if we'll hit the low-water thresh */ ++ if (!(flags & BMAN_ACQUIRE_FLAG_STOCKPILE) && ++ (pool->sp_fill <= (BMAN_STOCKPILE_LOW + num))) { ++ /* refill stockpile with max amount, but if max amount ++ * isn't available, try amount the user wants */ ++ int bufcount = 8; ++ ret = __bman_acquire(pool, pool->sp + pool->sp_fill, bufcount); ++ if (ret < 0 && bufcount != num) { ++ bufcount = num; ++ /* Maybe buffer pool has less than 8 */ ++ ret = __bman_acquire(pool, pool->sp + pool->sp_fill, ++ bufcount); ++ } ++ if (ret < 0) ++ goto hw_starved; ++ DPA_ASSERT(ret == bufcount); ++ pool->sp_fill += bufcount; ++ } else { ++hw_starved: ++ if (pool->sp_fill < num) { ++ ret = -ENOMEM; ++ goto acquire_done; ++ } ++ } ++ copy_words(bufs, pool->sp + (pool->sp_fill - num), ++ sizeof(struct bm_buffer) * num); ++ pool->sp_fill -= num; ++ ret = num; ++acquire_done: ++#ifdef CONFIG_FSL_DPA_CHECKING ++ atomic_inc(&pool->in_use); ++#endif ++ return ret; ++} ++EXPORT_SYMBOL(bman_acquire); ++ ++int bman_flush_stockpile(struct bman_pool *pool, u32 flags) ++{ ++ u8 num; ++ int ret; ++ ++ while (pool->sp_fill) { ++ num = ((pool->sp_fill > 8) ? 8 : pool->sp_fill); ++ ret = __bman_release(pool, pool->sp + (pool->sp_fill - num), ++ num, flags); ++ if (ret) ++ return ret; ++ pool->sp_fill -= num; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(bman_flush_stockpile); ++ ++int bman_query_pools(struct bm_pool_state *state) ++{ ++ struct bman_portal *p = get_affine_portal(); ++ struct bm_mc_result *mcr; ++ __maybe_unused unsigned long irqflags; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ bm_mc_start(&p->p); ++ bm_mc_commit(&p->p, BM_MCC_VERB_CMD_QUERY); ++ while (!(mcr = bm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & BM_MCR_VERB_CMD_MASK) == BM_MCR_VERB_CMD_QUERY); ++ *state = mcr->query; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return 0; ++} ++EXPORT_SYMBOL(bman_query_pools); ++ ++#ifdef CONFIG_FSL_BMAN_CONFIG ++u32 bman_query_free_buffers(struct bman_pool *pool) ++{ ++ return bm_pool_free_buffers(pool->params.bpid); ++} ++EXPORT_SYMBOL(bman_query_free_buffers); ++ ++int bman_update_pool_thresholds(struct bman_pool *pool, const u32 *thresholds) ++{ ++ u32 bpid; ++ ++ bpid = bman_get_params(pool)->bpid; ++ ++ return bm_pool_set(bpid, thresholds); ++} ++EXPORT_SYMBOL(bman_update_pool_thresholds); ++#endif +diff --git a/drivers/staging/fsl_qbman/bman_low.h b/drivers/staging/fsl_qbman/bman_low.h +new file mode 100644 +index 0000000..262bae7 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_low.h +@@ -0,0 +1,494 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "bman_private.h" ++ ++/***************************/ ++/* Portal register assists */ ++/***************************/ ++ ++/* Cache-inhibited register offsets */ ++#define REG_RCR_PI_CINH 0x0000 ++#define REG_RCR_CI_CINH 0x0004 ++#define REG_RCR_ITR 0x0008 ++#define REG_CFG 0x0100 ++#define REG_SCN(n) (0x0200 + ((n) << 2)) ++#define REG_ISR 0x0e00 ++ ++/* Cache-enabled register offsets */ ++#define CL_CR 0x0000 ++#define CL_RR0 0x0100 ++#define CL_RR1 0x0140 ++#define CL_RCR 0x1000 ++#define CL_RCR_PI_CENA 0x3000 ++#define CL_RCR_CI_CENA 0x3100 ++ ++/* BTW, the drivers (and h/w programming model) already obtain the required ++ * synchronisation for portal accesses via lwsync(), hwsync(), and ++ * data-dependencies. Use of barrier()s or other order-preserving primitives ++ * simply degrade performance. Hence the use of the __raw_*() interfaces, which ++ * simply ensure that the compiler treats the portal registers as volatile (ie. ++ * non-coherent). */ ++ ++/* Cache-inhibited register access. */ ++#define __bm_in(bm, o) __raw_readl((bm)->addr_ci + (o)) ++#define __bm_out(bm, o, val) __raw_writel((val), (bm)->addr_ci + (o)) ++#define bm_in(reg) __bm_in(&portal->addr, REG_##reg) ++#define bm_out(reg, val) __bm_out(&portal->addr, REG_##reg, val) ++ ++/* Cache-enabled (index) register access */ ++#define __bm_cl_touch_ro(bm, o) dcbt_ro((bm)->addr_ce + (o)) ++#define __bm_cl_touch_rw(bm, o) dcbt_rw((bm)->addr_ce + (o)) ++#define __bm_cl_in(bm, o) __raw_readl((bm)->addr_ce + (o)) ++#define __bm_cl_out(bm, o, val) \ ++ do { \ ++ u32 *__tmpclout = (bm)->addr_ce + (o); \ ++ __raw_writel((val), __tmpclout); \ ++ dcbf(__tmpclout); \ ++ } while (0) ++#define __bm_cl_invalidate(bm, o) dcbi((bm)->addr_ce + (o)) ++#define bm_cl_touch_ro(reg) __bm_cl_touch_ro(&portal->addr, CL_##reg##_CENA) ++#define bm_cl_touch_rw(reg) __bm_cl_touch_rw(&portal->addr, CL_##reg##_CENA) ++#define bm_cl_in(reg) __bm_cl_in(&portal->addr, CL_##reg##_CENA) ++#define bm_cl_out(reg, val) __bm_cl_out(&portal->addr, CL_##reg##_CENA, val) ++#define bm_cl_invalidate(reg) __bm_cl_invalidate(&portal->addr, CL_##reg##_CENA) ++ ++/* Cyclic helper for rings. FIXME: once we are able to do fine-grain perf ++ * analysis, look at using the "extra" bit in the ring index registers to avoid ++ * cyclic issues. */ ++static inline u8 cyc_diff(u8 ringsize, u8 first, u8 last) ++{ ++ /* 'first' is included, 'last' is excluded */ ++ if (first <= last) ++ return last - first; ++ return ringsize + last - first; ++} ++ ++/* Portal modes. ++ * Enum types; ++ * pmode == production mode ++ * cmode == consumption mode, ++ * Enum values use 3 letter codes. First letter matches the portal mode, ++ * remaining two letters indicate; ++ * ci == cache-inhibited portal register ++ * ce == cache-enabled portal register ++ * vb == in-band valid-bit (cache-enabled) ++ */ ++enum bm_rcr_pmode { /* matches BCSP_CFG::RPM */ ++ bm_rcr_pci = 0, /* PI index, cache-inhibited */ ++ bm_rcr_pce = 1, /* PI index, cache-enabled */ ++ bm_rcr_pvb = 2 /* valid-bit */ ++}; ++enum bm_rcr_cmode { /* s/w-only */ ++ bm_rcr_cci, /* CI index, cache-inhibited */ ++ bm_rcr_cce /* CI index, cache-enabled */ ++}; ++ ++ ++/* ------------------------- */ ++/* --- Portal structures --- */ ++ ++#define BM_RCR_SIZE 8 ++ ++struct bm_rcr { ++ struct bm_rcr_entry *ring, *cursor; ++ u8 ci, available, ithresh, vbit; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ u32 busy; ++ enum bm_rcr_pmode pmode; ++ enum bm_rcr_cmode cmode; ++#endif ++}; ++ ++struct bm_mc { ++ struct bm_mc_command *cr; ++ struct bm_mc_result *rr; ++ u8 rridx, vbit; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ enum { ++ /* Can only be _mc_start()ed */ ++ mc_idle, ++ /* Can only be _mc_commit()ed or _mc_abort()ed */ ++ mc_user, ++ /* Can only be _mc_retry()ed */ ++ mc_hw ++ } state; ++#endif ++}; ++ ++struct bm_addr { ++ void __iomem *addr_ce; /* cache-enabled */ ++ void __iomem *addr_ci; /* cache-inhibited */ ++}; ++ ++struct bm_portal { ++ struct bm_addr addr; ++ struct bm_rcr rcr; ++ struct bm_mc mc; ++ struct bm_portal_config config; ++} ____cacheline_aligned; ++ ++ ++/* --------------- */ ++/* --- RCR API --- */ ++ ++/* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */ ++#define RCR_CARRYCLEAR(p) \ ++ (void *)((unsigned long)(p) & (~(unsigned long)(BM_RCR_SIZE << 6))) ++ ++/* Bit-wise logic to convert a ring pointer to a ring index */ ++static inline u8 RCR_PTR2IDX(struct bm_rcr_entry *e) ++{ ++ return ((uintptr_t)e >> 6) & (BM_RCR_SIZE - 1); ++} ++ ++/* Increment the 'cursor' ring pointer, taking 'vbit' into account */ ++static inline void RCR_INC(struct bm_rcr *rcr) ++{ ++ /* NB: this is odd-looking, but experiments show that it generates ++ * fast code with essentially no branching overheads. We increment to ++ * the next RCR pointer and handle overflow and 'vbit'. */ ++ struct bm_rcr_entry *partial = rcr->cursor + 1; ++ rcr->cursor = RCR_CARRYCLEAR(partial); ++ if (partial != rcr->cursor) ++ rcr->vbit ^= BM_RCR_VERB_VBIT; ++} ++ ++static inline int bm_rcr_init(struct bm_portal *portal, enum bm_rcr_pmode pmode, ++ __maybe_unused enum bm_rcr_cmode cmode) ++{ ++ /* This use of 'register', as well as all other occurances, is because ++ * it has been observed to generate much faster code with gcc than is ++ * otherwise the case. */ ++ register struct bm_rcr *rcr = &portal->rcr; ++ u32 cfg; ++ u8 pi; ++ ++ rcr->ring = portal->addr.addr_ce + CL_RCR; ++ rcr->ci = bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1); ++ pi = bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1); ++ rcr->cursor = rcr->ring + pi; ++ rcr->vbit = (bm_in(RCR_PI_CINH) & BM_RCR_SIZE) ? BM_RCR_VERB_VBIT : 0; ++ rcr->available = BM_RCR_SIZE - 1 - cyc_diff(BM_RCR_SIZE, rcr->ci, pi); ++ rcr->ithresh = bm_in(RCR_ITR); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ rcr->busy = 0; ++ rcr->pmode = pmode; ++ rcr->cmode = cmode; ++#endif ++ cfg = (bm_in(CFG) & 0xffffffe0) | (pmode & 0x3); /* BCSP_CFG::RPM */ ++ bm_out(CFG, cfg); ++ return 0; ++} ++ ++static inline void bm_rcr_finish(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ u8 pi = bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1); ++ u8 ci = bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1); ++ DPA_ASSERT(!rcr->busy); ++ if (pi != RCR_PTR2IDX(rcr->cursor)) ++ pr_crit("losing uncommited RCR entries\n"); ++ if (ci != rcr->ci) ++ pr_crit("missing existing RCR completions\n"); ++ if (rcr->ci != RCR_PTR2IDX(rcr->cursor)) ++ pr_crit("RCR destroyed unquiesced\n"); ++} ++ ++static inline struct bm_rcr_entry *bm_rcr_start(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(!rcr->busy); ++ if (!rcr->available) ++ return NULL; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ rcr->busy = 1; ++#endif ++ dcbz_64(rcr->cursor); ++ return rcr->cursor; ++} ++ ++static inline void bm_rcr_abort(struct bm_portal *portal) ++{ ++ __maybe_unused register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(rcr->busy); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ rcr->busy = 0; ++#endif ++} ++ ++static inline struct bm_rcr_entry *bm_rcr_pend_and_next( ++ struct bm_portal *portal, u8 myverb) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(rcr->busy); ++ DPA_ASSERT(rcr->pmode != bm_rcr_pvb); ++ if (rcr->available == 1) ++ return NULL; ++ rcr->cursor->__dont_write_directly__verb = myverb | rcr->vbit; ++ dcbf_64(rcr->cursor); ++ RCR_INC(rcr); ++ rcr->available--; ++ dcbz_64(rcr->cursor); ++ return rcr->cursor; ++} ++ ++static inline void bm_rcr_pci_commit(struct bm_portal *portal, u8 myverb) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(rcr->busy); ++ DPA_ASSERT(rcr->pmode == bm_rcr_pci); ++ rcr->cursor->__dont_write_directly__verb = myverb | rcr->vbit; ++ RCR_INC(rcr); ++ rcr->available--; ++ hwsync(); ++ bm_out(RCR_PI_CINH, RCR_PTR2IDX(rcr->cursor)); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ rcr->busy = 0; ++#endif ++} ++ ++static inline void bm_rcr_pce_prefetch(struct bm_portal *portal) ++{ ++ __maybe_unused register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(rcr->pmode == bm_rcr_pce); ++ bm_cl_invalidate(RCR_PI); ++ bm_cl_touch_rw(RCR_PI); ++} ++ ++static inline void bm_rcr_pce_commit(struct bm_portal *portal, u8 myverb) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(rcr->busy); ++ DPA_ASSERT(rcr->pmode == bm_rcr_pce); ++ rcr->cursor->__dont_write_directly__verb = myverb | rcr->vbit; ++ RCR_INC(rcr); ++ rcr->available--; ++ lwsync(); ++ bm_cl_out(RCR_PI, RCR_PTR2IDX(rcr->cursor)); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ rcr->busy = 0; ++#endif ++} ++ ++static inline void bm_rcr_pvb_commit(struct bm_portal *portal, u8 myverb) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ struct bm_rcr_entry *rcursor; ++ DPA_ASSERT(rcr->busy); ++ DPA_ASSERT(rcr->pmode == bm_rcr_pvb); ++ lwsync(); ++ rcursor = rcr->cursor; ++ rcursor->__dont_write_directly__verb = myverb | rcr->vbit; ++ dcbf_64(rcursor); ++ RCR_INC(rcr); ++ rcr->available--; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ rcr->busy = 0; ++#endif ++} ++ ++static inline u8 bm_rcr_cci_update(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ u8 diff, old_ci = rcr->ci; ++ DPA_ASSERT(rcr->cmode == bm_rcr_cci); ++ rcr->ci = bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1); ++ diff = cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci); ++ rcr->available += diff; ++ return diff; ++} ++ ++static inline void bm_rcr_cce_prefetch(struct bm_portal *portal) ++{ ++ __maybe_unused register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(rcr->cmode == bm_rcr_cce); ++ bm_cl_touch_ro(RCR_CI); ++} ++ ++static inline u8 bm_rcr_cce_update(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ u8 diff, old_ci = rcr->ci; ++ DPA_ASSERT(rcr->cmode == bm_rcr_cce); ++ rcr->ci = bm_cl_in(RCR_CI) & (BM_RCR_SIZE - 1); ++ bm_cl_invalidate(RCR_CI); ++ diff = cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci); ++ rcr->available += diff; ++ return diff; ++} ++ ++static inline u8 bm_rcr_get_ithresh(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ return rcr->ithresh; ++} ++ ++static inline void bm_rcr_set_ithresh(struct bm_portal *portal, u8 ithresh) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ rcr->ithresh = ithresh; ++ bm_out(RCR_ITR, ithresh); ++} ++ ++static inline u8 bm_rcr_get_avail(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ return rcr->available; ++} ++ ++static inline u8 bm_rcr_get_fill(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ return BM_RCR_SIZE - 1 - rcr->available; ++} ++ ++ ++/* ------------------------------ */ ++/* --- Management command API --- */ ++ ++static inline int bm_mc_init(struct bm_portal *portal) ++{ ++ register struct bm_mc *mc = &portal->mc; ++ mc->cr = portal->addr.addr_ce + CL_CR; ++ mc->rr = portal->addr.addr_ce + CL_RR0; ++ mc->rridx = (__raw_readb(&mc->cr->__dont_write_directly__verb) & ++ BM_MCC_VERB_VBIT) ? 0 : 1; ++ mc->vbit = mc->rridx ? BM_MCC_VERB_VBIT : 0; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_idle; ++#endif ++ return 0; ++} ++ ++static inline void bm_mc_finish(struct bm_portal *portal) ++{ ++ __maybe_unused register struct bm_mc *mc = &portal->mc; ++ DPA_ASSERT(mc->state == mc_idle); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (mc->state != mc_idle) ++ pr_crit("Losing incomplete MC command\n"); ++#endif ++} ++ ++static inline struct bm_mc_command *bm_mc_start(struct bm_portal *portal) ++{ ++ register struct bm_mc *mc = &portal->mc; ++ DPA_ASSERT(mc->state == mc_idle); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_user; ++#endif ++ dcbz_64(mc->cr); ++ return mc->cr; ++} ++ ++static inline void bm_mc_abort(struct bm_portal *portal) ++{ ++ __maybe_unused register struct bm_mc *mc = &portal->mc; ++ DPA_ASSERT(mc->state == mc_user); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_idle; ++#endif ++} ++ ++static inline void bm_mc_commit(struct bm_portal *portal, u8 myverb) ++{ ++ register struct bm_mc *mc = &portal->mc; ++ struct bm_mc_result *rr = mc->rr + mc->rridx; ++ DPA_ASSERT(mc->state == mc_user); ++ lwsync(); ++ mc->cr->__dont_write_directly__verb = myverb | mc->vbit; ++ dcbf(mc->cr); ++ dcbit_ro(rr); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_hw; ++#endif ++} ++ ++static inline struct bm_mc_result *bm_mc_result(struct bm_portal *portal) ++{ ++ register struct bm_mc *mc = &portal->mc; ++ struct bm_mc_result *rr = mc->rr + mc->rridx; ++ DPA_ASSERT(mc->state == mc_hw); ++ /* The inactive response register's verb byte always returns zero until ++ * its command is submitted and completed. This includes the valid-bit, ++ * in case you were wondering... */ ++ if (!__raw_readb(&rr->verb)) { ++ dcbit_ro(rr); ++ return NULL; ++ } ++ mc->rridx ^= 1; ++ mc->vbit ^= BM_MCC_VERB_VBIT; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_idle; ++#endif ++ return rr; ++} ++ ++ ++/* ------------------------------------- */ ++/* --- Portal interrupt register API --- */ ++ ++static inline int bm_isr_init(__always_unused struct bm_portal *portal) ++{ ++ return 0; ++} ++ ++static inline void bm_isr_finish(__always_unused struct bm_portal *portal) ++{ ++} ++ ++#define SCN_REG(bpid) REG_SCN((bpid) / 32) ++#define SCN_BIT(bpid) (0x80000000 >> (bpid & 31)) ++static inline void bm_isr_bscn_mask(struct bm_portal *portal, u8 bpid, ++ int enable) ++{ ++ u32 val; ++ DPA_ASSERT(bpid < bman_pool_max); ++ /* REG_SCN for bpid=0..31, REG_SCN+4 for bpid=32..63 */ ++ val = __bm_in(&portal->addr, SCN_REG(bpid)); ++ if (enable) ++ val |= SCN_BIT(bpid); ++ else ++ val &= ~SCN_BIT(bpid); ++ __bm_out(&portal->addr, SCN_REG(bpid), val); ++} ++ ++static inline u32 __bm_isr_read(struct bm_portal *portal, enum bm_isr_reg n) ++{ ++ return __bm_in(&portal->addr, REG_ISR + (n << 2)); ++} ++ ++static inline void __bm_isr_write(struct bm_portal *portal, enum bm_isr_reg n, ++ u32 val) ++{ ++ __bm_out(&portal->addr, REG_ISR + (n << 2), val); ++} +diff --git a/drivers/staging/fsl_qbman/bman_private.h b/drivers/staging/fsl_qbman/bman_private.h +new file mode 100644 +index 0000000..c567314 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_private.h +@@ -0,0 +1,144 @@ ++/* Copyright 2008-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "dpa_sys.h" ++#include ++ ++/* Revision info (for errata and feature handling) */ ++#define BMAN_REV10 0x0100 ++#define BMAN_REV20 0x0200 ++#define BMAN_REV21 0x0201 ++extern u16 bman_ip_rev; /* 0 if uninitialised, otherwise QMAN_REVx */ ++ ++/* ++ * Global variables of the max portal/pool number this bman version supported ++ */ ++extern u16 bman_pool_max; ++ ++/* used by CCSR and portal interrupt code */ ++enum bm_isr_reg { ++ bm_isr_status = 0, ++ bm_isr_enable = 1, ++ bm_isr_disable = 2, ++ bm_isr_inhibit = 3 ++}; ++ ++struct bm_portal_config { ++ /* Corenet portal addresses; ++ * [0]==cache-enabled, [1]==cache-inhibited. */ ++ __iomem void *addr_virt[2]; ++ struct resource addr_phys[2]; ++ /* Allow these to be joined in lists */ ++ struct list_head list; ++ /* User-visible portal configuration settings */ ++ struct bman_portal_config public_cfg; ++}; ++ ++#ifdef CONFIG_FSL_BMAN_CONFIG ++/* Hooks from bman_driver.c to bman_config.c */ ++int bman_init_ccsr(struct device_node *node); ++#endif ++ ++/* Hooks from bman_driver.c in to bman_high.c */ ++struct bman_portal *bman_create_affine_portal( ++ const struct bm_portal_config *config); ++struct bman_portal *bman_create_affine_slave(struct bman_portal *redirect); ++const struct bm_portal_config *bman_destroy_affine_portal(void); ++ ++/* Pool logic in the portal driver, during initialisation, needs to know if ++ * there's access to CCSR or not (if not, it'll cripple the pool allocator). */ ++#ifdef CONFIG_FSL_BMAN_CONFIG ++int bman_have_ccsr(void); ++#else ++#define bman_have_ccsr() 0 ++#endif ++ ++/* Stockpile build constants. The _LOW value: when bman_acquire() is called and ++ * the stockpile fill-level is <= _LOW, an acquire is attempted from h/w but it ++ * might fail (if the buffer pool is depleted). So this value provides some ++ * "stagger" in that the bman_acquire() function will only fail if lots of bufs ++ * are requested at once or if h/w has been tested a couple of times without ++ * luck. The _HIGH value: when bman_release() is called and the stockpile ++ * fill-level is >= _HIGH, a release is attempted to h/w but it might fail (if ++ * the release ring is full). So this value provides some "stagger" so that ++ * ring-access is retried a couple of times prior to the API returning a ++ * failure. The following *must* be true; ++ * BMAN_STOCKPILE_HIGH-BMAN_STOCKPILE_LOW > 8 ++ * (to avoid thrashing) ++ * BMAN_STOCKPILE_SZ >= 16 ++ * (as the release logic expects to either send 8 buffers to hw prior to ++ * adding the given buffers to the stockpile or add the buffers to the ++ * stockpile before sending 8 to hw, as the API must be an all-or-nothing ++ * success/fail.) ++ */ ++#define BMAN_STOCKPILE_SZ 16u /* number of bufs in per-pool cache */ ++#define BMAN_STOCKPILE_LOW 2u /* when fill is <= this, acquire from hw */ ++#define BMAN_STOCKPILE_HIGH 14u /* when fill is >= this, release to hw */ ++ ++/*************************************************/ ++/* BMan s/w corenet portal, low-level i/face */ ++/*************************************************/ ++ ++/* Used by all portal interrupt registers except 'inhibit'. NB, some of these ++ * definitions are exported for use by the bman_irqsource_***() APIs, so are ++ * commented-out here. */ ++#if 0 ++#define BM_PIRQ_RCRI 0x00000002 /* RCR Ring (below threshold) */ ++#define BM_PIRQ_BSCN 0x00000001 /* Buffer depletion State Change */ ++#endif ++/* This mask contains all the "irqsource" bits visible to API users */ ++#define BM_PIRQ_VISIBLE (BM_PIRQ_RCRI | BM_PIRQ_BSCN) ++ ++/* These are bm__(). So for example, bm_disable_write() means "write ++ * the disable register" rather than "disable the ability to write". */ ++#define bm_isr_status_read(bm) __bm_isr_read(bm, bm_isr_status) ++#define bm_isr_status_clear(bm, m) __bm_isr_write(bm, bm_isr_status, m) ++#define bm_isr_enable_read(bm) __bm_isr_read(bm, bm_isr_enable) ++#define bm_isr_enable_write(bm, v) __bm_isr_write(bm, bm_isr_enable, v) ++#define bm_isr_disable_read(bm) __bm_isr_read(bm, bm_isr_disable) ++#define bm_isr_disable_write(bm, v) __bm_isr_write(bm, bm_isr_disable, v) ++#define bm_isr_inhibit(bm) __bm_isr_write(bm, bm_isr_inhibit, 1) ++#define bm_isr_uninhibit(bm) __bm_isr_write(bm, bm_isr_inhibit, 0) ++ ++#ifdef CONFIG_FSL_BMAN_CONFIG ++/* Set depletion thresholds associated with a buffer pool. Requires that the ++ * operating system have access to Bman CCSR (ie. compiled in support and ++ * run-time access courtesy of the device-tree). */ ++int bm_pool_set(u32 bpid, const u32 *thresholds); ++#define BM_POOL_THRESH_SW_ENTER 0 ++#define BM_POOL_THRESH_SW_EXIT 1 ++#define BM_POOL_THRESH_HW_ENTER 2 ++#define BM_POOL_THRESH_HW_EXIT 3 ++ ++/* Read the free buffer count for a given buffer */ ++u32 bm_pool_free_buffers(u32 bpid); ++ ++#endif /* CONFIG_FSL_BMAN_CONFIG */ +diff --git a/drivers/staging/fsl_qbman/bman_test.c b/drivers/staging/fsl_qbman/bman_test.c +new file mode 100644 +index 0000000..db5b7fd +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_test.c +@@ -0,0 +1,56 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "bman_test.h" ++ ++MODULE_AUTHOR("Geoff Thorpe"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("Bman testing"); ++ ++static int test_init(void) ++{ ++#ifdef CONFIG_FSL_BMAN_TEST_HIGH ++ int loop = 1; ++ while (loop--) ++ bman_test_high(); ++#endif ++#ifdef CONFIG_FSL_BMAN_TEST_THRESH ++ bman_test_thresh(); ++#endif ++ return 0; ++} ++ ++static void test_exit(void) ++{ ++} ++ ++module_init(test_init); ++module_exit(test_exit); +diff --git a/drivers/staging/fsl_qbman/bman_test.h b/drivers/staging/fsl_qbman/bman_test.h +new file mode 100644 +index 0000000..27c7c05 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_test.h +@@ -0,0 +1,91 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++void bman_test_high(void); ++void bman_test_thresh(void); ++ ++static inline void __hexdump(unsigned long start, unsigned long end, ++ unsigned long p, size_t sz, unsigned char *c) ++{ ++ while (start < end) { ++ unsigned int pos = 0; ++ char buf[64]; ++ int nl = 0; ++ pos += sprintf(buf + pos, "%08lx: ", start); ++ do { ++ if ((start < p) || (start >= (p + sz))) ++ pos += sprintf(buf + pos, ".."); ++ else ++ pos += sprintf(buf + pos, "%02x", *(c++)); ++ if (!(++start & 15)) { ++ buf[pos++] = '\n'; ++ nl = 1; ++ } else { ++ nl = 0; ++ if(!(start & 1)) ++ buf[pos++] = ' '; ++ if(!(start & 3)) ++ buf[pos++] = ' '; ++ } ++ } while (start & 15); ++ if (!nl) ++ buf[pos++] = '\n'; ++ buf[pos] = '\0'; ++ pr_info("%s", buf); ++ } ++} ++static inline void hexdump(void *ptr, size_t sz) ++{ ++ unsigned long p = (unsigned long)ptr; ++ unsigned long start = p & ~(unsigned long)15; ++ unsigned long end = (p + sz + 15) & ~(unsigned long)15; ++ unsigned char *c = ptr; ++ __hexdump(start, end, p, sz, c); ++} ++static inline void hexdump_by_cl(void *ptr, size_t sz) ++{ ++ unsigned long p = (unsigned long)ptr; ++ unsigned long start = p & ~(unsigned long)63; ++ unsigned long end = (p + sz + 63) & ~(unsigned long)63; ++ unsigned char *c = ptr; ++ __hexdump(start, end, p, sz, c); ++} +diff --git a/drivers/staging/fsl_qbman/bman_test_high.c b/drivers/staging/fsl_qbman/bman_test_high.c +new file mode 100644 +index 0000000..f2a5284 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_test_high.c +@@ -0,0 +1,181 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "bman_test.h" ++#include "bman_private.h" ++ ++/*************/ ++/* constants */ ++/*************/ ++ ++#define PORTAL_OPAQUE (void *)0xf00dbeef ++#define POOL_OPAQUE (void *)0xdeadabba ++#define NUM_BUFS 93 ++#define LOOPS 3 ++#define BMAN_TOKEN_MASK 0x00FFFFFFFFFFLLU ++ ++/***************/ ++/* global vars */ ++/***************/ ++ ++static struct bman_pool *pool; ++static int depleted; ++static struct bm_buffer bufs_in[NUM_BUFS] ____cacheline_aligned; ++static struct bm_buffer bufs_out[NUM_BUFS] ____cacheline_aligned; ++static int bufs_received; ++ ++/* Predeclare the callback so we can instantiate pool parameters */ ++static void depletion_cb(struct bman_portal *, struct bman_pool *, void *, int); ++ ++/**********************/ ++/* internal functions */ ++/**********************/ ++ ++static void bufs_init(void) ++{ ++ int i; ++ for (i = 0; i < NUM_BUFS; i++) ++ bm_buffer_set64(&bufs_in[i], 0xfedc01234567LLU * i); ++ bufs_received = 0; ++} ++ ++static inline int bufs_cmp(const struct bm_buffer *a, const struct bm_buffer *b) ++{ ++ if ((bman_ip_rev == BMAN_REV20) || (bman_ip_rev == BMAN_REV21)) { ++ ++ /* On SoCs with Bman revison 2.0, Bman only respects the 40 ++ * LS-bits of buffer addresses, masking off the upper 8-bits on ++ * release commands. The API provides for 48-bit addresses ++ * because some SoCs support all 48-bits. When generating ++ * garbage addresses for testing, we either need to zero the ++ * upper 8-bits when releasing to Bman (otherwise we'll be ++ * disappointed when the buffers we acquire back from Bman ++ * don't match), or we need to mask the upper 8-bits off when ++ * comparing. We do the latter. ++ */ ++ if ((bm_buffer_get64(a) & BMAN_TOKEN_MASK) ++ < (bm_buffer_get64(b) & BMAN_TOKEN_MASK)) ++ return -1; ++ if ((bm_buffer_get64(a) & BMAN_TOKEN_MASK) ++ > (bm_buffer_get64(b) & BMAN_TOKEN_MASK)) ++ return 1; ++ } else { ++ if (bm_buffer_get64(a) < bm_buffer_get64(b)) ++ return -1; ++ if (bm_buffer_get64(a) > bm_buffer_get64(b)) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void bufs_confirm(void) ++{ ++ int i, j; ++ for (i = 0; i < NUM_BUFS; i++) { ++ int matches = 0; ++ for (j = 0; j < NUM_BUFS; j++) ++ if (!bufs_cmp(&bufs_in[i], &bufs_out[j])) ++ matches++; ++ BUG_ON(matches != 1); ++ } ++} ++ ++/********/ ++/* test */ ++/********/ ++ ++static void depletion_cb(struct bman_portal *__portal, struct bman_pool *__pool, ++ void *pool_ctx, int __depleted) ++{ ++ BUG_ON(__pool != pool); ++ BUG_ON(pool_ctx != POOL_OPAQUE); ++ depleted = __depleted; ++} ++ ++void bman_test_high(void) ++{ ++ struct bman_pool_params pparams = { ++ .flags = BMAN_POOL_FLAG_DEPLETION | BMAN_POOL_FLAG_DYNAMIC_BPID, ++ .cb = depletion_cb, ++ .cb_ctx = POOL_OPAQUE, ++ }; ++ int i, loops = LOOPS; ++ ++ bufs_init(); ++ ++ pr_info("BMAN: --- starting high-level test ---\n"); ++ ++ pool = bman_new_pool(&pparams); ++ BUG_ON(!pool); ++ ++ /*******************/ ++ /* Release buffers */ ++ /*******************/ ++do_loop: ++ i = 0; ++ while (i < NUM_BUFS) { ++ u32 flags = BMAN_RELEASE_FLAG_WAIT; ++ int num = 8; ++ if ((i + num) > NUM_BUFS) ++ num = NUM_BUFS - i; ++ if ((i + num) == NUM_BUFS) ++ flags |= BMAN_RELEASE_FLAG_WAIT_SYNC; ++ if (bman_release(pool, bufs_in + i, num, flags)) ++ panic("bman_release() failed\n"); ++ i += num; ++ } ++ ++ /*******************/ ++ /* Acquire buffers */ ++ /*******************/ ++ while (i > 0) { ++ int tmp, num = 8; ++ if (num > i) ++ num = i; ++ tmp = bman_acquire(pool, bufs_out + i - num, num, 0); ++ BUG_ON(tmp != num); ++ i -= num; ++ } ++ i = bman_acquire(pool, NULL, 1, 0); ++ BUG_ON(i > 0); ++ ++ bufs_confirm(); ++ ++ if (--loops) ++ goto do_loop; ++ ++ /************/ ++ /* Clean up */ ++ /************/ ++ bman_free_pool(pool); ++ pr_info("BMAN: --- finished high-level test ---\n"); ++} +diff --git a/drivers/staging/fsl_qbman/bman_test_thresh.c b/drivers/staging/fsl_qbman/bman_test_thresh.c +new file mode 100644 +index 0000000..b11862f +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_test_thresh.c +@@ -0,0 +1,196 @@ ++/* Copyright 2010-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "bman_test.h" ++ ++/* Test constants */ ++#define TEST_NUMBUFS 129728 ++#define TEST_EXIT 129536 ++#define TEST_ENTRY 129024 ++ ++struct affine_test_data { ++ struct task_struct *t; ++ int cpu; ++ int expect_affinity; ++ int drain; ++ int num_enter; ++ int num_exit; ++ struct list_head node; ++ struct completion wakethread; ++ struct completion wakeparent; ++}; ++ ++static void cb_depletion(struct bman_portal *portal, ++ struct bman_pool *pool, ++ void *opaque, ++ int depleted) ++{ ++ struct affine_test_data *data = opaque; ++ int c = smp_processor_id(); ++ pr_info("cb_depletion: bpid=%d, depleted=%d, cpu=%d, original=%d\n", ++ bman_get_params(pool)->bpid, depleted, c, data->cpu); ++ /* We should be executing on the CPU of the thread that owns the pool if ++ * and that CPU has an affine portal (ie. it isn't slaved). */ ++ BUG_ON((c != data->cpu) && data->expect_affinity); ++ BUG_ON((c == data->cpu) && !data->expect_affinity); ++ if (depleted) ++ data->num_enter++; ++ else ++ data->num_exit++; ++} ++ ++/* Params used to set up a pool, this also dynamically allocates a BPID */ ++struct bman_pool_params params_nocb = { ++ .flags = BMAN_POOL_FLAG_DYNAMIC_BPID | BMAN_POOL_FLAG_THRESH, ++ .thresholds = { TEST_ENTRY, TEST_EXIT, 0, 0 } ++}; ++ ++/* Params used to set up each cpu's pool with callbacks enabled */ ++struct bman_pool_params params_cb = { ++ .bpid = 0, /* will be replaced to match pool_nocb */ ++ .flags = BMAN_POOL_FLAG_DEPLETION, ++ .cb = cb_depletion ++}; ++ ++static struct bman_pool *pool_nocb; ++static LIST_HEAD(threads); ++ ++static int affine_test(void *__data) ++{ ++ struct bman_pool *pool; ++ struct affine_test_data *data = __data; ++ struct bman_pool_params my_params = params_cb; ++ ++ pr_info("thread %d: starting\n", data->cpu); ++ /* create the pool */ ++ my_params.cb_ctx = data; ++ pool = bman_new_pool(&my_params); ++ BUG_ON(!pool); ++ complete(&data->wakeparent); ++ wait_for_completion(&data->wakethread); ++ init_completion(&data->wakethread); ++ ++ /* if we're the drainer, we get signalled for that */ ++ if (data->drain) { ++ struct bm_buffer buf; ++ int ret; ++ pr_info("thread %d: draining...\n", data->cpu); ++ do { ++ ret = bman_acquire(pool, &buf, 1, 0); ++ } while (ret > 0); ++ pr_info("thread %d: draining done.\n", data->cpu); ++ complete(&data->wakeparent); ++ wait_for_completion(&data->wakethread); ++ init_completion(&data->wakethread); ++ } ++ ++ /* cleanup */ ++ bman_free_pool(pool); ++ while (!kthread_should_stop()) ++ cpu_relax(); ++ pr_info("thread %d: exiting\n", data->cpu); ++ return 0; ++} ++ ++static struct affine_test_data *start_affine_test(int cpu, int drain) ++{ ++ struct affine_test_data *data = kmalloc(sizeof(*data), GFP_KERNEL); ++ ++ if (!data) ++ return NULL; ++ data->cpu = cpu; ++ data->expect_affinity = cpumask_test_cpu(cpu, bman_affine_cpus()); ++ data->drain = drain; ++ data->num_enter = 0; ++ data->num_exit = 0; ++ init_completion(&data->wakethread); ++ init_completion(&data->wakeparent); ++ list_add_tail(&data->node, &threads); ++ data->t = kthread_create(affine_test, data, "threshtest%d", cpu); ++ BUG_ON(IS_ERR(data->t)); ++ kthread_bind(data->t, cpu); ++ wake_up_process(data->t); ++ return data; ++} ++ ++void bman_test_thresh(void) ++{ ++ int loop = TEST_NUMBUFS; ++ int ret, num_cpus = 0; ++ struct affine_test_data *data, *drainer = NULL; ++ ++ pr_info("bman_test_thresh: start\n"); ++ ++ /* allocate a BPID and seed it */ ++ pool_nocb = bman_new_pool(¶ms_nocb); ++ BUG_ON(!pool_nocb); ++ while (loop--) { ++ struct bm_buffer buf; ++ bm_buffer_set64(&buf, 0x0badbeef + loop); ++ ret = bman_release(pool_nocb, &buf, 1, ++ BMAN_RELEASE_FLAG_WAIT); ++ BUG_ON(ret); ++ } ++ while (!bman_rcr_is_empty()) ++ cpu_relax(); ++ pr_info("bman_test_thresh: buffers are in\n"); ++ ++ /* create threads and wait for them to create pools */ ++ params_cb.bpid = bman_get_params(pool_nocb)->bpid; ++ for_each_cpu(loop, cpu_online_mask) { ++ data = start_affine_test(loop, drainer ? 0 : 1); ++ BUG_ON(!data); ++ if (!drainer) ++ drainer = data; ++ num_cpus++; ++ wait_for_completion(&data->wakeparent); ++ } ++ ++ /* signal the drainer to start draining */ ++ complete(&drainer->wakethread); ++ wait_for_completion(&drainer->wakeparent); ++ init_completion(&drainer->wakeparent); ++ ++ /* tear down */ ++ list_for_each_entry_safe(data, drainer, &threads, node) { ++ complete(&data->wakethread); ++ ret = kthread_stop(data->t); ++ BUG_ON(ret); ++ list_del(&data->node); ++ /* check that we get the expected callbacks (and no others) */ ++ BUG_ON(data->num_enter != 1); ++ BUG_ON(data->num_exit != 0); ++ kfree(data); ++ } ++ bman_free_pool(pool_nocb); ++ ++ pr_info("bman_test_thresh: done\n"); ++} +diff --git a/drivers/staging/fsl_qbman/dpa_alloc.c b/drivers/staging/fsl_qbman/dpa_alloc.c +new file mode 100644 +index 0000000..03a9d28 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/dpa_alloc.c +@@ -0,0 +1,503 @@ ++/* Copyright 2009-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "dpa_sys.h" ++#include ++#include ++ ++/* Qman and Bman APIs are front-ends to the common code; */ ++ ++static DECLARE_DPA_ALLOC(bpalloc); /* BPID allocator */ ++static DECLARE_DPA_ALLOC(fqalloc); /* FQID allocator */ ++static DECLARE_DPA_ALLOC(qpalloc); /* pool-channel allocator */ ++static DECLARE_DPA_ALLOC(cgralloc); /* CGR ID allocator */ ++static DECLARE_DPA_ALLOC(ceetm0_challoc); /* CEETM Channel ID allocator */ ++static DECLARE_DPA_ALLOC(ceetm0_lfqidalloc); /* CEETM LFQID allocator */ ++static DECLARE_DPA_ALLOC(ceetm1_challoc); /* CEETM Channel ID allocator */ ++static DECLARE_DPA_ALLOC(ceetm1_lfqidalloc); /* CEETM LFQID allocator */ ++ ++/* This is a sort-of-conditional dpa_alloc_free() routine. Eg. when releasing ++ * FQIDs (probably from user-space), it can filter out those that aren't in the ++ * OOS state (better to leak a h/w resource than to crash). This function ++ * returns the number of invalid IDs that were not released. */ ++static u32 release_id_range(struct dpa_alloc *alloc, u32 id, u32 count, ++ int (*is_valid)(u32 id)) ++{ ++ int valid_mode = 0; ++ u32 loop = id, total_invalid = 0; ++ while (loop < (id + count)) { ++ int isvalid = is_valid ? is_valid(loop) : 1; ++ if (!valid_mode) { ++ /* We're looking for a valid ID to terminate an invalid ++ * range */ ++ if (isvalid) { ++ /* We finished a range of invalid IDs, a valid ++ * range is now underway */ ++ valid_mode = 1; ++ count -= (loop - id); ++ id = loop; ++ } else ++ total_invalid++; ++ } else { ++ /* We're looking for an invalid ID to terminate a ++ * valid range */ ++ if (!isvalid) { ++ /* Release the range of valid IDs, an unvalid ++ * range is now underway */ ++ if (loop > id) ++ dpa_alloc_free(alloc, id, loop - id); ++ valid_mode = 0; ++ } ++ } ++ loop++; ++ } ++ /* Release any unterminated range of valid IDs */ ++ if (valid_mode && count) ++ dpa_alloc_free(alloc, id, count); ++ return total_invalid; ++} ++ ++/* BPID allocator front-end */ ++ ++int bman_alloc_bpid_range(u32 *result, u32 count, u32 align, int partial) ++{ ++ return dpa_alloc_new(&bpalloc, result, count, align, partial); ++} ++EXPORT_SYMBOL(bman_alloc_bpid_range); ++ ++static int bp_valid(u32 bpid) ++{ ++ struct bm_pool_state state; ++ int ret = bman_query_pools(&state); ++ BUG_ON(ret); ++ if (bman_depletion_get(&state.as.state, bpid)) ++ /* "Available==1" means unavailable, go figure. Ie. it has no ++ * buffers, which is means it is valid for deallocation. (So ++ * true means false, which means true...) */ ++ return 1; ++ return 0; ++} ++void bman_release_bpid_range(u32 bpid, u32 count) ++{ ++ u32 total_invalid = release_id_range(&bpalloc, bpid, count, bp_valid); ++ if (total_invalid) ++ pr_err("BPID range [%d..%d] (%d) had %d leaks\n", ++ bpid, bpid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(bman_release_bpid_range); ++ ++/* FQID allocator front-end */ ++ ++int qman_alloc_fqid_range(u32 *result, u32 count, u32 align, int partial) ++{ ++ return dpa_alloc_new(&fqalloc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_fqid_range); ++ ++static int fq_valid(u32 fqid) ++{ ++ struct qman_fq fq = { ++ .fqid = fqid ++ }; ++ struct qm_mcr_queryfq_np np; ++ int err = qman_query_fq_np(&fq, &np); ++ BUG_ON(err); ++ return ((np.state & QM_MCR_NP_STATE_MASK) == QM_MCR_NP_STATE_OOS); ++} ++void qman_release_fqid_range(u32 fqid, u32 count) ++{ ++ u32 total_invalid = release_id_range(&fqalloc, fqid, count, fq_valid); ++ if (total_invalid) ++ pr_err("FQID range [%d..%d] (%d) had %d leaks\n", ++ fqid, fqid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(qman_release_fqid_range); ++ ++/* Pool-channel allocator front-end */ ++ ++int qman_alloc_pool_range(u32 *result, u32 count, u32 align, int partial) ++{ ++ return dpa_alloc_new(&qpalloc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_pool_range); ++ ++static int qp_valid(u32 qp) ++{ ++ /* TBD: when resource-management improves, we may be able to find ++ * something better than this. Currently we query all FQDs starting from ++ * FQID 1 until we get an "invalid FQID" error, looking for non-OOS FQDs ++ * whose destination channel is the pool-channel being released. */ ++ struct qman_fq fq = { ++ .fqid = 1 ++ }; ++ int err; ++ do { ++ struct qm_mcr_queryfq_np np; ++ err = qman_query_fq_np(&fq, &np); ++ if (err) ++ /* FQID range exceeded, found no problems */ ++ return 1; ++ if ((np.state & QM_MCR_NP_STATE_MASK) != QM_MCR_NP_STATE_OOS) { ++ struct qm_fqd fqd; ++ err = qman_query_fq(&fq, &fqd); ++ BUG_ON(err); ++ if (fqd.dest.channel == qp) ++ /* The channel is the FQ's target, can't free */ ++ return 0; ++ } ++ /* Move to the next FQID */ ++ fq.fqid++; ++ } while (1); ++} ++void qman_release_pool_range(u32 qp, u32 count) ++{ ++ u32 total_invalid = release_id_range(&qpalloc, qp, count, qp_valid); ++ if (total_invalid) { ++ /* Pool channels are almost always used individually */ ++ if (count == 1) ++ pr_err("Pool channel 0x%x had %d leaks\n", ++ qp, total_invalid); ++ else ++ pr_err("Pool channels [%d..%d] (%d) had %d leaks\n", ++ qp, qp + count - 1, count, total_invalid); ++ } ++} ++EXPORT_SYMBOL(qman_release_pool_range); ++ ++/* CGR ID allocator front-end */ ++ ++int qman_alloc_cgrid_range(u32 *result, u32 count, u32 align, int partial) ++{ ++ return dpa_alloc_new(&cgralloc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_cgrid_range); ++ ++void qman_release_cgrid_range(u32 cgrid, u32 count) ++{ ++ u32 total_invalid = release_id_range(&cgralloc, cgrid, count, NULL); ++ if (total_invalid) ++ pr_err("CGRID range [%d..%d] (%d) had %d leaks\n", ++ cgrid, cgrid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(qman_release_cgrid_range); ++ ++/* CEETM CHANNEL ID allocator front-end */ ++int qman_alloc_ceetm0_channel_range(u32 *result, u32 count, u32 align, ++ int partial) ++{ ++ return dpa_alloc_new(&ceetm0_challoc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_ceetm0_channel_range); ++ ++int qman_alloc_ceetm1_channel_range(u32 *result, u32 count, u32 align, ++ int partial) ++{ ++ return dpa_alloc_new(&ceetm1_challoc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_ceetm1_channel_range); ++ ++void qman_release_ceetm0_channel_range(u32 channelid, u32 count) ++{ ++ u32 total_invalid; ++ ++ total_invalid = release_id_range(&ceetm0_challoc, channelid, count, ++ NULL); ++ if (total_invalid) ++ pr_err("CEETM channel range [%d..%d] (%d) had %d leaks\n", ++ channelid, channelid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(qman_release_ceetm0_channel_range); ++ ++void qman_release_ceetm1_channel_range(u32 channelid, u32 count) ++{ ++ u32 total_invalid; ++ total_invalid = release_id_range(&ceetm1_challoc, channelid, count, ++ NULL); ++ if (total_invalid) ++ pr_err("CEETM channel range [%d..%d] (%d) had %d leaks\n", ++ channelid, channelid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(qman_release_ceetm1_channel_range); ++ ++/* CEETM LFQID allocator front-end */ ++int qman_alloc_ceetm0_lfqid_range(u32 *result, u32 count, u32 align, ++ int partial) ++{ ++ return dpa_alloc_new(&ceetm0_lfqidalloc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_ceetm0_lfqid_range); ++ ++int qman_alloc_ceetm1_lfqid_range(u32 *result, u32 count, u32 align, ++ int partial) ++{ ++ return dpa_alloc_new(&ceetm1_lfqidalloc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_ceetm1_lfqid_range); ++ ++void qman_release_ceetm0_lfqid_range(u32 lfqid, u32 count) ++{ ++ u32 total_invalid; ++ ++ total_invalid = release_id_range(&ceetm0_lfqidalloc, lfqid, count, ++ NULL); ++ if (total_invalid) ++ pr_err("CEETM LFQID range [0x%x..0x%x] (%d) had %d leaks\n", ++ lfqid, lfqid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(qman_release_ceetm0_lfqid_range); ++ ++void qman_release_ceetm1_lfqid_range(u32 lfqid, u32 count) ++{ ++ u32 total_invalid; ++ ++ total_invalid = release_id_range(&ceetm1_lfqidalloc, lfqid, count, ++ NULL); ++ if (total_invalid) ++ pr_err("CEETM LFQID range [0x%x..0x%x] (%d) had %d leaks\n", ++ lfqid, lfqid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(qman_release_ceetm1_lfqid_range); ++ ++/* Everything else is the common backend to all the allocators */ ++ ++/* The allocator is a (possibly-empty) list of these; */ ++struct alloc_node { ++ struct list_head list; ++ u32 base; ++ u32 num; ++}; ++ ++/* #define DPA_ALLOC_DEBUG */ ++ ++#ifdef DPA_ALLOC_DEBUG ++#define DPRINT pr_info ++static void DUMP(struct dpa_alloc *alloc) ++{ ++ int off = 0; ++ char buf[256]; ++ struct alloc_node *p; ++ list_for_each_entry(p, &alloc->list, list) { ++ if (off < 255) ++ off += snprintf(buf + off, 255-off, "{%d,%d}", ++ p->base, p->base + p->num - 1); ++ } ++ pr_info("%s\n", buf); ++} ++#else ++#define DPRINT(x...) do { ; } while (0) ++#define DUMP(a) do { ; } while (0) ++#endif ++ ++int dpa_alloc_new(struct dpa_alloc *alloc, u32 *result, u32 count, u32 align, ++ int partial) ++{ ++ struct alloc_node *i = NULL, *next_best = NULL; ++ u32 base, next_best_base = 0, num = 0, next_best_num = 0; ++ struct alloc_node *margin_left, *margin_right; ++ ++ *result = (u32)-1; ++ DPRINT("alloc_range(%d,%d,%d)\n", count, align, partial); ++ DUMP(alloc); ++ /* If 'align' is 0, it should behave as though it was 1 */ ++ if (!align) ++ align = 1; ++ margin_left = kmalloc(sizeof(*margin_left), GFP_KERNEL); ++ if (!margin_left) ++ goto err; ++ margin_right = kmalloc(sizeof(*margin_right), GFP_KERNEL); ++ if (!margin_right) { ++ kfree(margin_left); ++ goto err; ++ } ++ spin_lock_irq(&alloc->lock); ++ list_for_each_entry(i, &alloc->list, list) { ++ base = (i->base + align - 1) / align; ++ base *= align; ++ if ((base - i->base) >= i->num) ++ /* alignment is impossible, regardless of count */ ++ continue; ++ num = i->num - (base - i->base); ++ if (num >= count) { ++ /* this one will do nicely */ ++ num = count; ++ goto done; ++ } ++ if (num > next_best_num) { ++ next_best = i; ++ next_best_base = base; ++ next_best_num = num; ++ } ++ } ++ if (partial && next_best) { ++ i = next_best; ++ base = next_best_base; ++ num = next_best_num; ++ } else ++ i = NULL; ++done: ++ if (i) { ++ if (base != i->base) { ++ margin_left->base = i->base; ++ margin_left->num = base - i->base; ++ list_add_tail(&margin_left->list, &i->list); ++ } else ++ kfree(margin_left); ++ if ((base + num) < (i->base + i->num)) { ++ margin_right->base = base + num; ++ margin_right->num = (i->base + i->num) - ++ (base + num); ++ list_add(&margin_right->list, &i->list); ++ } else ++ kfree(margin_right); ++ list_del(&i->list); ++ kfree(i); ++ *result = base; ++ } ++ spin_unlock_irq(&alloc->lock); ++err: ++ DPRINT("returning %d\n", i ? num : -ENOMEM); ++ DUMP(alloc); ++ return i ? (int)num : -ENOMEM; ++} ++ ++/* Allocate the list node using GFP_ATOMIC, because we *really* want to avoid ++ * forcing error-handling on to users in the deallocation path. */ ++void dpa_alloc_free(struct dpa_alloc *alloc, u32 base_id, u32 count) ++{ ++ struct alloc_node *i, *node = kmalloc(sizeof(*node), GFP_ATOMIC); ++ BUG_ON(!node); ++ DPRINT("release_range(%d,%d)\n", base_id, count); ++ DUMP(alloc); ++ BUG_ON(!count); ++ spin_lock_irq(&alloc->lock); ++ node->base = base_id; ++ node->num = count; ++ list_for_each_entry(i, &alloc->list, list) { ++ if (i->base >= node->base) { ++ /* BUG_ON(any overlapping) */ ++ BUG_ON(i->base < (node->base + node->num)); ++ list_add_tail(&node->list, &i->list); ++ goto done; ++ } ++ } ++ list_add_tail(&node->list, &alloc->list); ++done: ++ /* Merge to the left */ ++ i = list_entry(node->list.prev, struct alloc_node, list); ++ if (node->list.prev != &alloc->list) { ++ BUG_ON((i->base + i->num) > node->base); ++ if ((i->base + i->num) == node->base) { ++ node->base = i->base; ++ node->num += i->num; ++ list_del(&i->list); ++ kfree(i); ++ } ++ } ++ /* Merge to the right */ ++ i = list_entry(node->list.next, struct alloc_node, list); ++ if (node->list.next != &alloc->list) { ++ BUG_ON((node->base + node->num) > i->base); ++ if ((node->base + node->num) == i->base) { ++ node->num += i->num; ++ list_del(&i->list); ++ kfree(i); ++ } ++ } ++ spin_unlock_irq(&alloc->lock); ++ DUMP(alloc); ++} ++ ++int dpa_alloc_reserve(struct dpa_alloc *alloc, u32 base, u32 num) ++{ ++ struct alloc_node *i = NULL; ++ struct alloc_node *margin_left, *margin_right; ++ ++ DPRINT("alloc_reserve(%d,%d)\n", base_id, count); ++ DUMP(alloc); ++ margin_left = kmalloc(sizeof(*margin_left), GFP_KERNEL); ++ if (!margin_left) ++ goto err; ++ margin_right = kmalloc(sizeof(*margin_right), GFP_KERNEL); ++ if (!margin_right) { ++ kfree(margin_left); ++ goto err; ++ } ++ spin_lock_irq(&alloc->lock); ++ list_for_each_entry(i, &alloc->list, list) ++ if ((i->base <= base) && ((i->base + i->num) >= (base + num))) ++ /* yep, the reservation is within this node */ ++ goto done; ++ i = NULL; ++done: ++ if (i) { ++ if (base != i->base) { ++ margin_left->base = i->base; ++ margin_left->num = base - i->base; ++ list_add_tail(&margin_left->list, &i->list); ++ } else ++ kfree(margin_left); ++ if ((base + num) < (i->base + i->num)) { ++ margin_right->base = base + num; ++ margin_right->num = (i->base + i->num) - ++ (base + num); ++ list_add(&margin_right->list, &i->list); ++ } else ++ kfree(margin_right); ++ list_del(&i->list); ++ kfree(i); ++ } ++ spin_unlock_irq(&alloc->lock); ++err: ++ DPRINT("returning %d\n", i ? 0 : -ENOMEM); ++ DUMP(alloc); ++ return i ? 0 : -ENOMEM; ++} ++ ++int dpa_alloc_pop(struct dpa_alloc *alloc, u32 *result, u32 *count) ++{ ++ struct alloc_node *i = NULL; ++ DPRINT("alloc_pop()\n"); ++ DUMP(alloc); ++ spin_lock_irq(&alloc->lock); ++ if (!list_empty(&alloc->list)) { ++ i = list_entry(alloc->list.next, struct alloc_node, list); ++ list_del(&i->list); ++ } ++ spin_unlock_irq(&alloc->lock); ++ DPRINT("returning %d\n", i ? 0 : -ENOMEM); ++ DUMP(alloc); ++ if (!i) ++ return -ENOMEM; ++ *result = i->base; ++ *count = i->num; ++ kfree(i); ++ return 0; ++} +diff --git a/drivers/staging/fsl_qbman/dpa_sys.h b/drivers/staging/fsl_qbman/dpa_sys.h +new file mode 100644 +index 0000000..8adc656 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/dpa_sys.h +@@ -0,0 +1,353 @@ ++/* Copyright 2008-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 DPA_SYS_H ++#define DPA_SYS_H ++ ++#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 ++ ++/* When copying aligned words or shorts, try to avoid memcpy() */ ++#define CONFIG_TRY_BETTER_MEMCPY ++ ++/* Handle portals destined for USDPAA (user-space). ++ * ++ * The UIO handling is mostly in dpa_uio.c which is common to qman and bman, but ++ * there are some specifics to each case, and they have independent data ++ * structures. The "pcfg"s for qman and bman portals are maintained in lists in ++ * their respective drivers, and they're detached from those lists when they are ++ * to be registered as UIO devices, so we have dpa_uio.c store them in a ++ * mixed-type list, and use this vtable of callbacks to let the qman+bman ++ * drivers container_of() the list item to their respective object wrappers and ++ * implement whatever logic distinguishes them. ++ */ ++struct dpa_uio_vtable { ++ /* This callback should fill in 'name', 'mem', and 'irq'. The rest will ++ * be filled in by dpa_uio.c */ ++ int (*init_uio)(const struct list_head *pcfg, struct uio_info *info); ++ /* Free up whatever object contains 'pcfg' */ ++ void (*destroy)(const struct list_head *pcfg, struct uio_info *info); ++ /* Called when the portal is opened (Qman uses this for rerouting ++ * stashing to the current cpu) */ ++ int (*on_open)(const struct list_head *pcfg); ++ void (*on_close)(const struct list_head *pcfg); ++ /* Called when an interrupt fires - must disable interrupts */ ++ void (*on_interrupt)(const struct list_head *pcfg); ++}; ++int __init dpa_uio_register(struct list_head *new_pcfg, ++ const struct dpa_uio_vtable *vtable); ++ ++/* For 2-element tables related to cache-inhibited and cache-enabled mappings */ ++#define DPA_PORTAL_CE 0 ++#define DPA_PORTAL_CI 1 ++ ++/* These stubs are re-mapped to hypervisor+failover features in kernel trees ++ * that contain that support. */ ++static inline int pamu_enable_liodn(struct device_node *n, int i) ++{ ++ return 0; ++} ++/***********************/ ++/* Misc inline assists */ ++/***********************/ ++ ++/* TODO: NB, we currently assume that hwsync() and lwsync() imply compiler ++ * barriers and that dcb*() won't fall victim to compiler or execution ++ * reordering with respect to other code/instructions that manipulate the same ++ * cacheline. */ ++#define hwsync() \ ++ do { \ ++ __asm__ __volatile__ ("sync" : : : "memory"); \ ++ } while(0) ++#define lwsync() \ ++ do { \ ++ __asm__ __volatile__ (stringify_in_c(LWSYNC) : : : "memory"); \ ++ } while(0) ++#define dcbf(p) \ ++ do { \ ++ __asm__ __volatile__ ("dcbf 0,%0" : : "r" (p) : "memory"); \ ++ } while(0) ++#define dcbt_ro(p) \ ++ do { \ ++ __asm__ __volatile__ ("dcbt 0,%0" : : "r" (p)); \ ++ } while(0) ++#define dcbt_rw(p) \ ++ do { \ ++ __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (p)); \ ++ } while(0) ++#define dcbi(p) dcbf(p) ++#ifdef CONFIG_PPC_E500MC ++#define dcbzl(p) \ ++ do { \ ++ __asm__ __volatile__ ("dcbzl 0,%0" : : "r" (p)); \ ++ } while (0) ++#define dcbz_64(p) \ ++ do { \ ++ dcbzl(p); \ ++ } while (0) ++#define dcbf_64(p) \ ++ do { \ ++ dcbf(p); \ ++ } while (0) ++/* Commonly used combo */ ++#define dcbit_ro(p) \ ++ do { \ ++ dcbi(p); \ ++ dcbt_ro(p); \ ++ } while (0) ++#else ++#define dcbz(p) \ ++ do { \ ++ __asm__ __volatile__ ("dcbz 0,%0" : : "r" (p)); \ ++ } while (0) ++#define dcbz_64(p) \ ++ do { \ ++ dcbz((u32)p + 32); \ ++ dcbz(p); \ ++ } while (0) ++#define dcbf_64(p) \ ++ do { \ ++ dcbf((u32)p + 32); \ ++ dcbf(p); \ ++ } while (0) ++/* Commonly used combo */ ++#define dcbit_ro(p) \ ++ do { \ ++ dcbi(p); \ ++ dcbi((u32)p + 32); \ ++ dcbt_ro(p); \ ++ dcbt_ro((u32)p + 32); \ ++ } while (0) ++#endif /* CONFIG_PPC_E500MC */ ++ ++static inline u64 mfatb(void) ++{ ++ u32 hi, lo, chk; ++ do { ++ hi = mfspr(SPRN_ATBU); ++ lo = mfspr(SPRN_ATBL); ++ chk = mfspr(SPRN_ATBU); ++ } while (unlikely(hi != chk)); ++ return ((u64)hi << 32) | (u64)lo; ++} ++ ++#ifdef CONFIG_FSL_DPA_CHECKING ++#define DPA_ASSERT(x) \ ++ do { \ ++ if (!(x)) { \ ++ pr_crit("ASSERT: (%s:%d) %s\n", __FILE__, __LINE__, \ ++ __stringify_1(x)); \ ++ dump_stack(); \ ++ panic("assertion failure"); \ ++ } \ ++ } while(0) ++#else ++#define DPA_ASSERT(x) ++#endif ++ ++/* memcpy() stuff - when you know alignments in advance */ ++#ifdef CONFIG_TRY_BETTER_MEMCPY ++static inline void copy_words(void *dest, const void *src, size_t sz) ++{ ++ u32 *__dest = dest; ++ const u32 *__src = src; ++ size_t __sz = sz >> 2; ++ BUG_ON((unsigned long)dest & 0x3); ++ BUG_ON((unsigned long)src & 0x3); ++ BUG_ON(sz & 0x3); ++ while (__sz--) ++ *(__dest++) = *(__src++); ++} ++static inline void copy_shorts(void *dest, const void *src, size_t sz) ++{ ++ u16 *__dest = dest; ++ const u16 *__src = src; ++ size_t __sz = sz >> 1; ++ BUG_ON((unsigned long)dest & 0x1); ++ BUG_ON((unsigned long)src & 0x1); ++ BUG_ON(sz & 0x1); ++ while (__sz--) ++ *(__dest++) = *(__src++); ++} ++static inline void copy_bytes(void *dest, const void *src, size_t sz) ++{ ++ u8 *__dest = dest; ++ const u8 *__src = src; ++ while (sz--) ++ *(__dest++) = *(__src++); ++} ++#else ++#define copy_words memcpy ++#define copy_shorts memcpy ++#define copy_bytes memcpy ++#endif ++ ++/************/ ++/* RB-trees */ ++/************/ ++ ++/* We encapsulate RB-trees so that its easier to use non-linux forms in ++ * non-linux systems. This also encapsulates the extra plumbing that linux code ++ * usually provides when using RB-trees. This encapsulation assumes that the ++ * data type held by the tree is u32. */ ++ ++struct dpa_rbtree { ++ struct rb_root root; ++}; ++#define DPA_RBTREE { .root = RB_ROOT } ++ ++static inline void dpa_rbtree_init(struct dpa_rbtree *tree) ++{ ++ tree->root = RB_ROOT; ++} ++ ++#define IMPLEMENT_DPA_RBTREE(name, type, node_field, val_field) \ ++static inline int name##_push(struct dpa_rbtree *tree, type *obj) \ ++{ \ ++ struct rb_node *parent = NULL, **p = &tree->root.rb_node; \ ++ while (*p) { \ ++ u32 item; \ ++ parent = *p; \ ++ item = rb_entry(parent, type, node_field)->val_field; \ ++ if (obj->val_field < item) \ ++ p = &parent->rb_left; \ ++ else if (obj->val_field > item) \ ++ p = &parent->rb_right; \ ++ else \ ++ return -EBUSY; \ ++ } \ ++ rb_link_node(&obj->node_field, parent, p); \ ++ rb_insert_color(&obj->node_field, &tree->root); \ ++ return 0; \ ++} \ ++static inline void name##_del(struct dpa_rbtree *tree, type *obj) \ ++{ \ ++ rb_erase(&obj->node_field, &tree->root); \ ++} \ ++static inline type *name##_find(struct dpa_rbtree *tree, u32 val) \ ++{ \ ++ type *ret; \ ++ struct rb_node *p = tree->root.rb_node; \ ++ while (p) { \ ++ ret = rb_entry(p, type, node_field); \ ++ if (val < ret->val_field) \ ++ p = p->rb_left; \ ++ else if (val > ret->val_field) \ ++ p = p->rb_right; \ ++ else \ ++ return ret; \ ++ } \ ++ return NULL; \ ++} ++ ++/************/ ++/* Bootargs */ ++/************/ ++ ++/* Qman has "qportals=" and Bman has "bportals=", they use the same syntax ++ * though; a comma-separated list of items, each item being a cpu index and/or a ++ * range of cpu indices, and each item optionally be prefixed by "s" to indicate ++ * that the portal associated with that cpu should be shared. See bman_driver.c ++ * for more specifics. */ ++static int __parse_portals_cpu(const char **s, int *cpu) ++{ ++ *cpu = 0; ++ if (!isdigit(**s)) ++ return -EINVAL; ++ while (isdigit(**s)) ++ *cpu = *cpu * 10 + (*((*s)++) - '0'); ++ return 0; ++} ++static inline int parse_portals_bootarg(char *str, struct cpumask *want_shared, ++ struct cpumask *want_unshared, ++ const char *argname) ++{ ++ const char *s = str; ++ unsigned int shared, cpu1, cpu2, loop; ++ ++keep_going: ++ if (*s == 's') { ++ shared = 1; ++ s++; ++ } else ++ shared = 0; ++ if (__parse_portals_cpu(&s, &cpu1)) ++ goto err; ++ if (*s == '-') { ++ s++; ++ if (__parse_portals_cpu(&s, &cpu2)) ++ goto err; ++ if (cpu2 < cpu1) ++ goto err; ++ } else ++ cpu2 = cpu1; ++ for (loop = cpu1; loop <= cpu2; loop++) ++ cpumask_set_cpu(loop, shared ? want_shared : want_unshared); ++ if (*s == ',') { ++ s++; ++ goto keep_going; ++ } else if ((*s == '\0') || isspace(*s)) ++ return 0; ++err: ++ pr_crit("Malformed %s argument: %s, offset: %lu\n", argname, str, ++ (unsigned long)s - (unsigned long)str); ++ return -EINVAL; ++} ++ ++#endif /* DPA_SYS_H */ +diff --git a/drivers/staging/fsl_qbman/dpa_uio.c b/drivers/staging/fsl_qbman/dpa_uio.c +new file mode 100644 +index 0000000..cdb78db +--- /dev/null ++++ b/drivers/staging/fsl_qbman/dpa_uio.c +@@ -0,0 +1,190 @@ ++/* Copyright 2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "bman_private.h" ++#include "qman_private.h" ++ ++static const char dpa_uio_version[] = "USDPAA UIO portal driver v0.2"; ++ ++static LIST_HEAD(dpa_uio_list); ++ ++struct dpa_uio_info { ++ const struct dpa_uio_vtable *vtable; ++ const struct list_head *pcfg; ++ atomic_t ref; /* exclusive, only one open() at a time */ ++ struct uio_info uio; ++ struct platform_device *pdev; ++ struct list_head node; ++}; ++ ++static int dpa_uio_open(struct uio_info *info, struct inode *inode) ++{ ++ struct dpa_uio_info *i = container_of(info, struct dpa_uio_info, uio); ++ int ret = 0; ++ ++ if (!atomic_dec_and_test(&i->ref)) { ++ atomic_inc(&i->ref); ++ return -EBUSY; ++ } ++ if (i->vtable->on_open) { ++ ret = i->vtable->on_open(i->pcfg); ++ if (ret) ++ atomic_inc(&i->ref); ++ } ++ return ret; ++} ++ ++static int dpa_uio_release(struct uio_info *info, struct inode *inode) ++{ ++ struct dpa_uio_info *i = container_of(info, struct dpa_uio_info, uio); ++ if (i->vtable->on_close) ++ i->vtable->on_close(i->pcfg); ++ atomic_inc(&i->ref); ++ return 0; ++} ++ ++static pgprot_t dpa_uio_pgprot(struct uio_info *info, unsigned int mem_idx, ++ pgprot_t prot) ++{ ++ if (mem_idx == DPA_PORTAL_CE) ++ /* It's the cache-enabled portal region. NB, we shouldn't use ++ * pgprot_cached() here because it includes _PAGE_COHERENT. The ++ * region is cachable but *not* coherent - stashing (if enabled) ++ * leads to "coherent-like" behaviour, otherwise the driver ++ * explicitly invalidates/prefetches. */ ++ return pgprot_cached_noncoherent(prot); ++ /* Otherwise it's the cache-inhibited portal region */ ++ return pgprot_noncached(prot); ++} ++ ++static irqreturn_t dpa_uio_irq_handler(int irq, struct uio_info *info) ++{ ++ struct dpa_uio_info *i = container_of(info, struct dpa_uio_info, uio); ++ i->vtable->on_interrupt(i->pcfg); ++ return IRQ_HANDLED; ++} ++ ++static int __init dpa_uio_portal_init(struct dpa_uio_info *info) ++{ ++ int ret; ++ ++ /* Fill in qbman-specific fields of uio_info */ ++ ret = info->vtable->init_uio(info->pcfg, &info->uio); ++ if (ret) { ++ pr_err("dpa_uio_portal: qbman parameter setup failed\n"); ++ return -ENODEV; ++ } ++ ++ /* Fill in common fields of uio_info */ ++ info->uio.version = dpa_uio_version; ++ info->uio.handler = dpa_uio_irq_handler; ++ info->uio.set_pgprot = dpa_uio_pgprot; ++ info->uio.open = dpa_uio_open; ++ info->uio.release = dpa_uio_release; ++ ++ /* Fill in state private to this file */ ++ atomic_set(&info->ref, 1); ++ info->pdev = platform_device_alloc(info->uio.name, -1); ++ if (!info->pdev) { ++ info->vtable->destroy(info->pcfg, &info->uio); ++ pr_err("dpa_uio_portal: platform_device_alloc() failed\n"); ++ return -ENOMEM; ++ } ++ ret = platform_device_add(info->pdev); ++ if (ret) { ++ platform_device_put(info->pdev); ++ info->vtable->destroy(info->pcfg, &info->uio); ++ pr_err("dpa_uio_portal: platform_device_add() failed\n"); ++ return -ENOMEM; ++ } ++ ++ /* Register the device */ ++ ret = uio_register_device(&info->pdev->dev, &info->uio); ++ if (ret) { ++ platform_device_del(info->pdev); ++ platform_device_put(info->pdev); ++ info->vtable->destroy(info->pcfg, &info->uio); ++ pr_err("dpa_uio_portal: UIO registration failed\n"); ++ return -EBUSY; ++ } ++ pr_info("USDPAA portal initialised, %s\n", info->uio.name); ++ return 0; ++} ++ ++static void __init dpa_uio_portal_finish(struct dpa_uio_info *info) ++{ ++ info->vtable->destroy(info->pcfg, &info->uio); ++ uio_unregister_device(&info->uio); ++ platform_device_del(info->pdev); ++ platform_device_put(info->pdev); ++ pr_info("USDPAA portal removed, %s\n", info->uio.name); ++} ++ ++static int __init dpa_uio_init(void) ++{ ++ struct dpa_uio_info *info, *tmp; ++ list_for_each_entry_safe(info, tmp, &dpa_uio_list, node) { ++ int ret = dpa_uio_portal_init(info); ++ if (ret) { ++ list_del(&info->node); ++ kfree(info); ++ } ++ } ++ pr_info("USDPAA portal layer loaded\n"); ++ return 0; ++} ++ ++static void __exit dpa_uio_exit(void) ++{ ++ struct dpa_uio_info *info, *tmp; ++ list_for_each_entry_safe(info, tmp, &dpa_uio_list, node) { ++ dpa_uio_portal_finish(info); ++ list_del(&info->node); ++ kfree(info); ++ } ++ pr_info("USDPAA portal layer unloaded\n"); ++} ++ ++int __init dpa_uio_register(struct list_head *new_pcfg, ++ const struct dpa_uio_vtable *vtable) ++{ ++ struct dpa_uio_info *info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ info->vtable = vtable; ++ info->pcfg = new_pcfg; ++ list_add_tail(&info->node, &dpa_uio_list); ++ return 0; ++} ++ ++module_init(dpa_uio_init) ++module_exit(dpa_uio_exit) ++MODULE_LICENSE("GPL"); +diff --git a/drivers/staging/fsl_qbman/qman_config.c b/drivers/staging/fsl_qbman/qman_config.c +new file mode 100644 +index 0000000..c924ab9 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_config.c +@@ -0,0 +1,1221 @@ ++/* Copyright 2008-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 CONFIG_SMP ++#include /* get_hard_smp_processor_id() */ ++#endif ++ ++#include ++#include "qman_private.h" ++ ++/* Last updated for v00.800 of the BG */ ++ ++/* Register offsets */ ++#define REG_QCSP_LIO_CFG(n) (0x0000 + ((n) * 0x10)) ++#define REG_QCSP_IO_CFG(n) (0x0004 + ((n) * 0x10)) ++#define REG_QCSP_DD_CFG(n) (0x000c + ((n) * 0x10)) ++#define REG_DD_CFG 0x0200 ++#define REG_DCP_CFG(n) (0x0300 + ((n) * 0x10)) ++#define REG_DCP_DD_CFG(n) (0x0304 + ((n) * 0x10)) ++#define REG_DCP_DLM_AVG(n) (0x030c + ((n) * 0x10)) ++#define REG_PFDR_FPC 0x0400 ++#define REG_PFDR_FP_HEAD 0x0404 ++#define REG_PFDR_FP_TAIL 0x0408 ++#define REG_PFDR_FP_LWIT 0x0410 ++#define REG_PFDR_CFG 0x0414 ++#define REG_SFDR_CFG 0x0500 ++#define REG_SFDR_IN_USE 0x0504 ++#define REG_WQ_CS_CFG(n) (0x0600 + ((n) * 0x04)) ++#define REG_WQ_DEF_ENC_WQID 0x0630 ++#define REG_WQ_SC_DD_CFG(n) (0x640 + ((n) * 0x04)) ++#define REG_WQ_PC_DD_CFG(n) (0x680 + ((n) * 0x04)) ++#define REG_WQ_DC0_DD_CFG(n) (0x6c0 + ((n) * 0x04)) ++#define REG_WQ_DC1_DD_CFG(n) (0x700 + ((n) * 0x04)) ++#define REG_WQ_DCn_DD_CFG(n) (0x6c0 + ((n) * 0x40)) /* n=2,3 */ ++#define REG_CM_CFG 0x0800 ++#define REG_ECSR 0x0a00 ++#define REG_ECIR 0x0a04 ++#define REG_EADR 0x0a08 ++#define REG_ECIR2 0x0a0c ++#define REG_EDATA(n) (0x0a10 + ((n) * 0x04)) ++#define REG_SBEC(n) (0x0a80 + ((n) * 0x04)) ++#define REG_MCR 0x0b00 ++#define REG_MCP(n) (0x0b04 + ((n) * 0x04)) ++#define REG_MISC_CFG 0x0be0 ++#define REG_HID_CFG 0x0bf0 ++#define REG_IDLE_STAT 0x0bf4 ++#define REG_IP_REV_1 0x0bf8 ++#define REG_IP_REV_2 0x0bfc ++#define REG_FQD_BARE 0x0c00 ++#define REG_PFDR_BARE 0x0c20 ++#define REG_offset_BAR 0x0004 /* relative to REG_[FQD|PFDR]_BARE */ ++#define REG_offset_AR 0x0010 /* relative to REG_[FQD|PFDR]_BARE */ ++#define REG_QCSP_BARE 0x0c80 ++#define REG_QCSP_BAR 0x0c84 ++#define REG_CI_SCHED_CFG 0x0d00 ++#define REG_SRCIDR 0x0d04 ++#define REG_LIODNR 0x0d08 ++#define REG_CI_RLM_AVG 0x0d14 ++#define REG_ERR_ISR 0x0e00 /* + "enum qm_isr_reg" */ ++#define REG_REV3_QCSP_LIO_CFG(n) (0x1000 + ((n) * 0x10)) ++#define REG_REV3_QCSP_IO_CFG(n) (0x1004 + ((n) * 0x10)) ++#define REG_REV3_QCSP_DD_CFG(n) (0x100c + ((n) * 0x10)) ++#define REG_CEETM_CFG_IDX 0x900 ++#define REG_CEETM_CFG_PRES 0x904 ++ ++/* Assists for QMAN_MCR */ ++#define MCR_INIT_PFDR 0x01000000 ++#define MCR_get_rslt(v) (u8)((v) >> 24) ++#define MCR_rslt_idle(r) (!rslt || (rslt >= 0xf0)) ++#define MCR_rslt_ok(r) (rslt == 0xf0) ++#define MCR_rslt_eaccess(r) (rslt == 0xf8) ++#define MCR_rslt_inval(r) (rslt == 0xff) ++ ++struct qman; ++ ++/* Follows WQ_CS_CFG0-5 */ ++enum qm_wq_class { ++ qm_wq_portal = 0, ++ qm_wq_pool = 1, ++ qm_wq_fman0 = 2, ++ qm_wq_fman1 = 3, ++ qm_wq_caam = 4, ++ qm_wq_pme = 5, ++ qm_wq_first = qm_wq_portal, ++ qm_wq_last = qm_wq_pme ++}; ++ ++/* Follows FQD_[BARE|BAR|AR] and PFDR_[BARE|BAR|AR] */ ++enum qm_memory { ++ qm_memory_fqd, ++ qm_memory_pfdr ++}; ++ ++/* Used by all error interrupt registers except 'inhibit' */ ++#define QM_EIRQ_CIDE 0x20000000 /* Corenet Initiator Data Error */ ++#define QM_EIRQ_CTDE 0x10000000 /* Corenet Target Data Error */ ++#define QM_EIRQ_CITT 0x08000000 /* Corenet Invalid Target Transaction */ ++#define QM_EIRQ_PLWI 0x04000000 /* PFDR Low Watermark */ ++#define QM_EIRQ_MBEI 0x02000000 /* Multi-bit ECC Error */ ++#define QM_EIRQ_SBEI 0x01000000 /* Single-bit ECC Error */ ++#define QM_EIRQ_PEBI 0x00800000 /* PFDR Enqueues Blocked Interrupt */ ++#define QM_EIRQ_IFSI 0x00020000 /* Invalid FQ Flow Control State */ ++#define QM_EIRQ_ICVI 0x00010000 /* Invalid Command Verb */ ++#define QM_EIRQ_IDDI 0x00000800 /* Invalid Dequeue (Direct-connect) */ ++#define QM_EIRQ_IDFI 0x00000400 /* Invalid Dequeue FQ */ ++#define QM_EIRQ_IDSI 0x00000200 /* Invalid Dequeue Source */ ++#define QM_EIRQ_IDQI 0x00000100 /* Invalid Dequeue Queue */ ++#define QM_EIRQ_IECE 0x00000010 /* Invalid Enqueue Configuration */ ++#define QM_EIRQ_IEOI 0x00000008 /* Invalid Enqueue Overflow */ ++#define QM_EIRQ_IESI 0x00000004 /* Invalid Enqueue State */ ++#define QM_EIRQ_IECI 0x00000002 /* Invalid Enqueue Channel */ ++#define QM_EIRQ_IEQI 0x00000001 /* Invalid Enqueue Queue */ ++ ++/* QMAN_ECIR valid error bit */ ++#define PORTAL_ECSR_ERR (QM_EIRQ_IEQI | QM_EIRQ_IESI | QM_EIRQ_IEOI | \ ++ QM_EIRQ_IDQI | QM_EIRQ_IDSI | QM_EIRQ_IDFI | \ ++ QM_EIRQ_IDDI | QM_EIRQ_ICVI | QM_EIRQ_IFSI) ++#define FQID_ECSR_ERR (QM_EIRQ_IEQI | QM_EIRQ_IECI | QM_EIRQ_IESI | \ ++ QM_EIRQ_IEOI | QM_EIRQ_IDQI | QM_EIRQ_IDFI | \ ++ QM_EIRQ_IFSI) ++ ++union qman_ecir { ++ u32 ecir_raw; ++ struct { ++ u32 __reserved:2; ++ u32 portal_type:1; ++ u32 portal_num:5; ++ u32 fqid:24; ++ } __packed info; ++}; ++ ++union qman_ecir2 { ++ u32 ecir2_raw; ++ struct { ++ u32 portal_type:1; ++ u32 __reserved:21; ++ u32 portal_num:10; ++ } __packed info; ++}; ++ ++union qman_eadr { ++ u32 eadr_raw; ++ struct { ++ u32 __reserved1:4; ++ u32 memid:4; ++ u32 __reserved2:12; ++ u32 eadr:12; ++ } __packed info; ++ struct { ++ u32 __reserved1:3; ++ u32 memid:5; ++ u32 __reserved:8; ++ u32 eadr:16; ++ } __packed info_rev3; ++}; ++ ++struct qman_hwerr_txt { ++ u32 mask; ++ const char *txt; ++}; ++ ++#define QMAN_HWE_TXT(a, b) { .mask = QM_EIRQ_##a, .txt = b } ++ ++static const struct qman_hwerr_txt qman_hwerr_txts[] = { ++ QMAN_HWE_TXT(CIDE, "Corenet Initiator Data Error"), ++ QMAN_HWE_TXT(CTDE, "Corenet Target Data Error"), ++ QMAN_HWE_TXT(CITT, "Corenet Invalid Target Transaction"), ++ QMAN_HWE_TXT(PLWI, "PFDR Low Watermark"), ++ QMAN_HWE_TXT(MBEI, "Multi-bit ECC Error"), ++ QMAN_HWE_TXT(SBEI, "Single-bit ECC Error"), ++ QMAN_HWE_TXT(PEBI, "PFDR Enqueues Blocked Interrupt"), ++ QMAN_HWE_TXT(ICVI, "Invalid Command Verb"), ++ QMAN_HWE_TXT(IFSI, "Invalid Flow Control State"), ++ QMAN_HWE_TXT(IDDI, "Invalid Dequeue (Direct-connect)"), ++ QMAN_HWE_TXT(IDFI, "Invalid Dequeue FQ"), ++ QMAN_HWE_TXT(IDSI, "Invalid Dequeue Source"), ++ QMAN_HWE_TXT(IDQI, "Invalid Dequeue Queue"), ++ QMAN_HWE_TXT(IECE, "Invalid Enqueue Configuration"), ++ QMAN_HWE_TXT(IEOI, "Invalid Enqueue Overflow"), ++ QMAN_HWE_TXT(IESI, "Invalid Enqueue State"), ++ QMAN_HWE_TXT(IECI, "Invalid Enqueue Channel"), ++ QMAN_HWE_TXT(IEQI, "Invalid Enqueue Queue") ++}; ++#define QMAN_HWE_COUNT (sizeof(qman_hwerr_txts)/sizeof(struct qman_hwerr_txt)) ++ ++struct qman_error_info_mdata { ++ u16 addr_mask; ++ u16 bits; ++ const char *txt; ++}; ++ ++#define QMAN_ERR_MDATA(a, b, c) { .addr_mask = a, .bits = b, .txt = c} ++static const struct qman_error_info_mdata error_mdata[] = { ++ QMAN_ERR_MDATA(0x01FF, 24, "FQD cache tag memory 0"), ++ QMAN_ERR_MDATA(0x01FF, 24, "FQD cache tag memory 1"), ++ QMAN_ERR_MDATA(0x01FF, 24, "FQD cache tag memory 2"), ++ QMAN_ERR_MDATA(0x01FF, 24, "FQD cache tag memory 3"), ++ QMAN_ERR_MDATA(0x0FFF, 512, "FQD cache memory"), ++ QMAN_ERR_MDATA(0x07FF, 128, "SFDR memory"), ++ QMAN_ERR_MDATA(0x01FF, 72, "WQ context memory"), ++ QMAN_ERR_MDATA(0x00FF, 240, "CGR memory"), ++ QMAN_ERR_MDATA(0x00FF, 302, "Internal Order Restoration List memory"), ++ QMAN_ERR_MDATA(0x01FF, 256, "SW portal ring memory"), ++ QMAN_ERR_MDATA(0x07FF, 181, "CEETM class queue descriptor memory"), ++ QMAN_ERR_MDATA(0x0FFF, 140, "CEETM extended SFDR memory"), ++ QMAN_ERR_MDATA(0x0FFF, 25, "CEETM logical FQ mapping memory"), ++ QMAN_ERR_MDATA(0x0FFF, 96, "CEETM dequeue context memory"), ++ QMAN_ERR_MDATA(0x07FF, 396, "CEETM ccgr memory"), ++ QMAN_ERR_MDATA(0x00FF, 146, "CEETM CQ channel shaping memory"), ++ QMAN_ERR_MDATA(0x007F, 256, "CEETM CQ channel scheduling memory"), ++ QMAN_ERR_MDATA(0x01FF, 88, "CEETM dequeue statistics memory"), ++}; ++#define QMAN_ERR_MDATA_COUNT \ ++ (sizeof(error_mdata)/sizeof(struct qman_error_info_mdata)) ++ ++/* Add this in Kconfig */ ++#define QMAN_ERRS_TO_UNENABLE (QM_EIRQ_PLWI | QM_EIRQ_PEBI) ++ ++/** ++ * qm_err_isr__ - Manipulate global interrupt registers ++ * @v: for accessors that write values, this is the 32-bit value ++ * ++ * Manipulates QMAN_ERR_ISR, QMAN_ERR_IER, QMAN_ERR_ISDR, QMAN_ERR_IIR. All ++ * manipulations except qm_err_isr_[un]inhibit() use 32-bit masks composed of ++ * the QM_EIRQ_*** definitions. Note that "qm_err_isr_enable_write" means ++ * "write the enable register" rather than "enable the write register"! ++ */ ++#define qm_err_isr_status_read(qm) __qm_err_isr_read(qm, qm_isr_status) ++#define qm_err_isr_status_clear(qm, m) __qm_err_isr_write(qm, qm_isr_status,m) ++#define qm_err_isr_enable_read(qm) __qm_err_isr_read(qm, qm_isr_enable) ++#define qm_err_isr_enable_write(qm, v) __qm_err_isr_write(qm, qm_isr_enable,v) ++#define qm_err_isr_disable_read(qm) __qm_err_isr_read(qm, qm_isr_disable) ++#define qm_err_isr_disable_write(qm, v) __qm_err_isr_write(qm, qm_isr_disable,v) ++#define qm_err_isr_inhibit(qm) __qm_err_isr_write(qm, qm_isr_inhibit,1) ++#define qm_err_isr_uninhibit(qm) __qm_err_isr_write(qm, qm_isr_inhibit,0) ++ ++/* ++ * TODO: unimplemented registers ++ * ++ * Keeping a list here of Qman registers I have not yet covered; ++ * QCSP_DD_IHRSR, QCSP_DD_IHRFR, QCSP_DD_HASR, ++ * DCP_DD_IHRSR, DCP_DD_IHRFR, DCP_DD_HASR, CM_CFG, ++ * QMAN_EECC, QMAN_SBET, QMAN_EINJ, QMAN_SBEC0-12 ++ */ ++ ++/* Encapsulate "struct qman *" as a cast of the register space address. */ ++ ++static struct qman *qm_create(void *regs) ++{ ++ return (struct qman *)regs; ++} ++ ++static inline u32 __qm_in(struct qman *qm, u32 offset) ++{ ++ return in_be32((void *)qm + offset); ++} ++static inline void __qm_out(struct qman *qm, u32 offset, u32 val) ++{ ++ out_be32((void *)qm + offset, val); ++} ++#define qm_in(reg) __qm_in(qm, REG_##reg) ++#define qm_out(reg, val) __qm_out(qm, REG_##reg, val) ++ ++static u32 __qm_err_isr_read(struct qman *qm, enum qm_isr_reg n) ++{ ++ return __qm_in(qm, REG_ERR_ISR + (n << 2)); ++} ++ ++static void __qm_err_isr_write(struct qman *qm, enum qm_isr_reg n, u32 val) ++{ ++ __qm_out(qm, REG_ERR_ISR + (n << 2), val); ++} ++ ++#if 0 ++ ++static void qm_set_portal(struct qman *qm, u8 swportalID, ++ u16 ec_tp_cfg, u16 ecd_tp_cfg) ++{ ++ qm_out(QCSP_DD_CFG(swportalID), ++ ((ec_tp_cfg & 0x1ff) << 16) | (ecd_tp_cfg & 0x1ff)); ++} ++ ++static void qm_set_ddebug(struct qman *qm, u8 mdd, u8 m_cfg) ++{ ++ qm_out(DD_CFG, ((mdd & 0x3) << 4) | (m_cfg & 0xf)); ++} ++ ++static void qm_set_dc_ddebug(struct qman *qm, enum qm_dc_portal portal, u16 ecd_tp_cfg) ++{ ++ qm_out(DCP_DD_CFG(portal), ecd_tp_cfg & 0x1ff); ++} ++ ++static u32 qm_get_pfdr_free_pool_count(struct qman *qm) ++{ ++ return qm_in(PFDR_FPC); ++} ++ ++static void qm_get_pfdr_free_pool(struct qman *qm, u32 *head, u32 *tail) ++{ ++ *head = qm_in(PFDR_FP_HEAD); ++ *tail = qm_in(PFDR_FP_TAIL); ++} ++ ++static void qm_set_default_wq(struct qman *qm, u16 wqid) ++{ ++ qm_out(WQ_DEF_ENC_WQID, wqid); ++} ++ ++static void qm_set_channel_ddebug(struct qman *qm, u16 channel, u16 tp_cfg) ++{ ++ u32 offset; ++ int upperhalf = 0; ++ if ((channel >= QM_CHANNEL_SWPORTAL0) && ++ (channel <= qm_channel_swportal9)) { ++ offset = (channel - QM_CHANNEL_SWPORTAL0); ++ upperhalf = offset & 0x1; ++ offset = REG_WQ_SC_DD_CFG(offset / 2); ++ } else if ((channel >= qm_channel_pool1) && ++ (channel <= qm_channel_pool15)) { ++ offset = (channel + 1 - qm_channel_pool1); ++ upperhalf = offset & 0x1; ++ offset = REG_WQ_PC_DD_CFG(offset / 2); ++ } else if ((channel >= qm_channel_fman0_sp0) && ++ (channel <= qm_channel_fman0_sp11)) { ++ offset = (channel - qm_channel_fman0_sp0); ++ upperhalf = offset & 0x1; ++ offset = REG_WQ_DC0_DD_CFG(offset / 2); ++ } ++ else if ((channel >= qm_channel_fman1_sp0) && ++ (channel <= qm_channel_fman1_sp11)) { ++ offset = (channel - qm_channel_fman1_sp0); ++ upperhalf = offset & 0x1; ++ offset = REG_WQ_DC1_DD_CFG(offset / 2); ++ } ++ else if (channel == qm_channel_caam) ++ offset = REG_WQ_DCn_DD_CFG(2); ++ else if (channel == qm_channel_pme) ++ offset = REG_WQ_DCn_DD_CFG(3); ++ else { ++ pr_crit("Illegal qm_channel type %d\n", channel); ++ return; ++ } ++ __qm_out(qm, offset, upperhalf ? ((u32)tp_cfg << 16) : tp_cfg); ++} ++ ++static void qm_get_details(struct qman *qm, u8 *int_options, u8 *errata, ++ u8 *conf_options) ++{ ++ u32 v = qm_in(IP_REV_1); ++ *int_options = (v >> 16) & 0xff; ++ *errata = (v >> 8) & 0xff; ++ *conf_options = v & 0xff; ++} ++ ++static void qm_set_corenet_bar(struct qman *qm, u16 eba, u32 ba) ++{ ++ /* choke if 'ba' isn't properly aligned */ ++ DPA_ASSERT(!(ba & 0x001fffff)); ++ qm_out(QCSP_BARE, eba); ++ qm_out(QCSP_BAR, ba); ++} ++ ++static u8 qm_get_corenet_sourceid(struct qman *qm) ++{ ++ return qm_in(SRCIDR); ++} ++ ++static u16 qm_get_liodn(struct qman *qm) ++{ ++ return qm_in(LIODNR); ++} ++ ++static void qm_set_congestion_config(struct qman *qm, u16 pres) ++{ ++ qm_out(CM_CFG, pres); ++} ++ ++#endif ++ ++static void qm_set_dc(struct qman *qm, enum qm_dc_portal portal, ++ int ed, u8 sernd) ++{ ++ DPA_ASSERT(!ed || (portal == qm_dc_portal_fman0) || ++ (portal == qm_dc_portal_fman1)); ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) ++ qm_out(DCP_CFG(portal), (ed ? 0x1000 : 0) | (sernd & 0x3ff)); ++ else ++ qm_out(DCP_CFG(portal), (ed ? 0x100 : 0) | (sernd & 0x1f)); ++} ++ ++static void qm_set_wq_scheduling(struct qman *qm, enum qm_wq_class wq_class, ++ u8 cs_elev, u8 csw2, u8 csw3, u8 csw4, u8 csw5, ++ u8 csw6, u8 csw7) ++{ ++#ifdef CONFIG_FSL_QMAN_BUG_AND_FEATURE_REV1 ++#define csw(x) \ ++do { \ ++ if (++x == 8) \ ++ x = 7; \ ++} while (0) ++ if (qman_ip_rev == QMAN_REV10) { ++ csw(csw2); ++ csw(csw3); ++ csw(csw4); ++ csw(csw5); ++ csw(csw6); ++ csw(csw7); ++ } ++#endif ++ qm_out(WQ_CS_CFG(wq_class), ((cs_elev & 0xff) << 24) | ++ ((csw2 & 0x7) << 20) | ((csw3 & 0x7) << 16) | ++ ((csw4 & 0x7) << 12) | ((csw5 & 0x7) << 8) | ++ ((csw6 & 0x7) << 4) | (csw7 & 0x7)); ++} ++ ++static void qm_set_hid(struct qman *qm) ++{ ++#ifdef CONFIG_FSL_QMAN_BUG_AND_FEATURE_REV1 ++ if (qman_ip_rev == QMAN_REV10) ++ qm_out(HID_CFG, 3); ++ else ++#endif ++ qm_out(HID_CFG, 0); ++} ++ ++static void qm_set_corenet_initiator(struct qman *qm) ++{ ++ qm_out(CI_SCHED_CFG, ++ 0x80000000 | /* write srcciv enable */ ++ (CONFIG_FSL_QMAN_CI_SCHED_CFG_SRCCIV << 24) | ++ (CONFIG_FSL_QMAN_CI_SCHED_CFG_SRQ_W << 8) | ++ (CONFIG_FSL_QMAN_CI_SCHED_CFG_RW_W << 4) | ++ CONFIG_FSL_QMAN_CI_SCHED_CFG_BMAN_W); ++} ++ ++static void qm_get_version(struct qman *qm, u16 *id, u8 *major, u8 *minor) ++{ ++ u32 v = qm_in(IP_REV_1); ++ *id = (v >> 16); ++ *major = (v >> 8) & 0xff; ++ *minor = v & 0xff; ++} ++ ++static void qm_set_memory(struct qman *qm, enum qm_memory memory, u64 ba, ++ int enable, int prio, int stash, u32 size) ++{ ++ u32 offset = (memory == qm_memory_fqd) ? REG_FQD_BARE : REG_PFDR_BARE; ++ u32 exp = ilog2(size); ++ /* choke if size isn't within range */ ++ DPA_ASSERT((size >= 4096) && (size <= 1073741824) && ++ is_power_of_2(size)); ++ /* choke if 'ba' has lower-alignment than 'size' */ ++ DPA_ASSERT(!(ba & (size - 1))); ++ __qm_out(qm, offset, upper_32_bits(ba)); ++ __qm_out(qm, offset + REG_offset_BAR, lower_32_bits(ba)); ++ __qm_out(qm, offset + REG_offset_AR, ++ (enable ? 0x80000000 : 0) | ++ (prio ? 0x40000000 : 0) | ++ (stash ? 0x20000000 : 0) | ++ (exp - 1)); ++} ++ ++static void qm_set_pfdr_threshold(struct qman *qm, u32 th, u8 k) ++{ ++ qm_out(PFDR_FP_LWIT, th & 0xffffff); ++ qm_out(PFDR_CFG, k); ++} ++ ++static void qm_set_sfdr_threshold(struct qman *qm, u16 th) ++{ ++ qm_out(SFDR_CFG, th & 0x3ff); ++} ++ ++static int qm_init_pfdr(struct qman *qm, u32 pfdr_start, u32 num) ++{ ++ u8 rslt = MCR_get_rslt(qm_in(MCR)); ++ ++ DPA_ASSERT(pfdr_start && !(pfdr_start & 7) && !(num & 7) && num); ++ /* Make sure the command interface is 'idle' */ ++ if(!MCR_rslt_idle(rslt)) ++ panic("QMAN_MCR isn't idle"); ++ ++ /* Write the MCR command params then the verb */ ++ qm_out(MCP(0), pfdr_start ); ++ /* TODO: remove this - it's a workaround for a model bug that is ++ * corrected in more recent versions. We use the workaround until ++ * everyone has upgraded. */ ++ qm_out(MCP(1), (pfdr_start + num - 16)); ++ lwsync(); ++ qm_out(MCR, MCR_INIT_PFDR); ++ /* Poll for the result */ ++ do { ++ rslt = MCR_get_rslt(qm_in(MCR)); ++ } while(!MCR_rslt_idle(rslt)); ++ if (MCR_rslt_ok(rslt)) ++ return 0; ++ if (MCR_rslt_eaccess(rslt)) ++ return -EACCES; ++ if (MCR_rslt_inval(rslt)) ++ return -EINVAL; ++ pr_crit("Unexpected result from MCR_INIT_PFDR: %02x\n", rslt); ++ return -ENOSYS; ++} ++ ++/*****************/ ++/* Config driver */ ++/*****************/ ++ ++#define DEFAULT_FQD_SZ (PAGE_SIZE << CONFIG_FSL_QMAN_FQD_SZ) ++#define DEFAULT_PFDR_SZ (PAGE_SIZE << CONFIG_FSL_QMAN_PFDR_SZ) ++ ++/* We support only one of these */ ++static struct qman *qm; ++static struct device_node *qm_node; ++ ++/* And this state belongs to 'qm'. It is set during fsl_qman_init(), but used ++ * during qman_init_ccsr(). */ ++static dma_addr_t fqd_a, pfdr_a; ++static size_t fqd_sz = DEFAULT_FQD_SZ, pfdr_sz = DEFAULT_PFDR_SZ; ++ ++/* Parse the property to extract the memory location and size and ++ * memblock_reserve() it. If it isn't supplied, memblock_alloc() the default ++ * size. Also flush this memory range from data cache so that QMAN originated ++ * transactions for this memory region could be marked non-coherent. ++ */ ++static __init int parse_mem_property(struct device_node *node, const char *name, ++ dma_addr_t *addr, size_t *sz, int zero) ++{ ++ const u32 *pint; ++ int ret; ++ unsigned long vaddr; ++ ++ pint = of_get_property(node, name, &ret); ++ if (!pint || (ret != 16)) { ++ pr_info("No %s property '%s', using memblock_alloc(%016zx)\n", ++ node->full_name, name, *sz); ++ *addr = memblock_alloc(*sz, *sz); ++ vaddr = (unsigned long)phys_to_virt(*addr); ++ if (zero) ++ memset((void *)vaddr, 0, *sz); ++ flush_dcache_range(vaddr, vaddr + *sz); ++ return 0; ++ } ++ pr_info("Using %s property '%s'\n", node->full_name, name); ++ /* If using a "zero-pma", don't try to zero it, even if you asked */ ++ if (zero && of_find_property(node, "zero-pma", &ret)) { ++ pr_info(" it's a 'zero-pma', not zeroing from s/w\n"); ++ zero = 0; ++ } ++ *addr = ((u64)pint[0] << 32) | (u64)pint[1]; ++ *sz = ((u64)pint[2] << 32) | (u64)pint[3]; ++ /* Keep things simple, it's either all in the DRAM range or it's all ++ * outside. */ ++ if (*addr < memblock_end_of_DRAM()) { ++ BUG_ON((u64)*addr + (u64)*sz > memblock_end_of_DRAM()); ++ if (memblock_reserve(*addr, *sz) < 0) { ++ pr_err("Failed to reserve %s\n", name); ++ return -ENOMEM; ++ } ++ vaddr = (unsigned long)phys_to_virt(*addr); ++ if (zero) ++ memset(phys_to_virt(*addr), 0, *sz); ++ flush_dcache_range(vaddr, vaddr + *sz); ++ } else if (zero) { ++ /* map as cacheable, non-guarded */ ++ void *tmpp = ioremap_prot(*addr, *sz, 0); ++ memset(tmpp, 0, *sz); ++ vaddr = (unsigned long)tmpp; ++ flush_dcache_range(vaddr, vaddr + *sz); ++ iounmap(tmpp); ++ } ++ return 0; ++} ++ ++/* TODO: ++ * - there is obviously no handling of errors, ++ * - the calls to qm_set_memory() hard-code the priority and CPC-stashing for ++ * both memory resources to zero. ++ */ ++static int __init fsl_qman_init(struct device_node *node) ++{ ++ struct resource res; ++ u32 __iomem *regs; ++ const char *s; ++ int ret, standby = 0; ++ u16 id; ++ u8 major, minor; ++ ret = of_address_to_resource(node, 0, &res); ++ if (ret) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, "reg"); ++ return ret; ++ } ++ s = of_get_property(node, "fsl,hv-claimable", &ret); ++ if (s && !strcmp(s, "standby")) ++ standby = 1; ++ if (!standby) { ++ ret = parse_mem_property(node, "fsl,qman-fqd", ++ &fqd_a, &fqd_sz, 1); ++ BUG_ON(ret); ++ ret = parse_mem_property(node, "fsl,qman-pfdr", ++ &pfdr_a, &pfdr_sz, 0); ++ BUG_ON(ret); ++ } ++ /* Global configuration */ ++ regs = ioremap(res.start, res.end - res.start + 1); ++ qm = qm_create(regs); ++ qm_node = node; ++ qm_get_version(qm, &id, &major, &minor); ++ pr_info("Qman ver:%04x,%02x,%02x\n", id, major, minor); ++ if (!qman_ip_rev) { ++ if ((major == 1) && (minor == 0)) ++ qman_ip_rev = QMAN_REV10; ++ else if ((major == 1) && (minor == 1)) ++ qman_ip_rev = QMAN_REV11; ++ else if ((major == 1) && (minor == 2)) ++ qman_ip_rev = QMAN_REV12; ++ else if ((major == 2) && (minor == 0)) ++ qman_ip_rev = QMAN_REV20; ++ else if ((major == 3) && (minor == 0)) ++ qman_ip_rev = QMAN_REV30; ++ else { ++ pr_warning("unknown Qman version, default to rev1.1\n"); ++ qman_ip_rev = QMAN_REV11; ++ } ++ } ++ ++ if (standby) { ++ pr_info(" -> in standby mode\n"); ++ return 0; ++ } ++ return 0; ++} ++ ++int qman_have_ccsr(void) ++{ ++ return qm ? 1 : 0; ++} ++ ++__init void qman_init_early(void) ++{ ++ struct device_node *dn; ++ int ret; ++ ++ for_each_compatible_node(dn, NULL, "fsl,qman") { ++ if (qm) ++ pr_err("%s: only one 'fsl,qman' allowed\n", ++ dn->full_name); ++ else { ++ if (!of_device_is_available(dn)) ++ continue; ++ ++ ret = fsl_qman_init(dn); ++ BUG_ON(ret); ++ } ++ } ++} ++ ++static void log_edata_bits(u32 bit_count) ++{ ++ u32 i, j, mask = 0xffffffff; ++ ++ pr_warning("Qman ErrInt, EDATA:\n"); ++ i = bit_count/32; ++ if (bit_count%32) { ++ i++; ++ mask = ~(mask << bit_count%32); ++ } ++ j = 16-i; ++ pr_warning(" 0x%08x\n", qm_in(EDATA(j)) & mask); ++ j++; ++ for (; j < 16; j++) ++ pr_warning(" 0x%08x\n", qm_in(EDATA(j))); ++} ++ ++static void log_additional_error_info(u32 isr_val, u32 ecsr_val) ++{ ++ union qman_ecir ecir_val; ++ union qman_eadr eadr_val; ++ ++ ecir_val.ecir_raw = qm_in(ECIR); ++ /* Is portal info valid */ ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) { ++ union qman_ecir2 ecir2_val; ++ ecir2_val.ecir2_raw = qm_in(ECIR2); ++ if (ecsr_val & PORTAL_ECSR_ERR) { ++ pr_warning("Qman ErrInt: %s id %d\n", ++ (ecir2_val.info.portal_type) ? ++ "DCP" : "SWP", ecir2_val.info.portal_num); ++ } ++ if (ecsr_val & (FQID_ECSR_ERR | QM_EIRQ_IECE)) { ++ pr_warning("Qman ErrInt: ecir.fqid 0x%x\n", ++ ecir_val.info.fqid); ++ } ++ if (ecsr_val & (QM_EIRQ_SBEI|QM_EIRQ_MBEI)) { ++ eadr_val.eadr_raw = qm_in(EADR); ++ pr_warning("Qman ErrInt: EADR Memory: %s, 0x%x\n", ++ error_mdata[eadr_val.info_rev3.memid].txt, ++ error_mdata[eadr_val.info_rev3.memid].addr_mask ++ & eadr_val.info_rev3.eadr); ++ log_edata_bits( ++ error_mdata[eadr_val.info_rev3.memid].bits); ++ } ++ } else { ++ if (ecsr_val & PORTAL_ECSR_ERR) { ++ pr_warning("Qman ErrInt: %s id %d\n", ++ (ecir_val.info.portal_type) ? ++ "DCP" : "SWP", ecir_val.info.portal_num); ++ } ++ if (ecsr_val & FQID_ECSR_ERR) { ++ pr_warning("Qman ErrInt: ecir.fqid 0x%x\n", ++ ecir_val.info.fqid); ++ } ++ if (ecsr_val & (QM_EIRQ_SBEI|QM_EIRQ_MBEI)) { ++ eadr_val.eadr_raw = qm_in(EADR); ++ pr_warning("Qman ErrInt: EADR Memory: %s, 0x%x\n", ++ error_mdata[eadr_val.info.memid].txt, ++ error_mdata[eadr_val.info.memid].addr_mask ++ & eadr_val.info.eadr); ++ log_edata_bits(error_mdata[eadr_val.info.memid].bits); ++ } ++ } ++} ++ ++/* Qman interrupt handler */ ++static irqreturn_t qman_isr(int irq, void *ptr) ++{ ++ u32 isr_val, ier_val, ecsr_val, isr_mask, i; ++ ++ ier_val = qm_err_isr_enable_read(qm); ++ isr_val = qm_err_isr_status_read(qm); ++ ecsr_val = qm_in(ECSR); ++ isr_mask = isr_val & ier_val; ++ ++ if (!isr_mask) ++ return IRQ_NONE; ++ for (i = 0; i < QMAN_HWE_COUNT; i++) { ++ if (qman_hwerr_txts[i].mask & isr_mask) { ++ pr_warning("Qman ErrInt: %s\n", qman_hwerr_txts[i].txt); ++ if (qman_hwerr_txts[i].mask & ecsr_val) { ++ log_additional_error_info(isr_mask, ecsr_val); ++ /* Re-arm error capture registers */ ++ qm_out(ECSR, ecsr_val); ++ } ++ if (qman_hwerr_txts[i].mask & QMAN_ERRS_TO_UNENABLE) { ++ pr_devel("Qman un-enabling error 0x%x\n", ++ qman_hwerr_txts[i].mask); ++ ier_val &= ~qman_hwerr_txts[i].mask; ++ qm_err_isr_enable_write(qm, ier_val); ++ } ++ } ++ } ++ qm_err_isr_status_clear(qm, isr_val); ++ return IRQ_HANDLED; ++} ++ ++static int __bind_irq(void) ++{ ++ int ret, err_irq; ++ ++ err_irq = of_irq_to_resource(qm_node, 0, NULL); ++ if (err_irq == NO_IRQ) { ++ pr_info("Can't get %s property '%s'\n", qm_node->full_name, ++ "interrupts"); ++ return -ENODEV; ++ } ++ ret = request_irq(err_irq, qman_isr, IRQF_SHARED, "qman-err", qm_node); ++ if (ret) { ++ pr_err("request_irq() failed %d for '%s'\n", ret, ++ qm_node->full_name); ++ return -ENODEV; ++ } ++ /* Write-to-clear any stale bits, (eg. starvation being asserted prior ++ * to resource allocation during driver init). */ ++ qm_err_isr_status_clear(qm, 0xffffffff); ++ /* Enable Error Interrupts */ ++ qm_err_isr_enable_write(qm, 0xffffffff); ++ return 0; ++} ++ ++int qman_init_ccsr(struct device_node *node) ++{ ++ int ret; ++ if (!qman_have_ccsr()) ++ return 0; ++ if (node != qm_node) ++ return -EINVAL; ++ /* FQD memory */ ++ qm_set_memory(qm, qm_memory_fqd, fqd_a, 1, 0, 0, fqd_sz); ++ /* PFDR memory */ ++ qm_set_memory(qm, qm_memory_pfdr, pfdr_a, 1, 0, 0, pfdr_sz); ++ qm_init_pfdr(qm, 8, pfdr_sz / 64 - 8); ++ /* thresholds */ ++ qm_set_pfdr_threshold(qm, 512, 64); ++ qm_set_sfdr_threshold(qm, 128); ++ /* clear stale PEBI bit from interrupt status register */ ++ qm_err_isr_status_clear(qm, QM_EIRQ_PEBI); ++ /* corenet initiator settings */ ++ qm_set_corenet_initiator(qm); ++ /* HID settings */ ++ qm_set_hid(qm); ++ /* Set scheduling weights to defaults */ ++ for (ret = qm_wq_first; ret <= qm_wq_last; ret++) ++ qm_set_wq_scheduling(qm, ret, 0, 0, 0, 0, 0, 0, 0); ++ /* We are not prepared to accept ERNs for hardware enqueues */ ++ qm_set_dc(qm, qm_dc_portal_fman0, 1, 0); ++ qm_set_dc(qm, qm_dc_portal_fman1, 1, 0); ++ /* Initialise Error Interrupt Handler */ ++ ret = __bind_irq(); ++ if (ret) ++ return ret; ++ return 0; ++} ++ ++#define LIO_CFG_LIODN_MASK 0x0fff0000 ++void qman_liodn_fixup(u16 channel) ++{ ++ static int done; ++ static u32 liodn_offset; ++ u32 before, after; ++ int idx = channel - QM_CHANNEL_SWPORTAL0; ++ ++ if (!qman_have_ccsr()) ++ return; ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) ++ before = qm_in(REV3_QCSP_LIO_CFG(idx)); ++ else ++ before = qm_in(QCSP_LIO_CFG(idx)); ++ if (!done) { ++ liodn_offset = before & LIO_CFG_LIODN_MASK; ++ done = 1; ++ return; ++ } ++ after = (before & (~LIO_CFG_LIODN_MASK)) | liodn_offset; ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) ++ qm_out(REV3_QCSP_LIO_CFG(idx), after); ++ else ++ qm_out(QCSP_LIO_CFG(idx), after); ++} ++ ++#define IO_CFG_SDEST_MASK 0x00ff0000 ++int qman_set_sdest(u16 channel, unsigned int cpu_idx) ++{ ++ int idx = channel - QM_CHANNEL_SWPORTAL0; ++ u32 before, after; ++ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) { ++ before = qm_in(REV3_QCSP_IO_CFG(idx)); ++ /* Each pair of vcpu share the same SRQ(SDEST) */ ++ cpu_idx /= 2; ++ after = (before & (~IO_CFG_SDEST_MASK)) | (cpu_idx << 16); ++ qm_out(REV3_QCSP_IO_CFG(idx), after); ++ } else { ++ before = qm_in(QCSP_IO_CFG(idx)); ++ after = (before & (~IO_CFG_SDEST_MASK)) | (cpu_idx << 16); ++ qm_out(QCSP_IO_CFG(idx), after); ++ } ++ return 0; ++} ++ ++#define MISC_CFG_WPM_MASK 0x00000002 ++int qm_set_wpm(int wpm) ++{ ++ u32 before; ++ u32 after; ++ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ ++ before = qm_in(MISC_CFG); ++ after = (before & (~MISC_CFG_WPM_MASK)) | (wpm << 1); ++ qm_out(MISC_CFG, after); ++ return 0; ++} ++ ++int qm_get_wpm(int *wpm) ++{ ++ u32 before; ++ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ ++ before = qm_in(MISC_CFG); ++ *wpm = (before & MISC_CFG_WPM_MASK) >> 1; ++ return 0; ++} ++ ++/* CEETM_CFG_PRES register has PRES field which is calculated by: ++ * PRES = (2^22 / credit update reference period) * QMan clock period ++ * = (2^22 * 10^9)/ CONFIG_QMAN_CEETM_UPDATE_PERIOD) / qman_clk ++ */ ++ ++int qman_ceetm_set_prescaler(enum qm_dc_portal portal) ++{ ++ u64 temp; ++ u16 pres; ++ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ ++ temp = 0x400000 * 100; ++ temp /= CONFIG_QMAN_CEETM_UPDATE_PERIOD; ++ temp *= 10000000; ++ pres = (u16)(temp / qman_clk); ++ ++ qm_out(CEETM_CFG_IDX, portal); ++ qm_out(CEETM_CFG_PRES, pres); ++ return 0; ++} ++ ++int qman_ceetm_get_prescaler(u16 *pres) ++{ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ *pres = (u16)qm_in(CEETM_CFG_PRES); ++ return 0; ++} ++ ++#define DCP_CFG_CEETME_MASK 0xFFFF0000 ++#define QM_SP_ENABLE_CEETM(n) (0x80000000 >> (n)) ++int qman_sp_enable_ceetm_mode(enum qm_dc_portal portal, u16 sub_portal) ++{ ++ u32 dcp_cfg; ++ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ ++ dcp_cfg = qm_in(DCP_CFG(portal)); ++ dcp_cfg |= QM_SP_ENABLE_CEETM(sub_portal); ++ qm_out(DCP_CFG(portal), dcp_cfg); ++ return 0; ++} ++ ++int qman_sp_disable_ceetm_mode(enum qm_dc_portal portal, u16 sub_portal) ++{ ++ u32 dcp_cfg; ++ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ dcp_cfg = qm_in(DCP_CFG(portal)); ++ dcp_cfg &= ~(QM_SP_ENABLE_CEETM(sub_portal)); ++ qm_out(DCP_CFG(portal), dcp_cfg); ++ return 0; ++} ++ ++#ifdef CONFIG_SYSFS ++ ++#define DRV_NAME "fsl-qman" ++ ++static ssize_t show_pfdr_fpc(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(PFDR_FPC)); ++}; ++ ++static ssize_t show_dlm_avg(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ u32 data; ++ int i; ++ ++ if (!sscanf(dev_attr->attr.name, "dcp%d_dlm_avg", &i)) ++ return -EINVAL; ++ data = qm_in(DCP_DLM_AVG(i)); ++ return snprintf(buf, PAGE_SIZE, "%d.%08d\n", data>>8, ++ (data & 0x000000ff)*390625); ++}; ++ ++static ssize_t set_dlm_avg(struct device *dev, ++ struct device_attribute *dev_attr, const char *buf, size_t count) ++{ ++ unsigned long val; ++ int i; ++ ++ if (!sscanf(dev_attr->attr.name, "dcp%d_dlm_avg", &i)) ++ return -EINVAL; ++ if (strict_strtoul(buf, 0, &val)) { ++ dev_dbg(dev, "invalid input %s\n", buf); ++ return -EINVAL; ++ } ++ qm_out(DCP_DLM_AVG(i), val); ++ return count; ++}; ++ ++static ssize_t show_pfdr_cfg(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(PFDR_CFG)); ++}; ++ ++static ssize_t set_pfdr_cfg(struct device *dev, ++ struct device_attribute *dev_attr, const char *buf, size_t count) ++{ ++ unsigned long val; ++ ++ if (strict_strtoul(buf, 0, &val)) { ++ dev_dbg(dev, "invalid input %s\n", buf); ++ return -EINVAL; ++ } ++ qm_out(PFDR_CFG, val); ++ return count; ++}; ++ ++static ssize_t show_sfdr_in_use(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(SFDR_IN_USE)); ++}; ++ ++static ssize_t show_idle_stat(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(IDLE_STAT)); ++}; ++ ++static ssize_t show_ci_rlm_avg(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ u32 data = qm_in(CI_RLM_AVG); ++ return snprintf(buf, PAGE_SIZE, "%d.%08d\n", data>>8, ++ (data & 0x000000ff)*390625); ++}; ++ ++static ssize_t set_ci_rlm_avg(struct device *dev, ++ struct device_attribute *dev_attr, const char *buf, size_t count) ++{ ++ unsigned long val; ++ ++ if (strict_strtoul(buf, 0, &val)) { ++ dev_dbg(dev, "invalid input %s\n", buf); ++ return -EINVAL; ++ } ++ qm_out(CI_RLM_AVG, val); ++ return count; ++}; ++ ++static ssize_t show_err_isr(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "0x%08x\n", qm_in(ERR_ISR)); ++}; ++ ++ ++static ssize_t show_sbec(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ int i; ++ ++ if (!sscanf(dev_attr->attr.name, "sbec_%d", &i)) ++ return -EINVAL; ++ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(SBEC(i))); ++}; ++ ++static DEVICE_ATTR(pfdr_fpc, S_IRUSR, show_pfdr_fpc, NULL); ++static DEVICE_ATTR(pfdr_cfg, S_IRUSR, show_pfdr_cfg, set_pfdr_cfg); ++static DEVICE_ATTR(idle_stat, S_IRUSR, show_idle_stat, NULL); ++static DEVICE_ATTR(ci_rlm_avg, (S_IRUSR|S_IWUGO), ++ show_ci_rlm_avg, set_ci_rlm_avg); ++static DEVICE_ATTR(err_isr, S_IRUSR, show_err_isr, NULL); ++static DEVICE_ATTR(sfdr_in_use, S_IRUSR, show_sfdr_in_use, NULL); ++ ++static DEVICE_ATTR(dcp0_dlm_avg, (S_IRUSR|S_IWUGO), show_dlm_avg, set_dlm_avg); ++static DEVICE_ATTR(dcp1_dlm_avg, (S_IRUSR|S_IWUGO), show_dlm_avg, set_dlm_avg); ++static DEVICE_ATTR(dcp2_dlm_avg, (S_IRUSR|S_IWUGO), show_dlm_avg, set_dlm_avg); ++static DEVICE_ATTR(dcp3_dlm_avg, (S_IRUSR|S_IWUGO), show_dlm_avg, set_dlm_avg); ++ ++static DEVICE_ATTR(sbec_0, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_1, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_2, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_3, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_4, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_5, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_6, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_7, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_8, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_9, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_10, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_11, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_12, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_13, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_14, S_IRUSR, show_sbec, NULL); ++ ++static struct attribute *qman_dev_attributes[] = { ++ &dev_attr_pfdr_fpc.attr, ++ &dev_attr_pfdr_cfg.attr, ++ &dev_attr_idle_stat.attr, ++ &dev_attr_ci_rlm_avg.attr, ++ &dev_attr_err_isr.attr, ++ &dev_attr_dcp0_dlm_avg.attr, ++ &dev_attr_dcp1_dlm_avg.attr, ++ &dev_attr_dcp2_dlm_avg.attr, ++ &dev_attr_dcp3_dlm_avg.attr, ++ /* sfdr_in_use will be added if necessary */ ++ NULL ++}; ++ ++static struct attribute *qman_dev_ecr_attributes[] = { ++ &dev_attr_sbec_0.attr, ++ &dev_attr_sbec_1.attr, ++ &dev_attr_sbec_2.attr, ++ &dev_attr_sbec_3.attr, ++ &dev_attr_sbec_4.attr, ++ &dev_attr_sbec_5.attr, ++ &dev_attr_sbec_6.attr, ++ &dev_attr_sbec_7.attr, ++ &dev_attr_sbec_8.attr, ++ &dev_attr_sbec_9.attr, ++ &dev_attr_sbec_10.attr, ++ &dev_attr_sbec_11.attr, ++ &dev_attr_sbec_12.attr, ++ &dev_attr_sbec_13.attr, ++ &dev_attr_sbec_14.attr, ++ NULL ++}; ++ ++/* root level */ ++static const struct attribute_group qman_dev_attr_grp = { ++ .name = NULL, ++ .attrs = qman_dev_attributes ++}; ++static const struct attribute_group qman_dev_ecr_grp = { ++ .name = "error_capture", ++ .attrs = qman_dev_ecr_attributes ++}; ++ ++static int of_fsl_qman_remove(struct platform_device *ofdev) ++{ ++ sysfs_remove_group(&ofdev->dev.kobj, &qman_dev_attr_grp); ++ return 0; ++}; ++ ++static int __devinit of_fsl_qman_probe(struct platform_device *ofdev) ++{ ++ int ret; ++ ++ ret = sysfs_create_group(&ofdev->dev.kobj, &qman_dev_attr_grp); ++ if (ret) ++ goto done; ++ if (qman_ip_rev != QMAN_REV10) { ++ ret = sysfs_add_file_to_group(&ofdev->dev.kobj, ++ &dev_attr_sfdr_in_use.attr, qman_dev_attr_grp.name); ++ if (ret) ++ goto del_group_0; ++ } ++ ret = sysfs_create_group(&ofdev->dev.kobj, &qman_dev_ecr_grp); ++ if (ret) ++ goto del_group_0; ++ ++ goto done; ++ ++del_group_0: ++ sysfs_remove_group(&ofdev->dev.kobj, &qman_dev_attr_grp); ++done: ++ if (ret) ++ dev_err(&ofdev->dev, ++ "Cannot create dev attributes ret=%d\n", ret); ++ return ret; ++}; ++ ++static struct of_device_id of_fsl_qman_ids[] = { ++ { ++ .compatible = "fsl,qman", ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, of_fsl_qman_ids); ++ ++static struct platform_driver of_fsl_qman_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = DRV_NAME, ++ .of_match_table = of_fsl_qman_ids, ++ }, ++ .probe = of_fsl_qman_probe, ++ .remove = __devexit_p(of_fsl_qman_remove), ++}; ++ ++static int qman_ctrl_init(void) ++{ ++ return platform_driver_register(&of_fsl_qman_driver); ++} ++ ++static void qman_ctrl_exit(void) ++{ ++ platform_driver_unregister(&of_fsl_qman_driver); ++} ++ ++module_init(qman_ctrl_init); ++module_exit(qman_ctrl_exit); ++ ++#endif /* CONFIG_SYSFS */ +diff --git a/drivers/staging/fsl_qbman/qman_debugfs.c b/drivers/staging/fsl_qbman/qman_debugfs.c +new file mode 100644 +index 0000000..8a17550 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_debugfs.c +@@ -0,0 +1,1404 @@ ++/* Copyright 2010-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "qman_private.h" ++ ++#define MAX_FQID (0x00ffffff) ++#define QM_FQD_BLOCK_SIZE 64 ++#define QM_FQD_AR (0xC10) ++ ++static u32 fqid_max; ++static u64 qman_ccsr_start; ++static u64 qman_ccsr_size; ++ ++static const char *state_txt[] = { ++ "Out of Service", ++ "Retired", ++ "Tentatively Scheduled", ++ "Truly Scheduled", ++ "Parked", ++ "Active, Active Held or Held Suspended", ++ "Unknown State 6", ++ "Unknown State 7", ++ NULL, ++}; ++ ++static const u8 fqd_states[] = { ++ QM_MCR_NP_STATE_OOS, QM_MCR_NP_STATE_RETIRED, QM_MCR_NP_STATE_TEN_SCHED, ++ QM_MCR_NP_STATE_TRU_SCHED, QM_MCR_NP_STATE_PARKED, ++ QM_MCR_NP_STATE_ACTIVE}; ++static const u32 fqd_states_count = sizeof(fqd_states)/sizeof(u8); ++ ++struct mask_to_text { ++ u16 mask; ++ const char *txt; ++}; ++ ++struct mask_filter_s { ++ u16 mask; ++ u8 filter; ++}; ++ ++static const struct mask_filter_s mask_filter[] = { ++ {QM_FQCTRL_PREFERINCACHE, 0}, ++ {QM_FQCTRL_PREFERINCACHE, 1}, ++ {QM_FQCTRL_HOLDACTIVE, 0}, ++ {QM_FQCTRL_HOLDACTIVE, 1}, ++ {QM_FQCTRL_AVOIDBLOCK, 0}, ++ {QM_FQCTRL_AVOIDBLOCK, 1}, ++ {QM_FQCTRL_FORCESFDR, 0}, ++ {QM_FQCTRL_FORCESFDR, 1}, ++ {QM_FQCTRL_CPCSTASH, 0}, ++ {QM_FQCTRL_CPCSTASH, 1}, ++ {QM_FQCTRL_CTXASTASHING, 0}, ++ {QM_FQCTRL_CTXASTASHING, 1}, ++ {QM_FQCTRL_ORP, 0}, ++ {QM_FQCTRL_ORP, 1}, ++ {QM_FQCTRL_TDE, 0}, ++ {QM_FQCTRL_TDE, 1}, ++ {QM_FQCTRL_CGE, 0}, ++ {QM_FQCTRL_CGE, 1} ++}; ++static const u32 mask_filter_count = ++ sizeof(mask_filter)/sizeof(struct mask_filter_s); ++ ++static const struct mask_to_text fq_ctrl_text_list[] = { ++ { ++ .mask = QM_FQCTRL_PREFERINCACHE, ++ .txt = "Prefer in cache", ++ }, ++ { ++ .mask = QM_FQCTRL_HOLDACTIVE, ++ .txt = "Hold active in portal", ++ }, ++ { ++ .mask = QM_FQCTRL_AVOIDBLOCK, ++ .txt = "Avoid Blocking", ++ }, ++ { ++ .mask = QM_FQCTRL_FORCESFDR, ++ .txt = "High-priority SFDRs", ++ }, ++ { ++ .mask = QM_FQCTRL_CPCSTASH, ++ .txt = "CPC Stash Enable", ++ }, ++ { ++ .mask = QM_FQCTRL_CTXASTASHING, ++ .txt = "Context-A stashing", ++ }, ++ { ++ .mask = QM_FQCTRL_ORP, ++ .txt = "ORP Enable", ++ }, ++ { ++ .mask = QM_FQCTRL_TDE, ++ .txt = "Tail-Drop Enable", ++ }, ++ { ++ .mask = QM_FQCTRL_CGE, ++ .txt = "Congestion Group Enable", ++ }, ++ { ++ .mask = 0, ++ .txt = NULL, ++ } ++}; ++ ++static const char *get_fqd_ctrl_text(u16 mask) ++{ ++ int i = 0; ++ ++ while (fq_ctrl_text_list[i].txt != NULL) { ++ if (fq_ctrl_text_list[i].mask == mask) ++ return fq_ctrl_text_list[i].txt; ++ i++; ++ } ++ return NULL; ++} ++ ++static const struct mask_to_text stashing_text_list[] = { ++ { ++ .mask = QM_STASHING_EXCL_CTX, ++ .txt = "FQ Ctx Stash" ++ }, ++ { ++ .mask = QM_STASHING_EXCL_DATA, ++ .txt = "Frame Data Stash", ++ }, ++ { ++ .mask = QM_STASHING_EXCL_ANNOTATION, ++ .txt = "Frame Annotation Stash", ++ }, ++ { ++ .mask = 0, ++ .txt = NULL, ++ }, ++}; ++ ++static int user_input_convert(const char __user *user_buf, size_t count, ++ unsigned long *val) ++{ ++ char buf[12]; ++ ++ if (count > sizeof(buf) - 1) ++ return -EINVAL; ++ if (copy_from_user(buf, user_buf, count)) ++ return -EFAULT; ++ buf[count] = '\0'; ++ if (strict_strtoul(buf, 0, val)) ++ return -EINVAL; ++ return 0; ++} ++ ++struct line_buffer_fq { ++ u32 buf[8]; ++ u32 buf_cnt; ++ int line_cnt; ++}; ++ ++static void add_to_line_buffer(struct line_buffer_fq *line_buf, u32 fqid, ++ struct seq_file *file) ++{ ++ line_buf->buf[line_buf->buf_cnt] = fqid; ++ line_buf->buf_cnt++; ++ if (line_buf->buf_cnt == 8) { ++ /* Buffer is full, flush it */ ++ if (line_buf->line_cnt != 0) ++ seq_printf(file, ",\n"); ++ seq_printf(file, "0x%06x,0x%06x,0x%06x,0x%06x,0x%06x," ++ "0x%06x,0x%06x,0x%06x", ++ line_buf->buf[0], line_buf->buf[1], line_buf->buf[2], ++ line_buf->buf[3], line_buf->buf[4], line_buf->buf[5], ++ line_buf->buf[6], line_buf->buf[7]); ++ line_buf->buf_cnt = 0; ++ line_buf->line_cnt++; ++ } ++} ++ ++static void flush_line_buffer(struct line_buffer_fq *line_buf, ++ struct seq_file *file) ++{ ++ if (line_buf->buf_cnt) { ++ int y = 0; ++ if (line_buf->line_cnt != 0) ++ seq_printf(file, ",\n"); ++ while (y != line_buf->buf_cnt) { ++ if (y+1 == line_buf->buf_cnt) ++ seq_printf(file, "0x%06x", line_buf->buf[y]); ++ else ++ seq_printf(file, "0x%06x,", line_buf->buf[y]); ++ y++; ++ } ++ line_buf->line_cnt++; ++ } ++ if (line_buf->line_cnt) ++ seq_printf(file, "\n"); ++} ++ ++static struct dentry *dfs_root; /* debugfs root directory */ ++ ++/******************************************************************************* ++ * Query Frame Queue Non Programmable Fields ++ ******************************************************************************/ ++struct query_fq_np_fields_data_s { ++ u32 fqid; ++}; ++static struct query_fq_np_fields_data_s query_fq_np_fields_data = { ++ .fqid = 1, ++}; ++ ++static int query_fq_np_fields_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_queryfq_np np; ++ struct qman_fq fq; ++ ++ fq.fqid = query_fq_np_fields_data.fqid; ++ ret = qman_query_fq_np(&fq, &np); ++ if (ret) ++ return ret; ++ /* Print state */ ++ seq_printf(file, "Query FQ Non Programmable Fields Result fqid 0x%x\n", ++ fq.fqid); ++ seq_printf(file, " force eligible pending: %s\n", ++ (np.state & QM_MCR_NP_STATE_FE) ? "yes" : "no"); ++ seq_printf(file, " retirement pending: %s\n", ++ (np.state & QM_MCR_NP_STATE_R) ? "yes" : "no"); ++ seq_printf(file, " state: %s\n", ++ state_txt[np.state & QM_MCR_NP_STATE_MASK]); ++ seq_printf(file, " fq_link: 0x%x\n", np.fqd_link); ++ seq_printf(file, " odp_seq: %u\n", np.odp_seq); ++ seq_printf(file, " orp_nesn: %u\n", np.orp_nesn); ++ seq_printf(file, " orp_ea_hseq: %u\n", np.orp_ea_hseq); ++ seq_printf(file, " orp_ea_tseq: %u\n", np.orp_ea_tseq); ++ seq_printf(file, " orp_ea_hptr: 0x%x\n", np.orp_ea_hptr); ++ seq_printf(file, " orp_ea_tptr: 0x%x\n", np.orp_ea_tptr); ++ seq_printf(file, " pfdr_hptr: 0x%x\n", np.pfdr_hptr); ++ seq_printf(file, " pfdr_tptr: 0x%x\n", np.pfdr_tptr); ++ seq_printf(file, " is: ics_surp contains a %s\n", ++ (np.is) ? "deficit" : "surplus"); ++ seq_printf(file, " ics_surp: %u\n", np.ics_surp); ++ seq_printf(file, " byte_cnt: %u\n", np.byte_cnt); ++ seq_printf(file, " frm_cnt: %u\n", np.frm_cnt); ++ seq_printf(file, " ra1_sfdr: 0x%x\n", np.ra1_sfdr); ++ seq_printf(file, " ra2_sfdr: 0x%x\n", np.ra2_sfdr); ++ seq_printf(file, " od1_sfdr: 0x%x\n", np.od1_sfdr); ++ seq_printf(file, " od2_sfdr: 0x%x\n", np.od2_sfdr); ++ seq_printf(file, " od3_sfdr: 0x%x\n", np.od3_sfdr); ++ return 0; ++} ++ ++static int query_fq_np_fields_open(struct inode *inode, ++ struct file *file) ++{ ++ return single_open(file, query_fq_np_fields_show, NULL); ++} ++ ++static ssize_t query_fq_np_fields_write(struct file *f, ++ const char __user *buf, size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > MAX_FQID) ++ return -EINVAL; ++ query_fq_np_fields_data.fqid = (u32)val; ++ return count; ++} ++ ++static const struct file_operations query_fq_np_fields_fops = { ++ .owner = THIS_MODULE, ++ .open = query_fq_np_fields_open, ++ .read = seq_read, ++ .write = query_fq_np_fields_write, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * Frame Queue Programmable Fields ++ ******************************************************************************/ ++struct query_fq_fields_data_s { ++ u32 fqid; ++}; ++ ++static struct query_fq_fields_data_s query_fq_fields_data = { ++ .fqid = 1, ++}; ++ ++static int query_fq_fields_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_fqd fqd; ++ struct qman_fq fq; ++ int i = 0; ++ ++ memset(&fqd, 0, sizeof(struct qm_fqd)); ++ fq.fqid = query_fq_fields_data.fqid; ++ ret = qman_query_fq(&fq, &fqd); ++ if (ret) ++ return ret; ++ seq_printf(file, "Query FQ Programmable Fields Result fqid 0x%x\n", ++ fq.fqid); ++ seq_printf(file, " orprws: %u\n", fqd.orprws); ++ seq_printf(file, " oa: %u\n", fqd.oa); ++ seq_printf(file, " olws: %u\n", fqd.olws); ++ ++ seq_printf(file, " cgid: %u\n", fqd.cgid); ++ ++ if ((fqd.fq_ctrl & QM_FQCTRL_MASK) == 0) ++ seq_printf(file, " fq_ctrl: None\n"); ++ else { ++ i = 0; ++ seq_printf(file, " fq_ctrl:\n"); ++ while (fq_ctrl_text_list[i].txt != NULL) { ++ if ((fqd.fq_ctrl & QM_FQCTRL_MASK) & ++ fq_ctrl_text_list[i].mask) ++ seq_printf(file, " %s\n", ++ fq_ctrl_text_list[i].txt); ++ i++; ++ } ++ } ++ seq_printf(file, " dest_channel: %u\n", fqd.dest.channel); ++ seq_printf(file, " dest_wq: %u\n", fqd.dest.wq); ++ seq_printf(file, " ics_cred: %u\n", fqd.ics_cred); ++ seq_printf(file, " td_mant: %u\n", fqd.td.mant); ++ seq_printf(file, " td_exp: %u\n", fqd.td.exp); ++ ++ seq_printf(file, " ctx_b: 0x%x\n", fqd.context_b); ++ ++ seq_printf(file, " ctx_a: 0x%llx\n", qm_fqd_stashing_get64(&fqd)); ++ /* Any stashing configured */ ++ if ((fqd.context_a.stashing.exclusive & 0x7) == 0) ++ seq_printf(file, " ctx_a_stash_exclusive: None\n"); ++ else { ++ seq_printf(file, " ctx_a_stash_exclusive:\n"); ++ i = 0; ++ while (stashing_text_list[i].txt != NULL) { ++ if ((fqd.fq_ctrl & 0x7) & stashing_text_list[i].mask) ++ seq_printf(file, " %s\n", ++ stashing_text_list[i].txt); ++ i++; ++ } ++ } ++ seq_printf(file, " ctx_a_stash_annotation_cl: %u\n", ++ fqd.context_a.stashing.annotation_cl); ++ seq_printf(file, " ctx_a_stash_data_cl: %u\n", ++ fqd.context_a.stashing.data_cl); ++ seq_printf(file, " ctx_a_stash_context_cl: %u\n", ++ fqd.context_a.stashing.context_cl); ++ return 0; ++} ++ ++static int query_fq_fields_open(struct inode *inode, ++ struct file *file) ++{ ++ return single_open(file, query_fq_fields_show, NULL); ++} ++ ++static ssize_t query_fq_fields_write(struct file *f, ++ const char __user *buf, size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > MAX_FQID) ++ return -EINVAL; ++ query_fq_fields_data.fqid = (u32)val; ++ return count; ++} ++ ++static const struct file_operations query_fq_fields_fops = { ++ .owner = THIS_MODULE, ++ .open = query_fq_fields_open, ++ .read = seq_read, ++ .write = query_fq_fields_write, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * Query WQ lengths ++ ******************************************************************************/ ++struct query_wq_lengths_data_s { ++ union { ++ u16 channel_wq; /* ignores wq (3 lsbits) */ ++ struct { ++ u16 id:13; /* qm_channel */ ++ u16 __reserved:3; ++ } __packed channel; ++ }; ++}; ++static struct query_wq_lengths_data_s query_wq_lengths_data; ++static int query_wq_lengths_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_querywq wq; ++ int i; ++ ++ memset(&wq, 0, sizeof(struct qm_mcr_querywq)); ++ wq.channel.id = query_wq_lengths_data.channel.id; ++ ret = qman_query_wq(0, &wq); ++ if (ret) ++ return ret; ++ seq_printf(file, "Query Result For Channel: 0x%x\n", wq.channel.id); ++ for (i = 0; i < 8; i++) ++ /* mask out upper 4 bits since they are not part of length */ ++ seq_printf(file, " wq%d_len : %u\n", i, wq.wq_len[i] & 0x0fff); ++ return 0; ++} ++ ++static int query_wq_lengths_open(struct inode *inode, ++ struct file *file) ++{ ++ return single_open(file, query_wq_lengths_show, NULL); ++} ++ ++static ssize_t query_wq_lengths_write(struct file *f, ++ const char __user *buf, size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > 0xfff8) ++ return -EINVAL; ++ query_wq_lengths_data.channel.id = (u16)val; ++ return count; ++} ++ ++static const struct file_operations query_wq_lengths_fops = { ++ .owner = THIS_MODULE, ++ .open = query_wq_lengths_open, ++ .read = seq_read, ++ .write = query_wq_lengths_write, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * Query CGR ++ ******************************************************************************/ ++struct query_cgr_s { ++ u8 cgid; ++}; ++static struct query_cgr_s query_cgr_data; ++ ++static int query_cgr_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_querycgr cgrd; ++ struct qman_cgr cgr; ++ int i, j; ++ u32 mask; ++ ++ memset(&cgr, 0, sizeof(struct qm_mcr_querycgr)); ++ cgr.cgrid = query_cgr_data.cgid; ++ ret = qman_query_cgr(&cgr, &cgrd); ++ if (ret) ++ return ret; ++ seq_printf(file, "Query CGR id 0x%x\n", cgr.cgrid); ++ seq_printf(file, " wr_parm_g MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ cgrd.cgr.wr_parm_g.MA, cgrd.cgr.wr_parm_g.Mn, ++ cgrd.cgr.wr_parm_g.SA, cgrd.cgr.wr_parm_g.Sn, ++ cgrd.cgr.wr_parm_g.Pn); ++ ++ seq_printf(file, " wr_parm_y MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ cgrd.cgr.wr_parm_y.MA, cgrd.cgr.wr_parm_y.Mn, ++ cgrd.cgr.wr_parm_y.SA, cgrd.cgr.wr_parm_y.Sn, ++ cgrd.cgr.wr_parm_y.Pn); ++ ++ seq_printf(file, " wr_parm_r MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ cgrd.cgr.wr_parm_r.MA, cgrd.cgr.wr_parm_r.Mn, ++ cgrd.cgr.wr_parm_r.SA, cgrd.cgr.wr_parm_r.Sn, ++ cgrd.cgr.wr_parm_r.Pn); ++ ++ seq_printf(file, " wr_en_g: %u, wr_en_y: %u, we_en_r: %u\n", ++ cgrd.cgr.wr_en_g, cgrd.cgr.wr_en_y, cgrd.cgr.wr_en_r); ++ ++ seq_printf(file, " cscn_en: %u\n", cgrd.cgr.cscn_en); ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) { ++ seq_printf(file, " cscn_targ_dcp:\n"); ++ mask = 0x80000000; ++ for (i = 0; i < 32; i++) { ++ if (cgrd.cgr.cscn_targ & mask) ++ seq_printf(file, " send CSCN to dcp %u\n", ++ (31 - i)); ++ mask >>= 1; ++ } ++ ++ seq_printf(file, " cscn_targ_swp:\n"); ++ for (i = 0; i < 4; i++) { ++ mask = 0x80000000; ++ for (j = 0; j < 32; j++) { ++ if (cgrd.cscn_targ_swp[i] & mask) ++ seq_printf(file, " send CSCN to swp" ++ " %u\n", (127 - (i * 32) - j)); ++ mask >>= 1; ++ } ++ } ++ } else { ++ seq_printf(file, " cscn_targ: %u\n", cgrd.cgr.cscn_targ); ++ } ++ seq_printf(file, " cstd_en: %u\n", cgrd.cgr.cstd_en); ++ seq_printf(file, " cs: %u\n", cgrd.cgr.cs); ++ ++ seq_printf(file, " cs_thresh_TA: %u, cs_thresh_Tn: %u\n", ++ cgrd.cgr.cs_thres.TA, cgrd.cgr.cs_thres.Tn); ++ ++ if (qman_ip_rev != QMAN_REV10) { ++ seq_printf(file, " mode: %s\n", ++ (cgrd.cgr.mode & QMAN_CGR_MODE_FRAME) ? ++ "frame count" : "byte count"); ++ } ++ seq_printf(file, " i_bcnt: %llu\n", qm_mcr_querycgr_i_get64(&cgrd)); ++ seq_printf(file, " a_bcnt: %llu\n", qm_mcr_querycgr_a_get64(&cgrd)); ++ ++ return 0; ++} ++ ++static int query_cgr_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, query_cgr_show, NULL); ++} ++ ++static ssize_t query_cgr_write(struct file *f, const char __user *buf, ++ size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > 0xff) ++ return -EINVAL; ++ query_cgr_data.cgid = (u8)val; ++ return count; ++} ++ ++static const struct file_operations query_cgr_fops = { ++ .owner = THIS_MODULE, ++ .open = query_cgr_open, ++ .read = seq_read, ++ .write = query_cgr_write, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * Test Write CGR ++ ******************************************************************************/ ++struct test_write_cgr_s { ++ u64 i_bcnt; ++ u8 cgid; ++}; ++static struct test_write_cgr_s test_write_cgr_data; ++ ++static int testwrite_cgr_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_cgrtestwrite result; ++ struct qman_cgr cgr; ++ u64 i_bcnt; ++ ++ memset(&cgr, 0, sizeof(struct qman_cgr)); ++ memset(&result, 0, sizeof(struct qm_mcr_cgrtestwrite)); ++ cgr.cgrid = test_write_cgr_data.cgid; ++ i_bcnt = test_write_cgr_data.i_bcnt; ++ ret = qman_testwrite_cgr(&cgr, i_bcnt, &result); ++ if (ret) ++ return ret; ++ seq_printf(file, "CGR Test Write CGR id 0x%x\n", cgr.cgrid); ++ seq_printf(file, " wr_parm_g MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ result.cgr.wr_parm_g.MA, result.cgr.wr_parm_g.Mn, ++ result.cgr.wr_parm_g.SA, result.cgr.wr_parm_g.Sn, ++ result.cgr.wr_parm_g.Pn); ++ seq_printf(file, " wr_parm_y MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ result.cgr.wr_parm_y.MA, result.cgr.wr_parm_y.Mn, ++ result.cgr.wr_parm_y.SA, result.cgr.wr_parm_y.Sn, ++ result.cgr.wr_parm_y.Pn); ++ seq_printf(file, " wr_parm_r MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ result.cgr.wr_parm_r.MA, result.cgr.wr_parm_r.Mn, ++ result.cgr.wr_parm_r.SA, result.cgr.wr_parm_r.Sn, ++ result.cgr.wr_parm_r.Pn); ++ seq_printf(file, " wr_en_g: %u, wr_en_y: %u, we_en_r: %u\n", ++ result.cgr.wr_en_g, result.cgr.wr_en_y, result.cgr.wr_en_r); ++ seq_printf(file, " cscn_en: %u\n", result.cgr.cscn_en); ++ seq_printf(file, " cscn_targ: %u\n", result.cgr.cscn_targ); ++ seq_printf(file, " cstd_en: %u\n", result.cgr.cstd_en); ++ seq_printf(file, " cs: %u\n", result.cgr.cs); ++ seq_printf(file, " cs_thresh_TA: %u, cs_thresh_Tn: %u\n", ++ result.cgr.cs_thres.TA, result.cgr.cs_thres.Tn); ++ ++ /* Add Mode for Si 2 */ ++ if (qman_ip_rev != QMAN_REV10) { ++ seq_printf(file, " mode: %s\n", ++ (result.cgr.mode & QMAN_CGR_MODE_FRAME) ? ++ "frame count" : "byte count"); ++ } ++ ++ seq_printf(file, " i_bcnt: %llu\n", ++ qm_mcr_cgrtestwrite_i_get64(&result)); ++ seq_printf(file, " a_bcnt: %llu\n", ++ qm_mcr_cgrtestwrite_a_get64(&result)); ++ seq_printf(file, " wr_prob_g: %u\n", result.wr_prob_g); ++ seq_printf(file, " wr_prob_y: %u\n", result.wr_prob_y); ++ seq_printf(file, " wr_prob_r: %u\n", result.wr_prob_r); ++ return 0; ++} ++ ++static int testwrite_cgr_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, testwrite_cgr_show, NULL); ++} ++ ++static const struct file_operations testwrite_cgr_fops = { ++ .owner = THIS_MODULE, ++ .open = testwrite_cgr_open, ++ .read = seq_read, ++ .release = single_release, ++}; ++ ++ ++static int testwrite_cgr_ibcnt_show(struct seq_file *file, void *offset) ++{ ++ seq_printf(file, "i_bcnt: %llu\n", test_write_cgr_data.i_bcnt); ++ return 0; ++} ++static int testwrite_cgr_ibcnt_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, testwrite_cgr_ibcnt_show, NULL); ++} ++ ++static ssize_t testwrite_cgr_ibcnt_write(struct file *f, const char __user *buf, ++ size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ test_write_cgr_data.i_bcnt = val; ++ return count; ++} ++ ++static const struct file_operations teswrite_cgr_ibcnt_fops = { ++ .owner = THIS_MODULE, ++ .open = testwrite_cgr_ibcnt_open, ++ .read = seq_read, ++ .write = testwrite_cgr_ibcnt_write, ++ .release = single_release, ++}; ++ ++static int testwrite_cgr_cgrid_show(struct seq_file *file, void *offset) ++{ ++ seq_printf(file, "cgrid: %u\n", (u32)test_write_cgr_data.cgid); ++ return 0; ++} ++static int testwrite_cgr_cgrid_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, testwrite_cgr_cgrid_show, NULL); ++} ++ ++static ssize_t testwrite_cgr_cgrid_write(struct file *f, const char __user *buf, ++ size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > 0xff) ++ return -EINVAL; ++ test_write_cgr_data.cgid = (u8)val; ++ return count; ++} ++ ++static const struct file_operations teswrite_cgr_cgrid_fops = { ++ .owner = THIS_MODULE, ++ .open = testwrite_cgr_cgrid_open, ++ .read = seq_read, ++ .write = testwrite_cgr_cgrid_write, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * Query Congestion State ++ ******************************************************************************/ ++static int query_congestion_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_querycongestion cs; ++ int i, j, in_cong = 0; ++ u32 mask; ++ ++ memset(&cs, 0, sizeof(struct qm_mcr_querycongestion)); ++ ret = qman_query_congestion(&cs); ++ if (ret) ++ return ret; ++ seq_printf(file, "Query Congestion Result\n"); ++ for (i = 0; i < 8; i++) { ++ mask = 0x80000000; ++ for (j = 0; j < 32; j++) { ++ if (cs.state.__state[i] & mask) { ++ in_cong = 1; ++ seq_printf(file, " cg %u: %s\n", (i*32)+j, ++ "in congestion"); ++ } ++ mask >>= 1; ++ } ++ } ++ if (!in_cong) ++ seq_printf(file, " All congestion groups not congested.\n"); ++ return 0; ++} ++ ++static int query_congestion_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, query_congestion_show, NULL); ++} ++ ++static const struct file_operations query_congestion_fops = { ++ .owner = THIS_MODULE, ++ .open = query_congestion_open, ++ .read = seq_read, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * QMan register ++ ******************************************************************************/ ++struct qman_register_s { ++ u32 val; ++}; ++static struct qman_register_s qman_register_data; ++ ++static void init_ccsrmempeek(void) ++{ ++ struct device_node *dn; ++ const u32 *regaddr_p; ++ ++ dn = of_find_compatible_node(NULL, NULL, "fsl,qman"); ++ if (!dn) { ++ pr_info("No fsl,qman node\n"); ++ return; ++ } ++ regaddr_p = of_get_address(dn, 0, &qman_ccsr_size, NULL); ++ if (!regaddr_p) { ++ of_node_put(dn); ++ return; ++ } ++ qman_ccsr_start = of_translate_address(dn, regaddr_p); ++ of_node_put(dn); ++} ++/* This function provides access to QMan ccsr memory map */ ++static int qman_ccsrmempeek(u32 *val, u32 offset) ++{ ++ void __iomem *addr; ++ u64 phys_addr; ++ ++ if (!qman_ccsr_start) ++ return -EINVAL; ++ ++ if (offset > (qman_ccsr_size - sizeof(u32))) ++ return -EINVAL; ++ ++ phys_addr = qman_ccsr_start + offset; ++ addr = ioremap(phys_addr, sizeof(u32)); ++ if (!addr) { ++ pr_err("ccsrmempeek, ioremap failed\n"); ++ return -EINVAL; ++ } ++ *val = in_be32(addr); ++ iounmap(addr); ++ return 0; ++} ++ ++static int qman_ccsrmempeek_show(struct seq_file *file, void *offset) ++{ ++ u32 b; ++ ++ qman_ccsrmempeek(&b, qman_register_data.val); ++ seq_printf(file, "QMan register offset = 0x%x\n", ++ qman_register_data.val); ++ seq_printf(file, "value = 0x%08x\n", b); ++ ++ return 0; ++} ++ ++static int qman_ccsrmempeek_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, qman_ccsrmempeek_show, NULL); ++} ++ ++static ssize_t qman_ccsrmempeek_write(struct file *f, const char __user *buf, ++ size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ /* multiple of 4 */ ++ if (val > (qman_ccsr_size - sizeof(u32))) { ++ pr_info("Input 0x%lx > 0x%llx\n", ++ val, (qman_ccsr_size - sizeof(u32))); ++ return -EINVAL; ++ } ++ if (val & 0x3) { ++ pr_info("Input 0x%lx not multiple of 4\n", val); ++ return -EINVAL; ++ } ++ qman_register_data.val = val; ++ return count; ++} ++ ++static const struct file_operations qman_ccsrmempeek_fops = { ++ .owner = THIS_MODULE, ++ .open = qman_ccsrmempeek_open, ++ .read = seq_read, ++ .write = qman_ccsrmempeek_write, ++}; ++ ++/******************************************************************************* ++ * QMan state ++ ******************************************************************************/ ++static int qman_fqd_state_show(struct seq_file *file, void *offset) ++{ ++ struct qm_mcr_queryfq_np np; ++ struct qman_fq fq; ++ struct line_buffer_fq line_buf; ++ int ret, i; ++ u8 *state = file->private; ++ u32 qm_fq_state_cnt[fqd_states_count]; ++ ++ memset(qm_fq_state_cnt, 0, sizeof(qm_fq_state_cnt)); ++ memset(&line_buf, 0, sizeof(line_buf)); ++ ++ seq_printf(file, "List of fq ids in state: %s\n", state_txt[*state]); ++ ++ for (i = 1; i < fqid_max; i++) { ++ fq.fqid = i; ++ ret = qman_query_fq_np(&fq, &np); ++ if (ret) ++ return ret; ++ if (*state == (np.state & QM_MCR_NP_STATE_MASK)) ++ add_to_line_buffer(&line_buf, fq.fqid, file); ++ /* Keep a summary count of all states */ ++ if ((np.state & QM_MCR_NP_STATE_MASK) < fqd_states_count) ++ qm_fq_state_cnt[(np.state & QM_MCR_NP_STATE_MASK)]++; ++ } ++ flush_line_buffer(&line_buf, file); ++ ++ for (i = 0; i < fqd_states_count; i++) { ++ seq_printf(file, "%s count = %u\n", state_txt[i], ++ qm_fq_state_cnt[i]); ++ } ++ return 0; ++} ++ ++static int qman_fqd_state_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, qman_fqd_state_show, inode->i_private); ++} ++ ++static const struct file_operations qman_fqd_state_fops = { ++ .owner = THIS_MODULE, ++ .open = qman_fqd_state_open, ++ .read = seq_read, ++}; ++ ++static int qman_fqd_ctrl_show(struct seq_file *file, void *offset) ++{ ++ struct qm_fqd fqd; ++ struct qman_fq fq; ++ u32 fq_en_cnt = 0, fq_di_cnt = 0; ++ int ret, i; ++ struct mask_filter_s *data = file->private; ++ const char *ctrl_txt = get_fqd_ctrl_text(data->mask); ++ struct line_buffer_fq line_buf; ++ ++ memset(&line_buf, 0, sizeof(line_buf)); ++ seq_printf(file, "List of fq ids with: %s :%s\n", ++ ctrl_txt, (data->filter) ? "enabled" : "disabled"); ++ for (i = 1; i < fqid_max; i++) { ++ fq.fqid = i; ++ memset(&fqd, 0, sizeof(struct qm_fqd)); ++ ret = qman_query_fq(&fq, &fqd); ++ if (ret) ++ return ret; ++ if (data->filter) { ++ if (fqd.fq_ctrl & data->mask) ++ add_to_line_buffer(&line_buf, fq.fqid, file); ++ } else { ++ if (!(fqd.fq_ctrl & data->mask)) ++ add_to_line_buffer(&line_buf, fq.fqid, file); ++ } ++ if (fqd.fq_ctrl & data->mask) ++ fq_en_cnt++; ++ else ++ fq_di_cnt++; ++ } ++ flush_line_buffer(&line_buf, file); ++ ++ seq_printf(file, "Total FQD with: %s : enabled = %u\n", ++ ctrl_txt, fq_en_cnt); ++ seq_printf(file, "Total FQD with: %s : disabled = %u\n", ++ ctrl_txt, fq_di_cnt); ++ return 0; ++} ++ ++/******************************************************************************* ++ * QMan ctrl CGE, TDE, ORP, CTX, CPC, SFDR, BLOCK, HOLD, CACHE ++ ******************************************************************************/ ++static int qman_fqd_ctrl_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, qman_fqd_ctrl_show, inode->i_private); ++} ++ ++static const struct file_operations qman_fqd_ctrl_fops = { ++ .owner = THIS_MODULE, ++ .open = qman_fqd_ctrl_open, ++ .read = seq_read, ++}; ++ ++/******************************************************************************* ++ * QMan ctrl summary ++ ******************************************************************************/ ++/******************************************************************************* ++ * QMan summary state ++ ******************************************************************************/ ++static int qman_fqd_non_prog_summary_show(struct seq_file *file, void *offset) ++{ ++ struct qm_mcr_queryfq_np np; ++ struct qman_fq fq; ++ int ret, i; ++ u32 qm_fq_state_cnt[fqd_states_count]; ++ ++ memset(qm_fq_state_cnt, 0, sizeof(qm_fq_state_cnt)); ++ ++ for (i = 1; i < fqid_max; i++) { ++ fq.fqid = i; ++ ret = qman_query_fq_np(&fq, &np); ++ if (ret) ++ return ret; ++ /* Keep a summary count of all states */ ++ if ((np.state & QM_MCR_NP_STATE_MASK) < fqd_states_count) ++ qm_fq_state_cnt[(np.state & QM_MCR_NP_STATE_MASK)]++; ++ } ++ ++ for (i = 0; i < fqd_states_count; i++) { ++ seq_printf(file, "%s count = %u\n", state_txt[i], ++ qm_fq_state_cnt[i]); ++ } ++ return 0; ++} ++ ++static int qman_fqd_prog_summary_show(struct seq_file *file, void *offset) ++{ ++ struct qm_fqd fqd; ++ struct qman_fq fq; ++ int ret, i , j; ++ u32 qm_prog_cnt[mask_filter_count/2]; ++ ++ memset(qm_prog_cnt, 0, sizeof(qm_prog_cnt)); ++ ++ for (i = 1; i < fqid_max; i++) { ++ memset(&fqd, 0, sizeof(struct qm_fqd)); ++ fq.fqid = i; ++ ret = qman_query_fq(&fq, &fqd); ++ if (ret) ++ return ret; ++ /* Keep a summary count of all states */ ++ for (j = 0; j < mask_filter_count; j += 2) ++ if ((fqd.fq_ctrl & QM_FQCTRL_MASK) & ++ mask_filter[j].mask) ++ qm_prog_cnt[j/2]++; ++ } ++ for (i = 0; i < mask_filter_count/2; i++) { ++ seq_printf(file, "%s count = %u\n", ++ get_fqd_ctrl_text(mask_filter[i*2].mask), ++ qm_prog_cnt[i]); ++ } ++ return 0; ++} ++ ++static int qman_fqd_summary_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ ++ /* Display summary of non programmable fields */ ++ ret = qman_fqd_non_prog_summary_show(file, offset); ++ if (ret) ++ return ret; ++ seq_printf(file, "-----------------------------------------\n"); ++ /* Display programmable fields */ ++ ret = qman_fqd_prog_summary_show(file, offset); ++ if (ret) ++ return ret; ++ return 0; ++} ++ ++static int qman_fqd_summary_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, qman_fqd_summary_show, NULL); ++} ++ ++static const struct file_operations qman_fqd_summary_fops = { ++ .owner = THIS_MODULE, ++ .open = qman_fqd_summary_open, ++ .read = seq_read, ++}; ++ ++/******************************************************************************* ++ * QMan destination work queue ++ ******************************************************************************/ ++struct qman_dest_wq_s { ++ u16 wq_id; ++}; ++static struct qman_dest_wq_s qman_dest_wq_data = { ++ .wq_id = 0, ++}; ++ ++static int qman_fqd_dest_wq_show(struct seq_file *file, void *offset) ++{ ++ struct qm_fqd fqd; ++ struct qman_fq fq; ++ int ret, i; ++ u16 *wq, wq_id = qman_dest_wq_data.wq_id; ++ struct line_buffer_fq line_buf; ++ ++ memset(&line_buf, 0, sizeof(line_buf)); ++ /* use vmalloc : need to allocate large memory region and don't ++ * require the memory to be physically contiguous. */ ++ wq = vmalloc(sizeof(u16) * (0xFFFF+1)); ++ if (!wq) ++ return -ENOMEM; ++ memset(wq, 0, sizeof(u16) * (0xFFFF+1)); ++ ++ seq_printf(file, "List of fq ids with destination work queue id" ++ " = 0x%x\n", wq_id); ++ ++ for (i = 1; i < fqid_max; i++) { ++ fq.fqid = i; ++ memset(&fqd, 0, sizeof(struct qm_fqd)); ++ ret = qman_query_fq(&fq, &fqd); ++ if (ret) { ++ vfree(wq); ++ return ret; ++ } ++ if (wq_id == fqd.dest_wq) ++ add_to_line_buffer(&line_buf, fq.fqid, file); ++ wq[fqd.dest_wq]++; ++ } ++ flush_line_buffer(&line_buf, file); ++ ++ seq_printf(file, "Summary of all FQD destination work queue values\n"); ++ for (i = 0; i < 0xFFFF; i++) { ++ if (wq[i]) ++ seq_printf(file, "Channel: 0x%x WQ: 0x%x WQ_ID: 0x%x, " ++ "count = %u\n", i >> 3, i & 0x3, i, wq[i]); ++ } ++ vfree(wq); ++ return 0; ++} ++ ++static ssize_t qman_fqd_dest_wq_write(struct file *f, const char __user *buf, ++ size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > 0xFFFF) ++ return -EINVAL; ++ qman_dest_wq_data.wq_id = val; ++ return count; ++} ++ ++static int qman_fqd_dest_wq_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, qman_fqd_dest_wq_show, NULL); ++} ++ ++static const struct file_operations qman_fqd_dest_wq_fops = { ++ .owner = THIS_MODULE, ++ .open = qman_fqd_dest_wq_open, ++ .read = seq_read, ++ .write = qman_fqd_dest_wq_write, ++}; ++ ++/******************************************************************************* ++ * QMan Intra-Class Scheduling Credit ++ ******************************************************************************/ ++static int qman_fqd_cred_show(struct seq_file *file, void *offset) ++{ ++ struct qm_fqd fqd; ++ struct qman_fq fq; ++ int ret, i; ++ u32 fq_cnt = 0; ++ struct line_buffer_fq line_buf; ++ ++ memset(&line_buf, 0, sizeof(line_buf)); ++ seq_printf(file, "List of fq ids with Intra-Class Scheduling Credit > 0" ++ "\n"); ++ ++ for (i = 1; i < fqid_max; i++) { ++ fq.fqid = i; ++ memset(&fqd, 0, sizeof(struct qm_fqd)); ++ ret = qman_query_fq(&fq, &fqd); ++ if (ret) ++ return ret; ++ if (fqd.ics_cred > 0) { ++ add_to_line_buffer(&line_buf, fq.fqid, file); ++ fq_cnt++; ++ } ++ } ++ flush_line_buffer(&line_buf, file); ++ ++ seq_printf(file, "Total FQD with ics_cred > 0 = %d\n", fq_cnt); ++ return 0; ++} ++ ++static int qman_fqd_cred_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, qman_fqd_cred_show, NULL); ++} ++ ++static const struct file_operations qman_fqd_cred_fops = { ++ .owner = THIS_MODULE, ++ .open = qman_fqd_cred_open, ++ .read = seq_read, ++}; ++ ++/******************************************************************************* ++ * Class Queue Fields ++ ******************************************************************************/ ++struct query_cq_fields_data_s { ++ u32 cqid; ++}; ++ ++static struct query_cq_fields_data_s query_cq_fields_data = { ++ .cqid = 1, ++}; ++ ++static int query_cq_fields_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_ceetm_cq_query query_result; ++ unsigned int cqid; ++ ++ cqid = query_cq_fields_data.cqid; ++ ret = qman_ceetm_query_cq(cqid, 0, &query_result); ++ if (ret) ++ return ret; ++ seq_printf(file, "Query CQ Fields Result cqid 0x%x\n", cqid); ++ seq_printf(file, " ccgid: %u\n", query_result.ccgid); ++ seq_printf(file, " state: %u\n", query_result.state); ++ seq_printf(file, " pfdr_hptr: %u\n", query_result.pfdr_hptr); ++ seq_printf(file, " pfdr_tptr: %u\n", query_result.pfdr_tptr); ++ seq_printf(file, " od1_xsfdr: %u\n", query_result.od1_xsfdr); ++ seq_printf(file, " od2_xsfdr: %u\n", query_result.od2_xsfdr); ++ seq_printf(file, " od3_xsfdr: %u\n", query_result.od3_xsfdr); ++ seq_printf(file, " od4_xsfdr: %u\n", query_result.od4_xsfdr); ++ seq_printf(file, " od5_xsfdr: %u\n", query_result.od5_xsfdr); ++ seq_printf(file, " od6_xsfdr: %u\n", query_result.od6_xsfdr); ++ seq_printf(file, " ra1_xsfdr: %u\n", query_result.ra1_xsfdr); ++ seq_printf(file, " ra2_xsfdr: %u\n", query_result.ra2_xsfdr); ++ seq_printf(file, " frame_count: %u\n", query_result.frm_cnt); ++ ++ return 0; ++} ++ ++static int query_cq_fields_open(struct inode *inode, ++ struct file *file) ++{ ++ return single_open(file, query_cq_fields_show, NULL); ++} ++ ++static ssize_t query_cq_fields_write(struct file *f, ++ const char __user *buf, size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > MAX_FQID) ++ return -EINVAL; ++ query_cq_fields_data.cqid = (u32)val; ++ return count; ++} ++ ++static const struct file_operations query_cq_fields_fops = { ++ .owner = THIS_MODULE, ++ .open = query_cq_fields_open, ++ .read = seq_read, ++ .write = query_cq_fields_write, ++ .release = single_release, ++}; ++/* helper macros used in qman_debugfs_module_init */ ++#define QMAN_DBGFS_ENTRY(name, mode, parent, data, fops) \ ++ do { \ ++ d = debugfs_create_file(name, \ ++ mode, parent, \ ++ data, \ ++ fops); \ ++ if (d == NULL) { \ ++ ret = -ENOMEM; \ ++ goto _return; \ ++ } \ ++ } while (0) ++ ++/* dfs_root as parent */ ++#define QMAN_DBGFS_ENTRY_ROOT(name, mode, data, fops) \ ++ QMAN_DBGFS_ENTRY(name, mode, dfs_root, data, fops) ++ ++/* fqd_root as parent */ ++#define QMAN_DBGFS_ENTRY_FQDROOT(name, mode, data, fops) \ ++ QMAN_DBGFS_ENTRY(name, mode, fqd_root, data, fops) ++ ++/* fqd state */ ++#define QMAN_DBGFS_ENTRY_FQDSTATE(name, index) \ ++ QMAN_DBGFS_ENTRY_FQDROOT(name, S_IRUGO, \ ++ (void *)&mask_filter[index], &qman_fqd_ctrl_fops) ++ ++static int __init qman_debugfs_module_init(void) ++{ ++ int ret = 0; ++ struct dentry *d, *fqd_root; ++ u32 reg; ++ ++ fqid_max = 0; ++ init_ccsrmempeek(); ++ if (qman_ccsr_start) { ++ if (!qman_ccsrmempeek(®, QM_FQD_AR)) { ++ /* extract the size of the FQD window */ ++ reg = reg & 0x3f; ++ /* calculate valid frame queue descriptor range */ ++ fqid_max = (1 << (reg + 1)) / QM_FQD_BLOCK_SIZE; ++ } ++ } ++ dfs_root = debugfs_create_dir("qman", NULL); ++ fqd_root = debugfs_create_dir("fqd", dfs_root); ++ if (dfs_root == NULL || fqd_root == NULL) { ++ ret = -ENOMEM; ++ pr_err("Cannot create qman/fqd debugfs dir\n"); ++ goto _return; ++ } ++ if (fqid_max) { ++ QMAN_DBGFS_ENTRY_ROOT("ccsrmempeek", S_IRUGO | S_IWUGO, ++ NULL, &qman_ccsrmempeek_fops); ++ } ++ QMAN_DBGFS_ENTRY_ROOT("query_fq_np_fields", S_IRUGO | S_IWUGO, ++ &query_fq_np_fields_data, &query_fq_np_fields_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("query_fq_fields", S_IRUGO | S_IWUGO, ++ &query_fq_fields_data, &query_fq_fields_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("query_wq_lengths", S_IRUGO | S_IWUGO, ++ &query_wq_lengths_data, &query_wq_lengths_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("query_cgr", S_IRUGO | S_IWUGO, ++ &query_cgr_data, &query_cgr_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("query_congestion", S_IRUGO, ++ NULL, &query_congestion_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("testwrite_cgr", S_IRUGO, ++ NULL, &testwrite_cgr_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("testwrite_cgr_cgrid", S_IRUGO | S_IWUGO, ++ NULL, &teswrite_cgr_cgrid_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("testwrite_cgr_ibcnt", S_IRUGO | S_IWUGO, ++ NULL, &teswrite_cgr_ibcnt_fops); ++ ++ /* Create files with fqd_root as parent */ ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("stateoos", S_IRUGO, ++ (void *)&fqd_states[QM_MCR_NP_STATE_OOS], &qman_fqd_state_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("state_retired", S_IRUGO, ++ (void *)&fqd_states[QM_MCR_NP_STATE_RETIRED], ++ &qman_fqd_state_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("state_tentatively_sched", S_IRUGO, ++ (void *)&fqd_states[QM_MCR_NP_STATE_TEN_SCHED], ++ &qman_fqd_state_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("state_truly_sched", S_IRUGO, ++ (void *)&fqd_states[QM_MCR_NP_STATE_TRU_SCHED], ++ &qman_fqd_state_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("state_parked", S_IRUGO, ++ (void *)&fqd_states[QM_MCR_NP_STATE_PARKED], ++ &qman_fqd_state_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("state_active", S_IRUGO, ++ (void *)&fqd_states[QM_MCR_NP_STATE_ACTIVE], ++ &qman_fqd_state_fops); ++ QMAN_DBGFS_ENTRY_ROOT("query_cq_fields", S_IRUGO | S_IWUGO, ++ &query_cq_fields_data, &query_cq_fields_fops); ++ ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("cge_enable", 17); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("cge_disable", 16); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("tde_enable", 15); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("tde_disable", 14); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("orp_enable", 13); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("orp_disable", 12); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("ctx_a_stashing_enable", 11); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("ctx_a_stashing_disable", 10); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("cpc_enable", 9); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("cpc_disable", 8); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("sfdr_enable", 7); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("sfdr_disable", 6); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("avoid_blocking_enable", 5); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("avoid_blocking_disable", 4); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("hold_active_enable", 3); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("hold_active_disable", 2); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("prefer_in_cache_enable", 1); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("prefer_in_cache_disable", 0); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("summary", S_IRUGO, ++ NULL, &qman_fqd_summary_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("wq", S_IRUGO | S_IWUGO, ++ NULL, &qman_fqd_dest_wq_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("cred", S_IRUGO, ++ NULL, &qman_fqd_cred_fops); ++ ++ return 0; ++ ++_return: ++ if (dfs_root) ++ debugfs_remove_recursive(dfs_root); ++ return ret; ++} ++ ++static void __exit qman_debugfs_module_exit(void) ++{ ++ debugfs_remove_recursive(dfs_root); ++} ++ ++module_init(qman_debugfs_module_init); ++module_exit(qman_debugfs_module_exit); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/staging/fsl_qbman/qman_driver.c b/drivers/staging/fsl_qbman/qman_driver.c +new file mode 100644 +index 0000000..7157fac +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_driver.c +@@ -0,0 +1,743 @@ ++/* Copyright 2008-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "qman_private.h" ++#include ++ ++/* Global variable containing revision id (even on non-control plane systems ++ * where CCSR isn't available) */ ++u16 qman_ip_rev; ++EXPORT_SYMBOL(qman_ip_rev); ++u16 qm_channel_pool1 = QMAN_CHANNEL_POOL1; ++EXPORT_SYMBOL(qm_channel_pool1); ++u16 qm_channel_caam = QMAN_CHANNEL_CAAM; ++EXPORT_SYMBOL(qm_channel_caam); ++u16 qm_channel_pme = QMAN_CHANNEL_PME; ++EXPORT_SYMBOL(qm_channel_pme); ++u16 qman_portal_max; ++ ++u32 qman_clk; ++struct qm_ceetm qman_ceetms[QMAN_CEETM_MAX]; ++ ++/* size of the fqd region in bytes */ ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++static u32 fqd_size = (PAGE_SIZE << CONFIG_FSL_QMAN_FQD_SZ); ++#endif ++ ++/* For these variables, and the portal-initialisation logic, the ++ * comments in bman_driver.c apply here so won't be repeated. */ ++static struct qman_portal *shared_portals[NR_CPUS]; ++static int num_shared_portals; ++static int shared_portals_idx; ++ ++/* A SDQCR mask comprising all the available/visible pool channels */ ++static u32 pools_sdqcr; ++ ++#define STR_ERR_NOPROP "No '%s' property in node %s\n" ++#define STR_ERR_CELL "'%s' is not a %d-cell range in node %s\n" ++#define STR_FQID_RANGE "fsl,fqid-range" ++#define STR_POOL_CHAN_RANGE "fsl,pool-channel-range" ++#define STR_CGRID_RANGE "fsl,cgrid-range" ++ ++/* A "fsl,fqid-range" node; release the given range to the allocator */ ++static __init int fsl_fqid_range_init(struct device_node *node) ++{ ++ int ret; ++ const u32 *range = of_get_property(node, STR_FQID_RANGE, &ret); ++ if (!range) { ++ pr_err(STR_ERR_NOPROP, STR_FQID_RANGE, node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err(STR_ERR_CELL, STR_FQID_RANGE, 2, node->full_name); ++ return -EINVAL; ++ } ++ qman_release_fqid_range(range[0], range[1]); ++ pr_info("Qman: FQID allocator includes range %d:%d\n", ++ range[0], range[1]); ++ return 0; ++} ++ ++/* A "fsl,pool-channel-range" node; add to the SDQCR mask only */ ++static __init int fsl_pool_channel_range_sdqcr(struct device_node *node) ++{ ++ int ret; ++ const u32 *chanid = of_get_property(node, STR_POOL_CHAN_RANGE, &ret); ++ if (!chanid) { ++ pr_err(STR_ERR_NOPROP, STR_POOL_CHAN_RANGE, node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err(STR_ERR_CELL, STR_POOL_CHAN_RANGE, 1, node->full_name); ++ return -EINVAL; ++ } ++ for (ret = 0; ret < chanid[1]; ret++) ++ pools_sdqcr |= QM_SDQCR_CHANNELS_POOL_CONV(chanid[0] + ret); ++ return 0; ++} ++ ++/* A "fsl,pool-channel-range" node; release the given range to the allocator */ ++static __init int fsl_pool_channel_range_init(struct device_node *node) ++{ ++ int ret; ++ const u32 *chanid = of_get_property(node, STR_POOL_CHAN_RANGE, &ret); ++ if (!chanid) { ++ pr_err(STR_ERR_NOPROP, STR_POOL_CHAN_RANGE, node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err(STR_ERR_CELL, STR_POOL_CHAN_RANGE, 1, node->full_name); ++ return -EINVAL; ++ } ++ qman_release_pool_range(chanid[0], chanid[1]); ++ pr_info("Qman: pool channel allocator includes range %d:%d\n", ++ chanid[0], chanid[1]); ++ return 0; ++} ++ ++/* A "fsl,cgrid-range" node; release the given range to the allocator */ ++static __init int fsl_cgrid_range_init(struct device_node *node) ++{ ++ struct qman_cgr cgr; ++ int ret, errors = 0; ++ const u32 *range = of_get_property(node, STR_CGRID_RANGE, &ret); ++ if (!range) { ++ pr_err(STR_ERR_NOPROP, STR_CGRID_RANGE, node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err(STR_ERR_CELL, STR_CGRID_RANGE, 2, node->full_name); ++ return -EINVAL; ++ } ++ qman_release_cgrid_range(range[0], range[1]); ++ pr_info("Qman: CGRID allocator includes range %d:%d\n", ++ range[0], range[1]); ++ for (cgr.cgrid = 0; cgr.cgrid < __CGR_NUM; cgr.cgrid++) { ++ ret = qman_modify_cgr(&cgr, QMAN_CGR_FLAG_USE_INIT, NULL); ++ if (ret) ++ errors++; ++ } ++ if (errors) ++ pr_err("Warning: %d error%s while initialising CGRs %d:%d\n", ++ errors, (errors > 1) ? "s" : "", range[0], range[1]); ++ return 0; ++} ++ ++static __init int fsl_ceetm_init(struct device_node *node) ++{ ++ enum qm_dc_portal dcp_portal; ++ struct qm_ceetm_sp *sp; ++ struct qm_ceetm_lni *lni; ++ int ret, i; ++ const u32 *range; ++ ++ /* Find LFQID range */ ++ range = of_get_property(node, "fsl,ceetm-lfqid-range", &ret); ++ if (!range) { ++ pr_err("No fsl,ceetm-lfqid-range in node %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err("fsl,ceetm-lfqid-range is not a 2-cell range in node" ++ " %s\n", node->full_name); ++ return -EINVAL; ++ } ++ ++ dcp_portal = (range[0] & 0x0F0000) >> 16; ++ if (dcp_portal > qm_dc_portal_fman1) { ++ pr_err("The DCP portal %d doesn't support CEETM\n", dcp_portal); ++ return -EINVAL; ++ } ++ ++ if (dcp_portal == qm_dc_portal_fman0) ++ qman_release_ceetm0_lfqid_range(range[0], range[1]); ++ if (dcp_portal == qm_dc_portal_fman1) ++ qman_release_ceetm1_lfqid_range(range[0], range[1]); ++ pr_debug("Qman: The lfqid allocator of CEETM %d includes range" ++ " 0x%x:0x%x\n", dcp_portal, range[0], range[1]); ++ ++ qman_ceetms[dcp_portal].idx = dcp_portal; ++ INIT_LIST_HEAD(&qman_ceetms[dcp_portal].sub_portals); ++ INIT_LIST_HEAD(&qman_ceetms[dcp_portal].lnis); ++ ++ /* Find Sub-portal range */ ++ range = of_get_property(node, "fsl,ceetm-sp-range", &ret); ++ if (!range) { ++ pr_err("No fsl,ceetm-sp-range in node %s\n", node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err("fsl,ceetm-sp-range is not a 2-cell range in node %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < range[1]; i++) { ++ sp = kzalloc(sizeof(*sp), GFP_KERNEL); ++ if (!sp) { ++ pr_err("Can't alloc memory for sub-portal %d\n", ++ range[0] + i); ++ return -ENOMEM; ++ } ++ sp->idx = range[0] + i; ++ sp->dcp_idx = dcp_portal; ++ sp->is_claimed = 0; ++ list_add_tail(&sp->node, &qman_ceetms[dcp_portal].sub_portals); ++ sp++; ++ } ++ pr_debug("Qman: Reserve sub-portal %d:%d for CEETM %d\n", ++ range[0], range[1], dcp_portal); ++ qman_ceetms[dcp_portal].sp_range[0] = range[0]; ++ qman_ceetms[dcp_portal].sp_range[1] = range[1]; ++ ++ /* Find LNI range */ ++ range = of_get_property(node, "fsl,ceetm-lni-range", &ret); ++ if (!range) { ++ pr_err("No fsl,ceetm-lni-range in node %s\n", node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err("fsl,ceetm-lni-range is not a 2-cell range in node %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < range[1]; i++) { ++ lni = kzalloc(sizeof(*lni), GFP_KERNEL); ++ if (!lni) { ++ pr_err("Can't alloc memory for LNI %d\n", ++ range[0] + i); ++ return -ENOMEM; ++ } ++ lni->idx = range[0] + i; ++ lni->dcp_idx = dcp_portal; ++ lni->is_claimed = 0; ++ INIT_LIST_HEAD(&lni->channels); ++ list_add_tail(&lni->node, &qman_ceetms[dcp_portal].lnis); ++ lni++; ++ } ++ pr_debug("Qman: Reserve LNI %d:%d for CEETM %d\n", ++ range[0], range[1], dcp_portal); ++ qman_ceetms[dcp_portal].lni_range[0] = range[0]; ++ qman_ceetms[dcp_portal].lni_range[1] = range[1]; ++ ++ /* Find CEETM channel range */ ++ range = of_get_property(node, "fsl,ceetm-channel-range", &ret); ++ if (!range) { ++ pr_err("No fsl,ceetm-channel-range in node %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err("fsl,ceetm-channel-range is not a 2-cell range in node" ++ "%s\n", node->full_name); ++ return -EINVAL; ++ } ++ ++ if (dcp_portal == qm_dc_portal_fman0) ++ qman_release_ceetm0_channel_range(range[0], range[1]); ++ if (dcp_portal == qm_dc_portal_fman1) ++ qman_release_ceetm1_channel_range(range[0], range[1]); ++ pr_debug("Qman: The channel allocator of CEETM %d includes" ++ " range %d:%d\n", dcp_portal, range[0], range[1]); ++ ++ /* Set CEETM PRES register */ ++ ret = qman_ceetm_set_prescaler(dcp_portal); ++ if (ret) ++ return ret; ++ return 0; ++} ++ ++void qman_get_ip_revision(struct device_node *dn) ++{ ++ u16 ip_rev = 0; ++ for_each_compatible_node(dn, NULL, "fsl,qman-portal") { ++ if (!of_device_is_available(dn)) ++ continue; ++ if (of_device_is_compatible(dn, "fsl,qman-portal-1.0") || ++ of_device_is_compatible(dn, "fsl,qman-portal-1.0.0")) { ++ ip_rev = QMAN_REV10; ++ qman_portal_max = 10; ++ } else if (of_device_is_compatible(dn, "fsl,qman-portal-1.1") || ++ of_device_is_compatible(dn, "fsl,qman-portal-1.1.0")) { ++ ip_rev = QMAN_REV11; ++ qman_portal_max = 10; ++ } else if (of_device_is_compatible(dn, "fsl,qman-portal-1.2") || ++ of_device_is_compatible(dn, "fsl,qman-portal-1.2.0")) { ++ ip_rev = QMAN_REV12; ++ qman_portal_max = 10; ++ } else if (of_device_is_compatible(dn, "fsl,qman-portal-2.0") || ++ of_device_is_compatible(dn, "fsl,qman-portal-2.0.0")) { ++ ip_rev = QMAN_REV20; ++ qman_portal_max = 3; ++ } else if (of_device_is_compatible(dn, ++ "fsl,qman-portal-3.0.0")) { ++ ip_rev = QMAN_REV30; ++ qman_portal_max = 50; ++ } else if (of_device_is_compatible(dn, ++ "fsl,qman-portal-3.0.1")) { ++ ip_rev = QMAN_REV30; ++ qman_portal_max = 25; ++ } else if (of_device_is_compatible(dn, ++ "fsl,qman-portal-3.0.2")) { ++ ip_rev = QMAN_REV30; ++ qman_portal_max = 10; ++ } else if (of_device_is_compatible(dn, ++ "fsl,qman-portal-3.0.3")) { ++ ip_rev = QMAN_REV30; ++ qman_portal_max = 18; ++ } ++ ++ if (!qman_ip_rev) { ++ if (ip_rev) { ++ qman_ip_rev = ip_rev; ++ } else { ++ pr_warning("unknown Qman version," ++ " default to rev1.1\n"); ++ qman_ip_rev = QMAN_REV11; ++ } ++ } else if (ip_rev && (qman_ip_rev != ip_rev)) ++ pr_warning("Revision=0x%04x, but portal '%s' has" ++ " 0x%04x\n", ++ qman_ip_rev, dn->full_name, ip_rev); ++ if (qman_ip_rev == ip_rev) ++ break; ++ } ++} ++ ++/* Parse a portal node, perform generic mapping duties and return the config. It ++ * is not known at this stage for what purpose (or even if) the portal will be ++ * used. */ ++static struct qm_portal_config * __init parse_pcfg(struct device_node *node) ++{ ++ struct qm_portal_config *pcfg; ++ const u32 *index, *channel; ++ int irq, ret; ++ ++ pcfg = kmalloc(sizeof(*pcfg), GFP_KERNEL); ++ if (!pcfg) { ++ pr_err("can't allocate portal config"); ++ return NULL; ++ } ++ ++ ret = of_address_to_resource(node, DPA_PORTAL_CE, ++ &pcfg->addr_phys[DPA_PORTAL_CE]); ++ if (ret) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, ++ "reg::CE"); ++ goto err; ++ } ++ ret = of_address_to_resource(node, DPA_PORTAL_CI, ++ &pcfg->addr_phys[DPA_PORTAL_CI]); ++ if (ret) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, ++ "reg::CI"); ++ goto err; ++ } ++ index = of_get_property(node, "cell-index", &ret); ++ if (!index || (ret != 4)) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, ++ "cell-index"); ++ goto err; ++ } ++ if (*index >= qman_portal_max) ++ goto err; ++ ++ channel = of_get_property(node, "fsl,qman-channel-id", &ret); ++ if (!channel || (ret != 4)) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, ++ "fsl,qman-channel-id"); ++ goto err; ++ } ++ if (*channel != (*index + QM_CHANNEL_SWPORTAL0)) ++ pr_err("Warning: node %s has mismatched %s and %s\n", ++ node->full_name, "cell-index", "fsl,qman-channel-id"); ++ pcfg->public_cfg.channel = *channel; ++ pcfg->public_cfg.cpu = -1; ++ irq = irq_of_parse_and_map(node, 0); ++ if (irq == NO_IRQ) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, ++ "interrupts"); ++ goto err; ++ } ++ pcfg->public_cfg.irq = irq; ++ pcfg->public_cfg.index = *index; ++ pcfg->node = node; ++#ifdef CONFIG_FSL_QMAN_CONFIG ++ /* We need the same LIODN offset for all portals */ ++ qman_liodn_fixup(pcfg->public_cfg.channel); ++#endif ++ ++ pcfg->addr_virt[DPA_PORTAL_CE] = ioremap_prot( ++ pcfg->addr_phys[DPA_PORTAL_CE].start, ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CE]), ++ 0); ++ pcfg->addr_virt[DPA_PORTAL_CI] = ioremap_prot( ++ pcfg->addr_phys[DPA_PORTAL_CI].start, ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CI]), ++ _PAGE_GUARDED | _PAGE_NO_CACHE); ++ ++ return pcfg; ++err: ++ kfree(pcfg); ++ return NULL; ++} ++ ++/* Destroy a previously-parsed portal config. */ ++static void destroy_pcfg(struct qm_portal_config *pcfg) ++{ ++ iounmap(pcfg->addr_virt[DPA_PORTAL_CI]); ++ iounmap(pcfg->addr_virt[DPA_PORTAL_CE]); ++ kfree(pcfg); ++} ++ ++static struct qm_portal_config *get_pcfg(struct list_head *list) ++{ ++ struct qm_portal_config *pcfg; ++ if (list_empty(list)) ++ return NULL; ++ pcfg = list_entry(list->prev, struct qm_portal_config, list); ++ list_del(&pcfg->list); ++ return pcfg; ++} ++ ++#ifdef CONFIG_FSL_PAMU ++static void portal_set_liodns(const struct qm_portal_config *pcfg, int cpu) ++{ ++ unsigned int index = 0; ++ unsigned int liodn_cnt = pamu_get_liodn_count(pcfg->node); ++ while (index < liodn_cnt) { ++ int ret = pamu_set_stash_dest(pcfg->node, index++, cpu, 1); ++ if (ret < 0) ++ pr_warning("Failed to set QMan stashing LIODN\n"); ++ } ++} ++#else ++#define portal_set_liodns(pcfg, cpu) do { } while (0) ++#endif ++ ++static void portal_set_cpu(const struct qm_portal_config *pcfg, int cpu) ++{ ++ portal_set_liodns(pcfg, cpu); ++#ifdef CONFIG_FSL_QMAN_CONFIG ++ if (qman_set_sdest(pcfg->public_cfg.channel, cpu)) ++#endif ++ pr_warning("Failed to set QMan portal's stash request queue\n"); ++} ++ ++/* UIO handling callbacks */ ++#define QMAN_UIO_PREAMBLE() \ ++ const struct qm_portal_config *pcfg = \ ++ container_of(__p, struct qm_portal_config, list) ++static int qman_uio_cb_init(const struct list_head *__p, struct uio_info *info) ++{ ++ QMAN_UIO_PREAMBLE(); ++ /* big enough for "qman-uio-xx" */ ++ char *name = kzalloc(16, GFP_KERNEL); ++ if (!name) ++ return -ENOMEM; ++ sprintf(name, "qman-uio-%x", pcfg->public_cfg.index); ++ info->name = name; ++ info->mem[DPA_PORTAL_CE].name = "cena"; ++ info->mem[DPA_PORTAL_CE].addr = pcfg->addr_phys[DPA_PORTAL_CE].start; ++ info->mem[DPA_PORTAL_CE].size = ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CE]); ++ info->mem[DPA_PORTAL_CE].memtype = UIO_MEM_PHYS; ++ info->mem[DPA_PORTAL_CI].name = "cinh"; ++ info->mem[DPA_PORTAL_CI].addr = pcfg->addr_phys[DPA_PORTAL_CI].start; ++ info->mem[DPA_PORTAL_CI].size = ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CI]); ++ info->mem[DPA_PORTAL_CI].memtype = UIO_MEM_PHYS; ++ info->irq = pcfg->public_cfg.irq; ++ return 0; ++} ++static void qman_uio_cb_destroy(const struct list_head *__p, ++ struct uio_info *info) ++{ ++ QMAN_UIO_PREAMBLE(); ++ kfree(info->name); ++ /* We own this struct but had passed it to the dpa_uio layer as a const ++ * so that we don't accidentally meddle with it in the dpa_uio code. ++ * Here it's passed back to us for final clean it up, so de-constify. */ ++ destroy_pcfg((struct qm_portal_config *)pcfg); ++} ++static int qman_uio_cb_open(const struct list_head *__p) ++{ ++ QMAN_UIO_PREAMBLE(); ++ /* Bind stashing LIODNs to the CPU we are currently executing on, and ++ * set the portal to use the stashing request queue corresonding to the ++ * cpu as well. The user-space driver assumption is that the pthread has ++ * to already be affine to one cpu only before opening a portal. If that ++ * check is circumvented, the only risk is a performance degradation - ++ * stashing will go to whatever cpu they happened to be running on when ++ * opening the device file, and if that isn't the cpu they subsequently ++ * bind to and do their polling on, tough. */ ++ portal_set_cpu(pcfg, hard_smp_processor_id()); ++ return 0; ++} ++static void qman_uio_cb_interrupt(const struct list_head *__p) ++{ ++ QMAN_UIO_PREAMBLE(); ++ /* This is the only manipulation of a portal register that isn't in the ++ * regular kernel portal driver (_high.c/_low.h). It is also the only ++ * time the kernel touches a register on a portal that is otherwise ++ * being driven by a user-space driver. So rather than messing up ++ * encapsulation for one trivial call, I am hard-coding the offset to ++ * the inhibit register and writing it directly from here. */ ++ out_be32(pcfg->addr_virt[DPA_PORTAL_CI] + 0xe0c, ~(u32)0); ++} ++static const struct dpa_uio_vtable qman_uio = { ++ .init_uio = qman_uio_cb_init, ++ .destroy = qman_uio_cb_destroy, ++ .on_open = qman_uio_cb_open, ++ .on_interrupt = qman_uio_cb_interrupt ++}; ++ ++static struct qman_portal *init_pcfg(struct qm_portal_config *pcfg) ++{ ++ struct qman_portal *p; ++ struct cpumask oldmask = *tsk_cpus_allowed(current); ++ ++ portal_set_cpu(pcfg, pcfg->public_cfg.cpu); ++ set_cpus_allowed_ptr(current, get_cpu_mask(pcfg->public_cfg.cpu)); ++ p = qman_create_affine_portal(pcfg, NULL); ++ if (p) { ++ u32 irq_sources = 0; ++ /* Determine what should be interrupt-vs-poll driven */ ++#ifdef CONFIG_FSL_DPA_PIRQ_SLOW ++ irq_sources |= QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI | ++ QM_PIRQ_CSCI; ++#endif ++#ifdef CONFIG_FSL_DPA_PIRQ_FAST ++ irq_sources |= QM_PIRQ_DQRI; ++#endif ++ qman_irqsource_add(irq_sources); ++ pr_info("Qman portal %sinitialised, cpu %d\n", ++ pcfg->public_cfg.is_shared ? "(shared) " : "", ++ pcfg->public_cfg.cpu); ++ } else ++ pr_crit("Qman portal failure on cpu %d\n", ++ pcfg->public_cfg.cpu); ++ set_cpus_allowed_ptr(current, &oldmask); ++ return p; ++} ++ ++static void init_slave(int cpu) ++{ ++ struct qman_portal *p; ++ struct cpumask oldmask = *tsk_cpus_allowed(current); ++ set_cpus_allowed_ptr(current, get_cpu_mask(cpu)); ++ p = qman_create_affine_slave(shared_portals[shared_portals_idx++]); ++ if (!p) ++ pr_err("Qman slave portal failure on cpu %d\n", cpu); ++ else ++ pr_info("Qman portal %sinitialised, cpu %d\n", "(slave) ", cpu); ++ set_cpus_allowed_ptr(current, &oldmask); ++ if (shared_portals_idx >= num_shared_portals) ++ shared_portals_idx = 0; ++} ++ ++static struct cpumask want_unshared __initdata; ++static struct cpumask want_shared __initdata; ++ ++static int __init parse_qportals(char *str) ++{ ++ return parse_portals_bootarg(str, &want_shared, &want_unshared, ++ "qportals"); ++} ++__setup("qportals=", parse_qportals); ++ ++static __init int qman_init(void) ++{ ++ struct cpumask slave_cpus; ++ struct cpumask unshared_cpus = *cpu_none_mask; ++ struct cpumask shared_cpus = *cpu_none_mask; ++ LIST_HEAD(unused_pcfgs); ++ LIST_HEAD(unshared_pcfgs); ++ LIST_HEAD(shared_pcfgs); ++ struct device_node *dn; ++ struct qm_portal_config *pcfg; ++ struct qman_portal *p; ++ int cpu, ret; ++ const u32 *clk; ++ ++ /* Initialise the Qman (CCSR) device */ ++ for_each_compatible_node(dn, NULL, "fsl,qman") { ++ if (!qman_init_ccsr(dn)) ++ pr_info("Qman err interrupt handler present\n"); ++ else ++ pr_err("Qman CCSR setup failed\n"); ++ ++ clk = of_get_property(dn, "clock-frequency", NULL); ++ if (!clk) ++ pr_warning("Can't find Qman clock frequency\n"); ++ else ++ qman_clk = *clk; ++ } ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ /* Setup lookup table for FQ demux */ ++ ret = qman_setup_fq_lookup_table(fqd_size/64); ++ if (ret) ++ return ret; ++#endif ++ ++ /* Get qman ip revision */ ++ qman_get_ip_revision(dn); ++ if ((qman_ip_rev & 0xff00) >= QMAN_REV30) { ++ qm_channel_pool1 = QMAN_CHANNEL_POOL1_REV3; ++ qm_channel_caam = QMAN_CHANNEL_CAAM_REV3; ++ qm_channel_pme = QMAN_CHANNEL_PME_REV3; ++ } ++ ++ /* Parse pool channels into the SDQCR mask. (Must happen before portals ++ * are initialised.) */ ++ for_each_compatible_node(dn, NULL, "fsl,pool-channel-range") { ++ ret = fsl_pool_channel_range_sdqcr(dn); ++ if (ret) ++ return ret; ++ } ++ /* Initialise portals. See bman_driver.c for comments */ ++ for_each_compatible_node(dn, NULL, "fsl,qman-portal") { ++ if (!of_device_is_available(dn)) ++ continue; ++ pcfg = parse_pcfg(dn); ++ if (pcfg) { ++ pcfg->public_cfg.pools = pools_sdqcr; ++ list_add_tail(&pcfg->list, &unused_pcfgs); ++ } ++ } ++ for_each_cpu(cpu, &want_shared) { ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ pcfg->public_cfg.cpu = cpu; ++ list_add_tail(&pcfg->list, &shared_pcfgs); ++ cpumask_set_cpu(cpu, &shared_cpus); ++ } ++ for_each_cpu(cpu, &want_unshared) { ++ if (cpumask_test_cpu(cpu, &shared_cpus)) ++ continue; ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ pcfg->public_cfg.cpu = cpu; ++ list_add_tail(&pcfg->list, &unshared_pcfgs); ++ cpumask_set_cpu(cpu, &unshared_cpus); ++ } ++ if (list_empty(&shared_pcfgs) && list_empty(&unshared_pcfgs)) { ++ for_each_online_cpu(cpu) { ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ pcfg->public_cfg.cpu = cpu; ++ list_add_tail(&pcfg->list, &unshared_pcfgs); ++ cpumask_set_cpu(cpu, &unshared_cpus); ++ } ++ } ++ cpumask_andnot(&slave_cpus, cpu_online_mask, &shared_cpus); ++ cpumask_andnot(&slave_cpus, &slave_cpus, &unshared_cpus); ++ if (cpumask_empty(&slave_cpus)) { ++ if (!list_empty(&shared_pcfgs)) { ++ cpumask_or(&unshared_cpus, &unshared_cpus, ++ &shared_cpus); ++ cpumask_clear(&shared_cpus); ++ list_splice_tail(&shared_pcfgs, &unshared_pcfgs); ++ INIT_LIST_HEAD(&shared_pcfgs); ++ } ++ } else { ++ if (list_empty(&shared_pcfgs)) { ++ pcfg = get_pcfg(&unshared_pcfgs); ++ if (!pcfg) { ++ pr_crit("No QMan portals available!\n"); ++ return 0; ++ } ++ cpumask_clear_cpu(pcfg->public_cfg.cpu, &unshared_cpus); ++ cpumask_set_cpu(pcfg->public_cfg.cpu, &shared_cpus); ++ list_add_tail(&pcfg->list, &shared_pcfgs); ++ } ++ } ++ list_for_each_entry(pcfg, &unshared_pcfgs, list) { ++ pcfg->public_cfg.is_shared = 0; ++ p = init_pcfg(pcfg); ++ } ++ list_for_each_entry(pcfg, &shared_pcfgs, list) { ++ pcfg->public_cfg.is_shared = 1; ++ p = init_pcfg(pcfg); ++ if (p) ++ shared_portals[num_shared_portals++] = p; ++ } ++ if (!cpumask_empty(&slave_cpus)) ++ for_each_cpu(cpu, &slave_cpus) ++ init_slave(cpu); ++ pr_info("Qman portals initialised\n"); ++#ifdef CONFIG_FSL_DPA_UIO ++ /* Export any left over portals as UIO devices */ ++ do { ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ ret = dpa_uio_register(&pcfg->list, &qman_uio); ++ if (ret) { ++ pr_err("Failure registering QMan UIO portal\n"); ++ destroy_pcfg(pcfg); ++ } ++ } while (1); ++#endif ++ /* Initialise FQID allocation ranges */ ++ for_each_compatible_node(dn, NULL, "fsl,fqid-range") { ++ ret = fsl_fqid_range_init(dn); ++ if (ret) ++ return ret; ++ } ++ /* Initialise CGRID allocation ranges */ ++ for_each_compatible_node(dn, NULL, "fsl,cgrid-range") { ++ ret = fsl_cgrid_range_init(dn); ++ if (ret) ++ return ret; ++ } ++ /* Parse pool channels into the allocator. (Must happen after portals ++ * are initialised.) */ ++ for_each_compatible_node(dn, NULL, "fsl,pool-channel-range") { ++ ret = fsl_pool_channel_range_init(dn); ++ if (ret) ++ return ret; ++ } ++ ++ /* Parse CEETM */ ++ for_each_compatible_node(dn, NULL, "fsl,qman-ceetm") { ++ ret = fsl_ceetm_init(dn); ++ if (ret) ++ return ret; ++ } ++ return 0; ++} ++subsys_initcall(qman_init); +diff --git a/drivers/staging/fsl_qbman/qman_high.c b/drivers/staging/fsl_qbman/qman_high.c +new file mode 100644 +index 0000000..a00185e +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_high.c +@@ -0,0 +1,4351 @@ ++/* Copyright 2008-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "qman_low.h" ++ ++/* Compilation constants */ ++#define DQRR_MAXFILL 15 ++#define EQCR_ITHRESH 4 /* if EQCR congests, interrupt threshold */ ++#define IRQNAME "QMan portal %d" ++#define MAX_IRQNAME 16 /* big enough for "QMan portal %d" */ ++ ++/* Lock/unlock frame queues, subject to the "LOCKED" flag. This is about ++ * inter-processor locking only. Note, FQLOCK() is always called either under a ++ * local_irq_save() or from interrupt context - hence there's no need for irq ++ * protection (and indeed, attempting to nest irq-protection doesn't work, as ++ * the "irq en/disable" machinery isn't recursive...). */ ++#define FQLOCK(fq) \ ++ do { \ ++ struct qman_fq *__fq478 = (fq); \ ++ if (fq_isset(__fq478, QMAN_FQ_FLAG_LOCKED)) \ ++ spin_lock(&__fq478->fqlock); \ ++ } while(0) ++#define FQUNLOCK(fq) \ ++ do { \ ++ struct qman_fq *__fq478 = (fq); \ ++ if (fq_isset(__fq478, QMAN_FQ_FLAG_LOCKED)) \ ++ spin_unlock(&__fq478->fqlock); \ ++ } while(0) ++ ++static inline void fq_set(struct qman_fq *fq, u32 mask) ++{ ++ set_bits(mask, &fq->flags); ++} ++static inline void fq_clear(struct qman_fq *fq, u32 mask) ++{ ++ clear_bits(mask, &fq->flags); ++} ++static inline int fq_isset(struct qman_fq *fq, u32 mask) ++{ ++ return fq->flags & mask; ++} ++static inline int fq_isclear(struct qman_fq *fq, u32 mask) ++{ ++ return !(fq->flags & mask); ++} ++ ++struct qman_portal { ++ struct qm_portal p; ++ unsigned long bits; /* PORTAL_BITS_*** - dynamic, strictly internal */ ++ unsigned long irq_sources; ++ u32 slowpoll; /* only used when interrupts are off */ ++ struct qman_fq *vdqcr_owned; /* only 1 volatile dequeue at a time */ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ struct qman_fq *eqci_owned; /* only 1 enqueue WAIT_SYNC at a time */ ++#endif ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ raw_spinlock_t sharing_lock; /* only used if is_shared */ ++ int is_shared; ++ struct qman_portal *sharing_redirect; ++#endif ++ u32 sdqcr; ++ int dqrr_disable_ref; ++ /* A portal-specific handler for DCP ERNs. If this is NULL, the global ++ * handler is called instead. */ ++ qman_cb_dc_ern cb_dc_ern; ++ /* When the cpu-affine portal is activated, this is non-NULL */ ++ const struct qm_portal_config *config; ++ /* This is needed for providing a non-NULL device to dma_map_***() */ ++ struct platform_device *pdev; ++ struct dpa_rbtree retire_table; ++ char irqname[MAX_IRQNAME]; ++ /* 2-element array. cgrs[0] is mask, cgrs[1] is snapshot. */ ++ struct qman_cgrs *cgrs; ++ /* 256-element array, each is a linked-list of CSCN handlers. */ ++ struct list_head cgr_cbs[256]; ++ /* list lock */ ++ spinlock_t cgr_lock; ++}; ++ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++#define PORTAL_IRQ_LOCK(p, irqflags) \ ++ do { \ ++ if ((p)->is_shared) \ ++ raw_spin_lock_irqsave(&(p)->sharing_lock, irqflags); \ ++ else \ ++ local_irq_save(irqflags); \ ++ } while (0) ++#define PORTAL_IRQ_UNLOCK(p, irqflags) \ ++ do { \ ++ if ((p)->is_shared) \ ++ raw_spin_unlock_irqrestore(&(p)->sharing_lock, \ ++ irqflags); \ ++ else \ ++ local_irq_restore(irqflags); \ ++ } while (0) ++#else ++#define PORTAL_IRQ_LOCK(p, irqflags) local_irq_save(irqflags) ++#define PORTAL_IRQ_UNLOCK(p, irqflags) local_irq_restore(irqflags) ++#endif ++ ++/* Global handler for DCP ERNs. Used when the portal receiving the message does ++ * not have a portal-specific handler. */ ++static qman_cb_dc_ern cb_dc_ern; ++ ++static cpumask_t affine_mask; ++static DEFINE_SPINLOCK(affine_mask_lock); ++static u16 affine_channels[NR_CPUS]; ++static DEFINE_PER_CPU(struct qman_portal, qman_affine_portal); ++/* "raw" gets the cpu-local struct whether it's a redirect or not. */ ++static inline struct qman_portal *get_raw_affine_portal(void) ++{ ++ return &get_cpu_var(qman_affine_portal); ++} ++/* For ops that can redirect, this obtains the portal to use */ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++static inline struct qman_portal *get_affine_portal(void) ++{ ++ struct qman_portal *p = get_raw_affine_portal(); ++ if (p->sharing_redirect) ++ return p->sharing_redirect; ++ return p; ++} ++#else ++#define get_affine_portal() get_raw_affine_portal() ++#endif ++/* For every "get", there must be a "put" */ ++static inline void put_affine_portal(void) ++{ ++ put_cpu_var(qman_affine_portal); ++} ++/* Exception: poll functions assume the caller is cpu-affine and in no risk of ++ * re-entrance, which are the two reasons we usually use the get/put_cpu_var() ++ * semantic - ie. to disable pre-emption. Some use-cases expect the execution ++ * context to remain as non-atomic during poll-triggered callbacks as it was ++ * when the poll API was first called (eg. NAPI), so we go out of our way in ++ * this case to not disable pre-emption. */ ++static inline struct qman_portal *get_poll_portal(void) ++{ ++ return &__get_cpu_var(qman_affine_portal); ++} ++#define put_poll_portal() do { ; } while (0) ++ ++/* This gives a FQID->FQ lookup to cover the fact that we can't directly demux ++ * retirement notifications (the fact they are sometimes h/w-consumed means that ++ * contextB isn't always a s/w demux - and as we can't know which case it is ++ * when looking at the notification, we have to use the slow lookup for all of ++ * them). NB, it's possible to have multiple FQ objects refer to the same FQID ++ * (though at most one of them should be the consumer), so this table isn't for ++ * all FQs - FQs are added when retirement commands are issued, and removed when ++ * they complete, which also massively reduces the size of this table. */ ++IMPLEMENT_DPA_RBTREE(fqtree, struct qman_fq, node, fqid); ++ ++/* This is what everything can wait on, even if it migrates to a different cpu ++ * to the one whose affine portal it is waiting on. */ ++static DECLARE_WAIT_QUEUE_HEAD(affine_queue); ++ ++static inline int table_push_fq(struct qman_portal *p, struct qman_fq *fq) ++{ ++ int ret = fqtree_push(&p->retire_table, fq); ++ if (ret) ++ pr_err("ERROR: double FQ-retirement %d\n", fq->fqid); ++ return ret; ++} ++ ++static inline void table_del_fq(struct qman_portal *p, struct qman_fq *fq) ++{ ++ fqtree_del(&p->retire_table, fq); ++} ++ ++static inline struct qman_fq *table_find_fq(struct qman_portal *p, u32 fqid) ++{ ++ return fqtree_find(&p->retire_table, fqid); ++} ++ ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++static void **qman_fq_lookup_table; ++static size_t qman_fq_lookup_table_size; ++ ++int qman_setup_fq_lookup_table(size_t num_entries) ++{ ++ num_entries++; ++ /* Allocate 1 more entry since the first entry is not used */ ++ qman_fq_lookup_table = vmalloc((num_entries * sizeof(void *))); ++ if (!qman_fq_lookup_table) { ++ pr_err("QMan: Could not allocate fq lookup table\n"); ++ return -ENOMEM; ++ } ++ memset(qman_fq_lookup_table, 0, num_entries * sizeof(void *)); ++ qman_fq_lookup_table_size = num_entries; ++ pr_info("QMan: Allocated lookup table at %p, entry count %lu\n", ++ qman_fq_lookup_table, ++ (unsigned long)qman_fq_lookup_table_size); ++ return 0; ++} ++ ++/* global structure that maintains fq object mapping */ ++static DEFINE_SPINLOCK(fq_hash_table_lock); ++ ++static int find_empty_fq_table_entry(u32 *entry, struct qman_fq *fq) ++{ ++ u32 i; ++ ++ spin_lock(&fq_hash_table_lock); ++ /* Can't use index zero because this has special meaning ++ * in context_b field. */ ++ for (i = 1; i < qman_fq_lookup_table_size; i++) { ++ if (qman_fq_lookup_table[i] == NULL) { ++ *entry = i; ++ qman_fq_lookup_table[i] = fq; ++ spin_unlock(&fq_hash_table_lock); ++ return 0; ++ } ++ } ++ spin_unlock(&fq_hash_table_lock); ++ return -ENOMEM; ++} ++ ++static void clear_fq_table_entry(u32 entry) ++{ ++ spin_lock(&fq_hash_table_lock); ++ BUG_ON(entry >= qman_fq_lookup_table_size); ++ qman_fq_lookup_table[entry] = NULL; ++ spin_unlock(&fq_hash_table_lock); ++} ++ ++static inline struct qman_fq *get_fq_table_entry(u32 entry) ++{ ++ BUG_ON(entry >= qman_fq_lookup_table_size); ++ return qman_fq_lookup_table[entry]; ++} ++#endif ++ ++/* In the case that slow- and fast-path handling are both done by qman_poll() ++ * (ie. because there is no interrupt handling), we ought to balance how often ++ * we do the fast-path poll versus the slow-path poll. We'll use two decrementer ++ * sources, so we call the fast poll 'n' times before calling the slow poll ++ * once. The idle decrementer constant is used when the last slow-poll detected ++ * no work to do, and the busy decrementer constant when the last slow-poll had ++ * work to do. */ ++#define SLOW_POLL_IDLE 1000 ++#define SLOW_POLL_BUSY 10 ++static u32 __poll_portal_slow(struct qman_portal *p, u32 is); ++static inline unsigned int __poll_portal_fast(struct qman_portal *p, ++ unsigned int poll_limit); ++ ++/* Portal interrupt handler */ ++static irqreturn_t portal_isr(__always_unused int irq, void *ptr) ++{ ++ struct qman_portal *p = ptr; ++ /* The CSCI source is cleared inside __poll_portal_slow(), because ++ * it could race against a Query Congestion State command also given ++ * as part of the handling of this interrupt source. We mustn't ++ * clear it a second time in this top-level function. */ ++ u32 clear = QM_DQAVAIL_MASK | (p->irq_sources & ~QM_PIRQ_CSCI); ++ u32 is = qm_isr_status_read(&p->p) & p->irq_sources; ++ /* DQRR-handling if it's interrupt-driven */ ++ if (is & QM_PIRQ_DQRI) ++ __poll_portal_fast(p, CONFIG_FSL_QMAN_POLL_LIMIT); ++ /* Handling of anything else that's interrupt-driven */ ++ clear |= __poll_portal_slow(p, is); ++ qm_isr_status_clear(&p->p, clear); ++ return IRQ_HANDLED; ++} ++ ++/* This inner version is used privately by qman_create_affine_portal(), as well ++ * as by the exported qman_stop_dequeues(). */ ++static inline void qman_stop_dequeues_ex(struct qman_portal *p) ++{ ++ unsigned long irqflags __maybe_unused; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ if (!(p->dqrr_disable_ref++)) ++ qm_dqrr_set_maxfill(&p->p, 0); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++} ++ ++static int drain_mr_fqrni(struct qm_portal *p) ++{ ++ const struct qm_mr_entry *msg; ++loop: ++ msg = qm_mr_current(p); ++ if (!msg) { ++ /* if MR was full and h/w had other FQRNI entries to produce, we ++ * need to allow it time to produce those entries once the ++ * existing entries are consumed. A worst-case situation ++ * (fully-loaded system) means h/w sequencers may have to do 3-4 ++ * other things before servicing the portal's MR pump, each of ++ * which (if slow) may take ~50 qman cycles (which is ~200 ++ * processor cycles). So rounding up and then multiplying this ++ * worst-case estimate by a factor of 10, just to be ++ * ultra-paranoid, goes as high as 10,000 cycles. NB, we consume ++ * one entry at a time, so h/w has an opportunity to produce new ++ * entries well before the ring has been fully consumed, so ++ * we're being *really* paranoid here. */ ++ u64 now, then = mfatb(); ++ do { ++ now = mfatb(); ++ } while ((then + 10000) > now); ++ msg = qm_mr_current(p); ++ if (!msg) ++ return 0; ++ } ++ if ((msg->verb & QM_MR_VERB_TYPE_MASK) != QM_MR_VERB_FQRNI) ++ /* We aren't draining anything but FQRNIs */ ++ return -1; ++ qm_mr_next(p); ++ qm_mr_cci_consume(p, 1); ++ goto loop; ++} ++ ++struct qman_portal *qman_create_affine_portal( ++ const struct qm_portal_config *config, ++ const struct qman_cgrs *cgrs) ++{ ++ struct qman_portal *portal = get_raw_affine_portal(); ++ struct qm_portal *__p = &portal->p; ++ char buf[16]; ++ int ret; ++ u32 isdr; ++ ++ /* A criteria for calling this function (from qman_driver.c) is that ++ * we're already affine to the cpu and won't schedule onto another cpu. ++ * This means we can put_affine_portal() and yet continue to use ++ * "portal", which in turn means aspects of this routine can sleep. */ ++ put_affine_portal(); ++ /* prep the low-level portal struct with the mapped addresses from the ++ * config, everything that follows depends on it and "config" is more ++ * for (de)reference... */ ++ __p->addr.addr_ce = config->addr_virt[DPA_PORTAL_CE]; ++ __p->addr.addr_ci = config->addr_virt[DPA_PORTAL_CI]; ++ if (qm_eqcr_init(__p, qm_eqcr_pvb, qm_eqcr_cce)) { ++ pr_err("Qman EQCR initialisation failed\n"); ++ goto fail_eqcr; ++ } ++ if (qm_dqrr_init(__p, config, qm_dqrr_dpush, qm_dqrr_pvb, ++ qm_dqrr_cdc, DQRR_MAXFILL)) { ++ pr_err("Qman DQRR initialisation failed\n"); ++ goto fail_dqrr; ++ } ++ if (qm_mr_init(__p, qm_mr_pvb, qm_mr_cci)) { ++ pr_err("Qman MR initialisation failed\n"); ++ goto fail_mr; ++ } ++ if (qm_mc_init(__p)) { ++ pr_err("Qman MC initialisation failed\n"); ++ goto fail_mc; ++ } ++ if (qm_isr_init(__p)) { ++ pr_err("Qman ISR initialisation failed\n"); ++ goto fail_isr; ++ } ++ /* static interrupt-gating controls */ ++ qm_dqrr_set_ithresh(__p, CONFIG_FSL_QMAN_PIRQ_DQRR_ITHRESH); ++ qm_mr_set_ithresh(__p, CONFIG_FSL_QMAN_PIRQ_MR_ITHRESH); ++ qm_isr_set_iperiod(__p, CONFIG_FSL_QMAN_PIRQ_IPERIOD); ++ portal->cgrs = kmalloc(2 * sizeof(*cgrs), GFP_KERNEL); ++ if (!portal->cgrs) ++ goto fail_cgrs; ++ /* initial snapshot is no-depletion */ ++ qman_cgrs_init(&portal->cgrs[1]); ++ if (cgrs) ++ portal->cgrs[0] = *cgrs; ++ else ++ /* if the given mask is NULL, assume all CGRs can be seen */ ++ qman_cgrs_fill(&portal->cgrs[0]); ++ for (ret = 0; ret < __CGR_NUM; ret++) ++ INIT_LIST_HEAD(&portal->cgr_cbs[ret]); ++ spin_lock_init(&portal->cgr_lock); ++ portal->bits = 0; ++ portal->slowpoll = 0; ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ portal->eqci_owned = NULL; ++#endif ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ raw_spin_lock_init(&portal->sharing_lock); ++ portal->is_shared = config->public_cfg.is_shared; ++ portal->sharing_redirect = NULL; ++#endif ++ portal->sdqcr = QM_SDQCR_SOURCE_CHANNELS | QM_SDQCR_COUNT_UPTO3 | ++ QM_SDQCR_DEDICATED_PRECEDENCE | QM_SDQCR_TYPE_PRIO_QOS | ++ QM_SDQCR_TOKEN_SET(0xab) | QM_SDQCR_CHANNELS_DEDICATED; ++ portal->dqrr_disable_ref = 0; ++ portal->cb_dc_ern = NULL; ++ sprintf(buf, "qportal-%d", config->public_cfg.channel); ++ portal->pdev = platform_device_alloc(buf, -1); ++ if (!portal->pdev) ++ goto fail_devalloc; ++ if (dma_set_mask(&portal->pdev->dev, DMA_BIT_MASK(40))) ++ goto fail_devadd; ++ ret = platform_device_add(portal->pdev); ++ if (ret) ++ goto fail_devadd; ++ dpa_rbtree_init(&portal->retire_table); ++ isdr = 0xffffffff; ++ qm_isr_disable_write(__p, isdr); ++ portal->irq_sources = 0; ++ qm_isr_enable_write(__p, portal->irq_sources); ++ qm_isr_status_clear(__p, 0xffffffff); ++ snprintf(portal->irqname, MAX_IRQNAME, IRQNAME, config->public_cfg.cpu); ++ if (request_irq(config->public_cfg.irq, portal_isr, 0, portal->irqname, ++ portal)) { ++ pr_err("request_irq() failed\n"); ++ goto fail_irq; ++ } ++ if ((config->public_cfg.cpu != -1) && ++ irq_can_set_affinity(config->public_cfg.irq) && ++ irq_set_affinity(config->public_cfg.irq, ++ cpumask_of(config->public_cfg.cpu))) { ++ pr_err("irq_set_affinity() failed\n"); ++ goto fail_affinity; ++ } ++ /* Need EQCR to be empty before continuing */ ++ isdr ^= QM_PIRQ_EQCI; ++ qm_isr_disable_write(__p, isdr); ++ ret = qm_eqcr_get_fill(__p); ++ if (ret) { ++ pr_err("Qman EQCR unclean\n"); ++ goto fail_eqcr_empty; ++ } ++ isdr ^= (QM_PIRQ_DQRI | QM_PIRQ_MRI); ++ qm_isr_disable_write(__p, isdr); ++ if (qm_dqrr_current(__p) != NULL) { ++ pr_err("Qman DQRR unclean\n"); ++ goto fail_dqrr_mr_empty; ++ } ++ if (qm_mr_current(__p) != NULL) { ++ /* special handling, drain just in case it's a few FQRNIs */ ++ if (drain_mr_fqrni(__p)) { ++ pr_err("Qman MR unclean\n"); ++ goto fail_dqrr_mr_empty; ++ } ++ } ++ /* Success */ ++ portal->config = config; ++ spin_lock(&affine_mask_lock); ++ cpumask_set_cpu(config->public_cfg.cpu, &affine_mask); ++ affine_channels[config->public_cfg.cpu] = config->public_cfg.channel; ++ spin_unlock(&affine_mask_lock); ++ qm_isr_disable_write(__p, 0); ++ qm_isr_uninhibit(__p); ++ /* Write a sane SDQCR */ ++ qm_dqrr_sdqcr_set(__p, portal->sdqcr); ++ return portal; ++fail_dqrr_mr_empty: ++fail_eqcr_empty: ++fail_affinity: ++ free_irq(config->public_cfg.irq, portal); ++fail_irq: ++ platform_device_del(portal->pdev); ++fail_devadd: ++ platform_device_put(portal->pdev); ++fail_devalloc: ++ if (portal->cgrs) ++ kfree(portal->cgrs); ++fail_cgrs: ++ qm_isr_finish(__p); ++fail_isr: ++ qm_mc_finish(__p); ++fail_mc: ++ qm_mr_finish(__p); ++fail_mr: ++ qm_dqrr_finish(__p); ++fail_dqrr: ++ qm_eqcr_finish(__p); ++fail_eqcr: ++ return NULL; ++} ++ ++/* These checks are BUG_ON()s because the driver is already supposed to avoid ++ * these cases. */ ++struct qman_portal *qman_create_affine_slave(struct qman_portal *redirect) ++{ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ struct qman_portal *p = get_raw_affine_portal(); ++ /* Check that we don't already have our own portal */ ++ BUG_ON(p->config); ++ /* Check that we aren't already slaving to another portal */ ++ BUG_ON(p->is_shared); ++ /* Check that 'redirect' is prepared to have us */ ++ BUG_ON(!redirect->config->public_cfg.is_shared); ++ /* These are the only elements to initialise when redirecting */ ++ p->irq_sources = 0; ++ p->sharing_redirect = redirect; ++ put_affine_portal(); ++ return p; ++#else ++ BUG(); ++ return NULL; ++#endif ++} ++ ++const struct qm_portal_config *qman_destroy_affine_portal(void) ++{ ++ /* We don't want to redirect if we're a slave, use "raw" */ ++ struct qman_portal *qm = get_raw_affine_portal(); ++ const struct qm_portal_config *pcfg; ++ int cpu; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (qm->sharing_redirect) { ++ qm->sharing_redirect = NULL; ++ put_affine_portal(); ++ return NULL; ++ } ++ qm->is_shared = 0; ++#endif ++ pcfg = qm->config; ++ cpu = pcfg->public_cfg.cpu; ++ /* NB we do this to "quiesce" EQCR. If we add enqueue-completions or ++ * something related to QM_PIRQ_EQCI, this may need fixing. ++ * Also, due to the prefetching model used for CI updates in the enqueue ++ * path, this update will only invalidate the CI cacheline *after* ++ * working on it, so we need to call this twice to ensure a full update ++ * irrespective of where the enqueue processing was at when the teardown ++ * began. */ ++ qm_eqcr_cce_update(&qm->p); ++ qm_eqcr_cce_update(&qm->p); ++ free_irq(pcfg->public_cfg.irq, qm); ++ kfree(qm->cgrs); ++ qm_isr_finish(&qm->p); ++ qm_mc_finish(&qm->p); ++ qm_mr_finish(&qm->p); ++ qm_dqrr_finish(&qm->p); ++ qm_eqcr_finish(&qm->p); ++ qm->config = NULL; ++ spin_lock(&affine_mask_lock); ++ cpumask_clear_cpu(cpu, &affine_mask); ++ spin_unlock(&affine_mask_lock); ++ put_affine_portal(); ++ return pcfg; ++} ++ ++const struct qman_portal_config *qman_get_portal_config(void) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ const struct qman_portal_config *ret = &p->config->public_cfg; ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_get_portal_config); ++ ++/* Inline helper to reduce nesting in __poll_portal_slow() */ ++static inline void fq_state_change(struct qman_portal *p, struct qman_fq *fq, ++ const struct qm_mr_entry *msg, u8 verb) ++{ ++ FQLOCK(fq); ++ switch(verb) { ++ case QM_MR_VERB_FQRL: ++ DPA_ASSERT(fq_isset(fq, QMAN_FQ_STATE_ORL)); ++ fq_clear(fq, QMAN_FQ_STATE_ORL); ++ table_del_fq(p, fq); ++ break; ++ case QM_MR_VERB_FQRN: ++ DPA_ASSERT((fq->state == qman_fq_state_parked) || ++ (fq->state == qman_fq_state_sched)); ++ DPA_ASSERT(fq_isset(fq, QMAN_FQ_STATE_CHANGING)); ++ fq_clear(fq, QMAN_FQ_STATE_CHANGING); ++ if (msg->fq.fqs & QM_MR_FQS_NOTEMPTY) ++ fq_set(fq, QMAN_FQ_STATE_NE); ++ if (msg->fq.fqs & QM_MR_FQS_ORLPRESENT) ++ fq_set(fq, QMAN_FQ_STATE_ORL); ++ else ++ table_del_fq(p, fq); ++ fq->state = qman_fq_state_retired; ++ break; ++ case QM_MR_VERB_FQPN: ++ DPA_ASSERT(fq->state == qman_fq_state_sched); ++ DPA_ASSERT(fq_isclear(fq, QMAN_FQ_STATE_CHANGING)); ++ fq->state = qman_fq_state_parked; ++ } ++ FQUNLOCK(fq); ++} ++ ++static u32 __poll_portal_slow(struct qman_portal *p, u32 is) ++{ ++ const struct qm_mr_entry *msg; ++ ++ if (is & QM_PIRQ_CSCI) { ++ struct qman_cgrs rr, c; ++ struct qm_mc_result *mcr; ++ struct qman_cgr *cgr; ++ int i; ++ unsigned long irqflags __maybe_unused; ++ ++ spin_lock_irqsave(&p->cgr_lock, irqflags); ++ /* The CSCI bit must be cleared _before_ issuing the ++ * Query Congestion State command, to ensure that a long ++ * CGR State Change callback cannot miss an intervening ++ * state change. */ ++ qm_isr_status_clear(&p->p, QM_PIRQ_CSCI); ++ ++ qm_mc_start(&p->p); ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCONGESTION); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ /* mask out the ones I'm not interested in */ ++ qman_cgrs_and(&rr, (const struct qman_cgrs *) ++ &mcr->querycongestion.state, &p->cgrs[0]); ++ /* check previous snapshot for delta, enter/exit congestion */ ++ qman_cgrs_xor(&c, &rr, &p->cgrs[1]); ++ /* update snapshot */ ++ qman_cgrs_cp(&p->cgrs[1], &rr); ++ /* Invoke callback */ ++ qman_cgrs_for_each_1(i, &c) ++ list_for_each_entry(cgr, &p->cgr_cbs[i], node) { ++ if (cgr->cb) ++ cgr->cb(p, cgr, qman_cgrs_get(&rr, i)); ++ } ++ spin_unlock_irqrestore(&p->cgr_lock, irqflags); ++ } ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (is & QM_PIRQ_EQCI) { ++ unsigned long irqflags; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ p->eqci_owned = NULL; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ wake_up(&affine_queue); ++ } ++#endif ++ ++ if (is & QM_PIRQ_EQRI) { ++ unsigned long irqflags __maybe_unused; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ qm_eqcr_cce_update(&p->p); ++ qm_eqcr_set_ithresh(&p->p, 0); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ wake_up(&affine_queue); ++ } ++ ++ if (is & QM_PIRQ_MRI) { ++ struct qman_fq *fq; ++ u8 verb, num = 0; ++mr_loop: ++ qm_mr_pvb_update(&p->p); ++ msg = qm_mr_current(&p->p); ++ if (!msg) ++ goto mr_done; ++ verb = msg->verb & QM_MR_VERB_TYPE_MASK; ++ /* The message is a software ERN iff the 0x20 bit is set */ ++ if (verb & 0x20) { ++ switch (verb) { ++ case QM_MR_VERB_FQRNI: ++ /* nada, we drop FQRNIs on the floor */ ++ break; ++ case QM_MR_VERB_FQRN: ++ case QM_MR_VERB_FQRL: ++ /* Lookup in the retirement table */ ++ fq = table_find_fq(p, msg->fq.fqid); ++ BUG_ON(!fq); ++ fq_state_change(p, fq, msg, verb); ++ if (fq->cb.fqs) ++ fq->cb.fqs(p, fq, msg); ++ break; ++ case QM_MR_VERB_FQPN: ++ /* Parked */ ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ fq = get_fq_table_entry(msg->fq.contextB); ++#else ++ fq = (void *)(uintptr_t)msg->fq.contextB; ++#endif ++ fq_state_change(p, fq, msg, verb); ++ if (fq->cb.fqs) ++ fq->cb.fqs(p, fq, msg); ++ break; ++ case QM_MR_VERB_DC_ERN: ++ /* DCP ERN */ ++ if (p->cb_dc_ern) ++ p->cb_dc_ern(p, msg); ++ else if (cb_dc_ern) ++ cb_dc_ern(p, msg); ++ else { ++ static int warn_once; ++ if (!warn_once) { ++ pr_crit("Leaking DCP ERNs!\n"); ++ warn_once = 1; ++ } ++ } ++ break; ++ default: ++ pr_crit("Invalid MR verb 0x%02x\n", verb); ++ } ++ } else { ++ /* Its a software ERN */ ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ fq = get_fq_table_entry(msg->ern.tag); ++#else ++ fq = (void *)(uintptr_t)msg->ern.tag; ++#endif ++ fq->cb.ern(p, fq, msg); ++ } ++ num++; ++ qm_mr_next(&p->p); ++ goto mr_loop; ++mr_done: ++ qm_mr_cci_consume(&p->p, num); ++ } ++ ++ /* QM_PIRQ_CSCI has already been cleared, as part of its specific ++ * processing. If that interrupt source has meanwhile been re-asserted, ++ * we mustn't clear it here (or in the top-level interrupt handler). */ ++ return is & (QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI); ++} ++ ++/* remove some slowish-path stuff from the "fast path" and make sure it isn't ++ * inlined. */ ++static noinline void clear_vdqcr(struct qman_portal *p, struct qman_fq *fq) ++{ ++ p->vdqcr_owned = NULL; ++ FQLOCK(fq); ++ fq_clear(fq, QMAN_FQ_STATE_VDQCR); ++ FQUNLOCK(fq); ++ wake_up(&affine_queue); ++} ++ ++/* Look: no locks, no irq_save()s, no preempt_disable()s! :-) The only states ++ * that would conflict with other things if they ran at the same time on the ++ * same cpu are; ++ * ++ * (i) setting/clearing vdqcr_owned, and ++ * (ii) clearing the NE (Not Empty) flag. ++ * ++ * Both are safe. Because; ++ * ++ * (i) this clearing can only occur after qman_volatile_dequeue() has set the ++ * vdqcr_owned field (which it does before setting VDQCR), and ++ * qman_volatile_dequeue() blocks interrupts and preemption while this is ++ * done so that we can't interfere. ++ * (ii) the NE flag is only cleared after qman_retire_fq() has set it, and as ++ * with (i) that API prevents us from interfering until it's safe. ++ * ++ * The good thing is that qman_volatile_dequeue() and qman_retire_fq() run far ++ * less frequently (ie. per-FQ) than __poll_portal_fast() does, so the nett ++ * advantage comes from this function not having to "lock" anything at all. ++ * ++ * Note also that the callbacks are invoked at points which are safe against the ++ * above potential conflicts, but that this function itself is not re-entrant ++ * (this is because the function tracks one end of each FIFO in the portal and ++ * we do *not* want to lock that). So the consequence is that it is safe for ++ * user callbacks to call into any Qman API *except* qman_poll() (as that's the ++ * sole API that could be invoking the callback through this function). ++ */ ++static inline unsigned int __poll_portal_fast(struct qman_portal *p, ++ unsigned int poll_limit) ++{ ++ const struct qm_dqrr_entry *dq; ++ struct qman_fq *fq; ++ enum qman_cb_dqrr_result res; ++ unsigned int limit = 0; ++ ++loop: ++ qm_dqrr_pvb_update(&p->p); ++ dq = qm_dqrr_current(&p->p); ++ if (!dq) ++ goto done; ++ if (dq->stat & QM_DQRR_STAT_UNSCHEDULED) { ++ /* VDQCR: don't trust contextB as the FQ may have been ++ * configured for h/w consumption and we're draining it ++ * post-retirement. */ ++ fq = p->vdqcr_owned; ++ /* We only set QMAN_FQ_STATE_NE when retiring, so we only need ++ * to check for clearing it when doing volatile dequeues. It's ++ * one less thing to check in the critical path (SDQCR). */ ++ if (dq->stat & QM_DQRR_STAT_FQ_EMPTY) ++ fq_clear(fq, QMAN_FQ_STATE_NE); ++ /* this is duplicated from the SDQCR code, but we have stuff to ++ * do before *and* after this callback, and we don't want ++ * multiple if()s in the critical path (SDQCR). */ ++ res = fq->cb.dqrr(p, fq, dq); ++ if (res == qman_cb_dqrr_stop) ++ goto done; ++ /* Check for VDQCR completion */ ++ if (dq->stat & QM_DQRR_STAT_DQCR_EXPIRED) ++ clear_vdqcr(p, fq); ++ } else { ++ /* SDQCR: contextB points to the FQ */ ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ fq = get_fq_table_entry(dq->contextB); ++#else ++ fq = (void *)(uintptr_t)dq->contextB; ++#endif ++ /* Now let the callback do its stuff */ ++ res = fq->cb.dqrr(p, fq, dq); ++ /* The callback can request that we exit without consuming this ++ * entry nor advancing; */ ++ if (res == qman_cb_dqrr_stop) ++ goto done; ++ } ++ /* Interpret 'dq' from a driver perspective. */ ++ /* Parking isn't possible unless HELDACTIVE was set. NB, ++ * FORCEELIGIBLE implies HELDACTIVE, so we only need to ++ * check for HELDACTIVE to cover both. */ ++ DPA_ASSERT((dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) || ++ (res != qman_cb_dqrr_park)); ++ /* Defer just means "skip it, I'll consume it myself later on" */ ++ if (res != qman_cb_dqrr_defer) ++ qm_dqrr_cdc_consume_1ptr(&p->p, dq, (res == qman_cb_dqrr_park)); ++ /* Move forward */ ++ qm_dqrr_next(&p->p); ++ /* Entry processed and consumed, increment our counter. The callback can ++ * request that we exit after consuming the entry, and we also exit if ++ * we reach our processing limit, so loop back only if neither of these ++ * conditions is met. */ ++ if ((++limit < poll_limit) && (res != qman_cb_dqrr_consume_stop)) ++ goto loop; ++done: ++ return limit; ++} ++ ++u32 qman_irqsource_get(void) ++{ ++ /* "irqsource" and "poll" APIs mustn't redirect when sharing, they ++ * should shut the user out if they are not the primary CPU hosting the ++ * portal. That's why we use the "raw" interface. */ ++ struct qman_portal *p = get_raw_affine_portal(); ++ u32 ret = p->irq_sources & QM_PIRQ_VISIBLE; ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_irqsource_get); ++ ++int qman_irqsource_add(u32 bits __maybe_unused) ++{ ++ struct qman_portal *p = get_raw_affine_portal(); ++ int ret = 0; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (p->sharing_redirect) ++ ret = -EINVAL; ++ else ++#endif ++ { ++ __maybe_unused unsigned long irqflags; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ set_bits(bits & QM_PIRQ_VISIBLE, &p->irq_sources); ++ qm_isr_enable_write(&p->p, p->irq_sources); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ } ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_irqsource_add); ++ ++int qman_irqsource_remove(u32 bits) ++{ ++ struct qman_portal *p = get_raw_affine_portal(); ++ __maybe_unused unsigned long irqflags; ++ u32 ier; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (p->sharing_redirect) { ++ put_affine_portal(); ++ return -EINVAL; ++ } ++#endif ++ /* Our interrupt handler only processes+clears status register bits that ++ * are in p->irq_sources. As we're trimming that mask, if one of them ++ * were to assert in the status register just before we remove it from ++ * the enable register, there would be an interrupt-storm when we ++ * release the IRQ lock. So we wait for the enable register update to ++ * take effect in h/w (by reading it back) and then clear all other bits ++ * in the status register. Ie. we clear them from ISR once it's certain ++ * IER won't allow them to reassert. */ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ bits &= QM_PIRQ_VISIBLE; ++ clear_bits(bits, &p->irq_sources); ++ qm_isr_enable_write(&p->p, p->irq_sources); ++ ier = qm_isr_enable_read(&p->p); ++ /* Using "~ier" (rather than "bits" or "~p->irq_sources") creates a ++ * data-dependency, ie. to protect against re-ordering. */ ++ qm_isr_status_clear(&p->p, ~ier); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return 0; ++} ++EXPORT_SYMBOL(qman_irqsource_remove); ++ ++const cpumask_t *qman_affine_cpus(void) ++{ ++ return &affine_mask; ++} ++EXPORT_SYMBOL(qman_affine_cpus); ++ ++u16 qman_affine_channel(int cpu) ++{ ++ if (cpu < 0) { ++ struct qman_portal *portal = get_raw_affine_portal(); ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ BUG_ON(portal->sharing_redirect); ++#endif ++ cpu = portal->config->public_cfg.cpu; ++ put_affine_portal(); ++ } ++ BUG_ON(!cpumask_test_cpu(cpu, &affine_mask)); ++ return affine_channels[cpu]; ++} ++EXPORT_SYMBOL(qman_affine_channel); ++ ++int qman_poll_dqrr(unsigned int limit) ++{ ++ struct qman_portal *p = get_poll_portal(); ++ int ret; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (unlikely(p->sharing_redirect)) ++ ret = -EINVAL; ++ else ++#endif ++ { ++ BUG_ON(p->irq_sources & QM_PIRQ_DQRI); ++ ret = __poll_portal_fast(p, limit); ++ } ++ put_poll_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_poll_dqrr); ++ ++u32 qman_poll_slow(void) ++{ ++ struct qman_portal *p = get_poll_portal(); ++ u32 ret; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (unlikely(p->sharing_redirect)) ++ ret = (u32)-1; ++ else ++#endif ++ { ++ u32 is = qm_isr_status_read(&p->p) & ~p->irq_sources; ++ ret = __poll_portal_slow(p, is); ++ qm_isr_status_clear(&p->p, ret); ++ } ++ put_poll_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_poll_slow); ++ ++/* Legacy wrapper */ ++void qman_poll(void) ++{ ++ struct qman_portal *p = get_poll_portal(); ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (unlikely(p->sharing_redirect)) ++ goto done; ++#endif ++ if ((~p->irq_sources) & QM_PIRQ_SLOW) { ++ if (!(p->slowpoll--)) { ++ u32 is = qm_isr_status_read(&p->p) & ~p->irq_sources; ++ u32 active = __poll_portal_slow(p, is); ++ if (active) { ++ qm_isr_status_clear(&p->p, active); ++ p->slowpoll = SLOW_POLL_BUSY; ++ } else ++ p->slowpoll = SLOW_POLL_IDLE; ++ } ++ } ++ if ((~p->irq_sources) & QM_PIRQ_DQRI) ++ __poll_portal_fast(p, CONFIG_FSL_QMAN_POLL_LIMIT); ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++done: ++#endif ++ put_poll_portal(); ++} ++EXPORT_SYMBOL(qman_poll); ++ ++void qman_stop_dequeues(void) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ qman_stop_dequeues_ex(p); ++ put_affine_portal(); ++} ++EXPORT_SYMBOL(qman_stop_dequeues); ++ ++void qman_start_dequeues(void) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ DPA_ASSERT(p->dqrr_disable_ref > 0); ++ if (!(--p->dqrr_disable_ref)) ++ qm_dqrr_set_maxfill(&p->p, DQRR_MAXFILL); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++} ++EXPORT_SYMBOL(qman_start_dequeues); ++ ++void qman_static_dequeue_add(u32 pools) ++{ ++ unsigned long irqflags __maybe_unused; ++ struct qman_portal *p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ pools &= p->config->public_cfg.pools; ++ p->sdqcr |= pools; ++ qm_dqrr_sdqcr_set(&p->p, p->sdqcr); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++} ++EXPORT_SYMBOL(qman_static_dequeue_add); ++ ++void qman_static_dequeue_del(u32 pools) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ pools &= p->config->public_cfg.pools; ++ p->sdqcr &= ~pools; ++ qm_dqrr_sdqcr_set(&p->p, p->sdqcr); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++} ++EXPORT_SYMBOL(qman_static_dequeue_del); ++ ++u32 qman_static_dequeue_get(void) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ u32 ret = p->sdqcr; ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_static_dequeue_get); ++ ++void qman_dca(struct qm_dqrr_entry *dq, int park_request) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ qm_dqrr_cdc_consume_1ptr(&p->p, dq, park_request); ++ put_affine_portal(); ++} ++EXPORT_SYMBOL(qman_dca); ++ ++/*******************/ ++/* Frame queue API */ ++/*******************/ ++ ++static const char *mcr_result_str(u8 result) ++{ ++ switch (result) { ++ case QM_MCR_RESULT_NULL: ++ return "QM_MCR_RESULT_NULL"; ++ case QM_MCR_RESULT_OK: ++ return "QM_MCR_RESULT_OK"; ++ case QM_MCR_RESULT_ERR_FQID: ++ return "QM_MCR_RESULT_ERR_FQID"; ++ case QM_MCR_RESULT_ERR_FQSTATE: ++ return "QM_MCR_RESULT_ERR_FQSTATE"; ++ case QM_MCR_RESULT_ERR_NOTEMPTY: ++ return "QM_MCR_RESULT_ERR_NOTEMPTY"; ++ case QM_MCR_RESULT_PENDING: ++ return "QM_MCR_RESULT_PENDING"; ++ case QM_MCR_RESULT_ERR_BADCOMMAND: ++ return "QM_MCR_RESULT_ERR_BADCOMMAND"; ++ } ++ return ""; ++} ++ ++int qman_create_fq(u32 fqid, u32 flags, struct qman_fq *fq) ++{ ++ struct qm_fqd fqd; ++ struct qm_mcr_queryfq_np np; ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ ++ if (flags & QMAN_FQ_FLAG_DYNAMIC_FQID) { ++ int ret = qman_alloc_fqid(&fqid); ++ if (ret) ++ return ret; ++ } ++ spin_lock_init(&fq->fqlock); ++ fq->fqid = fqid; ++ fq->flags = flags; ++ fq->state = qman_fq_state_oos; ++ fq->cgr_groupid = 0; ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ if (unlikely(find_empty_fq_table_entry(&fq->key, fq))) ++ return -ENOMEM; ++#endif ++ if (!(flags & QMAN_FQ_FLAG_AS_IS) || (flags & QMAN_FQ_FLAG_NO_MODIFY)) ++ return 0; ++ /* Everything else is AS_IS support */ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = qm_mc_start(&p->p); ++ mcc->queryfq.fqid = fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ); ++ if (mcr->result != QM_MCR_RESULT_OK) { ++ pr_err("QUERYFQ failed: %s\n", mcr_result_str(mcr->result)); ++ goto err; ++ } ++ fqd = mcr->queryfq.fqd; ++ mcc = qm_mc_start(&p->p); ++ mcc->queryfq_np.fqid = fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ_NP); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ_NP); ++ if (mcr->result != QM_MCR_RESULT_OK) { ++ pr_err("QUERYFQ_NP failed: %s\n", mcr_result_str(mcr->result)); ++ goto err; ++ } ++ np = mcr->queryfq_np; ++ /* Phew, have queryfq and queryfq_np results, stitch together ++ * the FQ object from those. */ ++ fq->cgr_groupid = fqd.cgid; ++ switch (np.state & QM_MCR_NP_STATE_MASK) { ++ case QM_MCR_NP_STATE_OOS: ++ break; ++ case QM_MCR_NP_STATE_RETIRED: ++ fq->state = qman_fq_state_retired; ++ if (np.frm_cnt) ++ fq_set(fq, QMAN_FQ_STATE_NE); ++ break; ++ case QM_MCR_NP_STATE_TEN_SCHED: ++ case QM_MCR_NP_STATE_TRU_SCHED: ++ case QM_MCR_NP_STATE_ACTIVE: ++ fq->state = qman_fq_state_sched; ++ if (np.state & QM_MCR_NP_STATE_R) ++ fq_set(fq, QMAN_FQ_STATE_CHANGING); ++ break; ++ case QM_MCR_NP_STATE_PARKED: ++ fq->state = qman_fq_state_parked; ++ break; ++ default: ++ DPA_ASSERT(NULL == "invalid FQ state"); ++ } ++ if (fqd.fq_ctrl & QM_FQCTRL_CGE) ++ fq->state |= QMAN_FQ_STATE_CGR_EN; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return 0; ++err: ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (flags & QMAN_FQ_FLAG_DYNAMIC_FQID) ++ qman_release_fqid(fqid); ++ return -EIO; ++} ++EXPORT_SYMBOL(qman_create_fq); ++ ++void qman_destroy_fq(struct qman_fq *fq, u32 flags __maybe_unused) ++{ ++ /* We don't need to lock the FQ as it is a pre-condition that the FQ be ++ * quiesced. Instead, run some checks. */ ++ switch (fq->state) { ++ case qman_fq_state_parked: ++ DPA_ASSERT(flags & QMAN_FQ_DESTROY_PARKED); ++ case qman_fq_state_oos: ++ if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID)) ++ qman_release_fqid(fq->fqid); ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ clear_fq_table_entry(fq->key); ++#endif ++ return; ++ default: ++ break; ++ } ++ DPA_ASSERT(NULL == "qman_free_fq() on unquiesced FQ!"); ++} ++EXPORT_SYMBOL(qman_destroy_fq); ++ ++u32 qman_fq_fqid(struct qman_fq *fq) ++{ ++ return fq->fqid; ++} ++EXPORT_SYMBOL(qman_fq_fqid); ++ ++void qman_fq_state(struct qman_fq *fq, enum qman_fq_state *state, u32 *flags) ++{ ++ if (state) ++ *state = fq->state; ++ if (flags) ++ *flags = fq->flags; ++} ++EXPORT_SYMBOL(qman_fq_state); ++ ++int qman_init_fq(struct qman_fq *fq, u32 flags, struct qm_mcc_initfq *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res, myverb = (flags & QMAN_INITFQ_FLAG_SCHED) ? ++ QM_MCC_VERB_INITFQ_SCHED : QM_MCC_VERB_INITFQ_PARKED; ++ ++ if ((fq->state != qman_fq_state_oos) && ++ (fq->state != qman_fq_state_parked)) ++ return -EINVAL; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY))) ++ return -EINVAL; ++#endif ++ if (opts && (opts->we_mask & QM_INITFQ_WE_OAC)) { ++ /* OAC not supported on rev1.0 */ ++ if (unlikely(qman_ip_rev == QMAN_REV10)) ++ return -EINVAL; ++ /* And can't be set at the same time as TDTHRESH */ ++ if (opts->we_mask & QM_INITFQ_WE_TDTHRESH) ++ return -EINVAL; ++ } ++ /* Issue an INITFQ_[PARKED|SCHED] management command */ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ FQLOCK(fq); ++ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_CHANGING)) || ++ ((fq->state != qman_fq_state_oos) && ++ (fq->state != qman_fq_state_parked)))) { ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return -EBUSY; ++ } ++ mcc = qm_mc_start(&p->p); ++ if (opts) ++ mcc->initfq = *opts; ++ mcc->initfq.fqid = fq->fqid; ++ mcc->initfq.count = 0; ++ /* If the FQ does *not* have the TO_DCPORTAL flag, contextB is set as a ++ * demux pointer. Otherwise, the caller-provided value is allowed to ++ * stand, don't overwrite it. */ ++ if (fq_isclear(fq, QMAN_FQ_FLAG_TO_DCPORTAL)) { ++ dma_addr_t phys_fq; ++ mcc->initfq.we_mask |= QM_INITFQ_WE_CONTEXTB; ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ mcc->initfq.fqd.context_b = fq->key; ++#else ++ mcc->initfq.fqd.context_b = (u32)(uintptr_t)fq; ++#endif ++ /* and the physical address - NB, if the user wasn't trying to ++ * set CONTEXTA, clear the stashing settings. */ ++ if (!(mcc->initfq.we_mask & QM_INITFQ_WE_CONTEXTA)) { ++ mcc->initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; ++ memset(&mcc->initfq.fqd.context_a, 0, ++ sizeof(mcc->initfq.fqd.context_a)); ++ } else { ++ phys_fq = dma_map_single(&p->pdev->dev, fq, sizeof(*fq), ++ DMA_TO_DEVICE); ++ qm_fqd_stashing_set64(&mcc->initfq.fqd, phys_fq); ++ } ++ } ++ if (flags & QMAN_INITFQ_FLAG_LOCAL) { ++ mcc->initfq.fqd.dest.channel = p->config->public_cfg.channel; ++ if (!(mcc->initfq.we_mask & QM_INITFQ_WE_DESTWQ)) { ++ mcc->initfq.we_mask |= QM_INITFQ_WE_DESTWQ; ++ mcc->initfq.fqd.dest.wq = 4; ++ } ++ } ++ qm_mc_commit(&p->p, myverb); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == myverb); ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return -EIO; ++ } ++ if (opts) { ++ if (opts->we_mask & QM_INITFQ_WE_FQCTRL) { ++ if (opts->fqd.fq_ctrl & QM_FQCTRL_CGE) ++ fq_set(fq, QMAN_FQ_STATE_CGR_EN); ++ else ++ fq_clear(fq, QMAN_FQ_STATE_CGR_EN); ++ } ++ if (opts->we_mask & QM_INITFQ_WE_CGID) ++ fq->cgr_groupid = opts->fqd.cgid; ++ } ++ fq->state = (flags & QMAN_INITFQ_FLAG_SCHED) ? ++ qman_fq_state_sched : qman_fq_state_parked; ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return 0; ++} ++EXPORT_SYMBOL(qman_init_fq); ++ ++int qman_schedule_fq(struct qman_fq *fq) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ int ret = 0; ++ u8 res; ++ ++ if (fq->state != qman_fq_state_parked) ++ return -EINVAL; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY))) ++ return -EINVAL; ++#endif ++ /* Issue a ALTERFQ_SCHED management command */ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ FQLOCK(fq); ++ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_CHANGING)) || ++ (fq->state != qman_fq_state_parked))) { ++ ret = -EBUSY; ++ goto out; ++ } ++ mcc = qm_mc_start(&p->p); ++ mcc->alterfq.fqid = fq->fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_SCHED); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_SCHED); ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ ret = -EIO; ++ goto out; ++ } ++ fq->state = qman_fq_state_sched; ++out: ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_schedule_fq); ++ ++int qman_retire_fq(struct qman_fq *fq, u32 *flags) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ int rval; ++ u8 res; ++ ++ if ((fq->state != qman_fq_state_parked) && ++ (fq->state != qman_fq_state_sched)) ++ return -EINVAL; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY))) ++ return -EINVAL; ++#endif ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ FQLOCK(fq); ++ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_CHANGING)) || ++ (fq->state == qman_fq_state_retired) || ++ (fq->state == qman_fq_state_oos))) { ++ rval = -EBUSY; ++ goto out; ++ } ++ rval = table_push_fq(p, fq); ++ if (rval) ++ goto out; ++ mcc = qm_mc_start(&p->p); ++ mcc->alterfq.fqid = fq->fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_RETIRE); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_RETIRE); ++ res = mcr->result; ++ /* "Elegant" would be to treat OK/PENDING the same way; set CHANGING, ++ * and defer the flags until FQRNI or FQRN (respectively) show up. But ++ * "Friendly" is to process OK immediately, and not set CHANGING. We do ++ * friendly, otherwise the caller doesn't necessarily have a fully ++ * "retired" FQ on return even if the retirement was immediate. However ++ * this does mean some code duplication between here and ++ * fq_state_change(). */ ++ if (likely(res == QM_MCR_RESULT_OK)) { ++ rval = 0; ++ /* Process 'fq' right away, we'll ignore FQRNI */ ++ if (mcr->alterfq.fqs & QM_MCR_FQS_NOTEMPTY) ++ fq_set(fq, QMAN_FQ_STATE_NE); ++ if (mcr->alterfq.fqs & QM_MCR_FQS_ORLPRESENT) ++ fq_set(fq, QMAN_FQ_STATE_ORL); ++ else ++ table_del_fq(p, fq); ++ if (flags) ++ *flags = fq->flags; ++ fq->state = qman_fq_state_retired; ++ if (fq->cb.fqs) { ++ /* Another issue with supporting "immediate" retirement ++ * is that we're forced to drop FQRNIs, because by the ++ * time they're seen it may already be "too late" (the ++ * fq may have been OOS'd and free()'d already). But if ++ * the upper layer wants a callback whether it's ++ * immediate or not, we have to fake a "MR" entry to ++ * look like an FQRNI... */ ++ struct qm_mr_entry msg; ++ msg.verb = QM_MR_VERB_FQRNI; ++ msg.fq.fqs = mcr->alterfq.fqs; ++ msg.fq.fqid = fq->fqid; ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ msg.fq.contextB = fq->key; ++#else ++ msg.fq.contextB = (u32)(uintptr_t)fq; ++#endif ++ fq->cb.fqs(p, fq, &msg); ++ } ++ } else if (res == QM_MCR_RESULT_PENDING) { ++ rval = 1; ++ fq_set(fq, QMAN_FQ_STATE_CHANGING); ++ } else { ++ rval = -EIO; ++ table_del_fq(p, fq); ++ } ++out: ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return rval; ++} ++EXPORT_SYMBOL(qman_retire_fq); ++ ++int qman_oos_fq(struct qman_fq *fq) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ int ret = 0; ++ u8 res; ++ ++ if (fq->state != qman_fq_state_retired) ++ return -EINVAL; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY))) ++ return -EINVAL; ++#endif ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ FQLOCK(fq); ++ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_BLOCKOOS)) || ++ (fq->state != qman_fq_state_retired))) { ++ ret = -EBUSY; ++ goto out; ++ } ++ mcc = qm_mc_start(&p->p); ++ mcc->alterfq.fqid = fq->fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_OOS); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_OOS); ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ ret = -EIO; ++ goto out; ++ } ++ fq->state = qman_fq_state_oos; ++out: ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_oos_fq); ++ ++int qman_fq_flow_control(struct qman_fq *fq, int xon) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ int ret = 0; ++ u8 res; ++ u8 myverb; ++ ++ if ((fq->state == qman_fq_state_oos) || ++ (fq->state == qman_fq_state_retired) || ++ (fq->state == qman_fq_state_parked)) ++ return -EINVAL; ++ ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY))) ++ return -EINVAL; ++#endif ++ /* Issue a ALTER_FQXON or ALTER_FQXOFF management command */ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ FQLOCK(fq); ++ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_CHANGING)) || ++ (fq->state == qman_fq_state_parked) || ++ (fq->state == qman_fq_state_oos) || ++ (fq->state == qman_fq_state_retired))) { ++ ret = -EBUSY; ++ goto out; ++ } ++ mcc = qm_mc_start(&p->p); ++ mcc->alterfq.fqid = fq->fqid; ++ mcc->alterfq.count = 0; ++ myverb = xon ? QM_MCC_VERB_ALTER_FQXON : QM_MCC_VERB_ALTER_FQXOFF; ++ ++ qm_mc_commit(&p->p, myverb); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == myverb); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ ret = -EIO; ++ goto out; ++ } ++out: ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_fq_flow_control); ++ ++int qman_query_fq(struct qman_fq *fq, struct qm_fqd *fqd) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = qm_mc_start(&p->p); ++ mcc->queryfq.fqid = fq->fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *fqd = mcr->queryfq.fqd; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) ++ return -EIO; ++ return 0; ++} ++EXPORT_SYMBOL(qman_query_fq); ++ ++int qman_query_fq_np(struct qman_fq *fq, struct qm_mcr_queryfq_np *np) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = qm_mc_start(&p->p); ++ mcc->queryfq.fqid = fq->fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ_NP); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ_NP); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *np = mcr->queryfq_np; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) ++ return -EIO; ++ return 0; ++} ++EXPORT_SYMBOL(qman_query_fq_np); ++ ++int qman_query_wq(u8 query_dedicated, struct qm_mcr_querywq *wq) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res, myverb; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ myverb = (query_dedicated) ? QM_MCR_VERB_QUERYWQ_DEDICATED : ++ QM_MCR_VERB_QUERYWQ; ++ mcc = qm_mc_start(&p->p); ++ mcc->querywq.channel.id = wq->channel.id; ++ qm_mc_commit(&p->p, myverb); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == myverb); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *wq = mcr->querywq; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("QUERYWQ failed: %s\n", mcr_result_str(res)); ++ return -EIO; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_query_wq); ++ ++int qman_testwrite_cgr(struct qman_cgr *cgr, u64 i_bcnt, ++ struct qm_mcr_cgrtestwrite *result) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = qm_mc_start(&p->p); ++ mcc->cgrtestwrite.cgid = cgr->cgrid; ++ mcc->cgrtestwrite.i_bcnt_hi = (u8)(i_bcnt >> 32); ++ mcc->cgrtestwrite.i_bcnt_lo = (u32)i_bcnt; ++ qm_mc_commit(&p->p, QM_MCC_VERB_CGRTESTWRITE); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_CGRTESTWRITE); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *result = mcr->cgrtestwrite; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CGR TEST WRITE failed: %s\n", mcr_result_str(res)); ++ return -EIO; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_testwrite_cgr); ++ ++int qman_query_cgr(struct qman_cgr *cgr, struct qm_mcr_querycgr *cgrd) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = qm_mc_start(&p->p); ++ mcc->querycgr.cgid = cgr->cgrid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCGR); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *cgrd = mcr->querycgr; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("QUERY_CGR failed: %s\n", mcr_result_str(res)); ++ return -EIO; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_query_cgr); ++ ++int qman_query_congestion(struct qm_mcr_querycongestion *congestion) ++{ ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ qm_mc_start(&p->p); ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCONGESTION); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_MCC_VERB_QUERYCONGESTION); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *congestion = mcr->querycongestion; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("QUERY_CONGESTION failed: %s\n", mcr_result_str(res)); ++ return -EIO; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_query_congestion); ++ ++/* internal function used as a wait_event() expression */ ++static int set_vdqcr(struct qman_portal **p, struct qman_fq *fq, u32 vdqcr) ++{ ++ unsigned long irqflags __maybe_unused; ++ int ret = -EBUSY; ++ *p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(*p, irqflags); ++ if (!(*p)->vdqcr_owned) { ++ FQLOCK(fq); ++ if (fq_isset(fq, QMAN_FQ_STATE_VDQCR)) ++ goto escape; ++ fq_set(fq, QMAN_FQ_STATE_VDQCR); ++ FQUNLOCK(fq); ++ (*p)->vdqcr_owned = fq; ++ ret = 0; ++ } ++escape: ++ PORTAL_IRQ_UNLOCK(*p, irqflags); ++ if (!ret) ++ qm_dqrr_vdqcr_set(&(*p)->p, vdqcr); ++ put_affine_portal(); ++ return ret; ++} ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++static int wait_vdqcr_start(struct qman_portal **p, struct qman_fq *fq, ++ u32 vdqcr, u32 flags) ++{ ++ int ret = 0; ++ if (flags & QMAN_VOLATILE_FLAG_WAIT_INT) ++ ret = wait_event_interruptible(affine_queue, ++ !(ret = set_vdqcr(p, fq, vdqcr))); ++ else ++ wait_event(affine_queue, !(ret = set_vdqcr(p, fq, vdqcr))); ++ return ret; ++} ++#endif ++ ++int qman_volatile_dequeue(struct qman_fq *fq, u32 flags __maybe_unused, ++ u32 vdqcr) ++{ ++ struct qman_portal *p; ++ int ret; ++ ++ if ((fq->state != qman_fq_state_parked) && ++ (fq->state != qman_fq_state_retired)) ++ return -EINVAL; ++ if (vdqcr & QM_VDQCR_FQID_MASK) ++ return -EINVAL; ++ if (fq_isset(fq, QMAN_FQ_STATE_VDQCR)) ++ return -EBUSY; ++ vdqcr = (vdqcr & ~QM_VDQCR_FQID_MASK) | fq->fqid; ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_VOLATILE_FLAG_WAIT) ++ ret = wait_vdqcr_start(&p, fq, vdqcr, flags); ++ else ++#endif ++ ret = set_vdqcr(&p, fq, vdqcr); ++ if (ret) ++ return ret; ++ /* VDQCR is set */ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_VOLATILE_FLAG_FINISH) { ++ if (flags & QMAN_VOLATILE_FLAG_WAIT_INT) ++ /* NB: don't propagate any error - the caller wouldn't ++ * know whether the VDQCR was issued or not. A signal ++ * could arrive after returning anyway, so the caller ++ * can check signal_pending() if that's an issue. */ ++ wait_event_interruptible(affine_queue, ++ !fq_isset(fq, QMAN_FQ_STATE_VDQCR)); ++ else ++ wait_event(affine_queue, ++ !fq_isset(fq, QMAN_FQ_STATE_VDQCR)); ++ } ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_volatile_dequeue); ++ ++static noinline void update_eqcr_ci(struct qman_portal *p, u8 avail) ++{ ++ if (avail) ++ qm_eqcr_cce_prefetch(&p->p); ++ else ++ qm_eqcr_cce_update(&p->p); ++} ++ ++int qman_eqcr_is_empty(void) ++{ ++ unsigned long irqflags __maybe_unused; ++ struct qman_portal *p = get_affine_portal(); ++ u8 avail; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ update_eqcr_ci(p, 0); ++ avail = qm_eqcr_get_fill(&p->p); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return (avail == 0); ++} ++EXPORT_SYMBOL(qman_eqcr_is_empty); ++ ++void qman_set_dc_ern(qman_cb_dc_ern handler, int affine) ++{ ++ if (affine) { ++ unsigned long irqflags __maybe_unused; ++ struct qman_portal *p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ p->cb_dc_ern = handler; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ } else ++ cb_dc_ern = handler; ++} ++EXPORT_SYMBOL(qman_set_dc_ern); ++ ++static inline struct qm_eqcr_entry *try_eq_start(struct qman_portal **p, ++ unsigned long *irqflags __maybe_unused, ++ struct qman_fq *fq, ++ const struct qm_fd *fd, ++ u32 flags) ++{ ++ struct qm_eqcr_entry *eq; ++ u8 avail; ++ ++ *p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(*p, (*irqflags)); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && ++ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) { ++ if ((*p)->eqci_owned) { ++ PORTAL_IRQ_UNLOCK(*p, (*irqflags)); ++ put_affine_portal(); ++ return NULL; ++ } ++ (*p)->eqci_owned = fq; ++ } ++#endif ++ avail = qm_eqcr_get_avail(&(*p)->p); ++ if (avail < 2) ++ update_eqcr_ci(*p, avail); ++ eq = qm_eqcr_start(&(*p)->p); ++ if (unlikely(!eq)) { ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && ++ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) ++ (*p)->eqci_owned = NULL; ++#endif ++ PORTAL_IRQ_UNLOCK(*p, (*irqflags)); ++ put_affine_portal(); ++ return NULL; ++ } ++ if (flags & QMAN_ENQUEUE_FLAG_DCA) ++ eq->dca = QM_EQCR_DCA_ENABLE | ++ ((flags & QMAN_ENQUEUE_FLAG_DCA_PARK) ? ++ QM_EQCR_DCA_PARK : 0) | ++ ((flags >> 8) & QM_EQCR_DCA_IDXMASK); ++ eq->fqid = fq->fqid; ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ eq->tag = fq->key; ++#else ++ eq->tag = (u32)(uintptr_t)fq; ++#endif ++ /* From p4080 rev1 -> rev2, the FD struct's address went from 48-bit to ++ * 40-bit but rev1 chips will still interpret it as 48-bit, meaning we ++ * have to scrub the upper 8-bits, just in case the user left noise in ++ * there. Doing this selectively via a run-time check of the h/w ++ * revision (as we do for most errata, for example) is too slow in this ++ * critical path code. The most inexpensive way to handle this is just ++ * to reinterpret the FD as 4 32-bit words and to mask the first word ++ * appropriately, irrespecitive of the h/w revision. The struct fields ++ * corresponding to this word are; ++ * u8 dd:2; ++ * u8 liodn_offset:6; ++ * u8 bpid; ++ * u8 eliodn_offset:4; ++ * u8 __reserved:4; ++ * u8 addr_hi; ++ * So we mask this word with 0xc0ff00ff, which implicitly scrubs out ++ * liodn_offset, eliodn_offset, and __reserved - the latter two fields ++ * are interpreted as the 8 msbits of the 48-bit address in the case of ++ * rev1. ++ */ ++ { ++ const u32 *src = (const u32 *)fd; ++ u32 *dest = (u32 *)&eq->fd; ++ dest[0] = src[0] & 0xc0ff00ff; ++ dest[1] = src[1]; ++ dest[2] = src[2]; ++ dest[3] = src[3]; ++ } ++ return eq; ++} ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++static noinline struct qm_eqcr_entry *__wait_eq_start(struct qman_portal **p, ++ unsigned long *irqflags __maybe_unused, ++ struct qman_fq *fq, ++ const struct qm_fd *fd, ++ u32 flags) ++{ ++ struct qm_eqcr_entry *eq = try_eq_start(p, irqflags, fq, fd, flags); ++ if (!eq) ++ qm_eqcr_set_ithresh(&(*p)->p, EQCR_ITHRESH); ++ return eq; ++} ++static noinline struct qm_eqcr_entry *wait_eq_start(struct qman_portal **p, ++ unsigned long *irqflags __maybe_unused, ++ struct qman_fq *fq, ++ const struct qm_fd *fd, ++ u32 flags) ++{ ++ struct qm_eqcr_entry *eq; ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT) ++ wait_event_interruptible(affine_queue, ++ (eq = __wait_eq_start(p, irqflags, fq, fd, flags))); ++ else ++ wait_event(affine_queue, ++ (eq = __wait_eq_start(p, irqflags, fq, fd, flags))); ++ return eq; ++} ++#endif ++ ++int qman_enqueue(struct qman_fq *fq, const struct qm_fd *fd, u32 flags) ++{ ++ struct qman_portal *p; ++ struct qm_eqcr_entry *eq; ++ unsigned long irqflags __maybe_unused; ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT) ++ eq = wait_eq_start(&p, &irqflags, fq, fd, flags); ++ else ++#endif ++ eq = try_eq_start(&p, &irqflags, fq, fd, flags); ++ if (!eq) ++ return -EBUSY; ++ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */ ++ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_CMD_ENQUEUE | ++ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))); ++ /* Factor the below out, it's used from qman_enqueue_orp() too */ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && ++ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) { ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT) ++ wait_event_interruptible(affine_queue, ++ (p->eqci_owned != fq)); ++ else ++ wait_event(affine_queue, (p->eqci_owned != fq)); ++ } ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_enqueue); ++ ++int qman_enqueue_orp(struct qman_fq *fq, const struct qm_fd *fd, u32 flags, ++ struct qman_fq *orp, u16 orp_seqnum) ++{ ++ struct qman_portal *p; ++ struct qm_eqcr_entry *eq; ++ unsigned long irqflags __maybe_unused; ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT) ++ eq = wait_eq_start(&p, &irqflags, fq, fd, flags); ++ else ++#endif ++ eq = try_eq_start(&p, &irqflags, fq, fd, flags); ++ if (!eq) ++ return -EBUSY; ++ /* Process ORP-specifics here */ ++ if (flags & QMAN_ENQUEUE_FLAG_NLIS) ++ orp_seqnum |= QM_EQCR_SEQNUM_NLIS; ++ else { ++ orp_seqnum &= ~QM_EQCR_SEQNUM_NLIS; ++ if (flags & QMAN_ENQUEUE_FLAG_NESN) ++ orp_seqnum |= QM_EQCR_SEQNUM_NESN; ++ else ++ /* No need to check 4 QMAN_ENQUEUE_FLAG_HOLE */ ++ orp_seqnum &= ~QM_EQCR_SEQNUM_NESN; ++ } ++ eq->seqnum = orp_seqnum; ++ eq->orp = orp->fqid; ++ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */ ++ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_ORP | ++ ((flags & (QMAN_ENQUEUE_FLAG_HOLE | QMAN_ENQUEUE_FLAG_NESN)) ? ++ 0 : QM_EQCR_VERB_CMD_ENQUEUE) | ++ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && ++ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) { ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT) ++ wait_event_interruptible(affine_queue, ++ (p->eqci_owned != fq)); ++ else ++ wait_event(affine_queue, (p->eqci_owned != fq)); ++ } ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_enqueue_orp); ++ ++int qman_modify_cgr(struct qman_cgr *cgr, u32 flags, ++ struct qm_mcc_initcgr *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ u8 verb = QM_MCC_VERB_MODIFYCGR; ++ ++ /* frame mode not supported on rev1.0 */ ++ if (unlikely(qman_ip_rev == QMAN_REV10)) { ++ if (opts && (opts->we_mask & QM_CGR_WE_MODE) && ++ opts->cgr.mode == QMAN_CGR_MODE_FRAME) { ++ put_affine_portal(); ++ return -EIO; ++ } ++ } ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = qm_mc_start(&p->p); ++ if (opts) ++ mcc->initcgr = *opts; ++ mcc->initcgr.cgid = cgr->cgrid; ++ if (flags & QMAN_CGR_FLAG_USE_INIT) ++ verb = QM_MCC_VERB_INITCGR; ++ qm_mc_commit(&p->p, verb); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == verb); ++ res = mcr->result; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return (res == QM_MCR_RESULT_OK) ? 0 : -EIO; ++} ++EXPORT_SYMBOL(qman_modify_cgr); ++ ++#define TARG_MASK(n) (0x80000000 >> (n->config->public_cfg.channel - \ ++ QM_CHANNEL_SWPORTAL0)) ++#define PORTAL_IDX(n) (n->config->public_cfg.channel - QM_CHANNEL_SWPORTAL0) ++ ++int qman_create_cgr(struct qman_cgr *cgr, u32 flags, ++ struct qm_mcc_initcgr *opts) ++{ ++ unsigned long irqflags __maybe_unused; ++ struct qm_mcr_querycgr cgr_state; ++ struct qm_mcc_initcgr local_opts; ++ int ret; ++ struct qman_portal *p; ++ ++ /* We have to check that the provided CGRID is within the limits of the ++ * data-structures, for obvious reasons. However we'll let h/w take ++ * care of determining whether it's within the limits of what exists on ++ * the SoC. */ ++ if (cgr->cgrid >= __CGR_NUM) ++ return -EINVAL; ++ ++ p = get_affine_portal(); ++ ++ memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr)); ++ cgr->chan = p->config->public_cfg.channel; ++ spin_lock_irqsave(&p->cgr_lock, irqflags); ++ ++ /* if no opts specified and I'm not the first for this portal, just add ++ * to the list */ ++ if ((opts == NULL) && !list_empty(&p->cgr_cbs[cgr->cgrid])) ++ goto add_list; ++ ++ ret = qman_query_cgr(cgr, &cgr_state); ++ if (ret) ++ goto release_lock; ++ if (opts) ++ local_opts = *opts; ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) ++ local_opts.cgr.cscn_targ_upd_ctrl = ++ QM_CGR_TARG_UDP_CTRL_WRITE_BIT | PORTAL_IDX(p); ++ else ++ /* Overwrite TARG */ ++ local_opts.cgr.cscn_targ = cgr_state.cgr.cscn_targ | ++ TARG_MASK(p); ++ local_opts.we_mask |= QM_CGR_WE_CSCN_TARG; ++ ++ /* send init if flags indicate so */ ++ if (opts && (flags & QMAN_CGR_FLAG_USE_INIT)) ++ ret = qman_modify_cgr(cgr, QMAN_CGR_FLAG_USE_INIT, &local_opts); ++ else ++ ret = qman_modify_cgr(cgr, 0, &local_opts); ++ if (ret) ++ goto release_lock; ++add_list: ++ list_add(&cgr->node, &p->cgr_cbs[cgr->cgrid]); ++ ++ /* Determine if newly added object requires its callback to be called */ ++ ret = qman_query_cgr(cgr, &cgr_state); ++ if (ret) { ++ /* we can't go back, so proceed and return success, but screen ++ * and wail to the log file */ ++ pr_crit("CGR HW state partially modified\n"); ++ ret = 0; ++ goto release_lock; ++ } ++ if (cgr->cb && cgr_state.cgr.cscn_en && qman_cgrs_get(&p->cgrs[1], ++ cgr->cgrid)) ++ cgr->cb(p, cgr, 1); ++release_lock: ++ spin_unlock_irqrestore(&p->cgr_lock, irqflags); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_create_cgr); ++ ++int qman_create_cgr_to_dcp(struct qman_cgr *cgr, u32 flags, u16 dcp_portal, ++ struct qm_mcc_initcgr *opts) ++{ ++ unsigned long irqflags __maybe_unused; ++ struct qm_mcc_initcgr local_opts; ++ int ret; ++ ++ if ((qman_ip_rev & 0xFF00) < QMAN_REV30) { ++ pr_warning("This QMan version doesn't support to send CSCN to" ++ " DCP portal\n"); ++ return -EINVAL; ++ } ++ /* We have to check that the provided CGRID is within the limits of the ++ * data-structures, for obvious reasons. However we'll let h/w take ++ * care of determining whether it's within the limits of what exists on ++ * the SoC. ++ */ ++ if (cgr->cgrid >= __CGR_NUM) ++ return -EINVAL; ++ ++ memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr)); ++ if (opts) ++ local_opts = *opts; ++ ++ local_opts.cgr.cscn_targ_upd_ctrl = QM_CGR_TARG_UDP_CTRL_WRITE_BIT | ++ QM_CGR_TARG_UDP_CTRL_DCP | dcp_portal; ++ local_opts.we_mask |= QM_CGR_WE_CSCN_TARG; ++ ++ /* send init if flags indicate so */ ++ if (opts && (flags & QMAN_CGR_FLAG_USE_INIT)) ++ ret = qman_modify_cgr(cgr, QMAN_CGR_FLAG_USE_INIT, ++ &local_opts); ++ else ++ ret = qman_modify_cgr(cgr, 0, &local_opts); ++ ++ return ret; ++} ++EXPORT_SYMBOL(qman_create_cgr_to_dcp); ++ ++int qman_delete_cgr(struct qman_cgr *cgr) ++{ ++ unsigned long irqflags __maybe_unused; ++ struct qm_mcr_querycgr cgr_state; ++ struct qm_mcc_initcgr local_opts; ++ int ret = 0; ++ struct qman_portal *p = get_affine_portal(); ++ ++ if (cgr->chan != p->config->public_cfg.channel) { ++ pr_crit("Attempting to delete cgr from different portal " ++ "than it was create: create 0x%x, delete 0x%x\n", ++ cgr->chan, p->config->public_cfg.channel); ++ ret = -EINVAL; ++ goto put_portal; ++ } ++ memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr)); ++ spin_lock_irqsave(&p->cgr_lock, irqflags); ++ list_del(&cgr->node); ++ /* If last in list, CSCN_TARG must be set accordingly */ ++ if (!list_empty(&p->cgr_cbs[cgr->cgrid])) ++ goto release_lock; ++ ret = qman_query_cgr(cgr, &cgr_state); ++ if (ret) { ++ /* add back to the list */ ++ list_add(&cgr->node, &p->cgr_cbs[cgr->cgrid]); ++ goto release_lock; ++ } ++ /* Overwrite TARG */ ++ local_opts.we_mask = QM_CGR_WE_CSCN_TARG; ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) ++ local_opts.cgr.cscn_targ_upd_ctrl = ++ ~QM_CGR_TARG_UDP_CTRL_WRITE_BIT | PORTAL_IDX(p); ++ else ++ local_opts.cgr.cscn_targ = cgr_state.cgr.cscn_targ & ++ ~(TARG_MASK(p)); ++ ret = qman_modify_cgr(cgr, 0, &local_opts); ++ if (ret) ++ /* add back to the list */ ++ list_add(&cgr->node, &p->cgr_cbs[cgr->cgrid]); ++release_lock: ++ spin_unlock_irqrestore(&p->cgr_lock, irqflags); ++put_portal: ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_delete_cgr); ++ ++int qm_get_clock(u64 *clock_hz) ++{ ++ if (!qman_clk) { ++ pr_warning("Qman clock speed is unknown\n"); ++ return -EINVAL; ++ } ++ *clock_hz = (u64)qman_clk; ++ return 0; ++} ++EXPORT_SYMBOL(qm_get_clock); ++ ++int qm_set_clock(u64 clock_hz) ++{ ++ if (qman_clk) ++ return -1; ++ qman_clk = (u32)clock_hz; ++ return 0; ++} ++EXPORT_SYMBOL(qm_set_clock); ++ ++/* CEETM management command */ ++int qman_ceetm_configure_lfqmt(struct qm_mcc_ceetm_lfqmt_config *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->lfqmt_config = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_LFQMT_CONFIG); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_LFQMT_CONFIG); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CONFIGURE LFQMT failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++int qman_ceetm_query_lfqmt(int lfqid, ++ struct qm_mcr_ceetm_lfqmt_query *lfqmt_query) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->lfqmt_query.lfqid = lfqid; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_LFQMT_QUERY); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_LFQMT_QUERY); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *lfqmt_query = mcr->lfqmt_query; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: QUERY LFQMT failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++int qman_ceetm_configure_cq(struct qm_mcc_ceetm_cq_config *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->cq_config = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CQ_CONFIG); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ res = mcr->result; ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_CQ_CONFIG); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CONFIGURE CQ failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++int qman_ceetm_query_cq(unsigned int cqid, unsigned int dcpid, ++ struct qm_mcr_ceetm_cq_query *cq_query) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->cq_query.cqid = cqid; ++ mcc->cq_query.dcpid = dcpid; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CQ_QUERY); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ res = mcr->result; ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_CQ_QUERY); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: QUERY CQ failed\n"); ++ return -EIO; ++ } ++ ++ *cq_query = mcr->cq_query; ++ return 0; ++} ++ ++int qman_ceetm_configure_dct(struct qm_mcc_ceetm_dct_config *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->dct_config = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_DCT_CONFIG); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_DCT_CONFIG); ++ res = mcr->result; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CONFIGURE DCT failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++int qman_ceetm_query_dct(struct qm_mcc_ceetm_dct_query *opts, ++ struct qm_mcr_ceetm_dct_query *dct_query) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->dct_query = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_DCT_QUERY); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_DCT_QUERY); ++ res = mcr->result; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: QUERY DCT failed\n"); ++ return -EIO; ++ } ++ ++ *dct_query = mcr->dct_query; ++ return 0; ++} ++ ++int qman_ceetm_configure_class_scheduler( ++ struct qm_mcc_ceetm_class_scheduler_config *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->csch_config = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CLASS_SCHEDULER_CONFIG); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_CLASS_SCHEDULER_CONFIG); ++ res = mcr->result; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CONFIGURE CLASS SCHEDULER failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++int qman_ceetm_query_class_scheduler(struct qm_ceetm_channel *channel, ++ struct qm_mcr_ceetm_class_scheduler_query *query) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->csch_query.cqcid = channel->idx; ++ mcc->csch_query.dcpid = channel->dcp_idx; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CLASS_SCHEDULER_QUERY); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_CLASS_SCHEDULER_QUERY); ++ res = mcr->result; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: QUERY CLASS SCHEDULER failed\n"); ++ return -EIO; ++ } ++ *query = mcr->csch_query; ++ return 0; ++} ++ ++int qman_ceetm_configure_mapping_shaper_tcfc( ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->mst_config = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_MAPPING_SHAPER_TCFC_CONFIG); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_MAPPING_SHAPER_TCFC_CONFIG); ++ res = mcr->result; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CONFIGURE CHANNEL MAPPING failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++int qman_ceetm_query_mapping_shaper_tcfc( ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query *opts, ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query *response) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->mst_query = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_MAPPING_SHAPER_TCFC_QUERY); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_MAPPING_SHAPER_TCFC_QUERY); ++ res = mcr->result; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: QUERY CHANNEL MAPPING failed\n"); ++ return -EIO; ++ } ++ ++ *response = mcr->mst_query; ++ return 0; ++} ++ ++int qman_ceetm_configure_ccgr(struct qm_mcc_ceetm_ccgr_config *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->ccgr_config = *opts; ++ ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CCGR_CONFIG); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_CCGR_CONFIG); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CONFIGURE CCGR failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++int qman_ceetm_query_ccgr(struct qm_mcc_ceetm_ccgr_query *ccgr_query, ++ struct qm_mcr_ceetm_ccgr_query *response) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->ccgr_query = *ccgr_query; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CCGR_QUERY); ++ ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_CCGR_QUERY); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: QUERY CCGR failed\n"); ++ return -EIO; ++ } ++ *response = mcr->ccgr_query; ++ return 0; ++} ++ ++int qman_ceetm_cq_peek_pop_xsfdrread(struct qm_ceetm_cq *cq, ++ u8 command_type, u16 xsfdr, ++ struct qm_mcr_ceetm_cq_peek_pop_xsfdrread *cq_ppxr) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ switch (command_type) { ++ case 0: ++ case 1: ++ mcc->cq_ppxr.cqid = (cq->parent->idx << 4) | cq->idx; ++ break; ++ case 2: ++ mcc->cq_ppxr.xsfdr = xsfdr; ++ break; ++ default: ++ break; ++ } ++ mcc->cq_ppxr.ct = command_type; ++ mcc->cq_ppxr.dcpid = cq->parent->dcp_idx; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CQ_PEEK_POP_XFDRREAD); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_CQ_PEEK_POP_XFDRREAD); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CQ PEEK/POP/XSFDR READ failed\n"); ++ return -EIO; ++ } ++ *cq_ppxr = mcr->cq_ppxr; ++ return 0; ++} ++ ++int qman_ceetm_query_statistics(u16 cid, ++ enum qm_dc_portal dcp_idx, ++ u16 command_type, ++ struct qm_mcr_ceetm_statistics_query *query_result) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->stats_query_write.cid = cid; ++ mcc->stats_query_write.dcpid = dcp_idx; ++ mcc->stats_query_write.ct = command_type; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_STATISTICS_QUERY_WRITE); ++ ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_STATISTICS_QUERY_WRITE); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: STATISTICS QUERY failed\n"); ++ return -EIO; ++ } ++ *query_result = mcr->stats_query; ++ return 0; ++} ++ ++int qman_ceetm_write_statistics(u16 cid, enum qm_dc_portal dcp_idx, ++ u16 command_type, u64 frame_count, u64 byte_count) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->stats_query_write.cid = cid; ++ mcc->stats_query_write.dcpid = dcp_idx; ++ mcc->stats_query_write.ct = command_type; ++ mcc->stats_query_write.frm_cnt = frame_count; ++ mcc->stats_query_write.byte_cnt = byte_count; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_STATISTICS_QUERY_WRITE); ++ ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_STATISTICS_QUERY_WRITE); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: STATISTICS WRITE failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++/* bit divisor, dividend and result. dynamic precision */ ++static __inline__ uint64_t _div64_64(uint64_t dividend, uint64_t divisor) ++{ ++ uint32_t d = divisor; ++ ++ if (divisor > 0xffffffffULL) ++ { ++ unsigned int shift = fls(divisor >> 32); ++ ++ d = divisor >> shift; ++ dividend >>= shift; ++ } ++ ++ /* avoid 64 bit division if possible */ ++ if (dividend >> 32) ++ do_div(dividend, d); ++ else ++ dividend = (uint32_t) dividend / d; ++ ++ return dividend; ++} ++ ++int qman_ceetm_bps2tokenrate(u32 bps, struct qm_ceetm_rate *token_rate, ++ int rounding) ++{ ++ u16 pres; ++ u64 temp; ++ u64 qman_freq; ++ int ret; ++ ++ /* Read PRES from CEET_CFG_PRES register */ ++ ret = qman_ceetm_get_prescaler(&pres); ++ if (ret) ++ return -EINVAL; ++ ++ ret = qm_get_clock(&qman_freq); ++ if (ret) ++ return -EINVAL; ++ ++ /* token-rate = bytes-per-second * update-reference-period ++ * ++ * Where token-rate is N/8192 for a interger N, and ++ * update-reference-period is (2^22)/(PRES*QHz), where PRES ++ * is the prescalar value and QHz is the QMan clock frequency. ++ * So: ++ * ++ * token-rate = (byte-per-second*2^22)/PRES*QHZ) ++ * ++ * Converting to bits-per-second gives; ++ * ++ * token-rate = (bps*2^19) / (PRES*QHZ) ++ * N = (bps*2^32) / (PRES*QHz) ++ * ++ */ ++ temp = ROUNDING(((u64)bps << 32), pres, rounding); ++ temp = ROUNDING(temp, qman_freq, rounding); ++ token_rate->whole = temp >> 13; ++ token_rate->fraction = temp & (((u64)1 << 13) - 1); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_bps2tokenrate); ++ ++int qman_ceetm_tokenrate2bps(const struct qm_ceetm_rate *token_rate, u32 *bps, ++ int rounding) ++{ ++ u16 pres; ++ u64 temp; ++ u64 qman_freq; ++ int ret; ++ ++ /* Read PRES from CEET_CFG_PRES register */ ++ ret = qman_ceetm_get_prescaler(&pres); ++ if (ret) ++ return -EINVAL; ++ ++ ret = qm_get_clock(&qman_freq); ++ if (ret) ++ return -EINVAL; ++ ++ /* bytes-per-second = token-rate / update-reference-period ++ * ++ * where "token-rate" is N/8192 for an integer N, and ++ * "update-reference-period" is (2^22)/(PRES*QHz), where PRES is ++ * the prescalar value and QHz is the QMan clock frequency. So; ++ * ++ * bytes-per-second = (N/8192) / (4194304/PRES*QHz) ++ * = N*PRES*QHz / (4194304*8192) ++ * = N*PRES*QHz / (2^35) ++ * ++ * Converting to bits-per-second gives; ++ * ++ * bps = N*PRES*QHZ / (2^32) ++ * ++ * Note, the numerator has a maximum width of 72 bits! So to ++ * avoid 64-bit overflow errors, we calculate PRES*QHZ (maximum ++ * width 48 bits) divided by 2^9 (reducing to maximum 39 bits), before ++ * multiplying by N (goes to maximum of 63 bits). ++ * ++ * temp = PRES*QHZ / (2^16) ++ * kbps = temp*N / (2^16) ++ */ ++ temp = ROUNDING(qman_freq * pres, (u64)1 << 16 , rounding); ++ temp *= ((token_rate->whole << 13) + token_rate->fraction); ++ *bps = ROUNDING(temp, (u64)(1) << 16, rounding); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_tokenrate2bps); ++ ++int qman_ceetm_sp_claim(struct qm_ceetm_sp **sp, enum qm_dc_portal dcp_idx, ++ unsigned int sp_idx) ++{ ++ struct qm_ceetm_sp *p; ++ ++ DPA_ASSERT((dcp_idx == qm_dc_portal_fman0) || ++ (dcp_idx == qm_dc_portal_fman1)); ++ ++ if ((sp_idx < qman_ceetms[dcp_idx].sp_range[0]) || ++ (sp_idx > (qman_ceetms[dcp_idx].sp_range[0] + ++ qman_ceetms[dcp_idx].sp_range[1]))) { ++ pr_err("Sub-portal index doesn't exist\n"); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(p, &qman_ceetms[dcp_idx].sub_portals, node) { ++ if ((p->idx == sp_idx) && (p->is_claimed == 0)) { ++ p->is_claimed = 1; ++ *sp = p; ++ return 0; ++ } ++ } ++ pr_err("The sub-portal#%d is not available!\n", sp_idx); ++ return -ENODEV; ++} ++EXPORT_SYMBOL(qman_ceetm_sp_claim); ++ ++int qman_ceetm_sp_release(struct qm_ceetm_sp *sp) ++{ ++ struct qm_ceetm_sp *p; ++ ++ if (sp->lni->is_claimed == 1) { ++ pr_err("The dependency of sub-portal has not been released!\n"); ++ return -EBUSY; ++ } ++ ++ list_for_each_entry(p, &qman_ceetms[sp->dcp_idx].sub_portals, node) { ++ if (p->idx == sp->idx) { ++ p->is_claimed = 0; ++ p->lni = NULL; ++ } ++ } ++ /* Disable CEETM mode of this sub-portal */ ++ qman_sp_disable_ceetm_mode(sp->idx, sp->dcp_idx); ++ ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_sp_release); ++ ++int qman_ceetm_lni_claim(struct qm_ceetm_lni **lni, enum qm_dc_portal dcp_idx, ++ unsigned int lni_idx) ++{ ++ struct qm_ceetm_lni *p; ++ ++ if ((lni_idx < qman_ceetms[dcp_idx].lni_range[0]) || ++ (lni_idx > (qman_ceetms[dcp_idx].lni_range[0] + ++ qman_ceetms[dcp_idx].lni_range[1]))) { ++ pr_err("The lni index is out of range\n"); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(p, &qman_ceetms[dcp_idx].lnis, node) { ++ if ((p->idx == lni_idx) && (p->is_claimed == 0)) { ++ *lni = p; ++ p->is_claimed = 1; ++ return 0; ++ } ++ } ++ ++ pr_err("The LNI#%d is not available!\n", lni_idx); ++ return -EINVAL; ++} ++EXPORT_SYMBOL(qman_ceetm_lni_claim); ++ ++int qman_ceetm_lni_release(struct qm_ceetm_lni *lni) ++{ ++ struct qm_ceetm_lni *p; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ ++ if (!list_empty(&lni->channels)) { ++ pr_err("The LNI dependencies are not released!\n"); ++ return -EBUSY; ++ } ++ ++ list_for_each_entry(p, &qman_ceetms[lni->dcp_idx].lnis, node) { ++ if (p->idx == lni->idx) { ++ p->shaper_enable = 0; ++ p->shaper_couple = 0; ++ p->cr_token_rate.whole = 0; ++ p->cr_token_rate.fraction = 0; ++ p->er_token_rate.whole = 0; ++ p->er_token_rate.fraction = 0; ++ p->cr_token_bucket_limit = 0; ++ p->er_token_bucket_limit = 0; ++ p->is_claimed = 0; ++ } ++ } ++ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ config_opts.dcpid = lni->dcp_idx; ++ memset(&config_opts.shaper_config, 0, ++ sizeof(config_opts.shaper_config)); ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_release); ++ ++int qman_ceetm_sp_set_lni(struct qm_ceetm_sp *sp, struct qm_ceetm_lni *lni) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ ++ config_opts.cid = CEETM_COMMAND_SP_MAPPING | sp->idx; ++ config_opts.dcpid = sp->dcp_idx; ++ config_opts.sp_mapping.map_lni_id = lni->idx; ++ sp->lni = lni; ++ ++ if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts)) ++ return -EINVAL; ++ ++ /* Enable CEETM mode for this sub-portal */ ++ return qman_sp_enable_ceetm_mode(sp->dcp_idx, sp->idx); ++} ++EXPORT_SYMBOL(qman_ceetm_sp_set_lni); ++ ++int qman_ceetm_sp_get_lni(struct qm_ceetm_sp *sp, unsigned int *lni_idx) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ ++ query_opts.cid = CEETM_COMMAND_SP_MAPPING | sp->idx; ++ query_opts.dcpid = sp->dcp_idx; ++ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) { ++ pr_err("Can't get SP <-> LNI mapping\n"); ++ return -EINVAL; ++ } ++ *lni_idx = query_result.sp_mapping_query.map_lni_id; ++ sp->lni->idx = query_result.sp_mapping_query.map_lni_id; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_sp_get_lni); ++ ++int qman_ceetm_lni_enable_shaper(struct qm_ceetm_lni *lni, int coupled, ++ int oal) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ ++ if (lni->shaper_enable) { ++ pr_err("The shaper has already been enabled\n"); ++ return -EINVAL; ++ } ++ ++ lni->shaper_enable = 1; ++ lni->shaper_couple = coupled; ++ ++ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ config_opts.dcpid = lni->dcp_idx; ++ config_opts.shaper_config.cpl = (coupled << 7) | oal; ++ config_opts.shaper_config.crtcr = (lni->cr_token_rate.whole << 13) | ++ lni->cr_token_rate.fraction; ++ config_opts.shaper_config.ertcr = (lni->er_token_rate.whole << 13) | ++ lni->er_token_rate.fraction; ++ config_opts.shaper_config.crtbl = lni->cr_token_bucket_limit; ++ config_opts.shaper_config.ertbl = lni->er_token_bucket_limit; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_enable_shaper); ++ ++int qman_ceetm_lni_disable_shaper(struct qm_ceetm_lni *lni) ++{ ++ if (!lni->shaper_enable) { ++ pr_err("The shaper has been disabled\n"); ++ return -EINVAL; ++ } ++ ++ lni->shaper_enable = 0; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lni_disable_shaper); ++ ++int qman_ceetm_lni_set_commit_rate(struct qm_ceetm_lni *lni, ++ const struct qm_ceetm_rate *token_rate, ++ u16 token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ if (!lni->shaper_enable) { ++ pr_err("The LNI#%d is unshaped, cannot set CR rate\n", ++ lni->idx); ++ return -EINVAL; ++ } ++ ++ query_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ query_opts.dcpid = lni->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret) { ++ pr_err("Fail to get current LNI shaper setting\n"); ++ return -EINVAL; ++ } ++ ++ lni->cr_token_rate.whole = token_rate->whole; ++ lni->cr_token_rate.fraction = token_rate->fraction; ++ lni->cr_token_bucket_limit = token_limit; ++ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ config_opts.dcpid = lni->dcp_idx; ++ config_opts.shaper_config.crtcr = (token_rate->whole << 13) | ++ (token_rate->fraction); ++ config_opts.shaper_config.crtbl = token_limit; ++ config_opts.shaper_config.cpl = query_result.shaper_query.cpl; ++ config_opts.shaper_config.ertcr = query_result.shaper_query.ertcr; ++ config_opts.shaper_config.ertbl = query_result.shaper_query.ertbl; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_set_commit_rate); ++ ++int qman_ceetm_lni_get_commit_rate(struct qm_ceetm_lni *lni, ++ struct qm_ceetm_rate *token_rate, ++ u16 *token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ query_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ query_opts.dcpid = lni->dcp_idx; ++ ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret | !query_result.shaper_query.crtcr | ++ !query_result.shaper_query.crtbl) { ++ pr_err("The LNI CR rate or limit is not set\n"); ++ return -EINVAL; ++ } ++ token_rate->whole = query_result.shaper_query.crtcr >> 13; ++ token_rate->fraction = query_result.shaper_query.crtcr & 0x1FFF; ++ *token_limit = query_result.shaper_query.crtbl; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lni_get_commit_rate); ++ ++int qman_ceetm_lni_set_excess_rate(struct qm_ceetm_lni *lni, ++ const struct qm_ceetm_rate *token_rate, ++ u16 token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ if (!lni->shaper_enable) { ++ pr_err("The LIN#%d is unshaped, cannot set ER rate\n", ++ lni->idx); ++ return -EINVAL; ++ } ++ ++ query_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ query_opts.dcpid = lni->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret) { ++ pr_err("Fail to get current LNI shaper setting\n"); ++ return -EINVAL; ++ } ++ ++ lni->er_token_rate.whole = token_rate->whole; ++ lni->er_token_rate.fraction = token_rate->fraction; ++ lni->er_token_bucket_limit = token_limit; ++ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ config_opts.dcpid = lni->dcp_idx; ++ config_opts.shaper_config.ertcr = ++ (token_rate->whole << 13) | (token_rate->fraction); ++ config_opts.shaper_config.ertbl = token_limit; ++ config_opts.shaper_config.cpl = query_result.shaper_query.cpl; ++ config_opts.shaper_config.crtcr = query_result.shaper_query.crtcr; ++ config_opts.shaper_config.crtbl = query_result.shaper_query.crtbl; ++ ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_set_excess_rate); ++ ++int qman_ceetm_lni_get_excess_rate(struct qm_ceetm_lni *lni, ++ struct qm_ceetm_rate *token_rate, ++ u16 *token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ query_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ query_opts.dcpid = lni->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret | !query_result.shaper_query.ertcr | ++ !query_result.shaper_query.ertbl) { ++ pr_err("The LNI ER rate or limit is not set\n"); ++ return -EINVAL; ++ } ++ token_rate->whole = query_result.shaper_query.ertcr >> 13; ++ token_rate->fraction = query_result.shaper_query.ertcr & 0x1FFF; ++ *token_limit = query_result.shaper_query.ertbl; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lni_get_excess_rate); ++ ++#define QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(n) ((15 - n) * 4) ++#define QMAN_CEETM_LNITCFCC_ENABLE 0x8 ++int qman_ceetm_lni_set_tcfcc(struct qm_ceetm_lni *lni, ++ unsigned int cq_level, ++ int traffic_class) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ u64 lnitcfcc; ++ ++ if ((cq_level > 15) | (traffic_class > 7)) { ++ pr_err("The CQ or traffic class id is out of range\n"); ++ return -EINVAL; ++ } ++ ++ query_opts.cid = CEETM_COMMAND_TCFC | lni->idx; ++ query_opts.dcpid = lni->dcp_idx; ++ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) { ++ pr_err("Fail to query tcfcc\n"); ++ return -EINVAL; ++ } ++ ++ lnitcfcc = query_result.tcfc_query.lnitcfcc; ++ if (traffic_class == -1) { ++ /* disable tcfc for this CQ */ ++ lnitcfcc &= ~((u64)QMAN_CEETM_LNITCFCC_ENABLE << ++ QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(cq_level)); ++ } else { ++ lnitcfcc &= ~((u64)0xF << ++ QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(cq_level)); ++ lnitcfcc |= ((u64)(QMAN_CEETM_LNITCFCC_ENABLE | ++ traffic_class)) << ++ QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(cq_level); ++ } ++ config_opts.tcfc_config.lnitcfcc = lnitcfcc; ++ config_opts.cid = CEETM_COMMAND_TCFC | lni->idx; ++ config_opts.dcpid = lni->dcp_idx; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_set_tcfcc); ++ ++#define QMAN_CEETM_LNITCFCC_TC_MASK 0x7 ++int qman_ceetm_lni_get_tcfcc(struct qm_ceetm_lni *lni, unsigned int cq_level, ++ int *traffic_class) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ u8 lnitcfcc; ++ ++ if (cq_level > 15) { ++ pr_err("the CQ level is out of range\n"); ++ return -EINVAL; ++ } ++ ++ query_opts.cid = CEETM_COMMAND_TCFC | lni->idx; ++ query_opts.dcpid = lni->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret) ++ return ret; ++ lnitcfcc = (u8)(query_result.tcfc_query.lnitcfcc >> ++ QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(cq_level)); ++ if (lnitcfcc & QMAN_CEETM_LNITCFCC_ENABLE) ++ *traffic_class = lnitcfcc & QMAN_CEETM_LNITCFCC_TC_MASK; ++ else ++ *traffic_class = -1; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lni_get_tcfcc); ++ ++#define QMAN_CEETM_ENABLE_CHANNEL_SHAPER 0x80 ++int qman_ceetm_channel_claim(struct qm_ceetm_channel **channel, ++ struct qm_ceetm_lni *lni) ++{ ++ struct qm_ceetm_channel *p; ++ u32 channel_idx; ++ int ret = 0; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ static u8 map; ++ ++ if (lni->dcp_idx == qm_dc_portal_fman0) ++ ret = qman_alloc_ceetm0_channel(&channel_idx); ++ if (lni->dcp_idx == qm_dc_portal_fman1) ++ ret = qman_alloc_ceetm1_channel(&channel_idx); ++ if (ret) { ++ pr_err("The is no channel available for LNI#%d\n", lni->idx); ++ return -ENODEV; ++ } ++ ++ p = kzalloc(sizeof(*p), GFP_KERNEL); ++ p->idx = channel_idx; ++ p->dcp_idx = lni->dcp_idx; ++ list_add_tail(&p->node, &lni->channels); ++ INIT_LIST_HEAD(&p->class_queues); ++ INIT_LIST_HEAD(&p->ccgs); ++ config_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel_idx; ++ config_opts.dcpid = lni->dcp_idx; ++ map = (u8)~QMAN_CEETM_ENABLE_CHANNEL_SHAPER; ++ map &= lni->idx; ++ config_opts.channel_mapping.map = map; ++ if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts)) { ++ pr_err("Can't map channel#%d for LNI#%d\n", ++ channel_idx, lni->idx); ++ return -EINVAL; ++ } ++ *channel = p; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_claim); ++ ++int qman_ceetm_channel_release(struct qm_ceetm_channel *channel) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ if (!list_empty(&channel->class_queues)) { ++ pr_err("CEETM channel#%d has class queue unreleased!\n", ++ channel->idx); ++ return -EBUSY; ++ } ++ if (!list_empty(&channel->ccgs)) { ++ pr_err("CEETM channel#%d has ccg unreleased!\n", ++ channel->idx); ++ return -EBUSY; ++ } ++ ++ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ memset(&config_opts.shaper_config, 0, ++ sizeof(config_opts.shaper_config)); ++ if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts)) { ++ pr_err("Can't reset channel shapping parameters\n"); ++ return -EINVAL; ++ } ++ ++ if (channel->dcp_idx == qm_dc_portal_fman0) ++ qman_release_ceetm0_channelid(channel->idx); ++ if (channel->dcp_idx == qm_dc_portal_fman1) ++ qman_release_ceetm1_channelid(channel->idx); ++ list_del(&channel->node); ++ kfree(channel); ++ ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_release); ++ ++int qman_ceetm_channel_enable_shaper(struct qm_ceetm_channel *channel, ++ int coupled) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ u8 map; ++ ++ if (channel->shaper_enable == 1) { ++ pr_err("This channel shaper has been enabled!\n"); ++ return -EINVAL; ++ } ++ ++ channel->shaper_enable = 1; ++ channel->shaper_couple = coupled; ++ ++ query_opts.cid = (u16)(CEETM_COMMAND_CHANNEL_MAPPING | channel->idx); ++ query_opts.dcpid = (u8)channel->dcp_idx; ++ ++ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) { ++ pr_err("Can't query channel mapping\n"); ++ return -EINVAL; ++ } ++ ++ map = query_result.channel_mapping_query.map; ++ map |= QMAN_CEETM_ENABLE_CHANNEL_SHAPER; ++ ++ config_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ config_opts.channel_mapping.map = map; ++ if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts)) { ++ pr_err("Can't enable shaper for channel #%d\n", ++ channel->idx); ++ return -EINVAL; ++ } ++ ++ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ config_opts.shaper_config.cpl = coupled << 7; ++ config_opts.shaper_config.crtcr = (channel->cr_token_rate.whole << 13) | ++ channel->cr_token_rate.fraction; ++ config_opts.shaper_config.ertcr = (channel->er_token_rate.whole << 13) | ++ channel->er_token_rate.fraction; ++ config_opts.shaper_config.crtbl = channel->cr_token_bucket_limit; ++ config_opts.shaper_config.ertbl = channel->er_token_bucket_limit; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_enable_shaper); ++ ++int qman_ceetm_channel_disable_shaper(struct qm_ceetm_channel *channel) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ u8 map; ++ ++ if (channel->shaper_enable == 0) { ++ pr_err("This channel shaper has been disabled\n"); ++ return -EINVAL; ++ } ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ++ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) { ++ pr_err("Can't query channel mapping\n"); ++ return -EINVAL; ++ } ++ ++ map = query_result.channel_mapping_query.map; ++ map &= ~QMAN_CEETM_ENABLE_CHANNEL_SHAPER; ++ ++ config_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ config_opts.channel_mapping.map = map; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_disable_shaper); ++ ++int qman_ceetm_channel_set_commit_rate(struct qm_ceetm_channel *channel, ++ const struct qm_ceetm_rate *token_rate, ++ u16 token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ if (!channel->shaper_enable) { ++ pr_err("This channel is unshaped\n"); ++ return -EINVAL; ++ } ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret) { ++ pr_err("Fail to get the current channel shaper setting\n"); ++ return -EINVAL; ++ } ++ ++ channel->cr_token_rate.whole = token_rate->whole; ++ channel->cr_token_rate.fraction = token_rate->fraction; ++ channel->cr_token_bucket_limit = token_limit; ++ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ config_opts.shaper_config.crtcr = (token_rate->whole << 13) | ++ (token_rate->fraction); ++ config_opts.shaper_config.crtbl = token_limit; ++ config_opts.shaper_config.cpl = query_result.shaper_query.cpl; ++ config_opts.shaper_config.ertcr = query_result.shaper_query.ertcr; ++ config_opts.shaper_config.ertbl = query_result.shaper_query.ertbl; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_commit_rate); ++ ++int qman_ceetm_channel_get_commit_rate(struct qm_ceetm_channel *channel, ++ struct qm_ceetm_rate *token_rate, ++ u16 *token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret | !query_result.shaper_query.crtcr | ++ !query_result.shaper_query.crtbl) { ++ pr_err("The channel commit rate or limit is not set\n"); ++ return -EINVAL; ++ } ++ token_rate->whole = query_result.shaper_query.crtcr >> 13; ++ token_rate->fraction = query_result.shaper_query.crtcr & 0x1FFF; ++ *token_limit = query_result.shaper_query.crtbl; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_get_commit_rate); ++ ++int qman_ceetm_channel_set_excess_rate(struct qm_ceetm_channel *channel, ++ const struct qm_ceetm_rate *token_rate, ++ u16 token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ if (!channel->shaper_enable) { ++ pr_err("This channel is unshaped\n"); ++ return -EINVAL; ++ } ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret) { ++ pr_err("Fail to get the current channel shaper setting\n"); ++ return -EINVAL; ++ } ++ ++ channel->er_token_rate.whole = token_rate->whole; ++ channel->er_token_rate.fraction = token_rate->fraction; ++ channel->er_token_bucket_limit = token_limit; ++ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ config_opts.shaper_config.ertcr = ++ (token_rate->whole << 13) | (token_rate->fraction); ++ config_opts.shaper_config.ertbl = token_limit; ++ config_opts.shaper_config.cpl = query_result.shaper_query.cpl; ++ config_opts.shaper_config.crtcr = query_result.shaper_query.crtcr; ++ config_opts.shaper_config.crtbl = query_result.shaper_query.crtbl; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_excess_rate); ++ ++int qman_ceetm_channel_get_excess_rate(struct qm_ceetm_channel *channel, ++ struct qm_ceetm_rate *token_rate, ++ u16 *token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret | !query_result.shaper_query.ertcr | ++ !query_result.shaper_query.ertbl) { ++ pr_err("The channel excess rate or limit is not set\n"); ++ return -EINVAL; ++ } ++ token_rate->whole = query_result.shaper_query.ertcr >> 13; ++ token_rate->fraction = query_result.shaper_query.ertcr & 0x1FFF; ++ *token_limit = query_result.shaper_query.ertbl; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_get_excess_rate); ++ ++int qman_ceetm_channel_set_weight(struct qm_ceetm_channel *channel, ++ u16 token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ ++ if (channel->shaper_enable) { ++ pr_err("This channel is a shaped one\n"); ++ return -EINVAL; ++ } ++ ++ channel->cr_token_bucket_limit = token_limit; ++ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ config_opts.shaper_config.crtbl = token_limit; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_weight); ++ ++int qman_ceetm_channel_get_weight(struct qm_ceetm_channel *channel, ++ u16 *token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret | !query_result.shaper_query.crtbl) { ++ pr_err("This unshaped channel's uFQ wight is unavailable\n"); ++ return -EINVAL; ++ } ++ *token_limit = query_result.shaper_query.crtbl; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_get_weight); ++ ++int qman_ceetm_channel_set_group(struct qm_ceetm_channel *channel, int group_b, ++ unsigned int prio_a, unsigned int prio_b) ++{ ++ struct qm_mcc_ceetm_class_scheduler_config config_opts; ++ struct qm_mcr_ceetm_class_scheduler_query query_result; ++ int i; ++ ++ if (!prio_a | (prio_a > 7)) { ++ pr_err("The priority of group A is out of range\n"); ++ return -EINVAL; ++ } ++ if (!prio_a || (prio_b > 7)) { ++ pr_err("The priority of group B is out of range\n"); ++ return -EINVAL; ++ } ++ ++ if (qman_ceetm_query_class_scheduler(channel, &query_result)) { ++ pr_err("Can't query channel#%d's scheduler!\n", channel->idx); ++ return -EINVAL; ++ } ++ ++ config_opts.cqcid = channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ if (!group_b) ++ config_opts.gpc = (u8)((1 << 6) | prio_a); ++ else ++ config_opts.gpc = (u8)((prio_b << 3) | prio_a); ++ ++ for (i = 0; i < 8; i++) ++ config_opts.w[i] = query_result.w[i]; ++ config_opts.crem = query_result.crem; ++ config_opts.erem = query_result.erem; ++ ++ return qman_ceetm_configure_class_scheduler(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_group); ++ ++int qman_ceetm_channel_get_group(struct qm_ceetm_channel *channel, int *group_b, ++ unsigned int *prio_a, unsigned int *prio_b) ++{ ++ struct qm_mcr_ceetm_class_scheduler_query query_result; ++ ++ if (qman_ceetm_query_class_scheduler(channel, &query_result)) { ++ pr_err("Can't query channel#%d's scheduler!\n", channel->idx); ++ return -EINVAL; ++ } ++ *group_b = (query_result.gpc >> 6) & 0x1; ++ *prio_a = query_result.gpc & 0x3; ++ *prio_b = (query_result.gpc >> 3) & 0x3; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_get_group); ++ ++#define CQ_ELIGIBILITY_MASK(n) (1 << (7 - n)) ++#define CQ_A_ELIGIBILITY_MASK (1 << 8) ++#define CQ_B_ELIGIBILITY_MASK (1 << 9) ++int qman_ceetm_cq_claim(struct qm_ceetm_cq **cq, ++ struct qm_ceetm_channel *channel, unsigned int idx, ++ struct qm_ceetm_ccg *ccg) ++{ ++ struct qm_ceetm_cq *p; ++ struct qm_mcc_ceetm_cq_config cq_config; ++ struct qm_mcc_ceetm_class_scheduler_config csch_config; ++ struct qm_mcr_ceetm_class_scheduler_query csch_query_result; ++ int i; ++ ++ if (idx > 7) { ++ pr_err("The independent class queue id is out of range\n"); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(p, &channel->class_queues, node) { ++ if (p->idx == idx) { ++ pr_err("The CQ#%d has been claimed!\n", idx); ++ return -EINVAL; ++ } ++ } ++ ++ p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) { ++ pr_err("Can't allocate memory for CQ#%d!\n", idx); ++ return -ENOMEM; ++ } ++ ++ list_add_tail(&p->node, &channel->class_queues); ++ p->idx = idx; ++ p->is_claimed = 1; ++ p->parent = channel; ++ INIT_LIST_HEAD(&p->bound_lfqids); ++ ++ if (ccg) { ++ cq_config.cqid = (channel->idx << 4) | idx; ++ cq_config.dcpid = channel->dcp_idx; ++ cq_config.ccgid = ccg->idx; ++ if (qman_ceetm_configure_cq(&cq_config)) { ++ pr_err("Can't configure the CQ#%d with CCGRID#%d\n", ++ idx, ccg->idx); ++ return -EINVAL; ++ } ++ } ++ ++ if (channel->shaper_enable) { ++ if (qman_ceetm_query_class_scheduler(channel, ++ &csch_query_result)) { ++ pr_err("Can't query channel#%d!\n", channel->idx); ++ return -EINVAL; ++ } ++ csch_config.cqcid = channel->idx; ++ csch_config.dcpid = channel->dcp_idx; ++ csch_config.crem = csch_query_result.crem | ++ CQ_ELIGIBILITY_MASK(idx); ++ csch_config.erem = csch_query_result.erem | ++ CQ_ELIGIBILITY_MASK(idx); ++ csch_config.gpc = csch_query_result.gpc; ++ for (i = 0; i < 8; i++) ++ csch_config.w[i] = csch_query_result.w[i]; ++ ++ if (qman_ceetm_configure_class_scheduler(&csch_config)) { ++ pr_err("Can't config channel scheduler to set" ++ " eligibility mask for CQ#%d\n", idx); ++ return -EINVAL; ++ } ++ } ++ ++ *cq = p; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cq_claim); ++ ++int qman_ceetm_cq_claim_A(struct qm_ceetm_cq **cq, ++ struct qm_ceetm_channel *channel, unsigned int idx, ++ struct qm_ceetm_ccg *ccg) ++{ ++ struct qm_ceetm_cq *p; ++ struct qm_mcc_ceetm_cq_config cq_config; ++ struct qm_mcc_ceetm_class_scheduler_config csch_config; ++ struct qm_mcr_ceetm_class_scheduler_query csch_query_result; ++ int i; ++ ++ if ((idx < 7) || (idx > 15)) { ++ pr_err("This grouped class queue id is out of range\n"); ++ return -EINVAL; ++ } ++ p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) { ++ pr_err("Can't allocate memory for CQ#%d!\n", idx); ++ return -ENOMEM; ++ } ++ ++ list_for_each_entry(p, &channel->class_queues, node) { ++ if (p->idx == idx) { ++ pr_err("The CQ#%d has been claimed!\n", idx); ++ return -EINVAL; ++ } ++ } ++ list_add_tail(&p->node, &channel->class_queues); ++ p->idx = idx; ++ p->is_claimed = 1; ++ p->parent = channel; ++ INIT_LIST_HEAD(&p->bound_lfqids); ++ ++ if (ccg) { ++ cq_config.cqid = (channel->idx << 4) | idx; ++ cq_config.dcpid = channel->dcp_idx; ++ cq_config.ccgid = ccg->idx; ++ if (qman_ceetm_configure_cq(&cq_config)) { ++ pr_err("Can't configure the CQ#%d with CCGRID#%d\n", ++ idx, ccg->idx); ++ return -EINVAL; ++ } ++ } ++ ++ if (channel->shaper_enable) { ++ if (qman_ceetm_query_class_scheduler(channel, ++ &csch_query_result)) { ++ pr_err("Can't query channel#%d!\n", channel->idx); ++ return -EINVAL; ++ } ++ csch_config.cqcid = channel->idx; ++ csch_config.dcpid = channel->dcp_idx; ++ csch_config.crem = csch_query_result.crem | ++ CQ_A_ELIGIBILITY_MASK; ++ csch_config.erem = csch_query_result.erem | ++ CQ_A_ELIGIBILITY_MASK; ++ csch_config.gpc = csch_query_result.gpc; ++ for (i = 0; i < 8; i++) ++ csch_config.w[i] = csch_query_result.w[i]; ++ if (qman_ceetm_configure_class_scheduler(&csch_config)) { ++ pr_err("Can't config channel scheduler to set" ++ " eligibility mask for CQ#%d\n", idx); ++ return -EINVAL; ++ } ++ } ++ *cq = p; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cq_claim_A); ++ ++int qman_ceetm_cq_claim_B(struct qm_ceetm_cq **cq, ++ struct qm_ceetm_channel *channel, unsigned int idx, ++ struct qm_ceetm_ccg *ccg) ++{ ++ struct qm_ceetm_cq *p; ++ struct qm_mcc_ceetm_cq_config cq_config; ++ struct qm_mcc_ceetm_class_scheduler_config csch_config; ++ struct qm_mcr_ceetm_class_scheduler_query csch_query_result; ++ int i; ++ ++ if ((idx < 11) || (idx > 15)) { ++ pr_err("This grouped class queue id is out of range\n"); ++ return -EINVAL; ++ } ++ ++ p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) { ++ pr_err("Can't allocate memory for CQ#%d!\n", idx); ++ return -ENOMEM; ++ } ++ ++ list_for_each_entry(p, &channel->class_queues, node) { ++ if (p->idx == idx) { ++ pr_err("The CQ#%d has been claimed!\n", idx); ++ return -EINVAL; ++ } ++ } ++ list_add_tail(&p->node, &channel->class_queues); ++ p->idx = idx; ++ p->is_claimed = 1; ++ p->parent = channel; ++ INIT_LIST_HEAD(&p->bound_lfqids); ++ ++ if (ccg) { ++ cq_config.cqid = (channel->idx << 4) | idx; ++ cq_config.dcpid = channel->dcp_idx; ++ cq_config.ccgid = ccg->idx; ++ if (qman_ceetm_configure_cq(&cq_config)) { ++ pr_err("Can't configure the CQ#%d with CCGRID#%d\n", ++ idx, ccg->idx); ++ return -EINVAL; ++ } ++ } ++ ++ if (channel->shaper_enable) { ++ if (qman_ceetm_query_class_scheduler(channel, ++ &csch_query_result)) { ++ pr_err("Can't query channel#%d!\n", channel->idx); ++ return -EINVAL; ++ } ++ csch_config.cqcid = channel->idx; ++ csch_config.dcpid = channel->dcp_idx; ++ csch_config.crem = csch_query_result.crem | ++ CQ_B_ELIGIBILITY_MASK; ++ csch_config.erem = csch_query_result.erem | ++ CQ_B_ELIGIBILITY_MASK; ++ csch_config.gpc = csch_query_result.gpc; ++ for (i = 0; i < 8; i++) ++ csch_config.w[i] = csch_query_result.w[i]; ++ if (qman_ceetm_configure_class_scheduler(&csch_config)) { ++ pr_err("Can't config channel scheduler to set" ++ " eligibility mask for CQ#%d\n", idx); ++ return -EINVAL; ++ } ++ } ++ *cq = p; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cq_claim_B); ++ ++int qman_ceetm_cq_release(struct qm_ceetm_cq *cq) ++{ ++ if (!list_empty(&cq->bound_lfqids)) { ++ pr_err("The CQ#%d has unreleased LFQID\n", cq->idx); ++ return -EBUSY; ++ } ++ list_del(&cq->node); ++ kfree(cq); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cq_release); ++ ++int qman_ceetm_set_queue_weight(struct qm_ceetm_cq *cq, ++ struct qm_ceetm_weight_code *weight_code) ++{ ++ struct qm_mcc_ceetm_class_scheduler_config config_opts; ++ struct qm_mcr_ceetm_class_scheduler_query query_result; ++ int i; ++ ++ if (qman_ceetm_query_class_scheduler(cq->parent, &query_result)) { ++ pr_err("Can't query channel#%d's scheduler!\n", ++ cq->parent->idx); ++ return -EINVAL; ++ } ++ ++ config_opts.cqcid = cq->parent->idx; ++ config_opts.dcpid = cq->parent->dcp_idx; ++ config_opts.crem = query_result.crem; ++ config_opts.erem = query_result.erem; ++ config_opts.gpc = query_result.gpc; ++ for (i = 0; i < 8; i++) ++ config_opts.w[i] = query_result.w[i]; ++ config_opts.w[cq->idx] = (weight_code->y << 3) | weight_code->x; ++ return qman_ceetm_configure_class_scheduler(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_set_queue_weight); ++ ++int qman_ceetm_get_queue_weight(struct qm_ceetm_cq *cq, ++ struct qm_ceetm_weight_code *weight_code) ++{ ++ struct qm_mcr_ceetm_class_scheduler_query query_result; ++ ++ if (qman_ceetm_query_class_scheduler(cq->parent, ++ &query_result)) { ++ pr_err("Can't get the weight code for CQ#%d!\n", cq->idx); ++ return -EINVAL; ++ } ++ weight_code->y = (query_result.w[cq->idx] >> 3) & 0x1F; ++ weight_code->x = query_result.w[cq->idx] & 0x3; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_get_queue_weight); ++ ++/* The WBFS code is represent as {x,y}, the effect wieght can be calculated as: ++ * effective weight = 2^x / (1 - (y/64)) ++ * = 2^(x+6) / (64 - y) ++ */ ++#define QM_WBFS_MAKECODE(x, y) (((y) << 3) | ((x & 0x7))) ++#define QM_WBFS_CODE_X(c) ((c) & 0x7) ++#define QM_WBFS_CODE_Y(c) ((c) >> 3) ++static void reduce_fraction(u32 *n, u32 *d) ++{ ++ u32 factor = 2; ++ u32 lesser = (*n < *d) ? *n : *d; ++ /* If factor exceeds the square-root of the lesser of *n and *d, ++ * then there's no point continuing. Proof: if there was a factor ++ * bigger than the square root, that would imply there exists ++ * another factor smaller than the square-root with which it ++ * multiplies to give 'lesser' - but that's a contradiction ++ * because the other factor would have already been found and ++ * divided out. ++ */ ++ while ((factor * factor) <= lesser) { ++ /* If 'factor' is a factor of *n and *d, divide them both ++ * by 'factor' as many times as possible. ++ */ ++ while (!(*n % factor) && !(*d % factor)) { ++ *n /= factor; ++ *d /= factor; ++ lesser /= factor; ++ } ++ if (factor == 2) ++ factor = 3; ++ else ++ factor += 2; ++ } ++} ++ ++int qman_ceetm_wbfs2ratio(unsigned int weight_code, ++ u32 *numerator, ++ u32 *denominator) ++{ ++ *numerator = (u32) 1 << (QM_WBFS_CODE_X(weight_code) + 6); ++ *denominator = 64 - QM_WBFS_CODE_Y(weight_code); ++ reduce_fraction(numerator, denominator); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_wbfs2ratio); ++ ++/* For a given x, the weight is between 2^x (inclusive) and 2^(x+1) (exclusive). ++ * So find 'x' by range, and then estimate 'y' using: ++ * 64 - y = 2^(x + 6) / weight ++ * = 2^(x + 6) / (n/d) ++ * = d * 2^(x+6) / n ++ * y = 64 - (d * 2^(x+6) / n) ++ */ ++int qman_ceetm_ratio2wbfs(u32 numerator, ++ u32 denominator, ++ unsigned int *weight_code, ++ int rounding) ++{ ++ unsigned int y, x = 0; ++ /* search incrementing 'x' until: ++ * weight < 2^(x+1) ++ * n/d < 2^(x+1) ++ * n < d * 2^(x+1) ++ */ ++ while ((x < 8) && (numerator >= (denominator << (x + 1)))) ++ x++; ++ if (x >= 8) ++ return -ERANGE; ++ /* because of the subtraction, use '-rounding' */ ++ y = 64 - ROUNDING(denominator << (x + 6), numerator, -rounding); ++ if (y >= 32) ++ return -ERANGE; ++ *weight_code = QM_WBFS_MAKECODE(x, y); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_ratio2wbfs); ++ ++int qman_ceetm_cq_get_dequeue_statistics(struct qm_ceetm_cq *cq, u32 flags, ++ u64 *frame_count, u64 *byte_count) ++{ ++ struct qm_mcr_ceetm_statistics_query result; ++ u16 cid, command_type; ++ enum qm_dc_portal dcp_idx; ++ int ret; ++ ++ cid = (cq->parent->idx << 4) | cq->idx; ++ dcp_idx = cq->parent->dcp_idx; ++ if (flags == QMAN_CEETM_FLAG_CLEAR_STATISTICS_COUNTER) ++ command_type = CEETM_QUERY_DEQUEUE_CLEAR_STATISTICS; ++ else ++ command_type = CEETM_QUERY_DEQUEUE_STATISTICS; ++ ++ ret = qman_ceetm_query_statistics(cid, dcp_idx, command_type, &result); ++ if (ret) { ++ pr_err("Can't query the statistics of CQ#%d!\n", cq->idx); ++ return -EINVAL; ++ } ++ ++ *frame_count = result.frm_cnt; ++ *byte_count = result.byte_cnt; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cq_get_dequeue_statistics); ++ ++#define CEETM_LFQMT_LFQID_MSB 0xF00000 ++#define CEETM_LFQMT_LFQID_LSB 0x000FFF ++int qman_ceetm_lfq_claim(struct qm_ceetm_lfq **lfq, ++ struct qm_ceetm_cq *cq) ++{ ++ struct qm_ceetm_lfq *p; ++ u32 lfqid; ++ int ret = 0; ++ struct qm_mcc_ceetm_lfqmt_config lfqmt_config; ++ ++ if (cq->parent->dcp_idx == qm_dc_portal_fman0) ++ ret = qman_alloc_ceetm0_lfqid(&lfqid); ++ if (cq->parent->dcp_idx == qm_dc_portal_fman1) ++ ret = qman_alloc_ceetm1_lfqid(&lfqid); ++ if (ret) { ++ pr_err("There is no lfqid avalaible for CQ#%d!\n", cq->idx); ++ return -ENODEV; ++ } ++ p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) ++ return -ENOMEM; ++ p->idx = lfqid; ++ p->dctidx = (u16)(lfqid & CEETM_LFQMT_LFQID_LSB); ++ p->parent = cq->parent; ++ list_add_tail(&p->node, &cq->bound_lfqids); ++ ++ lfqmt_config.lfqid = CEETM_LFQMT_LFQID_MSB | ++ (cq->parent->dcp_idx << 16) | ++ (lfqid & CEETM_LFQMT_LFQID_LSB); ++ lfqmt_config.cqid = (cq->parent->idx << 4) | (cq->idx); ++ lfqmt_config.dctidx = p->dctidx; ++ if (qman_ceetm_configure_lfqmt(&lfqmt_config)) { ++ pr_err("Can't configure LFQMT for LFQID#%d @ CQ#%d\n", ++ lfqid, cq->idx); ++ return -EINVAL; ++ } ++ *lfq = p; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lfq_claim); ++ ++int qman_ceetm_lfq_release(struct qm_ceetm_lfq *lfq) ++{ ++ if (lfq->parent->dcp_idx == qm_dc_portal_fman0) ++ qman_release_ceetm0_lfqid(lfq->idx); ++ if (lfq->parent->dcp_idx == qm_dc_portal_fman1) ++ qman_release_ceetm1_lfqid(lfq->idx); ++ list_del(&lfq->node); ++ kfree(lfq); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lfq_release); ++ ++int qman_ceetm_lfq_set_context(struct qm_ceetm_lfq *lfq, u64 context_a, ++ u32 context_b) ++{ ++ struct qm_mcc_ceetm_dct_config dct_config; ++ lfq->context_a = context_a; ++ lfq->context_b = context_b; ++ dct_config.dctidx = (u16)lfq->dctidx; ++ dct_config.dcpid = lfq->parent->dcp_idx; ++ dct_config.context_b = context_b; ++ dct_config.context_a = context_a; ++ return qman_ceetm_configure_dct(&dct_config); ++} ++EXPORT_SYMBOL(qman_ceetm_lfq_set_context); ++ ++int qman_ceetm_lfq_get_context(struct qm_ceetm_lfq *lfq, u64 *context_a, ++ u32 *context_b) ++{ ++ struct qm_mcc_ceetm_dct_query dct_query; ++ struct qm_mcr_ceetm_dct_query query_result; ++ ++ dct_query.dctidx = (u16)lfq->dctidx; ++ dct_query.dcpid = lfq->parent->dcp_idx; ++ if (qman_ceetm_query_dct(&dct_query, &query_result)) { ++ pr_err("Can't query LFQID#%d's context!\n", lfq->idx); ++ return -EINVAL; ++ } ++ *context_a = query_result.context_a; ++ *context_b = query_result.context_b; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lfq_get_context); ++ ++int qman_ceetm_create_fq(struct qm_ceetm_lfq *lfq, struct qman_fq *fq) ++{ ++ spin_lock_init(&fq->fqlock); ++ fq->fqid = lfq->idx; ++ fq->flags = QMAN_FQ_FLAG_NO_MODIFY; ++ if (lfq->ern) ++ fq->cb.ern = lfq->ern; ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ if (unlikely(find_empty_fq_table_entry(&fq->key, fq))) ++ return -ENOMEM; ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_create_fq); ++ ++int qman_ceetm_ccg_claim(struct qm_ceetm_ccg **ccg, ++ struct qm_ceetm_channel *channel, ++ unsigned int idx, ++ void (*cscn)(struct qm_ceetm_ccg *, ++ void *cb_ctx, ++ int congested), ++ void *cb_ctx) ++{ ++ struct qm_ceetm_ccg *p; ++ ++ if ((idx < 0) || (idx > 15)) { ++ pr_err("The given ccg index is out of range\n"); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(p, &channel->ccgs, node) { ++ if (p->idx == idx) { ++ pr_err("The CCG#%d has been claimed\n", idx); ++ return -EINVAL; ++ } ++ } ++ ++ p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) { ++ pr_err("Can't allocate memory for CCG#%d!\n", idx); ++ return -ENOMEM; ++ } ++ ++ list_add_tail(&p->node, &channel->ccgs); ++ ++ p->idx = idx; ++ p->parent = channel; ++ p->cb = cscn; ++ p->cb_ctx = cb_ctx; ++ ++ *ccg = p; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_ccg_claim); ++ ++int qman_ceetm_ccg_release(struct qm_ceetm_ccg *ccg) ++{ ++ list_del(&ccg->node); ++ kfree(ccg); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_ccg_release); ++ ++int qman_ceetm_ccg_set(struct qm_ceetm_ccg *ccg, u16 we_mask, ++ const struct qm_ceetm_ccg_params *params) ++{ ++ struct qm_mcc_ceetm_ccgr_config config_opts; ++ ++ config_opts.ccgrid = CEETM_CCGR_CM_CONFIGURE | ++ (ccg->parent->idx << 4) | ccg->idx; ++ config_opts.dcpid = ccg->parent->dcp_idx; ++ config_opts.we_mask = we_mask; ++ config_opts.cm_config.ctl = (params->wr_en_g << 6) | ++ (params->wr_en_y << 5) | ++ (params->wr_en_r << 4) | ++ (params->td_en << 3) | ++ (params->td_mode << 2) | ++ (params->cscn_en << 1) | ++ (params->mode); ++ config_opts.cm_config.oal = params->oal; ++ config_opts.cm_config.cs_thres = params->cs_thres_in; ++ config_opts.cm_config.cs_thres_x = params->cs_thres_out; ++ config_opts.cm_config.td_thres = params->td_thres; ++ config_opts.cm_config.wr_parm_g = params->wr_parm_g; ++ config_opts.cm_config.wr_parm_y = params->wr_parm_y; ++ config_opts.cm_config.wr_parm_r = params->wr_parm_r; ++ ++ return qman_ceetm_configure_ccgr(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_ccg_set); ++ ++#define CEETM_CCGR_CTL_MASK 0x01 ++int qman_ceetm_ccg_get(struct qm_ceetm_ccg *ccg, ++ struct qm_ceetm_ccg_params *params) ++{ ++ struct qm_mcc_ceetm_ccgr_query query_opts; ++ struct qm_mcr_ceetm_ccgr_query query_result; ++ ++ query_opts.ccgrid = CEETM_CCGR_CM_QUERY | ++ (ccg->parent->idx << 4) | ccg->idx; ++ query_opts.dcpid = ccg->parent->dcp_idx; ++ ++ if (qman_ceetm_query_ccgr(&query_opts, &query_result)) { ++ pr_err("Can't query CCGR#%d\n", ccg->idx); ++ return -EINVAL; ++ } ++ ++ params->wr_parm_r = query_result.cm_query.wr_parm_r; ++ params->wr_parm_y = query_result.cm_query.wr_parm_y; ++ params->wr_parm_g = query_result.cm_query.wr_parm_g; ++ params->td_thres = query_result.cm_query.td_thres; ++ params->cs_thres_out = query_result.cm_query.cs_thres_x; ++ params->cs_thres_in = query_result.cm_query.cs_thres; ++ params->oal = query_result.cm_query.oal; ++ params->wr_en_g = (query_result.cm_query.ctl >> 6) & ++ CEETM_CCGR_CTL_MASK; ++ params->wr_en_y = (query_result.cm_query.ctl >> 5) & ++ CEETM_CCGR_CTL_MASK; ++ params->wr_en_r = (query_result.cm_query.ctl >> 4) & ++ CEETM_CCGR_CTL_MASK; ++ params->td_en = (query_result.cm_query.ctl >> 3) & ++ CEETM_CCGR_CTL_MASK; ++ params->td_mode = (query_result.cm_query.ctl >> 2) & ++ CEETM_CCGR_CTL_MASK; ++ params->cscn_en = (query_result.cm_query.ctl >> 1) & ++ CEETM_CCGR_CTL_MASK; ++ params->mode = (query_result.cm_query.ctl & CEETM_CCGR_CTL_MASK); ++ ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_ccg_get); ++ ++int qman_ceetm_ccg_get_reject_statistics(struct qm_ceetm_ccg *ccg, u32 flags, ++ u64 *frame_count, u64 *byte_count) ++{ ++ struct qm_mcr_ceetm_statistics_query result; ++ u16 cid, command_type; ++ enum qm_dc_portal dcp_idx; ++ int ret; ++ ++ cid = (ccg->parent->idx << 4) | ccg->idx; ++ dcp_idx = ccg->parent->dcp_idx; ++ if (flags == QMAN_CEETM_FLAG_CLEAR_STATISTICS_COUNTER) ++ command_type = CEETM_QUERY_REJECT_CLEAR_STATISTICS; ++ else ++ command_type = CEETM_QUERY_REJECT_STATISTICS; ++ ++ ret = qman_ceetm_query_statistics(cid, dcp_idx, command_type, &result); ++ if (ret) { ++ pr_err("Can't query the statistics of CCG#%d!\n", ccg->idx); ++ return -EINVAL; ++ } ++ ++ *frame_count = result.frm_cnt; ++ *byte_count = result.byte_cnt; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_ccg_get_reject_statistics); ++ ++#define CEETM_CSCN_TARG_SWP 0 ++#define CEETM_CSCN_TARG_DCP 1 ++int qman_ceetm_cscn_swp_set(struct qm_ceetm_ccg *ccg, ++ u16 swp_idx, ++ unsigned int cscn_enabled, ++ u16 we_mask, ++ const struct qm_ceetm_ccg_params *params) ++{ ++ struct qm_mcc_ceetm_ccgr_config config_opts; ++ int ret; ++ ++ config_opts.ccgrid = CEETM_CCGR_CM_CONFIGURE | ++ (ccg->parent->idx << 4) | ccg->idx; ++ config_opts.dcpid = ccg->parent->dcp_idx; ++ config_opts.we_mask = we_mask | QM_CCGR_WE_CSCN_TUPD; ++ config_opts.cm_config.cscn_tupd = (cscn_enabled << 15) | ++ (CEETM_CSCN_TARG_SWP << 14) | ++ swp_idx; ++ config_opts.cm_config.ctl = (params->wr_en_g << 6) | ++ (params->wr_en_y << 5) | ++ (params->wr_en_r << 4) | ++ (params->td_en << 3) | ++ (params->td_mode << 2) | ++ (params->cscn_en << 1) | ++ (params->mode); ++ config_opts.cm_config.cs_thres = params->cs_thres_in; ++ config_opts.cm_config.cs_thres_x = params->cs_thres_out; ++ config_opts.cm_config.td_thres = params->td_thres; ++ config_opts.cm_config.wr_parm_g = params->wr_parm_g; ++ config_opts.cm_config.wr_parm_y = params->wr_parm_y; ++ config_opts.cm_config.wr_parm_r = params->wr_parm_r; ++ ++ ret = qman_ceetm_configure_ccgr(&config_opts); ++ if (ret) { ++ pr_err("Configure CSCN_TARG_SWP failed!\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cscn_swp_set); ++ ++int qman_ceetm_cscn_swp_get(struct qm_ceetm_ccg *ccg, ++ u16 swp_idx, ++ unsigned int *cscn_enabled) ++{ ++ struct qm_mcc_ceetm_ccgr_query query_opts; ++ struct qm_mcr_ceetm_ccgr_query query_result; ++ ++ query_opts.ccgrid = CEETM_CCGR_CM_QUERY | ++ (ccg->parent->idx << 4) | ccg->idx; ++ query_opts.dcpid = ccg->parent->dcp_idx; ++ ++ if (qman_ceetm_query_ccgr(&query_opts, &query_result)) { ++ pr_err("Can't query CCGR#%d\n", ccg->idx); ++ return -EINVAL; ++ } ++ ++ if (swp_idx < 63) ++ *cscn_enabled = (query_result.cm_query.cscn_targ_swp[0] >> ++ (63 - swp_idx)) & 0x1; ++ else ++ *cscn_enabled = (query_result.cm_query.cscn_targ_swp[1] >> ++ (127 - swp_idx)) & 0x1; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cscn_swp_get); ++ ++int qman_ceetm_cscn_dcp_set(struct qm_ceetm_ccg *ccg, ++ u16 dcp_idx, ++ u8 vcgid, ++ unsigned int cscn_enabled, ++ u16 we_mask, ++ const struct qm_ceetm_ccg_params *params) ++{ ++ struct qm_mcc_ceetm_ccgr_config config_opts; ++ int ret; ++ ++ config_opts.ccgrid = CEETM_CCGR_CM_CONFIGURE | ++ (ccg->parent->idx << 4) | ccg->idx; ++ config_opts.dcpid = ccg->parent->dcp_idx; ++ config_opts.we_mask = we_mask | QM_CCGR_WE_CSCN_TUPD | QM_CCGR_WE_CDV; ++ config_opts.cm_config.cdv = vcgid; ++ config_opts.cm_config.cscn_tupd = (cscn_enabled << 15) | ++ (CEETM_CSCN_TARG_DCP << 14) | ++ dcp_idx; ++ config_opts.cm_config.ctl = (params->wr_en_g << 6) | ++ (params->wr_en_y << 5) | ++ (params->wr_en_r << 4) | ++ (params->td_en << 3) | ++ (params->td_mode << 2) | ++ (params->cscn_en << 1) | ++ (params->mode); ++ config_opts.cm_config.cs_thres = params->cs_thres_in; ++ config_opts.cm_config.cs_thres_x = params->cs_thres_out; ++ config_opts.cm_config.td_thres = params->td_thres; ++ config_opts.cm_config.wr_parm_g = params->wr_parm_g; ++ config_opts.cm_config.wr_parm_y = params->wr_parm_y; ++ config_opts.cm_config.wr_parm_r = params->wr_parm_r; ++ ++ ret = qman_ceetm_configure_ccgr(&config_opts); ++ if (ret) { ++ pr_err("Configure CSCN_TARG_DCP failed!\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cscn_dcp_set); ++ ++int qman_ceetm_cscn_dcp_get(struct qm_ceetm_ccg *ccg, ++ u16 dcp_idx, ++ u8 *vcgid, ++ unsigned int *cscn_enabled) ++{ ++ struct qm_mcc_ceetm_ccgr_query query_opts; ++ struct qm_mcr_ceetm_ccgr_query query_result; ++ ++ query_opts.ccgrid = CEETM_CCGR_CM_QUERY | ++ (ccg->parent->idx << 4) | ccg->idx; ++ query_opts.dcpid = ccg->parent->dcp_idx; ++ ++ if (qman_ceetm_query_ccgr(&query_opts, &query_result)) { ++ pr_err("Can't query CCGR#%d\n", ccg->idx); ++ return -EINVAL; ++ } ++ ++ *vcgid = query_result.cm_query.cdv; ++ *cscn_enabled = (query_result.cm_query.cscn_targ_dcp >> ++ (7 - dcp_idx)) & 0x1; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cscn_dcp_get); ++ ++int qman_ceetm_querycongestion(u16 *ccg_state, unsigned int dcp_idx) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ int i, j; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ for (i = 0; i < 1 ; i++) { ++ mcc->ccgr_query.ccgrid = i; ++ mcc->ccgr_query.dcpid = dcp_idx; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CCGR_QUERY); ++ ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_CCGR_QUERY); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) { ++ for (j = 0; j < 16; j++) ++ *(ccg_state + j) = ++ mcr->ccgr_query.congestion_state.ccg_state[j]; ++ } else { ++ pr_err("QUERY CEETM CONGESTION STATE failed\n"); ++ return -EIO; ++ } ++ } ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return 0; ++} ++ ++int qman_set_wpm(int wpm_enable) ++{ ++ return qm_set_wpm(wpm_enable); ++} ++EXPORT_SYMBOL(qman_set_wpm); ++ ++int qman_get_wpm(int *wpm_enable) ++{ ++ return qm_get_wpm(wpm_enable); ++} ++EXPORT_SYMBOL(qman_get_wpm); +diff --git a/drivers/staging/fsl_qbman/qman_low.h b/drivers/staging/fsl_qbman/qman_low.h +new file mode 100644 +index 0000000..d517af5 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_low.h +@@ -0,0 +1,1171 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "qman_private.h" ++ ++/***************************/ ++/* Portal register assists */ ++/***************************/ ++ ++/* Cache-inhibited register offsets */ ++#define REG_EQCR_PI_CINH 0x0000 ++#define REG_EQCR_CI_CINH 0x0004 ++#define REG_EQCR_ITR 0x0008 ++#define REG_DQRR_PI_CINH 0x0040 ++#define REG_DQRR_CI_CINH 0x0044 ++#define REG_DQRR_ITR 0x0048 ++#define REG_DQRR_DCAP 0x0050 ++#define REG_DQRR_SDQCR 0x0054 ++#define REG_DQRR_VDQCR 0x0058 ++#define REG_DQRR_PDQCR 0x005c ++#define REG_MR_PI_CINH 0x0080 ++#define REG_MR_CI_CINH 0x0084 ++#define REG_MR_ITR 0x0088 ++#define REG_CFG 0x0100 ++#define REG_ISR 0x0e00 ++#define REG_ITPR 0x0e14 ++ ++/* Cache-enabled register offsets */ ++#define CL_EQCR 0x0000 ++#define CL_DQRR 0x1000 ++#define CL_MR 0x2000 ++#define CL_EQCR_PI_CENA 0x3000 ++#define CL_EQCR_CI_CENA 0x3100 ++#define CL_DQRR_PI_CENA 0x3200 ++#define CL_DQRR_CI_CENA 0x3300 ++#define CL_MR_PI_CENA 0x3400 ++#define CL_MR_CI_CENA 0x3500 ++#define CL_CR 0x3800 ++#define CL_RR0 0x3900 ++#define CL_RR1 0x3940 ++ ++/* BTW, the drivers (and h/w programming model) already obtain the required ++ * synchronisation for portal accesses via lwsync(), hwsync(), and ++ * data-dependencies. Use of barrier()s or other order-preserving primitives ++ * simply degrade performance. Hence the use of the __raw_*() interfaces, which ++ * simply ensure that the compiler treats the portal registers as volatile (ie. ++ * non-coherent). */ ++ ++/* Cache-inhibited register access. */ ++#define __qm_in(qm, o) __raw_readl((qm)->addr_ci + (o)) ++#define __qm_out(qm, o, val) __raw_writel((val), (qm)->addr_ci + (o)) ++#define qm_in(reg) __qm_in(&portal->addr, REG_##reg) ++#define qm_out(reg, val) __qm_out(&portal->addr, REG_##reg, val) ++ ++/* Cache-enabled (index) register access */ ++#define __qm_cl_touch_ro(qm, o) dcbt_ro((qm)->addr_ce + (o)) ++#define __qm_cl_touch_rw(qm, o) dcbt_rw((qm)->addr_ce + (o)) ++#define __qm_cl_in(qm, o) __raw_readl((qm)->addr_ce + (o)) ++#define __qm_cl_out(qm, o, val) \ ++ do { \ ++ u32 *__tmpclout = (qm)->addr_ce + (o); \ ++ __raw_writel((val), __tmpclout); \ ++ dcbf(__tmpclout); \ ++ } while (0) ++#define __qm_cl_invalidate(qm, o) dcbi((qm)->addr_ce + (o)) ++#define qm_cl_touch_ro(reg) __qm_cl_touch_ro(&portal->addr, CL_##reg##_CENA) ++#define qm_cl_touch_rw(reg) __qm_cl_touch_rw(&portal->addr, CL_##reg##_CENA) ++#define qm_cl_in(reg) __qm_cl_in(&portal->addr, CL_##reg##_CENA) ++#define qm_cl_out(reg, val) __qm_cl_out(&portal->addr, CL_##reg##_CENA, val) ++#define qm_cl_invalidate(reg) __qm_cl_invalidate(&portal->addr, CL_##reg##_CENA) ++ ++/* Cache-enabled ring access */ ++#define qm_cl(base, idx) ((void *)base + ((idx) << 6)) ++ ++/* Cyclic helper for rings. FIXME: once we are able to do fine-grain perf ++ * analysis, look at using the "extra" bit in the ring index registers to avoid ++ * cyclic issues. */ ++static inline u8 cyc_diff(u8 ringsize, u8 first, u8 last) ++{ ++ /* 'first' is included, 'last' is excluded */ ++ if (first <= last) ++ return last - first; ++ return ringsize + last - first; ++} ++ ++/* Portal modes. ++ * Enum types; ++ * pmode == production mode ++ * cmode == consumption mode, ++ * dmode == h/w dequeue mode. ++ * Enum values use 3 letter codes. First letter matches the portal mode, ++ * remaining two letters indicate; ++ * ci == cache-inhibited portal register ++ * ce == cache-enabled portal register ++ * vb == in-band valid-bit (cache-enabled) ++ * dc == DCA (Discrete Consumption Acknowledgement), DQRR-only ++ * As for "enum qm_dqrr_dmode", it should be self-explanatory. ++ */ ++enum qm_eqcr_pmode { /* matches QCSP_CFG::EPM */ ++ qm_eqcr_pci = 0, /* PI index, cache-inhibited */ ++ qm_eqcr_pce = 1, /* PI index, cache-enabled */ ++ qm_eqcr_pvb = 2 /* valid-bit */ ++}; ++enum qm_eqcr_cmode { /* s/w-only */ ++ qm_eqcr_cci, /* CI index, cache-inhibited */ ++ qm_eqcr_cce /* CI index, cache-enabled */ ++}; ++enum qm_dqrr_dmode { /* matches QCSP_CFG::DP */ ++ qm_dqrr_dpush = 0, /* SDQCR + VDQCR */ ++ qm_dqrr_dpull = 1 /* PDQCR */ ++}; ++enum qm_dqrr_pmode { /* s/w-only */ ++ qm_dqrr_pci, /* reads DQRR_PI_CINH */ ++ qm_dqrr_pce, /* reads DQRR_PI_CENA */ ++ qm_dqrr_pvb /* reads valid-bit */ ++}; ++enum qm_dqrr_cmode { /* matches QCSP_CFG::DCM */ ++ qm_dqrr_cci = 0, /* CI index, cache-inhibited */ ++ qm_dqrr_cce = 1, /* CI index, cache-enabled */ ++ qm_dqrr_cdc = 2 /* Discrete Consumption Acknowledgement */ ++}; ++enum qm_mr_pmode { /* s/w-only */ ++ qm_mr_pci, /* reads MR_PI_CINH */ ++ qm_mr_pce, /* reads MR_PI_CENA */ ++ qm_mr_pvb /* reads valid-bit */ ++}; ++enum qm_mr_cmode { /* matches QCSP_CFG::MM */ ++ qm_mr_cci = 0, /* CI index, cache-inhibited */ ++ qm_mr_cce = 1 /* CI index, cache-enabled */ ++}; ++ ++ ++/* ------------------------- */ ++/* --- Portal structures --- */ ++ ++#define QM_EQCR_SIZE 8 ++#define QM_DQRR_SIZE 16 ++#define QM_MR_SIZE 8 ++ ++struct qm_eqcr { ++ struct qm_eqcr_entry *ring, *cursor; ++ u8 ci, available, ithresh, vbit; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ u32 busy; ++ enum qm_eqcr_pmode pmode; ++ enum qm_eqcr_cmode cmode; ++#endif ++}; ++ ++struct qm_dqrr { ++ const struct qm_dqrr_entry *ring, *cursor; ++ u8 pi, ci, fill, ithresh, vbit; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ enum qm_dqrr_dmode dmode; ++ enum qm_dqrr_pmode pmode; ++ enum qm_dqrr_cmode cmode; ++#endif ++}; ++ ++struct qm_mr { ++ const struct qm_mr_entry *ring, *cursor; ++ u8 pi, ci, fill, ithresh, vbit; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ enum qm_mr_pmode pmode; ++ enum qm_mr_cmode cmode; ++#endif ++}; ++ ++struct qm_mc { ++ struct qm_mc_command *cr; ++ struct qm_mc_result *rr; ++ u8 rridx, vbit; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ enum { ++ /* Can be _mc_start()ed */ ++ mc_idle, ++ /* Can be _mc_commit()ed or _mc_abort()ed */ ++ mc_user, ++ /* Can only be _mc_retry()ed */ ++ mc_hw ++ } state; ++#endif ++}; ++ ++#ifdef CONFIG_FSL_QMAN_BUG_AND_FEATURE_REV1 ++/* For workarounds that require storage. The struct alignment is required for ++ * cases where operations on "shadow" structs need the same alignment as is ++ * present on the corresponding h/w data structs (specifically, there is a ++ * zero-bit present above the range required to address the ring, so that ++ * iteration can be achieved by incrementing a ring pointer and clearing the ++ * carry-bit). The "portal" struct needs the same alignment because this type ++ * goes at its head, so it has a more radical alignment requirement if this ++ * structure is used. (NB: "64" instead of "L1_CACHE_BYTES", because this ++ * alignment relates to the h/w interface, not the CPU cache granularity!)*/ ++#define QM_PORTAL_ALIGNMENT __attribute__((aligned(32 * 64))) ++struct qm_portal_bugs { ++ /* shadow MR ring, for QMAN9 workaround, 8-CL-aligned */ ++ struct qm_mr_entry mr[QM_MR_SIZE]; ++ /* shadow MC result, for QMAN6 and QMAN7 workarounds, CL-aligned */ ++ struct qm_mc_result result; ++ /* boolean switch for QMAN7 workaround */ ++ int initfq_and_sched; ++} QM_PORTAL_ALIGNMENT; ++#else ++#define QM_PORTAL_ALIGNMENT ____cacheline_aligned ++#endif ++ ++struct qm_addr { ++ void __iomem *addr_ce; /* cache-enabled */ ++ void __iomem *addr_ci; /* cache-inhibited */ ++}; ++ ++struct qm_portal { ++#ifdef CONFIG_FSL_QMAN_BUG_AND_FEATURE_REV1 ++ struct qm_portal_bugs bugs; ++#endif ++ /* In the non-CONFIG_FSL_DPA_CHECKING case, the following stuff up to ++ * and including 'mc' fits within a cacheline (yay!). The 'config' part ++ * is setup-only, so isn't a cause for a concern. In other words, don't ++ * rearrange this structure on a whim, there be dragons ... */ ++ struct qm_addr addr; ++ struct qm_eqcr eqcr; ++ struct qm_dqrr dqrr; ++ struct qm_mr mr; ++ struct qm_mc mc; ++} QM_PORTAL_ALIGNMENT; ++ ++ ++/* ---------------- */ ++/* --- EQCR API --- */ ++ ++/* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */ ++#define EQCR_CARRYCLEAR(p) \ ++ (void *)((unsigned long)(p) & (~(unsigned long)(QM_EQCR_SIZE << 6))) ++ ++/* Bit-wise logic to convert a ring pointer to a ring index */ ++static inline u8 EQCR_PTR2IDX(struct qm_eqcr_entry *e) ++{ ++ return ((uintptr_t)e >> 6) & (QM_EQCR_SIZE - 1); ++} ++ ++/* Increment the 'cursor' ring pointer, taking 'vbit' into account */ ++static inline void EQCR_INC(struct qm_eqcr *eqcr) ++{ ++ /* NB: this is odd-looking, but experiments show that it generates fast ++ * code with essentially no branching overheads. We increment to the ++ * next EQCR pointer and handle overflow and 'vbit'. */ ++ struct qm_eqcr_entry *partial = eqcr->cursor + 1; ++ eqcr->cursor = EQCR_CARRYCLEAR(partial); ++ if (partial != eqcr->cursor) ++ eqcr->vbit ^= QM_EQCR_VERB_VBIT; ++} ++ ++static inline int qm_eqcr_init(struct qm_portal *portal, ++ enum qm_eqcr_pmode pmode, ++ __maybe_unused enum qm_eqcr_cmode cmode) ++{ ++ /* This use of 'register', as well as all other occurances, is because ++ * it has been observed to generate much faster code with gcc than is ++ * otherwise the case. */ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ u32 cfg; ++ u8 pi; ++ ++ eqcr->ring = portal->addr.addr_ce + CL_EQCR; ++ eqcr->ci = qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1); ++ qm_cl_invalidate(EQCR_CI); ++ pi = qm_in(EQCR_PI_CINH) & (QM_EQCR_SIZE - 1); ++ eqcr->cursor = eqcr->ring + pi; ++ eqcr->vbit = (qm_in(EQCR_PI_CINH) & QM_EQCR_SIZE) ? ++ QM_EQCR_VERB_VBIT : 0; ++ eqcr->available = QM_EQCR_SIZE - 1 - ++ cyc_diff(QM_EQCR_SIZE, eqcr->ci, pi); ++ eqcr->ithresh = qm_in(EQCR_ITR); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 0; ++ eqcr->pmode = pmode; ++ eqcr->cmode = cmode; ++#endif ++ cfg = (qm_in(CFG) & 0x00ffffff) | ++ ((pmode & 0x3) << 24); /* QCSP_CFG::EPM */ ++ qm_out(CFG, cfg); ++ return 0; ++} ++ ++static inline void qm_eqcr_finish(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ u8 pi = qm_in(EQCR_PI_CINH) & (QM_EQCR_SIZE - 1); ++ u8 ci = qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1); ++ ++ DPA_ASSERT(!eqcr->busy); ++ if (pi != EQCR_PTR2IDX(eqcr->cursor)) ++ pr_crit("losing uncommited EQCR entries\n"); ++ if (ci != eqcr->ci) ++ pr_crit("missing existing EQCR completions\n"); ++ if (eqcr->ci != EQCR_PTR2IDX(eqcr->cursor)) ++ pr_crit("EQCR destroyed unquiesced\n"); ++} ++ ++static inline struct qm_eqcr_entry *qm_eqcr_start(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ DPA_ASSERT(!eqcr->busy); ++ if (!eqcr->available) ++ return NULL; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 1; ++#endif ++ dcbz_64(eqcr->cursor); ++ return eqcr->cursor; ++} ++ ++static inline void qm_eqcr_abort(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr; ++ DPA_ASSERT(eqcr->busy); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 0; ++#endif ++} ++ ++static inline struct qm_eqcr_entry *qm_eqcr_pend_and_next( ++ struct qm_portal *portal, u8 myverb) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ DPA_ASSERT(eqcr->busy); ++ DPA_ASSERT(eqcr->pmode != qm_eqcr_pvb); ++ if (eqcr->available == 1) ++ return NULL; ++ eqcr->cursor->__dont_write_directly__verb = myverb | eqcr->vbit; ++ dcbf(eqcr->cursor); ++ EQCR_INC(eqcr); ++ eqcr->available--; ++ dcbz_64(eqcr->cursor); ++ return eqcr->cursor; ++} ++ ++#define EQCR_COMMIT_CHECKS(eqcr) \ ++do { \ ++ DPA_ASSERT(eqcr->busy); \ ++ DPA_ASSERT(eqcr->cursor->orp == (eqcr->cursor->orp & 0x00ffffff)); \ ++ DPA_ASSERT(eqcr->cursor->fqid == (eqcr->cursor->fqid & 0x00ffffff)); \ ++} while(0) ++ ++static inline void qm_eqcr_pci_commit(struct qm_portal *portal, u8 myverb) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ EQCR_COMMIT_CHECKS(eqcr); ++ DPA_ASSERT(eqcr->pmode == qm_eqcr_pci); ++ eqcr->cursor->__dont_write_directly__verb = myverb | eqcr->vbit; ++ EQCR_INC(eqcr); ++ eqcr->available--; ++ dcbf(eqcr->cursor); ++ hwsync(); ++ qm_out(EQCR_PI_CINH, EQCR_PTR2IDX(eqcr->cursor)); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 0; ++#endif ++} ++ ++static inline void qm_eqcr_pce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr; ++ DPA_ASSERT(eqcr->pmode == qm_eqcr_pce); ++ qm_cl_invalidate(EQCR_PI); ++ qm_cl_touch_rw(EQCR_PI); ++} ++ ++static inline void qm_eqcr_pce_commit(struct qm_portal *portal, u8 myverb) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ EQCR_COMMIT_CHECKS(eqcr); ++ DPA_ASSERT(eqcr->pmode == qm_eqcr_pce); ++ eqcr->cursor->__dont_write_directly__verb = myverb | eqcr->vbit; ++ EQCR_INC(eqcr); ++ eqcr->available--; ++ dcbf(eqcr->cursor); ++ lwsync(); ++ qm_cl_out(EQCR_PI, EQCR_PTR2IDX(eqcr->cursor)); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 0; ++#endif ++} ++ ++static inline void qm_eqcr_pvb_commit(struct qm_portal *portal, u8 myverb) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ struct qm_eqcr_entry *eqcursor; ++ EQCR_COMMIT_CHECKS(eqcr); ++ DPA_ASSERT(eqcr->pmode == qm_eqcr_pvb); ++ lwsync(); ++ eqcursor = eqcr->cursor; ++ eqcursor->__dont_write_directly__verb = myverb | eqcr->vbit; ++ dcbf(eqcursor); ++ EQCR_INC(eqcr); ++ eqcr->available--; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 0; ++#endif ++} ++ ++static inline u8 qm_eqcr_cci_update(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ u8 diff, old_ci = eqcr->ci; ++ DPA_ASSERT(eqcr->cmode == qm_eqcr_cci); ++ eqcr->ci = qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1); ++ diff = cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci); ++ eqcr->available += diff; ++ return diff; ++} ++ ++static inline void qm_eqcr_cce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr; ++ DPA_ASSERT(eqcr->cmode == qm_eqcr_cce); ++ qm_cl_touch_ro(EQCR_CI); ++} ++ ++static inline u8 qm_eqcr_cce_update(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ u8 diff, old_ci = eqcr->ci; ++ DPA_ASSERT(eqcr->cmode == qm_eqcr_cce); ++ eqcr->ci = qm_cl_in(EQCR_CI) & (QM_EQCR_SIZE - 1); ++ qm_cl_invalidate(EQCR_CI); ++ diff = cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci); ++ eqcr->available += diff; ++ return diff; ++} ++ ++static inline u8 qm_eqcr_get_ithresh(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ return eqcr->ithresh; ++} ++ ++static inline void qm_eqcr_set_ithresh(struct qm_portal *portal, u8 ithresh) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ eqcr->ithresh = ithresh; ++ qm_out(EQCR_ITR, ithresh); ++} ++ ++static inline u8 qm_eqcr_get_avail(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ return eqcr->available; ++} ++ ++static inline u8 qm_eqcr_get_fill(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ return QM_EQCR_SIZE - 1 - eqcr->available; ++} ++ ++ ++/* ---------------- */ ++/* --- DQRR API --- */ ++ ++/* FIXME: many possible improvements; ++ * - look at changing the API to use pointer rather than index parameters now ++ * that 'cursor' is a pointer, ++ * - consider moving other parameters to pointer if it could help (ci) ++ */ ++ ++#define DQRR_CARRYCLEAR(p) \ ++ (void *)((unsigned long)(p) & (~(unsigned long)(QM_DQRR_SIZE << 6))) ++ ++static inline u8 DQRR_PTR2IDX(const struct qm_dqrr_entry *e) ++{ ++ return ((uintptr_t)e >> 6) & (QM_DQRR_SIZE - 1); ++} ++ ++static inline const struct qm_dqrr_entry *DQRR_INC( ++ const struct qm_dqrr_entry *e) ++{ ++ return DQRR_CARRYCLEAR(e + 1); ++} ++ ++static inline void qm_dqrr_set_maxfill(struct qm_portal *portal, u8 mf) ++{ ++ qm_out(CFG, (qm_in(CFG) & 0xff0fffff) | ++ ((mf & (QM_DQRR_SIZE - 1)) << 20)); ++} ++ ++static inline int qm_dqrr_init(struct qm_portal *portal, ++ const struct qm_portal_config *config, ++ enum qm_dqrr_dmode dmode, ++ __maybe_unused enum qm_dqrr_pmode pmode, ++ enum qm_dqrr_cmode cmode, u8 max_fill) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ u32 cfg; ++ ++ /* Make sure the DQRR will be idle when we enable */ ++ qm_out(DQRR_SDQCR, 0); ++ qm_out(DQRR_VDQCR, 0); ++ qm_out(DQRR_PDQCR, 0); ++ dqrr->ring = portal->addr.addr_ce + CL_DQRR; ++ dqrr->pi = qm_in(DQRR_PI_CINH) & (QM_DQRR_SIZE - 1); ++ dqrr->ci = qm_in(DQRR_CI_CINH) & (QM_DQRR_SIZE - 1); ++ dqrr->cursor = dqrr->ring + dqrr->ci; ++ dqrr->fill = cyc_diff(QM_DQRR_SIZE, dqrr->ci, dqrr->pi); ++ dqrr->vbit = (qm_in(DQRR_PI_CINH) & QM_DQRR_SIZE) ? ++ QM_DQRR_VERB_VBIT : 0; ++ dqrr->ithresh = qm_in(DQRR_ITR); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ dqrr->dmode = dmode; ++ dqrr->pmode = pmode; ++ dqrr->cmode = cmode; ++#endif ++ /* Invalidate every ring entry before beginning */ ++ for (cfg = 0; cfg > QM_DQRR_SIZE; cfg++) ++ dcbi(qm_cl(dqrr->ring, cfg)); ++ cfg = (qm_in(CFG) & 0xff000f00) | ++ ((max_fill & (QM_DQRR_SIZE - 1)) << 20) | /* DQRR_MF */ ++ ((dmode & 1) << 18) | /* DP */ ++ ((cmode & 3) << 16) | /* DCM */ ++ 0xa0 | /* RE+SE */ ++ (0 ? 0x40 : 0) | /* Ignore RP */ ++ (0 ? 0x10 : 0); /* Ignore SP */ ++ qm_out(CFG, cfg); ++ qm_dqrr_set_maxfill(portal, max_fill); ++ return 0; ++} ++ ++static inline void qm_dqrr_finish(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if ((dqrr->cmode != qm_dqrr_cdc) && ++ (dqrr->ci != DQRR_PTR2IDX(dqrr->cursor))) ++ pr_crit("Ignoring completed DQRR entries\n"); ++#endif ++} ++ ++static inline const struct qm_dqrr_entry *qm_dqrr_current( ++ struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ if (!dqrr->fill) ++ return NULL; ++ return dqrr->cursor; ++} ++ ++static inline u8 qm_dqrr_cursor(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ return DQRR_PTR2IDX(dqrr->cursor); ++} ++ ++static inline u8 qm_dqrr_next(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->fill); ++ dqrr->cursor = DQRR_INC(dqrr->cursor); ++ return --dqrr->fill; ++} ++ ++static inline u8 qm_dqrr_pci_update(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ u8 diff, old_pi = dqrr->pi; ++ DPA_ASSERT(dqrr->pmode == qm_dqrr_pci); ++ dqrr->pi = qm_in(DQRR_PI_CINH) & (QM_DQRR_SIZE - 1); ++ diff = cyc_diff(QM_DQRR_SIZE, old_pi, dqrr->pi); ++ dqrr->fill += diff; ++ return diff; ++} ++ ++static inline void qm_dqrr_pce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->pmode == qm_dqrr_pce); ++ qm_cl_invalidate(DQRR_PI); ++ qm_cl_touch_ro(DQRR_PI); ++} ++ ++static inline u8 qm_dqrr_pce_update(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ u8 diff, old_pi = dqrr->pi; ++ DPA_ASSERT(dqrr->pmode == qm_dqrr_pce); ++ dqrr->pi = qm_cl_in(DQRR_PI) & (QM_DQRR_SIZE - 1); ++ diff = cyc_diff(QM_DQRR_SIZE, old_pi, dqrr->pi); ++ dqrr->fill += diff; ++ return diff; ++} ++ ++static inline void qm_dqrr_pvb_update(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ const struct qm_dqrr_entry *res = qm_cl(dqrr->ring, dqrr->pi); ++ DPA_ASSERT(dqrr->pmode == qm_dqrr_pvb); ++ /* when accessing 'verb', use __raw_readb() to ensure that compiler ++ * inlining doesn't try to optimise out "excess reads". */ ++ if ((__raw_readb(&res->verb) & QM_DQRR_VERB_VBIT) == dqrr->vbit) { ++ dqrr->pi = (dqrr->pi + 1) & (QM_DQRR_SIZE - 1); ++ if (!dqrr->pi) ++ dqrr->vbit ^= QM_DQRR_VERB_VBIT; ++ dqrr->fill++; ++ } ++} ++ ++static inline void qm_dqrr_cci_consume(struct qm_portal *portal, u8 num) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cci); ++ dqrr->ci = (dqrr->ci + num) & (QM_DQRR_SIZE - 1); ++ qm_out(DQRR_CI_CINH, dqrr->ci); ++} ++ ++static inline void qm_dqrr_cci_consume_to_current(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cci); ++ dqrr->ci = DQRR_PTR2IDX(dqrr->cursor); ++ qm_out(DQRR_CI_CINH, dqrr->ci); ++} ++ ++static inline void qm_dqrr_cce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cce); ++ qm_cl_invalidate(DQRR_CI); ++ qm_cl_touch_rw(DQRR_CI); ++} ++ ++static inline void qm_dqrr_cce_consume(struct qm_portal *portal, u8 num) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cce); ++ dqrr->ci = (dqrr->ci + num) & (QM_DQRR_SIZE - 1); ++ qm_cl_out(DQRR_CI, dqrr->ci); ++} ++ ++static inline void qm_dqrr_cce_consume_to_current(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cce); ++ dqrr->ci = DQRR_PTR2IDX(dqrr->cursor); ++ qm_cl_out(DQRR_CI, dqrr->ci); ++} ++ ++static inline void qm_dqrr_cdc_consume_1(struct qm_portal *portal, u8 idx, ++ int park) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc); ++ DPA_ASSERT(idx < QM_DQRR_SIZE); ++ qm_out(DQRR_DCAP, (0 << 8) | /* S */ ++ ((park ? 1 : 0) << 6) | /* PK */ ++ idx); /* DCAP_CI */ ++} ++ ++static inline void qm_dqrr_cdc_consume_1ptr(struct qm_portal *portal, ++ const struct qm_dqrr_entry *dq, ++ int park) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ u8 idx = DQRR_PTR2IDX(dq); ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc); ++ DPA_ASSERT((dqrr->ring + idx) == dq); ++ DPA_ASSERT(idx < QM_DQRR_SIZE); ++ qm_out(DQRR_DCAP, (0 << 8) | /* DQRR_DCAP::S */ ++ ((park ? 1 : 0) << 6) | /* DQRR_DCAP::PK */ ++ idx); /* DQRR_DCAP::DCAP_CI */ ++} ++ ++static inline void qm_dqrr_cdc_consume_n(struct qm_portal *portal, u16 bitmask) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc); ++ qm_out(DQRR_DCAP, (1 << 8) | /* DQRR_DCAP::S */ ++ ((u32)bitmask << 16)); /* DQRR_DCAP::DCAP_CI */ ++} ++ ++static inline u8 qm_dqrr_cdc_cci(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc); ++ return qm_in(DQRR_CI_CINH) & (QM_DQRR_SIZE - 1); ++} ++ ++static inline void qm_dqrr_cdc_cce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc); ++ qm_cl_invalidate(DQRR_CI); ++ qm_cl_touch_ro(DQRR_CI); ++} ++ ++static inline u8 qm_dqrr_cdc_cce(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc); ++ return qm_cl_in(DQRR_CI) & (QM_DQRR_SIZE - 1); ++} ++ ++static inline u8 qm_dqrr_get_ci(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode != qm_dqrr_cdc); ++ return dqrr->ci; ++} ++ ++static inline void qm_dqrr_park(struct qm_portal *portal, u8 idx) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode != qm_dqrr_cdc); ++ qm_out(DQRR_DCAP, (0 << 8) | /* S */ ++ (1 << 6) | /* PK */ ++ (idx & (QM_DQRR_SIZE - 1))); /* DCAP_CI */ ++} ++ ++static inline void qm_dqrr_park_current(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode != qm_dqrr_cdc); ++ qm_out(DQRR_DCAP, (0 << 8) | /* S */ ++ (1 << 6) | /* PK */ ++ DQRR_PTR2IDX(dqrr->cursor)); /* DCAP_CI */ ++} ++ ++static inline void qm_dqrr_sdqcr_set(struct qm_portal *portal, u32 sdqcr) ++{ ++ qm_out(DQRR_SDQCR, sdqcr); ++} ++ ++static inline u32 qm_dqrr_sdqcr_get(struct qm_portal *portal) ++{ ++ return qm_in(DQRR_SDQCR); ++} ++ ++static inline void qm_dqrr_vdqcr_set(struct qm_portal *portal, u32 vdqcr) ++{ ++ qm_out(DQRR_VDQCR, vdqcr); ++} ++ ++static inline u32 qm_dqrr_vdqcr_get(struct qm_portal *portal) ++{ ++ return qm_in(DQRR_VDQCR); ++} ++ ++static inline void qm_dqrr_pdqcr_set(struct qm_portal *portal, u32 pdqcr) ++{ ++ qm_out(DQRR_PDQCR, pdqcr); ++} ++ ++static inline u32 qm_dqrr_pdqcr_get(struct qm_portal *portal) ++{ ++ return qm_in(DQRR_PDQCR); ++} ++ ++static inline u8 qm_dqrr_get_ithresh(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ return dqrr->ithresh; ++} ++ ++static inline void qm_dqrr_set_ithresh(struct qm_portal *portal, u8 ithresh) ++{ ++ qm_out(DQRR_ITR, ithresh); ++} ++ ++static inline u8 qm_dqrr_get_maxfill(struct qm_portal *portal) ++{ ++ return (qm_in(CFG) & 0x00f00000) >> 20; ++} ++ ++ ++/* -------------- */ ++/* --- MR API --- */ ++ ++#define MR_CARRYCLEAR(p) \ ++ (void *)((unsigned long)(p) & (~(unsigned long)(QM_MR_SIZE << 6))) ++ ++static inline u8 MR_PTR2IDX(const struct qm_mr_entry *e) ++{ ++ return ((uintptr_t)e >> 6) & (QM_MR_SIZE - 1); ++} ++ ++static inline const struct qm_mr_entry *MR_INC(const struct qm_mr_entry *e) ++{ ++ return MR_CARRYCLEAR(e + 1); ++} ++ ++#ifdef CONFIG_FSL_QMAN_BUG_AND_FEATURE_REV1 ++static inline void __mr_copy_and_fixup(struct qm_portal *p, u8 idx) ++{ ++ if (qman_ip_rev == QMAN_REV10) { ++ struct qm_mr_entry *shadow = qm_cl(p->bugs.mr, idx); ++ struct qm_mr_entry *res = qm_cl(p->mr.ring, idx); ++ copy_words(shadow, res, sizeof(*res)); ++ /* Bypass the QM_MR_RC_*** definitions, and check the byte value ++ * directly to handle the erratum. */ ++ if (shadow->ern.rc == 0x06) ++ shadow->ern.rc = 0x60; ++ } ++} ++#else ++#define __mr_copy_and_fixup(p, idx) do { ; } while (0) ++#endif ++ ++static inline int qm_mr_init(struct qm_portal *portal, enum qm_mr_pmode pmode, ++ enum qm_mr_cmode cmode) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ u32 cfg; ++ int loop; ++ ++#ifdef CONFIG_FSL_QMAN_BUG_AND_FEATURE_REV1 ++ if ((qman_ip_rev == QMAN_REV10) && (pmode != qm_mr_pvb)) { ++ pr_err("Qman is rev1, so QMAN9 workaround requires 'pvb'\n"); ++ return -EINVAL; ++ } ++#endif ++ mr->ring = portal->addr.addr_ce + CL_MR; ++ mr->pi = qm_in(MR_PI_CINH) & (QM_MR_SIZE - 1); ++ mr->ci = qm_in(MR_CI_CINH) & (QM_MR_SIZE - 1); ++#ifdef CONFIG_FSL_QMAN_BUG_AND_FEATURE_REV1 ++ if (qman_ip_rev == QMAN_REV10) ++ /* Situate the cursor in the shadow ring */ ++ mr->cursor = portal->bugs.mr + mr->ci; ++ else ++#endif ++ mr->cursor = mr->ring + mr->ci; ++ mr->fill = cyc_diff(QM_MR_SIZE, mr->ci, mr->pi); ++ mr->vbit = (qm_in(MR_PI_CINH) & QM_MR_SIZE) ? QM_MR_VERB_VBIT : 0; ++ mr->ithresh = qm_in(MR_ITR); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mr->pmode = pmode; ++ mr->cmode = cmode; ++#endif ++ /* Only new entries get the copy-and-fixup treatment from ++ * qm_mr_pvb_update(), so perform it here for any stale entries. */ ++ for (loop = 0; loop < mr->fill; loop++) ++ __mr_copy_and_fixup(portal, (mr->ci + loop) & (QM_MR_SIZE - 1)); ++ cfg = (qm_in(CFG) & 0xfffff0ff) | ++ ((cmode & 1) << 8); /* QCSP_CFG:MM */ ++ qm_out(CFG, cfg); ++ return 0; ++} ++ ++static inline void qm_mr_finish(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ if (mr->ci != MR_PTR2IDX(mr->cursor)) ++ pr_crit("Ignoring completed MR entries\n"); ++} ++ ++static inline const struct qm_mr_entry *qm_mr_current(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ if (!mr->fill) ++ return NULL; ++ return mr->cursor; ++} ++ ++static inline u8 qm_mr_cursor(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ return MR_PTR2IDX(mr->cursor); ++} ++ ++static inline u8 qm_mr_next(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->fill); ++ mr->cursor = MR_INC(mr->cursor); ++ return --mr->fill; ++} ++ ++static inline u8 qm_mr_pci_update(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ u8 diff, old_pi = mr->pi; ++ DPA_ASSERT(mr->pmode == qm_mr_pci); ++ mr->pi = qm_in(MR_PI_CINH); ++ diff = cyc_diff(QM_MR_SIZE, old_pi, mr->pi); ++ mr->fill += diff; ++ return diff; ++} ++ ++static inline void qm_mr_pce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->pmode == qm_mr_pce); ++ qm_cl_invalidate(MR_PI); ++ qm_cl_touch_ro(MR_PI); ++} ++ ++static inline u8 qm_mr_pce_update(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ u8 diff, old_pi = mr->pi; ++ DPA_ASSERT(mr->pmode == qm_mr_pce); ++ mr->pi = qm_cl_in(MR_PI) & (QM_MR_SIZE - 1); ++ diff = cyc_diff(QM_MR_SIZE, old_pi, mr->pi); ++ mr->fill += diff; ++ return diff; ++} ++ ++static inline void qm_mr_pvb_update(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ const struct qm_mr_entry *res = qm_cl(mr->ring, mr->pi); ++ DPA_ASSERT(mr->pmode == qm_mr_pvb); ++ /* when accessing 'verb', use __raw_readb() to ensure that compiler ++ * inlining doesn't try to optimise out "excess reads". */ ++ if ((__raw_readb(&res->verb) & QM_MR_VERB_VBIT) == mr->vbit) { ++ __mr_copy_and_fixup(portal, mr->pi); ++ mr->pi = (mr->pi + 1) & (QM_MR_SIZE - 1); ++ if (!mr->pi) ++ mr->vbit ^= QM_MR_VERB_VBIT; ++ mr->fill++; ++ res = MR_INC(res); ++ } ++ dcbit_ro(res); ++} ++ ++static inline void qm_mr_cci_consume(struct qm_portal *portal, u8 num) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->cmode == qm_mr_cci); ++ mr->ci = (mr->ci + num) & (QM_MR_SIZE - 1); ++ qm_out(MR_CI_CINH, mr->ci); ++} ++ ++static inline void qm_mr_cci_consume_to_current(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->cmode == qm_mr_cci); ++ mr->ci = MR_PTR2IDX(mr->cursor); ++ qm_out(MR_CI_CINH, mr->ci); ++} ++ ++static inline void qm_mr_cce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->cmode == qm_mr_cce); ++ qm_cl_invalidate(MR_CI); ++ qm_cl_touch_rw(MR_CI); ++} ++ ++static inline void qm_mr_cce_consume(struct qm_portal *portal, u8 num) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->cmode == qm_mr_cce); ++ mr->ci = (mr->ci + num) & (QM_MR_SIZE - 1); ++ qm_cl_out(MR_CI, mr->ci); ++} ++ ++static inline void qm_mr_cce_consume_to_current(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->cmode == qm_mr_cce); ++ mr->ci = MR_PTR2IDX(mr->cursor); ++ qm_cl_out(MR_CI, mr->ci); ++} ++ ++static inline u8 qm_mr_get_ci(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ return mr->ci; ++} ++ ++static inline u8 qm_mr_get_ithresh(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ return mr->ithresh; ++} ++ ++static inline void qm_mr_set_ithresh(struct qm_portal *portal, u8 ithresh) ++{ ++ qm_out(MR_ITR, ithresh); ++} ++ ++ ++/* ------------------------------ */ ++/* --- Management command API --- */ ++ ++static inline int qm_mc_init(struct qm_portal *portal) ++{ ++ register struct qm_mc *mc = &portal->mc; ++ mc->cr = portal->addr.addr_ce + CL_CR; ++ mc->rr = portal->addr.addr_ce + CL_RR0; ++ mc->rridx = (__raw_readb(&mc->cr->__dont_write_directly__verb) & ++ QM_MCC_VERB_VBIT) ? 0 : 1; ++ mc->vbit = mc->rridx ? QM_MCC_VERB_VBIT : 0; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_idle; ++#endif ++ return 0; ++} ++ ++static inline void qm_mc_finish(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_mc *mc = &portal->mc; ++ DPA_ASSERT(mc->state == mc_idle); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (mc->state != mc_idle) ++ pr_crit("Losing incomplete MC command\n"); ++#endif ++} ++ ++static inline struct qm_mc_command *qm_mc_start(struct qm_portal *portal) ++{ ++ register struct qm_mc *mc = &portal->mc; ++ DPA_ASSERT(mc->state == mc_idle); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_user; ++#endif ++ dcbz_64(mc->cr); ++ return mc->cr; ++} ++ ++static inline void qm_mc_abort(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_mc *mc = &portal->mc; ++ DPA_ASSERT(mc->state == mc_user); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_idle; ++#endif ++} ++ ++static inline void qm_mc_commit(struct qm_portal *portal, u8 myverb) ++{ ++ register struct qm_mc *mc = &portal->mc; ++ struct qm_mc_result *rr = mc->rr + mc->rridx; ++ DPA_ASSERT(mc->state == mc_user); ++ lwsync(); ++#ifdef CONFIG_FSL_QMAN_BUG_AND_FEATURE_REV1 ++ if ((qman_ip_rev == QMAN_REV10) && ((myverb & QM_MCC_VERB_MASK) == ++ QM_MCC_VERB_INITFQ_SCHED)) { ++ u32 fqid = mc->cr->initfq.fqid; ++ /* Do two commands to avoid the hw bug. Note, we poll locally ++ * rather than using qm_mc_result() because from a DPA_CHECKING ++ * perspective, we don't want to appear to have "finished" until ++ * both commands are done. */ ++ mc->cr->__dont_write_directly__verb = mc->vbit | ++ QM_MCC_VERB_INITFQ_PARKED; ++ dcbf(mc->cr); ++ portal->bugs.initfq_and_sched = 1; ++ do { ++ dcbit_ro(rr); ++ } while (!__raw_readb(&rr->verb)); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_idle; ++#endif ++ if (rr->result != QM_MCR_RESULT_OK) { ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_hw; ++#endif ++ return; ++ } ++ mc->rridx ^= 1; ++ mc->vbit ^= QM_MCC_VERB_VBIT; ++ rr = mc->rr + mc->rridx; ++ dcbz_64(mc->cr); ++ mc->cr->alterfq.fqid = fqid; ++ lwsync(); ++ myverb = QM_MCC_VERB_ALTER_SCHED; ++ } else ++ portal->bugs.initfq_and_sched = 0; ++#endif ++ mc->cr->__dont_write_directly__verb = myverb | mc->vbit; ++ dcbf(mc->cr); ++ dcbit_ro(rr); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_hw; ++#endif ++} ++ ++static inline struct qm_mc_result *qm_mc_result(struct qm_portal *portal) ++{ ++ register struct qm_mc *mc = &portal->mc; ++ struct qm_mc_result *rr = mc->rr + mc->rridx; ++ DPA_ASSERT(mc->state == mc_hw); ++ /* The inactive response register's verb byte always returns zero until ++ * its command is submitted and completed. This includes the valid-bit, ++ * in case you were wondering... */ ++ if (!__raw_readb(&rr->verb)) { ++ dcbit_ro(rr); ++ return NULL; ++ } ++#ifdef CONFIG_FSL_QMAN_BUG_AND_FEATURE_REV1 ++ if (qman_ip_rev == QMAN_REV10) { ++ if ((__raw_readb(&rr->verb) & QM_MCR_VERB_MASK) == ++ QM_MCR_VERB_QUERYFQ) { ++ void *misplaced = (void *)rr + 50; ++ copy_words(&portal->bugs.result, rr, sizeof(*rr)); ++ rr = &portal->bugs.result; ++ copy_shorts(&rr->queryfq.fqd.td, misplaced, ++ sizeof(rr->queryfq.fqd.td)); ++ } else if (portal->bugs.initfq_and_sched) { ++ /* We split the user-requested command, make the final ++ * result match the requested type. */ ++ copy_words(&portal->bugs.result, rr, sizeof(*rr)); ++ rr = &portal->bugs.result; ++ rr->verb = (rr->verb & QM_MCR_VERB_RRID) | ++ QM_MCR_VERB_INITFQ_SCHED; ++ } ++ } ++#endif ++ mc->rridx ^= 1; ++ mc->vbit ^= QM_MCC_VERB_VBIT; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_idle; ++#endif ++ return rr; ++} ++ ++ ++/* ------------------------------------- */ ++/* --- Portal interrupt register API --- */ ++ ++static inline int qm_isr_init(__always_unused struct qm_portal *portal) ++{ ++ return 0; ++} ++ ++static inline void qm_isr_finish(__always_unused struct qm_portal *portal) ++{ ++} ++ ++static inline void qm_isr_set_iperiod(struct qm_portal *portal, u16 iperiod) ++{ ++ qm_out(ITPR, iperiod); ++} ++ ++static inline u32 __qm_isr_read(struct qm_portal *portal, enum qm_isr_reg n) ++{ ++ return __qm_in(&portal->addr, REG_ISR + (n << 2)); ++} ++ ++static inline void __qm_isr_write(struct qm_portal *portal, enum qm_isr_reg n, ++ u32 val) ++{ ++ __qm_out(&portal->addr, REG_ISR + (n << 2), val); ++} +diff --git a/drivers/staging/fsl_qbman/qman_private.h b/drivers/staging/fsl_qbman/qman_private.h +new file mode 100644 +index 0000000..e43a41a +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_private.h +@@ -0,0 +1,300 @@ ++/* Copyright 2008-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "dpa_sys.h" ++#include ++ ++#if !defined(CONFIG_FSL_QMAN_FQ_LOOKUP) && defined(CONFIG_PPC64) ++#error "_PPC64 requires _FSL_QMAN_FQ_LOOKUP" ++#endif ++ ++ /* ----------------- */ ++ /* Congestion Groups */ ++ /* ----------------- */ ++/* This wrapper represents a bit-array for the state of the 256 Qman congestion ++ * groups. Is also used as a *mask* for congestion groups, eg. so we ignore ++ * those that don't concern us. We harness the structure and accessor details ++ * already used in the management command to query congestion groups. */ ++struct qman_cgrs { ++ struct __qm_mcr_querycongestion q; ++}; ++static inline void qman_cgrs_init(struct qman_cgrs *c) ++{ ++ memset(c, 0, sizeof(*c)); ++} ++static inline void qman_cgrs_fill(struct qman_cgrs *c) ++{ ++ memset(c, 0xff, sizeof(*c)); ++} ++static inline int qman_cgrs_get(struct qman_cgrs *c, int num) ++{ ++ return QM_MCR_QUERYCONGESTION(&c->q, num); ++} ++static inline void qman_cgrs_set(struct qman_cgrs *c, int num) ++{ ++ c->q.__state[__CGR_WORD(num)] |= (0x80000000 >> __CGR_SHIFT(num)); ++} ++static inline void qman_cgrs_unset(struct qman_cgrs *c, int num) ++{ ++ c->q.__state[__CGR_WORD(num)] &= ~(0x80000000 >> __CGR_SHIFT(num)); ++} ++static inline int qman_cgrs_next(struct qman_cgrs *c, int num) ++{ ++ while ((++num < __CGR_NUM) && !qman_cgrs_get(c, num)) ++ ; ++ return num; ++} ++static inline void qman_cgrs_cp(struct qman_cgrs *dest, ++ const struct qman_cgrs *src) ++{ ++ memcpy(dest, src, sizeof(*dest)); ++} ++static inline void qman_cgrs_and(struct qman_cgrs *dest, ++ const struct qman_cgrs *a, const struct qman_cgrs *b) ++{ ++ int ret; ++ u32 *_d = dest->q.__state; ++ const u32 *_a = a->q.__state; ++ const u32 *_b = b->q.__state; ++ for (ret = 0; ret < 8; ret++) ++ *(_d++) = *(_a++) & *(_b++); ++} ++static inline void qman_cgrs_xor(struct qman_cgrs *dest, ++ const struct qman_cgrs *a, const struct qman_cgrs *b) ++{ ++ int ret; ++ u32 *_d = dest->q.__state; ++ const u32 *_a = a->q.__state; ++ const u32 *_b = b->q.__state; ++ for (ret = 0; ret < 8; ret++) ++ *(_d++) = *(_a++) ^ *(_b++); ++} ++ ++#define qman_cgrs_for_each_1(cgr, cgrs) \ ++ for ((cgr) = -1; (cgr) = qman_cgrs_next((cgrs), (cgr)),\ ++ (cgr) < __CGR_NUM;) ++ ++/* used by CCSR and portal interrupt code */ ++enum qm_isr_reg { ++ qm_isr_status = 0, ++ qm_isr_enable = 1, ++ qm_isr_disable = 2, ++ qm_isr_inhibit = 3 ++}; ++ ++struct qm_portal_config { ++ /* Corenet portal addresses; ++ * [0]==cache-enabled, [1]==cache-inhibited. */ ++ __iomem void *addr_virt[2]; ++ struct resource addr_phys[2]; ++ struct device_node *node; ++ /* Allow these to be joined in lists */ ++ struct list_head list; ++ /* User-visible portal configuration settings */ ++ struct qman_portal_config public_cfg; ++}; ++ ++/* Revision info (for errata and feature handling) */ ++#define QMAN_REV10 0x0100 ++#define QMAN_REV11 0x0101 ++#define QMAN_REV12 0x0102 ++#define QMAN_REV20 0x0200 ++#define QMAN_REV30 0x0300 ++extern u16 qman_ip_rev; /* 0 if uninitialised, otherwise QMAN_REVx */ ++extern u32 qman_clk; ++ ++#ifdef CONFIG_FSL_QMAN_CONFIG ++/* Hooks from qman_driver.c to qman_config.c */ ++int qman_init_ccsr(struct device_node *node); ++void qman_liodn_fixup(u16 channel); ++int qman_set_sdest(u16 channel, unsigned int cpu_idx); ++#endif ++ ++int qm_set_wpm(int wpm); ++int qm_get_wpm(int *wpm); ++ ++/* Hooks from qman_driver.c in to qman_high.c */ ++struct qman_portal *qman_create_affine_portal( ++ const struct qm_portal_config *config, ++ const struct qman_cgrs *cgrs); ++struct qman_portal *qman_create_affine_slave(struct qman_portal *redirect); ++const struct qm_portal_config *qman_destroy_affine_portal(void); ++ ++/* This CGR feature is supported by h/w and required by unit-tests and the ++ * debugfs hooks, so is implemented in the driver. However it allows an explicit ++ * corruption of h/w fields by s/w that are usually incorruptible (because the ++ * counters are usually maintained entirely within h/w). As such, we declare ++ * this API internally. */ ++int qman_testwrite_cgr(struct qman_cgr *cgr, u64 i_bcnt, ++ struct qm_mcr_cgrtestwrite *result); ++ ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++/* If the fq object pointer is greater than the size of context_b field, ++ * than a lookup table is required. */ ++int qman_setup_fq_lookup_table(size_t num_entries); ++#endif ++ ++/*************************************************/ ++/* QMan s/w corenet portal, low-level i/face */ ++/*************************************************/ ++ ++/* Note: most functions are only used by the high-level interface, so are ++ * inlined from qman_low.h. The stuff below is for use by other parts of the ++ * driver. */ ++ ++/* For qm_dqrr_sdqcr_set(); Choose one SOURCE. Choose one COUNT. Choose one ++ * dequeue TYPE. Choose TOKEN (8-bit). ++ * If SOURCE == CHANNELS, ++ * Choose CHANNELS_DEDICATED and/or CHANNELS_POOL(n). ++ * You can choose DEDICATED_PRECEDENCE if the portal channel should have ++ * priority. ++ * If SOURCE == SPECIFICWQ, ++ * Either select the work-queue ID with SPECIFICWQ_WQ(), or select the ++ * channel (SPECIFICWQ_DEDICATED or SPECIFICWQ_POOL()) and specify the ++ * work-queue priority (0-7) with SPECIFICWQ_WQ() - either way, you get the ++ * same value. ++ */ ++#define QM_SDQCR_SOURCE_CHANNELS 0x0 ++#define QM_SDQCR_SOURCE_SPECIFICWQ 0x40000000 ++#define QM_SDQCR_COUNT_EXACT1 0x0 ++#define QM_SDQCR_COUNT_UPTO3 0x20000000 ++#define QM_SDQCR_DEDICATED_PRECEDENCE 0x10000000 ++#define QM_SDQCR_TYPE_MASK 0x03000000 ++#define QM_SDQCR_TYPE_NULL 0x0 ++#define QM_SDQCR_TYPE_PRIO_QOS 0x01000000 ++#define QM_SDQCR_TYPE_ACTIVE_QOS 0x02000000 ++#define QM_SDQCR_TYPE_ACTIVE 0x03000000 ++#define QM_SDQCR_TOKEN_MASK 0x00ff0000 ++#define QM_SDQCR_TOKEN_SET(v) (((v) & 0xff) << 16) ++#define QM_SDQCR_TOKEN_GET(v) (((v) >> 16) & 0xff) ++#define QM_SDQCR_CHANNELS_DEDICATED 0x00008000 ++#if 0 /* These are defined in the external fsl_qman.h API */ ++#define QM_SDQCR_CHANNELS_POOL_MASK 0x00007fff ++#define QM_SDQCR_CHANNELS_POOL(n) (0x00008000 >> (n)) ++#endif ++#define QM_SDQCR_SPECIFICWQ_MASK 0x000000f7 ++#define QM_SDQCR_SPECIFICWQ_DEDICATED 0x00000000 ++#define QM_SDQCR_SPECIFICWQ_POOL(n) ((n) << 4) ++#define QM_SDQCR_SPECIFICWQ_WQ(n) (n) ++ ++/* For qm_dqrr_vdqcr_set(); Choose one PRECEDENCE. EXACT is optional. Use ++ * NUMFRAMES(n) (6-bit) or NUMFRAMES_TILLEMPTY to fill in the frame-count. Use ++ * FQID(n) to fill in the frame queue ID. */ ++#if 0 /* These are defined in the external fsl_qman.h API */ ++#define QM_VDQCR_PRECEDENCE_VDQCR 0x0 ++#define QM_VDQCR_PRECEDENCE_SDQCR 0x80000000 ++#define QM_VDQCR_EXACT 0x40000000 ++#define QM_VDQCR_NUMFRAMES_MASK 0x3f000000 ++#define QM_VDQCR_NUMFRAMES_SET(n) (((n) & 0x3f) << 24) ++#define QM_VDQCR_NUMFRAMES_GET(n) (((n) >> 24) & 0x3f) ++#define QM_VDQCR_NUMFRAMES_TILLEMPTY QM_VDQCR_NUMFRAMES_SET(0) ++#endif ++#define QM_VDQCR_FQID_MASK 0x00ffffff ++#define QM_VDQCR_FQID(n) ((n) & QM_VDQCR_FQID_MASK) ++ ++/* For qm_dqrr_pdqcr_set(); Choose one MODE. Choose one COUNT. ++ * If MODE==SCHEDULED ++ * Choose SCHEDULED_CHANNELS or SCHEDULED_SPECIFICWQ. Choose one dequeue TYPE. ++ * If CHANNELS, ++ * Choose CHANNELS_DEDICATED and/or CHANNELS_POOL() channels. ++ * You can choose DEDICATED_PRECEDENCE if the portal channel should have ++ * priority. ++ * If SPECIFICWQ, ++ * Either select the work-queue ID with SPECIFICWQ_WQ(), or select the ++ * channel (SPECIFICWQ_DEDICATED or SPECIFICWQ_POOL()) and specify the ++ * work-queue priority (0-7) with SPECIFICWQ_WQ() - either way, you get the ++ * same value. ++ * If MODE==UNSCHEDULED ++ * Choose FQID(). ++ */ ++#define QM_PDQCR_MODE_SCHEDULED 0x0 ++#define QM_PDQCR_MODE_UNSCHEDULED 0x80000000 ++#define QM_PDQCR_SCHEDULED_CHANNELS 0x0 ++#define QM_PDQCR_SCHEDULED_SPECIFICWQ 0x40000000 ++#define QM_PDQCR_COUNT_EXACT1 0x0 ++#define QM_PDQCR_COUNT_UPTO3 0x20000000 ++#define QM_PDQCR_DEDICATED_PRECEDENCE 0x10000000 ++#define QM_PDQCR_TYPE_MASK 0x03000000 ++#define QM_PDQCR_TYPE_NULL 0x0 ++#define QM_PDQCR_TYPE_PRIO_QOS 0x01000000 ++#define QM_PDQCR_TYPE_ACTIVE_QOS 0x02000000 ++#define QM_PDQCR_TYPE_ACTIVE 0x03000000 ++#define QM_PDQCR_CHANNELS_DEDICATED 0x00008000 ++#define QM_PDQCR_CHANNELS_POOL(n) (0x00008000 >> (n)) ++#define QM_PDQCR_SPECIFICWQ_MASK 0x000000f7 ++#define QM_PDQCR_SPECIFICWQ_DEDICATED 0x00000000 ++#define QM_PDQCR_SPECIFICWQ_POOL(n) ((n) << 4) ++#define QM_PDQCR_SPECIFICWQ_WQ(n) (n) ++#define QM_PDQCR_FQID(n) ((n) & 0xffffff) ++ ++/* Used by all portal interrupt registers except 'inhibit'. NB, some of these ++ * definitions are exported for use by the qman_irqsource_***() APIs, so are ++ * commented-out here. */ ++#define QM_PIRQ_DQAVAIL 0x0000ffff /* Channels with frame availability */ ++#if 0 ++#define QM_PIRQ_CSCI 0x00100000 /* Congestion State Change */ ++#define QM_PIRQ_EQCI 0x00080000 /* Enqueue Command Committed */ ++#define QM_PIRQ_EQRI 0x00040000 /* EQCR Ring (below threshold) */ ++#define QM_PIRQ_DQRI 0x00020000 /* DQRR Ring (non-empty) */ ++#define QM_PIRQ_MRI 0x00010000 /* MR Ring (non-empty) */ ++/* This mask contains all the interrupt sources that need handling except DQRI, ++ * ie. that if present should trigger slow-path processing. */ ++#define QM_PIRQ_SLOW (QM_PIRQ_CSCI | QM_PIRQ_EQCI | QM_PIRQ_EQRI | \ ++ QM_PIRQ_MRI) ++#endif ++/* The DQAVAIL interrupt fields break down into these bits; */ ++#define QM_DQAVAIL_PORTAL 0x8000 /* Portal channel */ ++#define QM_DQAVAIL_POOL(n) (0x8000 >> (n)) /* Pool channel, n==[1..15] */ ++#define QM_DQAVAIL_MASK 0xffff ++/* This mask contains all the "irqsource" bits visible to API users */ ++#define QM_PIRQ_VISIBLE (QM_PIRQ_SLOW | QM_PIRQ_DQRI) ++ ++/* These are qm__(). So for example, qm_disable_write() means "write ++ * the disable register" rather than "disable the ability to write". */ ++#define qm_isr_status_read(qm) __qm_isr_read(qm, qm_isr_status) ++#define qm_isr_status_clear(qm, m) __qm_isr_write(qm, qm_isr_status, m) ++#define qm_isr_enable_read(qm) __qm_isr_read(qm, qm_isr_enable) ++#define qm_isr_enable_write(qm, v) __qm_isr_write(qm, qm_isr_enable, v) ++#define qm_isr_disable_read(qm) __qm_isr_read(qm, qm_isr_disable) ++#define qm_isr_disable_write(qm, v) __qm_isr_write(qm, qm_isr_disable, v) ++/* TODO: unfortunate name-clash here, reword? */ ++#define qm_isr_inhibit(qm) __qm_isr_write(qm, qm_isr_inhibit, 1) ++#define qm_isr_uninhibit(qm) __qm_isr_write(qm, qm_isr_inhibit, 0) ++ ++/* CEETM related */ ++#define QMAN_CEETM_MAX 2 ++extern struct qm_ceetm qman_ceetms[QMAN_CEETM_MAX]; ++int qman_sp_enable_ceetm_mode(enum qm_dc_portal portal, u16 sub_portal); ++int qman_sp_disable_ceetm_mode(enum qm_dc_portal portal, u16 sub_portal); ++int qman_ceetm_set_prescaler(enum qm_dc_portal portal); ++int qman_ceetm_get_prescaler(u16 *pres); ++int qman_ceetm_query_cq(unsigned int cqid, unsigned int dcpid, ++ struct qm_mcr_ceetm_cq_query *cq_query); +diff --git a/drivers/staging/fsl_qbman/qman_test.c b/drivers/staging/fsl_qbman/qman_test.c +new file mode 100644 +index 0000000..ea39449 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_test.c +@@ -0,0 +1,60 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "qman_test.h" ++ ++MODULE_AUTHOR("Geoff Thorpe"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("Qman testing"); ++ ++static int test_init(void) ++{ ++ int loop = 1; ++ while(loop--) { ++#ifdef CONFIG_FSL_QMAN_TEST_STASH_POTATO ++ qman_test_hotpotato(); ++#endif ++#ifdef CONFIG_FSL_QMAN_TEST_HIGH ++ qman_test_high(); ++#endif ++#ifdef CONFIG_FSL_QMAN_TEST_ERRATA ++ qman_test_errata(); ++#endif ++ } ++ return 0; ++} ++ ++static void test_exit(void) ++{ ++} ++ ++module_init(test_init); ++module_exit(test_exit); +diff --git a/drivers/staging/fsl_qbman/qman_test.h b/drivers/staging/fsl_qbman/qman_test.h +new file mode 100644 +index 0000000..082d9f2 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_test.h +@@ -0,0 +1,84 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++void qman_test_hotpotato(void); ++void qman_test_high(void); ++void qman_test_errata(void); ++void qman_test_fqrange(void); ++ ++static inline void __hexdump(unsigned long start, unsigned long end, ++ unsigned long p, size_t sz, const unsigned char *c) ++{ ++ while (start < end) { ++ unsigned int pos = 0; ++ char buf[64]; ++ int nl = 0; ++ pos += sprintf(buf + pos, "%08lx: ", start); ++ do { ++ if ((start < p) || (start >= (p + sz))) ++ pos += sprintf(buf + pos, ".."); ++ else ++ pos += sprintf(buf + pos, "%02x", *(c++)); ++ if (!(++start & 15)) { ++ buf[pos++] = '\n'; ++ nl = 1; ++ } else { ++ nl = 0; ++ if(!(start & 1)) ++ buf[pos++] = ' '; ++ if(!(start & 3)) ++ buf[pos++] = ' '; ++ } ++ } while (start & 15); ++ if (!nl) ++ buf[pos++] = '\n'; ++ buf[pos] = '\0'; ++ pr_info("%s", buf); ++ } ++} ++static inline void hexdump(const void *ptr, size_t sz) ++{ ++ unsigned long p = (unsigned long)ptr; ++ unsigned long start = p & ~(unsigned long)15; ++ unsigned long end = (p + sz + 15) & ~(unsigned long)15; ++ const unsigned char *c = ptr; ++ __hexdump(start, end, p, sz, c); ++} +diff --git a/drivers/staging/fsl_qbman/qman_test_errata.c b/drivers/staging/fsl_qbman/qman_test_errata.c +new file mode 100644 +index 0000000..0f44cad +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_test_errata.c +@@ -0,0 +1,247 @@ ++/* Copyright 2009-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "qman_test.h" ++ ++/* Waiting on a model fix from virtutech */ ++#if 0 ++/*********************/ ++/* generic utilities */ ++/*********************/ ++ ++static int do_enqueues(struct qman_fq *fq, const struct qm_fd *fds, int num) ++{ ++ int ret = 0; ++ u32 flags = QMAN_ENQUEUE_FLAG_WAIT; ++ while (num-- && !ret) { ++ if (!num) ++ flags |= QMAN_ENQUEUE_FLAG_WAIT_SYNC; ++ pr_info("about to enqueue\n"); ++ ret = qman_enqueue(fq, fds++, flags); ++ } ++ return ret; ++} ++ ++/***************************/ ++/* "tdthresh" test (QMAN6) */ ++/***************************/ ++ ++/* First thresh == 201 * (2^21) == 421527552 (0x19200000) */ ++#define THRESH_MANT 201 ++#define THRESH_EXP 21 ++ ++/* first three equal thresh, fourth takes us over */ ++static const struct qm_fd td_eq[] = { ++ QM_FD_FMT_20(0, 0x34, 0x87654321, QM_FD_SG, 0, 79321), ++ QM_FD_FMT_29(0, 0x34, 0x87654321, QM_FD_COMPOUND, 29923679), ++ QM_FD_FMT_29(0, 0x0d, 0xacadabba, QM_FD_CONTIG_BIG, 391524552), ++ QM_FD_FMT_20(0, 0x0b, 0x0fa10ada, QM_FD_CONTIG, 0, 1), ++ QM_FD_FMT_20(0, 0x0b, 0x0fa10ada, QM_FD_CONTIG, 0, 1), ++}; ++ ++struct tdthresh_fq { ++ struct qman_fq fq; ++ int got_ern; ++ int num_dqrr; ++}; ++ ++static enum qman_cb_dqrr_result cb_dqrr_tdthresh(struct qman_portal *p, ++ struct qman_fq *__fq, ++ const struct qm_dqrr_entry *dqrr) ++{ ++ struct tdthresh_fq *t = (void *)__fq; ++ t->num_dqrr++; ++ return qman_cb_dqrr_consume; ++} ++ ++static void cb_ern_tdthresh(struct qman_portal *p, struct qman_fq *__fq, ++ const struct qm_mr_entry *mr) ++{ ++ struct tdthresh_fq *t = (void *)__fq; ++ t->got_ern = 1; ++} ++ ++static void test_tdthresh(void) ++{ ++ struct tdthresh_fq tdfq = { ++ .fq = { ++ .cb = { ++ .dqrr = cb_dqrr_tdthresh, ++ .ern = cb_ern_tdthresh ++ } ++ }, ++ .got_ern = 0, ++ .num_dqrr = 0 ++ }; ++ struct qman_fq *fq = &tdfq.fq; ++ struct qm_mcc_initfq opts = { ++ .we_mask = QM_INITFQ_WE_FQCTRL | QM_INITFQ_WE_TDTHRESH, ++ .fqd = { ++ .fq_ctrl = QM_FQCTRL_TDE, ++ .td = { ++ .exp = THRESH_EXP, ++ .mant = THRESH_MANT, ++ } ++ } ++ }; ++ struct qm_fqd fqd; ++ u32 flags; ++ int ret = qman_create_fq(0, QMAN_FQ_FLAG_DYNAMIC_FQID, fq); ++ BUG_ON(ret); ++ /* leave it parked, and set it for local dequeue (loopback) */ ++ ret = qman_init_fq(fq, QMAN_INITFQ_FLAG_LOCAL, &opts); ++ BUG_ON(ret); ++ /* query it back and confirm everything is ok */ ++ ret = qman_query_fq(fq, &fqd); ++ BUG_ON(ret); ++ if (fqd.fq_ctrl != opts.fqd.fq_ctrl) { ++ pr_err("queried fq_ctrl=%x, should be=%x\n", fqd.fq_ctrl, ++ opts.fqd.fq_ctrl); ++ panic("fail"); ++ } ++ if (memcmp(&fqd.td, &opts.fqd.td, sizeof(fqd.td))) { ++ pr_err("queried td_thresh=%x:%x, should be=%x:%x\n", ++ fqd.td.exp, fqd.td.mant, ++ opts.fqd.td.exp, opts.fqd.td.mant); ++ panic("fail"); ++ } ++ ret = do_enqueues(fq, td_eq, 3); ++ BUG_ON(ret); ++ pr_info(" tdthresh: eq[0..2] complete\n"); ++ /* enqueues are flushed, so if Qman is going to throw an ERN, the irq ++ * assertion will already be on its way. */ ++ msleep(500); ++ BUG_ON(tdfq.got_ern); ++ pr_info(" tdthresh: eq <= thresh OK\n"); ++ ret = do_enqueues(fq, td_eq + 3, 1); ++ BUG_ON(ret); ++ pr_info(" tdthresh: eq[3] complete\n"); ++ /* enqueues are flushed, so if Qman is going to throw an ERN, the irq ++ * assertion will already be on its way. */ ++ msleep(500); ++ BUG_ON(tdfq.got_ern); ++ pr_info(" tdthresh: eq <= thresh OK\n"); ++ ret = do_enqueues(fq, td_eq + 4, 1); ++ BUG_ON(ret); ++ pr_info(" tdthresh: eq[4] complete\n"); ++ /* enqueues are flushed, so if Qman is going to throw an ERN, the irq ++ * assertion will already be on its way. */ ++ msleep(500); ++ BUG_ON(!tdfq.got_ern); ++ pr_info(" tdthresh: eq > thresh OK\n"); ++ ret = qman_volatile_dequeue(fq, ++ QMAN_VOLATILE_FLAG_WAIT | QMAN_VOLATILE_FLAG_FINISH, ++ QM_VDQCR_NUMFRAMES_TILLEMPTY); ++ BUG_ON(ret); ++ BUG_ON(tdfq.num_dqrr != 4); ++ ret = qman_retire_fq(fq, &flags); ++ BUG_ON(ret); ++ BUG_ON(flags); ++ ret = qman_oos_fq(fq); ++ BUG_ON(ret); ++} ++ ++/****************************/ ++/* "ern code6" test (QMAN9) */ ++/****************************/ ++ ++/* Dummy FD to enqueue out-of-sequence and generate an ERN */ ++static const struct qm_fd c6_eq = ++ QM_FD_FMT_29(0, 0xba, 0xdeadbeef, QM_FD_CONTIG_BIG, 1234); ++ ++struct code6_fq { ++ struct qman_fq fq; ++ struct qm_mr_entry mr; ++ struct completion got_ern; ++}; ++ ++static void cb_ern_code6(struct qman_portal *p, struct qman_fq *__fq, ++ const struct qm_mr_entry *mr) ++{ ++ struct code6_fq *c = (void *)__fq; ++ memcpy(&c->mr, mr, sizeof(*mr)); ++ complete(&c->got_ern); ++} ++ ++static void test_ern_code6(void) ++{ ++ struct code6_fq c6fq = { ++ .fq = { ++ .cb = { ++ .ern = cb_ern_code6 ++ } ++ }, ++ .got_ern = COMPLETION_INITIALIZER(c6fq.got_ern) ++ }; ++ struct qman_fq *fq = &c6fq.fq; ++ struct qm_mcc_initfq opts = { ++ .we_mask = QM_INITFQ_WE_FQCTRL, ++ .fqd = { ++ .fq_ctrl = QM_FQCTRL_ORP ++ } ++ }; ++ u32 flags; ++ int ret = qman_create_fq(0, QMAN_FQ_FLAG_DYNAMIC_FQID, fq); ++ BUG_ON(ret); ++ /* leave it parked, and set it for local dequeue (loopback) */ ++ ret = qman_init_fq(fq, QMAN_INITFQ_FLAG_LOCAL, &opts); ++ BUG_ON(ret); ++ /* enqueue with ORP using a "too early" sequence number */ ++ ret = qman_enqueue_orp(fq, &c6_eq, ++ QMAN_ENQUEUE_FLAG_WAIT | QMAN_ENQUEUE_FLAG_WAIT_SYNC, fq, 5); ++ BUG_ON(ret); ++ pr_info(" code6: eq complete\n"); ++ ret = qman_retire_fq(fq, &flags); ++ BUG_ON(ret); ++ pr_info(" code6: retire complete, flags=%08x\n", flags); ++ BUG_ON(flags != QMAN_FQ_STATE_ORL); ++ wait_for_completion(&c6fq.got_ern); ++ pr_info(" code6: ERN, VERB=0x%02x, RC==0x%02x\n", ++ c6fq.mr.verb, c6fq.mr.ern.rc); ++ BUG_ON(c6fq.mr.verb & 0x20); ++ BUG_ON((c6fq.mr.ern.rc & QM_MR_RC_MASK) != QM_MR_RC_ORPWINDOW_RETIRED); ++ ret = qman_oos_fq(fq); ++ BUG_ON(ret); ++} ++ ++void qman_test_errata(void) ++{ ++ pr_info("Testing Qman errata handling ...\n"); ++ test_tdthresh(); ++ test_ern_code6(); ++ pr_info(" ... SUCCESS!\n"); ++} ++#else ++void qman_test_errata(void) ++{ ++ pr_info("Qman errata-handling test disabled, waiting on model fix\n"); ++} ++#endif +diff --git a/drivers/staging/fsl_qbman/qman_test_high.c b/drivers/staging/fsl_qbman/qman_test_high.c +new file mode 100644 +index 0000000..cba6c25 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_test_high.c +@@ -0,0 +1,212 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "qman_test.h" ++ ++/*************/ ++/* constants */ ++/*************/ ++ ++#define CGR_ID 27 ++#define POOL_ID 2 ++#define FQ_FLAGS QMAN_FQ_FLAG_DYNAMIC_FQID ++#define NUM_ENQUEUES 10 ++#define NUM_PARTIAL 4 ++#define PORTAL_SDQCR (QM_SDQCR_SOURCE_CHANNELS | \ ++ QM_SDQCR_TYPE_PRIO_QOS | \ ++ QM_SDQCR_TOKEN_SET(0x98) | \ ++ QM_SDQCR_CHANNELS_DEDICATED | \ ++ QM_SDQCR_CHANNELS_POOL(POOL_ID)) ++#define PORTAL_OPAQUE (void *)0xf00dbeef ++#define VDQCR_FLAGS (QMAN_VOLATILE_FLAG_WAIT | QMAN_VOLATILE_FLAG_FINISH) ++ ++/*************************************/ ++/* Predeclarations (eg. for fq_base) */ ++/*************************************/ ++ ++static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *, ++ struct qman_fq *, ++ const struct qm_dqrr_entry *); ++static void cb_ern(struct qman_portal *, struct qman_fq *, ++ const struct qm_mr_entry *); ++static void cb_fqs(struct qman_portal *, struct qman_fq *, ++ const struct qm_mr_entry *); ++ ++/***************/ ++/* global vars */ ++/***************/ ++ ++static struct qm_fd fd, fd_dq; ++static struct qman_fq fq_base = { ++ .cb.dqrr = cb_dqrr, ++ .cb.ern = cb_ern, ++ .cb.fqs = cb_fqs ++}; ++static DECLARE_WAIT_QUEUE_HEAD(waitqueue); ++static int retire_complete, sdqcr_complete; ++ ++/**********************/ ++/* internal functions */ ++/**********************/ ++ ++/* Helpers for initialising and "incrementing" a frame descriptor */ ++static void fd_init(struct qm_fd *__fd) ++{ ++ qm_fd_addr_set64(__fd, 0xabdeadbeefLLU); ++ __fd->format = qm_fd_contig_big; ++ __fd->length29 = 0x0000ffff; ++ __fd->cmd = 0xfeedf00d; ++} ++ ++static void fd_inc(struct qm_fd *__fd) ++{ ++ u64 t = qm_fd_addr_get64(__fd); ++ int z = t >> 40; ++ t <<= 1; ++ if (z) ++ t |= 1; ++ qm_fd_addr_set64(__fd, t); ++ __fd->length29--; ++ __fd->cmd++; ++} ++ ++/* The only part of the 'fd' we can't memcmp() is the ppid */ ++static int fd_cmp(const struct qm_fd *a, const struct qm_fd *b) ++{ ++ int r = (qm_fd_addr_get64(a) == qm_fd_addr_get64(b)) ? 0 : -1; ++ if (!r) ++ r = a->format - b->format; ++ if (!r) ++ r = a->opaque - b->opaque; ++ if (!r) ++ r = a->cmd - b->cmd; ++ return r; ++} ++ ++/********/ ++/* test */ ++/********/ ++ ++static void do_enqueues(struct qman_fq *fq) ++{ ++ unsigned int loop; ++ for (loop = 0; loop < NUM_ENQUEUES; loop++) { ++ if (qman_enqueue(fq, &fd, QMAN_ENQUEUE_FLAG_WAIT | ++ (((loop + 1) == NUM_ENQUEUES) ? ++ QMAN_ENQUEUE_FLAG_WAIT_SYNC : 0))) ++ panic("qman_enqueue() failed\n"); ++ fd_inc(&fd); ++ } ++} ++ ++void qman_test_high(void) ++{ ++ int flags, res; ++ struct qman_fq *fq = &fq_base; ++ ++ pr_info("qman_test_high starting\n"); ++ fd_init(&fd); ++ fd_init(&fd_dq); ++ ++ /* Initialise (parked) FQ */ ++ if (qman_create_fq(0, FQ_FLAGS, fq)) ++ panic("qman_create_fq() failed\n"); ++ if (qman_init_fq(fq, QMAN_INITFQ_FLAG_LOCAL, NULL)) ++ panic("qman_init_fq() failed\n"); ++ ++ /* Do enqueues + VDQCR, twice. (Parked FQ) */ ++ do_enqueues(fq); ++ pr_info("VDQCR (till-empty);\n"); ++ if (qman_volatile_dequeue(fq, VDQCR_FLAGS, ++ QM_VDQCR_NUMFRAMES_TILLEMPTY)) ++ panic("qman_volatile_dequeue() failed\n"); ++ do_enqueues(fq); ++ pr_info("VDQCR (%d of %d);\n", NUM_PARTIAL, NUM_ENQUEUES); ++ if (qman_volatile_dequeue(fq, VDQCR_FLAGS, ++ QM_VDQCR_NUMFRAMES_SET(NUM_PARTIAL))) ++ panic("qman_volatile_dequeue() failed\n"); ++ pr_info("VDQCR (%d of %d);\n", NUM_ENQUEUES - NUM_PARTIAL, ++ NUM_ENQUEUES); ++ if (qman_volatile_dequeue(fq, VDQCR_FLAGS, ++ QM_VDQCR_NUMFRAMES_SET(NUM_ENQUEUES - NUM_PARTIAL))) ++ panic("qman_volatile_dequeue() failed\n"); ++ ++ do_enqueues(fq); ++ pr_info("scheduled dequeue (till-empty)\n"); ++ if (qman_schedule_fq(fq)) ++ panic("qman_schedule_fq() failed\n"); ++ wait_event(waitqueue, sdqcr_complete); ++ ++ /* Retire and OOS the FQ */ ++ res = qman_retire_fq(fq, &flags); ++ if (res < 0) ++ panic("qman_retire_fq() failed\n"); ++ wait_event(waitqueue, retire_complete); ++ if (flags & QMAN_FQ_STATE_BLOCKOOS) ++ panic("leaking frames\n"); ++ if (qman_oos_fq(fq)) ++ panic("qman_oos_fq() failed\n"); ++ qman_destroy_fq(fq, 0); ++ pr_info("qman_test_high finished\n"); ++} ++ ++static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *p, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ if (fd_cmp(&fd_dq, &dq->fd)) { ++ pr_err("BADNESS: dequeued frame doesn't match;\n"); ++ BUG(); ++ } ++ fd_inc(&fd_dq); ++ if (!(dq->stat & QM_DQRR_STAT_UNSCHEDULED) && !fd_cmp(&fd_dq, &fd)) { ++ sdqcr_complete = 1; ++ wake_up(&waitqueue); ++ } ++ return qman_cb_dqrr_consume; ++} ++ ++static void cb_ern(struct qman_portal *p, struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ panic("cb_ern() unimplemented"); ++} ++ ++static void cb_fqs(struct qman_portal *p, struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ u8 verb = (msg->verb & QM_MR_VERB_TYPE_MASK); ++ if ((verb != QM_MR_VERB_FQRN) && (verb != QM_MR_VERB_FQRNI)) ++ panic("unexpected FQS message"); ++ pr_info("Retirement message received\n"); ++ retire_complete = 1; ++ wake_up(&waitqueue); ++} +diff --git a/drivers/staging/fsl_qbman/qman_test_hotpotato.c b/drivers/staging/fsl_qbman/qman_test_hotpotato.c +new file mode 100644 +index 0000000..91e01d7 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_test_hotpotato.c +@@ -0,0 +1,497 @@ ++/* Copyright 2009-2012 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 ++#include ++#include ++#include "qman_test.h" ++ ++/* Algorithm: ++ * ++ * Each cpu will have HP_PER_CPU "handlers" set up, each of which incorporates ++ * an rx/tx pair of FQ objects (both of which are stashed on dequeue). The ++ * organisation of FQIDs is such that the HP_PER_CPU*NUM_CPUS handlers will ++ * shuttle a "hot potato" frame around them such that every forwarding action ++ * moves it from one cpu to another. (The use of more than one handler per cpu ++ * is to allow enough handlers/FQs to truly test the significance of caching - ++ * ie. when cache-expiries are occuring.) ++ * ++ * The "hot potato" frame content will be HP_NUM_WORDS*4 bytes in size, and the ++ * first and last words of the frame data will undergo a transformation step on ++ * each forwarding action. To achieve this, each handler will be assigned a ++ * 32-bit "mixer", that is produced using a 32-bit LFSR. When a frame is ++ * received by a handler, the mixer of the expected sender is XOR'd into all ++ * words of the entire frame, which is then validated against the original ++ * values. Then, before forwarding, the entire frame is XOR'd with the mixer of ++ * the current handler. Apart from validating that the frame is taking the ++ * expected path, this also provides some quasi-realistic overheads to each ++ * forwarding action - dereferencing *all* the frame data, computation, and ++ * conditional branching. There is a "special" handler designated to act as the ++ * instigator of the test by creating an enqueuing the "hot potato" frame, and ++ * to determine when the test has completed by counting HP_LOOPS iterations. ++ * ++ * Init phases: ++ * ++ * 1. prepare each cpu's 'hp_cpu' struct using on_each_cpu(,,1) and link them ++ * into 'hp_cpu_list'. Specifically, set processor_id, allocate HP_PER_CPU ++ * handlers and link-list them (but do no other handler setup). ++ * ++ * 2. scan over 'hp_cpu_list' HP_PER_CPU times, the first time sets each ++ * hp_cpu's 'iterator' to point to its first handler. With each loop, ++ * allocate rx/tx FQIDs and mixer values to the hp_cpu's iterator handler ++ * and advance the iterator for the next loop. This includes a final fixup, ++ * which connects the last handler to the first (and which is why phase 2 ++ * and 3 are separate). ++ * ++ * 3. scan over 'hp_cpu_list' HP_PER_CPU times, the first time sets each ++ * hp_cpu's 'iterator' to point to its first handler. With each loop, ++ * initialise FQ objects and advance the iterator for the next loop. ++ * Moreover, do this initialisation on the cpu it applies to so that Rx FQ ++ * initialisation targets the correct cpu. ++ */ ++ ++/* helper to run something on all cpus (can't use on_each_cpu(), as that invokes ++ * the fn from irq context, which is too restrictive). */ ++struct bstrap { ++ void (*fn)(void); ++ atomic_t started; ++}; ++static int bstrap_fn(void *__bstrap) ++{ ++ struct bstrap *bstrap = __bstrap; ++ atomic_inc(&bstrap->started); ++ bstrap->fn(); ++ while (!kthread_should_stop()) ++ msleep(1); ++ return 0; ++} ++static int on_all_cpus(void (*fn)(void)) ++{ ++ int cpu; ++ for_each_cpu(cpu, cpu_online_mask) { ++ struct bstrap bstrap = { ++ .fn = fn, ++ .started = ATOMIC_INIT(0) ++ }; ++ struct task_struct *k = kthread_create(bstrap_fn, &bstrap, ++ "hotpotato%d", cpu); ++ int ret; ++ if (IS_ERR(k)) ++ return -ENOMEM; ++ kthread_bind(k, cpu); ++ wake_up_process(k); ++ /* If we call kthread_stop() before the "wake up" has had an ++ * effect, then the thread may exit with -EINTR without ever ++ * running the function. So poll until it's started before ++ * requesting it to stop. */ ++ while (!atomic_read(&bstrap.started)) ++ msleep(10); ++ ret = kthread_stop(k); ++ if (ret) ++ return ret; ++ } ++ return 0; ++} ++ ++struct hp_handler { ++ ++ /* The following data is stashed when 'rx' is dequeued; */ ++ /* -------------- */ ++ /* The Rx FQ, dequeues of which will stash the entire hp_handler */ ++ struct qman_fq rx; ++ /* The Tx FQ we should forward to */ ++ struct qman_fq tx; ++ /* The value we XOR post-dequeue, prior to validating */ ++ u32 rx_mixer; ++ /* The value we XOR pre-enqueue, after validating */ ++ u32 tx_mixer; ++ /* what the hotpotato address should be on dequeue */ ++ dma_addr_t addr; ++ u32 *frame_ptr; ++ ++ /* The following data isn't (necessarily) stashed on dequeue; */ ++ /* -------------- */ ++ u32 fqid_rx, fqid_tx; ++ /* list node for linking us into 'hp_cpu' */ ++ struct list_head node; ++ /* Just to check ... */ ++ unsigned int processor_id; ++} ____cacheline_aligned; ++ ++struct hp_cpu { ++ /* identify the cpu we run on; */ ++ unsigned int processor_id; ++ /* root node for the per-cpu list of handlers */ ++ struct list_head handlers; ++ /* list node for linking us into 'hp_cpu_list' */ ++ struct list_head node; ++ /* when repeatedly scanning 'hp_list', each time linking the n'th ++ * handlers together, this is used as per-cpu iterator state */ ++ struct hp_handler *iterator; ++}; ++ ++/* Each cpu has one of these */ ++static DEFINE_PER_CPU(struct hp_cpu, hp_cpus); ++ ++/* links together the hp_cpu structs, in first-come first-serve order. */ ++static LIST_HEAD(hp_cpu_list); ++static spinlock_t hp_lock = __SPIN_LOCK_UNLOCKED(hp_lock); ++ ++static unsigned int hp_cpu_list_length; ++ ++/* the "special" handler, that starts and terminates the test. */ ++static struct hp_handler *special_handler; ++static int loop_counter; ++ ++/* handlers are allocated out of this, so they're properly aligned. */ ++static struct kmem_cache *hp_handler_slab; ++ ++/* this is the frame data */ ++static void *__frame_ptr; ++static u32 *frame_ptr; ++static dma_addr_t frame_dma; ++ ++/* the main function waits on this */ ++static DECLARE_WAIT_QUEUE_HEAD(queue); ++ ++#define HP_PER_CPU 2 ++#define HP_LOOPS 8 ++/* 80 bytes, like a small ethernet frame, and bleeds into a second cacheline */ ++#define HP_NUM_WORDS 80 ++/* First word of the LFSR-based frame data */ ++#define HP_FIRST_WORD 0xabbaf00d ++ ++static inline u32 do_lfsr(u32 prev) ++{ ++ return (prev >> 1) ^ (-(prev & 1u) & 0xd0000001u); ++} ++ ++static void allocate_frame_data(void) ++{ ++ u32 lfsr = HP_FIRST_WORD; ++ int loop; ++ struct platform_device *pdev = platform_device_alloc("foobar", -1); ++ if (!pdev) ++ panic("platform_device_alloc() failed"); ++ if (platform_device_add(pdev)) ++ panic("platform_device_add() failed"); ++ __frame_ptr = kmalloc(4 * HP_NUM_WORDS, GFP_KERNEL); ++ if (!__frame_ptr) ++ panic("kmalloc() failed"); ++ frame_ptr = (void *)(((unsigned long)__frame_ptr + 63) & ++ ~(unsigned long)63); ++ for (loop = 0; loop < HP_NUM_WORDS; loop++) { ++ frame_ptr[loop] = lfsr; ++ lfsr = do_lfsr(lfsr); ++ } ++ frame_dma = dma_map_single(&pdev->dev, frame_ptr, 4 * HP_NUM_WORDS, ++ DMA_BIDIRECTIONAL); ++ platform_device_del(pdev); ++ platform_device_put(pdev); ++} ++ ++static void deallocate_frame_data(void) ++{ ++ kfree(__frame_ptr); ++} ++ ++static inline void process_frame_data(struct hp_handler *handler, ++ const struct qm_fd *fd) ++{ ++ u32 *p = handler->frame_ptr; ++ u32 lfsr = HP_FIRST_WORD; ++ int loop; ++ if (qm_fd_addr_get64(fd) != handler->addr) ++ panic("bad frame address"); ++ for (loop = 0; loop < HP_NUM_WORDS; loop++, p++) { ++ *p ^= handler->rx_mixer; ++ if (*p != lfsr) ++ panic("corrupt frame data"); ++ *p ^= handler->tx_mixer; ++ lfsr = do_lfsr(lfsr); ++ } ++} ++ ++static enum qman_cb_dqrr_result normal_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dqrr) ++{ ++ struct hp_handler *handler = (struct hp_handler *)fq; ++ ++ process_frame_data(handler, &dqrr->fd); ++ if (qman_enqueue(&handler->tx, &dqrr->fd, 0)) ++ panic("qman_enqueue() failed"); ++ return qman_cb_dqrr_consume; ++} ++ ++static enum qman_cb_dqrr_result special_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dqrr) ++{ ++ struct hp_handler *handler = (struct hp_handler *)fq; ++ ++ process_frame_data(handler, &dqrr->fd); ++ if (++loop_counter < HP_LOOPS) { ++ if (qman_enqueue(&handler->tx, &dqrr->fd, 0)) ++ panic("qman_enqueue() failed"); ++ } else { ++ pr_info("Received final (%dth) frame\n", loop_counter); ++ wake_up(&queue); ++ } ++ return qman_cb_dqrr_consume; ++} ++ ++static void create_per_cpu_handlers(void) ++{ ++ struct hp_handler *handler; ++ int loop; ++ struct hp_cpu *hp_cpu = &__get_cpu_var(hp_cpus); ++ ++ hp_cpu->processor_id = smp_processor_id(); ++ spin_lock(&hp_lock); ++ list_add_tail(&hp_cpu->node, &hp_cpu_list); ++ hp_cpu_list_length++; ++ spin_unlock(&hp_lock); ++ INIT_LIST_HEAD(&hp_cpu->handlers); ++ for (loop = 0; loop < HP_PER_CPU; loop++) { ++ handler = kmem_cache_alloc(hp_handler_slab, GFP_KERNEL); ++ if (!handler) ++ panic("kmem_cache_alloc() failed"); ++ handler->processor_id = hp_cpu->processor_id; ++ handler->addr = frame_dma; ++ handler->frame_ptr = frame_ptr; ++ list_add_tail(&handler->node, &hp_cpu->handlers); ++ } ++} ++ ++static void destroy_per_cpu_handlers(void) ++{ ++ struct list_head *loop, *tmp; ++ struct hp_cpu *hp_cpu = &__get_cpu_var(hp_cpus); ++ ++ spin_lock(&hp_lock); ++ list_del(&hp_cpu->node); ++ spin_unlock(&hp_lock); ++ list_for_each_safe(loop, tmp, &hp_cpu->handlers) { ++ u32 flags; ++ struct hp_handler *handler = list_entry(loop, struct hp_handler, ++ node); ++ if (qman_retire_fq(&handler->rx, &flags)) ++ panic("qman_retire_fq(rx) failed"); ++ BUG_ON(flags & QMAN_FQ_STATE_BLOCKOOS); ++ if (qman_oos_fq(&handler->rx)) ++ panic("qman_oos_fq(rx) failed"); ++ qman_destroy_fq(&handler->rx, 0); ++ qman_destroy_fq(&handler->tx, 0); ++ qman_release_fqid(handler->fqid_rx); ++ list_del(&handler->node); ++ kmem_cache_free(hp_handler_slab, handler); ++ } ++} ++ ++static inline u8 num_cachelines(u32 offset) ++{ ++ u8 res = (offset + (L1_CACHE_BYTES - 1)) ++ / (L1_CACHE_BYTES); ++ if (res > 3) ++ return 3; ++ return res; ++} ++#define STASH_DATA_CL \ ++ num_cachelines(HP_NUM_WORDS * 4) ++#define STASH_CTX_CL \ ++ num_cachelines(offsetof(struct hp_handler,fqid_rx)) ++ ++static void init_handler(void *__handler) ++{ ++ struct qm_mcc_initfq opts; ++ struct hp_handler *handler = __handler; ++ BUG_ON(handler->processor_id != smp_processor_id()); ++ /* Set up rx */ ++ memset(&handler->rx, 0, sizeof(handler->rx)); ++ if (handler == special_handler) ++ handler->rx.cb.dqrr = special_dqrr; ++ else ++ handler->rx.cb.dqrr = normal_dqrr; ++ if (qman_create_fq(handler->fqid_rx, 0, &handler->rx)) ++ panic("qman_create_fq(rx) failed"); ++ memset(&opts, 0, sizeof(opts)); ++ opts.we_mask = QM_INITFQ_WE_FQCTRL | QM_INITFQ_WE_CONTEXTA; ++ opts.fqd.fq_ctrl = QM_FQCTRL_CTXASTASHING; ++ opts.fqd.context_a.stashing.data_cl = STASH_DATA_CL; ++ opts.fqd.context_a.stashing.context_cl = STASH_CTX_CL; ++ if (qman_init_fq(&handler->rx, QMAN_INITFQ_FLAG_SCHED | ++ QMAN_INITFQ_FLAG_LOCAL, &opts)) ++ panic("qman_init_fq(rx) failed"); ++ /* Set up tx */ ++ memset(&handler->tx, 0, sizeof(handler->tx)); ++ if (qman_create_fq(handler->fqid_tx, QMAN_FQ_FLAG_NO_MODIFY, ++ &handler->tx)) ++ panic("qman_create_fq(tx) failed"); ++} ++ ++static void init_phase2(void) ++{ ++ int loop; ++ u32 fqid = 0; ++ u32 lfsr = 0xdeadbeef; ++ struct hp_cpu *hp_cpu; ++ struct hp_handler *handler; ++ ++ for (loop = 0; loop < HP_PER_CPU; loop++) { ++ list_for_each_entry(hp_cpu, &hp_cpu_list, node) { ++ int ret; ++ if (!loop) ++ hp_cpu->iterator = list_first_entry( ++ &hp_cpu->handlers, ++ struct hp_handler, node); ++ else ++ hp_cpu->iterator = list_entry( ++ hp_cpu->iterator->node.next, ++ struct hp_handler, node); ++ /* Rx FQID is the previous handler's Tx FQID */ ++ hp_cpu->iterator->fqid_rx = fqid; ++ /* Allocate new FQID for Tx */ ++ ret = qman_alloc_fqid(&fqid); ++ if (ret) ++ panic("qman_alloc_fqid() failed"); ++ hp_cpu->iterator->fqid_tx = fqid; ++ /* Rx mixer is the previous handler's Tx mixer */ ++ hp_cpu->iterator->rx_mixer = lfsr; ++ /* Get new mixer for Tx */ ++ lfsr = do_lfsr(lfsr); ++ hp_cpu->iterator->tx_mixer = lfsr; ++ } ++ } ++ /* Fix up the first handler (fqid_rx==0, rx_mixer=0xdeadbeef) */ ++ hp_cpu = list_first_entry(&hp_cpu_list, struct hp_cpu, node); ++ handler = list_first_entry(&hp_cpu->handlers, struct hp_handler, node); ++ BUG_ON((handler->fqid_rx != 0) || (handler->rx_mixer != 0xdeadbeef)); ++ handler->fqid_rx = fqid; ++ handler->rx_mixer = lfsr; ++ /* and tag it as our "special" handler */ ++ special_handler = handler; ++} ++ ++static void init_phase3(void) ++{ ++ int loop; ++ struct hp_cpu *hp_cpu; ++ ++ for (loop = 0; loop < HP_PER_CPU; loop++) { ++ list_for_each_entry(hp_cpu, &hp_cpu_list, node) { ++ if (!loop) ++ hp_cpu->iterator = list_first_entry( ++ &hp_cpu->handlers, ++ struct hp_handler, node); ++ else ++ hp_cpu->iterator = list_entry( ++ hp_cpu->iterator->node.next, ++ struct hp_handler, node); ++ preempt_disable(); ++ if (hp_cpu->processor_id == smp_processor_id()) ++ init_handler(hp_cpu->iterator); ++ else ++ smp_call_function_single(hp_cpu->processor_id, ++ init_handler, hp_cpu->iterator, 1); ++ preempt_enable(); ++ } ++ } ++} ++ ++static void send_first_frame(void *ignore) ++{ ++ u32 *p = special_handler->frame_ptr; ++ u32 lfsr = HP_FIRST_WORD; ++ int loop; ++ struct qm_fd fd; ++ ++ BUG_ON(special_handler->processor_id != smp_processor_id()); ++ memset(&fd, 0, sizeof(fd)); ++ qm_fd_addr_set64(&fd, special_handler->addr); ++ fd.format = qm_fd_contig_big; ++ fd.length29 = HP_NUM_WORDS * 4; ++ for (loop = 0; loop < HP_NUM_WORDS; loop++, p++) { ++ if (*p != lfsr) ++ panic("corrupt frame data"); ++ *p ^= special_handler->tx_mixer; ++ lfsr = do_lfsr(lfsr); ++ } ++ pr_info("Sending first frame\n"); ++ if (qman_enqueue(&special_handler->tx, &fd, 0)) ++ panic("qman_enqueue() failed"); ++} ++ ++void qman_test_hotpotato(void) ++{ ++ if (cpumask_weight(cpu_online_mask) < 2) { ++ pr_info("qman_test_hotpotato, skip - only 1 CPU\n"); ++ return; ++ } ++ ++ pr_info("qman_test_hotpotato starting\n"); ++ ++ hp_cpu_list_length = 0; ++ loop_counter = 0; ++ hp_handler_slab = kmem_cache_create("hp_handler_slab", ++ sizeof(struct hp_handler), L1_CACHE_BYTES, ++ SLAB_HWCACHE_ALIGN, NULL); ++ if (!hp_handler_slab) ++ panic("kmem_cache_create() failed"); ++ ++ allocate_frame_data(); ++ ++ /* Init phase 1 */ ++ pr_info("Creating %d handlers per cpu...\n", HP_PER_CPU); ++ if (on_all_cpus(create_per_cpu_handlers)) ++ panic("on_each_cpu() failed"); ++ pr_info("Number of cpus: %d, total of %d handlers\n", ++ hp_cpu_list_length, hp_cpu_list_length * HP_PER_CPU); ++ ++ init_phase2(); ++ ++ init_phase3(); ++ ++ preempt_disable(); ++ if (special_handler->processor_id == smp_processor_id()) ++ send_first_frame(NULL); ++ else ++ smp_call_function_single(special_handler->processor_id, ++ send_first_frame, NULL, 1); ++ preempt_enable(); ++ ++ wait_event(queue, loop_counter == HP_LOOPS); ++ deallocate_frame_data(); ++ if (on_all_cpus(destroy_per_cpu_handlers)) ++ panic("on_each_cpu() failed"); ++ kmem_cache_destroy(hp_handler_slab); ++ pr_info("qman_test_hotpotato finished\n"); ++} +diff --git a/drivers/staging/fsl_qbman/qman_utility.c b/drivers/staging/fsl_qbman/qman_utility.c +new file mode 100644 +index 0000000..fa2f40b +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_utility.c +@@ -0,0 +1,130 @@ ++/* Copyright 2008-2011 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * 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. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "qman_private.h" ++ ++/* ----------------- */ ++/* --- FQID Pool --- */ ++ ++struct qman_fqid_pool { ++ /* Base and size of the FQID range */ ++ u32 fqid_base; ++ u32 total; ++ /* Number of FQIDs currently "allocated" */ ++ u32 used; ++ /* Allocation optimisation. When 'usedfqid_base = fqid_start; ++ pool->total = num; ++ pool->used = 0; ++ pool->next = 0; ++ pool->bits = kmalloc(QNUM_BYTES(num), GFP_KERNEL); ++ if (!pool->bits) { ++ kfree(pool); ++ return NULL; ++ } ++ memset(pool->bits, 0, QNUM_BYTES(num)); ++ /* If num is not an even multiple of QLONG_BITS (or even 8, for ++ * byte-oriented searching) then we fill the trailing bits with 1, to ++ * make them look allocated (permanently). */ ++ for (i = num + 1; i < QNUM_BITS(num); i++) ++ set_bit(i, pool->bits); ++ return pool; ++} ++EXPORT_SYMBOL(qman_fqid_pool_create); ++ ++int qman_fqid_pool_destroy(struct qman_fqid_pool *pool) ++{ ++ int ret = pool->used; ++ kfree(pool->bits); ++ kfree(pool); ++ return ret; ++} ++EXPORT_SYMBOL(qman_fqid_pool_destroy); ++ ++int qman_fqid_pool_alloc(struct qman_fqid_pool *pool, u32 *fqid) ++{ ++ int ret; ++ if (pool->used == pool->total) ++ return -ENOMEM; ++ *fqid = pool->fqid_base + pool->next; ++ ret = test_and_set_bit(pool->next, pool->bits); ++ BUG_ON(ret); ++ if (++pool->used == pool->total) ++ return 0; ++ pool->next = find_next_zero_bit(pool->bits, pool->total, pool->next); ++ if (pool->next >= pool->total) ++ pool->next = find_first_zero_bit(pool->bits, pool->total); ++ BUG_ON(pool->next >= pool->total); ++ return 0; ++} ++EXPORT_SYMBOL(qman_fqid_pool_alloc); ++ ++void qman_fqid_pool_free(struct qman_fqid_pool *pool, u32 fqid) ++{ ++ int ret; ++ ++ fqid -= pool->fqid_base; ++ ret = test_and_clear_bit(fqid, pool->bits); ++ BUG_ON(!ret); ++ if (pool->used-- == pool->total) ++ pool->next = fqid; ++} ++EXPORT_SYMBOL(qman_fqid_pool_free); ++ ++u32 qman_fqid_pool_used(struct qman_fqid_pool *pool) ++{ ++ return pool->used; ++} ++EXPORT_SYMBOL(qman_fqid_pool_used); +diff --git a/drivers/staging/fsl_rman/Kconfig b/drivers/staging/fsl_rman/Kconfig +new file mode 100644 +index 0000000..ee34e03 +--- /dev/null ++++ b/drivers/staging/fsl_rman/Kconfig +@@ -0,0 +1,4 @@ ++config FSL_RMAN_UIO ++ bool "Freescale RapidIO Message Manager support" ++ depends on FSL_DPA && UIO ++ default y +diff --git a/drivers/staging/fsl_rman/Makefile b/drivers/staging/fsl_rman/Makefile +new file mode 100644 +index 0000000..f712470 +--- /dev/null ++++ b/drivers/staging/fsl_rman/Makefile +@@ -0,0 +1,2 @@ ++# Rman ++obj-$(CONFIG_FSL_RMAN_UIO) += rman_uio_driver.o +diff --git a/drivers/staging/fsl_rman/rman_uio_driver.c b/drivers/staging/fsl_rman/rman_uio_driver.c +new file mode 100644 +index 0000000..e5bfae7 +--- /dev/null ++++ b/drivers/staging/fsl_rman/rman_uio_driver.c +@@ -0,0 +1,345 @@ ++/* ++ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. ++ * ++ * Author: Minghuan Lian ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static const char rman_uio_version[] = "Rman UIO driver v1.0"; ++ ++#define IB_INDEX_OFFSET 12 ++#define MMIER 0x0420 /* Message manage Interrupt Enable Register*/ ++#define MMEDR 0x0424 /* Message manager error detect register */ ++#define MMEDR_CLEAR 0x800000FF ++ ++struct rman_uio_info { ++ atomic_t ref; /* exclusive, only one open() at a time */ ++ struct uio_info uio; ++ char name[30]; ++}; ++ ++struct rman_dev { ++ u32 revision; ++ int irq; ++ void __iomem *global_regs; ++ struct device *dev; ++ struct rman_uio_info info; ++ struct resource *res; ++ struct list_head ib_list; ++}; ++ ++struct rman_inbound_block { ++ struct list_head node; ++ u32 index; ++ struct device *dev; ++ struct rman_uio_info info; ++ struct resource *res; ++}; ++ ++static int rman_uio_open(struct uio_info *info, struct inode *inode) ++{ ++ struct rman_uio_info *i = container_of(info, struct rman_uio_info, uio); ++ if (!atomic_dec_and_test(&i->ref)) { ++ pr_err("%s: failing non-exclusive open()\n", i->name); ++ atomic_inc(&i->ref); ++ return -EBUSY; ++ } ++ return 0; ++} ++ ++static int rman_uio_release(struct uio_info *info, struct inode *inode) ++{ ++ struct rman_uio_info *i = container_of(info, struct rman_uio_info, uio); ++ atomic_inc(&i->ref); ++ return 0; ++} ++ ++static irqreturn_t rman_uio_irq_handler(int irq, struct uio_info *dev_info) ++{ ++ struct rman_dev *rmdev = dev_info->priv; ++ u32 status; ++ ++ status = in_be32(rmdev->global_regs + MMEDR); ++ ++ if (status) { ++ /* disable interrupt */ ++ out_be32(rmdev->global_regs + MMIER, 0); ++ return IRQ_HANDLED; ++ } else ++ return IRQ_NONE; ++} ++ ++static int __init rman_uio_init(struct rman_dev *rmdev) ++{ ++ int ret; ++ struct rman_uio_info *info; ++ ++ info = &rmdev->info; ++ atomic_set(&info->ref, 1); ++ info->uio.name = info->name; ++ info->uio.version = rman_uio_version; ++ info->uio.mem[0].name = "rman regs"; ++ info->uio.mem[0].addr = rmdev->res->start; ++ info->uio.mem[0].size = rmdev->res->end - rmdev->res->start + 1; ++ info->uio.mem[0].internal_addr = rmdev->global_regs; ++ info->uio.mem[0].memtype = UIO_MEM_PHYS; ++ info->uio.irq = rmdev->irq; ++ info->uio.irq_flags = IRQF_SHARED; ++ info->uio.handler = rman_uio_irq_handler; ++ info->uio.open = rman_uio_open; ++ info->uio.release = rman_uio_release; ++ info->uio.priv = rmdev; ++ ret = uio_register_device(rmdev->dev, &info->uio); ++ if (ret) { ++ pr_err("rman_uio: UIO registration failed\n"); ++ return ret; ++ } ++ return 0; ++} ++ ++static int __init rman_ib_uio_init(struct rman_inbound_block *ib) ++{ ++ int ret; ++ struct rman_uio_info *info; ++ ++ info = &ib->info; ++ atomic_set(&info->ref, 1); ++ info->uio.name = info->name; ++ info->uio.version = rman_uio_version; ++ info->uio.mem[0].name = "rman inbound block regs"; ++ info->uio.mem[0].addr = ib->res->start; ++ info->uio.mem[0].size = ib->res->end - ib->res->start + 1; ++ info->uio.mem[0].memtype = UIO_MEM_PHYS; ++ info->uio.open = rman_uio_open; ++ info->uio.release = rman_uio_release; ++ info->uio.priv = ib; ++ ret = uio_register_device(ib->dev, &info->uio); ++ if (ret) { ++ pr_err("rman_ib_uio: UIO registration failed\n"); ++ return ret; ++ } ++ return 0; ++} ++ ++static int fsl_rman_ib_probe(struct device_node *ib_node, ++ struct rman_dev *rmdev) ++{ ++ struct rman_inbound_block *ib; ++ struct resource regs; ++ int err; ++ ++ if (!ib_node || !rmdev) ++ return -EINVAL; ++ ++ ib = kzalloc(sizeof(*ib), GFP_KERNEL); ++ if (!ib) { ++ dev_err(rmdev->dev, "Can't alloc memory for inbound_block\n"); ++ return -ENOMEM; ++ } ++ ++ ib->dev = rmdev->dev; ++ ++ err = of_address_to_resource(ib_node, 0, ®s); ++ if (unlikely(err < 0)) { ++ dev_err(ib->dev, "Can't get property 'reg'\n"); ++ err = -EFAULT; ++ goto _err; ++ } ++ ++ ib->index = (regs.start >> IB_INDEX_OFFSET) & 0xf; ++ snprintf(ib->info.name, sizeof(ib->info.name)-1, ++ "rman-inbound-block%d", ib->index); ++ ++ ib->res = devm_request_mem_region(rmdev->dev, regs.start, ++ regs.end + 1 - regs.start, ++ ib->info.name); ++ if (unlikely(!ib->res)) { ++ dev_err(ib->dev, "devm_request_mem_region failed\n"); ++ err = -ENOMEM; ++ goto _err; ++ } ++ dev_dbg(ib->dev, ++ "inbound block%d reg start 0x%016llx, size 0x%016llx.\n", ++ ib->index, ib->res->start, ++ ib->res->end + 1 - ib->res->start); ++ ++ err = rman_ib_uio_init(ib); ++ if (err) ++ goto _err; ++ ++ list_add(&ib->node, &rmdev->ib_list); ++ dev_info(ib->dev, "RMan inbound block%d initialized.\n", ib->index); ++ return 0; ++_err: ++ kfree(ib); ++ return err; ++} ++ ++static int fsl_rman_ib_remove(struct rman_inbound_block *ib) ++{ ++ if (!ib) ++ return 0; ++ uio_unregister_device(&ib->info.uio); ++ kfree(ib); ++ return 0; ++} ++ ++static int __devinit fsl_rman_probe(struct platform_device *dev) ++{ ++ struct resource regs; ++ struct rman_dev *rman_dev; ++ struct device_node *rman_node, *child; ++ struct rman_inbound_block *ib, *tmp; ++ int err; ++ ++ rman_node = dev->dev.of_node; ++ if (!rman_node) { ++ dev_err(&dev->dev, "Device OF-Node is NULL"); ++ return -EFAULT; ++ } ++ dev_info(&dev->dev, "Of-device full name %s initialized\n", ++ rman_node->full_name); ++ ++ rman_dev = kzalloc(sizeof(struct rman_dev), GFP_KERNEL); ++ if (!rman_dev) { ++ dev_err(&dev->dev, "Can't allocate memory for 'rman_dev'\n"); ++ return -ENOMEM; ++ } ++ ++ rman_dev->dev = &dev->dev; ++ INIT_LIST_HEAD(&rman_dev->ib_list); ++ platform_set_drvdata(dev, rman_dev); ++ ++ for_each_child_of_node(rman_node, child) { ++ if (of_device_is_compatible(child, "fsl,rman-inbound-block")) ++ fsl_rman_ib_probe(child, rman_dev); ++ ++ if (of_device_is_compatible(child, "fsl,rman-global-cfg")) { ++ err = of_address_to_resource(child, 0, ®s); ++ if (unlikely(err < 0)) { ++ dev_err(&dev->dev, ++ "Can't get property 'reg'\n"); ++ err = -EFAULT; ++ goto _err; ++ } ++ } ++ } ++ ++ snprintf(rman_dev->info.name, sizeof(rman_dev->info.name)-1, ++ "rman-uio"); ++ rman_dev->res = devm_request_mem_region(&dev->dev, regs.start, ++ regs.end + 1 - regs.start, ++ rman_dev->info.name); ++ dev_dbg(&dev->dev, "global regs start 0x%016llx, size 0x%016llx.\n", ++ rman_dev->res->start, ++ rman_dev->res->end + 1 - rman_dev->res->start); ++ if (unlikely(rman_dev->res == NULL)) { ++ dev_err(&dev->dev, "devm_request_mem_region failed\n"); ++ err = -ENOMEM; ++ goto _err; ++ } ++ ++ rman_dev->global_regs = devm_ioremap(&dev->dev, rman_dev->res->start, ++ rman_dev->res->end - rman_dev->res->start + 1); ++ if (unlikely(rman_dev->global_regs == 0)) { ++ dev_err(&dev->dev, "devm_ioremap failed\n"); ++ err = -EIO; ++ goto _err; ++ } ++ ++ rman_dev->irq = irq_of_parse_and_map(rman_node, 0); ++ dev_dbg(rman_dev->dev, "errirq: %d\n", rman_dev->irq); ++ ++ err = rman_uio_init(rman_dev); ++ if (err) ++ goto _err; ++ return 0; ++ ++_err: ++ platform_set_drvdata(dev, NULL); ++ list_for_each_entry_safe(ib, tmp, &rman_dev->ib_list, node) { ++ list_del(&ib->node); ++ fsl_rman_ib_remove(ib); ++ } ++ kfree(rman_dev); ++ return err; ++} ++ ++static int __devexit fsl_rman_remove(struct platform_device *dev) ++{ ++ struct rman_dev *rman_dev = platform_get_drvdata(dev); ++ struct rman_inbound_block *ib, *tmp; ++ ++ if (!rman_dev) ++ return 0; ++ ++ list_for_each_entry_safe(ib, tmp, &rman_dev->ib_list, node) { ++ list_del(&ib->node); ++ fsl_rman_ib_remove(ib); ++ } ++ ++ uio_unregister_device(&rman_dev->info.uio); ++ platform_set_drvdata(dev, NULL); ++ kfree(rman_dev); ++ return 0; ++} ++ ++static const struct of_device_id fsl_of_rman_match[] = { ++ { ++ .compatible = "fsl,rman", ++ }, ++ {} ++}; ++ ++static struct platform_driver fsl_rman_driver = { ++ .driver = { ++ .name = "fsl-of-rman", ++ .owner = THIS_MODULE, ++ .of_match_table = fsl_of_rman_match, ++ }, ++ .probe = fsl_rman_probe, ++ .remove = __devexit_p(fsl_rman_remove), ++}; ++ ++static __init int fsl_rman_init(void) ++{ ++ int err; ++ ++ err = platform_driver_register(&fsl_rman_driver); ++ if (unlikely(err < 0)) ++ pr_warning( ++ ": %s:%hu:%s(): platform_driver_register() = %d\n", ++ __FILE__, __LINE__, __func__, err); ++ ++ return err; ++} ++ ++static void __exit fsl_rman_exit(void) ++{ ++ platform_driver_unregister(&fsl_rman_driver); ++} ++ ++module_init(fsl_rman_init); ++module_exit(fsl_rman_exit); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/staging/ft1000/ft1000-pcmcia/boot.h b/drivers/staging/ft1000/ft1000-pcmcia/boot.h +deleted file mode 100644 +index 1fc4ac1..0000000 +--- a/drivers/staging/ft1000/ft1000-pcmcia/boot.h ++++ /dev/null +@@ -1,158 +0,0 @@ +-//--------------------------------------------------------------------------- +-// FT1000 driver for Flarion Flash OFDM NIC Device +-// +-// Copyright (C) 2002 Flarion Technologies, 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 as published by the Free +-// Software Foundation; either version 2 of the License, or (at your option) any +-// later version. This program is distributed in the hope that it will be useful, +-// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +-// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +-// more details. You should have received a copy of the GNU General Public +-// License along with this program; if not, write to the +-// Free Software Foundation, Inc., 59 Temple Place - +-// Suite 330, Boston, MA 02111-1307, USA. +-//--------------------------------------------------------------------------- +-// +-// File: boot.h +-// +-// Description: boatloader +-// +-// History: +-// 1/11/05 Whc Ported to Linux. +-// +-//--------------------------------------------------------------------------- +-#ifndef _BOOTH_ +-#define _BOOTH_ +- +-// Official bootloader +-unsigned char bootimage [] = { +-0x00,0x00,0x01,0x5E,0x00,0x00 +-,0x00,0x00,0x00,0x00,0x02,0xD7 +-,0x00,0x00,0x01,0x5E,0x46,0xB3 +-,0xE6,0x02,0x00,0x98,0xE6,0x8C +-,0x00,0x98,0xFB,0x92,0xFF,0xFF +-,0x98,0xFB,0x94,0xFF,0xFF,0x98 +-,0xFB,0x06,0x08,0x00,0x98,0xFB +-,0x96,0x84,0x00,0x98,0xFB,0x08 +-,0x1C,0x00,0x98,0xFB,0x51,0x25 +-,0x10,0x1C,0x00,0xE6,0x51,0x01 +-,0x07,0xFD,0x4C,0xFF,0x20,0xF5 +-,0x51,0x02,0x20,0x08,0x00,0x4C +-,0xFF,0x20,0x3C,0x00,0xC0,0x64 +-,0x98,0xC0,0x66,0x98,0xC0,0x68 +-,0x98,0xC0,0x6A,0x98,0xC0,0x6C +-,0x98,0x90,0x08,0x90,0x09,0x90 +-,0x0A,0x90,0x0B,0x90,0x0C,0x90 +-,0x0D,0x90,0x0E,0x90,0x0F,0x90 +-,0x04,0x90,0x06,0xFB,0x51,0x22 +-,0x16,0x08,0x03,0xFB,0x51,0x52 +-,0x16,0x08,0x04,0xFB,0x51,0x24 +-,0x2B,0x08,0x06,0xFB,0x51,0x54 +-,0x2B,0x08,0x07,0xFB,0x51,0x24 +-,0x2B,0x08,0x09,0xFB,0x51,0x54 +-,0x2B,0x08,0x0A,0xFB,0x51,0x12 +-,0x16,0x08,0x0C,0xFB,0x51,0x52 +-,0x16,0x08,0x0D,0x78,0x00,0x00 +-,0x00,0x16,0x00,0x00,0xEC,0x31 +-,0xAE,0x00,0x00,0x81,0x4C,0x0F +-,0xE6,0x43,0xFF,0xEC,0x31,0x4E +-,0x00,0x00,0x91,0xEC,0x31,0xAE +-,0x00,0x00,0x91,0x4C,0x0F,0xE6 +-,0x43,0xFF,0xEC,0x31,0x5E,0x00 +-,0x00,0xA1,0xEB,0x31,0x08,0x00 +-,0x00,0xA6,0xEB,0x31,0x08,0x00 +-,0x00,0xAC,0x3C,0x00,0xEB,0x31 +-,0x08,0x00,0x00,0xA8,0x76,0xFE +-,0xFE,0x08,0xEB,0x31,0x08,0x20 +-,0x00,0x00,0x76,0xFF,0xFF,0x18 +-,0xED,0x31,0x08,0x20,0x00,0x00 +-,0x26,0x10,0x04,0x10,0xF5,0x3C +-,0x01,0x3C,0x00,0x08,0x01,0x12 +-,0x3C,0x11,0x3C,0x00,0x08,0x01 +-,0x0B,0x08,0x00,0x6D,0xEC,0x31 +-,0xAE,0x20,0x00,0x06,0xED,0x4D +-,0x08,0x00,0x00,0x67,0x80,0x6F +-,0x00,0x01,0x0B,0x6F,0x00,0x02 +-,0x2E,0x76,0xEE,0x01,0x48,0x06 +-,0x01,0x39,0xED,0x4D,0x18,0x00 +-,0x02,0xED,0x4D,0x08,0x00,0x04 +-,0x14,0x06,0xA4,0xED,0x31,0x22 +-,0x00,0x00,0xAC,0x76,0xEE,0x07 +-,0x48,0x6D,0x22,0x01,0x1E,0x08 +-,0x01,0x58,0xEB,0x31,0x08,0x00 +-,0x00,0xAC,0x06,0xFF,0xBA,0x3C +-,0x00,0xEB,0x31,0x08,0x20,0x00 +-,0x04,0x3C,0x30,0xEB,0x31,0x08 +-,0x20,0x00,0x02,0x3C,0x10,0xEB +-,0x31,0x08,0x20,0x00,0x00,0xED +-,0x31,0x08,0x20,0x00,0x00,0x04 +-,0x10,0xF7,0xED,0x31,0x08,0x00 +-,0x00,0xA2,0x91,0x00,0x9C,0x3C +-,0x80,0xEB,0x31,0x08,0x20,0x00 +-,0x04,0x3C,0x20,0xEB,0x31,0x08 +-,0x20,0x00,0x02,0x3C,0x10,0xEB +-,0x31,0x08,0x20,0x00,0x00,0xED +-,0x31,0x08,0x20,0x00,0x00,0x04 +-,0x10,0xF7,0xED,0x31,0x08,0x20 +-,0x00,0x04,0x42,0x10,0x90,0x08 +-,0xEC,0x31,0xAE,0x20,0x00,0x06 +-,0xA4,0x41,0x08,0x00,0xB6,0xED +-,0x41,0x28,0x7D,0xFF,0xFF,0x22 +-,0xB3,0x40,0x98,0x2A,0x32,0xEB +-,0x41,0x28,0xB4,0x43,0xFC,0x05 +-,0xFF,0xE6,0xA0,0x31,0x20,0x00 +-,0x06,0xEB,0x31,0x08,0x20,0x00 +-,0x04,0x3C,0x20,0xEB,0x31,0x08 +-,0x20,0x00,0x02,0x3C,0x10,0xEB +-,0x31,0x08,0x20,0x00,0x00,0xED +-,0x31,0x08,0x20,0x00,0x00,0x04 +-,0x10,0xF7,0xED,0x31,0x08,0x20 +-,0x00,0x04,0x42,0x10,0x90,0x08 +-,0xEC,0x31,0xAE,0x20,0x00,0x06 +-,0xA4,0x41,0x08,0x00,0x68,0xED +-,0x41,0x28,0x7D,0xFF,0xFF,0x22 +-,0xB3,0x40,0x98,0x2A,0x32,0xEB +-,0x41,0x28,0xB4,0x43,0xFC,0x05 +-,0xFF,0xE6,0x48,0x04,0xEB,0x31 +-,0x08,0x20,0x00,0x04,0xEB,0x31 +-,0x18,0x20,0x00,0x02,0x3C,0x11 +-,0xEB,0x31,0x18,0x20,0x00,0x00 +-,0xED,0x31,0x08,0x20,0x00,0x00 +-,0x04,0x10,0xF7,0xED,0x31,0x08 +-,0x20,0x00,0x02,0x66,0x00,0x6F +-,0x00,0x01,0x16,0x76,0xEE,0x06 +-,0x48,0x4A,0x1E,0x48,0x04,0xED +-,0x31,0x08,0x20,0x00,0x04,0xEB +-,0x31,0x08,0x00,0x00,0xA4,0x48 +-,0x04,0xED,0x31,0x08,0x20,0x00 +-,0x04,0xEB,0x31,0x08,0x00,0x00 +-,0xA2,0x48,0x04,0x20,0x20,0x4A +-,0x7C,0x46,0x82,0x50,0x05,0x50 +-,0x15,0xB5,0x1E,0x98,0xED,0x31 +-,0x08,0x00,0x00,0xA8,0x10,0x47 +-,0x3B,0x2C,0x01,0xDB,0x40,0x11 +-,0x98,0xC1,0x1E,0x98,0x10,0x07 +-,0x30,0xF9,0x40,0x07,0x18,0x98 +-,0x2A,0x10,0xEB,0x31,0x08,0x00 +-,0x00,0xA8,0xA4,0x1E,0x98,0xBB +-,0x1E,0x98,0x50,0x14,0x50,0x04 +-,0x46,0x83,0x48,0x04,0x02,0x01 +-,0x00,0x50,0x05,0x50,0x15,0x10 +-,0x87,0x3F,0x90,0x2B,0x18,0x01 +-,0x00,0xC0,0x31,0x00,0x00,0xAE +-,0xDF,0x41,0x00,0x08,0x00,0x1A +-,0x42,0x11,0x67,0x01,0xDF,0x41 +-,0x02,0x08,0x00,0x10,0x42,0x11 +-,0x62,0x01,0xB4,0x43,0x4A,0x68 +-,0x50,0x14,0x50,0x04,0x24,0x10 +-,0x48,0x04,0xF2,0x31,0x00,0x01 +-,0x00,0x00,0xAE,0xF6,0x31,0x00 +-,0x01,0x00,0x00,0xAE,0x62,0xE4 +-,0xE5,0x61,0x04,0x48,0x04,0xE5 +-,0x63,0x05,0x48,0x04,0x20,0x20 +-,0x00,0x00,0x00,0x00 +-}; +- +-#endif +diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.img b/drivers/staging/ft1000/ft1000-pcmcia/ft1000.img +deleted file mode 100644 +index aad3c80..0000000 +Binary files a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.img and /dev/null differ +diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +index b3d743a..61b33f3 100644 +--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c ++++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +@@ -2194,16 +2194,12 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link, + info->AsicID = ft1000_read_reg(dev, FT1000_REG_ASIC_ID); + if (info->AsicID == ELECTRABUZZ_ID) { + DEBUG(0, "ft1000_hw: ELECTRABUZZ ASIC\n"); +- if (request_firmware(&fw_entry, "ft1000.img", &link->dev) != 0) { +- printk(KERN_INFO "ft1000: Could not open ft1000.img\n"); ++ if (request_firmware(&fw_entry, "ft1000.img", &link->dev) != 0) + goto err_unreg; +- } + } else { + DEBUG(0, "ft1000_hw: MAGNEMITE ASIC\n"); +- if (request_firmware(&fw_entry, "ft2000.img", &link->dev) != 0) { +- printk(KERN_INFO "ft1000: Could not open ft2000.img\n"); ++ if (request_firmware(&fw_entry, "ft2000.img", &link->dev) != 0) + goto err_unreg; +- } + } + + ft1000_enable_interrupts(dev); +diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c +index 79482ac..17a7aef 100644 +--- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c ++++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c +@@ -139,10 +139,8 @@ static int ft1000_probe(struct usb_interface *interface, + ft1000dev->bulk_out_endpointAddr); + + ret = request_firmware(&dsp_fw, "ft3000.img", &dev->dev); +- if (ret < 0) { +- printk(KERN_ERR "Error request_firmware().\n"); ++ if (ret) + goto err_fw; +- } + + size = max_t(uint, dsp_fw->size, 4096); + pFileStart = kmalloc(size, GFP_KERNEL); +diff --git a/drivers/staging/ft1000/ft1000-usb/ft3000.img b/drivers/staging/ft1000/ft1000-usb/ft3000.img +deleted file mode 100644 +index 7bef6bd..0000000 +Binary files a/drivers/staging/ft1000/ft1000-usb/ft3000.img and /dev/null differ +diff --git a/drivers/staging/gma500/Kconfig b/drivers/staging/gma500/Kconfig +deleted file mode 100644 +index bfe2166..0000000 +--- a/drivers/staging/gma500/Kconfig ++++ /dev/null +@@ -1,33 +0,0 @@ +-config DRM_PSB +- tristate "Intel GMA5/600 KMS Framebuffer" +- depends on DRM && PCI && X86 +- select FB_CFB_COPYAREA +- select FB_CFB_FILLRECT +- select FB_CFB_IMAGEBLIT +- select DRM_KMS_HELPER +- select DRM_TTM +- help +- Say yes for an experimental 2D KMS framebuffer driver for the +- Intel GMA500 ('Poulsbo') and other Intel IMG based graphics +- devices. +- +-config DRM_PSB_MRST +- bool "Intel GMA600 support (Experimental)" +- depends on DRM_PSB +- help +- Say yes to include support for GMA600 (Intel Moorestown/Oaktrail) +- platforms with LVDS ports. HDMI and MIPI are not currently +- supported. +- +-config DRM_PSB_MFLD +- bool "Intel Medfield support (Experimental)" +- depends on DRM_PSB +- help +- Say yes to include support for Intel Medfield platforms with MIPI +- interfaces. +- +-config DRM_PSB_CDV +- bool "Intel Cedarview support (Experimental)" +- depends on DRM_PSB +- help +- Say yes to include support for Intel Cedarview platforms +diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile +deleted file mode 100644 +index c729868..0000000 +--- a/drivers/staging/gma500/Makefile ++++ /dev/null +@@ -1,52 +0,0 @@ +-# +-# KMS driver for the GMA500 +-# +-ccflags-y += -Iinclude/drm +- +-psb_gfx-y += gem_glue.o \ +- accel_2d.o \ +- backlight.o \ +- framebuffer.o \ +- gem.o \ +- gtt.o \ +- intel_bios.o \ +- intel_i2c.o \ +- intel_opregion.o \ +- mmu.o \ +- power.o \ +- psb_drv.o \ +- psb_intel_display.o \ +- psb_intel_lvds.o \ +- psb_intel_modes.o \ +- psb_intel_sdvo.o \ +- psb_lid.o \ +- psb_irq.o \ +- psb_device.o \ +- mid_bios.o +- +-psb_gfx-$(CONFIG_DRM_PSB_CDV) += cdv_device.o \ +- cdv_intel_crt.o \ +- cdv_intel_display.o \ +- cdv_intel_hdmi.o \ +- cdv_intel_lvds.o +- +-psb_gfx-$(CONFIG_DRM_PSB_MRST) += mrst_device.o \ +- mrst_crtc.o \ +- mrst_lvds.o \ +- mrst_hdmi.o \ +- mrst_hdmi_i2c.o +- +-psb_gfx-$(CONFIG_DRM_PSB_MFLD) += mdfld_device.o \ +- mdfld_output.o \ +- mdfld_pyr_cmd.o \ +- mdfld_tmd_vid.o \ +- mdfld_tpo_cmd.o \ +- mdfld_tpo_vid.o \ +- mdfld_dsi_pkg_sender.o \ +- mdfld_dsi_dpi.o \ +- mdfld_dsi_output.o \ +- mdfld_dsi_dbi.o \ +- mdfld_dsi_dbi_dpu.o \ +- mdfld_intel_display.o +- +-obj-$(CONFIG_DRM_PSB) += psb_gfx.o +diff --git a/drivers/staging/gma500/TODO b/drivers/staging/gma500/TODO +deleted file mode 100644 +index fc83615..0000000 +--- a/drivers/staging/gma500/TODO ++++ /dev/null +@@ -1,15 +0,0 @@ +-- Sort out the power management side. Not important for Poulsbo but +- matters for Moorestown/Medfield +-- Debug Oaktrail/Moorestown support (single pipe, no BIOS on mrst, +- some other differences) +-- Add 2D acceleration via console and DRM +-- Add scrolling acceleration using the GTT to do remapping on the main +- framebuffer. +-- HDMI testing +-- Oaktrail HDMI and other features +-- Oaktrail MIPI +-- Medfield needs a lot of further love +- +-As per kernel policy and the in the interest of the safety of various +-kittens there is no support or plans to add hooks for the closed user space +-stuff. +diff --git a/drivers/staging/gma500/accel_2d.c b/drivers/staging/gma500/accel_2d.c +deleted file mode 100644 +index 114b99a..0000000 +--- a/drivers/staging/gma500/accel_2d.c ++++ /dev/null +@@ -1,414 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2007-2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to +- * develop this driver. +- * +- **************************************************************************/ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include "psb_drv.h" +-#include "psb_reg.h" +-#include "framebuffer.h" +- +-/** +- * psb_spank - reset the 2D engine +- * @dev_priv: our PSB DRM device +- * +- * Soft reset the graphics engine and then reload the necessary registers. +- * We use this at initialisation time but it will become relevant for +- * accelerated X later +- */ +-void psb_spank(struct drm_psb_private *dev_priv) +-{ +- PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET | +- _PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET | +- _PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET | +- _PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET); +- PSB_RSGX32(PSB_CR_SOFT_RESET); +- +- msleep(1); +- +- PSB_WSGX32(0, PSB_CR_SOFT_RESET); +- wmb(); +- PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT, +- PSB_CR_BIF_CTRL); +- wmb(); +- (void) PSB_RSGX32(PSB_CR_BIF_CTRL); +- +- msleep(1); +- PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT, +- PSB_CR_BIF_CTRL); +- (void) PSB_RSGX32(PSB_CR_BIF_CTRL); +- PSB_WSGX32(dev_priv->gtt.gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); +-} +- +-/** +- * psb2_2d_wait_available - wait for FIFO room +- * @dev_priv: our DRM device +- * @size: size (in dwords) of the command we want to issue +- * +- * Wait until there is room to load the FIFO with our data. If the +- * device is not responding then reset it +- */ +-static int psb_2d_wait_available(struct drm_psb_private *dev_priv, +- unsigned size) +-{ +- uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF); +- unsigned long t = jiffies + HZ; +- +- while (avail < size) { +- avail = PSB_RSGX32(PSB_CR_2D_SOCIF); +- if (time_after(jiffies, t)) { +- psb_spank(dev_priv); +- return -EIO; +- } +- } +- return 0; +-} +- +-/** +- * psb_2d_submit - submit a 2D command +- * @dev_priv: our DRM device +- * @cmdbuf: command to issue +- * @size: length (in dwords) +- * +- * Issue one or more 2D commands to the accelerator. This needs to be +- * serialized later when we add the GEM interfaces for acceleration +- */ +-static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, +- unsigned size) +-{ +- int ret = 0; +- int i; +- unsigned submit_size; +- unsigned long flags; +- +- spin_lock_irqsave(&dev_priv->lock_2d, flags); +- while (size > 0) { +- submit_size = (size < 0x60) ? size : 0x60; +- size -= submit_size; +- ret = psb_2d_wait_available(dev_priv, submit_size); +- if (ret) +- break; +- +- submit_size <<= 2; +- +- for (i = 0; i < submit_size; i += 4) +- PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i); +- +- (void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4); +- } +- spin_unlock_irqrestore(&dev_priv->lock_2d, flags); +- return ret; +-} +- +- +-/** +- * psb_accel_2d_copy_direction - compute blit order +- * @xdir: X direction of move +- * @ydir: Y direction of move +- * +- * Compute the correct order setings to ensure that an overlapping blit +- * correctly copies all the pixels. +- */ +-static u32 psb_accel_2d_copy_direction(int xdir, int ydir) +-{ +- if (xdir < 0) +- return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL : +- PSB_2D_COPYORDER_TR2BL; +- else +- return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR : +- PSB_2D_COPYORDER_TL2BR; +-} +- +-/** +- * psb_accel_2d_copy - accelerated 2D copy +- * @dev_priv: our DRM device +- * @src_offset in bytes +- * @src_stride in bytes +- * @src_format psb 2D format defines +- * @dst_offset in bytes +- * @dst_stride in bytes +- * @dst_format psb 2D format defines +- * @src_x offset in pixels +- * @src_y offset in pixels +- * @dst_x offset in pixels +- * @dst_y offset in pixels +- * @size_x of the copied area +- * @size_y of the copied area +- * +- * Format and issue a 2D accelerated copy command. +- */ +-static int psb_accel_2d_copy(struct drm_psb_private *dev_priv, +- uint32_t src_offset, uint32_t src_stride, +- uint32_t src_format, uint32_t dst_offset, +- uint32_t dst_stride, uint32_t dst_format, +- uint16_t src_x, uint16_t src_y, +- uint16_t dst_x, uint16_t dst_y, +- uint16_t size_x, uint16_t size_y) +-{ +- uint32_t blit_cmd; +- uint32_t buffer[10]; +- uint32_t *buf; +- uint32_t direction; +- +- buf = buffer; +- +- direction = +- psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y); +- +- if (direction == PSB_2D_COPYORDER_BR2TL || +- direction == PSB_2D_COPYORDER_TR2BL) { +- src_x += size_x - 1; +- dst_x += size_x - 1; +- } +- if (direction == PSB_2D_COPYORDER_BR2TL || +- direction == PSB_2D_COPYORDER_BL2TR) { +- src_y += size_y - 1; +- dst_y += size_y - 1; +- } +- +- blit_cmd = +- PSB_2D_BLIT_BH | +- PSB_2D_ROT_NONE | +- PSB_2D_DSTCK_DISABLE | +- PSB_2D_SRCCK_DISABLE | +- PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction; +- +- *buf++ = PSB_2D_FENCE_BH; +- *buf++ = +- PSB_2D_DST_SURF_BH | dst_format | (dst_stride << +- PSB_2D_DST_STRIDE_SHIFT); +- *buf++ = dst_offset; +- *buf++ = +- PSB_2D_SRC_SURF_BH | src_format | (src_stride << +- PSB_2D_SRC_STRIDE_SHIFT); +- *buf++ = src_offset; +- *buf++ = +- PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) | +- (src_y << PSB_2D_SRCOFF_YSTART_SHIFT); +- *buf++ = blit_cmd; +- *buf++ = +- (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y << +- PSB_2D_DST_YSTART_SHIFT); +- *buf++ = +- (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y << +- PSB_2D_DST_YSIZE_SHIFT); +- *buf++ = PSB_2D_FLUSH_BH; +- +- return psbfb_2d_submit(dev_priv, buffer, buf - buffer); +-} +- +-/** +- * psbfb_copyarea_accel - copyarea acceleration for /dev/fb +- * @info: our framebuffer +- * @a: copyarea parameters from the framebuffer core +- * +- * Perform a 2D copy via the accelerator +- */ +-static void psbfb_copyarea_accel(struct fb_info *info, +- const struct fb_copyarea *a) +-{ +- struct psb_fbdev *fbdev = info->par; +- struct psb_framebuffer *psbfb = &fbdev->pfb; +- struct drm_device *dev = psbfb->base.dev; +- struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb; +- struct drm_psb_private *dev_priv = dev->dev_private; +- uint32_t offset; +- uint32_t stride; +- uint32_t src_format; +- uint32_t dst_format; +- +- if (!fb) +- return; +- +- offset = psbfb->gtt->offset; +- stride = fb->pitch; +- +- switch (fb->depth) { +- case 8: +- src_format = PSB_2D_SRC_332RGB; +- dst_format = PSB_2D_DST_332RGB; +- break; +- case 15: +- src_format = PSB_2D_SRC_555RGB; +- dst_format = PSB_2D_DST_555RGB; +- break; +- case 16: +- src_format = PSB_2D_SRC_565RGB; +- dst_format = PSB_2D_DST_565RGB; +- break; +- case 24: +- case 32: +- /* this is wrong but since we don't do blending its okay */ +- src_format = PSB_2D_SRC_8888ARGB; +- dst_format = PSB_2D_DST_8888ARGB; +- break; +- default: +- /* software fallback */ +- cfb_copyarea(info, a); +- return; +- } +- +- if (!gma_power_begin(dev, false)) { +- cfb_copyarea(info, a); +- return; +- } +- psb_accel_2d_copy(dev_priv, +- offset, stride, src_format, +- offset, stride, dst_format, +- a->sx, a->sy, a->dx, a->dy, a->width, a->height); +- gma_power_end(dev); +-} +- +-/** +- * psbfb_copyarea - 2D copy interface +- * @info: our framebuffer +- * @region: region to copy +- * +- * Copy an area of the framebuffer console either by the accelerator +- * or directly using the cfb helpers according to the request +- */ +-void psbfb_copyarea(struct fb_info *info, +- const struct fb_copyarea *region) +-{ +- if (unlikely(info->state != FBINFO_STATE_RUNNING)) +- return; +- +- /* Avoid the 8 pixel erratum */ +- if (region->width == 8 || region->height == 8 || +- (info->flags & FBINFO_HWACCEL_DISABLED)) +- return cfb_copyarea(info, region); +- +- psbfb_copyarea_accel(info, region); +-} +- +-/** +- * psbfb_sync - synchronize 2D +- * @info: our framebuffer +- * +- * Wait for the 2D engine to quiesce so that we can do CPU +- * access to the framebuffer again +- */ +-int psbfb_sync(struct fb_info *info) +-{ +- struct psb_fbdev *fbdev = info->par; +- struct psb_framebuffer *psbfb = &fbdev->pfb; +- struct drm_device *dev = psbfb->base.dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- unsigned long _end = jiffies + DRM_HZ; +- int busy = 0; +- unsigned long flags; +- +- spin_lock_irqsave(&dev_priv->lock_2d, flags); +- /* +- * First idle the 2D engine. +- */ +- +- if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) && +- ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0)) +- goto out; +- +- do { +- busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY); +- cpu_relax(); +- } while (busy && !time_after_eq(jiffies, _end)); +- +- if (busy) +- busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY); +- if (busy) +- goto out; +- +- do { +- busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & +- _PSB_C2B_STATUS_BUSY) != 0); +- cpu_relax(); +- } while (busy && !time_after_eq(jiffies, _end)); +- if (busy) +- busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & +- _PSB_C2B_STATUS_BUSY) != 0); +- +-out: +- spin_unlock_irqrestore(&dev_priv->lock_2d, flags); +- return (busy) ? -EBUSY : 0; +-} +- +-int psb_accel_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct drm_psb_2d_op *op = data; +- u32 *op_ptr = &op->cmd[0]; +- int i; +- struct drm_gem_object *obj; +- struct gtt_range *gtt; +- int err = -EINVAL; +- +- if (!dev_priv->ops->accel_2d) +- return -EOPNOTSUPP; +- if (op->size > PSB_2D_OP_BUFLEN) +- return -EINVAL; +- +- /* The GEM object being used. We need to support separate src/dst/etc +- in the end but for now keep them all the same */ +- obj = drm_gem_object_lookup(dev, file, op->src); +- if (obj == NULL) +- return -ENOENT; +- gtt = container_of(obj, struct gtt_range, gem); +- +- if (psb_gtt_pin(gtt) < 0) +- goto bad_2; +- for (i = 0; i < op->size; i++, op_ptr++) { +- u32 r = *op_ptr & 0xF0000000; +- /* Fill in the GTT offsets for the command buffer */ +- if (r == PSB_2D_SRC_SURF_BH || +- r == PSB_2D_DST_SURF_BH || +- r == PSB_2D_MASK_SURF_BH || +- r == PSB_2D_PAT_SURF_BH) { +- i++; +- op_ptr++; +- if (i == op->size) +- goto bad; +- if (*op_ptr) +- goto bad; +- *op_ptr = gtt->offset; +- continue; +- } +- } +- psbfb_2d_submit(dev_priv, op->cmd, op->size); +- err = 0; +-bad: +- psb_gtt_unpin(gtt); +-bad_2: +- drm_gem_object_unreference(obj); +- return err; +-} +diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c +deleted file mode 100644 +index 2079395..0000000 +--- a/drivers/staging/gma500/backlight.c ++++ /dev/null +@@ -1,49 +0,0 @@ +-/* +- * GMA500 Backlight Interface +- * +- * Copyright (c) 2009-2011, Intel Corporation. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: Eric Knopp +- * +- */ +- +-#include "psb_drv.h" +-#include "psb_intel_reg.h" +-#include "psb_intel_drv.h" +-#include "intel_bios.h" +-#include "power.h" +- +-int gma_backlight_init(struct drm_device *dev) +-{ +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- struct drm_psb_private *dev_priv = dev->dev_private; +- return dev_priv->ops->backlight_init(dev); +-#else +- return 0; +-#endif +-} +- +-void gma_backlight_exit(struct drm_device *dev) +-{ +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- struct drm_psb_private *dev_priv = dev->dev_private; +- if (dev_priv->backlight_device) { +- dev_priv->backlight_device->props.brightness = 0; +- backlight_update_status(dev_priv->backlight_device); +- backlight_device_unregister(dev_priv->backlight_device); +- } +-#endif +-} +diff --git a/drivers/staging/gma500/cdv_device.c b/drivers/staging/gma500/cdv_device.c +deleted file mode 100644 +index 8ec10ca..0000000 +--- a/drivers/staging/gma500/cdv_device.c ++++ /dev/null +@@ -1,350 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-#include +-#include +-#include +-#include "psb_drm.h" +-#include "psb_drv.h" +-#include "psb_reg.h" +-#include "psb_intel_reg.h" +-#include "intel_bios.h" +-#include "cdv_device.h" +- +-#define VGA_SR_INDEX 0x3c4 +-#define VGA_SR_DATA 0x3c5 +- +-static void cdv_disable_vga(struct drm_device *dev) +-{ +- u8 sr1; +- u32 vga_reg; +- +- vga_reg = VGACNTRL; +- +- outb(1, VGA_SR_INDEX); +- sr1 = inb(VGA_SR_DATA); +- outb(sr1 | 1<<5, VGA_SR_DATA); +- udelay(300); +- +- REG_WRITE(vga_reg, VGA_DISP_DISABLE); +- REG_READ(vga_reg); +-} +- +-static int cdv_output_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- cdv_disable_vga(dev); +- +- cdv_intel_crt_init(dev, &dev_priv->mode_dev); +- cdv_intel_lvds_init(dev, &dev_priv->mode_dev); +- +- /* These bits indicate HDMI not SDVO on CDV, but we don't yet support +- the HDMI interface */ +- if (REG_READ(SDVOB) & SDVO_DETECTED) +- cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB); +- if (REG_READ(SDVOC) & SDVO_DETECTED) +- cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC); +- return 0; +-} +- +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- +-/* +- * Poulsbo Backlight Interfaces +- */ +- +-#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ +-#define BLC_PWM_FREQ_CALC_CONSTANT 32 +-#define MHz 1000000 +- +-#define PSB_BLC_PWM_PRECISION_FACTOR 10 +-#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE +-#define PSB_BLC_MIN_PWM_REG_FREQ 0x2 +- +-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) +-#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) +- +-static int cdv_brightness; +-static struct backlight_device *cdv_backlight_device; +- +-static int cdv_get_brightness(struct backlight_device *bd) +-{ +- /* return locally cached var instead of HW read (due to DPST etc.) */ +- /* FIXME: ideally return actual value in case firmware fiddled with +- it */ +- return cdv_brightness; +-} +- +- +-static int cdv_backlight_setup(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- unsigned long core_clock; +- /* u32 bl_max_freq; */ +- /* unsigned long value; */ +- u16 bl_max_freq; +- uint32_t value; +- uint32_t blc_pwm_precision_factor; +- +- /* get bl_max_freq and pol from dev_priv*/ +- if (!dev_priv->lvds_bl) { +- dev_err(dev->dev, "Has no valid LVDS backlight info\n"); +- return -ENOENT; +- } +- bl_max_freq = dev_priv->lvds_bl->freq; +- blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; +- +- core_clock = dev_priv->core_freq; +- +- value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; +- value *= blc_pwm_precision_factor; +- value /= bl_max_freq; +- value /= blc_pwm_precision_factor; +- +- if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || +- value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) +- return -ERANGE; +- else { +- /* FIXME */ +- } +- return 0; +-} +- +-static int cdv_set_brightness(struct backlight_device *bd) +-{ +- int level = bd->props.brightness; +- +- /* Percentage 1-100% being valid */ +- if (level < 1) +- level = 1; +- +- /*cdv_intel_lvds_set_brightness(dev, level); FIXME */ +- cdv_brightness = level; +- return 0; +-} +- +-static const struct backlight_ops cdv_ops = { +- .get_brightness = cdv_get_brightness, +- .update_status = cdv_set_brightness, +-}; +- +-static int cdv_backlight_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- int ret; +- struct backlight_properties props; +- +- memset(&props, 0, sizeof(struct backlight_properties)); +- props.max_brightness = 100; +- props.type = BACKLIGHT_PLATFORM; +- +- cdv_backlight_device = backlight_device_register("psb-bl", +- NULL, (void *)dev, &cdv_ops, &props); +- if (IS_ERR(cdv_backlight_device)) +- return PTR_ERR(cdv_backlight_device); +- +- ret = cdv_backlight_setup(dev); +- if (ret < 0) { +- backlight_device_unregister(cdv_backlight_device); +- cdv_backlight_device = NULL; +- return ret; +- } +- cdv_backlight_device->props.brightness = 100; +- cdv_backlight_device->props.max_brightness = 100; +- backlight_update_status(cdv_backlight_device); +- dev_priv->backlight_device = cdv_backlight_device; +- return 0; +-} +- +-#endif +- +-/* +- * Provide the Cedarview specific chip logic and low level methods +- * for power management +- * +- * FIXME: we need to implement the apm/ospm base management bits +- * for this and the MID devices. +- */ +- +-static inline u32 CDV_MSG_READ32(uint port, uint offset) +-{ +- int mcr = (0x10<<24) | (port << 16) | (offset << 8); +- uint32_t ret_val = 0; +- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); +- pci_write_config_dword(pci_root, 0xD0, mcr); +- pci_read_config_dword(pci_root, 0xD4, &ret_val); +- pci_dev_put(pci_root); +- return ret_val; +-} +- +-static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value) +-{ +- int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; +- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); +- pci_write_config_dword(pci_root, 0xD4, value); +- pci_write_config_dword(pci_root, 0xD0, mcr); +- pci_dev_put(pci_root); +-} +- +-#define PSB_APM_CMD 0x0 +-#define PSB_APM_STS 0x04 +-#define PSB_PM_SSC 0x20 +-#define PSB_PM_SSS 0x30 +-#define PSB_PWRGT_GFX_MASK 0x3 +-#define CDV_PWRGT_DISPLAY_CNTR 0x000fc00c +-#define CDV_PWRGT_DISPLAY_STS 0x000fc00c +- +-static void cdv_init_pm(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 pwr_cnt; +- int i; +- +- dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, +- PSB_APMBA) & 0xFFFF; +- dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, +- PSB_OSPMBA) & 0xFFFF; +- +- /* Force power on for now */ +- pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD); +- pwr_cnt &= ~PSB_PWRGT_GFX_MASK; +- +- outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD); +- for (i = 0; i < 5; i++) { +- u32 pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS); +- if ((pwr_sts & PSB_PWRGT_GFX_MASK) == 0) +- break; +- udelay(10); +- } +- pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC); +- pwr_cnt &= ~CDV_PWRGT_DISPLAY_CNTR; +- outl(pwr_cnt, dev_priv->ospm_base + PSB_PM_SSC); +- for (i = 0; i < 5; i++) { +- u32 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); +- if ((pwr_sts & CDV_PWRGT_DISPLAY_STS) == 0) +- break; +- udelay(10); +- } +-} +- +-/** +- * cdv_save_display_registers - save registers lost on suspend +- * @dev: our DRM device +- * +- * Save the state we need in order to be able to restore the interface +- * upon resume from suspend +- * +- * FIXME: review +- */ +-static int cdv_save_display_registers(struct drm_device *dev) +-{ +- return 0; +-} +- +-/** +- * cdv_restore_display_registers - restore lost register state +- * @dev: our DRM device +- * +- * Restore register state that was lost during suspend and resume. +- * +- * FIXME: review +- */ +-static int cdv_restore_display_registers(struct drm_device *dev) +-{ +- return 0; +-} +- +-static int cdv_power_down(struct drm_device *dev) +-{ +- return 0; +-} +- +-static int cdv_power_up(struct drm_device *dev) +-{ +- return 0; +-} +- +-/* FIXME ? - shared with Poulsbo */ +-static void cdv_get_core_freq(struct drm_device *dev) +-{ +- uint32_t clock; +- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- pci_write_config_dword(pci_root, 0xD0, 0xD0050300); +- pci_read_config_dword(pci_root, 0xD4, &clock); +- pci_dev_put(pci_root); +- +- switch (clock & 0x07) { +- case 0: +- dev_priv->core_freq = 100; +- break; +- case 1: +- dev_priv->core_freq = 133; +- break; +- case 2: +- dev_priv->core_freq = 150; +- break; +- case 3: +- dev_priv->core_freq = 178; +- break; +- case 4: +- dev_priv->core_freq = 200; +- break; +- case 5: +- case 6: +- case 7: +- dev_priv->core_freq = 266; +- default: +- dev_priv->core_freq = 0; +- } +-} +- +-static int cdv_chip_setup(struct drm_device *dev) +-{ +- cdv_get_core_freq(dev); +- gma_intel_opregion_init(dev); +- psb_intel_init_bios(dev); +- return 0; +-} +- +-/* CDV is much like Poulsbo but has MID like SGX offsets and PM */ +- +-const struct psb_ops cdv_chip_ops = { +- .name = "Cedartrail", +- .accel_2d = 0, +- .pipes = 2, +- .sgx_offset = MRST_SGX_OFFSET, +- .chip_setup = cdv_chip_setup, +- +- .crtc_helper = &cdv_intel_helper_funcs, +- .crtc_funcs = &cdv_intel_crtc_funcs, +- +- .output_init = cdv_output_init, +- +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- .backlight_init = cdv_backlight_init, +-#endif +- +- .init_pm = cdv_init_pm, +- .save_regs = cdv_save_display_registers, +- .restore_regs = cdv_restore_display_registers, +- .power_down = cdv_power_down, +- .power_up = cdv_power_up, +-}; +diff --git a/drivers/staging/gma500/cdv_device.h b/drivers/staging/gma500/cdv_device.h +deleted file mode 100644 +index 2a88b7b..0000000 +--- a/drivers/staging/gma500/cdv_device.h ++++ /dev/null +@@ -1,36 +0,0 @@ +-/* +- * Copyright © 2011 Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs; +-extern const struct drm_crtc_funcs cdv_intel_crtc_funcs; +-extern void cdv_intel_crt_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev); +-extern void cdv_intel_lvds_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev); +-extern void cdv_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, +- int reg); +-extern struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev, +- struct drm_crtc *crtc); +- +-extern inline void cdv_intel_wait_for_vblank(struct drm_device *dev) +-{ +- /* Wait for 20ms, i.e. one cycle at 50hz. */ +- /* FIXME: msleep ?? */ +- mdelay(20); +-} +- +- +diff --git a/drivers/staging/gma500/cdv_intel_crt.c b/drivers/staging/gma500/cdv_intel_crt.c +deleted file mode 100644 +index efda63b..0000000 +--- a/drivers/staging/gma500/cdv_intel_crt.c ++++ /dev/null +@@ -1,326 +0,0 @@ +-/* +- * Copyright © 2006-2007 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Eric Anholt +- */ +- +-#include +-#include +- +-#include "intel_bios.h" +-#include "psb_drv.h" +-#include "psb_intel_drv.h" +-#include "psb_intel_reg.h" +-#include "power.h" +-#include +- +- +-static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode) +-{ +- struct drm_device *dev = encoder->dev; +- u32 temp, reg; +- reg = ADPA; +- +- temp = REG_READ(reg); +- temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); +- temp &= ~ADPA_DAC_ENABLE; +- +- switch (mode) { +- case DRM_MODE_DPMS_ON: +- temp |= ADPA_DAC_ENABLE; +- break; +- case DRM_MODE_DPMS_STANDBY: +- temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE; +- break; +- case DRM_MODE_DPMS_SUSPEND: +- temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE; +- break; +- case DRM_MODE_DPMS_OFF: +- temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE; +- break; +- } +- +- REG_WRITE(reg, temp); +-} +- +-static int cdv_intel_crt_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) +-{ +- int max_clock = 0; +- if (mode->flags & DRM_MODE_FLAG_DBLSCAN) +- return MODE_NO_DBLESCAN; +- +- /* The lowest clock for CDV is 20000KHz */ +- if (mode->clock < 20000) +- return MODE_CLOCK_LOW; +- +- /* The max clock for CDV is 355 instead of 400 */ +- max_clock = 355000; +- if (mode->clock > max_clock) +- return MODE_CLOCK_HIGH; +- +- if (mode->hdisplay > 1680 || mode->vdisplay > 1050) +- return MODE_PANEL; +- +- return MODE_OK; +-} +- +-static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- return true; +-} +- +-static void cdv_intel_crt_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- +- struct drm_device *dev = encoder->dev; +- struct drm_crtc *crtc = encoder->crtc; +- struct psb_intel_crtc *psb_intel_crtc = +- to_psb_intel_crtc(crtc); +- int dpll_md_reg; +- u32 adpa, dpll_md; +- u32 adpa_reg; +- +- if (psb_intel_crtc->pipe == 0) +- dpll_md_reg = DPLL_A_MD; +- else +- dpll_md_reg = DPLL_B_MD; +- +- adpa_reg = ADPA; +- +- /* +- * Disable separate mode multiplier used when cloning SDVO to CRT +- * XXX this needs to be adjusted when we really are cloning +- */ +- { +- dpll_md = REG_READ(dpll_md_reg); +- REG_WRITE(dpll_md_reg, +- dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); +- } +- +- adpa = 0; +- if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) +- adpa |= ADPA_HSYNC_ACTIVE_HIGH; +- if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) +- adpa |= ADPA_VSYNC_ACTIVE_HIGH; +- +- if (psb_intel_crtc->pipe == 0) +- adpa |= ADPA_PIPE_A_SELECT; +- else +- adpa |= ADPA_PIPE_B_SELECT; +- +- REG_WRITE(adpa_reg, adpa); +-} +- +- +-/** +- * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. +- * +- * \return true if CRT is connected. +- * \return false if CRT is disconnected. +- */ +-static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector, +- bool force) +-{ +- struct drm_device *dev = connector->dev; +- u32 hotplug_en; +- int i, tries = 0, ret = false; +- u32 adpa_orig; +- +- /* disable the DAC when doing the hotplug detection */ +- +- adpa_orig = REG_READ(ADPA); +- +- REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE)); +- +- /* +- * On a CDV thep, CRT detect sequence need to be done twice +- * to get a reliable result. +- */ +- tries = 2; +- +- hotplug_en = REG_READ(PORT_HOTPLUG_EN); +- hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK); +- hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; +- +- hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; +- hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; +- +- for (i = 0; i < tries ; i++) { +- unsigned long timeout; +- /* turn on the FORCE_DETECT */ +- REG_WRITE(PORT_HOTPLUG_EN, hotplug_en); +- timeout = jiffies + msecs_to_jiffies(1000); +- /* wait for FORCE_DETECT to go off */ +- do { +- if (!(REG_READ(PORT_HOTPLUG_EN) & +- CRT_HOTPLUG_FORCE_DETECT)) +- break; +- msleep(1); +- } while (time_after(timeout, jiffies)); +- } +- +- if ((REG_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) != +- CRT_HOTPLUG_MONITOR_NONE) +- ret = true; +- +- /* Restore the saved ADPA */ +- REG_WRITE(ADPA, adpa_orig); +- return ret; +-} +- +-static enum drm_connector_status cdv_intel_crt_detect( +- struct drm_connector *connector, bool force) +-{ +- if (cdv_intel_crt_detect_hotplug(connector, force)) +- return connector_status_connected; +- else +- return connector_status_disconnected; +-} +- +-static void cdv_intel_crt_destroy(struct drm_connector *connector) +-{ +- struct psb_intel_output *intel_output = to_psb_intel_output(connector); +- +- psb_intel_i2c_destroy(intel_output->ddc_bus); +- drm_sysfs_connector_remove(connector); +- drm_connector_cleanup(connector); +- kfree(connector); +-} +- +-static int cdv_intel_crt_get_modes(struct drm_connector *connector) +-{ +- struct psb_intel_output *intel_output = +- to_psb_intel_output(connector); +- return psb_intel_ddc_get_modes(intel_output); +-} +- +-static int cdv_intel_crt_set_property(struct drm_connector *connector, +- struct drm_property *property, +- uint64_t value) +-{ +- return 0; +-} +- +-/* +- * Routines for controlling stuff on the analog port +- */ +- +-static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = { +- .dpms = cdv_intel_crt_dpms, +- .mode_fixup = cdv_intel_crt_mode_fixup, +- .prepare = psb_intel_encoder_prepare, +- .commit = psb_intel_encoder_commit, +- .mode_set = cdv_intel_crt_mode_set, +-}; +- +-static const struct drm_connector_funcs cdv_intel_crt_connector_funcs = { +- .dpms = drm_helper_connector_dpms, +- .detect = cdv_intel_crt_detect, +- .fill_modes = drm_helper_probe_single_connector_modes, +- .destroy = cdv_intel_crt_destroy, +- .set_property = cdv_intel_crt_set_property, +-}; +- +-static const struct drm_connector_helper_funcs +- cdv_intel_crt_connector_helper_funcs = { +- .mode_valid = cdv_intel_crt_mode_valid, +- .get_modes = cdv_intel_crt_get_modes, +- .best_encoder = psb_intel_best_encoder, +-}; +- +-static void cdv_intel_crt_enc_destroy(struct drm_encoder *encoder) +-{ +- drm_encoder_cleanup(encoder); +-} +- +-static const struct drm_encoder_funcs cdv_intel_crt_enc_funcs = { +- .destroy = cdv_intel_crt_enc_destroy, +-}; +- +-void cdv_intel_crt_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev) +-{ +- +- struct psb_intel_output *psb_intel_output; +- struct drm_connector *connector; +- struct drm_encoder *encoder; +- +- u32 i2c_reg; +- +- psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); +- if (!psb_intel_output) +- return; +- +- psb_intel_output->mode_dev = mode_dev; +- connector = &psb_intel_output->base; +- drm_connector_init(dev, connector, +- &cdv_intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); +- +- encoder = &psb_intel_output->enc; +- drm_encoder_init(dev, encoder, +- &cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC); +- +- drm_mode_connector_attach_encoder(&psb_intel_output->base, +- &psb_intel_output->enc); +- +- /* Set up the DDC bus. */ +- i2c_reg = GPIOA; +- /* Remove the following code for CDV */ +- /* +- if (dev_priv->crt_ddc_bus != 0) +- i2c_reg = dev_priv->crt_ddc_bus; +- }*/ +- psb_intel_output->ddc_bus = psb_intel_i2c_create(dev, +- i2c_reg, "CRTDDC_A"); +- if (!psb_intel_output->ddc_bus) { +- dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " +- "failed.\n"); +- goto failed_ddc; +- } +- +- psb_intel_output->type = INTEL_OUTPUT_ANALOG; +- /* +- psb_intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT); +- psb_intel_output->crtc_mask = (1 << 0) | (1 << 1); +- */ +- connector->interlace_allowed = 0; +- connector->doublescan_allowed = 0; +- +- drm_encoder_helper_add(encoder, &cdv_intel_crt_helper_funcs); +- drm_connector_helper_add(connector, +- &cdv_intel_crt_connector_helper_funcs); +- +- drm_sysfs_connector_add(connector); +- +- return; +-failed_ddc: +- drm_encoder_cleanup(&psb_intel_output->enc); +- drm_connector_cleanup(&psb_intel_output->base); +- kfree(psb_intel_output); +- return; +-} +diff --git a/drivers/staging/gma500/cdv_intel_display.c b/drivers/staging/gma500/cdv_intel_display.c +deleted file mode 100644 +index 626ae47..0000000 +--- a/drivers/staging/gma500/cdv_intel_display.c ++++ /dev/null +@@ -1,1522 +0,0 @@ +-/* +- * Copyright © 2006-2011 Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Eric Anholt +- */ +- +-#include +-#include +- +-#include +-#include "framebuffer.h" +-#include "psb_drv.h" +-#include "psb_intel_drv.h" +-#include "psb_intel_reg.h" +-#include "psb_intel_display.h" +-#include "power.h" +-#include "cdv_device.h" +- +- +-struct cdv_intel_range_t { +- int min, max; +-}; +- +-struct cdv_intel_p2_t { +- int dot_limit; +- int p2_slow, p2_fast; +-}; +- +-struct cdv_intel_clock_t { +- /* given values */ +- int n; +- int m1, m2; +- int p1, p2; +- /* derived values */ +- int dot; +- int vco; +- int m; +- int p; +-}; +- +-#define INTEL_P2_NUM 2 +- +-struct cdv_intel_limit_t { +- struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1; +- struct cdv_intel_p2_t p2; +-}; +- +-#define CDV_LIMIT_SINGLE_LVDS_96 0 +-#define CDV_LIMIT_SINGLE_LVDS_100 1 +-#define CDV_LIMIT_DAC_HDMI_27 2 +-#define CDV_LIMIT_DAC_HDMI_96 3 +- +-static const struct cdv_intel_limit_t cdv_intel_limits[] = { +- { /* CDV_SIGNLE_LVDS_96MHz */ +- .dot = {.min = 20000, .max = 115500}, +- .vco = {.min = 1800000, .max = 3600000}, +- .n = {.min = 2, .max = 6}, +- .m = {.min = 60, .max = 160}, +- .m1 = {.min = 0, .max = 0}, +- .m2 = {.min = 58, .max = 158}, +- .p = {.min = 28, .max = 140}, +- .p1 = {.min = 2, .max = 10}, +- .p2 = {.dot_limit = 200000, +- .p2_slow = 14, .p2_fast = 14}, +- }, +- { /* CDV_SINGLE_LVDS_100MHz */ +- .dot = {.min = 20000, .max = 115500}, +- .vco = {.min = 1800000, .max = 3600000}, +- .n = {.min = 2, .max = 6}, +- .m = {.min = 60, .max = 160}, +- .m1 = {.min = 0, .max = 0}, +- .m2 = {.min = 58, .max = 158}, +- .p = {.min = 28, .max = 140}, +- .p1 = {.min = 2, .max = 10}, +- /* The single-channel range is 25-112Mhz, and dual-channel +- * is 80-224Mhz. Prefer single channel as much as possible. +- */ +- .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14}, +- }, +- { /* CDV_DAC_HDMI_27MHz */ +- .dot = {.min = 20000, .max = 400000}, +- .vco = {.min = 1809000, .max = 3564000}, +- .n = {.min = 1, .max = 1}, +- .m = {.min = 67, .max = 132}, +- .m1 = {.min = 0, .max = 0}, +- .m2 = {.min = 65, .max = 130}, +- .p = {.min = 5, .max = 90}, +- .p1 = {.min = 1, .max = 9}, +- .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, +- }, +- { /* CDV_DAC_HDMI_96MHz */ +- .dot = {.min = 20000, .max = 400000}, +- .vco = {.min = 1800000, .max = 3600000}, +- .n = {.min = 2, .max = 6}, +- .m = {.min = 60, .max = 160}, +- .m1 = {.min = 0, .max = 0}, +- .m2 = {.min = 58, .max = 158}, +- .p = {.min = 5, .max = 100}, +- .p1 = {.min = 1, .max = 10}, +- .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, +- }, +-}; +- +-#define _wait_for(COND, MS, W) ({ \ +- unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ +- int ret__ = 0; \ +- while (!(COND)) { \ +- if (time_after(jiffies, timeout__)) { \ +- ret__ = -ETIMEDOUT; \ +- break; \ +- } \ +- if (W && !in_dbg_master()) \ +- msleep(W); \ +- } \ +- ret__; \ +-}) +- +-#define wait_for(COND, MS) _wait_for(COND, MS, 1) +- +- +-static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val) +-{ +- int ret; +- +- ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); +- if (ret) { +- DRM_ERROR("timeout waiting for SB to idle before read\n"); +- return ret; +- } +- +- REG_WRITE(SB_ADDR, reg); +- REG_WRITE(SB_PCKT, +- SET_FIELD(SB_OPCODE_READ, SB_OPCODE) | +- SET_FIELD(SB_DEST_DPLL, SB_DEST) | +- SET_FIELD(0xf, SB_BYTE_ENABLE)); +- +- ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); +- if (ret) { +- DRM_ERROR("timeout waiting for SB to idle after read\n"); +- return ret; +- } +- +- *val = REG_READ(SB_DATA); +- +- return 0; +-} +- +-static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val) +-{ +- int ret; +- static bool dpio_debug = true; +- u32 temp; +- +- if (dpio_debug) { +- if (cdv_sb_read(dev, reg, &temp) == 0) +- DRM_DEBUG_KMS("0x%08x: 0x%08x (before)\n", reg, temp); +- DRM_DEBUG_KMS("0x%08x: 0x%08x\n", reg, val); +- } +- +- ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); +- if (ret) { +- DRM_ERROR("timeout waiting for SB to idle before write\n"); +- return ret; +- } +- +- REG_WRITE(SB_ADDR, reg); +- REG_WRITE(SB_DATA, val); +- REG_WRITE(SB_PCKT, +- SET_FIELD(SB_OPCODE_WRITE, SB_OPCODE) | +- SET_FIELD(SB_DEST_DPLL, SB_DEST) | +- SET_FIELD(0xf, SB_BYTE_ENABLE)); +- +- ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); +- if (ret) { +- DRM_ERROR("timeout waiting for SB to idle after write\n"); +- return ret; +- } +- +- if (dpio_debug) { +- if (cdv_sb_read(dev, reg, &temp) == 0) +- DRM_DEBUG_KMS("0x%08x: 0x%08x (after)\n", reg, temp); +- } +- +- return 0; +-} +- +-/* Reset the DPIO configuration register. The BIOS does this at every +- * mode set. +- */ +-static void cdv_sb_reset(struct drm_device *dev) +-{ +- +- REG_WRITE(DPIO_CFG, 0); +- REG_READ(DPIO_CFG); +- REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N); +-} +- +-/* Unlike most Intel display engines, on Cedarview the DPLL registers +- * are behind this sideband bus. They must be programmed while the +- * DPLL reference clock is on in the DPLL control register, but before +- * the DPLL is enabled in the DPLL control register. +- */ +-static int +-cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, +- struct cdv_intel_clock_t *clock) +-{ +- struct psb_intel_crtc *psb_crtc = +- to_psb_intel_crtc(crtc); +- int pipe = psb_crtc->pipe; +- u32 m, n_vco, p; +- int ret = 0; +- int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; +- u32 ref_value; +- +- cdv_sb_reset(dev); +- +- if ((REG_READ(dpll_reg) & DPLL_SYNCLOCK_ENABLE) == 0) { +- DRM_ERROR("Attempting to set DPLL with refclk disabled\n"); +- return -EBUSY; +- } +- +- /* Follow the BIOS and write the REF/SFR Register. Hardcoded value */ +- ref_value = 0x68A701; +- +- cdv_sb_write(dev, SB_REF_SFR(pipe), ref_value); +- +- /* We don't know what the other fields of these regs are, so +- * leave them in place. +- */ +- ret = cdv_sb_read(dev, SB_M(pipe), &m); +- if (ret) +- return ret; +- m &= ~SB_M_DIVIDER_MASK; +- m |= ((clock->m2) << SB_M_DIVIDER_SHIFT); +- ret = cdv_sb_write(dev, SB_M(pipe), m); +- if (ret) +- return ret; +- +- ret = cdv_sb_read(dev, SB_N_VCO(pipe), &n_vco); +- if (ret) +- return ret; +- +- /* Follow the BIOS to program the N_DIVIDER REG */ +- n_vco &= 0xFFFF; +- n_vco |= 0x107; +- n_vco &= ~(SB_N_VCO_SEL_MASK | +- SB_N_DIVIDER_MASK | +- SB_N_CB_TUNE_MASK); +- +- n_vco |= ((clock->n) << SB_N_DIVIDER_SHIFT); +- +- if (clock->vco < 2250000) { +- n_vco |= (2 << SB_N_CB_TUNE_SHIFT); +- n_vco |= (0 << SB_N_VCO_SEL_SHIFT); +- } else if (clock->vco < 2750000) { +- n_vco |= (1 << SB_N_CB_TUNE_SHIFT); +- n_vco |= (1 << SB_N_VCO_SEL_SHIFT); +- } else if (clock->vco < 3300000) { +- n_vco |= (0 << SB_N_CB_TUNE_SHIFT); +- n_vco |= (2 << SB_N_VCO_SEL_SHIFT); +- } else { +- n_vco |= (0 << SB_N_CB_TUNE_SHIFT); +- n_vco |= (3 << SB_N_VCO_SEL_SHIFT); +- } +- +- ret = cdv_sb_write(dev, SB_N_VCO(pipe), n_vco); +- if (ret) +- return ret; +- +- ret = cdv_sb_read(dev, SB_P(pipe), &p); +- if (ret) +- return ret; +- p &= ~(SB_P2_DIVIDER_MASK | SB_P1_DIVIDER_MASK); +- p |= SET_FIELD(clock->p1, SB_P1_DIVIDER); +- switch (clock->p2) { +- case 5: +- p |= SET_FIELD(SB_P2_5, SB_P2_DIVIDER); +- break; +- case 10: +- p |= SET_FIELD(SB_P2_10, SB_P2_DIVIDER); +- break; +- case 14: +- p |= SET_FIELD(SB_P2_14, SB_P2_DIVIDER); +- break; +- case 7: +- p |= SET_FIELD(SB_P2_7, SB_P2_DIVIDER); +- break; +- default: +- DRM_ERROR("Bad P2 clock: %d\n", clock->p2); +- return -EINVAL; +- } +- ret = cdv_sb_write(dev, SB_P(pipe), p); +- if (ret) +- return ret; +- +- /* always Program the Lane Register for the Pipe A*/ +- if (pipe == 0) { +- /* Program the Lane0/1 for HDMI B */ +- u32 lane_reg, lane_value; +- +- lane_reg = PSB_LANE0; +- cdv_sb_read(dev, lane_reg, &lane_value); +- lane_value &= ~(LANE_PLL_MASK); +- lane_value |= LANE_PLL_ENABLE; +- cdv_sb_write(dev, lane_reg, lane_value); +- +- lane_reg = PSB_LANE1; +- cdv_sb_read(dev, lane_reg, &lane_value); +- lane_value &= ~(LANE_PLL_MASK); +- lane_value |= LANE_PLL_ENABLE; +- cdv_sb_write(dev, lane_reg, lane_value); +- +- /* Program the Lane2/3 for HDMI C */ +- lane_reg = PSB_LANE2; +- cdv_sb_read(dev, lane_reg, &lane_value); +- lane_value &= ~(LANE_PLL_MASK); +- lane_value |= LANE_PLL_ENABLE; +- cdv_sb_write(dev, lane_reg, lane_value); +- +- lane_reg = PSB_LANE3; +- cdv_sb_read(dev, lane_reg, &lane_value); +- lane_value &= ~(LANE_PLL_MASK); +- lane_value |= LANE_PLL_ENABLE; +- cdv_sb_write(dev, lane_reg, lane_value); +- } +- +- return 0; +-} +- +-/* +- * Returns whether any output on the specified pipe is of the specified type +- */ +-bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type) +-{ +- struct drm_device *dev = crtc->dev; +- struct drm_mode_config *mode_config = &dev->mode_config; +- struct drm_connector *l_entry; +- +- list_for_each_entry(l_entry, &mode_config->connector_list, head) { +- if (l_entry->encoder && l_entry->encoder->crtc == crtc) { +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(l_entry); +- if (psb_intel_output->type == type) +- return true; +- } +- } +- return false; +-} +- +-static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc, +- int refclk) +-{ +- const struct cdv_intel_limit_t *limit; +- if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { +- /* +- * Now only single-channel LVDS is supported on CDV. If it is +- * incorrect, please add the dual-channel LVDS. +- */ +- if (refclk == 96000) +- limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96]; +- else +- limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100]; +- } else { +- if (refclk == 27000) +- limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27]; +- else +- limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_96]; +- } +- return limit; +-} +- +-/* m1 is reserved as 0 in CDV, n is a ring counter */ +-static void cdv_intel_clock(struct drm_device *dev, +- int refclk, struct cdv_intel_clock_t *clock) +-{ +- clock->m = clock->m2 + 2; +- clock->p = clock->p1 * clock->p2; +- clock->vco = (refclk * clock->m) / clock->n; +- clock->dot = clock->vco / clock->p; +-} +- +- +-#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } +-static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc, +- const struct cdv_intel_limit_t *limit, +- struct cdv_intel_clock_t *clock) +-{ +- if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) +- INTELPllInvalid("p1 out of range\n"); +- if (clock->p < limit->p.min || limit->p.max < clock->p) +- INTELPllInvalid("p out of range\n"); +- /* unnecessary to check the range of m(m1/M2)/n again */ +- if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) +- INTELPllInvalid("vco out of range\n"); +- /* XXX: We may need to be checking "Dot clock" +- * depending on the multiplier, connector, etc., +- * rather than just a single range. +- */ +- if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) +- INTELPllInvalid("dot out of range\n"); +- +- return true; +-} +- +-static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target, +- int refclk, +- struct cdv_intel_clock_t *best_clock) +-{ +- struct drm_device *dev = crtc->dev; +- struct cdv_intel_clock_t clock; +- const struct cdv_intel_limit_t *limit = cdv_intel_limit(crtc, refclk); +- int err = target; +- +- +- if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && +- (REG_READ(LVDS) & LVDS_PORT_EN) != 0) { +- /* +- * For LVDS, if the panel is on, just rely on its current +- * settings for dual-channel. We haven't figured out how to +- * reliably set up different single/dual channel state, if we +- * even can. +- */ +- if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) == +- LVDS_CLKB_POWER_UP) +- clock.p2 = limit->p2.p2_fast; +- else +- clock.p2 = limit->p2.p2_slow; +- } else { +- if (target < limit->p2.dot_limit) +- clock.p2 = limit->p2.p2_slow; +- else +- clock.p2 = limit->p2.p2_fast; +- } +- +- memset(best_clock, 0, sizeof(*best_clock)); +- clock.m1 = 0; +- /* m1 is reserved as 0 in CDV, n is a ring counter. +- So skip the m1 loop */ +- for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) { +- for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; +- clock.m2++) { +- for (clock.p1 = limit->p1.min; +- clock.p1 <= limit->p1.max; +- clock.p1++) { +- int this_err; +- +- cdv_intel_clock(dev, refclk, &clock); +- +- if (!cdv_intel_PLL_is_valid(crtc, +- limit, &clock)) +- continue; +- +- this_err = abs(clock.dot - target); +- if (this_err < err) { +- *best_clock = clock; +- err = this_err; +- } +- } +- } +- } +- +- return err != target; +-} +- +-int cdv_intel_pipe_set_base(struct drm_crtc *crtc, +- int x, int y, struct drm_framebuffer *old_fb) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); +- int pipe = psb_intel_crtc->pipe; +- unsigned long start, offset; +- int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); +- int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); +- int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; +- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; +- u32 dspcntr; +- int ret = 0; +- +- if (!gma_power_begin(dev, true)) +- return 0; +- +- /* no fb bound */ +- if (!crtc->fb) { +- dev_err(dev->dev, "No FB bound\n"); +- goto psb_intel_pipe_cleaner; +- } +- +- +- /* We are displaying this buffer, make sure it is actually loaded +- into the GTT */ +- ret = psb_gtt_pin(psbfb->gtt); +- if (ret < 0) +- goto psb_intel_pipe_set_base_exit; +- start = psbfb->gtt->offset; +- offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); +- +- REG_WRITE(dspstride, crtc->fb->pitch); +- +- dspcntr = REG_READ(dspcntr_reg); +- dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; +- +- switch (crtc->fb->bits_per_pixel) { +- case 8: +- dspcntr |= DISPPLANE_8BPP; +- break; +- case 16: +- if (crtc->fb->depth == 15) +- dspcntr |= DISPPLANE_15_16BPP; +- else +- dspcntr |= DISPPLANE_16BPP; +- break; +- case 24: +- case 32: +- dspcntr |= DISPPLANE_32BPP_NO_ALPHA; +- break; +- default: +- dev_err(dev->dev, "Unknown color depth\n"); +- ret = -EINVAL; +- goto psb_intel_pipe_set_base_exit; +- } +- REG_WRITE(dspcntr_reg, dspcntr); +- +- dev_dbg(dev->dev, +- "Writing base %08lX %08lX %d %d\n", start, offset, x, y); +- +- REG_WRITE(dspbase, offset); +- REG_READ(dspbase); +- REG_WRITE(dspsurf, start); +- REG_READ(dspsurf); +- +-psb_intel_pipe_cleaner: +- /* If there was a previous display we can now unpin it */ +- if (old_fb) +- psb_gtt_unpin(to_psb_fb(old_fb)->gtt); +- +-psb_intel_pipe_set_base_exit: +- gma_power_end(dev); +- return ret; +-} +- +-/** +- * Sets the power management mode of the pipe and plane. +- * +- * This code should probably grow support for turning the cursor off and back +- * on appropriately at the same time as we're turning the pipe off/on. +- */ +-static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; +- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; +- int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; +- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; +- u32 temp; +- bool enabled; +- +- /* XXX: When our outputs are all unaware of DPMS modes other than off +- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. +- */ +- switch (mode) { +- case DRM_MODE_DPMS_ON: +- case DRM_MODE_DPMS_STANDBY: +- case DRM_MODE_DPMS_SUSPEND: +- /* Enable the DPLL */ +- temp = REG_READ(dpll_reg); +- if ((temp & DPLL_VCO_ENABLE) == 0) { +- REG_WRITE(dpll_reg, temp); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- } +- +- /* Jim Bish - switch plan and pipe per scott */ +- /* Enable the plane */ +- temp = REG_READ(dspcntr_reg); +- if ((temp & DISPLAY_PLANE_ENABLE) == 0) { +- REG_WRITE(dspcntr_reg, +- temp | DISPLAY_PLANE_ENABLE); +- /* Flush the plane changes */ +- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); +- } +- +- udelay(150); +- +- /* Enable the pipe */ +- temp = REG_READ(pipeconf_reg); +- if ((temp & PIPEACONF_ENABLE) == 0) +- REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); +- +- psb_intel_crtc_load_lut(crtc); +- +- /* Give the overlay scaler a chance to enable +- * if it's on this pipe */ +- /* psb_intel_crtc_dpms_video(crtc, true); TODO */ +- break; +- case DRM_MODE_DPMS_OFF: +- /* Give the overlay scaler a chance to disable +- * if it's on this pipe */ +- /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ +- +- /* Disable the VGA plane that we never use */ +- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); +- +- /* Jim Bish - changed pipe/plane here as well. */ +- +- /* Wait for vblank for the disable to take effect */ +- cdv_intel_wait_for_vblank(dev); +- +- /* Next, disable display pipes */ +- temp = REG_READ(pipeconf_reg); +- if ((temp & PIPEACONF_ENABLE) != 0) { +- REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); +- REG_READ(pipeconf_reg); +- } +- +- /* Wait for vblank for the disable to take effect. */ +- cdv_intel_wait_for_vblank(dev); +- +- udelay(150); +- +- /* Disable display plane */ +- temp = REG_READ(dspcntr_reg); +- if ((temp & DISPLAY_PLANE_ENABLE) != 0) { +- REG_WRITE(dspcntr_reg, +- temp & ~DISPLAY_PLANE_ENABLE); +- /* Flush the plane changes */ +- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); +- REG_READ(dspbase_reg); +- } +- +- temp = REG_READ(dpll_reg); +- if ((temp & DPLL_VCO_ENABLE) != 0) { +- REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- } +- +- /* Wait for the clocks to turn off. */ +- udelay(150); +- break; +- } +- enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; +- /*Set FIFO Watermarks*/ +- REG_WRITE(DSPARB, 0x3F3E); +-} +- +-static void cdv_intel_crtc_prepare(struct drm_crtc *crtc) +-{ +- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); +-} +- +-static void cdv_intel_crtc_commit(struct drm_crtc *crtc) +-{ +- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); +-} +- +-void cdv_intel_encoder_prepare(struct drm_encoder *encoder) +-{ +- struct drm_encoder_helper_funcs *encoder_funcs = +- encoder->helper_private; +- /* lvds has its own version of prepare see cdv_intel_lvds_prepare */ +- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); +-} +- +-void cdv_intel_encoder_commit(struct drm_encoder *encoder) +-{ +- struct drm_encoder_helper_funcs *encoder_funcs = +- encoder->helper_private; +- /* lvds has its own version of commit see cdv_intel_lvds_commit */ +- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); +-} +- +-static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- return true; +-} +- +- +-/** +- * Return the pipe currently connected to the panel fitter, +- * or -1 if the panel fitter is not present or not in use +- */ +-static int cdv_intel_panel_fitter_pipe(struct drm_device *dev) +-{ +- u32 pfit_control; +- +- pfit_control = REG_READ(PFIT_CONTROL); +- +- /* See if the panel fitter is in use */ +- if ((pfit_control & PFIT_ENABLE) == 0) +- return -1; +- return (pfit_control >> 29) & 0x3; +-} +- +-static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode, +- int x, int y, +- struct drm_framebuffer *old_fb) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; +- int dpll_md_reg = (psb_intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; +- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; +- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; +- int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; +- int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; +- int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; +- int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; +- int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; +- int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; +- int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; +- int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; +- int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; +- int refclk; +- struct cdv_intel_clock_t clock; +- u32 dpll = 0, dspcntr, pipeconf; +- bool ok, is_sdvo = false, is_dvo = false; +- bool is_crt = false, is_lvds = false, is_tv = false; +- bool is_hdmi = false; +- struct drm_mode_config *mode_config = &dev->mode_config; +- struct drm_connector *connector; +- +- list_for_each_entry(connector, &mode_config->connector_list, head) { +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- +- if (!connector->encoder +- || connector->encoder->crtc != crtc) +- continue; +- +- switch (psb_intel_output->type) { +- case INTEL_OUTPUT_LVDS: +- is_lvds = true; +- break; +- case INTEL_OUTPUT_SDVO: +- is_sdvo = true; +- break; +- case INTEL_OUTPUT_DVO: +- is_dvo = true; +- break; +- case INTEL_OUTPUT_TVOUT: +- is_tv = true; +- break; +- case INTEL_OUTPUT_ANALOG: +- is_crt = true; +- break; +- case INTEL_OUTPUT_HDMI: +- is_hdmi = true; +- break; +- } +- } +- +- refclk = 96000; +- +- /* Hack selection about ref clk for CRT */ +- /* Select 27MHz as the reference clk for HDMI */ +- if (is_crt || is_hdmi) +- refclk = 27000; +- +- drm_mode_debug_printmodeline(adjusted_mode); +- +- ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, +- &clock); +- if (!ok) { +- dev_err(dev->dev, "Couldn't find PLL settings for mode!\n"); +- return 0; +- } +- +- dpll = DPLL_VGA_MODE_DIS; +- if (is_tv) { +- /* XXX: just matching BIOS for now */ +-/* dpll |= PLL_REF_INPUT_TVCLKINBC; */ +- dpll |= 3; +- } +- dpll |= PLL_REF_INPUT_DREFCLK; +- +- dpll |= DPLL_SYNCLOCK_ENABLE; +- dpll |= DPLL_VGA_MODE_DIS; +- if (is_lvds) +- dpll |= DPLLB_MODE_LVDS; +- else +- dpll |= DPLLB_MODE_DAC_SERIAL; +- /* dpll |= (2 << 11); */ +- +- /* setup pipeconf */ +- pipeconf = REG_READ(pipeconf_reg); +- +- /* Set up the display plane register */ +- dspcntr = DISPPLANE_GAMMA_ENABLE; +- +- if (pipe == 0) +- dspcntr |= DISPPLANE_SEL_PIPE_A; +- else +- dspcntr |= DISPPLANE_SEL_PIPE_B; +- +- dspcntr |= DISPLAY_PLANE_ENABLE; +- pipeconf |= PIPEACONF_ENABLE; +- +- REG_WRITE(dpll_reg, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE); +- REG_READ(dpll_reg); +- +- cdv_dpll_set_clock_cdv(dev, crtc, &clock); +- +- udelay(150); +- +- +- /* The LVDS pin pair needs to be on before the DPLLs are enabled. +- * This is an exception to the general rule that mode_set doesn't turn +- * things on. +- */ +- if (is_lvds) { +- u32 lvds = REG_READ(LVDS); +- +- lvds |= +- LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | +- LVDS_PIPEB_SELECT; +- /* Set the B0-B3 data pairs corresponding to +- * whether we're going to +- * set the DPLLs for dual-channel mode or not. +- */ +- if (clock.p2 == 7) +- lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; +- else +- lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); +- +- /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) +- * appropriately here, but we need to look more +- * thoroughly into how panels behave in the two modes. +- */ +- +- REG_WRITE(LVDS, lvds); +- REG_READ(LVDS); +- } +- +- dpll |= DPLL_VCO_ENABLE; +- +- /* Disable the panel fitter if it was on our pipe */ +- if (cdv_intel_panel_fitter_pipe(dev) == pipe) +- REG_WRITE(PFIT_CONTROL, 0); +- +- DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); +- drm_mode_debug_printmodeline(mode); +- +- REG_WRITE(dpll_reg, +- (REG_READ(dpll_reg) & ~DPLL_LOCK) | DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); /* 42 usec w/o calibration, 110 with. rounded up. */ +- +- if (!(REG_READ(dpll_reg) & DPLL_LOCK)) { +- dev_err(dev->dev, "Failed to get DPLL lock\n"); +- return -EBUSY; +- } +- +- { +- int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; +- REG_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); +- } +- +- REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | +- ((adjusted_mode->crtc_htotal - 1) << 16)); +- REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | +- ((adjusted_mode->crtc_hblank_end - 1) << 16)); +- REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | +- ((adjusted_mode->crtc_hsync_end - 1) << 16)); +- REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | +- ((adjusted_mode->crtc_vtotal - 1) << 16)); +- REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | +- ((adjusted_mode->crtc_vblank_end - 1) << 16)); +- REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | +- ((adjusted_mode->crtc_vsync_end - 1) << 16)); +- /* pipesrc and dspsize control the size that is scaled from, +- * which should always be the user's requested size. +- */ +- REG_WRITE(dspsize_reg, +- ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); +- REG_WRITE(dsppos_reg, 0); +- REG_WRITE(pipesrc_reg, +- ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); +- REG_WRITE(pipeconf_reg, pipeconf); +- REG_READ(pipeconf_reg); +- +- cdv_intel_wait_for_vblank(dev); +- +- REG_WRITE(dspcntr_reg, dspcntr); +- +- /* Flush the plane changes */ +- { +- struct drm_crtc_helper_funcs *crtc_funcs = +- crtc->helper_private; +- crtc_funcs->mode_set_base(crtc, x, y, old_fb); +- } +- +- cdv_intel_wait_for_vblank(dev); +- +- return 0; +-} +- +-/** Loads the palette/gamma unit for the CRTC with the prepared values */ +-void cdv_intel_crtc_load_lut(struct drm_crtc *crtc) +-{ +- struct drm_device *dev = crtc->dev; +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *)dev->dev_private; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int palreg = PALETTE_A; +- int i; +- +- /* The clocks have to be on to load the palette. */ +- if (!crtc->enabled) +- return; +- +- switch (psb_intel_crtc->pipe) { +- case 0: +- break; +- case 1: +- palreg = PALETTE_B; +- break; +- case 2: +- palreg = PALETTE_C; +- break; +- default: +- dev_err(dev->dev, "Illegal Pipe Number.\n"); +- return; +- } +- +- if (gma_power_begin(dev, false)) { +- for (i = 0; i < 256; i++) { +- REG_WRITE(palreg + 4 * i, +- ((psb_intel_crtc->lut_r[i] + +- psb_intel_crtc->lut_adj[i]) << 16) | +- ((psb_intel_crtc->lut_g[i] + +- psb_intel_crtc->lut_adj[i]) << 8) | +- (psb_intel_crtc->lut_b[i] + +- psb_intel_crtc->lut_adj[i])); +- } +- gma_power_end(dev); +- } else { +- for (i = 0; i < 256; i++) { +- dev_priv->save_palette_a[i] = +- ((psb_intel_crtc->lut_r[i] + +- psb_intel_crtc->lut_adj[i]) << 16) | +- ((psb_intel_crtc->lut_g[i] + +- psb_intel_crtc->lut_adj[i]) << 8) | +- (psb_intel_crtc->lut_b[i] + +- psb_intel_crtc->lut_adj[i]); +- } +- +- } +-} +- +-/** +- * Save HW states of giving crtc +- */ +-static void cdv_intel_crtc_save(struct drm_crtc *crtc) +-{ +- struct drm_device *dev = crtc->dev; +- /* struct drm_psb_private *dev_priv = +- (struct drm_psb_private *)dev->dev_private; */ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; +- int pipeA = (psb_intel_crtc->pipe == 0); +- uint32_t paletteReg; +- int i; +- +- if (!crtc_state) { +- dev_dbg(dev->dev, "No CRTC state found\n"); +- return; +- } +- +- crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR); +- crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF); +- crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC); +- crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0); +- crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1); +- crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B); +- crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B); +- crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B); +- crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B); +- crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B); +- crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B); +- crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B); +- crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE); +- +- /*NOTE: DSPSIZE DSPPOS only for psb*/ +- crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE); +- crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS); +- +- crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE); +- +- DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n", +- crtc_state->saveDSPCNTR, +- crtc_state->savePIPECONF, +- crtc_state->savePIPESRC, +- crtc_state->saveFP0, +- crtc_state->saveFP1, +- crtc_state->saveDPLL, +- crtc_state->saveHTOTAL, +- crtc_state->saveHBLANK, +- crtc_state->saveHSYNC, +- crtc_state->saveVTOTAL, +- crtc_state->saveVBLANK, +- crtc_state->saveVSYNC, +- crtc_state->saveDSPSTRIDE, +- crtc_state->saveDSPSIZE, +- crtc_state->saveDSPPOS, +- crtc_state->saveDSPBASE +- ); +- +- paletteReg = pipeA ? PALETTE_A : PALETTE_B; +- for (i = 0; i < 256; ++i) +- crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2)); +-} +- +-/** +- * Restore HW states of giving crtc +- */ +-static void cdv_intel_crtc_restore(struct drm_crtc *crtc) +-{ +- struct drm_device *dev = crtc->dev; +- /* struct drm_psb_private * dev_priv = +- (struct drm_psb_private *)dev->dev_private; */ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; +- /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */ +- int pipeA = (psb_intel_crtc->pipe == 0); +- uint32_t paletteReg; +- int i; +- +- if (!crtc_state) { +- dev_dbg(dev->dev, "No crtc state\n"); +- return; +- } +- +- DRM_DEBUG( +- "current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n", +- REG_READ(pipeA ? DSPACNTR : DSPBCNTR), +- REG_READ(pipeA ? PIPEACONF : PIPEBCONF), +- REG_READ(pipeA ? PIPEASRC : PIPEBSRC), +- REG_READ(pipeA ? FPA0 : FPB0), +- REG_READ(pipeA ? FPA1 : FPB1), +- REG_READ(pipeA ? DPLL_A : DPLL_B), +- REG_READ(pipeA ? HTOTAL_A : HTOTAL_B), +- REG_READ(pipeA ? HBLANK_A : HBLANK_B), +- REG_READ(pipeA ? HSYNC_A : HSYNC_B), +- REG_READ(pipeA ? VTOTAL_A : VTOTAL_B), +- REG_READ(pipeA ? VBLANK_A : VBLANK_B), +- REG_READ(pipeA ? VSYNC_A : VSYNC_B), +- REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE), +- REG_READ(pipeA ? DSPASIZE : DSPBSIZE), +- REG_READ(pipeA ? DSPAPOS : DSPBPOS), +- REG_READ(pipeA ? DSPABASE : DSPBBASE) +- ); +- +- DRM_DEBUG( +- "saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n", +- crtc_state->saveDSPCNTR, +- crtc_state->savePIPECONF, +- crtc_state->savePIPESRC, +- crtc_state->saveFP0, +- crtc_state->saveFP1, +- crtc_state->saveDPLL, +- crtc_state->saveHTOTAL, +- crtc_state->saveHBLANK, +- crtc_state->saveHSYNC, +- crtc_state->saveVTOTAL, +- crtc_state->saveVBLANK, +- crtc_state->saveVSYNC, +- crtc_state->saveDSPSTRIDE, +- crtc_state->saveDSPSIZE, +- crtc_state->saveDSPPOS, +- crtc_state->saveDSPBASE +- ); +- +- +- if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) { +- REG_WRITE(pipeA ? DPLL_A : DPLL_B, +- crtc_state->saveDPLL & ~DPLL_VCO_ENABLE); +- REG_READ(pipeA ? DPLL_A : DPLL_B); +- DRM_DEBUG("write dpll: %x\n", +- REG_READ(pipeA ? DPLL_A : DPLL_B)); +- udelay(150); +- } +- +- REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0); +- REG_READ(pipeA ? FPA0 : FPB0); +- +- REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1); +- REG_READ(pipeA ? FPA1 : FPB1); +- +- REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL); +- REG_READ(pipeA ? DPLL_A : DPLL_B); +- udelay(150); +- +- REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL); +- REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK); +- REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC); +- REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL); +- REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK); +- REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC); +- REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE); +- +- REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE); +- REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS); +- +- REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC); +- REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); +- REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF); +- +- cdv_intel_wait_for_vblank(dev); +- +- REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR); +- REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); +- +- cdv_intel_wait_for_vblank(dev); +- +- paletteReg = pipeA ? PALETTE_A : PALETTE_B; +- for (i = 0; i < 256; ++i) +- REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]); +-} +- +-static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc, +- struct drm_file *file_priv, +- uint32_t handle, +- uint32_t width, uint32_t height) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; +- uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; +- uint32_t temp; +- size_t addr = 0; +- struct gtt_range *gt; +- struct drm_gem_object *obj; +- int ret; +- +- /* if we want to turn of the cursor ignore width and height */ +- if (!handle) { +- /* turn off the cursor */ +- temp = CURSOR_MODE_DISABLE; +- +- if (gma_power_begin(dev, false)) { +- REG_WRITE(control, temp); +- REG_WRITE(base, 0); +- gma_power_end(dev); +- } +- +- /* unpin the old GEM object */ +- if (psb_intel_crtc->cursor_obj) { +- gt = container_of(psb_intel_crtc->cursor_obj, +- struct gtt_range, gem); +- psb_gtt_unpin(gt); +- drm_gem_object_unreference(psb_intel_crtc->cursor_obj); +- psb_intel_crtc->cursor_obj = NULL; +- } +- +- return 0; +- } +- +- /* Currently we only support 64x64 cursors */ +- if (width != 64 || height != 64) { +- dev_dbg(dev->dev, "we currently only support 64x64 cursors\n"); +- return -EINVAL; +- } +- +- obj = drm_gem_object_lookup(dev, file_priv, handle); +- if (!obj) +- return -ENOENT; +- +- if (obj->size < width * height * 4) { +- dev_dbg(dev->dev, "buffer is to small\n"); +- return -ENOMEM; +- } +- +- gt = container_of(obj, struct gtt_range, gem); +- +- /* Pin the memory into the GTT */ +- ret = psb_gtt_pin(gt); +- if (ret) { +- dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); +- return ret; +- } +- +- addr = gt->offset; /* Or resource.start ??? */ +- +- psb_intel_crtc->cursor_addr = addr; +- +- temp = 0; +- /* set the pipe for the cursor */ +- temp |= (pipe << 28); +- temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; +- +- if (gma_power_begin(dev, false)) { +- REG_WRITE(control, temp); +- REG_WRITE(base, addr); +- gma_power_end(dev); +- } +- +- /* unpin the old GEM object */ +- if (psb_intel_crtc->cursor_obj) { +- gt = container_of(psb_intel_crtc->cursor_obj, +- struct gtt_range, gem); +- psb_gtt_unpin(gt); +- drm_gem_object_unreference(psb_intel_crtc->cursor_obj); +- psb_intel_crtc->cursor_obj = obj; +- } +- return 0; +-} +- +-static int cdv_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- uint32_t temp = 0; +- uint32_t adder; +- +- +- if (x < 0) { +- temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); +- x = -x; +- } +- if (y < 0) { +- temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); +- y = -y; +- } +- +- temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); +- temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); +- +- adder = psb_intel_crtc->cursor_addr; +- +- if (gma_power_begin(dev, false)) { +- REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); +- REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder); +- gma_power_end(dev); +- } +- return 0; +-} +- +-static void cdv_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, +- u16 *green, u16 *blue, uint32_t start, uint32_t size) +-{ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int i; +- int end = (start + size > 256) ? 256 : start + size; +- +- for (i = start; i < end; i++) { +- psb_intel_crtc->lut_r[i] = red[i] >> 8; +- psb_intel_crtc->lut_g[i] = green[i] >> 8; +- psb_intel_crtc->lut_b[i] = blue[i] >> 8; +- } +- +- cdv_intel_crtc_load_lut(crtc); +-} +- +-static int cdv_crtc_set_config(struct drm_mode_set *set) +-{ +- int ret = 0; +- struct drm_device *dev = set->crtc->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (!dev_priv->rpm_enabled) +- return drm_crtc_helper_set_config(set); +- +- pm_runtime_forbid(&dev->pdev->dev); +- +- ret = drm_crtc_helper_set_config(set); +- +- pm_runtime_allow(&dev->pdev->dev); +- +- return ret; +-} +- +-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ +- +-/* FIXME: why are we using this, should it be cdv_ in this tree ? */ +- +-static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock) +-{ +- clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); +- clock->p = clock->p1 * clock->p2; +- clock->vco = refclk * clock->m / (clock->n + 2); +- clock->dot = clock->vco / clock->p; +-} +- +-/* Returns the clock of the currently programmed mode of the given pipe. */ +-static int cdv_intel_crtc_clock_get(struct drm_device *dev, +- struct drm_crtc *crtc) +-{ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- u32 dpll; +- u32 fp; +- struct cdv_intel_clock_t clock; +- bool is_lvds; +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (gma_power_begin(dev, false)) { +- dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B); +- if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) +- fp = REG_READ((pipe == 0) ? FPA0 : FPB0); +- else +- fp = REG_READ((pipe == 0) ? FPA1 : FPB1); +- is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN); +- gma_power_end(dev); +- } else { +- dpll = (pipe == 0) ? +- dev_priv->saveDPLL_A : dev_priv->saveDPLL_B; +- +- if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) +- fp = (pipe == 0) ? +- dev_priv->saveFPA0 : +- dev_priv->saveFPB0; +- else +- fp = (pipe == 0) ? +- dev_priv->saveFPA1 : +- dev_priv->saveFPB1; +- +- is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN); +- } +- +- clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; +- clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; +- clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; +- +- if (is_lvds) { +- clock.p1 = +- ffs((dpll & +- DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> +- DPLL_FPA01_P1_POST_DIV_SHIFT); +- if (clock.p1 == 0) { +- clock.p1 = 4; +- dev_err(dev->dev, "PLL %d\n", dpll); +- } +- clock.p2 = 14; +- +- if ((dpll & PLL_REF_INPUT_MASK) == +- PLLB_REF_INPUT_SPREADSPECTRUMIN) { +- /* XXX: might not be 66MHz */ +- i8xx_clock(66000, &clock); +- } else +- i8xx_clock(48000, &clock); +- } else { +- if (dpll & PLL_P1_DIVIDE_BY_TWO) +- clock.p1 = 2; +- else { +- clock.p1 = +- ((dpll & +- DPLL_FPA01_P1_POST_DIV_MASK_I830) >> +- DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; +- } +- if (dpll & PLL_P2_DIVIDE_BY_4) +- clock.p2 = 4; +- else +- clock.p2 = 2; +- +- i8xx_clock(48000, &clock); +- } +- +- /* XXX: It would be nice to validate the clocks, but we can't reuse +- * i830PllIsValid() because it relies on the xf86_config connector +- * configuration being accurate, which it isn't necessarily. +- */ +- +- return clock.dot; +-} +- +-/** Returns the currently programmed mode of the given pipe. */ +-struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev, +- struct drm_crtc *crtc) +-{ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- struct drm_display_mode *mode; +- int htot; +- int hsync; +- int vtot; +- int vsync; +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (gma_power_begin(dev, false)) { +- htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); +- hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B); +- vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); +- vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B); +- gma_power_end(dev); +- } else { +- htot = (pipe == 0) ? +- dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B; +- hsync = (pipe == 0) ? +- dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B; +- vtot = (pipe == 0) ? +- dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B; +- vsync = (pipe == 0) ? +- dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B; +- } +- +- mode = kzalloc(sizeof(*mode), GFP_KERNEL); +- if (!mode) +- return NULL; +- +- mode->clock = cdv_intel_crtc_clock_get(dev, crtc); +- mode->hdisplay = (htot & 0xffff) + 1; +- mode->htotal = ((htot & 0xffff0000) >> 16) + 1; +- mode->hsync_start = (hsync & 0xffff) + 1; +- mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; +- mode->vdisplay = (vtot & 0xffff) + 1; +- mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; +- mode->vsync_start = (vsync & 0xffff) + 1; +- mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; +- +- drm_mode_set_name(mode); +- drm_mode_set_crtcinfo(mode, 0); +- +- return mode; +-} +- +-static void cdv_intel_crtc_destroy(struct drm_crtc *crtc) +-{ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- +- kfree(psb_intel_crtc->crtc_state); +- drm_crtc_cleanup(crtc); +- kfree(psb_intel_crtc); +-} +- +-static void cdv_intel_crtc_disable(struct drm_crtc *crtc) +-{ +- struct gtt_range *gt; +- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +- +- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); +- +- if (crtc->fb) { +- gt = to_psb_fb(crtc->fb)->gtt; +- psb_gtt_unpin(gt); +- } +-} +- +-const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = { +- .dpms = cdv_intel_crtc_dpms, +- .mode_fixup = cdv_intel_crtc_mode_fixup, +- .mode_set = cdv_intel_crtc_mode_set, +- .mode_set_base = cdv_intel_pipe_set_base, +- .prepare = cdv_intel_crtc_prepare, +- .commit = cdv_intel_crtc_commit, +- .disable = cdv_intel_crtc_disable, +-}; +- +-const struct drm_crtc_funcs cdv_intel_crtc_funcs = { +- .save = cdv_intel_crtc_save, +- .restore = cdv_intel_crtc_restore, +- .cursor_set = cdv_intel_crtc_cursor_set, +- .cursor_move = cdv_intel_crtc_cursor_move, +- .gamma_set = cdv_intel_crtc_gamma_set, +- .set_config = cdv_crtc_set_config, +- .destroy = cdv_intel_crtc_destroy, +-}; +- +-/* +- * Set the default value of cursor control and base register +- * to zero. This is a workaround for h/w defect on oaktrail +- */ +-void cdv_intel_cursor_init(struct drm_device *dev, int pipe) +-{ +- uint32_t control; +- uint32_t base; +- +- switch (pipe) { +- case 0: +- control = CURACNTR; +- base = CURABASE; +- break; +- case 1: +- control = CURBCNTR; +- base = CURBBASE; +- break; +- case 2: +- control = CURCCNTR; +- base = CURCBASE; +- break; +- default: +- return; +- } +- +- REG_WRITE(control, 0); +- REG_WRITE(base, 0); +-} +- +diff --git a/drivers/staging/gma500/cdv_intel_hdmi.c b/drivers/staging/gma500/cdv_intel_hdmi.c +deleted file mode 100644 +index cbca2b0..0000000 +--- a/drivers/staging/gma500/cdv_intel_hdmi.c ++++ /dev/null +@@ -1,376 +0,0 @@ +-/* +- * Copyright © 2006-2011 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * jim liu +- * +- * FIXME: +- * We should probably make this generic and share it with Medfield +- */ +- +-#include +-#include +-#include +-#include +-#include "psb_intel_drv.h" +-#include "psb_drv.h" +-#include "psb_intel_reg.h" +-#include +- +-/* hdmi control bits */ +-#define HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9) +-#define HDMI_BORDER_ENABLE (1 << 7) +-#define HDMI_AUDIO_ENABLE (1 << 6) +-#define HDMI_VSYNC_ACTIVE_HIGH (1 << 4) +-#define HDMI_HSYNC_ACTIVE_HIGH (1 << 3) +-/* hdmi-b control bits */ +-#define HDMIB_PIPE_B_SELECT (1 << 30) +- +- +-struct mid_intel_hdmi_priv { +- u32 hdmi_reg; +- u32 save_HDMIB; +- bool has_hdmi_sink; +- bool has_hdmi_audio; +- /* Should set this when detect hotplug */ +- bool hdmi_device_connected; +- struct mdfld_hdmi_i2c *i2c_bus; +- struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */ +- struct drm_device *dev; +-}; +- +-static void cdv_hdmi_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- struct drm_device *dev = encoder->dev; +- struct psb_intel_output *output = enc_to_psb_intel_output(encoder); +- struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv; +- u32 hdmib; +- struct drm_crtc *crtc = encoder->crtc; +- struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); +- +- hdmib = (2 << 10); +- +- if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) +- hdmib |= HDMI_VSYNC_ACTIVE_HIGH; +- if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) +- hdmib |= HDMI_HSYNC_ACTIVE_HIGH; +- +- if (intel_crtc->pipe == 1) +- hdmib |= HDMIB_PIPE_B_SELECT; +- +- if (hdmi_priv->has_hdmi_audio) { +- hdmib |= HDMI_AUDIO_ENABLE; +- hdmib |= HDMI_NULL_PACKETS_DURING_VSYNC; +- } +- +- REG_WRITE(hdmi_priv->hdmi_reg, hdmib); +- REG_READ(hdmi_priv->hdmi_reg); +-} +- +-static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- return true; +-} +- +-static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode) +-{ +- struct drm_device *dev = encoder->dev; +- struct psb_intel_output *output = enc_to_psb_intel_output(encoder); +- struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv; +- u32 hdmib; +- +- hdmib = REG_READ(hdmi_priv->hdmi_reg); +- +- if (mode != DRM_MODE_DPMS_ON) +- REG_WRITE(hdmi_priv->hdmi_reg, hdmib & ~HDMIB_PORT_EN); +- else +- REG_WRITE(hdmi_priv->hdmi_reg, hdmib | HDMIB_PORT_EN); +- REG_READ(hdmi_priv->hdmi_reg); +-} +- +-static void cdv_hdmi_save(struct drm_connector *connector) +-{ +- struct drm_device *dev = connector->dev; +- struct psb_intel_output *output = to_psb_intel_output(connector); +- struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv; +- +- hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmi_reg); +-} +- +-static void cdv_hdmi_restore(struct drm_connector *connector) +-{ +- struct drm_device *dev = connector->dev; +- struct psb_intel_output *output = to_psb_intel_output(connector); +- struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv; +- +- REG_WRITE(hdmi_priv->hdmi_reg, hdmi_priv->save_HDMIB); +- REG_READ(hdmi_priv->hdmi_reg); +-} +- +-static enum drm_connector_status cdv_hdmi_detect( +- struct drm_connector *connector, bool force) +-{ +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_output->dev_priv; +- struct edid *edid = NULL; +- enum drm_connector_status status = connector_status_disconnected; +- +- edid = drm_get_edid(&psb_intel_output->base, +- psb_intel_output->hdmi_i2c_adapter); +- +- hdmi_priv->has_hdmi_sink = false; +- hdmi_priv->has_hdmi_audio = false; +- if (edid) { +- if (edid->input & DRM_EDID_INPUT_DIGITAL) { +- status = connector_status_connected; +- hdmi_priv->has_hdmi_sink = +- drm_detect_hdmi_monitor(edid); +- hdmi_priv->has_hdmi_audio = +- drm_detect_monitor_audio(edid); +- } +- +- psb_intel_output->base.display_info.raw_edid = NULL; +- kfree(edid); +- } +- return status; +-} +- +-static int cdv_hdmi_set_property(struct drm_connector *connector, +- struct drm_property *property, +- uint64_t value) +-{ +- struct drm_encoder *encoder = connector->encoder; +- +- if (!strcmp(property->name, "scaling mode") && encoder) { +- struct psb_intel_crtc *crtc = to_psb_intel_crtc(encoder->crtc); +- bool centre; +- uint64_t curValue; +- +- if (!crtc) +- return -1; +- +- switch (value) { +- case DRM_MODE_SCALE_FULLSCREEN: +- break; +- case DRM_MODE_SCALE_NO_SCALE: +- break; +- case DRM_MODE_SCALE_ASPECT: +- break; +- default: +- return -1; +- } +- +- if (drm_connector_property_get_value(connector, +- property, &curValue)) +- return -1; +- +- if (curValue == value) +- return 0; +- +- if (drm_connector_property_set_value(connector, +- property, value)) +- return -1; +- +- centre = (curValue == DRM_MODE_SCALE_NO_SCALE) || +- (value == DRM_MODE_SCALE_NO_SCALE); +- +- if (crtc->saved_mode.hdisplay != 0 && +- crtc->saved_mode.vdisplay != 0) { +- if (centre) { +- if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode, +- encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb)) +- return -1; +- } else { +- struct drm_encoder_helper_funcs *helpers +- = encoder->helper_private; +- helpers->mode_set(encoder, &crtc->saved_mode, +- &crtc->saved_adjusted_mode); +- } +- } +- } +- return 0; +-} +- +-/* +- * Return the list of HDMI DDC modes if available. +- */ +-static int cdv_hdmi_get_modes(struct drm_connector *connector) +-{ +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- struct edid *edid = NULL; +- int ret = 0; +- +- edid = drm_get_edid(&psb_intel_output->base, +- psb_intel_output->hdmi_i2c_adapter); +- if (edid) { +- drm_mode_connector_update_edid_property(&psb_intel_output-> +- base, edid); +- ret = drm_add_edid_modes(&psb_intel_output->base, edid); +- kfree(edid); +- } +- return ret; +-} +- +-static int cdv_hdmi_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) +-{ +- +- if (mode->clock > 165000) +- return MODE_CLOCK_HIGH; +- if (mode->clock < 20000) +- return MODE_CLOCK_HIGH; +- +- /* just in case */ +- if (mode->flags & DRM_MODE_FLAG_DBLSCAN) +- return MODE_NO_DBLESCAN; +- +- /* just in case */ +- if (mode->flags & DRM_MODE_FLAG_INTERLACE) +- return MODE_NO_INTERLACE; +- +- /* +- * FIXME: for now we limit the size to 1680x1050 on CDV, otherwise it +- * will go beyond the stolen memory size allocated to the framebuffer +- */ +- if (mode->hdisplay > 1680) +- return MODE_PANEL; +- if (mode->vdisplay > 1050) +- return MODE_PANEL; +- return MODE_OK; +-} +- +-static void cdv_hdmi_destroy(struct drm_connector *connector) +-{ +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- +- if (psb_intel_output->ddc_bus) +- psb_intel_i2c_destroy(psb_intel_output->ddc_bus); +- drm_sysfs_connector_remove(connector); +- drm_connector_cleanup(connector); +- kfree(connector); +-} +- +-static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = { +- .dpms = cdv_hdmi_dpms, +- .mode_fixup = cdv_hdmi_mode_fixup, +- .prepare = psb_intel_encoder_prepare, +- .mode_set = cdv_hdmi_mode_set, +- .commit = psb_intel_encoder_commit, +-}; +- +-static const struct drm_connector_helper_funcs +- cdv_hdmi_connector_helper_funcs = { +- .get_modes = cdv_hdmi_get_modes, +- .mode_valid = cdv_hdmi_mode_valid, +- .best_encoder = psb_intel_best_encoder, +-}; +- +-static const struct drm_connector_funcs cdv_hdmi_connector_funcs = { +- .dpms = drm_helper_connector_dpms, +- .save = cdv_hdmi_save, +- .restore = cdv_hdmi_restore, +- .detect = cdv_hdmi_detect, +- .fill_modes = drm_helper_probe_single_connector_modes, +- .set_property = cdv_hdmi_set_property, +- .destroy = cdv_hdmi_destroy, +-}; +- +-void cdv_hdmi_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev, int reg) +-{ +- struct psb_intel_output *psb_intel_output; +- struct drm_connector *connector; +- struct drm_encoder *encoder; +- struct mid_intel_hdmi_priv *hdmi_priv; +- int ddc_bus; +- +- psb_intel_output = kzalloc(sizeof(struct psb_intel_output) + +- sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL); +- if (!psb_intel_output) +- return; +- +- hdmi_priv = (struct mid_intel_hdmi_priv *)(psb_intel_output + 1); +- psb_intel_output->mode_dev = mode_dev; +- connector = &psb_intel_output->base; +- encoder = &psb_intel_output->enc; +- drm_connector_init(dev, &psb_intel_output->base, +- &cdv_hdmi_connector_funcs, +- DRM_MODE_CONNECTOR_DVID); +- +- drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs, +- DRM_MODE_ENCODER_TMDS); +- +- drm_mode_connector_attach_encoder(&psb_intel_output->base, +- &psb_intel_output->enc); +- psb_intel_output->type = INTEL_OUTPUT_HDMI; +- hdmi_priv->hdmi_reg = reg; +- hdmi_priv->has_hdmi_sink = false; +- psb_intel_output->dev_priv = hdmi_priv; +- +- drm_encoder_helper_add(encoder, &cdv_hdmi_helper_funcs); +- drm_connector_helper_add(connector, +- &cdv_hdmi_connector_helper_funcs); +- connector->display_info.subpixel_order = SubPixelHorizontalRGB; +- connector->interlace_allowed = false; +- connector->doublescan_allowed = false; +- +- drm_connector_attach_property(connector, +- dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN); +- +- switch (reg) { +- case SDVOB: +- ddc_bus = GPIOE; +- break; +- case SDVOC: +- ddc_bus = GPIOD; +- break; +- default: +- DRM_ERROR("unknown reg 0x%x for HDMI\n", reg); +- goto failed_ddc; +- break; +- } +- +- psb_intel_output->ddc_bus = psb_intel_i2c_create(dev, +- ddc_bus, (reg == SDVOB) ? "HDMIB" : "HDMIC"); +- +- if (!psb_intel_output->ddc_bus) { +- dev_err(dev->dev, "No ddc adapter available!\n"); +- goto failed_ddc; +- } +- psb_intel_output->hdmi_i2c_adapter = +- &(psb_intel_output->ddc_bus->adapter); +- hdmi_priv->dev = dev; +- drm_sysfs_connector_add(connector); +- return; +- +-failed_ddc: +- drm_encoder_cleanup(&psb_intel_output->enc); +- drm_connector_cleanup(&psb_intel_output->base); +- kfree(psb_intel_output); +-} +diff --git a/drivers/staging/gma500/cdv_intel_lvds.c b/drivers/staging/gma500/cdv_intel_lvds.c +deleted file mode 100644 +index 988b2d0..0000000 +--- a/drivers/staging/gma500/cdv_intel_lvds.c ++++ /dev/null +@@ -1,721 +0,0 @@ +-/* +- * Copyright © 2006-2011 Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Eric Anholt +- * Dave Airlie +- * Jesse Barnes +- */ +- +-#include +-#include +-#include +- +-#include "intel_bios.h" +-#include "psb_drv.h" +-#include "psb_intel_drv.h" +-#include "psb_intel_reg.h" +-#include "power.h" +-#include +-#include "cdv_device.h" +- +-/** +- * LVDS I2C backlight control macros +- */ +-#define BRIGHTNESS_MAX_LEVEL 100 +-#define BRIGHTNESS_MASK 0xFF +-#define BLC_I2C_TYPE 0x01 +-#define BLC_PWM_TYPT 0x02 +- +-#define BLC_POLARITY_NORMAL 0 +-#define BLC_POLARITY_INVERSE 1 +- +-#define PSB_BLC_MAX_PWM_REG_FREQ (0xFFFE) +-#define PSB_BLC_MIN_PWM_REG_FREQ (0x2) +-#define PSB_BLC_PWM_PRECISION_FACTOR (10) +-#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) +-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) +- +-struct cdv_intel_lvds_priv { +- /** +- * Saved LVDO output states +- */ +- uint32_t savePP_ON; +- uint32_t savePP_OFF; +- uint32_t saveLVDS; +- uint32_t savePP_CONTROL; +- uint32_t savePP_CYCLE; +- uint32_t savePFIT_CONTROL; +- uint32_t savePFIT_PGM_RATIOS; +- uint32_t saveBLC_PWM_CTL; +-}; +- +-/* +- * Returns the maximum level of the backlight duty cycle field. +- */ +-static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 retval; +- +- if (gma_power_begin(dev, false)) { +- retval = ((REG_READ(BLC_PWM_CTL) & +- BACKLIGHT_MODULATION_FREQ_MASK) >> +- BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; +- +- gma_power_end(dev); +- } else +- retval = ((dev_priv->saveBLC_PWM_CTL & +- BACKLIGHT_MODULATION_FREQ_MASK) >> +- BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; +- +- return retval; +-} +- +-/* +- * Set LVDS backlight level by I2C command +- */ +-static int cdv_lvds_i2c_set_brightness(struct drm_device *dev, +- unsigned int level) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus; +- u8 out_buf[2]; +- unsigned int blc_i2c_brightness; +- +- struct i2c_msg msgs[] = { +- { +- .addr = lvds_i2c_bus->slave_addr, +- .flags = 0, +- .len = 2, +- .buf = out_buf, +- } +- }; +- +- blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level * +- BRIGHTNESS_MASK / +- BRIGHTNESS_MAX_LEVEL); +- +- if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) +- blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness; +- +- out_buf[0] = dev_priv->lvds_bl->brightnesscmd; +- out_buf[1] = (u8)blc_i2c_brightness; +- +- if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) +- return 0; +- +- DRM_ERROR("I2C transfer error\n"); +- return -1; +-} +- +- +-static int cdv_lvds_pwm_set_brightness(struct drm_device *dev, int level) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- u32 max_pwm_blc; +- u32 blc_pwm_duty_cycle; +- +- max_pwm_blc = cdv_intel_lvds_get_max_backlight(dev); +- +- /*BLC_PWM_CTL Should be initiated while backlight device init*/ +- BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0); +- +- blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL; +- +- if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) +- blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle; +- +- blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; +- REG_WRITE(BLC_PWM_CTL, +- (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | +- (blc_pwm_duty_cycle)); +- +- return 0; +-} +- +-/* +- * Set LVDS backlight level either by I2C or PWM +- */ +-void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (!dev_priv->lvds_bl) { +- DRM_ERROR("NO LVDS Backlight Info\n"); +- return; +- } +- +- if (dev_priv->lvds_bl->type == BLC_I2C_TYPE) +- cdv_lvds_i2c_set_brightness(dev, level); +- else +- cdv_lvds_pwm_set_brightness(dev, level); +-} +- +-/** +- * Sets the backlight level. +- * +- * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight(). +- */ +-static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 blc_pwm_ctl; +- +- if (gma_power_begin(dev, false)) { +- blc_pwm_ctl = +- REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; +- REG_WRITE(BLC_PWM_CTL, +- (blc_pwm_ctl | +- (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); +- gma_power_end(dev); +- } else { +- blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL & +- ~BACKLIGHT_DUTY_CYCLE_MASK; +- dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl | +- (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); +- } +-} +- +-/** +- * Sets the power state for the panel. +- */ +-static void cdv_intel_lvds_set_power(struct drm_device *dev, +- struct psb_intel_output *output, bool on) +-{ +- u32 pp_status; +- +- if (!gma_power_begin(dev, true)) +- return; +- +- if (on) { +- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | +- POWER_TARGET_ON); +- do { +- pp_status = REG_READ(PP_STATUS); +- } while ((pp_status & PP_ON) == 0); +- +- cdv_intel_lvds_set_backlight(dev, +- output-> +- mode_dev->backlight_duty_cycle); +- } else { +- cdv_intel_lvds_set_backlight(dev, 0); +- +- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & +- ~POWER_TARGET_ON); +- do { +- pp_status = REG_READ(PP_STATUS); +- } while (pp_status & PP_ON); +- } +- gma_power_end(dev); +-} +- +-static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode) +-{ +- struct drm_device *dev = encoder->dev; +- struct psb_intel_output *output = enc_to_psb_intel_output(encoder); +- if (mode == DRM_MODE_DPMS_ON) +- cdv_intel_lvds_set_power(dev, output, true); +- else +- cdv_intel_lvds_set_power(dev, output, false); +- /* XXX: We never power down the LVDS pairs. */ +-} +- +-static void cdv_intel_lvds_save(struct drm_connector *connector) +-{ +-} +- +-static void cdv_intel_lvds_restore(struct drm_connector *connector) +-{ +-} +- +-int cdv_intel_lvds_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) +-{ +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- struct drm_display_mode *fixed_mode = +- psb_intel_output->mode_dev->panel_fixed_mode; +- +- /* just in case */ +- if (mode->flags & DRM_MODE_FLAG_DBLSCAN) +- return MODE_NO_DBLESCAN; +- +- /* just in case */ +- if (mode->flags & DRM_MODE_FLAG_INTERLACE) +- return MODE_NO_INTERLACE; +- +- if (fixed_mode) { +- if (mode->hdisplay > fixed_mode->hdisplay) +- return MODE_PANEL; +- if (mode->vdisplay > fixed_mode->vdisplay) +- return MODE_PANEL; +- } +- return MODE_OK; +-} +- +-bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- struct psb_intel_mode_device *mode_dev = +- enc_to_psb_intel_output(encoder)->mode_dev; +- struct drm_device *dev = encoder->dev; +- struct drm_encoder *tmp_encoder; +- struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode; +- +- /* Should never happen!! */ +- list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, +- head) { +- if (tmp_encoder != encoder +- && tmp_encoder->crtc == encoder->crtc) { +- printk(KERN_ERR "Can't enable LVDS and another " +- "encoder on the same pipe\n"); +- return false; +- } +- } +- +- /* +- * If we have timings from the BIOS for the panel, put them in +- * to the adjusted mode. The CRTC will be set up for this mode, +- * with the panel scaling set up to source from the H/VDisplay +- * of the original mode. +- */ +- if (panel_fixed_mode != NULL) { +- adjusted_mode->hdisplay = panel_fixed_mode->hdisplay; +- adjusted_mode->hsync_start = panel_fixed_mode->hsync_start; +- adjusted_mode->hsync_end = panel_fixed_mode->hsync_end; +- adjusted_mode->htotal = panel_fixed_mode->htotal; +- adjusted_mode->vdisplay = panel_fixed_mode->vdisplay; +- adjusted_mode->vsync_start = panel_fixed_mode->vsync_start; +- adjusted_mode->vsync_end = panel_fixed_mode->vsync_end; +- adjusted_mode->vtotal = panel_fixed_mode->vtotal; +- adjusted_mode->clock = panel_fixed_mode->clock; +- drm_mode_set_crtcinfo(adjusted_mode, +- CRTC_INTERLACE_HALVE_V); +- } +- +- /* +- * XXX: It would be nice to support lower refresh rates on the +- * panels to reduce power consumption, and perhaps match the +- * user's requested refresh rate. +- */ +- +- return true; +-} +- +-static void cdv_intel_lvds_prepare(struct drm_encoder *encoder) +-{ +- struct drm_device *dev = encoder->dev; +- struct psb_intel_output *output = enc_to_psb_intel_output(encoder); +- struct psb_intel_mode_device *mode_dev = output->mode_dev; +- +- if (!gma_power_begin(dev, true)) +- return; +- +- mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); +- mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & +- BACKLIGHT_DUTY_CYCLE_MASK); +- +- cdv_intel_lvds_set_power(dev, output, false); +- +- gma_power_end(dev); +-} +- +-static void cdv_intel_lvds_commit(struct drm_encoder *encoder) +-{ +- struct drm_device *dev = encoder->dev; +- struct psb_intel_output *output = enc_to_psb_intel_output(encoder); +- struct psb_intel_mode_device *mode_dev = output->mode_dev; +- +- if (mode_dev->backlight_duty_cycle == 0) +- mode_dev->backlight_duty_cycle = +- cdv_intel_lvds_get_max_backlight(dev); +- +- cdv_intel_lvds_set_power(dev, output, true); +-} +- +-static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- struct drm_device *dev = encoder->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 pfit_control; +- +- /* +- * The LVDS pin pair will already have been turned on in the +- * cdv_intel_crtc_mode_set since it has a large impact on the DPLL +- * settings. +- */ +- +- /* +- * Enable automatic panel scaling so that non-native modes fill the +- * screen. Should be enabled before the pipe is enabled, according to +- * register description and PRM. +- */ +- if (mode->hdisplay != adjusted_mode->hdisplay || +- mode->vdisplay != adjusted_mode->vdisplay) +- pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | +- HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | +- HORIZ_INTERP_BILINEAR); +- else +- pfit_control = 0; +- +- if (dev_priv->lvds_dither) +- pfit_control |= PANEL_8TO6_DITHER_ENABLE; +- +- REG_WRITE(PFIT_CONTROL, pfit_control); +-} +- +-/** +- * Detect the LVDS connection. +- * +- * This always returns CONNECTOR_STATUS_CONNECTED. +- * This connector should only have +- * been set up if the LVDS was actually connected anyway. +- */ +-static enum drm_connector_status cdv_intel_lvds_detect( +- struct drm_connector *connector, bool force) +-{ +- return connector_status_connected; +-} +- +-/** +- * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. +- */ +-static int cdv_intel_lvds_get_modes(struct drm_connector *connector) +-{ +- struct drm_device *dev = connector->dev; +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- struct psb_intel_mode_device *mode_dev = +- psb_intel_output->mode_dev; +- int ret; +- +- ret = psb_intel_ddc_get_modes(psb_intel_output); +- +- if (ret) +- return ret; +- +- /* Didn't get an EDID, so +- * Set wide sync ranges so we get all modes +- * handed to valid_mode for checking +- */ +- connector->display_info.min_vfreq = 0; +- connector->display_info.max_vfreq = 200; +- connector->display_info.min_hfreq = 0; +- connector->display_info.max_hfreq = 200; +- if (mode_dev->panel_fixed_mode != NULL) { +- struct drm_display_mode *mode = +- drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); +- drm_mode_probed_add(connector, mode); +- return 1; +- } +- +- return 0; +-} +- +-/** +- * cdv_intel_lvds_destroy - unregister and free LVDS structures +- * @connector: connector to free +- * +- * Unregister the DDC bus for this connector then free the driver private +- * structure. +- */ +-void cdv_intel_lvds_destroy(struct drm_connector *connector) +-{ +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- +- if (psb_intel_output->ddc_bus) +- psb_intel_i2c_destroy(psb_intel_output->ddc_bus); +- drm_sysfs_connector_remove(connector); +- drm_connector_cleanup(connector); +- kfree(connector); +-} +- +-int cdv_intel_lvds_set_property(struct drm_connector *connector, +- struct drm_property *property, +- uint64_t value) +-{ +- struct drm_encoder *encoder = connector->encoder; +- +- if (!strcmp(property->name, "scaling mode") && encoder) { +- struct psb_intel_crtc *crtc = +- to_psb_intel_crtc(encoder->crtc); +- uint64_t curValue; +- +- if (!crtc) +- return -1; +- +- switch (value) { +- case DRM_MODE_SCALE_FULLSCREEN: +- break; +- case DRM_MODE_SCALE_NO_SCALE: +- break; +- case DRM_MODE_SCALE_ASPECT: +- break; +- default: +- return -1; +- } +- +- if (drm_connector_property_get_value(connector, +- property, +- &curValue)) +- return -1; +- +- if (curValue == value) +- return 0; +- +- if (drm_connector_property_set_value(connector, +- property, +- value)) +- return -1; +- +- if (crtc->saved_mode.hdisplay != 0 && +- crtc->saved_mode.vdisplay != 0) { +- if (!drm_crtc_helper_set_mode(encoder->crtc, +- &crtc->saved_mode, +- encoder->crtc->x, +- encoder->crtc->y, +- encoder->crtc->fb)) +- return -1; +- } +- } else if (!strcmp(property->name, "backlight") && encoder) { +- if (drm_connector_property_set_value(connector, +- property, +- value)) +- return -1; +- else { +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- struct drm_psb_private *dev_priv = +- encoder->dev->dev_private; +- struct backlight_device *bd = +- dev_priv->backlight_device; +- bd->props.brightness = value; +- backlight_update_status(bd); +-#endif +- } +- } else if (!strcmp(property->name, "DPMS") && encoder) { +- struct drm_encoder_helper_funcs *helpers = +- encoder->helper_private; +- helpers->dpms(encoder, value); +- } +- return 0; +-} +- +-static const struct drm_encoder_helper_funcs +- cdv_intel_lvds_helper_funcs = { +- .dpms = cdv_intel_lvds_encoder_dpms, +- .mode_fixup = cdv_intel_lvds_mode_fixup, +- .prepare = cdv_intel_lvds_prepare, +- .mode_set = cdv_intel_lvds_mode_set, +- .commit = cdv_intel_lvds_commit, +-}; +- +-static const struct drm_connector_helper_funcs +- cdv_intel_lvds_connector_helper_funcs = { +- .get_modes = cdv_intel_lvds_get_modes, +- .mode_valid = cdv_intel_lvds_mode_valid, +- .best_encoder = psb_intel_best_encoder, +-}; +- +-static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = { +- .dpms = drm_helper_connector_dpms, +- .save = cdv_intel_lvds_save, +- .restore = cdv_intel_lvds_restore, +- .detect = cdv_intel_lvds_detect, +- .fill_modes = drm_helper_probe_single_connector_modes, +- .set_property = cdv_intel_lvds_set_property, +- .destroy = cdv_intel_lvds_destroy, +-}; +- +- +-static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder) +-{ +- drm_encoder_cleanup(encoder); +-} +- +-const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = { +- .destroy = cdv_intel_lvds_enc_destroy, +-}; +- +-/** +- * cdv_intel_lvds_init - setup LVDS connectors on this device +- * @dev: drm device +- * +- * Create the connector, register the LVDS DDC bus, and try to figure out what +- * modes we can display on the LVDS panel (if present). +- */ +-void cdv_intel_lvds_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev) +-{ +- struct psb_intel_output *psb_intel_output; +- struct cdv_intel_lvds_priv *lvds_priv; +- struct drm_connector *connector; +- struct drm_encoder *encoder; +- struct drm_display_mode *scan; +- struct drm_crtc *crtc; +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 lvds; +- int pipe; +- +- psb_intel_output = kzalloc(sizeof(struct psb_intel_output) + +- sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL); +- if (!psb_intel_output) +- return; +- +- lvds_priv = (struct cdv_intel_lvds_priv *)(psb_intel_output + 1); +- +- psb_intel_output->dev_priv = lvds_priv; +- +- psb_intel_output->mode_dev = mode_dev; +- connector = &psb_intel_output->base; +- encoder = &psb_intel_output->enc; +- +- +- drm_connector_init(dev, &psb_intel_output->base, +- &cdv_intel_lvds_connector_funcs, +- DRM_MODE_CONNECTOR_LVDS); +- +- drm_encoder_init(dev, &psb_intel_output->enc, +- &cdv_intel_lvds_enc_funcs, +- DRM_MODE_ENCODER_LVDS); +- +- +- drm_mode_connector_attach_encoder(&psb_intel_output->base, +- &psb_intel_output->enc); +- psb_intel_output->type = INTEL_OUTPUT_LVDS; +- +- drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs); +- drm_connector_helper_add(connector, +- &cdv_intel_lvds_connector_helper_funcs); +- connector->display_info.subpixel_order = SubPixelHorizontalRGB; +- connector->interlace_allowed = false; +- connector->doublescan_allowed = false; +- +- /*Attach connector properties*/ +- drm_connector_attach_property(connector, +- dev->mode_config.scaling_mode_property, +- DRM_MODE_SCALE_FULLSCREEN); +- drm_connector_attach_property(connector, +- dev_priv->backlight_property, +- BRIGHTNESS_MAX_LEVEL); +- +- /** +- * Set up I2C bus +- * FIXME: distroy i2c_bus when exit +- */ +- psb_intel_output->i2c_bus = psb_intel_i2c_create(dev, +- GPIOB, +- "LVDSBLC_B"); +- if (!psb_intel_output->i2c_bus) { +- dev_printk(KERN_ERR, +- &dev->pdev->dev, "I2C bus registration failed.\n"); +- goto failed_blc_i2c; +- } +- psb_intel_output->i2c_bus->slave_addr = 0x2C; +- dev_priv->lvds_i2c_bus = psb_intel_output->i2c_bus; +- +- /* +- * LVDS discovery: +- * 1) check for EDID on DDC +- * 2) check for VBT data +- * 3) check to see if LVDS is already on +- * if none of the above, no panel +- * 4) make sure lid is open +- * if closed, act like it's not there for now +- */ +- +- /* Set up the DDC bus. */ +- psb_intel_output->ddc_bus = psb_intel_i2c_create(dev, +- GPIOC, +- "LVDSDDC_C"); +- if (!psb_intel_output->ddc_bus) { +- dev_printk(KERN_ERR, &dev->pdev->dev, +- "DDC bus registration " "failed.\n"); +- goto failed_ddc; +- } +- +- /* +- * Attempt to get the fixed panel mode from DDC. Assume that the +- * preferred mode is the right one. +- */ +- psb_intel_ddc_get_modes(psb_intel_output); +- list_for_each_entry(scan, &connector->probed_modes, head) { +- if (scan->type & DRM_MODE_TYPE_PREFERRED) { +- mode_dev->panel_fixed_mode = +- drm_mode_duplicate(dev, scan); +- goto out; /* FIXME: check for quirks */ +- } +- } +- +- /* Failed to get EDID, what about VBT? do we need this?*/ +- if (dev_priv->lfp_lvds_vbt_mode) { +- mode_dev->panel_fixed_mode = +- drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); +- if (mode_dev->panel_fixed_mode) { +- mode_dev->panel_fixed_mode->type |= +- DRM_MODE_TYPE_PREFERRED; +- goto out; /* FIXME: check for quirks */ +- } +- } +- /* +- * If we didn't get EDID, try checking if the panel is already turned +- * on. If so, assume that whatever is currently programmed is the +- * correct mode. +- */ +- lvds = REG_READ(LVDS); +- pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; +- crtc = psb_intel_get_crtc_from_pipe(dev, pipe); +- +- if (crtc && (lvds & LVDS_PORT_EN)) { +- mode_dev->panel_fixed_mode = +- cdv_intel_crtc_mode_get(dev, crtc); +- if (mode_dev->panel_fixed_mode) { +- mode_dev->panel_fixed_mode->type |= +- DRM_MODE_TYPE_PREFERRED; +- goto out; /* FIXME: check for quirks */ +- } +- } +- +- /* If we still don't have a mode after all that, give up. */ +- if (!mode_dev->panel_fixed_mode) { +- DRM_DEBUG +- ("Found no modes on the lvds, ignoring the LVDS\n"); +- goto failed_find; +- } +- +-out: +- drm_sysfs_connector_add(connector); +- return; +- +-failed_find: +- printk(KERN_ERR "Failed find\n"); +- if (psb_intel_output->ddc_bus) +- psb_intel_i2c_destroy(psb_intel_output->ddc_bus); +-failed_ddc: +- printk(KERN_ERR "Failed DDC\n"); +- if (psb_intel_output->i2c_bus) +- psb_intel_i2c_destroy(psb_intel_output->i2c_bus); +-failed_blc_i2c: +- printk(KERN_ERR "Failed BLC\n"); +- drm_encoder_cleanup(encoder); +- drm_connector_cleanup(connector); +- kfree(connector); +-} +diff --git a/drivers/staging/gma500/displays/hdmi.h b/drivers/staging/gma500/displays/hdmi.h +deleted file mode 100644 +index d58ba9b..0000000 +--- a/drivers/staging/gma500/displays/hdmi.h ++++ /dev/null +@@ -1,33 +0,0 @@ +-/* +- * Copyright (c) 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Thomas Eaton +- * Scott Rowe +- */ +- +-#ifndef HDMI_H +-#define HDMI_H +- +-extern void hdmi_init(struct drm_device *dev); +- +-#endif +diff --git a/drivers/staging/gma500/displays/pyr_cmd.h b/drivers/staging/gma500/displays/pyr_cmd.h +deleted file mode 100644 +index 84bae5c..0000000 +--- a/drivers/staging/gma500/displays/pyr_cmd.h ++++ /dev/null +@@ -1,34 +0,0 @@ +-/* +- * Copyright (c) 2010 Intel Corporation +- * +- * 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, sublicensen +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Thomas Eaton +- * Scott Rowe +- */ +- +-#ifndef PYR_CMD_H +-#define PYR_CMD_H +- +-extern void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs); +- +-#endif +- +diff --git a/drivers/staging/gma500/displays/pyr_vid.h b/drivers/staging/gma500/displays/pyr_vid.h +deleted file mode 100644 +index ce98860..0000000 +--- a/drivers/staging/gma500/displays/pyr_vid.h ++++ /dev/null +@@ -1,34 +0,0 @@ +-/* +- * Copyright (c) 2010 Intel Corporation +- * +- * 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, sublicensen +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Thomas Eaton +- * Scott Rowe +-*/ +- +-#ifndef PYR_VID_H +-#define PYR_VID_H +- +-extern void pyr_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs); +-extern struct drm_display_mode *pyr_vid_get_config_mode(struct drm_device* dev); +- +-#endif +diff --git a/drivers/staging/gma500/displays/tmd_cmd.h b/drivers/staging/gma500/displays/tmd_cmd.h +deleted file mode 100644 +index 641e85e..0000000 +--- a/drivers/staging/gma500/displays/tmd_cmd.h ++++ /dev/null +@@ -1,34 +0,0 @@ +-/* +- * Copyright (c) 2010 Intel Corporation +- * +- * 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, sublicensen +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Thomas Eaton +- * Scott Rowe +- */ +- +-#ifndef TMD_CMD_H +-#define TMD_CMD_H +- +-extern void tmd_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs); +-extern struct drm_display_mode *tmd_cmd_get_config_mode(struct drm_device *dev); +- +-#endif +diff --git a/drivers/staging/gma500/displays/tmd_vid.h b/drivers/staging/gma500/displays/tmd_vid.h +deleted file mode 100644 +index 7a5fa3b..0000000 +--- a/drivers/staging/gma500/displays/tmd_vid.h ++++ /dev/null +@@ -1,34 +0,0 @@ +-/* +- * Copyright (c) 2010 Intel Corporation +- * +- * 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, sublicensen +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Thomas Eaton +- * Scott Rowe +-*/ +- +-#ifndef TMD_VID_H +-#define TMD_VID_H +- +-extern void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs); +-extern struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev); +- +-#endif +diff --git a/drivers/staging/gma500/displays/tpo_cmd.h b/drivers/staging/gma500/displays/tpo_cmd.h +deleted file mode 100644 +index 6105527..0000000 +--- a/drivers/staging/gma500/displays/tpo_cmd.h ++++ /dev/null +@@ -1,35 +0,0 @@ +-/* +- * Copyright (c) 2010 Intel Corporation +- * +- * 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, sublicensen +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Thomas Eaton +- * Scott Rowe +-*/ +- +-#ifndef TPO_CMD_H +-#define TPO_CMD_H +- +-extern void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs); +-/* extern struct drm_display_mode * */ +-/* tpo_cmd_get_config_mode(struct drm_device *dev); */ +- +-#endif +diff --git a/drivers/staging/gma500/displays/tpo_vid.h b/drivers/staging/gma500/displays/tpo_vid.h +deleted file mode 100644 +index c24f057..0000000 +--- a/drivers/staging/gma500/displays/tpo_vid.h ++++ /dev/null +@@ -1,33 +0,0 @@ +-/* +- * Copyright (c) 2010 Intel Corporation +- * +- * 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, sublicensen +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Thomas Eaton +- * Scott Rowe +- */ +- +-#ifndef TPO_VID_H +-#define TPO_VID_H +- +-extern void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs); +- +-#endif +diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c +deleted file mode 100644 +index d28fdc2..0000000 +--- a/drivers/staging/gma500/framebuffer.c ++++ /dev/null +@@ -1,849 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2007-2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include "psb_drv.h" +-#include "psb_intel_reg.h" +-#include "psb_intel_drv.h" +-#include "framebuffer.h" +-#include "gtt.h" +- +-#include "mdfld_output.h" +- +-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb); +-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, +- struct drm_file *file_priv, +- unsigned int *handle); +- +-static const struct drm_framebuffer_funcs psb_fb_funcs = { +- .destroy = psb_user_framebuffer_destroy, +- .create_handle = psb_user_framebuffer_create_handle, +-}; +- +-#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16) +- +-static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green, +- unsigned blue, unsigned transp, +- struct fb_info *info) +-{ +- struct psb_fbdev *fbdev = info->par; +- struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb; +- uint32_t v; +- +- if (!fb) +- return -ENOMEM; +- +- if (regno > 255) +- return 1; +- +- red = CMAP_TOHW(red, info->var.red.length); +- blue = CMAP_TOHW(blue, info->var.blue.length); +- green = CMAP_TOHW(green, info->var.green.length); +- transp = CMAP_TOHW(transp, info->var.transp.length); +- +- v = (red << info->var.red.offset) | +- (green << info->var.green.offset) | +- (blue << info->var.blue.offset) | +- (transp << info->var.transp.offset); +- +- if (regno < 16) { +- switch (fb->bits_per_pixel) { +- case 16: +- ((uint32_t *) info->pseudo_palette)[regno] = v; +- break; +- case 24: +- case 32: +- ((uint32_t *) info->pseudo_palette)[regno] = v; +- break; +- } +- } +- +- return 0; +-} +- +-static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info) +-{ +- struct psb_fbdev *fbdev = info->par; +- struct psb_framebuffer *psbfb = &fbdev->pfb; +- struct drm_device *dev = psbfb->base.dev; +- +- /* +- * We have to poke our nose in here. The core fb code assumes +- * panning is part of the hardware that can be invoked before +- * the actual fb is mapped. In our case that isn't quite true. +- */ +- if (psbfb->gtt->npage) +- psb_gtt_roll(dev, psbfb->gtt, var->yoffset); +- return 0; +-} +- +-void psbfb_suspend(struct drm_device *dev) +-{ +- struct drm_framebuffer *fb = 0; +- struct psb_framebuffer *psbfb = to_psb_fb(fb); +- +- console_lock(); +- mutex_lock(&dev->mode_config.mutex); +- list_for_each_entry(fb, &dev->mode_config.fb_list, head) { +- struct fb_info *info = psbfb->fbdev; +- fb_set_suspend(info, 1); +- drm_fb_helper_blank(FB_BLANK_POWERDOWN, info); +- } +- mutex_unlock(&dev->mode_config.mutex); +- console_unlock(); +-} +- +-void psbfb_resume(struct drm_device *dev) +-{ +- struct drm_framebuffer *fb = 0; +- struct psb_framebuffer *psbfb = to_psb_fb(fb); +- +- console_lock(); +- mutex_lock(&dev->mode_config.mutex); +- list_for_each_entry(fb, &dev->mode_config.fb_list, head) { +- struct fb_info *info = psbfb->fbdev; +- fb_set_suspend(info, 0); +- drm_fb_helper_blank(FB_BLANK_UNBLANK, info); +- } +- mutex_unlock(&dev->mode_config.mutex); +- console_unlock(); +- drm_helper_disable_unused_functions(dev); +-} +- +-static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +-{ +- struct psb_framebuffer *psbfb = vma->vm_private_data; +- struct drm_device *dev = psbfb->base.dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- int page_num; +- int i; +- unsigned long address; +- int ret; +- unsigned long pfn; +- /* FIXME: assumes fb at stolen base which may not be true */ +- unsigned long phys_addr = (unsigned long)dev_priv->stolen_base; +- +- page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; +- address = (unsigned long)vmf->virtual_address; +- +- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +- +- for (i = 0; i < page_num; i++) { +- pfn = (phys_addr >> PAGE_SHIFT); +- +- ret = vm_insert_mixed(vma, address, pfn); +- if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0))) +- break; +- else if (unlikely(ret != 0)) { +- ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; +- return ret; +- } +- address += PAGE_SIZE; +- phys_addr += PAGE_SIZE; +- } +- return VM_FAULT_NOPAGE; +-} +- +-static void psbfb_vm_open(struct vm_area_struct *vma) +-{ +-} +- +-static void psbfb_vm_close(struct vm_area_struct *vma) +-{ +-} +- +-static struct vm_operations_struct psbfb_vm_ops = { +- .fault = psbfb_vm_fault, +- .open = psbfb_vm_open, +- .close = psbfb_vm_close +-}; +- +-static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) +-{ +- struct psb_fbdev *fbdev = info->par; +- struct psb_framebuffer *psbfb = &fbdev->pfb; +- +- if (vma->vm_pgoff != 0) +- return -EINVAL; +- if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) +- return -EINVAL; +- +- if (!psbfb->addr_space) +- psbfb->addr_space = vma->vm_file->f_mapping; +- /* +- * If this is a GEM object then info->screen_base is the virtual +- * kernel remapping of the object. FIXME: Review if this is +- * suitable for our mmap work +- */ +- vma->vm_ops = &psbfb_vm_ops; +- vma->vm_private_data = (void *)psbfb; +- vma->vm_flags |= VM_RESERVED | VM_IO | +- VM_MIXEDMAP | VM_DONTEXPAND; +- return 0; +-} +- +-static int psbfb_ioctl(struct fb_info *info, unsigned int cmd, +- unsigned long arg) +-{ +- return -ENOTTY; +-} +- +-static struct fb_ops psbfb_ops = { +- .owner = THIS_MODULE, +- .fb_check_var = drm_fb_helper_check_var, +- .fb_set_par = drm_fb_helper_set_par, +- .fb_blank = drm_fb_helper_blank, +- .fb_setcolreg = psbfb_setcolreg, +- .fb_fillrect = cfb_fillrect, +- .fb_copyarea = psbfb_copyarea, +- .fb_imageblit = cfb_imageblit, +- .fb_mmap = psbfb_mmap, +- .fb_sync = psbfb_sync, +- .fb_ioctl = psbfb_ioctl, +-}; +- +-static struct fb_ops psbfb_roll_ops = { +- .owner = THIS_MODULE, +- .fb_check_var = drm_fb_helper_check_var, +- .fb_set_par = drm_fb_helper_set_par, +- .fb_blank = drm_fb_helper_blank, +- .fb_setcolreg = psbfb_setcolreg, +- .fb_fillrect = cfb_fillrect, +- .fb_copyarea = cfb_copyarea, +- .fb_imageblit = cfb_imageblit, +- .fb_pan_display = psbfb_pan, +- .fb_mmap = psbfb_mmap, +- .fb_sync = psbfb_sync, +- .fb_ioctl = psbfb_ioctl, +-}; +- +-static struct fb_ops psbfb_unaccel_ops = { +- .owner = THIS_MODULE, +- .fb_check_var = drm_fb_helper_check_var, +- .fb_set_par = drm_fb_helper_set_par, +- .fb_blank = drm_fb_helper_blank, +- .fb_setcolreg = psbfb_setcolreg, +- .fb_fillrect = cfb_fillrect, +- .fb_copyarea = cfb_copyarea, +- .fb_imageblit = cfb_imageblit, +- .fb_mmap = psbfb_mmap, +- .fb_ioctl = psbfb_ioctl, +-}; +- +-/** +- * psb_framebuffer_init - initialize a framebuffer +- * @dev: our DRM device +- * @fb: framebuffer to set up +- * @mode_cmd: mode description +- * @gt: backing object +- * +- * Configure and fill in the boilerplate for our frame buffer. Return +- * 0 on success or an error code if we fail. +- */ +-static int psb_framebuffer_init(struct drm_device *dev, +- struct psb_framebuffer *fb, +- struct drm_mode_fb_cmd *mode_cmd, +- struct gtt_range *gt) +-{ +- int ret; +- +- if (mode_cmd->pitch & 63) +- return -EINVAL; +- switch (mode_cmd->bpp) { +- case 8: +- case 16: +- case 24: +- case 32: +- break; +- default: +- return -EINVAL; +- } +- ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs); +- if (ret) { +- dev_err(dev->dev, "framebuffer init failed: %d\n", ret); +- return ret; +- } +- drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); +- fb->gtt = gt; +- return 0; +-} +- +-/** +- * psb_framebuffer_create - create a framebuffer backed by gt +- * @dev: our DRM device +- * @mode_cmd: the description of the requested mode +- * @gt: the backing object +- * +- * Create a framebuffer object backed by the gt, and fill in the +- * boilerplate required +- * +- * TODO: review object references +- */ +- +-static struct drm_framebuffer *psb_framebuffer_create +- (struct drm_device *dev, +- struct drm_mode_fb_cmd *mode_cmd, +- struct gtt_range *gt) +-{ +- struct psb_framebuffer *fb; +- int ret; +- +- fb = kzalloc(sizeof(*fb), GFP_KERNEL); +- if (!fb) +- return ERR_PTR(-ENOMEM); +- +- ret = psb_framebuffer_init(dev, fb, mode_cmd, gt); +- if (ret) { +- kfree(fb); +- return ERR_PTR(ret); +- } +- return &fb->base; +-} +- +-/** +- * psbfb_alloc - allocate frame buffer memory +- * @dev: the DRM device +- * @aligned_size: space needed +- * @force: fall back to GEM buffers if need be +- * +- * Allocate the frame buffer. In the usual case we get a GTT range that +- * is stolen memory backed and life is simple. If there isn't sufficient +- * stolen memory or the system has no stolen memory we allocate a range +- * and back it with a GEM object. +- * +- * In this case the GEM object has no handle. +- */ +-static struct gtt_range *psbfb_alloc(struct drm_device *dev, +- int aligned_size, int force) +-{ +- struct gtt_range *backing; +- /* Begin by trying to use stolen memory backing */ +- backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1); +- if (backing) { +- if (drm_gem_private_object_init(dev, +- &backing->gem, aligned_size) == 0) +- return backing; +- psb_gtt_free_range(dev, backing); +- } +- if (!force) +- return NULL; +- +- /* Next try using GEM host memory */ +- backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0); +- if (backing == NULL) +- return NULL; +- +- /* Now back it with an object */ +- if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) { +- psb_gtt_free_range(dev, backing); +- return NULL; +- } +- return backing; +-} +- +-/** +- * psbfb_create - create a framebuffer +- * @fbdev: the framebuffer device +- * @sizes: specification of the layout +- * +- * Create a framebuffer to the specifications provided +- */ +-static int psbfb_create(struct psb_fbdev *fbdev, +- struct drm_fb_helper_surface_size *sizes) +-{ +- struct drm_device *dev = fbdev->psb_fb_helper.dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct fb_info *info; +- struct drm_framebuffer *fb; +- struct psb_framebuffer *psbfb = &fbdev->pfb; +- struct drm_mode_fb_cmd mode_cmd; +- struct device *device = &dev->pdev->dev; +- int size; +- int ret; +- struct gtt_range *backing; +- int gtt_roll = 1; +- +- mode_cmd.width = sizes->surface_width; +- mode_cmd.height = sizes->surface_height; +- mode_cmd.bpp = sizes->surface_bpp; +- +- /* No 24bit packed */ +- if (mode_cmd.bpp == 24) +- mode_cmd.bpp = 32; +- +- /* Acceleration via the GTT requires pitch to be 4096 byte aligned +- (ie 1024 or 2048 pixels in normal use) */ +- mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 4096); +- mode_cmd.depth = sizes->surface_depth; +- +- size = mode_cmd.pitch * mode_cmd.height; +- size = ALIGN(size, PAGE_SIZE); +- +- /* Allocate the framebuffer in the GTT with stolen page backing */ +- backing = psbfb_alloc(dev, size, 0); +- if (backing == NULL) { +- /* +- * We couldn't get the space we wanted, fall back to the +- * display engine requirement instead. The HW requires +- * the pitch to be 64 byte aligned +- */ +- +- gtt_roll = 0; /* Don't use GTT accelerated scrolling */ +- +- mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64); +- mode_cmd.depth = sizes->surface_depth; +- +- size = mode_cmd.pitch * mode_cmd.height; +- size = ALIGN(size, PAGE_SIZE); +- +- /* Allocate the framebuffer in the GTT with stolen page +- backing when there is room */ +- backing = psbfb_alloc(dev, size, 1); +- if (backing == NULL) +- return -ENOMEM; +- } +- +- mutex_lock(&dev->struct_mutex); +- +- info = framebuffer_alloc(0, device); +- if (!info) { +- ret = -ENOMEM; +- goto out_err1; +- } +- info->par = fbdev; +- +- ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing); +- if (ret) +- goto out_unref; +- +- fb = &psbfb->base; +- psbfb->fbdev = info; +- +- fbdev->psb_fb_helper.fb = fb; +- fbdev->psb_fb_helper.fbdev = info; +- +- strcpy(info->fix.id, "psbfb"); +- +- info->flags = FBINFO_DEFAULT; +- if (gtt_roll) { /* GTT rolling seems best */ +- info->fbops = &psbfb_roll_ops; +- info->flags |= FBINFO_HWACCEL_YPAN; +- } +- else if (dev_priv->ops->accel_2d) /* 2D engine */ +- info->fbops = &psbfb_ops; +- else /* Software */ +- info->fbops = &psbfb_unaccel_ops; +- +- ret = fb_alloc_cmap(&info->cmap, 256, 0); +- if (ret) { +- ret = -ENOMEM; +- goto out_unref; +- } +- +- info->fix.smem_start = dev->mode_config.fb_base; +- info->fix.smem_len = size; +- info->fix.ywrapstep = gtt_roll; +- info->fix.ypanstep = gtt_roll; +- +- if (backing->stolen) { +- /* Accessed stolen memory directly */ +- info->screen_base = (char *)dev_priv->vram_addr + +- backing->offset; +- } else { +- /* Pin the pages into the GTT and create a mapping to them */ +- psb_gtt_pin(backing); +- info->screen_base = vm_map_ram(backing->pages, backing->npage, +- -1, PAGE_KERNEL); +- if (info->screen_base == NULL) { +- psb_gtt_unpin(backing); +- ret = -ENOMEM; +- goto out_unref; +- } +- psbfb->vm_map = 1; +- } +- info->screen_size = size; +- +- if (dev_priv->gtt.stolen_size) { +- info->apertures = alloc_apertures(1); +- if (!info->apertures) { +- ret = -ENOMEM; +- goto out_unref; +- } +- info->apertures->ranges[0].base = dev->mode_config.fb_base; +- info->apertures->ranges[0].size = dev_priv->gtt.stolen_size; +- } +- +- drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); +- drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, +- sizes->fb_width, sizes->fb_height); +- +- info->fix.mmio_start = pci_resource_start(dev->pdev, 0); +- info->fix.mmio_len = pci_resource_len(dev->pdev, 0); +- +- info->pixmap.size = 64 * 1024; +- info->pixmap.buf_align = 8; +- info->pixmap.access_align = 32; +- info->pixmap.flags = FB_PIXMAP_SYSTEM; +- info->pixmap.scan_align = 1; +- +- dev_info(dev->dev, "allocated %dx%d fb\n", +- psbfb->base.width, psbfb->base.height); +- +- mutex_unlock(&dev->struct_mutex); +- return 0; +-out_unref: +- if (backing->stolen) +- psb_gtt_free_range(dev, backing); +- else { +- if (psbfb->vm_map) +- vm_unmap_ram(info->screen_base, backing->npage); +- drm_gem_object_unreference(&backing->gem); +- } +-out_err1: +- mutex_unlock(&dev->struct_mutex); +- psb_gtt_free_range(dev, backing); +- return ret; +-} +- +-/** +- * psb_user_framebuffer_create - create framebuffer +- * @dev: our DRM device +- * @filp: client file +- * @cmd: mode request +- * +- * Create a new framebuffer backed by a userspace GEM object +- */ +-static struct drm_framebuffer *psb_user_framebuffer_create +- (struct drm_device *dev, struct drm_file *filp, +- struct drm_mode_fb_cmd *cmd) +-{ +- struct gtt_range *r; +- struct drm_gem_object *obj; +- +- /* +- * Find the GEM object and thus the gtt range object that is +- * to back this space +- */ +- obj = drm_gem_object_lookup(dev, filp, cmd->handle); +- if (obj == NULL) +- return ERR_PTR(-ENOENT); +- +- /* Let the core code do all the work */ +- r = container_of(obj, struct gtt_range, gem); +- return psb_framebuffer_create(dev, cmd, r); +-} +- +-static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, +- u16 blue, int regno) +-{ +-} +- +-static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red, +- u16 *green, u16 *blue, int regno) +-{ +-} +- +-static int psbfb_probe(struct drm_fb_helper *helper, +- struct drm_fb_helper_surface_size *sizes) +-{ +- struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper; +- int new_fb = 0; +- int ret; +- +- if (!helper->fb) { +- ret = psbfb_create(psb_fbdev, sizes); +- if (ret) +- return ret; +- new_fb = 1; +- } +- return new_fb; +-} +- +-struct drm_fb_helper_funcs psb_fb_helper_funcs = { +- .gamma_set = psbfb_gamma_set, +- .gamma_get = psbfb_gamma_get, +- .fb_probe = psbfb_probe, +-}; +- +-int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev) +-{ +- struct fb_info *info; +- struct psb_framebuffer *psbfb = &fbdev->pfb; +- +- if (fbdev->psb_fb_helper.fbdev) { +- info = fbdev->psb_fb_helper.fbdev; +- +- /* If this is our base framebuffer then kill any virtual map +- for the framebuffer layer and unpin it */ +- if (psbfb->vm_map) { +- vm_unmap_ram(info->screen_base, psbfb->gtt->npage); +- psb_gtt_unpin(psbfb->gtt); +- } +- unregister_framebuffer(info); +- if (info->cmap.len) +- fb_dealloc_cmap(&info->cmap); +- framebuffer_release(info); +- } +- drm_fb_helper_fini(&fbdev->psb_fb_helper); +- drm_framebuffer_cleanup(&psbfb->base); +- +- if (psbfb->gtt) +- drm_gem_object_unreference(&psbfb->gtt->gem); +- return 0; +-} +- +-int psb_fbdev_init(struct drm_device *dev) +-{ +- struct psb_fbdev *fbdev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL); +- if (!fbdev) { +- dev_err(dev->dev, "no memory\n"); +- return -ENOMEM; +- } +- +- dev_priv->fbdev = fbdev; +- fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs; +- +- drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs, +- INTELFB_CONN_LIMIT); +- +- drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper); +- drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32); +- return 0; +-} +- +-void psb_fbdev_fini(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (!dev_priv->fbdev) +- return; +- +- psb_fbdev_destroy(dev, dev_priv->fbdev); +- kfree(dev_priv->fbdev); +- dev_priv->fbdev = NULL; +-} +- +-static void psbfb_output_poll_changed(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev; +- drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper); +-} +- +-/** +- * psb_user_framebuffer_create_handle - add hamdle to a framebuffer +- * @fb: framebuffer +- * @file_priv: our DRM file +- * @handle: returned handle +- * +- * Our framebuffer object is a GTT range which also contains a GEM +- * object. We need to turn it into a handle for userspace. GEM will do +- * the work for us +- */ +-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, +- struct drm_file *file_priv, +- unsigned int *handle) +-{ +- struct psb_framebuffer *psbfb = to_psb_fb(fb); +- struct gtt_range *r = psbfb->gtt; +- return drm_gem_handle_create(file_priv, &r->gem, handle); +-} +- +-/** +- * psb_user_framebuffer_destroy - destruct user created fb +- * @fb: framebuffer +- * +- * User framebuffers are backed by GEM objects so all we have to do is +- * clean up a bit and drop the reference, GEM will handle the fallout +- */ +-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb) +-{ +- struct psb_framebuffer *psbfb = to_psb_fb(fb); +- struct gtt_range *r = psbfb->gtt; +- struct drm_device *dev = fb->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct psb_fbdev *fbdev = dev_priv->fbdev; +- struct drm_crtc *crtc; +- int reset = 0; +- +- /* Should never get stolen memory for a user fb */ +- WARN_ON(r->stolen); +- +- /* Check if we are erroneously live */ +- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) +- if (crtc->fb == fb) +- reset = 1; +- +- if (reset) +- /* +- * Now force a sane response before we permit the DRM CRTC +- * layer to do stupid things like blank the display. Instead +- * we reset this framebuffer as if the user had forced a reset. +- * We must do this before the cleanup so that the DRM layer +- * doesn't get a chance to stick its oar in where it isn't +- * wanted. +- */ +- drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper); +- +- /* Let DRM do its clean up */ +- drm_framebuffer_cleanup(fb); +- /* We are no longer using the resource in GEM */ +- drm_gem_object_unreference_unlocked(&r->gem); +- kfree(fb); +-} +- +-static const struct drm_mode_config_funcs psb_mode_funcs = { +- .fb_create = psb_user_framebuffer_create, +- .output_poll_changed = psbfb_output_poll_changed, +-}; +- +-static int psb_create_backlight_property(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct drm_property *backlight; +- +- if (dev_priv->backlight_property) +- return 0; +- +- backlight = drm_property_create(dev, DRM_MODE_PROP_RANGE, +- "backlight", 2); +- backlight->values[0] = 0; +- backlight->values[1] = 100; +- +- dev_priv->backlight_property = backlight; +- +- return 0; +-} +- +-static void psb_setup_outputs(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct drm_connector *connector; +- +- drm_mode_create_scaling_mode_property(dev); +- psb_create_backlight_property(dev); +- +- dev_priv->ops->output_init(dev); +- +- list_for_each_entry(connector, &dev->mode_config.connector_list, +- head) { +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- struct drm_encoder *encoder = &psb_intel_output->enc; +- int crtc_mask = 0, clone_mask = 0; +- +- /* valid crtcs */ +- switch (psb_intel_output->type) { +- case INTEL_OUTPUT_ANALOG: +- crtc_mask = (1 << 0); +- clone_mask = (1 << INTEL_OUTPUT_ANALOG); +- break; +- case INTEL_OUTPUT_SDVO: +- crtc_mask = ((1 << 0) | (1 << 1)); +- clone_mask = (1 << INTEL_OUTPUT_SDVO); +- break; +- case INTEL_OUTPUT_LVDS: +- if (IS_MRST(dev)) +- crtc_mask = (1 << 0); +- else +- crtc_mask = (1 << 1); +- clone_mask = (1 << INTEL_OUTPUT_LVDS); +- break; +- case INTEL_OUTPUT_MIPI: +- crtc_mask = (1 << 0); +- clone_mask = (1 << INTEL_OUTPUT_MIPI); +- break; +- case INTEL_OUTPUT_MIPI2: +- crtc_mask = (1 << 2); +- clone_mask = (1 << INTEL_OUTPUT_MIPI2); +- break; +- case INTEL_OUTPUT_HDMI: +- /* HDMI on crtc 1 for SoC devices and crtc 0 for +- Cedarview. HDMI on Poulsbo is only via external +- logic */ +- if (IS_MFLD(dev) || IS_MRST(dev)) +- crtc_mask = (1 << 1); +- else +- crtc_mask = (1 << 0); /* Cedarview */ +- clone_mask = (1 << INTEL_OUTPUT_HDMI); +- break; +- } +- encoder->possible_crtcs = crtc_mask; +- encoder->possible_clones = +- psb_intel_connector_clones(dev, clone_mask); +- } +-} +- +-void psb_modeset_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *) dev->dev_private; +- struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; +- int i; +- +- drm_mode_config_init(dev); +- +- dev->mode_config.min_width = 0; +- dev->mode_config.min_height = 0; +- +- dev->mode_config.funcs = (void *) &psb_mode_funcs; +- +- /* set memory base */ +- /* MRST and PSB should use BAR 2*/ +- pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *) +- &(dev->mode_config.fb_base)); +- +- /* num pipes is 2 for PSB but 1 for Mrst */ +- for (i = 0; i < dev_priv->num_pipe; i++) +- psb_intel_crtc_init(dev, i, mode_dev); +- +- dev->mode_config.max_width = 4096; +- dev->mode_config.max_height = 4096; +- +- psb_setup_outputs(dev); +-} +- +-void psb_modeset_cleanup(struct drm_device *dev) +-{ +- mutex_lock(&dev->struct_mutex); +- +- drm_kms_helper_poll_fini(dev); +- psb_fbdev_fini(dev); +- drm_mode_config_cleanup(dev); +- +- mutex_unlock(&dev->struct_mutex); +-} +diff --git a/drivers/staging/gma500/framebuffer.h b/drivers/staging/gma500/framebuffer.h +deleted file mode 100644 +index d1b2289..0000000 +--- a/drivers/staging/gma500/framebuffer.h ++++ /dev/null +@@ -1,48 +0,0 @@ +-/* +- * Copyright (c) 2008-2011, Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Eric Anholt +- * +- */ +- +-#ifndef _FRAMEBUFFER_H_ +-#define _FRAMEBUFFER_H_ +- +-#include +-#include +- +-#include "psb_drv.h" +- +-struct psb_framebuffer { +- struct drm_framebuffer base; +- struct address_space *addr_space; +- struct fb_info *fbdev; +- struct gtt_range *gtt; +- bool vm_map; /* True if we must undo a vm_map_ram */ +-}; +- +-struct psb_fbdev { +- struct drm_fb_helper psb_fb_helper; +- struct psb_framebuffer pfb; +-}; +- +-#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base) +- +-extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask); +- +-#endif +- +diff --git a/drivers/staging/gma500/gem.c b/drivers/staging/gma500/gem.c +deleted file mode 100644 +index f6433c0..0000000 +--- a/drivers/staging/gma500/gem.c ++++ /dev/null +@@ -1,292 +0,0 @@ +-/* +- * psb GEM interface +- * +- * Copyright (c) 2011, Intel Corporation. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: Alan Cox +- * +- * TODO: +- * - we need to work out if the MMU is relevant (eg for +- * accelerated operations on a GEM object) +- */ +- +-#include +-#include +-#include "psb_drm.h" +-#include "psb_drv.h" +- +-int psb_gem_init_object(struct drm_gem_object *obj) +-{ +- return -EINVAL; +-} +- +-void psb_gem_free_object(struct drm_gem_object *obj) +-{ +- struct gtt_range *gtt = container_of(obj, struct gtt_range, gem); +- drm_gem_object_release_wrap(obj); +- /* This must occur last as it frees up the memory of the GEM object */ +- psb_gtt_free_range(obj->dev, gtt); +-} +- +-int psb_gem_get_aperture(struct drm_device *dev, void *data, +- struct drm_file *file) +-{ +- return -EINVAL; +-} +- +-/** +- * psb_gem_dumb_map_gtt - buffer mapping for dumb interface +- * @file: our drm client file +- * @dev: drm device +- * @handle: GEM handle to the object (from dumb_create) +- * +- * Do the necessary setup to allow the mapping of the frame buffer +- * into user memory. We don't have to do much here at the moment. +- */ +-int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, +- uint32_t handle, uint64_t *offset) +-{ +- int ret = 0; +- struct drm_gem_object *obj; +- +- if (!(dev->driver->driver_features & DRIVER_GEM)) +- return -ENODEV; +- +- mutex_lock(&dev->struct_mutex); +- +- /* GEM does all our handle to object mapping */ +- obj = drm_gem_object_lookup(dev, file, handle); +- if (obj == NULL) { +- ret = -ENOENT; +- goto unlock; +- } +- /* What validation is needed here ? */ +- +- /* Make it mmapable */ +- if (!obj->map_list.map) { +- ret = gem_create_mmap_offset(obj); +- if (ret) +- goto out; +- } +- /* GEM should really work out the hash offsets for us */ +- *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT; +-out: +- drm_gem_object_unreference(obj); +-unlock: +- mutex_unlock(&dev->struct_mutex); +- return ret; +-} +- +-/** +- * psb_gem_create - create a mappable object +- * @file: the DRM file of the client +- * @dev: our device +- * @size: the size requested +- * @handlep: returned handle (opaque number) +- * +- * Create a GEM object, fill in the boilerplate and attach a handle to +- * it so that userspace can speak about it. This does the core work +- * for the various methods that do/will create GEM objects for things +- */ +-static int psb_gem_create(struct drm_file *file, +- struct drm_device *dev, uint64_t size, uint32_t *handlep) +-{ +- struct gtt_range *r; +- int ret; +- u32 handle; +- +- size = roundup(size, PAGE_SIZE); +- +- /* Allocate our object - for now a direct gtt range which is not +- stolen memory backed */ +- r = psb_gtt_alloc_range(dev, size, "gem", 0); +- if (r == NULL) { +- dev_err(dev->dev, "no memory for %lld byte GEM object\n", size); +- return -ENOSPC; +- } +- /* Initialize the extra goodies GEM needs to do all the hard work */ +- if (drm_gem_object_init(dev, &r->gem, size) != 0) { +- psb_gtt_free_range(dev, r); +- /* GEM doesn't give an error code so use -ENOMEM */ +- dev_err(dev->dev, "GEM init failed for %lld\n", size); +- return -ENOMEM; +- } +- /* Give the object a handle so we can carry it more easily */ +- ret = drm_gem_handle_create(file, &r->gem, &handle); +- if (ret) { +- dev_err(dev->dev, "GEM handle failed for %p, %lld\n", +- &r->gem, size); +- drm_gem_object_release(&r->gem); +- psb_gtt_free_range(dev, r); +- return ret; +- } +- /* We have the initial and handle reference but need only one now */ +- drm_gem_object_unreference(&r->gem); +- *handlep = handle; +- return 0; +-} +- +-/** +- * psb_gem_dumb_create - create a dumb buffer +- * @drm_file: our client file +- * @dev: our device +- * @args: the requested arguments copied from userspace +- * +- * Allocate a buffer suitable for use for a frame buffer of the +- * form described by user space. Give userspace a handle by which +- * to reference it. +- */ +-int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev, +- struct drm_mode_create_dumb *args) +-{ +- args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64); +- args->size = args->pitch * args->height; +- return psb_gem_create(file, dev, args->size, &args->handle); +-} +- +-/** +- * psb_gem_dumb_destroy - destroy a dumb buffer +- * @file: client file +- * @dev: our DRM device +- * @handle: the object handle +- * +- * Destroy a handle that was created via psb_gem_dumb_create, at least +- * we hope it was created that way. i915 seems to assume the caller +- * does the checking but that might be worth review ! FIXME +- */ +-int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, +- uint32_t handle) +-{ +- /* No special work needed, drop the reference and see what falls out */ +- return drm_gem_handle_delete(file, handle); +-} +- +-/** +- * psb_gem_fault - pagefault handler for GEM objects +- * @vma: the VMA of the GEM object +- * @vmf: fault detail +- * +- * Invoked when a fault occurs on an mmap of a GEM managed area. GEM +- * does most of the work for us including the actual map/unmap calls +- * but we need to do the actual page work. +- * +- * This code eventually needs to handle faulting objects in and out +- * of the GTT and repacking it when we run out of space. We can put +- * that off for now and for our simple uses +- * +- * The VMA was set up by GEM. In doing so it also ensured that the +- * vma->vm_private_data points to the GEM object that is backing this +- * mapping. +- */ +-int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +-{ +- struct drm_gem_object *obj; +- struct gtt_range *r; +- int ret; +- unsigned long pfn; +- pgoff_t page_offset; +- struct drm_device *dev; +- struct drm_psb_private *dev_priv; +- +- obj = vma->vm_private_data; /* GEM object */ +- dev = obj->dev; +- dev_priv = dev->dev_private; +- +- r = container_of(obj, struct gtt_range, gem); /* Get the gtt range */ +- +- /* Make sure we don't parallel update on a fault, nor move or remove +- something from beneath our feet */ +- mutex_lock(&dev->struct_mutex); +- +- /* For now the mmap pins the object and it stays pinned. As things +- stand that will do us no harm */ +- if (r->mmapping == 0) { +- ret = psb_gtt_pin(r); +- if (ret < 0) { +- dev_err(dev->dev, "gma500: pin failed: %d\n", ret); +- goto fail; +- } +- r->mmapping = 1; +- } +- +- /* Page relative to the VMA start - we must calculate this ourselves +- because vmf->pgoff is the fake GEM offset */ +- page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start) +- >> PAGE_SHIFT; +- +- /* CPU view of the page, don't go via the GART for CPU writes */ +- if (r->stolen) +- pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT; +- else +- pfn = page_to_pfn(r->pages[page_offset]); +- ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); +- +-fail: +- mutex_unlock(&dev->struct_mutex); +- switch (ret) { +- case 0: +- case -ERESTARTSYS: +- case -EINTR: +- return VM_FAULT_NOPAGE; +- case -ENOMEM: +- return VM_FAULT_OOM; +- default: +- return VM_FAULT_SIGBUS; +- } +-} +- +-static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev, +- int size, u32 *handle) +-{ +- struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1); +- if (gtt == NULL) +- return -ENOMEM; +- if (drm_gem_private_object_init(dev, >t->gem, size) != 0) +- goto free_gtt; +- if (drm_gem_handle_create(file, >t->gem, handle) == 0) +- return 0; +-free_gtt: +- psb_gtt_free_range(dev, gtt); +- return -ENOMEM; +-} +- +-/* +- * GEM interfaces for our specific client +- */ +-int psb_gem_create_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file) +-{ +- struct drm_psb_gem_create *args = data; +- int ret; +- if (args->flags & PSB_GEM_CREATE_STOLEN) { +- ret = psb_gem_create_stolen(file, dev, args->size, +- &args->handle); +- if (ret == 0) +- return 0; +- /* Fall throguh */ +- args->flags &= ~PSB_GEM_CREATE_STOLEN; +- } +- return psb_gem_create(file, dev, args->size, &args->handle); +-} +- +-int psb_gem_mmap_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file) +-{ +- struct drm_psb_gem_mmap *args = data; +- return dev->driver->dumb_map_offset(file, dev, +- args->handle, &args->offset); +-} +- +diff --git a/drivers/staging/gma500/gem_glue.c b/drivers/staging/gma500/gem_glue.c +deleted file mode 100644 +index daac121..0000000 +--- a/drivers/staging/gma500/gem_glue.c ++++ /dev/null +@@ -1,89 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-#include +-#include +- +-void drm_gem_object_release_wrap(struct drm_gem_object *obj) +-{ +- /* Remove the list map if one is present */ +- if (obj->map_list.map) { +- struct drm_gem_mm *mm = obj->dev->mm_private; +- struct drm_map_list *list = &obj->map_list; +- drm_ht_remove_item(&mm->offset_hash, &list->hash); +- drm_mm_put_block(list->file_offset_node); +- kfree(list->map); +- list->map = NULL; +- } +- drm_gem_object_release(obj); +-} +- +-/** +- * gem_create_mmap_offset - invent an mmap offset +- * @obj: our object +- * +- * Standard implementation of offset generation for mmap as is +- * duplicated in several drivers. This belongs in GEM. +- */ +-int gem_create_mmap_offset(struct drm_gem_object *obj) +-{ +- struct drm_device *dev = obj->dev; +- struct drm_gem_mm *mm = dev->mm_private; +- struct drm_map_list *list; +- struct drm_local_map *map; +- int ret; +- +- list = &obj->map_list; +- list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); +- if (list->map == NULL) +- return -ENOMEM; +- map = list->map; +- map->type = _DRM_GEM; +- map->size = obj->size; +- map->handle = obj; +- +- list->file_offset_node = drm_mm_search_free(&mm->offset_manager, +- obj->size / PAGE_SIZE, 0, 0); +- if (!list->file_offset_node) { +- dev_err(dev->dev, "failed to allocate offset for bo %d\n", +- obj->name); +- ret = -ENOSPC; +- goto free_it; +- } +- list->file_offset_node = drm_mm_get_block(list->file_offset_node, +- obj->size / PAGE_SIZE, 0); +- if (!list->file_offset_node) { +- ret = -ENOMEM; +- goto free_it; +- } +- list->hash.key = list->file_offset_node->start; +- ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); +- if (ret) { +- dev_err(dev->dev, "failed to add to map hash\n"); +- goto free_mm; +- } +- return 0; +- +-free_mm: +- drm_mm_put_block(list->file_offset_node); +-free_it: +- kfree(list->map); +- list->map = NULL; +- return ret; +-} +diff --git a/drivers/staging/gma500/gem_glue.h b/drivers/staging/gma500/gem_glue.h +deleted file mode 100644 +index ce5ce30..0000000 +--- a/drivers/staging/gma500/gem_glue.h ++++ /dev/null +@@ -1,2 +0,0 @@ +-extern void drm_gem_object_release_wrap(struct drm_gem_object *obj); +-extern int gem_create_mmap_offset(struct drm_gem_object *obj); +diff --git a/drivers/staging/gma500/gtt.c b/drivers/staging/gma500/gtt.c +deleted file mode 100644 +index e770bd1..0000000 +--- a/drivers/staging/gma500/gtt.c ++++ /dev/null +@@ -1,553 +0,0 @@ +-/* +- * Copyright (c) 2007, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: Thomas Hellstrom +- * Alan Cox +- */ +- +-#include +-#include "psb_drv.h" +- +- +-/* +- * GTT resource allocator - manage page mappings in GTT space +- */ +- +-/** +- * psb_gtt_mask_pte - generate GTT pte entry +- * @pfn: page number to encode +- * @type: type of memory in the GTT +- * +- * Set the GTT entry for the appropriate memory type. +- */ +-static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type) +-{ +- uint32_t mask = PSB_PTE_VALID; +- +- if (type & PSB_MMU_CACHED_MEMORY) +- mask |= PSB_PTE_CACHED; +- if (type & PSB_MMU_RO_MEMORY) +- mask |= PSB_PTE_RO; +- if (type & PSB_MMU_WO_MEMORY) +- mask |= PSB_PTE_WO; +- +- return (pfn << PAGE_SHIFT) | mask; +-} +- +-/** +- * psb_gtt_entry - find the GTT entries for a gtt_range +- * @dev: our DRM device +- * @r: our GTT range +- * +- * Given a gtt_range object return the GTT offset of the page table +- * entries for this gtt_range +- */ +-u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- unsigned long offset; +- +- offset = r->resource.start - dev_priv->gtt_mem->start; +- +- return dev_priv->gtt_map + (offset >> PAGE_SHIFT); +-} +- +-/** +- * psb_gtt_insert - put an object into the GTT +- * @dev: our DRM device +- * @r: our GTT range +- * +- * Take our preallocated GTT range and insert the GEM object into +- * the GTT. This is protected via the gtt mutex which the caller +- * must hold. +- */ +-static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r) +-{ +- u32 *gtt_slot, pte; +- struct page **pages; +- int i; +- +- if (r->pages == NULL) { +- WARN_ON(1); +- return -EINVAL; +- } +- +- WARN_ON(r->stolen); /* refcount these maybe ? */ +- +- gtt_slot = psb_gtt_entry(dev, r); +- pages = r->pages; +- +- /* Make sure changes are visible to the GPU */ +- set_pages_array_uc(pages, r->npage); +- +- /* Write our page entries into the GTT itself */ +- for (i = r->roll; i < r->npage; i++) { +- pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); +- iowrite32(pte, gtt_slot++); +- } +- for (i = 0; i < r->roll; i++) { +- pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); +- iowrite32(pte, gtt_slot++); +- } +- /* Make sure all the entries are set before we return */ +- ioread32(gtt_slot - 1); +- +- return 0; +-} +- +-/** +- * psb_gtt_remove - remove an object from the GTT +- * @dev: our DRM device +- * @r: our GTT range +- * +- * Remove a preallocated GTT range from the GTT. Overwrite all the +- * page table entries with the dummy page. This is protected via the gtt +- * mutex which the caller must hold. +- */ +-static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 *gtt_slot, pte; +- int i; +- +- WARN_ON(r->stolen); +- +- gtt_slot = psb_gtt_entry(dev, r); +- pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0); +- +- for (i = 0; i < r->npage; i++) +- iowrite32(pte, gtt_slot++); +- ioread32(gtt_slot - 1); +- set_pages_array_wb(r->pages, r->npage); +-} +- +-/** +- * psb_gtt_roll - set scrolling position +- * @dev: our DRM device +- * @r: the gtt mapping we are using +- * @roll: roll offset +- * +- * Roll an existing pinned mapping by moving the pages through the GTT. +- * This allows us to implement hardware scrolling on the consoles without +- * a 2D engine +- */ +-void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll) +-{ +- u32 *gtt_slot, pte; +- int i; +- +- if (roll >= r->npage) { +- WARN_ON(1); +- return; +- } +- +- r->roll = roll; +- +- /* Not currently in the GTT - no worry we will write the mapping at +- the right position when it gets pinned */ +- if (!r->stolen && !r->in_gart) +- return; +- +- gtt_slot = psb_gtt_entry(dev, r); +- +- for (i = r->roll; i < r->npage; i++) { +- pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); +- iowrite32(pte, gtt_slot++); +- } +- for (i = 0; i < r->roll; i++) { +- pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); +- iowrite32(pte, gtt_slot++); +- } +- ioread32(gtt_slot - 1); +-} +- +-/** +- * psb_gtt_attach_pages - attach and pin GEM pages +- * @gt: the gtt range +- * +- * Pin and build an in kernel list of the pages that back our GEM object. +- * While we hold this the pages cannot be swapped out. This is protected +- * via the gtt mutex which the caller must hold. +- */ +-static int psb_gtt_attach_pages(struct gtt_range *gt) +-{ +- struct inode *inode; +- struct address_space *mapping; +- int i; +- struct page *p; +- int pages = gt->gem.size / PAGE_SIZE; +- +- WARN_ON(gt->pages); +- +- /* This is the shared memory object that backs the GEM resource */ +- inode = gt->gem.filp->f_path.dentry->d_inode; +- mapping = inode->i_mapping; +- +- gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL); +- if (gt->pages == NULL) +- return -ENOMEM; +- gt->npage = pages; +- +- for (i = 0; i < pages; i++) { +- /* FIXME: needs updating as per mail from Hugh Dickins */ +- p = read_cache_page_gfp(mapping, i, +- __GFP_COLD | GFP_KERNEL); +- if (IS_ERR(p)) +- goto err; +- gt->pages[i] = p; +- } +- return 0; +- +-err: +- while (i--) +- page_cache_release(gt->pages[i]); +- kfree(gt->pages); +- gt->pages = NULL; +- return PTR_ERR(p); +-} +- +-/** +- * psb_gtt_detach_pages - attach and pin GEM pages +- * @gt: the gtt range +- * +- * Undo the effect of psb_gtt_attach_pages. At this point the pages +- * must have been removed from the GTT as they could now be paged out +- * and move bus address. This is protected via the gtt mutex which the +- * caller must hold. +- */ +-static void psb_gtt_detach_pages(struct gtt_range *gt) +-{ +- int i; +- for (i = 0; i < gt->npage; i++) { +- /* FIXME: do we need to force dirty */ +- set_page_dirty(gt->pages[i]); +- page_cache_release(gt->pages[i]); +- } +- kfree(gt->pages); +- gt->pages = NULL; +-} +- +-/** +- * psb_gtt_pin - pin pages into the GTT +- * @gt: range to pin +- * +- * Pin a set of pages into the GTT. The pins are refcounted so that +- * multiple pins need multiple unpins to undo. +- * +- * Non GEM backed objects treat this as a no-op as they are always GTT +- * backed objects. +- */ +-int psb_gtt_pin(struct gtt_range *gt) +-{ +- int ret = 0; +- struct drm_device *dev = gt->gem.dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- mutex_lock(&dev_priv->gtt_mutex); +- +- if (gt->in_gart == 0 && gt->stolen == 0) { +- ret = psb_gtt_attach_pages(gt); +- if (ret < 0) +- goto out; +- ret = psb_gtt_insert(dev, gt); +- if (ret < 0) { +- psb_gtt_detach_pages(gt); +- goto out; +- } +- } +- gt->in_gart++; +-out: +- mutex_unlock(&dev_priv->gtt_mutex); +- return ret; +-} +- +-/** +- * psb_gtt_unpin - Drop a GTT pin requirement +- * @gt: range to pin +- * +- * Undoes the effect of psb_gtt_pin. On the last drop the GEM object +- * will be removed from the GTT which will also drop the page references +- * and allow the VM to clean up or page stuff. +- * +- * Non GEM backed objects treat this as a no-op as they are always GTT +- * backed objects. +- */ +-void psb_gtt_unpin(struct gtt_range *gt) +-{ +- struct drm_device *dev = gt->gem.dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- mutex_lock(&dev_priv->gtt_mutex); +- +- WARN_ON(!gt->in_gart); +- +- gt->in_gart--; +- if (gt->in_gart == 0 && gt->stolen == 0) { +- psb_gtt_remove(dev, gt); +- psb_gtt_detach_pages(gt); +- } +- mutex_unlock(&dev_priv->gtt_mutex); +-} +- +-/* +- * GTT resource allocator - allocate and manage GTT address space +- */ +- +-/** +- * psb_gtt_alloc_range - allocate GTT address space +- * @dev: Our DRM device +- * @len: length (bytes) of address space required +- * @name: resource name +- * @backed: resource should be backed by stolen pages +- * +- * Ask the kernel core to find us a suitable range of addresses +- * to use for a GTT mapping. +- * +- * Returns a gtt_range structure describing the object, or NULL on +- * error. On successful return the resource is both allocated and marked +- * as in use. +- */ +-struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, +- const char *name, int backed) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct gtt_range *gt; +- struct resource *r = dev_priv->gtt_mem; +- int ret; +- unsigned long start, end; +- +- if (backed) { +- /* The start of the GTT is the stolen pages */ +- start = r->start; +- end = r->start + dev_priv->gtt.stolen_size - 1; +- } else { +- /* The rest we will use for GEM backed objects */ +- start = r->start + dev_priv->gtt.stolen_size; +- end = r->end; +- } +- +- gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL); +- if (gt == NULL) +- return NULL; +- gt->resource.name = name; +- gt->stolen = backed; +- gt->in_gart = backed; +- gt->roll = 0; +- /* Ensure this is set for non GEM objects */ +- gt->gem.dev = dev; +- ret = allocate_resource(dev_priv->gtt_mem, >->resource, +- len, start, end, PAGE_SIZE, NULL, NULL); +- if (ret == 0) { +- gt->offset = gt->resource.start - r->start; +- return gt; +- } +- kfree(gt); +- return NULL; +-} +- +-/** +- * psb_gtt_free_range - release GTT address space +- * @dev: our DRM device +- * @gt: a mapping created with psb_gtt_alloc_range +- * +- * Release a resource that was allocated with psb_gtt_alloc_range. If the +- * object has been pinned by mmap users we clean this up here currently. +- */ +-void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt) +-{ +- /* Undo the mmap pin if we are destroying the object */ +- if (gt->mmapping) { +- psb_gtt_unpin(gt); +- gt->mmapping = 0; +- } +- WARN_ON(gt->in_gart && !gt->stolen); +- release_resource(>->resource); +- kfree(gt); +-} +- +-void psb_gtt_alloc(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- init_rwsem(&dev_priv->gtt.sem); +-} +- +-void psb_gtt_takedown(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (dev_priv->gtt_map) { +- iounmap(dev_priv->gtt_map); +- dev_priv->gtt_map = NULL; +- } +- if (dev_priv->gtt_initialized) { +- pci_write_config_word(dev->pdev, PSB_GMCH_CTRL, +- dev_priv->gmch_ctrl); +- PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); +- (void) PSB_RVDC32(PSB_PGETBL_CTL); +- } +- if (dev_priv->vram_addr) +- iounmap(dev_priv->gtt_map); +-} +- +-int psb_gtt_init(struct drm_device *dev, int resume) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- unsigned gtt_pages; +- unsigned long stolen_size, vram_stolen_size; +- unsigned i, num_pages; +- unsigned pfn_base; +- uint32_t vram_pages; +- uint32_t dvmt_mode = 0; +- struct psb_gtt *pg; +- +- int ret = 0; +- uint32_t pte; +- +- mutex_init(&dev_priv->gtt_mutex); +- +- psb_gtt_alloc(dev); +- pg = &dev_priv->gtt; +- +- /* Enable the GTT */ +- pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl); +- pci_write_config_word(dev->pdev, PSB_GMCH_CTRL, +- dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); +- +- dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL); +- PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); +- (void) PSB_RVDC32(PSB_PGETBL_CTL); +- +- /* The root resource we allocate address space from */ +- dev_priv->gtt_initialized = 1; +- +- pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; +- +- /* +- * The video mmu has a hw bug when accessing 0x0D0000000. +- * Make gatt start at 0x0e000,0000. This doesn't actually +- * matter for us but may do if the video acceleration ever +- * gets opened up. +- */ +- pg->mmu_gatt_start = 0xE0000000; +- +- pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE); +- gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) +- >> PAGE_SHIFT; +- /* Some CDV firmware doesn't report this currently. In which case the +- system has 64 gtt pages */ +- if (pg->gtt_start == 0 || gtt_pages == 0) { +- dev_err(dev->dev, "GTT PCI BAR not initialized.\n"); +- gtt_pages = 64; +- pg->gtt_start = dev_priv->pge_ctl; +- } +- +- pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE); +- pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE) +- >> PAGE_SHIFT; +- dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE]; +- +- if (pg->gatt_pages == 0 || pg->gatt_start == 0) { +- static struct resource fudge; /* Preferably peppermint */ +- /* This can occur on CDV SDV systems. Fudge it in this case. +- We really don't care what imaginary space is being allocated +- at this point */ +- dev_err(dev->dev, "GATT PCI BAR not initialized.\n"); +- pg->gatt_start = 0x40000000; +- pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT; +- /* This is a little confusing but in fact the GTT is providing +- a view from the GPU into memory and not vice versa. As such +- this is really allocating space that is not the same as the +- CPU address space on CDV */ +- fudge.start = 0x40000000; +- fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1; +- fudge.name = "fudge"; +- fudge.flags = IORESOURCE_MEM; +- dev_priv->gtt_mem = &fudge; +- } +- +- pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base); +- vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base +- - PAGE_SIZE; +- +- stolen_size = vram_stolen_size; +- +- printk(KERN_INFO "Stolen memory information\n"); +- printk(KERN_INFO " base in RAM: 0x%x\n", dev_priv->stolen_base); +- printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n", +- vram_stolen_size/1024); +- dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7; +- printk(KERN_INFO " the correct size should be: %dM(dvmt mode=%d)\n", +- (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode); +- +- if (resume && (gtt_pages != pg->gtt_pages) && +- (stolen_size != pg->stolen_size)) { +- dev_err(dev->dev, "GTT resume error.\n"); +- ret = -EINVAL; +- goto out_err; +- } +- +- pg->gtt_pages = gtt_pages; +- pg->stolen_size = stolen_size; +- dev_priv->vram_stolen_size = vram_stolen_size; +- +- /* +- * Map the GTT and the stolen memory area +- */ +- dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start, +- gtt_pages << PAGE_SHIFT); +- if (!dev_priv->gtt_map) { +- dev_err(dev->dev, "Failure to map gtt.\n"); +- ret = -ENOMEM; +- goto out_err; +- } +- +- dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size); +- if (!dev_priv->vram_addr) { +- dev_err(dev->dev, "Failure to map stolen base.\n"); +- ret = -ENOMEM; +- goto out_err; +- } +- +- /* +- * Insert vram stolen pages into the GTT +- */ +- +- pfn_base = dev_priv->stolen_base >> PAGE_SHIFT; +- vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT; +- printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n", +- num_pages, pfn_base << PAGE_SHIFT, 0); +- for (i = 0; i < num_pages; ++i) { +- pte = psb_gtt_mask_pte(pfn_base + i, 0); +- iowrite32(pte, dev_priv->gtt_map + i); +- } +- +- /* +- * Init rest of GTT to the scratch page to avoid accidents or scribbles +- */ +- +- pfn_base = page_to_pfn(dev_priv->scratch_page); +- pte = psb_gtt_mask_pte(pfn_base, 0); +- for (; i < gtt_pages; ++i) +- iowrite32(pte, dev_priv->gtt_map + i); +- +- (void) ioread32(dev_priv->gtt_map + i - 1); +- return 0; +- +-out_err: +- psb_gtt_takedown(dev); +- return ret; +-} +diff --git a/drivers/staging/gma500/gtt.h b/drivers/staging/gma500/gtt.h +deleted file mode 100644 +index aa17423..0000000 +--- a/drivers/staging/gma500/gtt.h ++++ /dev/null +@@ -1,64 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2007-2008, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-#ifndef _PSB_GTT_H_ +-#define _PSB_GTT_H_ +- +-#include +- +-/* This wants cleaning up with respect to the psb_dev and un-needed stuff */ +-struct psb_gtt { +- uint32_t gatt_start; +- uint32_t mmu_gatt_start; +- uint32_t gtt_start; +- uint32_t gtt_phys_start; +- unsigned gtt_pages; +- unsigned gatt_pages; +- unsigned long stolen_size; +- unsigned long vram_stolen_size; +- struct rw_semaphore sem; +-}; +- +-/* Exported functions */ +-extern int psb_gtt_init(struct drm_device *dev, int resume); +-extern void psb_gtt_takedown(struct drm_device *dev); +- +-/* Each gtt_range describes an allocation in the GTT area */ +-struct gtt_range { +- struct resource resource; /* Resource for our allocation */ +- u32 offset; /* GTT offset of our object */ +- struct drm_gem_object gem; /* GEM high level stuff */ +- int in_gart; /* Currently in the GART (ref ct) */ +- bool stolen; /* Backed from stolen RAM */ +- bool mmapping; /* Is mmappable */ +- struct page **pages; /* Backing pages if present */ +- int npage; /* Number of backing pages */ +- int roll; /* Roll applied to the GTT entries */ +-}; +- +-extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, +- const char *name, int backed); +-extern void psb_gtt_kref_put(struct gtt_range *gt); +-extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt); +-extern int psb_gtt_pin(struct gtt_range *gt); +-extern void psb_gtt_unpin(struct gtt_range *gt); +-extern void psb_gtt_roll(struct drm_device *dev, +- struct gtt_range *gt, int roll); +- +-#endif +diff --git a/drivers/staging/gma500/intel_bios.c b/drivers/staging/gma500/intel_bios.c +deleted file mode 100644 +index 096757f..0000000 +--- a/drivers/staging/gma500/intel_bios.c ++++ /dev/null +@@ -1,303 +0,0 @@ +-/* +- * Copyright (c) 2006 Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Eric Anholt +- * +- */ +-#include +-#include +-#include "psb_drm.h" +-#include "psb_drv.h" +-#include "psb_intel_drv.h" +-#include "psb_intel_reg.h" +-#include "intel_bios.h" +- +- +-static void *find_section(struct bdb_header *bdb, int section_id) +-{ +- u8 *base = (u8 *)bdb; +- int index = 0; +- u16 total, current_size; +- u8 current_id; +- +- /* skip to first section */ +- index += bdb->header_size; +- total = bdb->bdb_size; +- +- /* walk the sections looking for section_id */ +- while (index < total) { +- current_id = *(base + index); +- index++; +- current_size = *((u16 *)(base + index)); +- index += 2; +- if (current_id == section_id) +- return base + index; +- index += current_size; +- } +- +- return NULL; +-} +- +-static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, +- struct lvds_dvo_timing *dvo_timing) +-{ +- panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | +- dvo_timing->hactive_lo; +- panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + +- ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); +- panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + +- dvo_timing->hsync_pulse_width; +- panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + +- ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); +- +- panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | +- dvo_timing->vactive_lo; +- panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + +- dvo_timing->vsync_off; +- panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + +- dvo_timing->vsync_pulse_width; +- panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + +- ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); +- panel_fixed_mode->clock = dvo_timing->clock * 10; +- panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; +- +- /* Some VBTs have bogus h/vtotal values */ +- if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) +- panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; +- if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) +- panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; +- +- drm_mode_set_name(panel_fixed_mode); +-} +- +-static void parse_backlight_data(struct drm_psb_private *dev_priv, +- struct bdb_header *bdb) +-{ +- struct bdb_lvds_backlight *vbt_lvds_bl = NULL; +- struct bdb_lvds_backlight *lvds_bl; +- u8 p_type = 0; +- void *bl_start = NULL; +- struct bdb_lvds_options *lvds_opts +- = find_section(bdb, BDB_LVDS_OPTIONS); +- +- dev_priv->lvds_bl = NULL; +- +- if (lvds_opts) +- p_type = lvds_opts->panel_type; +- else +- return; +- +- bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT); +- vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type; +- +- lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL); +- if (!lvds_bl) { +- dev_err(dev_priv->dev->dev, "out of memory for backlight data\n"); +- return; +- } +- memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl)); +- dev_priv->lvds_bl = lvds_bl; +-} +- +-/* Try to find integrated panel data */ +-static void parse_lfp_panel_data(struct drm_psb_private *dev_priv, +- struct bdb_header *bdb) +-{ +- struct bdb_lvds_options *lvds_options; +- struct bdb_lvds_lfp_data *lvds_lfp_data; +- struct bdb_lvds_lfp_data_entry *entry; +- struct lvds_dvo_timing *dvo_timing; +- struct drm_display_mode *panel_fixed_mode; +- +- /* Defaults if we can't find VBT info */ +- dev_priv->lvds_dither = 0; +- dev_priv->lvds_vbt = 0; +- +- lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); +- if (!lvds_options) +- return; +- +- dev_priv->lvds_dither = lvds_options->pixel_dither; +- if (lvds_options->panel_type == 0xff) +- return; +- +- lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); +- if (!lvds_lfp_data) +- return; +- +- +- entry = &lvds_lfp_data->data[lvds_options->panel_type]; +- dvo_timing = &entry->dvo_timing; +- +- panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), +- GFP_KERNEL); +- if (panel_fixed_mode == NULL) { +- dev_err(dev_priv->dev->dev, "out of memory for fixed panel mode\n"); +- return; +- } +- +- dev_priv->lvds_vbt = 1; +- fill_detail_timing_data(panel_fixed_mode, dvo_timing); +- +- if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) { +- dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; +- drm_mode_debug_printmodeline(panel_fixed_mode); +- } else { +- dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n"); +- dev_priv->lvds_vbt = 0; +- kfree(panel_fixed_mode); +- } +- return; +-} +- +-/* Try to find sdvo panel data */ +-static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv, +- struct bdb_header *bdb) +-{ +- struct bdb_sdvo_lvds_options *sdvo_lvds_options; +- struct lvds_dvo_timing *dvo_timing; +- struct drm_display_mode *panel_fixed_mode; +- +- dev_priv->sdvo_lvds_vbt_mode = NULL; +- +- sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); +- if (!sdvo_lvds_options) +- return; +- +- dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); +- if (!dvo_timing) +- return; +- +- panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); +- +- if (!panel_fixed_mode) +- return; +- +- fill_detail_timing_data(panel_fixed_mode, +- dvo_timing + sdvo_lvds_options->panel_type); +- +- dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; +- +- return; +-} +- +-static void parse_general_features(struct drm_psb_private *dev_priv, +- struct bdb_header *bdb) +-{ +- struct bdb_general_features *general; +- +- /* Set sensible defaults in case we can't find the general block */ +- dev_priv->int_tv_support = 1; +- dev_priv->int_crt_support = 1; +- +- general = find_section(bdb, BDB_GENERAL_FEATURES); +- if (general) { +- dev_priv->int_tv_support = general->int_tv_support; +- dev_priv->int_crt_support = general->int_crt_support; +- dev_priv->lvds_use_ssc = general->enable_ssc; +- +- if (dev_priv->lvds_use_ssc) { +- dev_priv->lvds_ssc_freq +- = general->ssc_freq ? 100 : 96; +- } +- } +-} +- +-/** +- * psb_intel_init_bios - initialize VBIOS settings & find VBT +- * @dev: DRM device +- * +- * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers +- * to appropriate values. +- * +- * VBT existence is a sanity check that is relied on by other i830_bios.c code. +- * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may +- * feed an updated VBT back through that, compared to what we'll fetch using +- * this method of groping around in the BIOS data. +- * +- * Returns 0 on success, nonzero on failure. +- */ +-bool psb_intel_init_bios(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct pci_dev *pdev = dev->pdev; +- struct vbt_header *vbt = NULL; +- struct bdb_header *bdb; +- u8 __iomem *bios; +- size_t size; +- int i; +- +- bios = pci_map_rom(pdev, &size); +- if (!bios) +- return -1; +- +- /* Scour memory looking for the VBT signature */ +- for (i = 0; i + 4 < size; i++) { +- if (!memcmp(bios + i, "$VBT", 4)) { +- vbt = (struct vbt_header *)(bios + i); +- break; +- } +- } +- +- if (!vbt) { +- dev_err(dev->dev, "VBT signature missing\n"); +- pci_unmap_rom(pdev, bios); +- return -1; +- } +- +- bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); +- +- /* Grab useful general definitions */ +- parse_general_features(dev_priv, bdb); +- parse_lfp_panel_data(dev_priv, bdb); +- parse_sdvo_panel_data(dev_priv, bdb); +- parse_backlight_data(dev_priv, bdb); +- +- pci_unmap_rom(pdev, bios); +- +- return 0; +-} +- +-/** +- * Destroy and free VBT data +- */ +-void psb_intel_destroy_bios(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct drm_display_mode *sdvo_lvds_vbt_mode = +- dev_priv->sdvo_lvds_vbt_mode; +- struct drm_display_mode *lfp_lvds_vbt_mode = +- dev_priv->lfp_lvds_vbt_mode; +- struct bdb_lvds_backlight *lvds_bl = +- dev_priv->lvds_bl; +- +- /*free sdvo panel mode*/ +- if (sdvo_lvds_vbt_mode) { +- dev_priv->sdvo_lvds_vbt_mode = NULL; +- kfree(sdvo_lvds_vbt_mode); +- } +- +- if (lfp_lvds_vbt_mode) { +- dev_priv->lfp_lvds_vbt_mode = NULL; +- kfree(lfp_lvds_vbt_mode); +- } +- +- if (lvds_bl) { +- dev_priv->lvds_bl = NULL; +- kfree(lvds_bl); +- } +-} +diff --git a/drivers/staging/gma500/intel_bios.h b/drivers/staging/gma500/intel_bios.h +deleted file mode 100644 +index 70f1bf0..0000000 +--- a/drivers/staging/gma500/intel_bios.h ++++ /dev/null +@@ -1,430 +0,0 @@ +-/* +- * Copyright (c) 2006 Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Eric Anholt +- * +- */ +- +-#ifndef _I830_BIOS_H_ +-#define _I830_BIOS_H_ +- +-#include +- +-struct vbt_header { +- u8 signature[20]; /**< Always starts with 'VBT$' */ +- u16 version; /**< decimal */ +- u16 header_size; /**< in bytes */ +- u16 vbt_size; /**< in bytes */ +- u8 vbt_checksum; +- u8 reserved0; +- u32 bdb_offset; /**< from beginning of VBT */ +- u32 aim_offset[4]; /**< from beginning of VBT */ +-} __attribute__((packed)); +- +- +-struct bdb_header { +- u8 signature[16]; /**< Always 'BIOS_DATA_BLOCK' */ +- u16 version; /**< decimal */ +- u16 header_size; /**< in bytes */ +- u16 bdb_size; /**< in bytes */ +-}; +- +-/* strictly speaking, this is a "skip" block, but it has interesting info */ +-struct vbios_data { +- u8 type; /* 0 == desktop, 1 == mobile */ +- u8 relstage; +- u8 chipset; +- u8 lvds_present:1; +- u8 tv_present:1; +- u8 rsvd2:6; /* finish byte */ +- u8 rsvd3[4]; +- u8 signon[155]; +- u8 copyright[61]; +- u16 code_segment; +- u8 dos_boot_mode; +- u8 bandwidth_percent; +- u8 rsvd4; /* popup memory size */ +- u8 resize_pci_bios; +- u8 rsvd5; /* is crt already on ddc2 */ +-} __attribute__((packed)); +- +-/* +- * There are several types of BIOS data blocks (BDBs), each block has +- * an ID and size in the first 3 bytes (ID in first, size in next 2). +- * Known types are listed below. +- */ +-#define BDB_GENERAL_FEATURES 1 +-#define BDB_GENERAL_DEFINITIONS 2 +-#define BDB_OLD_TOGGLE_LIST 3 +-#define BDB_MODE_SUPPORT_LIST 4 +-#define BDB_GENERIC_MODE_TABLE 5 +-#define BDB_EXT_MMIO_REGS 6 +-#define BDB_SWF_IO 7 +-#define BDB_SWF_MMIO 8 +-#define BDB_DOT_CLOCK_TABLE 9 +-#define BDB_MODE_REMOVAL_TABLE 10 +-#define BDB_CHILD_DEVICE_TABLE 11 +-#define BDB_DRIVER_FEATURES 12 +-#define BDB_DRIVER_PERSISTENCE 13 +-#define BDB_EXT_TABLE_PTRS 14 +-#define BDB_DOT_CLOCK_OVERRIDE 15 +-#define BDB_DISPLAY_SELECT 16 +-/* 17 rsvd */ +-#define BDB_DRIVER_ROTATION 18 +-#define BDB_DISPLAY_REMOVE 19 +-#define BDB_OEM_CUSTOM 20 +-#define BDB_EFP_LIST 21 /* workarounds for VGA hsync/vsync */ +-#define BDB_SDVO_LVDS_OPTIONS 22 +-#define BDB_SDVO_PANEL_DTDS 23 +-#define BDB_SDVO_LVDS_PNP_IDS 24 +-#define BDB_SDVO_LVDS_POWER_SEQ 25 +-#define BDB_TV_OPTIONS 26 +-#define BDB_LVDS_OPTIONS 40 +-#define BDB_LVDS_LFP_DATA_PTRS 41 +-#define BDB_LVDS_LFP_DATA 42 +-#define BDB_LVDS_BACKLIGHT 43 +-#define BDB_LVDS_POWER 44 +-#define BDB_SKIP 254 /* VBIOS private block, ignore */ +- +-struct bdb_general_features { +- /* bits 1 */ +- u8 panel_fitting:2; +- u8 flexaim:1; +- u8 msg_enable:1; +- u8 clear_screen:3; +- u8 color_flip:1; +- +- /* bits 2 */ +- u8 download_ext_vbt:1; +- u8 enable_ssc:1; +- u8 ssc_freq:1; +- u8 enable_lfp_on_override:1; +- u8 disable_ssc_ddt:1; +- u8 rsvd8:3; /* finish byte */ +- +- /* bits 3 */ +- u8 disable_smooth_vision:1; +- u8 single_dvi:1; +- u8 rsvd9:6; /* finish byte */ +- +- /* bits 4 */ +- u8 legacy_monitor_detect; +- +- /* bits 5 */ +- u8 int_crt_support:1; +- u8 int_tv_support:1; +- u8 rsvd11:6; /* finish byte */ +-} __attribute__((packed)); +- +-struct bdb_general_definitions { +- /* DDC GPIO */ +- u8 crt_ddc_gmbus_pin; +- +- /* DPMS bits */ +- u8 dpms_acpi:1; +- u8 skip_boot_crt_detect:1; +- u8 dpms_aim:1; +- u8 rsvd1:5; /* finish byte */ +- +- /* boot device bits */ +- u8 boot_display[2]; +- u8 child_dev_size; +- +- /* device info */ +- u8 tv_or_lvds_info[33]; +- u8 dev1[33]; +- u8 dev2[33]; +- u8 dev3[33]; +- u8 dev4[33]; +- /* may be another device block here on some platforms */ +-}; +- +-struct bdb_lvds_options { +- u8 panel_type; +- u8 rsvd1; +- /* LVDS capabilities, stored in a dword */ +- u8 pfit_mode:2; +- u8 pfit_text_mode_enhanced:1; +- u8 pfit_gfx_mode_enhanced:1; +- u8 pfit_ratio_auto:1; +- u8 pixel_dither:1; +- u8 lvds_edid:1; +- u8 rsvd2:1; +- u8 rsvd4; +-} __attribute__((packed)); +- +-struct bdb_lvds_backlight { +- u8 type:2; +- u8 pol:1; +- u8 gpio:3; +- u8 gmbus:2; +- u16 freq; +- u8 minbrightness; +- u8 i2caddr; +- u8 brightnesscmd; +- /*FIXME: more...*/ +-} __attribute__((packed)); +- +-/* LFP pointer table contains entries to the struct below */ +-struct bdb_lvds_lfp_data_ptr { +- u16 fp_timing_offset; /* offsets are from start of bdb */ +- u8 fp_table_size; +- u16 dvo_timing_offset; +- u8 dvo_table_size; +- u16 panel_pnp_id_offset; +- u8 pnp_table_size; +-} __attribute__((packed)); +- +-struct bdb_lvds_lfp_data_ptrs { +- u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */ +- struct bdb_lvds_lfp_data_ptr ptr[16]; +-} __attribute__((packed)); +- +-/* LFP data has 3 blocks per entry */ +-struct lvds_fp_timing { +- u16 x_res; +- u16 y_res; +- u32 lvds_reg; +- u32 lvds_reg_val; +- u32 pp_on_reg; +- u32 pp_on_reg_val; +- u32 pp_off_reg; +- u32 pp_off_reg_val; +- u32 pp_cycle_reg; +- u32 pp_cycle_reg_val; +- u32 pfit_reg; +- u32 pfit_reg_val; +- u16 terminator; +-} __attribute__((packed)); +- +-struct lvds_dvo_timing { +- u16 clock; /**< In 10khz */ +- u8 hactive_lo; +- u8 hblank_lo; +- u8 hblank_hi:4; +- u8 hactive_hi:4; +- u8 vactive_lo; +- u8 vblank_lo; +- u8 vblank_hi:4; +- u8 vactive_hi:4; +- u8 hsync_off_lo; +- u8 hsync_pulse_width; +- u8 vsync_pulse_width:4; +- u8 vsync_off:4; +- u8 rsvd0:6; +- u8 hsync_off_hi:2; +- u8 h_image; +- u8 v_image; +- u8 max_hv; +- u8 h_border; +- u8 v_border; +- u8 rsvd1:3; +- u8 digital:2; +- u8 vsync_positive:1; +- u8 hsync_positive:1; +- u8 rsvd2:1; +-} __attribute__((packed)); +- +-struct lvds_pnp_id { +- u16 mfg_name; +- u16 product_code; +- u32 serial; +- u8 mfg_week; +- u8 mfg_year; +-} __attribute__((packed)); +- +-struct bdb_lvds_lfp_data_entry { +- struct lvds_fp_timing fp_timing; +- struct lvds_dvo_timing dvo_timing; +- struct lvds_pnp_id pnp_id; +-} __attribute__((packed)); +- +-struct bdb_lvds_lfp_data { +- struct bdb_lvds_lfp_data_entry data[16]; +-} __attribute__((packed)); +- +-struct aimdb_header { +- char signature[16]; +- char oem_device[20]; +- u16 aimdb_version; +- u16 aimdb_header_size; +- u16 aimdb_size; +-} __attribute__((packed)); +- +-struct aimdb_block { +- u8 aimdb_id; +- u16 aimdb_size; +-} __attribute__((packed)); +- +-struct vch_panel_data { +- u16 fp_timing_offset; +- u8 fp_timing_size; +- u16 dvo_timing_offset; +- u8 dvo_timing_size; +- u16 text_fitting_offset; +- u8 text_fitting_size; +- u16 graphics_fitting_offset; +- u8 graphics_fitting_size; +-} __attribute__((packed)); +- +-struct vch_bdb_22 { +- struct aimdb_block aimdb_block; +- struct vch_panel_data panels[16]; +-} __attribute__((packed)); +- +-struct bdb_sdvo_lvds_options { +- u8 panel_backlight; +- u8 h40_set_panel_type; +- u8 panel_type; +- u8 ssc_clk_freq; +- u16 als_low_trip; +- u16 als_high_trip; +- u8 sclalarcoeff_tab_row_num; +- u8 sclalarcoeff_tab_row_size; +- u8 coefficient[8]; +- u8 panel_misc_bits_1; +- u8 panel_misc_bits_2; +- u8 panel_misc_bits_3; +- u8 panel_misc_bits_4; +-} __attribute__((packed)); +- +- +-extern bool psb_intel_init_bios(struct drm_device *dev); +-extern void psb_intel_destroy_bios(struct drm_device *dev); +- +-/* +- * Driver<->VBIOS interaction occurs through scratch bits in +- * GR18 & SWF*. +- */ +- +-/* GR18 bits are set on display switch and hotkey events */ +-#define GR18_DRIVER_SWITCH_EN (1<<7) /* 0: VBIOS control, 1: driver control */ +-#define GR18_HOTKEY_MASK 0x78 /* See also SWF4 15:0 */ +-#define GR18_HK_NONE (0x0<<3) +-#define GR18_HK_LFP_STRETCH (0x1<<3) +-#define GR18_HK_TOGGLE_DISP (0x2<<3) +-#define GR18_HK_DISP_SWITCH (0x4<<3) /* see SWF14 15:0 for what to enable */ +-#define GR18_HK_POPUP_DISABLED (0x6<<3) +-#define GR18_HK_POPUP_ENABLED (0x7<<3) +-#define GR18_HK_PFIT (0x8<<3) +-#define GR18_HK_APM_CHANGE (0xa<<3) +-#define GR18_HK_MULTIPLE (0xc<<3) +-#define GR18_USER_INT_EN (1<<2) +-#define GR18_A0000_FLUSH_EN (1<<1) +-#define GR18_SMM_EN (1<<0) +- +-/* Set by driver, cleared by VBIOS */ +-#define SWF00_YRES_SHIFT 16 +-#define SWF00_XRES_SHIFT 0 +-#define SWF00_RES_MASK 0xffff +- +-/* Set by VBIOS at boot time and driver at runtime */ +-#define SWF01_TV2_FORMAT_SHIFT 8 +-#define SWF01_TV1_FORMAT_SHIFT 0 +-#define SWF01_TV_FORMAT_MASK 0xffff +- +-#define SWF10_VBIOS_BLC_I2C_EN (1<<29) +-#define SWF10_GTT_OVERRIDE_EN (1<<28) +-#define SWF10_LFP_DPMS_OVR (1<<27) /* override DPMS on display switch */ +-#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24) +-#define SWF10_OLD_TOGGLE 0x0 +-#define SWF10_TOGGLE_LIST_1 0x1 +-#define SWF10_TOGGLE_LIST_2 0x2 +-#define SWF10_TOGGLE_LIST_3 0x3 +-#define SWF10_TOGGLE_LIST_4 0x4 +-#define SWF10_PANNING_EN (1<<23) +-#define SWF10_DRIVER_LOADED (1<<22) +-#define SWF10_EXTENDED_DESKTOP (1<<21) +-#define SWF10_EXCLUSIVE_MODE (1<<20) +-#define SWF10_OVERLAY_EN (1<<19) +-#define SWF10_PLANEB_HOLDOFF (1<<18) +-#define SWF10_PLANEA_HOLDOFF (1<<17) +-#define SWF10_VGA_HOLDOFF (1<<16) +-#define SWF10_ACTIVE_DISP_MASK 0xffff +-#define SWF10_PIPEB_LFP2 (1<<15) +-#define SWF10_PIPEB_EFP2 (1<<14) +-#define SWF10_PIPEB_TV2 (1<<13) +-#define SWF10_PIPEB_CRT2 (1<<12) +-#define SWF10_PIPEB_LFP (1<<11) +-#define SWF10_PIPEB_EFP (1<<10) +-#define SWF10_PIPEB_TV (1<<9) +-#define SWF10_PIPEB_CRT (1<<8) +-#define SWF10_PIPEA_LFP2 (1<<7) +-#define SWF10_PIPEA_EFP2 (1<<6) +-#define SWF10_PIPEA_TV2 (1<<5) +-#define SWF10_PIPEA_CRT2 (1<<4) +-#define SWF10_PIPEA_LFP (1<<3) +-#define SWF10_PIPEA_EFP (1<<2) +-#define SWF10_PIPEA_TV (1<<1) +-#define SWF10_PIPEA_CRT (1<<0) +- +-#define SWF11_MEMORY_SIZE_SHIFT 16 +-#define SWF11_SV_TEST_EN (1<<15) +-#define SWF11_IS_AGP (1<<14) +-#define SWF11_DISPLAY_HOLDOFF (1<<13) +-#define SWF11_DPMS_REDUCED (1<<12) +-#define SWF11_IS_VBE_MODE (1<<11) +-#define SWF11_PIPEB_ACCESS (1<<10) /* 0 here means pipe a */ +-#define SWF11_DPMS_MASK 0x07 +-#define SWF11_DPMS_OFF (1<<2) +-#define SWF11_DPMS_SUSPEND (1<<1) +-#define SWF11_DPMS_STANDBY (1<<0) +-#define SWF11_DPMS_ON 0 +- +-#define SWF14_GFX_PFIT_EN (1<<31) +-#define SWF14_TEXT_PFIT_EN (1<<30) +-#define SWF14_LID_STATUS_CLOSED (1<<29) /* 0 here means open */ +-#define SWF14_POPUP_EN (1<<28) +-#define SWF14_DISPLAY_HOLDOFF (1<<27) +-#define SWF14_DISP_DETECT_EN (1<<26) +-#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */ +-#define SWF14_DRIVER_STATUS (1<<24) +-#define SWF14_OS_TYPE_WIN9X (1<<23) +-#define SWF14_OS_TYPE_WINNT (1<<22) +-/* 21:19 rsvd */ +-#define SWF14_PM_TYPE_MASK 0x00070000 +-#define SWF14_PM_ACPI_VIDEO (0x4 << 16) +-#define SWF14_PM_ACPI (0x3 << 16) +-#define SWF14_PM_APM_12 (0x2 << 16) +-#define SWF14_PM_APM_11 (0x1 << 16) +-#define SWF14_HK_REQUEST_MASK 0x0000ffff /* see GR18 6:3 for event type */ +- /* if GR18 indicates a display switch */ +-#define SWF14_DS_PIPEB_LFP2_EN (1<<15) +-#define SWF14_DS_PIPEB_EFP2_EN (1<<14) +-#define SWF14_DS_PIPEB_TV2_EN (1<<13) +-#define SWF14_DS_PIPEB_CRT2_EN (1<<12) +-#define SWF14_DS_PIPEB_LFP_EN (1<<11) +-#define SWF14_DS_PIPEB_EFP_EN (1<<10) +-#define SWF14_DS_PIPEB_TV_EN (1<<9) +-#define SWF14_DS_PIPEB_CRT_EN (1<<8) +-#define SWF14_DS_PIPEA_LFP2_EN (1<<7) +-#define SWF14_DS_PIPEA_EFP2_EN (1<<6) +-#define SWF14_DS_PIPEA_TV2_EN (1<<5) +-#define SWF14_DS_PIPEA_CRT2_EN (1<<4) +-#define SWF14_DS_PIPEA_LFP_EN (1<<3) +-#define SWF14_DS_PIPEA_EFP_EN (1<<2) +-#define SWF14_DS_PIPEA_TV_EN (1<<1) +-#define SWF14_DS_PIPEA_CRT_EN (1<<0) +- /* if GR18 indicates a panel fitting request */ +-#define SWF14_PFIT_EN (1<<0) /* 0 means disable */ +- /* if GR18 indicates an APM change request */ +-#define SWF14_APM_HIBERNATE 0x4 +-#define SWF14_APM_SUSPEND 0x3 +-#define SWF14_APM_STANDBY 0x1 +-#define SWF14_APM_RESTORE 0x0 +- +-#endif /* _I830_BIOS_H_ */ +diff --git a/drivers/staging/gma500/intel_i2c.c b/drivers/staging/gma500/intel_i2c.c +deleted file mode 100644 +index 51cbf65..0000000 +--- a/drivers/staging/gma500/intel_i2c.c ++++ /dev/null +@@ -1,170 +0,0 @@ +-/* +- * Copyright © 2006-2007 Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Eric Anholt +- */ +- +-#include +-#include +-#include +- +-#include "psb_drv.h" +-#include "psb_intel_reg.h" +- +-/* +- * Intel GPIO access functions +- */ +- +-#define I2C_RISEFALL_TIME 20 +- +-static int get_clock(void *data) +-{ +- struct psb_intel_i2c_chan *chan = data; +- struct drm_device *dev = chan->drm_dev; +- u32 val; +- +- val = REG_READ(chan->reg); +- return (val & GPIO_CLOCK_VAL_IN) != 0; +-} +- +-static int get_data(void *data) +-{ +- struct psb_intel_i2c_chan *chan = data; +- struct drm_device *dev = chan->drm_dev; +- u32 val; +- +- val = REG_READ(chan->reg); +- return (val & GPIO_DATA_VAL_IN) != 0; +-} +- +-static void set_clock(void *data, int state_high) +-{ +- struct psb_intel_i2c_chan *chan = data; +- struct drm_device *dev = chan->drm_dev; +- u32 reserved = 0, clock_bits; +- +- /* On most chips, these bits must be preserved in software. */ +- reserved = +- REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | +- GPIO_CLOCK_PULLUP_DISABLE); +- +- if (state_high) +- clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; +- else +- clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | +- GPIO_CLOCK_VAL_MASK; +- REG_WRITE(chan->reg, reserved | clock_bits); +- udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ +-} +- +-static void set_data(void *data, int state_high) +-{ +- struct psb_intel_i2c_chan *chan = data; +- struct drm_device *dev = chan->drm_dev; +- u32 reserved = 0, data_bits; +- +- /* On most chips, these bits must be preserved in software. */ +- reserved = +- REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | +- GPIO_CLOCK_PULLUP_DISABLE); +- +- if (state_high) +- data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; +- else +- data_bits = +- GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | +- GPIO_DATA_VAL_MASK; +- +- REG_WRITE(chan->reg, reserved | data_bits); +- udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ +-} +- +-/** +- * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg +- * @dev: DRM device +- * @output: driver specific output device +- * @reg: GPIO reg to use +- * @name: name for this bus +- * +- * Creates and registers a new i2c bus with the Linux i2c layer, for use +- * in output probing and control (e.g. DDC or SDVO control functions). +- * +- * Possible values for @reg include: +- * %GPIOA +- * %GPIOB +- * %GPIOC +- * %GPIOD +- * %GPIOE +- * %GPIOF +- * %GPIOG +- * %GPIOH +- * see PRM for details on how these different busses are used. +- */ +-struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev, +- const u32 reg, const char *name) +-{ +- struct psb_intel_i2c_chan *chan; +- +- chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL); +- if (!chan) +- goto out_free; +- +- chan->drm_dev = dev; +- chan->reg = reg; +- snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name); +- chan->adapter.owner = THIS_MODULE; +- chan->adapter.algo_data = &chan->algo; +- chan->adapter.dev.parent = &dev->pdev->dev; +- chan->algo.setsda = set_data; +- chan->algo.setscl = set_clock; +- chan->algo.getsda = get_data; +- chan->algo.getscl = get_clock; +- chan->algo.udelay = 20; +- chan->algo.timeout = usecs_to_jiffies(2200); +- chan->algo.data = chan; +- +- i2c_set_adapdata(&chan->adapter, chan); +- +- if (i2c_bit_add_bus(&chan->adapter)) +- goto out_free; +- +- /* JJJ: raise SCL and SDA? */ +- set_data(chan, 1); +- set_clock(chan, 1); +- udelay(20); +- +- return chan; +- +-out_free: +- kfree(chan); +- return NULL; +-} +- +-/** +- * psb_intel_i2c_destroy - unregister and free i2c bus resources +- * @output: channel to free +- * +- * Unregister the adapter from the i2c layer, then free the structure. +- */ +-void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan) +-{ +- if (!chan) +- return; +- +- i2c_del_adapter(&chan->adapter); +- kfree(chan); +-} +diff --git a/drivers/staging/gma500/intel_opregion.c b/drivers/staging/gma500/intel_opregion.c +deleted file mode 100644 +index d946bc1..0000000 +--- a/drivers/staging/gma500/intel_opregion.c ++++ /dev/null +@@ -1,81 +0,0 @@ +-/* +- * Copyright 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * FIXME: resolve with the i915 version +- */ +- +-#include "psb_drv.h" +- +-struct opregion_header { +- u8 signature[16]; +- u32 size; +- u32 opregion_ver; +- u8 bios_ver[32]; +- u8 vbios_ver[16]; +- u8 driver_ver[16]; +- u32 mboxes; +- u8 reserved[164]; +-} __packed; +- +-struct opregion_apci { +- /*FIXME: add it later*/ +-} __packed; +- +-struct opregion_swsci { +- /*FIXME: add it later*/ +-} __packed; +- +-struct opregion_acpi { +- /*FIXME: add it later*/ +-} __packed; +- +-int gma_intel_opregion_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 opregion_phy; +- void *base; +- u32 *lid_state; +- +- dev_priv->lid_state = NULL; +- +- pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy); +- if (opregion_phy == 0) +- return -ENOTSUPP; +- +- base = ioremap(opregion_phy, 8*1024); +- if (!base) +- return -ENOMEM; +- +- lid_state = base + 0x01ac; +- +- dev_priv->lid_state = lid_state; +- dev_priv->lid_last_state = readl(lid_state); +- return 0; +-} +- +-int gma_intel_opregion_exit(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- if (dev_priv->lid_state) +- iounmap(dev_priv->lid_state); +- return 0; +-} +diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c +deleted file mode 100644 +index f47aeb7..0000000 +--- a/drivers/staging/gma500/mdfld_device.c ++++ /dev/null +@@ -1,714 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-#include +-#include +-#include +-#include "psb_reg.h" +-#include "psb_intel_reg.h" +-#include "psb_drm.h" +-#include "psb_drv.h" +-#include "mdfld_output.h" +-#include "mdfld_dsi_output.h" +-#include "mid_bios.h" +- +-/* +- * Provide the Medfield specific backlight management +- */ +- +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- +-static int mdfld_brightness; +-struct backlight_device *mdfld_backlight_device; +- +-static int mfld_set_brightness(struct backlight_device *bd) +-{ +- struct drm_device *dev = bl_get_data(mdfld_backlight_device); +- struct drm_psb_private *dev_priv = dev->dev_private; +- int level = bd->props.brightness; +- +- /* Percentage 1-100% being valid */ +- if (level < 1) +- level = 1; +- +- if (gma_power_begin(dev, 0)) { +- /* Calculate and set the brightness value */ +- u32 adjusted_level; +- +- /* Adjust the backlight level with the percent in +- * dev_priv->blc_adj2; +- */ +- adjusted_level = level * dev_priv->blc_adj2; +- adjusted_level = adjusted_level / 100; +-#if 0 +-#ifndef CONFIG_MDFLD_DSI_DPU +- if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) && +- (dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){ +- mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0); +- dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level); +- } +-#endif +- mdfld_dsi_brightness_control(dev, 0, adjusted_level); +- +- if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2)) +- mdfld_dsi_brightness_control(dev, 2, adjusted_level); +-#endif +- gma_power_end(dev); +- } +- mdfld_brightness = level; +- return 0; +-} +- +-int psb_get_brightness(struct backlight_device *bd) +-{ +- /* return locally cached var instead of HW read (due to DPST etc.) */ +- /* FIXME: ideally return actual value in case firmware fiddled with +- it */ +- return mdfld_brightness; +-} +- +-static const struct backlight_ops mfld_ops = { +- .get_brightness = psb_get_brightness, +- .update_status = mfld_set_brightness, +-}; +- +-static int mdfld_backlight_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct backlight_properties props; +- memset(&props, 0, sizeof(struct backlight_properties)); +- props.max_brightness = 100; +- props.type = BACKLIGHT_PLATFORM; +- +- mdfld_backlight_device = backlight_device_register("mfld-bl", +- NULL, (void *)dev, &mfld_ops, &props); +- +- if (IS_ERR(mdfld_backlight_device)) +- return PTR_ERR(mdfld_backlight_device); +- +- dev_priv->blc_adj1 = 100; +- dev_priv->blc_adj2 = 100; +- mdfld_backlight_device->props.brightness = 100; +- mdfld_backlight_device->props.max_brightness = 100; +- backlight_update_status(mdfld_backlight_device); +- dev_priv->backlight_device = mdfld_backlight_device; +- return 0; +-} +- +-#endif +- +-/* +- * Provide the Medfield specific chip logic and low level methods for +- * power management. +- */ +- +-static void mdfld_init_pm(struct drm_device *dev) +-{ +- /* No work needed here yet */ +-} +- +-/** +- * mdfld_save_display_registers - save registers for pipe +- * @dev: our device +- * @pipe: pipe to save +- * +- * Save the pipe state of the device before we power it off. Keep everything +- * we need to put it back again +- */ +-static int mdfld_save_display_registers(struct drm_device *dev, int pipe) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- int i; +- +- /* register */ +- u32 dpll_reg = MRST_DPLL_A; +- u32 fp_reg = MRST_FPA0; +- u32 pipeconf_reg = PIPEACONF; +- u32 htot_reg = HTOTAL_A; +- u32 hblank_reg = HBLANK_A; +- u32 hsync_reg = HSYNC_A; +- u32 vtot_reg = VTOTAL_A; +- u32 vblank_reg = VBLANK_A; +- u32 vsync_reg = VSYNC_A; +- u32 pipesrc_reg = PIPEASRC; +- u32 dspstride_reg = DSPASTRIDE; +- u32 dsplinoff_reg = DSPALINOFF; +- u32 dsptileoff_reg = DSPATILEOFF; +- u32 dspsize_reg = DSPASIZE; +- u32 dsppos_reg = DSPAPOS; +- u32 dspsurf_reg = DSPASURF; +- u32 mipi_reg = MIPI; +- u32 dspcntr_reg = DSPACNTR; +- u32 dspstatus_reg = PIPEASTAT; +- u32 palette_reg = PALETTE_A; +- +- /* pointer to values */ +- u32 *dpll_val = &dev_priv->saveDPLL_A; +- u32 *fp_val = &dev_priv->saveFPA0; +- u32 *pipeconf_val = &dev_priv->savePIPEACONF; +- u32 *htot_val = &dev_priv->saveHTOTAL_A; +- u32 *hblank_val = &dev_priv->saveHBLANK_A; +- u32 *hsync_val = &dev_priv->saveHSYNC_A; +- u32 *vtot_val = &dev_priv->saveVTOTAL_A; +- u32 *vblank_val = &dev_priv->saveVBLANK_A; +- u32 *vsync_val = &dev_priv->saveVSYNC_A; +- u32 *pipesrc_val = &dev_priv->savePIPEASRC; +- u32 *dspstride_val = &dev_priv->saveDSPASTRIDE; +- u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF; +- u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF; +- u32 *dspsize_val = &dev_priv->saveDSPASIZE; +- u32 *dsppos_val = &dev_priv->saveDSPAPOS; +- u32 *dspsurf_val = &dev_priv->saveDSPASURF; +- u32 *mipi_val = &dev_priv->saveMIPI; +- u32 *dspcntr_val = &dev_priv->saveDSPACNTR; +- u32 *dspstatus_val = &dev_priv->saveDSPASTATUS; +- u32 *palette_val = dev_priv->save_palette_a; +- +- switch (pipe) { +- case 0: +- break; +- case 1: +- /* register */ +- dpll_reg = MDFLD_DPLL_B; +- fp_reg = MDFLD_DPLL_DIV0; +- pipeconf_reg = PIPEBCONF; +- htot_reg = HTOTAL_B; +- hblank_reg = HBLANK_B; +- hsync_reg = HSYNC_B; +- vtot_reg = VTOTAL_B; +- vblank_reg = VBLANK_B; +- vsync_reg = VSYNC_B; +- pipesrc_reg = PIPEBSRC; +- dspstride_reg = DSPBSTRIDE; +- dsplinoff_reg = DSPBLINOFF; +- dsptileoff_reg = DSPBTILEOFF; +- dspsize_reg = DSPBSIZE; +- dsppos_reg = DSPBPOS; +- dspsurf_reg = DSPBSURF; +- dspcntr_reg = DSPBCNTR; +- dspstatus_reg = PIPEBSTAT; +- palette_reg = PALETTE_B; +- +- /* values */ +- dpll_val = &dev_priv->saveDPLL_B; +- fp_val = &dev_priv->saveFPB0; +- pipeconf_val = &dev_priv->savePIPEBCONF; +- htot_val = &dev_priv->saveHTOTAL_B; +- hblank_val = &dev_priv->saveHBLANK_B; +- hsync_val = &dev_priv->saveHSYNC_B; +- vtot_val = &dev_priv->saveVTOTAL_B; +- vblank_val = &dev_priv->saveVBLANK_B; +- vsync_val = &dev_priv->saveVSYNC_B; +- pipesrc_val = &dev_priv->savePIPEBSRC; +- dspstride_val = &dev_priv->saveDSPBSTRIDE; +- dsplinoff_val = &dev_priv->saveDSPBLINOFF; +- dsptileoff_val = &dev_priv->saveDSPBTILEOFF; +- dspsize_val = &dev_priv->saveDSPBSIZE; +- dsppos_val = &dev_priv->saveDSPBPOS; +- dspsurf_val = &dev_priv->saveDSPBSURF; +- dspcntr_val = &dev_priv->saveDSPBCNTR; +- dspstatus_val = &dev_priv->saveDSPBSTATUS; +- palette_val = dev_priv->save_palette_b; +- break; +- case 2: +- /* register */ +- pipeconf_reg = PIPECCONF; +- htot_reg = HTOTAL_C; +- hblank_reg = HBLANK_C; +- hsync_reg = HSYNC_C; +- vtot_reg = VTOTAL_C; +- vblank_reg = VBLANK_C; +- vsync_reg = VSYNC_C; +- pipesrc_reg = PIPECSRC; +- dspstride_reg = DSPCSTRIDE; +- dsplinoff_reg = DSPCLINOFF; +- dsptileoff_reg = DSPCTILEOFF; +- dspsize_reg = DSPCSIZE; +- dsppos_reg = DSPCPOS; +- dspsurf_reg = DSPCSURF; +- mipi_reg = MIPI_C; +- dspcntr_reg = DSPCCNTR; +- dspstatus_reg = PIPECSTAT; +- palette_reg = PALETTE_C; +- +- /* pointer to values */ +- pipeconf_val = &dev_priv->savePIPECCONF; +- htot_val = &dev_priv->saveHTOTAL_C; +- hblank_val = &dev_priv->saveHBLANK_C; +- hsync_val = &dev_priv->saveHSYNC_C; +- vtot_val = &dev_priv->saveVTOTAL_C; +- vblank_val = &dev_priv->saveVBLANK_C; +- vsync_val = &dev_priv->saveVSYNC_C; +- pipesrc_val = &dev_priv->savePIPECSRC; +- dspstride_val = &dev_priv->saveDSPCSTRIDE; +- dsplinoff_val = &dev_priv->saveDSPCLINOFF; +- dsptileoff_val = &dev_priv->saveDSPCTILEOFF; +- dspsize_val = &dev_priv->saveDSPCSIZE; +- dsppos_val = &dev_priv->saveDSPCPOS; +- dspsurf_val = &dev_priv->saveDSPCSURF; +- mipi_val = &dev_priv->saveMIPI_C; +- dspcntr_val = &dev_priv->saveDSPCCNTR; +- dspstatus_val = &dev_priv->saveDSPCSTATUS; +- palette_val = dev_priv->save_palette_c; +- break; +- default: +- DRM_ERROR("%s, invalid pipe number.\n", __func__); +- return -EINVAL; +- } +- +- /* Pipe & plane A info */ +- *dpll_val = PSB_RVDC32(dpll_reg); +- *fp_val = PSB_RVDC32(fp_reg); +- *pipeconf_val = PSB_RVDC32(pipeconf_reg); +- *htot_val = PSB_RVDC32(htot_reg); +- *hblank_val = PSB_RVDC32(hblank_reg); +- *hsync_val = PSB_RVDC32(hsync_reg); +- *vtot_val = PSB_RVDC32(vtot_reg); +- *vblank_val = PSB_RVDC32(vblank_reg); +- *vsync_val = PSB_RVDC32(vsync_reg); +- *pipesrc_val = PSB_RVDC32(pipesrc_reg); +- *dspstride_val = PSB_RVDC32(dspstride_reg); +- *dsplinoff_val = PSB_RVDC32(dsplinoff_reg); +- *dsptileoff_val = PSB_RVDC32(dsptileoff_reg); +- *dspsize_val = PSB_RVDC32(dspsize_reg); +- *dsppos_val = PSB_RVDC32(dsppos_reg); +- *dspsurf_val = PSB_RVDC32(dspsurf_reg); +- *dspcntr_val = PSB_RVDC32(dspcntr_reg); +- *dspstatus_val = PSB_RVDC32(dspstatus_reg); +- +- /*save palette (gamma) */ +- for (i = 0; i < 256; i++) +- palette_val[i] = PSB_RVDC32(palette_reg + (i<<2)); +- +- if (pipe == 1) { +- dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL); +- dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS); +- dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL); +- dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL); +- return 0; +- } +- *mipi_val = PSB_RVDC32(mipi_reg); +- return 0; +-} +- +-/** +- * mdfld_save_cursor_overlay_registers - save cursor overlay info +- * @dev: our device +- * +- * Save the cursor and overlay register state +- */ +-static int mdfld_save_cursor_overlay_registers(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- /* Save cursor regs */ +- dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR); +- dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE); +- dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS); +- +- dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR); +- dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE); +- dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS); +- +- dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR); +- dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE); +- dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS); +- +- /* HW overlay */ +- dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD); +- dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0); +- dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1); +- dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2); +- dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3); +- dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4); +- dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5); +- +- dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET); +- dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET); +- dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET); +- dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET); +- dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET); +- dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET); +- dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET); +- +- return 0; +-} +-/* +- * mdfld_restore_display_registers - restore the state of a pipe +- * @dev: our device +- * @pipe: the pipe to restore +- * +- * Restore the state of a pipe to that which was saved by the register save +- * functions. +- */ +-static int mdfld_restore_display_registers(struct drm_device *dev, int pipe) +-{ +- /* To get panel out of ULPS mode */ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dsi_config *dsi_config = NULL; +- u32 i = 0; +- u32 dpll = 0; +- u32 timeout = 0; +- u32 reg_offset = 0; +- +- /* register */ +- u32 dpll_reg = MRST_DPLL_A; +- u32 fp_reg = MRST_FPA0; +- u32 pipeconf_reg = PIPEACONF; +- u32 htot_reg = HTOTAL_A; +- u32 hblank_reg = HBLANK_A; +- u32 hsync_reg = HSYNC_A; +- u32 vtot_reg = VTOTAL_A; +- u32 vblank_reg = VBLANK_A; +- u32 vsync_reg = VSYNC_A; +- u32 pipesrc_reg = PIPEASRC; +- u32 dspstride_reg = DSPASTRIDE; +- u32 dsplinoff_reg = DSPALINOFF; +- u32 dsptileoff_reg = DSPATILEOFF; +- u32 dspsize_reg = DSPASIZE; +- u32 dsppos_reg = DSPAPOS; +- u32 dspsurf_reg = DSPASURF; +- u32 dspstatus_reg = PIPEASTAT; +- u32 mipi_reg = MIPI; +- u32 dspcntr_reg = DSPACNTR; +- u32 palette_reg = PALETTE_A; +- +- /* values */ +- u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE; +- u32 fp_val = dev_priv->saveFPA0; +- u32 pipeconf_val = dev_priv->savePIPEACONF; +- u32 htot_val = dev_priv->saveHTOTAL_A; +- u32 hblank_val = dev_priv->saveHBLANK_A; +- u32 hsync_val = dev_priv->saveHSYNC_A; +- u32 vtot_val = dev_priv->saveVTOTAL_A; +- u32 vblank_val = dev_priv->saveVBLANK_A; +- u32 vsync_val = dev_priv->saveVSYNC_A; +- u32 pipesrc_val = dev_priv->savePIPEASRC; +- u32 dspstride_val = dev_priv->saveDSPASTRIDE; +- u32 dsplinoff_val = dev_priv->saveDSPALINOFF; +- u32 dsptileoff_val = dev_priv->saveDSPATILEOFF; +- u32 dspsize_val = dev_priv->saveDSPASIZE; +- u32 dsppos_val = dev_priv->saveDSPAPOS; +- u32 dspsurf_val = dev_priv->saveDSPASURF; +- u32 dspstatus_val = dev_priv->saveDSPASTATUS; +- u32 mipi_val = dev_priv->saveMIPI; +- u32 dspcntr_val = dev_priv->saveDSPACNTR; +- u32 *palette_val = dev_priv->save_palette_a; +- +- switch (pipe) { +- case 0: +- dsi_config = dev_priv->dsi_configs[0]; +- break; +- case 1: +- /* register */ +- dpll_reg = MDFLD_DPLL_B; +- fp_reg = MDFLD_DPLL_DIV0; +- pipeconf_reg = PIPEBCONF; +- htot_reg = HTOTAL_B; +- hblank_reg = HBLANK_B; +- hsync_reg = HSYNC_B; +- vtot_reg = VTOTAL_B; +- vblank_reg = VBLANK_B; +- vsync_reg = VSYNC_B; +- pipesrc_reg = PIPEBSRC; +- dspstride_reg = DSPBSTRIDE; +- dsplinoff_reg = DSPBLINOFF; +- dsptileoff_reg = DSPBTILEOFF; +- dspsize_reg = DSPBSIZE; +- dsppos_reg = DSPBPOS; +- dspsurf_reg = DSPBSURF; +- dspcntr_reg = DSPBCNTR; +- palette_reg = PALETTE_B; +- dspstatus_reg = PIPEBSTAT; +- +- /* values */ +- dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE; +- fp_val = dev_priv->saveFPB0; +- pipeconf_val = dev_priv->savePIPEBCONF; +- htot_val = dev_priv->saveHTOTAL_B; +- hblank_val = dev_priv->saveHBLANK_B; +- hsync_val = dev_priv->saveHSYNC_B; +- vtot_val = dev_priv->saveVTOTAL_B; +- vblank_val = dev_priv->saveVBLANK_B; +- vsync_val = dev_priv->saveVSYNC_B; +- pipesrc_val = dev_priv->savePIPEBSRC; +- dspstride_val = dev_priv->saveDSPBSTRIDE; +- dsplinoff_val = dev_priv->saveDSPBLINOFF; +- dsptileoff_val = dev_priv->saveDSPBTILEOFF; +- dspsize_val = dev_priv->saveDSPBSIZE; +- dsppos_val = dev_priv->saveDSPBPOS; +- dspsurf_val = dev_priv->saveDSPBSURF; +- dspcntr_val = dev_priv->saveDSPBCNTR; +- dspstatus_val = dev_priv->saveDSPBSTATUS; +- palette_val = dev_priv->save_palette_b; +- break; +- case 2: +- reg_offset = MIPIC_REG_OFFSET; +- +- /* register */ +- pipeconf_reg = PIPECCONF; +- htot_reg = HTOTAL_C; +- hblank_reg = HBLANK_C; +- hsync_reg = HSYNC_C; +- vtot_reg = VTOTAL_C; +- vblank_reg = VBLANK_C; +- vsync_reg = VSYNC_C; +- pipesrc_reg = PIPECSRC; +- dspstride_reg = DSPCSTRIDE; +- dsplinoff_reg = DSPCLINOFF; +- dsptileoff_reg = DSPCTILEOFF; +- dspsize_reg = DSPCSIZE; +- dsppos_reg = DSPCPOS; +- dspsurf_reg = DSPCSURF; +- mipi_reg = MIPI_C; +- dspcntr_reg = DSPCCNTR; +- palette_reg = PALETTE_C; +- dspstatus_reg = PIPECSTAT; +- +- /* values */ +- pipeconf_val = dev_priv->savePIPECCONF; +- htot_val = dev_priv->saveHTOTAL_C; +- hblank_val = dev_priv->saveHBLANK_C; +- hsync_val = dev_priv->saveHSYNC_C; +- vtot_val = dev_priv->saveVTOTAL_C; +- vblank_val = dev_priv->saveVBLANK_C; +- vsync_val = dev_priv->saveVSYNC_C; +- pipesrc_val = dev_priv->savePIPECSRC; +- dspstride_val = dev_priv->saveDSPCSTRIDE; +- dsplinoff_val = dev_priv->saveDSPCLINOFF; +- dsptileoff_val = dev_priv->saveDSPCTILEOFF; +- dspsize_val = dev_priv->saveDSPCSIZE; +- dsppos_val = dev_priv->saveDSPCPOS; +- dspsurf_val = dev_priv->saveDSPCSURF; +- dspstatus_val = dev_priv->saveDSPCSTATUS; +- mipi_val = dev_priv->saveMIPI_C; +- dspcntr_val = dev_priv->saveDSPCCNTR; +- palette_val = dev_priv->save_palette_c; +- +- dsi_config = dev_priv->dsi_configs[1]; +- break; +- default: +- DRM_ERROR("%s, invalid pipe number.\n", __func__); +- return -EINVAL; +- } +- +- /* Make sure VGA plane is off. it initializes to on after reset!*/ +- PSB_WVDC32(0x80000000, VGACNTRL); +- if (pipe == 1) { +- PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg); +- PSB_RVDC32(dpll_reg); +- +- PSB_WVDC32(fp_val, fp_reg); +- } else { +- dpll = PSB_RVDC32(dpll_reg); +- +- if (!(dpll & DPLL_VCO_ENABLE)) { +- +- /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */ +- if (dpll & MDFLD_PWR_GATE_EN) { +- dpll &= ~MDFLD_PWR_GATE_EN; +- PSB_WVDC32(dpll, dpll_reg); +- udelay(500); /* FIXME: 1 ? */ +- } +- +- PSB_WVDC32(fp_val, fp_reg); +- PSB_WVDC32(dpll_val, dpll_reg); +- /* FIXME_MDFLD PO - change 500 to 1 after PO */ +- udelay(500); +- +- dpll_val |= DPLL_VCO_ENABLE; +- PSB_WVDC32(dpll_val, dpll_reg); +- PSB_RVDC32(dpll_reg); +- +- /* wait for DSI PLL to lock */ +- while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { +- udelay(150); +- timeout++; +- } +- +- if (timeout == 20000) { +- DRM_ERROR("%s, can't lock DSIPLL.\n", +- __func__); +- return -EINVAL; +- } +- } +- } +- /* Restore mode */ +- PSB_WVDC32(htot_val, htot_reg); +- PSB_WVDC32(hblank_val, hblank_reg); +- PSB_WVDC32(hsync_val, hsync_reg); +- PSB_WVDC32(vtot_val, vtot_reg); +- PSB_WVDC32(vblank_val, vblank_reg); +- PSB_WVDC32(vsync_val, vsync_reg); +- PSB_WVDC32(pipesrc_val, pipesrc_reg); +- PSB_WVDC32(dspstatus_val, dspstatus_reg); +- +- /* Set up the plane */ +- PSB_WVDC32(dspstride_val, dspstride_reg); +- PSB_WVDC32(dsplinoff_val, dsplinoff_reg); +- PSB_WVDC32(dsptileoff_val, dsptileoff_reg); +- PSB_WVDC32(dspsize_val, dspsize_reg); +- PSB_WVDC32(dsppos_val, dsppos_reg); +- PSB_WVDC32(dspsurf_val, dspsurf_reg); +- +- if (pipe == 1) { +- PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL); +- PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); +- PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL); +- PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL); +- +- } else { +- /* Set up pipe related registers */ +- PSB_WVDC32(mipi_val, mipi_reg); +- /* Setup MIPI adapter + MIPI IP registers */ +- mdfld_dsi_controller_init(dsi_config, pipe); +- msleep(20); +- } +- /* Enable the plane */ +- PSB_WVDC32(dspcntr_val, dspcntr_reg); +- msleep(20); +- /* Enable the pipe */ +- PSB_WVDC32(pipeconf_val, pipeconf_reg); +- +- for (i = 0; i < 256; i++) +- PSB_WVDC32(palette_val[i], palette_reg + (i<<2)); +- if (pipe == 1) +- return 0; +- if (!mdfld_panel_dpi(dev)) +- mdfld_enable_te(dev, pipe); +- return 0; +-} +- +-/** +- * mdfld_restore_cursor_overlay_registers - restore cursor +- * @dev: our device +- * +- * Restore the cursor and overlay state that was saved earlier +- */ +-static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- /* Enable Cursor A */ +- PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR); +- PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS); +- PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE); +- +- PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR); +- PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS); +- PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE); +- +- PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR); +- PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS); +- PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE); +- +- /* Restore HW overlay */ +- PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD); +- PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0); +- PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1); +- PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2); +- PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3); +- PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4); +- PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5); +- +- PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET); +- PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET); +- PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET); +- PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET); +- PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET); +- PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET); +- PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET); +- +- return 0; +-} +- +-/** +- * mdfld_save_display_registers - save registers lost on suspend +- * @dev: our DRM device +- * +- * Save the state we need in order to be able to restore the interface +- * upon resume from suspend +- */ +-static int mdfld_save_registers(struct drm_device *dev) +-{ +- /* FIXME: We need to shut down panels here if using them +- and once the right bits are merged */ +- mdfld_save_cursor_overlay_registers(dev); +- mdfld_save_display_registers(dev, 0); +- mdfld_save_display_registers(dev, 0); +- mdfld_save_display_registers(dev, 2); +- mdfld_save_display_registers(dev, 1); +- mdfld_disable_crtc(dev, 0); +- mdfld_disable_crtc(dev, 2); +- mdfld_disable_crtc(dev, 1); +- return 0; +-} +- +-/** +- * mdfld_restore_display_registers - restore lost register state +- * @dev: our DRM device +- * +- * Restore register state that was lost during suspend and resume. +- */ +-static int mdfld_restore_registers(struct drm_device *dev) +-{ +- mdfld_restore_display_registers(dev, 1); +- mdfld_restore_display_registers(dev, 0); +- mdfld_restore_display_registers(dev, 2); +- mdfld_restore_cursor_overlay_registers(dev); +- return 0; +-} +- +-static int mdfld_power_down(struct drm_device *dev) +-{ +- /* FIXME */ +- return 0; +-} +- +-static int mdfld_power_up(struct drm_device *dev) +-{ +- /* FIXME */ +- return 0; +-} +- +-const struct psb_ops mdfld_chip_ops = { +- .name = "Medfield", +- .accel_2d = 0, +- .pipes = 3, +- .crtcs = 2, +- .sgx_offset = MRST_SGX_OFFSET, +- +- .chip_setup = mid_chip_setup, +- +- .crtc_helper = &mdfld_helper_funcs, +- .crtc_funcs = &mdfld_intel_crtc_funcs, +- +- .output_init = mdfld_output_init, +- +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- .backlight_init = mdfld_backlight_init, +-#endif +- +- .init_pm = mdfld_init_pm, +- .save_regs = mdfld_save_registers, +- .restore_regs = mdfld_restore_registers, +- .power_down = mdfld_power_down, +- .power_up = mdfld_power_up, +-}; +- +diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.c b/drivers/staging/gma500/mdfld_dsi_dbi.c +deleted file mode 100644 +index fd211f3..0000000 +--- a/drivers/staging/gma500/mdfld_dsi_dbi.c ++++ /dev/null +@@ -1,761 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * jim liu +- * Jackie Li +- */ +- +-#include "mdfld_dsi_dbi.h" +-#include "mdfld_dsi_dbi_dpu.h" +-#include "mdfld_dsi_pkg_sender.h" +- +-#include "power.h" +-#include +- +-int enable_gfx_rtpm; +- +-extern struct drm_device *gpDrmDevice; +-extern int gfxrtdelay; +-int enter_dsr; +-struct mdfld_dsi_dbi_output *gdbi_output; +-extern bool gbgfxsuspended; +-extern int enable_gfx_rtpm; +-extern int gfxrtdelay; +- +-#define MDFLD_DSR_MAX_IDLE_COUNT 2 +- +-/* +- * set refreshing area +- */ +-int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output, +- u16 x1, u16 y1, u16 x2, u16 y2) +-{ +- struct mdfld_dsi_pkg_sender *sender = +- mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); +- u8 param[4]; +- u8 cmd; +- int err; +- +- if (!sender) { +- WARN_ON(1); +- return -EINVAL; +- } +- +- /* Set column */ +- cmd = DCS_SET_COLUMN_ADDRESS; +- param[0] = x1 >> 8; +- param[1] = x1; +- param[2] = x2 >> 8; +- param[3] = x2; +- +- err = mdfld_dsi_send_dcs(sender, +- cmd, +- param, +- 4, +- CMD_DATA_SRC_SYSTEM_MEM, +- MDFLD_DSI_QUEUE_PACKAGE); +- if (err) { +- dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd); +- goto err_out; +- } +- +- /* Set page */ +- cmd = DCS_SET_PAGE_ADDRESS; +- param[0] = y1 >> 8; +- param[1] = y1; +- param[2] = y2 >> 8; +- param[3] = y2; +- +- err = mdfld_dsi_send_dcs(sender, +- cmd, +- param, +- 4, +- CMD_DATA_SRC_SYSTEM_MEM, +- MDFLD_DSI_QUEUE_PACKAGE); +- if (err) { +- dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd); +- goto err_out; +- } +- +- /*update screen*/ +- err = mdfld_dsi_send_dcs(sender, +- write_mem_start, +- NULL, +- 0, +- CMD_DATA_SRC_PIPE, +- MDFLD_DSI_QUEUE_PACKAGE); +- if (err) { +- dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd); +- goto err_out; +- } +- mdfld_dsi_cmds_kick_out(sender); +-err_out: +- return err; +-} +- +-/* +- * set panel's power state +- */ +-int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output, +- int mode) +-{ +- struct drm_device *dev = dbi_output->dev; +- struct mdfld_dsi_pkg_sender *sender = +- mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); +- u8 param = 0; +- u32 err = 0; +- +- if (!sender) { +- WARN_ON(1); +- return -EINVAL; +- } +- +- if (mode == DRM_MODE_DPMS_ON) { +- /* Exit sleep mode */ +- err = mdfld_dsi_send_dcs(sender, +- DCS_EXIT_SLEEP_MODE, +- NULL, +- 0, +- CMD_DATA_SRC_SYSTEM_MEM, +- MDFLD_DSI_QUEUE_PACKAGE); +- if (err) { +- dev_err(dev->dev, "DCS 0x%x sent failed\n", +- DCS_EXIT_SLEEP_MODE); +- goto power_err; +- } +- +- /* Set display on */ +- err = mdfld_dsi_send_dcs(sender, +- DCS_SET_DISPLAY_ON, +- NULL, +- 0, +- CMD_DATA_SRC_SYSTEM_MEM, +- MDFLD_DSI_QUEUE_PACKAGE); +- if (err) { +- dev_err(dev->dev, "DCS 0x%x sent failed\n", +- DCS_SET_DISPLAY_ON); +- goto power_err; +- } +- +- /* set tear effect on */ +- err = mdfld_dsi_send_dcs(sender, +- DCS_SET_TEAR_ON, +- ¶m, +- 1, +- CMD_DATA_SRC_SYSTEM_MEM, +- MDFLD_DSI_QUEUE_PACKAGE); +- if (err) { +- dev_err(dev->dev, "DCS 0x%x sent failed\n", +- set_tear_on); +- goto power_err; +- } +- +- /** +- * FIXME: remove this later +- */ +- err = mdfld_dsi_send_dcs(sender, +- DCS_WRITE_MEM_START, +- NULL, +- 0, +- CMD_DATA_SRC_PIPE, +- MDFLD_DSI_QUEUE_PACKAGE); +- if (err) { +- dev_err(dev->dev, "DCS 0x%x sent failed\n", +- DCS_WRITE_MEM_START); +- goto power_err; +- } +- } else { +- /* Set tear effect off */ +- err = mdfld_dsi_send_dcs(sender, +- DCS_SET_TEAR_OFF, +- NULL, +- 0, +- CMD_DATA_SRC_SYSTEM_MEM, +- MDFLD_DSI_QUEUE_PACKAGE); +- if (err) { +- dev_err(dev->dev, "DCS 0x%x sent failed\n", +- DCS_SET_TEAR_OFF); +- goto power_err; +- } +- +- /* Turn display off */ +- err = mdfld_dsi_send_dcs(sender, +- DCS_SET_DISPLAY_OFF, +- NULL, +- 0, +- CMD_DATA_SRC_SYSTEM_MEM, +- MDFLD_DSI_QUEUE_PACKAGE); +- if (err) { +- dev_err(dev->dev, "DCS 0x%x sent failed\n", +- DCS_SET_DISPLAY_OFF); +- goto power_err; +- } +- +- /* Now enter sleep mode */ +- err = mdfld_dsi_send_dcs(sender, +- DCS_ENTER_SLEEP_MODE, +- NULL, +- 0, +- CMD_DATA_SRC_SYSTEM_MEM, +- MDFLD_DSI_QUEUE_PACKAGE); +- if (err) { +- dev_err(dev->dev, "DCS 0x%x sent failed\n", +- DCS_ENTER_SLEEP_MODE); +- goto power_err; +- } +- } +- mdfld_dsi_cmds_kick_out(sender); +-power_err: +- return err; +-} +- +-/* +- * send a generic DCS command with a parameter list +- */ +-int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output, +- u8 dcs, u8 *param, u32 num, u8 data_src) +-{ +- struct mdfld_dsi_pkg_sender *sender = +- mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); +- int ret; +- +- if (!sender) { +- WARN_ON(1); +- return -EINVAL; +- } +- +- ret = mdfld_dsi_send_dcs(sender, +- dcs, +- param, +- num, +- data_src, +- MDFLD_DSI_SEND_PACKAGE); +- +- return ret; +-} +- +-/* +- * Enter DSR +- */ +-void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe) +-{ +- u32 reg_val; +- struct drm_device *dev = dbi_output->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct drm_crtc *crtc = dbi_output->base.base.crtc; +- struct psb_intel_crtc *psb_crtc = (crtc) ? +- to_psb_intel_crtc(crtc) : NULL; +- u32 dpll_reg = MRST_DPLL_A; +- u32 pipeconf_reg = PIPEACONF; +- u32 dspcntr_reg = DSPACNTR; +- +- if (!dbi_output) +- return; +- +- /* FIXME check if can go */ +- dev_priv->is_in_idle = true; +- +- gdbi_output = dbi_output; +- if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || +- (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) +- return; +- +- if (pipe == 2) { +- dpll_reg = MRST_DPLL_A; +- pipeconf_reg = PIPECCONF; +- dspcntr_reg = DSPCCNTR; +- } +- +- if (!gma_power_begin(dev, true)) { +- dev_err(dev->dev, "hw begin failed\n"); +- return; +- } +- /* Disable te interrupts */ +- mdfld_disable_te(dev, pipe); +- +- /* Disable plane */ +- reg_val = REG_READ(dspcntr_reg); +- if (!(reg_val & DISPLAY_PLANE_ENABLE)) { +- REG_WRITE(dspcntr_reg, reg_val & ~DISPLAY_PLANE_ENABLE); +- REG_READ(dspcntr_reg); +- } +- +- /* Disable pipe */ +- reg_val = REG_READ(pipeconf_reg); +- if (!(reg_val & DISPLAY_PLANE_ENABLE)) { +- reg_val &= ~DISPLAY_PLANE_ENABLE; +- reg_val |= (PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF); +- REG_WRITE(pipeconf_reg, reg_val); +- REG_READ(pipeconf_reg); +- mdfldWaitForPipeDisable(dev, pipe); +- } +- +- /* Disable DPLL */ +- reg_val = REG_READ(dpll_reg); +- if (!(reg_val & DPLL_VCO_ENABLE)) { +- reg_val &= ~DPLL_VCO_ENABLE; +- REG_WRITE(dpll_reg, reg_val); +- REG_READ(dpll_reg); +- udelay(500); +- } +- +- gma_power_end(dev); +- dbi_output->mode_flags |= MODE_SETTING_IN_DSR; +- if (pipe == 2) { +- enter_dsr = 1; +- /* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */ +- } +-} +- +-static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output, +- int pipe) +-{ +- struct drm_device *dev = dbi_output->dev; +- struct drm_crtc *crtc = dbi_output->base.base.crtc; +- struct psb_intel_crtc *psb_crtc = (crtc) ? +- to_psb_intel_crtc(crtc) : NULL; +- u32 reg_val; +- u32 dpll_reg = MRST_DPLL_A; +- u32 pipeconf_reg = PIPEACONF; +- u32 dspcntr_reg = DSPACNTR; +- u32 reg_offset = 0; +- +- /*if mode setting on-going, back off*/ +- if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || +- (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) +- return; +- +- if (pipe == 2) { +- dpll_reg = MRST_DPLL_A; +- pipeconf_reg = PIPECCONF; +- dspcntr_reg = DSPCCNTR; +- reg_offset = MIPIC_REG_OFFSET; +- } +- +- if (!gma_power_begin(dev, true)) { +- dev_err(dev->dev, "hw begin failed\n"); +- return; +- } +- +- /* Enable DPLL */ +- reg_val = REG_READ(dpll_reg); +- if (!(reg_val & DPLL_VCO_ENABLE)) { +- if (reg_val & MDFLD_PWR_GATE_EN) { +- reg_val &= ~MDFLD_PWR_GATE_EN; +- REG_WRITE(dpll_reg, reg_val); +- REG_READ(dpll_reg); +- udelay(500); +- } +- +- reg_val |= DPLL_VCO_ENABLE; +- REG_WRITE(dpll_reg, reg_val); +- REG_READ(dpll_reg); +- udelay(500); +- +- /* Add timeout */ +- while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) +- cpu_relax(); +- } +- +- /* Enable pipe */ +- reg_val = REG_READ(pipeconf_reg); +- if (!(reg_val & PIPEACONF_ENABLE)) { +- reg_val |= PIPEACONF_ENABLE; +- REG_WRITE(pipeconf_reg, reg_val); +- REG_READ(pipeconf_reg); +- udelay(500); +- mdfldWaitForPipeEnable(dev, pipe); +- } +- +- /* Enable plane */ +- reg_val = REG_READ(dspcntr_reg); +- if (!(reg_val & DISPLAY_PLANE_ENABLE)) { +- reg_val |= DISPLAY_PLANE_ENABLE; +- REG_WRITE(dspcntr_reg, reg_val); +- REG_READ(dspcntr_reg); +- udelay(500); +- } +- +- /* Enable TE interrupt on this pipe */ +- mdfld_enable_te(dev, pipe); +- gma_power_end(dev); +- +- /*clean IN_DSR flag*/ +- dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; +-} +- +-/* +- * Exit from DSR +- */ +-void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; +- struct mdfld_dsi_dbi_output **dbi_output; +- int i; +- int pipe; +- +- /* FIXME can go ? */ +- dev_priv->is_in_idle = false; +- dbi_output = dsr_info->dbi_outputs; +- +-#ifdef CONFIG_PM_RUNTIME +- if (!enable_gfx_rtpm) { +-/* pm_runtime_allow(&gpDrmDevice->pdev->dev); */ +-/* schedule_delayed_work(&rtpm_work, 30 * 1000);*/ /* FIXME: HZ ? */ +- } +-#endif +- +- /* For each output, exit dsr */ +- for (i = 0; i < dsr_info->dbi_output_num; i++) { +- /* If panel has been turned off, skip */ +- if (!dbi_output[i] || !dbi_output[i]->dbi_panel_on) +- continue; +- pipe = dbi_output[i]->channel_num ? 2 : 0; +- enter_dsr = 0; +- mdfld_dbi_output_exit_dsr(dbi_output[i], pipe); +- } +- dev_priv->dsr_fb_update |= update_src; +-} +- +-static bool mdfld_dbi_is_in_dsr(struct drm_device *dev) +-{ +- if (REG_READ(MRST_DPLL_A) & DPLL_VCO_ENABLE) +- return false; +- if ((REG_READ(PIPEACONF) & PIPEACONF_ENABLE) || +- (REG_READ(PIPECCONF) & PIPEACONF_ENABLE)) +- return false; +- if ((REG_READ(DSPACNTR) & DISPLAY_PLANE_ENABLE) || +- (REG_READ(DSPCCNTR) & DISPLAY_PLANE_ENABLE)) +- return false; +- +- return true; +-} +- +-/* Periodically update dbi panel */ +-void mdfld_dbi_update_panel(struct drm_device *dev, int pipe) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; +- struct mdfld_dsi_dbi_output **dbi_outputs; +- struct mdfld_dsi_dbi_output *dbi_output; +- int i; +- int can_enter_dsr = 0; +- u32 damage_mask; +- +- dbi_outputs = dsr_info->dbi_outputs; +- dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0]; +- +- if (!dbi_output) +- return; +- +- if (pipe == 0) +- damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_0; +- else if (pipe == 2) +- damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_2; +- else +- return; +- +- /* If FB is damaged and panel is on update on-panel FB */ +- if (damage_mask && dbi_output->dbi_panel_on) { +- dbi_output->dsr_fb_update_done = false; +- +- if (dbi_output->p_funcs->update_fb) +- dbi_output->p_funcs->update_fb(dbi_output, pipe); +- +- if (dev_priv->dsr_enable && dbi_output->dsr_fb_update_done) +- dev_priv->dsr_fb_update &= ~damage_mask; +- +- /*clean IN_DSR flag*/ +- dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; +- +- dbi_output->dsr_idle_count = 0; +- } else { +- dbi_output->dsr_idle_count++; +- } +- +- switch (dsr_info->dbi_output_num) { +- case 1: +- if (dbi_output->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT) +- can_enter_dsr = 1; +- break; +- case 2: +- if (dbi_outputs[0]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT +- && dbi_outputs[1]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT) +- can_enter_dsr = 1; +- break; +- default: +- DRM_ERROR("Wrong DBI output number\n"); +- } +- +- /* Try to enter DSR */ +- if (can_enter_dsr) { +- for (i = 0; i < dsr_info->dbi_output_num; i++) { +- if (!mdfld_dbi_is_in_dsr(dev) && dbi_outputs[i] && +- !(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) { +- mdfld_dsi_dbi_enter_dsr(dbi_outputs[i], +- dbi_outputs[i]->channel_num ? 2 : 0); +-#if 0 +- enter_dsr = 1; +- pr_err("%s: enter_dsr = 1\n", __func__); +-#endif +- } +- } +- /*schedule rpm suspend after gfxrtdelay*/ +-#ifdef CONFIG_GFX_RTPM +- if (!dev_priv->rpm_enabled +- || !enter_dsr +- /* || (REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN) */ +- || pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay)) +- dev_warn(dev->dev, +- "Runtime PM schedule suspend failed, rpm %d\n", +- dev_priv->rpm_enabled); +-#endif +- } +-} +- +-int mdfld_dbi_dsr_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; +- +- if (!dsr_info || IS_ERR(dsr_info)) { +- dsr_info = kzalloc(sizeof(struct mdfld_dbi_dsr_info), +- GFP_KERNEL); +- if (!dsr_info) { +- dev_err(dev->dev, "No memory\n"); +- return -ENOMEM; +- } +- dev_priv->dbi_dsr_info = dsr_info; +- } +- return 0; +-} +- +-void mdfld_dbi_dsr_exit(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; +- +- if (dsr_info) { +- kfree(dsr_info); +- dev_priv->dbi_dsr_info = NULL; +- } +-} +- +-void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config, +- int pipe) +-{ +- struct drm_device *dev = dsi_config->dev; +- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; +- int lane_count = dsi_config->lane_count; +- u32 val = 0; +- +- dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe); +- +- /* Un-ready device */ +- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); +- +- /* Init dsi adapter before kicking off */ +- REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); +- +- /* TODO: figure out how to setup these registers */ +- REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); +- REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), +- 0x000a0014); +- REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400); +- REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001); +- REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000); +- +- /* Enable all interrupts */ +- REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); +- /* Max value: 20 clock cycles of txclkesc */ +- REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f); +- /* Min 21 txclkesc, max: ffffh */ +- REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff); +- /* Min: 7d0 max: 4e20 */ +- REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0); +- +- /* Set up func_prg */ +- val |= lane_count; +- val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET); +- val |= DSI_DBI_COLOR_FORMAT_OPTION2; +- REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); +- +- REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff); +- REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff); +- +- /* De-assert dbi_stall when half of DBI FIFO is empty */ +- /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */ +- +- REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); +- REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); +- REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); +- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); +-} +- +-#if 0 +-/*DBI encoder helper funcs*/ +-static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = { +- .dpms = mdfld_dsi_dbi_dpms, +- .mode_fixup = mdfld_dsi_dbi_mode_fixup, +- .prepare = mdfld_dsi_dbi_prepare, +- .mode_set = mdfld_dsi_dbi_mode_set, +- .commit = mdfld_dsi_dbi_commit, +-}; +- +-/*DBI encoder funcs*/ +-static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = { +- .destroy = drm_encoder_cleanup, +-}; +- +-#endif +- +-/* +- * Init DSI DBI encoder. +- * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector +- * return pointer of newly allocated DBI encoder, NULL on error +- */ +-struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev, +- struct mdfld_dsi_connector *dsi_connector, +- struct panel_funcs *p_funcs) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dsi_dbi_output *dbi_output = NULL; +- struct mdfld_dsi_config *dsi_config; +- struct drm_connector *connector = NULL; +- struct drm_encoder *encoder = NULL; +- struct drm_display_mode *fixed_mode = NULL; +- struct psb_gtt *pg = dev_priv ? (&dev_priv->gtt) : NULL; +- struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL; +- struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL; +- u32 data = 0; +- int pipe; +- int ret; +- +- if (!pg || !dsi_connector || !p_funcs) { +- WARN_ON(1); +- return NULL; +- } +- +- dsi_config = mdfld_dsi_get_config(dsi_connector); +- pipe = dsi_connector->pipe; +- +- /*panel hard-reset*/ +- if (p_funcs->reset) { +- ret = p_funcs->reset(pipe); +- if (ret) { +- DRM_ERROR("Panel %d hard-reset failed\n", pipe); +- return NULL; +- } +- } +- /* Panel drvIC init */ +- if (p_funcs->drv_ic_init) +- p_funcs->drv_ic_init(dsi_config, pipe); +- +- /* Panel power mode detect */ +- ret = mdfld_dsi_get_power_mode(dsi_config, +- &data, +- MDFLD_DSI_HS_TRANSMISSION); +- if (ret) { +- DRM_ERROR("Panel %d get power mode failed\n", pipe); +- dsi_connector->status = connector_status_disconnected; +- } else { +- DRM_INFO("pipe %d power mode 0x%x\n", pipe, data); +- dsi_connector->status = connector_status_connected; +- } +- +- /*TODO: get panel info from DDB*/ +- +- dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL); +- if (!dbi_output) { +- dev_err(dev->dev, "No memory\n"); +- return NULL; +- } +- +- if (dsi_connector->pipe == 0) { +- dbi_output->channel_num = 0; +- dev_priv->dbi_output = dbi_output; +- } else if (dsi_connector->pipe == 2) { +- dbi_output->channel_num = 1; +- dev_priv->dbi_output2 = dbi_output; +- } else { +- dev_err(dev->dev, "only support 2 DSI outputs\n"); +- goto out_err1; +- } +- +- dbi_output->dev = dev; +- dbi_output->p_funcs = p_funcs; +- fixed_mode = dsi_config->fixed_mode; +- dbi_output->panel_fixed_mode = fixed_mode; +- +- /* Create drm encoder object */ +- connector = &dsi_connector->base.base; +- encoder = &dbi_output->base.base; +- /* Review this if we ever get MIPI-HDMI bridges or similar */ +- drm_encoder_init(dev, +- encoder, +- p_funcs->encoder_funcs, +- DRM_MODE_ENCODER_LVDS); +- drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs); +- +- /* Attach to given connector */ +- drm_mode_connector_attach_encoder(connector, encoder); +- +- /* Set possible CRTCs and clones */ +- if (dsi_connector->pipe) { +- encoder->possible_crtcs = (1 << 2); +- encoder->possible_clones = (1 << 1); +- } else { +- encoder->possible_crtcs = (1 << 0); +- encoder->possible_clones = (1 << 0); +- } +- +- dev_priv->dsr_fb_update = 0; +- dev_priv->dsr_enable = false; +- dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr; +- +- dbi_output->first_boot = true; +- dbi_output->mode_flags = MODE_SETTING_IN_ENCODER; +- +- /* Add this output to dpu_info if in DPU mode */ +- if (dpu_info && dsi_connector->status == connector_status_connected) { +- if (dsi_connector->pipe == 0) +- dpu_info->dbi_outputs[0] = dbi_output; +- else +- dpu_info->dbi_outputs[1] = dbi_output; +- +- dpu_info->dbi_output_num++; +- } else if (dsi_connector->status == connector_status_connected) { +- /* Add this output to dsr_info if not */ +- if (dsi_connector->pipe == 0) +- dsr_info->dbi_outputs[0] = dbi_output; +- else +- dsr_info->dbi_outputs[1] = dbi_output; +- +- dsr_info->dbi_output_num++; +- } +- return &dbi_output->base; +-out_err1: +- kfree(dbi_output); +- return NULL; +-} +diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.h b/drivers/staging/gma500/mdfld_dsi_dbi.h +deleted file mode 100644 +index f0fa986..0000000 +--- a/drivers/staging/gma500/mdfld_dsi_dbi.h ++++ /dev/null +@@ -1,173 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * jim liu +- * Jackie Li +- */ +- +-#ifndef __MDFLD_DSI_DBI_H__ +-#define __MDFLD_DSI_DBI_H__ +- +-#include +-#include +-#include +-#include +-#include +- +-#include "psb_drv.h" +-#include "psb_intel_drv.h" +-#include "psb_intel_reg.h" +-#include "power.h" +- +-#include "mdfld_dsi_output.h" +-#include "mdfld_output.h" +- +-/* +- * DBI encoder which inherits from mdfld_dsi_encoder +- */ +-struct mdfld_dsi_dbi_output { +- struct mdfld_dsi_encoder base; +- struct drm_display_mode *panel_fixed_mode; +- u8 last_cmd; +- u8 lane_count; +- u8 channel_num; +- struct drm_device *dev; +- +- /* Backlight operations */ +- +- /* DSR timer */ +- u32 dsr_idle_count; +- bool dsr_fb_update_done; +- +- /* Mode setting flags */ +- u32 mode_flags; +- +- /* Panel status */ +- bool dbi_panel_on; +- bool first_boot; +- struct panel_funcs *p_funcs; +- +- /* DPU */ +- u32 *dbi_cb_addr; +- u32 dbi_cb_phy; +- spinlock_t cb_lock; +- u32 cb_write; +-}; +- +-#define MDFLD_DSI_DBI_OUTPUT(dsi_encoder) \ +- container_of(dsi_encoder, struct mdfld_dsi_dbi_output, base) +- +-struct mdfld_dbi_dsr_info { +- int dbi_output_num; +- struct mdfld_dsi_dbi_output *dbi_outputs[2]; +- +- u32 dsr_idle_count; +-}; +- +-#define DBI_CB_TIMEOUT_COUNT 0xffff +- +-/* Offsets */ +-#define CMD_MEM_ADDR_OFFSET 0 +- +-#define CMD_DATA_SRC_SYSTEM_MEM 0 +-#define CMD_DATA_SRC_PIPE 1 +- +-static inline int mdfld_dsi_dbi_fifo_ready(struct mdfld_dsi_dbi_output *dbi_output) +-{ +- struct drm_device *dev = dbi_output->dev; +- u32 retry = DBI_CB_TIMEOUT_COUNT; +- int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0; +- int ret = 0; +- +- /* Query the dbi fifo status*/ +- while (retry--) { +- if (REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset) & (1 << 27)) +- break; +- } +- +- if (!retry) { +- DRM_ERROR("Timeout waiting for DBI FIFO empty\n"); +- ret = -EAGAIN; +- } +- return ret; +-} +- +-static inline int mdfld_dsi_dbi_cmd_sent(struct mdfld_dsi_dbi_output *dbi_output) +-{ +- struct drm_device *dev = dbi_output->dev; +- u32 retry = DBI_CB_TIMEOUT_COUNT; +- int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0; +- int ret = 0; +- +- /* Query the command execution status */ +- while (retry--) +- if (!(REG_READ(MIPIA_CMD_ADD_REG + reg_offset) & (1 << 0))) +- break; +- +- if (!retry) { +- DRM_ERROR("Timeout waiting for DBI command status\n"); +- ret = -EAGAIN; +- } +- +- return ret; +-} +- +-static inline int mdfld_dsi_dbi_cb_ready(struct mdfld_dsi_dbi_output *dbi_output) +-{ +- int ret = 0; +- +- /* Query the command execution status*/ +- ret = mdfld_dsi_dbi_cmd_sent(dbi_output); +- if (ret) { +- DRM_ERROR("Peripheral is busy\n"); +- ret = -EAGAIN; +- } +- /* Query the dbi fifo status*/ +- ret = mdfld_dsi_dbi_fifo_ready(dbi_output); +- if (ret) { +- DRM_ERROR("DBI FIFO is not empty\n"); +- ret = -EAGAIN; +- } +- return ret; +-} +- +-extern void mdfld_dsi_dbi_output_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev, int pipe); +-extern void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src); +-extern void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, +- int pipe); +-extern int mdfld_dbi_dsr_init(struct drm_device *dev); +-extern void mdfld_dbi_dsr_exit(struct drm_device *dev); +-extern struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev, +- struct mdfld_dsi_connector *dsi_connector, +- struct panel_funcs *p_funcs); +-extern int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output, +- u8 dcs, u8 *param, u32 num, u8 data_src); +-extern int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output, +- u16 x1, u16 y1, u16 x2, u16 y2); +-extern int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output, +- int mode); +-extern void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config, +- int pipe); +- +-#endif /*__MDFLD_DSI_DBI_H__*/ +diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c +deleted file mode 100644 +index a4e2ff4..0000000 +--- a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c ++++ /dev/null +@@ -1,778 +0,0 @@ +-/* +- * Copyright © 2010-2011 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Jim Liu +- * Jackie Li +- */ +- +-#include "mdfld_dsi_dbi_dpu.h" +-#include "mdfld_dsi_dbi.h" +- +-/* +- * NOTE: all mdlfd_x_damage funcs should be called by holding dpu_update_lock +- */ +- +-static int mdfld_cursor_damage(struct mdfld_dbi_dpu_info *dpu_info, +- mdfld_plane_t plane, +- struct psb_drm_dpu_rect *damaged_rect) +-{ +- int x, y; +- int new_x, new_y; +- struct psb_drm_dpu_rect *rect; +- struct psb_drm_dpu_rect *pipe_rect; +- int cursor_size; +- struct mdfld_cursor_info *cursor; +- mdfld_plane_t fb_plane; +- +- if (plane == MDFLD_CURSORA) { +- cursor = &dpu_info->cursors[0]; +- x = dpu_info->cursors[0].x; +- y = dpu_info->cursors[0].y; +- cursor_size = dpu_info->cursors[0].size; +- pipe_rect = &dpu_info->damage_pipea; +- fb_plane = MDFLD_PLANEA; +- } else { +- cursor = &dpu_info->cursors[1]; +- x = dpu_info->cursors[1].x; +- y = dpu_info->cursors[1].y; +- cursor_size = dpu_info->cursors[1].size; +- pipe_rect = &dpu_info->damage_pipec; +- fb_plane = MDFLD_PLANEC; +- } +- new_x = damaged_rect->x; +- new_y = damaged_rect->y; +- +- if (x == new_x && y == new_y) +- return 0; +- +- rect = &dpu_info->damaged_rects[plane]; +- /* Move to right */ +- if (new_x >= x) { +- if (new_y > y) { +- rect->x = x; +- rect->y = y; +- rect->width = (new_x + cursor_size) - x; +- rect->height = (new_y + cursor_size) - y; +- goto cursor_out; +- } else { +- rect->x = x; +- rect->y = new_y; +- rect->width = (new_x + cursor_size) - x; +- rect->height = (y - new_y); +- goto cursor_out; +- } +- } else { +- if (new_y > y) { +- rect->x = new_x; +- rect->y = y; +- rect->width = (x + cursor_size) - new_x; +- rect->height = new_y - y; +- goto cursor_out; +- } else { +- rect->x = new_x; +- rect->y = new_y; +- rect->width = (x + cursor_size) - new_x; +- rect->height = (y + cursor_size) - new_y; +- } +- } +-cursor_out: +- if (new_x < 0) +- cursor->x = 0; +- else if (new_x > 864) +- cursor->x = 864; +- else +- cursor->x = new_x; +- +- if (new_y < 0) +- cursor->y = 0; +- else if (new_y > 480) +- cursor->y = 480; +- else +- cursor->y = new_y; +- +- /* +- * FIXME: this is a workaround for cursor plane update, +- * remove it later! +- */ +- rect->x = 0; +- rect->y = 0; +- rect->width = 864; +- rect->height = 480; +- +- mdfld_check_boundary(dpu_info, rect); +- mdfld_dpu_region_extent(pipe_rect, rect); +- +- /* Update pending status of dpu_info */ +- dpu_info->pending |= (1 << plane); +- /* Update fb panel as well */ +- dpu_info->pending |= (1 << fb_plane); +- return 0; +-} +- +-static int mdfld_fb_damage(struct mdfld_dbi_dpu_info *dpu_info, +- mdfld_plane_t plane, +- struct psb_drm_dpu_rect *damaged_rect) +-{ +- struct psb_drm_dpu_rect *rect; +- +- if (plane == MDFLD_PLANEA) +- rect = &dpu_info->damage_pipea; +- else +- rect = &dpu_info->damage_pipec; +- +- mdfld_check_boundary(dpu_info, damaged_rect); +- +- /* Add fb damage area to this pipe */ +- mdfld_dpu_region_extent(rect, damaged_rect); +- +- /* Update pending status of dpu_info */ +- dpu_info->pending |= (1 << plane); +- return 0; +-} +- +-/* Do nothing here, right now */ +-static int mdfld_overlay_damage(struct mdfld_dbi_dpu_info *dpu_info, +- mdfld_plane_t plane, +- struct psb_drm_dpu_rect *damaged_rect) +-{ +- return 0; +-} +- +-int mdfld_dbi_dpu_report_damage(struct drm_device *dev, +- mdfld_plane_t plane, +- struct psb_drm_dpu_rect *rect) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; +- int ret = 0; +- +- /* DPU not in use, no damage reporting needed */ +- if (dpu_info == NULL) +- return 0; +- +- spin_lock(&dpu_info->dpu_update_lock); +- +- switch (plane) { +- case MDFLD_PLANEA: +- case MDFLD_PLANEC: +- mdfld_fb_damage(dpu_info, plane, rect); +- break; +- case MDFLD_CURSORA: +- case MDFLD_CURSORC: +- mdfld_cursor_damage(dpu_info, plane, rect); +- break; +- case MDFLD_OVERLAYA: +- case MDFLD_OVERLAYC: +- mdfld_overlay_damage(dpu_info, plane, rect); +- break; +- default: +- DRM_ERROR("Invalid plane type %d\n", plane); +- ret = -EINVAL; +- } +- spin_unlock(&dpu_info->dpu_update_lock); +- return ret; +-} +- +-int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv; +- struct mdfld_dbi_dpu_info *dpu_info; +- struct mdfld_dsi_config *dsi_config; +- struct psb_drm_dpu_rect rect; +- int i; +- +- if (!dev) { +- DRM_ERROR("Invalid parameter\n"); +- return -EINVAL; +- } +- +- dev_priv = dev->dev_private; +- dpu_info = dev_priv->dbi_dpu_info; +- +- /* This is fine - we may be in non DPU mode */ +- if (!dpu_info) +- return -EINVAL; +- +- for (i = 0; i < dpu_info->dbi_output_num; i++) { +- dsi_config = dev_priv->dsi_configs[i]; +- if (dsi_config) { +- rect.x = rect.y = 0; +- rect.width = dsi_config->fixed_mode->hdisplay; +- rect.height = dsi_config->fixed_mode->vdisplay; +- mdfld_dbi_dpu_report_damage(dev, +- i ? (MDFLD_PLANEC) : (MDFLD_PLANEA), +- &rect); +- } +- } +- /* Exit DSR state */ +- mdfld_dpu_exit_dsr(dev); +- return 0; +-} +- +-int mdfld_dsi_dbi_dsr_off(struct drm_device *dev, +- struct psb_drm_dpu_rect *rect) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; +- +- mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, rect); +- +- /* If dual display mode */ +- if (dpu_info->dbi_output_num == 2) +- mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, rect); +- +- /* Force dsi to exit DSR mode */ +- mdfld_dpu_exit_dsr(dev); +- return 0; +-} +- +-static void mdfld_dpu_cursor_plane_flush(struct mdfld_dbi_dpu_info *dpu_info, +- mdfld_plane_t plane) +-{ +- struct drm_device *dev = dpu_info->dev; +- u32 curpos_reg = CURAPOS; +- u32 curbase_reg = CURABASE; +- u32 curcntr_reg = CURACNTR; +- struct mdfld_cursor_info *cursor = &dpu_info->cursors[0]; +- +- if (plane == MDFLD_CURSORC) { +- curpos_reg = CURCPOS; +- curbase_reg = CURCBASE; +- curcntr_reg = CURCCNTR; +- cursor = &dpu_info->cursors[1]; +- } +- +- REG_WRITE(curcntr_reg, REG_READ(curcntr_reg)); +- REG_WRITE(curpos_reg, +- (((cursor->x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | +- ((cursor->y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT))); +- REG_WRITE(curbase_reg, REG_READ(curbase_reg)); +-} +- +-static void mdfld_dpu_fb_plane_flush(struct mdfld_dbi_dpu_info *dpu_info, +- mdfld_plane_t plane) +-{ +- u32 pipesrc_reg = PIPEASRC; +- u32 dspsize_reg = DSPASIZE; +- u32 dspoff_reg = DSPALINOFF; +- u32 dspsurf_reg = DSPASURF; +- u32 dspstride_reg = DSPASTRIDE; +- u32 stride; +- struct psb_drm_dpu_rect *rect = &dpu_info->damage_pipea; +- struct drm_device *dev = dpu_info->dev; +- +- if (plane == MDFLD_PLANEC) { +- pipesrc_reg = PIPECSRC; +- dspsize_reg = DSPCSIZE; +- dspoff_reg = DSPCLINOFF; +- dspsurf_reg = DSPCSURF; +- dspstride_reg = DSPCSTRIDE; +- rect = &dpu_info->damage_pipec; +- } +- +- stride = REG_READ(dspstride_reg); +- /* FIXME: should I do the pipe src update here? */ +- REG_WRITE(pipesrc_reg, ((rect->width - 1) << 16) | (rect->height - 1)); +- /* Flush plane */ +- REG_WRITE(dspsize_reg, ((rect->height - 1) << 16) | (rect->width - 1)); +- REG_WRITE(dspoff_reg, ((rect->x * 4) + (rect->y * stride))); +- REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg)); +- +- /* +- * TODO: wait for flip finished and restore the pipesrc reg, +- * or cursor will be show at a wrong position +- */ +-} +- +-static void mdfld_dpu_overlay_plane_flush(struct mdfld_dbi_dpu_info *dpu_info, +- mdfld_plane_t plane) +-{ +-} +- +-/* +- * TODO: we are still in dbi normal mode now, we will try to use partial +- * mode later. +- */ +-static int mdfld_dbi_prepare_cb(struct mdfld_dsi_dbi_output *dbi_output, +- struct mdfld_dbi_dpu_info *dpu_info, int pipe) +-{ +- u8 *cb_addr = (u8 *)dbi_output->dbi_cb_addr; +- u32 *index; +- struct psb_drm_dpu_rect *rect = pipe ? +- (&dpu_info->damage_pipec) : (&dpu_info->damage_pipea); +- +- /* FIXME: lock command buffer, this may lead to a deadlock, +- as we already hold the dpu_update_lock */ +- if (!spin_trylock(&dbi_output->cb_lock)) { +- DRM_ERROR("lock command buffer failed, try again\n"); +- return -EAGAIN; +- } +- +- index = &dbi_output->cb_write; +- +- if (*index) { +- DRM_ERROR("DBI command buffer unclean\n"); +- return -EAGAIN; +- } +- +- /* Column address */ +- *(cb_addr + ((*index)++)) = set_column_address; +- *(cb_addr + ((*index)++)) = rect->x >> 8; +- *(cb_addr + ((*index)++)) = rect->x; +- *(cb_addr + ((*index)++)) = (rect->x + rect->width - 1) >> 8; +- *(cb_addr + ((*index)++)) = (rect->x + rect->width - 1); +- +- *index = 8; +- +- /* Page address */ +- *(cb_addr + ((*index)++)) = set_page_addr; +- *(cb_addr + ((*index)++)) = rect->y >> 8; +- *(cb_addr + ((*index)++)) = rect->y; +- *(cb_addr + ((*index)++)) = (rect->y + rect->height - 1) >> 8; +- *(cb_addr + ((*index)++)) = (rect->y + rect->height - 1); +- +- *index = 16; +- +- /*write memory*/ +- *(cb_addr + ((*index)++)) = write_mem_start; +- +- return 0; +-} +- +-static int mdfld_dbi_flush_cb(struct mdfld_dsi_dbi_output *dbi_output, int pipe) +-{ +- u32 cmd_phy = dbi_output->dbi_cb_phy; +- u32 *index = &dbi_output->cb_write; +- int reg_offset = pipe ? MIPIC_REG_OFFSET : 0; +- struct drm_device *dev = dbi_output->dev; +- +- if (*index == 0 || !dbi_output) +- return 0; +- +- REG_WRITE((MIPIA_CMD_LEN_REG + reg_offset), 0x010505); +- REG_WRITE((MIPIA_CMD_ADD_REG + reg_offset), cmd_phy | 3); +- +- *index = 0; +- +- /* FIXME: unlock command buffer */ +- spin_unlock(&dbi_output->cb_lock); +- return 0; +-} +- +-static int mdfld_dpu_update_pipe(struct mdfld_dsi_dbi_output *dbi_output, +- struct mdfld_dbi_dpu_info *dpu_info, int pipe) +-{ +- struct drm_device *dev = dbi_output->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- mdfld_plane_t cursor_plane = MDFLD_CURSORA; +- mdfld_plane_t fb_plane = MDFLD_PLANEA; +- mdfld_plane_t overlay_plane = MDFLD_OVERLAYA; +- int ret = 0; +- u32 plane_mask = MDFLD_PIPEA_PLANE_MASK; +- +- /* Damaged rects on this pipe */ +- if (pipe) { +- cursor_plane = MDFLD_CURSORC; +- fb_plane = MDFLD_PLANEC; +- overlay_plane = MDFLD_OVERLAYC; +- plane_mask = MDFLD_PIPEC_PLANE_MASK; +- } +- +- /*update cursor which assigned to @pipe*/ +- if (dpu_info->pending & (1 << cursor_plane)) +- mdfld_dpu_cursor_plane_flush(dpu_info, cursor_plane); +- +- /*update fb which assigned to @pipe*/ +- if (dpu_info->pending & (1 << fb_plane)) +- mdfld_dpu_fb_plane_flush(dpu_info, fb_plane); +- +- /* TODO: update overlay */ +- if (dpu_info->pending & (1 << overlay_plane)) +- mdfld_dpu_overlay_plane_flush(dpu_info, overlay_plane); +- +- /* Flush damage area to panel fb */ +- if (dpu_info->pending & plane_mask) { +- ret = mdfld_dbi_prepare_cb(dbi_output, dpu_info, pipe); +- /* +- * TODO: remove b_dsr_enable later, +- * added it so that text console could boot smoothly +- */ +- /* Clean pending flags on this pipe */ +- if (!ret && dev_priv->dsr_enable) { +- dpu_info->pending &= ~plane_mask; +- /* Reset overlay pipe damage rect */ +- mdfld_dpu_init_damage(dpu_info, pipe); +- } +- } +- return ret; +-} +- +-static int mdfld_dpu_update_fb(struct drm_device *dev) +-{ +- struct drm_crtc *crtc; +- struct psb_intel_crtc *psb_crtc; +- struct mdfld_dsi_dbi_output **dbi_output; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; +- bool pipe_updated[2]; +- unsigned long irq_flags; +- u32 dpll_reg = MRST_DPLL_A; +- u32 dspcntr_reg = DSPACNTR; +- u32 pipeconf_reg = PIPEACONF; +- u32 dsplinoff_reg = DSPALINOFF; +- u32 dspsurf_reg = DSPASURF; +- u32 mipi_state_reg = MIPIA_INTR_STAT_REG; +- u32 reg_offset = 0; +- int pipe; +- int i; +- int ret; +- +- dbi_output = dpu_info->dbi_outputs; +- pipe_updated[0] = pipe_updated[1] = false; +- +- if (!gma_power_begin(dev, true)) +- return -EAGAIN; +- +- /* Try to prevent any new damage reports */ +- if (!spin_trylock_irqsave(&dpu_info->dpu_update_lock, irq_flags)) +- return -EAGAIN; +- +- for (i = 0; i < dpu_info->dbi_output_num; i++) { +- crtc = dbi_output[i]->base.base.crtc; +- psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; +- +- pipe = dbi_output[i]->channel_num ? 2 : 0; +- +- if (pipe == 2) { +- dspcntr_reg = DSPCCNTR; +- pipeconf_reg = PIPECCONF; +- dsplinoff_reg = DSPCLINOFF; +- dspsurf_reg = DSPCSURF; +- reg_offset = MIPIC_REG_OFFSET; +- } +- +- if (!(REG_READ((MIPIA_GEN_FIFO_STAT_REG + reg_offset)) +- & (1 << 27)) || +- !(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) || +- !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) || +- !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) { +- dev_err(dev->dev, +- "DBI FIFO is busy, DSI %d state %x\n", +- pipe, +- REG_READ(mipi_state_reg + reg_offset)); +- continue; +- } +- +- /* +- * If DBI output is in a exclusive state then the pipe +- * change won't be updated +- */ +- if (dbi_output[i]->dbi_panel_on && +- !(dbi_output[i]->mode_flags & MODE_SETTING_ON_GOING) && +- !(psb_crtc && +- psb_crtc->mode_flags & MODE_SETTING_ON_GOING) && +- !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) { +- ret = mdfld_dpu_update_pipe(dbi_output[i], +- dpu_info, dbi_output[i]->channel_num ? 2 : 0); +- if (!ret) +- pipe_updated[i] = true; +- } +- } +- +- for (i = 0; i < dpu_info->dbi_output_num; i++) +- if (pipe_updated[i]) +- mdfld_dbi_flush_cb(dbi_output[i], +- dbi_output[i]->channel_num ? 2 : 0); +- +- spin_unlock_irqrestore(&dpu_info->dpu_update_lock, irq_flags); +- gma_power_end(dev); +- return 0; +-} +- +-static int __mdfld_dbi_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output, +- int pipe) +-{ +- struct drm_device *dev = dbi_output->dev; +- struct drm_crtc *crtc = dbi_output->base.base.crtc; +- struct psb_intel_crtc *psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) +- : NULL; +- u32 reg_val; +- u32 dpll_reg = MRST_DPLL_A; +- u32 pipeconf_reg = PIPEACONF; +- u32 dspcntr_reg = DSPACNTR; +- u32 dspbase_reg = DSPABASE; +- u32 dspsurf_reg = DSPASURF; +- u32 reg_offset = 0; +- +- if (!dbi_output) +- return 0; +- +- /* If mode setting on-going, back off */ +- if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || +- (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) +- return -EAGAIN; +- +- if (pipe == 2) { +- dpll_reg = MRST_DPLL_A; +- pipeconf_reg = PIPECCONF; +- dspcntr_reg = DSPCCNTR; +- dspbase_reg = MDFLD_DSPCBASE; +- dspsurf_reg = DSPCSURF; +- +- reg_offset = MIPIC_REG_OFFSET; +- } +- +- if (!gma_power_begin(dev, true)) +- return -EAGAIN; +- +- /* Enable DPLL */ +- reg_val = REG_READ(dpll_reg); +- if (!(reg_val & DPLL_VCO_ENABLE)) { +- +- if (reg_val & MDFLD_PWR_GATE_EN) { +- reg_val &= ~MDFLD_PWR_GATE_EN; +- REG_WRITE(dpll_reg, reg_val); +- REG_READ(dpll_reg); +- udelay(500); +- } +- +- reg_val |= DPLL_VCO_ENABLE; +- REG_WRITE(dpll_reg, reg_val); +- REG_READ(dpll_reg); +- udelay(500); +- +- /* FIXME: add timeout */ +- while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) +- cpu_relax(); +- } +- +- /* Enable pipe */ +- reg_val = REG_READ(pipeconf_reg); +- if (!(reg_val & PIPEACONF_ENABLE)) { +- reg_val |= PIPEACONF_ENABLE; +- REG_WRITE(pipeconf_reg, reg_val); +- REG_READ(pipeconf_reg); +- udelay(500); +- mdfldWaitForPipeEnable(dev, pipe); +- } +- +- /* Enable plane */ +- reg_val = REG_READ(dspcntr_reg); +- if (!(reg_val & DISPLAY_PLANE_ENABLE)) { +- reg_val |= DISPLAY_PLANE_ENABLE; +- REG_WRITE(dspcntr_reg, reg_val); +- REG_READ(dspcntr_reg); +- udelay(500); +- } +- +- gma_power_end(dev); +- +- /* Clean IN_DSR flag */ +- dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; +- +- return 0; +-} +- +-int mdfld_dpu_exit_dsr(struct drm_device *dev) +-{ +- struct mdfld_dsi_dbi_output **dbi_output; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; +- int i; +- int pipe; +- +- dbi_output = dpu_info->dbi_outputs; +- +- for (i = 0; i < dpu_info->dbi_output_num; i++) { +- /* If this output is not in DSR mode, don't call exit dsr */ +- if (dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR) +- __mdfld_dbi_exit_dsr(dbi_output[i], +- dbi_output[i]->channel_num ? 2 : 0); +- } +- +- /* Enable TE interrupt */ +- for (i = 0; i < dpu_info->dbi_output_num; i++) { +- /* If this output is not in DSR mode, don't call exit dsr */ +- pipe = dbi_output[i]->channel_num ? 2 : 0; +- if (dbi_output[i]->dbi_panel_on && pipe) { +- mdfld_disable_te(dev, 0); +- mdfld_enable_te(dev, 2); +- } else if (dbi_output[i]->dbi_panel_on && !pipe) { +- mdfld_disable_te(dev, 2); +- mdfld_enable_te(dev, 0); +- } +- } +- return 0; +-} +- +-static int mdfld_dpu_enter_dsr(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; +- struct mdfld_dsi_dbi_output **dbi_output; +- int i; +- +- dbi_output = dpu_info->dbi_outputs; +- +- for (i = 0; i < dpu_info->dbi_output_num; i++) { +- /* If output is off or already in DSR state, don't re-enter */ +- if (dbi_output[i]->dbi_panel_on && +- !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) { +- mdfld_dsi_dbi_enter_dsr(dbi_output[i], +- dbi_output[i]->channel_num ? 2 : 0); +- } +- } +- +- return 0; +-} +- +-static void mdfld_dbi_dpu_timer_func(unsigned long data) +-{ +- struct drm_device *dev = (struct drm_device *)data; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; +- struct timer_list *dpu_timer = &dpu_info->dpu_timer; +- unsigned long flags; +- +- if (dpu_info->pending) { +- dpu_info->idle_count = 0; +- /* Update panel fb with damaged area */ +- mdfld_dpu_update_fb(dev); +- } else { +- dpu_info->idle_count++; +- } +- +- if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) { +- mdfld_dpu_enter_dsr(dev); +- /* Stop timer by return */ +- return; +- } +- +- spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags); +- if (!timer_pending(dpu_timer)) { +- dpu_timer->expires = jiffies + MDFLD_DSR_DELAY; +- add_timer(dpu_timer); +- } +- spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags); +-} +- +-void mdfld_dpu_update_panel(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; +- +- if (dpu_info->pending) { +- dpu_info->idle_count = 0; +- +- /*update panel fb with damaged area*/ +- mdfld_dpu_update_fb(dev); +- } else { +- dpu_info->idle_count++; +- } +- +- if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) { +- /*enter dsr*/ +- mdfld_dpu_enter_dsr(dev); +- } +-} +- +-static int mdfld_dbi_dpu_timer_init(struct drm_device *dev, +- struct mdfld_dbi_dpu_info *dpu_info) +-{ +- struct timer_list *dpu_timer = &dpu_info->dpu_timer; +- unsigned long flags; +- +- spin_lock_init(&dpu_info->dpu_timer_lock); +- spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags); +- +- init_timer(dpu_timer); +- +- dpu_timer->data = (unsigned long)dev; +- dpu_timer->function = mdfld_dbi_dpu_timer_func; +- dpu_timer->expires = jiffies + MDFLD_DSR_DELAY; +- +- spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags); +- +- return 0; +-} +- +-void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info) +-{ +- struct timer_list *dpu_timer = &dpu_info->dpu_timer; +- unsigned long flags; +- +- spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags); +- if (!timer_pending(dpu_timer)) { +- dpu_timer->expires = jiffies + MDFLD_DSR_DELAY; +- add_timer(dpu_timer); +- } +- spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags); +-} +- +-int mdfld_dbi_dpu_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; +- +- if (!dpu_info || IS_ERR(dpu_info)) { +- dpu_info = kzalloc(sizeof(struct mdfld_dbi_dpu_info), +- GFP_KERNEL); +- if (!dpu_info) { +- DRM_ERROR("No memory\n"); +- return -ENOMEM; +- } +- dev_priv->dbi_dpu_info = dpu_info; +- } +- +- dpu_info->dev = dev; +- +- dpu_info->cursors[0].size = MDFLD_CURSOR_SIZE; +- dpu_info->cursors[1].size = MDFLD_CURSOR_SIZE; +- +- /*init dpu_update_lock*/ +- spin_lock_init(&dpu_info->dpu_update_lock); +- +- /*init dpu refresh timer*/ +- mdfld_dbi_dpu_timer_init(dev, dpu_info); +- +- /*init pipe damage area*/ +- mdfld_dpu_init_damage(dpu_info, 0); +- mdfld_dpu_init_damage(dpu_info, 2); +- +- return 0; +-} +- +-void mdfld_dbi_dpu_exit(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; +- +- if (!dpu_info) +- return; +- +- del_timer_sync(&dpu_info->dpu_timer); +- kfree(dpu_info); +- dev_priv->dbi_dpu_info = NULL; +-} +- +- +diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h +deleted file mode 100644 +index 42367ed..0000000 +--- a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h ++++ /dev/null +@@ -1,154 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * jim liu +- * Jackie Li +- */ +- +-#ifndef __MDFLD_DSI_DBI_DPU_H__ +-#define __MDFLD_DSI_DBI_DPU_H__ +- +-#include "mdfld_dsi_dbi.h" +- +-typedef enum { +- MDFLD_PLANEA, +- MDFLD_PLANEC, +- MDFLD_CURSORA, +- MDFLD_CURSORC, +- MDFLD_OVERLAYA, +- MDFLD_OVERLAYC, +- MDFLD_PLANE_NUM, +-} mdfld_plane_t; +- +-#define MDFLD_PIPEA_PLANE_MASK 0x15 +-#define MDFLD_PIPEC_PLANE_MASK 0x2A +- +-struct mdfld_cursor_info { +- int x, y; +- int size; +-}; +- +-#define MDFLD_CURSOR_SIZE 64 +- +-/* +- * enter DSR mode if screen has no update for 2 frames. +- */ +-#define MDFLD_MAX_IDLE_COUNT 2 +- +-struct mdfld_dbi_dpu_info { +- struct drm_device *dev; +- /* Lock */ +- spinlock_t dpu_update_lock; +- +- /* Cursor postion */ +- struct mdfld_cursor_info cursors[2]; +- +- /* Damaged area for each plane */ +- struct psb_drm_dpu_rect damaged_rects[MDFLD_PLANE_NUM]; +- +- /* Final damaged area */ +- struct psb_drm_dpu_rect damage_pipea; +- struct psb_drm_dpu_rect damage_pipec; +- +- /* Pending */ +- u32 pending; +- +- /* DPU timer */ +- struct timer_list dpu_timer; +- spinlock_t dpu_timer_lock; +- +- /* DPU idle count */ +- u32 idle_count; +- +- /* DSI outputs */ +- struct mdfld_dsi_dbi_output *dbi_outputs[2]; +- int dbi_output_num; +-}; +- +-static inline int mdfld_dpu_region_extent(struct psb_drm_dpu_rect *origin, +- struct psb_drm_dpu_rect *rect) +-{ +- int x1, y1, x2, y2; +- +- x1 = origin->x + origin->width; +- y1 = origin->y + origin->height; +- +- x2 = rect->x + rect->width; +- y2 = rect->y + rect->height; +- +- origin->x = min(origin->x, rect->x); +- origin->y = min(origin->y, rect->y); +- origin->width = max(x1, x2) - origin->x; +- origin->height = max(y1, y2) - origin->y; +- +- return 0; +-} +- +-static inline void mdfld_check_boundary(struct mdfld_dbi_dpu_info *dpu_info, +- struct psb_drm_dpu_rect *rect) +-{ +- if (rect->x < 0) +- rect->x = 0; +- if (rect->y < 0) +- rect->y = 0; +- +- if (rect->x + rect->width > 864) +- rect->width = 864 - rect->x; +- if (rect->y + rect->height > 480) +- rect->height = 480 - rect->height; +- +- if (!rect->width) +- rect->width = 1; +- if (!rect->height) +- rect->height = 1; +-} +- +-static inline void mdfld_dpu_init_damage(struct mdfld_dbi_dpu_info *dpu_info, +- int pipe) +-{ +- struct psb_drm_dpu_rect *rect; +- +- if (pipe == 0) +- rect = &dpu_info->damage_pipea; +- else +- rect = &dpu_info->damage_pipec; +- +- rect->x = 864; +- rect->y = 480; +- rect->width = -864; +- rect->height = -480; +-} +- +-extern int mdfld_dsi_dbi_dsr_off(struct drm_device *dev, +- struct psb_drm_dpu_rect *rect); +-extern int mdfld_dbi_dpu_report_damage(struct drm_device *dev, +- mdfld_plane_t plane, +- struct psb_drm_dpu_rect *rect); +-extern int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev); +-extern int mdfld_dpu_exit_dsr(struct drm_device *dev); +-extern void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info); +-extern int mdfld_dbi_dpu_init(struct drm_device *dev); +-extern void mdfld_dbi_dpu_exit(struct drm_device *dev); +-extern void mdfld_dpu_update_panel(struct drm_device *dev); +- +-#endif /*__MDFLD_DSI_DBI_DPU_H__*/ +diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.c b/drivers/staging/gma500/mdfld_dsi_dpi.c +deleted file mode 100644 +index e685f12..0000000 +--- a/drivers/staging/gma500/mdfld_dsi_dpi.c ++++ /dev/null +@@ -1,805 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * jim liu +- * Jackie Li +- */ +- +-#include "mdfld_dsi_dpi.h" +-#include "mdfld_output.h" +-#include "mdfld_dsi_pkg_sender.h" +- +- +-static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe) +-{ +- u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG; +- int timeout = 0; +- +- if (pipe == 2) +- gen_fifo_stat_reg += MIPIC_REG_OFFSET; +- +- udelay(500); +- +- /* This will time out after approximately 2+ seconds */ +- while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) { +- udelay(100); +- timeout++; +- } +- +- if (timeout == 20000) +- dev_warn(dev->dev, "MIPI: HS Data FIFO was never cleared!\n"); +-} +- +-static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe) +-{ +- u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG; +- int timeout = 0; +- +- if (pipe == 2) +- gen_fifo_stat_reg += MIPIC_REG_OFFSET; +- +- udelay(500); +- +- /* This will time out after approximately 2+ seconds */ +- while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_CTRL_FULL)) { +- udelay(100); +- timeout++; +- } +- if (timeout == 20000) +- dev_warn(dev->dev, "MIPI: HS CMD FIFO was never cleared!\n"); +-} +- +-static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe) +-{ +- u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG; +- int timeout = 0; +- +- if (pipe == 2) +- gen_fifo_stat_reg += MIPIC_REG_OFFSET; +- +- udelay(500); +- +- /* This will time out after approximately 2+ seconds */ +- while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & DPI_FIFO_EMPTY) +- != DPI_FIFO_EMPTY)) { +- udelay(100); +- timeout++; +- } +- +- if (timeout == 20000) +- dev_warn(dev->dev, "MIPI: DPI FIFO was never cleared!\n"); +-} +- +-static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe) +-{ +- u32 intr_stat_reg = MIPIA_INTR_STAT_REG; +- int timeout = 0; +- +- if (pipe == 2) +- intr_stat_reg += MIPIC_REG_OFFSET; +- +- udelay(500); +- +- /* This will time out after approximately 2+ seconds */ +- while ((timeout < 20000) && (!(REG_READ(intr_stat_reg) & DSI_INTR_STATE_SPL_PKG_SENT))) { +- udelay(100); +- timeout++; +- } +- +- if (timeout == 20000) +- dev_warn(dev->dev, "MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n"); +-} +- +- +-/* ************************************************************************* *\ +- * FUNCTION: mdfld_dsi_tpo_ic_init +- * +- * DESCRIPTION: This function is called only by mrst_dsi_mode_set and +- * restore_display_registers. since this function does not +- * acquire the mutex, it is important that the calling function +- * does! +-\* ************************************************************************* */ +-void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe) +-{ +- struct drm_device *dev = dsi_config->dev; +- u32 dcsChannelNumber = dsi_config->channel_num; +- u32 gen_data_reg = MIPIA_HS_GEN_DATA_REG; +- u32 gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG; +- u32 gen_ctrl_val = GEN_LONG_WRITE; +- +- if (pipe == 2) { +- gen_data_reg = HS_GEN_DATA_REG + MIPIC_REG_OFFSET; +- gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET; +- } +- +- gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS; +- +- /* Flip page order */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x00008036); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS)); +- +- /* 0xF0 */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x005a5af0); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); +- +- /* Write protection key */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x005a5af1); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); +- +- /* 0xFC */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x005a5afc); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); +- +- /* 0xB7 */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x770000b7); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x00000044); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS)); +- +- /* 0xB6 */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x000a0ab6); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); +- +- /* 0xF2 */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x081010f2); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x4a070708); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x000000c5); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); +- +- /* 0xF8 */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x024003f8); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x01030a04); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x0e020220); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x00000004); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS)); +- +- /* 0xE2 */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x398fc3e2); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x0000916f); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS)); +- +- /* 0xB0 */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x000000b0); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS)); +- +- /* 0xF4 */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x240242f4); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x78ee2002); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x2a071050); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x507fee10); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x10300710); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS)); +- +- /* 0xBA */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x19fe07ba); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x101c0a31); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x00000010); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); +- +- /* 0xBB */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x28ff07bb); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x24280a31); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x00000034); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); +- +- /* 0xFB */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x535d05fb); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x1b1a2130); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x221e180e); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x131d2120); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x535d0508); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x1c1a2131); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x231f160d); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x111b2220); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x535c2008); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x1f1d2433); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x2c251a10); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x2c34372d); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x00000023); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS)); +- +- /* 0xFA */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x525c0bfa); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x1c1c232f); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x2623190e); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x18212625); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x545d0d0e); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x1e1d2333); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x26231a10); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x1a222725); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x545d280f); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x21202635); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x31292013); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x31393d33); +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x00000029); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS)); +- +- /* Set DM */ +- mdfld_wait_for_HS_DATA_FIFO(dev, pipe); +- REG_WRITE(gen_data_reg, 0x000100f7); +- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); +- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); +-} +- +-static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count, +- int num_lane, int bpp) +-{ +- return (u16)((pixel_clock_count * bpp) / (num_lane * 8)); +-} +- +-/* +- * Calculate the dpi time basing on a given drm mode @mode +- * return 0 on success. +- * FIXME: I was using proposed mode value for calculation, may need to +- * use crtc mode values later +- */ +-int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, +- struct mdfld_dsi_dpi_timing *dpi_timing, +- int num_lane, int bpp) +-{ +- int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive; +- int pclk_vsync, pclk_vfp, pclk_vbp, pclk_vactive; +- +- if(!mode || !dpi_timing) { +- DRM_ERROR("Invalid parameter\n"); +- return -EINVAL; +- } +- +- pclk_hactive = mode->hdisplay; +- pclk_hfp = mode->hsync_start - mode->hdisplay; +- pclk_hsync = mode->hsync_end - mode->hsync_start; +- pclk_hbp = mode->htotal - mode->hsync_end; +- +- pclk_vactive = mode->vdisplay; +- pclk_vfp = mode->vsync_start - mode->vdisplay; +- pclk_vsync = mode->vsync_end - mode->vsync_start; +- pclk_vbp = mode->vtotal - mode->vsync_end; +- +- /* +- * byte clock counts were calculated by following formula +- * bclock_count = pclk_count * bpp / num_lane / 8 +- */ +- dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hsync, num_lane, bpp); +- dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hbp, num_lane, bpp); +- dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hfp, num_lane, bpp); +- dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hactive, num_lane, bpp); +- dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vsync, num_lane, bpp); +- dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vbp, num_lane, bpp); +- dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vfp, num_lane, bpp); +- +- return 0; +-} +- +-void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe) +-{ +- struct drm_device *dev = dsi_config->dev; +- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; +- int lane_count = dsi_config->lane_count; +- struct mdfld_dsi_dpi_timing dpi_timing; +- struct drm_display_mode *mode = dsi_config->mode; +- u32 val = 0; +- +- /*un-ready device*/ +- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); +- +- /*init dsi adapter before kicking off*/ +- REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); +- +- /*enable all interrupts*/ +- REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); +- +- +- /*set up func_prg*/ +- val |= lane_count; +- val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET; +- +- switch(dsi_config->bpp) { +- case 16: +- val |= DSI_DPI_COLOR_FORMAT_RGB565; +- break; +- case 18: +- val |= DSI_DPI_COLOR_FORMAT_RGB666; +- break; +- case 24: +- val |= DSI_DPI_COLOR_FORMAT_RGB888; +- break; +- default: +- DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp); +- } +- REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); +- +- REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), +- (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK); +- REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK); +- +- /*max value: 20 clock cycles of txclkesc*/ +- REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK); +- +- /*min 21 txclkesc, max: ffffh*/ +- REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK); +- +- REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay); +- +- /*set DPI timing registers*/ +- mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp); +- +- REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); +- REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); +- REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); +- REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); +- REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); +- REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); +- REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); +- +- REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); +- +- /*min: 7d0 max: 4e20*/ +- REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0); +- +- /*set up video mode*/ +- val = 0; +- val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE; +- REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val); +- +- REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); +- +- REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); +- +- /*TODO: figure out how to setup these registers*/ +- REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); +- +- REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14); +- /*set device ready*/ +- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); +-} +- +-void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe) +-{ +- struct drm_device *dev = output->dev; +- u32 reg_offset = 0; +- +- if(output->panel_on) +- return; +- +- if(pipe) +- reg_offset = MIPIC_REG_OFFSET; +- +- /* clear special packet sent bit */ +- if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { +- REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT); +- } +- +- /*send turn on package*/ +- REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON); +- +- /*wait for SPL_PKG_SENT interrupt*/ +- mdfld_wait_for_SPL_PKG_SENT(dev, pipe); +- +- if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { +- REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT); +- } +- +- output->panel_on = 1; +- +- /* FIXME the following is disabled to WA the X slow start issue for TMD panel */ +- /* if(pipe == 2) */ +- /* dev_priv->dpi_panel_on2 = true; */ +- /* else if (pipe == 0) */ +- /* dev_priv->dpi_panel_on = true; */ +-} +- +-static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pipe) +-{ +- struct drm_device *dev = output->dev; +- u32 reg_offset = 0; +- +- /*if output is on, or mode setting didn't happen, ignore this*/ +- if((!output->panel_on) || output->first_boot) { +- output->first_boot = 0; +- return; +- } +- +- if(pipe) +- reg_offset = MIPIC_REG_OFFSET; +- +- /* Wait for dpi fifo to empty */ +- mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe); +- +- /* Clear the special packet interrupt bit if set */ +- if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { +- REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT); +- } +- +- if(REG_READ(MIPIA_DPI_CONTROL_REG + reg_offset) == DSI_DPI_CTRL_HS_SHUTDOWN) { +- dev_warn(dev->dev, "try to send the same package again, abort!"); +- goto shutdown_out; +- } +- +- REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN); +- +-shutdown_out: +- output->panel_on = 0; +- output->first_boot = 0; +- +- /* FIXME the following is disabled to WA the X slow start issue for TMD panel */ +- /* if(pipe == 2) */ +- /* dev_priv->dpi_panel_on2 = false; */ +- /* else if (pipe == 0) */ +- /* dev_priv->dpi_panel_on = false; */ +- /* #ifdef CONFIG_PM_RUNTIME*/ +- /* if (drm_psb_ospm && !enable_gfx_rtpm) { */ +- /* pm_runtime_allow(&gpDrmDevice->pdev->dev); */ +- /* schedule_delayed_work(&dev_priv->rtpm_work, 30 * 1000); */ +- /* } */ +- /*if (enable_gfx_rtpm) */ +- /* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */ +- /* #endif */ +-} +- +-void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) +-{ +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); +- struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); +- int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); +- struct drm_device *dev = dsi_config->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 mipi_reg = MIPI; +- u32 pipeconf_reg = PIPEACONF; +- +- if(pipe) { +- mipi_reg = MIPI_C; +- pipeconf_reg = PIPECCONF; +- } +- +- /* Start up display island if it was shutdown */ +- if (!gma_power_begin(dev, true)) +- return; +- +- if(on) { +- if (mdfld_get_panel_type(dev, pipe) == TMD_VID){ +- mdfld_dsi_dpi_turn_on(dpi_output, pipe); +- } else { +- /* Enable mipi port */ +- REG_WRITE(mipi_reg, (REG_READ(mipi_reg) | (1 << 31))); +- REG_READ(mipi_reg); +- +- mdfld_dsi_dpi_turn_on(dpi_output, pipe); +- mdfld_dsi_tpo_ic_init(dsi_config, pipe); +- } +- +- if(pipe == 2) { +- dev_priv->dpi_panel_on2 = true; +- } +- else { +- dev_priv->dpi_panel_on = true; +- } +- +- } else { +- if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { +- mdfld_dsi_dpi_shut_down(dpi_output, pipe); +- } else { +- mdfld_dsi_dpi_shut_down(dpi_output, pipe); +- /* Disable mipi port */ +- REG_WRITE(mipi_reg, (REG_READ(mipi_reg) & ~(1<<31))); +- REG_READ(mipi_reg); +- } +- +- if(pipe == 2) +- dev_priv->dpi_panel_on2 = false; +- else +- dev_priv->dpi_panel_on = false; +- } +- gma_power_end(dev); +-} +- +-void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode) +-{ +- dev_dbg(encoder->dev->dev, "DPMS %s\n", +- (mode == DRM_MODE_DPMS_ON ? "on":"off")); +- +- if (mode == DRM_MODE_DPMS_ON) +- mdfld_dsi_dpi_set_power(encoder, true); +- else { +- mdfld_dsi_dpi_set_power(encoder, false); +-#if 0 /* FIXME */ +-#ifdef CONFIG_PM_RUNTIME +- if (enable_gfx_rtpm) +- pm_schedule_suspend(&gpDrmDevice->pdev->dev, gfxrtdelay); +-#endif +-#endif +- } +-} +- +-bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); +- struct drm_display_mode *fixed_mode = dsi_config->fixed_mode; +- +- if(fixed_mode) { +- adjusted_mode->hdisplay = fixed_mode->hdisplay; +- adjusted_mode->hsync_start = fixed_mode->hsync_start; +- adjusted_mode->hsync_end = fixed_mode->hsync_end; +- adjusted_mode->htotal = fixed_mode->htotal; +- adjusted_mode->vdisplay = fixed_mode->vdisplay; +- adjusted_mode->vsync_start = fixed_mode->vsync_start; +- adjusted_mode->vsync_end = fixed_mode->vsync_end; +- adjusted_mode->vtotal = fixed_mode->vtotal; +- adjusted_mode->clock = fixed_mode->clock; +- drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); +- } +- +- return true; +-} +- +-void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder) +-{ +- mdfld_dsi_dpi_set_power(encoder, false); +-} +- +-void mdfld_dsi_dpi_commit(struct drm_encoder *encoder) +-{ +- mdfld_dsi_dpi_set_power(encoder, true); +-} +- +-void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); +- struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); +- struct drm_device *dev = dsi_config->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); +- +- u32 pipeconf_reg = PIPEACONF; +- u32 dspcntr_reg = DSPACNTR; +- u32 mipi_reg = MIPI; +- u32 reg_offset = 0; +- +- u32 pipeconf = dev_priv->pipeconf; +- u32 dspcntr = dev_priv->dspcntr; +- u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; +- +- dev_dbg(dev->dev, "set mode %dx%d on pipe %d\n", +- mode->hdisplay, mode->vdisplay, pipe); +- +- if(pipe) { +- pipeconf_reg = PIPECCONF; +- dspcntr_reg = DSPCCNTR; +- mipi_reg = MIPI_C; +- reg_offset = MIPIC_REG_OFFSET; +- } else { +- mipi |= 2; +- } +- +- if (!gma_power_begin(dev, true)) +- return; +- +- /* Set up mipi port FIXME: do at init time */ +- REG_WRITE(mipi_reg, mipi); +- REG_READ(mipi_reg); +- +- /* Set up DSI controller DPI interface */ +- mdfld_dsi_dpi_controller_init(dsi_config, pipe); +- +- if (mdfld_get_panel_type(dev, pipe) != TMD_VID) { +- /* Turn on DPI interface */ +- mdfld_dsi_dpi_turn_on(dpi_output, pipe); +- } +- +- /* Set up pipe */ +- REG_WRITE(pipeconf_reg, pipeconf); +- REG_READ(pipeconf_reg); +- +- /* Set up display plane */ +- REG_WRITE(dspcntr_reg, dspcntr); +- REG_READ(dspcntr_reg); +- +- msleep(20); /* FIXME: this should wait for vblank */ +- +- dev_dbg(dev->dev, "State %x, power %d\n", +- REG_READ(MIPIA_INTR_STAT_REG + reg_offset), +- dpi_output->panel_on); +- +- if (mdfld_get_panel_type(dev, pipe) != TMD_VID) { +- /* Init driver ic */ +- mdfld_dsi_tpo_ic_init(dsi_config, pipe); +- /* Init backlight */ +- mdfld_dsi_brightness_init(dsi_config, pipe); +- } +- gma_power_end(dev); +-} +- +- +-/* +- * Init DSI DPI encoder. +- * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector +- * return pointer of newly allocated DPI encoder, NULL on error +- */ +-struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, +- struct mdfld_dsi_connector *dsi_connector, +- struct panel_funcs *p_funcs) +-{ +- struct mdfld_dsi_dpi_output *dpi_output = NULL; +- struct mdfld_dsi_config *dsi_config; +- struct drm_connector *connector = NULL; +- struct drm_encoder *encoder = NULL; +- struct drm_display_mode *fixed_mode = NULL; +- int pipe; +- u32 data; +- int ret; +- +- if (!dsi_connector || !p_funcs) { +- WARN_ON(1); +- return NULL; +- } +- +- dsi_config = mdfld_dsi_get_config(dsi_connector); +- pipe = dsi_connector->pipe; +- +- /* Panel hard-reset */ +- if (p_funcs->reset) { +- ret = p_funcs->reset(pipe); +- if (ret) { +- DRM_ERROR("Panel %d hard-reset failed\n", pipe); +- return NULL; +- } +- } +- +- /* Panel drvIC init */ +- if (p_funcs->drv_ic_init) +- p_funcs->drv_ic_init(dsi_config, pipe); +- +- /* Panel power mode detect */ +- ret = mdfld_dsi_get_power_mode(dsi_config, +- &data, +- MDFLD_DSI_LP_TRANSMISSION); +- if (ret) { +- DRM_ERROR("Panel %d get power mode failed\n", pipe); +- dsi_connector->status = connector_status_disconnected; +- } else { +- DRM_INFO("pipe %d power mode 0x%x\n", pipe, data); +- dsi_connector->status = connector_status_connected; +- } +- +- dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL); +- if(!dpi_output) { +- dev_err(dev->dev, "No memory for dsi_dpi_output\n"); +- return NULL; +- } +- +- if(dsi_connector->pipe) +- dpi_output->panel_on = 0; +- else +- dpi_output->panel_on = 0; +- +- dpi_output->dev = dev; +- dpi_output->p_funcs = p_funcs; +- dpi_output->first_boot = 1; +- +- /* Get fixed mode */ +- dsi_config = mdfld_dsi_get_config(dsi_connector); +- fixed_mode = dsi_config->fixed_mode; +- +- /* Create drm encoder object */ +- connector = &dsi_connector->base.base; +- encoder = &dpi_output->base.base; +- /* +- * On existing hardware this will be a panel of some form, +- * if future devices also have HDMI bridges this will need +- * revisiting +- */ +- drm_encoder_init(dev, +- encoder, +- p_funcs->encoder_funcs, +- DRM_MODE_ENCODER_LVDS); +- drm_encoder_helper_add(encoder, +- p_funcs->encoder_helper_funcs); +- +- /* Attach to given connector */ +- drm_mode_connector_attach_encoder(connector, encoder); +- +- /* Set possible crtcs and clones */ +- if(dsi_connector->pipe) { +- encoder->possible_crtcs = (1 << 2); +- encoder->possible_clones = (1 << 1); +- } else { +- encoder->possible_crtcs = (1 << 0); +- encoder->possible_clones = (1 << 0); +- } +- return &dpi_output->base; +-} +- +diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.h b/drivers/staging/gma500/mdfld_dsi_dpi.h +deleted file mode 100644 +index ed92d45..0000000 +--- a/drivers/staging/gma500/mdfld_dsi_dpi.h ++++ /dev/null +@@ -1,78 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * jim liu +- * Jackie Li +- */ +- +-#ifndef __MDFLD_DSI_DPI_H__ +-#define __MDFLD_DSI_DPI_H__ +- +-#include "mdfld_dsi_output.h" +-#include "mdfld_output.h" +- +-struct mdfld_dsi_dpi_timing { +- u16 hsync_count; +- u16 hbp_count; +- u16 hfp_count; +- u16 hactive_count; +- u16 vsync_count; +- u16 vbp_count; +- u16 vfp_count; +-}; +- +-struct mdfld_dsi_dpi_output { +- struct mdfld_dsi_encoder base; +- struct drm_device *dev; +- +- int panel_on; +- int first_boot; +- +- struct panel_funcs *p_funcs; +-}; +- +-#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder) \ +- container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base) +- +-extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, +- struct mdfld_dsi_dpi_timing *dpi_timing, +- int num_lane, int bpp); +-extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, +- struct mdfld_dsi_connector *dsi_connector, +- struct panel_funcs *p_funcs); +- +-/* Medfield DPI helper functions */ +-extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode); +-extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode); +-extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder); +-extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder); +-extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode); +-extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, +- int pipe); +-extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *si_config, +- int pipe); +-#endif /*__MDFLD_DSI_DPI_H__*/ +diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c +deleted file mode 100644 +index 3f979db..0000000 +--- a/drivers/staging/gma500/mdfld_dsi_output.c ++++ /dev/null +@@ -1,1014 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * jim liu +- * Jackie Li +- */ +- +-#include "mdfld_dsi_output.h" +-#include "mdfld_dsi_dbi.h" +-#include "mdfld_dsi_dpi.h" +-#include "mdfld_output.h" +-#include +-#include "mdfld_dsi_pkg_sender.h" +-#include +-#include +- +-#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100 +- +-static int CABC_control = 1; +-static int LABC_control = 1; +- +-module_param (CABC_control, int, 0644); +-module_param (LABC_control, int, 0644); +- +-/** +- * make these MCS command global +- * we don't need 'movl' everytime we send them. +- * FIXME: these datas were provided by OEM, we should get them from GCT. +- **/ +-static u32 mdfld_dbi_mcs_hysteresis[] = { +- 0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff, +- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, +- 0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff, +- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, +- 0x000000ff, +-}; +- +-static u32 mdfld_dbi_mcs_display_profile[] = { +- 0x50281450, 0x0000c882, 0x00000000, 0x00000000, +- 0x00000000, +-}; +- +-static u32 mdfld_dbi_mcs_kbbc_profile[] = { +- 0x00ffcc60, 0x00000000, 0x00000000, 0x00000000, +-}; +- +-static u32 mdfld_dbi_mcs_gamma_profile[] = { +- 0x81111158, 0x88888888, 0x88888888, +-}; +- +-/* +- * write hysteresis values. +- */ +-static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config *dsi_config, +- int pipe) +-{ +- struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); +- +- if(!sender) { +- WARN_ON(1); +- return; +- } +- mdfld_dsi_send_mcs_long_hs(sender, +- mdfld_dbi_mcs_hysteresis, +- 17, +- MDFLD_DSI_SEND_PACKAGE); +-} +- +-/* +- * write display profile values. +- */ +-static void mdfld_dsi_write_display_profile(struct mdfld_dsi_config *dsi_config, int pipe) +-{ +- struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); +- +- if(!sender) { +- WARN_ON(1); +- return; +- } +- mdfld_dsi_send_mcs_long_hs(sender, +- mdfld_dbi_mcs_display_profile, +- 5, +- MDFLD_DSI_SEND_PACKAGE); +-} +- +-/* +- * write KBBC profile values. +- */ +-static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config * dsi_config, int pipe) +-{ +- struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); +- +- if(!sender) { +- WARN_ON(1); +- return; +- } +- mdfld_dsi_send_mcs_long_hs(sender, +- mdfld_dbi_mcs_kbbc_profile, +- 4, +- MDFLD_DSI_SEND_PACKAGE); +-} +- +-/* +- * write gamma setting. +- */ +-static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config *dsi_config, int pipe) +-{ +- struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); +- +- if(!sender) { +- WARN_ON(1); +- return; +- } +- mdfld_dsi_send_mcs_long_hs(sender, +- mdfld_dbi_mcs_gamma_profile, +- 3, +- MDFLD_DSI_SEND_PACKAGE); +-} +- +-/* +- * Check and see if the generic control or data buffer is empty and ready. +- */ +-void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat) +-{ +- u32 GEN_BF_time_out_count = 0; +- +- /* Check MIPI Adatper command registers */ +- for (GEN_BF_time_out_count = 0; GEN_BF_time_out_count < GEN_FB_TIME_OUT; GEN_BF_time_out_count++) +- { +- if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat) +- break; +- udelay (100); +- } +- +- if (GEN_BF_time_out_count == GEN_FB_TIME_OUT) +- dev_err(dev->dev, +- "mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n", +- gen_fifo_stat_reg); +-} +- +-/* +- * Manage the DSI MIPI keyboard and display brightness. +- * FIXME: this is exported to OSPM code. should work out an specific +- * display interface to OSPM. +- */ +-void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe) +-{ +- struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); +- struct drm_device *dev = sender->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 gen_ctrl_val; +- +- if(!sender) { +- WARN_ON(1); +- return; +- } +- /* Set default display backlight value to 85% (0xd8)*/ +- mdfld_dsi_send_mcs_short_hs(sender, +- write_display_brightness, +- 0xd8, +- 1, +- MDFLD_DSI_SEND_PACKAGE); +- +- /* Set minimum brightness setting of CABC function to 20% (0x33)*/ +- mdfld_dsi_send_mcs_short_hs(sender, +- write_cabc_min_bright, +- 0x33, +- 1, +- MDFLD_DSI_SEND_PACKAGE); +- +- mdfld_dsi_write_hysteresis(dsi_config, pipe); +- mdfld_dsi_write_display_profile (dsi_config, pipe); +- mdfld_dsi_write_kbbc_profile (dsi_config, pipe); +- mdfld_dsi_write_gamma_setting (dsi_config, pipe); +- +- /* Enable backlight or/and LABC */ +- gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON; +- if (LABC_control == 1 || CABC_control == 1) +- gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO; +- +- if (LABC_control == 1) +- gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON; +- +- dev_priv->mipi_ctrl_display = gen_ctrl_val; +- +- mdfld_dsi_send_mcs_short_hs(sender, +- write_ctrl_display, +- (u8)gen_ctrl_val, +- 1, +- MDFLD_DSI_SEND_PACKAGE); +- +- if (CABC_control == 0) +- return; +- mdfld_dsi_send_mcs_short_hs(sender, +- write_ctrl_cabc, +- UI_IMAGE, +- 1, +- MDFLD_DSI_SEND_PACKAGE); +-} +- +-/* +- * Manage the mipi display brightness. +- * TODO: refine this interface later +- */ +-void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level) +-{ +- struct mdfld_dsi_pkg_sender *sender; +- struct drm_psb_private *dev_priv; +- struct mdfld_dsi_config *dsi_config; +- u32 gen_ctrl_val; +- int p_type; +- +- if (!dev || (pipe != 0 && pipe != 2)) { +- dev_err(dev->dev, "Invalid parameter\n"); +- return; +- } +- +- p_type = mdfld_get_panel_type(dev, 0); +- +- dev_priv = dev->dev_private; +- +- if(pipe) +- dsi_config = dev_priv->dsi_configs[1]; +- else +- dsi_config = dev_priv->dsi_configs[0]; +- +- sender = mdfld_dsi_get_pkg_sender(dsi_config); +- +- if(!sender) { +- WARN_ON(1); +- return; +- } +- +- gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff; +- +- dev_dbg(dev->dev, +- "pipe = %d, gen_ctrl_val = %d. \n", pipe, gen_ctrl_val); +- +- if(p_type == TMD_VID || p_type == TMD_CMD){ +- /* Set display backlight value */ +- mdfld_dsi_send_mcs_short_hs(sender, +- tmd_write_display_brightness, +- (u8)gen_ctrl_val, +- 1, +- MDFLD_DSI_SEND_PACKAGE); +- } else { +- /* Set display backlight value */ +- mdfld_dsi_send_mcs_short_hs(sender, +- write_display_brightness, +- (u8)gen_ctrl_val, +- 1, +- MDFLD_DSI_SEND_PACKAGE); +- +- +- /* Enable backlight control */ +- if (level == 0) +- gen_ctrl_val = 0; +- else +- gen_ctrl_val = dev_priv->mipi_ctrl_display; +- +- mdfld_dsi_send_mcs_short_hs(sender, +- write_ctrl_display, +- (u8)gen_ctrl_val, +- 1, +- MDFLD_DSI_SEND_PACKAGE); +- } +-} +- +-/* +- * shut down DSI controller +- */ +-void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pipe) +-{ +- struct drm_device * dev; +- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; +- int retry = 100; +- +- if (!dsi_config) { +- WARN_ON(1); +- return; +- } +- +- dev = dsi_config->dev; +- +- if (!gma_power_begin(dev, true)) { +- dev_err(dev->dev, "hw begin failed\n"); +- return; +- } +- +- if(!(REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY)) +- goto shutdown_out; +- +- /* Send shut down package, clean packet send bit first */ +- if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { +- REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), +- (REG_READ(MIPIA_INTR_STAT_REG + reg_offset) | DSI_INTR_STATE_SPL_PKG_SENT)); +- } +- +- /*send shut down package in HS*/ +- REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN); +- +- +- /* +- * make sure shut down is sent. +- * FIXME: add max retry counter +- */ +- while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) { +- retry--; +- +- if(!retry) { +- dev_err(dev->dev, "timeout\n"); +- break; +- } +- } +- +- /*sleep 1 ms to ensure shutdown finished*/ +- msleep(100); +- +- /*un-ready device*/ +- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), +- (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & ~DSI_DEVICE_READY)); +- +-shutdown_out: +- gma_power_end(dev); +-} +- +-void mdfld_dsi_controller_startup(struct mdfld_dsi_config * dsi_config, int pipe) +-{ +- struct drm_device * dev; +- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; +- int retry = 100; +- +- +- if (!dsi_config) { +- WARN_ON(1); +- return; +- } +- +- dev = dsi_config->dev; +- dev_dbg(dev->dev, "starting up DSI controller on pipe %d...\n", pipe); +- +- if (!gma_power_begin(dev, true)) { +- dev_err(dev->dev, "hw begin failed\n"); +- return; +- } +- +- if((REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY)) +- goto startup_out; +- +- /*if config DPI, turn on DPI interface*/ +- if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { +- if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { +- REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT); +- } +- +- REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON); +- +- /* +- * make sure shut down is sent. +- * FIXME: add max retry counter +- */ +- while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) { +- retry--; +- if(!retry) { +- dev_err(dev->dev, "timeout\n"); +- break; +- } +- } +- +- msleep(100); +- } +- +- /*set device ready*/ +- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), +- (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) | DSI_DEVICE_READY)); +- +-startup_out: +- gma_power_end(dev); +-} +- +- +-static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config, +- u8 dcs, +- u32 *data, +- u8 transmission) +-{ +- struct mdfld_dsi_pkg_sender *sender +- = mdfld_dsi_get_pkg_sender(dsi_config); +- +- if (!sender || !data) { +- DRM_ERROR("Invalid parameter\n"); +- return -EINVAL; +- } +- +- if (transmission == MDFLD_DSI_HS_TRANSMISSION) +- return mdfld_dsi_read_mcs_hs(sender, dcs, data, 1); +- else if (transmission == MDFLD_DSI_LP_TRANSMISSION) +- return mdfld_dsi_read_mcs_lp(sender, dcs, data, 1); +- else +- return -EINVAL; +-} +- +-int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, +- u32 *mode, +- u8 transmission) +-{ +- if (!dsi_config || !mode) { +- DRM_ERROR("Invalid parameter\n"); +- return -EINVAL; +- } +- +- return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, transmission); +-} +- +-int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config, +- u32 *result, +- u8 transmission) +-{ +- if (!dsi_config || !result) { +- DRM_ERROR("Invalid parameter\n"); +- return -EINVAL; +- } +- +- return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result, +- transmission); +-} +- +-/* +- * NOTE: this function was used by OSPM. +- * TODO: will be removed later, should work out display interfaces for OSPM +- */ +-void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe) +-{ +- if(!dsi_config || ((pipe != 0) && (pipe != 2))) { +- WARN_ON(1); +- return; +- } +- +- if(dsi_config->type) +- mdfld_dsi_dpi_controller_init(dsi_config, pipe); +- else +- mdfld_dsi_controller_dbi_init(dsi_config, pipe); +-} +- +-static void mdfld_dsi_connector_save(struct drm_connector * connector) +-{ +-} +- +-static void mdfld_dsi_connector_restore(struct drm_connector * connector) +-{ +-} +- +-static enum drm_connector_status mdfld_dsi_connector_detect(struct drm_connector * connector, bool force) +-{ +- struct psb_intel_output *psb_output +- = to_psb_intel_output(connector); +- struct mdfld_dsi_connector *dsi_connector +- = MDFLD_DSI_CONNECTOR(psb_output); +- return dsi_connector->status; +-} +- +-static int mdfld_dsi_connector_set_property(struct drm_connector *connector, +- struct drm_property *property, +- uint64_t value) +-{ +- struct drm_encoder *encoder = connector->encoder; +- +- if (!strcmp(property->name, "scaling mode") && encoder) { +- struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc); +- bool bTransitionFromToCentered; +- uint64_t curValue; +- +- if (!psb_crtc) +- goto set_prop_error; +- +- switch (value) { +- case DRM_MODE_SCALE_FULLSCREEN: +- break; +- case DRM_MODE_SCALE_NO_SCALE: +- break; +- case DRM_MODE_SCALE_ASPECT: +- break; +- default: +- goto set_prop_error; +- } +- +- if (drm_connector_property_get_value(connector, property, &curValue)) +- goto set_prop_error; +- +- if (curValue == value) +- goto set_prop_done; +- +- if (drm_connector_property_set_value(connector, property, value)) +- goto set_prop_error; +- +- bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) || +- (value == DRM_MODE_SCALE_NO_SCALE); +- +- if (psb_crtc->saved_mode.hdisplay != 0 && +- psb_crtc->saved_mode.vdisplay != 0) { +- if (bTransitionFromToCentered) { +- if (!drm_crtc_helper_set_mode(encoder->crtc, &psb_crtc->saved_mode, +- encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb)) +- goto set_prop_error; +- } else { +- struct drm_encoder_helper_funcs *pEncHFuncs = encoder->helper_private; +- pEncHFuncs->mode_set(encoder, &psb_crtc->saved_mode, +- &psb_crtc->saved_adjusted_mode); +- } +- } +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- } else if (!strcmp(property->name, "backlight") && encoder) { +- struct drm_psb_private *dev_priv = encoder->dev->dev_private; +- struct backlight_device *psb_bd = dev_priv->backlight_device; +- dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value); +- if (drm_connector_property_set_value(connector, property, value)) +- goto set_prop_error; +- else { +- dev_dbg(encoder->dev->dev, +- "set brightness to %d", (int)value); +- if (psb_bd) { +- psb_bd->props.brightness = value; +- backlight_update_status(psb_bd); +- } +- } +-#endif +- } +-set_prop_done: +- return 0; +-set_prop_error: +- return -1; +-} +- +-static void mdfld_dsi_connector_destroy(struct drm_connector *connector) +-{ +- struct psb_intel_output * psb_output = to_psb_intel_output(connector); +- struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output); +- struct mdfld_dsi_pkg_sender * sender; +- +- if(!dsi_connector) +- return; +- +- drm_sysfs_connector_remove(connector); +- drm_connector_cleanup(connector); +- +- sender = dsi_connector->pkg_sender; +- +- mdfld_dsi_pkg_sender_destroy(sender); +- +- kfree(dsi_connector); +-} +- +-static int mdfld_dsi_connector_get_modes(struct drm_connector * connector) +-{ +- struct psb_intel_output * psb_output = to_psb_intel_output(connector); +- struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output); +- struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector); +- struct drm_display_mode * fixed_mode = dsi_config->fixed_mode; +- struct drm_display_mode * dup_mode = NULL; +- struct drm_device * dev = connector->dev; +- +- connector->display_info.min_vfreq = 0; +- connector->display_info.max_vfreq = 200; +- connector->display_info.min_hfreq = 0; +- connector->display_info.max_hfreq = 200; +- +- if(fixed_mode) { +- dev_dbg(dev->dev, "fixed_mode %dx%d\n", +- fixed_mode->hdisplay, fixed_mode->vdisplay); +- +- dup_mode = drm_mode_duplicate(dev, fixed_mode); +- drm_mode_probed_add(connector, dup_mode); +- return 1; +- } +- dev_err(dev->dev, "Didn't get any modes!\n"); +- return 0; +-} +- +-static int mdfld_dsi_connector_mode_valid(struct drm_connector * connector, struct drm_display_mode * mode) +-{ +- struct psb_intel_output * psb_output = to_psb_intel_output(connector); +- struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output); +- struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector); +- struct drm_display_mode * fixed_mode = dsi_config->fixed_mode; +- +- dev_dbg(connector->dev->dev, "mode %p, fixed mode %p\n", +- mode, fixed_mode); +- +- if(mode->flags & DRM_MODE_FLAG_DBLSCAN) +- return MODE_NO_DBLESCAN; +- +- if(mode->flags & DRM_MODE_FLAG_INTERLACE) +- return MODE_NO_INTERLACE; +- +- /** +- * FIXME: current DC has no fitting unit, reject any mode setting request +- * will figure out a way to do up-scaling(pannel fitting) later. +- **/ +- if(fixed_mode) { +- if(mode->hdisplay != fixed_mode->hdisplay) +- return MODE_PANEL; +- +- if(mode->vdisplay != fixed_mode->vdisplay) +- return MODE_PANEL; +- } +- dev_dbg(connector->dev->dev, "mode ok\n"); +- +- return MODE_OK; +-} +- +-static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode) +-{ +-#ifdef CONFIG_PM_RUNTIME +- struct drm_device * dev = connector->dev; +- struct drm_psb_private * dev_priv = dev->dev_private; +- bool panel_on, panel_on2; +-#endif +- /* First, execute DPMS */ +- drm_helper_connector_dpms(connector, mode); +- +-#ifdef CONFIG_PM_RUNTIME +- if(mdfld_panel_dpi(dev)) { +- /* DPI panel */ +- panel_on = dev_priv->dpi_panel_on; +- panel_on2 = dev_priv->dpi_panel_on2; +- } else { +- /* DBI panel */ +- panel_on = dev_priv->dbi_panel_on; +- panel_on2 = dev_priv->dbi_panel_on2; +- } +- +- /* Then check all display panels + monitors status */ +- /* Make sure that the Display (B) sub-system status isn't i3 when +- * R/W the DC register, otherwise "Fabric error" issue would occur +- * during S0i3 state. */ +- if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL) +- & HDMIB_PORT_EN)) { +- /* Request rpm idle */ +- if(dev_priv->rpm_enabled) +- pm_request_idle(&dev->pdev->dev); +- } +- /* +- * if rpm wasn't enabled yet, try to allow it +- * FIXME: won't enable rpm for DPI since DPI +- * CRTC setting is a little messy now. +- * Enable it later! +- */ +-#if 0 +- if(!dev_priv->rpm_enabled && !mdfld_panel_dpi(dev)) +- ospm_runtime_pm_allow(dev); +-#endif +-#endif +-} +- +-static struct drm_encoder *mdfld_dsi_connector_best_encoder( +- struct drm_connector *connector) +-{ +- struct psb_intel_output * psb_output = to_psb_intel_output(connector); +- struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output); +- struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector); +- struct mdfld_dsi_encoder * encoder = NULL; +- +- if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) +- encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DBI]; +- else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) +- encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DPI]; +- +- dev_dbg(connector->dev->dev, "get encoder %p\n", encoder); +- +- if(!encoder) { +- dev_err(connector->dev->dev, +- "Invalid encoder for type %d\n", dsi_config->type); +- return NULL; +- } +- dsi_config->encoder = encoder; +- return &encoder->base; +-} +- +-/* DSI connector funcs */ +-static const struct drm_connector_funcs mdfld_dsi_connector_funcs = { +- .dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms, +- .save = mdfld_dsi_connector_save, +- .restore = mdfld_dsi_connector_restore, +- .detect = mdfld_dsi_connector_detect, +- .fill_modes = drm_helper_probe_single_connector_modes, +- .set_property = mdfld_dsi_connector_set_property, +- .destroy = mdfld_dsi_connector_destroy, +-}; +- +-/* DSI connector helper funcs */ +-static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs = { +- .get_modes = mdfld_dsi_connector_get_modes, +- .mode_valid = mdfld_dsi_connector_mode_valid, +- .best_encoder = mdfld_dsi_connector_best_encoder, +-}; +- +-static int mdfld_dsi_get_default_config(struct drm_device * dev, +- struct mdfld_dsi_config * config, int pipe) +-{ +- if(!dev || !config) { +- WARN_ON(1); +- return -EINVAL; +- } +- +- config->bpp = 24; +- config->type = mdfld_panel_dpi(dev); +- config->lane_count = 2; +- config->channel_num = 0; +- /*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/ +- if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { +- config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE; +- } else { +- config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE; +- } +- +- return 0; +-} +- +-/* +- * Returns the panel fixed mode from configuration. +- */ +-struct drm_display_mode * +-mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe) +-{ +- struct drm_device *dev = dsi_config->dev; +- struct drm_display_mode *mode; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; +- bool use_gct = false; +- +- mode = kzalloc(sizeof(*mode), GFP_KERNEL); +- if (!mode) { +- dev_err(dev->dev, "Out of memory for mode\n"); +- return NULL; +- } +- if (use_gct) { +- dev_dbg(dev->dev, "gct find MIPI panel.\n"); +- +- mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; +- mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; +- mode->hsync_start = mode->hdisplay + \ +- ((ti->hsync_offset_hi << 8) | \ +- ti->hsync_offset_lo); +- mode->hsync_end = mode->hsync_start + \ +- ((ti->hsync_pulse_width_hi << 8) | \ +- ti->hsync_pulse_width_lo); +- mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ +- ti->hblank_lo); +- mode->vsync_start = \ +- mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ +- ti->vsync_offset_lo); +- mode->vsync_end = \ +- mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ +- ti->vsync_pulse_width_lo); +- mode->vtotal = mode->vdisplay + \ +- ((ti->vblank_hi << 8) | ti->vblank_lo); +- mode->clock = ti->pixel_clock * 10; +- } else { +- if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { +- if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { +- mode->hdisplay = 480; +- mode->vdisplay = 854; +- mode->hsync_start = 487; +- mode->hsync_end = 490; +- mode->htotal = 499; +- mode->vsync_start = 861; +- mode->vsync_end = 865; +- mode->vtotal = 873; +- mode->clock = 33264; +- } else { +- mode->hdisplay = 864; +- mode->vdisplay = 480; +- mode->hsync_start = 873; +- mode->hsync_end = 876; +- mode->htotal = 887; +- mode->vsync_start = 487; +- mode->vsync_end = 490; +- mode->vtotal = 499; +- mode->clock = 33264; +- } +- } else if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) { +- mode->hdisplay = 864; +- mode->vdisplay = 480; +- mode->hsync_start = 872; +- mode->hsync_end = 876; +- mode->htotal = 884; +- mode->vsync_start = 482; +- mode->vsync_end = 494; +- mode->vtotal = 486; +- mode->clock = 25777; +- +- } +- } +- +- drm_mode_set_name(mode); +- drm_mode_set_crtcinfo(mode, 0); +- +- mode->type |= DRM_MODE_TYPE_PREFERRED; +- +- return mode; +-} +- +-int mdfld_dsi_panel_reset(int pipe) +-{ +- unsigned gpio; +- int ret = 0; +- +- switch (pipe) { +- case 0: +- gpio = 128; +- break; +- case 2: +- gpio = 34; +- break; +- default: +- DRM_ERROR("Invalid output\n"); +- return -EINVAL; +- } +- +- ret = gpio_request(gpio, "gfx"); +- if (ret) { +- DRM_ERROR("gpio_rqueset failed\n"); +- return ret; +- } +- +- ret = gpio_direction_output(gpio, 1); +- if (ret) { +- DRM_ERROR("gpio_direction_output failed\n"); +- goto gpio_error; +- } +- +- gpio_get_value(128); +- +-gpio_error: +- if (gpio_is_valid(gpio)) +- gpio_free(gpio); +- +- return ret; +-} +- +-/* +- * MIPI output init +- * @dev drm device +- * @pipe pipe number. 0 or 2 +- * @config +- * +- * Do the initialization of a MIPI output, including create DRM mode objects +- * initialization of DSI output on @pipe +- */ +-void mdfld_dsi_output_init(struct drm_device *dev, +- int pipe, +- struct mdfld_dsi_config *config, +- struct panel_funcs* p_cmd_funcs, +- struct panel_funcs* p_vid_funcs) +-{ +- struct mdfld_dsi_config * dsi_config; +- struct mdfld_dsi_connector * dsi_connector; +- struct psb_intel_output * psb_output; +- struct drm_connector * connector; +- struct mdfld_dsi_encoder * encoder; +- struct drm_psb_private * dev_priv = dev->dev_private; +- struct panel_info dsi_panel_info; +- u32 width_mm, height_mm; +- +- dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe); +- +- if(!dev || ((pipe != 0) && (pipe != 2))) { +- WARN_ON(1); +- return; +- } +- +- /*create a new connetor*/ +- dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL); +- if(!dsi_connector) { +- DRM_ERROR("No memory"); +- return; +- } +- +- dsi_connector->pipe = pipe; +- +- /*set DSI config*/ +- if(config) { +- dsi_config = config; +- } else { +- dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), GFP_KERNEL); +- if(!dsi_config) { +- dev_err(dev->dev, +- "cannot allocate memory for DSI config\n"); +- goto dsi_init_err0; +- } +- +- mdfld_dsi_get_default_config(dev, dsi_config, pipe); +- } +- +- dsi_connector->private = dsi_config; +- +- dsi_config->changed = 1; +- dsi_config->dev = dev; +- +- /* Init fixed mode basing on DSI config type */ +- if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) { +- dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev); +- if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info)) +- goto dsi_init_err0; +- } else if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { +- dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev); +- if(p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info)) +- goto dsi_init_err0; +- } +- +- width_mm = dsi_panel_info.width_mm; +- height_mm = dsi_panel_info.height_mm; +- +- dsi_config->mode = dsi_config->fixed_mode; +- dsi_config->connector = dsi_connector; +- +- if(!dsi_config->fixed_mode) { +- dev_err(dev->dev, "No pannel fixed mode was found\n"); +- goto dsi_init_err0; +- } +- +- if(pipe && dev_priv->dsi_configs[0]) { +- dsi_config->dvr_ic_inited = 0; +- dev_priv->dsi_configs[1] = dsi_config; +- } else if(pipe == 0) { +- dsi_config->dvr_ic_inited = 1; +- dev_priv->dsi_configs[0] = dsi_config; +- } else { +- dev_err(dev->dev, "Trying to init MIPI1 before MIPI0\n"); +- goto dsi_init_err0; +- } +- +- /*init drm connector object*/ +- psb_output = &dsi_connector->base; +- +- psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2; +- +- connector = &psb_output->base; +- /* Revisit type if MIPI/HDMI bridges ever appear on Medfield */ +- drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs, +- DRM_MODE_CONNECTOR_LVDS); +- drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs); +- +- connector->display_info.subpixel_order = SubPixelHorizontalRGB; +- connector->display_info.width_mm = width_mm; +- connector->display_info.height_mm = height_mm; +- connector->interlace_allowed = false; +- connector->doublescan_allowed = false; +- +- /* Attach properties */ +- drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN); +- drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL); +- +- /* Init DSI package sender on this output */ +- if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) { +- DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe); +- goto dsi_init_err0; +- } +- +- /* Init DBI & DPI encoders */ +- if (p_cmd_funcs) { +- encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs); +- if(!encoder) { +- dev_err(dev->dev, "Create DBI encoder failed\n"); +- goto dsi_init_err1; +- } +- encoder->private = dsi_config; +- dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder; +- } +- +- if(p_vid_funcs) { +- encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs); +- if(!encoder) { +- dev_err(dev->dev, "Create DPI encoder failed\n"); +- goto dsi_init_err1; +- } +- encoder->private = dsi_config; +- dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder; +- } +- +- drm_sysfs_connector_add(connector); +- return; +- +- /*TODO: add code to destroy outputs on error*/ +-dsi_init_err1: +- /*destroy sender*/ +- mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender); +- +- drm_connector_cleanup(connector); +- kfree(dsi_config->fixed_mode); +- kfree(dsi_config); +-dsi_init_err0: +- kfree(dsi_connector); +-} +diff --git a/drivers/staging/gma500/mdfld_dsi_output.h b/drivers/staging/gma500/mdfld_dsi_output.h +deleted file mode 100644 +index 4699267..0000000 +--- a/drivers/staging/gma500/mdfld_dsi_output.h ++++ /dev/null +@@ -1,138 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * jim liu +- * Jackie Li +- */ +- +-#ifndef __MDFLD_DSI_OUTPUT_H__ +-#define __MDFLD_DSI_OUTPUT_H__ +- +-#include +-#include +-#include +-#include +-#include +- +-#include "psb_drv.h" +-#include "psb_intel_drv.h" +-#include "psb_intel_reg.h" +-#include "power.h" +-#include "mdfld_output.h" +- +-#include +- +- +-static inline struct mdfld_dsi_config * +- mdfld_dsi_get_config(struct mdfld_dsi_connector *connector) +-{ +- if (!connector) +- return NULL; +- return (struct mdfld_dsi_config *)connector->private; +-} +- +-static inline void *mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config *config) +-{ +- struct mdfld_dsi_connector *dsi_connector; +- +- if (!config) +- return NULL; +- +- dsi_connector = config->connector; +- +- if (!dsi_connector) +- return NULL; +- +- return dsi_connector->pkg_sender; +-} +- +-static inline struct mdfld_dsi_config * +- mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder *encoder) +-{ +- if (!encoder) +- return NULL; +- return (struct mdfld_dsi_config *)encoder->private; +-} +- +-static inline struct mdfld_dsi_connector * +- mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder *encoder) +-{ +- struct mdfld_dsi_config *config; +- +- if (!encoder) +- return NULL; +- +- config = mdfld_dsi_encoder_get_config(encoder); +- if (!config) +- return NULL; +- +- return config->connector; +-} +- +-static inline void *mdfld_dsi_encoder_get_pkg_sender( +- struct mdfld_dsi_encoder *encoder) +-{ +- struct mdfld_dsi_config *dsi_config; +- +- dsi_config = mdfld_dsi_encoder_get_config(encoder); +- if (!dsi_config) +- return NULL; +- +- return mdfld_dsi_get_pkg_sender(dsi_config); +-} +- +-static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder *encoder) +-{ +- struct mdfld_dsi_connector *connector; +- +- if (!encoder) +- return -1; +- +- connector = mdfld_dsi_encoder_get_connector(encoder); +- if (!connector) +- return -1; +- +- return connector->pipe; +-} +- +-extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev, +- u32 gen_fifo_stat_reg, u32 fifo_stat); +-extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, +- int pipe); +-extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, +- int level); +-extern void mdfld_dsi_output_init(struct drm_device *dev, int pipe, +- struct mdfld_dsi_config *config, +- struct panel_funcs *p_cmd_funcs, +- struct panel_funcs *p_vid_funcs); +-extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config, +- int pipe); +-extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, +- u32 *mode, +- u8 transmission); +-extern int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config, +- u32 *result, +- u8 transmission); +-extern int mdfld_dsi_panel_reset(int pipe); +- +-#endif /*__MDFLD_DSI_OUTPUT_H__*/ +diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c b/drivers/staging/gma500/mdfld_dsi_pkg_sender.c +deleted file mode 100644 +index 9b96a5c..0000000 +--- a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c ++++ /dev/null +@@ -1,1484 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Jackie Li +- */ +- +-#include +- +-#include "mdfld_dsi_output.h" +-#include "mdfld_dsi_pkg_sender.h" +-#include "mdfld_dsi_dbi.h" +-#include "mdfld_dsi_dpi.h" +- +-#define MDFLD_DSI_DBI_FIFO_TIMEOUT 100 +-#define MDFLD_DSI_MAX_RETURN_PACKET_SIZE 512 +-#define MDFLD_DSI_READ_MAX_COUNT 5000 +- +-static const char * const dsi_errors[] = { +- "RX SOT Error", +- "RX SOT Sync Error", +- "RX EOT Sync Error", +- "RX Escape Mode Entry Error", +- "RX LP TX Sync Error", +- "RX HS Receive Timeout Error", +- "RX False Control Error", +- "RX ECC Single Bit Error", +- "RX ECC Multibit Error", +- "RX Checksum Error", +- "RX DSI Data Type Not Recognised", +- "RX DSI VC ID Invalid", +- "TX False Control Error", +- "TX ECC Single Bit Error", +- "TX ECC Multibit Error", +- "TX Checksum Error", +- "TX DSI Data Type Not Recognised", +- "TX DSI VC ID invalid", +- "High Contention", +- "Low contention", +- "DPI FIFO Under run", +- "HS TX Timeout", +- "LP RX Timeout", +- "Turn Around ACK Timeout", +- "ACK With No Error", +- "RX Invalid TX Length", +- "RX Prot Violation", +- "HS Generic Write FIFO Full", +- "LP Generic Write FIFO Full", +- "Generic Read Data Avail", +- "Special Packet Sent", +- "Tearing Effect", +-}; +- +-static int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender, +- u32 mask) +-{ +- struct drm_device *dev = sender->dev; +- u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg; +- int retry = 0xffff; +- +- while (retry--) { +- if ((mask & REG_READ(gen_fifo_stat_reg)) == mask) +- return 0; +- udelay(100); +- } +- dev_err(dev->dev, "fifo is NOT empty 0x%08x\n", +- REG_READ(gen_fifo_stat_reg)); +- return -EIO; +-} +- +-static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender) +-{ +- return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 10) | (1 << 18) +- | (1 << 26) | (1 << 27) | (1 << 28)); +-} +- +-static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender) +-{ +- return wait_for_gen_fifo_empty(sender, (1 << 10) | (1 << 26)); +-} +- +-static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender) +-{ +- return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 18)); +-} +- +-static int wait_for_dbi_fifo_empty(struct mdfld_dsi_pkg_sender *sender) +-{ +- return wait_for_gen_fifo_empty(sender, (1 << 27)); +-} +- +-static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask) +-{ +- u32 intr_stat_reg = sender->mipi_intr_stat_reg; +- struct drm_device *dev = sender->dev; +- +- switch (mask) { +- case (1 << 0): +- case (1 << 1): +- case (1 << 2): +- case (1 << 3): +- case (1 << 4): +- case (1 << 5): +- case (1 << 6): +- case (1 << 7): +- case (1 << 8): +- case (1 << 9): +- case (1 << 10): +- case (1 << 11): +- case (1 << 12): +- case (1 << 13): +- break; +- case (1 << 14): +- /*wait for all fifo empty*/ +- /*wait_for_all_fifos_empty(sender)*/; +- break; +- case (1 << 15): +- break; +- case (1 << 16): +- break; +- case (1 << 17): +- break; +- case (1 << 18): +- case (1 << 19): +- /*wait for contention recovery time*/ +- /*mdelay(10);*/ +- /*wait for all fifo empty*/ +- if (0) +- wait_for_all_fifos_empty(sender); +- break; +- case (1 << 20): +- break; +- case (1 << 21): +- /*wait for all fifo empty*/ +- /*wait_for_all_fifos_empty(sender);*/ +- break; +- case (1 << 22): +- break; +- case (1 << 23): +- case (1 << 24): +- case (1 << 25): +- case (1 << 26): +- case (1 << 27): +- /* HS Gen fifo full */ +- REG_WRITE(intr_stat_reg, mask); +- wait_for_hs_fifos_empty(sender); +- break; +- case (1 << 28): +- /* LP Gen fifo full\n */ +- REG_WRITE(intr_stat_reg, mask); +- wait_for_lp_fifos_empty(sender); +- break; +- case (1 << 29): +- case (1 << 30): +- case (1 << 31): +- break; +- } +- +- if (mask & REG_READ(intr_stat_reg)) +- dev_warn(dev->dev, "Cannot clean interrupt 0x%08x\n", mask); +- +- return 0; +-} +- +-static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender) +-{ +- struct drm_device *dev = sender->dev; +- u32 intr_stat_reg = sender->mipi_intr_stat_reg; +- u32 mask; +- u32 intr_stat; +- int i; +- int err = 0; +- +- intr_stat = REG_READ(intr_stat_reg); +- +- for (i = 0; i < 32; i++) { +- mask = (0x00000001UL) << i; +- if (intr_stat & mask) { +- dev_dbg(dev->dev, "[DSI]: %s\n", dsi_errors[i]); +- err = handle_dsi_error(sender, mask); +- if (err) +- dev_err(dev->dev, "Cannot handle error\n"); +- } +- } +- return err; +-} +- +-static inline int dbi_cmd_sent(struct mdfld_dsi_pkg_sender *sender) +-{ +- struct drm_device *dev = sender->dev; +- u32 retry = 0xffff; +- u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg; +- +- /* Query the command execution status */ +- while (retry--) { +- if (!(REG_READ(dbi_cmd_addr_reg) & (1 << 0))) +- break; +- } +- +- if (!retry) { +- dev_err(dev->dev, "Timeout waiting for DBI Command status\n"); +- return -EAGAIN; +- } +- return 0; +-} +- +-/* +- * NOTE: this interface is abandoned expect for write_mem_start DCS +- * other DCS are sent via generic pkg interfaces +- */ +-static int send_dcs_pkg(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg) +-{ +- struct drm_device *dev = sender->dev; +- struct mdfld_dsi_dcs_pkg *dcs_pkg = &pkg->pkg.dcs_pkg; +- u32 dbi_cmd_len_reg = sender->mipi_cmd_len_reg; +- u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg; +- u32 cb_phy = sender->dbi_cb_phy; +- u32 index = 0; +- u8 *cb = (u8 *)sender->dbi_cb_addr; +- int i; +- int ret; +- +- if (!sender->dbi_pkg_support) { +- dev_err(dev->dev, "Trying to send DCS on a non DBI output, abort!\n"); +- return -ENOTSUPP; +- } +- +- /*wait for DBI fifo empty*/ +- wait_for_dbi_fifo_empty(sender); +- +- *(cb + (index++)) = dcs_pkg->cmd; +- if (dcs_pkg->param_num) { +- for (i = 0; i < dcs_pkg->param_num; i++) +- *(cb + (index++)) = *(dcs_pkg->param + i); +- } +- +- REG_WRITE(dbi_cmd_len_reg, (1 + dcs_pkg->param_num)); +- REG_WRITE(dbi_cmd_addr_reg, +- (cb_phy << CMD_MEM_ADDR_OFFSET) +- | (1 << 0) +- | ((dcs_pkg->data_src == CMD_DATA_SRC_PIPE) ? (1 << 1) : 0)); +- +- ret = dbi_cmd_sent(sender); +- if (ret) { +- dev_err(dev->dev, "command 0x%x not complete\n", dcs_pkg->cmd); +- return -EAGAIN; +- } +- return 0; +-} +- +-static int __send_short_pkg(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg) +-{ +- struct drm_device *dev = sender->dev; +- u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg; +- u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg; +- u32 gen_ctrl_val = 0; +- struct mdfld_dsi_gen_short_pkg *short_pkg = &pkg->pkg.short_pkg; +- +- gen_ctrl_val |= short_pkg->cmd << MCS_COMMANDS_POS; +- gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS; +- gen_ctrl_val |= pkg->pkg_type; +- gen_ctrl_val |= short_pkg->param << MCS_PARAMETER_POS; +- +- if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) { +- /* wait for hs fifo empty */ +- /* wait_for_hs_fifos_empty(sender); */ +- /* Send pkg */ +- REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val); +- } else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) { +- /* wait_for_lp_fifos_empty(sender); */ +- /* Send pkg*/ +- REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val); +- } else { +- dev_err(dev->dev, "Unknown transmission type %d\n", +- pkg->transmission_type); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int __send_long_pkg(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg) +-{ +- struct drm_device *dev = sender->dev; +- u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg; +- u32 hs_gen_data_reg = sender->mipi_hs_gen_data_reg; +- u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg; +- u32 lp_gen_data_reg = sender->mipi_lp_gen_data_reg; +- u32 gen_ctrl_val = 0; +- u32 *dp; +- int i; +- struct mdfld_dsi_gen_long_pkg *long_pkg = &pkg->pkg.long_pkg; +- +- dp = long_pkg->data; +- +- /* +- * Set up word count for long pkg +- * FIXME: double check word count field. +- * currently, using the byte counts of the payload as the word count. +- * ------------------------------------------------------------ +- * | DI | WC | ECC| PAYLOAD |CHECKSUM| +- * ------------------------------------------------------------ +- */ +- gen_ctrl_val |= (long_pkg->len << 2) << WORD_COUNTS_POS; +- gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS; +- gen_ctrl_val |= pkg->pkg_type; +- +- if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) { +- /* Wait for hs ctrl and data fifos to be empty */ +- /* wait_for_hs_fifos_empty(sender); */ +- for (i = 0; i < long_pkg->len; i++) +- REG_WRITE(hs_gen_data_reg, *(dp + i)); +- REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val); +- } else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) { +- /* wait_for_lp_fifos_empty(sender); */ +- for (i = 0; i < long_pkg->len; i++) +- REG_WRITE(lp_gen_data_reg, *(dp + i)); +- REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val); +- } else { +- dev_err(dev->dev, "Unknown transmission type %d\n", +- pkg->transmission_type); +- return -EINVAL; +- } +- +- return 0; +- +-} +- +-static int send_mcs_short_pkg(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg) +-{ +- return __send_short_pkg(sender, pkg); +-} +- +-static int send_mcs_long_pkg(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg) +-{ +- return __send_long_pkg(sender, pkg); +-} +- +-static int send_gen_short_pkg(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg) +-{ +- return __send_short_pkg(sender, pkg); +-} +- +-static int send_gen_long_pkg(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg) +-{ +- return __send_long_pkg(sender, pkg); +-} +- +-static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg) +-{ +- u8 cmd; +- u8 *data; +- +- switch (pkg->pkg_type) { +- case MDFLD_DSI_PKG_DCS: +- cmd = pkg->pkg.dcs_pkg.cmd; +- break; +- case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0: +- case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1: +- cmd = pkg->pkg.short_pkg.cmd; +- break; +- case MDFLD_DSI_PKG_MCS_LONG_WRITE: +- data = (u8 *)pkg->pkg.long_pkg.data; +- cmd = *data; +- break; +- default: +- return 0; +- } +- +- /* This prevents other package sending while doing msleep */ +- sender->status = MDFLD_DSI_PKG_SENDER_BUSY; +- +- /* Check panel mode v.s. sending command */ +- if ((sender->panel_mode & MDFLD_DSI_PANEL_MODE_SLEEP) && +- cmd != exit_sleep_mode) { +- dev_err(sender->dev->dev, +- "sending 0x%x when panel sleep in\n", cmd); +- sender->status = MDFLD_DSI_PKG_SENDER_FREE; +- return -EINVAL; +- } +- +- /* Wait for 120 milliseconds in case exit_sleep_mode just be sent */ +- if (cmd == DCS_ENTER_SLEEP_MODE) { +- /*TODO: replace it with msleep later*/ +- mdelay(120); +- } +- return 0; +-} +- +-static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg) +-{ +- u8 cmd; +- u8 *data; +- +- switch (pkg->pkg_type) { +- case MDFLD_DSI_PKG_DCS: +- cmd = pkg->pkg.dcs_pkg.cmd; +- break; +- case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0: +- case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1: +- cmd = pkg->pkg.short_pkg.cmd; +- break; +- case MDFLD_DSI_PKG_MCS_LONG_WRITE: +- data = (u8 *)pkg->pkg.long_pkg.data; +- cmd = *data; +- break; +- default: +- return 0; +- } +- +- /* Update panel status */ +- if (cmd == DCS_ENTER_SLEEP_MODE) { +- sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP; +- /*TODO: replace it with msleep later*/ +- mdelay(120); +- } else if (cmd == DCS_EXIT_SLEEP_MODE) { +- sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP; +- /*TODO: replace it with msleep later*/ +- mdelay(120); +- } else if (unlikely(cmd == DCS_SOFT_RESET)) { +- /*TODO: replace it with msleep later*/ +- mdelay(5); +- } +- sender->status = MDFLD_DSI_PKG_SENDER_FREE; +- return 0; +- +-} +- +-static int do_send_pkg(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg) +-{ +- int ret; +- +- if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) { +- dev_err(sender->dev->dev, "sender is busy\n"); +- return -EAGAIN; +- } +- +- ret = send_pkg_prepare(sender, pkg); +- if (ret) { +- dev_err(sender->dev->dev, "send_pkg_prepare error\n"); +- return ret; +- } +- +- switch (pkg->pkg_type) { +- case MDFLD_DSI_PKG_DCS: +- ret = send_dcs_pkg(sender, pkg); +- break; +- case MDFLD_DSI_PKG_GEN_SHORT_WRITE_0: +- case MDFLD_DSI_PKG_GEN_SHORT_WRITE_1: +- case MDFLD_DSI_PKG_GEN_SHORT_WRITE_2: +- case MDFLD_DSI_PKG_GEN_READ_0: +- case MDFLD_DSI_PKG_GEN_READ_1: +- case MDFLD_DSI_PKG_GEN_READ_2: +- ret = send_gen_short_pkg(sender, pkg); +- break; +- case MDFLD_DSI_PKG_GEN_LONG_WRITE: +- ret = send_gen_long_pkg(sender, pkg); +- break; +- case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0: +- case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1: +- case MDFLD_DSI_PKG_MCS_READ: +- ret = send_mcs_short_pkg(sender, pkg); +- break; +- case MDFLD_DSI_PKG_MCS_LONG_WRITE: +- ret = send_mcs_long_pkg(sender, pkg); +- break; +- default: +- dev_err(sender->dev->dev, "Invalid pkg type 0x%x\n", +- pkg->pkg_type); +- ret = -EINVAL; +- } +- send_pkg_done(sender, pkg); +- return ret; +-} +- +-static int send_pkg(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg) +-{ +- int err ; +- +- /* Handle DSI error */ +- err = dsi_error_handler(sender); +- if (err) { +- dev_err(sender->dev->dev, "Error handling failed\n"); +- err = -EAGAIN; +- goto send_pkg_err; +- } +- +- /* Send pkg */ +- err = do_send_pkg(sender, pkg); +- if (err) { +- dev_err(sender->dev->dev, "sent pkg failed\n"); +- err = -EAGAIN; +- goto send_pkg_err; +- } +- +- /* FIXME: should I query complete and fifo empty here? */ +-send_pkg_err: +- return err; +-} +- +-static struct mdfld_dsi_pkg *pkg_sender_get_pkg_locked( +- struct mdfld_dsi_pkg_sender *sender) +-{ +- struct mdfld_dsi_pkg *pkg; +- +- if (list_empty(&sender->free_list)) { +- dev_err(sender->dev->dev, "No free pkg left\n"); +- return NULL; +- } +- pkg = list_first_entry(&sender->free_list, struct mdfld_dsi_pkg, entry); +- /* Detach from free list */ +- list_del_init(&pkg->entry); +- return pkg; +-} +- +-static void pkg_sender_put_pkg_locked(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg) +-{ +- memset(pkg, 0, sizeof(struct mdfld_dsi_pkg)); +- INIT_LIST_HEAD(&pkg->entry); +- list_add_tail(&pkg->entry, &sender->free_list); +-} +- +-static int mdfld_dbi_cb_init(struct mdfld_dsi_pkg_sender *sender, +- struct psb_gtt *pg, int pipe) +-{ +- unsigned long phys; +- void *virt_addr = NULL; +- +- switch (pipe) { +- case 0: +- /* FIXME: Doesn't this collide with stolen space ? */ +- phys = pg->gtt_phys_start - 0x1000; +- break; +- case 2: +- phys = pg->gtt_phys_start - 0x800; +- break; +- default: +- dev_err(sender->dev->dev, "Unsupported channel %d\n", pipe); +- return -EINVAL; +- } +- +- virt_addr = ioremap_nocache(phys, 0x800); +- if (!virt_addr) { +- dev_err(sender->dev->dev, "Map DBI command buffer error\n"); +- return -ENOMEM; +- } +- sender->dbi_cb_phy = phys; +- sender->dbi_cb_addr = virt_addr; +- return 0; +-} +- +-static void mdfld_dbi_cb_destroy(struct mdfld_dsi_pkg_sender *sender) +-{ +- if (sender && sender->dbi_cb_addr) +- iounmap(sender->dbi_cb_addr); +-} +- +-static void pkg_sender_queue_pkg(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg, +- int delay) +-{ +- unsigned long flags; +- +- spin_lock_irqsave(&sender->lock, flags); +- +- if (!delay) { +- send_pkg(sender, pkg); +- pkg_sender_put_pkg_locked(sender, pkg); +- } else { +- /* Queue it */ +- list_add_tail(&pkg->entry, &sender->pkg_list); +- } +- spin_unlock_irqrestore(&sender->lock, flags); +-} +- +-static void process_pkg_list(struct mdfld_dsi_pkg_sender *sender) +-{ +- struct mdfld_dsi_pkg *pkg; +- unsigned long flags; +- +- spin_lock_irqsave(&sender->lock, flags); +- +- while (!list_empty(&sender->pkg_list)) { +- pkg = list_first_entry(&sender->pkg_list, +- struct mdfld_dsi_pkg, entry); +- send_pkg(sender, pkg); +- list_del_init(&pkg->entry); +- pkg_sender_put_pkg_locked(sender, pkg); +- } +- +- spin_unlock_irqrestore(&sender->lock, flags); +-} +- +-static int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, +- u32 *data, u32 len, u8 transmission, int delay) +-{ +- struct mdfld_dsi_pkg *pkg; +- unsigned long flags; +- +- spin_lock_irqsave(&sender->lock, flags); +- pkg = pkg_sender_get_pkg_locked(sender); +- spin_unlock_irqrestore(&sender->lock, flags); +- +- if (!pkg) { +- dev_err(sender->dev->dev, "No memory\n"); +- return -ENOMEM; +- } +- pkg->pkg_type = MDFLD_DSI_PKG_MCS_LONG_WRITE; +- pkg->transmission_type = transmission; +- pkg->pkg.long_pkg.data = data; +- pkg->pkg.long_pkg.len = len; +- INIT_LIST_HEAD(&pkg->entry); +- +- pkg_sender_queue_pkg(sender, pkg, delay); +- return 0; +-} +- +-static int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, +- u8 cmd, u8 param, u8 param_num, +- u8 transmission, +- int delay) +-{ +- struct mdfld_dsi_pkg *pkg; +- unsigned long flags; +- +- spin_lock_irqsave(&sender->lock, flags); +- pkg = pkg_sender_get_pkg_locked(sender); +- spin_unlock_irqrestore(&sender->lock, flags); +- +- if (!pkg) { +- dev_err(sender->dev->dev, "No memory\n"); +- return -ENOMEM; +- } +- +- if (param_num) { +- pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_1; +- pkg->pkg.short_pkg.param = param; +- } else { +- pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_0; +- pkg->pkg.short_pkg.param = 0; +- } +- pkg->transmission_type = transmission; +- pkg->pkg.short_pkg.cmd = cmd; +- INIT_LIST_HEAD(&pkg->entry); +- +- pkg_sender_queue_pkg(sender, pkg, delay); +- return 0; +-} +- +-static int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, +- u8 param0, u8 param1, u8 param_num, +- u8 transmission, +- int delay) +-{ +- struct mdfld_dsi_pkg *pkg; +- unsigned long flags; +- +- spin_lock_irqsave(&sender->lock, flags); +- pkg = pkg_sender_get_pkg_locked(sender); +- spin_unlock_irqrestore(&sender->lock, flags); +- +- if (!pkg) { +- dev_err(sender->dev->dev, "No pkg memory\n"); +- return -ENOMEM; +- } +- +- switch (param_num) { +- case 0: +- pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_0; +- pkg->pkg.short_pkg.cmd = 0; +- pkg->pkg.short_pkg.param = 0; +- break; +- case 1: +- pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_1; +- pkg->pkg.short_pkg.cmd = param0; +- pkg->pkg.short_pkg.param = 0; +- break; +- case 2: +- pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_2; +- pkg->pkg.short_pkg.cmd = param0; +- pkg->pkg.short_pkg.param = param1; +- break; +- } +- +- pkg->transmission_type = transmission; +- INIT_LIST_HEAD(&pkg->entry); +- +- pkg_sender_queue_pkg(sender, pkg, delay); +- return 0; +-} +- +-static int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, +- u32 *data, u32 len, u8 transmission, int delay) +-{ +- struct mdfld_dsi_pkg *pkg; +- unsigned long flags; +- +- spin_lock_irqsave(&sender->lock, flags); +- pkg = pkg_sender_get_pkg_locked(sender); +- spin_unlock_irqrestore(&sender->lock, flags); +- +- if (!pkg) { +- dev_err(sender->dev->dev, "No pkg memory\n"); +- return -ENOMEM; +- } +- +- pkg->pkg_type = MDFLD_DSI_PKG_GEN_LONG_WRITE; +- pkg->transmission_type = transmission; +- pkg->pkg.long_pkg.data = data; +- pkg->pkg.long_pkg.len = len; +- +- INIT_LIST_HEAD(&pkg->entry); +- +- pkg_sender_queue_pkg(sender, pkg, delay); +- +- return 0; +-} +- +-static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, +- struct mdfld_dsi_pkg *pkg, +- u32 *data, +- u16 len) +-{ +- unsigned long flags; +- struct drm_device *dev = sender->dev; +- int i; +- u32 gen_data_reg; +- int retry = MDFLD_DSI_READ_MAX_COUNT; +- u8 transmission = pkg->transmission_type; +- +- /* +- * do reading. +- * 0) send out generic read request +- * 1) polling read data avail interrupt +- * 2) read data +- */ +- spin_lock_irqsave(&sender->lock, flags); +- +- REG_WRITE(sender->mipi_intr_stat_reg, 1 << 29); +- +- if ((REG_READ(sender->mipi_intr_stat_reg) & (1 << 29))) +- DRM_ERROR("Can NOT clean read data valid interrupt\n"); +- +- /*send out read request*/ +- send_pkg(sender, pkg); +- +- pkg_sender_put_pkg_locked(sender, pkg); +- +- /*polling read data avail interrupt*/ +- while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & (1 << 29))) { +- udelay(100); +- retry--; +- } +- +- if (!retry) { +- spin_unlock_irqrestore(&sender->lock, flags); +- return -ETIMEDOUT; +- } +- +- REG_WRITE(sender->mipi_intr_stat_reg, (1 << 29)); +- +- /*read data*/ +- if (transmission == MDFLD_DSI_HS_TRANSMISSION) +- gen_data_reg = sender->mipi_hs_gen_data_reg; +- else if (transmission == MDFLD_DSI_LP_TRANSMISSION) +- gen_data_reg = sender->mipi_lp_gen_data_reg; +- else { +- DRM_ERROR("Unknown transmission"); +- spin_unlock_irqrestore(&sender->lock, flags); +- return -EINVAL; +- } +- +- for (i=0; ilock, flags); +- +- return 0; +-} +- +-static int mdfld_dsi_read_gen(struct mdfld_dsi_pkg_sender *sender, +- u8 param0, +- u8 param1, +- u8 param_num, +- u32 *data, +- u16 len, +- u8 transmission) +-{ +- struct mdfld_dsi_pkg *pkg; +- unsigned long flags; +- +- spin_lock_irqsave(&sender->lock, flags); +- +- pkg = pkg_sender_get_pkg_locked(sender); +- +- spin_unlock_irqrestore(&sender->lock,flags); +- +- if (!pkg) { +- dev_err(sender->dev->dev, "No pkg memory\n"); +- return -ENOMEM; +- } +- +- switch (param_num) { +- case 0: +- pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_0; +- pkg->pkg.short_pkg.cmd = 0; +- pkg->pkg.short_pkg.param = 0; +- break; +- case 1: +- pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_1; +- pkg->pkg.short_pkg.cmd = param0; +- pkg->pkg.short_pkg.param = 0; +- break; +- case 2: +- pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_2; +- pkg->pkg.short_pkg.cmd = param0; +- pkg->pkg.short_pkg.param = param1; +- break; +- } +- +- pkg->transmission_type = transmission; +- +- INIT_LIST_HEAD(&pkg->entry); +- +- return __read_panel_data(sender, pkg, data, len); +-} +- +-static int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, +- u8 cmd, +- u32 *data, +- u16 len, +- u8 transmission) +-{ +- struct mdfld_dsi_pkg *pkg; +- unsigned long flags; +- +- spin_lock_irqsave(&sender->lock, flags); +- +- pkg = pkg_sender_get_pkg_locked(sender); +- +- spin_unlock_irqrestore(&sender->lock, flags); +- +- if (!pkg) { +- dev_err(sender->dev->dev, "No pkg memory\n"); +- return -ENOMEM; +- } +- +- pkg->pkg_type = MDFLD_DSI_PKG_MCS_READ; +- pkg->pkg.short_pkg.cmd = cmd; +- pkg->pkg.short_pkg.param = 0; +- +- pkg->transmission_type = transmission; +- +- INIT_LIST_HEAD(&pkg->entry); +- +- return __read_panel_data(sender, pkg, data, len); +-} +- +-void dsi_controller_dbi_init(struct mdfld_dsi_config * dsi_config, int pipe) +-{ +- struct drm_device * dev = dsi_config->dev; +- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; +- int lane_count = dsi_config->lane_count; +- u32 val = 0; +- +- /*un-ready device*/ +- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); +- +- /*init dsi adapter before kicking off*/ +- REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); +- +- /*TODO: figure out how to setup these registers*/ +- REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); +- REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), 0x000a0014); +- REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400); +- REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001); +- REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000); +- +- /*enable all interrupts*/ +- REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); +- /*max value: 20 clock cycles of txclkesc*/ +- REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f); +- /*min 21 txclkesc, max: ffffh*/ +- REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff); +- /*min: 7d0 max: 4e20*/ +- REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0); +- +- /*set up max return packet size*/ +- REG_WRITE((MIPIA_MAX_RETURN_PACK_SIZE_REG + reg_offset), +- MDFLD_DSI_MAX_RETURN_PACKET_SIZE); +- +- /*set up func_prg*/ +- val |= lane_count; +- val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET); +- val |= DSI_DBI_COLOR_FORMAT_OPTION2; +- REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); +- +- REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff); +- REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff); +- +- REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); +- REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); +- REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); +- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); +-} +- +-void dsi_controller_dpi_init(struct mdfld_dsi_config * dsi_config, int pipe) +-{ +- struct drm_device * dev = dsi_config->dev; +- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; +- int lane_count = dsi_config->lane_count; +- struct mdfld_dsi_dpi_timing dpi_timing; +- struct drm_display_mode * mode = dsi_config->mode; +- u32 val = 0; +- +- /*un-ready device*/ +- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); +- +- /*init dsi adapter before kicking off*/ +- REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); +- +- /*enable all interrupts*/ +- REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); +- +- /*set up func_prg*/ +- val |= lane_count; +- val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET; +- +- switch(dsi_config->bpp) { +- case 16: +- val |= DSI_DPI_COLOR_FORMAT_RGB565; +- break; +- case 18: +- val |= DSI_DPI_COLOR_FORMAT_RGB666; +- break; +- case 24: +- val |= DSI_DPI_COLOR_FORMAT_RGB888; +- break; +- default: +- DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp); +- } +- +- REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); +- +- REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), +- (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK); +- REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK); +- +- /*max value: 20 clock cycles of txclkesc*/ +- REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK); +- +- /*min 21 txclkesc, max: ffffh*/ +- REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK); +- +- REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay); +- +- /*set DPI timing registers*/ +- mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp); +- +- REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); +- REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); +- REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); +- REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); +- REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); +- REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); +- REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); +- +- REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); +- +- /*min: 7d0 max: 4e20*/ +- REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0); +- +- /*set up video mode*/ +- val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE; +- REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val); +- +- REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); +- +- REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); +- +- /*TODO: figure out how to setup these registers*/ +- REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); +- +- REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14); +- +- /*set device ready*/ +- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); +-} +- +-static void dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe) +-{ +- if (!dsi_config || ((pipe != 0) && (pipe != 2))) { +- DRM_ERROR("Invalid parameters\n"); +- return; +- } +- +- if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) +- dsi_controller_dpi_init(dsi_config, pipe); +- else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) +- dsi_controller_dbi_init(dsi_config, pipe); +- else +- DRM_ERROR("Bad DSI encoder type\n"); +-} +- +-void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender) +-{ +- process_pkg_list(sender); +-} +- +-int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender, +- u8 dcs, u8 *param, u32 param_num, u8 data_src, +- int delay) +-{ +- struct mdfld_dsi_pkg *pkg; +- u32 cb_phy = sender->dbi_cb_phy; +- struct drm_device *dev = sender->dev; +- u32 index = 0; +- u8 *cb = (u8 *)sender->dbi_cb_addr; +- unsigned long flags; +- int retry; +- u8 *dst = NULL; +- u32 len; +- +- if (!sender) { +- WARN_ON(1); +- return -EINVAL; +- } +- +- if (!sender->dbi_pkg_support) { +- dev_err(dev->dev, "No DBI pkg sending on this sender\n"); +- return -ENOTSUPP; +- } +- +- if (param_num > MDFLD_MAX_DCS_PARAM) { +- dev_err(dev->dev, "Sender only supports up to %d DCS params\n", +- MDFLD_MAX_DCS_PARAM); +- return -EINVAL; +- } +- +- /* +- * If dcs is write_mem_start, send it directly using DSI adapter +- * interface +- */ +- if (dcs == DCS_WRITE_MEM_START) { +- if (!spin_trylock(&sender->lock)) +- return -EAGAIN; +- +- /* +- * query whether DBI FIFO is empty, +- * if not wait it becoming empty +- */ +- retry = MDFLD_DSI_DBI_FIFO_TIMEOUT; +- while (retry && +- !(REG_READ(sender->mipi_gen_fifo_stat_reg) & (1 << 27))) { +- udelay(500); +- retry--; +- } +- +- /* If DBI FIFO timeout, drop this frame */ +- if (!retry) { +- spin_unlock(&sender->lock); +- return 0; +- } +- +- *(cb + (index++)) = write_mem_start; +- +- REG_WRITE(sender->mipi_cmd_len_reg, 1); +- REG_WRITE(sender->mipi_cmd_addr_reg, +- cb_phy | (1 << 0) | (1 << 1)); +- +- retry = MDFLD_DSI_DBI_FIFO_TIMEOUT; +- while (retry && +- (REG_READ(sender->mipi_cmd_addr_reg) & (1 << 0))) { +- udelay(1); +- retry--; +- } +- +- spin_unlock(&sender->lock); +- return 0; +- } +- +- /* Get a free pkg */ +- spin_lock_irqsave(&sender->lock, flags); +- pkg = pkg_sender_get_pkg_locked(sender); +- spin_unlock_irqrestore(&sender->lock, flags); +- +- if (!pkg) { +- dev_err(dev->dev, "No packages memory\n"); +- return -ENOMEM; +- } +- +- dst = pkg->pkg.dcs_pkg.param; +- memcpy(dst, param, param_num); +- +- pkg->pkg_type = MDFLD_DSI_PKG_DCS; +- pkg->transmission_type = MDFLD_DSI_DCS; +- pkg->pkg.dcs_pkg.cmd = dcs; +- pkg->pkg.dcs_pkg.param_num = param_num; +- pkg->pkg.dcs_pkg.data_src = data_src; +- +- INIT_LIST_HEAD(&pkg->entry); +- +- if (param_num == 0) +- return mdfld_dsi_send_mcs_short_hs(sender, dcs, 0, 0, delay); +- else if (param_num == 1) +- return mdfld_dsi_send_mcs_short_hs(sender, dcs, +- param[0], 1, delay); +- else if (param_num > 1) { +- len = (param_num + 1) / 4; +- if ((param_num + 1) % 4) +- len++; +- return mdfld_dsi_send_mcs_long_hs(sender, +- (u32 *)&pkg->pkg.dcs_pkg, len, delay); +- } +- return 0; +-} +- +-int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender, +- u8 cmd, u8 param, u8 param_num, int delay) +-{ +- if (!sender) { +- WARN_ON(1); +- return -EINVAL; +- } +- return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num, +- MDFLD_DSI_HS_TRANSMISSION, delay); +-} +- +-int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender, +- u8 cmd, u8 param, u8 param_num, int delay) +-{ +- if (!sender) { +- WARN_ON(1); +- return -EINVAL; +- } +- return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num, +- MDFLD_DSI_LP_TRANSMISSION, delay); +-} +- +-int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender, +- u32 *data, +- u32 len, +- int delay) +-{ +- if (!sender || !data || !len) { +- DRM_ERROR("Invalid parameters\n"); +- return -EINVAL; +- } +- return mdfld_dsi_send_mcs_long(sender, data, len, +- MDFLD_DSI_HS_TRANSMISSION, delay); +-} +- +-int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender, +- u32 *data, +- u32 len, +- int delay) +-{ +- if (!sender || !data || !len) { +- WARN_ON(1); +- return -EINVAL; +- } +- return mdfld_dsi_send_mcs_long(sender, data, len, +- MDFLD_DSI_LP_TRANSMISSION, delay); +-} +- +-int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender, +- u8 param0, u8 param1, u8 param_num, int delay) +-{ +- if (!sender) { +- WARN_ON(1); +- return -EINVAL; +- } +- return mdfld_dsi_send_gen_short(sender, param0, param1, param_num, +- MDFLD_DSI_HS_TRANSMISSION, delay); +-} +- +-int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender, +- u8 param0, u8 param1, u8 param_num, int delay) +-{ +- if (!sender || param_num < 0 || param_num > 2) { +- WARN_ON(1); +- return -EINVAL; +- } +- return mdfld_dsi_send_gen_short(sender, param0, param1, param_num, +- MDFLD_DSI_LP_TRANSMISSION, delay); +-} +- +-int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender, +- u32 *data, +- u32 len, +- int delay) +-{ +- if (!sender || !data || !len) { +- WARN_ON(1); +- return -EINVAL; +- } +- return mdfld_dsi_send_gen_long(sender, data, len, +- MDFLD_DSI_HS_TRANSMISSION, delay); +-} +- +-int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender, +- u32 *data, +- u32 len, +- int delay) +-{ +- if (!sender || !data || !len) { +- WARN_ON(1); +- return -EINVAL; +- } +- return mdfld_dsi_send_gen_long(sender, data, len, +- MDFLD_DSI_LP_TRANSMISSION, delay); +-} +- +-int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender, +- u8 param0, +- u8 param1, +- u8 param_num, +- u32 *data, +- u16 len) +-{ +- if (!sender || !data || param_num < 0 || param_num > 2 +- || !data || !len) { +- DRM_ERROR("Invalid parameters\n"); +- return -EINVAL; +- } +- +- return mdfld_dsi_read_gen(sender, param0, param1, param_num, +- data, len, MDFLD_DSI_HS_TRANSMISSION); +- +-} +- +-int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender, +- u8 param0, +- u8 param1, +- u8 param_num, +- u32 *data, +- u16 len) +-{ +- if (!sender || !data || param_num < 0 || param_num > 2 +- || !data || !len) { +- DRM_ERROR("Invalid parameters\n"); +- return -EINVAL; +- } +- +- return mdfld_dsi_read_gen(sender, param0, param1, param_num, +- data, len, MDFLD_DSI_LP_TRANSMISSION); +-} +- +-int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender, +- u8 cmd, +- u32 *data, +- u16 len) +-{ +- if (!sender || !data || !len) { +- DRM_ERROR("Invalid parameters\n"); +- return -EINVAL; +- } +- +- return mdfld_dsi_read_mcs(sender, cmd, data, len, +- MDFLD_DSI_HS_TRANSMISSION); +-} +- +-int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender, +- u8 cmd, +- u32 *data, +- u16 len) +-{ +- if (!sender || !data || !len) { +- WARN_ON(1); +- return -EINVAL; +- } +- +- return mdfld_dsi_read_mcs(sender, cmd, data, len, +- MDFLD_DSI_LP_TRANSMISSION); +-} +- +-int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector, +- int pipe) +-{ +- int ret; +- struct mdfld_dsi_pkg_sender *pkg_sender; +- struct mdfld_dsi_config *dsi_config = +- mdfld_dsi_get_config(dsi_connector); +- struct drm_device *dev = dsi_config->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct psb_gtt *pg = &dev_priv->gtt; +- int i; +- struct mdfld_dsi_pkg *pkg, *tmp; +- u32 mipi_val = 0; +- +- if (!dsi_connector) { +- WARN_ON(1); +- return -EINVAL; +- } +- +- pkg_sender = dsi_connector->pkg_sender; +- +- if (!pkg_sender || IS_ERR(pkg_sender)) { +- pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender), +- GFP_KERNEL); +- if (!pkg_sender) { +- dev_err(dev->dev, "Create DSI pkg sender failed\n"); +- return -ENOMEM; +- } +- +- dsi_connector->pkg_sender = (void *)pkg_sender; +- } +- +- pkg_sender->dev = dev; +- pkg_sender->dsi_connector = dsi_connector; +- pkg_sender->pipe = pipe; +- pkg_sender->pkg_num = 0; +- pkg_sender->panel_mode = 0; +- pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE; +- +- /* Init dbi command buffer*/ +- +- if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) { +- pkg_sender->dbi_pkg_support = 1; +- ret = mdfld_dbi_cb_init(pkg_sender, pg, pipe); +- if (ret) { +- dev_err(dev->dev, "DBI command buffer map failed\n"); +- goto mapping_err; +- } +- } +- +- /* Init regs */ +- if (pipe == 0) { +- pkg_sender->dpll_reg = MRST_DPLL_A; +- pkg_sender->dspcntr_reg = DSPACNTR; +- pkg_sender->pipeconf_reg = PIPEACONF; +- pkg_sender->dsplinoff_reg = DSPALINOFF; +- pkg_sender->dspsurf_reg = DSPASURF; +- pkg_sender->pipestat_reg = PIPEASTAT; +- +- pkg_sender->mipi_intr_stat_reg = MIPIA_INTR_STAT_REG; +- pkg_sender->mipi_lp_gen_data_reg = MIPIA_LP_GEN_DATA_REG; +- pkg_sender->mipi_hs_gen_data_reg = MIPIA_HS_GEN_DATA_REG; +- pkg_sender->mipi_lp_gen_ctrl_reg = MIPIA_LP_GEN_CTRL_REG; +- pkg_sender->mipi_hs_gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG; +- pkg_sender->mipi_gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG; +- pkg_sender->mipi_data_addr_reg = MIPIA_DATA_ADD_REG; +- pkg_sender->mipi_data_len_reg = MIPIA_DATA_LEN_REG; +- pkg_sender->mipi_cmd_addr_reg = MIPIA_CMD_ADD_REG; +- pkg_sender->mipi_cmd_len_reg = MIPIA_CMD_LEN_REG; +- } else if (pipe == 2) { +- pkg_sender->dpll_reg = MRST_DPLL_A; +- pkg_sender->dspcntr_reg = DSPCCNTR; +- pkg_sender->pipeconf_reg = PIPECCONF; +- pkg_sender->dsplinoff_reg = DSPCLINOFF; +- pkg_sender->dspsurf_reg = DSPCSURF; +- pkg_sender->pipestat_reg = PIPECSTAT; +- +- pkg_sender->mipi_intr_stat_reg = +- MIPIA_INTR_STAT_REG + MIPIC_REG_OFFSET; +- pkg_sender->mipi_lp_gen_data_reg = +- MIPIA_LP_GEN_DATA_REG + MIPIC_REG_OFFSET; +- pkg_sender->mipi_hs_gen_data_reg = +- MIPIA_HS_GEN_DATA_REG + MIPIC_REG_OFFSET; +- pkg_sender->mipi_lp_gen_ctrl_reg = +- MIPIA_LP_GEN_CTRL_REG + MIPIC_REG_OFFSET; +- pkg_sender->mipi_hs_gen_ctrl_reg = +- MIPIA_HS_GEN_CTRL_REG + MIPIC_REG_OFFSET; +- pkg_sender->mipi_gen_fifo_stat_reg = +- MIPIA_GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET; +- pkg_sender->mipi_data_addr_reg = +- MIPIA_DATA_ADD_REG + MIPIC_REG_OFFSET; +- pkg_sender->mipi_data_len_reg = +- MIPIA_DATA_LEN_REG + MIPIC_REG_OFFSET; +- pkg_sender->mipi_cmd_addr_reg = +- MIPIA_CMD_ADD_REG + MIPIC_REG_OFFSET; +- pkg_sender->mipi_cmd_len_reg = +- MIPIA_CMD_LEN_REG + MIPIC_REG_OFFSET; +- } +- +- /* Init pkg list */ +- INIT_LIST_HEAD(&pkg_sender->pkg_list); +- INIT_LIST_HEAD(&pkg_sender->free_list); +- +- spin_lock_init(&pkg_sender->lock); +- +- /* Allocate free pkg pool */ +- for (i = 0; i < MDFLD_MAX_PKG_NUM; i++) { +- pkg = kzalloc(sizeof(struct mdfld_dsi_pkg), GFP_KERNEL); +- if (!pkg) { +- dev_err(dev->dev, "Out of memory allocating pkg pool"); +- ret = -ENOMEM; +- goto pkg_alloc_err; +- } +- INIT_LIST_HEAD(&pkg->entry); +- list_add_tail(&pkg->entry, &pkg_sender->free_list); +- } +- +- /* +- * For video mode, don't enable DPI timing output here, +- * will init the DPI timing output during mode setting. +- */ +- if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) +- mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; +- else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) +- mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX +- | TE_TRIGGER_GPIO_PIN; +- else +- DRM_ERROR("Bad DSI encoder type\n"); +- +- if (pipe == 0) { +- mipi_val |= 0x2; +- REG_WRITE(MIPI, mipi_val); +- REG_READ(MIPI); +- } else if (pipe == 2) { +- REG_WRITE(MIPI_C, mipi_val); +- REG_READ(MIPI_C); +- } +- +- /*do dsi controller init*/ +- dsi_controller_init(dsi_config, pipe); +- +- return 0; +- +-pkg_alloc_err: +- list_for_each_entry_safe(pkg, tmp, &pkg_sender->free_list, entry) { +- list_del(&pkg->entry); +- kfree(pkg); +- } +- +- /* Free mapped command buffer */ +- mdfld_dbi_cb_destroy(pkg_sender); +-mapping_err: +- kfree(pkg_sender); +- dsi_connector->pkg_sender = NULL; +- return ret; +-} +- +-void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender) +-{ +- struct mdfld_dsi_pkg *pkg, *tmp; +- +- if (!sender || IS_ERR(sender)) +- return; +- +- /* Free pkg pool */ +- list_for_each_entry_safe(pkg, tmp, &sender->free_list, entry) { +- list_del(&pkg->entry); +- kfree(pkg); +- } +- /* Free pkg list */ +- list_for_each_entry_safe(pkg, tmp, &sender->pkg_list, entry) { +- list_del(&pkg->entry); +- kfree(pkg); +- } +- mdfld_dbi_cb_destroy(sender); /* free mapped command buffer */ +- kfree(sender); +-} +diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h b/drivers/staging/gma500/mdfld_dsi_pkg_sender.h +deleted file mode 100644 +index f24abc7..0000000 +--- a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h ++++ /dev/null +@@ -1,184 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Jackie Li +- */ +-#ifndef __MDFLD_DSI_PKG_SENDER_H__ +-#define __MDFLD_DSI_PKG_SENDER_H__ +- +-#include +- +-#define MDFLD_MAX_DCS_PARAM 8 +-#define MDFLD_MAX_PKG_NUM 2048 +- +-enum { +- MDFLD_DSI_PKG_DCS, +- MDFLD_DSI_PKG_GEN_SHORT_WRITE_0 = 0x03, +- MDFLD_DSI_PKG_GEN_SHORT_WRITE_1 = 0x13, +- MDFLD_DSI_PKG_GEN_SHORT_WRITE_2 = 0x23, +- MDFLD_DSI_PKG_GEN_READ_0 = 0x04, +- MDFLD_DSI_PKG_GEN_READ_1 = 0x14, +- MDFLD_DSI_PKG_GEN_READ_2 = 0x24, +- MDFLD_DSI_PKG_GEN_LONG_WRITE = 0x29, +- MDFLD_DSI_PKG_MCS_SHORT_WRITE_0 = 0x05, +- MDFLD_DSI_PKG_MCS_SHORT_WRITE_1 = 0x15, +- MDFLD_DSI_PKG_MCS_READ = 0x06, +- MDFLD_DSI_PKG_MCS_LONG_WRITE = 0x39, +-}; +- +-enum { +- MDFLD_DSI_LP_TRANSMISSION, +- MDFLD_DSI_HS_TRANSMISSION, +- MDFLD_DSI_DCS, +-}; +- +-enum { +- MDFLD_DSI_PANEL_MODE_SLEEP = 0x1, +-}; +- +-enum { +- MDFLD_DSI_PKG_SENDER_FREE = 0x0, +- MDFLD_DSI_PKG_SENDER_BUSY = 0x1, +-}; +- +-enum { +- MDFLD_DSI_SEND_PACKAGE, +- MDFLD_DSI_QUEUE_PACKAGE, +-}; +- +-struct mdfld_dsi_gen_short_pkg { +- u8 cmd; +- u8 param; +-}; +- +-struct mdfld_dsi_gen_long_pkg { +- u32 *data; +- u32 len; +-}; +- +-struct mdfld_dsi_dcs_pkg { +- u8 cmd; +- u8 param[MDFLD_MAX_DCS_PARAM]; +- u32 param_num; +- u8 data_src; +-}; +- +-struct mdfld_dsi_pkg { +- u8 pkg_type; +- u8 transmission_type; +- +- union { +- struct mdfld_dsi_gen_short_pkg short_pkg; +- struct mdfld_dsi_gen_long_pkg long_pkg; +- struct mdfld_dsi_dcs_pkg dcs_pkg; +- } pkg; +- +- struct list_head entry; +-}; +- +-struct mdfld_dsi_pkg_sender { +- struct drm_device *dev; +- struct mdfld_dsi_connector *dsi_connector; +- u32 status; +- +- u32 panel_mode; +- +- int pipe; +- +- spinlock_t lock; +- struct list_head pkg_list; +- struct list_head free_list; +- +- u32 pkg_num; +- +- int dbi_pkg_support; +- +- u32 dbi_cb_phy; +- void *dbi_cb_addr; +- +- /* Registers */ +- u32 dpll_reg; +- u32 dspcntr_reg; +- u32 pipeconf_reg; +- u32 pipestat_reg; +- u32 dsplinoff_reg; +- u32 dspsurf_reg; +- +- u32 mipi_intr_stat_reg; +- u32 mipi_lp_gen_data_reg; +- u32 mipi_hs_gen_data_reg; +- u32 mipi_lp_gen_ctrl_reg; +- u32 mipi_hs_gen_ctrl_reg; +- u32 mipi_gen_fifo_stat_reg; +- u32 mipi_data_addr_reg; +- u32 mipi_data_len_reg; +- u32 mipi_cmd_addr_reg; +- u32 mipi_cmd_len_reg; +-}; +- +-/* DCS definitions */ +-#define DCS_SOFT_RESET 0x01 +-#define DCS_ENTER_SLEEP_MODE 0x10 +-#define DCS_EXIT_SLEEP_MODE 0x11 +-#define DCS_SET_DISPLAY_OFF 0x28 +-#define DCS_SET_DISPLAY_ON 0x29 +-#define DCS_SET_COLUMN_ADDRESS 0x2a +-#define DCS_SET_PAGE_ADDRESS 0x2b +-#define DCS_WRITE_MEM_START 0x2c +-#define DCS_SET_TEAR_OFF 0x34 +-#define DCS_SET_TEAR_ON 0x35 +- +-extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector, +- int pipe); +-extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender); +-extern int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender, u8 dcs, +- u8 *param, u32 param_num, u8 data_src, int delay); +-extern int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender, +- u8 cmd, u8 param, u8 param_num, int delay); +-extern int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender, +- u8 cmd, u8 param, u8 param_num, int delay); +-extern int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender, +- u32 *data, u32 len, int delay); +-extern int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender, +- u32 *data, u32 len, int delay); +-extern int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender, +- u8 param0, u8 param1, u8 param_num, int delay); +-extern int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender, +- u8 param0, u8 param1, u8 param_num, int delay); +-extern int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender, +- u32 *data, u32 len, int delay); +-extern int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender, +- u32 *data, u32 len, int delay); +- +-extern int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender, +- u8 param0, u8 param1, u8 param_num, u32 *data, u16 len); +-extern int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender, +- u8 param0, u8 param1, u8 param_num, u32 *data, u16 len); +-extern int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender, +- u8 cmd, u32 *data, u16 len); +-extern int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender, +- u8 cmd, u32 *data, u16 len); +- +-extern void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender); +- +-#endif /* __MDFLD_DSI_PKG_SENDER_H__ */ +diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c +deleted file mode 100644 +index 8eb827e..0000000 +--- a/drivers/staging/gma500/mdfld_intel_display.c ++++ /dev/null +@@ -1,1404 +0,0 @@ +-/* +- * Copyright © 2006-2011 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Eric Anholt +- */ +- +-#include "framebuffer.h" +-#include "psb_intel_display.h" +-#include "mdfld_dsi_dbi.h" +-#include "mdfld_dsi_dpi.h" +-#include "mdfld_dsi_dbi_dpu.h" +- +-#include +- +-#ifdef MIN +-#undef MIN +-#endif +- +-#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +- +-/* Hardcoded currently */ +-static int ksel = KSEL_CRYSTAL_19; +- +-extern void mdfld_save_display(struct drm_device *dev); +-extern bool gbgfxsuspended; +- +-struct psb_intel_range_t { +- int min, max; +-}; +- +-struct mdfld_limit_t { +- struct psb_intel_range_t dot, m, p1; +-}; +- +-struct mdfld_intel_clock_t { +- /* given values */ +- int n; +- int m1, m2; +- int p1, p2; +- /* derived values */ +- int dot; +- int vco; +- int m; +- int p; +-}; +- +- +- +-#define COUNT_MAX 0x10000000 +- +-void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe) +-{ +- int count, temp; +- u32 pipeconf_reg = PIPEACONF; +- +- switch (pipe) { +- case 0: +- break; +- case 1: +- pipeconf_reg = PIPEBCONF; +- break; +- case 2: +- pipeconf_reg = PIPECCONF; +- break; +- default: +- DRM_ERROR("Illegal Pipe Number. \n"); +- return; +- } +- +- /* FIXME JLIU7_PO */ +- psb_intel_wait_for_vblank(dev); +- return; +- +- /* Wait for for the pipe disable to take effect. */ +- for (count = 0; count < COUNT_MAX; count++) { +- temp = REG_READ(pipeconf_reg); +- if ((temp & PIPEACONF_PIPE_STATE) == 0) +- break; +- } +-} +- +-void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe) +-{ +- int count, temp; +- u32 pipeconf_reg = PIPEACONF; +- +- switch (pipe) { +- case 0: +- break; +- case 1: +- pipeconf_reg = PIPEBCONF; +- break; +- case 2: +- pipeconf_reg = PIPECCONF; +- break; +- default: +- dev_err(dev->dev, "Illegal Pipe Number.\n"); +- return; +- } +- +- /* FIXME JLIU7_PO */ +- psb_intel_wait_for_vblank(dev); +- return; +- +- /* Wait for for the pipe enable to take effect. */ +- for (count = 0; count < COUNT_MAX; count++) { +- temp = REG_READ(pipeconf_reg); +- if ((temp & PIPEACONF_PIPE_STATE) == 1) +- break; +- } +-} +- +- +-static int mdfld_intel_crtc_cursor_set(struct drm_crtc *crtc, +- struct drm_file *file_priv, +- uint32_t handle, +- uint32_t width, uint32_t height) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- uint32_t control = CURACNTR; +- uint32_t base = CURABASE; +- uint32_t temp; +- size_t addr = 0; +- struct gtt_range *gt; +- struct drm_gem_object *obj; +- int ret; +- +- switch (pipe) { +- case 0: +- break; +- case 1: +- control = CURBCNTR; +- base = CURBBASE; +- break; +- case 2: +- control = CURCCNTR; +- base = CURCBASE; +- break; +- default: +- dev_err(dev->dev, "Illegal Pipe Number. \n"); +- return -EINVAL; +- } +- +-#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */ +- if (pipe != 0) +- return 0; +-#endif +- /* if we want to turn of the cursor ignore width and height */ +- if (!handle) { +- dev_dbg(dev->dev, "cursor off\n"); +- /* turn off the cursor */ +- temp = 0; +- temp |= CURSOR_MODE_DISABLE; +- +- if (gma_power_begin(dev, true)) { +- REG_WRITE(control, temp); +- REG_WRITE(base, 0); +- gma_power_end(dev); +- } +- /* Unpin the old GEM object */ +- if (psb_intel_crtc->cursor_obj) { +- gt = container_of(psb_intel_crtc->cursor_obj, +- struct gtt_range, gem); +- psb_gtt_unpin(gt); +- drm_gem_object_unreference(psb_intel_crtc->cursor_obj); +- psb_intel_crtc->cursor_obj = NULL; +- } +- return 0; +- } +- +- /* Currently we only support 64x64 cursors */ +- if (width != 64 || height != 64) { +- DRM_ERROR("we currently only support 64x64 cursors\n"); +- return -EINVAL; +- } +- +- obj = drm_gem_object_lookup(dev, file_priv, handle); +- if (!obj) +- return -ENOENT; +- +- if (obj->size < width * height * 4) { +- dev_dbg(dev->dev, "buffer is to small\n"); +- return -ENOMEM; +- } +- +- gt = container_of(obj, struct gtt_range, gem); +- +- /* Pin the memory into the GTT */ +- ret = psb_gtt_pin(gt); +- if (ret) { +- dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); +- return ret; +- } +- +- +- addr = gt->offset; /* Or resource.start ??? */ +- +- psb_intel_crtc->cursor_addr = addr; +- +- temp = 0; +- /* set the pipe for the cursor */ +- temp |= (pipe << 28); +- temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; +- +- if (gma_power_begin(dev, true)) { +- REG_WRITE(control, temp); +- REG_WRITE(base, addr); +- gma_power_end(dev); +- } +- /* unpin the old GEM object */ +- if (psb_intel_crtc->cursor_obj) { +- gt = container_of(psb_intel_crtc->cursor_obj, +- struct gtt_range, gem); +- psb_gtt_unpin(gt); +- drm_gem_object_unreference(psb_intel_crtc->cursor_obj); +- psb_intel_crtc->cursor_obj = obj; +- } +- return 0; +-} +- +-static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) +-{ +- struct drm_device *dev = crtc->dev; +- struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private; +- struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; +- struct psb_drm_dpu_rect rect; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- uint32_t pos = CURAPOS; +- uint32_t base = CURABASE; +- uint32_t temp = 0; +- uint32_t addr; +- +- switch (pipe) { +- case 0: +- if (dpu_info) { +- rect.x = x; +- rect.y = y; +- +- mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORA, &rect); +- mdfld_dpu_exit_dsr(dev); +- } else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_0)) +- mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_0); +- break; +- case 1: +- pos = CURBPOS; +- base = CURBBASE; +- break; +- case 2: +- if (dpu_info) { +- mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORC, &rect); +- mdfld_dpu_exit_dsr(dev); +- } else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_2)) +- mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_2); +- pos = CURCPOS; +- base = CURCBASE; +- break; +- default: +- DRM_ERROR("Illegal Pipe Number. \n"); +- return -EINVAL; +- } +- +-#if 1 /* FIXME_JLIU7 can't enable cursorB/C HW issue. need to remove after HW fix */ +- if (pipe != 0) +- return 0; +-#endif +- if (x < 0) { +- temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); +- x = -x; +- } +- if (y < 0) { +- temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); +- y = -y; +- } +- +- temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); +- temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); +- +- addr = psb_intel_crtc->cursor_addr; +- +- if (gma_power_begin(dev, true)) { +- REG_WRITE(pos, temp); +- REG_WRITE(base, addr); +- gma_power_end(dev); +- } +- +- return 0; +-} +- +-const struct drm_crtc_funcs mdfld_intel_crtc_funcs = { +- .cursor_set = mdfld_intel_crtc_cursor_set, +- .cursor_move = mdfld_intel_crtc_cursor_move, +- .gamma_set = psb_intel_crtc_gamma_set, +- .set_config = drm_crtc_helper_set_config, +- .destroy = psb_intel_crtc_destroy, +-}; +- +-static struct drm_device globle_dev; +- +-void mdfld__intel_plane_set_alpha(int enable) +-{ +- struct drm_device *dev = &globle_dev; +- int dspcntr_reg = DSPACNTR; +- u32 dspcntr; +- +- dspcntr = REG_READ(dspcntr_reg); +- +- if (enable) { +- dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA; +- dspcntr |= DISPPLANE_32BPP; +- } else { +- dspcntr &= ~DISPPLANE_32BPP; +- dspcntr |= DISPPLANE_32BPP_NO_ALPHA; +- } +- +- REG_WRITE(dspcntr_reg, dspcntr); +-} +- +-int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) +-{ +- struct drm_device *dev = crtc->dev; +- /* struct drm_i915_master_private *master_priv; */ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); +- int pipe = psb_intel_crtc->pipe; +- unsigned long start, offset; +- int dsplinoff = DSPALINOFF; +- int dspsurf = DSPASURF; +- int dspstride = DSPASTRIDE; +- int dspcntr_reg = DSPACNTR; +- u32 dspcntr; +- int ret = 0; +- +- memcpy(&globle_dev, dev, sizeof(struct drm_device)); +- +- if (!gma_power_begin(dev, true)) +- return 0; +- +- /* no fb bound */ +- if (!crtc->fb) { +- dev_err(dev->dev, "No FB bound\n"); +- goto psb_intel_pipe_cleaner; +- } +- +- switch (pipe) { +- case 0: +- dsplinoff = DSPALINOFF; +- break; +- case 1: +- dsplinoff = DSPBLINOFF; +- dspsurf = DSPBSURF; +- dspstride = DSPBSTRIDE; +- dspcntr_reg = DSPBCNTR; +- break; +- case 2: +- dsplinoff = DSPCLINOFF; +- dspsurf = DSPCSURF; +- dspstride = DSPCSTRIDE; +- dspcntr_reg = DSPCCNTR; +- break; +- default: +- dev_err(dev->dev, "Illegal Pipe Number.\n"); +- return -EINVAL; +- } +- +- ret = psb_gtt_pin(psbfb->gtt); +- if (ret < 0) +- goto psb_intel_pipe_set_base_exit; +- +- start = psbfb->gtt->offset; +- offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); +- +- REG_WRITE(dspstride, crtc->fb->pitch); +- dspcntr = REG_READ(dspcntr_reg); +- dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; +- +- switch (crtc->fb->bits_per_pixel) { +- case 8: +- dspcntr |= DISPPLANE_8BPP; +- break; +- case 16: +- if (crtc->fb->depth == 15) +- dspcntr |= DISPPLANE_15_16BPP; +- else +- dspcntr |= DISPPLANE_16BPP; +- break; +- case 24: +- case 32: +- dspcntr |= DISPPLANE_32BPP_NO_ALPHA; +- break; +- default: +- dev_err(dev->dev, "Unknown color depth\n"); +- ret = -EINVAL; +- goto psb_intel_pipe_set_base_exit; +- } +- REG_WRITE(dspcntr_reg, dspcntr); +- +- dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n", +- start, offset, x, y); +- +- REG_WRITE(dsplinoff, offset); +- REG_READ(dsplinoff); +- REG_WRITE(dspsurf, start); +- REG_READ(dspsurf); +- +-psb_intel_pipe_cleaner: +- /* If there was a previous display we can now unpin it */ +- if (old_fb) +- psb_gtt_unpin(to_psb_fb(old_fb)->gtt); +- +-psb_intel_pipe_set_base_exit: +- gma_power_end(dev); +- return ret; +-} +- +-/** +- * Disable the pipe, plane and pll. +- * +- */ +-void mdfld_disable_crtc (struct drm_device *dev, int pipe) +-{ +- int dpll_reg = MRST_DPLL_A; +- int dspcntr_reg = DSPACNTR; +- int dspbase_reg = MRST_DSPABASE; +- int pipeconf_reg = PIPEACONF; +- u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG; +- u32 temp; +- +- switch (pipe) { +- case 0: +- break; +- case 1: +- dpll_reg = MDFLD_DPLL_B; +- dspcntr_reg = DSPBCNTR; +- dspbase_reg = DSPBSURF; +- pipeconf_reg = PIPEBCONF; +- break; +- case 2: +- dpll_reg = MRST_DPLL_A; +- dspcntr_reg = DSPCCNTR; +- dspbase_reg = MDFLD_DSPCBASE; +- pipeconf_reg = PIPECCONF; +- gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET; +- break; +- default: +- dev_err(dev->dev, "Illegal Pipe Number. \n"); +- return; +- } +- +- if (pipe != 1) +- mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); +- +- /* Disable display plane */ +- temp = REG_READ(dspcntr_reg); +- if ((temp & DISPLAY_PLANE_ENABLE) != 0) { +- REG_WRITE(dspcntr_reg, +- temp & ~DISPLAY_PLANE_ENABLE); +- /* Flush the plane changes */ +- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); +- REG_READ(dspbase_reg); +- } +- +- /* FIXME_JLIU7 MDFLD_PO revisit */ +- /* Wait for vblank for the disable to take effect */ +-/* MDFLD_PO_JLIU7 psb_intel_wait_for_vblank(dev); */ +- +- /* Next, disable display pipes */ +- temp = REG_READ(pipeconf_reg); +- if ((temp & PIPEACONF_ENABLE) != 0) { +- temp &= ~PIPEACONF_ENABLE; +- temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF; +- REG_WRITE(pipeconf_reg, temp); +- REG_READ(pipeconf_reg); +- +- /* Wait for for the pipe disable to take effect. */ +- mdfldWaitForPipeDisable(dev, pipe); +- } +- +- temp = REG_READ(dpll_reg); +- if (temp & DPLL_VCO_ENABLE) { +- if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE)) +- || (pipe == 1)){ +- temp &= ~(DPLL_VCO_ENABLE); +- REG_WRITE(dpll_reg, temp); +- REG_READ(dpll_reg); +- /* Wait for the clocks to turn off. */ +- /* FIXME_MDFLD PO may need more delay */ +- udelay(500); +- +- if (!(temp & MDFLD_PWR_GATE_EN)) { +- /* gating power of DPLL */ +- REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN); +- /* FIXME_MDFLD PO - change 500 to 1 after PO */ +- udelay(5000); +- } +- } +- } +- +-} +- +-/** +- * Sets the power management mode of the pipe and plane. +- * +- * This code should probably grow support for turning the cursor off and back +- * on appropriately at the same time as we're turning the pipe off/on. +- */ +-static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode) +-{ +- struct drm_device *dev = crtc->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- int dpll_reg = MRST_DPLL_A; +- int dspcntr_reg = DSPACNTR; +- int dspbase_reg = MRST_DSPABASE; +- int pipeconf_reg = PIPEACONF; +- u32 pipestat_reg = PIPEASTAT; +- u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG; +- u32 pipeconf = dev_priv->pipeconf; +- u32 dspcntr = dev_priv->dspcntr; +- u32 mipi_enable_reg = MIPIA_DEVICE_READY_REG; +- u32 temp; +- bool enabled; +- int timeout = 0; +- +- if (!gma_power_begin(dev, true)) +- return; +- +- /* Ignore if system is already in DSR and in suspended state. */ +- if(/*gbgfxsuspended */0 && dev_priv->dispstatus == false && mode == 3){ +- if(dev_priv->rpm_enabled && pipe == 1){ +- // dev_priv->is_mipi_on = false; +- pm_request_idle(&dev->pdev->dev); +- } +- return; +- }else if(mode == 0) { +- //do not need to set gbdispstatus=true in crtc. +- //this will be set in encoder such as mdfld_dsi_dbi_dpms +- //gbdispstatus = true; +- } +- +-/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */ +-/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */ +- +- switch (pipe) { +- case 0: +- break; +- case 1: +- dpll_reg = DPLL_B; +- dspcntr_reg = DSPBCNTR; +- dspbase_reg = MRST_DSPBBASE; +- pipeconf_reg = PIPEBCONF; +- pipeconf = dev_priv->pipeconf1; +- dspcntr = dev_priv->dspcntr1; +- dpll_reg = MDFLD_DPLL_B; +- break; +- case 2: +- dpll_reg = MRST_DPLL_A; +- dspcntr_reg = DSPCCNTR; +- dspbase_reg = MDFLD_DSPCBASE; +- pipeconf_reg = PIPECCONF; +- pipestat_reg = PIPECSTAT; +- pipeconf = dev_priv->pipeconf2; +- dspcntr = dev_priv->dspcntr2; +- gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET; +- mipi_enable_reg = MIPIA_DEVICE_READY_REG + MIPIC_REG_OFFSET; +- break; +- default: +- dev_err(dev->dev, "Illegal Pipe Number.\n"); +- return; +- } +- +- /* XXX: When our outputs are all unaware of DPMS modes other than off +- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. +- */ +- switch (mode) { +- case DRM_MODE_DPMS_ON: +- case DRM_MODE_DPMS_STANDBY: +- case DRM_MODE_DPMS_SUSPEND: +- /* Enable the DPLL */ +- temp = REG_READ(dpll_reg); +- +- if ((temp & DPLL_VCO_ENABLE) == 0) { +- /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */ +- if (temp & MDFLD_PWR_GATE_EN) { +- temp &= ~MDFLD_PWR_GATE_EN; +- REG_WRITE(dpll_reg, temp); +- /* FIXME_MDFLD PO - change 500 to 1 after PO */ +- udelay(500); +- } +- +- REG_WRITE(dpll_reg, temp); +- REG_READ(dpll_reg); +- /* FIXME_MDFLD PO - change 500 to 1 after PO */ +- udelay(500); +- +- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- +- /** +- * wait for DSI PLL to lock +- * NOTE: only need to poll status of pipe 0 and pipe 1, +- * since both MIPI pipes share the same PLL. +- */ +- while ((pipe != 2) && (timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { +- udelay(150); +- timeout ++; +- } +- } +- +- /* Enable the plane */ +- temp = REG_READ(dspcntr_reg); +- if ((temp & DISPLAY_PLANE_ENABLE) == 0) { +- REG_WRITE(dspcntr_reg, +- temp | DISPLAY_PLANE_ENABLE); +- /* Flush the plane changes */ +- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); +- } +- +- /* Enable the pipe */ +- temp = REG_READ(pipeconf_reg); +- if ((temp & PIPEACONF_ENABLE) == 0) { +- REG_WRITE(pipeconf_reg, pipeconf); +- +- /* Wait for for the pipe enable to take effect. */ +- mdfldWaitForPipeEnable(dev, pipe); +- } +- +- /*workaround for sighting 3741701 Random X blank display*/ +- /*perform w/a in video mode only on pipe A or C*/ +- if ((pipe == 0 || pipe == 2) && +- (mdfld_panel_dpi(dev) == true)) { +- REG_WRITE(pipestat_reg, REG_READ(pipestat_reg)); +- msleep(100); +- if(PIPE_VBLANK_STATUS & REG_READ(pipestat_reg)) { +- printk(KERN_ALERT "OK"); +- } else { +- printk(KERN_ALERT "STUCK!!!!"); +- /*shutdown controller*/ +- temp = REG_READ(dspcntr_reg); +- REG_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); +- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); +- /*mdfld_dsi_dpi_shut_down(dev, pipe);*/ +- REG_WRITE(0xb048, 1); +- msleep(100); +- temp = REG_READ(pipeconf_reg); +- temp &= ~PIPEACONF_ENABLE; +- REG_WRITE(pipeconf_reg, temp); +- msleep(100); /*wait for pipe disable*/ +- /*printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008)); +- printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));*/ +- REG_WRITE(mipi_enable_reg, 0); +- msleep(100); +- printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008)); +- printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074)); +- REG_WRITE(0xb004, REG_READ(0xb004)); +- /* try to bring the controller back up again*/ +- REG_WRITE(mipi_enable_reg, 1); +- temp = REG_READ(dspcntr_reg); +- REG_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); +- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); +- /*mdfld_dsi_dpi_turn_on(dev, pipe);*/ +- REG_WRITE(0xb048, 2); +- msleep(100); +- temp = REG_READ(pipeconf_reg); +- temp |= PIPEACONF_ENABLE; +- REG_WRITE(pipeconf_reg, temp); +- } +- } +- +- psb_intel_crtc_load_lut(crtc); +- +- /* Give the overlay scaler a chance to enable +- if it's on this pipe */ +- /* psb_intel_crtc_dpms_video(crtc, true); TODO */ +- +- break; +- case DRM_MODE_DPMS_OFF: +- /* Give the overlay scaler a chance to disable +- * if it's on this pipe */ +- /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ +- if (pipe != 1) +- mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); +- +- /* Disable the VGA plane that we never use */ +- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); +- +- /* Disable display plane */ +- temp = REG_READ(dspcntr_reg); +- if ((temp & DISPLAY_PLANE_ENABLE) != 0) { +- REG_WRITE(dspcntr_reg, +- temp & ~DISPLAY_PLANE_ENABLE); +- /* Flush the plane changes */ +- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); +- REG_READ(dspbase_reg); +- } +- +- /* FIXME_JLIU7 MDFLD_PO revisit */ +- /* Wait for vblank for the disable to take effect */ +-// MDFLD_PO_JLIU7 psb_intel_wait_for_vblank(dev); +- +- /* Next, disable display pipes */ +- temp = REG_READ(pipeconf_reg); +- if ((temp & PIPEACONF_ENABLE) != 0) { +- temp &= ~PIPEACONF_ENABLE; +- temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF; +- REG_WRITE(pipeconf_reg, temp); +-// REG_WRITE(pipeconf_reg, 0); +- REG_READ(pipeconf_reg); +- +- /* Wait for for the pipe disable to take effect. */ +- mdfldWaitForPipeDisable(dev, pipe); +- } +- +- temp = REG_READ(dpll_reg); +- if (temp & DPLL_VCO_ENABLE) { +- if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE)) +- || (pipe == 1)){ +- temp &= ~(DPLL_VCO_ENABLE); +- REG_WRITE(dpll_reg, temp); +- REG_READ(dpll_reg); +- /* Wait for the clocks to turn off. */ +- /* FIXME_MDFLD PO may need more delay */ +- udelay(500); +-#if 0 /* MDFLD_PO_JLIU7 */ +- if (!(temp & MDFLD_PWR_GATE_EN)) { +- /* gating power of DPLL */ +- REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN); +- /* FIXME_MDFLD PO - change 500 to 1 after PO */ +- udelay(5000); +- } +-#endif /* MDFLD_PO_JLIU7 */ +- } +- } +- break; +- } +- +- enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; +- +-#if 0 /* JB: Add vblank support later */ +- if (enabled) +- dev_priv->vblank_pipe |= (1 << pipe); +- else +- dev_priv->vblank_pipe &= ~(1 << pipe); +-#endif +- +- gma_power_end(dev); +-} +- +- +-#define MDFLD_LIMT_DPLL_19 0 +-#define MDFLD_LIMT_DPLL_25 1 +-#define MDFLD_LIMT_DPLL_83 2 +-#define MDFLD_LIMT_DPLL_100 3 +-#define MDFLD_LIMT_DSIPLL_19 4 +-#define MDFLD_LIMT_DSIPLL_25 5 +-#define MDFLD_LIMT_DSIPLL_83 6 +-#define MDFLD_LIMT_DSIPLL_100 7 +- +-#define MDFLD_DOT_MIN 19750 /* FIXME_MDFLD JLIU7 need to find out min & max for MDFLD */ +-#define MDFLD_DOT_MAX 120000 +-#define MDFLD_DPLL_M_MIN_19 113 +-#define MDFLD_DPLL_M_MAX_19 155 +-#define MDFLD_DPLL_P1_MIN_19 2 +-#define MDFLD_DPLL_P1_MAX_19 10 +-#define MDFLD_DPLL_M_MIN_25 101 +-#define MDFLD_DPLL_M_MAX_25 130 +-#define MDFLD_DPLL_P1_MIN_25 2 +-#define MDFLD_DPLL_P1_MAX_25 10 +-#define MDFLD_DPLL_M_MIN_83 64 +-#define MDFLD_DPLL_M_MAX_83 64 +-#define MDFLD_DPLL_P1_MIN_83 2 +-#define MDFLD_DPLL_P1_MAX_83 2 +-#define MDFLD_DPLL_M_MIN_100 64 +-#define MDFLD_DPLL_M_MAX_100 64 +-#define MDFLD_DPLL_P1_MIN_100 2 +-#define MDFLD_DPLL_P1_MAX_100 2 +-#define MDFLD_DSIPLL_M_MIN_19 131 +-#define MDFLD_DSIPLL_M_MAX_19 175 +-#define MDFLD_DSIPLL_P1_MIN_19 3 +-#define MDFLD_DSIPLL_P1_MAX_19 8 +-#define MDFLD_DSIPLL_M_MIN_25 97 +-#define MDFLD_DSIPLL_M_MAX_25 140 +-#define MDFLD_DSIPLL_P1_MIN_25 3 +-#define MDFLD_DSIPLL_P1_MAX_25 9 +-#define MDFLD_DSIPLL_M_MIN_83 33 +-#define MDFLD_DSIPLL_M_MAX_83 92 +-#define MDFLD_DSIPLL_P1_MIN_83 2 +-#define MDFLD_DSIPLL_P1_MAX_83 3 +-#define MDFLD_DSIPLL_M_MIN_100 97 +-#define MDFLD_DSIPLL_M_MAX_100 140 +-#define MDFLD_DSIPLL_P1_MIN_100 3 +-#define MDFLD_DSIPLL_P1_MAX_100 9 +- +-static const struct mdfld_limit_t mdfld_limits[] = { +- { /* MDFLD_LIMT_DPLL_19 */ +- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, +- .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19}, +- .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19}, +- }, +- { /* MDFLD_LIMT_DPLL_25 */ +- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, +- .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25}, +- .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25}, +- }, +- { /* MDFLD_LIMT_DPLL_83 */ +- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, +- .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83}, +- .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83}, +- }, +- { /* MDFLD_LIMT_DPLL_100 */ +- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, +- .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100}, +- .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100}, +- }, +- { /* MDFLD_LIMT_DSIPLL_19 */ +- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, +- .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19}, +- .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19}, +- }, +- { /* MDFLD_LIMT_DSIPLL_25 */ +- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, +- .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25}, +- .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25}, +- }, +- { /* MDFLD_LIMT_DSIPLL_83 */ +- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, +- .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83}, +- .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83}, +- }, +- { /* MDFLD_LIMT_DSIPLL_100 */ +- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, +- .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100}, +- .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100}, +- }, +-}; +- +-#define MDFLD_M_MIN 21 +-#define MDFLD_M_MAX 180 +-static const u32 mdfld_m_converts[] = { +-/* M configuration table from 9-bit LFSR table */ +- 224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */ +- 173, 342, 171, 85, 298, 149, 74, 37, 18, 265, /* 31 - 40 */ +- 388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */ +- 83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */ +- 341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */ +- 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */ +- 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */ +- 71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */ +- 253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */ +- 478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */ +- 477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */ +- 210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */ +- 145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */ +- 380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */ +- 103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */ +- 396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */ +-}; +- +-static const struct mdfld_limit_t *mdfld_limit(struct drm_crtc *crtc) +-{ +- const struct mdfld_limit_t *limit = NULL; +- struct drm_device *dev = crtc->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI) +- || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) { +- if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) +- limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19]; +- else if (ksel == KSEL_BYPASS_25) +- limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25]; +- else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) +- limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83]; +- else if ((ksel == KSEL_BYPASS_83_100) && +- (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) +- limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100]; +- } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { +- if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) +- limit = &mdfld_limits[MDFLD_LIMT_DPLL_19]; +- else if (ksel == KSEL_BYPASS_25) +- limit = &mdfld_limits[MDFLD_LIMT_DPLL_25]; +- else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) +- limit = &mdfld_limits[MDFLD_LIMT_DPLL_83]; +- else if ((ksel == KSEL_BYPASS_83_100) && +- (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) +- limit = &mdfld_limits[MDFLD_LIMT_DPLL_100]; +- } else { +- limit = NULL; +- dev_err(dev->dev, "mdfld_limit Wrong display type.\n"); +- } +- +- return limit; +-} +- +-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ +-static void mdfld_clock(int refclk, struct mdfld_intel_clock_t *clock) +-{ +- clock->dot = (refclk * clock->m) / clock->p1; +-} +- +-/** +- * Returns a set of divisors for the desired target clock with the given refclk, +- * or FALSE. Divisor values are the actual divisors for +- */ +-static bool +-mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk, +- struct mdfld_intel_clock_t *best_clock) +-{ +- struct mdfld_intel_clock_t clock; +- const struct mdfld_limit_t *limit = mdfld_limit(crtc); +- int err = target; +- +- memset(best_clock, 0, sizeof(*best_clock)); +- +- for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { +- for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; +- clock.p1++) { +- int this_err; +- +- mdfld_clock(refclk, &clock); +- +- this_err = abs(clock.dot - target); +- if (this_err < err) { +- *best_clock = clock; +- err = this_err; +- } +- } +- } +- return err != target; +-} +- +-/** +- * Return the pipe currently connected to the panel fitter, +- * or -1 if the panel fitter is not present or not in use +- */ +-static int mdfld_panel_fitter_pipe(struct drm_device *dev) +-{ +- u32 pfit_control; +- +- pfit_control = REG_READ(PFIT_CONTROL); +- +- /* See if the panel fitter is in use */ +- if ((pfit_control & PFIT_ENABLE) == 0) +- return -1; +- return (pfit_control >> 29) & 3; +-} +- +-static int mdfld_crtc_mode_set(struct drm_crtc *crtc, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode, +- int x, int y, +- struct drm_framebuffer *old_fb) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct drm_psb_private *dev_priv = dev->dev_private; +- int pipe = psb_intel_crtc->pipe; +- int fp_reg = MRST_FPA0; +- int dpll_reg = MRST_DPLL_A; +- int dspcntr_reg = DSPACNTR; +- int pipeconf_reg = PIPEACONF; +- int htot_reg = HTOTAL_A; +- int hblank_reg = HBLANK_A; +- int hsync_reg = HSYNC_A; +- int vtot_reg = VTOTAL_A; +- int vblank_reg = VBLANK_A; +- int vsync_reg = VSYNC_A; +- int dspsize_reg = DSPASIZE; +- int dsppos_reg = DSPAPOS; +- int pipesrc_reg = PIPEASRC; +- u32 *pipeconf = &dev_priv->pipeconf; +- u32 *dspcntr = &dev_priv->dspcntr; +- int refclk = 0; +- int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0, clk_tmp = 0; +- struct mdfld_intel_clock_t clock; +- bool ok; +- u32 dpll = 0, fp = 0; +- bool is_crt = false, is_lvds = false, is_tv = false; +- bool is_mipi = false, is_mipi2 = false, is_hdmi = false; +- struct drm_mode_config *mode_config = &dev->mode_config; +- struct psb_intel_output *psb_intel_output = NULL; +- uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; +- struct drm_encoder *encoder; +- struct drm_connector *connector; +- int timeout = 0; +- +- dev_dbg(dev->dev, "pipe = 0x%x \n", pipe); +- +- switch (pipe) { +- case 0: +- break; +- case 1: +- fp_reg = FPB0; +- dpll_reg = DPLL_B; +- dspcntr_reg = DSPBCNTR; +- pipeconf_reg = PIPEBCONF; +- htot_reg = HTOTAL_B; +- hblank_reg = HBLANK_B; +- hsync_reg = HSYNC_B; +- vtot_reg = VTOTAL_B; +- vblank_reg = VBLANK_B; +- vsync_reg = VSYNC_B; +- dspsize_reg = DSPBSIZE; +- dsppos_reg = DSPBPOS; +- pipesrc_reg = PIPEBSRC; +- pipeconf = &dev_priv->pipeconf1; +- dspcntr = &dev_priv->dspcntr1; +- fp_reg = MDFLD_DPLL_DIV0; +- dpll_reg = MDFLD_DPLL_B; +- break; +- case 2: +- dpll_reg = MRST_DPLL_A; +- dspcntr_reg = DSPCCNTR; +- pipeconf_reg = PIPECCONF; +- htot_reg = HTOTAL_C; +- hblank_reg = HBLANK_C; +- hsync_reg = HSYNC_C; +- vtot_reg = VTOTAL_C; +- vblank_reg = VBLANK_C; +- vsync_reg = VSYNC_C; +- dspsize_reg = DSPCSIZE; +- dsppos_reg = DSPCPOS; +- pipesrc_reg = PIPECSRC; +- pipeconf = &dev_priv->pipeconf2; +- dspcntr = &dev_priv->dspcntr2; +- break; +- default: +- DRM_ERROR("Illegal Pipe Number. \n"); +- return 0; +- } +- +- dev_dbg(dev->dev, "adjusted_hdisplay = %d\n", +- adjusted_mode->hdisplay); +- dev_dbg(dev->dev, "adjusted_vdisplay = %d\n", +- adjusted_mode->vdisplay); +- dev_dbg(dev->dev, "adjusted_hsync_start = %d\n", +- adjusted_mode->hsync_start); +- dev_dbg(dev->dev, "adjusted_hsync_end = %d\n", +- adjusted_mode->hsync_end); +- dev_dbg(dev->dev, "adjusted_htotal = %d\n", +- adjusted_mode->htotal); +- dev_dbg(dev->dev, "adjusted_vsync_start = %d\n", +- adjusted_mode->vsync_start); +- dev_dbg(dev->dev, "adjusted_vsync_end = %d\n", +- adjusted_mode->vsync_end); +- dev_dbg(dev->dev, "adjusted_vtotal = %d\n", +- adjusted_mode->vtotal); +- dev_dbg(dev->dev, "adjusted_clock = %d\n", +- adjusted_mode->clock); +- dev_dbg(dev->dev, "hdisplay = %d\n", +- mode->hdisplay); +- dev_dbg(dev->dev, "vdisplay = %d\n", +- mode->vdisplay); +- +- if (!gma_power_begin(dev, true)) +- return 0; +- +- memcpy(&psb_intel_crtc->saved_mode, mode, sizeof(struct drm_display_mode)); +- memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, sizeof(struct drm_display_mode)); +- +- list_for_each_entry(connector, &mode_config->connector_list, head) { +- +- encoder = connector->encoder; +- +- if(!encoder) +- continue; +- +- if (encoder->crtc != crtc) +- continue; +- +- psb_intel_output = to_psb_intel_output(connector); +- +- dev_dbg(dev->dev, "output->type = 0x%x \n", psb_intel_output->type); +- +- switch (psb_intel_output->type) { +- case INTEL_OUTPUT_LVDS: +- is_lvds = true; +- break; +- case INTEL_OUTPUT_TVOUT: +- is_tv = true; +- break; +- case INTEL_OUTPUT_ANALOG: +- is_crt = true; +- break; +- case INTEL_OUTPUT_MIPI: +- is_mipi = true; +- break; +- case INTEL_OUTPUT_MIPI2: +- is_mipi2 = true; +- break; +- case INTEL_OUTPUT_HDMI: +- is_hdmi = true; +- break; +- } +- } +- +- /* Disable the VGA plane that we never use */ +- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); +- +- /* Disable the panel fitter if it was on our pipe */ +- if (mdfld_panel_fitter_pipe(dev) == pipe) +- REG_WRITE(PFIT_CONTROL, 0); +- +- /* pipesrc and dspsize control the size that is scaled from, +- * which should always be the user's requested size. +- */ +- if (pipe == 1) { +- /* FIXME: To make HDMI display with 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD), set the sprite +- * width/height and souce image size registers with the adjusted mode for pipe B. */ +- +- /* The defined sprite rectangle must always be completely contained within the displayable +- * area of the screen image (frame buffer). */ +- REG_WRITE(dspsize_reg, ((MIN(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16) +- | (MIN(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1)); +- /* Set the CRTC with encoder mode. */ +- REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) +- | (mode->crtc_vdisplay - 1)); +- } else { +- REG_WRITE(dspsize_reg, ((mode->crtc_vdisplay - 1) << 16) | (mode->crtc_hdisplay - 1)); +- REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1)); +- } +- +- REG_WRITE(dsppos_reg, 0); +- +- if (psb_intel_output) +- drm_connector_property_get_value(&psb_intel_output->base, +- dev->mode_config.scaling_mode_property, &scalingType); +- +- if (scalingType == DRM_MODE_SCALE_NO_SCALE) { +- /* +- * Medfield doesn't have register support for centering so +- * we need to mess with the h/vblank and h/vsync start and +- * ends to get central +- */ +- int offsetX = 0, offsetY = 0; +- +- offsetX = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; +- offsetY = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; +- +- REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) | +- ((adjusted_mode->crtc_htotal - 1) << 16)); +- REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) | +- ((adjusted_mode->crtc_vtotal - 1) << 16)); +- REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - offsetX - 1) | +- ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); +- REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - offsetX - 1) | +- ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); +- REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - offsetY - 1) | +- ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); +- REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - offsetY - 1) | +- ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); +- } else { +- REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | +- ((adjusted_mode->crtc_htotal - 1) << 16)); +- REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | +- ((adjusted_mode->crtc_vtotal - 1) << 16)); +- REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | +- ((adjusted_mode->crtc_hblank_end - 1) << 16)); +- REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | +- ((adjusted_mode->crtc_hsync_end - 1) << 16)); +- REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | +- ((adjusted_mode->crtc_vblank_end - 1) << 16)); +- REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | +- ((adjusted_mode->crtc_vsync_end - 1) << 16)); +- } +- +- /* Flush the plane changes */ +- { +- struct drm_crtc_helper_funcs *crtc_funcs = +- crtc->helper_private; +- crtc_funcs->mode_set_base(crtc, x, y, old_fb); +- } +- +- /* setup pipeconf */ +- *pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */ +- +- /* Set up the display plane register */ +- *dspcntr = REG_READ(dspcntr_reg); +- *dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS; +- *dspcntr |= DISPLAY_PLANE_ENABLE; +-/* MDFLD_PO_JLIU7 dspcntr |= DISPPLANE_BOTTOM; */ +-/* MDFLD_PO_JLIU7 dspcntr |= DISPPLANE_GAMMA_ENABLE; */ +- +- if (is_mipi2) +- { +- goto mrst_crtc_mode_set_exit; +- } +-/* FIXME JLIU7 Add MDFLD HDMI supports */ +-/* FIXME_MDFLD JLIU7 DSIPLL clock *= 8? */ +-/* FIXME_MDFLD JLIU7 need to revist for dual MIPI supports */ +- clk = adjusted_mode->clock; +- +- if (is_hdmi) { +- if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) +- { +- refclk = 19200; +- +- if (is_mipi || is_mipi2) +- { +- clk_n = 1, clk_p2 = 8; +- } else if (is_hdmi) { +- clk_n = 1, clk_p2 = 10; +- } +- } else if (ksel == KSEL_BYPASS_25) { +- refclk = 25000; +- +- if (is_mipi || is_mipi2) +- { +- clk_n = 1, clk_p2 = 8; +- } else if (is_hdmi) { +- clk_n = 1, clk_p2 = 10; +- } +- } else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) { +- refclk = 83000; +- +- if (is_mipi || is_mipi2) +- { +- clk_n = 4, clk_p2 = 8; +- } else if (is_hdmi) { +- clk_n = 4, clk_p2 = 10; +- } +- } else if ((ksel == KSEL_BYPASS_83_100) && +- (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) { +- refclk = 100000; +- if (is_mipi || is_mipi2) +- { +- clk_n = 4, clk_p2 = 8; +- } else if (is_hdmi) { +- clk_n = 4, clk_p2 = 10; +- } +- } +- +- if (is_mipi) +- clk_byte = dev_priv->bpp / 8; +- else if (is_mipi2) +- clk_byte = dev_priv->bpp2 / 8; +- +- clk_tmp = clk * clk_n * clk_p2 * clk_byte; +- +- dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n, clk_p2); +- dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d. \n", adjusted_mode->clock, clk_tmp); +- +- ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock); +- +- if (!ok) { +- dev_err(dev->dev, +- "mdfldFindBestPLL fail in mdfld_crtc_mode_set. \n"); +- } else { +- m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)]; +- +- dev_dbg(dev->dev, "dot clock = %d," +- "m = %d, p1 = %d, m_conv = %d. \n", clock.dot, clock.m, +- clock.p1, m_conv); +- } +- +- dpll = REG_READ(dpll_reg); +- +- if (dpll & DPLL_VCO_ENABLE) { +- dpll &= ~DPLL_VCO_ENABLE; +- REG_WRITE(dpll_reg, dpll); +- REG_READ(dpll_reg); +- +- /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */ +- /* FIXME_MDFLD PO - change 500 to 1 after PO */ +- udelay(500); +- +- /* reset M1, N1 & P1 */ +- REG_WRITE(fp_reg, 0); +- dpll &= ~MDFLD_P1_MASK; +- REG_WRITE(dpll_reg, dpll); +- /* FIXME_MDFLD PO - change 500 to 1 after PO */ +- udelay(500); +- } +- +- /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */ +- if (dpll & MDFLD_PWR_GATE_EN) { +- dpll &= ~MDFLD_PWR_GATE_EN; +- REG_WRITE(dpll_reg, dpll); +- /* FIXME_MDFLD PO - change 500 to 1 after PO */ +- udelay(500); +- } +- +- dpll = 0; +- +-#if 0 /* FIXME revisit later */ +- if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19) || (ksel == KSEL_BYPASS_25)) { +- dpll &= ~MDFLD_INPUT_REF_SEL; +- } else if (ksel == KSEL_BYPASS_83_100) { +- dpll |= MDFLD_INPUT_REF_SEL; +- } +-#endif /* FIXME revisit later */ +- +- if (is_hdmi) +- dpll |= MDFLD_VCO_SEL; +- +- fp = (clk_n / 2) << 16; +- fp |= m_conv; +- +- /* compute bitmask from p1 value */ +- dpll |= (1 << (clock.p1 - 2)) << 17; +- +-#if 0 /* 1080p30 & 720p */ +- dpll = 0x00050000; +- fp = 0x000001be; +-#endif +-#if 0 /* 480p */ +- dpll = 0x02010000; +- fp = 0x000000d2; +-#endif +- } else { +-#if 0 /*DBI_TPO_480x864*/ +- dpll = 0x00020000; +- fp = 0x00000156; +-#endif /* DBI_TPO_480x864 */ /* get from spec. */ +- +- dpll = 0x00800000; +- fp = 0x000000c1; +-} +- +- REG_WRITE(fp_reg, fp); +- REG_WRITE(dpll_reg, dpll); +- /* FIXME_MDFLD PO - change 500 to 1 after PO */ +- udelay(500); +- +- dpll |= DPLL_VCO_ENABLE; +- REG_WRITE(dpll_reg, dpll); +- REG_READ(dpll_reg); +- +- /* wait for DSI PLL to lock */ +- while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { +- udelay(150); +- timeout ++; +- } +- +- if (is_mipi) +- goto mrst_crtc_mode_set_exit; +- +- dev_dbg(dev->dev, "is_mipi = 0x%x \n", is_mipi); +- +- REG_WRITE(pipeconf_reg, *pipeconf); +- REG_READ(pipeconf_reg); +- +- /* Wait for for the pipe enable to take effect. */ +-//FIXME_JLIU7 HDMI mrstWaitForPipeEnable(dev); +- +- REG_WRITE(dspcntr_reg, *dspcntr); +- psb_intel_wait_for_vblank(dev); +- +-mrst_crtc_mode_set_exit: +- +- gma_power_end(dev); +- +- return 0; +-} +- +-static void mdfld_crtc_prepare(struct drm_crtc *crtc) +-{ +- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); +-} +- +-static void mdfld_crtc_commit(struct drm_crtc *crtc) +-{ +- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); +-} +- +-static bool mdfld_crtc_mode_fixup(struct drm_crtc *crtc, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- return true; +-} +- +-const struct drm_crtc_helper_funcs mdfld_helper_funcs = { +- .dpms = mdfld_crtc_dpms, +- .mode_fixup = mdfld_crtc_mode_fixup, +- .mode_set = mdfld_crtc_mode_set, +- .mode_set_base = mdfld__intel_pipe_set_base, +- .prepare = mdfld_crtc_prepare, +- .commit = mdfld_crtc_commit, +-}; +diff --git a/drivers/staging/gma500/mdfld_msic.h b/drivers/staging/gma500/mdfld_msic.h +deleted file mode 100644 +index a7ad6547..0000000 +--- a/drivers/staging/gma500/mdfld_msic.h ++++ /dev/null +@@ -1,31 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Jim Liu +- */ +- +-#define MSIC_PCI_DEVICE_ID 0x831 +- +-int msic_regsiter_driver(void); +-int msic_unregister_driver(void); +-extern void hpd_notify_um(void); +diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c +deleted file mode 100644 +index eabf53d..0000000 +--- a/drivers/staging/gma500/mdfld_output.c ++++ /dev/null +@@ -1,171 +0,0 @@ +-/* +- * Copyright (c) 2010 Intel Corporation +- * +- * 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, sublicensen +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Thomas Eaton +- * Scott Rowe +-*/ +- +-#include +-#include +-#include "mdfld_dsi_dbi.h" +-#include "mdfld_dsi_dpi.h" +-#include "mdfld_dsi_output.h" +-#include "mdfld_output.h" +-#include "mdfld_dsi_dbi_dpu.h" +- +-#include "displays/tpo_cmd.h" +-#include "displays/tpo_vid.h" +-#include "displays/tmd_cmd.h" +-#include "displays/tmd_vid.h" +-#include "displays/pyr_cmd.h" +-#include "displays/pyr_vid.h" +-/* #include "displays/hdmi.h" */ +- +-static int mdfld_dual_mipi; +-static int mdfld_hdmi; +-static int mdfld_dpu; +- +-module_param(mdfld_dual_mipi, int, 0600); +-MODULE_PARM_DESC(mdfld_dual_mipi, "Enable dual MIPI configuration"); +-module_param(mdfld_hdmi, int, 0600); +-MODULE_PARM_DESC(mdfld_hdmi, "Enable Medfield HDMI"); +-module_param(mdfld_dpu, int, 0600); +-MODULE_PARM_DESC(mdfld_dpu, "Enable Medfield DPU"); +- +-/* For now a single type per device is all we cope with */ +-int mdfld_get_panel_type(struct drm_device *dev, int pipe) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- return dev_priv->panel_id; +-} +- +-int mdfld_panel_dpi(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- switch (dev_priv->panel_id) { +- case TMD_VID: +- case TPO_VID: +- case PYR_VID: +- return true; +- case TMD_CMD: +- case TPO_CMD: +- case PYR_CMD: +- default: +- return false; +- } +-} +- +-static int init_panel(struct drm_device *dev, int mipi_pipe, int p_type) +-{ +- struct panel_funcs *p_cmd_funcs; +- struct panel_funcs *p_vid_funcs; +- +- /* Oh boy ... FIXME */ +- p_cmd_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL); +- if (p_cmd_funcs == NULL) +- return -ENODEV; +- p_vid_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL); +- if (p_vid_funcs == NULL) { +- kfree(p_cmd_funcs); +- return -ENODEV; +- } +- +- switch (p_type) { +- case TPO_CMD: +- tpo_cmd_init(dev, p_cmd_funcs); +- mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL); +- break; +- case TPO_VID: +- tpo_vid_init(dev, p_vid_funcs); +- mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs); +- break; +- case TMD_CMD: +- /*tmd_cmd_init(dev, p_cmd_funcs); */ +- mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL); +- break; +- case TMD_VID: +- tmd_vid_init(dev, p_vid_funcs); +- mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs); +- break; +- case PYR_CMD: +- pyr_cmd_init(dev, p_cmd_funcs); +- mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL); +- break; +- case PYR_VID: +- mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs); +- break; +- case TPO: /* TPO panel supports both cmd & vid interfaces */ +- tpo_cmd_init(dev, p_cmd_funcs); +- tpo_vid_init(dev, p_vid_funcs); +- mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, +- p_vid_funcs); +- break; +- case TMD: +- break; +- case PYR: +- break; +-#if 0 +- case HDMI: +- dev_dbg(dev->dev, "Initializing HDMI"); +- mdfld_hdmi_init(dev, &dev_priv->mode_dev); +- break; +-#endif +- default: +- dev_err(dev->dev, "Unsupported interface %d", p_type); +- return -ENODEV; +- } +- return 0; +-} +- +-int mdfld_output_init(struct drm_device *dev) +-{ +- int type; +- +- /* MIPI panel 1 */ +- type = mdfld_get_panel_type(dev, 0); +- dev_info(dev->dev, "panel 1: type is %d\n", type); +- init_panel(dev, 0, type); +- +- if (mdfld_dual_mipi) { +- /* MIPI panel 2 */ +- type = mdfld_get_panel_type(dev, 2); +- dev_info(dev->dev, "panel 2: type is %d\n", type); +- init_panel(dev, 2, type); +- } +- if (mdfld_hdmi) +- /* HDMI panel */ +- init_panel(dev, 0, HDMI); +- return 0; +-} +- +-void mdfld_output_setup(struct drm_device *dev) +-{ +- /* FIXME: this is not the right place for this stuff ! */ +- if (IS_MFLD(dev)) { +- if (mdfld_dpu) +- mdfld_dbi_dpu_init(dev); +- else +- mdfld_dbi_dsr_init(dev); +- } +-} +diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h +deleted file mode 100644 +index daf33e7..0000000 +--- a/drivers/staging/gma500/mdfld_output.h ++++ /dev/null +@@ -1,41 +0,0 @@ +-/* +- * Copyright (c) 2010 Intel Corporation +- * +- * 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, sublicensen +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Thomas Eaton +- * Scott Rowe +-*/ +- +-#ifndef MDFLD_OUTPUT_H +-#define MDFLD_OUTPUT_H +- +-int mdfld_output_init(struct drm_device *dev); +-int mdfld_panel_dpi(struct drm_device *dev); +-int mdfld_get_panel_type(struct drm_device *dev, int pipe); +-void mdfld_disable_crtc (struct drm_device *dev, int pipe); +- +-extern const struct drm_crtc_helper_funcs mdfld_helper_funcs; +-extern const struct drm_crtc_funcs mdfld_intel_crtc_funcs; +- +-extern void mdfld_output_setup(struct drm_device *dev); +- +-#endif +diff --git a/drivers/staging/gma500/mdfld_pyr_cmd.c b/drivers/staging/gma500/mdfld_pyr_cmd.c +deleted file mode 100644 +index 523f2d8..0000000 +--- a/drivers/staging/gma500/mdfld_pyr_cmd.c ++++ /dev/null +@@ -1,558 +0,0 @@ +-/* +- * Copyright (c) 2010 Intel Corporation +- * +- * 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, sublicensen +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Thomas Eaton +- * Scott Rowe +-*/ +- +-#include "mdfld_dsi_dbi.h" +-#include "mdfld_dsi_dpi.h" +-#include "mdfld_dsi_output.h" +-#include "mdfld_output.h" +-#include "mdfld_dsi_dbi_dpu.h" +-#include "mdfld_dsi_pkg_sender.h" +- +-#include "displays/pyr_cmd.h" +- +-static struct drm_display_mode *pyr_cmd_get_config_mode(struct drm_device *dev) +-{ +- struct drm_display_mode *mode; +- +- mode = kzalloc(sizeof(*mode), GFP_KERNEL); +- if (!mode) { +- dev_err(dev->dev, "Out of memory\n"); +- return NULL; +- } +- +- dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); +- dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); +- dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); +- dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); +- dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); +- dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); +- dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); +- dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); +- dev_dbg(dev->dev, "clock is %d\n", mode->clock); +- +- mode->hdisplay = 480; +- mode->vdisplay = 864; +- mode->hsync_start = 487; +- mode->hsync_end = 490; +- mode->htotal = 499; +- mode->vsync_start = 874; +- mode->vsync_end = 878; +- mode->vtotal = 886; +- mode->clock = 25777; +- +- drm_mode_set_name(mode); +- drm_mode_set_crtcinfo(mode, 0); +- +- mode->type |= DRM_MODE_TYPE_PREFERRED; +- +- return mode; +-} +- +-static bool pyr_dsi_dbi_mode_fixup(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- struct drm_device *dev = encoder->dev; +- struct drm_display_mode *fixed_mode = pyr_cmd_get_config_mode(dev); +- +- if (fixed_mode) { +- adjusted_mode->hdisplay = fixed_mode->hdisplay; +- adjusted_mode->hsync_start = fixed_mode->hsync_start; +- adjusted_mode->hsync_end = fixed_mode->hsync_end; +- adjusted_mode->htotal = fixed_mode->htotal; +- adjusted_mode->vdisplay = fixed_mode->vdisplay; +- adjusted_mode->vsync_start = fixed_mode->vsync_start; +- adjusted_mode->vsync_end = fixed_mode->vsync_end; +- adjusted_mode->vtotal = fixed_mode->vtotal; +- adjusted_mode->clock = fixed_mode->clock; +- drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); +- kfree(fixed_mode); +- } +- return true; +-} +- +-static void pyr_dsi_dbi_set_power(struct drm_encoder *encoder, bool on) +-{ +- int ret = 0; +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_dbi_output *dbi_output = +- MDFLD_DSI_DBI_OUTPUT(dsi_encoder); +- struct drm_device *dev = encoder->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 reg_offset = 0; +- int pipe = (dbi_output->channel_num == 0) ? 0 : 2; +- +- dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", pipe, +- on ? "On" : "Off", +- dbi_output->dbi_panel_on ? "True" : "False"); +- +- if (pipe == 2) { +- if (on) +- dev_priv->dual_mipi = true; +- else +- dev_priv->dual_mipi = false; +- +- reg_offset = MIPIC_REG_OFFSET; +- } else { +- if (!on) +- dev_priv->dual_mipi = false; +- } +- +- if (!gma_power_begin(dev, true)) { +- dev_err(dev->dev, "hw begin failed\n"); +- return; +- } +- +- +- if (on) { +- if (dbi_output->dbi_panel_on) +- goto out_err; +- +- ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON); +- if (ret) { +- dev_err(dev->dev, "power on error\n"); +- goto out_err; +- } +- +- dbi_output->dbi_panel_on = true; +- +- if (pipe == 2) { +- dev_priv->dbi_panel_on2 = true; +- } else { +- dev_priv->dbi_panel_on = true; +- mdfld_enable_te(dev, 0); +- } +- } else { +- if (!dbi_output->dbi_panel_on && !dbi_output->first_boot) +- goto out_err; +- +- dbi_output->dbi_panel_on = false; +- dbi_output->first_boot = false; +- +- if (pipe == 2) { +- dev_priv->dbi_panel_on2 = false; +- mdfld_disable_te(dev, 2); +- } else { +- dev_priv->dbi_panel_on = false; +- mdfld_disable_te(dev, 0); +- +- if (dev_priv->dbi_panel_on2) +- mdfld_enable_te(dev, 2); +- } +- +- ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF); +- if (ret) { +- dev_err(dev->dev, "power on error\n"); +- goto out_err; +- } +- } +- +-out_err: +- gma_power_end(dev); +- +- if (ret) +- dev_err(dev->dev, "failed\n"); +-} +- +-static void pyr_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config, +- int pipe) +-{ +- struct drm_device *dev = dsi_config->dev; +- u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; +- int lane_count = dsi_config->lane_count; +- u32 val = 0; +- +- dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe); +- +- /* Un-ready device */ +- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); +- +- /* Init dsi adapter before kicking off */ +- REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); +- +- /* TODO: figure out how to setup these registers */ +- REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c600F); +- REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), +- 0x000a0014); +- REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400); +- REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000); +- +- /* Enable all interrupts */ +- REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); +- /* Max value: 20 clock cycles of txclkesc */ +- REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f); +- /* Min 21 txclkesc, max: ffffh */ +- REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff); +- /* Min: 7d0 max: 4e20 */ +- REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0); +- +- /* Set up func_prg */ +- val |= lane_count; +- val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET); +- val |= DSI_DBI_COLOR_FORMAT_OPTION2; +- REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); +- +- REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff); +- REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff); +- +- /* De-assert dbi_stall when half of DBI FIFO is empty */ +- /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */ +- +- REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); +- REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000002); +- REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); +- REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); +-} +- +-static void pyr_dsi_dbi_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- int ret = 0; +- struct drm_device *dev = encoder->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_dbi_output *dsi_output = +- MDFLD_DSI_DBI_OUTPUT(dsi_encoder); +- struct mdfld_dsi_config *dsi_config = +- mdfld_dsi_encoder_get_config(dsi_encoder); +- struct mdfld_dsi_connector *dsi_connector = dsi_config->connector; +- int pipe = dsi_connector->pipe; +- u8 param = 0; +- +- /* Regs */ +- u32 mipi_reg = MIPI; +- u32 dspcntr_reg = DSPACNTR; +- u32 pipeconf_reg = PIPEACONF; +- u32 reg_offset = 0; +- +- /* Values */ +- u32 dspcntr_val = dev_priv->dspcntr; +- u32 pipeconf_val = dev_priv->pipeconf; +- u32 h_active_area = mode->hdisplay; +- u32 v_active_area = mode->vdisplay; +- u32 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX | +- TE_TRIGGER_GPIO_PIN); +- +- dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val); +- +- dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI"); +- dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay); +- +- if (pipe == 2) { +- mipi_reg = MIPI_C; +- dspcntr_reg = DSPCCNTR; +- pipeconf_reg = PIPECCONF; +- +- reg_offset = MIPIC_REG_OFFSET; +- +- dspcntr_val = dev_priv->dspcntr2; +- pipeconf_val = dev_priv->pipeconf2; +- } else { +- mipi_val |= 0x2; /* Two lanes for port A and C respectively */ +- } +- +- if (!gma_power_begin(dev, true)) { +- dev_err(dev->dev, "hw begin failed\n"); +- return; +- } +- +- /* Set up pipe related registers */ +- REG_WRITE(mipi_reg, mipi_val); +- REG_READ(mipi_reg); +- +- pyr_dsi_controller_dbi_init(dsi_config, pipe); +- +- msleep(20); +- +- REG_WRITE(dspcntr_reg, dspcntr_val); +- REG_READ(dspcntr_reg); +- +- /* 20ms delay before sending exit_sleep_mode */ +- msleep(20); +- +- /* Send exit_sleep_mode DCS */ +- ret = mdfld_dsi_dbi_send_dcs(dsi_output, exit_sleep_mode, NULL, +- 0, CMD_DATA_SRC_SYSTEM_MEM); +- if (ret) { +- dev_err(dev->dev, "sent exit_sleep_mode faild\n"); +- goto out_err; +- } +- +- /*send set_tear_on DCS*/ +- ret = mdfld_dsi_dbi_send_dcs(dsi_output, set_tear_on, +- ¶m, 1, CMD_DATA_SRC_SYSTEM_MEM); +- if (ret) { +- dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__); +- goto out_err; +- } +- +- /* Do some init stuff */ +- mdfld_dsi_brightness_init(dsi_config, pipe); +- mdfld_dsi_gen_fifo_ready(dev, (MIPIA_GEN_FIFO_STAT_REG + reg_offset), +- HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); +- +- REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR); +- REG_READ(pipeconf_reg); +- +- /* TODO: this looks ugly, try to move it to CRTC mode setting */ +- if (pipe == 2) +- dev_priv->pipeconf2 |= PIPEACONF_DSR; +- else +- dev_priv->pipeconf |= PIPEACONF_DSR; +- +- dev_dbg(dev->dev, "pipeconf %x\n", REG_READ(pipeconf_reg)); +- +- ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0, +- h_active_area - 1, v_active_area - 1); +- if (ret) { +- dev_err(dev->dev, "update area failed\n"); +- goto out_err; +- } +- +-out_err: +- gma_power_end(dev); +- +- if (ret) +- dev_err(dev->dev, "mode set failed\n"); +- else +- dev_dbg(dev->dev, "mode set done successfully\n"); +-} +- +-static void pyr_dsi_dbi_prepare(struct drm_encoder *encoder) +-{ +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_dbi_output *dbi_output = +- MDFLD_DSI_DBI_OUTPUT(dsi_encoder); +- +- dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER; +- dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE; +- +- pyr_dsi_dbi_set_power(encoder, false); +-} +- +-static void pyr_dsi_dbi_commit(struct drm_encoder *encoder) +-{ +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_dbi_output *dbi_output = +- MDFLD_DSI_DBI_OUTPUT(dsi_encoder); +- struct drm_device *dev = dbi_output->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct psb_drm_dpu_rect rect; +- +- pyr_dsi_dbi_set_power(encoder, true); +- +- dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER; +- +- rect.x = rect.y = 0; +- rect.width = 864; +- rect.height = 480; +- +- if (dbi_output->channel_num == 1) { +- dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2; +- /* If DPU enabled report a fullscreen damage */ +- mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect); +- } else { +- dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0; +- mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect); +- } +- dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE; +-} +- +-static void pyr_dsi_dbi_dpms(struct drm_encoder *encoder, int mode) +-{ +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_dbi_output *dbi_output = +- MDFLD_DSI_DBI_OUTPUT(dsi_encoder); +- struct drm_device *dev = dbi_output->dev; +- +- dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off")); +- +- if (mode == DRM_MODE_DPMS_ON) +- pyr_dsi_dbi_set_power(encoder, true); +- else +- pyr_dsi_dbi_set_power(encoder, false); +-} +- +-/* +- * Update the DBI MIPI Panel Frame Buffer. +- */ +-static void pyr_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output, +- int pipe) +-{ +- struct mdfld_dsi_pkg_sender *sender = +- mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); +- struct drm_device *dev = dbi_output->dev; +- struct drm_crtc *crtc = dbi_output->base.base.crtc; +- struct psb_intel_crtc *psb_crtc = (crtc) ? +- to_psb_intel_crtc(crtc) : NULL; +- +- u32 dpll_reg = MRST_DPLL_A; +- u32 dspcntr_reg = DSPACNTR; +- u32 pipeconf_reg = PIPEACONF; +- u32 dsplinoff_reg = DSPALINOFF; +- u32 dspsurf_reg = DSPASURF; +- u32 hs_gen_ctrl_reg = HS_GEN_CTRL_REG; +- u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG; +- u32 reg_offset = 0; +- +- u32 intr_status; +- u32 fifo_stat_reg_val; +- u32 dpll_reg_val; +- u32 dspcntr_reg_val; +- u32 pipeconf_reg_val; +- +- /* If mode setting on-going, back off */ +- if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || +- (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) || +- !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE)) +- return; +- +- /* +- * Look for errors here. In particular we're checking for whatever +- * error status might have appeared during the last frame transmit +- * (memory write). +- * +- * Normally, the bits we're testing here would be set infrequently, +- * if at all. However, one panel (at least) returns at least one +- * error bit on most frames. So we've disabled the kernel message +- * for now. +- * +- * Still clear whatever error bits are set, except don't clear the +- * ones that would make the Penwell DSI controller reset if we +- * cleared them. +- */ +- intr_status = REG_READ(INTR_STAT_REG); +- if ((intr_status & 0x26FFFFFF) != 0) { +- /* dev_err(dev->dev, "DSI status: 0x%08X\n", intr_status); */ +- intr_status &= 0x26F3FFFF; +- REG_WRITE(INTR_STAT_REG, intr_status); +- } +- +- if (pipe == 2) { +- dspcntr_reg = DSPCCNTR; +- pipeconf_reg = PIPECCONF; +- dsplinoff_reg = DSPCLINOFF; +- dspsurf_reg = DSPCSURF; +- +- hs_gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET; +- gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET, +- +- reg_offset = MIPIC_REG_OFFSET; +- } +- +- if (!gma_power_begin(dev, true)) { +- dev_err(dev->dev, "hw begin failed\n"); +- return; +- } +- +- fifo_stat_reg_val = REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset); +- dpll_reg_val = REG_READ(dpll_reg); +- dspcntr_reg_val = REG_READ(dspcntr_reg); +- pipeconf_reg_val = REG_READ(pipeconf_reg); +- +- if (!(fifo_stat_reg_val & (1 << 27)) || +- (dpll_reg_val & DPLL_VCO_ENABLE) || +- !(dspcntr_reg_val & DISPLAY_PLANE_ENABLE) || +- !(pipeconf_reg_val & DISPLAY_PLANE_ENABLE)) { +- goto update_fb_out0; +- } +- +- /* Refresh plane changes */ +- REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg)); +- REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg)); +- REG_READ(dspsurf_reg); +- +- mdfld_dsi_send_dcs(sender, +- write_mem_start, +- NULL, +- 0, +- CMD_DATA_SRC_PIPE, +- MDFLD_DSI_SEND_PACKAGE); +- +- /* +- * The idea here is to transmit a Generic Read command after the +- * Write Memory Start/Continue commands finish. This asks for +- * the panel to return an "ACK No Errors," or (if it has errors +- * to report) an Error Report. This allows us to monitor the +- * panel's perception of the health of the DSI. +- */ +- mdfld_dsi_gen_fifo_ready(dev, gen_fifo_stat_reg, +- HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); +- REG_WRITE(hs_gen_ctrl_reg, (1 << WORD_COUNTS_POS) | GEN_READ_0); +- +- dbi_output->dsr_fb_update_done = true; +-update_fb_out0: +- gma_power_end(dev); +-} +- +-/* +- * TODO: will be removed later, should work out display interfaces for power +- */ +-void pyr_dsi_adapter_init(struct mdfld_dsi_config *dsi_config, int pipe) +-{ +- if (!dsi_config || (pipe != 0 && pipe != 2)) { +- WARN_ON(1); +- return; +- } +- pyr_dsi_controller_dbi_init(dsi_config, pipe); +-} +- +-static int pyr_cmd_get_panel_info(struct drm_device *dev, int pipe, +- struct panel_info *pi) +-{ +- if (!dev || !pi) +- return -EINVAL; +- +- pi->width_mm = PYR_PANEL_WIDTH; +- pi->height_mm = PYR_PANEL_HEIGHT; +- +- return 0; +-} +- +-/* PYR DBI encoder helper funcs */ +-static const struct drm_encoder_helper_funcs pyr_dsi_dbi_helper_funcs = { +- .dpms = pyr_dsi_dbi_dpms, +- .mode_fixup = pyr_dsi_dbi_mode_fixup, +- .prepare = pyr_dsi_dbi_prepare, +- .mode_set = pyr_dsi_dbi_mode_set, +- .commit = pyr_dsi_dbi_commit, +-}; +- +-/* PYR DBI encoder funcs */ +-static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = { +- .destroy = drm_encoder_cleanup, +-}; +- +-void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs) +-{ +- p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs; +- p_funcs->encoder_helper_funcs = &pyr_dsi_dbi_helper_funcs; +- p_funcs->get_config_mode = &pyr_cmd_get_config_mode; +- p_funcs->update_fb = pyr_dsi_dbi_update_fb; +- p_funcs->get_panel_info = pyr_cmd_get_panel_info; +-} +diff --git a/drivers/staging/gma500/mdfld_tmd_vid.c b/drivers/staging/gma500/mdfld_tmd_vid.c +deleted file mode 100644 +index affdc09..0000000 +--- a/drivers/staging/gma500/mdfld_tmd_vid.c ++++ /dev/null +@@ -1,206 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Jim Liu +- * Jackie Li +- * Gideon Eaton +- */ +- +-#include "mdfld_dsi_dbi.h" +-#include "mdfld_dsi_dpi.h" +-#include "mdfld_dsi_output.h" +-#include "mdfld_output.h" +- +-#include "mdfld_dsi_pkg_sender.h" +- +-#include "displays/tmd_vid.h" +- +-/* FIXME: static ? */ +-struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev) +-{ +- struct drm_display_mode *mode; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; +- bool use_gct = false; /*Disable GCT for now*/ +- +- mode = kzalloc(sizeof(*mode), GFP_KERNEL); +- if (!mode) { +- dev_err(dev->dev, "Out of memory\n"); +- return NULL; +- } +- +- if (use_gct) { +- dev_dbg(dev->dev, "gct find MIPI panel.\n"); +- +- mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; +- mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; +- mode->hsync_start = mode->hdisplay + +- ((ti->hsync_offset_hi << 8) | +- ti->hsync_offset_lo); +- mode->hsync_end = mode->hsync_start + +- ((ti->hsync_pulse_width_hi << 8) | +- ti->hsync_pulse_width_lo); +- mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | +- ti->hblank_lo); +- mode->vsync_start = \ +- mode->vdisplay + ((ti->vsync_offset_hi << 8) | +- ti->vsync_offset_lo); +- mode->vsync_end = \ +- mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ +- ti->vsync_pulse_width_lo); +- mode->vtotal = mode->vdisplay + +- ((ti->vblank_hi << 8) | ti->vblank_lo); +- mode->clock = ti->pixel_clock * 10; +- +- dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); +- dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); +- dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); +- dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); +- dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); +- dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); +- dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); +- dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); +- dev_dbg(dev->dev, "clock is %d\n", mode->clock); +- } else { +- mode->hdisplay = 480; +- mode->vdisplay = 854; +- mode->hsync_start = 487; +- mode->hsync_end = 490; +- mode->htotal = 499; +- mode->vsync_start = 861; +- mode->vsync_end = 865; +- mode->vtotal = 873; +- mode->clock = 33264; +- } +- drm_mode_set_name(mode); +- drm_mode_set_crtcinfo(mode, 0); +- +- mode->type |= DRM_MODE_TYPE_PREFERRED; +- +- return mode; +-} +- +-static int tmd_vid_get_panel_info(struct drm_device *dev, +- int pipe, +- struct panel_info *pi) +-{ +- if (!dev || !pi) +- return -EINVAL; +- +- pi->width_mm = TMD_PANEL_WIDTH; +- pi->height_mm = TMD_PANEL_HEIGHT; +- +- return 0; +-} +- +-/* +- * mdfld_init_TMD_MIPI - initialise a TMD interface +- * @dsi_config: configuration +- * @pipe: pipe to configure +- * +- * This function is called only by mrst_dsi_mode_set and +- * restore_display_registers. since this function does not +- * acquire the mutex, it is important that the calling function +- * does! +- */ +- +- +-static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config, +- int pipe) +-{ +- static u32 tmd_cmd_mcap_off[] = {0x000000b2}; +- static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef}; +- static u32 tmd_cmd_set_lane_num[] = {0x006360ef}; +- static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef}; +- static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef}; +- static u32 tmd_cmd_set_mode[] = {0x000000b3}; +- static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef}; +- static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df}; +- static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055}; +- static u32 tmd_cmd_set_video_mode[] = {0x00000153}; +- /*no auto_bl,need add in furture*/ +- static u32 tmd_cmd_enable_backlight[] = {0x00005ab4}; +- static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd}; +- +- struct mdfld_dsi_pkg_sender *sender +- = mdfld_dsi_get_pkg_sender(dsi_config); +- +- DRM_INFO("Enter mdfld init TMD MIPI display.\n"); +- +- if (!sender) { +- DRM_ERROR("Cannot get sender\n"); +- return; +- } +- +- if (dsi_config->dvr_ic_inited) +- return; +- +- msleep(3); +- +- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_mcap_off, 1, 0); +- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_lane_switch, 1, 0); +- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_lane_num, 1, 0); +- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock0, 1, 0); +- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock1, 1, 0); +- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_mode, 1, 0); +- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_sync_pulse_mode, 1, 0); +- mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_column, 2, 0); +- mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_page, 2, 0); +- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_video_mode, 1, 0); +- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_backlight, 1, 0); +- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_backlight_dimming, 1, 0); +- +- dsi_config->dvr_ic_inited = 1; +-} +- +-/* TMD DPI encoder helper funcs */ +-static const struct drm_encoder_helper_funcs +- mdfld_tpo_dpi_encoder_helper_funcs = { +- .dpms = mdfld_dsi_dpi_dpms, +- .mode_fixup = mdfld_dsi_dpi_mode_fixup, +- .prepare = mdfld_dsi_dpi_prepare, +- .mode_set = mdfld_dsi_dpi_mode_set, +- .commit = mdfld_dsi_dpi_commit, +-}; +- +-/* TMD DPI encoder funcs */ +-static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = { +- .destroy = drm_encoder_cleanup, +-}; +- +-void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs) +-{ +- if (!dev || !p_funcs) { +- dev_err(dev->dev, "Invalid parameters\n"); +- return; +- } +- +- p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs; +- p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs; +- p_funcs->get_config_mode = &tmd_vid_get_config_mode; +- p_funcs->update_fb = NULL; +- p_funcs->get_panel_info = tmd_vid_get_panel_info; +- p_funcs->reset = mdfld_dsi_panel_reset; +- p_funcs->drv_ic_init = mdfld_dsi_tmd_drv_ic_init; +-} +diff --git a/drivers/staging/gma500/mdfld_tpo_cmd.c b/drivers/staging/gma500/mdfld_tpo_cmd.c +deleted file mode 100644 +index c7f7c9c..0000000 +--- a/drivers/staging/gma500/mdfld_tpo_cmd.c ++++ /dev/null +@@ -1,509 +0,0 @@ +-/* +- * Copyright (c) 2010 Intel Corporation +- * +- * 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, sublicensen +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Thomas Eaton +- * Scott Rowe +- */ +- +-#include "mdfld_dsi_dbi.h" +-#include "mdfld_dsi_dpi.h" +-#include "mdfld_dsi_output.h" +-#include "mdfld_output.h" +-#include "mdfld_dsi_dbi_dpu.h" +-#include "mdfld_dsi_pkg_sender.h" +- +-#include "displays/tpo_cmd.h" +- +-static struct drm_display_mode *tpo_cmd_get_config_mode(struct drm_device *dev) +-{ +- struct drm_display_mode *mode; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; +- bool use_gct = false; +- +- mode = kzalloc(sizeof(*mode), GFP_KERNEL); +- if (!mode) +- return NULL; +- +- if (use_gct) { +- dev_dbg(dev->dev, "gct find MIPI panel.\n"); +- +- mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; +- mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; +- mode->hsync_start = mode->hdisplay + \ +- ((ti->hsync_offset_hi << 8) | \ +- ti->hsync_offset_lo); +- mode->hsync_end = mode->hsync_start + \ +- ((ti->hsync_pulse_width_hi << 8) | \ +- ti->hsync_pulse_width_lo); +- mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ +- ti->hblank_lo); +- mode->vsync_start = \ +- mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ +- ti->vsync_offset_lo); +- mode->vsync_end = \ +- mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ +- ti->vsync_pulse_width_lo); +- mode->vtotal = mode->vdisplay + \ +- ((ti->vblank_hi << 8) | ti->vblank_lo); +- mode->clock = ti->pixel_clock * 10; +- +- dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); +- dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); +- dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); +- dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); +- dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); +- dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); +- dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); +- dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); +- dev_dbg(dev->dev, "clock is %d\n", mode->clock); +- } else { +- mode->hdisplay = 864; +- mode->vdisplay = 480; +- mode->hsync_start = 872; +- mode->hsync_end = 876; +- mode->htotal = 884; +- mode->vsync_start = 482; +- mode->vsync_end = 494; +- mode->vtotal = 486; +- mode->clock = 25777; +- } +- +- drm_mode_set_name(mode); +- drm_mode_set_crtcinfo(mode, 0); +- +- mode->type |= DRM_MODE_TYPE_PREFERRED; +- +- return mode; +-} +- +-static bool mdfld_dsi_dbi_mode_fixup(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- struct drm_device *dev = encoder->dev; +- struct drm_display_mode *fixed_mode = tpo_cmd_get_config_mode(dev); +- +- if (fixed_mode) { +- adjusted_mode->hdisplay = fixed_mode->hdisplay; +- adjusted_mode->hsync_start = fixed_mode->hsync_start; +- adjusted_mode->hsync_end = fixed_mode->hsync_end; +- adjusted_mode->htotal = fixed_mode->htotal; +- adjusted_mode->vdisplay = fixed_mode->vdisplay; +- adjusted_mode->vsync_start = fixed_mode->vsync_start; +- adjusted_mode->vsync_end = fixed_mode->vsync_end; +- adjusted_mode->vtotal = fixed_mode->vtotal; +- adjusted_mode->clock = fixed_mode->clock; +- drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); +- kfree(fixed_mode); +- } +- return true; +-} +- +-static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on) +-{ +- int ret = 0; +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_dbi_output *dbi_output = +- MDFLD_DSI_DBI_OUTPUT(dsi_encoder); +- struct mdfld_dsi_config *dsi_config = +- mdfld_dsi_encoder_get_config(dsi_encoder); +- struct mdfld_dsi_pkg_sender *sender = +- mdfld_dsi_encoder_get_pkg_sender(dsi_encoder); +- struct drm_device *dev = encoder->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 reg_offset = 0; +- int pipe = (dbi_output->channel_num == 0) ? 0 : 2; +- u32 data = 0; +- +- dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", +- pipe, on ? "On" : "Off", +- dbi_output->dbi_panel_on ? "True" : "False"); +- +- if (pipe == 2) { +- if (on) +- dev_priv->dual_mipi = true; +- else +- dev_priv->dual_mipi = false; +- reg_offset = MIPIC_REG_OFFSET; +- } else { +- if (!on) +- dev_priv->dual_mipi = false; +- } +- +- if (!gma_power_begin(dev, true)) { +- dev_err(dev->dev, "hw begin failed\n"); +- return; +- } +- +- if (on) { +- if (dbi_output->dbi_panel_on) +- goto out_err; +- +- ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON); +- if (ret) { +- dev_err(dev->dev, "power on error\n"); +- goto out_err; +- } +- +- dbi_output->dbi_panel_on = true; +- +- if (pipe == 2) +- dev_priv->dbi_panel_on2 = true; +- else +- dev_priv->dbi_panel_on = true; +- mdfld_enable_te(dev, pipe); +- } else { +- if (!dbi_output->dbi_panel_on && !dbi_output->first_boot) +- goto out_err; +- +- dbi_output->dbi_panel_on = false; +- dbi_output->first_boot = false; +- +- if (pipe == 2) +- dev_priv->dbi_panel_on2 = false; +- else +- dev_priv->dbi_panel_on = false; +- +- mdfld_disable_te(dev, pipe); +- +- ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF); +- if (ret) { +- dev_err(dev->dev, "power on error\n"); +- goto out_err; +- } +- } +- +- /* +- * FIXME: this is a WA for TPO panel crash on DPMS on & off around +- * 83 times. the root cause of this issue is that Booster in +- * drvIC crashed. Add this WA so that we can resume the driver IC +- * once we found that booster has a fault +- */ +- mdfld_dsi_get_power_mode(dsi_config, +- &data, +- MDFLD_DSI_HS_TRANSMISSION); +- +- if (on && data && !(data & (1 << 7))) { +- /* Soft reset */ +- mdfld_dsi_send_dcs(sender, +- DCS_SOFT_RESET, +- NULL, +- 0, +- CMD_DATA_SRC_PIPE, +- MDFLD_DSI_SEND_PACKAGE); +- +- /* Init drvIC */ +- if (dbi_output->p_funcs->drv_ic_init) +- dbi_output->p_funcs->drv_ic_init(dsi_config, +- pipe); +- } +- +-out_err: +- gma_power_end(dev); +- if (ret) +- dev_err(dev->dev, "failed\n"); +-} +- +- +-static void mdfld_dsi_dbi_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- int ret = 0; +- struct drm_device *dev = encoder->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_dbi_output *dsi_output = +- MDFLD_DSI_DBI_OUTPUT(dsi_encoder); +- struct mdfld_dsi_config *dsi_config = +- mdfld_dsi_encoder_get_config(dsi_encoder); +- struct mdfld_dsi_connector *dsi_connector = dsi_config->connector; +- int pipe = dsi_connector->pipe; +- u8 param = 0; +- +- /* Regs */ +- u32 mipi_reg = MIPI; +- u32 dspcntr_reg = DSPACNTR; +- u32 pipeconf_reg = PIPEACONF; +- u32 reg_offset = 0; +- +- /* Values */ +- u32 dspcntr_val = dev_priv->dspcntr; +- u32 pipeconf_val = dev_priv->pipeconf; +- u32 h_active_area = mode->hdisplay; +- u32 v_active_area = mode->vdisplay; +- u32 mipi_val; +- +- mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX | +- TE_TRIGGER_GPIO_PIN); +- +- dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val); +- +- dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI"); +- dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay); +- +- if (pipe == 2) { +- mipi_reg = MIPI_C; +- dspcntr_reg = DSPCCNTR; +- pipeconf_reg = PIPECCONF; +- +- reg_offset = MIPIC_REG_OFFSET; +- +- dspcntr_val = dev_priv->dspcntr2; +- pipeconf_val = dev_priv->pipeconf2; +- } else { +- mipi_val |= 0x2; /*two lanes for port A and C respectively*/ +- } +- +- if (!gma_power_begin(dev, true)) { +- dev_err(dev->dev, "hw begin failed\n"); +- return; +- } +- +- REG_WRITE(dspcntr_reg, dspcntr_val); +- REG_READ(dspcntr_reg); +- +- /* 20ms delay before sending exit_sleep_mode */ +- msleep(20); +- +- /* Send exit_sleep_mode DCS */ +- ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_EXIT_SLEEP_MODE, +- NULL, 0, CMD_DATA_SRC_SYSTEM_MEM); +- if (ret) { +- dev_err(dev->dev, "sent exit_sleep_mode faild\n"); +- goto out_err; +- } +- +- /* Send set_tear_on DCS */ +- ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_SET_TEAR_ON, +- ¶m, 1, CMD_DATA_SRC_SYSTEM_MEM); +- if (ret) { +- dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__); +- goto out_err; +- } +- +- /* Do some init stuff */ +- REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR); +- REG_READ(pipeconf_reg); +- +- /* TODO: this looks ugly, try to move it to CRTC mode setting*/ +- if (pipe == 2) +- dev_priv->pipeconf2 |= PIPEACONF_DSR; +- else +- dev_priv->pipeconf |= PIPEACONF_DSR; +- +- dev_dbg(dev->dev, "pipeconf %x\n", REG_READ(pipeconf_reg)); +- +- ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0, +- h_active_area - 1, v_active_area - 1); +- if (ret) { +- dev_err(dev->dev, "update area failed\n"); +- goto out_err; +- } +- +-out_err: +- gma_power_end(dev); +- +- if (ret) +- dev_err(dev->dev, "mode set failed\n"); +-} +- +-static void mdfld_dsi_dbi_prepare(struct drm_encoder *encoder) +-{ +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_dbi_output *dbi_output +- = MDFLD_DSI_DBI_OUTPUT(dsi_encoder); +- +- dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER; +- dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE; +- +- mdfld_dsi_dbi_set_power(encoder, false); +-} +- +-static void mdfld_dsi_dbi_commit(struct drm_encoder *encoder) +-{ +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_dbi_output *dbi_output = +- MDFLD_DSI_DBI_OUTPUT(dsi_encoder); +- struct drm_device *dev = dbi_output->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct psb_drm_dpu_rect rect; +- +- mdfld_dsi_dbi_set_power(encoder, true); +- dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER; +- +- rect.x = rect.y = 0; +- rect.width = 864; +- rect.height = 480; +- +- if (dbi_output->channel_num == 1) { +- dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2; +- /*if dpu enabled report a fullscreen damage*/ +- mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect); +- } else { +- dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0; +- mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect); +- } +- dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE; +-} +- +-static void mdfld_dsi_dbi_dpms(struct drm_encoder *encoder, int mode) +-{ +- struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); +- struct mdfld_dsi_dbi_output *dbi_output +- = MDFLD_DSI_DBI_OUTPUT(dsi_encoder); +- struct drm_device *dev = dbi_output->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- static bool bdispoff; +- +- dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off")); +- +- if (mode == DRM_MODE_DPMS_ON) { +- /* +- * FIXME: in case I am wrong! +- * we don't need to exit dsr here to wake up plane/pipe/pll +- * if everything goes right, hw_begin will resume them all +- * during set_power. +- */ +- if (bdispoff /* FIXME && gbgfxsuspended */) { +- mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D); +- bdispoff = false; +- dev_priv->dispstatus = true; +- } +- +- mdfld_dsi_dbi_set_power(encoder, true); +- /* FIXME if (gbgfxsuspended) +- gbgfxsuspended = false; */ +- } else { +- /* +- * I am not sure whether this is the perfect place to +- * turn rpm on since we still have a lot of CRTC turnning +- * on work to do. +- */ +- bdispoff = true; +- dev_priv->dispstatus = false; +- mdfld_dsi_dbi_set_power(encoder, false); +- } +-} +- +- +-/* +- * Update the DBI MIPI Panel Frame Buffer. +- */ +-static void mdfld_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output, +- int pipe) +-{ +- struct mdfld_dsi_pkg_sender *sender = +- mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); +- struct drm_device *dev = dbi_output->dev; +- struct drm_crtc *crtc = dbi_output->base.base.crtc; +- struct psb_intel_crtc *psb_crtc = (crtc) ? +- to_psb_intel_crtc(crtc) : NULL; +- u32 dpll_reg = MRST_DPLL_A; +- u32 dspcntr_reg = DSPACNTR; +- u32 pipeconf_reg = PIPEACONF; +- u32 dsplinoff_reg = DSPALINOFF; +- u32 dspsurf_reg = DSPASURF; +- u32 reg_offset = 0; +- +- /* If mode setting on-going, back off */ +- if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || +- (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) || +- !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE)) +- return; +- +- if (pipe == 2) { +- dspcntr_reg = DSPCCNTR; +- pipeconf_reg = PIPECCONF; +- dsplinoff_reg = DSPCLINOFF; +- dspsurf_reg = DSPCSURF; +- reg_offset = MIPIC_REG_OFFSET; +- } +- +- if (!gma_power_begin(dev, true)) { +- dev_err(dev->dev, "hw begin failed\n"); +- return; +- } +- +- /* Check DBI FIFO status */ +- if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) || +- !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) || +- !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) +- goto update_fb_out0; +- +- /* Refresh plane changes */ +- REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg)); +- REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg)); +- REG_READ(dspsurf_reg); +- +- mdfld_dsi_send_dcs(sender, +- DCS_WRITE_MEM_START, +- NULL, +- 0, +- CMD_DATA_SRC_PIPE, +- MDFLD_DSI_SEND_PACKAGE); +- +- dbi_output->dsr_fb_update_done = true; +-update_fb_out0: +- gma_power_end(dev); +-} +- +-static int tpo_cmd_get_panel_info(struct drm_device *dev, +- int pipe, +- struct panel_info *pi) +-{ +- if (!dev || !pi) +- return -EINVAL; +- +- pi->width_mm = TPO_PANEL_WIDTH; +- pi->height_mm = TPO_PANEL_HEIGHT; +- +- return 0; +-} +- +- +-/* TPO DBI encoder helper funcs */ +-static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = { +- .dpms = mdfld_dsi_dbi_dpms, +- .mode_fixup = mdfld_dsi_dbi_mode_fixup, +- .prepare = mdfld_dsi_dbi_prepare, +- .mode_set = mdfld_dsi_dbi_mode_set, +- .commit = mdfld_dsi_dbi_commit, +-}; +- +-/* TPO DBI encoder funcs */ +-static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = { +- .destroy = drm_encoder_cleanup, +-}; +- +-void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs) +-{ +- p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs; +- p_funcs->encoder_helper_funcs = &mdfld_dsi_dbi_helper_funcs; +- p_funcs->get_config_mode = &tpo_cmd_get_config_mode; +- p_funcs->update_fb = mdfld_dsi_dbi_update_fb; +- p_funcs->get_panel_info = tpo_cmd_get_panel_info; +- p_funcs->reset = mdfld_dsi_panel_reset; +- p_funcs->drv_ic_init = mdfld_dsi_brightness_init; +-} +diff --git a/drivers/staging/gma500/mdfld_tpo_vid.c b/drivers/staging/gma500/mdfld_tpo_vid.c +deleted file mode 100644 +index 9549017..0000000 +--- a/drivers/staging/gma500/mdfld_tpo_vid.c ++++ /dev/null +@@ -1,140 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * jim liu +- * Jackie Li +- */ +- +-#include "mdfld_dsi_dbi.h" +-#include "mdfld_dsi_dpi.h" +-#include "mdfld_dsi_output.h" +-#include "mdfld_output.h" +- +-#include "mdfld_dsi_pkg_sender.h" +- +-#include "displays/tpo_vid.h" +- +-static struct drm_display_mode *tpo_vid_get_config_mode(struct drm_device *dev) +-{ +- struct drm_display_mode *mode; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; +- bool use_gct = false; +- +- mode = kzalloc(sizeof(*mode), GFP_KERNEL); +- if (!mode) { +- dev_err(dev->dev, "out of memory\n"); +- return NULL; +- } +- +- if (use_gct) { +- mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; +- mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; +- mode->hsync_start = mode->hdisplay + \ +- ((ti->hsync_offset_hi << 8) | \ +- ti->hsync_offset_lo); +- mode->hsync_end = mode->hsync_start + \ +- ((ti->hsync_pulse_width_hi << 8) | \ +- ti->hsync_pulse_width_lo); +- mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ +- ti->hblank_lo); +- mode->vsync_start = \ +- mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ +- ti->vsync_offset_lo); +- mode->vsync_end = \ +- mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ +- ti->vsync_pulse_width_lo); +- mode->vtotal = mode->vdisplay + \ +- ((ti->vblank_hi << 8) | ti->vblank_lo); +- mode->clock = ti->pixel_clock * 10; +- +- dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); +- dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); +- dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); +- dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); +- dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); +- dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); +- dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); +- dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); +- dev_dbg(dev->dev, "clock is %d\n", mode->clock); +- } else { +- mode->hdisplay = 864; +- mode->vdisplay = 480; +- mode->hsync_start = 873; +- mode->hsync_end = 876; +- mode->htotal = 887; +- mode->vsync_start = 487; +- mode->vsync_end = 490; +- mode->vtotal = 499; +- mode->clock = 33264; +- } +- +- drm_mode_set_name(mode); +- drm_mode_set_crtcinfo(mode, 0); +- +- mode->type |= DRM_MODE_TYPE_PREFERRED; +- +- return mode; +-} +- +-static int tpo_vid_get_panel_info(struct drm_device *dev, +- int pipe, +- struct panel_info *pi) +-{ +- if (!dev || !pi) +- return -EINVAL; +- +- pi->width_mm = TPO_PANEL_WIDTH; +- pi->height_mm = TPO_PANEL_HEIGHT; +- +- return 0; +-} +- +-/*TPO DPI encoder helper funcs*/ +-static const struct drm_encoder_helper_funcs +- mdfld_tpo_dpi_encoder_helper_funcs = { +- .dpms = mdfld_dsi_dpi_dpms, +- .mode_fixup = mdfld_dsi_dpi_mode_fixup, +- .prepare = mdfld_dsi_dpi_prepare, +- .mode_set = mdfld_dsi_dpi_mode_set, +- .commit = mdfld_dsi_dpi_commit, +-}; +- +-/*TPO DPI encoder funcs*/ +-static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = { +- .destroy = drm_encoder_cleanup, +-}; +- +-void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs) +-{ +- if (!dev || !p_funcs) { +- dev_err(dev->dev, "tpo_vid_init: Invalid parameters\n"); +- return; +- } +- +- p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs; +- p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs; +- p_funcs->get_config_mode = &tpo_vid_get_config_mode; +- p_funcs->update_fb = NULL; +- p_funcs->get_panel_info = tpo_vid_get_panel_info; +-} +diff --git a/drivers/staging/gma500/medfield.h b/drivers/staging/gma500/medfield.h +deleted file mode 100644 +index 09e9687..0000000 +--- a/drivers/staging/gma500/medfield.h ++++ /dev/null +@@ -1,268 +0,0 @@ +-/* +- * Copyright © 2011 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- */ +- +-/* Medfield DSI controller registers */ +- +-#define MIPIA_DEVICE_READY_REG 0xb000 +-#define MIPIA_INTR_STAT_REG 0xb004 +-#define MIPIA_INTR_EN_REG 0xb008 +-#define MIPIA_DSI_FUNC_PRG_REG 0xb00c +-#define MIPIA_HS_TX_TIMEOUT_REG 0xb010 +-#define MIPIA_LP_RX_TIMEOUT_REG 0xb014 +-#define MIPIA_TURN_AROUND_TIMEOUT_REG 0xb018 +-#define MIPIA_DEVICE_RESET_TIMER_REG 0xb01c +-#define MIPIA_DPI_RESOLUTION_REG 0xb020 +-#define MIPIA_DBI_FIFO_THROTTLE_REG 0xb024 +-#define MIPIA_HSYNC_COUNT_REG 0xb028 +-#define MIPIA_HBP_COUNT_REG 0xb02c +-#define MIPIA_HFP_COUNT_REG 0xb030 +-#define MIPIA_HACTIVE_COUNT_REG 0xb034 +-#define MIPIA_VSYNC_COUNT_REG 0xb038 +-#define MIPIA_VBP_COUNT_REG 0xb03c +-#define MIPIA_VFP_COUNT_REG 0xb040 +-#define MIPIA_HIGH_LOW_SWITCH_COUNT_REG 0xb044 +-#define MIPIA_DPI_CONTROL_REG 0xb048 +-#define MIPIA_DPI_DATA_REG 0xb04c +-#define MIPIA_INIT_COUNT_REG 0xb050 +-#define MIPIA_MAX_RETURN_PACK_SIZE_REG 0xb054 +-#define MIPIA_VIDEO_MODE_FORMAT_REG 0xb058 +-#define MIPIA_EOT_DISABLE_REG 0xb05c +-#define MIPIA_LP_BYTECLK_REG 0xb060 +-#define MIPIA_LP_GEN_DATA_REG 0xb064 +-#define MIPIA_HS_GEN_DATA_REG 0xb068 +-#define MIPIA_LP_GEN_CTRL_REG 0xb06c +-#define MIPIA_HS_GEN_CTRL_REG 0xb070 +-#define MIPIA_GEN_FIFO_STAT_REG 0xb074 +-#define MIPIA_HS_LS_DBI_ENABLE_REG 0xb078 +-#define MIPIA_DPHY_PARAM_REG 0xb080 +-#define MIPIA_DBI_BW_CTRL_REG 0xb084 +-#define MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG 0xb088 +- +-#define DSI_DEVICE_READY (0x1) +-#define DSI_POWER_STATE_ULPS_ENTER (0x2 << 1) +-#define DSI_POWER_STATE_ULPS_EXIT (0x1 << 1) +-#define DSI_POWER_STATE_ULPS_OFFSET (0x1) +- +- +-#define DSI_ONE_DATA_LANE (0x1) +-#define DSI_TWO_DATA_LANE (0x2) +-#define DSI_THREE_DATA_LANE (0X3) +-#define DSI_FOUR_DATA_LANE (0x4) +-#define DSI_DPI_VIRT_CHANNEL_OFFSET (0x3) +-#define DSI_DBI_VIRT_CHANNEL_OFFSET (0x5) +-#define DSI_DPI_COLOR_FORMAT_RGB565 (0x01 << 7) +-#define DSI_DPI_COLOR_FORMAT_RGB666 (0x02 << 7) +-#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK (0x03 << 7) +-#define DSI_DPI_COLOR_FORMAT_RGB888 (0x04 << 7) +-#define DSI_DBI_COLOR_FORMAT_OPTION2 (0x05 << 13) +- +-#define DSI_INTR_STATE_RXSOTERROR 1 +- +-#define DSI_INTR_STATE_SPL_PKG_SENT (1 << 30) +-#define DSI_INTR_STATE_TE (1 << 31) +- +-#define DSI_HS_TX_TIMEOUT_MASK (0xffffff) +- +-#define DSI_LP_RX_TIMEOUT_MASK (0xffffff) +- +-#define DSI_TURN_AROUND_TIMEOUT_MASK (0x3f) +- +-#define DSI_RESET_TIMER_MASK (0xffff) +- +-#define DSI_DBI_FIFO_WM_HALF (0x0) +-#define DSI_DBI_FIFO_WM_QUARTER (0x1) +-#define DSI_DBI_FIFO_WM_LOW (0x2) +- +-#define DSI_DPI_TIMING_MASK (0xffff) +- +-#define DSI_INIT_TIMER_MASK (0xffff) +- +-#define DSI_DBI_RETURN_PACK_SIZE_MASK (0x3ff) +- +-#define DSI_LP_BYTECLK_MASK (0x0ffff) +- +-#define DSI_HS_CTRL_GEN_SHORT_W0 (0x03) +-#define DSI_HS_CTRL_GEN_SHORT_W1 (0x13) +-#define DSI_HS_CTRL_GEN_SHORT_W2 (0x23) +-#define DSI_HS_CTRL_GEN_R0 (0x04) +-#define DSI_HS_CTRL_GEN_R1 (0x14) +-#define DSI_HS_CTRL_GEN_R2 (0x24) +-#define DSI_HS_CTRL_GEN_LONG_W (0x29) +-#define DSI_HS_CTRL_MCS_SHORT_W0 (0x05) +-#define DSI_HS_CTRL_MCS_SHORT_W1 (0x15) +-#define DSI_HS_CTRL_MCS_R0 (0x06) +-#define DSI_HS_CTRL_MCS_LONG_W (0x39) +-#define DSI_HS_CTRL_VC_OFFSET (0x06) +-#define DSI_HS_CTRL_WC_OFFSET (0x08) +- +-#define DSI_FIFO_GEN_HS_DATA_FULL (1 << 0) +-#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY (1 << 1) +-#define DSI_FIFO_GEN_HS_DATA_EMPTY (1 << 2) +-#define DSI_FIFO_GEN_LP_DATA_FULL (1 << 8) +-#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY (1 << 9) +-#define DSI_FIFO_GEN_LP_DATA_EMPTY (1 << 10) +-#define DSI_FIFO_GEN_HS_CTRL_FULL (1 << 16) +-#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY (1 << 17) +-#define DSI_FIFO_GEN_HS_CTRL_EMPTY (1 << 18) +-#define DSI_FIFO_GEN_LP_CTRL_FULL (1 << 24) +-#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY (1 << 25) +-#define DSI_FIFO_GEN_LP_CTRL_EMPTY (1 << 26) +-#define DSI_FIFO_DBI_EMPTY (1 << 27) +-#define DSI_FIFO_DPI_EMPTY (1 << 28) +- +-#define DSI_DBI_HS_LP_SWITCH_MASK (0x1) +- +-#define DSI_HS_LP_SWITCH_COUNTER_OFFSET (0x0) +-#define DSI_LP_HS_SWITCH_COUNTER_OFFSET (0x16) +- +-#define DSI_DPI_CTRL_HS_SHUTDOWN (0x00000001) +-#define DSI_DPI_CTRL_HS_TURN_ON (0x00000002) +- +-/* Medfield DSI adapter registers */ +-#define MIPIA_CONTROL_REG 0xb104 +-#define MIPIA_DATA_ADD_REG 0xb108 +-#define MIPIA_DATA_LEN_REG 0xb10c +-#define MIPIA_CMD_ADD_REG 0xb110 +-#define MIPIA_CMD_LEN_REG 0xb114 +- +-/*dsi power modes*/ +-#define DSI_POWER_MODE_DISPLAY_ON (1 << 2) +-#define DSI_POWER_MODE_NORMAL_ON (1 << 3) +-#define DSI_POWER_MODE_SLEEP_OUT (1 << 4) +-#define DSI_POWER_MODE_PARTIAL_ON (1 << 5) +-#define DSI_POWER_MODE_IDLE_ON (1 << 6) +- +-enum { +- MDFLD_DSI_ENCODER_DBI = 0, +- MDFLD_DSI_ENCODER_DPI, +-}; +- +-enum { +- MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1, +- MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2, +- MDFLD_DSI_VIDEO_BURST_MODE = 3, +-}; +- +-#define DSI_DPI_COMPLETE_LAST_LINE (1 << 2) +-#define DSI_DPI_DISABLE_BTA (1 << 3) +-/* Panel types */ +-enum { +- TPO_CMD, +- TPO_VID, +- TMD_CMD, +- TMD_VID, +- PYR_CMD, +- PYR_VID, +- TPO, +- TMD, +- PYR, +- HDMI, +- GCT_DETECT +-}; +- +-/* Junk that belongs elsewhere */ +-#define TPO_PANEL_WIDTH 84 +-#define TPO_PANEL_HEIGHT 46 +-#define TMD_PANEL_WIDTH 39 +-#define TMD_PANEL_HEIGHT 71 +-#define PYR_PANEL_WIDTH 53 +-#define PYR_PANEL_HEIGHT 95 +- +-/* Panel interface */ +-struct panel_info { +- u32 width_mm; +- u32 height_mm; +-}; +- +-struct mdfld_dsi_dbi_output; +- +-struct mdfld_dsi_connector_state { +- u32 mipi_ctrl_reg; +-}; +- +-struct mdfld_dsi_encoder_state { +- +-}; +- +-struct mdfld_dsi_connector { +- /* +- * This is ugly, but I have to use connector in it! :-( +- * FIXME: use drm_connector instead. +- */ +- struct psb_intel_output base; +- +- int pipe; +- void *private; +- void *pkg_sender; +- +- /* Connection status */ +- enum drm_connector_status status; +-}; +- +-struct mdfld_dsi_encoder { +- struct drm_encoder base; +- void *private; +-}; +- +-/* +- * DSI config, consists of one DSI connector, two DSI encoders. +- * DRM will pick up on DSI encoder basing on differents configs. +- */ +-struct mdfld_dsi_config { +- struct drm_device *dev; +- struct drm_display_mode *fixed_mode; +- struct drm_display_mode *mode; +- +- struct mdfld_dsi_connector *connector; +- struct mdfld_dsi_encoder *encoders[DRM_CONNECTOR_MAX_ENCODER]; +- struct mdfld_dsi_encoder *encoder; +- +- int changed; +- +- int bpp; +- int type; +- int lane_count; +- /*Virtual channel number for this encoder*/ +- int channel_num; +- /*video mode configure*/ +- int video_mode; +- +- int dvr_ic_inited; +-}; +- +-#define MDFLD_DSI_CONNECTOR(psb_output) \ +- (container_of(psb_output, struct mdfld_dsi_connector, base)) +- +-#define MDFLD_DSI_ENCODER(encoder) \ +- (container_of(encoder, struct mdfld_dsi_encoder, base)) +- +-struct panel_funcs { +- const struct drm_encoder_funcs *encoder_funcs; +- const struct drm_encoder_helper_funcs *encoder_helper_funcs; +- struct drm_display_mode *(*get_config_mode) (struct drm_device *); +- void (*update_fb) (struct mdfld_dsi_dbi_output *, int); +- int (*get_panel_info) (struct drm_device *, int, struct panel_info *); +- int (*reset)(int pipe); +- void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe); +-}; +- +diff --git a/drivers/staging/gma500/mid_bios.c b/drivers/staging/gma500/mid_bios.c +deleted file mode 100644 +index ee3c036..0000000 +--- a/drivers/staging/gma500/mid_bios.c ++++ /dev/null +@@ -1,270 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-/* TODO +- * - Split functions by vbt type +- * - Make them all take drm_device +- * - Check ioremap failures +- */ +- +-#include +-#include +-#include +-#include "psb_drm.h" +-#include "psb_drv.h" +-#include "mid_bios.h" +-#include "mdfld_output.h" +- +-static int panel_id = GCT_DETECT; +-module_param_named(panel_id, panel_id, int, 0600); +-MODULE_PARM_DESC(panel_id, "Panel Identifier"); +- +- +-static void mid_get_fuse_settings(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); +- uint32_t fuse_value = 0; +- uint32_t fuse_value_tmp = 0; +- +-#define FB_REG06 0xD0810600 +-#define FB_MIPI_DISABLE (1 << 11) +-#define FB_REG09 0xD0810900 +-#define FB_REG09 0xD0810900 +-#define FB_SKU_MASK 0x7000 +-#define FB_SKU_SHIFT 12 +-#define FB_SKU_100 0 +-#define FB_SKU_100L 1 +-#define FB_SKU_83 2 +- pci_write_config_dword(pci_root, 0xD0, FB_REG06); +- pci_read_config_dword(pci_root, 0xD4, &fuse_value); +- +- /* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */ +- if (IS_MRST(dev)) +- dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE; +- +- DRM_INFO("internal display is %s\n", +- dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display"); +- +- /* Prevent runtime suspend at start*/ +- if (dev_priv->iLVDS_enable) { +- dev_priv->is_lvds_on = true; +- dev_priv->is_mipi_on = false; +- } else { +- dev_priv->is_mipi_on = true; +- dev_priv->is_lvds_on = false; +- } +- +- dev_priv->video_device_fuse = fuse_value; +- +- pci_write_config_dword(pci_root, 0xD0, FB_REG09); +- pci_read_config_dword(pci_root, 0xD4, &fuse_value); +- +- dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value); +- fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT; +- +- dev_priv->fuse_reg_value = fuse_value; +- +- switch (fuse_value_tmp) { +- case FB_SKU_100: +- dev_priv->core_freq = 200; +- break; +- case FB_SKU_100L: +- dev_priv->core_freq = 100; +- break; +- case FB_SKU_83: +- dev_priv->core_freq = 166; +- break; +- default: +- dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n", +- fuse_value_tmp); +- dev_priv->core_freq = 0; +- } +- dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq); +- pci_dev_put(pci_root); +-} +- +-/* +- * Get the revison ID, B0:D2:F0;0x08 +- */ +-static void mid_get_pci_revID(struct drm_psb_private *dev_priv) +-{ +- uint32_t platform_rev_id = 0; +- struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); +- +- pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id); +- dev_priv->platform_rev_id = (uint8_t) platform_rev_id; +- pci_dev_put(pci_gfx_root); +- dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n", +- dev_priv->platform_rev_id); +-} +- +-static void mid_get_vbt_data(struct drm_psb_private *dev_priv) +-{ +- struct drm_device *dev = dev_priv->dev; +- struct mrst_vbt *vbt = &dev_priv->vbt_data; +- u32 addr; +- u16 new_size; +- u8 *vbt_virtual; +- u8 bpi; +- u8 number_desc = 0; +- struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD; +- struct gct_r10_timing_info ti; +- void *pGCT; +- struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); +- +- /* Get the address of the platform config vbt, B0:D2:F0;0xFC */ +- pci_read_config_dword(pci_gfx_root, 0xFC, &addr); +- pci_dev_put(pci_gfx_root); +- +- dev_dbg(dev->dev, "drm platform config address is %x\n", addr); +- +- /* check for platform config address == 0. */ +- /* this means fw doesn't support vbt */ +- +- if (addr == 0) { +- vbt->size = 0; +- return; +- } +- +- /* get the virtual address of the vbt */ +- vbt_virtual = ioremap(addr, sizeof(*vbt)); +- +- memcpy(vbt, vbt_virtual, sizeof(*vbt)); +- iounmap(vbt_virtual); /* Free virtual address space */ +- +- dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision); +- +- switch (vbt->revision) { +- case 0: +- vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4, +- vbt->size - sizeof(*vbt) + 4); +- pGCT = vbt->mrst_gct; +- bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex; +- dev_priv->gct_data.bpi = bpi; +- dev_priv->gct_data.pt = +- ((struct mrst_gct_v1 *)pGCT)->PD.PanelType; +- memcpy(&dev_priv->gct_data.DTD, +- &((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD, +- sizeof(struct mrst_timing_info)); +- dev_priv->gct_data.Panel_Port_Control = +- ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control; +- dev_priv->gct_data.Panel_MIPI_Display_Descriptor = +- ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; +- break; +- case 1: +- vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4, +- vbt->size - sizeof(*vbt) + 4); +- pGCT = vbt->mrst_gct; +- bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex; +- dev_priv->gct_data.bpi = bpi; +- dev_priv->gct_data.pt = +- ((struct mrst_gct_v2 *)pGCT)->PD.PanelType; +- memcpy(&dev_priv->gct_data.DTD, +- &((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD, +- sizeof(struct mrst_timing_info)); +- dev_priv->gct_data.Panel_Port_Control = +- ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control; +- dev_priv->gct_data.Panel_MIPI_Display_Descriptor = +- ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; +- break; +- case 0x10: +- /*header definition changed from rev 01 (v2) to rev 10h. */ +- /*so, some values have changed location*/ +- new_size = vbt->checksum; /*checksum contains lo size byte*/ +- /*LSB of mrst_gct contains hi size byte*/ +- new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8; +- +- vbt->checksum = vbt->size; /*size contains the checksum*/ +- if (new_size > 0xff) +- vbt->size = 0xff; /*restrict size to 255*/ +- else +- vbt->size = new_size; +- +- /* number of descriptors defined in the GCT */ +- number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8; +- bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16; +- vbt->mrst_gct = ioremap(addr + GCT_R10_HEADER_SIZE, +- GCT_R10_DISPLAY_DESC_SIZE * number_desc); +- pGCT = vbt->mrst_gct; +- pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE); +- dev_priv->gct_data.bpi = bpi; /*save boot panel id*/ +- +- /*copy the GCT display timings into a temp structure*/ +- memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info)); +- +- /*now copy the temp struct into the dev_priv->gct_data*/ +- dp_ti->pixel_clock = ti.pixel_clock; +- dp_ti->hactive_hi = ti.hactive_hi; +- dp_ti->hactive_lo = ti.hactive_lo; +- dp_ti->hblank_hi = ti.hblank_hi; +- dp_ti->hblank_lo = ti.hblank_lo; +- dp_ti->hsync_offset_hi = ti.hsync_offset_hi; +- dp_ti->hsync_offset_lo = ti.hsync_offset_lo; +- dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi; +- dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo; +- dp_ti->vactive_hi = ti.vactive_hi; +- dp_ti->vactive_lo = ti.vactive_lo; +- dp_ti->vblank_hi = ti.vblank_hi; +- dp_ti->vblank_lo = ti.vblank_lo; +- dp_ti->vsync_offset_hi = ti.vsync_offset_hi; +- dp_ti->vsync_offset_lo = ti.vsync_offset_lo; +- dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi; +- dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo; +- +- /* Move the MIPI_Display_Descriptor data from GCT to dev priv */ +- dev_priv->gct_data.Panel_MIPI_Display_Descriptor = +- *((u8 *)pGCT + 0x0d); +- dev_priv->gct_data.Panel_MIPI_Display_Descriptor |= +- (*((u8 *)pGCT + 0x0e)) << 8; +- break; +- default: +- dev_err(dev->dev, "Unknown revision of GCT!\n"); +- vbt->size = 0; +- } +- if (IS_MFLD(dev_priv->dev)) { +- if (panel_id == GCT_DETECT) { +- if (dev_priv->gct_data.bpi == 2) { +- dev_info(dev->dev, "[GFX] PYR Panel Detected\n"); +- dev_priv->panel_id = PYR_CMD; +- panel_id = PYR_CMD; +- } else if (dev_priv->gct_data.bpi == 0) { +- dev_info(dev->dev, "[GFX] TMD Panel Detected.\n"); +- dev_priv->panel_id = TMD_VID; +- panel_id = TMD_VID; +- } else { +- dev_info(dev->dev, "[GFX] Default Panel (TPO)\n"); +- dev_priv->panel_id = TPO_CMD; +- panel_id = TPO_CMD; +- } +- } else { +- dev_info(dev->dev, "[GFX] Panel Parameter Passed in through cmd line\n"); +- dev_priv->panel_id = panel_id; +- } +- } +-} +- +-int mid_chip_setup(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- mid_get_fuse_settings(dev); +- mid_get_vbt_data(dev_priv); +- mid_get_pci_revID(dev_priv); +- return 0; +-} +diff --git a/drivers/staging/gma500/mid_bios.h b/drivers/staging/gma500/mid_bios.h +deleted file mode 100644 +index 00e7d56..0000000 +--- a/drivers/staging/gma500/mid_bios.h ++++ /dev/null +@@ -1,21 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-extern int mid_chip_setup(struct drm_device *dev); +- +diff --git a/drivers/staging/gma500/mmu.c b/drivers/staging/gma500/mmu.c +deleted file mode 100644 +index c904d73..0000000 +--- a/drivers/staging/gma500/mmu.c ++++ /dev/null +@@ -1,858 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2007, Intel Corporation. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +-#include +-#include "psb_drv.h" +-#include "psb_reg.h" +- +-/* +- * Code for the SGX MMU: +- */ +- +-/* +- * clflush on one processor only: +- * clflush should apparently flush the cache line on all processors in an +- * SMP system. +- */ +- +-/* +- * kmap atomic: +- * The usage of the slots must be completely encapsulated within a spinlock, and +- * no other functions that may be using the locks for other purposed may be +- * called from within the locked region. +- * Since the slots are per processor, this will guarantee that we are the only +- * user. +- */ +- +-/* +- * TODO: Inserting ptes from an interrupt handler: +- * This may be desirable for some SGX functionality where the GPU can fault in +- * needed pages. For that, we need to make an atomic insert_pages function, that +- * may fail. +- * If it fails, the caller need to insert the page using a workqueue function, +- * but on average it should be fast. +- */ +- +-struct psb_mmu_driver { +- /* protects driver- and pd structures. Always take in read mode +- * before taking the page table spinlock. +- */ +- struct rw_semaphore sem; +- +- /* protects page tables, directory tables and pt tables. +- * and pt structures. +- */ +- spinlock_t lock; +- +- atomic_t needs_tlbflush; +- +- uint8_t __iomem *register_map; +- struct psb_mmu_pd *default_pd; +- /*uint32_t bif_ctrl;*/ +- int has_clflush; +- int clflush_add; +- unsigned long clflush_mask; +- +- struct drm_psb_private *dev_priv; +-}; +- +-struct psb_mmu_pd; +- +-struct psb_mmu_pt { +- struct psb_mmu_pd *pd; +- uint32_t index; +- uint32_t count; +- struct page *p; +- uint32_t *v; +-}; +- +-struct psb_mmu_pd { +- struct psb_mmu_driver *driver; +- int hw_context; +- struct psb_mmu_pt **tables; +- struct page *p; +- struct page *dummy_pt; +- struct page *dummy_page; +- uint32_t pd_mask; +- uint32_t invalid_pde; +- uint32_t invalid_pte; +-}; +- +-static inline uint32_t psb_mmu_pt_index(uint32_t offset) +-{ +- return (offset >> PSB_PTE_SHIFT) & 0x3FF; +-} +- +-static inline uint32_t psb_mmu_pd_index(uint32_t offset) +-{ +- return offset >> PSB_PDE_SHIFT; +-} +- +-static inline void psb_clflush(void *addr) +-{ +- __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory"); +-} +- +-static inline void psb_mmu_clflush(struct psb_mmu_driver *driver, +- void *addr) +-{ +- if (!driver->has_clflush) +- return; +- +- mb(); +- psb_clflush(addr); +- mb(); +-} +- +-static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page) +-{ +- uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT; +- uint32_t clflush_count = PAGE_SIZE / clflush_add; +- int i; +- uint8_t *clf; +- +- clf = kmap_atomic(page, KM_USER0); +- mb(); +- for (i = 0; i < clflush_count; ++i) { +- psb_clflush(clf); +- clf += clflush_add; +- } +- mb(); +- kunmap_atomic(clf, KM_USER0); +-} +- +-static void psb_pages_clflush(struct psb_mmu_driver *driver, +- struct page *page[], unsigned long num_pages) +-{ +- int i; +- +- if (!driver->has_clflush) +- return ; +- +- for (i = 0; i < num_pages; i++) +- psb_page_clflush(driver, *page++); +-} +- +-static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver, +- int force) +-{ +- atomic_set(&driver->needs_tlbflush, 0); +-} +- +-static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force) +-{ +- down_write(&driver->sem); +- psb_mmu_flush_pd_locked(driver, force); +- up_write(&driver->sem); +-} +- +-void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot) +-{ +- if (rc_prot) +- down_write(&driver->sem); +- if (rc_prot) +- up_write(&driver->sem); +-} +- +-void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context) +-{ +- /*ttm_tt_cache_flush(&pd->p, 1);*/ +- psb_pages_clflush(pd->driver, &pd->p, 1); +- down_write(&pd->driver->sem); +- wmb(); +- psb_mmu_flush_pd_locked(pd->driver, 1); +- pd->hw_context = hw_context; +- up_write(&pd->driver->sem); +- +-} +- +-static inline unsigned long psb_pd_addr_end(unsigned long addr, +- unsigned long end) +-{ +- +- addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK; +- return (addr < end) ? addr : end; +-} +- +-static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type) +-{ +- uint32_t mask = PSB_PTE_VALID; +- +- if (type & PSB_MMU_CACHED_MEMORY) +- mask |= PSB_PTE_CACHED; +- if (type & PSB_MMU_RO_MEMORY) +- mask |= PSB_PTE_RO; +- if (type & PSB_MMU_WO_MEMORY) +- mask |= PSB_PTE_WO; +- +- return (pfn << PAGE_SHIFT) | mask; +-} +- +-struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver, +- int trap_pagefaults, int invalid_type) +-{ +- struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL); +- uint32_t *v; +- int i; +- +- if (!pd) +- return NULL; +- +- pd->p = alloc_page(GFP_DMA32); +- if (!pd->p) +- goto out_err1; +- pd->dummy_pt = alloc_page(GFP_DMA32); +- if (!pd->dummy_pt) +- goto out_err2; +- pd->dummy_page = alloc_page(GFP_DMA32); +- if (!pd->dummy_page) +- goto out_err3; +- +- if (!trap_pagefaults) { +- pd->invalid_pde = +- psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt), +- invalid_type); +- pd->invalid_pte = +- psb_mmu_mask_pte(page_to_pfn(pd->dummy_page), +- invalid_type); +- } else { +- pd->invalid_pde = 0; +- pd->invalid_pte = 0; +- } +- +- v = kmap(pd->dummy_pt); +- for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) +- v[i] = pd->invalid_pte; +- +- kunmap(pd->dummy_pt); +- +- v = kmap(pd->p); +- for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) +- v[i] = pd->invalid_pde; +- +- kunmap(pd->p); +- +- clear_page(kmap(pd->dummy_page)); +- kunmap(pd->dummy_page); +- +- pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024); +- if (!pd->tables) +- goto out_err4; +- +- pd->hw_context = -1; +- pd->pd_mask = PSB_PTE_VALID; +- pd->driver = driver; +- +- return pd; +- +-out_err4: +- __free_page(pd->dummy_page); +-out_err3: +- __free_page(pd->dummy_pt); +-out_err2: +- __free_page(pd->p); +-out_err1: +- kfree(pd); +- return NULL; +-} +- +-void psb_mmu_free_pt(struct psb_mmu_pt *pt) +-{ +- __free_page(pt->p); +- kfree(pt); +-} +- +-void psb_mmu_free_pagedir(struct psb_mmu_pd *pd) +-{ +- struct psb_mmu_driver *driver = pd->driver; +- struct psb_mmu_pt *pt; +- int i; +- +- down_write(&driver->sem); +- if (pd->hw_context != -1) +- psb_mmu_flush_pd_locked(driver, 1); +- +- /* Should take the spinlock here, but we don't need to do that +- since we have the semaphore in write mode. */ +- +- for (i = 0; i < 1024; ++i) { +- pt = pd->tables[i]; +- if (pt) +- psb_mmu_free_pt(pt); +- } +- +- vfree(pd->tables); +- __free_page(pd->dummy_page); +- __free_page(pd->dummy_pt); +- __free_page(pd->p); +- kfree(pd); +- up_write(&driver->sem); +-} +- +-static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd) +-{ +- struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL); +- void *v; +- uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT; +- uint32_t clflush_count = PAGE_SIZE / clflush_add; +- spinlock_t *lock = &pd->driver->lock; +- uint8_t *clf; +- uint32_t *ptes; +- int i; +- +- if (!pt) +- return NULL; +- +- pt->p = alloc_page(GFP_DMA32); +- if (!pt->p) { +- kfree(pt); +- return NULL; +- } +- +- spin_lock(lock); +- +- v = kmap_atomic(pt->p, KM_USER0); +- clf = (uint8_t *) v; +- ptes = (uint32_t *) v; +- for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) +- *ptes++ = pd->invalid_pte; +- +- +- if (pd->driver->has_clflush && pd->hw_context != -1) { +- mb(); +- for (i = 0; i < clflush_count; ++i) { +- psb_clflush(clf); +- clf += clflush_add; +- } +- mb(); +- } +- +- kunmap_atomic(v, KM_USER0); +- spin_unlock(lock); +- +- pt->count = 0; +- pt->pd = pd; +- pt->index = 0; +- +- return pt; +-} +- +-struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd, +- unsigned long addr) +-{ +- uint32_t index = psb_mmu_pd_index(addr); +- struct psb_mmu_pt *pt; +- uint32_t *v; +- spinlock_t *lock = &pd->driver->lock; +- +- spin_lock(lock); +- pt = pd->tables[index]; +- while (!pt) { +- spin_unlock(lock); +- pt = psb_mmu_alloc_pt(pd); +- if (!pt) +- return NULL; +- spin_lock(lock); +- +- if (pd->tables[index]) { +- spin_unlock(lock); +- psb_mmu_free_pt(pt); +- spin_lock(lock); +- pt = pd->tables[index]; +- continue; +- } +- +- v = kmap_atomic(pd->p, KM_USER0); +- pd->tables[index] = pt; +- v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask; +- pt->index = index; +- kunmap_atomic((void *) v, KM_USER0); +- +- if (pd->hw_context != -1) { +- psb_mmu_clflush(pd->driver, (void *) &v[index]); +- atomic_set(&pd->driver->needs_tlbflush, 1); +- } +- } +- pt->v = kmap_atomic(pt->p, KM_USER0); +- return pt; +-} +- +-static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd, +- unsigned long addr) +-{ +- uint32_t index = psb_mmu_pd_index(addr); +- struct psb_mmu_pt *pt; +- spinlock_t *lock = &pd->driver->lock; +- +- spin_lock(lock); +- pt = pd->tables[index]; +- if (!pt) { +- spin_unlock(lock); +- return NULL; +- } +- pt->v = kmap_atomic(pt->p, KM_USER0); +- return pt; +-} +- +-static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt) +-{ +- struct psb_mmu_pd *pd = pt->pd; +- uint32_t *v; +- +- kunmap_atomic(pt->v, KM_USER0); +- if (pt->count == 0) { +- v = kmap_atomic(pd->p, KM_USER0); +- v[pt->index] = pd->invalid_pde; +- pd->tables[pt->index] = NULL; +- +- if (pd->hw_context != -1) { +- psb_mmu_clflush(pd->driver, +- (void *) &v[pt->index]); +- atomic_set(&pd->driver->needs_tlbflush, 1); +- } +- kunmap_atomic(pt->v, KM_USER0); +- spin_unlock(&pd->driver->lock); +- psb_mmu_free_pt(pt); +- return; +- } +- spin_unlock(&pd->driver->lock); +-} +- +-static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt, +- unsigned long addr, uint32_t pte) +-{ +- pt->v[psb_mmu_pt_index(addr)] = pte; +-} +- +-static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt, +- unsigned long addr) +-{ +- pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte; +-} +- +- +-void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, +- uint32_t mmu_offset, uint32_t gtt_start, +- uint32_t gtt_pages) +-{ +- uint32_t *v; +- uint32_t start = psb_mmu_pd_index(mmu_offset); +- struct psb_mmu_driver *driver = pd->driver; +- int num_pages = gtt_pages; +- +- down_read(&driver->sem); +- spin_lock(&driver->lock); +- +- v = kmap_atomic(pd->p, KM_USER0); +- v += start; +- +- while (gtt_pages--) { +- *v++ = gtt_start | pd->pd_mask; +- gtt_start += PAGE_SIZE; +- } +- +- /*ttm_tt_cache_flush(&pd->p, num_pages);*/ +- psb_pages_clflush(pd->driver, &pd->p, num_pages); +- kunmap_atomic(v, KM_USER0); +- spin_unlock(&driver->lock); +- +- if (pd->hw_context != -1) +- atomic_set(&pd->driver->needs_tlbflush, 1); +- +- up_read(&pd->driver->sem); +- psb_mmu_flush_pd(pd->driver, 0); +-} +- +-struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver) +-{ +- struct psb_mmu_pd *pd; +- +- /* down_read(&driver->sem); */ +- pd = driver->default_pd; +- /* up_read(&driver->sem); */ +- +- return pd; +-} +- +-/* Returns the physical address of the PD shared by sgx/msvdx */ +-uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver) +-{ +- struct psb_mmu_pd *pd; +- +- pd = psb_mmu_get_default_pd(driver); +- return page_to_pfn(pd->p) << PAGE_SHIFT; +-} +- +-void psb_mmu_driver_takedown(struct psb_mmu_driver *driver) +-{ +- psb_mmu_free_pagedir(driver->default_pd); +- kfree(driver); +-} +- +-struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers, +- int trap_pagefaults, +- int invalid_type, +- struct drm_psb_private *dev_priv) +-{ +- struct psb_mmu_driver *driver; +- +- driver = kmalloc(sizeof(*driver), GFP_KERNEL); +- +- if (!driver) +- return NULL; +- driver->dev_priv = dev_priv; +- +- driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults, +- invalid_type); +- if (!driver->default_pd) +- goto out_err1; +- +- spin_lock_init(&driver->lock); +- init_rwsem(&driver->sem); +- down_write(&driver->sem); +- driver->register_map = registers; +- atomic_set(&driver->needs_tlbflush, 1); +- +- driver->has_clflush = 0; +- +- if (boot_cpu_has(X86_FEATURE_CLFLSH)) { +- uint32_t tfms, misc, cap0, cap4, clflush_size; +- +- /* +- * clflush size is determined at kernel setup for x86_64 +- * but not for i386. We have to do it here. +- */ +- +- cpuid(0x00000001, &tfms, &misc, &cap0, &cap4); +- clflush_size = ((misc >> 8) & 0xff) * 8; +- driver->has_clflush = 1; +- driver->clflush_add = +- PAGE_SIZE * clflush_size / sizeof(uint32_t); +- driver->clflush_mask = driver->clflush_add - 1; +- driver->clflush_mask = ~driver->clflush_mask; +- } +- +- up_write(&driver->sem); +- return driver; +- +-out_err1: +- kfree(driver); +- return NULL; +-} +- +-static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd, +- unsigned long address, uint32_t num_pages, +- uint32_t desired_tile_stride, +- uint32_t hw_tile_stride) +-{ +- struct psb_mmu_pt *pt; +- uint32_t rows = 1; +- uint32_t i; +- unsigned long addr; +- unsigned long end; +- unsigned long next; +- unsigned long add; +- unsigned long row_add; +- unsigned long clflush_add = pd->driver->clflush_add; +- unsigned long clflush_mask = pd->driver->clflush_mask; +- +- if (!pd->driver->has_clflush) { +- /*ttm_tt_cache_flush(&pd->p, num_pages);*/ +- psb_pages_clflush(pd->driver, &pd->p, num_pages); +- return; +- } +- +- if (hw_tile_stride) +- rows = num_pages / desired_tile_stride; +- else +- desired_tile_stride = num_pages; +- +- add = desired_tile_stride << PAGE_SHIFT; +- row_add = hw_tile_stride << PAGE_SHIFT; +- mb(); +- for (i = 0; i < rows; ++i) { +- +- addr = address; +- end = addr + add; +- +- do { +- next = psb_pd_addr_end(addr, end); +- pt = psb_mmu_pt_map_lock(pd, addr); +- if (!pt) +- continue; +- do { +- psb_clflush(&pt->v +- [psb_mmu_pt_index(addr)]); +- } while (addr += +- clflush_add, +- (addr & clflush_mask) < next); +- +- psb_mmu_pt_unmap_unlock(pt); +- } while (addr = next, next != end); +- address += row_add; +- } +- mb(); +-} +- +-void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd, +- unsigned long address, uint32_t num_pages) +-{ +- struct psb_mmu_pt *pt; +- unsigned long addr; +- unsigned long end; +- unsigned long next; +- unsigned long f_address = address; +- +- down_read(&pd->driver->sem); +- +- addr = address; +- end = addr + (num_pages << PAGE_SHIFT); +- +- do { +- next = psb_pd_addr_end(addr, end); +- pt = psb_mmu_pt_alloc_map_lock(pd, addr); +- if (!pt) +- goto out; +- do { +- psb_mmu_invalidate_pte(pt, addr); +- --pt->count; +- } while (addr += PAGE_SIZE, addr < next); +- psb_mmu_pt_unmap_unlock(pt); +- +- } while (addr = next, next != end); +- +-out: +- if (pd->hw_context != -1) +- psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1); +- +- up_read(&pd->driver->sem); +- +- if (pd->hw_context != -1) +- psb_mmu_flush(pd->driver, 0); +- +- return; +-} +- +-void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address, +- uint32_t num_pages, uint32_t desired_tile_stride, +- uint32_t hw_tile_stride) +-{ +- struct psb_mmu_pt *pt; +- uint32_t rows = 1; +- uint32_t i; +- unsigned long addr; +- unsigned long end; +- unsigned long next; +- unsigned long add; +- unsigned long row_add; +- unsigned long f_address = address; +- +- if (hw_tile_stride) +- rows = num_pages / desired_tile_stride; +- else +- desired_tile_stride = num_pages; +- +- add = desired_tile_stride << PAGE_SHIFT; +- row_add = hw_tile_stride << PAGE_SHIFT; +- +- /* down_read(&pd->driver->sem); */ +- +- /* Make sure we only need to flush this processor's cache */ +- +- for (i = 0; i < rows; ++i) { +- +- addr = address; +- end = addr + add; +- +- do { +- next = psb_pd_addr_end(addr, end); +- pt = psb_mmu_pt_map_lock(pd, addr); +- if (!pt) +- continue; +- do { +- psb_mmu_invalidate_pte(pt, addr); +- --pt->count; +- +- } while (addr += PAGE_SIZE, addr < next); +- psb_mmu_pt_unmap_unlock(pt); +- +- } while (addr = next, next != end); +- address += row_add; +- } +- if (pd->hw_context != -1) +- psb_mmu_flush_ptes(pd, f_address, num_pages, +- desired_tile_stride, hw_tile_stride); +- +- /* up_read(&pd->driver->sem); */ +- +- if (pd->hw_context != -1) +- psb_mmu_flush(pd->driver, 0); +-} +- +-int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn, +- unsigned long address, uint32_t num_pages, +- int type) +-{ +- struct psb_mmu_pt *pt; +- uint32_t pte; +- unsigned long addr; +- unsigned long end; +- unsigned long next; +- unsigned long f_address = address; +- int ret = 0; +- +- down_read(&pd->driver->sem); +- +- addr = address; +- end = addr + (num_pages << PAGE_SHIFT); +- +- do { +- next = psb_pd_addr_end(addr, end); +- pt = psb_mmu_pt_alloc_map_lock(pd, addr); +- if (!pt) { +- ret = -ENOMEM; +- goto out; +- } +- do { +- pte = psb_mmu_mask_pte(start_pfn++, type); +- psb_mmu_set_pte(pt, addr, pte); +- pt->count++; +- } while (addr += PAGE_SIZE, addr < next); +- psb_mmu_pt_unmap_unlock(pt); +- +- } while (addr = next, next != end); +- +-out: +- if (pd->hw_context != -1) +- psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1); +- +- up_read(&pd->driver->sem); +- +- if (pd->hw_context != -1) +- psb_mmu_flush(pd->driver, 1); +- +- return ret; +-} +- +-int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages, +- unsigned long address, uint32_t num_pages, +- uint32_t desired_tile_stride, +- uint32_t hw_tile_stride, int type) +-{ +- struct psb_mmu_pt *pt; +- uint32_t rows = 1; +- uint32_t i; +- uint32_t pte; +- unsigned long addr; +- unsigned long end; +- unsigned long next; +- unsigned long add; +- unsigned long row_add; +- unsigned long f_address = address; +- int ret = 0; +- +- if (hw_tile_stride) { +- if (num_pages % desired_tile_stride != 0) +- return -EINVAL; +- rows = num_pages / desired_tile_stride; +- } else { +- desired_tile_stride = num_pages; +- } +- +- add = desired_tile_stride << PAGE_SHIFT; +- row_add = hw_tile_stride << PAGE_SHIFT; +- +- down_read(&pd->driver->sem); +- +- for (i = 0; i < rows; ++i) { +- +- addr = address; +- end = addr + add; +- +- do { +- next = psb_pd_addr_end(addr, end); +- pt = psb_mmu_pt_alloc_map_lock(pd, addr); +- if (!pt) { +- ret = -ENOMEM; +- goto out; +- } +- do { +- pte = +- psb_mmu_mask_pte(page_to_pfn(*pages++), +- type); +- psb_mmu_set_pte(pt, addr, pte); +- pt->count++; +- } while (addr += PAGE_SIZE, addr < next); +- psb_mmu_pt_unmap_unlock(pt); +- +- } while (addr = next, next != end); +- +- address += row_add; +- } +-out: +- if (pd->hw_context != -1) +- psb_mmu_flush_ptes(pd, f_address, num_pages, +- desired_tile_stride, hw_tile_stride); +- +- up_read(&pd->driver->sem); +- +- if (pd->hw_context != -1) +- psb_mmu_flush(pd->driver, 1); +- +- return ret; +-} +- +-int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual, +- unsigned long *pfn) +-{ +- int ret; +- struct psb_mmu_pt *pt; +- uint32_t tmp; +- spinlock_t *lock = &pd->driver->lock; +- +- down_read(&pd->driver->sem); +- pt = psb_mmu_pt_map_lock(pd, virtual); +- if (!pt) { +- uint32_t *v; +- +- spin_lock(lock); +- v = kmap_atomic(pd->p, KM_USER0); +- tmp = v[psb_mmu_pd_index(virtual)]; +- kunmap_atomic(v, KM_USER0); +- spin_unlock(lock); +- +- if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) || +- !(pd->invalid_pte & PSB_PTE_VALID)) { +- ret = -EINVAL; +- goto out; +- } +- ret = 0; +- *pfn = pd->invalid_pte >> PAGE_SHIFT; +- goto out; +- } +- tmp = pt->v[psb_mmu_pt_index(virtual)]; +- if (!(tmp & PSB_PTE_VALID)) { +- ret = -EINVAL; +- } else { +- ret = 0; +- *pfn = tmp >> PAGE_SHIFT; +- } +- psb_mmu_pt_unmap_unlock(pt); +-out: +- up_read(&pd->driver->sem); +- return ret; +-} +diff --git a/drivers/staging/gma500/mrst.h b/drivers/staging/gma500/mrst.h +deleted file mode 100644 +index b563dbc..0000000 +--- a/drivers/staging/gma500/mrst.h ++++ /dev/null +@@ -1,252 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2007-2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-/* MID device specific descriptors */ +- +-struct mrst_vbt { +- s8 signature[4]; /*4 bytes,"$GCT" */ +- u8 revision; +- u8 size; +- u8 checksum; +- void *mrst_gct; +-} __packed; +- +-struct mrst_timing_info { +- u16 pixel_clock; +- u8 hactive_lo; +- u8 hblank_lo; +- u8 hblank_hi:4; +- u8 hactive_hi:4; +- u8 vactive_lo; +- u8 vblank_lo; +- u8 vblank_hi:4; +- u8 vactive_hi:4; +- u8 hsync_offset_lo; +- u8 hsync_pulse_width_lo; +- u8 vsync_pulse_width_lo:4; +- u8 vsync_offset_lo:4; +- u8 vsync_pulse_width_hi:2; +- u8 vsync_offset_hi:2; +- u8 hsync_pulse_width_hi:2; +- u8 hsync_offset_hi:2; +- u8 width_mm_lo; +- u8 height_mm_lo; +- u8 height_mm_hi:4; +- u8 width_mm_hi:4; +- u8 hborder; +- u8 vborder; +- u8 unknown0:1; +- u8 hsync_positive:1; +- u8 vsync_positive:1; +- u8 separate_sync:2; +- u8 stereo:1; +- u8 unknown6:1; +- u8 interlaced:1; +-} __packed; +- +-struct gct_r10_timing_info { +- u16 pixel_clock; +- u32 hactive_lo:8; +- u32 hactive_hi:4; +- u32 hblank_lo:8; +- u32 hblank_hi:4; +- u32 hsync_offset_lo:8; +- u16 hsync_offset_hi:2; +- u16 hsync_pulse_width_lo:8; +- u16 hsync_pulse_width_hi:2; +- u16 hsync_positive:1; +- u16 rsvd_1:3; +- u8 vactive_lo:8; +- u16 vactive_hi:4; +- u16 vblank_lo:8; +- u16 vblank_hi:4; +- u16 vsync_offset_lo:4; +- u16 vsync_offset_hi:2; +- u16 vsync_pulse_width_lo:4; +- u16 vsync_pulse_width_hi:2; +- u16 vsync_positive:1; +- u16 rsvd_2:3; +-} __packed; +- +-struct mrst_panel_descriptor_v1 { +- u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */ +- /* 0x61190 if MIPI */ +- u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/ +- u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/ +- u32 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 dword */ +- /* Register 0x61210 */ +- struct mrst_timing_info DTD;/*18 bytes, Standard definition */ +- u16 Panel_Backlight_Inverter_Descriptor;/* 16 bits, as follows */ +- /* Bit 0, Frequency, 15 bits,0 - 32767Hz */ +- /* Bit 15, Polarity, 1 bit, 0: Normal, 1: Inverted */ +- u16 Panel_MIPI_Display_Descriptor; +- /*16 bits, Defined as follows: */ +- /* if MIPI, 0x0000 if LVDS */ +- /* Bit 0, Type, 2 bits, */ +- /* 0: Type-1, */ +- /* 1: Type-2, */ +- /* 2: Type-3, */ +- /* 3: Type-4 */ +- /* Bit 2, Pixel Format, 4 bits */ +- /* Bit0: 16bpp (not supported in LNC), */ +- /* Bit1: 18bpp loosely packed, */ +- /* Bit2: 18bpp packed, */ +- /* Bit3: 24bpp */ +- /* Bit 6, Reserved, 2 bits, 00b */ +- /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */ +- /* Bit 14, Reserved, 2 bits, 00b */ +-} __packed; +- +-struct mrst_panel_descriptor_v2 { +- u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */ +- /* 0x61190 if MIPI */ +- u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/ +- u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/ +- u8 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 byte */ +- /* Register 0x61210 */ +- struct mrst_timing_info DTD;/*18 bytes, Standard definition */ +- u16 Panel_Backlight_Inverter_Descriptor;/*16 bits, as follows*/ +- /*Bit 0, Frequency, 16 bits, 0 - 32767Hz*/ +- u8 Panel_Initial_Brightness;/* [7:0] 0 - 100% */ +- /*Bit 7, Polarity, 1 bit,0: Normal, 1: Inverted*/ +- u16 Panel_MIPI_Display_Descriptor; +- /*16 bits, Defined as follows: */ +- /* if MIPI, 0x0000 if LVDS */ +- /* Bit 0, Type, 2 bits, */ +- /* 0: Type-1, */ +- /* 1: Type-2, */ +- /* 2: Type-3, */ +- /* 3: Type-4 */ +- /* Bit 2, Pixel Format, 4 bits */ +- /* Bit0: 16bpp (not supported in LNC), */ +- /* Bit1: 18bpp loosely packed, */ +- /* Bit2: 18bpp packed, */ +- /* Bit3: 24bpp */ +- /* Bit 6, Reserved, 2 bits, 00b */ +- /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */ +- /* Bit 14, Reserved, 2 bits, 00b */ +-} __packed; +- +-union mrst_panel_rx { +- struct { +- u16 NumberOfLanes:2; /*Num of Lanes, 2 bits,0 = 1 lane,*/ +- /* 1 = 2 lanes, 2 = 3 lanes, 3 = 4 lanes. */ +- u16 MaxLaneFreq:3; /* 0: 100MHz, 1: 200MHz, 2: 300MHz, */ +- /*3: 400MHz, 4: 500MHz, 5: 600MHz, 6: 700MHz, 7: 800MHz.*/ +- u16 SupportedVideoTransferMode:2; /*0: Non-burst only */ +- /* 1: Burst and non-burst */ +- /* 2/3: Reserved */ +- u16 HSClkBehavior:1; /*0: Continuous, 1: Non-continuous*/ +- u16 DuoDisplaySupport:1; /*1 bit,0: No, 1: Yes*/ +- u16 ECC_ChecksumCapabilities:1;/*1 bit,0: No, 1: Yes*/ +- u16 BidirectionalCommunication:1;/*1 bit,0: No, 1: Yes */ +- u16 Rsvd:5;/*5 bits,00000b */ +- } panelrx; +- u16 panel_receiver; +-} __packed; +- +-struct mrst_gct_v1 { +- union { /*8 bits,Defined as follows: */ +- struct { +- u8 PanelType:4; /*4 bits, Bit field for panels*/ +- /* 0 - 3: 0 = LVDS, 1 = MIPI*/ +- /*2 bits,Specifies which of the*/ +- u8 BootPanelIndex:2; +- /* 4 panels to use by default*/ +- u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/ +- /* the 4 MIPI DSI receivers to use*/ +- } PD; +- u8 PanelDescriptor; +- }; +- struct mrst_panel_descriptor_v1 panel[4];/*panel descrs,38 bytes each*/ +- union mrst_panel_rx panelrx[4]; /* panel receivers*/ +-} __packed; +- +-struct mrst_gct_v2 { +- union { /*8 bits,Defined as follows: */ +- struct { +- u8 PanelType:4; /*4 bits, Bit field for panels*/ +- /* 0 - 3: 0 = LVDS, 1 = MIPI*/ +- /*2 bits,Specifies which of the*/ +- u8 BootPanelIndex:2; +- /* 4 panels to use by default*/ +- u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/ +- /* the 4 MIPI DSI receivers to use*/ +- } PD; +- u8 PanelDescriptor; +- }; +- struct mrst_panel_descriptor_v2 panel[4];/*panel descrs,38 bytes each*/ +- union mrst_panel_rx panelrx[4]; /* panel receivers*/ +-} __packed; +- +-struct mrst_gct_data { +- u8 bpi; /* boot panel index, number of panel used during boot */ +- u8 pt; /* panel type, 4 bit field, 0=lvds, 1=mipi */ +- struct mrst_timing_info DTD; /* timing info for the selected panel */ +- u32 Panel_Port_Control; +- u32 PP_On_Sequencing;/*1 dword,Register 0x61208,*/ +- u32 PP_Off_Sequencing;/*1 dword,Register 0x6120C,*/ +- u32 PP_Cycle_Delay; +- u16 Panel_Backlight_Inverter_Descriptor; +- u16 Panel_MIPI_Display_Descriptor; +-} __packed; +- +-#define MODE_SETTING_IN_CRTC 0x1 +-#define MODE_SETTING_IN_ENCODER 0x2 +-#define MODE_SETTING_ON_GOING 0x3 +-#define MODE_SETTING_IN_DSR 0x4 +-#define MODE_SETTING_ENCODER_DONE 0x8 +- +-#define GCT_R10_HEADER_SIZE 16 +-#define GCT_R10_DISPLAY_DESC_SIZE 28 +- +-/* +- * Moorestown HDMI interfaces +- */ +- +-struct mrst_hdmi_dev { +- struct pci_dev *dev; +- void __iomem *regs; +- unsigned int mmio, mmio_len; +- int dpms_mode; +- struct hdmi_i2c_dev *i2c_dev; +- +- /* register state */ +- u32 saveDPLL_CTRL; +- u32 saveDPLL_DIV_CTRL; +- u32 saveDPLL_ADJUST; +- u32 saveDPLL_UPDATE; +- u32 saveDPLL_CLK_ENABLE; +- u32 savePCH_HTOTAL_B; +- u32 savePCH_HBLANK_B; +- u32 savePCH_HSYNC_B; +- u32 savePCH_VTOTAL_B; +- u32 savePCH_VBLANK_B; +- u32 savePCH_VSYNC_B; +- u32 savePCH_PIPEBCONF; +- u32 savePCH_PIPEBSRC; +-}; +- +-extern void mrst_hdmi_setup(struct drm_device *dev); +-extern void mrst_hdmi_teardown(struct drm_device *dev); +-extern int mrst_hdmi_i2c_init(struct pci_dev *dev); +-extern void mrst_hdmi_i2c_exit(struct pci_dev *dev); +-extern void mrst_hdmi_save(struct drm_device *dev); +-extern void mrst_hdmi_restore(struct drm_device *dev); +-extern void mrst_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev); +diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c +deleted file mode 100644 +index c9311a5..0000000 +--- a/drivers/staging/gma500/mrst_crtc.c ++++ /dev/null +@@ -1,604 +0,0 @@ +-/* +- * Copyright © 2009 Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include +- +-#include +-#include "framebuffer.h" +-#include "psb_drv.h" +-#include "psb_intel_drv.h" +-#include "psb_intel_reg.h" +-#include "psb_intel_display.h" +-#include "power.h" +- +-struct psb_intel_range_t { +- int min, max; +-}; +- +-struct mrst_limit_t { +- struct psb_intel_range_t dot, m, p1; +-}; +- +-struct mrst_clock_t { +- /* derived values */ +- int dot; +- int m; +- int p1; +-}; +- +-#define MRST_LIMIT_LVDS_100L 0 +-#define MRST_LIMIT_LVDS_83 1 +-#define MRST_LIMIT_LVDS_100 2 +- +-#define MRST_DOT_MIN 19750 +-#define MRST_DOT_MAX 120000 +-#define MRST_M_MIN_100L 20 +-#define MRST_M_MIN_100 10 +-#define MRST_M_MIN_83 12 +-#define MRST_M_MAX_100L 34 +-#define MRST_M_MAX_100 17 +-#define MRST_M_MAX_83 20 +-#define MRST_P1_MIN 2 +-#define MRST_P1_MAX_0 7 +-#define MRST_P1_MAX_1 8 +- +-static const struct mrst_limit_t mrst_limits[] = { +- { /* MRST_LIMIT_LVDS_100L */ +- .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, +- .m = {.min = MRST_M_MIN_100L, .max = MRST_M_MAX_100L}, +- .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, +- }, +- { /* MRST_LIMIT_LVDS_83L */ +- .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, +- .m = {.min = MRST_M_MIN_83, .max = MRST_M_MAX_83}, +- .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_0}, +- }, +- { /* MRST_LIMIT_LVDS_100 */ +- .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, +- .m = {.min = MRST_M_MIN_100, .max = MRST_M_MAX_100}, +- .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, +- }, +-}; +- +-#define MRST_M_MIN 10 +-static const u32 mrst_m_converts[] = { +- 0x2B, 0x15, 0x2A, 0x35, 0x1A, 0x0D, 0x26, 0x33, 0x19, 0x2C, +- 0x36, 0x3B, 0x1D, 0x2E, 0x37, 0x1B, 0x2D, 0x16, 0x0B, 0x25, +- 0x12, 0x09, 0x24, 0x32, 0x39, 0x1c, +-}; +- +-static const struct mrst_limit_t *mrst_limit(struct drm_crtc *crtc) +-{ +- const struct mrst_limit_t *limit = NULL; +- struct drm_device *dev = crtc->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) +- || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) { +- switch (dev_priv->core_freq) { +- case 100: +- limit = &mrst_limits[MRST_LIMIT_LVDS_100L]; +- break; +- case 166: +- limit = &mrst_limits[MRST_LIMIT_LVDS_83]; +- break; +- case 200: +- limit = &mrst_limits[MRST_LIMIT_LVDS_100]; +- break; +- } +- } else { +- limit = NULL; +- dev_err(dev->dev, "mrst_limit Wrong display type.\n"); +- } +- +- return limit; +-} +- +-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ +-static void mrst_clock(int refclk, struct mrst_clock_t *clock) +-{ +- clock->dot = (refclk * clock->m) / (14 * clock->p1); +-} +- +-void mrstPrintPll(char *prefix, struct mrst_clock_t *clock) +-{ +- pr_debug("%s: dotclock = %d, m = %d, p1 = %d.\n", +- prefix, clock->dot, clock->m, clock->p1); +-} +- +-/** +- * Returns a set of divisors for the desired target clock with the given refclk, +- * or FALSE. Divisor values are the actual divisors for +- */ +-static bool +-mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk, +- struct mrst_clock_t *best_clock) +-{ +- struct mrst_clock_t clock; +- const struct mrst_limit_t *limit = mrst_limit(crtc); +- int err = target; +- +- memset(best_clock, 0, sizeof(*best_clock)); +- +- for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { +- for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; +- clock.p1++) { +- int this_err; +- +- mrst_clock(refclk, &clock); +- +- this_err = abs(clock.dot - target); +- if (this_err < err) { +- *best_clock = clock; +- err = this_err; +- } +- } +- } +- dev_dbg(crtc->dev->dev, "mrstFindBestPLL err = %d.\n", err); +- return err != target; +-} +- +-/** +- * Sets the power management mode of the pipe and plane. +- * +- * This code should probably grow support for turning the cursor off and back +- * on appropriately at the same time as we're turning the pipe off/on. +- */ +-static void mrst_crtc_dpms(struct drm_crtc *crtc, int mode) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; +- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; +- int dspbase_reg = (pipe == 0) ? MRST_DSPABASE : DSPBBASE; +- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; +- u32 temp; +- bool enabled; +- +- if (!gma_power_begin(dev, true)) +- return; +- +- /* XXX: When our outputs are all unaware of DPMS modes other than off +- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. +- */ +- switch (mode) { +- case DRM_MODE_DPMS_ON: +- case DRM_MODE_DPMS_STANDBY: +- case DRM_MODE_DPMS_SUSPEND: +- /* Enable the DPLL */ +- temp = REG_READ(dpll_reg); +- if ((temp & DPLL_VCO_ENABLE) == 0) { +- REG_WRITE(dpll_reg, temp); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- } +- /* Enable the pipe */ +- temp = REG_READ(pipeconf_reg); +- if ((temp & PIPEACONF_ENABLE) == 0) +- REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); +- /* Enable the plane */ +- temp = REG_READ(dspcntr_reg); +- if ((temp & DISPLAY_PLANE_ENABLE) == 0) { +- REG_WRITE(dspcntr_reg, +- temp | DISPLAY_PLANE_ENABLE); +- /* Flush the plane changes */ +- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); +- } +- +- psb_intel_crtc_load_lut(crtc); +- +- /* Give the overlay scaler a chance to enable +- if it's on this pipe */ +- /* psb_intel_crtc_dpms_video(crtc, true); TODO */ +- break; +- case DRM_MODE_DPMS_OFF: +- /* Give the overlay scaler a chance to disable +- * if it's on this pipe */ +- /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ +- +- /* Disable the VGA plane that we never use */ +- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); +- /* Disable display plane */ +- temp = REG_READ(dspcntr_reg); +- if ((temp & DISPLAY_PLANE_ENABLE) != 0) { +- REG_WRITE(dspcntr_reg, +- temp & ~DISPLAY_PLANE_ENABLE); +- /* Flush the plane changes */ +- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); +- REG_READ(dspbase_reg); +- } +- +- /* Next, disable display pipes */ +- temp = REG_READ(pipeconf_reg); +- if ((temp & PIPEACONF_ENABLE) != 0) { +- REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); +- REG_READ(pipeconf_reg); +- } +- /* Wait for for the pipe disable to take effect. */ +- psb_intel_wait_for_vblank(dev); +- +- temp = REG_READ(dpll_reg); +- if ((temp & DPLL_VCO_ENABLE) != 0) { +- REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- } +- +- /* Wait for the clocks to turn off. */ +- udelay(150); +- break; +- } +- +- enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; +- +- /*Set FIFO Watermarks*/ +- REG_WRITE(DSPARB, 0x3FFF); +- REG_WRITE(DSPFW1, 0x3F88080A); +- REG_WRITE(DSPFW2, 0x0b060808); +- REG_WRITE(DSPFW3, 0x0); +- REG_WRITE(DSPFW4, 0x08030404); +- REG_WRITE(DSPFW5, 0x04040404); +- REG_WRITE(DSPFW6, 0x78); +- REG_WRITE(0x70400, REG_READ(0x70400) | 0x4000); +- /* Must write Bit 14 of the Chicken Bit Register */ +- +- gma_power_end(dev); +-} +- +-/** +- * Return the pipe currently connected to the panel fitter, +- * or -1 if the panel fitter is not present or not in use +- */ +-static int mrst_panel_fitter_pipe(struct drm_device *dev) +-{ +- u32 pfit_control; +- +- pfit_control = REG_READ(PFIT_CONTROL); +- +- /* See if the panel fitter is in use */ +- if ((pfit_control & PFIT_ENABLE) == 0) +- return -1; +- return (pfit_control >> 29) & 3; +-} +- +-static int mrst_crtc_mode_set(struct drm_crtc *crtc, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode, +- int x, int y, +- struct drm_framebuffer *old_fb) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct drm_psb_private *dev_priv = dev->dev_private; +- int pipe = psb_intel_crtc->pipe; +- int fp_reg = (pipe == 0) ? MRST_FPA0 : FPB0; +- int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; +- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; +- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; +- int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; +- int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; +- int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; +- int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; +- int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; +- int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; +- int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; +- int refclk = 0; +- struct mrst_clock_t clock; +- u32 dpll = 0, fp = 0, dspcntr, pipeconf; +- bool ok, is_sdvo = false; +- bool is_crt = false, is_lvds = false, is_tv = false; +- bool is_mipi = false; +- struct drm_mode_config *mode_config = &dev->mode_config; +- struct psb_intel_output *psb_intel_output = NULL; +- uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; +- struct drm_encoder *encoder; +- +- if (!gma_power_begin(dev, true)) +- return 0; +- +- memcpy(&psb_intel_crtc->saved_mode, +- mode, +- sizeof(struct drm_display_mode)); +- memcpy(&psb_intel_crtc->saved_adjusted_mode, +- adjusted_mode, +- sizeof(struct drm_display_mode)); +- +- list_for_each_entry(encoder, &mode_config->encoder_list, head) { +- +- if (encoder->crtc != crtc) +- continue; +- +- psb_intel_output = enc_to_psb_intel_output(encoder); +- switch (psb_intel_output->type) { +- case INTEL_OUTPUT_LVDS: +- is_lvds = true; +- break; +- case INTEL_OUTPUT_SDVO: +- is_sdvo = true; +- break; +- case INTEL_OUTPUT_TVOUT: +- is_tv = true; +- break; +- case INTEL_OUTPUT_ANALOG: +- is_crt = true; +- break; +- case INTEL_OUTPUT_MIPI: +- is_mipi = true; +- break; +- } +- } +- +- /* Disable the VGA plane that we never use */ +- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); +- +- /* Disable the panel fitter if it was on our pipe */ +- if (mrst_panel_fitter_pipe(dev) == pipe) +- REG_WRITE(PFIT_CONTROL, 0); +- +- REG_WRITE(pipesrc_reg, +- ((mode->crtc_hdisplay - 1) << 16) | +- (mode->crtc_vdisplay - 1)); +- +- if (psb_intel_output) +- drm_connector_property_get_value(&psb_intel_output->base, +- dev->mode_config.scaling_mode_property, &scalingType); +- +- if (scalingType == DRM_MODE_SCALE_NO_SCALE) { +- /* Moorestown doesn't have register support for centering so +- * we need to mess with the h/vblank and h/vsync start and +- * ends to get centering */ +- int offsetX = 0, offsetY = 0; +- +- offsetX = (adjusted_mode->crtc_hdisplay - +- mode->crtc_hdisplay) / 2; +- offsetY = (adjusted_mode->crtc_vdisplay - +- mode->crtc_vdisplay) / 2; +- +- REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) | +- ((adjusted_mode->crtc_htotal - 1) << 16)); +- REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) | +- ((adjusted_mode->crtc_vtotal - 1) << 16)); +- REG_WRITE(hblank_reg, +- (adjusted_mode->crtc_hblank_start - offsetX - 1) | +- ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); +- REG_WRITE(hsync_reg, +- (adjusted_mode->crtc_hsync_start - offsetX - 1) | +- ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); +- REG_WRITE(vblank_reg, +- (adjusted_mode->crtc_vblank_start - offsetY - 1) | +- ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); +- REG_WRITE(vsync_reg, +- (adjusted_mode->crtc_vsync_start - offsetY - 1) | +- ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); +- } else { +- REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | +- ((adjusted_mode->crtc_htotal - 1) << 16)); +- REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | +- ((adjusted_mode->crtc_vtotal - 1) << 16)); +- REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | +- ((adjusted_mode->crtc_hblank_end - 1) << 16)); +- REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | +- ((adjusted_mode->crtc_hsync_end - 1) << 16)); +- REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | +- ((adjusted_mode->crtc_vblank_end - 1) << 16)); +- REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | +- ((adjusted_mode->crtc_vsync_end - 1) << 16)); +- } +- +- /* Flush the plane changes */ +- { +- struct drm_crtc_helper_funcs *crtc_funcs = +- crtc->helper_private; +- crtc_funcs->mode_set_base(crtc, x, y, old_fb); +- } +- +- /* setup pipeconf */ +- pipeconf = REG_READ(pipeconf_reg); +- +- /* Set up the display plane register */ +- dspcntr = REG_READ(dspcntr_reg); +- dspcntr |= DISPPLANE_GAMMA_ENABLE; +- +- if (pipe == 0) +- dspcntr |= DISPPLANE_SEL_PIPE_A; +- else +- dspcntr |= DISPPLANE_SEL_PIPE_B; +- +- dev_priv->dspcntr = dspcntr |= DISPLAY_PLANE_ENABLE; +- dev_priv->pipeconf = pipeconf |= PIPEACONF_ENABLE; +- +- if (is_mipi) +- goto mrst_crtc_mode_set_exit; +- +- refclk = dev_priv->core_freq * 1000; +- +- dpll = 0; /*BIT16 = 0 for 100MHz reference */ +- +- ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock); +- +- if (!ok) { +- dev_dbg(dev->dev, "mrstFindBestPLL fail in mrst_crtc_mode_set.\n"); +- } else { +- dev_dbg(dev->dev, "mrst_crtc_mode_set pixel clock = %d," +- "m = %x, p1 = %x.\n", clock.dot, clock.m, +- clock.p1); +- } +- +- fp = mrst_m_converts[(clock.m - MRST_M_MIN)] << 8; +- +- dpll |= DPLL_VGA_MODE_DIS; +- +- +- dpll |= DPLL_VCO_ENABLE; +- +- if (is_lvds) +- dpll |= DPLLA_MODE_LVDS; +- else +- dpll |= DPLLB_MODE_DAC_SERIAL; +- +- if (is_sdvo) { +- int sdvo_pixel_multiply = +- adjusted_mode->clock / mode->clock; +- +- dpll |= DPLL_DVO_HIGH_SPEED; +- dpll |= +- (sdvo_pixel_multiply - +- 1) << SDVO_MULTIPLIER_SHIFT_HIRES; +- } +- +- +- /* compute bitmask from p1 value */ +- dpll |= (1 << (clock.p1 - 2)) << 17; +- +- dpll |= DPLL_VCO_ENABLE; +- +- mrstPrintPll("chosen", &clock); +- +- if (dpll & DPLL_VCO_ENABLE) { +- REG_WRITE(fp_reg, fp); +- REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- /* Check the DPLLA lock bit PIPEACONF[29] */ +- udelay(150); +- } +- +- REG_WRITE(fp_reg, fp); +- REG_WRITE(dpll_reg, dpll); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- +- /* write it again -- the BIOS does, after all */ +- REG_WRITE(dpll_reg, dpll); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- +- REG_WRITE(pipeconf_reg, pipeconf); +- REG_READ(pipeconf_reg); +- psb_intel_wait_for_vblank(dev); +- +- REG_WRITE(dspcntr_reg, dspcntr); +- psb_intel_wait_for_vblank(dev); +- +-mrst_crtc_mode_set_exit: +- gma_power_end(dev); +- return 0; +-} +- +-static bool mrst_crtc_mode_fixup(struct drm_crtc *crtc, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- return true; +-} +- +-int mrst_pipe_set_base(struct drm_crtc *crtc, +- int x, int y, struct drm_framebuffer *old_fb) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); +- int pipe = psb_intel_crtc->pipe; +- unsigned long start, offset; +- +- int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE); +- int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); +- int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; +- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; +- u32 dspcntr; +- int ret = 0; +- +- /* no fb bound */ +- if (!crtc->fb) { +- dev_dbg(dev->dev, "No FB bound\n"); +- return 0; +- } +- +- if (!gma_power_begin(dev, true)) +- return 0; +- +- start = psbfb->gtt->offset; +- offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); +- +- REG_WRITE(dspstride, crtc->fb->pitch); +- +- dspcntr = REG_READ(dspcntr_reg); +- dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; +- +- switch (crtc->fb->bits_per_pixel) { +- case 8: +- dspcntr |= DISPPLANE_8BPP; +- break; +- case 16: +- if (crtc->fb->depth == 15) +- dspcntr |= DISPPLANE_15_16BPP; +- else +- dspcntr |= DISPPLANE_16BPP; +- break; +- case 24: +- case 32: +- dspcntr |= DISPPLANE_32BPP_NO_ALPHA; +- break; +- default: +- dev_err(dev->dev, "Unknown color depth\n"); +- ret = -EINVAL; +- goto pipe_set_base_exit; +- } +- REG_WRITE(dspcntr_reg, dspcntr); +- +- REG_WRITE(dspbase, offset); +- REG_READ(dspbase); +- REG_WRITE(dspsurf, start); +- REG_READ(dspsurf); +- +-pipe_set_base_exit: +- gma_power_end(dev); +- return ret; +-} +- +-static void mrst_crtc_prepare(struct drm_crtc *crtc) +-{ +- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); +-} +- +-static void mrst_crtc_commit(struct drm_crtc *crtc) +-{ +- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); +-} +- +-const struct drm_crtc_helper_funcs mrst_helper_funcs = { +- .dpms = mrst_crtc_dpms, +- .mode_fixup = mrst_crtc_mode_fixup, +- .mode_set = mrst_crtc_mode_set, +- .mode_set_base = mrst_pipe_set_base, +- .prepare = mrst_crtc_prepare, +- .commit = mrst_crtc_commit, +-}; +- +diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c +deleted file mode 100644 +index 6707faf..0000000 +--- a/drivers/staging/gma500/mrst_device.c ++++ /dev/null +@@ -1,634 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-#include +-#include +-#include +-#include +-#include +-#include "psb_drm.h" +-#include "psb_drv.h" +-#include "psb_reg.h" +-#include "psb_intel_reg.h" +-#include +-#include +-#include "mid_bios.h" +- +-static int devtype; +- +-module_param_named(type, devtype, int, 0600); +-MODULE_PARM_DESC(type, "Moorestown/Oaktrail device type"); +- +-#define DEVICE_MOORESTOWN 1 +-#define DEVICE_OAKTRAIL 2 +-#define DEVICE_MOORESTOWN_MM 3 +- +-static int mrst_device_ident(struct drm_device *dev) +-{ +- /* User forced */ +- if (devtype) +- return devtype; +- if (dmi_match(DMI_PRODUCT_NAME, "OakTrail") || +- dmi_match(DMI_PRODUCT_NAME, "OakTrail platform")) +- return DEVICE_OAKTRAIL; +-#if defined(CONFIG_X86_MRST) +- if (dmi_match(DMI_PRODUCT_NAME, "MM") || +- dmi_match(DMI_PRODUCT_NAME, "MM 10")) +- return DEVICE_MOORESTOWN_MM; +- if (mrst_identify_cpu()) +- return DEVICE_MOORESTOWN; +-#endif +- return DEVICE_OAKTRAIL; +-} +- +- +-/* IPC message and command defines used to enable/disable mipi panel voltages */ +-#define IPC_MSG_PANEL_ON_OFF 0xE9 +-#define IPC_CMD_PANEL_ON 1 +-#define IPC_CMD_PANEL_OFF 0 +- +-static int mrst_output_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- if (dev_priv->iLVDS_enable) +- mrst_lvds_init(dev, &dev_priv->mode_dev); +- else +- dev_err(dev->dev, "DSI is not supported\n"); +- if (dev_priv->hdmi_priv) +- mrst_hdmi_init(dev, &dev_priv->mode_dev); +- return 0; +-} +- +-/* +- * Provide the low level interfaces for the Moorestown backlight +- */ +- +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- +-#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF +-#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ +-#define BLC_PWM_FREQ_CALC_CONSTANT 32 +-#define MHz 1000000 +-#define BLC_ADJUSTMENT_MAX 100 +- +-static struct backlight_device *mrst_backlight_device; +-static int mrst_brightness; +- +-static int mrst_set_brightness(struct backlight_device *bd) +-{ +- struct drm_device *dev = bl_get_data(mrst_backlight_device); +- struct drm_psb_private *dev_priv = dev->dev_private; +- int level = bd->props.brightness; +- u32 blc_pwm_ctl; +- u32 max_pwm_blc; +- +- /* Percentage 1-100% being valid */ +- if (level < 1) +- level = 1; +- +- if (gma_power_begin(dev, 0)) { +- /* Calculate and set the brightness value */ +- max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16; +- blc_pwm_ctl = level * max_pwm_blc / 100; +- +- /* Adjust the backlight level with the percent in +- * dev_priv->blc_adj1; +- */ +- blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1; +- blc_pwm_ctl = blc_pwm_ctl / 100; +- +- /* Adjust the backlight level with the percent in +- * dev_priv->blc_adj2; +- */ +- blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2; +- blc_pwm_ctl = blc_pwm_ctl / 100; +- +- /* force PWM bit on */ +- REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2))); +- REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl); +- gma_power_end(dev); +- } +- mrst_brightness = level; +- return 0; +-} +- +-static int mrst_get_brightness(struct backlight_device *bd) +-{ +- /* return locally cached var instead of HW read (due to DPST etc.) */ +- /* FIXME: ideally return actual value in case firmware fiddled with +- it */ +- return mrst_brightness; +-} +- +-static int device_backlight_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- unsigned long core_clock; +- u16 bl_max_freq; +- uint32_t value; +- uint32_t blc_pwm_precision_factor; +- +- dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX; +- dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX; +- bl_max_freq = 256; +- /* this needs to be set elsewhere */ +- blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR; +- +- core_clock = dev_priv->core_freq; +- +- value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; +- value *= blc_pwm_precision_factor; +- value /= bl_max_freq; +- value /= blc_pwm_precision_factor; +- +- if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ) +- return -ERANGE; +- +- if (gma_power_begin(dev, false)) { +- REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2))); +- REG_WRITE(BLC_PWM_CTL, value | (value << 16)); +- gma_power_end(dev); +- } +- return 0; +-} +- +-static const struct backlight_ops mrst_ops = { +- .get_brightness = mrst_get_brightness, +- .update_status = mrst_set_brightness, +-}; +- +-int mrst_backlight_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- int ret; +- struct backlight_properties props; +- +- memset(&props, 0, sizeof(struct backlight_properties)); +- props.max_brightness = 100; +- props.type = BACKLIGHT_PLATFORM; +- +- mrst_backlight_device = backlight_device_register("mrst-bl", +- NULL, (void *)dev, &mrst_ops, &props); +- +- if (IS_ERR(mrst_backlight_device)) +- return PTR_ERR(mrst_backlight_device); +- +- ret = device_backlight_init(dev); +- if (ret < 0) { +- backlight_device_unregister(mrst_backlight_device); +- return ret; +- } +- mrst_backlight_device->props.brightness = 100; +- mrst_backlight_device->props.max_brightness = 100; +- backlight_update_status(mrst_backlight_device); +- dev_priv->backlight_device = mrst_backlight_device; +- return 0; +-} +- +-#endif +- +-/* +- * Provide the Moorestown specific chip logic and low level methods +- * for power management +- */ +- +-static void mrst_init_pm(struct drm_device *dev) +-{ +-} +- +-/** +- * mrst_save_display_registers - save registers lost on suspend +- * @dev: our DRM device +- * +- * Save the state we need in order to be able to restore the interface +- * upon resume from suspend +- */ +-static int mrst_save_display_registers(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- int i; +- u32 pp_stat; +- +- /* Display arbitration control + watermarks */ +- dev_priv->saveDSPARB = PSB_RVDC32(DSPARB); +- dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1); +- dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2); +- dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3); +- dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4); +- dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5); +- dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6); +- dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); +- +- /* Pipe & plane A info */ +- dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF); +- dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC); +- dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0); +- dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1); +- dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A); +- dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A); +- dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A); +- dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A); +- dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A); +- dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A); +- dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A); +- dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A); +- dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR); +- dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE); +- dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE); +- dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF); +- dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF); +- dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF); +- +- /* Save cursor regs */ +- dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR); +- dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE); +- dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS); +- +- /* Save palette (gamma) */ +- for (i = 0; i < 256; i++) +- dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2)); +- +- if (dev_priv->hdmi_priv) +- mrst_hdmi_save(dev); +- +- /* Save performance state */ +- dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE); +- +- /* LVDS state */ +- dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL); +- dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS); +- dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS); +- dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL); +- dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2); +- dev_priv->saveLVDS = PSB_RVDC32(LVDS); +- dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL); +- dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON); +- dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF); +- dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE); +- +- /* HW overlay */ +- dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD); +- dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0); +- dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1); +- dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2); +- dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3); +- dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4); +- dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5); +- +- /* DPST registers */ +- dev_priv->saveHISTOGRAM_INT_CONTROL_REG = +- PSB_RVDC32(HISTOGRAM_INT_CONTROL); +- dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG = +- PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); +- dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC); +- +- if (dev_priv->iLVDS_enable) { +- /* Shut down the panel */ +- PSB_WVDC32(0, PP_CONTROL); +- +- do { +- pp_stat = PSB_RVDC32(PP_STATUS); +- } while (pp_stat & 0x80000000); +- +- /* Turn off the plane */ +- PSB_WVDC32(0x58000000, DSPACNTR); +- /* Trigger the plane disable */ +- PSB_WVDC32(0, DSPASURF); +- +- /* Wait ~4 ticks */ +- msleep(4); +- +- /* Turn off pipe */ +- PSB_WVDC32(0x0, PIPEACONF); +- /* Wait ~8 ticks */ +- msleep(8); +- +- /* Turn off PLLs */ +- PSB_WVDC32(0, MRST_DPLL_A); +- } +- return 0; +-} +- +-/** +- * mrst_restore_display_registers - restore lost register state +- * @dev: our DRM device +- * +- * Restore register state that was lost during suspend and resume. +- */ +-static int mrst_restore_display_registers(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 pp_stat; +- int i; +- +- /* Display arbitration + watermarks */ +- PSB_WVDC32(dev_priv->saveDSPARB, DSPARB); +- PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1); +- PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2); +- PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3); +- PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4); +- PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5); +- PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6); +- PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT); +- +- /* Make sure VGA plane is off. it initializes to on after reset!*/ +- PSB_WVDC32(0x80000000, VGACNTRL); +- +- /* set the plls */ +- PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0); +- PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1); +- +- /* Actually enable it */ +- PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A); +- DRM_UDELAY(150); +- +- /* Restore mode */ +- PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A); +- PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A); +- PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A); +- PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A); +- PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A); +- PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A); +- PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC); +- PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A); +- +- /* Restore performance mode*/ +- PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE); +- +- /* Enable the pipe*/ +- if (dev_priv->iLVDS_enable) +- PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF); +- +- /* Set up the plane*/ +- PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF); +- PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE); +- PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF); +- +- /* Enable the plane */ +- PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR); +- PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF); +- +- /* Enable Cursor A */ +- PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR); +- PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS); +- PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE); +- +- /* Restore palette (gamma) */ +- for (i = 0; i < 256; i++) +- PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i << 2)); +- +- if (dev_priv->hdmi_priv) +- mrst_hdmi_restore(dev); +- +- if (dev_priv->iLVDS_enable) { +- PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2); +- PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/ +- PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL); +- PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); +- PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS); +- PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL); +- PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON); +- PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF); +- PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE); +- PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL); +- } +- +- /* Wait for cycle delay */ +- do { +- pp_stat = PSB_RVDC32(PP_STATUS); +- } while (pp_stat & 0x08000000); +- +- /* Wait for panel power up */ +- do { +- pp_stat = PSB_RVDC32(PP_STATUS); +- } while (pp_stat & 0x10000000); +- +- /* Restore HW overlay */ +- PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD); +- PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0); +- PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1); +- PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2); +- PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3); +- PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4); +- PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5); +- +- /* DPST registers */ +- PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG, +- HISTOGRAM_INT_CONTROL); +- PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG, +- HISTOGRAM_LOGIC_CONTROL); +- PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC); +- +- return 0; +-} +- +-/** +- * mrst_power_down - power down the display island +- * @dev: our DRM device +- * +- * Power down the display interface of our device +- */ +-static int mrst_power_down(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 pwr_mask ; +- u32 pwr_sts; +- +- pwr_mask = PSB_PWRGT_DISPLAY_MASK; +- outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC); +- +- while (true) { +- pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); +- if ((pwr_sts & pwr_mask) == pwr_mask) +- break; +- else +- udelay(10); +- } +- return 0; +-} +- +-/* +- * mrst_power_up +- * +- * Restore power to the specified island(s) (powergating) +- */ +-static int mrst_power_up(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK; +- u32 pwr_sts, pwr_cnt; +- +- pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC); +- pwr_cnt &= ~pwr_mask; +- outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC)); +- +- while (true) { +- pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); +- if ((pwr_sts & pwr_mask) == 0) +- break; +- else +- udelay(10); +- } +- return 0; +-} +- +-#if defined(CONFIG_X86_MRST) +-static void mrst_lvds_cache_bl(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- intel_scu_ipc_ioread8(0x28, &(dev_priv->saveBKLTCNT)); +- intel_scu_ipc_ioread8(0x29, &(dev_priv->saveBKLTREQ)); +- intel_scu_ipc_ioread8(0x2A, &(dev_priv->saveBKLTBRTL)); +-} +- +-static void mrst_mm_bl_power(struct drm_device *dev, bool on) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (on) { +- intel_scu_ipc_iowrite8(0x2A, dev_priv->saveBKLTBRTL); +- intel_scu_ipc_iowrite8(0x28, dev_priv->saveBKLTCNT); +- intel_scu_ipc_iowrite8(0x29, dev_priv->saveBKLTREQ); +- } else { +- intel_scu_ipc_iowrite8(0x2A, 0); +- intel_scu_ipc_iowrite8(0x28, 0); +- intel_scu_ipc_iowrite8(0x29, 0); +- } +-} +- +-static const struct psb_ops mrst_mm_chip_ops = { +- .name = "Moorestown MM ", +- .accel_2d = 1, +- .pipes = 1, +- .crtcs = 1, +- .sgx_offset = MRST_SGX_OFFSET, +- +- .crtc_helper = &mrst_helper_funcs, +- .crtc_funcs = &psb_intel_crtc_funcs, +- +- .output_init = mrst_output_init, +- +- .lvds_bl_power = mrst_mm_bl_power, +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- .backlight_init = mrst_backlight_init, +-#endif +- +- .init_pm = mrst_init_pm, +- .save_regs = mrst_save_display_registers, +- .restore_regs = mrst_restore_display_registers, +- .power_down = mrst_power_down, +- .power_up = mrst_power_up, +- +- .i2c_bus = 0, +-}; +- +-#endif +- +-static void oaktrail_teardown(struct drm_device *dev) +-{ +- mrst_hdmi_teardown(dev); +-} +- +-static const struct psb_ops oaktrail_chip_ops = { +- .name = "Oaktrail", +- .accel_2d = 1, +- .pipes = 2, +- .crtcs = 2, +- .sgx_offset = MRST_SGX_OFFSET, +- +- .chip_setup = mid_chip_setup, +- .chip_teardown = oaktrail_teardown, +- .crtc_helper = &mrst_helper_funcs, +- .crtc_funcs = &psb_intel_crtc_funcs, +- +- .output_init = mrst_output_init, +- +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- .backlight_init = mrst_backlight_init, +-#endif +- +- .init_pm = mrst_init_pm, +- .save_regs = mrst_save_display_registers, +- .restore_regs = mrst_restore_display_registers, +- .power_down = mrst_power_down, +- .power_up = mrst_power_up, +- +- .i2c_bus = 1, +-}; +- +-/** +- * mrst_chip_setup - perform the initial chip init +- * @dev: Our drm_device +- * +- * Figure out which incarnation we are and then scan the firmware for +- * tables and information. +- */ +-static int mrst_chip_setup(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- switch (mrst_device_ident(dev)) { +- case DEVICE_OAKTRAIL: +- /* Dual CRTC, PC compatible, HDMI, I2C #2 */ +- dev_priv->ops = &oaktrail_chip_ops; +- mrst_hdmi_setup(dev); +- return mid_chip_setup(dev); +-#if defined(CONFIG_X86_MRST) +- case DEVICE_MOORESTOWN_MM: +- /* Single CRTC, No HDMI, I2C #0, BL control */ +- mrst_lvds_cache_bl(dev); +- dev_priv->ops = &mrst_mm_chip_ops; +- return mid_chip_setup(dev); +- case DEVICE_MOORESTOWN: +- /* Dual CRTC, No HDMI(?), I2C #1 */ +- return mid_chip_setup(dev); +-#endif +- default: +- dev_err(dev->dev, "unsupported device type.\n"); +- return -ENODEV; +- } +-} +- +-const struct psb_ops mrst_chip_ops = { +- .name = "Moorestown", +- .accel_2d = 1, +- .pipes = 2, +- .crtcs = 2, +- .sgx_offset = MRST_SGX_OFFSET, +- +- .chip_setup = mrst_chip_setup, +- .crtc_helper = &mrst_helper_funcs, +- .crtc_funcs = &psb_intel_crtc_funcs, +- +- .output_init = mrst_output_init, +- +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- .backlight_init = mrst_backlight_init, +-#endif +- +- .init_pm = mrst_init_pm, +- .save_regs = mrst_save_display_registers, +- .restore_regs = mrst_restore_display_registers, +- .power_down = mrst_power_down, +- .power_up = mrst_power_up, +- +- .i2c_bus = 2, +-}; +- +diff --git a/drivers/staging/gma500/mrst_hdmi.c b/drivers/staging/gma500/mrst_hdmi.c +deleted file mode 100644 +index e66607e..0000000 +--- a/drivers/staging/gma500/mrst_hdmi.c ++++ /dev/null +@@ -1,852 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Li Peng +- */ +- +-#include +-#include +-#include "psb_intel_drv.h" +-#include "psb_intel_reg.h" +-#include "psb_drv.h" +- +-#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg)) +-#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg)) +- +-#define HDMI_HCR 0x1000 +-#define HCR_ENABLE_HDCP (1 << 5) +-#define HCR_ENABLE_AUDIO (1 << 2) +-#define HCR_ENABLE_PIXEL (1 << 1) +-#define HCR_ENABLE_TMDS (1 << 0) +- +-#define HDMI_HICR 0x1004 +-#define HDMI_HSR 0x1008 +-#define HDMI_HISR 0x100C +-#define HDMI_DETECT_HDP (1 << 0) +- +-#define HDMI_VIDEO_REG 0x3000 +-#define HDMI_UNIT_EN (1 << 7) +-#define HDMI_MODE_OUTPUT (1 << 0) +-#define HDMI_HBLANK_A 0x3100 +- +-#define HDMI_AUDIO_CTRL 0x4000 +-#define HDMI_ENABLE_AUDIO (1 << 0) +- +-#define PCH_HTOTAL_B 0x3100 +-#define PCH_HBLANK_B 0x3104 +-#define PCH_HSYNC_B 0x3108 +-#define PCH_VTOTAL_B 0x310C +-#define PCH_VBLANK_B 0x3110 +-#define PCH_VSYNC_B 0x3114 +-#define PCH_PIPEBSRC 0x311C +- +-#define PCH_PIPEB_DSL 0x3800 +-#define PCH_PIPEB_SLC 0x3804 +-#define PCH_PIPEBCONF 0x3808 +-#define PCH_PIPEBSTAT 0x3824 +- +-#define CDVO_DFT 0x5000 +-#define CDVO_SLEWRATE 0x5004 +-#define CDVO_STRENGTH 0x5008 +-#define CDVO_RCOMP 0x500C +- +-#define DPLL_CTRL 0x6000 +-#define DPLL_PDIV_SHIFT 16 +-#define DPLL_PDIV_MASK (0xf << 16) +-#define DPLL_PWRDN (1 << 4) +-#define DPLL_RESET (1 << 3) +-#define DPLL_FASTEN (1 << 2) +-#define DPLL_ENSTAT (1 << 1) +-#define DPLL_DITHEN (1 << 0) +- +-#define DPLL_DIV_CTRL 0x6004 +-#define DPLL_CLKF_MASK 0xffffffc0 +-#define DPLL_CLKR_MASK (0x3f) +- +-#define DPLL_CLK_ENABLE 0x6008 +-#define DPLL_EN_DISP (1 << 31) +-#define DPLL_SEL_HDMI (1 << 8) +-#define DPLL_EN_HDMI (1 << 1) +-#define DPLL_EN_VGA (1 << 0) +- +-#define DPLL_ADJUST 0x600C +-#define DPLL_STATUS 0x6010 +-#define DPLL_UPDATE 0x6014 +-#define DPLL_DFT 0x6020 +- +-struct intel_range { +- int min, max; +-}; +- +-struct mrst_hdmi_limit { +- struct intel_range vco, np, nr, nf; +-}; +- +-struct mrst_hdmi_clock { +- int np; +- int nr; +- int nf; +- int dot; +-}; +- +-#define VCO_MIN 320000 +-#define VCO_MAX 1650000 +-#define NP_MIN 1 +-#define NP_MAX 15 +-#define NR_MIN 1 +-#define NR_MAX 64 +-#define NF_MIN 2 +-#define NF_MAX 4095 +- +-static const struct mrst_hdmi_limit mrst_hdmi_limit = { +- .vco = { .min = VCO_MIN, .max = VCO_MAX }, +- .np = { .min = NP_MIN, .max = NP_MAX }, +- .nr = { .min = NR_MIN, .max = NR_MAX }, +- .nf = { .min = NF_MIN, .max = NF_MAX }, +-}; +- +-static void wait_for_vblank(struct drm_device *dev) +-{ +- /* FIXME: Can we do this as a sleep ? */ +- /* Wait for 20ms, i.e. one cycle at 50hz. */ +- mdelay(20); +-} +- +-static void scu_busy_loop(void *scu_base) +-{ +- u32 status = 0; +- u32 loop_count = 0; +- +- status = readl(scu_base + 0x04); +- while (status & 1) { +- udelay(1); /* scu processing time is in few u secods */ +- status = readl(scu_base + 0x04); +- loop_count++; +- /* break if scu doesn't reset busy bit after huge retry */ +- if (loop_count > 1000) { +- DRM_DEBUG_KMS("SCU IPC timed out"); +- return; +- } +- } +-} +- +-static void mrst_hdmi_reset(struct drm_device *dev) +-{ +- void *base; +- /* FIXME: at least make these defines */ +- unsigned int scu_ipc_mmio = 0xff11c000; +- int scu_len = 1024; +- +- base = ioremap((resource_size_t)scu_ipc_mmio, scu_len); +- if (base == NULL) { +- DRM_ERROR("failed to map SCU mmio\n"); +- return; +- } +- +- /* scu ipc: assert hdmi controller reset */ +- writel(0xff11d118, base + 0x0c); +- writel(0x7fffffdf, base + 0x80); +- writel(0x42005, base + 0x0); +- scu_busy_loop(base); +- +- /* scu ipc: de-assert hdmi controller reset */ +- writel(0xff11d118, base + 0x0c); +- writel(0x7fffffff, base + 0x80); +- writel(0x42005, base + 0x0); +- scu_busy_loop(base); +- +- iounmap(base); +-} +- +-static void mrst_hdmi_audio_enable(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; +- +- HDMI_WRITE(HDMI_HCR, 0x67); +- HDMI_READ(HDMI_HCR); +- +- HDMI_WRITE(0x51a8, 0x10); +- HDMI_READ(0x51a8); +- +- HDMI_WRITE(HDMI_AUDIO_CTRL, 0x1); +- HDMI_READ(HDMI_AUDIO_CTRL); +-} +- +-static void mrst_hdmi_audio_disable(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; +- +- HDMI_WRITE(0x51a8, 0x0); +- HDMI_READ(0x51a8); +- +- HDMI_WRITE(HDMI_AUDIO_CTRL, 0x0); +- HDMI_READ(HDMI_AUDIO_CTRL); +- +- HDMI_WRITE(HDMI_HCR, 0x47); +- HDMI_READ(HDMI_HCR); +-} +- +-void mrst_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode) +-{ +- struct drm_device *dev = crtc->dev; +- u32 temp; +- +- switch (mode) { +- case DRM_MODE_DPMS_OFF: +- /* Disable VGACNTRL */ +- REG_WRITE(VGACNTRL, 0x80000000); +- +- /* Disable plane */ +- temp = REG_READ(DSPBCNTR); +- if ((temp & DISPLAY_PLANE_ENABLE) != 0) { +- REG_WRITE(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); +- REG_READ(DSPBCNTR); +- /* Flush the plane changes */ +- REG_WRITE(DSPBSURF, REG_READ(DSPBSURF)); +- REG_READ(DSPBSURF); +- } +- +- /* Disable pipe B */ +- temp = REG_READ(PIPEBCONF); +- if ((temp & PIPEACONF_ENABLE) != 0) { +- REG_WRITE(PIPEBCONF, temp & ~PIPEACONF_ENABLE); +- REG_READ(PIPEBCONF); +- } +- +- /* Disable LNW Pipes, etc */ +- temp = REG_READ(PCH_PIPEBCONF); +- if ((temp & PIPEACONF_ENABLE) != 0) { +- REG_WRITE(PCH_PIPEBCONF, temp & ~PIPEACONF_ENABLE); +- REG_READ(PCH_PIPEBCONF); +- } +- /* wait for pipe off */ +- udelay(150); +- /* Disable dpll */ +- temp = REG_READ(DPLL_CTRL); +- if ((temp & DPLL_PWRDN) == 0) { +- REG_WRITE(DPLL_CTRL, temp | (DPLL_PWRDN | DPLL_RESET)); +- REG_WRITE(DPLL_STATUS, 0x1); +- } +- /* wait for dpll off */ +- udelay(150); +- break; +- case DRM_MODE_DPMS_ON: +- case DRM_MODE_DPMS_STANDBY: +- case DRM_MODE_DPMS_SUSPEND: +- /* Enable dpll */ +- temp = REG_READ(DPLL_CTRL); +- if ((temp & DPLL_PWRDN) != 0) { +- REG_WRITE(DPLL_CTRL, temp & ~(DPLL_PWRDN | DPLL_RESET)); +- temp = REG_READ(DPLL_CLK_ENABLE); +- REG_WRITE(DPLL_CLK_ENABLE, temp | DPLL_EN_DISP | DPLL_SEL_HDMI | DPLL_EN_HDMI); +- REG_READ(DPLL_CLK_ENABLE); +- } +- /* wait for dpll warm up */ +- udelay(150); +- +- /* Enable pipe B */ +- temp = REG_READ(PIPEBCONF); +- if ((temp & PIPEACONF_ENABLE) == 0) { +- REG_WRITE(PIPEBCONF, temp | PIPEACONF_ENABLE); +- REG_READ(PIPEBCONF); +- } +- +- /* Enable LNW Pipe B */ +- temp = REG_READ(PCH_PIPEBCONF); +- if ((temp & PIPEACONF_ENABLE) == 0) { +- REG_WRITE(PCH_PIPEBCONF, temp | PIPEACONF_ENABLE); +- REG_READ(PCH_PIPEBCONF); +- } +- wait_for_vblank(dev); +- +- /* Enable plane */ +- temp = REG_READ(DSPBCNTR); +- if ((temp & DISPLAY_PLANE_ENABLE) == 0) { +- REG_WRITE(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE); +- /* Flush the plane changes */ +- REG_WRITE(DSPBSURF, REG_READ(DSPBSURF)); +- REG_READ(DSPBSURF); +- } +- psb_intel_crtc_load_lut(crtc); +- } +- /* DSPARB */ +- REG_WRITE(DSPARB, 0x00003fbf); +- /* FW1 */ +- REG_WRITE(0x70034, 0x3f880a0a); +- /* FW2 */ +- REG_WRITE(0x70038, 0x0b060808); +- /* FW4 */ +- REG_WRITE(0x70050, 0x08030404); +- /* FW5 */ +- REG_WRITE(0x70054, 0x04040404); +- /* LNC Chicken Bits */ +- REG_WRITE(0x70400, 0x4000); +-} +- +- +-static void mrst_hdmi_dpms(struct drm_encoder *encoder, int mode) +-{ +- static int dpms_mode = -1; +- +- struct drm_device *dev = encoder->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; +- u32 temp; +- +- if (dpms_mode == mode) +- return; +- +- if (mode != DRM_MODE_DPMS_ON) +- temp = 0x0; +- else +- temp = 0x99; +- +- dpms_mode = mode; +- HDMI_WRITE(HDMI_VIDEO_REG, temp); +-} +- +-static unsigned int htotal_calculate(struct drm_display_mode *mode) +-{ +- u32 htotal, new_crtc_htotal; +- +- htotal = (mode->crtc_hdisplay - 1) | ((mode->crtc_htotal - 1) << 16); +- +- /* +- * 1024 x 768 new_crtc_htotal = 0x1024; +- * 1280 x 1024 new_crtc_htotal = 0x0c34; +- */ +- new_crtc_htotal = (mode->crtc_htotal - 1) * 200 * 1000 / mode->clock; +- +- return (mode->crtc_hdisplay - 1) | (new_crtc_htotal << 16); +-} +- +-static void mrst_hdmi_find_dpll(struct drm_crtc *crtc, int target, +- int refclk, struct mrst_hdmi_clock *best_clock) +-{ +- int np_min, np_max, nr_min, nr_max; +- int np, nr, nf; +- +- np_min = DIV_ROUND_UP(mrst_hdmi_limit.vco.min, target * 10); +- np_max = mrst_hdmi_limit.vco.max / (target * 10); +- if (np_min < mrst_hdmi_limit.np.min) +- np_min = mrst_hdmi_limit.np.min; +- if (np_max > mrst_hdmi_limit.np.max) +- np_max = mrst_hdmi_limit.np.max; +- +- nr_min = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_max)); +- nr_max = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_min)); +- if (nr_min < mrst_hdmi_limit.nr.min) +- nr_min = mrst_hdmi_limit.nr.min; +- if (nr_max > mrst_hdmi_limit.nr.max) +- nr_max = mrst_hdmi_limit.nr.max; +- +- np = DIV_ROUND_UP((refclk * 1000), (target * 10 * nr_max)); +- nr = DIV_ROUND_UP((refclk * 1000), (target * 10 * np)); +- nf = DIV_ROUND_CLOSEST((target * 10 * np * nr), refclk); +- DRM_DEBUG_KMS("np, nr, nf %d %d %d\n", np, nr, nf); +- +- /* +- * 1024 x 768 np = 1; nr = 0x26; nf = 0x0fd8000; +- * 1280 x 1024 np = 1; nr = 0x17; nf = 0x1034000; +- */ +- best_clock->np = np; +- best_clock->nr = nr - 1; +- best_clock->nf = (nf << 14); +-} +- +-int mrst_crtc_hdmi_mode_set(struct drm_crtc *crtc, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode, +- int x, int y, +- struct drm_framebuffer *old_fb) +-{ +- struct drm_device *dev = crtc->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; +- int pipe = 1; +- int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; +- int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; +- int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; +- int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; +- int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; +- int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; +- int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; +- int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; +- int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; +- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; +- int refclk; +- struct mrst_hdmi_clock clock; +- u32 dspcntr, pipeconf, dpll, temp; +- int dspcntr_reg = DSPBCNTR; +- +- /* Disable the VGA plane that we never use */ +- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); +- +- /* XXX: Disable the panel fitter if it was on our pipe */ +- +- /* Disable dpll if necessary */ +- dpll = REG_READ(DPLL_CTRL); +- if ((dpll & DPLL_PWRDN) == 0) { +- REG_WRITE(DPLL_CTRL, dpll | (DPLL_PWRDN | DPLL_RESET)); +- REG_WRITE(DPLL_DIV_CTRL, 0x00000000); +- REG_WRITE(DPLL_STATUS, 0x1); +- } +- udelay(150); +- +- /* reset controller: FIXME - can we sort out the ioremap mess ? */ +- iounmap(hdmi_dev->regs); +- mrst_hdmi_reset(dev); +- +- /* program and enable dpll */ +- refclk = 25000; +- mrst_hdmi_find_dpll(crtc, adjusted_mode->clock, refclk, &clock); +- +- /* Setting DPLL */ +- dpll = REG_READ(DPLL_CTRL); +- dpll &= ~DPLL_PDIV_MASK; +- dpll &= ~(DPLL_PWRDN | DPLL_RESET); +- REG_WRITE(DPLL_CTRL, 0x00000008); +- REG_WRITE(DPLL_DIV_CTRL, ((clock.nf << 6) | clock.nr)); +- REG_WRITE(DPLL_ADJUST, ((clock.nf >> 14) - 1)); +- REG_WRITE(DPLL_CTRL, (dpll | (clock.np << DPLL_PDIV_SHIFT) | DPLL_ENSTAT | DPLL_DITHEN)); +- REG_WRITE(DPLL_UPDATE, 0x80000000); +- REG_WRITE(DPLL_CLK_ENABLE, 0x80050102); +- udelay(150); +- +- hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len); +- if (hdmi_dev->regs == NULL) { +- DRM_ERROR("failed to do hdmi mmio mapping\n"); +- return -ENOMEM; +- } +- +- /* configure HDMI */ +- HDMI_WRITE(0x1004, 0x1fd); +- HDMI_WRITE(0x2000, 0x1); +- HDMI_WRITE(0x2008, 0x0); +- HDMI_WRITE(0x3130, 0x8); +- HDMI_WRITE(0x101c, 0x1800810); +- +- temp = htotal_calculate(adjusted_mode); +- REG_WRITE(htot_reg, temp); +- REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16)); +- REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16)); +- REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16)); +- REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16)); +- REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16)); +- REG_WRITE(pipesrc_reg, +- ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1)); +- +- REG_WRITE(PCH_HTOTAL_B, (adjusted_mode->crtc_hdisplay - 1) | ((adjusted_mode->crtc_htotal - 1) << 16)); +- REG_WRITE(PCH_HBLANK_B, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16)); +- REG_WRITE(PCH_HSYNC_B, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16)); +- REG_WRITE(PCH_VTOTAL_B, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16)); +- REG_WRITE(PCH_VBLANK_B, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16)); +- REG_WRITE(PCH_VSYNC_B, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16)); +- REG_WRITE(PCH_PIPEBSRC, +- ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1)); +- +- temp = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start; +- HDMI_WRITE(HDMI_HBLANK_A, ((adjusted_mode->crtc_hdisplay - 1) << 16) | temp); +- +- REG_WRITE(dspsize_reg, +- ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); +- REG_WRITE(dsppos_reg, 0); +- +- /* Flush the plane changes */ +- { +- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +- crtc_funcs->mode_set_base(crtc, x, y, old_fb); +- } +- +- /* Set up the display plane register */ +- dspcntr = REG_READ(dspcntr_reg); +- dspcntr |= DISPPLANE_GAMMA_ENABLE; +- dspcntr |= DISPPLANE_SEL_PIPE_B; +- dspcntr |= DISPLAY_PLANE_ENABLE; +- +- /* setup pipeconf */ +- pipeconf = REG_READ(pipeconf_reg); +- pipeconf |= PIPEACONF_ENABLE; +- +- REG_WRITE(pipeconf_reg, pipeconf); +- REG_READ(pipeconf_reg); +- +- REG_WRITE(PCH_PIPEBCONF, pipeconf); +- REG_READ(PCH_PIPEBCONF); +- wait_for_vblank(dev); +- +- REG_WRITE(dspcntr_reg, dspcntr); +- wait_for_vblank(dev); +- +- return 0; +-} +- +-static int mrst_hdmi_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) +-{ +- if (mode->clock > 165000) +- return MODE_CLOCK_HIGH; +- if (mode->clock < 20000) +- return MODE_CLOCK_LOW; +- +- if (mode->flags & DRM_MODE_FLAG_DBLSCAN) +- return MODE_NO_DBLESCAN; +- +- return MODE_OK; +-} +- +-static bool mrst_hdmi_mode_fixup(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- return true; +-} +- +-static enum drm_connector_status +-mrst_hdmi_detect(struct drm_connector *connector, bool force) +-{ +- enum drm_connector_status status; +- struct drm_device *dev = connector->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; +- u32 temp; +- +- temp = HDMI_READ(HDMI_HSR); +- DRM_DEBUG_KMS("HDMI_HSR %x\n", temp); +- +- if ((temp & HDMI_DETECT_HDP) != 0) +- status = connector_status_connected; +- else +- status = connector_status_disconnected; +- +- return status; +-} +- +-static const unsigned char raw_edid[] = { +- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x2f, 0xa0, +- 0x53, 0x55, 0x33, 0x30, 0x16, 0x13, 0x01, 0x03, 0x0e, 0x3a, 0x24, 0x78, +- 0xea, 0xe9, 0xf5, 0xac, 0x51, 0x30, 0xb4, 0x25, 0x11, 0x50, 0x54, 0xa5, +- 0x4b, 0x00, 0x81, 0x80, 0xa9, 0x40, 0x71, 0x4f, 0xb3, 0x00, 0x01, 0x01, +- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0, +- 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x46, 0x6c, 0x21, 0x00, 0x00, 0x1a, +- 0x00, 0x00, 0x00, 0xff, 0x00, 0x47, 0x4e, 0x37, 0x32, 0x31, 0x39, 0x35, +- 0x52, 0x30, 0x33, 0x55, 0x53, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44, +- 0x45, 0x4c, 0x4c, 0x20, 0x32, 0x37, 0x30, 0x39, 0x57, 0x0a, 0x20, 0x20, +- 0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x8d +-}; +- +-static int mrst_hdmi_get_modes(struct drm_connector *connector) +-{ +- struct drm_device *dev = connector->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct i2c_adapter *i2c_adap; +- struct edid *edid; +- struct drm_display_mode *mode, *t; +- int i = 0, ret = 0; +- +- i2c_adap = i2c_get_adapter(3); +- if (i2c_adap == NULL) { +- DRM_ERROR("No ddc adapter available!\n"); +- edid = (struct edid *)raw_edid; +- } else { +- edid = (struct edid *)raw_edid; +- /* FIXME ? edid = drm_get_edid(connector, i2c_adap); */ +- } +- +- if (edid) { +- drm_mode_connector_update_edid_property(connector, edid); +- ret = drm_add_edid_modes(connector, edid); +- connector->display_info.raw_edid = NULL; +- } +- +- /* +- * prune modes that require frame buffer bigger than stolen mem +- */ +- list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { +- if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) { +- i++; +- drm_mode_remove(connector, mode); +- } +- } +- return ret - i; +-} +- +-static void mrst_hdmi_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- struct drm_device *dev = encoder->dev; +- +- mrst_hdmi_audio_enable(dev); +- return; +-} +- +-static void mrst_hdmi_destroy(struct drm_connector *connector) +-{ +- return; +-} +- +-static const struct drm_encoder_helper_funcs mrst_hdmi_helper_funcs = { +- .dpms = mrst_hdmi_dpms, +- .mode_fixup = mrst_hdmi_mode_fixup, +- .prepare = psb_intel_encoder_prepare, +- .mode_set = mrst_hdmi_mode_set, +- .commit = psb_intel_encoder_commit, +-}; +- +-static const struct drm_connector_helper_funcs +- mrst_hdmi_connector_helper_funcs = { +- .get_modes = mrst_hdmi_get_modes, +- .mode_valid = mrst_hdmi_mode_valid, +- .best_encoder = psb_intel_best_encoder, +-}; +- +-static const struct drm_connector_funcs mrst_hdmi_connector_funcs = { +- .dpms = drm_helper_connector_dpms, +- .detect = mrst_hdmi_detect, +- .fill_modes = drm_helper_probe_single_connector_modes, +- .destroy = mrst_hdmi_destroy, +-}; +- +-static void mrst_hdmi_enc_destroy(struct drm_encoder *encoder) +-{ +- drm_encoder_cleanup(encoder); +-} +- +-static const struct drm_encoder_funcs mrst_hdmi_enc_funcs = { +- .destroy = mrst_hdmi_enc_destroy, +-}; +- +-void mrst_hdmi_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev) +-{ +- struct psb_intel_output *psb_intel_output; +- struct drm_connector *connector; +- struct drm_encoder *encoder; +- +- psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); +- if (!psb_intel_output) +- return; +- +- psb_intel_output->mode_dev = mode_dev; +- connector = &psb_intel_output->base; +- encoder = &psb_intel_output->enc; +- drm_connector_init(dev, &psb_intel_output->base, +- &mrst_hdmi_connector_funcs, +- DRM_MODE_CONNECTOR_DVID); +- +- drm_encoder_init(dev, &psb_intel_output->enc, +- &mrst_hdmi_enc_funcs, +- DRM_MODE_ENCODER_TMDS); +- +- drm_mode_connector_attach_encoder(&psb_intel_output->base, +- &psb_intel_output->enc); +- +- psb_intel_output->type = INTEL_OUTPUT_HDMI; +- drm_encoder_helper_add(encoder, &mrst_hdmi_helper_funcs); +- drm_connector_helper_add(connector, &mrst_hdmi_connector_helper_funcs); +- +- connector->display_info.subpixel_order = SubPixelHorizontalRGB; +- connector->interlace_allowed = false; +- connector->doublescan_allowed = false; +- drm_sysfs_connector_add(connector); +- +- return; +-} +- +-static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = { +- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) }, +- {} +-}; +- +-void mrst_hdmi_setup(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct pci_dev *pdev; +- struct mrst_hdmi_dev *hdmi_dev; +- int ret; +- +- pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x080d, NULL); +- if (!pdev) +- return; +- +- hdmi_dev = kzalloc(sizeof(struct mrst_hdmi_dev), GFP_KERNEL); +- if (!hdmi_dev) { +- dev_err(dev->dev, "failed to allocate memory\n"); +- goto out; +- } +- +- +- ret = pci_enable_device(pdev); +- if (ret) { +- dev_err(dev->dev, "failed to enable hdmi controller\n"); +- goto free; +- } +- +- hdmi_dev->mmio = pci_resource_start(pdev, 0); +- hdmi_dev->mmio_len = pci_resource_len(pdev, 0); +- hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len); +- if (!hdmi_dev->regs) { +- dev_err(dev->dev, "failed to map hdmi mmio\n"); +- goto free; +- } +- +- hdmi_dev->dev = pdev; +- pci_set_drvdata(pdev, hdmi_dev); +- +- /* Initialize i2c controller */ +- ret = mrst_hdmi_i2c_init(hdmi_dev->dev); +- if (ret) +- dev_err(dev->dev, "HDMI I2C initialization failed\n"); +- +- dev_priv->hdmi_priv = hdmi_dev; +- mrst_hdmi_audio_disable(dev); +- return; +- +-free: +- kfree(hdmi_dev); +-out: +- return; +-} +- +-void mrst_hdmi_teardown(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; +- struct pci_dev *pdev; +- +- if (hdmi_dev) { +- pdev = hdmi_dev->dev; +- pci_set_drvdata(pdev, NULL); +- mrst_hdmi_i2c_exit(pdev); +- iounmap(hdmi_dev->regs); +- kfree(hdmi_dev); +- pci_dev_put(pdev); +- } +-} +- +-/* save HDMI register state */ +-void mrst_hdmi_save(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; +- int i; +- +- /* dpll */ +- hdmi_dev->saveDPLL_CTRL = PSB_RVDC32(DPLL_CTRL); +- hdmi_dev->saveDPLL_DIV_CTRL = PSB_RVDC32(DPLL_DIV_CTRL); +- hdmi_dev->saveDPLL_ADJUST = PSB_RVDC32(DPLL_ADJUST); +- hdmi_dev->saveDPLL_UPDATE = PSB_RVDC32(DPLL_UPDATE); +- hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE); +- +- /* pipe B */ +- dev_priv->savePIPEBCONF = PSB_RVDC32(PIPEBCONF); +- dev_priv->savePIPEBSRC = PSB_RVDC32(PIPEBSRC); +- dev_priv->saveHTOTAL_B = PSB_RVDC32(HTOTAL_B); +- dev_priv->saveHBLANK_B = PSB_RVDC32(HBLANK_B); +- dev_priv->saveHSYNC_B = PSB_RVDC32(HSYNC_B); +- dev_priv->saveVTOTAL_B = PSB_RVDC32(VTOTAL_B); +- dev_priv->saveVBLANK_B = PSB_RVDC32(VBLANK_B); +- dev_priv->saveVSYNC_B = PSB_RVDC32(VSYNC_B); +- +- hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF); +- hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC); +- hdmi_dev->savePCH_HTOTAL_B = PSB_RVDC32(PCH_HTOTAL_B); +- hdmi_dev->savePCH_HBLANK_B = PSB_RVDC32(PCH_HBLANK_B); +- hdmi_dev->savePCH_HSYNC_B = PSB_RVDC32(PCH_HSYNC_B); +- hdmi_dev->savePCH_VTOTAL_B = PSB_RVDC32(PCH_VTOTAL_B); +- hdmi_dev->savePCH_VBLANK_B = PSB_RVDC32(PCH_VBLANK_B); +- hdmi_dev->savePCH_VSYNC_B = PSB_RVDC32(PCH_VSYNC_B); +- +- /* plane */ +- dev_priv->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR); +- dev_priv->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE); +- dev_priv->saveDSPBADDR = PSB_RVDC32(DSPBBASE); +- dev_priv->saveDSPBSURF = PSB_RVDC32(DSPBSURF); +- dev_priv->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF); +- dev_priv->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF); +- +- /* cursor B */ +- dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR); +- dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE); +- dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS); +- +- /* save palette */ +- for (i = 0; i < 256; i++) +- dev_priv->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2)); +-} +- +-/* restore HDMI register state */ +-void mrst_hdmi_restore(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; +- int i; +- +- /* dpll */ +- PSB_WVDC32(hdmi_dev->saveDPLL_CTRL, DPLL_CTRL); +- PSB_WVDC32(hdmi_dev->saveDPLL_DIV_CTRL, DPLL_DIV_CTRL); +- PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST); +- PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE); +- PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE); +- DRM_UDELAY(150); +- +- /* pipe */ +- PSB_WVDC32(dev_priv->savePIPEBSRC, PIPEBSRC); +- PSB_WVDC32(dev_priv->saveHTOTAL_B, HTOTAL_B); +- PSB_WVDC32(dev_priv->saveHBLANK_B, HBLANK_B); +- PSB_WVDC32(dev_priv->saveHSYNC_B, HSYNC_B); +- PSB_WVDC32(dev_priv->saveVTOTAL_B, VTOTAL_B); +- PSB_WVDC32(dev_priv->saveVBLANK_B, VBLANK_B); +- PSB_WVDC32(dev_priv->saveVSYNC_B, VSYNC_B); +- +- PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC); +- PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B); +- PSB_WVDC32(hdmi_dev->savePCH_HBLANK_B, PCH_HBLANK_B); +- PSB_WVDC32(hdmi_dev->savePCH_HSYNC_B, PCH_HSYNC_B); +- PSB_WVDC32(hdmi_dev->savePCH_VTOTAL_B, PCH_VTOTAL_B); +- PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B); +- PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B, PCH_VSYNC_B); +- +- PSB_WVDC32(dev_priv->savePIPEBCONF, PIPEBCONF); +- PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF); +- +- /* plane */ +- PSB_WVDC32(dev_priv->saveDSPBLINOFF, DSPBLINOFF); +- PSB_WVDC32(dev_priv->saveDSPBSTRIDE, DSPBSTRIDE); +- PSB_WVDC32(dev_priv->saveDSPBTILEOFF, DSPBTILEOFF); +- PSB_WVDC32(dev_priv->saveDSPBCNTR, DSPBCNTR); +- PSB_WVDC32(dev_priv->saveDSPBSURF, DSPBSURF); +- +- /* cursor B */ +- PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR); +- PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS); +- PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE); +- +- /* restore palette */ +- for (i = 0; i < 256; i++) +- PSB_WVDC32(dev_priv->save_palette_b[i], PALETTE_B + (i << 2)); +-} +diff --git a/drivers/staging/gma500/mrst_hdmi_i2c.c b/drivers/staging/gma500/mrst_hdmi_i2c.c +deleted file mode 100644 +index 36e7edc..0000000 +--- a/drivers/staging/gma500/mrst_hdmi_i2c.c ++++ /dev/null +@@ -1,328 +0,0 @@ +-/* +- * Copyright © 2010 Intel Corporation +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Li Peng +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include "psb_drv.h" +- +-#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg)) +-#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg)) +- +-#define HDMI_HCR 0x1000 +-#define HCR_DETECT_HDP (1 << 6) +-#define HCR_ENABLE_HDCP (1 << 5) +-#define HCR_ENABLE_AUDIO (1 << 2) +-#define HCR_ENABLE_PIXEL (1 << 1) +-#define HCR_ENABLE_TMDS (1 << 0) +-#define HDMI_HICR 0x1004 +-#define HDMI_INTR_I2C_ERROR (1 << 4) +-#define HDMI_INTR_I2C_FULL (1 << 3) +-#define HDMI_INTR_I2C_DONE (1 << 2) +-#define HDMI_INTR_HPD (1 << 0) +-#define HDMI_HSR 0x1008 +-#define HDMI_HISR 0x100C +-#define HDMI_HI2CRDB0 0x1200 +-#define HDMI_HI2CHCR 0x1240 +-#define HI2C_HDCP_WRITE (0 << 2) +-#define HI2C_HDCP_RI_READ (1 << 2) +-#define HI2C_HDCP_READ (2 << 2) +-#define HI2C_EDID_READ (3 << 2) +-#define HI2C_READ_CONTINUE (1 << 1) +-#define HI2C_ENABLE_TRANSACTION (1 << 0) +- +-#define HDMI_ICRH 0x1100 +-#define HDMI_HI2CTDR0 0x1244 +-#define HDMI_HI2CTDR1 0x1248 +- +-#define I2C_STAT_INIT 0 +-#define I2C_READ_DONE 1 +-#define I2C_TRANSACTION_DONE 2 +- +-struct hdmi_i2c_dev { +- struct i2c_adapter *adap; +- struct mutex i2c_lock; +- struct completion complete; +- int status; +- struct i2c_msg *msg; +- int buf_offset; +-}; +- +-static void hdmi_i2c_irq_enable(struct mrst_hdmi_dev *hdmi_dev) +-{ +- u32 temp; +- +- temp = HDMI_READ(HDMI_HICR); +- temp |= (HDMI_INTR_I2C_ERROR | HDMI_INTR_I2C_FULL | HDMI_INTR_I2C_DONE); +- HDMI_WRITE(HDMI_HICR, temp); +- HDMI_READ(HDMI_HICR); +-} +- +-static void hdmi_i2c_irq_disable(struct mrst_hdmi_dev *hdmi_dev) +-{ +- HDMI_WRITE(HDMI_HICR, 0x0); +- HDMI_READ(HDMI_HICR); +-} +- +-static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg) +-{ +- struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap); +- struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; +- u32 temp; +- +- i2c_dev->status = I2C_STAT_INIT; +- i2c_dev->msg = pmsg; +- i2c_dev->buf_offset = 0; +- INIT_COMPLETION(i2c_dev->complete); +- +- /* Enable I2C transaction */ +- temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION; +- HDMI_WRITE(HDMI_HI2CHCR, temp); +- HDMI_READ(HDMI_HI2CHCR); +- +- while (i2c_dev->status != I2C_TRANSACTION_DONE) +- wait_for_completion_interruptible_timeout(&i2c_dev->complete, +- 10 * HZ); +- +- return 0; +-} +- +-static int xfer_write(struct i2c_adapter *adap, struct i2c_msg *pmsg) +-{ +- /* +- * XXX: i2c write seems isn't useful for EDID probe, don't do anything +- */ +- return 0; +-} +- +-static int mrst_hdmi_i2c_access(struct i2c_adapter *adap, +- struct i2c_msg *pmsg, +- int num) +-{ +- struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap); +- struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; +- int i, err = 0; +- +- mutex_lock(&i2c_dev->i2c_lock); +- +- /* Enable i2c unit */ +- HDMI_WRITE(HDMI_ICRH, 0x00008760); +- +- /* Enable irq */ +- hdmi_i2c_irq_enable(hdmi_dev); +- for (i = 0; i < num; i++) { +- if (pmsg->len && pmsg->buf) { +- if (pmsg->flags & I2C_M_RD) +- err = xfer_read(adap, pmsg); +- else +- err = xfer_write(adap, pmsg); +- } +- pmsg++; /* next message */ +- } +- +- /* Disable irq */ +- hdmi_i2c_irq_disable(hdmi_dev); +- +- mutex_unlock(&i2c_dev->i2c_lock); +- +- return i; +-} +- +-static u32 mrst_hdmi_i2c_func(struct i2c_adapter *adapter) +-{ +- return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; +-} +- +-static const struct i2c_algorithm mrst_hdmi_i2c_algorithm = { +- .master_xfer = mrst_hdmi_i2c_access, +- .functionality = mrst_hdmi_i2c_func, +-}; +- +-static struct i2c_adapter mrst_hdmi_i2c_adapter = { +- .name = "mrst_hdmi_i2c", +- .nr = 3, +- .owner = THIS_MODULE, +- .class = I2C_CLASS_DDC, +- .algo = &mrst_hdmi_i2c_algorithm, +-}; +- +-static void hdmi_i2c_read(struct mrst_hdmi_dev *hdmi_dev) +-{ +- struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; +- struct i2c_msg *msg = i2c_dev->msg; +- u8 *buf = msg->buf; +- u32 temp; +- int i, offset; +- +- offset = i2c_dev->buf_offset; +- for (i = 0; i < 0x10; i++) { +- temp = HDMI_READ(HDMI_HI2CRDB0 + (i * 4)); +- memcpy(buf + (offset + i * 4), &temp, 4); +- } +- i2c_dev->buf_offset += (0x10 * 4); +- +- /* clearing read buffer full intr */ +- temp = HDMI_READ(HDMI_HISR); +- HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_FULL); +- HDMI_READ(HDMI_HISR); +- +- /* continue read transaction */ +- temp = HDMI_READ(HDMI_HI2CHCR); +- HDMI_WRITE(HDMI_HI2CHCR, temp | HI2C_READ_CONTINUE); +- HDMI_READ(HDMI_HI2CHCR); +- +- i2c_dev->status = I2C_READ_DONE; +- return; +-} +- +-static void hdmi_i2c_transaction_done(struct mrst_hdmi_dev *hdmi_dev) +-{ +- struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; +- u32 temp; +- +- /* clear transaction done intr */ +- temp = HDMI_READ(HDMI_HISR); +- HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_DONE); +- HDMI_READ(HDMI_HISR); +- +- +- temp = HDMI_READ(HDMI_HI2CHCR); +- HDMI_WRITE(HDMI_HI2CHCR, temp & ~HI2C_ENABLE_TRANSACTION); +- HDMI_READ(HDMI_HI2CHCR); +- +- i2c_dev->status = I2C_TRANSACTION_DONE; +- return; +-} +- +-static irqreturn_t mrst_hdmi_i2c_handler(int this_irq, void *dev) +-{ +- struct mrst_hdmi_dev *hdmi_dev = dev; +- struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; +- u32 stat; +- +- stat = HDMI_READ(HDMI_HISR); +- +- if (stat & HDMI_INTR_HPD) { +- HDMI_WRITE(HDMI_HISR, stat | HDMI_INTR_HPD); +- HDMI_READ(HDMI_HISR); +- } +- +- if (stat & HDMI_INTR_I2C_FULL) +- hdmi_i2c_read(hdmi_dev); +- +- if (stat & HDMI_INTR_I2C_DONE) +- hdmi_i2c_transaction_done(hdmi_dev); +- +- complete(&i2c_dev->complete); +- +- return IRQ_HANDLED; +-} +- +-/* +- * choose alternate function 2 of GPIO pin 52, 53, +- * which is used by HDMI I2C logic +- */ +-static void mrst_hdmi_i2c_gpio_fix(void) +-{ +- void *base; +- unsigned int gpio_base = 0xff12c000; +- int gpio_len = 0x1000; +- u32 temp; +- +- base = ioremap((resource_size_t)gpio_base, gpio_len); +- if (base == NULL) { +- DRM_ERROR("gpio ioremap fail\n"); +- return; +- } +- +- temp = readl(base + 0x44); +- DRM_DEBUG_DRIVER("old gpio val %x\n", temp); +- writel((temp | 0x00000a00), (base + 0x44)); +- temp = readl(base + 0x44); +- DRM_DEBUG_DRIVER("new gpio val %x\n", temp); +- +- iounmap(base); +-} +- +-int mrst_hdmi_i2c_init(struct pci_dev *dev) +-{ +- struct mrst_hdmi_dev *hdmi_dev; +- struct hdmi_i2c_dev *i2c_dev; +- int ret; +- +- hdmi_dev = pci_get_drvdata(dev); +- +- i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL); +- if (i2c_dev == NULL) { +- DRM_ERROR("Can't allocate interface\n"); +- ret = -ENOMEM; +- goto exit; +- } +- +- i2c_dev->adap = &mrst_hdmi_i2c_adapter; +- i2c_dev->status = I2C_STAT_INIT; +- init_completion(&i2c_dev->complete); +- mutex_init(&i2c_dev->i2c_lock); +- i2c_set_adapdata(&mrst_hdmi_i2c_adapter, hdmi_dev); +- hdmi_dev->i2c_dev = i2c_dev; +- +- /* Enable HDMI I2C function on gpio */ +- mrst_hdmi_i2c_gpio_fix(); +- +- /* request irq */ +- ret = request_irq(dev->irq, mrst_hdmi_i2c_handler, IRQF_SHARED, +- mrst_hdmi_i2c_adapter.name, hdmi_dev); +- if (ret) { +- DRM_ERROR("Failed to request IRQ for I2C controller\n"); +- goto err; +- } +- +- /* Adapter registration */ +- ret = i2c_add_numbered_adapter(&mrst_hdmi_i2c_adapter); +- return ret; +- +-err: +- kfree(i2c_dev); +-exit: +- return ret; +-} +- +-void mrst_hdmi_i2c_exit(struct pci_dev *dev) +-{ +- struct mrst_hdmi_dev *hdmi_dev; +- struct hdmi_i2c_dev *i2c_dev; +- +- hdmi_dev = pci_get_drvdata(dev); +- if (i2c_del_adapter(&mrst_hdmi_i2c_adapter)) +- DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n"); +- +- i2c_dev = hdmi_dev->i2c_dev; +- kfree(i2c_dev); +- free_irq(dev->irq, hdmi_dev); +-} +diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c +deleted file mode 100644 +index e7999a2..0000000 +--- a/drivers/staging/gma500/mrst_lvds.c ++++ /dev/null +@@ -1,407 +0,0 @@ +-/* +- * Copyright © 2006-2009 Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Eric Anholt +- * Dave Airlie +- * Jesse Barnes +- */ +- +-#include +-#include +-#include +- +-#include "intel_bios.h" +-#include "psb_drv.h" +-#include "psb_intel_drv.h" +-#include "psb_intel_reg.h" +-#include "power.h" +-#include +- +-/* The max/min PWM frequency in BPCR[31:17] - */ +-/* The smallest number is 1 (not 0) that can fit in the +- * 15-bit field of the and then*/ +-/* shifts to the left by one bit to get the actual 16-bit +- * value that the 15-bits correspond to.*/ +-#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF +-#define BRIGHTNESS_MAX_LEVEL 100 +- +-/** +- * Sets the power state for the panel. +- */ +-static void mrst_lvds_set_power(struct drm_device *dev, +- struct psb_intel_output *output, bool on) +-{ +- u32 pp_status; +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (!gma_power_begin(dev, true)) +- return; +- +- if (on) { +- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | +- POWER_TARGET_ON); +- do { +- pp_status = REG_READ(PP_STATUS); +- } while ((pp_status & (PP_ON | PP_READY)) == PP_READY); +- dev_priv->is_lvds_on = true; +- if (dev_priv->ops->lvds_bl_power) +- dev_priv->ops->lvds_bl_power(dev, true); +- } else { +- if (dev_priv->ops->lvds_bl_power) +- dev_priv->ops->lvds_bl_power(dev, false); +- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & +- ~POWER_TARGET_ON); +- do { +- pp_status = REG_READ(PP_STATUS); +- } while (pp_status & PP_ON); +- dev_priv->is_lvds_on = false; +- pm_request_idle(&dev->pdev->dev); +- } +- gma_power_end(dev); +-} +- +-static void mrst_lvds_dpms(struct drm_encoder *encoder, int mode) +-{ +- struct drm_device *dev = encoder->dev; +- struct psb_intel_output *output = enc_to_psb_intel_output(encoder); +- +- if (mode == DRM_MODE_DPMS_ON) +- mrst_lvds_set_power(dev, output, true); +- else +- mrst_lvds_set_power(dev, output, false); +- +- /* XXX: We never power down the LVDS pairs. */ +-} +- +-static void mrst_lvds_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- struct psb_intel_mode_device *mode_dev = +- enc_to_psb_intel_output(encoder)->mode_dev; +- struct drm_device *dev = encoder->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 lvds_port; +- uint64_t v = DRM_MODE_SCALE_FULLSCREEN; +- +- if (!gma_power_begin(dev, true)) +- return; +- +- /* +- * The LVDS pin pair will already have been turned on in the +- * psb_intel_crtc_mode_set since it has a large impact on the DPLL +- * settings. +- */ +- lvds_port = (REG_READ(LVDS) & +- (~LVDS_PIPEB_SELECT)) | +- LVDS_PORT_EN | +- LVDS_BORDER_EN; +- +- /* If the firmware says dither on Moorestown, or the BIOS does +- on Oaktrail then enable dithering */ +- if (mode_dev->panel_wants_dither || dev_priv->lvds_dither) +- lvds_port |= MRST_PANEL_8TO6_DITHER_ENABLE; +- +- REG_WRITE(LVDS, lvds_port); +- +- drm_connector_property_get_value( +- &enc_to_psb_intel_output(encoder)->base, +- dev->mode_config.scaling_mode_property, +- &v); +- +- if (v == DRM_MODE_SCALE_NO_SCALE) +- REG_WRITE(PFIT_CONTROL, 0); +- else if (v == DRM_MODE_SCALE_ASPECT) { +- if ((mode->vdisplay != adjusted_mode->crtc_vdisplay) || +- (mode->hdisplay != adjusted_mode->crtc_hdisplay)) { +- if ((adjusted_mode->crtc_hdisplay * mode->vdisplay) == +- (mode->hdisplay * adjusted_mode->crtc_vdisplay)) +- REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); +- else if ((adjusted_mode->crtc_hdisplay * +- mode->vdisplay) > (mode->hdisplay * +- adjusted_mode->crtc_vdisplay)) +- REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | +- PFIT_SCALING_MODE_PILLARBOX); +- else +- REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | +- PFIT_SCALING_MODE_LETTERBOX); +- } else +- REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); +- } else /*(v == DRM_MODE_SCALE_FULLSCREEN)*/ +- REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); +- +- gma_power_end(dev); +-} +- +-static void mrst_lvds_prepare(struct drm_encoder *encoder) +-{ +- struct drm_device *dev = encoder->dev; +- struct psb_intel_output *output = enc_to_psb_intel_output(encoder); +- struct psb_intel_mode_device *mode_dev = output->mode_dev; +- +- if (!gma_power_begin(dev, true)) +- return; +- +- mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); +- mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & +- BACKLIGHT_DUTY_CYCLE_MASK); +- mrst_lvds_set_power(dev, output, false); +- gma_power_end(dev); +-} +- +-static u32 mrst_lvds_get_max_backlight(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 ret; +- +- if (gma_power_begin(dev, false)) { +- ret = ((REG_READ(BLC_PWM_CTL) & +- BACKLIGHT_MODULATION_FREQ_MASK) >> +- BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; +- +- gma_power_end(dev); +- } else +- ret = ((dev_priv->saveBLC_PWM_CTL & +- BACKLIGHT_MODULATION_FREQ_MASK) >> +- BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; +- +- return ret; +-} +- +-static void mrst_lvds_commit(struct drm_encoder *encoder) +-{ +- struct drm_device *dev = encoder->dev; +- struct psb_intel_output *output = enc_to_psb_intel_output(encoder); +- struct psb_intel_mode_device *mode_dev = output->mode_dev; +- +- if (mode_dev->backlight_duty_cycle == 0) +- mode_dev->backlight_duty_cycle = +- mrst_lvds_get_max_backlight(dev); +- mrst_lvds_set_power(dev, output, true); +-} +- +-static const struct drm_encoder_helper_funcs mrst_lvds_helper_funcs = { +- .dpms = mrst_lvds_dpms, +- .mode_fixup = psb_intel_lvds_mode_fixup, +- .prepare = mrst_lvds_prepare, +- .mode_set = mrst_lvds_mode_set, +- .commit = mrst_lvds_commit, +-}; +- +-static struct drm_display_mode lvds_configuration_modes[] = { +- /* hard coded fixed mode for TPO LTPS LPJ040K001A */ +- { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 33264, 800, 836, +- 846, 1056, 0, 480, 489, 491, 525, 0, 0) }, +- /* hard coded fixed mode for LVDS 800x480 */ +- { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 30994, 800, 801, +- 802, 1024, 0, 480, 481, 482, 525, 0, 0) }, +- /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ +- { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1072, +- 1104, 1184, 0, 600, 603, 604, 608, 0, 0) }, +- /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ +- { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1104, +- 1136, 1184, 0, 600, 603, 604, 608, 0, 0) }, +- /* hard coded fixed mode for Sharp wsvga LVDS 1024x600 */ +- { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 48885, 1024, 1124, +- 1204, 1312, 0, 600, 607, 610, 621, 0, 0) }, +- /* hard coded fixed mode for LVDS 1024x768 */ +- { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, +- 1184, 1344, 0, 768, 771, 777, 806, 0, 0) }, +- /* hard coded fixed mode for LVDS 1366x768 */ +- { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 77500, 1366, 1430, +- 1558, 1664, 0, 768, 769, 770, 776, 0, 0) }, +-}; +- +-/* Returns the panel fixed mode from configuration. */ +- +-static struct drm_display_mode * +-mrst_lvds_get_configuration_mode(struct drm_device *dev) +-{ +- struct drm_display_mode *mode = NULL; +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; +- +- if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/ +- mode = kzalloc(sizeof(*mode), GFP_KERNEL); +- if (!mode) +- return NULL; +- +- mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; +- mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; +- mode->hsync_start = mode->hdisplay + \ +- ((ti->hsync_offset_hi << 8) | \ +- ti->hsync_offset_lo); +- mode->hsync_end = mode->hsync_start + \ +- ((ti->hsync_pulse_width_hi << 8) | \ +- ti->hsync_pulse_width_lo); +- mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ +- ti->hblank_lo); +- mode->vsync_start = \ +- mode->vdisplay + ((ti->vsync_offset_hi << 4) | \ +- ti->vsync_offset_lo); +- mode->vsync_end = \ +- mode->vsync_start + ((ti->vsync_pulse_width_hi << 4) | \ +- ti->vsync_pulse_width_lo); +- mode->vtotal = mode->vdisplay + \ +- ((ti->vblank_hi << 8) | ti->vblank_lo); +- mode->clock = ti->pixel_clock * 10; +-#if 0 +- printk(KERN_INFO "hdisplay is %d\n", mode->hdisplay); +- printk(KERN_INFO "vdisplay is %d\n", mode->vdisplay); +- printk(KERN_INFO "HSS is %d\n", mode->hsync_start); +- printk(KERN_INFO "HSE is %d\n", mode->hsync_end); +- printk(KERN_INFO "htotal is %d\n", mode->htotal); +- printk(KERN_INFO "VSS is %d\n", mode->vsync_start); +- printk(KERN_INFO "VSE is %d\n", mode->vsync_end); +- printk(KERN_INFO "vtotal is %d\n", mode->vtotal); +- printk(KERN_INFO "clock is %d\n", mode->clock); +-#endif +- } else +- mode = drm_mode_duplicate(dev, &lvds_configuration_modes[2]); +- +- drm_mode_set_name(mode); +- drm_mode_set_crtcinfo(mode, 0); +- +- return mode; +-} +- +-/** +- * mrst_lvds_init - setup LVDS connectors on this device +- * @dev: drm device +- * +- * Create the connector, register the LVDS DDC bus, and try to figure out what +- * modes we can display on the LVDS panel (if present). +- */ +-void mrst_lvds_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev) +-{ +- struct psb_intel_output *psb_intel_output; +- struct drm_connector *connector; +- struct drm_encoder *encoder; +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *) dev->dev_private; +- struct edid *edid; +- int ret = 0; +- struct i2c_adapter *i2c_adap; +- struct drm_display_mode *scan; /* *modes, *bios_mode; */ +- +- psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); +- if (!psb_intel_output) +- return; +- +- psb_intel_output->mode_dev = mode_dev; +- connector = &psb_intel_output->base; +- encoder = &psb_intel_output->enc; +- dev_priv->is_lvds_on = true; +- drm_connector_init(dev, &psb_intel_output->base, +- &psb_intel_lvds_connector_funcs, +- DRM_MODE_CONNECTOR_LVDS); +- +- drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs, +- DRM_MODE_ENCODER_LVDS); +- +- drm_mode_connector_attach_encoder(&psb_intel_output->base, +- &psb_intel_output->enc); +- psb_intel_output->type = INTEL_OUTPUT_LVDS; +- +- drm_encoder_helper_add(encoder, &mrst_lvds_helper_funcs); +- drm_connector_helper_add(connector, +- &psb_intel_lvds_connector_helper_funcs); +- connector->display_info.subpixel_order = SubPixelHorizontalRGB; +- connector->interlace_allowed = false; +- connector->doublescan_allowed = false; +- +- drm_connector_attach_property(connector, +- dev->mode_config.scaling_mode_property, +- DRM_MODE_SCALE_FULLSCREEN); +- drm_connector_attach_property(connector, +- dev_priv->backlight_property, +- BRIGHTNESS_MAX_LEVEL); +- +- mode_dev->panel_wants_dither = false; +- if (dev_priv->vbt_data.size != 0x00) +- mode_dev->panel_wants_dither = (dev_priv->gct_data. +- Panel_Port_Control & MRST_PANEL_8TO6_DITHER_ENABLE); +- +- /* +- * LVDS discovery: +- * 1) check for EDID on DDC +- * 2) check for VBT data +- * 3) check to see if LVDS is already on +- * if none of the above, no panel +- * 4) make sure lid is open +- * if closed, act like it's not there for now +- */ +- +- i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus); +- +- if (i2c_adap == NULL) +- dev_err(dev->dev, "No ddc adapter available!\n"); +- /* +- * Attempt to get the fixed panel mode from DDC. Assume that the +- * preferred mode is the right one. +- */ +- if (i2c_adap) { +- edid = drm_get_edid(connector, i2c_adap); +- if (edid) { +- drm_mode_connector_update_edid_property(connector, +- edid); +- ret = drm_add_edid_modes(connector, edid); +- kfree(edid); +- } +- +- list_for_each_entry(scan, &connector->probed_modes, head) { +- if (scan->type & DRM_MODE_TYPE_PREFERRED) { +- mode_dev->panel_fixed_mode = +- drm_mode_duplicate(dev, scan); +- goto out; /* FIXME: check for quirks */ +- } +- } +- } +- /* +- * If we didn't get EDID, try geting panel timing +- * from configuration data +- */ +- mode_dev->panel_fixed_mode = mrst_lvds_get_configuration_mode(dev); +- +- if (mode_dev->panel_fixed_mode) { +- mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; +- goto out; /* FIXME: check for quirks */ +- } +- +- /* If we still don't have a mode after all that, give up. */ +- if (!mode_dev->panel_fixed_mode) { +- dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n"); +- goto failed_find; +- } +- +-out: +- drm_sysfs_connector_add(connector); +- return; +- +-failed_find: +- dev_dbg(dev->dev, "No LVDS modes found, disabling.\n"); +- if (psb_intel_output->ddc_bus) +- psb_intel_i2c_destroy(psb_intel_output->ddc_bus); +- +-/* failed_ddc: */ +- +- drm_encoder_cleanup(encoder); +- drm_connector_cleanup(connector); +- kfree(connector); +-} +- +diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c +deleted file mode 100644 +index 436fe97..0000000 +--- a/drivers/staging/gma500/power.c ++++ /dev/null +@@ -1,318 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2009-2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Benjamin Defnet +- * Rajesh Poornachandran +- * Massively reworked +- * Alan Cox +- */ +- +-#include "power.h" +-#include "psb_drv.h" +-#include "psb_reg.h" +-#include "psb_intel_reg.h" +-#include +-#include +- +-static struct mutex power_mutex; /* Serialize power ops */ +-static spinlock_t power_ctrl_lock; /* Serialize power claim */ +- +-/** +- * gma_power_init - initialise power manager +- * @dev: our device +- * +- * Set up for power management tracking of our hardware. +- */ +-void gma_power_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- /* FIXME: Move APM/OSPM base into relevant device code */ +- dev_priv->apm_base = dev_priv->apm_reg & 0xffff; +- dev_priv->ospm_base &= 0xffff; +- +- dev_priv->display_power = true; /* We start active */ +- dev_priv->display_count = 0; /* Currently no users */ +- dev_priv->suspended = false; /* And not suspended */ +- spin_lock_init(&power_ctrl_lock); +- mutex_init(&power_mutex); +- +- dev_priv->ops->init_pm(dev); +-} +- +-/** +- * gma_power_uninit - end power manager +- * @dev: device to end for +- * +- * Undo the effects of gma_power_init +- */ +-void gma_power_uninit(struct drm_device *dev) +-{ +- pm_runtime_disable(&dev->pdev->dev); +- pm_runtime_set_suspended(&dev->pdev->dev); +-} +- +-/** +- * gma_suspend_display - suspend the display logic +- * @dev: our DRM device +- * +- * Suspend the display logic of the graphics interface +- */ +-static void gma_suspend_display(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (!dev_priv->display_power) +- return; +- dev_priv->ops->save_regs(dev); +- dev_priv->ops->power_down(dev); +- dev_priv->display_power = false; +-} +- +-/** +- * gma_resume_display - resume display side logic +- * +- * Resume the display hardware restoring state and enabling +- * as necessary. +- */ +-static void gma_resume_display(struct pci_dev *pdev) +-{ +- struct drm_device *dev = pci_get_drvdata(pdev); +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (dev_priv->display_power) +- return; +- +- /* turn on the display power island */ +- dev_priv->ops->power_up(dev); +- dev_priv->suspended = false; +- dev_priv->display_power = true; +- +- PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); +- pci_write_config_word(pdev, PSB_GMCH_CTRL, +- dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); +- dev_priv->ops->restore_regs(dev); +-} +- +-/** +- * gma_suspend_pci - suspend PCI side +- * @pdev: PCI device +- * +- * Perform the suspend processing on our PCI device state +- */ +-static void gma_suspend_pci(struct pci_dev *pdev) +-{ +- struct drm_device *dev = pci_get_drvdata(pdev); +- struct drm_psb_private *dev_priv = dev->dev_private; +- int bsm, vbt; +- +- if (dev_priv->suspended) +- return; +- +- pci_save_state(pdev); +- pci_read_config_dword(pdev, 0x5C, &bsm); +- dev_priv->saveBSM = bsm; +- pci_read_config_dword(pdev, 0xFC, &vbt); +- dev_priv->saveVBT = vbt; +- pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr); +- pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data); +- +- pci_disable_device(pdev); +- pci_set_power_state(pdev, PCI_D3hot); +- +- dev_priv->suspended = true; +-} +- +-/** +- * gma_resume_pci - resume helper +- * @dev: our PCI device +- * +- * Perform the resume processing on our PCI device state - rewrite +- * register state and re-enable the PCI device +- */ +-static bool gma_resume_pci(struct pci_dev *pdev) +-{ +- struct drm_device *dev = pci_get_drvdata(pdev); +- struct drm_psb_private *dev_priv = dev->dev_private; +- int ret; +- +- if (!dev_priv->suspended) +- return true; +- +- pci_set_power_state(pdev, PCI_D0); +- pci_restore_state(pdev); +- pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM); +- pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT); +- /* restoring MSI address and data in PCIx space */ +- pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr); +- pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data); +- ret = pci_enable_device(pdev); +- +- if (ret != 0) +- dev_err(&pdev->dev, "pci_enable failed: %d\n", ret); +- else +- dev_priv->suspended = false; +- return !dev_priv->suspended; +-} +- +-/** +- * gma_power_suspend - bus callback for suspend +- * @pdev: our PCI device +- * @state: suspend type +- * +- * Called back by the PCI layer during a suspend of the system. We +- * perform the necessary shut down steps and save enough state that +- * we can undo this when resume is called. +- */ +-int gma_power_suspend(struct device *_dev) +-{ +- struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev); +- struct drm_device *dev = pci_get_drvdata(pdev); +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- mutex_lock(&power_mutex); +- if (!dev_priv->suspended) { +- if (dev_priv->display_count) { +- mutex_unlock(&power_mutex); +- return -EBUSY; +- } +- psb_irq_uninstall(dev); +- gma_suspend_display(dev); +- gma_suspend_pci(pdev); +- } +- mutex_unlock(&power_mutex); +- return 0; +-} +- +-/** +- * gma_power_resume - resume power +- * @pdev: PCI device +- * +- * Resume the PCI side of the graphics and then the displays +- */ +-int gma_power_resume(struct device *_dev) +-{ +- struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev); +- struct drm_device *dev = pci_get_drvdata(pdev); +- +- mutex_lock(&power_mutex); +- gma_resume_pci(pdev); +- gma_resume_display(pdev); +- psb_irq_preinstall(dev); +- psb_irq_postinstall(dev); +- mutex_unlock(&power_mutex); +- return 0; +-} +- +-/** +- * gma_power_is_on - returne true if power is on +- * @dev: our DRM device +- * +- * Returns true if the display island power is on at this moment +- */ +-bool gma_power_is_on(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- return dev_priv->display_power; +-} +- +-/** +- * gma_power_begin - begin requiring power +- * @dev: our DRM device +- * @force_on: true to force power on +- * +- * Begin an action that requires the display power island is enabled. +- * We refcount the islands. +- */ +-bool gma_power_begin(struct drm_device *dev, bool force_on) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- int ret; +- unsigned long flags; +- +- spin_lock_irqsave(&power_ctrl_lock, flags); +- /* Power already on ? */ +- if (dev_priv->display_power) { +- dev_priv->display_count++; +- pm_runtime_get(&dev->pdev->dev); +- spin_unlock_irqrestore(&power_ctrl_lock, flags); +- return true; +- } +- if (force_on == false) +- goto out_false; +- +- /* Ok power up needed */ +- ret = gma_resume_pci(dev->pdev); +- if (ret == 0) { +- /* FIXME: we want to defer this for Medfield/Oaktrail */ +- gma_resume_display(dev); +- psb_irq_preinstall(dev); +- psb_irq_postinstall(dev); +- pm_runtime_get(&dev->pdev->dev); +- dev_priv->display_count++; +- spin_unlock_irqrestore(&power_ctrl_lock, flags); +- return true; +- } +-out_false: +- spin_unlock_irqrestore(&power_ctrl_lock, flags); +- return false; +-} +- +-/** +- * gma_power_end - end use of power +- * @dev: Our DRM device +- * +- * Indicate that one of our gma_power_begin() requested periods when +- * the diplay island power is needed has completed. +- */ +-void gma_power_end(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- unsigned long flags; +- spin_lock_irqsave(&power_ctrl_lock, flags); +- dev_priv->display_count--; +- WARN_ON(dev_priv->display_count < 0); +- spin_unlock_irqrestore(&power_ctrl_lock, flags); +- pm_runtime_put(&dev->pdev->dev); +-} +- +-int psb_runtime_suspend(struct device *dev) +-{ +- return gma_power_suspend(dev); +-} +- +-int psb_runtime_resume(struct device *dev) +-{ +- return gma_power_resume(dev);; +-} +- +-int psb_runtime_idle(struct device *dev) +-{ +- struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev)); +- struct drm_psb_private *dev_priv = drmdev->dev_private; +- if (dev_priv->display_count) +- return 0; +- else +- return 1; +-} +diff --git a/drivers/staging/gma500/power.h b/drivers/staging/gma500/power.h +deleted file mode 100644 +index 1969d2e..0000000 +--- a/drivers/staging/gma500/power.h ++++ /dev/null +@@ -1,67 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2009-2011, Intel Corporation. +- * All Rights Reserved. +- +- * 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 (including the next +- * paragraph) 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. +- * +- * Authors: +- * Benjamin Defnet +- * Rajesh Poornachandran +- * Massively reworked +- * Alan Cox +- */ +-#ifndef _PSB_POWERMGMT_H_ +-#define _PSB_POWERMGMT_H_ +- +-#include +-#include +- +-void gma_power_init(struct drm_device *dev); +-void gma_power_uninit(struct drm_device *dev); +- +-/* +- * The kernel bus power management will call these functions +- */ +-int gma_power_suspend(struct device *dev); +-int gma_power_resume(struct device *dev); +- +-/* +- * These are the functions the driver should use to wrap all hw access +- * (i.e. register reads and writes) +- */ +-bool gma_power_begin(struct drm_device *dev, bool force); +-void gma_power_end(struct drm_device *dev); +- +-/* +- * Use this function to do an instantaneous check for if the hw is on. +- * Only use this in cases where you know the mutex is already held such +- * as in irq install/uninstall and you need to +- * prevent a deadlock situation. Otherwise use gma_power_begin(). +- */ +-bool gma_power_is_on(struct drm_device *dev); +- +-/* +- * GFX-Runtime PM callbacks +- */ +-int psb_runtime_suspend(struct device *dev); +-int psb_runtime_resume(struct device *dev); +-int psb_runtime_idle(struct device *dev); +- +-#endif /*_PSB_POWERMGMT_H_*/ +diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c +deleted file mode 100644 +index b97aa78..0000000 +--- a/drivers/staging/gma500/psb_device.c ++++ /dev/null +@@ -1,321 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-#include +-#include +-#include +-#include "psb_drm.h" +-#include "psb_drv.h" +-#include "psb_reg.h" +-#include "psb_intel_reg.h" +-#include "intel_bios.h" +- +- +-static int psb_output_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- psb_intel_lvds_init(dev, &dev_priv->mode_dev); +- psb_intel_sdvo_init(dev, SDVOB); +- return 0; +-} +- +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- +-/* +- * Poulsbo Backlight Interfaces +- */ +- +-#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ +-#define BLC_PWM_FREQ_CALC_CONSTANT 32 +-#define MHz 1000000 +- +-#define PSB_BLC_PWM_PRECISION_FACTOR 10 +-#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE +-#define PSB_BLC_MIN_PWM_REG_FREQ 0x2 +- +-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) +-#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) +- +-static int psb_brightness; +-static struct backlight_device *psb_backlight_device; +- +-static int psb_get_brightness(struct backlight_device *bd) +-{ +- /* return locally cached var instead of HW read (due to DPST etc.) */ +- /* FIXME: ideally return actual value in case firmware fiddled with +- it */ +- return psb_brightness; +-} +- +- +-static int psb_backlight_setup(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- unsigned long core_clock; +- /* u32 bl_max_freq; */ +- /* unsigned long value; */ +- u16 bl_max_freq; +- uint32_t value; +- uint32_t blc_pwm_precision_factor; +- +- /* get bl_max_freq and pol from dev_priv*/ +- if (!dev_priv->lvds_bl) { +- dev_err(dev->dev, "Has no valid LVDS backlight info\n"); +- return -ENOENT; +- } +- bl_max_freq = dev_priv->lvds_bl->freq; +- blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; +- +- core_clock = dev_priv->core_freq; +- +- value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; +- value *= blc_pwm_precision_factor; +- value /= bl_max_freq; +- value /= blc_pwm_precision_factor; +- +- if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || +- value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) +- return -ERANGE; +- else { +- value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; +- REG_WRITE(BLC_PWM_CTL, +- (value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value)); +- } +- return 0; +-} +- +-static int psb_set_brightness(struct backlight_device *bd) +-{ +- struct drm_device *dev = bl_get_data(psb_backlight_device); +- int level = bd->props.brightness; +- +- /* Percentage 1-100% being valid */ +- if (level < 1) +- level = 1; +- +- psb_intel_lvds_set_brightness(dev, level); +- psb_brightness = level; +- return 0; +-} +- +-static const struct backlight_ops psb_ops = { +- .get_brightness = psb_get_brightness, +- .update_status = psb_set_brightness, +-}; +- +-static int psb_backlight_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- int ret; +- struct backlight_properties props; +- +- memset(&props, 0, sizeof(struct backlight_properties)); +- props.max_brightness = 100; +- props.type = BACKLIGHT_PLATFORM; +- +- psb_backlight_device = backlight_device_register("psb-bl", +- NULL, (void *)dev, &psb_ops, &props); +- if (IS_ERR(psb_backlight_device)) +- return PTR_ERR(psb_backlight_device); +- +- ret = psb_backlight_setup(dev); +- if (ret < 0) { +- backlight_device_unregister(psb_backlight_device); +- psb_backlight_device = NULL; +- return ret; +- } +- psb_backlight_device->props.brightness = 100; +- psb_backlight_device->props.max_brightness = 100; +- backlight_update_status(psb_backlight_device); +- dev_priv->backlight_device = psb_backlight_device; +- return 0; +-} +- +-#endif +- +-/* +- * Provide the Poulsbo specific chip logic and low level methods +- * for power management +- */ +- +-static void psb_init_pm(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL); +- gating &= ~3; /* Disable 2D clock gating */ +- gating |= 1; +- PSB_WSGX32(gating, PSB_CR_CLKGATECTL); +- PSB_RSGX32(PSB_CR_CLKGATECTL); +-} +- +-/** +- * psb_save_display_registers - save registers lost on suspend +- * @dev: our DRM device +- * +- * Save the state we need in order to be able to restore the interface +- * upon resume from suspend +- */ +-static int psb_save_display_registers(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct drm_crtc *crtc; +- struct drm_connector *connector; +- +- /* Display arbitration control + watermarks */ +- dev_priv->saveDSPARB = PSB_RVDC32(DSPARB); +- dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1); +- dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2); +- dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3); +- dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4); +- dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5); +- dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6); +- dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); +- +- /* Save crtc and output state */ +- mutex_lock(&dev->mode_config.mutex); +- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { +- if (drm_helper_crtc_in_use(crtc)) +- crtc->funcs->save(crtc); +- } +- +- list_for_each_entry(connector, &dev->mode_config.connector_list, head) +- connector->funcs->save(connector); +- +- mutex_unlock(&dev->mode_config.mutex); +- return 0; +-} +- +-/** +- * psb_restore_display_registers - restore lost register state +- * @dev: our DRM device +- * +- * Restore register state that was lost during suspend and resume. +- */ +-static int psb_restore_display_registers(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct drm_crtc *crtc; +- struct drm_connector *connector; +- +- /* Display arbitration + watermarks */ +- PSB_WVDC32(dev_priv->saveDSPARB, DSPARB); +- PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1); +- PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2); +- PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3); +- PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4); +- PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5); +- PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6); +- PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT); +- +- /*make sure VGA plane is off. it initializes to on after reset!*/ +- PSB_WVDC32(0x80000000, VGACNTRL); +- +- mutex_lock(&dev->mode_config.mutex); +- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) +- if (drm_helper_crtc_in_use(crtc)) +- crtc->funcs->restore(crtc); +- +- list_for_each_entry(connector, &dev->mode_config.connector_list, head) +- connector->funcs->restore(connector); +- +- mutex_unlock(&dev->mode_config.mutex); +- return 0; +-} +- +-static int psb_power_down(struct drm_device *dev) +-{ +- return 0; +-} +- +-static int psb_power_up(struct drm_device *dev) +-{ +- return 0; +-} +- +-static void psb_get_core_freq(struct drm_device *dev) +-{ +- uint32_t clock; +- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/ +- /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/ +- +- pci_write_config_dword(pci_root, 0xD0, 0xD0050300); +- pci_read_config_dword(pci_root, 0xD4, &clock); +- pci_dev_put(pci_root); +- +- switch (clock & 0x07) { +- case 0: +- dev_priv->core_freq = 100; +- break; +- case 1: +- dev_priv->core_freq = 133; +- break; +- case 2: +- dev_priv->core_freq = 150; +- break; +- case 3: +- dev_priv->core_freq = 178; +- break; +- case 4: +- dev_priv->core_freq = 200; +- break; +- case 5: +- case 6: +- case 7: +- dev_priv->core_freq = 266; +- default: +- dev_priv->core_freq = 0; +- } +-} +- +-static int psb_chip_setup(struct drm_device *dev) +-{ +- psb_get_core_freq(dev); +- gma_intel_opregion_init(dev); +- psb_intel_init_bios(dev); +- return 0; +-} +- +-const struct psb_ops psb_chip_ops = { +- .name = "Poulsbo", +- .accel_2d = 1, +- .pipes = 2, +- .crtcs = 2, +- .sgx_offset = PSB_SGX_OFFSET, +- .chip_setup = psb_chip_setup, +- +- .crtc_helper = &psb_intel_helper_funcs, +- .crtc_funcs = &psb_intel_crtc_funcs, +- +- .output_init = psb_output_init, +- +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- .backlight_init = psb_backlight_init, +-#endif +- +- .init_pm = psb_init_pm, +- .save_regs = psb_save_display_registers, +- .restore_regs = psb_restore_display_registers, +- .power_down = psb_power_down, +- .power_up = psb_power_up, +-}; +- +diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h +deleted file mode 100644 +index 0da8468..0000000 +--- a/drivers/staging/gma500/psb_drm.h ++++ /dev/null +@@ -1,219 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2007-2011, Intel Corporation. +- * All Rights Reserved. +- * Copyright (c) 2008, Tungsten Graphics Inc. Cedar Park, TX., USA. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-#ifndef _PSB_DRM_H_ +-#define _PSB_DRM_H_ +- +-#define PSB_NUM_PIPE 3 +- +-#define PSB_GPU_ACCESS_READ (1ULL << 32) +-#define PSB_GPU_ACCESS_WRITE (1ULL << 33) +-#define PSB_GPU_ACCESS_MASK (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE) +- +-#define PSB_BO_FLAG_COMMAND (1ULL << 52) +- +-/* +- * Feedback components: +- */ +- +-struct drm_psb_sizes_arg { +- u32 ta_mem_size; +- u32 mmu_size; +- u32 pds_size; +- u32 rastgeom_size; +- u32 tt_size; +- u32 vram_size; +-}; +- +-struct drm_psb_dpst_lut_arg { +- uint8_t lut[256]; +- int output_id; +-}; +- +-#define PSB_DC_CRTC_SAVE 0x01 +-#define PSB_DC_CRTC_RESTORE 0x02 +-#define PSB_DC_OUTPUT_SAVE 0x04 +-#define PSB_DC_OUTPUT_RESTORE 0x08 +-#define PSB_DC_CRTC_MASK 0x03 +-#define PSB_DC_OUTPUT_MASK 0x0C +- +-struct drm_psb_dc_state_arg { +- u32 flags; +- u32 obj_id; +-}; +- +-struct drm_psb_mode_operation_arg { +- u32 obj_id; +- u16 operation; +- struct drm_mode_modeinfo mode; +- void *data; +-}; +- +-struct drm_psb_stolen_memory_arg { +- u32 base; +- u32 size; +-}; +- +-/*Display Register Bits*/ +-#define REGRWBITS_PFIT_CONTROLS (1 << 0) +-#define REGRWBITS_PFIT_AUTOSCALE_RATIOS (1 << 1) +-#define REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS (1 << 2) +-#define REGRWBITS_PIPEASRC (1 << 3) +-#define REGRWBITS_PIPEBSRC (1 << 4) +-#define REGRWBITS_VTOTAL_A (1 << 5) +-#define REGRWBITS_VTOTAL_B (1 << 6) +-#define REGRWBITS_DSPACNTR (1 << 8) +-#define REGRWBITS_DSPBCNTR (1 << 9) +-#define REGRWBITS_DSPCCNTR (1 << 10) +- +-/*Overlay Register Bits*/ +-#define OV_REGRWBITS_OVADD (1 << 0) +-#define OV_REGRWBITS_OGAM_ALL (1 << 1) +- +-#define OVC_REGRWBITS_OVADD (1 << 2) +-#define OVC_REGRWBITS_OGAM_ALL (1 << 3) +- +-struct drm_psb_register_rw_arg { +- u32 b_force_hw_on; +- +- u32 display_read_mask; +- u32 display_write_mask; +- +- struct { +- u32 pfit_controls; +- u32 pfit_autoscale_ratios; +- u32 pfit_programmed_scale_ratios; +- u32 pipeasrc; +- u32 pipebsrc; +- u32 vtotal_a; +- u32 vtotal_b; +- } display; +- +- u32 overlay_read_mask; +- u32 overlay_write_mask; +- +- struct { +- u32 OVADD; +- u32 OGAMC0; +- u32 OGAMC1; +- u32 OGAMC2; +- u32 OGAMC3; +- u32 OGAMC4; +- u32 OGAMC5; +- u32 IEP_ENABLED; +- u32 IEP_BLE_MINMAX; +- u32 IEP_BSSCC_CONTROL; +- u32 b_wait_vblank; +- } overlay; +- +- u32 sprite_enable_mask; +- u32 sprite_disable_mask; +- +- struct { +- u32 dspa_control; +- u32 dspa_key_value; +- u32 dspa_key_mask; +- u32 dspc_control; +- u32 dspc_stride; +- u32 dspc_position; +- u32 dspc_linear_offset; +- u32 dspc_size; +- u32 dspc_surface; +- } sprite; +- +- u32 subpicture_enable_mask; +- u32 subpicture_disable_mask; +-}; +- +-/* Controlling the kernel modesetting buffers */ +- +-#define DRM_PSB_SIZES 0x07 +-#define DRM_PSB_FUSE_REG 0x08 +-#define DRM_PSB_DC_STATE 0x0A +-#define DRM_PSB_ADB 0x0B +-#define DRM_PSB_MODE_OPERATION 0x0C +-#define DRM_PSB_STOLEN_MEMORY 0x0D +-#define DRM_PSB_REGISTER_RW 0x0E +- +-/* +- * NOTE: Add new commands here, but increment +- * the values below and increment their +- * corresponding defines where they're +- * defined elsewhere. +- */ +- +-#define DRM_PSB_GEM_CREATE 0x10 +-#define DRM_PSB_2D_OP 0x11 +-#define DRM_PSB_GEM_MMAP 0x12 +-#define DRM_PSB_DPST 0x1B +-#define DRM_PSB_GAMMA 0x1C +-#define DRM_PSB_DPST_BL 0x1D +-#define DRM_PSB_GET_PIPE_FROM_CRTC_ID 0x1F +- +-#define PSB_MODE_OPERATION_MODE_VALID 0x01 +-#define PSB_MODE_OPERATION_SET_DC_BASE 0x02 +- +-struct drm_psb_get_pipe_from_crtc_id_arg { +- /** ID of CRTC being requested **/ +- u32 crtc_id; +- +- /** pipe of requested CRTC **/ +- u32 pipe; +-}; +- +-/* FIXME: move this into a medfield header once we are sure it isn't needed for an +- ioctl */ +-struct psb_drm_dpu_rect { +- int x, y; +- int width, height; +-}; +- +-struct drm_psb_gem_create { +- __u64 size; +- __u32 handle; +- __u32 flags; +-#define PSB_GEM_CREATE_STOLEN 1 /* Stolen memory can be used */ +-}; +- +-#define PSB_2D_OP_BUFLEN 16 +- +-struct drm_psb_2d_op { +- __u32 src; /* Handles, only src supported right now */ +- __u32 dst; +- __u32 mask; +- __u32 pat; +- __u32 size; /* In dwords of command */ +- __u32 spare; /* And bumps array to u64 align */ +- __u32 cmd[PSB_2D_OP_BUFLEN]; +-}; +- +-struct drm_psb_gem_mmap { +- __u32 handle; +- __u32 pad; +- /** +- * Fake offset to use for subsequent mmap call +- * +- * This is a fixed-size type for 32/64 compatibility. +- */ +- __u64 offset; +-}; +- +-#endif +diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c +deleted file mode 100644 +index 986a04d..0000000 +--- a/drivers/staging/gma500/psb_drv.c ++++ /dev/null +@@ -1,1229 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2007-2011, Intel Corporation. +- * All Rights Reserved. +- * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-#include +-#include +-#include "psb_drm.h" +-#include "psb_drv.h" +-#include "framebuffer.h" +-#include "psb_reg.h" +-#include "psb_intel_reg.h" +-#include "intel_bios.h" +-#include "mid_bios.h" +-#include "mdfld_dsi_dbi.h" +-#include +-#include "power.h" +-#include +-#include +-#include +-#include +-#include +-#include +- +-static int drm_psb_trap_pagefaults; +- +-int drm_psb_no_fb; +- +-static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent); +- +-MODULE_PARM_DESC(no_fb, "Disable FBdev"); +-MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults"); +-module_param_named(no_fb, drm_psb_no_fb, int, 0600); +-module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600); +- +- +-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { +- { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, +- { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, +-#if defined(CONFIG_DRM_PSB_MRST) +- { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, +- { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, +- { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, +- { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, +- { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, +- { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, +- { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, +- { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, +-#endif +-#if defined(CONFIG_DRM_PSB_MFLD) +- { 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, +- { 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, +- { 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, +- { 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, +- { 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, +- { 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, +- { 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, +- { 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, +-#endif +-#if defined(CONFIG_DRM_PSB_CDV) +- { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, +- { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, +- { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, +- { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, +- { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, +- { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, +- { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, +- { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, +-#endif +- { 0, 0, 0} +-}; +-MODULE_DEVICE_TABLE(pci, pciidlist); +- +-/* +- * Standard IOCTLs. +- */ +- +-#define DRM_IOCTL_PSB_SIZES \ +- DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \ +- struct drm_psb_sizes_arg) +-#define DRM_IOCTL_PSB_FUSE_REG \ +- DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t) +-#define DRM_IOCTL_PSB_DC_STATE \ +- DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \ +- struct drm_psb_dc_state_arg) +-#define DRM_IOCTL_PSB_ADB \ +- DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t) +-#define DRM_IOCTL_PSB_MODE_OPERATION \ +- DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \ +- struct drm_psb_mode_operation_arg) +-#define DRM_IOCTL_PSB_STOLEN_MEMORY \ +- DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \ +- struct drm_psb_stolen_memory_arg) +-#define DRM_IOCTL_PSB_REGISTER_RW \ +- DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \ +- struct drm_psb_register_rw_arg) +-#define DRM_IOCTL_PSB_DPST \ +- DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \ +- uint32_t) +-#define DRM_IOCTL_PSB_GAMMA \ +- DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \ +- struct drm_psb_dpst_lut_arg) +-#define DRM_IOCTL_PSB_DPST_BL \ +- DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \ +- uint32_t) +-#define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID \ +- DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \ +- struct drm_psb_get_pipe_from_crtc_id_arg) +-#define DRM_IOCTL_PSB_GEM_CREATE \ +- DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \ +- struct drm_psb_gem_create) +-#define DRM_IOCTL_PSB_2D_OP \ +- DRM_IOW(DRM_PSB_2D_OP + DRM_COMMAND_BASE, \ +- struct drm_psb_2d_op) +-#define DRM_IOCTL_PSB_GEM_MMAP \ +- DRM_IOWR(DRM_PSB_GEM_MMAP + DRM_COMMAND_BASE, \ +- struct drm_psb_gem_mmap) +- +-static int psb_sizes_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +-static int psb_dc_state_ioctl(struct drm_device *dev, void * data, +- struct drm_file *file_priv); +-static int psb_adb_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +-static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +-static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +-static int psb_register_rw_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +-static int psb_dpst_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +-static int psb_gamma_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +-static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +- +-#define PSB_IOCTL_DEF(ioctl, func, flags) \ +- [DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func} +- +-static struct drm_ioctl_desc psb_ioctls[] = { +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH), +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH), +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH), +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl, +- DRM_AUTH), +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl, +- DRM_AUTH), +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl, +- DRM_AUTH), +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH), +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH), +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH), +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID, +- psb_intel_get_pipe_from_crtc_id, 0), +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl, +- DRM_UNLOCKED | DRM_AUTH), +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_2D_OP, psb_accel_ioctl, +- DRM_UNLOCKED| DRM_AUTH), +- PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_MMAP, psb_gem_mmap_ioctl, +- DRM_UNLOCKED | DRM_AUTH), +-}; +- +-static void psb_lastclose(struct drm_device *dev) +-{ +- return; +-} +- +-static void psb_do_takedown(struct drm_device *dev) +-{ +-} +- +-static int psb_do_init(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct psb_gtt *pg = &dev_priv->gtt; +- +- uint32_t stolen_gtt; +- +- int ret = -ENOMEM; +- +- if (pg->mmu_gatt_start & 0x0FFFFFFF) { +- dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n"); +- ret = -EINVAL; +- goto out_err; +- } +- +- +- stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4; +- stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT; +- stolen_gtt = +- (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages; +- +- dev_priv->gatt_free_offset = pg->mmu_gatt_start + +- (stolen_gtt << PAGE_SHIFT) * 1024; +- +- if (1 || drm_debug) { +- uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID); +- uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION); +- DRM_INFO("SGX core id = 0x%08x\n", core_id); +- DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n", +- (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >> +- _PSB_CC_REVISION_MAJOR_SHIFT, +- (core_rev & _PSB_CC_REVISION_MINOR_MASK) >> +- _PSB_CC_REVISION_MINOR_SHIFT); +- DRM_INFO +- ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n", +- (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >> +- _PSB_CC_REVISION_MAINTENANCE_SHIFT, +- (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >> +- _PSB_CC_REVISION_DESIGNER_SHIFT); +- } +- +- +- spin_lock_init(&dev_priv->irqmask_lock); +- spin_lock_init(&dev_priv->lock_2d); +- +- PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0); +- PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1); +- PSB_RSGX32(PSB_CR_BIF_BANK1); +- PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK, +- PSB_CR_BIF_CTRL); +- psb_spank(dev_priv); +- +- /* mmu_gatt ?? */ +- PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); +- return 0; +-out_err: +- psb_do_takedown(dev); +- return ret; +-} +- +-static int psb_driver_unload(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- /* Kill vblank etc here */ +- +- gma_backlight_exit(dev); +- +- if (drm_psb_no_fb == 0) +- psb_modeset_cleanup(dev); +- +- if (dev_priv) { +- psb_lid_timer_takedown(dev_priv); +- gma_intel_opregion_exit(dev); +- +- if (dev_priv->ops->chip_teardown) +- dev_priv->ops->chip_teardown(dev); +- psb_do_takedown(dev); +- +- +- if (dev_priv->pf_pd) { +- psb_mmu_free_pagedir(dev_priv->pf_pd); +- dev_priv->pf_pd = NULL; +- } +- if (dev_priv->mmu) { +- struct psb_gtt *pg = &dev_priv->gtt; +- +- down_read(&pg->sem); +- psb_mmu_remove_pfn_sequence( +- psb_mmu_get_default_pd +- (dev_priv->mmu), +- pg->mmu_gatt_start, +- dev_priv->vram_stolen_size >> PAGE_SHIFT); +- up_read(&pg->sem); +- psb_mmu_driver_takedown(dev_priv->mmu); +- dev_priv->mmu = NULL; +- } +- psb_gtt_takedown(dev); +- if (dev_priv->scratch_page) { +- __free_page(dev_priv->scratch_page); +- dev_priv->scratch_page = NULL; +- } +- if (dev_priv->vdc_reg) { +- iounmap(dev_priv->vdc_reg); +- dev_priv->vdc_reg = NULL; +- } +- if (dev_priv->sgx_reg) { +- iounmap(dev_priv->sgx_reg); +- dev_priv->sgx_reg = NULL; +- } +- +- kfree(dev_priv); +- dev->dev_private = NULL; +- +- /*destroy VBT data*/ +- psb_intel_destroy_bios(dev); +- } +- +- gma_power_uninit(dev); +- +- return 0; +-} +- +- +-static int psb_driver_load(struct drm_device *dev, unsigned long chipset) +-{ +- struct drm_psb_private *dev_priv; +- unsigned long resource_start; +- struct psb_gtt *pg; +- unsigned long irqflags; +- int ret = -ENOMEM; +- uint32_t tt_pages; +- struct drm_connector *connector; +- struct psb_intel_output *psb_intel_output; +- +- dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); +- if (dev_priv == NULL) +- return -ENOMEM; +- +- dev_priv->ops = (struct psb_ops *)chipset; +- dev_priv->dev = dev; +- dev->dev_private = (void *) dev_priv; +- +- if (!IS_PSB(dev)) { +- if (pci_enable_msi(dev->pdev)) +- dev_warn(dev->dev, "Enabling MSI failed!\n"); +- } +- +- dev_priv->num_pipe = dev_priv->ops->pipes; +- +- resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE); +- +- dev_priv->vdc_reg = +- ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE); +- if (!dev_priv->vdc_reg) +- goto out_err; +- +- dev_priv->sgx_reg = ioremap(resource_start + dev_priv->ops->sgx_offset, +- PSB_SGX_SIZE); +- if (!dev_priv->sgx_reg) +- goto out_err; +- +- ret = dev_priv->ops->chip_setup(dev); +- if (ret) +- goto out_err; +- +- /* Init OSPM support */ +- gma_power_init(dev); +- +- ret = -ENOMEM; +- +- dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO); +- if (!dev_priv->scratch_page) +- goto out_err; +- +- set_pages_uc(dev_priv->scratch_page, 1); +- +- ret = psb_gtt_init(dev, 0); +- if (ret) +- goto out_err; +- +- dev_priv->mmu = psb_mmu_driver_init((void *)0, +- drm_psb_trap_pagefaults, 0, +- dev_priv); +- if (!dev_priv->mmu) +- goto out_err; +- +- pg = &dev_priv->gtt; +- +- tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ? +- (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT; +- +- +- dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0); +- if (!dev_priv->pf_pd) +- goto out_err; +- +- psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0); +- psb_mmu_set_pd_context(dev_priv->pf_pd, 1); +- +- ret = psb_do_init(dev); +- if (ret) +- return ret; +- +- PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE); +- PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE); +- +-/* igd_opregion_init(&dev_priv->opregion_dev); */ +- acpi_video_register(); +- if (dev_priv->lid_state) +- psb_lid_timer_init(dev_priv); +- +- ret = drm_vblank_init(dev, dev_priv->num_pipe); +- if (ret) +- goto out_err; +- +- /* +- * Install interrupt handlers prior to powering off SGX or else we will +- * crash. +- */ +- dev_priv->vdc_irq_mask = 0; +- dev_priv->pipestat[0] = 0; +- dev_priv->pipestat[1] = 0; +- dev_priv->pipestat[2] = 0; +- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); +- PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); +- PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R); +- PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R); +- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); +- if (IS_PSB(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) +- drm_irq_install(dev); +- +- dev->vblank_disable_allowed = 1; +- +- dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ +- +- dev->driver->get_vblank_counter = psb_get_vblank_counter; +- +-#if defined(CONFIG_DRM_PSB_MFLD) +- /* FIXME: this is not the right place for this stuff ! */ +- mdfld_output_setup(dev); +-#endif +- if (drm_psb_no_fb == 0) { +- psb_modeset_init(dev); +- psb_fbdev_init(dev); +- drm_kms_helper_poll_init(dev); +- } +- +- /* Only add backlight support if we have LVDS output */ +- list_for_each_entry(connector, &dev->mode_config.connector_list, +- head) { +- psb_intel_output = to_psb_intel_output(connector); +- +- switch (psb_intel_output->type) { +- case INTEL_OUTPUT_LVDS: +- case INTEL_OUTPUT_MIPI: +- ret = gma_backlight_init(dev); +- break; +- } +- } +- +- if (ret) +- return ret; +- +- /* Enable runtime pm at last */ +- pm_runtime_set_active(&dev->pdev->dev); +- return 0; +-out_err: +- psb_driver_unload(dev); +- return ret; +-} +- +-int psb_driver_device_is_agp(struct drm_device *dev) +-{ +- return 0; +-} +- +- +-static int psb_sizes_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- struct drm_psb_private *dev_priv = psb_priv(dev); +- struct drm_psb_sizes_arg *arg = data; +- +- *arg = dev_priv->sizes; +- return 0; +-} +- +-static int psb_dc_state_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- uint32_t flags; +- uint32_t obj_id; +- struct drm_mode_object *obj; +- struct drm_connector *connector; +- struct drm_crtc *crtc; +- struct drm_psb_dc_state_arg *arg = data; +- +- +- /* Double check MRST case */ +- if (IS_MRST(dev) || IS_MFLD(dev)) +- return -EOPNOTSUPP; +- +- flags = arg->flags; +- obj_id = arg->obj_id; +- +- if (flags & PSB_DC_CRTC_MASK) { +- obj = drm_mode_object_find(dev, obj_id, +- DRM_MODE_OBJECT_CRTC); +- if (!obj) { +- dev_dbg(dev->dev, "Invalid CRTC object.\n"); +- return -EINVAL; +- } +- +- crtc = obj_to_crtc(obj); +- +- mutex_lock(&dev->mode_config.mutex); +- if (drm_helper_crtc_in_use(crtc)) { +- if (flags & PSB_DC_CRTC_SAVE) +- crtc->funcs->save(crtc); +- else +- crtc->funcs->restore(crtc); +- } +- mutex_unlock(&dev->mode_config.mutex); +- +- return 0; +- } else if (flags & PSB_DC_OUTPUT_MASK) { +- obj = drm_mode_object_find(dev, obj_id, +- DRM_MODE_OBJECT_CONNECTOR); +- if (!obj) { +- dev_dbg(dev->dev, "Invalid connector id.\n"); +- return -EINVAL; +- } +- +- connector = obj_to_connector(obj); +- if (flags & PSB_DC_OUTPUT_SAVE) +- connector->funcs->save(connector); +- else +- connector->funcs->restore(connector); +- +- return 0; +- } +- return -EINVAL; +-} +- +-static inline void get_brightness(struct backlight_device *bd) +-{ +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- if (bd) { +- bd->props.brightness = bd->ops->get_brightness(bd); +- backlight_update_status(bd); +- } +-#endif +-} +- +-static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- struct drm_psb_private *dev_priv = psb_priv(dev); +- uint32_t *arg = data; +- +- dev_priv->blc_adj2 = *arg; +- get_brightness(dev_priv->backlight_device); +- return 0; +-} +- +-static int psb_adb_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- struct drm_psb_private *dev_priv = psb_priv(dev); +- uint32_t *arg = data; +- +- dev_priv->blc_adj1 = *arg; +- get_brightness(dev_priv->backlight_device); +- return 0; +-} +- +-/* return the current mode to the dpst module */ +-static int psb_dpst_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- struct drm_psb_private *dev_priv = psb_priv(dev); +- uint32_t *arg = data; +- uint32_t x; +- uint32_t y; +- uint32_t reg; +- +- if (!gma_power_begin(dev, 0)) +- return -EIO; +- +- reg = PSB_RVDC32(PIPEASRC); +- +- gma_power_end(dev); +- +- /* horizontal is the left 16 bits */ +- x = reg >> 16; +- /* vertical is the right 16 bits */ +- y = reg & 0x0000ffff; +- +- /* the values are the image size minus one */ +- x++; +- y++; +- +- *arg = (x << 16) | y; +- +- return 0; +-} +-static int psb_gamma_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- struct drm_psb_dpst_lut_arg *lut_arg = data; +- struct drm_mode_object *obj; +- struct drm_crtc *crtc; +- struct drm_connector *connector; +- struct psb_intel_crtc *psb_intel_crtc; +- int i = 0; +- int32_t obj_id; +- +- obj_id = lut_arg->output_id; +- obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR); +- if (!obj) { +- dev_dbg(dev->dev, "Invalid Connector object.\n"); +- return -EINVAL; +- } +- +- connector = obj_to_connector(obj); +- crtc = connector->encoder->crtc; +- psb_intel_crtc = to_psb_intel_crtc(crtc); +- +- for (i = 0; i < 256; i++) +- psb_intel_crtc->lut_adj[i] = lut_arg->lut[i]; +- +- psb_intel_crtc_load_lut(crtc); +- +- return 0; +-} +- +-static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- uint32_t obj_id; +- uint16_t op; +- struct drm_mode_modeinfo *umode; +- struct drm_display_mode *mode = NULL; +- struct drm_psb_mode_operation_arg *arg; +- struct drm_mode_object *obj; +- struct drm_connector *connector; +- struct drm_framebuffer *drm_fb; +- struct psb_framebuffer *psb_fb; +- struct drm_connector_helper_funcs *connector_funcs; +- int ret = 0; +- int resp = MODE_OK; +- struct drm_psb_private *dev_priv = psb_priv(dev); +- +- arg = (struct drm_psb_mode_operation_arg *)data; +- obj_id = arg->obj_id; +- op = arg->operation; +- +- switch (op) { +- case PSB_MODE_OPERATION_SET_DC_BASE: +- obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB); +- if (!obj) { +- dev_dbg(dev->dev, "Invalid FB id %d\n", obj_id); +- return -EINVAL; +- } +- +- drm_fb = obj_to_fb(obj); +- psb_fb = to_psb_fb(drm_fb); +- +- if (gma_power_begin(dev, 0)) { +- REG_WRITE(DSPASURF, psb_fb->gtt->offset); +- REG_READ(DSPASURF); +- gma_power_end(dev); +- } else { +- dev_priv->saveDSPASURF = psb_fb->gtt->offset; +- } +- +- return 0; +- case PSB_MODE_OPERATION_MODE_VALID: +- umode = &arg->mode; +- +- mutex_lock(&dev->mode_config.mutex); +- +- obj = drm_mode_object_find(dev, obj_id, +- DRM_MODE_OBJECT_CONNECTOR); +- if (!obj) { +- ret = -EINVAL; +- goto mode_op_out; +- } +- +- connector = obj_to_connector(obj); +- +- mode = drm_mode_create(dev); +- if (!mode) { +- ret = -ENOMEM; +- goto mode_op_out; +- } +- +- /* drm_crtc_convert_umode(mode, umode); */ +- { +- mode->clock = umode->clock; +- mode->hdisplay = umode->hdisplay; +- mode->hsync_start = umode->hsync_start; +- mode->hsync_end = umode->hsync_end; +- mode->htotal = umode->htotal; +- mode->hskew = umode->hskew; +- mode->vdisplay = umode->vdisplay; +- mode->vsync_start = umode->vsync_start; +- mode->vsync_end = umode->vsync_end; +- mode->vtotal = umode->vtotal; +- mode->vscan = umode->vscan; +- mode->vrefresh = umode->vrefresh; +- mode->flags = umode->flags; +- mode->type = umode->type; +- strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN); +- mode->name[DRM_DISPLAY_MODE_LEN-1] = 0; +- } +- +- connector_funcs = (struct drm_connector_helper_funcs *) +- connector->helper_private; +- +- if (connector_funcs->mode_valid) { +- resp = connector_funcs->mode_valid(connector, mode); +- arg->data = (void *)resp; +- } +- +- /*do some clean up work*/ +- if (mode) +- drm_mode_destroy(dev, mode); +-mode_op_out: +- mutex_unlock(&dev->mode_config.mutex); +- return ret; +- +- default: +- dev_dbg(dev->dev, "Unsupported psb mode operation\n"); +- return -EOPNOTSUPP; +- } +- +- return 0; +-} +- +-static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- struct drm_psb_private *dev_priv = psb_priv(dev); +- struct drm_psb_stolen_memory_arg *arg = data; +- +- arg->base = dev_priv->stolen_base; +- arg->size = dev_priv->vram_stolen_size; +- +- return 0; +-} +- +-/* FIXME: needs Medfield changes */ +-static int psb_register_rw_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- struct drm_psb_private *dev_priv = psb_priv(dev); +- struct drm_psb_register_rw_arg *arg = data; +- bool usage = arg->b_force_hw_on ? true : false; +- +- if (arg->display_write_mask != 0) { +- if (gma_power_begin(dev, usage)) { +- if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS) +- PSB_WVDC32(arg->display.pfit_controls, +- PFIT_CONTROL); +- if (arg->display_write_mask & +- REGRWBITS_PFIT_AUTOSCALE_RATIOS) +- PSB_WVDC32(arg->display.pfit_autoscale_ratios, +- PFIT_AUTO_RATIOS); +- if (arg->display_write_mask & +- REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) +- PSB_WVDC32( +- arg->display.pfit_programmed_scale_ratios, +- PFIT_PGM_RATIOS); +- if (arg->display_write_mask & REGRWBITS_PIPEASRC) +- PSB_WVDC32(arg->display.pipeasrc, +- PIPEASRC); +- if (arg->display_write_mask & REGRWBITS_PIPEBSRC) +- PSB_WVDC32(arg->display.pipebsrc, +- PIPEBSRC); +- if (arg->display_write_mask & REGRWBITS_VTOTAL_A) +- PSB_WVDC32(arg->display.vtotal_a, +- VTOTAL_A); +- if (arg->display_write_mask & REGRWBITS_VTOTAL_B) +- PSB_WVDC32(arg->display.vtotal_b, +- VTOTAL_B); +- gma_power_end(dev); +- } else { +- if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS) +- dev_priv->savePFIT_CONTROL = +- arg->display.pfit_controls; +- if (arg->display_write_mask & +- REGRWBITS_PFIT_AUTOSCALE_RATIOS) +- dev_priv->savePFIT_AUTO_RATIOS = +- arg->display.pfit_autoscale_ratios; +- if (arg->display_write_mask & +- REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) +- dev_priv->savePFIT_PGM_RATIOS = +- arg->display.pfit_programmed_scale_ratios; +- if (arg->display_write_mask & REGRWBITS_PIPEASRC) +- dev_priv->savePIPEASRC = arg->display.pipeasrc; +- if (arg->display_write_mask & REGRWBITS_PIPEBSRC) +- dev_priv->savePIPEBSRC = arg->display.pipebsrc; +- if (arg->display_write_mask & REGRWBITS_VTOTAL_A) +- dev_priv->saveVTOTAL_A = arg->display.vtotal_a; +- if (arg->display_write_mask & REGRWBITS_VTOTAL_B) +- dev_priv->saveVTOTAL_B = arg->display.vtotal_b; +- } +- } +- +- if (arg->display_read_mask != 0) { +- if (gma_power_begin(dev, usage)) { +- if (arg->display_read_mask & +- REGRWBITS_PFIT_CONTROLS) +- arg->display.pfit_controls = +- PSB_RVDC32(PFIT_CONTROL); +- if (arg->display_read_mask & +- REGRWBITS_PFIT_AUTOSCALE_RATIOS) +- arg->display.pfit_autoscale_ratios = +- PSB_RVDC32(PFIT_AUTO_RATIOS); +- if (arg->display_read_mask & +- REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) +- arg->display.pfit_programmed_scale_ratios = +- PSB_RVDC32(PFIT_PGM_RATIOS); +- if (arg->display_read_mask & REGRWBITS_PIPEASRC) +- arg->display.pipeasrc = PSB_RVDC32(PIPEASRC); +- if (arg->display_read_mask & REGRWBITS_PIPEBSRC) +- arg->display.pipebsrc = PSB_RVDC32(PIPEBSRC); +- if (arg->display_read_mask & REGRWBITS_VTOTAL_A) +- arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A); +- if (arg->display_read_mask & REGRWBITS_VTOTAL_B) +- arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B); +- gma_power_end(dev); +- } else { +- if (arg->display_read_mask & +- REGRWBITS_PFIT_CONTROLS) +- arg->display.pfit_controls = +- dev_priv->savePFIT_CONTROL; +- if (arg->display_read_mask & +- REGRWBITS_PFIT_AUTOSCALE_RATIOS) +- arg->display.pfit_autoscale_ratios = +- dev_priv->savePFIT_AUTO_RATIOS; +- if (arg->display_read_mask & +- REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) +- arg->display.pfit_programmed_scale_ratios = +- dev_priv->savePFIT_PGM_RATIOS; +- if (arg->display_read_mask & REGRWBITS_PIPEASRC) +- arg->display.pipeasrc = dev_priv->savePIPEASRC; +- if (arg->display_read_mask & REGRWBITS_PIPEBSRC) +- arg->display.pipebsrc = dev_priv->savePIPEBSRC; +- if (arg->display_read_mask & REGRWBITS_VTOTAL_A) +- arg->display.vtotal_a = dev_priv->saveVTOTAL_A; +- if (arg->display_read_mask & REGRWBITS_VTOTAL_B) +- arg->display.vtotal_b = dev_priv->saveVTOTAL_B; +- } +- } +- +- if (arg->overlay_write_mask != 0) { +- if (gma_power_begin(dev, usage)) { +- if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) { +- PSB_WVDC32(arg->overlay.OGAMC5, OV_OGAMC5); +- PSB_WVDC32(arg->overlay.OGAMC4, OV_OGAMC4); +- PSB_WVDC32(arg->overlay.OGAMC3, OV_OGAMC3); +- PSB_WVDC32(arg->overlay.OGAMC2, OV_OGAMC2); +- PSB_WVDC32(arg->overlay.OGAMC1, OV_OGAMC1); +- PSB_WVDC32(arg->overlay.OGAMC0, OV_OGAMC0); +- } +- if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) { +- PSB_WVDC32(arg->overlay.OGAMC5, OVC_OGAMC5); +- PSB_WVDC32(arg->overlay.OGAMC4, OVC_OGAMC4); +- PSB_WVDC32(arg->overlay.OGAMC3, OVC_OGAMC3); +- PSB_WVDC32(arg->overlay.OGAMC2, OVC_OGAMC2); +- PSB_WVDC32(arg->overlay.OGAMC1, OVC_OGAMC1); +- PSB_WVDC32(arg->overlay.OGAMC0, OVC_OGAMC0); +- } +- +- if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) { +- PSB_WVDC32(arg->overlay.OVADD, OV_OVADD); +- +- if (arg->overlay.b_wait_vblank) { +- /* Wait for 20ms.*/ +- unsigned long vblank_timeout = jiffies +- + HZ/50; +- uint32_t temp; +- while (time_before_eq(jiffies, +- vblank_timeout)) { +- temp = PSB_RVDC32(OV_DOVASTA); +- if ((temp & (0x1 << 31)) != 0) +- break; +- cpu_relax(); +- } +- } +- } +- if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) { +- PSB_WVDC32(arg->overlay.OVADD, OVC_OVADD); +- if (arg->overlay.b_wait_vblank) { +- /* Wait for 20ms.*/ +- unsigned long vblank_timeout = +- jiffies + HZ/50; +- uint32_t temp; +- while (time_before_eq(jiffies, +- vblank_timeout)) { +- temp = PSB_RVDC32(OVC_DOVCSTA); +- if ((temp & (0x1 << 31)) != 0) +- break; +- cpu_relax(); +- } +- } +- } +- gma_power_end(dev); +- } else { +- if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) { +- dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5; +- dev_priv->saveOV_OGAMC4 = arg->overlay.OGAMC4; +- dev_priv->saveOV_OGAMC3 = arg->overlay.OGAMC3; +- dev_priv->saveOV_OGAMC2 = arg->overlay.OGAMC2; +- dev_priv->saveOV_OGAMC1 = arg->overlay.OGAMC1; +- dev_priv->saveOV_OGAMC0 = arg->overlay.OGAMC0; +- } +- if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) { +- dev_priv->saveOVC_OGAMC5 = arg->overlay.OGAMC5; +- dev_priv->saveOVC_OGAMC4 = arg->overlay.OGAMC4; +- dev_priv->saveOVC_OGAMC3 = arg->overlay.OGAMC3; +- dev_priv->saveOVC_OGAMC2 = arg->overlay.OGAMC2; +- dev_priv->saveOVC_OGAMC1 = arg->overlay.OGAMC1; +- dev_priv->saveOVC_OGAMC0 = arg->overlay.OGAMC0; +- } +- if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) +- dev_priv->saveOV_OVADD = arg->overlay.OVADD; +- if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) +- dev_priv->saveOVC_OVADD = arg->overlay.OVADD; +- } +- } +- +- if (arg->overlay_read_mask != 0) { +- if (gma_power_begin(dev, usage)) { +- if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) { +- arg->overlay.OGAMC5 = PSB_RVDC32(OV_OGAMC5); +- arg->overlay.OGAMC4 = PSB_RVDC32(OV_OGAMC4); +- arg->overlay.OGAMC3 = PSB_RVDC32(OV_OGAMC3); +- arg->overlay.OGAMC2 = PSB_RVDC32(OV_OGAMC2); +- arg->overlay.OGAMC1 = PSB_RVDC32(OV_OGAMC1); +- arg->overlay.OGAMC0 = PSB_RVDC32(OV_OGAMC0); +- } +- if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) { +- arg->overlay.OGAMC5 = PSB_RVDC32(OVC_OGAMC5); +- arg->overlay.OGAMC4 = PSB_RVDC32(OVC_OGAMC4); +- arg->overlay.OGAMC3 = PSB_RVDC32(OVC_OGAMC3); +- arg->overlay.OGAMC2 = PSB_RVDC32(OVC_OGAMC2); +- arg->overlay.OGAMC1 = PSB_RVDC32(OVC_OGAMC1); +- arg->overlay.OGAMC0 = PSB_RVDC32(OVC_OGAMC0); +- } +- if (arg->overlay_read_mask & OV_REGRWBITS_OVADD) +- arg->overlay.OVADD = PSB_RVDC32(OV_OVADD); +- if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD) +- arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD); +- gma_power_end(dev); +- } else { +- if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) { +- arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5; +- arg->overlay.OGAMC4 = dev_priv->saveOV_OGAMC4; +- arg->overlay.OGAMC3 = dev_priv->saveOV_OGAMC3; +- arg->overlay.OGAMC2 = dev_priv->saveOV_OGAMC2; +- arg->overlay.OGAMC1 = dev_priv->saveOV_OGAMC1; +- arg->overlay.OGAMC0 = dev_priv->saveOV_OGAMC0; +- } +- if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) { +- arg->overlay.OGAMC5 = dev_priv->saveOVC_OGAMC5; +- arg->overlay.OGAMC4 = dev_priv->saveOVC_OGAMC4; +- arg->overlay.OGAMC3 = dev_priv->saveOVC_OGAMC3; +- arg->overlay.OGAMC2 = dev_priv->saveOVC_OGAMC2; +- arg->overlay.OGAMC1 = dev_priv->saveOVC_OGAMC1; +- arg->overlay.OGAMC0 = dev_priv->saveOVC_OGAMC0; +- } +- if (arg->overlay_read_mask & OV_REGRWBITS_OVADD) +- arg->overlay.OVADD = dev_priv->saveOV_OVADD; +- if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD) +- arg->overlay.OVADD = dev_priv->saveOVC_OVADD; +- } +- } +- +- if (arg->sprite_enable_mask != 0) { +- if (gma_power_begin(dev, usage)) { +- PSB_WVDC32(0x1F3E, DSPARB); +- PSB_WVDC32(arg->sprite.dspa_control +- | PSB_RVDC32(DSPACNTR), DSPACNTR); +- PSB_WVDC32(arg->sprite.dspa_key_value, DSPAKEYVAL); +- PSB_WVDC32(arg->sprite.dspa_key_mask, DSPAKEYMASK); +- PSB_WVDC32(PSB_RVDC32(DSPASURF), DSPASURF); +- PSB_RVDC32(DSPASURF); +- PSB_WVDC32(arg->sprite.dspc_control, DSPCCNTR); +- PSB_WVDC32(arg->sprite.dspc_stride, DSPCSTRIDE); +- PSB_WVDC32(arg->sprite.dspc_position, DSPCPOS); +- PSB_WVDC32(arg->sprite.dspc_linear_offset, DSPCLINOFF); +- PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE); +- PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF); +- PSB_RVDC32(DSPCSURF); +- gma_power_end(dev); +- } +- } +- +- if (arg->sprite_disable_mask != 0) { +- if (gma_power_begin(dev, usage)) { +- PSB_WVDC32(0x3F3E, DSPARB); +- PSB_WVDC32(0x0, DSPCCNTR); +- PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF); +- PSB_RVDC32(DSPCSURF); +- gma_power_end(dev); +- } +- } +- +- if (arg->subpicture_enable_mask != 0) { +- if (gma_power_begin(dev, usage)) { +- uint32_t temp; +- if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) { +- temp = PSB_RVDC32(DSPACNTR); +- temp &= ~DISPPLANE_PIXFORMAT_MASK; +- temp &= ~DISPPLANE_BOTTOM; +- temp |= DISPPLANE_32BPP; +- PSB_WVDC32(temp, DSPACNTR); +- +- temp = PSB_RVDC32(DSPABASE); +- PSB_WVDC32(temp, DSPABASE); +- PSB_RVDC32(DSPABASE); +- temp = PSB_RVDC32(DSPASURF); +- PSB_WVDC32(temp, DSPASURF); +- PSB_RVDC32(DSPASURF); +- } +- if (arg->subpicture_enable_mask & REGRWBITS_DSPBCNTR) { +- temp = PSB_RVDC32(DSPBCNTR); +- temp &= ~DISPPLANE_PIXFORMAT_MASK; +- temp &= ~DISPPLANE_BOTTOM; +- temp |= DISPPLANE_32BPP; +- PSB_WVDC32(temp, DSPBCNTR); +- +- temp = PSB_RVDC32(DSPBBASE); +- PSB_WVDC32(temp, DSPBBASE); +- PSB_RVDC32(DSPBBASE); +- temp = PSB_RVDC32(DSPBSURF); +- PSB_WVDC32(temp, DSPBSURF); +- PSB_RVDC32(DSPBSURF); +- } +- if (arg->subpicture_enable_mask & REGRWBITS_DSPCCNTR) { +- temp = PSB_RVDC32(DSPCCNTR); +- temp &= ~DISPPLANE_PIXFORMAT_MASK; +- temp &= ~DISPPLANE_BOTTOM; +- temp |= DISPPLANE_32BPP; +- PSB_WVDC32(temp, DSPCCNTR); +- +- temp = PSB_RVDC32(DSPCBASE); +- PSB_WVDC32(temp, DSPCBASE); +- PSB_RVDC32(DSPCBASE); +- temp = PSB_RVDC32(DSPCSURF); +- PSB_WVDC32(temp, DSPCSURF); +- PSB_RVDC32(DSPCSURF); +- } +- gma_power_end(dev); +- } +- } +- +- if (arg->subpicture_disable_mask != 0) { +- if (gma_power_begin(dev, usage)) { +- uint32_t temp; +- if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) { +- temp = PSB_RVDC32(DSPACNTR); +- temp &= ~DISPPLANE_PIXFORMAT_MASK; +- temp |= DISPPLANE_32BPP_NO_ALPHA; +- PSB_WVDC32(temp, DSPACNTR); +- +- temp = PSB_RVDC32(DSPABASE); +- PSB_WVDC32(temp, DSPABASE); +- PSB_RVDC32(DSPABASE); +- temp = PSB_RVDC32(DSPASURF); +- PSB_WVDC32(temp, DSPASURF); +- PSB_RVDC32(DSPASURF); +- } +- if (arg->subpicture_disable_mask & REGRWBITS_DSPBCNTR) { +- temp = PSB_RVDC32(DSPBCNTR); +- temp &= ~DISPPLANE_PIXFORMAT_MASK; +- temp |= DISPPLANE_32BPP_NO_ALPHA; +- PSB_WVDC32(temp, DSPBCNTR); +- +- temp = PSB_RVDC32(DSPBBASE); +- PSB_WVDC32(temp, DSPBBASE); +- PSB_RVDC32(DSPBBASE); +- temp = PSB_RVDC32(DSPBSURF); +- PSB_WVDC32(temp, DSPBSURF); +- PSB_RVDC32(DSPBSURF); +- } +- if (arg->subpicture_disable_mask & REGRWBITS_DSPCCNTR) { +- temp = PSB_RVDC32(DSPCCNTR); +- temp &= ~DISPPLANE_PIXFORMAT_MASK; +- temp |= DISPPLANE_32BPP_NO_ALPHA; +- PSB_WVDC32(temp, DSPCCNTR); +- +- temp = PSB_RVDC32(DSPCBASE); +- PSB_WVDC32(temp, DSPCBASE); +- PSB_RVDC32(DSPCBASE); +- temp = PSB_RVDC32(DSPCSURF); +- PSB_WVDC32(temp, DSPCSURF); +- PSB_RVDC32(DSPCSURF); +- } +- gma_power_end(dev); +- } +- } +- +- return 0; +-} +- +-static int psb_driver_open(struct drm_device *dev, struct drm_file *priv) +-{ +- return 0; +-} +- +-static void psb_driver_close(struct drm_device *dev, struct drm_file *priv) +-{ +-} +- +-static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd, +- unsigned long arg) +-{ +- struct drm_file *file_priv = filp->private_data; +- struct drm_device *dev = file_priv->minor->dev; +- int ret; +- +- pm_runtime_forbid(dev->dev); +- ret = drm_ioctl(filp, cmd, arg); +- pm_runtime_allow(dev->dev); +- return ret; +- /* FIXME: do we need to wrap the other side of this */ +-} +- +- +-/* When a client dies: +- * - Check for and clean up flipped page state +- */ +-void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv) +-{ +-} +- +-static void psb_remove(struct pci_dev *pdev) +-{ +- struct drm_device *dev = pci_get_drvdata(pdev); +- drm_put_dev(dev); +-} +- +-static const struct dev_pm_ops psb_pm_ops = { +- .suspend = gma_power_suspend, +- .resume = gma_power_resume, +- .freeze = gma_power_suspend, +- .thaw = gma_power_resume, +- .poweroff = gma_power_suspend, +- .restore = gma_power_resume, +- .runtime_suspend = psb_runtime_suspend, +- .runtime_resume = psb_runtime_resume, +- .runtime_idle = psb_runtime_idle, +-}; +- +-static struct vm_operations_struct psb_gem_vm_ops = { +- .fault = psb_gem_fault, +- .open = drm_gem_vm_open, +- .close = drm_gem_vm_close, +-}; +- +-static struct drm_driver driver = { +- .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \ +- DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM , +- .load = psb_driver_load, +- .unload = psb_driver_unload, +- +- .ioctls = psb_ioctls, +- .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls), +- .device_is_agp = psb_driver_device_is_agp, +- .irq_preinstall = psb_irq_preinstall, +- .irq_postinstall = psb_irq_postinstall, +- .irq_uninstall = psb_irq_uninstall, +- .irq_handler = psb_irq_handler, +- .enable_vblank = psb_enable_vblank, +- .disable_vblank = psb_disable_vblank, +- .get_vblank_counter = psb_get_vblank_counter, +- .lastclose = psb_lastclose, +- .open = psb_driver_open, +- .preclose = psb_driver_preclose, +- .postclose = psb_driver_close, +- .reclaim_buffers = drm_core_reclaim_buffers, +- +- .gem_init_object = psb_gem_init_object, +- .gem_free_object = psb_gem_free_object, +- .gem_vm_ops = &psb_gem_vm_ops, +- .dumb_create = psb_gem_dumb_create, +- .dumb_map_offset = psb_gem_dumb_map_gtt, +- .dumb_destroy = psb_gem_dumb_destroy, +- +- .fops = { +- .owner = THIS_MODULE, +- .open = drm_open, +- .release = drm_release, +- .unlocked_ioctl = psb_unlocked_ioctl, +- .mmap = drm_gem_mmap, +- .poll = drm_poll, +- .fasync = drm_fasync, +- .read = drm_read, +- }, +- .name = DRIVER_NAME, +- .desc = DRIVER_DESC, +- .date = PSB_DRM_DRIVER_DATE, +- .major = PSB_DRM_DRIVER_MAJOR, +- .minor = PSB_DRM_DRIVER_MINOR, +- .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL +-}; +- +-static struct pci_driver psb_pci_driver = { +- .name = DRIVER_NAME, +- .id_table = pciidlist, +- .probe = psb_probe, +- .remove = psb_remove, +- .driver.pm = &psb_pm_ops, +-}; +- +-static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +-{ +- return drm_get_pci_dev(pdev, ent, &driver); +-} +- +-static int __init psb_init(void) +-{ +- return drm_pci_init(&driver, &psb_pci_driver); +-} +- +-static void __exit psb_exit(void) +-{ +- drm_pci_exit(&driver, &psb_pci_driver); +-} +- +-late_initcall(psb_init); +-module_exit(psb_exit); +- +-MODULE_AUTHOR("Alan Cox and others"); +-MODULE_DESCRIPTION(DRIVER_DESC); +-MODULE_LICENSE("GPL"); +diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h +deleted file mode 100644 +index 11d963a..0000000 +--- a/drivers/staging/gma500/psb_drv.h ++++ /dev/null +@@ -1,952 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2007-2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- **************************************************************************/ +- +-#ifndef _PSB_DRV_H_ +-#define _PSB_DRV_H_ +- +-#include +- +-#include +-#include "drm_global.h" +-#include "gem_glue.h" +-#include "psb_drm.h" +-#include "psb_reg.h" +-#include "psb_intel_drv.h" +-#include "gtt.h" +-#include "power.h" +-#include "mrst.h" +-#include "medfield.h" +- +-/* Append new drm mode definition here, align with libdrm definition */ +-#define DRM_MODE_SCALE_NO_SCALE 2 +- +-enum { +- CHIP_PSB_8108 = 0, /* Poulsbo */ +- CHIP_PSB_8109 = 1, /* Poulsbo */ +- CHIP_MRST_4100 = 2, /* Moorestown/Oaktrail */ +- CHIP_MFLD_0130 = 3, /* Medfield */ +-}; +- +-#define IS_PSB(dev) (((dev)->pci_device & 0xfffe) == 0x8108) +-#define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100) +-#define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130) +- +-/* +- * Driver definitions +- */ +- +-#define DRIVER_NAME "gma500" +-#define DRIVER_DESC "DRM driver for the Intel GMA500" +- +-#define PSB_DRM_DRIVER_DATE "2011-06-06" +-#define PSB_DRM_DRIVER_MAJOR 1 +-#define PSB_DRM_DRIVER_MINOR 0 +-#define PSB_DRM_DRIVER_PATCHLEVEL 0 +- +-/* +- * Hardware offsets +- */ +-#define PSB_VDC_OFFSET 0x00000000 +-#define PSB_VDC_SIZE 0x000080000 +-#define MRST_MMIO_SIZE 0x0000C0000 +-#define MDFLD_MMIO_SIZE 0x000100000 +-#define PSB_SGX_SIZE 0x8000 +-#define PSB_SGX_OFFSET 0x00040000 +-#define MRST_SGX_OFFSET 0x00080000 +-/* +- * PCI resource identifiers +- */ +-#define PSB_MMIO_RESOURCE 0 +-#define PSB_GATT_RESOURCE 2 +-#define PSB_GTT_RESOURCE 3 +-/* +- * PCI configuration +- */ +-#define PSB_GMCH_CTRL 0x52 +-#define PSB_BSM 0x5C +-#define _PSB_GMCH_ENABLED 0x4 +-#define PSB_PGETBL_CTL 0x2020 +-#define _PSB_PGETBL_ENABLED 0x00000001 +-#define PSB_SGX_2D_SLAVE_PORT 0x4000 +- +-/* To get rid of */ +-#define PSB_TT_PRIV0_LIMIT (256*1024*1024) +-#define PSB_TT_PRIV0_PLIMIT (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT) +- +-/* +- * SGX side MMU definitions (these can probably go) +- */ +- +-/* +- * Flags for external memory type field. +- */ +-#define PSB_MMU_CACHED_MEMORY 0x0001 /* Bind to MMU only */ +-#define PSB_MMU_RO_MEMORY 0x0002 /* MMU RO memory */ +-#define PSB_MMU_WO_MEMORY 0x0004 /* MMU WO memory */ +-/* +- * PTE's and PDE's +- */ +-#define PSB_PDE_MASK 0x003FFFFF +-#define PSB_PDE_SHIFT 22 +-#define PSB_PTE_SHIFT 12 +-/* +- * Cache control +- */ +-#define PSB_PTE_VALID 0x0001 /* PTE / PDE valid */ +-#define PSB_PTE_WO 0x0002 /* Write only */ +-#define PSB_PTE_RO 0x0004 /* Read only */ +-#define PSB_PTE_CACHED 0x0008 /* CPU cache coherent */ +- +-/* +- * VDC registers and bits +- */ +-#define PSB_MSVDX_CLOCKGATING 0x2064 +-#define PSB_TOPAZ_CLOCKGATING 0x2068 +-#define PSB_HWSTAM 0x2098 +-#define PSB_INSTPM 0x20C0 +-#define PSB_INT_IDENTITY_R 0x20A4 +-#define _MDFLD_PIPEC_EVENT_FLAG (1<<2) +-#define _MDFLD_PIPEC_VBLANK_FLAG (1<<3) +-#define _PSB_DPST_PIPEB_FLAG (1<<4) +-#define _MDFLD_PIPEB_EVENT_FLAG (1<<4) +-#define _PSB_VSYNC_PIPEB_FLAG (1<<5) +-#define _PSB_DPST_PIPEA_FLAG (1<<6) +-#define _PSB_PIPEA_EVENT_FLAG (1<<6) +-#define _PSB_VSYNC_PIPEA_FLAG (1<<7) +-#define _MDFLD_MIPIA_FLAG (1<<16) +-#define _MDFLD_MIPIC_FLAG (1<<17) +-#define _PSB_IRQ_SGX_FLAG (1<<18) +-#define _PSB_IRQ_MSVDX_FLAG (1<<19) +-#define _LNC_IRQ_TOPAZ_FLAG (1<<20) +- +-#define _PSB_PIPE_EVENT_FLAG (_PSB_VSYNC_PIPEA_FLAG | \ +- _PSB_VSYNC_PIPEB_FLAG) +- +-/* This flag includes all the display IRQ bits excepts the vblank irqs. */ +-#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \ +- _MDFLD_PIPEB_EVENT_FLAG | \ +- _PSB_PIPEA_EVENT_FLAG | \ +- _PSB_VSYNC_PIPEA_FLAG | \ +- _MDFLD_MIPIA_FLAG | \ +- _MDFLD_MIPIC_FLAG) +-#define PSB_INT_IDENTITY_R 0x20A4 +-#define PSB_INT_MASK_R 0x20A8 +-#define PSB_INT_ENABLE_R 0x20A0 +- +-#define _PSB_MMU_ER_MASK 0x0001FF00 +-#define _PSB_MMU_ER_HOST (1 << 16) +-#define GPIOA 0x5010 +-#define GPIOB 0x5014 +-#define GPIOC 0x5018 +-#define GPIOD 0x501c +-#define GPIOE 0x5020 +-#define GPIOF 0x5024 +-#define GPIOG 0x5028 +-#define GPIOH 0x502c +-#define GPIO_CLOCK_DIR_MASK (1 << 0) +-#define GPIO_CLOCK_DIR_IN (0 << 1) +-#define GPIO_CLOCK_DIR_OUT (1 << 1) +-#define GPIO_CLOCK_VAL_MASK (1 << 2) +-#define GPIO_CLOCK_VAL_OUT (1 << 3) +-#define GPIO_CLOCK_VAL_IN (1 << 4) +-#define GPIO_CLOCK_PULLUP_DISABLE (1 << 5) +-#define GPIO_DATA_DIR_MASK (1 << 8) +-#define GPIO_DATA_DIR_IN (0 << 9) +-#define GPIO_DATA_DIR_OUT (1 << 9) +-#define GPIO_DATA_VAL_MASK (1 << 10) +-#define GPIO_DATA_VAL_OUT (1 << 11) +-#define GPIO_DATA_VAL_IN (1 << 12) +-#define GPIO_DATA_PULLUP_DISABLE (1 << 13) +- +-#define VCLK_DIVISOR_VGA0 0x6000 +-#define VCLK_DIVISOR_VGA1 0x6004 +-#define VCLK_POST_DIV 0x6010 +- +-#define PSB_COMM_2D (PSB_ENGINE_2D << 4) +-#define PSB_COMM_3D (PSB_ENGINE_3D << 4) +-#define PSB_COMM_TA (PSB_ENGINE_TA << 4) +-#define PSB_COMM_HP (PSB_ENGINE_HP << 4) +-#define PSB_COMM_USER_IRQ (1024 >> 2) +-#define PSB_COMM_USER_IRQ_LOST (PSB_COMM_USER_IRQ + 1) +-#define PSB_COMM_FW (2048 >> 2) +- +-#define PSB_UIRQ_VISTEST 1 +-#define PSB_UIRQ_OOM_REPLY 2 +-#define PSB_UIRQ_FIRE_TA_REPLY 3 +-#define PSB_UIRQ_FIRE_RASTER_REPLY 4 +- +-#define PSB_2D_SIZE (256*1024*1024) +-#define PSB_MAX_RELOC_PAGES 1024 +- +-#define PSB_LOW_REG_OFFS 0x0204 +-#define PSB_HIGH_REG_OFFS 0x0600 +- +-#define PSB_NUM_VBLANKS 2 +- +- +-#define PSB_2D_SIZE (256*1024*1024) +-#define PSB_MAX_RELOC_PAGES 1024 +- +-#define PSB_LOW_REG_OFFS 0x0204 +-#define PSB_HIGH_REG_OFFS 0x0600 +- +-#define PSB_NUM_VBLANKS 2 +-#define PSB_WATCHDOG_DELAY (DRM_HZ * 2) +-#define PSB_LID_DELAY (DRM_HZ / 10) +- +-#define MDFLD_PNW_B0 0x04 +-#define MDFLD_PNW_C0 0x08 +- +-#define MDFLD_DSR_2D_3D_0 (1 << 0) +-#define MDFLD_DSR_2D_3D_2 (1 << 1) +-#define MDFLD_DSR_CURSOR_0 (1 << 2) +-#define MDFLD_DSR_CURSOR_2 (1 << 3) +-#define MDFLD_DSR_OVERLAY_0 (1 << 4) +-#define MDFLD_DSR_OVERLAY_2 (1 << 5) +-#define MDFLD_DSR_MIPI_CONTROL (1 << 6) +-#define MDFLD_DSR_DAMAGE_MASK_0 ((1 << 0) | (1 << 2) | (1 << 4)) +-#define MDFLD_DSR_DAMAGE_MASK_2 ((1 << 1) | (1 << 3) | (1 << 5)) +-#define MDFLD_DSR_2D_3D (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2) +- +-#define MDFLD_DSR_RR 45 +-#define MDFLD_DPU_ENABLE (1 << 31) +-#define MDFLD_DSR_FULLSCREEN (1 << 30) +-#define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR) +- +-#define PSB_PWR_STATE_ON 1 +-#define PSB_PWR_STATE_OFF 2 +- +-#define PSB_PMPOLICY_NOPM 0 +-#define PSB_PMPOLICY_CLOCKGATING 1 +-#define PSB_PMPOLICY_POWERDOWN 2 +- +-#define PSB_PMSTATE_POWERUP 0 +-#define PSB_PMSTATE_CLOCKGATED 1 +-#define PSB_PMSTATE_POWERDOWN 2 +-#define PSB_PCIx_MSI_ADDR_LOC 0x94 +-#define PSB_PCIx_MSI_DATA_LOC 0x98 +- +-/* Medfield crystal settings */ +-#define KSEL_CRYSTAL_19 1 +-#define KSEL_BYPASS_19 5 +-#define KSEL_BYPASS_25 6 +-#define KSEL_BYPASS_83_100 7 +- +-struct opregion_header; +-struct opregion_acpi; +-struct opregion_swsci; +-struct opregion_asle; +- +-struct psb_intel_opregion { +- struct opregion_header *header; +- struct opregion_acpi *acpi; +- struct opregion_swsci *swsci; +- struct opregion_asle *asle; +- int enabled; +-}; +- +-struct psb_ops; +- +-struct drm_psb_private { +- struct drm_device *dev; +- const struct psb_ops *ops; +- +- struct psb_gtt gtt; +- +- /* GTT Memory manager */ +- struct psb_gtt_mm *gtt_mm; +- struct page *scratch_page; +- u32 *gtt_map; +- uint32_t stolen_base; +- void *vram_addr; +- unsigned long vram_stolen_size; +- int gtt_initialized; +- u16 gmch_ctrl; /* Saved GTT setup */ +- u32 pge_ctl; +- +- struct mutex gtt_mutex; +- struct resource *gtt_mem; /* Our PCI resource */ +- +- struct psb_mmu_driver *mmu; +- struct psb_mmu_pd *pf_pd; +- +- /* +- * Register base +- */ +- +- uint8_t *sgx_reg; +- uint8_t *vdc_reg; +- uint32_t gatt_free_offset; +- +- /* +- * Fencing / irq. +- */ +- +- uint32_t vdc_irq_mask; +- uint32_t pipestat[PSB_NUM_PIPE]; +- +- spinlock_t irqmask_lock; +- +- /* +- * Power +- */ +- +- bool suspended; +- bool display_power; +- int display_count; +- +- /* +- * Modesetting +- */ +- struct psb_intel_mode_device mode_dev; +- +- struct drm_crtc *plane_to_crtc_mapping[PSB_NUM_PIPE]; +- struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE]; +- uint32_t num_pipe; +- +- /* +- * OSPM info (Power management base) (can go ?) +- */ +- uint32_t ospm_base; +- +- /* +- * Sizes info +- */ +- +- struct drm_psb_sizes_arg sizes; +- +- u32 fuse_reg_value; +- u32 video_device_fuse; +- +- /* PCI revision ID for B0:D2:F0 */ +- uint8_t platform_rev_id; +- +- /* +- * LVDS info +- */ +- int backlight_duty_cycle; /* restore backlight to this value */ +- bool panel_wants_dither; +- struct drm_display_mode *panel_fixed_mode; +- struct drm_display_mode *lfp_lvds_vbt_mode; +- struct drm_display_mode *sdvo_lvds_vbt_mode; +- +- struct bdb_lvds_backlight *lvds_bl; /* LVDS backlight info from VBT */ +- struct psb_intel_i2c_chan *lvds_i2c_bus; +- +- /* Feature bits from the VBIOS */ +- unsigned int int_tv_support:1; +- unsigned int lvds_dither:1; +- unsigned int lvds_vbt:1; +- unsigned int int_crt_support:1; +- unsigned int lvds_use_ssc:1; +- int lvds_ssc_freq; +- bool is_lvds_on; +- bool is_mipi_on; +- u32 mipi_ctrl_display; +- +- unsigned int core_freq; +- uint32_t iLVDS_enable; +- +- /* Runtime PM state */ +- int rpm_enabled; +- +- /* MID specific */ +- struct mrst_vbt vbt_data; +- struct mrst_gct_data gct_data; +- +- /* MIPI Panel type etc */ +- int panel_id; +- bool dual_mipi; /* dual display - DPI & DBI */ +- bool dpi_panel_on; /* The DPI panel power is on */ +- bool dpi_panel_on2; /* The DPI panel power is on */ +- bool dbi_panel_on; /* The DBI panel power is on */ +- bool dbi_panel_on2; /* The DBI panel power is on */ +- u32 dsr_fb_update; /* DSR FB update counter */ +- +- /* Moorestown HDMI state */ +- struct mrst_hdmi_dev *hdmi_priv; +- +- /* Moorestown pipe config register value cache */ +- uint32_t pipeconf; +- uint32_t pipeconf1; +- uint32_t pipeconf2; +- +- /* Moorestown plane control register value cache */ +- uint32_t dspcntr; +- uint32_t dspcntr1; +- uint32_t dspcntr2; +- +- /* Moorestown MM backlight cache */ +- uint8_t saveBKLTCNT; +- uint8_t saveBKLTREQ; +- uint8_t saveBKLTBRTL; +- +- /* +- * Register state +- */ +- uint32_t saveDSPACNTR; +- uint32_t saveDSPBCNTR; +- uint32_t savePIPEACONF; +- uint32_t savePIPEBCONF; +- uint32_t savePIPEASRC; +- uint32_t savePIPEBSRC; +- uint32_t saveFPA0; +- uint32_t saveFPA1; +- uint32_t saveDPLL_A; +- uint32_t saveDPLL_A_MD; +- uint32_t saveHTOTAL_A; +- uint32_t saveHBLANK_A; +- uint32_t saveHSYNC_A; +- uint32_t saveVTOTAL_A; +- uint32_t saveVBLANK_A; +- uint32_t saveVSYNC_A; +- uint32_t saveDSPASTRIDE; +- uint32_t saveDSPASIZE; +- uint32_t saveDSPAPOS; +- uint32_t saveDSPABASE; +- uint32_t saveDSPASURF; +- uint32_t saveDSPASTATUS; +- uint32_t saveFPB0; +- uint32_t saveFPB1; +- uint32_t saveDPLL_B; +- uint32_t saveDPLL_B_MD; +- uint32_t saveHTOTAL_B; +- uint32_t saveHBLANK_B; +- uint32_t saveHSYNC_B; +- uint32_t saveVTOTAL_B; +- uint32_t saveVBLANK_B; +- uint32_t saveVSYNC_B; +- uint32_t saveDSPBSTRIDE; +- uint32_t saveDSPBSIZE; +- uint32_t saveDSPBPOS; +- uint32_t saveDSPBBASE; +- uint32_t saveDSPBSURF; +- uint32_t saveDSPBSTATUS; +- uint32_t saveVCLK_DIVISOR_VGA0; +- uint32_t saveVCLK_DIVISOR_VGA1; +- uint32_t saveVCLK_POST_DIV; +- uint32_t saveVGACNTRL; +- uint32_t saveADPA; +- uint32_t saveLVDS; +- uint32_t saveDVOA; +- uint32_t saveDVOB; +- uint32_t saveDVOC; +- uint32_t savePP_ON; +- uint32_t savePP_OFF; +- uint32_t savePP_CONTROL; +- uint32_t savePP_CYCLE; +- uint32_t savePFIT_CONTROL; +- uint32_t savePaletteA[256]; +- uint32_t savePaletteB[256]; +- uint32_t saveBLC_PWM_CTL2; +- uint32_t saveBLC_PWM_CTL; +- uint32_t saveCLOCKGATING; +- uint32_t saveDSPARB; +- uint32_t saveDSPATILEOFF; +- uint32_t saveDSPBTILEOFF; +- uint32_t saveDSPAADDR; +- uint32_t saveDSPBADDR; +- uint32_t savePFIT_AUTO_RATIOS; +- uint32_t savePFIT_PGM_RATIOS; +- uint32_t savePP_ON_DELAYS; +- uint32_t savePP_OFF_DELAYS; +- uint32_t savePP_DIVISOR; +- uint32_t saveBSM; +- uint32_t saveVBT; +- uint32_t saveBCLRPAT_A; +- uint32_t saveBCLRPAT_B; +- uint32_t saveDSPALINOFF; +- uint32_t saveDSPBLINOFF; +- uint32_t savePERF_MODE; +- uint32_t saveDSPFW1; +- uint32_t saveDSPFW2; +- uint32_t saveDSPFW3; +- uint32_t saveDSPFW4; +- uint32_t saveDSPFW5; +- uint32_t saveDSPFW6; +- uint32_t saveCHICKENBIT; +- uint32_t saveDSPACURSOR_CTRL; +- uint32_t saveDSPBCURSOR_CTRL; +- uint32_t saveDSPACURSOR_BASE; +- uint32_t saveDSPBCURSOR_BASE; +- uint32_t saveDSPACURSOR_POS; +- uint32_t saveDSPBCURSOR_POS; +- uint32_t save_palette_a[256]; +- uint32_t save_palette_b[256]; +- uint32_t saveOV_OVADD; +- uint32_t saveOV_OGAMC0; +- uint32_t saveOV_OGAMC1; +- uint32_t saveOV_OGAMC2; +- uint32_t saveOV_OGAMC3; +- uint32_t saveOV_OGAMC4; +- uint32_t saveOV_OGAMC5; +- uint32_t saveOVC_OVADD; +- uint32_t saveOVC_OGAMC0; +- uint32_t saveOVC_OGAMC1; +- uint32_t saveOVC_OGAMC2; +- uint32_t saveOVC_OGAMC3; +- uint32_t saveOVC_OGAMC4; +- uint32_t saveOVC_OGAMC5; +- +- /* MSI reg save */ +- uint32_t msi_addr; +- uint32_t msi_data; +- +- /* Medfield specific register save state */ +- uint32_t saveHDMIPHYMISCCTL; +- uint32_t saveHDMIB_CONTROL; +- uint32_t saveDSPCCNTR; +- uint32_t savePIPECCONF; +- uint32_t savePIPECSRC; +- uint32_t saveHTOTAL_C; +- uint32_t saveHBLANK_C; +- uint32_t saveHSYNC_C; +- uint32_t saveVTOTAL_C; +- uint32_t saveVBLANK_C; +- uint32_t saveVSYNC_C; +- uint32_t saveDSPCSTRIDE; +- uint32_t saveDSPCSIZE; +- uint32_t saveDSPCPOS; +- uint32_t saveDSPCSURF; +- uint32_t saveDSPCSTATUS; +- uint32_t saveDSPCLINOFF; +- uint32_t saveDSPCTILEOFF; +- uint32_t saveDSPCCURSOR_CTRL; +- uint32_t saveDSPCCURSOR_BASE; +- uint32_t saveDSPCCURSOR_POS; +- uint32_t save_palette_c[256]; +- uint32_t saveOV_OVADD_C; +- uint32_t saveOV_OGAMC0_C; +- uint32_t saveOV_OGAMC1_C; +- uint32_t saveOV_OGAMC2_C; +- uint32_t saveOV_OGAMC3_C; +- uint32_t saveOV_OGAMC4_C; +- uint32_t saveOV_OGAMC5_C; +- +- /* DSI register save */ +- uint32_t saveDEVICE_READY_REG; +- uint32_t saveINTR_EN_REG; +- uint32_t saveDSI_FUNC_PRG_REG; +- uint32_t saveHS_TX_TIMEOUT_REG; +- uint32_t saveLP_RX_TIMEOUT_REG; +- uint32_t saveTURN_AROUND_TIMEOUT_REG; +- uint32_t saveDEVICE_RESET_REG; +- uint32_t saveDPI_RESOLUTION_REG; +- uint32_t saveHORIZ_SYNC_PAD_COUNT_REG; +- uint32_t saveHORIZ_BACK_PORCH_COUNT_REG; +- uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG; +- uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG; +- uint32_t saveVERT_SYNC_PAD_COUNT_REG; +- uint32_t saveVERT_BACK_PORCH_COUNT_REG; +- uint32_t saveVERT_FRONT_PORCH_COUNT_REG; +- uint32_t saveHIGH_LOW_SWITCH_COUNT_REG; +- uint32_t saveINIT_COUNT_REG; +- uint32_t saveMAX_RET_PAK_REG; +- uint32_t saveVIDEO_FMT_REG; +- uint32_t saveEOT_DISABLE_REG; +- uint32_t saveLP_BYTECLK_REG; +- uint32_t saveHS_LS_DBI_ENABLE_REG; +- uint32_t saveTXCLKESC_REG; +- uint32_t saveDPHY_PARAM_REG; +- uint32_t saveMIPI_CONTROL_REG; +- uint32_t saveMIPI; +- uint32_t saveMIPI_C; +- +- /* DPST register save */ +- uint32_t saveHISTOGRAM_INT_CONTROL_REG; +- uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG; +- uint32_t savePWM_CONTROL_LOGIC; +- +- /* +- * DSI info. +- */ +- void * dbi_dsr_info; +- void * dbi_dpu_info; +- void * dsi_configs[2]; +- /* +- * LID-Switch +- */ +- spinlock_t lid_lock; +- struct timer_list lid_timer; +- struct psb_intel_opregion opregion; +- u32 *lid_state; +- u32 lid_last_state; +- +- /* +- * Watchdog +- */ +- +- uint32_t apm_reg; +- uint16_t apm_base; +- +- /* +- * Used for modifying backlight from +- * xrandr -- consider removing and using HAL instead +- */ +- struct backlight_device *backlight_device; +- struct drm_property *backlight_property; +- uint32_t blc_adj1; +- uint32_t blc_adj2; +- +- void *fbdev; +- /* DPST state */ +- uint32_t dsr_idle_count; +- bool is_in_idle; +- bool dsr_enable; +- void (*exit_idle)(struct drm_device *dev, u32 update_src); +- +- /* 2D acceleration */ +- spinlock_t lock_2d; +- +- /* FIXME: Arrays anyone ? */ +- struct mdfld_dsi_encoder *encoder0; +- struct mdfld_dsi_encoder *encoder2; +- struct mdfld_dsi_dbi_output * dbi_output; +- struct mdfld_dsi_dbi_output * dbi_output2; +- u32 bpp; +- u32 bpp2; +- +- bool dispstatus; +-}; +- +- +-/* +- * Operations for each board type +- */ +- +-struct psb_ops { +- const char *name; +- unsigned int accel_2d:1; +- int pipes; /* Number of output pipes */ +- int crtcs; /* Number of CRTCs */ +- int sgx_offset; /* Base offset of SGX device */ +- +- /* Sub functions */ +- struct drm_crtc_helper_funcs const *crtc_helper; +- struct drm_crtc_funcs const *crtc_funcs; +- +- /* Setup hooks */ +- int (*chip_setup)(struct drm_device *dev); +- void (*chip_teardown)(struct drm_device *dev); +- +- /* Display management hooks */ +- int (*output_init)(struct drm_device *dev); +- /* Power management hooks */ +- void (*init_pm)(struct drm_device *dev); +- int (*save_regs)(struct drm_device *dev); +- int (*restore_regs)(struct drm_device *dev); +- int (*power_up)(struct drm_device *dev); +- int (*power_down)(struct drm_device *dev); +- +- void (*lvds_bl_power)(struct drm_device *dev, bool on); +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- /* Backlight */ +- int (*backlight_init)(struct drm_device *dev); +-#endif +- int i2c_bus; /* I2C bus identifier for Moorestown */ +-}; +- +- +- +-struct psb_mmu_driver; +- +-extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int); +-extern int drm_pick_crtcs(struct drm_device *dev); +- +-static inline struct drm_psb_private *psb_priv(struct drm_device *dev) +-{ +- return (struct drm_psb_private *) dev->dev_private; +-} +- +-/* +- * MMU stuff. +- */ +- +-extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers, +- int trap_pagefaults, +- int invalid_type, +- struct drm_psb_private *dev_priv); +-extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver); +-extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver +- *driver); +-extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset, +- uint32_t gtt_start, uint32_t gtt_pages); +-extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver, +- int trap_pagefaults, +- int invalid_type); +-extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd); +-extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot); +-extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd, +- unsigned long address, +- uint32_t num_pages); +-extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, +- uint32_t start_pfn, +- unsigned long address, +- uint32_t num_pages, int type); +-extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual, +- unsigned long *pfn); +- +-/* +- * Enable / disable MMU for different requestors. +- */ +- +- +-extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context); +-extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages, +- unsigned long address, uint32_t num_pages, +- uint32_t desired_tile_stride, +- uint32_t hw_tile_stride, int type); +-extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd, +- unsigned long address, uint32_t num_pages, +- uint32_t desired_tile_stride, +- uint32_t hw_tile_stride); +-/* +- *psb_irq.c +- */ +- +-extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS); +-extern int psb_irq_enable_dpst(struct drm_device *dev); +-extern int psb_irq_disable_dpst(struct drm_device *dev); +-extern void psb_irq_preinstall(struct drm_device *dev); +-extern int psb_irq_postinstall(struct drm_device *dev); +-extern void psb_irq_uninstall(struct drm_device *dev); +-extern void psb_irq_turn_on_dpst(struct drm_device *dev); +-extern void psb_irq_turn_off_dpst(struct drm_device *dev); +- +-extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands); +-extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence); +-extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence); +-extern int psb_enable_vblank(struct drm_device *dev, int crtc); +-extern void psb_disable_vblank(struct drm_device *dev, int crtc); +-void +-psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); +- +-void +-psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); +- +-extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc); +- +-extern int mdfld_enable_te(struct drm_device *dev, int pipe); +-extern void mdfld_disable_te(struct drm_device *dev, int pipe); +- +-/* +- * intel_opregion.c +- */ +-extern int gma_intel_opregion_init(struct drm_device *dev); +-extern int gma_intel_opregion_exit(struct drm_device *dev); +- +-/* +- * framebuffer.c +- */ +-extern int psbfb_probed(struct drm_device *dev); +-extern int psbfb_remove(struct drm_device *dev, +- struct drm_framebuffer *fb); +-/* +- * accel_2d.c +- */ +-extern void psbfb_copyarea(struct fb_info *info, +- const struct fb_copyarea *region); +-extern int psbfb_sync(struct fb_info *info); +-extern void psb_spank(struct drm_psb_private *dev_priv); +-extern int psb_accel_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file); +- +-/* +- * psb_reset.c +- */ +- +-extern void psb_lid_timer_init(struct drm_psb_private *dev_priv); +-extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv); +-extern void psb_print_pagefault(struct drm_psb_private *dev_priv); +- +-/* modesetting */ +-extern void psb_modeset_init(struct drm_device *dev); +-extern void psb_modeset_cleanup(struct drm_device *dev); +-extern int psb_fbdev_init(struct drm_device *dev); +- +-/* backlight.c */ +-int gma_backlight_init(struct drm_device *dev); +-void gma_backlight_exit(struct drm_device *dev); +- +-/* mrst_crtc.c */ +-extern const struct drm_crtc_helper_funcs mrst_helper_funcs; +- +-/* mrst_lvds.c */ +-extern void mrst_lvds_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev); +- +-/* psb_intel_display.c */ +-extern const struct drm_crtc_helper_funcs psb_intel_helper_funcs; +-extern const struct drm_crtc_funcs psb_intel_crtc_funcs; +- +-/* psb_intel_lvds.c */ +-extern const struct drm_connector_helper_funcs +- psb_intel_lvds_connector_helper_funcs; +-extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs; +- +-/* gem.c */ +-extern int psb_gem_init_object(struct drm_gem_object *obj); +-extern void psb_gem_free_object(struct drm_gem_object *obj); +-extern int psb_gem_get_aperture(struct drm_device *dev, void *data, +- struct drm_file *file); +-extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev, +- struct drm_mode_create_dumb *args); +-extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, +- uint32_t handle); +-extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, +- uint32_t handle, uint64_t *offset); +-extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); +-extern int psb_gem_create_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file); +-extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data, +- struct drm_file *file); +- +-/* psb_device.c */ +-extern const struct psb_ops psb_chip_ops; +- +-/* mrst_device.c */ +-extern const struct psb_ops mrst_chip_ops; +- +-/* mdfld_device.c */ +-extern const struct psb_ops mdfld_chip_ops; +- +-/* cdv_device.c */ +-extern const struct psb_ops cdv_chip_ops; +- +-/* +- * Debug print bits setting +- */ +-#define PSB_D_GENERAL (1 << 0) +-#define PSB_D_INIT (1 << 1) +-#define PSB_D_IRQ (1 << 2) +-#define PSB_D_ENTRY (1 << 3) +-/* debug the get H/V BP/FP count */ +-#define PSB_D_HV (1 << 4) +-#define PSB_D_DBI_BF (1 << 5) +-#define PSB_D_PM (1 << 6) +-#define PSB_D_RENDER (1 << 7) +-#define PSB_D_REG (1 << 8) +-#define PSB_D_MSVDX (1 << 9) +-#define PSB_D_TOPAZ (1 << 10) +- +-extern int drm_psb_no_fb; +-extern int drm_idle_check_interval; +- +-/* +- * Utilities +- */ +- +-static inline u32 MRST_MSG_READ32(uint port, uint offset) +-{ +- int mcr = (0xD0<<24) | (port << 16) | (offset << 8); +- uint32_t ret_val = 0; +- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); +- pci_write_config_dword(pci_root, 0xD0, mcr); +- pci_read_config_dword(pci_root, 0xD4, &ret_val); +- pci_dev_put(pci_root); +- return ret_val; +-} +-static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value) +-{ +- int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0; +- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); +- pci_write_config_dword(pci_root, 0xD4, value); +- pci_write_config_dword(pci_root, 0xD0, mcr); +- pci_dev_put(pci_root); +-} +-static inline u32 MDFLD_MSG_READ32(uint port, uint offset) +-{ +- int mcr = (0x10<<24) | (port << 16) | (offset << 8); +- uint32_t ret_val = 0; +- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); +- pci_write_config_dword(pci_root, 0xD0, mcr); +- pci_read_config_dword(pci_root, 0xD4, &ret_val); +- pci_dev_put(pci_root); +- return ret_val; +-} +-static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value) +-{ +- int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; +- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); +- pci_write_config_dword(pci_root, 0xD4, value); +- pci_write_config_dword(pci_root, 0xD0, mcr); +- pci_dev_put(pci_root); +-} +- +-static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- return ioread32(dev_priv->vdc_reg + reg); +-} +- +-#define REG_READ(reg) REGISTER_READ(dev, (reg)) +- +-static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg, +- uint32_t val) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- iowrite32((val), dev_priv->vdc_reg + (reg)); +-} +- +-#define REG_WRITE(reg, val) REGISTER_WRITE(dev, (reg), (val)) +- +-static inline void REGISTER_WRITE16(struct drm_device *dev, +- uint32_t reg, uint32_t val) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- iowrite16((val), dev_priv->vdc_reg + (reg)); +-} +- +-#define REG_WRITE16(reg, val) REGISTER_WRITE16(dev, (reg), (val)) +- +-static inline void REGISTER_WRITE8(struct drm_device *dev, +- uint32_t reg, uint32_t val) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- iowrite8((val), dev_priv->vdc_reg + (reg)); +-} +- +-#define REG_WRITE8(reg, val) REGISTER_WRITE8(dev, (reg), (val)) +- +-#define PSB_WVDC32(_val, _offs) iowrite32(_val, dev_priv->vdc_reg + (_offs)) +-#define PSB_RVDC32(_offs) ioread32(dev_priv->vdc_reg + (_offs)) +- +-/* #define TRAP_SGX_PM_FAULT 1 */ +-#ifdef TRAP_SGX_PM_FAULT +-#define PSB_RSGX32(_offs) \ +-({ \ +- if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) { \ +- printk(KERN_ERR \ +- "access sgx when it's off!! (READ) %s, %d\n", \ +- __FILE__, __LINE__); \ +- melay(1000); \ +- } \ +- ioread32(dev_priv->sgx_reg + (_offs)); \ +-}) +-#else +-#define PSB_RSGX32(_offs) ioread32(dev_priv->sgx_reg + (_offs)) +-#endif +-#define PSB_WSGX32(_val, _offs) iowrite32(_val, dev_priv->sgx_reg + (_offs)) +- +-#define MSVDX_REG_DUMP 0 +- +-#define PSB_WMSVDX32(_val, _offs) iowrite32(_val, dev_priv->msvdx_reg + (_offs)) +-#define PSB_RMSVDX32(_offs) ioread32(dev_priv->msvdx_reg + (_offs)) +- +-#endif +diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c +deleted file mode 100644 +index 0d872e9..0000000 +--- a/drivers/staging/gma500/psb_intel_display.c ++++ /dev/null +@@ -1,1443 +0,0 @@ +-/* +- * Copyright © 2006-2011 Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Eric Anholt +- */ +- +-#include +-#include +- +-#include +-#include "framebuffer.h" +-#include "psb_drv.h" +-#include "psb_intel_drv.h" +-#include "psb_intel_reg.h" +-#include "psb_intel_display.h" +-#include "power.h" +- +-#include "mdfld_output.h" +- +-struct psb_intel_clock_t { +- /* given values */ +- int n; +- int m1, m2; +- int p1, p2; +- /* derived values */ +- int dot; +- int vco; +- int m; +- int p; +-}; +- +-struct psb_intel_range_t { +- int min, max; +-}; +- +-struct psb_intel_p2_t { +- int dot_limit; +- int p2_slow, p2_fast; +-}; +- +-#define INTEL_P2_NUM 2 +- +-struct psb_intel_limit_t { +- struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1; +- struct psb_intel_p2_t p2; +-}; +- +-#define I8XX_DOT_MIN 25000 +-#define I8XX_DOT_MAX 350000 +-#define I8XX_VCO_MIN 930000 +-#define I8XX_VCO_MAX 1400000 +-#define I8XX_N_MIN 3 +-#define I8XX_N_MAX 16 +-#define I8XX_M_MIN 96 +-#define I8XX_M_MAX 140 +-#define I8XX_M1_MIN 18 +-#define I8XX_M1_MAX 26 +-#define I8XX_M2_MIN 6 +-#define I8XX_M2_MAX 16 +-#define I8XX_P_MIN 4 +-#define I8XX_P_MAX 128 +-#define I8XX_P1_MIN 2 +-#define I8XX_P1_MAX 33 +-#define I8XX_P1_LVDS_MIN 1 +-#define I8XX_P1_LVDS_MAX 6 +-#define I8XX_P2_SLOW 4 +-#define I8XX_P2_FAST 2 +-#define I8XX_P2_LVDS_SLOW 14 +-#define I8XX_P2_LVDS_FAST 14 /* No fast option */ +-#define I8XX_P2_SLOW_LIMIT 165000 +- +-#define I9XX_DOT_MIN 20000 +-#define I9XX_DOT_MAX 400000 +-#define I9XX_VCO_MIN 1400000 +-#define I9XX_VCO_MAX 2800000 +-#define I9XX_N_MIN 3 +-#define I9XX_N_MAX 8 +-#define I9XX_M_MIN 70 +-#define I9XX_M_MAX 120 +-#define I9XX_M1_MIN 10 +-#define I9XX_M1_MAX 20 +-#define I9XX_M2_MIN 5 +-#define I9XX_M2_MAX 9 +-#define I9XX_P_SDVO_DAC_MIN 5 +-#define I9XX_P_SDVO_DAC_MAX 80 +-#define I9XX_P_LVDS_MIN 7 +-#define I9XX_P_LVDS_MAX 98 +-#define I9XX_P1_MIN 1 +-#define I9XX_P1_MAX 8 +-#define I9XX_P2_SDVO_DAC_SLOW 10 +-#define I9XX_P2_SDVO_DAC_FAST 5 +-#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000 +-#define I9XX_P2_LVDS_SLOW 14 +-#define I9XX_P2_LVDS_FAST 7 +-#define I9XX_P2_LVDS_SLOW_LIMIT 112000 +- +-#define INTEL_LIMIT_I8XX_DVO_DAC 0 +-#define INTEL_LIMIT_I8XX_LVDS 1 +-#define INTEL_LIMIT_I9XX_SDVO_DAC 2 +-#define INTEL_LIMIT_I9XX_LVDS 3 +- +-static const struct psb_intel_limit_t psb_intel_limits[] = { +- { /* INTEL_LIMIT_I8XX_DVO_DAC */ +- .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, +- .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, +- .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, +- .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, +- .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, +- .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, +- .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, +- .p1 = {.min = I8XX_P1_MIN, .max = I8XX_P1_MAX}, +- .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, +- .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST}, +- }, +- { /* INTEL_LIMIT_I8XX_LVDS */ +- .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, +- .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, +- .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, +- .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, +- .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, +- .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, +- .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, +- .p1 = {.min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX}, +- .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, +- .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST}, +- }, +- { /* INTEL_LIMIT_I9XX_SDVO_DAC */ +- .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, +- .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, +- .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, +- .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, +- .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, +- .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, +- .p = {.min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX}, +- .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, +- .p2 = {.dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, +- .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = +- I9XX_P2_SDVO_DAC_FAST}, +- }, +- { /* INTEL_LIMIT_I9XX_LVDS */ +- .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, +- .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, +- .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, +- .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, +- .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, +- .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, +- .p = {.min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX}, +- .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, +- /* The single-channel range is 25-112Mhz, and dual-channel +- * is 80-224Mhz. Prefer single channel as much as possible. +- */ +- .p2 = {.dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, +- .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST}, +- }, +-}; +- +-static const struct psb_intel_limit_t *psb_intel_limit(struct drm_crtc *crtc) +-{ +- const struct psb_intel_limit_t *limit; +- +- if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) +- limit = &psb_intel_limits[INTEL_LIMIT_I9XX_LVDS]; +- else +- limit = &psb_intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; +- return limit; +-} +- +-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ +- +-static void i8xx_clock(int refclk, struct psb_intel_clock_t *clock) +-{ +- clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); +- clock->p = clock->p1 * clock->p2; +- clock->vco = refclk * clock->m / (clock->n + 2); +- clock->dot = clock->vco / clock->p; +-} +- +-/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ +- +-static void i9xx_clock(int refclk, struct psb_intel_clock_t *clock) +-{ +- clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); +- clock->p = clock->p1 * clock->p2; +- clock->vco = refclk * clock->m / (clock->n + 2); +- clock->dot = clock->vco / clock->p; +-} +- +-static void psb_intel_clock(struct drm_device *dev, int refclk, +- struct psb_intel_clock_t *clock) +-{ +- return i9xx_clock(refclk, clock); +-} +- +-/** +- * Returns whether any output on the specified pipe is of the specified type +- */ +-bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type) +-{ +- struct drm_device *dev = crtc->dev; +- struct drm_mode_config *mode_config = &dev->mode_config; +- struct drm_connector *l_entry; +- +- list_for_each_entry(l_entry, &mode_config->connector_list, head) { +- if (l_entry->encoder && l_entry->encoder->crtc == crtc) { +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(l_entry); +- if (psb_intel_output->type == type) +- return true; +- } +- } +- return false; +-} +- +-#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } +-/** +- * Returns whether the given set of divisors are valid for a given refclk with +- * the given connectors. +- */ +- +-static bool psb_intel_PLL_is_valid(struct drm_crtc *crtc, +- struct psb_intel_clock_t *clock) +-{ +- const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); +- +- if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) +- INTELPllInvalid("p1 out of range\n"); +- if (clock->p < limit->p.min || limit->p.max < clock->p) +- INTELPllInvalid("p out of range\n"); +- if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) +- INTELPllInvalid("m2 out of range\n"); +- if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) +- INTELPllInvalid("m1 out of range\n"); +- if (clock->m1 <= clock->m2) +- INTELPllInvalid("m1 <= m2\n"); +- if (clock->m < limit->m.min || limit->m.max < clock->m) +- INTELPllInvalid("m out of range\n"); +- if (clock->n < limit->n.min || limit->n.max < clock->n) +- INTELPllInvalid("n out of range\n"); +- if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) +- INTELPllInvalid("vco out of range\n"); +- /* XXX: We may need to be checking "Dot clock" +- * depending on the multiplier, connector, etc., +- * rather than just a single range. +- */ +- if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) +- INTELPllInvalid("dot out of range\n"); +- +- return true; +-} +- +-/** +- * Returns a set of divisors for the desired target clock with the given +- * refclk, or FALSE. The returned values represent the clock equation: +- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. +- */ +-static bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target, +- int refclk, +- struct psb_intel_clock_t *best_clock) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_clock_t clock; +- const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); +- int err = target; +- +- if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && +- (REG_READ(LVDS) & LVDS_PORT_EN) != 0) { +- /* +- * For LVDS, if the panel is on, just rely on its current +- * settings for dual-channel. We haven't figured out how to +- * reliably set up different single/dual channel state, if we +- * even can. +- */ +- if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) == +- LVDS_CLKB_POWER_UP) +- clock.p2 = limit->p2.p2_fast; +- else +- clock.p2 = limit->p2.p2_slow; +- } else { +- if (target < limit->p2.dot_limit) +- clock.p2 = limit->p2.p2_slow; +- else +- clock.p2 = limit->p2.p2_fast; +- } +- +- memset(best_clock, 0, sizeof(*best_clock)); +- +- for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; +- clock.m1++) { +- for (clock.m2 = limit->m2.min; +- clock.m2 < clock.m1 && clock.m2 <= limit->m2.max; +- clock.m2++) { +- for (clock.n = limit->n.min; +- clock.n <= limit->n.max; clock.n++) { +- for (clock.p1 = limit->p1.min; +- clock.p1 <= limit->p1.max; +- clock.p1++) { +- int this_err; +- +- psb_intel_clock(dev, refclk, &clock); +- +- if (!psb_intel_PLL_is_valid +- (crtc, &clock)) +- continue; +- +- this_err = abs(clock.dot - target); +- if (this_err < err) { +- *best_clock = clock; +- err = this_err; +- } +- } +- } +- } +- } +- +- return err != target; +-} +- +-void psb_intel_wait_for_vblank(struct drm_device *dev) +-{ +- /* Wait for 20ms, i.e. one cycle at 50hz. */ +- mdelay(20); +-} +- +-int psb_intel_pipe_set_base(struct drm_crtc *crtc, +- int x, int y, struct drm_framebuffer *old_fb) +-{ +- struct drm_device *dev = crtc->dev; +- /* struct drm_i915_master_private *master_priv; */ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); +- int pipe = psb_intel_crtc->pipe; +- unsigned long start, offset; +- int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); +- int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); +- int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; +- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; +- u32 dspcntr; +- int ret = 0; +- +- if (!gma_power_begin(dev, true)) +- return 0; +- +- /* no fb bound */ +- if (!crtc->fb) { +- dev_dbg(dev->dev, "No FB bound\n"); +- goto psb_intel_pipe_cleaner; +- } +- +- /* We are displaying this buffer, make sure it is actually loaded +- into the GTT */ +- ret = psb_gtt_pin(psbfb->gtt); +- if (ret < 0) +- goto psb_intel_pipe_set_base_exit; +- start = psbfb->gtt->offset; +- +- offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); +- +- REG_WRITE(dspstride, crtc->fb->pitch); +- +- dspcntr = REG_READ(dspcntr_reg); +- dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; +- +- switch (crtc->fb->bits_per_pixel) { +- case 8: +- dspcntr |= DISPPLANE_8BPP; +- break; +- case 16: +- if (crtc->fb->depth == 15) +- dspcntr |= DISPPLANE_15_16BPP; +- else +- dspcntr |= DISPPLANE_16BPP; +- break; +- case 24: +- case 32: +- dspcntr |= DISPPLANE_32BPP_NO_ALPHA; +- break; +- default: +- dev_err(dev->dev, "Unknown color depth\n"); +- ret = -EINVAL; +- psb_gtt_unpin(psbfb->gtt); +- goto psb_intel_pipe_set_base_exit; +- } +- REG_WRITE(dspcntr_reg, dspcntr); +- +- +- if (0 /* FIXMEAC - check what PSB needs */) { +- REG_WRITE(dspbase, offset); +- REG_READ(dspbase); +- REG_WRITE(dspsurf, start); +- REG_READ(dspsurf); +- } else { +- REG_WRITE(dspbase, start + offset); +- REG_READ(dspbase); +- } +- +-psb_intel_pipe_cleaner: +- /* If there was a previous display we can now unpin it */ +- if (old_fb) +- psb_gtt_unpin(to_psb_fb(old_fb)->gtt); +- +-psb_intel_pipe_set_base_exit: +- gma_power_end(dev); +- return ret; +-} +- +-/** +- * Sets the power management mode of the pipe and plane. +- * +- * This code should probably grow support for turning the cursor off and back +- * on appropriately at the same time as we're turning the pipe off/on. +- */ +-static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode) +-{ +- struct drm_device *dev = crtc->dev; +- /* struct drm_i915_master_private *master_priv; */ +- /* struct drm_i915_private *dev_priv = dev->dev_private; */ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; +- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; +- int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; +- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; +- u32 temp; +- bool enabled; +- +- /* XXX: When our outputs are all unaware of DPMS modes other than off +- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. +- */ +- switch (mode) { +- case DRM_MODE_DPMS_ON: +- case DRM_MODE_DPMS_STANDBY: +- case DRM_MODE_DPMS_SUSPEND: +- /* Enable the DPLL */ +- temp = REG_READ(dpll_reg); +- if ((temp & DPLL_VCO_ENABLE) == 0) { +- REG_WRITE(dpll_reg, temp); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- } +- +- /* Enable the pipe */ +- temp = REG_READ(pipeconf_reg); +- if ((temp & PIPEACONF_ENABLE) == 0) +- REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); +- +- /* Enable the plane */ +- temp = REG_READ(dspcntr_reg); +- if ((temp & DISPLAY_PLANE_ENABLE) == 0) { +- REG_WRITE(dspcntr_reg, +- temp | DISPLAY_PLANE_ENABLE); +- /* Flush the plane changes */ +- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); +- } +- +- psb_intel_crtc_load_lut(crtc); +- +- /* Give the overlay scaler a chance to enable +- * if it's on this pipe */ +- /* psb_intel_crtc_dpms_video(crtc, true); TODO */ +- break; +- case DRM_MODE_DPMS_OFF: +- /* Give the overlay scaler a chance to disable +- * if it's on this pipe */ +- /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ +- +- /* Disable the VGA plane that we never use */ +- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); +- +- /* Disable display plane */ +- temp = REG_READ(dspcntr_reg); +- if ((temp & DISPLAY_PLANE_ENABLE) != 0) { +- REG_WRITE(dspcntr_reg, +- temp & ~DISPLAY_PLANE_ENABLE); +- /* Flush the plane changes */ +- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); +- REG_READ(dspbase_reg); +- } +- +- /* Next, disable display pipes */ +- temp = REG_READ(pipeconf_reg); +- if ((temp & PIPEACONF_ENABLE) != 0) { +- REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); +- REG_READ(pipeconf_reg); +- } +- +- /* Wait for vblank for the disable to take effect. */ +- psb_intel_wait_for_vblank(dev); +- +- temp = REG_READ(dpll_reg); +- if ((temp & DPLL_VCO_ENABLE) != 0) { +- REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- } +- +- /* Wait for the clocks to turn off. */ +- udelay(150); +- break; +- } +- +- enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; +- +- /*Set FIFO Watermarks*/ +- REG_WRITE(DSPARB, 0x3F3E); +-} +- +-static void psb_intel_crtc_prepare(struct drm_crtc *crtc) +-{ +- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); +-} +- +-static void psb_intel_crtc_commit(struct drm_crtc *crtc) +-{ +- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); +-} +- +-void psb_intel_encoder_prepare(struct drm_encoder *encoder) +-{ +- struct drm_encoder_helper_funcs *encoder_funcs = +- encoder->helper_private; +- /* lvds has its own version of prepare see psb_intel_lvds_prepare */ +- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); +-} +- +-void psb_intel_encoder_commit(struct drm_encoder *encoder) +-{ +- struct drm_encoder_helper_funcs *encoder_funcs = +- encoder->helper_private; +- /* lvds has its own version of commit see psb_intel_lvds_commit */ +- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); +-} +- +-static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- return true; +-} +- +- +-/** +- * Return the pipe currently connected to the panel fitter, +- * or -1 if the panel fitter is not present or not in use +- */ +-static int psb_intel_panel_fitter_pipe(struct drm_device *dev) +-{ +- u32 pfit_control; +- +- pfit_control = REG_READ(PFIT_CONTROL); +- +- /* See if the panel fitter is in use */ +- if ((pfit_control & PFIT_ENABLE) == 0) +- return -1; +- /* Must be on PIPE 1 for PSB */ +- return 1; +-} +- +-static int psb_intel_crtc_mode_set(struct drm_crtc *crtc, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode, +- int x, int y, +- struct drm_framebuffer *old_fb) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +- int pipe = psb_intel_crtc->pipe; +- int fp_reg = (pipe == 0) ? FPA0 : FPB0; +- int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; +- int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; +- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; +- int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; +- int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; +- int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; +- int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; +- int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; +- int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; +- int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; +- int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; +- int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; +- int refclk; +- struct psb_intel_clock_t clock; +- u32 dpll = 0, fp = 0, dspcntr, pipeconf; +- bool ok, is_sdvo = false, is_dvo = false; +- bool is_crt = false, is_lvds = false, is_tv = false; +- struct drm_mode_config *mode_config = &dev->mode_config; +- struct drm_connector *connector; +- +- /* No scan out no play */ +- if (crtc->fb == NULL) { +- crtc_funcs->mode_set_base(crtc, x, y, old_fb); +- return 0; +- } +- +- list_for_each_entry(connector, &mode_config->connector_list, head) { +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- +- if (!connector->encoder +- || connector->encoder->crtc != crtc) +- continue; +- +- switch (psb_intel_output->type) { +- case INTEL_OUTPUT_LVDS: +- is_lvds = true; +- break; +- case INTEL_OUTPUT_SDVO: +- is_sdvo = true; +- break; +- case INTEL_OUTPUT_DVO: +- is_dvo = true; +- break; +- case INTEL_OUTPUT_TVOUT: +- is_tv = true; +- break; +- case INTEL_OUTPUT_ANALOG: +- is_crt = true; +- break; +- } +- } +- +- refclk = 96000; +- +- ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, +- &clock); +- if (!ok) { +- dev_err(dev->dev, "Couldn't find PLL settings for mode!\n"); +- return 0; +- } +- +- fp = clock.n << 16 | clock.m1 << 8 | clock.m2; +- +- dpll = DPLL_VGA_MODE_DIS; +- if (is_lvds) { +- dpll |= DPLLB_MODE_LVDS; +- dpll |= DPLL_DVO_HIGH_SPEED; +- } else +- dpll |= DPLLB_MODE_DAC_SERIAL; +- if (is_sdvo) { +- int sdvo_pixel_multiply = +- adjusted_mode->clock / mode->clock; +- dpll |= DPLL_DVO_HIGH_SPEED; +- dpll |= +- (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; +- } +- +- /* compute bitmask from p1 value */ +- dpll |= (1 << (clock.p1 - 1)) << 16; +- switch (clock.p2) { +- case 5: +- dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; +- break; +- case 7: +- dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; +- break; +- case 10: +- dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; +- break; +- case 14: +- dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; +- break; +- } +- +- if (is_tv) { +- /* XXX: just matching BIOS for now */ +-/* dpll |= PLL_REF_INPUT_TVCLKINBC; */ +- dpll |= 3; +- } +- dpll |= PLL_REF_INPUT_DREFCLK; +- +- /* setup pipeconf */ +- pipeconf = REG_READ(pipeconf_reg); +- +- /* Set up the display plane register */ +- dspcntr = DISPPLANE_GAMMA_ENABLE; +- +- if (pipe == 0) +- dspcntr |= DISPPLANE_SEL_PIPE_A; +- else +- dspcntr |= DISPPLANE_SEL_PIPE_B; +- +- dspcntr |= DISPLAY_PLANE_ENABLE; +- pipeconf |= PIPEACONF_ENABLE; +- dpll |= DPLL_VCO_ENABLE; +- +- +- /* Disable the panel fitter if it was on our pipe */ +- if (psb_intel_panel_fitter_pipe(dev) == pipe) +- REG_WRITE(PFIT_CONTROL, 0); +- +- drm_mode_debug_printmodeline(mode); +- +- if (dpll & DPLL_VCO_ENABLE) { +- REG_WRITE(fp_reg, fp); +- REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); +- REG_READ(dpll_reg); +- udelay(150); +- } +- +- /* The LVDS pin pair needs to be on before the DPLLs are enabled. +- * This is an exception to the general rule that mode_set doesn't turn +- * things on. +- */ +- if (is_lvds) { +- u32 lvds = REG_READ(LVDS); +- +- lvds &= ~LVDS_PIPEB_SELECT; +- if (pipe == 1) +- lvds |= LVDS_PIPEB_SELECT; +- +- lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; +- /* Set the B0-B3 data pairs corresponding to +- * whether we're going to +- * set the DPLLs for dual-channel mode or not. +- */ +- lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); +- if (clock.p2 == 7) +- lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; +- +- /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) +- * appropriately here, but we need to look more +- * thoroughly into how panels behave in the two modes. +- */ +- +- REG_WRITE(LVDS, lvds); +- REG_READ(LVDS); +- } +- +- REG_WRITE(fp_reg, fp); +- REG_WRITE(dpll_reg, dpll); +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- +- /* write it again -- the BIOS does, after all */ +- REG_WRITE(dpll_reg, dpll); +- +- REG_READ(dpll_reg); +- /* Wait for the clocks to stabilize. */ +- udelay(150); +- +- REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | +- ((adjusted_mode->crtc_htotal - 1) << 16)); +- REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | +- ((adjusted_mode->crtc_hblank_end - 1) << 16)); +- REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | +- ((adjusted_mode->crtc_hsync_end - 1) << 16)); +- REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | +- ((adjusted_mode->crtc_vtotal - 1) << 16)); +- REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | +- ((adjusted_mode->crtc_vblank_end - 1) << 16)); +- REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | +- ((adjusted_mode->crtc_vsync_end - 1) << 16)); +- /* pipesrc and dspsize control the size that is scaled from, +- * which should always be the user's requested size. +- */ +- REG_WRITE(dspsize_reg, +- ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); +- REG_WRITE(dsppos_reg, 0); +- REG_WRITE(pipesrc_reg, +- ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); +- REG_WRITE(pipeconf_reg, pipeconf); +- REG_READ(pipeconf_reg); +- +- psb_intel_wait_for_vblank(dev); +- +- REG_WRITE(dspcntr_reg, dspcntr); +- +- /* Flush the plane changes */ +- crtc_funcs->mode_set_base(crtc, x, y, old_fb); +- +- psb_intel_wait_for_vblank(dev); +- +- return 0; +-} +- +-/** Loads the palette/gamma unit for the CRTC with the prepared values */ +-void psb_intel_crtc_load_lut(struct drm_crtc *crtc) +-{ +- struct drm_device *dev = crtc->dev; +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *)dev->dev_private; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int palreg = PALETTE_A; +- int i; +- +- /* The clocks have to be on to load the palette. */ +- if (!crtc->enabled) +- return; +- +- switch (psb_intel_crtc->pipe) { +- case 0: +- break; +- case 1: +- palreg = PALETTE_B; +- break; +- case 2: +- palreg = PALETTE_C; +- break; +- default: +- dev_err(dev->dev, "Illegal Pipe Number.\n"); +- return; +- } +- +- if (gma_power_begin(dev, false)) { +- for (i = 0; i < 256; i++) { +- REG_WRITE(palreg + 4 * i, +- ((psb_intel_crtc->lut_r[i] + +- psb_intel_crtc->lut_adj[i]) << 16) | +- ((psb_intel_crtc->lut_g[i] + +- psb_intel_crtc->lut_adj[i]) << 8) | +- (psb_intel_crtc->lut_b[i] + +- psb_intel_crtc->lut_adj[i])); +- } +- gma_power_end(dev); +- } else { +- for (i = 0; i < 256; i++) { +- dev_priv->save_palette_a[i] = +- ((psb_intel_crtc->lut_r[i] + +- psb_intel_crtc->lut_adj[i]) << 16) | +- ((psb_intel_crtc->lut_g[i] + +- psb_intel_crtc->lut_adj[i]) << 8) | +- (psb_intel_crtc->lut_b[i] + +- psb_intel_crtc->lut_adj[i]); +- } +- +- } +-} +- +-/** +- * Save HW states of giving crtc +- */ +-static void psb_intel_crtc_save(struct drm_crtc *crtc) +-{ +- struct drm_device *dev = crtc->dev; +- /* struct drm_psb_private *dev_priv = +- (struct drm_psb_private *)dev->dev_private; */ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; +- int pipeA = (psb_intel_crtc->pipe == 0); +- uint32_t paletteReg; +- int i; +- +- if (!crtc_state) { +- dev_err(dev->dev, "No CRTC state found\n"); +- return; +- } +- +- crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR); +- crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF); +- crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC); +- crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0); +- crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1); +- crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B); +- crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B); +- crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B); +- crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B); +- crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B); +- crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B); +- crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B); +- crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE); +- +- /*NOTE: DSPSIZE DSPPOS only for psb*/ +- crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE); +- crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS); +- +- crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE); +- +- paletteReg = pipeA ? PALETTE_A : PALETTE_B; +- for (i = 0; i < 256; ++i) +- crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2)); +-} +- +-/** +- * Restore HW states of giving crtc +- */ +-static void psb_intel_crtc_restore(struct drm_crtc *crtc) +-{ +- struct drm_device *dev = crtc->dev; +- /* struct drm_psb_private * dev_priv = +- (struct drm_psb_private *)dev->dev_private; */ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; +- /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */ +- int pipeA = (psb_intel_crtc->pipe == 0); +- uint32_t paletteReg; +- int i; +- +- if (!crtc_state) { +- dev_err(dev->dev, "No crtc state\n"); +- return; +- } +- +- if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) { +- REG_WRITE(pipeA ? DPLL_A : DPLL_B, +- crtc_state->saveDPLL & ~DPLL_VCO_ENABLE); +- REG_READ(pipeA ? DPLL_A : DPLL_B); +- udelay(150); +- } +- +- REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0); +- REG_READ(pipeA ? FPA0 : FPB0); +- +- REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1); +- REG_READ(pipeA ? FPA1 : FPB1); +- +- REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL); +- REG_READ(pipeA ? DPLL_A : DPLL_B); +- udelay(150); +- +- REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL); +- REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK); +- REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC); +- REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL); +- REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK); +- REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC); +- REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE); +- +- REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE); +- REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS); +- +- REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC); +- REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); +- REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF); +- +- psb_intel_wait_for_vblank(dev); +- +- REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR); +- REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); +- +- psb_intel_wait_for_vblank(dev); +- +- paletteReg = pipeA ? PALETTE_A : PALETTE_B; +- for (i = 0; i < 256; ++i) +- REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]); +-} +- +-static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, +- struct drm_file *file_priv, +- uint32_t handle, +- uint32_t width, uint32_t height) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; +- uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; +- uint32_t temp; +- size_t addr = 0; +- struct gtt_range *gt; +- struct drm_gem_object *obj; +- int ret; +- +- /* if we want to turn of the cursor ignore width and height */ +- if (!handle) { +- /* turn off the cursor */ +- temp = CURSOR_MODE_DISABLE; +- +- if (gma_power_begin(dev, false)) { +- REG_WRITE(control, temp); +- REG_WRITE(base, 0); +- gma_power_end(dev); +- } +- +- /* Unpin the old GEM object */ +- if (psb_intel_crtc->cursor_obj) { +- gt = container_of(psb_intel_crtc->cursor_obj, +- struct gtt_range, gem); +- psb_gtt_unpin(gt); +- drm_gem_object_unreference(psb_intel_crtc->cursor_obj); +- psb_intel_crtc->cursor_obj = NULL; +- } +- +- return 0; +- } +- +- /* Currently we only support 64x64 cursors */ +- if (width != 64 || height != 64) { +- dev_dbg(dev->dev, "we currently only support 64x64 cursors\n"); +- return -EINVAL; +- } +- +- obj = drm_gem_object_lookup(dev, file_priv, handle); +- if (!obj) +- return -ENOENT; +- +- if (obj->size < width * height * 4) { +- dev_dbg(dev->dev, "buffer is to small\n"); +- return -ENOMEM; +- } +- +- gt = container_of(obj, struct gtt_range, gem); +- +- /* Pin the memory into the GTT */ +- ret = psb_gtt_pin(gt); +- if (ret) { +- dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); +- return ret; +- } +- +- +- addr = gt->offset; /* Or resource.start ??? */ +- +- psb_intel_crtc->cursor_addr = addr; +- +- temp = 0; +- /* set the pipe for the cursor */ +- temp |= (pipe << 28); +- temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; +- +- if (gma_power_begin(dev, false)) { +- REG_WRITE(control, temp); +- REG_WRITE(base, addr); +- gma_power_end(dev); +- } +- +- /* unpin the old bo */ +- if (psb_intel_crtc->cursor_obj) { +- gt = container_of(psb_intel_crtc->cursor_obj, +- struct gtt_range, gem); +- psb_gtt_unpin(gt); +- drm_gem_object_unreference(psb_intel_crtc->cursor_obj); +- psb_intel_crtc->cursor_obj = obj; +- } +- return 0; +-} +- +-static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) +-{ +- struct drm_device *dev = crtc->dev; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- uint32_t temp = 0; +- uint32_t addr; +- +- +- if (x < 0) { +- temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); +- x = -x; +- } +- if (y < 0) { +- temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); +- y = -y; +- } +- +- temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); +- temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); +- +- addr = psb_intel_crtc->cursor_addr; +- +- if (gma_power_begin(dev, false)) { +- REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); +- REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr); +- gma_power_end(dev); +- } +- return 0; +-} +- +-void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, +- u16 *green, u16 *blue, uint32_t type, uint32_t size) +-{ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int i; +- +- if (size != 256) +- return; +- +- for (i = 0; i < 256; i++) { +- psb_intel_crtc->lut_r[i] = red[i] >> 8; +- psb_intel_crtc->lut_g[i] = green[i] >> 8; +- psb_intel_crtc->lut_b[i] = blue[i] >> 8; +- } +- +- psb_intel_crtc_load_lut(crtc); +-} +- +-static int psb_crtc_set_config(struct drm_mode_set *set) +-{ +- int ret; +- struct drm_device *dev = set->crtc->dev; +- +- pm_runtime_forbid(&dev->pdev->dev); +- ret = drm_crtc_helper_set_config(set); +- pm_runtime_allow(&dev->pdev->dev); +- return ret; +-} +- +-/* Returns the clock of the currently programmed mode of the given pipe. */ +-static int psb_intel_crtc_clock_get(struct drm_device *dev, +- struct drm_crtc *crtc) +-{ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- u32 dpll; +- u32 fp; +- struct psb_intel_clock_t clock; +- bool is_lvds; +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (gma_power_begin(dev, false)) { +- dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B); +- if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) +- fp = REG_READ((pipe == 0) ? FPA0 : FPB0); +- else +- fp = REG_READ((pipe == 0) ? FPA1 : FPB1); +- is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN); +- gma_power_end(dev); +- } else { +- dpll = (pipe == 0) ? +- dev_priv->saveDPLL_A : dev_priv->saveDPLL_B; +- +- if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) +- fp = (pipe == 0) ? +- dev_priv->saveFPA0 : +- dev_priv->saveFPB0; +- else +- fp = (pipe == 0) ? +- dev_priv->saveFPA1 : +- dev_priv->saveFPB1; +- +- is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN); +- } +- +- clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; +- clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; +- clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; +- +- if (is_lvds) { +- clock.p1 = +- ffs((dpll & +- DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> +- DPLL_FPA01_P1_POST_DIV_SHIFT); +- clock.p2 = 14; +- +- if ((dpll & PLL_REF_INPUT_MASK) == +- PLLB_REF_INPUT_SPREADSPECTRUMIN) { +- /* XXX: might not be 66MHz */ +- i8xx_clock(66000, &clock); +- } else +- i8xx_clock(48000, &clock); +- } else { +- if (dpll & PLL_P1_DIVIDE_BY_TWO) +- clock.p1 = 2; +- else { +- clock.p1 = +- ((dpll & +- DPLL_FPA01_P1_POST_DIV_MASK_I830) >> +- DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; +- } +- if (dpll & PLL_P2_DIVIDE_BY_4) +- clock.p2 = 4; +- else +- clock.p2 = 2; +- +- i8xx_clock(48000, &clock); +- } +- +- /* XXX: It would be nice to validate the clocks, but we can't reuse +- * i830PllIsValid() because it relies on the xf86_config connector +- * configuration being accurate, which it isn't necessarily. +- */ +- +- return clock.dot; +-} +- +-/** Returns the currently programmed mode of the given pipe. */ +-struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, +- struct drm_crtc *crtc) +-{ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- int pipe = psb_intel_crtc->pipe; +- struct drm_display_mode *mode; +- int htot; +- int hsync; +- int vtot; +- int vsync; +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- if (gma_power_begin(dev, false)) { +- htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); +- hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B); +- vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); +- vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B); +- gma_power_end(dev); +- } else { +- htot = (pipe == 0) ? +- dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B; +- hsync = (pipe == 0) ? +- dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B; +- vtot = (pipe == 0) ? +- dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B; +- vsync = (pipe == 0) ? +- dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B; +- } +- +- mode = kzalloc(sizeof(*mode), GFP_KERNEL); +- if (!mode) +- return NULL; +- +- mode->clock = psb_intel_crtc_clock_get(dev, crtc); +- mode->hdisplay = (htot & 0xffff) + 1; +- mode->htotal = ((htot & 0xffff0000) >> 16) + 1; +- mode->hsync_start = (hsync & 0xffff) + 1; +- mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; +- mode->vdisplay = (vtot & 0xffff) + 1; +- mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; +- mode->vsync_start = (vsync & 0xffff) + 1; +- mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; +- +- drm_mode_set_name(mode); +- drm_mode_set_crtcinfo(mode, 0); +- +- return mode; +-} +- +-void psb_intel_crtc_destroy(struct drm_crtc *crtc) +-{ +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct gtt_range *gt; +- +- /* Unpin the old GEM object */ +- if (psb_intel_crtc->cursor_obj) { +- gt = container_of(psb_intel_crtc->cursor_obj, +- struct gtt_range, gem); +- psb_gtt_unpin(gt); +- drm_gem_object_unreference(psb_intel_crtc->cursor_obj); +- psb_intel_crtc->cursor_obj = NULL; +- } +- kfree(psb_intel_crtc->crtc_state); +- drm_crtc_cleanup(crtc); +- kfree(psb_intel_crtc); +-} +- +-static void psb_intel_crtc_disable(struct drm_crtc *crtc) +-{ +- struct gtt_range *gt; +- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +- +- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); +- +- if (crtc->fb) { +- gt = to_psb_fb(crtc->fb)->gtt; +- psb_gtt_unpin(gt); +- } +-} +- +-const struct drm_crtc_helper_funcs psb_intel_helper_funcs = { +- .dpms = psb_intel_crtc_dpms, +- .mode_fixup = psb_intel_crtc_mode_fixup, +- .mode_set = psb_intel_crtc_mode_set, +- .mode_set_base = psb_intel_pipe_set_base, +- .prepare = psb_intel_crtc_prepare, +- .commit = psb_intel_crtc_commit, +- .disable = psb_intel_crtc_disable, +-}; +- +-const struct drm_crtc_funcs psb_intel_crtc_funcs = { +- .save = psb_intel_crtc_save, +- .restore = psb_intel_crtc_restore, +- .cursor_set = psb_intel_crtc_cursor_set, +- .cursor_move = psb_intel_crtc_cursor_move, +- .gamma_set = psb_intel_crtc_gamma_set, +- .set_config = psb_crtc_set_config, +- .destroy = psb_intel_crtc_destroy, +-}; +- +-/* +- * Set the default value of cursor control and base register +- * to zero. This is a workaround for h/w defect on Oaktrail +- */ +-static void psb_intel_cursor_init(struct drm_device *dev, int pipe) +-{ +- u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR }; +- u32 base[3] = { CURABASE, CURBBASE, CURCBASE }; +- +- REG_WRITE(control[pipe], 0); +- REG_WRITE(base[pipe], 0); +-} +- +-void psb_intel_crtc_init(struct drm_device *dev, int pipe, +- struct psb_intel_mode_device *mode_dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct psb_intel_crtc *psb_intel_crtc; +- int i; +- uint16_t *r_base, *g_base, *b_base; +- +- /* We allocate a extra array of drm_connector pointers +- * for fbdev after the crtc */ +- psb_intel_crtc = +- kzalloc(sizeof(struct psb_intel_crtc) + +- (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), +- GFP_KERNEL); +- if (psb_intel_crtc == NULL) +- return; +- +- psb_intel_crtc->crtc_state = +- kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL); +- if (!psb_intel_crtc->crtc_state) { +- dev_err(dev->dev, "Crtc state error: No memory\n"); +- kfree(psb_intel_crtc); +- return; +- } +- +- /* Set the CRTC operations from the chip specific data */ +- drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs); +- +- drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256); +- psb_intel_crtc->pipe = pipe; +- psb_intel_crtc->plane = pipe; +- +- r_base = psb_intel_crtc->base.gamma_store; +- g_base = r_base + 256; +- b_base = g_base + 256; +- for (i = 0; i < 256; i++) { +- psb_intel_crtc->lut_r[i] = i; +- psb_intel_crtc->lut_g[i] = i; +- psb_intel_crtc->lut_b[i] = i; +- r_base[i] = i << 8; +- g_base[i] = i << 8; +- b_base[i] = i << 8; +- +- psb_intel_crtc->lut_adj[i] = 0; +- } +- +- psb_intel_crtc->mode_dev = mode_dev; +- psb_intel_crtc->cursor_addr = 0; +- +- drm_crtc_helper_add(&psb_intel_crtc->base, +- dev_priv->ops->crtc_helper); +- +- /* Setup the array of drm_connector pointer array */ +- psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base; +- BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || +- dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL); +- dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] = +- &psb_intel_crtc->base; +- dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] = +- &psb_intel_crtc->base; +- psb_intel_crtc->mode_set.connectors = +- (struct drm_connector **) (psb_intel_crtc + 1); +- psb_intel_crtc->mode_set.num_connectors = 0; +- psb_intel_cursor_init(dev, pipe); +-} +- +-int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, +- struct drm_file *file_priv) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data; +- struct drm_mode_object *drmmode_obj; +- struct psb_intel_crtc *crtc; +- +- if (!dev_priv) { +- dev_err(dev->dev, "called with no initialization\n"); +- return -EINVAL; +- } +- +- drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id, +- DRM_MODE_OBJECT_CRTC); +- +- if (!drmmode_obj) { +- dev_err(dev->dev, "no such CRTC id\n"); +- return -EINVAL; +- } +- +- crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj)); +- pipe_from_crtc_id->pipe = crtc->pipe; +- +- return 0; +-} +- +-struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) +-{ +- struct drm_crtc *crtc = NULL; +- +- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- if (psb_intel_crtc->pipe == pipe) +- break; +- } +- return crtc; +-} +- +-int psb_intel_connector_clones(struct drm_device *dev, int type_mask) +-{ +- int index_mask = 0; +- struct drm_connector *connector; +- int entry = 0; +- +- list_for_each_entry(connector, &dev->mode_config.connector_list, +- head) { +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- if (type_mask & (1 << psb_intel_output->type)) +- index_mask |= (1 << entry); +- entry++; +- } +- return index_mask; +-} +- +- +-void psb_intel_modeset_cleanup(struct drm_device *dev) +-{ +- drm_mode_config_cleanup(dev); +-} +- +- +-/* current intel driver doesn't take advantage of encoders +- always give back the encoder for the connector +-*/ +-struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector) +-{ +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- +- return &psb_intel_output->enc; +-} +- +diff --git a/drivers/staging/gma500/psb_intel_display.h b/drivers/staging/gma500/psb_intel_display.h +deleted file mode 100644 +index 535b49a..0000000 +--- a/drivers/staging/gma500/psb_intel_display.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-/* copyright (c) 2008, Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Eric Anholt +- */ +- +-#ifndef _INTEL_DISPLAY_H_ +-#define _INTEL_DISPLAY_H_ +- +-bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type); +-void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, +- u16 *green, u16 *blue, uint32_t type, uint32_t size); +-void psb_intel_crtc_destroy(struct drm_crtc *crtc); +- +-#endif +diff --git a/drivers/staging/gma500/psb_intel_drv.h b/drivers/staging/gma500/psb_intel_drv.h +deleted file mode 100644 +index 36b554b..0000000 +--- a/drivers/staging/gma500/psb_intel_drv.h ++++ /dev/null +@@ -1,230 +0,0 @@ +-/* +- * Copyright (c) 2009-2011, Intel Corporation. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- */ +- +-#ifndef __INTEL_DRV_H__ +-#define __INTEL_DRV_H__ +- +-#include +-#include +-#include +-#include +-#include +- +-/* +- * Display related stuff +- */ +- +-/* store information about an Ixxx DVO */ +-/* The i830->i865 use multiple DVOs with multiple i2cs */ +-/* the i915, i945 have a single sDVO i2c bus - which is different */ +-#define MAX_OUTPUTS 6 +-/* maximum connectors per crtcs in the mode set */ +-#define INTELFB_CONN_LIMIT 4 +- +-#define INTEL_I2C_BUS_DVO 1 +-#define INTEL_I2C_BUS_SDVO 2 +- +-/* these are outputs from the chip - integrated only +- * external chips are via DVO or SDVO output */ +-#define INTEL_OUTPUT_UNUSED 0 +-#define INTEL_OUTPUT_ANALOG 1 +-#define INTEL_OUTPUT_DVO 2 +-#define INTEL_OUTPUT_SDVO 3 +-#define INTEL_OUTPUT_LVDS 4 +-#define INTEL_OUTPUT_TVOUT 5 +-#define INTEL_OUTPUT_HDMI 6 +-#define INTEL_OUTPUT_MIPI 7 +-#define INTEL_OUTPUT_MIPI2 8 +- +-#define INTEL_DVO_CHIP_NONE 0 +-#define INTEL_DVO_CHIP_LVDS 1 +-#define INTEL_DVO_CHIP_TMDS 2 +-#define INTEL_DVO_CHIP_TVOUT 4 +- +-/* +- * Hold information useally put on the device driver privates here, +- * since it needs to be shared across multiple of devices drivers privates. +- */ +-struct psb_intel_mode_device { +- +- /* +- * Abstracted memory manager operations +- */ +- size_t(*bo_offset) (struct drm_device *dev, void *bo); +- +- /* +- * Cursor (Can go ?) +- */ +- int cursor_needs_physical; +- +- /* +- * LVDS info +- */ +- int backlight_duty_cycle; /* restore backlight to this value */ +- bool panel_wants_dither; +- struct drm_display_mode *panel_fixed_mode; +- struct drm_display_mode *panel_fixed_mode2; +- struct drm_display_mode *vbt_mode; /* if any */ +- +- uint32_t saveBLC_PWM_CTL; +-}; +- +-struct psb_intel_i2c_chan { +- /* for getting at dev. private (mmio etc.) */ +- struct drm_device *drm_dev; +- u32 reg; /* GPIO reg */ +- struct i2c_adapter adapter; +- struct i2c_algo_bit_data algo; +- u8 slave_addr; +-}; +- +-struct psb_intel_output { +- struct drm_connector base; +- +- struct drm_encoder enc; +- int type; +- +- struct psb_intel_i2c_chan *i2c_bus; /* for control functions */ +- struct psb_intel_i2c_chan *ddc_bus; /* for DDC only stuff */ +- bool load_detect_temp; +- void *dev_priv; +- +- struct psb_intel_mode_device *mode_dev; +- struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */ +-}; +- +-struct psb_intel_crtc_state { +- uint32_t saveDSPCNTR; +- uint32_t savePIPECONF; +- uint32_t savePIPESRC; +- uint32_t saveDPLL; +- uint32_t saveFP0; +- uint32_t saveFP1; +- uint32_t saveHTOTAL; +- uint32_t saveHBLANK; +- uint32_t saveHSYNC; +- uint32_t saveVTOTAL; +- uint32_t saveVBLANK; +- uint32_t saveVSYNC; +- uint32_t saveDSPSTRIDE; +- uint32_t saveDSPSIZE; +- uint32_t saveDSPPOS; +- uint32_t saveDSPBASE; +- uint32_t savePalette[256]; +-}; +- +-struct psb_intel_crtc { +- struct drm_crtc base; +- int pipe; +- int plane; +- uint32_t cursor_addr; +- u8 lut_r[256], lut_g[256], lut_b[256]; +- u8 lut_adj[256]; +- struct psb_intel_framebuffer *fbdev_fb; +- /* a mode_set for fbdev users on this crtc */ +- struct drm_mode_set mode_set; +- +- /* GEM object that holds our cursor */ +- struct drm_gem_object *cursor_obj; +- +- struct drm_display_mode saved_mode; +- struct drm_display_mode saved_adjusted_mode; +- +- struct psb_intel_mode_device *mode_dev; +- +- /*crtc mode setting flags*/ +- u32 mode_flags; +- +- /* Saved Crtc HW states */ +- struct psb_intel_crtc_state *crtc_state; +-}; +- +-#define to_psb_intel_crtc(x) \ +- container_of(x, struct psb_intel_crtc, base) +-#define to_psb_intel_output(x) \ +- container_of(x, struct psb_intel_output, base) +-#define enc_to_psb_intel_output(x) \ +- container_of(x, struct psb_intel_output, enc) +-#define to_psb_intel_framebuffer(x) \ +- container_of(x, struct psb_intel_framebuffer, base) +- +-struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev, +- const u32 reg, const char *name); +-void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan); +-int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output); +-extern bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output); +- +-extern void psb_intel_crtc_init(struct drm_device *dev, int pipe, +- struct psb_intel_mode_device *mode_dev); +-extern void psb_intel_crt_init(struct drm_device *dev); +-extern void psb_intel_sdvo_init(struct drm_device *dev, int output_device); +-extern void psb_intel_dvo_init(struct drm_device *dev); +-extern void psb_intel_tv_init(struct drm_device *dev); +-extern void psb_intel_lvds_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev); +-extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level); +-extern void mrst_lvds_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev); +-extern void mrst_wait_for_INTR_PKT_SENT(struct drm_device *dev); +-extern void mrst_dsi_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev); +-extern void mid_dsi_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev, int dsi_num); +- +-extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc); +-extern void psb_intel_encoder_prepare(struct drm_encoder *encoder); +-extern void psb_intel_encoder_commit(struct drm_encoder *encoder); +- +-extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector +- *connector); +- +-extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, +- struct drm_crtc *crtc); +-extern void psb_intel_wait_for_vblank(struct drm_device *dev); +-extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, +- struct drm_file *file_priv); +-extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, +- int pipe); +-extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, +- int sdvoB); +-extern int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector); +-extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, +- int enable); +-extern int intelfb_probe(struct drm_device *dev); +-extern int intelfb_remove(struct drm_device *dev, +- struct drm_framebuffer *fb); +-extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device +- *dev, struct +- drm_mode_fb_cmd +- *mode_cmd, +- void *mm_private); +-extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode); +-extern int psb_intel_lvds_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode); +-extern int psb_intel_lvds_set_property(struct drm_connector *connector, +- struct drm_property *property, +- uint64_t value); +-extern void psb_intel_lvds_destroy(struct drm_connector *connector); +-extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs; +- +-extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe); +-extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe); +- +-#endif /* __INTEL_DRV_H__ */ +diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c +deleted file mode 100644 +index 21022e1..0000000 +--- a/drivers/staging/gma500/psb_intel_lvds.c ++++ /dev/null +@@ -1,854 +0,0 @@ +-/* +- * Copyright © 2006-2007 Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Eric Anholt +- * Dave Airlie +- * Jesse Barnes +- */ +- +-#include +-#include +- +-#include "intel_bios.h" +-#include "psb_drv.h" +-#include "psb_intel_drv.h" +-#include "psb_intel_reg.h" +-#include "power.h" +-#include +- +-/* +- * LVDS I2C backlight control macros +- */ +-#define BRIGHTNESS_MAX_LEVEL 100 +-#define BRIGHTNESS_MASK 0xFF +-#define BLC_I2C_TYPE 0x01 +-#define BLC_PWM_TYPT 0x02 +- +-#define BLC_POLARITY_NORMAL 0 +-#define BLC_POLARITY_INVERSE 1 +- +-#define PSB_BLC_MAX_PWM_REG_FREQ (0xFFFE) +-#define PSB_BLC_MIN_PWM_REG_FREQ (0x2) +-#define PSB_BLC_PWM_PRECISION_FACTOR (10) +-#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) +-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) +- +-struct psb_intel_lvds_priv { +- /* +- * Saved LVDO output states +- */ +- uint32_t savePP_ON; +- uint32_t savePP_OFF; +- uint32_t saveLVDS; +- uint32_t savePP_CONTROL; +- uint32_t savePP_CYCLE; +- uint32_t savePFIT_CONTROL; +- uint32_t savePFIT_PGM_RATIOS; +- uint32_t saveBLC_PWM_CTL; +-}; +- +- +-/* +- * Returns the maximum level of the backlight duty cycle field. +- */ +-static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 ret; +- +- if (gma_power_begin(dev, false)) { +- ret = REG_READ(BLC_PWM_CTL); +- gma_power_end(dev); +- } else /* Powered off, use the saved value */ +- ret = dev_priv->saveBLC_PWM_CTL; +- +- /* Top 15bits hold the frequency mask */ +- ret = (ret & BACKLIGHT_MODULATION_FREQ_MASK) >> +- BACKLIGHT_MODULATION_FREQ_SHIFT; +- +- ret *= 2; /* Return a 16bit range as needed for setting */ +- if (ret == 0) +- dev_err(dev->dev, "BL bug: Reg %08x save %08X\n", +- REG_READ(BLC_PWM_CTL), dev_priv->saveBLC_PWM_CTL); +- return ret; +-} +- +-/* +- * Set LVDS backlight level by I2C command +- * +- * FIXME: at some point we need to both track this for PM and also +- * disable runtime pm on MRST if the brightness is nil (ie blanked) +- */ +-static int psb_lvds_i2c_set_brightness(struct drm_device *dev, +- unsigned int level) +-{ +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *)dev->dev_private; +- +- struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus; +- u8 out_buf[2]; +- unsigned int blc_i2c_brightness; +- +- struct i2c_msg msgs[] = { +- { +- .addr = lvds_i2c_bus->slave_addr, +- .flags = 0, +- .len = 2, +- .buf = out_buf, +- } +- }; +- +- blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level * +- BRIGHTNESS_MASK / +- BRIGHTNESS_MAX_LEVEL); +- +- if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) +- blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness; +- +- out_buf[0] = dev_priv->lvds_bl->brightnesscmd; +- out_buf[1] = (u8)blc_i2c_brightness; +- +- if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) { +- dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n", +- dev_priv->lvds_bl->brightnesscmd, +- blc_i2c_brightness); +- return 0; +- } +- +- dev_err(dev->dev, "I2C transfer error\n"); +- return -1; +-} +- +- +-static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level) +-{ +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *)dev->dev_private; +- +- u32 max_pwm_blc; +- u32 blc_pwm_duty_cycle; +- +- max_pwm_blc = psb_intel_lvds_get_max_backlight(dev); +- +- /*BLC_PWM_CTL Should be initiated while backlight device init*/ +- BUG_ON(max_pwm_blc == 0); +- +- blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL; +- +- if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) +- blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle; +- +- blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; +- REG_WRITE(BLC_PWM_CTL, +- (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | +- (blc_pwm_duty_cycle)); +- +- dev_info(dev->dev, "Backlight lvds set brightness %08x\n", +- (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | +- (blc_pwm_duty_cycle)); +- +- return 0; +-} +- +-/* +- * Set LVDS backlight level either by I2C or PWM +- */ +-void psb_intel_lvds_set_brightness(struct drm_device *dev, int level) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- +- dev_dbg(dev->dev, "backlight level is %d\n", level); +- +- if (!dev_priv->lvds_bl) { +- dev_err(dev->dev, "NO LVDS backlight info\n"); +- return; +- } +- +- if (dev_priv->lvds_bl->type == BLC_I2C_TYPE) +- psb_lvds_i2c_set_brightness(dev, level); +- else +- psb_lvds_pwm_set_brightness(dev, level); +-} +- +-/* +- * Sets the backlight level. +- * +- * level: backlight level, from 0 to psb_intel_lvds_get_max_backlight(). +- */ +-static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 blc_pwm_ctl; +- +- if (gma_power_begin(dev, false)) { +- blc_pwm_ctl = REG_READ(BLC_PWM_CTL); +- blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK; +- REG_WRITE(BLC_PWM_CTL, +- (blc_pwm_ctl | +- (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); +- dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl | +- (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); +- gma_power_end(dev); +- } else { +- blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL & +- ~BACKLIGHT_DUTY_CYCLE_MASK; +- dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl | +- (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); +- } +-} +- +-/* +- * Sets the power state for the panel. +- */ +-static void psb_intel_lvds_set_power(struct drm_device *dev, +- struct psb_intel_output *output, bool on) +-{ +- u32 pp_status; +- +- if (!gma_power_begin(dev, true)) { +- dev_err(dev->dev, "set power, chip off!\n"); +- return; +- } +- +- if (on) { +- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | +- POWER_TARGET_ON); +- do { +- pp_status = REG_READ(PP_STATUS); +- } while ((pp_status & PP_ON) == 0); +- +- psb_intel_lvds_set_backlight(dev, +- output-> +- mode_dev->backlight_duty_cycle); +- } else { +- psb_intel_lvds_set_backlight(dev, 0); +- +- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & +- ~POWER_TARGET_ON); +- do { +- pp_status = REG_READ(PP_STATUS); +- } while (pp_status & PP_ON); +- } +- +- gma_power_end(dev); +-} +- +-static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode) +-{ +- struct drm_device *dev = encoder->dev; +- struct psb_intel_output *output = enc_to_psb_intel_output(encoder); +- +- if (mode == DRM_MODE_DPMS_ON) +- psb_intel_lvds_set_power(dev, output, true); +- else +- psb_intel_lvds_set_power(dev, output, false); +- +- /* XXX: We never power down the LVDS pairs. */ +-} +- +-static void psb_intel_lvds_save(struct drm_connector *connector) +-{ +- struct drm_device *dev = connector->dev; +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *)dev->dev_private; +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- struct psb_intel_lvds_priv *lvds_priv = +- (struct psb_intel_lvds_priv *)psb_intel_output->dev_priv; +- +- lvds_priv->savePP_ON = REG_READ(LVDSPP_ON); +- lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF); +- lvds_priv->saveLVDS = REG_READ(LVDS); +- lvds_priv->savePP_CONTROL = REG_READ(PP_CONTROL); +- lvds_priv->savePP_CYCLE = REG_READ(PP_CYCLE); +- /*lvds_priv->savePP_DIVISOR = REG_READ(PP_DIVISOR);*/ +- lvds_priv->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); +- lvds_priv->savePFIT_CONTROL = REG_READ(PFIT_CONTROL); +- lvds_priv->savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS); +- +- /*TODO: move backlight_duty_cycle to psb_intel_lvds_priv*/ +- dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & +- BACKLIGHT_DUTY_CYCLE_MASK); +- +- /* +- * If the light is off at server startup, +- * just make it full brightness +- */ +- if (dev_priv->backlight_duty_cycle == 0) +- dev_priv->backlight_duty_cycle = +- psb_intel_lvds_get_max_backlight(dev); +- +- dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", +- lvds_priv->savePP_ON, +- lvds_priv->savePP_OFF, +- lvds_priv->saveLVDS, +- lvds_priv->savePP_CONTROL, +- lvds_priv->savePP_CYCLE, +- lvds_priv->saveBLC_PWM_CTL); +-} +- +-static void psb_intel_lvds_restore(struct drm_connector *connector) +-{ +- struct drm_device *dev = connector->dev; +- u32 pp_status; +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- struct psb_intel_lvds_priv *lvds_priv = +- (struct psb_intel_lvds_priv *)psb_intel_output->dev_priv; +- +- dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", +- lvds_priv->savePP_ON, +- lvds_priv->savePP_OFF, +- lvds_priv->saveLVDS, +- lvds_priv->savePP_CONTROL, +- lvds_priv->savePP_CYCLE, +- lvds_priv->saveBLC_PWM_CTL); +- +- REG_WRITE(BLC_PWM_CTL, lvds_priv->saveBLC_PWM_CTL); +- REG_WRITE(PFIT_CONTROL, lvds_priv->savePFIT_CONTROL); +- REG_WRITE(PFIT_PGM_RATIOS, lvds_priv->savePFIT_PGM_RATIOS); +- REG_WRITE(LVDSPP_ON, lvds_priv->savePP_ON); +- REG_WRITE(LVDSPP_OFF, lvds_priv->savePP_OFF); +- /*REG_WRITE(PP_DIVISOR, lvds_priv->savePP_DIVISOR);*/ +- REG_WRITE(PP_CYCLE, lvds_priv->savePP_CYCLE); +- REG_WRITE(PP_CONTROL, lvds_priv->savePP_CONTROL); +- REG_WRITE(LVDS, lvds_priv->saveLVDS); +- +- if (lvds_priv->savePP_CONTROL & POWER_TARGET_ON) { +- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | +- POWER_TARGET_ON); +- do { +- pp_status = REG_READ(PP_STATUS); +- } while ((pp_status & PP_ON) == 0); +- } else { +- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & +- ~POWER_TARGET_ON); +- do { +- pp_status = REG_READ(PP_STATUS); +- } while (pp_status & PP_ON); +- } +-} +- +-int psb_intel_lvds_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) +-{ +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- struct drm_display_mode *fixed_mode = +- psb_intel_output->mode_dev->panel_fixed_mode; +- +- if (psb_intel_output->type == INTEL_OUTPUT_MIPI2) +- fixed_mode = psb_intel_output->mode_dev->panel_fixed_mode2; +- +- /* just in case */ +- if (mode->flags & DRM_MODE_FLAG_DBLSCAN) +- return MODE_NO_DBLESCAN; +- +- /* just in case */ +- if (mode->flags & DRM_MODE_FLAG_INTERLACE) +- return MODE_NO_INTERLACE; +- +- if (fixed_mode) { +- if (mode->hdisplay > fixed_mode->hdisplay) +- return MODE_PANEL; +- if (mode->vdisplay > fixed_mode->vdisplay) +- return MODE_PANEL; +- } +- return MODE_OK; +-} +- +-bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- struct psb_intel_mode_device *mode_dev = +- enc_to_psb_intel_output(encoder)->mode_dev; +- struct drm_device *dev = encoder->dev; +- struct psb_intel_crtc *psb_intel_crtc = +- to_psb_intel_crtc(encoder->crtc); +- struct drm_encoder *tmp_encoder; +- struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode; +- struct psb_intel_output *psb_intel_output = +- enc_to_psb_intel_output(encoder); +- +- if (psb_intel_output->type == INTEL_OUTPUT_MIPI2) +- panel_fixed_mode = mode_dev->panel_fixed_mode2; +- +- /* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */ +- if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) { +- printk(KERN_ERR "Can't support LVDS on pipe A\n"); +- return false; +- } +- if (IS_MRST(dev) && psb_intel_crtc->pipe != 0) { +- printk(KERN_ERR "Must use PIPE A\n"); +- return false; +- } +- /* Should never happen!! */ +- list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, +- head) { +- if (tmp_encoder != encoder +- && tmp_encoder->crtc == encoder->crtc) { +- printk(KERN_ERR "Can't enable LVDS and another " +- "encoder on the same pipe\n"); +- return false; +- } +- } +- +- /* +- * If we have timings from the BIOS for the panel, put them in +- * to the adjusted mode. The CRTC will be set up for this mode, +- * with the panel scaling set up to source from the H/VDisplay +- * of the original mode. +- */ +- if (panel_fixed_mode != NULL) { +- adjusted_mode->hdisplay = panel_fixed_mode->hdisplay; +- adjusted_mode->hsync_start = panel_fixed_mode->hsync_start; +- adjusted_mode->hsync_end = panel_fixed_mode->hsync_end; +- adjusted_mode->htotal = panel_fixed_mode->htotal; +- adjusted_mode->vdisplay = panel_fixed_mode->vdisplay; +- adjusted_mode->vsync_start = panel_fixed_mode->vsync_start; +- adjusted_mode->vsync_end = panel_fixed_mode->vsync_end; +- adjusted_mode->vtotal = panel_fixed_mode->vtotal; +- adjusted_mode->clock = panel_fixed_mode->clock; +- drm_mode_set_crtcinfo(adjusted_mode, +- CRTC_INTERLACE_HALVE_V); +- } +- +- /* +- * XXX: It would be nice to support lower refresh rates on the +- * panels to reduce power consumption, and perhaps match the +- * user's requested refresh rate. +- */ +- +- return true; +-} +- +-static void psb_intel_lvds_prepare(struct drm_encoder *encoder) +-{ +- struct drm_device *dev = encoder->dev; +- struct psb_intel_output *output = enc_to_psb_intel_output(encoder); +- struct psb_intel_mode_device *mode_dev = output->mode_dev; +- +- if (!gma_power_begin(dev, true)) +- return; +- +- mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); +- mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & +- BACKLIGHT_DUTY_CYCLE_MASK); +- +- psb_intel_lvds_set_power(dev, output, false); +- +- gma_power_end(dev); +-} +- +-static void psb_intel_lvds_commit(struct drm_encoder *encoder) +-{ +- struct drm_device *dev = encoder->dev; +- struct psb_intel_output *output = enc_to_psb_intel_output(encoder); +- struct psb_intel_mode_device *mode_dev = output->mode_dev; +- +- if (mode_dev->backlight_duty_cycle == 0) +- mode_dev->backlight_duty_cycle = +- psb_intel_lvds_get_max_backlight(dev); +- +- psb_intel_lvds_set_power(dev, output, true); +-} +- +-static void psb_intel_lvds_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- struct drm_device *dev = encoder->dev; +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 pfit_control; +- +- /* +- * The LVDS pin pair will already have been turned on in the +- * psb_intel_crtc_mode_set since it has a large impact on the DPLL +- * settings. +- */ +- +- /* +- * Enable automatic panel scaling so that non-native modes fill the +- * screen. Should be enabled before the pipe is enabled, according to +- * register description and PRM. +- */ +- if (mode->hdisplay != adjusted_mode->hdisplay || +- mode->vdisplay != adjusted_mode->vdisplay) +- pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | +- HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | +- HORIZ_INTERP_BILINEAR); +- else +- pfit_control = 0; +- +- if (dev_priv->lvds_dither) +- pfit_control |= PANEL_8TO6_DITHER_ENABLE; +- +- REG_WRITE(PFIT_CONTROL, pfit_control); +-} +- +-/* +- * Detect the LVDS connection. +- * +- * This always returns CONNECTOR_STATUS_CONNECTED. +- * This connector should only have +- * been set up if the LVDS was actually connected anyway. +- */ +-static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector +- *connector, bool force) +-{ +- return connector_status_connected; +-} +- +-/* +- * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. +- */ +-static int psb_intel_lvds_get_modes(struct drm_connector *connector) +-{ +- struct drm_device *dev = connector->dev; +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- struct psb_intel_mode_device *mode_dev = +- psb_intel_output->mode_dev; +- int ret = 0; +- +- if (!IS_MRST(dev)) +- ret = psb_intel_ddc_get_modes(psb_intel_output); +- +- if (ret) +- return ret; +- +- /* Didn't get an EDID, so +- * Set wide sync ranges so we get all modes +- * handed to valid_mode for checking +- */ +- connector->display_info.min_vfreq = 0; +- connector->display_info.max_vfreq = 200; +- connector->display_info.min_hfreq = 0; +- connector->display_info.max_hfreq = 200; +- +- if (mode_dev->panel_fixed_mode != NULL) { +- struct drm_display_mode *mode = +- drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); +- drm_mode_probed_add(connector, mode); +- return 1; +- } +- +- return 0; +-} +- +-/** +- * psb_intel_lvds_destroy - unregister and free LVDS structures +- * @connector: connector to free +- * +- * Unregister the DDC bus for this connector then free the driver private +- * structure. +- */ +-void psb_intel_lvds_destroy(struct drm_connector *connector) +-{ +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- +- if (psb_intel_output->ddc_bus) +- psb_intel_i2c_destroy(psb_intel_output->ddc_bus); +- drm_sysfs_connector_remove(connector); +- drm_connector_cleanup(connector); +- kfree(connector); +-} +- +-int psb_intel_lvds_set_property(struct drm_connector *connector, +- struct drm_property *property, +- uint64_t value) +-{ +- struct drm_encoder *encoder = connector->encoder; +- +- if (!encoder) +- return -1; +- +- if (!strcmp(property->name, "scaling mode")) { +- struct psb_intel_crtc *crtc = +- to_psb_intel_crtc(encoder->crtc); +- uint64_t curval; +- +- if (!crtc) +- goto set_prop_error; +- +- switch (value) { +- case DRM_MODE_SCALE_FULLSCREEN: +- break; +- case DRM_MODE_SCALE_NO_SCALE: +- break; +- case DRM_MODE_SCALE_ASPECT: +- break; +- default: +- goto set_prop_error; +- } +- +- if (drm_connector_property_get_value(connector, +- property, +- &curval)) +- goto set_prop_error; +- +- if (curval == value) +- goto set_prop_done; +- +- if (drm_connector_property_set_value(connector, +- property, +- value)) +- goto set_prop_error; +- +- if (crtc->saved_mode.hdisplay != 0 && +- crtc->saved_mode.vdisplay != 0) { +- if (!drm_crtc_helper_set_mode(encoder->crtc, +- &crtc->saved_mode, +- encoder->crtc->x, +- encoder->crtc->y, +- encoder->crtc->fb)) +- goto set_prop_error; +- } +- } else if (!strcmp(property->name, "backlight")) { +- if (drm_connector_property_set_value(connector, +- property, +- value)) +- goto set_prop_error; +- else { +-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +- struct drm_psb_private *devp = +- encoder->dev->dev_private; +- struct backlight_device *bd = devp->backlight_device; +- if (bd) { +- bd->props.brightness = value; +- backlight_update_status(bd); +- } +-#endif +- } +- } else if (!strcmp(property->name, "DPMS")) { +- struct drm_encoder_helper_funcs *hfuncs +- = encoder->helper_private; +- hfuncs->dpms(encoder, value); +- } +- +-set_prop_done: +- return 0; +-set_prop_error: +- return -1; +-} +- +-static const struct drm_encoder_helper_funcs psb_intel_lvds_helper_funcs = { +- .dpms = psb_intel_lvds_encoder_dpms, +- .mode_fixup = psb_intel_lvds_mode_fixup, +- .prepare = psb_intel_lvds_prepare, +- .mode_set = psb_intel_lvds_mode_set, +- .commit = psb_intel_lvds_commit, +-}; +- +-const struct drm_connector_helper_funcs +- psb_intel_lvds_connector_helper_funcs = { +- .get_modes = psb_intel_lvds_get_modes, +- .mode_valid = psb_intel_lvds_mode_valid, +- .best_encoder = psb_intel_best_encoder, +-}; +- +-const struct drm_connector_funcs psb_intel_lvds_connector_funcs = { +- .dpms = drm_helper_connector_dpms, +- .save = psb_intel_lvds_save, +- .restore = psb_intel_lvds_restore, +- .detect = psb_intel_lvds_detect, +- .fill_modes = drm_helper_probe_single_connector_modes, +- .set_property = psb_intel_lvds_set_property, +- .destroy = psb_intel_lvds_destroy, +-}; +- +- +-static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder) +-{ +- drm_encoder_cleanup(encoder); +-} +- +-const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = { +- .destroy = psb_intel_lvds_enc_destroy, +-}; +- +- +- +-/** +- * psb_intel_lvds_init - setup LVDS connectors on this device +- * @dev: drm device +- * +- * Create the connector, register the LVDS DDC bus, and try to figure out what +- * modes we can display on the LVDS panel (if present). +- */ +-void psb_intel_lvds_init(struct drm_device *dev, +- struct psb_intel_mode_device *mode_dev) +-{ +- struct psb_intel_output *psb_intel_output; +- struct psb_intel_lvds_priv *lvds_priv; +- struct drm_connector *connector; +- struct drm_encoder *encoder; +- struct drm_display_mode *scan; /* *modes, *bios_mode; */ +- struct drm_crtc *crtc; +- struct drm_psb_private *dev_priv = dev->dev_private; +- u32 lvds; +- int pipe; +- +- psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); +- if (!psb_intel_output) +- return; +- +- lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL); +- if (!lvds_priv) { +- kfree(psb_intel_output); +- dev_err(dev->dev, "LVDS private allocation error\n"); +- return; +- } +- +- psb_intel_output->dev_priv = lvds_priv; +- psb_intel_output->mode_dev = mode_dev; +- +- connector = &psb_intel_output->base; +- encoder = &psb_intel_output->enc; +- drm_connector_init(dev, &psb_intel_output->base, +- &psb_intel_lvds_connector_funcs, +- DRM_MODE_CONNECTOR_LVDS); +- +- drm_encoder_init(dev, &psb_intel_output->enc, +- &psb_intel_lvds_enc_funcs, +- DRM_MODE_ENCODER_LVDS); +- +- drm_mode_connector_attach_encoder(&psb_intel_output->base, +- &psb_intel_output->enc); +- psb_intel_output->type = INTEL_OUTPUT_LVDS; +- +- drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs); +- drm_connector_helper_add(connector, +- &psb_intel_lvds_connector_helper_funcs); +- connector->display_info.subpixel_order = SubPixelHorizontalRGB; +- connector->interlace_allowed = false; +- connector->doublescan_allowed = false; +- +- /*Attach connector properties*/ +- drm_connector_attach_property(connector, +- dev->mode_config.scaling_mode_property, +- DRM_MODE_SCALE_FULLSCREEN); +- drm_connector_attach_property(connector, +- dev_priv->backlight_property, +- BRIGHTNESS_MAX_LEVEL); +- +- /* +- * Set up I2C bus +- * FIXME: distroy i2c_bus when exit +- */ +- psb_intel_output->i2c_bus = psb_intel_i2c_create(dev, +- GPIOB, +- "LVDSBLC_B"); +- if (!psb_intel_output->i2c_bus) { +- dev_printk(KERN_ERR, +- &dev->pdev->dev, "I2C bus registration failed.\n"); +- goto failed_blc_i2c; +- } +- psb_intel_output->i2c_bus->slave_addr = 0x2C; +- dev_priv->lvds_i2c_bus = psb_intel_output->i2c_bus; +- +- /* +- * LVDS discovery: +- * 1) check for EDID on DDC +- * 2) check for VBT data +- * 3) check to see if LVDS is already on +- * if none of the above, no panel +- * 4) make sure lid is open +- * if closed, act like it's not there for now +- */ +- +- /* Set up the DDC bus. */ +- psb_intel_output->ddc_bus = psb_intel_i2c_create(dev, +- GPIOC, +- "LVDSDDC_C"); +- if (!psb_intel_output->ddc_bus) { +- dev_printk(KERN_ERR, &dev->pdev->dev, +- "DDC bus registration " "failed.\n"); +- goto failed_ddc; +- } +- +- /* +- * Attempt to get the fixed panel mode from DDC. Assume that the +- * preferred mode is the right one. +- */ +- psb_intel_ddc_get_modes(psb_intel_output); +- list_for_each_entry(scan, &connector->probed_modes, head) { +- if (scan->type & DRM_MODE_TYPE_PREFERRED) { +- mode_dev->panel_fixed_mode = +- drm_mode_duplicate(dev, scan); +- goto out; /* FIXME: check for quirks */ +- } +- } +- +- /* Failed to get EDID, what about VBT? do we need this? */ +- if (mode_dev->vbt_mode) +- mode_dev->panel_fixed_mode = +- drm_mode_duplicate(dev, mode_dev->vbt_mode); +- +- if (!mode_dev->panel_fixed_mode) +- if (dev_priv->lfp_lvds_vbt_mode) +- mode_dev->panel_fixed_mode = +- drm_mode_duplicate(dev, +- dev_priv->lfp_lvds_vbt_mode); +- +- /* +- * If we didn't get EDID, try checking if the panel is already turned +- * on. If so, assume that whatever is currently programmed is the +- * correct mode. +- */ +- lvds = REG_READ(LVDS); +- pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; +- crtc = psb_intel_get_crtc_from_pipe(dev, pipe); +- +- if (crtc && (lvds & LVDS_PORT_EN)) { +- mode_dev->panel_fixed_mode = +- psb_intel_crtc_mode_get(dev, crtc); +- if (mode_dev->panel_fixed_mode) { +- mode_dev->panel_fixed_mode->type |= +- DRM_MODE_TYPE_PREFERRED; +- goto out; /* FIXME: check for quirks */ +- } +- } +- +- /* If we still don't have a mode after all that, give up. */ +- if (!mode_dev->panel_fixed_mode) { +- dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n"); +- goto failed_find; +- } +- +- /* +- * Blacklist machines with BIOSes that list an LVDS panel without +- * actually having one. +- */ +-out: +- drm_sysfs_connector_add(connector); +- return; +- +-failed_find: +- if (psb_intel_output->ddc_bus) +- psb_intel_i2c_destroy(psb_intel_output->ddc_bus); +-failed_ddc: +- if (psb_intel_output->i2c_bus) +- psb_intel_i2c_destroy(psb_intel_output->i2c_bus); +-failed_blc_i2c: +- drm_encoder_cleanup(encoder); +- drm_connector_cleanup(connector); +- kfree(connector); +-} +- +diff --git a/drivers/staging/gma500/psb_intel_modes.c b/drivers/staging/gma500/psb_intel_modes.c +deleted file mode 100644 +index bde1aff..0000000 +--- a/drivers/staging/gma500/psb_intel_modes.c ++++ /dev/null +@@ -1,77 +0,0 @@ +-/* +- * Copyright (c) 2007 Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authers: Jesse Barnes +- */ +- +-#include +-#include +-#include +-#include "psb_intel_drv.h" +- +-/** +- * psb_intel_ddc_probe +- * +- */ +-bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output) +-{ +- u8 out_buf[] = { 0x0, 0x0 }; +- u8 buf[2]; +- int ret; +- struct i2c_msg msgs[] = { +- { +- .addr = 0x50, +- .flags = 0, +- .len = 1, +- .buf = out_buf, +- }, +- { +- .addr = 0x50, +- .flags = I2C_M_RD, +- .len = 1, +- .buf = buf, +- } +- }; +- +- ret = i2c_transfer(&psb_intel_output->ddc_bus->adapter, msgs, 2); +- if (ret == 2) +- return true; +- +- return false; +-} +- +-/** +- * psb_intel_ddc_get_modes - get modelist from monitor +- * @connector: DRM connector device to use +- * +- * Fetch the EDID information from @connector using the DDC bus. +- */ +-int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output) +-{ +- struct edid *edid; +- int ret = 0; +- +- edid = +- drm_get_edid(&psb_intel_output->base, +- &psb_intel_output->ddc_bus->adapter); +- if (edid) { +- drm_mode_connector_update_edid_property(&psb_intel_output-> +- base, edid); +- ret = drm_add_edid_modes(&psb_intel_output->base, edid); +- kfree(edid); +- } +- return ret; +-} +diff --git a/drivers/staging/gma500/psb_intel_reg.h b/drivers/staging/gma500/psb_intel_reg.h +deleted file mode 100644 +index 1ac16aa..0000000 +--- a/drivers/staging/gma500/psb_intel_reg.h ++++ /dev/null +@@ -1,1235 +0,0 @@ +-/* +- * Copyright (c) 2009, Intel Corporation. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- */ +-#ifndef __PSB_INTEL_REG_H__ +-#define __PSB_INTEL_REG_H__ +- +-#define BLC_PWM_CTL 0x61254 +-#define BLC_PWM_CTL2 0x61250 +-#define BLC_PWM_CTL_C 0x62254 +-#define BLC_PWM_CTL2_C 0x62250 +-#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) +-/* +- * This is the most significant 15 bits of the number of backlight cycles in a +- * complete cycle of the modulated backlight control. +- * +- * The actual value is this field multiplied by two. +- */ +-#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) +-#define BLM_LEGACY_MODE (1 << 16) +-/* +- * This is the number of cycles out of the backlight modulation cycle for which +- * the backlight is on. +- * +- * This field must be no greater than the number of cycles in the complete +- * backlight modulation cycle. +- */ +-#define BACKLIGHT_DUTY_CYCLE_SHIFT (0) +-#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) +- +-#define I915_GCFGC 0xf0 +-#define I915_LOW_FREQUENCY_ENABLE (1 << 7) +-#define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4) +-#define I915_DISPLAY_CLOCK_333_MHZ (4 << 4) +-#define I915_DISPLAY_CLOCK_MASK (7 << 4) +- +-#define I855_HPLLCC 0xc0 +-#define I855_CLOCK_CONTROL_MASK (3 << 0) +-#define I855_CLOCK_133_200 (0 << 0) +-#define I855_CLOCK_100_200 (1 << 0) +-#define I855_CLOCK_100_133 (2 << 0) +-#define I855_CLOCK_166_250 (3 << 0) +- +-/* I830 CRTC registers */ +-#define HTOTAL_A 0x60000 +-#define HBLANK_A 0x60004 +-#define HSYNC_A 0x60008 +-#define VTOTAL_A 0x6000c +-#define VBLANK_A 0x60010 +-#define VSYNC_A 0x60014 +-#define PIPEASRC 0x6001c +-#define BCLRPAT_A 0x60020 +-#define VSYNCSHIFT_A 0x60028 +- +-#define HTOTAL_B 0x61000 +-#define HBLANK_B 0x61004 +-#define HSYNC_B 0x61008 +-#define VTOTAL_B 0x6100c +-#define VBLANK_B 0x61010 +-#define VSYNC_B 0x61014 +-#define PIPEBSRC 0x6101c +-#define BCLRPAT_B 0x61020 +-#define VSYNCSHIFT_B 0x61028 +- +-#define HTOTAL_C 0x62000 +-#define HBLANK_C 0x62004 +-#define HSYNC_C 0x62008 +-#define VTOTAL_C 0x6200c +-#define VBLANK_C 0x62010 +-#define VSYNC_C 0x62014 +-#define PIPECSRC 0x6201c +-#define BCLRPAT_C 0x62020 +-#define VSYNCSHIFT_C 0x62028 +- +-#define PP_STATUS 0x61200 +-# define PP_ON (1 << 31) +-/* +- * Indicates that all dependencies of the panel are on: +- * +- * - PLL enabled +- * - pipe enabled +- * - LVDS/DVOB/DVOC on +- */ +-#define PP_READY (1 << 30) +-#define PP_SEQUENCE_NONE (0 << 28) +-#define PP_SEQUENCE_ON (1 << 28) +-#define PP_SEQUENCE_OFF (2 << 28) +-#define PP_SEQUENCE_MASK 0x30000000 +-#define PP_CONTROL 0x61204 +-#define POWER_TARGET_ON (1 << 0) +- +-#define LVDSPP_ON 0x61208 +-#define LVDSPP_OFF 0x6120c +-#define PP_CYCLE 0x61210 +- +-#define PFIT_CONTROL 0x61230 +-#define PFIT_ENABLE (1 << 31) +-#define PFIT_PIPE_MASK (3 << 29) +-#define PFIT_PIPE_SHIFT 29 +-#define PFIT_SCALING_MODE_PILLARBOX (1 << 27) +-#define PFIT_SCALING_MODE_LETTERBOX (3 << 26) +-#define VERT_INTERP_DISABLE (0 << 10) +-#define VERT_INTERP_BILINEAR (1 << 10) +-#define VERT_INTERP_MASK (3 << 10) +-#define VERT_AUTO_SCALE (1 << 9) +-#define HORIZ_INTERP_DISABLE (0 << 6) +-#define HORIZ_INTERP_BILINEAR (1 << 6) +-#define HORIZ_INTERP_MASK (3 << 6) +-#define HORIZ_AUTO_SCALE (1 << 5) +-#define PANEL_8TO6_DITHER_ENABLE (1 << 3) +- +-#define PFIT_PGM_RATIOS 0x61234 +-#define PFIT_VERT_SCALE_MASK 0xfff00000 +-#define PFIT_HORIZ_SCALE_MASK 0x0000fff0 +- +-#define PFIT_AUTO_RATIOS 0x61238 +- +-#define DPLL_A 0x06014 +-#define DPLL_B 0x06018 +-#define DPLL_VCO_ENABLE (1 << 31) +-#define DPLL_DVO_HIGH_SPEED (1 << 30) +-#define DPLL_SYNCLOCK_ENABLE (1 << 29) +-#define DPLL_VGA_MODE_DIS (1 << 28) +-#define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */ +-#define DPLLB_MODE_LVDS (2 << 26) /* i915 */ +-#define DPLL_MODE_MASK (3 << 26) +-#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */ +-#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */ +-#define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */ +-#define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ +-#define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ +-#define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ +-#define DPLL_LOCK (1 << 15) /* CDV */ +- +-/* +- * The i830 generation, in DAC/serial mode, defines p1 as two plus this +- * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set. +- */ +-# define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 +-/* +- * The i830 generation, in LVDS mode, defines P1 as the bit number set within +- * this field (only one bit may be set). +- */ +-#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 +-#define DPLL_FPA01_P1_POST_DIV_SHIFT 16 +-#define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required +- * in DVO non-gang */ +-# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ +-#define PLL_REF_INPUT_DREFCLK (0 << 13) +-#define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ +-#define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO +- * TVCLKIN */ +-#define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) +-#define PLL_REF_INPUT_MASK (3 << 13) +-#define PLL_LOAD_PULSE_PHASE_SHIFT 9 +-/* +- * Parallel to Serial Load Pulse phase selection. +- * Selects the phase for the 10X DPLL clock for the PCIe +- * digital display port. The range is 4 to 13; 10 or more +- * is just a flip delay. The default is 6 +- */ +-#define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT) +-#define DISPLAY_RATE_SELECT_FPA1 (1 << 8) +- +-/* +- * SDVO multiplier for 945G/GM. Not used on 965. +- * +- * DPLL_MD_UDI_MULTIPLIER_MASK +- */ +-#define SDVO_MULTIPLIER_MASK 0x000000ff +-#define SDVO_MULTIPLIER_SHIFT_HIRES 4 +-#define SDVO_MULTIPLIER_SHIFT_VGA 0 +- +-/* +- * PLL_MD +- */ +-/* Pipe A SDVO/UDI clock multiplier/divider register for G965. */ +-#define DPLL_A_MD 0x0601c +-/* Pipe B SDVO/UDI clock multiplier/divider register for G965. */ +-#define DPLL_B_MD 0x06020 +-/* +- * UDI pixel divider, controlling how many pixels are stuffed into a packet. +- * +- * Value is pixels minus 1. Must be set to 1 pixel for SDVO. +- */ +-#define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000 +-#define DPLL_MD_UDI_DIVIDER_SHIFT 24 +-/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */ +-#define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000 +-#define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16 +-/* +- * SDVO/UDI pixel multiplier. +- * +- * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus +- * clock rate is 10 times the DPLL clock. At low resolution/refresh rate +- * modes, the bus rate would be below the limits, so SDVO allows for stuffing +- * dummy bytes in the datastream at an increased clock rate, with both sides of +- * the link knowing how many bytes are fill. +- * +- * So, for a mode with a dotclock of 65Mhz, we would want to double the clock +- * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be +- * set to 130Mhz, and the SDVO multiplier set to 2x in this register and +- * through an SDVO command. +- * +- * This register field has values of multiplication factor minus 1, with +- * a maximum multiplier of 5 for SDVO. +- */ +-#define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00 +-#define DPLL_MD_UDI_MULTIPLIER_SHIFT 8 +-/* +- * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. +- * This best be set to the default value (3) or the CRT won't work. No, +- * I don't entirely understand what this does... +- */ +-#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f +-#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 +- +-#define DPLL_TEST 0x606c +-#define DPLLB_TEST_SDVO_DIV_1 (0 << 22) +-#define DPLLB_TEST_SDVO_DIV_2 (1 << 22) +-#define DPLLB_TEST_SDVO_DIV_4 (2 << 22) +-#define DPLLB_TEST_SDVO_DIV_MASK (3 << 22) +-#define DPLLB_TEST_N_BYPASS (1 << 19) +-#define DPLLB_TEST_M_BYPASS (1 << 18) +-#define DPLLB_INPUT_BUFFER_ENABLE (1 << 16) +-#define DPLLA_TEST_N_BYPASS (1 << 3) +-#define DPLLA_TEST_M_BYPASS (1 << 2) +-#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) +- +-#define ADPA 0x61100 +-#define ADPA_DAC_ENABLE (1 << 31) +-#define ADPA_DAC_DISABLE 0 +-#define ADPA_PIPE_SELECT_MASK (1 << 30) +-#define ADPA_PIPE_A_SELECT 0 +-#define ADPA_PIPE_B_SELECT (1 << 30) +-#define ADPA_USE_VGA_HVPOLARITY (1 << 15) +-#define ADPA_SETS_HVPOLARITY 0 +-#define ADPA_VSYNC_CNTL_DISABLE (1 << 11) +-#define ADPA_VSYNC_CNTL_ENABLE 0 +-#define ADPA_HSYNC_CNTL_DISABLE (1 << 10) +-#define ADPA_HSYNC_CNTL_ENABLE 0 +-#define ADPA_VSYNC_ACTIVE_HIGH (1 << 4) +-#define ADPA_VSYNC_ACTIVE_LOW 0 +-#define ADPA_HSYNC_ACTIVE_HIGH (1 << 3) +-#define ADPA_HSYNC_ACTIVE_LOW 0 +- +-#define FPA0 0x06040 +-#define FPA1 0x06044 +-#define FPB0 0x06048 +-#define FPB1 0x0604c +-#define FP_N_DIV_MASK 0x003f0000 +-#define FP_N_DIV_SHIFT 16 +-#define FP_M1_DIV_MASK 0x00003f00 +-#define FP_M1_DIV_SHIFT 8 +-#define FP_M2_DIV_MASK 0x0000003f +-#define FP_M2_DIV_SHIFT 0 +- +-#define PORT_HOTPLUG_EN 0x61110 +-#define SDVOB_HOTPLUG_INT_EN (1 << 26) +-#define SDVOC_HOTPLUG_INT_EN (1 << 25) +-#define TV_HOTPLUG_INT_EN (1 << 18) +-#define CRT_HOTPLUG_INT_EN (1 << 9) +-#define CRT_HOTPLUG_FORCE_DETECT (1 << 3) +-/* CDV.. */ +-#define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8) +-#define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7) +-#define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7) +-#define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5) +-#define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5) +-#define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5) +-#define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5) +-#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5) +-#define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4) +-#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4) +-#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) +-#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) +-#define CRT_HOTPLUG_DETECT_MASK 0x000000F8 +- +-#define PORT_HOTPLUG_STAT 0x61114 +-#define CRT_HOTPLUG_INT_STATUS (1 << 11) +-#define TV_HOTPLUG_INT_STATUS (1 << 10) +-#define CRT_HOTPLUG_MONITOR_MASK (3 << 8) +-#define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) +-#define CRT_HOTPLUG_MONITOR_MONO (2 << 8) +-#define CRT_HOTPLUG_MONITOR_NONE (0 << 8) +-#define SDVOC_HOTPLUG_INT_STATUS (1 << 7) +-#define SDVOB_HOTPLUG_INT_STATUS (1 << 6) +- +-#define SDVOB 0x61140 +-#define SDVOC 0x61160 +-#define SDVO_ENABLE (1 << 31) +-#define SDVO_PIPE_B_SELECT (1 << 30) +-#define SDVO_STALL_SELECT (1 << 29) +-#define SDVO_INTERRUPT_ENABLE (1 << 26) +- +-/** +- * 915G/GM SDVO pixel multiplier. +- * +- * Programmed value is multiplier - 1, up to 5x. +- * +- * DPLL_MD_UDI_MULTIPLIER_MASK +- */ +-#define SDVO_PORT_MULTIPLY_MASK (7 << 23) +-#define SDVO_PORT_MULTIPLY_SHIFT 23 +-#define SDVO_PHASE_SELECT_MASK (15 << 19) +-#define SDVO_PHASE_SELECT_DEFAULT (6 << 19) +-#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) +-#define SDVOC_GANG_MODE (1 << 16) +-#define SDVO_BORDER_ENABLE (1 << 7) +-#define SDVOB_PCIE_CONCURRENCY (1 << 3) +-#define SDVO_DETECTED (1 << 2) +-/* Bits to be preserved when writing */ +-#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14)) +-#define SDVOC_PRESERVE_MASK (1 << 17) +- +-/* +- * This register controls the LVDS output enable, pipe selection, and data +- * format selection. +- * +- * All of the clock/data pairs are force powered down by power sequencing. +- */ +-#define LVDS 0x61180 +-/* +- * Enables the LVDS port. This bit must be set before DPLLs are enabled, as +- * the DPLL semantics change when the LVDS is assigned to that pipe. +- */ +-#define LVDS_PORT_EN (1 << 31) +-/* Selects pipe B for LVDS data. Must be set on pre-965. */ +-#define LVDS_PIPEB_SELECT (1 << 30) +- +-/* Turns on border drawing to allow centered display. */ +-#define LVDS_BORDER_EN (1 << 15) +- +-/* +- * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per +- * pixel. +- */ +-#define LVDS_A0A2_CLKA_POWER_MASK (3 << 8) +-#define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8) +-#define LVDS_A0A2_CLKA_POWER_UP (3 << 8) +-/* +- * Controls the A3 data pair, which contains the additional LSBs for 24 bit +- * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be +- * on. +- */ +-#define LVDS_A3_POWER_MASK (3 << 6) +-#define LVDS_A3_POWER_DOWN (0 << 6) +-#define LVDS_A3_POWER_UP (3 << 6) +-/* +- * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP +- * is set. +- */ +-#define LVDS_CLKB_POWER_MASK (3 << 4) +-#define LVDS_CLKB_POWER_DOWN (0 << 4) +-#define LVDS_CLKB_POWER_UP (3 << 4) +-/* +- * Controls the B0-B3 data pairs. This must be set to match the DPLL p2 +- * setting for whether we are in dual-channel mode. The B3 pair will +- * additionally only be powered up when LVDS_A3_POWER_UP is set. +- */ +-#define LVDS_B0B3_POWER_MASK (3 << 2) +-#define LVDS_B0B3_POWER_DOWN (0 << 2) +-#define LVDS_B0B3_POWER_UP (3 << 2) +- +-#define PIPEACONF 0x70008 +-#define PIPEACONF_ENABLE (1 << 31) +-#define PIPEACONF_DISABLE 0 +-#define PIPEACONF_DOUBLE_WIDE (1 << 30) +-#define PIPECONF_ACTIVE (1 << 30) +-#define I965_PIPECONF_ACTIVE (1 << 30) +-#define PIPECONF_DSIPLL_LOCK (1 << 29) +-#define PIPEACONF_SINGLE_WIDE 0 +-#define PIPEACONF_PIPE_UNLOCKED 0 +-#define PIPEACONF_DSR (1 << 26) +-#define PIPEACONF_PIPE_LOCKED (1 << 25) +-#define PIPEACONF_PALETTE 0 +-#define PIPECONF_FORCE_BORDER (1 << 25) +-#define PIPEACONF_GAMMA (1 << 24) +-#define PIPECONF_PROGRESSIVE (0 << 21) +-#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) +-#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) +-#define PIPECONF_PLANE_OFF (1 << 19) +-#define PIPECONF_CURSOR_OFF (1 << 18) +- +-#define PIPEBCONF 0x71008 +-#define PIPEBCONF_ENABLE (1 << 31) +-#define PIPEBCONF_DISABLE 0 +-#define PIPEBCONF_DOUBLE_WIDE (1 << 30) +-#define PIPEBCONF_DISABLE 0 +-#define PIPEBCONF_GAMMA (1 << 24) +-#define PIPEBCONF_PALETTE 0 +- +-#define PIPECCONF 0x72008 +- +-#define PIPEBGCMAXRED 0x71010 +-#define PIPEBGCMAXGREEN 0x71014 +-#define PIPEBGCMAXBLUE 0x71018 +- +-#define PIPEASTAT 0x70024 +-#define PIPEBSTAT 0x71024 +-#define PIPECSTAT 0x72024 +-#define PIPE_VBLANK_INTERRUPT_STATUS (1UL << 1) +-#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL << 2) +-#define PIPE_VBLANK_CLEAR (1 << 1) +-#define PIPE_VBLANK_STATUS (1 << 1) +-#define PIPE_TE_STATUS (1UL << 6) +-#define PIPE_DPST_EVENT_STATUS (1UL << 7) +-#define PIPE_VSYNC_CLEAR (1UL << 9) +-#define PIPE_VSYNC_STATUS (1UL << 9) +-#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS (1UL << 10) +-#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS (1UL << 11) +-#define PIPE_VBLANK_INTERRUPT_ENABLE (1UL << 17) +-#define PIPE_START_VBLANK_INTERRUPT_ENABLE (1UL << 18) +-#define PIPE_TE_ENABLE (1UL << 22) +-#define PIPE_DPST_EVENT_ENABLE (1UL << 23) +-#define PIPE_VSYNC_ENABL (1UL << 25) +-#define PIPE_HDMI_AUDIO_UNDERRUN (1UL << 26) +-#define PIPE_HDMI_AUDIO_BUFFER_DONE (1UL << 27) +-#define PIPE_HDMI_AUDIO_INT_MASK (PIPE_HDMI_AUDIO_UNDERRUN | \ +- PIPE_HDMI_AUDIO_BUFFER_DONE) +-#define PIPE_EVENT_MASK ((1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)|(1 << 24)|(1 << 23)|(1 << 22)|(1 << 21)|(1 << 20)|(1 << 16)) +-#define PIPE_VBLANK_MASK ((1 << 25)|(1 << 24)|(1 << 18)|(1 << 17)) +-#define HISTOGRAM_INT_CONTROL 0x61268 +-#define HISTOGRAM_BIN_DATA 0X61264 +-#define HISTOGRAM_LOGIC_CONTROL 0x61260 +-#define PWM_CONTROL_LOGIC 0x61250 +-#define PIPE_HOTPLUG_INTERRUPT_STATUS (1UL << 10) +-#define HISTOGRAM_INTERRUPT_ENABLE (1UL << 31) +-#define HISTOGRAM_LOGIC_ENABLE (1UL << 31) +-#define PWM_LOGIC_ENABLE (1UL << 31) +-#define PWM_PHASEIN_ENABLE (1UL << 25) +-#define PWM_PHASEIN_INT_ENABLE (1UL << 24) +-#define PWM_PHASEIN_VB_COUNT 0x00001f00 +-#define PWM_PHASEIN_INC 0x0000001f +-#define HISTOGRAM_INT_CTRL_CLEAR (1UL << 30) +-#define DPST_YUV_LUMA_MODE 0 +- +-struct dpst_ie_histogram_control { +- union { +- uint32_t data; +- struct { +- uint32_t bin_reg_index:7; +- uint32_t reserved:4; +- uint32_t bin_reg_func_select:1; +- uint32_t sync_to_phase_in:1; +- uint32_t alt_enhancement_mode:2; +- uint32_t reserved1:1; +- uint32_t sync_to_phase_in_count:8; +- uint32_t histogram_mode_select:1; +- uint32_t reserved2:4; +- uint32_t ie_pipe_assignment:1; +- uint32_t ie_mode_table_enabled:1; +- uint32_t ie_histogram_enable:1; +- }; +- }; +-}; +- +-struct dpst_guardband { +- union { +- uint32_t data; +- struct { +- uint32_t guardband:22; +- uint32_t guardband_interrupt_delay:8; +- uint32_t interrupt_status:1; +- uint32_t interrupt_enable:1; +- }; +- }; +-}; +- +-#define PIPEAFRAMEHIGH 0x70040 +-#define PIPEAFRAMEPIXEL 0x70044 +-#define PIPEBFRAMEHIGH 0x71040 +-#define PIPEBFRAMEPIXEL 0x71044 +-#define PIPECFRAMEHIGH 0x72040 +-#define PIPECFRAMEPIXEL 0x72044 +-#define PIPE_FRAME_HIGH_MASK 0x0000ffff +-#define PIPE_FRAME_HIGH_SHIFT 0 +-#define PIPE_FRAME_LOW_MASK 0xff000000 +-#define PIPE_FRAME_LOW_SHIFT 24 +-#define PIPE_PIXEL_MASK 0x00ffffff +-#define PIPE_PIXEL_SHIFT 0 +- +-#define DSPARB 0x70030 +-#define DSPFW1 0x70034 +-#define DSPFW2 0x70038 +-#define DSPFW3 0x7003c +-#define DSPFW4 0x70050 +-#define DSPFW5 0x70054 +-#define DSPFW6 0x70058 +-#define DSPCHICKENBIT 0x70400 +-#define DSPACNTR 0x70180 +-#define DSPBCNTR 0x71180 +-#define DSPCCNTR 0x72180 +-#define DISPLAY_PLANE_ENABLE (1 << 31) +-#define DISPLAY_PLANE_DISABLE 0 +-#define DISPPLANE_GAMMA_ENABLE (1 << 30) +-#define DISPPLANE_GAMMA_DISABLE 0 +-#define DISPPLANE_PIXFORMAT_MASK (0xf << 26) +-#define DISPPLANE_8BPP (0x2 << 26) +-#define DISPPLANE_15_16BPP (0x4 << 26) +-#define DISPPLANE_16BPP (0x5 << 26) +-#define DISPPLANE_32BPP_NO_ALPHA (0x6 << 26) +-#define DISPPLANE_32BPP (0x7 << 26) +-#define DISPPLANE_STEREO_ENABLE (1 << 25) +-#define DISPPLANE_STEREO_DISABLE 0 +-#define DISPPLANE_SEL_PIPE_MASK (1 << 24) +-#define DISPPLANE_SEL_PIPE_POS 24 +-#define DISPPLANE_SEL_PIPE_A 0 +-#define DISPPLANE_SEL_PIPE_B (1 << 24) +-#define DISPPLANE_SRC_KEY_ENABLE (1 << 22) +-#define DISPPLANE_SRC_KEY_DISABLE 0 +-#define DISPPLANE_LINE_DOUBLE (1 << 20) +-#define DISPPLANE_NO_LINE_DOUBLE 0 +-#define DISPPLANE_STEREO_POLARITY_FIRST 0 +-#define DISPPLANE_STEREO_POLARITY_SECOND (1 << 18) +-/* plane B only */ +-#define DISPPLANE_ALPHA_TRANS_ENABLE (1 << 15) +-#define DISPPLANE_ALPHA_TRANS_DISABLE 0 +-#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0 +-#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1) +-#define DISPPLANE_BOTTOM (4) +- +-#define DSPABASE 0x70184 +-#define DSPALINOFF 0x70184 +-#define DSPASTRIDE 0x70188 +- +-#define DSPBBASE 0x71184 +-#define DSPBLINOFF 0X71184 +-#define DSPBADDR DSPBBASE +-#define DSPBSTRIDE 0x71188 +- +-#define DSPCBASE 0x72184 +-#define DSPCLINOFF 0x72184 +-#define DSPCSTRIDE 0x72188 +- +-#define DSPAKEYVAL 0x70194 +-#define DSPAKEYMASK 0x70198 +- +-#define DSPAPOS 0x7018C /* reserved */ +-#define DSPASIZE 0x70190 +-#define DSPBPOS 0x7118C +-#define DSPBSIZE 0x71190 +-#define DSPCPOS 0x7218C +-#define DSPCSIZE 0x72190 +- +-#define DSPASURF 0x7019C +-#define DSPATILEOFF 0x701A4 +- +-#define DSPBSURF 0x7119C +-#define DSPBTILEOFF 0x711A4 +- +-#define DSPCSURF 0x7219C +-#define DSPCTILEOFF 0x721A4 +-#define DSPCKEYMAXVAL 0x721A0 +-#define DSPCKEYMINVAL 0x72194 +-#define DSPCKEYMSK 0x72198 +- +-#define VGACNTRL 0x71400 +-#define VGA_DISP_DISABLE (1 << 31) +-#define VGA_2X_MODE (1 << 30) +-#define VGA_PIPE_B_SELECT (1 << 29) +- +-/* +- * Overlay registers +- */ +-#define OV_C_OFFSET 0x08000 +-#define OV_OVADD 0x30000 +-#define OV_DOVASTA 0x30008 +-# define OV_PIPE_SELECT ((1 << 6)|(1 << 7)) +-# define OV_PIPE_SELECT_POS 6 +-# define OV_PIPE_A 0 +-# define OV_PIPE_C 1 +-#define OV_OGAMC5 0x30010 +-#define OV_OGAMC4 0x30014 +-#define OV_OGAMC3 0x30018 +-#define OV_OGAMC2 0x3001C +-#define OV_OGAMC1 0x30020 +-#define OV_OGAMC0 0x30024 +-#define OVC_OVADD 0x38000 +-#define OVC_DOVCSTA 0x38008 +-#define OVC_OGAMC5 0x38010 +-#define OVC_OGAMC4 0x38014 +-#define OVC_OGAMC3 0x38018 +-#define OVC_OGAMC2 0x3801C +-#define OVC_OGAMC1 0x38020 +-#define OVC_OGAMC0 0x38024 +- +-/* +- * Some BIOS scratch area registers. The 845 (and 830?) store the amount +- * of video memory available to the BIOS in SWF1. +- */ +-#define SWF0 0x71410 +-#define SWF1 0x71414 +-#define SWF2 0x71418 +-#define SWF3 0x7141c +-#define SWF4 0x71420 +-#define SWF5 0x71424 +-#define SWF6 0x71428 +- +-/* +- * 855 scratch registers. +- */ +-#define SWF00 0x70410 +-#define SWF01 0x70414 +-#define SWF02 0x70418 +-#define SWF03 0x7041c +-#define SWF04 0x70420 +-#define SWF05 0x70424 +-#define SWF06 0x70428 +- +-#define SWF10 SWF0 +-#define SWF11 SWF1 +-#define SWF12 SWF2 +-#define SWF13 SWF3 +-#define SWF14 SWF4 +-#define SWF15 SWF5 +-#define SWF16 SWF6 +- +-#define SWF30 0x72414 +-#define SWF31 0x72418 +-#define SWF32 0x7241c +- +- +-/* +- * Palette registers +- */ +-#define PALETTE_A 0x0a000 +-#define PALETTE_B 0x0a800 +-#define PALETTE_C 0x0ac00 +- +-/* Cursor A & B regs */ +-#define CURACNTR 0x70080 +-#define CURSOR_MODE_DISABLE 0x00 +-#define CURSOR_MODE_64_32B_AX 0x07 +-#define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX) +-#define MCURSOR_GAMMA_ENABLE (1 << 26) +-#define CURABASE 0x70084 +-#define CURAPOS 0x70088 +-#define CURSOR_POS_MASK 0x007FF +-#define CURSOR_POS_SIGN 0x8000 +-#define CURSOR_X_SHIFT 0 +-#define CURSOR_Y_SHIFT 16 +-#define CURBCNTR 0x700c0 +-#define CURBBASE 0x700c4 +-#define CURBPOS 0x700c8 +-#define CURCCNTR 0x700e0 +-#define CURCBASE 0x700e4 +-#define CURCPOS 0x700e8 +- +-/* +- * Interrupt Registers +- */ +-#define IER 0x020a0 +-#define IIR 0x020a4 +-#define IMR 0x020a8 +-#define ISR 0x020ac +- +-/* +- * MOORESTOWN delta registers +- */ +-#define MRST_DPLL_A 0x0f014 +-#define MDFLD_DPLL_B 0x0f018 +-#define MDFLD_INPUT_REF_SEL (1 << 14) +-#define MDFLD_VCO_SEL (1 << 16) +-#define DPLLA_MODE_LVDS (2 << 26) /* mrst */ +-#define MDFLD_PLL_LATCHEN (1 << 28) +-#define MDFLD_PWR_GATE_EN (1 << 30) +-#define MDFLD_P1_MASK (0x1FF << 17) +-#define MRST_FPA0 0x0f040 +-#define MRST_FPA1 0x0f044 +-#define MDFLD_DPLL_DIV0 0x0f048 +-#define MDFLD_DPLL_DIV1 0x0f04c +-#define MRST_PERF_MODE 0x020f4 +- +-/* +- * MEDFIELD HDMI registers +- */ +-#define HDMIPHYMISCCTL 0x61134 +-#define HDMI_PHY_POWER_DOWN 0x7f +-#define HDMIB_CONTROL 0x61140 +-#define HDMIB_PORT_EN (1 << 31) +-#define HDMIB_PIPE_B_SELECT (1 << 30) +-#define HDMIB_NULL_PACKET (1 << 9) +-#define HDMIB_HDCP_PORT (1 << 5) +- +-/* #define LVDS 0x61180 */ +-#define MRST_PANEL_8TO6_DITHER_ENABLE (1 << 25) +-#define MRST_PANEL_24_DOT_1_FORMAT (1 << 24) +-#define LVDS_A3_POWER_UP_0_OUTPUT (1 << 6) +- +-#define MIPI 0x61190 +-#define MIPI_C 0x62190 +-#define MIPI_PORT_EN (1 << 31) +-/* Turns on border drawing to allow centered display. */ +-#define SEL_FLOPPED_HSTX (1 << 23) +-#define PASS_FROM_SPHY_TO_AFE (1 << 16) +-#define MIPI_BORDER_EN (1 << 15) +-#define MIPIA_3LANE_MIPIC_1LANE 0x1 +-#define MIPIA_2LANE_MIPIC_2LANE 0x2 +-#define TE_TRIGGER_DSI_PROTOCOL (1 << 2) +-#define TE_TRIGGER_GPIO_PIN (1 << 3) +-#define MIPI_TE_COUNT 0x61194 +- +-/* #define PP_CONTROL 0x61204 */ +-#define POWER_DOWN_ON_RESET (1 << 1) +- +-/* #define PFIT_CONTROL 0x61230 */ +-#define PFIT_PIPE_SELECT (3 << 29) +-#define PFIT_PIPE_SELECT_SHIFT (29) +- +-/* #define BLC_PWM_CTL 0x61254 */ +-#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT (16) +-#define MRST_BACKLIGHT_MODULATION_FREQ_MASK (0xffff << 16) +- +-/* #define PIPEACONF 0x70008 */ +-#define PIPEACONF_PIPE_STATE (1 << 30) +-/* #define DSPACNTR 0x70180 */ +- +-#define MRST_DSPABASE 0x7019c +-#define MRST_DSPBBASE 0x7119c +-#define MDFLD_DSPCBASE 0x7219c +- +-/* +- * Moorestown registers. +- */ +- +-/* +- * MIPI IP registers +- */ +-#define MIPIC_REG_OFFSET 0x800 +- +-#define DEVICE_READY_REG 0xb000 +-#define LP_OUTPUT_HOLD (1 << 16) +-#define EXIT_ULPS_DEV_READY 0x3 +-#define LP_OUTPUT_HOLD_RELEASE 0x810000 +-# define ENTERING_ULPS (2 << 1) +-# define EXITING_ULPS (1 << 1) +-# define ULPS_MASK (3 << 1) +-# define BUS_POSSESSION (1 << 3) +-#define INTR_STAT_REG 0xb004 +-#define RX_SOT_ERROR (1 << 0) +-#define RX_SOT_SYNC_ERROR (1 << 1) +-#define RX_ESCAPE_MODE_ENTRY_ERROR (1 << 3) +-#define RX_LP_TX_SYNC_ERROR (1 << 4) +-#define RX_HS_RECEIVE_TIMEOUT_ERROR (1 << 5) +-#define RX_FALSE_CONTROL_ERROR (1 << 6) +-#define RX_ECC_SINGLE_BIT_ERROR (1 << 7) +-#define RX_ECC_MULTI_BIT_ERROR (1 << 8) +-#define RX_CHECKSUM_ERROR (1 << 9) +-#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 10) +-#define RX_DSI_VC_ID_INVALID (1 << 11) +-#define TX_FALSE_CONTROL_ERROR (1 << 12) +-#define TX_ECC_SINGLE_BIT_ERROR (1 << 13) +-#define TX_ECC_MULTI_BIT_ERROR (1 << 14) +-#define TX_CHECKSUM_ERROR (1 << 15) +-#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 16) +-#define TX_DSI_VC_ID_INVALID (1 << 17) +-#define HIGH_CONTENTION (1 << 18) +-#define LOW_CONTENTION (1 << 19) +-#define DPI_FIFO_UNDER_RUN (1 << 20) +-#define HS_TX_TIMEOUT (1 << 21) +-#define LP_RX_TIMEOUT (1 << 22) +-#define TURN_AROUND_ACK_TIMEOUT (1 << 23) +-#define ACK_WITH_NO_ERROR (1 << 24) +-#define HS_GENERIC_WR_FIFO_FULL (1 << 27) +-#define LP_GENERIC_WR_FIFO_FULL (1 << 28) +-#define SPL_PKT_SENT (1 << 30) +-#define INTR_EN_REG 0xb008 +-#define DSI_FUNC_PRG_REG 0xb00c +-#define DPI_CHANNEL_NUMBER_POS 0x03 +-#define DBI_CHANNEL_NUMBER_POS 0x05 +-#define FMT_DPI_POS 0x07 +-#define FMT_DBI_POS 0x0A +-#define DBI_DATA_WIDTH_POS 0x0D +- +-/* DPI PIXEL FORMATS */ +-#define RGB_565_FMT 0x01 /* RGB 565 FORMAT */ +-#define RGB_666_FMT 0x02 /* RGB 666 FORMAT */ +-#define LRGB_666_FMT 0x03 /* RGB LOOSELY PACKED +- * 666 FORMAT +- */ +-#define RGB_888_FMT 0x04 /* RGB 888 FORMAT */ +-#define VIRTUAL_CHANNEL_NUMBER_0 0x00 /* Virtual channel 0 */ +-#define VIRTUAL_CHANNEL_NUMBER_1 0x01 /* Virtual channel 1 */ +-#define VIRTUAL_CHANNEL_NUMBER_2 0x02 /* Virtual channel 2 */ +-#define VIRTUAL_CHANNEL_NUMBER_3 0x03 /* Virtual channel 3 */ +- +-#define DBI_NOT_SUPPORTED 0x00 /* command mode +- * is not supported +- */ +-#define DBI_DATA_WIDTH_16BIT 0x01 /* 16 bit data */ +-#define DBI_DATA_WIDTH_9BIT 0x02 /* 9 bit data */ +-#define DBI_DATA_WIDTH_8BIT 0x03 /* 8 bit data */ +-#define DBI_DATA_WIDTH_OPT1 0x04 /* option 1 */ +-#define DBI_DATA_WIDTH_OPT2 0x05 /* option 2 */ +- +-#define HS_TX_TIMEOUT_REG 0xb010 +-#define LP_RX_TIMEOUT_REG 0xb014 +-#define TURN_AROUND_TIMEOUT_REG 0xb018 +-#define DEVICE_RESET_REG 0xb01C +-#define DPI_RESOLUTION_REG 0xb020 +-#define RES_V_POS 0x10 +-#define DBI_RESOLUTION_REG 0xb024 /* Reserved for MDFLD */ +-#define HORIZ_SYNC_PAD_COUNT_REG 0xb028 +-#define HORIZ_BACK_PORCH_COUNT_REG 0xb02C +-#define HORIZ_FRONT_PORCH_COUNT_REG 0xb030 +-#define HORIZ_ACTIVE_AREA_COUNT_REG 0xb034 +-#define VERT_SYNC_PAD_COUNT_REG 0xb038 +-#define VERT_BACK_PORCH_COUNT_REG 0xb03c +-#define VERT_FRONT_PORCH_COUNT_REG 0xb040 +-#define HIGH_LOW_SWITCH_COUNT_REG 0xb044 +-#define DPI_CONTROL_REG 0xb048 +-#define DPI_SHUT_DOWN (1 << 0) +-#define DPI_TURN_ON (1 << 1) +-#define DPI_COLOR_MODE_ON (1 << 2) +-#define DPI_COLOR_MODE_OFF (1 << 3) +-#define DPI_BACK_LIGHT_ON (1 << 4) +-#define DPI_BACK_LIGHT_OFF (1 << 5) +-#define DPI_LP (1 << 6) +-#define DPI_DATA_REG 0xb04c +-#define DPI_BACK_LIGHT_ON_DATA 0x07 +-#define DPI_BACK_LIGHT_OFF_DATA 0x17 +-#define INIT_COUNT_REG 0xb050 +-#define MAX_RET_PAK_REG 0xb054 +-#define VIDEO_FMT_REG 0xb058 +-#define COMPLETE_LAST_PCKT (1 << 2) +-#define EOT_DISABLE_REG 0xb05c +-#define ENABLE_CLOCK_STOPPING (1 << 1) +-#define LP_BYTECLK_REG 0xb060 +-#define LP_GEN_DATA_REG 0xb064 +-#define HS_GEN_DATA_REG 0xb068 +-#define LP_GEN_CTRL_REG 0xb06C +-#define HS_GEN_CTRL_REG 0xb070 +-#define DCS_CHANNEL_NUMBER_POS 0x6 +-#define MCS_COMMANDS_POS 0x8 +-#define WORD_COUNTS_POS 0x8 +-#define MCS_PARAMETER_POS 0x10 +-#define GEN_FIFO_STAT_REG 0xb074 +-#define HS_DATA_FIFO_FULL (1 << 0) +-#define HS_DATA_FIFO_HALF_EMPTY (1 << 1) +-#define HS_DATA_FIFO_EMPTY (1 << 2) +-#define LP_DATA_FIFO_FULL (1 << 8) +-#define LP_DATA_FIFO_HALF_EMPTY (1 << 9) +-#define LP_DATA_FIFO_EMPTY (1 << 10) +-#define HS_CTRL_FIFO_FULL (1 << 16) +-#define HS_CTRL_FIFO_HALF_EMPTY (1 << 17) +-#define HS_CTRL_FIFO_EMPTY (1 << 18) +-#define LP_CTRL_FIFO_FULL (1 << 24) +-#define LP_CTRL_FIFO_HALF_EMPTY (1 << 25) +-#define LP_CTRL_FIFO_EMPTY (1 << 26) +-#define DBI_FIFO_EMPTY (1 << 27) +-#define DPI_FIFO_EMPTY (1 << 28) +-#define HS_LS_DBI_ENABLE_REG 0xb078 +-#define TXCLKESC_REG 0xb07c +-#define DPHY_PARAM_REG 0xb080 +-#define DBI_BW_CTRL_REG 0xb084 +-#define CLK_LANE_SWT_REG 0xb088 +- +-/* +- * MIPI Adapter registers +- */ +-#define MIPI_CONTROL_REG 0xb104 +-#define MIPI_2X_CLOCK_BITS ((1 << 0) | (1 << 1)) +-#define MIPI_DATA_ADDRESS_REG 0xb108 +-#define MIPI_DATA_LENGTH_REG 0xb10C +-#define MIPI_COMMAND_ADDRESS_REG 0xb110 +-#define MIPI_COMMAND_LENGTH_REG 0xb114 +-#define MIPI_READ_DATA_RETURN_REG0 0xb118 +-#define MIPI_READ_DATA_RETURN_REG1 0xb11C +-#define MIPI_READ_DATA_RETURN_REG2 0xb120 +-#define MIPI_READ_DATA_RETURN_REG3 0xb124 +-#define MIPI_READ_DATA_RETURN_REG4 0xb128 +-#define MIPI_READ_DATA_RETURN_REG5 0xb12C +-#define MIPI_READ_DATA_RETURN_REG6 0xb130 +-#define MIPI_READ_DATA_RETURN_REG7 0xb134 +-#define MIPI_READ_DATA_VALID_REG 0xb138 +- +-/* DBI COMMANDS */ +-#define soft_reset 0x01 +-/* +- * The display module performs a software reset. +- * Registers are written with their SW Reset default values. +- */ +-#define get_power_mode 0x0a +-/* +- * The display module returns the current power mode +- */ +-#define get_address_mode 0x0b +-/* +- * The display module returns the current status. +- */ +-#define get_pixel_format 0x0c +-/* +- * This command gets the pixel format for the RGB image data +- * used by the interface. +- */ +-#define get_display_mode 0x0d +-/* +- * The display module returns the Display Image Mode status. +- */ +-#define get_signal_mode 0x0e +-/* +- * The display module returns the Display Signal Mode. +- */ +-#define get_diagnostic_result 0x0f +-/* +- * The display module returns the self-diagnostic results following +- * a Sleep Out command. +- */ +-#define enter_sleep_mode 0x10 +-/* +- * This command causes the display module to enter the Sleep mode. +- * In this mode, all unnecessary blocks inside the display module are +- * disabled except interface communication. This is the lowest power +- * mode the display module supports. +- */ +-#define exit_sleep_mode 0x11 +-/* +- * This command causes the display module to exit Sleep mode. +- * All blocks inside the display module are enabled. +- */ +-#define enter_partial_mode 0x12 +-/* +- * This command causes the display module to enter the Partial Display +- * Mode. The Partial Display Mode window is described by the +- * set_partial_area command. +- */ +-#define enter_normal_mode 0x13 +-/* +- * This command causes the display module to enter the Normal mode. +- * Normal Mode is defined as Partial Display mode and Scroll mode are off +- */ +-#define exit_invert_mode 0x20 +-/* +- * This command causes the display module to stop inverting the image +- * data on the display device. The frame memory contents remain unchanged. +- * No status bits are changed. +- */ +-#define enter_invert_mode 0x21 +-/* +- * This command causes the display module to invert the image data only on +- * the display device. The frame memory contents remain unchanged. +- * No status bits are changed. +- */ +-#define set_gamma_curve 0x26 +-/* +- * This command selects the desired gamma curve for the display device. +- * Four fixed gamma curves are defined in section DCS spec. +- */ +-#define set_display_off 0x28 +-/* ************************************************************************* *\ +-This command causes the display module to stop displaying the image data +-on the display device. The frame memory contents remain unchanged. +-No status bits are changed. +-\* ************************************************************************* */ +-#define set_display_on 0x29 +-/* ************************************************************************* *\ +-This command causes the display module to start displaying the image data +-on the display device. The frame memory contents remain unchanged. +-No status bits are changed. +-\* ************************************************************************* */ +-#define set_column_address 0x2a +-/* +- * This command defines the column extent of the frame memory accessed by +- * the hostprocessor with the read_memory_continue and +- * write_memory_continue commands. +- * No status bits are changed. +- */ +-#define set_page_addr 0x2b +-/* +- * This command defines the page extent of the frame memory accessed by +- * the host processor with the write_memory_continue and +- * read_memory_continue command. +- * No status bits are changed. +- */ +-#define write_mem_start 0x2c +-/* +- * This command transfers image data from the host processor to the +- * display modules frame memory starting at the pixel location specified +- * by preceding set_column_address and set_page_address commands. +- */ +-#define set_partial_area 0x30 +-/* +- * This command defines the Partial Display mode s display area. +- * There are two parameters associated with this command, the first +- * defines the Start Row (SR) and the second the End Row (ER). SR and ER +- * refer to the Frame Memory Line Pointer. +- */ +-#define set_scroll_area 0x33 +-/* +- * This command defines the display modules Vertical Scrolling Area. +- */ +-#define set_tear_off 0x34 +-/* +- * This command turns off the display modules Tearing Effect output +- * signal on the TE signal line. +- */ +-#define set_tear_on 0x35 +-/* +- * This command turns on the display modules Tearing Effect output signal +- * on the TE signal line. +- */ +-#define set_address_mode 0x36 +-/* +- * This command sets the data order for transfers from the host processor +- * to display modules frame memory,bits B[7:5] and B3, and from the +- * display modules frame memory to the display device, bits B[2:0] and B4. +- */ +-#define set_scroll_start 0x37 +-/* +- * This command sets the start of the vertical scrolling area in the frame +- * memory. The vertical scrolling area is fully defined when this command +- * is used with the set_scroll_area command The set_scroll_start command +- * has one parameter, the Vertical Scroll Pointer. The VSP defines the +- * line in the frame memory that is written to the display device as the +- * first line of the vertical scroll area. +- */ +-#define exit_idle_mode 0x38 +-/* +- * This command causes the display module to exit Idle mode. +- */ +-#define enter_idle_mode 0x39 +-/* +- * This command causes the display module to enter Idle Mode. +- * In Idle Mode, color expression is reduced. Colors are shown on the +- * display device using the MSB of each of the R, G and B color +- * components in the frame memory +- */ +-#define set_pixel_format 0x3a +-/* +- * This command sets the pixel format for the RGB image data used by the +- * interface. +- * Bits D[6:4] DPI Pixel Format Definition +- * Bits D[2:0] DBI Pixel Format Definition +- * Bits D7 and D3 are not used. +- */ +-#define DCS_PIXEL_FORMAT_3bpp 0x1 +-#define DCS_PIXEL_FORMAT_8bpp 0x2 +-#define DCS_PIXEL_FORMAT_12bpp 0x3 +-#define DCS_PIXEL_FORMAT_16bpp 0x5 +-#define DCS_PIXEL_FORMAT_18bpp 0x6 +-#define DCS_PIXEL_FORMAT_24bpp 0x7 +- +-#define write_mem_cont 0x3c +- +-/* +- * This command transfers image data from the host processor to the +- * display module's frame memory continuing from the pixel location +- * following the previous write_memory_continue or write_memory_start +- * command. +- */ +-#define set_tear_scanline 0x44 +-/* +- * This command turns on the display modules Tearing Effect output signal +- * on the TE signal line when the display module reaches line N. +- */ +-#define get_scanline 0x45 +-/* +- * The display module returns the current scanline, N, used to update the +- * display device. The total number of scanlines on a display device is +- * defined as VSYNC + VBP + VACT + VFP.The first scanline is defined as +- * the first line of V Sync and is denoted as Line 0. +- * When in Sleep Mode, the value returned by get_scanline is undefined. +- */ +- +-/* MCS or Generic COMMANDS */ +-/* MCS/generic data type */ +-#define GEN_SHORT_WRITE_0 0x03 /* generic short write, no parameters */ +-#define GEN_SHORT_WRITE_1 0x13 /* generic short write, 1 parameters */ +-#define GEN_SHORT_WRITE_2 0x23 /* generic short write, 2 parameters */ +-#define GEN_READ_0 0x04 /* generic read, no parameters */ +-#define GEN_READ_1 0x14 /* generic read, 1 parameters */ +-#define GEN_READ_2 0x24 /* generic read, 2 parameters */ +-#define GEN_LONG_WRITE 0x29 /* generic long write */ +-#define MCS_SHORT_WRITE_0 0x05 /* MCS short write, no parameters */ +-#define MCS_SHORT_WRITE_1 0x15 /* MCS short write, 1 parameters */ +-#define MCS_READ 0x06 /* MCS read, no parameters */ +-#define MCS_LONG_WRITE 0x39 /* MCS long write */ +-/* MCS/generic commands */ +-/* TPO MCS */ +-#define write_display_profile 0x50 +-#define write_display_brightness 0x51 +-#define write_ctrl_display 0x53 +-#define write_ctrl_cabc 0x55 +- #define UI_IMAGE 0x01 +- #define STILL_IMAGE 0x02 +- #define MOVING_IMAGE 0x03 +-#define write_hysteresis 0x57 +-#define write_gamma_setting 0x58 +-#define write_cabc_min_bright 0x5e +-#define write_kbbc_profile 0x60 +-/* TMD MCS */ +-#define tmd_write_display_brightness 0x8c +- +-/* +- * This command is used to control ambient light, panel backlight +- * brightness and gamma settings. +- */ +-#define BRIGHT_CNTL_BLOCK_ON (1 << 5) +-#define AMBIENT_LIGHT_SENSE_ON (1 << 4) +-#define DISPLAY_DIMMING_ON (1 << 3) +-#define BACKLIGHT_ON (1 << 2) +-#define DISPLAY_BRIGHTNESS_AUTO (1 << 1) +-#define GAMMA_AUTO (1 << 0) +- +-/* DCS Interface Pixel Formats */ +-#define DCS_PIXEL_FORMAT_3BPP 0x1 +-#define DCS_PIXEL_FORMAT_8BPP 0x2 +-#define DCS_PIXEL_FORMAT_12BPP 0x3 +-#define DCS_PIXEL_FORMAT_16BPP 0x5 +-#define DCS_PIXEL_FORMAT_18BPP 0x6 +-#define DCS_PIXEL_FORMAT_24BPP 0x7 +-/* ONE PARAMETER READ DATA */ +-#define addr_mode_data 0xfc +-#define diag_res_data 0x00 +-#define disp_mode_data 0x23 +-#define pxl_fmt_data 0x77 +-#define pwr_mode_data 0x74 +-#define sig_mode_data 0x00 +-/* TWO PARAMETERS READ DATA */ +-#define scanline_data1 0xff +-#define scanline_data2 0xff +-#define NON_BURST_MODE_SYNC_PULSE 0x01 /* Non Burst Mode +- * with Sync Pulse +- */ +-#define NON_BURST_MODE_SYNC_EVENTS 0x02 /* Non Burst Mode +- * with Sync events +- */ +-#define BURST_MODE 0x03 /* Burst Mode */ +-#define DBI_COMMAND_BUFFER_SIZE 0x240 /* 0x32 */ /* 0x120 */ +- /* Allocate at least +- * 0x100 Byte with 32 +- * byte alignment +- */ +-#define DBI_DATA_BUFFER_SIZE 0x120 /* Allocate at least +- * 0x100 Byte with 32 +- * byte alignment +- */ +-#define DBI_CB_TIME_OUT 0xFFFF +- +-#define GEN_FB_TIME_OUT 2000 +- +-#define SKU_83 0x01 +-#define SKU_100 0x02 +-#define SKU_100L 0x04 +-#define SKU_BYPASS 0x08 +- +-/* Some handy macros for playing with bitfields. */ +-#define PSB_MASK(high, low) (((1<<((high)-(low)+1))-1)<<(low)) +-#define SET_FIELD(value, field) (((value) << field ## _SHIFT) & field ## _MASK) +-#define GET_FIELD(word, field) (((word) & field ## _MASK) >> field ## _SHIFT) +- +-#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) +- +-/* PCI config space */ +- +-#define SB_PCKT 0x02100 /* cedarview */ +-# define SB_OPCODE_MASK PSB_MASK(31, 16) +-# define SB_OPCODE_SHIFT 16 +-# define SB_OPCODE_READ 0 +-# define SB_OPCODE_WRITE 1 +-# define SB_DEST_MASK PSB_MASK(15, 8) +-# define SB_DEST_SHIFT 8 +-# define SB_DEST_DPLL 0x88 +-# define SB_BYTE_ENABLE_MASK PSB_MASK(7, 4) +-# define SB_BYTE_ENABLE_SHIFT 4 +-# define SB_BUSY (1 << 0) +- +- +-/* 32-bit value read/written from the DPIO reg. */ +-#define SB_DATA 0x02104 /* cedarview */ +-/* 32-bit address of the DPIO reg to be read/written. */ +-#define SB_ADDR 0x02108 /* cedarview */ +-#define DPIO_CFG 0x02110 /* cedarview */ +-# define DPIO_MODE_SELECT_1 (1 << 3) +-# define DPIO_MODE_SELECT_0 (1 << 2) +-# define DPIO_SFR_BYPASS (1 << 1) +-/* reset is active low */ +-# define DPIO_CMN_RESET_N (1 << 0) +- +-/* Cedarview sideband registers */ +-#define _SB_M_A 0x8008 +-#define _SB_M_B 0x8028 +-#define SB_M(pipe) _PIPE(pipe, _SB_M_A, _SB_M_B) +-# define SB_M_DIVIDER_MASK (0xFF << 24) +-# define SB_M_DIVIDER_SHIFT 24 +- +-#define _SB_N_VCO_A 0x8014 +-#define _SB_N_VCO_B 0x8034 +-#define SB_N_VCO(pipe) _PIPE(pipe, _SB_N_VCO_A, _SB_N_VCO_B) +-#define SB_N_VCO_SEL_MASK PSB_MASK(31, 30) +-#define SB_N_VCO_SEL_SHIFT 30 +-#define SB_N_DIVIDER_MASK PSB_MASK(29, 26) +-#define SB_N_DIVIDER_SHIFT 26 +-#define SB_N_CB_TUNE_MASK PSB_MASK(25, 24) +-#define SB_N_CB_TUNE_SHIFT 24 +- +-#define _SB_REF_A 0x8018 +-#define _SB_REF_B 0x8038 +-#define SB_REF_SFR(pipe) _PIPE(pipe, _SB_REF_A, _SB_REF_B) +- +-#define _SB_P_A 0x801c +-#define _SB_P_B 0x803c +-#define SB_P(pipe) _PIPE(pipe, _SB_P_A, _SB_P_B) +-#define SB_P2_DIVIDER_MASK PSB_MASK(31, 30) +-#define SB_P2_DIVIDER_SHIFT 30 +-#define SB_P2_10 0 /* HDMI, DP, DAC */ +-#define SB_P2_5 1 /* DAC */ +-#define SB_P2_14 2 /* LVDS single */ +-#define SB_P2_7 3 /* LVDS double */ +-#define SB_P1_DIVIDER_MASK PSB_MASK(15, 12) +-#define SB_P1_DIVIDER_SHIFT 12 +- +-#define PSB_LANE0 0x120 +-#define PSB_LANE1 0x220 +-#define PSB_LANE2 0x2320 +-#define PSB_LANE3 0x2420 +- +-#define LANE_PLL_MASK (0x7 << 20) +-#define LANE_PLL_ENABLE (0x3 << 20) +- +- +-#endif +diff --git a/drivers/staging/gma500/psb_intel_sdvo.c b/drivers/staging/gma500/psb_intel_sdvo.c +deleted file mode 100644 +index a4bad1a..0000000 +--- a/drivers/staging/gma500/psb_intel_sdvo.c ++++ /dev/null +@@ -1,1293 +0,0 @@ +-/* +- * Copyright (c) 2006-2007 Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Eric Anholt +- */ +- +-#include +-#include +-/* #include */ +-#include +-#include "psb_drv.h" +-#include "psb_intel_drv.h" +-#include "psb_intel_reg.h" +-#include "psb_intel_sdvo_regs.h" +- +-struct psb_intel_sdvo_priv { +- struct psb_intel_i2c_chan *i2c_bus; +- int slaveaddr; +- int output_device; +- +- u16 active_outputs; +- +- struct psb_intel_sdvo_caps caps; +- int pixel_clock_min, pixel_clock_max; +- +- int save_sdvo_mult; +- u16 save_active_outputs; +- struct psb_intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2; +- struct psb_intel_sdvo_dtd save_output_dtd[16]; +- u32 save_SDVOX; +- u8 in_out_map[4]; +- +- u8 by_input_wiring; +- u32 active_device; +-}; +- +-/** +- * Writes the SDVOB or SDVOC with the given value, but always writes both +- * SDVOB and SDVOC to work around apparent hardware issues (according to +- * comments in the BIOS). +- */ +-void psb_intel_sdvo_write_sdvox(struct psb_intel_output *psb_intel_output, +- u32 val) +-{ +- struct drm_device *dev = psb_intel_output->base.dev; +- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; +- u32 bval = val, cval = val; +- int i; +- +- if (sdvo_priv->output_device == SDVOB) +- cval = REG_READ(SDVOC); +- else +- bval = REG_READ(SDVOB); +- /* +- * Write the registers twice for luck. Sometimes, +- * writing them only once doesn't appear to 'stick'. +- * The BIOS does this too. Yay, magic +- */ +- for (i = 0; i < 2; i++) { +- REG_WRITE(SDVOB, bval); +- REG_READ(SDVOB); +- REG_WRITE(SDVOC, cval); +- REG_READ(SDVOC); +- } +-} +- +-static bool psb_intel_sdvo_read_byte( +- struct psb_intel_output *psb_intel_output, +- u8 addr, u8 *ch) +-{ +- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; +- u8 out_buf[2]; +- u8 buf[2]; +- int ret; +- +- struct i2c_msg msgs[] = { +- { +- .addr = sdvo_priv->i2c_bus->slave_addr, +- .flags = 0, +- .len = 1, +- .buf = out_buf, +- }, +- { +- .addr = sdvo_priv->i2c_bus->slave_addr, +- .flags = I2C_M_RD, +- .len = 1, +- .buf = buf, +- } +- }; +- +- out_buf[0] = addr; +- out_buf[1] = 0; +- +- ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2); +- if (ret == 2) { +- *ch = buf[0]; +- return true; +- } +- +- return false; +-} +- +-static bool psb_intel_sdvo_write_byte( +- struct psb_intel_output *psb_intel_output, +- int addr, u8 ch) +-{ +- u8 out_buf[2]; +- struct i2c_msg msgs[] = { +- { +- .addr = psb_intel_output->i2c_bus->slave_addr, +- .flags = 0, +- .len = 2, +- .buf = out_buf, +- } +- }; +- +- out_buf[0] = addr; +- out_buf[1] = ch; +- +- if (i2c_transfer(&psb_intel_output->i2c_bus->adapter, msgs, 1) == 1) +- return true; +- return false; +-} +- +-#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} +-/** Mapping of command numbers to names, for debug output */ +-static const struct _sdvo_cmd_name { +- u8 cmd; +- char *name; +-} sdvo_cmd_names[] = { +-SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG), +- SDVO_CMD_NAME_ENTRY +- (SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2), +- SDVO_CMD_NAME_ENTRY +- (SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING), +- SDVO_CMD_NAME_ENTRY +- (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1), +- SDVO_CMD_NAME_ENTRY +- (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2), +- SDVO_CMD_NAME_ENTRY +- (SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE), +- SDVO_CMD_NAME_ENTRY +- (SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE), +- SDVO_CMD_NAME_ENTRY +- (SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), +- SDVO_CMD_NAME_ENTRY +- (SDVO_CMD_SET_TV_RESOLUTION_SUPPORT), +- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),}; +- +-#define SDVO_NAME(dev_priv) \ +- ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC") +-#define SDVO_PRIV(output) ((struct psb_intel_sdvo_priv *) (output)->dev_priv) +- +-static void psb_intel_sdvo_write_cmd(struct psb_intel_output *psb_intel_output, +- u8 cmd, +- void *args, +- int args_len) +-{ +- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; +- int i; +- +- if (0) { +- printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd); +- for (i = 0; i < args_len; i++) +- printk(KERN_CONT "%02X ", ((u8 *) args)[i]); +- for (; i < 8; i++) +- printk(KERN_CONT " "); +- for (i = 0; +- i < +- sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); +- i++) { +- if (cmd == sdvo_cmd_names[i].cmd) { +- printk(KERN_CONT +- "(%s)", sdvo_cmd_names[i].name); +- break; +- } +- } +- if (i == +- sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0])) +- printk(KERN_CONT "(%02X)", cmd); +- printk(KERN_CONT "\n"); +- } +- +- for (i = 0; i < args_len; i++) { +- psb_intel_sdvo_write_byte(psb_intel_output, +- SDVO_I2C_ARG_0 - i, +- ((u8 *) args)[i]); +- } +- +- psb_intel_sdvo_write_byte(psb_intel_output, SDVO_I2C_OPCODE, cmd); +-} +- +-static const char *const cmd_status_names[] = { +- "Power on", +- "Success", +- "Not supported", +- "Invalid arg", +- "Pending", +- "Target not specified", +- "Scaling not supported" +-}; +- +-static u8 psb_intel_sdvo_read_response( +- struct psb_intel_output *psb_intel_output, +- void *response, int response_len) +-{ +- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; +- int i; +- u8 status; +- u8 retry = 50; +- +- while (retry--) { +- /* Read the command response */ +- for (i = 0; i < response_len; i++) { +- psb_intel_sdvo_read_byte(psb_intel_output, +- SDVO_I2C_RETURN_0 + i, +- &((u8 *) response)[i]); +- } +- +- /* read the return status */ +- psb_intel_sdvo_read_byte(psb_intel_output, +- SDVO_I2C_CMD_STATUS, +- &status); +- +- if (0) { +- pr_debug("%s: R: ", SDVO_NAME(sdvo_priv)); +- for (i = 0; i < response_len; i++) +- printk(KERN_CONT "%02X ", ((u8 *) response)[i]); +- for (; i < 8; i++) +- printk(" "); +- if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) +- printk(KERN_CONT "(%s)", +- cmd_status_names[status]); +- else +- printk(KERN_CONT "(??? %d)", status); +- printk(KERN_CONT "\n"); +- } +- +- if (status != SDVO_CMD_STATUS_PENDING) +- return status; +- +- mdelay(50); +- } +- +- return status; +-} +- +-int psb_intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) +-{ +- if (mode->clock >= 100000) +- return 1; +- else if (mode->clock >= 50000) +- return 2; +- else +- return 4; +-} +- +-/** +- * Don't check status code from this as it switches the bus back to the +- * SDVO chips which defeats the purpose of doing a bus switch in the first +- * place. +- */ +-void psb_intel_sdvo_set_control_bus_switch( +- struct psb_intel_output *psb_intel_output, +- u8 target) +-{ +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_SET_CONTROL_BUS_SWITCH, +- &target, +- 1); +-} +- +-static bool psb_intel_sdvo_set_target_input( +- struct psb_intel_output *psb_intel_output, +- bool target_0, bool target_1) +-{ +- struct psb_intel_sdvo_set_target_input_args targets = { 0 }; +- u8 status; +- +- if (target_0 && target_1) +- return SDVO_CMD_STATUS_NOTSUPP; +- +- if (target_1) +- targets.target_1 = 1; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_INPUT, +- &targets, sizeof(targets)); +- +- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); +- +- return status == SDVO_CMD_STATUS_SUCCESS; +-} +- +-/** +- * Return whether each input is trained. +- * +- * This function is making an assumption about the layout of the response, +- * which should be checked against the docs. +- */ +-static bool psb_intel_sdvo_get_trained_inputs(struct psb_intel_output +- *psb_intel_output, bool *input_1, +- bool *input_2) +-{ +- struct psb_intel_sdvo_get_trained_inputs_response response; +- u8 status; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_TRAINED_INPUTS, +- NULL, 0); +- status = +- psb_intel_sdvo_read_response(psb_intel_output, &response, +- sizeof(response)); +- if (status != SDVO_CMD_STATUS_SUCCESS) +- return false; +- +- *input_1 = response.input0_trained; +- *input_2 = response.input1_trained; +- return true; +-} +- +-static bool psb_intel_sdvo_get_active_outputs(struct psb_intel_output +- *psb_intel_output, u16 *outputs) +-{ +- u8 status; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_ACTIVE_OUTPUTS, +- NULL, 0); +- status = +- psb_intel_sdvo_read_response(psb_intel_output, outputs, +- sizeof(*outputs)); +- +- return status == SDVO_CMD_STATUS_SUCCESS; +-} +- +-static bool psb_intel_sdvo_set_active_outputs(struct psb_intel_output +- *psb_intel_output, u16 outputs) +-{ +- u8 status; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_ACTIVE_OUTPUTS, +- &outputs, sizeof(outputs)); +- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); +- return status == SDVO_CMD_STATUS_SUCCESS; +-} +- +-static bool psb_intel_sdvo_set_encoder_power_state(struct psb_intel_output +- *psb_intel_output, int mode) +-{ +- u8 status, state = SDVO_ENCODER_STATE_ON; +- +- switch (mode) { +- case DRM_MODE_DPMS_ON: +- state = SDVO_ENCODER_STATE_ON; +- break; +- case DRM_MODE_DPMS_STANDBY: +- state = SDVO_ENCODER_STATE_STANDBY; +- break; +- case DRM_MODE_DPMS_SUSPEND: +- state = SDVO_ENCODER_STATE_SUSPEND; +- break; +- case DRM_MODE_DPMS_OFF: +- state = SDVO_ENCODER_STATE_OFF; +- break; +- } +- +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_SET_ENCODER_POWER_STATE, &state, +- sizeof(state)); +- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); +- +- return status == SDVO_CMD_STATUS_SUCCESS; +-} +- +-static bool psb_intel_sdvo_get_input_pixel_clock_range(struct psb_intel_output +- *psb_intel_output, +- int *clock_min, +- int *clock_max) +-{ +- struct psb_intel_sdvo_pixel_clock_range clocks; +- u8 status; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, NULL, +- 0); +- +- status = +- psb_intel_sdvo_read_response(psb_intel_output, &clocks, +- sizeof(clocks)); +- +- if (status != SDVO_CMD_STATUS_SUCCESS) +- return false; +- +- /* Convert the values from units of 10 kHz to kHz. */ +- *clock_min = clocks.min * 10; +- *clock_max = clocks.max * 10; +- +- return true; +-} +- +-static bool psb_intel_sdvo_set_target_output( +- struct psb_intel_output *psb_intel_output, +- u16 outputs) +-{ +- u8 status; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_OUTPUT, +- &outputs, sizeof(outputs)); +- +- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); +- return status == SDVO_CMD_STATUS_SUCCESS; +-} +- +-static bool psb_intel_sdvo_get_timing(struct psb_intel_output *psb_intel_output, +- u8 cmd, struct psb_intel_sdvo_dtd *dtd) +-{ +- u8 status; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, cmd, NULL, 0); +- status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part1, +- sizeof(dtd->part1)); +- if (status != SDVO_CMD_STATUS_SUCCESS) +- return false; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, NULL, 0); +- status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part2, +- sizeof(dtd->part2)); +- if (status != SDVO_CMD_STATUS_SUCCESS) +- return false; +- +- return true; +-} +- +-static bool psb_intel_sdvo_get_input_timing( +- struct psb_intel_output *psb_intel_output, +- struct psb_intel_sdvo_dtd *dtd) +-{ +- return psb_intel_sdvo_get_timing(psb_intel_output, +- SDVO_CMD_GET_INPUT_TIMINGS_PART1, +- dtd); +-} +- +-static bool psb_intel_sdvo_set_timing( +- struct psb_intel_output *psb_intel_output, +- u8 cmd, +- struct psb_intel_sdvo_dtd *dtd) +-{ +- u8 status; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, cmd, &dtd->part1, +- sizeof(dtd->part1)); +- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); +- if (status != SDVO_CMD_STATUS_SUCCESS) +- return false; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, &dtd->part2, +- sizeof(dtd->part2)); +- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); +- if (status != SDVO_CMD_STATUS_SUCCESS) +- return false; +- +- return true; +-} +- +-static bool psb_intel_sdvo_set_input_timing( +- struct psb_intel_output *psb_intel_output, +- struct psb_intel_sdvo_dtd *dtd) +-{ +- return psb_intel_sdvo_set_timing(psb_intel_output, +- SDVO_CMD_SET_INPUT_TIMINGS_PART1, +- dtd); +-} +- +-static bool psb_intel_sdvo_set_output_timing( +- struct psb_intel_output *psb_intel_output, +- struct psb_intel_sdvo_dtd *dtd) +-{ +- return psb_intel_sdvo_set_timing(psb_intel_output, +- SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, +- dtd); +-} +- +-static int psb_intel_sdvo_get_clock_rate_mult(struct psb_intel_output +- *psb_intel_output) +-{ +- u8 response, status; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_GET_CLOCK_RATE_MULT, +- NULL, +- 0); +- +- status = psb_intel_sdvo_read_response(psb_intel_output, &response, 1); +- +- if (status != SDVO_CMD_STATUS_SUCCESS) { +- DRM_DEBUG("Couldn't get SDVO clock rate multiplier\n"); +- return SDVO_CLOCK_RATE_MULT_1X; +- } else { +- DRM_DEBUG("Current clock rate multiplier: %d\n", response); +- } +- +- return response; +-} +- +-static bool psb_intel_sdvo_set_clock_rate_mult(struct psb_intel_output +- *psb_intel_output, u8 val) +-{ +- u8 status; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_SET_CLOCK_RATE_MULT, +- &val, +- 1); +- +- status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); +- if (status != SDVO_CMD_STATUS_SUCCESS) +- return false; +- +- return true; +-} +- +-static bool psb_sdvo_set_current_inoutmap(struct psb_intel_output *output, +- u32 in0outputmask, +- u32 in1outputmask) +-{ +- u8 byArgs[4]; +- u8 status; +- int i; +- struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv; +- +- /* Make all fields of the args/ret to zero */ +- memset(byArgs, 0, sizeof(byArgs)); +- +- /* Fill up the argument values; */ +- byArgs[0] = (u8) (in0outputmask & 0xFF); +- byArgs[1] = (u8) ((in0outputmask >> 8) & 0xFF); +- byArgs[2] = (u8) (in1outputmask & 0xFF); +- byArgs[3] = (u8) ((in1outputmask >> 8) & 0xFF); +- +- +- /*save inoutmap arg here*/ +- for (i = 0; i < 4; i++) +- sdvo_priv->in_out_map[i] = byArgs[0]; +- +- psb_intel_sdvo_write_cmd(output, SDVO_CMD_SET_IN_OUT_MAP, byArgs, 4); +- status = psb_intel_sdvo_read_response(output, NULL, 0); +- +- if (status != SDVO_CMD_STATUS_SUCCESS) +- return false; +- return true; +-} +- +- +-static void psb_intel_sdvo_set_iomap(struct psb_intel_output *output) +-{ +- u32 dwCurrentSDVOIn0 = 0; +- u32 dwCurrentSDVOIn1 = 0; +- u32 dwDevMask = 0; +- +- +- struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv; +- +- /* Please DO NOT change the following code. */ +- /* SDVOB_IN0 or SDVOB_IN1 ==> sdvo_in0 */ +- /* SDVOC_IN0 or SDVOC_IN1 ==> sdvo_in1 */ +- if (sdvo_priv->by_input_wiring & (SDVOB_IN0 | SDVOC_IN0)) { +- switch (sdvo_priv->active_device) { +- case SDVO_DEVICE_LVDS: +- dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1; +- break; +- case SDVO_DEVICE_TMDS: +- dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1; +- break; +- case SDVO_DEVICE_TV: +- dwDevMask = +- SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 | +- SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 | +- SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 | +- SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1; +- break; +- case SDVO_DEVICE_CRT: +- dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1; +- break; +- } +- dwCurrentSDVOIn0 = (sdvo_priv->active_outputs & dwDevMask); +- } else if (sdvo_priv->by_input_wiring & (SDVOB_IN1 | SDVOC_IN1)) { +- switch (sdvo_priv->active_device) { +- case SDVO_DEVICE_LVDS: +- dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1; +- break; +- case SDVO_DEVICE_TMDS: +- dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1; +- break; +- case SDVO_DEVICE_TV: +- dwDevMask = +- SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 | +- SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 | +- SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 | +- SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1; +- break; +- case SDVO_DEVICE_CRT: +- dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1; +- break; +- } +- dwCurrentSDVOIn1 = (sdvo_priv->active_outputs & dwDevMask); +- } +- +- psb_sdvo_set_current_inoutmap(output, dwCurrentSDVOIn0, +- dwCurrentSDVOIn1); +-} +- +- +-static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- /* Make the CRTC code factor in the SDVO pixel multiplier. The SDVO +- * device will be told of the multiplier during mode_set. +- */ +- adjusted_mode->clock *= psb_intel_sdvo_get_pixel_multiplier(mode); +- return true; +-} +- +-static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder, +- struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- struct drm_device *dev = encoder->dev; +- struct drm_crtc *crtc = encoder->crtc; +- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); +- struct psb_intel_output *psb_intel_output = +- enc_to_psb_intel_output(encoder); +- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; +- u16 width, height; +- u16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; +- u16 h_sync_offset, v_sync_offset; +- u32 sdvox; +- struct psb_intel_sdvo_dtd output_dtd; +- int sdvo_pixel_multiply; +- +- if (!mode) +- return; +- +- psb_intel_sdvo_set_target_output(psb_intel_output, 0); +- +- width = mode->crtc_hdisplay; +- height = mode->crtc_vdisplay; +- +- /* do some mode translations */ +- h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start; +- h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; +- +- v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start; +- v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; +- +- h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; +- v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; +- +- output_dtd.part1.clock = mode->clock / 10; +- output_dtd.part1.h_active = width & 0xff; +- output_dtd.part1.h_blank = h_blank_len & 0xff; +- output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) | +- ((h_blank_len >> 8) & 0xf); +- output_dtd.part1.v_active = height & 0xff; +- output_dtd.part1.v_blank = v_blank_len & 0xff; +- output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) | +- ((v_blank_len >> 8) & 0xf); +- +- output_dtd.part2.h_sync_off = h_sync_offset; +- output_dtd.part2.h_sync_width = h_sync_len & 0xff; +- output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | +- (v_sync_len & 0xf); +- output_dtd.part2.sync_off_width_high = +- ((h_sync_offset & 0x300) >> 2) | ((h_sync_len & 0x300) >> 4) | +- ((v_sync_offset & 0x30) >> 2) | ((v_sync_len & 0x30) >> 4); +- +- output_dtd.part2.dtd_flags = 0x18; +- if (mode->flags & DRM_MODE_FLAG_PHSYNC) +- output_dtd.part2.dtd_flags |= 0x2; +- if (mode->flags & DRM_MODE_FLAG_PVSYNC) +- output_dtd.part2.dtd_flags |= 0x4; +- +- output_dtd.part2.sdvo_flags = 0; +- output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0; +- output_dtd.part2.reserved = 0; +- +- /* Set the output timing to the screen */ +- psb_intel_sdvo_set_target_output(psb_intel_output, +- sdvo_priv->active_outputs); +- +- /* Set the input timing to the screen. Assume always input 0. */ +- psb_intel_sdvo_set_target_input(psb_intel_output, true, false); +- +- psb_intel_sdvo_set_output_timing(psb_intel_output, &output_dtd); +- +- /* We would like to use i830_sdvo_create_preferred_input_timing() to +- * provide the device with a timing it can support, if it supports that +- * feature. However, presumably we would need to adjust the CRTC to +- * output the preferred timing, and we don't support that currently. +- */ +- psb_intel_sdvo_set_input_timing(psb_intel_output, &output_dtd); +- +- switch (psb_intel_sdvo_get_pixel_multiplier(mode)) { +- case 1: +- psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, +- SDVO_CLOCK_RATE_MULT_1X); +- break; +- case 2: +- psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, +- SDVO_CLOCK_RATE_MULT_2X); +- break; +- case 4: +- psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, +- SDVO_CLOCK_RATE_MULT_4X); +- break; +- } +- +- /* Set the SDVO control regs. */ +- sdvox = REG_READ(sdvo_priv->output_device); +- switch (sdvo_priv->output_device) { +- case SDVOB: +- sdvox &= SDVOB_PRESERVE_MASK; +- break; +- case SDVOC: +- sdvox &= SDVOC_PRESERVE_MASK; +- break; +- } +- sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; +- if (psb_intel_crtc->pipe == 1) +- sdvox |= SDVO_PIPE_B_SELECT; +- +- sdvo_pixel_multiply = psb_intel_sdvo_get_pixel_multiplier(mode); +- +- psb_intel_sdvo_write_sdvox(psb_intel_output, sdvox); +- +- psb_intel_sdvo_set_iomap(psb_intel_output); +-} +- +-static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode) +-{ +- struct drm_device *dev = encoder->dev; +- struct psb_intel_output *psb_intel_output = +- enc_to_psb_intel_output(encoder); +- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; +- u32 temp; +- +- if (mode != DRM_MODE_DPMS_ON) { +- psb_intel_sdvo_set_active_outputs(psb_intel_output, 0); +- if (0) +- psb_intel_sdvo_set_encoder_power_state( +- psb_intel_output, +- mode); +- +- if (mode == DRM_MODE_DPMS_OFF) { +- temp = REG_READ(sdvo_priv->output_device); +- if ((temp & SDVO_ENABLE) != 0) { +- psb_intel_sdvo_write_sdvox(psb_intel_output, +- temp & +- ~SDVO_ENABLE); +- } +- } +- } else { +- bool input1, input2; +- int i; +- u8 status; +- +- temp = REG_READ(sdvo_priv->output_device); +- if ((temp & SDVO_ENABLE) == 0) +- psb_intel_sdvo_write_sdvox(psb_intel_output, +- temp | SDVO_ENABLE); +- for (i = 0; i < 2; i++) +- psb_intel_wait_for_vblank(dev); +- +- status = +- psb_intel_sdvo_get_trained_inputs(psb_intel_output, +- &input1, +- &input2); +- +- +- /* Warn if the device reported failure to sync. +- * A lot of SDVO devices fail to notify of sync, but it's +- * a given it the status is a success, we succeeded. +- */ +- if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { +- DRM_DEBUG +- ("First %s output reported failure to sync\n", +- SDVO_NAME(sdvo_priv)); +- } +- +- if (0) +- psb_intel_sdvo_set_encoder_power_state( +- psb_intel_output, +- mode); +- psb_intel_sdvo_set_active_outputs(psb_intel_output, +- sdvo_priv->active_outputs); +- } +- return; +-} +- +-static void psb_intel_sdvo_save(struct drm_connector *connector) +-{ +- struct drm_device *dev = connector->dev; +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; +- /*int o;*/ +- +- sdvo_priv->save_sdvo_mult = +- psb_intel_sdvo_get_clock_rate_mult(psb_intel_output); +- psb_intel_sdvo_get_active_outputs(psb_intel_output, +- &sdvo_priv->save_active_outputs); +- +- if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { +- psb_intel_sdvo_set_target_input(psb_intel_output, +- true, +- false); +- psb_intel_sdvo_get_input_timing(psb_intel_output, +- &sdvo_priv->save_input_dtd_1); +- } +- +- if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) { +- psb_intel_sdvo_set_target_input(psb_intel_output, +- false, +- true); +- psb_intel_sdvo_get_input_timing(psb_intel_output, +- &sdvo_priv->save_input_dtd_2); +- } +- sdvo_priv->save_SDVOX = REG_READ(sdvo_priv->output_device); +- +- /*TODO: save the in_out_map state*/ +-} +- +-static void psb_intel_sdvo_restore(struct drm_connector *connector) +-{ +- struct drm_device *dev = connector->dev; +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; +- /*int o;*/ +- int i; +- bool input1, input2; +- u8 status; +- +- psb_intel_sdvo_set_active_outputs(psb_intel_output, 0); +- +- if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { +- psb_intel_sdvo_set_target_input(psb_intel_output, true, false); +- psb_intel_sdvo_set_input_timing(psb_intel_output, +- &sdvo_priv->save_input_dtd_1); +- } +- +- if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) { +- psb_intel_sdvo_set_target_input(psb_intel_output, false, true); +- psb_intel_sdvo_set_input_timing(psb_intel_output, +- &sdvo_priv->save_input_dtd_2); +- } +- +- psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, +- sdvo_priv->save_sdvo_mult); +- +- REG_WRITE(sdvo_priv->output_device, sdvo_priv->save_SDVOX); +- +- if (sdvo_priv->save_SDVOX & SDVO_ENABLE) { +- for (i = 0; i < 2; i++) +- psb_intel_wait_for_vblank(dev); +- status = +- psb_intel_sdvo_get_trained_inputs(psb_intel_output, +- &input1, +- &input2); +- if (status == SDVO_CMD_STATUS_SUCCESS && !input1) +- DRM_DEBUG +- ("First %s output reported failure to sync\n", +- SDVO_NAME(sdvo_priv)); +- } +- +- psb_intel_sdvo_set_active_outputs(psb_intel_output, +- sdvo_priv->save_active_outputs); +- +- /*TODO: restore in_out_map*/ +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_SET_IN_OUT_MAP, +- sdvo_priv->in_out_map, +- 4); +- +- psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); +-} +- +-static int psb_intel_sdvo_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) +-{ +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; +- +- if (mode->flags & DRM_MODE_FLAG_DBLSCAN) +- return MODE_NO_DBLESCAN; +- +- if (sdvo_priv->pixel_clock_min > mode->clock) +- return MODE_CLOCK_LOW; +- +- if (sdvo_priv->pixel_clock_max < mode->clock) +- return MODE_CLOCK_HIGH; +- +- return MODE_OK; +-} +- +-static bool psb_intel_sdvo_get_capabilities( +- struct psb_intel_output *psb_intel_output, +- struct psb_intel_sdvo_caps *caps) +-{ +- u8 status; +- +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_GET_DEVICE_CAPS, +- NULL, +- 0); +- status = psb_intel_sdvo_read_response(psb_intel_output, +- caps, +- sizeof(*caps)); +- if (status != SDVO_CMD_STATUS_SUCCESS) +- return false; +- +- return true; +-} +- +-struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, int sdvoB) +-{ +- struct drm_connector *connector = NULL; +- struct psb_intel_output *iout = NULL; +- struct psb_intel_sdvo_priv *sdvo; +- +- /* find the sdvo connector */ +- list_for_each_entry(connector, &dev->mode_config.connector_list, +- head) { +- iout = to_psb_intel_output(connector); +- +- if (iout->type != INTEL_OUTPUT_SDVO) +- continue; +- +- sdvo = iout->dev_priv; +- +- if (sdvo->output_device == SDVOB && sdvoB) +- return connector; +- +- if (sdvo->output_device == SDVOC && !sdvoB) +- return connector; +- +- } +- +- return NULL; +-} +- +-int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector) +-{ +- u8 response[2]; +- u8 status; +- struct psb_intel_output *psb_intel_output; +- +- if (!connector) +- return 0; +- +- psb_intel_output = to_psb_intel_output(connector); +- +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_GET_HOT_PLUG_SUPPORT, +- NULL, +- 0); +- status = psb_intel_sdvo_read_response(psb_intel_output, +- &response, +- 2); +- +- if (response[0] != 0) +- return 1; +- +- return 0; +-} +- +-void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, int on) +-{ +- u8 response[2]; +- u8 status; +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_GET_ACTIVE_HOT_PLUG, +- NULL, +- 0); +- psb_intel_sdvo_read_response(psb_intel_output, &response, 2); +- +- if (on) { +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, +- 0); +- status = psb_intel_sdvo_read_response(psb_intel_output, +- &response, +- 2); +- +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_SET_ACTIVE_HOT_PLUG, +- &response, 2); +- } else { +- response[0] = 0; +- response[1] = 0; +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_SET_ACTIVE_HOT_PLUG, +- &response, 2); +- } +- +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_GET_ACTIVE_HOT_PLUG, +- NULL, +- 0); +- psb_intel_sdvo_read_response(psb_intel_output, &response, 2); +-} +- +-static enum drm_connector_status psb_intel_sdvo_detect(struct drm_connector +- *connector, bool force) +-{ +- u8 response[2]; +- u8 status; +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- +- psb_intel_sdvo_write_cmd(psb_intel_output, +- SDVO_CMD_GET_ATTACHED_DISPLAYS, +- NULL, +- 0); +- status = psb_intel_sdvo_read_response(psb_intel_output, &response, 2); +- +- DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]); +- if ((response[0] != 0) || (response[1] != 0)) +- return connector_status_connected; +- else +- return connector_status_disconnected; +-} +- +-static int psb_intel_sdvo_get_modes(struct drm_connector *connector) +-{ +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- +- /* set the bus switch and get the modes */ +- psb_intel_sdvo_set_control_bus_switch(psb_intel_output, +- SDVO_CONTROL_BUS_DDC2); +- psb_intel_ddc_get_modes(psb_intel_output); +- +- if (list_empty(&connector->probed_modes)) +- return 0; +- return 1; +-} +- +-static void psb_intel_sdvo_destroy(struct drm_connector *connector) +-{ +- struct psb_intel_output *psb_intel_output = +- to_psb_intel_output(connector); +- +- if (psb_intel_output->i2c_bus) +- psb_intel_i2c_destroy(psb_intel_output->i2c_bus); +- drm_sysfs_connector_remove(connector); +- drm_connector_cleanup(connector); +- kfree(psb_intel_output); +-} +- +-static const struct drm_encoder_helper_funcs psb_intel_sdvo_helper_funcs = { +- .dpms = psb_intel_sdvo_dpms, +- .mode_fixup = psb_intel_sdvo_mode_fixup, +- .prepare = psb_intel_encoder_prepare, +- .mode_set = psb_intel_sdvo_mode_set, +- .commit = psb_intel_encoder_commit, +-}; +- +-static const struct drm_connector_funcs psb_intel_sdvo_connector_funcs = { +- .dpms = drm_helper_connector_dpms, +- .save = psb_intel_sdvo_save, +- .restore = psb_intel_sdvo_restore, +- .detect = psb_intel_sdvo_detect, +- .fill_modes = drm_helper_probe_single_connector_modes, +- .destroy = psb_intel_sdvo_destroy, +-}; +- +-static const struct drm_connector_helper_funcs +- psb_intel_sdvo_connector_helper_funcs = { +- .get_modes = psb_intel_sdvo_get_modes, +- .mode_valid = psb_intel_sdvo_mode_valid, +- .best_encoder = psb_intel_best_encoder, +-}; +- +-void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder) +-{ +- drm_encoder_cleanup(encoder); +-} +- +-static const struct drm_encoder_funcs psb_intel_sdvo_enc_funcs = { +- .destroy = psb_intel_sdvo_enc_destroy, +-}; +- +- +-void psb_intel_sdvo_init(struct drm_device *dev, int output_device) +-{ +- struct drm_connector *connector; +- struct psb_intel_output *psb_intel_output; +- struct psb_intel_sdvo_priv *sdvo_priv; +- struct psb_intel_i2c_chan *i2cbus = NULL; +- int connector_type; +- u8 ch[0x40]; +- int i; +- int encoder_type, output_id; +- +- psb_intel_output = +- kcalloc(sizeof(struct psb_intel_output) + +- sizeof(struct psb_intel_sdvo_priv), 1, GFP_KERNEL); +- if (!psb_intel_output) +- return; +- +- connector = &psb_intel_output->base; +- +- drm_connector_init(dev, connector, &psb_intel_sdvo_connector_funcs, +- DRM_MODE_CONNECTOR_Unknown); +- drm_connector_helper_add(connector, +- &psb_intel_sdvo_connector_helper_funcs); +- sdvo_priv = (struct psb_intel_sdvo_priv *) (psb_intel_output + 1); +- psb_intel_output->type = INTEL_OUTPUT_SDVO; +- +- connector->interlace_allowed = 0; +- connector->doublescan_allowed = 0; +- +- /* setup the DDC bus. */ +- if (output_device == SDVOB) +- i2cbus = +- psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); +- else +- i2cbus = +- psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); +- +- if (!i2cbus) +- goto err_connector; +- +- sdvo_priv->i2c_bus = i2cbus; +- +- if (output_device == SDVOB) { +- output_id = 1; +- sdvo_priv->by_input_wiring = SDVOB_IN0; +- sdvo_priv->i2c_bus->slave_addr = 0x38; +- } else { +- output_id = 2; +- sdvo_priv->i2c_bus->slave_addr = 0x39; +- } +- +- sdvo_priv->output_device = output_device; +- psb_intel_output->i2c_bus = i2cbus; +- psb_intel_output->dev_priv = sdvo_priv; +- +- +- /* Read the regs to test if we can talk to the device */ +- for (i = 0; i < 0x40; i++) { +- if (!psb_intel_sdvo_read_byte(psb_intel_output, i, &ch[i])) { +- dev_dbg(dev->dev, "No SDVO device found on SDVO%c\n", +- output_device == SDVOB ? 'B' : 'C'); +- goto err_i2c; +- } +- } +- +- psb_intel_sdvo_get_capabilities(psb_intel_output, &sdvo_priv->caps); +- +- memset(&sdvo_priv->active_outputs, 0, +- sizeof(sdvo_priv->active_outputs)); +- +- /* TODO, CVBS, SVID, YPRPB & SCART outputs. */ +- if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) { +- sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0; +- sdvo_priv->active_device = SDVO_DEVICE_CRT; +- connector->display_info.subpixel_order = +- SubPixelHorizontalRGB; +- encoder_type = DRM_MODE_ENCODER_DAC; +- connector_type = DRM_MODE_CONNECTOR_VGA; +- } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) { +- sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1; +- sdvo_priv->active_outputs = SDVO_DEVICE_CRT; +- connector->display_info.subpixel_order = +- SubPixelHorizontalRGB; +- encoder_type = DRM_MODE_ENCODER_DAC; +- connector_type = DRM_MODE_CONNECTOR_VGA; +- } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) { +- sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0; +- sdvo_priv->active_device = SDVO_DEVICE_TMDS; +- connector->display_info.subpixel_order = +- SubPixelHorizontalRGB; +- encoder_type = DRM_MODE_ENCODER_TMDS; +- connector_type = DRM_MODE_CONNECTOR_DVID; +- } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) { +- sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1; +- sdvo_priv->active_device = SDVO_DEVICE_TMDS; +- connector->display_info.subpixel_order = +- SubPixelHorizontalRGB; +- encoder_type = DRM_MODE_ENCODER_TMDS; +- connector_type = DRM_MODE_CONNECTOR_DVID; +- } else { +- unsigned char bytes[2]; +- +- memcpy(bytes, &sdvo_priv->caps.output_flags, 2); +- dev_dbg(dev->dev, "%s: No active RGB or TMDS outputs (0x%02x%02x)\n", +- SDVO_NAME(sdvo_priv), bytes[0], bytes[1]); +- goto err_i2c; +- } +- +- drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_sdvo_enc_funcs, +- encoder_type); +- drm_encoder_helper_add(&psb_intel_output->enc, +- &psb_intel_sdvo_helper_funcs); +- connector->connector_type = connector_type; +- +- drm_mode_connector_attach_encoder(&psb_intel_output->base, +- &psb_intel_output->enc); +- drm_sysfs_connector_add(connector); +- +- /* Set the input timing to the screen. Assume always input 0. */ +- psb_intel_sdvo_set_target_input(psb_intel_output, true, false); +- +- psb_intel_sdvo_get_input_pixel_clock_range(psb_intel_output, +- &sdvo_priv->pixel_clock_min, +- &sdvo_priv-> +- pixel_clock_max); +- +- +- dev_dbg(dev->dev, "%s device VID/DID: %02X:%02X.%02X, " +- "clock range %dMHz - %dMHz, " +- "input 1: %c, input 2: %c, " +- "output 1: %c, output 2: %c\n", +- SDVO_NAME(sdvo_priv), +- sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id, +- sdvo_priv->caps.device_rev_id, +- sdvo_priv->pixel_clock_min / 1000, +- sdvo_priv->pixel_clock_max / 1000, +- (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', +- (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', +- /* check currently supported outputs */ +- sdvo_priv->caps.output_flags & +- (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N', +- sdvo_priv->caps.output_flags & +- (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); +- +- psb_intel_output->ddc_bus = i2cbus; +- +- return; +- +-err_i2c: +- psb_intel_i2c_destroy(psb_intel_output->i2c_bus); +-err_connector: +- drm_connector_cleanup(connector); +- kfree(psb_intel_output); +- +- return; +-} +diff --git a/drivers/staging/gma500/psb_intel_sdvo_regs.h b/drivers/staging/gma500/psb_intel_sdvo_regs.h +deleted file mode 100644 +index 96862ea..0000000 +--- a/drivers/staging/gma500/psb_intel_sdvo_regs.h ++++ /dev/null +@@ -1,338 +0,0 @@ +-/* +- * SDVO command definitions and structures. +- * +- * Copyright (c) 2008, Intel Corporation +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Eric Anholt +- */ +- +-#define SDVO_OUTPUT_FIRST (0) +-#define SDVO_OUTPUT_TMDS0 (1 << 0) +-#define SDVO_OUTPUT_RGB0 (1 << 1) +-#define SDVO_OUTPUT_CVBS0 (1 << 2) +-#define SDVO_OUTPUT_SVID0 (1 << 3) +-#define SDVO_OUTPUT_YPRPB0 (1 << 4) +-#define SDVO_OUTPUT_SCART0 (1 << 5) +-#define SDVO_OUTPUT_LVDS0 (1 << 6) +-#define SDVO_OUTPUT_TMDS1 (1 << 8) +-#define SDVO_OUTPUT_RGB1 (1 << 9) +-#define SDVO_OUTPUT_CVBS1 (1 << 10) +-#define SDVO_OUTPUT_SVID1 (1 << 11) +-#define SDVO_OUTPUT_YPRPB1 (1 << 12) +-#define SDVO_OUTPUT_SCART1 (1 << 13) +-#define SDVO_OUTPUT_LVDS1 (1 << 14) +-#define SDVO_OUTPUT_LAST (14) +- +-struct psb_intel_sdvo_caps { +- u8 vendor_id; +- u8 device_id; +- u8 device_rev_id; +- u8 sdvo_version_major; +- u8 sdvo_version_minor; +- unsigned int sdvo_inputs_mask:2; +- unsigned int smooth_scaling:1; +- unsigned int sharp_scaling:1; +- unsigned int up_scaling:1; +- unsigned int down_scaling:1; +- unsigned int stall_support:1; +- unsigned int pad:1; +- u16 output_flags; +-} __packed; +- +-/** This matches the EDID DTD structure, more or less */ +-struct psb_intel_sdvo_dtd { +- struct { +- u16 clock; /**< pixel clock, in 10kHz units */ +- u8 h_active; /**< lower 8 bits (pixels) */ +- u8 h_blank; /**< lower 8 bits (pixels) */ +- u8 h_high; /**< upper 4 bits each h_active, h_blank */ +- u8 v_active; /**< lower 8 bits (lines) */ +- u8 v_blank; /**< lower 8 bits (lines) */ +- u8 v_high; /**< upper 4 bits each v_active, v_blank */ +- } part1; +- +- struct { +- u8 h_sync_off; +- /**< lower 8 bits, from hblank start */ +- u8 h_sync_width;/**< lower 8 bits (pixels) */ +- /** lower 4 bits each vsync offset, vsync width */ +- u8 v_sync_off_width; +- /** +- * 2 high bits of hsync offset, 2 high bits of hsync width, +- * bits 4-5 of vsync offset, and 2 high bits of vsync width. +- */ +- u8 sync_off_width_high; +- u8 dtd_flags; +- u8 sdvo_flags; +- /** bits 6-7 of vsync offset at bits 6-7 */ +- u8 v_sync_off_high; +- u8 reserved; +- } part2; +-} __packed; +- +-struct psb_intel_sdvo_pixel_clock_range { +- u16 min; /**< pixel clock, in 10kHz units */ +- u16 max; /**< pixel clock, in 10kHz units */ +-} __packed; +- +-struct psb_intel_sdvo_preferred_input_timing_args { +- u16 clock; +- u16 width; +- u16 height; +-} __packed; +- +-/* I2C registers for SDVO */ +-#define SDVO_I2C_ARG_0 0x07 +-#define SDVO_I2C_ARG_1 0x06 +-#define SDVO_I2C_ARG_2 0x05 +-#define SDVO_I2C_ARG_3 0x04 +-#define SDVO_I2C_ARG_4 0x03 +-#define SDVO_I2C_ARG_5 0x02 +-#define SDVO_I2C_ARG_6 0x01 +-#define SDVO_I2C_ARG_7 0x00 +-#define SDVO_I2C_OPCODE 0x08 +-#define SDVO_I2C_CMD_STATUS 0x09 +-#define SDVO_I2C_RETURN_0 0x0a +-#define SDVO_I2C_RETURN_1 0x0b +-#define SDVO_I2C_RETURN_2 0x0c +-#define SDVO_I2C_RETURN_3 0x0d +-#define SDVO_I2C_RETURN_4 0x0e +-#define SDVO_I2C_RETURN_5 0x0f +-#define SDVO_I2C_RETURN_6 0x10 +-#define SDVO_I2C_RETURN_7 0x11 +-#define SDVO_I2C_VENDOR_BEGIN 0x20 +- +-/* Status results */ +-#define SDVO_CMD_STATUS_POWER_ON 0x0 +-#define SDVO_CMD_STATUS_SUCCESS 0x1 +-#define SDVO_CMD_STATUS_NOTSUPP 0x2 +-#define SDVO_CMD_STATUS_INVALID_ARG 0x3 +-#define SDVO_CMD_STATUS_PENDING 0x4 +-#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED 0x5 +-#define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6 +- +-/* SDVO commands, argument/result registers */ +- +-#define SDVO_CMD_RESET 0x01 +- +-/** Returns a struct psb_intel_sdvo_caps */ +-#define SDVO_CMD_GET_DEVICE_CAPS 0x02 +- +-#define SDVO_CMD_GET_FIRMWARE_REV 0x86 +-# define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0 +-# define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1 +-# define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2 +- +-/** +- * Reports which inputs are trained (managed to sync). +- * +- * Devices must have trained within 2 vsyncs of a mode change. +- */ +-#define SDVO_CMD_GET_TRAINED_INPUTS 0x03 +-struct psb_intel_sdvo_get_trained_inputs_response { +- unsigned int input0_trained:1; +- unsigned int input1_trained:1; +- unsigned int pad:6; +-} __packed; +- +-/** Returns a struct psb_intel_sdvo_output_flags of active outputs. */ +-#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04 +- +-/** +- * Sets the current set of active outputs. +- * +- * Takes a struct psb_intel_sdvo_output_flags. +- * Must be preceded by a SET_IN_OUT_MAP +- * on multi-output devices. +- */ +-#define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05 +- +-/** +- * Returns the current mapping of SDVO inputs to outputs on the device. +- * +- * Returns two struct psb_intel_sdvo_output_flags structures. +- */ +-#define SDVO_CMD_GET_IN_OUT_MAP 0x06 +- +-/** +- * Sets the current mapping of SDVO inputs to outputs on the device. +- * +- * Takes two struct i380_sdvo_output_flags structures. +- */ +-#define SDVO_CMD_SET_IN_OUT_MAP 0x07 +- +-/** +- * Returns a struct psb_intel_sdvo_output_flags of attached displays. +- */ +-#define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b +- +-/** +- * Returns a struct psb_intel_sdvo_ouptut_flags of displays supporting hot plugging. +- */ +-#define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c +- +-/** +- * Takes a struct psb_intel_sdvo_output_flags. +- */ +-#define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d +- +-/** +- * Returns a struct psb_intel_sdvo_output_flags of displays with hot plug +- * interrupts enabled. +- */ +-#define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e +- +-#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f +-struct psb_intel_sdvo_get_interrupt_event_source_response { +- u16 interrupt_status; +- unsigned int ambient_light_interrupt:1; +- unsigned int pad:7; +-} __packed; +- +-/** +- * Selects which input is affected by future input commands. +- * +- * Commands affected include SET_INPUT_TIMINGS_PART[12], +- * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12], +- * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS. +- */ +-#define SDVO_CMD_SET_TARGET_INPUT 0x10 +-struct psb_intel_sdvo_set_target_input_args { +- unsigned int target_1:1; +- unsigned int pad:7; +-} __packed; +- +-/** +- * Takes a struct psb_intel_sdvo_output_flags of which outputs are targeted by +- * future output commands. +- * +- * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12], +- * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE. +- */ +-#define SDVO_CMD_SET_TARGET_OUTPUT 0x11 +- +-#define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12 +-#define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13 +-#define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14 +-#define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15 +-#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16 +-#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17 +-#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18 +-#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19 +-/* Part 1 */ +-# define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0 +-# define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1 +-# define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2 +-# define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3 +-# define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4 +-# define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5 +-# define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6 +-# define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7 +-/* Part 2 */ +-# define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0 +-# define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1 +-# define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2 +-# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3 +-# define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4 +-# define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7) +-# define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5) +-# define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3) +-# define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1) +-# define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5 +-# define SDVO_DTD_SDVO_FLAG_STALL (1 << 7) +-# define SDVO_DTD_SDVO_FLAG_CENTERED (0 << 6) +-# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT (1 << 6) +-# define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4) +-# define SDVO_DTD_SDVO_FLAG_SCALING_NONE (0 << 4) +-# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP (1 << 4) +-# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4) +-# define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6 +- +-/** +- * Generates a DTD based on the given width, height, and flags. +- * +- * This will be supported by any device supporting scaling or interlaced +- * modes. +- */ +-#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a +-# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0 +-# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1 +-# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2 +-# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3 +-# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4 +-# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5 +-# define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6 +-# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0) +-# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1) +- +-#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b +-#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c +- +-/** Returns a struct psb_intel_sdvo_pixel_clock_range */ +-#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d +-/** Returns a struct psb_intel_sdvo_pixel_clock_range */ +-#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e +- +-/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */ +-#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f +- +-/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ +-#define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20 +-/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ +-#define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21 +-# define SDVO_CLOCK_RATE_MULT_1X (1 << 0) +-# define SDVO_CLOCK_RATE_MULT_2X (1 << 1) +-# define SDVO_CLOCK_RATE_MULT_4X (1 << 3) +- +-#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 +- +-#define SDVO_CMD_GET_TV_FORMAT 0x28 +- +-#define SDVO_CMD_SET_TV_FORMAT 0x29 +- +-#define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a +-#define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b +-#define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c +-# define SDVO_ENCODER_STATE_ON (1 << 0) +-# define SDVO_ENCODER_STATE_STANDBY (1 << 1) +-# define SDVO_ENCODER_STATE_SUSPEND (1 << 2) +-# define SDVO_ENCODER_STATE_OFF (1 << 3) +- +-#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93 +- +-#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a +-# define SDVO_CONTROL_BUS_PROM 0x0 +-# define SDVO_CONTROL_BUS_DDC1 0x1 +-# define SDVO_CONTROL_BUS_DDC2 0x2 +-# define SDVO_CONTROL_BUS_DDC3 0x3 +- +-/* SDVO Bus & SDVO Inputs wiring details*/ +-/* Bit 0: Is SDVOB connected to In0 (1 = yes, 0 = no*/ +-/* Bit 1: Is SDVOB connected to In1 (1 = yes, 0 = no*/ +-/* Bit 2: Is SDVOC connected to In0 (1 = yes, 0 = no*/ +-/* Bit 3: Is SDVOC connected to In1 (1 = yes, 0 = no*/ +-#define SDVOB_IN0 0x01 +-#define SDVOB_IN1 0x02 +-#define SDVOC_IN0 0x04 +-#define SDVOC_IN1 0x08 +- +-#define SDVO_DEVICE_NONE 0x00 +-#define SDVO_DEVICE_CRT 0x01 +-#define SDVO_DEVICE_TV 0x02 +-#define SDVO_DEVICE_LVDS 0x04 +-#define SDVO_DEVICE_TMDS 0x08 +- +diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c +deleted file mode 100644 +index 36dd630..0000000 +--- a/drivers/staging/gma500/psb_irq.c ++++ /dev/null +@@ -1,627 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2007, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to +- * develop this driver. +- * +- **************************************************************************/ +-/* +- */ +- +-#include +-#include "psb_drv.h" +-#include "psb_reg.h" +-#include "psb_intel_reg.h" +-#include "power.h" +-#include "mdfld_output.h" +- +-/* +- * inline functions +- */ +- +-static inline u32 +-psb_pipestat(int pipe) +-{ +- if (pipe == 0) +- return PIPEASTAT; +- if (pipe == 1) +- return PIPEBSTAT; +- if (pipe == 2) +- return PIPECSTAT; +- BUG(); +-} +- +-static inline u32 +-mid_pipe_event(int pipe) +-{ +- if (pipe == 0) +- return _PSB_PIPEA_EVENT_FLAG; +- if (pipe == 1) +- return _MDFLD_PIPEB_EVENT_FLAG; +- if (pipe == 2) +- return _MDFLD_PIPEC_EVENT_FLAG; +- BUG(); +-} +- +-static inline u32 +-mid_pipe_vsync(int pipe) +-{ +- if (pipe == 0) +- return _PSB_VSYNC_PIPEA_FLAG; +- if (pipe == 1) +- return _PSB_VSYNC_PIPEB_FLAG; +- if (pipe == 2) +- return _MDFLD_PIPEC_VBLANK_FLAG; +- BUG(); +-} +- +-static inline u32 +-mid_pipeconf(int pipe) +-{ +- if (pipe == 0) +- return PIPEACONF; +- if (pipe == 1) +- return PIPEBCONF; +- if (pipe == 2) +- return PIPECCONF; +- BUG(); +-} +- +-void +-psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) +-{ +- if ((dev_priv->pipestat[pipe] & mask) != mask) { +- u32 reg = psb_pipestat(pipe); +- dev_priv->pipestat[pipe] |= mask; +- /* Enable the interrupt, clear any pending status */ +- if (gma_power_begin(dev_priv->dev, false)) { +- u32 writeVal = PSB_RVDC32(reg); +- writeVal |= (mask | (mask >> 16)); +- PSB_WVDC32(writeVal, reg); +- (void) PSB_RVDC32(reg); +- gma_power_end(dev_priv->dev); +- } +- } +-} +- +-void +-psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) +-{ +- if ((dev_priv->pipestat[pipe] & mask) != 0) { +- u32 reg = psb_pipestat(pipe); +- dev_priv->pipestat[pipe] &= ~mask; +- if (gma_power_begin(dev_priv->dev, false)) { +- u32 writeVal = PSB_RVDC32(reg); +- writeVal &= ~mask; +- PSB_WVDC32(writeVal, reg); +- (void) PSB_RVDC32(reg); +- gma_power_end(dev_priv->dev); +- } +- } +-} +- +-void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe) +-{ +- if (gma_power_begin(dev_priv->dev, false)) { +- u32 pipe_event = mid_pipe_event(pipe); +- dev_priv->vdc_irq_mask |= pipe_event; +- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); +- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); +- gma_power_end(dev_priv->dev); +- } +-} +- +-void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe) +-{ +- if (dev_priv->pipestat[pipe] == 0) { +- if (gma_power_begin(dev_priv->dev, false)) { +- u32 pipe_event = mid_pipe_event(pipe); +- dev_priv->vdc_irq_mask &= ~pipe_event; +- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); +- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); +- gma_power_end(dev_priv->dev); +- } +- } +-} +- +-/** +- * Display controller interrupt handler for pipe event. +- * +- */ +-static void mid_pipe_event_handler(struct drm_device *dev, int pipe) +-{ +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *) dev->dev_private; +- +- uint32_t pipe_stat_val = 0; +- uint32_t pipe_stat_reg = psb_pipestat(pipe); +- uint32_t pipe_enable = dev_priv->pipestat[pipe]; +- uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16; +- uint32_t pipe_clear; +- uint32_t i = 0; +- +- spin_lock(&dev_priv->irqmask_lock); +- +- pipe_stat_val = PSB_RVDC32(pipe_stat_reg); +- pipe_stat_val &= pipe_enable | pipe_status; +- pipe_stat_val &= pipe_stat_val >> 16; +- +- spin_unlock(&dev_priv->irqmask_lock); +- +- /* Clear the 2nd level interrupt status bits +- * Sometimes the bits are very sticky so we repeat until they unstick */ +- for (i = 0; i < 0xffff; i++) { +- PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg); +- pipe_clear = PSB_RVDC32(pipe_stat_reg) & pipe_status; +- +- if (pipe_clear == 0) +- break; +- } +- +- if (pipe_clear) +- dev_err(dev->dev, +- "%s, can't clear status bits for pipe %d, its value = 0x%x.\n", +- __func__, pipe, PSB_RVDC32(pipe_stat_reg)); +- +- if (pipe_stat_val & PIPE_VBLANK_STATUS) +- drm_handle_vblank(dev, pipe); +- +- if (pipe_stat_val & PIPE_TE_STATUS) +- drm_handle_vblank(dev, pipe); +-} +- +-/* +- * Display controller interrupt handler. +- */ +-static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) +-{ +- if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG) +- mid_pipe_event_handler(dev, 0); +- +- if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG) +- mid_pipe_event_handler(dev, 1); +-} +- +-irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) +-{ +- struct drm_device *dev = (struct drm_device *) arg; +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *) dev->dev_private; +- +- uint32_t vdc_stat, dsp_int = 0, sgx_int = 0; +- int handled = 0; +- +- spin_lock(&dev_priv->irqmask_lock); +- +- vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R); +- +- if (vdc_stat & _PSB_PIPE_EVENT_FLAG) +- dsp_int = 1; +- +- /* FIXME: Handle Medfield +- if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG) +- dsp_int = 1; +- */ +- +- if (vdc_stat & _PSB_IRQ_SGX_FLAG) +- sgx_int = 1; +- +- vdc_stat &= dev_priv->vdc_irq_mask; +- spin_unlock(&dev_priv->irqmask_lock); +- +- if (dsp_int && gma_power_is_on(dev)) { +- psb_vdc_interrupt(dev, vdc_stat); +- handled = 1; +- } +- +- if (sgx_int) { +- /* Not expected - we have it masked, shut it up */ +- u32 s, s2; +- s = PSB_RSGX32(PSB_CR_EVENT_STATUS); +- s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2); +- PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR); +- PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2); +- /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but +- we may as well poll even if we add that ! */ +- handled = 1; +- } +- +- PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R); +- (void) PSB_RVDC32(PSB_INT_IDENTITY_R); +- DRM_READMEMORYBARRIER(); +- +- if (!handled) +- return IRQ_NONE; +- +- return IRQ_HANDLED; +-} +- +-void psb_irq_preinstall(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *) dev->dev_private; +- unsigned long irqflags; +- +- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); +- +- if (gma_power_is_on(dev)) +- PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); +- if (dev->vblank_enabled[0]) +- dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; +- if (dev->vblank_enabled[1]) +- dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; +- +- /* FIXME: Handle Medfield irq mask +- if (dev->vblank_enabled[1]) +- dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG; +- if (dev->vblank_enabled[2]) +- dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; +- */ +- +- /* This register is safe even if display island is off */ +- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); +- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); +-} +- +-int psb_irq_postinstall(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *) dev->dev_private; +- unsigned long irqflags; +- +- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); +- +- /* This register is safe even if display island is off */ +- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); +- PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); +- +- if (dev->vblank_enabled[0]) +- psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); +- else +- psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); +- +- if (dev->vblank_enabled[1]) +- psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); +- else +- psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); +- +- if (dev->vblank_enabled[2]) +- psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); +- else +- psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); +- +- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); +- return 0; +-} +- +-void psb_irq_uninstall(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *) dev->dev_private; +- unsigned long irqflags; +- +- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); +- +- PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); +- +- if (dev->vblank_enabled[0]) +- psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); +- +- if (dev->vblank_enabled[1]) +- psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); +- +- if (dev->vblank_enabled[2]) +- psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); +- +- dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | +- _PSB_IRQ_MSVDX_FLAG | +- _LNC_IRQ_TOPAZ_FLAG; +- +- /* These two registers are safe even if display island is off */ +- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); +- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); +- +- wmb(); +- +- /* This register is safe even if display island is off */ +- PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R); +- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); +-} +- +-void psb_irq_turn_on_dpst(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *) dev->dev_private; +- u32 hist_reg; +- u32 pwm_reg; +- +- if (gma_power_begin(dev, false)) { +- PSB_WVDC32(1 << 31, HISTOGRAM_LOGIC_CONTROL); +- hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); +- PSB_WVDC32(1 << 31, HISTOGRAM_INT_CONTROL); +- hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); +- +- PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC); +- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); +- PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE +- | PWM_PHASEIN_INT_ENABLE, +- PWM_CONTROL_LOGIC); +- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); +- +- psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); +- +- hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); +- PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR, +- HISTOGRAM_INT_CONTROL); +- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); +- PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE, +- PWM_CONTROL_LOGIC); +- +- gma_power_end(dev); +- } +-} +- +-int psb_irq_enable_dpst(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *) dev->dev_private; +- unsigned long irqflags; +- +- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); +- +- /* enable DPST */ +- mid_enable_pipe_event(dev_priv, 0); +- psb_irq_turn_on_dpst(dev); +- +- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); +- return 0; +-} +- +-void psb_irq_turn_off_dpst(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *) dev->dev_private; +- u32 hist_reg; +- u32 pwm_reg; +- +- if (gma_power_begin(dev, false)) { +- PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL); +- hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); +- +- psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); +- +- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); +- PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE), +- PWM_CONTROL_LOGIC); +- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); +- +- gma_power_end(dev); +- } +-} +- +-int psb_irq_disable_dpst(struct drm_device *dev) +-{ +- struct drm_psb_private *dev_priv = +- (struct drm_psb_private *) dev->dev_private; +- unsigned long irqflags; +- +- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); +- +- mid_disable_pipe_event(dev_priv, 0); +- psb_irq_turn_off_dpst(dev); +- +- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); +- +- return 0; +-} +- +-#ifdef PSB_FIXME +-static int psb_vblank_do_wait(struct drm_device *dev, +- unsigned int *sequence, atomic_t *counter) +-{ +- unsigned int cur_vblank; +- int ret = 0; +- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, +- (((cur_vblank = atomic_read(counter)) +- - *sequence) <= (1 << 23))); +- *sequence = cur_vblank; +- +- return ret; +-} +-#endif +- +-/* +- * It is used to enable VBLANK interrupt +- */ +-int psb_enable_vblank(struct drm_device *dev, int pipe) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- unsigned long irqflags; +- uint32_t reg_val = 0; +- uint32_t pipeconf_reg = mid_pipeconf(pipe); +- +-#if defined(CONFIG_DRM_PSB_MFLD) +- /* Medfield is different - we should perhaps extract out vblank +- and blacklight etc ops */ +- if (IS_MFLD(dev) && !mdfld_panel_dpi(dev)) +- return mdfld_enable_te(dev, pipe); +-#endif +- if (gma_power_begin(dev, false)) { +- reg_val = REG_READ(pipeconf_reg); +- gma_power_end(dev); +- } +- +- if (!(reg_val & PIPEACONF_ENABLE)) +- return -EINVAL; +- +- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); +- +- if (pipe == 0) +- dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; +- else if (pipe == 1) +- dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; +- +- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); +- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); +- psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); +- +- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); +- +- return 0; +-} +- +-/* +- * It is used to disable VBLANK interrupt +- */ +-void psb_disable_vblank(struct drm_device *dev, int pipe) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- unsigned long irqflags; +- +-#if defined(CONFIG_DRM_PSB_MFLD) +- if (IS_MFLD(dev) && !mdfld_panel_dpi(dev)) +- mdfld_disable_te(dev, pipe); +-#endif +- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); +- +- if (pipe == 0) +- dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEA_FLAG; +- else if (pipe == 1) +- dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEB_FLAG; +- +- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); +- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); +- psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); +- +- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); +-} +- +-/** +- * mdfld_enable_te - enable TE events +- * @dev: our DRM device +- * @pipe: which pipe to work on +- * +- * Enable TE events on a Medfield display pipe. Medfield specific. +- */ +-int mdfld_enable_te(struct drm_device *dev, int pipe) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- unsigned long flags; +- uint32_t reg_val = 0; +- uint32_t pipeconf_reg = mid_pipeconf(pipe); +- +- if (gma_power_begin(dev, false)) { +- reg_val = REG_READ(pipeconf_reg); +- gma_power_end(dev); +- } +- +- if (!(reg_val & PIPEACONF_ENABLE)) +- return -EINVAL; +- +- spin_lock_irqsave(&dev_priv->irqmask_lock, flags); +- +- mid_enable_pipe_event(dev_priv, pipe); +- psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE); +- +- spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags); +- +- return 0; +-} +- +-/** +- * mdfld_disable_te - disable TE events +- * @dev: our DRM device +- * @pipe: which pipe to work on +- * +- * Disable TE events on a Medfield display pipe. Medfield specific. +- */ +-void mdfld_disable_te(struct drm_device *dev, int pipe) +-{ +- struct drm_psb_private *dev_priv = dev->dev_private; +- unsigned long flags; +- +- spin_lock_irqsave(&dev_priv->irqmask_lock, flags); +- +- mid_disable_pipe_event(dev_priv, pipe); +- psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE); +- +- spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags); +-} +- +-/* Called from drm generic code, passed a 'crtc', which +- * we use as a pipe index +- */ +-u32 psb_get_vblank_counter(struct drm_device *dev, int pipe) +-{ +- uint32_t high_frame = PIPEAFRAMEHIGH; +- uint32_t low_frame = PIPEAFRAMEPIXEL; +- uint32_t pipeconf_reg = PIPEACONF; +- uint32_t reg_val = 0; +- uint32_t high1 = 0, high2 = 0, low = 0, count = 0; +- +- switch (pipe) { +- case 0: +- break; +- case 1: +- high_frame = PIPEBFRAMEHIGH; +- low_frame = PIPEBFRAMEPIXEL; +- pipeconf_reg = PIPEBCONF; +- break; +- case 2: +- high_frame = PIPECFRAMEHIGH; +- low_frame = PIPECFRAMEPIXEL; +- pipeconf_reg = PIPECCONF; +- break; +- default: +- dev_err(dev->dev, "%s, invalid pipe.\n", __func__); +- return 0; +- } +- +- if (!gma_power_begin(dev, false)) +- return 0; +- +- reg_val = REG_READ(pipeconf_reg); +- +- if (!(reg_val & PIPEACONF_ENABLE)) { +- dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n", +- pipe); +- goto psb_get_vblank_counter_exit; +- } +- +- /* +- * High & low register fields aren't synchronized, so make sure +- * we get a low value that's stable across two reads of the high +- * register. +- */ +- do { +- high1 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> +- PIPE_FRAME_HIGH_SHIFT); +- low = ((REG_READ(low_frame) & PIPE_FRAME_LOW_MASK) >> +- PIPE_FRAME_LOW_SHIFT); +- high2 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> +- PIPE_FRAME_HIGH_SHIFT); +- } while (high1 != high2); +- +- count = (high1 << 8) | low; +- +-psb_get_vblank_counter_exit: +- +- gma_power_end(dev); +- +- return count; +-} +- +diff --git a/drivers/staging/gma500/psb_irq.h b/drivers/staging/gma500/psb_irq.h +deleted file mode 100644 +index 216fda3..0000000 +--- a/drivers/staging/gma500/psb_irq.h ++++ /dev/null +@@ -1,45 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2009-2011, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: +- * Benjamin Defnet +- * Rajesh Poornachandran +- * +- **************************************************************************/ +- +-#ifndef _SYSIRQ_H_ +-#define _SYSIRQ_H_ +- +-#include +- +-bool sysirq_init(struct drm_device *dev); +-void sysirq_uninit(struct drm_device *dev); +- +-void psb_irq_preinstall(struct drm_device *dev); +-int psb_irq_postinstall(struct drm_device *dev); +-void psb_irq_uninstall(struct drm_device *dev); +-irqreturn_t psb_irq_handler(DRM_IRQ_ARGS); +- +-int psb_irq_enable_dpst(struct drm_device *dev); +-int psb_irq_disable_dpst(struct drm_device *dev); +-void psb_irq_turn_on_dpst(struct drm_device *dev); +-void psb_irq_turn_off_dpst(struct drm_device *dev); +-int psb_enable_vblank(struct drm_device *dev, int pipe); +-void psb_disable_vblank(struct drm_device *dev, int pipe); +-u32 psb_get_vblank_counter(struct drm_device *dev, int pipe); +- +-#endif /* _SYSIRQ_H_ */ +diff --git a/drivers/staging/gma500/psb_lid.c b/drivers/staging/gma500/psb_lid.c +deleted file mode 100644 +index b867aab..0000000 +--- a/drivers/staging/gma500/psb_lid.c ++++ /dev/null +@@ -1,88 +0,0 @@ +-/************************************************************************** +- * Copyright (c) 2007, Intel Corporation. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Authors: Thomas Hellstrom +- **************************************************************************/ +- +-#include +-#include "psb_drv.h" +-#include "psb_reg.h" +-#include "psb_intel_reg.h" +-#include +- +-static void psb_lid_timer_func(unsigned long data) +-{ +- struct drm_psb_private * dev_priv = (struct drm_psb_private *)data; +- struct drm_device *dev = (struct drm_device *)dev_priv->dev; +- struct timer_list *lid_timer = &dev_priv->lid_timer; +- unsigned long irq_flags; +- u32 *lid_state = dev_priv->lid_state; +- u32 pp_status; +- +- if (readl(lid_state) == dev_priv->lid_last_state) +- goto lid_timer_schedule; +- +- if ((readl(lid_state)) & 0x01) { +- /*lid state is open*/ +- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON); +- do { +- pp_status = REG_READ(PP_STATUS); +- } while ((pp_status & PP_ON) == 0); +- +- /*FIXME: should be backlight level before*/ +- psb_intel_lvds_set_brightness(dev, 100); +- } else { +- psb_intel_lvds_set_brightness(dev, 0); +- +- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON); +- do { +- pp_status = REG_READ(PP_STATUS); +- } while ((pp_status & PP_ON) == 0); +- } +- dev_priv->lid_last_state = readl(lid_state); +- +-lid_timer_schedule: +- spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); +- if (!timer_pending(lid_timer)) { +- lid_timer->expires = jiffies + PSB_LID_DELAY; +- add_timer(lid_timer); +- } +- spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); +-} +- +-void psb_lid_timer_init(struct drm_psb_private *dev_priv) +-{ +- struct timer_list *lid_timer = &dev_priv->lid_timer; +- unsigned long irq_flags; +- +- spin_lock_init(&dev_priv->lid_lock); +- spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); +- +- init_timer(lid_timer); +- +- lid_timer->data = (unsigned long)dev_priv; +- lid_timer->function = psb_lid_timer_func; +- lid_timer->expires = jiffies + PSB_LID_DELAY; +- +- add_timer(lid_timer); +- spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); +-} +- +-void psb_lid_timer_takedown(struct drm_psb_private *dev_priv) +-{ +- del_timer_sync(&dev_priv->lid_timer); +-} +- +diff --git a/drivers/staging/gma500/psb_reg.h b/drivers/staging/gma500/psb_reg.h +deleted file mode 100644 +index b81c7c1..0000000 +--- a/drivers/staging/gma500/psb_reg.h ++++ /dev/null +@@ -1,582 +0,0 @@ +-/************************************************************************** +- * +- * Copyright (c) (2005-2007) Imagination Technologies Limited. +- * Copyright (c) 2007, Intel Corporation. +- * All Rights Reserved. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.. +- * +- **************************************************************************/ +- +-#ifndef _PSB_REG_H_ +-#define _PSB_REG_H_ +- +-#define PSB_CR_CLKGATECTL 0x0000 +-#define _PSB_C_CLKGATECTL_AUTO_MAN_REG (1 << 24) +-#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT (20) +-#define _PSB_C_CLKGATECTL_USE_CLKG_MASK (0x3 << 20) +-#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT (16) +-#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK (0x3 << 16) +-#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT (12) +-#define _PSB_C_CLKGATECTL_TA_CLKG_MASK (0x3 << 12) +-#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT (8) +-#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK (0x3 << 8) +-#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT (4) +-#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK (0x3 << 4) +-#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT (0) +-#define _PSB_C_CLKGATECTL_2D_CLKG_MASK (0x3 << 0) +-#define _PSB_C_CLKGATECTL_CLKG_ENABLED (0) +-#define _PSB_C_CLKGATECTL_CLKG_DISABLED (1) +-#define _PSB_C_CLKGATECTL_CLKG_AUTO (2) +- +-#define PSB_CR_CORE_ID 0x0010 +-#define _PSB_CC_ID_ID_SHIFT (16) +-#define _PSB_CC_ID_ID_MASK (0xFFFF << 16) +-#define _PSB_CC_ID_CONFIG_SHIFT (0) +-#define _PSB_CC_ID_CONFIG_MASK (0xFFFF << 0) +- +-#define PSB_CR_CORE_REVISION 0x0014 +-#define _PSB_CC_REVISION_DESIGNER_SHIFT (24) +-#define _PSB_CC_REVISION_DESIGNER_MASK (0xFF << 24) +-#define _PSB_CC_REVISION_MAJOR_SHIFT (16) +-#define _PSB_CC_REVISION_MAJOR_MASK (0xFF << 16) +-#define _PSB_CC_REVISION_MINOR_SHIFT (8) +-#define _PSB_CC_REVISION_MINOR_MASK (0xFF << 8) +-#define _PSB_CC_REVISION_MAINTENANCE_SHIFT (0) +-#define _PSB_CC_REVISION_MAINTENANCE_MASK (0xFF << 0) +- +-#define PSB_CR_DESIGNER_REV_FIELD1 0x0018 +- +-#define PSB_CR_SOFT_RESET 0x0080 +-#define _PSB_CS_RESET_TSP_RESET (1 << 6) +-#define _PSB_CS_RESET_ISP_RESET (1 << 5) +-#define _PSB_CS_RESET_USE_RESET (1 << 4) +-#define _PSB_CS_RESET_TA_RESET (1 << 3) +-#define _PSB_CS_RESET_DPM_RESET (1 << 2) +-#define _PSB_CS_RESET_TWOD_RESET (1 << 1) +-#define _PSB_CS_RESET_BIF_RESET (1 << 0) +- +-#define PSB_CR_DESIGNER_REV_FIELD2 0x001C +- +-#define PSB_CR_EVENT_HOST_ENABLE2 0x0110 +- +-#define PSB_CR_EVENT_STATUS2 0x0118 +- +-#define PSB_CR_EVENT_HOST_CLEAR2 0x0114 +-#define _PSB_CE2_BIF_REQUESTER_FAULT (1 << 4) +- +-#define PSB_CR_EVENT_STATUS 0x012C +- +-#define PSB_CR_EVENT_HOST_ENABLE 0x0130 +- +-#define PSB_CR_EVENT_HOST_CLEAR 0x0134 +-#define _PSB_CE_MASTER_INTERRUPT (1 << 31) +-#define _PSB_CE_TA_DPM_FAULT (1 << 28) +-#define _PSB_CE_TWOD_COMPLETE (1 << 27) +-#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS (1 << 25) +-#define _PSB_CE_DPM_TA_MEM_FREE (1 << 24) +-#define _PSB_CE_PIXELBE_END_RENDER (1 << 18) +-#define _PSB_CE_SW_EVENT (1 << 14) +-#define _PSB_CE_TA_FINISHED (1 << 13) +-#define _PSB_CE_TA_TERMINATE (1 << 12) +-#define _PSB_CE_DPM_REACHED_MEM_THRESH (1 << 3) +-#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL (1 << 2) +-#define _PSB_CE_DPM_OUT_OF_MEMORY_MT (1 << 1) +-#define _PSB_CE_DPM_3D_MEM_FREE (1 << 0) +- +- +-#define PSB_USE_OFFSET_MASK 0x0007FFFF +-#define PSB_USE_OFFSET_SIZE (PSB_USE_OFFSET_MASK + 1) +-#define PSB_CR_USE_CODE_BASE0 0x0A0C +-#define PSB_CR_USE_CODE_BASE1 0x0A10 +-#define PSB_CR_USE_CODE_BASE2 0x0A14 +-#define PSB_CR_USE_CODE_BASE3 0x0A18 +-#define PSB_CR_USE_CODE_BASE4 0x0A1C +-#define PSB_CR_USE_CODE_BASE5 0x0A20 +-#define PSB_CR_USE_CODE_BASE6 0x0A24 +-#define PSB_CR_USE_CODE_BASE7 0x0A28 +-#define PSB_CR_USE_CODE_BASE8 0x0A2C +-#define PSB_CR_USE_CODE_BASE9 0x0A30 +-#define PSB_CR_USE_CODE_BASE10 0x0A34 +-#define PSB_CR_USE_CODE_BASE11 0x0A38 +-#define PSB_CR_USE_CODE_BASE12 0x0A3C +-#define PSB_CR_USE_CODE_BASE13 0x0A40 +-#define PSB_CR_USE_CODE_BASE14 0x0A44 +-#define PSB_CR_USE_CODE_BASE15 0x0A48 +-#define PSB_CR_USE_CODE_BASE(_i) (0x0A0C + ((_i) << 2)) +-#define _PSB_CUC_BASE_DM_SHIFT (25) +-#define _PSB_CUC_BASE_DM_MASK (0x3 << 25) +-#define _PSB_CUC_BASE_ADDR_SHIFT (0) /* 1024-bit aligned address? */ +-#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT (7) +-#define _PSB_CUC_BASE_ADDR_MASK (0x1FFFFFF << 0) +-#define _PSB_CUC_DM_VERTEX (0) +-#define _PSB_CUC_DM_PIXEL (1) +-#define _PSB_CUC_DM_RESERVED (2) +-#define _PSB_CUC_DM_EDM (3) +- +-#define PSB_CR_PDS_EXEC_BASE 0x0AB8 +-#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT (20) /* 1MB aligned address */ +-#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT (20) +- +-#define PSB_CR_EVENT_KICKER 0x0AC4 +-#define _PSB_CE_KICKER_ADDRESS_SHIFT (4) /* 128-bit aligned address */ +- +-#define PSB_CR_EVENT_KICK 0x0AC8 +-#define _PSB_CE_KICK_NOW (1 << 0) +- +-#define PSB_CR_BIF_DIR_LIST_BASE1 0x0C38 +- +-#define PSB_CR_BIF_CTRL 0x0C00 +-#define _PSB_CB_CTRL_CLEAR_FAULT (1 << 4) +-#define _PSB_CB_CTRL_INVALDC (1 << 3) +-#define _PSB_CB_CTRL_FLUSH (1 << 2) +- +-#define PSB_CR_BIF_INT_STAT 0x0C04 +- +-#define PSB_CR_BIF_FAULT 0x0C08 +-#define _PSB_CBI_STAT_PF_N_RW (1 << 14) +-#define _PSB_CBI_STAT_FAULT_SHIFT (0) +-#define _PSB_CBI_STAT_FAULT_MASK (0x3FFF << 0) +-#define _PSB_CBI_STAT_FAULT_CACHE (1 << 1) +-#define _PSB_CBI_STAT_FAULT_TA (1 << 2) +-#define _PSB_CBI_STAT_FAULT_VDM (1 << 3) +-#define _PSB_CBI_STAT_FAULT_2D (1 << 4) +-#define _PSB_CBI_STAT_FAULT_PBE (1 << 5) +-#define _PSB_CBI_STAT_FAULT_TSP (1 << 6) +-#define _PSB_CBI_STAT_FAULT_ISP (1 << 7) +-#define _PSB_CBI_STAT_FAULT_USSEPDS (1 << 8) +-#define _PSB_CBI_STAT_FAULT_HOST (1 << 9) +- +-#define PSB_CR_BIF_BANK0 0x0C78 +-#define PSB_CR_BIF_BANK1 0x0C7C +-#define PSB_CR_BIF_DIR_LIST_BASE0 0x0C84 +-#define PSB_CR_BIF_TWOD_REQ_BASE 0x0C88 +-#define PSB_CR_BIF_3D_REQ_BASE 0x0CAC +- +-#define PSB_CR_2D_SOCIF 0x0E18 +-#define _PSB_C2_SOCIF_FREESPACE_SHIFT (0) +-#define _PSB_C2_SOCIF_FREESPACE_MASK (0xFF << 0) +-#define _PSB_C2_SOCIF_EMPTY (0x80 << 0) +- +-#define PSB_CR_2D_BLIT_STATUS 0x0E04 +-#define _PSB_C2B_STATUS_BUSY (1 << 24) +-#define _PSB_C2B_STATUS_COMPLETE_SHIFT (0) +-#define _PSB_C2B_STATUS_COMPLETE_MASK (0xFFFFFF << 0) +- +-/* +- * 2D defs. +- */ +- +-/* +- * 2D Slave Port Data : Block Header's Object Type +- */ +- +-#define PSB_2D_CLIP_BH (0x00000000) +-#define PSB_2D_PAT_BH (0x10000000) +-#define PSB_2D_CTRL_BH (0x20000000) +-#define PSB_2D_SRC_OFF_BH (0x30000000) +-#define PSB_2D_MASK_OFF_BH (0x40000000) +-#define PSB_2D_RESERVED1_BH (0x50000000) +-#define PSB_2D_RESERVED2_BH (0x60000000) +-#define PSB_2D_FENCE_BH (0x70000000) +-#define PSB_2D_BLIT_BH (0x80000000) +-#define PSB_2D_SRC_SURF_BH (0x90000000) +-#define PSB_2D_DST_SURF_BH (0xA0000000) +-#define PSB_2D_PAT_SURF_BH (0xB0000000) +-#define PSB_2D_SRC_PAL_BH (0xC0000000) +-#define PSB_2D_PAT_PAL_BH (0xD0000000) +-#define PSB_2D_MASK_SURF_BH (0xE0000000) +-#define PSB_2D_FLUSH_BH (0xF0000000) +- +-/* +- * Clip Definition block (PSB_2D_CLIP_BH) +- */ +-#define PSB_2D_CLIPCOUNT_MAX (1) +-#define PSB_2D_CLIPCOUNT_MASK (0x00000000) +-#define PSB_2D_CLIPCOUNT_CLRMASK (0xFFFFFFFF) +-#define PSB_2D_CLIPCOUNT_SHIFT (0) +-/* clip rectangle min & max */ +-#define PSB_2D_CLIP_XMAX_MASK (0x00FFF000) +-#define PSB_2D_CLIP_XMAX_CLRMASK (0xFF000FFF) +-#define PSB_2D_CLIP_XMAX_SHIFT (12) +-#define PSB_2D_CLIP_XMIN_MASK (0x00000FFF) +-#define PSB_2D_CLIP_XMIN_CLRMASK (0x00FFF000) +-#define PSB_2D_CLIP_XMIN_SHIFT (0) +-/* clip rectangle offset */ +-#define PSB_2D_CLIP_YMAX_MASK (0x00FFF000) +-#define PSB_2D_CLIP_YMAX_CLRMASK (0xFF000FFF) +-#define PSB_2D_CLIP_YMAX_SHIFT (12) +-#define PSB_2D_CLIP_YMIN_MASK (0x00000FFF) +-#define PSB_2D_CLIP_YMIN_CLRMASK (0x00FFF000) +-#define PSB_2D_CLIP_YMIN_SHIFT (0) +- +-/* +- * Pattern Control (PSB_2D_PAT_BH) +- */ +-#define PSB_2D_PAT_HEIGHT_MASK (0x0000001F) +-#define PSB_2D_PAT_HEIGHT_SHIFT (0) +-#define PSB_2D_PAT_WIDTH_MASK (0x000003E0) +-#define PSB_2D_PAT_WIDTH_SHIFT (5) +-#define PSB_2D_PAT_YSTART_MASK (0x00007C00) +-#define PSB_2D_PAT_YSTART_SHIFT (10) +-#define PSB_2D_PAT_XSTART_MASK (0x000F8000) +-#define PSB_2D_PAT_XSTART_SHIFT (15) +- +-/* +- * 2D Control block (PSB_2D_CTRL_BH) +- */ +-/* Present Flags */ +-#define PSB_2D_SRCCK_CTRL (0x00000001) +-#define PSB_2D_DSTCK_CTRL (0x00000002) +-#define PSB_2D_ALPHA_CTRL (0x00000004) +-/* Colour Key Colour (SRC/DST)*/ +-#define PSB_2D_CK_COL_MASK (0xFFFFFFFF) +-#define PSB_2D_CK_COL_CLRMASK (0x00000000) +-#define PSB_2D_CK_COL_SHIFT (0) +-/* Colour Key Mask (SRC/DST)*/ +-#define PSB_2D_CK_MASK_MASK (0xFFFFFFFF) +-#define PSB_2D_CK_MASK_CLRMASK (0x00000000) +-#define PSB_2D_CK_MASK_SHIFT (0) +-/* Alpha Control (Alpha/RGB)*/ +-#define PSB_2D_GBLALPHA_MASK (0x000FF000) +-#define PSB_2D_GBLALPHA_CLRMASK (0xFFF00FFF) +-#define PSB_2D_GBLALPHA_SHIFT (12) +-#define PSB_2D_SRCALPHA_OP_MASK (0x00700000) +-#define PSB_2D_SRCALPHA_OP_CLRMASK (0xFF8FFFFF) +-#define PSB_2D_SRCALPHA_OP_SHIFT (20) +-#define PSB_2D_SRCALPHA_OP_ONE (0x00000000) +-#define PSB_2D_SRCALPHA_OP_SRC (0x00100000) +-#define PSB_2D_SRCALPHA_OP_DST (0x00200000) +-#define PSB_2D_SRCALPHA_OP_SG (0x00300000) +-#define PSB_2D_SRCALPHA_OP_DG (0x00400000) +-#define PSB_2D_SRCALPHA_OP_GBL (0x00500000) +-#define PSB_2D_SRCALPHA_OP_ZERO (0x00600000) +-#define PSB_2D_SRCALPHA_INVERT (0x00800000) +-#define PSB_2D_SRCALPHA_INVERT_CLR (0xFF7FFFFF) +-#define PSB_2D_DSTALPHA_OP_MASK (0x07000000) +-#define PSB_2D_DSTALPHA_OP_CLRMASK (0xF8FFFFFF) +-#define PSB_2D_DSTALPHA_OP_SHIFT (24) +-#define PSB_2D_DSTALPHA_OP_ONE (0x00000000) +-#define PSB_2D_DSTALPHA_OP_SRC (0x01000000) +-#define PSB_2D_DSTALPHA_OP_DST (0x02000000) +-#define PSB_2D_DSTALPHA_OP_SG (0x03000000) +-#define PSB_2D_DSTALPHA_OP_DG (0x04000000) +-#define PSB_2D_DSTALPHA_OP_GBL (0x05000000) +-#define PSB_2D_DSTALPHA_OP_ZERO (0x06000000) +-#define PSB_2D_DSTALPHA_INVERT (0x08000000) +-#define PSB_2D_DSTALPHA_INVERT_CLR (0xF7FFFFFF) +- +-#define PSB_2D_PRE_MULTIPLICATION_ENABLE (0x10000000) +-#define PSB_2D_PRE_MULTIPLICATION_CLRMASK (0xEFFFFFFF) +-#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE (0x20000000) +-#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK (0xDFFFFFFF) +- +-/* +- *Source Offset (PSB_2D_SRC_OFF_BH) +- */ +-#define PSB_2D_SRCOFF_XSTART_MASK ((0x00000FFF) << 12) +-#define PSB_2D_SRCOFF_XSTART_SHIFT (12) +-#define PSB_2D_SRCOFF_YSTART_MASK (0x00000FFF) +-#define PSB_2D_SRCOFF_YSTART_SHIFT (0) +- +-/* +- * Mask Offset (PSB_2D_MASK_OFF_BH) +- */ +-#define PSB_2D_MASKOFF_XSTART_MASK ((0x00000FFF) << 12) +-#define PSB_2D_MASKOFF_XSTART_SHIFT (12) +-#define PSB_2D_MASKOFF_YSTART_MASK (0x00000FFF) +-#define PSB_2D_MASKOFF_YSTART_SHIFT (0) +- +-/* +- * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored +- */ +- +-/* +- *Blit Rectangle (PSB_2D_BLIT_BH) +- */ +- +-#define PSB_2D_ROT_MASK (3 << 25) +-#define PSB_2D_ROT_CLRMASK (~PSB_2D_ROT_MASK) +-#define PSB_2D_ROT_NONE (0 << 25) +-#define PSB_2D_ROT_90DEGS (1 << 25) +-#define PSB_2D_ROT_180DEGS (2 << 25) +-#define PSB_2D_ROT_270DEGS (3 << 25) +- +-#define PSB_2D_COPYORDER_MASK (3 << 23) +-#define PSB_2D_COPYORDER_CLRMASK (~PSB_2D_COPYORDER_MASK) +-#define PSB_2D_COPYORDER_TL2BR (0 << 23) +-#define PSB_2D_COPYORDER_BR2TL (1 << 23) +-#define PSB_2D_COPYORDER_TR2BL (2 << 23) +-#define PSB_2D_COPYORDER_BL2TR (3 << 23) +- +-#define PSB_2D_DSTCK_CLRMASK (0xFF9FFFFF) +-#define PSB_2D_DSTCK_DISABLE (0x00000000) +-#define PSB_2D_DSTCK_PASS (0x00200000) +-#define PSB_2D_DSTCK_REJECT (0x00400000) +- +-#define PSB_2D_SRCCK_CLRMASK (0xFFE7FFFF) +-#define PSB_2D_SRCCK_DISABLE (0x00000000) +-#define PSB_2D_SRCCK_PASS (0x00080000) +-#define PSB_2D_SRCCK_REJECT (0x00100000) +- +-#define PSB_2D_CLIP_ENABLE (0x00040000) +- +-#define PSB_2D_ALPHA_ENABLE (0x00020000) +- +-#define PSB_2D_PAT_CLRMASK (0xFFFEFFFF) +-#define PSB_2D_PAT_MASK (0x00010000) +-#define PSB_2D_USE_PAT (0x00010000) +-#define PSB_2D_USE_FILL (0x00000000) +-/* +- * Tungsten Graphics note on rop codes: If rop A and rop B are +- * identical, the mask surface will not be read and need not be +- * set up. +- */ +- +-#define PSB_2D_ROP3B_MASK (0x0000FF00) +-#define PSB_2D_ROP3B_CLRMASK (0xFFFF00FF) +-#define PSB_2D_ROP3B_SHIFT (8) +-/* rop code A */ +-#define PSB_2D_ROP3A_MASK (0x000000FF) +-#define PSB_2D_ROP3A_CLRMASK (0xFFFFFF00) +-#define PSB_2D_ROP3A_SHIFT (0) +- +-#define PSB_2D_ROP4_MASK (0x0000FFFF) +-/* +- * DWORD0: (Only pass if Pattern control == Use Fill Colour) +- * Fill Colour RGBA8888 +- */ +-#define PSB_2D_FILLCOLOUR_MASK (0xFFFFFFFF) +-#define PSB_2D_FILLCOLOUR_SHIFT (0) +-/* +- * DWORD1: (Always Present) +- * X Start (Dest) +- * Y Start (Dest) +- */ +-#define PSB_2D_DST_XSTART_MASK (0x00FFF000) +-#define PSB_2D_DST_XSTART_CLRMASK (0xFF000FFF) +-#define PSB_2D_DST_XSTART_SHIFT (12) +-#define PSB_2D_DST_YSTART_MASK (0x00000FFF) +-#define PSB_2D_DST_YSTART_CLRMASK (0xFFFFF000) +-#define PSB_2D_DST_YSTART_SHIFT (0) +-/* +- * DWORD2: (Always Present) +- * X Size (Dest) +- * Y Size (Dest) +- */ +-#define PSB_2D_DST_XSIZE_MASK (0x00FFF000) +-#define PSB_2D_DST_XSIZE_CLRMASK (0xFF000FFF) +-#define PSB_2D_DST_XSIZE_SHIFT (12) +-#define PSB_2D_DST_YSIZE_MASK (0x00000FFF) +-#define PSB_2D_DST_YSIZE_CLRMASK (0xFFFFF000) +-#define PSB_2D_DST_YSIZE_SHIFT (0) +- +-/* +- * Source Surface (PSB_2D_SRC_SURF_BH) +- */ +-/* +- * WORD 0 +- */ +- +-#define PSB_2D_SRC_FORMAT_MASK (0x00078000) +-#define PSB_2D_SRC_1_PAL (0x00000000) +-#define PSB_2D_SRC_2_PAL (0x00008000) +-#define PSB_2D_SRC_4_PAL (0x00010000) +-#define PSB_2D_SRC_8_PAL (0x00018000) +-#define PSB_2D_SRC_8_ALPHA (0x00020000) +-#define PSB_2D_SRC_4_ALPHA (0x00028000) +-#define PSB_2D_SRC_332RGB (0x00030000) +-#define PSB_2D_SRC_4444ARGB (0x00038000) +-#define PSB_2D_SRC_555RGB (0x00040000) +-#define PSB_2D_SRC_1555ARGB (0x00048000) +-#define PSB_2D_SRC_565RGB (0x00050000) +-#define PSB_2D_SRC_0888ARGB (0x00058000) +-#define PSB_2D_SRC_8888ARGB (0x00060000) +-#define PSB_2D_SRC_8888UYVY (0x00068000) +-#define PSB_2D_SRC_RESERVED (0x00070000) +-#define PSB_2D_SRC_1555ARGB_LOOKUP (0x00078000) +- +- +-#define PSB_2D_SRC_STRIDE_MASK (0x00007FFF) +-#define PSB_2D_SRC_STRIDE_CLRMASK (0xFFFF8000) +-#define PSB_2D_SRC_STRIDE_SHIFT (0) +-/* +- * WORD 1 - Base Address +- */ +-#define PSB_2D_SRC_ADDR_MASK (0x0FFFFFFC) +-#define PSB_2D_SRC_ADDR_CLRMASK (0x00000003) +-#define PSB_2D_SRC_ADDR_SHIFT (2) +-#define PSB_2D_SRC_ADDR_ALIGNSHIFT (2) +- +-/* +- * Pattern Surface (PSB_2D_PAT_SURF_BH) +- */ +-/* +- * WORD 0 +- */ +- +-#define PSB_2D_PAT_FORMAT_MASK (0x00078000) +-#define PSB_2D_PAT_1_PAL (0x00000000) +-#define PSB_2D_PAT_2_PAL (0x00008000) +-#define PSB_2D_PAT_4_PAL (0x00010000) +-#define PSB_2D_PAT_8_PAL (0x00018000) +-#define PSB_2D_PAT_8_ALPHA (0x00020000) +-#define PSB_2D_PAT_4_ALPHA (0x00028000) +-#define PSB_2D_PAT_332RGB (0x00030000) +-#define PSB_2D_PAT_4444ARGB (0x00038000) +-#define PSB_2D_PAT_555RGB (0x00040000) +-#define PSB_2D_PAT_1555ARGB (0x00048000) +-#define PSB_2D_PAT_565RGB (0x00050000) +-#define PSB_2D_PAT_0888ARGB (0x00058000) +-#define PSB_2D_PAT_8888ARGB (0x00060000) +- +-#define PSB_2D_PAT_STRIDE_MASK (0x00007FFF) +-#define PSB_2D_PAT_STRIDE_CLRMASK (0xFFFF8000) +-#define PSB_2D_PAT_STRIDE_SHIFT (0) +-/* +- * WORD 1 - Base Address +- */ +-#define PSB_2D_PAT_ADDR_MASK (0x0FFFFFFC) +-#define PSB_2D_PAT_ADDR_CLRMASK (0x00000003) +-#define PSB_2D_PAT_ADDR_SHIFT (2) +-#define PSB_2D_PAT_ADDR_ALIGNSHIFT (2) +- +-/* +- * Destination Surface (PSB_2D_DST_SURF_BH) +- */ +-/* +- * WORD 0 +- */ +- +-#define PSB_2D_DST_FORMAT_MASK (0x00078000) +-#define PSB_2D_DST_332RGB (0x00030000) +-#define PSB_2D_DST_4444ARGB (0x00038000) +-#define PSB_2D_DST_555RGB (0x00040000) +-#define PSB_2D_DST_1555ARGB (0x00048000) +-#define PSB_2D_DST_565RGB (0x00050000) +-#define PSB_2D_DST_0888ARGB (0x00058000) +-#define PSB_2D_DST_8888ARGB (0x00060000) +-#define PSB_2D_DST_8888AYUV (0x00070000) +- +-#define PSB_2D_DST_STRIDE_MASK (0x00007FFF) +-#define PSB_2D_DST_STRIDE_CLRMASK (0xFFFF8000) +-#define PSB_2D_DST_STRIDE_SHIFT (0) +-/* +- * WORD 1 - Base Address +- */ +-#define PSB_2D_DST_ADDR_MASK (0x0FFFFFFC) +-#define PSB_2D_DST_ADDR_CLRMASK (0x00000003) +-#define PSB_2D_DST_ADDR_SHIFT (2) +-#define PSB_2D_DST_ADDR_ALIGNSHIFT (2) +- +-/* +- * Mask Surface (PSB_2D_MASK_SURF_BH) +- */ +-/* +- * WORD 0 +- */ +-#define PSB_2D_MASK_STRIDE_MASK (0x00007FFF) +-#define PSB_2D_MASK_STRIDE_CLRMASK (0xFFFF8000) +-#define PSB_2D_MASK_STRIDE_SHIFT (0) +-/* +- * WORD 1 - Base Address +- */ +-#define PSB_2D_MASK_ADDR_MASK (0x0FFFFFFC) +-#define PSB_2D_MASK_ADDR_CLRMASK (0x00000003) +-#define PSB_2D_MASK_ADDR_SHIFT (2) +-#define PSB_2D_MASK_ADDR_ALIGNSHIFT (2) +- +-/* +- * Source Palette (PSB_2D_SRC_PAL_BH) +- */ +- +-#define PSB_2D_SRCPAL_ADDR_SHIFT (0) +-#define PSB_2D_SRCPAL_ADDR_CLRMASK (0xF0000007) +-#define PSB_2D_SRCPAL_ADDR_MASK (0x0FFFFFF8) +-#define PSB_2D_SRCPAL_BYTEALIGN (1024) +- +-/* +- * Pattern Palette (PSB_2D_PAT_PAL_BH) +- */ +- +-#define PSB_2D_PATPAL_ADDR_SHIFT (0) +-#define PSB_2D_PATPAL_ADDR_CLRMASK (0xF0000007) +-#define PSB_2D_PATPAL_ADDR_MASK (0x0FFFFFF8) +-#define PSB_2D_PATPAL_BYTEALIGN (1024) +- +-/* +- * Rop3 Codes (2 LS bytes) +- */ +- +-#define PSB_2D_ROP3_SRCCOPY (0xCCCC) +-#define PSB_2D_ROP3_PATCOPY (0xF0F0) +-#define PSB_2D_ROP3_WHITENESS (0xFFFF) +-#define PSB_2D_ROP3_BLACKNESS (0x0000) +-#define PSB_2D_ROP3_SRC (0xCC) +-#define PSB_2D_ROP3_PAT (0xF0) +-#define PSB_2D_ROP3_DST (0xAA) +- +-/* +- * Sizes. +- */ +- +-#define PSB_SCENE_HW_COOKIE_SIZE 16 +-#define PSB_TA_MEM_HW_COOKIE_SIZE 16 +- +-/* +- * Scene stuff. +- */ +- +-#define PSB_NUM_HW_SCENES 2 +- +-/* +- * Scheduler completion actions. +- */ +- +-#define PSB_RASTER_BLOCK 0 +-#define PSB_RASTER 1 +-#define PSB_RETURN 2 +-#define PSB_TA 3 +- +-/* Power management */ +-#define PSB_PUNIT_PORT 0x04 +-#define PSB_OSPMBA 0x78 +-#define PSB_APMBA 0x7a +-#define PSB_APM_CMD 0x0 +-#define PSB_APM_STS 0x04 +-#define PSB_PWRGT_VID_ENC_MASK 0x30 +-#define PSB_PWRGT_VID_DEC_MASK 0xc +-#define PSB_PWRGT_GL3_MASK 0xc0 +- +-#define PSB_PM_SSC 0x20 +-#define PSB_PM_SSS 0x30 +-#define PSB_PWRGT_DISPLAY_MASK 0xc /*on a different BA than video/gfx*/ +-#define MDFLD_PWRGT_DISPLAY_A_CNTR 0x0000000c +-#define MDFLD_PWRGT_DISPLAY_B_CNTR 0x0000c000 +-#define MDFLD_PWRGT_DISPLAY_C_CNTR 0x00030000 +-#define MDFLD_PWRGT_DISP_MIPI_CNTR 0x000c0000 +-#define MDFLD_PWRGT_DISPLAY_CNTR (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR) /* 0x000fc00c */ +-/* Display SSS register bits are different in A0 vs. B0 */ +-#define PSB_PWRGT_GFX_MASK 0x3 +-#define MDFLD_PWRGT_DISPLAY_A_STS 0x000000c0 +-#define MDFLD_PWRGT_DISPLAY_B_STS 0x00000300 +-#define MDFLD_PWRGT_DISPLAY_C_STS 0x00000c00 +-#define PSB_PWRGT_GFX_MASK_B0 0xc3 +-#define MDFLD_PWRGT_DISPLAY_A_STS_B0 0x0000000c +-#define MDFLD_PWRGT_DISPLAY_B_STS_B0 0x0000c000 +-#define MDFLD_PWRGT_DISPLAY_C_STS_B0 0x00030000 +-#define MDFLD_PWRGT_DISP_MIPI_STS 0x000c0000 +-#define MDFLD_PWRGT_DISPLAY_STS_A0 (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */ +-#define MDFLD_PWRGT_DISPLAY_STS_B0 (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */ +-#endif +diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig +deleted file mode 100644 +index 072185e..0000000 +--- a/drivers/staging/hv/Kconfig ++++ /dev/null +@@ -1,17 +0,0 @@ +-config HYPERV_STORAGE +- tristate "Microsoft Hyper-V virtual storage driver" +- depends on HYPERV && SCSI +- help +- Select this option to enable the Hyper-V virtual storage driver. +- +-config HYPERV_NET +- tristate "Microsoft Hyper-V virtual network driver" +- depends on HYPERV && NET +- help +- Select this option to enable the Hyper-V virtual network driver. +- +-config HYPERV_MOUSE +- tristate "Microsoft Hyper-V mouse driver" +- depends on HYPERV && HID +- help +- Select this option to enable the Hyper-V mouse driver. +diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile +deleted file mode 100644 +index 0f55cee..0000000 +--- a/drivers/staging/hv/Makefile ++++ /dev/null +@@ -1,6 +0,0 @@ +-obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o +-obj-$(CONFIG_HYPERV_NET) += hv_netvsc.o +-obj-$(CONFIG_HYPERV_MOUSE) += hv_mouse.o +- +-hv_storvsc-y := storvsc_drv.o +-hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o +diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO +deleted file mode 100644 +index ed4d636..0000000 +--- a/drivers/staging/hv/TODO ++++ /dev/null +@@ -1,7 +0,0 @@ +-TODO: +- - audit the network driver +- - audit the scsi driver +- +-Please send patches for this code to Greg Kroah-Hartman , +-Hank Janssen , Haiyang Zhang , +-K. Y. Srinivasan +diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c +deleted file mode 100644 +index ccd39c7..0000000 +--- a/drivers/staging/hv/hv_mouse.c ++++ /dev/null +@@ -1,599 +0,0 @@ +-/* +- * Copyright (c) 2009, Citrix Systems, Inc. +- * Copyright (c) 2010, Microsoft Corporation. +- * Copyright (c) 2011, Novell Inc. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * 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 +- +- +-struct hv_input_dev_info { +- unsigned int size; +- unsigned short vendor; +- unsigned short product; +- unsigned short version; +- unsigned short reserved[11]; +-}; +- +-/* The maximum size of a synthetic input message. */ +-#define SYNTHHID_MAX_INPUT_REPORT_SIZE 16 +- +-/* +- * Current version +- * +- * History: +- * Beta, RC < 2008/1/22 1,0 +- * RC > 2008/1/22 2,0 +- */ +-#define SYNTHHID_INPUT_VERSION_MAJOR 2 +-#define SYNTHHID_INPUT_VERSION_MINOR 0 +-#define SYNTHHID_INPUT_VERSION (SYNTHHID_INPUT_VERSION_MINOR | \ +- (SYNTHHID_INPUT_VERSION_MAJOR << 16)) +- +- +-#pragma pack(push, 1) +-/* +- * Message types in the synthetic input protocol +- */ +-enum synthhid_msg_type { +- SYNTH_HID_PROTOCOL_REQUEST, +- SYNTH_HID_PROTOCOL_RESPONSE, +- SYNTH_HID_INITIAL_DEVICE_INFO, +- SYNTH_HID_INITIAL_DEVICE_INFO_ACK, +- SYNTH_HID_INPUT_REPORT, +- SYNTH_HID_MAX +-}; +- +-/* +- * Basic message structures. +- */ +-struct synthhid_msg_hdr { +- enum synthhid_msg_type type; +- u32 size; +-}; +- +-struct synthhid_msg { +- struct synthhid_msg_hdr header; +- char data[1]; /* Enclosed message */ +-}; +- +-union synthhid_version { +- struct { +- u16 minor_version; +- u16 major_version; +- }; +- u32 version; +-}; +- +-/* +- * Protocol messages +- */ +-struct synthhid_protocol_request { +- struct synthhid_msg_hdr header; +- union synthhid_version version_requested; +-}; +- +-struct synthhid_protocol_response { +- struct synthhid_msg_hdr header; +- union synthhid_version version_requested; +- unsigned char approved; +-}; +- +-struct synthhid_device_info { +- struct synthhid_msg_hdr header; +- struct hv_input_dev_info hid_dev_info; +- struct hid_descriptor hid_descriptor; +-}; +- +-struct synthhid_device_info_ack { +- struct synthhid_msg_hdr header; +- unsigned char reserved; +-}; +- +-struct synthhid_input_report { +- struct synthhid_msg_hdr header; +- char buffer[1]; +-}; +- +-#pragma pack(pop) +- +-#define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE) +-#define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE) +- +-#define NBITS(x) (((x)/BITS_PER_LONG)+1) +- +-enum pipe_prot_msg_type { +- PIPE_MESSAGE_INVALID, +- PIPE_MESSAGE_DATA, +- PIPE_MESSAGE_MAXIMUM +-}; +- +- +-struct pipe_prt_msg { +- enum pipe_prot_msg_type type; +- u32 size; +- char data[1]; +-}; +- +-struct mousevsc_prt_msg { +- enum pipe_prot_msg_type type; +- u32 size; +- union { +- struct synthhid_protocol_request request; +- struct synthhid_protocol_response response; +- struct synthhid_device_info_ack ack; +- }; +-}; +- +-/* +- * Represents an mousevsc device +- */ +-struct mousevsc_dev { +- struct hv_device *device; +- unsigned char init_complete; +- struct mousevsc_prt_msg protocol_req; +- struct mousevsc_prt_msg protocol_resp; +- /* Synchronize the request/response if needed */ +- struct completion wait_event; +- int dev_info_status; +- +- struct hid_descriptor *hid_desc; +- unsigned char *report_desc; +- u32 report_desc_size; +- struct hv_input_dev_info hid_dev_info; +- int connected; +- struct hid_device *hid_device; +-}; +- +- +-static struct mousevsc_dev *alloc_input_device(struct hv_device *device) +-{ +- struct mousevsc_dev *input_dev; +- +- input_dev = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL); +- +- if (!input_dev) +- return NULL; +- +- input_dev->device = device; +- hv_set_drvdata(device, input_dev); +- init_completion(&input_dev->wait_event); +- +- return input_dev; +-} +- +-static void free_input_device(struct mousevsc_dev *device) +-{ +- kfree(device->hid_desc); +- kfree(device->report_desc); +- hv_set_drvdata(device->device, NULL); +- kfree(device); +-} +- +- +-static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, +- struct synthhid_device_info *device_info) +-{ +- int ret = 0; +- struct hid_descriptor *desc; +- struct mousevsc_prt_msg ack; +- +- /* Assume success for now */ +- input_device->dev_info_status = 0; +- +- memcpy(&input_device->hid_dev_info, &device_info->hid_dev_info, +- sizeof(struct hv_input_dev_info)); +- +- desc = &device_info->hid_descriptor; +- WARN_ON(desc->bLength == 0); +- +- input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC); +- +- if (!input_device->hid_desc) +- goto cleanup; +- +- memcpy(input_device->hid_desc, desc, desc->bLength); +- +- input_device->report_desc_size = desc->desc[0].wDescriptorLength; +- if (input_device->report_desc_size == 0) +- goto cleanup; +- input_device->report_desc = kzalloc(input_device->report_desc_size, +- GFP_ATOMIC); +- +- if (!input_device->report_desc) +- goto cleanup; +- +- memcpy(input_device->report_desc, +- ((unsigned char *)desc) + desc->bLength, +- desc->desc[0].wDescriptorLength); +- +- /* Send the ack */ +- memset(&ack, 0, sizeof(struct mousevsc_prt_msg)); +- +- ack.type = PIPE_MESSAGE_DATA; +- ack.size = sizeof(struct synthhid_device_info_ack); +- +- ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK; +- ack.ack.header.size = 1; +- ack.ack.reserved = 0; +- +- ret = vmbus_sendpacket(input_device->device->channel, +- &ack, +- sizeof(struct pipe_prt_msg) - sizeof(unsigned char) + +- sizeof(struct synthhid_device_info_ack), +- (unsigned long)&ack, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); +- if (ret != 0) +- goto cleanup; +- +- complete(&input_device->wait_event); +- +- return; +- +-cleanup: +- kfree(input_device->hid_desc); +- input_device->hid_desc = NULL; +- +- kfree(input_device->report_desc); +- input_device->report_desc = NULL; +- +- input_device->dev_info_status = -1; +- complete(&input_device->wait_event); +-} +- +-static void mousevsc_on_receive(struct hv_device *device, +- struct vmpacket_descriptor *packet) +-{ +- struct pipe_prt_msg *pipe_msg; +- struct synthhid_msg *hid_msg; +- struct mousevsc_dev *input_dev = hv_get_drvdata(device); +- struct synthhid_input_report *input_report; +- +- pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet + +- (packet->offset8 << 3)); +- +- if (pipe_msg->type != PIPE_MESSAGE_DATA) +- return; +- +- hid_msg = (struct synthhid_msg *)&pipe_msg->data[0]; +- +- switch (hid_msg->header.type) { +- case SYNTH_HID_PROTOCOL_RESPONSE: +- memcpy(&input_dev->protocol_resp, pipe_msg, +- pipe_msg->size + sizeof(struct pipe_prt_msg) - +- sizeof(unsigned char)); +- complete(&input_dev->wait_event); +- break; +- +- case SYNTH_HID_INITIAL_DEVICE_INFO: +- WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info)); +- +- /* +- * Parse out the device info into device attr, +- * hid desc and report desc +- */ +- mousevsc_on_receive_device_info(input_dev, +- (struct synthhid_device_info *)&pipe_msg->data[0]); +- break; +- case SYNTH_HID_INPUT_REPORT: +- input_report = +- (struct synthhid_input_report *)&pipe_msg->data[0]; +- if (!input_dev->init_complete) +- break; +- hid_input_report(input_dev->hid_device, +- HID_INPUT_REPORT, input_report->buffer, +- input_report->header.size, 1); +- break; +- default: +- pr_err("unsupported hid msg type - type %d len %d", +- hid_msg->header.type, hid_msg->header.size); +- break; +- } +- +-} +- +-static void mousevsc_on_channel_callback(void *context) +-{ +- const int packetSize = 0x100; +- int ret = 0; +- struct hv_device *device = (struct hv_device *)context; +- +- u32 bytes_recvd; +- u64 req_id; +- unsigned char packet[0x100]; +- struct vmpacket_descriptor *desc; +- unsigned char *buffer = packet; +- int bufferlen = packetSize; +- +- +- do { +- ret = vmbus_recvpacket_raw(device->channel, buffer, +- bufferlen, &bytes_recvd, &req_id); +- +- if (ret == 0) { +- if (bytes_recvd > 0) { +- desc = (struct vmpacket_descriptor *)buffer; +- +- switch (desc->type) { +- case VM_PKT_COMP: +- break; +- +- case VM_PKT_DATA_INBAND: +- mousevsc_on_receive( +- device, desc); +- break; +- +- default: +- pr_err("unhandled packet type %d, tid %llx len %d\n", +- desc->type, +- req_id, +- bytes_recvd); +- break; +- } +- +- /* reset */ +- if (bufferlen > packetSize) { +- kfree(buffer); +- +- buffer = packet; +- bufferlen = packetSize; +- } +- } else { +- if (bufferlen > packetSize) { +- kfree(buffer); +- +- buffer = packet; +- bufferlen = packetSize; +- } +- break; +- } +- } else if (ret == -ENOBUFS) { +- /* Handle large packet */ +- bufferlen = bytes_recvd; +- buffer = kzalloc(bytes_recvd, GFP_ATOMIC); +- +- if (buffer == NULL) { +- buffer = packet; +- bufferlen = packetSize; +- break; +- } +- } +- } while (1); +- +- return; +-} +- +-static int mousevsc_connect_to_vsp(struct hv_device *device) +-{ +- int ret = 0; +- int t; +- struct mousevsc_dev *input_dev = hv_get_drvdata(device); +- struct mousevsc_prt_msg *request; +- struct mousevsc_prt_msg *response; +- +- +- request = &input_dev->protocol_req; +- +- memset(request, 0, sizeof(struct mousevsc_prt_msg)); +- +- request->type = PIPE_MESSAGE_DATA; +- request->size = sizeof(struct synthhid_protocol_request); +- +- request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST; +- request->request.header.size = sizeof(unsigned int); +- request->request.version_requested.version = SYNTHHID_INPUT_VERSION; +- +- +- ret = vmbus_sendpacket(device->channel, request, +- sizeof(struct pipe_prt_msg) - +- sizeof(unsigned char) + +- sizeof(struct synthhid_protocol_request), +- (unsigned long)request, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); +- if (ret != 0) +- goto cleanup; +- +- t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- response = &input_dev->protocol_resp; +- +- if (!response->response.approved) { +- pr_err("synthhid protocol request failed (version %d)", +- SYNTHHID_INPUT_VERSION); +- ret = -ENODEV; +- goto cleanup; +- } +- +- t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- /* +- * We should have gotten the device attr, hid desc and report +- * desc at this point +- */ +- if (input_dev->dev_info_status) +- ret = -ENOMEM; +- +-cleanup: +- +- return ret; +-} +- +-static int mousevsc_hid_open(struct hid_device *hid) +-{ +- return 0; +-} +- +-static void mousevsc_hid_close(struct hid_device *hid) +-{ +-} +- +-static struct hid_ll_driver mousevsc_ll_driver = { +- .open = mousevsc_hid_open, +- .close = mousevsc_hid_close, +-}; +- +-static struct hid_driver mousevsc_hid_driver; +- +-static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) +-{ +- struct hid_device *hid_dev; +- struct mousevsc_dev *input_device = hv_get_drvdata(dev); +- +- hid_dev = hid_allocate_device(); +- if (IS_ERR(hid_dev)) +- return; +- +- hid_dev->ll_driver = &mousevsc_ll_driver; +- hid_dev->driver = &mousevsc_hid_driver; +- +- if (hid_parse_report(hid_dev, packet, len)) +- return; +- +- hid_dev->bus = BUS_VIRTUAL; +- hid_dev->vendor = input_device->hid_dev_info.vendor; +- hid_dev->product = input_device->hid_dev_info.product; +- hid_dev->version = input_device->hid_dev_info.version; +- +- sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse"); +- +- if (!hidinput_connect(hid_dev, 0)) { +- hid_dev->claimed |= HID_CLAIMED_INPUT; +- +- input_device->connected = 1; +- +- } +- +- input_device->hid_device = hid_dev; +-} +- +-static int mousevsc_on_device_add(struct hv_device *device) +-{ +- int ret = 0; +- struct mousevsc_dev *input_dev; +- +- input_dev = alloc_input_device(device); +- +- if (!input_dev) +- return -ENOMEM; +- +- input_dev->init_complete = false; +- +- ret = vmbus_open(device->channel, +- INPUTVSC_SEND_RING_BUFFER_SIZE, +- INPUTVSC_RECV_RING_BUFFER_SIZE, +- NULL, +- 0, +- mousevsc_on_channel_callback, +- device +- ); +- +- if (ret != 0) { +- free_input_device(input_dev); +- return ret; +- } +- +- +- ret = mousevsc_connect_to_vsp(device); +- +- if (ret != 0) { +- vmbus_close(device->channel); +- free_input_device(input_dev); +- return ret; +- } +- +- +- /* workaround SA-167 */ +- if (input_dev->report_desc[14] == 0x25) +- input_dev->report_desc[14] = 0x29; +- +- reportdesc_callback(device, input_dev->report_desc, +- input_dev->report_desc_size); +- +- input_dev->init_complete = true; +- +- return ret; +-} +- +-static int mousevsc_probe(struct hv_device *dev, +- const struct hv_vmbus_device_id *dev_id) +-{ +- +- return mousevsc_on_device_add(dev); +- +-} +- +-static int mousevsc_remove(struct hv_device *dev) +-{ +- struct mousevsc_dev *input_dev = hv_get_drvdata(dev); +- +- vmbus_close(dev->channel); +- +- if (input_dev->connected) { +- hidinput_disconnect(input_dev->hid_device); +- input_dev->connected = 0; +- hid_destroy_device(input_dev->hid_device); +- } +- +- free_input_device(input_dev); +- +- return 0; +-} +- +-static const struct hv_vmbus_device_id id_table[] = { +- /* Mouse guid */ +- { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, +- 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A) }, +- { }, +-}; +- +-MODULE_DEVICE_TABLE(vmbus, id_table); +- +-static struct hv_driver mousevsc_drv = { +- .name = "mousevsc", +- .id_table = id_table, +- .probe = mousevsc_probe, +- .remove = mousevsc_remove, +-}; +- +-static int __init mousevsc_init(void) +-{ +- return vmbus_driver_register(&mousevsc_drv); +-} +- +-static void __exit mousevsc_exit(void) +-{ +- vmbus_driver_unregister(&mousevsc_drv); +-} +- +-MODULE_LICENSE("GPL"); +-MODULE_VERSION(HV_DRV_VERSION); +-module_init(mousevsc_init); +-module_exit(mousevsc_exit); +diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h +deleted file mode 100644 +index ac1ec84..0000000 +--- a/drivers/staging/hv/hyperv_net.h ++++ /dev/null +@@ -1,1058 +0,0 @@ +-/* +- * +- * Copyright (c) 2011, Microsoft Corporation. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple +- * Place - Suite 330, Boston, MA 02111-1307 USA. +- * +- * Authors: +- * Haiyang Zhang +- * Hank Janssen +- * K. Y. Srinivasan +- * +- */ +- +-#ifndef _HYPERV_NET_H +-#define _HYPERV_NET_H +- +-#include +-#include +- +-/* Fwd declaration */ +-struct hv_netvsc_packet; +- +-/* Represent the xfer page packet which contains 1 or more netvsc packet */ +-struct xferpage_packet { +- struct list_head list_ent; +- +- /* # of netvsc packets this xfer packet contains */ +- u32 count; +-}; +- +-/* The number of pages which are enough to cover jumbo frame buffer. */ +-#define NETVSC_PACKET_MAXPAGE 4 +- +-/* +- * Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame +- * within the RNDIS +- */ +-struct hv_netvsc_packet { +- /* Bookkeeping stuff */ +- struct list_head list_ent; +- +- struct hv_device *device; +- bool is_data_pkt; +- +- /* +- * Valid only for receives when we break a xfer page packet +- * into multiple netvsc packets +- */ +- struct xferpage_packet *xfer_page_pkt; +- +- union { +- struct { +- u64 recv_completion_tid; +- void *recv_completion_ctx; +- void (*recv_completion)(void *context); +- } recv; +- struct { +- u64 send_completion_tid; +- void *send_completion_ctx; +- void (*send_completion)(void *context); +- } send; +- } completion; +- +- /* This points to the memory after page_buf */ +- void *extension; +- +- u32 total_data_buflen; +- /* Points to the send/receive buffer where the ethernet frame is */ +- u32 page_buf_cnt; +- struct hv_page_buffer page_buf[NETVSC_PACKET_MAXPAGE]; +-}; +- +-struct netvsc_device_info { +- unsigned char mac_adr[6]; +- bool link_state; /* 0 - link up, 1 - link down */ +- int ring_size; +-}; +- +-/* Interface */ +-int netvsc_device_add(struct hv_device *device, void *additional_info); +-int netvsc_device_remove(struct hv_device *device); +-int netvsc_send(struct hv_device *device, +- struct hv_netvsc_packet *packet); +-void netvsc_linkstatus_callback(struct hv_device *device_obj, +- unsigned int status); +-int netvsc_recv_callback(struct hv_device *device_obj, +- struct hv_netvsc_packet *packet); +-int rndis_filter_open(struct hv_device *dev); +-int rndis_filter_close(struct hv_device *dev); +-int rndis_filter_device_add(struct hv_device *dev, +- void *additional_info); +-void rndis_filter_device_remove(struct hv_device *dev); +-int rndis_filter_receive(struct hv_device *dev, +- struct hv_netvsc_packet *pkt); +- +- +- +-int rndis_filter_send(struct hv_device *dev, +- struct hv_netvsc_packet *pkt); +- +-#define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF) +- +-#define NVSP_PROTOCOL_VERSION_1 2 +-#define NVSP_MIN_PROTOCOL_VERSION NVSP_PROTOCOL_VERSION_1 +-#define NVSP_MAX_PROTOCOL_VERSION NVSP_PROTOCOL_VERSION_1 +- +-enum { +- NVSP_MSG_TYPE_NONE = 0, +- +- /* Init Messages */ +- NVSP_MSG_TYPE_INIT = 1, +- NVSP_MSG_TYPE_INIT_COMPLETE = 2, +- +- NVSP_VERSION_MSG_START = 100, +- +- /* Version 1 Messages */ +- NVSP_MSG1_TYPE_SEND_NDIS_VER = NVSP_VERSION_MSG_START, +- +- NVSP_MSG1_TYPE_SEND_RECV_BUF, +- NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE, +- NVSP_MSG1_TYPE_REVOKE_RECV_BUF, +- +- NVSP_MSG1_TYPE_SEND_SEND_BUF, +- NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE, +- NVSP_MSG1_TYPE_REVOKE_SEND_BUF, +- +- NVSP_MSG1_TYPE_SEND_RNDIS_PKT, +- NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE, +- +- /* +- * This should be set to the number of messages for the version with +- * the maximum number of messages. +- */ +- NVSP_NUM_MSG_PER_VERSION = 9, +-}; +- +-enum { +- NVSP_STAT_NONE = 0, +- NVSP_STAT_SUCCESS, +- NVSP_STAT_FAIL, +- NVSP_STAT_PROTOCOL_TOO_NEW, +- NVSP_STAT_PROTOCOL_TOO_OLD, +- NVSP_STAT_INVALID_RNDIS_PKT, +- NVSP_STAT_BUSY, +- NVSP_STAT_MAX, +-}; +- +-struct nvsp_message_header { +- u32 msg_type; +-}; +- +-/* Init Messages */ +- +-/* +- * This message is used by the VSC to initialize the channel after the channels +- * has been opened. This message should never include anything other then +- * versioning (i.e. this message will be the same for ever). +- */ +-struct nvsp_message_init { +- u32 min_protocol_ver; +- u32 max_protocol_ver; +-} __packed; +- +-/* +- * This message is used by the VSP to complete the initialization of the +- * channel. This message should never include anything other then versioning +- * (i.e. this message will be the same for ever). +- */ +-struct nvsp_message_init_complete { +- u32 negotiated_protocol_ver; +- u32 max_mdl_chain_len; +- u32 status; +-} __packed; +- +-union nvsp_message_init_uber { +- struct nvsp_message_init init; +- struct nvsp_message_init_complete init_complete; +-} __packed; +- +-/* Version 1 Messages */ +- +-/* +- * This message is used by the VSC to send the NDIS version to the VSP. The VSP +- * can use this information when handling OIDs sent by the VSC. +- */ +-struct nvsp_1_message_send_ndis_version { +- u32 ndis_major_ver; +- u32 ndis_minor_ver; +-} __packed; +- +-/* +- * This message is used by the VSC to send a receive buffer to the VSP. The VSP +- * can then use the receive buffer to send data to the VSC. +- */ +-struct nvsp_1_message_send_receive_buffer { +- u32 gpadl_handle; +- u16 id; +-} __packed; +- +-struct nvsp_1_receive_buffer_section { +- u32 offset; +- u32 sub_alloc_size; +- u32 num_sub_allocs; +- u32 end_offset; +-} __packed; +- +-/* +- * This message is used by the VSP to acknowledge a receive buffer send by the +- * VSC. This message must be sent by the VSP before the VSP uses the receive +- * buffer. +- */ +-struct nvsp_1_message_send_receive_buffer_complete { +- u32 status; +- u32 num_sections; +- +- /* +- * The receive buffer is split into two parts, a large suballocation +- * section and a small suballocation section. These sections are then +- * suballocated by a certain size. +- */ +- +- /* +- * For example, the following break up of the receive buffer has 6 +- * large suballocations and 10 small suballocations. +- */ +- +- /* +- * | Large Section | | Small Section | +- * ------------------------------------------------------------ +- * | | | | | | | | | | | | | | | | | | +- * | | +- * LargeOffset SmallOffset +- */ +- +- struct nvsp_1_receive_buffer_section sections[1]; +-} __packed; +- +-/* +- * This message is sent by the VSC to revoke the receive buffer. After the VSP +- * completes this transaction, the vsp should never use the receive buffer +- * again. +- */ +-struct nvsp_1_message_revoke_receive_buffer { +- u16 id; +-}; +- +-/* +- * This message is used by the VSC to send a send buffer to the VSP. The VSC +- * can then use the send buffer to send data to the VSP. +- */ +-struct nvsp_1_message_send_send_buffer { +- u32 gpadl_handle; +- u16 id; +-} __packed; +- +-/* +- * This message is used by the VSP to acknowledge a send buffer sent by the +- * VSC. This message must be sent by the VSP before the VSP uses the sent +- * buffer. +- */ +-struct nvsp_1_message_send_send_buffer_complete { +- u32 status; +- +- /* +- * The VSC gets to choose the size of the send buffer and the VSP gets +- * to choose the sections size of the buffer. This was done to enable +- * dynamic reconfigurations when the cost of GPA-direct buffers +- * decreases. +- */ +- u32 section_size; +-} __packed; +- +-/* +- * This message is sent by the VSC to revoke the send buffer. After the VSP +- * completes this transaction, the vsp should never use the send buffer again. +- */ +-struct nvsp_1_message_revoke_send_buffer { +- u16 id; +-}; +- +-/* +- * This message is used by both the VSP and the VSC to send a RNDIS message to +- * the opposite channel endpoint. +- */ +-struct nvsp_1_message_send_rndis_packet { +- /* +- * This field is specified by RNIDS. They assume there's two different +- * channels of communication. However, the Network VSP only has one. +- * Therefore, the channel travels with the RNDIS packet. +- */ +- u32 channel_type; +- +- /* +- * This field is used to send part or all of the data through a send +- * buffer. This values specifies an index into the send buffer. If the +- * index is 0xFFFFFFFF, then the send buffer is not being used and all +- * of the data was sent through other VMBus mechanisms. +- */ +- u32 send_buf_section_index; +- u32 send_buf_section_size; +-} __packed; +- +-/* +- * This message is used by both the VSP and the VSC to complete a RNDIS message +- * to the opposite channel endpoint. At this point, the initiator of this +- * message cannot use any resources associated with the original RNDIS packet. +- */ +-struct nvsp_1_message_send_rndis_packet_complete { +- u32 status; +-}; +- +-union nvsp_1_message_uber { +- struct nvsp_1_message_send_ndis_version send_ndis_ver; +- +- struct nvsp_1_message_send_receive_buffer send_recv_buf; +- struct nvsp_1_message_send_receive_buffer_complete +- send_recv_buf_complete; +- struct nvsp_1_message_revoke_receive_buffer revoke_recv_buf; +- +- struct nvsp_1_message_send_send_buffer send_send_buf; +- struct nvsp_1_message_send_send_buffer_complete send_send_buf_complete; +- struct nvsp_1_message_revoke_send_buffer revoke_send_buf; +- +- struct nvsp_1_message_send_rndis_packet send_rndis_pkt; +- struct nvsp_1_message_send_rndis_packet_complete +- send_rndis_pkt_complete; +-} __packed; +- +-union nvsp_all_messages { +- union nvsp_message_init_uber init_msg; +- union nvsp_1_message_uber v1_msg; +-} __packed; +- +-/* ALL Messages */ +-struct nvsp_message { +- struct nvsp_message_header hdr; +- union nvsp_all_messages msg; +-} __packed; +- +- +- +- +-/* #define NVSC_MIN_PROTOCOL_VERSION 1 */ +-/* #define NVSC_MAX_PROTOCOL_VERSION 1 */ +- +-#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024) /* 1MB */ +- +-#define NETVSC_RECEIVE_BUFFER_ID 0xcafe +- +-#define NETVSC_RECEIVE_SG_COUNT 1 +- +-/* Preallocated receive packets */ +-#define NETVSC_RECEIVE_PACKETLIST_COUNT 256 +- +-#define NETVSC_PACKET_SIZE 2048 +- +-/* Per netvsc channel-specific */ +-struct netvsc_device { +- struct hv_device *dev; +- +- atomic_t num_outstanding_sends; +- bool destroy; +- /* +- * List of free preallocated hv_netvsc_packet to represent receive +- * packet +- */ +- struct list_head recv_pkt_list; +- spinlock_t recv_pkt_list_lock; +- +- /* Receive buffer allocated by us but manages by NetVSP */ +- void *recv_buf; +- u32 recv_buf_size; +- u32 recv_buf_gpadl_handle; +- u32 recv_section_cnt; +- struct nvsp_1_receive_buffer_section *recv_section; +- +- /* Used for NetVSP initialization protocol */ +- struct completion channel_init_wait; +- struct nvsp_message channel_init_pkt; +- +- struct nvsp_message revoke_packet; +- /* unsigned char HwMacAddr[HW_MACADDR_LEN]; */ +- +- struct net_device *ndev; +- +- /* Holds rndis device info */ +- void *extension; +-}; +- +- +-/* Status codes */ +- +- +-#ifndef STATUS_SUCCESS +-#define STATUS_SUCCESS (0x00000000L) +-#endif +- +-#ifndef STATUS_UNSUCCESSFUL +-#define STATUS_UNSUCCESSFUL (0xC0000001L) +-#endif +- +-#ifndef STATUS_PENDING +-#define STATUS_PENDING (0x00000103L) +-#endif +- +-#ifndef STATUS_INSUFFICIENT_RESOURCES +-#define STATUS_INSUFFICIENT_RESOURCES (0xC000009AL) +-#endif +- +-#ifndef STATUS_BUFFER_OVERFLOW +-#define STATUS_BUFFER_OVERFLOW (0x80000005L) +-#endif +- +-#ifndef STATUS_NOT_SUPPORTED +-#define STATUS_NOT_SUPPORTED (0xC00000BBL) +-#endif +- +-#define RNDIS_STATUS_SUCCESS (STATUS_SUCCESS) +-#define RNDIS_STATUS_PENDING (STATUS_PENDING) +-#define RNDIS_STATUS_NOT_RECOGNIZED (0x00010001L) +-#define RNDIS_STATUS_NOT_COPIED (0x00010002L) +-#define RNDIS_STATUS_NOT_ACCEPTED (0x00010003L) +-#define RNDIS_STATUS_CALL_ACTIVE (0x00010007L) +- +-#define RNDIS_STATUS_ONLINE (0x40010003L) +-#define RNDIS_STATUS_RESET_START (0x40010004L) +-#define RNDIS_STATUS_RESET_END (0x40010005L) +-#define RNDIS_STATUS_RING_STATUS (0x40010006L) +-#define RNDIS_STATUS_CLOSED (0x40010007L) +-#define RNDIS_STATUS_WAN_LINE_UP (0x40010008L) +-#define RNDIS_STATUS_WAN_LINE_DOWN (0x40010009L) +-#define RNDIS_STATUS_WAN_FRAGMENT (0x4001000AL) +-#define RNDIS_STATUS_MEDIA_CONNECT (0x4001000BL) +-#define RNDIS_STATUS_MEDIA_DISCONNECT (0x4001000CL) +-#define RNDIS_STATUS_HARDWARE_LINE_UP (0x4001000DL) +-#define RNDIS_STATUS_HARDWARE_LINE_DOWN (0x4001000EL) +-#define RNDIS_STATUS_INTERFACE_UP (0x4001000FL) +-#define RNDIS_STATUS_INTERFACE_DOWN (0x40010010L) +-#define RNDIS_STATUS_MEDIA_BUSY (0x40010011L) +-#define RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION (0x40010012L) +-#define RNDIS_STATUS_WW_INDICATION RDIA_SPECIFIC_INDICATION +-#define RNDIS_STATUS_LINK_SPEED_CHANGE (0x40010013L) +- +-#define RNDIS_STATUS_NOT_RESETTABLE (0x80010001L) +-#define RNDIS_STATUS_SOFT_ERRORS (0x80010003L) +-#define RNDIS_STATUS_HARD_ERRORS (0x80010004L) +-#define RNDIS_STATUS_BUFFER_OVERFLOW (STATUS_BUFFER_OVERFLOW) +- +-#define RNDIS_STATUS_FAILURE (STATUS_UNSUCCESSFUL) +-#define RNDIS_STATUS_RESOURCES (STATUS_INSUFFICIENT_RESOURCES) +-#define RNDIS_STATUS_CLOSING (0xC0010002L) +-#define RNDIS_STATUS_BAD_VERSION (0xC0010004L) +-#define RNDIS_STATUS_BAD_CHARACTERISTICS (0xC0010005L) +-#define RNDIS_STATUS_ADAPTER_NOT_FOUND (0xC0010006L) +-#define RNDIS_STATUS_OPEN_FAILED (0xC0010007L) +-#define RNDIS_STATUS_DEVICE_FAILED (0xC0010008L) +-#define RNDIS_STATUS_MULTICAST_FULL (0xC0010009L) +-#define RNDIS_STATUS_MULTICAST_EXISTS (0xC001000AL) +-#define RNDIS_STATUS_MULTICAST_NOT_FOUND (0xC001000BL) +-#define RNDIS_STATUS_REQUEST_ABORTED (0xC001000CL) +-#define RNDIS_STATUS_RESET_IN_PROGRESS (0xC001000DL) +-#define RNDIS_STATUS_CLOSING_INDICATING (0xC001000EL) +-#define RNDIS_STATUS_NOT_SUPPORTED (STATUS_NOT_SUPPORTED) +-#define RNDIS_STATUS_INVALID_PACKET (0xC001000FL) +-#define RNDIS_STATUS_OPEN_LIST_FULL (0xC0010010L) +-#define RNDIS_STATUS_ADAPTER_NOT_READY (0xC0010011L) +-#define RNDIS_STATUS_ADAPTER_NOT_OPEN (0xC0010012L) +-#define RNDIS_STATUS_NOT_INDICATING (0xC0010013L) +-#define RNDIS_STATUS_INVALID_LENGTH (0xC0010014L) +-#define RNDIS_STATUS_INVALID_DATA (0xC0010015L) +-#define RNDIS_STATUS_BUFFER_TOO_SHORT (0xC0010016L) +-#define RNDIS_STATUS_INVALID_OID (0xC0010017L) +-#define RNDIS_STATUS_ADAPTER_REMOVED (0xC0010018L) +-#define RNDIS_STATUS_UNSUPPORTED_MEDIA (0xC0010019L) +-#define RNDIS_STATUS_GROUP_ADDRESS_IN_USE (0xC001001AL) +-#define RNDIS_STATUS_FILE_NOT_FOUND (0xC001001BL) +-#define RNDIS_STATUS_ERROR_READING_FILE (0xC001001CL) +-#define RNDIS_STATUS_ALREADY_MAPPED (0xC001001DL) +-#define RNDIS_STATUS_RESOURCE_CONFLICT (0xC001001EL) +-#define RNDIS_STATUS_NO_CABLE (0xC001001FL) +- +-#define RNDIS_STATUS_INVALID_SAP (0xC0010020L) +-#define RNDIS_STATUS_SAP_IN_USE (0xC0010021L) +-#define RNDIS_STATUS_INVALID_ADDRESS (0xC0010022L) +-#define RNDIS_STATUS_VC_NOT_ACTIVATED (0xC0010023L) +-#define RNDIS_STATUS_DEST_OUT_OF_ORDER (0xC0010024L) +-#define RNDIS_STATUS_VC_NOT_AVAILABLE (0xC0010025L) +-#define RNDIS_STATUS_CELLRATE_NOT_AVAILABLE (0xC0010026L) +-#define RNDIS_STATUS_INCOMPATABLE_QOS (0xC0010027L) +-#define RNDIS_STATUS_AAL_PARAMS_UNSUPPORTED (0xC0010028L) +-#define RNDIS_STATUS_NO_ROUTE_TO_DESTINATION (0xC0010029L) +- +-#define RNDIS_STATUS_TOKEN_RING_OPEN_ERROR (0xC0011000L) +- +-/* Object Identifiers used by NdisRequest Query/Set Information */ +-/* General Objects */ +-#define RNDIS_OID_GEN_SUPPORTED_LIST 0x00010101 +-#define RNDIS_OID_GEN_HARDWARE_STATUS 0x00010102 +-#define RNDIS_OID_GEN_MEDIA_SUPPORTED 0x00010103 +-#define RNDIS_OID_GEN_MEDIA_IN_USE 0x00010104 +-#define RNDIS_OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +-#define RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +-#define RNDIS_OID_GEN_LINK_SPEED 0x00010107 +-#define RNDIS_OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +-#define RNDIS_OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +-#define RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +-#define RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +-#define RNDIS_OID_GEN_VENDOR_ID 0x0001010C +-#define RNDIS_OID_GEN_VENDOR_DESCRIPTION 0x0001010D +-#define RNDIS_OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +-#define RNDIS_OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +-#define RNDIS_OID_GEN_DRIVER_VERSION 0x00010110 +-#define RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +-#define RNDIS_OID_GEN_PROTOCOL_OPTIONS 0x00010112 +-#define RNDIS_OID_GEN_MAC_OPTIONS 0x00010113 +-#define RNDIS_OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +-#define RNDIS_OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +-#define RNDIS_OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 +-#define RNDIS_OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 +-#define RNDIS_OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 +-#define RNDIS_OID_GEN_MACHINE_NAME 0x0001021A +-#define RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B +- +-#define RNDIS_OID_GEN_XMIT_OK 0x00020101 +-#define RNDIS_OID_GEN_RCV_OK 0x00020102 +-#define RNDIS_OID_GEN_XMIT_ERROR 0x00020103 +-#define RNDIS_OID_GEN_RCV_ERROR 0x00020104 +-#define RNDIS_OID_GEN_RCV_NO_BUFFER 0x00020105 +- +-#define RNDIS_OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +-#define RNDIS_OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +-#define RNDIS_OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +-#define RNDIS_OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +-#define RNDIS_OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +-#define RNDIS_OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +-#define RNDIS_OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +-#define RNDIS_OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +-#define RNDIS_OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +-#define RNDIS_OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +-#define RNDIS_OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +-#define RNDIS_OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +- +-#define RNDIS_OID_GEN_RCV_CRC_ERROR 0x0002020D +-#define RNDIS_OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E +- +-#define RNDIS_OID_GEN_GET_TIME_CAPS 0x0002020F +-#define RNDIS_OID_GEN_GET_NETCARD_TIME 0x00020210 +- +-/* These are connection-oriented general OIDs. */ +-/* These replace the above OIDs for connection-oriented media. */ +-#define RNDIS_OID_GEN_CO_SUPPORTED_LIST 0x00010101 +-#define RNDIS_OID_GEN_CO_HARDWARE_STATUS 0x00010102 +-#define RNDIS_OID_GEN_CO_MEDIA_SUPPORTED 0x00010103 +-#define RNDIS_OID_GEN_CO_MEDIA_IN_USE 0x00010104 +-#define RNDIS_OID_GEN_CO_LINK_SPEED 0x00010105 +-#define RNDIS_OID_GEN_CO_VENDOR_ID 0x00010106 +-#define RNDIS_OID_GEN_CO_VENDOR_DESCRIPTION 0x00010107 +-#define RNDIS_OID_GEN_CO_DRIVER_VERSION 0x00010108 +-#define RNDIS_OID_GEN_CO_PROTOCOL_OPTIONS 0x00010109 +-#define RNDIS_OID_GEN_CO_MAC_OPTIONS 0x0001010A +-#define RNDIS_OID_GEN_CO_MEDIA_CONNECT_STATUS 0x0001010B +-#define RNDIS_OID_GEN_CO_VENDOR_DRIVER_VERSION 0x0001010C +-#define RNDIS_OID_GEN_CO_MINIMUM_LINK_SPEED 0x0001010D +- +-#define RNDIS_OID_GEN_CO_GET_TIME_CAPS 0x00010201 +-#define RNDIS_OID_GEN_CO_GET_NETCARD_TIME 0x00010202 +- +-/* These are connection-oriented statistics OIDs. */ +-#define RNDIS_OID_GEN_CO_XMIT_PDUS_OK 0x00020101 +-#define RNDIS_OID_GEN_CO_RCV_PDUS_OK 0x00020102 +-#define RNDIS_OID_GEN_CO_XMIT_PDUS_ERROR 0x00020103 +-#define RNDIS_OID_GEN_CO_RCV_PDUS_ERROR 0x00020104 +-#define RNDIS_OID_GEN_CO_RCV_PDUS_NO_BUFFER 0x00020105 +- +- +-#define RNDIS_OID_GEN_CO_RCV_CRC_ERROR 0x00020201 +-#define RNDIS_OID_GEN_CO_TRANSMIT_QUEUE_LENGTH 0x00020202 +-#define RNDIS_OID_GEN_CO_BYTES_XMIT 0x00020203 +-#define RNDIS_OID_GEN_CO_BYTES_RCV 0x00020204 +-#define RNDIS_OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020205 +-#define RNDIS_OID_GEN_CO_NETCARD_LOAD 0x00020206 +- +-/* These are objects for Connection-oriented media call-managers. */ +-#define RNDIS_OID_CO_ADD_PVC 0xFF000001 +-#define RNDIS_OID_CO_DELETE_PVC 0xFF000002 +-#define RNDIS_OID_CO_GET_CALL_INFORMATION 0xFF000003 +-#define RNDIS_OID_CO_ADD_ADDRESS 0xFF000004 +-#define RNDIS_OID_CO_DELETE_ADDRESS 0xFF000005 +-#define RNDIS_OID_CO_GET_ADDRESSES 0xFF000006 +-#define RNDIS_OID_CO_ADDRESS_CHANGE 0xFF000007 +-#define RNDIS_OID_CO_SIGNALING_ENABLED 0xFF000008 +-#define RNDIS_OID_CO_SIGNALING_DISABLED 0xFF000009 +- +-/* 802.3 Objects (Ethernet) */ +-#define RNDIS_OID_802_3_PERMANENT_ADDRESS 0x01010101 +-#define RNDIS_OID_802_3_CURRENT_ADDRESS 0x01010102 +-#define RNDIS_OID_802_3_MULTICAST_LIST 0x01010103 +-#define RNDIS_OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 +-#define RNDIS_OID_802_3_MAC_OPTIONS 0x01010105 +- +-#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 +- +-#define RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +-#define RNDIS_OID_802_3_XMIT_ONE_COLLISION 0x01020102 +-#define RNDIS_OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +- +-#define RNDIS_OID_802_3_XMIT_DEFERRED 0x01020201 +-#define RNDIS_OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +-#define RNDIS_OID_802_3_RCV_OVERRUN 0x01020203 +-#define RNDIS_OID_802_3_XMIT_UNDERRUN 0x01020204 +-#define RNDIS_OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +-#define RNDIS_OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +-#define RNDIS_OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 +- +-/* Remote NDIS message types */ +-#define REMOTE_NDIS_PACKET_MSG 0x00000001 +-#define REMOTE_NDIS_INITIALIZE_MSG 0x00000002 +-#define REMOTE_NDIS_HALT_MSG 0x00000003 +-#define REMOTE_NDIS_QUERY_MSG 0x00000004 +-#define REMOTE_NDIS_SET_MSG 0x00000005 +-#define REMOTE_NDIS_RESET_MSG 0x00000006 +-#define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007 +-#define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008 +- +-#define REMOTE_CONDIS_MP_CREATE_VC_MSG 0x00008001 +-#define REMOTE_CONDIS_MP_DELETE_VC_MSG 0x00008002 +-#define REMOTE_CONDIS_MP_ACTIVATE_VC_MSG 0x00008005 +-#define REMOTE_CONDIS_MP_DEACTIVATE_VC_MSG 0x00008006 +-#define REMOTE_CONDIS_INDICATE_STATUS_MSG 0x00008007 +- +-/* Remote NDIS message completion types */ +-#define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002 +-#define REMOTE_NDIS_QUERY_CMPLT 0x80000004 +-#define REMOTE_NDIS_SET_CMPLT 0x80000005 +-#define REMOTE_NDIS_RESET_CMPLT 0x80000006 +-#define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008 +- +-#define REMOTE_CONDIS_MP_CREATE_VC_CMPLT 0x80008001 +-#define REMOTE_CONDIS_MP_DELETE_VC_CMPLT 0x80008002 +-#define REMOTE_CONDIS_MP_ACTIVATE_VC_CMPLT 0x80008005 +-#define REMOTE_CONDIS_MP_DEACTIVATE_VC_CMPLT 0x80008006 +- +-/* +- * Reserved message type for private communication between lower-layer host +- * driver and remote device, if necessary. +- */ +-#define REMOTE_NDIS_BUS_MSG 0xff000001 +- +-/* Defines for DeviceFlags in struct rndis_initialize_complete */ +-#define RNDIS_DF_CONNECTIONLESS 0x00000001 +-#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002 +-#define RNDIS_DF_RAW_DATA 0x00000004 +- +-/* Remote NDIS medium types. */ +-#define RNDIS_MEDIUM_802_3 0x00000000 +-#define RNDIS_MEDIUM_802_5 0x00000001 +-#define RNDIS_MEDIUM_FDDI 0x00000002 +-#define RNDIS_MEDIUM_WAN 0x00000003 +-#define RNDIS_MEDIUM_LOCAL_TALK 0x00000004 +-#define RNDIS_MEDIUM_ARCNET_RAW 0x00000006 +-#define RNDIS_MEDIUM_ARCNET_878_2 0x00000007 +-#define RNDIS_MEDIUM_ATM 0x00000008 +-#define RNDIS_MEDIUM_WIRELESS_WAN 0x00000009 +-#define RNDIS_MEDIUM_IRDA 0x0000000a +-#define RNDIS_MEDIUM_CO_WAN 0x0000000b +-/* Not a real medium, defined as an upper-bound */ +-#define RNDIS_MEDIUM_MAX 0x0000000d +- +- +-/* Remote NDIS medium connection states. */ +-#define RNDIS_MEDIA_STATE_CONNECTED 0x00000000 +-#define RNDIS_MEDIA_STATE_DISCONNECTED 0x00000001 +- +-/* Remote NDIS version numbers */ +-#define RNDIS_MAJOR_VERSION 0x00000001 +-#define RNDIS_MINOR_VERSION 0x00000000 +- +- +-/* NdisInitialize message */ +-struct rndis_initialize_request { +- u32 req_id; +- u32 major_ver; +- u32 minor_ver; +- u32 max_xfer_size; +-}; +- +-/* Response to NdisInitialize */ +-struct rndis_initialize_complete { +- u32 req_id; +- u32 status; +- u32 major_ver; +- u32 minor_ver; +- u32 dev_flags; +- u32 medium; +- u32 max_pkt_per_msg; +- u32 max_xfer_size; +- u32 pkt_alignment_factor; +- u32 af_list_offset; +- u32 af_list_size; +-}; +- +-/* Call manager devices only: Information about an address family */ +-/* supported by the device is appended to the response to NdisInitialize. */ +-struct rndis_co_address_family { +- u32 address_family; +- u32 major_ver; +- u32 minor_ver; +-}; +- +-/* NdisHalt message */ +-struct rndis_halt_request { +- u32 req_id; +-}; +- +-/* NdisQueryRequest message */ +-struct rndis_query_request { +- u32 req_id; +- u32 oid; +- u32 info_buflen; +- u32 info_buf_offset; +- u32 dev_vc_handle; +-}; +- +-/* Response to NdisQueryRequest */ +-struct rndis_query_complete { +- u32 req_id; +- u32 status; +- u32 info_buflen; +- u32 info_buf_offset; +-}; +- +-/* NdisSetRequest message */ +-struct rndis_set_request { +- u32 req_id; +- u32 oid; +- u32 info_buflen; +- u32 info_buf_offset; +- u32 dev_vc_handle; +-}; +- +-/* Response to NdisSetRequest */ +-struct rndis_set_complete { +- u32 req_id; +- u32 status; +-}; +- +-/* NdisReset message */ +-struct rndis_reset_request { +- u32 reserved; +-}; +- +-/* Response to NdisReset */ +-struct rndis_reset_complete { +- u32 status; +- u32 addressing_reset; +-}; +- +-/* NdisMIndicateStatus message */ +-struct rndis_indicate_status { +- u32 status; +- u32 status_buflen; +- u32 status_buf_offset; +-}; +- +-/* Diagnostic information passed as the status buffer in */ +-/* struct rndis_indicate_status messages signifying error conditions. */ +-struct rndis_diagnostic_info { +- u32 diag_status; +- u32 error_offset; +-}; +- +-/* NdisKeepAlive message */ +-struct rndis_keepalive_request { +- u32 req_id; +-}; +- +-/* Response to NdisKeepAlive */ +-struct rndis_keepalive_complete { +- u32 req_id; +- u32 status; +-}; +- +-/* +- * Data message. All Offset fields contain byte offsets from the beginning of +- * struct rndis_packet. All Length fields are in bytes. VcHandle is set +- * to 0 for connectionless data, otherwise it contains the VC handle. +- */ +-struct rndis_packet { +- u32 data_offset; +- u32 data_len; +- u32 oob_data_offset; +- u32 oob_data_len; +- u32 num_oob_data_elements; +- u32 per_pkt_info_offset; +- u32 per_pkt_info_len; +- u32 vc_handle; +- u32 reserved; +-}; +- +-/* Optional Out of Band data associated with a Data message. */ +-struct rndis_oobd { +- u32 size; +- u32 type; +- u32 class_info_offset; +-}; +- +-/* Packet extension field contents associated with a Data message. */ +-struct rndis_per_packet_info { +- u32 size; +- u32 type; +- u32 per_pkt_info_offset; +-}; +- +-/* Format of Information buffer passed in a SetRequest for the OID */ +-/* OID_GEN_RNDIS_CONFIG_PARAMETER. */ +-struct rndis_config_parameter_info { +- u32 parameter_name_offset; +- u32 parameter_name_length; +- u32 parameter_type; +- u32 parameter_value_offset; +- u32 parameter_value_length; +-}; +- +-/* Values for ParameterType in struct rndis_config_parameter_info */ +-#define RNDIS_CONFIG_PARAM_TYPE_INTEGER 0 +-#define RNDIS_CONFIG_PARAM_TYPE_STRING 2 +- +-/* CONDIS Miniport messages for connection oriented devices */ +-/* that do not implement a call manager. */ +- +-/* CoNdisMiniportCreateVc message */ +-struct rcondis_mp_create_vc { +- u32 req_id; +- u32 ndis_vc_handle; +-}; +- +-/* Response to CoNdisMiniportCreateVc */ +-struct rcondis_mp_create_vc_complete { +- u32 req_id; +- u32 dev_vc_handle; +- u32 status; +-}; +- +-/* CoNdisMiniportDeleteVc message */ +-struct rcondis_mp_delete_vc { +- u32 req_id; +- u32 dev_vc_handle; +-}; +- +-/* Response to CoNdisMiniportDeleteVc */ +-struct rcondis_mp_delete_vc_complete { +- u32 req_id; +- u32 status; +-}; +- +-/* CoNdisMiniportQueryRequest message */ +-struct rcondis_mp_query_request { +- u32 req_id; +- u32 request_type; +- u32 oid; +- u32 dev_vc_handle; +- u32 info_buflen; +- u32 info_buf_offset; +-}; +- +-/* CoNdisMiniportSetRequest message */ +-struct rcondis_mp_set_request { +- u32 req_id; +- u32 request_type; +- u32 oid; +- u32 dev_vc_handle; +- u32 info_buflen; +- u32 info_buf_offset; +-}; +- +-/* CoNdisIndicateStatus message */ +-struct rcondis_indicate_status { +- u32 ndis_vc_handle; +- u32 status; +- u32 status_buflen; +- u32 status_buf_offset; +-}; +- +-/* CONDIS Call/VC parameters */ +-struct rcondis_specific_parameters { +- u32 parameter_type; +- u32 parameter_length; +- u32 parameter_lffset; +-}; +- +-struct rcondis_media_parameters { +- u32 flags; +- u32 reserved1; +- u32 reserved2; +- struct rcondis_specific_parameters media_specific; +-}; +- +-struct rndis_flowspec { +- u32 token_rate; +- u32 token_bucket_size; +- u32 peak_bandwidth; +- u32 latency; +- u32 delay_variation; +- u32 service_type; +- u32 max_sdu_size; +- u32 minimum_policed_size; +-}; +- +-struct rcondis_call_manager_parameters { +- struct rndis_flowspec transmit; +- struct rndis_flowspec receive; +- struct rcondis_specific_parameters call_mgr_specific; +-}; +- +-/* CoNdisMiniportActivateVc message */ +-struct rcondis_mp_activate_vc_request { +- u32 req_id; +- u32 flags; +- u32 dev_vc_handle; +- u32 media_params_offset; +- u32 media_params_length; +- u32 call_mgr_params_offset; +- u32 call_mgr_params_length; +-}; +- +-/* Response to CoNdisMiniportActivateVc */ +-struct rcondis_mp_activate_vc_complete { +- u32 req_id; +- u32 status; +-}; +- +-/* CoNdisMiniportDeactivateVc message */ +-struct rcondis_mp_deactivate_vc_request { +- u32 req_id; +- u32 flags; +- u32 dev_vc_handle; +-}; +- +-/* Response to CoNdisMiniportDeactivateVc */ +-struct rcondis_mp_deactivate_vc_complete { +- u32 req_id; +- u32 status; +-}; +- +- +-/* union with all of the RNDIS messages */ +-union rndis_message_container { +- struct rndis_packet pkt; +- struct rndis_initialize_request init_req; +- struct rndis_halt_request halt_req; +- struct rndis_query_request query_req; +- struct rndis_set_request set_req; +- struct rndis_reset_request reset_req; +- struct rndis_keepalive_request keep_alive_req; +- struct rndis_indicate_status indicate_status; +- struct rndis_initialize_complete init_complete; +- struct rndis_query_complete query_complete; +- struct rndis_set_complete set_complete; +- struct rndis_reset_complete reset_complete; +- struct rndis_keepalive_complete keep_alive_complete; +- struct rcondis_mp_create_vc co_miniport_create_vc; +- struct rcondis_mp_delete_vc co_miniport_delete_vc; +- struct rcondis_indicate_status co_indicate_status; +- struct rcondis_mp_activate_vc_request co_miniport_activate_vc; +- struct rcondis_mp_deactivate_vc_request co_miniport_deactivate_vc; +- struct rcondis_mp_create_vc_complete co_miniport_create_vc_complete; +- struct rcondis_mp_delete_vc_complete co_miniport_delete_vc_complete; +- struct rcondis_mp_activate_vc_complete co_miniport_activate_vc_complete; +- struct rcondis_mp_deactivate_vc_complete +- co_miniport_deactivate_vc_complete; +-}; +- +-/* Remote NDIS message format */ +-struct rndis_message { +- u32 ndis_msg_type; +- +- /* Total length of this message, from the beginning */ +- /* of the sruct rndis_message, in bytes. */ +- u32 msg_len; +- +- /* Actual message */ +- union rndis_message_container msg; +-}; +- +- +-struct rndis_filter_packet { +- void *completion_ctx; +- void (*completion)(void *context); +- struct rndis_message msg; +-}; +- +-/* Handy macros */ +- +-/* get the size of an RNDIS message. Pass in the message type, */ +-/* struct rndis_set_request, struct rndis_packet for example */ +-#define RNDIS_MESSAGE_SIZE(msg) \ +- (sizeof(msg) + (sizeof(struct rndis_message) - \ +- sizeof(union rndis_message_container))) +- +-/* get pointer to info buffer with message pointer */ +-#define MESSAGE_TO_INFO_BUFFER(msg) \ +- (((unsigned char *)(msg)) + msg->info_buf_offset) +- +-/* get pointer to status buffer with message pointer */ +-#define MESSAGE_TO_STATUS_BUFFER(msg) \ +- (((unsigned char *)(msg)) + msg->status_buf_offset) +- +-/* get pointer to OOBD buffer with message pointer */ +-#define MESSAGE_TO_OOBD_BUFFER(msg) \ +- (((unsigned char *)(msg)) + msg->oob_data_offset) +- +-/* get pointer to data buffer with message pointer */ +-#define MESSAGE_TO_DATA_BUFFER(msg) \ +- (((unsigned char *)(msg)) + msg->per_pkt_info_offset) +- +-/* get pointer to contained message from NDIS_MESSAGE pointer */ +-#define RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(rndis_msg) \ +- ((void *) &rndis_msg->msg) +- +-/* get pointer to contained message from NDIS_MESSAGE pointer */ +-#define RNDIS_MESSAGE_RAW_PTR_TO_MESSAGE_PTR(rndis_msg) \ +- ((void *) rndis_msg) +- +- +-#define __struct_bcount(x) +- +- +- +-#define RNDIS_HEADER_SIZE (sizeof(struct rndis_message) - \ +- sizeof(union rndis_message_container)) +- +-#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 +-#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 +-#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 +-#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 +-#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 +-#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 +-#define NDIS_PACKET_TYPE_SMT 0x00000040 +-#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 +-#define NDIS_PACKET_TYPE_GROUP 0x00000100 +-#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200 +-#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400 +-#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800 +- +- +- +-#endif /* _HYPERV_NET_H */ +diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c +deleted file mode 100644 +index b902579..0000000 +--- a/drivers/staging/hv/netvsc.c ++++ /dev/null +@@ -1,944 +0,0 @@ +-/* +- * Copyright (c) 2009, Microsoft Corporation. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple +- * Place - Suite 330, Boston, MA 02111-1307 USA. +- * +- * Authors: +- * Haiyang Zhang +- * Hank Janssen +- */ +-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "hyperv_net.h" +- +- +-static struct netvsc_device *alloc_net_device(struct hv_device *device) +-{ +- struct netvsc_device *net_device; +- struct net_device *ndev = hv_get_drvdata(device); +- +- net_device = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL); +- if (!net_device) +- return NULL; +- +- +- net_device->destroy = false; +- net_device->dev = device; +- net_device->ndev = ndev; +- +- hv_set_drvdata(device, net_device); +- return net_device; +-} +- +-static struct netvsc_device *get_outbound_net_device(struct hv_device *device) +-{ +- struct netvsc_device *net_device; +- +- net_device = hv_get_drvdata(device); +- if (net_device && net_device->destroy) +- net_device = NULL; +- +- return net_device; +-} +- +-static struct netvsc_device *get_inbound_net_device(struct hv_device *device) +-{ +- struct netvsc_device *net_device; +- +- net_device = hv_get_drvdata(device); +- +- if (!net_device) +- goto get_in_err; +- +- if (net_device->destroy && +- atomic_read(&net_device->num_outstanding_sends) == 0) +- net_device = NULL; +- +-get_in_err: +- return net_device; +-} +- +- +-static int netvsc_destroy_recv_buf(struct netvsc_device *net_device) +-{ +- struct nvsp_message *revoke_packet; +- int ret = 0; +- struct net_device *ndev = net_device->ndev; +- +- /* +- * If we got a section count, it means we received a +- * SendReceiveBufferComplete msg (ie sent +- * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need +- * to send a revoke msg here +- */ +- if (net_device->recv_section_cnt) { +- /* Send the revoke receive buffer */ +- revoke_packet = &net_device->revoke_packet; +- memset(revoke_packet, 0, sizeof(struct nvsp_message)); +- +- revoke_packet->hdr.msg_type = +- NVSP_MSG1_TYPE_REVOKE_RECV_BUF; +- revoke_packet->msg.v1_msg. +- revoke_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID; +- +- ret = vmbus_sendpacket(net_device->dev->channel, +- revoke_packet, +- sizeof(struct nvsp_message), +- (unsigned long)revoke_packet, +- VM_PKT_DATA_INBAND, 0); +- /* +- * If we failed here, we might as well return and +- * have a leak rather than continue and a bugchk +- */ +- if (ret != 0) { +- netdev_err(ndev, "unable to send " +- "revoke receive buffer to netvsp\n"); +- return ret; +- } +- } +- +- /* Teardown the gpadl on the vsp end */ +- if (net_device->recv_buf_gpadl_handle) { +- ret = vmbus_teardown_gpadl(net_device->dev->channel, +- net_device->recv_buf_gpadl_handle); +- +- /* If we failed here, we might as well return and have a leak +- * rather than continue and a bugchk +- */ +- if (ret != 0) { +- netdev_err(ndev, +- "unable to teardown receive buffer's gpadl\n"); +- return ret; +- } +- net_device->recv_buf_gpadl_handle = 0; +- } +- +- if (net_device->recv_buf) { +- /* Free up the receive buffer */ +- free_pages((unsigned long)net_device->recv_buf, +- get_order(net_device->recv_buf_size)); +- net_device->recv_buf = NULL; +- } +- +- if (net_device->recv_section) { +- net_device->recv_section_cnt = 0; +- kfree(net_device->recv_section); +- net_device->recv_section = NULL; +- } +- +- return ret; +-} +- +-static int netvsc_init_recv_buf(struct hv_device *device) +-{ +- int ret = 0; +- int t; +- struct netvsc_device *net_device; +- struct nvsp_message *init_packet; +- struct net_device *ndev; +- +- net_device = get_outbound_net_device(device); +- if (!net_device) +- return -ENODEV; +- ndev = net_device->ndev; +- +- net_device->recv_buf = +- (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, +- get_order(net_device->recv_buf_size)); +- if (!net_device->recv_buf) { +- netdev_err(ndev, "unable to allocate receive " +- "buffer of size %d\n", net_device->recv_buf_size); +- ret = -ENOMEM; +- goto cleanup; +- } +- +- /* +- * Establish the gpadl handle for this buffer on this +- * channel. Note: This call uses the vmbus connection rather +- * than the channel to establish the gpadl handle. +- */ +- ret = vmbus_establish_gpadl(device->channel, net_device->recv_buf, +- net_device->recv_buf_size, +- &net_device->recv_buf_gpadl_handle); +- if (ret != 0) { +- netdev_err(ndev, +- "unable to establish receive buffer's gpadl\n"); +- goto cleanup; +- } +- +- +- /* Notify the NetVsp of the gpadl handle */ +- init_packet = &net_device->channel_init_pkt; +- +- memset(init_packet, 0, sizeof(struct nvsp_message)); +- +- init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF; +- init_packet->msg.v1_msg.send_recv_buf. +- gpadl_handle = net_device->recv_buf_gpadl_handle; +- init_packet->msg.v1_msg. +- send_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID; +- +- /* Send the gpadl notification request */ +- ret = vmbus_sendpacket(device->channel, init_packet, +- sizeof(struct nvsp_message), +- (unsigned long)init_packet, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); +- if (ret != 0) { +- netdev_err(ndev, +- "unable to send receive buffer's gpadl to netvsp\n"); +- goto cleanup; +- } +- +- t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ); +- BUG_ON(t == 0); +- +- +- /* Check the response */ +- if (init_packet->msg.v1_msg. +- send_recv_buf_complete.status != NVSP_STAT_SUCCESS) { +- netdev_err(ndev, "Unable to complete receive buffer " +- "initialization with NetVsp - status %d\n", +- init_packet->msg.v1_msg. +- send_recv_buf_complete.status); +- ret = -EINVAL; +- goto cleanup; +- } +- +- /* Parse the response */ +- +- net_device->recv_section_cnt = init_packet->msg. +- v1_msg.send_recv_buf_complete.num_sections; +- +- net_device->recv_section = kmalloc(net_device->recv_section_cnt +- * sizeof(struct nvsp_1_receive_buffer_section), GFP_KERNEL); +- if (net_device->recv_section == NULL) { +- ret = -EINVAL; +- goto cleanup; +- } +- +- memcpy(net_device->recv_section, +- init_packet->msg.v1_msg. +- send_recv_buf_complete.sections, +- net_device->recv_section_cnt * +- sizeof(struct nvsp_1_receive_buffer_section)); +- +- /* +- * For 1st release, there should only be 1 section that represents the +- * entire receive buffer +- */ +- if (net_device->recv_section_cnt != 1 || +- net_device->recv_section->offset != 0) { +- ret = -EINVAL; +- goto cleanup; +- } +- +- goto exit; +- +-cleanup: +- netvsc_destroy_recv_buf(net_device); +- +-exit: +- return ret; +-} +- +- +-static int netvsc_connect_vsp(struct hv_device *device) +-{ +- int ret, t; +- struct netvsc_device *net_device; +- struct nvsp_message *init_packet; +- int ndis_version; +- struct net_device *ndev; +- +- net_device = get_outbound_net_device(device); +- if (!net_device) +- return -ENODEV; +- ndev = net_device->ndev; +- +- init_packet = &net_device->channel_init_pkt; +- +- memset(init_packet, 0, sizeof(struct nvsp_message)); +- init_packet->hdr.msg_type = NVSP_MSG_TYPE_INIT; +- init_packet->msg.init_msg.init.min_protocol_ver = +- NVSP_MIN_PROTOCOL_VERSION; +- init_packet->msg.init_msg.init.max_protocol_ver = +- NVSP_MAX_PROTOCOL_VERSION; +- +- /* Send the init request */ +- ret = vmbus_sendpacket(device->channel, init_packet, +- sizeof(struct nvsp_message), +- (unsigned long)init_packet, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); +- +- if (ret != 0) +- goto cleanup; +- +- t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ); +- +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- if (init_packet->msg.init_msg.init_complete.status != +- NVSP_STAT_SUCCESS) { +- ret = -EINVAL; +- goto cleanup; +- } +- +- if (init_packet->msg.init_msg.init_complete. +- negotiated_protocol_ver != NVSP_PROTOCOL_VERSION_1) { +- ret = -EPROTO; +- goto cleanup; +- } +- /* Send the ndis version */ +- memset(init_packet, 0, sizeof(struct nvsp_message)); +- +- ndis_version = 0x00050000; +- +- init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER; +- init_packet->msg.v1_msg. +- send_ndis_ver.ndis_major_ver = +- (ndis_version & 0xFFFF0000) >> 16; +- init_packet->msg.v1_msg. +- send_ndis_ver.ndis_minor_ver = +- ndis_version & 0xFFFF; +- +- /* Send the init request */ +- ret = vmbus_sendpacket(device->channel, init_packet, +- sizeof(struct nvsp_message), +- (unsigned long)init_packet, +- VM_PKT_DATA_INBAND, 0); +- if (ret != 0) +- goto cleanup; +- +- /* Post the big receive buffer to NetVSP */ +- ret = netvsc_init_recv_buf(device); +- +-cleanup: +- return ret; +-} +- +-static void netvsc_disconnect_vsp(struct netvsc_device *net_device) +-{ +- netvsc_destroy_recv_buf(net_device); +-} +- +-/* +- * netvsc_device_remove - Callback when the root bus device is removed +- */ +-int netvsc_device_remove(struct hv_device *device) +-{ +- struct netvsc_device *net_device; +- struct hv_netvsc_packet *netvsc_packet, *pos; +- unsigned long flags; +- +- net_device = hv_get_drvdata(device); +- spin_lock_irqsave(&device->channel->inbound_lock, flags); +- net_device->destroy = true; +- spin_unlock_irqrestore(&device->channel->inbound_lock, flags); +- +- /* Wait for all send completions */ +- while (atomic_read(&net_device->num_outstanding_sends)) { +- dev_info(&device->device, +- "waiting for %d requests to complete...\n", +- atomic_read(&net_device->num_outstanding_sends)); +- udelay(100); +- } +- +- netvsc_disconnect_vsp(net_device); +- +- /* +- * Since we have already drained, we don't need to busy wait +- * as was done in final_release_stor_device() +- * Note that we cannot set the ext pointer to NULL until +- * we have drained - to drain the outgoing packets, we need to +- * allow incoming packets. +- */ +- +- spin_lock_irqsave(&device->channel->inbound_lock, flags); +- hv_set_drvdata(device, NULL); +- spin_unlock_irqrestore(&device->channel->inbound_lock, flags); +- +- /* +- * At this point, no one should be accessing net_device +- * except in here +- */ +- dev_notice(&device->device, "net device safe to remove\n"); +- +- /* Now, we can close the channel safely */ +- vmbus_close(device->channel); +- +- /* Release all resources */ +- list_for_each_entry_safe(netvsc_packet, pos, +- &net_device->recv_pkt_list, list_ent) { +- list_del(&netvsc_packet->list_ent); +- kfree(netvsc_packet); +- } +- +- kfree(net_device); +- return 0; +-} +- +-static void netvsc_send_completion(struct hv_device *device, +- struct vmpacket_descriptor *packet) +-{ +- struct netvsc_device *net_device; +- struct nvsp_message *nvsp_packet; +- struct hv_netvsc_packet *nvsc_packet; +- struct net_device *ndev; +- +- net_device = get_inbound_net_device(device); +- if (!net_device) +- return; +- ndev = net_device->ndev; +- +- nvsp_packet = (struct nvsp_message *)((unsigned long)packet + +- (packet->offset8 << 3)); +- +- if ((nvsp_packet->hdr.msg_type == NVSP_MSG_TYPE_INIT_COMPLETE) || +- (nvsp_packet->hdr.msg_type == +- NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE) || +- (nvsp_packet->hdr.msg_type == +- NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE)) { +- /* Copy the response back */ +- memcpy(&net_device->channel_init_pkt, nvsp_packet, +- sizeof(struct nvsp_message)); +- complete(&net_device->channel_init_wait); +- } else if (nvsp_packet->hdr.msg_type == +- NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) { +- /* Get the send context */ +- nvsc_packet = (struct hv_netvsc_packet *)(unsigned long) +- packet->trans_id; +- +- /* Notify the layer above us */ +- nvsc_packet->completion.send.send_completion( +- nvsc_packet->completion.send.send_completion_ctx); +- +- atomic_dec(&net_device->num_outstanding_sends); +- } else { +- netdev_err(ndev, "Unknown send completion packet type- " +- "%d received!!\n", nvsp_packet->hdr.msg_type); +- } +- +-} +- +-int netvsc_send(struct hv_device *device, +- struct hv_netvsc_packet *packet) +-{ +- struct netvsc_device *net_device; +- int ret = 0; +- struct nvsp_message sendMessage; +- struct net_device *ndev; +- +- net_device = get_outbound_net_device(device); +- if (!net_device) +- return -ENODEV; +- ndev = net_device->ndev; +- +- sendMessage.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT; +- if (packet->is_data_pkt) { +- /* 0 is RMC_DATA; */ +- sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 0; +- } else { +- /* 1 is RMC_CONTROL; */ +- sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 1; +- } +- +- /* Not using send buffer section */ +- sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_index = +- 0xFFFFFFFF; +- sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = 0; +- +- if (packet->page_buf_cnt) { +- ret = vmbus_sendpacket_pagebuffer(device->channel, +- packet->page_buf, +- packet->page_buf_cnt, +- &sendMessage, +- sizeof(struct nvsp_message), +- (unsigned long)packet); +- } else { +- ret = vmbus_sendpacket(device->channel, &sendMessage, +- sizeof(struct nvsp_message), +- (unsigned long)packet, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); +- +- } +- +- if (ret != 0) +- netdev_err(ndev, "Unable to send packet %p ret %d\n", +- packet, ret); +- else +- atomic_inc(&net_device->num_outstanding_sends); +- +- return ret; +-} +- +-static void netvsc_send_recv_completion(struct hv_device *device, +- u64 transaction_id) +-{ +- struct nvsp_message recvcompMessage; +- int retries = 0; +- int ret; +- struct net_device *ndev; +- struct netvsc_device *net_device = hv_get_drvdata(device); +- +- ndev = net_device->ndev; +- +- recvcompMessage.hdr.msg_type = +- NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE; +- +- /* FIXME: Pass in the status */ +- recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status = +- NVSP_STAT_SUCCESS; +- +-retry_send_cmplt: +- /* Send the completion */ +- ret = vmbus_sendpacket(device->channel, &recvcompMessage, +- sizeof(struct nvsp_message), transaction_id, +- VM_PKT_COMP, 0); +- if (ret == 0) { +- /* success */ +- /* no-op */ +- } else if (ret == -EAGAIN) { +- /* no more room...wait a bit and attempt to retry 3 times */ +- retries++; +- netdev_err(ndev, "unable to send receive completion pkt" +- " (tid %llx)...retrying %d\n", transaction_id, retries); +- +- if (retries < 4) { +- udelay(100); +- goto retry_send_cmplt; +- } else { +- netdev_err(ndev, "unable to send receive " +- "completion pkt (tid %llx)...give up retrying\n", +- transaction_id); +- } +- } else { +- netdev_err(ndev, "unable to send receive " +- "completion pkt - %llx\n", transaction_id); +- } +-} +- +-/* Send a receive completion packet to RNDIS device (ie NetVsp) */ +-static void netvsc_receive_completion(void *context) +-{ +- struct hv_netvsc_packet *packet = context; +- struct hv_device *device = (struct hv_device *)packet->device; +- struct netvsc_device *net_device; +- u64 transaction_id = 0; +- bool fsend_receive_comp = false; +- unsigned long flags; +- struct net_device *ndev; +- +- /* +- * Even though it seems logical to do a GetOutboundNetDevice() here to +- * send out receive completion, we are using GetInboundNetDevice() +- * since we may have disable outbound traffic already. +- */ +- net_device = get_inbound_net_device(device); +- if (!net_device) +- return; +- ndev = net_device->ndev; +- +- /* Overloading use of the lock. */ +- spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags); +- +- packet->xfer_page_pkt->count--; +- +- /* +- * Last one in the line that represent 1 xfer page packet. +- * Return the xfer page packet itself to the freelist +- */ +- if (packet->xfer_page_pkt->count == 0) { +- fsend_receive_comp = true; +- transaction_id = packet->completion.recv.recv_completion_tid; +- list_add_tail(&packet->xfer_page_pkt->list_ent, +- &net_device->recv_pkt_list); +- +- } +- +- /* Put the packet back */ +- list_add_tail(&packet->list_ent, &net_device->recv_pkt_list); +- spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags); +- +- /* Send a receive completion for the xfer page packet */ +- if (fsend_receive_comp) +- netvsc_send_recv_completion(device, transaction_id); +- +-} +- +-static void netvsc_receive(struct hv_device *device, +- struct vmpacket_descriptor *packet) +-{ +- struct netvsc_device *net_device; +- struct vmtransfer_page_packet_header *vmxferpage_packet; +- struct nvsp_message *nvsp_packet; +- struct hv_netvsc_packet *netvsc_packet = NULL; +- unsigned long start; +- unsigned long end, end_virtual; +- /* struct netvsc_driver *netvscDriver; */ +- struct xferpage_packet *xferpage_packet = NULL; +- int i, j; +- int count = 0, bytes_remain = 0; +- unsigned long flags; +- struct net_device *ndev; +- +- LIST_HEAD(listHead); +- +- net_device = get_inbound_net_device(device); +- if (!net_device) +- return; +- ndev = net_device->ndev; +- +- /* +- * All inbound packets other than send completion should be xfer page +- * packet +- */ +- if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) { +- netdev_err(ndev, "Unknown packet type received - %d\n", +- packet->type); +- return; +- } +- +- nvsp_packet = (struct nvsp_message *)((unsigned long)packet + +- (packet->offset8 << 3)); +- +- /* Make sure this is a valid nvsp packet */ +- if (nvsp_packet->hdr.msg_type != +- NVSP_MSG1_TYPE_SEND_RNDIS_PKT) { +- netdev_err(ndev, "Unknown nvsp packet type received-" +- " %d\n", nvsp_packet->hdr.msg_type); +- return; +- } +- +- vmxferpage_packet = (struct vmtransfer_page_packet_header *)packet; +- +- if (vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID) { +- netdev_err(ndev, "Invalid xfer page set id - " +- "expecting %x got %x\n", NETVSC_RECEIVE_BUFFER_ID, +- vmxferpage_packet->xfer_pageset_id); +- return; +- } +- +- /* +- * Grab free packets (range count + 1) to represent this xfer +- * page packet. +1 to represent the xfer page packet itself. +- * We grab it here so that we know exactly how many we can +- * fulfil +- */ +- spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags); +- while (!list_empty(&net_device->recv_pkt_list)) { +- list_move_tail(net_device->recv_pkt_list.next, &listHead); +- if (++count == vmxferpage_packet->range_cnt + 1) +- break; +- } +- spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags); +- +- /* +- * We need at least 2 netvsc pkts (1 to represent the xfer +- * page and at least 1 for the range) i.e. we can handled +- * some of the xfer page packet ranges... +- */ +- if (count < 2) { +- netdev_err(ndev, "Got only %d netvsc pkt...needed " +- "%d pkts. Dropping this xfer page packet completely!\n", +- count, vmxferpage_packet->range_cnt + 1); +- +- /* Return it to the freelist */ +- spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags); +- for (i = count; i != 0; i--) { +- list_move_tail(listHead.next, +- &net_device->recv_pkt_list); +- } +- spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, +- flags); +- +- netvsc_send_recv_completion(device, +- vmxferpage_packet->d.trans_id); +- +- return; +- } +- +- /* Remove the 1st packet to represent the xfer page packet itself */ +- xferpage_packet = (struct xferpage_packet *)listHead.next; +- list_del(&xferpage_packet->list_ent); +- +- /* This is how much we can satisfy */ +- xferpage_packet->count = count - 1; +- +- if (xferpage_packet->count != vmxferpage_packet->range_cnt) { +- netdev_err(ndev, "Needed %d netvsc pkts to satisfy " +- "this xfer page...got %d\n", +- vmxferpage_packet->range_cnt, xferpage_packet->count); +- } +- +- /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */ +- for (i = 0; i < (count - 1); i++) { +- netvsc_packet = (struct hv_netvsc_packet *)listHead.next; +- list_del(&netvsc_packet->list_ent); +- +- /* Initialize the netvsc packet */ +- netvsc_packet->xfer_page_pkt = xferpage_packet; +- netvsc_packet->completion.recv.recv_completion = +- netvsc_receive_completion; +- netvsc_packet->completion.recv.recv_completion_ctx = +- netvsc_packet; +- netvsc_packet->device = device; +- /* Save this so that we can send it back */ +- netvsc_packet->completion.recv.recv_completion_tid = +- vmxferpage_packet->d.trans_id; +- +- netvsc_packet->total_data_buflen = +- vmxferpage_packet->ranges[i].byte_count; +- netvsc_packet->page_buf_cnt = 1; +- +- netvsc_packet->page_buf[0].len = +- vmxferpage_packet->ranges[i].byte_count; +- +- start = virt_to_phys((void *)((unsigned long)net_device-> +- recv_buf + vmxferpage_packet->ranges[i].byte_offset)); +- +- netvsc_packet->page_buf[0].pfn = start >> PAGE_SHIFT; +- end_virtual = (unsigned long)net_device->recv_buf +- + vmxferpage_packet->ranges[i].byte_offset +- + vmxferpage_packet->ranges[i].byte_count - 1; +- end = virt_to_phys((void *)end_virtual); +- +- /* Calculate the page relative offset */ +- netvsc_packet->page_buf[0].offset = +- vmxferpage_packet->ranges[i].byte_offset & +- (PAGE_SIZE - 1); +- if ((end >> PAGE_SHIFT) != (start >> PAGE_SHIFT)) { +- /* Handle frame across multiple pages: */ +- netvsc_packet->page_buf[0].len = +- (netvsc_packet->page_buf[0].pfn << +- PAGE_SHIFT) +- + PAGE_SIZE - start; +- bytes_remain = netvsc_packet->total_data_buflen - +- netvsc_packet->page_buf[0].len; +- for (j = 1; j < NETVSC_PACKET_MAXPAGE; j++) { +- netvsc_packet->page_buf[j].offset = 0; +- if (bytes_remain <= PAGE_SIZE) { +- netvsc_packet->page_buf[j].len = +- bytes_remain; +- bytes_remain = 0; +- } else { +- netvsc_packet->page_buf[j].len = +- PAGE_SIZE; +- bytes_remain -= PAGE_SIZE; +- } +- netvsc_packet->page_buf[j].pfn = +- virt_to_phys((void *)(end_virtual - +- bytes_remain)) >> PAGE_SHIFT; +- netvsc_packet->page_buf_cnt++; +- if (bytes_remain == 0) +- break; +- } +- } +- +- /* Pass it to the upper layer */ +- rndis_filter_receive(device, netvsc_packet); +- +- netvsc_receive_completion(netvsc_packet-> +- completion.recv.recv_completion_ctx); +- } +- +-} +- +-static void netvsc_channel_cb(void *context) +-{ +- int ret; +- struct hv_device *device = context; +- struct netvsc_device *net_device; +- u32 bytes_recvd; +- u64 request_id; +- unsigned char *packet; +- struct vmpacket_descriptor *desc; +- unsigned char *buffer; +- int bufferlen = NETVSC_PACKET_SIZE; +- struct net_device *ndev; +- +- packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char), +- GFP_ATOMIC); +- if (!packet) +- return; +- buffer = packet; +- +- net_device = get_inbound_net_device(device); +- if (!net_device) +- goto out; +- ndev = net_device->ndev; +- +- do { +- ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen, +- &bytes_recvd, &request_id); +- if (ret == 0) { +- if (bytes_recvd > 0) { +- desc = (struct vmpacket_descriptor *)buffer; +- switch (desc->type) { +- case VM_PKT_COMP: +- netvsc_send_completion(device, desc); +- break; +- +- case VM_PKT_DATA_USING_XFER_PAGES: +- netvsc_receive(device, desc); +- break; +- +- default: +- netdev_err(ndev, +- "unhandled packet type %d, " +- "tid %llx len %d\n", +- desc->type, request_id, +- bytes_recvd); +- break; +- } +- +- /* reset */ +- if (bufferlen > NETVSC_PACKET_SIZE) { +- kfree(buffer); +- buffer = packet; +- bufferlen = NETVSC_PACKET_SIZE; +- } +- } else { +- /* reset */ +- if (bufferlen > NETVSC_PACKET_SIZE) { +- kfree(buffer); +- buffer = packet; +- bufferlen = NETVSC_PACKET_SIZE; +- } +- +- break; +- } +- } else if (ret == -ENOBUFS) { +- /* Handle large packet */ +- buffer = kmalloc(bytes_recvd, GFP_ATOMIC); +- if (buffer == NULL) { +- /* Try again next time around */ +- netdev_err(ndev, +- "unable to allocate buffer of size " +- "(%d)!!\n", bytes_recvd); +- break; +- } +- +- bufferlen = bytes_recvd; +- } +- } while (1); +- +-out: +- kfree(buffer); +- return; +-} +- +-/* +- * netvsc_device_add - Callback when the device belonging to this +- * driver is added +- */ +-int netvsc_device_add(struct hv_device *device, void *additional_info) +-{ +- int ret = 0; +- int i; +- int ring_size = +- ((struct netvsc_device_info *)additional_info)->ring_size; +- struct netvsc_device *net_device; +- struct hv_netvsc_packet *packet, *pos; +- struct net_device *ndev; +- +- net_device = alloc_net_device(device); +- if (!net_device) { +- ret = -ENOMEM; +- goto cleanup; +- } +- +- /* +- * Coming into this function, struct net_device * is +- * registered as the driver private data. +- * In alloc_net_device(), we register struct netvsc_device * +- * as the driver private data and stash away struct net_device * +- * in struct netvsc_device *. +- */ +- ndev = net_device->ndev; +- +- /* Initialize the NetVSC channel extension */ +- net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; +- spin_lock_init(&net_device->recv_pkt_list_lock); +- +- INIT_LIST_HEAD(&net_device->recv_pkt_list); +- +- for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) { +- packet = kzalloc(sizeof(struct hv_netvsc_packet) + +- (NETVSC_RECEIVE_SG_COUNT * +- sizeof(struct hv_page_buffer)), GFP_KERNEL); +- if (!packet) +- break; +- +- list_add_tail(&packet->list_ent, +- &net_device->recv_pkt_list); +- } +- init_completion(&net_device->channel_init_wait); +- +- /* Open the channel */ +- ret = vmbus_open(device->channel, ring_size * PAGE_SIZE, +- ring_size * PAGE_SIZE, NULL, 0, +- netvsc_channel_cb, device); +- +- if (ret != 0) { +- netdev_err(ndev, "unable to open channel: %d\n", ret); +- goto cleanup; +- } +- +- /* Channel is opened */ +- pr_info("hv_netvsc channel opened successfully\n"); +- +- /* Connect with the NetVsp */ +- ret = netvsc_connect_vsp(device); +- if (ret != 0) { +- netdev_err(ndev, +- "unable to connect to NetVSP - %d\n", ret); +- goto close; +- } +- +- return ret; +- +-close: +- /* Now, we can close the channel safely */ +- vmbus_close(device->channel); +- +-cleanup: +- +- if (net_device) { +- list_for_each_entry_safe(packet, pos, +- &net_device->recv_pkt_list, +- list_ent) { +- list_del(&packet->list_ent); +- kfree(packet); +- } +- +- kfree(net_device); +- } +- +- return ret; +-} +diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c +deleted file mode 100644 +index 93b0e91..0000000 +--- a/drivers/staging/hv/netvsc_drv.c ++++ /dev/null +@@ -1,456 +0,0 @@ +-/* +- * Copyright (c) 2009, Microsoft Corporation. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple +- * Place - Suite 330, Boston, MA 02111-1307 USA. +- * +- * Authors: +- * Haiyang Zhang +- * Hank Janssen +- */ +-#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 "hyperv_net.h" +- +-struct net_device_context { +- /* point back to our device context */ +- struct hv_device *device_ctx; +- atomic_t avail; +- struct delayed_work dwork; +-}; +- +- +-#define PACKET_PAGES_LOWATER 8 +-/* Need this many pages to handle worst case fragmented packet */ +-#define PACKET_PAGES_HIWATER (MAX_SKB_FRAGS + 2) +- +-static int ring_size = 128; +-module_param(ring_size, int, S_IRUGO); +-MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); +- +-/* no-op so the netdev core doesn't return -EINVAL when modifying the the +- * multicast address list in SIOCADDMULTI. hv is setup to get all multicast +- * when it calls RndisFilterOnOpen() */ +-static void netvsc_set_multicast_list(struct net_device *net) +-{ +-} +- +-static int netvsc_open(struct net_device *net) +-{ +- struct net_device_context *net_device_ctx = netdev_priv(net); +- struct hv_device *device_obj = net_device_ctx->device_ctx; +- int ret = 0; +- +- /* Open up the device */ +- ret = rndis_filter_open(device_obj); +- if (ret != 0) { +- netdev_err(net, "unable to open device (ret %d).\n", ret); +- return ret; +- } +- +- netif_start_queue(net); +- +- return ret; +-} +- +-static int netvsc_close(struct net_device *net) +-{ +- struct net_device_context *net_device_ctx = netdev_priv(net); +- struct hv_device *device_obj = net_device_ctx->device_ctx; +- int ret; +- +- netif_stop_queue(net); +- +- ret = rndis_filter_close(device_obj); +- if (ret != 0) +- netdev_err(net, "unable to close device (ret %d).\n", ret); +- +- return ret; +-} +- +-static void netvsc_xmit_completion(void *context) +-{ +- struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context; +- struct sk_buff *skb = (struct sk_buff *) +- (unsigned long)packet->completion.send.send_completion_tid; +- +- kfree(packet); +- +- if (skb) { +- struct net_device *net = skb->dev; +- struct net_device_context *net_device_ctx = netdev_priv(net); +- unsigned int num_pages = skb_shinfo(skb)->nr_frags + 2; +- +- dev_kfree_skb_any(skb); +- +- atomic_add(num_pages, &net_device_ctx->avail); +- if (atomic_read(&net_device_ctx->avail) >= +- PACKET_PAGES_HIWATER) +- netif_wake_queue(net); +- } +-} +- +-static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) +-{ +- struct net_device_context *net_device_ctx = netdev_priv(net); +- struct hv_netvsc_packet *packet; +- int ret; +- unsigned int i, num_pages; +- +- /* Add 1 for skb->data and additional one for RNDIS */ +- num_pages = skb_shinfo(skb)->nr_frags + 1 + 1; +- if (num_pages > atomic_read(&net_device_ctx->avail)) +- return NETDEV_TX_BUSY; +- +- /* Allocate a netvsc packet based on # of frags. */ +- packet = kzalloc(sizeof(struct hv_netvsc_packet) + +- (num_pages * sizeof(struct hv_page_buffer)) + +- sizeof(struct rndis_filter_packet), GFP_ATOMIC); +- if (!packet) { +- /* out of memory, drop packet */ +- netdev_err(net, "unable to allocate hv_netvsc_packet\n"); +- +- dev_kfree_skb(skb); +- net->stats.tx_dropped++; +- return NETDEV_TX_BUSY; +- } +- +- packet->extension = (void *)(unsigned long)packet + +- sizeof(struct hv_netvsc_packet) + +- (num_pages * sizeof(struct hv_page_buffer)); +- +- /* Setup the rndis header */ +- packet->page_buf_cnt = num_pages; +- +- /* Initialize it from the skb */ +- packet->total_data_buflen = skb->len; +- +- /* Start filling in the page buffers starting after RNDIS buffer. */ +- packet->page_buf[1].pfn = virt_to_phys(skb->data) >> PAGE_SHIFT; +- packet->page_buf[1].offset +- = (unsigned long)skb->data & (PAGE_SIZE - 1); +- packet->page_buf[1].len = skb_headlen(skb); +- +- /* Additional fragments are after SKB data */ +- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { +- const skb_frag_t *f = &skb_shinfo(skb)->frags[i]; +- +- packet->page_buf[i+2].pfn = page_to_pfn(skb_frag_page(f)); +- packet->page_buf[i+2].offset = f->page_offset; +- packet->page_buf[i+2].len = skb_frag_size(f); +- } +- +- /* Set the completion routine */ +- packet->completion.send.send_completion = netvsc_xmit_completion; +- packet->completion.send.send_completion_ctx = packet; +- packet->completion.send.send_completion_tid = (unsigned long)skb; +- +- ret = rndis_filter_send(net_device_ctx->device_ctx, +- packet); +- if (ret == 0) { +- net->stats.tx_bytes += skb->len; +- net->stats.tx_packets++; +- +- atomic_sub(num_pages, &net_device_ctx->avail); +- if (atomic_read(&net_device_ctx->avail) < PACKET_PAGES_LOWATER) +- netif_stop_queue(net); +- } else { +- /* we are shutting down or bus overloaded, just drop packet */ +- net->stats.tx_dropped++; +- kfree(packet); +- dev_kfree_skb_any(skb); +- } +- +- return ret ? NETDEV_TX_BUSY : NETDEV_TX_OK; +-} +- +-/* +- * netvsc_linkstatus_callback - Link up/down notification +- */ +-void netvsc_linkstatus_callback(struct hv_device *device_obj, +- unsigned int status) +-{ +- struct net_device *net; +- struct net_device_context *ndev_ctx; +- struct netvsc_device *net_device; +- +- net_device = hv_get_drvdata(device_obj); +- net = net_device->ndev; +- +- if (!net) { +- netdev_err(net, "got link status but net device " +- "not initialized yet\n"); +- return; +- } +- +- if (status == 1) { +- netif_carrier_on(net); +- netif_wake_queue(net); +- ndev_ctx = netdev_priv(net); +- schedule_delayed_work(&ndev_ctx->dwork, 0); +- schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20)); +- } else { +- netif_carrier_off(net); +- netif_stop_queue(net); +- } +-} +- +-/* +- * netvsc_recv_callback - Callback when we receive a packet from the +- * "wire" on the specified device. +- */ +-int netvsc_recv_callback(struct hv_device *device_obj, +- struct hv_netvsc_packet *packet) +-{ +- struct net_device *net = dev_get_drvdata(&device_obj->device); +- struct sk_buff *skb; +- void *data; +- int i; +- unsigned long flags; +- struct netvsc_device *net_device; +- +- net_device = hv_get_drvdata(device_obj); +- net = net_device->ndev; +- +- if (!net) { +- netdev_err(net, "got receive callback but net device" +- " not initialized yet\n"); +- return 0; +- } +- +- /* Allocate a skb - TODO direct I/O to pages? */ +- skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen); +- if (unlikely(!skb)) { +- ++net->stats.rx_dropped; +- return 0; +- } +- +- /* for kmap_atomic */ +- local_irq_save(flags); +- +- /* +- * Copy to skb. This copy is needed here since the memory pointed by +- * hv_netvsc_packet cannot be deallocated +- */ +- for (i = 0; i < packet->page_buf_cnt; i++) { +- data = kmap_atomic(pfn_to_page(packet->page_buf[i].pfn), +- KM_IRQ1); +- data = (void *)(unsigned long)data + +- packet->page_buf[i].offset; +- +- memcpy(skb_put(skb, packet->page_buf[i].len), data, +- packet->page_buf[i].len); +- +- kunmap_atomic((void *)((unsigned long)data - +- packet->page_buf[i].offset), KM_IRQ1); +- } +- +- local_irq_restore(flags); +- +- skb->protocol = eth_type_trans(skb, net); +- skb->ip_summed = CHECKSUM_NONE; +- +- net->stats.rx_packets++; +- net->stats.rx_bytes += skb->len; +- +- /* +- * Pass the skb back up. Network stack will deallocate the skb when it +- * is done. +- * TODO - use NAPI? +- */ +- netif_rx(skb); +- +- return 0; +-} +- +-static void netvsc_get_drvinfo(struct net_device *net, +- struct ethtool_drvinfo *info) +-{ +- strcpy(info->driver, "hv_netvsc"); +- strcpy(info->version, HV_DRV_VERSION); +- strcpy(info->fw_version, "N/A"); +-} +- +-static const struct ethtool_ops ethtool_ops = { +- .get_drvinfo = netvsc_get_drvinfo, +- .get_link = ethtool_op_get_link, +-}; +- +-static const struct net_device_ops device_ops = { +- .ndo_open = netvsc_open, +- .ndo_stop = netvsc_close, +- .ndo_start_xmit = netvsc_start_xmit, +- .ndo_set_rx_mode = netvsc_set_multicast_list, +- .ndo_change_mtu = eth_change_mtu, +- .ndo_validate_addr = eth_validate_addr, +- .ndo_set_mac_address = eth_mac_addr, +-}; +- +-/* +- * Send GARP packet to network peers after migrations. +- * After Quick Migration, the network is not immediately operational in the +- * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add +- * another netif_notify_peers() into a delayed work, otherwise GARP packet +- * will not be sent after quick migration, and cause network disconnection. +- */ +-static void netvsc_send_garp(struct work_struct *w) +-{ +- struct net_device_context *ndev_ctx; +- struct net_device *net; +- struct netvsc_device *net_device; +- +- ndev_ctx = container_of(w, struct net_device_context, dwork.work); +- net_device = hv_get_drvdata(ndev_ctx->device_ctx); +- net = net_device->ndev; +- netif_notify_peers(net); +-} +- +- +-static int netvsc_probe(struct hv_device *dev, +- const struct hv_vmbus_device_id *dev_id) +-{ +- struct net_device *net = NULL; +- struct net_device_context *net_device_ctx; +- struct netvsc_device_info device_info; +- int ret; +- +- net = alloc_etherdev(sizeof(struct net_device_context)); +- if (!net) +- return -ENOMEM; +- +- /* Set initial state */ +- netif_carrier_off(net); +- +- net_device_ctx = netdev_priv(net); +- net_device_ctx->device_ctx = dev; +- atomic_set(&net_device_ctx->avail, ring_size); +- hv_set_drvdata(dev, net); +- INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp); +- +- net->netdev_ops = &device_ops; +- +- /* TODO: Add GSO and Checksum offload */ +- net->hw_features = NETIF_F_SG; +- net->features = NETIF_F_SG; +- +- SET_ETHTOOL_OPS(net, ðtool_ops); +- SET_NETDEV_DEV(net, &dev->device); +- +- ret = register_netdev(net); +- if (ret != 0) { +- pr_err("Unable to register netdev.\n"); +- free_netdev(net); +- goto out; +- } +- +- /* Notify the netvsc driver of the new device */ +- device_info.ring_size = ring_size; +- ret = rndis_filter_device_add(dev, &device_info); +- if (ret != 0) { +- netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); +- unregister_netdev(net); +- free_netdev(net); +- hv_set_drvdata(dev, NULL); +- return ret; +- } +- memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); +- +- netif_carrier_on(net); +- +-out: +- return ret; +-} +- +-static int netvsc_remove(struct hv_device *dev) +-{ +- struct net_device *net; +- struct net_device_context *ndev_ctx; +- struct netvsc_device *net_device; +- +- net_device = hv_get_drvdata(dev); +- net = net_device->ndev; +- +- if (net == NULL) { +- dev_err(&dev->device, "No net device to remove\n"); +- return 0; +- } +- +- ndev_ctx = netdev_priv(net); +- cancel_delayed_work_sync(&ndev_ctx->dwork); +- +- /* Stop outbound asap */ +- netif_stop_queue(net); +- +- unregister_netdev(net); +- +- /* +- * Call to the vsc driver to let it know that the device is being +- * removed +- */ +- rndis_filter_device_remove(dev); +- +- free_netdev(net); +- return 0; +-} +- +-static const struct hv_vmbus_device_id id_table[] = { +- /* Network guid */ +- { VMBUS_DEVICE(0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, +- 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E) }, +- { }, +-}; +- +-MODULE_DEVICE_TABLE(vmbus, id_table); +- +-/* The one and only one */ +-static struct hv_driver netvsc_drv = { +- .name = "netvsc", +- .id_table = id_table, +- .probe = netvsc_probe, +- .remove = netvsc_remove, +-}; +- +-static void __exit netvsc_drv_exit(void) +-{ +- vmbus_driver_unregister(&netvsc_drv); +-} +- +-static int __init netvsc_drv_init(void) +-{ +- return vmbus_driver_register(&netvsc_drv); +-} +- +-MODULE_LICENSE("GPL"); +-MODULE_VERSION(HV_DRV_VERSION); +-MODULE_DESCRIPTION("Microsoft Hyper-V network driver"); +- +-module_init(netvsc_drv_init); +-module_exit(netvsc_drv_exit); +diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c +deleted file mode 100644 +index bafccb3..0000000 +--- a/drivers/staging/hv/rndis_filter.c ++++ /dev/null +@@ -1,855 +0,0 @@ +-/* +- * Copyright (c) 2009, Microsoft Corporation. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple +- * Place - Suite 330, Boston, MA 02111-1307 USA. +- * +- * Authors: +- * Haiyang Zhang +- * Hank Janssen +- */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "hyperv_net.h" +- +- +-enum rndis_device_state { +- RNDIS_DEV_UNINITIALIZED = 0, +- RNDIS_DEV_INITIALIZING, +- RNDIS_DEV_INITIALIZED, +- RNDIS_DEV_DATAINITIALIZED, +-}; +- +-struct rndis_device { +- struct netvsc_device *net_dev; +- +- enum rndis_device_state state; +- bool link_state; +- atomic_t new_req_id; +- +- spinlock_t request_lock; +- struct list_head req_list; +- +- unsigned char hw_mac_adr[ETH_ALEN]; +-}; +- +-struct rndis_request { +- struct list_head list_ent; +- struct completion wait_event; +- +- /* +- * FIXME: We assumed a fixed size response here. If we do ever need to +- * handle a bigger response, we can either define a max response +- * message or add a response buffer variable above this field +- */ +- struct rndis_message response_msg; +- +- /* Simplify allocation by having a netvsc packet inline */ +- struct hv_netvsc_packet pkt; +- struct hv_page_buffer buf; +- /* FIXME: We assumed a fixed size request here. */ +- struct rndis_message request_msg; +-}; +- +-static void rndis_filter_send_completion(void *ctx); +- +-static void rndis_filter_send_request_completion(void *ctx); +- +- +- +-static struct rndis_device *get_rndis_device(void) +-{ +- struct rndis_device *device; +- +- device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL); +- if (!device) +- return NULL; +- +- spin_lock_init(&device->request_lock); +- +- INIT_LIST_HEAD(&device->req_list); +- +- device->state = RNDIS_DEV_UNINITIALIZED; +- +- return device; +-} +- +-static struct rndis_request *get_rndis_request(struct rndis_device *dev, +- u32 msg_type, +- u32 msg_len) +-{ +- struct rndis_request *request; +- struct rndis_message *rndis_msg; +- struct rndis_set_request *set; +- unsigned long flags; +- +- request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL); +- if (!request) +- return NULL; +- +- init_completion(&request->wait_event); +- +- rndis_msg = &request->request_msg; +- rndis_msg->ndis_msg_type = msg_type; +- rndis_msg->msg_len = msg_len; +- +- /* +- * Set the request id. This field is always after the rndis header for +- * request/response packet types so we just used the SetRequest as a +- * template +- */ +- set = &rndis_msg->msg.set_req; +- set->req_id = atomic_inc_return(&dev->new_req_id); +- +- /* Add to the request list */ +- spin_lock_irqsave(&dev->request_lock, flags); +- list_add_tail(&request->list_ent, &dev->req_list); +- spin_unlock_irqrestore(&dev->request_lock, flags); +- +- return request; +-} +- +-static void put_rndis_request(struct rndis_device *dev, +- struct rndis_request *req) +-{ +- unsigned long flags; +- +- spin_lock_irqsave(&dev->request_lock, flags); +- list_del(&req->list_ent); +- spin_unlock_irqrestore(&dev->request_lock, flags); +- +- kfree(req); +-} +- +-static void dump_rndis_message(struct hv_device *hv_dev, +- struct rndis_message *rndis_msg) +-{ +- struct net_device *netdev; +- struct netvsc_device *net_device; +- +- net_device = hv_get_drvdata(hv_dev); +- netdev = net_device->ndev; +- +- switch (rndis_msg->ndis_msg_type) { +- case REMOTE_NDIS_PACKET_MSG: +- netdev_dbg(netdev, "REMOTE_NDIS_PACKET_MSG (len %u, " +- "data offset %u data len %u, # oob %u, " +- "oob offset %u, oob len %u, pkt offset %u, " +- "pkt len %u\n", +- rndis_msg->msg_len, +- rndis_msg->msg.pkt.data_offset, +- rndis_msg->msg.pkt.data_len, +- rndis_msg->msg.pkt.num_oob_data_elements, +- rndis_msg->msg.pkt.oob_data_offset, +- rndis_msg->msg.pkt.oob_data_len, +- rndis_msg->msg.pkt.per_pkt_info_offset, +- rndis_msg->msg.pkt.per_pkt_info_len); +- break; +- +- case REMOTE_NDIS_INITIALIZE_CMPLT: +- netdev_dbg(netdev, "REMOTE_NDIS_INITIALIZE_CMPLT " +- "(len %u, id 0x%x, status 0x%x, major %d, minor %d, " +- "device flags %d, max xfer size 0x%x, max pkts %u, " +- "pkt aligned %u)\n", +- rndis_msg->msg_len, +- rndis_msg->msg.init_complete.req_id, +- rndis_msg->msg.init_complete.status, +- rndis_msg->msg.init_complete.major_ver, +- rndis_msg->msg.init_complete.minor_ver, +- rndis_msg->msg.init_complete.dev_flags, +- rndis_msg->msg.init_complete.max_xfer_size, +- rndis_msg->msg.init_complete. +- max_pkt_per_msg, +- rndis_msg->msg.init_complete. +- pkt_alignment_factor); +- break; +- +- case REMOTE_NDIS_QUERY_CMPLT: +- netdev_dbg(netdev, "REMOTE_NDIS_QUERY_CMPLT " +- "(len %u, id 0x%x, status 0x%x, buf len %u, " +- "buf offset %u)\n", +- rndis_msg->msg_len, +- rndis_msg->msg.query_complete.req_id, +- rndis_msg->msg.query_complete.status, +- rndis_msg->msg.query_complete. +- info_buflen, +- rndis_msg->msg.query_complete. +- info_buf_offset); +- break; +- +- case REMOTE_NDIS_SET_CMPLT: +- netdev_dbg(netdev, +- "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)\n", +- rndis_msg->msg_len, +- rndis_msg->msg.set_complete.req_id, +- rndis_msg->msg.set_complete.status); +- break; +- +- case REMOTE_NDIS_INDICATE_STATUS_MSG: +- netdev_dbg(netdev, "REMOTE_NDIS_INDICATE_STATUS_MSG " +- "(len %u, status 0x%x, buf len %u, buf offset %u)\n", +- rndis_msg->msg_len, +- rndis_msg->msg.indicate_status.status, +- rndis_msg->msg.indicate_status.status_buflen, +- rndis_msg->msg.indicate_status.status_buf_offset); +- break; +- +- default: +- netdev_dbg(netdev, "0x%x (len %u)\n", +- rndis_msg->ndis_msg_type, +- rndis_msg->msg_len); +- break; +- } +-} +- +-static int rndis_filter_send_request(struct rndis_device *dev, +- struct rndis_request *req) +-{ +- int ret; +- struct hv_netvsc_packet *packet; +- +- /* Setup the packet to send it */ +- packet = &req->pkt; +- +- packet->is_data_pkt = false; +- packet->total_data_buflen = req->request_msg.msg_len; +- packet->page_buf_cnt = 1; +- +- packet->page_buf[0].pfn = virt_to_phys(&req->request_msg) >> +- PAGE_SHIFT; +- packet->page_buf[0].len = req->request_msg.msg_len; +- packet->page_buf[0].offset = +- (unsigned long)&req->request_msg & (PAGE_SIZE - 1); +- +- packet->completion.send.send_completion_ctx = req;/* packet; */ +- packet->completion.send.send_completion = +- rndis_filter_send_request_completion; +- packet->completion.send.send_completion_tid = (unsigned long)dev; +- +- ret = netvsc_send(dev->net_dev->dev, packet); +- return ret; +-} +- +-static void rndis_filter_receive_response(struct rndis_device *dev, +- struct rndis_message *resp) +-{ +- struct rndis_request *request = NULL; +- bool found = false; +- unsigned long flags; +- struct net_device *ndev; +- +- ndev = dev->net_dev->ndev; +- +- spin_lock_irqsave(&dev->request_lock, flags); +- list_for_each_entry(request, &dev->req_list, list_ent) { +- /* +- * All request/response message contains RequestId as the 1st +- * field +- */ +- if (request->request_msg.msg.init_req.req_id +- == resp->msg.init_complete.req_id) { +- found = true; +- break; +- } +- } +- spin_unlock_irqrestore(&dev->request_lock, flags); +- +- if (found) { +- if (resp->msg_len <= sizeof(struct rndis_message)) { +- memcpy(&request->response_msg, resp, +- resp->msg_len); +- } else { +- netdev_err(ndev, +- "rndis response buffer overflow " +- "detected (size %u max %zu)\n", +- resp->msg_len, +- sizeof(struct rndis_filter_packet)); +- +- if (resp->ndis_msg_type == +- REMOTE_NDIS_RESET_CMPLT) { +- /* does not have a request id field */ +- request->response_msg.msg.reset_complete. +- status = STATUS_BUFFER_OVERFLOW; +- } else { +- request->response_msg.msg. +- init_complete.status = +- STATUS_BUFFER_OVERFLOW; +- } +- } +- +- complete(&request->wait_event); +- } else { +- netdev_err(ndev, +- "no rndis request found for this response " +- "(id 0x%x res type 0x%x)\n", +- resp->msg.init_complete.req_id, +- resp->ndis_msg_type); +- } +-} +- +-static void rndis_filter_receive_indicate_status(struct rndis_device *dev, +- struct rndis_message *resp) +-{ +- struct rndis_indicate_status *indicate = +- &resp->msg.indicate_status; +- +- if (indicate->status == RNDIS_STATUS_MEDIA_CONNECT) { +- netvsc_linkstatus_callback( +- dev->net_dev->dev, 1); +- } else if (indicate->status == RNDIS_STATUS_MEDIA_DISCONNECT) { +- netvsc_linkstatus_callback( +- dev->net_dev->dev, 0); +- } else { +- /* +- * TODO: +- */ +- } +-} +- +-static void rndis_filter_receive_data(struct rndis_device *dev, +- struct rndis_message *msg, +- struct hv_netvsc_packet *pkt) +-{ +- struct rndis_packet *rndis_pkt; +- u32 data_offset; +- int i; +- +- rndis_pkt = &msg->msg.pkt; +- +- /* +- * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this +- * netvsc packet (ie TotalDataBufferLength != MessageLength) +- */ +- +- /* Remove the rndis header and pass it back up the stack */ +- data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset; +- +- pkt->total_data_buflen -= data_offset; +- pkt->page_buf[0].offset += data_offset; +- pkt->page_buf[0].len -= data_offset; +- +- /* Drop the 0th page, if rndis data go beyond page boundary */ +- if (pkt->page_buf[0].offset >= PAGE_SIZE) { +- pkt->page_buf[1].offset = pkt->page_buf[0].offset - PAGE_SIZE; +- pkt->page_buf[1].len -= pkt->page_buf[1].offset; +- pkt->page_buf_cnt--; +- for (i = 0; i < pkt->page_buf_cnt; i++) +- pkt->page_buf[i] = pkt->page_buf[i+1]; +- } +- +- pkt->is_data_pkt = true; +- +- netvsc_recv_callback(dev->net_dev->dev, pkt); +-} +- +-int rndis_filter_receive(struct hv_device *dev, +- struct hv_netvsc_packet *pkt) +-{ +- struct netvsc_device *net_dev = hv_get_drvdata(dev); +- struct rndis_device *rndis_dev; +- struct rndis_message rndis_msg; +- struct rndis_message *rndis_hdr; +- struct net_device *ndev; +- +- if (!net_dev) +- return -EINVAL; +- +- ndev = net_dev->ndev; +- +- /* Make sure the rndis device state is initialized */ +- if (!net_dev->extension) { +- netdev_err(ndev, "got rndis message but no rndis device - " +- "dropping this message!\n"); +- return -ENODEV; +- } +- +- rndis_dev = (struct rndis_device *)net_dev->extension; +- if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) { +- netdev_err(ndev, "got rndis message but rndis device " +- "uninitialized...dropping this message!\n"); +- return -ENODEV; +- } +- +- rndis_hdr = (struct rndis_message *)kmap_atomic( +- pfn_to_page(pkt->page_buf[0].pfn), KM_IRQ0); +- +- rndis_hdr = (void *)((unsigned long)rndis_hdr + +- pkt->page_buf[0].offset); +- +- /* Make sure we got a valid rndis message */ +- if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) && +- (rndis_hdr->msg_len > sizeof(struct rndis_message))) { +- netdev_err(ndev, "incoming rndis message buffer overflow " +- "detected (got %u, max %zu)..marking it an error!\n", +- rndis_hdr->msg_len, +- sizeof(struct rndis_message)); +- } +- +- memcpy(&rndis_msg, rndis_hdr, +- (rndis_hdr->msg_len > sizeof(struct rndis_message)) ? +- sizeof(struct rndis_message) : +- rndis_hdr->msg_len); +- +- kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset, KM_IRQ0); +- +- dump_rndis_message(dev, &rndis_msg); +- +- switch (rndis_msg.ndis_msg_type) { +- case REMOTE_NDIS_PACKET_MSG: +- /* data msg */ +- rndis_filter_receive_data(rndis_dev, &rndis_msg, pkt); +- break; +- +- case REMOTE_NDIS_INITIALIZE_CMPLT: +- case REMOTE_NDIS_QUERY_CMPLT: +- case REMOTE_NDIS_SET_CMPLT: +- /* completion msgs */ +- rndis_filter_receive_response(rndis_dev, &rndis_msg); +- break; +- +- case REMOTE_NDIS_INDICATE_STATUS_MSG: +- /* notification msgs */ +- rndis_filter_receive_indicate_status(rndis_dev, &rndis_msg); +- break; +- default: +- netdev_err(ndev, +- "unhandled rndis message (type %u len %u)\n", +- rndis_msg.ndis_msg_type, +- rndis_msg.msg_len); +- break; +- } +- +- return 0; +-} +- +-static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, +- void *result, u32 *result_size) +-{ +- struct rndis_request *request; +- u32 inresult_size = *result_size; +- struct rndis_query_request *query; +- struct rndis_query_complete *query_complete; +- int ret = 0; +- int t; +- +- if (!result) +- return -EINVAL; +- +- *result_size = 0; +- request = get_rndis_request(dev, REMOTE_NDIS_QUERY_MSG, +- RNDIS_MESSAGE_SIZE(struct rndis_query_request)); +- if (!request) { +- ret = -ENOMEM; +- goto cleanup; +- } +- +- /* Setup the rndis query */ +- query = &request->request_msg.msg.query_req; +- query->oid = oid; +- query->info_buf_offset = sizeof(struct rndis_query_request); +- query->info_buflen = 0; +- query->dev_vc_handle = 0; +- +- ret = rndis_filter_send_request(dev, request); +- if (ret != 0) +- goto cleanup; +- +- t = wait_for_completion_timeout(&request->wait_event, 5*HZ); +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- /* Copy the response back */ +- query_complete = &request->response_msg.msg.query_complete; +- +- if (query_complete->info_buflen > inresult_size) { +- ret = -1; +- goto cleanup; +- } +- +- memcpy(result, +- (void *)((unsigned long)query_complete + +- query_complete->info_buf_offset), +- query_complete->info_buflen); +- +- *result_size = query_complete->info_buflen; +- +-cleanup: +- if (request) +- put_rndis_request(dev, request); +- +- return ret; +-} +- +-static int rndis_filter_query_device_mac(struct rndis_device *dev) +-{ +- u32 size = ETH_ALEN; +- +- return rndis_filter_query_device(dev, +- RNDIS_OID_802_3_PERMANENT_ADDRESS, +- dev->hw_mac_adr, &size); +-} +- +-static int rndis_filter_query_device_link_status(struct rndis_device *dev) +-{ +- u32 size = sizeof(u32); +- u32 link_status; +- int ret; +- +- ret = rndis_filter_query_device(dev, +- RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, +- &link_status, &size); +- dev->link_state = (link_status != 0) ? true : false; +- +- return ret; +-} +- +-static int rndis_filter_set_packet_filter(struct rndis_device *dev, +- u32 new_filter) +-{ +- struct rndis_request *request; +- struct rndis_set_request *set; +- struct rndis_set_complete *set_complete; +- u32 status; +- int ret, t; +- struct net_device *ndev; +- +- ndev = dev->net_dev->ndev; +- +- request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG, +- RNDIS_MESSAGE_SIZE(struct rndis_set_request) + +- sizeof(u32)); +- if (!request) { +- ret = -ENOMEM; +- goto cleanup; +- } +- +- /* Setup the rndis set */ +- set = &request->request_msg.msg.set_req; +- set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER; +- set->info_buflen = sizeof(u32); +- set->info_buf_offset = sizeof(struct rndis_set_request); +- +- memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request), +- &new_filter, sizeof(u32)); +- +- ret = rndis_filter_send_request(dev, request); +- if (ret != 0) +- goto cleanup; +- +- t = wait_for_completion_timeout(&request->wait_event, 5*HZ); +- +- if (t == 0) { +- netdev_err(ndev, +- "timeout before we got a set response...\n"); +- /* +- * We can't deallocate the request since we may still receive a +- * send completion for it. +- */ +- goto exit; +- } else { +- set_complete = &request->response_msg.msg.set_complete; +- status = set_complete->status; +- } +- +-cleanup: +- if (request) +- put_rndis_request(dev, request); +-exit: +- return ret; +-} +- +- +-static int rndis_filter_init_device(struct rndis_device *dev) +-{ +- struct rndis_request *request; +- struct rndis_initialize_request *init; +- struct rndis_initialize_complete *init_complete; +- u32 status; +- int ret, t; +- +- request = get_rndis_request(dev, REMOTE_NDIS_INITIALIZE_MSG, +- RNDIS_MESSAGE_SIZE(struct rndis_initialize_request)); +- if (!request) { +- ret = -ENOMEM; +- goto cleanup; +- } +- +- /* Setup the rndis set */ +- init = &request->request_msg.msg.init_req; +- init->major_ver = RNDIS_MAJOR_VERSION; +- init->minor_ver = RNDIS_MINOR_VERSION; +- /* FIXME: Use 1536 - rounded ethernet frame size */ +- init->max_xfer_size = 2048; +- +- dev->state = RNDIS_DEV_INITIALIZING; +- +- ret = rndis_filter_send_request(dev, request); +- if (ret != 0) { +- dev->state = RNDIS_DEV_UNINITIALIZED; +- goto cleanup; +- } +- +- +- t = wait_for_completion_timeout(&request->wait_event, 5*HZ); +- +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- init_complete = &request->response_msg.msg.init_complete; +- status = init_complete->status; +- if (status == RNDIS_STATUS_SUCCESS) { +- dev->state = RNDIS_DEV_INITIALIZED; +- ret = 0; +- } else { +- dev->state = RNDIS_DEV_UNINITIALIZED; +- ret = -EINVAL; +- } +- +-cleanup: +- if (request) +- put_rndis_request(dev, request); +- +- return ret; +-} +- +-static void rndis_filter_halt_device(struct rndis_device *dev) +-{ +- struct rndis_request *request; +- struct rndis_halt_request *halt; +- +- /* Attempt to do a rndis device halt */ +- request = get_rndis_request(dev, REMOTE_NDIS_HALT_MSG, +- RNDIS_MESSAGE_SIZE(struct rndis_halt_request)); +- if (!request) +- goto cleanup; +- +- /* Setup the rndis set */ +- halt = &request->request_msg.msg.halt_req; +- halt->req_id = atomic_inc_return(&dev->new_req_id); +- +- /* Ignore return since this msg is optional. */ +- rndis_filter_send_request(dev, request); +- +- dev->state = RNDIS_DEV_UNINITIALIZED; +- +-cleanup: +- if (request) +- put_rndis_request(dev, request); +- return; +-} +- +-static int rndis_filter_open_device(struct rndis_device *dev) +-{ +- int ret; +- +- if (dev->state != RNDIS_DEV_INITIALIZED) +- return 0; +- +- ret = rndis_filter_set_packet_filter(dev, +- NDIS_PACKET_TYPE_BROADCAST | +- NDIS_PACKET_TYPE_ALL_MULTICAST | +- NDIS_PACKET_TYPE_DIRECTED); +- if (ret == 0) +- dev->state = RNDIS_DEV_DATAINITIALIZED; +- +- return ret; +-} +- +-static int rndis_filter_close_device(struct rndis_device *dev) +-{ +- int ret; +- +- if (dev->state != RNDIS_DEV_DATAINITIALIZED) +- return 0; +- +- ret = rndis_filter_set_packet_filter(dev, 0); +- if (ret == 0) +- dev->state = RNDIS_DEV_INITIALIZED; +- +- return ret; +-} +- +-int rndis_filter_device_add(struct hv_device *dev, +- void *additional_info) +-{ +- int ret; +- struct netvsc_device *net_device; +- struct rndis_device *rndis_device; +- struct netvsc_device_info *device_info = additional_info; +- +- rndis_device = get_rndis_device(); +- if (!rndis_device) +- return -ENODEV; +- +- /* +- * Let the inner driver handle this first to create the netvsc channel +- * NOTE! Once the channel is created, we may get a receive callback +- * (RndisFilterOnReceive()) before this call is completed +- */ +- ret = netvsc_device_add(dev, additional_info); +- if (ret != 0) { +- kfree(rndis_device); +- return ret; +- } +- +- +- /* Initialize the rndis device */ +- net_device = hv_get_drvdata(dev); +- +- net_device->extension = rndis_device; +- rndis_device->net_dev = net_device; +- +- /* Send the rndis initialization message */ +- ret = rndis_filter_init_device(rndis_device); +- if (ret != 0) { +- /* +- * TODO: If rndis init failed, we will need to shut down the +- * channel +- */ +- } +- +- /* Get the mac address */ +- ret = rndis_filter_query_device_mac(rndis_device); +- if (ret != 0) { +- /* +- * TODO: shutdown rndis device and the channel +- */ +- } +- +- memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN); +- +- rndis_filter_query_device_link_status(rndis_device); +- +- device_info->link_state = rndis_device->link_state; +- +- dev_info(&dev->device, "Device MAC %pM link state %s\n", +- rndis_device->hw_mac_adr, +- device_info->link_state ? "down" : "up"); +- +- return ret; +-} +- +-void rndis_filter_device_remove(struct hv_device *dev) +-{ +- struct netvsc_device *net_dev = hv_get_drvdata(dev); +- struct rndis_device *rndis_dev = net_dev->extension; +- +- /* Halt and release the rndis device */ +- rndis_filter_halt_device(rndis_dev); +- +- kfree(rndis_dev); +- net_dev->extension = NULL; +- +- netvsc_device_remove(dev); +-} +- +- +-int rndis_filter_open(struct hv_device *dev) +-{ +- struct netvsc_device *net_device = hv_get_drvdata(dev); +- +- if (!net_device) +- return -EINVAL; +- +- return rndis_filter_open_device(net_device->extension); +-} +- +-int rndis_filter_close(struct hv_device *dev) +-{ +- struct netvsc_device *netDevice = hv_get_drvdata(dev); +- +- if (!netDevice) +- return -EINVAL; +- +- return rndis_filter_close_device(netDevice->extension); +-} +- +-int rndis_filter_send(struct hv_device *dev, +- struct hv_netvsc_packet *pkt) +-{ +- int ret; +- struct rndis_filter_packet *filterPacket; +- struct rndis_message *rndisMessage; +- struct rndis_packet *rndisPacket; +- u32 rndisMessageSize; +- +- /* Add the rndis header */ +- filterPacket = (struct rndis_filter_packet *)pkt->extension; +- +- memset(filterPacket, 0, sizeof(struct rndis_filter_packet)); +- +- rndisMessage = &filterPacket->msg; +- rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet); +- +- rndisMessage->ndis_msg_type = REMOTE_NDIS_PACKET_MSG; +- rndisMessage->msg_len = pkt->total_data_buflen + +- rndisMessageSize; +- +- rndisPacket = &rndisMessage->msg.pkt; +- rndisPacket->data_offset = sizeof(struct rndis_packet); +- rndisPacket->data_len = pkt->total_data_buflen; +- +- pkt->is_data_pkt = true; +- pkt->page_buf[0].pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT; +- pkt->page_buf[0].offset = +- (unsigned long)rndisMessage & (PAGE_SIZE-1); +- pkt->page_buf[0].len = rndisMessageSize; +- +- /* Save the packet send completion and context */ +- filterPacket->completion = pkt->completion.send.send_completion; +- filterPacket->completion_ctx = +- pkt->completion.send.send_completion_ctx; +- +- /* Use ours */ +- pkt->completion.send.send_completion = rndis_filter_send_completion; +- pkt->completion.send.send_completion_ctx = filterPacket; +- +- ret = netvsc_send(dev, pkt); +- if (ret != 0) { +- /* +- * Reset the completion to originals to allow retries from +- * above +- */ +- pkt->completion.send.send_completion = +- filterPacket->completion; +- pkt->completion.send.send_completion_ctx = +- filterPacket->completion_ctx; +- } +- +- return ret; +-} +- +-static void rndis_filter_send_completion(void *ctx) +-{ +- struct rndis_filter_packet *filterPacket = ctx; +- +- /* Pass it back to the original handler */ +- filterPacket->completion(filterPacket->completion_ctx); +-} +- +- +-static void rndis_filter_send_request_completion(void *ctx) +-{ +- /* Noop */ +-} +diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c +deleted file mode 100644 +index 54ef3d4..0000000 +--- a/drivers/staging/hv/storvsc_drv.c ++++ /dev/null +@@ -1,1499 +0,0 @@ +-/* +- * Copyright (c) 2009, Microsoft Corporation. +- * +- * 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. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple +- * Place - Suite 330, Boston, MA 02111-1307 USA. +- * +- * Authors: +- * Haiyang Zhang +- * Hank Janssen +- * K. Y. Srinivasan +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +- +-#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) +-static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE; +- +-module_param(storvsc_ringbuffer_size, int, S_IRUGO); +-MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); +- +-/* to alert the user that structure sizes may be mismatched even though the */ +-/* protocol versions match. */ +- +- +-#define REVISION_STRING(REVISION_) #REVISION_ +-#define FILL_VMSTOR_REVISION(RESULT_LVALUE_) \ +- do { \ +- char *revision_string \ +- = REVISION_STRING($Rev : 6 $) + 6; \ +- RESULT_LVALUE_ = 0; \ +- while (*revision_string >= '0' \ +- && *revision_string <= '9') { \ +- RESULT_LVALUE_ *= 10; \ +- RESULT_LVALUE_ += *revision_string - '0'; \ +- revision_string++; \ +- } \ +- } while (0) +- +-/* Major/minor macros. Minor version is in LSB, meaning that earlier flat */ +-/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */ +-#define VMSTOR_PROTOCOL_MAJOR(VERSION_) (((VERSION_) >> 8) & 0xff) +-#define VMSTOR_PROTOCOL_MINOR(VERSION_) (((VERSION_)) & 0xff) +-#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ +- (((MINOR_) & 0xff))) +-#define VMSTOR_INVALID_PROTOCOL_VERSION (-1) +- +-/* Version history: */ +-/* V1 Beta 0.1 */ +-/* V1 RC < 2008/1/31 1.0 */ +-/* V1 RC > 2008/1/31 2.0 */ +-#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0) +- +- +- +- +-/* This will get replaced with the max transfer length that is possible on */ +-/* the host adapter. */ +-/* The max transfer length will be published when we offer a vmbus channel. */ +-#define MAX_TRANSFER_LENGTH 0x40000 +-#define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) + \ +- sizeof(struct vstor_packet) + \ +- sizesizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE))) +- +- +-/* Packet structure describing virtual storage requests. */ +-enum vstor_packet_operation { +- VSTOR_OPERATION_COMPLETE_IO = 1, +- VSTOR_OPERATION_REMOVE_DEVICE = 2, +- VSTOR_OPERATION_EXECUTE_SRB = 3, +- VSTOR_OPERATION_RESET_LUN = 4, +- VSTOR_OPERATION_RESET_ADAPTER = 5, +- VSTOR_OPERATION_RESET_BUS = 6, +- VSTOR_OPERATION_BEGIN_INITIALIZATION = 7, +- VSTOR_OPERATION_END_INITIALIZATION = 8, +- VSTOR_OPERATION_QUERY_PROTOCOL_VERSION = 9, +- VSTOR_OPERATION_QUERY_PROPERTIES = 10, +- VSTOR_OPERATION_MAXIMUM = 10 +-}; +- +-/* +- * Platform neutral description of a scsi request - +- * this remains the same across the write regardless of 32/64 bit +- * note: it's patterned off the SCSI_PASS_THROUGH structure +- */ +-#define CDB16GENERIC_LENGTH 0x10 +- +-#ifndef SENSE_BUFFER_SIZE +-#define SENSE_BUFFER_SIZE 0x12 +-#endif +- +-#define MAX_DATA_BUF_LEN_WITH_PADDING 0x14 +- +-struct vmscsi_request { +- unsigned short length; +- unsigned char srb_status; +- unsigned char scsi_status; +- +- unsigned char port_number; +- unsigned char path_id; +- unsigned char target_id; +- unsigned char lun; +- +- unsigned char cdb_length; +- unsigned char sense_info_length; +- unsigned char data_in; +- unsigned char reserved; +- +- unsigned int data_transfer_length; +- +- union { +- unsigned char cdb[CDB16GENERIC_LENGTH]; +- unsigned char sense_data[SENSE_BUFFER_SIZE]; +- unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING]; +- }; +-} __attribute((packed)); +- +- +-/* +- * This structure is sent during the intialization phase to get the different +- * properties of the channel. +- */ +-struct vmstorage_channel_properties { +- unsigned short protocol_version; +- unsigned char path_id; +- unsigned char target_id; +- +- /* Note: port number is only really known on the client side */ +- unsigned int port_number; +- unsigned int flags; +- unsigned int max_transfer_bytes; +- +- /* This id is unique for each channel and will correspond with */ +- /* vendor specific data in the inquirydata */ +- unsigned long long unique_id; +-} __packed; +- +-/* This structure is sent during the storage protocol negotiations. */ +-struct vmstorage_protocol_version { +- /* Major (MSW) and minor (LSW) version numbers. */ +- unsigned short major_minor; +- +- /* +- * Revision number is auto-incremented whenever this file is changed +- * (See FILL_VMSTOR_REVISION macro above). Mismatch does not +- * definitely indicate incompatibility--but it does indicate mismatched +- * builds. +- */ +- unsigned short revision; +-} __packed; +- +-/* Channel Property Flags */ +-#define STORAGE_CHANNEL_REMOVABLE_FLAG 0x1 +-#define STORAGE_CHANNEL_EMULATED_IDE_FLAG 0x2 +- +-struct vstor_packet { +- /* Requested operation type */ +- enum vstor_packet_operation operation; +- +- /* Flags - see below for values */ +- unsigned int flags; +- +- /* Status of the request returned from the server side. */ +- unsigned int status; +- +- /* Data payload area */ +- union { +- /* +- * Structure used to forward SCSI commands from the +- * client to the server. +- */ +- struct vmscsi_request vm_srb; +- +- /* Structure used to query channel properties. */ +- struct vmstorage_channel_properties storage_channel_properties; +- +- /* Used during version negotiations. */ +- struct vmstorage_protocol_version version; +- }; +-} __packed; +- +-/* Packet flags */ +-/* +- * This flag indicates that the server should send back a completion for this +- * packet. +- */ +-#define REQUEST_COMPLETION_FLAG 0x1 +- +-/* This is the set of flags that the vsc can set in any packets it sends */ +-#define VSC_LEGAL_FLAGS (REQUEST_COMPLETION_FLAG) +- +- +-/* Defines */ +- +-#define STORVSC_MAX_IO_REQUESTS 128 +- +-/* +- * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In +- * reality, the path/target is not used (ie always set to 0) so our +- * scsi host adapter essentially has 1 bus with 1 target that contains +- * up to 256 luns. +- */ +-#define STORVSC_MAX_LUNS_PER_TARGET 64 +-#define STORVSC_MAX_TARGETS 1 +-#define STORVSC_MAX_CHANNELS 1 +-#define STORVSC_MAX_CMD_LEN 16 +- +-struct hv_storvsc_request; +- +-/* Matches Windows-end */ +-enum storvsc_request_type { +- WRITE_TYPE, +- READ_TYPE, +- UNKNOWN_TYPE, +-}; +- +- +-struct hv_storvsc_request { +- struct hv_device *device; +- +- /* Synchronize the request/response if needed */ +- struct completion wait_event; +- +- unsigned char *sense_buffer; +- void *context; +- void (*on_io_completion)(struct hv_storvsc_request *request); +- struct hv_multipage_buffer data_buffer; +- +- struct vstor_packet vstor_packet; +-}; +- +- +-/* A storvsc device is a device object that contains a vmbus channel */ +-struct storvsc_device { +- struct hv_device *device; +- +- bool destroy; +- bool drain_notify; +- atomic_t num_outstanding_req; +- struct Scsi_Host *host; +- +- wait_queue_head_t waiting_to_drain; +- +- /* +- * Each unique Port/Path/Target represents 1 channel ie scsi +- * controller. In reality, the pathid, targetid is always 0 +- * and the port is set by us +- */ +- unsigned int port_number; +- unsigned char path_id; +- unsigned char target_id; +- +- /* Used for vsc/vsp channel reset process */ +- struct hv_storvsc_request init_request; +- struct hv_storvsc_request reset_request; +-}; +- +-struct hv_host_device { +- struct hv_device *dev; +- struct kmem_cache *request_pool; +- unsigned int port; +- unsigned char path; +- unsigned char target; +-}; +- +-struct storvsc_cmd_request { +- struct list_head entry; +- struct scsi_cmnd *cmd; +- +- unsigned int bounce_sgl_count; +- struct scatterlist *bounce_sgl; +- +- struct hv_storvsc_request request; +-}; +- +-static inline struct storvsc_device *get_out_stor_device( +- struct hv_device *device) +-{ +- struct storvsc_device *stor_device; +- +- stor_device = hv_get_drvdata(device); +- +- if (stor_device && stor_device->destroy) +- stor_device = NULL; +- +- return stor_device; +-} +- +- +-static inline void storvsc_wait_to_drain(struct storvsc_device *dev) +-{ +- dev->drain_notify = true; +- wait_event(dev->waiting_to_drain, +- atomic_read(&dev->num_outstanding_req) == 0); +- dev->drain_notify = false; +-} +- +-static inline struct storvsc_device *get_in_stor_device( +- struct hv_device *device) +-{ +- struct storvsc_device *stor_device; +- +- stor_device = hv_get_drvdata(device); +- +- if (!stor_device) +- goto get_in_err; +- +- /* +- * If the device is being destroyed; allow incoming +- * traffic only to cleanup outstanding requests. +- */ +- +- if (stor_device->destroy && +- (atomic_read(&stor_device->num_outstanding_req) == 0)) +- stor_device = NULL; +- +-get_in_err: +- return stor_device; +- +-} +- +-static int storvsc_channel_init(struct hv_device *device) +-{ +- struct storvsc_device *stor_device; +- struct hv_storvsc_request *request; +- struct vstor_packet *vstor_packet; +- int ret, t; +- +- stor_device = get_out_stor_device(device); +- if (!stor_device) +- return -ENODEV; +- +- request = &stor_device->init_request; +- vstor_packet = &request->vstor_packet; +- +- /* +- * Now, initiate the vsc/vsp initialization protocol on the open +- * channel +- */ +- memset(request, 0, sizeof(struct hv_storvsc_request)); +- init_completion(&request->wait_event); +- vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; +- vstor_packet->flags = REQUEST_COMPLETION_FLAG; +- +- ret = vmbus_sendpacket(device->channel, vstor_packet, +- sizeof(struct vstor_packet), +- (unsigned long)request, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); +- if (ret != 0) +- goto cleanup; +- +- t = wait_for_completion_timeout(&request->wait_event, 5*HZ); +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || +- vstor_packet->status != 0) +- goto cleanup; +- +- +- /* reuse the packet for version range supported */ +- memset(vstor_packet, 0, sizeof(struct vstor_packet)); +- vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; +- vstor_packet->flags = REQUEST_COMPLETION_FLAG; +- +- vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT; +- FILL_VMSTOR_REVISION(vstor_packet->version.revision); +- +- ret = vmbus_sendpacket(device->channel, vstor_packet, +- sizeof(struct vstor_packet), +- (unsigned long)request, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); +- if (ret != 0) +- goto cleanup; +- +- t = wait_for_completion_timeout(&request->wait_event, 5*HZ); +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || +- vstor_packet->status != 0) +- goto cleanup; +- +- +- memset(vstor_packet, 0, sizeof(struct vstor_packet)); +- vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES; +- vstor_packet->flags = REQUEST_COMPLETION_FLAG; +- vstor_packet->storage_channel_properties.port_number = +- stor_device->port_number; +- +- ret = vmbus_sendpacket(device->channel, vstor_packet, +- sizeof(struct vstor_packet), +- (unsigned long)request, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); +- +- if (ret != 0) +- goto cleanup; +- +- t = wait_for_completion_timeout(&request->wait_event, 5*HZ); +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || +- vstor_packet->status != 0) +- goto cleanup; +- +- stor_device->path_id = vstor_packet->storage_channel_properties.path_id; +- stor_device->target_id +- = vstor_packet->storage_channel_properties.target_id; +- +- memset(vstor_packet, 0, sizeof(struct vstor_packet)); +- vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION; +- vstor_packet->flags = REQUEST_COMPLETION_FLAG; +- +- ret = vmbus_sendpacket(device->channel, vstor_packet, +- sizeof(struct vstor_packet), +- (unsigned long)request, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); +- +- if (ret != 0) +- goto cleanup; +- +- t = wait_for_completion_timeout(&request->wait_event, 5*HZ); +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || +- vstor_packet->status != 0) +- goto cleanup; +- +- +-cleanup: +- return ret; +-} +- +-static void storvsc_on_io_completion(struct hv_device *device, +- struct vstor_packet *vstor_packet, +- struct hv_storvsc_request *request) +-{ +- struct storvsc_device *stor_device; +- struct vstor_packet *stor_pkt; +- +- stor_device = hv_get_drvdata(device); +- stor_pkt = &request->vstor_packet; +- +- /* +- * The current SCSI handling on the host side does +- * not correctly handle: +- * INQUIRY command with page code parameter set to 0x80 +- * MODE_SENSE command with cmd[2] == 0x1c +- * +- * Setup srb and scsi status so this won't be fatal. +- * We do this so we can distinguish truly fatal failues +- * (srb status == 0x4) and off-line the device in that case. +- */ +- +- if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) || +- (stor_pkt->vm_srb.cdb[0] == MODE_SENSE)) { +- vstor_packet->vm_srb.scsi_status = 0; +- vstor_packet->vm_srb.srb_status = 0x1; +- } +- +- +- /* Copy over the status...etc */ +- stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status; +- stor_pkt->vm_srb.srb_status = vstor_packet->vm_srb.srb_status; +- stor_pkt->vm_srb.sense_info_length = +- vstor_packet->vm_srb.sense_info_length; +- +- if (vstor_packet->vm_srb.scsi_status != 0 || +- vstor_packet->vm_srb.srb_status != 1){ +- dev_warn(&device->device, +- "cmd 0x%x scsi status 0x%x srb status 0x%x\n", +- stor_pkt->vm_srb.cdb[0], +- vstor_packet->vm_srb.scsi_status, +- vstor_packet->vm_srb.srb_status); +- } +- +- if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) { +- /* CHECK_CONDITION */ +- if (vstor_packet->vm_srb.srb_status & 0x80) { +- /* autosense data available */ +- dev_warn(&device->device, +- "stor pkt %p autosense data valid - len %d\n", +- request, +- vstor_packet->vm_srb.sense_info_length); +- +- memcpy(request->sense_buffer, +- vstor_packet->vm_srb.sense_data, +- vstor_packet->vm_srb.sense_info_length); +- +- } +- } +- +- stor_pkt->vm_srb.data_transfer_length = +- vstor_packet->vm_srb.data_transfer_length; +- +- request->on_io_completion(request); +- +- if (atomic_dec_and_test(&stor_device->num_outstanding_req) && +- stor_device->drain_notify) +- wake_up(&stor_device->waiting_to_drain); +- +- +-} +- +-static void storvsc_on_receive(struct hv_device *device, +- struct vstor_packet *vstor_packet, +- struct hv_storvsc_request *request) +-{ +- switch (vstor_packet->operation) { +- case VSTOR_OPERATION_COMPLETE_IO: +- storvsc_on_io_completion(device, vstor_packet, request); +- break; +- case VSTOR_OPERATION_REMOVE_DEVICE: +- +- default: +- break; +- } +-} +- +-static void storvsc_on_channel_callback(void *context) +-{ +- struct hv_device *device = (struct hv_device *)context; +- struct storvsc_device *stor_device; +- u32 bytes_recvd; +- u64 request_id; +- unsigned char packet[ALIGN(sizeof(struct vstor_packet), 8)]; +- struct hv_storvsc_request *request; +- int ret; +- +- +- stor_device = get_in_stor_device(device); +- if (!stor_device) +- return; +- +- do { +- ret = vmbus_recvpacket(device->channel, packet, +- ALIGN(sizeof(struct vstor_packet), 8), +- &bytes_recvd, &request_id); +- if (ret == 0 && bytes_recvd > 0) { +- +- request = (struct hv_storvsc_request *) +- (unsigned long)request_id; +- +- if ((request == &stor_device->init_request) || +- (request == &stor_device->reset_request)) { +- +- memcpy(&request->vstor_packet, packet, +- sizeof(struct vstor_packet)); +- complete(&request->wait_event); +- } else { +- storvsc_on_receive(device, +- (struct vstor_packet *)packet, +- request); +- } +- } else { +- break; +- } +- } while (1); +- +- return; +-} +- +-static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size) +-{ +- struct vmstorage_channel_properties props; +- int ret; +- +- memset(&props, 0, sizeof(struct vmstorage_channel_properties)); +- +- /* Open the channel */ +- ret = vmbus_open(device->channel, +- ring_size, +- ring_size, +- (void *)&props, +- sizeof(struct vmstorage_channel_properties), +- storvsc_on_channel_callback, device); +- +- if (ret != 0) +- return ret; +- +- ret = storvsc_channel_init(device); +- +- return ret; +-} +- +-static int storvsc_dev_remove(struct hv_device *device) +-{ +- struct storvsc_device *stor_device; +- unsigned long flags; +- +- stor_device = hv_get_drvdata(device); +- +- spin_lock_irqsave(&device->channel->inbound_lock, flags); +- stor_device->destroy = true; +- spin_unlock_irqrestore(&device->channel->inbound_lock, flags); +- +- /* +- * At this point, all outbound traffic should be disable. We +- * only allow inbound traffic (responses) to proceed so that +- * outstanding requests can be completed. +- */ +- +- storvsc_wait_to_drain(stor_device); +- +- /* +- * Since we have already drained, we don't need to busy wait +- * as was done in final_release_stor_device() +- * Note that we cannot set the ext pointer to NULL until +- * we have drained - to drain the outgoing packets, we need to +- * allow incoming packets. +- */ +- spin_lock_irqsave(&device->channel->inbound_lock, flags); +- hv_set_drvdata(device, NULL); +- spin_unlock_irqrestore(&device->channel->inbound_lock, flags); +- +- /* Close the channel */ +- vmbus_close(device->channel); +- +- kfree(stor_device); +- return 0; +-} +- +-static int storvsc_do_io(struct hv_device *device, +- struct hv_storvsc_request *request) +-{ +- struct storvsc_device *stor_device; +- struct vstor_packet *vstor_packet; +- int ret = 0; +- +- vstor_packet = &request->vstor_packet; +- stor_device = get_out_stor_device(device); +- +- if (!stor_device) +- return -ENODEV; +- +- +- request->device = device; +- +- +- vstor_packet->flags |= REQUEST_COMPLETION_FLAG; +- +- vstor_packet->vm_srb.length = sizeof(struct vmscsi_request); +- +- +- vstor_packet->vm_srb.sense_info_length = SENSE_BUFFER_SIZE; +- +- +- vstor_packet->vm_srb.data_transfer_length = +- request->data_buffer.len; +- +- vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB; +- +- if (request->data_buffer.len) { +- ret = vmbus_sendpacket_multipagebuffer(device->channel, +- &request->data_buffer, +- vstor_packet, +- sizeof(struct vstor_packet), +- (unsigned long)request); +- } else { +- ret = vmbus_sendpacket(device->channel, vstor_packet, +- sizeof(struct vstor_packet), +- (unsigned long)request, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); +- } +- +- if (ret != 0) +- return ret; +- +- atomic_inc(&stor_device->num_outstanding_req); +- +- return ret; +-} +- +-static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path) +-{ +- *target = +- dev->dev_instance.b[5] << 8 | dev->dev_instance.b[4]; +- +- *path = +- dev->dev_instance.b[3] << 24 | +- dev->dev_instance.b[2] << 16 | +- dev->dev_instance.b[1] << 8 | dev->dev_instance.b[0]; +-} +- +- +-static int storvsc_device_alloc(struct scsi_device *sdevice) +-{ +- /* +- * This enables luns to be located sparsely. Otherwise, we may not +- * discovered them. +- */ +- sdevice->sdev_bflags |= BLIST_SPARSELUN | BLIST_LARGELUN; +- return 0; +-} +- +-static int storvsc_merge_bvec(struct request_queue *q, +- struct bvec_merge_data *bmd, struct bio_vec *bvec) +-{ +- /* checking done by caller. */ +- return bvec->bv_len; +-} +- +-static int storvsc_device_configure(struct scsi_device *sdevice) +-{ +- scsi_adjust_queue_depth(sdevice, MSG_SIMPLE_TAG, +- STORVSC_MAX_IO_REQUESTS); +- +- blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE); +- +- blk_queue_merge_bvec(sdevice->request_queue, storvsc_merge_bvec); +- +- blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY); +- +- return 0; +-} +- +-static void destroy_bounce_buffer(struct scatterlist *sgl, +- unsigned int sg_count) +-{ +- int i; +- struct page *page_buf; +- +- for (i = 0; i < sg_count; i++) { +- page_buf = sg_page((&sgl[i])); +- if (page_buf != NULL) +- __free_page(page_buf); +- } +- +- kfree(sgl); +-} +- +-static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count) +-{ +- int i; +- +- /* No need to check */ +- if (sg_count < 2) +- return -1; +- +- /* We have at least 2 sg entries */ +- for (i = 0; i < sg_count; i++) { +- if (i == 0) { +- /* make sure 1st one does not have hole */ +- if (sgl[i].offset + sgl[i].length != PAGE_SIZE) +- return i; +- } else if (i == sg_count - 1) { +- /* make sure last one does not have hole */ +- if (sgl[i].offset != 0) +- return i; +- } else { +- /* make sure no hole in the middle */ +- if (sgl[i].length != PAGE_SIZE || sgl[i].offset != 0) +- return i; +- } +- } +- return -1; +-} +- +-static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl, +- unsigned int sg_count, +- unsigned int len) +-{ +- int i; +- int num_pages; +- struct scatterlist *bounce_sgl; +- struct page *page_buf; +- +- num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT; +- +- bounce_sgl = kcalloc(num_pages, sizeof(struct scatterlist), GFP_ATOMIC); +- if (!bounce_sgl) +- return NULL; +- +- sg_init_table(bounce_sgl, num_pages); +- for (i = 0; i < num_pages; i++) { +- page_buf = alloc_page(GFP_ATOMIC); +- if (!page_buf) +- goto cleanup; +- sg_set_page(&bounce_sgl[i], page_buf, 0, 0); +- } +- +- return bounce_sgl; +- +-cleanup: +- destroy_bounce_buffer(bounce_sgl, num_pages); +- return NULL; +-} +- +- +-/* Assume the original sgl has enough room */ +-static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, +- struct scatterlist *bounce_sgl, +- unsigned int orig_sgl_count) +-{ +- int i; +- int j = 0; +- unsigned long src, dest; +- unsigned int srclen, destlen, copylen; +- unsigned int total_copied = 0; +- unsigned long bounce_addr = 0; +- unsigned long dest_addr = 0; +- unsigned long flags; +- +- local_irq_save(flags); +- +- for (i = 0; i < orig_sgl_count; i++) { +- dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])), +- KM_IRQ0) + orig_sgl[i].offset; +- dest = dest_addr; +- destlen = orig_sgl[i].length; +- +- if (bounce_addr == 0) +- bounce_addr = +- (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), +- KM_IRQ0); +- +- while (destlen) { +- src = bounce_addr + bounce_sgl[j].offset; +- srclen = bounce_sgl[j].length - bounce_sgl[j].offset; +- +- copylen = min(srclen, destlen); +- memcpy((void *)dest, (void *)src, copylen); +- +- total_copied += copylen; +- bounce_sgl[j].offset += copylen; +- destlen -= copylen; +- dest += copylen; +- +- if (bounce_sgl[j].offset == bounce_sgl[j].length) { +- /* full */ +- kunmap_atomic((void *)bounce_addr, KM_IRQ0); +- j++; +- +- /* if we need to use another bounce buffer */ +- if (destlen || i != orig_sgl_count - 1) +- bounce_addr = +- (unsigned long)kmap_atomic( +- sg_page((&bounce_sgl[j])), KM_IRQ0); +- } else if (destlen == 0 && i == orig_sgl_count - 1) { +- /* unmap the last bounce that is < PAGE_SIZE */ +- kunmap_atomic((void *)bounce_addr, KM_IRQ0); +- } +- } +- +- kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset), +- KM_IRQ0); +- } +- +- local_irq_restore(flags); +- +- return total_copied; +-} +- +- +-/* Assume the bounce_sgl has enough room ie using the create_bounce_buffer() */ +-static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, +- struct scatterlist *bounce_sgl, +- unsigned int orig_sgl_count) +-{ +- int i; +- int j = 0; +- unsigned long src, dest; +- unsigned int srclen, destlen, copylen; +- unsigned int total_copied = 0; +- unsigned long bounce_addr = 0; +- unsigned long src_addr = 0; +- unsigned long flags; +- +- local_irq_save(flags); +- +- for (i = 0; i < orig_sgl_count; i++) { +- src_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])), +- KM_IRQ0) + orig_sgl[i].offset; +- src = src_addr; +- srclen = orig_sgl[i].length; +- +- if (bounce_addr == 0) +- bounce_addr = +- (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), +- KM_IRQ0); +- +- while (srclen) { +- /* assume bounce offset always == 0 */ +- dest = bounce_addr + bounce_sgl[j].length; +- destlen = PAGE_SIZE - bounce_sgl[j].length; +- +- copylen = min(srclen, destlen); +- memcpy((void *)dest, (void *)src, copylen); +- +- total_copied += copylen; +- bounce_sgl[j].length += copylen; +- srclen -= copylen; +- src += copylen; +- +- if (bounce_sgl[j].length == PAGE_SIZE) { +- /* full..move to next entry */ +- kunmap_atomic((void *)bounce_addr, KM_IRQ0); +- bounce_addr = 0; +- j++; +- } +- +- /* if we need to use another bounce buffer */ +- if (srclen && bounce_addr == 0) +- bounce_addr = +- (unsigned long)kmap_atomic( +- sg_page((&bounce_sgl[j])), KM_IRQ0); +- +- } +- +- kunmap_atomic((void *)(src_addr - orig_sgl[i].offset), KM_IRQ0); +- } +- +- if (bounce_addr) +- kunmap_atomic((void *)bounce_addr, KM_IRQ0); +- +- local_irq_restore(flags); +- +- return total_copied; +-} +- +- +-static int storvsc_remove(struct hv_device *dev) +-{ +- struct storvsc_device *stor_device = hv_get_drvdata(dev); +- struct Scsi_Host *host = stor_device->host; +- struct hv_host_device *host_dev = +- (struct hv_host_device *)host->hostdata; +- +- scsi_remove_host(host); +- +- scsi_host_put(host); +- +- storvsc_dev_remove(dev); +- if (host_dev->request_pool) { +- kmem_cache_destroy(host_dev->request_pool); +- host_dev->request_pool = NULL; +- } +- return 0; +-} +- +- +-static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev, +- sector_t capacity, int *info) +-{ +- sector_t nsect = capacity; +- sector_t cylinders = nsect; +- int heads, sectors_pt; +- +- /* +- * We are making up these values; let us keep it simple. +- */ +- heads = 0xff; +- sectors_pt = 0x3f; /* Sectors per track */ +- sector_div(cylinders, heads * sectors_pt); +- if ((sector_t)(cylinders + 1) * heads * sectors_pt < nsect) +- cylinders = 0xffff; +- +- info[0] = heads; +- info[1] = sectors_pt; +- info[2] = (int)cylinders; +- +- return 0; +-} +- +-static int storvsc_host_reset(struct hv_device *device) +-{ +- struct storvsc_device *stor_device; +- struct hv_storvsc_request *request; +- struct vstor_packet *vstor_packet; +- int ret, t; +- +- +- stor_device = get_out_stor_device(device); +- if (!stor_device) +- return -ENODEV; +- +- request = &stor_device->reset_request; +- vstor_packet = &request->vstor_packet; +- +- init_completion(&request->wait_event); +- +- vstor_packet->operation = VSTOR_OPERATION_RESET_BUS; +- vstor_packet->flags = REQUEST_COMPLETION_FLAG; +- vstor_packet->vm_srb.path_id = stor_device->path_id; +- +- ret = vmbus_sendpacket(device->channel, vstor_packet, +- sizeof(struct vstor_packet), +- (unsigned long)&stor_device->reset_request, +- VM_PKT_DATA_INBAND, +- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); +- if (ret != 0) +- goto cleanup; +- +- t = wait_for_completion_timeout(&request->wait_event, 5*HZ); +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- +- /* +- * At this point, all outstanding requests in the adapter +- * should have been flushed out and return to us +- * There is a potential race here where the host may be in +- * the process of responding when we return from here. +- * Just wait for all in-transit packets to be accounted for +- * before we return from here. +- */ +- storvsc_wait_to_drain(stor_device); +- +-cleanup: +- return ret; +-} +- +- +-/* +- * storvsc_host_reset_handler - Reset the scsi HBA +- */ +-static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) +-{ +- int ret; +- struct hv_host_device *host_dev = +- (struct hv_host_device *)scmnd->device->host->hostdata; +- struct hv_device *dev = host_dev->dev; +- +- ret = storvsc_host_reset(dev); +- if (ret != 0) +- return ret; +- +- return ret; +-} +- +- +-/* +- * storvsc_command_completion - Command completion processing +- */ +-static void storvsc_command_completion(struct hv_storvsc_request *request) +-{ +- struct storvsc_cmd_request *cmd_request = +- (struct storvsc_cmd_request *)request->context; +- struct scsi_cmnd *scmnd = cmd_request->cmd; +- struct hv_host_device *host_dev = +- (struct hv_host_device *)scmnd->device->host->hostdata; +- void (*scsi_done_fn)(struct scsi_cmnd *); +- struct scsi_sense_hdr sense_hdr; +- struct vmscsi_request *vm_srb; +- +- vm_srb = &request->vstor_packet.vm_srb; +- if (cmd_request->bounce_sgl_count) { +- if (vm_srb->data_in == READ_TYPE) { +- copy_from_bounce_buffer(scsi_sglist(scmnd), +- cmd_request->bounce_sgl, +- scsi_sg_count(scmnd)); +- destroy_bounce_buffer(cmd_request->bounce_sgl, +- cmd_request->bounce_sgl_count); +- } +- } +- +- /* +- * If there is an error; offline the device since all +- * error recovery strategies would have already been +- * deployed on the host side. +- */ +- if (vm_srb->srb_status == 0x4) +- scmnd->result = DID_TARGET_FAILURE << 16; +- else +- scmnd->result = vm_srb->scsi_status; +- +- if (scmnd->result) { +- if (scsi_normalize_sense(scmnd->sense_buffer, +- SCSI_SENSE_BUFFERSIZE, &sense_hdr)) +- scsi_print_sense_hdr("storvsc", &sense_hdr); +- } +- +- scsi_set_resid(scmnd, +- request->data_buffer.len - +- vm_srb->data_transfer_length); +- +- scsi_done_fn = scmnd->scsi_done; +- +- scmnd->host_scribble = NULL; +- scmnd->scsi_done = NULL; +- +- scsi_done_fn(scmnd); +- +- kmem_cache_free(host_dev->request_pool, cmd_request); +-} +- +-/* +- * The host guarantees to respond to each command, although I/O latencies might +- * be unbounded on Azure. Reset the timer unconditionally to give the host a +- * chance to perform EH. +- */ +-static enum blk_eh_timer_return storvsc_eh_timed_out(struct scsi_cmnd *scmnd) +-{ +- return BLK_EH_RESET_TIMER; +-} +- +-static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd) +-{ +- bool allowed = true; +- u8 scsi_op = scmnd->cmnd[0]; +- +- switch (scsi_op) { +- /* smartd sends this command, which will offline the device */ +- case SET_WINDOW: +- scmnd->result = DID_ERROR << 16; +- allowed = false; +- break; +- default: +- break; +- } +- return allowed; +-} +- +-/* +- * storvsc_queuecommand - Initiate command processing +- */ +-static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd, +- void (*done)(struct scsi_cmnd *)) +-{ +- int ret; +- struct hv_host_device *host_dev = +- (struct hv_host_device *)scmnd->device->host->hostdata; +- struct hv_device *dev = host_dev->dev; +- struct hv_storvsc_request *request; +- struct storvsc_cmd_request *cmd_request; +- unsigned int request_size = 0; +- int i; +- struct scatterlist *sgl; +- unsigned int sg_count = 0; +- struct vmscsi_request *vm_srb; +- +- if (storvsc_check_scsi_cmd(scmnd) == false) { +- done(scmnd); +- return 0; +- } +- +- /* If retrying, no need to prep the cmd */ +- if (scmnd->host_scribble) { +- +- cmd_request = +- (struct storvsc_cmd_request *)scmnd->host_scribble; +- +- goto retry_request; +- } +- +- scmnd->scsi_done = done; +- +- request_size = sizeof(struct storvsc_cmd_request); +- +- cmd_request = kmem_cache_zalloc(host_dev->request_pool, +- GFP_ATOMIC); +- if (!cmd_request) { +- scmnd->scsi_done = NULL; +- return SCSI_MLQUEUE_DEVICE_BUSY; +- } +- +- /* Setup the cmd request */ +- cmd_request->bounce_sgl_count = 0; +- cmd_request->bounce_sgl = NULL; +- cmd_request->cmd = scmnd; +- +- scmnd->host_scribble = (unsigned char *)cmd_request; +- +- request = &cmd_request->request; +- vm_srb = &request->vstor_packet.vm_srb; +- +- +- /* Build the SRB */ +- switch (scmnd->sc_data_direction) { +- case DMA_TO_DEVICE: +- vm_srb->data_in = WRITE_TYPE; +- break; +- case DMA_FROM_DEVICE: +- vm_srb->data_in = READ_TYPE; +- break; +- default: +- vm_srb->data_in = UNKNOWN_TYPE; +- break; +- } +- +- request->on_io_completion = storvsc_command_completion; +- request->context = cmd_request;/* scmnd; */ +- +- vm_srb->port_number = host_dev->port; +- vm_srb->path_id = scmnd->device->channel; +- vm_srb->target_id = scmnd->device->id; +- vm_srb->lun = scmnd->device->lun; +- +- vm_srb->cdb_length = scmnd->cmd_len; +- +- memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length); +- +- request->sense_buffer = scmnd->sense_buffer; +- +- +- request->data_buffer.len = scsi_bufflen(scmnd); +- if (scsi_sg_count(scmnd)) { +- sgl = (struct scatterlist *)scsi_sglist(scmnd); +- sg_count = scsi_sg_count(scmnd); +- +- /* check if we need to bounce the sgl */ +- if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) { +- cmd_request->bounce_sgl = +- create_bounce_buffer(sgl, scsi_sg_count(scmnd), +- scsi_bufflen(scmnd)); +- if (!cmd_request->bounce_sgl) { +- scmnd->scsi_done = NULL; +- scmnd->host_scribble = NULL; +- kmem_cache_free(host_dev->request_pool, +- cmd_request); +- +- return SCSI_MLQUEUE_HOST_BUSY; +- } +- +- cmd_request->bounce_sgl_count = +- ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >> +- PAGE_SHIFT; +- +- if (vm_srb->data_in == WRITE_TYPE) +- copy_to_bounce_buffer(sgl, +- cmd_request->bounce_sgl, +- scsi_sg_count(scmnd)); +- +- sgl = cmd_request->bounce_sgl; +- sg_count = cmd_request->bounce_sgl_count; +- } +- +- request->data_buffer.offset = sgl[0].offset; +- +- for (i = 0; i < sg_count; i++) +- request->data_buffer.pfn_array[i] = +- page_to_pfn(sg_page((&sgl[i]))); +- +- } else if (scsi_sglist(scmnd)) { +- request->data_buffer.offset = +- virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1); +- request->data_buffer.pfn_array[0] = +- virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT; +- } +- +-retry_request: +- /* Invokes the vsc to start an IO */ +- ret = storvsc_do_io(dev, &cmd_request->request); +- +- if (ret == -EAGAIN) { +- /* no more space */ +- +- if (cmd_request->bounce_sgl_count) +- destroy_bounce_buffer(cmd_request->bounce_sgl, +- cmd_request->bounce_sgl_count); +- +- kmem_cache_free(host_dev->request_pool, cmd_request); +- +- scmnd->scsi_done = NULL; +- scmnd->host_scribble = NULL; +- +- ret = SCSI_MLQUEUE_DEVICE_BUSY; +- } +- +- return ret; +-} +- +-static DEF_SCSI_QCMD(storvsc_queuecommand) +- +- +-/* Scsi driver */ +-static struct scsi_host_template scsi_driver = { +- .module = THIS_MODULE, +- .name = "storvsc_host_t", +- .bios_param = storvsc_get_chs, +- .queuecommand = storvsc_queuecommand, +- .eh_host_reset_handler = storvsc_host_reset_handler, +- .eh_timed_out = storvsc_eh_timed_out, +- .slave_alloc = storvsc_device_alloc, +- .slave_configure = storvsc_device_configure, +- .cmd_per_lun = 1, +- /* 64 max_queue * 1 target */ +- .can_queue = STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS, +- .this_id = -1, +- /* no use setting to 0 since ll_blk_rw reset it to 1 */ +- /* currently 32 */ +- .sg_tablesize = MAX_MULTIPAGE_BUFFER_COUNT, +- /* +- * ENABLE_CLUSTERING allows mutiple physically contig bio_vecs to merge +- * into 1 sg element. If set, we must limit the max_segment_size to +- * PAGE_SIZE, otherwise we may get 1 sg element that represents +- * multiple +- */ +- /* physically contig pfns (ie sg[x].length > PAGE_SIZE). */ +- .use_clustering = ENABLE_CLUSTERING, +- /* Make sure we dont get a sg segment crosses a page boundary */ +- .dma_boundary = PAGE_SIZE-1, +-}; +- +-enum { +- SCSI_GUID, +- IDE_GUID, +-}; +- +-static const struct hv_vmbus_device_id id_table[] = { +- /* SCSI guid */ +- { VMBUS_DEVICE(0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, +- 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f) +- .driver_data = SCSI_GUID }, +- /* IDE guid */ +- { VMBUS_DEVICE(0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, +- 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5) +- .driver_data = IDE_GUID }, +- { }, +-}; +- +-MODULE_DEVICE_TABLE(vmbus, id_table); +- +- +-/* +- * storvsc_probe - Add a new device for this driver +- */ +- +-static int storvsc_probe(struct hv_device *device, +- const struct hv_vmbus_device_id *dev_id) +-{ +- int ret; +- struct Scsi_Host *host; +- struct hv_host_device *host_dev; +- bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false); +- int path = 0; +- int target = 0; +- struct storvsc_device *stor_device; +- +- host = scsi_host_alloc(&scsi_driver, +- sizeof(struct hv_host_device)); +- if (!host) +- return -ENOMEM; +- +- host_dev = (struct hv_host_device *)host->hostdata; +- memset(host_dev, 0, sizeof(struct hv_host_device)); +- +- host_dev->port = host->host_no; +- host_dev->dev = device; +- +- host_dev->request_pool = +- kmem_cache_create(dev_name(&device->device), +- sizeof(struct storvsc_cmd_request), 0, +- SLAB_HWCACHE_ALIGN, NULL); +- +- if (!host_dev->request_pool) { +- scsi_host_put(host); +- return -ENOMEM; +- } +- +- stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL); +- if (!stor_device) { +- kmem_cache_destroy(host_dev->request_pool); +- scsi_host_put(host); +- return -ENOMEM; +- } +- +- stor_device->destroy = false; +- init_waitqueue_head(&stor_device->waiting_to_drain); +- stor_device->device = device; +- stor_device->host = host; +- hv_set_drvdata(device, stor_device); +- +- stor_device->port_number = host->host_no; +- ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size); +- if (ret) { +- kmem_cache_destroy(host_dev->request_pool); +- scsi_host_put(host); +- kfree(stor_device); +- return ret; +- } +- +- if (dev_is_ide) +- storvsc_get_ide_info(device, &target, &path); +- +- host_dev->path = stor_device->path_id; +- host_dev->target = stor_device->target_id; +- +- /* max # of devices per target */ +- host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; +- /* max # of targets per channel */ +- host->max_id = STORVSC_MAX_TARGETS; +- /* max # of channels */ +- host->max_channel = STORVSC_MAX_CHANNELS - 1; +- /* max cmd length */ +- host->max_cmd_len = STORVSC_MAX_CMD_LEN; +- +- /* Register the HBA and start the scsi bus scan */ +- ret = scsi_add_host(host, &device->device); +- if (ret != 0) +- goto err_out; +- +- if (!dev_is_ide) { +- scsi_scan_host(host); +- return 0; +- } +- ret = scsi_add_device(host, 0, target, 0); +- if (ret) { +- scsi_remove_host(host); +- goto err_out; +- } +- return 0; +- +-err_out: +- storvsc_dev_remove(device); +- kmem_cache_destroy(host_dev->request_pool); +- scsi_host_put(host); +- return -ENODEV; +-} +- +-/* The one and only one */ +- +-static struct hv_driver storvsc_drv = { +- .name = "storvsc", +- .id_table = id_table, +- .probe = storvsc_probe, +- .remove = storvsc_remove, +-}; +- +-static int __init storvsc_drv_init(void) +-{ +- u32 max_outstanding_req_per_channel; +- +- /* +- * Divide the ring buffer data size (which is 1 page less +- * than the ring buffer size since that page is reserved for +- * the ring buffer indices) by the max request size (which is +- * vmbus_channel_packet_multipage_buffer + struct vstor_packet + u64) +- */ +- max_outstanding_req_per_channel = +- ((storvsc_ringbuffer_size - PAGE_SIZE) / +- ALIGN(MAX_MULTIPAGE_BUFFER_PACKET + +- sizeof(struct vstor_packet) + sizeof(u64), +- sizeof(u64))); +- +- if (max_outstanding_req_per_channel < +- STORVSC_MAX_IO_REQUESTS) +- return -EINVAL; +- +- return vmbus_driver_register(&storvsc_drv); +-} +- +-static void __exit storvsc_drv_exit(void) +-{ +- vmbus_driver_unregister(&storvsc_drv); +-} +- +-MODULE_LICENSE("GPL"); +-MODULE_VERSION(HV_DRV_VERSION); +-MODULE_DESCRIPTION("Microsoft Hyper-V virtual storage driver"); +-module_init(storvsc_drv_init); +-module_exit(storvsc_drv_exit); +diff --git a/drivers/staging/intel_sst/intel_sst_drv_interface.c b/drivers/staging/intel_sst/intel_sst_drv_interface.c +index 22bd29c..ba414eb 100644 +--- a/drivers/staging/intel_sst/intel_sst_drv_interface.c ++++ b/drivers/staging/intel_sst/intel_sst_drv_interface.c +@@ -66,10 +66,8 @@ int sst_download_fw(void) + + pr_debug("Downloading %s FW now...\n", name); + retval = request_firmware(&fw_sst, name, &sst_drv_ctx->pci->dev); +- if (retval) { +- pr_err("request fw failed %d\n", retval); ++ if (retval) + return retval; +- } + sst_drv_ctx->alloc_block[0].sst_id = FW_DWNL_ID; + sst_drv_ctx->alloc_block[0].ops_block.condition = false; + retval = sst_load_fw(fw_sst, NULL); +diff --git a/drivers/staging/intel_sst/intel_sst_dsp.c b/drivers/staging/intel_sst/intel_sst_dsp.c +index 426d2b9..48d36bd 100644 +--- a/drivers/staging/intel_sst/intel_sst_dsp.c ++++ b/drivers/staging/intel_sst/intel_sst_dsp.c +@@ -471,10 +471,8 @@ int sst_load_library(struct snd_sst_lib_download *lib, u8 ops) + pr_debug("Requesting %s\n", buf); + + error = request_firmware(&fw_lib, buf, &sst_drv_ctx->pci->dev); +- if (error) { +- pr_err("library load failed %d\n", error); ++ if (error) + goto wake; +- } + error = sst_validate_library(fw_lib, &lib->slot_info, &entry_point); + if (error) + goto wake_free; +diff --git a/drivers/staging/keucr/init.h b/drivers/staging/keucr/init.h +deleted file mode 100644 +index c8b2cd6..0000000 +--- a/drivers/staging/keucr/init.h ++++ /dev/null +@@ -1,523 +0,0 @@ +-#include "common.h" +- +-extern DWORD MediaChange; +-extern int Check_D_MediaFmt(struct us_data *); +- +- +- +-static BYTE SM_Init[] = { +-0x7B, 0x09, 0x7C, 0xF0, 0x7D, 0x10, 0x7E, 0xE9, +-0x7F, 0xCC, 0x12, 0x2F, 0x71, 0x90, 0xE9, 0xCC, +-0xE0, 0xB4, 0x07, 0x12, 0x90, 0xFF, 0x09, 0xE0, +-0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, +-0xF0, 0x12, 0x2F, 0x5C, 0xD3, 0x22, 0x78, 0x00, +-0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x0A, +-0x20, 0x0A, 0x03, 0x02, 0xE0, 0xD0, 0x7F, 0x00, +-0x12, 0x2F, 0xCB, 0x20, 0x01, 0x05, 0xC2, 0x25, +-0x02, 0xE0, 0xEB, 0xC3, 0xE8, 0x94, 0x02, 0x40, +-0x03, 0x02, 0xE0, 0xD0, 0xC0, 0x00, 0x90, 0xFE, +-0x66, 0x74, 0x90, 0xF0, 0x12, 0xE1, 0x40, 0x90, +-0xFF, 0x95, 0xE0, 0xC2, 0xE4, 0xF0, 0x90, 0xFF, +-0x97, 0x74, 0x01, 0xF0, 0x7E, 0x01, 0x7F, 0x90, +-0x12, 0x2F, 0x74, 0x90, 0xFF, 0x97, 0x74, 0x03, +-0xF0, 0x90, 0xFE, 0xC5, 0xE4, 0xF0, 0x74, 0x00, +-0x90, 0xFE, 0x6A, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, +-0xA3, 0xF0, 0x7E, 0x23, 0x7F, 0xDC, 0x12, 0x2F, +-0x74, 0x12, 0x2F, 0x5C, 0x90, 0xFE, 0x64, 0xE0, +-0x54, 0x01, 0x60, 0x04, 0xD2, 0x02, 0x80, 0x02, +-0xC2, 0x02, 0x90, 0xFF, 0x95, 0xE0, 0xD2, 0xE4, +-0xF0, 0x78, 0x10, 0x79, 0x04, 0x12, 0xE1, 0x71, +-0x50, 0x3A, 0x90, 0xE9, 0xC6, 0xE0, 0x90, 0xE9, +-0xC3, 0xF0, 0x78, 0x9A, 0x79, 0x04, 0x12, 0xE1, +-0x71, 0x50, 0x29, 0x90, 0xE9, 0xC7, 0xE0, 0xB4, +-0xB5, 0x22, 0x90, 0xE9, 0xC4, 0xF0, 0xD0, 0x00, +-0xD2, 0x00, 0xC2, 0x01, 0xC2, 0x25, 0x80, 0x1B, +-0xC2, 0x00, 0xD2, 0x01, 0x74, 0xFF, 0x90, 0xE9, +-0xC3, 0xF0, 0xA3, 0xF0, 0x51, 0x01, 0xC2, 0x0A, +-0xC2, 0x02, 0x80, 0x07, 0xD0, 0x00, 0x05, 0x00, +-0x02, 0xE0, 0x43, 0x90, 0xFF, 0x09, 0xE0, 0x30, +-0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, +-0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xFC, 0xE4, +-0xA2, 0x0A, 0x92, 0xE0, 0xA2, 0x00, 0x92, 0xE1, +-0xA2, 0x01, 0x92, 0xE2, 0xA2, 0x02, 0x92, 0xE6, +-0xA2, 0x25, 0x92, 0xE7, 0x90, 0xF4, 0x00, 0xF0, +-0x90, 0xE9, 0xC3, 0xE0, 0x90, 0xF4, 0x01, 0xF0, +-0x90, 0xE9, 0xC4, 0xE0, 0x90, 0xF4, 0x02, 0xF0, +-0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0, 0xA3, 0x74, +-0x00, 0xF0, 0x75, 0x3C, 0x00, 0x75, 0x3D, 0x00, +-0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22, +-0x90, 0xFE, 0x71, 0xE4, 0xF0, 0x90, 0xFE, 0x72, +-0x74, 0x01, 0xF0, 0x90, 0xFE, 0x64, 0x74, 0x0C, +-0xF0, 0x90, 0xFE, 0x64, 0x74, 0x00, 0x45, 0x4E, +-0xF0, 0x90, 0xFE, 0x64, 0xE0, 0x54, 0x10, 0x60, +-0x08, 0x90, 0xFE, 0x72, 0x74, 0x81, 0xF0, 0xD3, +-0x22, 0x90, 0xFE, 0x64, 0x74, 0x08, 0xF0, 0xC3, +-0x22, 0x90, 0xFE, 0x6F, 0xE9, 0x14, 0xF0, 0x90, +-0xFE, 0x70, 0xE0, 0x54, 0xFC, 0xF0, 0x90, 0xFE, +-0x68, 0x74, 0x00, 0xF0, 0xB8, 0x9A, 0x2A, 0x74, +-0x15, 0x90, 0xFE, 0x64, 0xF0, 0x74, 0x9A, 0x90, +-0xFE, 0x60, 0xF0, 0x74, 0x16, 0x90, 0xFE, 0x64, +-0xF0, 0x74, 0x00, 0x90, 0xFE, 0x60, 0xF0, 0x30, +-0x0A, 0x5D, 0x90, 0xFE, 0x64, 0xE0, 0x20, 0xE7, +-0xF6, 0x74, 0x14, 0x90, 0xFE, 0x64, 0xF0, 0x80, +-0x20, 0x90, 0xFE, 0x6E, 0xE8, 0x44, 0x01, 0xF0, +-0xC2, 0x09, 0x12, 0xE3, 0x26, 0x20, 0x08, 0x0E, +-0x12, 0xE3, 0x32, 0x30, 0x3E, 0xF7, 0x90, 0xFE, +-0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x09, 0x20, 0x09, +-0x2E, 0x7A, 0xE9, 0x7B, 0xC5, 0x7C, 0xFE, 0x7D, +-0x60, 0xB8, 0x10, 0x07, 0x90, 0xFE, 0x69, 0xE0, +-0x20, 0xE6, 0xFC, 0x8C, 0x83, 0x8D, 0x82, 0xE0, +-0x8A, 0x83, 0x8B, 0x82, 0xF0, 0xA3, 0xAA, 0x83, +-0xAB, 0x82, 0xD9, 0xE5, 0xB8, 0x9A, 0x06, 0x74, +-0x10, 0x90, 0xFE, 0x64, 0xF0, 0xD3, 0x22, 0xC3, +-0x22, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, +-0x25, 0x20, 0x25, 0x06, 0xC2, 0x1F, 0xD2, 0x19, +-0xC3, 0x22, 0x7F, 0x02, 0x12, 0x2F, 0xCB, 0x20, +-0x19, 0x05, 0x30, 0x1F, 0x02, 0xD3, 0x22, 0x90, +-0xEA, 0x44, 0x74, 0x80, 0xF0, 0x7F, 0x10, 0x12, +-0x2F, 0xC5, 0x90, 0xFE, 0x47, 0xE0, 0x44, 0x80, +-0xF0, 0x78, 0x00, 0xE8, 0xC3, 0x94, 0x04, 0x50, +-0x0A, 0x7F, 0x88, 0x7E, 0x13, 0x12, 0xE3, 0x4D, +-0x08, 0x80, 0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x54, +-0xFB, 0xF0, 0x90, 0xFE, 0x47, 0xE0, 0x54, 0xBF, +-0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0xFE, 0xF0, +-0x90, 0xFE, 0x45, 0xE0, 0x54, 0x7F, 0xF0, 0x90, +-0xFE, 0x46, 0xE0, 0x44, 0x40, 0xF0, 0x90, 0xFE, +-0x45, 0xE0, 0x54, 0xC7, 0x44, 0x18, 0xF0, 0x90, +-0xFE, 0x47, 0xE0, 0x44, 0x08, 0xF0, 0x90, 0xFE, +-0x45, 0xE0, 0x44, 0x40, 0xF0, 0x7F, 0x32, 0x7E, +-0x00, 0x12, 0xE3, 0x4D, 0x90, 0xFE, 0x51, 0xE0, +-0x54, 0x33, 0xF0, 0x90, 0xFE, 0x44, 0x74, 0x02, +-0xF0, 0x30, 0x25, 0x04, 0xE0, 0x20, 0xE1, 0xF9, +-0x90, 0xFE, 0x51, 0xE0, 0x54, 0x0F, 0xF0, 0x90, +-0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25, 0x04, +-0xE0, 0x20, 0xE1, 0xF9, 0x90, 0xFE, 0x44, 0x74, +-0x04, 0xF0, 0x30, 0x25, 0x04, 0xE0, 0x20, 0xE2, +-0xF9, 0x90, 0xFE, 0x4C, 0xE0, 0xF0, 0x90, 0xFE, +-0x4D, 0xE0, 0xF0, 0x90, 0xFE, 0x48, 0x74, 0x7F, +-0xF0, 0x90, 0xFE, 0x49, 0x74, 0x9F, 0xF0, 0x90, +-0xFE, 0x51, 0xE0, 0x54, 0x3C, 0x44, 0x02, 0xF0, +-0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25, +-0x04, 0xE0, 0x20, 0xE1, 0xF9, 0x90, 0xFE, 0x46, +-0xE0, 0x44, 0x20, 0xF0, 0x79, 0x02, 0x7A, 0x06, +-0x7B, 0x00, 0x7C, 0x00, 0x7D, 0x06, 0x7E, 0xEB, +-0x7F, 0xC9, 0x12, 0x2F, 0xA7, 0x40, 0x03, 0x02, +-0xE3, 0x04, 0xD3, 0x22, 0xE4, 0x90, 0xFE, 0x48, +-0xF0, 0x90, 0xFE, 0x49, 0xF0, 0x90, 0xFE, 0x4C, +-0xE0, 0xF0, 0x90, 0xFE, 0x4D, 0xE0, 0xF0, 0x90, +-0xFE, 0x47, 0xE0, 0x54, 0x7F, 0xF0, 0xC2, 0x25, +-0xC2, 0x1F, 0xD2, 0x19, 0xC3, 0x22, 0xC2, 0x3E, +-0x75, 0x7C, 0x00, 0x75, 0x7D, 0x00, 0x75, 0x7E, +-0x00, 0x22, 0x05, 0x7C, 0xE5, 0x7C, 0x70, 0x14, +-0x05, 0x7D, 0xE5, 0x7D, 0x70, 0x04, 0x05, 0x7E, +-0x80, 0x0A, 0xB4, 0x17, 0x07, 0xE5, 0x7E, 0xB4, +-0x06, 0x02, 0xD2, 0x3E, 0x22, 0x75, 0x8A, 0x00, +-0x75, 0x8C, 0xCE, 0xC2, 0x8D, 0x90, 0xEA, 0x65, +-0xE4, 0xF0, 0xA3, 0xF0, 0xD2, 0x8C, 0x90, 0xEA, +-0x65, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEC, 0xC3, +-0x9E, 0x40, 0xF3, 0x70, 0x05, 0xED, 0xC3, 0x9F, +-0x40, 0xEC, 0xC2, 0x8C, 0x22, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x58, 0x44, 0x2D, 0x49, 0x6E, 0x69, 0x74, 0x20, +-0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x31 }; +- +-static BYTE SM_Rdwr[] = { +-0x7B, 0x0C, 0x7C, 0xF0, 0x7D, 0x10, 0x7E, 0xE9, +-0x7F, 0xCC, 0x12, 0x2F, 0x71, 0x90, 0xE9, 0xC3, +-0xE0, 0xB4, 0x73, 0x04, 0x74, 0x40, 0x80, 0x09, +-0xB4, 0x75, 0x04, 0x74, 0x40, 0x80, 0x02, 0x74, +-0xC0, 0x90, 0xFE, 0x70, 0xF0, 0x90, 0xFF, 0x09, +-0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, +-0x80, 0xF0, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, +-0x92, 0x0A, 0x40, 0x01, 0x22, 0x90, 0xFE, 0x6A, +-0xE4, 0xF0, 0x90, 0xE9, 0xCC, 0xE0, 0xB4, 0x02, +-0x05, 0xD2, 0x06, 0x02, 0xE0, 0x78, 0xB4, 0x03, +-0x03, 0x02, 0xE3, 0xD0, 0xB4, 0x04, 0x03, 0x02, +-0xE1, 0xC6, 0xB4, 0x05, 0x03, 0x02, 0xE5, 0x20, +-0xB4, 0x06, 0x03, 0x02, 0xE5, 0xE0, 0xB4, 0x07, +-0x05, 0x12, 0x2F, 0x5C, 0xD3, 0x22, 0xB4, 0x08, +-0x05, 0xC2, 0x06, 0x02, 0xE6, 0x3B, 0xC3, 0x22, +-0xE5, 0x3E, 0xC3, 0x13, 0x90, 0xE9, 0xCA, 0xF0, +-0xC0, 0xE0, 0x75, 0xF0, 0x02, 0xC0, 0xF0, 0x12, +-0xE0, 0xD8, 0xEF, 0x70, 0x21, 0x20, 0x37, 0x07, +-0x20, 0x09, 0x04, 0xD0, 0xF0, 0x80, 0x05, 0xD0, +-0xF0, 0xD5, 0xF0, 0xE9, 0xD0, 0xE0, 0x90, 0xFF, +-0x28, 0xE0, 0x30, 0xE7, 0xFC, 0x90, 0xFF, 0x28, +-0xE0, 0x44, 0x01, 0xF0, 0xC3, 0x22, 0xD0, 0xF0, +-0x90, 0xE9, 0xCF, 0xE0, 0x24, 0x01, 0xF0, 0x90, +-0xE9, 0xCE, 0xE0, 0x34, 0x00, 0xF0, 0x90, 0xE9, +-0xCD, 0xE0, 0x34, 0x00, 0xF0, 0xD0, 0xE0, 0x14, +-0x70, 0xB6, 0x75, 0x3C, 0x00, 0x75, 0x3D, 0x00, +-0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22, +-0xC2, 0x08, 0xC2, 0x36, 0xC2, 0x37, 0xE4, 0x90, +-0xEB, 0xC2, 0xF0, 0x90, 0xE9, 0xCD, 0xE0, 0xF8, +-0xA3, 0xE0, 0xF9, 0xA3, 0xE0, 0x90, 0xFE, 0x6B, +-0xF0, 0xA3, 0xE9, 0xF0, 0xA3, 0xE8, 0xF0, 0x90, +-0xFE, 0x6F, 0x74, 0x0F, 0xF0, 0x90, 0xFE, 0x70, +-0xE0, 0x54, 0xFC, 0x44, 0x02, 0xF0, 0x90, 0xFE, +-0xC6, 0x74, 0x02, 0xF0, 0xA3, 0x74, 0x0F, 0xF0, +-0x90, 0xFE, 0xC0, 0x74, 0xF4, 0xF0, 0x74, 0x00, +-0xA3, 0xF0, 0x90, 0xFE, 0x68, 0x74, 0x21, 0xF0, +-0x90, 0xFE, 0x64, 0x74, 0x70, 0x45, 0x4E, 0xF0, +-0x90, 0xFE, 0x64, 0x74, 0x30, 0x45, 0x4E, 0xF0, +-0x30, 0x06, 0x07, 0x90, 0xFF, 0x09, 0xE0, 0x30, +-0xE5, 0xFC, 0x90, 0xFE, 0x6E, 0x74, 0x51, 0xF0, +-0x90, 0xFE, 0xC4, 0x74, 0x21, 0xF0, 0xC2, 0x09, +-0x12, 0xE7, 0xB0, 0x20, 0x08, 0x0E, 0x12, 0xE7, +-0xBC, 0x30, 0x3E, 0xF7, 0x90, 0xFE, 0xD8, 0x74, +-0x01, 0xF0, 0xD2, 0x09, 0x30, 0x09, 0x03, 0x7F, +-0x00, 0x22, 0x12, 0xE7, 0xB0, 0x20, 0x36, 0x11, +-0x20, 0x37, 0x0E, 0x12, 0xE7, 0xBC, 0x30, 0x3E, +-0xF4, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xD2, +-0x37, 0x30, 0x37, 0x03, 0x7F, 0x00, 0x22, 0x90, +-0xFE, 0x64, 0x74, 0x10, 0x45, 0x4E, 0xF0, 0x90, +-0xFE, 0x64, 0x74, 0x00, 0x45, 0x4E, 0xF0, 0x12, +-0x2F, 0x65, 0x12, 0x2F, 0x68, 0xBF, 0x00, 0x09, +-0x74, 0x02, 0x90, 0xEB, 0xC2, 0xF0, 0x7F, 0x00, +-0x22, 0x12, 0x2F, 0x6B, 0xBF, 0x00, 0x0F, 0x12, +-0x2F, 0x6E, 0xBF, 0x00, 0x09, 0x74, 0x01, 0x90, +-0xEB, 0xC2, 0xF0, 0x7F, 0x00, 0x22, 0x30, 0x06, +-0x0A, 0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0, 0xA3, +-0x74, 0x00, 0xF0, 0x7F, 0x01, 0x22, 0x12, 0xE3, +-0xAA, 0x74, 0x01, 0x90, 0xE9, 0xCB, 0xF0, 0xE5, +-0x3E, 0xC3, 0x13, 0x90, 0xE9, 0xCA, 0xF0, 0xC0, +-0xE0, 0x75, 0xF0, 0x02, 0xC0, 0xF0, 0x12, 0xE2, +-0x2F, 0xEF, 0x70, 0x21, 0x20, 0x37, 0x07, 0x20, +-0x09, 0x04, 0xD0, 0xF0, 0x80, 0x05, 0xD0, 0xF0, +-0xD5, 0xF0, 0xE9, 0xD0, 0xE0, 0x90, 0xFF, 0x28, +-0xE0, 0x30, 0xE7, 0xFC, 0x90, 0xFF, 0x28, 0xE0, +-0x44, 0x01, 0xF0, 0xC3, 0x22, 0xD0, 0xF0, 0x90, +-0xE9, 0xD2, 0xE0, 0x24, 0x01, 0xF0, 0x90, 0xE9, +-0xD1, 0xE0, 0x34, 0x00, 0xF0, 0x90, 0xE9, 0xD0, +-0xE0, 0x34, 0x00, 0xF0, 0xD0, 0xE0, 0x14, 0x70, +-0xB6, 0x75, 0x3C, 0x00, 0x75, 0x3D, 0x00, 0x75, +-0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22, 0xC2, +-0x08, 0xC2, 0x36, 0xC2, 0x37, 0x90, 0xFE, 0x68, +-0x74, 0x31, 0xF0, 0x90, 0xE9, 0xD0, 0xE0, 0xF8, +-0xA3, 0xE0, 0xF9, 0xA3, 0xE0, 0x90, 0xFE, 0x6B, +-0xF0, 0xA3, 0xE9, 0xF0, 0xA3, 0xE8, 0xF0, 0x90, +-0xFE, 0x6F, 0x74, 0x0F, 0xF0, 0x90, 0xFE, 0x70, +-0xE0, 0x54, 0xFC, 0x44, 0x22, 0xF0, 0x90, 0xE9, +-0xCB, 0xE0, 0x70, 0x0C, 0x90, 0xFE, 0xC0, 0x74, +-0xF4, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0x80, 0x0A, +-0x90, 0xFE, 0xC0, 0x74, 0xF0, 0xF0, 0xA3, 0x74, +-0x00, 0xF0, 0x90, 0xFE, 0x64, 0x74, 0xF0, 0x45, +-0x4E, 0xF0, 0x90, 0xFE, 0x64, 0x74, 0xB0, 0x45, +-0x4E, 0xF0, 0x90, 0xFE, 0x6E, 0x74, 0x81, 0xF0, +-0x90, 0xE9, 0xCB, 0xE0, 0x70, 0x0D, 0x90, 0xFE, +-0xC6, 0x74, 0x02, 0xF0, 0xA3, 0x74, 0x0F, 0xF0, +-0x02, 0xE3, 0x56, 0x20, 0x2D, 0x03, 0x02, 0xE2, +-0xEF, 0x90, 0xFE, 0xC6, 0x74, 0x01, 0xF0, 0xA3, +-0x74, 0xFF, 0xF0, 0x90, 0xFF, 0x09, 0x30, 0x0A, +-0x04, 0xE0, 0x30, 0xE1, 0xF9, 0x90, 0xFE, 0xC4, +-0x74, 0x23, 0xF0, 0x12, 0xE7, 0xB0, 0x20, 0x36, +-0x11, 0x20, 0x37, 0x0E, 0x12, 0xE7, 0xBC, 0x30, +-0x3E, 0xF4, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, +-0xD2, 0x37, 0x30, 0x37, 0x02, 0x61, 0xA7, 0x90, +-0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, +-0x23, 0x74, 0x80, 0xF0, 0x02, 0xE3, 0x3F, 0x90, +-0xFE, 0xC6, 0xE4, 0xF0, 0xA3, 0x74, 0x3F, 0xF0, +-0x78, 0x08, 0xC0, 0x00, 0xC2, 0x36, 0xC2, 0x37, +-0x90, 0xFF, 0x09, 0x30, 0x0A, 0x04, 0xE0, 0x30, +-0xE1, 0xF9, 0x90, 0xFE, 0xC4, 0x74, 0x23, 0xF0, +-0x12, 0xE7, 0xB0, 0x20, 0x36, 0x11, 0x20, 0x37, +-0x0E, 0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF4, 0x90, +-0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x37, 0x90, +-0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, +-0x23, 0x74, 0x80, 0xF0, 0x30, 0x37, 0x04, 0xD0, +-0x00, 0x80, 0x6C, 0xD0, 0x00, 0xD8, 0xBB, 0xC2, +-0x36, 0xC2, 0x37, 0x90, 0xFE, 0xC6, 0xE4, 0xF0, +-0xA3, 0x74, 0x0F, 0xF0, 0x90, 0xFE, 0xC0, 0x74, +-0xF6, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0x90, 0xFE, +-0xC4, 0x74, 0x23, 0xF0, 0x12, 0xE7, 0xB0, 0x20, +-0x36, 0x11, 0x20, 0x37, 0x0E, 0x12, 0xE7, 0xBC, +-0x30, 0x3E, 0xF4, 0x90, 0xFE, 0xD8, 0x74, 0x01, +-0xF0, 0xD2, 0x37, 0x30, 0x37, 0x02, 0x80, 0x2F, +-0xC2, 0x09, 0x12, 0xE7, 0xB0, 0x20, 0x08, 0x0E, +-0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF7, 0x90, 0xFE, +-0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x09, 0x30, 0x09, +-0x02, 0x80, 0x14, 0x90, 0xFE, 0x64, 0x74, 0x90, +-0x45, 0x4E, 0xF0, 0x90, 0xFE, 0x64, 0x74, 0x80, +-0x45, 0x4E, 0xF0, 0x12, 0x2F, 0x59, 0x22, 0x7F, +-0x00, 0x22, 0x90, 0xF6, 0x00, 0x7F, 0x06, 0x74, +-0xFF, 0xF0, 0xA3, 0xDF, 0xFC, 0x7B, 0x02, 0x7C, +-0xE9, 0x7D, 0xD3, 0x7E, 0xF6, 0x7F, 0x06, 0x12, +-0x2F, 0x71, 0x7B, 0x02, 0x7C, 0xE9, 0x7D, 0xD3, +-0x7E, 0xF6, 0x7F, 0x0B, 0x12, 0x2F, 0x71, 0x22, +-0x90, 0xFE, 0xC6, 0xE4, 0xF0, 0xA3, 0x74, 0x0F, +-0xF0, 0x90, 0xFE, 0x6F, 0xF0, 0x90, 0xFE, 0x70, +-0xE0, 0x54, 0xFC, 0xF0, 0x90, 0xFE, 0xC0, 0x74, +-0xF6, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0x90, 0xFE, +-0x68, 0x74, 0x21, 0xF0, 0x90, 0xFE, 0x66, 0xE0, +-0x54, 0xEF, 0xF0, 0x90, 0xE9, 0xD3, 0xE0, 0xF5, +-0x08, 0xA3, 0xE0, 0xF5, 0x09, 0x90, 0xFF, 0x09, +-0xE0, 0x30, 0xE5, 0xFC, 0xE4, 0xF5, 0x10, 0x7E, +-0xF4, 0x7F, 0x00, 0xC0, 0x06, 0xC0, 0x07, 0xC2, +-0x36, 0xC2, 0x37, 0xC2, 0x09, 0x90, 0xE9, 0xCD, +-0xE0, 0xF8, 0xA3, 0xE0, 0xF9, 0xA3, 0xE0, 0x90, +-0xFE, 0x6B, 0xF0, 0xA3, 0xE9, 0xF0, 0xA3, 0xE8, +-0xF0, 0x90, 0xFE, 0x6E, 0x74, 0x71, 0xF0, 0x90, +-0xFE, 0xC4, 0x74, 0x21, 0xF0, 0x90, 0xFE, 0x65, +-0x12, 0xE7, 0xB0, 0xE0, 0x20, 0xE4, 0x11, 0x12, +-0xE7, 0xBC, 0x30, 0x3E, 0xF6, 0x90, 0xFE, 0xD8, +-0x74, 0x01, 0xF0, 0xD2, 0x09, 0x02, 0xE4, 0x72, +-0x74, 0x10, 0xF0, 0x12, 0xE7, 0xB0, 0x20, 0x36, +-0x11, 0x20, 0x37, 0x0E, 0x12, 0xE7, 0xBC, 0x30, +-0x3E, 0xF4, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, +-0xD2, 0x37, 0x20, 0x09, 0x05, 0x20, 0x37, 0x02, +-0x80, 0x10, 0x90, 0xFE, 0x66, 0xE0, 0x44, 0x10, +-0xF0, 0x12, 0x2F, 0x5C, 0xD0, 0x07, 0xD0, 0x06, +-0xC3, 0x22, 0xD0, 0x07, 0xD0, 0x06, 0x7B, 0x10, +-0x7C, 0xF6, 0x7D, 0x00, 0x12, 0x2F, 0x71, 0x05, +-0x10, 0xC3, 0xE5, 0x09, 0x94, 0x01, 0xF5, 0x09, +-0xE5, 0x08, 0x94, 0x00, 0xF5, 0x08, 0x45, 0x09, +-0x70, 0x03, 0x02, 0xE4, 0xEF, 0x90, 0xE9, 0xCF, +-0xE0, 0x24, 0x20, 0xF0, 0x90, 0xE9, 0xCE, 0xE0, +-0x34, 0x00, 0xF0, 0x90, 0xE9, 0xCD, 0xE0, 0x34, +-0x00, 0xF0, 0xC3, 0xEF, 0x24, 0x10, 0xFF, 0xEE, +-0x34, 0x00, 0xFE, 0xE5, 0x10, 0x64, 0x20, 0x60, +-0x03, 0x02, 0xE4, 0x13, 0x90, 0xFF, 0x2A, 0x74, +-0x02, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0x75, 0x10, +-0x00, 0x7E, 0xF4, 0x7F, 0x00, 0x90, 0xFF, 0x09, +-0xE0, 0x30, 0xE5, 0xFC, 0x02, 0xE4, 0x13, 0xE5, +-0x10, 0x60, 0x17, 0x7E, 0x00, 0x7F, 0x00, 0x78, +-0x04, 0xC3, 0x33, 0xFF, 0xEE, 0x33, 0xFE, 0xEF, +-0xD8, 0xF8, 0x90, 0xFF, 0x2A, 0xEE, 0xF0, 0xA3, +-0xEF, 0xF0, 0x90, 0xFE, 0x66, 0xE0, 0x44, 0x10, +-0xF0, 0x12, 0x2F, 0x5C, 0x78, 0x00, 0x88, 0x3C, +-0x88, 0x3D, 0x88, 0x3E, 0x88, 0x3F, 0xD3, 0x22, +-0x12, 0x2F, 0x5F, 0x12, 0x2F, 0x62, 0x90, 0xFE, +-0xC6, 0xE4, 0xF0, 0xA3, 0x74, 0x0F, 0xF0, 0x90, +-0xFE, 0x6F, 0xF0, 0x90, 0xFE, 0x70, 0xE0, 0x54, +-0xFC, 0xF0, 0x90, 0xFE, 0xC0, 0x74, 0xF6, 0xF0, +-0xA3, 0x74, 0x00, 0xF0, 0x90, 0xFE, 0x68, 0x74, +-0x31, 0xF0, 0x90, 0xE9, 0xD3, 0xE0, 0xF8, 0xC0, +-0x00, 0xC2, 0x08, 0xC2, 0x36, 0xC2, 0x37, 0x90, +-0xE9, 0xD0, 0xE0, 0xF8, 0xA3, 0xE0, 0xF9, 0xA3, +-0xE0, 0x90, 0xFE, 0x6B, 0xF0, 0xA3, 0xE9, 0xF0, +-0xA3, 0xE8, 0xF0, 0x90, 0xFE, 0x6E, 0x74, 0x81, +-0xF0, 0x90, 0xFE, 0xC4, 0x74, 0x23, 0xF0, 0x12, +-0xE7, 0xB0, 0x20, 0x36, 0x11, 0x20, 0x37, 0x0E, +-0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF4, 0x90, 0xFE, +-0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x37, 0x30, 0x37, +-0x07, 0xD0, 0x00, 0x12, 0x2F, 0x5C, 0xC3, 0x22, +-0xC2, 0x09, 0x12, 0xE7, 0xB0, 0x20, 0x08, 0x0E, +-0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF7, 0x90, 0xFE, +-0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x09, 0x20, 0x09, +-0xE0, 0x90, 0xE9, 0xD2, 0xE0, 0x24, 0x01, 0xF0, +-0x90, 0xE9, 0xD1, 0xE0, 0x34, 0x00, 0xF0, 0x90, +-0xE9, 0xD0, 0xE0, 0x34, 0x00, 0xF0, 0xD0, 0x00, +-0x18, 0xE8, 0x60, 0x03, 0x02, 0xE5, 0x4F, 0x12, +-0x2F, 0x5C, 0x75, 0x3C, 0x00, 0x75, 0x3D, 0x00, +-0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22, +-0x90, 0xE9, 0xD0, 0xE0, 0xF8, 0xA3, 0xE0, 0xF9, +-0xA3, 0xE0, 0x90, 0xFE, 0x6B, 0xF0, 0xA3, 0xE9, +-0xF0, 0xA3, 0xE8, 0xF0, 0x90, 0xFE, 0x68, 0x74, +-0x00, 0xF0, 0xC2, 0x08, 0x90, 0xFE, 0x6E, 0x74, +-0xB1, 0xF0, 0xC2, 0x09, 0x12, 0xE7, 0xB0, 0x20, +-0x08, 0x0E, 0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF7, +-0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x09, +-0x20, 0x09, 0x1E, 0x90, 0xFE, 0x70, 0xE0, 0x44, +-0x10, 0xF0, 0x54, 0xEF, 0xF0, 0x12, 0x2F, 0x59, +-0xEF, 0x60, 0x0E, 0x75, 0x3C, 0x00, 0x75, 0x3D, +-0x00, 0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, +-0x22, 0xC3, 0x22, 0x7B, 0x03, 0x7C, 0xE9, 0x7D, +-0xCD, 0x7E, 0xE9, 0x7F, 0xD7, 0x12, 0x2F, 0x71, +-0x12, 0xE3, 0xAA, 0x90, 0xE9, 0xD5, 0xE0, 0x60, +-0x12, 0xF9, 0x12, 0xE7, 0x17, 0x40, 0x01, 0x22, +-0x90, 0xF6, 0x00, 0x78, 0x06, 0x74, 0xFF, 0xF0, +-0xA3, 0xD8, 0xFC, 0x74, 0x01, 0x90, 0xE9, 0xCB, +-0xF0, 0xE5, 0x3E, 0xC3, 0x13, 0x90, 0xE9, 0xCA, +-0xF0, 0xC0, 0xE0, 0x75, 0xF0, 0x02, 0xC0, 0xF0, +-0x12, 0xE2, 0x2F, 0xEF, 0x70, 0x21, 0x20, 0x37, +-0x07, 0x20, 0x09, 0x04, 0xD0, 0xF0, 0x80, 0x05, +-0xD0, 0xF0, 0xD5, 0xF0, 0xE9, 0xD0, 0xE0, 0x90, +-0xFF, 0x28, 0xE0, 0x30, 0xE7, 0xFC, 0x90, 0xFF, +-0x28, 0xE0, 0x44, 0x01, 0xF0, 0xC3, 0x22, 0xD0, +-0xF0, 0x90, 0xE9, 0xD2, 0xE0, 0x24, 0x01, 0xF0, +-0x90, 0xE9, 0xD1, 0xE0, 0x34, 0x00, 0xF0, 0x90, +-0xE9, 0xD0, 0xE0, 0x34, 0x00, 0xF0, 0xD0, 0xE0, +-0x14, 0x70, 0xB6, 0x90, 0xE9, 0xD5, 0xE0, 0xF8, +-0x90, 0xE9, 0xCA, 0xE0, 0x28, 0xF5, 0xF0, 0xC3, +-0x74, 0x20, 0x95, 0xF0, 0x60, 0x22, 0xF9, 0x90, +-0xE9, 0xCA, 0xE0, 0xF5, 0xF0, 0x90, 0xE9, 0xCF, +-0xE0, 0x25, 0xF0, 0xF0, 0x90, 0xE9, 0xCE, 0xE0, +-0x34, 0x00, 0xF0, 0x90, 0xE9, 0xCD, 0xE0, 0x34, +-0x00, 0xF0, 0x12, 0xE7, 0x17, 0x40, 0x01, 0x22, +-0x90, 0xE9, 0xD6, 0xE0, 0x70, 0x13, 0x7B, 0x03, +-0x7C, 0xE9, 0x7D, 0xD7, 0x7E, 0xE9, 0x7F, 0xD0, +-0x12, 0x2F, 0x71, 0x12, 0xE5, 0xE0, 0x40, 0x01, +-0x22, 0x75, 0x3C, 0x00, 0x75, 0x3D, 0x00, 0x75, +-0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22, 0x90, +-0xE9, 0xD6, 0xE0, 0x60, 0x18, 0x74, 0xFF, 0x90, +-0xF4, 0x00, 0x78, 0xFF, 0xF0, 0xA3, 0x18, 0xB8, +-0x00, 0xFA, 0x78, 0xFF, 0xF0, 0xA3, 0x18, 0xB8, +-0x00, 0xFA, 0xF0, 0xA3, 0xF0, 0xC0, 0x01, 0x12, +-0xE7, 0x70, 0x40, 0x04, 0xD0, 0x01, 0xC3, 0x22, +-0x90, 0xE9, 0xCF, 0xE0, 0x24, 0x01, 0xF0, 0x90, +-0xE9, 0xCE, 0xE0, 0x34, 0x00, 0xF0, 0x90, 0xE9, +-0xCD, 0xE0, 0x34, 0x00, 0xF0, 0x90, 0xE9, 0xD2, +-0xE0, 0x24, 0x01, 0xF0, 0x90, 0xE9, 0xD1, 0xE0, +-0x34, 0x00, 0xF0, 0x90, 0xE9, 0xD0, 0xE0, 0x34, +-0x00, 0xF0, 0xD0, 0x01, 0xD9, 0xC7, 0xD3, 0x22, +-0xC2, 0x06, 0x90, 0xE9, 0xD6, 0xE0, 0x70, 0x28, +-0x12, 0xE0, 0xD8, 0xEF, 0x60, 0x03, 0x02, 0xE7, +-0xA0, 0x90, 0xEB, 0xC2, 0xE0, 0x60, 0x17, 0x64, +-0x02, 0x60, 0x15, 0x90, 0xF6, 0x00, 0x78, 0x06, +-0x74, 0xFF, 0xF0, 0xA3, 0xD8, 0xFC, 0x74, 0xF0, +-0x90, 0xF6, 0x04, 0xF0, 0x80, 0x02, 0xC3, 0x22, +-0xE4, 0x90, 0xE9, 0xCB, 0xF0, 0x12, 0xE2, 0x2F, +-0xEF, 0x70, 0x03, 0x02, 0xE7, 0x81, 0xD3, 0x22, +-0xC2, 0x3E, 0x75, 0x7C, 0x00, 0x75, 0x7D, 0x00, +-0x75, 0x7E, 0x00, 0x22, 0x05, 0x7C, 0xE5, 0x7C, +-0x70, 0x14, 0x05, 0x7D, 0xE5, 0x7D, 0x70, 0x04, +-0x05, 0x7E, 0x80, 0x0A, 0xB4, 0x17, 0x07, 0xE5, +-0x7E, 0xB4, 0x06, 0x02, 0xD2, 0x3E, 0x22, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +-0x58, 0x44, 0x2D, 0x52, 0x57, 0x20, 0x20, 0x20, +-0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30 }; +- +diff --git a/drivers/staging/line6/Kconfig b/drivers/staging/line6/Kconfig +index 43120ff..b635436 100644 +--- a/drivers/staging/line6/Kconfig ++++ b/drivers/staging/line6/Kconfig +@@ -23,32 +23,6 @@ menuconfig LINE6_USB + + if LINE6_USB + +-config LINE6_USB_DEBUG +- bool "print debug messages" +- default n +- help +- Say Y here to write debug messages to the syslog. +- +- If unsure, say N. +- +-config LINE6_USB_DUMP_CTRL +- bool "dump control messages" +- default n +- help +- Say Y here to write control messages sent to and received from +- Line6 devices to the syslog. +- +- If unsure, say N. +- +-config LINE6_USB_DUMP_MIDI +- bool "dump MIDI messages" +- default n +- help +- Say Y here to write MIDI messages sent to and received from +- Line6 devices to the syslog. +- +- If unsure, say N. +- + config LINE6_USB_DUMP_PCM + bool "dump PCM data" + default n +@@ -59,17 +33,6 @@ config LINE6_USB_DUMP_PCM + + If unsure, say N. + +-config LINE6_USB_RAW +- bool "raw data communication" +- default n +- help +- Say Y here to create special files which allow to send raw data +- to the device. This bypasses any sanity checks, so if you discover +- the code to erase the firmware, feel free to render your device +- useless, but only after reading the GPL section "NO WARRANTY". +- +- If unsure, say N. +- + config LINE6_USB_IMPULSE_RESPONSE + bool "measure impulse response" + default n +diff --git a/drivers/staging/line6/Makefile b/drivers/staging/line6/Makefile +index de6bd12..ae5c374 100644 +--- a/drivers/staging/line6/Makefile ++++ b/drivers/staging/line6/Makefile +@@ -3,13 +3,12 @@ obj-$(CONFIG_LINE6_USB) += line6usb.o + line6usb-y := \ + audio.o \ + capture.o \ +- control.o \ + driver.o \ +- dumprequest.o \ + midi.o \ + midibuf.o \ + pcm.o \ + playback.o \ + pod.o \ + toneport.o \ +- variax.o ++ variax.o \ ++ podhd.o +diff --git a/drivers/staging/line6/audio.c b/drivers/staging/line6/audio.c +index 8e73983..a92e21f 100644 +--- a/drivers/staging/line6/audio.c ++++ b/drivers/staging/line6/audio.c +@@ -16,20 +16,16 @@ + #include "driver.h" + #include "audio.h" + +-static int line6_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; +-static char *line6_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; +- + /* + Initialize the Line6 USB audio system. + */ + int line6_init_audio(struct usb_line6 *line6) + { +- static int dev; + struct snd_card *card; + int err; + +- err = snd_card_create(line6_index[dev], line6_id[dev], THIS_MODULE, 0, +- &card); ++ err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, ++ THIS_MODULE, 0, &card); + if (err < 0) + return err; + +diff --git a/drivers/staging/line6/capture.c b/drivers/staging/line6/capture.c +index 9647154..389c41f 100644 +--- a/drivers/staging/line6/capture.c ++++ b/drivers/staging/line6/capture.c +@@ -9,6 +9,7 @@ + * + */ + ++#include + #include + #include + #include +@@ -106,7 +107,7 @@ void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm) + Wait until unlinking of all currently active capture URBs has been + finished. + */ +-static void wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm) ++void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm) + { + int timeout = HZ; + unsigned int i; +@@ -133,7 +134,7 @@ static void wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm) + void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm) + { + line6_unlink_audio_in_urbs(line6pcm); +- wait_clear_audio_in_urbs(line6pcm); ++ line6_wait_clear_audio_in_urbs(line6pcm); + } + + /* +@@ -192,6 +193,12 @@ void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length) + } + } + ++void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm) ++{ ++ kfree(line6pcm->buffer_in); ++ line6pcm->buffer_in = NULL; ++} ++ + /* + * Callback for completed capture URB. + */ +@@ -243,18 +250,14 @@ static void audio_in_callback(struct urb *urb) + length += fsize; + + /* the following assumes LINE6_ISO_PACKETS == 1: */ +-#if LINE6_BACKUP_MONITOR_SIGNAL +- memcpy(line6pcm->prev_fbuf, fbuf, fsize); +-#else + line6pcm->prev_fbuf = fbuf; +-#endif + line6pcm->prev_fsize = fsize; + + #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE +- if (!(line6pcm->flags & MASK_PCM_IMPULSE)) ++ if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE)) + #endif +- if (test_bit(BIT_PCM_ALSA_CAPTURE, &line6pcm->flags) +- && (fsize > 0)) ++ if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM, ++ &line6pcm->flags) && (fsize > 0)) + line6_capture_copy(line6pcm, fbuf, fsize); + } + +@@ -269,9 +272,10 @@ static void audio_in_callback(struct urb *urb) + submit_audio_in_urb(line6pcm); + + #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE +- if (!(line6pcm->flags & MASK_PCM_IMPULSE)) ++ if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE)) + #endif +- if (test_bit(BIT_PCM_ALSA_CAPTURE, &line6pcm->flags)) ++ if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM, ++ &line6pcm->flags)) + line6_capture_check_period(line6pcm, length); + } + } +@@ -319,10 +323,17 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream, + } + /* -- [FD] end */ + ++ ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER); ++ ++ if (ret < 0) ++ return ret; ++ + ret = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); +- if (ret < 0) ++ if (ret < 0) { ++ line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER); + return ret; ++ } + + line6pcm->period_in = params_period_bytes(hw_params); + return 0; +@@ -331,6 +342,8 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream, + /* hw_free capture callback */ + static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream) + { ++ struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); ++ line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER); + return snd_pcm_lib_free_pages(substream); + } + +@@ -344,7 +357,8 @@ int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd) + #ifdef CONFIG_PM + case SNDRV_PCM_TRIGGER_RESUME: + #endif +- err = line6_pcm_start(line6pcm, MASK_PCM_ALSA_CAPTURE); ++ err = line6_pcm_acquire(line6pcm, ++ LINE6_BIT_PCM_ALSA_CAPTURE_STREAM); + + if (err < 0) + return err; +@@ -355,7 +369,8 @@ int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd) + #ifdef CONFIG_PM + case SNDRV_PCM_TRIGGER_SUSPEND: + #endif +- err = line6_pcm_stop(line6pcm, MASK_PCM_ALSA_CAPTURE); ++ err = line6_pcm_release(line6pcm, ++ LINE6_BIT_PCM_ALSA_CAPTURE_STREAM); + + if (err < 0) + return err; +diff --git a/drivers/staging/line6/capture.h b/drivers/staging/line6/capture.h +index a7509fb..4157bcb 100644 +--- a/drivers/staging/line6/capture.h ++++ b/drivers/staging/line6/capture.h +@@ -24,10 +24,12 @@ extern void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, + extern void line6_capture_check_period(struct snd_line6_pcm *line6pcm, + int length); + extern int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm); ++extern void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm); + extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm); + extern void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm); + extern void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm + *line6pcm); ++extern void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm); + extern int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd); + + #endif +diff --git a/drivers/staging/line6/config.h b/drivers/staging/line6/config.h +deleted file mode 100644 +index f8a5149..0000000 +--- a/drivers/staging/line6/config.h ++++ /dev/null +@@ -1,48 +0,0 @@ +-/* +- * Line6 Linux USB driver - 0.8.0 +- * +- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) +- * +- * This program is free software; 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. +- * +- */ +- +-#ifndef CONFIG_H +-#define CONFIG_H +- +- +-#ifdef CONFIG_USB_DEBUG +-#define DEBUG 1 +-#endif +- +- +-/* +- * Development tools. +- */ +-#define DO_DEBUG_MESSAGES 0 +-#define DO_DUMP_URB_SEND DO_DEBUG_MESSAGES +-#define DO_DUMP_URB_RECEIVE DO_DEBUG_MESSAGES +-#define DO_DUMP_PCM_SEND 0 +-#define DO_DUMP_PCM_RECEIVE 0 +-#define DO_DUMP_MIDI_SEND DO_DEBUG_MESSAGES +-#define DO_DUMP_MIDI_RECEIVE DO_DEBUG_MESSAGES +-#define DO_DUMP_ANY (DO_DUMP_URB_SEND || DO_DUMP_URB_RECEIVE || \ +- DO_DUMP_PCM_SEND || DO_DUMP_PCM_RECEIVE || \ +- DO_DUMP_MIDI_SEND || DO_DUMP_MIDI_RECEIVE) +-#define CREATE_RAW_FILE 0 +- +-#if DO_DEBUG_MESSAGES +-#define CHECKPOINT printk(KERN_INFO "line6usb: %s (%s:%d)\n", \ +- __func__, __FILE__, __LINE__) +-#endif +- +-#if DO_DEBUG_MESSAGES +-#define DEBUG_MESSAGES(x) (x) +-#else +-#define DEBUG_MESSAGES(x) +-#endif +- +- +-#endif +diff --git a/drivers/staging/line6/control.c b/drivers/staging/line6/control.c +deleted file mode 100644 +index 67e23b6..0000000 +--- a/drivers/staging/line6/control.c ++++ /dev/null +@@ -1,995 +0,0 @@ +-/* +- * Line6 Linux USB driver - 0.9.1beta +- * +- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) +- * +- * This program is free software; 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. +- * +- */ +- +-#include +- +-#include "control.h" +-#include "driver.h" +-#include "pod.h" +-#include "usbdefs.h" +-#include "variax.h" +- +-#define DEVICE_ATTR2(_name1, _name2, _mode, _show, _store) \ +-struct device_attribute dev_attr_##_name1 = __ATTR(_name2, _mode, _show, _store) +- +-#define LINE6_PARAM_R(PREFIX, prefix, type, param) \ +-static ssize_t prefix##_get_##param(struct device *dev, \ +- struct device_attribute *attr, char *buf) \ +-{ \ +- return prefix##_get_param_##type(dev, buf, PREFIX##_##param); \ +-} +- +-#define LINE6_PARAM_RW(PREFIX, prefix, type, param) \ +-LINE6_PARAM_R(PREFIX, prefix, type, param); \ +-static ssize_t prefix##_set_##param(struct device *dev, \ +- struct device_attribute *attr, const char *buf, size_t count) \ +-{ \ +- return prefix##_set_param_##type(dev, buf, count, PREFIX##_##param); \ +-} +- +-#define POD_PARAM_R(type, param) LINE6_PARAM_R(POD, pod, type, param) +-#define POD_PARAM_RW(type, param) LINE6_PARAM_RW(POD, pod, type, param) +-#define VARIAX_PARAM_R(type, param) LINE6_PARAM_R(VARIAX, variax, type, param) +-#define VARIAX_PARAM_RW(type, param) LINE6_PARAM_RW(VARIAX, variax, type, param) +- +-static ssize_t pod_get_param_int(struct device *dev, char *buf, int param) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- int retval = line6_dump_wait_interruptible(&pod->dumpreq); +- if (retval < 0) +- return retval; +- return sprintf(buf, "%d\n", pod->prog_data.control[param]); +-} +- +-static ssize_t pod_set_param_int(struct device *dev, const char *buf, +- size_t count, int param) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- unsigned long value; +- int retval; +- +- retval = strict_strtoul(buf, 10, &value); +- if (retval) +- return retval; +- +- line6_pod_transmit_parameter(pod, param, value); +- return count; +-} +- +-static ssize_t variax_get_param_int(struct device *dev, char *buf, int param) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_variax *variax = usb_get_intfdata(interface); +- int retval = line6_dump_wait_interruptible(&variax->dumpreq); +- if (retval < 0) +- return retval; +- return sprintf(buf, "%d\n", variax->model_data.control[param]); +-} +- +-static ssize_t variax_get_param_float(struct device *dev, char *buf, int param) +-{ +- /* +- We do our own floating point handling here since at the time +- this code was written (Jan 2006) it was highly discouraged to +- use floating point arithmetic in the kernel. If you think that +- this no longer applies, feel free to replace this by generic +- floating point code. +- */ +- +- static const int BIAS = 0x7f; +- static const int OFFSET = 0xf; +- static const int PRECISION = 1000; +- +- int len = 0; +- unsigned part_int, part_frac; +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_variax *variax = usb_get_intfdata(interface); +- const unsigned char *p = variax->model_data.control + param; +- int retval = line6_dump_wait_interruptible(&variax->dumpreq); +- if (retval < 0) +- return retval; +- +- if ((p[0] == 0) && (p[1] == 0) && (p[2] == 0)) +- part_int = part_frac = 0; +- else { +- int exponent = (((p[0] & 0x7f) << 1) | (p[1] >> 7)) - BIAS; +- unsigned mantissa = (p[1] << 8) | p[2] | 0x8000; +- exponent -= OFFSET; +- +- if (exponent >= 0) { +- part_int = mantissa << exponent; +- part_frac = 0; +- } else { +- part_int = mantissa >> -exponent; +- part_frac = (mantissa << (32 + exponent)) & 0xffffffff; +- } +- +- part_frac = +- (part_frac / ((1UL << 31) / (PRECISION / 2 * 10)) + 5) / 10; +- } +- +- len += +- sprintf(buf + len, "%s%d.%03d\n", ((p[0] & 0x80) ? "-" : ""), +- part_int, part_frac); +- return len; +-} +- +-POD_PARAM_RW(int, tweak); +-POD_PARAM_RW(int, wah_position); +-POD_PARAM_RW(int, compression_gain); +-POD_PARAM_RW(int, vol_pedal_position); +-POD_PARAM_RW(int, compression_threshold); +-POD_PARAM_RW(int, pan); +-POD_PARAM_RW(int, amp_model_setup); +-POD_PARAM_RW(int, amp_model); +-POD_PARAM_RW(int, drive); +-POD_PARAM_RW(int, bass); +-POD_PARAM_RW(int, mid); +-POD_PARAM_RW(int, lowmid); +-POD_PARAM_RW(int, treble); +-POD_PARAM_RW(int, highmid); +-POD_PARAM_RW(int, chan_vol); +-POD_PARAM_RW(int, reverb_mix); +-POD_PARAM_RW(int, effect_setup); +-POD_PARAM_RW(int, band_1_frequency); +-POD_PARAM_RW(int, presence); +-POD_PARAM_RW(int, treble__bass); +-POD_PARAM_RW(int, noise_gate_enable); +-POD_PARAM_RW(int, gate_threshold); +-POD_PARAM_RW(int, gate_decay_time); +-POD_PARAM_RW(int, stomp_enable); +-POD_PARAM_RW(int, comp_enable); +-POD_PARAM_RW(int, stomp_time); +-POD_PARAM_RW(int, delay_enable); +-POD_PARAM_RW(int, mod_param_1); +-POD_PARAM_RW(int, delay_param_1); +-POD_PARAM_RW(int, delay_param_1_note_value); +-POD_PARAM_RW(int, band_2_frequency__bass); +-POD_PARAM_RW(int, delay_param_2); +-POD_PARAM_RW(int, delay_volume_mix); +-POD_PARAM_RW(int, delay_param_3); +-POD_PARAM_RW(int, reverb_enable); +-POD_PARAM_RW(int, reverb_type); +-POD_PARAM_RW(int, reverb_decay); +-POD_PARAM_RW(int, reverb_tone); +-POD_PARAM_RW(int, reverb_pre_delay); +-POD_PARAM_RW(int, reverb_pre_post); +-POD_PARAM_RW(int, band_2_frequency); +-POD_PARAM_RW(int, band_3_frequency__bass); +-POD_PARAM_RW(int, wah_enable); +-POD_PARAM_RW(int, modulation_lo_cut); +-POD_PARAM_RW(int, delay_reverb_lo_cut); +-POD_PARAM_RW(int, volume_pedal_minimum); +-POD_PARAM_RW(int, eq_pre_post); +-POD_PARAM_RW(int, volume_pre_post); +-POD_PARAM_RW(int, di_model); +-POD_PARAM_RW(int, di_delay); +-POD_PARAM_RW(int, mod_enable); +-POD_PARAM_RW(int, mod_param_1_note_value); +-POD_PARAM_RW(int, mod_param_2); +-POD_PARAM_RW(int, mod_param_3); +-POD_PARAM_RW(int, mod_param_4); +-POD_PARAM_RW(int, mod_param_5); +-POD_PARAM_RW(int, mod_volume_mix); +-POD_PARAM_RW(int, mod_pre_post); +-POD_PARAM_RW(int, modulation_model); +-POD_PARAM_RW(int, band_3_frequency); +-POD_PARAM_RW(int, band_4_frequency__bass); +-POD_PARAM_RW(int, mod_param_1_double_precision); +-POD_PARAM_RW(int, delay_param_1_double_precision); +-POD_PARAM_RW(int, eq_enable); +-POD_PARAM_RW(int, tap); +-POD_PARAM_RW(int, volume_tweak_pedal_assign); +-POD_PARAM_RW(int, band_5_frequency); +-POD_PARAM_RW(int, tuner); +-POD_PARAM_RW(int, mic_selection); +-POD_PARAM_RW(int, cabinet_model); +-POD_PARAM_RW(int, stomp_model); +-POD_PARAM_RW(int, roomlevel); +-POD_PARAM_RW(int, band_4_frequency); +-POD_PARAM_RW(int, band_6_frequency); +-POD_PARAM_RW(int, stomp_param_1_note_value); +-POD_PARAM_RW(int, stomp_param_2); +-POD_PARAM_RW(int, stomp_param_3); +-POD_PARAM_RW(int, stomp_param_4); +-POD_PARAM_RW(int, stomp_param_5); +-POD_PARAM_RW(int, stomp_param_6); +-POD_PARAM_RW(int, amp_switch_select); +-POD_PARAM_RW(int, delay_param_4); +-POD_PARAM_RW(int, delay_param_5); +-POD_PARAM_RW(int, delay_pre_post); +-POD_PARAM_RW(int, delay_model); +-POD_PARAM_RW(int, delay_verb_model); +-POD_PARAM_RW(int, tempo_msb); +-POD_PARAM_RW(int, tempo_lsb); +-POD_PARAM_RW(int, wah_model); +-POD_PARAM_RW(int, bypass_volume); +-POD_PARAM_RW(int, fx_loop_on_off); +-POD_PARAM_RW(int, tweak_param_select); +-POD_PARAM_RW(int, amp1_engage); +-POD_PARAM_RW(int, band_1_gain); +-POD_PARAM_RW(int, band_2_gain__bass); +-POD_PARAM_RW(int, band_2_gain); +-POD_PARAM_RW(int, band_3_gain__bass); +-POD_PARAM_RW(int, band_3_gain); +-POD_PARAM_RW(int, band_4_gain__bass); +-POD_PARAM_RW(int, band_5_gain__bass); +-POD_PARAM_RW(int, band_4_gain); +-POD_PARAM_RW(int, band_6_gain__bass); +-VARIAX_PARAM_R(int, body); +-VARIAX_PARAM_R(int, pickup1_enable); +-VARIAX_PARAM_R(int, pickup1_type); +-VARIAX_PARAM_R(float, pickup1_position); +-VARIAX_PARAM_R(float, pickup1_angle); +-VARIAX_PARAM_R(float, pickup1_level); +-VARIAX_PARAM_R(int, pickup2_enable); +-VARIAX_PARAM_R(int, pickup2_type); +-VARIAX_PARAM_R(float, pickup2_position); +-VARIAX_PARAM_R(float, pickup2_angle); +-VARIAX_PARAM_R(float, pickup2_level); +-VARIAX_PARAM_R(int, pickup_phase); +-VARIAX_PARAM_R(float, capacitance); +-VARIAX_PARAM_R(float, tone_resistance); +-VARIAX_PARAM_R(float, volume_resistance); +-VARIAX_PARAM_R(int, taper); +-VARIAX_PARAM_R(float, tone_dump); +-VARIAX_PARAM_R(int, save_tone); +-VARIAX_PARAM_R(float, volume_dump); +-VARIAX_PARAM_R(int, tuning_enable); +-VARIAX_PARAM_R(int, tuning6); +-VARIAX_PARAM_R(int, tuning5); +-VARIAX_PARAM_R(int, tuning4); +-VARIAX_PARAM_R(int, tuning3); +-VARIAX_PARAM_R(int, tuning2); +-VARIAX_PARAM_R(int, tuning1); +-VARIAX_PARAM_R(float, detune6); +-VARIAX_PARAM_R(float, detune5); +-VARIAX_PARAM_R(float, detune4); +-VARIAX_PARAM_R(float, detune3); +-VARIAX_PARAM_R(float, detune2); +-VARIAX_PARAM_R(float, detune1); +-VARIAX_PARAM_R(float, mix6); +-VARIAX_PARAM_R(float, mix5); +-VARIAX_PARAM_R(float, mix4); +-VARIAX_PARAM_R(float, mix3); +-VARIAX_PARAM_R(float, mix2); +-VARIAX_PARAM_R(float, mix1); +-VARIAX_PARAM_R(int, pickup_wiring); +- +-static DEVICE_ATTR(tweak, S_IWUSR | S_IRUGO, pod_get_tweak, pod_set_tweak); +-static DEVICE_ATTR(wah_position, S_IWUSR | S_IRUGO, pod_get_wah_position, +- pod_set_wah_position); +-static DEVICE_ATTR(compression_gain, S_IWUSR | S_IRUGO, +- pod_get_compression_gain, pod_set_compression_gain); +-static DEVICE_ATTR(vol_pedal_position, S_IWUSR | S_IRUGO, +- pod_get_vol_pedal_position, pod_set_vol_pedal_position); +-static DEVICE_ATTR(compression_threshold, S_IWUSR | S_IRUGO, +- pod_get_compression_threshold, +- pod_set_compression_threshold); +-static DEVICE_ATTR(pan, S_IWUSR | S_IRUGO, pod_get_pan, pod_set_pan); +-static DEVICE_ATTR(amp_model_setup, S_IWUSR | S_IRUGO, pod_get_amp_model_setup, +- pod_set_amp_model_setup); +-static DEVICE_ATTR(amp_model, S_IWUSR | S_IRUGO, pod_get_amp_model, +- pod_set_amp_model); +-static DEVICE_ATTR(drive, S_IWUSR | S_IRUGO, pod_get_drive, pod_set_drive); +-static DEVICE_ATTR(bass, S_IWUSR | S_IRUGO, pod_get_bass, pod_set_bass); +-static DEVICE_ATTR(mid, S_IWUSR | S_IRUGO, pod_get_mid, pod_set_mid); +-static DEVICE_ATTR(lowmid, S_IWUSR | S_IRUGO, pod_get_lowmid, pod_set_lowmid); +-static DEVICE_ATTR(treble, S_IWUSR | S_IRUGO, pod_get_treble, pod_set_treble); +-static DEVICE_ATTR(highmid, S_IWUSR | S_IRUGO, pod_get_highmid, +- pod_set_highmid); +-static DEVICE_ATTR(chan_vol, S_IWUSR | S_IRUGO, pod_get_chan_vol, +- pod_set_chan_vol); +-static DEVICE_ATTR(reverb_mix, S_IWUSR | S_IRUGO, pod_get_reverb_mix, +- pod_set_reverb_mix); +-static DEVICE_ATTR(effect_setup, S_IWUSR | S_IRUGO, pod_get_effect_setup, +- pod_set_effect_setup); +-static DEVICE_ATTR(band_1_frequency, S_IWUSR | S_IRUGO, +- pod_get_band_1_frequency, pod_set_band_1_frequency); +-static DEVICE_ATTR(presence, S_IWUSR | S_IRUGO, pod_get_presence, +- pod_set_presence); +-static DEVICE_ATTR2(treble__bass, treble, S_IWUSR | S_IRUGO, +- pod_get_treble__bass, pod_set_treble__bass); +-static DEVICE_ATTR(noise_gate_enable, S_IWUSR | S_IRUGO, +- pod_get_noise_gate_enable, pod_set_noise_gate_enable); +-static DEVICE_ATTR(gate_threshold, S_IWUSR | S_IRUGO, pod_get_gate_threshold, +- pod_set_gate_threshold); +-static DEVICE_ATTR(gate_decay_time, S_IWUSR | S_IRUGO, pod_get_gate_decay_time, +- pod_set_gate_decay_time); +-static DEVICE_ATTR(stomp_enable, S_IWUSR | S_IRUGO, pod_get_stomp_enable, +- pod_set_stomp_enable); +-static DEVICE_ATTR(comp_enable, S_IWUSR | S_IRUGO, pod_get_comp_enable, +- pod_set_comp_enable); +-static DEVICE_ATTR(stomp_time, S_IWUSR | S_IRUGO, pod_get_stomp_time, +- pod_set_stomp_time); +-static DEVICE_ATTR(delay_enable, S_IWUSR | S_IRUGO, pod_get_delay_enable, +- pod_set_delay_enable); +-static DEVICE_ATTR(mod_param_1, S_IWUSR | S_IRUGO, pod_get_mod_param_1, +- pod_set_mod_param_1); +-static DEVICE_ATTR(delay_param_1, S_IWUSR | S_IRUGO, pod_get_delay_param_1, +- pod_set_delay_param_1); +-static DEVICE_ATTR(delay_param_1_note_value, S_IWUSR | S_IRUGO, +- pod_get_delay_param_1_note_value, +- pod_set_delay_param_1_note_value); +-static DEVICE_ATTR2(band_2_frequency__bass, band_2_frequency, S_IWUSR | S_IRUGO, +- pod_get_band_2_frequency__bass, +- pod_set_band_2_frequency__bass); +-static DEVICE_ATTR(delay_param_2, S_IWUSR | S_IRUGO, pod_get_delay_param_2, +- pod_set_delay_param_2); +-static DEVICE_ATTR(delay_volume_mix, S_IWUSR | S_IRUGO, +- pod_get_delay_volume_mix, pod_set_delay_volume_mix); +-static DEVICE_ATTR(delay_param_3, S_IWUSR | S_IRUGO, pod_get_delay_param_3, +- pod_set_delay_param_3); +-static DEVICE_ATTR(reverb_enable, S_IWUSR | S_IRUGO, pod_get_reverb_enable, +- pod_set_reverb_enable); +-static DEVICE_ATTR(reverb_type, S_IWUSR | S_IRUGO, pod_get_reverb_type, +- pod_set_reverb_type); +-static DEVICE_ATTR(reverb_decay, S_IWUSR | S_IRUGO, pod_get_reverb_decay, +- pod_set_reverb_decay); +-static DEVICE_ATTR(reverb_tone, S_IWUSR | S_IRUGO, pod_get_reverb_tone, +- pod_set_reverb_tone); +-static DEVICE_ATTR(reverb_pre_delay, S_IWUSR | S_IRUGO, +- pod_get_reverb_pre_delay, pod_set_reverb_pre_delay); +-static DEVICE_ATTR(reverb_pre_post, S_IWUSR | S_IRUGO, pod_get_reverb_pre_post, +- pod_set_reverb_pre_post); +-static DEVICE_ATTR(band_2_frequency, S_IWUSR | S_IRUGO, +- pod_get_band_2_frequency, pod_set_band_2_frequency); +-static DEVICE_ATTR2(band_3_frequency__bass, band_3_frequency, S_IWUSR | S_IRUGO, +- pod_get_band_3_frequency__bass, +- pod_set_band_3_frequency__bass); +-static DEVICE_ATTR(wah_enable, S_IWUSR | S_IRUGO, pod_get_wah_enable, +- pod_set_wah_enable); +-static DEVICE_ATTR(modulation_lo_cut, S_IWUSR | S_IRUGO, +- pod_get_modulation_lo_cut, pod_set_modulation_lo_cut); +-static DEVICE_ATTR(delay_reverb_lo_cut, S_IWUSR | S_IRUGO, +- pod_get_delay_reverb_lo_cut, pod_set_delay_reverb_lo_cut); +-static DEVICE_ATTR(volume_pedal_minimum, S_IWUSR | S_IRUGO, +- pod_get_volume_pedal_minimum, pod_set_volume_pedal_minimum); +-static DEVICE_ATTR(eq_pre_post, S_IWUSR | S_IRUGO, pod_get_eq_pre_post, +- pod_set_eq_pre_post); +-static DEVICE_ATTR(volume_pre_post, S_IWUSR | S_IRUGO, pod_get_volume_pre_post, +- pod_set_volume_pre_post); +-static DEVICE_ATTR(di_model, S_IWUSR | S_IRUGO, pod_get_di_model, +- pod_set_di_model); +-static DEVICE_ATTR(di_delay, S_IWUSR | S_IRUGO, pod_get_di_delay, +- pod_set_di_delay); +-static DEVICE_ATTR(mod_enable, S_IWUSR | S_IRUGO, pod_get_mod_enable, +- pod_set_mod_enable); +-static DEVICE_ATTR(mod_param_1_note_value, S_IWUSR | S_IRUGO, +- pod_get_mod_param_1_note_value, +- pod_set_mod_param_1_note_value); +-static DEVICE_ATTR(mod_param_2, S_IWUSR | S_IRUGO, pod_get_mod_param_2, +- pod_set_mod_param_2); +-static DEVICE_ATTR(mod_param_3, S_IWUSR | S_IRUGO, pod_get_mod_param_3, +- pod_set_mod_param_3); +-static DEVICE_ATTR(mod_param_4, S_IWUSR | S_IRUGO, pod_get_mod_param_4, +- pod_set_mod_param_4); +-static DEVICE_ATTR(mod_param_5, S_IWUSR | S_IRUGO, pod_get_mod_param_5, +- pod_set_mod_param_5); +-static DEVICE_ATTR(mod_volume_mix, S_IWUSR | S_IRUGO, pod_get_mod_volume_mix, +- pod_set_mod_volume_mix); +-static DEVICE_ATTR(mod_pre_post, S_IWUSR | S_IRUGO, pod_get_mod_pre_post, +- pod_set_mod_pre_post); +-static DEVICE_ATTR(modulation_model, S_IWUSR | S_IRUGO, +- pod_get_modulation_model, pod_set_modulation_model); +-static DEVICE_ATTR(band_3_frequency, S_IWUSR | S_IRUGO, +- pod_get_band_3_frequency, pod_set_band_3_frequency); +-static DEVICE_ATTR2(band_4_frequency__bass, band_4_frequency, S_IWUSR | S_IRUGO, +- pod_get_band_4_frequency__bass, +- pod_set_band_4_frequency__bass); +-static DEVICE_ATTR(mod_param_1_double_precision, S_IWUSR | S_IRUGO, +- pod_get_mod_param_1_double_precision, +- pod_set_mod_param_1_double_precision); +-static DEVICE_ATTR(delay_param_1_double_precision, S_IWUSR | S_IRUGO, +- pod_get_delay_param_1_double_precision, +- pod_set_delay_param_1_double_precision); +-static DEVICE_ATTR(eq_enable, S_IWUSR | S_IRUGO, pod_get_eq_enable, +- pod_set_eq_enable); +-static DEVICE_ATTR(tap, S_IWUSR | S_IRUGO, pod_get_tap, pod_set_tap); +-static DEVICE_ATTR(volume_tweak_pedal_assign, S_IWUSR | S_IRUGO, +- pod_get_volume_tweak_pedal_assign, +- pod_set_volume_tweak_pedal_assign); +-static DEVICE_ATTR(band_5_frequency, S_IWUSR | S_IRUGO, +- pod_get_band_5_frequency, pod_set_band_5_frequency); +-static DEVICE_ATTR(tuner, S_IWUSR | S_IRUGO, pod_get_tuner, pod_set_tuner); +-static DEVICE_ATTR(mic_selection, S_IWUSR | S_IRUGO, pod_get_mic_selection, +- pod_set_mic_selection); +-static DEVICE_ATTR(cabinet_model, S_IWUSR | S_IRUGO, pod_get_cabinet_model, +- pod_set_cabinet_model); +-static DEVICE_ATTR(stomp_model, S_IWUSR | S_IRUGO, pod_get_stomp_model, +- pod_set_stomp_model); +-static DEVICE_ATTR(roomlevel, S_IWUSR | S_IRUGO, pod_get_roomlevel, +- pod_set_roomlevel); +-static DEVICE_ATTR(band_4_frequency, S_IWUSR | S_IRUGO, +- pod_get_band_4_frequency, pod_set_band_4_frequency); +-static DEVICE_ATTR(band_6_frequency, S_IWUSR | S_IRUGO, +- pod_get_band_6_frequency, pod_set_band_6_frequency); +-static DEVICE_ATTR(stomp_param_1_note_value, S_IWUSR | S_IRUGO, +- pod_get_stomp_param_1_note_value, +- pod_set_stomp_param_1_note_value); +-static DEVICE_ATTR(stomp_param_2, S_IWUSR | S_IRUGO, pod_get_stomp_param_2, +- pod_set_stomp_param_2); +-static DEVICE_ATTR(stomp_param_3, S_IWUSR | S_IRUGO, pod_get_stomp_param_3, +- pod_set_stomp_param_3); +-static DEVICE_ATTR(stomp_param_4, S_IWUSR | S_IRUGO, pod_get_stomp_param_4, +- pod_set_stomp_param_4); +-static DEVICE_ATTR(stomp_param_5, S_IWUSR | S_IRUGO, pod_get_stomp_param_5, +- pod_set_stomp_param_5); +-static DEVICE_ATTR(stomp_param_6, S_IWUSR | S_IRUGO, pod_get_stomp_param_6, +- pod_set_stomp_param_6); +-static DEVICE_ATTR(amp_switch_select, S_IWUSR | S_IRUGO, +- pod_get_amp_switch_select, pod_set_amp_switch_select); +-static DEVICE_ATTR(delay_param_4, S_IWUSR | S_IRUGO, pod_get_delay_param_4, +- pod_set_delay_param_4); +-static DEVICE_ATTR(delay_param_5, S_IWUSR | S_IRUGO, pod_get_delay_param_5, +- pod_set_delay_param_5); +-static DEVICE_ATTR(delay_pre_post, S_IWUSR | S_IRUGO, pod_get_delay_pre_post, +- pod_set_delay_pre_post); +-static DEVICE_ATTR(delay_model, S_IWUSR | S_IRUGO, pod_get_delay_model, +- pod_set_delay_model); +-static DEVICE_ATTR(delay_verb_model, S_IWUSR | S_IRUGO, +- pod_get_delay_verb_model, pod_set_delay_verb_model); +-static DEVICE_ATTR(tempo_msb, S_IWUSR | S_IRUGO, pod_get_tempo_msb, +- pod_set_tempo_msb); +-static DEVICE_ATTR(tempo_lsb, S_IWUSR | S_IRUGO, pod_get_tempo_lsb, +- pod_set_tempo_lsb); +-static DEVICE_ATTR(wah_model, S_IWUSR | S_IRUGO, pod_get_wah_model, +- pod_set_wah_model); +-static DEVICE_ATTR(bypass_volume, S_IWUSR | S_IRUGO, pod_get_bypass_volume, +- pod_set_bypass_volume); +-static DEVICE_ATTR(fx_loop_on_off, S_IWUSR | S_IRUGO, pod_get_fx_loop_on_off, +- pod_set_fx_loop_on_off); +-static DEVICE_ATTR(tweak_param_select, S_IWUSR | S_IRUGO, +- pod_get_tweak_param_select, pod_set_tweak_param_select); +-static DEVICE_ATTR(amp1_engage, S_IWUSR | S_IRUGO, pod_get_amp1_engage, +- pod_set_amp1_engage); +-static DEVICE_ATTR(band_1_gain, S_IWUSR | S_IRUGO, pod_get_band_1_gain, +- pod_set_band_1_gain); +-static DEVICE_ATTR2(band_2_gain__bass, band_2_gain, S_IWUSR | S_IRUGO, +- pod_get_band_2_gain__bass, pod_set_band_2_gain__bass); +-static DEVICE_ATTR(band_2_gain, S_IWUSR | S_IRUGO, pod_get_band_2_gain, +- pod_set_band_2_gain); +-static DEVICE_ATTR2(band_3_gain__bass, band_3_gain, S_IWUSR | S_IRUGO, +- pod_get_band_3_gain__bass, pod_set_band_3_gain__bass); +-static DEVICE_ATTR(band_3_gain, S_IWUSR | S_IRUGO, pod_get_band_3_gain, +- pod_set_band_3_gain); +-static DEVICE_ATTR2(band_4_gain__bass, band_4_gain, S_IWUSR | S_IRUGO, +- pod_get_band_4_gain__bass, pod_set_band_4_gain__bass); +-static DEVICE_ATTR2(band_5_gain__bass, band_5_gain, S_IWUSR | S_IRUGO, +- pod_get_band_5_gain__bass, pod_set_band_5_gain__bass); +-static DEVICE_ATTR(band_4_gain, S_IWUSR | S_IRUGO, pod_get_band_4_gain, +- pod_set_band_4_gain); +-static DEVICE_ATTR2(band_6_gain__bass, band_6_gain, S_IWUSR | S_IRUGO, +- pod_get_band_6_gain__bass, pod_set_band_6_gain__bass); +-static DEVICE_ATTR(body, S_IRUGO, variax_get_body, line6_nop_write); +-static DEVICE_ATTR(pickup1_enable, S_IRUGO, variax_get_pickup1_enable, +- line6_nop_write); +-static DEVICE_ATTR(pickup1_type, S_IRUGO, variax_get_pickup1_type, +- line6_nop_write); +-static DEVICE_ATTR(pickup1_position, S_IRUGO, variax_get_pickup1_position, +- line6_nop_write); +-static DEVICE_ATTR(pickup1_angle, S_IRUGO, variax_get_pickup1_angle, +- line6_nop_write); +-static DEVICE_ATTR(pickup1_level, S_IRUGO, variax_get_pickup1_level, +- line6_nop_write); +-static DEVICE_ATTR(pickup2_enable, S_IRUGO, variax_get_pickup2_enable, +- line6_nop_write); +-static DEVICE_ATTR(pickup2_type, S_IRUGO, variax_get_pickup2_type, +- line6_nop_write); +-static DEVICE_ATTR(pickup2_position, S_IRUGO, variax_get_pickup2_position, +- line6_nop_write); +-static DEVICE_ATTR(pickup2_angle, S_IRUGO, variax_get_pickup2_angle, +- line6_nop_write); +-static DEVICE_ATTR(pickup2_level, S_IRUGO, variax_get_pickup2_level, +- line6_nop_write); +-static DEVICE_ATTR(pickup_phase, S_IRUGO, variax_get_pickup_phase, +- line6_nop_write); +-static DEVICE_ATTR(capacitance, S_IRUGO, variax_get_capacitance, +- line6_nop_write); +-static DEVICE_ATTR(tone_resistance, S_IRUGO, variax_get_tone_resistance, +- line6_nop_write); +-static DEVICE_ATTR(volume_resistance, S_IRUGO, variax_get_volume_resistance, +- line6_nop_write); +-static DEVICE_ATTR(taper, S_IRUGO, variax_get_taper, line6_nop_write); +-static DEVICE_ATTR(tone_dump, S_IRUGO, variax_get_tone_dump, line6_nop_write); +-static DEVICE_ATTR(save_tone, S_IRUGO, variax_get_save_tone, line6_nop_write); +-static DEVICE_ATTR(volume_dump, S_IRUGO, variax_get_volume_dump, +- line6_nop_write); +-static DEVICE_ATTR(tuning_enable, S_IRUGO, variax_get_tuning_enable, +- line6_nop_write); +-static DEVICE_ATTR(tuning6, S_IRUGO, variax_get_tuning6, line6_nop_write); +-static DEVICE_ATTR(tuning5, S_IRUGO, variax_get_tuning5, line6_nop_write); +-static DEVICE_ATTR(tuning4, S_IRUGO, variax_get_tuning4, line6_nop_write); +-static DEVICE_ATTR(tuning3, S_IRUGO, variax_get_tuning3, line6_nop_write); +-static DEVICE_ATTR(tuning2, S_IRUGO, variax_get_tuning2, line6_nop_write); +-static DEVICE_ATTR(tuning1, S_IRUGO, variax_get_tuning1, line6_nop_write); +-static DEVICE_ATTR(detune6, S_IRUGO, variax_get_detune6, line6_nop_write); +-static DEVICE_ATTR(detune5, S_IRUGO, variax_get_detune5, line6_nop_write); +-static DEVICE_ATTR(detune4, S_IRUGO, variax_get_detune4, line6_nop_write); +-static DEVICE_ATTR(detune3, S_IRUGO, variax_get_detune3, line6_nop_write); +-static DEVICE_ATTR(detune2, S_IRUGO, variax_get_detune2, line6_nop_write); +-static DEVICE_ATTR(detune1, S_IRUGO, variax_get_detune1, line6_nop_write); +-static DEVICE_ATTR(mix6, S_IRUGO, variax_get_mix6, line6_nop_write); +-static DEVICE_ATTR(mix5, S_IRUGO, variax_get_mix5, line6_nop_write); +-static DEVICE_ATTR(mix4, S_IRUGO, variax_get_mix4, line6_nop_write); +-static DEVICE_ATTR(mix3, S_IRUGO, variax_get_mix3, line6_nop_write); +-static DEVICE_ATTR(mix2, S_IRUGO, variax_get_mix2, line6_nop_write); +-static DEVICE_ATTR(mix1, S_IRUGO, variax_get_mix1, line6_nop_write); +-static DEVICE_ATTR(pickup_wiring, S_IRUGO, variax_get_pickup_wiring, +- line6_nop_write); +- +-int line6_pod_create_files(int firmware, int type, struct device *dev) +-{ +- int err; +- CHECK_RETURN(device_create_file(dev, &dev_attr_tweak)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_wah_position)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_compression_gain)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_vol_pedal_position)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_compression_threshold)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pan)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_amp_model_setup)); +- if (firmware >= 200) +- CHECK_RETURN(device_create_file(dev, &dev_attr_amp_model)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_drive)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_bass)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_mid)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_lowmid)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_treble)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_highmid)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_chan_vol)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_mix)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_effect_setup)); +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_1_frequency)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_presence)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_treble__bass)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_noise_gate_enable)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_gate_threshold)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_gate_decay_time)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_enable)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_comp_enable)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_time)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_delay_enable)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_1)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_1)); +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_delay_param_1_note_value)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_2_frequency__bass)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_2)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_delay_volume_mix)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_3)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_enable)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_type)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_decay)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_tone)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_reverb_pre_delay)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_reverb_pre_post)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_2_frequency)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_3_frequency__bass)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_wah_enable)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_modulation_lo_cut)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_delay_reverb_lo_cut)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_volume_pedal_minimum)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_eq_pre_post)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_volume_pre_post)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_di_model)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_di_delay)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mod_enable)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_1_note_value)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_2)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_3)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_4)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_5)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mod_volume_mix)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mod_pre_post)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_modulation_model)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_3_frequency)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_4_frequency__bass)); +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_mod_param_1_double_precision)); +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_delay_param_1_double_precision)); +- if (firmware >= 200) +- CHECK_RETURN(device_create_file(dev, &dev_attr_eq_enable)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tap)); +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_volume_tweak_pedal_assign)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_5_frequency)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tuner)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mic_selection)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_cabinet_model)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_model)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_roomlevel)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_4_frequency)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_6_frequency)); +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_stomp_param_1_note_value)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_2)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_3)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_4)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_5)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_6)); +- if ((type & (LINE6_BITS_LIVE)) != 0) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_amp_switch_select)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_4)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_5)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_delay_pre_post)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_delay_model)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_delay_verb_model)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tempo_msb)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tempo_lsb)); +- if (firmware >= 300) +- CHECK_RETURN(device_create_file(dev, &dev_attr_wah_model)); +- if (firmware >= 214) +- CHECK_RETURN(device_create_file(dev, &dev_attr_bypass_volume)); +- if ((type & (LINE6_BITS_PRO)) != 0) +- CHECK_RETURN(device_create_file(dev, &dev_attr_fx_loop_on_off)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tweak_param_select)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_amp1_engage)); +- if (firmware >= 200) +- CHECK_RETURN(device_create_file(dev, &dev_attr_band_1_gain)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_2_gain__bass)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_2_gain)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_3_gain__bass)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_3_gain)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_4_gain__bass)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_5_gain__bass)); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_4_gain)); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- CHECK_RETURN(device_create_file +- (dev, &dev_attr_band_6_gain__bass)); +- return 0; +-} +- +-void line6_pod_remove_files(int firmware, int type, struct device *dev) +-{ +- device_remove_file(dev, &dev_attr_tweak); +- device_remove_file(dev, &dev_attr_wah_position); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_compression_gain); +- device_remove_file(dev, &dev_attr_vol_pedal_position); +- device_remove_file(dev, &dev_attr_compression_threshold); +- device_remove_file(dev, &dev_attr_pan); +- device_remove_file(dev, &dev_attr_amp_model_setup); +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_amp_model); +- device_remove_file(dev, &dev_attr_drive); +- device_remove_file(dev, &dev_attr_bass); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_mid); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_lowmid); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_treble); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_highmid); +- device_remove_file(dev, &dev_attr_chan_vol); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_reverb_mix); +- device_remove_file(dev, &dev_attr_effect_setup); +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_1_frequency); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_presence); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_treble__bass); +- device_remove_file(dev, &dev_attr_noise_gate_enable); +- device_remove_file(dev, &dev_attr_gate_threshold); +- device_remove_file(dev, &dev_attr_gate_decay_time); +- device_remove_file(dev, &dev_attr_stomp_enable); +- device_remove_file(dev, &dev_attr_comp_enable); +- device_remove_file(dev, &dev_attr_stomp_time); +- device_remove_file(dev, &dev_attr_delay_enable); +- device_remove_file(dev, &dev_attr_mod_param_1); +- device_remove_file(dev, &dev_attr_delay_param_1); +- device_remove_file(dev, &dev_attr_delay_param_1_note_value); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, +- &dev_attr_band_2_frequency__bass); +- device_remove_file(dev, &dev_attr_delay_param_2); +- device_remove_file(dev, &dev_attr_delay_volume_mix); +- device_remove_file(dev, &dev_attr_delay_param_3); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_reverb_enable); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_reverb_type); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_reverb_decay); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_reverb_tone); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_reverb_pre_delay); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_reverb_pre_post); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_2_frequency); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, +- &dev_attr_band_3_frequency__bass); +- device_remove_file(dev, &dev_attr_wah_enable); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_modulation_lo_cut); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_delay_reverb_lo_cut); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_volume_pedal_minimum); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_eq_pre_post); +- device_remove_file(dev, &dev_attr_volume_pre_post); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_di_model); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_di_delay); +- device_remove_file(dev, &dev_attr_mod_enable); +- device_remove_file(dev, &dev_attr_mod_param_1_note_value); +- device_remove_file(dev, &dev_attr_mod_param_2); +- device_remove_file(dev, &dev_attr_mod_param_3); +- device_remove_file(dev, &dev_attr_mod_param_4); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_mod_param_5); +- device_remove_file(dev, &dev_attr_mod_volume_mix); +- device_remove_file(dev, &dev_attr_mod_pre_post); +- device_remove_file(dev, &dev_attr_modulation_model); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_3_frequency); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, +- &dev_attr_band_4_frequency__bass); +- device_remove_file(dev, &dev_attr_mod_param_1_double_precision); +- device_remove_file(dev, &dev_attr_delay_param_1_double_precision); +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_eq_enable); +- device_remove_file(dev, &dev_attr_tap); +- device_remove_file(dev, &dev_attr_volume_tweak_pedal_assign); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_5_frequency); +- device_remove_file(dev, &dev_attr_tuner); +- device_remove_file(dev, &dev_attr_mic_selection); +- device_remove_file(dev, &dev_attr_cabinet_model); +- device_remove_file(dev, &dev_attr_stomp_model); +- device_remove_file(dev, &dev_attr_roomlevel); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_4_frequency); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_6_frequency); +- device_remove_file(dev, &dev_attr_stomp_param_1_note_value); +- device_remove_file(dev, &dev_attr_stomp_param_2); +- device_remove_file(dev, &dev_attr_stomp_param_3); +- device_remove_file(dev, &dev_attr_stomp_param_4); +- device_remove_file(dev, &dev_attr_stomp_param_5); +- device_remove_file(dev, &dev_attr_stomp_param_6); +- if ((type & (LINE6_BITS_LIVE)) != 0) +- device_remove_file(dev, &dev_attr_amp_switch_select); +- device_remove_file(dev, &dev_attr_delay_param_4); +- device_remove_file(dev, &dev_attr_delay_param_5); +- device_remove_file(dev, &dev_attr_delay_pre_post); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_delay_model); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- device_remove_file(dev, &dev_attr_delay_verb_model); +- device_remove_file(dev, &dev_attr_tempo_msb); +- device_remove_file(dev, &dev_attr_tempo_lsb); +- if (firmware >= 300) +- device_remove_file(dev, &dev_attr_wah_model); +- if (firmware >= 214) +- device_remove_file(dev, &dev_attr_bypass_volume); +- if ((type & (LINE6_BITS_PRO)) != 0) +- device_remove_file(dev, &dev_attr_fx_loop_on_off); +- device_remove_file(dev, &dev_attr_tweak_param_select); +- device_remove_file(dev, &dev_attr_amp1_engage); +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_1_gain); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_2_gain__bass); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_2_gain); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_3_gain__bass); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_3_gain); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_4_gain__bass); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_5_gain__bass); +- if ((type & (LINE6_BITS_PODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_4_gain); +- if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) +- if (firmware >= 200) +- device_remove_file(dev, &dev_attr_band_6_gain__bass); +-} +- +-int line6_variax_create_files(int firmware, int type, struct device *dev) +-{ +- int err; +- CHECK_RETURN(device_create_file(dev, &dev_attr_body)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_enable)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_type)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_position)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_angle)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_level)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_enable)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_type)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_position)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_angle)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_level)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pickup_phase)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_capacitance)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tone_resistance)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_volume_resistance)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_taper)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tone_dump)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_save_tone)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_volume_dump)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tuning_enable)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tuning6)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tuning5)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tuning4)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tuning3)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tuning2)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tuning1)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_detune6)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_detune5)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_detune4)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_detune3)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_detune2)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_detune1)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mix6)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mix5)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mix4)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mix3)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mix2)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_mix1)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_pickup_wiring)); +- return 0; +-} +- +-void line6_variax_remove_files(int firmware, int type, struct device *dev) +-{ +- device_remove_file(dev, &dev_attr_body); +- device_remove_file(dev, &dev_attr_pickup1_enable); +- device_remove_file(dev, &dev_attr_pickup1_type); +- device_remove_file(dev, &dev_attr_pickup1_position); +- device_remove_file(dev, &dev_attr_pickup1_angle); +- device_remove_file(dev, &dev_attr_pickup1_level); +- device_remove_file(dev, &dev_attr_pickup2_enable); +- device_remove_file(dev, &dev_attr_pickup2_type); +- device_remove_file(dev, &dev_attr_pickup2_position); +- device_remove_file(dev, &dev_attr_pickup2_angle); +- device_remove_file(dev, &dev_attr_pickup2_level); +- device_remove_file(dev, &dev_attr_pickup_phase); +- device_remove_file(dev, &dev_attr_capacitance); +- device_remove_file(dev, &dev_attr_tone_resistance); +- device_remove_file(dev, &dev_attr_volume_resistance); +- device_remove_file(dev, &dev_attr_taper); +- device_remove_file(dev, &dev_attr_tone_dump); +- device_remove_file(dev, &dev_attr_save_tone); +- device_remove_file(dev, &dev_attr_volume_dump); +- device_remove_file(dev, &dev_attr_tuning_enable); +- device_remove_file(dev, &dev_attr_tuning6); +- device_remove_file(dev, &dev_attr_tuning5); +- device_remove_file(dev, &dev_attr_tuning4); +- device_remove_file(dev, &dev_attr_tuning3); +- device_remove_file(dev, &dev_attr_tuning2); +- device_remove_file(dev, &dev_attr_tuning1); +- device_remove_file(dev, &dev_attr_detune6); +- device_remove_file(dev, &dev_attr_detune5); +- device_remove_file(dev, &dev_attr_detune4); +- device_remove_file(dev, &dev_attr_detune3); +- device_remove_file(dev, &dev_attr_detune2); +- device_remove_file(dev, &dev_attr_detune1); +- device_remove_file(dev, &dev_attr_mix6); +- device_remove_file(dev, &dev_attr_mix5); +- device_remove_file(dev, &dev_attr_mix4); +- device_remove_file(dev, &dev_attr_mix3); +- device_remove_file(dev, &dev_attr_mix2); +- device_remove_file(dev, &dev_attr_mix1); +- device_remove_file(dev, &dev_attr_pickup_wiring); +-} +diff --git a/drivers/staging/line6/control.h b/drivers/staging/line6/control.h +deleted file mode 100644 +index e4c5d2c..0000000 +--- a/drivers/staging/line6/control.h ++++ /dev/null +@@ -1,195 +0,0 @@ +-/* +- * Line6 Linux USB driver - 0.9.1beta +- * +- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) +- * +- * This program is free software; 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. +- * +- */ +- +-#ifndef LINE6_CONTROL_H +-#define LINE6_CONTROL_H +- +-/** +- List of PODxt Pro controls. +- See Appendix C of the "PODxt (Pro) Pilot's Handbook" by Line6. +- Comments after the number refer to the PODxt Pro firmware version required +- for this feature. +- +- Please *don't* reformat this file since "control.c" is created automatically +- from "control.h", and this process depends on the exact formatting of the +- code and the comments below! +-*/ +- +-/* *INDENT-OFF* */ +- +-enum { +- POD_tweak = 1, +- POD_wah_position = 4, +- POD_compression_gain = 5, /* device: LINE6_BITS_PODXTALL */ +- POD_vol_pedal_position = 7, +- POD_compression_threshold = 9, +- POD_pan = 10, +- POD_amp_model_setup = 11, +- POD_amp_model = 12, /* firmware: 2.0 */ +- POD_drive = 13, +- POD_bass = 14, +- POD_mid = 15, /* device: LINE6_BITS_PODXTALL */ +- POD_lowmid = 15, /* device: LINE6_BITS_BASSPODXTALL */ +- POD_treble = 16, /* device: LINE6_BITS_PODXTALL */ +- POD_highmid = 16, /* device: LINE6_BITS_BASSPODXTALL */ +- POD_chan_vol = 17, +- POD_reverb_mix = 18, /* device: LINE6_BITS_PODXTALL */ +- POD_effect_setup = 19, +- POD_band_1_frequency = 20, /* firmware: 2.0 */ +- POD_presence = 21, /* device: LINE6_BITS_PODXTALL */ +- POD_treble__bass = 21, /* device: LINE6_BITS_BASSPODXTALL */ +- POD_noise_gate_enable = 22, +- POD_gate_threshold = 23, +- POD_gate_decay_time = 24, +- POD_stomp_enable = 25, +- POD_comp_enable = 26, +- POD_stomp_time = 27, +- POD_delay_enable = 28, +- POD_mod_param_1 = 29, +- POD_delay_param_1 = 30, +- POD_delay_param_1_note_value = 31, +- POD_band_2_frequency__bass = 32, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ +- POD_delay_param_2 = 33, +- POD_delay_volume_mix = 34, +- POD_delay_param_3 = 35, +- POD_reverb_enable = 36, /* device: LINE6_BITS_PODXTALL */ +- POD_reverb_type = 37, /* device: LINE6_BITS_PODXTALL */ +- POD_reverb_decay = 38, /* device: LINE6_BITS_PODXTALL */ +- POD_reverb_tone = 39, /* device: LINE6_BITS_PODXTALL */ +- POD_reverb_pre_delay = 40, /* device: LINE6_BITS_PODXTALL */ +- POD_reverb_pre_post = 41, /* device: LINE6_BITS_PODXTALL */ +- POD_band_2_frequency = 42, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ +- POD_band_3_frequency__bass = 42, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ +- POD_wah_enable = 43, +- POD_modulation_lo_cut = 44, /* device: LINE6_BITS_BASSPODXTALL */ +- POD_delay_reverb_lo_cut = 45, /* device: LINE6_BITS_BASSPODXTALL */ +- POD_volume_pedal_minimum = 46, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ +- POD_eq_pre_post = 46, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ +- POD_volume_pre_post = 47, +- POD_di_model = 48, /* device: LINE6_BITS_BASSPODXTALL */ +- POD_di_delay = 49, /* device: LINE6_BITS_BASSPODXTALL */ +- POD_mod_enable = 50, +- POD_mod_param_1_note_value = 51, +- POD_mod_param_2 = 52, +- POD_mod_param_3 = 53, +- POD_mod_param_4 = 54, +- POD_mod_param_5 = 55, /* device: LINE6_BITS_BASSPODXTALL */ +- POD_mod_volume_mix = 56, +- POD_mod_pre_post = 57, +- POD_modulation_model = 58, +- POD_band_3_frequency = 60, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ +- POD_band_4_frequency__bass = 60, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ +- POD_mod_param_1_double_precision = 61, +- POD_delay_param_1_double_precision = 62, +- POD_eq_enable = 63, /* firmware: 2.0 */ +- POD_tap = 64, +- POD_volume_tweak_pedal_assign = 65, +- POD_band_5_frequency = 68, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ +- POD_tuner = 69, +- POD_mic_selection = 70, +- POD_cabinet_model = 71, +- POD_stomp_model = 75, +- POD_roomlevel = 76, +- POD_band_4_frequency = 77, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ +- POD_band_6_frequency = 77, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ +- POD_stomp_param_1_note_value = 78, +- POD_stomp_param_2 = 79, +- POD_stomp_param_3 = 80, +- POD_stomp_param_4 = 81, +- POD_stomp_param_5 = 82, +- POD_stomp_param_6 = 83, +- POD_amp_switch_select = 84, /* device: LINE6_BITS_LIVE */ +- POD_delay_param_4 = 85, +- POD_delay_param_5 = 86, +- POD_delay_pre_post = 87, +- POD_delay_model = 88, /* device: LINE6_BITS_PODXTALL */ +- POD_delay_verb_model = 88, /* device: LINE6_BITS_BASSPODXTALL */ +- POD_tempo_msb = 89, +- POD_tempo_lsb = 90, +- POD_wah_model = 91, /* firmware: 3.0 */ +- POD_bypass_volume = 105, /* firmware: 2.14 */ +- POD_fx_loop_on_off = 107, /* device: LINE6_BITS_PRO */ +- POD_tweak_param_select = 108, +- POD_amp1_engage = 111, +- POD_band_1_gain = 114, /* firmware: 2.0 */ +- POD_band_2_gain__bass = 115, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ +- POD_band_2_gain = 116, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ +- POD_band_3_gain__bass = 116, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ +- POD_band_3_gain = 117, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ +- POD_band_4_gain__bass = 117, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ +- POD_band_5_gain__bass = 118, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ +- POD_band_4_gain = 119, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ +- POD_band_6_gain__bass = 119 /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ +-}; +- +-/** +- List of Variax workbench controls (dump). +-*/ +-enum { +- VARIAX_body = 3, +- VARIAX_pickup1_enable = 4, /* 0: enabled, 1: disabled */ +- VARIAX_pickup1_type = 8, +- VARIAX_pickup1_position = 9, /* type: 24 bit float */ +- VARIAX_pickup1_angle = 12, /* type: 24 bit float */ +- VARIAX_pickup1_level = 15, /* type: 24 bit float */ +- VARIAX_pickup2_enable = 18, /* 0: enabled, 1: disabled */ +- VARIAX_pickup2_type = 22, +- VARIAX_pickup2_position = 23, /* type: 24 bit float */ +- VARIAX_pickup2_angle = 26, /* type: 24 bit float */ +- VARIAX_pickup2_level = 29, /* type: 24 bit float */ +- VARIAX_pickup_phase = 32, /* 0: in phase, 1: out of phase */ +- VARIAX_capacitance = 33, /* type: 24 bit float */ +- VARIAX_tone_resistance = 36, /* type: 24 bit float */ +- VARIAX_volume_resistance = 39, /* type: 24 bit float */ +- VARIAX_taper = 42, /* 0: Linear, 1: Audio */ +- VARIAX_tone_dump = 43, /* type: 24 bit float */ +- VARIAX_save_tone = 46, +- VARIAX_volume_dump = 47, /* type: 24 bit float */ +- VARIAX_tuning_enable = 50, +- VARIAX_tuning6 = 51, +- VARIAX_tuning5 = 52, +- VARIAX_tuning4 = 53, +- VARIAX_tuning3 = 54, +- VARIAX_tuning2 = 55, +- VARIAX_tuning1 = 56, +- VARIAX_detune6 = 57, /* type: 24 bit float */ +- VARIAX_detune5 = 60, /* type: 24 bit float */ +- VARIAX_detune4 = 63, /* type: 24 bit float */ +- VARIAX_detune3 = 66, /* type: 24 bit float */ +- VARIAX_detune2 = 69, /* type: 24 bit float */ +- VARIAX_detune1 = 72, /* type: 24 bit float */ +- VARIAX_mix6 = 75, /* type: 24 bit float */ +- VARIAX_mix5 = 78, /* type: 24 bit float */ +- VARIAX_mix4 = 81, /* type: 24 bit float */ +- VARIAX_mix3 = 84, /* type: 24 bit float */ +- VARIAX_mix2 = 87, /* type: 24 bit float */ +- VARIAX_mix1 = 90, /* type: 24 bit float */ +- VARIAX_pickup_wiring = 96 /* 0: parallel, 1: series */ +-}; +- +-/** +- List of Variax workbench controls (MIDI). +-*/ +-enum { +- VARIAXMIDI_volume = 7, +- VARIAXMIDI_tone = 79, +-}; +- +-/* *INDENT-ON* */ +- +-extern int line6_pod_create_files(int firmware, int type, struct device *dev); +-extern void line6_pod_remove_files(int firmware, int type, struct device *dev); +-extern int line6_variax_create_files(int firmware, int type, +- struct device *dev); +-extern void line6_variax_remove_files(int firmware, int type, +- struct device *dev); +- +-#endif +diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c +index 851b762..1e4ce500 100644 +--- a/drivers/staging/line6/driver.c ++++ b/drivers/staging/line6/driver.c +@@ -16,11 +16,11 @@ + + #include "audio.h" + #include "capture.h" +-#include "control.h" + #include "driver.h" + #include "midi.h" + #include "playback.h" + #include "pod.h" ++#include "podhd.h" + #include "revision.h" + #include "toneport.h" + #include "usbdefs.h" +@@ -37,6 +37,8 @@ static const struct usb_device_id line6_id_table[] = { + {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTPRO)}, + {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_GUITARPORT)}, + {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_POCKETPOD)}, ++ {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODHD300)}, ++ {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODHD500)}, + {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_GX)}, + {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX1)}, + {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX2)}, +@@ -56,23 +58,25 @@ MODULE_DEVICE_TABLE(usb, line6_id_table); + + /* *INDENT-OFF* */ + static struct line6_properties line6_properties_table[] = { +- { "BassPODxt", "BassPODxt", LINE6_BIT_BASSPODXT, LINE6_BIT_CONTROL_PCM_HWMON }, +- { "BassPODxtLive", "BassPODxt Live", LINE6_BIT_BASSPODXTLIVE, LINE6_BIT_CONTROL_PCM_HWMON }, +- { "BassPODxtPro", "BassPODxt Pro", LINE6_BIT_BASSPODXTPRO, LINE6_BIT_CONTROL_PCM_HWMON }, +- { "GuitarPort", "GuitarPort", LINE6_BIT_GUITARPORT, LINE6_BIT_PCM }, +- { "PocketPOD", "Pocket POD", LINE6_BIT_POCKETPOD, LINE6_BIT_CONTROL }, +- { "PODStudioGX", "POD Studio GX", LINE6_BIT_PODSTUDIO_GX, LINE6_BIT_PCM }, +- { "PODStudioUX1", "POD Studio UX1", LINE6_BIT_PODSTUDIO_UX1, LINE6_BIT_PCM }, +- { "PODStudioUX2", "POD Studio UX2", LINE6_BIT_PODSTUDIO_UX2, LINE6_BIT_PCM }, +- { "PODX3", "POD X3", LINE6_BIT_PODX3, LINE6_BIT_PCM }, +- { "PODX3Live", "POD X3 Live", LINE6_BIT_PODX3LIVE, LINE6_BIT_PCM }, +- { "PODxt", "PODxt", LINE6_BIT_PODXT, LINE6_BIT_CONTROL_PCM_HWMON }, +- { "PODxtLive", "PODxt Live", LINE6_BIT_PODXTLIVE, LINE6_BIT_CONTROL_PCM_HWMON }, +- { "PODxtPro", "PODxt Pro", LINE6_BIT_PODXTPRO, LINE6_BIT_CONTROL_PCM_HWMON }, +- { "TonePortGX", "TonePort GX", LINE6_BIT_TONEPORT_GX, LINE6_BIT_PCM }, +- { "TonePortUX1", "TonePort UX1", LINE6_BIT_TONEPORT_UX1, LINE6_BIT_PCM }, +- { "TonePortUX2", "TonePort UX2", LINE6_BIT_TONEPORT_UX2, LINE6_BIT_PCM }, +- { "Variax", "Variax Workbench", LINE6_BIT_VARIAX, LINE6_BIT_CONTROL } ++ { LINE6_BIT_BASSPODXT, "BassPODxt", "BassPODxt", LINE6_BIT_CONTROL_PCM_HWMON }, ++ { LINE6_BIT_BASSPODXTLIVE, "BassPODxtLive", "BassPODxt Live", LINE6_BIT_CONTROL_PCM_HWMON }, ++ { LINE6_BIT_BASSPODXTPRO, "BassPODxtPro", "BassPODxt Pro", LINE6_BIT_CONTROL_PCM_HWMON }, ++ { LINE6_BIT_GUITARPORT, "GuitarPort", "GuitarPort", LINE6_BIT_PCM }, ++ { LINE6_BIT_POCKETPOD, "PocketPOD", "Pocket POD", LINE6_BIT_CONTROL }, ++ { LINE6_BIT_PODHD300, "PODHD300", "POD HD300", LINE6_BIT_CONTROL_PCM_HWMON }, ++ { LINE6_BIT_PODHD500, "PODHD500", "POD HD500", LINE6_BIT_CONTROL_PCM_HWMON }, ++ { LINE6_BIT_PODSTUDIO_GX, "PODStudioGX", "POD Studio GX", LINE6_BIT_PCM }, ++ { LINE6_BIT_PODSTUDIO_UX1, "PODStudioUX1", "POD Studio UX1", LINE6_BIT_PCM }, ++ { LINE6_BIT_PODSTUDIO_UX2, "PODStudioUX2", "POD Studio UX2", LINE6_BIT_PCM }, ++ { LINE6_BIT_PODX3, "PODX3", "POD X3", LINE6_BIT_PCM }, ++ { LINE6_BIT_PODX3LIVE, "PODX3Live", "POD X3 Live", LINE6_BIT_PCM }, ++ { LINE6_BIT_PODXT, "PODxt", "PODxt", LINE6_BIT_CONTROL_PCM_HWMON }, ++ { LINE6_BIT_PODXTLIVE, "PODxtLive", "PODxt Live", LINE6_BIT_CONTROL_PCM_HWMON }, ++ { LINE6_BIT_PODXTPRO, "PODxtPro", "PODxt Pro", LINE6_BIT_CONTROL_PCM_HWMON }, ++ { LINE6_BIT_TONEPORT_GX, "TonePortGX", "TonePort GX", LINE6_BIT_PCM }, ++ { LINE6_BIT_TONEPORT_UX1, "TonePortUX1", "TonePort UX1", LINE6_BIT_PCM }, ++ { LINE6_BIT_TONEPORT_UX2, "TonePortUX2", "TonePort UX2", LINE6_BIT_PCM }, ++ { LINE6_BIT_VARIAX, "Variax", "Variax Workbench", LINE6_BIT_CONTROL }, + }; + /* *INDENT-ON* */ + +@@ -87,17 +91,10 @@ const unsigned char line6_midi_id[] = { + Code to request version of POD, Variax interface + (and maybe other devices). + */ +-static const char line6_request_version0[] = { ++static const char line6_request_version[] = { + 0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7 + }; + +-/* +- Copy of version request code with GFP_KERNEL flag for use in URB. +-*/ +-static const char *line6_request_version; +- +-struct usb_line6 *line6_devices[LINE6_MAX_DEVICES]; +- + /** + Class for asynchronous messages. + */ +@@ -179,22 +176,6 @@ void line6_write_hexdump(struct usb_line6 *line6, char dir, + } + #endif + +-#ifdef CONFIG_LINE6_USB_DUMP_CTRL +-/* +- Dump URB data to syslog. +-*/ +-static void line6_dump_urb(struct urb *urb) +-{ +- struct usb_line6 *line6 = (struct usb_line6 *)urb->context; +- +- if (urb->status < 0) +- return; +- +- line6_write_hexdump(line6, 'R', (unsigned char *)urb->transfer_buffer, +- urb->actual_length); +-} +-#endif +- + /* + Send raw message in pieces of wMaxPacketSize bytes. + */ +@@ -203,10 +184,6 @@ int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, + { + int i, done = 0; + +-#ifdef CONFIG_LINE6_USB_DUMP_CTRL +- line6_write_hexdump(line6, 'S', buffer, size); +-#endif +- + for (i = 0; i < size; i += line6->max_packet_size) { + int partial; + const char *frag_buf = buffer + i; +@@ -261,10 +238,6 @@ static int line6_send_raw_message_async_part(struct message *msg, + (char *)msg->buffer + done, bytes, + line6_async_request_sent, msg, line6->interval); + +-#ifdef CONFIG_LINE6_USB_DUMP_CTRL +- line6_write_hexdump(line6, 'S', (char *)msg->buffer + done, bytes); +-#endif +- + msg->done += bytes; + retval = usb_submit_urb(urb, GFP_ATOMIC); + +@@ -331,8 +304,21 @@ int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer, + */ + int line6_version_request_async(struct usb_line6 *line6) + { +- return line6_send_raw_message_async(line6, line6_request_version, +- sizeof(line6_request_version0)); ++ char *buffer; ++ int retval; ++ ++ buffer = kmalloc(sizeof(line6_request_version), GFP_ATOMIC); ++ if (buffer == NULL) { ++ dev_err(line6->ifcdev, "Out of memory"); ++ return -ENOMEM; ++ } ++ ++ memcpy(buffer, line6_request_version, sizeof(line6_request_version)); ++ ++ retval = line6_send_raw_message_async(line6, buffer, ++ sizeof(line6_request_version)); ++ kfree(buffer); ++ return retval; + } + + /* +@@ -392,19 +378,13 @@ static void line6_data_received(struct urb *urb) + if (urb->status == -ESHUTDOWN) + return; + +-#ifdef CONFIG_LINE6_USB_DUMP_CTRL +- line6_dump_urb(urb); +-#endif +- + done = + line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length); + + if (done < urb->actual_length) { + line6_midibuf_ignore(mb, done); +- DEBUG_MESSAGES(dev_err +- (line6->ifcdev, +- "%d %d buffer overflow - message skipped\n", +- done, urb->actual_length)); ++ dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n", ++ done, urb->actual_length); + } + + for (;;) { +@@ -415,15 +395,7 @@ static void line6_data_received(struct urb *urb) + if (done == 0) + break; + +- /* MIDI input filter */ +- if (line6_midibuf_skip_message +- (mb, line6->line6midi->midi_mask_receive)) +- continue; +- + line6->message_length = done; +-#ifdef CONFIG_LINE6_USB_DUMP_MIDI +- line6_write_hexdump(line6, 'r', line6->buffer_message, done); +-#endif + line6_midi_receive(line6, line6->buffer_message, done); + + switch (line6->usbdev->descriptor.idProduct) { +@@ -437,6 +409,10 @@ static void line6_data_received(struct urb *urb) + line6); + break; + ++ case LINE6_DEVID_PODHD300: ++ case LINE6_DEVID_PODHD500: ++ break; /* let userspace handle MIDI */ ++ + case LINE6_DEVID_PODXTLIVE: + switch (line6->interface_number) { + case PODXTLIVE_INTERFACE_POD: +@@ -473,7 +449,7 @@ static void line6_data_received(struct urb *urb) + /* + Send channel number (i.e., switch to a different sound). + */ +-int line6_send_program(struct usb_line6 *line6, int value) ++int line6_send_program(struct usb_line6 *line6, u8 value) + { + int retval; + unsigned char *buffer; +@@ -489,10 +465,6 @@ int line6_send_program(struct usb_line6 *line6, int value) + buffer[0] = LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST; + buffer[1] = value; + +-#ifdef CONFIG_LINE6_USB_DUMP_CTRL +- line6_write_hexdump(line6, 'S', buffer, 2); +-#endif +- + retval = usb_interrupt_msg(line6->usbdev, + usb_sndintpipe(line6->usbdev, + line6->ep_control_write), +@@ -509,7 +481,7 @@ int line6_send_program(struct usb_line6 *line6, int value) + /* + Transmit Line6 control parameter. + */ +-int line6_transmit_parameter(struct usb_line6 *line6, int param, int value) ++int line6_transmit_parameter(struct usb_line6 *line6, int param, u8 value) + { + int retval; + unsigned char *buffer; +@@ -526,10 +498,6 @@ int line6_transmit_parameter(struct usb_line6 *line6, int param, int value) + buffer[1] = param; + buffer[2] = value; + +-#ifdef CONFIG_LINE6_USB_DUMP_CTRL +- line6_write_hexdump(line6, 'S', buffer, 3); +-#endif +- + retval = usb_interrupt_msg(line6->usbdev, + usb_sndintpipe(line6->usbdev, + line6->ep_control_write), +@@ -673,20 +641,6 @@ ssize_t line6_nop_write(struct device *dev, struct device_attribute *attr, + } + + /* +- "write" request on "raw" special file. +-*/ +-#ifdef CONFIG_LINE6_USB_RAW +-ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6 *line6 = usb_get_intfdata(interface); +- line6_send_raw_message(line6, buf, count); +- return count; +-} +-#endif +- +-/* + Generic destructor. + */ + static void line6_destruct(struct usb_interface *interface) +@@ -720,10 +674,9 @@ static int line6_probe(struct usb_interface *interface, + const struct usb_device_id *id) + { + int devtype; +- struct usb_device *usbdev = NULL; +- struct usb_line6 *line6 = NULL; ++ struct usb_device *usbdev; ++ struct usb_line6 *line6; + const struct line6_properties *properties; +- int devnum; + int interface_number, alternate = 0; + int product; + int size = 0; +@@ -757,16 +710,6 @@ static int line6_probe(struct usb_interface *interface, + goto err_put; + } + +- /* find free slot in device table: */ +- for (devnum = 0; devnum < LINE6_MAX_DEVICES; ++devnum) +- if (line6_devices[devnum] == NULL) +- break; +- +- if (devnum == LINE6_MAX_DEVICES) { +- ret = -ENODEV; +- goto err_put; +- } +- + /* initialize device info: */ + properties = &line6_properties_table[devtype]; + dev_info(&interface->dev, "Line6 %s found\n", properties->name); +@@ -794,6 +737,7 @@ static int line6_probe(struct usb_interface *interface, + } + break; + ++ case LINE6_DEVID_PODHD500: + case LINE6_DEVID_PODX3: + case LINE6_DEVID_PODX3LIVE: + switch (interface_number) { +@@ -812,6 +756,7 @@ static int line6_probe(struct usb_interface *interface, + case LINE6_DEVID_BASSPODXTPRO: + case LINE6_DEVID_PODXT: + case LINE6_DEVID_PODXTPRO: ++ case LINE6_DEVID_PODHD300: + alternate = 5; + break; + +@@ -865,6 +810,18 @@ static int line6_probe(struct usb_interface *interface, + ep_write = 0x03; + break; + ++ case LINE6_DEVID_PODHD300: ++ size = sizeof(struct usb_line6_podhd); ++ ep_read = 0x84; ++ ep_write = 0x03; ++ break; ++ ++ case LINE6_DEVID_PODHD500: ++ size = sizeof(struct usb_line6_podhd); ++ ep_read = 0x81; ++ ep_write = 0x01; ++ break; ++ + case LINE6_DEVID_POCKETPOD: + size = sizeof(struct usb_line6_pod); + ep_read = 0x82; +@@ -923,7 +880,7 @@ static int line6_probe(struct usb_interface *interface, + } + + if (size == 0) { +- dev_err(line6->ifcdev, ++ dev_err(&interface->dev, + "driver bug: interface data size not set\n"); + ret = -ENODEV; + goto err_put; +@@ -1017,6 +974,12 @@ static int line6_probe(struct usb_interface *interface, + ret = line6_pod_init(interface, (struct usb_line6_pod *)line6); + break; + ++ case LINE6_DEVID_PODHD300: ++ case LINE6_DEVID_PODHD500: ++ ret = line6_podhd_init(interface, ++ (struct usb_line6_podhd *)line6); ++ break; ++ + case LINE6_DEVID_PODXTLIVE: + switch (interface_number) { + case PODXTLIVE_INTERFACE_POD: +@@ -1075,7 +1038,6 @@ static int line6_probe(struct usb_interface *interface, + + dev_info(&interface->dev, "Line6 %s now attached\n", + line6->properties->name); +- line6_devices[devnum] = line6; + + switch (product) { + case LINE6_DEVID_PODX3: +@@ -1104,7 +1066,7 @@ static void line6_disconnect(struct usb_interface *interface) + { + struct usb_line6 *line6; + struct usb_device *usbdev; +- int interface_number, i; ++ int interface_number; + + if (interface == NULL) + return; +@@ -1139,6 +1101,11 @@ static void line6_disconnect(struct usb_interface *interface) + line6_pod_disconnect(interface); + break; + ++ case LINE6_DEVID_PODHD300: ++ case LINE6_DEVID_PODHD500: ++ line6_podhd_disconnect(interface); ++ break; ++ + case LINE6_DEVID_PODXTLIVE: + switch (interface_number) { + case PODXTLIVE_INTERFACE_POD: +@@ -1172,10 +1139,6 @@ static void line6_disconnect(struct usb_interface *interface) + + dev_info(&interface->dev, "Line6 %s now disconnected\n", + line6->properties->name); +- +- for (i = LINE6_MAX_DEVICES; i--;) +- if (line6_devices[i] == line6) +- line6_devices[i] = NULL; + } + + line6_destruct(interface); +@@ -1258,69 +1221,7 @@ static struct usb_driver line6_driver = { + .id_table = line6_id_table, + }; + +-/* +- Module initialization. +-*/ +-static int __init line6_init(void) +-{ +- int i, retval; +- +- printk(KERN_INFO "%s driver version %s\n", DRIVER_NAME, DRIVER_VERSION); +- +- for (i = LINE6_MAX_DEVICES; i--;) +- line6_devices[i] = NULL; +- +- retval = usb_register(&line6_driver); +- +- if (retval) { +- err("usb_register failed. Error number %d", retval); +- return retval; +- } +- +- line6_request_version = kmalloc(sizeof(line6_request_version0), +- GFP_KERNEL); +- +- if (line6_request_version == NULL) { +- err("Out of memory"); +- return -ENOMEM; +- } +- +- memcpy((char *)line6_request_version, line6_request_version0, +- sizeof(line6_request_version0)); +- +- return retval; +-} +- +-/* +- Module cleanup. +-*/ +-static void __exit line6_exit(void) +-{ +- int i; +- struct usb_line6 *line6; +- struct snd_line6_pcm *line6pcm; +- +- /* stop all PCM channels */ +- for (i = LINE6_MAX_DEVICES; i--;) { +- line6 = line6_devices[i]; +- +- if (line6 == NULL) +- continue; +- +- line6pcm = line6->line6pcm; +- +- if (line6pcm == NULL) +- continue; +- +- line6_pcm_stop(line6pcm, ~0); +- } +- +- usb_deregister(&line6_driver); +- kfree(line6_request_version); +-} +- +-module_init(line6_init); +-module_exit(line6_exit); ++module_usb_driver(line6_driver); + + MODULE_AUTHOR(DRIVER_AUTHOR); + MODULE_DESCRIPTION(DRIVER_DESC); +diff --git a/drivers/staging/line6/driver.h b/drivers/staging/line6/driver.h +index 553192f..f0be5a2 100644 +--- a/drivers/staging/line6/driver.h ++++ b/drivers/staging/line6/driver.h +@@ -20,12 +20,11 @@ + + #define DRIVER_NAME "line6usb" + +-#if defined(CONFIG_LINE6_USB_DUMP_CTRL) || defined(CONFIG_LINE6_USB_DUMP_MIDI) || defined(CONFIG_LINE6_USB_DUMP_PCM) ++#if defined(CONFIG_LINE6_USB_DUMP_PCM) + #define CONFIG_LINE6_USB_DUMP_ANY + #endif + + #define LINE6_TIMEOUT 1 +-#define LINE6_MAX_DEVICES 8 + #define LINE6_BUFSIZE_LISTEN 32 + #define LINE6_MESSAGE_MAXLEN 256 + +@@ -53,12 +52,6 @@ + + #define LINE6_CHANNEL_MASK 0x0f + +-#ifdef CONFIG_LINE6_USB_DEBUG +-#define DEBUG_MESSAGES(x) (x) +-#else +-#define DEBUG_MESSAGES(x) +-#endif +- + #define MISSING_CASE \ + printk(KERN_ERR "line6usb driver bug: missing case in %s:%d\n", \ + __FILE__, __LINE__) +@@ -78,7 +71,6 @@ do { \ + } while (0) + + extern const unsigned char line6_midi_id[3]; +-extern struct usb_line6 *line6_devices[LINE6_MAX_DEVICES]; + + static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3; + static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4; +@@ -88,6 +80,11 @@ static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4; + */ + struct line6_properties { + /** ++ Bit identifying this device in the line6usb driver. ++ */ ++ int device_bit; ++ ++ /** + Card id string (maximum 16 characters). + This can be used to address the device in ALSA programs as + "default:CARD=" +@@ -100,11 +97,6 @@ struct line6_properties { + const char *name; + + /** +- Bit identifying this device in the line6usb driver. +- */ +- int device_bit; +- +- /** + Bit vector defining this device's capabilities in the + line6usb driver. + */ +@@ -209,7 +201,7 @@ extern int line6_read_data(struct usb_line6 *line6, int address, void *data, + size_t datalen); + extern int line6_read_serial_number(struct usb_line6 *line6, + int *serial_number); +-extern int line6_send_program(struct usb_line6 *line6, int value); ++extern int line6_send_program(struct usb_line6 *line6, u8 value); + extern int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, + int size); + extern int line6_send_raw_message_async(struct usb_line6 *line6, +@@ -224,7 +216,7 @@ extern void line6_start_timer(struct timer_list *timer, unsigned int msecs, + void (*function) (unsigned long), + unsigned long data); + extern int line6_transmit_parameter(struct usb_line6 *line6, int param, +- int value); ++ u8 value); + extern int line6_version_request_async(struct usb_line6 *line6); + extern int line6_write_data(struct usb_line6 *line6, int address, void *data, + size_t datalen); +diff --git a/drivers/staging/line6/dumprequest.c b/drivers/staging/line6/dumprequest.c +deleted file mode 100644 +index 60c7bae..0000000 +--- a/drivers/staging/line6/dumprequest.c ++++ /dev/null +@@ -1,135 +0,0 @@ +-/* +- * Line6 Linux USB driver - 0.9.1beta +- * +- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) +- * +- * This program is free software; 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. +- * +- */ +- +-#include +- +-#include "driver.h" +-#include "dumprequest.h" +- +-/* +- Set "dump in progress" flag. +-*/ +-void line6_dump_started(struct line6_dump_request *l6dr, int dest) +-{ +- l6dr->in_progress = dest; +-} +- +-/* +- Invalidate current channel, i.e., set "dump in progress" flag. +- Reading from the "dump" special file blocks until dump is completed. +-*/ +-void line6_invalidate_current(struct line6_dump_request *l6dr) +-{ +- line6_dump_started(l6dr, LINE6_DUMP_CURRENT); +-} +- +-/* +- Clear "dump in progress" flag and notify waiting processes. +-*/ +-void line6_dump_finished(struct line6_dump_request *l6dr) +-{ +- l6dr->in_progress = LINE6_DUMP_NONE; +- wake_up(&l6dr->wait); +-} +- +-/* +- Send an asynchronous channel dump request. +-*/ +-int line6_dump_request_async(struct line6_dump_request *l6dr, +- struct usb_line6 *line6, int num, int dest) +-{ +- int ret; +- line6_dump_started(l6dr, dest); +- ret = line6_send_raw_message_async(line6, l6dr->reqbufs[num].buffer, +- l6dr->reqbufs[num].length); +- +- if (ret < 0) +- line6_dump_finished(l6dr); +- +- return ret; +-} +- +-/* +- Wait for completion (interruptible). +-*/ +-int line6_dump_wait_interruptible(struct line6_dump_request *l6dr) +-{ +- return wait_event_interruptible(l6dr->wait, +- l6dr->in_progress == LINE6_DUMP_NONE); +-} +- +-/* +- Wait for completion. +-*/ +-void line6_dump_wait(struct line6_dump_request *l6dr) +-{ +- wait_event(l6dr->wait, l6dr->in_progress == LINE6_DUMP_NONE); +-} +- +-/* +- Wait for completion (with timeout). +-*/ +-int line6_dump_wait_timeout(struct line6_dump_request *l6dr, long timeout) +-{ +- return wait_event_timeout(l6dr->wait, +- l6dr->in_progress == LINE6_DUMP_NONE, +- timeout); +-} +- +-/* +- Initialize dump request buffer. +-*/ +-int line6_dumpreq_initbuf(struct line6_dump_request *l6dr, const void *buf, +- size_t len, int num) +-{ +- l6dr->reqbufs[num].buffer = kmemdup(buf, len, GFP_KERNEL); +- if (l6dr->reqbufs[num].buffer == NULL) +- return -ENOMEM; +- l6dr->reqbufs[num].length = len; +- return 0; +-} +- +-/* +- Initialize dump request data structure (including one buffer). +-*/ +-int line6_dumpreq_init(struct line6_dump_request *l6dr, const void *buf, +- size_t len) +-{ +- int ret; +- ret = line6_dumpreq_initbuf(l6dr, buf, len, 0); +- if (ret < 0) +- return ret; +- init_waitqueue_head(&l6dr->wait); +- return 0; +-} +- +-/* +- Destruct dump request data structure. +-*/ +-void line6_dumpreq_destructbuf(struct line6_dump_request *l6dr, int num) +-{ +- if (l6dr == NULL) +- return; +- if (l6dr->reqbufs[num].buffer == NULL) +- return; +- kfree(l6dr->reqbufs[num].buffer); +- l6dr->reqbufs[num].buffer = NULL; +-} +- +-/* +- Destruct dump request data structure. +-*/ +-void line6_dumpreq_destruct(struct line6_dump_request *l6dr) +-{ +- if (l6dr->reqbufs[0].buffer == NULL) +- return; +- line6_dumpreq_destructbuf(l6dr, 0); +-} +diff --git a/drivers/staging/line6/dumprequest.h b/drivers/staging/line6/dumprequest.h +deleted file mode 100644 +index c17a262..0000000 +--- a/drivers/staging/line6/dumprequest.h ++++ /dev/null +@@ -1,76 +0,0 @@ +-/* +- * Line6 Linux USB driver - 0.9.1beta +- * +- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) +- * +- * This program is free software; 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. +- * +- */ +- +-#ifndef DUMPREQUEST_H +-#define DUMPREQUEST_H +- +-#include +-#include +-#include +- +-enum { +- LINE6_DUMP_NONE, +- LINE6_DUMP_CURRENT +-}; +- +-struct line6_dump_reqbuf { +- /** +- Buffer for dump requests. +- */ +- unsigned char *buffer; +- +- /** +- Size of dump request. +- */ +- size_t length; +-}; +- +-/** +- Provides the functionality to request channel/model/... dump data from a +- Line6 device. +-*/ +-struct line6_dump_request { +- /** +- Wait queue for access to program dump data. +- */ +- wait_queue_head_t wait; +- +- /** +- Indicates an unfinished program dump request. +- 0: no dump +- 1: dump current settings +- Other device-specific values are also allowed. +- */ +- int in_progress; +- +- /** +- Dump request buffers +- */ +- struct line6_dump_reqbuf reqbufs[1]; +-}; +- +-extern void line6_dump_finished(struct line6_dump_request *l6dr); +-extern int line6_dump_request_async(struct line6_dump_request *l6dr, +- struct usb_line6 *line6, int num, int dest); +-extern void line6_dump_started(struct line6_dump_request *l6dr, int dest); +-extern void line6_dumpreq_destruct(struct line6_dump_request *l6dr); +-extern void line6_dumpreq_destructbuf(struct line6_dump_request *l6dr, int num); +-extern int line6_dumpreq_init(struct line6_dump_request *l6dr, const void *buf, +- size_t len); +-extern int line6_dumpreq_initbuf(struct line6_dump_request *l6dr, +- const void *buf, size_t len, int num); +-extern void line6_invalidate_current(struct line6_dump_request *l6dr); +-extern void line6_dump_wait(struct line6_dump_request *l6dr); +-extern int line6_dump_wait_interruptible(struct line6_dump_request *l6dr); +-extern int line6_dump_wait_timeout(struct line6_dump_request *l6dr, +- long timeout); +- +-#endif +diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c +index e554a2d..6982eca 100644 +--- a/drivers/staging/line6/midi.c ++++ b/drivers/staging/line6/midi.c +@@ -59,9 +59,6 @@ static void line6_midi_transmit(struct snd_rawmidi_substream *substream) + if (done == 0) + break; + +-#ifdef CONFIG_LINE6_USB_DUMP_MIDI +- line6_write_hexdump(line6, 's', chunk, done); +-#endif + line6_midibuf_write(mb, chunk, done); + snd_rawmidi_transmit_ack(substream, done); + } +@@ -72,10 +69,6 @@ static void line6_midi_transmit(struct snd_rawmidi_substream *substream) + if (done == 0) + break; + +- if (line6_midibuf_skip_message +- (mb, line6midi->midi_mask_transmit)) +- continue; +- + send_midi_async(line6, chunk, done); + } + +@@ -131,11 +124,8 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data, + dev_err(line6->ifcdev, "Out of memory\n"); + return -ENOMEM; + } +-#ifdef CONFIG_LINE6_USB_DUMP_CTRL +- line6_write_hexdump(line6, 'S', data, length); +-#endif + +- transfer_buffer = kmalloc(length, GFP_ATOMIC); ++ transfer_buffer = kmemdup(data, length, GFP_ATOMIC); + + if (transfer_buffer == NULL) { + usb_free_urb(urb); +@@ -143,7 +133,6 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data, + return -ENOMEM; + } + +- memcpy(transfer_buffer, data, length); + usb_fill_int_urb(urb, line6->usbdev, + usb_sndbulkpipe(line6->usbdev, + line6->ep_control_write), +@@ -159,26 +148,6 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data, + } + + ++line6->line6midi->num_active_send_urbs; +- +- switch (line6->usbdev->descriptor.idProduct) { +- case LINE6_DEVID_BASSPODXT: +- case LINE6_DEVID_BASSPODXTLIVE: +- case LINE6_DEVID_BASSPODXTPRO: +- case LINE6_DEVID_PODXT: +- case LINE6_DEVID_PODXTLIVE: +- case LINE6_DEVID_PODXTPRO: +- case LINE6_DEVID_POCKETPOD: +- line6_pod_midi_postprocess((struct usb_line6_pod *)line6, data, +- length); +- break; +- +- case LINE6_DEVID_VARIAX: +- break; +- +- default: +- MISSING_CASE; +- } +- + return 0; + } + +@@ -286,83 +255,10 @@ static int snd_line6_new_midi(struct snd_line6_midi *line6midi) + return 0; + } + +-/* +- "read" request on "midi_mask_transmit" special file. +-*/ +-static ssize_t midi_get_midi_mask_transmit(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6 *line6 = usb_get_intfdata(interface); +- return sprintf(buf, "%d\n", line6->line6midi->midi_mask_transmit); +-} +- +-/* +- "write" request on "midi_mask" special file. +-*/ +-static ssize_t midi_set_midi_mask_transmit(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6 *line6 = usb_get_intfdata(interface); +- unsigned long value; +- int ret; +- +- ret = strict_strtoul(buf, 10, &value); +- if (ret) +- return ret; +- +- line6->line6midi->midi_mask_transmit = value; +- return count; +-} +- +-/* +- "read" request on "midi_mask_receive" special file. +-*/ +-static ssize_t midi_get_midi_mask_receive(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6 *line6 = usb_get_intfdata(interface); +- return sprintf(buf, "%d\n", line6->line6midi->midi_mask_receive); +-} +- +-/* +- "write" request on "midi_mask" special file. +-*/ +-static ssize_t midi_set_midi_mask_receive(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6 *line6 = usb_get_intfdata(interface); +- unsigned long value; +- int ret; +- +- ret = strict_strtoul(buf, 10, &value); +- if (ret) +- return ret; +- +- line6->line6midi->midi_mask_receive = value; +- return count; +-} +- +-static DEVICE_ATTR(midi_mask_transmit, S_IWUSR | S_IRUGO, +- midi_get_midi_mask_transmit, midi_set_midi_mask_transmit); +-static DEVICE_ATTR(midi_mask_receive, S_IWUSR | S_IRUGO, +- midi_get_midi_mask_receive, midi_set_midi_mask_receive); +- + /* MIDI device destructor */ + static int snd_line6_midi_free(struct snd_device *device) + { + struct snd_line6_midi *line6midi = device->device_data; +- device_remove_file(line6midi->line6->ifcdev, +- &dev_attr_midi_mask_transmit); +- device_remove_file(line6midi->line6->ifcdev, +- &dev_attr_midi_mask_receive); + line6_midibuf_destroy(&line6midi->midibuf_in); + line6_midibuf_destroy(&line6midi->midibuf_out); + return 0; +@@ -391,16 +287,19 @@ int line6_init_midi(struct usb_line6 *line6) + return -ENOMEM; + + err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0); +- if (err < 0) ++ if (err < 0) { ++ kfree(line6midi); + return err; ++ } + + err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1); +- if (err < 0) ++ if (err < 0) { ++ kfree(line6midi->midibuf_in.buf); ++ kfree(line6midi); + return err; ++ } + + line6midi->line6 = line6; +- line6midi->midi_mask_transmit = 1; +- line6midi->midi_mask_receive = 4; + line6->line6midi = line6midi; + + err = snd_device_new(line6->card, SNDRV_DEV_RAWMIDI, line6midi, +@@ -414,14 +313,6 @@ int line6_init_midi(struct usb_line6 *line6) + if (err < 0) + return err; + +- err = device_create_file(line6->ifcdev, &dev_attr_midi_mask_transmit); +- if (err < 0) +- return err; +- +- err = device_create_file(line6->ifcdev, &dev_attr_midi_mask_receive); +- if (err < 0) +- return err; +- + init_waitqueue_head(&line6midi->send_wait); + spin_lock_init(&line6midi->send_urb_lock); + spin_lock_init(&line6midi->midi_transmit_lock); +diff --git a/drivers/staging/line6/midi.h b/drivers/staging/line6/midi.h +index b73a025..19dabd5 100644 +--- a/drivers/staging/line6/midi.h ++++ b/drivers/staging/line6/midi.h +@@ -55,16 +55,6 @@ struct snd_line6_midi { + wait_queue_head_t send_wait; + + /** +- Bit mask for output MIDI channels. +- */ +- int midi_mask_transmit; +- +- /** +- Bit mask for input MIDI channels. +- */ +- int midi_mask_receive; +- +- /** + Buffer for incoming MIDI stream. + */ + struct MidiBuffer midibuf_in; +diff --git a/drivers/staging/line6/midibuf.c b/drivers/staging/line6/midibuf.c +index 7b532e5..968e0de 100644 +--- a/drivers/staging/line6/midibuf.c ++++ b/drivers/staging/line6/midibuf.c +@@ -64,9 +64,9 @@ int line6_midibuf_init(struct MidiBuffer *this, int size, int split) + + void line6_midibuf_status(struct MidiBuffer *this) + { +- printk(KERN_DEBUG "midibuf size=%d split=%d pos_read=%d pos_write=%d " +- "full=%d command_prev=%02x\n", this->size, this->split, +- this->pos_read, this->pos_write, this->full, this->command_prev); ++ pr_debug("midibuf size=%d split=%d pos_read=%d pos_write=%d full=%d command_prev=%02x\n", ++ this->size, this->split, this->pos_read, this->pos_write, ++ this->full, this->command_prev); + } + + int line6_midibuf_bytes_free(struct MidiBuffer *this) +diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c +index 955c6de..0640de3 100644 +--- a/drivers/staging/line6/pcm.c ++++ b/drivers/staging/line6/pcm.c +@@ -48,13 +48,19 @@ static ssize_t pcm_set_impulse_volume(struct device *dev, + const char *buf, size_t count) + { + struct snd_line6_pcm *line6pcm = dev2pcm(dev); +- int value = simple_strtoul(buf, NULL, 10); ++ int value; ++ int rv; ++ ++ rv = kstrtoint(buf, 10, &value); ++ if (rv < 0) ++ return rv; ++ + line6pcm->impulse_volume = value; + + if (value > 0) +- line6_pcm_start(line6pcm, MASK_PCM_IMPULSE); ++ line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_IMPULSE); + else +- line6_pcm_stop(line6pcm, MASK_PCM_IMPULSE); ++ line6_pcm_release(line6pcm, LINE6_BITS_PCM_IMPULSE); + + return count; + } +@@ -86,50 +92,52 @@ static DEVICE_ATTR(impulse_period, S_IWUSR | S_IRUGO, pcm_get_impulse_period, + + #endif + +-int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels) ++static bool test_flags(unsigned long flags0, unsigned long flags1, ++ unsigned long mask) + { +- unsigned long flags_old, flags_new; ++ return ((flags0 & mask) == 0) && ((flags1 & mask) != 0); ++} ++ ++int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels) ++{ ++ unsigned long flags_old, flags_new, flags_final; + int err; + + do { + flags_old = ACCESS_ONCE(line6pcm->flags); + flags_new = flags_old | channels; ++ flags_final = flags_old; + } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); + +-#if LINE6_BACKUP_MONITOR_SIGNAL +- if (!(line6pcm->line6->properties->capabilities & LINE6_BIT_HWMON)) { +- line6pcm->prev_fbuf = +- kmalloc(LINE6_ISO_PACKETS * line6pcm->max_packet_size, +- GFP_KERNEL); ++ line6pcm->prev_fbuf = NULL; + +- if (!line6pcm->prev_fbuf) { +- dev_err(line6pcm->line6->ifcdev, +- "cannot malloc monitor buffer\n"); +- return -ENOMEM; ++ if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_BUFFER)) { ++ /* Invoked multiple times in a row so allocate once only */ ++ if (!line6pcm->buffer_in) { ++ line6pcm->buffer_in = ++ kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * ++ line6pcm->max_packet_size, GFP_KERNEL); ++ ++ if (!line6pcm->buffer_in) { ++ dev_err(line6pcm->line6->ifcdev, ++ "cannot malloc capture buffer\n"); ++ err = -ENOMEM; ++ goto pcm_acquire_error; ++ } ++ ++ flags_final |= channels & LINE6_BITS_CAPTURE_BUFFER; + } + } +-#else +- line6pcm->prev_fbuf = NULL; +-#endif + +- if (((flags_old & MASK_CAPTURE) == 0) && +- ((flags_new & MASK_CAPTURE) != 0)) { ++ if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_STREAM)) { + /* + Waiting for completion of active URBs in the stop handler is + a bug, we therefore report an error if capturing is restarted + too soon. + */ +- if (line6pcm->active_urb_in | line6pcm->unlink_urb_in) ++ if (line6pcm->active_urb_in | line6pcm->unlink_urb_in) { ++ dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n"); + return -EBUSY; +- +- line6pcm->buffer_in = +- kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * +- line6pcm->max_packet_size, GFP_KERNEL); +- +- if (!line6pcm->buffer_in) { +- dev_err(line6pcm->line6->ifcdev, +- "cannot malloc capture buffer\n"); +- return -ENOMEM; + } + + line6pcm->count_in = 0; +@@ -137,37 +145,55 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels) + err = line6_submit_audio_in_all_urbs(line6pcm); + + if (err < 0) +- goto fail; ++ goto pcm_acquire_error; ++ ++ flags_final |= channels & LINE6_BITS_CAPTURE_STREAM; + } + +- if (((flags_old & MASK_PLAYBACK) == 0) && +- ((flags_new & MASK_PLAYBACK) != 0)) { +- /* +- See comment above regarding PCM restart. +- */ +- if (line6pcm->active_urb_out | line6pcm->unlink_urb_out) +- return -EBUSY; ++ if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_BUFFER)) { ++ /* Invoked multiple times in a row so allocate once only */ ++ if (!line6pcm->buffer_out) { ++ line6pcm->buffer_out = ++ kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * ++ line6pcm->max_packet_size, GFP_KERNEL); ++ ++ if (!line6pcm->buffer_out) { ++ dev_err(line6pcm->line6->ifcdev, ++ "cannot malloc playback buffer\n"); ++ err = -ENOMEM; ++ goto pcm_acquire_error; ++ } + +- line6pcm->buffer_out = +- kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * +- line6pcm->max_packet_size, GFP_KERNEL); ++ flags_final |= channels & LINE6_BITS_PLAYBACK_BUFFER; ++ } ++ } + +- if (!line6pcm->buffer_out) { +- dev_err(line6pcm->line6->ifcdev, +- "cannot malloc playback buffer\n"); +- return -ENOMEM; ++ if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_STREAM)) { ++ /* ++ See comment above regarding PCM restart. ++ */ ++ if (line6pcm->active_urb_out | line6pcm->unlink_urb_out) { ++ dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n"); ++ return -EBUSY; + } + + line6pcm->count_out = 0; + err = line6_submit_audio_out_all_urbs(line6pcm); + + if (err < 0) +- goto fail; ++ goto pcm_acquire_error; ++ ++ flags_final |= channels & LINE6_BITS_PLAYBACK_STREAM; + } + + return 0; + +-fail: ++pcm_acquire_error: ++ /* ++ If not all requested resources/streams could be obtained, release ++ those which were successfully obtained (if any). ++ */ ++ line6_pcm_release(line6pcm, flags_final & channels); + do { + flags_old = ACCESS_ONCE(line6pcm->flags); + flags_new = flags_old & ~channels; +@@ -176,7 +202,7 @@ fail: + return err; + } + +-int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels) ++int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels) + { + unsigned long flags_old, flags_new; + +@@ -185,22 +211,21 @@ int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels) + flags_new = flags_old & ~channels; + } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); + +- if (((flags_old & MASK_CAPTURE) != 0) && +- ((flags_new & MASK_CAPTURE) == 0)) { ++ if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM)) + line6_unlink_audio_in_urbs(line6pcm); +- kfree(line6pcm->buffer_in); +- line6pcm->buffer_in = NULL; ++ ++ if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_BUFFER)) { ++ line6_wait_clear_audio_in_urbs(line6pcm); ++ line6_free_capture_buffer(line6pcm); + } + +- if (((flags_old & MASK_PLAYBACK) != 0) && +- ((flags_new & MASK_PLAYBACK) == 0)) { ++ if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_STREAM)) + line6_unlink_audio_out_urbs(line6pcm); +- kfree(line6pcm->buffer_out); +- line6pcm->buffer_out = NULL; ++ ++ if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_BUFFER)) { ++ line6_wait_clear_audio_out_urbs(line6pcm); ++ line6_free_playback_buffer(line6pcm); + } +-#if LINE6_BACKUP_MONITOR_SIGNAL +- kfree(line6pcm->prev_fbuf); +-#endif + + return 0; + } +@@ -214,7 +239,7 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) + unsigned long flags; + + spin_lock_irqsave(&line6pcm->lock_trigger, flags); +- clear_bit(BIT_PREPARED, &line6pcm->flags); ++ clear_bit(LINE6_INDEX_PREPARED, &line6pcm->flags); + + snd_pcm_group_for_each_entry(s, substream) { + switch (s->stream) { +@@ -416,10 +441,12 @@ int line6_init_pcm(struct usb_line6 *line6, + case LINE6_DEVID_PODXT: + case LINE6_DEVID_PODXTLIVE: + case LINE6_DEVID_PODXTPRO: ++ case LINE6_DEVID_PODHD300: + ep_read = 0x82; + ep_write = 0x01; + break; + ++ case LINE6_DEVID_PODHD500: + case LINE6_DEVID_PODX3: + case LINE6_DEVID_PODX3LIVE: + ep_read = 0x86; +@@ -464,9 +491,14 @@ int line6_init_pcm(struct usb_line6 *line6, + line6pcm->line6 = line6; + line6pcm->ep_audio_read = ep_read; + line6pcm->ep_audio_write = ep_write; +- line6pcm->max_packet_size = usb_maxpacket(line6->usbdev, +- usb_rcvintpipe(line6->usbdev, +- ep_read), 0); ++ ++ /* Read and write buffers are sized identically, so choose minimum */ ++ line6pcm->max_packet_size = min( ++ usb_maxpacket(line6->usbdev, ++ usb_rcvisocpipe(line6->usbdev, ep_read), 0), ++ usb_maxpacket(line6->usbdev, ++ usb_sndisocpipe(line6->usbdev, ep_write), 1)); ++ + line6pcm->properties = properties; + line6->line6pcm = line6pcm; + +@@ -521,7 +553,24 @@ int snd_line6_prepare(struct snd_pcm_substream *substream) + { + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + +- if (!test_and_set_bit(BIT_PREPARED, &line6pcm->flags)) { ++ switch (substream->stream) { ++ case SNDRV_PCM_STREAM_PLAYBACK: ++ if ((line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) == 0) ++ line6_unlink_wait_clear_audio_out_urbs(line6pcm); ++ ++ break; ++ ++ case SNDRV_PCM_STREAM_CAPTURE: ++ if ((line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) == 0) ++ line6_unlink_wait_clear_audio_in_urbs(line6pcm); ++ ++ break; ++ ++ default: ++ MISSING_CASE; ++ } ++ ++ if (!test_and_set_bit(LINE6_INDEX_PREPARED, &line6pcm->flags)) { + line6pcm->count_out = 0; + line6pcm->pos_out = 0; + line6pcm->pos_out_done = 0; +diff --git a/drivers/staging/line6/pcm.h b/drivers/staging/line6/pcm.h +index 77055b3..6aa0d46 100644 +--- a/drivers/staging/line6/pcm.h ++++ b/drivers/staging/line6/pcm.h +@@ -39,9 +39,6 @@ + #define LINE6_IMPULSE_DEFAULT_PERIOD 100 + #endif + +-#define LINE6_BACKUP_MONITOR_SIGNAL 0 +-#define LINE6_REUSE_DMA_AREA_FOR_PLAYBACK 0 +- + /* + Get substream from Line6 PCM data structure + */ +@@ -49,57 +46,131 @@ + (line6pcm->pcm->streams[stream].substream) + + /* +- PCM mode bits and masks. +- "ALSA": operations triggered by applications via ALSA +- "MONITOR": software monitoring +- "IMPULSE": optional impulse response operation ++ PCM mode bits. ++ ++ There are several features of the Line6 USB driver which require PCM ++ data to be exchanged with the device: ++ *) PCM playback and capture via ALSA ++ *) software monitoring (for devices without hardware monitoring) ++ *) optional impulse response measurement ++ However, from the device's point of view, there is just a single ++ capture and playback stream, which must be shared between these ++ subsystems. It is therefore necessary to maintain the state of the ++ subsystems with respect to PCM usage. We define several constants of ++ the form LINE6_BIT_PCM___ with the ++ following meanings: ++ *) is one of ++ -) ALSA: PCM playback and capture via ALSA ++ -) MONITOR: software monitoring ++ -) IMPULSE: optional impulse response measurement ++ *) is one of ++ -) PLAYBACK: audio output (from host to device) ++ -) CAPTURE: audio input (from device to host) ++ *) is one of ++ -) BUFFER: buffer required by PCM data stream ++ -) STREAM: actual PCM data stream ++ ++ The subsystems call line6_pcm_acquire() to acquire the (shared) ++ resources needed for a particular operation (e.g., allocate the buffer ++ for ALSA playback or start the capture stream for software monitoring). ++ When a resource is no longer needed, it is released by calling ++ line6_pcm_release(). Buffer allocation and stream startup are handled ++ separately to allow the ALSA kernel driver to perform them at ++ appropriate places (since the callback which starts a PCM stream is not ++ allowed to sleep). + */ + enum { +- /* individual bits: */ +- BIT_PCM_ALSA_PLAYBACK, +- BIT_PCM_ALSA_CAPTURE, +- BIT_PCM_MONITOR_PLAYBACK, +- BIT_PCM_MONITOR_CAPTURE, ++ /* individual bit indices: */ ++ LINE6_INDEX_PCM_ALSA_PLAYBACK_BUFFER, ++ LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, ++ LINE6_INDEX_PCM_ALSA_CAPTURE_BUFFER, ++ LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM, ++ LINE6_INDEX_PCM_MONITOR_PLAYBACK_BUFFER, ++ LINE6_INDEX_PCM_MONITOR_PLAYBACK_STREAM, ++ LINE6_INDEX_PCM_MONITOR_CAPTURE_BUFFER, ++ LINE6_INDEX_PCM_MONITOR_CAPTURE_STREAM, + #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE +- BIT_PCM_IMPULSE_PLAYBACK, +- BIT_PCM_IMPULSE_CAPTURE, ++ LINE6_INDEX_PCM_IMPULSE_PLAYBACK_BUFFER, ++ LINE6_INDEX_PCM_IMPULSE_PLAYBACK_STREAM, ++ LINE6_INDEX_PCM_IMPULSE_CAPTURE_BUFFER, ++ LINE6_INDEX_PCM_IMPULSE_CAPTURE_STREAM, + #endif +- BIT_PAUSE_PLAYBACK, +- BIT_PREPARED, +- +- /* individual masks: */ +-/* *INDENT-OFF* */ +- MASK_PCM_ALSA_PLAYBACK = 1 << BIT_PCM_ALSA_PLAYBACK, +- MASK_PCM_ALSA_CAPTURE = 1 << BIT_PCM_ALSA_CAPTURE, +- MASK_PCM_MONITOR_PLAYBACK = 1 << BIT_PCM_MONITOR_PLAYBACK, +- MASK_PCM_MONITOR_CAPTURE = 1 << BIT_PCM_MONITOR_CAPTURE, ++ LINE6_INDEX_PAUSE_PLAYBACK, ++ LINE6_INDEX_PREPARED, ++ ++ /* individual bit masks: */ ++ LINE6_BIT(PCM_ALSA_PLAYBACK_BUFFER), ++ LINE6_BIT(PCM_ALSA_PLAYBACK_STREAM), ++ LINE6_BIT(PCM_ALSA_CAPTURE_BUFFER), ++ LINE6_BIT(PCM_ALSA_CAPTURE_STREAM), ++ LINE6_BIT(PCM_MONITOR_PLAYBACK_BUFFER), ++ LINE6_BIT(PCM_MONITOR_PLAYBACK_STREAM), ++ LINE6_BIT(PCM_MONITOR_CAPTURE_BUFFER), ++ LINE6_BIT(PCM_MONITOR_CAPTURE_STREAM), + #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE +- MASK_PCM_IMPULSE_PLAYBACK = 1 << BIT_PCM_IMPULSE_PLAYBACK, +- MASK_PCM_IMPULSE_CAPTURE = 1 << BIT_PCM_IMPULSE_CAPTURE, ++ LINE6_BIT(PCM_IMPULSE_PLAYBACK_BUFFER), ++ LINE6_BIT(PCM_IMPULSE_PLAYBACK_STREAM), ++ LINE6_BIT(PCM_IMPULSE_CAPTURE_BUFFER), ++ LINE6_BIT(PCM_IMPULSE_CAPTURE_STREAM), + #endif +- MASK_PAUSE_PLAYBACK = 1 << BIT_PAUSE_PLAYBACK, +- MASK_PREPARED = 1 << BIT_PREPARED, +-/* *INDENT-ON* */ ++ LINE6_BIT(PAUSE_PLAYBACK), ++ LINE6_BIT(PREPARED), ++ ++ /* combined bit masks (by operation): */ ++ LINE6_BITS_PCM_ALSA_BUFFER = ++ LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER | ++ LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER, ++ ++ LINE6_BITS_PCM_ALSA_STREAM = ++ LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM | ++ LINE6_BIT_PCM_ALSA_CAPTURE_STREAM, ++ ++ LINE6_BITS_PCM_MONITOR = ++ LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER | ++ LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM | ++ LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER | ++ LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM, + +- /* combined masks (by operation): */ +- MASK_PCM_ALSA = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_ALSA_CAPTURE, +- MASK_PCM_MONITOR = MASK_PCM_MONITOR_PLAYBACK | MASK_PCM_MONITOR_CAPTURE, + #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE +- MASK_PCM_IMPULSE = MASK_PCM_IMPULSE_PLAYBACK | MASK_PCM_IMPULSE_CAPTURE, ++ LINE6_BITS_PCM_IMPULSE = ++ LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER | ++ LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM | ++ LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER | ++ LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM, + #endif + +- /* combined masks (by direction): */ ++ /* combined bit masks (by direction): */ ++ LINE6_BITS_PLAYBACK_BUFFER = + #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE +- MASK_PLAYBACK = +- MASK_PCM_ALSA_PLAYBACK | MASK_PCM_MONITOR_PLAYBACK | +- MASK_PCM_IMPULSE_PLAYBACK, +- MASK_CAPTURE = +- MASK_PCM_ALSA_CAPTURE | MASK_PCM_MONITOR_CAPTURE | +- MASK_PCM_IMPULSE_CAPTURE +-#else +- MASK_PLAYBACK = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_MONITOR_PLAYBACK, +- MASK_CAPTURE = MASK_PCM_ALSA_CAPTURE | MASK_PCM_MONITOR_CAPTURE ++ LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER | + #endif ++ LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER | ++ LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER , ++ ++ LINE6_BITS_PLAYBACK_STREAM = ++#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE ++ LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM | ++#endif ++ LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM | ++ LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM , ++ ++ LINE6_BITS_CAPTURE_BUFFER = ++#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE ++ LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER | ++#endif ++ LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER | ++ LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER , ++ ++ LINE6_BITS_CAPTURE_STREAM = ++#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE ++ LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM | ++#endif ++ LINE6_BIT_PCM_ALSA_CAPTURE_STREAM | ++ LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM, ++ ++ LINE6_BITS_STREAM = ++ LINE6_BITS_PLAYBACK_STREAM | ++ LINE6_BITS_CAPTURE_STREAM + }; + + struct line6_pcm_properties { +@@ -149,11 +220,6 @@ struct snd_line6_pcm { + unsigned char *buffer_in; + + /** +- Temporary buffer index for playback. +- */ +- int index_out; +- +- /** + Previously captured frame (for software monitoring). + */ + unsigned char *prev_fbuf; +@@ -298,7 +364,7 @@ struct snd_line6_pcm { + #endif + + /** +- Several status bits (see BIT_*). ++ Several status bits (see LINE6_BIT_*). + */ + unsigned long flags; + +@@ -310,16 +376,7 @@ extern int line6_init_pcm(struct usb_line6 *line6, + extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd); + extern int snd_line6_prepare(struct snd_pcm_substream *substream); + extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); +-extern int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels); +-extern int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels); +- +-#define PRINT_FRAME_DIFF(op) { \ +- static int diff_prev = 1000; \ +- int diff = line6pcm->last_frame_out - line6pcm->last_frame_in; \ +- if ((diff != diff_prev) && (abs(diff) < 100)) { \ +- printk(KERN_INFO "%s frame diff = %d\n", op, diff); \ +- diff_prev = diff; \ +- } \ +-} ++extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels); ++extern int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels); + + #endif +diff --git a/drivers/staging/line6/playback.c b/drivers/staging/line6/playback.c +index 10c5438..4cf23af 100644 +--- a/drivers/staging/line6/playback.c ++++ b/drivers/staging/line6/playback.c +@@ -9,6 +9,7 @@ + * + */ + ++#include + #include + #include + #include +@@ -165,7 +166,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) + struct usb_iso_packet_descriptor *fout = + &urb_out->iso_frame_desc[i]; + +- if (line6pcm->flags & MASK_CAPTURE) ++ if (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) + fsize = line6pcm->prev_fsize; + + if (fsize == 0) { +@@ -184,22 +185,19 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) + if (urb_size == 0) { + /* can't determine URB size */ + spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags); +- dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n"); /* this is somewhat paranoid */ ++ dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n"); + return -EINVAL; + } + + urb_frames = urb_size / bytes_per_frame; + urb_out->transfer_buffer = + line6pcm->buffer_out + +- line6pcm->max_packet_size * line6pcm->index_out; ++ index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; + urb_out->transfer_buffer_length = urb_size; + urb_out->context = line6pcm; + +- if (++line6pcm->index_out == LINE6_ISO_BUFFERS) +- line6pcm->index_out = 0; +- +- if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags) && +- !test_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags)) { ++ if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags) && ++ !test_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags)) { + struct snd_pcm_runtime *runtime = + get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime; + +@@ -220,20 +218,13 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) + len * bytes_per_frame, runtime->dma_area, + (urb_frames - len) * bytes_per_frame); + } else +- dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n", len); /* this is somewhat paranoid */ ++ dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n", ++ len); + } else { +-#if LINE6_REUSE_DMA_AREA_FOR_PLAYBACK +- /* set the buffer pointer */ +- urb_out->transfer_buffer = +- runtime->dma_area + +- line6pcm->pos_out * bytes_per_frame; +-#else +- /* copy data */ + memcpy(urb_out->transfer_buffer, + runtime->dma_area + + line6pcm->pos_out * bytes_per_frame, + urb_out->transfer_buffer_length); +-#endif + } + + line6pcm->pos_out += urb_frames; +@@ -248,10 +239,10 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) + + if (line6pcm->prev_fbuf != NULL) { + #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE +- if (line6pcm->flags & MASK_PCM_IMPULSE) { ++ if (line6pcm->flags & LINE6_BITS_PCM_IMPULSE) { + create_impulse_test_signal(line6pcm, urb_out, + bytes_per_frame); +- if (line6pcm->flags & MASK_PCM_ALSA_CAPTURE) { ++ if (line6pcm->flags & LINE6_BIT_PCM_ALSA_CAPTURE_STREAM) { + line6_capture_copy(line6pcm, + urb_out->transfer_buffer, + urb_out-> +@@ -264,8 +255,8 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) + if (! + (line6pcm->line6-> + properties->capabilities & LINE6_BIT_HWMON) +-&& (line6pcm->flags & MASK_PLAYBACK) +-&& (line6pcm->flags & MASK_CAPTURE)) ++ && (line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) ++ && (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM)) + add_monitor_signal(urb_out, line6pcm->prev_fbuf, + line6pcm->volume_monitor, + bytes_per_frame); +@@ -329,9 +320,10 @@ void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm) + } + + /* +- Wait until unlinking of all currently active playback URBs has been finished. ++ Wait until unlinking of all currently active playback URBs has been ++ finished. + */ +-static void wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) ++void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) + { + int timeout = HZ; + unsigned int i; +@@ -358,7 +350,13 @@ static void wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) + void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) + { + line6_unlink_audio_out_urbs(line6pcm); +- wait_clear_audio_out_urbs(line6pcm); ++ line6_wait_clear_audio_out_urbs(line6pcm); ++} ++ ++void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm) ++{ ++ kfree(line6pcm->buffer_out); ++ line6pcm->buffer_out = NULL; + } + + /* +@@ -392,7 +390,7 @@ static void audio_out_callback(struct urb *urb) + + spin_lock_irqsave(&line6pcm->lock_audio_out, flags); + +- if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags)) { ++ if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags)) { + struct snd_pcm_runtime *runtime = substream->runtime; + line6pcm->pos_out_done += + length / line6pcm->properties->bytes_per_frame; +@@ -417,7 +415,8 @@ static void audio_out_callback(struct urb *urb) + if (!shutdown) { + submit_audio_out_urb(line6pcm); + +- if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags)) { ++ if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, ++ &line6pcm->flags)) { + line6pcm->bytes_out += length; + if (line6pcm->bytes_out >= line6pcm->period_out) { + line6pcm->bytes_out %= line6pcm->period_out; +@@ -469,10 +468,17 @@ static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream, + } + /* -- [FD] end */ + ++ ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER); ++ ++ if (ret < 0) ++ return ret; ++ + ret = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); +- if (ret < 0) ++ if (ret < 0) { ++ line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER); + return ret; ++ } + + line6pcm->period_out = params_period_bytes(hw_params); + return 0; +@@ -481,6 +487,8 @@ static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream, + /* hw_free playback callback */ + static int snd_line6_playback_hw_free(struct snd_pcm_substream *substream) + { ++ struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); ++ line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER); + return snd_pcm_lib_free_pages(substream); + } + +@@ -494,7 +502,8 @@ int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd) + #ifdef CONFIG_PM + case SNDRV_PCM_TRIGGER_RESUME: + #endif +- err = line6_pcm_start(line6pcm, MASK_PCM_ALSA_PLAYBACK); ++ err = line6_pcm_acquire(line6pcm, ++ LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM); + + if (err < 0) + return err; +@@ -505,7 +514,8 @@ int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd) + #ifdef CONFIG_PM + case SNDRV_PCM_TRIGGER_SUSPEND: + #endif +- err = line6_pcm_stop(line6pcm, MASK_PCM_ALSA_PLAYBACK); ++ err = line6_pcm_release(line6pcm, ++ LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM); + + if (err < 0) + return err; +@@ -513,11 +523,11 @@ int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd) + break; + + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: +- set_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags); ++ set_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags); + break; + + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: +- clear_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags); ++ clear_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags); + break; + + default: +diff --git a/drivers/staging/line6/playback.h b/drivers/staging/line6/playback.h +index f2fc8c0..743bd6f 100644 +--- a/drivers/staging/line6/playback.h ++++ b/drivers/staging/line6/playback.h +@@ -30,10 +30,12 @@ + extern struct snd_pcm_ops snd_line6_playback_ops; + + extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm); ++extern void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm); + extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm); + extern void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm); + extern void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm + *line6pcm); ++extern void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm); + extern int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd); + + #endif +diff --git a/drivers/staging/line6/pod.c b/drivers/staging/line6/pod.c +index d9b3021..e542540 100644 +--- a/drivers/staging/line6/pod.c ++++ b/drivers/staging/line6/pod.c +@@ -15,7 +15,6 @@ + + #include "audio.h" + #include "capture.h" +-#include "control.h" + #include "driver.h" + #include "playback.h" + #include "pod.h" +@@ -26,7 +25,6 @@ + /* *INDENT-OFF* */ + + enum { +- POD_SYSEX_CLIP = 0x0f, + POD_SYSEX_SAVE = 0x24, + POD_SYSEX_SYSTEM = 0x56, + POD_SYSEX_SYSTEMREQ = 0x57, +@@ -41,11 +39,6 @@ enum { + + enum { + POD_monitor_level = 0x04, +- POD_routing = 0x05, +- POD_tuner_mute = 0x13, +- POD_tuner_freq = 0x15, +- POD_tuner_note = 0x16, +- POD_tuner_pitch = 0x17, + POD_system_invalid = 0x10000 + }; + +@@ -118,10 +111,6 @@ static struct line6_pcm_properties pod_pcm_properties = { + .bytes_per_frame = POD_BYTES_PER_FRAME + }; + +-static const char pod_request_channel[] = { +- 0xf0, 0x00, 0x01, 0x0c, 0x03, 0x75, 0xf7 +-}; +- + static const char pod_version_header[] = { + 0xf2, 0x7e, 0x7f, 0x06, 0x02 + }; +@@ -129,18 +118,6 @@ static const char pod_version_header[] = { + /* forward declarations: */ + static void pod_startup2(unsigned long data); + static void pod_startup3(struct usb_line6_pod *pod); +-static void pod_startup4(struct usb_line6_pod *pod); +- +-/* +- Mark all parameters as dirty and notify waiting processes. +-*/ +-static void pod_mark_batch_all_dirty(struct usb_line6_pod *pod) +-{ +- int i; +- +- for (i = 0; i < POD_CONTROL_SIZE; i++) +- set_bit(i, pod->param_dirty); +-} + + static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, + int size) +@@ -150,45 +127,6 @@ static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, + } + + /* +- Send channel dump data to the PODxt Pro. +-*/ +-static void pod_dump(struct usb_line6_pod *pod, const unsigned char *data) +-{ +- int size = 1 + sizeof(pod->prog_data); +- char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMP, size); +- if (!sysex) +- return; +- /* Don't know what this is good for, but PODxt Pro transmits it, so we +- * also do... */ +- sysex[SYSEX_DATA_OFS] = 5; +- memcpy(sysex + SYSEX_DATA_OFS + 1, data, sizeof(pod->prog_data)); +- line6_send_sysex_message(&pod->line6, sysex, size); +- memcpy(&pod->prog_data, data, sizeof(pod->prog_data)); +- pod_mark_batch_all_dirty(pod); +- kfree(sysex); +-} +- +-/* +- Store parameter value in driver memory and mark it as dirty. +-*/ +-static void pod_store_parameter(struct usb_line6_pod *pod, int param, int value) +-{ +- pod->prog_data.control[param] = value; +- set_bit(param, pod->param_dirty); +- pod->dirty = 1; +-} +- +-/* +- Handle SAVE button. +-*/ +-static void pod_save_button_pressed(struct usb_line6_pod *pod, int type, +- int index) +-{ +- pod->dirty = 0; +- set_bit(POD_SAVE_PRESSED, &pod->atomic_flags); +-} +- +-/* + Process a completely received message. + */ + void line6_pod_process_message(struct usb_line6_pod *pod) +@@ -209,25 +147,11 @@ void line6_pod_process_message(struct usb_line6_pod *pod) + /* process all remaining messages */ + switch (buf[0]) { + case LINE6_PARAM_CHANGE | LINE6_CHANNEL_DEVICE: +- pod_store_parameter(pod, buf[1], buf[2]); +- /* intentionally no break here! */ +- + case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST: +- if ((buf[1] == POD_amp_model_setup) || +- (buf[1] == POD_effect_setup)) +- /* these also affect other settings */ +- line6_dump_request_async(&pod->dumpreq, &pod->line6, 0, +- LINE6_DUMP_CURRENT); +- + break; + + case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE: + case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST: +- pod->channel_num = buf[1]; +- pod->dirty = 0; +- set_bit(POD_CHANNEL_DIRTY, &pod->atomic_flags); +- line6_dump_request_async(&pod->dumpreq, &pod->line6, 0, +- LINE6_DUMP_CURRENT); + break; + + case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE: +@@ -235,43 +159,6 @@ void line6_pod_process_message(struct usb_line6_pod *pod) + if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) == 0) { + switch (buf[5]) { + case POD_SYSEX_DUMP: +- if (pod->line6.message_length == +- sizeof(pod->prog_data) + 7) { +- switch (pod->dumpreq.in_progress) { +- case LINE6_DUMP_CURRENT: +- memcpy(&pod->prog_data, buf + 7, +- sizeof(pod->prog_data)); +- pod_mark_batch_all_dirty(pod); +- break; +- +- case POD_DUMP_MEMORY: +- memcpy(&pod->prog_data_buf, +- buf + 7, +- sizeof +- (pod->prog_data_buf)); +- break; +- +- default: +- DEBUG_MESSAGES(dev_err +- (pod-> +- line6.ifcdev, +- "unknown dump code %02X\n", +- pod-> +- dumpreq.in_progress)); +- } +- +- line6_dump_finished(&pod->dumpreq); +- pod_startup3(pod); +- } else +- DEBUG_MESSAGES(dev_err +- (pod->line6.ifcdev, +- "wrong size of channel dump message (%d instead of %d)\n", +- pod-> +- line6.message_length, +- (int) +- sizeof(pod->prog_data) + +- 7)); +- + break; + + case POD_SYSEX_SYSTEM:{ +@@ -280,35 +167,8 @@ void line6_pod_process_message(struct usb_line6_pod *pod) + << 8) | + ((int)buf[9] << 4) | (int)buf[10]; + +-#define PROCESS_SYSTEM_PARAM(x) \ +- case POD_ ## x: \ +- pod->x.value = value; \ +- wake_up(&pod->x.wait); \ +- break; +- +- switch (buf[6]) { +- PROCESS_SYSTEM_PARAM +- (monitor_level); +- PROCESS_SYSTEM_PARAM(routing); +- PROCESS_SYSTEM_PARAM +- (tuner_mute); +- PROCESS_SYSTEM_PARAM +- (tuner_freq); +- PROCESS_SYSTEM_PARAM +- (tuner_note); +- PROCESS_SYSTEM_PARAM +- (tuner_pitch); +- +-#undef PROCESS_SYSTEM_PARAM +- +- default: +- DEBUG_MESSAGES(dev_err +- (pod-> +- line6.ifcdev, +- "unknown tuner/system response %02X\n", +- buf[6])); +- } +- ++ if (buf[6] == POD_monitor_level) ++ pod->monitor_level = value; + break; + } + +@@ -317,29 +177,18 @@ void line6_pod_process_message(struct usb_line6_pod *pod) + break; + + case POD_SYSEX_SAVE: +- pod_save_button_pressed(pod, buf[6], buf[7]); +- break; +- +- case POD_SYSEX_CLIP: +- DEBUG_MESSAGES(dev_err +- (pod->line6.ifcdev, +- "audio clipped\n")); +- pod->clipping.value = 1; +- wake_up(&pod->clipping.wait); + break; + + case POD_SYSEX_STORE: +- DEBUG_MESSAGES(dev_err +- (pod->line6.ifcdev, +- "message %02X not yet implemented\n", +- buf[5])); ++ dev_dbg(pod->line6.ifcdev, ++ "message %02X not yet implemented\n", ++ buf[5]); + break; + + default: +- DEBUG_MESSAGES(dev_err +- (pod->line6.ifcdev, +- "unknown sysex message %02X\n", +- buf[5])); ++ dev_dbg(pod->line6.ifcdev, ++ "unknown sysex message %02X\n", ++ buf[5]); + } + } else + if (memcmp +@@ -350,11 +199,9 @@ void line6_pod_process_message(struct usb_line6_pod *pod) + pod->device_id = + ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int) + buf[10]; +- pod_startup4(pod); ++ pod_startup3(pod); + } else +- DEBUG_MESSAGES(dev_err +- (pod->line6.ifcdev, +- "unknown sysex header\n")); ++ dev_dbg(pod->line6.ifcdev, "unknown sysex header\n"); + + break; + +@@ -362,349 +209,22 @@ void line6_pod_process_message(struct usb_line6_pod *pod) + break; + + default: +- DEBUG_MESSAGES(dev_err +- (pod->line6.ifcdev, +- "POD: unknown message %02X\n", buf[0])); ++ dev_dbg(pod->line6.ifcdev, "POD: unknown message %02X\n", ++ buf[0]); + } + } + + /* +- Detect some cases that require a channel dump after sending a command to the +- device. Important notes: +- *) The actual dump request can not be sent here since we are not allowed to +- wait for the completion of the first message in this context, and sending +- the dump request before completion of the previous message leaves the POD +- in an undefined state. The dump request will be sent when the echoed +- commands are received. +- *) This method fails if a param change message is "chopped" after the first +- byte. +-*/ +-void line6_pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data, +- int length) +-{ +- int i; +- +- if (!pod->midi_postprocess) +- return; +- +- for (i = 0; i < length; ++i) { +- if (data[i] == (LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST)) { +- line6_invalidate_current(&pod->dumpreq); +- break; +- } else +- if ((data[i] == (LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST)) +- && (i < length - 1)) +- if ((data[i + 1] == POD_amp_model_setup) +- || (data[i + 1] == POD_effect_setup)) { +- line6_invalidate_current(&pod->dumpreq); +- break; +- } +- } +-} +- +-/* +- Send channel number (i.e., switch to a different sound). +-*/ +-static void pod_send_channel(struct usb_line6_pod *pod, int value) +-{ +- line6_invalidate_current(&pod->dumpreq); +- +- if (line6_send_program(&pod->line6, value) == 0) +- pod->channel_num = value; +- else +- line6_dump_finished(&pod->dumpreq); +-} +- +-/* + Transmit PODxt Pro control parameter. + */ + void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param, +- int value) +-{ +- if (line6_transmit_parameter(&pod->line6, param, value) == 0) +- pod_store_parameter(pod, param, value); +- +- if ((param == POD_amp_model_setup) || (param == POD_effect_setup)) /* these also affect other settings */ +- line6_invalidate_current(&pod->dumpreq); +-} +- +-/* +- Resolve value to memory location. +-*/ +-static int pod_resolve(const char *buf, short block0, short block1, +- unsigned char *location) +-{ +- unsigned long value; +- short block; +- int ret; +- +- ret = strict_strtoul(buf, 10, &value); +- if (ret) +- return ret; +- +- block = (value < 0x40) ? block0 : block1; +- value &= 0x3f; +- location[0] = block >> 7; +- location[1] = value | (block & 0x7f); +- return 0; +-} +- +-/* +- Send command to store channel/effects setup/amp setup to PODxt Pro. +-*/ +-static ssize_t pod_send_store_command(struct device *dev, const char *buf, +- size_t count, short block0, short block1) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- int ret; +- int size = 3 + sizeof(pod->prog_data_buf); +- char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_STORE, size); +- +- if (!sysex) +- return 0; +- +- sysex[SYSEX_DATA_OFS] = 5; /* see pod_dump() */ +- ret = pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS + 1); +- if (ret) { +- kfree(sysex); +- return ret; +- } +- +- memcpy(sysex + SYSEX_DATA_OFS + 3, &pod->prog_data_buf, +- sizeof(pod->prog_data_buf)); +- +- line6_send_sysex_message(&pod->line6, sysex, size); +- kfree(sysex); +- /* needs some delay here on AMD64 platform */ +- return count; +-} +- +-/* +- Send command to retrieve channel/effects setup/amp setup to PODxt Pro. +-*/ +-static ssize_t pod_send_retrieve_command(struct device *dev, const char *buf, +- size_t count, short block0, +- short block1) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- int ret; +- int size = 4; +- char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMPMEM, size); +- +- if (!sysex) +- return 0; +- +- ret = pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS); +- if (ret) { +- kfree(sysex); +- return ret; +- } +- sysex[SYSEX_DATA_OFS + 2] = 0; +- sysex[SYSEX_DATA_OFS + 3] = 0; +- line6_dump_started(&pod->dumpreq, POD_DUMP_MEMORY); +- +- if (line6_send_sysex_message(&pod->line6, sysex, size) < size) +- line6_dump_finished(&pod->dumpreq); +- +- kfree(sysex); +- /* needs some delay here on AMD64 platform */ +- return count; +-} +- +-/* +- Generic get name function. +-*/ +-static ssize_t get_name_generic(struct usb_line6_pod *pod, const char *str, +- char *buf) ++ u8 value) + { +- int length = 0; +- const char *p1; +- char *p2; +- char *last_non_space = buf; +- +- int retval = line6_dump_wait_interruptible(&pod->dumpreq); +- if (retval < 0) +- return retval; +- +- for (p1 = str, p2 = buf; *p1; ++p1, ++p2) { +- *p2 = *p1; +- if (*p2 != ' ') +- last_non_space = p2; +- if (++length == POD_NAME_LENGTH) +- break; +- } +- +- *(last_non_space + 1) = '\n'; +- return last_non_space - buf + 2; +-} +- +-/* +- "read" request on "channel" special file. +-*/ +-static ssize_t pod_get_channel(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- return sprintf(buf, "%d\n", pod->channel_num); +-} +- +-/* +- "write" request on "channel" special file. +-*/ +-static ssize_t pod_set_channel(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- unsigned long value; +- int ret; +- +- ret = strict_strtoul(buf, 10, &value); +- if (ret) +- return ret; +- +- pod_send_channel(pod, value); +- return count; +-} +- +-/* +- "read" request on "name" special file. +-*/ +-static ssize_t pod_get_name(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- return get_name_generic(pod, pod->prog_data.header + POD_NAME_OFFSET, +- buf); +-} +- +-/* +- "read" request on "name" special file. +-*/ +-static ssize_t pod_get_name_buf(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- return get_name_generic(pod, +- pod->prog_data_buf.header + POD_NAME_OFFSET, +- buf); +-} +- +-/* +- "read" request on "dump" special file. +-*/ +-static ssize_t pod_get_dump(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- int retval = line6_dump_wait_interruptible(&pod->dumpreq); +- if (retval < 0) +- return retval; +- memcpy(buf, &pod->prog_data, sizeof(pod->prog_data)); +- return sizeof(pod->prog_data); +-} +- +-/* +- "write" request on "dump" special file. +-*/ +-static ssize_t pod_set_dump(struct device *dev, struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- +- if (count != sizeof(pod->prog_data)) { +- dev_err(pod->line6.ifcdev, +- "data block must be exactly %d bytes\n", +- (int)sizeof(pod->prog_data)); +- return -EINVAL; +- } +- +- pod_dump(pod, buf); +- return sizeof(pod->prog_data); +-} +- +-/* +- Identify system parameters related to the tuner. +-*/ +-static bool pod_is_tuner(int code) +-{ +- return +- (code == POD_tuner_mute) || +- (code == POD_tuner_freq) || +- (code == POD_tuner_note) || (code == POD_tuner_pitch); +-} +- +-/* +- Get system parameter (as integer). +- @param tuner non-zero, if code refers to a tuner parameter +-*/ +-static int pod_get_system_param_int(struct usb_line6_pod *pod, int *value, +- int code, struct ValueWait *param, int sign) +-{ +- char *sysex; +- static const int size = 1; +- int retval = 0; +- +- if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) +- && pod_is_tuner(code)) +- return -ENODEV; +- +- /* send value request to device: */ +- param->value = POD_system_invalid; +- sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEMREQ, size); +- +- if (!sysex) +- return -ENOMEM; +- +- sysex[SYSEX_DATA_OFS] = code; +- line6_send_sysex_message(&pod->line6, sysex, size); +- kfree(sysex); +- +- /* wait for device to respond: */ +- retval = +- wait_event_interruptible(param->wait, +- param->value != POD_system_invalid); +- +- if (retval < 0) +- return retval; +- +- *value = sign ? (int)(signed short)param->value : (int)(unsigned short) +- param->value; +- +- if (*value == POD_system_invalid) +- *value = 0; /* don't report uninitialized values */ +- +- return 0; +-} +- +-/* +- Get system parameter (as string). +- @param tuner non-zero, if code refers to a tuner parameter +-*/ +-static ssize_t pod_get_system_param_string(struct usb_line6_pod *pod, char *buf, +- int code, struct ValueWait *param, +- int sign) +-{ +- int retval, value = 0; +- retval = pod_get_system_param_int(pod, &value, code, param, sign); +- +- if (retval < 0) +- return retval; +- +- return sprintf(buf, "%d\n", value); ++ line6_transmit_parameter(&pod->line6, param, value); + } + + /* + Send system parameter (from integer). +- @param tuner non-zero, if code refers to a tuner parameter + */ + static int pod_set_system_param_int(struct usb_line6_pod *pod, int value, + int code) +@@ -712,11 +232,6 @@ static int pod_set_system_param_int(struct usb_line6_pod *pod, int value, + char *sysex; + static const int size = 5; + +- if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) +- && pod_is_tuner(code)) +- return -EINVAL; +- +- /* send value to tuner: */ + sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size); + if (!sysex) + return -ENOMEM; +@@ -731,179 +246,6 @@ static int pod_set_system_param_int(struct usb_line6_pod *pod, int value, + } + + /* +- Send system parameter (from string). +- @param tuner non-zero, if code refers to a tuner parameter +-*/ +-static ssize_t pod_set_system_param_string(struct usb_line6_pod *pod, +- const char *buf, int count, int code, +- unsigned short mask) +-{ +- int retval; +- unsigned short value = simple_strtoul(buf, NULL, 10) & mask; +- retval = pod_set_system_param_int(pod, value, code); +- return (retval < 0) ? retval : count; +-} +- +-/* +- "read" request on "dump_buf" special file. +-*/ +-static ssize_t pod_get_dump_buf(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- int retval = line6_dump_wait_interruptible(&pod->dumpreq); +- if (retval < 0) +- return retval; +- memcpy(buf, &pod->prog_data_buf, sizeof(pod->prog_data_buf)); +- return sizeof(pod->prog_data_buf); +-} +- +-/* +- "write" request on "dump_buf" special file. +-*/ +-static ssize_t pod_set_dump_buf(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- +- if (count != sizeof(pod->prog_data)) { +- dev_err(pod->line6.ifcdev, +- "data block must be exactly %d bytes\n", +- (int)sizeof(pod->prog_data)); +- return -EINVAL; +- } +- +- memcpy(&pod->prog_data_buf, buf, sizeof(pod->prog_data)); +- return sizeof(pod->prog_data); +-} +- +-/* +- "write" request on "finish" special file. +-*/ +-static ssize_t pod_set_finish(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- int size = 0; +- char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_FINISH, size); +- if (!sysex) +- return 0; +- line6_send_sysex_message(&pod->line6, sysex, size); +- kfree(sysex); +- return count; +-} +- +-/* +- "write" request on "store_channel" special file. +-*/ +-static ssize_t pod_set_store_channel(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- return pod_send_store_command(dev, buf, count, 0x0000, 0x00c0); +-} +- +-/* +- "write" request on "store_effects_setup" special file. +-*/ +-static ssize_t pod_set_store_effects_setup(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- return pod_send_store_command(dev, buf, count, 0x0080, 0x0080); +-} +- +-/* +- "write" request on "store_amp_setup" special file. +-*/ +-static ssize_t pod_set_store_amp_setup(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- return pod_send_store_command(dev, buf, count, 0x0040, 0x0100); +-} +- +-/* +- "write" request on "retrieve_channel" special file. +-*/ +-static ssize_t pod_set_retrieve_channel(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- return pod_send_retrieve_command(dev, buf, count, 0x0000, 0x00c0); +-} +- +-/* +- "write" request on "retrieve_effects_setup" special file. +-*/ +-static ssize_t pod_set_retrieve_effects_setup(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- return pod_send_retrieve_command(dev, buf, count, 0x0080, 0x0080); +-} +- +-/* +- "write" request on "retrieve_amp_setup" special file. +-*/ +-static ssize_t pod_set_retrieve_amp_setup(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- return pod_send_retrieve_command(dev, buf, count, 0x0040, 0x0100); +-} +- +-/* +- "read" request on "dirty" special file. +-*/ +-static ssize_t pod_get_dirty(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- buf[0] = pod->dirty ? '1' : '0'; +- buf[1] = '\n'; +- return 2; +-} +- +-/* +- "read" request on "midi_postprocess" special file. +-*/ +-static ssize_t pod_get_midi_postprocess(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- return sprintf(buf, "%d\n", pod->midi_postprocess); +-} +- +-/* +- "write" request on "midi_postprocess" special file. +-*/ +-static ssize_t pod_set_midi_postprocess(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- unsigned long value; +- int ret; +- +- ret = strict_strtoul(buf, 10, &value); +- if (ret) +- return ret; +- +- pod->midi_postprocess = value ? 1 : 0; +- return count; +-} +- +-/* + "read" request on "serial_number" special file. + */ + static ssize_t pod_get_serial_number(struct device *dev, +@@ -939,18 +281,6 @@ static ssize_t pod_get_device_id(struct device *dev, + } + + /* +- "read" request on "clip" special file. +-*/ +-static ssize_t pod_wait_for_clip(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct usb_interface *interface = to_usb_interface(dev); +- struct usb_line6_pod *pod = usb_get_intfdata(interface); +- return wait_event_interruptible(pod->clipping.wait, +- pod->clipping.value != 0); +-} +- +-/* + POD startup procedure. + This is a sequence of functions with special requirements (e.g., must + not run immediately after initialization, must not run in interrupt +@@ -969,22 +299,6 @@ static void pod_startup1(struct usb_line6_pod *pod) + static void pod_startup2(unsigned long data) + { + struct usb_line6_pod *pod = (struct usb_line6_pod *)data; +- +- /* schedule another startup procedure until startup is complete: */ +- if (pod->startup_progress >= POD_STARTUP_LAST) +- return; +- +- pod->startup_progress = POD_STARTUP_DUMPREQ; +- line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2, +- (unsigned long)pod); +- +- /* current channel dump: */ +- line6_dump_request_async(&pod->dumpreq, &pod->line6, 0, +- LINE6_DUMP_CURRENT); +-} +- +-static void pod_startup3(struct usb_line6_pod *pod) +-{ + struct usb_line6 *line6 = &pod->line6; + CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ); + +@@ -992,7 +306,7 @@ static void pod_startup3(struct usb_line6_pod *pod) + line6_version_request_async(line6); + } + +-static void pod_startup4(struct usb_line6_pod *pod) ++static void pod_startup3(struct usb_line6_pod *pod) + { + CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE); + +@@ -1000,7 +314,7 @@ static void pod_startup4(struct usb_line6_pod *pod) + schedule_work(&pod->startup_work); + } + +-static void pod_startup5(struct work_struct *work) ++static void pod_startup4(struct work_struct *work) + { + struct usb_line6_pod *pod = + container_of(work, struct usb_line6_pod, startup_work); +@@ -1013,87 +327,14 @@ static void pod_startup5(struct work_struct *work) + + /* ALSA audio interface: */ + line6_register_audio(line6); +- +- /* device files: */ +- line6_pod_create_files(pod->firmware_version, +- line6->properties->device_bit, line6->ifcdev); + } + +-#define POD_GET_SYSTEM_PARAM(code, sign) \ +-static ssize_t pod_get_ ## code(struct device *dev, \ +- struct device_attribute *attr, char *buf) \ +-{ \ +- struct usb_interface *interface = to_usb_interface(dev); \ +- struct usb_line6_pod *pod = usb_get_intfdata(interface); \ +- return pod_get_system_param_string(pod, buf, POD_ ## code, \ +- &pod->code, sign); \ +-} +- +-#define POD_GET_SET_SYSTEM_PARAM(code, mask, sign) \ +-POD_GET_SYSTEM_PARAM(code, sign) \ +-static ssize_t pod_set_ ## code(struct device *dev, \ +- struct device_attribute *attr, \ +- const char *buf, size_t count) \ +-{ \ +- struct usb_interface *interface = to_usb_interface(dev); \ +- struct usb_line6_pod *pod = usb_get_intfdata(interface); \ +- return pod_set_system_param_string(pod, buf, count, POD_ ## code, mask); \ +-} +- +-POD_GET_SET_SYSTEM_PARAM(monitor_level, 0xffff, 0); +-POD_GET_SET_SYSTEM_PARAM(routing, 0x0003, 0); +-POD_GET_SET_SYSTEM_PARAM(tuner_mute, 0x0001, 0); +-POD_GET_SET_SYSTEM_PARAM(tuner_freq, 0xffff, 0); +-POD_GET_SYSTEM_PARAM(tuner_note, 1); +-POD_GET_SYSTEM_PARAM(tuner_pitch, 1); +- +-#undef GET_SET_SYSTEM_PARAM +-#undef GET_SYSTEM_PARAM +- + /* POD special files: */ +-static DEVICE_ATTR(channel, S_IWUSR | S_IRUGO, pod_get_channel, +- pod_set_channel); +-static DEVICE_ATTR(clip, S_IRUGO, pod_wait_for_clip, line6_nop_write); + static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write); +-static DEVICE_ATTR(dirty, S_IRUGO, pod_get_dirty, line6_nop_write); +-static DEVICE_ATTR(dump, S_IWUSR | S_IRUGO, pod_get_dump, pod_set_dump); +-static DEVICE_ATTR(dump_buf, S_IWUSR | S_IRUGO, pod_get_dump_buf, +- pod_set_dump_buf); +-static DEVICE_ATTR(finish, S_IWUSR, line6_nop_read, pod_set_finish); + static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version, + line6_nop_write); +-static DEVICE_ATTR(midi_postprocess, S_IWUSR | S_IRUGO, +- pod_get_midi_postprocess, pod_set_midi_postprocess); +-static DEVICE_ATTR(monitor_level, S_IWUSR | S_IRUGO, pod_get_monitor_level, +- pod_set_monitor_level); +-static DEVICE_ATTR(name, S_IRUGO, pod_get_name, line6_nop_write); +-static DEVICE_ATTR(name_buf, S_IRUGO, pod_get_name_buf, line6_nop_write); +-static DEVICE_ATTR(retrieve_amp_setup, S_IWUSR, line6_nop_read, +- pod_set_retrieve_amp_setup); +-static DEVICE_ATTR(retrieve_channel, S_IWUSR, line6_nop_read, +- pod_set_retrieve_channel); +-static DEVICE_ATTR(retrieve_effects_setup, S_IWUSR, line6_nop_read, +- pod_set_retrieve_effects_setup); +-static DEVICE_ATTR(routing, S_IWUSR | S_IRUGO, pod_get_routing, +- pod_set_routing); + static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number, + line6_nop_write); +-static DEVICE_ATTR(store_amp_setup, S_IWUSR, line6_nop_read, +- pod_set_store_amp_setup); +-static DEVICE_ATTR(store_channel, S_IWUSR, line6_nop_read, +- pod_set_store_channel); +-static DEVICE_ATTR(store_effects_setup, S_IWUSR, line6_nop_read, +- pod_set_store_effects_setup); +-static DEVICE_ATTR(tuner_freq, S_IWUSR | S_IRUGO, pod_get_tuner_freq, +- pod_set_tuner_freq); +-static DEVICE_ATTR(tuner_mute, S_IWUSR | S_IRUGO, pod_get_tuner_mute, +- pod_set_tuner_mute); +-static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write); +-static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write); +- +-#ifdef CONFIG_LINE6_USB_RAW +-static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw); +-#endif + + /* control info callback */ + static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol, +@@ -1112,7 +353,7 @@ static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol, + { + struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); + struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6; +- ucontrol->value.integer.value[0] = pod->monitor_level.value; ++ ucontrol->value.integer.value[0] = pod->monitor_level; + return 0; + } + +@@ -1123,10 +364,10 @@ static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol, + struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); + struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6; + +- if (ucontrol->value.integer.value[0] == pod->monitor_level.value) ++ if (ucontrol->value.integer.value[0] == pod->monitor_level) + return 0; + +- pod->monitor_level.value = ucontrol->value.integer.value[0]; ++ pod->monitor_level = ucontrol->value.integer.value[0]; + pod_set_system_param_int(pod, ucontrol->value.integer.value[0], + POD_monitor_level); + return 1; +@@ -1149,20 +390,13 @@ static struct snd_kcontrol_new pod_control_monitor = { + static void pod_destruct(struct usb_interface *interface) + { + struct usb_line6_pod *pod = usb_get_intfdata(interface); +- struct usb_line6 *line6; + + if (pod == NULL) + return; +- line6 = &pod->line6; +- if (line6 == NULL) +- return; +- line6_cleanup_audio(line6); ++ line6_cleanup_audio(&pod->line6); + + del_timer(&pod->startup_timer); + cancel_work_sync(&pod->startup_work); +- +- /* free dump request data: */ +- line6_dumpreq_destruct(&pod->dumpreq); + } + + /* +@@ -1172,35 +406,9 @@ static int pod_create_files2(struct device *dev) + { + int err; + +- CHECK_RETURN(device_create_file(dev, &dev_attr_channel)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_clip)); + CHECK_RETURN(device_create_file(dev, &dev_attr_device_id)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_dirty)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_dump)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_dump_buf)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_finish)); + CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_midi_postprocess)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_monitor_level)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_name)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_name_buf)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_amp_setup)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_channel)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_effects_setup)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_routing)); + CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_store_amp_setup)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_store_channel)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_store_effects_setup)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_freq)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_mute)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_note)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_pitch)); +- +-#ifdef CONFIG_LINE6_USB_RAW +- CHECK_RETURN(device_create_file(dev, &dev_attr_raw)); +-#endif +- + return 0; + } + +@@ -1214,32 +422,11 @@ static int pod_try_init(struct usb_interface *interface, + struct usb_line6 *line6 = &pod->line6; + + init_timer(&pod->startup_timer); +- INIT_WORK(&pod->startup_work, pod_startup5); ++ INIT_WORK(&pod->startup_work, pod_startup4); + + if ((interface == NULL) || (pod == NULL)) + return -ENODEV; + +- pod->channel_num = 255; +- +- /* initialize wait queues: */ +- init_waitqueue_head(&pod->monitor_level.wait); +- init_waitqueue_head(&pod->routing.wait); +- init_waitqueue_head(&pod->tuner_mute.wait); +- init_waitqueue_head(&pod->tuner_freq.wait); +- init_waitqueue_head(&pod->tuner_note.wait); +- init_waitqueue_head(&pod->tuner_pitch.wait); +- init_waitqueue_head(&pod->clipping.wait); +- +- memset(pod->param_dirty, 0xff, sizeof(pod->param_dirty)); +- +- /* initialize USB buffers: */ +- err = line6_dumpreq_init(&pod->dumpreq, pod_request_channel, +- sizeof(pod_request_channel)); +- if (err < 0) { +- dev_err(&interface->dev, "Out of memory\n"); +- return -ENOMEM; +- } +- + /* create sysfs entries: */ + err = pod_create_files2(&interface->dev); + if (err < 0) +@@ -1273,7 +460,7 @@ static int pod_try_init(struct usb_interface *interface, + */ + + if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) { +- pod->monitor_level.value = POD_system_invalid; ++ pod->monitor_level = POD_system_invalid; + + /* initiate startup procedure: */ + pod_startup1(pod); +@@ -1315,39 +502,9 @@ void line6_pod_disconnect(struct usb_interface *interface) + + if (dev != NULL) { + /* remove sysfs entries: */ +- line6_pod_remove_files(pod->firmware_version, +- pod->line6. +- properties->device_bit, dev); +- +- device_remove_file(dev, &dev_attr_channel); +- device_remove_file(dev, &dev_attr_clip); + device_remove_file(dev, &dev_attr_device_id); +- device_remove_file(dev, &dev_attr_dirty); +- device_remove_file(dev, &dev_attr_dump); +- device_remove_file(dev, &dev_attr_dump_buf); +- device_remove_file(dev, &dev_attr_finish); + device_remove_file(dev, &dev_attr_firmware_version); +- device_remove_file(dev, &dev_attr_midi_postprocess); +- device_remove_file(dev, &dev_attr_monitor_level); +- device_remove_file(dev, &dev_attr_name); +- device_remove_file(dev, &dev_attr_name_buf); +- device_remove_file(dev, &dev_attr_retrieve_amp_setup); +- device_remove_file(dev, &dev_attr_retrieve_channel); +- device_remove_file(dev, +- &dev_attr_retrieve_effects_setup); +- device_remove_file(dev, &dev_attr_routing); + device_remove_file(dev, &dev_attr_serial_number); +- device_remove_file(dev, &dev_attr_store_amp_setup); +- device_remove_file(dev, &dev_attr_store_channel); +- device_remove_file(dev, &dev_attr_store_effects_setup); +- device_remove_file(dev, &dev_attr_tuner_freq); +- device_remove_file(dev, &dev_attr_tuner_mute); +- device_remove_file(dev, &dev_attr_tuner_note); +- device_remove_file(dev, &dev_attr_tuner_pitch); +- +-#ifdef CONFIG_LINE6_USB_RAW +- device_remove_file(dev, &dev_attr_raw); +-#endif + } + } + +diff --git a/drivers/staging/line6/pod.h b/drivers/staging/line6/pod.h +index 18b9d08..3e3f167 100644 +--- a/drivers/staging/line6/pod.h ++++ b/drivers/staging/line6/pod.h +@@ -15,12 +15,10 @@ + #include + #include + #include +-#include + + #include + + #include "driver.h" +-#include "dumprequest.h" + + /* + PODxt Live interfaces +@@ -46,37 +44,12 @@ + */ + enum { + POD_STARTUP_INIT = 1, +- POD_STARTUP_DUMPREQ, + POD_STARTUP_VERSIONREQ, + POD_STARTUP_WORKQUEUE, + POD_STARTUP_SETUP, + POD_STARTUP_LAST = POD_STARTUP_SETUP - 1 + }; + +-/** +- Data structure for values that need to be requested explicitly. +- This is the case for system and tuner settings. +-*/ +-struct ValueWait { +- int value; +- wait_queue_head_t wait; +-}; +- +-/** +- Binary PODxt Pro program dump +-*/ +-struct pod_program { +- /** +- Header information (including program name). +- */ +- unsigned char header[0x20]; +- +- /** +- Program parameters. +- */ +- unsigned char control[POD_CONTROL_SIZE]; +-}; +- + struct usb_line6_pod { + /** + Generic Line6 USB data. +@@ -84,63 +57,9 @@ struct usb_line6_pod { + struct usb_line6 line6; + + /** +- Dump request structure. +- */ +- struct line6_dump_request dumpreq; +- +- /** +- Current program number. +- */ +- unsigned char channel_num; +- +- /** +- Current program settings. +- */ +- struct pod_program prog_data; +- +- /** +- Buffer for data retrieved from or to be stored on PODxt Pro. +- */ +- struct pod_program prog_data_buf; +- +- /** +- Tuner mute mode. +- */ +- struct ValueWait tuner_mute; +- +- /** +- Tuner base frequency (typically 440Hz). +- */ +- struct ValueWait tuner_freq; +- +- /** +- Note received from tuner. +- */ +- struct ValueWait tuner_note; +- +- /** +- Pitch value received from tuner. +- */ +- struct ValueWait tuner_pitch; +- +- /** + Instrument monitor level. + */ +- struct ValueWait monitor_level; +- +- /** +- Audio routing mode. +- 0: send processed guitar +- 1: send clean guitar +- 2: send clean guitar re-amp playback +- 3: send re-amp playback +- */ +- struct ValueWait routing; +- +- /** +- Wait for audio clipping event. +- */ +- struct ValueWait clipping; ++ int monitor_level; + + /** + Timer for device initializaton. +@@ -158,16 +77,6 @@ struct usb_line6_pod { + int startup_progress; + + /** +- Dirty flags for access to parameter data. +- */ +- unsigned long param_dirty[POD_CONTROL_SIZE / sizeof(unsigned long)]; +- +- /** +- Some atomic flags. +- */ +- unsigned long atomic_flags; +- +- /** + Serial number of device. + */ + int serial_number; +@@ -181,25 +90,13 @@ struct usb_line6_pod { + Device ID. + */ + int device_id; +- +- /** +- Flag to indicate modification of current program settings. +- */ +- char dirty; +- +- /** +- Flag to enable MIDI postprocessing. +- */ +- char midi_postprocess; + }; + + extern void line6_pod_disconnect(struct usb_interface *interface); + extern int line6_pod_init(struct usb_interface *interface, + struct usb_line6_pod *pod); +-extern void line6_pod_midi_postprocess(struct usb_line6_pod *pod, +- unsigned char *data, int length); + extern void line6_pod_process_message(struct usb_line6_pod *pod); + extern void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param, +- int value); ++ u8 value); + + #endif +diff --git a/drivers/staging/line6/podhd.c b/drivers/staging/line6/podhd.c +new file mode 100644 +index 0000000..7ef4543 +--- /dev/null ++++ b/drivers/staging/line6/podhd.c +@@ -0,0 +1,154 @@ ++/* ++ * Line6 Pod HD ++ * ++ * Copyright (C) 2011 Stefan Hajnoczi ++ * ++ * This program is free software; 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. ++ * ++ */ ++ ++#include ++#include ++ ++#include "audio.h" ++#include "driver.h" ++#include "pcm.h" ++#include "podhd.h" ++ ++#define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ ++ ++static struct snd_ratden podhd_ratden = { ++ .num_min = 48000, ++ .num_max = 48000, ++ .num_step = 1, ++ .den = 1, ++}; ++ ++static struct line6_pcm_properties podhd_pcm_properties = { ++ .snd_line6_playback_hw = { ++ .info = (SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_BLOCK_TRANSFER | ++ SNDRV_PCM_INFO_MMAP_VALID | ++ SNDRV_PCM_INFO_PAUSE | ++#ifdef CONFIG_PM ++ SNDRV_PCM_INFO_RESUME | ++#endif ++ SNDRV_PCM_INFO_SYNC_START), ++ .formats = SNDRV_PCM_FMTBIT_S24_3LE, ++ .rates = SNDRV_PCM_RATE_48000, ++ .rate_min = 48000, ++ .rate_max = 48000, ++ .channels_min = 2, ++ .channels_max = 2, ++ .buffer_bytes_max = 60000, ++ .period_bytes_min = 64, ++ .period_bytes_max = 8192, ++ .periods_min = 1, ++ .periods_max = 1024}, ++ .snd_line6_capture_hw = { ++ .info = (SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_BLOCK_TRANSFER | ++ SNDRV_PCM_INFO_MMAP_VALID | ++#ifdef CONFIG_PM ++ SNDRV_PCM_INFO_RESUME | ++#endif ++ SNDRV_PCM_INFO_SYNC_START), ++ .formats = SNDRV_PCM_FMTBIT_S24_3LE, ++ .rates = SNDRV_PCM_RATE_48000, ++ .rate_min = 48000, ++ .rate_max = 48000, ++ .channels_min = 2, ++ .channels_max = 2, ++ .buffer_bytes_max = 60000, ++ .period_bytes_min = 64, ++ .period_bytes_max = 8192, ++ .periods_min = 1, ++ .periods_max = 1024}, ++ .snd_line6_rates = { ++ .nrats = 1, ++ .rats = &podhd_ratden}, ++ .bytes_per_frame = PODHD_BYTES_PER_FRAME ++}; ++ ++/* ++ POD HD destructor. ++*/ ++static void podhd_destruct(struct usb_interface *interface) ++{ ++ struct usb_line6_podhd *podhd = usb_get_intfdata(interface); ++ ++ if (podhd == NULL) ++ return; ++ line6_cleanup_audio(&podhd->line6); ++} ++ ++/* ++ Try to init POD HD device. ++*/ ++static int podhd_try_init(struct usb_interface *interface, ++ struct usb_line6_podhd *podhd) ++{ ++ int err; ++ struct usb_line6 *line6 = &podhd->line6; ++ ++ if ((interface == NULL) || (podhd == NULL)) ++ return -ENODEV; ++ ++ /* initialize audio system: */ ++ err = line6_init_audio(line6); ++ if (err < 0) ++ return err; ++ ++ /* initialize MIDI subsystem: */ ++ err = line6_init_midi(line6); ++ if (err < 0) ++ return err; ++ ++ /* initialize PCM subsystem: */ ++ err = line6_init_pcm(line6, &podhd_pcm_properties); ++ if (err < 0) ++ return err; ++ ++ /* register USB audio system: */ ++ err = line6_register_audio(line6); ++ return err; ++} ++ ++/* ++ Init POD HD device (and clean up in case of failure). ++*/ ++int line6_podhd_init(struct usb_interface *interface, ++ struct usb_line6_podhd *podhd) ++{ ++ int err = podhd_try_init(interface, podhd); ++ ++ if (err < 0) ++ podhd_destruct(interface); ++ ++ return err; ++} ++ ++/* ++ POD HD device disconnected. ++*/ ++void line6_podhd_disconnect(struct usb_interface *interface) ++{ ++ struct usb_line6_podhd *podhd; ++ ++ if (interface == NULL) ++ return; ++ podhd = usb_get_intfdata(interface); ++ ++ if (podhd != NULL) { ++ struct snd_line6_pcm *line6pcm = podhd->line6.line6pcm; ++ ++ if (line6pcm != NULL) ++ line6_pcm_disconnect(line6pcm); ++ } ++ ++ podhd_destruct(interface); ++} +diff --git a/drivers/staging/line6/podhd.h b/drivers/staging/line6/podhd.h +new file mode 100644 +index 0000000..652f740 +--- /dev/null ++++ b/drivers/staging/line6/podhd.h +@@ -0,0 +1,30 @@ ++/* ++ * Line6 Pod HD ++ * ++ * Copyright (C) 2011 Stefan Hajnoczi ++ * ++ * This program is free software; 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. ++ * ++ */ ++ ++#ifndef PODHD_H ++#define PODHD_H ++ ++#include ++ ++#include "driver.h" ++ ++struct usb_line6_podhd { ++ /** ++ Generic Line6 USB data. ++ */ ++ struct usb_line6 line6; ++}; ++ ++extern void line6_podhd_disconnect(struct usb_interface *interface); ++extern int line6_podhd_init(struct usb_interface *interface, ++ struct usb_line6_podhd *podhd); ++ ++#endif /* PODHD_H */ +diff --git a/drivers/staging/line6/revision.h b/drivers/staging/line6/revision.h +index 350d0df..b4eee2b 100644 +--- a/drivers/staging/line6/revision.h ++++ b/drivers/staging/line6/revision.h +@@ -1,4 +1,4 @@ + #ifndef DRIVER_REVISION + /* current subversion revision */ +-#define DRIVER_REVISION " (revision 690)" ++#define DRIVER_REVISION " (904)" + #endif +diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c +index 879e699..a529dd3 100644 +--- a/drivers/staging/line6/toneport.c ++++ b/drivers/staging/line6/toneport.c +@@ -127,13 +127,11 @@ static ssize_t toneport_set_led_red(struct device *dev, + const char *buf, size_t count) + { + int retval; +- long value; + +- retval = strict_strtol(buf, 10, &value); ++ retval = kstrtoint(buf, 10, &led_red); + if (retval) + return retval; + +- led_red = value; + toneport_update_led(dev); + return count; + } +@@ -143,13 +141,11 @@ static ssize_t toneport_set_led_green(struct device *dev, + const char *buf, size_t count) + { + int retval; +- long value; + +- retval = strict_strtol(buf, 10, &value); ++ retval = kstrtoint(buf, 10, &led_green); + if (retval) + return retval; + +- led_green = value; + toneport_update_led(dev); + return count; + } +@@ -168,7 +164,7 @@ static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) + cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ); + + if (ret < 0) { +- err("send failed (error %d)\n", ret); ++ dev_err(&usbdev->dev, "send failed (error %d)\n", ret); + return ret; + } + +@@ -207,9 +203,9 @@ static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol, + line6pcm->volume_monitor = ucontrol->value.integer.value[0]; + + if (line6pcm->volume_monitor > 0) +- line6_pcm_start(line6pcm, MASK_PCM_MONITOR); ++ line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_MONITOR); + else +- line6_pcm_stop(line6pcm, MASK_PCM_MONITOR); ++ line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR); + + return 1; + } +@@ -264,7 +260,7 @@ static void toneport_start_pcm(unsigned long arg) + { + struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg; + struct usb_line6 *line6 = &toneport->line6; +- line6_pcm_start(line6->line6pcm, MASK_PCM_MONITOR); ++ line6_pcm_acquire(line6->line6pcm, LINE6_BITS_PCM_MONITOR); + } + + /* control definition */ +@@ -295,14 +291,10 @@ static struct snd_kcontrol_new toneport_control_source = { + static void toneport_destruct(struct usb_interface *interface) + { + struct usb_line6_toneport *toneport = usb_get_intfdata(interface); +- struct usb_line6 *line6; + + if (toneport == NULL) + return; +- line6 = &toneport->line6; +- if (line6 == NULL) +- return; +- line6_cleanup_audio(line6); ++ line6_cleanup_audio(&toneport->line6); + } + + /* +@@ -324,7 +316,9 @@ static void toneport_setup(struct usb_line6_toneport *toneport) + /* initialize source select: */ + switch (usbdev->descriptor.idProduct) { + case LINE6_DEVID_TONEPORT_UX1: ++ case LINE6_DEVID_TONEPORT_UX2: + case LINE6_DEVID_PODSTUDIO_UX1: ++ case LINE6_DEVID_PODSTUDIO_UX2: + toneport_send_cmd(usbdev, + toneport_source_info[toneport->source].code, + 0x0000); +@@ -367,7 +361,9 @@ static int toneport_try_init(struct usb_interface *interface, + /* register source select control: */ + switch (usbdev->descriptor.idProduct) { + case LINE6_DEVID_TONEPORT_UX1: ++ case LINE6_DEVID_TONEPORT_UX2: + case LINE6_DEVID_PODSTUDIO_UX1: ++ case LINE6_DEVID_PODSTUDIO_UX2: + err = + snd_ctl_add(line6->card, + snd_ctl_new1(&toneport_control_source, +@@ -446,7 +442,7 @@ void line6_toneport_disconnect(struct usb_interface *interface) + struct snd_line6_pcm *line6pcm = toneport->line6.line6pcm; + + if (line6pcm != NULL) { +- line6_pcm_stop(line6pcm, MASK_PCM_MONITOR); ++ line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR); + line6_pcm_disconnect(line6pcm); + } + } +diff --git a/drivers/staging/line6/usbdefs.h b/drivers/staging/line6/usbdefs.h +index c6dffe6..43eb540 100644 +--- a/drivers/staging/line6/usbdefs.h ++++ b/drivers/staging/line6/usbdefs.h +@@ -24,6 +24,8 @@ + #define LINE6_DEVID_BASSPODXTPRO 0x4252 + #define LINE6_DEVID_GUITARPORT 0x4750 + #define LINE6_DEVID_POCKETPOD 0x5051 ++#define LINE6_DEVID_PODHD300 0x5057 ++#define LINE6_DEVID_PODHD500 0x414D + #define LINE6_DEVID_PODSTUDIO_GX 0x4153 + #define LINE6_DEVID_PODSTUDIO_UX1 0x4150 + #define LINE6_DEVID_PODSTUDIO_UX2 0x4151 +@@ -37,48 +39,73 @@ + #define LINE6_DEVID_TONEPORT_UX2 0x4142 + #define LINE6_DEVID_VARIAX 0x534d + +-#define LINE6_BIT_BASSPODXT (1 << 0) +-#define LINE6_BIT_BASSPODXTLIVE (1 << 1) +-#define LINE6_BIT_BASSPODXTPRO (1 << 2) +-#define LINE6_BIT_GUITARPORT (1 << 3) +-#define LINE6_BIT_POCKETPOD (1 << 4) +-#define LINE6_BIT_PODSTUDIO_GX (1 << 5) +-#define LINE6_BIT_PODSTUDIO_UX1 (1 << 6) +-#define LINE6_BIT_PODSTUDIO_UX2 (1 << 7) +-#define LINE6_BIT_PODX3 (1 << 8) +-#define LINE6_BIT_PODX3LIVE (1 << 9) +-#define LINE6_BIT_PODXT (1 << 10) +-#define LINE6_BIT_PODXTLIVE (1 << 11) +-#define LINE6_BIT_PODXTPRO (1 << 12) +-#define LINE6_BIT_TONEPORT_GX (1 << 13) +-#define LINE6_BIT_TONEPORT_UX1 (1 << 14) +-#define LINE6_BIT_TONEPORT_UX2 (1 << 15) +-#define LINE6_BIT_VARIAX (1 << 16) ++#define LINE6_BIT(x) LINE6_BIT_ ## x = 1 << LINE6_INDEX_ ## x + +-#define LINE6_BITS_PRO (LINE6_BIT_BASSPODXTPRO | \ +- LINE6_BIT_PODXTPRO) +-#define LINE6_BITS_LIVE (LINE6_BIT_BASSPODXTLIVE | \ +- LINE6_BIT_PODXTLIVE | \ +- LINE6_BIT_PODX3LIVE) +-#define LINE6_BITS_PODXTALL (LINE6_BIT_PODXT | \ +- LINE6_BIT_PODXTLIVE | \ +- LINE6_BIT_PODXTPRO) +-#define LINE6_BITS_BASSPODXTALL (LINE6_BIT_BASSPODXT | \ +- LINE6_BIT_BASSPODXTLIVE | \ +- LINE6_BIT_BASSPODXTPRO) ++enum { ++ LINE6_INDEX_BASSPODXT, ++ LINE6_INDEX_BASSPODXTLIVE, ++ LINE6_INDEX_BASSPODXTPRO, ++ LINE6_INDEX_GUITARPORT, ++ LINE6_INDEX_POCKETPOD, ++ LINE6_INDEX_PODHD300, ++ LINE6_INDEX_PODHD500, ++ LINE6_INDEX_PODSTUDIO_GX, ++ LINE6_INDEX_PODSTUDIO_UX1, ++ LINE6_INDEX_PODSTUDIO_UX2, ++ LINE6_INDEX_PODX3, ++ LINE6_INDEX_PODX3LIVE, ++ LINE6_INDEX_PODXT, ++ LINE6_INDEX_PODXTLIVE, ++ LINE6_INDEX_PODXTPRO, ++ LINE6_INDEX_TONEPORT_GX, ++ LINE6_INDEX_TONEPORT_UX1, ++ LINE6_INDEX_TONEPORT_UX2, ++ LINE6_INDEX_VARIAX, ++ ++ LINE6_BIT(BASSPODXT), ++ LINE6_BIT(BASSPODXTLIVE), ++ LINE6_BIT(BASSPODXTPRO), ++ LINE6_BIT(GUITARPORT), ++ LINE6_BIT(POCKETPOD), ++ LINE6_BIT(PODHD300), ++ LINE6_BIT(PODHD500), ++ LINE6_BIT(PODSTUDIO_GX), ++ LINE6_BIT(PODSTUDIO_UX1), ++ LINE6_BIT(PODSTUDIO_UX2), ++ LINE6_BIT(PODX3), ++ LINE6_BIT(PODX3LIVE), ++ LINE6_BIT(PODXT), ++ LINE6_BIT(PODXTLIVE), ++ LINE6_BIT(PODXTPRO), ++ LINE6_BIT(TONEPORT_GX), ++ LINE6_BIT(TONEPORT_UX1), ++ LINE6_BIT(TONEPORT_UX2), ++ LINE6_BIT(VARIAX), ++ ++ LINE6_BITS_PRO = LINE6_BIT_BASSPODXTPRO | LINE6_BIT_PODXTPRO, ++ LINE6_BITS_LIVE = LINE6_BIT_BASSPODXTLIVE | LINE6_BIT_PODXTLIVE | ++ LINE6_BIT_PODX3LIVE, ++ LINE6_BITS_PODXTALL = LINE6_BIT_PODXT | LINE6_BIT_PODXTLIVE | ++ LINE6_BIT_PODXTPRO, ++ LINE6_BITS_PODX3ALL = LINE6_BIT_PODX3 | LINE6_BIT_PODX3LIVE, ++ LINE6_BITS_PODHDALL = LINE6_BIT_PODHD300 | LINE6_BIT_PODHD500, ++ LINE6_BITS_BASSPODXTALL = LINE6_BIT_BASSPODXT | ++ LINE6_BIT_BASSPODXTLIVE | ++ LINE6_BIT_BASSPODXTPRO ++}; + + /* device supports settings parameter via USB */ +-#define LINE6_BIT_CONTROL (1 << 0) ++#define LINE6_BIT_CONTROL (1 << 0) + /* device supports PCM input/output via USB */ +-#define LINE6_BIT_PCM (1 << 1) ++#define LINE6_BIT_PCM (1 << 1) + /* device support hardware monitoring */ +-#define LINE6_BIT_HWMON (1 << 2) ++#define LINE6_BIT_HWMON (1 << 2) + + #define LINE6_BIT_CONTROL_PCM_HWMON (LINE6_BIT_CONTROL | \ + LINE6_BIT_PCM | \ + LINE6_BIT_HWMON) + +-#define LINE6_FALLBACK_INTERVAL 10 +-#define LINE6_FALLBACK_MAXPACKETSIZE 16 ++#define LINE6_FALLBACK_INTERVAL 10 ++#define LINE6_FALLBACK_MAXPACKETSIZE 16 + + #endif +diff --git a/drivers/staging/line6/variax.c b/drivers/staging/line6/variax.c +index 81241cd..4fca58f 100644 +--- a/drivers/staging/line6/variax.c ++++ b/drivers/staging/line6/variax.c +@@ -12,28 +12,13 @@ + #include + + #include "audio.h" +-#include "control.h" + #include "driver.h" + #include "variax.h" + +-#define VARIAX_SYSEX_CODE 7 +-#define VARIAX_SYSEX_PARAM 0x3b +-#define VARIAX_SYSEX_ACTIVATE 0x2a +-#define VARIAX_MODEL_HEADER_LENGTH 7 +-#define VARIAX_MODEL_MESSAGE_LENGTH 199 + #define VARIAX_OFFSET_ACTIVATE 7 + + /* + This message is sent by the device during initialization and identifies +- the connected guitar model. +-*/ +-static const char variax_init_model[] = { +- 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x69, 0x02, +- 0x00 +-}; +- +-/* +- This message is sent by the device during initialization and identifies + the connected guitar version. + */ + static const char variax_init_version[] = { +@@ -53,43 +38,11 @@ static const char variax_activate[] = { + 0xf7 + }; + +-static const char variax_request_bank[] = { +- 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6d, 0xf7 +-}; +- +-static const char variax_request_model1[] = { +- 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x3c, 0x00, +- 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x03, +- 0x00, 0x00, 0x00, 0xf7 +-}; +- +-static const char variax_request_model2[] = { +- 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x3c, 0x00, +- 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x03, +- 0x00, 0x00, 0x00, 0xf7 +-}; +- + /* forward declarations: */ +-static int variax_create_files2(struct device *dev); + static void variax_startup2(unsigned long data); + static void variax_startup4(unsigned long data); + static void variax_startup5(unsigned long data); + +-/* +- Decode data transmitted by workbench. +-*/ +-static void variax_decode(const unsigned char *raw_data, unsigned char *data, +- int raw_size) +-{ +- for (; raw_size > 0; raw_size -= 6) { +- data[2] = raw_data[0] | (raw_data[1] << 4); +- data[1] = raw_data[2] | (raw_data[3] << 4); +- data[0] = raw_data[4] | (raw_data[5] << 4); +- raw_data += 6; +- data += 3; +- } +-} +- + static void variax_activate_async(struct usb_line6_variax *variax, int a) + { + variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a; +@@ -155,37 +108,21 @@ static void variax_startup5(unsigned long data) + { + struct usb_line6_variax *variax = (struct usb_line6_variax *)data; + CHECK_STARTUP_PROGRESS(variax->startup_progress, +- VARIAX_STARTUP_DUMPREQ); +- +- /* current model dump: */ +- line6_dump_request_async(&variax->dumpreq, &variax->line6, 0, +- VARIAX_DUMP_PASS1); +- /* passes 2 and 3 are performed implicitly before entering variax_startup6 */ +-} +- +-static void variax_startup6(struct usb_line6_variax *variax) +-{ +- CHECK_STARTUP_PROGRESS(variax->startup_progress, + VARIAX_STARTUP_WORKQUEUE); + + /* schedule work for global work queue: */ + schedule_work(&variax->startup_work); + } + +-static void variax_startup7(struct work_struct *work) ++static void variax_startup6(struct work_struct *work) + { + struct usb_line6_variax *variax = + container_of(work, struct usb_line6_variax, startup_work); +- struct usb_line6 *line6 = &variax->line6; + + CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP); + + /* ALSA audio interface: */ + line6_register_audio(&variax->line6); +- +- /* device files: */ +- line6_variax_create_files(0, 0, line6->ifcdev); +- variax_create_files2(line6->ifcdev); + } + + /* +@@ -197,22 +134,10 @@ void line6_variax_process_message(struct usb_line6_variax *variax) + + switch (buf[0]) { + case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST: +- switch (buf[1]) { +- case VARIAXMIDI_volume: +- variax->volume = buf[2]; +- break; +- +- case VARIAXMIDI_tone: +- variax->tone = buf[2]; +- } +- + break; + + case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE: + case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST: +- variax->model = buf[1]; +- line6_dump_request_async(&variax->dumpreq, &variax->line6, 0, +- VARIAX_DUMP_PASS1); + break; + + case LINE6_RESET: +@@ -220,401 +145,44 @@ void line6_variax_process_message(struct usb_line6_variax *variax) + break; + + case LINE6_SYSEX_BEGIN: +- if (memcmp(buf + 1, variax_request_model1 + 1, +- VARIAX_MODEL_HEADER_LENGTH - 1) == 0) { +- if (variax->line6.message_length == +- VARIAX_MODEL_MESSAGE_LENGTH) { +- switch (variax->dumpreq.in_progress) { +- case VARIAX_DUMP_PASS1: +- variax_decode(buf + +- VARIAX_MODEL_HEADER_LENGTH, +- (unsigned char *) +- &variax->model_data, +- (sizeof +- (variax->model_data. +- name) + +- sizeof(variax-> +- model_data. +- control) +- / 2) * 2); +- line6_dump_request_async +- (&variax->dumpreq, &variax->line6, +- 1, VARIAX_DUMP_PASS2); +- break; +- +- case VARIAX_DUMP_PASS2: +- /* model name is transmitted twice, so skip it here: */ +- variax_decode(buf + +- VARIAX_MODEL_HEADER_LENGTH, +- (unsigned char *) +- &variax-> +- model_data.control + +- sizeof(variax->model_data. +- control) +- / 2, +- sizeof(variax->model_data. +- control) +- / 2 * 2); +- line6_dump_request_async +- (&variax->dumpreq, &variax->line6, +- 2, VARIAX_DUMP_PASS3); +- } +- } else { +- DEBUG_MESSAGES(dev_err +- (variax->line6.ifcdev, +- "illegal length %d of model data\n", +- variax->line6.message_length)); +- line6_dump_finished(&variax->dumpreq); +- } +- } else if (memcmp(buf + 1, variax_request_bank + 1, +- sizeof(variax_request_bank) - 2) == 0) { +- memcpy(variax->bank, +- buf + sizeof(variax_request_bank) - 1, +- sizeof(variax->bank)); +- line6_dump_finished(&variax->dumpreq); +- variax_startup6(variax); +- } else if (memcmp(buf + 1, variax_init_model + 1, +- sizeof(variax_init_model) - 1) == 0) { +- memcpy(variax->guitar, +- buf + sizeof(variax_init_model), +- sizeof(variax->guitar)); +- } else if (memcmp(buf + 1, variax_init_version + 1, +- sizeof(variax_init_version) - 1) == 0) { ++ if (memcmp(buf + 1, variax_init_version + 1, ++ sizeof(variax_init_version) - 1) == 0) { + variax_startup3(variax); + } else if (memcmp(buf + 1, variax_init_done + 1, + sizeof(variax_init_done) - 1) == 0) { + /* notify of complete initialization: */ + variax_startup4((unsigned long)variax); + } +- + break; + + case LINE6_SYSEX_END: + break; + + default: +- DEBUG_MESSAGES(dev_err +- (variax->line6.ifcdev, +- "Variax: unknown message %02X\n", buf[0])); ++ dev_dbg(variax->line6.ifcdev, ++ "Variax: unknown message %02X\n", buf[0]); + } + } + + /* +- "read" request on "volume" special file. +-*/ +-static ssize_t variax_get_volume(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- return sprintf(buf, "%d\n", variax->volume); +-} +- +-/* +- "write" request on "volume" special file. +-*/ +-static ssize_t variax_set_volume(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- unsigned long value; +- int ret; +- +- ret = strict_strtoul(buf, 10, &value); +- if (ret) +- return ret; +- +- if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_volume, +- value) == 0) +- variax->volume = value; +- +- return count; +-} +- +-/* +- "read" request on "model" special file. +-*/ +-static ssize_t variax_get_model(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- return sprintf(buf, "%d\n", variax->model); +-} +- +-/* +- "write" request on "model" special file. +-*/ +-static ssize_t variax_set_model(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- unsigned long value; +- int ret; +- +- ret = strict_strtoul(buf, 10, &value); +- if (ret) +- return ret; +- +- if (line6_send_program(&variax->line6, value) == 0) +- variax->model = value; +- +- return count; +-} +- +-/* +- "read" request on "active" special file. +-*/ +-static ssize_t variax_get_active(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- return sprintf(buf, "%d\n", +- variax->buffer_activate[VARIAX_OFFSET_ACTIVATE]); +-} +- +-/* +- "write" request on "active" special file. +-*/ +-static ssize_t variax_set_active(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- unsigned long value; +- int ret; +- +- ret = strict_strtoul(buf, 10, &value); +- if (ret) +- return ret; +- +- variax_activate_async(variax, value ? 1 : 0); +- return count; +-} +- +-/* +- "read" request on "tone" special file. +-*/ +-static ssize_t variax_get_tone(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- return sprintf(buf, "%d\n", variax->tone); +-} +- +-/* +- "write" request on "tone" special file. +-*/ +-static ssize_t variax_set_tone(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- unsigned long value; +- int ret; +- +- ret = strict_strtoul(buf, 10, &value); +- if (ret) +- return ret; +- +- if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_tone, +- value) == 0) +- variax->tone = value; +- +- return count; +-} +- +-static ssize_t get_string(char *buf, const char *data, int length) +-{ +- int i; +- memcpy(buf, data, length); +- +- for (i = length; i--;) { +- char c = buf[i]; +- +- if ((c != 0) && (c != ' ')) +- break; +- } +- +- buf[i + 1] = '\n'; +- return i + 2; +-} +- +-/* +- "read" request on "name" special file. +-*/ +-static ssize_t variax_get_name(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- line6_dump_wait_interruptible(&variax->dumpreq); +- return get_string(buf, variax->model_data.name, +- sizeof(variax->model_data.name)); +-} +- +-/* +- "read" request on "bank" special file. +-*/ +-static ssize_t variax_get_bank(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- line6_dump_wait_interruptible(&variax->dumpreq); +- return get_string(buf, variax->bank, sizeof(variax->bank)); +-} +- +-/* +- "read" request on "dump" special file. +-*/ +-static ssize_t variax_get_dump(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- int retval; +- retval = line6_dump_wait_interruptible(&variax->dumpreq); +- if (retval < 0) +- return retval; +- memcpy(buf, &variax->model_data.control, +- sizeof(variax->model_data.control)); +- return sizeof(variax->model_data.control); +-} +- +-/* +- "read" request on "guitar" special file. +-*/ +-static ssize_t variax_get_guitar(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- return sprintf(buf, "%s\n", variax->guitar); +-} +- +-#ifdef CONFIG_LINE6_USB_RAW +- +-static char *variax_alloc_sysex_buffer(struct usb_line6_variax *variax, +- int code, int size) +-{ +- return line6_alloc_sysex_buffer(&variax->line6, VARIAX_SYSEX_CODE, code, +- size); +-} +- +-/* +- "write" request on "raw" special file. +-*/ +-static ssize_t variax_set_raw2(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct usb_line6_variax *variax = +- usb_get_intfdata(to_usb_interface(dev)); +- int size; +- int i; +- char *sysex; +- +- count -= count % 3; +- size = count * 2; +- sysex = variax_alloc_sysex_buffer(variax, VARIAX_SYSEX_PARAM, size); +- +- if (!sysex) +- return 0; +- +- for (i = 0; i < count; i += 3) { +- const unsigned char *p1 = buf + i; +- char *p2 = sysex + SYSEX_DATA_OFS + i * 2; +- p2[0] = p1[2] & 0x0f; +- p2[1] = p1[2] >> 4; +- p2[2] = p1[1] & 0x0f; +- p2[3] = p1[1] >> 4; +- p2[4] = p1[0] & 0x0f; +- p2[5] = p1[0] >> 4; +- } +- +- line6_send_sysex_message(&variax->line6, sysex, size); +- kfree(sysex); +- return count; +-} +- +-#endif +- +-/* Variax workbench special files: */ +-static DEVICE_ATTR(model, S_IWUSR | S_IRUGO, variax_get_model, +- variax_set_model); +-static DEVICE_ATTR(volume, S_IWUSR | S_IRUGO, variax_get_volume, +- variax_set_volume); +-static DEVICE_ATTR(tone, S_IWUSR | S_IRUGO, variax_get_tone, variax_set_tone); +-static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write); +-static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write); +-static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write); +-static DEVICE_ATTR(active, S_IWUSR | S_IRUGO, variax_get_active, +- variax_set_active); +-static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write); +- +-#ifdef CONFIG_LINE6_USB_RAW +-static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw); +-static DEVICE_ATTR(raw2, S_IWUSR, line6_nop_read, variax_set_raw2); +-#endif +- +-/* + Variax destructor. + */ + static void variax_destruct(struct usb_interface *interface) + { + struct usb_line6_variax *variax = usb_get_intfdata(interface); +- struct usb_line6 *line6; + + if (variax == NULL) + return; +- line6 = &variax->line6; +- if (line6 == NULL) +- return; +- line6_cleanup_audio(line6); ++ line6_cleanup_audio(&variax->line6); + + del_timer(&variax->startup_timer1); + del_timer(&variax->startup_timer2); + cancel_work_sync(&variax->startup_work); + +- /* free dump request data: */ +- line6_dumpreq_destructbuf(&variax->dumpreq, 2); +- line6_dumpreq_destructbuf(&variax->dumpreq, 1); +- line6_dumpreq_destruct(&variax->dumpreq); +- + kfree(variax->buffer_activate); + } + + /* +- Create sysfs entries. +-*/ +-static int variax_create_files2(struct device *dev) +-{ +- int err; +- CHECK_RETURN(device_create_file(dev, &dev_attr_model)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_volume)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_tone)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_name)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_bank)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_dump)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_active)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_guitar)); +-#ifdef CONFIG_LINE6_USB_RAW +- CHECK_RETURN(device_create_file(dev, &dev_attr_raw)); +- CHECK_RETURN(device_create_file(dev, &dev_attr_raw2)); +-#endif +- return 0; +-} +- +-/* + Try to init workbench device. + */ + static int variax_try_init(struct usb_interface *interface, +@@ -624,36 +192,12 @@ static int variax_try_init(struct usb_interface *interface, + + init_timer(&variax->startup_timer1); + init_timer(&variax->startup_timer2); +- INIT_WORK(&variax->startup_work, variax_startup7); ++ INIT_WORK(&variax->startup_work, variax_startup6); + + if ((interface == NULL) || (variax == NULL)) + return -ENODEV; + + /* initialize USB buffers: */ +- err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1, +- sizeof(variax_request_model1)); +- +- if (err < 0) { +- dev_err(&interface->dev, "Out of memory\n"); +- return err; +- } +- +- err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_model2, +- sizeof(variax_request_model2), 1); +- +- if (err < 0) { +- dev_err(&interface->dev, "Out of memory\n"); +- return err; +- } +- +- err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_bank, +- sizeof(variax_request_bank), 2); +- +- if (err < 0) { +- dev_err(&interface->dev, "Out of memory\n"); +- return err; +- } +- + variax->buffer_activate = kmemdup(variax_activate, + sizeof(variax_activate), GFP_KERNEL); + +@@ -696,28 +240,8 @@ int line6_variax_init(struct usb_interface *interface, + */ + void line6_variax_disconnect(struct usb_interface *interface) + { +- struct device *dev; +- + if (interface == NULL) + return; +- dev = &interface->dev; +- +- if (dev != NULL) { +- /* remove sysfs entries: */ +- line6_variax_remove_files(0, 0, dev); +- device_remove_file(dev, &dev_attr_model); +- device_remove_file(dev, &dev_attr_volume); +- device_remove_file(dev, &dev_attr_tone); +- device_remove_file(dev, &dev_attr_name); +- device_remove_file(dev, &dev_attr_bank); +- device_remove_file(dev, &dev_attr_dump); +- device_remove_file(dev, &dev_attr_active); +- device_remove_file(dev, &dev_attr_guitar); +-#ifdef CONFIG_LINE6_USB_RAW +- device_remove_file(dev, &dev_attr_raw); +- device_remove_file(dev, &dev_attr_raw2); +-#endif +- } + + variax_destruct(interface); + } +diff --git a/drivers/staging/line6/variax.h b/drivers/staging/line6/variax.h +index e2999ab..24de796 100644 +--- a/drivers/staging/line6/variax.h ++++ b/drivers/staging/line6/variax.h +@@ -18,7 +18,6 @@ + #include + + #include "driver.h" +-#include "dumprequest.h" + + #define VARIAX_STARTUP_DELAY1 1000 + #define VARIAX_STARTUP_DELAY3 100 +@@ -32,33 +31,11 @@ enum { + VARIAX_STARTUP_VERSIONREQ, + VARIAX_STARTUP_WAIT, + VARIAX_STARTUP_ACTIVATE, +- VARIAX_STARTUP_DUMPREQ, + VARIAX_STARTUP_WORKQUEUE, + VARIAX_STARTUP_SETUP, + VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1 + }; + +-enum { +- VARIAX_DUMP_PASS1 = LINE6_DUMP_CURRENT, +- VARIAX_DUMP_PASS2, +- VARIAX_DUMP_PASS3 +-}; +- +-/** +- Binary Variax model dump +-*/ +-struct variax_model { +- /** +- Header information (including program name). +- */ +- unsigned char name[18]; +- +- /** +- Model parameters. +- */ +- unsigned char control[78 * 2]; +-}; +- + struct usb_line6_variax { + /** + Generic Line6 USB data. +@@ -66,48 +43,11 @@ struct usb_line6_variax { + struct usb_line6 line6; + + /** +- Dump request structure. +- Append two extra buffers for 3-pass data query. +- */ +- struct line6_dump_request dumpreq; +- struct line6_dump_reqbuf extrabuf[2]; +- +- /** + Buffer for activation code. + */ + unsigned char *buffer_activate; + + /** +- Model number. +- */ +- int model; +- +- /** +- Current model settings. +- */ +- struct variax_model model_data; +- +- /** +- Name of connected guitar. +- */ +- unsigned char guitar[18]; +- +- /** +- Name of current model bank. +- */ +- unsigned char bank[18]; +- +- /** +- Position of volume dial. +- */ +- int volume; +- +- /** +- Position of tone control dial. +- */ +- int tone; +- +- /** + Handler for device initializaton. + */ + struct work_struct startup_work; +diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c +index c019df9..bda3c1a 100644 +--- a/drivers/staging/media/as102/as102_fw.c ++++ b/drivers/staging/media/as102/as102_fw.c +@@ -197,11 +197,8 @@ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap) + + /* request kernel to locate firmware file: part1 */ + errno = request_firmware(&firmware, fw1, &dev->dev); +- if (errno < 0) { +- printk(KERN_ERR "%s: unable to locate firmware file: %s\n", +- DRIVER_NAME, fw1); ++ if (errno) + goto error; +- } + + /* initiate firmware upload */ + errno = as102_firmware_upload(bus_adap, cmd_buf, firmware); +@@ -220,11 +217,8 @@ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap) + + /* request kernel to locate firmware file: part2 */ + errno = request_firmware(&firmware, fw2, &dev->dev); +- if (errno < 0) { +- printk(KERN_ERR "%s: unable to locate firmware file: %s\n", +- DRIVER_NAME, fw2); ++ if (errno) + goto error; +- } + + /* initiate firmware upload */ + errno = as102_firmware_upload(bus_adap, cmd_buf, firmware); +diff --git a/drivers/staging/media/go7007/go7007-driver.c b/drivers/staging/media/go7007/go7007-driver.c +index 6c9279a..53bcaf0 100644 +--- a/drivers/staging/media/go7007/go7007-driver.c ++++ b/drivers/staging/media/go7007/go7007-driver.c +@@ -97,11 +97,8 @@ static int go7007_load_encoder(struct go7007 *go) + int fw_len, rv = 0; + u16 intr_val, intr_data; + +- if (request_firmware(&fw_entry, fw_name, go->dev)) { +- v4l2_err(go, "unable to load firmware from file " +- "\"%s\"\n", fw_name); ++ if (request_firmware(&fw_entry, fw_name, go->dev)) + return -1; +- } + if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) { + v4l2_err(go, "file \"%s\" does not appear to be " + "go7007 firmware\n", fw_name); +diff --git a/drivers/staging/media/go7007/go7007-fw.c b/drivers/staging/media/go7007/go7007-fw.c +index c9a6409..75d0c5a 100644 +--- a/drivers/staging/media/go7007/go7007-fw.c ++++ b/drivers/staging/media/go7007/go7007-fw.c +@@ -1576,12 +1576,8 @@ int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen) + default: + return -1; + } +- if (request_firmware(&fw_entry, go->board_info->firmware, go->dev)) { +- printk(KERN_ERR +- "go7007: unable to load firmware from file \"%s\"\n", +- go->board_info->firmware); ++ if (request_firmware(&fw_entry, go->board_info->firmware, go->dev)) + return -1; +- } + code = kzalloc(codespace * 2, GFP_KERNEL); + if (code == NULL) { + printk(KERN_ERR "go7007: unable to allocate %d bytes for " +diff --git a/drivers/staging/media/go7007/s2250-loader.c b/drivers/staging/media/go7007/s2250-loader.c +index 4e13251..9b9bfa4 100644 +--- a/drivers/staging/media/go7007/s2250-loader.c ++++ b/drivers/staging/media/go7007/s2250-loader.c +@@ -98,12 +98,8 @@ static int s2250loader_probe(struct usb_interface *interface, + + mutex_unlock(&s2250_dev_table_mutex); + +- if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) { +- printk(KERN_ERR +- "s2250: unable to load firmware from file \"%s\"\n", +- S2250_LOADER_FIRMWARE); ++ if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) + goto failed2; +- } + ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2); + release_firmware(fw); + if (0 != ret) { +@@ -111,12 +107,8 @@ static int s2250loader_probe(struct usb_interface *interface, + goto failed2; + } + +- if (request_firmware(&fw, S2250_FIRMWARE, &usbdev->dev)) { +- printk(KERN_ERR +- "s2250: unable to load firmware from file \"%s\"\n", +- S2250_FIRMWARE); ++ if (request_firmware(&fw, S2250_FIRMWARE, &usbdev->dev)) + goto failed2; +- } + ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2); + release_firmware(fw); + if (0 != ret) { +diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c +index 1501e4e..0ca308a 100644 +--- a/drivers/staging/media/lirc/lirc_serial.c ++++ b/drivers/staging/media/lirc/lirc_serial.c +@@ -773,7 +773,7 @@ static int hardware_init_port(void) + /* we fail, there's nothing here */ + printk(KERN_ERR LIRC_DRIVER_NAME ": port existence test " + "failed, cannot continue\n"); +- return -EINVAL; ++ return -ENODEV; + } + + +@@ -876,10 +876,9 @@ static int __devinit lirc_serial_probe(struct platform_device *dev) + goto exit_free_irq; + } + +- if (hardware_init_port() < 0) { +- result = -EINVAL; ++ result = hardware_init_port(); ++ if (result < 0) + goto exit_release_region; +- } + + /* Initialize pulse/space widths */ + init_timing_params(duty_cycle, freq); +@@ -977,7 +976,7 @@ static ssize_t lirc_write(struct file *file, const char *buf, + int *wbuf; + + if (!(hardware[type].features & LIRC_CAN_SEND_PULSE)) +- return -EBADF; ++ return -EPERM; + + count = n / sizeof(int); + if (n % sizeof(int) || count % 2 == 0) +@@ -1028,11 +1027,11 @@ static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) + return result; + /* only LIRC_MODE_PULSE supported */ + if (value != LIRC_MODE_PULSE) +- return -ENOSYS; ++ return -EINVAL; + break; + + case LIRC_GET_LENGTH: +- return -ENOSYS; ++ return -ENOIOCTLCMD; + break; + + case LIRC_SET_SEND_DUTY_CYCLE: +@@ -1123,9 +1122,11 @@ static void lirc_serial_exit(void); + static int lirc_serial_resume(struct platform_device *dev) + { + unsigned long flags; ++ int result; + +- if (hardware_init_port() < 0) +- return -EINVAL; ++ result = hardware_init_port(); ++ if (result < 0) ++ return result; + + spin_lock_irqsave(&hardware[type].lock, flags); + /* Enable Interrupt */ +@@ -1158,7 +1159,7 @@ static int __init lirc_serial_init(void) + /* Init read buffer. */ + result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN); + if (result < 0) +- return -ENOMEM; ++ return result; + + result = platform_driver_register(&lirc_serial_driver); + if (result) { +@@ -1244,7 +1245,7 @@ static int __init lirc_serial_init_module(void) + printk(KERN_ERR LIRC_DRIVER_NAME + ": register_chrdev failed!\n"); + lirc_serial_exit(); +- return -EIO; ++ return driver.minor; + } + return 0; + } +diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c +index 0302d82..c4f1f23 100644 +--- a/drivers/staging/media/lirc/lirc_zilog.c ++++ b/drivers/staging/media/lirc/lirc_zilog.c +@@ -765,8 +765,6 @@ static int fw_load(struct IR_tx *tx) + /* Request codeset data file */ + ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->l.dev); + if (ret != 0) { +- zilog_error("firmware haup-ir-blaster.bin not available " +- "(%d)\n", ret); + ret = ret < 0 ? ret : -EFAULT; + goto out; + } +diff --git a/drivers/staging/rtl8192e/r8192E_firmware.c b/drivers/staging/rtl8192e/r8192E_firmware.c +index 3771985..b073208 100644 +--- a/drivers/staging/rtl8192e/r8192E_firmware.c ++++ b/drivers/staging/rtl8192e/r8192E_firmware.c +@@ -228,13 +228,6 @@ bool init_firmware(struct net_device *dev) + struct r8192_priv *priv = rtllib_priv(dev); + bool rt_status = true; + +- u8 *firmware_img_buf[3] = { &Rtl8192PciEFwBootArray[0], +- &Rtl8192PciEFwMainArray[0], +- &Rtl8192PciEFwDataArray[0]}; +- +- u32 firmware_img_len[3] = { sizeof(Rtl8192PciEFwBootArray), +- sizeof(Rtl8192PciEFwMainArray), +- sizeof(Rtl8192PciEFwDataArray)}; + u32 file_length = 0; + u8 *mapped_file = NULL; + u8 init_step = 0; +@@ -308,14 +301,6 @@ bool init_firmware(struct net_device *dev) + file_length = pfirmware->firmware_buf_size[init_step]; + break; + } +- case FW_SOURCE_HEADER_FILE: +- mapped_file = firmware_img_buf[init_step]; +- file_length = firmware_img_len[init_step]; +- if (init_step == FW_INIT_STEP2_DATA) { +- memcpy(pfirmware->firmware_buf[init_step], mapped_file, file_length); +- pfirmware->firmware_buf_size[init_step] = file_length; +- } +- break; + + default: + break; +diff --git a/drivers/staging/rtl8192e/r8192E_hwimg.c b/drivers/staging/rtl8192e/r8192E_hwimg.c +index 08e7dbb..85a707c 100644 +--- a/drivers/staging/rtl8192e/r8192E_hwimg.c ++++ b/drivers/staging/rtl8192e/r8192E_hwimg.c +@@ -20,2776 +20,6 @@ + + #include "r8192E_hwimg.h" + +-u8 Rtl8192PciEFwBootArray[BootArrayLengthPciE] = { +-0x10,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x3c,0x08,0xbf,0xc0,0x25,0x08,0x00,0x08, +-0x3c,0x09,0xb0,0x03,0xad,0x28,0x00,0x20,0x40,0x80,0x68,0x00,0x00,0x00,0x00,0x00, +-0x3c,0x0a,0xd0,0x00,0x40,0x8a,0x60,0x00,0x00,0x00,0x00,0x00,0x3c,0x08,0x80,0x01, +-0x25,0x08,0xa8,0x04,0x24,0x09,0x00,0x01,0x3c,0x01,0x7f,0xff,0x34,0x21,0xff,0xff, +-0x01,0x01,0x50,0x24,0x00,0x09,0x48,0x40,0x35,0x29,0x00,0x01,0x01,0x2a,0x10,0x2b, +-0x14,0x40,0xff,0xfc,0x00,0x00,0x00,0x00,0x3c,0x0a,0x00,0x00,0x25,0x4a,0x00,0x00, +-0x4c,0x8a,0x00,0x00,0x4c,0x89,0x08,0x00,0x00,0x00,0x00,0x00,0x3c,0x08,0x80,0x01, +-0x25,0x08,0xa8,0x04,0x3c,0x01,0x80,0x00,0x01,0x21,0x48,0x25,0x3c,0x0a,0xbf,0xc0, +-0x25,0x4a,0x00,0x7c,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20,0xad,0x00,0x00,0x00, +-0x21,0x08,0x00,0x04,0x01,0x09,0x10,0x2b,0x14,0x40,0xff,0xf8,0x00,0x00,0x00,0x00, +-0x3c,0x08,0x80,0x01,0x25,0x08,0x7f,0xff,0x24,0x09,0x00,0x01,0x3c,0x01,0x7f,0xff, +-0x34,0x21,0xff,0xff,0x01,0x01,0x50,0x24,0x00,0x09,0x48,0x40,0x35,0x29,0x00,0x01, +-0x01,0x2a,0x10,0x2b,0x14,0x40,0xff,0xfc,0x00,0x00,0x00,0x00,0x3c,0x0a,0x80,0x01, +-0x25,0x4a,0x00,0x00,0x3c,0x01,0x7f,0xff,0x34,0x21,0xff,0xff,0x01,0x41,0x50,0x24, +-0x3c,0x09,0x00,0x01,0x35,0x29,0x7f,0xff,0x4c,0x8a,0x20,0x00,0x4c,0x89,0x28,0x00, +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x08,0x04,0x10, +-0x00,0x00,0x00,0x00,0x40,0x88,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +-0x3c,0x08,0xbf,0xc0,0x00,0x00,0x00,0x00,0x8d,0x09,0x00,0x00,0x00,0x00,0x00,0x00, +-0x3c,0x0a,0xbf,0xc0,0x25,0x4a,0x01,0x20,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20, +-0x3c,0x08,0xb0,0x03,0x8d,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x29,0x00,0x10, +-0xad,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x08,0x80,0x00,0x25,0x08,0x4b,0x94, +-0x01,0x00,0x00,0x08,0x00,0x00,0x00,0x00,}; +- +-u8 Rtl8192PciEFwMainArray[MainArrayLengthPciE] = { +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +-0x40,0x04,0x68,0x00,0x40,0x05,0x70,0x00,0x40,0x06,0x40,0x00,0x0c,0x00,0x12,0x98, +-0x00,0x00,0x00,0x00,0x40,0x1a,0x68,0x00,0x33,0x5b,0x00,0x3c,0x17,0x60,0x00,0x09, +-0x00,0x00,0x00,0x00,0x40,0x1b,0x60,0x00,0x00,0x00,0x00,0x00,0x03,0x5b,0xd0,0x24, +-0x40,0x1a,0x70,0x00,0x03,0x40,0x00,0x08,0x42,0x00,0x00,0x10,0x00,0x00,0x00,0x00, +-0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0xff,0x34,0x42,0xff,0xff,0x8c,0x43,0x00,0x00, +-0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x00,0xd0, +-0xac,0x62,0x00,0x00,0x00,0x00,0x20,0x21,0x27,0x85,0x8b,0x70,0x00,0x85,0x18,0x21, +-0x24,0x84,0x00,0x01,0x28,0x82,0x00,0x0a,0x14,0x40,0xff,0xfc,0xa0,0x60,0x00,0x00, +-0x27,0x82,0x8b,0x7a,0x24,0x04,0x00,0x06,0x24,0x84,0xff,0xff,0xa4,0x40,0x00,0x00, +-0x04,0x81,0xff,0xfd,0x24,0x42,0x00,0x02,0x24,0x02,0x00,0x03,0xa3,0x82,0x8b,0x70, +-0x24,0x02,0x00,0x0a,0x24,0x03,0x09,0xc4,0xa3,0x82,0x8b,0x72,0x24,0x02,0x00,0x04, +-0x24,0x04,0x00,0x01,0x24,0x05,0x00,0x02,0xa7,0x83,0x8b,0x86,0xa3,0x82,0x8b,0x78, +-0x24,0x03,0x04,0x00,0x24,0x02,0x02,0x00,0xaf,0x83,0x8b,0x8c,0xa3,0x85,0x8b,0x79, +-0xa7,0x82,0x8b,0x7a,0xa7,0x84,0x8b,0x7c,0xaf,0x84,0x8b,0x88,0xa3,0x84,0x8b,0x71, +-0xa3,0x80,0x8b,0x73,0xa3,0x80,0x8b,0x74,0xa3,0x80,0x8b,0x75,0xa3,0x84,0x8b,0x76, +-0xa3,0x85,0x8b,0x77,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03, +-0x3c,0x02,0x80,0x00,0x24,0x42,0x01,0x7c,0x34,0x63,0x00,0x20,0xac,0x62,0x00,0x00, +-0x27,0x84,0x8b,0x98,0x00,0x00,0x10,0x21,0x24,0x42,0x00,0x01,0x00,0x02,0x16,0x00, +-0x00,0x02,0x16,0x03,0x28,0x43,0x00,0x03,0xac,0x80,0xff,0xfc,0xa0,0x80,0x00,0x00, +-0x14,0x60,0xff,0xf9,0x24,0x84,0x00,0x0c,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +-0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x01,0xc0, +-0x3c,0x08,0xb0,0x03,0xac,0x62,0x00,0x00,0x35,0x08,0x00,0x70,0x8d,0x02,0x00,0x00, +-0x00,0xa0,0x48,0x21,0x00,0x04,0x26,0x00,0x00,0x02,0x2a,0x43,0x00,0x06,0x36,0x00, +-0x00,0x07,0x3e,0x00,0x00,0x02,0x12,0x03,0x29,0x23,0x00,0x03,0x00,0x04,0x56,0x03, +-0x00,0x06,0x36,0x03,0x00,0x07,0x3e,0x03,0x30,0x48,0x00,0x01,0x10,0x60,0x00,0x11, +-0x30,0xa5,0x00,0x07,0x24,0x02,0x00,0x02,0x00,0x49,0x10,0x23,0x00,0x45,0x10,0x07, +-0x30,0x42,0x00,0x01,0x10,0x40,0x00,0x66,0x00,0x00,0x00,0x00,0x8f,0xa2,0x00,0x10, +-0x00,0x00,0x00,0x00,0x00,0x02,0x21,0x43,0x11,0x00,0x00,0x10,0x00,0x07,0x20,0x0b, +-0x15,0x20,0x00,0x06,0x24,0x02,0x00,0x01,0x3c,0x02,0xb0,0x05,0x34,0x42,0x01,0x20, +-0xa4,0x44,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x11,0x22,0x00,0x04, +-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x05,0x08,0x00,0x00,0x94,0x34,0x42,0x01,0x24, +-0x3c,0x02,0xb0,0x05,0x08,0x00,0x00,0x94,0x34,0x42,0x01,0x22,0x15,0x20,0x00,0x54, +-0x24,0x02,0x00,0x01,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x74,0x90,0x43,0x00,0x00, +-0x00,0x00,0x00,0x00,0xaf,0x83,0x8b,0x94,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x70, +-0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x6b,0x00,0x08,0x11,0x60,0x00,0x18, +-0x00,0x09,0x28,0x40,0x00,0x00,0x40,0x21,0x27,0x85,0x8b,0x90,0x8c,0xa3,0x00,0x00, +-0x8c,0xa2,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x62,0x38,0x23,0x00,0x43,0x10,0x2a, +-0x10,0x40,0x00,0x3d,0x00,0x00,0x00,0x00,0xac,0xa7,0x00,0x00,0x25,0x02,0x00,0x01, +-0x00,0x02,0x16,0x00,0x00,0x02,0x46,0x03,0x29,0x03,0x00,0x03,0x14,0x60,0xff,0xf3, +-0x24,0xa5,0x00,0x0c,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x70,0x90,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x4b,0x10,0x23,0xa0,0x62,0x00,0x00,0x00,0x09,0x28,0x40, +-0x00,0xa9,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x8b,0x98,0x00,0x0a,0x20,0x0b, +-0x00,0x43,0x18,0x21,0x10,0xc0,0x00,0x05,0x00,0x00,0x38,0x21,0x80,0x62,0x00,0x01, +-0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x05,0x00,0x00,0x00,0x00,0x80,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x03,0x00,0xa9,0x10,0x21,0x24,0x07,0x00,0x01, +-0x00,0xa9,0x10,0x21,0x00,0x02,0x30,0x80,0x27,0x82,0x8b,0x98,0xa0,0x67,0x00,0x01, +-0x00,0xc2,0x38,0x21,0x80,0xe3,0x00,0x01,0x00,0x00,0x00,0x00,0x10,0x60,0x00,0x07, +-0x00,0x00,0x00,0x00,0x27,0x83,0x8b,0x90,0x00,0xc3,0x18,0x21,0x8c,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x44,0x10,0x21,0xac,0x62,0x00,0x00,0x27,0x85,0x8b,0x94, +-0x27,0x82,0x8b,0x90,0x00,0xc5,0x28,0x21,0x00,0xc2,0x10,0x21,0x8c,0x43,0x00,0x00, +-0x8c,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x18,0x2a,0x14,0x60,0x00,0x03, +-0x24,0x02,0x00,0x01,0x03,0xe0,0x00,0x08,0xa0,0xe2,0x00,0x00,0xa0,0xe0,0x00,0x00, +-0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0xb7,0xac,0xa0,0x00,0x00, +-0x11,0x22,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x7c, +-0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x83,0x8b,0xac,0x08,0x00,0x00,0xa7, +-0x3c,0x02,0xb0,0x03,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x78,0x90,0x43,0x00,0x00, +-0x00,0x00,0x00,0x00,0xaf,0x83,0x8b,0xa0,0x08,0x00,0x00,0xa7,0x3c,0x02,0xb0,0x03, +-0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x04,0x10, +-0x3c,0x05,0xb0,0x03,0xac,0x62,0x00,0x00,0x34,0xa5,0x00,0x70,0x8c,0xa2,0x00,0x00, +-0x90,0x84,0x00,0x08,0x3c,0x06,0xb0,0x03,0x00,0x02,0x16,0x00,0x2c,0x83,0x00,0x03, +-0x34,0xc6,0x00,0x72,0x24,0x07,0x00,0x01,0x10,0x60,0x00,0x11,0x00,0x02,0x2f,0xc2, +-0x90,0xc2,0x00,0x00,0x00,0x00,0x18,0x21,0x00,0x02,0x16,0x00,0x10,0xa7,0x00,0x09, +-0x00,0x02,0x16,0x03,0x14,0x80,0x00,0x0c,0x30,0x43,0x00,0x03,0x83,0x82,0x8b,0x98, +-0x00,0x00,0x00,0x00,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x00,0x02,0x16,0x00, +-0x00,0x02,0x1e,0x03,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x72,0xa0,0x43,0x00,0x00, +-0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0x45,0x00,0x05,0x10,0x87,0x00,0x04, +-0x30,0x43,0x00,0x06,0x93,0x82,0x8b,0xb0,0x08,0x00,0x01,0x1f,0x00,0x43,0x10,0x21, +-0x83,0x82,0x8b,0xa4,0x00,0x00,0x00,0x00,0x00,0x02,0x10,0x40,0x08,0x00,0x01,0x1f, +-0x00,0x45,0x10,0x21,0x10,0x80,0x00,0x05,0x00,0x00,0x18,0x21,0x24,0x63,0x00,0x01, +-0x00,0x64,0x10,0x2b,0x14,0x40,0xff,0xfd,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08, +-0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x04,0xe4, +-0x3c,0x04,0xb0,0x02,0x34,0x63,0x00,0x20,0xac,0x62,0x00,0x00,0x34,0x84,0x00,0x08, +-0x24,0x02,0x00,0x01,0xaf,0x84,0x8b,0xc0,0xa3,0x82,0x8b,0xd0,0xa7,0x80,0x8b,0xc4, +-0xa7,0x80,0x8b,0xc6,0xaf,0x80,0x8b,0xc8,0xaf,0x80,0x8b,0xcc,0x03,0xe0,0x00,0x08, +-0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20, +-0x24,0x42,0x05,0x24,0x3c,0x04,0xb0,0x03,0xac,0x62,0x00,0x00,0x34,0x84,0x00,0xac, +-0x80,0xa2,0x00,0x15,0x8c,0x83,0x00,0x00,0x27,0xbd,0xff,0xf0,0x00,0x43,0x10,0x21, +-0xac,0x82,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x10,0x3c,0x02,0xb0,0x03, +-0x3c,0x03,0x80,0x00,0x34,0x42,0x00,0x20,0x24,0x63,0x05,0x5c,0x27,0xbd,0xff,0xe0, +-0xac,0x43,0x00,0x00,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x18, +-0x8f,0x90,0x8b,0xc0,0x0c,0x00,0x02,0x98,0x00,0x80,0x88,0x21,0x14,0x40,0x00,0x2a, +-0x3c,0x02,0x00,0x80,0x16,0x20,0x00,0x02,0x34,0x42,0x02,0x01,0x24,0x02,0x02,0x01, +-0xae,0x02,0x00,0x00,0x97,0x84,0x8b,0xc4,0x97,0x82,0x8b,0xc6,0x3c,0x03,0xb0,0x02, +-0x00,0x83,0x20,0x21,0x24,0x42,0x00,0x04,0xa7,0x82,0x8b,0xc6,0xa4,0x82,0x00,0x00, +-0x8f,0x84,0x8b,0xc8,0x8f,0x82,0x8b,0xc0,0x93,0x85,0x8b,0x72,0x24,0x84,0x00,0x01, +-0x24,0x42,0x00,0x04,0x24,0x03,0x8f,0xff,0x3c,0x07,0xb0,0x06,0x3c,0x06,0xb0,0x03, +-0x00,0x43,0x10,0x24,0x00,0x85,0x28,0x2a,0x34,0xe7,0x80,0x18,0xaf,0x82,0x8b,0xc0, +-0xaf,0x84,0x8b,0xc8,0x10,0xa0,0x00,0x08,0x34,0xc6,0x01,0x08,0x8f,0x83,0x8b,0xcc, +-0x8f,0x84,0x8b,0x8c,0x8c,0xc2,0x00,0x00,0x00,0x64,0x18,0x21,0x00,0x43,0x10,0x2b, +-0x14,0x40,0x00,0x09,0x00,0x00,0x00,0x00,0x8c,0xe2,0x00,0x00,0x3c,0x03,0x0f,0x00, +-0x3c,0x04,0x04,0x00,0x00,0x43,0x10,0x24,0x10,0x44,0x00,0x03,0x00,0x00,0x00,0x00, +-0x0c,0x00,0x04,0x96,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x18,0x7b,0xb0,0x00,0xbc, +-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x27,0xbd,0xff,0xd8,0x3c,0x02,0xb0,0x03, +-0x3c,0x03,0x80,0x00,0x24,0x63,0x06,0x48,0xaf,0xb0,0x00,0x10,0x34,0x42,0x00,0x20, +-0x8f,0x90,0x8b,0xc0,0xac,0x43,0x00,0x00,0xaf,0xb3,0x00,0x1c,0xaf,0xb2,0x00,0x18, +-0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x20,0x00,0x80,0x88,0x21,0x00,0xa0,0x90,0x21, +-0x0c,0x00,0x02,0x98,0x00,0xc0,0x98,0x21,0x24,0x07,0x8f,0xff,0x14,0x40,0x00,0x19, +-0x26,0x03,0x00,0x04,0x24,0x02,0x0e,0x03,0xae,0x02,0x00,0x00,0x00,0x67,0x80,0x24, +-0x26,0x02,0x00,0x04,0xae,0x11,0x00,0x00,0x00,0x47,0x80,0x24,0x97,0x86,0x8b,0xc4, +-0x26,0x03,0x00,0x04,0xae,0x12,0x00,0x00,0x00,0x67,0x80,0x24,0xae,0x13,0x00,0x00, +-0x8f,0x84,0x8b,0xc0,0x3c,0x02,0xb0,0x02,0x97,0x85,0x8b,0xc6,0x00,0xc2,0x30,0x21, +-0x8f,0x82,0x8b,0xc8,0x24,0x84,0x00,0x10,0x24,0xa5,0x00,0x10,0x00,0x87,0x20,0x24, +-0x24,0x42,0x00,0x01,0xa7,0x85,0x8b,0xc6,0xaf,0x84,0x8b,0xc0,0xaf,0x82,0x8b,0xc8, +-0xa4,0xc5,0x00,0x00,0x8f,0xbf,0x00,0x20,0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc, +-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28,0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10, +-0x94,0x82,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x42,0xe0,0x00,0x14,0x40,0x00,0x14, +-0x00,0x00,0x00,0x00,0x90,0x82,0x00,0x02,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xfc, +-0x00,0x82,0x28,0x21,0x8c,0xa4,0x00,0x00,0x3c,0x02,0x00,0x70,0x8c,0xa6,0x00,0x08, +-0x00,0x82,0x10,0x21,0x2c,0x43,0x00,0x06,0x10,0x60,0x00,0x09,0x3c,0x03,0x80,0x01, +-0x00,0x02,0x10,0x80,0x24,0x63,0x01,0xe8,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x08,0x00,0x00,0x00,0x00,0xaf,0x86,0x80,0x14, +-0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18, +-0x8c,0xa4,0x00,0x00,0x0c,0x00,0x17,0x84,0x00,0x00,0x00,0x00,0x08,0x00,0x01,0xdc, +-0x00,0x00,0x00,0x00,0x0c,0x00,0x24,0x49,0x00,0xc0,0x20,0x21,0x08,0x00,0x01,0xdc, +-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x08,0x8c,0x44,0x00,0x00, +-0x8f,0x82,0x80,0x18,0x3c,0x03,0x00,0x0f,0x34,0x63,0x42,0x40,0x00,0x43,0x10,0x21, +-0x00,0x82,0x20,0x2b,0x10,0x80,0x00,0x09,0x24,0x03,0x00,0x05,0x8f,0x82,0x83,0x60, +-0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,0xaf,0x82,0x83,0x60,0x10,0x43,0x00,0x03, +-0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03, +-0x8c,0x63,0x01,0x08,0x24,0x02,0x00,0x01,0xa3,0x82,0x80,0x11,0xaf,0x80,0x83,0x60, +-0xaf,0x83,0x80,0x18,0x08,0x00,0x01,0xf9,0x00,0x00,0x00,0x00,0x30,0x84,0x00,0xff, +-0x14,0x80,0x00,0x2f,0x00,0x00,0x00,0x00,0x8f,0x82,0x80,0x14,0xa3,0x85,0x83,0x93, +-0x10,0x40,0x00,0x2b,0x2c,0xa2,0x00,0x04,0x14,0x40,0x00,0x06,0x00,0x05,0x10,0x40, +-0x24,0xa2,0xff,0xfc,0x2c,0x42,0x00,0x08,0x10,0x40,0x00,0x09,0x24,0xa2,0xff,0xf0, +-0x00,0x05,0x10,0x40,0x27,0x84,0x83,0x9c,0x00,0x44,0x10,0x21,0x94,0x43,0x00,0x00, +-0x00,0x00,0x00,0x00,0x24,0x63,0x00,0x01,0x03,0xe0,0x00,0x08,0xa4,0x43,0x00,0x00, +-0x2c,0x42,0x00,0x10,0x14,0x40,0x00,0x0a,0x00,0x05,0x10,0x40,0x24,0xa2,0xff,0xe0, +-0x2c,0x42,0x00,0x10,0x14,0x40,0x00,0x06,0x00,0x05,0x10,0x40,0x24,0xa2,0xff,0xd0, +-0x2c,0x42,0x00,0x10,0x10,0x40,0x00,0x09,0x24,0xa2,0xff,0xc0,0x00,0x05,0x10,0x40, +-0x27,0x84,0x83,0x9c,0x00,0x44,0x10,0x21,0x94,0x43,0xff,0xf8,0x00,0x00,0x00,0x00, +-0x24,0x63,0x00,0x01,0x03,0xe0,0x00,0x08,0xa4,0x43,0xff,0xf8,0x2c,0x42,0x00,0x10, +-0x10,0x40,0x00,0x07,0x00,0x05,0x10,0x40,0x27,0x84,0x83,0x9c,0x00,0x44,0x10,0x21, +-0x94,0x43,0xff,0xf8,0x00,0x00,0x00,0x00,0x24,0x63,0x00,0x01,0xa4,0x43,0xff,0xf8, +-0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x8f,0x86,0x8b,0xc0,0x8f,0x82,0x80,0x14, +-0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10,0x10,0x40,0x00,0x2a,0x00,0xc0,0x38,0x21, +-0x24,0x02,0x00,0x07,0x24,0x03,0xff,0x9c,0xa3,0x82,0x83,0x9b,0xa3,0x83,0x83,0x9a, +-0x27,0x8a,0x83,0x98,0x00,0x00,0x20,0x21,0x24,0x09,0x8f,0xff,0x00,0x04,0x10,0x80, +-0x00,0x4a,0x28,0x21,0x8c,0xa2,0x00,0x00,0x24,0xe3,0x00,0x04,0x24,0x88,0x00,0x01, +-0xac,0xe2,0x00,0x00,0x10,0x80,0x00,0x02,0x00,0x69,0x38,0x24,0xac,0xa0,0x00,0x00, +-0x31,0x04,0x00,0xff,0x2c,0x82,0x00,0x27,0x14,0x40,0xff,0xf5,0x00,0x04,0x10,0x80, +-0x97,0x83,0x8b,0xc6,0x97,0x85,0x8b,0xc4,0x3c,0x02,0xb0,0x02,0x24,0x63,0x00,0x9c, +-0x00,0xa2,0x28,0x21,0x3c,0x04,0xb0,0x06,0xa7,0x83,0x8b,0xc6,0x34,0x84,0x80,0x18, +-0xa4,0xa3,0x00,0x00,0x8c,0x85,0x00,0x00,0x24,0x02,0x8f,0xff,0x24,0xc6,0x00,0x9c, +-0x3c,0x03,0x0f,0x00,0x00,0xc2,0x30,0x24,0x00,0xa3,0x28,0x24,0x3c,0x02,0x04,0x00, +-0xaf,0x86,0x8b,0xc0,0x10,0xa2,0x00,0x03,0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0x96, +-0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x18,0x8f,0x86,0x8b,0xc0,0x27,0xbd,0xff,0xc8,0x24,0x02,0x00,0x08, +-0x24,0x03,0x00,0x20,0xaf,0xbf,0x00,0x30,0xa3,0xa2,0x00,0x13,0xa3,0xa3,0x00,0x12, +-0xa7,0xa4,0x00,0x10,0x00,0xc0,0x28,0x21,0x27,0xa9,0x00,0x10,0x00,0x00,0x38,0x21, +-0x24,0x08,0x8f,0xff,0x00,0x07,0x10,0x80,0x00,0x49,0x10,0x21,0x8c,0x44,0x00,0x00, +-0x24,0xe3,0x00,0x01,0x30,0x67,0x00,0xff,0x24,0xa2,0x00,0x04,0x2c,0xe3,0x00,0x08, +-0xac,0xa4,0x00,0x00,0x14,0x60,0xff,0xf7,0x00,0x48,0x28,0x24,0x97,0x83,0x8b,0xc6, +-0x97,0x85,0x8b,0xc4,0x3c,0x02,0xb0,0x02,0x24,0x63,0x00,0x20,0x00,0xa2,0x28,0x21, +-0x3c,0x04,0xb0,0x06,0xa7,0x83,0x8b,0xc6,0x34,0x84,0x80,0x18,0xa4,0xa3,0x00,0x00, +-0x8c,0x85,0x00,0x00,0x24,0x02,0x8f,0xff,0x24,0xc6,0x00,0x20,0x3c,0x03,0x0f,0x00, +-0x00,0xc2,0x30,0x24,0x00,0xa3,0x28,0x24,0x3c,0x02,0x04,0x00,0xaf,0x86,0x8b,0xc0, +-0x10,0xa2,0x00,0x03,0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0x96,0x00,0x00,0x00,0x00, +-0x8f,0xbf,0x00,0x30,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x38, +-0x93,0x82,0x8b,0xd0,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x11,0x24,0x06,0x00,0x01, +-0x8f,0x82,0x8b,0xc8,0x3c,0x05,0xb0,0x06,0x3c,0x04,0xb0,0x03,0x34,0xa5,0x80,0x18, +-0x34,0x84,0x01,0x08,0x14,0x40,0x00,0x09,0x00,0x00,0x30,0x21,0x97,0x82,0x8b,0xc4, +-0x8c,0x84,0x00,0x00,0x3c,0x03,0xb0,0x02,0x00,0x43,0x10,0x21,0xaf,0x84,0x8b,0xcc, +-0xa7,0x80,0x8b,0xc6,0xac,0x40,0x00,0x00,0xac,0x40,0x00,0x04,0x8c,0xa2,0x00,0x00, +-0x03,0xe0,0x00,0x08,0x00,0xc0,0x10,0x21,0x8f,0x86,0x8b,0xc0,0x8f,0x82,0x8b,0xc8, +-0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10,0x00,0xc0,0x40,0x21,0x14,0x40,0x00,0x0a, +-0x00,0x40,0x50,0x21,0x00,0x00,0x38,0x21,0x27,0x89,0x83,0x68,0x24,0xe2,0x00,0x01, +-0x00,0x07,0x18,0x80,0x30,0x47,0x00,0xff,0x00,0x69,0x18,0x21,0x2c,0xe2,0x00,0x0a, +-0x14,0x40,0xff,0xfa,0xac,0x60,0x00,0x00,0x3c,0x02,0x00,0x80,0x10,0x82,0x00,0x6f, +-0x00,0x00,0x00,0x00,0x97,0x82,0x83,0x6e,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01, +-0xa7,0x82,0x83,0x6e,0x90,0xa3,0x00,0x15,0x97,0x82,0x83,0x70,0x00,0x03,0x1e,0x00, +-0x00,0x03,0x1e,0x03,0x00,0x43,0x10,0x21,0xa7,0x82,0x83,0x70,0x8c,0xa4,0x00,0x20, +-0x3c,0x02,0x00,0x60,0x3c,0x03,0x00,0x20,0x00,0x82,0x20,0x24,0x10,0x83,0x00,0x54, +-0x00,0x00,0x00,0x00,0x14,0x80,0x00,0x47,0x00,0x00,0x00,0x00,0x97,0x82,0x83,0x74, +-0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,0xa7,0x82,0x83,0x74,0x84,0xa3,0x00,0x06, +-0x8f,0x82,0x83,0x84,0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x21,0xaf,0x82,0x83,0x84, +-0x25,0x42,0x00,0x01,0x28,0x43,0x27,0x10,0xaf,0x82,0x8b,0xc8,0x10,0x60,0x00,0x09, +-0x24,0x02,0x00,0x04,0x93,0x83,0x80,0x11,0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x05, +-0x24,0x02,0x00,0x04,0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x18,0x24,0x03,0x00,0x28,0xa3,0x83,0x83,0x6a,0xa3,0x82,0x83,0x6b, +-0x90,0xa2,0x00,0x18,0x93,0x83,0x83,0x93,0x00,0x00,0x38,0x21,0x00,0x02,0x16,0x00, +-0x00,0x02,0x16,0x03,0xa7,0x82,0x83,0x7e,0xa3,0x83,0x83,0x8c,0x27,0x89,0x83,0x68, +-0x24,0x05,0x8f,0xff,0x00,0x07,0x10,0x80,0x00,0x49,0x10,0x21,0x8c,0x44,0x00,0x00, +-0x24,0xe3,0x00,0x01,0x30,0x67,0x00,0xff,0x25,0x02,0x00,0x04,0x2c,0xe3,0x00,0x0a, +-0xad,0x04,0x00,0x00,0x14,0x60,0xff,0xf7,0x00,0x45,0x40,0x24,0x97,0x83,0x8b,0xc6, +-0x97,0x85,0x8b,0xc4,0x3c,0x02,0xb0,0x02,0x24,0x63,0x00,0x28,0x00,0xa2,0x28,0x21, +-0x3c,0x04,0xb0,0x06,0xa7,0x83,0x8b,0xc6,0x34,0x84,0x80,0x18,0xa4,0xa3,0x00,0x00, +-0x8c,0x85,0x00,0x00,0x24,0x02,0x8f,0xff,0x24,0xc6,0x00,0x28,0x3c,0x03,0x0f,0x00, +-0x00,0xc2,0x30,0x24,0x00,0xa3,0x28,0x24,0x3c,0x02,0x04,0x00,0xaf,0x86,0x8b,0xc0, +-0x10,0xa2,0x00,0x03,0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0x96,0x00,0x00,0x00,0x00, +-0x0c,0x00,0x02,0x36,0x00,0x00,0x00,0x00,0xa3,0x80,0x80,0x11,0x08,0x00,0x02,0xe5, +-0x00,0x00,0x00,0x00,0x97,0x82,0x83,0x76,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01, +-0xa7,0x82,0x83,0x76,0x84,0xa3,0x00,0x06,0x8f,0x82,0x83,0x88,0x00,0x00,0x00,0x00, +-0x00,0x43,0x10,0x21,0xaf,0x82,0x83,0x88,0x08,0x00,0x02,0xdd,0x25,0x42,0x00,0x01, +-0x97,0x82,0x83,0x72,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,0xa7,0x82,0x83,0x72, +-0x84,0xa3,0x00,0x06,0x8f,0x82,0x83,0x80,0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x21, +-0xaf,0x82,0x83,0x80,0x08,0x00,0x02,0xdd,0x25,0x42,0x00,0x01,0x97,0x82,0x83,0x6c, +-0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,0xa7,0x82,0x83,0x6c,0x08,0x00,0x02,0xc5, +-0x00,0x00,0x00,0x00,0x27,0xbd,0xff,0xd0,0xaf,0xbf,0x00,0x28,0x8c,0xa3,0x00,0x20, +-0x8f,0x8a,0x8b,0xc0,0x3c,0x02,0x00,0x10,0x00,0x62,0x10,0x24,0x00,0xa0,0x38,0x21, +-0x01,0x40,0x48,0x21,0x10,0x40,0x00,0x3d,0x00,0x80,0x28,0x21,0x8c,0xe4,0x00,0x1c, +-0x34,0xa5,0x12,0x06,0xaf,0xa5,0x00,0x10,0x8c,0x82,0x00,0x08,0x00,0x03,0x1c,0x42, +-0x30,0x63,0x00,0x30,0x00,0x02,0x13,0x02,0x30,0x42,0x00,0x40,0x00,0x43,0x10,0x25, +-0x90,0xe6,0x00,0x10,0x90,0xe4,0x00,0x13,0x94,0xe8,0x00,0x0c,0x94,0xe3,0x00,0x1a, +-0x00,0x02,0x16,0x00,0x90,0xe7,0x00,0x12,0x00,0xa2,0x28,0x25,0x24,0x02,0x12,0x34, +-0xa7,0xa2,0x00,0x1c,0x24,0x02,0x56,0x78,0xaf,0xa5,0x00,0x10,0xa3,0xa6,0x00,0x18, +-0xa3,0xa7,0x00,0x1f,0xa7,0xa3,0x00,0x1a,0xa3,0xa4,0x00,0x19,0xa7,0xa8,0x00,0x20, +-0xa7,0xa2,0x00,0x22,0x00,0x00,0x28,0x21,0x27,0xa7,0x00,0x10,0x24,0x06,0x8f,0xff, +-0x00,0x05,0x10,0x80,0x00,0x47,0x10,0x21,0x8c,0x44,0x00,0x00,0x24,0xa3,0x00,0x01, +-0x30,0x65,0x00,0xff,0x25,0x22,0x00,0x04,0x2c,0xa3,0x00,0x05,0xad,0x24,0x00,0x00, +-0x14,0x60,0xff,0xf7,0x00,0x46,0x48,0x24,0x97,0x83,0x8b,0xc6,0x97,0x85,0x8b,0xc4, +-0x3c,0x02,0xb0,0x02,0x24,0x63,0x00,0x14,0x00,0xa2,0x28,0x21,0x3c,0x04,0xb0,0x06, +-0xa7,0x83,0x8b,0xc6,0x34,0x84,0x80,0x18,0xa4,0xa3,0x00,0x00,0x8c,0x85,0x00,0x00, +-0x24,0x02,0x8f,0xff,0x25,0x46,0x00,0x14,0x3c,0x03,0x0f,0x00,0x00,0xc2,0x50,0x24, +-0x00,0xa3,0x28,0x24,0x3c,0x02,0x04,0x00,0xaf,0x8a,0x8b,0xc0,0x10,0xa2,0x00,0x03, +-0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0x96,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x28, +-0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x30,0x3c,0x05,0xb0,0x03, +-0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xc8,0x00,0x04,0x22,0x00,0x34,0xa5,0x00,0x20, +-0x24,0x42,0x0d,0xfc,0x3c,0x03,0xb0,0x00,0xaf,0xb5,0x00,0x24,0xaf,0xb4,0x00,0x20, +-0xaf,0xb2,0x00,0x18,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x30,0x00,0x83,0x80,0x21, +-0xaf,0xb7,0x00,0x2c,0xaf,0xb6,0x00,0x28,0xaf,0xb3,0x00,0x1c,0xaf,0xb1,0x00,0x14, +-0xac,0xa2,0x00,0x00,0x8e,0x09,0x00,0x00,0x00,0x00,0x90,0x21,0x26,0x10,0x00,0x08, +-0x00,0x09,0xa6,0x02,0x12,0x80,0x00,0x13,0x00,0x00,0xa8,0x21,0x24,0x13,0x00,0x02, +-0x3c,0x16,0x00,0xff,0x3c,0x17,0xff,0x00,0x8e,0x09,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x09,0x12,0x02,0x24,0x42,0x00,0x02,0x31,0x25,0x00,0xff,0x10,0xb3,0x00,0x76, +-0x30,0x51,0x00,0xff,0x24,0x02,0x00,0x03,0x10,0xa2,0x00,0x18,0x00,0x00,0x00,0x00, +-0x02,0x51,0x10,0x21,0x30,0x52,0xff,0xff,0x02,0x54,0x18,0x2b,0x14,0x60,0xff,0xf2, +-0x02,0x11,0x80,0x21,0x12,0xa0,0x00,0x0a,0x3c,0x02,0xb0,0x06,0x34,0x42,0x80,0x18, +-0x8c,0x43,0x00,0x00,0x3c,0x04,0x0f,0x00,0x3c,0x02,0x04,0x00,0x00,0x64,0x18,0x24, +-0x10,0x62,0x00,0x03,0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0x96,0x00,0x00,0x00,0x00, +-0x8f,0xbf,0x00,0x30,0x7b,0xb6,0x01,0x7c,0x7b,0xb4,0x01,0x3c,0x7b,0xb2,0x00,0xfc, +-0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x38,0x8e,0x09,0x00,0x04, +-0x24,0x15,0x00,0x01,0x8e,0x06,0x00,0x0c,0x00,0x09,0x11,0x42,0x00,0x09,0x18,0xc2, +-0x30,0x48,0x00,0x03,0x00,0x09,0x14,0x02,0x30,0x6c,0x00,0x03,0x00,0x09,0x26,0x02, +-0x11,0x15,0x00,0x45,0x30,0x43,0x00,0x0f,0x29,0x02,0x00,0x02,0x14,0x40,0x00,0x26, +-0x00,0x00,0x00,0x00,0x11,0x13,0x00,0x0f,0x00,0x00,0x38,0x21,0x00,0x07,0x22,0x02, +-0x30,0x84,0xff,0x00,0x3c,0x03,0x00,0xff,0x00,0x07,0x2e,0x02,0x00,0x07,0x12,0x00, +-0x00,0x43,0x10,0x24,0x00,0xa4,0x28,0x25,0x00,0xa2,0x28,0x25,0x00,0x07,0x1e,0x00, +-0x00,0xa3,0x28,0x25,0x0c,0x00,0x01,0x92,0x01,0x20,0x20,0x21,0x08,0x00,0x03,0xa5, +-0x02,0x51,0x10,0x21,0x11,0x95,0x00,0x0f,0x00,0x00,0x00,0x00,0x11,0x88,0x00,0x07, +-0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x80,0x27,0x83,0x8b,0x70,0x00,0x43,0x10,0x21, +-0x8c,0x47,0x00,0x18,0x08,0x00,0x03,0xcc,0x00,0x07,0x22,0x02,0x00,0x04,0x10,0x40, +-0x27,0x83,0x8b,0x78,0x00,0x43,0x10,0x21,0x94,0x47,0x00,0x02,0x08,0x00,0x03,0xcc, +-0x00,0x07,0x22,0x02,0x27,0x82,0x8b,0x70,0x00,0x82,0x10,0x21,0x90,0x47,0x00,0x00, +-0x08,0x00,0x03,0xcc,0x00,0x07,0x22,0x02,0x15,0x00,0xff,0xdc,0x00,0x00,0x38,0x21, +-0x10,0x75,0x00,0x05,0x00,0x80,0x38,0x21,0x00,0x65,0x18,0x26,0x24,0x82,0x01,0x00, +-0x00,0x00,0x38,0x21,0x00,0x43,0x38,0x0a,0x24,0x02,0x00,0x01,0x11,0x82,0x00,0x0e, +-0x3c,0x02,0xb0,0x03,0x24,0x02,0x00,0x02,0x11,0x82,0x00,0x06,0x00,0x00,0x00,0x00, +-0x3c,0x02,0xb0,0x03,0x00,0xe2,0x10,0x21,0x8c,0x47,0x00,0x00,0x08,0x00,0x03,0xcc, +-0x00,0x07,0x22,0x02,0x3c,0x02,0xb0,0x03,0x00,0xe2,0x10,0x21,0x94,0x43,0x00,0x00, +-0x08,0x00,0x03,0xcb,0x30,0x67,0xff,0xff,0x00,0xe2,0x10,0x21,0x90,0x43,0x00,0x00, +-0x08,0x00,0x03,0xcb,0x30,0x67,0x00,0xff,0x30,0x62,0x00,0x03,0x00,0x02,0x12,0x00, +-0x11,0x95,0x00,0x07,0x00,0x44,0x38,0x21,0x11,0x93,0x00,0x03,0x00,0x00,0x00,0x00, +-0x08,0x00,0x03,0xfd,0x3c,0x02,0xb0,0x0a,0x08,0x00,0x04,0x02,0x3c,0x02,0xb0,0x0a, +-0x08,0x00,0x04,0x06,0x3c,0x02,0xb0,0x0a,0x8e,0x09,0x00,0x04,0x8e,0x02,0x00,0x08, +-0x8e,0x03,0x00,0x0c,0x00,0x09,0x41,0x42,0x00,0x02,0x22,0x02,0x00,0x03,0x3a,0x02, +-0x30,0x84,0xff,0x00,0x30,0xe7,0xff,0x00,0x00,0x02,0x5e,0x02,0x00,0x02,0x32,0x00, +-0x00,0x03,0x56,0x02,0x00,0x03,0x2a,0x00,0x01,0x64,0x58,0x25,0x00,0xd6,0x30,0x24, +-0x01,0x47,0x50,0x25,0x00,0x02,0x16,0x00,0x00,0xb6,0x28,0x24,0x00,0x03,0x1e,0x00, +-0x01,0x66,0x58,0x25,0x01,0x45,0x50,0x25,0x00,0x57,0x10,0x24,0x00,0x77,0x18,0x24, +-0x01,0x62,0x38,0x25,0x01,0x43,0x30,0x25,0x00,0x09,0x10,0xc2,0x00,0x09,0x1c,0x02, +-0x31,0x08,0x00,0x03,0x30,0x4c,0x00,0x03,0x30,0x63,0x00,0x0f,0x00,0x09,0x26,0x02, +-0x00,0xe0,0x58,0x21,0x15,0x00,0x00,0x28,0x00,0xc0,0x50,0x21,0x24,0x02,0x00,0x01, +-0x10,0x62,0x00,0x06,0x00,0x80,0x28,0x21,0x24,0x02,0x00,0x03,0x14,0x62,0xff,0x69, +-0x02,0x51,0x10,0x21,0x24,0x85,0x01,0x00,0x24,0x02,0x00,0x01,0x11,0x82,0x00,0x15, +-0x24,0x02,0x00,0x02,0x11,0x82,0x00,0x0a,0x3c,0x03,0xb0,0x03,0x00,0xa3,0x18,0x21, +-0x8c,0x62,0x00,0x00,0x00,0x0a,0x20,0x27,0x01,0x6a,0x28,0x24,0x00,0x44,0x10,0x24, +-0x00,0x45,0x10,0x25,0xac,0x62,0x00,0x00,0x08,0x00,0x03,0xa5,0x02,0x51,0x10,0x21, +-0x00,0xa3,0x18,0x21,0x94,0x62,0x00,0x00,0x00,0x0a,0x20,0x27,0x01,0x6a,0x28,0x24, +-0x00,0x44,0x10,0x24,0x00,0x45,0x10,0x25,0xa4,0x62,0x00,0x00,0x08,0x00,0x03,0xa5, +-0x02,0x51,0x10,0x21,0x3c,0x03,0xb0,0x03,0x00,0xa3,0x18,0x21,0x90,0x62,0x00,0x00, +-0x00,0x0a,0x20,0x27,0x01,0x6a,0x28,0x24,0x00,0x44,0x10,0x24,0x00,0x45,0x10,0x25, +-0x08,0x00,0x03,0xa4,0xa0,0x62,0x00,0x00,0x24,0x02,0x00,0x01,0x11,0x02,0x00,0x21, +-0x00,0x00,0x00,0x00,0x15,0x13,0xff,0x42,0x00,0x00,0x00,0x00,0x11,0x82,0x00,0x17, +-0x00,0x00,0x00,0x00,0x11,0x88,0x00,0x0b,0x00,0x00,0x00,0x00,0x27,0x83,0x8b,0x70, +-0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,0x8c,0x82,0x00,0x18,0x00,0x06,0x18,0x27, +-0x00,0xe6,0x28,0x24,0x00,0x43,0x10,0x24,0x00,0x45,0x10,0x25,0x08,0x00,0x03,0xa4, +-0xac,0x82,0x00,0x18,0x27,0x83,0x8b,0x78,0x00,0x04,0x20,0x40,0x00,0x83,0x20,0x21, +-0x94,0x82,0x00,0x02,0x00,0x06,0x18,0x27,0x00,0xe6,0x28,0x24,0x00,0x43,0x10,0x24, +-0x00,0x45,0x10,0x25,0x08,0x00,0x03,0xa4,0xa4,0x82,0x00,0x02,0x27,0x83,0x8b,0x70, +-0x00,0x83,0x18,0x21,0x90,0x62,0x00,0x00,0x00,0x06,0x20,0x27,0x08,0x00,0x04,0x5a, +-0x00,0xe6,0x28,0x24,0x30,0x62,0x00,0x07,0x00,0x02,0x12,0x00,0x11,0x88,0x00,0x0f, +-0x00,0x44,0x10,0x21,0x11,0x93,0x00,0x07,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x0a, +-0x00,0x43,0x18,0x21,0x8c,0x62,0x00,0x00,0x00,0x06,0x20,0x27,0x08,0x00,0x04,0x47, +-0x00,0xe6,0x28,0x24,0x3c,0x03,0xb0,0x0a,0x00,0x43,0x18,0x21,0x94,0x62,0x00,0x00, +-0x00,0x06,0x20,0x27,0x08,0x00,0x04,0x50,0x00,0xe6,0x28,0x24,0x3c,0x03,0xb0,0x0a, +-0x08,0x00,0x04,0x7d,0x00,0x43,0x18,0x21,0x97,0x85,0x8b,0xc4,0x3c,0x07,0xb0,0x02, +-0x3c,0x04,0xb0,0x03,0x3c,0x02,0x80,0x00,0x00,0xa7,0x28,0x21,0x34,0x84,0x00,0x20, +-0x24,0x42,0x12,0x58,0x24,0x03,0xff,0x80,0xac,0x82,0x00,0x00,0xa0,0xa3,0x00,0x07, +-0x97,0x82,0x8b,0xc6,0x97,0x85,0x8b,0xc4,0x3c,0x06,0xb0,0x06,0x30,0x42,0xff,0xf8, +-0x24,0x42,0x00,0x10,0x00,0xa2,0x10,0x21,0x30,0x42,0x0f,0xff,0x24,0x44,0x00,0x08, +-0x30,0x84,0x0f,0xff,0x00,0x05,0x28,0xc2,0x3c,0x03,0x00,0x40,0x00,0xa3,0x28,0x25, +-0x00,0x87,0x20,0x21,0x34,0xc6,0x80,0x18,0xac,0xc5,0x00,0x00,0xaf,0x84,0x8b,0xc0, +-0xa7,0x82,0x8b,0xc4,0xa7,0x80,0x8b,0xc6,0xaf,0x80,0x8b,0xc8,0x03,0xe0,0x00,0x08, +-0x00,0x00,0x00,0x00,0x30,0xa5,0x00,0xff,0x30,0x84,0x00,0xff,0x24,0x02,0x00,0x01, +-0x00,0xe0,0x48,0x21,0x30,0xc6,0x00,0xff,0x8f,0xa7,0x00,0x10,0x10,0x82,0x00,0x07, +-0x00,0xa0,0x40,0x21,0x24,0x02,0x00,0x03,0x10,0x82,0x00,0x03,0x00,0x00,0x00,0x00, +-0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x24,0xa8,0x01,0x00,0x3c,0x03,0xb0,0x03, +-0x24,0x02,0x00,0x01,0x00,0x07,0x20,0x27,0x01,0x27,0x28,0x24,0x10,0xc2,0x00,0x14, +-0x01,0x03,0x18,0x21,0x24,0x02,0x00,0x02,0x10,0xc2,0x00,0x09,0x00,0x07,0x50,0x27, +-0x3c,0x03,0xb0,0x03,0x01,0x03,0x18,0x21,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x4a,0x10,0x24,0x00,0x45,0x10,0x25,0x08,0x00,0x04,0xe1,0xac,0x62,0x00,0x00, +-0x3c,0x03,0xb0,0x03,0x01,0x03,0x18,0x21,0x94,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x4a,0x10,0x24,0x00,0x45,0x10,0x25,0x03,0xe0,0x00,0x08,0xa4,0x62,0x00,0x00, +-0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x10,0x24,0x00,0x45,0x10,0x25, +-0xa0,0x62,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0x84,0x00,0x07, +-0x00,0x04,0x22,0x00,0x30,0xa5,0x00,0xff,0x00,0x85,0x28,0x21,0x3c,0x02,0xb0,0x0a, +-0x00,0xa2,0x40,0x21,0x30,0xc6,0x00,0xff,0x24,0x02,0x00,0x01,0x8f,0xa4,0x00,0x10, +-0x10,0xc2,0x00,0x14,0x24,0x02,0x00,0x02,0x00,0x04,0x50,0x27,0x10,0xc2,0x00,0x09, +-0x00,0xe4,0x48,0x24,0x3c,0x03,0xb0,0x0a,0x00,0xa3,0x18,0x21,0x8c,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x4a,0x10,0x24,0x00,0x49,0x10,0x25,0x03,0xe0,0x00,0x08, +-0xac,0x62,0x00,0x00,0x3c,0x03,0xb0,0x0a,0x00,0xa3,0x18,0x21,0x94,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x4a,0x10,0x24,0x00,0x49,0x10,0x25,0x03,0xe0,0x00,0x08, +-0xa4,0x62,0x00,0x00,0x91,0x02,0x00,0x00,0x00,0x04,0x18,0x27,0x00,0xe4,0x20,0x24, +-0x00,0x43,0x10,0x24,0x00,0x44,0x10,0x25,0x03,0xe0,0x00,0x08,0xa1,0x02,0x00,0x00, +-0x30,0xa9,0x00,0xff,0x27,0x83,0x8b,0x70,0x30,0x85,0x00,0xff,0x24,0x02,0x00,0x01, +-0x00,0x07,0x50,0x27,0x00,0xc7,0x40,0x24,0x11,0x22,0x00,0x17,0x00,0xa3,0x18,0x21, +-0x00,0x05,0x20,0x40,0x27,0x82,0x8b,0x70,0x00,0x05,0x28,0x80,0x27,0x83,0x8b,0x78, +-0x00,0x83,0x50,0x21,0x00,0xa2,0x20,0x21,0x24,0x02,0x00,0x02,0x00,0x07,0x40,0x27, +-0x11,0x22,0x00,0x07,0x00,0xc7,0x28,0x24,0x8c,0x82,0x00,0x18,0x00,0x00,0x00,0x00, +-0x00,0x48,0x10,0x24,0x00,0x45,0x10,0x25,0x03,0xe0,0x00,0x08,0xac,0x82,0x00,0x18, +-0x95,0x42,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x48,0x10,0x24,0x00,0x45,0x10,0x25, +-0x03,0xe0,0x00,0x08,0xa5,0x42,0x00,0x02,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x4a,0x10,0x24,0x00,0x48,0x10,0x25,0x03,0xe0,0x00,0x08,0xa0,0x62,0x00,0x00, +-0x00,0x04,0x32,0x02,0x30,0xc6,0xff,0x00,0x00,0x04,0x16,0x02,0x00,0x04,0x1a,0x00, +-0x3c,0x05,0x00,0xff,0x00,0x65,0x18,0x24,0x00,0x46,0x10,0x25,0x00,0x43,0x10,0x25, +-0x00,0x04,0x26,0x00,0x03,0xe0,0x00,0x08,0x00,0x44,0x10,0x25,0x3c,0x03,0xb0,0x03, +-0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xe8,0x34,0x63,0x00,0x20,0x24,0x42,0x14,0xdc, +-0x3c,0x04,0xb0,0x03,0xaf,0xbf,0x00,0x14,0xac,0x62,0x00,0x00,0xaf,0xb0,0x00,0x10, +-0x34,0x84,0x00,0x2c,0x8c,0x83,0x00,0x00,0xa7,0x80,0xbc,0x00,0x00,0x03,0x12,0x02, +-0x00,0x03,0x2d,0x02,0x30,0x42,0x0f,0xff,0xa3,0x83,0xbc,0x08,0xa7,0x85,0xbc,0x0c, +-0xa7,0x82,0xbc,0x0a,0xa7,0x80,0xbc,0x02,0xa7,0x80,0xbc,0x04,0xa7,0x80,0xbc,0x06, +-0x0c,0x00,0x06,0xd1,0x24,0x04,0x05,0x00,0x3c,0x05,0x08,0x00,0x00,0x45,0x28,0x25, +-0x24,0x04,0x05,0x00,0x0c,0x00,0x06,0xbf,0x00,0x40,0x80,0x21,0x3c,0x02,0xf7,0xff, +-0x34,0x42,0xff,0xff,0x02,0x02,0x80,0x24,0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xbf, +-0x24,0x04,0x05,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0xb0,0x03,0x34,0x42,0x01,0x08, +-0x34,0x63,0x01,0x18,0x8c,0x45,0x00,0x00,0x8c,0x64,0x00,0x00,0x3c,0x02,0x00,0x0f, +-0x3c,0x03,0x00,0x4c,0x30,0x84,0x02,0x00,0x34,0x63,0x4b,0x40,0xaf,0x85,0xbc,0x10, +-0x10,0x80,0x00,0x06,0x34,0x42,0x42,0x40,0xaf,0x83,0xbc,0x14,0x8f,0xbf,0x00,0x14, +-0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0xaf,0x82,0xbc,0x14, +-0x08,0x00,0x05,0x67,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00, +-0x27,0xbd,0xff,0xc8,0x34,0x63,0x00,0x20,0x24,0x42,0x15,0xb8,0x30,0x84,0x00,0xff, +-0xaf,0xbf,0x00,0x30,0xaf,0xb7,0x00,0x2c,0xaf,0xb6,0x00,0x28,0xaf,0xb5,0x00,0x24, +-0xaf,0xb4,0x00,0x20,0xaf,0xb3,0x00,0x1c,0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14, +-0xaf,0xb0,0x00,0x10,0xac,0x62,0x00,0x00,0x10,0x80,0x00,0x1c,0x24,0x02,0x00,0x02, +-0x10,0x82,0x00,0x08,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x30,0x7b,0xb6,0x01,0x7c, +-0x7b,0xb4,0x01,0x3c,0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x38,0xa7,0x80,0xbc,0x00,0xa7,0x80,0xbc,0x02,0xa7,0x80,0xbc,0x04, +-0xa7,0x80,0xbc,0x06,0x0c,0x00,0x06,0xd1,0x24,0x04,0x05,0x00,0x3c,0x05,0x08,0x00, +-0x00,0x45,0x28,0x25,0x24,0x04,0x05,0x00,0x0c,0x00,0x06,0xbf,0x00,0x40,0x80,0x21, +-0x3c,0x05,0xf7,0xff,0x34,0xa5,0xff,0xff,0x02,0x05,0x28,0x24,0x0c,0x00,0x06,0xbf, +-0x24,0x04,0x05,0x00,0x08,0x00,0x05,0x82,0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xd1, +-0x24,0x04,0x05,0xa0,0x24,0x04,0x05,0xa4,0x0c,0x00,0x06,0xd1,0x00,0x02,0xbc,0x02, +-0x24,0x04,0x05,0xa8,0x00,0x02,0xb4,0x02,0x0c,0x00,0x06,0xd1,0x30,0x55,0xff,0xff, +-0x00,0x40,0x80,0x21,0x97,0x84,0xbc,0x00,0x97,0x82,0xbc,0x02,0x97,0x83,0xbc,0x06, +-0x02,0xe4,0x20,0x23,0x02,0xa2,0x10,0x23,0x00,0x82,0x20,0x21,0x97,0x82,0xbc,0x04, +-0x32,0x14,0xff,0xff,0x02,0x83,0x18,0x23,0x02,0xc2,0x10,0x23,0x00,0x82,0x20,0x21, +-0x93,0x82,0xbc,0x08,0x00,0x83,0x20,0x21,0x30,0x84,0xff,0xff,0x00,0x82,0x10,0x2b, +-0x14,0x40,0x00,0xaa,0x00,0x00,0x00,0x00,0x97,0x82,0xbc,0x0c,0x00,0x00,0x00,0x00, +-0x00,0x44,0x10,0x2b,0x14,0x40,0x00,0x7f,0x00,0x00,0x00,0x00,0x97,0x82,0xbc,0x0a, +-0x00,0x00,0x00,0x00,0x00,0x44,0x10,0x2b,0x10,0x40,0x00,0x3a,0x00,0x00,0x00,0x00, +-0x0c,0x00,0x06,0xd1,0x24,0x04,0x04,0x50,0x30,0x51,0x00,0x7f,0x00,0x40,0x80,0x21, +-0x2e,0x22,0x00,0x32,0x10,0x40,0x00,0x13,0x24,0x02,0x00,0x20,0x12,0x22,0x00,0x17, +-0x24,0x02,0xff,0x80,0x02,0x02,0x10,0x24,0x26,0x31,0x00,0x01,0x00,0x51,0x80,0x25, +-0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xbf,0x24,0x04,0x04,0x50,0x02,0x00,0x28,0x21, +-0x0c,0x00,0x06,0xbf,0x24,0x04,0x04,0x58,0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xbf, +-0x24,0x04,0x04,0x60,0x02,0x00,0x28,0x21,0x24,0x04,0x04,0x68,0x0c,0x00,0x06,0xbf, +-0x00,0x00,0x00,0x00,0xa7,0x97,0xbc,0x00,0xa7,0x95,0xbc,0x02,0xa7,0x96,0xbc,0x04, +-0xa7,0x94,0xbc,0x06,0x08,0x00,0x05,0x82,0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xd1, +-0x24,0x04,0x02,0x08,0x3c,0x04,0x00,0xc0,0x00,0x40,0x28,0x21,0x00,0x44,0x10,0x24, +-0x00,0x02,0x15,0x82,0x24,0x03,0x00,0x03,0x10,0x43,0x00,0x07,0x00,0x00,0x00,0x00, +-0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff,0x00,0xa2,0x10,0x24,0x00,0x44,0x28,0x25, +-0x0c,0x00,0x06,0xbf,0x24,0x04,0x02,0x08,0x0c,0x00,0x06,0xd1,0x24,0x04,0x02,0x2c, +-0x00,0x40,0x90,0x21,0x3c,0x02,0xff,0xff,0x34,0x42,0x3f,0xff,0x02,0x42,0x90,0x24, +-0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xbf,0x24,0x04,0x02,0x2c,0x08,0x00,0x05,0xc9, +-0x24,0x02,0xff,0x80,0x0c,0x00,0x06,0xd1,0x24,0x04,0x04,0x50,0x30,0x51,0x00,0x7f, +-0x24,0x02,0x00,0x20,0x16,0x22,0xff,0xdb,0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xd1, +-0x24,0x04,0x02,0x2c,0x34,0x52,0x40,0x00,0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xbf, +-0x24,0x04,0x02,0x2c,0x0c,0x00,0x06,0xd1,0x24,0x04,0x02,0x58,0x24,0x04,0x02,0x5c, +-0x0c,0x00,0x06,0xd1,0x00,0x02,0x9e,0x02,0x30,0x43,0x00,0xff,0x00,0x13,0x12,0x00, +-0x00,0x43,0x10,0x25,0x2c,0x43,0x00,0x04,0x14,0x60,0x00,0x1d,0x2c,0x42,0x00,0x11, +-0x10,0x40,0x00,0x0b,0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0xff,0x34,0x42,0x3f,0xff, +-0x02,0x42,0x90,0x24,0x02,0x40,0x28,0x21,0x24,0x04,0x02,0x2c,0x0c,0x00,0x06,0xbf, +-0x36,0x52,0x80,0x00,0x02,0x40,0x28,0x21,0x08,0x00,0x05,0xd7,0x24,0x04,0x02,0x2c, +-0x0c,0x00,0x06,0xd1,0x24,0x04,0x02,0x08,0x3c,0x04,0x00,0xc0,0x00,0x40,0x28,0x21, +-0x00,0x44,0x10,0x24,0x00,0x02,0x15,0x82,0x24,0x03,0x00,0x02,0x14,0x43,0xff,0xee, +-0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff,0x00,0xa2,0x10,0x24,0x00,0x44,0x28,0x25, +-0x0c,0x00,0x06,0xbf,0x24,0x04,0x02,0x08,0x08,0x00,0x06,0x13,0x3c,0x02,0xff,0xff, +-0x0c,0x00,0x06,0xd1,0x24,0x04,0x02,0x08,0x00,0x40,0x28,0x21,0x00,0x02,0x15,0x82, +-0x30,0x42,0x00,0x03,0x24,0x03,0x00,0x03,0x14,0x43,0xff,0xdf,0x3c,0x02,0xff,0x3f, +-0x34,0x42,0xff,0xff,0x00,0xa2,0x10,0x24,0x3c,0x03,0x00,0x80,0x08,0x00,0x06,0x28, +-0x00,0x43,0x28,0x25,0x0c,0x00,0x06,0xd1,0x24,0x04,0x04,0x50,0x30,0x51,0x00,0x7f, +-0x00,0x40,0x80,0x21,0x2e,0x22,0x00,0x32,0x10,0x40,0xff,0x9a,0x24,0x02,0x00,0x20, +-0x12,0x22,0x00,0x04,0x24,0x02,0xff,0x80,0x02,0x02,0x10,0x24,0x08,0x00,0x05,0xcb, +-0x26,0x31,0x00,0x02,0x0c,0x00,0x06,0xd1,0x24,0x04,0x02,0x08,0x3c,0x04,0x00,0xc0, +-0x00,0x40,0x28,0x21,0x00,0x44,0x10,0x24,0x00,0x02,0x15,0x82,0x24,0x03,0x00,0x03, +-0x10,0x43,0x00,0x07,0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff, +-0x00,0xa2,0x10,0x24,0x00,0x44,0x28,0x25,0x0c,0x00,0x06,0xbf,0x24,0x04,0x02,0x08, +-0x0c,0x00,0x06,0xd1,0x24,0x04,0x02,0x2c,0x00,0x40,0x90,0x21,0x3c,0x02,0xff,0xff, +-0x34,0x42,0x3f,0xff,0x02,0x42,0x90,0x24,0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xbf, +-0x24,0x04,0x02,0x2c,0x08,0x00,0x06,0x42,0x24,0x02,0xff,0x80,0x0c,0x00,0x06,0xd1, +-0x24,0x04,0x04,0x50,0x00,0x40,0x80,0x21,0x30,0x51,0x00,0x7f,0x24,0x02,0x00,0x20, +-0x12,0x22,0x00,0x1d,0x2e,0x22,0x00,0x21,0x14,0x40,0xff,0x72,0x24,0x02,0xff,0x80, +-0x02,0x02,0x10,0x24,0x26,0x31,0xff,0xff,0x00,0x51,0x80,0x25,0x24,0x04,0x04,0x50, +-0x0c,0x00,0x06,0xbf,0x02,0x00,0x28,0x21,0x24,0x04,0x04,0x58,0x0c,0x00,0x06,0xbf, +-0x02,0x00,0x28,0x21,0x24,0x04,0x04,0x60,0x0c,0x00,0x06,0xbf,0x02,0x00,0x28,0x21, +-0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xbf,0x24,0x04,0x04,0x68,0x24,0x02,0x00,0x20, +-0x16,0x22,0xff,0x60,0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xd1,0x24,0x04,0x02,0x2c, +-0x00,0x40,0x90,0x21,0x3c,0x02,0xff,0xff,0x34,0x42,0x3f,0xff,0x02,0x42,0x10,0x24, +-0x08,0x00,0x06,0x19,0x34,0x52,0x80,0x00,0x0c,0x00,0x06,0xd1,0x24,0x04,0x02,0x2c, +-0x34,0x52,0x40,0x00,0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xbf,0x24,0x04,0x02,0x2c, +-0x0c,0x00,0x06,0xd1,0x24,0x04,0x02,0x58,0x24,0x04,0x02,0x5c,0x0c,0x00,0x06,0xd1, +-0x00,0x02,0x9e,0x02,0x30,0x43,0x00,0xff,0x00,0x13,0x12,0x00,0x00,0x43,0x10,0x25, +-0x2c,0x43,0x00,0x04,0x14,0x60,0x00,0x20,0x2c,0x42,0x00,0x11,0x10,0x40,0x00,0x0d, +-0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0xff,0x34,0x42,0x3f,0xff,0x02,0x42,0x90,0x24, +-0x02,0x40,0x28,0x21,0x24,0x04,0x02,0x2c,0x0c,0x00,0x06,0xbf,0x36,0x52,0x80,0x00, +-0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xbf,0x24,0x04,0x02,0x2c,0x08,0x00,0x06,0x66, +-0x2e,0x22,0x00,0x21,0x0c,0x00,0x06,0xd1,0x24,0x04,0x02,0x08,0x3c,0x04,0x00,0xc0, +-0x00,0x40,0x28,0x21,0x00,0x44,0x10,0x24,0x00,0x02,0x15,0x82,0x24,0x03,0x00,0x02, +-0x14,0x43,0xff,0xec,0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff, +-0x00,0xa2,0x10,0x24,0x00,0x44,0x28,0x25,0x0c,0x00,0x06,0xbf,0x24,0x04,0x02,0x08, +-0x08,0x00,0x06,0x96,0x3c,0x02,0xff,0xff,0x0c,0x00,0x06,0xd1,0x24,0x04,0x02,0x08, +-0x00,0x40,0x28,0x21,0x00,0x02,0x15,0x82,0x30,0x42,0x00,0x03,0x24,0x03,0x00,0x03, +-0x14,0x43,0xff,0xdc,0x3c,0x03,0x00,0x80,0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff, +-0x00,0xa2,0x10,0x24,0x08,0x00,0x06,0xae,0x00,0x43,0x28,0x25,0x30,0x83,0x00,0x03, +-0x00,0x04,0x20,0x40,0x00,0x83,0x20,0x23,0x3c,0x02,0xb0,0x0a,0x00,0x82,0x20,0x21, +-0x3c,0x06,0x00,0x01,0xac,0x85,0x00,0x00,0x24,0x07,0x00,0x01,0x00,0x00,0x28,0x21, +-0x34,0xc6,0x86,0x9f,0x8c,0x82,0x10,0x00,0x24,0xa5,0x00,0x01,0x10,0x47,0x00,0x03, +-0x00,0xc5,0x18,0x2b,0x10,0x60,0xff,0xfb,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08, +-0x00,0x00,0x00,0x00,0x30,0x83,0x00,0x03,0x00,0x04,0x20,0x40,0x3c,0x02,0xb0,0x0a, +-0x00,0x83,0x20,0x23,0x00,0x82,0x20,0x21,0x3c,0x06,0x00,0x01,0x24,0x02,0xff,0xff, +-0xac,0x82,0x10,0x00,0x00,0x00,0x28,0x21,0x24,0x07,0x00,0x01,0x34,0xc6,0x86,0x9f, +-0x8c,0x82,0x10,0x00,0x24,0xa5,0x00,0x01,0x10,0x47,0x00,0x03,0x00,0xc5,0x18,0x2b, +-0x10,0x60,0xff,0xfb,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x00,0x03,0xe0,0x00,0x08, +-0x00,0x00,0x00,0x00,0x3c,0x05,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x1b,0x94, +-0x24,0x03,0x00,0x01,0x34,0xa5,0x00,0x20,0x3c,0x06,0xb0,0x03,0xac,0xa2,0x00,0x00, +-0x34,0xc6,0x01,0x04,0xa0,0x83,0x00,0x48,0xa0,0x80,0x00,0x04,0xa0,0x80,0x00,0x05, +-0xa0,0x80,0x00,0x06,0xa0,0x80,0x00,0x07,0xa0,0x80,0x00,0x08,0xa0,0x80,0x00,0x09, +-0xa0,0x80,0x00,0x0a,0xa0,0x80,0x00,0x11,0xa0,0x80,0x00,0x13,0xa0,0x80,0x00,0x49, +-0x94,0xc2,0x00,0x00,0xac,0x80,0x00,0x00,0xa0,0x80,0x00,0x4e,0x00,0x02,0x14,0x00, +-0x00,0x02,0x14,0x03,0x30,0x43,0x00,0xff,0x30,0x42,0xff,0x00,0xa4,0x82,0x00,0x44, +-0xa4,0x83,0x00,0x46,0xac,0x80,0x00,0x24,0xac,0x80,0x00,0x28,0xac,0x80,0x00,0x2c, +-0xac,0x80,0x00,0x30,0xac,0x80,0x00,0x34,0xac,0x80,0x00,0x38,0xac,0x80,0x00,0x3c, +-0x03,0xe0,0x00,0x08,0xac,0x80,0x00,0x40,0x84,0x83,0x00,0x0c,0x3c,0x07,0xb0,0x03, +-0x34,0xe7,0x00,0x20,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80, +-0x27,0x83,0x90,0x04,0x00,0x43,0x10,0x21,0x8c,0x48,0x00,0x18,0x3c,0x02,0x80,0x00, +-0x24,0x42,0x1c,0x28,0xac,0xe2,0x00,0x00,0x8d,0x03,0x00,0x08,0x80,0x82,0x00,0x13, +-0x00,0x05,0x2c,0x00,0x00,0x03,0x1e,0x02,0x00,0x02,0x12,0x00,0x30,0x63,0x00,0x7e, +-0x00,0x62,0x18,0x21,0x00,0x65,0x18,0x21,0x3c,0x02,0xc0,0x00,0x3c,0x05,0xb0,0x05, +-0x34,0x42,0x04,0x00,0x24,0x63,0x00,0x01,0x3c,0x07,0xb0,0x05,0x3c,0x08,0xb0,0x05, +-0x34,0xa5,0x04,0x20,0xac,0xa3,0x00,0x00,0x00,0xc2,0x30,0x21,0x34,0xe7,0x04,0x24, +-0x35,0x08,0x02,0x28,0x24,0x02,0x00,0x01,0x24,0x03,0x00,0x20,0xac,0xe6,0x00,0x00, +-0xac,0x82,0x00,0x3c,0x03,0xe0,0x00,0x08,0xa1,0x03,0x00,0x00,0x27,0xbd,0xff,0xa8, +-0x00,0x07,0x60,0x80,0x27,0x82,0xb4,0x00,0xaf,0xbe,0x00,0x50,0xaf,0xb7,0x00,0x4c, +-0xaf,0xb5,0x00,0x44,0xaf,0xb4,0x00,0x40,0xaf,0xbf,0x00,0x54,0xaf,0xb6,0x00,0x48, +-0xaf,0xb3,0x00,0x3c,0xaf,0xb2,0x00,0x38,0xaf,0xb1,0x00,0x34,0xaf,0xb0,0x00,0x30, +-0x01,0x82,0x10,0x21,0x8c,0x43,0x00,0x00,0x00,0xe0,0x70,0x21,0x3c,0x02,0x80,0x00, +-0x94,0x73,0x00,0x14,0x3c,0x07,0xb0,0x03,0x34,0xe7,0x00,0x20,0x24,0x42,0x1c,0xbc, +-0x3c,0x03,0xb0,0x05,0xac,0xe2,0x00,0x00,0x34,0x63,0x01,0x28,0x90,0x67,0x00,0x00, +-0x00,0x13,0xa8,0xc0,0x02,0xb3,0x18,0x21,0x27,0x82,0x90,0x04,0x00,0x03,0x18,0x80, +-0x00,0x62,0x18,0x21,0x00,0x05,0x2c,0x00,0x00,0x07,0x3e,0x00,0x28,0xc2,0x00,0x03, +-0x00,0xc0,0xa0,0x21,0x00,0x80,0x78,0x21,0x00,0x05,0xbc,0x03,0x8c,0x68,0x00,0x18, +-0x02,0xa0,0x58,0x21,0x10,0x40,0x01,0x81,0x00,0x07,0xf6,0x03,0x00,0xde,0x10,0x07, +-0x30,0x5e,0x00,0x01,0x01,0x73,0x10,0x21,0x27,0x83,0x90,0x08,0x00,0x02,0x10,0x80, +-0x00,0x43,0x10,0x21,0x80,0x4d,0x00,0x06,0x8d,0x03,0x00,0x00,0x8d,0x02,0x00,0x04, +-0x8d,0x0a,0x00,0x08,0x8d,0x03,0x00,0x0c,0xaf,0xa2,0x00,0x20,0x11,0xa0,0x01,0x71, +-0xaf,0xa3,0x00,0x18,0x27,0x82,0xb4,0x00,0x01,0x82,0x10,0x21,0x8c,0x44,0x00,0x00, +-0x00,0x00,0x00,0x00,0x90,0x83,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x04, +-0x14,0x60,0x00,0x12,0x00,0x00,0xb0,0x21,0x3c,0x02,0xb0,0x09,0x34,0x42,0x01,0x46, +-0x90,0x43,0x00,0x00,0x2a,0x84,0x00,0x04,0x10,0x80,0x01,0x56,0x30,0x65,0x00,0x01, +-0x91,0xe2,0x00,0x09,0x00,0x00,0x00,0x00,0x12,0x82,0x00,0x02,0x00,0x00,0x00,0x00, +-0x00,0x00,0x28,0x21,0x14,0xa0,0x00,0x03,0x00,0x00,0x38,0x21,0x13,0xc0,0x00,0x03, +-0x38,0xf6,0x00,0x01,0x24,0x07,0x00,0x01,0x38,0xf6,0x00,0x01,0x01,0x73,0x10,0x21, +-0x00,0x02,0x30,0x80,0x27,0x83,0x90,0x10,0x00,0xc3,0x48,0x21,0x91,0x25,0x00,0x00, +-0x8f,0xa4,0x00,0x20,0x2c,0xa3,0x00,0x04,0x00,0x04,0x11,0xc3,0x30,0x42,0x00,0x01, +-0x00,0x03,0xb0,0x0b,0x12,0xc0,0x00,0xd8,0xaf,0xa2,0x00,0x24,0x93,0x90,0xbb,0xea, +-0x00,0x0a,0x16,0x42,0x30,0x52,0x00,0x3f,0x2e,0x06,0x00,0x0c,0x10,0xc0,0x00,0xc0, +-0x00,0xa0,0x20,0x21,0x2c,0xa2,0x00,0x10,0x14,0x40,0x00,0x04,0x00,0x90,0x10,0x2b, +-0x30,0xa2,0x00,0x07,0x24,0x44,0x00,0x04,0x00,0x90,0x10,0x2b,0x10,0x40,0x00,0x0b, +-0x01,0x73,0x10,0x21,0x27,0x85,0xbb,0x1c,0x00,0x10,0x10,0x40,0x00,0x50,0x10,0x21, +-0x00,0x45,0x10,0x21,0x90,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x18,0x2b, +-0x14,0x60,0xff,0xfa,0x00,0x10,0x10,0x40,0x01,0x73,0x10,0x21,0x00,0x02,0x10,0x80, +-0x27,0x83,0x90,0x08,0x00,0x43,0x10,0x21,0x31,0xa4,0x00,0x01,0x10,0x80,0x00,0xa5, +-0xa0,0x50,0x00,0x07,0x3c,0x04,0xb0,0x05,0x34,0x84,0x00,0x08,0x24,0x02,0x00,0x01, +-0x3c,0x03,0x80,0x00,0xa1,0xe2,0x00,0x4e,0xac,0x83,0x00,0x00,0x8c,0x85,0x00,0x00, +-0x3c,0x02,0x00,0xf0,0x3c,0x03,0x40,0xf0,0x34,0x42,0xf0,0x00,0x34,0x63,0xf0,0x00, +-0x24,0x17,0x00,0x0e,0x24,0x13,0x01,0x06,0xac,0x82,0x00,0x00,0xac,0x83,0x00,0x00, +-0x27,0x82,0xb4,0x00,0x01,0x82,0x10,0x21,0x8c,0x43,0x00,0x00,0x24,0x05,0x00,0x01, +-0xaf,0xa5,0x00,0x1c,0x90,0x62,0x00,0x16,0x00,0x13,0xa8,0xc0,0x32,0x51,0x00,0x02, +-0x34,0x42,0x00,0x04,0xa0,0x62,0x00,0x16,0x8f,0xa3,0x00,0x20,0x8f,0xa4,0x00,0x18, +-0x00,0x03,0x13,0x43,0x00,0x04,0x1a,0x02,0x30,0x47,0x00,0x01,0x12,0x20,0x00,0x04, +-0x30,0x64,0x07,0xff,0x2e,0x03,0x00,0x04,0x32,0x42,0x00,0x33,0x00,0x43,0x90,0x0b, +-0x8f,0xa5,0x00,0x24,0x8f,0xa6,0x00,0x1c,0x00,0x12,0x10,0x40,0x00,0x05,0x19,0xc0, +-0x00,0x47,0x10,0x21,0x00,0x06,0x2a,0x80,0x00,0x43,0x10,0x21,0x00,0x10,0x32,0x00, +-0x00,0x04,0x24,0x80,0x02,0x65,0x28,0x21,0x00,0xa4,0x28,0x21,0x00,0x46,0x10,0x21, +-0x00,0x17,0x1c,0x00,0x3c,0x04,0xc0,0x00,0x00,0x43,0x30,0x21,0x16,0x80,0x00,0x29, +-0x00,0xa4,0x28,0x21,0x3c,0x02,0xb0,0x05,0x34,0x42,0x04,0x00,0x3c,0x03,0xb0,0x05, +-0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00,0x34,0x63,0x04,0x04,0x34,0x84,0x02,0x28, +-0x24,0x02,0x00,0x01,0xac,0x65,0x00,0x00,0xa0,0x82,0x00,0x00,0x3c,0x02,0xb0,0x09, +-0x34,0x42,0x01,0x46,0x90,0x44,0x00,0x00,0x91,0xe3,0x00,0x09,0x30,0x86,0x00,0x01, +-0x02,0x83,0x18,0x26,0x00,0x03,0x30,0x0b,0x14,0xc0,0x00,0x03,0x00,0x00,0x28,0x21, +-0x13,0xc0,0x00,0x03,0x02,0xb3,0x10,0x21,0x24,0x05,0x00,0x01,0x02,0xb3,0x10,0x21, +-0x27,0x83,0x90,0x08,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x84,0x48,0x00,0x04, +-0x00,0xa0,0x30,0x21,0x00,0xe0,0x20,0x21,0x02,0x80,0x28,0x21,0x02,0xc0,0x38,0x21, +-0x0c,0x00,0x00,0x70,0xaf,0xa8,0x00,0x10,0x7b,0xbe,0x02,0xbc,0x7b,0xb6,0x02,0x7c, +-0x7b,0xb4,0x02,0x3c,0x7b,0xb2,0x01,0xfc,0x7b,0xb0,0x01,0xbc,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x58,0x24,0x02,0x00,0x01,0x12,0x82,0x00,0x3d,0x3c,0x02,0xb0,0x05, +-0x24,0x02,0x00,0x02,0x12,0x82,0x00,0x31,0x3c,0x02,0xb0,0x05,0x24,0x02,0x00,0x03, +-0x12,0x82,0x00,0x25,0x3c,0x02,0xb0,0x05,0x24,0x02,0x00,0x10,0x12,0x82,0x00,0x19, +-0x3c,0x02,0xb0,0x05,0x24,0x02,0x00,0x11,0x12,0x82,0x00,0x0d,0x3c,0x02,0xb0,0x05, +-0x24,0x02,0x00,0x12,0x16,0x82,0xff,0xd1,0x3c,0x02,0xb0,0x05,0x3c,0x03,0xb0,0x05, +-0x34,0x42,0x04,0x20,0x3c,0x04,0xb0,0x05,0x34,0x63,0x04,0x24,0xac,0x46,0x00,0x00, +-0x34,0x84,0x02,0x28,0xac,0x65,0x00,0x00,0x08,0x00,0x07,0xe6,0x24,0x02,0x00,0x20, +-0x34,0x42,0x04,0x40,0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00, +-0x34,0x63,0x04,0x44,0x34,0x84,0x02,0x28,0x24,0x02,0x00,0x40,0x08,0x00,0x07,0xe6, +-0xac,0x65,0x00,0x00,0x34,0x42,0x04,0x28,0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05, +-0xac,0x46,0x00,0x00,0x34,0x63,0x04,0x2c,0x34,0x84,0x02,0x28,0x24,0x02,0xff,0x80, +-0x08,0x00,0x07,0xe6,0xac,0x65,0x00,0x00,0x34,0x42,0x04,0x18,0x3c,0x03,0xb0,0x05, +-0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00,0x34,0x63,0x04,0x1c,0x34,0x84,0x02,0x28, +-0x24,0x02,0x00,0x08,0x08,0x00,0x07,0xe6,0xac,0x65,0x00,0x00,0x34,0x42,0x04,0x10, +-0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00,0x34,0x63,0x04,0x14, +-0x34,0x84,0x02,0x28,0x24,0x02,0x00,0x04,0x08,0x00,0x07,0xe6,0xac,0x65,0x00,0x00, +-0x34,0x42,0x04,0x08,0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00, +-0x34,0x63,0x04,0x0c,0x34,0x84,0x02,0x28,0x24,0x02,0x00,0x02,0x08,0x00,0x07,0xe6, +-0xac,0x65,0x00,0x00,0x24,0x17,0x00,0x14,0x08,0x00,0x07,0xb8,0x24,0x13,0x01,0x02, +-0x30,0xa2,0x00,0x07,0x24,0x44,0x00,0x0c,0x00,0x90,0x18,0x2b,0x10,0x60,0x00,0x0c, +-0x26,0x02,0x00,0x04,0x27,0x85,0xbb,0x1c,0x00,0x10,0x10,0x40,0x00,0x50,0x10,0x21, +-0x00,0x45,0x10,0x21,0x90,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x18,0x2b, +-0x14,0x60,0xff,0xfa,0x00,0x10,0x10,0x40,0x2e,0x06,0x00,0x0c,0x26,0x02,0x00,0x04, +-0x08,0x00,0x07,0xa2,0x00,0x46,0x80,0x0a,0x27,0x82,0xb4,0x00,0x01,0x82,0x20,0x21, +-0x8c,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0xe2,0x00,0x19,0x00,0x00,0x00,0x00, +-0x14,0x40,0x00,0x07,0x00,0x00,0x00,0x00,0x27,0x82,0x90,0x20,0x00,0xc2,0x10,0x21, +-0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x60,0x00,0x14,0x00,0x00,0x00,0x00, +-0x90,0xe3,0x00,0x16,0x27,0x82,0x90,0x08,0x00,0xc2,0x10,0x21,0x34,0x63,0x00,0x20, +-0x90,0x50,0x00,0x07,0xa0,0xe3,0x00,0x16,0x8c,0x84,0x00,0x00,0x00,0x0a,0x1e,0x42, +-0x24,0x06,0x00,0x01,0x90,0x82,0x00,0x16,0x30,0x71,0x00,0x02,0x30,0x72,0x00,0x3f, +-0x30,0x42,0x00,0xfb,0x24,0x17,0x00,0x18,0x24,0x13,0x01,0x03,0x24,0x15,0x08,0x18, +-0xaf,0xa6,0x00,0x1c,0x08,0x00,0x07,0xc2,0xa0,0x82,0x00,0x16,0x8d,0x02,0x00,0x04, +-0x00,0x0a,0x1c,0x42,0x30,0x42,0x00,0x10,0x14,0x40,0x00,0x15,0x30,0x72,0x00,0x3f, +-0x81,0x22,0x00,0x05,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x11,0x30,0x72,0x00,0x3e, +-0x27,0x83,0x90,0x18,0x00,0xc3,0x18,0x21,0x80,0x64,0x00,0x00,0x27,0x83,0xb5,0x78, +-0x00,0x04,0x11,0x00,0x00,0x44,0x10,0x23,0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x23, +-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x05,0x90,0x43,0x00,0x04, +-0x00,0x00,0x00,0x00,0x00,0x64,0x18,0x24,0x30,0x63,0x00,0x01,0x02,0x43,0x90,0x25, +-0x27,0x85,0xb4,0x00,0x01,0x85,0x28,0x21,0x8c,0xa6,0x00,0x00,0x01,0x73,0x10,0x21, +-0x27,0x83,0x90,0x10,0x90,0xc4,0x00,0x16,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21, +-0x30,0x84,0x00,0xdf,0x90,0x50,0x00,0x00,0xa0,0xc4,0x00,0x16,0x80,0xc6,0x00,0x12, +-0x8c,0xa3,0x00,0x00,0x2d,0xc4,0x00,0x02,0xaf,0xa6,0x00,0x1c,0x90,0x62,0x00,0x16, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xfb,0x14,0x80,0x00,0x06,0xa0,0x62,0x00,0x16, +-0x24,0x02,0x00,0x06,0x11,0xc2,0x00,0x03,0x24,0x02,0x00,0x04,0x15,0xc2,0xff,0x0e, +-0x32,0x51,0x00,0x02,0x32,0x51,0x00,0x02,0x2e,0x02,0x00,0x0c,0x14,0x40,0x00,0x0f, +-0x00,0x11,0x18,0x2b,0x32,0x02,0x00,0x0f,0x34,0x42,0x00,0x10,0x00,0x03,0x19,0x00, +-0x00,0x43,0x18,0x21,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xe0,0xa0,0x43,0x00,0x00, +-0x00,0x00,0x20,0x21,0x02,0x00,0x28,0x21,0x0c,0x00,0x02,0x03,0xaf,0xaf,0x00,0x28, +-0x8f,0xaf,0x00,0x28,0x08,0x00,0x07,0xc2,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0xbd, +-0x32,0x03,0x00,0xff,0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x42,0x90,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x0f,0x14,0x40,0xfe,0xaa,0x00,0x00,0x00,0x00, +-0x91,0xe2,0x00,0x09,0x00,0x00,0x00,0x00,0x02,0x82,0x10,0x26,0x08,0x00,0x07,0x79, +-0x00,0x02,0x28,0x0b,0x08,0x00,0x07,0x7f,0x00,0x00,0xb0,0x21,0x24,0x02,0x00,0x10, +-0x10,0xc2,0x00,0x08,0x24,0x02,0x00,0x11,0x10,0xc2,0xfe,0x7d,0x00,0x07,0x17,0x83, +-0x24,0x02,0x00,0x12,0x14,0xc2,0xfe,0x7b,0x00,0x07,0x17,0x43,0x08,0x00,0x07,0x59, +-0x30,0x5e,0x00,0x01,0x08,0x00,0x07,0x59,0x00,0x07,0xf7,0xc2,0x00,0x04,0x10,0x40, +-0x27,0x83,0x80,0x1c,0x00,0x43,0x10,0x21,0x00,0x80,0x40,0x21,0x94,0x44,0x00,0x00, +-0x2d,0x07,0x00,0x04,0x24,0xc2,0x00,0x03,0x00,0x47,0x30,0x0a,0x00,0x86,0x00,0x18, +-0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x23,0x8c, +-0xac,0x62,0x00,0x00,0x2d,0x06,0x00,0x10,0x00,0x00,0x20,0x12,0x00,0x04,0x22,0x42, +-0x24,0x84,0x00,0x01,0x24,0x83,0x00,0xc0,0x10,0xe0,0x00,0x0b,0x24,0x82,0x00,0x60, +-0x00,0x40,0x20,0x21,0x00,0x65,0x20,0x0a,0x3c,0x03,0xb0,0x03,0x34,0x63,0x01,0x00, +-0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x00,0x44,0x20,0x04, +-0x03,0xe0,0x00,0x08,0x00,0x80,0x10,0x21,0x24,0x85,0x00,0x28,0x24,0x83,0x00,0x24, +-0x31,0x02,0x00,0x08,0x14,0xc0,0xff,0xf4,0x24,0x84,0x00,0x14,0x00,0x60,0x20,0x21, +-0x08,0x00,0x08,0xfa,0x00,0xa2,0x20,0x0b,0x27,0xbd,0xff,0xe0,0x3c,0x03,0xb0,0x03, +-0x3c,0x02,0x80,0x00,0xaf,0xb0,0x00,0x10,0x24,0x42,0x24,0x28,0x00,0x80,0x80,0x21, +-0x34,0x63,0x00,0x20,0x3c,0x04,0xb0,0x03,0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14, +-0xaf,0xbf,0x00,0x1c,0x83,0xb1,0x00,0x33,0x83,0xa8,0x00,0x37,0x34,0x84,0x01,0x10, +-0xac,0x62,0x00,0x00,0x2e,0x02,0x00,0x10,0x00,0xe0,0x90,0x21,0x8c,0x87,0x00,0x00, +-0x14,0x40,0x00,0x0c,0x2e,0x02,0x00,0x0c,0x3c,0x02,0x00,0x0f,0x34,0x42,0xf0,0x00, +-0x00,0xe2,0x10,0x24,0x14,0x40,0x00,0x37,0x32,0x02,0x00,0x08,0x32,0x02,0x00,0x07, +-0x27,0x83,0x80,0xcc,0x00,0x43,0x10,0x21,0x90,0x50,0x00,0x00,0x00,0x00,0x00,0x00, +-0x2e,0x02,0x00,0x0c,0x14,0x40,0x00,0x03,0x02,0x00,0x20,0x21,0x32,0x02,0x00,0x0f, +-0x24,0x44,0x00,0x0c,0x00,0x87,0x10,0x06,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x07, +-0x2c,0x82,0x00,0x0c,0x00,0x04,0x10,0x80,0x27,0x83,0xb4,0x50,0x00,0x43,0x10,0x21, +-0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x82,0x00,0x0c,0x14,0x40,0x00,0x05, +-0x00,0x05,0x10,0x40,0x00,0x46,0x10,0x21,0x00,0x02,0x11,0x00,0x00,0x82,0x10,0x21, +-0x24,0x44,0x00,0x04,0x15,0x00,0x00,0x02,0x24,0x06,0x00,0x20,0x24,0x06,0x00,0x0e, +-0x0c,0x00,0x08,0xe3,0x00,0x00,0x00,0x00,0x00,0x40,0x30,0x21,0x3c,0x02,0xb0,0x03, +-0x34,0x42,0x01,0x00,0x90,0x43,0x00,0x00,0x2e,0x04,0x00,0x04,0x24,0x02,0x00,0x10, +-0x24,0x05,0x00,0x0a,0x00,0x44,0x28,0x0a,0x30,0x63,0x00,0x01,0x14,0x60,0x00,0x02, +-0x00,0x05,0x10,0x40,0x00,0xa0,0x10,0x21,0x30,0x45,0x00,0xff,0x00,0xc5,0x10,0x21, +-0x24,0x46,0x00,0x46,0x02,0x26,0x18,0x04,0xa6,0x43,0x00,0x00,0x8f,0xbf,0x00,0x1c, +-0x8f,0xb2,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x00,0xc0,0x10,0x21,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x20,0x10,0x40,0xff,0xcf,0x2e,0x02,0x00,0x0c,0x32,0x02,0x00,0x07, +-0x27,0x83,0x80,0xc4,0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x00,0x08,0x00,0x09,0x28, +-0x02,0x04,0x80,0x23,0x27,0xbd,0xff,0xb8,0x00,0x05,0x38,0x80,0x27,0x82,0xb4,0x00, +-0xaf,0xbe,0x00,0x40,0xaf,0xb6,0x00,0x38,0xaf,0xb3,0x00,0x2c,0xaf,0xbf,0x00,0x44, +-0xaf,0xb7,0x00,0x3c,0xaf,0xb5,0x00,0x34,0xaf,0xb4,0x00,0x30,0xaf,0xb2,0x00,0x28, +-0xaf,0xb1,0x00,0x24,0xaf,0xb0,0x00,0x20,0x00,0xe2,0x38,0x21,0x8c,0xe6,0x00,0x00, +-0xaf,0xa5,0x00,0x4c,0x3c,0x02,0x80,0x00,0x3c,0x05,0xb0,0x03,0x34,0xa5,0x00,0x20, +-0x24,0x42,0x25,0x84,0x24,0x03,0x00,0x01,0xac,0xa2,0x00,0x00,0xa0,0xc3,0x00,0x12, +-0x8c,0xe5,0x00,0x00,0x94,0xc3,0x00,0x06,0x90,0xa2,0x00,0x16,0xa4,0xc3,0x00,0x14, +-0x27,0x83,0x90,0x00,0x34,0x42,0x00,0x08,0xa0,0xa2,0x00,0x16,0x8c,0xe8,0x00,0x00, +-0xaf,0xa4,0x00,0x48,0x27,0x82,0x90,0x04,0x95,0x11,0x00,0x14,0x00,0x00,0x00,0x00, +-0x00,0x11,0x98,0xc0,0x02,0x71,0x20,0x21,0x00,0x04,0x20,0x80,0x00,0x82,0x10,0x21, +-0x8c,0x52,0x00,0x18,0x00,0x83,0x18,0x21,0x84,0x75,0x00,0x06,0x8e,0x45,0x00,0x08, +-0x8e,0x46,0x00,0x04,0x8e,0x47,0x00,0x04,0x00,0x05,0x1c,0x82,0x00,0x06,0x31,0x42, +-0x27,0x82,0x90,0x10,0x30,0x63,0x00,0x01,0x30,0xc6,0x00,0x01,0x00,0x82,0x20,0x21, +-0xa5,0x15,0x00,0x1a,0x00,0x05,0x14,0x42,0xaf,0xa3,0x00,0x18,0xaf,0xa6,0x00,0x1c, +-0x30,0xe7,0x00,0x10,0x30,0x56,0x00,0x01,0x80,0x97,0x00,0x06,0x14,0xe0,0x00,0x47, +-0x00,0x05,0xf7,0xc2,0x80,0x82,0x00,0x05,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x44, +-0x02,0x71,0x10,0x21,0x93,0x90,0xbb,0xe9,0x00,0x00,0x00,0x00,0x2e,0x02,0x00,0x0c, +-0x14,0x40,0x00,0x06,0x02,0x00,0x20,0x21,0x00,0x16,0x10,0x40,0x00,0x43,0x10,0x21, +-0x00,0x02,0x11,0x00,0x02,0x02,0x10,0x21,0x24,0x44,0x00,0x04,0x02,0x71,0x10,0x21, +-0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x10,0x00,0x43,0x10,0x21,0x00,0x80,0x80,0x21, +-0xa0,0x44,0x00,0x03,0xa0,0x44,0x00,0x00,0x02,0x00,0x20,0x21,0x02,0xc0,0x28,0x21, +-0x0c,0x00,0x08,0xe3,0x02,0xa0,0x30,0x21,0x02,0x71,0x18,0x21,0x00,0x03,0x88,0x80, +-0x00,0x40,0xa0,0x21,0x27,0x82,0x90,0x20,0x02,0x22,0x10,0x21,0x8c,0x44,0x00,0x00, +-0x26,0xe3,0x00,0x02,0x00,0x03,0x17,0xc2,0x00,0x62,0x18,0x21,0x00,0x04,0x25,0xc2, +-0x00,0x03,0x18,0x43,0x30,0x84,0x00,0x01,0x00,0x03,0x18,0x40,0x03,0xc4,0x20,0x24, +-0x14,0x80,0x00,0x15,0x02,0x43,0x38,0x21,0x3c,0x08,0xb0,0x03,0x35,0x08,0x00,0x28, +-0x8d,0x03,0x00,0x00,0x8f,0xa6,0x00,0x4c,0x8f,0xa4,0x00,0x48,0x27,0x82,0x90,0x08, +-0x02,0x22,0x10,0x21,0x24,0x63,0x00,0x01,0x02,0xa0,0x28,0x21,0xa4,0x54,0x00,0x04, +-0x00,0xc0,0x38,0x21,0x0c,0x00,0x07,0x2f,0xad,0x03,0x00,0x00,0x7b,0xbe,0x02,0x3c, +-0x7b,0xb6,0x01,0xfc,0x7b,0xb4,0x01,0xbc,0x7b,0xb2,0x01,0x7c,0x7b,0xb0,0x01,0x3c, +-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x48,0x8f,0xa2,0x00,0x1c,0x8f,0xa6,0x00,0x18, +-0x02,0x00,0x20,0x21,0x02,0xc0,0x28,0x21,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0x0a, +-0xaf,0xa0,0x00,0x14,0x08,0x00,0x09,0xc6,0x02,0x82,0xa0,0x21,0x02,0x71,0x10,0x21, +-0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x10,0x00,0x43,0x10,0x21,0x90,0x50,0x00,0x00, +-0x08,0x00,0x09,0xb2,0xa0,0x50,0x00,0x03,0x27,0xbd,0xff,0xb8,0xaf,0xb1,0x00,0x24, +-0x8f,0xb1,0x00,0x5c,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20, +-0x24,0x42,0x27,0xa8,0xaf,0xbe,0x00,0x40,0xaf,0xb7,0x00,0x3c,0xaf,0xb6,0x00,0x38, +-0xaf,0xb5,0x00,0x34,0xaf,0xb4,0x00,0x30,0xaf,0xa5,0x00,0x4c,0x8f,0xb5,0x00,0x58, +-0xaf,0xbf,0x00,0x44,0xaf,0xb3,0x00,0x2c,0xaf,0xb2,0x00,0x28,0xaf,0xb0,0x00,0x20, +-0x00,0xe0,0xb0,0x21,0xac,0x62,0x00,0x00,0x00,0x80,0xf0,0x21,0x00,0x00,0xb8,0x21, +-0x16,0x20,0x00,0x2b,0x00,0x00,0xa0,0x21,0x27,0x85,0xb4,0x00,0x00,0x07,0x10,0x80, +-0x00,0x45,0x10,0x21,0x8c,0x53,0x00,0x00,0x00,0x15,0x18,0x80,0x00,0x65,0x18,0x21, +-0x92,0x62,0x00,0x16,0x8c,0x72,0x00,0x00,0x30,0x42,0x00,0x03,0x14,0x40,0x00,0x2d, +-0x00,0x00,0x00,0x00,0x92,0x42,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x03, +-0x14,0x40,0x00,0x28,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x34,0x00,0x00,0x00,0x00, +-0x14,0x40,0x00,0x18,0x02,0x20,0x10,0x21,0x8c,0x82,0x00,0x38,0x00,0x00,0x00,0x00, +-0x14,0x40,0x00,0x14,0x02,0x20,0x10,0x21,0x8c,0x82,0x00,0x3c,0x00,0x00,0x00,0x00, +-0x14,0x40,0x00,0x0f,0x3c,0x03,0xb0,0x09,0x3c,0x05,0xb0,0x05,0x34,0x63,0x01,0x44, +-0x34,0xa5,0x02,0x52,0x94,0x66,0x00,0x00,0x90,0xa2,0x00,0x00,0x8f,0xa3,0x00,0x4c, +-0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x06,0x30,0x42,0x00,0x01,0x10,0x40,0x00,0x04, +-0x30,0xc6,0xff,0xff,0x2c,0xc2,0x00,0x41,0x10,0x40,0x00,0x09,0x24,0x05,0x00,0x14, +-0x02,0x20,0x10,0x21,0x7b,0xbe,0x02,0x3c,0x7b,0xb6,0x01,0xfc,0x7b,0xb4,0x01,0xbc, +-0x7b,0xb2,0x01,0x7c,0x7b,0xb0,0x01,0x3c,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x48, +-0x0c,0x00,0x07,0x0a,0x24,0x06,0x01,0x07,0x24,0x02,0x00,0x01,0x08,0x00,0x0a,0x2c, +-0xa3,0xc2,0x00,0x11,0x10,0xc0,0x00,0x1c,0x24,0x02,0x00,0x01,0x10,0xc2,0x00,0x17, +-0x00,0xc0,0x88,0x21,0x96,0x54,0x00,0x1a,0x02,0xa0,0xb8,0x21,0x12,0x20,0xff,0xed, +-0x02,0x20,0x10,0x21,0x27,0x83,0xb4,0x00,0x00,0x17,0x10,0x80,0x00,0x43,0x10,0x21, +-0x8c,0x44,0x00,0x00,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x28,0x80,0x86,0x00,0x12, +-0x8c,0x62,0x00,0x00,0x00,0x14,0x2c,0x00,0x00,0x05,0x2c,0x03,0x00,0x46,0x10,0x21, +-0x8f,0xa6,0x00,0x4c,0x02,0xe0,0x38,0x21,0x03,0xc0,0x20,0x21,0x0c,0x00,0x07,0x2f, +-0xac,0x62,0x00,0x00,0x08,0x00,0x0a,0x2c,0xaf,0xd1,0x00,0x40,0x96,0x74,0x00,0x1a, +-0x08,0x00,0x0a,0x3f,0x02,0xc0,0xb8,0x21,0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x08, +-0x8c,0x50,0x00,0x00,0x02,0x60,0x20,0x21,0x0c,0x00,0x1e,0xf3,0x02,0x00,0x28,0x21, +-0x30,0x42,0x00,0xff,0x02,0x00,0x28,0x21,0x02,0x40,0x20,0x21,0x0c,0x00,0x1e,0xf3, +-0xaf,0xa2,0x00,0x18,0x8f,0xa4,0x00,0x18,0x00,0x00,0x00,0x00,0x10,0x80,0x00,0xed, +-0x30,0x50,0x00,0xff,0x12,0x00,0x00,0x18,0x24,0x11,0x00,0x01,0x96,0x63,0x00,0x14, +-0x96,0x44,0x00,0x14,0x27,0x85,0x90,0x00,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +-0x00,0x02,0x10,0x80,0x00,0x45,0x10,0x21,0x00,0x04,0x18,0xc0,0x8c,0x46,0x00,0x08, +-0x00,0x64,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0x65,0x18,0x21,0x00,0x06,0x17,0x02, +-0x24,0x04,0x00,0xff,0x8c,0x63,0x00,0x08,0x10,0x44,0x00,0xd6,0x00,0x03,0x17,0x02, +-0x10,0x44,0x00,0xd5,0x3c,0x02,0x80,0x00,0x00,0x66,0x18,0x2b,0x24,0x11,0x00,0x02, +-0x24,0x02,0x00,0x01,0x00,0x43,0x88,0x0a,0x24,0x02,0x00,0x01,0x12,0x22,0x00,0x5a, +-0x24,0x02,0x00,0x02,0x16,0x22,0xff,0xbd,0x00,0x00,0x00,0x00,0x96,0x49,0x00,0x14, +-0x27,0x82,0x90,0x04,0x02,0xa0,0xb8,0x21,0x00,0x09,0x50,0xc0,0x01,0x49,0x18,0x21, +-0x00,0x03,0x40,0x80,0x01,0x02,0x10,0x21,0x8c,0x43,0x00,0x18,0x00,0x00,0x00,0x00, +-0x8c,0x65,0x00,0x08,0x8c,0x62,0x00,0x0c,0x8c,0x62,0x00,0x04,0x00,0x05,0x24,0x42, +-0x00,0x05,0x1c,0x82,0x30,0x42,0x00,0x10,0x30,0x66,0x00,0x01,0x14,0x40,0x00,0x41, +-0x30,0x87,0x00,0x01,0x27,0x82,0x90,0x18,0x01,0x02,0x10,0x21,0x80,0x44,0x00,0x00, +-0x27,0x82,0xb5,0x78,0x00,0x04,0x19,0x00,0x00,0x64,0x18,0x23,0x00,0x03,0x18,0x80, +-0x00,0x64,0x18,0x23,0x00,0x03,0x18,0x80,0x00,0x62,0x10,0x21,0x90,0x45,0x00,0x05, +-0x27,0x84,0xb4,0xa0,0x00,0x64,0x18,0x21,0x90,0x63,0x00,0x00,0x10,0xa0,0x00,0x2b, +-0x2c,0x64,0x00,0x0c,0x14,0x80,0x00,0x04,0x00,0x60,0x10,0x21,0x00,0x06,0x11,0x00, +-0x00,0x62,0x10,0x21,0x24,0x42,0x00,0x24,0x3c,0x01,0xb0,0x03,0xa0,0x22,0x00,0xe1, +-0x14,0x80,0x00,0x06,0x00,0x60,0x28,0x21,0x00,0x07,0x10,0x40,0x00,0x46,0x10,0x21, +-0x00,0x02,0x11,0x00,0x00,0x62,0x10,0x21,0x24,0x45,0x00,0x04,0x01,0x49,0x10,0x21, +-0x27,0x83,0x90,0x10,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x00,0xa0,0x18,0x21, +-0xa0,0x45,0x00,0x03,0xa0,0x45,0x00,0x00,0x24,0x02,0x00,0x08,0x12,0x02,0x00,0x0b, +-0x24,0x02,0x00,0x01,0x00,0x60,0x28,0x21,0x02,0x40,0x20,0x21,0x0c,0x00,0x1f,0x6f, +-0xaf,0xa2,0x00,0x10,0x30,0x54,0xff,0xff,0x92,0x42,0x00,0x16,0x00,0x00,0x00,0x00, +-0x02,0x02,0x10,0x25,0x08,0x00,0x0a,0x3f,0xa2,0x42,0x00,0x16,0x00,0x60,0x28,0x21, +-0x02,0x40,0x20,0x21,0x0c,0x00,0x1f,0x20,0xaf,0xa0,0x00,0x10,0x08,0x00,0x0a,0xc2, +-0x30,0x54,0xff,0xff,0x08,0x00,0x0a,0xaa,0x00,0x60,0x10,0x21,0x14,0x80,0xff,0xfd, +-0x00,0x00,0x00,0x00,0x00,0x06,0x11,0x00,0x00,0x62,0x10,0x21,0x08,0x00,0x0a,0xaa, +-0x24,0x42,0x00,0x04,0x27,0x82,0x90,0x10,0x01,0x02,0x10,0x21,0x90,0x43,0x00,0x00, +-0x08,0x00,0x0a,0xba,0xa0,0x43,0x00,0x03,0x96,0x69,0x00,0x14,0x02,0xc0,0xb8,0x21, +-0x24,0x0b,0x00,0x01,0x00,0x09,0x10,0xc0,0x00,0x49,0x18,0x21,0x00,0x03,0x40,0x80, +-0x00,0x40,0x50,0x21,0x27,0x82,0x90,0x04,0x01,0x02,0x10,0x21,0x8c,0x43,0x00,0x18, +-0x00,0x00,0x00,0x00,0x8c,0x65,0x00,0x08,0x8c,0x62,0x00,0x0c,0x8c,0x62,0x00,0x04, +-0x00,0x05,0x24,0x42,0x00,0x05,0x1c,0x82,0x30,0x42,0x00,0x10,0x30,0x66,0x00,0x01, +-0x10,0x40,0x00,0x0d,0x30,0x87,0x00,0x01,0x27,0x82,0x90,0x18,0x01,0x02,0x10,0x21, +-0x80,0x43,0x00,0x00,0x00,0x00,0x58,0x21,0x00,0x03,0x11,0x00,0x00,0x43,0x10,0x23, +-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x23,0x00,0x02,0x10,0x80,0x27,0x83,0xb5,0x70, +-0x00,0x43,0x10,0x21,0xa0,0x40,0x00,0x04,0x11,0x60,0x00,0x4f,0x00,0x00,0x00,0x00, +-0x01,0x49,0x10,0x21,0x00,0x02,0x20,0x80,0x27,0x85,0x90,0x10,0x00,0x85,0x10,0x21, +-0x80,0x43,0x00,0x05,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x42,0x01,0x49,0x10,0x21, +-0x27,0x82,0x90,0x18,0x00,0x82,0x10,0x21,0x80,0x44,0x00,0x00,0x27,0x82,0xb5,0x78, +-0x00,0x04,0x19,0x00,0x00,0x64,0x18,0x23,0x00,0x03,0x18,0x80,0x00,0x64,0x18,0x23, +-0x00,0x03,0x18,0x80,0x00,0x62,0x10,0x21,0x90,0x45,0x00,0x05,0x27,0x84,0xb4,0xa0, +-0x00,0x64,0x18,0x21,0x90,0x63,0x00,0x00,0x10,0xa0,0x00,0x2c,0x2c,0x64,0x00,0x0c, +-0x14,0x80,0x00,0x04,0x00,0x60,0x10,0x21,0x00,0x06,0x11,0x00,0x00,0x62,0x10,0x21, +-0x24,0x42,0x00,0x24,0x3c,0x01,0xb0,0x03,0xa0,0x22,0x00,0xe1,0x14,0x80,0x00,0x06, +-0x00,0x60,0x28,0x21,0x00,0x07,0x10,0x40,0x00,0x46,0x10,0x21,0x00,0x02,0x11,0x00, +-0x00,0x62,0x10,0x21,0x24,0x45,0x00,0x04,0x01,0x49,0x10,0x21,0x27,0x83,0x90,0x10, +-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x00,0xa0,0x18,0x21,0xa0,0x45,0x00,0x03, +-0xa0,0x45,0x00,0x00,0x8f,0xa4,0x00,0x18,0x24,0x02,0x00,0x08,0x10,0x82,0x00,0x0c, +-0x00,0x60,0x28,0x21,0x24,0x02,0x00,0x01,0x02,0x60,0x20,0x21,0x0c,0x00,0x1f,0x6f, +-0xaf,0xa2,0x00,0x10,0x8f,0xa3,0x00,0x18,0x30,0x54,0xff,0xff,0x92,0x62,0x00,0x16, +-0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x25,0x08,0x00,0x0a,0x3f,0xa2,0x62,0x00,0x16, +-0x02,0x60,0x20,0x21,0x0c,0x00,0x1f,0x20,0xaf,0xa0,0x00,0x10,0x08,0x00,0x0b,0x31, +-0x00,0x00,0x00,0x00,0x08,0x00,0x0b,0x19,0x00,0x60,0x10,0x21,0x14,0x80,0xff,0xfd, +-0x00,0x00,0x00,0x00,0x00,0x06,0x11,0x00,0x00,0x62,0x10,0x21,0x08,0x00,0x0b,0x19, +-0x24,0x42,0x00,0x04,0x00,0x02,0x10,0x80,0x00,0x45,0x10,0x21,0x90,0x43,0x00,0x00, +-0x08,0x00,0x0b,0x29,0xa0,0x43,0x00,0x03,0x27,0x85,0x90,0x10,0x08,0x00,0x0b,0x45, +-0x01,0x49,0x10,0x21,0x3c,0x02,0x80,0x00,0x00,0x62,0x18,0x26,0x08,0x00,0x0a,0x7a, +-0x00,0xc2,0x30,0x26,0x12,0x00,0xff,0x2d,0x24,0x02,0x00,0x01,0x08,0x00,0x0a,0x7f, +-0x24,0x11,0x00,0x02,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xd0, +-0x24,0x42,0x2d,0x54,0x34,0x63,0x00,0x20,0x3c,0x05,0xb0,0x05,0xaf,0xb3,0x00,0x24, +-0xaf,0xb2,0x00,0x20,0xaf,0xb1,0x00,0x1c,0xaf,0xbf,0x00,0x28,0xaf,0xb0,0x00,0x18, +-0xac,0x62,0x00,0x00,0x34,0xa5,0x02,0x42,0x90,0xa2,0x00,0x00,0x00,0x80,0x90,0x21, +-0x24,0x11,0x00,0x10,0x30,0x53,0x00,0xff,0x24,0x02,0x00,0x10,0x12,0x22,0x00,0xcf, +-0x00,0x00,0x18,0x21,0x24,0x02,0x00,0x11,0x12,0x22,0x00,0xc1,0x24,0x02,0x00,0x12, +-0x12,0x22,0x00,0xb4,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0xad,0xae,0x43,0x00,0x40, +-0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2c,0x8c,0x44,0x00,0x00,0x3c,0x03,0x00,0x02, +-0x34,0x63,0x00,0xff,0x00,0x83,0x80,0x24,0x00,0x10,0x14,0x43,0x10,0x40,0x00,0x05, +-0x00,0x00,0x00,0x00,0x8e,0x42,0x00,0x34,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x92, +-0x00,0x00,0x00,0x00,0x93,0x83,0x8b,0x71,0x00,0x00,0x00,0x00,0x30,0x62,0x00,0x02, +-0x10,0x40,0x00,0x04,0x32,0x10,0x00,0xff,0x00,0x10,0x11,0xc3,0x14,0x40,0x00,0x86, +-0x00,0x00,0x00,0x00,0x16,0x00,0x00,0x15,0x02,0x00,0x10,0x21,0x26,0x22,0x00,0x01, +-0x30,0x51,0x00,0xff,0x2e,0x23,0x00,0x13,0x14,0x60,0xff,0xdb,0x24,0x03,0x00,0x02, +-0x12,0x63,0x00,0x73,0x24,0x02,0x00,0x05,0x2a,0x62,0x00,0x03,0x10,0x40,0x00,0x58, +-0x24,0x02,0x00,0x04,0x24,0x02,0x00,0x01,0x12,0x62,0x00,0x4b,0x02,0x40,0x20,0x21, +-0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2c,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00, +-0x30,0x70,0x00,0xff,0x12,0x00,0x00,0x06,0x02,0x00,0x10,0x21,0x8f,0xbf,0x00,0x28, +-0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x30, +-0x92,0x46,0x00,0x04,0x8e,0x43,0x00,0x24,0x24,0x02,0x00,0x07,0x02,0x40,0x20,0x21, +-0x00,0x00,0x28,0x21,0x24,0x07,0x00,0x06,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xea, +-0xaf,0xa3,0x00,0x14,0xae,0x42,0x00,0x24,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x02,0x2c, +-0x00,0x00,0x00,0x00,0x30,0x50,0x00,0xff,0x16,0x00,0xff,0xec,0x02,0x00,0x10,0x21, +-0x92,0x46,0x00,0x05,0x8e,0x43,0x00,0x28,0x24,0x02,0x00,0x05,0x02,0x40,0x20,0x21, +-0x24,0x05,0x00,0x01,0x24,0x07,0x00,0x04,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xea, +-0xaf,0xa3,0x00,0x14,0xae,0x42,0x00,0x28,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x02,0x2c, +-0x00,0x00,0x00,0x00,0x30,0x50,0x00,0xff,0x16,0x00,0xff,0xdc,0x02,0x00,0x10,0x21, +-0x92,0x46,0x00,0x06,0x8e,0x43,0x00,0x2c,0x24,0x02,0x00,0x03,0x02,0x40,0x20,0x21, +-0x24,0x05,0x00,0x02,0x00,0x00,0x38,0x21,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xea, +-0xaf,0xa3,0x00,0x14,0xae,0x42,0x00,0x2c,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x02,0x2c, +-0x00,0x00,0x00,0x00,0x30,0x50,0x00,0xff,0x16,0x00,0xff,0xcc,0x02,0x00,0x10,0x21, +-0x92,0x46,0x00,0x07,0x8e,0x43,0x00,0x30,0x24,0x02,0x00,0x02,0x02,0x40,0x20,0x21, +-0x24,0x05,0x00,0x03,0x24,0x07,0x00,0x01,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xea, +-0xaf,0xa3,0x00,0x14,0xae,0x42,0x00,0x30,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x02,0x2c, +-0x08,0x00,0x0b,0x9b,0x30,0x42,0x00,0xff,0x92,0x46,0x00,0x04,0x8e,0x43,0x00,0x24, +-0x24,0x02,0x00,0x07,0x00,0x00,0x28,0x21,0x24,0x07,0x00,0x06,0xaf,0xa2,0x00,0x10, +-0x0c,0x00,0x09,0xea,0xaf,0xa3,0x00,0x14,0x08,0x00,0x0b,0x94,0xae,0x42,0x00,0x24, +-0x12,0x62,0x00,0x0d,0x24,0x02,0x00,0x03,0x24,0x02,0x00,0x08,0x16,0x62,0xff,0xa8, +-0x02,0x40,0x20,0x21,0x92,0x46,0x00,0x07,0x8e,0x42,0x00,0x30,0x24,0x05,0x00,0x03, +-0x24,0x07,0x00,0x01,0xaf,0xa3,0x00,0x10,0x0c,0x00,0x09,0xea,0xaf,0xa2,0x00,0x14, +-0x08,0x00,0x0b,0x94,0xae,0x42,0x00,0x30,0x92,0x46,0x00,0x06,0x8e,0x43,0x00,0x2c, +-0x02,0x40,0x20,0x21,0x24,0x05,0x00,0x02,0x00,0x00,0x38,0x21,0xaf,0xa2,0x00,0x10, +-0x0c,0x00,0x09,0xea,0xaf,0xa3,0x00,0x14,0x08,0x00,0x0b,0x94,0xae,0x42,0x00,0x2c, +-0x92,0x46,0x00,0x05,0x8e,0x43,0x00,0x28,0x02,0x40,0x20,0x21,0x24,0x05,0x00,0x01, +-0x24,0x07,0x00,0x04,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xea,0xaf,0xa3,0x00,0x14, +-0x08,0x00,0x0b,0x94,0xae,0x42,0x00,0x28,0x0c,0x00,0x01,0x57,0x24,0x04,0x00,0x01, +-0x08,0x00,0x0b,0x85,0x00,0x00,0x00,0x00,0x8f,0x84,0xb4,0x40,0xae,0x40,0x00,0x34, +-0x94,0x85,0x00,0x14,0x0c,0x00,0x1b,0x66,0x00,0x00,0x00,0x00,0x93,0x83,0x8b,0x71, +-0x00,0x00,0x00,0x00,0x30,0x62,0x00,0x02,0x10,0x40,0xff,0x69,0x00,0x00,0x00,0x00, +-0x0c,0x00,0x01,0x57,0x00,0x00,0x20,0x21,0x08,0x00,0x0b,0x7d,0x00,0x00,0x00,0x00, +-0x02,0x40,0x20,0x21,0x0c,0x00,0x09,0x61,0x02,0x20,0x28,0x21,0x08,0x00,0x0b,0x71, +-0x3c,0x02,0xb0,0x05,0x8e,0x42,0x00,0x3c,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x4a, +-0x00,0x00,0x00,0x00,0x8f,0x82,0xb4,0x48,0x00,0x00,0x00,0x00,0x90,0x42,0x00,0x0a, +-0x00,0x00,0x00,0x00,0x00,0x02,0x18,0x2b,0x08,0x00,0x0b,0x6e,0xae,0x43,0x00,0x3c, +-0x8e,0x42,0x00,0x38,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x3d,0x24,0x02,0x00,0x12, +-0x8f,0x82,0xb4,0x44,0x00,0x00,0x00,0x00,0x90,0x42,0x00,0x0a,0x00,0x00,0x00,0x00, +-0x00,0x02,0x18,0x2b,0x08,0x00,0x0b,0x6e,0xae,0x43,0x00,0x38,0x8e,0x42,0x00,0x34, +-0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x30,0x24,0x02,0x00,0x11,0x8f,0x82,0xb4,0x40, +-0x00,0x00,0x00,0x00,0x90,0x42,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x02,0x18,0x2b, +-0x08,0x00,0x0b,0x6e,0xae,0x43,0x00,0x34,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00, +-0x27,0xbd,0xff,0xe0,0x34,0x63,0x00,0x20,0x24,0x42,0x31,0x08,0x3c,0x08,0xb0,0x03, +-0xaf,0xb1,0x00,0x14,0xac,0x62,0x00,0x00,0x35,0x08,0x01,0x00,0xaf,0xbf,0x00,0x18, +-0xaf,0xb0,0x00,0x10,0x91,0x03,0x00,0x00,0x00,0xa0,0x48,0x21,0x24,0x11,0x00,0x0a, +-0x2c,0xa5,0x00,0x04,0x24,0x02,0x00,0x10,0x00,0x45,0x88,0x0a,0x30,0x63,0x00,0x01, +-0x00,0xc0,0x28,0x21,0x14,0x60,0x00,0x02,0x00,0x11,0x40,0x40,0x02,0x20,0x40,0x21, +-0x84,0x83,0x00,0x0c,0x31,0x11,0x00,0xff,0x01,0x20,0x20,0x21,0x00,0x03,0x10,0xc0, +-0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x08,0x00,0x43,0x10,0x21, +-0x84,0x43,0x00,0x04,0x24,0x06,0x00,0x0e,0x10,0xe0,0x00,0x06,0x02,0x23,0x80,0x21, +-0x02,0x00,0x10,0x21,0x8f,0xbf,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x20,0x0c,0x00,0x08,0xe3,0x00,0x00,0x00,0x00,0x02,0x11,0x18,0x21, +-0x08,0x00,0x0c,0x64,0x00,0x62,0x80,0x21,0x27,0xbd,0xff,0xd0,0xaf,0xbf,0x00,0x28, +-0xaf,0xb4,0x00,0x20,0xaf,0xb3,0x00,0x1c,0xaf,0xb2,0x00,0x18,0xaf,0xb5,0x00,0x24, +-0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0x84,0x82,0x00,0x0c,0x3c,0x06,0xb0,0x03, +-0x34,0xc6,0x00,0x20,0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21,0x00,0x03,0x18,0x80, +-0x27,0x82,0x90,0x04,0x00,0x62,0x10,0x21,0x8c,0x55,0x00,0x18,0x3c,0x02,0x80,0x00, +-0x24,0x42,0x31,0xb8,0xac,0xc2,0x00,0x00,0x8e,0xb0,0x00,0x08,0x27,0x82,0x90,0x08, +-0x00,0x62,0x18,0x21,0x90,0x71,0x00,0x07,0x00,0x10,0x86,0x43,0x32,0x10,0x00,0x01, +-0x00,0xa0,0x38,0x21,0x02,0x00,0x30,0x21,0x00,0xa0,0x98,0x21,0x02,0x20,0x28,0x21, +-0x0c,0x00,0x0c,0x42,0x00,0x80,0x90,0x21,0x02,0x20,0x20,0x21,0x02,0x00,0x28,0x21, +-0x24,0x06,0x00,0x14,0x0c,0x00,0x08,0xe3,0x00,0x40,0xa0,0x21,0x86,0x43,0x00,0x0c, +-0x3c,0x09,0xb0,0x09,0x3c,0x08,0xb0,0x09,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +-0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x10,0x00,0x43,0x10,0x21,0x80,0x43,0x00,0x06, +-0x3c,0x07,0xb0,0x09,0x3c,0x05,0xb0,0x09,0x28,0x62,0x00,0x00,0x24,0x64,0x00,0x03, +-0x00,0x82,0x18,0x0b,0x00,0x03,0x18,0x83,0x3c,0x02,0xb0,0x09,0x00,0x03,0x18,0x80, +-0x34,0x42,0x01,0x02,0x35,0x29,0x01,0x10,0x35,0x08,0x01,0x14,0x34,0xe7,0x01,0x20, +-0x34,0xa5,0x01,0x24,0xa4,0x54,0x00,0x00,0x12,0x60,0x00,0x11,0x02,0xa3,0xa8,0x21, +-0x8e,0xa2,0x00,0x0c,0x8e,0xa3,0x00,0x08,0x00,0x02,0x14,0x00,0x00,0x03,0x1c,0x02, +-0x00,0x43,0x10,0x21,0xad,0x22,0x00,0x00,0x8e,0xa3,0x00,0x0c,0x00,0x00,0x00,0x00, +-0x00,0x03,0x1c,0x02,0xa5,0x03,0x00,0x00,0x8f,0xbf,0x00,0x28,0x7b,0xb4,0x01,0x3c, +-0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x30, +-0x8e,0xa2,0x00,0x04,0x00,0x00,0x00,0x00,0xad,0x22,0x00,0x00,0x8e,0xa4,0x00,0x08, +-0x00,0x00,0x00,0x00,0xa5,0x04,0x00,0x00,0x7a,0xa2,0x00,0x7c,0x00,0x00,0x00,0x00, +-0x00,0x03,0x1c,0x00,0x00,0x02,0x14,0x02,0x00,0x62,0x18,0x21,0xac,0xe3,0x00,0x00, +-0x8e,0xa2,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x02,0x08,0x00,0x0c,0xb6, +-0xa4,0xa2,0x00,0x00,0x27,0xbd,0xff,0xe0,0xaf,0xb2,0x00,0x18,0xaf,0xb0,0x00,0x10, +-0xaf,0xbf,0x00,0x1c,0xaf,0xb1,0x00,0x14,0x84,0x82,0x00,0x0c,0x00,0x80,0x90,0x21, +-0x3c,0x05,0xb0,0x03,0x00,0x02,0x20,0xc0,0x00,0x82,0x20,0x21,0x00,0x04,0x20,0x80, +-0x27,0x82,0x90,0x04,0x00,0x82,0x10,0x21,0x8c,0x51,0x00,0x18,0x3c,0x02,0x80,0x00, +-0x34,0xa5,0x00,0x20,0x24,0x42,0x33,0x34,0x27,0x83,0x90,0x08,0xac,0xa2,0x00,0x00, +-0x00,0x83,0x20,0x21,0x3c,0x02,0xb0,0x03,0x90,0x86,0x00,0x07,0x34,0x42,0x01,0x00, +-0x8e,0x23,0x00,0x08,0x90,0x44,0x00,0x00,0x2c,0xc5,0x00,0x04,0x24,0x02,0x00,0x10, +-0x24,0x10,0x00,0x0a,0x00,0x45,0x80,0x0a,0x00,0x03,0x1e,0x43,0x30,0x84,0x00,0x01, +-0x30,0x65,0x00,0x01,0x14,0x80,0x00,0x02,0x00,0x10,0x10,0x40,0x02,0x00,0x10,0x21, +-0x00,0xc0,0x20,0x21,0x24,0x06,0x00,0x20,0x0c,0x00,0x08,0xe3,0x30,0x50,0x00,0xff, +-0x86,0x44,0x00,0x0c,0x27,0x85,0x90,0x10,0x3c,0x06,0xb0,0x09,0x00,0x04,0x18,0xc0, +-0x00,0x64,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0x65,0x18,0x21,0x80,0x64,0x00,0x06, +-0x00,0x50,0x10,0x21,0x34,0xc6,0x01,0x02,0x24,0x85,0x00,0x03,0x28,0x83,0x00,0x00, +-0x00,0xa3,0x20,0x0b,0x00,0x04,0x20,0x83,0x00,0x04,0x20,0x80,0xa4,0xc2,0x00,0x00, +-0x02,0x24,0x20,0x21,0x8c,0x83,0x00,0x04,0x3c,0x02,0xb0,0x09,0x34,0x42,0x01,0x10, +-0xac,0x43,0x00,0x00,0x8c,0x86,0x00,0x08,0x3c,0x02,0xb0,0x09,0x34,0x42,0x01,0x14, +-0xa4,0x46,0x00,0x00,0x8c,0x85,0x00,0x0c,0x8c,0x82,0x00,0x08,0x3c,0x06,0xb0,0x09, +-0x00,0x05,0x2c,0x00,0x00,0x02,0x14,0x02,0x00,0xa2,0x28,0x21,0x34,0xc6,0x01,0x20, +-0xac,0xc5,0x00,0x00,0x8c,0x83,0x00,0x0c,0x3c,0x05,0xb0,0x09,0x34,0xa5,0x01,0x24, +-0x00,0x03,0x1c,0x02,0xa4,0xa3,0x00,0x00,0x92,0x42,0x00,0x0a,0x3c,0x03,0xb0,0x09, +-0x34,0x63,0x01,0x30,0x00,0x02,0x13,0x00,0x24,0x42,0x00,0x04,0x30,0x42,0xff,0xff, +-0xa4,0x62,0x00,0x00,0x86,0x44,0x00,0x0c,0x27,0x83,0x90,0x18,0x8f,0xbf,0x00,0x1c, +-0x00,0x04,0x10,0xc0,0x00,0x44,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21, +-0x94,0x44,0x00,0x02,0x8f,0xb2,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x3c,0x05,0xb0,0x09, +-0x34,0xa5,0x01,0x32,0xa4,0xa4,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20, +-0x27,0xbd,0xff,0xe0,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x00,0xaf,0xb0,0x00,0x10, +-0x34,0x42,0x00,0x20,0x00,0xa0,0x80,0x21,0x24,0x63,0x34,0xc0,0x00,0x05,0x2c,0x43, +-0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x18,0xac,0x43,0x00,0x00,0x10,0xa0,0x00,0x05, +-0x00,0x80,0x88,0x21,0x8c,0x82,0x00,0x34,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0xb6, +-0x00,0x00,0x00,0x00,0x32,0x10,0x00,0xff,0x12,0x00,0x00,0x4c,0x00,0x00,0x10,0x21, +-0x24,0x02,0x00,0x08,0x12,0x02,0x00,0xa3,0x2a,0x02,0x00,0x09,0x10,0x40,0x00,0x89, +-0x24,0x02,0x00,0x40,0x24,0x04,0x00,0x02,0x12,0x04,0x00,0x79,0x2a,0x02,0x00,0x03, +-0x10,0x40,0x00,0x69,0x24,0x02,0x00,0x04,0x24,0x02,0x00,0x01,0x12,0x02,0x00,0x5a, +-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x05,0x34,0x42,0x00,0x08,0x3c,0x03,0x80,0x00, +-0xa2,0x20,0x00,0x4e,0xac,0x43,0x00,0x00,0x82,0x24,0x00,0x11,0x92,0x27,0x00,0x11, +-0x10,0x80,0x00,0x4e,0x00,0x00,0x00,0x00,0x92,0x26,0x00,0x0a,0x24,0x02,0x00,0x12, +-0x10,0x46,0x00,0x09,0x30,0xc2,0x00,0xff,0x27,0x83,0xb4,0x00,0x00,0x02,0x10,0x80, +-0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x83,0x00,0x14, +-0x00,0x00,0x00,0x00,0xa6,0x23,0x00,0x0c,0x3c,0x02,0xb0,0x09,0x34,0x42,0x00,0x40, +-0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x03,0xa2,0x23,0x00,0x10, +-0x14,0x60,0x00,0x2b,0x30,0x65,0x00,0x01,0x30,0xc2,0x00,0xff,0x27,0x83,0xb4,0x00, +-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x82,0x23,0x00,0x12, +-0x90,0x82,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x02,0x11,0x42,0x30,0x42,0x00,0x01, +-0x00,0x62,0x18,0x21,0x00,0x03,0x26,0x00,0x14,0x80,0x00,0x18,0xa2,0x23,0x00,0x12, +-0x00,0x07,0x16,0x00,0x14,0x40,0x00,0x11,0x24,0x02,0x00,0x01,0x96,0x23,0x00,0x0c, +-0x27,0x84,0x90,0x10,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80, +-0x00,0x44,0x10,0x21,0x80,0x45,0x00,0x06,0x00,0x03,0x1a,0x00,0x3c,0x02,0xb0,0x00, +-0x00,0x65,0x18,0x21,0x00,0x62,0x18,0x21,0x90,0x64,0x00,0x00,0x90,0x62,0x00,0x04, +-0xa2,0x20,0x00,0x15,0xa3,0x80,0x8b,0xd4,0x24,0x02,0x00,0x01,0x8f,0xbf,0x00,0x18, +-0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x0c,0x00,0x0c,0xcd, +-0x02,0x20,0x20,0x21,0x92,0x27,0x00,0x11,0x08,0x00,0x0d,0x7d,0x00,0x07,0x16,0x00, +-0x0c,0x00,0x0c,0x6e,0x02,0x20,0x20,0x21,0x86,0x23,0x00,0x0c,0x27,0x84,0x90,0x08, +-0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x44,0x20,0x21, +-0x90,0x85,0x00,0x07,0x27,0x83,0x90,0x10,0x00,0x43,0x10,0x21,0xa2,0x25,0x00,0x13, +-0x90,0x83,0x00,0x07,0x08,0x00,0x0d,0x95,0xa0,0x43,0x00,0x02,0x92,0x26,0x00,0x0a, +-0x08,0x00,0x0d,0x5e,0x30,0xc2,0x00,0xff,0x8e,0x22,0x00,0x24,0x00,0x00,0x00,0x00, +-0x10,0x50,0x00,0x07,0xa2,0x20,0x00,0x08,0x24,0x02,0x00,0x07,0xa2,0x22,0x00,0x0a, +-0x92,0x22,0x00,0x27,0xae,0x20,0x00,0x24,0x08,0x00,0x0d,0x51,0xa2,0x22,0x00,0x04, +-0x08,0x00,0x0d,0xaf,0x24,0x02,0x00,0x06,0x16,0x02,0xff,0x9b,0x3c,0x02,0xb0,0x05, +-0x8e,0x23,0x00,0x2c,0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x07,0xa2,0x24,0x00,0x08, +-0x24,0x02,0x00,0x03,0xa2,0x22,0x00,0x0a,0x92,0x22,0x00,0x2f,0xae,0x20,0x00,0x2c, +-0x08,0x00,0x0d,0x51,0xa2,0x22,0x00,0x06,0x08,0x00,0x0d,0xbe,0xa2,0x20,0x00,0x0a, +-0x8e,0x22,0x00,0x28,0x24,0x03,0x00,0x01,0x24,0x04,0x00,0x01,0x10,0x44,0x00,0x07, +-0xa2,0x23,0x00,0x08,0x24,0x02,0x00,0x05,0xa2,0x22,0x00,0x0a,0x92,0x22,0x00,0x2b, +-0xae,0x20,0x00,0x28,0x08,0x00,0x0d,0x51,0xa2,0x22,0x00,0x05,0x08,0x00,0x0d,0xca, +-0x24,0x02,0x00,0x04,0x12,0x02,0x00,0x12,0x2a,0x02,0x00,0x41,0x10,0x40,0x00,0x09, +-0x24,0x02,0x00,0x80,0x24,0x02,0x00,0x20,0x16,0x02,0xff,0x7b,0x3c,0x02,0xb0,0x05, +-0x24,0x02,0x00,0x12,0xa2,0x22,0x00,0x0a,0xa2,0x22,0x00,0x08,0x08,0x00,0x0d,0x51, +-0xae,0x20,0x00,0x3c,0x16,0x02,0xff,0x74,0x3c,0x02,0xb0,0x05,0x24,0x02,0x00,0x10, +-0xa2,0x22,0x00,0x0a,0xa2,0x22,0x00,0x08,0x08,0x00,0x0d,0x51,0xae,0x20,0x00,0x34, +-0x24,0x02,0x00,0x11,0xa2,0x22,0x00,0x0a,0xa2,0x22,0x00,0x08,0x08,0x00,0x0d,0x51, +-0xae,0x20,0x00,0x38,0x8e,0x24,0x00,0x30,0x24,0x02,0x00,0x03,0x24,0x03,0x00,0x01, +-0x10,0x83,0x00,0x07,0xa2,0x22,0x00,0x08,0x24,0x02,0x00,0x02,0xa2,0x22,0x00,0x0a, +-0x92,0x22,0x00,0x33,0xae,0x20,0x00,0x30,0x08,0x00,0x0d,0x51,0xa2,0x22,0x00,0x07, +-0x08,0x00,0x0d,0xf0,0xa2,0x24,0x00,0x0a,0x8f,0x84,0xb4,0x40,0xae,0x20,0x00,0x34, +-0x94,0x85,0x00,0x14,0x0c,0x00,0x1b,0x66,0x32,0x10,0x00,0xff,0x08,0x00,0x0d,0x42, +-0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x37,0xf4, +-0x34,0x63,0x00,0x20,0xac,0x62,0x00,0x00,0x80,0xa2,0x00,0x15,0x3c,0x06,0xb0,0x05, +-0x10,0x40,0x00,0x0a,0x34,0xc6,0x02,0x54,0x83,0x83,0x8b,0xd4,0x00,0x00,0x00,0x00, +-0xac,0x83,0x00,0x24,0x8c,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x42, +-0x30,0x42,0x00,0x01,0x03,0xe0,0x00,0x08,0xac,0x82,0x00,0x28,0x8c,0x82,0x00,0x2c, +-0x3c,0x06,0xb0,0x05,0x34,0xc6,0x04,0x50,0x00,0x02,0x18,0x43,0x30,0x63,0x00,0x01, +-0x10,0x40,0x00,0x04,0x30,0x45,0x00,0x01,0xac,0x83,0x00,0x28,0x03,0xe0,0x00,0x08, +-0xac,0x85,0x00,0x24,0x90,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff, +-0x30,0x43,0x00,0x02,0x30,0x42,0x00,0x01,0xac,0x83,0x00,0x28,0x03,0xe0,0x00,0x08, +-0xac,0x82,0x00,0x24,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xd8, +-0x34,0x63,0x00,0x20,0x24,0x42,0x38,0x84,0xac,0x62,0x00,0x00,0xaf,0xb1,0x00,0x1c, +-0xaf,0xbf,0x00,0x20,0xaf,0xb0,0x00,0x18,0x90,0xa6,0x00,0x0a,0x27,0x83,0xb4,0x00, +-0x00,0xa0,0x88,0x21,0x00,0x06,0x10,0x80,0x00,0x43,0x10,0x21,0x8c,0x50,0x00,0x00, +-0x80,0xa5,0x00,0x11,0x92,0x03,0x00,0x12,0x10,0xa0,0x00,0x04,0xa2,0x20,0x00,0x15, +-0x24,0x02,0x00,0x12,0x10,0xc2,0x00,0xda,0x00,0x00,0x00,0x00,0x82,0x22,0x00,0x12, +-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x67,0x00,0x00,0x00,0x00,0xa2,0x20,0x00,0x12, +-0xa2,0x00,0x00,0x19,0x86,0x23,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0xc0, +-0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x20,0x00,0x43,0x10,0x21, +-0xa0,0x40,0x00,0x00,0x92,0x03,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0xdf, +-0xa2,0x03,0x00,0x16,0x82,0x02,0x00,0x12,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x20, +-0x00,0x00,0x00,0x00,0x92,0x23,0x00,0x08,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x45, +-0x24,0x02,0x00,0x01,0xa2,0x20,0x00,0x04,0x92,0x08,0x00,0x04,0x00,0x00,0x00,0x00, +-0x15,0x00,0x00,0x1e,0x24,0x02,0x00,0x01,0x92,0x07,0x00,0x0a,0xa2,0x02,0x00,0x17, +-0x92,0x02,0x00,0x16,0x30,0xe3,0x00,0xff,0x30,0x42,0x00,0xe4,0x10,0x60,0x00,0x03, +-0xa2,0x02,0x00,0x16,0x34,0x42,0x00,0x01,0xa2,0x02,0x00,0x16,0x11,0x00,0x00,0x05, +-0x00,0x00,0x00,0x00,0x92,0x02,0x00,0x16,0x00,0x00,0x00,0x00,0x34,0x42,0x00,0x02, +-0xa2,0x02,0x00,0x16,0x92,0x02,0x00,0x17,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x08, +-0x00,0x00,0x00,0x00,0x96,0x02,0x00,0x06,0x00,0x00,0x00,0x00,0xa6,0x02,0x00,0x14, +-0x8f,0xbf,0x00,0x20,0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28, +-0x96,0x02,0x00,0x00,0x08,0x00,0x0e,0x6c,0xa6,0x02,0x00,0x14,0x92,0x07,0x00,0x0a, +-0x00,0x00,0x00,0x00,0x14,0xe0,0x00,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0x0e,0x58, +-0xa2,0x00,0x00,0x17,0x96,0x04,0x00,0x00,0x96,0x05,0x00,0x06,0x27,0x86,0x90,0x00, +-0x00,0x04,0x18,0xc0,0x00,0x64,0x18,0x21,0x00,0x05,0x10,0xc0,0x00,0x45,0x10,0x21, +-0x00,0x03,0x18,0x80,0x00,0x66,0x18,0x21,0x00,0x02,0x10,0x80,0x00,0x46,0x10,0x21, +-0x8c,0x66,0x00,0x08,0x8c,0x45,0x00,0x08,0x3c,0x03,0x80,0x00,0x00,0xc3,0x20,0x24, +-0x10,0x80,0x00,0x08,0x00,0xa3,0x10,0x24,0x10,0x40,0x00,0x04,0x00,0x00,0x18,0x21, +-0x10,0x80,0x00,0x02,0x24,0x03,0x00,0x01,0x00,0xa6,0x18,0x2b,0x08,0x00,0x0e,0x58, +-0xa2,0x03,0x00,0x17,0x10,0x40,0xff,0xfd,0x00,0xa6,0x18,0x2b,0x08,0x00,0x0e,0x8c, +-0x00,0x00,0x00,0x00,0x10,0x62,0x00,0x09,0x24,0x02,0x00,0x02,0x10,0x62,0x00,0x05, +-0x24,0x02,0x00,0x03,0x14,0x62,0xff,0xb8,0x00,0x00,0x00,0x00,0x08,0x00,0x0e,0x52, +-0xa2,0x20,0x00,0x07,0x08,0x00,0x0e,0x52,0xa2,0x20,0x00,0x06,0x08,0x00,0x0e,0x52, +-0xa2,0x20,0x00,0x05,0x82,0x22,0x00,0x10,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x69, +-0x2c,0x62,0x00,0x02,0x10,0x40,0x00,0x49,0x3c,0x02,0xb0,0x09,0x92,0x25,0x00,0x08, +-0x00,0x00,0x00,0x00,0x30,0xa6,0x00,0xff,0x2c,0xc2,0x00,0x04,0x10,0x40,0x00,0x3b, +-0x2c,0xc2,0x00,0x10,0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00, +-0x24,0x02,0x00,0x01,0x00,0xc2,0x10,0x04,0x00,0x02,0x10,0x27,0x00,0x62,0x18,0x24, +-0xa0,0x83,0x00,0x00,0x86,0x23,0x00,0x0c,0x96,0x26,0x00,0x0c,0x00,0x03,0x10,0xc0, +-0x00,0x43,0x10,0x21,0x00,0x02,0x28,0x80,0x27,0x83,0x90,0x04,0x00,0xa3,0x18,0x21, +-0x8c,0x64,0x00,0x18,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x04,0x00,0x00,0x00,0x00, +-0x30,0x42,0x00,0x10,0x10,0x40,0x00,0x18,0x24,0x07,0x00,0x01,0x93,0x82,0x8b,0x71, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x0a,0x24,0x05,0x00,0x24, +-0x00,0x06,0x2c,0x00,0x00,0x05,0x2c,0x03,0x0c,0x00,0x1b,0x66,0x02,0x00,0x20,0x21, +-0x92,0x02,0x00,0x16,0xa2,0x00,0x00,0x12,0x30,0x42,0x00,0xe7,0x08,0x00,0x0e,0x49, +-0xa2,0x02,0x00,0x16,0xf0,0xc5,0x00,0x06,0x00,0x00,0x28,0x12,0x27,0x82,0x90,0x00, +-0x00,0xa2,0x28,0x21,0x0c,0x00,0x01,0x49,0x3c,0x04,0x00,0x80,0x96,0x26,0x00,0x0c, +-0x08,0x00,0x0e,0xc9,0x00,0x06,0x2c,0x00,0x27,0x83,0x90,0x10,0x27,0x82,0x90,0x18, +-0x00,0xa2,0x10,0x21,0x00,0xa3,0x18,0x21,0x90,0x44,0x00,0x00,0x90,0x65,0x00,0x05, +-0x93,0x82,0x80,0x10,0x00,0x00,0x30,0x21,0x0c,0x00,0x21,0x9a,0xaf,0xa2,0x00,0x10, +-0x96,0x26,0x00,0x0c,0x08,0x00,0x0e,0xc3,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0xcd, +-0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x30,0xa5,0x00,0x0f, +-0x24,0x02,0x00,0x80,0x08,0x00,0x0e,0xb2,0x00,0xa2,0x10,0x07,0x86,0x26,0x00,0x0c, +-0x3c,0x03,0xb0,0x09,0x34,0x42,0x01,0x72,0x34,0x63,0x01,0x78,0x94,0x47,0x00,0x00, +-0x8c,0x65,0x00,0x00,0x00,0x06,0x10,0xc0,0x00,0x46,0x10,0x21,0x3c,0x04,0xb0,0x09, +-0xae,0x25,0x00,0x1c,0x34,0x84,0x01,0x7c,0x27,0x83,0x90,0x04,0x00,0x02,0x10,0x80, +-0x8c,0x85,0x00,0x00,0x00,0x43,0x10,0x21,0x8c,0x43,0x00,0x18,0xae,0x25,0x00,0x20, +-0xa6,0x27,0x00,0x18,0x8c,0x66,0x00,0x08,0x02,0x20,0x20,0x21,0x0c,0x00,0x0f,0x19, +-0x00,0x00,0x28,0x21,0x86,0x25,0x00,0x18,0x8e,0x26,0x00,0x1c,0x8e,0x27,0x00,0x20, +-0x02,0x20,0x20,0x21,0x0c,0x00,0x1c,0x68,0xaf,0xa2,0x00,0x10,0x08,0x00,0x0e,0x49, +-0xa2,0x02,0x00,0x12,0x92,0x22,0x00,0x08,0x08,0x00,0x0e,0x49,0xa2,0x22,0x00,0x09, +-0xa2,0x20,0x00,0x11,0x80,0x82,0x00,0x50,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x03, +-0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xd0,0xac,0x40,0x00,0x00,0x08,0x00,0x0e,0x49, +-0xa0,0x80,0x00,0x50,0x94,0x8a,0x00,0x0c,0x24,0x03,0x00,0x24,0x00,0x80,0x70,0x21, +-0x3c,0x02,0x80,0x00,0x3c,0x04,0xb0,0x03,0x24,0x42,0x3c,0x64,0xf1,0x43,0x00,0x06, +-0x34,0x84,0x00,0x20,0x00,0x00,0x18,0x12,0x00,0xa0,0x68,0x21,0xac,0x82,0x00,0x00, +-0x27,0x85,0x90,0x10,0x27,0x82,0x90,0x0f,0x27,0xbd,0xff,0xf8,0x00,0x62,0x60,0x21, +-0x00,0x65,0x58,0x21,0x00,0x00,0xc0,0x21,0x11,0xa0,0x00,0xcc,0x00,0x00,0x78,0x21, +-0x00,0x0a,0x1c,0x00,0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +-0x00,0x02,0x10,0x80,0x00,0x45,0x10,0x21,0x91,0x87,0x00,0x00,0x80,0x48,0x00,0x04, +-0x03,0xa0,0x60,0x21,0x00,0x0a,0x1c,0x00,0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0, +-0x00,0x43,0x10,0x21,0x00,0x02,0x48,0x80,0x27,0x83,0x90,0x04,0xa3,0xa7,0x00,0x00, +-0x01,0x23,0x18,0x21,0x8c,0x64,0x00,0x18,0x25,0x02,0xff,0xff,0x00,0x48,0x40,0x0b, +-0x8c,0x83,0x00,0x04,0x2d,0x05,0x00,0x07,0x24,0x02,0x00,0x06,0x30,0x63,0x00,0x08, +-0x14,0x60,0x00,0x35,0x00,0x45,0x40,0x0a,0x93,0xa7,0x00,0x00,0x27,0x82,0x90,0x18, +-0x01,0x22,0x10,0x21,0x30,0xe3,0x00,0xf0,0x38,0x63,0x00,0x50,0x30,0xe5,0x00,0xff, +-0x00,0x05,0x20,0x2b,0x00,0x03,0x18,0x2b,0x00,0x64,0x18,0x24,0x90,0x49,0x00,0x00, +-0x10,0x60,0x00,0x16,0x30,0xe4,0x00,0x0f,0x24,0x02,0x00,0x04,0x10,0xa2,0x00,0x9d, +-0x00,0x00,0x00,0x00,0x11,0xa0,0x00,0x3a,0x2c,0xa2,0x00,0x0c,0x10,0x40,0x00,0x02, +-0x24,0x84,0x00,0x0c,0x00,0xe0,0x20,0x21,0x30,0x84,0x00,0xff,0x00,0x04,0x10,0x40, +-0x27,0x83,0xbb,0x1c,0x00,0x44,0x10,0x21,0x00,0x43,0x10,0x21,0x90,0x47,0x00,0x00, +-0x00,0x00,0x00,0x00,0x2c,0xe3,0x00,0x0c,0xa3,0xa7,0x00,0x00,0x10,0x60,0x00,0x02, +-0x24,0xe2,0x00,0x04,0x00,0xe0,0x10,0x21,0xa3,0xa2,0x00,0x00,0x91,0x65,0x00,0x00, +-0x91,0x82,0x00,0x00,0x30,0xa3,0x00,0xff,0x00,0x62,0x10,0x2b,0x10,0x40,0x00,0x0e, +-0x2c,0x62,0x00,0x0c,0x14,0x40,0x00,0x03,0x00,0x60,0x20,0x21,0x30,0xa2,0x00,0x0f, +-0x24,0x44,0x00,0x0c,0x00,0x04,0x10,0x40,0x00,0x44,0x20,0x21,0x27,0x83,0xbb,0x1c, +-0x00,0x83,0x18,0x21,0x90,0x62,0x00,0x02,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x05, +-0x00,0x09,0x11,0x00,0xa1,0x85,0x00,0x00,0x93,0xa2,0x00,0x00,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x08,0x00,0x49,0x10,0x23,0x00,0x02,0x10,0x80,0x00,0x49,0x10,0x23, +-0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x21,0x27,0x83,0xb4,0xa8,0x00,0x43,0x10,0x21, +-0x90,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x83,0x00,0x0c,0x14,0x60,0x00,0x06, +-0x00,0x80,0x10,0x21,0x00,0x18,0x10,0x40,0x00,0x4f,0x10,0x21,0x00,0x02,0x11,0x00, +-0x00,0x82,0x10,0x21,0x24,0x42,0x00,0x04,0x08,0x00,0x0f,0x7a,0xa1,0x82,0x00,0x00, +-0x8f,0x8d,0x81,0x5c,0x00,0x00,0x00,0x00,0x01,0xa8,0x10,0x21,0x90,0x43,0x00,0x00, +-0x00,0x00,0x00,0x00,0x10,0x60,0xff,0xd1,0x00,0x00,0x28,0x21,0x00,0x06,0x74,0x82, +-0x30,0xe2,0x00,0xff,0x2c,0x42,0x00,0x0c,0x14,0x40,0x00,0x03,0x00,0xe0,0x10,0x21, +-0x30,0xe2,0x00,0x0f,0x24,0x42,0x00,0x0c,0x30,0x44,0x00,0xff,0xa3,0xa2,0x00,0x00, +-0x24,0x02,0x00,0x0c,0x10,0x82,0x00,0x0d,0x00,0x09,0x11,0x00,0x00,0x49,0x10,0x23, +-0x00,0x02,0x10,0x80,0x00,0x04,0x18,0x40,0x00,0x49,0x10,0x23,0x00,0x64,0x18,0x21, +-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x27,0x84,0xb4,0xa8,0x00,0x44,0x10,0x21, +-0x90,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xa7,0x00,0x00,0x00,0x0a,0x1c,0x00, +-0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80, +-0x27,0x83,0x90,0x04,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x18,0x00,0x00,0x00,0x00, +-0x8c,0x83,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x10,0x14,0x60,0x00,0x33, +-0x00,0x06,0x14,0x42,0x00,0x09,0x11,0x00,0x00,0x49,0x10,0x23,0x00,0x02,0x10,0x80, +-0x00,0x49,0x10,0x23,0x27,0x83,0xb5,0x78,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21, +-0x90,0x44,0x00,0x04,0x90,0x43,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x64,0xc0,0x24, +-0x93,0xa7,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0xe2,0x00,0x0f,0x10,0x40,0x00,0x0f, +-0x31,0xcf,0x00,0x01,0x00,0x0a,0x1c,0x00,0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0, +-0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x84,0x90,0x00,0x00,0x44,0x10,0x21, +-0x84,0x43,0x00,0x06,0x00,0x00,0x00,0x00,0x28,0x63,0x06,0x41,0x14,0x60,0x00,0x04, +-0x30,0xe2,0x00,0xff,0x24,0x07,0x00,0x0f,0xa3,0xa7,0x00,0x00,0x30,0xe2,0x00,0xff, +-0x2c,0x42,0x00,0x0c,0x14,0x40,0x00,0x06,0x00,0xe0,0x10,0x21,0x00,0x18,0x10,0x40, +-0x00,0x4f,0x10,0x21,0x00,0x02,0x11,0x00,0x00,0x47,0x10,0x21,0x24,0x42,0x00,0x04, +-0xa3,0xa2,0x00,0x00,0x00,0x40,0x38,0x21,0x01,0xa8,0x10,0x21,0x90,0x43,0x00,0x00, +-0x24,0xa4,0x00,0x01,0x30,0x85,0xff,0xff,0x00,0xa3,0x18,0x2b,0x14,0x60,0xff,0xad, +-0x30,0xe2,0x00,0xff,0x08,0x00,0x0f,0x67,0x00,0x00,0x00,0x00,0x08,0x00,0x0f,0xc8, +-0x30,0x58,0x00,0x01,0x81,0xc2,0x00,0x48,0x00,0x00,0x00,0x00,0x10,0x40,0xff,0x73, +-0x00,0x00,0x00,0x00,0x08,0x00,0x0f,0x55,0x00,0x00,0x00,0x00,0x00,0x0a,0x1c,0x00, +-0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80, +-0x00,0x45,0x10,0x21,0x80,0x48,0x00,0x05,0x91,0x67,0x00,0x00,0x08,0x00,0x0f,0x35, +-0x03,0xa0,0x58,0x21,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20, +-0x24,0x42,0x40,0x04,0x03,0xe0,0x00,0x08,0xac,0x62,0x00,0x00,0x27,0xbd,0xff,0xc0, +-0xaf,0xb7,0x00,0x34,0xaf,0xb6,0x00,0x30,0xaf,0xb5,0x00,0x2c,0xaf,0xb4,0x00,0x28, +-0xaf,0xb3,0x00,0x24,0xaf,0xb2,0x00,0x20,0xaf,0xbf,0x00,0x3c,0xaf,0xbe,0x00,0x38, +-0xaf,0xb1,0x00,0x1c,0xaf,0xb0,0x00,0x18,0x84,0x82,0x00,0x0c,0x27,0x93,0x90,0x04, +-0x3c,0x05,0xb0,0x03,0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21,0x00,0x03,0x18,0x80, +-0x00,0x73,0x10,0x21,0x8c,0x5e,0x00,0x18,0x3c,0x02,0x80,0x00,0x34,0xa5,0x00,0x20, +-0x24,0x42,0x40,0x1c,0xac,0xa2,0x00,0x00,0x8f,0xd0,0x00,0x08,0x27,0x95,0x90,0x10, +-0x00,0x75,0x18,0x21,0x00,0x00,0x28,0x21,0x02,0x00,0x30,0x21,0x90,0x71,0x00,0x00, +-0x0c,0x00,0x0f,0x19,0x00,0x80,0xb0,0x21,0x00,0x40,0x90,0x21,0x00,0x10,0x14,0x42, +-0x30,0x54,0x00,0x01,0x02,0x40,0x20,0x21,0x00,0x10,0x14,0x82,0x02,0x80,0x28,0x21, +-0x12,0x51,0x00,0x23,0x00,0x10,0xbf,0xc2,0x86,0xc3,0x00,0x0c,0x30,0x50,0x00,0x01, +-0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x55,0x10,0x21, +-0xa0,0x52,0x00,0x00,0x86,0xc3,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0xc0, +-0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x53,0x30,0x21,0x8c,0xc7,0x00,0x18, +-0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0x8c,0xe3,0x00,0x04,0x84,0x46,0x00,0x06, +-0x00,0x03,0x19,0x42,0x0c,0x00,0x08,0xe3,0x30,0x73,0x00,0x01,0x00,0x40,0x88,0x21, +-0x02,0x40,0x20,0x21,0x02,0x80,0x28,0x21,0x16,0xe0,0x00,0x10,0x02,0x00,0x30,0x21, +-0x86,0xc2,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21, +-0x00,0x03,0x18,0x80,0x27,0x82,0x90,0x08,0x00,0x62,0x18,0x21,0xa4,0x71,0x00,0x04, +-0x7b,0xbe,0x01,0xfc,0x7b,0xb6,0x01,0xbc,0x7b,0xb4,0x01,0x7c,0x7b,0xb2,0x01,0x3c, +-0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x40,0x86,0xc3,0x00,0x0c, +-0xaf,0xb3,0x00,0x10,0xaf,0xa0,0x00,0x14,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +-0x00,0x02,0x10,0x80,0x00,0x55,0x10,0x21,0x80,0x47,0x00,0x06,0x00,0x00,0x00,0x00, +-0x24,0xe7,0x00,0x02,0x00,0x07,0x17,0xc2,0x00,0xe2,0x38,0x21,0x00,0x07,0x38,0x43, +-0x00,0x07,0x38,0x40,0x0c,0x00,0x09,0x0a,0x03,0xc7,0x38,0x21,0x08,0x00,0x10,0x48, +-0x02,0x22,0x88,0x21,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xd0, +-0x34,0x63,0x00,0x20,0x24,0x42,0x41,0xa4,0xaf,0xb2,0x00,0x20,0xac,0x62,0x00,0x00, +-0xaf,0xbf,0x00,0x28,0xaf,0xb3,0x00,0x24,0xaf,0xb1,0x00,0x1c,0xaf,0xb0,0x00,0x18, +-0x3c,0x02,0xb0,0x03,0x90,0x83,0x00,0x0a,0x34,0x42,0x01,0x04,0x94,0x45,0x00,0x00, +-0x00,0x03,0x18,0x80,0x27,0x82,0xb4,0x00,0x00,0x62,0x18,0x21,0x30,0xa6,0xff,0xff, +-0x8c,0x71,0x00,0x00,0x80,0x85,0x00,0x12,0x30,0xc9,0x00,0xff,0x00,0x06,0x32,0x02, +-0xa4,0x86,0x00,0x44,0xa4,0x89,0x00,0x46,0x82,0x22,0x00,0x12,0x00,0x80,0x90,0x21, +-0x10,0xa0,0x00,0x1b,0xa0,0x80,0x00,0x15,0x00,0xc5,0x10,0x2a,0x10,0x40,0x00,0x14, +-0x00,0x00,0x00,0x00,0xa2,0x20,0x00,0x19,0x84,0x83,0x00,0x0c,0x00,0x00,0x00,0x00, +-0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x20, +-0x00,0x43,0x10,0x21,0xa0,0x40,0x00,0x00,0xa0,0x80,0x00,0x12,0x92,0x22,0x00,0x16, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xdf,0xa2,0x22,0x00,0x16,0x8f,0xbf,0x00,0x28, +-0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x30, +-0x0c,0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x97,0x00,0x00,0x00,0x00, +-0x28,0x42,0x00,0x02,0x10,0x40,0x01,0x76,0x00,0x00,0x28,0x21,0x94,0x87,0x00,0x0c, +-0x00,0x00,0x00,0x00,0x00,0xe0,0x10,0x21,0x00,0x02,0x14,0x00,0x00,0x02,0x14,0x03, +-0x00,0x07,0x24,0x00,0x00,0x04,0x24,0x03,0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21, +-0x00,0x04,0x28,0xc0,0x00,0xa4,0x28,0x21,0x27,0x82,0x90,0x20,0x00,0x03,0x18,0x80, +-0x00,0x62,0x18,0x21,0x00,0x05,0x28,0x80,0x27,0x82,0x90,0x08,0x00,0xa2,0x10,0x21, +-0x8c,0x68,0x00,0x00,0x80,0x44,0x00,0x06,0x27,0x82,0x90,0x10,0x00,0x08,0x1d,0x02, +-0x00,0xa2,0x28,0x21,0x38,0x84,0x00,0x00,0x30,0x63,0x00,0x01,0x01,0x24,0x30,0x0b, +-0x80,0xaa,0x00,0x04,0x80,0xa9,0x00,0x05,0x10,0x60,0x00,0x02,0x00,0x08,0x14,0x02, +-0x30,0x46,0x00,0x0f,0x15,0x20,0x00,0x28,0x01,0x49,0x10,0x21,0x15,0x40,0x00,0x11, +-0x30,0xe3,0xff,0xff,0x92,0x45,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xa8,0x00,0xff, +-0x2d,0x02,0x00,0x04,0x10,0x40,0x01,0x46,0x2d,0x02,0x00,0x10,0x3c,0x04,0xb0,0x05, +-0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x24,0x02,0x00,0x01,0x01,0x02,0x10,0x04, +-0x00,0x62,0x18,0x25,0xa0,0x83,0x00,0x00,0x96,0x47,0x00,0x0c,0x00,0x00,0x00,0x00, +-0x30,0xe3,0xff,0xff,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x27,0x84,0x90,0x10, +-0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x21,0x80,0x45,0x00,0x06,0x00,0x03,0x1a,0x00, +-0x3c,0x04,0xb0,0x00,0x00,0x65,0x18,0x21,0x00,0x64,0x20,0x21,0x94,0x82,0x00,0x00, +-0x82,0x43,0x00,0x10,0x00,0x02,0x14,0x00,0x14,0x60,0x00,0x06,0x00,0x02,0x3c,0x03, +-0x30,0xe2,0x00,0x04,0x14,0x40,0x00,0x04,0x01,0x49,0x10,0x21,0x34,0xe2,0x08,0x00, +-0xa4,0x82,0x00,0x00,0x01,0x49,0x10,0x21,0x00,0x02,0x16,0x00,0x00,0x02,0x16,0x03, +-0x00,0x46,0x10,0x2a,0x10,0x40,0x00,0x7c,0x00,0x00,0x00,0x00,0x82,0x42,0x00,0x10, +-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0e,0x00,0x00,0x00,0x00,0x86,0x43,0x00,0x0c, +-0x25,0x44,0x00,0x01,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80, +-0x27,0x83,0x90,0x10,0x00,0x43,0x10,0x21,0xa0,0x44,0x00,0x04,0x92,0x23,0x00,0x16, +-0x02,0x40,0x20,0x21,0x30,0x63,0x00,0xfb,0x08,0x00,0x10,0x9c,0xa2,0x23,0x00,0x16, +-0x86,0x43,0x00,0x0c,0x25,0x24,0x00,0x01,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +-0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x10,0x00,0x43,0x10,0x21,0xa0,0x44,0x00,0x05, +-0x86,0x45,0x00,0x0c,0x0c,0x00,0x1e,0xea,0x02,0x20,0x20,0x21,0x10,0x40,0x00,0x5a, +-0x00,0x00,0x00,0x00,0x92,0x45,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xa6,0x00,0xff, +-0x2c,0xc2,0x00,0x04,0x10,0x40,0x00,0x4c,0x2c,0xc2,0x00,0x10,0x3c,0x04,0xb0,0x05, +-0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x24,0x02,0x00,0x01,0x00,0xc2,0x10,0x04, +-0x00,0x02,0x10,0x27,0x00,0x62,0x18,0x24,0xa0,0x83,0x00,0x00,0x92,0x45,0x00,0x08, +-0x00,0x00,0x00,0x00,0x30,0xa5,0x00,0xff,0x14,0xa0,0x00,0x33,0x24,0x02,0x00,0x01, +-0xa2,0x40,0x00,0x04,0x92,0x22,0x00,0x04,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x0c, +-0x24,0x02,0x00,0x01,0xa2,0x22,0x00,0x17,0x92,0x22,0x00,0x17,0x00,0x00,0x00,0x00, +-0x10,0x40,0x00,0x04,0x00,0x00,0x00,0x00,0x96,0x22,0x00,0x06,0x08,0x00,0x10,0x97, +-0xa6,0x22,0x00,0x14,0x96,0x22,0x00,0x00,0x08,0x00,0x10,0x97,0xa6,0x22,0x00,0x14, +-0x92,0x22,0x00,0x0a,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x03,0x00,0x00,0x00,0x00, +-0x08,0x00,0x11,0x26,0xa2,0x20,0x00,0x17,0x96,0x24,0x00,0x00,0x96,0x25,0x00,0x06, +-0x27,0x86,0x90,0x00,0x00,0x04,0x18,0xc0,0x00,0x64,0x18,0x21,0x00,0x05,0x10,0xc0, +-0x00,0x45,0x10,0x21,0x00,0x03,0x18,0x80,0x00,0x66,0x18,0x21,0x00,0x02,0x10,0x80, +-0x00,0x46,0x10,0x21,0x8c,0x65,0x00,0x08,0x8c,0x44,0x00,0x08,0x3c,0x03,0x80,0x00, +-0x00,0xa3,0x30,0x24,0x10,0xc0,0x00,0x08,0x00,0x83,0x10,0x24,0x10,0x40,0x00,0x04, +-0x00,0x00,0x18,0x21,0x10,0xc0,0x00,0x02,0x24,0x03,0x00,0x01,0x00,0x85,0x18,0x2b, +-0x08,0x00,0x11,0x26,0xa2,0x23,0x00,0x17,0x10,0x40,0xff,0xfd,0x00,0x85,0x18,0x2b, +-0x08,0x00,0x11,0x49,0x00,0x00,0x00,0x00,0x10,0xa2,0x00,0x09,0x24,0x02,0x00,0x02, +-0x10,0xa2,0x00,0x05,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xca,0x00,0x00,0x00,0x00, +-0x08,0x00,0x11,0x21,0xa2,0x40,0x00,0x07,0x08,0x00,0x11,0x21,0xa2,0x40,0x00,0x06, +-0x08,0x00,0x11,0x21,0xa2,0x40,0x00,0x05,0x14,0x40,0xff,0xbe,0x3c,0x04,0xb0,0x05, +-0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x30,0xa5,0x00,0x0f,0x24,0x02,0x00,0x80, +-0x08,0x00,0x11,0x18,0x00,0xa2,0x10,0x07,0x0c,0x00,0x10,0x07,0x02,0x40,0x20,0x21, +-0x08,0x00,0x10,0x97,0x00,0x00,0x00,0x00,0x92,0x45,0x00,0x08,0x00,0x00,0x00,0x00, +-0x30,0xa6,0x00,0xff,0x2c,0xc2,0x00,0x04,0x10,0x40,0x00,0x99,0x2c,0xc2,0x00,0x10, +-0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x24,0x02,0x00,0x01, +-0x00,0xc2,0x10,0x04,0x00,0x02,0x10,0x27,0x00,0x62,0x18,0x24,0xa0,0x83,0x00,0x00, +-0x92,0x45,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xa5,0x00,0xff,0x14,0xa0,0x00,0x80, +-0x24,0x02,0x00,0x01,0xa2,0x40,0x00,0x04,0x86,0x43,0x00,0x0c,0x27,0x93,0x90,0x04, +-0x96,0x47,0x00,0x0c,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x28,0x80, +-0x00,0xb3,0x18,0x21,0x8c,0x64,0x00,0x18,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x04, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x10,0x10,0x40,0x00,0x64,0x00,0x00,0x30,0x21, +-0x00,0x07,0x1c,0x00,0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +-0x00,0x02,0x10,0x80,0x00,0x53,0x10,0x21,0x8c,0x43,0x00,0x18,0x93,0x82,0x8b,0x71, +-0x8c,0x64,0x00,0x04,0x30,0x42,0x00,0x01,0x00,0x04,0x21,0x42,0x14,0x40,0x00,0x4d, +-0x30,0x90,0x00,0x01,0x00,0x07,0x2c,0x00,0x00,0x05,0x2c,0x03,0x0c,0x00,0x1b,0x66, +-0x02,0x20,0x20,0x21,0x96,0x26,0x00,0x06,0x12,0x00,0x00,0x14,0x30,0xc5,0xff,0xff, +-0x02,0x60,0x90,0x21,0x00,0x05,0x10,0xc0,0x00,0x45,0x10,0x21,0x00,0x02,0x10,0x80, +-0x00,0x52,0x18,0x21,0x92,0x22,0x00,0x0a,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0b, +-0x02,0x20,0x20,0x21,0x8c,0x63,0x00,0x18,0x00,0x00,0x00,0x00,0x8c,0x62,0x00,0x04, +-0x00,0x00,0x00,0x00,0x00,0x02,0x11,0x42,0x0c,0x00,0x1b,0x66,0x30,0x50,0x00,0x01, +-0x96,0x26,0x00,0x06,0x16,0x00,0xff,0xef,0x30,0xc5,0xff,0xff,0x92,0x22,0x00,0x04, +-0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x0d,0x24,0x02,0x00,0x01,0xa2,0x22,0x00,0x17, +-0x92,0x22,0x00,0x17,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x05,0x00,0x00,0x00,0x00, +-0xa6,0x26,0x00,0x14,0x92,0x22,0x00,0x16,0x08,0x00,0x10,0x96,0x30,0x42,0x00,0xc3, +-0x96,0x22,0x00,0x00,0x08,0x00,0x11,0xbd,0xa6,0x22,0x00,0x14,0x92,0x22,0x00,0x0a, +-0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0x11,0xb8, +-0xa2,0x20,0x00,0x17,0x96,0x24,0x00,0x00,0x30,0xc5,0xff,0xff,0x00,0x05,0x18,0xc0, +-0x00,0x04,0x10,0xc0,0x00,0x44,0x10,0x21,0x00,0x65,0x18,0x21,0x27,0x84,0x90,0x00, +-0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x21,0x00,0x03,0x18,0x80,0x8c,0x45,0x00,0x08, +-0x00,0x64,0x18,0x21,0x8c,0x64,0x00,0x08,0x3c,0x02,0x80,0x00,0x00,0xa2,0x38,0x24, +-0x10,0xe0,0x00,0x08,0x00,0x82,0x10,0x24,0x10,0x40,0x00,0x04,0x00,0x00,0x18,0x21, +-0x10,0xe0,0x00,0x02,0x24,0x03,0x00,0x01,0x00,0x85,0x18,0x2b,0x08,0x00,0x11,0xb8, +-0xa2,0x23,0x00,0x17,0x10,0x40,0xff,0xfd,0x00,0x85,0x18,0x2b,0x08,0x00,0x11,0xdc, +-0x00,0x00,0x00,0x00,0x24,0x05,0x00,0x24,0xf0,0xe5,0x00,0x06,0x00,0x00,0x28,0x12, +-0x27,0x82,0x90,0x00,0x00,0xa2,0x28,0x21,0x0c,0x00,0x01,0x49,0x00,0x00,0x20,0x21, +-0x96,0x47,0x00,0x0c,0x08,0x00,0x11,0x9a,0x00,0x07,0x2c,0x00,0x27,0x83,0x90,0x10, +-0x27,0x82,0x90,0x18,0x00,0xa2,0x10,0x21,0x00,0xa3,0x18,0x21,0x90,0x44,0x00,0x00, +-0x90,0x65,0x00,0x05,0x93,0x82,0x80,0x10,0x24,0x07,0x00,0x01,0x0c,0x00,0x21,0x9a, +-0xaf,0xa2,0x00,0x10,0x96,0x47,0x00,0x0c,0x08,0x00,0x11,0x8d,0x00,0x07,0x1c,0x00, +-0x10,0xa2,0x00,0x09,0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x05,0x24,0x02,0x00,0x03, +-0x14,0xa2,0xff,0x7d,0x00,0x00,0x00,0x00,0x08,0x00,0x11,0x7e,0xa2,0x40,0x00,0x07, +-0x08,0x00,0x11,0x7e,0xa2,0x40,0x00,0x06,0x08,0x00,0x11,0x7e,0xa2,0x40,0x00,0x05, +-0x14,0x40,0xff,0x71,0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00, +-0x30,0xa5,0x00,0x0f,0x24,0x02,0x00,0x80,0x08,0x00,0x11,0x75,0x00,0xa2,0x10,0x07, +-0x14,0x40,0xfe,0xc3,0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00, +-0x30,0xa5,0x00,0x0f,0x24,0x02,0x00,0x80,0x08,0x00,0x10,0xd0,0x00,0xa2,0x10,0x07, +-0x84,0x83,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21, +-0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x04,0x00,0x43,0x10,0x21,0x8c,0x47,0x00,0x18, +-0x00,0x00,0x00,0x00,0x8c,0xe6,0x00,0x08,0x0c,0x00,0x0f,0x19,0x00,0x00,0x00,0x00, +-0x02,0x40,0x20,0x21,0x00,0x00,0x28,0x21,0x00,0x00,0x30,0x21,0x00,0x00,0x38,0x21, +-0x0c,0x00,0x1c,0x68,0xaf,0xa2,0x00,0x10,0x00,0x02,0x1e,0x00,0x14,0x60,0xfe,0x6b, +-0xa2,0x22,0x00,0x12,0x92,0x43,0x00,0x08,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x40, +-0x24,0x02,0x00,0x01,0xa2,0x40,0x00,0x04,0x92,0x28,0x00,0x04,0x00,0x00,0x00,0x00, +-0x15,0x00,0x00,0x19,0x24,0x02,0x00,0x01,0x92,0x27,0x00,0x0a,0xa2,0x22,0x00,0x17, +-0x92,0x22,0x00,0x17,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x10,0x00,0x00,0x00,0x00, +-0x96,0x22,0x00,0x06,0x00,0x00,0x00,0x00,0xa6,0x22,0x00,0x14,0x92,0x22,0x00,0x16, +-0x30,0xe3,0x00,0xff,0x30,0x42,0x00,0xc0,0x10,0x60,0x00,0x03,0xa2,0x22,0x00,0x16, +-0x34,0x42,0x00,0x01,0xa2,0x22,0x00,0x16,0x11,0x00,0xfe,0x50,0x00,0x00,0x00,0x00, +-0x92,0x22,0x00,0x16,0x08,0x00,0x10,0x96,0x34,0x42,0x00,0x02,0x96,0x22,0x00,0x00, +-0x08,0x00,0x12,0x3f,0xa6,0x22,0x00,0x14,0x92,0x27,0x00,0x0a,0x00,0x00,0x00,0x00, +-0x14,0xe0,0x00,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0x12,0x38,0xa2,0x20,0x00,0x17, +-0x96,0x24,0x00,0x00,0x96,0x25,0x00,0x06,0x27,0x86,0x90,0x00,0x00,0x04,0x18,0xc0, +-0x00,0x64,0x18,0x21,0x00,0x05,0x10,0xc0,0x00,0x45,0x10,0x21,0x00,0x03,0x18,0x80, +-0x00,0x66,0x18,0x21,0x00,0x02,0x10,0x80,0x00,0x46,0x10,0x21,0x8c,0x65,0x00,0x08, +-0x8c,0x44,0x00,0x08,0x3c,0x03,0x80,0x00,0x00,0xa3,0x30,0x24,0x10,0xc0,0x00,0x08, +-0x00,0x83,0x10,0x24,0x10,0x40,0x00,0x04,0x00,0x00,0x18,0x21,0x10,0xc0,0x00,0x02, +-0x24,0x03,0x00,0x01,0x00,0x85,0x18,0x2b,0x08,0x00,0x12,0x38,0xa2,0x23,0x00,0x17, +-0x10,0x40,0xff,0xfd,0x00,0x85,0x18,0x2b,0x08,0x00,0x12,0x67,0x00,0x00,0x00,0x00, +-0x10,0x62,0x00,0x09,0x24,0x02,0x00,0x02,0x10,0x62,0x00,0x05,0x24,0x02,0x00,0x03, +-0x14,0x62,0xff,0xbd,0x00,0x00,0x00,0x00,0x08,0x00,0x12,0x32,0xa2,0x40,0x00,0x07, +-0x08,0x00,0x12,0x32,0xa2,0x40,0x00,0x06,0x08,0x00,0x12,0x32,0xa2,0x40,0x00,0x05, +-0x3c,0x02,0x80,0x00,0x00,0x82,0x30,0x24,0x10,0xc0,0x00,0x08,0x00,0xa2,0x18,0x24, +-0x10,0x60,0x00,0x04,0x00,0x00,0x10,0x21,0x10,0xc0,0x00,0x02,0x24,0x02,0x00,0x01, +-0x00,0xa4,0x10,0x2b,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x10,0x60,0xff,0xfd, +-0x00,0xa4,0x10,0x2b,0x08,0x00,0x12,0x82,0x00,0x00,0x00,0x00,0x30,0x82,0xff,0xff, +-0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21,0x27,0x84,0x90,0x10,0x00,0x03,0x18,0x80, +-0x00,0x64,0x18,0x21,0x80,0x66,0x00,0x06,0x00,0x02,0x12,0x00,0x3c,0x03,0xb0,0x00, +-0x00,0x46,0x10,0x21,0x00,0x45,0x10,0x21,0x03,0xe0,0x00,0x08,0x00,0x43,0x10,0x21, +-0x27,0xbd,0xff,0xe0,0x30,0x82,0x00,0x7c,0x30,0x84,0xff,0x00,0xaf,0xbf,0x00,0x1c, +-0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0x14,0x40,0x00,0x41, +-0x00,0x04,0x22,0x03,0x24,0x02,0x00,0x04,0x3c,0x10,0xb0,0x03,0x8e,0x10,0x00,0x00, +-0x10,0x82,0x00,0x32,0x24,0x02,0x00,0x08,0x10,0x82,0x00,0x03,0x32,0x02,0x00,0x20, +-0x08,0x00,0x12,0xa8,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x17,0x3c,0x02,0xb0,0x06, +-0x34,0x42,0x80,0x24,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x67,0x00,0xff, +-0x10,0xe0,0x00,0x23,0x00,0x00,0x88,0x21,0x8f,0x85,0x8f,0xe0,0x00,0x40,0x30,0x21, +-0x94,0xa2,0x00,0x08,0x8c,0xc3,0x00,0x00,0x26,0x31,0x00,0x01,0x24,0x42,0x00,0x02, +-0x30,0x42,0x01,0xff,0x34,0x63,0x01,0x00,0x02,0x27,0x20,0x2a,0xa4,0xa2,0x00,0x08, +-0x14,0x80,0xff,0xf7,0xac,0xc3,0x00,0x00,0x84,0xa3,0x00,0x08,0x3c,0x02,0xb0,0x03, +-0x34,0x42,0x00,0x30,0xac,0x43,0x00,0x00,0x27,0x92,0xb4,0x00,0x24,0x11,0x00,0x12, +-0x8e,0x44,0x00,0x00,0x26,0x31,0xff,0xff,0x90,0x82,0x00,0x10,0x00,0x00,0x00,0x00, +-0x10,0x40,0x00,0x03,0x26,0x52,0x00,0x04,0x0c,0x00,0x18,0xd0,0x00,0x00,0x00,0x00, +-0x06,0x21,0xff,0xf7,0x24,0x02,0xff,0xdf,0x02,0x02,0x80,0x24,0x3c,0x01,0xb0,0x03, +-0x0c,0x00,0x13,0x1c,0xac,0x30,0x00,0x00,0x08,0x00,0x12,0xa8,0x00,0x00,0x00,0x00, +-0x8f,0x85,0x8f,0xe0,0x08,0x00,0x12,0xbe,0x00,0x00,0x00,0x00,0x24,0x02,0xff,0x95, +-0x3c,0x03,0xb0,0x03,0x02,0x02,0x80,0x24,0x34,0x63,0x00,0x30,0x3c,0x01,0xb0,0x03, +-0xac,0x30,0x00,0x00,0x0c,0x00,0x12,0xe5,0xac,0x60,0x00,0x00,0x08,0x00,0x12,0xa8, +-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x50,0x08,0x00,0x12,0xa8, +-0xac,0x46,0x00,0x00,0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4b,0x94,0x3c,0x0b,0xb0,0x03, +-0xad,0x6a,0x00,0x20,0x3c,0x08,0x80,0x01,0x25,0x08,0x00,0x00,0x3c,0x09,0x80,0x01, +-0x25,0x29,0x03,0x50,0x11,0x09,0x00,0x10,0x00,0x00,0x00,0x00,0x3c,0x0a,0x80,0x00, +-0x25,0x4a,0x4b,0xbc,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20,0x3c,0x08,0xb0,0x06, +-0x35,0x08,0x80,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8d,0x09,0x00,0x00, +-0x00,0x00,0x00,0x00,0x31,0x29,0x00,0x01,0x00,0x00,0x00,0x00,0x24,0x01,0x00,0x01, +-0x15,0x21,0xff,0xf2,0x00,0x00,0x00,0x00,0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4b,0xf8, +-0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20,0x3c,0x02,0xb0,0x03,0x8c,0x43,0x00,0x00, +-0x00,0x00,0x00,0x00,0x34,0x63,0x00,0x40,0x00,0x00,0x00,0x00,0xac,0x43,0x00,0x00, +-0x00,0x00,0x00,0x00,0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4c,0x24,0x3c,0x0b,0xb0,0x03, +-0xad,0x6a,0x00,0x20,0x3c,0x02,0x80,0x01,0x24,0x42,0x00,0x00,0x3c,0x03,0x80,0x01, +-0x24,0x63,0x03,0x50,0x3c,0x04,0xb0,0x00,0x8c,0x85,0x00,0x00,0x00,0x00,0x00,0x00, +-0xac,0x45,0x00,0x00,0x24,0x42,0x00,0x04,0x24,0x84,0x00,0x04,0x00,0x43,0x08,0x2a, +-0x14,0x20,0xff,0xf9,0x00,0x00,0x00,0x00,0x0c,0x00,0x13,0x1c,0x00,0x00,0x00,0x00, +-0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4c,0x70,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20, +-0x3c,0x02,0x80,0x01,0x24,0x42,0x03,0x50,0x3c,0x03,0x80,0x01,0x24,0x63,0x3f,0x24, +-0xac,0x40,0x00,0x00,0xac,0x40,0x00,0x04,0xac,0x40,0x00,0x08,0xac,0x40,0x00,0x0c, +-0x24,0x42,0x00,0x10,0x00,0x43,0x08,0x2a,0x14,0x20,0xff,0xf9,0x00,0x00,0x00,0x00, +-0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4c,0xb0,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20, +-0x3c,0x1c,0x80,0x01,0x27,0x9c,0x7f,0xf0,0x27,0x9d,0x8b,0xe0,0x00,0x00,0x00,0x00, +-0x27,0x9d,0x8f,0xc8,0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4c,0xd4,0x3c,0x0b,0xb0,0x03, +-0xad,0x6a,0x00,0x20,0x40,0x80,0x68,0x00,0x40,0x08,0x60,0x00,0x00,0x00,0x00,0x00, +-0x35,0x08,0xff,0x01,0x40,0x88,0x60,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x15,0x62, +-0x00,0x00,0x00,0x00,0x24,0x84,0xf8,0x00,0x30,0x87,0x00,0x03,0x00,0x04,0x30,0x40, +-0x00,0xc7,0x20,0x23,0x3c,0x02,0xb0,0x0a,0x27,0xbd,0xff,0xe0,0x24,0x03,0xff,0xff, +-0x00,0x82,0x20,0x21,0xaf,0xb1,0x00,0x14,0xac,0x83,0x10,0x00,0xaf,0xbf,0x00,0x18, +-0xaf,0xb0,0x00,0x10,0x00,0xa0,0x88,0x21,0x24,0x03,0x00,0x01,0x8c,0x82,0x10,0x00, +-0x00,0x00,0x00,0x00,0x14,0x43,0xff,0xfd,0x00,0xc7,0x10,0x23,0x3c,0x03,0xb0,0x0a, +-0x00,0x43,0x10,0x21,0x8c,0x50,0x00,0x00,0x0c,0x00,0x13,0x99,0x02,0x20,0x20,0x21, +-0x02,0x11,0x80,0x24,0x00,0x50,0x80,0x06,0x02,0x00,0x10,0x21,0x8f,0xbf,0x00,0x18, +-0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x27,0xbd,0xff,0xd8, +-0xaf,0xb2,0x00,0x18,0x00,0xa0,0x90,0x21,0x24,0x05,0xff,0xff,0xaf,0xb3,0x00,0x1c, +-0xaf,0xbf,0x00,0x20,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0x00,0xc0,0x98,0x21, +-0x12,0x45,0x00,0x23,0x24,0x84,0xf8,0x00,0x30,0x83,0x00,0x03,0x00,0x04,0x10,0x40, +-0x00,0x40,0x88,0x21,0x00,0x60,0x20,0x21,0x00,0x43,0x10,0x23,0x3c,0x03,0xb0,0x0a, +-0x00,0x43,0x10,0x21,0xac,0x45,0x10,0x00,0x00,0x40,0x18,0x21,0x24,0x05,0x00,0x01, +-0x8c,0x62,0x10,0x00,0x00,0x00,0x00,0x00,0x14,0x45,0xff,0xfd,0x3c,0x02,0xb0,0x0a, +-0x02,0x24,0x88,0x23,0x02,0x22,0x88,0x21,0x8e,0x30,0x00,0x00,0x0c,0x00,0x13,0x99, +-0x02,0x40,0x20,0x21,0x00,0x12,0x18,0x27,0x02,0x03,0x80,0x24,0x00,0x53,0x10,0x04, +-0x02,0x02,0x80,0x25,0xae,0x30,0x00,0x00,0x24,0x03,0x00,0x01,0x8e,0x22,0x10,0x00, +-0x00,0x00,0x00,0x00,0x14,0x43,0xff,0xfd,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x20, +-0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28, +-0x30,0x82,0x00,0x03,0x00,0x04,0x18,0x40,0x00,0x62,0x18,0x23,0x3c,0x04,0xb0,0x0a, +-0x00,0x64,0x18,0x21,0xac,0x66,0x00,0x00,0x24,0x04,0x00,0x01,0x8c,0x62,0x10,0x00, +-0x00,0x00,0x00,0x00,0x14,0x44,0xff,0xfd,0x00,0x00,0x00,0x00,0x08,0x00,0x13,0x87, +-0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x21,0x00,0x64,0x10,0x06,0x30,0x42,0x00,0x01, +-0x14,0x40,0x00,0x05,0x00,0x00,0x00,0x00,0x24,0x63,0x00,0x01,0x2c,0x62,0x00,0x20, +-0x14,0x40,0xff,0xf9,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x60,0x10,0x21, +-0x27,0xbd,0xff,0xe0,0x3c,0x03,0xb0,0x05,0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14, +-0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x1c,0x00,0x80,0x90,0x21,0x00,0xa0,0x80,0x21, +-0x00,0xc0,0x88,0x21,0x34,0x63,0x02,0x2e,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +-0x30,0x42,0x00,0x01,0x14,0x40,0xff,0xfc,0x24,0x04,0x08,0x24,0x3c,0x05,0x00,0xc0, +-0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x03,0x24,0x04,0x08,0x34,0x3c,0x05,0x00,0xc0, +-0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x03,0x3c,0x02,0xc0,0x00,0x00,0x10,0x1c,0x00, +-0x34,0x42,0x04,0x00,0x3c,0x04,0xb0,0x05,0x3c,0x05,0xb0,0x05,0x24,0x63,0x16,0x09, +-0x02,0x22,0x10,0x21,0x34,0x84,0x04,0x20,0x34,0xa5,0x04,0x24,0x3c,0x06,0xb0,0x05, +-0xac,0x83,0x00,0x00,0x24,0x07,0x00,0x01,0xac,0xa2,0x00,0x00,0x34,0xc6,0x02,0x28, +-0x24,0x02,0x00,0x20,0xae,0x47,0x00,0x3c,0x24,0x04,0x08,0x24,0xa0,0xc2,0x00,0x00, +-0x3c,0x05,0x00,0xc0,0xa2,0x47,0x00,0x11,0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x01, +-0x24,0x04,0x08,0x34,0x3c,0x05,0x00,0xc0,0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x01, +-0x8f,0xbf,0x00,0x1c,0x8f,0xb2,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x20,0x24,0x02,0x00,0x06,0xac,0x82,0x00,0x0c,0xa0,0x80,0x00,0x50, +-0xac,0x80,0x00,0x00,0xac,0x80,0x00,0x04,0xac,0x80,0x00,0x08,0xac,0x80,0x00,0x14, +-0xac,0x80,0x00,0x18,0xac,0x80,0x00,0x1c,0xa4,0x80,0x00,0x20,0xac,0x80,0x00,0x24, +-0xac,0x80,0x00,0x28,0xac,0x80,0x00,0x2c,0xa0,0x80,0x00,0x30,0xa0,0x80,0x00,0x31, +-0xac,0x80,0x00,0x34,0xac,0x80,0x00,0x38,0xa0,0x80,0x00,0x3c,0xac,0x82,0x00,0x10, +-0xa0,0x80,0x00,0x44,0xac,0x80,0x00,0x48,0x03,0xe0,0x00,0x08,0xac,0x80,0x00,0x4c, +-0x3c,0x04,0xb0,0x06,0x34,0x84,0x80,0x00,0x8c,0x83,0x00,0x00,0x3c,0x02,0x12,0x00, +-0x3c,0x05,0xb0,0x03,0x00,0x62,0x18,0x25,0x34,0xa5,0x00,0x8b,0x24,0x02,0xff,0x80, +-0xac,0x83,0x00,0x00,0x03,0xe0,0x00,0x08,0xa0,0xa2,0x00,0x00,0x3c,0x04,0xb0,0x03, +-0x34,0x84,0x00,0x0b,0x24,0x02,0x00,0x22,0x3c,0x05,0xb0,0x01,0x3c,0x06,0x45,0x67, +-0x3c,0x0a,0xb0,0x09,0xa0,0x82,0x00,0x00,0x34,0xa5,0x00,0x04,0x34,0xc6,0x89,0xaa, +-0x35,0x4a,0x00,0x04,0x24,0x02,0x01,0x23,0x3c,0x0b,0xb0,0x09,0x3c,0x07,0x01,0x23, +-0x3c,0x0c,0xb0,0x09,0x3c,0x01,0xb0,0x01,0xac,0x20,0x00,0x00,0x27,0xbd,0xff,0xe0, +-0xac,0xa0,0x00,0x00,0x35,0x6b,0x00,0x08,0x3c,0x01,0xb0,0x09,0xac,0x26,0x00,0x00, +-0x34,0xe7,0x45,0x66,0xa5,0x42,0x00,0x00,0x35,0x8c,0x00,0x0c,0x24,0x02,0xcd,0xef, +-0x3c,0x0d,0xb0,0x09,0x3c,0x08,0xcd,0xef,0x3c,0x0e,0xb0,0x09,0xad,0x67,0x00,0x00, +-0xaf,0xb7,0x00,0x1c,0xa5,0x82,0x00,0x00,0xaf,0xb6,0x00,0x18,0xaf,0xb5,0x00,0x14, +-0xaf,0xb4,0x00,0x10,0xaf,0xb3,0x00,0x0c,0xaf,0xb2,0x00,0x08,0xaf,0xb1,0x00,0x04, +-0xaf,0xb0,0x00,0x00,0x35,0xad,0x00,0x10,0x35,0x08,0x01,0x22,0x35,0xce,0x00,0x14, +-0x24,0x02,0x89,0xab,0x3c,0x0f,0xb0,0x09,0x3c,0x09,0x89,0xab,0x3c,0x10,0xb0,0x09, +-0x3c,0x11,0xb0,0x09,0x3c,0x12,0xb0,0x09,0x3c,0x13,0xb0,0x09,0x3c,0x14,0xb0,0x09, +-0x3c,0x15,0xb0,0x09,0x3c,0x16,0xb0,0x09,0x3c,0x17,0xb0,0x09,0xad,0xa8,0x00,0x00, +-0x24,0x03,0xff,0xff,0xa5,0xc2,0x00,0x00,0x35,0xef,0x00,0x18,0x35,0x29,0xcd,0xee, +-0x36,0x10,0x00,0x1c,0x36,0x31,0x00,0x20,0x36,0x52,0x00,0x24,0x36,0x73,0x00,0x28, +-0x36,0x94,0x00,0x2c,0x36,0xb5,0x00,0x30,0x36,0xd6,0x00,0x34,0x36,0xf7,0x00,0x38, +-0x24,0x02,0x45,0x67,0xad,0xe9,0x00,0x00,0xa6,0x02,0x00,0x00,0xae,0x23,0x00,0x00, +-0x8f,0xb0,0x00,0x00,0xa6,0x43,0x00,0x00,0x8f,0xb1,0x00,0x04,0xae,0x63,0x00,0x00, +-0x8f,0xb2,0x00,0x08,0xa6,0x83,0x00,0x00,0x8f,0xb3,0x00,0x0c,0xae,0xa3,0x00,0x00, +-0x8f,0xb4,0x00,0x10,0xa6,0xc3,0x00,0x00,0x8f,0xb5,0x00,0x14,0xae,0xe3,0x00,0x00, +-0x7b,0xb6,0x00,0xfc,0x3c,0x18,0xb0,0x09,0x37,0x18,0x00,0x3c,0xa7,0x03,0x00,0x00, +-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00, +-0x34,0x63,0x00,0x20,0x24,0x42,0x51,0x48,0xac,0x62,0x00,0x00,0x8c,0x83,0x00,0x34, +-0x34,0x02,0xff,0xff,0x00,0x43,0x10,0x2a,0x14,0x40,0x01,0x04,0x00,0x80,0x28,0x21, +-0x8c,0x86,0x00,0x08,0x24,0x02,0x00,0x03,0x10,0xc2,0x00,0xf7,0x00,0x00,0x00,0x00, +-0x8c,0xa2,0x00,0x2c,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x4f,0x24,0x02,0x00,0x06, +-0x3c,0x03,0xb0,0x05,0x34,0x63,0x04,0x50,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +-0x30,0x42,0x00,0xff,0x14,0x40,0x00,0xdd,0xac,0xa2,0x00,0x2c,0x24,0x02,0x00,0x01, +-0x10,0xc2,0x00,0xdc,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xc2,0x00,0xca, +-0x00,0x00,0x00,0x00,0x8c,0xa7,0x00,0x04,0x24,0x02,0x00,0x02,0x10,0xe2,0x00,0xc0, +-0x00,0x00,0x00,0x00,0x8c,0xa2,0x00,0x14,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x09, +-0x24,0x02,0x00,0x01,0x3c,0x03,0xb0,0x09,0x34,0x63,0x01,0x60,0x90,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0x10,0x40,0x00,0x05,0xac,0xa2,0x00,0x14, +-0x24,0x02,0x00,0x01,0xac,0xa2,0x00,0x00,0x03,0xe0,0x00,0x08,0xac,0xa0,0x00,0x14, +-0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xd0,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00, +-0x04,0x61,0x00,0x19,0x3c,0x02,0xb0,0x03,0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x2e, +-0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x12, +-0x3c,0x02,0xb0,0x03,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x42,0x90,0x43,0x00,0x00, +-0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x0c,0x3c,0x02,0xb0,0x03,0x80,0xa2,0x00,0x50, +-0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x08,0x3c,0x02,0xb0,0x03,0x14,0xc0,0x00,0x07, +-0x34,0x42,0x00,0x3f,0x24,0x02,0x00,0x0e,0x24,0x03,0x00,0x01,0xac,0xa2,0x00,0x00, +-0x03,0xe0,0x00,0x08,0xa0,0xa3,0x00,0x50,0x34,0x42,0x00,0x3f,0x90,0x44,0x00,0x00, +-0x24,0x03,0x00,0x01,0x10,0x64,0x00,0x7f,0x3c,0x03,0xb0,0x05,0x80,0xa2,0x00,0x31, +-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0a,0x3c,0x02,0xb0,0x06,0x34,0x42,0x80,0x18, +-0x8c,0x43,0x00,0x00,0x3c,0x04,0xf0,0x00,0x3c,0x02,0x80,0x00,0x00,0x64,0x18,0x24, +-0x10,0x62,0x00,0x03,0x24,0x02,0x00,0x09,0x03,0xe0,0x00,0x08,0xac,0xa2,0x00,0x00, +-0x8c,0xa2,0x00,0x40,0x00,0x00,0x00,0x00,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00, +-0x10,0x60,0x00,0x09,0x3c,0x03,0xb0,0x03,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2c, +-0x8c,0x43,0x00,0x00,0x3c,0x04,0x00,0x02,0x00,0x64,0x18,0x24,0x14,0x60,0xff,0xf2, +-0x24,0x02,0x00,0x10,0x3c,0x03,0xb0,0x03,0x34,0x63,0x02,0x01,0x90,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x80,0x10,0x40,0x00,0x0e,0x00,0x00,0x00,0x00, +-0x8c,0xa3,0x00,0x0c,0x00,0x00,0x00,0x00,0xac,0xa3,0x00,0x10,0x3c,0x02,0xb0,0x03, +-0x90,0x42,0x02,0x01,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x0f,0xac,0xa2,0x00,0x0c, +-0x90,0xa3,0x00,0x0f,0x24,0x02,0x00,0x0d,0x3c,0x01,0xb0,0x03,0x08,0x00,0x14,0xb2, +-0xa0,0x23,0x02,0x01,0x3c,0x02,0xb0,0x09,0x34,0x42,0x01,0x80,0x90,0x44,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x04,0x1e,0x00,0x00,0x03,0x1e,0x03,0x10,0x60,0x00,0x15, +-0xa0,0xa4,0x00,0x44,0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x0b,0x24,0x02,0x00,0x02, +-0x10,0x62,0x00,0x03,0x24,0x03,0x00,0x0d,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +-0x8c,0xa2,0x00,0x0c,0xac,0xa3,0x00,0x00,0x24,0x03,0x00,0x04,0xac,0xa2,0x00,0x10, +-0x03,0xe0,0x00,0x08,0xac,0xa3,0x00,0x0c,0x24,0x02,0x00,0x0d,0xac,0xa2,0x00,0x00, +-0x24,0x03,0x00,0x04,0x24,0x02,0x00,0x06,0xac,0xa3,0x00,0x10,0x03,0xe0,0x00,0x08, +-0xac,0xa2,0x00,0x0c,0x8c,0xa3,0x00,0x38,0x24,0x04,0x00,0x01,0x10,0x64,0x00,0x2d, +-0x24,0x02,0x00,0x02,0x10,0x60,0x00,0x19,0x00,0x00,0x00,0x00,0x10,0x62,0x00,0x10, +-0x24,0x02,0x00,0x04,0x10,0x62,0x00,0x04,0x00,0x00,0x00,0x00,0xac,0xa0,0x00,0x38, +-0x03,0xe0,0x00,0x08,0xac,0xa0,0x00,0x00,0x10,0xe4,0x00,0x07,0x24,0x02,0x00,0x03, +-0x80,0xa2,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x02,0x18,0x0b,0xac,0xa3,0x00,0x00, +-0x03,0xe0,0x00,0x08,0xac,0xa0,0x00,0x38,0x08,0x00,0x15,0x04,0xac,0xa2,0x00,0x00, +-0x10,0xe4,0x00,0x02,0x24,0x02,0x00,0x03,0x24,0x02,0x00,0x0c,0xac,0xa2,0x00,0x00, +-0x24,0x02,0x00,0x04,0x03,0xe0,0x00,0x08,0xac,0xa2,0x00,0x38,0x10,0xe4,0x00,0x0e, +-0x3c,0x03,0xb0,0x06,0x34,0x63,0x80,0x24,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +-0x30,0x42,0x00,0xff,0x10,0x40,0x00,0x06,0xac,0xa2,0x00,0x18,0x24,0x02,0x00,0x02, +-0xac,0xa2,0x00,0x00,0xac,0xa0,0x00,0x18,0x08,0x00,0x15,0x0d,0x24,0x02,0x00,0x01, +-0x08,0x00,0x15,0x1a,0xac,0xa0,0x00,0x00,0x24,0x02,0x00,0x03,0x08,0x00,0x15,0x1a, +-0xac,0xa2,0x00,0x00,0x24,0x03,0x00,0x0b,0xac,0xa2,0x00,0x38,0x03,0xe0,0x00,0x08, +-0xac,0xa3,0x00,0x00,0x34,0x63,0x02,0x2e,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +-0x30,0x42,0x00,0x01,0x14,0x40,0xff,0x7d,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x42, +-0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x60,0xff,0x78,0x00,0x00,0x00,0x00, +-0x10,0xc0,0xff,0x81,0x24,0x02,0x00,0x0e,0x08,0x00,0x14,0xa7,0x00,0x00,0x00,0x00, +-0x80,0xa2,0x00,0x30,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x3e,0x24,0x02,0x00,0x04, +-0x08,0x00,0x14,0xb2,0x00,0x00,0x00,0x00,0x84,0xa2,0x00,0x20,0x00,0x00,0x00,0x00, +-0x10,0x40,0xff,0x75,0x24,0x02,0x00,0x06,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2e, +-0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x01,0x30,0x63,0x00,0xff, +-0x00,0x60,0x10,0x21,0x14,0x40,0xff,0x2b,0xa4,0xa3,0x00,0x20,0x08,0x00,0x14,0xb2, +-0x24,0x02,0x00,0x06,0x8c,0xa2,0x00,0x1c,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x66, +-0x24,0x02,0x00,0x05,0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x2c,0x8c,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0x10,0x40,0xff,0x1b,0xac,0xa2,0x00,0x1c, +-0x08,0x00,0x14,0xb2,0x24,0x02,0x00,0x05,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x42,0x30,0x42,0x00,0x01,0x14,0x40,0xff,0x56, +-0x24,0x02,0x00,0x06,0x08,0x00,0x14,0x60,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x0a, +-0x03,0xe0,0x00,0x08,0xac,0x82,0x00,0x00,0x27,0xbd,0xff,0xd8,0xaf,0xb0,0x00,0x10, +-0x27,0x90,0x86,0x58,0xaf,0xbf,0x00,0x20,0xaf,0xb3,0x00,0x1c,0xaf,0xb2,0x00,0x18, +-0x0c,0x00,0x29,0xd5,0xaf,0xb1,0x00,0x14,0xaf,0x90,0x8f,0xe0,0x48,0x02,0x00,0x00, +-0x0c,0x00,0x13,0xf0,0x00,0x00,0x00,0x00,0x0c,0x00,0x18,0x1f,0x02,0x00,0x20,0x21, +-0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x3a,0x94,0x43,0x00,0x00,0x00,0x00,0x00,0x00, +-0xa3,0x83,0x8f,0xe4,0x0c,0x00,0x00,0x34,0x00,0x00,0x00,0x00,0x0c,0x00,0x13,0xfb, +-0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x98,0x0c,0x00,0x27,0x59,0x00,0x00,0x00,0x00, +-0x93,0x84,0x80,0x10,0x0c,0x00,0x21,0x3f,0x00,0x00,0x00,0x00,0x27,0x84,0x89,0x18, +-0x0c,0x00,0x06,0xe5,0x00,0x00,0x00,0x00,0x0c,0x00,0x01,0x39,0x00,0x00,0x00,0x00, +-0x27,0x84,0x84,0x40,0x0c,0x00,0x13,0xd9,0x00,0x00,0x00,0x00,0x27,0x82,0x89,0x4c, +-0xaf,0x82,0x84,0x80,0x0c,0x00,0x00,0x5f,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03, +-0x34,0x63,0x01,0x08,0x3c,0x04,0xb0,0x09,0x3c,0x05,0xb0,0x09,0x8c,0x66,0x00,0x00, +-0x34,0x84,0x01,0x68,0x34,0xa5,0x01,0x40,0x24,0x02,0xc8,0x80,0x24,0x03,0x00,0x0a, +-0xa4,0x82,0x00,0x00,0xa4,0xa3,0x00,0x00,0x3c,0x04,0xb0,0x03,0x8c,0x82,0x00,0x00, +-0x8f,0x85,0x84,0x40,0xaf,0x86,0x84,0x38,0x34,0x42,0x00,0x20,0xac,0x82,0x00,0x00, +-0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x58,0x8c,0x43,0x00,0x00,0x2c,0xa4,0x00,0x11, +-0x34,0x63,0x01,0x00,0xac,0x43,0x00,0x00,0x10,0x80,0xff,0xfa,0x3c,0x02,0xb0,0x03, +-0x3c,0x03,0x80,0x01,0x00,0x05,0x10,0x80,0x24,0x63,0x02,0x00,0x00,0x43,0x10,0x21, +-0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x08,0x00,0x00,0x00,0x00, +-0x27,0x84,0x84,0x98,0x0c,0x00,0x26,0x8e,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x40, +-0x0c,0x00,0x14,0x52,0x00,0x00,0x00,0x00,0x93,0x83,0x81,0xf1,0x24,0x02,0x00,0x01, +-0x10,0x62,0x00,0x08,0x00,0x00,0x00,0x00,0x8f,0x85,0x84,0x40,0x8f,0x82,0x84,0x74, +-0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,0xaf,0x82,0x84,0x74,0x08,0x00,0x15,0x9d, +-0x3c,0x02,0xb0,0x03,0x27,0x84,0x84,0x98,0x0c,0x00,0x27,0x0d,0x00,0x00,0x00,0x00, +-0x08,0x00,0x15,0xb6,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x98,0x0c,0x00,0x28,0xdd, +-0x00,0x00,0x00,0x00,0xa3,0x82,0x84,0x71,0x8f,0x82,0x84,0x74,0xaf,0x80,0x84,0x40, +-0x24,0x42,0x00,0x01,0xaf,0x82,0x84,0x74,0x08,0x00,0x15,0x9c,0x00,0x00,0x28,0x21, +-0x27,0x84,0x86,0x58,0x0c,0x00,0x19,0x5b,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff, +-0x14,0x40,0x00,0x05,0x3c,0x03,0xb0,0x05,0xaf,0x80,0x84,0x40,0xaf,0x80,0x84,0x44, +-0x08,0x00,0x15,0xb6,0x00,0x00,0x00,0x00,0x34,0x63,0x04,0x50,0x90,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x6c,0x14,0x40,0x00,0x20, +-0x24,0x02,0x00,0x01,0x8f,0x84,0x84,0x48,0x00,0x00,0x00,0x00,0x10,0x82,0x00,0x20, +-0x3c,0x03,0xb0,0x09,0x34,0x63,0x01,0x60,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +-0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x54,0x14,0x40,0x00,0x15,0x24,0x02,0x00,0x01, +-0x24,0x02,0x00,0x02,0x10,0x82,0x00,0x07,0x00,0x00,0x00,0x00,0x24,0x05,0x00,0x03, +-0x24,0x02,0x00,0x01,0xaf,0x82,0x84,0x44,0xaf,0x85,0x84,0x40,0x08,0x00,0x15,0xb6, +-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2e,0x90,0x43,0x00,0x00, +-0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x01,0x30,0x63,0x00,0xff,0x00,0x60,0x10,0x21, +-0xa7,0x83,0x84,0x60,0x14,0x40,0xff,0xf1,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +-0xaf,0x82,0x84,0x44,0xaf,0x80,0x84,0x40,0x08,0x00,0x15,0xb6,0x00,0x00,0x00,0x00, +-0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x2c,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +-0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x5c,0x14,0x40,0xff,0xf5,0x24,0x02,0x00,0x01, +-0x08,0x00,0x15,0xe1,0x3c,0x03,0xb0,0x09,0x27,0x84,0x86,0x58,0x0c,0x00,0x1a,0xd1, +-0x00,0x00,0x00,0x00,0x83,0x82,0x84,0x70,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0xec, +-0x24,0x02,0x00,0x02,0x3c,0x03,0xb0,0x05,0x34,0x63,0x04,0x50,0x90,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x6c,0x14,0x40,0xff,0xe4, +-0x24,0x02,0x00,0x02,0x8f,0x84,0x84,0x48,0x24,0x02,0x00,0x01,0x10,0x82,0x00,0x12, +-0x24,0x02,0x00,0x02,0x10,0x82,0x00,0x04,0x00,0x00,0x00,0x00,0x24,0x05,0x00,0x04, +-0x08,0x00,0x15,0xed,0x24,0x02,0x00,0x02,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2e, +-0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x01,0x30,0x63,0x00,0xff, +-0x00,0x60,0x10,0x21,0xa7,0x83,0x84,0x60,0x14,0x40,0xff,0xf4,0x00,0x00,0x00,0x00, +-0x08,0x00,0x15,0xfc,0x24,0x02,0x00,0x02,0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x2c, +-0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x5c, +-0x14,0x40,0xff,0xf7,0x00,0x00,0x00,0x00,0x08,0x00,0x16,0x1d,0x24,0x02,0x00,0x02, +-0x27,0x84,0x89,0x18,0x0c,0x00,0x0b,0x55,0x00,0x00,0x00,0x00,0x8f,0x83,0x84,0x44, +-0xaf,0x82,0x84,0x5c,0x38,0x64,0x00,0x02,0x00,0x04,0x18,0x0a,0xaf,0x83,0x84,0x44, +-0x14,0x40,0xff,0xad,0x24,0x05,0x00,0x05,0x8f,0x82,0x89,0x58,0xaf,0x80,0x84,0x40, +-0x10,0x40,0x00,0x02,0x24,0x04,0x00,0x01,0xaf,0x84,0x84,0x48,0x93,0x82,0x89,0x66, +-0x00,0x00,0x00,0x00,0x10,0x40,0xff,0x6c,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x05, +-0x34,0x42,0x00,0x08,0x8c,0x43,0x00,0x00,0x3c,0x04,0x20,0x00,0x00,0x64,0x18,0x24, +-0x10,0x60,0xff,0x65,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xa0, +-0x8c,0x43,0x00,0x00,0x3c,0x04,0x80,0x00,0xaf,0x80,0x89,0x40,0x24,0x63,0x00,0x01, +-0xac,0x43,0x00,0x00,0x3c,0x01,0xb0,0x05,0xac,0x24,0x00,0x08,0xaf,0x80,0x89,0x3c, +-0xaf,0x80,0x89,0x44,0xaf,0x80,0x89,0x48,0xaf,0x80,0x89,0x54,0xaf,0x80,0x89,0x4c, +-0x08,0x00,0x15,0xb6,0x00,0x00,0x00,0x00,0x83,0x82,0x84,0x90,0x00,0x00,0x00,0x00, +-0x10,0x40,0x00,0x02,0x24,0x02,0x00,0x20,0xaf,0x82,0x84,0x5c,0x8f,0x85,0x84,0x5c, +-0x27,0x84,0x89,0x18,0x0c,0x00,0x0d,0x30,0x00,0x00,0x00,0x00,0x00,0x02,0x1e,0x00, +-0xa3,0x82,0x84,0x70,0xaf,0x80,0x84,0x5c,0x10,0x60,0xff,0x8e,0x00,0x00,0x00,0x00, +-0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2e,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00, +-0x30,0x63,0x00,0x01,0x30,0x63,0x00,0xff,0x00,0x60,0x10,0x21,0xa7,0x83,0x84,0x60, +-0x10,0x40,0x00,0x04,0x24,0x04,0x00,0x02,0xaf,0x84,0x84,0x48,0x08,0x00,0x15,0xfd, +-0x00,0x00,0x00,0x00,0x08,0x00,0x15,0xee,0x24,0x05,0x00,0x06,0x27,0x84,0x84,0x40, +-0x27,0x85,0x89,0x18,0x0c,0x00,0x0d,0xfd,0x00,0x00,0x00,0x00,0x8f,0x82,0x84,0x64, +-0xaf,0x80,0x84,0x6c,0x14,0x40,0x00,0x19,0x00,0x40,0x18,0x21,0x8f,0x82,0x84,0x68, +-0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x15,0x24,0x02,0x00,0x02,0x8f,0x83,0x84,0x48, +-0x00,0x00,0x00,0x00,0x10,0x62,0x00,0x0b,0x3c,0x02,0x40,0x00,0x8f,0x83,0x84,0x44, +-0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x02,0x24,0x05,0x00,0x03,0x24,0x05,0x00,0x06, +-0xaf,0x85,0x84,0x40,0x24,0x04,0x00,0x03,0xaf,0x84,0x84,0x48,0x08,0x00,0x15,0xb6, +-0x00,0x00,0x00,0x00,0x34,0x42,0x00,0x14,0x3c,0x01,0xb0,0x05,0xac,0x22,0x00,0x00, +-0xaf,0x80,0x84,0x40,0x08,0x00,0x16,0x96,0x24,0x04,0x00,0x03,0x10,0x60,0x00,0x10, +-0x00,0x00,0x00,0x00,0x27,0x85,0x89,0x18,0x27,0x84,0x84,0x40,0x0c,0x00,0x0e,0x21, +-0x00,0x00,0x00,0x00,0x8f,0x83,0x84,0x44,0x24,0x02,0x00,0x01,0xa3,0x80,0x84,0x70, +-0xaf,0x80,0x84,0x48,0x10,0x62,0x00,0x02,0x24,0x05,0x00,0x03,0x24,0x05,0x00,0x04, +-0xaf,0x85,0x84,0x40,0xaf,0x80,0x84,0x64,0x08,0x00,0x15,0xb6,0x00,0x00,0x00,0x00, +-0x83,0x82,0x84,0x90,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x04,0x00,0x00,0x00,0x00, +-0x27,0x84,0x89,0x18,0x0c,0x00,0x10,0x69,0x00,0x00,0x00,0x00,0x8f,0x82,0x84,0x44, +-0xa3,0x80,0x84,0x70,0xaf,0x80,0x84,0x40,0xaf,0x80,0x84,0x48,0x14,0x40,0x00,0x03, +-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0xaf,0x82,0x84,0x44,0xaf,0x80,0x84,0x68, +-0x08,0x00,0x15,0xb6,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x40,0x27,0x85,0x89,0x18, +-0x0c,0x00,0x0e,0x21,0x00,0x00,0x00,0x00,0x8f,0x82,0x84,0x44,0xa3,0x80,0x84,0x70, +-0xaf,0x80,0x84,0x40,0xaf,0x80,0x84,0x48,0x14,0x40,0xfe,0xeb,0x00,0x00,0x00,0x00, +-0x24,0x02,0x00,0x02,0xaf,0x82,0x84,0x44,0x08,0x00,0x15,0xb6,0x00,0x00,0x00,0x00, +-0x27,0x84,0x89,0x18,0x0c,0x00,0x10,0x69,0x00,0x00,0x00,0x00,0x08,0x00,0x16,0xc6, +-0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x98,0x0c,0x00,0x29,0x73,0x00,0x00,0x00,0x00, +-0x08,0x00,0x15,0xc5,0x00,0x00,0x00,0x00,0x0c,0x00,0x24,0x05,0x00,0x00,0x00,0x00, +-0x0c,0x00,0x26,0xff,0x00,0x00,0x00,0x00,0x0c,0x00,0x18,0x11,0x00,0x00,0x00,0x00, +-0x93,0x83,0xbc,0x18,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x2b,0x3c,0x02,0xb0,0x03, +-0x34,0x42,0x01,0x08,0x8c,0x44,0x00,0x00,0x8f,0x83,0xbc,0x10,0x8f,0x82,0xbc,0x14, +-0x00,0x83,0x18,0x23,0x00,0x43,0x10,0x2b,0x10,0x40,0x00,0x23,0x3c,0x02,0xb0,0x03, +-0x24,0x04,0x05,0xa0,0x34,0x42,0x01,0x18,0x8c,0x42,0x00,0x00,0x0c,0x00,0x06,0xd1, +-0x00,0x00,0x00,0x00,0x24,0x04,0x05,0xa4,0x0c,0x00,0x06,0xd1,0x00,0x02,0x84,0x02, +-0x30,0x51,0xff,0xff,0x24,0x04,0x05,0xa8,0x00,0x02,0x94,0x02,0x0c,0x00,0x06,0xd1, +-0x3a,0x10,0xff,0xff,0x3a,0x31,0xff,0xff,0x30,0x42,0xff,0xff,0x2e,0x10,0x00,0x01, +-0x2e,0x31,0x00,0x01,0x3a,0x52,0xff,0xff,0x02,0x11,0x80,0x25,0x2e,0x52,0x00,0x01, +-0x38,0x42,0xff,0xff,0x02,0x12,0x80,0x25,0x2c,0x42,0x00,0x01,0x02,0x02,0x80,0x25, +-0x16,0x00,0x00,0x02,0x24,0x04,0x00,0x02,0x00,0x00,0x20,0x21,0x0c,0x00,0x05,0x6e, +-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x08,0x8c,0x43,0x00,0x00, +-0x00,0x00,0x00,0x00,0xaf,0x83,0xbc,0x10,0x0c,0x00,0x01,0xe9,0x00,0x00,0x00,0x00, +-0xaf,0x80,0x84,0x40,0xaf,0x80,0x84,0x74,0x08,0x00,0x15,0x9c,0x00,0x00,0x28,0x21, +-0x27,0x90,0xb4,0x00,0x24,0x11,0x00,0x12,0x8e,0x04,0x00,0x00,0x00,0x00,0x00,0x00, +-0x90,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x03,0x00,0x00,0x00,0x00, +-0x0c,0x00,0x18,0xd0,0x00,0x00,0x00,0x00,0x26,0x31,0xff,0xff,0x06,0x21,0xff,0xf6, +-0x26,0x10,0x00,0x04,0xaf,0x80,0x84,0x40,0x08,0x00,0x15,0xb7,0x00,0x00,0x28,0x21, +-0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x08,0x8c,0x44,0x00,0x00,0x8f,0x82,0x84,0x38, +-0x00,0x04,0x19,0xc2,0x00,0x02,0x11,0xc2,0x10,0x62,0xff,0xf6,0x00,0x00,0x00,0x00, +-0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x02,0x90,0x43,0x00,0x00,0x3c,0x12,0xb0,0x05, +-0xaf,0x84,0x84,0x38,0x30,0x63,0x00,0xff,0x00,0x03,0x11,0x40,0x00,0x43,0x10,0x23, +-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x00,0x02,0x99,0x00,0x00,0x00,0x88,0x21, +-0x36,0x52,0x02,0x2c,0x27,0x90,0xb4,0x00,0x8e,0x04,0x00,0x00,0x00,0x00,0x00,0x00, +-0x90,0x83,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x62,0x00,0x03,0x10,0x40,0x00,0x06, +-0x30,0x62,0x00,0x1c,0x14,0x40,0x00,0x04,0x00,0x00,0x00,0x00,0x8f,0x85,0x84,0x38, +-0x0c,0x00,0x1e,0x94,0x02,0x60,0x30,0x21,0x8e,0x42,0x00,0x00,0x00,0x00,0x00,0x00, +-0x30,0x42,0x00,0xff,0x14,0x40,0xff,0xd7,0x00,0x00,0x00,0x00,0x26,0x31,0x00,0x01, +-0x2a,0x22,0x00,0x13,0x14,0x40,0xff,0xec,0x26,0x10,0x00,0x04,0x08,0x00,0x17,0x21, +-0x00,0x00,0x00,0x00,0x8f,0x84,0x84,0x4c,0x27,0x85,0x89,0x18,0x0c,0x00,0x17,0xa4, +-0x00,0x00,0x00,0x00,0x8f,0x83,0x84,0x4c,0x24,0x02,0x00,0x04,0x14,0x62,0xfe,0xa5, +-0x00,0x00,0x00,0x00,0x08,0x00,0x15,0xee,0x24,0x05,0x00,0x05,0x3c,0x02,0xb0,0x03, +-0x34,0x42,0x00,0x3f,0x90,0x44,0x00,0x00,0x24,0x03,0x00,0x01,0x10,0x64,0x00,0x08, +-0x00,0x00,0x00,0x00,0x27,0x84,0x89,0x18,0x0c,0x00,0x24,0x2c,0x00,0x00,0x00,0x00, +-0x24,0x05,0x00,0x05,0xaf,0x85,0x84,0x40,0x08,0x00,0x15,0xb7,0x00,0x00,0x00,0x00, +-0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x14,0x8c,0x44,0x00,0x00,0x0c,0x00,0x24,0x49, +-0x00,0x00,0x00,0x00,0x08,0x00,0x17,0x65,0x24,0x05,0x00,0x05,0x8f,0x82,0x89,0x4c, +-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0d,0x00,0x00,0x00,0x00,0x8f,0x84,0xb4,0x40, +-0xaf,0x80,0x89,0x4c,0x94,0x85,0x00,0x14,0x0c,0x00,0x1b,0x66,0x00,0x00,0x00,0x00, +-0x93,0x82,0x8b,0x71,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x02,0x10,0x40,0x00,0x03, +-0x00,0x00,0x00,0x00,0x0c,0x00,0x01,0x57,0x00,0x00,0x20,0x21,0x8f,0x84,0xb4,0x40, +-0x0c,0x00,0x18,0xd0,0x00,0x00,0x00,0x00,0x08,0x00,0x17,0x21,0x00,0x00,0x00,0x00, +-0x3c,0x02,0xff,0x90,0x27,0xbd,0xff,0xe8,0x00,0x80,0x18,0x21,0x34,0x42,0x00,0x01, +-0x27,0x84,0x89,0x18,0x10,0x62,0x00,0x05,0xaf,0xbf,0x00,0x10,0x8f,0xbf,0x00,0x10, +-0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x0c,0x00,0x06,0xe5, +-0x00,0x00,0x00,0x00,0x27,0x84,0x86,0x58,0x0c,0x00,0x18,0x1f,0x00,0x00,0x00,0x00, +-0x27,0x84,0x84,0x40,0x0c,0x00,0x13,0xd9,0x00,0x00,0x00,0x00,0x08,0x00,0x17,0x8b, +-0x00,0x00,0x00,0x00,0x8f,0x82,0x89,0x58,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x05, +-0x00,0x00,0x18,0x21,0x8f,0x82,0x84,0x48,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x02, +-0x00,0x00,0x00,0x00,0x24,0x03,0x00,0x01,0x03,0xe0,0x00,0x08,0x00,0x60,0x10,0x21, +-0x27,0xbd,0xff,0xe0,0x3c,0x06,0xb0,0x03,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10, +-0x34,0xc6,0x00,0x5f,0xaf,0xbf,0x00,0x18,0x90,0xc3,0x00,0x00,0x3c,0x07,0xb0,0x03, +-0x34,0xe7,0x00,0x5d,0x34,0x63,0x00,0x01,0x3c,0x09,0xb0,0x03,0x24,0x02,0x00,0x01, +-0xa0,0xc3,0x00,0x00,0x00,0x80,0x80,0x21,0xa0,0xe2,0x00,0x00,0x00,0xa0,0x88,0x21, +-0x35,0x29,0x00,0x5e,0x00,0xe0,0x40,0x21,0x24,0x04,0x00,0x01,0x91,0x22,0x00,0x00, +-0x91,0x03,0x00,0x00,0x30,0x42,0x00,0x01,0x14,0x83,0x00,0x03,0x30,0x42,0x00,0x01, +-0x14,0x40,0xff,0xfa,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x04,0x12,0x02,0x00,0x2c, +-0x24,0x05,0x0f,0x00,0x24,0x02,0x00,0x06,0x12,0x02,0x00,0x08,0x24,0x05,0x00,0x0f, +-0x3c,0x02,0xb0,0x03,0x34,0x42,0x02,0x00,0xa0,0x50,0x00,0x00,0x8f,0xbf,0x00,0x18, +-0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x24,0x04,0x0c,0x04, +-0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x0f,0x24,0x04,0x0d,0x04,0x24,0x05,0x00,0x0f, +-0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x0f,0x24,0x04,0x08,0x80,0x24,0x05,0x1e,0x00, +-0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x0f,0x24,0x04,0x08,0x8c,0x24,0x05,0x0f,0x00, +-0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x0f,0x24,0x04,0x08,0x24,0x3c,0x05,0x00,0x30, +-0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x02,0x24,0x04,0x08,0x2c,0x3c,0x05,0x00,0x30, +-0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x02,0x24,0x04,0x08,0x34,0x3c,0x05,0x00,0x30, +-0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x02,0x24,0x04,0x08,0x3c,0x3c,0x05,0x00,0x30, +-0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x02,0x08,0x00,0x17,0xc5,0x3c,0x02,0xb0,0x03, +-0x24,0x04,0x08,0x8c,0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x04,0x24,0x04,0x08,0x80, +-0x24,0x05,0x1e,0x00,0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x04,0x24,0x04,0x0c,0x04, +-0x24,0x05,0x00,0x0f,0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x04,0x24,0x04,0x0d,0x04, +-0x24,0x05,0x00,0x0f,0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x04,0x24,0x04,0x08,0x24, +-0x3c,0x05,0x00,0x30,0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x03,0x24,0x04,0x08,0x2c, +-0x3c,0x05,0x00,0x30,0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x03,0x24,0x04,0x08,0x34, +-0x3c,0x05,0x00,0x30,0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x02,0x3c,0x05,0x00,0x30, +-0x24,0x06,0x00,0x03,0x0c,0x00,0x13,0x5f,0x24,0x04,0x08,0x3c,0x02,0x20,0x20,0x21, +-0x24,0x05,0x00,0x14,0x0c,0x00,0x13,0xa4,0x24,0x06,0x01,0x07,0x08,0x00,0x17,0xc5, +-0x3c,0x02,0xb0,0x03,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x73,0x90,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x02,0x14,0x40,0x00,0x04,0x00,0x00,0x00,0x00, +-0xa3,0x80,0x81,0x58,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +-0xa3,0x82,0x81,0x58,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03, +-0x3c,0x02,0x80,0x00,0x00,0x80,0x70,0x21,0x34,0x63,0x00,0x20,0x24,0x42,0x60,0x7c, +-0x3c,0x04,0xb0,0x03,0xac,0x62,0x00,0x00,0x34,0x84,0x00,0x30,0xad,0xc0,0x02,0xb8, +-0x8c,0x83,0x00,0x00,0x24,0x02,0x00,0xff,0xa5,0xc0,0x00,0x0a,0x00,0x00,0x30,0x21, +-0xa7,0x82,0x8f,0xf0,0x27,0x88,0x90,0x00,0xa5,0xc3,0x00,0x08,0x3c,0x07,0xb0,0x08, +-0x30,0xc2,0xff,0xff,0x00,0x02,0x20,0xc0,0x24,0xc3,0x00,0x01,0x00,0x82,0x10,0x21, +-0x00,0x60,0x30,0x21,0x00,0x02,0x10,0x80,0x30,0x63,0xff,0xff,0x00,0x48,0x10,0x21, +-0x00,0x87,0x20,0x21,0x28,0xc5,0x00,0xff,0xac,0x83,0x00,0x00,0x14,0xa0,0xff,0xf4, +-0xa4,0x43,0x00,0x00,0x3c,0x02,0xb0,0x08,0x34,0x03,0xff,0xff,0x25,0xc4,0x00,0x0c, +-0x24,0x0a,0x00,0x02,0x34,0x42,0x07,0xf8,0x3c,0x06,0xb0,0x03,0xa7,0x83,0xb3,0xdc, +-0xac,0x43,0x00,0x00,0xaf,0x84,0xb4,0x00,0x34,0xc6,0x00,0x64,0xa0,0x8a,0x00,0x18, +-0x94,0xc5,0x00,0x00,0x8f,0x82,0xb4,0x00,0x25,0xc4,0x00,0x30,0x24,0x08,0x00,0x03, +-0x3c,0x03,0xb0,0x03,0xa0,0x45,0x00,0x21,0x34,0x63,0x00,0x66,0xaf,0x84,0xb4,0x04, +-0xa0,0x88,0x00,0x18,0x94,0x65,0x00,0x00,0x8f,0x82,0xb4,0x04,0x25,0xc4,0x00,0x54, +-0x25,0xc7,0x00,0x78,0xa0,0x45,0x00,0x21,0xaf,0x84,0xb4,0x08,0xa0,0x88,0x00,0x18, +-0x94,0x65,0x00,0x00,0x8f,0x82,0xb4,0x08,0x25,0xc8,0x00,0x9c,0x24,0x09,0x00,0x01, +-0xa0,0x45,0x00,0x21,0xaf,0x87,0xb4,0x0c,0xa0,0xea,0x00,0x18,0x94,0xc4,0x00,0x00, +-0x8f,0x82,0xb4,0x0c,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x62,0xa0,0x44,0x00,0x21, +-0xaf,0x88,0xb4,0x10,0xa1,0x09,0x00,0x18,0x94,0x65,0x00,0x00,0x8f,0x82,0xb4,0x10, +-0x25,0xc4,0x00,0xc0,0x3c,0x06,0xb0,0x03,0xa0,0x45,0x00,0x21,0xaf,0x84,0xb4,0x14, +-0xa0,0x89,0x00,0x18,0x94,0x65,0x00,0x00,0x8f,0x82,0xb4,0x14,0x25,0xc4,0x00,0xe4, +-0x34,0xc6,0x00,0x60,0xa0,0x45,0x00,0x21,0xaf,0x84,0xb4,0x18,0xa0,0x80,0x00,0x18, +-0x94,0xc5,0x00,0x00,0x8f,0x82,0xb4,0x18,0x25,0xc3,0x01,0x08,0x25,0xc7,0x01,0x2c, +-0xa0,0x45,0x00,0x21,0xaf,0x83,0xb4,0x1c,0xa0,0x60,0x00,0x18,0x94,0xc8,0x00,0x00, +-0x8f,0x82,0xb4,0x1c,0x25,0xc4,0x01,0x50,0x25,0xc5,0x01,0x74,0xa0,0x48,0x00,0x21, +-0x25,0xc6,0x01,0x98,0x25,0xc9,0x01,0xbc,0x25,0xca,0x01,0xe0,0x25,0xcb,0x02,0x04, +-0x25,0xcc,0x02,0x28,0x25,0xcd,0x02,0x4c,0x24,0x02,0x00,0x10,0x3c,0x03,0xb0,0x03, +-0xaf,0x87,0xb4,0x20,0x34,0x63,0x00,0x38,0xa0,0xe0,0x00,0x18,0xaf,0x84,0xb4,0x24, +-0xa0,0x80,0x00,0x18,0xaf,0x85,0xb4,0x28,0xa0,0xa0,0x00,0x18,0xaf,0x86,0xb4,0x2c, +-0xa0,0xc0,0x00,0x18,0xaf,0x89,0xb4,0x30,0xa1,0x20,0x00,0x18,0xaf,0x8a,0xb4,0x34, +-0xa1,0x40,0x00,0x18,0xaf,0x8b,0xb4,0x38,0xa1,0x60,0x00,0x18,0xaf,0x8c,0xb4,0x3c, +-0xa1,0x80,0x00,0x18,0xaf,0x8d,0xb4,0x40,0xa1,0xa2,0x00,0x18,0x94,0x64,0x00,0x00, +-0x8f,0x82,0xb4,0x40,0x25,0xc5,0x02,0x70,0x3c,0x03,0xb0,0x03,0xa0,0x44,0x00,0x21, +-0x24,0x02,0x00,0x11,0xaf,0x85,0xb4,0x44,0x34,0x63,0x00,0x6e,0xa0,0xa2,0x00,0x18, +-0x94,0x64,0x00,0x00,0x8f,0x82,0xb4,0x44,0x25,0xc5,0x02,0x94,0x3c,0x03,0xb0,0x03, +-0xa0,0x44,0x00,0x21,0x24,0x02,0x00,0x12,0xaf,0x85,0xb4,0x48,0x34,0x63,0x00,0x6c, +-0xa0,0xa2,0x00,0x18,0x94,0x64,0x00,0x00,0x8f,0x82,0xb4,0x48,0x24,0x05,0xff,0xff, +-0x24,0x07,0x00,0x01,0xa0,0x44,0x00,0x21,0x24,0x06,0x00,0x12,0x27,0x84,0xb4,0x00, +-0x8c,0x82,0x00,0x00,0x24,0xc6,0xff,0xff,0xa0,0x40,0x00,0x04,0x8c,0x83,0x00,0x00, +-0xa4,0x45,0x00,0x00,0xa4,0x45,0x00,0x02,0xa0,0x60,0x00,0x0a,0x8c,0x82,0x00,0x00, +-0xa4,0x65,0x00,0x06,0xa4,0x65,0x00,0x08,0xa0,0x40,0x00,0x10,0x8c,0x83,0x00,0x00, +-0xa4,0x45,0x00,0x0c,0xa4,0x45,0x00,0x0e,0xa0,0x60,0x00,0x12,0x8c,0x82,0x00,0x00, +-0x00,0x00,0x00,0x00,0xa0,0x40,0x00,0x16,0x8c,0x83,0x00,0x00,0xa4,0x45,0x00,0x14, +-0xa0,0x67,0x00,0x17,0x8c,0x82,0x00,0x00,0x24,0x84,0x00,0x04,0xa0,0x40,0x00,0x20, +-0x04,0xc1,0xff,0xe7,0xac,0x40,0x00,0x1c,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +-0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x00,0x34,0x42,0x00,0x20,0x24,0x63,0x63,0x40, +-0xac,0x43,0x00,0x00,0x90,0x82,0x00,0x10,0x00,0x80,0x60,0x21,0x10,0x40,0x00,0x56, +-0x00,0x00,0x70,0x21,0x97,0x82,0x8f,0xf0,0x94,0x8a,0x00,0x0c,0x27,0x87,0x90,0x00, +-0x00,0x02,0x40,0xc0,0x01,0x02,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x47,0x10,0x21, +-0x90,0x8b,0x00,0x18,0xa4,0x4a,0x00,0x00,0x94,0x83,0x00,0x0e,0x39,0x64,0x00,0x10, +-0x2c,0x84,0x00,0x01,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x34,0x85,0x00,0x02, +-0x39,0x63,0x00,0x11,0x00,0x83,0x28,0x0b,0x34,0xa3,0x00,0x08,0x39,0x64,0x00,0x12, +-0x00,0x02,0x10,0x80,0x00,0xa4,0x18,0x0b,0x00,0x47,0x10,0x21,0x94,0x49,0x00,0x04, +-0x34,0x64,0x00,0x20,0x00,0x6b,0x20,0x0b,0x34,0x83,0x00,0x40,0x39,0x62,0x00,0x01, +-0x00,0x82,0x18,0x0b,0x00,0x09,0x30,0xc0,0x34,0x64,0x00,0x80,0x00,0xc9,0x28,0x21, +-0x39,0x62,0x00,0x02,0x00,0x60,0x68,0x21,0x00,0x82,0x68,0x0a,0x00,0x05,0x28,0x80, +-0x3c,0x02,0xb0,0x08,0x00,0xa7,0x28,0x21,0x00,0xc2,0x30,0x21,0x01,0x02,0x40,0x21, +-0x34,0x03,0xff,0xff,0x35,0xa4,0x01,0x00,0x39,0x62,0x00,0x03,0x2d,0x67,0x00,0x13, +-0xad,0x0a,0x00,0x00,0xa4,0xa3,0x00,0x00,0xac,0xc3,0x00,0x00,0xa7,0x89,0x8f,0xf0, +-0x10,0xe0,0x00,0x0f,0x00,0x82,0x68,0x0a,0x3c,0x03,0x80,0x01,0x00,0x0b,0x10,0x80, +-0x24,0x63,0x02,0x44,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x80,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x60, +-0x94,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x00,0x00,0x02,0x74,0x03, +-0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x3a,0x94,0x44,0x00,0x00,0x93,0x83,0x8f,0xe4, +-0x91,0x82,0x00,0x21,0x01,0xc4,0x20,0x21,0x91,0x85,0x00,0x10,0x00,0x04,0x24,0x00, +-0x00,0x62,0x18,0x21,0x00,0x04,0x74,0x03,0x00,0x6e,0x18,0x23,0x00,0x65,0x10,0x2a, +-0x00,0xa2,0x18,0x0a,0x00,0x0d,0x24,0x00,0x3c,0x02,0xb0,0x06,0x24,0x05,0xff,0xff, +-0x00,0x64,0x18,0x25,0x34,0x42,0x80,0x20,0xac,0x43,0x00,0x00,0xa5,0x85,0x00,0x0e, +-0xa1,0x80,0x00,0x10,0xa5,0x85,0x00,0x0c,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +-0x3c,0x03,0xb0,0x03,0x08,0x00,0x19,0x14,0x34,0x63,0x00,0x62,0x3c,0x03,0xb0,0x03, +-0x08,0x00,0x19,0x14,0x34,0x63,0x00,0x64,0x3c,0x03,0xb0,0x03,0x08,0x00,0x19,0x14, +-0x34,0x63,0x00,0x66,0x3c,0x03,0xb0,0x03,0x08,0x00,0x19,0x14,0x34,0x63,0x00,0x38, +-0x3c,0x03,0xb0,0x03,0x08,0x00,0x19,0x14,0x34,0x63,0x00,0x6e,0x3c,0x03,0xb0,0x03, +-0x08,0x00,0x19,0x14,0x34,0x63,0x00,0x6c,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00, +-0x34,0x63,0x00,0x20,0x24,0x42,0x65,0x08,0x00,0x05,0x28,0x40,0xac,0x62,0x00,0x00, +-0x00,0xa6,0x28,0x21,0x2c,0xe2,0x00,0x10,0x14,0x80,0x00,0x06,0x00,0x00,0x18,0x21, +-0x10,0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0xe0,0x18,0x21,0x03,0xe0,0x00,0x08, +-0x00,0x60,0x10,0x21,0x24,0x02,0x00,0x20,0x10,0xe2,0x00,0x06,0x2c,0xe4,0x00,0x10, +-0x24,0xa2,0x00,0x01,0x10,0x80,0xff,0xf9,0x00,0x02,0x11,0x00,0x08,0x00,0x19,0x4f, +-0x00,0x47,0x18,0x21,0x08,0x00,0x19,0x4f,0x24,0xa3,0x00,0x50,0x27,0xbd,0xff,0xc8, +-0xaf,0xb3,0x00,0x1c,0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x30, +-0xaf,0xb7,0x00,0x2c,0xaf,0xb6,0x00,0x28,0xaf,0xb5,0x00,0x24,0xaf,0xb4,0x00,0x20, +-0xaf,0xb0,0x00,0x10,0x00,0x80,0x88,0x21,0x84,0x84,0x00,0x08,0x3c,0x05,0xb0,0x03, +-0x3c,0x02,0x80,0x00,0x34,0xa5,0x00,0x20,0x24,0x42,0x65,0x6c,0x3c,0x03,0xb0,0x06, +-0x00,0x04,0x20,0x80,0xac,0xa2,0x00,0x00,0x00,0x83,0x20,0x21,0x3c,0x06,0xb0,0x06, +-0x8c,0x82,0x00,0x00,0x34,0xc6,0x80,0x24,0x8c,0x88,0x00,0x00,0x8c,0xc4,0x00,0x00, +-0x96,0x25,0x00,0x08,0x30,0x52,0xff,0xff,0x00,0x08,0x44,0x02,0x34,0x84,0x01,0x00, +-0x3c,0x02,0xb0,0x00,0x00,0x08,0x18,0xc0,0x00,0x12,0x3a,0x00,0xac,0xc4,0x00,0x00, +-0x00,0xe2,0x38,0x21,0xae,0x32,0x02,0xb8,0x00,0x68,0x18,0x21,0x24,0xa5,0x00,0x02, +-0x8c,0xf6,0x00,0x00,0x30,0xa5,0x01,0xff,0x8c,0xf4,0x00,0x04,0x27,0x86,0x90,0x00, +-0x00,0x03,0x18,0x80,0x00,0x12,0x98,0xc0,0xa6,0x25,0x00,0x08,0x00,0x66,0x18,0x21, +-0x02,0x72,0x10,0x21,0x94,0x65,0x00,0x00,0x00,0x02,0x48,0x80,0x01,0x26,0x30,0x21, +-0x24,0x02,0xff,0xff,0x00,0x14,0x1a,0x02,0x27,0x84,0x90,0x10,0xa4,0xc2,0x00,0x02, +-0x30,0x63,0x00,0x1f,0x24,0x02,0x00,0x10,0x01,0x24,0x20,0x21,0xa4,0xc8,0x00,0x04, +-0x8c,0xf0,0x00,0x08,0xa6,0x23,0x00,0x06,0xa6,0x25,0x00,0x0a,0xa0,0x82,0x00,0x06, +-0x86,0x25,0x00,0x06,0x27,0x82,0x90,0x04,0x01,0x22,0x10,0x21,0x24,0x03,0x00,0x13, +-0x10,0xa3,0x00,0xee,0xac,0x47,0x00,0x18,0x3c,0x03,0xb0,0x03,0x34,0x63,0x01,0x00, +-0xa6,0x20,0x00,0x02,0x3c,0x02,0xb0,0x03,0x90,0x64,0x00,0x00,0x34,0x42,0x01,0x08, +-0x8c,0x45,0x00,0x00,0x00,0x10,0x1b,0xc2,0x00,0x04,0x20,0x82,0x30,0x63,0x00,0x01, +-0xac,0xc5,0x00,0x08,0x10,0x60,0x00,0xc7,0x30,0x97,0x00,0x01,0x00,0x10,0x16,0x82, +-0x30,0x46,0x00,0x01,0x00,0x10,0x12,0x02,0x00,0x10,0x19,0xc2,0x00,0x10,0x26,0x02, +-0x00,0x10,0x2e,0x42,0x30,0x48,0x00,0x7f,0x24,0x02,0x00,0x01,0x30,0x75,0x00,0x01, +-0x30,0x84,0x00,0x01,0x10,0xc2,0x00,0xb3,0x30,0xa3,0x00,0x01,0x00,0x60,0x28,0x21, +-0x0c,0x00,0x19,0x42,0x01,0x00,0x38,0x21,0x02,0x72,0x18,0x21,0x00,0x03,0x18,0x80, +-0x2c,0x46,0x00,0x54,0x27,0x85,0x90,0x10,0x27,0x84,0x90,0x08,0x00,0x06,0x10,0x0a, +-0x00,0x65,0x28,0x21,0x26,0xa6,0x00,0x02,0x00,0x64,0x18,0x21,0xa0,0xa2,0x00,0x02, +-0xa0,0x66,0x00,0x06,0xa0,0x62,0x00,0x07,0xa0,0xa2,0x00,0x01,0x02,0x72,0x28,0x21, +-0x00,0x05,0x28,0x80,0x27,0x82,0x90,0x04,0x00,0xa2,0x58,0x21,0x8d,0x64,0x00,0x18, +-0x00,0x10,0x15,0xc2,0x30,0x42,0x00,0x01,0x8c,0x83,0x00,0x0c,0x27,0x84,0x90,0x20, +-0x00,0xa4,0x48,0x21,0xa6,0x22,0x00,0x00,0xa6,0x36,0x00,0x04,0x8d,0x26,0x00,0x00, +-0x00,0x03,0x19,0x42,0x3c,0x02,0xff,0xef,0x34,0x42,0xff,0xff,0x30,0x63,0x00,0x01, +-0x00,0xc2,0x40,0x24,0x00,0x03,0x1d,0x00,0x01,0x03,0x40,0x25,0x00,0x08,0x15,0x02, +-0x00,0x14,0x19,0x82,0x00,0x14,0x25,0x82,0x00,0x10,0x34,0x42,0x00,0x10,0x3c,0x82, +-0x00,0x10,0x2c,0x02,0x30,0x42,0x00,0x01,0x30,0xcd,0x00,0x01,0x30,0x6c,0x00,0x01, +-0x30,0xe6,0x00,0x01,0x30,0x8a,0x00,0x03,0x32,0x94,0x00,0x07,0x30,0xa5,0x00,0x01, +-0xad,0x28,0x00,0x00,0x10,0x40,0x00,0x0b,0x32,0x07,0x00,0x7f,0x8d,0x64,0x00,0x18, +-0x3c,0x03,0xff,0xf0,0x34,0x63,0xff,0xff,0x8c,0x82,0x00,0x0c,0x01,0x03,0x18,0x24, +-0x00,0x02,0x13,0x82,0x30,0x42,0x00,0x0f,0x00,0x02,0x14,0x00,0x00,0x62,0x18,0x25, +-0xad,0x23,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xc2,0x00,0x6a,0x00,0x00,0x00,0x00, +-0x15,0x80,0x00,0x03,0x00,0x00,0x00,0x00,0x15,0x40,0x00,0x5b,0x24,0x02,0x00,0x01, +-0x96,0x22,0x00,0x04,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x04,0xa6,0x22,0x00,0x04, +-0x00,0xa0,0x20,0x21,0x0c,0x00,0x19,0x42,0x01,0xa0,0x28,0x21,0x02,0x72,0x18,0x21, +-0x00,0x03,0x40,0x80,0x2c,0x45,0x00,0x54,0x27,0x84,0x90,0x10,0x01,0x04,0x20,0x21, +-0x00,0x05,0x10,0x0a,0xa0,0x82,0x00,0x00,0xa0,0x80,0x00,0x04,0xa0,0x80,0x00,0x05, +-0x96,0x23,0x00,0x04,0x27,0x82,0x90,0x00,0x01,0x02,0x10,0x21,0xa4,0x43,0x00,0x06, +-0x27,0x82,0x90,0x04,0x92,0x26,0x00,0x01,0x01,0x02,0x10,0x21,0x8c,0x45,0x00,0x18, +-0x27,0x83,0x90,0x20,0x01,0x03,0x18,0x21,0xa0,0x60,0x00,0x00,0xa0,0x86,0x00,0x07, +-0x94,0xa2,0x00,0x10,0x24,0x03,0x00,0x04,0x30,0x42,0x00,0x0f,0x10,0x43,0x00,0x36, +-0x24,0xa5,0x00,0x10,0x94,0xa3,0x00,0x16,0x27,0x87,0x90,0x18,0x01,0x07,0x10,0x21, +-0xa4,0x43,0x00,0x02,0x94,0xa2,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01, +-0x14,0x40,0x00,0x24,0x02,0x72,0x20,0x21,0x94,0xa2,0x00,0x00,0x24,0x03,0x00,0xa4, +-0x30,0x42,0x00,0xff,0x10,0x43,0x00,0x1f,0x00,0x00,0x00,0x00,0x94,0xa2,0x00,0x00, +-0x24,0x03,0x00,0x88,0x30,0x42,0x00,0x88,0x10,0x43,0x00,0x14,0x02,0x72,0x18,0x21, +-0x27,0x84,0x90,0x20,0x00,0x03,0x18,0x80,0x00,0x64,0x18,0x21,0x8c,0x62,0x00,0x00, +-0x3c,0x04,0x00,0x80,0x00,0x44,0x10,0x25,0xac,0x62,0x00,0x00,0x02,0x72,0x10,0x21, +-0x00,0x02,0x10,0x80,0x00,0x47,0x10,0x21,0xa0,0x54,0x00,0x00,0x8f,0xbf,0x00,0x30, +-0x7b,0xb6,0x01,0x7c,0x7b,0xb4,0x01,0x3c,0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc, +-0x24,0x02,0x00,0x01,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x38,0x94,0xa2,0x00,0x18, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x60,0x10,0x40,0xff,0xe9,0x02,0x72,0x18,0x21, +-0x02,0x72,0x20,0x21,0x27,0x82,0x90,0x20,0x00,0x04,0x20,0x80,0x00,0x82,0x20,0x21, +-0x8c,0x83,0x00,0x00,0x3c,0x02,0xff,0x7f,0x34,0x42,0xff,0xff,0x00,0x62,0x18,0x24, +-0x08,0x00,0x1a,0x37,0xac,0x83,0x00,0x00,0x27,0x87,0x90,0x18,0x01,0x07,0x10,0x21, +-0x08,0x00,0x1a,0x21,0xa4,0x40,0x00,0x02,0x11,0x42,0x00,0x07,0x00,0x00,0x00,0x00, +-0x2d,0x42,0x00,0x02,0x14,0x40,0xff,0xa7,0x00,0xa0,0x20,0x21,0x96,0x22,0x00,0x04, +-0x08,0x00,0x19,0xff,0x24,0x42,0x00,0x0c,0x96,0x22,0x00,0x04,0x08,0x00,0x19,0xff, +-0x24,0x42,0x00,0x08,0x16,0xe6,0xff,0x96,0x3c,0x02,0xff,0xfb,0x8d,0x63,0x00,0x18, +-0x34,0x42,0xff,0xff,0x02,0x02,0x10,0x24,0xac,0x62,0x00,0x08,0x08,0x00,0x19,0xf8, +-0x00,0x00,0x30,0x21,0x16,0xe6,0xff,0x4e,0x00,0x60,0x28,0x21,0x3c,0x02,0xfb,0xff, +-0x34,0x42,0xff,0xff,0x02,0x02,0x10,0x24,0xac,0xe2,0x00,0x08,0x08,0x00,0x19,0xb7, +-0x00,0x00,0x30,0x21,0x93,0x87,0xbb,0x14,0x00,0x10,0x1e,0x42,0x00,0x10,0x26,0x82, +-0x27,0x82,0x90,0x08,0x2c,0xe5,0x00,0x0c,0x01,0x22,0x48,0x21,0x30,0x63,0x00,0x01, +-0x30,0x86,0x00,0x01,0x14,0xa0,0x00,0x06,0x00,0xe0,0x40,0x21,0x00,0x03,0x10,0x40, +-0x00,0x46,0x10,0x21,0x00,0x02,0x11,0x00,0x00,0xe2,0x10,0x21,0x24,0x48,0x00,0x04, +-0x02,0x72,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x84,0x90,0x10,0x27,0x83,0x90,0x08, +-0x00,0x44,0x20,0x21,0x00,0x43,0x10,0x21,0xa1,0x28,0x00,0x07,0xa0,0x40,0x00,0x06, +-0xa0,0x80,0x00,0x02,0x08,0x00,0x19,0xc7,0xa0,0x80,0x00,0x01,0x24,0x02,0x00,0x01, +-0xa6,0x22,0x00,0x02,0x0c,0x00,0x01,0xc2,0x00,0xe0,0x20,0x21,0x08,0x00,0x1a,0x3b, +-0x00,0x00,0x00,0x00,0x30,0xa7,0xff,0xff,0x00,0x07,0x18,0xc0,0x00,0x67,0x18,0x21, +-0x3c,0x06,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x6a,0x44,0x27,0x85,0x90,0x10, +-0x00,0x03,0x18,0x80,0x34,0xc6,0x00,0x20,0x00,0x65,0x18,0x21,0xac,0xc2,0x00,0x00, +-0x80,0x62,0x00,0x07,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x29,0x00,0x80,0x28,0x21, +-0x90,0x82,0x00,0x16,0x00,0x00,0x00,0x00,0x34,0x42,0x00,0x02,0x30,0x43,0x00,0x01, +-0x14,0x60,0x00,0x02,0xa0,0x82,0x00,0x16,0xa0,0x80,0x00,0x17,0x90,0xa2,0x00,0x04, +-0x3c,0x03,0xb0,0x03,0x27,0x86,0x90,0x00,0x14,0x40,0x00,0x06,0x34,0x63,0x00,0x20, +-0x24,0x02,0x00,0x01,0xa0,0xa2,0x00,0x04,0xa4,0xa7,0x00,0x02,0x03,0xe0,0x00,0x08, +-0xa4,0xa7,0x00,0x00,0x94,0xa4,0x00,0x02,0x3c,0x02,0x80,0x01,0x24,0x42,0x82,0x6c, +-0xac,0x62,0x00,0x00,0x00,0x04,0x18,0xc0,0x00,0x64,0x18,0x21,0x00,0x03,0x18,0x80, +-0x00,0x66,0x18,0x21,0x94,0x62,0x00,0x04,0xa4,0x67,0x00,0x02,0x3c,0x03,0xb0,0x08, +-0x00,0x02,0x20,0xc0,0x00,0x82,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x46,0x10,0x21, +-0x00,0x83,0x20,0x21,0xa4,0x47,0x00,0x00,0xac,0x87,0x00,0x00,0x90,0xa2,0x00,0x04, +-0xa4,0xa7,0x00,0x02,0x24,0x42,0x00,0x01,0x03,0xe0,0x00,0x08,0xa0,0xa2,0x00,0x04, +-0x90,0x82,0x00,0x16,0x24,0x85,0x00,0x06,0x34,0x42,0x00,0x01,0x30,0x43,0x00,0x02, +-0x14,0x60,0xff,0xda,0xa0,0x82,0x00,0x16,0x24,0x02,0x00,0x01,0x08,0x00,0x1a,0xa7, +-0xa0,0x82,0x00,0x17,0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10,0x00,0x80,0x38,0x21, +-0x84,0x84,0x00,0x02,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x3c,0x0a,0xb0,0x06, +-0x34,0x63,0x00,0x20,0x24,0x42,0x6b,0x44,0x3c,0x0b,0xb0,0x08,0x27,0x89,0x90,0x00, +-0x34,0x0c,0xff,0xff,0x35,0x4a,0x80,0x20,0x10,0x80,0x00,0x30,0xac,0x62,0x00,0x00, +-0x97,0x82,0x8f,0xf0,0x94,0xe6,0x02,0xba,0x00,0x02,0x18,0xc0,0x00,0x6b,0x28,0x21, +-0xac,0xa6,0x00,0x00,0x8c,0xe4,0x02,0xb8,0x00,0x62,0x18,0x21,0x00,0x03,0x18,0x80, +-0x00,0x04,0x10,0xc0,0x00,0x44,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x49,0x10,0x21, +-0x94,0x48,0x00,0x04,0x00,0x69,0x18,0x21,0xa4,0x66,0x00,0x00,0x00,0x08,0x28,0xc0, +-0x00,0xab,0x10,0x21,0xac,0x4c,0x00,0x00,0x8c,0xe4,0x02,0xb8,0x27,0x82,0x90,0x04, +-0x00,0xa8,0x28,0x21,0x00,0x04,0x18,0xc0,0x00,0x64,0x18,0x21,0x00,0x03,0x18,0x80, +-0x00,0x62,0x10,0x21,0x8c,0x46,0x00,0x18,0x27,0x84,0x90,0x10,0x00,0x64,0x18,0x21, +-0x8c,0xc2,0x00,0x00,0x80,0x67,0x00,0x06,0x00,0x05,0x28,0x80,0x30,0x42,0xff,0xff, +-0x00,0x47,0x10,0x21,0x30,0x43,0x00,0xff,0x00,0x03,0x18,0x2b,0x00,0x02,0x12,0x02, +-0x00,0x43,0x10,0x21,0x3c,0x04,0x00,0x04,0x00,0xa9,0x28,0x21,0x00,0x44,0x10,0x25, +-0xa4,0xac,0x00,0x00,0xad,0x42,0x00,0x00,0xa7,0x88,0x8f,0xf0,0x8f,0xbf,0x00,0x10, +-0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x84,0xe3,0x00,0x06, +-0x27,0x82,0xb4,0x00,0x94,0xe5,0x02,0xba,0x00,0x03,0x18,0x80,0x00,0x62,0x18,0x21, +-0x8c,0x64,0x00,0x00,0x0c,0x00,0x1a,0x91,0x00,0x00,0x00,0x00,0x08,0x00,0x1b,0x0b, +-0x00,0x00,0x00,0x00,0x94,0x88,0x00,0x00,0x00,0x80,0x58,0x21,0x27,0x8a,0x90,0x00, +-0x00,0x08,0x18,0xc0,0x00,0x68,0x18,0x21,0x3c,0x04,0xb0,0x03,0x00,0x03,0x18,0x80, +-0x3c,0x02,0x80,0x00,0x00,0x6a,0x18,0x21,0x34,0x84,0x00,0x20,0x24,0x42,0x6c,0x64, +-0x30,0xa5,0xff,0xff,0xac,0x82,0x00,0x00,0x94,0x67,0x00,0x02,0x11,0x05,0x00,0x35, +-0x24,0x04,0x00,0x01,0x91,0x66,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x86,0x10,0x2a, +-0x10,0x40,0x00,0x10,0x00,0xc0,0x48,0x21,0x3c,0x0d,0xb0,0x03,0x01,0x40,0x60,0x21, +-0x35,0xad,0x00,0x20,0x10,0xe5,0x00,0x0d,0x24,0x84,0x00,0x01,0x00,0x07,0x10,0xc0, +-0x00,0x47,0x10,0x21,0x00,0x02,0x10,0x80,0x01,0x20,0x30,0x21,0x00,0x4a,0x10,0x21, +-0x00,0x86,0x18,0x2a,0x00,0xe0,0x40,0x21,0x94,0x47,0x00,0x02,0x14,0x60,0xff,0xf5, +-0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x10,0x21,0x00,0x08,0x20,0xc0, +-0x00,0x88,0x20,0x21,0x24,0xc2,0xff,0xff,0x00,0x04,0x20,0x80,0xa1,0x62,0x00,0x04, +-0x00,0x8c,0x20,0x21,0x94,0x83,0x00,0x04,0x00,0x07,0x10,0xc0,0x00,0x47,0x10,0x21, +-0x00,0x02,0x10,0x80,0x00,0x4c,0x10,0x21,0x00,0x03,0x28,0xc0,0x94,0x46,0x00,0x02, +-0x00,0xa3,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0x6c,0x18,0x21,0xa4,0x66,0x00,0x00, +-0xa4,0x86,0x00,0x02,0x95,0x64,0x00,0x02,0x3c,0x03,0xb0,0x08,0x3c,0x02,0x80,0x01, +-0x00,0xa3,0x28,0x21,0x24,0x42,0x82,0x6c,0xad,0xa2,0x00,0x00,0x10,0x87,0x00,0x03, +-0xac,0xa6,0x00,0x00,0x03,0xe0,0x00,0x08,0x24,0x02,0x00,0x01,0x08,0x00,0x1b,0x59, +-0xa5,0x68,0x00,0x02,0x91,0x62,0x00,0x04,0xa5,0x67,0x00,0x00,0x24,0x42,0xff,0xff, +-0x30,0x43,0x00,0xff,0x14,0x60,0xff,0xf7,0xa1,0x62,0x00,0x04,0x24,0x02,0xff,0xff, +-0x08,0x00,0x1b,0x59,0xa5,0x62,0x00,0x02,0x00,0x05,0x40,0xc0,0x01,0x05,0x30,0x21, +-0x27,0xbd,0xff,0xd8,0x00,0x06,0x30,0x80,0x27,0x82,0x90,0x04,0xaf,0xb2,0x00,0x18, +-0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x20,0xaf,0xb3,0x00,0x1c,0xaf,0xb0,0x00,0x10, +-0x00,0xc2,0x10,0x21,0x8c,0x47,0x00,0x18,0x00,0xa0,0x90,0x21,0x3c,0x02,0x80,0x00, +-0x3c,0x05,0xb0,0x03,0x34,0xa5,0x00,0x20,0x24,0x42,0x6d,0x98,0xac,0xa2,0x00,0x00, +-0x27,0x83,0x90,0x10,0x00,0xc3,0x30,0x21,0x8c,0xe2,0x00,0x00,0x80,0xc5,0x00,0x06, +-0x00,0x80,0x88,0x21,0x30,0x42,0xff,0xff,0x00,0x45,0x10,0x21,0x30,0x43,0x00,0xff, +-0x10,0x60,0x00,0x02,0x00,0x02,0x12,0x02,0x24,0x42,0x00,0x01,0x30,0x53,0x00,0xff, +-0x01,0x12,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x10,0x00,0x43,0x10,0x21, +-0x80,0x44,0x00,0x07,0x00,0x00,0x00,0x00,0x10,0x80,0x00,0x4b,0x26,0x24,0x00,0x06, +-0x32,0x50,0xff,0xff,0x02,0x20,0x20,0x21,0x0c,0x00,0x1b,0x19,0x02,0x00,0x28,0x21, +-0x92,0x22,0x00,0x10,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x2e,0x3c,0x03,0xb0,0x08, +-0x3c,0x09,0x80,0x01,0x27,0x88,0x90,0x00,0xa6,0x32,0x00,0x0c,0x00,0x10,0x20,0xc0, +-0x00,0x90,0x20,0x21,0x00,0x04,0x20,0x80,0x00,0x88,0x20,0x21,0x94,0x82,0x00,0x04, +-0x3c,0x03,0xb0,0x08,0x3c,0x07,0xb0,0x03,0x00,0x02,0x28,0xc0,0x00,0xa2,0x10,0x21, +-0x00,0x02,0x10,0x80,0x00,0x48,0x10,0x21,0x00,0xa3,0x28,0x21,0x25,0x26,0x82,0x6c, +-0x34,0x03,0xff,0xff,0x34,0xe7,0x00,0x20,0xac,0xe6,0x00,0x00,0xa4,0x83,0x00,0x02, +-0xa4,0x43,0x00,0x00,0xac,0xa3,0x00,0x00,0x92,0x22,0x00,0x10,0x92,0x23,0x00,0x0a, +-0xa6,0x32,0x00,0x0e,0x02,0x62,0x10,0x21,0x14,0x60,0x00,0x05,0xa2,0x22,0x00,0x10, +-0x92,0x22,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xfe,0xa2,0x22,0x00,0x16, +-0x92,0x22,0x00,0x04,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x05,0x00,0x00,0x00,0x00, +-0x92,0x22,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xfd,0xa2,0x22,0x00,0x16, +-0x8f,0xbf,0x00,0x20,0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x28,0x96,0x22,0x00,0x0e,0x27,0x88,0x90,0x00,0x00,0x02,0x20,0xc0, +-0x00,0x82,0x20,0x21,0x00,0x04,0x20,0x80,0x00,0x88,0x20,0x21,0x94,0x82,0x00,0x04, +-0x3c,0x06,0xb0,0x03,0x3c,0x09,0x80,0x01,0x00,0x02,0x28,0xc0,0x00,0xa2,0x10,0x21, +-0x00,0x02,0x10,0x80,0x00,0xa3,0x28,0x21,0x00,0x48,0x10,0x21,0x34,0xc6,0x00,0x20, +-0x25,0x23,0x82,0x6c,0xac,0xc3,0x00,0x00,0xa4,0x50,0x00,0x00,0xac,0xb0,0x00,0x00, +-0x08,0x00,0x1b,0x97,0xa4,0x90,0x00,0x02,0x08,0x00,0x1b,0x8e,0x32,0x50,0xff,0xff, +-0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x6f,0x60,0x34,0x63,0x00,0x20, +-0xac,0x62,0x00,0x00,0x90,0x82,0x00,0x04,0x97,0xaa,0x00,0x12,0x00,0x80,0x60,0x21, +-0x30,0xa8,0xff,0xff,0x00,0x4a,0x20,0x23,0x34,0x09,0xff,0xff,0x30,0xcf,0xff,0xff, +-0x30,0xee,0xff,0xff,0x11,0x09,0x00,0x73,0xa1,0x84,0x00,0x04,0x00,0x0e,0xc0,0xc0, +-0x00,0x08,0x10,0xc0,0x00,0x48,0x10,0x21,0x03,0x0e,0x20,0x21,0x27,0x8d,0x90,0x00, +-0x00,0x04,0x20,0x80,0x00,0x02,0x10,0x80,0x00,0x4d,0x10,0x21,0x00,0x8d,0x20,0x21, +-0x94,0x86,0x00,0x02,0x94,0x43,0x00,0x04,0x3c,0x19,0x80,0x01,0xa4,0x46,0x00,0x02, +-0x00,0x03,0x28,0xc0,0x00,0xa3,0x18,0x21,0x94,0x87,0x00,0x02,0x3c,0x02,0xb0,0x08, +-0x00,0x03,0x18,0x80,0x00,0xa2,0x28,0x21,0x00,0x6d,0x18,0x21,0x27,0x22,0x82,0x6c, +-0x3c,0x01,0xb0,0x03,0xac,0x22,0x00,0x20,0xa4,0x66,0x00,0x00,0x10,0xe9,0x00,0x57, +-0xac,0xa6,0x00,0x00,0x01,0xe0,0x30,0x21,0x11,0x40,0x00,0x1d,0x00,0x00,0x48,0x21, +-0x01,0x40,0x38,0x21,0x27,0x8b,0x90,0x04,0x27,0x8a,0x90,0x10,0x00,0x06,0x40,0xc0, +-0x01,0x06,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0x6b,0x10,0x21,0x8c,0x44,0x00,0x18, +-0x00,0x6a,0x18,0x21,0x80,0x65,0x00,0x06,0x8c,0x82,0x00,0x00,0x00,0x00,0x00,0x00, +-0x30,0x42,0xff,0xff,0x00,0x45,0x10,0x21,0x30,0x44,0x00,0xff,0x00,0x02,0x12,0x02, +-0x01,0x22,0x18,0x21,0x24,0x62,0x00,0x01,0x14,0x80,0x00,0x02,0x30,0x49,0x00,0xff, +-0x30,0x69,0x00,0xff,0x01,0x06,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x4d,0x10,0x21, +-0x24,0xe7,0xff,0xff,0x94,0x46,0x00,0x02,0x14,0xe0,0xff,0xe9,0x00,0x06,0x40,0xc0, +-0x91,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x20,0x3c,0x06,0xb0,0x03, +-0xa5,0x8f,0x00,0x0c,0x03,0x0e,0x20,0x21,0x00,0x04,0x20,0x80,0x00,0x8d,0x20,0x21, +-0x94,0x82,0x00,0x04,0x3c,0x03,0xb0,0x08,0x3c,0x07,0xb0,0x03,0x00,0x02,0x28,0xc0, +-0x00,0xa2,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x4d,0x10,0x21,0x00,0xa3,0x28,0x21, +-0x27,0x26,0x82,0x6c,0x34,0x03,0xff,0xff,0x34,0xe7,0x00,0x20,0xac,0xe6,0x00,0x00, +-0xa4,0x83,0x00,0x02,0xa4,0x43,0x00,0x00,0xac,0xa3,0x00,0x00,0x91,0x82,0x00,0x10, +-0x91,0x83,0x00,0x04,0xa5,0x8e,0x00,0x0e,0x01,0x22,0x10,0x21,0x14,0x60,0x00,0x05, +-0xa1,0x82,0x00,0x10,0x91,0x82,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xfd, +-0xa1,0x82,0x00,0x16,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x95,0x82,0x00,0x0e, +-0x3c,0x03,0xb0,0x08,0x00,0x02,0x20,0xc0,0x00,0x82,0x20,0x21,0x00,0x04,0x20,0x80, +-0x00,0x8d,0x20,0x21,0x94,0x82,0x00,0x04,0x34,0xc6,0x00,0x20,0x27,0x27,0x82,0x6c, +-0x00,0x02,0x28,0xc0,0x00,0xa2,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0xa3,0x28,0x21, +-0x00,0x4d,0x10,0x21,0xac,0xc7,0x00,0x00,0xa4,0x8f,0x00,0x02,0xa4,0x4f,0x00,0x00, +-0xac,0xaf,0x00,0x00,0x08,0x00,0x1c,0x26,0x03,0x0e,0x20,0x21,0x08,0x00,0x1c,0x01, +-0xa5,0x88,0x00,0x02,0x00,0x0e,0xc0,0xc0,0x03,0x0e,0x10,0x21,0x00,0x02,0x10,0x80, +-0x27,0x8d,0x90,0x00,0x00,0x4d,0x10,0x21,0x94,0x43,0x00,0x02,0x30,0x84,0x00,0xff, +-0x14,0x80,0x00,0x05,0xa5,0x83,0x00,0x00,0x24,0x02,0xff,0xff,0x3c,0x19,0x80,0x01, +-0x08,0x00,0x1c,0x01,0xa5,0x82,0x00,0x02,0x08,0x00,0x1c,0x01,0x3c,0x19,0x80,0x01, +-0x3c,0x08,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0x78,0x35,0x08,0x00,0x20, +-0x24,0x42,0x71,0xa0,0xaf,0xb2,0x00,0x68,0xaf,0xb1,0x00,0x64,0xaf,0xb0,0x00,0x60, +-0xad,0x02,0x00,0x00,0xaf,0xbf,0x00,0x84,0xaf,0xbe,0x00,0x80,0xaf,0xb7,0x00,0x7c, +-0xaf,0xb6,0x00,0x78,0xaf,0xb5,0x00,0x74,0xaf,0xb4,0x00,0x70,0xaf,0xb3,0x00,0x6c, +-0xaf,0xa4,0x00,0x88,0x90,0x83,0x00,0x0a,0x27,0x82,0xb4,0x00,0xaf,0xa6,0x00,0x90, +-0x00,0x03,0x18,0x80,0x00,0x62,0x18,0x21,0x8c,0x63,0x00,0x00,0xaf,0xa7,0x00,0x94, +-0x27,0x86,0x90,0x04,0xaf,0xa3,0x00,0x1c,0x94,0x63,0x00,0x14,0x30,0xb1,0xff,0xff, +-0x24,0x08,0x00,0x01,0x00,0x03,0x20,0xc0,0xaf,0xa3,0x00,0x18,0x00,0x83,0x18,0x21, +-0xaf,0xa4,0x00,0x54,0x00,0x03,0x18,0x80,0x27,0x84,0x90,0x10,0x00,0x64,0x20,0x21, +-0x80,0x82,0x00,0x06,0x00,0x66,0x18,0x21,0x8c,0x66,0x00,0x18,0x24,0x42,0x00,0x02, +-0x00,0x02,0x1f,0xc2,0x8c,0xc4,0x00,0x08,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x43, +-0x00,0x02,0x10,0x40,0x00,0x04,0x2f,0xc2,0x00,0x04,0x1c,0x82,0x00,0xc2,0x38,0x21, +-0x00,0x04,0x24,0x42,0x8f,0xa2,0x00,0x1c,0x30,0x63,0x00,0x01,0x30,0x84,0x00,0x01, +-0xaf,0xa5,0x00,0x3c,0xaf,0xa3,0x00,0x34,0xaf,0xa4,0x00,0x38,0xaf,0xa0,0x00,0x40, +-0xaf,0xa0,0x00,0x44,0xaf,0xa0,0x00,0x50,0xaf,0xa8,0x00,0x20,0x80,0x42,0x00,0x12, +-0x8f,0xb2,0x00,0x18,0xaf,0xa2,0x00,0x28,0x8c,0xd0,0x00,0x0c,0x14,0xa0,0x01,0xe4, +-0x00,0x60,0x30,0x21,0x00,0x10,0x10,0x82,0x30,0x45,0x00,0x07,0x10,0xa0,0x00,0x11, +-0xaf,0xa0,0x00,0x30,0x8f,0xa4,0x00,0x98,0x27,0x82,0x80,0x1c,0x00,0x04,0x18,0x40, +-0x00,0x62,0x18,0x21,0x24,0xa2,0x00,0x06,0x8f,0xa5,0x00,0x20,0x94,0x64,0x00,0x00, +-0x00,0x45,0x10,0x04,0x00,0x44,0x00,0x1a,0x14,0x80,0x00,0x02,0x00,0x00,0x00,0x00, +-0x00,0x07,0x00,0x0d,0x00,0x00,0x10,0x12,0x24,0x42,0x00,0x20,0x30,0x42,0xff,0xfc, +-0xaf,0xa2,0x00,0x30,0x8f,0xa3,0x00,0x18,0x8f,0xa4,0x00,0x28,0x34,0x02,0xff,0xff, +-0xaf,0xa0,0x00,0x2c,0xaf,0xa2,0x00,0x48,0xaf,0xa3,0x00,0x4c,0x00,0x60,0xf0,0x21, +-0x00,0x00,0xb8,0x21,0x18,0x80,0x00,0x48,0xaf,0xa0,0x00,0x24,0x00,0x11,0x89,0x02, +-0xaf,0xb1,0x00,0x58,0x00,0x80,0xa8,0x21,0x00,0x12,0x10,0xc0,0x00,0x52,0x18,0x21, +-0x00,0x03,0x80,0x80,0x27,0x85,0x90,0x00,0x02,0x40,0x20,0x21,0x00,0x40,0xa0,0x21, +-0x02,0x05,0x10,0x21,0x94,0x56,0x00,0x02,0x0c,0x00,0x12,0x8b,0x00,0x00,0x28,0x21, +-0x90,0x42,0x00,0x00,0x24,0x03,0x00,0x08,0x30,0x42,0x00,0x0c,0x10,0x43,0x01,0x9e, +-0x24,0x04,0x00,0x01,0x24,0x02,0x00,0x01,0x10,0x82,0x01,0x7c,0x3c,0x02,0xb0,0x03, +-0x8f,0xa6,0x00,0x88,0x34,0x42,0x01,0x04,0x84,0xc5,0x00,0x0c,0x02,0x92,0x18,0x21, +-0x94,0x46,0x00,0x00,0x00,0x05,0x20,0xc0,0x00,0x85,0x20,0x21,0x00,0x03,0x18,0x80, +-0x27,0x82,0x90,0x10,0x27,0x85,0x90,0x08,0x00,0x65,0x28,0x21,0x00,0x62,0x18,0x21, +-0x80,0x71,0x00,0x05,0x80,0x73,0x00,0x04,0x8f,0xa3,0x00,0x88,0x30,0xd0,0xff,0xff, +-0x00,0x10,0x3a,0x03,0x32,0x08,0x00,0xff,0x27,0x82,0x90,0x20,0x00,0x04,0x20,0x80, +-0x80,0xa6,0x00,0x06,0x00,0x82,0x20,0x21,0xa4,0x67,0x00,0x44,0xa4,0x68,0x00,0x46, +-0x8c,0x84,0x00,0x00,0x38,0xc6,0x00,0x00,0x01,0x00,0x80,0x21,0x00,0x04,0x15,0x02, +-0x30,0x42,0x00,0x01,0x10,0x40,0x00,0x03,0x00,0xe6,0x80,0x0a,0x00,0x04,0x14,0x02, +-0x30,0x50,0x00,0x0f,0x12,0x20,0x01,0x50,0x02,0x40,0x20,0x21,0x02,0x71,0x10,0x21, +-0x00,0x50,0x10,0x2a,0x14,0x40,0x00,0xed,0x02,0x92,0x10,0x21,0x93,0x82,0x8b,0x71, +-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0xe0,0x02,0x92,0x28,0x21, +-0x26,0xe2,0x00,0x01,0x30,0x57,0xff,0xff,0x02,0x40,0xf0,0x21,0x26,0xb5,0xff,0xff, +-0x16,0xa0,0xff,0xbd,0x02,0xc0,0x90,0x21,0x16,0xe0,0x00,0xd0,0x00,0x00,0x00,0x00, +-0x8f,0xa3,0x00,0x98,0x00,0x00,0x00,0x00,0x2c,0x62,0x00,0x10,0x10,0x40,0x00,0x2e, +-0x00,0x00,0x00,0x00,0x8f,0xa4,0x00,0x24,0x00,0x00,0x00,0x00,0x18,0x80,0x00,0x2a, +-0x24,0x03,0x00,0x01,0x8f,0xa5,0x00,0x1c,0x27,0x84,0x90,0x04,0x94,0xb2,0x00,0x14, +-0xa0,0xa3,0x00,0x12,0x8f,0xa6,0x00,0x3c,0x00,0x12,0x10,0xc0,0x00,0x52,0x10,0x21, +-0x00,0x02,0x80,0x80,0x27,0x82,0x90,0x10,0x02,0x02,0x10,0x21,0x80,0x43,0x00,0x06, +-0x02,0x04,0x20,0x21,0x8c,0x85,0x00,0x18,0x24,0x63,0x00,0x02,0x00,0x03,0x17,0xc2, +-0x00,0x62,0x18,0x21,0x00,0x03,0x18,0x43,0x00,0x03,0x18,0x40,0x14,0xc0,0x00,0x0e, +-0x00,0xa3,0x38,0x21,0x27,0x82,0x90,0x00,0x02,0x02,0x10,0x21,0x94,0x43,0x00,0x06, +-0x8f,0xa8,0x00,0x1c,0x24,0x02,0x00,0x01,0xa5,0x03,0x00,0x1a,0x7b,0xbe,0x04,0x3c, +-0x7b,0xb6,0x03,0xfc,0x7b,0xb4,0x03,0xbc,0x7b,0xb2,0x03,0x7c,0x7b,0xb0,0x03,0x3c, +-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x88,0x8f,0xa4,0x00,0x98,0x8f,0xa5,0x00,0x38, +-0x8f,0xa6,0x00,0x34,0xaf,0xa0,0x00,0x10,0x0c,0x00,0x09,0x0a,0xaf,0xa0,0x00,0x14, +-0x08,0x00,0x1d,0x2d,0x00,0x00,0x00,0x00,0x8f,0xa3,0x00,0x44,0x93,0x82,0x81,0x58, +-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x61,0x30,0x69,0x00,0x03,0x8f,0xa4,0x00,0x24, +-0x8f,0xa5,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x85,0x10,0x2a,0x10,0x40,0x00,0x8f, +-0x00,0x00,0x00,0x00,0x8f,0xa6,0x00,0x1c,0x00,0x00,0x00,0x00,0x90,0xc4,0x00,0x04, +-0x00,0x00,0x00,0x00,0x30,0x83,0x00,0xff,0x00,0xa3,0x10,0x2a,0x10,0x40,0x00,0x87, +-0x00,0x00,0x00,0x00,0x8f,0xa8,0x00,0x24,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x83, +-0x00,0x65,0x10,0x23,0x00,0xa8,0x18,0x23,0x00,0x62,0x10,0x2a,0x14,0x40,0x00,0x7d, +-0x30,0x63,0x00,0xff,0x00,0x85,0x10,0x23,0x30,0x42,0x00,0xff,0xaf,0xa2,0x00,0x50, +-0x8f,0xa2,0x00,0x50,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x73,0x00,0x00,0xa8,0x21, +-0x27,0x8c,0x90,0x00,0x3c,0x0b,0x80,0xff,0x24,0x10,0x00,0x04,0x27,0x91,0x90,0x04, +-0x35,0x6b,0xff,0xff,0x3c,0x0d,0x7f,0x00,0x27,0x8e,0x90,0x10,0x01,0x80,0x78,0x21, +-0x00,0x12,0x30,0xc0,0x00,0xd2,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x4c,0x10,0x21, +-0x94,0x42,0x00,0x06,0x8f,0xa3,0x00,0x2c,0x8f,0xa4,0x00,0x30,0xaf,0xa2,0x00,0x44, +-0x8f,0xa5,0x00,0x44,0x30,0x49,0x00,0x03,0x02,0x09,0x10,0x23,0x30,0x42,0x00,0x03, +-0x00,0xa2,0x10,0x21,0x8f,0xa8,0x00,0x30,0x24,0x42,0x00,0x04,0x30,0x42,0xff,0xff, +-0x00,0x64,0x38,0x21,0x01,0x02,0x28,0x23,0x00,0x62,0x18,0x21,0x00,0x48,0x10,0x2b, +-0x10,0x40,0x00,0x52,0x00,0x00,0x20,0x21,0x30,0xe7,0xff,0xff,0x30,0xa4,0xff,0xff, +-0xaf,0xa7,0x00,0x2c,0x00,0xd2,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x51,0x18,0x21, +-0x8c,0x65,0x00,0x18,0x00,0x04,0x25,0x40,0x00,0x8d,0x20,0x24,0x8c,0xa8,0x00,0x04, +-0x00,0x4e,0x18,0x21,0x00,0x4f,0x50,0x21,0x01,0x0b,0x40,0x24,0x01,0x04,0x40,0x25, +-0xac,0xa8,0x00,0x04,0x8f,0xa4,0x00,0x98,0x8f,0xa2,0x00,0x50,0x26,0xb5,0x00,0x01, +-0xa0,0x64,0x00,0x00,0x8c,0xa4,0x00,0x08,0x00,0x00,0x00,0x00,0x04,0x81,0x00,0x0c, +-0x02,0xa2,0x30,0x2a,0x80,0x62,0x00,0x06,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x02, +-0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x43,0x00,0x02,0x10,0x40, +-0x00,0xa2,0x38,0x21,0x8f,0xa5,0x00,0x40,0x00,0x00,0x00,0x00,0xa4,0xe5,0x00,0x00, +-0x95,0x52,0x00,0x02,0x14,0xc0,0xff,0xc7,0x00,0x12,0x30,0xc0,0x8f,0xa4,0x00,0x24, +-0x8f,0xa5,0x00,0x50,0x8f,0xa6,0x00,0x1c,0x8f,0xa3,0x00,0x2c,0x00,0x85,0x80,0x21, +-0xa0,0xd0,0x00,0x12,0x00,0x09,0x10,0x23,0x30,0x42,0x00,0x03,0x8f,0xa8,0x00,0x88, +-0x00,0x62,0x10,0x23,0xa4,0xc2,0x00,0x1a,0x85,0x03,0x00,0x0c,0x00,0x00,0x00,0x00, +-0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x04, +-0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x18,0x00,0x00,0x00,0x00,0x8c,0x83,0x00,0x04, +-0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x10,0x14,0x60,0xff,0x74,0x02,0x00,0x10,0x21, +-0x8f,0xa3,0x00,0x54,0x8f,0xa4,0x00,0x18,0x8f,0xa5,0x00,0x24,0x00,0x64,0x10,0x21, +-0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x18,0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x00, +-0x10,0xa0,0x00,0x03,0x00,0x00,0x30,0x21,0x08,0x00,0x1d,0x33,0x02,0x00,0x10,0x21, +-0x93,0x82,0x80,0x10,0x00,0x00,0x28,0x21,0x00,0x00,0x38,0x21,0x0c,0x00,0x21,0x9a, +-0xaf,0xa2,0x00,0x10,0x08,0x00,0x1d,0x33,0x02,0x00,0x10,0x21,0x30,0x63,0xff,0xff, +-0x08,0x00,0x1d,0x85,0xaf,0xa3,0x00,0x2c,0x8f,0xa8,0x00,0x44,0x08,0x00,0x1d,0xa7, +-0x31,0x09,0x00,0x03,0x08,0x00,0x1d,0x60,0xaf,0xa3,0x00,0x50,0x8f,0xa6,0x00,0x44, +-0xaf,0xa0,0x00,0x50,0x08,0x00,0x1d,0xa7,0x30,0xc9,0x00,0x03,0x8f,0xa5,0x00,0x48, +-0x8f,0xa6,0x00,0x4c,0x8f,0xa4,0x00,0x1c,0x03,0xc0,0x38,0x21,0x0c,0x00,0x1b,0xd8, +-0xaf,0xb7,0x00,0x10,0x08,0x00,0x1d,0x10,0x00,0x00,0x00,0x00,0x00,0x05,0x28,0x80, +-0x27,0x82,0x90,0x00,0x00,0xa2,0x28,0x21,0x00,0x00,0x20,0x21,0x0c,0x00,0x01,0x49, +-0x00,0x00,0x00,0x00,0x08,0x00,0x1d,0x09,0x26,0xe2,0x00,0x01,0x00,0x02,0x80,0x80, +-0x27,0x83,0x90,0x10,0x8f,0xa4,0x00,0x1c,0x02,0x03,0x18,0x21,0x26,0x31,0x00,0x01, +-0x02,0x40,0x28,0x21,0x0c,0x00,0x1e,0xea,0xa0,0x71,0x00,0x05,0x14,0x40,0xff,0x13, +-0x00,0x00,0x00,0x00,0x16,0xe0,0x00,0x4d,0x03,0xc0,0x38,0x21,0x8f,0xa4,0x00,0x24, +-0x8f,0xa5,0x00,0x20,0x24,0x02,0x00,0x01,0x24,0x84,0x00,0x01,0xaf,0xb2,0x00,0x48, +-0xaf,0xb6,0x00,0x4c,0x02,0xc0,0xf0,0x21,0x10,0xa2,0x00,0x41,0xaf,0xa4,0x00,0x24, +-0x27,0x82,0x90,0x00,0x02,0x02,0x10,0x21,0x94,0x42,0x00,0x06,0x8f,0xa4,0x00,0x30, +-0xaf,0xa0,0x00,0x20,0xaf,0xa2,0x00,0x44,0x30,0x49,0x00,0x03,0x8f,0xa8,0x00,0x44, +-0x00,0x09,0x10,0x23,0x30,0x42,0x00,0x03,0x01,0x02,0x10,0x21,0x24,0x42,0x00,0x04, +-0x30,0x42,0xff,0xff,0x00,0x44,0x18,0x2b,0x10,0x60,0x00,0x2b,0x00,0x00,0x00,0x00, +-0x8f,0xa5,0x00,0x2c,0x00,0x82,0x10,0x23,0x00,0xa4,0x18,0x21,0x30,0x63,0xff,0xff, +-0x30,0x44,0xff,0xff,0xaf,0xa3,0x00,0x2c,0x02,0x92,0x28,0x21,0x00,0x05,0x28,0x80, +-0x27,0x82,0x90,0x04,0x00,0xa2,0x10,0x21,0x8c,0x46,0x00,0x18,0x3c,0x03,0x80,0xff, +-0x3c,0x02,0x7f,0x00,0x8c,0xc8,0x00,0x04,0x00,0x04,0x25,0x40,0x34,0x63,0xff,0xff, +-0x00,0x82,0x20,0x24,0x01,0x03,0x40,0x24,0x01,0x04,0x40,0x25,0xac,0xc8,0x00,0x04, +-0x8f,0xa8,0x00,0x98,0x27,0x82,0x90,0x10,0x00,0xa2,0x10,0x21,0xa0,0x48,0x00,0x00, +-0x8c,0xc4,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x04,0x27,0xc2,0x10,0x80,0xfe,0xdb, +-0xaf,0xa4,0x00,0x3c,0x80,0x42,0x00,0x06,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x02, +-0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x43,0x00,0x02,0x10,0x40, +-0x00,0xc2,0x38,0x21,0x8f,0xa2,0x00,0x40,0x00,0x00,0x00,0x00,0xa4,0xe2,0x00,0x00, +-0x08,0x00,0x1d,0x0c,0x26,0xb5,0xff,0xff,0x8f,0xa6,0x00,0x2c,0x00,0x00,0x20,0x21, +-0x00,0xc2,0x10,0x21,0x30,0x42,0xff,0xff,0x08,0x00,0x1e,0x1a,0xaf,0xa2,0x00,0x2c, +-0x8f,0xa6,0x00,0x1c,0x08,0x00,0x1e,0x04,0xa4,0xd2,0x00,0x14,0x8f,0xa5,0x00,0x48, +-0x8f,0xa6,0x00,0x4c,0x8f,0xa4,0x00,0x1c,0x0c,0x00,0x1b,0xd8,0xaf,0xb7,0x00,0x10, +-0x08,0x00,0x1d,0xfb,0x00,0x00,0xb8,0x21,0x0c,0x00,0x12,0x8b,0x00,0x00,0x28,0x21, +-0x00,0x40,0x18,0x21,0x94,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x42,0x08,0x00, +-0xa4,0x62,0x00,0x00,0x08,0x00,0x1d,0x00,0x02,0x71,0x10,0x21,0x02,0x92,0x18,0x21, +-0x00,0x03,0x80,0x80,0x27,0x82,0x90,0x04,0x02,0x02,0x10,0x21,0x8c,0x44,0x00,0x18, +-0x00,0x00,0x00,0x00,0x8c,0x83,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x10, +-0x10,0x60,0x00,0x09,0x24,0x06,0x00,0x01,0x93,0x82,0x8b,0x71,0x00,0x00,0x00,0x00, +-0x30,0x42,0x00,0x01,0x10,0x40,0xfe,0xa2,0x3c,0x04,0x00,0x80,0x27,0x85,0x90,0x00, +-0x08,0x00,0x1d,0xeb,0x02,0x05,0x28,0x21,0x27,0x83,0x90,0x18,0x27,0x82,0x90,0x10, +-0x02,0x03,0x18,0x21,0x02,0x02,0x10,0x21,0x90,0x64,0x00,0x00,0x90,0x45,0x00,0x05, +-0x93,0x83,0x80,0x10,0x00,0x00,0x38,0x21,0x0c,0x00,0x21,0x9a,0xaf,0xa3,0x00,0x10, +-0x08,0x00,0x1e,0x62,0x00,0x00,0x00,0x00,0x27,0x82,0x90,0x18,0x02,0x02,0x10,0x21, +-0x94,0x43,0x00,0x02,0x8f,0xa6,0x00,0x58,0x00,0x03,0x19,0x02,0x00,0x66,0x18,0x23, +-0x30,0x63,0x0f,0xff,0x28,0x62,0x00,0x20,0x10,0x40,0x00,0x06,0x28,0x62,0x00,0x40, +-0x8f,0xa8,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0x68,0x10,0x06,0x08,0x00,0x1c,0xd9, +-0x30,0x44,0x00,0x01,0x10,0x40,0x00,0x04,0x00,0x00,0x00,0x00,0x8f,0xa4,0x00,0x94, +-0x08,0x00,0x1e,0x83,0x00,0x64,0x10,0x06,0x08,0x00,0x1c,0xd9,0x00,0x00,0x20,0x21, +-0x8f,0xa4,0x00,0x98,0x8f,0xa5,0x00,0x38,0xaf,0xa0,0x00,0x10,0x0c,0x00,0x09,0x0a, +-0xaf,0xa8,0x00,0x14,0x30,0x42,0xff,0xff,0x08,0x00,0x1c,0xa9,0xaf,0xa2,0x00,0x40, +-0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x00,0x27,0xbd,0xff,0xe0,0x34,0x42,0x00,0x20, +-0x24,0x63,0x7a,0x50,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x18, +-0xac,0x43,0x00,0x00,0x90,0x82,0x00,0x0a,0x00,0x80,0x80,0x21,0x14,0x40,0x00,0x45, +-0x00,0x00,0x88,0x21,0x92,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x3c, +-0x00,0x00,0x00,0x00,0x12,0x20,0x00,0x18,0x00,0x00,0x00,0x00,0x92,0x02,0x00,0x16, +-0x92,0x05,0x00,0x0a,0x30,0x42,0x00,0xfc,0x10,0xa0,0x00,0x03,0xa2,0x02,0x00,0x16, +-0x34,0x42,0x00,0x01,0xa2,0x02,0x00,0x16,0x92,0x04,0x00,0x04,0x00,0x00,0x00,0x00, +-0x30,0x83,0x00,0xff,0x10,0x60,0x00,0x05,0x00,0x00,0x00,0x00,0x92,0x02,0x00,0x16, +-0x00,0x00,0x00,0x00,0x34,0x42,0x00,0x02,0xa2,0x02,0x00,0x16,0x10,0x60,0x00,0x0a, +-0x00,0x00,0x00,0x00,0x14,0xa0,0x00,0x08,0x00,0x00,0x00,0x00,0x96,0x02,0x00,0x00, +-0xa2,0x00,0x00,0x17,0xa6,0x02,0x00,0x14,0x8f,0xbf,0x00,0x18,0x7b,0xb0,0x00,0xbc, +-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x14,0x80,0x00,0x05,0x24,0x02,0x00,0x01, +-0x96,0x03,0x00,0x06,0xa2,0x02,0x00,0x17,0x08,0x00,0x1e,0xbe,0xa6,0x03,0x00,0x14, +-0x96,0x04,0x00,0x00,0x96,0x05,0x00,0x06,0x27,0x86,0x90,0x00,0x00,0x04,0x10,0xc0, +-0x00,0x05,0x18,0xc0,0x00,0x44,0x10,0x21,0x00,0x65,0x18,0x21,0x00,0x02,0x10,0x80, +-0x00,0x03,0x18,0x80,0x00,0x66,0x18,0x21,0x00,0x46,0x10,0x21,0x8c,0x65,0x00,0x08, +-0x8c,0x44,0x00,0x08,0x0c,0x00,0x12,0x7c,0x00,0x00,0x00,0x00,0x30,0x43,0x00,0xff, +-0x10,0x60,0x00,0x04,0xa2,0x02,0x00,0x17,0x96,0x02,0x00,0x06,0x08,0x00,0x1e,0xbe, +-0xa6,0x02,0x00,0x14,0x96,0x02,0x00,0x00,0x08,0x00,0x1e,0xbe,0xa6,0x02,0x00,0x14, +-0x96,0x05,0x00,0x00,0x0c,0x00,0x1e,0xea,0x02,0x00,0x20,0x21,0x08,0x00,0x1e,0xa5, +-0x02,0x22,0x88,0x21,0x94,0x85,0x00,0x06,0x0c,0x00,0x1e,0xea,0x00,0x00,0x00,0x00, +-0x08,0x00,0x1e,0xa1,0x00,0x40,0x88,0x21,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00, +-0x34,0x63,0x00,0x20,0x24,0x42,0x7b,0xa8,0x27,0xbd,0xff,0xf0,0xac,0x62,0x00,0x00, +-0x00,0x00,0x10,0x21,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x10,0x3c,0x03,0xb0,0x03, +-0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x7b,0xcc,0xac,0x62,0x00,0x00, +-0x90,0x89,0x00,0x0a,0x00,0x80,0x30,0x21,0x11,0x20,0x00,0x05,0x00,0xa0,0x50,0x21, +-0x90,0x82,0x00,0x17,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x1b,0x00,0x00,0x00,0x00, +-0x90,0xc7,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0xe0,0x00,0x1b,0x00,0x00,0x00,0x00, +-0x94,0xc8,0x00,0x00,0x27,0x83,0x90,0x00,0x93,0x85,0x8b,0x70,0x00,0x08,0x10,0xc0, +-0x00,0x48,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x08, +-0x00,0xe5,0x28,0x2b,0x10,0xa0,0x00,0x06,0x01,0x44,0x18,0x23,0x8f,0x82,0x8b,0x88, +-0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x2b,0x10,0x40,0x00,0x05,0x00,0x00,0x00,0x00, +-0x24,0x03,0x00,0x10,0xa4,0xc8,0x00,0x14,0x03,0xe0,0x00,0x08,0x00,0x60,0x10,0x21, +-0x11,0x20,0x00,0x05,0x00,0x00,0x00,0x00,0x94,0xc2,0x00,0x06,0x24,0x03,0x00,0x08, +-0x08,0x00,0x1f,0x16,0xa4,0xc2,0x00,0x14,0x08,0x00,0x1f,0x16,0x00,0x00,0x18,0x21, +-0x27,0xbd,0xff,0xc8,0xaf,0xb5,0x00,0x2c,0xaf,0xb4,0x00,0x28,0xaf,0xb3,0x00,0x24, +-0xaf,0xb0,0x00,0x18,0xaf,0xbf,0x00,0x30,0xaf,0xb2,0x00,0x20,0xaf,0xb1,0x00,0x1c, +-0x94,0x91,0x00,0x06,0x00,0x80,0xa0,0x21,0x3c,0x02,0x80,0x00,0x3c,0x04,0xb0,0x03, +-0x00,0x11,0xa8,0xc0,0x34,0x84,0x00,0x20,0x24,0x42,0x7c,0x80,0x02,0xb1,0x48,0x21, +-0xac,0x82,0x00,0x00,0x00,0x09,0x48,0x80,0x24,0x03,0x00,0x01,0x27,0x82,0x90,0x10, +-0xa2,0x83,0x00,0x12,0x01,0x22,0x10,0x21,0x27,0x84,0x90,0x04,0x01,0x24,0x20,0x21, +-0x80,0x48,0x00,0x06,0x8c,0x8a,0x00,0x18,0x27,0x83,0x90,0x20,0x01,0x23,0x48,0x21, +-0x8d,0x24,0x00,0x00,0x25,0x08,0x00,0x02,0x8d,0x42,0x00,0x00,0x8d,0x49,0x00,0x04, +-0x00,0x08,0x17,0xc2,0x8d,0x43,0x00,0x08,0x01,0x02,0x40,0x21,0x00,0x04,0x25,0xc2, +-0x00,0x08,0x40,0x43,0x30,0x84,0x00,0x01,0x00,0x03,0x1f,0xc2,0x00,0x08,0x40,0x40, +-0x00,0xe0,0x80,0x21,0x00,0x64,0x18,0x24,0x00,0x09,0x49,0x42,0x01,0x48,0x10,0x21, +-0x00,0xa0,0x98,0x21,0x00,0xa0,0x20,0x21,0x00,0x40,0x38,0x21,0x02,0x00,0x28,0x21, +-0x14,0x60,0x00,0x19,0x31,0x29,0x00,0x01,0x94,0x42,0x00,0x00,0x02,0xb1,0x88,0x21, +-0x02,0x00,0x28,0x21,0x00,0x11,0x88,0x80,0x27,0x90,0x90,0x00,0x02,0x30,0x80,0x21, +-0x96,0x03,0x00,0x06,0x30,0x52,0xff,0xff,0x02,0x60,0x20,0x21,0x00,0x60,0x30,0x21, +-0xa6,0x83,0x00,0x1a,0x27,0x82,0x90,0x08,0x0c,0x00,0x08,0xe3,0x02,0x22,0x88,0x21, +-0x00,0x52,0x10,0x21,0x96,0x03,0x00,0x06,0xa6,0x22,0x00,0x04,0x8f,0xbf,0x00,0x30, +-0x7b,0xb4,0x01,0x7c,0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc,0x00,0x60,0x10,0x21, +-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x38,0xaf,0xa9,0x00,0x10,0x0c,0x00,0x09,0x0a, +-0xaf,0xa0,0x00,0x14,0x08,0x00,0x1f,0x54,0x02,0xb1,0x88,0x21,0x27,0xbd,0xff,0xc0, +-0xaf,0xbe,0x00,0x38,0xaf,0xb7,0x00,0x34,0xaf,0xb6,0x00,0x30,0xaf,0xb5,0x00,0x2c, +-0xaf,0xb3,0x00,0x24,0xaf,0xb1,0x00,0x1c,0xaf,0xbf,0x00,0x3c,0xaf,0xb4,0x00,0x28, +-0xaf,0xb2,0x00,0x20,0xaf,0xb0,0x00,0x18,0x94,0x90,0x00,0x00,0x3c,0x08,0xb0,0x03, +-0x35,0x08,0x00,0x20,0x00,0x10,0x10,0xc0,0x00,0x50,0x18,0x21,0x00,0x40,0x88,0x21, +-0x3c,0x02,0x80,0x00,0x00,0x03,0x48,0x80,0x24,0x42,0x7d,0xbc,0x00,0x80,0x98,0x21, +-0x27,0x84,0x90,0x10,0x01,0x24,0x20,0x21,0x93,0xb7,0x00,0x53,0xad,0x02,0x00,0x00, +-0x80,0x83,0x00,0x06,0x27,0x82,0x90,0x04,0x01,0x22,0x10,0x21,0x8c,0x44,0x00,0x18, +-0x24,0x63,0x00,0x02,0x00,0x03,0x17,0xc2,0x8c,0x88,0x00,0x08,0x00,0x62,0x18,0x21, +-0x00,0x03,0x18,0x43,0x00,0x03,0x18,0x40,0xaf,0xa7,0x00,0x4c,0x2c,0xa2,0x00,0x10, +-0x00,0xa0,0xa8,0x21,0x00,0x83,0x50,0x21,0x00,0x08,0x47,0xc2,0x00,0xc0,0x58,0x21, +-0x00,0x00,0xb0,0x21,0x8c,0x92,0x00,0x0c,0x14,0x40,0x00,0x13,0x00,0x00,0xf0,0x21, +-0x92,0x67,0x00,0x04,0x24,0x14,0x00,0x01,0x12,0x87,0x00,0x10,0x02,0x30,0x10,0x21, +-0x27,0x83,0x90,0x18,0x01,0x23,0x18,0x21,0x80,0x64,0x00,0x00,0x27,0x83,0xb5,0x70, +-0x00,0x04,0x11,0x00,0x00,0x44,0x10,0x23,0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x23, +-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x04,0x00,0x00,0x00,0x00, +-0x10,0x80,0x00,0x23,0x00,0x00,0x00,0x00,0x02,0x30,0x10,0x21,0x00,0x02,0x80,0x80, +-0x24,0x04,0x00,0x01,0x27,0x83,0x90,0x20,0xa2,0x64,0x00,0x12,0x02,0x03,0x18,0x21, +-0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0xc2,0x30,0x42,0x00,0x01, +-0x01,0x02,0x10,0x24,0x14,0x40,0x00,0x0e,0x02,0xa0,0x20,0x21,0x27,0x82,0x90,0x00, +-0x02,0x02,0x10,0x21,0x94,0x43,0x00,0x06,0x00,0x00,0x00,0x00,0xa6,0x63,0x00,0x1a, +-0x94,0x42,0x00,0x06,0x7b,0xbe,0x01,0xfc,0x7b,0xb6,0x01,0xbc,0x7b,0xb4,0x01,0x7c, +-0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x40, +-0x8f,0xa5,0x00,0x4c,0x01,0x60,0x30,0x21,0x01,0x40,0x38,0x21,0xaf,0xa0,0x00,0x10, +-0x0c,0x00,0x09,0x0a,0xaf,0xa0,0x00,0x14,0x08,0x00,0x1f,0xbb,0x00,0x00,0x00,0x00, +-0x27,0x83,0x90,0x20,0x01,0x23,0x18,0x21,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x02,0x15,0xc2,0x30,0x42,0x00,0x01,0x01,0x02,0x10,0x24,0x14,0x40,0x00,0xaf, +-0x00,0xa0,0x20,0x21,0x32,0x4f,0x00,0x03,0x00,0x12,0x10,0x82,0x25,0xe3,0x00,0x0d, +-0x30,0x45,0x00,0x07,0x00,0x74,0x78,0x04,0x10,0xa0,0x00,0x0e,0x00,0x00,0x90,0x21, +-0x27,0x82,0x80,0x1c,0x00,0x15,0x18,0x40,0x00,0x62,0x18,0x21,0x94,0x64,0x00,0x00, +-0x24,0xa2,0x00,0x06,0x00,0x54,0x10,0x04,0x00,0x44,0x00,0x1a,0x14,0x80,0x00,0x02, +-0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0d,0x00,0x00,0x10,0x12,0x24,0x42,0x00,0x20, +-0x30,0x52,0xff,0xfc,0x02,0x30,0x10,0x21,0x27,0x83,0x90,0x10,0x00,0x02,0x10,0x80, +-0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x03,0x00,0x00,0x00,0x00,0x30,0x83,0x00,0xff, +-0x2c,0x62,0x00,0x0c,0x14,0x40,0x00,0x04,0x2c,0x62,0x00,0x19,0x30,0x82,0x00,0x0f, +-0x24,0x43,0x00,0x0c,0x2c,0x62,0x00,0x19,0x10,0x40,0x00,0x19,0x24,0x0e,0x00,0x20, +-0x24,0x62,0xff,0xe9,0x2c,0x42,0x00,0x02,0x14,0x40,0x00,0x15,0x24,0x0e,0x00,0x10, +-0x24,0x62,0xff,0xeb,0x2c,0x42,0x00,0x02,0x14,0x40,0x00,0x11,0x24,0x0e,0x00,0x08, +-0x24,0x02,0x00,0x14,0x10,0x62,0x00,0x0e,0x24,0x0e,0x00,0x02,0x24,0x62,0xff,0xef, +-0x2c,0x42,0x00,0x03,0x14,0x40,0x00,0x0a,0x24,0x0e,0x00,0x10,0x24,0x62,0xff,0xf1, +-0x2c,0x42,0x00,0x02,0x14,0x40,0x00,0x06,0x24,0x0e,0x00,0x08,0x24,0x62,0xff,0xf3, +-0x2c,0x42,0x00,0x02,0x24,0x0e,0x00,0x04,0x24,0x03,0x00,0x02,0x00,0x62,0x70,0x0a, +-0x30,0xe2,0x00,0xff,0x00,0x00,0x48,0x21,0x00,0x00,0x68,0x21,0x10,0x40,0x00,0x6d, +-0x00,0x00,0x58,0x21,0x3c,0x14,0x80,0xff,0x27,0x99,0x90,0x00,0x01,0xf2,0xc0,0x23, +-0x36,0x94,0xff,0xff,0x01,0xc9,0x10,0x2a,0x14,0x40,0x00,0x64,0x24,0x03,0x00,0x04, +-0x00,0x10,0x28,0xc0,0x00,0xb0,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x59,0x10,0x21, +-0x94,0x56,0x00,0x06,0x00,0x00,0x00,0x00,0x32,0xcc,0x00,0x03,0x00,0x6c,0x10,0x23, +-0x30,0x42,0x00,0x03,0x02,0xc2,0x10,0x21,0x24,0x42,0x00,0x04,0x30,0x51,0xff,0xff, +-0x02,0x32,0x18,0x2b,0x10,0x60,0x00,0x4d,0x01,0xf1,0x10,0x23,0x02,0x51,0x10,0x23, +-0x01,0x78,0x18,0x2b,0x10,0x60,0x00,0x34,0x30,0x44,0xff,0xff,0x29,0x22,0x00,0x40, +-0x10,0x40,0x00,0x31,0x01,0x72,0x18,0x21,0x25,0x22,0x00,0x01,0x00,0x02,0x16,0x00, +-0x00,0x02,0x4e,0x03,0x00,0xb0,0x10,0x21,0x00,0x02,0x30,0x80,0x27,0x82,0x90,0x04, +-0x30,0x6b,0xff,0xff,0x00,0xc2,0x18,0x21,0x8c,0x67,0x00,0x18,0x00,0x04,0x25,0x40, +-0x3c,0x03,0x7f,0x00,0x8c,0xe2,0x00,0x04,0x00,0x83,0x20,0x24,0x27,0x83,0x90,0x10, +-0x00,0x54,0x10,0x24,0x00,0xc3,0x28,0x21,0x00,0x44,0x10,0x25,0xac,0xe2,0x00,0x04, +-0x16,0xe0,0x00,0x02,0xa0,0xb5,0x00,0x00,0xa0,0xb5,0x00,0x03,0x27,0x84,0x90,0x20, +-0x00,0xc4,0x18,0x21,0x8c,0x62,0x00,0x00,0x8c,0xe8,0x00,0x08,0x00,0x02,0x15,0xc2, +-0x00,0x08,0x47,0xc2,0x30,0x42,0x00,0x01,0x01,0x02,0x10,0x24,0x10,0x40,0x00,0x0a, +-0x00,0x00,0x00,0x00,0x80,0xa2,0x00,0x06,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x02, +-0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x43,0x00,0x02,0x10,0x40, +-0x00,0xe2,0x50,0x21,0xa5,0x5e,0x00,0x00,0x92,0x62,0x00,0x04,0x25,0xad,0x00,0x01, +-0x27,0x84,0x90,0x00,0x00,0xc4,0x18,0x21,0x01,0xa2,0x10,0x2a,0x94,0x70,0x00,0x02, +-0x14,0x40,0xff,0xb8,0x00,0x00,0x00,0x00,0x96,0x63,0x00,0x14,0x00,0x0c,0x10,0x23, +-0xa2,0x69,0x00,0x12,0x30,0x42,0x00,0x03,0x01,0x62,0x10,0x23,0x00,0x03,0x80,0xc0, +-0x8f,0xa5,0x00,0x4c,0x30,0x4b,0xff,0xff,0x02,0x03,0x80,0x21,0x27,0x82,0x90,0x08, +-0x00,0x10,0x80,0x80,0xa6,0x6b,0x00,0x1a,0x02,0xa0,0x20,0x21,0x01,0x60,0x30,0x21, +-0x01,0x60,0x88,0x21,0x0c,0x00,0x08,0xe3,0x02,0x02,0x80,0x21,0x00,0x5e,0x10,0x21, +-0xa6,0x02,0x00,0x04,0x08,0x00,0x1f,0xc1,0x02,0x20,0x10,0x21,0x01,0x62,0x10,0x2b, +-0x10,0x40,0xff,0xe9,0x00,0x00,0x20,0x21,0x29,0x22,0x00,0x40,0x10,0x40,0xff,0xe6, +-0x01,0x71,0x18,0x21,0x08,0x00,0x20,0x37,0x25,0x22,0x00,0x01,0x08,0x00,0x20,0x66, +-0x32,0xcc,0x00,0x03,0x08,0x00,0x20,0x66,0x00,0x00,0x60,0x21,0x8f,0xa5,0x00,0x4c, +-0x01,0x40,0x38,0x21,0xaf,0xa0,0x00,0x10,0x0c,0x00,0x09,0x0a,0xaf,0xb4,0x00,0x14, +-0x92,0x67,0x00,0x04,0x08,0x00,0x1f,0xd9,0x30,0x5e,0xff,0xff,0x30,0x84,0xff,0xff, +-0x00,0x04,0x30,0xc0,0x00,0xc4,0x20,0x21,0x00,0x04,0x20,0x80,0x27,0x82,0x90,0x00, +-0x3c,0x03,0xb0,0x08,0x30,0xa5,0xff,0xff,0x00,0x82,0x20,0x21,0x00,0xc3,0x30,0x21, +-0xac,0xc5,0x00,0x00,0x03,0xe0,0x00,0x08,0xa4,0x85,0x00,0x00,0x30,0x84,0xff,0xff, +-0x00,0x04,0x30,0xc0,0x00,0xc4,0x30,0x21,0x27,0x88,0x90,0x00,0x00,0x06,0x30,0x80, +-0x00,0xc8,0x30,0x21,0x94,0xc3,0x00,0x04,0x3c,0x02,0xb0,0x08,0x3c,0x07,0xb0,0x03, +-0x00,0x03,0x20,0xc0,0x00,0x83,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0x82,0x20,0x21, +-0x3c,0x02,0x80,0x01,0x30,0xa5,0xff,0xff,0x00,0x68,0x18,0x21,0x34,0xe7,0x00,0x20, +-0x24,0x42,0x82,0x6c,0xac,0xe2,0x00,0x00,0xa4,0xc5,0x00,0x02,0xa4,0x65,0x00,0x00, +-0x03,0xe0,0x00,0x08,0xac,0x85,0x00,0x00,0x30,0x84,0xff,0xff,0x00,0x04,0x10,0xc0, +-0x00,0x44,0x10,0x21,0x27,0x89,0x90,0x00,0x00,0x02,0x10,0x80,0x00,0x49,0x10,0x21, +-0x97,0x83,0x8f,0xf0,0x94,0x4a,0x00,0x04,0x3c,0x02,0xb0,0x08,0x00,0x03,0x38,0xc0, +-0x00,0x0a,0x40,0xc0,0x00,0xe3,0x18,0x21,0x01,0x0a,0x28,0x21,0x00,0xe2,0x38,0x21, +-0x01,0x02,0x40,0x21,0x00,0x03,0x18,0x80,0x00,0x05,0x28,0x80,0x3c,0x06,0xb0,0x03, +-0x3c,0x02,0x80,0x01,0x00,0xa9,0x28,0x21,0x00,0x69,0x18,0x21,0x34,0xc6,0x00,0x20, +-0x34,0x09,0xff,0xff,0x24,0x42,0x82,0xc8,0xac,0xc2,0x00,0x00,0xa4,0x64,0x00,0x00, +-0xac,0xe4,0x00,0x00,0xa4,0xa9,0x00,0x00,0xad,0x09,0x00,0x00,0xa7,0x8a,0x8f,0xf0, +-0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x01, +-0x34,0x63,0x00,0x20,0x24,0x42,0x83,0x48,0x3c,0x04,0xb0,0x03,0xac,0x62,0x00,0x00, +-0x34,0x84,0x01,0x10,0x8c,0x82,0x00,0x00,0x97,0x83,0x81,0x60,0x30,0x42,0xff,0xff, +-0x10,0x62,0x00,0x16,0x24,0x0a,0x00,0x01,0xa7,0x82,0x81,0x60,0xaf,0x80,0xb4,0x50, +-0x00,0x40,0x28,0x21,0x24,0x06,0x00,0x01,0x27,0x84,0xb4,0x54,0x25,0x43,0xff,0xff, +-0x00,0x66,0x10,0x04,0x00,0xa2,0x10,0x24,0x14,0x40,0x00,0x07,0x00,0x00,0x00,0x00, +-0x8c,0x83,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x66,0x10,0x04,0x00,0xa2,0x10,0x24, +-0x38,0x42,0x00,0x00,0x01,0x42,0x18,0x0a,0x25,0x4a,0x00,0x01,0x2d,0x42,0x00,0x14, +-0xac,0x83,0x00,0x00,0x14,0x40,0xff,0xf1,0x24,0x84,0x00,0x04,0x3c,0x0b,0xb0,0x03, +-0x00,0x00,0x50,0x21,0x3c,0x0c,0x80,0x00,0x27,0x89,0xb4,0xa0,0x35,0x6b,0x01,0x20, +-0x8d,0x68,0x00,0x00,0x8d,0x23,0x00,0x04,0x01,0x0c,0x10,0x24,0x00,0x02,0x17,0xc2, +-0x11,0x03,0x00,0x37,0xa1,0x22,0x00,0xdc,0xa1,0x20,0x00,0xd5,0xa1,0x20,0x00,0xd6, +-0x01,0x20,0x30,0x21,0x00,0x00,0x38,0x21,0x00,0x00,0x28,0x21,0x01,0x20,0x20,0x21, +-0x00,0xa8,0x10,0x06,0x30,0x42,0x00,0x01,0x10,0xe0,0x00,0x10,0xa0,0x82,0x00,0x0a, +-0x90,0x82,0x00,0x07,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x31,0x24,0xa2,0xff,0xff, +-0xa0,0x82,0x00,0x08,0x90,0x82,0x00,0x0a,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x09, +-0x00,0x00,0x00,0x00,0x90,0x83,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0x40, +-0x00,0x43,0x10,0x21,0x00,0x46,0x10,0x21,0xa0,0x45,0x00,0x09,0x90,0x82,0x00,0x0a, +-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x07,0x00,0x00,0x00,0x00,0x14,0xe0,0x00,0x04, +-0x00,0x00,0x00,0x00,0xa0,0xc5,0x00,0xd5,0x24,0x07,0x00,0x01,0xa0,0x85,0x00,0x08, +-0xa0,0xc5,0x00,0xd6,0x24,0xa5,0x00,0x01,0x2c,0xa2,0x00,0x1c,0x14,0x40,0xff,0xe0, +-0x24,0x84,0x00,0x03,0x90,0xc4,0x00,0xd5,0x00,0x00,0x28,0x21,0x00,0xa4,0x10,0x2b, +-0x10,0x40,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0xc0,0x18,0x21,0xa0,0x64,0x00,0x08, +-0x90,0xc2,0x00,0xd5,0x24,0xa5,0x00,0x01,0xa0,0x62,0x00,0x09,0x90,0xc4,0x00,0xd5, +-0x00,0x00,0x00,0x00,0x00,0xa4,0x10,0x2b,0x14,0x40,0xff,0xf8,0x24,0x63,0x00,0x03, +-0x25,0x4a,0x00,0x01,0x2d,0x42,0x00,0x08,0xad,0x28,0x00,0x04,0x25,0x6b,0x00,0x04, +-0x14,0x40,0xff,0xbf,0x25,0x29,0x00,0xec,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +-0x90,0x82,0x00,0x05,0x08,0x00,0x21,0x0d,0xa0,0x82,0x00,0x08,0x97,0x85,0x8b,0x7a, +-0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x01,0x27,0xbd,0xff,0xe8,0x34,0x63,0x00,0x20, +-0x24,0x42,0x84,0xfc,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0xac,0x62,0x00,0x00, +-0x30,0x90,0x00,0xff,0x00,0x05,0x28,0x42,0x00,0x00,0x48,0x21,0x27,0x8f,0xb4,0xa4, +-0x00,0x00,0x50,0x21,0x00,0x00,0x58,0x21,0x27,0x98,0xb5,0x84,0x27,0x99,0xb5,0x80, +-0x27,0x8e,0xb5,0x7e,0x27,0x8c,0xb4,0xa8,0x27,0x8d,0xb5,0x00,0x27,0x88,0xb5,0x78, +-0x00,0x0a,0x18,0x80,0x01,0x6f,0x10,0x21,0xac,0x40,0x00,0x00,0xac,0x45,0x00,0x58, +-0x00,0x6e,0x20,0x21,0x00,0x78,0x10,0x21,0xa1,0x00,0xff,0xfc,0xad,0x00,0x00,0x00, +-0xa1,0x00,0x00,0x04,0xa1,0x00,0x00,0x05,0xad,0x00,0xff,0xf8,0x00,0x79,0x18,0x21, +-0x24,0x06,0x00,0x01,0x24,0xc6,0xff,0xff,0xa0,0x80,0x00,0x00,0xa4,0x60,0x00,0x00, +-0xac,0x40,0x00,0x00,0x24,0x63,0x00,0x02,0x24,0x42,0x00,0x04,0x04,0xc1,0xff,0xf9, +-0x24,0x84,0x00,0x01,0x00,0x0a,0x10,0x80,0x00,0x4d,0x20,0x21,0x00,0x00,0x30,0x21, +-0x00,0x4c,0x18,0x21,0x27,0x87,0x81,0x64,0x8c,0xe2,0x00,0x00,0x24,0xe7,0x00,0x04, +-0xac,0x82,0x00,0x00,0xa0,0x66,0x00,0x00,0xa0,0x66,0x00,0x01,0x24,0xc6,0x00,0x01, +-0x28,0xc2,0x00,0x1c,0xa0,0x60,0x00,0x02,0x24,0x84,0x00,0x04,0x14,0x40,0xff,0xf6, +-0x24,0x63,0x00,0x03,0x25,0x29,0x00,0x01,0x29,0x22,0x00,0x08,0x25,0x4a,0x00,0x3b, +-0x25,0x08,0x00,0xec,0x14,0x40,0xff,0xd6,0x25,0x6b,0x00,0xec,0xa7,0x80,0x81,0x60, +-0x00,0x00,0x48,0x21,0x27,0x83,0xb4,0x50,0xac,0x69,0x00,0x00,0x25,0x29,0x00,0x01, +-0x29,0x22,0x00,0x0c,0x14,0x40,0xff,0xfc,0x24,0x63,0x00,0x04,0x0c,0x00,0x20,0xd2, +-0x00,0x00,0x00,0x00,0x2e,0x04,0x00,0x14,0x27,0x83,0xb4,0xa0,0x24,0x09,0x00,0x07, +-0x10,0x80,0x00,0x0a,0x00,0x00,0x00,0x00,0x90,0x62,0x00,0xd5,0x25,0x29,0xff,0xff, +-0xa0,0x62,0x00,0x00,0x05,0x21,0xff,0xfa,0x24,0x63,0x00,0xec,0x8f,0xbf,0x00,0x14, +-0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x90,0x62,0x00,0xd6, +-0x08,0x00,0x21,0x90,0x25,0x29,0xff,0xff,0x30,0x84,0x00,0xff,0x00,0x04,0x11,0x00, +-0x00,0x44,0x10,0x23,0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x23,0x00,0x02,0x10,0x80, +-0x27,0x83,0xb4,0xa0,0x00,0x43,0x60,0x21,0x3c,0x04,0xb0,0x03,0x3c,0x02,0x80,0x01, +-0x34,0x84,0x00,0x20,0x24,0x42,0x86,0x68,0x30,0xc6,0x00,0xff,0x93,0xaa,0x00,0x13, +-0x30,0xa5,0x00,0xff,0x30,0xe7,0x00,0xff,0xac,0x82,0x00,0x00,0x10,0xc0,0x00,0xe8, +-0x25,0x8f,0x00,0xd0,0x91,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x42,0xff,0xfc, +-0x2c,0x43,0x00,0x18,0x10,0x60,0x00,0xc7,0x3c,0x03,0x80,0x01,0x00,0x02,0x10,0x80, +-0x24,0x63,0x02,0x90,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x80,0x00,0x08,0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x30,0x14,0x40,0x00,0x1c, +-0x00,0x00,0x00,0x00,0x10,0xa0,0x00,0x17,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +-0x10,0xa2,0x00,0x11,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x0c, +-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x03,0x10,0xa2,0x00,0x06,0x00,0x00,0x00,0x00, +-0x8d,0x82,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x42,0xff,0xe0,0x03,0xe0,0x00,0x08, +-0xad,0x82,0x00,0xd0,0x8d,0x82,0x00,0xd0,0x08,0x00,0x21,0xcb,0x24,0x42,0xff,0xe8, +-0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x21,0xcb, +-0x24,0x42,0x00,0x01,0x8d,0x82,0x00,0xd0,0x08,0x00,0x21,0xcb,0x24,0x42,0x00,0x02, +-0x10,0xa0,0xff,0xf9,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x0a, +-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xe9,0x00,0x00,0x00,0x00, +-0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0xe6,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0, +-0x08,0x00,0x21,0xcb,0x24,0x42,0xff,0xd0,0x8d,0x82,0x00,0xd0,0x08,0x00,0x21,0xcb, +-0x24,0x42,0xff,0xfc,0x10,0xa0,0xff,0xeb,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +-0x10,0xa2,0xff,0xe5,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xe0, +-0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xdb,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0, +-0x08,0x00,0x21,0xcb,0x24,0x42,0xff,0xf8,0x2d,0x42,0x00,0x19,0x14,0x40,0xff,0xc5, +-0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xdb,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +-0x10,0xa2,0xff,0xd5,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xd0, +-0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0xf1,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0, +-0x08,0x00,0x21,0xcb,0x24,0x42,0xff,0xf0,0x2d,0x42,0x00,0x1b,0x10,0x40,0xff,0xf1, +-0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xcb,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +-0x10,0xa2,0xff,0xc5,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x14,0xa2,0xff,0xb5, +-0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x21,0xcb,0x24,0x42,0xff,0xf4, +-0x2d,0x42,0x00,0x1e,0x10,0x40,0xff,0xe3,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xbd, +-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xb5,0x24,0x02,0x00,0x02, +-0x10,0xa2,0xff,0xd6,0x00,0x00,0x00,0x00,0x08,0x00,0x21,0xc6,0x24,0x02,0x00,0x03, +-0x2d,0x42,0x00,0x23,0x10,0x40,0xff,0xd7,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xae, +-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xa9,0x24,0x02,0x00,0x02, +-0x14,0xa2,0xff,0xb7,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x03,0x00,0x00,0x00,0x00, +-0x2d,0x42,0x00,0x25,0x10,0x40,0xff,0xcb,0x00,0x00,0x00,0x00,0x08,0x00,0x21,0xd8, +-0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x16,0x14,0x40,0x00,0x0e,0x00,0x00,0x00,0x00, +-0x10,0xa0,0xff,0xa0,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x9a, +-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x95,0x24,0x02,0x00,0x03, +-0x14,0xa2,0xff,0xb6,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x21,0xcb, +-0x24,0x42,0xff,0xfa,0x10,0xa0,0xff,0x93,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +-0x10,0xa2,0xff,0x8d,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x88, +-0x00,0x00,0x00,0x00,0x08,0x00,0x21,0xf3,0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x17, +-0x14,0x40,0xff,0xac,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x34,0x00,0x00,0x00,0x00, +-0x2d,0x42,0x00,0x19,0x10,0x40,0xff,0xe2,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0x81, +-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x7b,0x00,0x00,0x00,0x00, +-0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x76,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0x97, +-0x00,0x00,0x00,0x00,0x08,0x00,0x21,0xc8,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x51, +-0x2d,0x42,0x00,0x1b,0x2d,0x42,0x00,0x1e,0x10,0x40,0xff,0xde,0x00,0x00,0x00,0x00, +-0x10,0xa0,0xff,0x70,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x6a, +-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x65,0x24,0x02,0x00,0x03, +-0x10,0xa2,0xff,0x96,0x00,0x00,0x00,0x00,0x08,0x00,0x21,0xc8,0x00,0x00,0x00,0x00, +-0x2d,0x42,0x00,0x23,0x14,0x40,0xff,0xf2,0x00,0x00,0x00,0x00,0x08,0x00,0x21,0xf9, +-0x00,0x00,0x00,0x00,0x08,0x00,0x21,0xf7,0x2d,0x42,0x00,0x25,0x08,0x00,0x22,0x2d, +-0x2d,0x42,0x00,0x27,0x10,0xa0,0xff,0x5b,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +-0x10,0xa2,0xff,0x55,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x50, +-0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0x71,0x00,0x00,0x00,0x00,0x08,0x00,0x21,0xe6, +-0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x27,0x14,0x40,0xff,0xad,0x00,0x00,0x00,0x00, +-0x08,0x00,0x22,0x79,0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x2a,0x14,0x40,0xff,0xd8, +-0x00,0x00,0x00,0x00,0x08,0x00,0x21,0xe9,0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x2c, +-0x14,0x40,0xff,0x78,0x00,0x00,0x00,0x00,0x08,0x00,0x21,0xbd,0x00,0x00,0x00,0x00, +-0x91,0x86,0x00,0x00,0x91,0x83,0x00,0xd4,0x25,0x8d,0x00,0x5c,0x30,0xc4,0x00,0xff, +-0x00,0x04,0x10,0x40,0x00,0x44,0x10,0x21,0x00,0x04,0x48,0x80,0x01,0x82,0x58,0x21, +-0x01,0x89,0x40,0x21,0x25,0x78,0x00,0x08,0x10,0x60,0x00,0x37,0x25,0x0e,0x00,0x60, +-0x2c,0xa2,0x00,0x03,0x14,0x40,0x00,0x25,0x00,0x00,0x00,0x00,0x91,0x82,0x00,0xdd, +-0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x1e,0x00,0x00,0x00,0x00,0x27,0x87,0x81,0x64, +-0x01,0x27,0x10,0x21,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0x03,0x00,0x60, +-0x91,0x62,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x40,0x30,0x21,0xa1,0x82,0x00,0x00, +-0x30,0xc2,0x00,0xff,0x00,0x02,0x10,0x80,0x00,0x47,0x10,0x21,0x8c,0x43,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x03,0x18,0x42,0xad,0xa3,0x00,0x00,0x91,0x84,0x00,0x00, +-0x8d,0xc5,0x00,0x00,0x00,0x04,0x20,0x80,0x00,0x87,0x10,0x21,0x8c,0x43,0x00,0x00, +-0x00,0x05,0x28,0x40,0x00,0x8c,0x20,0x21,0x00,0x03,0x18,0x80,0x00,0xa3,0x10,0x2b, +-0x00,0x62,0x28,0x0a,0xac,0x85,0x00,0x60,0x03,0xe0,0x00,0x08,0xa1,0x80,0x00,0xd4, +-0x27,0x87,0x81,0x64,0x08,0x00,0x22,0xb0,0xa1,0x80,0x00,0xdd,0x27,0x82,0x81,0xd4, +-0x8d,0x83,0x00,0xd8,0x00,0x82,0x10,0x21,0x90,0x44,0x00,0x00,0x24,0x63,0x00,0x01, +-0x00,0x64,0x20,0x2b,0x14,0x80,0xff,0x02,0xad,0x83,0x00,0xd8,0x8d,0x02,0x00,0x60, +-0xa1,0x80,0x00,0xd4,0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x43, +-0x03,0xe0,0x00,0x08,0xad,0x82,0x00,0x5c,0x10,0xe0,0x00,0x1d,0x24,0x83,0xff,0xfc, +-0x2c,0x62,0x00,0x18,0x10,0x40,0x01,0x10,0x00,0x03,0x10,0x80,0x3c,0x03,0x80,0x01, +-0x24,0x63,0x02,0xf0,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x80,0x00,0x08,0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x30,0x14,0x40,0x00,0x65, +-0x00,0x00,0x00,0x00,0x10,0xa0,0x00,0x60,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +-0x10,0xa2,0x00,0x5a,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x08, +-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x03,0x10,0xa2,0x00,0x51,0x00,0x00,0x00,0x00, +-0x8d,0x82,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x42,0xff,0xe0,0xad,0x82,0x00,0xd0, +-0x8d,0xe3,0x00,0x00,0x8d,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x21, +-0xad,0xa2,0x00,0x00,0xad,0xe0,0x00,0x00,0x8d,0xa3,0x00,0x00,0x8d,0xc4,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x83,0x10,0x2a,0x10,0x40,0x00,0x22,0x00,0x00,0x00,0x00, +-0x93,0x05,0x00,0x01,0x91,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x45,0x00,0x05, +-0x24,0x02,0x00,0x01,0xa1,0x85,0x00,0x00,0xa1,0x82,0x00,0xd4,0x03,0xe0,0x00,0x08, +-0xad,0x80,0x00,0xd8,0x91,0x82,0x00,0xdd,0x24,0x03,0x00,0x01,0x10,0x43,0x00,0x05, +-0x00,0x00,0x00,0x00,0xa1,0x83,0x00,0xd4,0xad,0x80,0x00,0xd8,0x03,0xe0,0x00,0x08, +-0xa1,0x83,0x00,0xdd,0x00,0x04,0x17,0xc2,0x00,0x82,0x10,0x21,0x00,0x02,0x10,0x43, +-0xad,0xa2,0x00,0x00,0x91,0x83,0x00,0x00,0x27,0x82,0x81,0x64,0x8d,0xc5,0x00,0x00, +-0x00,0x03,0x18,0x80,0x00,0x62,0x18,0x21,0x8c,0x64,0x00,0x00,0x00,0x05,0x28,0x40, +-0x00,0x04,0x18,0x80,0x00,0xa3,0x10,0x2b,0x00,0x62,0x28,0x0a,0x08,0x00,0x22,0xc2, +-0xad,0xc5,0x00,0x00,0x97,0x82,0x8b,0x7c,0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x2a, +-0x10,0x40,0xfe,0xab,0x00,0x00,0x00,0x00,0x91,0x82,0x00,0xdd,0x00,0x00,0x00,0x00, +-0x14,0x40,0x00,0x15,0x00,0x00,0x00,0x00,0x91,0x83,0x00,0x00,0x27,0x82,0x81,0x64, +-0x00,0x03,0x18,0x80,0x00,0x62,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x6c,0x18,0x21, +-0xac,0x64,0x00,0x60,0x93,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x10,0x80, +-0x01,0x82,0x10,0x21,0x24,0x4e,0x00,0x60,0xa1,0x85,0x00,0x00,0x8d,0xc2,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x43, +-0x03,0xe0,0x00,0x08,0xad,0xa2,0x00,0x00,0x08,0x00,0x23,0x37,0xa1,0x80,0x00,0xdd, +-0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0xf3,0x24,0x42,0xff,0xe8,0x8d,0x82,0x00,0xd0, +-0x08,0x00,0x22,0xf3,0x24,0x42,0x00,0x01,0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0xf3, +-0x24,0x42,0x00,0x02,0x10,0xa0,0xff,0xf9,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +-0x10,0xa2,0x00,0x0a,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xa0, +-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0x9d,0x00,0x00,0x00,0x00, +-0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0xf3,0x24,0x42,0xff,0xd0,0x8d,0x82,0x00,0xd0, +-0x08,0x00,0x22,0xf3,0x24,0x42,0xff,0xfc,0x10,0xa0,0xff,0xeb,0x00,0x00,0x00,0x00, +-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xe5,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +-0x10,0xa2,0xff,0x93,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xdd,0x00,0x00,0x00,0x00, +-0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0xf3,0x24,0x42,0xff,0xf8,0x2d,0x42,0x00,0x19, +-0x14,0x40,0xff,0x7c,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xdb,0x00,0x00,0x00,0x00, +-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xd5,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +-0x10,0xa2,0xff,0x83,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0xf1,0x00,0x00,0x00,0x00, +-0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0xf3,0x24,0x42,0xff,0xf0,0x2d,0x42,0x00,0x1b, +-0x10,0x40,0xff,0xf1,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xcb,0x00,0x00,0x00,0x00, +-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xc5,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +-0x14,0xa2,0xff,0x6c,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0xf3, +-0x24,0x42,0xff,0xf4,0x2d,0x42,0x00,0x1e,0x10,0x40,0xff,0xe3,0x00,0x00,0x00,0x00, +-0x10,0xa0,0xff,0xbd,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x68, +-0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xd6,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0xee, +-0x24,0x02,0x00,0x03,0x2d,0x42,0x00,0x23,0x10,0x40,0xff,0xd7,0x00,0x00,0x00,0x00, +-0x10,0xa0,0xff,0xae,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x5c, +-0x24,0x02,0x00,0x02,0x14,0xa2,0xff,0xb7,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0x74, +-0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x25,0x10,0x40,0xff,0xcb,0x00,0x00,0x00,0x00, +-0x08,0x00,0x23,0x49,0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x16,0x14,0x40,0x00,0x0e, +-0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xa0,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +-0x10,0xa2,0xff,0x9a,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x48, +-0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xb6,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0, +-0x08,0x00,0x22,0xf3,0x24,0x42,0xff,0xfa,0x10,0xa0,0xff,0x93,0x00,0x00,0x00,0x00, +-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x8d,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +-0x10,0xa2,0xff,0x3b,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0x64,0x00,0x00,0x00,0x00, +-0x2d,0x42,0x00,0x17,0x14,0x40,0xff,0xac,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0xa5, +-0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x19,0x10,0x40,0xff,0xe2,0x00,0x00,0x00,0x00, +-0x10,0xa0,0xff,0x81,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x7b, +-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x29,0x24,0x02,0x00,0x03, +-0x10,0xa2,0xff,0x97,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0xf0,0x00,0x00,0x00,0x00, +-0x08,0x00,0x23,0xc2,0x2d,0x42,0x00,0x1b,0x2d,0x42,0x00,0x1e,0x10,0x40,0xff,0xde, +-0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0x70,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01, +-0x10,0xa2,0xff,0x6a,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x18, +-0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0x96,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0xf0, +-0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x23,0x14,0x40,0xff,0xf2,0x00,0x00,0x00,0x00, +-0x08,0x00,0x23,0x6a,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0x68,0x2d,0x42,0x00,0x25, +-0x08,0x00,0x23,0x9e,0x2d,0x42,0x00,0x27,0x10,0xa0,0xff,0x5b,0x00,0x00,0x00,0x00, +-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x55,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02, +-0x10,0xa2,0xff,0x03,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0x71,0x00,0x00,0x00,0x00, +-0x08,0x00,0x23,0x57,0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x27,0x14,0x40,0xff,0xad, +-0x00,0x00,0x00,0x00,0x08,0x00,0x23,0xea,0x00,0x00,0x00,0x00,0x2d,0x42,0x00,0x2a, +-0x14,0x40,0xff,0xd8,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0x5a,0x00,0x00,0x00,0x00, +-0x2d,0x42,0x00,0x2c,0x14,0x40,0xff,0x78,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0xe5, +-0x00,0x00,0x00,0x00,0x27,0xbd,0xff,0xe8,0x3c,0x02,0xb0,0x03,0xaf,0xbf,0x00,0x14, +-0xaf,0xb0,0x00,0x10,0x34,0x42,0x01,0x18,0x3c,0x03,0xb0,0x03,0x8c,0x50,0x00,0x00, +-0x34,0x63,0x01,0x2c,0x90,0x62,0x00,0x00,0x32,0x05,0x00,0x01,0xa3,0x82,0x80,0x10, +-0x14,0xa0,0x00,0x14,0x30,0x44,0x00,0xff,0x32,0x02,0x01,0x00,0x14,0x40,0x00,0x09, +-0x00,0x00,0x00,0x00,0x32,0x02,0x08,0x00,0x10,0x40,0x00,0x02,0x24,0x02,0x00,0x01, +-0xa3,0x82,0xbc,0x18,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x18,0x0c,0x00,0x05,0x37,0x00,0x00,0x00,0x00,0x26,0x02,0xff,0x00, +-0xa3,0x80,0xbc,0x18,0x3c,0x01,0xb0,0x03,0xac,0x22,0x01,0x18,0x08,0x00,0x24,0x16, +-0x32,0x02,0x08,0x00,0x0c,0x00,0x21,0x3f,0x00,0x00,0x00,0x00,0x26,0x02,0xff,0xff, +-0x3c,0x01,0xb0,0x03,0xac,0x22,0x01,0x18,0x08,0x00,0x24,0x13,0x32,0x02,0x01,0x00, +-0x27,0xbd,0xff,0xe0,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xd0,0xaf,0xbf,0x00,0x18, +-0x8c,0x43,0x00,0x00,0x3c,0x02,0x00,0x40,0x24,0x07,0x0f,0xff,0x00,0x03,0x33,0x02, +-0x00,0x03,0x2d,0x02,0x00,0x03,0x43,0x02,0x30,0x69,0x0f,0xff,0x00,0x62,0x18,0x24, +-0x30,0xa5,0x00,0x03,0x30,0xc6,0x00,0xff,0x10,0x60,0x00,0x08,0x31,0x08,0x00,0xff, +-0x01,0x00,0x30,0x21,0x0c,0x00,0x24,0xdf,0xaf,0xa9,0x00,0x10,0x8f,0xbf,0x00,0x18, +-0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x0c,0x00,0x25,0x31, +-0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0xd4,0x08,0x00,0x24,0x3f, +-0xac,0x62,0x00,0x00,0x27,0xbd,0xff,0xc0,0x3c,0x02,0xb0,0x03,0xaf,0xbe,0x00,0x38, +-0xaf,0xb5,0x00,0x2c,0xaf,0xb1,0x00,0x1c,0xaf,0xb0,0x00,0x18,0xaf,0xbf,0x00,0x3c, +-0xaf,0xb7,0x00,0x34,0xaf,0xb6,0x00,0x30,0xaf,0xb4,0x00,0x28,0xaf,0xb3,0x00,0x24, +-0xaf,0xb2,0x00,0x20,0x34,0x42,0x00,0x3f,0x90,0x43,0x00,0x00,0x00,0x80,0x80,0x21, +-0x00,0x00,0xf0,0x21,0x00,0x00,0x88,0x21,0x10,0x60,0x00,0x76,0x00,0x00,0xa8,0x21, +-0x3c,0x01,0xb0,0x03,0xa0,0x20,0x00,0x3f,0x00,0x10,0x12,0x02,0x24,0x04,0x06,0x14, +-0x0c,0x00,0x06,0xd1,0x30,0x54,0x00,0x0f,0x24,0x04,0x06,0x14,0x0c,0x00,0x06,0xd1, +-0xaf,0xa2,0x00,0x10,0x3c,0x03,0x00,0xff,0x34,0x63,0xff,0xff,0x32,0x10,0x00,0x7f, +-0x00,0x43,0x10,0x24,0x00,0x10,0x86,0x00,0x02,0x02,0x80,0x25,0x02,0x00,0x28,0x21, +-0x24,0x04,0x06,0x14,0x3c,0x13,0xbf,0xff,0x0c,0x00,0x06,0xbf,0x3c,0x16,0xb0,0x03, +-0x00,0x00,0x90,0x21,0x3c,0x17,0x40,0x00,0x36,0x73,0xff,0xff,0x36,0xd6,0x00,0x3e, +-0x0c,0x00,0x06,0xd1,0x24,0x04,0x04,0x00,0x00,0x57,0x10,0x25,0x00,0x40,0x28,0x21, +-0x0c,0x00,0x06,0xbf,0x24,0x04,0x04,0x00,0x00,0x00,0x80,0x21,0x0c,0x00,0x25,0xf9, +-0x00,0x00,0x00,0x00,0x26,0x03,0x00,0x01,0x10,0x40,0x00,0x46,0x30,0x70,0x00,0xff, +-0x12,0x00,0xff,0xfa,0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xd1,0x24,0x04,0x04,0x00, +-0x00,0x53,0x10,0x24,0x00,0x40,0x28,0x21,0x0c,0x00,0x06,0xbf,0x24,0x04,0x04,0x00, +-0x24,0x02,0x00,0x01,0x12,0x82,0x00,0x37,0x00,0x00,0x00,0x00,0x12,0x80,0x00,0x35, +-0x00,0x00,0x00,0x00,0x32,0x31,0x00,0x7f,0x12,0x20,0x00,0x04,0x24,0x03,0x00,0x04, +-0x27,0xc2,0x00,0x01,0x30,0x5e,0x00,0xff,0x02,0xb1,0xa8,0x21,0x12,0x43,0x00,0x2a, +-0x3c,0x03,0xb0,0x03,0x02,0x43,0x10,0x21,0xa0,0x51,0x00,0x34,0x26,0x42,0x00,0x01, +-0x30,0x52,0x00,0xff,0x2e,0x43,0x00,0x05,0x14,0x60,0xff,0xd9,0x00,0x00,0x00,0x00, +-0x8f,0xa5,0x00,0x10,0x0c,0x00,0x06,0xbf,0x24,0x04,0x06,0x14,0x12,0xa0,0x00,0x0e, +-0x3c,0x02,0xb0,0x03,0x13,0xc0,0x00,0x0d,0x34,0x42,0x00,0x3c,0x00,0x15,0x10,0x40, +-0x00,0x55,0x10,0x21,0x00,0x02,0x10,0xc0,0x00,0x55,0x10,0x21,0x00,0x02,0xa8,0x80, +-0x02,0xbe,0x00,0x1b,0x17,0xc0,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0d, +-0x00,0x00,0xa8,0x12,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x3c,0x3c,0x03,0xb0,0x03, +-0x3c,0x04,0xb0,0x03,0xa4,0x55,0x00,0x00,0x34,0x63,0x00,0x1c,0x34,0x84,0x00,0x1d, +-0x24,0x02,0x00,0x01,0xa0,0x60,0x00,0x00,0xa0,0x82,0x00,0x00,0x7b,0xbe,0x01,0xfc, +-0x7b,0xb6,0x01,0xbc,0x7b,0xb4,0x01,0x7c,0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc, +-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x40,0xa2,0xd1,0x00,0x00,0x08,0x00,0x24,0x98, +-0x26,0x42,0x00,0x01,0x0c,0x00,0x06,0xd1,0x24,0x04,0x04,0xfc,0x08,0x00,0x24,0x8d, +-0x00,0x40,0x88,0x21,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x3c,0x3c,0x04,0xb0,0x03, +-0x3c,0x05,0xb0,0x03,0xa4,0x60,0x00,0x00,0x34,0x84,0x00,0x1c,0x34,0xa5,0x00,0x1d, +-0x24,0x02,0x00,0x02,0x24,0x03,0x00,0x01,0xa0,0x82,0x00,0x00,0x08,0x00,0x24,0xb7, +-0xa0,0xa3,0x00,0x00,0x0c,0x00,0x17,0x99,0x00,0x00,0x00,0x00,0x10,0x40,0xff,0x8b, +-0x00,0x10,0x12,0x02,0x3c,0x02,0xb0,0x03,0x3c,0x04,0xb0,0x03,0x34,0x42,0x00,0x3c, +-0x34,0x84,0x00,0x14,0x24,0x03,0x00,0x01,0xa4,0x40,0x00,0x00,0x3c,0x01,0xb0,0x03, +-0xa0,0x23,0x00,0x3f,0x08,0x00,0x24,0xb7,0xac,0x90,0x00,0x00,0x27,0xbd,0xff,0xd8, +-0xaf,0xb0,0x00,0x10,0x30,0xd0,0x00,0xff,0x2e,0x02,0x00,0x2e,0xaf,0xb2,0x00,0x18, +-0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x20,0xaf,0xb3,0x00,0x1c,0x30,0xb1,0x00,0xff, +-0x14,0x40,0x00,0x06,0x00,0x80,0x90,0x21,0x8f,0xbf,0x00,0x20,0x7b,0xb2,0x00,0xfc, +-0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28,0x2e,0x13,0x00,0x10, +-0x24,0x05,0x00,0x14,0x0c,0x00,0x13,0xa4,0x24,0x06,0x01,0x07,0x12,0x60,0x00,0x38, +-0x02,0x00,0x30,0x21,0x8f,0xa2,0x00,0x38,0x30,0xc3,0x00,0x3f,0x3c,0x04,0xb0,0x09, +-0x00,0x02,0x14,0x00,0x00,0x43,0x30,0x25,0x34,0x84,0x01,0x60,0x90,0x82,0x00,0x00, +-0x00,0x00,0x00,0x00,0x14,0x40,0xff,0xfd,0x24,0x02,0x00,0x01,0x12,0x22,0x00,0x2a, +-0x2a,0x22,0x00,0x02,0x14,0x40,0x00,0x24,0x24,0x02,0x00,0x02,0x12,0x22,0x00,0x20, +-0x24,0x02,0x00,0x03,0x12,0x22,0x00,0x19,0x00,0x00,0x00,0x00,0x16,0x60,0xff,0xe2, +-0x24,0x02,0x00,0x01,0x12,0x22,0x00,0x13,0x2a,0x22,0x00,0x02,0x14,0x40,0x00,0x0d, +-0x24,0x02,0x00,0x02,0x12,0x22,0x00,0x09,0x24,0x02,0x00,0x03,0x16,0x22,0xff,0xda, +-0x00,0x00,0x00,0x00,0x24,0x04,0x08,0x4c,0x24,0x05,0xff,0xff,0x0c,0x00,0x13,0x5f, +-0x3c,0x06,0x0c,0xb8,0x08,0x00,0x24,0xea,0x00,0x00,0x00,0x00,0x08,0x00,0x25,0x12, +-0x24,0x04,0x08,0x48,0x16,0x20,0xff,0xd0,0x00,0x00,0x00,0x00,0x08,0x00,0x25,0x12, +-0x24,0x04,0x08,0x40,0x08,0x00,0x25,0x12,0x24,0x04,0x08,0x44,0x24,0x04,0x08,0x4c, +-0x0c,0x00,0x13,0x5f,0x24,0x05,0xff,0xff,0x08,0x00,0x25,0x07,0x00,0x00,0x00,0x00, +-0x08,0x00,0x25,0x20,0x24,0x04,0x08,0x48,0x16,0x20,0xff,0xe0,0x00,0x00,0x00,0x00, +-0x08,0x00,0x25,0x20,0x24,0x04,0x08,0x40,0x08,0x00,0x25,0x20,0x24,0x04,0x08,0x44, +-0x02,0x40,0x20,0x21,0x0c,0x00,0x25,0x71,0x02,0x20,0x28,0x21,0x08,0x00,0x24,0xf5, +-0x00,0x40,0x30,0x21,0x27,0xbd,0xff,0xd8,0x2c,0xc2,0x00,0x2e,0xaf,0xb2,0x00,0x18, +-0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x20,0xaf,0xb3,0x00,0x1c, +-0x00,0xc0,0x80,0x21,0x30,0xb1,0x00,0xff,0x00,0x80,0x90,0x21,0x14,0x40,0x00,0x07, +-0x00,0x00,0x18,0x21,0x8f,0xbf,0x00,0x20,0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc, +-0x00,0x60,0x10,0x21,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28,0x2e,0x13,0x00,0x10, +-0x24,0x05,0x00,0x14,0x0c,0x00,0x13,0xa4,0x24,0x06,0x01,0x07,0x12,0x60,0x00,0x24, +-0x02,0x00,0x30,0x21,0x3c,0x03,0xb0,0x09,0x34,0x63,0x01,0x60,0x90,0x62,0x00,0x00, +-0x00,0x00,0x00,0x00,0x14,0x40,0xff,0xfd,0x30,0xc5,0x00,0x3f,0x0c,0x00,0x25,0xae, +-0x02,0x20,0x20,0x21,0x16,0x60,0x00,0x0a,0x00,0x40,0x80,0x21,0x24,0x02,0x00,0x01, +-0x12,0x22,0x00,0x15,0x2a,0x22,0x00,0x02,0x14,0x40,0x00,0x0f,0x24,0x02,0x00,0x02, +-0x12,0x22,0x00,0x0b,0x24,0x02,0x00,0x03,0x12,0x22,0x00,0x03,0x00,0x00,0x00,0x00, +-0x08,0x00,0x25,0x3d,0x02,0x00,0x18,0x21,0x24,0x04,0x08,0x4c,0x24,0x05,0xff,0xff, +-0x0c,0x00,0x13,0x5f,0x3c,0x06,0x0c,0xb8,0x08,0x00,0x25,0x3d,0x02,0x00,0x18,0x21, +-0x08,0x00,0x25,0x5f,0x24,0x04,0x08,0x48,0x16,0x20,0xff,0xf5,0x00,0x00,0x00,0x00, +-0x08,0x00,0x25,0x5f,0x24,0x04,0x08,0x40,0x08,0x00,0x25,0x5f,0x24,0x04,0x08,0x44, +-0x02,0x40,0x20,0x21,0x0c,0x00,0x25,0x71,0x02,0x20,0x28,0x21,0x08,0x00,0x25,0x49, +-0x00,0x40,0x30,0x21,0x27,0xbd,0xff,0xe8,0x2c,0xc2,0x00,0x1f,0xaf,0xb0,0x00,0x10, +-0xaf,0xbf,0x00,0x14,0x00,0xc0,0x80,0x21,0x14,0x40,0x00,0x1d,0x30,0xa5,0x00,0xff, +-0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x18,0x28,0xa2,0x00,0x02,0x14,0x40,0x00,0x12, +-0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x0e,0x24,0x02,0x00,0x03,0x10,0xa2,0x00,0x07, +-0x24,0x04,0x08,0x4c,0x26,0x10,0xff,0xe2,0x02,0x00,0x10,0x21,0x8f,0xbf,0x00,0x14, +-0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x24,0x05,0xff,0xff, +-0x0c,0x00,0x13,0x5f,0x3c,0x06,0x0d,0xf8,0x08,0x00,0x25,0x82,0x26,0x10,0xff,0xe2, +-0x08,0x00,0x25,0x87,0x24,0x04,0x08,0x48,0x14,0xa0,0xff,0xf2,0x24,0x04,0x08,0x40, +-0x08,0x00,0x25,0x88,0x24,0x05,0xff,0xff,0x08,0x00,0x25,0x87,0x24,0x04,0x08,0x44, +-0x2c,0xc2,0x00,0x10,0x14,0x40,0xff,0xec,0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x14, +-0x28,0xa2,0x00,0x02,0x14,0x40,0x00,0x0e,0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x0a, +-0x24,0x02,0x00,0x03,0x10,0xa2,0x00,0x03,0x24,0x04,0x08,0x4c,0x08,0x00,0x25,0x82, +-0x26,0x10,0xff,0xf1,0x24,0x05,0xff,0xff,0x0c,0x00,0x13,0x5f,0x3c,0x06,0x0d,0xb8, +-0x08,0x00,0x25,0x82,0x26,0x10,0xff,0xf1,0x08,0x00,0x25,0xa1,0x24,0x04,0x08,0x48, +-0x14,0xa0,0xff,0xf6,0x24,0x04,0x08,0x40,0x08,0x00,0x25,0xa2,0x24,0x05,0xff,0xff, +-0x08,0x00,0x25,0xa1,0x24,0x04,0x08,0x44,0x27,0xbd,0xff,0xe8,0x30,0x84,0x00,0xff, +-0x24,0x02,0x00,0x01,0x10,0x82,0x00,0x39,0xaf,0xbf,0x00,0x10,0x28,0x82,0x00,0x02, +-0x14,0x40,0x00,0x27,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0x82,0x00,0x17, +-0x00,0xa0,0x30,0x21,0x24,0x02,0x00,0x03,0x10,0x82,0x00,0x05,0x24,0x04,0x08,0x3c, +-0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18, +-0x0c,0x00,0x13,0x5f,0x3c,0x05,0x3f,0x00,0x24,0x04,0x08,0x3c,0x3c,0x05,0x80,0x00, +-0x0c,0x00,0x13,0x5f,0x00,0x00,0x30,0x21,0x24,0x04,0x08,0x3c,0x3c,0x05,0x80,0x00, +-0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x01,0x24,0x04,0x08,0xac,0x0c,0x00,0x13,0x41, +-0x24,0x05,0x0f,0xff,0x08,0x00,0x25,0xbc,0x00,0x00,0x00,0x00,0x24,0x04,0x08,0x34, +-0x0c,0x00,0x13,0x5f,0x3c,0x05,0x3f,0x00,0x24,0x04,0x08,0x34,0x3c,0x05,0x80,0x00, +-0x0c,0x00,0x13,0x5f,0x00,0x00,0x30,0x21,0x24,0x04,0x08,0x34,0x3c,0x05,0x80,0x00, +-0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x01,0x08,0x00,0x25,0xcb,0x24,0x04,0x08,0xa8, +-0x14,0x80,0xff,0xdf,0x00,0xa0,0x30,0x21,0x24,0x04,0x08,0x24,0x0c,0x00,0x13,0x5f, +-0x3c,0x05,0x3f,0x00,0x24,0x04,0x08,0x24,0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5f, +-0x00,0x00,0x30,0x21,0x24,0x04,0x08,0x24,0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5f, +-0x24,0x06,0x00,0x01,0x08,0x00,0x25,0xcb,0x24,0x04,0x08,0xa0,0x00,0xa0,0x30,0x21, +-0x24,0x04,0x08,0x2c,0x0c,0x00,0x13,0x5f,0x3c,0x05,0x3f,0x00,0x24,0x04,0x08,0x2c, +-0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5f,0x00,0x00,0x30,0x21,0x24,0x04,0x08,0x2c, +-0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5f,0x24,0x06,0x00,0x01,0x08,0x00,0x25,0xcb, +-0x24,0x04,0x08,0xa4,0x3c,0x05,0x00,0x14,0x3c,0x02,0xb0,0x05,0x34,0x42,0x04,0x20, +-0x3c,0x06,0xc0,0x00,0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05,0x34,0xa5,0x17,0x09, +-0xac,0x45,0x00,0x00,0x34,0xc6,0x05,0x07,0x34,0x63,0x04,0x24,0x34,0x84,0x02,0x28, +-0x3c,0x07,0xb0,0x05,0x24,0x02,0x00,0x20,0xac,0x66,0x00,0x00,0x34,0xe7,0x04,0x50, +-0xa0,0x82,0x00,0x00,0x90,0xe2,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x03, +-0x10,0x40,0xff,0xfc,0x24,0x02,0x00,0x01,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +-0x93,0x85,0x81,0xf1,0x24,0x02,0x00,0x01,0x14,0xa2,0x00,0x53,0x00,0x80,0x40,0x21, +-0x8c,0x89,0x00,0x04,0x3c,0x02,0xb0,0x01,0x01,0x22,0x30,0x21,0x8c,0xc3,0x00,0x04, +-0x3c,0x02,0x01,0x00,0x00,0x62,0x10,0x24,0x10,0x40,0x00,0x4b,0x30,0x62,0x00,0x08, +-0x10,0x45,0x00,0x59,0x00,0x00,0x00,0x00,0x94,0xc2,0x00,0x38,0x24,0x03,0x00,0xb4, +-0x30,0x44,0x00,0xff,0x10,0x83,0x00,0x61,0x24,0x02,0x00,0xc4,0x10,0x82,0x00,0x54, +-0x24,0x02,0x00,0x94,0x10,0x82,0x00,0x45,0x00,0x00,0x00,0x00,0x94,0xc2,0x00,0x38, +-0x00,0x00,0x00,0x00,0x30,0x47,0xff,0xff,0x30,0xe3,0x40,0xff,0x24,0x02,0x40,0x88, +-0x14,0x62,0x00,0x39,0x30,0xe3,0x03,0x00,0x24,0x02,0x03,0x00,0x10,0x62,0x00,0x38, +-0x00,0x00,0x00,0x00,0x94,0xc2,0x00,0x56,0x00,0x00,0x00,0x00,0x30,0x47,0xff,0xff, +-0x30,0xe2,0x00,0x80,0x14,0x40,0x00,0x30,0x3c,0x02,0xb0,0x01,0x01,0x22,0x30,0x21, +-0x94,0xc3,0x00,0x60,0x24,0x02,0x00,0x08,0x14,0x43,0x00,0x3b,0x00,0x00,0x00,0x00, +-0x90,0xc2,0x00,0x62,0x24,0x03,0x00,0x04,0x00,0x02,0x39,0x02,0x10,0xe3,0x00,0x15, +-0x24,0x02,0x00,0x06,0x14,0xe2,0x00,0x34,0x00,0x00,0x00,0x00,0x8d,0x05,0x01,0xac, +-0x94,0xc4,0x00,0x66,0x27,0x82,0x89,0x68,0x00,0x05,0x28,0x80,0x30,0x87,0xff,0xff, +-0x00,0xa2,0x28,0x21,0x00,0x07,0x1a,0x00,0x8c,0xa4,0x00,0x00,0x00,0x07,0x12,0x02, +-0x00,0x43,0x10,0x25,0x24,0x42,0x00,0x5e,0x24,0x03,0xc0,0x00,0x30,0x47,0xff,0xff, +-0x00,0x83,0x20,0x24,0x00,0x87,0x20,0x25,0xac,0xa4,0x00,0x00,0x08,0x00,0x26,0x76, +-0xad,0x07,0x00,0x10,0x8d,0x05,0x01,0xac,0x94,0xc4,0x00,0x64,0x27,0x82,0x89,0x68, +-0x00,0x05,0x28,0x80,0x30,0x87,0xff,0xff,0x00,0xa2,0x28,0x21,0x00,0x07,0x1a,0x00, +-0x8c,0xa4,0x00,0x00,0x00,0x07,0x12,0x02,0x00,0x43,0x10,0x25,0x24,0x42,0x00,0x36, +-0x3c,0x03,0xff,0xff,0x30,0x47,0xff,0xff,0x00,0x83,0x20,0x24,0x00,0x87,0x20,0x25, +-0xac,0xa4,0x00,0x00,0xad,0x07,0x00,0x10,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +-0x94,0xc2,0x00,0x50,0x08,0x00,0x26,0x34,0x30,0x47,0xff,0xff,0x8d,0x04,0x01,0xac, +-0x27,0x83,0x89,0x68,0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,0x8c,0x82,0x00,0x00, +-0x3c,0x03,0xff,0xff,0x00,0x43,0x10,0x24,0x34,0x42,0x00,0x2e,0xac,0x82,0x00,0x00, +-0x24,0x03,0x00,0x2e,0xad,0x03,0x00,0x10,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +-0x8d,0x04,0x01,0xac,0x27,0x83,0x89,0x68,0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21, +-0x8c,0x82,0x00,0x00,0x3c,0x03,0xff,0xff,0x00,0x43,0x10,0x24,0x34,0x42,0x00,0x0e, +-0x24,0x03,0x00,0x0e,0x08,0x00,0x26,0x75,0xac,0x82,0x00,0x00,0x8d,0x04,0x01,0xac, +-0x27,0x83,0x89,0x68,0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,0x8c,0x82,0x00,0x00, +-0x3c,0x03,0xff,0xff,0x00,0x43,0x10,0x24,0x34,0x42,0x00,0x14,0x24,0x03,0x00,0x14, +-0x08,0x00,0x26,0x75,0xac,0x82,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +-0x30,0xc6,0x00,0xff,0x00,0x06,0x48,0x40,0x01,0x26,0x10,0x21,0x00,0x02,0x10,0x80, +-0x27,0x8b,0xbc,0x30,0x27,0x83,0xbc,0x36,0x00,0x4b,0x40,0x21,0x00,0x43,0x10,0x21, +-0x94,0x47,0x00,0x00,0x30,0xa2,0x3f,0xff,0x10,0xe2,0x00,0x29,0x30,0x8a,0xff,0xff, +-0x95,0x02,0x00,0x02,0x24,0x03,0x00,0x01,0x00,0x02,0x11,0x82,0x30,0x42,0x00,0x01, +-0x10,0x43,0x00,0x18,0x00,0x00,0x00,0x00,0x01,0x26,0x10,0x21,0x00,0x02,0x10,0x80, +-0x00,0x4b,0x30,0x21,0x94,0xc4,0x00,0x02,0x27,0x83,0xbc,0x36,0x27,0x85,0xbc,0x34, +-0x00,0x45,0x28,0x21,0x30,0x84,0xff,0xdf,0x00,0x43,0x10,0x21,0xa4,0xc4,0x00,0x02, +-0xa4,0x40,0x00,0x00,0xa4,0xa0,0x00,0x00,0x94,0xc3,0x00,0x02,0x3c,0x04,0xb0,0x01, +-0x01,0x44,0x20,0x21,0x30,0x63,0xff,0xbf,0xa4,0xc3,0x00,0x02,0xa0,0xc0,0x00,0x00, +-0x8c,0x82,0x00,0x04,0x24,0x03,0xf0,0xff,0x00,0x43,0x10,0x24,0x03,0xe0,0x00,0x08, +-0xac,0x82,0x00,0x04,0x24,0x02,0xc0,0x00,0x91,0x04,0x00,0x01,0x00,0xa2,0x10,0x24, +-0x00,0x47,0x28,0x25,0x3c,0x03,0xb0,0x01,0x24,0x02,0x00,0x02,0x14,0x82,0xff,0xe2, +-0x01,0x43,0x18,0x21,0xac,0x65,0x00,0x00,0x08,0x00,0x26,0xa3,0x01,0x26,0x10,0x21, +-0x08,0x00,0x26,0xa3,0x01,0x26,0x10,0x21,0x93,0x83,0x81,0xf1,0x24,0x02,0x00,0x01, +-0x14,0x62,0x00,0x0d,0x3c,0x02,0xb0,0x01,0x8c,0x84,0x00,0x04,0x3c,0x06,0xb0,0x09, +-0x00,0x82,0x20,0x21,0x8c,0x85,0x00,0x08,0x8c,0x83,0x00,0x04,0x3c,0x02,0x01,0x00, +-0x34,0xc6,0x01,0x00,0x00,0x62,0x18,0x24,0x14,0x60,0x00,0x05,0x30,0xa5,0x20,0x00, +-0x24,0x02,0x00,0x06,0xa0,0xc2,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00, +-0x3c,0x03,0xb0,0x09,0x10,0xa0,0xff,0xfc,0x34,0x63,0x01,0x00,0x24,0x02,0x00,0x0e, +-0x08,0x00,0x26,0xd6,0xa0,0x62,0x00,0x00,0x3c,0x02,0xb0,0x01,0x30,0xa5,0xff,0xff, +-0x00,0xa2,0x28,0x21,0x8c,0xa3,0x00,0x00,0x3c,0x02,0x10,0x00,0x00,0x80,0x30,0x21, +-0x00,0x62,0x18,0x24,0x8c,0xa2,0x00,0x04,0x10,0x60,0x00,0x04,0x00,0x00,0x00,0x00, +-0x30,0x42,0x80,0x00,0x10,0x40,0x00,0x13,0x00,0x00,0x00,0x00,0x8c,0xc2,0x01,0xa8, +-0x00,0x00,0x00,0x00,0x24,0x44,0x00,0x01,0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40, +-0x00,0x83,0x10,0x0a,0x93,0x83,0x81,0xf0,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80, +-0x00,0x82,0x20,0x23,0x24,0x63,0xff,0xff,0xac,0xc4,0x01,0xa8,0xa3,0x83,0x81,0xf0, +-0x8c,0xc4,0x01,0xac,0x8c,0xc2,0x01,0xa8,0x00,0x00,0x00,0x00,0x00,0x44,0x10,0x26, +-0x00,0x02,0x10,0x2b,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03, +-0x34,0x63,0x00,0x73,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01, +-0x14,0x40,0x00,0x04,0x00,0x00,0x00,0x00,0xa3,0x80,0x81,0xf1,0x03,0xe0,0x00,0x08, +-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0xa3,0x82,0x81,0xf1,0x03,0xe0,0x00,0x08, +-0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x04,0x3c,0x05,0xb0,0x01,0x00,0x80,0x50,0x21, +-0x00,0x45,0x10,0x21,0x8c,0x43,0x00,0x04,0x24,0x02,0x00,0x05,0x00,0x03,0x1a,0x02, +-0x30,0x69,0x00,0x0f,0x11,0x22,0x00,0x0b,0x24,0x02,0x00,0x07,0x11,0x22,0x00,0x09, +-0x24,0x02,0x00,0x0a,0x11,0x22,0x00,0x07,0x24,0x02,0x00,0x0b,0x11,0x22,0x00,0x05, +-0x24,0x02,0x00,0x01,0x93,0x83,0x81,0xf0,0x3c,0x04,0xb0,0x06,0x10,0x62,0x00,0x03, +-0x34,0x84,0x80,0x18,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x02,0x14,0x40,0xff,0xfa,0x00,0x00,0x00,0x00, +-0x8d,0x43,0x01,0xa8,0x27,0x82,0x89,0x68,0x00,0x03,0x18,0x80,0x00,0x6a,0x20,0x21, +-0x8c,0x87,0x00,0xa8,0x00,0x62,0x18,0x21,0x8c,0x68,0x00,0x00,0x00,0xe5,0x28,0x21, +-0x8c,0xa9,0x00,0x00,0x3c,0x02,0xff,0xff,0x27,0x83,0x8a,0x68,0x01,0x22,0x10,0x24, +-0x00,0x48,0x10,0x25,0xac,0xa2,0x00,0x00,0x8d,0x44,0x01,0xa8,0x00,0x07,0x30,0xc2, +-0x3c,0x02,0x00,0x80,0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,0x00,0x06,0x32,0x00, +-0x8c,0xa9,0x00,0x04,0x00,0xc2,0x30,0x25,0x8c,0x82,0x00,0x00,0x3c,0x03,0x80,0x00, +-0x01,0x22,0x10,0x25,0x00,0x43,0x10,0x25,0xac,0xa2,0x00,0x04,0xaf,0x87,0xbc,0x20, +-0x8c,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x82,0xbc,0x28,0x8c,0xa3,0x00,0x04, +-0x3c,0x01,0xb0,0x07,0xac,0x26,0x80,0x18,0x8d,0x42,0x01,0xa8,0xaf,0x83,0xbc,0x24, +-0x93,0x85,0x81,0xf0,0x24,0x44,0x00,0x01,0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40, +-0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x24,0xa5,0xff,0xff, +-0x00,0x82,0x20,0x23,0xad,0x44,0x01,0xa8,0xa3,0x85,0x81,0xf0,0x08,0x00,0x27,0x21, +-0x00,0x00,0x00,0x00,0x3c,0x05,0xb0,0x03,0x3c,0x02,0x80,0x01,0x34,0xa5,0x00,0x20, +-0x24,0x42,0x9d,0x64,0xac,0xa2,0x00,0x00,0x24,0x02,0x00,0x02,0x24,0x03,0x00,0x20, +-0xac,0x82,0x00,0x64,0x3c,0x02,0x80,0x01,0xac,0x83,0x00,0x60,0xac,0x80,0x00,0x00, +-0xac,0x80,0x00,0x04,0xac,0x80,0x00,0x08,0xac,0x80,0x00,0x4c,0xac,0x80,0x00,0x50, +-0xac,0x80,0x00,0x54,0xac,0x80,0x00,0x0c,0xac,0x80,0x00,0x58,0xa0,0x80,0x00,0x5c, +-0x24,0x42,0x9e,0x28,0x24,0x83,0x00,0x68,0x24,0x05,0x00,0x0f,0x24,0xa5,0xff,0xff, +-0xac,0x62,0x00,0x00,0x04,0xa1,0xff,0xfd,0x24,0x63,0x00,0x04,0x3c,0x02,0x80,0x01, +-0x24,0x42,0x9f,0x10,0xac,0x82,0x00,0x78,0x3c,0x03,0x80,0x01,0x3c,0x02,0x80,0x01, +-0x24,0x63,0xa0,0x9c,0x24,0x42,0xa0,0x08,0xac,0x83,0x00,0x88,0xac,0x82,0x00,0x98, +-0x3c,0x03,0x80,0x01,0x3c,0x02,0x80,0x01,0x24,0x63,0xa1,0x44,0x24,0x42,0xa2,0x5c, +-0xac,0x83,0x00,0xa0,0xac,0x82,0x00,0xa4,0xa0,0x80,0x01,0xba,0xac,0x80,0x01,0xa8, +-0xac,0x80,0x01,0xac,0xac,0x80,0x01,0xb0,0xac,0x80,0x01,0xb4,0xa0,0x80,0x01,0xb8, +-0x03,0xe0,0x00,0x08,0xa0,0x80,0x01,0xb9,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x01, +-0x34,0x63,0x00,0x20,0x24,0x42,0x9e,0x28,0x03,0xe0,0x00,0x08,0xac,0x62,0x00,0x00, +-0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x34,0x42,0x00,0x20,0x24,0x63,0x9e,0x40, +-0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x11, +-0x00,0x80,0x28,0x21,0x8c,0x82,0x00,0x14,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0d, +-0x00,0x00,0x00,0x00,0x8c,0x84,0x00,0x10,0x8c,0xa3,0x00,0x14,0x8c,0xa2,0x00,0x04, +-0x00,0x83,0x20,0x21,0x00,0x44,0x10,0x21,0x30,0x43,0x00,0xff,0x00,0x03,0x18,0x2b, +-0x00,0x02,0x12,0x02,0x00,0x43,0x10,0x21,0x00,0x02,0x12,0x00,0x30,0x42,0x3f,0xff, +-0xac,0xa2,0x00,0x04,0xac,0xa0,0x00,0x00,0xac,0xa0,0x00,0x4c,0xac,0xa0,0x00,0x50, +-0xac,0xa0,0x00,0x54,0x03,0xe0,0x00,0x08,0xac,0xa0,0x00,0x0c,0x3c,0x03,0xb0,0x03, +-0x3c,0x02,0x80,0x01,0x34,0x63,0x00,0x20,0x24,0x42,0x9e,0xbc,0xac,0x62,0x00,0x00, +-0x8c,0x86,0x00,0x04,0x3c,0x02,0xb0,0x01,0x24,0x03,0x00,0x01,0x00,0xc2,0x10,0x21, +-0x8c,0x45,0x00,0x00,0xac,0x83,0x00,0x4c,0x00,0x05,0x14,0x02,0x30,0xa3,0x3f,0xff, +-0x30,0x42,0x00,0xff,0xac,0x83,0x00,0x10,0xac,0x82,0x00,0x14,0x8c,0x83,0x00,0x14, +-0xac,0x85,0x00,0x40,0x00,0xc3,0x30,0x21,0x03,0xe0,0x00,0x08,0xac,0x86,0x00,0x08, +-0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20, +-0x24,0x63,0x9f,0x10,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00, +-0x8c,0x82,0x00,0x4c,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0a,0x00,0x80,0x80,0x21, +-0xae,0x00,0x00,0x00,0xae,0x00,0x00,0x4c,0xae,0x00,0x00,0x50,0xae,0x00,0x00,0x54, +-0xae,0x00,0x00,0x0c,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x18,0x0c,0x00,0x27,0xaf,0x00,0x00,0x00,0x00,0x08,0x00,0x27,0xd1, +-0xae,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8, +-0x34,0x42,0x00,0x20,0x24,0x63,0x9f,0x74,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14, +-0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x4c,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x16, +-0x00,0x80,0x80,0x21,0x8e,0x03,0x00,0x08,0x3c,0x02,0xb0,0x01,0x8e,0x04,0x00,0x44, +-0x00,0x62,0x18,0x21,0x90,0x65,0x00,0x00,0x24,0x02,0x00,0x01,0xae,0x02,0x00,0x50, +-0x30,0xa3,0x00,0xff,0x00,0x03,0x10,0x82,0x00,0x04,0x23,0x02,0x30,0x84,0x00,0x0f, +-0x30,0x42,0x00,0x03,0x00,0x03,0x19,0x02,0xae,0x04,0x00,0x34,0xae,0x02,0x00,0x2c, +-0xae,0x03,0x00,0x30,0xa2,0x05,0x00,0x48,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10, +-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x0c,0x00,0x27,0xaf,0x00,0x00,0x00,0x00, +-0x08,0x00,0x27,0xe9,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01, +-0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20,0x24,0x63,0xa0,0x08,0xaf,0xb0,0x00,0x10, +-0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x50,0x00,0x00,0x00,0x00, +-0x10,0x40,0x00,0x16,0x00,0x80,0x80,0x21,0x92,0x03,0x00,0x44,0x8e,0x02,0x00,0x40, +-0x83,0x85,0x8b,0xd4,0x92,0x04,0x00,0x41,0x30,0x63,0x00,0x01,0x00,0x02,0x16,0x02, +-0xae,0x04,0x00,0x14,0x00,0x00,0x30,0x21,0xae,0x02,0x00,0x18,0x10,0xa0,0x00,0x04, +-0xae,0x03,0x00,0x3c,0x10,0x60,0x00,0x03,0x24,0x02,0x00,0x01,0x24,0x06,0x00,0x01, +-0x24,0x02,0x00,0x01,0xa3,0x86,0x8b,0xd4,0x8f,0xbf,0x00,0x14,0xae,0x02,0x00,0x54, +-0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x0c,0x00,0x27,0xdd, +-0x00,0x00,0x00,0x00,0x08,0x00,0x28,0x0e,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03, +-0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20,0x24,0x63,0xa0,0x9c, +-0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x50, +-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x1b,0x00,0x80,0x80,0x21,0x3c,0x02,0xb0,0x03, +-0x8c,0x42,0x00,0x00,0x92,0x04,0x00,0x44,0x8e,0x03,0x00,0x40,0x83,0x86,0x8b,0xd4, +-0x92,0x05,0x00,0x41,0x30,0x42,0x08,0x00,0x30,0x84,0x00,0x01,0x00,0x02,0x12,0xc2, +-0x00,0x03,0x1e,0x02,0x00,0x82,0x20,0x25,0xae,0x05,0x00,0x14,0x00,0x00,0x38,0x21, +-0xae,0x03,0x00,0x18,0x10,0xc0,0x00,0x04,0xae,0x04,0x00,0x3c,0x10,0x80,0x00,0x03, +-0x24,0x02,0x00,0x01,0x24,0x07,0x00,0x01,0x24,0x02,0x00,0x01,0xa3,0x87,0x8b,0xd4, +-0x8f,0xbf,0x00,0x14,0xae,0x02,0x00,0x54,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x18,0x0c,0x00,0x27,0xdd,0x00,0x00,0x00,0x00,0x08,0x00,0x28,0x33, +-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8, +-0x34,0x42,0x00,0x20,0x24,0x63,0xa1,0x44,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14, +-0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x54,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x37, +-0x00,0x80,0x80,0x21,0x8e,0x04,0x00,0x04,0x8e,0x03,0x00,0x44,0x3c,0x02,0x80,0x00, +-0x3c,0x05,0xb0,0x01,0x34,0x42,0x00,0x10,0x00,0x85,0x20,0x21,0x00,0x62,0x18,0x25, +-0xac,0x83,0x00,0x04,0x8e,0x02,0x00,0x04,0x8e,0x03,0x01,0xac,0x02,0x00,0x20,0x21, +-0x00,0x45,0x10,0x21,0x8c,0x46,0x00,0x00,0x00,0x03,0x18,0x80,0x27,0x82,0x89,0x68, +-0x00,0x62,0x18,0x21,0xac,0x66,0x00,0x00,0x8e,0x02,0x00,0x04,0x8e,0x03,0x01,0xac, +-0x00,0x45,0x10,0x21,0x8c,0x46,0x00,0x04,0x00,0x03,0x18,0x80,0x27,0x82,0x8a,0x68, +-0x00,0x62,0x18,0x21,0x0c,0x00,0x26,0x10,0xac,0x66,0x00,0x00,0x8e,0x03,0x01,0xac, +-0x8e,0x07,0x00,0x04,0x3c,0x06,0xb0,0x03,0x24,0x65,0x00,0x01,0x28,0xa4,0x00,0x00, +-0x24,0x62,0x00,0x40,0x00,0xa4,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80, +-0x00,0x03,0x18,0x80,0x00,0xa2,0x28,0x23,0x00,0x70,0x18,0x21,0xae,0x05,0x01,0xac, +-0xac,0x67,0x00,0xa8,0x34,0xc6,0x00,0x30,0x8c,0xc3,0x00,0x00,0x93,0x82,0x81,0xf0, +-0x02,0x00,0x20,0x21,0x24,0x63,0x00,0x01,0x24,0x42,0x00,0x01,0xac,0xc3,0x00,0x00, +-0xa3,0x82,0x81,0xf0,0x0c,0x00,0x27,0x90,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x14, +-0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x0c,0x00,0x28,0x27, +-0x00,0x00,0x00,0x00,0x08,0x00,0x28,0x5d,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03, +-0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20,0x24,0x63,0xa2,0x5c, +-0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x54, +-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x37,0x00,0x80,0x80,0x21,0x8e,0x04,0x00,0x04, +-0x8e,0x03,0x00,0x44,0x3c,0x02,0x80,0x00,0x3c,0x05,0xb0,0x01,0x34,0x42,0x00,0x10, +-0x00,0x85,0x20,0x21,0x00,0x62,0x18,0x25,0xac,0x83,0x00,0x04,0x8e,0x02,0x00,0x04, +-0x8e,0x03,0x01,0xac,0x02,0x00,0x20,0x21,0x00,0x45,0x10,0x21,0x8c,0x46,0x00,0x00, +-0x00,0x03,0x18,0x80,0x27,0x82,0x89,0x68,0x00,0x62,0x18,0x21,0xac,0x66,0x00,0x00, +-0x8e,0x02,0x00,0x04,0x8e,0x03,0x01,0xac,0x00,0x45,0x10,0x21,0x8c,0x46,0x00,0x04, +-0x00,0x03,0x18,0x80,0x27,0x82,0x8a,0x68,0x00,0x62,0x18,0x21,0x0c,0x00,0x26,0x10, +-0xac,0x66,0x00,0x00,0x8e,0x03,0x01,0xac,0x8e,0x07,0x00,0x04,0x3c,0x06,0xb0,0x03, +-0x24,0x65,0x00,0x01,0x28,0xa4,0x00,0x00,0x24,0x62,0x00,0x40,0x00,0xa4,0x10,0x0a, +-0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x00,0x03,0x18,0x80,0x00,0xa2,0x28,0x23, +-0x00,0x70,0x18,0x21,0xae,0x05,0x01,0xac,0xac,0x67,0x00,0xa8,0x34,0xc6,0x00,0x30, +-0x8c,0xc3,0x00,0x00,0x93,0x82,0x81,0xf0,0x02,0x00,0x20,0x21,0x24,0x63,0x00,0x01, +-0x24,0x42,0x00,0x01,0xac,0xc3,0x00,0x00,0xa3,0x82,0x81,0xf0,0x0c,0x00,0x27,0x90, +-0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x18,0x0c,0x00,0x28,0x27,0x00,0x00,0x00,0x00,0x08,0x00,0x28,0xa3, +-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x34,0x42,0x00,0x20, +-0x24,0x63,0xa3,0x74,0x27,0xbd,0xff,0xe0,0xac,0x43,0x00,0x00,0x3c,0x02,0x80,0x01, +-0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x1c, +-0x00,0x80,0x80,0x21,0x24,0x52,0x9e,0x28,0x00,0x00,0x88,0x21,0x3c,0x03,0xb0,0x09, +-0x34,0x63,0x00,0x06,0x8e,0x06,0x00,0x04,0x90,0x62,0x00,0x00,0x00,0x06,0x22,0x02, +-0x00,0x44,0x10,0x23,0x24,0x44,0x00,0x40,0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x7f, +-0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x24,0x84,0xff,0xff, +-0x10,0x44,0x00,0x68,0x00,0x00,0x28,0x21,0x3c,0x02,0xb0,0x01,0x00,0xc2,0x10,0x21, +-0x8c,0x44,0x00,0x04,0x3c,0x03,0x7c,0x00,0x34,0x63,0x00,0xf0,0x00,0x83,0x18,0x24, +-0xae,0x04,0x00,0x44,0x8c,0x44,0x00,0x00,0x10,0x60,0x00,0x69,0x00,0x00,0x38,0x21, +-0x3c,0x09,0xb0,0x03,0x3c,0x06,0x7c,0x00,0x35,0x29,0x00,0x99,0x3c,0x0a,0xb0,0x01, +-0x24,0x08,0x00,0x40,0x34,0xc6,0x00,0xf0,0x3c,0x0b,0xff,0xff,0x3c,0x0c,0x28,0x38, +-0x16,0x20,0x00,0x06,0x24,0xa5,0x00,0x01,0x93,0x82,0x81,0xf6,0x24,0x11,0x00,0x01, +-0x24,0x42,0x00,0x01,0xa1,0x22,0x00,0x00,0xa3,0x82,0x81,0xf6,0x8e,0x02,0x00,0x04, +-0x24,0x07,0x00,0x01,0x24,0x42,0x01,0x00,0x30,0x42,0x3f,0xff,0xae,0x02,0x00,0x04, +-0x00,0x4a,0x10,0x21,0x8c,0x43,0x00,0x04,0x00,0x00,0x00,0x00,0xae,0x03,0x00,0x44, +-0x8c,0x44,0x00,0x00,0x10,0xa8,0x00,0x2d,0x00,0x66,0x18,0x24,0x14,0x60,0xff,0xec, +-0x00,0x8b,0x10,0x24,0x14,0x4c,0xff,0xea,0x24,0x02,0x00,0x01,0x10,0xe2,0x00,0x2f, +-0x3c,0x03,0xb0,0x09,0x8e,0x02,0x00,0x44,0x8e,0x04,0x00,0x60,0x00,0x02,0x1e,0x42, +-0x00,0x02,0x12,0x02,0x30,0x42,0x00,0x0f,0x30,0x63,0x00,0x01,0xae,0x02,0x00,0x00, +-0x10,0x44,0x00,0x1a,0xae,0x03,0x00,0x58,0x8e,0x02,0x00,0x64,0x8e,0x04,0x00,0x58, +-0x00,0x00,0x00,0x00,0x10,0x82,0x00,0x05,0x00,0x00,0x00,0x00,0xae,0x00,0x00,0x4c, +-0xae,0x00,0x00,0x50,0xae,0x00,0x00,0x54,0xae,0x00,0x00,0x0c,0x8e,0x03,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x03,0x10,0x80,0x00,0x50,0x10,0x21,0x8c,0x42,0x00,0x68, +-0x00,0x00,0x00,0x00,0x10,0x52,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x40,0xf8,0x09, +-0x02,0x00,0x20,0x21,0x8e,0x04,0x00,0x58,0x8e,0x03,0x00,0x00,0x00,0x00,0x00,0x00, +-0xae,0x03,0x00,0x60,0x08,0x00,0x28,0xeb,0xae,0x04,0x00,0x64,0x8e,0x02,0x00,0x64, +-0x00,0x00,0x00,0x00,0x14,0x62,0xff,0xe5,0x00,0x00,0x00,0x00,0x7a,0x02,0x0d,0x7c, +-0x8f,0xbf,0x00,0x1c,0x8f,0xb2,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x00,0x43,0x10,0x26, +-0x00,0x02,0x10,0x2b,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x34,0x63,0x00,0x06, +-0x8e,0x04,0x00,0x04,0x90,0x62,0x00,0x00,0x00,0x04,0x22,0x02,0x00,0x44,0x10,0x23, +-0x24,0x44,0x00,0x40,0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x7f,0x00,0x83,0x10,0x0a, +-0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x00,0x82,0x20,0x23,0x14,0x87,0xff,0xc5, +-0x00,0x00,0x00,0x00,0x8e,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x62,0x00,0x03, +-0x14,0x40,0x00,0x05,0x24,0x02,0x00,0x0d,0x10,0x62,0x00,0x03,0x24,0x02,0x00,0x01, +-0x08,0x00,0x29,0x4b,0xa2,0x02,0x00,0x5c,0x08,0x00,0x29,0x4b,0xa2,0x00,0x00,0x5c, +-0x3c,0x02,0xff,0xff,0x00,0x82,0x10,0x24,0x3c,0x03,0x28,0x38,0x14,0x43,0xff,0x94, +-0x24,0x02,0x00,0x01,0x08,0x00,0x29,0x23,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03, +-0x3c,0x03,0x80,0x01,0x34,0x42,0x00,0x20,0x24,0x63,0xa5,0xcc,0xac,0x43,0x00,0x00, +-0x8c,0x83,0x01,0xa8,0x8c,0x82,0x01,0xac,0x00,0x80,0x40,0x21,0x10,0x62,0x00,0x20, +-0x00,0x00,0x20,0x21,0x93,0x82,0x81,0xf1,0x00,0x03,0x28,0x80,0x3c,0x07,0xb0,0x06, +-0x00,0xa8,0x18,0x21,0x24,0x04,0x00,0x01,0x8c,0x66,0x00,0xa8,0x10,0x44,0x00,0x1c, +-0x34,0xe7,0x80,0x18,0x3c,0x05,0xb0,0x01,0xaf,0x86,0xbc,0x20,0x00,0xc5,0x28,0x21, +-0x8c,0xa3,0x00,0x00,0x00,0x06,0x20,0xc2,0x3c,0x02,0x00,0x80,0x00,0x04,0x22,0x00, +-0x00,0x82,0x20,0x25,0xaf,0x83,0xbc,0x28,0x8c,0xa2,0x00,0x04,0xac,0xe4,0x00,0x00, +-0x8d,0x03,0x01,0xa8,0xaf,0x82,0xbc,0x24,0x24,0x64,0x00,0x01,0x04,0x80,0x00,0x0a, +-0x00,0x80,0x10,0x21,0x00,0x02,0x11,0x83,0x8d,0x03,0x01,0xac,0x00,0x02,0x11,0x80, +-0x00,0x82,0x10,0x23,0x00,0x43,0x18,0x26,0xad,0x02,0x01,0xa8,0x00,0x03,0x20,0x2b, +-0x03,0xe0,0x00,0x08,0x00,0x80,0x10,0x21,0x08,0x00,0x29,0x95,0x24,0x62,0x00,0x40, +-0x27,0x82,0x89,0x68,0x00,0x06,0x20,0xc2,0x00,0x04,0x22,0x00,0x00,0xa2,0x48,0x21, +-0x3c,0x02,0x00,0x80,0x00,0x82,0x58,0x25,0x93,0x82,0x81,0xf0,0x3c,0x0a,0xb0,0x06, +-0x3c,0x03,0xb0,0x01,0x2c,0x42,0x00,0x02,0x00,0xc3,0x38,0x21,0x35,0x4a,0x80,0x18, +-0x14,0x40,0xff,0xef,0x00,0x00,0x20,0x21,0x8c,0xe5,0x00,0x00,0x8d,0x23,0x00,0x00, +-0x24,0x02,0xc0,0x00,0x00,0xa2,0x10,0x24,0x00,0x43,0x10,0x25,0xac,0xe2,0x00,0x00, +-0x8d,0x04,0x01,0xa8,0x27,0x83,0x8a,0x68,0x8c,0xe5,0x00,0x04,0x00,0x04,0x20,0x80, +-0x00,0x83,0x20,0x21,0x8c,0x82,0x00,0x00,0x3c,0x03,0x80,0x00,0x00,0xa2,0x10,0x25, +-0x00,0x43,0x10,0x25,0xac,0xe2,0x00,0x04,0xaf,0x86,0xbc,0x20,0x8c,0xe2,0x00,0x00, +-0x93,0x85,0x81,0xf0,0xaf,0x82,0xbc,0x28,0x8c,0xe3,0x00,0x04,0xad,0x4b,0x00,0x00, +-0x8d,0x02,0x01,0xa8,0xaf,0x83,0xbc,0x24,0x24,0xa5,0xff,0xff,0x24,0x44,0x00,0x01, +-0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40,0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83, +-0x00,0x02,0x11,0x80,0x00,0x82,0x20,0x23,0xad,0x04,0x01,0xa8,0xa3,0x85,0x81,0xf0, +-0x79,0x02,0x0d,0x7c,0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x26,0x08,0x00,0x29,0x9c, +-0x00,0x02,0x20,0x2b,0x3c,0x04,0xb0,0x03,0x3c,0x06,0xb0,0x07,0x3c,0x02,0x80,0x01, +-0x34,0xc6,0x00,0x18,0x34,0x84,0x00,0x20,0x24,0x42,0xa7,0x54,0x24,0x03,0xff,0x83, +-0xac,0x82,0x00,0x00,0xa0,0xc3,0x00,0x00,0x90,0xc4,0x00,0x00,0x27,0xbd,0xff,0xf8, +-0x3c,0x03,0xb0,0x07,0x24,0x02,0xff,0x82,0xa3,0xa4,0x00,0x00,0xa0,0x62,0x00,0x00, +-0x90,0x64,0x00,0x00,0x3c,0x02,0xb0,0x07,0x34,0x42,0x00,0x08,0xa3,0xa4,0x00,0x01, +-0xa0,0x40,0x00,0x00,0x90,0x43,0x00,0x00,0x24,0x02,0x00,0x03,0x3c,0x05,0xb0,0x07, +-0xa3,0xa3,0x00,0x00,0xa0,0xc2,0x00,0x00,0x90,0xc4,0x00,0x00,0x34,0xa5,0x00,0x10, +-0x24,0x02,0x00,0x06,0x3c,0x03,0xb0,0x07,0xa3,0xa4,0x00,0x00,0x34,0x63,0x00,0x38, +-0xa0,0xa2,0x00,0x00,0x90,0x64,0x00,0x00,0x3c,0x02,0xb0,0x07,0x34,0x42,0x00,0x20, +-0xa3,0xa4,0x00,0x00,0xa0,0xa0,0x00,0x00,0x90,0xa3,0x00,0x00,0xaf,0x82,0xbf,0x30, +-0xa3,0xa3,0x00,0x00,0xa0,0x40,0x00,0x00,0x90,0x43,0x00,0x00,0x03,0xe0,0x00,0x08, +-0x27,0xbd,0x00,0x08,}; +- +-u8 Rtl8192PciEFwDataArray[DataArrayLengthPciE] = { +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00, +-0x02,0xe9,0x01,0x74,0x02,0xab,0x01,0xc7,0x01,0x55,0x00,0xe4,0x00,0xab,0x00,0x72, +-0x00,0x55,0x00,0x4c,0x00,0x4c,0x00,0x4c,0x00,0x4c,0x00,0x4c,0x02,0x76,0x01,0x3b, +-0x00,0xd2,0x00,0x9e,0x00,0x69,0x00,0x4f,0x00,0x46,0x00,0x3f,0x01,0x3b,0x00,0x9e, +-0x00,0x69,0x00,0x4f,0x00,0x35,0x00,0x27,0x00,0x23,0x00,0x20,0x01,0x2f,0x00,0x98, +-0x00,0x65,0x00,0x4c,0x00,0x33,0x00,0x26,0x00,0x22,0x00,0x1e,0x00,0x98,0x00,0x4c, +-0x00,0x33,0x00,0x26,0x00,0x19,0x00,0x13,0x00,0x11,0x00,0x0f,0x02,0x39,0x01,0x1c, +-0x00,0xbd,0x00,0x8e,0x00,0x5f,0x00,0x47,0x00,0x3f,0x00,0x39,0x01,0x1c,0x00,0x8e, +-0x00,0x5f,0x00,0x47,0x00,0x2f,0x00,0x23,0x00,0x20,0x00,0x1c,0x01,0x11,0x00,0x89, +-0x00,0x5b,0x00,0x44,0x00,0x2e,0x00,0x22,0x00,0x1e,0x00,0x1b,0x00,0x89,0x00,0x44, +-0x00,0x2e,0x00,0x22,0x00,0x17,0x00,0x11,0x00,0x0f,0x00,0x0e,0x02,0xab,0x02,0xab, +-0x02,0x66,0x02,0x66,0x07,0x06,0x06,0x06,0x05,0x06,0x07,0x08,0x04,0x06,0x07,0x08, +-0x09,0x0a,0x0b,0x0b,0x49,0x6e,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x4c, +-0x42,0x4d,0x4f,0x44,0x00,0x00,0x00,0x00,0x54,0x4c,0x42,0x4c,0x5f,0x64,0x61,0x74, +-0x61,0x00,0x54,0x4c,0x42,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x64,0x45,0x4c, +-0x5f,0x64,0x61,0x74,0x61,0x00,0x41,0x64,0x45,0x53,0x00,0x00,0x00,0x00,0x00,0x00, +-0x45,0x78,0x63,0x43,0x6f,0x64,0x65,0x36,0x00,0x00,0x45,0x78,0x63,0x43,0x6f,0x64, +-0x65,0x37,0x00,0x00,0x53,0x79,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x70, +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x49,0x00,0x00,0x00,0x00,0x00,0x00, +-0x00,0x00,0x43,0x70,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0x76,0x00,0x00, +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x0b,0x63, +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x2c, +-0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x60, +-0x00,0x00,0x00,0x90,0x00,0x00,0x00,0xc0,0x00,0x00,0x01,0x20,0x00,0x00,0x01,0x80, +-0x00,0x00,0x01,0xb0,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x9c, +-0x00,0x00,0x00,0xd0,0x00,0x00,0x01,0x38,0x00,0x00,0x01,0xa0,0x00,0x00,0x01,0xd4, +-0x00,0x00,0x02,0x08,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0xd0,0x00,0x00,0x01,0x38, +-0x00,0x00,0x01,0xa0,0x00,0x00,0x02,0x6f,0x00,0x00,0x03,0x40,0x00,0x00,0x03,0xa8, +-0x00,0x00,0x04,0x10,0x01,0x01,0x01,0x02,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04, +-0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08, +-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x07,0x6c,0x80,0x00,0x07,0x80, +-0x80,0x00,0x07,0x80,0x80,0x00,0x07,0x70,0x80,0x00,0x07,0x70,0x80,0x00,0x07,0x94, +-0x80,0x00,0x56,0xb0,0x80,0x00,0x57,0x08,0x80,0x00,0x57,0x30,0x80,0x00,0x58,0x28, +-0x80,0x00,0x58,0xe0,0x80,0x00,0x59,0x88,0x80,0x00,0x59,0xfc,0x80,0x00,0x5b,0x08, +-0x80,0x00,0x5b,0x40,0x80,0x00,0x5b,0x54,0x80,0x00,0x5b,0x68,0x80,0x00,0x5c,0x50, +-0x80,0x00,0x5c,0x90,0x80,0x00,0x5d,0x44,0x80,0x00,0x5d,0x6c,0x80,0x00,0x56,0x70, +-0x80,0x00,0x5d,0xbc,0x80,0x00,0x64,0x48,0x80,0x00,0x64,0xc0,0x80,0x00,0x64,0xcc, +-0x80,0x00,0x64,0xd8,0x80,0x00,0x64,0x60,0x80,0x00,0x64,0x60,0x80,0x00,0x64,0x60, +-0x80,0x00,0x64,0x60,0x80,0x00,0x64,0x60,0x80,0x00,0x64,0x60,0x80,0x00,0x64,0x60, +-0x80,0x00,0x64,0x60,0x80,0x00,0x64,0x60,0x80,0x00,0x64,0x60,0x80,0x00,0x64,0x60, +-0x80,0x00,0x64,0x60,0x80,0x00,0x64,0xe4,0x80,0x00,0x64,0xf0,0x80,0x00,0x64,0xfc, +-0x80,0x00,0x87,0xa4,0x80,0x00,0x87,0xa4,0x80,0x00,0x87,0xa4,0x80,0x00,0x87,0xd8, +-0x80,0x00,0x88,0x18,0x80,0x00,0x88,0x50,0x80,0x00,0x88,0x80,0x80,0x00,0x88,0xb0, +-0x80,0x00,0x88,0xc4,0x80,0x00,0x89,0x2c,0x80,0x00,0x89,0x40,0x80,0x00,0x89,0x7c, +-0x80,0x00,0x89,0x84,0x80,0x00,0x89,0xc0,0x80,0x00,0x89,0xd4,0x80,0x00,0x89,0xdc, +-0x80,0x00,0x89,0xe4,0x80,0x00,0x89,0xe4,0x80,0x00,0x89,0xe4,0x80,0x00,0x89,0xe4, +-0x80,0x00,0x8a,0x14,0x80,0x00,0x8a,0x28,0x80,0x00,0x8a,0x3c,0x80,0x00,0x86,0xe8, +-0x80,0x00,0x8d,0x68,0x80,0x00,0x8d,0x68,0x80,0x00,0x8d,0x68,0x80,0x00,0x8d,0x9c, +-0x80,0x00,0x8d,0xdc,0x80,0x00,0x8e,0x14,0x80,0x00,0x8e,0x44,0x80,0x00,0x8e,0x74, +-0x80,0x00,0x8e,0x88,0x80,0x00,0x8e,0xf0,0x80,0x00,0x8f,0x04,0x80,0x00,0x8f,0x40, +-0x80,0x00,0x8f,0x48,0x80,0x00,0x8f,0x84,0x80,0x00,0x8f,0x98,0x80,0x00,0x8f,0xa0, +-0x80,0x00,0x8f,0xa8,0x80,0x00,0x8f,0xa8,0x80,0x00,0x8f,0xa8,0x80,0x00,0x8f,0xa8, +-0x80,0x00,0x8f,0xd8,0x80,0x00,0x8f,0xec,0x80,0x00,0x90,0x00,0x80,0x00,0x8b,0x88, +-}; + + u32 Rtl8192PciEPHY_REGArray[PHY_REGArrayLengthPciE] = {0x0,}; + +diff --git a/drivers/staging/rtl8192u/r819xU_firmware.c b/drivers/staging/rtl8192u/r819xU_firmware.c +index 4bb5fff..a8ae860 100644 +--- a/drivers/staging/rtl8192u/r819xU_firmware.c ++++ b/drivers/staging/rtl8192u/r819xU_firmware.c +@@ -284,10 +284,8 @@ bool init_firmware(struct net_device *dev) + */ + if(rst_opt == OPT_SYSTEM_RESET) { + rc = request_firmware(&fw_entry, fw_name[init_step],&priv->udev->dev); +- if(rc < 0 ) { +- RT_TRACE(COMP_ERR, "request firmware fail!\n"); ++ if (rc) + goto download_firmware_fail; +- } + + if(fw_entry->size > sizeof(pfirmware->firmware_buf)) { + RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n"); +diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c +index cc893c0..f05ae86 100644 +--- a/drivers/staging/rtl8712/hal_init.c ++++ b/drivers/staging/rtl8712/hal_init.c +@@ -50,7 +50,6 @@ static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context) + if (!firmware) { + struct usb_device *udev = padapter->dvobjpriv.pusbdev; + struct usb_interface *pusb_intf = padapter->pusb_intf; +- printk(KERN_ERR "r8712u: Firmware request failed\n"); + padapter->fw_found = false; + usb_put_dev(udev); + usb_set_intfdata(pusb_intf, NULL); +diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c +index 77a0751..106e8f3 100644 +--- a/drivers/staging/slicoss/slicoss.c ++++ b/drivers/staging/slicoss/slicoss.c +@@ -519,11 +519,8 @@ static int slic_card_download_gbrcv(struct adapter *adapter) + } + + ret = request_firmware(&fw, file, &adapter->pcidev->dev); +- if (ret) { +- dev_err(&adapter->pcidev->dev, +- "SLICOSS: Failed to load firmware %s\n", file); ++ if (ret) + return ret; +- } + + rcvucodelen = *(u32 *)(fw->data + index); + index += 4; +@@ -597,11 +594,8 @@ static int slic_card_download(struct adapter *adapter) + break; + } + ret = request_firmware(&fw, file, &adapter->pcidev->dev); +- if (ret) { +- dev_err(&adapter->pcidev->dev, +- "SLICOSS: Failed to load firmware %s\n", file); ++ if (ret) + return ret; +- } + numsects = *(u32 *)(fw->data + index); + index += 4; + ASSERT(numsects <= 3); +diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c +index 8c8126a..f1d3946 100644 +--- a/drivers/staging/vt6656/firmware.c ++++ b/drivers/staging/vt6656/firmware.c +@@ -76,11 +76,8 @@ FIRMWAREbDownload( + int rc; + + rc = request_firmware(&pDevice->firmware, FIRMWARE_NAME, dev); +- if (rc) { +- dev_err(dev, "firmware file %s request failed (%d)\n", +- FIRMWARE_NAME, rc); ++ if (rc) + goto out; +- } + } + fw = pDevice->firmware; + +diff --git a/drivers/staging/wlags49_h2/Kconfig b/drivers/staging/wlags49_h2/Kconfig +index 3efcbf8..8f6933c 100644 +--- a/drivers/staging/wlags49_h2/Kconfig ++++ b/drivers/staging/wlags49_h2/Kconfig +@@ -1,6 +1,7 @@ + config WLAGS49_H2 + tristate "Agere Systems HERMES II Wireless PC Card Model 0110" + depends on WLAN && PCMCIA ++ depends on BROKEN + select WIRELESS_EXT + select WEXT_SPY + select WEXT_PRIV +diff --git a/drivers/staging/wlags49_h2/ap_h2.c b/drivers/staging/wlags49_h2/ap_h2.c +deleted file mode 100644 +index eb8244c..0000000 +--- a/drivers/staging/wlags49_h2/ap_h2.c ++++ /dev/null +@@ -1,3337 +0,0 @@ +-/* +- * File: ap_h24.236 +- * +- * Abstract: This file contains memory image 'fw_image'. +- * +- * Contents: Total size of the memory image: 51010 bytes. +- * Total number of blocks: 4 blocks. +- * Block 1 : load address 00000060, 326 bytes. +- * Block 2 : load address 00000C16, 6424 bytes. +- * Block 3 : load address 001E252E, 444 bytes. +- * Block 4 : load address 001F4000, 43816 bytes. +- * +- * Identity: component id: 32 (variant 2) version 2.36 +- * +- * Compatibility: +- * supplying interface 8 (variant 2) : 2 - 4 +- * acting on interface 1 (variant 4) : 6 - 7 +- * acting on interface 1 (variant 5) : 6 - 7 +- * acting on interface 1 (variant 6) : 6 - 7 +- * acting on interface 2 (variant 2) : 1 - 2 +- * +- * Generated: by g:\fw\fupu3.exe version 4.26 +- * +- * Commandline: g:\fw\fupu3.exe /f=4 /n=fw_image /i=t2023600.hex +- */ +- +- +-#include "hcfcfg.h" /* to get hcf_16 etc defined as well as */ +- /* possible settings which inluence mdd.h or dhf.h */ +-#include "mdd.h" /* to get COMP_ID_STA etc defined */ +-#include "dhf.h" /* used to be "fhfmem.h", to get memblock,plugrecord, */ +- +-static const hcf_8 fw_image_1_data[] = { +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x0D, 0x00, 0x00, +- 0x3A, 0x0C, 0x00, 0x00, 0x3A, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, +- 0x0A, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0xEA, 0x00, 0x00, 0xFF, 0x07, 0x02, 0x00, 0x64, 0x00, 0x64, 0x00, 0x10, 0x27, 0x10, 0x27, +- 0x14, 0x00, 0xD0, 0x07, 0xD0, 0x07, 0x10, 0x27, 0x2F, 0x00, 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, +- 0x02, 0x00, 0x02, 0x00, 0x10, 0x27, 0x05, 0x00, 0x00, 0x02, 0x00, 0x02, 0x13, 0x00, 0x0A, 0x00, +- 0x07, 0x00, 0x03, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x09, 0x2B, 0x09, 0x2B, 0x09, +- 0x03, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x14, 0x01, 0x00, 0x40, 0x00, 0x32, 0x00, 0x32, 0x00, +- 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- +-}; /* fw_image_1_data */ +- +-static const hcf_8 fw_image_2_data[] = { +- 0x9B, 0xA7, 0x00, 0x0A, 0x10, 0x01, 0x68, 0xA4, 0xB0, 0x01, 0x84, 0x01, 0x30, 0x33, 0x31, 0x33, +- 0x44, 0x44, 0x30, 0x33, 0x31, 0x33, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, 0x32, 0x33, 0x90, 0x00, +- 0x78, 0x04, 0xAE, 0xE4, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, +- 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x84, 0xF8, 0x99, 0xEE, +- 0x8D, 0xF6, 0x0D, 0xFF, 0xBD, 0xD6, 0xB1, 0xDE, 0x54, 0x91, 0x50, 0x60, 0x03, 0x02, 0xA9, 0xCE, +- 0x7D, 0x56, 0x19, 0xE7, 0x62, 0xB5, 0xE6, 0x4D, 0x9A, 0xEC, 0x45, 0x8F, 0x9D, 0x1F, 0x40, 0x89, +- 0x87, 0xFA, 0x15, 0xEF, 0xEB, 0xB2, 0xC9, 0x8E, 0x0B, 0xFB, 0xEC, 0x41, 0x67, 0xB3, 0xFD, 0x5F, +- 0xEA, 0x45, 0xBF, 0x23, 0xF7, 0x53, 0x96, 0xE4, 0x5B, 0x9B, 0xC2, 0x75, 0x1C, 0xE1, 0xAE, 0x3D, +- 0x6A, 0x4C, 0x5A, 0x6C, 0x41, 0x7E, 0x02, 0xF5, 0x4F, 0x83, 0x5C, 0x68, 0xF4, 0x51, 0x34, 0xD1, +- 0x08, 0xF9, 0x93, 0xE2, 0x73, 0xAB, 0x53, 0x62, 0x3F, 0x2A, 0x0C, 0x08, 0x52, 0x95, 0x65, 0x46, +- 0x5E, 0x9D, 0x28, 0x30, 0xA1, 0x37, 0x0F, 0x0A, 0xB5, 0x2F, 0x09, 0x0E, 0x36, 0x24, 0x9B, 0x1B, +- 0x3D, 0xDF, 0x26, 0xCD, 0x69, 0x4E, 0xCD, 0x7F, 0x9F, 0xEA, 0x1B, 0x12, 0x9E, 0x1D, 0x74, 0x58, +- 0x2E, 0x34, 0x2D, 0x36, 0xB2, 0xDC, 0xEE, 0xB4, 0xFB, 0x5B, 0xF6, 0xA4, 0x4D, 0x76, 0x61, 0xB7, +- 0xCE, 0x7D, 0x7B, 0x52, 0x3E, 0xDD, 0x71, 0x5E, 0x97, 0x13, 0xF5, 0xA6, 0x68, 0xB9, 0x00, 0x00, +- 0x2C, 0xC1, 0x60, 0x40, 0x1F, 0xE3, 0xC8, 0x79, 0xED, 0xB6, 0xBE, 0xD4, 0x46, 0x8D, 0xD9, 0x67, +- 0x4B, 0x72, 0xDE, 0x94, 0xD4, 0x98, 0xE8, 0xB0, 0x4A, 0x85, 0x6B, 0xBB, 0x2A, 0xC5, 0xE5, 0x4F, +- 0x16, 0xED, 0xC5, 0x86, 0xD7, 0x9A, 0x55, 0x66, 0x94, 0x11, 0xCF, 0x8A, 0x10, 0xE9, 0x06, 0x04, +- 0x81, 0xFE, 0xF0, 0xA0, 0x44, 0x78, 0xBA, 0x25, 0xE3, 0x4B, 0xF3, 0xA2, 0xFE, 0x5D, 0xC0, 0x80, +- 0x8A, 0x05, 0xAD, 0x3F, 0xBC, 0x21, 0x48, 0x70, 0x04, 0xF1, 0xDF, 0x63, 0xC1, 0x77, 0x75, 0xAF, +- 0x63, 0x42, 0x30, 0x20, 0x1A, 0xE5, 0x0E, 0xFD, 0x6D, 0xBF, 0x4C, 0x81, 0x14, 0x18, 0x35, 0x26, +- 0x2F, 0xC3, 0xE1, 0xBE, 0xA2, 0x35, 0xCC, 0x88, 0x39, 0x2E, 0x57, 0x93, 0xF2, 0x55, 0x82, 0xFC, +- 0x47, 0x7A, 0xAC, 0xC8, 0xE7, 0xBA, 0x2B, 0x32, 0x95, 0xE6, 0xA0, 0xC0, 0x98, 0x19, 0xD1, 0x9E, +- 0x7F, 0xA3, 0x66, 0x44, 0x7E, 0x54, 0xAB, 0x3B, 0x83, 0x0B, 0xCA, 0x8C, 0x29, 0xC7, 0xD3, 0x6B, +- 0x3C, 0x28, 0x79, 0xA7, 0xE2, 0xBC, 0x1D, 0x16, 0x76, 0xAD, 0x3B, 0xDB, 0x56, 0x64, 0x4E, 0x74, +- 0x1E, 0x14, 0xDB, 0x92, 0x0A, 0x0C, 0x6C, 0x48, 0xE4, 0xB8, 0x5D, 0x9F, 0x6E, 0xBD, 0xEF, 0x43, +- 0xA6, 0xC4, 0xA8, 0x39, 0xA4, 0x31, 0x37, 0xD3, 0x8B, 0xF2, 0x32, 0xD5, 0x43, 0x8B, 0x59, 0x6E, +- 0xB7, 0xDA, 0x8C, 0x01, 0x64, 0xB1, 0xD2, 0x9C, 0xE0, 0x49, 0xB4, 0xD8, 0xFA, 0xAC, 0x07, 0xF3, +- 0x25, 0xCF, 0xAF, 0xCA, 0x8E, 0xF4, 0xE9, 0x47, 0x18, 0x10, 0xD5, 0x6F, 0x88, 0xF0, 0x6F, 0x4A, +- 0x72, 0x5C, 0x24, 0x38, 0xF1, 0x57, 0xC7, 0x73, 0x51, 0x97, 0x23, 0xCB, 0x7C, 0xA1, 0x9C, 0xE8, +- 0x21, 0x3E, 0xDD, 0x96, 0xDC, 0x61, 0x86, 0x0D, 0x85, 0x0F, 0x90, 0xE0, 0x42, 0x7C, 0xC4, 0x71, +- 0xAA, 0xCC, 0xD8, 0x90, 0x05, 0x06, 0x01, 0xF7, 0x12, 0x1C, 0xA3, 0xC2, 0x5F, 0x6A, 0xF9, 0xAE, +- 0xD0, 0x69, 0x91, 0x17, 0x58, 0x99, 0x27, 0x3A, 0xB9, 0x27, 0x38, 0xD9, 0x13, 0xEB, 0xB3, 0x2B, +- 0x33, 0x22, 0xBB, 0xD2, 0x70, 0xA9, 0x89, 0x07, 0xA7, 0x33, 0xB6, 0x2D, 0x22, 0x3C, 0x92, 0x15, +- 0x20, 0xC9, 0x49, 0x87, 0xFF, 0xAA, 0x78, 0x50, 0x7A, 0xA5, 0x8F, 0x03, 0xF8, 0x59, 0x80, 0x09, +- 0x17, 0x1A, 0xDA, 0x65, 0x31, 0xD7, 0xC6, 0x84, 0xB8, 0xD0, 0xC3, 0x82, 0xB0, 0x29, 0x77, 0x5A, +- 0x11, 0x1E, 0xCB, 0x7B, 0xFC, 0xA8, 0xD6, 0x6D, 0x3A, 0x2C, 0x00, 0x30, 0x00, 0x31, 0x00, 0x33, +- 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x38, 0x00, 0x3A, 0x00, 0x3B, +- 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x3F, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x02, 0x14, +- 0x05, 0x32, 0x0B, 0x37, 0x08, 0x50, 0x0B, 0x6E, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x3F, 0x00, +- 0x0C, 0x00, 0x30, 0x00, 0x03, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0x3C, 0x00, 0x02, 0x00, 0x04, 0x00, +- 0x0A, 0x00, 0x0B, 0x00, 0x10, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x63, 0x00, 0x20, 0x00, 0x63, 0x00, 0x63, 0x00, 0x20, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x10, +- 0x9E, 0x10, 0x56, 0x10, 0x98, 0x10, 0x5C, 0x10, 0x92, 0x10, 0x62, 0x10, 0x8C, 0x10, 0x68, 0x10, +- 0x86, 0x10, 0x6E, 0x10, 0x80, 0x10, 0x74, 0x10, 0x7A, 0x10, 0x07, 0x01, 0x00, 0x00, 0x0A, 0x22, +- 0x00, 0x04, 0x08, 0x01, 0x00, 0x00, 0x0A, 0x26, 0x00, 0x04, 0x09, 0x01, 0x00, 0x00, 0x0A, 0x2A, +- 0x00, 0x04, 0x0A, 0x01, 0x00, 0x00, 0x0A, 0x2E, 0x00, 0x04, 0x0B, 0x01, 0x00, 0x00, 0x10, 0x24, +- 0x04, 0x04, 0x0C, 0x01, 0x00, 0x00, 0x10, 0x28, 0x04, 0x04, 0x0D, 0x01, 0x00, 0x00, 0x10, 0x2C, +- 0x04, 0x04, 0x0E, 0x01, 0x00, 0x00, 0x10, 0x30, 0x04, 0x04, 0x0F, 0x01, 0x00, 0x00, 0x16, 0x34, +- 0x08, 0x04, 0x10, 0x01, 0x00, 0x00, 0x16, 0x38, 0x08, 0x04, 0x11, 0x01, 0x00, 0x00, 0x16, 0x3C, +- 0x08, 0x04, 0x12, 0x01, 0x00, 0x00, 0x16, 0x40, 0x08, 0x04, 0x13, 0x01, 0x00, 0x00, 0x17, 0x64, +- 0x0C, 0x0B, 0x14, 0x01, 0x00, 0x00, 0x17, 0x68, 0x0C, 0x0B, 0x15, 0x01, 0x00, 0x00, 0x17, 0x6C, +- 0x0C, 0x0B, 0x16, 0x01, 0x00, 0x00, 0x17, 0x70, 0x0C, 0x0B, 0x17, 0x01, 0x00, 0x00, 0x17, 0x74, +- 0x0C, 0x0B, 0x18, 0x01, 0x00, 0x00, 0x17, 0x78, 0x0C, 0x0B, 0x19, 0x01, 0x00, 0x00, 0x17, 0x7C, +- 0x0C, 0x0B, 0x1A, 0x01, 0x00, 0x00, 0x17, 0x80, 0x0C, 0x0B, 0x1B, 0x01, 0x00, 0x00, 0x17, 0x84, +- 0x0C, 0x0B, 0x1C, 0x01, 0x00, 0x00, 0x17, 0x88, 0x0C, 0x0B, 0x1D, 0x01, 0x00, 0x00, 0x17, 0x8C, +- 0x0C, 0x0B, 0x1E, 0x01, 0x00, 0x00, 0x1D, 0x95, 0x17, 0x04, 0x1F, 0x01, 0x00, 0x00, 0x1D, 0x99, +- 0x17, 0x04, 0x20, 0x01, 0x00, 0x00, 0x1D, 0x9D, 0x17, 0x04, 0x21, 0x01, 0x00, 0x00, 0x1D, 0xA1, +- 0x17, 0x04, 0x22, 0x01, 0x00, 0x00, 0x0E, 0xA5, 0x00, 0x00, 0xC0, 0x10, 0xE0, 0x10, 0x00, 0x11, +- 0x20, 0x11, 0x78, 0x11, 0xC8, 0x10, 0xE8, 0x10, 0x08, 0x11, 0x28, 0x11, 0x80, 0x11, 0xD0, 0x10, +- 0xF0, 0x10, 0x10, 0x11, 0x30, 0x11, 0x88, 0x11, 0xD8, 0x10, 0xF8, 0x10, 0x18, 0x11, 0x38, 0x11, +- 0x90, 0x11, 0x40, 0x11, 0x48, 0x11, 0x50, 0x11, 0x58, 0x11, 0x60, 0x11, 0x68, 0x11, 0x70, 0x11, +- 0x98, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2, 0x14, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xEB, 0xBA, 0xEB, +- 0xDF, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, +- 0x57, 0xEB, 0x90, 0xF1, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0xD6, 0xED, +- 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, +- 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x2F, 0xEE, +- 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, +- 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0xA4, 0xED, 0xBE, 0xED, +- 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x57, 0xEB, 0x7F, 0xF4, 0x19, 0xEC, +- 0x2C, 0xEC, 0xDC, 0xEC, 0xE0, 0xEC, 0x57, 0xEB, 0x57, 0xEB, 0x8F, 0xED, 0x84, 0xE3, 0x59, 0xE3, +- 0xD7, 0xE3, 0x28, 0xE4, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xEB, 0xF6, 0xEB, 0x72, 0xF0, 0x72, 0xF0, +- 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0x89, 0xEE, 0x45, 0xF0, 0x5A, 0x00, 0x02, 0x00, 0xF9, 0xFF, +- 0x89, 0xEE, 0x9F, 0xEE, 0xCC, 0x00, 0x02, 0x00, 0xF7, 0xFF, 0x89, 0xEE, 0x9F, 0xEE, 0xB6, 0x1F, +- 0x06, 0x00, 0xF0, 0xFF, 0x89, 0xEE, 0x73, 0xEE, 0x00, 0x00, 0x00, 0x02, 0xF6, 0xFF, 0x89, 0xEE, +- 0x9F, 0xEE, 0x6C, 0x00, 0x02, 0x00, 0xF4, 0xFF, 0x89, 0xEE, 0x9F, 0xEE, 0x6A, 0x01, 0x02, 0x00, +- 0xF5, 0xFF, 0x89, 0xEE, 0x4E, 0xF0, 0xA8, 0x1F, 0x02, 0x00, 0xE0, 0xFF, 0x89, 0xEE, 0x9F, 0xEE, +- 0xEE, 0x21, 0x02, 0x00, 0xE1, 0xFF, 0x89, 0xEE, 0x9F, 0xEE, 0xF0, 0x21, 0x02, 0x00, 0xE2, 0xFF, +- 0x89, 0xEE, 0x9F, 0xEE, 0xF2, 0x21, 0x02, 0x00, 0xE3, 0xFF, 0x89, 0xEE, 0x9F, 0xEE, 0xEA, 0x21, +- 0x02, 0x00, 0x03, 0xFC, 0x89, 0xEE, 0xE5, 0xEF, 0x7C, 0x21, 0x02, 0x00, 0x04, 0xFC, 0x89, 0xEE, +- 0x99, 0xEE, 0xBE, 0x1F, 0x22, 0x00, 0x06, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0xA6, 0x1F, 0x02, 0x00, +- 0x07, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x02, 0x20, 0x02, 0x00, 0x0E, 0xFC, 0x89, 0xEE, 0xF7, 0xEF, +- 0x0C, 0x20, 0x22, 0x00, 0xB1, 0xFC, 0x89, 0xEE, 0x58, 0xF2, 0x2C, 0x21, 0x02, 0x00, 0x20, 0xFC, +- 0x89, 0xEE, 0x9F, 0xEE, 0x32, 0x20, 0x02, 0x00, 0x25, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x3C, 0x20, +- 0x02, 0x00, 0x26, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x3E, 0x20, 0x02, 0x00, 0x27, 0xFC, 0x89, 0xEE, +- 0x9F, 0xEE, 0x40, 0x20, 0x02, 0x00, 0xB2, 0xFC, 0x89, 0xEE, 0x99, 0xEE, 0x50, 0x21, 0x22, 0x00, +- 0xC1, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x98, 0x21, 0x20, 0x00, 0xB0, 0xFC, 0x69, 0xEE, 0x5D, 0xF2, +- 0x00, 0x00, 0x00, 0x00, 0xC4, 0xFC, 0x69, 0xEE, 0x68, 0xF0, 0x00, 0x00, 0x08, 0x00, 0xC8, 0xFC, +- 0x69, 0xEE, 0x63, 0xF0, 0x00, 0x00, 0x08, 0x00, 0xB4, 0xFC, 0x69, 0xEE, 0x9B, 0xF2, 0x00, 0x00, +- 0x00, 0x00, 0xB6, 0xFC, 0x69, 0xEE, 0x4E, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xFC, 0x69, 0xEE, +- 0x90, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xFC, 0x69, 0xEE, 0xED, 0xF3, 0x00, 0x00, 0x00, 0x00, +- 0xB5, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0xE6, 0x21, 0x02, 0x00, 0xB9, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, +- 0xE8, 0x21, 0x02, 0x00, 0x90, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0xEC, 0x21, 0x02, 0x00, 0x23, 0xFC, +- 0x89, 0xEE, 0x9F, 0xEE, 0x38, 0x20, 0x02, 0x00, 0x29, 0xFC, 0x48, 0xEF, 0xF5, 0xEE, 0x00, 0x00, +- 0x00, 0x00, 0xC2, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x74, 0x21, 0x02, 0x00, 0x32, 0xFC, 0x89, 0xEE, +- 0x9F, 0xEE, 0x60, 0x01, 0x02, 0x00, 0x33, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x62, 0x01, 0x02, 0x00, +- 0x10, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0xAE, 0x1F, 0x02, 0x00, 0x11, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, +- 0x46, 0x20, 0x06, 0x00, 0x12, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x4C, 0x20, 0x06, 0x00, 0x13, 0xFC, +- 0x89, 0xEE, 0x9F, 0xEE, 0x52, 0x20, 0x06, 0x00, 0x14, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x58, 0x20, +- 0x06, 0x00, 0x15, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x5E, 0x20, 0x06, 0x00, 0x16, 0xFC, 0x89, 0xEE, +- 0x9F, 0xEE, 0x64, 0x20, 0x06, 0x00, 0x17, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x2E, 0x20, 0x02, 0x00, +- 0x83, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x6E, 0x01, 0x02, 0x00, 0x97, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, +- 0x6C, 0x01, 0x02, 0x00, 0x98, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE4, 0x00, 0x02, 0x00, 0x99, 0xFC, +- 0x31, 0xF0, 0x1F, 0xF0, 0xE4, 0x02, 0x02, 0x00, 0x9A, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE4, 0x04, +- 0x02, 0x00, 0x9B, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE4, 0x06, 0x02, 0x00, 0x9C, 0xFC, 0x31, 0xF0, +- 0x1F, 0xF0, 0xE4, 0x08, 0x02, 0x00, 0x9D, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE4, 0x0A, 0x02, 0x00, +- 0x18, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x30, 0x20, 0x02, 0x00, 0x22, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, +- 0x36, 0x20, 0x02, 0x00, 0x24, 0xFC, 0x89, 0xEE, 0x9F, 0xEE, 0x3A, 0x20, 0x02, 0x00, 0xC0, 0xFC, +- 0x69, 0xEE, 0x61, 0xF0, 0x00, 0x00, 0x06, 0x00, 0x9E, 0xFC, 0x89, 0xEE, 0x17, 0xF0, 0x70, 0x01, +- 0x02, 0x00, 0x9F, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE6, 0x00, 0x02, 0x00, 0xA0, 0xFC, 0x31, 0xF0, +- 0x1F, 0xF0, 0xE6, 0x02, 0x02, 0x00, 0xA1, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE6, 0x04, 0x02, 0x00, +- 0xA2, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE6, 0x06, 0x02, 0x00, 0xA3, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, +- 0xE6, 0x08, 0x02, 0x00, 0xA4, 0xFC, 0x31, 0xF0, 0x1F, 0xF0, 0xE6, 0x0A, 0x02, 0x00, 0x20, 0xFD, +- 0xBA, 0xEE, 0x73, 0xEE, 0x53, 0xF5, 0x08, 0x00, 0x21, 0xFD, 0xBA, 0xEE, 0x73, 0xEE, 0x57, 0xF5, +- 0x0A, 0x00, 0x22, 0xFD, 0xBA, 0xEE, 0x73, 0xEE, 0x5C, 0xF5, 0x16, 0x00, 0x23, 0xFD, 0xBA, 0xEE, +- 0x73, 0xEE, 0x67, 0xF5, 0x0A, 0x00, 0x10, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0x34, 0x01, 0x02, 0x00, +- 0x45, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0xCC, 0x00, 0x02, 0x00, 0x47, 0xFD, 0x89, 0xEE, 0x73, 0xEE, +- 0x38, 0x01, 0x02, 0x00, 0x48, 0xFD, 0x9E, 0xEF, 0x73, 0xEE, 0x60, 0x01, 0x02, 0x00, 0x49, 0xFD, +- 0x9E, 0xEF, 0x73, 0xEE, 0x62, 0x01, 0x02, 0x00, 0x4A, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0x58, 0x01, +- 0x02, 0x00, 0x4B, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0x5A, 0x01, 0x02, 0x00, 0x4D, 0xFD, 0xBA, 0xEE, +- 0x73, 0xEE, 0x6C, 0xF5, 0x04, 0x00, 0x4F, 0xFD, 0xB2, 0xEF, 0x73, 0xEE, 0x80, 0x21, 0x02, 0x00, +- 0xC0, 0xFD, 0xBA, 0xEE, 0x73, 0xEE, 0x6E, 0xF5, 0x02, 0x00, 0xC2, 0xFD, 0xA8, 0xEF, 0x73, 0xEE, +- 0x00, 0x00, 0x02, 0x00, 0xC3, 0xFD, 0xBA, 0xEE, 0x73, 0xEE, 0x6F, 0xF5, 0x02, 0x00, 0x40, 0xFD, +- 0xB2, 0xEE, 0x73, 0xEE, 0x78, 0x01, 0x02, 0x00, 0x24, 0xFD, 0xD8, 0xEF, 0x73, 0xEE, 0x00, 0x00, +- 0x02, 0x00, 0x91, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0x86, 0x1B, 0x02, 0x00, 0x93, 0xFD, 0x89, 0xEE, +- 0x73, 0xEE, 0x8C, 0x1B, 0x02, 0x00, 0xC1, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0xCA, 0x00, 0x02, 0x00, +- 0xC6, 0xFD, 0xE7, 0xEE, 0x73, 0xEE, 0x8E, 0x21, 0x0A, 0x00, 0x89, 0xFD, 0x5F, 0xEF, 0x73, 0xEE, +- 0x00, 0x00, 0x00, 0x00, 0x8A, 0xFD, 0xD7, 0xEE, 0x73, 0xEE, 0xC0, 0x21, 0x24, 0x00, 0x46, 0xFD, +- 0x89, 0xEE, 0x73, 0xEE, 0x7A, 0x01, 0x06, 0x00, 0x86, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0xB6, 0x1F, +- 0x06, 0x00, 0x87, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0xB8, 0x21, 0x06, 0x00, 0x8B, 0xFD, 0x7A, 0xF3, +- 0x73, 0xEE, 0x00, 0x00, 0x12, 0x00, 0x8E, 0xFD, 0x89, 0xEE, 0x73, 0xEE, 0xB8, 0x12, 0x02, 0x00, +- 0x80, 0xFD, 0xBC, 0xEF, 0x73, 0xEE, 0x1C, 0x00, 0x02, 0x00, 0x81, 0xFD, 0xBC, 0xEF, 0x73, 0xEE, +- 0x1C, 0x02, 0x02, 0x00, 0x82, 0xFD, 0xBC, 0xEF, 0x73, 0xEE, 0x1C, 0x04, 0x02, 0x00, 0x83, 0xFD, +- 0xBC, 0xEF, 0x73, 0xEE, 0x1C, 0x06, 0x02, 0x00, 0x84, 0xFD, 0xBC, 0xEF, 0x73, 0xEE, 0x1C, 0x08, +- 0x02, 0x00, 0x85, 0xFD, 0xBC, 0xEF, 0x73, 0xEE, 0x1C, 0x0A, 0x02, 0x00, 0x00, 0xF1, 0x46, 0x00, +- 0x2D, 0xEE, 0xF8, 0x00, 0x00, 0x03, 0x8A, 0xEA, 0x1F, 0x00, 0x36, 0x01, 0xCA, 0x00, 0x96, 0x01, +- 0xCE, 0x00, 0xFC, 0x00, 0x78, 0x01, 0xDA, 0x1E, 0x1A, 0x01, 0x86, 0x1B, 0xC8, 0x00, 0x00, 0x00, +- 0xCE, 0x12, 0x00, 0x00, 0xD2, 0x14, 0x14, 0x01, 0x03, 0x00, 0xAE, 0x00, 0xE4, 0x00, 0x3C, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x77, 0xB4, 0xEA, 0xB3, 0x26, 0xB5, 0x2F, 0xB5, 0xFB, 0xB3, 0xA4, 0xB4, 0x69, 0xB4, 0xE7, 0xC5, +- 0x4A, 0xC5, 0xE7, 0xC5, 0xBE, 0xC5, 0x54, 0xC5, 0x48, 0xC5, 0x06, 0xC6, 0x17, 0xC6, 0x17, 0xC6, +- 0x17, 0xC6, 0x20, 0xC6, 0x3B, 0xC6, 0x98, 0xC6, 0xB4, 0xC6, 0xBF, 0xC5, 0xD2, 0xC5, 0xA6, 0xC5, +- 0x10, 0x00, 0x12, 0x00, 0x13, 0x00, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x30, 0x00, 0x31, 0x00, +- 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, +- 0x3A, 0x00, 0x00, 0x00, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, +- 0x14, 0x01, 0x14, 0x01, 0xF3, 0x02, 0xAD, 0x03, 0x60, 0x04, 0x04, 0x05, 0x07, 0x06, 0x08, 0x07, +- 0x0A, 0x08, 0x16, 0x09, 0x44, 0x0A, 0x04, 0x0B, 0x40, 0x0C, 0x80, 0x0D, 0x00, 0x0E, 0x84, 0x0F, +- 0x01, 0x10, 0x10, 0x11, 0x02, 0x14, 0x40, 0x20, 0x32, 0x21, 0x32, 0x22, 0x04, 0x23, 0x01, 0x24, +- 0x0F, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x28, 0x00, 0x29, 0x00, 0x2A, 0x01, 0x2B, 0x06, 0x2C, +- 0x00, 0x38, 0x00, 0x39, 0xD6, 0x3A, 0x00, 0x3B, 0x00, 0x3C, 0x14, 0x3D, 0x7F, 0x3E, 0x00, 0x3F, +- 0x68, 0x40, 0x75, 0x41, 0x07, 0x42, 0x07, 0x43, 0x00, 0x45, 0x3B, 0x4A, 0x00, 0x4B, 0x00, 0x4C, +- 0x0F, 0x4D, 0x02, 0x75, 0x00, 0x76, 0x80, 0x00, 0x08, 0x01, 0x09, 0x01, 0x09, 0x01, 0x0A, 0x01, +- 0x0A, 0x01, 0x0B, 0x01, 0x0B, 0x01, 0x0C, 0x01, 0x0C, 0x01, 0x0D, 0x01, 0x0D, 0x01, 0x0E, 0x01, +- 0x0E, 0x01, 0x0F, 0x01, 0x0F, 0x01, 0x10, 0x01, 0x10, 0x01, 0x11, 0x01, 0x11, 0x01, 0x12, 0x01, +- 0x12, 0x01, 0x13, 0x01, 0x13, 0x01, 0x14, 0x01, 0x14, 0x01, 0x15, 0x01, 0x15, 0x01, 0x16, 0x01, +- 0x16, 0x01, 0x17, 0x01, 0x17, 0x01, 0x18, 0x01, 0x18, 0x01, 0x19, 0x01, 0x19, 0x01, 0x4D, 0x01, +- 0x4D, 0x01, 0x4E, 0x01, 0x4E, 0x01, 0x4F, 0x01, 0x4F, 0x01, 0x50, 0x01, 0x50, 0x01, 0x51, 0x01, +- 0x51, 0x01, 0x52, 0x01, 0x52, 0x01, 0x53, 0x01, 0x53, 0x01, 0x54, 0x01, 0x54, 0x01, 0x65, 0x01, +- 0x65, 0x01, 0x66, 0x01, 0x66, 0x01, 0x67, 0x01, 0x67, 0x01, 0x68, 0x01, 0x68, 0x01, 0x69, 0x01, +- 0x69, 0x01, 0x6A, 0x01, 0x6A, 0x01, 0x6B, 0x01, 0x6B, 0x01, 0x6C, 0x01, 0x6C, 0x01, 0x6D, 0x01, +- 0x6D, 0x01, 0x6E, 0x01, 0x6E, 0x01, 0x6F, 0x01, 0x6F, 0x01, 0x70, 0x01, 0x70, 0x01, 0x71, 0x01, +- 0x71, 0x01, 0x72, 0x01, 0x72, 0x01, 0x73, 0x01, 0x73, 0x01, 0x74, 0x01, 0x74, 0x01, 0x75, 0x01, +- 0x75, 0x01, 0x76, 0x01, 0x76, 0x01, 0x77, 0x01, 0x77, 0x01, 0x78, 0x01, 0x78, 0x01, 0x79, 0x01, +- 0x79, 0x01, 0x7A, 0x01, 0x7A, 0x01, 0x7B, 0x01, 0x7B, 0x01, 0x7C, 0x01, 0x7C, 0x01, 0x7D, 0x01, +- 0x7D, 0x01, 0x7E, 0x01, 0x7E, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, +- 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, +- 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, +- 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, +- 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, +- 0x80, 0x12, 0x80, 0x12, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, +- 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, +- 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, +- 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x22, 0x46, 0x22, 0x46, +- 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, +- 0x22, 0x46, 0x23, 0x46, 0x23, 0x46, 0x23, 0x46, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, +- 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, +- 0x1C, 0x47, 0x1D, 0x47, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0xDA, 0x48, +- 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0x33, 0x48, +- 0x78, 0x49, 0x78, 0x49, 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, 0x7A, 0x49, 0x7A, 0x49, +- 0x7A, 0x49, 0x7A, 0x49, 0x7B, 0x49, 0x7B, 0x49, 0x7B, 0x49, 0x7C, 0x49, 0x32, 0x00, 0x46, 0x00, +- 0x5A, 0x00, 0x6E, 0x00, 0x82, 0x00, 0x96, 0x00, 0xAA, 0x00, 0xBE, 0x00, 0xD2, 0x00, 0xE6, 0x00, +- 0xFA, 0x00, 0x0E, 0x01, 0x22, 0x01, 0x52, 0x01, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, +- 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, +- 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, +- 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, +- 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, +- 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +- 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, +- 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, +- 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, +- 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, +- 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +- 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x69, 0x72, 0x73, 0x74, 0x20, +- 0x57, 0x61, 0x76, 0x65, 0x4C, 0x41, 0x4E, 0x20, 0x49, 0x49, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x02, 0x01, 0x82, 0x84, 0x8B, 0x96, 0x00, 0x00, +- 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, +- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xDD, 0x00, 0x50, 0xF2, 0x01, +- 0x01, 0x00, 0x00, 0x50, 0xF2, 0x05, 0x02, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x50, 0xF2, 0x04, +- 0x02, 0x00, 0x00, 0x50, 0xF2, 0x00, 0x00, 0x50, 0xF2, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, +- 0x15, 0x00, 0x02, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x04, 0x00, 0x10, 0x00, 0x02, 0x00, +- 0x01, 0x00, 0x04, 0x00, 0x15, 0x00, 0x20, 0x00, 0x11, 0x00, 0x20, 0x00, 0x1E, 0x1F, 0x8E, 0x21, +- 0x00, 0x23, 0xDA, 0x22, 0x04, 0x23, 0xC0, 0x21, 0xFF, 0xFF, 0xFF, 0xFF, 0x34, 0x23, 0x00, 0x00, +- 0x50, 0x21, 0x8E, 0x21, 0xFF, 0xFF, 0x00, 0x00, 0x1E, 0x1F, 0x8E, 0x21, 0x00, 0x23, 0xFF, 0xFF, +- 0x04, 0x23, 0xC0, 0x21, 0xFF, 0xFF, 0xFF, 0xFF, 0x34, 0x23, 0x00, 0x00, 0x8E, 0x21, 0x3C, 0x23, +- 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00, 0x06, 0x07, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, +- 0x00, 0x60, 0x1D, 0x00, 0x00, 0x00, 0x0D, 0x81, 0x00, 0x60, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, +- +-}; /* fw_image_2_data */ +- +-static const hcf_8 fw_image_3_data[] = { +- 0x3F, 0x41, 0xA5, 0x4C, 0x50, 0x37, 0x04, 0x00, 0x01, 0xB9, 0x41, 0x5F, 0xB5, 0x60, 0x55, 0xE0, +- 0x0C, 0x60, 0x10, 0x62, 0xA2, 0xD3, 0x01, 0x60, 0x01, 0x65, 0xD4, 0x80, 0x5A, 0xD1, 0x0F, 0x02, +- 0x5A, 0xD3, 0x3E, 0x60, 0x00, 0x66, 0xE0, 0x87, 0x40, 0x4A, 0xEA, 0x60, 0x88, 0x61, 0x64, 0x44, +- 0xC8, 0x84, 0x0C, 0x63, 0xAA, 0x46, 0x58, 0xD0, 0xAA, 0x46, 0x59, 0xD8, 0xFB, 0x1F, 0x08, 0x60, +- 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, 0xA3, 0xD3, 0x02, 0xA8, 0xD4, 0x80, 0x61, 0x02, +- 0x60, 0x02, 0x26, 0x60, 0x6A, 0x61, 0x3C, 0x60, 0x00, 0x66, 0x41, 0x4B, 0x2B, 0x41, 0x26, 0x60, +- 0xB2, 0x7C, 0xD1, 0x80, 0xA1, 0xD2, 0x25, 0x05, 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, +- 0xE0, 0x87, 0x40, 0x4A, 0x59, 0xD2, 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, +- 0xBD, 0xD1, 0xEC, 0x18, 0xD4, 0x80, 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, +- 0x67, 0x44, 0xC0, 0x84, 0xE0, 0x85, 0x2C, 0x44, 0xD4, 0x80, 0x63, 0x41, 0x01, 0x06, 0x65, 0x44, +- 0xC8, 0x83, 0xAA, 0x46, 0x59, 0xD1, 0x27, 0xD8, 0x5A, 0x87, 0xFC, 0x1F, 0xAA, 0x46, 0x2B, 0x41, +- 0xD5, 0x01, 0x26, 0x60, 0xB2, 0x61, 0x41, 0x4B, 0x2B, 0x41, 0x26, 0x60, 0xEA, 0x7C, 0xD1, 0x80, +- 0xA1, 0xD2, 0x27, 0x05, 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, 0xE0, 0x87, 0x40, 0x4A, +- 0x59, 0xD2, 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, 0xEC, 0x18, +- 0xD4, 0x80, 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x04, 0xA3, 0xA3, 0xD1, +- 0x5A, 0x88, 0x2C, 0x43, 0xD3, 0x80, 0xFF, 0xFF, 0x01, 0x06, 0x64, 0x43, 0xCF, 0x83, 0xAA, 0x46, +- 0x60, 0xFE, 0x28, 0xD1, 0x5E, 0x88, 0x27, 0xD8, 0x5A, 0x87, 0xFB, 0x1F, 0x20, 0xFE, 0xAA, 0x46, +- 0xD3, 0x01, 0xB8, 0xFE, 0xB9, 0xFE, 0xBA, 0xFE, 0xBB, 0xFE, 0xBD, 0xFE, 0xBF, 0xFE, 0x21, 0x60, +- 0x80, 0x62, 0xA2, 0xD3, 0x12, 0x63, 0x60, 0x40, 0x01, 0x27, 0x05, 0x00, 0x0B, 0x60, 0xEA, 0x62, +- 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0xA2, 0x60, 0x49, 0x78, 0xFF, 0xFF, 0xF1, 0xFF, 0x94, 0x48, +- 0x1F, 0x00, 0x04, 0x00, 0xF2, 0xFF, 0x98, 0x48, 0x1F, 0x00, 0x04, 0x00, 0xFB, 0xFF, 0xA0, 0x48, +- 0x1F, 0x00, 0x04, 0x00, 0xF1, 0xFF, 0xF2, 0x4D, 0x1F, 0x00, 0x04, 0x00, 0xF2, 0xFF, 0xF6, 0x4D, +- 0x1F, 0x00, 0x04, 0x00, 0xFB, 0xFF, 0xFE, 0x4D, 0x1F, 0x00, 0x04, 0x00, 0x86, 0xFD, 0xB6, 0x1F, +- 0x00, 0x00, 0x06, 0x00, 0x10, 0xFD, 0x34, 0x01, 0x00, 0x00, 0x02, 0x00, 0x14, 0xFD, 0x7E, 0x21, +- 0x00, 0x00, 0x0A, 0x00, 0x20, 0xFA, 0xFA, 0x1D, 0x00, 0x00, 0x0E, 0x00, 0x21, 0xFA, 0xDE, 0x1D, +- 0x00, 0x00, 0x0E, 0x00, 0x22, 0xFA, 0x16, 0x1E, 0x00, 0x00, 0x0E, 0x00, 0x23, 0xFA, 0xCA, 0x1C, +- 0x00, 0x00, 0x01, 0x00, 0x24, 0xFA, 0xBE, 0x1E, 0x00, 0x00, 0x0E, 0x00, 0x25, 0xFA, 0xDE, 0x1C, +- 0x00, 0x00, 0x80, 0x00, 0x26, 0xFA, 0xC4, 0x1C, 0x00, 0x00, 0x01, 0x00, +- +-}; /* fw_image_3_data */ +- +-static const hcf_8 fw_image_4_data[] = { +- 0xA6, 0x60, 0x25, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA6, 0x60, 0x0B, 0x78, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA6, 0x60, 0x11, 0x78, 0xC4, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA5, 0x60, 0x61, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x44, 0xFF, 0x20, 0x54, 0xCD, 0xE2, 0xA6, 0x60, 0x23, 0x78, 0x08, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA6, 0x60, 0x25, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA6, 0x60, 0x25, 0x78, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA6, 0x60, 0x25, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAC, 0x60, 0x81, 0x78, 0x4C, 0x4E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAC, 0x60, 0x18, 0x78, 0x4C, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC4, 0xE2, 0x84, 0xFF, 0x22, 0x58, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA7, 0x60, 0xC4, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xE4, 0xE2, 0xAC, 0x60, 0x31, 0x78, 0x95, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBF, 0x60, 0x76, 0x78, 0x64, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAC, 0x60, 0x8C, 0x78, 0xA4, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAC, 0x60, 0x72, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB2, 0x60, 0xD1, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB2, 0x60, 0xFE, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB1, 0x60, 0x90, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB1, 0x60, 0xC0, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB1, 0x60, 0xC0, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB4, 0x60, 0x73, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB1, 0x60, 0xC3, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0x60, 0x83, 0x64, 0x80, 0x29, 0x09, 0xFB, 0xB2, 0x60, 0x99, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC0, 0x60, 0x29, 0x78, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBF, 0x60, 0xB4, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBE, 0x60, 0x78, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBD, 0x60, 0xE8, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB5, 0x60, 0x96, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x83, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC0, 0x60, 0x9F, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xB0, 0xFF, 0xB1, 0xFF, 0x40, 0xFF, 0x43, 0xFF, 0xC0, 0x60, 0x9A, 0x78, 0x44, 0xFF, 0xFF, 0x01, +- 0xC0, 0x60, 0x9F, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xC6, 0x60, 0x66, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xC0, 0x60, 0x9A, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xC0, 0x60, 0x99, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xC7, 0x60, 0x26, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xE5, 0x60, 0x0E, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC7, 0x60, 0x2E, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC7, 0x60, 0x2E, 0x78, 0x24, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xE3, 0x60, 0x45, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC7, 0x60, 0x2E, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC7, 0x60, 0x2E, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC7, 0x60, 0x2E, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xEB, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xEB, 0x60, 0x87, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xEB, 0x60, 0xA0, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xEB, 0x60, 0x84, 0x78, 0x28, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xEB, 0x60, 0x84, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xEB, 0x60, 0x84, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xEB, 0x60, 0x84, 0x78, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0x60, 0x87, 0x64, 0x80, 0x29, 0x09, 0xFB, 0x47, 0xFF, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x87, 0xF3, 0x88, 0xF3, 0xDC, 0x81, 0x00, 0x7C, 0x01, 0x00, 0x00, 0xFA, 0x60, 0x46, 0xFE, 0x63, +- 0xA3, 0xD8, 0xFE, 0x1F, 0xCD, 0x81, 0xD8, 0x84, 0xF8, 0x02, 0x87, 0xF3, 0x88, 0xF5, 0xDC, 0x81, +- 0x80, 0x67, 0x40, 0x4A, 0x14, 0x60, 0x02, 0x65, 0x01, 0x7C, 0x07, 0x18, 0x2A, 0x43, 0x02, 0xFC, +- 0x5F, 0x8A, 0x8E, 0xF8, 0x70, 0xF8, 0x00, 0xF4, 0xF8, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0x89, 0xF5, +- 0x06, 0x64, 0x66, 0x43, 0x00, 0x7C, 0x63, 0x46, 0xFE, 0x63, 0xA3, 0xD8, 0xFE, 0x1F, 0xCC, 0x84, +- 0x66, 0x43, 0xDB, 0x83, 0xF8, 0x02, 0x14, 0x60, 0x02, 0x65, 0x09, 0x60, 0x2B, 0x7C, 0x89, 0xF3, +- 0x06, 0x61, 0x60, 0x46, 0x01, 0x63, 0x72, 0xF8, 0x00, 0xFC, 0x63, 0x47, 0x06, 0xFA, 0x72, 0xF8, +- 0x8E, 0xF8, 0xDF, 0x83, 0x66, 0x44, 0xCD, 0x81, 0x02, 0xA6, 0xF5, 0x02, 0x89, 0xF3, 0x06, 0x61, +- 0x60, 0x46, 0x03, 0x7C, 0x73, 0xF8, 0x66, 0x44, 0xCD, 0x81, 0x02, 0xA6, 0xFB, 0x02, 0x2E, 0x58, +- 0xFF, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x0A, 0x00, 0x42, 0x60, 0x09, 0xE0, 0x3F, 0x40, 0x01, 0x2A, +- 0x03, 0x00, 0x60, 0x60, 0x1C, 0xE0, 0x02, 0x00, 0x80, 0x60, 0x1C, 0xE0, 0x40, 0xEC, 0x00, 0xED, +- 0x02, 0xEE, 0x80, 0x60, 0x58, 0xEC, 0x80, 0x60, 0x00, 0xED, 0x80, 0x60, 0x82, 0xEE, 0xC0, 0x60, +- 0x59, 0xEC, 0xC0, 0x60, 0x07, 0xED, 0xAD, 0x4F, 0xFE, 0xB4, 0xA0, 0x5D, 0x00, 0xF3, 0x28, 0xFB, +- 0x40, 0x44, 0xA4, 0x60, 0x5D, 0x7C, 0x20, 0xF9, 0xA5, 0x60, 0x48, 0x7C, 0x21, 0xF9, 0xA7, 0x60, +- 0x30, 0x7C, 0x22, 0xF9, 0xB0, 0x60, 0xCD, 0x7C, 0x23, 0xF9, 0xB5, 0x60, 0x6C, 0x7C, 0x24, 0xF9, +- 0xC0, 0x60, 0x88, 0x7C, 0x25, 0xF9, 0xC6, 0x60, 0xE0, 0x7C, 0x26, 0xF9, 0x91, 0x60, 0x00, 0xE8, +- 0x28, 0xE8, 0x44, 0x60, 0x02, 0xE6, 0x00, 0x64, 0x40, 0x52, 0x10, 0x60, 0x04, 0xE6, 0x08, 0x60, +- 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, 0xBD, 0xD3, 0x02, 0xA8, 0xD4, 0x80, 0x47, 0x02, +- 0x46, 0x02, 0xDB, 0x83, 0xFA, 0x60, 0x27, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, 0x1A, 0x18, 0xC3, 0x83, +- 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xDB, 0x83, 0xD3, 0x83, 0xD3, 0x86, 0x64, 0x41, 0xCD, 0x81, +- 0xA6, 0xD1, 0xDA, 0x86, 0x1C, 0x60, 0x68, 0x65, 0x00, 0x60, 0x72, 0x63, 0xA5, 0xD3, 0xDA, 0x85, +- 0x90, 0x84, 0xFF, 0x27, 0x02, 0x00, 0xA2, 0xD9, 0x01, 0x00, 0xF8, 0x1F, 0xCD, 0x81, 0xFF, 0xFF, +- 0xEF, 0x02, 0x08, 0x60, 0x06, 0x63, 0xFA, 0x60, 0x28, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, 0x0B, 0x18, +- 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xBF, 0xD3, 0x21, 0x60, 0x72, 0x62, 0x0E, 0xB4, +- 0xE0, 0x84, 0xE0, 0x84, 0xA2, 0xDB, 0x08, 0x60, 0x06, 0x63, 0xFD, 0x60, 0x0C, 0x65, 0x5B, 0xD3, +- 0xBF, 0xD1, 0x0D, 0x18, 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xFA, 0xA3, 0xA3, 0xD3, +- 0x02, 0x60, 0x00, 0x65, 0xF7, 0xA0, 0xFC, 0xA0, 0x0A, 0x05, 0x01, 0x05, 0x00, 0x00, 0x21, 0x60, +- 0x00, 0x65, 0x3F, 0x43, 0x3F, 0x43, 0x21, 0x60, 0x00, 0x65, 0xC0, 0x60, 0x8F, 0xEE, 0xB7, 0x84, +- 0x40, 0x5F, 0x00, 0x60, 0x30, 0xE2, 0x00, 0x60, 0x50, 0xE2, 0x00, 0x60, 0x79, 0xE2, 0x00, 0x60, +- 0x90, 0xE2, 0x01, 0x60, 0xD0, 0xE2, 0x01, 0x60, 0xF0, 0xE2, 0x01, 0x60, 0xB0, 0xE2, 0x26, 0x64, +- 0x35, 0xFB, 0x01, 0x60, 0x30, 0x64, 0x0A, 0xA4, 0x38, 0xFB, 0x60, 0x45, 0x00, 0x60, 0xF8, 0x64, +- 0x0A, 0xA4, 0x39, 0xFB, 0x35, 0xF1, 0x0A, 0x64, 0xC4, 0x84, 0x36, 0xFB, 0xC0, 0x84, 0x0A, 0xA4, +- 0x37, 0xFB, 0x09, 0x60, 0x2A, 0x64, 0x99, 0xFB, 0x82, 0xFF, 0x92, 0xFF, 0x5C, 0x41, 0x5C, 0x46, +- 0x5C, 0x47, 0x00, 0xE1, 0xA7, 0x60, 0x9B, 0x63, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x87, 0xFF, +- 0x97, 0xFF, 0x0C, 0x60, 0x02, 0x64, 0x40, 0x5A, 0x06, 0xA4, 0x40, 0x5B, 0x5C, 0x5E, 0x5C, 0x51, +- 0x1F, 0x60, 0xAA, 0x62, 0xA2, 0xD3, 0x65, 0xFB, 0x21, 0x60, 0xEC, 0x61, 0x27, 0x7C, 0xA1, 0xD9, +- 0x25, 0x60, 0x2E, 0x63, 0x7F, 0xA3, 0xE3, 0x87, 0x00, 0x7F, 0x8A, 0xFB, 0x02, 0x60, 0x80, 0x66, +- 0x22, 0x60, 0x22, 0x64, 0x77, 0x60, 0x77, 0x63, 0x00, 0xFA, 0x01, 0xFC, 0x00, 0xF0, 0x01, 0xF0, +- 0xD0, 0x80, 0xD3, 0x80, 0x1E, 0x02, 0x1D, 0x02, 0x06, 0x60, 0x80, 0x65, 0x45, 0x4A, 0xAA, 0x46, +- 0x00, 0xFC, 0x01, 0xFA, 0xAA, 0x46, 0x00, 0xF0, 0x2A, 0x41, 0x50, 0x65, 0xD3, 0x80, 0xCD, 0x84, +- 0x13, 0x03, 0x0A, 0x60, 0x80, 0x65, 0x45, 0x4A, 0xAA, 0x46, 0x00, 0xFC, 0x01, 0xFA, 0xAA, 0x46, +- 0x00, 0xF0, 0x65, 0x41, 0xC8, 0x65, 0xD3, 0x80, 0xCD, 0x84, 0x06, 0x03, 0x12, 0x60, 0x7F, 0x64, +- 0x03, 0x00, 0x10, 0x65, 0x02, 0x60, 0x7F, 0x64, 0x65, 0x43, 0x87, 0xFD, 0x1B, 0x60, 0x72, 0x62, +- 0xA2, 0xDD, 0x07, 0x61, 0xC5, 0x81, 0xE1, 0x85, 0xD4, 0x84, 0x8B, 0xFB, 0xDC, 0x84, 0x89, 0xFB, +- 0x0C, 0xA4, 0x88, 0xFB, 0x1B, 0x60, 0x74, 0x62, 0xA2, 0xDB, 0xA2, 0x60, 0x58, 0x4E, 0x1F, 0x78, +- 0xFF, 0xFF, 0xA2, 0x60, 0x58, 0x4E, 0x00, 0x78, 0xFF, 0xFF, 0x8B, 0xF1, 0x8A, 0xF3, 0x7C, 0x63, +- 0x8D, 0xFB, 0x60, 0x46, 0x01, 0xFC, 0xDC, 0x84, 0xD0, 0x80, 0x00, 0xFA, 0xFA, 0x04, 0x8E, 0xFB, +- 0x60, 0x46, 0x00, 0x64, 0x00, 0xFA, 0x63, 0x44, 0x80, 0x7F, 0x01, 0xFA, 0x8B, 0xF3, 0x8A, 0xF1, +- 0xDC, 0x84, 0xD0, 0x84, 0x8C, 0xFB, 0x03, 0x60, 0x26, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x64, 0x78, +- 0xFF, 0xFF, 0x66, 0x44, 0x2E, 0xFB, 0x82, 0xFF, 0x40, 0x42, 0x87, 0xFF, 0x8C, 0xF3, 0x94, 0xFB, +- 0x00, 0x64, 0x12, 0x60, 0xC8, 0x63, 0xA3, 0xDB, 0x00, 0x64, 0x40, 0x50, 0x63, 0xFF, 0x66, 0xFF, +- 0x65, 0xFF, 0x64, 0xFF, 0x61, 0xFF, 0x62, 0xFF, 0x49, 0x60, 0x02, 0xE1, 0x52, 0x60, 0x02, 0xE1, +- 0x5B, 0x60, 0x02, 0xE1, 0x65, 0x60, 0x02, 0xE1, 0x6C, 0x60, 0x02, 0xE1, 0x76, 0x60, 0x02, 0xE1, +- 0x41, 0x60, 0x02, 0xE1, 0x04, 0x65, 0x21, 0x60, 0x7E, 0x64, 0x44, 0xD3, 0xEA, 0x60, 0x58, 0x4E, +- 0x78, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0x04, 0x65, 0x0C, 0x64, 0xA5, 0xDB, 0xA3, 0x60, 0xED, 0x64, +- 0x80, 0xFB, 0x2D, 0xFF, 0x0A, 0x61, 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, 0xB3, 0x60, 0x58, 0x4D, +- 0x64, 0x78, 0xFF, 0xFF, 0xF0, 0x67, 0x0E, 0xFA, 0x1B, 0x60, 0xE0, 0x62, 0x1B, 0x60, 0xC4, 0x64, +- 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x2B, 0x41, +- 0x4D, 0x8B, 0xFF, 0xFF, 0xE9, 0x02, 0x0A, 0x61, 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, 0xB3, 0x60, +- 0x58, 0x4D, 0x64, 0x78, 0xFF, 0xFF, 0x1B, 0x60, 0xE0, 0x62, 0x1B, 0x60, 0xB8, 0x64, 0xA2, 0xDB, +- 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x2B, 0x41, 0x4D, 0x8B, +- 0xFF, 0xFF, 0xEB, 0x02, 0xEB, 0x60, 0x4E, 0x78, 0xFF, 0xFF, 0x00, 0xEA, 0x00, 0xEB, 0x50, 0x60, +- 0x03, 0xEA, 0x51, 0x60, 0x13, 0xEA, 0x52, 0x60, 0x30, 0xEA, 0x53, 0x60, 0x40, 0xEA, 0x54, 0x60, +- 0x52, 0xEA, 0x55, 0x60, 0x6D, 0xEA, 0x56, 0x60, 0x71, 0xEA, 0x57, 0x60, 0x8B, 0xEA, 0x58, 0x60, +- 0x47, 0xEA, 0x59, 0x60, 0xA0, 0xEA, 0x5A, 0x60, 0xB2, 0xEA, 0x5B, 0x60, 0xC1, 0xEA, 0x5C, 0x60, +- 0xD7, 0xEA, 0x5D, 0x60, 0xEB, 0xEA, 0x5E, 0x60, 0xA0, 0xEA, 0x50, 0x60, 0x36, 0xEB, 0x51, 0x60, +- 0x37, 0xEB, 0x52, 0x60, 0x20, 0xEB, 0x53, 0x60, 0xE4, 0xEB, 0x54, 0x60, 0x34, 0xEB, 0x55, 0x60, +- 0x58, 0xEB, 0x56, 0x60, 0x48, 0xEB, 0x57, 0x60, 0xD0, 0xEB, 0x58, 0x60, 0xC3, 0xEB, 0x59, 0x60, +- 0xFC, 0xEB, 0x5A, 0x60, 0x34, 0xEB, 0x5B, 0x60, 0x58, 0xEB, 0x5C, 0x60, 0xC0, 0xEB, 0x5D, 0x60, +- 0xD0, 0xEB, 0x5E, 0x60, 0x91, 0xEB, 0x00, 0xEA, 0x00, 0xEB, 0xE0, 0x60, 0x02, 0xEA, 0xE0, 0x60, +- 0x03, 0xEB, 0xA0, 0x60, 0x00, 0xEB, 0xB0, 0x60, 0x00, 0xEB, 0xAB, 0x48, 0x40, 0x3B, 0x01, 0x00, +- 0xFC, 0x01, 0x00, 0xEB, 0x03, 0x60, 0x02, 0x62, 0x62, 0x44, 0xA2, 0xDB, 0x0F, 0x64, 0x60, 0x7F, +- 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x3F, 0x40, +- 0x40, 0x26, 0x08, 0x00, 0x00, 0x60, 0x18, 0x64, 0x00, 0x60, 0x00, 0x65, 0x94, 0x84, 0xA0, 0x50, +- 0x1D, 0x60, 0x19, 0xE2, 0x24, 0x44, 0xFF, 0xB4, 0x04, 0xFB, 0x50, 0x60, 0x00, 0x64, 0x05, 0xFB, +- 0x10, 0x60, 0x10, 0x75, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0x80, 0xFF, 0x90, 0xFF, 0x98, 0xFF, +- 0x23, 0x60, 0x5C, 0x63, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, +- 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, +- 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, +- 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, +- 0x2F, 0x44, 0xBD, 0xDB, 0x23, 0x60, 0x50, 0x64, 0xA0, 0xDD, 0x24, 0x60, 0x7C, 0x63, 0x23, 0x60, +- 0x52, 0x64, 0xA0, 0xDD, 0x23, 0x60, 0x54, 0x63, 0x30, 0x44, 0xA3, 0xDB, 0x23, 0x60, 0x56, 0x63, +- 0x31, 0x44, 0xA3, 0xDB, 0x23, 0x60, 0x58, 0x63, 0x32, 0x44, 0xA3, 0xDB, 0x23, 0x60, 0x5A, 0x63, +- 0x33, 0x44, 0xA3, 0xDB, 0x81, 0xFF, 0x91, 0xFF, 0x58, 0x51, 0x48, 0x00, 0x82, 0xFF, 0x92, 0xFF, +- 0x58, 0x51, 0x44, 0x00, 0x83, 0xFF, 0x93, 0xFF, 0x58, 0x51, 0x40, 0x00, 0x84, 0xFF, 0x94, 0xFF, +- 0x58, 0x51, 0x3C, 0x00, 0x85, 0xFF, 0x95, 0xFF, 0x58, 0x51, 0x38, 0x00, 0x86, 0xFF, 0x96, 0xFF, +- 0x58, 0x51, 0x34, 0x00, 0x87, 0xFF, 0x97, 0xFF, 0x58, 0x51, 0x30, 0x00, 0x80, 0xFF, 0x90, 0xFF, +- 0x99, 0xFF, 0x23, 0x60, 0x50, 0x64, 0xA0, 0xD1, 0x30, 0x44, 0x64, 0x43, 0xBD, 0xDB, 0x31, 0x44, +- 0xBD, 0xDB, 0x32, 0x44, 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, 0x35, 0x44, +- 0xBD, 0xDB, 0x36, 0x44, 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, 0x39, 0x44, +- 0xBD, 0xDB, 0x3A, 0x44, 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, 0x3D, 0x44, +- 0xBD, 0xDB, 0x3E, 0x44, 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0xE3, 0x60, 0x50, 0x64, 0x0A, 0xFB, +- 0x40, 0x21, 0xFE, 0x01, 0xA1, 0xFF, 0xFF, 0xFF, 0x78, 0x01, 0xFF, 0xFF, 0x42, 0x50, 0x40, 0x53, +- 0x23, 0x60, 0x52, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x52, 0x33, 0x44, 0x32, 0x42, 0xA2, 0xDB, +- 0xDA, 0x82, 0xA2, 0xDD, 0xDA, 0x83, 0x65, 0x44, 0xBD, 0xDB, 0x61, 0x44, 0xBD, 0xDB, 0x66, 0x44, +- 0xBD, 0xDB, 0xBD, 0xD9, 0x30, 0x44, 0xBD, 0xDB, 0x99, 0xFF, 0xA4, 0x4C, 0xBD, 0xDB, 0xA5, 0x4C, +- 0xBD, 0xDB, 0xA0, 0x4C, 0xBD, 0xDB, 0xA1, 0x4C, 0xBD, 0xDB, 0x98, 0xFF, 0x23, 0x60, 0x52, 0x64, +- 0xA0, 0xDD, 0x23, 0x60, 0x54, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x50, 0x23, 0x60, 0x58, 0x62, +- 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x52, 0x23, 0x60, 0x5A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x53, +- 0x31, 0x41, 0x23, 0x60, 0x56, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x51, 0x23, 0x60, 0x50, 0x62, +- 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x43, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, +- 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, +- 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, +- 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, +- 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, 0x23, 0x60, 0x50, 0x64, 0xA0, 0xDD, 0x61, 0x58, 0xFF, 0xFF, +- 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x07, 0x02, 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, +- 0x66, 0xFF, 0xBF, 0xFE, 0xA1, 0xFF, 0x82, 0xFF, 0x88, 0xFF, 0x6C, 0x40, 0x41, 0xFF, 0xC4, 0xE2, +- 0x43, 0xFF, 0x5C, 0x49, 0x08, 0xE1, 0xA5, 0x60, 0x5E, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0x98, 0xFF, +- 0x80, 0x3E, 0x9F, 0xFE, 0x03, 0x04, 0xA6, 0x60, 0x28, 0x78, 0xFF, 0xFF, 0xE2, 0xFE, 0x40, 0x05, +- 0xE0, 0xFE, 0x5B, 0x05, 0xE1, 0xFE, 0xF2, 0x04, 0x29, 0x40, 0x08, 0x26, 0xEF, 0x01, 0x72, 0x44, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x95, 0xF3, 0xE8, 0x85, 0xFF, 0xB7, +- 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x85, 0x73, 0x44, 0xD4, 0x84, 0x10, 0x65, 0xD4, 0x80, 0xFF, 0xFF, +- 0x26, 0x04, 0x3F, 0x40, 0x40, 0x26, 0x13, 0x00, 0x0B, 0x60, 0xF8, 0x62, 0xA2, 0xD1, 0x00, 0x60, +- 0x10, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xF8, 0xA2, 0xA2, 0xD1, 0x0A, 0x60, 0x19, 0x64, 0x90, 0x84, +- 0xA0, 0x52, 0x06, 0xA2, 0xA2, 0xD1, 0x46, 0x60, 0x09, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xD2, 0xF4, +- 0x25, 0x60, 0x16, 0x7C, 0x63, 0x40, 0x01, 0x26, 0x08, 0x00, 0xA4, 0xD3, 0xFF, 0xFF, 0x01, 0xB4, +- 0xFF, 0xFF, 0x03, 0x02, 0xAD, 0x4F, 0xFE, 0xB4, 0xA0, 0x5D, 0x02, 0xEE, 0xBD, 0xFE, 0xBE, 0x01, +- 0x21, 0x46, 0x5E, 0x62, 0x9A, 0xFF, 0x07, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x06, 0x25, 0x10, 0x00, +- 0xA2, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x62, 0x62, 0x01, 0x5D, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, +- 0x7A, 0xDC, 0x44, 0xFF, 0x06, 0x25, 0x04, 0x00, 0x0E, 0xE1, 0x02, 0x60, 0x01, 0xE1, 0x9E, 0x01, +- 0x62, 0xFF, 0xC4, 0xE2, 0x41, 0xFF, 0x0A, 0xE1, 0x99, 0x01, 0xC8, 0x74, 0xCD, 0xE2, 0x29, 0x44, +- 0x08, 0xBC, 0x40, 0x49, 0x05, 0xE1, 0x25, 0x60, 0x18, 0x63, 0xA3, 0xD3, 0xD2, 0xF3, 0x06, 0x18, +- 0x28, 0x40, 0x08, 0x2A, 0x05, 0x00, 0x28, 0x40, 0x48, 0x36, 0x02, 0x00, 0x02, 0xBC, 0xD2, 0xFB, +- 0x3F, 0x40, 0x01, 0x2B, 0xFF, 0xFF, 0xA1, 0xFF, 0x67, 0x4C, 0x06, 0x61, 0xCD, 0x81, 0x04, 0x25, +- 0x30, 0x00, 0x87, 0x4C, 0xFB, 0x02, 0x28, 0x40, 0x40, 0x2B, 0x02, 0x00, 0x15, 0x60, 0x6F, 0x6B, +- 0xF3, 0x60, 0xA0, 0x64, 0x04, 0x25, 0x25, 0x00, 0x80, 0x4C, 0x30, 0x64, 0x3A, 0xDB, 0x44, 0xFF, +- 0x04, 0x25, 0x1F, 0x00, 0x04, 0x60, 0x00, 0x65, 0x25, 0x44, 0x37, 0x36, 0xB4, 0x84, 0x6E, 0x36, +- 0xB4, 0x84, 0x80, 0x4E, 0x24, 0x41, 0x04, 0x25, 0x14, 0x00, 0x61, 0x4C, 0x64, 0xA1, 0x61, 0x54, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x04, 0x25, 0x0D, 0x00, 0x67, 0x4E, 0x07, 0x64, 0x1C, 0xFB, 0x00, 0xE1, +- 0x02, 0x60, 0x01, 0xE1, 0x53, 0x01, 0x33, 0xF3, 0xFD, 0x11, 0xFC, 0x18, 0x40, 0x64, 0x3A, 0xDB, +- 0x0A, 0x00, 0xC4, 0xE2, 0x27, 0x44, 0x20, 0x2A, 0x04, 0x00, 0x42, 0x64, 0x3A, 0xDB, 0x67, 0x4C, +- 0x02, 0x00, 0x41, 0x64, 0x3A, 0xDB, 0x62, 0xFF, 0x08, 0xE1, 0xE2, 0xFE, 0x72, 0x52, 0x5C, 0x49, +- 0x32, 0x7B, 0x4D, 0xE2, 0x3B, 0x01, 0x08, 0xE1, 0x39, 0x01, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, +- 0x00, 0x60, 0x46, 0x74, 0xCD, 0xE2, 0x04, 0xE1, 0x02, 0x60, 0x00, 0xE1, 0x3F, 0x44, 0x40, 0x26, +- 0x0B, 0x00, 0x01, 0x2A, 0x05, 0x00, 0x42, 0x60, 0x09, 0xE0, 0x60, 0x60, 0x1C, 0xE0, 0x04, 0x00, +- 0x42, 0x60, 0x09, 0xE0, 0x80, 0x60, 0x1C, 0xE0, 0x04, 0x29, 0xFE, 0x01, 0xC4, 0xE2, 0x43, 0x64, +- 0x3A, 0xDB, 0x83, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x3F, 0x44, 0x02, 0x27, 0x84, 0x00, 0x20, 0x2B, +- 0xFF, 0x01, 0x80, 0xE1, 0x95, 0x60, 0x80, 0xE7, 0x61, 0x40, 0x40, 0x2B, 0x0D, 0x00, 0x05, 0x63, +- 0xA7, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0x28, 0x63, 0xFF, 0xFF, 0xFE, 0x1F, 0x01, 0x63, +- 0xA7, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0xFF, 0xB1, 0xCD, 0x81, 0xE1, 0x85, 0x1E, 0x60, +- 0xA2, 0x64, 0x44, 0xD1, 0xFF, 0xFF, 0x64, 0x43, 0xA7, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, +- 0x00, 0x60, 0x00, 0x63, 0xA7, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xBE, 0x61, +- 0x21, 0x60, 0x72, 0x62, 0xA2, 0xD3, 0x45, 0xD1, 0x47, 0xBC, 0xE0, 0x84, 0x62, 0x45, 0x64, 0x5F, +- 0xE8, 0x83, 0xA7, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0x82, 0xF3, 0xCD, 0xE2, 0x60, 0x54, +- 0x04, 0xE1, 0x04, 0x29, 0xFE, 0x01, 0xC4, 0xE2, 0x15, 0x60, 0xA2, 0xE7, 0x38, 0x69, 0xFF, 0xFF, +- 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, 0x01, 0x2A, 0x36, 0x00, 0x03, 0x60, 0x80, 0x7C, 0xA3, 0x83, +- 0x21, 0x60, 0x72, 0x62, 0xA2, 0xD1, 0x43, 0xBB, 0xB3, 0x83, 0x95, 0x60, 0x80, 0xE7, 0xA7, 0x60, +- 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0xE3, 0x83, 0x15, 0x60, 0xA2, 0xE7, 0x38, 0x69, 0xFF, 0xFF, +- 0x68, 0x41, 0x01, 0x16, 0xFD, 0x01, 0x63, 0x47, 0x61, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x00, 0x3A, +- 0xCC, 0x84, 0x02, 0x00, 0x07, 0x3A, 0xDC, 0x84, 0xFF, 0xB4, 0xA5, 0xDB, 0x60, 0x47, 0xE8, 0x84, +- 0x47, 0x65, 0x21, 0x60, 0x72, 0x62, 0xA2, 0xD3, 0xB4, 0x85, 0xB4, 0x83, 0x80, 0xE1, 0x95, 0x60, +- 0x80, 0xE7, 0xA7, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0x82, 0xF3, 0xCD, 0xE2, 0x60, 0x54, +- 0x04, 0x29, 0xFE, 0x01, 0xC4, 0xE2, 0x83, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x2B, 0x04, 0x00, +- 0xA6, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0xFF, 0x01, 0x83, 0xF3, 0x80, 0xE1, 0xCC, 0x84, 0xE0, 0x85, +- 0x15, 0x60, 0xA2, 0xE7, 0x1D, 0x60, 0xDE, 0x64, 0x58, 0x4F, 0x4F, 0x00, 0x1D, 0x60, 0xFA, 0x64, +- 0x58, 0x4F, 0x4B, 0x00, 0x1E, 0x60, 0x16, 0x64, 0x58, 0x4F, 0x47, 0x00, 0x1E, 0x60, 0x32, 0x64, +- 0x58, 0x4F, 0x43, 0x00, 0x1E, 0x60, 0x4E, 0x64, 0x58, 0x4F, 0x3F, 0x00, 0x1E, 0x60, 0x6A, 0x64, +- 0x58, 0x4F, 0x3B, 0x00, 0x1E, 0x60, 0x86, 0x64, 0x58, 0x4F, 0x37, 0x00, 0x01, 0x68, 0xFF, 0x6A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x3F, 0x44, 0x20, 0x27, 0x00, 0x00, 0x3F, 0x40, 0x40, 0x26, +- 0x08, 0x00, 0x00, 0x60, 0x18, 0x64, 0x00, 0x60, 0x00, 0x65, 0x94, 0x84, 0xA0, 0x50, 0x1D, 0x60, +- 0x19, 0xE2, 0xC4, 0xE2, 0x00, 0x63, 0x82, 0xFD, 0x32, 0x7B, 0x4D, 0xE2, 0xBF, 0xFE, 0xC4, 0xE2, +- 0x41, 0xFF, 0xE0, 0xFE, 0xE1, 0xFE, 0xE2, 0xFE, 0x43, 0xFF, 0x44, 0xFF, 0x46, 0xFF, 0x84, 0xF3, +- 0x62, 0xFF, 0x60, 0x40, 0x05, 0x36, 0x2D, 0xFF, 0x07, 0x36, 0xD5, 0xFE, 0x08, 0xE1, 0x88, 0x60, +- 0x85, 0x71, 0x8D, 0xE2, 0xA5, 0x60, 0x5E, 0x78, 0xFF, 0xFF, 0x50, 0xEC, 0x63, 0x4A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x40, 0xEC, 0x2F, 0x58, 0xFF, 0xFF, 0x44, 0xD3, 0x80, 0x7C, 0x60, 0x48, +- 0x60, 0x47, 0x00, 0x7F, 0xB0, 0x8A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x2F, 0x58, 0xFF, 0xFF, +- 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x02, 0x02, 0xA1, 0xFF, 0xFF, 0xFF, 0x82, 0xFF, 0x88, 0xFF, +- 0x48, 0xE2, 0x01, 0x70, 0xAE, 0xF1, 0x00, 0x6B, 0x89, 0xFF, 0x64, 0x54, 0x88, 0xFF, 0x9F, 0xFE, +- 0x02, 0x05, 0x64, 0x44, 0x60, 0x54, 0xCD, 0xE2, 0xC2, 0x64, 0x3A, 0xDB, 0xBC, 0xFF, 0xB5, 0xFF, +- 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xB4, 0x40, 0x46, 0x3C, 0x44, 0x00, 0xBC, 0xFF, 0xFF, 0x06, 0x03, +- 0x27, 0x40, 0x26, 0x22, 0x03, 0x00, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x27, 0x44, 0x20, 0x2A, +- 0x04, 0x00, 0xA0, 0x60, 0x00, 0xEA, 0xB0, 0x60, 0x00, 0xEA, 0x5C, 0x4D, 0x27, 0x44, 0x18, 0xB4, +- 0x40, 0x47, 0x00, 0xE1, 0x6C, 0x40, 0x44, 0xE2, 0xC4, 0xE2, 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, +- 0x32, 0xF1, 0x08, 0x29, 0x09, 0x00, 0x64, 0x40, 0x07, 0x22, 0x06, 0x00, 0x43, 0xFF, 0x27, 0x44, +- 0x10, 0xBC, 0x40, 0x47, 0x00, 0x64, 0x32, 0xFB, 0x31, 0x41, 0x3C, 0x44, 0x01, 0xB1, 0x00, 0xBC, +- 0x0A, 0x02, 0x09, 0x03, 0x32, 0xF3, 0x00, 0x7C, 0x01, 0xB4, 0xFF, 0xFF, 0x04, 0x03, 0x32, 0xF9, +- 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x00, 0x64, +- 0x33, 0xFB, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x32, 0xF3, 0x08, 0x29, +- 0x0A, 0x00, 0x60, 0x40, 0x07, 0x22, 0x07, 0x00, 0xFE, 0xB4, 0x32, 0xFB, 0x27, 0x44, 0x10, 0xBC, +- 0xF7, 0xB4, 0x40, 0x47, 0x43, 0xFF, 0x00, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x08, 0xE1, 0x31, 0x40, +- 0x01, 0x2A, 0x04, 0x00, 0x00, 0x64, 0x33, 0xFB, 0x01, 0x60, 0x0A, 0xE1, 0xE5, 0xFE, 0x13, 0x05, +- 0x27, 0x44, 0x10, 0x26, 0x13, 0x00, 0x9F, 0xFE, 0x02, 0x04, 0x02, 0xE1, 0x06, 0x00, 0x3E, 0xE1, +- 0x31, 0x44, 0x01, 0x2A, 0x02, 0x00, 0x04, 0x0A, 0xBF, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, +- 0xAF, 0x60, 0x19, 0x78, 0xFF, 0xFF, 0xA8, 0x60, 0x09, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x08, 0x26, +- 0xFF, 0xFF, 0xBF, 0x60, 0x2A, 0x78, 0xFF, 0xFF, 0x48, 0xF3, 0x32, 0xF1, 0x00, 0x63, 0x64, 0x40, +- 0x03, 0x22, 0x3D, 0x00, 0x31, 0x40, 0x08, 0x26, 0xF4, 0x01, 0xCD, 0xE2, 0x84, 0xE1, 0x70, 0x41, +- 0xAD, 0x80, 0x71, 0x40, 0x80, 0x27, 0xED, 0x12, 0x03, 0x03, 0xBF, 0x60, 0x7C, 0x78, 0xFF, 0xFF, +- 0xA1, 0xFF, 0xFF, 0xFF, 0xC4, 0xE2, 0x32, 0xFD, 0x60, 0x40, 0x01, 0x2A, 0xDF, 0x01, 0x00, 0x63, +- 0x32, 0xFD, 0x6C, 0x40, 0x3C, 0x46, 0x3E, 0xF2, 0x2A, 0xF0, 0x27, 0x41, 0x44, 0x48, 0x20, 0xB9, +- 0x01, 0xB4, 0xF7, 0xB1, 0x0A, 0x03, 0x64, 0x40, 0x08, 0x27, 0x07, 0x00, 0x0F, 0x60, 0x92, 0x63, +- 0x00, 0x64, 0x45, 0xFB, 0x46, 0xFB, 0xBD, 0xDB, 0xA3, 0xDB, 0xCB, 0x0A, 0x41, 0x47, 0x3F, 0x40, +- 0x01, 0x2B, 0x04, 0x00, 0xF6, 0xFE, 0x67, 0x4C, 0x05, 0x60, 0x69, 0x6B, 0x02, 0xE1, 0x01, 0x60, +- 0x08, 0xE1, 0xF0, 0xFE, 0x84, 0xFF, 0xBF, 0x60, 0xAD, 0x64, 0x40, 0x42, 0x82, 0xFF, 0xE5, 0xFE, +- 0x03, 0x04, 0xAC, 0x60, 0x41, 0x78, 0xFF, 0xFF, 0xE4, 0xFE, 0x0A, 0x04, 0x1D, 0xFF, 0x00, 0xEB, +- 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, +- 0x43, 0xFF, 0xE6, 0xFE, 0x03, 0x05, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0x3C, 0x44, 0x60, 0x46, +- 0x0F, 0xF0, 0x40, 0x42, 0x64, 0x40, 0x01, 0x2A, 0x03, 0x00, 0xAB, 0x60, 0x03, 0x78, 0xFF, 0xFF, +- 0x0B, 0x64, 0x3A, 0xDB, 0x1C, 0x42, 0x22, 0x46, 0x13, 0xF2, 0xFF, 0x65, 0x60, 0x47, 0x2A, 0xF2, +- 0x40, 0x45, 0x40, 0x48, 0x04, 0x2B, 0x17, 0x00, 0x16, 0xF2, 0x1D, 0xF2, 0x40, 0x43, 0x0F, 0xF2, +- 0x40, 0x44, 0x25, 0x5E, 0x3F, 0x40, 0x01, 0x27, 0x40, 0x45, 0x0F, 0x64, 0x14, 0xF0, 0x35, 0xF2, +- 0xA0, 0x82, 0x0F, 0xB4, 0xCA, 0x85, 0xD4, 0x80, 0x10, 0xF2, 0x01, 0x02, 0x2B, 0xFA, 0x27, 0x44, +- 0x40, 0xBC, 0x40, 0x47, 0x13, 0x00, 0x17, 0xF2, 0x2C, 0xF0, 0x40, 0x43, 0x1B, 0xF2, 0x1D, 0xFA, +- 0x40, 0x44, 0x64, 0x40, 0x01, 0x2A, 0x02, 0x00, 0xAB, 0xFC, 0x05, 0x00, 0x28, 0x40, 0xA4, 0x36, +- 0x02, 0x00, 0x11, 0xF2, 0x2B, 0xFA, 0x27, 0x44, 0xBF, 0xB4, 0x40, 0x47, 0x28, 0x40, 0x40, 0x2B, +- 0xFF, 0xFF, 0xAF, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0x22, 0x46, 0x2C, 0xF0, 0x27, 0x44, 0xDF, 0xB4, +- 0x40, 0x47, 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, +- 0x08, 0x60, 0x00, 0x6B, 0x64, 0x40, 0x01, 0x2A, 0x01, 0x00, 0x13, 0x00, 0x2A, 0xF0, 0x01, 0x65, +- 0x64, 0x40, 0xA4, 0x3A, 0x04, 0x65, 0x27, 0x44, 0x34, 0x87, 0x36, 0xF3, 0xB4, 0xFF, 0x60, 0x5B, +- 0x4D, 0xE2, 0x04, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x0A, 0xE1, 0x2B, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x81, 0x3E, 0x06, 0x64, 0x3A, 0xDB, 0x22, 0x46, 0x01, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xBF, 0x60, +- 0x85, 0x78, 0xFF, 0xFF, 0xB5, 0xFF, 0xA1, 0xFF, 0x6C, 0x40, 0x3F, 0x40, 0x01, 0x2B, 0x03, 0x00, +- 0x67, 0x4C, 0x05, 0x60, 0x69, 0x6B, 0x02, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0xC4, 0xE2, 0x08, 0x64, +- 0x3A, 0xDB, 0xF0, 0xFE, 0x25, 0x46, 0x01, 0xF2, 0x61, 0x45, 0xD4, 0x9E, 0x21, 0x46, 0x16, 0xFA, +- 0x2A, 0x44, 0x72, 0x45, 0x24, 0xFA, 0x95, 0xF3, 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, +- 0x01, 0x26, 0x64, 0x44, 0x95, 0xF9, 0x25, 0xFA, 0x96, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x96, 0xFB, +- 0x28, 0xFA, 0x97, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x97, 0xFB, 0x29, 0xFA, 0x2D, 0x44, 0x04, 0x2A, +- 0x06, 0x00, 0x28, 0x40, 0xA4, 0x36, 0x03, 0x00, 0xA9, 0x60, 0xC9, 0x78, 0xFF, 0xFF, 0x94, 0xFC, +- 0x1F, 0x60, 0x9A, 0x65, 0xA5, 0xD1, 0x28, 0x44, 0x08, 0x2A, 0x51, 0x00, 0x03, 0x2B, 0x01, 0x00, +- 0x4E, 0x00, 0x64, 0x40, 0x00, 0x36, 0x4B, 0x00, 0x32, 0xF2, 0x2F, 0xF0, 0x50, 0xFE, 0x01, 0x2A, +- 0x03, 0x00, 0x01, 0x61, 0x8F, 0xF3, 0x31, 0x00, 0xD0, 0x80, 0x33, 0xF2, 0x30, 0xF0, 0x34, 0xF2, +- 0xD0, 0x80, 0x31, 0xF0, 0xFF, 0xFF, 0xD0, 0x80, 0x60, 0x47, 0x34, 0x0C, 0xFF, 0xB4, 0x12, 0x60, +- 0xCE, 0x65, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0xFF, 0xFF, 0x31, 0x18, 0x60, 0x43, 0x50, 0xFE, +- 0x66, 0x41, 0x32, 0xF0, 0x63, 0x46, 0x03, 0xF2, 0x61, 0x46, 0xD0, 0x80, 0x33, 0xF0, 0x63, 0x46, +- 0x04, 0xF2, 0x61, 0x46, 0xD0, 0x80, 0x34, 0xF0, 0x63, 0x46, 0x05, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, +- 0xFF, 0xFF, 0x04, 0x0C, 0x00, 0xF2, 0x61, 0x46, 0x1A, 0x18, 0xE8, 0x01, 0x06, 0xF0, 0x8F, 0xF3, +- 0x61, 0x46, 0x02, 0x61, 0x64, 0x40, 0x02, 0x2A, 0x12, 0x00, 0xFC, 0xA0, 0xFF, 0xFF, 0x04, 0x0E, +- 0x61, 0x44, 0x14, 0xFA, 0x11, 0xFC, 0x0B, 0x00, 0x2C, 0xF2, 0x2F, 0xFA, 0x2D, 0xF2, 0x30, 0xFA, +- 0x2E, 0xF2, 0x31, 0xFA, 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xBC, 0x40, 0x46, 0x20, 0x00, 0x26, 0x43, +- 0x84, 0xBB, 0xFC, 0xB3, 0x21, 0x46, 0x01, 0x5D, 0x0F, 0xFC, 0x5C, 0x46, 0x25, 0x44, 0x06, 0xFA, +- 0x05, 0xFF, 0x27, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x50, 0xFE, 0x28, 0x40, 0x08, 0x3A, 0x12, 0x00, +- 0x2F, 0xF2, 0x30, 0xF0, 0x60, 0x43, 0x31, 0xF2, 0x22, 0x46, 0x64, 0x41, 0x2C, 0xF0, 0x2D, 0xF0, +- 0xD3, 0x80, 0x2E, 0xF0, 0xD1, 0x80, 0xD0, 0x80, 0x27, 0x44, 0x09, 0x0C, 0x03, 0x00, 0x27, 0x44, +- 0x06, 0x22, 0x05, 0x00, 0xB8, 0xB4, 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xD4, 0x64, +- 0x40, 0x48, 0x0D, 0x64, 0x3A, 0xDB, 0x21, 0x46, 0x1C, 0xF2, 0x62, 0xF1, 0xFF, 0xB4, 0xD0, 0x80, +- 0xFF, 0xFF, 0x01, 0x06, 0x64, 0x44, 0x40, 0x45, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, +- 0x37, 0x3A, 0x03, 0x00, 0x04, 0x7F, 0x40, 0x45, 0x15, 0x64, 0x6E, 0x3A, 0x03, 0x00, 0x84, 0x7F, +- 0x40, 0x45, 0x0B, 0x64, 0x40, 0x44, 0x00, 0x63, 0x28, 0x44, 0xA4, 0x36, 0x07, 0x00, 0x04, 0x2B, +- 0x05, 0x00, 0x30, 0xF3, 0x24, 0x45, 0xD4, 0x84, 0xCA, 0x65, 0xD4, 0x83, 0xD4, 0x64, 0x1A, 0x00, +- 0x0F, 0x64, 0x3A, 0xDB, 0x21, 0x46, 0x70, 0x63, 0x1C, 0xF2, 0xCA, 0x65, 0x40, 0x45, 0x0A, 0x36, +- 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x3A, 0x03, 0x00, 0x04, 0x7F, 0x40, 0x45, 0x15, 0x64, +- 0x6E, 0x3A, 0x03, 0x00, 0x84, 0x7F, 0x40, 0x45, 0x0B, 0x64, 0x40, 0x44, 0x2B, 0xF2, 0xC4, 0x85, +- 0xD4, 0x83, 0xC4, 0x64, 0x40, 0x48, 0x2F, 0xF0, 0xB0, 0xF0, 0xB1, 0xF2, 0x00, 0xE1, 0xA1, 0xFF, +- 0xFF, 0xFF, 0x80, 0x4E, 0x83, 0x4C, 0x9A, 0xFF, 0x84, 0x4C, 0x85, 0x4C, 0x81, 0x4C, 0xA1, 0xFF, +- 0x98, 0xFF, 0x87, 0x4F, 0x87, 0x4C, 0x87, 0x4F, 0x87, 0x4D, 0x87, 0x4C, 0x01, 0x08, 0x01, 0x00, +- 0xFF, 0xFF, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x44, +- 0xBC, 0xFF, 0xC4, 0xE2, 0x0C, 0x74, 0x04, 0xE1, 0xA1, 0xFF, 0x35, 0xF3, 0xC4, 0xE2, 0x60, 0x54, +- 0x89, 0xFF, 0x13, 0x74, 0x88, 0xFF, 0xB5, 0xFF, 0x47, 0xFF, 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, +- 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x27, 0x44, 0x01, 0x2A, +- 0x05, 0x00, 0xFE, 0xB4, 0x40, 0x47, 0xA8, 0x60, 0x89, 0x78, 0xFF, 0xFF, 0xA7, 0x60, 0x8E, 0x78, +- 0xFF, 0xFF, 0x28, 0x40, 0xB4, 0x3A, 0x09, 0x00, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, +- 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x9B, 0x01, 0x28, 0x44, 0xD4, 0x36, 0x03, 0x00, +- 0xAA, 0x60, 0xEA, 0x78, 0xFF, 0xFF, 0x48, 0xE2, 0x27, 0x44, 0xFB, 0xB4, 0x40, 0x47, 0x21, 0x60, +- 0x98, 0x63, 0xA3, 0xD3, 0xB5, 0x60, 0x58, 0x4D, 0xE3, 0x78, 0xFF, 0xFF, 0x34, 0xFB, 0x1C, 0x42, +- 0x22, 0x46, 0x2A, 0xF0, 0xF7, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDA, 0x60, 0x40, 0x40, 0x2B, +- 0xCC, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x22, 0x26, 0x42, 0x00, 0x01, 0x26, 0x03, 0x00, +- 0x04, 0x26, 0x07, 0x00, 0xC2, 0x00, 0x04, 0x2B, 0xC0, 0x00, 0x88, 0xF3, 0xFF, 0xFF, 0x60, 0x46, +- 0x01, 0x00, 0x07, 0xF4, 0x47, 0xF2, 0xFF, 0xFF, 0xDC, 0x84, 0x47, 0xFA, 0x0D, 0x60, 0x3E, 0x62, +- 0x80, 0xFF, 0xC4, 0x60, 0x78, 0x44, 0x02, 0xA4, 0xA2, 0xDB, 0x7D, 0x78, 0xFF, 0xFF, 0x82, 0xFF, +- 0x88, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, 0x22, 0x46, 0x22, 0xF2, +- 0x63, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x47, 0xF0, 0x64, 0x41, 0x64, 0x47, +- 0xFF, 0xB4, 0x60, 0x5F, 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, 0x22, 0x46, 0x3A, 0xFA, +- 0x64, 0x44, 0x20, 0x7F, 0x34, 0x94, 0x3B, 0xFA, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, +- 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x85, 0x00, +- 0x2A, 0xF2, 0x00, 0x60, 0x7C, 0x62, 0x60, 0x40, 0x40, 0x2B, 0x27, 0x00, 0xA2, 0xD3, 0x00, 0x61, +- 0x60, 0xFE, 0xA0, 0xD3, 0xDE, 0x82, 0xA2, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, +- 0xF1, 0x81, 0xC0, 0x2B, 0x04, 0x00, 0x80, 0x2A, 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, +- 0x03, 0x00, 0x60, 0x47, 0xDC, 0x87, 0x01, 0x61, 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, +- 0x60, 0xFE, 0xDA, 0x82, 0xA2, 0xD1, 0xFF, 0xFF, 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, +- 0x01, 0x00, 0x00, 0x64, 0xA2, 0xDB, 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0x60, 0x7C, 0x62, 0xA2, 0xD3, +- 0xFF, 0xFF, 0xA0, 0xD3, 0x5A, 0xD1, 0x3A, 0xFA, 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, +- 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, 0x64, 0x44, +- 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x80, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, +- 0x64, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, +- 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, +- 0xE7, 0x7F, 0xA0, 0x5A, 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, +- 0xA0, 0x5A, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, +- 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, +- 0xED, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, +- 0xA0, 0x5A, 0x08, 0x60, 0x00, 0xEA, 0x65, 0x44, 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, +- 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x0B, 0xF2, 0xFF, 0xFF, 0x7F, 0xB4, +- 0x0C, 0xF0, 0x04, 0x02, 0x64, 0x46, 0x00, 0xF0, 0x04, 0x64, 0x22, 0x46, 0x03, 0xFA, 0x60, 0x41, +- 0x64, 0x46, 0x01, 0xF2, 0xFC, 0xA1, 0x61, 0x45, 0xD4, 0x84, 0xFF, 0xFF, 0x08, 0x02, 0x00, 0xF0, +- 0x04, 0x63, 0x64, 0x46, 0x01, 0xF2, 0x22, 0x46, 0x1A, 0xFA, 0x03, 0xFC, 0x02, 0x00, 0x22, 0x46, +- 0x1A, 0xFA, 0x35, 0xF2, 0x04, 0xF8, 0xDC, 0x84, 0x35, 0xFA, 0x14, 0xF2, 0x0F, 0xB5, 0x0F, 0xB4, +- 0xCC, 0x84, 0x94, 0x80, 0x04, 0x60, 0x00, 0x65, 0x2A, 0xF2, 0x01, 0x02, 0x94, 0x84, 0x2A, 0xFA, +- 0x95, 0xFC, 0x06, 0x00, 0xC4, 0x3A, 0x07, 0x00, 0x27, 0x44, 0xFD, 0xB4, 0x40, 0x47, 0x48, 0xE2, +- 0xA8, 0x60, 0x28, 0x78, 0xFF, 0xFF, 0x28, 0x44, 0x04, 0x26, 0x05, 0x00, 0x68, 0x3A, 0x03, 0x00, +- 0x32, 0x44, 0x00, 0x27, 0x03, 0x00, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0x0A, 0x64, 0x3A, 0xDB, +- 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0x0E, 0x64, 0x3A, 0xDB, 0x10, 0x60, 0x00, 0x65, 0x3C, 0x46, +- 0x2A, 0xF2, 0x13, 0xF0, 0xA4, 0x84, 0xB4, 0xBC, 0x40, 0x48, 0x62, 0xF1, 0x64, 0x47, 0xFF, 0xB4, +- 0x60, 0x45, 0xD0, 0x80, 0x70, 0x61, 0x01, 0x06, 0x64, 0x44, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, +- 0x38, 0x64, 0x37, 0x36, 0x15, 0x64, 0x6E, 0x36, 0x0B, 0x64, 0x40, 0x4E, 0xA0, 0x63, 0x0A, 0x64, +- 0x65, 0x40, 0x0A, 0x36, 0x03, 0x00, 0x38, 0x61, 0x14, 0x64, 0xEB, 0x83, 0x40, 0x45, 0x43, 0x44, +- 0x02, 0x60, 0x5E, 0x65, 0x2A, 0xF2, 0x2B, 0xF2, 0x60, 0x40, 0x04, 0x2B, 0x04, 0x00, 0x2E, 0x45, +- 0xD4, 0x85, 0xC5, 0x84, 0x05, 0x00, 0x1B, 0xF0, 0xC5, 0x84, 0xC0, 0x84, 0x2E, 0x45, 0xC4, 0x84, +- 0x60, 0x43, 0x28, 0x44, 0x00, 0xE1, 0xA1, 0xFF, 0x80, 0x4E, 0x83, 0x4C, 0x9A, 0xFF, 0x56, 0x62, +- 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x5C, 0x62, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0xA1, 0xFF, +- 0x98, 0xFF, 0x87, 0x4F, 0x87, 0x4C, 0x87, 0x4F, 0x87, 0x4D, 0x87, 0x4C, 0x01, 0x08, 0x01, 0x00, +- 0xFF, 0xFF, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x44, +- 0xBC, 0xFF, 0xB5, 0xFF, 0x47, 0xFF, 0x27, 0x44, 0x02, 0xBC, 0x40, 0x47, 0x36, 0xF3, 0xB7, 0xFF, +- 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x60, 0x5B, 0x4D, 0xE2, 0xA8, 0x60, +- 0x81, 0x78, 0xFF, 0xFF, 0x21, 0x46, 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, +- 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x26, 0x43, 0x25, 0x44, 0x06, 0xFA, 0x2A, 0x44, +- 0x72, 0x45, 0x24, 0xFA, 0x95, 0xF3, 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, 0x01, 0x26, +- 0x64, 0x44, 0x95, 0xF9, 0x25, 0xFA, 0x96, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x96, 0xFB, 0x28, 0xFA, +- 0x97, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x97, 0xFB, 0x29, 0xFA, 0x2D, 0x40, 0x01, 0x2A, 0x0E, 0x00, +- 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xBC, 0x40, 0x46, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, +- 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x30, 0xF1, 0x50, 0x00, 0xFC, 0xB3, 0x32, 0x40, +- 0x01, 0x2A, 0x06, 0x00, 0x0A, 0xBB, 0x0F, 0xFC, 0xCB, 0xFE, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, +- 0x2D, 0x44, 0x04, 0x26, 0x02, 0x00, 0x0F, 0xFC, 0x05, 0xFF, 0x30, 0xF1, 0x27, 0x44, 0x05, 0x22, +- 0x2D, 0x00, 0xFA, 0xB4, 0x40, 0x47, 0x2D, 0x44, 0x10, 0x2A, 0x24, 0x00, 0x28, 0x40, 0xD4, 0x3A, +- 0x21, 0x00, 0x31, 0x40, 0x08, 0x26, 0x00, 0x7C, 0x2B, 0x44, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, +- 0x64, 0x44, 0xC4, 0x84, 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, +- 0x20, 0x29, 0x6D, 0xE2, 0x12, 0x60, 0xC0, 0x63, 0x1D, 0xF0, 0xC0, 0x64, 0xC0, 0x84, 0xA3, 0xD1, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA3, 0xDB, 0xA8, 0x60, +- 0x89, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x07, 0x00, 0x02, 0x2A, 0x05, 0x00, +- 0xFD, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x05, 0x64, 0x3A, 0xDB, 0x28, 0x44, +- 0xA4, 0x3A, 0x04, 0x00, 0x39, 0xF1, 0x25, 0x44, 0x0A, 0x36, 0x38, 0xF1, 0x31, 0x40, 0x08, 0x26, +- 0x00, 0x7C, 0x2B, 0x44, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, 0x64, 0x44, 0xC4, 0x84, 0xFF, 0xFF, +- 0x04, 0x24, 0x00, 0xB4, 0x28, 0x40, 0xE4, 0x36, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, +- 0x20, 0x29, 0x6D, 0xE2, 0xA7, 0x60, 0x8E, 0x78, 0xFF, 0xFF, 0x21, 0x46, 0xB5, 0xFF, 0xBC, 0xFF, +- 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x27, 0x44, +- 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xEA, 0x01, +- 0x27, 0x44, 0x05, 0x22, 0x09, 0x00, 0xBA, 0xB4, 0x40, 0x47, 0x3C, 0x46, 0x02, 0x64, 0x31, 0xFB, +- 0xC0, 0xFE, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x02, 0x2A, 0x06, 0x00, 0xFD, 0xB4, +- 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xF4, 0x01, 0xF3, 0x0A, 0x7C, 0x50, 0x6D, 0xE2, +- 0xF0, 0x01, 0x72, 0x45, 0xDC, 0x84, 0x95, 0xFB, 0x11, 0x64, 0x3A, 0xDB, 0x96, 0xF3, 0x06, 0x04, +- 0xDC, 0x84, 0x96, 0xFB, 0x97, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x97, 0xFB, 0xA7, 0x60, 0xA6, 0x78, +- 0xFF, 0xFF, 0x00, 0x61, 0x12, 0x64, 0x3A, 0xDB, 0x16, 0x60, 0xBA, 0x63, 0xBD, 0xD3, 0x72, 0x45, +- 0x44, 0x8A, 0x02, 0x28, 0x02, 0x00, 0xE4, 0xE2, 0xDD, 0x81, 0x02, 0x28, 0x02, 0x00, 0xE4, 0xE2, +- 0xDD, 0x81, 0xBD, 0xD3, 0x95, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, +- 0xC4, 0x84, 0x60, 0x55, 0x2A, 0x52, 0x95, 0xFB, 0x02, 0x24, 0x01, 0xB9, 0xBD, 0xD3, 0x96, 0xF1, +- 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, 0xC4, 0x84, 0x96, 0xFB, 0x02, 0x24, +- 0x01, 0xB9, 0xBD, 0xD3, 0x97, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0xC4, 0x84, 0x97, 0xFB, 0xA8, 0x60, +- 0x0C, 0x78, 0xFF, 0xFF, 0xAE, 0x01, 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x25, 0x09, 0x00, 0x04, 0x25, +- 0x03, 0x00, 0x47, 0xFF, 0x32, 0x74, 0xA5, 0x01, 0xC4, 0xE2, 0xAF, 0x60, 0x19, 0x78, 0xFF, 0xFF, +- 0x4C, 0x4E, 0x47, 0xFF, 0x32, 0x74, 0xCD, 0xE2, 0xAC, 0x60, 0x8F, 0x78, 0x00, 0x61, 0x10, 0x64, +- 0x3A, 0xDB, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0x5C, 0x4D, +- 0x26, 0x44, 0x02, 0x26, 0x0C, 0x00, 0x3E, 0x46, 0x09, 0xF2, 0x1E, 0x41, 0x03, 0x1B, 0xAE, 0x60, +- 0xCB, 0x78, 0xFF, 0xFF, 0x40, 0x5E, 0xFD, 0xFB, 0x21, 0x44, 0x02, 0x64, 0x40, 0x46, 0x41, 0x5D, +- 0x21, 0x46, 0x00, 0xF2, 0x46, 0x45, 0x87, 0xFC, 0x4C, 0xE2, 0x01, 0x64, 0x33, 0xFB, 0x01, 0x60, +- 0x0E, 0xE1, 0x03, 0xE1, 0x3F, 0x40, 0x01, 0x27, 0x00, 0x00, 0x21, 0x69, 0xB6, 0xFF, 0xA1, 0xFF, +- 0x6C, 0x5E, 0xB6, 0xFF, 0xB7, 0xFF, 0x60, 0x5C, 0x20, 0x64, 0x3A, 0xDB, 0x68, 0x43, 0x26, 0xFC, +- 0x22, 0x69, 0x64, 0x44, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x5F, 0x60, 0x43, 0x26, 0xF2, 0xFF, 0xFF, +- 0x68, 0x5F, 0x26, 0xFA, 0x3A, 0x69, 0x1D, 0xFC, 0x2E, 0x44, 0x36, 0xF1, 0x1C, 0xFA, 0xC3, 0x94, +- 0xCD, 0xE2, 0x2E, 0x44, 0x14, 0x36, 0x12, 0x00, 0x0A, 0x36, 0x0F, 0x00, 0x63, 0x45, 0xE3, 0x83, +- 0xE3, 0x83, 0xC7, 0x83, 0xE3, 0x83, 0xC7, 0x83, 0xFF, 0xFF, 0x37, 0x36, 0x05, 0x00, 0x6E, 0x36, +- 0x04, 0x00, 0xAE, 0x60, 0xE3, 0x78, 0xFF, 0xFF, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, +- 0xFF, 0xFF, 0x80, 0x27, 0xCF, 0x83, 0x1B, 0xFC, 0x01, 0x64, 0x4F, 0xFB, 0xA1, 0xFF, 0x1C, 0xF2, +- 0x29, 0x41, 0xF9, 0x81, 0x52, 0x4A, 0x71, 0x89, 0x68, 0x5F, 0x27, 0xFA, 0x6C, 0x40, 0x03, 0x15, +- 0xAE, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0x88, 0x60, 0x85, 0x71, 0x8D, 0xE2, 0x99, 0xF1, 0xFC, 0xA3, +- 0xD3, 0x80, 0x43, 0x43, 0x03, 0x04, 0xAE, 0x60, 0xEB, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x01, 0x2A, +- 0x4C, 0x00, 0x9A, 0xFF, 0x23, 0x43, 0x18, 0x61, 0xA1, 0xFF, 0x8C, 0x44, 0xCB, 0x83, 0x2A, 0xFA, +- 0x40, 0x48, 0x40, 0x27, 0x04, 0xA1, 0x60, 0x40, 0x03, 0x2B, 0x01, 0x00, 0x06, 0xA1, 0x88, 0xB0, +- 0x88, 0x36, 0xD9, 0x81, 0x62, 0x45, 0x23, 0x44, 0x54, 0x94, 0x28, 0x40, 0x04, 0x26, 0x00, 0x64, +- 0x3F, 0xFA, 0xC9, 0x81, 0x65, 0x42, 0x7A, 0xDC, 0x00, 0xB9, 0xFD, 0x1C, 0x00, 0xF4, 0x6E, 0x61, +- 0x10, 0x62, 0x14, 0x02, 0x05, 0x1D, 0x12, 0x1E, 0x0C, 0x00, 0x00, 0xF4, 0x7C, 0x61, 0x02, 0x62, +- 0x7A, 0xDC, 0x63, 0x40, 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, 0x08, 0x1E, 0x02, 0x02, 0x00, 0xF4, +- 0x02, 0x62, 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0x6C, 0x44, 0x5A, 0xDA, 0x98, 0xFF, 0x01, 0x60, +- 0x08, 0xE1, 0x81, 0xE1, 0xA1, 0xFF, 0x6C, 0x40, 0xA1, 0xFF, 0x47, 0xFF, 0x26, 0x44, 0xFD, 0xB4, +- 0x84, 0xBC, 0x01, 0x15, 0x7F, 0xB4, 0x40, 0x46, 0xA1, 0xFF, 0x6C, 0x40, 0x14, 0x63, 0x01, 0x11, +- 0x01, 0x00, 0xFD, 0x1F, 0xAE, 0x60, 0x61, 0x78, 0xFF, 0xFF, 0x9A, 0xFF, 0x54, 0x63, 0x12, 0x64, +- 0x40, 0x46, 0x00, 0x64, 0x0F, 0xFA, 0xA1, 0xFF, 0xCB, 0xF1, 0x12, 0x61, 0x50, 0xFE, 0x8C, 0x44, +- 0xCC, 0xF0, 0xBD, 0xDA, 0x40, 0x48, 0x04, 0x26, 0x40, 0x00, 0xA1, 0xFF, 0x8C, 0x44, 0xBD, 0xDA, +- 0x30, 0xFB, 0x6C, 0x44, 0xBD, 0xDA, 0xFF, 0xFF, 0x01, 0x26, 0x24, 0x00, 0xD0, 0x80, 0xA1, 0xFF, +- 0x8C, 0x44, 0x6C, 0x5C, 0xF2, 0xFE, 0xBD, 0xDA, 0xCD, 0xF3, 0xD4, 0x80, 0xD0, 0x80, 0xBD, 0xD8, +- 0x2D, 0x44, 0x15, 0x0C, 0x32, 0x40, 0x02, 0x2A, 0x07, 0x00, 0x28, 0x42, 0x0C, 0xB2, 0x08, 0x3A, +- 0x03, 0x00, 0x10, 0xBC, 0x40, 0x4D, 0x4D, 0x00, 0x03, 0x0A, 0xAE, 0x60, 0xF9, 0x78, 0xFF, 0xFF, +- 0x11, 0xBC, 0x40, 0x4D, 0x28, 0x45, 0xBF, 0x60, 0xFF, 0x64, 0x24, 0x88, 0x42, 0x00, 0x30, 0xBC, +- 0x40, 0x4D, 0x3F, 0x00, 0x20, 0xB9, 0x5C, 0x8E, 0xA1, 0xFF, 0x8C, 0x44, 0xBD, 0xDA, 0xDC, 0x9C, +- 0x6C, 0x44, 0xF2, 0xFE, 0xBD, 0xDA, 0x08, 0x28, 0x44, 0x4E, 0xDC, 0x84, 0x2E, 0x5C, 0xB0, 0x84, +- 0xEF, 0xB1, 0x08, 0x24, 0x40, 0xB9, 0x41, 0x46, 0x2C, 0x00, 0x8C, 0x44, 0x04, 0x61, 0xBD, 0xDA, +- 0x50, 0xFE, 0x80, 0x27, 0x00, 0x64, 0x30, 0xFB, 0x8C, 0x44, 0xBD, 0xDA, 0xD0, 0x80, 0x8C, 0x44, +- 0xBD, 0xDA, 0xD4, 0x80, 0x00, 0x65, 0x8C, 0x44, 0xCD, 0xF1, 0xBD, 0xDA, 0xD0, 0x80, 0x28, 0x44, +- 0x03, 0x0C, 0xA0, 0x2A, 0x0A, 0x00, 0x11, 0x00, 0x10, 0x65, 0x60, 0x40, 0xC4, 0x36, 0x04, 0x00, +- 0xD4, 0x3A, 0x08, 0x00, 0x27, 0x40, 0x40, 0x26, 0x30, 0x65, 0x00, 0x64, 0x3F, 0xFA, 0x46, 0x4E, +- 0x35, 0x8D, 0x5F, 0x00, 0x40, 0x26, 0xF9, 0x01, 0x30, 0x65, 0x9D, 0xDC, 0x9D, 0xDC, 0x9D, 0xDC, +- 0xF4, 0x01, 0x00, 0xE1, 0x23, 0x43, 0xE8, 0xA3, 0x6A, 0x62, 0x9A, 0xFF, 0xA1, 0xFF, 0x28, 0x44, +- 0x03, 0x2B, 0x04, 0x00, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x28, 0x44, 0x88, 0xB0, 0x88, 0x2A, +- 0x03, 0x00, 0x70, 0x62, 0x7A, 0xDC, 0x28, 0x44, 0x40, 0x2B, 0x13, 0x00, 0x72, 0x62, 0x7A, 0xDC, +- 0x04, 0xE6, 0x7A, 0xDC, 0x3B, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x2B, 0x02, 0x00, 0x7A, 0xDC, +- 0x7A, 0xDC, 0x08, 0x60, 0x00, 0xEB, 0xFC, 0xA3, 0x25, 0xFF, 0x3F, 0xFC, 0x04, 0xA3, 0xB0, 0xFF, +- 0x01, 0x00, 0x3F, 0xFC, 0xCF, 0x83, 0xDF, 0x83, 0x04, 0x02, 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, +- 0x1F, 0x00, 0x27, 0x03, 0xCB, 0x83, 0xFF, 0x60, 0xFE, 0x65, 0x0E, 0xA3, 0xA7, 0x84, 0xF2, 0xA3, +- 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, 0x7A, 0xDC, 0xFE, 0x1C, 0x03, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, +- 0x0A, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xA7, 0x84, 0x7A, 0x61, 0x7A, 0xDC, 0xFE, 0x1C, 0xF9, 0x1D, +- 0x7C, 0xA8, 0xD9, 0x81, 0xF6, 0x03, 0xFF, 0xB1, 0x0C, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, +- 0xA1, 0xFF, 0x01, 0x60, 0x0C, 0xE1, 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0xCD, 0x81, 0x6C, 0x44, +- 0x5A, 0xDA, 0x98, 0xFF, 0x00, 0xE6, 0x7C, 0x44, 0x33, 0xFB, 0x01, 0x60, 0x0C, 0xE1, 0x83, 0xE1, +- 0xA1, 0xFF, 0x8C, 0x44, 0x46, 0x45, 0xA1, 0xFF, 0x14, 0x63, 0x01, 0x10, 0xFE, 0x1F, 0x01, 0x60, +- 0x08, 0xE1, 0x0A, 0x64, 0x60, 0x54, 0x47, 0xFF, 0x50, 0x4B, 0x67, 0x50, 0x69, 0xE2, 0x6A, 0x40, +- 0x40, 0x2B, 0x01, 0x15, 0x29, 0x00, 0x6C, 0x40, 0x28, 0x40, 0x03, 0x26, 0x15, 0x00, 0x31, 0x40, +- 0x20, 0x2A, 0x03, 0x00, 0x28, 0x40, 0x50, 0x3A, 0x0F, 0x00, 0x2D, 0x44, 0x20, 0x2A, 0x0C, 0x00, +- 0x2B, 0x44, 0xAC, 0x80, 0x28, 0x40, 0xB4, 0x3A, 0x03, 0x00, 0x02, 0x03, 0x30, 0xFB, 0x04, 0x00, +- 0x2B, 0x50, 0xA8, 0x60, 0x92, 0x78, 0x04, 0xE1, 0x04, 0xE1, 0xA1, 0xFF, 0x35, 0xF1, 0x26, 0x44, +- 0x64, 0x54, 0xCD, 0xE2, 0x84, 0xBC, 0x2D, 0x40, 0x0C, 0x22, 0xFD, 0xB4, 0x40, 0x46, 0x23, 0x64, +- 0x3A, 0xDB, 0xAB, 0x60, 0x6A, 0x78, 0xFF, 0xFF, 0x27, 0x40, 0x26, 0x22, 0x04, 0x00, 0x02, 0x64, +- 0x31, 0xFB, 0xC0, 0xFE, 0xFF, 0xFF, 0x6C, 0x40, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, +- 0x08, 0x60, 0x00, 0x6B, 0x37, 0xF3, 0x2B, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x28, 0x65, 0x44, +- 0x60, 0x50, 0xA0, 0x4C, 0x20, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0x35, 0xF1, 0x74, 0x44, 0xC0, 0x94, +- 0x32, 0x40, 0x02, 0x2A, 0x18, 0x00, 0x28, 0x44, 0xA4, 0x36, 0x04, 0x00, 0x0C, 0xB4, 0xFF, 0xFF, +- 0x04, 0x36, 0x11, 0x00, 0x26, 0x43, 0xFD, 0xB3, 0x04, 0xBB, 0x43, 0x46, 0x01, 0x2A, 0x03, 0x00, +- 0x28, 0x47, 0x40, 0xBF, 0x40, 0x48, 0x0A, 0xBB, 0x0F, 0xFC, 0x50, 0x4B, 0x67, 0x50, 0x00, 0x64, +- 0x30, 0xFB, 0x05, 0xFF, 0xC6, 0x01, 0x24, 0x64, 0x3A, 0xDB, 0x28, 0x44, 0x04, 0x2A, 0x03, 0x00, +- 0xA7, 0x60, 0x8E, 0x78, 0xFF, 0xFF, 0x1D, 0xFF, 0x48, 0xE2, 0x27, 0x44, 0x06, 0x22, 0x05, 0x00, +- 0xF9, 0xB4, 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x26, 0x40, 0x10, 0x2A, 0x18, 0x00, +- 0x26, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0xFF, 0xB4, 0xC0, 0xA0, 0xFF, 0xFF, 0x11, 0x0E, 0x98, 0xF1, +- 0x1E, 0x60, 0xF8, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, +- 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, +- 0xAC, 0x60, 0x05, 0x78, 0xFF, 0xFF, 0x98, 0xF1, 0x1E, 0x60, 0xFA, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, +- 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x2A, 0x64, 0x3A, 0xDB, 0x5C, 0x41, 0x87, 0xE1, +- 0xA1, 0xFF, 0x6C, 0x40, 0x02, 0x00, 0x29, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x08, 0xE1, 0x87, 0xE1, +- 0xA1, 0xFF, 0x6C, 0x40, 0x11, 0x00, 0x1F, 0x60, 0x0C, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, +- 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0xF1, 0x01, 0x01, 0x60, 0x08, 0xE1, 0x21, 0x64, 0x3A, 0xDB, +- 0x03, 0x00, 0x01, 0x60, 0x08, 0xE1, 0x6C, 0x40, 0x00, 0x64, 0x33, 0xFB, 0x32, 0x74, 0x40, 0x63, +- 0x01, 0x16, 0xFE, 0x01, 0x01, 0x68, 0x01, 0x11, 0x09, 0x00, 0xA7, 0x6A, 0x22, 0x64, 0x3A, 0xDB, +- 0x03, 0x60, 0xC9, 0x63, 0x01, 0x11, 0x02, 0x00, 0x6C, 0x40, 0xFC, 0x1F, 0x6C, 0x40, 0xB5, 0xFF, +- 0x6C, 0x40, 0xBC, 0xFF, 0x6C, 0x40, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, +- 0x00, 0x6B, 0x03, 0x0A, 0xA7, 0x60, 0x9B, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x4F, 0xFB, 0x27, 0x44, +- 0x06, 0x22, 0x06, 0x00, 0xF9, 0xB4, 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x48, 0xE2, +- 0x27, 0x64, 0x3A, 0xDB, 0xB3, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x54, 0x62, 0x22, 0x46, +- 0xA2, 0xD0, 0x16, 0x63, 0x7C, 0x41, 0x44, 0x48, 0x80, 0x36, 0x04, 0x61, 0x28, 0x40, 0x50, 0x36, +- 0x04, 0x61, 0x41, 0x4E, 0x28, 0x44, 0xA4, 0x36, 0x0E, 0x63, 0x12, 0x60, 0xC2, 0x62, 0xA2, 0xD1, +- 0x24, 0x44, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA2, 0xDB, +- 0x9A, 0xFF, 0xA1, 0xFF, 0x54, 0x62, 0xA2, 0xD2, 0xFF, 0xFF, 0x6A, 0x40, 0x80, 0x4E, 0x7A, 0xD4, +- 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0xFF, 0xFF, 0x01, 0x1D, +- 0x78, 0x00, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x28, 0x40, 0x03, 0x2B, 0x04, 0x00, +- 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x6A, 0x40, 0x70, 0x62, 0x28, 0x44, 0x88, 0xB0, 0x88, 0x36, +- 0x7A, 0xD4, 0x28, 0x40, 0x40, 0x2B, 0x0B, 0x00, 0x72, 0x62, 0x7A, 0xD4, 0x7A, 0xD4, 0xA2, 0xD2, +- 0xFF, 0xFF, 0x60, 0x40, 0x20, 0x2B, 0x02, 0x00, 0x7A, 0xD4, 0x7A, 0xD4, 0x46, 0x00, 0x23, 0x43, +- 0xCF, 0x83, 0xDF, 0x83, 0x02, 0x03, 0x55, 0x03, 0x04, 0x00, 0x03, 0xF0, 0x04, 0xF4, 0x64, 0x42, +- 0x37, 0x00, 0x2E, 0x40, 0x04, 0x2A, 0x21, 0x00, 0xA1, 0xFF, 0x02, 0xFE, 0x10, 0x25, 0x42, 0xFE, +- 0x72, 0x45, 0x65, 0x4C, 0x95, 0xF3, 0x03, 0x04, 0xE4, 0xE2, 0xDC, 0x84, 0x95, 0xFB, 0xA1, 0xFF, +- 0x80, 0x4C, 0x96, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x96, 0xFB, 0x80, 0x4C, 0x97, 0xF3, 0x02, 0x04, +- 0xDC, 0x84, 0x97, 0xFB, 0x80, 0x4C, 0x5C, 0x4E, 0xF8, 0xA3, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, +- 0xFF, 0xB1, 0xF8, 0xA1, 0x06, 0xA4, 0x60, 0x42, 0x09, 0x00, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, +- 0xC8, 0x82, 0xFF, 0xB1, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xB1, 0x7A, 0xD4, 0xFF, 0xFF, +- 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, 0x17, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, 0xDA, 0x82, +- 0xA2, 0xD2, 0xA1, 0xFF, 0x09, 0x74, 0x80, 0x4D, 0x0E, 0x00, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, +- 0x23, 0x43, 0xA1, 0xFF, 0xA0, 0xD2, 0xFE, 0xA1, 0xCB, 0x83, 0x80, 0x4E, 0xAF, 0x83, 0x02, 0x1D, +- 0x02, 0x03, 0xED, 0x01, 0xE3, 0x01, 0xA1, 0xFF, 0x28, 0x40, 0x40, 0x2B, 0x02, 0x00, 0x9C, 0x4E, +- 0x9C, 0x4C, 0xA1, 0xFF, 0xDA, 0x83, 0x66, 0x44, 0x22, 0x46, 0x0C, 0xFA, 0x0B, 0xFC, 0x87, 0x4F, +- 0x87, 0x4C, 0x87, 0x4F, 0x87, 0x4D, 0x87, 0x4C, 0x01, 0x08, 0x01, 0x00, 0xFF, 0xFF, 0x87, 0x4C, +- 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x44, 0xBC, 0xFF, 0x01, 0x60, +- 0x08, 0xE1, 0x0C, 0x74, 0x04, 0xE1, 0xA1, 0xFF, 0x35, 0xF3, 0xC4, 0xE2, 0x60, 0x54, 0x89, 0xFF, +- 0x13, 0x74, 0x88, 0xFF, 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, 0x34, 0x64, 0x3A, 0xDB, 0x06, 0xE1, +- 0x47, 0xFF, 0xA8, 0x60, 0x64, 0x78, 0xFF, 0xFF, 0xFF, 0x01, 0x08, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x43, 0xFF, 0x01, 0x60, 0x00, 0xE1, 0x28, 0xF3, 0x47, 0xFF, 0x60, 0x40, 0x07, 0x37, 0x4B, 0x00, +- 0x05, 0x3B, 0x04, 0x00, 0xFF, 0x0A, 0x80, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x29, 0xF5, 0x2A, 0xF3, +- 0x47, 0xFF, 0x3F, 0xF0, 0x01, 0x1B, 0x01, 0x64, 0x60, 0x56, 0xAD, 0xE2, 0xB5, 0xFF, 0x6C, 0x40, +- 0x40, 0xE1, 0xA1, 0xFF, 0x00, 0xF4, 0x6E, 0x61, 0x12, 0x62, 0x64, 0x43, 0x01, 0xE1, 0x03, 0x64, +- 0xE2, 0xD0, 0xC9, 0x81, 0x64, 0x4C, 0xCC, 0x84, 0xDA, 0x82, 0xFA, 0x02, 0x01, 0x60, 0x00, 0x6B, +- 0x9A, 0xFF, 0xCA, 0x82, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xFF, 0x7A, 0xD0, 0xA1, 0xFF, +- 0x64, 0x4C, 0xFC, 0x1C, 0xF8, 0x1D, 0x00, 0xB9, 0x06, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, +- 0x5A, 0xD2, 0xA1, 0xFF, 0x60, 0x4D, 0x3F, 0x40, 0x02, 0x2B, 0x08, 0x00, 0x28, 0xF3, 0xA5, 0x60, +- 0xC4, 0x65, 0x60, 0x40, 0x0E, 0x3B, 0x02, 0x00, 0x80, 0x4C, 0xFE, 0x01, 0xA1, 0xFF, 0x87, 0x4E, +- 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x67, 0x4C, 0xFF, 0xFF, 0xBC, 0xFF, 0x00, 0xE1, +- 0xD5, 0xFE, 0xA1, 0xFF, 0xFF, 0xFF, 0x00, 0x64, 0x40, 0x46, 0x60, 0x41, 0xB5, 0xFF, 0xB7, 0xFF, +- 0xB4, 0xFF, 0x29, 0xF5, 0x3F, 0xF0, 0x24, 0xF2, 0x44, 0x43, 0x40, 0x44, 0x00, 0xF4, 0xF3, 0x60, +- 0xA0, 0x65, 0x10, 0x62, 0x5A, 0xD2, 0xD9, 0x81, 0xD4, 0x80, 0xFF, 0xFF, 0xFB, 0x02, 0x61, 0x45, +- 0x24, 0x44, 0xD4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xFD, 0xA5, 0x48, 0x60, 0x00, 0x64, +- 0xC4, 0x9D, 0x0D, 0x60, 0x00, 0x6B, 0x24, 0x44, 0xC0, 0x83, 0xBB, 0xFF, 0x29, 0xF5, 0x01, 0xE1, +- 0x00, 0xF4, 0x6C, 0x61, 0x10, 0x62, 0x05, 0x00, 0x00, 0xF4, 0x01, 0xF2, 0xFF, 0xFF, 0x60, 0x41, +- 0x04, 0x62, 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x1A, 0x00, 0x26, 0x44, 0x01, 0x26, 0x0C, 0x00, +- 0x24, 0x44, 0xC8, 0x84, 0x40, 0x44, 0x02, 0x03, 0x6C, 0x45, 0xF3, 0x01, 0x03, 0x15, 0x01, 0x64, +- 0x05, 0xFA, 0x15, 0x00, 0x6C, 0x45, 0xED, 0x01, 0x23, 0x44, 0xC8, 0x84, 0x40, 0x43, 0x02, 0x03, +- 0x6C, 0x45, 0xE7, 0x01, 0x00, 0x64, 0x01, 0x15, 0x01, 0x64, 0x6C, 0x45, 0x05, 0xFB, 0xE2, 0xD2, +- 0xDA, 0x82, 0xC9, 0x81, 0x60, 0x4C, 0xDD, 0x1C, 0xD7, 0x03, 0xBC, 0xFF, 0xDA, 0x01, 0x00, 0xE1, +- 0xD5, 0xFE, 0xA1, 0xFF, 0xFF, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, 0x67, 0x4C, 0x43, 0xFF, 0xAD, 0x4F, +- 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x01, 0xE1, 0x01, 0x60, 0x69, 0x6B, 0xA5, 0x60, 0xC4, 0x64, +- 0x60, 0x4C, 0xBB, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, +- 0xFC, 0x01, 0x29, 0xF3, 0x2A, 0xF1, 0x07, 0xB5, 0x04, 0xE1, 0x65, 0x41, 0x64, 0x54, 0xCD, 0xE2, +- 0x95, 0x81, 0xA1, 0x5D, 0xA1, 0xFF, 0xFF, 0xFF, 0xF9, 0x01, 0x00, 0xE1, 0x30, 0x40, 0x02, 0x36, +- 0xA1, 0xFF, 0x83, 0xFF, 0x8D, 0xFF, 0x5C, 0x44, 0x5C, 0x43, 0x5C, 0x42, 0x5C, 0x41, 0x5C, 0x40, +- 0xAC, 0xFF, 0xAD, 0xFF, 0xE7, 0xE1, 0xB1, 0x60, 0xC0, 0x78, 0xFF, 0xFF, 0x10, 0x61, 0x7F, 0x60, +- 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, 0x02, 0x63, 0x26, 0x02, 0x98, 0xFE, 0x1A, 0x05, 0x1B, 0x60, +- 0xB8, 0x62, 0xA2, 0xD5, 0x0E, 0xF2, 0x15, 0x18, 0x02, 0x18, 0x09, 0xF4, 0xFB, 0x01, 0x23, 0x44, +- 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, 0x66, 0x44, 0x11, 0xFB, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, +- 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x08, 0xB9, 0x10, 0x7E, 0x00, 0x7F, 0x0E, 0xFA, 0x00, 0x67, +- 0x0A, 0x00, 0x20, 0x44, 0xDC, 0x85, 0x0F, 0xB4, 0xF6, 0xA0, 0x7F, 0x67, 0x07, 0x63, 0x03, 0x05, +- 0x45, 0x40, 0x00, 0x67, 0xD8, 0xFE, 0xFF, 0x27, 0x05, 0xFD, 0x0A, 0x7E, 0x04, 0xFB, 0x61, 0x55, +- 0x4A, 0x00, 0x28, 0xFB, 0x01, 0xF3, 0x29, 0xFB, 0x44, 0x46, 0x40, 0x45, 0x10, 0x61, 0x7E, 0x60, +- 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, 0x02, 0x63, 0x31, 0x02, 0xB3, 0x60, 0x58, 0x4F, 0x22, 0x78, +- 0xFF, 0xFF, 0x7F, 0x67, 0x03, 0x63, 0x2A, 0x02, 0x26, 0x40, 0x01, 0x2B, 0x24, 0x00, 0x98, 0xFE, +- 0x19, 0x05, 0x1B, 0x60, 0xB8, 0x62, 0xA2, 0xD5, 0x0E, 0xF2, 0x14, 0x18, 0x02, 0x18, 0x09, 0xF4, +- 0xFB, 0x01, 0x23, 0x44, 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, 0x66, 0x44, 0x11, 0xFB, 0x46, 0x43, +- 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x08, 0xB9, 0x10, 0x7E, 0x00, 0x7F, +- 0x0E, 0xFA, 0x09, 0x00, 0x20, 0x44, 0xDC, 0x85, 0x0F, 0xB4, 0xF6, 0xA0, 0x7F, 0x67, 0x07, 0x63, +- 0x05, 0x05, 0x45, 0x40, 0xD8, 0xFE, 0x00, 0x67, 0xD0, 0xFE, 0xD9, 0xFE, 0xFF, 0x27, 0x05, 0xFD, +- 0x0B, 0x7E, 0x04, 0xFB, 0x12, 0x60, 0xC8, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB0, 0x80, 0xBC, +- 0x08, 0x28, 0xA3, 0xDB, 0x61, 0x55, 0x63, 0x00, 0x04, 0xB5, 0x82, 0xB5, 0x25, 0x02, 0x04, 0x03, +- 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, 0xA3, 0xD3, 0x99, 0xFE, 0x04, 0x04, 0x02, 0xBC, 0xFE, 0xB4, +- 0xA3, 0xDB, 0x56, 0x00, 0xBC, 0xF3, 0x20, 0x40, 0x80, 0x26, 0x52, 0x00, 0xA3, 0xD3, 0xFF, 0xA0, +- 0xF8, 0xB4, 0x02, 0x02, 0xA3, 0xDB, 0x1C, 0x00, 0x04, 0xBC, 0xBF, 0xB4, 0xA3, 0xDB, 0x08, 0xB0, +- 0x01, 0x64, 0x08, 0x24, 0x02, 0x64, 0x28, 0xFB, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, 0xD0, 0xFE, +- 0x3F, 0x00, 0xBF, 0xB4, 0xA3, 0xDB, 0x3C, 0x00, 0x40, 0xB0, 0xFF, 0xFF, 0xFA, 0x02, 0xF8, 0xB4, +- 0xA3, 0xDB, 0x08, 0xB5, 0x07, 0x7C, 0x01, 0x02, 0xBC, 0xF9, 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, +- 0x12, 0x60, 0xC8, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB5, 0x07, 0xB5, 0x08, 0x28, 0xC4, 0x02, +- 0x99, 0xFE, 0x26, 0x05, 0x20, 0x44, 0x80, 0x26, 0x23, 0x00, 0x20, 0x2A, 0x00, 0x00, 0x40, 0x2A, +- 0x1F, 0x00, 0xBF, 0xB4, 0x40, 0x40, 0x09, 0x00, 0xA8, 0xFF, 0x20, 0x44, 0x99, 0xFE, 0x02, 0x05, +- 0x80, 0x2A, 0x03, 0x00, 0x40, 0xBC, 0x40, 0x40, 0x13, 0x00, 0x00, 0xF1, 0x80, 0xBC, 0x40, 0x40, +- 0x64, 0x44, 0xE0, 0x84, 0xE8, 0x84, 0x0A, 0x36, 0x29, 0x01, 0x0B, 0x36, 0x5A, 0x01, 0x28, 0xFB, +- 0x01, 0xF1, 0x29, 0xF9, 0x02, 0xF1, 0x2A, 0xF9, 0x03, 0xF1, 0x2B, 0xF9, 0xD0, 0xFE, 0xAE, 0xFF, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x82, 0x3E, 0x75, 0x44, 0x02, 0xB0, 0x01, 0xB0, 0x28, 0x02, 0xDC, 0x02, +- 0x04, 0xB0, 0x08, 0xB0, 0x0B, 0x02, 0x20, 0x02, 0x40, 0x26, 0xA7, 0xFF, 0x8C, 0xFF, 0x75, 0x40, +- 0x80, 0x2B, 0x01, 0x00, 0xAB, 0xFF, 0x75, 0x44, 0x8D, 0xFF, 0xEA, 0x01, 0x0A, 0xF3, 0xAA, 0xFF, +- 0x60, 0x40, 0x20, 0x2B, 0x02, 0x00, 0x60, 0xFF, 0x0D, 0x00, 0x01, 0x26, 0x0C, 0x00, 0xC0, 0x60, +- 0x00, 0x7C, 0xA0, 0x84, 0x80, 0x3B, 0x02, 0x00, 0xC0, 0x67, 0x03, 0x00, 0x40, 0x3B, 0x02, 0x00, +- 0x00, 0x67, 0x0A, 0xFB, 0xD5, 0x01, 0xD4, 0x01, 0xAB, 0xFF, 0x00, 0x00, 0xD1, 0x01, 0x79, 0x63, +- 0xFF, 0xFF, 0xFF, 0x1F, 0xA9, 0xFF, 0x77, 0x44, 0x60, 0x57, 0x10, 0x60, 0x00, 0x75, 0x40, 0x4A, +- 0x01, 0x2A, 0x1C, 0x00, 0x24, 0x44, 0xAC, 0x86, 0x08, 0xF2, 0x18, 0x03, 0x1B, 0x60, 0xBE, 0x65, +- 0xD4, 0x80, 0x0E, 0xF2, 0x02, 0x03, 0xA5, 0xD5, 0x04, 0x00, 0x01, 0xBC, 0x0E, 0xFA, 0x09, 0xF4, +- 0xD1, 0xFE, 0x46, 0x44, 0x0B, 0x18, 0x66, 0x44, 0x10, 0xFB, 0x66, 0x47, 0x20, 0xBF, 0x3B, 0x42, +- 0x04, 0xA2, 0xA2, 0xDB, 0x0E, 0xF2, 0x01, 0x75, 0x10, 0xBC, 0x0E, 0xFA, 0x2A, 0x44, 0x08, 0x2A, +- 0x18, 0x00, 0x23, 0x44, 0x00, 0xA8, 0x5C, 0x43, 0x14, 0x03, 0x1B, 0x60, 0xB8, 0x62, 0xA2, 0xD5, +- 0x01, 0x00, 0x09, 0xF4, 0x0E, 0xF2, 0x0D, 0x18, 0x08, 0xB0, 0x18, 0xAC, 0xFA, 0x03, 0x0E, 0xFA, +- 0x66, 0x43, 0x11, 0xFD, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, +- 0x08, 0x75, 0x2A, 0x44, 0x06, 0x22, 0x2D, 0x00, 0x22, 0x44, 0x00, 0xA8, 0x60, 0x46, 0x0E, 0xF2, +- 0x28, 0x03, 0x10, 0xB0, 0x01, 0xBC, 0x03, 0x02, 0x00, 0x64, 0x40, 0x42, 0x22, 0x00, 0x0E, 0xFA, +- 0xD1, 0xFE, 0x1B, 0x60, 0xB2, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x80, 0x00, 0x46, 0x42, 0x19, 0x02, +- 0x22, 0x47, 0x40, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x23, 0xF2, 0x66, 0x43, 0x00, 0xA8, +- 0x0E, 0xF2, 0x08, 0x02, 0x60, 0x40, 0x02, 0x2A, 0xE4, 0x01, 0x12, 0xFD, 0x10, 0x64, 0x0E, 0xFA, +- 0x02, 0x75, 0x07, 0x00, 0x60, 0x40, 0x04, 0x2A, 0xDC, 0x01, 0x12, 0xFD, 0x10, 0x64, 0x0E, 0xFA, +- 0x04, 0x75, 0x2A, 0x44, 0x80, 0x2A, 0x19, 0x00, 0x21, 0x44, 0xAC, 0x86, 0x0E, 0xF2, 0x15, 0x03, +- 0x01, 0xBC, 0x0E, 0xFA, 0xD1, 0xFE, 0x1B, 0x60, 0xCA, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x56, 0x00, +- 0x46, 0x41, 0x0B, 0x02, 0x21, 0x47, 0x10, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x0E, 0xF2, +- 0x66, 0x43, 0x08, 0xFD, 0x10, 0xBC, 0x0E, 0xFA, 0x80, 0x75, 0x2A, 0x44, 0x10, 0xB0, 0x20, 0x44, +- 0x15, 0x03, 0x7F, 0xB4, 0x40, 0x40, 0x12, 0x60, 0xC8, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB0, +- 0x80, 0xB0, 0x09, 0x03, 0x08, 0x03, 0x40, 0xBC, 0x7F, 0xB4, 0x04, 0xB0, 0xA3, 0xDB, 0x03, 0x03, +- 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, 0xB1, 0x60, 0x90, 0x78, 0xFF, 0xFF, 0xB1, 0x60, 0xC0, 0x78, +- 0xFF, 0xFF, 0xE8, 0xFE, 0x14, 0x05, 0xEA, 0xFE, 0x24, 0x05, 0xE9, 0xFE, 0x1C, 0x05, 0xE7, 0xFE, +- 0x09, 0x05, 0x47, 0xFF, 0x20, 0x44, 0x0F, 0x22, 0x03, 0x00, 0xCC, 0x84, 0x40, 0x40, 0x0F, 0x22, +- 0xB8, 0xFE, 0xEC, 0x01, 0x23, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0xE8, 0x02, 0x6E, 0x01, 0x24, 0x41, +- 0x00, 0xB9, 0x1B, 0x60, 0xBE, 0x65, 0x45, 0x47, 0xE1, 0x02, 0x58, 0x4F, 0x0F, 0x00, 0xDE, 0x02, +- 0x5C, 0x4A, 0x46, 0x44, 0x50, 0x01, 0x22, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0x08, 0x24, 0x81, 0x01, +- 0xD5, 0x01, 0x21, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0xA6, 0x03, 0xD0, 0x01, 0x27, 0xD3, 0x03, 0x00, +- 0x10, 0xB0, 0x09, 0xF2, 0x04, 0x03, 0xAC, 0x86, 0x0E, 0xF2, 0xFA, 0x02, 0x08, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x0E, 0xF3, 0x0F, 0x60, 0xFE, 0x65, 0x0C, 0xF3, 0x24, 0x86, 0x24, 0x46, 0x60, 0x40, +- 0xFB, 0x3B, 0x07, 0x00, 0x80, 0x26, 0x02, 0x00, 0x23, 0x46, 0x03, 0x4C, 0x46, 0x61, 0x3A, 0x65, +- 0x0C, 0x00, 0x2E, 0xF3, 0x40, 0x45, 0xF8, 0x2B, 0x02, 0x00, 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, +- 0x39, 0x00, 0x07, 0x02, 0x58, 0x4F, 0x45, 0x00, 0x04, 0x05, 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, +- 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, 0x0E, 0xFB, 0x2E, 0xF5, 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, +- 0x00, 0x72, 0x7E, 0x71, 0xAC, 0xFF, 0xB1, 0x60, 0xC0, 0x78, 0xFF, 0xFF, 0x8E, 0xFF, 0x0F, 0xF3, +- 0x0F, 0x60, 0xFE, 0x65, 0x24, 0x86, 0x0D, 0xF3, 0x2E, 0xF3, 0x40, 0x45, 0xF8, 0x2B, 0x02, 0x00, +- 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, 0x16, 0x00, 0x07, 0x02, 0x58, 0x4F, 0x22, 0x00, 0x04, 0x05, +- 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, 0x0F, 0xFB, 0x2E, 0xF5, +- 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, 0x00, 0x72, 0x7E, 0x71, 0x8D, 0xFF, 0xAD, 0xFF, 0xB1, 0x60, +- 0xC0, 0x78, 0xFF, 0xFF, 0x25, 0x44, 0x8A, 0xF1, 0x8B, 0xF1, 0xD0, 0x80, 0xD0, 0x80, 0x07, 0x04, +- 0x01, 0x06, 0x05, 0x00, 0x25, 0x46, 0x01, 0xF0, 0x03, 0x67, 0xA0, 0x85, 0x94, 0x80, 0x2F, 0x58, +- 0xFF, 0xFF, 0x25, 0x46, 0x26, 0x41, 0x46, 0x63, 0x01, 0xF2, 0xFF, 0xFF, 0xFF, 0xB5, 0xD5, 0x81, +- 0x00, 0xF2, 0x05, 0x04, 0x04, 0x63, 0x60, 0x46, 0xF7, 0x1B, 0x42, 0xFE, 0x0D, 0x00, 0x61, 0x44, +- 0xC5, 0x81, 0x63, 0x45, 0xC5, 0x81, 0x9C, 0x84, 0xDC, 0x84, 0x01, 0xF2, 0xF0, 0x85, 0xF0, 0x80, +- 0x65, 0x44, 0xF8, 0x85, 0xFF, 0xFF, 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x1B, 0x60, +- 0xD0, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xAC, 0x86, 0x0E, 0xF2, 0x07, 0x03, 0x00, 0xA8, 0x09, 0xF2, +- 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, 0x08, 0xFE, 0x17, 0x00, 0x8C, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, +- 0x00, 0xB4, 0x12, 0x06, 0x09, 0x60, 0x08, 0x61, 0x41, 0x4A, 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, +- 0xB3, 0x60, 0x58, 0x4E, 0x97, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x06, 0x03, 0x2A, 0x43, 0xB3, 0x60, +- 0x58, 0x4E, 0xB8, 0x78, 0xFF, 0xFF, 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0x41, 0x4A, +- 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, 0xB3, 0x60, 0x58, 0x4E, 0x97, 0x78, 0xFF, 0xFF, 0x07, 0x03, +- 0x2A, 0x43, 0xB3, 0x60, 0x58, 0x4E, 0xB8, 0x78, 0xFF, 0xFF, 0x08, 0xFE, 0x0D, 0x00, 0x1B, 0x60, +- 0xD0, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xAC, 0x86, 0x0E, 0xF2, 0x06, 0x03, 0x00, 0xA8, 0x09, 0xF2, +- 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0x8D, 0xF3, +- 0x7C, 0x63, 0x00, 0xBE, 0x40, 0x45, 0x1A, 0x03, 0x00, 0x65, 0x65, 0x44, 0xDC, 0x85, 0x84, 0xA1, +- 0x00, 0xF2, 0x06, 0x06, 0x01, 0xFC, 0x00, 0xA8, 0x60, 0x46, 0xF7, 0x02, 0x40, 0x45, 0x0E, 0x00, +- 0x8C, 0xF3, 0x00, 0x63, 0xD4, 0x84, 0x8C, 0xFB, 0x80, 0x60, 0x7C, 0x64, 0x01, 0xFA, 0x00, 0xF0, +- 0x00, 0xFC, 0xD3, 0x80, 0x8D, 0xF9, 0x02, 0x02, 0x8E, 0xF9, 0x08, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, +- 0x66, 0x44, 0x25, 0x46, 0x05, 0xFA, 0x06, 0xFA, 0x01, 0xF0, 0x03, 0x67, 0x02, 0xFC, 0xB0, 0x84, +- 0x3A, 0x7E, 0x01, 0xFA, 0x12, 0x64, 0x03, 0xFA, 0x00, 0xF0, 0x04, 0xF8, 0x00, 0x64, 0x0C, 0x61, +- 0x10, 0x63, 0x59, 0xDA, 0xFE, 0x1F, 0x2E, 0x58, 0xFF, 0xFF, 0x27, 0x43, 0xE3, 0x81, 0xE9, 0x81, +- 0x03, 0x05, 0x16, 0x03, 0x00, 0x61, 0x01, 0x00, 0xE4, 0x63, 0x61, 0x46, 0xBF, 0xD2, 0x27, 0x45, +- 0xDC, 0x84, 0xA2, 0xDA, 0xBE, 0xD2, 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, 0x25, 0x44, 0x61, 0x46, +- 0xA3, 0xDA, 0x04, 0x00, 0x0A, 0xFA, 0x60, 0x46, 0x25, 0x44, 0x09, 0xFA, 0x61, 0x46, 0xBE, 0xDA, +- 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x44, 0x00, 0xA8, 0x07, 0x4B, 0x0C, 0x03, 0x58, 0x4F, 0x33, 0x00, +- 0x0B, 0x47, 0x1B, 0x60, 0xC4, 0x65, 0x27, 0x44, 0xD4, 0x80, 0x00, 0x64, 0x01, 0x02, 0x0F, 0xFA, +- 0x58, 0x4F, 0xD3, 0x01, 0x70, 0x00, 0x25, 0x43, 0xE3, 0x84, 0x7C, 0x41, 0x02, 0x04, 0xE8, 0x81, +- 0xE4, 0x63, 0x61, 0x46, 0xA3, 0xD2, 0x00, 0x7C, 0x40, 0x45, 0xBF, 0xD8, 0xA3, 0xD8, 0xBE, 0xD8, +- 0x27, 0x42, 0x5A, 0xD3, 0x25, 0x5C, 0x60, 0x41, 0x02, 0x1B, 0x27, 0xD9, 0x05, 0x00, 0x25, 0x46, +- 0x0A, 0xFA, 0x61, 0x46, 0x25, 0x44, 0x09, 0xFA, 0x25, 0x44, 0x27, 0x43, 0x00, 0x61, 0x60, 0x46, +- 0x09, 0xF2, 0x08, 0xFC, 0x00, 0xA8, 0xDD, 0x81, 0xFA, 0x02, 0xBF, 0xD1, 0x66, 0x44, 0xBE, 0xDB, +- 0xC1, 0x84, 0xBF, 0xDB, 0x48, 0x00, 0x25, 0x46, 0xE4, 0x63, 0x08, 0xF2, 0x89, 0xF2, 0x1E, 0x18, +- 0x40, 0x47, 0xE0, 0x84, 0xE8, 0x85, 0x02, 0x05, 0xE8, 0x83, 0x00, 0x65, 0x65, 0x46, 0xBF, 0xD2, +- 0x61, 0x5C, 0xCC, 0x84, 0xA2, 0xDA, 0x25, 0x46, 0x0A, 0xF2, 0x00, 0xB9, 0x65, 0x46, 0x08, 0x24, +- 0xBE, 0xDA, 0x02, 0x1B, 0xA3, 0xD8, 0x02, 0x00, 0x60, 0x46, 0x89, 0xFA, 0x00, 0xB9, 0x61, 0x46, +- 0x08, 0x28, 0x0A, 0xFA, 0x25, 0x46, 0x89, 0xFC, 0x8A, 0xFC, 0x88, 0xFC, 0x2F, 0x58, 0xFF, 0xFF, +- 0x00, 0x61, 0x28, 0x65, 0x25, 0x43, 0x8E, 0xF3, 0xAF, 0x83, 0x00, 0xBE, 0x18, 0x03, 0x02, 0x03, +- 0x00, 0xFC, 0x01, 0x00, 0x8D, 0xFD, 0x63, 0x46, 0x65, 0x44, 0xCC, 0x85, 0x00, 0xF2, 0x07, 0x02, +- 0x8E, 0xF5, 0x00, 0x64, 0x00, 0xFA, 0xDE, 0x60, 0xAF, 0x64, 0x09, 0xFB, 0x08, 0x00, 0x66, 0x43, +- 0x00, 0xBE, 0xDD, 0x81, 0xF1, 0x02, 0x8C, 0xF1, 0x8E, 0xFD, 0xC1, 0x84, 0x8C, 0xFB, 0x2E, 0x58, +- 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x45, 0x29, 0x43, 0xFC, 0xA3, 0x66, 0x44, 0xBD, 0xDB, 0x25, 0x44, +- 0xBD, 0xDB, 0x00, 0x64, 0xBD, 0xDB, 0x03, 0x61, 0x0E, 0x65, 0x1B, 0x60, 0xD8, 0x63, 0x43, 0x49, +- 0xA3, 0xD3, 0x06, 0xA3, 0x00, 0xA8, 0xCD, 0x81, 0x04, 0x02, 0xF9, 0x02, 0xB1, 0x60, 0xC0, 0x78, +- 0xFF, 0xFF, 0x01, 0x26, 0xE6, 0x01, 0xD4, 0x80, 0x60, 0x45, 0xE3, 0x05, 0xF6, 0xA3, 0xBD, 0xD1, +- 0xBD, 0xD1, 0x44, 0x47, 0x44, 0x48, 0x44, 0x45, 0x1C, 0x60, 0x16, 0x64, 0x44, 0xD7, 0xFF, 0xFF, +- 0xFF, 0xFF, 0x48, 0xFE, 0x8D, 0xF5, 0x8C, 0xF3, 0x0D, 0x18, 0xCC, 0x84, 0x8C, 0xFB, 0x80, 0x60, +- 0x7C, 0x64, 0x01, 0xFA, 0x00, 0x64, 0x00, 0xF0, 0x00, 0xFA, 0xD0, 0x80, 0x8D, 0xF9, 0x02, 0x02, +- 0x8E, 0xF9, 0x08, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x1B, 0x60, 0x88, 0x63, 0x0D, 0x65, 0x00, 0x61, +- 0x41, 0x48, 0xA3, 0xD3, 0x06, 0xA3, 0xAC, 0x86, 0x00, 0x61, 0x09, 0x03, 0x00, 0xF2, 0x09, 0xF0, +- 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x64, 0x44, 0xAC, 0x86, 0xF6, 0x01, 0x61, 0x44, +- 0x25, 0x46, 0x27, 0xDA, 0x65, 0x44, 0x28, 0x45, 0x45, 0x88, 0xCC, 0x85, 0x5A, 0x87, 0xE9, 0x02, +- 0x00, 0x64, 0x27, 0xDA, 0x5A, 0xDA, 0x5A, 0x87, 0x88, 0xF3, 0x87, 0xF1, 0x02, 0xA4, 0x60, 0x46, +- 0x60, 0x45, 0x00, 0x61, 0x1E, 0xF2, 0xFF, 0xFF, 0xAC, 0x86, 0x00, 0xF2, 0x04, 0x03, 0xAC, 0x86, +- 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x65, 0x44, 0x02, 0xA5, 0x65, 0x46, 0x64, 0x44, 0xCC, 0x9C, +- 0xFF, 0xFF, 0xF0, 0x02, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x5A, 0x87, 0x28, 0x45, 0x45, 0x88, +- 0x88, 0xF3, 0x87, 0xF1, 0x02, 0xA4, 0x60, 0x46, 0x60, 0x45, 0x00, 0x61, 0x72, 0xF2, 0xFF, 0xFF, +- 0xAC, 0x86, 0x00, 0xF2, 0x09, 0x03, 0x00, 0xF2, 0x09, 0xF0, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, +- 0xFC, 0x02, 0x64, 0x44, 0xAC, 0x86, 0xF6, 0x01, 0x65, 0x44, 0x02, 0xA5, 0x65, 0x46, 0x64, 0x44, +- 0xCC, 0x9C, 0x61, 0x44, 0xEB, 0x02, 0x25, 0x46, 0x27, 0xDA, 0x5A, 0x87, 0x28, 0x45, 0x45, 0x88, +- 0x06, 0x60, 0x40, 0x65, 0x8D, 0xF3, 0x01, 0x61, 0xAC, 0x86, 0x00, 0xF2, 0x03, 0x03, 0xD5, 0x80, +- 0xDD, 0x81, 0xFA, 0x04, 0xCD, 0x84, 0x25, 0x46, 0x27, 0xDA, 0x28, 0x45, 0xC4, 0x84, 0x5A, 0xDA, +- 0xDA, 0x81, 0x8C, 0xF1, 0x59, 0xD8, 0x1B, 0x60, 0x86, 0x64, 0x18, 0x63, 0xA0, 0xD1, 0x06, 0xA4, +- 0x59, 0xD8, 0xFC, 0x1F, 0x00, 0x64, 0x59, 0xDA, 0x59, 0xDA, 0x01, 0x60, 0x1C, 0x64, 0x0A, 0x63, +- 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, 0x7E, 0xF1, 0x59, 0xD8, 0x45, 0x01, 0x07, 0x4B, 0xB4, 0x60, +- 0x58, 0x4F, 0x23, 0x78, 0xFF, 0xFF, 0x0B, 0x47, 0x58, 0x4F, 0x21, 0x00, 0x3C, 0x01, 0x07, 0x4B, +- 0xB4, 0x60, 0x58, 0x4F, 0x23, 0x78, 0xFF, 0xFF, 0x0B, 0x47, 0x27, 0x44, 0x00, 0xBE, 0x08, 0xF0, +- 0x15, 0x03, 0x64, 0x42, 0x4A, 0xD3, 0x09, 0xF2, 0xDC, 0x83, 0xA2, 0xDD, 0x25, 0x43, 0x09, 0xFC, +- 0x63, 0x46, 0x27, 0x43, 0x0A, 0xFC, 0x09, 0xFA, 0x08, 0xF8, 0x00, 0xA8, 0x66, 0x43, 0x03, 0x02, +- 0x64, 0x44, 0x58, 0xDD, 0x03, 0x00, 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, 0x1C, 0x01, 0x27, 0x43, +- 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, 0x16, 0x03, 0x00, 0x61, 0x01, 0x00, 0xE4, 0x63, 0x61, 0x46, +- 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, 0xA2, 0xDA, 0xA3, 0xD2, 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, +- 0x25, 0x44, 0x61, 0x46, 0xBE, 0xDA, 0x04, 0x00, 0x09, 0xFA, 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, +- 0x61, 0x46, 0xA3, 0xDA, 0x2F, 0x58, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x03, 0x02, +- 0x28, 0xE2, 0x40, 0xFF, 0xA1, 0xFF, 0x84, 0xFF, 0xBF, 0x60, 0xAD, 0x64, 0x40, 0x42, 0xB5, 0x60, +- 0xA2, 0x64, 0x40, 0x40, 0x9D, 0xF3, 0x66, 0xFB, 0x0F, 0x60, 0x9A, 0x63, 0xAA, 0xF3, 0xBD, 0xDB, +- 0x00, 0x60, 0x9A, 0x64, 0xBD, 0xDB, 0x02, 0x64, 0xBD, 0xDB, 0x04, 0x64, 0xA3, 0xDB, 0x5C, 0x49, +- 0x0A, 0x64, 0x40, 0x4B, 0x5C, 0x5C, 0x01, 0x60, 0x39, 0xE2, 0x04, 0x60, 0x00, 0x7A, 0x89, 0xFF, +- 0x03, 0x60, 0xFF, 0x73, 0x88, 0xFF, 0xB5, 0x60, 0xA2, 0x78, 0xFF, 0xFF, 0xA0, 0xFE, 0x07, 0x05, +- 0xA3, 0xFE, 0x07, 0x05, 0xA1, 0xFE, 0x50, 0x05, 0x60, 0x64, 0x3B, 0xDB, 0x10, 0x00, 0x20, 0x58, +- 0xFF, 0xFF, 0xFA, 0x01, 0x12, 0x60, 0xCC, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0xFB, 0xB4, 0xA3, 0xDB, +- 0xA0, 0x4C, 0x59, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0xA0, 0x4C, 0x7D, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, +- 0xFF, 0xFF, 0x83, 0x3E, 0x40, 0x60, 0x0B, 0x65, 0x2B, 0x44, 0x00, 0x63, 0xE8, 0x80, 0xF8, 0x84, +- 0x02, 0x24, 0x94, 0x84, 0xF3, 0x83, 0xCD, 0x81, 0xFF, 0xFF, 0xF8, 0x02, 0xDF, 0x83, 0x2F, 0x58, +- 0x40, 0x4B, 0x00, 0x62, 0x01, 0x64, 0xD4, 0x80, 0xE0, 0x84, 0x1A, 0x03, 0xD4, 0x80, 0xE0, 0x84, +- 0x15, 0x03, 0x61, 0x44, 0x11, 0x61, 0xE0, 0x84, 0xCD, 0x81, 0xFD, 0x04, 0x01, 0x00, 0xE0, 0x84, +- 0xF2, 0x82, 0xFF, 0xFF, 0x02, 0x24, 0xC6, 0x82, 0x02, 0x28, 0xD6, 0x82, 0xE2, 0x80, 0xCD, 0x81, +- 0x02, 0x28, 0x01, 0xBC, 0xF4, 0x02, 0x01, 0x2A, 0xC6, 0x82, 0x03, 0x00, 0xE9, 0x81, 0xF2, 0x82, +- 0x61, 0x44, 0x2D, 0x58, 0xFF, 0xFF, 0x00, 0xA8, 0x10, 0x61, 0x04, 0x03, 0xF0, 0x84, 0xCD, 0x81, +- 0xFD, 0x04, 0x61, 0x44, 0x2D, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x3B, 0xDB, 0x16, 0x60, 0xA8, 0x63, +- 0xBD, 0xD3, 0xA3, 0xD1, 0x60, 0x40, 0x04, 0x3A, 0x2D, 0x00, 0x00, 0x64, 0x4A, 0xDB, 0x1B, 0x60, +- 0x88, 0x63, 0xA3, 0xD3, 0x46, 0x43, 0xAC, 0x86, 0x3C, 0x45, 0x23, 0x03, 0xD4, 0x80, 0x07, 0xF2, +- 0x02, 0x02, 0x09, 0xF2, 0xF8, 0x01, 0xD0, 0x80, 0x09, 0xF2, 0xF5, 0x02, 0x60, 0x43, 0x80, 0x67, +- 0xB0, 0x81, 0x1B, 0x60, 0xDA, 0x62, 0x61, 0x44, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x09, 0x60, 0x08, 0x65, 0x0E, 0xF2, 0x02, 0xF2, 0x60, 0x40, +- 0xF0, 0x37, 0x05, 0x00, 0x90, 0xF3, 0xD4, 0x80, 0xCC, 0x84, 0x01, 0x02, 0x90, 0xFB, 0x63, 0x44, +- 0xDA, 0x01, 0x23, 0x46, 0x3C, 0x44, 0xAC, 0x80, 0xFF, 0xFF, 0x89, 0x02, 0x6A, 0xF3, 0x6B, 0xF3, +- 0x02, 0xA8, 0x02, 0xA8, 0x08, 0x02, 0x00, 0x64, 0x6C, 0xFB, 0x6A, 0xFB, 0x6B, 0xFB, 0x00, 0x64, +- 0x6D, 0xFB, 0xCA, 0xFE, 0x97, 0x00, 0x03, 0x02, 0x00, 0x64, 0x6B, 0xFB, 0xCA, 0xFE, 0x01, 0x64, +- 0x3B, 0xDB, 0x1B, 0x60, 0x8E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x35, 0x03, +- 0x2C, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x8A, 0x00, 0x2E, 0xF2, 0x12, 0x60, 0xCE, 0x65, +- 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, +- 0x16, 0x18, 0x61, 0x46, 0x2E, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, +- 0x2D, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2C, 0xF0, 0x63, 0x46, +- 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x88, 0xF3, +- 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x63, 0x02, 0x66, 0x45, 0x63, 0x46, 0x06, 0xF2, 0x65, 0x46, +- 0x80, 0xB0, 0x09, 0xF2, 0x5C, 0x03, 0xAC, 0x86, 0xCA, 0x01, 0x6B, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, +- 0xFF, 0xFF, 0x50, 0x02, 0x1B, 0x60, 0xA0, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, +- 0x0F, 0x03, 0x77, 0xF1, 0x07, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, 0x09, 0xF2, 0x03, 0x02, 0xAC, 0x86, +- 0x07, 0xF2, 0xFA, 0x02, 0x03, 0x02, 0x00, 0x64, 0x77, 0xFB, 0xEC, 0x01, 0x46, 0x5C, 0x3F, 0x00, +- 0x1B, 0x60, 0xA6, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x01, 0x03, 0x37, 0x02, +- 0x6C, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x14, 0x02, 0x1B, 0x60, 0x94, 0x62, 0xA2, 0xD3, +- 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x0B, 0x03, 0x2A, 0xF0, 0x20, 0x67, 0x09, 0xF2, 0xB0, 0x83, +- 0x00, 0xA8, 0x00, 0x64, 0x02, 0x03, 0x2A, 0xFC, 0x01, 0x00, 0x6C, 0xFB, 0x20, 0x00, 0x00, 0x64, +- 0x6C, 0xFB, 0x1B, 0x60, 0x88, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x12, 0x03, +- 0x2A, 0xF0, 0x08, 0x67, 0xA0, 0x80, 0xFF, 0xFF, 0x12, 0x03, 0x77, 0xF1, 0x07, 0xF2, 0xFF, 0xFF, +- 0xD0, 0x80, 0x09, 0xF2, 0x03, 0x02, 0xAC, 0x86, 0x07, 0xF2, 0xFA, 0x02, 0x08, 0x02, 0x00, 0x64, +- 0x77, 0xFB, 0xE7, 0x01, 0x00, 0x64, 0x77, 0xFB, 0xB5, 0x60, 0xA2, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0xFC, 0xFB, 0x46, 0x5C, 0x21, 0x60, 0x98, 0x63, 0xA3, 0xD3, 0xB5, 0x60, 0x58, 0x4D, 0xE3, 0x78, +- 0xFF, 0xFF, 0x0D, 0xF2, 0x60, 0x5C, 0x64, 0x5F, 0x0D, 0xFA, 0x07, 0xF0, 0x2A, 0xF2, 0xFF, 0xFF, +- 0x77, 0xF9, 0x60, 0x40, 0x08, 0x2B, 0x05, 0x00, 0x00, 0x64, 0x48, 0xFB, 0xB8, 0x60, 0x2D, 0x78, +- 0xFF, 0xFF, 0x00, 0x64, 0xD0, 0x80, 0x88, 0xF3, 0x07, 0x02, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, +- 0xA2, 0xDA, 0xBD, 0x60, 0x28, 0x78, 0xFF, 0xFF, 0xD0, 0x80, 0xB8, 0xF3, 0x03, 0x03, 0x60, 0x40, +- 0x03, 0x3A, 0x00, 0x00, 0x2A, 0xF2, 0x00, 0x63, 0x40, 0x47, 0x50, 0x36, 0x01, 0x00, 0x01, 0x63, +- 0x48, 0xFD, 0x4A, 0xF3, 0x35, 0xFA, 0x10, 0xA4, 0x4A, 0xFB, 0x00, 0x64, 0x15, 0xFA, 0x16, 0xFA, +- 0x0F, 0xFA, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x0E, 0xF0, 0x63, 0x46, 0x00, 0x7F, +- 0x64, 0x5E, 0x4B, 0xFB, 0x64, 0x44, 0x00, 0x7E, 0xBB, 0xFB, 0x07, 0xF0, 0x88, 0xF3, 0xFF, 0xFF, +- 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0xBB, 0xF3, 0xBA, 0xFB, 0x60, 0x41, 0x03, 0xF2, 0x00, 0xF4, +- 0x01, 0xF2, 0xFC, 0xA5, 0x00, 0x7F, 0xD4, 0x84, 0x27, 0x45, 0x3C, 0x46, 0x1A, 0xFA, 0x22, 0x63, +- 0x7B, 0x60, 0xFF, 0x64, 0xA4, 0x84, 0x03, 0x2B, 0x1C, 0x63, 0x2A, 0xFA, 0x60, 0x40, 0xA4, 0x36, +- 0x14, 0x63, 0x43, 0x4C, 0x00, 0x7C, 0x22, 0xF8, 0x64, 0x41, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, +- 0x36, 0xF2, 0x63, 0x46, 0xFF, 0xB4, 0x22, 0xFA, 0x60, 0x40, 0x00, 0x36, 0x8E, 0x00, 0x2A, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x3A, 0x89, 0x00, 0x03, 0xF2, 0x00, 0xF4, 0xA0, 0xD2, 0xAA, 0x60, +- 0xAA, 0x65, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, 0x0A, 0x02, 0xD0, 0x80, 0x00, 0x64, 0x5A, 0xD0, +- 0x06, 0x02, 0xD0, 0x80, 0xF8, 0x7F, 0xD0, 0x80, 0x01, 0x03, 0x01, 0x02, 0x01, 0x61, 0x62, 0x43, +- 0x46, 0x43, 0x3C, 0x46, 0x07, 0xF4, 0x36, 0xF2, 0xFF, 0xFF, 0xA3, 0x46, 0x60, 0x40, 0x22, 0x26, +- 0x45, 0x00, 0x60, 0x45, 0x63, 0x42, 0x5A, 0xD0, 0xCD, 0x81, 0x3C, 0x46, 0x14, 0x02, 0x64, 0x44, +- 0x88, 0x3A, 0x11, 0x00, 0x8E, 0x3B, 0x0F, 0x00, 0x65, 0x44, 0x01, 0x26, 0x5E, 0x00, 0x04, 0x26, +- 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, 0x2D, 0x00, 0xA3, 0x46, 0x37, 0xF2, 0xFF, 0xFF, 0x60, 0x40, +- 0x80, 0x2B, 0x53, 0x00, 0x3A, 0x00, 0xA3, 0x46, 0x65, 0x44, 0x01, 0x26, 0x0B, 0x00, 0x04, 0x26, +- 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, 0x1D, 0x00, 0x37, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x27, +- 0x2C, 0x00, 0x17, 0x00, 0x88, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x36, 0xF2, 0x66, 0x43, 0xFF, 0xB4, +- 0x3C, 0x46, 0x22, 0xF0, 0x60, 0x47, 0xB0, 0x84, 0x22, 0xFA, 0x63, 0x46, 0x37, 0xF0, 0x60, 0x40, +- 0x04, 0x27, 0x03, 0x00, 0x10, 0x27, 0x01, 0x00, 0x04, 0x00, 0x64, 0x40, 0x80, 0x27, 0x15, 0x00, +- 0x00, 0x00, 0x3C, 0x46, 0x02, 0x65, 0xBC, 0x60, 0x58, 0x78, 0xFF, 0xFF, 0xCD, 0x81, 0x63, 0x42, +- 0x5A, 0xD0, 0x3C, 0x46, 0x0A, 0x02, 0x64, 0x44, 0x88, 0x3A, 0x07, 0x00, 0x77, 0x37, 0x1D, 0x00, +- 0x78, 0x37, 0x1B, 0x00, 0x8E, 0x37, 0x19, 0x00, 0xF1, 0x01, 0x3C, 0x46, 0x22, 0xF0, 0x80, 0x67, +- 0xB0, 0x84, 0xA2, 0xDA, 0xFF, 0xFF, 0x3F, 0xF2, 0x3E, 0xF0, 0x08, 0xA4, 0x60, 0x41, 0x22, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x03, 0x00, 0x06, 0x00, 0x04, 0x2B, +- 0x04, 0x00, 0x61, 0x44, 0x64, 0x40, 0x10, 0x26, 0x3F, 0xFA, 0x3C, 0x46, 0x2C, 0xF2, 0x27, 0x40, +- 0x01, 0x27, 0x32, 0xF2, 0xB5, 0xF1, 0x60, 0x40, 0x01, 0x26, 0x53, 0x00, 0x09, 0x60, 0x00, 0x64, +- 0xD0, 0x80, 0x3F, 0xF2, 0x09, 0x06, 0x2C, 0x45, 0xC4, 0x84, 0xD0, 0x80, 0x40, 0x4A, 0x40, 0x06, +- 0x60, 0x43, 0x64, 0x44, 0x54, 0x88, 0x18, 0x00, 0x60, 0x45, 0x1F, 0x60, 0x9C, 0x64, 0xA0, 0xD3, +- 0xBB, 0xF3, 0x00, 0xBC, 0x60, 0x47, 0xEC, 0xA0, 0x33, 0x03, 0x32, 0x07, 0x2C, 0x44, 0xC4, 0x81, +- 0x02, 0x60, 0x1C, 0x65, 0x45, 0x4A, 0xD5, 0x80, 0x2C, 0x45, 0x2A, 0x06, 0x27, 0x40, 0x04, 0x27, +- 0x30, 0x00, 0x2A, 0x43, 0xD7, 0x85, 0x45, 0x48, 0xB6, 0xF1, 0x0F, 0xF2, 0xD3, 0x80, 0x01, 0x65, +- 0x01, 0x07, 0x00, 0x65, 0xB4, 0x84, 0x0F, 0xFA, 0x00, 0x63, 0x3F, 0xF2, 0x28, 0x45, 0x60, 0x41, +- 0xD4, 0x84, 0xDF, 0x83, 0xFC, 0x07, 0x14, 0xFC, 0x61, 0x44, 0x01, 0x36, 0x02, 0x00, 0x09, 0x3A, +- 0x06, 0x00, 0x28, 0x44, 0x48, 0x88, 0x2A, 0x44, 0xC8, 0x83, 0x43, 0x4A, 0xE5, 0x01, 0x17, 0xFA, +- 0x04, 0x60, 0x00, 0x64, 0x27, 0x45, 0xB4, 0x84, 0x2A, 0xFA, 0x28, 0x43, 0x16, 0xFC, 0x0D, 0x00, +- 0x3F, 0xF2, 0x2C, 0x45, 0xB6, 0xF1, 0xC4, 0x81, 0xD1, 0x80, 0x0F, 0xF2, 0x01, 0x06, 0x01, 0xBC, +- 0x0F, 0xFA, 0x3F, 0xF2, 0x17, 0xFA, 0x01, 0x64, 0x14, 0xFA, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, +- 0x0E, 0xF0, 0x63, 0x46, 0x00, 0x7F, 0x64, 0x5E, 0x4B, 0xFB, 0x64, 0x44, 0x00, 0x7E, 0xBB, 0xFB, +- 0x62, 0xF1, 0x60, 0x43, 0x60, 0x47, 0xD0, 0x80, 0xC0, 0x65, 0x01, 0x06, 0x64, 0x44, 0x0A, 0x36, +- 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x36, 0x15, 0x64, 0x6E, 0x36, 0x0B, 0x64, 0x44, 0x86, +- 0x2A, 0xF2, 0x07, 0xF0, 0x60, 0x40, 0xB0, 0x3A, 0x03, 0x00, 0x40, 0x3B, 0x01, 0x00, 0x12, 0x00, +- 0x0C, 0xB4, 0x08, 0x3A, 0x55, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, 0x50, 0x00, +- 0x17, 0xF2, 0x22, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x22, 0x22, 0x04, 0x00, 0x00, 0xA8, 0x01, 0xA8, +- 0x47, 0x03, 0x46, 0x03, 0x3C, 0x46, 0x2A, 0xF0, 0x40, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x60, 0x45, +- 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x43, 0x60, 0x40, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x0A, 0x00, +- 0x02, 0x00, 0x04, 0x27, 0x07, 0x00, 0x65, 0x44, 0x2A, 0x65, 0x60, 0x40, 0x03, 0x2B, 0x24, 0x65, +- 0x45, 0x4C, 0x2E, 0x00, 0x65, 0x44, 0x2E, 0x65, 0x60, 0x40, 0x03, 0x2B, 0x28, 0x65, 0x45, 0x4C, +- 0x07, 0xF0, 0x88, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0x00, 0x7C, 0x03, 0x03, 0x63, 0x40, 0x01, 0x2A, +- 0x01, 0x00, 0x3D, 0xF1, 0x2A, 0xF2, 0xFF, 0xFF, 0x08, 0xB0, 0x3E, 0xF2, 0x19, 0x03, 0x60, 0x47, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x03, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, 0x11, 0x03, 0x1B, 0x60, +- 0xD4, 0x62, 0x1B, 0x60, 0xAC, 0x64, 0xA2, 0xDB, 0x3C, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0x5C, 0x5C, 0xFC, 0xFC, 0xCE, 0xFE, 0xB5, 0x60, 0xEC, 0x78, 0xFF, 0xFF, +- 0xBB, 0xF1, 0x2C, 0x45, 0x64, 0x43, 0x17, 0xF2, 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x81, 0x63, 0x40, 0x37, 0x37, 0xE1, 0x81, 0x64, 0x45, 0xB5, 0x60, 0x58, 0x4D, 0xC1, 0x78, +- 0xFF, 0xFF, 0xAE, 0x82, 0xFC, 0xA2, 0x0A, 0x03, 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, +- 0x04, 0x0D, 0x63, 0x44, 0x80, 0x7E, 0xBB, 0xFB, 0x61, 0x44, 0xDC, 0x84, 0x2B, 0xF0, 0x1B, 0xFA, +- 0x64, 0x44, 0x80, 0x27, 0x34, 0x00, 0x16, 0xF2, 0x0F, 0xF0, 0xAC, 0x84, 0x2C, 0x45, 0x29, 0x03, +- 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x63, 0x40, 0x37, 0x37, 0xE1, 0x81, +- 0x64, 0x45, 0x0F, 0xF0, 0xB5, 0x60, 0x58, 0x4D, 0xC1, 0x78, 0xFF, 0xFF, 0xAE, 0x82, 0xFC, 0xA2, +- 0x0A, 0x03, 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, 0x04, 0x0D, 0x80, 0x67, 0xB0, 0x84, +- 0x0F, 0xFA, 0x61, 0x44, 0xDC, 0x84, 0x1D, 0xFA, 0xDE, 0x65, 0xC4, 0x85, 0x26, 0x41, 0xE1, 0x81, +- 0xC5, 0x84, 0x2B, 0xFA, 0x1B, 0xF0, 0xDE, 0x64, 0xC0, 0x85, 0x26, 0x44, 0xE0, 0x84, 0xC4, 0x84, +- 0x10, 0xFA, 0x26, 0x44, 0x2C, 0xF0, 0x0A, 0xA4, 0x64, 0x40, 0x01, 0x26, 0x00, 0x64, 0x11, 0xFA, +- 0xBB, 0xF3, 0x13, 0xFA, 0xFF, 0xFF, 0x0D, 0xF2, 0x3E, 0xF0, 0x60, 0x47, 0xFF, 0xB4, 0x64, 0x41, +- 0x01, 0xB1, 0x01, 0x63, 0x1D, 0x02, 0x60, 0x41, 0xFF, 0x22, 0x04, 0x00, 0xB5, 0x60, 0x58, 0x4F, +- 0xB2, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0x92, 0x64, 0xA0, 0xDD, 0x21, 0x60, 0x98, 0x62, 0xA2, 0xD3, +- 0xB5, 0x60, 0x58, 0x4D, 0xE3, 0x78, 0xFF, 0xFF, 0x60, 0x41, 0x01, 0x63, 0x61, 0x40, 0xFF, 0x22, +- 0x04, 0x00, 0xB5, 0x60, 0x58, 0x4F, 0xB2, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0x94, 0x64, 0xA0, 0xDD, +- 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, 0x03, 0x00, 0xBA, 0x60, 0x4A, 0x78, 0xFF, 0xFF, +- 0x22, 0xF2, 0x46, 0x43, 0x60, 0x40, 0x22, 0x26, 0x8B, 0x00, 0x01, 0x26, 0x05, 0x00, 0x04, 0x26, +- 0x0C, 0x00, 0xBA, 0x60, 0x4A, 0x78, 0xFF, 0xFF, 0x04, 0x27, 0x03, 0x00, 0xBA, 0x60, 0x4A, 0x78, +- 0xFF, 0xFF, 0x88, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x02, 0x00, 0x07, 0xF4, 0xFF, 0xFF, 0xA3, 0x46, +- 0x2A, 0xF2, 0xA3, 0x46, 0x60, 0x40, 0x08, 0x27, 0x3B, 0x00, 0x88, 0xF3, 0x66, 0x5C, 0xD0, 0x80, +- 0x37, 0xF0, 0x08, 0x03, 0x64, 0x40, 0x10, 0x2A, 0x12, 0x00, 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, +- 0x37, 0xFA, 0x24, 0x00, 0x3D, 0xF3, 0x01, 0x61, 0x60, 0x43, 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, +- 0xE9, 0x81, 0xA1, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0x91, 0x84, 0x37, 0xFA, 0x17, 0x00, 0x47, 0xF2, +- 0xFF, 0xFF, 0x10, 0xA0, 0xFF, 0xFF, 0x02, 0x04, 0xFF, 0x60, 0xFF, 0x64, 0xDC, 0x84, 0x47, 0xFA, +- 0x46, 0xF2, 0x16, 0x04, 0xDC, 0x84, 0x46, 0xFA, 0x45, 0xF2, 0x08, 0x04, 0xDC, 0x84, 0x45, 0xFA, +- 0x05, 0x04, 0x37, 0xF2, 0xFF, 0xFF, 0xE0, 0x84, 0xE8, 0x84, 0x37, 0xFA, 0x0D, 0x60, 0x3E, 0x62, +- 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC4, 0x60, 0x05, 0x78, 0xFF, 0xFF, 0x84, 0xFF, +- 0x0D, 0x60, 0x3E, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC4, 0x60, 0x7D, 0x78, +- 0xFF, 0xFF, 0x84, 0xFF, 0x88, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, +- 0x3C, 0x46, 0x22, 0xF2, 0x63, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x47, 0xF0, +- 0x64, 0x41, 0x64, 0x47, 0xFF, 0xB4, 0x60, 0x5F, 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, +- 0xA3, 0x46, 0x3A, 0xFA, 0x64, 0x44, 0x20, 0x7F, 0x34, 0x94, 0x3B, 0xFA, 0xA3, 0x46, 0x46, 0xF2, +- 0x45, 0xF0, 0xA3, 0x46, 0x3C, 0xFA, 0x3D, 0xF8, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, +- 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x8A, 0x00, +- 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x27, 0x35, 0x00, 0x2A, 0xF2, 0x00, 0x60, 0x7C, 0x62, +- 0x60, 0x40, 0x40, 0x2B, 0x27, 0x00, 0xA2, 0xD3, 0x00, 0x61, 0x60, 0xFE, 0xA0, 0xD3, 0xDE, 0x82, +- 0xA2, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, 0xC0, 0x2B, 0x04, 0x00, +- 0x80, 0x2A, 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, 0x60, 0x47, 0xDC, 0x87, +- 0x01, 0x61, 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, 0xDA, 0x82, 0xA2, 0xD1, +- 0xFF, 0xFF, 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, 0xA2, 0xDB, +- 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0x60, 0x7C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD3, 0x5A, 0xD1, +- 0x3A, 0xFA, 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5A, +- 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, +- 0x80, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, 0x64, 0x45, 0x64, 0x44, 0xE3, 0x7F, +- 0xA0, 0x5A, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5A, +- 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5A, 0x65, 0x40, +- 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE9, 0x7F, +- 0xA0, 0x5A, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5A, +- 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5A, 0x64, 0x47, +- 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5A, 0x08, 0x60, 0x00, 0xEA, +- 0x65, 0x44, 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, +- 0xD1, 0x60, 0x00, 0xEA, 0x02, 0x64, 0x3B, 0xDB, 0xBD, 0x60, 0xEB, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0xFC, 0xFB, 0x07, 0xF0, 0x00, 0x64, 0xD0, 0x80, 0x88, 0xF3, 0x17, 0x03, 0xD0, 0x80, 0x66, 0x41, +- 0x64, 0x46, 0x6F, 0xF2, 0x61, 0x46, 0x6D, 0x03, 0x60, 0x40, 0x00, 0x36, 0x6A, 0x00, 0x47, 0xF1, +- 0x07, 0xF0, 0x64, 0x40, 0x02, 0x26, 0x01, 0x00, 0x0B, 0x00, 0x03, 0x12, 0xBB, 0x60, 0x4E, 0x78, +- 0xFF, 0xFF, 0xFC, 0x0A, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, +- 0x3E, 0xF2, 0x60, 0x45, 0x60, 0x47, 0x07, 0xB0, 0x00, 0x3A, 0x01, 0x00, 0xA6, 0x00, 0x65, 0x44, +- 0x60, 0x40, 0x01, 0x36, 0x4E, 0x00, 0x02, 0x36, 0x4F, 0x00, 0x03, 0x36, 0x2D, 0x00, 0x04, 0x36, +- 0x3E, 0x00, 0x52, 0x00, 0x00, 0x64, 0x4C, 0xFB, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, +- 0x05, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x00, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, +- 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, +- 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, +- 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, +- 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, 0x1D, 0x00, 0x4C, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x4C, 0xFB, +- 0xAB, 0xF3, 0x60, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x14, 0x02, 0x1C, 0x60, 0x0C, 0x62, 0x0F, 0x60, +- 0x96, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xC3, 0x01, 0x4C, 0xF3, +- 0x66, 0x41, 0xDC, 0x84, 0x4C, 0xFB, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x03, 0x7E, 0x6F, 0xFA, +- 0x61, 0x46, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, +- 0x01, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0xF5, 0x01, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0x8C, 0xFA, +- 0x60, 0x47, 0x70, 0xF2, 0xFF, 0xB5, 0x08, 0x18, 0xE4, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x03, 0x02, +- 0xFB, 0x04, 0x01, 0x64, 0x01, 0x00, 0x00, 0x64, 0x0C, 0xF4, 0x00, 0xA8, 0xFF, 0xFF, 0xE4, 0x02, +- 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x70, 0xF2, 0xFF, 0xB5, 0x61, 0x46, +- 0x00, 0xA8, 0xFF, 0xFF, 0x29, 0x03, 0xE0, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0x66, 0x41, +- 0x64, 0x46, 0x70, 0xFA, 0x61, 0x46, 0x01, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, +- 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, +- 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, +- 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, +- 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, 0xA3, 0x01, 0xA2, 0x01, 0x65, 0x44, 0x60, 0x40, 0x01, 0x36, +- 0xA8, 0x01, 0x02, 0x36, 0x01, 0x00, 0xA5, 0x01, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, +- 0x01, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x00, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, +- 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, +- 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, +- 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, +- 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x3E, 0xF2, 0x60, 0x45, +- 0x60, 0x47, 0x07, 0xB0, 0x00, 0x3A, 0x01, 0x00, 0xA3, 0x00, 0x65, 0x44, 0x60, 0x40, 0x01, 0x36, +- 0x0B, 0x00, 0x02, 0x36, 0x14, 0x00, 0x03, 0x36, 0x47, 0x00, 0x04, 0x36, 0x5E, 0x00, 0x05, 0x36, +- 0x0E, 0x00, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, +- 0xFF, 0xFF, 0x02, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x07, 0xF0, +- 0x01, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, +- 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, +- 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, +- 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, +- 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0x00, 0x63, 0x03, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x4C, 0xFD, +- 0x1C, 0x60, 0x0C, 0x62, 0x0F, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x4C, 0xF3, +- 0x02, 0xB0, 0x61, 0x46, 0xCC, 0x84, 0x05, 0x03, 0x04, 0x28, 0x4C, 0xFB, 0xBC, 0x60, 0x48, 0x78, +- 0xFF, 0xFF, 0x04, 0x28, 0x4C, 0xFB, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x04, 0x7E, +- 0x6F, 0xFA, 0x61, 0x46, 0xBC, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, +- 0xFF, 0xFF, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x61, 0x46, 0xFF, 0xA0, 0xFF, 0xFF, 0x2F, 0x06, +- 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x29, 0x00, 0x64, 0x46, 0x70, 0xFA, +- 0x01, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, +- 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, +- 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, +- 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, +- 0x6F, 0xF2, 0x00, 0x63, 0x03, 0x7E, 0x6F, 0xFA, 0x3C, 0x46, 0x4C, 0xFD, 0x51, 0x00, 0x50, 0x00, +- 0x65, 0x44, 0x60, 0x40, 0x01, 0x36, 0x03, 0x00, 0x02, 0x36, 0x12, 0x00, 0x49, 0x00, 0x66, 0x41, +- 0x64, 0x46, 0x70, 0xF2, 0x61, 0x46, 0x01, 0xB0, 0xFF, 0xFF, 0x42, 0x02, 0x07, 0xF0, 0x66, 0x41, +- 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x02, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x39, 0x00, 0x38, 0x00, +- 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x6F, 0xFA, 0x60, 0x47, +- 0xFF, 0xB5, 0x70, 0xF2, 0x61, 0x46, 0xFF, 0xA0, 0xFF, 0xFF, 0xF1, 0x06, 0xE8, 0x84, 0xA4, 0x80, +- 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0xEB, 0x01, 0x66, 0x41, 0x64, 0x46, 0x70, 0xFA, 0x61, 0x46, +- 0x00, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, +- 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, +- 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, +- 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, +- 0x03, 0x64, 0x3B, 0xDB, 0xCA, 0xFE, 0x47, 0xF1, 0x01, 0x65, 0x32, 0x40, 0x04, 0x27, 0x08, 0x00, +- 0x2C, 0xF2, 0x64, 0x45, 0x02, 0x22, 0x04, 0x00, 0x60, 0x40, 0x01, 0x26, 0x01, 0x00, 0xEC, 0x00, +- 0x14, 0xF2, 0x65, 0x40, 0x01, 0x26, 0x1D, 0x00, 0x60, 0x45, 0x05, 0x64, 0x3B, 0xDB, 0x65, 0x44, +- 0xCC, 0x85, 0x98, 0xF1, 0x1E, 0x60, 0xDE, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, +- 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, +- 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, +- 0xAF, 0x00, 0x60, 0x41, 0x2A, 0xF0, 0x00, 0x60, 0x0C, 0x64, 0xA0, 0x84, 0x04, 0x36, 0x02, 0x00, +- 0x0C, 0x3A, 0x01, 0x00, 0xA5, 0x00, 0x61, 0x45, 0x60, 0x41, 0x98, 0xF1, 0x1E, 0x60, 0xDE, 0x64, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, +- 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, +- 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x61, 0x40, 0x08, 0x36, 0x01, 0x00, 0x88, 0x00, +- 0x14, 0xF2, 0x1C, 0x65, 0x60, 0x41, 0x00, 0x63, 0xCD, 0x81, 0xC7, 0x83, 0xFD, 0x02, 0x3F, 0xF0, +- 0x2C, 0xF2, 0xC3, 0x83, 0x60, 0x40, 0x01, 0x2A, 0x29, 0x00, 0x98, 0xF1, 0x1E, 0x60, 0xDC, 0x64, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, +- 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x98, 0xF1, 0x1E, 0x60, +- 0xE2, 0x64, 0xA0, 0xD3, 0x63, 0x45, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, +- 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, +- 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x52, 0x00, 0x98, 0xF1, 0x1E, 0x60, +- 0xDA, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, +- 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x98, 0xF1, +- 0x1E, 0x60, 0xE0, 0x64, 0xA0, 0xD3, 0x63, 0x45, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, +- 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, +- 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x15, 0xF2, 0xFF, 0xFF, +- 0x0F, 0xB4, 0x00, 0xA8, 0x01, 0xA8, 0x24, 0x03, 0x12, 0x03, 0x98, 0xF1, 0x1E, 0x60, 0xE8, 0x64, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, +- 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x11, 0x00, 0x98, 0xF1, +- 0x1E, 0x60, 0xE6, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, +- 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, +- 0x04, 0x64, 0x3B, 0xDB, 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x06, 0xF0, 0xFF, 0x60, 0x5F, 0x64, +- 0xA0, 0x84, 0x06, 0xFA, 0x61, 0x46, 0x1B, 0x60, 0xD4, 0x62, 0x1B, 0x60, 0xAC, 0x64, 0xA2, 0xDB, +- 0x3C, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x5C, 0x5C, 0xFC, 0xFC, +- 0xCE, 0xFE, 0xB5, 0x60, 0xEC, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0x64, 0x62, 0xA2, 0xD3, 0x07, 0xF4, +- 0x06, 0xF2, 0x02, 0xA8, 0x3C, 0x46, 0x10, 0x03, 0x10, 0xB0, 0x2A, 0xF2, 0x0D, 0x03, 0x0E, 0xF2, +- 0x0C, 0xB0, 0x60, 0x40, 0xF0, 0x37, 0x20, 0xBC, 0x02, 0x03, 0xFE, 0x7F, 0x0E, 0xFA, 0x23, 0xF0, +- 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xCC, 0x01, 0x0F, 0xF0, 0x15, 0xF2, 0x64, 0x41, 0x01, 0x2A, +- 0x02, 0x00, 0xB1, 0xF1, 0x09, 0x00, 0x03, 0x65, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x06, 0xF0, +- 0x63, 0x46, 0xB0, 0xF1, 0x64, 0x40, 0x10, 0x2A, 0x64, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x15, 0xFA, +- 0x3B, 0x07, 0x61, 0x40, 0x01, 0x2A, 0x09, 0x00, 0x1F, 0x60, 0x0E, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x08, 0x00, 0x1F, 0x60, 0x10, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x2A, 0xF0, 0x08, 0x67, 0xB0, 0x84, +- 0xA2, 0xDA, 0x08, 0xF0, 0x1B, 0x60, 0x8E, 0x64, 0xD0, 0x80, 0x07, 0xF2, 0x46, 0x43, 0x88, 0xF1, +- 0x06, 0x03, 0x60, 0x46, 0x86, 0xF4, 0xD0, 0x80, 0x80, 0xBB, 0x01, 0x03, 0x06, 0xFC, 0x23, 0x46, +- 0x3E, 0xF2, 0x00, 0x63, 0x01, 0xB0, 0x43, 0x5C, 0xFC, 0xFC, 0x0B, 0x03, 0x1B, 0x60, 0xDA, 0x62, +- 0x1B, 0x60, 0xA6, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xB5, 0x60, 0xEC, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x49, 0xFB, 0x98, 0xF1, 0x1E, 0x60, +- 0xE8, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, +- 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x98, 0xF1, +- 0x1E, 0x60, 0xEA, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, +- 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, +- 0x21, 0x60, 0x98, 0x63, 0xA3, 0xD3, 0xB5, 0x60, 0x58, 0x4D, 0xE3, 0x78, 0xFF, 0xFF, 0x0D, 0xF2, +- 0x60, 0x5C, 0x64, 0x5F, 0x0D, 0xFA, 0x23, 0xF0, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x07, 0xF0, +- 0x66, 0x41, 0x64, 0x46, 0x06, 0xF2, 0x7F, 0x65, 0xA4, 0x9E, 0x06, 0xFA, 0x61, 0x46, 0x40, 0x01, +- 0xBE, 0x60, 0x70, 0x78, 0xFF, 0xFF, 0x21, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0x01, 0x63, 0xC4, 0xB4, +- 0x31, 0xFB, 0x32, 0xFD, 0xBE, 0x60, 0x1C, 0x62, 0x42, 0x40, 0xA0, 0x4C, 0x40, 0xBC, 0x7D, 0xB4, +- 0xA0, 0x51, 0xA0, 0xFE, 0x1A, 0xFF, 0x1B, 0x60, 0xA0, 0x64, 0x08, 0xF0, 0x07, 0xF0, 0xD0, 0x80, +- 0x1B, 0x60, 0xA6, 0x62, 0x14, 0x02, 0xA2, 0xD3, 0x01, 0x63, 0xAC, 0x86, 0x07, 0xF2, 0x0F, 0x03, +- 0xD0, 0x80, 0x09, 0xF2, 0xFA, 0x02, 0x23, 0xFC, 0x1B, 0x60, 0xD4, 0x62, 0x1B, 0x60, 0xAC, 0x64, +- 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x3C, 0x46, +- 0x06, 0x64, 0xA1, 0xFF, 0x49, 0xFB, 0x83, 0x3E, 0x31, 0xF3, 0x87, 0x60, 0x80, 0x61, 0x1D, 0xF0, +- 0x60, 0x40, 0x01, 0x2A, 0x15, 0x00, 0xFE, 0xB4, 0x31, 0xFB, 0x00, 0x64, 0x49, 0xFB, 0x01, 0x64, +- 0x47, 0xFB, 0x21, 0x60, 0x98, 0x63, 0xA3, 0xD3, 0xB5, 0x60, 0x58, 0x4D, 0xE3, 0x78, 0xFF, 0xFF, +- 0x00, 0x71, 0x64, 0x5F, 0x0D, 0xFA, 0x40, 0x64, 0x3B, 0xDB, 0xBE, 0x60, 0x70, 0x78, 0xFF, 0xFF, +- 0x02, 0x2A, 0x1B, 0x00, 0xD1, 0x91, 0x8D, 0xE2, 0x41, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0x21, 0x60, +- 0xA0, 0x63, 0xFD, 0xB4, 0x31, 0xFB, 0xA3, 0xD3, 0xB5, 0x60, 0x58, 0x4D, 0xE3, 0x78, 0xFF, 0xFF, +- 0x02, 0x63, 0x60, 0x5C, 0x0D, 0xF2, 0x47, 0xFD, 0xFF, 0xB5, 0x60, 0x47, 0xD0, 0x80, 0xDC, 0x84, +- 0x1F, 0x03, 0x60, 0x47, 0xB4, 0x84, 0x0D, 0xFA, 0x1B, 0x00, 0x08, 0x2A, 0x07, 0x00, 0x42, 0x64, +- 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xF7, 0xB4, 0x31, 0xFB, 0x12, 0x00, 0x10, 0x2A, 0x09, 0x00, +- 0x43, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xEF, 0xB4, 0x31, 0xFB, 0xBD, 0x60, 0xEB, 0x78, +- 0xFF, 0xFF, 0x44, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xDF, 0xB4, 0x31, 0xFB, 0x00, 0x00, +- 0x2A, 0x64, 0x3B, 0xDB, 0xB5, 0x60, 0xA2, 0x64, 0x40, 0x40, 0xBA, 0x60, 0x4F, 0x78, 0xFF, 0xFF, +- 0x12, 0x60, 0xCC, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x02, 0xB5, 0x04, 0xB5, 0x04, 0x03, 0x03, 0x03, +- 0xBE, 0x60, 0xF7, 0x78, 0xFF, 0xFF, 0xEB, 0x60, 0x58, 0x4E, 0x24, 0x78, 0xFF, 0xFF, 0x31, 0x40, +- 0x01, 0x2A, 0x29, 0x00, 0x9D, 0xFE, 0x27, 0x04, 0x26, 0x0A, 0x9F, 0xFE, 0x24, 0x05, 0x85, 0xFF, +- 0x20, 0x44, 0x84, 0xFF, 0x40, 0x26, 0x1F, 0x00, 0x3F, 0x40, 0x20, 0x2B, 0x1C, 0x00, 0x38, 0x69, +- 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, 0x01, 0x2A, 0x15, 0x00, 0x1F, 0x60, 0x1A, 0x64, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x65, 0xF1, 0x02, 0x60, +- 0xEE, 0x64, 0x82, 0xFB, 0xFF, 0xFF, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0x83, 0xFB, 0x04, 0x64, +- 0x84, 0xFB, 0xDF, 0xFE, 0x19, 0xFF, 0x10, 0x64, 0x3B, 0xDB, 0x66, 0xF3, 0x73, 0x45, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0x75, 0xF1, 0xC9, 0xFE, 0x64, 0x40, 0x01, 0x26, 0x3D, 0x00, +- 0x49, 0xF3, 0x3C, 0x46, 0x33, 0x18, 0xCC, 0x84, 0x49, 0xFB, 0x30, 0x02, 0xBF, 0x60, 0xAD, 0x64, +- 0x40, 0x42, 0xFC, 0xFC, 0x00, 0x64, 0x5C, 0x5C, 0x32, 0xFB, 0x82, 0xFF, 0x5C, 0x47, 0x84, 0xFF, +- 0x62, 0xFF, 0x1F, 0x60, 0x0A, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, +- 0xA2, 0xDB, 0x2A, 0xF2, 0x07, 0xF0, 0x0C, 0xB4, 0x08, 0x3A, 0x07, 0x00, 0x66, 0x41, 0x64, 0x46, +- 0x06, 0xF0, 0xFF, 0x60, 0xDF, 0x64, 0xA0, 0x84, 0x06, 0xFA, 0x23, 0xF0, 0x01, 0x64, 0xB0, 0x84, +- 0xA2, 0xDA, 0x1B, 0x60, 0xD4, 0x62, 0x1B, 0x60, 0xAC, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xCE, 0xFE, 0x06, 0x00, 0x66, 0xF3, +- 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0x12, 0x60, 0xC8, 0x63, 0xA3, 0xD3, +- 0xAD, 0x49, 0x20, 0xB5, 0x08, 0xB1, 0x23, 0x03, 0xE1, 0x81, 0x10, 0xB5, 0x95, 0x81, 0x60, 0x41, +- 0x18, 0x02, 0x12, 0x60, 0xCA, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA4, 0xDB, 0x17, 0x02, +- 0x0A, 0x64, 0xA4, 0xDB, 0x61, 0x44, 0x07, 0xB4, 0xFF, 0xFF, 0x11, 0x02, 0x08, 0xB1, 0xE1, 0x81, +- 0x95, 0x81, 0xA3, 0xD3, 0x0C, 0x03, 0x08, 0xAC, 0x01, 0xBC, 0xA3, 0xDB, 0xFF, 0xFF, 0x13, 0xFF, +- 0x06, 0x00, 0x10, 0xAC, 0xA3, 0xDB, 0x12, 0x60, 0xCA, 0x63, 0x0A, 0x7C, 0xA3, 0xD9, 0xB5, 0x60, +- 0xAF, 0x78, 0xFF, 0xFF, 0x46, 0xF3, 0x45, 0xF1, 0x05, 0x1B, 0x64, 0x44, 0x03, 0x1B, 0x0F, 0x60, +- 0x92, 0x62, 0xA2, 0xD3, 0x45, 0xFB, 0x00, 0x63, 0x46, 0xFD, 0x60, 0x41, 0x25, 0x64, 0x3B, 0xDB, +- 0x27, 0x44, 0xEF, 0xB4, 0x40, 0x47, 0x00, 0xB9, 0x71, 0x40, 0x80, 0x27, 0x01, 0x12, 0x19, 0x03, +- 0xBF, 0x60, 0x4D, 0x62, 0x84, 0xFF, 0x42, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, +- 0xA0, 0x51, 0x1F, 0x0A, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x19, 0x0A, +- 0x71, 0x40, 0x80, 0x27, 0xF7, 0x12, 0x45, 0xF3, 0x27, 0x02, 0x03, 0x18, 0xCC, 0x84, 0x45, 0xFB, +- 0xF1, 0x02, 0x06, 0x0A, 0xA0, 0x4C, 0xFB, 0xB4, 0xA0, 0x51, 0xA7, 0x60, 0xDF, 0x78, 0xFF, 0xFF, +- 0x84, 0xFF, 0xBF, 0x60, 0x2A, 0x64, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, +- 0xA0, 0x51, 0xAF, 0x60, 0x19, 0x78, 0xFF, 0xFF, 0x3C, 0x44, 0xAC, 0x80, 0x32, 0xF1, 0x12, 0x03, +- 0x64, 0x40, 0x07, 0x22, 0x0F, 0x00, 0xA7, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0xA0, 0x4C, 0x1C, 0xBC, +- 0xDF, 0xB4, 0xA0, 0x51, 0xF1, 0x01, 0x06, 0x00, 0x28, 0x64, 0x3A, 0xDB, 0xA0, 0x4C, 0x30, 0xBC, +- 0xF3, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x28, 0x64, 0x3B, 0xDB, 0x0F, 0x60, +- 0x94, 0x62, 0xA2, 0xD3, 0x32, 0x40, 0x02, 0x27, 0x16, 0x00, 0x46, 0xFB, 0x14, 0x18, 0xBF, 0x60, +- 0x9B, 0x64, 0x84, 0xFF, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xF7, 0xB4, 0xA0, 0x51, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x46, 0xF3, 0xCA, 0x0A, 0xDC, 0x02, +- 0xCC, 0x84, 0x46, 0xFB, 0xF5, 0x02, 0x84, 0xFF, 0xBF, 0x60, 0xAD, 0x64, 0x40, 0x42, 0x82, 0xFF, +- 0x27, 0x44, 0x08, 0xBC, 0x40, 0x47, 0xBB, 0xE1, 0x04, 0x00, 0x3A, 0xE1, 0x31, 0x40, 0x01, 0x26, +- 0xBB, 0xE1, 0xA7, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0x24, 0xE2, 0x2D, 0xF3, 0x2C, 0xF3, 0x00, 0xBD, +- 0xCC, 0x84, 0x08, 0x03, 0x2C, 0xFB, 0x06, 0x02, 0x65, 0x44, 0x2C, 0xFB, 0x8A, 0xFF, 0x80, 0x60, +- 0x00, 0x75, 0x88, 0xFF, 0xD2, 0xF3, 0x31, 0x40, 0x01, 0x2A, 0x44, 0x00, 0x60, 0x43, 0x04, 0xB0, +- 0x02, 0xB0, 0x08, 0x24, 0x16, 0x02, 0x29, 0x44, 0xFF, 0xFF, 0x00, 0xA8, 0xCC, 0x81, 0x0E, 0x03, +- 0x41, 0x49, 0x37, 0x02, 0x63, 0x40, 0x08, 0x2A, 0x09, 0x00, 0xF7, 0xB3, 0x25, 0x60, 0x1C, 0x7C, +- 0xA4, 0xD1, 0xAD, 0x4F, 0xFD, 0xB4, 0xA0, 0x5D, 0x44, 0x49, 0x2B, 0x00, 0x63, 0x40, 0x02, 0x2A, +- 0x14, 0x00, 0x25, 0x60, 0x1E, 0x64, 0xA0, 0xD3, 0x25, 0x60, 0x1A, 0x7C, 0xA4, 0xDB, 0x40, 0x49, +- 0x25, 0x60, 0x20, 0x64, 0xA0, 0xD3, 0x25, 0x60, 0x1C, 0x7C, 0xA4, 0xDB, 0x0C, 0xBB, 0xFD, 0xB3, +- 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x14, 0x00, 0x25, 0x60, 0x22, 0x64, 0xA0, 0xD3, +- 0x25, 0x60, 0x1A, 0x7C, 0x0E, 0x18, 0xA4, 0xDB, 0x40, 0x49, 0x25, 0x60, 0x24, 0x64, 0xA0, 0xD3, +- 0x25, 0x60, 0x1C, 0x7C, 0xA4, 0xDB, 0x08, 0xBB, 0xFB, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, +- 0xA0, 0x5D, 0xD2, 0xFD, 0x01, 0x60, 0x0C, 0x61, 0xA1, 0xD3, 0x61, 0x43, 0x17, 0x18, 0x58, 0xD3, +- 0x62, 0x41, 0x03, 0x18, 0xCC, 0x84, 0xA1, 0xDB, 0x11, 0x00, 0x49, 0xD3, 0xA3, 0xDB, 0x06, 0xA1, +- 0xA1, 0xD3, 0x59, 0xD1, 0x60, 0x45, 0xA5, 0xD3, 0x59, 0xD1, 0xB0, 0x84, 0xA5, 0xDB, 0x64, 0x44, +- 0x06, 0x36, 0xCD, 0xFE, 0x07, 0x36, 0xD6, 0xFE, 0xE5, 0x01, 0x23, 0x46, 0xB5, 0x60, 0xAF, 0x78, +- 0xFF, 0xFF, 0x46, 0x43, 0x1C, 0x60, 0x0A, 0x61, 0xA1, 0xD3, 0x59, 0xD1, 0x06, 0x1B, 0x59, 0xD3, +- 0x59, 0xD1, 0x03, 0x1B, 0x59, 0xD3, 0x59, 0xD1, 0xF0, 0x18, 0x00, 0x63, 0x49, 0xDD, 0x60, 0x40, +- 0x02, 0x36, 0x11, 0x00, 0x03, 0x36, 0x32, 0x00, 0x01, 0x36, 0x08, 0x00, 0x05, 0x3A, 0xEA, 0x01, +- 0xA4, 0xD3, 0x5A, 0xD3, 0x9C, 0x85, 0xA4, 0x84, 0xA2, 0xDB, 0xE4, 0x01, 0x01, 0x60, 0x0C, 0x61, +- 0x00, 0x64, 0xA1, 0xDB, 0xDF, 0x01, 0xC0, 0x60, 0x4F, 0x64, 0x40, 0x45, 0x22, 0x00, 0x01, 0x60, +- 0x0C, 0x66, 0xA6, 0xD3, 0x04, 0xA1, 0x60, 0x43, 0xA1, 0xD3, 0xC9, 0x81, 0x60, 0x45, 0x00, 0xBB, +- 0xA1, 0xDB, 0xBE, 0xD3, 0x09, 0x03, 0xD4, 0x84, 0x9C, 0x84, 0xDC, 0x84, 0xFF, 0xFF, 0x04, 0x0E, +- 0xA3, 0xD1, 0x63, 0x46, 0x64, 0x43, 0xF2, 0x01, 0x9C, 0x84, 0xDC, 0x85, 0x49, 0xDD, 0x61, 0x44, +- 0x00, 0xBB, 0xA6, 0xDB, 0x02, 0x03, 0x65, 0x44, 0xBE, 0xDB, 0xBC, 0x01, 0xC0, 0x60, 0x2A, 0x64, +- 0x40, 0x45, 0x01, 0x60, 0x0C, 0x66, 0xA6, 0xD3, 0xFF, 0xFF, 0xD0, 0x80, 0x0F, 0x18, 0x02, 0x03, +- 0x60, 0x46, 0xF9, 0x01, 0x58, 0xD3, 0xA4, 0xD3, 0x60, 0x45, 0x00, 0x63, 0xA4, 0xDD, 0x05, 0x18, +- 0x58, 0xD3, 0xFF, 0xFF, 0xC4, 0x83, 0xA2, 0xDD, 0xCA, 0x84, 0xA6, 0xDB, 0x25, 0x58, 0x64, 0x41, +- 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x06, 0x02, 0x40, 0xFF, 0x42, 0xFF, 0x43, 0xFF, 0x44, 0xFF, +- 0x45, 0xFF, 0xA1, 0xFF, 0x88, 0xFF, 0x85, 0xFF, 0x21, 0xE1, 0x5C, 0x40, 0xC0, 0x60, 0x9A, 0x78, +- 0xFF, 0xFF, 0x43, 0xFF, 0x39, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x84, 0x3E, 0xFB, 0x01, 0xA0, 0x4C, +- 0x3D, 0x46, 0x2A, 0xF2, 0x46, 0x4D, 0x10, 0x25, 0x0E, 0x00, 0x09, 0xE1, 0xA1, 0xFF, 0x66, 0x40, +- 0x0F, 0xF2, 0x01, 0x29, 0x02, 0x00, 0x40, 0xFF, 0x0A, 0xBC, 0xA2, 0xDA, 0x08, 0x25, 0xE9, 0x01, +- 0xCB, 0xFE, 0x5C, 0x5D, 0xE7, 0x01, 0x44, 0xFF, 0x03, 0x2B, 0x21, 0x00, 0x89, 0xF3, 0x06, 0x61, +- 0x60, 0x43, 0x66, 0x45, 0x31, 0xF0, 0x63, 0x46, 0x05, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0x30, 0xF0, +- 0x0F, 0x02, 0x63, 0x46, 0x04, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0x2F, 0xF0, 0x09, 0x02, 0x63, 0x46, +- 0x03, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0xFF, 0xFF, 0x48, 0xFE, 0x06, 0x00, +- 0xCD, 0x81, 0x02, 0xA3, 0xE7, 0x02, 0x88, 0xF1, 0x08, 0xFE, 0x64, 0x43, 0x26, 0x03, 0x31, 0xF2, +- 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, +- 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, +- 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, +- 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, +- 0xE8, 0x1B, 0x88, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x07, 0xFC, 0x3F, 0xF2, 0x09, 0x60, +- 0xB0, 0x65, 0xD4, 0x80, 0x2A, 0xF2, 0xA1, 0x05, 0x08, 0x25, 0x93, 0x01, 0x00, 0x64, 0x0D, 0x60, +- 0x2C, 0x61, 0x40, 0x4B, 0xA1, 0xDB, 0x2D, 0x46, 0x3B, 0xF2, 0x88, 0xF1, 0x87, 0xF4, 0x60, 0x40, +- 0x20, 0x2B, 0x12, 0x00, 0xD3, 0x80, 0x2C, 0xF0, 0x90, 0x03, 0x07, 0xF4, 0x64, 0x40, 0x01, 0x26, +- 0x88, 0xF5, 0xB6, 0xF4, 0x2D, 0x46, 0x04, 0x64, 0x04, 0xB3, 0x22, 0xFA, 0x04, 0x03, 0xC2, 0x60, +- 0x11, 0x78, 0xFF, 0xFF, 0x01, 0x00, 0xE0, 0x00, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, +- 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5B, 0x64, 0x44, 0xE2, 0x7F, +- 0xA0, 0x5B, 0x64, 0x47, 0x7C, 0x5F, 0xE8, 0x84, 0xE8, 0x85, 0x0C, 0x60, 0x3A, 0x64, 0x44, 0xD3, +- 0x5A, 0xD1, 0x03, 0x1B, 0xC2, 0x60, 0x04, 0x78, 0xFF, 0xFF, 0x60, 0x45, 0x64, 0x44, 0xE3, 0x7F, +- 0xA0, 0x5B, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5B, +- 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5B, 0x65, 0x40, +- 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xE9, 0x7F, +- 0xA0, 0x5B, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5B, +- 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5B, 0x64, 0x47, +- 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5B, 0x65, 0x44, 0xD8, 0x84, +- 0x08, 0x25, 0x78, 0x00, 0x60, 0x7F, 0xA0, 0x5B, 0x80, 0x60, 0x00, 0xEB, 0xA0, 0x60, 0x00, 0xEB, +- 0xD1, 0x60, 0x00, 0xEB, 0x3F, 0xF2, 0x04, 0x65, 0xC4, 0x83, 0x0A, 0xE1, 0xB3, 0xFF, 0x9A, 0xFF, +- 0xCB, 0x83, 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, 0x0E, 0xA3, 0xAB, 0x84, 0xF2, 0xA3, 0xA1, 0xFF, +- 0x08, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0x02, 0x62, 0xC9, 0x81, 0xAB, 0x84, 0xA1, 0xFF, 0x01, 0x00, +- 0xA2, 0xDC, 0x7A, 0xD4, 0xFD, 0x1C, 0xA2, 0xDC, 0x08, 0x25, 0x54, 0x00, 0xF2, 0x1D, 0x7C, 0xA8, +- 0xD9, 0x81, 0xEF, 0x03, 0xFF, 0xB1, 0x09, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, 0x5A, 0xD2, +- 0x89, 0xFF, 0x80, 0x4F, 0x6F, 0x44, 0xA2, 0xDA, 0x88, 0xFF, 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, +- 0x3D, 0x46, 0x08, 0x25, 0x3F, 0x00, 0x40, 0xFF, 0x0F, 0xF0, 0x0A, 0x64, 0xB0, 0x84, 0x18, 0x14, +- 0xF7, 0xB4, 0xA2, 0xDA, 0x0D, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, +- 0x0C, 0x00, 0xD1, 0xF5, 0xD0, 0xF4, 0x0D, 0x60, 0x2C, 0x61, 0x59, 0xD1, 0x37, 0xF8, 0x05, 0x64, +- 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, 0xFC, 0x02, 0x2D, 0x46, 0xC0, 0x60, 0xB0, 0x78, 0xFF, 0xFF, +- 0xA2, 0xDA, 0x2D, 0x46, 0x3B, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x20, 0x2B, 0x18, 0x00, 0xD1, 0xF5, +- 0xB7, 0xF0, 0x2A, 0x44, 0xA4, 0x84, 0xFF, 0xFF, 0x2F, 0x26, 0x10, 0x00, 0x2D, 0x46, 0x64, 0x44, +- 0x3A, 0xF0, 0xBC, 0xF0, 0x64, 0x5F, 0x3D, 0xF0, 0x07, 0xF4, 0xD0, 0xF4, 0xFF, 0xFF, 0x08, 0xA3, +- 0x5B, 0xD8, 0x65, 0x5C, 0x5B, 0xD8, 0x5B, 0xDA, 0x2D, 0x46, 0x01, 0x00, 0x2D, 0x46, 0xC0, 0x60, +- 0xB0, 0x78, 0xFF, 0xFF, 0x98, 0xFF, 0x43, 0xFF, 0x40, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, 0x2D, 0x46, +- 0x0D, 0x60, 0x2C, 0x61, 0xA1, 0xD3, 0x2D, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x0A, 0x00, 0xD1, 0xF5, +- 0xD0, 0xF4, 0x59, 0xD1, 0x37, 0xF8, 0x05, 0x64, 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, 0xFC, 0x02, +- 0x2D, 0x46, 0xC0, 0x60, 0x9A, 0x78, 0xFF, 0xFF, 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, 0x3D, 0x46, +- 0x08, 0x25, 0xE0, 0x01, 0x0F, 0xF2, 0x40, 0xFF, 0x02, 0xBC, 0xA2, 0xDA, 0xC0, 0x60, 0xB0, 0x78, +- 0xFF, 0xFF, 0x00, 0x64, 0x0D, 0x60, 0x2C, 0x62, 0xA2, 0xDB, 0x04, 0x64, 0x22, 0xFA, 0x87, 0xF4, +- 0x88, 0xF1, 0xFF, 0xFF, 0xD3, 0x80, 0x3B, 0xF2, 0xE7, 0x03, 0x60, 0x47, 0xC0, 0xB7, 0x02, 0xFE, +- 0xF0, 0x84, 0xF0, 0x84, 0xF0, 0x84, 0x00, 0xA8, 0x40, 0x4A, 0x16, 0x03, 0xE0, 0x81, 0x61, 0x43, +- 0x42, 0xFE, 0x00, 0x64, 0xF0, 0x84, 0xFE, 0x1F, 0x40, 0x4A, 0xE1, 0x84, 0xE0, 0x84, 0x2D, 0x46, +- 0x07, 0xF4, 0xE0, 0x81, 0x37, 0xF0, 0x2A, 0x47, 0x0C, 0x60, 0x7A, 0x63, 0xA0, 0x84, 0x47, 0x9C, +- 0x10, 0x03, 0x7C, 0x44, 0xA0, 0x63, 0x11, 0x00, 0x20, 0x64, 0x40, 0x4A, 0x63, 0x46, 0x37, 0xF0, +- 0x66, 0x44, 0x64, 0x40, 0x80, 0x2B, 0x05, 0x00, 0x00, 0x60, 0x70, 0x7C, 0x00, 0x60, 0x90, 0x63, +- 0x04, 0x00, 0x2D, 0x46, 0xC2, 0x60, 0x04, 0x78, 0xFF, 0xFF, 0x2D, 0x46, 0xCE, 0xFB, 0xCF, 0xF9, +- 0xD0, 0xFD, 0x07, 0xF2, 0xD1, 0xFB, 0x60, 0x46, 0x37, 0xF0, 0x2A, 0x44, 0x0D, 0x60, 0x2C, 0x62, +- 0x5A, 0xD9, 0x00, 0x65, 0x45, 0x4B, 0xA0, 0x84, 0xFF, 0xFF, 0x3F, 0x22, 0x05, 0x00, 0x90, 0x84, +- 0x37, 0xFA, 0x01, 0x64, 0x40, 0x4B, 0x21, 0x00, 0xAD, 0x46, 0x0A, 0xA3, 0x3D, 0xF2, 0xAD, 0x46, +- 0xA3, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3C, 0xF2, 0xAD, 0x46, 0x02, 0x03, 0x16, 0x07, 0x14, 0x04, +- 0x5B, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3B, 0xF2, 0x03, 0x03, 0xAD, 0x46, 0x0E, 0x07, 0x0C, 0x04, +- 0x3A, 0xF0, 0xAD, 0x46, 0x5B, 0xD0, 0x64, 0x5F, 0xD0, 0x80, 0x2B, 0x44, 0x18, 0x07, 0x04, 0x03, +- 0xD0, 0x84, 0x10, 0xA4, 0xFF, 0xFF, 0x13, 0x07, 0x7F, 0x01, 0x01, 0x64, 0x0D, 0x60, 0x2C, 0x62, +- 0xA2, 0xDB, 0x2D, 0x46, 0x0D, 0x60, 0x3C, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, +- 0xC2, 0x60, 0xAA, 0x78, 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x53, 0x01, 0x2D, 0x46, +- 0x0D, 0x60, 0x3C, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC3, 0x60, 0x33, 0x78, +- 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x45, 0x01, 0x00, 0x60, 0x0F, 0x64, 0xC1, 0x60, +- 0x70, 0x78, 0xFF, 0xFF, 0x07, 0xF4, 0x66, 0x41, 0x03, 0xF2, 0x04, 0xF2, 0x40, 0x42, 0x05, 0xF2, +- 0x40, 0x43, 0x40, 0x44, 0x61, 0x46, 0x3C, 0xF2, 0x3D, 0xF2, 0x40, 0x40, 0x40, 0x41, 0x0D, 0x60, +- 0x70, 0x65, 0x00, 0x61, 0xCF, 0xF1, 0xCE, 0xF5, 0x44, 0x4C, 0x2C, 0x5C, 0xE9, 0x80, 0x00, 0x64, +- 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x24, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x20, 0x44, 0x40, 0x80, 0xDB, 0x83, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x21, 0x44, 0x40, 0x81, 0xDB, 0x83, 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x22, 0x44, 0x40, 0x82, 0xDB, 0x83, 0xBD, 0xD2, 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x23, 0x44, 0x40, 0x83, 0xF2, 0xA3, 0xBD, 0xD2, 0x23, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x24, 0x44, 0xC0, 0x9C, 0x41, 0x84, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, 0x0D, 0x60, 0x2E, 0x61, +- 0x05, 0x64, 0xD0, 0xF4, 0xD1, 0xF5, 0xFE, 0xA3, 0x5B, 0xD0, 0xCC, 0x84, 0x59, 0xD9, 0xFC, 0x02, +- 0xD0, 0xF3, 0xD1, 0xF5, 0x60, 0x42, 0x20, 0x44, 0xA2, 0xDA, 0x21, 0x44, 0x5A, 0xDA, 0x22, 0x44, +- 0x5A, 0xDA, 0x23, 0x44, 0x5A, 0xDA, 0x24, 0x44, 0x5A, 0xDA, 0x61, 0x46, 0x0D, 0x60, 0x3C, 0x62, +- 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x41, 0xD0, 0xF3, 0xD1, 0xF5, 0xA0, 0xD2, 0x5A, 0xD0, +- 0x40, 0x40, 0x44, 0x41, 0x5A, 0xD2, 0x5A, 0xD0, 0x40, 0x42, 0x5A, 0xD0, 0x44, 0x43, 0x61, 0x46, +- 0xBA, 0xF0, 0x3B, 0xF2, 0x44, 0x44, 0x65, 0x5F, 0x40, 0x85, 0xCF, 0xF4, 0xCE, 0xF5, 0x43, 0x4C, +- 0x0D, 0x60, 0x70, 0x65, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x20, 0x44, +- 0x40, 0x80, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x21, 0x44, 0x40, 0x81, +- 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x22, 0x44, 0x40, 0x82, 0xBD, 0xD2, +- 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x23, 0x44, 0x40, 0x83, 0xBD, 0xD2, 0x23, 0x5C, +- 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x24, 0x44, 0x40, 0x84, 0xBD, 0xD2, 0x24, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x25, 0x44, 0x40, 0x85, 0x61, 0x46, 0x3A, 0xF0, 0xFF, 0xFF, 0x64, 0x44, +- 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5B, 0x64, 0x44, 0xE2, 0x7F, +- 0xA0, 0x5B, 0x64, 0x47, 0xCE, 0xF5, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, +- 0x20, 0x5C, 0x40, 0x80, 0x20, 0x44, 0xE4, 0x7F, 0xA0, 0x5B, 0x20, 0x47, 0xE5, 0x7F, 0xA0, 0x5B, +- 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x21, 0x5C, 0x40, 0x81, 0x21, 0x44, +- 0xE6, 0x7F, 0xA0, 0x5B, 0x21, 0x47, 0xE7, 0x7F, 0xA0, 0x5B, 0x21, 0x44, 0xE8, 0x80, 0xF8, 0x84, +- 0x22, 0x5C, 0x40, 0x82, 0x22, 0x44, 0xE8, 0x7F, 0xA0, 0x5B, 0x22, 0x47, 0xE9, 0x7F, 0xA0, 0x5B, +- 0x22, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x23, 0x5C, 0x40, 0x83, 0x23, 0x44, 0xEA, 0x7F, 0xA0, 0x5B, +- 0x23, 0x47, 0xEB, 0x7F, 0xA0, 0x5B, 0x23, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x24, 0x5C, 0x40, 0x84, +- 0x24, 0x44, 0xEC, 0x7F, 0xA0, 0x5B, 0x24, 0x47, 0xED, 0x7F, 0xA0, 0x5B, 0x24, 0x44, 0xE8, 0x80, +- 0xF8, 0x84, 0x25, 0x5C, 0x40, 0x85, 0x25, 0x44, 0xEE, 0x7F, 0xA0, 0x5B, 0x25, 0x47, 0xEF, 0x7F, +- 0xA0, 0x5B, 0x2C, 0x43, 0xA3, 0xD2, 0x25, 0x5C, 0x90, 0x81, 0xE9, 0x84, 0xE3, 0x7F, 0xA0, 0x5B, +- 0x0D, 0x60, 0x3C, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0xF3, 0x5A, 0xD3, 0x40, 0x48, +- 0x5A, 0xD3, 0x40, 0x49, 0x40, 0x4A, 0x00, 0x60, 0x70, 0x7C, 0x44, 0x4D, 0x45, 0xF2, 0x46, 0xF2, +- 0x40, 0x47, 0x40, 0x46, 0x0D, 0x60, 0x70, 0x65, 0x00, 0x61, 0x2D, 0x5C, 0xE9, 0x80, 0x00, 0x64, +- 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x26, 0x44, 0x40, 0x86, 0xDB, 0x83, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x27, 0x44, 0x40, 0x87, 0xDB, 0x83, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x28, 0x44, 0x40, 0x88, 0xDB, 0x83, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x29, 0x44, 0x40, 0x89, 0xF2, 0xA3, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x2A, 0x44, 0xC0, 0x9C, 0x41, 0x8A, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, 0x26, 0x44, 0x40, 0xFA, +- 0x27, 0x44, 0x41, 0xFA, 0x28, 0x44, 0x42, 0xFA, 0x29, 0x44, 0x43, 0xFA, 0x2A, 0x44, 0x44, 0xFA, +- 0x0D, 0x60, 0x3E, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x80, 0x7C, 0x44, 0x4D, +- 0x2D, 0x42, 0xA2, 0xD2, 0x5A, 0xD0, 0x40, 0x46, 0x44, 0x47, 0x5A, 0xD2, 0x5A, 0xD0, 0x40, 0x48, +- 0x5A, 0xD0, 0x44, 0x49, 0x47, 0xF2, 0x44, 0x4A, 0x40, 0x8B, 0x60, 0x5C, 0x64, 0x47, 0xE0, 0x7F, +- 0xA0, 0x5A, 0xFF, 0xB4, 0x20, 0xBC, 0x7F, 0xB4, 0xE1, 0x7F, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, +- 0xA0, 0x5A, 0x00, 0x60, 0x70, 0x63, 0x0D, 0x60, 0x70, 0x65, 0xBD, 0xD2, 0x2B, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x26, 0x44, 0x40, 0x86, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x27, 0x44, 0x40, 0x87, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x28, 0x44, 0x40, 0x88, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x29, 0x44, +- 0x40, 0x89, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2A, 0x44, 0x40, 0x8A, +- 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2B, 0x44, 0x40, 0x8B, 0xBD, 0xD2, +- 0x2B, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x26, 0x5C, 0x40, 0x86, 0x26, 0x44, 0xE4, 0x7F, +- 0xA0, 0x5A, 0x26, 0x47, 0xE5, 0x7F, 0xA0, 0x5A, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x84, 0xE8, 0x80, +- 0xF8, 0x84, 0x27, 0x5C, 0x40, 0x87, 0x27, 0x44, 0xE6, 0x7F, 0xA0, 0x5A, 0x27, 0x47, 0xE7, 0x7F, +- 0xA0, 0x5A, 0x27, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x28, 0x5C, 0x40, 0x88, 0x28, 0x44, 0xE8, 0x7F, +- 0xA0, 0x5A, 0x28, 0x47, 0xE9, 0x7F, 0xA0, 0x5A, 0x28, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x29, 0x5C, +- 0x40, 0x89, 0x29, 0x44, 0xEA, 0x7F, 0xA0, 0x5A, 0x29, 0x47, 0xEB, 0x7F, 0xA0, 0x5A, 0x29, 0x44, +- 0xE8, 0x80, 0xF8, 0x84, 0x2A, 0x5C, 0x40, 0x8A, 0x2A, 0x44, 0xEC, 0x7F, 0xA0, 0x5A, 0x2A, 0x47, +- 0xED, 0x7F, 0xA0, 0x5A, 0x2A, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x2B, 0x5C, 0x40, 0x8B, 0x2B, 0x44, +- 0xEE, 0x7F, 0xA0, 0x5A, 0x2B, 0x47, 0xEF, 0x7F, 0xA0, 0x5A, 0x38, 0xF0, 0x2B, 0x44, 0x90, 0x84, +- 0xE8, 0x84, 0xE3, 0x7F, 0xA0, 0x5A, 0x0D, 0x60, 0x3E, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x42, 0xFF, 0x40, 0xFF, 0xDD, 0xFE, 0xAD, 0x4F, 0x00, 0x7F, 0x01, 0xBC, 0xA0, 0x5D, 0x00, 0xEE, +- 0x19, 0x61, 0xCD, 0x81, 0xFF, 0xFF, 0xFD, 0x02, 0x43, 0x45, 0x20, 0x44, 0x60, 0xBC, 0x40, 0x40, +- 0x02, 0x60, 0xEE, 0x63, 0x65, 0xF3, 0x82, 0xFD, 0x40, 0x7F, 0x83, 0xFB, 0x05, 0x64, 0x84, 0xFB, +- 0xDF, 0xFE, 0x19, 0xFF, 0xC5, 0x60, 0x6D, 0x64, 0x3F, 0x40, 0x01, 0x2B, 0x02, 0x00, 0xC5, 0x60, +- 0x6D, 0x64, 0x85, 0xFB, 0xC0, 0x60, 0x9A, 0x78, 0xFF, 0xFF, 0x04, 0xEE, 0xAD, 0x4F, 0x00, 0x7F, +- 0x01, 0xBC, 0xA0, 0x5D, 0x19, 0x61, 0xCD, 0x81, 0xFF, 0xFF, 0xFD, 0x02, 0xAD, 0x4F, 0x00, 0x7F, +- 0x01, 0xBC, 0xA0, 0x5D, 0x00, 0xEE, 0x15, 0x60, 0xA2, 0xE7, 0x1C, 0x60, 0x68, 0x63, 0x1C, 0x60, +- 0xDC, 0x65, 0xDF, 0xFE, 0x80, 0xE1, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, +- 0x00, 0x7F, 0x60, 0x4A, 0xD7, 0x80, 0xA1, 0xFF, 0xFF, 0xFF, 0xF5, 0x02, 0x1C, 0x60, 0xDC, 0x63, +- 0x1D, 0x60, 0xDE, 0x65, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, 0x00, 0x7F, +- 0x60, 0x4A, 0xD7, 0x80, 0xA1, 0xFF, 0xFF, 0xFF, 0xF5, 0x02, 0x3F, 0x40, 0x20, 0x2B, 0x00, 0x00, +- 0x01, 0x68, 0xFF, 0x6A, 0xBF, 0xFE, 0xC6, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x3F, 0x40, 0x20, 0x2B, +- 0xAD, 0x00, 0x01, 0x16, 0xFE, 0x01, 0x38, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x2A, +- 0xA5, 0x00, 0x1F, 0x60, 0x1A, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, +- 0xA2, 0xDB, 0x65, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x9C, 0x01, 0x00, 0x65, 0xF1, 0xDD, 0xFE, +- 0xAD, 0x4F, 0x00, 0x7F, 0x01, 0xBC, 0xA0, 0x5D, 0x00, 0xEE, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, +- 0x40, 0x40, 0x02, 0x60, 0xEE, 0x64, 0x82, 0xFB, 0x83, 0xF9, 0x05, 0x64, 0x84, 0xFB, 0xDF, 0xFE, +- 0x19, 0xFF, 0x83, 0x00, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x43, 0x45, 0xA4, 0xD1, 0xDA, 0x83, +- 0xC3, 0x85, 0x80, 0xE1, 0xDF, 0xFE, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, +- 0x00, 0x7F, 0x60, 0x4A, 0xD7, 0x80, 0xA1, 0xFF, 0xF6, 0x02, 0xBF, 0xFE, 0x6E, 0x00, 0x3F, 0x40, +- 0x40, 0x26, 0x13, 0x00, 0x0B, 0x60, 0xF8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x10, 0x64, 0x90, 0x84, +- 0xA0, 0x50, 0xF8, 0xA2, 0xA2, 0xD1, 0x0A, 0x60, 0x19, 0x64, 0x90, 0x84, 0xA0, 0x52, 0x06, 0xA2, +- 0xA2, 0xD1, 0x46, 0x60, 0x09, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xAD, 0x4F, 0xFE, 0xB4, 0xA0, 0x5D, +- 0xAD, 0x4F, 0xFD, 0xB4, 0xA0, 0x5D, 0x02, 0xEE, 0xBD, 0xFE, 0x50, 0x00, 0x80, 0xE1, 0x01, 0x16, +- 0xFE, 0x01, 0x64, 0x48, 0x92, 0x6A, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x40, 0x1F, 0x60, 0x08, 0x64, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x3F, 0x00, 0x80, 0xE1, +- 0x01, 0x16, 0xFE, 0x01, 0x01, 0x68, 0xA7, 0x6A, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x40, 0x36, 0x00, +- 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x80, 0xE1, 0x64, 0x46, 0x01, 0x16, 0xFE, 0x01, 0x21, 0x69, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x5E, 0x01, 0x16, 0xFE, 0x01, 0x22, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x68, 0x5F, 0x26, 0xFA, 0x1C, 0xF2, 0x01, 0x16, 0xFE, 0x01, 0x3A, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x68, 0x5F, 0x27, 0xFA, 0x1B, 0x00, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x43, 0x45, 0xBE, 0xD5, +- 0xA4, 0xD2, 0x5A, 0x86, 0xEF, 0xA0, 0x11, 0x61, 0x01, 0x06, 0x60, 0x41, 0x1C, 0x60, 0x46, 0x63, +- 0x80, 0xE1, 0xBD, 0xD3, 0x26, 0x42, 0x01, 0x16, 0xFE, 0x01, 0x60, 0x49, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x68, 0x44, 0xCD, 0x81, 0xA2, 0xDA, 0x5A, 0x86, 0xF4, 0x02, 0x25, 0x43, 0x21, 0xE1, 0x00, 0x64, +- 0xBF, 0xDB, 0x20, 0x44, 0x20, 0x2A, 0x07, 0x00, 0x07, 0xB4, 0x04, 0x36, 0xC3, 0xFE, 0x06, 0x36, +- 0xCC, 0xFE, 0x07, 0x36, 0xD5, 0xFE, 0x20, 0x44, 0xD8, 0xB4, 0x40, 0x40, 0x20, 0x44, 0x40, 0x2A, +- 0x07, 0x00, 0x9F, 0xFE, 0x1E, 0x05, 0xBF, 0xB4, 0x40, 0x40, 0x85, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x1B, 0x60, 0xE6, 0x63, 0xBD, 0xD3, 0x02, 0x61, 0x17, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x02, 0x61, +- 0x13, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x02, 0x61, 0x0F, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x04, 0x61, +- 0x0B, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x06, 0x61, 0x07, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x07, 0x61, +- 0x03, 0x1B, 0xC0, 0x60, 0x9A, 0x78, 0xFF, 0xFF, 0xA3, 0xD1, 0x40, 0x44, 0x20, 0x44, 0x07, 0xB5, +- 0xD4, 0x85, 0x35, 0x80, 0x24, 0x45, 0x1C, 0x60, 0x22, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x80, 0xE1, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x64, 0x43, 0xBD, 0xD3, 0xBD, 0xD1, +- 0x40, 0x44, 0x10, 0x27, 0x10, 0x00, 0xFF, 0x60, 0x7F, 0x65, 0x15, 0x60, 0xA2, 0x64, 0x24, 0x40, +- 0x08, 0x2B, 0xA4, 0x84, 0xA0, 0x57, 0xFF, 0xFF, 0x64, 0x49, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x16, +- 0xFD, 0x01, 0x00, 0x7F, 0xA3, 0xDB, 0xA1, 0x01, 0x80, 0xE1, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, +- 0x40, 0x40, 0x64, 0x43, 0xBD, 0xD3, 0xBD, 0xD1, 0x40, 0x44, 0x10, 0x2B, 0x11, 0x00, 0xA3, 0xD3, +- 0xFF, 0xFF, 0x15, 0x60, 0x80, 0xE7, 0x24, 0x40, 0x07, 0x27, 0x02, 0x00, 0x50, 0xEC, 0x00, 0x00, +- 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x24, 0x40, 0x20, 0x2B, 0x40, 0xEC, 0x0F, 0x00, +- 0x15, 0x60, 0x22, 0x64, 0x24, 0x40, 0x08, 0x27, 0x80, 0xBC, 0xA3, 0xD3, 0xA0, 0x57, 0x60, 0x48, +- 0x64, 0x44, 0x80, 0xBC, 0xFF, 0xB4, 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x75, 0x01, +- 0xA2, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x01, 0x02, 0xA1, 0xFF, 0x86, 0xFF, 0x88, 0xFF, +- 0x5C, 0x46, 0x5C, 0x49, 0x5C, 0x40, 0xDE, 0x60, 0x58, 0x4F, 0xE2, 0x78, 0xFF, 0xFF, 0xCE, 0x60, +- 0x58, 0x4F, 0x00, 0x78, 0xFF, 0xFF, 0xE7, 0x60, 0x58, 0x4F, 0xBE, 0x78, 0xFF, 0xFF, 0xDB, 0x60, +- 0x58, 0x4F, 0x3B, 0x78, 0xFF, 0xFF, 0x13, 0xE1, 0xA3, 0xFF, 0xC7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, +- 0xDC, 0x60, 0x87, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xCE, 0x62, 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x22, 0x00, 0x75, 0xF3, 0x31, 0x40, 0x01, 0x2A, 0x1E, 0x00, +- 0xDC, 0x84, 0x01, 0xB4, 0x75, 0xFB, 0x09, 0x02, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x00, 0x60, +- 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x11, 0x00, 0x0F, 0x60, 0xDC, 0x62, 0xA2, 0xD1, +- 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x08, 0x00, 0xA9, 0xFE, 0xE4, 0x05, +- 0xAB, 0xFE, 0x07, 0x05, 0xA8, 0xFE, 0xD4, 0x05, 0xAA, 0xFE, 0xD5, 0x05, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x85, 0x3E, 0x1B, 0x60, 0xC4, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x03, 0x02, +- 0xC7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0x26, 0x45, 0xD4, 0x80, 0x0F, 0xF0, 0xF9, 0x03, 0x64, 0x44, +- 0x70, 0xB0, 0x70, 0x2A, 0x14, 0x00, 0x1F, 0x60, 0x18, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, +- 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0xA2, 0xFF, 0x8F, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0xFE, 0xA0, +- 0x8F, 0xFB, 0x01, 0x07, 0xD4, 0xFE, 0xA3, 0xFF, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x64, 0x40, +- 0x02, 0x26, 0x09, 0x00, 0x66, 0x45, 0x09, 0xF4, 0x0F, 0xF2, 0x02, 0x18, 0x65, 0x46, 0xE3, 0x1B, +- 0x00, 0x64, 0x40, 0x46, 0xCB, 0x01, 0xA2, 0xFF, 0x8F, 0xF3, 0x46, 0x46, 0xCC, 0x84, 0xFE, 0xA0, +- 0x8F, 0xFB, 0x01, 0x07, 0xD4, 0xFE, 0xA3, 0xFF, 0x0F, 0xF0, 0xA3, 0xFC, 0x64, 0x44, 0x80, 0x26, +- 0x22, 0x00, 0x98, 0xF1, 0x1E, 0x60, 0xF8, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, +- 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, +- 0x00, 0x75, 0x88, 0xFF, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, 0x07, 0x60, 0x01, 0x64, 0x04, 0x00, +- 0x02, 0x2A, 0x06, 0x00, 0x00, 0x60, 0x01, 0x64, 0x23, 0xFA, 0xCB, 0x60, 0xC8, 0x78, 0xFF, 0xFF, +- 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x08, 0x26, 0x3F, 0x00, 0x2A, 0xF2, 0x60, 0x63, 0x60, 0x40, +- 0x02, 0x2B, 0x66, 0x63, 0xBE, 0xD2, 0x69, 0xF1, 0xA3, 0xD2, 0xD0, 0x80, 0x68, 0xF1, 0x18, 0x02, +- 0xBF, 0xD2, 0xD0, 0x80, 0x67, 0xF1, 0x14, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x11, 0x02, 0x98, 0xF1, +- 0x1F, 0x60, 0x04, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, +- 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, +- 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, 0x07, 0x60, 0x02, 0x64, 0x04, 0x00, 0x02, 0x2A, 0x06, 0x00, +- 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, 0xCB, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, +- 0x60, 0x40, 0xB0, 0x3A, 0x06, 0x00, 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, 0xC8, 0x60, 0x6D, 0x78, +- 0xFF, 0xFF, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x32, 0x44, 0x01, 0x2A, 0x4A, 0x00, 0x20, 0x60, +- 0x6C, 0x63, 0xBF, 0xD3, 0x00, 0x65, 0xB4, 0x81, 0xDB, 0x83, 0x3D, 0x03, 0xBF, 0xD3, 0xA3, 0xD3, +- 0x40, 0x48, 0xBE, 0xD3, 0x40, 0x4A, 0x2E, 0xF0, 0x40, 0x4C, 0xD0, 0x80, 0x2D, 0xF0, 0x08, 0x02, +- 0x2A, 0x44, 0xD0, 0x80, 0x2C, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x2B, 0x03, +- 0x31, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x30, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x2F, 0xF0, +- 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x1E, 0x03, 0x34, 0xF0, 0x2C, 0x44, 0xD0, 0x80, +- 0x33, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x32, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, +- 0xFF, 0xFF, 0x11, 0x03, 0x38, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x37, 0xF0, 0x08, 0x02, 0x2A, 0x44, +- 0xD0, 0x80, 0x36, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x03, 0xFA, 0xA1, +- 0x06, 0xA3, 0xB7, 0x03, 0xC3, 0x01, 0x07, 0x60, 0x00, 0x64, 0x23, 0xFA, 0xCB, 0x60, 0xC8, 0x78, +- 0xFF, 0xFF, 0x2A, 0xF2, 0x0F, 0xF0, 0x60, 0x45, 0xA4, 0x36, 0x08, 0x00, 0x0C, 0xB4, 0x04, 0x36, +- 0x02, 0x00, 0x0C, 0x3A, 0x06, 0x00, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0xC9, 0x60, 0x42, 0x78, +- 0xFF, 0xFF, 0x26, 0xF2, 0x50, 0xF1, 0x60, 0x47, 0x00, 0x7E, 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, 0xC0, 0x84, 0xA2, 0xDB, 0x0F, 0xF0, +- 0x65, 0x40, 0x40, 0x2B, 0x22, 0x00, 0x32, 0x40, 0x08, 0x26, 0x1F, 0x00, 0x07, 0xF4, 0x36, 0xF2, +- 0xFF, 0xFF, 0x37, 0xB4, 0x26, 0x46, 0x19, 0x02, 0x2C, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, +- 0x11, 0x00, 0x98, 0xF1, 0x1E, 0x60, 0xFE, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, +- 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, +- 0x00, 0x75, 0x88, 0xFF, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x64, 0x40, 0x60, 0x26, +- 0x03, 0x00, 0xC9, 0x60, 0x1A, 0x78, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x3A, 0xF3, 0x01, 0x98, 0xF1, +- 0x1E, 0x60, 0xF2, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, +- 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, +- 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3B, 0x12, 0x00, 0x98, 0xF1, 0x1F, 0x60, 0x00, 0x64, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, +- 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x13, 0x00, 0x02, 0x3B, +- 0x11, 0x00, 0x98, 0xF1, 0x1F, 0x60, 0x02, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, +- 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, +- 0x00, 0x75, 0x88, 0xFF, 0x2A, 0xF2, 0x28, 0x41, 0x40, 0xA8, 0x01, 0xB1, 0x02, 0x02, 0x5F, 0x02, +- 0x89, 0x00, 0x60, 0x40, 0x08, 0x2A, 0x2B, 0x00, 0x98, 0xF1, 0x1E, 0x60, 0xF0, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, +- 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, +- 0x98, 0xF1, 0x1E, 0x60, 0xF6, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, +- 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, +- 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x0F, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x26, 0x28, 0x00, 0x32, 0x44, 0x02, 0x26, 0x25, 0x00, 0x10, 0x2B, +- 0x26, 0x00, 0x20, 0x60, 0x6C, 0x63, 0xBF, 0xD3, 0x2C, 0xF0, 0x00, 0xA8, 0x60, 0x41, 0x0D, 0x03, +- 0x50, 0xFE, 0xBD, 0xD3, 0x2D, 0xF0, 0xD0, 0x80, 0xBD, 0xD3, 0x2E, 0xF0, 0xD0, 0x80, 0xBD, 0xD3, +- 0x2C, 0xF0, 0xD0, 0x80, 0xFA, 0xA1, 0x10, 0x0C, 0xF3, 0x02, 0x50, 0xFE, 0x60, 0x60, 0x01, 0x64, +- 0xD0, 0x80, 0x2D, 0xF0, 0x1D, 0x64, 0xD0, 0x80, 0x2E, 0xF0, 0x01, 0x64, 0xD0, 0x80, 0xFF, 0xFF, +- 0x03, 0x0C, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x40, 0x2A, 0x00, 0x00, 0xCB, 0x60, +- 0xB6, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x40, 0x26, 0xFA, 0x01, 0x2A, 0xF0, 0xFF, 0xFF, 0x64, 0x40, +- 0x08, 0x2A, 0x20, 0x00, 0x32, 0x40, 0x02, 0x2A, 0x1D, 0x00, 0x03, 0x67, 0xA0, 0x84, 0x00, 0x37, +- 0x64, 0x63, 0x60, 0x40, 0x02, 0x37, 0x5E, 0x63, 0x60, 0x40, 0x01, 0x37, 0x58, 0x63, 0x60, 0x40, +- 0x03, 0x37, 0x0D, 0x00, 0xBD, 0xD2, 0x67, 0xF1, 0xBD, 0xD2, 0xD0, 0x80, 0x68, 0xF1, 0x07, 0x02, +- 0xD0, 0x80, 0xBD, 0xD2, 0x69, 0xF1, 0x03, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0xCB, 0x60, +- 0xBC, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x87, 0xF4, 0x60, 0x40, 0x03, 0x2B, 0x31, 0x00, 0x89, 0xF3, +- 0x06, 0x61, 0x60, 0x43, 0x66, 0x45, 0x31, 0xF0, 0x63, 0x46, 0x05, 0xF2, 0x65, 0x46, 0xD0, 0x80, +- 0x30, 0xF0, 0x0F, 0x02, 0x63, 0x46, 0x04, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0x2F, 0xF0, 0x09, 0x02, +- 0x63, 0x46, 0x03, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0xFF, 0xFF, 0x48, 0xFE, +- 0x06, 0x00, 0xCD, 0x81, 0x02, 0xA3, 0xE7, 0x02, 0x88, 0xF1, 0x08, 0xFE, 0x64, 0x43, 0x03, 0x03, +- 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x43, 0x43, 0x23, 0x46, 0x06, 0xF0, 0x26, 0x46, 0x07, 0x67, +- 0xA0, 0x84, 0x23, 0xFA, 0x64, 0x40, 0x02, 0x26, 0x2B, 0x00, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, +- 0x26, 0x1B, 0x31, 0xF2, 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, +- 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, +- 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, +- 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, +- 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x88, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x43, 0x43, +- 0x07, 0xFC, 0x43, 0x43, 0x02, 0xFE, 0x1D, 0xF0, 0x12, 0x60, 0xC0, 0x62, 0xC0, 0x64, 0xC0, 0x84, +- 0xA2, 0xD1, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA2, 0xDB, +- 0x63, 0x45, 0x2A, 0xF2, 0x35, 0xF0, 0x60, 0x40, 0xA4, 0x36, 0x0B, 0x00, 0x08, 0x2B, 0x0C, 0x00, +- 0x23, 0x46, 0x22, 0xF2, 0x26, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x06, 0x02, 0xCB, 0x60, 0xBC, 0x78, +- 0xFF, 0xFF, 0xCB, 0x60, 0xB6, 0x78, 0xFF, 0xFF, 0x23, 0x46, 0x1E, 0xF2, 0x26, 0x46, 0x44, 0x4C, +- 0x0F, 0x26, 0x19, 0x00, 0x00, 0xBC, 0x40, 0x45, 0x0B, 0x03, 0x00, 0x64, 0x23, 0x46, 0x1E, 0xFA, +- 0x26, 0x46, 0xA2, 0xFF, 0xB4, 0x60, 0x58, 0x4E, 0x48, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, +- 0x2A, 0xF0, 0x2C, 0x44, 0x64, 0x40, 0x04, 0x27, 0x06, 0x00, 0x23, 0x46, 0x22, 0xFA, 0x26, 0x46, +- 0xCA, 0x60, 0xB6, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x02, 0xFA, 0xA2, 0xFF, 0x16, 0xF0, 0xFF, 0xFF, +- 0x64, 0x44, 0x01, 0x26, 0xDC, 0x9C, 0x93, 0xF3, 0x2A, 0xF2, 0xDC, 0x83, 0x93, 0xFD, 0x06, 0xF4, +- 0x01, 0xF8, 0x26, 0x46, 0x60, 0x40, 0x40, 0x2B, 0x18, 0x00, 0x64, 0x44, 0x00, 0x65, 0xFF, 0xB4, +- 0xFC, 0xA4, 0x06, 0xF0, 0x03, 0x03, 0x64, 0x46, 0x0C, 0x0D, 0x02, 0x65, 0x26, 0x46, 0x00, 0xF2, +- 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x60, 0x46, 0xF9, 0x01, 0x01, 0xF2, 0xFF, 0xFF, +- 0xD4, 0x84, 0x01, 0xFA, 0x66, 0x44, 0x26, 0x46, 0x06, 0xFA, 0x06, 0xF4, 0x00, 0xF2, 0x80, 0xFC, +- 0x40, 0x45, 0xB4, 0x60, 0x58, 0x4E, 0x48, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, 0x2C, 0x44, +- 0x0F, 0x26, 0x10, 0x00, 0x23, 0x46, 0x22, 0xFA, 0x26, 0x44, 0x1E, 0xFA, 0x26, 0x46, 0x1B, 0x60, +- 0xDA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x6F, 0x00, 0xA3, 0x46, 0x22, 0xF2, 0x60, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x22, 0xFA, +- 0xA3, 0x46, 0x6C, 0x02, 0x2A, 0xF0, 0xA3, 0x46, 0x1E, 0xF2, 0xA3, 0x46, 0x00, 0xBC, 0x00, 0xF2, +- 0x01, 0x02, 0x64, 0x00, 0x44, 0x4C, 0x3F, 0xF0, 0x60, 0x43, 0x23, 0x46, 0x1E, 0xF4, 0x09, 0x60, +- 0x00, 0x65, 0x3F, 0xF2, 0x26, 0x46, 0xC0, 0x84, 0xD4, 0x80, 0x60, 0x45, 0x57, 0x07, 0x80, 0xFC, +- 0x1B, 0xF2, 0x06, 0xF2, 0x60, 0x41, 0x23, 0x46, 0x1E, 0xF4, 0x1B, 0xF0, 0x06, 0xF0, 0xC1, 0x81, +- 0x06, 0xFA, 0x05, 0xFA, 0x9B, 0xFA, 0x65, 0x44, 0x3F, 0xFA, 0x64, 0x46, 0x00, 0xFC, 0x63, 0x46, +- 0x01, 0xF2, 0x10, 0x61, 0xF2, 0xA4, 0x01, 0xFA, 0xC8, 0x83, 0x02, 0x64, 0x59, 0xD0, 0x58, 0xD8, +- 0xFD, 0x1F, 0x06, 0x45, 0x1B, 0x60, 0xDA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x25, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, +- 0x70, 0x67, 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, +- 0x80, 0xFC, 0x05, 0xFA, 0xB4, 0x60, 0x58, 0x4E, 0x48, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, +- 0x2C, 0x44, 0x04, 0x27, 0x16, 0x00, 0x23, 0x46, 0x1E, 0xF2, 0x9E, 0xFC, 0x60, 0x46, 0x46, 0x46, +- 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, 0x26, 0x46, 0x2C, 0x43, 0x2A, 0xFC, 0x06, 0xF4, +- 0x00, 0x64, 0x00, 0xFA, 0x01, 0xF0, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0x01, 0xFA, 0x26, 0x46, +- 0x1D, 0x00, 0x00, 0x66, 0x46, 0x46, 0xC7, 0x60, 0x31, 0x78, 0xFF, 0xFF, 0xA3, 0x46, 0x1E, 0xF0, +- 0x9E, 0xFC, 0x00, 0x63, 0x33, 0x85, 0xA3, 0x46, 0x0D, 0x03, 0xA3, 0x46, 0x22, 0xF2, 0x0F, 0x65, +- 0xA4, 0x85, 0xD4, 0x84, 0x22, 0xFA, 0xA3, 0x46, 0xA2, 0xFF, 0xB4, 0x60, 0x58, 0x4E, 0x48, 0x78, +- 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, 0xCB, 0x60, 0xBC, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x88, 0xF3, +- 0xFF, 0xFF, 0xD0, 0x80, 0x64, 0x46, 0x6F, 0xF2, 0x26, 0x46, 0x50, 0x03, 0x60, 0x40, 0x00, 0x36, +- 0x4D, 0x00, 0x64, 0x46, 0x0E, 0xF2, 0x26, 0x46, 0x60, 0x47, 0xFF, 0xB5, 0x27, 0xF2, 0xFF, 0xFF, +- 0xFF, 0xB4, 0xD4, 0x80, 0xFF, 0xFF, 0x42, 0x06, 0x64, 0x46, 0x6F, 0xF2, 0x26, 0x46, 0x60, 0x47, +- 0xFF, 0xB5, 0x65, 0x41, 0x0F, 0x60, 0xA2, 0x65, 0x00, 0x64, 0xE9, 0x81, 0xD8, 0x84, 0xFD, 0x02, +- 0xC8, 0x84, 0x60, 0x43, 0x44, 0xD1, 0xFF, 0xFF, 0x64, 0x47, 0xFF, 0xB5, 0x27, 0xF2, 0xFF, 0xFF, +- 0xFF, 0xB4, 0xD4, 0x80, 0x64, 0x44, 0x06, 0x06, 0x07, 0xF0, 0xFF, 0xFF, 0x64, 0x46, 0x0E, 0xFA, +- 0x26, 0x46, 0x19, 0x00, 0x00, 0x61, 0x27, 0xF0, 0x0F, 0x60, 0xA2, 0x65, 0x61, 0x43, 0x45, 0xD3, +- 0x64, 0x41, 0xFF, 0xB1, 0x61, 0x45, 0x60, 0x47, 0xFF, 0xB4, 0xDB, 0x83, 0xD4, 0x80, 0x63, 0x41, +- 0xF3, 0x02, 0xCB, 0x83, 0x63, 0x41, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x07, 0xF0, 0xFF, 0xFF, +- 0x64, 0x46, 0x0E, 0xFA, 0x26, 0x46, 0xAF, 0x84, 0xE8, 0x81, 0x05, 0x03, 0x00, 0x60, 0x01, 0x64, +- 0xCD, 0x81, 0xE0, 0x84, 0xFD, 0x02, 0x64, 0x46, 0x70, 0xFA, 0x26, 0x46, 0x2A, 0xF2, 0x32, 0xF0, +- 0x60, 0x40, 0x08, 0x2A, 0x5C, 0x00, 0x01, 0x2B, 0x2F, 0x00, 0x64, 0x40, 0x01, 0x2A, 0x2C, 0x00, +- 0x98, 0xF1, 0x1E, 0x60, 0xF0, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, +- 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, +- 0x88, 0xFF, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0x98, 0xF1, 0x1E, 0x60, 0xF6, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, +- 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, +- 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x2B, 0x00, 0x98, 0xF1, 0x1E, 0x60, 0xEE, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, +- 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, +- 0x98, 0xF1, 0x1E, 0x60, 0xF4, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, +- 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, +- 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x07, 0xF4, +- 0xFF, 0xFF, 0x22, 0xF2, 0x26, 0x46, 0x0F, 0xB4, 0xDC, 0x85, 0x98, 0xF1, 0x1E, 0x60, 0xF2, 0x64, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, +- 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, +- 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3B, +- 0x12, 0x00, 0x98, 0xF1, 0x1F, 0x60, 0x00, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, +- 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, +- 0x00, 0x75, 0x88, 0xFF, 0x13, 0x00, 0x02, 0x3B, 0x11, 0x00, 0x98, 0xF1, 0x1F, 0x60, 0x02, 0x64, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, +- 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xCC, 0x60, 0x06, 0x78, +- 0xFF, 0xFF, 0xC7, 0x60, 0x31, 0x78, 0xFF, 0xFF, 0x1B, 0x60, 0xDA, 0x64, 0x40, 0x4B, 0xF0, 0x60, +- 0x58, 0x4D, 0x75, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xC7, 0x60, 0x31, 0x78, 0xFF, 0xFF, +- 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xBE, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0x00, 0x66, 0x46, 0x46, 0xC7, 0x60, 0x31, 0x78, +- 0xFF, 0xFF, 0x2A, 0xF2, 0x58, 0x63, 0x60, 0x47, 0x01, 0x27, 0x64, 0x63, 0x25, 0x60, 0x26, 0x62, +- 0x61, 0x5C, 0xA2, 0xD9, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, 0xBD, 0xD0, 0x00, 0xF4, +- 0x04, 0xF8, 0x83, 0xFA, 0x82, 0xF8, 0xA6, 0x46, 0x02, 0xB0, 0x5E, 0x63, 0x04, 0x03, 0x64, 0x63, +- 0x03, 0xB0, 0x02, 0x3A, 0x6C, 0x63, 0x3F, 0xF2, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, +- 0xBD, 0xD0, 0xA6, 0x46, 0x07, 0xF8, 0x86, 0xFA, 0x85, 0xF8, 0x60, 0x47, 0x08, 0xFA, 0x25, 0x60, +- 0x26, 0x62, 0xA2, 0xD1, 0x26, 0x46, 0x64, 0x41, 0x2F, 0x58, 0xFF, 0xFF, 0x2A, 0xF2, 0x2C, 0xF0, +- 0x31, 0x40, 0x20, 0x26, 0x09, 0x00, 0x60, 0x40, 0xA4, 0x36, 0x21, 0x00, 0x08, 0x26, 0x07, 0x00, +- 0x7E, 0xF1, 0xCC, 0x60, 0xCF, 0x78, 0xFF, 0xFF, 0xCC, 0x60, 0xFF, 0x78, 0xFF, 0xFF, 0x64, 0x40, +- 0x01, 0x26, 0x12, 0x00, 0x3F, 0xF0, 0x32, 0x40, 0x10, 0x2A, 0x0A, 0x00, 0x64, 0x41, 0x60, 0x40, +- 0x40, 0x27, 0x06, 0x00, 0xCD, 0x81, 0xDD, 0x81, 0x03, 0x03, 0x02, 0x03, 0x01, 0x61, 0x01, 0x00, +- 0x00, 0x61, 0x60, 0x40, 0x18, 0x3A, 0x03, 0x00, 0xCD, 0x60, 0x3B, 0x78, 0xFF, 0xFF, 0x07, 0xF2, +- 0x88, 0xF1, 0x66, 0x45, 0xD0, 0x80, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x03, 0x03, 0xFF, 0xFF, +- 0x02, 0x26, 0x07, 0x00, 0xDA, 0x60, 0x58, 0x4F, 0xDB, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0x37, 0x78, +- 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xA4, 0x3A, 0x07, 0x00, 0xDD, 0x60, 0x58, 0x4F, +- 0x45, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0x37, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0xCB, 0x60, 0x58, 0x4F, +- 0xD9, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x06, 0x65, 0xD4, 0x80, 0x60, 0x43, 0x52, 0x04, 0x00, 0xF4, +- 0xAA, 0x60, 0xAA, 0x65, 0x09, 0xF2, 0x0A, 0xF0, 0xD4, 0x80, 0x03, 0x64, 0x4A, 0x02, 0xD0, 0x80, +- 0x00, 0x64, 0x0B, 0xF0, 0x46, 0x02, 0x64, 0x45, 0xD4, 0x80, 0xF8, 0x7F, 0x08, 0x02, 0x0C, 0xF0, +- 0x26, 0x46, 0x64, 0x45, 0x23, 0xF0, 0x20, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x0B, 0x00, 0xD4, 0x80, +- 0x1D, 0x60, 0x60, 0x64, 0x11, 0x02, 0x0C, 0xF0, 0x26, 0x46, 0x64, 0x45, 0x23, 0xF0, 0x40, 0x67, +- 0xB0, 0x84, 0xA2, 0xDA, 0x65, 0x44, 0x88, 0x3A, 0x2C, 0x00, 0x77, 0x37, 0x03, 0x00, 0x78, 0x37, +- 0x01, 0x00, 0x8E, 0x37, 0x00, 0x61, 0x25, 0x00, 0xD4, 0x80, 0x08, 0x65, 0x22, 0x02, 0xD7, 0x80, +- 0x01, 0x60, 0x00, 0x64, 0x0C, 0xF0, 0x1D, 0x04, 0xD0, 0x80, 0x0D, 0xF0, 0x1A, 0x02, 0x26, 0x46, +- 0x14, 0xF2, 0x01, 0x63, 0x02, 0xA8, 0x64, 0x47, 0x14, 0x03, 0x7F, 0xB4, 0xFD, 0xA0, 0x06, 0x03, +- 0x10, 0x07, 0x23, 0xF0, 0x60, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x6A, 0x00, 0xD2, 0xF3, 0xFF, 0xFF, +- 0x02, 0xBC, 0xD2, 0xFB, 0xE5, 0x60, 0x58, 0x4F, 0x94, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0x37, 0x78, +- 0xFF, 0xFF, 0x26, 0x46, 0x61, 0x40, 0x01, 0x2A, 0x12, 0x00, 0x98, 0xF1, 0x1F, 0x60, 0x06, 0x64, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, +- 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x7C, 0x00, 0xDD, 0x60, +- 0x58, 0x4F, 0x45, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0x36, 0x73, 0x00, +- 0xCD, 0x60, 0x58, 0x4F, 0x48, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0x37, 0x78, 0xFF, 0xFF, 0x60, 0x40, +- 0x0C, 0x26, 0x69, 0x00, 0x64, 0x40, 0x01, 0x2A, 0x66, 0x00, 0xB0, 0x3A, 0x05, 0x00, 0xD1, 0x60, +- 0x58, 0x4F, 0x80, 0x78, 0xFF, 0xFF, 0x5B, 0x00, 0x00, 0x3A, 0x05, 0x00, 0xD4, 0x60, 0x58, 0x4F, +- 0xF3, 0x78, 0xFF, 0xFF, 0x54, 0x00, 0x20, 0x3A, 0x05, 0x00, 0xD4, 0x60, 0x58, 0x4F, 0xF3, 0x78, +- 0xFF, 0xFF, 0x4D, 0x00, 0xC0, 0x3A, 0x05, 0x00, 0xDA, 0x60, 0x58, 0x4F, 0x48, 0x78, 0xFF, 0xFF, +- 0x46, 0x00, 0xA0, 0x3A, 0x05, 0x00, 0xDA, 0x60, 0x58, 0x4F, 0xA6, 0x78, 0xFF, 0xFF, 0x3F, 0x00, +- 0x40, 0x3A, 0x0D, 0x00, 0xE1, 0x60, 0x58, 0x4F, 0x10, 0x78, 0xFF, 0xFF, 0x38, 0x00, 0x60, 0x40, +- 0x50, 0x3A, 0x05, 0x00, 0xEA, 0x60, 0x58, 0x4F, 0xF5, 0x78, 0xFF, 0xFF, 0x30, 0x00, 0x33, 0x00, +- 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0x2A, 0xF2, 0x3B, 0xF0, 0x60, 0x40, 0x40, 0x2B, +- 0x19, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x04, 0xB4, 0xFF, 0xFF, 0x14, 0x03, 0xC0, 0x60, 0x00, 0x64, +- 0x64, 0x40, 0x20, 0x2B, 0x0F, 0x00, 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x23, 0xF2, +- 0x10, 0xBD, 0xB4, 0x9C, 0x3F, 0xF2, 0x23, 0xF8, 0xF8, 0xA4, 0x3F, 0xFA, 0x00, 0xF4, 0x60, 0x47, +- 0x08, 0xFA, 0x26, 0x46, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xBE, 0x64, 0xA2, 0xDB, 0x26, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0x0C, 0x00, 0x66, 0x44, +- 0x00, 0xA8, 0xFF, 0xFF, 0x0A, 0x03, 0x26, 0x46, 0x1B, 0x60, 0xDA, 0x64, 0x40, 0x4B, 0xF0, 0x60, +- 0x58, 0x4D, 0x75, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xCB, 0x60, 0xB9, 0x78, 0xFF, 0xFF, +- 0x14, 0xF2, 0x00, 0x7C, 0x3E, 0xF8, 0xCC, 0x84, 0xCC, 0x84, 0x19, 0x03, 0x60, 0x02, 0x11, 0xF2, +- 0x07, 0xFA, 0xAC, 0xF3, 0x19, 0xFA, 0xCD, 0x60, 0x58, 0x4E, 0xE4, 0x78, 0xFF, 0xFF, 0x1B, 0x60, +- 0xDA, 0x62, 0x1B, 0x60, 0x9A, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0xF2, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x79, 0x00, 0xA2, 0xFF, +- 0x46, 0x45, 0xB4, 0x60, 0x58, 0x4E, 0x91, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x11, 0x03, 0x7E, 0x63, +- 0x46, 0x4B, 0x25, 0x46, 0xA3, 0xD0, 0x2B, 0x46, 0xA3, 0xD8, 0xFB, 0x1F, 0x89, 0xFC, 0x8A, 0xFC, +- 0x88, 0xFC, 0x05, 0x18, 0x64, 0x46, 0x01, 0xF0, 0x10, 0x67, 0xC0, 0x84, 0x01, 0xFA, 0x08, 0xFE, +- 0x2B, 0x46, 0x46, 0x46, 0x25, 0x46, 0xCD, 0x60, 0x58, 0x4E, 0xE4, 0x78, 0xFF, 0xFF, 0x1F, 0x60, +- 0x8E, 0x62, 0xA2, 0xD3, 0x88, 0xF3, 0x00, 0xA8, 0x07, 0xFA, 0x0F, 0x03, 0x1B, 0x60, 0xDA, 0x62, +- 0x1B, 0x60, 0x94, 0x64, 0xA2, 0xDB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xF3, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x0E, 0x00, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, +- 0x88, 0x64, 0xA2, 0xDB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xF4, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x26, 0x44, 0x00, 0xA8, 0xC1, 0xFE, 0x31, 0x03, 0xD2, 0xF3, +- 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0x26, 0x46, 0x2A, 0xF2, 0x3B, 0xF0, 0x60, 0x40, 0x40, 0x2B, +- 0x18, 0x00, 0x64, 0x40, 0x20, 0x2B, 0x15, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x04, 0xB4, 0xFF, 0xFF, +- 0x10, 0x03, 0xC0, 0x67, 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x23, 0xF2, 0x10, 0xBD, +- 0xB4, 0x9C, 0x3F, 0xF2, 0x23, 0xF8, 0xF8, 0xA4, 0x3F, 0xFA, 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, +- 0x26, 0x46, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xBE, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0xF1, 0x64, 0x3B, 0x42, 0x4A, 0xDB, +- 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x2A, 0xF2, 0x82, 0x60, 0xFF, 0x65, 0xA4, 0x87, +- 0x02, 0xBF, 0x2A, 0xFA, 0x1C, 0xF2, 0x13, 0xFA, 0x32, 0xF2, 0x2C, 0xFA, 0x33, 0xF2, 0x2D, 0xFA, +- 0x34, 0xF2, 0x2E, 0xFA, 0x2F, 0xF2, 0x32, 0xFA, 0x30, 0xF2, 0x33, 0xFA, 0x31, 0xF2, 0x34, 0xFA, +- 0x67, 0xF3, 0x2F, 0xFA, 0x68, 0xF3, 0x30, 0xFA, 0x69, 0xF3, 0x31, 0xFA, 0x2E, 0x58, 0xFF, 0xFF, +- 0x0F, 0x60, 0xF8, 0x62, 0xD0, 0x60, 0x7B, 0x64, 0xA2, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x1F, 0x60, +- 0x62, 0x63, 0x20, 0x60, 0x02, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1E, 0x63, 0x1F, 0x60, 0x6C, 0x61, +- 0x20, 0x60, 0x0C, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x1F, 0x60, 0x8E, 0x63, 0x20, 0x60, +- 0x2E, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, 0x90, 0x63, 0x20, 0x60, 0x30, 0x62, 0xA2, 0xD3, +- 0xA3, 0xDB, 0x1F, 0x60, 0x9A, 0x63, 0x20, 0x60, 0x3A, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, +- 0x9C, 0x63, 0x20, 0x60, 0x3C, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, 0x9E, 0x63, 0x20, 0x60, +- 0x3E, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, 0xA0, 0x63, 0x20, 0x60, 0x40, 0x62, 0xA2, 0xD3, +- 0xA3, 0xDB, 0x1F, 0x60, 0x92, 0x63, 0x20, 0x60, 0x32, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, +- 0x94, 0x63, 0x20, 0x60, 0x34, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, 0x96, 0x63, 0x20, 0x60, +- 0x36, 0x62, 0xA2, 0xD3, 0xA3, 0xDB, 0x1F, 0x60, 0xB6, 0x63, 0xBD, 0xD1, 0xCB, 0xF9, 0x67, 0xF9, +- 0xBD, 0xD1, 0xCC, 0xF9, 0x68, 0xF9, 0xA3, 0xD1, 0xCD, 0xF9, 0x69, 0xF9, 0x01, 0x64, 0x6B, 0xFB, +- 0x1F, 0x60, 0xA8, 0x62, 0xA2, 0xD3, 0xC4, 0xFB, 0x00, 0x63, 0x4A, 0xFD, 0x5A, 0xFD, 0x6C, 0xFD, +- 0x6D, 0xFD, 0x21, 0x60, 0x82, 0x64, 0xA0, 0xD3, 0xEA, 0x60, 0x58, 0x4E, 0x78, 0x78, 0xFF, 0xFF, +- 0x21, 0x60, 0x80, 0x64, 0xA0, 0xD1, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD3, 0xFF, 0x60, 0xE7, 0x65, +- 0x32, 0x41, 0xA5, 0x81, 0xFF, 0xA0, 0xFF, 0xFF, 0x01, 0x03, 0x0B, 0x00, 0x08, 0x65, 0xB5, 0x81, +- 0x1F, 0x60, 0x96, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x02, 0x00, 0x10, 0x65, +- 0xB5, 0x81, 0x41, 0x52, 0x88, 0xF5, 0x32, 0x44, 0x10, 0xB0, 0xFF, 0xFF, 0x0B, 0x03, 0x21, 0x60, +- 0x2C, 0x62, 0xA2, 0xD3, 0x06, 0xF0, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, +- 0xB0, 0x84, 0x06, 0xFA, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD3, 0x22, 0x7C, 0xFF, 0xA0, 0xFD, 0xA0, +- 0x05, 0x06, 0x03, 0x03, 0xFE, 0xA0, 0x04, 0x7C, 0x01, 0x02, 0x36, 0xF8, 0x0E, 0xF0, 0x0F, 0x60, +- 0xA2, 0x65, 0x20, 0x60, 0x38, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xFE, 0xA0, 0x03, 0xA8, 0x11, 0x06, +- 0x5F, 0xF1, 0x06, 0x02, 0x64, 0x44, 0x08, 0x2A, 0x09, 0x00, 0x06, 0x64, 0x44, 0xD3, 0x0D, 0x00, +- 0x64, 0x44, 0x20, 0x2A, 0x03, 0x00, 0x0A, 0x64, 0x44, 0xD3, 0x07, 0x00, 0x01, 0x64, 0x44, 0xD3, +- 0x04, 0x00, 0xE8, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x00, 0x00, 0x0E, 0xFA, 0x1F, 0x60, 0x9E, 0x62, +- 0xA2, 0xD1, 0x20, 0x44, 0x20, 0xB5, 0x64, 0x41, 0x00, 0xB9, 0xD4, 0x84, 0x08, 0x28, 0x20, 0xBC, +- 0x40, 0x40, 0x11, 0x60, 0xF0, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x00, 0xB8, 0x10, 0x60, 0x0C, 0x65, +- 0x0D, 0x03, 0x11, 0x60, 0xF8, 0x63, 0xC5, 0xF3, 0xA3, 0xD1, 0xE0, 0x84, 0xC4, 0x84, 0xA0, 0xD3, +- 0xFF, 0xFF, 0x01, 0xB0, 0xFF, 0xFF, 0x02, 0x02, 0xC5, 0xF9, 0x65, 0xF9, 0xC5, 0xF3, 0x01, 0x61, +- 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0xE1, 0x81, 0xFB, 0x01, 0x9A, 0xF3, 0x61, 0x45, 0xA4, 0x80, +- 0xFF, 0xFF, 0x0B, 0x02, 0x00, 0xB8, 0x01, 0x63, 0x08, 0x03, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x24, +- 0x02, 0x00, 0xDF, 0x83, 0xFA, 0x01, 0xC5, 0xFD, 0x65, 0xFD, 0x0A, 0x64, 0x25, 0x60, 0x1E, 0x63, +- 0xA3, 0xDB, 0x01, 0x64, 0x25, 0x60, 0x20, 0x63, 0xA3, 0xDB, 0xB6, 0xF1, 0x09, 0x60, 0x2A, 0x64, +- 0xD0, 0x80, 0x03, 0x64, 0x01, 0x06, 0x06, 0x64, 0xB0, 0xFB, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xD8, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, +- 0xCF, 0x60, 0x05, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD6, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x65, 0xF1, 0x1C, 0x60, 0x00, 0x62, 0xA2, 0xD9, 0x08, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCF, 0x60, +- 0x2D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xCE, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x20, 0x44, 0x01, 0x65, 0x34, 0x80, 0x1F, 0x60, 0xA6, 0x64, 0xA0, 0xD3, +- 0xC3, 0xFB, 0x60, 0x40, 0x05, 0x3A, 0x03, 0x00, 0xEB, 0x60, 0x1A, 0x61, 0x11, 0x00, 0x04, 0x3A, +- 0x03, 0x00, 0xEB, 0x60, 0x0E, 0x61, 0x0C, 0x00, 0x03, 0x3A, 0x03, 0x00, 0xEB, 0x60, 0x02, 0x61, +- 0x07, 0x00, 0x02, 0x3A, 0x03, 0x00, 0xEA, 0x60, 0xF6, 0x61, 0x02, 0x00, 0xEA, 0x60, 0xEA, 0x61, +- 0x3E, 0x60, 0x00, 0x66, 0x01, 0x60, 0x78, 0x64, 0x0A, 0x63, 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, +- 0x00, 0x66, 0xC4, 0xF3, 0x60, 0x41, 0x00, 0xA8, 0xFA, 0xA1, 0x01, 0x03, 0xA1, 0xDB, 0x01, 0x60, +- 0x7A, 0x63, 0x16, 0x60, 0xC4, 0x61, 0xBD, 0xD3, 0xFF, 0xFF, 0x20, 0x7F, 0xA1, 0xDB, 0xBD, 0xD3, +- 0xFF, 0xFF, 0x21, 0x7F, 0x59, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0x59, 0xDB, 0x0F, 0x60, +- 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xD8, 0x62, 0x40, 0x60, +- 0x00, 0x64, 0xA2, 0xDB, 0xCF, 0x60, 0x77, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x1C, 0x60, 0x00, 0x62, 0x16, 0x60, 0xC2, 0x64, 0xA2, 0xDB, 0x20, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x2D, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCF, 0x60, 0x9C, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x65, 0xF1, 0x1C, 0x60, 0x00, 0x62, 0xA2, 0xD9, 0x08, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, +- 0x0F, 0x60, 0xD8, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCF, 0x60, 0xB3, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, +- 0x0F, 0x60, 0xCE, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x20, 0x40, 0x20, 0x2A, 0x04, 0x00, 0xEB, 0x60, 0x58, 0x4E, 0x16, 0x78, 0xFF, 0xFF, 0x0F, 0x60, +- 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x4E, 0xF3, 0xFF, 0xFF, 0x13, 0x1B, 0x1F, 0x60, 0xAE, 0x64, +- 0xA0, 0xD3, 0xC7, 0xFB, 0x1F, 0x60, 0x1E, 0x65, 0x1F, 0x60, 0xBC, 0x61, 0x1F, 0x60, 0x1C, 0x64, +- 0x20, 0x63, 0x59, 0xD1, 0x58, 0xD9, 0xA5, 0xD9, 0xDA, 0x85, 0xFB, 0x1F, 0xD0, 0x60, 0x62, 0x78, +- 0xFF, 0xFF, 0x20, 0x60, 0x40, 0x63, 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x85, 0xC7, 0x83, 0xFE, 0xA5, +- 0x89, 0xF3, 0xFF, 0xFF, 0xC4, 0x84, 0x66, 0x45, 0x60, 0x46, 0x60, 0x41, 0xBD, 0xD1, 0x03, 0xF8, +- 0xBD, 0xD1, 0x04, 0xF8, 0xA3, 0xD1, 0x05, 0xF8, 0x06, 0xF2, 0xFF, 0xFF, 0x02, 0x7E, 0x06, 0xFA, +- 0x5F, 0xF3, 0x60, 0xFB, 0x73, 0xF0, 0x63, 0xF9, 0x66, 0x43, 0x21, 0x60, 0x2C, 0x62, 0x32, 0x40, +- 0x08, 0x2A, 0x09, 0x00, 0xA2, 0xD3, 0x06, 0xF0, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, +- 0x80, 0xBF, 0xB0, 0x84, 0x06, 0xFA, 0x63, 0x44, 0x63, 0xF3, 0x60, 0x45, 0x66, 0x41, 0x65, 0x46, +- 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, +- 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x5F, 0xF3, 0x60, 0xF1, +- 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, 0x02, 0x02, 0x5F, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, +- 0xAE, 0x65, 0x63, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, +- 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x61, 0xFB, 0x6F, 0xF0, +- 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, +- 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, +- 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, +- 0x66, 0x43, 0x0C, 0xF4, 0xC5, 0xFE, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, +- 0xD8, 0x62, 0x00, 0x60, 0x30, 0x64, 0xA2, 0xDB, 0xCF, 0x60, 0xC7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x4E, 0xDF, 0x60, 0x58, 0x4F, 0x13, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, +- 0x0F, 0x4E, 0xDC, 0x60, 0x58, 0x4F, 0x6B, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x4E, 0xDB, 0x60, +- 0x58, 0x4F, 0xE8, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x4E, 0xDB, 0x60, 0x58, 0x4F, 0x42, 0x78, +- 0xFF, 0xFF, 0x0E, 0x4F, 0xD7, 0x01, 0x4E, 0xF3, 0x7E, 0xF5, 0x60, 0x40, 0xFF, 0x22, 0x0A, 0x00, +- 0x89, 0xF1, 0xCC, 0x84, 0xE0, 0x84, 0xC0, 0x86, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, +- 0x7E, 0xF5, 0x08, 0x00, 0x0F, 0x60, 0xF4, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x11, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x4E, 0xF3, 0x66, 0x40, 0xFF, 0x22, 0x05, 0x00, 0xFF, 0x22, 0x37, 0x00, +- 0xD1, 0x60, 0x30, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x6A, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x6A, 0xF3, +- 0x00, 0x65, 0xD4, 0x80, 0x4E, 0xF3, 0x0F, 0x03, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x0F, 0x60, 0xD8, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD0, 0x60, 0x9F, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, +- 0x0B, 0x04, 0x0F, 0x60, 0xD8, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD0, 0x60, 0xB3, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x00, 0x62, 0x06, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x44, 0x01, 0xB5, 0x54, 0x80, 0xDA, 0xFE, 0xBE, 0xFE, 0x88, 0xF1, +- 0x02, 0x64, 0x87, 0xF3, 0xC0, 0x83, 0x40, 0x48, 0x76, 0xFD, 0xE4, 0x60, 0x58, 0x4E, 0x9D, 0x78, +- 0xFF, 0xFF, 0x28, 0x44, 0x4C, 0x88, 0x76, 0xF3, 0x02, 0x65, 0xC4, 0x83, 0xF5, 0x02, 0xA2, 0x60, +- 0x58, 0x4E, 0x00, 0x78, 0xFF, 0xFF, 0x14, 0x60, 0xD0, 0x62, 0x14, 0x60, 0xD2, 0x64, 0xA2, 0xDB, +- 0x00, 0x64, 0x4A, 0xDB, 0x01, 0x60, 0xFE, 0x63, 0x12, 0x60, 0xCC, 0x61, 0x00, 0x64, 0x59, 0xDB, +- 0xFE, 0x1F, 0x7E, 0xF1, 0x1B, 0x60, 0x9A, 0x61, 0x64, 0x40, 0xFF, 0x26, 0x39, 0x00, 0xD1, 0x60, +- 0x58, 0x4E, 0x33, 0x78, 0xFF, 0xFF, 0x1B, 0x60, 0x88, 0x61, 0xD1, 0x60, 0x58, 0x4E, 0x33, 0x78, +- 0xFF, 0xFF, 0x1B, 0x60, 0x8E, 0x61, 0xD1, 0x60, 0x58, 0x4E, 0x33, 0x78, 0xFF, 0xFF, 0x1B, 0x60, +- 0xA0, 0x61, 0xD1, 0x60, 0x58, 0x4E, 0x33, 0x78, 0xFF, 0xFF, 0x1B, 0x60, 0xA6, 0x61, 0xD1, 0x60, +- 0x58, 0x4E, 0x33, 0x78, 0xFF, 0xFF, 0x1B, 0x60, 0xB2, 0x61, 0xD1, 0x60, 0x58, 0x4E, 0x33, 0x78, +- 0xFF, 0xFF, 0x1B, 0x60, 0xBE, 0x61, 0xD1, 0x60, 0x58, 0x4E, 0x33, 0x78, 0xFF, 0xFF, 0x1B, 0x60, +- 0xAC, 0x61, 0xD1, 0x60, 0x58, 0x4E, 0x33, 0x78, 0xFF, 0xFF, 0x1B, 0x60, 0x94, 0x61, 0xD1, 0x60, +- 0x58, 0x4E, 0x5F, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xD6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, +- 0xC5, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xA1, 0xD3, 0x0E, 0x57, 0x24, 0x00, 0x0E, 0xF2, 0x44, 0x4C, +- 0x80, 0xB0, 0x10, 0xB0, 0x0B, 0x03, 0x1B, 0x60, 0xDA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x13, 0x00, 0x12, 0x02, 0xF0, 0x37, +- 0x09, 0x00, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0x90, 0xF3, 0x02, 0x02, +- 0xCC, 0x84, 0x90, 0xFB, 0x1B, 0x60, 0xDA, 0x64, 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, 0x75, 0x78, +- 0xFF, 0xFF, 0x2C, 0x44, 0xAC, 0x86, 0x09, 0xF0, 0xD9, 0x02, 0x37, 0x58, 0xFF, 0xFF, 0xA1, 0xD3, +- 0x0E, 0x57, 0x19, 0x00, 0x0E, 0xF2, 0x44, 0x4C, 0x80, 0xB0, 0x10, 0xB0, 0x0B, 0x03, 0x1B, 0x60, +- 0xDA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x08, 0x00, 0x07, 0x02, 0x1B, 0x60, 0xDA, 0x64, 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, +- 0x75, 0x78, 0xFF, 0xFF, 0x2C, 0x44, 0xAC, 0x86, 0x09, 0xF0, 0xE4, 0x02, 0x37, 0x58, 0xFF, 0xFF, +- 0x00, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xB0, 0x64, 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, +- 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0xCD, 0xF3, +- 0x31, 0xFA, 0x67, 0xF3, 0x32, 0xFA, 0x68, 0xF3, 0x33, 0xFA, 0x69, 0xF3, 0x34, 0xFA, 0xAC, 0xF1, +- 0x19, 0xF8, 0x06, 0x63, 0x3F, 0xFC, 0x1C, 0xF2, 0x13, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x07, 0xF2, +- 0x88, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x0C, 0x03, 0x60, 0x46, 0x06, 0xF2, 0x26, 0x46, +- 0x01, 0xB0, 0xFF, 0xFF, 0x03, 0x02, 0xD3, 0x60, 0x64, 0x78, 0xFF, 0xFF, 0xD4, 0x60, 0xBA, 0x78, +- 0xFF, 0xFF, 0x00, 0xF4, 0x0A, 0xF2, 0x09, 0xF2, 0xFF, 0xA0, 0x00, 0xA0, 0x13, 0x02, 0xFF, 0xA0, +- 0x04, 0x03, 0x08, 0x03, 0xD1, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x55, 0xFB, 0xD1, 0x60, +- 0xE0, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0x32, 0x40, 0x08, 0x2A, 0x0F, 0x00, 0x55, 0xFD, 0xD1, 0x60, +- 0xE0, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x0A, 0xF2, 0x0E, 0x63, 0x01, 0xA4, 0x0A, 0xFA, +- 0x0B, 0xFC, 0x43, 0x59, 0xD4, 0x60, 0x93, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x0A, 0xF2, +- 0x0D, 0x63, 0x01, 0xA4, 0x0A, 0xFA, 0x0B, 0xFC, 0x43, 0x59, 0xD4, 0x60, 0x93, 0x78, 0xFF, 0xFF, +- 0x88, 0xF5, 0x00, 0xF2, 0x26, 0x46, 0x00, 0xA0, 0x2E, 0xF0, 0x37, 0x03, 0x66, 0x41, 0x12, 0x60, +- 0xCE, 0x65, 0x64, 0x47, 0x00, 0x7F, 0x88, 0xF1, 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, +- 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, +- 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, +- 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, +- 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, 0x87, 0xF1, 0x14, 0x60, 0xCE, 0x61, +- 0xA1, 0xD3, 0xDA, 0x81, 0xD0, 0x80, 0xDC, 0x9C, 0x05, 0x05, 0xA1, 0xD3, 0x4A, 0xD9, 0xA0, 0xDD, +- 0xDA, 0x9C, 0xA1, 0xD9, 0xD3, 0x60, 0x2D, 0x78, 0xFF, 0xFF, 0x14, 0x60, 0xCE, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0x62, 0x18, 0x14, 0x60, 0xCE, 0x64, 0x04, 0xA5, 0xA0, 0xD1, 0x72, 0x44, 0xFF, 0xB4, +- 0x64, 0x40, 0xE0, 0x22, 0x1F, 0xB4, 0x64, 0x40, 0xF8, 0x22, 0x07, 0xB4, 0x02, 0x00, 0x03, 0x04, +- 0xD0, 0x84, 0xD0, 0x80, 0xFC, 0x01, 0xE0, 0x84, 0x44, 0xD3, 0xFF, 0xFF, 0x60, 0x43, 0x66, 0x41, +- 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, +- 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, +- 0x00, 0xF8, 0x88, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, +- 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, +- 0x61, 0x46, 0x2E, 0xF0, 0x66, 0x41, 0x12, 0x60, 0xCE, 0x65, 0x64, 0x47, 0x00, 0x7F, 0x88, 0xF1, +- 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, +- 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, +- 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, +- 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, +- 0x61, 0x46, 0xD3, 0x60, 0x2D, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x02, 0x61, 0xB3, 0x60, 0x58, 0x4D, +- 0x77, 0x78, 0xFF, 0xFF, 0x87, 0xF1, 0x72, 0x44, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x04, +- 0xD0, 0x84, 0xFB, 0x01, 0xE0, 0x83, 0x88, 0xF3, 0x02, 0xA3, 0x43, 0x93, 0x66, 0x44, 0x00, 0xA8, +- 0x56, 0xFD, 0x37, 0x03, 0x00, 0x64, 0x2B, 0xFA, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, 0x66, 0x45, +- 0x63, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x85, 0xF2, 0x65, 0x46, 0x2C, 0xFA, 0x2D, 0xF8, 0xAE, 0xFA, +- 0xCB, 0xF3, 0x2F, 0xFA, 0x32, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0x33, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, +- 0x34, 0xFA, 0xAC, 0xF1, 0x19, 0xF8, 0xFF, 0x67, 0x0E, 0xFA, 0x66, 0x45, 0x63, 0x46, 0x0E, 0xF2, +- 0x65, 0x46, 0x02, 0x63, 0x00, 0x7E, 0x13, 0xFA, 0x3F, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0x88, 0xF3, +- 0x07, 0xFA, 0x66, 0x41, 0x00, 0xF4, 0x05, 0x64, 0x09, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, +- 0x8E, 0x64, 0xA2, 0xDB, 0x61, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xC1, 0xFE, 0x56, 0xF3, 0xA3, 0xFF, 0x60, 0x43, 0xE4, 0x60, 0x58, 0x4E, 0x9D, 0x78, 0xFF, 0xFF, +- 0x56, 0xF3, 0xFF, 0xFF, 0x40, 0x58, 0x03, 0x65, 0xE2, 0x60, 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, +- 0x56, 0xF3, 0x26, 0x46, 0x60, 0x43, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, +- 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0x88, 0xF3, 0x63, 0x45, 0x60, 0x46, +- 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, +- 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x2E, 0xF0, 0x66, 0x41, 0x12, 0x60, +- 0xCE, 0x65, 0x64, 0x47, 0x00, 0x7F, 0x88, 0xF1, 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, +- 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, +- 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, +- 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, +- 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, 0x2C, 0xF2, 0x2D, 0xF0, 0xAE, 0xF2, +- 0x66, 0x45, 0x63, 0x46, 0x03, 0xFA, 0x04, 0xF8, 0x55, 0xF3, 0x85, 0xFA, 0xFF, 0xA0, 0x65, 0x46, +- 0x03, 0x03, 0xD4, 0x60, 0xD6, 0x78, 0xFF, 0xFF, 0x95, 0xF3, 0x66, 0x45, 0x63, 0x46, 0x1B, 0xFA, +- 0x65, 0x46, 0xBA, 0x65, 0x60, 0x44, 0xC4, 0x85, 0x01, 0x60, 0xFE, 0x61, 0x00, 0x64, 0x80, 0x63, +- 0xC7, 0x85, 0x94, 0x84, 0x59, 0xDB, 0xFC, 0x1F, 0x00, 0x60, 0x88, 0x64, 0x3F, 0xFA, 0x00, 0xF4, +- 0x02, 0x64, 0x0A, 0xFA, 0x00, 0x64, 0x0B, 0xFA, 0x80, 0x7F, 0x10, 0x7E, 0x0C, 0xFA, 0x1A, 0x65, +- 0x80, 0x61, 0x02, 0x60, 0x00, 0x63, 0x0F, 0x4E, 0xF2, 0x60, 0x58, 0x4F, 0x4A, 0x78, 0xFF, 0xFF, +- 0x0E, 0x4F, 0xD4, 0x60, 0xA7, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x23, 0xF0, 0x00, 0x60, 0x02, 0x64, +- 0xA0, 0x80, 0x00, 0xF4, 0x03, 0x03, 0xD4, 0x60, 0x50, 0x78, 0xFF, 0xFF, 0x09, 0xF2, 0xFF, 0xFF, +- 0xFF, 0xA0, 0x00, 0xA0, 0x0C, 0x03, 0x03, 0x03, 0xD3, 0x60, 0xCC, 0x78, 0xFF, 0xFF, 0x0A, 0xF2, +- 0x26, 0x46, 0xFF, 0xA0, 0x87, 0xF4, 0x10, 0x02, 0xD4, 0x60, 0xD6, 0x78, 0xFF, 0xFF, 0x0A, 0xF2, +- 0xFF, 0xFF, 0xFF, 0xA0, 0xFD, 0xA0, 0x02, 0x03, 0x04, 0x03, 0x06, 0x00, 0xD4, 0x60, 0x0C, 0x78, +- 0xFF, 0xFF, 0xD4, 0x60, 0x17, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, +- 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x12, 0x60, +- 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, +- 0x88, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, +- 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, +- 0x14, 0x60, 0xD0, 0x62, 0xA2, 0xD3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, +- 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, +- 0xA1, 0xDB, 0x14, 0x60, 0xD0, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, +- 0xA2, 0xDB, 0xD1, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, +- 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x12, 0x60, +- 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, +- 0x88, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, +- 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, +- 0x14, 0x60, 0xD0, 0x62, 0xA2, 0xD3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, +- 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, +- 0xA1, 0xDB, 0x14, 0x60, 0xD0, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, +- 0xA2, 0xDB, 0xD1, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x32, 0x44, 0x08, 0xB0, 0x87, 0xF4, +- 0x03, 0x02, 0xD1, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0xD3, 0x60, 0x3C, 0x78, 0xFF, 0xFF, 0x32, 0x44, +- 0x26, 0x46, 0x08, 0xB0, 0x07, 0xF2, 0x03, 0x02, 0xD1, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0x60, 0x46, +- 0x1B, 0xF2, 0x26, 0x46, 0xBA, 0x65, 0x60, 0x44, 0xC4, 0x85, 0x01, 0x60, 0xFE, 0x61, 0x00, 0x64, +- 0x80, 0x63, 0xC7, 0x85, 0x94, 0x84, 0x59, 0xDB, 0xFC, 0x1F, 0x00, 0xF4, 0x01, 0x60, 0xFE, 0x61, +- 0x7E, 0x65, 0x18, 0x63, 0x5B, 0xD2, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0xD7, 0x80, 0x18, 0x02, +- 0xF9, 0x02, 0x00, 0xF4, 0x02, 0x63, 0x0E, 0x65, 0x5B, 0xD2, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, +- 0xD7, 0x80, 0x0E, 0x02, 0xF9, 0x02, 0x26, 0x46, 0x07, 0xF4, 0x06, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, +- 0x06, 0xFA, 0x26, 0x46, 0x00, 0xF4, 0x04, 0x64, 0x0A, 0xFA, 0x00, 0x64, 0x0B, 0xFA, 0x57, 0x00, +- 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, +- 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0x88, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, +- 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, +- 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x14, 0x60, 0xD0, 0x62, 0xA2, 0xD3, 0xDA, 0x81, +- 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, +- 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x14, 0x60, 0xD0, 0x62, 0x65, 0x44, +- 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0x00, 0xF4, 0x04, 0x64, 0x0A, 0xFA, +- 0x0F, 0x64, 0x0B, 0xFA, 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x41, 0x58, 0x26, 0x46, 0x2C, 0xF2, +- 0xA1, 0xDB, 0x2D, 0xF2, 0x59, 0xDB, 0x2E, 0xF2, 0x59, 0xDB, 0x03, 0x65, 0xE2, 0x60, 0x58, 0x4E, +- 0x5B, 0x78, 0xFF, 0xFF, 0x03, 0x65, 0xE2, 0x60, 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x88, 0xF3, 0x07, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x26, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, +- 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0xF4, 0x0A, 0xF2, 0x09, 0xF2, 0xFF, 0xA0, 0x00, 0xA0, 0x06, 0x02, +- 0xFF, 0xA0, 0x07, 0x03, 0x09, 0x03, 0xD3, 0x60, 0xCC, 0x78, 0xFF, 0xFF, 0xD3, 0x60, 0x8C, 0x78, +- 0xFF, 0xFF, 0xD4, 0x60, 0xDB, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x07, 0xF4, 0x06, 0xF2, 0x66, 0x43, +- 0x00, 0x7E, 0x06, 0xFA, 0x26, 0x46, 0xD3, 0x60, 0x3C, 0x78, 0xFF, 0xFF, 0x63, 0x46, 0x06, 0xF2, +- 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x26, 0x46, 0x88, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x02, 0x64, +- 0x0A, 0xFA, 0x00, 0x64, 0x0B, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, +- 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, +- 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x16, 0x60, 0xAC, 0x7C, 0x2A, 0xF2, 0xA4, 0xDB, 0x22, 0x60, +- 0x2A, 0x63, 0xFF, 0xB4, 0x01, 0x61, 0x00, 0x60, 0x10, 0x7C, 0xA3, 0xDB, 0x60, 0x40, 0x00, 0x36, +- 0x03, 0x00, 0x02, 0x61, 0x00, 0x60, 0x30, 0x7C, 0x41, 0x47, 0x2A, 0xF8, 0x2F, 0xF2, 0x2C, 0xFA, +- 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, +- 0xCD, 0xF3, 0x31, 0xFA, 0x67, 0xF3, 0x32, 0xFA, 0x68, 0xF3, 0x33, 0xFA, 0x69, 0xF3, 0x34, 0xFA, +- 0xAC, 0xF1, 0x19, 0xF8, 0x00, 0x7C, 0x3E, 0xF8, 0x1C, 0xF0, 0x13, 0xF8, 0x07, 0xF2, 0x88, 0xF1, +- 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0xD9, 0x60, 0xA3, 0x78, 0xFF, 0xFF, 0x40, 0x4B, +- 0xAB, 0x46, 0x06, 0xF2, 0xAB, 0x46, 0x00, 0xF4, 0x01, 0xB0, 0xFF, 0xFF, 0x03, 0x02, 0xD9, 0x60, +- 0xA3, 0x78, 0xFF, 0xFF, 0x22, 0x60, 0x2C, 0x63, 0x09, 0xF2, 0xBD, 0xDB, 0x43, 0x44, 0x10, 0xB0, +- 0x80, 0x60, 0x00, 0x63, 0x0D, 0x03, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x44, +- 0xFE, 0x26, 0x08, 0x00, 0x32, 0x40, 0x08, 0x26, 0x06, 0x00, 0xDA, 0x60, 0x02, 0x78, 0xFF, 0xFF, +- 0x32, 0x40, 0x10, 0x2A, 0x00, 0x63, 0xAB, 0x46, 0x06, 0xF0, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, +- 0x63, 0x45, 0xB4, 0x84, 0x06, 0xFA, 0xAB, 0x46, 0x0A, 0xF0, 0x56, 0xF9, 0x24, 0x43, 0xBD, 0xD9, +- 0x43, 0x44, 0x01, 0x63, 0x32, 0x40, 0x10, 0x26, 0x10, 0xBB, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD3, +- 0xFF, 0xFF, 0x60, 0x40, 0xFE, 0x26, 0x10, 0xBB, 0x09, 0xFC, 0x27, 0x44, 0xFE, 0xA0, 0xFF, 0xFF, +- 0x03, 0x03, 0xD5, 0x60, 0xFE, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0xA2, 0x64, 0x24, 0x43, 0x0B, 0xF0, +- 0xA0, 0xD9, 0xBD, 0xD9, 0x0C, 0xF0, 0x58, 0xD9, 0xBD, 0xD9, 0x0D, 0xF0, 0x58, 0xD9, 0xBD, 0xD9, +- 0x43, 0x44, 0x1C, 0x65, 0x2D, 0x61, 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x64, 0x44, +- 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, +- 0xF4, 0x02, 0x02, 0x60, 0x02, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0xE0, 0x84, 0x04, 0xA5, 0xC5, 0x81, +- 0xA1, 0xD3, 0x00, 0x65, 0x60, 0x43, 0x59, 0xD3, 0xFF, 0xFF, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, +- 0x01, 0x64, 0x15, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, 0x11, 0x00, 0x0A, 0x3A, 0x02, 0x00, +- 0x04, 0x64, 0x0D, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x09, 0x00, 0x10, 0x3A, 0x02, 0x00, +- 0x10, 0x64, 0x05, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x20, 0x64, 0x01, 0x00, 0x00, 0x64, 0xCF, 0x83, +- 0xB4, 0x85, 0xE1, 0x02, 0x65, 0x44, 0x60, 0xFB, 0xB8, 0xF3, 0x2B, 0x45, 0x66, 0x41, 0x65, 0x46, +- 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, +- 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x5F, 0xF3, 0x60, 0xF1, +- 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, 0x02, 0x02, 0x5F, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, +- 0xAE, 0x65, 0xB8, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, +- 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x61, 0xFB, 0x6F, 0xF0, +- 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, +- 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, +- 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, +- 0x66, 0x43, 0x0C, 0xF4, 0xFF, 0xFF, 0xD6, 0x60, 0x80, 0x78, 0xFF, 0xFF, 0x16, 0x65, 0x2D, 0x61, +- 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, +- 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0xF4, 0x02, 0x02, 0x60, 0x02, 0x61, +- 0xA1, 0xD3, 0xFF, 0xFF, 0xE0, 0x84, 0x04, 0xA5, 0xC5, 0x81, 0xA1, 0xD3, 0x00, 0x65, 0x60, 0x43, +- 0x59, 0xD3, 0xFF, 0xFF, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x01, 0x64, 0x15, 0x00, 0x04, 0x3A, +- 0x02, 0x00, 0x02, 0x64, 0x11, 0x00, 0x0A, 0x3A, 0x02, 0x00, 0x04, 0x64, 0x0D, 0x00, 0x0B, 0x3A, +- 0x02, 0x00, 0x08, 0x64, 0x09, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x10, 0x64, 0x05, 0x00, 0x16, 0x3A, +- 0x02, 0x00, 0x20, 0x64, 0x01, 0x00, 0x00, 0x64, 0xCF, 0x83, 0xB4, 0x85, 0xE1, 0x02, 0x65, 0x44, +- 0x60, 0xFB, 0xB8, 0xF3, 0x2B, 0x45, 0x66, 0x41, 0x65, 0x46, 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, +- 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, +- 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x5F, 0xF3, 0x60, 0xF1, 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, +- 0x02, 0x02, 0x5F, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, 0xAE, 0x65, 0xB8, 0xF3, 0xFF, 0xFF, +- 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, +- 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x61, 0xFB, 0x6F, 0xF0, 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, +- 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, +- 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, +- 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x66, 0x43, 0x0C, 0xF4, 0xFF, 0xFF, +- 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x16, 0x65, 0x27, 0x40, 0x02, 0x3A, 0x03, 0x00, 0x1C, 0x65, +- 0xF6, 0xA4, 0x01, 0x00, 0xFC, 0xA4, 0x24, 0x43, 0x22, 0x60, 0x82, 0x61, 0x5D, 0x91, 0x51, 0x90, +- 0xFF, 0xFF, 0x04, 0x28, 0x60, 0x41, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, +- 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, +- 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x22, 0x60, 0x28, 0x7C, 0x03, 0x1E, +- 0x60, 0xFE, 0xBD, 0xDF, 0x20, 0xFE, 0x22, 0x60, 0x2C, 0x64, 0x53, 0x93, 0xA4, 0xDD, 0x26, 0x46, +- 0x00, 0xF4, 0x1F, 0x60, 0x90, 0x64, 0xA0, 0xD3, 0x00, 0x63, 0x00, 0xB8, 0x0A, 0xFC, 0x03, 0x02, +- 0xD7, 0x60, 0x14, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, 0x27, 0x40, 0x02, 0x3A, 0x02, 0x00, 0x0E, 0xF2, +- 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x3A, 0x26, 0x00, 0x60, 0x41, 0x00, 0x36, 0x23, 0x00, 0xE0, 0xA0, +- 0xDA, 0x85, 0x20, 0x07, 0x1F, 0x60, 0x1E, 0x63, 0xA3, 0xD1, 0x65, 0x42, 0xD1, 0x80, 0x1F, 0x60, +- 0x20, 0x63, 0x18, 0x02, 0x50, 0xFE, 0x61, 0x40, 0xFE, 0x22, 0x08, 0x00, 0x62, 0x45, 0xBD, 0xD3, +- 0xA5, 0xD0, 0xDA, 0x82, 0xD0, 0x80, 0xC9, 0x81, 0xF6, 0x0C, 0x0C, 0x00, 0x61, 0x40, 0x00, 0x36, +- 0x33, 0x00, 0x62, 0x45, 0xA3, 0xD3, 0xA5, 0xD0, 0xFF, 0xFF, 0x90, 0x80, 0xFF, 0x26, 0x02, 0x00, +- 0xDE, 0x82, 0x2A, 0x00, 0x0C, 0x63, 0x0A, 0xFC, 0x00, 0x64, 0x09, 0xFA, 0x0B, 0xFA, 0x01, 0x7E, +- 0x0C, 0xFA, 0x26, 0x46, 0x08, 0x64, 0x3F, 0xFA, 0x07, 0xF2, 0x88, 0xF1, 0x40, 0x58, 0x07, 0xF8, +- 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xDA, 0x60, 0x1E, 0x78, 0xFF, 0xFF, 0x20, 0xFE, +- 0x21, 0x60, 0xE2, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x22, 0xB0, 0xFF, 0xFF, 0x03, 0x03, 0xD8, 0x60, +- 0x9F, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0xD7, 0x01, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, +- 0xFF, 0xA4, 0xFF, 0xFF, 0x0C, 0x20, 0x0D, 0x00, 0xD8, 0x60, 0x9F, 0x78, 0xFF, 0xFF, 0x20, 0xFE, +- 0x28, 0x46, 0x2A, 0x41, 0xFF, 0xB1, 0x60, 0xFE, 0x82, 0x64, 0xA1, 0xDA, 0xFF, 0xFF, 0x20, 0xFE, +- 0x15, 0x00, 0x21, 0x60, 0xEE, 0x61, 0xA1, 0xDF, 0xD9, 0x81, 0xA1, 0xDF, 0xD9, 0x81, 0xA1, 0xDF, +- 0x04, 0xA1, 0xA1, 0xDF, 0xD9, 0x81, 0xA1, 0xDF, 0xD9, 0x81, 0xA1, 0xDF, 0xD9, 0x81, 0xA1, 0xDF, +- 0x2B, 0x46, 0x37, 0xF2, 0x7F, 0x60, 0xCF, 0x65, 0xA4, 0x84, 0xA2, 0xDA, 0x26, 0x46, 0x3F, 0xF2, +- 0x00, 0xF4, 0x27, 0x40, 0x02, 0x3A, 0x40, 0x00, 0x60, 0x43, 0xF6, 0xA3, 0x00, 0x60, 0x1B, 0x61, +- 0x00, 0x60, 0xDD, 0x65, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, +- 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0xD4, 0x80, 0x2D, 0x03, 0x17, 0x03, 0xCF, 0x83, 0x61, 0x44, +- 0x80, 0xA0, 0x28, 0x03, 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, +- 0x81, 0xA1, 0x20, 0x03, 0x05, 0x07, 0x7F, 0xA1, 0xCC, 0x84, 0xDD, 0x81, 0xE4, 0x03, 0xF7, 0x01, +- 0x00, 0xF4, 0x00, 0xB8, 0x04, 0x61, 0xE4, 0x03, 0xF2, 0x01, 0x01, 0x60, 0xFF, 0x63, 0x46, 0x48, +- 0x41, 0x4A, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, 0x64, 0x44, 0xDD, 0x81, 0xA1, 0xD0, +- 0xDF, 0x83, 0xA3, 0xD9, 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, 0x7F, 0xA1, 0xF7, 0x04, 0x00, 0xF4, +- 0x03, 0x61, 0xF4, 0x01, 0x20, 0xFE, 0x3F, 0x00, 0x60, 0x43, 0xFC, 0xA3, 0x00, 0x60, 0x15, 0x61, +- 0x00, 0x60, 0xDD, 0x65, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, +- 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0xD4, 0x80, 0x2D, 0x03, 0x17, 0x03, 0xCF, 0x83, 0x61, 0x44, +- 0x80, 0xA0, 0x28, 0x03, 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, +- 0x81, 0xA1, 0x20, 0x03, 0x05, 0x07, 0x7F, 0xA1, 0xCC, 0x84, 0xDD, 0x81, 0xE4, 0x03, 0xF7, 0x01, +- 0x00, 0xF4, 0x00, 0xB8, 0x04, 0x61, 0xE4, 0x03, 0xF2, 0x01, 0x01, 0x60, 0xFF, 0x63, 0x46, 0x48, +- 0x41, 0x4A, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, 0x64, 0x44, 0xDD, 0x81, 0xA1, 0xD0, +- 0xDF, 0x83, 0xA3, 0xD9, 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, 0x7F, 0xA1, 0xF7, 0x04, 0x00, 0xF4, +- 0x03, 0x61, 0xF4, 0x01, 0x20, 0xFE, 0x00, 0xBB, 0x02, 0x60, 0x00, 0x61, 0x08, 0x24, 0xD7, 0x00, +- 0x60, 0xFE, 0xA1, 0xD3, 0xFF, 0xFF, 0xFA, 0xA4, 0xFF, 0xFF, 0x01, 0x05, 0x50, 0x01, 0xDD, 0x81, +- 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x3A, 0x4A, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, +- 0x64, 0x40, 0x50, 0x3A, 0x44, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0xF2, 0x3A, +- 0x3E, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x3A, 0x20, 0x01, 0xDD, 0x81, +- 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x3A, 0x1A, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, +- 0x64, 0x40, 0x00, 0x3A, 0x14, 0x01, 0x60, 0x5C, 0x00, 0x36, 0x30, 0x00, 0x00, 0x64, 0xD8, 0x60, +- 0x58, 0x4E, 0xC4, 0x78, 0xFF, 0xFF, 0x21, 0x60, 0xF6, 0x62, 0xA2, 0xDB, 0x64, 0x40, 0x00, 0x36, +- 0x2B, 0x00, 0xDD, 0x81, 0xA1, 0xD3, 0xDD, 0x81, 0xD8, 0x60, 0x58, 0x4E, 0xC4, 0x78, 0xFF, 0xFF, +- 0x21, 0x60, 0xF8, 0x62, 0xA2, 0xDB, 0x64, 0x40, 0x00, 0x36, 0x24, 0x00, 0xDD, 0x81, 0xA1, 0xD3, +- 0xDD, 0x81, 0xD8, 0x60, 0x58, 0x4E, 0xC4, 0x78, 0xFF, 0xFF, 0x21, 0x60, 0xFA, 0x62, 0xA2, 0xDB, +- 0x64, 0x40, 0x00, 0x36, 0x1D, 0x00, 0xDD, 0x81, 0xA1, 0xD1, 0x21, 0x60, 0xFC, 0x62, 0xA2, 0xD9, +- 0xDD, 0x81, 0xA1, 0xD1, 0x21, 0x60, 0xFD, 0x62, 0xA2, 0xD9, 0x19, 0x00, 0x20, 0xFE, 0x21, 0x60, +- 0xF6, 0x62, 0x00, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0x20, 0xFE, 0x21, 0x60, 0xF8, 0x62, 0x00, 0x60, +- 0x04, 0x64, 0xA2, 0xDB, 0x20, 0xFE, 0x21, 0x60, 0xFA, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, +- 0x20, 0xFE, 0x21, 0x60, 0xFC, 0x62, 0x00, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x00, 0x20, 0xFE, +- 0x21, 0x60, 0xE2, 0x62, 0xA2, 0xD1, 0x21, 0x60, 0xF6, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0x84, +- 0xFF, 0xFF, 0x10, 0x26, 0x09, 0x00, 0x04, 0x26, 0x09, 0x00, 0x20, 0x26, 0x09, 0x00, 0x02, 0x26, +- 0x09, 0x00, 0xD7, 0x60, 0x07, 0x78, 0xFF, 0xFF, 0x10, 0x7C, 0x05, 0x00, 0x04, 0x7C, 0x03, 0x00, +- 0x20, 0x7C, 0x01, 0x00, 0x02, 0x7C, 0x21, 0x60, 0xEE, 0x61, 0xA1, 0xD9, 0x21, 0x60, 0xE4, 0x61, +- 0xA1, 0xD1, 0x21, 0x60, 0xF8, 0x61, 0xA1, 0xD3, 0x21, 0x60, 0xEE, 0x61, 0xA0, 0x84, 0xA1, 0xD1, +- 0xFF, 0xFF, 0x10, 0x26, 0x07, 0x00, 0x04, 0x26, 0x07, 0x00, 0x01, 0x26, 0x0D, 0x00, 0xD7, 0x60, +- 0x07, 0x78, 0xFF, 0xFF, 0x10, 0x7C, 0x09, 0x00, 0x64, 0x40, 0x10, 0x22, 0x03, 0x00, 0xD7, 0x60, +- 0x07, 0x78, 0xFF, 0xFF, 0x04, 0x7C, 0x01, 0x00, 0x01, 0x7C, 0x21, 0x60, 0xF0, 0x61, 0xA1, 0xD9, +- 0x21, 0x60, 0xE6, 0x61, 0xA1, 0xD1, 0x21, 0x60, 0xFA, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0xA0, 0x84, +- 0x02, 0x26, 0x07, 0x00, 0x04, 0x26, 0x07, 0x00, 0x01, 0x26, 0x07, 0x00, 0xD7, 0x60, 0x07, 0x78, +- 0xFF, 0xFF, 0x02, 0x7C, 0x03, 0x00, 0x04, 0x7C, 0x01, 0x00, 0x20, 0x7C, 0x21, 0x60, 0xF2, 0x61, +- 0xA1, 0xD9, 0x21, 0x60, 0xFC, 0x61, 0xA1, 0xD1, 0x21, 0x60, 0xF4, 0x61, 0xA1, 0xD9, 0x21, 0x60, +- 0xF2, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x21, 0x60, 0xF0, 0x61, 0xA1, 0xD1, 0xFF, 0xFF, +- 0xB0, 0x84, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x22, 0xBC, +- 0xAB, 0x46, 0x36, 0xFA, 0xAB, 0x46, 0x21, 0x60, 0xEE, 0x61, 0xA1, 0xD3, 0x1F, 0x60, 0x92, 0x62, +- 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x22, 0xBC, 0x88, 0xF1, 0x66, 0x41, 0x64, 0x46, +- 0x36, 0xFA, 0xFF, 0xFF, 0x61, 0x46, 0x50, 0x00, 0x21, 0x60, 0xFE, 0x62, 0xA2, 0xDB, 0xE0, 0x84, +- 0xE0, 0x84, 0x03, 0x02, 0x01, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x02, 0xA5, 0x64, 0x44, 0xD4, 0x9C, +- 0x22, 0x60, 0x00, 0x62, 0xA2, 0xD9, 0x22, 0x60, 0x02, 0x62, 0xA2, 0xDF, 0xDD, 0x81, 0xA1, 0xD1, +- 0x00, 0x65, 0x64, 0x40, 0x00, 0x3A, 0x01, 0x65, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, +- 0x50, 0x3A, 0x01, 0x65, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0xF2, 0x3A, 0x01, 0x65, +- 0xDD, 0x81, 0xA1, 0xD1, 0x65, 0x40, 0x00, 0x3A, 0x18, 0x00, 0x00, 0x60, 0x00, 0x65, 0x64, 0x40, +- 0x00, 0x36, 0x01, 0x65, 0x64, 0x40, 0x01, 0x36, 0x02, 0x65, 0x64, 0x40, 0x02, 0x36, 0x04, 0x65, +- 0x64, 0x40, 0x04, 0x36, 0x10, 0x65, 0x64, 0x40, 0x05, 0x36, 0x20, 0x65, 0x65, 0x5C, 0x22, 0x60, +- 0x02, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xB0, 0x84, 0xA2, 0xDB, 0x21, 0x60, 0xFE, 0x62, 0xA2, 0xD3, +- 0xFF, 0xFF, 0xFF, 0xA4, 0xA2, 0xDB, 0xCA, 0x02, 0x22, 0x60, 0x02, 0x62, 0xA2, 0xD3, 0x22, 0x60, +- 0x00, 0x62, 0xA2, 0xD1, 0x2E, 0x58, 0xFF, 0xFF, 0xAB, 0x46, 0x82, 0xF0, 0xC0, 0x67, 0xB4, 0x84, +- 0xAB, 0x46, 0x0B, 0xFA, 0x1F, 0x60, 0xA0, 0x64, 0xA0, 0xD1, 0x22, 0x60, 0xD4, 0x7C, 0x04, 0x1B, +- 0xFF, 0x60, 0xFF, 0x63, 0xA4, 0xDD, 0x29, 0x00, 0x23, 0x60, 0x3C, 0x63, 0xA4, 0xDD, 0xDB, 0x83, +- 0x60, 0xFE, 0x00, 0x64, 0xBD, 0xDB, 0x60, 0x64, 0xBD, 0xDB, 0x1D, 0x64, 0xBD, 0xDB, 0xC3, 0xF3, +- 0xBD, 0xDB, 0xFF, 0xFF, 0x20, 0xFE, 0x01, 0x60, 0x78, 0x64, 0x06, 0x61, 0x58, 0xD1, 0xFF, 0xFF, +- 0x60, 0xFE, 0xBD, 0xD9, 0x20, 0xFE, 0xCD, 0x81, 0x61, 0x40, 0x08, 0x28, 0xF7, 0x01, 0xB7, 0xF1, +- 0xFF, 0xFF, 0x64, 0x47, 0x60, 0xFE, 0xBD, 0xD9, 0xBD, 0xDB, 0x20, 0xFE, 0x1F, 0x60, 0x9C, 0x64, +- 0xA0, 0xD1, 0x60, 0xFE, 0xBD, 0xD9, 0xFF, 0xFF, 0x20, 0xFE, 0x22, 0x60, 0xD2, 0x64, 0x40, 0x48, +- 0x18, 0x61, 0x26, 0x46, 0x00, 0xF4, 0xFF, 0x60, 0xF2, 0x64, 0xE1, 0x60, 0x58, 0x4D, 0xE5, 0x78, +- 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xFC, 0x2B, 0x46, 0x56, 0xF1, 0x16, 0x60, 0xAC, 0x61, 0x1B, 0xF8, +- 0xA1, 0xD1, 0x10, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x06, 0xF2, 0x0C, 0x03, 0x10, 0xBC, 0x06, 0xFA, +- 0x87, 0xF3, 0x00, 0x60, 0xE2, 0x62, 0xA2, 0xD3, 0x60, 0x45, 0xD4, 0x80, 0xDC, 0x84, 0x07, 0x07, +- 0xA2, 0xDB, 0x05, 0x00, 0x10, 0xB5, 0xFF, 0xFF, 0x02, 0x03, 0xD4, 0x84, 0x06, 0xFA, 0x07, 0xF2, +- 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x02, 0xB0, 0xFF, 0xFF, 0x12, 0x03, 0x26, 0x46, +- 0x88, 0xF3, 0x07, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x26, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, +- 0x4C, 0x00, 0x26, 0x46, 0x88, 0xF3, 0x07, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, +- 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, +- 0x00, 0x66, 0x46, 0x46, 0x1A, 0x00, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, 0x02, 0x64, 0x3F, 0xFA, +- 0x88, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x09, 0x64, 0x09, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, +- 0x8E, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x2B, 0x43, 0x14, 0x60, 0xD0, 0x62, +- 0xA2, 0xD3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, +- 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x14, 0x60, +- 0xD0, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0xAB, 0x46, +- 0x06, 0xF2, 0xFF, 0xFF, 0x02, 0xBC, 0x06, 0xFA, 0xAB, 0x46, 0xAB, 0x46, 0x0F, 0x60, 0xFF, 0x64, +- 0x02, 0xF0, 0x72, 0xF1, 0xA0, 0x84, 0xD0, 0x80, 0x02, 0xFA, 0xAB, 0x46, 0x01, 0x06, 0x72, 0xFB, +- 0x27, 0x41, 0x01, 0xB1, 0xFF, 0xFF, 0x08, 0x03, 0x2B, 0x46, 0x0B, 0x58, 0x01, 0x65, 0xE2, 0x60, +- 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x0A, 0x00, 0x2B, 0x46, 0x0B, 0x58, 0x16, 0x60, 0xA2, 0x64, +- 0x40, 0x59, 0x02, 0x65, 0xE2, 0x60, 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, +- 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x00, 0x64, 0x09, 0xFA, 0x0B, 0xFA, 0x01, 0x7E, +- 0x0C, 0xFA, 0x0A, 0x64, 0x0A, 0xFA, 0x26, 0x46, 0x08, 0x64, 0x3F, 0xFA, 0x07, 0xF2, 0x88, 0xF1, +- 0x40, 0x58, 0x07, 0xF8, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x26, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xFF, 0x60, 0xFD, 0x65, +- 0x38, 0x46, 0x06, 0xF2, 0xFF, 0xFF, 0xA4, 0x83, 0x06, 0xFC, 0x02, 0xB0, 0x26, 0x46, 0x1C, 0x03, +- 0x38, 0x43, 0x87, 0xF1, 0x14, 0x60, 0xCE, 0x61, 0xA1, 0xD3, 0xDA, 0x81, 0xD0, 0x80, 0xDC, 0x9C, +- 0x05, 0x05, 0xA1, 0xD3, 0x4A, 0xD9, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0x02, 0x60, 0x00, 0x61, +- 0x2C, 0xF2, 0xA1, 0xDB, 0x2D, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x2E, 0xF2, 0x59, 0xDB, 0x03, 0x65, +- 0xE2, 0x60, 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, +- 0x07, 0xF2, 0x88, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, +- 0x40, 0x47, 0x07, 0xF2, 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x02, 0xB0, 0xFF, 0xFF, +- 0x1B, 0x02, 0x27, 0x43, 0x14, 0x60, 0xD0, 0x62, 0xA2, 0xD3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, +- 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, +- 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x14, 0x60, 0xD0, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, +- 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0x0C, 0x00, 0x27, 0x44, 0x40, 0x58, 0x03, 0x65, 0xE2, 0x60, +- 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x27, 0x43, 0xE4, 0x60, 0x58, 0x4E, 0x9D, 0x78, 0xFF, 0xFF, +- 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, +- 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0x88, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, +- 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, +- 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x07, 0xF2, 0x88, 0xF1, +- 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, 0x40, 0x47, 0x07, 0xF2, +- 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x02, 0xB0, 0xFF, 0xFF, 0x02, 0x02, 0x2F, 0x58, +- 0xFF, 0xFF, 0x27, 0x46, 0x06, 0xF0, 0xFF, 0x60, 0xED, 0x64, 0xA0, 0x84, 0x06, 0xFA, 0x27, 0x43, +- 0x87, 0xF1, 0x14, 0x60, 0xCE, 0x61, 0xA1, 0xD3, 0xDA, 0x81, 0xD0, 0x80, 0xDC, 0x9C, 0x05, 0x05, +- 0xA1, 0xD3, 0x4A, 0xD9, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0x07, 0x58, 0x03, 0x65, 0xE2, 0x60, +- 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x27, 0x43, 0xE4, 0x60, 0x58, 0x4E, 0x9D, 0x78, 0xFF, 0xFF, +- 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, +- 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, +- 0x67, 0xF3, 0x32, 0xFA, 0x68, 0xF3, 0x33, 0xFA, 0x69, 0xF3, 0x34, 0xFA, 0xAC, 0xF1, 0x19, 0xF8, +- 0x1C, 0xF2, 0x13, 0xFA, 0x02, 0x63, 0x3F, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0x02, 0x60, 0x00, 0x61, +- 0x2C, 0xF2, 0xA1, 0xDB, 0x2D, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x2E, 0xF2, 0x59, 0xDB, 0x06, 0x63, +- 0x07, 0xF2, 0x88, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x0D, 0x02, 0x43, 0x59, 0x02, 0x65, +- 0xE2, 0x60, 0x58, 0x4E, 0x5B, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0xC0, 0x64, 0x2A, 0xFA, 0x00, 0xF4, +- 0x06, 0x64, 0x09, 0xFA, 0x15, 0x00, 0x07, 0xF2, 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, +- 0x02, 0xB0, 0xFF, 0xFF, 0x1E, 0x02, 0x07, 0x63, 0x43, 0x59, 0x01, 0x65, 0xE2, 0x60, 0x58, 0x4E, +- 0x5B, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0xA0, 0x64, 0x2A, 0xFA, 0x00, 0xF4, 0x07, 0x64, 0x09, 0xFA, +- 0x26, 0x46, 0x88, 0xF3, 0x07, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, +- 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, +- 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xFE, 0x62, 0xDB, 0x60, 0xB0, 0x64, 0xA2, 0xDB, +- 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x60, 0x03, 0x64, 0xA2, 0xDB, 0xDB, 0x60, +- 0x4D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xE8, 0x62, 0xA2, 0xD1, +- 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x5A, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x72, 0xF3, +- 0x88, 0xF5, 0xDC, 0x81, 0x66, 0x43, 0x02, 0xA3, 0x63, 0x46, 0xCD, 0x81, 0x06, 0xF2, 0xED, 0x03, +- 0x60, 0x40, 0x08, 0x2A, 0xF7, 0x01, 0x0C, 0xAC, 0x06, 0xFA, 0x46, 0x49, 0x00, 0x60, 0x02, 0x61, +- 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, 0xE0, 0x03, 0x25, 0x60, 0x2C, 0x61, 0xA1, 0xD3, +- 0xFF, 0xFF, 0x03, 0x1B, 0x00, 0x60, 0xA0, 0x64, 0x02, 0x00, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, +- 0xAB, 0xFC, 0x66, 0x45, 0x29, 0x44, 0x07, 0xFA, 0x29, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x85, 0xF2, +- 0x65, 0x46, 0x2C, 0xFA, 0x2D, 0xF8, 0xAE, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0x32, 0xFA, 0xCC, 0xF3, +- 0x30, 0xFA, 0x33, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, 0x34, 0xFA, 0xAC, 0xF1, 0x19, 0xF8, 0x18, 0x67, +- 0x0E, 0xFA, 0x66, 0x45, 0x63, 0x46, 0x0E, 0xF2, 0x65, 0x46, 0x00, 0x7E, 0x13, 0xFA, 0x02, 0x63, +- 0x3F, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0x66, 0x41, 0x00, 0xF4, 0x25, 0x60, 0x28, 0x62, 0xA2, 0xD3, +- 0xFF, 0xFF, 0x09, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x9A, 0x64, 0xA2, 0xDB, 0x61, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0x9E, 0x01, 0x92, 0x01, +- 0x0F, 0x60, 0xE8, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x07, 0xF0, +- 0xFF, 0xFF, 0x64, 0x43, 0x14, 0x60, 0xD0, 0x62, 0xA2, 0xD3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, +- 0xA1, 0xD1, 0x04, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0x09, 0x00, 0xA1, 0xDD, 0x14, 0x60, +- 0xD0, 0x62, 0xD9, 0x84, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xA2, 0xDB, 0x66, 0x45, +- 0x63, 0x46, 0x06, 0xF2, 0xFF, 0x60, 0x01, 0x7C, 0xA0, 0x9C, 0x06, 0xF8, 0x65, 0x46, 0x71, 0xF3, +- 0x60, 0x40, 0x10, 0x2A, 0x03, 0x00, 0xCC, 0x84, 0x80, 0x2B, 0x71, 0xFB, 0x0F, 0x60, 0xE8, 0x62, +- 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x0F, 0x60, 0xDC, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xDE, 0x62, 0x00, 0x60, 0x02, 0x64, +- 0xA2, 0xDB, 0xDB, 0x60, 0xF7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x71, 0xF3, +- 0x72, 0xF3, 0x00, 0xA8, 0x60, 0x88, 0x50, 0x03, 0xE0, 0x83, 0x6C, 0x03, 0xCB, 0x83, 0x88, 0xF3, +- 0x73, 0xF1, 0x02, 0xA4, 0x40, 0x47, 0x64, 0x45, 0x27, 0x46, 0x72, 0xF4, 0x12, 0xF2, 0x40, 0x18, +- 0xD4, 0x80, 0x02, 0x64, 0x3D, 0x07, 0x23, 0xFA, 0x2A, 0xF2, 0x0E, 0xF2, 0x0C, 0xB0, 0x02, 0xF0, +- 0x0D, 0x02, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xE6, 0x01, 0x60, 0x40, 0xF0, 0x37, +- 0x08, 0x00, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0x90, 0xF3, 0x02, 0x02, 0xDC, 0x84, +- 0x90, 0xFB, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xAC, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA3, 0xFF, 0xCE, 0xFE, 0x98, 0xF1, 0x1E, 0x60, +- 0xEC, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, +- 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xBC, 0x01, +- 0x27, 0x44, 0x02, 0xA4, 0x40, 0x47, 0xB8, 0x1F, 0x28, 0x43, 0xCB, 0x83, 0x88, 0xF3, 0x1A, 0x0E, +- 0x02, 0xA4, 0x40, 0x4C, 0x43, 0x48, 0x2C, 0x46, 0x1E, 0xF2, 0x73, 0xF1, 0xAC, 0x86, 0x12, 0xF2, +- 0x0C, 0x03, 0xD0, 0x80, 0xFF, 0xFF, 0x09, 0x07, 0x1B, 0x60, 0xDA, 0x64, 0x40, 0x4B, 0xF0, 0x60, +- 0x58, 0x4D, 0x75, 0x78, 0xFF, 0xFF, 0x2C, 0x46, 0x9E, 0xFC, 0x2C, 0x44, 0x02, 0xA4, 0x28, 0x43, +- 0x40, 0x4C, 0xE8, 0x1F, 0x7D, 0x01, 0x01, 0x63, 0x66, 0xF3, 0xAC, 0xF3, 0x00, 0xBD, 0xAC, 0x81, +- 0x06, 0x03, 0x05, 0x03, 0xB5, 0x60, 0x58, 0x4D, 0xC1, 0x78, 0xFF, 0xFF, 0x60, 0x43, 0x5B, 0xFD, +- 0x3E, 0x63, 0x16, 0x60, 0x60, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, 0x71, 0xFB, 0x72, 0xFB, +- 0x16, 0x60, 0xA8, 0x65, 0x00, 0x64, 0xA5, 0xDB, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x1B, 0x60, +- 0x9A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x03, 0x02, 0xC7, 0x60, 0x2E, 0x78, +- 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x45, 0x64, 0x46, 0x1B, 0xF2, 0x65, 0x46, 0x64, 0x45, 0x5B, 0xF1, +- 0xE0, 0x84, 0x73, 0xF1, 0xC0, 0x84, 0xC0, 0x84, 0x12, 0xFA, 0x2C, 0xF2, 0x71, 0xF3, 0x60, 0x40, +- 0x01, 0x2A, 0x36, 0x00, 0x00, 0xA8, 0x1F, 0x60, 0x8E, 0x62, 0xA2, 0xD3, 0x37, 0x03, 0x00, 0xA8, +- 0xFF, 0xFF, 0x34, 0x03, 0xDE, 0x60, 0x58, 0x4D, 0x6B, 0x78, 0xFF, 0xFF, 0x25, 0x46, 0x09, 0x60, +- 0x08, 0x61, 0xA2, 0xFF, 0x0E, 0xF2, 0x02, 0xF0, 0x60, 0x40, 0xF0, 0x37, 0x0D, 0x00, 0x92, 0xF3, +- 0x90, 0xF3, 0xDC, 0x83, 0xD1, 0x80, 0x92, 0xFD, 0x0C, 0x03, 0x8C, 0xF3, 0xCC, 0x83, 0xD8, 0xA0, +- 0x90, 0xFD, 0x07, 0x04, 0xD4, 0xFE, 0x05, 0x00, 0xD1, 0x80, 0x93, 0xF3, 0x02, 0x03, 0xDC, 0x84, +- 0x93, 0xFB, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x94, 0x64, 0xA2, 0xDB, 0x25, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA3, 0xFF, 0xDC, 0x60, 0x87, 0x78, 0xFF, 0xFF, +- 0x66, 0x41, 0x65, 0x46, 0x06, 0xF2, 0x61, 0x46, 0x60, 0x40, 0x10, 0x2A, 0x4C, 0x00, 0x80, 0x67, +- 0xB4, 0x81, 0x1B, 0x60, 0xDA, 0x62, 0x61, 0x44, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xDE, 0x60, 0x58, 0x4D, 0x6B, 0x78, 0xFF, 0xFF, 0x25, 0x46, +- 0x2A, 0xF2, 0x09, 0x60, 0x08, 0x61, 0x0C, 0xB0, 0xA2, 0xFF, 0x17, 0x03, 0x0E, 0xF2, 0x02, 0xF0, +- 0x60, 0x40, 0xF0, 0x37, 0x0D, 0x00, 0x90, 0xF3, 0x92, 0xF3, 0xCC, 0x83, 0xD1, 0x80, 0x90, 0xFD, +- 0x0C, 0x03, 0x8C, 0xF3, 0xDC, 0x83, 0xD8, 0xA0, 0x92, 0xFD, 0x07, 0x04, 0xD4, 0xFE, 0x05, 0x00, +- 0xD1, 0x80, 0x93, 0xF3, 0x02, 0x03, 0xDC, 0x84, 0x93, 0xFB, 0x07, 0xF0, 0x0A, 0xF2, 0xA3, 0xFF, +- 0x64, 0x45, 0x30, 0x1B, 0x66, 0x41, 0x65, 0x46, 0x02, 0xF0, 0x61, 0x46, 0x0F, 0x60, 0xFF, 0x61, +- 0xA1, 0x84, 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, +- 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x16, 0x60, 0x62, 0x65, 0x46, 0xD1, 0x61, 0x44, +- 0xB0, 0x84, 0xA2, 0xDB, 0x17, 0x00, 0x1B, 0x60, 0x8E, 0x61, 0x2A, 0xF2, 0x3E, 0xF2, 0x0C, 0xB0, +- 0x01, 0xB0, 0x05, 0x03, 0x1B, 0x60, 0xA0, 0x61, 0x02, 0x02, 0x1B, 0x60, 0x88, 0x61, 0x1B, 0x60, +- 0xDA, 0x62, 0x61, 0x44, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xC1, 0xFE, 0xDC, 0x60, 0x87, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x2B, 0xF2, 0x2A, 0xF2, +- 0x60, 0x41, 0x44, 0x49, 0x60, 0x45, 0xA4, 0x3A, 0x0D, 0x00, 0x61, 0x40, 0xC0, 0x3B, 0x7B, 0x00, +- 0xA9, 0x46, 0x06, 0xF2, 0xA9, 0x46, 0x60, 0x40, 0x20, 0x26, 0x75, 0x00, 0x20, 0xBC, 0xA9, 0x46, +- 0x06, 0xFA, 0xA9, 0x46, 0xA9, 0x46, 0x06, 0xF0, 0xA9, 0x46, 0x65, 0x40, 0x10, 0x2B, 0x6E, 0x00, +- 0x64, 0x40, 0x10, 0x2A, 0x36, 0x00, 0x65, 0x40, 0xA4, 0x3A, 0x65, 0x00, 0x29, 0x45, 0x65, 0x46, +- 0x72, 0xF2, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x04, 0x02, 0x78, 0x00, 0xDE, 0x60, 0x51, 0x78, +- 0xFF, 0xFF, 0x09, 0xF2, 0x2A, 0xF0, 0x00, 0xA8, 0x20, 0x67, 0x02, 0x03, 0xB0, 0x84, 0x2A, 0xFA, +- 0x0E, 0xF2, 0x02, 0xF0, 0x60, 0x40, 0xF0, 0x37, 0x08, 0x00, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, +- 0xA2, 0xFF, 0x90, 0xF3, 0x02, 0x02, 0xDC, 0x84, 0x90, 0xFB, 0x3E, 0xF2, 0xA3, 0xFF, 0x01, 0xB0, +- 0x1B, 0x60, 0xA0, 0x61, 0x02, 0x02, 0x1B, 0x60, 0x8E, 0x61, 0x1B, 0x60, 0xDA, 0x62, 0x61, 0x44, +- 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, +- 0x17, 0x00, 0x10, 0x64, 0xB0, 0x84, 0xDF, 0x65, 0xA4, 0x9E, 0xA9, 0x46, 0x06, 0xFA, 0xA9, 0x46, +- 0xA2, 0xFF, 0x16, 0x60, 0xA8, 0x62, 0x04, 0x64, 0xA2, 0xDB, 0x29, 0x44, 0x5A, 0xDB, 0x71, 0xF3, +- 0xC1, 0xFE, 0xD4, 0xFE, 0x87, 0xF1, 0xA3, 0xFF, 0xD0, 0x80, 0xDC, 0x84, 0x01, 0x07, 0x71, 0xFB, +- 0xA9, 0x46, 0x72, 0xF2, 0xA9, 0x46, 0x65, 0x18, 0xA9, 0x46, 0x02, 0xF0, 0xA9, 0x46, 0x0F, 0x60, +- 0xFF, 0x61, 0xA1, 0x84, 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, +- 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x16, 0x60, 0x62, 0x65, 0x46, 0xD1, +- 0xFF, 0xFF, 0xB1, 0x84, 0xA2, 0xDB, 0xDE, 0x60, 0x68, 0x78, 0xFF, 0xFF, 0x64, 0x40, 0x10, 0x2A, +- 0xFA, 0x01, 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, 0xA9, 0x46, 0x06, 0xFA, 0xA9, 0x46, 0x65, 0x41, +- 0x71, 0xF3, 0x29, 0x45, 0xCC, 0x84, 0x80, 0x2B, 0x71, 0xFB, 0x65, 0x46, 0x72, 0xF2, 0xFF, 0xFF, +- 0x00, 0xA8, 0x60, 0x46, 0x37, 0x02, 0x61, 0x40, 0xA4, 0x3A, 0xE5, 0x01, 0x00, 0x60, 0x3A, 0x61, +- 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, 0x81, 0x03, 0x02, 0x60, 0x48, 0x64, 0x2A, 0xFA, +- 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x67, 0xF1, 0x32, 0xF8, +- 0x68, 0xF1, 0x33, 0xF8, 0x69, 0xF1, 0x34, 0xF8, 0xA9, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x85, 0xF0, +- 0xA9, 0x46, 0x2C, 0xFA, 0x2D, 0xF8, 0xAE, 0xF8, 0xAC, 0xF1, 0x19, 0xF8, 0xFF, 0x67, 0x0E, 0xFA, +- 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x29, 0x44, 0x07, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, +- 0x8E, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xC1, 0xFE, 0x37, 0x00, 0x80, 0x67, 0xB4, 0x83, 0x2A, 0xF2, 0x09, 0x60, 0x08, 0x65, 0x0C, 0xB0, +- 0x09, 0xF0, 0x0D, 0x02, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x9D, 0x18, 0x64, 0x46, 0x3E, 0xF2, +- 0xA2, 0xFF, 0x01, 0xB0, 0x1B, 0x60, 0xA0, 0x61, 0x02, 0x02, 0x1B, 0x60, 0x88, 0x61, 0x02, 0xF2, +- 0x0E, 0xF0, 0xD4, 0x80, 0x09, 0xF4, 0x06, 0x02, 0x90, 0xF3, 0x64, 0x40, 0xF0, 0x37, 0x02, 0x00, +- 0xDC, 0x84, 0x90, 0xFB, 0x66, 0x44, 0x00, 0xA8, 0xFF, 0xFF, 0xF1, 0x02, 0x1B, 0x60, 0xDA, 0x62, +- 0x61, 0x44, 0xA2, 0xDB, 0x5A, 0xDD, 0x08, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, +- 0xA3, 0xFF, 0xA9, 0x46, 0x02, 0xF0, 0xA9, 0x46, 0x0F, 0x60, 0xFF, 0x61, 0xA1, 0x84, 0x60, 0x41, +- 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, +- 0xE1, 0x81, 0xFD, 0x02, 0x16, 0x60, 0x62, 0x65, 0x46, 0xD3, 0x9D, 0x85, 0xA4, 0x84, 0xA2, 0xDB, +- 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x46, 0x45, 0x3F, 0xF2, 0x05, 0x48, 0x00, 0xA8, 0x60, 0x41, +- 0x66, 0x44, 0x0B, 0x03, 0x0E, 0xA1, 0x00, 0xF2, 0x42, 0xFE, 0xAC, 0x86, 0x01, 0xF2, 0x1F, 0x03, +- 0x7F, 0xB5, 0xD5, 0x81, 0x66, 0x44, 0xF7, 0x07, 0x25, 0x46, 0x05, 0xF0, 0x06, 0xFA, 0x05, 0xFA, +- 0xD0, 0x80, 0x64, 0x43, 0x13, 0x03, 0x60, 0x46, 0x01, 0xF0, 0x80, 0x67, 0xB0, 0x84, 0x01, 0xFA, +- 0x00, 0xF0, 0x00, 0x64, 0x00, 0xFA, 0x44, 0x45, 0xA2, 0xFF, 0xB4, 0x60, 0x58, 0x4E, 0x48, 0x78, +- 0xFF, 0xFF, 0xA3, 0xFF, 0x08, 0x45, 0x25, 0x46, 0x01, 0x64, 0x02, 0xFA, 0x02, 0xFE, 0x2D, 0x58, +- 0xFF, 0xFF, 0x23, 0xF2, 0x07, 0xF0, 0x10, 0xB0, 0x10, 0xAC, 0x3B, 0x03, 0x23, 0xFA, 0x80, 0x67, +- 0xB0, 0x81, 0x1B, 0x60, 0xDA, 0x62, 0x61, 0x44, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x04, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x46, 0x45, 0x64, 0x46, 0x02, 0xF0, 0x0F, 0x60, 0xFF, 0x61, +- 0xA1, 0x84, 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, +- 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x16, 0x60, 0x62, 0x65, 0x46, 0xD1, 0xFF, 0xFF, +- 0xB1, 0x84, 0xA2, 0xDB, 0x9B, 0xF2, 0x25, 0x46, 0xE1, 0x81, 0x5B, 0xF1, 0x73, 0xF1, 0xC1, 0x81, +- 0xC1, 0x81, 0x92, 0xFA, 0xA2, 0xFF, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x61, 0xD1, 0x80, 0x0E, 0xF2, +- 0x05, 0x02, 0x90, 0xF3, 0x20, 0xB0, 0xCC, 0x84, 0x01, 0x02, 0x90, 0xFB, 0xA3, 0xFF, 0x48, 0xFE, +- 0x07, 0x00, 0x0E, 0xF2, 0x08, 0xFE, 0xF0, 0x7F, 0x60, 0x40, 0x20, 0x2A, 0x00, 0x7F, 0x0E, 0xFA, +- 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0xA0, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, +- 0x66, 0x44, 0x57, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x80, 0x64, 0x2A, 0xFA, 0xAC, 0xF1, 0x19, 0xF8, +- 0x00, 0x64, 0x3E, 0xFA, 0x00, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0x88, 0xF1, 0x07, 0xF8, 0x67, 0x44, +- 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0x0F, 0x60, 0xF6, 0x62, 0xE1, 0x60, 0x9E, 0x64, 0xA2, 0xDB, +- 0x10, 0x60, 0x02, 0x62, 0xE0, 0x60, 0x0D, 0x64, 0xA2, 0xDB, 0x16, 0x60, 0xB2, 0x63, 0x65, 0x44, +- 0xBD, 0xDB, 0x10, 0x60, 0x04, 0x64, 0xBD, 0xDB, 0x02, 0x64, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, +- 0xE6, 0x60, 0x5A, 0x78, 0xFF, 0xFF, 0xE6, 0x60, 0x58, 0x4D, 0x66, 0x78, 0xFF, 0xFF, 0x57, 0xF5, +- 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x67, 0xF1, 0x32, 0xF8, +- 0x68, 0xF1, 0x33, 0xF8, 0x69, 0xF1, 0x34, 0xF8, 0x1F, 0x60, 0x92, 0x62, 0xA2, 0xD1, 0x01, 0x64, +- 0x64, 0x40, 0xFE, 0x26, 0x10, 0xBC, 0x32, 0x40, 0x10, 0x26, 0x10, 0xBC, 0x23, 0x60, 0x4C, 0x62, +- 0xA2, 0xDB, 0x1F, 0x60, 0x90, 0x62, 0xA2, 0xD1, 0x1F, 0x60, 0x1E, 0x64, 0x02, 0x18, 0x1F, 0x60, +- 0x40, 0x64, 0x22, 0x60, 0xA2, 0x62, 0xA2, 0xDB, 0x22, 0x60, 0xBE, 0x62, 0xA2, 0xDB, 0x21, 0x60, +- 0xC6, 0x61, 0x20, 0x60, 0x32, 0x62, 0xA2, 0xD3, 0x22, 0x60, 0x82, 0x65, 0xFE, 0xA4, 0xE0, 0x84, +- 0x02, 0x05, 0x67, 0x44, 0x99, 0x00, 0xE0, 0x84, 0xC4, 0x85, 0x21, 0x60, 0xEC, 0x62, 0xA2, 0xD3, +- 0xA5, 0xD1, 0xDA, 0x85, 0x21, 0x60, 0xE4, 0x62, 0xA0, 0x83, 0xA2, 0xDD, 0xA5, 0xD1, 0x21, 0x60, +- 0xE2, 0x62, 0xA0, 0x83, 0xA2, 0xDD, 0x21, 0x60, 0xC0, 0x61, 0xDD, 0x60, 0x06, 0x64, 0xA1, 0xDB, +- 0x06, 0xA1, 0x21, 0x60, 0xEA, 0x62, 0xA2, 0xD3, 0x21, 0x60, 0xE2, 0x62, 0x60, 0x40, 0xFD, 0xA0, +- 0xA2, 0xD3, 0x74, 0x03, 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, +- 0xF2, 0x63, 0x0E, 0x00, 0x04, 0x2A, 0x03, 0x00, 0x02, 0x60, 0xF2, 0x63, 0x09, 0x00, 0x10, 0x2A, +- 0x03, 0x00, 0x04, 0x60, 0xF2, 0x63, 0x04, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, 0xF2, 0x63, +- 0x59, 0xD9, 0x59, 0xDD, 0x21, 0x60, 0xEA, 0x62, 0xA2, 0xD3, 0x21, 0x60, 0xE4, 0x62, 0xFE, 0xA0, +- 0xA2, 0xD3, 0x54, 0x03, 0x00, 0x60, 0x00, 0x63, 0x59, 0xDD, 0x61, 0x45, 0x60, 0x40, 0x01, 0x2A, +- 0x04, 0x00, 0x00, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x02, 0x2A, 0x04, 0x00, +- 0x01, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x04, 0x2A, 0x04, 0x00, 0x02, 0x60, +- 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x10, 0x2A, 0x04, 0x00, 0x04, 0x60, 0xF2, 0x63, +- 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, 0xF2, 0x63, 0x59, 0xD9, +- 0x59, 0xDD, 0xD5, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xA5, 0xDD, 0x21, 0x60, 0xEA, 0x62, 0xA2, 0xD3, +- 0x21, 0x60, 0xE6, 0x62, 0xFF, 0xA0, 0xA2, 0xD3, 0x21, 0x03, 0x00, 0x60, 0x00, 0x63, 0x59, 0xDD, +- 0x61, 0x45, 0x60, 0x40, 0x01, 0x2A, 0x04, 0x00, 0x00, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, +- 0x60, 0x40, 0x02, 0x2A, 0x04, 0x00, 0x01, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, +- 0x04, 0x2A, 0x04, 0x00, 0x02, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0xD5, 0x83, 0xEB, 0x83, +- 0xEB, 0x83, 0xA5, 0xDD, 0x21, 0x60, 0xE8, 0x62, 0xA2, 0xD1, 0x59, 0xD9, 0x21, 0x60, 0xC0, 0x65, +- 0xD5, 0x84, 0xDD, 0x7F, 0xA5, 0xDB, 0x65, 0x44, 0x22, 0x60, 0xAC, 0x62, 0xA2, 0xDB, 0x22, 0x60, +- 0xC8, 0x62, 0xA2, 0xDB, 0x57, 0xF5, 0xCB, 0xF3, 0xCC, 0xF1, 0x00, 0x63, 0xC0, 0x87, 0xCD, 0xF1, +- 0x5A, 0xFD, 0xC0, 0x85, 0x65, 0x47, 0xC4, 0x84, 0x07, 0xB5, 0x1C, 0x60, 0x10, 0x62, 0x16, 0x60, +- 0xAE, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xD0, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xD2, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0xE0, 0x60, +- 0x17, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, +- 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, +- 0xD0, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x57, 0xF5, 0x00, 0x64, 0x95, 0xFB, 0x96, 0xFB, 0x97, 0xFB, +- 0x75, 0xFB, 0x66, 0xF3, 0x00, 0x75, 0x00, 0x72, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x93, 0xC7, 0xF3, +- 0xED, 0xE2, 0xCC, 0x84, 0x5A, 0xFB, 0x0F, 0x60, 0xD2, 0x62, 0x00, 0x60, 0x04, 0x64, 0xA2, 0xDB, +- 0xE0, 0x60, 0x36, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD0, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x65, 0xF1, 0x23, 0x60, 0x02, 0x62, 0xA2, 0xD9, 0x22, 0x60, 0xAA, 0x65, +- 0xE2, 0x60, 0x58, 0x4D, 0x2F, 0x78, 0xFF, 0xFF, 0xE1, 0x60, 0x58, 0x4D, 0xA8, 0x78, 0xFF, 0xFF, +- 0xE2, 0x60, 0x58, 0x4D, 0x49, 0x78, 0xFF, 0xFF, 0x57, 0xF5, 0x00, 0xF4, 0x66, 0xF1, 0x06, 0xF8, +- 0x23, 0x60, 0x4C, 0x62, 0xA2, 0xD3, 0x07, 0xFA, 0x22, 0x60, 0xA2, 0x64, 0x40, 0x48, 0x10, 0x61, +- 0x00, 0x60, 0x00, 0x64, 0xE1, 0x60, 0x58, 0x4D, 0xE5, 0x78, 0xFF, 0xFF, 0x57, 0xF5, 0x3F, 0xFC, +- 0x5A, 0xF3, 0xC7, 0xF1, 0xAC, 0x83, 0x01, 0x64, 0x02, 0x02, 0x6C, 0xFB, 0x64, 0x43, 0x1B, 0x60, +- 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x04, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xCF, 0x83, 0x73, 0xF3, 0x5A, 0xFD, 0xDC, 0x84, 0x73, 0xFB, +- 0x5C, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0x5C, 0xFB, 0x03, 0x03, 0xE1, 0x60, 0x0A, 0x78, 0xFF, 0xFF, +- 0x0A, 0x64, 0x5C, 0xFB, 0xA2, 0x4C, 0x20, 0x27, 0xF8, 0x01, 0x46, 0x60, 0x50, 0x65, 0x72, 0x44, +- 0xD4, 0x80, 0xFF, 0xFF, 0xF2, 0x04, 0x5D, 0xFB, 0x40, 0x48, 0x95, 0xF3, 0x5E, 0xFB, 0x40, 0x4A, +- 0x96, 0xF3, 0x97, 0xF3, 0x40, 0x4C, 0x60, 0x41, 0x66, 0xF1, 0x40, 0x63, 0xAD, 0x80, 0xF0, 0xA3, +- 0x09, 0x02, 0x3C, 0x03, 0x2C, 0x41, 0x2A, 0x44, 0x40, 0x4C, 0x28, 0x44, 0x40, 0x4A, 0x00, 0x64, +- 0x40, 0x48, 0xF4, 0x01, 0xD1, 0x80, 0x01, 0x02, 0x31, 0x04, 0x10, 0xA3, 0x80, 0x60, 0x00, 0x65, +- 0xA5, 0x80, 0xCF, 0x83, 0x08, 0x02, 0x28, 0x44, 0x60, 0x88, 0x2A, 0x44, 0x70, 0x8A, 0x2C, 0x44, +- 0x70, 0x8C, 0xF1, 0x81, 0xF5, 0x01, 0xE7, 0xA3, 0x64, 0x44, 0x00, 0xA0, 0x00, 0x62, 0x02, 0x02, +- 0x00, 0x61, 0x1C, 0x00, 0xE0, 0x84, 0xDE, 0x82, 0xFD, 0x04, 0x42, 0xFE, 0xF8, 0x84, 0x62, 0x45, +- 0xC7, 0x83, 0x60, 0x45, 0x02, 0xFE, 0xD5, 0x84, 0x02, 0x05, 0x01, 0x05, 0x61, 0x44, 0xCF, 0x83, +- 0x60, 0x41, 0x08, 0x03, 0x28, 0x44, 0x60, 0x88, 0x2A, 0x44, 0x70, 0x8A, 0x2C, 0x44, 0x70, 0x8C, +- 0xF1, 0x81, 0xF1, 0x01, 0xCE, 0x82, 0xE9, 0x81, 0xFD, 0x02, 0xF1, 0x81, 0x61, 0x44, 0x00, 0xA8, +- 0xFF, 0xFF, 0x30, 0x03, 0x73, 0x40, 0x5D, 0xF3, 0xFF, 0xFF, 0x60, 0x47, 0xE8, 0x84, 0xE8, 0x84, +- 0x5E, 0xF3, 0x3F, 0xB5, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, +- 0xB4, 0x84, 0x61, 0x45, 0xD4, 0x84, 0xC0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, +- 0x64, 0x44, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x85, 0x61, 0x44, 0xD4, 0x80, +- 0xFF, 0xFF, 0x10, 0x03, 0x60, 0x53, 0xD4, 0x84, 0xFF, 0xFF, 0x75, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, +- 0x01, 0xB4, 0x75, 0xFB, 0x1F, 0x60, 0x14, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, +- 0x08, 0x28, 0xA2, 0xDB, 0xE6, 0x60, 0xA3, 0x78, 0xFF, 0xFF, 0xC1, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x04, 0x64, 0x03, 0xFA, 0x00, 0xF4, 0x09, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x3A, 0x1C, 0x00, +- 0x60, 0x43, 0x00, 0x36, 0x1C, 0x00, 0xE0, 0xA0, 0xDA, 0x85, 0x16, 0x07, 0x1F, 0x60, 0x1E, 0x61, +- 0xA1, 0xD1, 0xFF, 0xFF, 0xD3, 0x80, 0xCB, 0x83, 0x0F, 0x02, 0x07, 0x0E, 0x59, 0xD3, 0xA5, 0xD0, +- 0xDA, 0x85, 0xD0, 0x80, 0xFF, 0xFF, 0x08, 0x02, 0xF9, 0x1F, 0x13, 0x1E, 0xA5, 0xD0, 0x59, 0xD3, +- 0xFF, 0xFF, 0x90, 0x80, 0xFF, 0x22, 0x0D, 0x00, 0xE1, 0x60, 0x9C, 0x78, 0xFF, 0xFF, 0x1F, 0x60, +- 0x90, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x1F, 0x60, 0x40, 0x64, +- 0x02, 0x00, 0x1F, 0x60, 0x1E, 0x64, 0x22, 0x60, 0xBE, 0x62, 0xA2, 0xDB, 0x26, 0x46, 0x2F, 0xF2, +- 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, +- 0x30, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x67, 0xF1, 0x32, 0xF8, 0x68, 0xF1, 0x33, 0xF8, 0x69, 0xF1, +- 0x34, 0xF8, 0x50, 0x63, 0x2A, 0xFC, 0xAC, 0xF3, 0x19, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x88, 0xF3, +- 0x07, 0xFA, 0x00, 0xF4, 0x66, 0xF1, 0x06, 0xF8, 0x23, 0x60, 0x4C, 0x62, 0xA2, 0xD3, 0x07, 0xFA, +- 0x22, 0x60, 0xC6, 0x65, 0xE2, 0x60, 0x58, 0x4D, 0x2F, 0x78, 0xFF, 0xFF, 0x22, 0x60, 0xBE, 0x64, +- 0x40, 0x48, 0x10, 0x61, 0x00, 0x60, 0x00, 0x64, 0xE1, 0x60, 0x58, 0x4D, 0xE5, 0x78, 0xFF, 0xFF, +- 0x26, 0x46, 0x3F, 0xFC, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x26, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x20, 0x44, 0x80, 0x26, +- 0x11, 0x00, 0x80, 0xBC, 0x40, 0x40, 0x00, 0x64, 0x95, 0xFB, 0x96, 0xFB, 0x97, 0xFB, 0x75, 0xFB, +- 0x66, 0xF3, 0x00, 0x75, 0x00, 0x72, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x93, 0xC7, 0xF3, 0xED, 0xE2, +- 0xCC, 0x84, 0x5A, 0xFB, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD0, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x00, 0x64, 0x73, 0xFB, 0x75, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, +- 0x3E, 0x63, 0x16, 0x60, 0x60, 0x61, 0x59, 0xD1, 0x61, 0x46, 0x08, 0x1B, 0xFC, 0x1F, 0x22, 0x60, +- 0xDE, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x65, 0x00, 0x61, 0x17, 0x00, 0x16, 0x60, 0xA2, 0x61, +- 0x49, 0xD1, 0xCB, 0x83, 0xFD, 0x18, 0x63, 0x41, 0x04, 0xA1, 0x61, 0x45, 0x66, 0x43, 0x22, 0x60, +- 0xDE, 0x64, 0xDC, 0x84, 0x60, 0xFE, 0xA3, 0xD1, 0xDF, 0x83, 0xA0, 0xD9, 0xCD, 0x81, 0x20, 0xFE, +- 0xF8, 0x02, 0x66, 0x44, 0x16, 0x60, 0x62, 0x7C, 0xD0, 0x81, 0x5A, 0xF3, 0xC7, 0xF1, 0x22, 0x60, +- 0xDC, 0x63, 0x00, 0xA0, 0x64, 0x5F, 0xBD, 0xDB, 0x1B, 0x60, 0x94, 0x66, 0xA6, 0xD1, 0x02, 0x02, +- 0x01, 0x18, 0x01, 0xB9, 0x61, 0x44, 0x60, 0xFE, 0xA3, 0xDB, 0xFC, 0xA3, 0x65, 0x44, 0x03, 0xA4, +- 0xA3, 0xDB, 0xFF, 0xFF, 0x20, 0xFE, 0x2D, 0x58, 0xFF, 0xFF, 0x23, 0x60, 0x4E, 0x62, 0xA2, 0xDB, +- 0xCD, 0x81, 0x28, 0xD3, 0x5A, 0x88, 0xDC, 0x83, 0x39, 0x18, 0xFB, 0x03, 0x61, 0x40, 0x7F, 0x3A, +- 0x07, 0x00, 0x23, 0x60, 0x4E, 0x62, 0xA2, 0xD3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x00, 0xF4, +- 0x60, 0xFE, 0xA3, 0xD1, 0xDD, 0x81, 0xA1, 0xD8, 0x61, 0x40, 0x7F, 0x3A, 0x09, 0x00, 0x20, 0xFE, +- 0x23, 0x60, 0x4E, 0x62, 0xA2, 0xD3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x00, 0xF4, 0x60, 0xFE, +- 0xCF, 0x83, 0xA3, 0xD3, 0xDD, 0x81, 0xA1, 0xDA, 0xFF, 0xB4, 0x00, 0x7F, 0x15, 0x03, 0xDB, 0x83, +- 0x61, 0x40, 0x7F, 0x3A, 0x0B, 0x00, 0x20, 0xFE, 0x60, 0x45, 0x23, 0x60, 0x4E, 0x62, 0xA2, 0xD3, +- 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x65, 0x44, 0x00, 0xF4, 0x60, 0xFE, 0xA3, 0xD1, 0xDF, 0x83, +- 0xDD, 0x81, 0xCC, 0x84, 0xA1, 0xD8, 0xEC, 0x02, 0x20, 0xFE, 0xC3, 0x01, 0x23, 0x60, 0x4E, 0x62, +- 0xA2, 0xD1, 0xFD, 0xA1, 0xFF, 0xB1, 0xC1, 0x83, 0xA2, 0xDD, 0x2D, 0x58, 0xFF, 0xFF, 0x67, 0x5C, +- 0x11, 0x60, 0xF0, 0x61, 0xA1, 0xD3, 0xA5, 0xD9, 0x12, 0x18, 0x60, 0x43, 0x23, 0x60, 0x04, 0x64, +- 0xA5, 0xDB, 0x60, 0xFE, 0xA0, 0xDD, 0xFF, 0xFF, 0x20, 0xFE, 0xDC, 0x84, 0xCF, 0x83, 0xE3, 0x83, +- 0x59, 0xD1, 0xDC, 0x84, 0x60, 0xFE, 0xA0, 0xD9, 0xFF, 0xFF, 0x20, 0xFE, 0xF9, 0x1F, 0x2D, 0x58, +- 0xFF, 0xFF, 0x20, 0x40, 0x20, 0x2A, 0x0D, 0x00, 0x12, 0x60, 0xB8, 0x62, 0xA2, 0xD1, 0x50, 0xF3, +- 0x23, 0x60, 0x39, 0x63, 0x60, 0xFE, 0xA3, 0xD9, 0xDF, 0x83, 0x60, 0x47, 0xA3, 0xDB, 0xFF, 0xFF, +- 0x20, 0xFE, 0x2D, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, 0x25, 0x00, 0x45, 0x48, +- 0x00, 0x60, 0x10, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, 0x1D, 0x03, 0xF2, 0x60, +- 0x02, 0x64, 0x24, 0xFA, 0x00, 0x60, 0x48, 0x61, 0x28, 0x44, 0x59, 0xDA, 0x03, 0x64, 0x38, 0x43, +- 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, 0x39, 0x44, 0x59, 0xDA, 0x06, 0x64, 0x23, 0xFA, +- 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xCA, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, +- 0x40, 0x26, 0x51, 0x00, 0x45, 0x48, 0x00, 0x60, 0x68, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, +- 0xFF, 0xFF, 0x49, 0x03, 0xF2, 0x60, 0x01, 0x64, 0x24, 0xFA, 0x02, 0x60, 0x00, 0x61, 0x46, 0x4A, +- 0x38, 0x44, 0x54, 0x94, 0x03, 0x64, 0x01, 0x02, 0x09, 0x00, 0x06, 0x63, 0x4A, 0x61, 0x38, 0x46, +- 0xBD, 0xD0, 0xCC, 0x84, 0x2A, 0x46, 0x59, 0xD8, 0xFA, 0x02, 0x06, 0x00, 0xDA, 0x81, 0x38, 0x43, +- 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, 0x05, 0x63, 0x28, 0x44, 0x02, 0xA8, 0x25, 0xFA, +- 0x07, 0x02, 0x03, 0x64, 0x39, 0x43, 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, 0x08, 0x63, +- 0x22, 0x60, 0x28, 0x7C, 0x28, 0x44, 0x03, 0xA8, 0xA4, 0xD3, 0x0F, 0x03, 0xE8, 0x85, 0xC7, 0x85, +- 0x60, 0x43, 0xFE, 0xA3, 0x22, 0x60, 0x2A, 0x64, 0x58, 0xD1, 0xD9, 0x81, 0xA1, 0xD8, 0x7E, 0x2A, +- 0x02, 0x00, 0x00, 0xF4, 0x02, 0x61, 0xF8, 0x1F, 0x65, 0x43, 0x2A, 0x46, 0x23, 0xFC, 0x1B, 0x60, +- 0xDA, 0x62, 0x1B, 0x60, 0xCA, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, +- 0x1C, 0x00, 0x45, 0x48, 0x00, 0x60, 0x06, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, +- 0x14, 0x03, 0x02, 0x64, 0x23, 0xFA, 0xF2, 0x60, 0x00, 0x64, 0x5A, 0xDA, 0x28, 0x44, 0x5A, 0xDA, +- 0xFF, 0xFF, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xCA, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, +- 0x32, 0x40, 0x40, 0x26, 0x3E, 0x00, 0x7C, 0xF3, 0x67, 0x43, 0xDC, 0x84, 0xCC, 0x84, 0x39, 0x03, +- 0x60, 0x46, 0x0A, 0x02, 0x7C, 0xFD, 0x00, 0x60, 0x46, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, +- 0xFF, 0xFF, 0x66, 0x44, 0x7C, 0xFB, 0x2E, 0x03, 0x46, 0x4B, 0x1E, 0x60, 0xD8, 0x61, 0x18, 0x64, +- 0x23, 0xFA, 0xF1, 0x60, 0x00, 0x64, 0x24, 0xFA, 0x4A, 0x65, 0xA2, 0xFF, 0x2C, 0x63, 0x00, 0x64, +- 0x59, 0xD1, 0xA2, 0xDB, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, +- 0xF7, 0x1F, 0x12, 0x63, 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, +- 0x04, 0x65, 0xF8, 0x1F, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xCA, 0x64, 0xA2, 0xDB, 0x2B, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0xA6, 0xFE, 0x00, 0x64, +- 0x7C, 0xFB, 0xA3, 0xFF, 0xC7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0xA6, 0xFE, 0xB8, 0x05, 0xA7, 0xFE, +- 0x0A, 0x05, 0xA5, 0xFE, 0x03, 0x04, 0xE3, 0x60, 0xD3, 0x78, 0xFF, 0xFF, 0xA4, 0xFE, 0xF2, 0x04, +- 0xE4, 0x60, 0x69, 0x78, 0xFF, 0xFF, 0x36, 0x45, 0x17, 0x60, 0x52, 0x64, 0x44, 0xD7, 0xFF, 0xFF, +- 0xFF, 0xFF, 0x28, 0xF3, 0x7E, 0xF1, 0x60, 0x47, 0x07, 0xB4, 0x4E, 0xFB, 0x01, 0x61, 0x03, 0x03, +- 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x9D, 0x84, 0xA1, 0x80, 0xA0, 0x83, 0x1A, 0x03, 0x7E, 0xFD, +- 0x0F, 0x60, 0xF4, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x7E, 0xF1, 0x31, 0x44, 0x64, 0x40, 0xFF, 0x26, 0x09, 0x00, 0xFE, 0xB4, 0x40, 0x51, 0x01, 0x7C, +- 0xBC, 0xF9, 0x49, 0xF3, 0x01, 0x63, 0x60, 0x40, 0xFF, 0x26, 0x49, 0xFD, 0xC7, 0x60, 0x2E, 0x78, +- 0xFF, 0xFF, 0xE3, 0x60, 0xD3, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0xB6, 0x63, 0xBD, 0xD3, 0xBD, 0xD1, +- 0xBD, 0xD1, 0xB0, 0x84, 0xB0, 0x84, 0xFF, 0xFF, 0x07, 0x02, 0x6B, 0xFB, 0x31, 0x44, 0xFE, 0xB4, +- 0x40, 0x51, 0x0D, 0x64, 0x05, 0xFB, 0x3F, 0x00, 0x28, 0xF3, 0x7E, 0xF1, 0x60, 0x47, 0x64, 0x41, +- 0x07, 0xB1, 0x07, 0xB4, 0x08, 0x24, 0x67, 0x4C, 0x4E, 0xFB, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, +- 0xE1, 0x81, 0xFD, 0x02, 0xA1, 0x80, 0xB1, 0x83, 0x2E, 0x02, 0x7E, 0xFD, 0x1F, 0x60, 0xAA, 0x62, +- 0xA2, 0xD3, 0xC5, 0xFB, 0x65, 0xFB, 0x7E, 0xF3, 0xFF, 0xFF, 0xCC, 0x85, 0xA4, 0x80, 0x7E, 0xFB, +- 0x17, 0x02, 0x1B, 0x60, 0xC4, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x46, 0x5E, +- 0x31, 0x44, 0x01, 0xBC, 0x40, 0x51, 0xED, 0xE2, 0x0F, 0x4E, 0xCE, 0x60, 0x58, 0x4F, 0x07, 0x78, +- 0xFF, 0xFF, 0x0E, 0x4F, 0x01, 0x65, 0xE2, 0x60, 0x58, 0x4E, 0xDD, 0x78, 0xFF, 0xFF, 0x08, 0x00, +- 0x0F, 0x60, 0xD6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0xE5, 0x60, 0x16, 0x78, 0xFF, 0xFF, 0xD7, 0xFE, 0xC7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0x2E, 0xF5, +- 0x27, 0xF2, 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, +- 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, +- 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, +- 0x63, 0x46, 0xE8, 0x1B, 0x88, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x28, 0x02, 0x14, 0x60, +- 0xD0, 0x62, 0xA2, 0xD3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x04, 0x03, 0xD3, 0x80, +- 0xD9, 0x81, 0xFA, 0x02, 0x09, 0x00, 0xA1, 0xDD, 0x14, 0x60, 0xD0, 0x62, 0xD9, 0x84, 0xA2, 0xDB, +- 0x4A, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xA2, 0xDB, 0x66, 0x45, 0x63, 0x46, 0x06, 0xF2, 0xFF, 0x60, +- 0x01, 0x7C, 0xA0, 0x9C, 0x06, 0xF8, 0x65, 0x46, 0x71, 0xF3, 0x60, 0x40, 0x10, 0x2A, 0x03, 0x00, +- 0xCC, 0x84, 0x80, 0x2B, 0x71, 0xFB, 0xE4, 0x60, 0x58, 0x4E, 0x9D, 0x78, 0xFF, 0xFF, 0xAB, 0x01, +- 0x2E, 0xF5, 0x25, 0x60, 0x28, 0x61, 0x28, 0xF0, 0xFF, 0xFF, 0xA1, 0xD9, 0x27, 0xF2, 0x12, 0x60, +- 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, +- 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, +- 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, +- 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, +- 0x88, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x13, 0x02, 0x63, 0x46, 0x06, 0xF2, 0xFF, 0xFF, +- 0x02, 0xB0, 0x08, 0xBC, 0x0D, 0x03, 0x06, 0xFA, 0xE4, 0x60, 0x58, 0x4E, 0x9D, 0x78, 0xFF, 0xFF, +- 0x0F, 0x60, 0xE8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x6A, 0x01, 0x7E, 0xF1, 0xFF, 0xFF, 0x64, 0x41, 0x07, 0xB1, 0xFF, 0xFF, 0x08, 0x24, 0x67, 0x4C, +- 0x1B, 0x60, 0xC4, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x46, 0x5E, 0x1F, 0x60, +- 0xAA, 0x62, 0xA2, 0xD3, 0xC5, 0xFB, 0x65, 0xFB, 0x1F, 0x60, 0xB6, 0x63, 0xBD, 0xD1, 0xCB, 0xF9, +- 0x67, 0xF9, 0xBD, 0xD1, 0xCC, 0xF9, 0x68, 0xF9, 0xA3, 0xD1, 0xCD, 0xF9, 0x69, 0xF9, 0x01, 0x64, +- 0x6B, 0xFB, 0x31, 0x44, 0x21, 0xBC, 0x40, 0x51, 0x20, 0x44, 0x01, 0x65, 0x34, 0x80, 0x01, 0x64, +- 0x51, 0xFB, 0x21, 0x60, 0x50, 0x64, 0x52, 0xFB, 0x0F, 0x4E, 0xE8, 0x60, 0x58, 0x4F, 0x02, 0x78, +- 0xFF, 0xFF, 0x0E, 0x4F, 0xC7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0x0E, 0x57, 0x63, 0x46, 0x43, 0x47, +- 0x1E, 0xF2, 0x72, 0xF2, 0x02, 0x1B, 0x01, 0x1B, 0x0C, 0x00, 0x60, 0x46, 0x1B, 0x60, 0xDA, 0x64, +- 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, 0x75, 0x78, 0xFF, 0xFF, 0x27, 0x46, 0x72, 0xF2, 0xFF, 0xFF, +- 0xF4, 0x1B, 0x37, 0x58, 0xFF, 0xFF, 0x1B, 0x60, 0xAC, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, +- 0x60, 0x46, 0x0E, 0xF2, 0x5B, 0x03, 0x60, 0x40, 0xF0, 0x37, 0x48, 0x00, 0xFF, 0x37, 0x3D, 0x00, +- 0xFD, 0x37, 0x35, 0x00, 0x18, 0x37, 0x29, 0x00, 0xFE, 0x37, 0x2C, 0x00, 0xF8, 0x37, 0x0A, 0x00, +- 0x60, 0x47, 0xFF, 0xB5, 0x0F, 0x60, 0xD0, 0x62, 0x46, 0xD1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x1B, 0x60, 0xDA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xD6, 0x01, 0x06, 0xB4, 0xFD, 0x7F, 0x0E, 0xFA, +- 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xB2, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF9, 0xFE, 0xC6, 0x01, 0xDB, 0x60, 0x58, 0x4F, 0xB7, 0x78, +- 0xFF, 0xFF, 0x14, 0x00, 0xDE, 0x60, 0x58, 0x4F, 0x99, 0x78, 0xFF, 0xFF, 0xBC, 0x03, 0x23, 0xF0, +- 0x60, 0x40, 0x04, 0x26, 0xE2, 0x1B, 0x02, 0x26, 0xE0, 0x18, 0xA2, 0xFF, 0x02, 0xF0, 0x09, 0x60, +- 0x08, 0x64, 0xD0, 0x80, 0x90, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0x90, 0xFB, 0x1B, 0x60, 0xDA, 0x64, +- 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, 0x75, 0x78, 0xFF, 0xFF, 0xA5, 0x01, 0xAC, 0xFE, 0x09, 0x05, +- 0xAD, 0xFE, 0x10, 0x05, 0xAE, 0xFE, 0x9F, 0x05, 0xAF, 0xFE, 0x3A, 0x05, 0xC7, 0x60, 0x2E, 0x78, +- 0xFF, 0xFF, 0x0F, 0x60, 0xCE, 0x62, 0xA2, 0xD1, 0x20, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0xF4, 0x01, 0x10, 0x60, 0x02, 0x65, 0x03, 0x61, 0x07, 0x00, 0xA2, 0xDD, 0x58, 0x4F, +- 0x64, 0x58, 0xFF, 0xFF, 0x00, 0xB9, 0xFF, 0xFF, 0x08, 0x03, 0x00, 0x63, 0xA5, 0xD1, 0x5A, 0xD3, +- 0xDA, 0x85, 0x00, 0xA8, 0xCD, 0x81, 0xF2, 0x02, 0xF8, 0x02, 0xE0, 0x01, 0x0F, 0x60, 0xCC, 0x62, +- 0x0F, 0x60, 0xF2, 0x65, 0xE5, 0x60, 0x4E, 0x63, 0x00, 0x64, 0x5A, 0xDB, 0xD6, 0x80, 0xFF, 0xFF, +- 0x04, 0x03, 0x5A, 0xDB, 0x5A, 0xDB, 0x5A, 0xDD, 0xF9, 0x01, 0x10, 0x60, 0x00, 0x65, 0x00, 0x64, +- 0x5A, 0xDB, 0xD6, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x5A, 0xDD, 0xFB, 0x01, 0x2F, 0x58, 0xFF, 0xFF, +- 0x0F, 0x60, 0xD0, 0x64, 0x40, 0x41, 0x0F, 0x60, 0xCE, 0x63, 0xA3, 0xD1, 0x00, 0x64, 0xD0, 0x80, +- 0x06, 0x61, 0x08, 0x03, 0xBD, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0xB0, 0x84, 0xCD, 0x81, 0xA3, 0xDB, +- 0x06, 0xA3, 0xF9, 0x02, 0x0F, 0x60, 0xF4, 0x63, 0xA3, 0xD1, 0x00, 0x64, 0xD0, 0x80, 0x07, 0x61, +- 0x19, 0x03, 0xBD, 0xDB, 0x64, 0x44, 0xFE, 0xA3, 0x02, 0xA3, 0xCD, 0x81, 0xE8, 0x84, 0xE3, 0x03, +- 0x02, 0x05, 0xE1, 0x03, 0xF9, 0x01, 0x78, 0xFB, 0x7A, 0xFD, 0x61, 0x5C, 0xA3, 0xD3, 0x79, 0xF9, +- 0x03, 0x18, 0x58, 0x4F, 0x60, 0x58, 0xFF, 0xFF, 0x7A, 0xF3, 0x79, 0xF1, 0x60, 0x43, 0x78, 0xF3, +- 0x64, 0x41, 0xEA, 0x01, 0x21, 0x43, 0x0F, 0x60, 0xF4, 0x65, 0xD7, 0x80, 0xBD, 0xD1, 0xBD, 0xD3, +- 0x03, 0x02, 0xC7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0xA0, 0x84, 0xBD, 0xD1, 0x43, 0x41, 0xF5, 0x03, +- 0xE5, 0x60, 0x53, 0x64, 0x64, 0x58, 0x40, 0x4F, 0x2A, 0xF0, 0x83, 0x60, 0xFF, 0x65, 0x64, 0x47, +- 0x03, 0x2B, 0x01, 0x00, 0x17, 0x00, 0x03, 0x26, 0x03, 0xAC, 0x60, 0x47, 0xA4, 0x84, 0x2A, 0xFA, +- 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x64, 0x41, 0xCB, 0xF3, +- 0x2F, 0xFA, 0x60, 0x43, 0xCC, 0xF3, 0x30, 0xFA, 0xCD, 0xF1, 0x31, 0xF8, 0x32, 0xFC, 0x33, 0xFA, +- 0x34, 0xF8, 0x19, 0x00, 0x60, 0x47, 0xA4, 0x84, 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, +- 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x36, 0xF2, 0x32, 0xFA, 0x37, 0xF2, 0x33, 0xFA, 0x38, 0xF2, +- 0x34, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0x36, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0x37, 0xFA, 0xCD, 0xF3, +- 0x31, 0xFA, 0x38, 0xFA, 0x64, 0x41, 0x1C, 0xF2, 0x13, 0xFA, 0x00, 0xF4, 0x0D, 0xF2, 0xFF, 0xFF, +- 0x60, 0x40, 0x80, 0x2B, 0x29, 0x00, 0x26, 0x46, 0x04, 0x63, 0x03, 0xFC, 0x00, 0xF4, 0x0D, 0xF2, +- 0x06, 0xFA, 0xE6, 0x60, 0x58, 0x4E, 0xF4, 0x78, 0xFF, 0xFF, 0xFF, 0xA0, 0x59, 0xF5, 0x1A, 0x02, +- 0x39, 0xF2, 0x26, 0x46, 0x3F, 0xFA, 0x00, 0xF4, 0x00, 0x60, 0x81, 0x67, 0x0D, 0xFA, 0x7C, 0x64, +- 0x01, 0xFA, 0x26, 0x46, 0x00, 0x64, 0x3E, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x9A, 0x64, +- 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, +- 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xF0, 0x42, 0x64, 0xD0, 0x80, +- 0xFF, 0xFF, 0x01, 0x04, 0x3F, 0xFA, 0x1C, 0xF2, 0x13, 0xFA, 0x26, 0xF2, 0x27, 0xF0, 0x60, 0x47, +- 0x00, 0xF4, 0x1F, 0xFA, 0x64, 0x47, 0x20, 0xFA, 0x61, 0x44, 0x21, 0xFA, 0x01, 0x67, 0x0D, 0xFA, +- 0x10, 0x61, 0x1F, 0x60, 0x6C, 0x64, 0x1E, 0x63, 0x58, 0xD1, 0xCD, 0x81, 0xBD, 0xD8, 0xFC, 0x02, +- 0x9B, 0xF1, 0xB8, 0xF1, 0x64, 0x5E, 0x64, 0x5F, 0x44, 0x63, 0xBD, 0xDA, 0x1F, 0x60, 0x66, 0x62, +- 0xA2, 0xD3, 0xFF, 0xFF, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x09, 0xBC, 0x4A, 0xD3, 0x60, 0x45, +- 0x60, 0x40, 0x01, 0x36, 0x03, 0x64, 0x02, 0x36, 0x01, 0x64, 0xB4, 0x84, 0x06, 0xA2, 0xA2, 0xD1, +- 0xBD, 0xDA, 0x64, 0x47, 0xBD, 0xDA, 0xB5, 0xF3, 0xB6, 0xF1, 0x60, 0x47, 0xBD, 0xDA, 0x64, 0x47, +- 0xC3, 0xF1, 0xBD, 0xDA, 0x64, 0x44, 0xBD, 0xDA, 0x26, 0x46, 0x00, 0x64, 0x23, 0xF0, 0x3B, 0xF0, +- 0x64, 0x40, 0x10, 0x2A, 0x06, 0x00, 0xC0, 0x67, 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, +- 0x10, 0xBC, 0x3E, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0x9A, 0x64, 0xA2, 0xDB, 0x26, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0x00, 0x66, 0x46, 0x46, +- 0x2F, 0x58, 0xFF, 0xFF, 0x04, 0x60, 0x5C, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, +- 0x66, 0x44, 0x59, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x2F, 0x58, 0xFF, 0xFF, 0x59, 0xF5, 0xAC, 0xF1, +- 0x19, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x08, 0x64, 0x2A, 0xFA, 0x80, 0x7E, 0xF8, 0x7F, 0x0E, 0xFA, +- 0x88, 0xF1, 0x07, 0xF8, 0x01, 0x60, 0x60, 0x67, 0x2C, 0xFA, 0x1D, 0x60, 0x00, 0x67, 0x2D, 0xFA, +- 0x01, 0x60, 0x00, 0x67, 0x2E, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, 0x32, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, +- 0x33, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x34, 0xF8, 0x00, 0x63, 0x3B, 0xFC, 0x3D, 0xFC, 0x01, 0x64, +- 0x3A, 0xFA, 0x66, 0x64, 0x39, 0xFA, 0x3C, 0xFC, 0xAA, 0x60, 0xAA, 0x64, 0x00, 0xF4, 0x02, 0xFA, +- 0x00, 0x60, 0x03, 0x64, 0x5A, 0xDA, 0x1D, 0x60, 0x60, 0x64, 0x5A, 0xDA, 0x01, 0x60, 0x00, 0x64, +- 0x5A, 0xDA, 0x82, 0x7F, 0x24, 0x7E, 0x08, 0xFA, 0x01, 0x60, 0x01, 0x64, 0x0A, 0xFA, 0x00, 0x64, +- 0x0E, 0xFA, 0x2D, 0x58, 0xFF, 0xFF, 0x59, 0xF5, 0x3D, 0xF2, 0x3C, 0xF2, 0xCC, 0x83, 0x00, 0xA8, +- 0x03, 0x03, 0x08, 0x28, 0x3D, 0xFC, 0x45, 0x00, 0x3D, 0xFA, 0x3A, 0xF2, 0x3B, 0xF0, 0x00, 0x63, +- 0x00, 0xF4, 0x07, 0xFC, 0x01, 0xB0, 0x0B, 0xFA, 0x1A, 0x03, 0x1F, 0xF8, 0xFF, 0xFF, 0x1B, 0x60, +- 0xDA, 0x62, 0x18, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x1F, 0xF2, 0x1E, 0xF0, 0x59, 0xF5, 0x00, 0xA8, 0x3B, 0xF8, 0xD0, 0x80, 0x06, 0x03, +- 0x05, 0x03, 0x04, 0x60, 0x5C, 0x63, 0x0F, 0x64, 0x3A, 0xFA, 0x39, 0xFC, 0x00, 0xF4, 0x00, 0x64, +- 0x06, 0xFA, 0xE6, 0x60, 0x58, 0x4E, 0xF4, 0x78, 0xFF, 0xFF, 0x59, 0xF5, 0x00, 0xF4, 0x81, 0x60, +- 0x00, 0x64, 0x06, 0xFA, 0x32, 0x47, 0x04, 0xBC, 0x07, 0xFA, 0xB8, 0xF1, 0x00, 0x7F, 0x64, 0x5E, +- 0x09, 0xFA, 0x59, 0xF5, 0x00, 0x64, 0x15, 0xFA, 0x39, 0xF2, 0x3F, 0xFA, 0x1B, 0x60, 0xDA, 0x62, +- 0x1B, 0x60, 0x88, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xE1, 0x60, 0x0D, 0x78, 0xFF, 0xFF, 0x66, 0x45, 0x0E, 0xF2, 0x0F, 0xF0, 0x10, 0xF0, +- 0x64, 0x41, 0x01, 0xA8, 0x59, 0xF5, 0x09, 0x02, 0xAD, 0x83, 0x64, 0x44, 0xAC, 0x84, 0x08, 0x24, +- 0x0A, 0x63, 0x3C, 0xFC, 0x3D, 0xFC, 0x1A, 0x02, 0x2D, 0x00, 0x03, 0x3A, 0x03, 0x00, 0x00, 0x64, +- 0x3C, 0xFA, 0x29, 0x00, 0x04, 0x3A, 0x09, 0x00, 0x0A, 0x64, 0x3C, 0xFA, 0x01, 0x64, 0x3A, 0xFA, +- 0x00, 0xF4, 0x00, 0x64, 0x1F, 0xFA, 0x1E, 0xFA, 0x1E, 0x00, 0x02, 0x3A, 0x1E, 0x00, 0x64, 0x44, +- 0xAD, 0x83, 0xAC, 0x84, 0x02, 0x03, 0x3C, 0xFC, 0x3D, 0xFC, 0x15, 0x03, 0x3A, 0xFA, 0xF8, 0x65, +- 0x52, 0x63, 0x64, 0x44, 0x01, 0x36, 0x0D, 0x00, 0x12, 0xA3, 0x64, 0x40, 0x02, 0x2A, 0x02, 0x00, +- 0xC7, 0x83, 0xC7, 0x83, 0x64, 0x40, 0x08, 0x2A, 0x01, 0x00, 0xC7, 0x83, 0x64, 0x40, 0x04, 0x26, +- 0xC7, 0x83, 0x39, 0xFC, 0x00, 0x64, 0x2E, 0x58, 0xFF, 0xFF, 0x3B, 0xF0, 0x3A, 0xF2, 0x65, 0x46, +- 0x06, 0xF2, 0x40, 0x47, 0x1D, 0x18, 0x32, 0x47, 0x07, 0xFA, 0x24, 0x7E, 0x82, 0x7F, 0x08, 0xFA, +- 0x01, 0x60, 0x01, 0x63, 0xB8, 0xF3, 0x0A, 0xFC, 0x00, 0x7F, 0x09, 0xFA, 0x27, 0x40, 0x01, 0x2A, +- 0x0F, 0x00, 0x1F, 0xF8, 0x1B, 0x60, 0xDA, 0x62, 0x18, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, +- 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x1E, 0xF0, 0x59, 0xF5, 0x3B, 0xF8, 0x65, 0x46, +- 0x27, 0x40, 0x02, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x13, 0x00, 0x6E, 0x61, 0xFF, 0x60, 0xFE, 0x64, +- 0x00, 0x60, 0x0E, 0x63, 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, 0x01, 0x60, 0xEE, 0x63, 0x00, 0xF4, +- 0x02, 0x61, 0x58, 0xD1, 0x59, 0xD8, 0x7E, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x02, 0x61, 0xF9, 0x1F, +- 0x27, 0x40, 0x04, 0x26, 0x1B, 0x00, 0x46, 0x4B, 0x1B, 0x60, 0x88, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, +- 0x00, 0xA8, 0x60, 0x46, 0x0E, 0x03, 0x89, 0xF0, 0xE7, 0x60, 0x58, 0x4D, 0xAE, 0x78, 0xFF, 0xFF, +- 0x65, 0x44, 0xAC, 0x86, 0xFF, 0xFF, 0x08, 0x03, 0xE7, 0x60, 0x58, 0x4D, 0xAE, 0x78, 0xFF, 0xFF, +- 0x04, 0x00, 0x2B, 0x46, 0x82, 0xFC, 0x00, 0xF4, 0x82, 0xFC, 0x00, 0xF4, 0x27, 0x40, 0x08, 0x26, +- 0x1A, 0x00, 0x46, 0x4B, 0x1B, 0x60, 0xC4, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, +- 0x0E, 0x03, 0x89, 0xF0, 0xE7, 0x60, 0x58, 0x4D, 0xAE, 0x78, 0xFF, 0xFF, 0x65, 0x44, 0xAC, 0x86, +- 0xFF, 0xFF, 0x08, 0x03, 0xE7, 0x60, 0x58, 0x4D, 0xAE, 0x78, 0xFF, 0xFF, 0x04, 0x00, 0x65, 0x46, +- 0x02, 0xFA, 0x00, 0xF4, 0x82, 0xFC, 0x01, 0x64, 0x2E, 0x58, 0xFF, 0xFF, 0x01, 0x61, 0x02, 0x64, +- 0x7A, 0x63, 0x58, 0xD0, 0xAB, 0x46, 0xA0, 0xD8, 0xAB, 0x46, 0xFB, 0x1F, 0xAB, 0x46, 0x00, 0xF4, +- 0xCD, 0x81, 0xAB, 0x46, 0x00, 0xF4, 0xF3, 0x02, 0x2D, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0x2A, 0x61, +- 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x58, 0xFB, 0x04, 0x64, 0x03, 0xFA, +- 0x67, 0x44, 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0x32, 0xFA, 0x33, 0xFA, 0x34, 0xFA, 0x12, 0x60, +- 0x80, 0x64, 0x88, 0xF1, 0x0E, 0xFA, 0x07, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x11, 0x60, 0xD8, 0x63, +- 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x08, 0x64, 0xBD, 0xDB, 0x04, 0x64, 0xBD, 0xDB, 0x06, 0x64, +- 0xA3, 0xDB, 0x10, 0x60, 0x06, 0x62, 0xEA, 0x60, 0x08, 0x64, 0xA2, 0xDB, 0x11, 0x60, 0xE4, 0x63, +- 0x00, 0x64, 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x0C, 0x64, 0xBD, 0xDB, 0x08, 0x64, 0xBD, 0xDB, +- 0x06, 0x64, 0xA3, 0xDB, 0x10, 0x60, 0x0A, 0x62, 0xEA, 0x60, 0x12, 0x64, 0xA2, 0xDB, 0x0F, 0x60, +- 0xFC, 0x62, 0xE9, 0x60, 0xF2, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x25, 0x60, 0x2A, 0x62, 0xA2, 0xDB, +- 0x2F, 0x58, 0xFF, 0xFF, 0x58, 0xF5, 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, +- 0x31, 0xF8, 0xAC, 0xF1, 0x19, 0xF8, 0xEA, 0x60, 0x58, 0x4E, 0x1C, 0x78, 0xFF, 0xFF, 0x30, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x16, 0x60, 0xCC, 0x61, +- 0xA1, 0xD3, 0xFF, 0xFF, 0x59, 0x18, 0x58, 0xF5, 0x40, 0x64, 0x2A, 0xFA, 0x52, 0xF3, 0x00, 0xF4, +- 0x60, 0x43, 0xBD, 0xD1, 0x04, 0x65, 0x64, 0x47, 0xA5, 0xDA, 0x64, 0x41, 0xDD, 0x81, 0xE9, 0x81, +- 0x62, 0x44, 0x04, 0x03, 0xBD, 0xD1, 0xCD, 0x81, 0x58, 0xD8, 0xFC, 0x02, 0x58, 0x8B, 0x21, 0x60, +- 0x8E, 0x63, 0xA3, 0xD1, 0x2B, 0x44, 0xC8, 0x84, 0x64, 0x41, 0xFF, 0xB1, 0x61, 0x45, 0x03, 0xA1, +- 0xE9, 0x81, 0x41, 0x4C, 0xBD, 0xD1, 0xCD, 0x81, 0x58, 0xD8, 0xFC, 0x02, 0x2B, 0xD2, 0x2B, 0x43, +- 0x60, 0x47, 0x01, 0x7E, 0x52, 0xF1, 0xA3, 0xDA, 0xA4, 0xD3, 0xCB, 0x83, 0x44, 0x8B, 0xF8, 0x84, +- 0x2C, 0x41, 0x0C, 0x04, 0xBE, 0xD2, 0xFF, 0xFF, 0x60, 0x47, 0xBE, 0xDA, 0x00, 0x7E, 0xA3, 0xD2, +- 0x60, 0x45, 0x00, 0x7F, 0xB4, 0x84, 0xCD, 0x81, 0xBD, 0xDA, 0xF4, 0x02, 0x58, 0xF5, 0x2B, 0x44, +- 0x04, 0xA4, 0x3F, 0xFA, 0x65, 0xF3, 0x64, 0xFB, 0x16, 0x60, 0xCE, 0x61, 0x01, 0x64, 0x52, 0xF1, +- 0xA1, 0xDB, 0x65, 0xFB, 0xA4, 0xD3, 0x04, 0x65, 0x51, 0xF3, 0x01, 0x18, 0x0C, 0x65, 0xF3, 0xB4, +- 0xB4, 0x84, 0x51, 0xFB, 0x02, 0xB0, 0xFF, 0xFF, 0x16, 0x03, 0x65, 0xF3, 0xFF, 0xFF, 0x60, 0x47, +- 0x0F, 0xB4, 0x65, 0xFB, 0x01, 0x03, 0x0F, 0x00, 0xE9, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0x51, 0xF1, +- 0x65, 0xF3, 0x64, 0x40, 0x02, 0x26, 0xF8, 0x01, 0xF3, 0xA0, 0x04, 0xA4, 0x01, 0x04, 0xF1, 0xA4, +- 0x10, 0x36, 0xF2, 0x01, 0x65, 0xFB, 0x65, 0xF3, 0x16, 0x60, 0xCC, 0x61, 0xA1, 0xD1, 0xCC, 0x84, +- 0x01, 0x61, 0x08, 0x24, 0x03, 0x00, 0xE1, 0x81, 0xCC, 0x84, 0xFB, 0x01, 0xA1, 0x84, 0x51, 0xF1, +- 0xE7, 0x03, 0x16, 0x60, 0xCE, 0x61, 0xA1, 0xDB, 0x00, 0x00, 0x65, 0xF3, 0x01, 0x61, 0xCC, 0x84, +- 0xFF, 0xFF, 0x02, 0x03, 0xE1, 0x81, 0xFB, 0x01, 0x9A, 0xF3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, +- 0xD7, 0x03, 0x31, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xE4, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xE8, 0x60, +- 0x95, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x65, 0xF1, 0x1C, 0x60, 0x00, 0x62, +- 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xE4, 0x62, 0x20, 0x60, +- 0x00, 0x64, 0xA2, 0xDB, 0xE8, 0x60, 0xC8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0xBE, 0xFE, 0x0F, 0x60, 0xCE, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x58, 0xF5, 0x1B, 0x60, 0xDA, 0x62, +- 0x1B, 0x60, 0x8E, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x00, 0x64, 0x4F, 0xFB, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, +- 0xE8, 0x60, 0xF2, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x33, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x2F, 0x58, 0xFF, 0xFF, 0x34, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0xA6, 0xF1, 0x11, 0x60, 0xDC, 0x62, 0xA2, 0xD9, 0x1C, 0x60, 0x10, 0x62, 0x11, 0x60, +- 0xD8, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xA7, 0xF1, 0x11, 0x60, +- 0xE8, 0x62, 0xA2, 0xD9, 0x1C, 0x60, 0x0E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xFD, 0x1B, 0x1C, 0x60, +- 0x10, 0x62, 0x11, 0x60, 0xE4, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x60, 0x08, 0x64, 0xA2, 0xDB, 0xE9, 0x60, 0x23, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x4F, 0xF1, 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x64, 0x40, 0xFF, 0x26, 0x03, 0x00, 0xE8, 0x60, 0x77, 0x78, 0xFF, 0xFF, 0x02, 0x0A, 0x00, 0x64, +- 0x4F, 0xFB, 0xA8, 0xF1, 0x11, 0x60, 0xE8, 0x62, 0xA2, 0xD9, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x60, +- 0x0C, 0x64, 0xA2, 0xDB, 0xE9, 0x60, 0x49, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, 0x10, 0x62, +- 0x11, 0x60, 0xE4, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, +- 0xFF, 0xFF, 0x0F, 0x60, 0xE2, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x0C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x10, 0x62, 0x11, 0x60, 0xE4, 0x64, 0xA2, 0xDB, +- 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x14, 0x00, 0xFF, 0x60, 0xF7, 0x64, 0xA0, 0x84, +- 0xA2, 0xDB, 0x4F, 0xF3, 0xDB, 0x0A, 0x00, 0xA0, 0x00, 0x64, 0x02, 0x03, 0x4F, 0xFB, 0xD6, 0x01, +- 0x1C, 0x60, 0x10, 0x62, 0x11, 0x60, 0xD8, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0xE8, 0x60, 0x77, 0x78, 0xFF, 0xFF, 0x35, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x1C, 0x60, +- 0x10, 0x62, 0x11, 0x60, 0xD8, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x51, 0xF3, 0xFF, 0xFF, 0xE3, 0xB4, 0x51, 0xFB, 0x16, 0x60, 0xCA, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xFE, 0xB4, 0xA2, 0xDB, 0x00, 0x64, 0x25, 0x60, 0x2A, 0x62, 0xA2, 0xDB, 0x0F, 0x60, 0xE2, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0E, 0x04, 0x32, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, +- 0xE4, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xE9, 0x60, 0x8E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x64, 0xF1, 0x65, 0xF9, 0x1C, 0x60, 0x00, 0x62, 0xA2, 0xD9, 0x1E, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xE4, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, +- 0xE9, 0x60, 0xB6, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x0F, 0x60, +- 0xCE, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, +- 0xCE, 0x62, 0xA2, 0xD1, 0x10, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x60, +- 0x04, 0x61, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x23, 0xFA, 0xF1, 0x60, +- 0x02, 0x64, 0x24, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xCA, 0x64, 0xA2, 0xDB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0xEA, 0x60, 0x58, 0x4E, +- 0x2E, 0x78, 0xFF, 0xFF, 0x20, 0x44, 0x01, 0xB5, 0x54, 0x80, 0x31, 0x44, 0xDE, 0xB4, 0x40, 0x51, +- 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x3E, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x2F, 0x58, 0xFF, 0xFF, 0x3F, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x1C, 0x60, 0x10, 0x62, 0x11, 0x60, +- 0xD8, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x51, 0xFB, +- 0x0F, 0x60, 0xE2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0xBE, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x0F, 0x60, 0xE2, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xE2, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x66, 0x01, 0x60, 0x7A, 0x61, 0x16, 0x60, +- 0xC4, 0x63, 0xA1, 0xD3, 0xFF, 0xFF, 0x20, 0x7F, 0xBD, 0xDB, 0x21, 0x60, 0x32, 0x64, 0xBD, 0xDB, +- 0x04, 0xA1, 0xA1, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x10, 0x00, 0x01, 0x60, 0x7A, 0x61, +- 0x16, 0x60, 0xC4, 0x63, 0xA1, 0xD3, 0x00, 0x66, 0x20, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, +- 0x21, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, 0xE2, 0x62, +- 0xA2, 0xD1, 0x9F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, +- 0xE4, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xEA, 0x60, 0x3E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x00, 0x62, 0x16, 0x60, 0xC2, 0x64, 0xA2, 0xDB, 0x20, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xE4, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, +- 0xEA, 0x60, 0x66, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xE2, 0x62, +- 0xA2, 0xD1, 0x9F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xCE, 0x62, +- 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, +- 0x5F, 0xFB, 0xAC, 0x85, 0x60, 0x41, 0x20, 0x03, 0x01, 0x60, 0x00, 0x63, 0x08, 0x64, 0xE9, 0x81, +- 0xCC, 0x84, 0x02, 0x24, 0xDF, 0x83, 0xFB, 0x02, 0x21, 0x60, 0x8E, 0x64, 0xA0, 0xDD, 0x65, 0x41, +- 0x21, 0x60, 0x90, 0x63, 0x0F, 0x60, 0xC0, 0x64, 0xE9, 0x81, 0x58, 0xD1, 0xFD, 0x04, 0xA3, 0xD9, +- 0x0B, 0x03, 0x58, 0xD1, 0xE9, 0x81, 0x60, 0x45, 0xFC, 0x04, 0xA3, 0xD1, 0x64, 0x47, 0xB0, 0x84, +- 0xBD, 0xDB, 0x00, 0xB9, 0x65, 0x44, 0xF0, 0x02, 0x20, 0x60, 0x38, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, +- 0x01, 0xA8, 0x01, 0x60, 0x70, 0x62, 0x06, 0x02, 0xA2, 0xD3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, +- 0x01, 0x03, 0x02, 0x64, 0x60, 0x41, 0x21, 0x60, 0x8E, 0x63, 0xBD, 0xD3, 0xA3, 0xD3, 0xFF, 0xB5, +- 0x80, 0xBF, 0xCD, 0x81, 0x65, 0x5C, 0x0F, 0x03, 0x80, 0xBF, 0xBD, 0xDB, 0x65, 0x44, 0xC8, 0x84, +- 0xFF, 0xFF, 0x0C, 0x03, 0x60, 0x45, 0xCD, 0x81, 0xA3, 0xD3, 0x08, 0x03, 0x80, 0xBF, 0xCD, 0x81, +- 0xFF, 0xFF, 0x01, 0x03, 0x80, 0xBC, 0x60, 0x47, 0xBD, 0xDB, 0x00, 0x65, 0x64, 0x41, 0x21, 0x60, +- 0x90, 0x63, 0xBD, 0xD3, 0xFF, 0xFF, 0x80, 0xB0, 0xFF, 0xFF, 0x01, 0x03, 0x60, 0x45, 0x60, 0x47, +- 0x80, 0xB0, 0xFF, 0xFF, 0x01, 0x03, 0x60, 0x45, 0xCD, 0x81, 0xFF, 0xFF, 0xF2, 0x02, 0x65, 0x44, +- 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x0A, 0x64, 0x15, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x14, 0x64, +- 0x11, 0x00, 0x0A, 0x3A, 0x02, 0x00, 0x32, 0x64, 0x0D, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x37, 0x64, +- 0x09, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x50, 0x64, 0x05, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x6E, 0x64, +- 0x01, 0x00, 0x14, 0x64, 0x62, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x3C, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x31, 0x40, 0x20, 0x2A, 0x18, 0x00, 0x3F, 0xF2, 0x47, 0x65, 0xC4, 0x84, 0xE8, 0x84, 0x23, 0xFA, +- 0xF1, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x1B, 0x60, 0xDA, 0x62, 0x1B, 0x60, 0xCA, 0x64, 0xA2, 0xDB, +- 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x00, 0x66, +- 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x0C, 0x63, 0x12, 0x60, +- 0xB6, 0x62, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x53, 0xFB, 0x54, 0xFB, 0x12, 0x60, 0xBA, 0x63, +- 0x02, 0x64, 0xA3, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0x12, 0x60, 0xBE, 0x62, 0xA2, 0xD3, 0x00, 0x63, +- 0xF0, 0xA0, 0x01, 0xA4, 0x03, 0x03, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0xA2, 0xDD, 0x12, 0x60, +- 0xC0, 0x62, 0xA2, 0xD1, 0xA2, 0xDD, 0x5A, 0xD3, 0xA2, 0xDD, 0xC0, 0x81, 0x61, 0x44, 0x02, 0x24, +- 0xFF, 0xFF, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0x5A, 0xD3, 0xE9, 0x81, 0xE8, 0x83, +- 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x85, 0xD4, 0x85, 0xC5, 0x83, 0xA2, 0xDD, 0x12, 0x60, +- 0xB8, 0x62, 0x63, 0x47, 0x00, 0x7F, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0x03, 0xE1, 0xA3, 0xFF, +- 0x1B, 0x60, 0x5A, 0x63, 0x17, 0xFD, 0xAE, 0xFF, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0x7F, 0x67, +- 0x01, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0xB1, 0xFE, 0x05, 0x05, 0xB0, 0xFE, 0x06, 0x05, 0xB2, 0xFE, +- 0xB3, 0xFE, 0x22, 0x00, 0xF0, 0x60, 0xFA, 0x78, 0xFF, 0xFF, 0x28, 0xF3, 0x29, 0xF1, 0x40, 0x44, +- 0x44, 0x45, 0x2A, 0xF1, 0x2B, 0xF1, 0x44, 0x46, 0x44, 0x47, 0x3F, 0xB4, 0xE0, 0x85, 0x16, 0x60, +- 0xD2, 0x64, 0x44, 0xD7, 0x58, 0x43, 0xFF, 0xFF, 0x60, 0x45, 0x12, 0x60, 0xC8, 0x7C, 0xA4, 0xD3, +- 0x61, 0x43, 0x04, 0xB4, 0x24, 0x44, 0x02, 0x03, 0x13, 0xFF, 0x06, 0x00, 0x3F, 0xB4, 0xB4, 0x84, +- 0xFF, 0x27, 0x05, 0xFD, 0x04, 0xFB, 0x10, 0x75, 0xA1, 0xFF, 0xFF, 0xFF, 0x86, 0x3E, 0xB4, 0xFE, +- 0x09, 0x05, 0xB5, 0xFE, 0x02, 0x24, 0x80, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xFE, 0x05, 0x05, +- 0xB6, 0xFE, 0xF2, 0x01, 0xF1, 0x60, 0x35, 0x78, 0xFF, 0xFF, 0x36, 0x44, 0x00, 0x7F, 0xF4, 0xA0, +- 0x60, 0x45, 0x05, 0x05, 0x17, 0x60, 0x5E, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xE4, 0x01, +- 0xE3, 0x01, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x10, 0x02, +- 0x10, 0x64, 0x40, 0x40, 0x02, 0x64, 0x40, 0x50, 0x61, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x04, 0x00, +- 0x10, 0xE0, 0x46, 0x60, 0x09, 0xE0, 0x00, 0x00, 0x27, 0xF1, 0x00, 0x66, 0x20, 0x78, 0x42, 0xFE, +- 0x23, 0x58, 0xFF, 0xFF, 0x78, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, +- 0x1C, 0x02, 0x12, 0x60, 0xC8, 0x63, 0xA3, 0xD3, 0x07, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, 0x04, 0x03, +- 0x03, 0x02, 0xBC, 0xF9, 0x00, 0x67, 0x11, 0x00, 0x00, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0xB4, 0x01, +- 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x06, 0x00, 0x04, 0x7C, +- 0xBC, 0xF9, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x78, 0x60, +- 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x31, 0x02, 0x12, 0x60, 0xC8, 0x63, +- 0xA3, 0xD3, 0x01, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, 0x03, 0x03, 0x02, 0x02, 0xBC, 0xF9, 0xFF, 0xFF, +- 0x02, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0x7E, 0xF1, 0x20, 0x44, +- 0x64, 0x40, 0xFF, 0x26, 0x1B, 0x00, 0x7F, 0xB4, 0x40, 0x40, 0x5C, 0x5E, 0x82, 0xFF, 0x26, 0x44, +- 0xFD, 0xB4, 0x40, 0x46, 0x5C, 0x41, 0x87, 0xFF, 0x62, 0xFF, 0x00, 0x63, 0x1B, 0x60, 0xC4, 0x62, +- 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x04, 0x03, 0x09, 0xF2, 0x0F, 0xFC, 0xAC, 0x86, +- 0xFB, 0x01, 0x1C, 0x60, 0x04, 0x62, 0x06, 0x64, 0xA2, 0xDB, 0x2D, 0xFF, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x25, 0x46, 0x01, 0xF2, 0x08, 0xF0, 0x60, 0x47, 0x03, 0xB4, 0x03, 0xAC, 0x7F, 0x67, +- 0x03, 0x61, 0x08, 0x02, 0x1B, 0x60, 0xE0, 0x64, 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, 0x75, 0x78, +- 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x2B, 0x49, 0x00, 0x25, 0x44, +- 0x1F, 0xB4, 0xE0, 0x85, 0xEC, 0x60, 0x36, 0x64, 0xC4, 0x98, 0xFF, 0xFF, 0xC0, 0xFE, 0x3D, 0x00, +- 0xC1, 0xFE, 0x3B, 0x00, 0xC2, 0xFE, 0x39, 0x00, 0xC3, 0xFE, 0x37, 0x00, 0xC4, 0xFE, 0x35, 0x00, +- 0xC5, 0xFE, 0x33, 0x00, 0xC6, 0xFE, 0x31, 0x00, 0xC7, 0xFE, 0x2F, 0x00, 0xC8, 0xFE, 0x2D, 0x00, +- 0xC9, 0xFE, 0x2B, 0x00, 0xCA, 0xFE, 0x29, 0x00, 0xCB, 0xFE, 0x27, 0x00, 0xCC, 0xFE, 0x25, 0x00, +- 0xCD, 0xFE, 0x23, 0x00, 0xCE, 0xFE, 0x21, 0x00, 0xCF, 0xFE, 0x1F, 0x00, 0xD0, 0xFE, 0x1D, 0x00, +- 0xD1, 0xFE, 0x1B, 0x00, 0xD2, 0xFE, 0x19, 0x00, 0xD3, 0xFE, 0x17, 0x00, 0xD4, 0xFE, 0x15, 0x00, +- 0xD5, 0xFE, 0x13, 0x00, 0xD6, 0xFE, 0x11, 0x00, 0xD7, 0xFE, 0x0F, 0x00, 0xD8, 0xFE, 0x0D, 0x00, +- 0xD9, 0xFE, 0x0B, 0x00, 0xDA, 0xFE, 0x09, 0x00, 0xDB, 0xFE, 0x07, 0x00, 0xDC, 0xFE, 0x05, 0x00, +- 0xDD, 0xFE, 0x03, 0x00, 0xDE, 0xFE, 0x01, 0x00, 0xDF, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x00, 0x64, 0x9F, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9D, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x9C, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x9A, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x99, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x98, 0xFE, 0xF0, 0x84, +- 0xFF, 0xFF, 0x97, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x96, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x95, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x94, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x93, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x92, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x91, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x90, 0xFE, 0xF0, 0x84, +- 0x06, 0xFB, 0x8F, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8D, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x8C, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x8A, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x89, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x88, 0xFE, 0xF0, 0x84, +- 0xFF, 0xFF, 0x87, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x86, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x85, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x84, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x83, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x82, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x81, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x80, 0xFE, 0xF0, 0x84, +- 0x05, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x5C, 0x5C, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x24, 0x40, 0x01, 0x27, 0x55, 0x00, 0x05, 0x60, 0x00, 0x63, 0x05, 0xFD, 0x30, 0x44, 0xBD, 0xDB, +- 0x31, 0x44, 0xBD, 0xDB, 0x32, 0x44, 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, +- 0x35, 0x44, 0xBD, 0xDB, 0x36, 0x44, 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, +- 0x39, 0x44, 0xBD, 0xDB, 0x3A, 0x44, 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, +- 0x3D, 0x44, 0xBD, 0xDB, 0x3E, 0x44, 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0x02, 0x61, 0x61, 0x44, +- 0x02, 0x36, 0x82, 0xFF, 0x03, 0x36, 0x83, 0xFF, 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, +- 0x06, 0x36, 0x86, 0xFF, 0x07, 0x36, 0x87, 0xFF, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, +- 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, +- 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, +- 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, +- 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, 0xDD, 0x81, 0x08, 0x3A, 0xD0, 0x01, 0x54, 0x00, +- 0x27, 0x40, 0x10, 0x26, 0x30, 0x00, 0x26, 0x44, 0x01, 0x36, 0x2D, 0x00, 0x02, 0x36, 0x82, 0xFF, +- 0x03, 0x36, 0x83, 0xFF, 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, 0x06, 0x36, 0x86, 0xFF, +- 0x25, 0x44, 0x00, 0x36, 0x44, 0x40, 0x01, 0x36, 0x44, 0x41, 0x02, 0x36, 0x44, 0x42, 0x03, 0x36, +- 0x44, 0x43, 0x04, 0x36, 0x44, 0x44, 0x05, 0x36, 0x44, 0x45, 0x06, 0x36, 0x44, 0x46, 0x07, 0x36, +- 0x44, 0x47, 0x08, 0x36, 0x44, 0x48, 0x09, 0x36, 0x44, 0x49, 0x0A, 0x36, 0x44, 0x4A, 0x0B, 0x36, +- 0x44, 0x4B, 0x0C, 0x36, 0x44, 0x4C, 0x0D, 0x36, 0x44, 0x4D, 0x0E, 0x36, 0x44, 0x4E, 0x0F, 0x36, +- 0x44, 0x4F, 0x87, 0xFF, 0x21, 0x00, 0x25, 0x44, 0x10, 0x36, 0x44, 0x50, 0x11, 0x36, 0x44, 0x51, +- 0x12, 0x36, 0x44, 0x52, 0x13, 0x36, 0x44, 0x53, 0x14, 0x36, 0x44, 0x54, 0x15, 0x36, 0x44, 0x55, +- 0x16, 0x36, 0x44, 0x56, 0x17, 0x36, 0x44, 0x57, 0x18, 0x36, 0x44, 0x58, 0x19, 0x36, 0x44, 0x59, +- 0x1A, 0x36, 0x44, 0x5A, 0x1B, 0x36, 0x44, 0x5B, 0x1C, 0x36, 0x44, 0x5C, 0x1D, 0x36, 0x44, 0x5D, +- 0x1E, 0x36, 0x44, 0x5E, 0x1F, 0x36, 0x44, 0x5F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0x46, +- 0xB3, 0x60, 0x58, 0x4F, 0x22, 0x78, 0xFF, 0xFF, 0x03, 0x61, 0x7F, 0x67, 0x0B, 0x02, 0x00, 0xF0, +- 0x1B, 0x60, 0xE0, 0x62, 0x04, 0x64, 0xA2, 0xDB, 0x5A, 0xD9, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, +- 0x7F, 0x67, 0x02, 0x61, 0x11, 0x02, 0x1C, 0x60, 0x04, 0x62, 0x1A, 0x64, 0xA2, 0xDB, 0x00, 0x60, +- 0x50, 0x63, 0x5A, 0xDD, 0xED, 0x60, 0xB9, 0x64, 0x80, 0xFB, 0x2D, 0xFF, 0xEB, 0x60, 0x84, 0x78, +- 0xFF, 0xFF, 0x2A, 0xF3, 0x05, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, +- 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x0F, 0x02, 0x1C, 0x60, 0x04, 0x62, 0x1C, 0x64, +- 0xA2, 0xDB, 0x00, 0x60, 0x50, 0x63, 0x5A, 0xDD, 0xED, 0x60, 0xD3, 0x64, 0x80, 0xFB, 0x2D, 0xFF, +- 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, +- 0x24, 0x45, 0xA4, 0x80, 0x02, 0x61, 0x34, 0x02, 0x25, 0x45, 0x20, 0x44, 0x80, 0x2A, 0x35, 0x00, +- 0xF1, 0x60, 0x00, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x01, 0x03, 0x29, 0x00, 0x21, 0x60, 0x74, 0x62, +- 0xA2, 0xD1, 0x9A, 0xF3, 0x16, 0x60, 0xCC, 0x61, 0xA0, 0x84, 0xA1, 0xDB, 0x25, 0x45, 0x1B, 0x60, +- 0x52, 0x63, 0x01, 0x61, 0xBD, 0xD3, 0xBD, 0xD1, 0xD4, 0x80, 0xBD, 0xD3, 0xBD, 0xD5, 0xCD, 0x81, +- 0x02, 0x03, 0x15, 0x03, 0xF7, 0x01, 0xA2, 0xFF, 0xA6, 0xD3, 0x40, 0x4C, 0x00, 0xA8, 0x67, 0x43, +- 0x0C, 0x02, 0xA2, 0xDD, 0x42, 0x48, 0x64, 0x41, 0xB3, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, +- 0x66, 0x44, 0x28, 0xDB, 0x02, 0x03, 0x2C, 0x58, 0xA3, 0xFF, 0x0C, 0x61, 0x03, 0x00, 0x04, 0x61, +- 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xF1, 0x60, 0x02, 0x64, 0xD4, 0x80, +- 0x7F, 0x67, 0x06, 0x63, 0xF8, 0x02, 0x31, 0x40, 0x20, 0x26, 0xF5, 0x01, 0x21, 0x60, 0x74, 0x62, +- 0xA2, 0xD1, 0x9A, 0xF3, 0x16, 0x60, 0xCC, 0x61, 0xA0, 0x84, 0xA1, 0xDB, 0x16, 0x60, 0xD0, 0x61, +- 0x01, 0x64, 0xA1, 0xDB, 0xFF, 0xFF, 0xC4, 0xFE, 0xE5, 0x01, 0xC6, 0xFE, 0xE3, 0x01, 0x7E, 0x60, +- 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x02, 0x61, 0x3F, 0x02, 0x25, 0x45, 0xF8, 0x2B, 0x3B, 0x00, +- 0x2E, 0xF5, 0x67, 0x44, 0xD4, 0x80, 0x17, 0x60, 0x6A, 0x63, 0x39, 0x03, 0x64, 0x61, 0x24, 0x44, +- 0x01, 0x27, 0x29, 0x00, 0xA3, 0xFC, 0xA4, 0xF8, 0xBD, 0xD3, 0xA3, 0xD1, 0xD4, 0x80, 0xCD, 0x81, +- 0x08, 0x24, 0x64, 0x58, 0x08, 0xA3, 0xF8, 0x02, 0x08, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xA3, 0xD1, +- 0xFE, 0xA0, 0xFA, 0x60, 0x00, 0x64, 0xD0, 0x80, 0x14, 0x02, 0x13, 0x02, 0x04, 0xA3, 0xBE, 0xD3, +- 0xBD, 0xD1, 0x0F, 0x18, 0xD4, 0x80, 0x0D, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, +- 0x64, 0x41, 0xDD, 0x81, 0xE1, 0x81, 0xCB, 0x83, 0x46, 0x65, 0xF2, 0x60, 0x58, 0x4F, 0x4A, 0x78, +- 0xFF, 0xFF, 0x00, 0x67, 0x0A, 0x00, 0xBD, 0xD3, 0xBE, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, +- 0x64, 0x58, 0x08, 0xA3, 0xF8, 0x02, 0x04, 0x61, 0x7F, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x0F, 0x64, +- 0x23, 0xFA, 0x67, 0x44, 0x24, 0xFA, 0x62, 0x41, 0x3E, 0x60, 0x00, 0x65, 0x1A, 0x63, 0xEA, 0x60, +- 0x88, 0x64, 0x65, 0x46, 0x58, 0xD0, 0x2E, 0xF5, 0x59, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x4B, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0xE8, 0x84, 0xDC, 0x84, 0x23, 0xFA, 0xBF, 0xD1, +- 0x4A, 0x65, 0x64, 0x43, 0xF2, 0x60, 0x58, 0x4F, 0x4A, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xE0, 0xA0, 0x20, 0x64, 0x01, 0x06, 0x25, 0xFA, 0x23, 0xF2, +- 0xDF, 0xD1, 0xCC, 0x84, 0xE0, 0x85, 0x0B, 0x06, 0xBF, 0xD1, 0x64, 0x41, 0xD5, 0x80, 0x64, 0x43, +- 0x01, 0x06, 0x65, 0x41, 0x4A, 0x65, 0xEF, 0x60, 0x58, 0x4F, 0x87, 0x78, 0xFF, 0xFF, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0xBC, 0xF3, 0x02, 0x63, 0x23, 0xFC, 0x07, 0xB4, 0x25, 0xFA, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x4B, 0xD3, 0xBF, 0xD3, 0x60, 0x41, 0xC9, 0x83, 0xE9, 0x81, 0xDD, 0x81, +- 0xA3, 0xFA, 0xE0, 0x81, 0x3C, 0x60, 0x00, 0x67, 0x02, 0x24, 0x02, 0xA4, 0x60, 0x47, 0x40, 0x4B, +- 0xC9, 0x81, 0x4A, 0x65, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, +- 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF6, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, +- 0xA3, 0xD1, 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, 0x60, 0x47, 0x25, 0xFA, 0x00, 0x7E, 0x60, 0x47, +- 0x01, 0x26, 0xDC, 0x84, 0x60, 0x41, 0xE8, 0x84, 0xD8, 0x84, 0x23, 0xFA, 0xAB, 0x01, 0xFC, 0xA3, +- 0xA3, 0xD1, 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, 0x00, 0x7F, 0x25, 0xFA, 0x60, 0x41, 0x01, 0x26, +- 0xDD, 0x81, 0xE9, 0x84, 0xD8, 0x84, 0x23, 0xFA, 0x9D, 0x01, 0x23, 0xF2, 0x12, 0x60, 0xB8, 0x65, +- 0x60, 0x41, 0x12, 0x60, 0x54, 0x63, 0xA3, 0xDB, 0xFF, 0xA1, 0x48, 0x64, 0x58, 0xD0, 0x7E, 0xA8, +- 0x5B, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xFF, 0xA1, 0xD7, 0x80, 0x02, 0x03, 0x01, 0x03, +- 0xF5, 0x01, 0x2E, 0xF5, 0x00, 0x60, 0x2F, 0x65, 0x25, 0xF2, 0x00, 0x63, 0xCC, 0x84, 0x03, 0xA3, +- 0xFD, 0x05, 0x4A, 0x64, 0xD7, 0x80, 0x11, 0x60, 0xF0, 0x61, 0x2F, 0x05, 0xA1, 0xDD, 0xE3, 0x83, +- 0xFE, 0xA3, 0x58, 0xD0, 0x7E, 0xA8, 0x59, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, +- 0x00, 0x63, 0x59, 0xDD, 0x2E, 0xF5, 0x11, 0x60, 0xF0, 0x64, 0x25, 0xF0, 0xA0, 0xD3, 0xD3, 0x80, +- 0x01, 0xB0, 0x04, 0x03, 0x01, 0xA4, 0x03, 0x03, 0xA2, 0xDB, 0x01, 0x00, 0xA2, 0xDD, 0x11, 0x60, +- 0xF8, 0x63, 0x10, 0x60, 0x0A, 0x65, 0xBD, 0xD3, 0xBD, 0xD1, 0xE0, 0x84, 0xC4, 0x82, 0x10, 0x60, +- 0x2A, 0x65, 0x07, 0x64, 0x64, 0x41, 0x5A, 0xDB, 0xD6, 0x80, 0xCD, 0x81, 0x06, 0x03, 0xFB, 0x02, +- 0x25, 0xF2, 0x02, 0xA3, 0xCC, 0x84, 0xA2, 0xDA, 0xEC, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x12, 0x60, 0x54, 0x61, 0xA1, 0xD3, 0x23, 0xFA, 0xE0, 0x83, 0x4A, 0x65, 0x04, 0x02, 0x02, 0x63, +- 0x23, 0xFC, 0xA5, 0xFC, 0x09, 0x00, 0xDB, 0x83, 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, +- 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x11, 0x60, +- 0xF0, 0x62, 0xA2, 0xD3, 0x00, 0x61, 0x02, 0xA4, 0xFE, 0xA0, 0x23, 0xFA, 0x1B, 0x03, 0xFA, 0xA4, +- 0xFD, 0xA4, 0x01, 0xA1, 0xFD, 0x07, 0x61, 0x43, 0x23, 0xF2, 0x25, 0xFC, 0xE0, 0x83, 0x02, 0xA3, +- 0x11, 0x60, 0xF0, 0x61, 0x00, 0x60, 0x4A, 0x64, 0x59, 0xD1, 0x58, 0xD8, 0x7E, 0x3A, 0x02, 0x00, +- 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x25, 0xF2, 0x23, 0xF2, 0x01, 0xB0, 0xCC, 0x84, 0x04, 0x02, +- 0x23, 0xFA, 0x02, 0x00, 0x00, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x41, 0x4B, +- 0x65, 0x42, 0x80, 0x64, 0xD4, 0x85, 0x2B, 0x41, 0x00, 0xA1, 0x55, 0x8B, 0x0D, 0x03, 0x02, 0x04, +- 0x65, 0x41, 0x02, 0x00, 0x00, 0x64, 0x40, 0x4B, 0xCA, 0x84, 0x58, 0xD0, 0xC9, 0x81, 0xBD, 0xD9, +- 0xFC, 0x02, 0x00, 0xF4, 0x04, 0x65, 0xEC, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD3, +- 0x02, 0x7C, 0xA0, 0xD3, 0x23, 0xF8, 0xDC, 0x84, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x02, 0x64, 0x23, 0xFA, 0x01, 0x64, 0x9D, 0xFE, 0x02, 0x28, 0x02, 0x64, 0x25, 0xFA, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x21, 0x60, 0x80, 0x62, 0xA2, 0xD3, 0x02, 0x7C, 0x23, 0xF8, 0x01, 0xB4, +- 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, 0x02, 0x64, 0x23, 0xFA, +- 0x64, 0x44, 0x7C, 0x5F, 0x60, 0x45, 0x64, 0x47, 0x7C, 0x5F, 0x89, 0xF1, 0x66, 0x41, 0xC0, 0x86, +- 0xA5, 0xD2, 0x61, 0x46, 0x00, 0x63, 0x60, 0x40, 0x0A, 0x37, 0x01, 0x63, 0x14, 0x37, 0x02, 0x63, +- 0x37, 0x37, 0x06, 0x63, 0x6E, 0x37, 0x0B, 0x63, 0x25, 0xFC, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x02, 0x64, 0x23, 0xFA, 0x88, 0xFF, 0x75, 0x44, 0x8D, 0xFF, 0xE8, 0x87, 0xE8, 0x84, 0xE8, 0x84, +- 0x03, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF0, 0x21, 0x60, 0x7C, 0x65, +- 0x23, 0xF2, 0xA5, 0xD9, 0x02, 0xA8, 0x64, 0x44, 0x07, 0x02, 0x00, 0xBC, 0xF2, 0xA4, 0x04, 0x03, +- 0x03, 0x07, 0x1F, 0x60, 0xAA, 0x62, 0xA2, 0xD9, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x20, 0x63, +- 0x20, 0x60, 0x0A, 0x61, 0x48, 0x64, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x25, 0xF0, 0x20, 0x64, +- 0xD0, 0x81, 0xFF, 0xFF, 0x02, 0x07, 0x25, 0xFA, 0x0F, 0x00, 0x20, 0x60, 0x0E, 0x63, 0xC3, 0x83, +- 0x01, 0x2A, 0x06, 0x00, 0xCF, 0x83, 0xA3, 0xD3, 0xCD, 0x81, 0x00, 0x7F, 0xBD, 0xDB, 0x04, 0x03, +- 0x00, 0x64, 0xC9, 0x81, 0xBD, 0xDB, 0xFD, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, +- 0x25, 0xF0, 0x01, 0x60, 0x70, 0x63, 0xA3, 0xD9, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, +- 0xA5, 0xF0, 0xA3, 0xD1, 0xFF, 0xFF, 0x64, 0x5E, 0x00, 0x7F, 0x60, 0x41, 0x64, 0x47, 0x7C, 0x5F, +- 0x89, 0xF1, 0x66, 0x43, 0xC0, 0x86, 0x65, 0x44, 0xA1, 0xDA, 0x63, 0x46, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, 0xFF, 0xFF, 0x64, 0x5E, 0x00, 0x7F, 0x60, 0x45, 0x64, 0x47, +- 0x7C, 0x5F, 0x89, 0xF1, 0x66, 0x41, 0xC0, 0x86, 0x65, 0x44, 0xA0, 0xD2, 0x61, 0x46, 0x25, 0xFA, +- 0x02, 0x64, 0x23, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, +- 0x00, 0x67, 0x02, 0x02, 0x2D, 0xF9, 0x2C, 0xF9, 0x23, 0x58, 0xFF, 0xFF, 0x1F, 0x60, 0xA8, 0x61, +- 0x23, 0xF2, 0x25, 0xF2, 0x02, 0xA8, 0x00, 0xA8, 0x09, 0x02, 0x07, 0x03, 0xD0, 0xA0, 0x30, 0x65, +- 0x03, 0x04, 0xA7, 0xA0, 0x59, 0x65, 0x01, 0x06, 0x65, 0x44, 0xA1, 0xDB, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x04, 0x61, 0x0A, 0x00, 0x25, 0x60, 0x2C, 0x61, 0x01, 0x64, 0xA1, 0xDB, 0x04, 0x00, +- 0x25, 0x60, 0x2C, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x06, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0xEB, 0x60, +- 0x84, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x46, 0x45, 0x02, 0xF0, +- 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0x00, 0xF4, 0x01, 0xF2, 0x66, 0x5C, 0x25, 0x46, 0x56, 0x02, +- 0x70, 0x27, 0x54, 0x00, 0x12, 0x64, 0x03, 0xFA, 0x04, 0xF8, 0x0E, 0xF2, 0x87, 0xFC, 0x8D, 0xFC, +- 0x8E, 0xFC, 0xDA, 0x82, 0x16, 0x61, 0x00, 0x63, 0xC9, 0x81, 0x5A, 0xDC, 0xFD, 0x02, 0x60, 0x40, +- 0xF0, 0x3B, 0x16, 0x00, 0x32, 0x44, 0x8F, 0xF3, 0x01, 0xB0, 0xF6, 0xA0, 0x08, 0x24, 0x2C, 0x05, +- 0xDC, 0x83, 0xF0, 0x67, 0x0E, 0xFA, 0x1B, 0x60, 0xC4, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0x8F, 0xFD, 0x2B, 0xFF, 0xFE, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x4F, 0x00, +- 0x90, 0xF3, 0x0A, 0x65, 0xD4, 0x80, 0xDC, 0x83, 0x17, 0x05, 0x90, 0xFD, 0x98, 0xFE, 0x04, 0x04, +- 0x00, 0x7F, 0x08, 0x7E, 0x0E, 0xFA, 0x3B, 0xFF, 0x1B, 0x60, 0xB8, 0x64, 0x2B, 0xDB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0x0E, 0xF2, 0x2B, 0xFF, 0x60, 0x40, 0x08, 0x26, 0xF7, 0xFE, +- 0xFD, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x32, 0x00, 0x8C, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, 0xFF, 0xFF, +- 0x0D, 0x04, 0x1B, 0x60, 0xD0, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xFC, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x21, 0x00, 0x46, 0x45, 0x00, 0x64, +- 0x2B, 0xDB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA2, 0xFF, +- 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, 0x70, 0x67, 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, 0xC0, 0x84, +- 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, 0x80, 0xFC, 0x05, 0xFA, 0xB4, 0x60, 0x58, 0x4E, 0x48, 0x78, +- 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, 0xFF, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0xD4, 0xFE, 0xA3, 0xFF, +- 0x2D, 0x58, 0xFF, 0xFF, 0x1B, 0x60, 0xBE, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x0D, 0x00, 0x1B, 0x60, +- 0xB2, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x18, 0x00, 0x1B, 0x60, 0xCA, 0x64, 0x40, 0x47, 0x58, 0x4F, +- 0x03, 0x00, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0x27, 0xD5, 0x0E, 0xF2, 0x0B, 0x18, 0x60, 0x40, +- 0x01, 0x2A, 0x08, 0x00, 0x1B, 0x60, 0xE0, 0x64, 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, 0x75, 0x78, +- 0xFF, 0xFF, 0xF2, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD5, 0x0E, 0xF2, 0x14, 0x18, 0x60, 0x40, +- 0x01, 0x2A, 0x11, 0x00, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0x90, 0xF3, +- 0x02, 0x02, 0xCC, 0x84, 0x90, 0xFB, 0x1B, 0x60, 0xE0, 0x64, 0x40, 0x4B, 0xF0, 0x60, 0x58, 0x4D, +- 0x75, 0x78, 0xFF, 0xFF, 0xE9, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFB, 0x64, 0x3A, 0x42, 0x4A, 0xDB, +- 0xA2, 0xFF, 0x93, 0xF3, 0x8F, 0xF3, 0xCC, 0x80, 0xFA, 0xA0, 0x01, 0x14, 0x1E, 0x05, 0xB3, 0x60, +- 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, 0x18, 0x03, 0xF0, 0x67, 0x0E, 0xFA, 0x1B, 0x60, +- 0xE0, 0x62, 0x1B, 0x60, 0xC4, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xF6, 0x64, 0x3A, 0x42, 0x4A, 0xDB, 0x93, 0xF3, 0x8F, 0xF3, 0xCC, 0x83, +- 0xDC, 0x84, 0x01, 0x15, 0x93, 0xFD, 0x8F, 0xFB, 0xD4, 0xFE, 0x92, 0xF3, 0x90, 0xF3, 0x00, 0xA8, +- 0x91, 0xF1, 0x03, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x27, 0x05, 0xB3, 0x60, 0x58, 0x4D, 0x4E, 0x78, +- 0xFF, 0xFF, 0xA2, 0xFF, 0x21, 0x03, 0x00, 0x63, 0x92, 0xF3, 0x0E, 0xFC, 0xCC, 0x84, 0xFF, 0x3A, +- 0x92, 0xFB, 0x98, 0xFE, 0x03, 0x04, 0x08, 0xBB, 0x0E, 0xFC, 0x3B, 0xFF, 0x1B, 0x60, 0xE0, 0x62, +- 0x1B, 0x60, 0xB8, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xF7, 0x64, 0x3A, 0x42, 0x4A, 0xDB, 0x90, 0xF3, 0x0E, 0xF2, 0xDC, 0x83, 0x08, 0xB0, +- 0x90, 0xFD, 0x08, 0x28, 0xF7, 0xFE, 0xD4, 0xFE, 0xA3, 0xFF, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, +- 0xB9, 0xFE, 0x13, 0xFF, 0x24, 0x40, 0x80, 0x2B, 0x0B, 0x00, 0xA2, 0xFF, 0x25, 0x46, 0x09, 0xF4, +- 0x0E, 0xF2, 0x05, 0x18, 0x08, 0xBC, 0x0E, 0xFA, 0xFF, 0xFF, 0xF7, 0xFE, 0x01, 0x00, 0xD8, 0xFE, +- 0xA3, 0xFF, 0x25, 0x46, 0x3E, 0xF2, 0x00, 0xF4, 0x08, 0xF0, 0x25, 0x46, 0x06, 0xB4, 0xFF, 0x7F, +- 0x10, 0xBC, 0x06, 0x26, 0xFD, 0x7F, 0x0E, 0xFA, 0x3E, 0xF2, 0x3F, 0xF2, 0x60, 0x41, 0x08, 0x2A, +- 0x64, 0x47, 0x3F, 0xFA, 0x60, 0x45, 0x1F, 0x60, 0x62, 0x62, 0xA2, 0xD3, 0xA3, 0xFC, 0xAB, 0xFC, +- 0x91, 0xFC, 0xD4, 0x80, 0xE0, 0x60, 0xC1, 0x65, 0xA5, 0x80, 0x01, 0x04, 0x07, 0x03, 0x23, 0xF0, +- 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xF2, 0x60, 0x25, 0x78, 0xFF, 0xFF, 0xF4, 0x60, 0x58, 0x4F, +- 0x2D, 0x78, 0xFF, 0xFF, 0x14, 0x04, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x98, 0xF1, +- 0x1E, 0x60, 0xFC, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, +- 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x02, 0x00, 0x20, 0x60, 0x00, 0x75, 0x46, 0x00, 0x3E, 0xF0, +- 0x89, 0xF1, 0x64, 0x47, 0x07, 0xB4, 0x07, 0x36, 0x3B, 0x00, 0x04, 0x03, 0xCC, 0x84, 0xE0, 0x84, +- 0xC0, 0x83, 0x2D, 0x00, 0x2C, 0xF2, 0x88, 0xF1, 0x01, 0xB0, 0x64, 0x43, 0x35, 0x02, 0x2E, 0xF2, +- 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, +- 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x2E, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, +- 0x0C, 0x02, 0x61, 0x46, 0x2D, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, +- 0x2C, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, +- 0xE8, 0x1B, 0x88, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x09, 0x00, 0x66, 0x45, +- 0x63, 0x46, 0x06, 0xF0, 0x65, 0x46, 0x64, 0x44, 0x0C, 0x26, 0x02, 0x00, 0x02, 0x26, 0x04, 0x00, +- 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x07, 0xFC, 0x23, 0xF2, 0xFF, 0xFF, 0x10, 0x1B, +- 0x1B, 0x60, 0xE0, 0x62, 0x1B, 0x60, 0x9A, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xC8, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x0F, 0x00, +- 0x1B, 0x60, 0xE0, 0x62, 0x1B, 0x60, 0xAC, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xCE, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0xEB, 0x60, +- 0x84, 0x78, 0xFF, 0xFF, 0xCB, 0x84, 0xC9, 0x83, 0xFF, 0xFF, 0x08, 0x04, 0x58, 0xD1, 0xA5, 0xD8, +- 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x2F, 0x58, 0xFF, 0xFF, +- 0x25, 0xF0, 0x21, 0x60, 0x2C, 0x62, 0xA2, 0xD9, 0x19, 0x00, 0x21, 0x60, 0x80, 0x64, 0xA0, 0xD1, +- 0x7F, 0xF9, 0x0C, 0x60, 0x38, 0x62, 0x40, 0x63, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x64, 0x40, +- 0x01, 0x2A, 0x0C, 0x00, 0x04, 0x65, 0x0C, 0x60, 0x38, 0x61, 0x48, 0x64, 0x3E, 0x63, 0x7C, 0xA8, +- 0x58, 0xD0, 0x59, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x21, 0x60, 0x2C, 0x62, +- 0xA2, 0xD1, 0x0D, 0x60, 0x1C, 0x65, 0x02, 0xFE, 0x64, 0x44, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x87, +- 0x60, 0x41, 0x64, 0x44, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x84, 0x3E, 0xFB, 0x60, 0x42, 0x61, 0x44, +- 0x03, 0xA2, 0x60, 0xFE, 0xA2, 0xDB, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x44, 0x0C, 0x60, 0x3A, 0x65, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x84, 0x40, 0xFB, 0xFF, 0xFF, 0x00, 0x67, +- 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x21, 0x60, 0x80, 0x64, 0xA0, 0xD1, 0x7F, 0xF9, 0x00, 0x64, +- 0x40, 0x41, 0x64, 0x40, 0x01, 0x2A, 0xA6, 0x00, 0x4A, 0x64, 0xA0, 0xD2, 0xFF, 0xFF, 0x40, 0x42, +- 0x80, 0x2B, 0x04, 0x00, 0xFF, 0xB4, 0x40, 0x42, 0x01, 0x64, 0x40, 0x41, 0x88, 0xF3, 0x46, 0x4B, +- 0x87, 0xF3, 0x60, 0x46, 0xE0, 0x83, 0xAB, 0x46, 0x26, 0xF0, 0xAB, 0x46, 0x55, 0xF8, 0xAB, 0x46, +- 0x27, 0xF0, 0xAB, 0x46, 0x56, 0xF8, 0xAB, 0x46, 0x28, 0xF0, 0xAB, 0x46, 0x57, 0xF8, 0x66, 0x44, +- 0x02, 0xA6, 0xF1, 0x1F, 0x88, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xAB, 0x46, 0x0C, 0x60, 0x7A, 0x65, +- 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, 0xC9, 0x81, +- 0x52, 0x64, 0x0E, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, +- 0xAB, 0x46, 0xF0, 0xA1, 0x6E, 0x64, 0x0E, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, +- 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x0C, 0x60, 0xDC, 0x65, 0xC4, 0x81, +- 0x60, 0x45, 0xC9, 0x81, 0x62, 0x64, 0x06, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, +- 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF8, 0xA1, 0xAE, 0x64, 0x06, 0x63, 0x59, 0xD1, 0x58, 0xD8, +- 0xFD, 0x1F, 0xAB, 0x46, 0x65, 0x44, 0x0C, 0x60, 0xFC, 0x65, 0xC4, 0x81, 0xC9, 0x81, 0x6A, 0x64, +- 0x06, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x85, +- 0xC4, 0x84, 0x0C, 0x60, 0xC2, 0x65, 0xC4, 0x81, 0x72, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, +- 0xFD, 0x1F, 0xAB, 0x46, 0x21, 0x44, 0x01, 0x2A, 0x06, 0x00, 0xFA, 0xA1, 0x88, 0x64, 0x04, 0x63, +- 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0x37, 0xF0, 0x21, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x22, 0x44, +- 0x3D, 0xFB, 0x60, 0x41, 0x02, 0xFE, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x84, 0x3C, 0xFB, 0x0C, 0x60, +- 0xBE, 0x63, 0x88, 0xFF, 0xCD, 0x81, 0x06, 0xA3, 0xFD, 0x0D, 0x8D, 0xFF, 0x3B, 0xFD, 0x64, 0x47, +- 0x80, 0xBF, 0x60, 0x5C, 0x22, 0x43, 0x80, 0x61, 0x88, 0xFF, 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, +- 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0xB1, 0x84, 0x37, 0xFA, 0x87, 0xF3, 0xFF, 0xFF, 0xCC, 0x83, +- 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0x37, 0xF0, 0x66, 0x44, 0xB1, 0x9C, 0x37, 0xF8, 0x02, 0xA6, +- 0xFA, 0x1F, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, +- 0x02, 0xA8, 0x00, 0x67, 0x24, 0x02, 0x3D, 0xF1, 0x64, 0x44, 0x03, 0xB4, 0x40, 0x42, 0xD0, 0x80, +- 0x88, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xB7, 0xF4, 0x80, 0x61, 0x02, 0x02, 0xE3, 0x83, 0xEB, 0x83, +- 0x22, 0x44, 0x88, 0xFF, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, +- 0x9D, 0x85, 0xA7, 0x83, 0x37, 0xFC, 0x87, 0xF3, 0xFF, 0xFF, 0xCC, 0x83, 0xE3, 0x83, 0x66, 0x44, +- 0x02, 0xA6, 0xB7, 0xF2, 0x66, 0x44, 0xA5, 0x81, 0xB7, 0xFA, 0x02, 0xA6, 0xFA, 0x1F, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x11, 0x64, 0x23, 0xFA, 0x25, 0x44, 0x24, 0xFA, 0x04, 0x64, 0x40, 0x4B, +- 0x62, 0x41, 0x0C, 0x60, 0xC2, 0x64, 0x04, 0x63, 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, 0x2B, 0x43, +- 0x00, 0x7C, 0x59, 0xD8, 0x4F, 0x8B, 0x06, 0xA4, 0xF6, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x21, 0x60, 0x80, 0x64, 0xA0, 0xD1, 0x7F, 0xF9, 0x64, 0x40, 0x01, 0x2A, 0x4E, 0x00, 0x27, 0xF2, +- 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, +- 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, +- 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, +- 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, +- 0xE8, 0x1B, 0x88, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x2A, 0x00, 0x43, 0x4B, +- 0xAB, 0x46, 0x37, 0xF2, 0x80, 0x60, 0x30, 0x7C, 0xB0, 0x84, 0xA2, 0xDA, 0x4E, 0x61, 0x6E, 0x64, +- 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x88, 0x64, 0x04, 0x63, +- 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0xD9, 0x81, 0x98, 0x64, 0x04, 0x63, +- 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0xD9, 0x81, 0xAE, 0x64, 0x0E, 0x63, +- 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, +- 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x21, 0x60, 0x80, 0x64, 0xA0, 0xD1, +- 0x7F, 0xF9, 0x64, 0x40, 0x01, 0x2A, 0x31, 0x00, 0x27, 0xF2, 0x12, 0x60, 0xCE, 0x65, 0x60, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, +- 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, +- 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x88, 0xF3, 0x08, 0xFE, +- 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x0D, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x37, 0xF2, 0x80, 0x60, +- 0x30, 0x61, 0x9D, 0x85, 0xA4, 0x84, 0xA2, 0xDA, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, +- 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x3E, 0xF2, 0xAC, 0xF1, 0x08, 0xB0, +- 0x19, 0xF8, 0x4A, 0x02, 0x07, 0x23, 0x2B, 0x00, 0x60, 0x47, 0x07, 0xB4, 0x89, 0xF1, 0xCC, 0x84, +- 0xE0, 0x84, 0x40, 0x8A, 0xAA, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x05, 0xF2, 0x60, 0x43, 0xAA, 0x46, +- 0x2C, 0xFC, 0x2D, 0xF8, 0x2E, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, +- 0x31, 0xF8, 0x46, 0x4A, 0x00, 0xF4, 0x02, 0xF2, 0x03, 0xF0, 0x04, 0xF2, 0x60, 0x43, 0xAA, 0x46, +- 0x32, 0xFC, 0x33, 0xF8, 0x34, 0xFA, 0xAA, 0x46, 0x05, 0xF2, 0x06, 0xF0, 0x07, 0xF2, 0x60, 0x43, +- 0xAA, 0x46, 0x36, 0xFC, 0x37, 0xF8, 0x38, 0xFA, 0x03, 0x60, 0x08, 0x64, 0x1C, 0x00, 0x67, 0xF1, +- 0x2F, 0xF8, 0x68, 0xF1, 0x30, 0xF8, 0x69, 0xF1, 0x31, 0xF8, 0x46, 0x4A, 0x00, 0xF4, 0x02, 0xF2, +- 0x03, 0xF0, 0x04, 0xF2, 0x60, 0x43, 0xAA, 0x46, 0x2C, 0xFC, 0x2D, 0xF8, 0x2E, 0xFA, 0xAA, 0x46, +- 0x05, 0xF2, 0x06, 0xF0, 0x07, 0xF2, 0x60, 0x43, 0xAA, 0x46, 0x32, 0xFC, 0x33, 0xF8, 0x34, 0xFA, +- 0x02, 0x60, 0x08, 0x64, 0x00, 0x00, 0x2A, 0xFA, 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x28, 0xF3, +- 0xFF, 0xFF, 0x60, 0x47, 0x0F, 0xB4, 0x59, 0x00, 0xFF, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x1C, 0x60, +- 0x04, 0x65, 0x04, 0x64, 0xA5, 0xDB, 0x12, 0x00, 0x1C, 0x60, 0x04, 0x65, 0x0C, 0x64, 0xA5, 0xDB, +- 0x0D, 0x00, 0x1C, 0x60, 0x04, 0x65, 0x06, 0x64, 0xA5, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x04, 0x65, 0x08, 0x64, 0xA5, 0xDB, 0xF4, 0x60, 0xD9, 0x64, +- 0x80, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0x29, 0xF3, 0x65, 0xFB, +- 0x83, 0xFB, 0x02, 0x60, 0xEE, 0x64, 0x82, 0xFB, 0x07, 0x64, 0x84, 0xFB, 0xF4, 0x60, 0xD9, 0x64, +- 0x80, 0xFB, 0xFF, 0xFF, 0xDF, 0xFE, 0x00, 0x64, 0x19, 0xFF, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, +- 0xAF, 0x60, 0xFD, 0x63, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0xF4, 0x60, 0xC6, 0x63, +- 0x80, 0xFD, 0xFF, 0xFF, 0x1A, 0xFF, 0xEB, 0x60, 0x84, 0x78, 0xFF, 0xFF, 0xA7, 0x60, 0x9B, 0x63, +- 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0x29, 0xF5, 0x1B, 0x60, 0xE0, 0x63, 0x1B, 0x60, +- 0xB2, 0x64, 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0x02, 0x64, 0xA3, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xF9, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xA7, 0x01, 0x00, 0x36, 0xA8, 0x01, 0x01, 0x36, +- 0xAB, 0x01, 0x02, 0x36, 0xAE, 0x01, 0x03, 0x36, 0xB5, 0x01, 0x04, 0x36, 0xD1, 0x01, 0x05, 0x36, +- 0xCF, 0x01, 0x06, 0x36, 0xF1, 0x01, 0x07, 0x36, 0xCB, 0x01, 0x08, 0x36, 0xB7, 0x01, 0x09, 0x36, +- 0x0C, 0x00, 0x0A, 0x36, 0x0D, 0x00, 0x0B, 0x36, 0x0E, 0x00, 0x0C, 0x36, 0x17, 0x00, 0x0D, 0x36, +- 0x0D, 0x00, 0x0E, 0x36, 0x1E, 0x00, 0x0F, 0x36, 0x32, 0x00, 0x02, 0x60, 0x00, 0x64, 0x08, 0x00, +- 0x04, 0x60, 0x00, 0x64, 0x05, 0x00, 0x00, 0x60, 0x01, 0x64, 0x02, 0x00, 0x20, 0x60, 0x00, 0x64, +- 0x32, 0x45, 0xB4, 0x85, 0x45, 0x52, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xB0, 0x60, 0xC1, 0x63, +- 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x3F, 0x40, 0x02, 0x2B, 0x05, 0x00, 0x90, 0x60, 0x00, 0xE8, 0xAF, 0x60, 0xFD, 0x63, +- 0x04, 0x00, 0x91, 0x60, 0x00, 0xE8, 0xB0, 0x60, 0xAB, 0x63, 0x28, 0xE8, 0x0C, 0x60, 0x16, 0x64, +- 0xA0, 0xDD, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x91, 0x60, +- 0x00, 0xE8, 0x28, 0xE8, 0xD9, 0x60, 0xFE, 0x64, 0x32, 0x45, 0xA4, 0x85, 0x45, 0x52, 0x99, 0xFF, +- 0xA5, 0x4F, 0xFF, 0xB4, 0x07, 0xFB, 0x98, 0xFF, 0xA7, 0x60, 0x9B, 0x63, 0x0C, 0x60, 0x16, 0x64, +- 0xA0, 0xDD, 0x62, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x42, 0x6F, 0x6F, 0x74, 0x63, 0x6F, +- 0x64, 0x65, 0x20, 0x21, 0x21, 0x20, 0x20, 0x00, 0x53, 0x54, 0x41, 0x2F, 0x41, 0x50, 0x20, 0x46, +- 0x75, 0x6E, 0x63, 0x27, 0x73, 0x00, 0x20, 0x00, 0x02, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00, 0x00, +- 0x08, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x06, 0x00, +- 0x07, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x07, 0x00, 0x01, 0x00, +- 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, +- 0x40, 0x00, 0x32, 0x00, 0x32, 0x00, 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x40, 0x00, 0x32, 0x00, +- 0x36, 0x00, 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x40, 0x00, 0x3B, 0x00, 0x40, 0x00, 0x17, 0x00, +- 0x07, 0x00, 0x07, 0x00, 0x4A, 0x00, 0x40, 0x00, 0x4A, 0x00, 0x1E, 0x00, 0x0C, 0x00, 0x08, 0x00, +- 0x57, 0x00, 0x4D, 0x00, 0x57, 0x00, 0x2B, 0x00, 0x19, 0x00, 0x08, 0x00, 0x5D, 0x00, 0x53, 0x00, +- 0x5D, 0x00, 0x31, 0x00, 0x1F, 0x00, 0x08, 0x00, +- +-}; /* fw_image_4_data */ +- +-static const CFG_IDENTITY_STRCT fw_image_infoidentity[] = { +- { +- sizeof(CFG_IDENTITY_STRCT) / sizeof(hcf_16) - 1, +- CFG_FW_IDENTITY, +- COMP_ID_FW_AP, +- 2, /* Variant / +- 2, /* Major */ +- 36 /* Minor */ +- }, +- { 0000, 0000, 0000, 0000, 0000, 0000 } /* endsentinel */ +-}; +- +-static const CFG_PROG_STRCT fw_image_code[] = { +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, /* mode */ +- 0x0146, /* sizeof(fw_image_1_data), */ +- 0x00000060, /* Target address in NIC Memory */ +- 0x0000, /* CRC: yes/no TYPE: primary/station/tertiary */ +- (hcf_8 FAR *) fw_image_1_data +- }, +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, /* mode */ +- 0x1918, /* sizeof(fw_image_2_data), */ +- 0x00000C16, /* Target address in NIC Memory */ +- 0x0000, /* CRC: yes/no TYPE: primary/station/tertiary */ +- (hcf_8 FAR *) fw_image_2_data +- }, +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, /* mode */ +- 0x01bc, /* sizeof(fw_image_3_data), */ +- 0x001E252E, /* Target address in NIC Memory */ +- 0x0000, /* CRC: yes/no TYPE: primary/station/tertiary */ +- (hcf_8 FAR *) fw_image_3_data +- }, +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, /* mode */ +- 0xab28, /* sizeof(fw_image_4_data), */ +- 0x001F4000, /* Target address in NIC Memory */ +- 0x0000, /* CRC: yes/no TYPE: primary/station/tertiary */ +- (hcf_8 FAR *) fw_image_4_data +- }, +- { +- 5, +- CFG_PROG, +- CFG_PROG_STOP, /* mode*/ +- 0000, +- 0x000F1297, /* Start execution address */ +- }, +- { 0000, 0000, 0000, 0000, 00000000, 0000, 00000000} +-}; +- +-static const CFG_RANGE20_STRCT fw_image_infocompat[] = { +- { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), +- CFG_FW_SUP_RANGE, +- COMP_ROLE_SUPL, +- COMP_ID_APF, +- { +- { 2, 2, 4 } /* variant, bottom, top */ +- } +- }, +- { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), +- CFG_MFI_ACT_RANGES_STA, +- COMP_ROLE_ACT, +- COMP_ID_MFI, +- { +- { 4, 6, 7 }, /* variant, bottom, top */ +- { 5, 6, 7 }, /* variant, bottom, top */ +- { 6, 6, 7 } /* variant, bottom, top */ +- } +- }, +- { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), +- CFG_CFI_ACT_RANGES_STA, +- COMP_ROLE_ACT, +- COMP_ID_CFI, +- { +- { 2, 1, 2 } /* variant, bottom, top */ +- } +- }, +- { 0000, 0000, 0000, 0000, { { 0000, 0000, 0000 } } } /* endsentinel */ +-}; +- +-memimage fw_image = { +- "FUPU7D37dhfwci\001C", /* signature, , C/Bin type */ +- (CFG_PROG_STRCT *) fw_image_code, +- 0x000F1297, +- 00000000, /* (dummy) pdaplug */ +- 00000000, /* (dummy) priplug */ +- (CFG_RANGE20_STRCT *) fw_image_infocompat, +- (CFG_IDENTITY_STRCT *) fw_image_infoidentity, +-}; +- +diff --git a/drivers/staging/wlags49_h2/ap_h25.c b/drivers/staging/wlags49_h2/ap_h25.c +deleted file mode 100644 +index f4491cb..0000000 +--- a/drivers/staging/wlags49_h2/ap_h25.c ++++ /dev/null +@@ -1,4094 +0,0 @@ +-/* +- * File: ap_h54.124 +- * +- * Abstract: This file contains memory image 'fw_image'. +- * +- * Contents: Total size of the memory image: 63146 bytes. +- * Total number of blocks: 4 blocks. +- * Block 1 : load address 00000060, 328 bytes. +- * Block 2 : load address 00000C16, 9266 bytes. +- * Block 3 : load address 001E3048, 6476 bytes. +- * Block 4 : load address 001F4000, 47076 bytes. +- * +- * Identity: component id: 32 (variant 3) version 1.24 +- * +- * Compatibility: +- * supplying interface 8 (variant 4) : 1 - 1 +- * acting on interface 1 (variant 7) : 3 - 3 +- * acting on interface 1 (variant 8) : 1 - 1 +- * acting on interface 2 (variant 4) : 1 - 2 +- * +- * Generated: by g:\fw\fupu3.exe version 4.26 +- * +- * Commandline: g:\fw\fupu3.exe /f=4 /n=fw_image /i=t3012400.hex +- */ +- +- +-#include "hcfcfg.h" // to get hcf_16 etc defined as well as +- // possible settings which inluence mdd.h or dhf.h +-#include "mdd.h" //to get COMP_ID_STA etc defined +-#include "dhf.h" //used to be "fhfmem.h", to get memblock,plugrecord, +- +-static const hcf_8 fw_image_1_data[] = { +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x0C, 0x00, 0x00, +- 0x02, 0x0D, 0x00, 0x00, 0x02, 0x0D, 0xD6, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, +- 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x09, 0x00, +- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, +- 0x00, 0x00, 0xFF, 0x07, 0x02, 0x00, 0x64, 0x00, 0x64, 0x00, 0x10, 0x27, 0x10, 0x27, 0x14, 0x00, +- 0xD0, 0x07, 0xD0, 0x07, 0x10, 0x27, 0x2F, 0x00, 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x02, 0x00, +- 0x02, 0x00, 0x10, 0x27, 0x05, 0x00, 0x00, 0x02, 0x00, 0x02, 0x13, 0x00, 0x07, 0x00, 0x03, 0x00, +- 0x32, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x09, 0x2B, 0x09, 0x2B, 0x09, 0xFF, 0x0F, +- 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x40, 0x00, 0x32, 0x00, 0x32, 0x00, +- 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- +-}; /* fw_image_1_data */ +- +-static const hcf_8 fw_image_2_data[] = { +- 0x7C, 0xA4, 0x00, 0x16, 0x08, 0x40, 0x0F, 0xD2, 0xE1, 0x28, 0xA5, 0x7C, 0x50, 0x30, 0xF1, 0x84, +- 0x44, 0x08, 0xAB, 0xAE, 0xA5, 0xB8, 0xFC, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, +- 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x84, 0xF8, +- 0x99, 0xEE, 0x8D, 0xF6, 0x0D, 0xFF, 0xBD, 0xD6, 0xB1, 0xDE, 0x54, 0x91, 0x50, 0x60, 0x03, 0x02, +- 0xA9, 0xCE, 0x7D, 0x56, 0x19, 0xE7, 0x62, 0xB5, 0xE6, 0x4D, 0x9A, 0xEC, 0x45, 0x8F, 0x9D, 0x1F, +- 0x40, 0x89, 0x87, 0xFA, 0x15, 0xEF, 0xEB, 0xB2, 0xC9, 0x8E, 0x0B, 0xFB, 0xEC, 0x41, 0x67, 0xB3, +- 0xFD, 0x5F, 0xEA, 0x45, 0xBF, 0x23, 0xF7, 0x53, 0x96, 0xE4, 0x5B, 0x9B, 0xC2, 0x75, 0x1C, 0xE1, +- 0xAE, 0x3D, 0x6A, 0x4C, 0x5A, 0x6C, 0x41, 0x7E, 0x02, 0xF5, 0x4F, 0x83, 0x5C, 0x68, 0xF4, 0x51, +- 0x34, 0xD1, 0x08, 0xF9, 0x93, 0xE2, 0x73, 0xAB, 0x53, 0x62, 0x3F, 0x2A, 0x0C, 0x08, 0x52, 0x95, +- 0x65, 0x46, 0x5E, 0x9D, 0x28, 0x30, 0xA1, 0x37, 0x0F, 0x0A, 0xB5, 0x2F, 0x09, 0x0E, 0x36, 0x24, +- 0x9B, 0x1B, 0x3D, 0xDF, 0x26, 0xCD, 0x69, 0x4E, 0xCD, 0x7F, 0x9F, 0xEA, 0x1B, 0x12, 0x9E, 0x1D, +- 0x74, 0x58, 0x2E, 0x34, 0x2D, 0x36, 0xB2, 0xDC, 0xEE, 0xB4, 0xFB, 0x5B, 0xF6, 0xA4, 0x4D, 0x76, +- 0x61, 0xB7, 0xCE, 0x7D, 0x7B, 0x52, 0x3E, 0xDD, 0x71, 0x5E, 0x97, 0x13, 0xF5, 0xA6, 0x68, 0xB9, +- 0x00, 0x00, 0x2C, 0xC1, 0x60, 0x40, 0x1F, 0xE3, 0xC8, 0x79, 0xED, 0xB6, 0xBE, 0xD4, 0x46, 0x8D, +- 0xD9, 0x67, 0x4B, 0x72, 0xDE, 0x94, 0xD4, 0x98, 0xE8, 0xB0, 0x4A, 0x85, 0x6B, 0xBB, 0x2A, 0xC5, +- 0xE5, 0x4F, 0x16, 0xED, 0xC5, 0x86, 0xD7, 0x9A, 0x55, 0x66, 0x94, 0x11, 0xCF, 0x8A, 0x10, 0xE9, +- 0x06, 0x04, 0x81, 0xFE, 0xF0, 0xA0, 0x44, 0x78, 0xBA, 0x25, 0xE3, 0x4B, 0xF3, 0xA2, 0xFE, 0x5D, +- 0xC0, 0x80, 0x8A, 0x05, 0xAD, 0x3F, 0xBC, 0x21, 0x48, 0x70, 0x04, 0xF1, 0xDF, 0x63, 0xC1, 0x77, +- 0x75, 0xAF, 0x63, 0x42, 0x30, 0x20, 0x1A, 0xE5, 0x0E, 0xFD, 0x6D, 0xBF, 0x4C, 0x81, 0x14, 0x18, +- 0x35, 0x26, 0x2F, 0xC3, 0xE1, 0xBE, 0xA2, 0x35, 0xCC, 0x88, 0x39, 0x2E, 0x57, 0x93, 0xF2, 0x55, +- 0x82, 0xFC, 0x47, 0x7A, 0xAC, 0xC8, 0xE7, 0xBA, 0x2B, 0x32, 0x95, 0xE6, 0xA0, 0xC0, 0x98, 0x19, +- 0xD1, 0x9E, 0x7F, 0xA3, 0x66, 0x44, 0x7E, 0x54, 0xAB, 0x3B, 0x83, 0x0B, 0xCA, 0x8C, 0x29, 0xC7, +- 0xD3, 0x6B, 0x3C, 0x28, 0x79, 0xA7, 0xE2, 0xBC, 0x1D, 0x16, 0x76, 0xAD, 0x3B, 0xDB, 0x56, 0x64, +- 0x4E, 0x74, 0x1E, 0x14, 0xDB, 0x92, 0x0A, 0x0C, 0x6C, 0x48, 0xE4, 0xB8, 0x5D, 0x9F, 0x6E, 0xBD, +- 0xEF, 0x43, 0xA6, 0xC4, 0xA8, 0x39, 0xA4, 0x31, 0x37, 0xD3, 0x8B, 0xF2, 0x32, 0xD5, 0x43, 0x8B, +- 0x59, 0x6E, 0xB7, 0xDA, 0x8C, 0x01, 0x64, 0xB1, 0xD2, 0x9C, 0xE0, 0x49, 0xB4, 0xD8, 0xFA, 0xAC, +- 0x07, 0xF3, 0x25, 0xCF, 0xAF, 0xCA, 0x8E, 0xF4, 0xE9, 0x47, 0x18, 0x10, 0xD5, 0x6F, 0x88, 0xF0, +- 0x6F, 0x4A, 0x72, 0x5C, 0x24, 0x38, 0xF1, 0x57, 0xC7, 0x73, 0x51, 0x97, 0x23, 0xCB, 0x7C, 0xA1, +- 0x9C, 0xE8, 0x21, 0x3E, 0xDD, 0x96, 0xDC, 0x61, 0x86, 0x0D, 0x85, 0x0F, 0x90, 0xE0, 0x42, 0x7C, +- 0xC4, 0x71, 0xAA, 0xCC, 0xD8, 0x90, 0x05, 0x06, 0x01, 0xF7, 0x12, 0x1C, 0xA3, 0xC2, 0x5F, 0x6A, +- 0xF9, 0xAE, 0xD0, 0x69, 0x91, 0x17, 0x58, 0x99, 0x27, 0x3A, 0xB9, 0x27, 0x38, 0xD9, 0x13, 0xEB, +- 0xB3, 0x2B, 0x33, 0x22, 0xBB, 0xD2, 0x70, 0xA9, 0x89, 0x07, 0xA7, 0x33, 0xB6, 0x2D, 0x22, 0x3C, +- 0x92, 0x15, 0x20, 0xC9, 0x49, 0x87, 0xFF, 0xAA, 0x78, 0x50, 0x7A, 0xA5, 0x8F, 0x03, 0xF8, 0x59, +- 0x80, 0x09, 0x17, 0x1A, 0xDA, 0x65, 0x31, 0xD7, 0xC6, 0x84, 0xB8, 0xD0, 0xC3, 0x82, 0xB0, 0x29, +- 0x77, 0x5A, 0x11, 0x1E, 0xCB, 0x7B, 0xFC, 0xA8, 0xD6, 0x6D, 0x3A, 0x2C, 0x00, 0x30, 0x00, 0x31, +- 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x38, 0x00, 0x3A, +- 0x00, 0x3B, 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x3F, 0x59, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x21, 0x10, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x20, 0x03, 0xE0, 0x01, 0x40, 0x01, 0x20, 0x03, 0xE0, 0x01, +- 0x40, 0x01, 0x18, 0x08, 0xF0, 0x3F, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x02, 0x14, 0x05, 0x32, 0x0B, 0x37, +- 0x08, 0x50, 0x0B, 0x6E, 0x02, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x16, 0x00, 0x0C, 0x00, 0x12, 0x00, +- 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x48, 0x00, 0x60, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x39, 0x00, 0x20, 0x00, 0x39, 0x00, +- 0x39, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0xA4, 0x10, 0xF2, 0x10, 0xAA, 0x10, 0xEC, 0x10, 0xB0, 0x10, 0xE6, 0x10, 0xB6, 0x10, +- 0xE0, 0x10, 0xBC, 0x10, 0xDA, 0x10, 0xC2, 0x10, 0xD4, 0x10, 0xC8, 0x10, 0xCE, 0x10, 0x07, 0x01, +- 0x00, 0x00, 0x16, 0x22, 0x00, 0x04, 0x08, 0x01, 0x00, 0x00, 0x16, 0x26, 0x00, 0x04, 0x09, 0x01, +- 0x00, 0x00, 0x16, 0x2A, 0x00, 0x04, 0x0A, 0x01, 0x00, 0x00, 0x16, 0x2E, 0x00, 0x04, 0x0B, 0x01, +- 0x00, 0x00, 0x10, 0x24, 0x04, 0x04, 0x0C, 0x01, 0x00, 0x00, 0x10, 0x28, 0x04, 0x04, 0x0D, 0x01, +- 0x00, 0x00, 0x10, 0x2C, 0x04, 0x04, 0x0E, 0x01, 0x00, 0x00, 0x10, 0x30, 0x04, 0x04, 0x0F, 0x01, +- 0x00, 0x00, 0x14, 0x34, 0x08, 0x84, 0x10, 0x01, 0x00, 0x00, 0x14, 0x38, 0x08, 0x84, 0x11, 0x01, +- 0x00, 0x00, 0x14, 0x3C, 0x08, 0x84, 0x12, 0x01, 0x00, 0x00, 0x14, 0x40, 0x08, 0x84, 0x13, 0x01, +- 0x00, 0x00, 0x17, 0x64, 0x0C, 0x8B, 0x14, 0x01, 0x00, 0x00, 0x17, 0x68, 0x0C, 0x8B, 0x15, 0x01, +- 0x00, 0x00, 0x17, 0x6C, 0x0C, 0x8B, 0x16, 0x01, 0x00, 0x00, 0x17, 0x70, 0x0C, 0x8B, 0x17, 0x01, +- 0x00, 0x00, 0x17, 0x74, 0x0C, 0x8B, 0x18, 0x01, 0x00, 0x00, 0x17, 0x78, 0x0C, 0x8B, 0x19, 0x01, +- 0x00, 0x00, 0x17, 0x7C, 0x0C, 0x8B, 0x1A, 0x01, 0x00, 0x00, 0x17, 0x80, 0x0C, 0x8B, 0x1B, 0x01, +- 0x00, 0x00, 0x17, 0x84, 0x0C, 0x8B, 0x1C, 0x01, 0x00, 0x00, 0x17, 0x88, 0x0C, 0x8B, 0x1D, 0x01, +- 0x00, 0x00, 0x17, 0x8C, 0x0C, 0x8B, 0x1E, 0x01, 0x00, 0x00, 0x0E, 0x95, 0x17, 0x04, 0x1F, 0x01, +- 0x00, 0x00, 0x0E, 0x99, 0x17, 0x04, 0x20, 0x01, 0x00, 0x00, 0x0E, 0x9D, 0x17, 0x04, 0x21, 0x01, +- 0x00, 0x00, 0x0E, 0xA1, 0x17, 0x04, 0x22, 0x01, 0x00, 0x00, 0x0E, 0xA5, 0x00, 0x00, 0x14, 0x11, +- 0x34, 0x11, 0x54, 0x11, 0x74, 0x11, 0xCC, 0x11, 0x1C, 0x11, 0x3C, 0x11, 0x5C, 0x11, 0x7C, 0x11, +- 0xD4, 0x11, 0x24, 0x11, 0x44, 0x11, 0x64, 0x11, 0x84, 0x11, 0xDC, 0x11, 0x2C, 0x11, 0x4C, 0x11, +- 0x6C, 0x11, 0x8C, 0x11, 0xE4, 0x11, 0x94, 0x11, 0x9C, 0x11, 0xA4, 0x11, 0xAC, 0x11, 0xB4, 0x11, +- 0xBC, 0x11, 0xC4, 0x11, 0xEC, 0x11, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, +- 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, +- 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, +- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, +- 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x10, 0x10, 0x10, 0x10, +- 0x17, 0x17, 0x17, 0x17, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x14, +- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +- 0x14, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x11, 0x11, 0x11, 0x11, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x14, 0x14, +- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x16, 0x16, 0x16, 0x16, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, +- 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0A, 0x0A, 0x0A, +- 0x0A, 0x7F, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x10, 0x10, 0x10, 0x10, 0x7F, 0x14, 0x14, 0x14, 0x14, +- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +- 0x14, 0x14, 0x14, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x9D, 0x9D, 0xA1, 0xAA, 0x10, 0x10, +- 0x9D, 0x9D, 0x08, 0x02, 0x06, 0x00, 0xA5, 0xA5, 0xAA, 0xAA, 0x17, 0x17, 0xA2, 0xA2, 0x15, 0x05, +- 0x07, 0x00, 0xAA, 0xAA, 0xB4, 0xB4, 0x1C, 0x1C, 0xA7, 0xA7, 0x1C, 0x0A, 0x08, 0x00, 0xB7, 0xB7, +- 0xC1, 0xC1, 0x09, 0x09, 0xB4, 0xB4, 0x29, 0x17, 0x08, 0x00, 0xBD, 0xBD, 0xC7, 0xC7, 0x0F, 0x0F, +- 0xBA, 0xBA, 0x2F, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x17, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0xE4, 0xF0, 0xFD, 0xF0, 0x1F, 0xF1, 0x60, 0xF6, 0x9B, 0xF0, 0x79, 0xF6, 0x9B, 0xF0, 0x9B, 0xF0, +- 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0xCC, 0xF7, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, +- 0x9B, 0xF0, 0x15, 0xF3, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, +- 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, +- 0x9B, 0xF0, 0x66, 0xF3, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, +- 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, +- 0xE3, 0xF2, 0xFE, 0xF2, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, 0x9B, 0xF0, +- 0xB4, 0x1C, 0x59, 0xF1, 0x6C, 0xF1, 0x1C, 0xF2, 0x20, 0xF2, 0x9B, 0xF0, 0x9B, 0xF0, 0xCF, 0xF2, +- 0x64, 0xE6, 0x3E, 0xE6, 0x92, 0xE6, 0xE1, 0xE6, 0xA9, 0xE7, 0xCF, 0xE7, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x12, 0xF1, 0x35, 0xF1, 0x5D, 0xF6, 0x5D, 0xF6, 0x6D, 0xF6, 0x86, 0xF6, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0xC0, 0xF3, 0xF2, 0xF5, 0x5A, 0x00, 0x02, 0x00, 0xF9, 0xFF, +- 0xC0, 0xF3, 0xD6, 0xF3, 0xCA, 0x00, 0x02, 0x00, 0xF7, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xB0, 0x26, +- 0x06, 0x00, 0xF0, 0xFF, 0xC0, 0xF3, 0xAA, 0xF3, 0x00, 0x00, 0x00, 0x02, 0xF6, 0xFF, 0xC0, 0xF3, +- 0xD6, 0xF3, 0x6C, 0x00, 0x02, 0x00, 0xF4, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0x68, 0x01, 0x02, 0x00, +- 0xF5, 0xFF, 0xC0, 0xF3, 0xFB, 0xF5, 0xA2, 0x26, 0x02, 0x00, 0xED, 0xFF, 0xC0, 0xF3, 0x0D, 0xF6, +- 0x9E, 0x2B, 0x02, 0x00, 0xEC, 0xFF, 0xC0, 0xF3, 0x3B, 0xF6, 0xA0, 0x2B, 0x02, 0x00, 0xEB, 0xFF, +- 0xC0, 0xF3, 0x41, 0xF6, 0xA2, 0x2B, 0x02, 0x00, 0xEE, 0xFF, 0xC0, 0xF3, 0x47, 0xF6, 0xD6, 0x2B, +- 0x02, 0x00, 0xDA, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xD0, 0x13, 0x0C, 0x00, 0xEA, 0xFF, 0xC0, 0xF3, +- 0xAA, 0xF3, 0xEC, 0x2B, 0x06, 0x00, 0xE9, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xF2, 0x2B, 0x02, 0x00, +- 0xE8, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xF4, 0x2B, 0x02, 0x00, 0xE7, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, +- 0xF6, 0x2B, 0x02, 0x00, 0xE6, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xF8, 0x2B, 0x02, 0x00, 0xE5, 0xFF, +- 0xC0, 0xF3, 0xD6, 0xF3, 0xFA, 0x2B, 0x10, 0x00, 0xE4, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0x0A, 0x2C, +- 0x18, 0x00, 0xDB, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0x22, 0x2C, 0x02, 0x00, 0xDC, 0xFF, 0xC0, 0xF3, +- 0xD6, 0xF3, 0x24, 0x2C, 0x02, 0x00, 0xE1, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xC6, 0x2C, 0x02, 0x00, +- 0xE0, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, 0xC4, 0x2C, 0x02, 0x00, 0xE3, 0xFF, 0xC0, 0xF3, 0xD6, 0xF3, +- 0xA8, 0x2C, 0x02, 0x00, 0xE2, 0xFF, 0x0E, 0xF4, 0xAA, 0xF3, 0x7E, 0x2C, 0x24, 0x00, 0x03, 0xFC, +- 0xC0, 0xF3, 0x3A, 0xF5, 0x92, 0x2B, 0x02, 0x00, 0x04, 0xFC, 0xC0, 0xF3, 0xD0, 0xF3, 0xBA, 0x26, +- 0x22, 0x00, 0x06, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0xA0, 0x26, 0x02, 0x00, 0x07, 0xFC, 0xC0, 0xF3, +- 0xD6, 0xF3, 0xFE, 0x26, 0x02, 0x00, 0x0E, 0xFC, 0xC0, 0xF3, 0x63, 0xF5, 0x08, 0x27, 0x22, 0x00, +- 0xB1, 0xFC, 0xC0, 0xF3, 0x88, 0xF8, 0x2A, 0x28, 0x02, 0x00, 0x20, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, +- 0x2E, 0x27, 0x02, 0x00, 0x25, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x3A, 0x27, 0x02, 0x00, 0x26, 0xFC, +- 0xC0, 0xF3, 0xD6, 0xF3, 0x3C, 0x27, 0x02, 0x00, 0x27, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x3E, 0x27, +- 0x02, 0x00, 0xB2, 0xFC, 0xC0, 0xF3, 0xD0, 0xF3, 0x4E, 0x28, 0x22, 0x00, 0xC1, 0xFC, 0xC0, 0xF3, +- 0xD6, 0xF3, 0x56, 0x2C, 0x20, 0x00, 0xB0, 0xFC, 0xA0, 0xF3, 0x8C, 0xF8, 0x00, 0x00, 0x00, 0x00, +- 0xC4, 0xFC, 0xA0, 0xF3, 0x54, 0xF6, 0x00, 0x00, 0x08, 0x00, 0xC8, 0xFC, 0xA0, 0xF3, 0x52, 0xF6, +- 0x00, 0x00, 0x08, 0x00, 0xB4, 0xFC, 0xA0, 0xF3, 0xC0, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xB6, 0xFC, +- 0xA0, 0xF3, 0x6A, 0xF9, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xFC, 0xA0, 0xF3, 0xAC, 0xF9, 0x00, 0x00, +- 0x00, 0x00, 0xB8, 0xFC, 0xA0, 0xF3, 0x02, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xBC, 0xFC, 0xA0, 0xF3, +- 0x3B, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xBD, 0xFC, 0xA0, 0xF3, 0xC3, 0xFA, 0x00, 0x00, 0x00, 0x00, +- 0xBE, 0xFC, 0xA0, 0xF3, 0xEF, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xBF, 0xFC, 0xA0, 0xF3, 0x3C, 0xFB, +- 0x00, 0x00, 0x00, 0x00, 0xB3, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0xA2, 0x0F, 0x10, 0x00, 0xB5, 0xFC, +- 0xC0, 0xF3, 0xD6, 0xF3, 0xA4, 0x2C, 0x02, 0x00, 0xB9, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0xA6, 0x2C, +- 0x02, 0x00, 0x90, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0xAA, 0x2C, 0x02, 0x00, 0x88, 0xFC, 0xC0, 0xF3, +- 0xD6, 0xF3, 0x78, 0x2B, 0x04, 0x00, 0x89, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x7C, 0x2B, 0x04, 0x00, +- 0xC5, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x80, 0x2B, 0x04, 0x00, 0x23, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, +- 0x34, 0x27, 0x04, 0x00, 0x2A, 0xFC, 0xC0, 0xF3, 0x2C, 0xF4, 0xB6, 0x26, 0x02, 0x00, 0xC7, 0xFD, +- 0xC0, 0xF3, 0xAA, 0xF3, 0xA6, 0x2B, 0x0A, 0x00, 0x29, 0xFC, 0x7F, 0xF4, 0x43, 0xF4, 0x00, 0x00, +- 0x00, 0x00, 0xC2, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x86, 0x2B, 0x08, 0x00, 0x32, 0xFC, 0xC0, 0xF3, +- 0xD6, 0xF3, 0x5C, 0x01, 0x02, 0x00, 0x33, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x5E, 0x01, 0x02, 0x00, +- 0x35, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x8E, 0x2B, 0x02, 0x00, 0xC7, 0xFC, 0xC0, 0xF3, 0xEB, 0xF5, +- 0x90, 0x2B, 0x02, 0x00, 0x10, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0xA8, 0x26, 0x02, 0x00, 0x11, 0xFC, +- 0xC0, 0xF3, 0xD6, 0xF3, 0x44, 0x27, 0x06, 0x00, 0x12, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x4A, 0x27, +- 0x06, 0x00, 0x13, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x50, 0x27, 0x06, 0x00, 0x14, 0xFC, 0xC0, 0xF3, +- 0xD6, 0xF3, 0x56, 0x27, 0x06, 0x00, 0x15, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x5C, 0x27, 0x06, 0x00, +- 0x16, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x62, 0x27, 0x06, 0x00, 0x17, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, +- 0x2A, 0x27, 0x02, 0x00, 0x83, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x6C, 0x01, 0x02, 0x00, 0x97, 0xFC, +- 0xC0, 0xF3, 0xD6, 0xF3, 0x6A, 0x01, 0x02, 0x00, 0x98, 0xFC, 0xD7, 0xF5, 0xC5, 0xF5, 0xEC, 0x00, +- 0x02, 0x00, 0x99, 0xFC, 0xD7, 0xF5, 0xC5, 0xF5, 0xEC, 0x02, 0x02, 0x00, 0x9A, 0xFC, 0xD7, 0xF5, +- 0xC5, 0xF5, 0xEC, 0x04, 0x02, 0x00, 0x9B, 0xFC, 0xD7, 0xF5, 0xC5, 0xF5, 0xEC, 0x06, 0x02, 0x00, +- 0x9C, 0xFC, 0xD7, 0xF5, 0xC5, 0xF5, 0xEC, 0x08, 0x02, 0x00, 0x9D, 0xFC, 0xD7, 0xF5, 0xC5, 0xF5, +- 0xEC, 0x0A, 0x02, 0x00, 0x18, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x2C, 0x27, 0x02, 0x00, 0x22, 0xFC, +- 0xC0, 0xF3, 0xD6, 0xF3, 0x32, 0x27, 0x02, 0x00, 0x24, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x38, 0x27, +- 0x02, 0x00, 0xC0, 0xFC, 0xA0, 0xF3, 0x50, 0xF6, 0x00, 0x00, 0x06, 0x00, 0x9E, 0xFC, 0xC0, 0xF3, +- 0x83, 0xF5, 0x6E, 0x01, 0x04, 0x00, 0x9F, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x3E, 0x2C, 0x04, 0x00, +- 0xA0, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x42, 0x2C, 0x04, 0x00, 0xA1, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, +- 0x46, 0x2C, 0x04, 0x00, 0xA2, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x4A, 0x2C, 0x04, 0x00, 0xA3, 0xFC, +- 0xC0, 0xF3, 0xD6, 0xF3, 0x4E, 0x2C, 0x04, 0x00, 0xA4, 0xFC, 0xC0, 0xF3, 0xD6, 0xF3, 0x52, 0x2C, +- 0x04, 0x00, 0x20, 0xFD, 0xF1, 0xF3, 0xAA, 0xF3, 0xD5, 0xFB, 0x08, 0x00, 0x21, 0xFD, 0xF1, 0xF3, +- 0xAA, 0xF3, 0xD9, 0xFB, 0x0A, 0x00, 0x22, 0xFD, 0xF1, 0xF3, 0xAA, 0xF3, 0xDE, 0xFB, 0x16, 0x00, +- 0x23, 0xFD, 0xF1, 0xF3, 0xAA, 0xF3, 0xE9, 0xFB, 0x0A, 0x00, 0x45, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, +- 0xCA, 0x00, 0x02, 0x00, 0x47, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0x36, 0x01, 0x02, 0x00, 0x48, 0xFD, +- 0xD4, 0xF4, 0xAA, 0xF3, 0x5C, 0x01, 0x02, 0x00, 0x49, 0xFD, 0xD4, 0xF4, 0xAA, 0xF3, 0x5E, 0x01, +- 0x02, 0x00, 0x4A, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0x56, 0x01, 0x02, 0x00, 0x4B, 0xFD, 0xC0, 0xF3, +- 0xAA, 0xF3, 0x58, 0x01, 0x02, 0x00, 0x4D, 0xFD, 0xF1, 0xF3, 0xAA, 0xF3, 0xEE, 0xFB, 0x08, 0x00, +- 0x4F, 0xFD, 0xE8, 0xF4, 0xAA, 0xF3, 0x96, 0x2B, 0x02, 0x00, 0xC2, 0xFD, 0xDE, 0xF4, 0xAA, 0xF3, +- 0x00, 0x00, 0x02, 0x00, 0x40, 0xFD, 0xE9, 0xF3, 0xAA, 0xF3, 0x78, 0x01, 0x02, 0x00, 0x24, 0xFD, +- 0x01, 0xF5, 0xAA, 0xF3, 0x00, 0x00, 0x02, 0x00, 0x91, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0xCC, 0x1E, +- 0x02, 0x00, 0x93, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0xD2, 0x1E, 0x02, 0x00, 0x8F, 0xFD, 0x0E, 0xF5, +- 0xAA, 0xF3, 0x00, 0x00, 0x08, 0x00, 0xC1, 0xFD, 0x92, 0xF6, 0xAA, 0xF3, 0xC8, 0x00, 0x02, 0x00, +- 0xC6, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0x20, 0x30, 0x04, 0x00, 0x25, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, +- 0x62, 0x01, 0x02, 0x00, 0x89, 0xFD, 0x96, 0xF4, 0xAA, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xFD, +- 0x0E, 0xF4, 0xAA, 0xF3, 0x7E, 0x2C, 0x24, 0x00, 0x46, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0x7A, 0x01, +- 0x06, 0x00, 0x86, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, 0xB0, 0x26, 0x06, 0x00, 0x87, 0xFD, 0xC0, 0xF3, +- 0xAA, 0xF3, 0x76, 0x2C, 0x06, 0x00, 0x8B, 0xFD, 0x96, 0xF9, 0xAA, 0xF3, 0x00, 0x00, 0x12, 0x00, +- 0x8B, 0xFD, 0x96, 0xF9, 0xAA, 0xF3, 0x00, 0x00, 0x12, 0x00, 0x8E, 0xFD, 0xC0, 0xF3, 0xAA, 0xF3, +- 0xEE, 0x14, 0x02, 0x00, 0x80, 0xFD, 0xEF, 0xF4, 0xAA, 0xF3, 0x22, 0x00, 0x02, 0x00, 0x81, 0xFD, +- 0xEF, 0xF4, 0xAA, 0xF3, 0x22, 0x02, 0x02, 0x00, 0x82, 0xFD, 0xEF, 0xF4, 0xAA, 0xF3, 0x22, 0x04, +- 0x02, 0x00, 0x83, 0xFD, 0xEF, 0xF4, 0xAA, 0xF3, 0x22, 0x06, 0x02, 0x00, 0x84, 0xFD, 0xEF, 0xF4, +- 0xAA, 0xF3, 0x22, 0x08, 0x02, 0x00, 0x85, 0xFD, 0xEF, 0xF4, 0xAA, 0xF3, 0x22, 0x0A, 0x02, 0x00, +- 0x00, 0xF1, 0x46, 0x00, 0x64, 0xF3, 0xF6, 0x00, 0x00, 0x03, 0x8E, 0xF7, 0x1F, 0x00, 0x34, 0x01, +- 0xC8, 0x00, 0x96, 0x01, 0xCC, 0x00, 0xFA, 0x00, 0x78, 0x01, 0xD2, 0x25, 0x18, 0x01, 0xCC, 0x1E, +- 0xC8, 0x00, 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x06, 0x17, 0x12, 0x01, 0x03, 0x00, 0xAE, 0x00, +- 0xEC, 0x00, 0x44, 0x00, 0xDC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x09, 0x08, 0x24, 0x28, 0x06, +- 0x0C, 0x18, 0x08, 0x30, 0x14, 0x0C, 0x08, 0x36, 0x10, 0x12, 0xA1, 0xB6, 0x14, 0xB6, 0x50, 0xB7, +- 0x59, 0xB7, 0x25, 0xB6, 0xCE, 0xB6, 0x93, 0xB6, 0x15, 0x1C, 0xD0, 0x1A, 0x15, 0x1C, 0x8B, 0x1B, +- 0xEE, 0x1A, 0xCB, 0x1A, 0xD2, 0x1B, 0xF1, 0x1B, 0x06, 0x1C, 0x48, 0x1C, 0x74, 0x1C, 0x74, 0x1B, +- 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, +- 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x23, 0x46, 0x23, 0x46, 0x23, 0x46, 0x1C, 0x47, 0x1C, 0x47, +- 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, +- 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1D, 0x47, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, +- 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, +- 0x9A, 0x48, 0x33, 0x48, 0x78, 0x49, 0x78, 0x49, 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, +- 0x7A, 0x49, 0x7A, 0x49, 0x7A, 0x49, 0x7A, 0x49, 0x7B, 0x49, 0x7B, 0x49, 0x7B, 0x49, 0x7C, 0x49, +- 0xD8, 0x03, 0xDC, 0x03, 0xE0, 0x03, 0xE4, 0x03, 0xF0, 0x03, 0xF4, 0x03, 0xF8, 0x03, 0x0A, 0x04, +- 0x0E, 0x04, 0x12, 0x04, 0x16, 0x04, 0x0C, 0x04, 0x10, 0x04, 0x14, 0x04, 0x18, 0x04, 0x1C, 0x04, +- 0x20, 0x04, 0x24, 0x04, 0x28, 0x04, 0x4C, 0x04, 0x50, 0x04, 0x54, 0x04, 0x58, 0x04, 0x5C, 0x04, +- 0x60, 0x04, 0x64, 0x04, 0x68, 0x04, 0x6C, 0x04, 0x70, 0x04, 0x74, 0x04, 0x7D, 0x04, 0x81, 0x04, +- 0x85, 0x04, 0x89, 0x04, 0x8D, 0x04, 0x10, 0x00, 0x8E, 0x19, 0xAC, 0x00, 0x04, 0x00, 0x00, 0x00, +- 0x00, 0x80, 0x3C, 0x0C, 0x00, 0x00, 0xFF, 0x3F, 0x44, 0x04, 0x00, 0x00, 0xD3, 0x22, 0x44, 0x04, +- 0x9C, 0x02, 0xCB, 0x54, 0x44, 0x04, 0x00, 0x00, 0x01, 0x00, 0x44, 0x04, 0x00, 0x00, 0x00, 0x03, +- 0x00, 0x0C, 0x71, 0x00, 0x30, 0x50, 0x20, 0x00, 0x80, 0xBF, 0x1F, 0xA6, 0x28, 0x00, 0x0B, 0x02, +- 0x60, 0x84, 0x4C, 0x00, 0x02, 0x00, 0x4B, 0x1C, 0x98, 0x00, 0x00, 0x00, 0x20, 0x0B, 0x34, 0x04, +- 0xFD, 0x34, 0x34, 0x00, 0x38, 0x04, 0xFD, 0x34, 0x34, 0x00, 0x3C, 0x04, 0x01, 0x00, 0x10, 0x00, +- 0x00, 0x08, 0x00, 0x52, 0x14, 0x00, 0x04, 0x08, 0x0E, 0x32, 0x00, 0xA6, 0x10, 0x08, 0xC4, 0x03, +- 0x50, 0x60, 0x18, 0x08, 0xF0, 0x3F, 0xFC, 0x01, 0x10, 0x0C, 0x00, 0x00, 0x80, 0x04, 0x14, 0x0C, +- 0x00, 0x00, 0x00, 0x41, 0x20, 0x0C, 0xB0, 0x00, 0xB0, 0xB8, 0x24, 0x0C, 0x00, 0x00, 0xAB, 0x05, +- 0x2C, 0x0C, 0x80, 0x05, 0x00, 0xFF, 0x30, 0x0C, 0x00, 0x00, 0xB0, 0x04, 0x34, 0x0C, 0x03, 0x00, +- 0x00, 0xE8, 0x44, 0x0C, 0x04, 0x00, 0xFF, 0x0F, 0x00, 0x10, 0x2E, 0x00, 0x0C, 0xE3, 0x44, 0x04, +- 0x00, 0x00, 0x01, 0x04, 0x44, 0x04, 0x00, 0x00, 0x01, 0x01, 0x44, 0x04, 0x00, 0x00, 0x01, 0x00, +- 0x44, 0x04, 0x00, 0x00, 0x01, 0x04, 0x44, 0x04, 0x00, 0x00, 0x80, 0x03, 0x48, 0x0C, 0x00, 0x00, +- 0x7F, 0x00, 0x04, 0x04, 0x08, 0x48, 0x00, 0x00, 0x04, 0x04, 0x08, 0x40, 0x00, 0x00, 0x00, 0x0C, +- 0x71, 0x00, 0x30, 0x30, 0x00, 0x00, 0x5E, 0x40, 0x01, 0x00, 0x18, 0x00, 0x36, 0xC0, 0xE8, 0x0E, +- 0x1C, 0x00, 0x78, 0xC8, 0xA5, 0x40, 0x24, 0x00, 0x9E, 0xB0, 0xB9, 0x95, 0x08, 0x08, 0x00, 0xEA, +- 0x40, 0x01, 0x0C, 0x08, 0x00, 0xEA, 0x00, 0x00, 0x1C, 0x08, 0x00, 0x00, 0x42, 0x07, 0x20, 0x08, +- 0x7B, 0x00, 0xD4, 0x09, 0x2C, 0x04, 0x14, 0x00, 0x50, 0x14, 0x30, 0x04, 0x28, 0x0F, 0x28, 0x7F, +- 0x18, 0x08, 0x20, 0x00, 0xFC, 0x01, 0x04, 0x10, 0x69, 0x00, 0xFD, 0xC3, 0x08, 0x10, 0x69, 0x00, +- 0xFD, 0xC3, 0x08, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0C, +- 0x00, 0x00, 0x7F, 0x00, 0x04, 0x04, 0x08, 0x48, 0x02, 0x00, 0x00, 0x00, 0x5E, 0x48, 0x00, 0x00, +- 0x04, 0x04, 0x08, 0x40, 0x02, 0x00, 0x00, 0x0C, 0x71, 0x00, 0x30, 0x50, 0x00, 0x00, 0x5E, 0x48, +- 0x01, 0x00, 0x18, 0x00, 0x3A, 0xC0, 0xE8, 0x04, 0x1C, 0x00, 0x78, 0xD0, 0xA5, 0x40, 0x24, 0x00, +- 0x9E, 0xB0, 0xB9, 0x85, 0x2C, 0x04, 0x14, 0x00, 0x50, 0x14, 0x30, 0x04, 0x28, 0x0F, 0x28, 0x7F, +- 0x08, 0x08, 0x00, 0xEA, 0x40, 0x01, 0x0C, 0x08, 0x00, 0xEA, 0x00, 0x00, 0x1C, 0x08, 0x00, 0x00, +- 0x42, 0x07, 0x20, 0x08, 0x7B, 0x00, 0xD4, 0x09, 0x18, 0x08, 0xF0, 0x3F, 0xFC, 0x01, 0x04, 0x10, +- 0x69, 0x00, 0xDD, 0xCD, 0x08, 0x10, 0x69, 0x00, 0xDD, 0xCD, 0x08, 0x0C, 0x00, 0x00, 0x00, 0x00, +- 0x48, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x40, 0x01, 0x41, 0x01, 0x0C, 0x04, 0x40, 0x04, +- 0x41, 0x04, 0x10, 0x04, 0xD6, 0x08, 0x56, 0x0A, 0x14, 0x04, 0x42, 0x02, 0x56, 0x0A, 0x18, 0x04, +- 0x56, 0x0A, 0x40, 0x02, 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x20, 0x04, 0xC2, 0x00, 0xD6, 0x08, +- 0x24, 0x04, 0xD6, 0x08, 0xC0, 0x00, 0x28, 0x04, 0xC2, 0x08, 0xC2, 0x28, 0x08, 0x04, 0x40, 0x01, +- 0x41, 0x01, 0x0C, 0x04, 0x00, 0x01, 0x01, 0x01, 0x10, 0x04, 0x56, 0x0A, 0x56, 0x0A, 0x14, 0x04, +- 0x42, 0x02, 0x56, 0x0A, 0x18, 0x04, 0x56, 0x0A, 0x40, 0x02, 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, +- 0x20, 0x04, 0x42, 0x02, 0x56, 0x0A, 0x24, 0x04, 0x56, 0x0A, 0x40, 0x02, 0x28, 0x04, 0x42, 0x0A, +- 0x42, 0x2A, 0x08, 0x04, 0x40, 0x01, 0x41, 0x01, 0x0C, 0x04, 0x40, 0x04, 0x41, 0x04, 0x10, 0x04, +- 0xCE, 0x08, 0x4E, 0x0A, 0x14, 0x04, 0x42, 0x02, 0x4E, 0x0A, 0x18, 0x04, 0x4E, 0x0A, 0x40, 0x02, +- 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x20, 0x04, 0xC2, 0x00, 0xCE, 0x08, 0x24, 0x04, 0xCE, 0x08, +- 0xC0, 0x00, 0x28, 0x04, 0xC2, 0x08, 0xC2, 0x28, 0x08, 0x04, 0x40, 0x01, 0x41, 0x01, 0x0C, 0x04, +- 0x00, 0x01, 0x01, 0x01, 0x10, 0x04, 0x4E, 0x0A, 0x4E, 0x0A, 0x14, 0x04, 0x42, 0x02, 0x4E, 0x0A, +- 0x18, 0x04, 0x4E, 0x0A, 0x40, 0x02, 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x20, 0x04, 0x42, 0x02, +- 0x4E, 0x0A, 0x24, 0x04, 0x4E, 0x0A, 0x40, 0x02, 0x28, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, +- 0x05, 0x00, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, +- 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, +- 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, +- 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x17, 0xA0, 0x17, 0xA0, 0x17, +- 0xA0, 0x18, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, +- 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, +- 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, +- 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, +- 0xFF, 0x06, 0x00, 0x00, 0x65, 0x00, 0x65, 0x00, 0x65, 0x00, 0x65, 0x00, 0x5D, 0x00, 0x52, 0x00, +- 0x48, 0x00, 0x40, 0x00, 0x38, 0x00, 0x31, 0x00, 0x2C, 0x00, 0x27, 0x00, 0x23, 0x00, 0x1F, 0x00, +- 0x00, 0x00, 0x65, 0x00, 0x65, 0x00, 0x65, 0x00, 0x65, 0x00, 0x5D, 0x00, 0x52, 0x00, 0x48, 0x00, +- 0x40, 0x00, 0x38, 0x00, 0x31, 0x00, 0x2C, 0x00, 0x27, 0x00, 0x23, 0x00, 0x1F, 0x00, 0x00, 0x00, +- 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, +- 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, +- 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, +- 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, +- 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x01, 0x00, +- 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, +- 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x14, 0x00, 0x03, 0x00, 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, +- 0x69, 0x65, 0x64, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, +- 0x64, 0x00, 0x00, 0x00, 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, 0x00, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, +- 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x69, 0x72, 0x73, 0x74, 0x20, 0x57, 0x61, +- 0x76, 0x65, 0x4C, 0x41, 0x4E, 0x20, 0x49, 0x49, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0xFF, 0x0F, 0xF0, 0x0F, 0x0F, 0x00, 0x50, 0x01, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x14, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x07, 0x00, 0x30, 0x00, 0xFF, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, +- 0x0A, 0x00, 0x0A, 0x00, 0x0B, 0x00, 0x0B, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x0A, 0x00, +- 0x00, 0x00, 0x02, 0x01, 0x02, 0x04, 0x0B, 0x16, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x82, 0x84, +- 0x8B, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, +- 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x1B, 0x00, 0x17, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0B, 0x00, +- 0x0B, 0x00, 0x09, 0x00, 0x17, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0D, 0x00, 0x0B, 0x00, 0x09, 0x00, +- 0x08, 0x00, 0x07, 0x00, 0x0D, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x05, 0x00, 0x05, 0x00, +- 0xD8, 0x0C, 0xC0, 0x08, 0x90, 0x0D, 0x60, 0x09, 0x48, 0x0E, 0x30, 0x0A, 0x24, 0x0F, 0x18, 0x0B, +- 0x0B, 0x6E, 0x0B, 0x37, 0x02, 0x14, 0x01, 0x0A, 0xFF, 0x0F, 0xF0, 0x0F, 0xFF, 0x0F, 0xF0, 0x0F, +- 0xFF, 0x0F, 0xF0, 0x0F, 0xFF, 0x0F, 0xF0, 0x0F, 0xFF, 0x0F, 0xF0, 0x0F, 0xFF, 0x0F, 0xF0, 0x0F, +- 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xDD, 0x00, 0x50, 0xF2, 0x01, 0x01, 0x00, +- 0x00, 0x50, 0xF2, 0x05, 0x02, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x50, 0xF2, 0x04, 0x02, 0x00, +- 0x00, 0x50, 0xF2, 0x00, 0x00, 0x50, 0xF2, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x15, 0x00, 0x02, 0x00, +- 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x04, 0x00, 0x10, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, +- 0x15, 0x00, 0x20, 0x00, 0x11, 0x00, 0x20, 0x00, 0x16, 0x26, 0xE2, 0x2B, 0xEA, 0x2D, 0xC4, 0x2D, +- 0xEE, 0x2D, 0x7E, 0x2C, 0x1E, 0x2E, 0x22, 0x2E, 0xFF, 0xFF, 0x2C, 0x2E, 0x00, 0x00, 0x4E, 0x28, +- 0xD8, 0x2B, 0x22, 0x2E, 0xFF, 0xFF, 0x00, 0x00, 0x16, 0x26, 0xE2, 0x2B, 0xEA, 0x2D, 0xFF, 0xFF, +- 0xEE, 0x2D, 0x7E, 0x2C, 0x1E, 0x2E, 0x22, 0x2E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0x2C, 0x2E, 0x00, 0x00, 0xE2, 0x2B, 0x34, 0x2E, 0x22, 0x2E, 0x00, 0x00, 0x00, 0x05, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2A, 0x00, 0x00, 0x08, 0x32, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x00, 0x60, 0x1D, 0x00, 0x00, 0x00, 0x0D, 0x81, +- 0x00, 0x60, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +- 0x00, 0x00, 0xDD, 0x00, 0xFF, 0xFF, 0x97, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x10, 0x00, 0x19, 0x0A, 0x09, 0x46, 0x1C, 0x60, 0x18, 0x00, 0x19, 0x1D, 0x09, 0x42, +- 0x1C, 0x60, +- +-}; /* fw_image_2_data */ +- +-static const hcf_8 fw_image_3_data[] = { +- 0x00, 0x60, 0x46, 0x74, 0xCD, 0xE2, 0x04, 0xE1, 0x02, 0x60, 0x00, 0xE1, 0x82, 0xF3, 0x21, 0x60, +- 0xCE, 0x61, 0x60, 0x40, 0x01, 0x2B, 0x02, 0x00, 0x21, 0x60, 0x56, 0x61, 0x0F, 0x60, 0xE8, 0x64, +- 0x59, 0xD1, 0x58, 0xD9, 0x59, 0xD1, 0x58, 0xD9, 0x3F, 0x44, 0x40, 0x26, 0x05, 0x00, 0x18, 0x60, +- 0x22, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x50, 0x3F, 0x40, 0x02, 0x2B, 0x03, 0x00, 0x18, 0x60, +- 0x74, 0x78, 0xFF, 0xFF, 0x04, 0x29, 0xFE, 0x01, 0xC4, 0xE2, 0x43, 0x64, 0x3A, 0xDB, 0x82, 0xF3, +- 0xFF, 0xFF, 0x60, 0x41, 0x3F, 0x44, 0xFF, 0x01, 0x3F, 0x40, 0x40, 0x26, 0x05, 0x00, 0x18, 0x60, +- 0x20, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x52, 0xC4, 0xE2, 0x00, 0x63, 0x81, 0xFD, 0x32, 0x7B, +- 0x4D, 0xE2, 0xBF, 0xFE, 0xC4, 0xE2, 0x41, 0xFF, 0xE0, 0xFE, 0xE1, 0xFE, 0xE2, 0xFE, 0x43, 0xFF, +- 0x44, 0xFF, 0x46, 0xFF, 0x83, 0xF3, 0x62, 0xFF, 0x60, 0x40, 0x05, 0x36, 0x2D, 0xFF, 0x07, 0x36, +- 0xD5, 0xFE, 0x08, 0xE1, 0x88, 0x60, 0x85, 0x71, 0x8D, 0xE2, 0xA3, 0x60, 0x30, 0x78, 0xFF, 0xFF, +- 0x00, 0x60, 0x10, 0x62, 0x1A, 0x60, 0x58, 0x4D, 0xB4, 0x78, 0xFF, 0xFF, 0x64, 0x41, 0xA9, 0x9C, +- 0x60, 0x45, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, 0x82, 0xF1, 0x09, 0x60, 0xB4, 0x61, +- 0x64, 0x44, 0x01, 0x27, 0x24, 0x00, 0x60, 0x40, 0x0E, 0x3A, 0x0D, 0x00, 0x01, 0x7C, 0x10, 0x60, +- 0xF2, 0xF9, 0x44, 0x60, 0x08, 0x7C, 0x10, 0x60, 0xC4, 0xF9, 0x12, 0x60, 0xE5, 0xF1, 0x02, 0x60, +- 0xB0, 0x61, 0xB1, 0x9C, 0x26, 0x00, 0x00, 0x7C, 0x10, 0x60, 0xF2, 0xF9, 0x40, 0x60, 0x08, 0x7C, +- 0x10, 0x60, 0xC4, 0xF9, 0x12, 0x60, 0xE5, 0xF1, 0x02, 0x60, 0x90, 0x61, 0xB1, 0x9C, 0x09, 0x60, +- 0x67, 0x65, 0xFF, 0xB4, 0xC4, 0x85, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, 0x12, 0x00, 0xFF, 0xB4, +- 0xED, 0xA0, 0x25, 0x60, 0xCC, 0x61, 0x04, 0x04, 0xE2, 0xA0, 0xD9, 0x81, 0x01, 0x04, 0xD9, 0x81, +- 0xA1, 0xD1, 0x02, 0x60, 0x50, 0x61, 0x1F, 0x60, 0xF6, 0x65, 0xE0, 0x84, 0x44, 0xD3, 0xB1, 0x9C, +- 0xC8, 0x81, 0x61, 0x47, 0x00, 0x7E, 0xE9, 0x81, 0x07, 0x60, 0xF0, 0x65, 0xA5, 0x81, 0x0B, 0xB9, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x85, 0xB5, 0x85, 0x04, 0x60, 0x44, 0x62, 0x1A, 0x60, 0x58, 0x4D, +- 0x88, 0x78, 0xFF, 0xFF, 0x82, 0xF3, 0xC8, 0x61, 0x61, 0x54, 0xCD, 0xE2, 0x60, 0x40, 0x01, 0x27, +- 0x2E, 0x00, 0xCC, 0x84, 0xE0, 0x85, 0x15, 0x60, 0xA2, 0xE7, 0x1F, 0x60, 0x86, 0x64, 0x1A, 0x60, +- 0x58, 0x4F, 0x7D, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0xA2, 0x64, 0x1A, 0x60, 0x58, 0x4F, 0x7D, 0x78, +- 0xFF, 0xFF, 0x1F, 0x60, 0xBE, 0x64, 0x1A, 0x60, 0x58, 0x4F, 0x7D, 0x78, 0xFF, 0xFF, 0x1F, 0x60, +- 0xDA, 0x64, 0x1A, 0x60, 0x58, 0x4F, 0x7D, 0x78, 0xFF, 0xFF, 0x75, 0x64, 0x06, 0x61, 0x61, 0x48, +- 0x60, 0x44, 0x80, 0xBC, 0xFF, 0xB4, 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x21, 0x60, +- 0xEC, 0x7C, 0x07, 0x60, 0xE9, 0xF9, 0x21, 0x60, 0x74, 0x63, 0x14, 0x61, 0x21, 0x00, 0x11, 0x60, +- 0x62, 0xF1, 0xFF, 0xB4, 0xED, 0xA0, 0x64, 0x41, 0x04, 0x04, 0xE2, 0xA0, 0xD9, 0x81, 0x01, 0x04, +- 0xD9, 0x81, 0xA1, 0xD1, 0x10, 0x60, 0x91, 0xF3, 0x64, 0x41, 0xFF, 0xB1, 0xFF, 0x60, 0x00, 0x65, +- 0xA4, 0x84, 0x34, 0x94, 0xA2, 0xDB, 0x5A, 0xD3, 0x64, 0x41, 0xA5, 0x81, 0xFF, 0xB4, 0x34, 0x94, +- 0xA2, 0xDB, 0x22, 0x60, 0x58, 0x7C, 0x07, 0x60, 0xE9, 0xF9, 0x21, 0x60, 0x02, 0x63, 0x13, 0x61, +- 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x07, 0x60, 0xE9, 0xF3, 0x31, 0x40, 0x80, 0x26, +- 0x36, 0xA4, 0x07, 0x60, 0xE9, 0xFB, 0x60, 0x43, 0x09, 0x61, 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, +- 0xFF, 0xFF, 0x82, 0xF3, 0x22, 0x60, 0xC4, 0x61, 0x00, 0x7C, 0x7E, 0x63, 0x59, 0xD9, 0xFE, 0x1F, +- 0x60, 0x40, 0x01, 0x27, 0x03, 0x00, 0x23, 0x60, 0x46, 0x65, 0x15, 0x00, 0xFF, 0xB4, 0xF9, 0xA0, +- 0x23, 0x60, 0x68, 0x65, 0x01, 0x7C, 0x0D, 0x04, 0xED, 0xA0, 0x23, 0x60, 0x8A, 0x65, 0x11, 0x7C, +- 0x08, 0x04, 0xE2, 0xA0, 0x23, 0x60, 0xAC, 0x65, 0x21, 0x7C, 0x03, 0x04, 0x23, 0x60, 0xCE, 0x65, +- 0x31, 0x7C, 0x64, 0x5F, 0x64, 0xFB, 0xA5, 0xD3, 0xDA, 0x85, 0xF0, 0xA0, 0x22, 0x60, 0xC4, 0x61, +- 0x08, 0x06, 0x40, 0x54, 0x58, 0x53, 0x08, 0xFF, 0xA2, 0x60, 0xE7, 0x64, 0x43, 0xFB, 0x08, 0xFF, +- 0xFF, 0x01, 0x60, 0x43, 0x60, 0x46, 0xA5, 0xD1, 0xDA, 0x85, 0xA5, 0xD3, 0xDA, 0x85, 0x59, 0xD9, +- 0x59, 0xDB, 0x59, 0xD9, 0x59, 0xDB, 0xFB, 0x1F, 0x0C, 0x63, 0xA5, 0xD1, 0xDA, 0x85, 0xA5, 0xD3, +- 0xDA, 0x85, 0x59, 0xD9, 0x59, 0xDB, 0x59, 0xD9, 0x59, 0xDB, 0xF7, 0x1F, 0x66, 0x44, 0x0E, 0x63, +- 0x53, 0x93, 0x60, 0x40, 0x10, 0x36, 0x07, 0x00, 0x65, 0x44, 0x48, 0xD3, 0x59, 0xD9, 0x59, 0xDB, +- 0x59, 0xD9, 0x59, 0xDB, 0xFB, 0x1F, 0x12, 0x60, 0xBC, 0xF1, 0x64, 0xF3, 0x64, 0x43, 0xDB, 0x81, +- 0x25, 0x60, 0x5A, 0x65, 0x60, 0x40, 0x01, 0x37, 0x12, 0x00, 0x11, 0x37, 0x17, 0x00, 0x21, 0x37, +- 0x1D, 0x00, 0x31, 0x37, 0x22, 0x00, 0xA3, 0xD1, 0x12, 0x60, 0xB7, 0xF5, 0x64, 0x44, 0xFF, 0xB4, +- 0x12, 0x60, 0xB6, 0xFB, 0x64, 0x47, 0xFF, 0xB4, 0x12, 0x60, 0xAD, 0xF1, 0x1D, 0x00, 0xA1, 0xD3, +- 0x12, 0x60, 0xB8, 0xF5, 0xFF, 0xB4, 0x12, 0x60, 0xAE, 0xF1, 0x16, 0x00, 0xA1, 0xD3, 0x12, 0x60, +- 0xB9, 0xF5, 0x60, 0x47, 0xFF, 0xB4, 0x12, 0x60, 0xAF, 0xF1, 0x0E, 0x00, 0x59, 0xD3, 0x12, 0x60, +- 0xBA, 0xF5, 0xFF, 0xB4, 0x12, 0x60, 0xB0, 0xF1, 0x07, 0x00, 0x59, 0xD3, 0x12, 0x60, 0xBB, 0xF5, +- 0x60, 0x47, 0xFF, 0xB4, 0x12, 0x60, 0xB1, 0xF1, 0x12, 0x60, 0xB5, 0xFB, 0x12, 0x60, 0xB2, 0xF9, +- 0x66, 0x42, 0xFC, 0xA2, 0xA2, 0xD3, 0x24, 0x60, 0x48, 0x63, 0xCC, 0x84, 0xE8, 0x84, 0xCC, 0x81, +- 0x63, 0x45, 0xA6, 0xD3, 0xDA, 0x82, 0xFF, 0xB4, 0xFF, 0xFF, 0x03, 0x03, 0x60, 0x40, 0x80, 0x2B, +- 0x03, 0x00, 0xDA, 0x86, 0xCD, 0x81, 0xF5, 0x01, 0x00, 0xB9, 0xA6, 0xD3, 0x0B, 0x03, 0x5A, 0xD1, +- 0xDA, 0x86, 0xFF, 0xB4, 0xE0, 0x84, 0xC4, 0x84, 0x5C, 0x90, 0xBD, 0xD9, 0xFD, 0x02, 0xCD, 0x81, +- 0x66, 0x42, 0xF2, 0x02, 0x5A, 0xD3, 0x24, 0x60, 0x86, 0x65, 0xD7, 0x80, 0xBD, 0xDB, 0xFD, 0x02, +- 0x64, 0xF3, 0x15, 0x60, 0xDD, 0xF1, 0x60, 0x40, 0x01, 0x27, 0x09, 0x00, 0x64, 0x40, 0x10, 0x26, +- 0x06, 0x00, 0x13, 0x64, 0xAD, 0xFB, 0x01, 0x60, 0x67, 0x64, 0x37, 0xFB, 0x09, 0x00, 0x08, 0x64, +- 0xAD, 0xFB, 0x82, 0xF3, 0x01, 0x60, 0x67, 0x7C, 0x60, 0x40, 0x01, 0x27, 0x5B, 0x7C, 0x37, 0xF9, +- 0x13, 0x60, 0x5B, 0xF1, 0x64, 0xF3, 0x15, 0x60, 0xD2, 0xF9, 0x15, 0x60, 0xD6, 0xF9, 0x60, 0x40, +- 0x01, 0x27, 0x0A, 0x00, 0xFF, 0xB5, 0x10, 0x60, 0xA8, 0x63, 0x65, 0x41, 0xCD, 0x81, 0x06, 0xA3, +- 0xFD, 0x02, 0xFA, 0xA3, 0xA3, 0xD3, 0x0F, 0x00, 0x01, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x11, 0x60, +- 0x14, 0x61, 0xA1, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0x08, 0xA1, 0xFB, 0x02, 0xFC, 0xA1, 0xA1, 0xD3, +- 0x15, 0x60, 0xD2, 0xF1, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x07, 0x15, 0x60, 0xD2, 0xFB, +- 0x15, 0x60, 0xD6, 0xFB, 0x25, 0x60, 0x7A, 0x63, 0x24, 0x60, 0x08, 0x65, 0x12, 0x60, 0xB6, 0xF1, +- 0x23, 0x60, 0xF0, 0x61, 0x25, 0x60, 0x68, 0x64, 0x40, 0x4F, 0x04, 0x64, 0xC3, 0x60, 0x58, 0x4D, +- 0x25, 0x78, 0xFF, 0xFF, 0x25, 0x60, 0x82, 0x63, 0x12, 0x60, 0xB5, 0xF1, 0x24, 0x60, 0x48, 0x65, +- 0x25, 0x60, 0x66, 0x64, 0x40, 0x4F, 0x08, 0x64, 0xC3, 0x60, 0x58, 0x4D, 0x25, 0x78, 0xFF, 0xFF, +- 0x64, 0xF3, 0x08, 0x7C, 0x38, 0xF9, 0x24, 0x60, 0xE0, 0x61, 0x60, 0x40, 0x01, 0x2B, 0x0E, 0x00, +- 0x01, 0x37, 0x06, 0x00, 0x11, 0x37, 0x03, 0x00, 0x21, 0x3B, 0x1E, 0xA1, 0x1E, 0xA1, 0x1E, 0xA1, +- 0x1C, 0x63, 0x24, 0x60, 0xC2, 0x64, 0x59, 0xD1, 0x58, 0xD9, 0xFD, 0x1F, 0x12, 0x60, 0xB2, 0xF3, +- 0x00, 0x7C, 0x60, 0x45, 0x70, 0x62, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, 0x04, 0x29, +- 0xFE, 0x01, 0x00, 0x60, 0x10, 0x62, 0x1A, 0x60, 0x58, 0x4D, 0xB4, 0x78, 0xFF, 0xFF, 0x01, 0x61, +- 0xB1, 0x9C, 0x60, 0x45, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, 0x18, 0x60, 0x50, 0x78, +- 0xFF, 0xFF, 0x44, 0xD3, 0x80, 0x7C, 0x60, 0x48, 0x60, 0x47, 0x00, 0x7F, 0xB0, 0x8A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xD5, 0x60, 0x84, 0xE7, 0x62, 0x47, 0x80, 0xBF, +- 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x64, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x2D, 0x58, 0xFF, 0xFF, +- 0x00, 0x7C, 0xBD, 0xD3, 0xD5, 0x60, 0x84, 0xE7, 0x60, 0x47, 0x80, 0xBF, 0x60, 0x4A, 0xBD, 0xD3, +- 0x01, 0x16, 0xFE, 0x01, 0x90, 0x8A, 0xBD, 0xD3, 0x01, 0x16, 0xFE, 0x01, 0x90, 0x8A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0xCD, 0x81, 0x95, 0x60, 0x84, 0xE7, 0xEB, 0x02, 0x2D, 0x58, 0xFF, 0xFF, +- 0xD5, 0x60, 0x84, 0xE7, 0x62, 0x4A, 0x02, 0x64, 0x01, 0x16, 0xFE, 0x01, 0xCC, 0x84, 0xFF, 0xFF, +- 0xFD, 0x02, 0x7C, 0x49, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x68, 0x5C, 0x7C, 0x49, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x68, 0x44, 0x95, 0x60, 0x84, 0xE7, 0x2D, 0x58, 0xFF, 0xFF, 0x42, 0xFF, +- 0x40, 0xFF, 0x3F, 0x40, 0x02, 0x27, 0x33, 0x00, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, +- 0x3F, 0x40, 0x02, 0x27, 0x1B, 0x00, 0x60, 0xBC, 0x40, 0x40, 0xDD, 0xFE, 0x18, 0x60, 0x07, 0xF1, +- 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x64, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, +- 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x00, 0xEE, 0x19, 0x61, 0xCD, 0x81, +- 0xFF, 0xFF, 0xFD, 0x02, 0x43, 0x45, 0x3F, 0x40, 0x02, 0x27, 0x11, 0x00, 0xAE, 0x4F, 0xFD, 0xB4, +- 0x04, 0xBC, 0xA0, 0x5E, 0x00, 0x60, 0x02, 0x71, 0x8D, 0xE2, 0x40, 0xE1, 0xA1, 0xFF, 0x04, 0xAC, +- 0xA0, 0x5E, 0x0F, 0x60, 0xA0, 0x71, 0x8D, 0xE2, 0xA1, 0xFF, 0xDD, 0xFE, 0x1E, 0x00, 0x43, 0x45, +- 0x20, 0x44, 0x60, 0xBC, 0x40, 0x40, 0xAE, 0x4F, 0xFD, 0xB4, 0x04, 0xBC, 0xA0, 0x5E, 0xDD, 0xFE, +- 0x00, 0x60, 0x02, 0x71, 0x8D, 0xE2, 0x40, 0xE1, 0xA1, 0xFF, 0x04, 0xAC, 0xA0, 0x5E, 0x00, 0x60, +- 0xC8, 0x71, 0x8D, 0xE2, 0xA1, 0xFF, 0x0C, 0x60, 0x00, 0x62, 0x00, 0x60, 0x71, 0x7C, 0x10, 0x60, +- 0x00, 0x65, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, 0x20, 0x60, 0x3C, 0x63, 0x1E, 0x61, +- 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x14, 0x71, 0x8D, 0xE2, 0xA1, 0xFF, +- 0x31, 0x44, 0x40, 0x26, 0x02, 0x00, 0x80, 0x26, 0x17, 0x00, 0x21, 0x60, 0xEC, 0x63, 0x07, 0x60, +- 0xE9, 0xFD, 0x09, 0x61, 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x31, 0x44, 0x40, 0x2A, +- 0x14, 0x00, 0x31, 0x44, 0x7F, 0xB4, 0x40, 0x51, 0xAE, 0x4C, 0x10, 0x26, 0x0E, 0x00, 0x07, 0x60, +- 0xEA, 0xFB, 0x31, 0x44, 0x80, 0xBC, 0x40, 0x51, 0x22, 0x60, 0x22, 0x63, 0x07, 0x60, 0xE9, 0xFD, +- 0x09, 0x61, 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x20, 0x60, 0xF0, 0x63, 0x03, 0x61, +- 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x62, 0x19, 0x60, 0x8F, 0x7C, +- 0x00, 0x60, 0xAC, 0x65, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, 0x80, 0xE1, 0xBF, 0xFE, +- 0xA1, 0x4F, 0x70, 0xB4, 0x50, 0x36, 0xAF, 0x00, 0x20, 0x36, 0x03, 0x00, 0x18, 0x60, 0x24, 0x78, +- 0xFF, 0xFF, 0x01, 0x60, 0x1A, 0xE1, 0xDF, 0xFE, 0x19, 0xFF, 0x00, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x3F, 0x40, 0x20, 0x2B, 0xA1, 0x00, 0x01, 0x16, 0xFE, 0x01, 0x38, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x68, 0x44, 0x01, 0x2A, 0x99, 0x00, 0x13, 0x60, 0x09, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, +- 0x00, 0x3B, 0xA2, 0xDB, 0x64, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x9C, 0x47, 0x00, 0x43, 0x45, +- 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x18, 0x60, 0x22, 0xF3, 0x3F, 0x40, 0x40, 0x26, 0x01, 0x00, +- 0xA0, 0x50, 0x3F, 0x40, 0x02, 0x2B, 0x29, 0x00, 0xAE, 0x4F, 0xFD, 0xB4, 0xA0, 0x5E, 0xDD, 0xFE, +- 0xAC, 0x4F, 0x10, 0xBC, 0xA0, 0x5C, 0xFF, 0xFF, 0x10, 0xAC, 0xA0, 0x5C, 0x00, 0x60, 0xC8, 0x71, +- 0x8D, 0xE2, 0x40, 0xE1, 0x40, 0x29, 0xFE, 0x01, 0x0C, 0x60, 0x00, 0x62, 0x00, 0x60, 0x71, 0x7C, +- 0x10, 0x60, 0x00, 0x65, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0xC8, 0x71, +- 0x8D, 0xE2, 0x40, 0xE1, 0x40, 0x29, 0xFE, 0x01, 0x01, 0x60, 0x08, 0xE1, 0x64, 0xF1, 0x82, 0xF9, +- 0x05, 0x7C, 0x83, 0xF9, 0xDF, 0xFE, 0x19, 0xFF, 0xFF, 0xFF, 0x18, 0x60, 0x07, 0xF1, 0xAD, 0x4F, +- 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x64, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, +- 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0xBF, 0xFE, 0x45, 0x00, 0x18, 0x60, 0x07, 0xF1, +- 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x64, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, +- 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, +- 0x40, 0x40, 0x02, 0x60, 0xEE, 0x64, 0x3F, 0x40, 0x02, 0x27, 0xC8, 0x64, 0x81, 0xFB, 0x82, 0xF9, +- 0x05, 0x64, 0x83, 0xFB, 0xDF, 0xFE, 0x19, 0xFF, 0x26, 0x00, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, +- 0x43, 0x45, 0xA4, 0xD1, 0xDA, 0x83, 0xC3, 0x85, 0x80, 0xE1, 0xDF, 0xFE, 0xBD, 0xD3, 0xFF, 0xFF, +- 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, 0x00, 0x7F, 0x60, 0x4A, 0xD7, 0x80, 0xA1, 0xFF, 0xF6, 0x02, +- 0xBF, 0xFE, 0x11, 0x00, 0x43, 0x45, 0xA4, 0xD1, 0xDA, 0x83, 0x0D, 0x18, 0x64, 0x44, 0x00, 0x61, +- 0xFA, 0xA4, 0xDD, 0x81, 0xFD, 0x02, 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0xBF, 0xFE, +- 0x02, 0x00, 0xF1, 0xFE, 0x01, 0x00, 0x25, 0x43, 0x21, 0xE1, 0x00, 0x64, 0xBF, 0xDB, 0x20, 0x44, +- 0x20, 0x2A, 0x07, 0x00, 0x07, 0xB4, 0x04, 0x36, 0xC3, 0xFE, 0x06, 0x36, 0xCC, 0xFE, 0x07, 0x36, +- 0xD5, 0xFE, 0x20, 0x44, 0xD8, 0xB4, 0x40, 0x40, 0x1F, 0x60, 0x2C, 0x63, 0xBD, 0xD3, 0x03, 0x61, +- 0x0F, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x04, 0x61, 0x0B, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x06, 0x61, +- 0x07, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x07, 0x61, 0x03, 0x1B, 0xC3, 0x60, 0x53, 0x78, 0xFF, 0xFF, +- 0xA3, 0xD1, 0x40, 0x44, 0x20, 0x44, 0x07, 0xB5, 0xD4, 0x85, 0x35, 0x80, 0x24, 0x45, 0x1F, 0x60, +- 0x6C, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, +- 0x64, 0x43, 0xBD, 0xD3, 0xBD, 0xD1, 0x40, 0x44, 0x10, 0x27, 0x19, 0x00, 0x3F, 0x40, 0x02, 0x2B, +- 0x06, 0x00, 0x24, 0x47, 0x08, 0x2B, 0x13, 0x00, 0x07, 0xB4, 0x01, 0x36, 0x11, 0x00, 0xFF, 0x60, +- 0x7F, 0x65, 0x15, 0x60, 0xA2, 0x64, 0x24, 0x40, 0x08, 0x2B, 0xA4, 0x84, 0xA0, 0x57, 0xFF, 0xFF, +- 0x64, 0x49, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, 0x00, 0x7F, 0xA3, 0xDB, 0xAB, 0x01, +- 0x64, 0x42, 0x1A, 0x60, 0x58, 0x4D, 0xB4, 0x78, 0xFF, 0xFF, 0xBD, 0xD9, 0xA3, 0xDB, 0xA3, 0x01, +- 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x64, 0x43, 0xBD, 0xD3, 0xA3, 0xD1, 0x40, 0x44, +- 0x10, 0x2B, 0x16, 0x00, 0xBE, 0xD1, 0xFF, 0xFF, 0x15, 0x60, 0x80, 0xE7, 0x24, 0x40, 0x07, 0x27, +- 0x04, 0x00, 0xAC, 0x4F, 0x10, 0xBC, 0x00, 0x7F, 0xA0, 0x5C, 0x64, 0x4A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x24, 0x40, 0x20, 0x27, 0x1D, 0x00, 0xAC, 0x4F, 0xEF, 0xB4, 0xA0, 0x5C, 0x19, 0x00, +- 0x3F, 0x40, 0x02, 0x2B, 0x06, 0x00, 0x24, 0x47, 0x08, 0x2B, 0x13, 0x00, 0x07, 0xB4, 0x01, 0x36, +- 0x11, 0x00, 0x15, 0x60, 0x22, 0x64, 0x24, 0x40, 0x08, 0x27, 0x80, 0xBC, 0x7C, 0x48, 0xBE, 0xD3, +- 0xA0, 0x57, 0x60, 0x48, 0x64, 0x44, 0x80, 0xBC, 0xFF, 0xB4, 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x69, 0x01, 0x01, 0x61, 0x1A, 0x60, 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x63, 0x01, +- 0x28, 0xF3, 0xFF, 0xFF, 0x60, 0x47, 0x0F, 0xB4, 0x9A, 0x00, 0xFF, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x04, 0x64, 0x0F, 0x60, 0x9F, 0xFB, 0x27, 0x00, 0x0C, 0x64, 0x3F, 0x40, 0x02, 0x2B, 0x23, 0x00, +- 0x29, 0xF1, 0x0F, 0x60, 0x9F, 0xFB, 0x5A, 0xD9, 0x1C, 0x60, 0xD0, 0x64, 0x7F, 0xFB, 0xFF, 0xFF, +- 0x2D, 0xFF, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x22, 0x60, 0x22, 0x63, 0x09, 0x61, 0x1A, 0x60, +- 0x58, 0x4D, 0x9C, 0x78, 0xFF, 0xFF, 0x77, 0x00, 0xD3, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xD3, 0xFB, +- 0x06, 0x64, 0x0F, 0x60, 0x9F, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x08, 0x64, 0x0F, 0x60, 0x9F, 0xFB, 0x1D, 0x60, 0x4F, 0x64, 0x7F, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, +- 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x29, 0xF3, 0x11, 0x60, 0xF9, 0x65, 0x60, 0x5C, 0x3F, 0x40, +- 0x02, 0x2B, 0x13, 0x00, 0x00, 0x37, 0x11, 0x00, 0x01, 0x3B, 0x55, 0x00, 0x11, 0x60, 0x19, 0x63, +- 0xFF, 0xB7, 0x60, 0x5C, 0xA3, 0xD3, 0x08, 0xA3, 0x00, 0x7E, 0xD0, 0x80, 0xD7, 0x80, 0x02, 0x03, +- 0xF9, 0x02, 0x49, 0x00, 0xF4, 0xA3, 0xA3, 0xD3, 0x05, 0x00, 0x00, 0xBC, 0xF2, 0xA4, 0x43, 0x03, +- 0x42, 0x07, 0x64, 0x44, 0x64, 0xFB, 0x82, 0xFB, 0xC8, 0x64, 0x81, 0xFB, 0x07, 0x64, 0x83, 0xFB, +- 0x1D, 0x60, 0x4F, 0x64, 0x7F, 0xFB, 0xFF, 0xFF, 0xDF, 0xFE, 0x00, 0x64, 0x19, 0xFF, 0xF0, 0x60, +- 0xC7, 0x78, 0xFF, 0xFF, 0x88, 0xFF, 0xBA, 0x60, 0x98, 0x71, 0x8D, 0xE2, 0x01, 0x11, 0x09, 0x00, +- 0x71, 0x40, 0x80, 0x27, 0xFB, 0x01, 0x88, 0xE2, 0xBA, 0x60, 0xD0, 0x64, 0x03, 0xFB, 0x8D, 0xFF, +- 0x15, 0x00, 0x8D, 0xFF, 0xB1, 0x60, 0xED, 0x63, 0x06, 0x60, 0x0B, 0xFD, 0xFF, 0xFF, 0x62, 0xFF, +- 0x1D, 0x60, 0x3C, 0x63, 0x7F, 0xFD, 0xFF, 0xFF, 0x1A, 0xFF, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, +- 0xA4, 0x60, 0x7C, 0x63, 0x06, 0x60, 0x0B, 0xFD, 0xFF, 0xFF, 0x62, 0xFF, 0x29, 0xF5, 0x1F, 0x60, +- 0x26, 0x63, 0x1E, 0x60, 0xF8, 0x64, 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0x02, 0x64, 0xA3, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xF9, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x66, 0x01, 0x00, 0x36, +- 0x67, 0x01, 0x01, 0x36, 0x69, 0x01, 0x02, 0x36, 0x7F, 0x01, 0x03, 0x36, 0x89, 0x01, 0x04, 0x36, +- 0xC1, 0x01, 0x05, 0x36, 0xBF, 0x01, 0x06, 0x36, 0xF1, 0x01, 0x07, 0x36, 0xBB, 0x01, 0x08, 0x36, +- 0x8A, 0x01, 0x09, 0x36, 0x0C, 0x00, 0x0A, 0x36, 0x0D, 0x00, 0x0B, 0x36, 0x0E, 0x00, 0x0C, 0x36, +- 0x17, 0x00, 0x0D, 0x36, 0x0D, 0x00, 0x0E, 0x36, 0x1D, 0x00, 0x0F, 0x36, 0x41, 0x00, 0x02, 0x60, +- 0x00, 0x64, 0x08, 0x00, 0x04, 0x60, 0x00, 0x64, 0x05, 0x00, 0x00, 0x60, 0x01, 0x64, 0x02, 0x00, +- 0x20, 0x60, 0x00, 0x64, 0x32, 0x45, 0xB4, 0x85, 0x45, 0x52, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0xB2, 0x60, 0xD0, 0x63, 0x06, 0x60, 0x0B, 0xFD, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x3F, 0x40, 0x02, 0x2B, 0x15, 0x00, 0x88, 0xFF, 0xBA, 0x60, 0x98, 0x71, +- 0x8D, 0xE2, 0x01, 0x11, 0x09, 0x00, 0x71, 0x40, 0x80, 0x27, 0xFB, 0x01, 0x88, 0xE2, 0xBA, 0x60, +- 0xD0, 0x64, 0x03, 0xFB, 0x8D, 0xFF, 0x11, 0x00, 0x8D, 0xFF, 0x90, 0x60, 0x00, 0xE8, 0xB1, 0x60, +- 0xED, 0x63, 0x04, 0x00, 0x91, 0x60, 0x00, 0xE8, 0xB2, 0x60, 0xB6, 0x63, 0x2A, 0xE8, 0x06, 0x60, +- 0x0B, 0xFD, 0xFF, 0xFF, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0xD2, 0xF3, 0xFF, 0xFF, 0xEF, 0xB4, 0xD2, 0xFB, 0xAD, 0x4F, 0xFD, 0xB4, 0xA0, 0x5D, 0xD0, 0x60, +- 0x00, 0xE8, 0x2A, 0xE8, 0xD9, 0x60, 0xFE, 0x64, 0x32, 0x45, 0xA4, 0x85, 0x45, 0x52, 0x99, 0xFF, +- 0xA5, 0x4F, 0xFF, 0xB4, 0x07, 0xFB, 0x98, 0xFF, 0xA4, 0x60, 0x7C, 0x63, 0x06, 0x60, 0x0B, 0xFD, +- 0x62, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x07, 0x02, +- 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, 0x66, 0xFF, 0xBF, 0xFE, 0xA1, 0xFF, 0x82, 0xFF, +- 0x88, 0xFF, 0x6C, 0x40, 0x41, 0xFF, 0xC4, 0xE2, 0x43, 0xFF, 0x5C, 0x49, 0x08, 0xE1, 0xA3, 0x60, +- 0x30, 0x78, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x02, 0x02, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x82, 0xFF, 0x88, 0xFF, 0xA8, 0xE2, 0x01, 0x70, 0xAD, 0xF1, 0x00, 0x6B, 0x89, 0xFF, 0x64, 0x54, +- 0x88, 0xFF, 0x9F, 0xFE, 0x02, 0x05, 0x64, 0x44, 0x60, 0x54, 0xCD, 0xE2, 0xC2, 0x64, 0x3A, 0xDB, +- 0xBC, 0xFF, 0xB5, 0xFF, 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xB4, 0x40, 0x46, 0x3C, 0x44, 0x00, 0xBC, +- 0xFF, 0xFF, 0x06, 0x03, 0x27, 0x40, 0x26, 0x22, 0x03, 0x00, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, +- 0x27, 0x44, 0x20, 0x2A, 0x04, 0x00, 0xA0, 0x60, 0x00, 0xEA, 0xB0, 0x60, 0x00, 0xEA, 0x5C, 0x44, +- 0x27, 0x44, 0x18, 0xB4, 0x40, 0x47, 0x00, 0xE1, 0xA4, 0xE2, 0xC4, 0xE2, 0x47, 0xFF, 0xB6, 0xFF, +- 0xB7, 0xFF, 0xB4, 0xFF, 0x32, 0xF1, 0x08, 0x29, 0x09, 0x00, 0x64, 0x40, 0x07, 0x22, 0x06, 0x00, +- 0x43, 0xFF, 0x27, 0x44, 0x10, 0xBC, 0x40, 0x47, 0x00, 0x64, 0x32, 0xFB, 0x31, 0x41, 0x3C, 0x44, +- 0x01, 0xB1, 0x00, 0xBC, 0x0A, 0x02, 0x09, 0x03, 0x32, 0xF3, 0x00, 0x7C, 0x01, 0xB4, 0xFF, 0xFF, +- 0x04, 0x03, 0x32, 0xF9, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xC8, 0x60, 0x09, 0x7D, 0x00, 0x60, +- 0x00, 0x6B, 0x00, 0x64, 0x33, 0xFB, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0xE1, 0x30, 0x40, 0x02, 0x36, 0xA1, 0xFF, 0x83, 0xFF, 0x8D, 0xFF, 0x5C, 0x44, 0x5C, 0x43, +- 0x5C, 0x42, 0x5C, 0x41, 0x5C, 0x40, 0xAC, 0xFF, 0xAD, 0xFF, 0xE7, 0xE1, 0xB3, 0x60, 0xBE, 0x78, +- 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x03, 0x02, 0x28, 0xE2, 0x40, 0xFF, 0xA1, 0xFF, +- 0x84, 0xFF, 0xC1, 0x60, 0x6B, 0x64, 0x40, 0x42, 0xB7, 0x60, 0xA2, 0x64, 0x40, 0x40, 0x9C, 0xF3, +- 0x65, 0xFB, 0x0F, 0x60, 0xF6, 0x63, 0xA9, 0xF3, 0xBD, 0xDB, 0x00, 0x60, 0x9A, 0x64, 0xBD, 0xDB, +- 0x02, 0x64, 0xBD, 0xDB, 0x04, 0x64, 0xA3, 0xDB, 0x5C, 0x49, 0x0A, 0x64, 0x40, 0x4B, 0x5C, 0x5C, +- 0x01, 0x60, 0x39, 0xE2, 0x04, 0x60, 0x00, 0x7A, 0x89, 0xFF, 0x03, 0x60, 0xFF, 0x73, 0x88, 0xFF, +- 0xB7, 0x60, 0xA2, 0x78, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x06, 0x02, 0x40, 0xFF, +- 0x42, 0xFF, 0x43, 0xFF, 0x44, 0xFF, 0x45, 0xFF, 0xA1, 0xFF, 0x88, 0xFF, 0x85, 0xFF, 0x21, 0xE1, +- 0x5C, 0x40, 0xC3, 0x60, 0x53, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, +- 0x01, 0x02, 0xA1, 0xFF, 0x86, 0xFF, 0x88, 0xFF, 0x5C, 0x46, 0x5C, 0x49, 0x5C, 0x40, 0xE1, 0x60, +- 0x58, 0x4F, 0x7A, 0x78, 0xFF, 0xFF, 0xD0, 0x60, 0x58, 0x4F, 0xA2, 0x78, 0xFF, 0xFF, 0xEB, 0x60, +- 0x58, 0x4F, 0x10, 0x78, 0xFF, 0xFF, 0xDD, 0x60, 0x58, 0x4F, 0xF5, 0x78, 0xFF, 0xFF, 0x1F, 0xE1, +- 0xA3, 0xFF, 0xCA, 0x60, 0x7E, 0x78, 0xFF, 0xFF, 0x03, 0xE1, 0xA3, 0xFF, 0x1E, 0x60, 0x9E, 0x63, +- 0x17, 0xFD, 0xAE, 0xFF, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x86, 0xF3, 0x87, 0xF3, 0xDC, 0x81, +- 0x00, 0x7C, 0x01, 0x00, 0x00, 0xFA, 0x60, 0x46, 0xFE, 0x63, 0xA3, 0xD8, 0xFE, 0x1F, 0xCD, 0x81, +- 0xD8, 0x84, 0xF8, 0x02, 0x86, 0xF3, 0x87, 0xF5, 0xDC, 0x81, 0x80, 0x67, 0x40, 0x4A, 0x05, 0x18, +- 0x2A, 0x43, 0x02, 0xFC, 0x5F, 0x8A, 0x00, 0xF4, 0xFA, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0x88, 0xF3, +- 0x06, 0x61, 0x00, 0x7C, 0x60, 0x46, 0xFE, 0x63, 0xA3, 0xD8, 0xFE, 0x1F, 0xCD, 0x81, 0x66, 0x44, +- 0xD8, 0x84, 0xF8, 0x02, 0x09, 0x60, 0x2B, 0x7C, 0x88, 0xF3, 0x06, 0x61, 0x60, 0x46, 0x01, 0x63, +- 0x76, 0xF8, 0x00, 0xFC, 0x63, 0x47, 0x06, 0xFA, 0x76, 0xF8, 0x03, 0x64, 0x77, 0xFA, 0xDF, 0x83, +- 0x66, 0x44, 0xCD, 0x81, 0x02, 0xA6, 0xF4, 0x02, 0x2E, 0x58, 0xFF, 0xFF, 0x8A, 0xF1, 0x89, 0xF3, +- 0x7C, 0x63, 0x8C, 0xFB, 0x60, 0x46, 0x01, 0xFC, 0xDC, 0x84, 0xD0, 0x80, 0x00, 0xFA, 0xFA, 0x04, +- 0x8D, 0xFB, 0x60, 0x46, 0x00, 0x64, 0x00, 0xFA, 0x63, 0x44, 0x80, 0x7F, 0x01, 0xFA, 0x8A, 0xF3, +- 0x89, 0xF1, 0xDC, 0x84, 0xD0, 0x84, 0x8B, 0xFB, 0x03, 0x60, 0x26, 0x61, 0xB5, 0x60, 0x58, 0x4D, +- 0x8C, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x2E, 0xFB, 0x82, 0xFF, 0x40, 0x42, 0x87, 0xFF, 0x8B, 0xF3, +- 0x93, 0xFB, 0x00, 0x64, 0x40, 0x50, 0x63, 0xFF, 0x60, 0xFF, 0x66, 0xFF, 0x65, 0xFF, 0x64, 0xFF, +- 0x61, 0xFF, 0x62, 0xFF, 0x49, 0x60, 0x02, 0xE1, 0x52, 0x60, 0x02, 0xE1, 0x5C, 0x60, 0x02, 0xE1, +- 0x65, 0x60, 0x02, 0xE1, 0x6B, 0x60, 0x02, 0xE1, 0x76, 0x60, 0x02, 0xE1, 0x41, 0x60, 0x02, 0xE1, +- 0x04, 0x64, 0x0F, 0x60, 0x9F, 0xFB, 0x1F, 0x60, 0x64, 0x64, 0x7F, 0xFB, 0x2D, 0xFF, 0x0A, 0x61, +- 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x8C, 0x78, 0xFF, 0xFF, 0xF0, 0x67, +- 0x0E, 0xFA, 0x1F, 0x60, 0x0A, 0x64, 0x0F, 0x60, 0x93, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x2B, 0x41, 0x4D, 0x8B, 0xFF, 0xFF, 0xEA, 0x02, 0x09, 0x61, +- 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x8C, 0x78, 0xFF, 0xFF, 0x1E, 0x60, +- 0xFE, 0x64, 0x0F, 0x60, 0x93, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x2B, 0x41, 0x4D, 0x8B, 0xFF, 0xFF, 0xEC, 0x02, 0x1E, 0x60, 0xB0, 0x78, 0xFF, 0xFF, +- 0x00, 0xEA, 0x00, 0xEB, 0x50, 0x60, 0x03, 0xEA, 0x51, 0x60, 0x13, 0xEA, 0x52, 0x60, 0x30, 0xEA, +- 0x53, 0x60, 0x40, 0xEA, 0x54, 0x60, 0x52, 0xEA, 0x55, 0x60, 0x6D, 0xEA, 0x56, 0x60, 0x71, 0xEA, +- 0x57, 0x60, 0x8B, 0xEA, 0x58, 0x60, 0x47, 0xEA, 0x59, 0x60, 0xA0, 0xEA, 0x5A, 0x60, 0xB2, 0xEA, +- 0x5B, 0x60, 0xC1, 0xEA, 0x5C, 0x60, 0xD7, 0xEA, 0x5D, 0x60, 0xEB, 0xEA, 0x5E, 0x60, 0xA0, 0xEA, +- 0x50, 0x60, 0x36, 0xEB, 0x51, 0x60, 0x37, 0xEB, 0x52, 0x60, 0x20, 0xEB, 0x53, 0x60, 0xE4, 0xEB, +- 0x54, 0x60, 0x34, 0xEB, 0x55, 0x60, 0x58, 0xEB, 0x56, 0x60, 0x48, 0xEB, 0x57, 0x60, 0xD0, 0xEB, +- 0x58, 0x60, 0xC3, 0xEB, 0x59, 0x60, 0xFC, 0xEB, 0x5A, 0x60, 0x34, 0xEB, 0x5B, 0x60, 0x58, 0xEB, +- 0x5C, 0x60, 0xC0, 0xEB, 0x5D, 0x60, 0xD0, 0xEB, 0x5E, 0x60, 0x91, 0xEB, 0x00, 0xEA, 0x00, 0xEB, +- 0xE0, 0x60, 0x02, 0xEA, 0xE0, 0x60, 0x03, 0xEB, 0xA0, 0x60, 0x00, 0xEB, 0xB0, 0x60, 0x00, 0xEB, +- 0xAB, 0x48, 0x40, 0x3B, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xEB, 0x03, 0x60, 0x02, 0x64, 0xA0, 0xDB, +- 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, +- 0x00, 0xEA, 0x24, 0x44, 0xFF, 0xB4, 0x04, 0xFB, 0x50, 0x60, 0x00, 0x64, 0x05, 0xFB, 0x10, 0x60, +- 0x10, 0x75, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x40, 0x00, 0x05, 0x60, +- 0xF9, 0xF1, 0x42, 0x60, 0x08, 0x64, 0x09, 0x60, 0x19, 0x63, 0x64, 0x40, 0x01, 0x2B, 0x04, 0x00, +- 0x42, 0x60, 0x09, 0x64, 0x0A, 0x60, 0x19, 0x63, 0x18, 0x60, 0x22, 0xFB, 0x04, 0x60, 0x00, 0xBC, +- 0x18, 0x60, 0x1E, 0xFB, 0x18, 0x60, 0x1D, 0xFD, 0x1D, 0x60, 0x19, 0x63, 0x18, 0x60, 0x21, 0xFD, +- 0x80, 0x60, 0x1C, 0x64, 0x3F, 0x40, 0x01, 0x2A, 0x02, 0x00, 0x60, 0x60, 0x1C, 0x64, 0x18, 0x60, +- 0x23, 0xFB, 0x18, 0x60, 0x1F, 0xFB, 0x18, 0x60, 0x22, 0xF3, 0xA0, 0x50, 0xA0, 0x50, 0x0B, 0x60, +- 0xF8, 0x63, 0xA3, 0xD1, 0x30, 0x60, 0x38, 0x61, 0xA1, 0xD3, 0xF8, 0xA3, 0x90, 0x84, 0xA2, 0xDB, +- 0xA3, 0xD1, 0x59, 0xD3, 0x06, 0xA3, 0x90, 0x84, 0xA2, 0xDB, 0xA3, 0xD1, 0x59, 0xD3, 0xFE, 0xA3, +- 0x90, 0x84, 0xA2, 0xDB, 0xA3, 0xD1, 0x59, 0xD3, 0xFF, 0xFF, 0x90, 0x84, 0xA2, 0xDB, 0x80, 0x60, +- 0x58, 0xEC, 0x80, 0x60, 0x00, 0xED, 0x80, 0x60, 0x80, 0xEE, 0x40, 0xEC, 0x00, 0xED, 0x00, 0xEE, +- 0xC0, 0x60, 0x59, 0xEC, 0xC0, 0x60, 0x07, 0xED, 0xC0, 0x60, 0x8F, 0xEE, 0xAD, 0x4F, 0xFA, 0xB4, +- 0xA0, 0x5D, 0x00, 0xF3, 0x28, 0xFB, 0x40, 0x44, 0xA2, 0x60, 0xE8, 0x7C, 0x20, 0xF9, 0x1D, 0x60, +- 0xD0, 0x7C, 0x21, 0xF9, 0x1D, 0x60, 0xE6, 0x7C, 0x22, 0xF9, 0x1E, 0x60, 0x44, 0x7C, 0x23, 0xF9, +- 0x1E, 0x60, 0x55, 0x7C, 0x24, 0xF9, 0x1E, 0x60, 0x7F, 0x7C, 0x25, 0xF9, 0x1E, 0x60, 0x90, 0x7C, +- 0x26, 0xF9, 0xD0, 0x60, 0x00, 0xE8, 0x28, 0xE8, 0x44, 0x60, 0x01, 0xE6, 0x00, 0x64, 0x40, 0x52, +- 0x10, 0x60, 0x04, 0xE6, 0x08, 0x60, 0x06, 0x63, 0xFD, 0x60, 0x0C, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, +- 0x0C, 0x18, 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xFA, 0xA3, 0xA3, 0xD3, 0x02, 0x60, +- 0x00, 0x65, 0xF9, 0xA0, 0xFC, 0xA0, 0x09, 0x05, 0x00, 0x05, 0x21, 0x60, 0x00, 0x65, 0x3F, 0x43, +- 0x21, 0x60, 0x00, 0x65, 0xC0, 0x60, 0x8F, 0xEE, 0x08, 0x00, 0x02, 0x60, 0x00, 0x65, 0x00, 0x60, +- 0x00, 0x64, 0x18, 0xFB, 0x3F, 0x43, 0x11, 0x60, 0x10, 0xE6, 0xB7, 0x84, 0x40, 0x5F, 0x30, 0x60, +- 0x20, 0x63, 0x3F, 0x40, 0x20, 0x27, 0x06, 0x00, 0x0F, 0x60, 0xFF, 0x64, 0xBD, 0xDB, 0x0F, 0x60, +- 0xF0, 0x64, 0x03, 0x00, 0x0F, 0x64, 0xBD, 0xDB, 0x00, 0x64, 0xA3, 0xDB, 0x00, 0x60, 0x30, 0xE2, +- 0x00, 0x60, 0x50, 0xE2, 0x00, 0x60, 0x79, 0xE2, 0x00, 0x60, 0x90, 0xE2, 0x01, 0x60, 0xD0, 0xE2, +- 0x01, 0x60, 0xF0, 0xE2, 0x01, 0x60, 0xB0, 0xE2, 0x13, 0x64, 0xAD, 0xFB, 0x01, 0x60, 0x67, 0x64, +- 0x37, 0xFB, 0x00, 0x60, 0x50, 0x64, 0x36, 0xFB, 0x09, 0x60, 0x2A, 0x64, 0x98, 0xFB, 0x82, 0xFF, +- 0x92, 0xFF, 0x5C, 0x41, 0x5C, 0x46, 0x5C, 0x47, 0x00, 0xE1, 0xA4, 0x60, 0x7C, 0x63, 0x0C, 0x60, +- 0x16, 0x64, 0xA0, 0xDD, 0x87, 0xFF, 0x97, 0xFF, 0x0C, 0x60, 0x02, 0x64, 0x40, 0x5A, 0x06, 0xA4, +- 0x40, 0x5B, 0x5C, 0x5E, 0x13, 0x60, 0x52, 0xF3, 0x64, 0xFB, 0x3F, 0x40, 0x01, 0x22, 0x03, 0x00, +- 0x80, 0x60, 0x37, 0x7C, 0x02, 0x00, 0x80, 0x60, 0x27, 0x7C, 0x16, 0x60, 0x55, 0xF9, 0x00, 0x60, +- 0x80, 0x64, 0x89, 0xFB, 0x02, 0x60, 0x80, 0x66, 0x22, 0x60, 0x22, 0x64, 0x77, 0x60, 0x77, 0x63, +- 0x00, 0xFA, 0x01, 0xFC, 0x00, 0xF0, 0x01, 0xF0, 0xD0, 0x80, 0xD3, 0x80, 0x1E, 0x02, 0x1D, 0x02, +- 0x06, 0x60, 0x80, 0x65, 0x45, 0x4A, 0xAA, 0x46, 0x00, 0xFC, 0x01, 0xFA, 0xAA, 0x46, 0x00, 0xF0, +- 0x2A, 0x41, 0x50, 0x65, 0xD3, 0x80, 0xCD, 0x84, 0x13, 0x03, 0x0A, 0x60, 0x80, 0x65, 0x45, 0x4A, +- 0xAA, 0x46, 0x00, 0xFC, 0x01, 0xFA, 0xAA, 0x46, 0x00, 0xF0, 0x65, 0x41, 0xC8, 0x65, 0xD3, 0x80, +- 0xCD, 0x84, 0x06, 0x03, 0x12, 0x60, 0x7F, 0x64, 0x03, 0x00, 0x10, 0x65, 0x02, 0x60, 0x7F, 0x64, +- 0x65, 0x43, 0x86, 0xFD, 0x0F, 0x60, 0x5B, 0xFD, 0x07, 0x61, 0xC5, 0x81, 0xE1, 0x85, 0xD4, 0x84, +- 0x8A, 0xFB, 0xDC, 0x84, 0x88, 0xFB, 0x0C, 0xA4, 0x87, 0xFB, 0x0F, 0x60, 0x5C, 0xFB, 0x1E, 0x60, +- 0x58, 0x4E, 0xD3, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0x58, 0x4E, 0xB9, 0x78, 0xFF, 0xFF, 0x3F, 0x40, +- 0x40, 0x26, 0x05, 0x00, 0x18, 0x60, 0x20, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x52, 0x00, 0x64, +- 0x0A, 0x60, 0x7E, 0xFB, 0x1E, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0x5C, 0x51, 0x3F, 0x41, 0xA5, 0x4C, +- 0x50, 0x37, 0x0B, 0x00, 0x01, 0xB9, 0x41, 0x5F, 0xB5, 0x60, 0x55, 0xE0, 0x05, 0x60, 0xF9, 0xF1, +- 0xC0, 0x67, 0x90, 0x84, 0x3F, 0x40, 0x01, 0x26, 0xA0, 0x50, 0x06, 0x60, 0x08, 0xF3, 0x01, 0x60, +- 0x01, 0x65, 0x01, 0x60, 0x02, 0x7C, 0xD4, 0x80, 0xD0, 0x80, 0x01, 0x03, 0x10, 0x02, 0x5A, 0xD1, +- 0x5A, 0xD3, 0x3E, 0x60, 0x00, 0x66, 0xE0, 0x87, 0x40, 0x4A, 0xF7, 0x60, 0x8C, 0x61, 0x64, 0x44, +- 0xC8, 0x84, 0x0C, 0x63, 0xAA, 0x46, 0x58, 0xD0, 0xAA, 0x46, 0x59, 0xD8, 0xFB, 0x1F, 0x08, 0x60, +- 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, 0xA3, 0xD3, 0x02, 0xA8, 0xD4, 0x80, 0x07, 0x02, +- 0x06, 0x02, 0x49, 0x60, 0x4C, 0x61, 0x3C, 0x60, 0x00, 0x66, 0x41, 0x4B, 0x03, 0x00, 0x24, 0x60, +- 0x84, 0x78, 0xFF, 0xFF, 0x2B, 0x41, 0x49, 0x60, 0x94, 0x7C, 0xD1, 0x80, 0xA1, 0xD2, 0x25, 0x05, +- 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, 0xE0, 0x87, 0x40, 0x4A, 0x59, 0xD2, 0x59, 0x8B, +- 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, 0xEC, 0x18, 0xD4, 0x80, 0xEA, 0x18, +- 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x67, 0x44, 0xC0, 0x84, 0xE0, 0x85, 0x2C, 0x44, +- 0xD4, 0x80, 0x63, 0x41, 0x01, 0x06, 0x65, 0x44, 0xC8, 0x83, 0xAA, 0x46, 0x59, 0xD1, 0x27, 0xD8, +- 0x5A, 0x87, 0xFC, 0x1F, 0xAA, 0x46, 0x2B, 0x41, 0xD5, 0x01, 0x49, 0x60, 0x94, 0x61, 0x41, 0x4B, +- 0x2B, 0x41, 0x49, 0x60, 0x94, 0x7C, 0xD1, 0x80, 0xA1, 0xD2, 0x27, 0x05, 0x59, 0xD0, 0x60, 0x45, +- 0x59, 0xD2, 0x44, 0x47, 0xE0, 0x87, 0x40, 0x4A, 0x59, 0xD2, 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, +- 0x00, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, 0xEC, 0x18, 0xD4, 0x80, 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, +- 0xC3, 0x83, 0xF7, 0x01, 0x04, 0xA3, 0xA3, 0xD1, 0x5A, 0x88, 0x2C, 0x43, 0xD3, 0x80, 0xFF, 0xFF, +- 0x01, 0x06, 0x64, 0x43, 0xCF, 0x83, 0xAA, 0x46, 0x60, 0xFE, 0x28, 0xD1, 0x5E, 0x88, 0x27, 0xD8, +- 0x5A, 0x87, 0xFB, 0x1F, 0x20, 0xFE, 0xAA, 0x46, 0xD3, 0x01, 0xFA, 0x60, 0x39, 0x65, 0x24, 0x60, +- 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x03, 0x03, 0xBE, 0xD1, 0x07, 0x60, 0xED, 0xF9, 0x07, 0x60, +- 0xED, 0xF3, 0x20, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x10, 0x2A, 0x05, 0x00, 0x07, 0x60, 0xEC, 0xF9, +- 0x07, 0x60, 0xEB, 0xF9, 0x12, 0x00, 0x04, 0xB0, 0x10, 0x60, 0x55, 0xF3, 0x0E, 0x03, 0x02, 0xBC, +- 0xA2, 0xDB, 0x07, 0x60, 0xF5, 0xFB, 0x10, 0x60, 0xE8, 0xF3, 0x10, 0x60, 0xAC, 0xF3, 0x02, 0xBD, +- 0x02, 0xBC, 0xA2, 0xDB, 0x65, 0x44, 0x10, 0x60, 0xE8, 0xFB, 0x07, 0x60, 0xED, 0xF3, 0x31, 0x41, +- 0x60, 0x40, 0x20, 0x2A, 0x40, 0xB9, 0x40, 0x26, 0x03, 0x00, 0x60, 0x40, 0x01, 0x26, 0x80, 0xB9, +- 0x41, 0x51, 0xFA, 0x60, 0x3A, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x03, 0x02, +- 0x23, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x5B, 0xD3, 0xF8, 0x60, 0x3F, 0x65, 0x00, 0x7F, 0xE0, 0x84, +- 0xE0, 0x84, 0x10, 0x60, 0xF7, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, +- 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0xE0, 0x84, 0x10, 0x60, 0xFA, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, +- 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x21, 0x60, 0xFA, 0x61, 0xA3, 0xD3, +- 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0xA1, 0xD3, 0xE0, 0x9C, 0xA4, 0x84, +- 0xB0, 0x84, 0xA1, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x59, 0xD3, +- 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, 0x11, 0x60, 0x00, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, +- 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x11, 0x60, +- 0x03, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, +- 0xB0, 0x84, 0xA2, 0xDB, 0x11, 0x60, 0x06, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, +- 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x11, 0x60, 0x09, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, +- 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x11, 0x60, 0x0C, 0xF3, +- 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, +- 0xA2, 0xDB, 0x11, 0x60, 0x0F, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, +- 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x02, 0xA3, 0xA3, 0xD3, 0xF8, 0x60, 0x3F, 0x65, +- 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x11, 0x60, 0x12, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, +- 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0xBD, 0xD3, 0xFF, 0xFF, +- 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x11, 0x60, 0x15, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, +- 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x22, 0x60, +- 0x30, 0x61, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0xA1, 0xD3, +- 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0x00, 0x7F, 0xE0, 0x84, +- 0xE0, 0x84, 0x59, 0xD3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, 0x11, 0x60, 0x1B, 0xF3, +- 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, +- 0xA2, 0xDB, 0x11, 0x60, 0x1E, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, +- 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x11, 0x60, 0x21, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, +- 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0xA3, 0xD3, +- 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x11, 0x60, 0x24, 0xF3, 0xE0, 0x9C, +- 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, +- 0x11, 0x60, 0x27, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, +- 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x11, 0x60, 0x2A, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, +- 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x00, 0x60, 0x6A, 0x63, +- 0x22, 0x60, 0x56, 0x61, 0x21, 0x60, 0xEA, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x11, 0x60, +- 0x33, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, +- 0x11, 0x60, 0x37, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, 0x39, 0xF3, 0xFF, 0xFF, +- 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, 0x40, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, +- 0x42, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, 0x4E, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, +- 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, 0x52, 0xF3, 0xFF, 0xFF, +- 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, 0x54, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, +- 0x5B, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x11, 0x60, 0x5D, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, +- 0xA2, 0xDB, 0xFA, 0x60, 0x2C, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x0E, 0x03, +- 0x63, 0x45, 0x23, 0x60, 0xF0, 0x63, 0x06, 0x61, 0xA5, 0xD1, 0xDA, 0x85, 0x64, 0x44, 0x0F, 0xB4, +- 0xBD, 0xDB, 0x64, 0x47, 0x0F, 0xB4, 0xCD, 0x81, 0xBD, 0xDB, 0xF6, 0x02, 0xFA, 0x60, 0x30, 0x65, +- 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x14, 0x03, 0xBD, 0xD3, 0x63, 0x46, 0x24, 0x60, +- 0x88, 0x63, 0x12, 0x60, 0x53, 0xFB, 0xDA, 0x85, 0xBD, 0xDB, 0x0E, 0x61, 0xA6, 0xD1, 0xDA, 0x86, +- 0x64, 0x44, 0xFF, 0xB4, 0xA5, 0xDB, 0xDA, 0x85, 0x64, 0x47, 0xFF, 0xB4, 0xCD, 0x81, 0xBD, 0xDB, +- 0xF5, 0x02, 0xFA, 0x60, 0x31, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x22, 0x03, +- 0xBD, 0xD3, 0x12, 0x60, 0x71, 0xFB, 0x5A, 0x81, 0x12, 0x60, 0x80, 0xFB, 0x5A, 0x82, 0x12, 0x60, +- 0x8F, 0xFB, 0x5A, 0x83, 0x12, 0x60, 0x9E, 0xFB, 0x5A, 0x84, 0x0E, 0x61, 0xBD, 0xD1, 0xBD, 0xD5, +- 0x64, 0x44, 0xFF, 0xB4, 0x21, 0xDB, 0x5A, 0x81, 0x64, 0x47, 0xFF, 0xB4, 0x22, 0xDB, 0x5A, 0x82, +- 0x66, 0x44, 0xFF, 0xB4, 0x23, 0xDB, 0x5A, 0x83, 0x66, 0x47, 0xFF, 0xB4, 0x24, 0xDB, 0xCD, 0x81, +- 0x5A, 0x84, 0xEC, 0x02, 0xFA, 0x60, 0x47, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, +- 0x11, 0x03, 0x63, 0x45, 0x25, 0x60, 0x5A, 0x63, 0xA5, 0xD1, 0xDA, 0x85, 0xBD, 0xD9, 0x02, 0x61, +- 0xA5, 0xD1, 0xDA, 0x85, 0x64, 0x47, 0x00, 0x7E, 0xBD, 0xDB, 0x64, 0x44, 0x00, 0x7E, 0xCD, 0x81, +- 0xBD, 0xDB, 0xF6, 0x02, 0xFA, 0x60, 0x2E, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, +- 0x1F, 0x03, 0x63, 0x46, 0xFC, 0xA3, 0xA3, 0xD3, 0x24, 0x60, 0x08, 0x63, 0xCC, 0x84, 0xE8, 0x84, +- 0xCC, 0x81, 0x00, 0x36, 0x0D, 0x00, 0x63, 0x45, 0xA6, 0xD3, 0x5A, 0xD1, 0xDA, 0x86, 0xFF, 0xB4, +- 0xE0, 0x84, 0xC4, 0x84, 0x5C, 0x90, 0xBD, 0xD9, 0xFD, 0x02, 0xCD, 0x81, 0x66, 0x42, 0xF4, 0x02, +- 0x66, 0x42, 0x5A, 0xD3, 0x24, 0x60, 0x48, 0x65, 0xBD, 0xDB, 0xD7, 0x80, 0xFF, 0xFF, 0xFC, 0x02, +- 0x25, 0x60, 0x6E, 0x61, 0xFA, 0x60, 0x46, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, +- 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, 0x2F, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, +- 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, 0x3E, 0x65, 0x24, 0x60, 0x58, 0x4D, +- 0x97, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, 0x3F, 0x65, 0x24, 0x60, +- 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, 0x40, 0x65, +- 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, +- 0x3B, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xFA, 0x60, +- 0x48, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x10, 0x03, 0xBD, 0xD3, 0x25, 0x60, +- 0xCA, 0x61, 0x0E, 0xB4, 0xBD, 0xD1, 0xA1, 0xDB, 0x64, 0x47, 0x0E, 0xB4, 0xA3, 0xD1, 0x59, 0xDB, +- 0x64, 0x44, 0x0E, 0xB4, 0x59, 0xDB, 0x64, 0x47, 0x0E, 0xB4, 0x59, 0xDB, 0xFA, 0x60, 0x29, 0x65, +- 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x04, 0xA3, 0xA3, 0xD3, 0x20, 0x60, +- 0x00, 0x65, 0xB4, 0x84, 0x10, 0x60, 0x29, 0xFB, 0xFA, 0x60, 0x2A, 0x65, 0x24, 0x60, 0x58, 0x4D, +- 0x97, 0x78, 0xFF, 0xFF, 0x39, 0x03, 0x04, 0xA3, 0xBD, 0xD1, 0x10, 0x60, 0xCD, 0xF3, 0x64, 0x41, +- 0x64, 0x5E, 0xA2, 0xDB, 0x64, 0x47, 0x5A, 0xD3, 0x60, 0x5C, 0x64, 0x5F, 0xA2, 0xDB, 0x10, 0x60, +- 0xE3, 0xF3, 0xFF, 0x60, 0xC0, 0xB5, 0x61, 0x40, 0x80, 0x27, 0x05, 0x00, 0xE9, 0x87, 0x3F, 0xB4, +- 0xB4, 0x84, 0xA2, 0xDB, 0x1E, 0x00, 0x65, 0x44, 0xA2, 0xDB, 0x10, 0x60, 0xDC, 0xF1, 0xE1, 0x80, +- 0xF9, 0x81, 0xE1, 0x80, 0xF9, 0x84, 0xFF, 0x60, 0x80, 0xB4, 0xC0, 0x9C, 0xA2, 0xD9, 0x10, 0x60, +- 0xDF, 0xF1, 0xFF, 0xFF, 0xC0, 0x9C, 0xA2, 0xD9, 0x10, 0x60, 0xE6, 0xF1, 0x01, 0x7E, 0x60, 0x47, +- 0x60, 0x41, 0x64, 0x44, 0xFE, 0x60, 0x00, 0xB5, 0xC1, 0x84, 0x01, 0x60, 0xFF, 0xB4, 0xB4, 0x84, +- 0xA2, 0xDB, 0xDB, 0x83, 0x11, 0x60, 0x62, 0xFD, 0xFA, 0x60, 0x2B, 0x65, 0x24, 0x60, 0x58, 0x4D, +- 0x97, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x04, 0xA3, 0xBD, 0xD3, 0x10, 0x60, 0xD0, 0xFB, 0xA3, 0xD3, +- 0x10, 0x60, 0x94, 0xFB, 0xFA, 0x60, 0x3C, 0x65, 0x24, 0x60, 0x58, 0x4D, 0x97, 0x78, 0xFF, 0xFF, +- 0x1F, 0x03, 0xA3, 0xD3, 0xFC, 0x60, 0xFC, 0x65, 0xA4, 0x84, 0x60, 0x5C, 0x00, 0x7E, 0xC0, 0x60, +- 0x00, 0xA0, 0x60, 0x43, 0x07, 0x04, 0x10, 0x60, 0xD4, 0xF3, 0xFF, 0xFF, 0x03, 0x60, 0xFF, 0xB4, +- 0x3C, 0x94, 0xA2, 0xDB, 0x21, 0x60, 0x30, 0x61, 0x64, 0x44, 0x00, 0x7F, 0xC0, 0xA0, 0x60, 0x47, +- 0x07, 0x04, 0x60, 0x43, 0xA1, 0xD3, 0xFF, 0xFF, 0x03, 0x60, 0xFF, 0xB4, 0x3C, 0x94, 0xA1, 0xDB, +- 0xB8, 0xFE, 0xB9, 0xFE, 0xBA, 0xFE, 0xBB, 0xFE, 0xBD, 0xFE, 0xBF, 0xFE, 0x15, 0x60, 0xCB, 0xF3, +- 0x12, 0x63, 0x60, 0x40, 0x01, 0x27, 0x04, 0x00, 0x0B, 0x60, 0xEA, 0x62, 0x5A, 0xDF, 0xFE, 0x1F, +- 0x1F, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x06, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, 0x07, 0x18, +- 0xD4, 0x80, 0x05, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0xDB, 0x83, 0x00, 0xBC, +- 0x2D, 0x58, 0xFF, 0xFF, 0x86, 0xFD, 0xB0, 0x26, 0x00, 0x00, 0x06, 0x00, 0x10, 0xFD, 0x32, 0x01, +- 0x00, 0x00, 0x02, 0x00, 0x14, 0xFD, 0x94, 0x2B, 0x00, 0x00, 0x0A, 0x00, 0x41, 0xFA, 0x46, 0x23, +- 0x00, 0x00, 0x22, 0x00, 0x42, 0xFA, 0x68, 0x23, 0x00, 0x00, 0x22, 0x00, 0x43, 0xFA, 0x8A, 0x23, +- 0x00, 0x00, 0x22, 0x00, 0x44, 0xFA, 0xAC, 0x23, 0x00, 0x00, 0x22, 0x00, 0x45, 0xFA, 0xCE, 0x23, +- 0x00, 0x00, 0x22, 0x00, 0x25, 0xFD, 0x62, 0x01, 0x00, 0x00, 0x02, 0x00, +- +-}; /* fw_image_3_data */ +- +-static const hcf_8 fw_image_4_data[] = { +- 0x6C, 0x40, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x41, 0xFF, 0x33, 0xF3, 0x32, 0x11, 0x31, 0x18, 0x40, 0x64, 0x3A, 0xDB, 0x1C, 0x00, 0xFF, 0xFF, +- 0xC4, 0xE2, 0x27, 0x44, 0x20, 0x2A, 0x01, 0x00, 0xFF, 0xFF, 0x42, 0x64, 0x3A, 0xDB, 0x23, 0x00, +- 0x41, 0xFF, 0xA3, 0x60, 0x34, 0x78, 0xE2, 0xFE, 0x40, 0x49, 0x02, 0x60, 0x01, 0xE1, 0x1D, 0x00, +- 0x44, 0xFF, 0x1B, 0x09, 0x29, 0x44, 0x10, 0x2A, 0x04, 0x74, 0xCD, 0xE2, 0x10, 0x65, 0x0B, 0x00, +- 0xA4, 0x60, 0x49, 0x78, 0xA4, 0xE2, 0x29, 0x44, 0x20, 0x2A, 0x0D, 0x00, 0x20, 0xAC, 0xEC, 0x01, +- 0xA4, 0x60, 0x49, 0x78, 0x46, 0xFF, 0xB4, 0x84, 0x40, 0x49, 0xA1, 0xFF, 0xFF, 0xFF, 0x80, 0x3E, +- 0xA4, 0x60, 0x49, 0x78, 0xFF, 0xFF, 0x62, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, +- 0xAA, 0x60, 0xF4, 0x78, 0x4C, 0x4E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAA, 0x60, 0xFB, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC4, 0xE2, 0x84, 0xFF, 0x22, 0x58, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA4, 0x60, 0xB9, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0xE1, 0x01, 0xFF, 0xFF, +- 0x10, 0x29, 0xFA, 0x01, 0xE4, 0xE2, 0xAA, 0x60, 0xB0, 0x78, 0x94, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC1, 0x60, 0x35, 0x78, 0x64, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAA, 0x60, 0x97, 0x78, 0xAC, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x80, 0x29, 0xE2, 0x01, 0xAA, 0x60, 0xF3, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB4, 0x60, 0xEF, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB5, 0x60, 0x1C, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB3, 0x60, 0x8B, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB3, 0x60, 0xBE, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB3, 0x60, 0xBE, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB6, 0x60, 0x9D, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB3, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0x60, 0x83, 0x64, 0x80, 0x29, 0x09, 0xFB, 0xB4, 0x60, 0xB7, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x98, 0xFF, 0xC2, 0x60, 0x69, 0x78, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC1, 0x60, 0xE0, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC0, 0x60, 0x3D, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBF, 0x60, 0xB8, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB7, 0x60, 0x96, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA1, 0xFF, 0x98, 0xFF, 0x83, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC3, 0x60, 0x58, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xB0, 0xFF, 0xB1, 0xFF, 0x40, 0xFF, 0x43, 0xFF, 0xC3, 0x60, 0x53, 0x78, 0x44, 0xFF, 0xFF, 0x01, +- 0xC3, 0x60, 0x58, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0x1C, 0x60, 0x28, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xC3, 0x60, 0x53, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xC3, 0x60, 0x52, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xCA, 0x60, 0x76, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xE8, 0x60, 0x6C, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x42, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x85, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xCA, 0x60, 0x7E, 0x78, 0x24, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xE6, 0x60, 0x2A, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xCA, 0x60, 0x7E, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xCA, 0x60, 0x7E, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xCA, 0x60, 0x7E, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xF0, 0x60, 0x9F, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xF0, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xF0, 0x60, 0xE3, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xF0, 0x60, 0xC7, 0x78, 0x28, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xF0, 0x60, 0xC7, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xF0, 0x60, 0xC7, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xF0, 0x60, 0xC7, 0x78, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0x60, 0x87, 0x64, 0x80, 0x29, 0x09, 0xFB, 0x47, 0xFF, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x43, 0xF7, 0xA7, 0xFF, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0xA2, 0x60, 0x00, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x2E, 0x60, 0x54, 0x63, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, +- 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, +- 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, +- 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, +- 0x2F, 0x44, 0xBD, 0xDB, 0x17, 0x60, 0x24, 0xFD, 0x2F, 0x60, 0x74, 0x63, 0x17, 0x60, 0x25, 0xFD, +- 0x30, 0x44, 0x17, 0x60, 0x26, 0xFB, 0x31, 0x44, 0x17, 0x60, 0x27, 0xFB, 0x32, 0x44, 0x17, 0x60, +- 0x28, 0xFB, 0x33, 0x44, 0x17, 0x60, 0x29, 0xFB, 0x81, 0xFF, 0x91, 0xFF, 0x58, 0x51, 0x44, 0x00, +- 0x82, 0xFF, 0x92, 0xFF, 0x58, 0x51, 0x40, 0x00, 0x83, 0xFF, 0x93, 0xFF, 0x58, 0x51, 0x3C, 0x00, +- 0x84, 0xFF, 0x94, 0xFF, 0x58, 0x51, 0x38, 0x00, 0x85, 0xFF, 0x95, 0xFF, 0x58, 0x51, 0x34, 0x00, +- 0x86, 0xFF, 0x96, 0xFF, 0x58, 0x51, 0x30, 0x00, 0x87, 0xFF, 0x97, 0xFF, 0x58, 0x51, 0x2C, 0x00, +- 0x80, 0xFF, 0x90, 0xFF, 0x99, 0xFF, 0x17, 0x60, 0x24, 0xF1, 0x30, 0x44, 0x64, 0x43, 0xBD, 0xDB, +- 0x31, 0x44, 0xBD, 0xDB, 0x32, 0x44, 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, +- 0x35, 0x44, 0xBD, 0xDB, 0x36, 0x44, 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, +- 0x39, 0x44, 0xBD, 0xDB, 0x3A, 0x44, 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, +- 0x3D, 0x44, 0xBD, 0xDB, 0x3E, 0x44, 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0xEE, 0x60, 0x48, 0x64, +- 0x0A, 0xFB, 0x40, 0x21, 0xFE, 0x01, 0x70, 0x00, 0x42, 0x50, 0x40, 0x53, 0x17, 0x60, 0x25, 0xF3, +- 0xFF, 0xFF, 0x40, 0x52, 0x33, 0x44, 0x32, 0x42, 0xA2, 0xDB, 0xDA, 0x82, 0xA2, 0xDD, 0xDA, 0x83, +- 0x65, 0x44, 0xBD, 0xDB, 0x61, 0x44, 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0xBD, 0xD9, 0x30, 0x44, +- 0xBD, 0xDB, 0x99, 0xFF, 0xA4, 0x4C, 0xBD, 0xDB, 0xA5, 0x4C, 0xBD, 0xDB, 0xA0, 0x4C, 0xBD, 0xDB, +- 0xA1, 0x4C, 0xBD, 0xDB, 0x98, 0xFF, 0x17, 0x60, 0x25, 0xFD, 0x17, 0x60, 0x26, 0xF3, 0xFF, 0xFF, +- 0x40, 0x50, 0x17, 0x60, 0x28, 0xF3, 0xFF, 0xFF, 0x40, 0x52, 0x17, 0x60, 0x29, 0xF3, 0xFF, 0xFF, +- 0x40, 0x53, 0x31, 0x41, 0x17, 0x60, 0x27, 0xF3, 0xFF, 0xFF, 0x40, 0x51, 0x17, 0x60, 0x24, 0xF3, +- 0xFF, 0xFF, 0x60, 0x43, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, +- 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, +- 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, +- 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, +- 0x2F, 0x44, 0xBD, 0xDB, 0x17, 0x60, 0x24, 0xFD, 0x61, 0x58, 0xFF, 0xFF, 0x28, 0x60, 0x76, 0x63, +- 0xA3, 0xD3, 0x33, 0x5C, 0x02, 0xA4, 0xBD, 0xDB, 0xFE, 0xB4, 0xE0, 0x85, 0xC4, 0x85, 0x47, 0xD9, +- 0x34, 0x44, 0x5B, 0xDB, 0x44, 0xF3, 0x5B, 0xDB, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, 0xFF, 0x01, +- 0x82, 0xE1, 0x80, 0xFF, 0x90, 0xFF, 0x88, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, 0x41, 0xFF, +- 0x00, 0x60, 0x03, 0xE1, 0x21, 0x46, 0x66, 0x45, 0x00, 0xF4, 0x2E, 0x44, 0x09, 0xFA, 0x6A, 0x61, +- 0x7F, 0x60, 0xFE, 0x63, 0xA1, 0xFF, 0x9A, 0xFF, 0x05, 0x11, 0x0A, 0x00, 0x00, 0xF4, 0x01, 0xF2, +- 0x17, 0x18, 0x7A, 0x61, 0x02, 0x25, 0x04, 0x00, 0x6C, 0x44, 0x7A, 0xDA, 0xFB, 0x1C, 0xF6, 0x11, +- 0xD9, 0x81, 0x41, 0xFF, 0x02, 0x1C, 0x00, 0xF4, 0xDA, 0x82, 0x41, 0xFF, 0xC9, 0x81, 0xCB, 0x83, +- 0x6C, 0x44, 0x5A, 0xDA, 0x02, 0x1C, 0x00, 0xF4, 0x81, 0xF2, 0x6C, 0x44, 0x5A, 0xDA, 0xCB, 0x83, +- 0x02, 0x74, 0x02, 0x60, 0x04, 0xE1, 0x80, 0x60, 0x00, 0x61, 0x5D, 0x93, 0xB5, 0xFF, 0x98, 0xFF, +- 0x26, 0x44, 0xFD, 0xB4, 0x84, 0xBC, 0x40, 0x46, 0x65, 0x46, 0x00, 0x64, 0x23, 0xFA, 0x3F, 0xFC, +- 0x63, 0x47, 0x0A, 0x63, 0x0F, 0xFC, 0x00, 0xF4, 0x08, 0xFA, 0xCB, 0xFE, 0x18, 0xE1, 0x44, 0xFF, +- 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0xE2, 0xFE, 0x03, 0x04, 0xA3, 0x60, 0x99, 0x78, 0xFF, 0xFF, +- 0xE0, 0xFE, 0x03, 0x04, 0xA3, 0x60, 0xAF, 0x78, 0xFF, 0xFF, 0xE1, 0xFE, 0x07, 0x05, 0x9F, 0xFE, +- 0x03, 0x04, 0x18, 0x60, 0x24, 0x78, 0xFF, 0xFF, 0x43, 0xFF, 0xA9, 0x01, 0xD3, 0xF3, 0xFF, 0xFF, +- 0x01, 0xB4, 0xFF, 0xFF, 0x08, 0x24, 0x15, 0x00, 0x29, 0x44, 0x08, 0x26, 0xE1, 0x01, 0x72, 0x44, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x94, 0xF3, 0xE8, 0x85, 0xFF, 0xB7, +- 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x85, 0x73, 0x44, 0xD4, 0x84, 0x10, 0x65, 0xD4, 0x80, 0xFF, 0xFF, +- 0x37, 0x04, 0x3F, 0x40, 0x40, 0x26, 0x09, 0x00, 0x18, 0x60, 0x1C, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, +- 0xA4, 0x52, 0x5A, 0xD3, 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x50, 0xBC, 0xF3, 0xD2, 0xF1, 0x01, 0xA8, +- 0x07, 0xA8, 0x0A, 0x03, 0x09, 0x03, 0x64, 0x40, 0x01, 0x26, 0x09, 0x00, 0x18, 0x60, 0x07, 0xF3, +- 0xFF, 0xFF, 0x01, 0xB4, 0xFF, 0xFF, 0x03, 0x02, 0xAD, 0x4F, 0xFA, 0xB4, 0xA0, 0x5D, 0xAE, 0x4F, +- 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x3F, 0x40, 0x02, 0x2B, 0x11, 0x00, 0x0C, 0x60, 0x00, 0x62, +- 0x00, 0x60, 0x71, 0x7C, 0x00, 0x60, 0xB1, 0x65, 0x1A, 0x60, 0x58, 0x4D, 0x88, 0x78, 0xFF, 0xFF, +- 0x08, 0xE1, 0x62, 0xFF, 0xA3, 0xFF, 0xFF, 0xFF, 0xA2, 0xFF, 0x02, 0x60, 0x08, 0xE1, 0xBD, 0xFE, +- 0x97, 0x01, 0x21, 0x46, 0x01, 0x5D, 0x5C, 0x62, 0x03, 0xE1, 0x44, 0xFF, 0xA1, 0xFF, 0x9A, 0xFF, +- 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x62, 0x62, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0xA1, 0xFF, +- 0x5A, 0xDC, 0x12, 0xE1, 0x02, 0x60, 0x01, 0xE1, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x28, 0x40, +- 0x40, 0x2B, 0x03, 0x00, 0x29, 0x40, 0x20, 0x27, 0x97, 0x00, 0xC8, 0x74, 0xCD, 0xE2, 0x29, 0x44, +- 0x08, 0xBC, 0x40, 0x49, 0x44, 0xFF, 0x05, 0xE1, 0x28, 0x40, 0x08, 0x2A, 0x07, 0x00, 0x28, 0x40, +- 0x48, 0x36, 0x04, 0x00, 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0x29, 0x44, 0xFF, 0x60, +- 0xEF, 0x65, 0x24, 0x89, 0x40, 0x27, 0x3F, 0x00, 0x00, 0x00, 0x29, 0x40, 0x80, 0x27, 0x0B, 0x00, +- 0x07, 0x61, 0xA1, 0xFF, 0xCD, 0x81, 0x04, 0x25, 0x61, 0x00, 0x87, 0x4C, 0xFB, 0x02, 0xF3, 0x60, +- 0xA0, 0x64, 0x80, 0x4C, 0x07, 0x00, 0xA1, 0xFF, 0x9C, 0x4C, 0x9C, 0x4C, 0x9C, 0x4D, 0x05, 0x60, +- 0xCF, 0x64, 0x80, 0x4C, 0x28, 0x40, 0x40, 0x2B, 0x05, 0x00, 0x29, 0x40, 0x20, 0x27, 0x02, 0x00, +- 0x15, 0x60, 0x6F, 0x6B, 0x04, 0x25, 0x4A, 0x00, 0x30, 0x64, 0x3A, 0xDB, 0x44, 0xFF, 0x04, 0x25, +- 0x45, 0x00, 0x04, 0x60, 0x00, 0x65, 0x25, 0x44, 0xB4, 0x84, 0x80, 0x4E, 0x2D, 0x41, 0x04, 0x25, +- 0x3D, 0x00, 0x61, 0x4C, 0x00, 0x60, 0x8A, 0x65, 0xC5, 0x81, 0x61, 0x54, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x04, 0x25, 0x34, 0x00, 0x67, 0x4E, 0x07, 0x64, 0x1C, 0xFB, 0x00, 0xE1, 0x02, 0x60, 0x05, 0xE1, +- 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x28, 0x40, 0x40, 0x27, 0x0A, 0x00, 0x1C, 0x65, 0x28, 0x40, +- 0xA4, 0x36, 0x14, 0x65, 0x23, 0x44, 0xC4, 0x84, 0x28, 0x40, 0x08, 0x2A, 0x0C, 0x00, 0x07, 0x00, +- 0x23, 0x44, 0x1C, 0xA4, 0x29, 0x40, 0x20, 0x27, 0x02, 0x00, 0x11, 0x60, 0x0F, 0x6B, 0x3C, 0x46, +- 0x98, 0xF0, 0x23, 0x44, 0xC4, 0x84, 0x06, 0x74, 0x25, 0x5C, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xB0, 0x84, 0x80, 0x4C, 0x9C, 0x4C, 0x44, 0xFF, 0x18, 0xE1, 0x0A, 0x64, 0x1E, 0x74, +- 0x02, 0x60, 0x05, 0xE1, 0x40, 0x40, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0xC4, 0xE2, 0x27, 0x44, +- 0x20, 0x2A, 0x06, 0x00, 0x42, 0x64, 0x3A, 0xDB, 0x67, 0x4C, 0xB0, 0x60, 0x80, 0x78, 0xFF, 0xFF, +- 0x41, 0x64, 0x3A, 0xDB, 0x62, 0xFF, 0x08, 0xE1, 0xE2, 0xFE, 0x72, 0x52, 0xA1, 0xFF, 0x98, 0xFF, +- 0x80, 0x3E, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x28, 0x40, 0x08, 0x27, 0x66, 0x01, 0x3C, 0x46, +- 0x8B, 0xFF, 0x84, 0x60, 0x00, 0xE4, 0x0F, 0x60, 0x92, 0x64, 0xC9, 0x60, 0x58, 0x4F, 0x10, 0x78, +- 0xFF, 0xFF, 0x3F, 0xF2, 0x00, 0x60, 0x18, 0x70, 0x18, 0x71, 0x20, 0x72, 0x00, 0xF2, 0x60, 0x53, +- 0x20, 0xE1, 0xA1, 0xFF, 0x88, 0x75, 0x00, 0xE1, 0xFF, 0xFF, 0x60, 0x50, 0x75, 0x44, 0x12, 0x71, +- 0x6E, 0x72, 0x81, 0x75, 0xFF, 0xFF, 0x88, 0xFF, 0xA3, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0x32, 0xF3, +- 0x08, 0x29, 0x0A, 0x00, 0x60, 0x40, 0x07, 0x22, 0x07, 0x00, 0xFE, 0xB4, 0x32, 0xFB, 0x27, 0x44, +- 0x10, 0xBC, 0xF7, 0xB4, 0x40, 0x47, 0x43, 0xFF, 0x00, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x08, 0xE1, +- 0x31, 0x40, 0x01, 0x2A, 0x04, 0x00, 0x00, 0x64, 0x33, 0xFB, 0x01, 0x60, 0x0A, 0xE1, 0xE5, 0xFE, +- 0x27, 0x05, 0x9F, 0xFE, 0x12, 0x05, 0x31, 0x41, 0x40, 0x2A, 0x0F, 0x00, 0x07, 0x60, 0xEA, 0xF1, +- 0xAE, 0x4C, 0x90, 0x80, 0x10, 0x2A, 0x09, 0x00, 0x7F, 0xB1, 0x07, 0x60, 0xEA, 0xFB, 0x60, 0x40, +- 0x10, 0x2A, 0x80, 0xB9, 0x41, 0x51, 0xDF, 0xFE, 0x19, 0xFF, 0x27, 0x44, 0x10, 0x26, 0x13, 0x00, +- 0x9F, 0xFE, 0x02, 0x04, 0x40, 0xE1, 0x06, 0x00, 0x7C, 0xE1, 0x31, 0x44, 0x01, 0x2A, 0x02, 0x00, +- 0x04, 0x0A, 0xFD, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0xAF, 0x60, 0x7B, 0x78, 0xFF, 0xFF, +- 0xAA, 0x60, 0xC0, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x08, 0x26, 0xFF, 0xFF, 0xC0, 0x60, 0xEA, 0x78, +- 0xFF, 0xFF, 0x48, 0xF3, 0x32, 0xF1, 0x00, 0x63, 0x64, 0x40, 0x07, 0x26, 0x03, 0x00, 0xA5, 0x60, +- 0x6C, 0x78, 0xFF, 0xFF, 0x31, 0x40, 0x08, 0x26, 0xF1, 0x01, 0xCD, 0xE2, 0x84, 0xE1, 0x70, 0x41, +- 0xAD, 0x80, 0x71, 0x40, 0x80, 0x27, 0xEA, 0x12, 0x03, 0x03, 0xC1, 0x60, 0x3B, 0x78, 0xFF, 0xFF, +- 0xA1, 0xFF, 0xFF, 0xFF, 0xC4, 0xE2, 0x32, 0xFD, 0x60, 0x40, 0x01, 0x2A, 0xDC, 0x01, 0x3C, 0x46, +- 0x3E, 0xF2, 0x2A, 0xF0, 0x27, 0x41, 0x44, 0x48, 0x20, 0xB9, 0x01, 0xB4, 0xF7, 0xB1, 0x0A, 0x03, +- 0x64, 0x40, 0x08, 0x27, 0x07, 0x00, 0x0F, 0x60, 0xEE, 0x63, 0x00, 0x64, 0x45, 0xFB, 0x46, 0xFB, +- 0xBD, 0xDB, 0xA3, 0xDB, 0xCB, 0x0A, 0xCA, 0x11, 0x41, 0x47, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, +- 0x10, 0x26, 0x04, 0x00, 0x01, 0x2A, 0x05, 0x00, 0x10, 0x2B, 0x03, 0x00, 0x29, 0x47, 0x20, 0xBF, +- 0x40, 0x49, 0x05, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0x2A, 0xE8, 0x3C, 0x46, 0x00, 0x63, 0x32, 0xFD, +- 0x43, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2A, 0x03, 0x00, 0xA8, 0x60, 0x76, 0x78, +- 0xFF, 0xFF, 0x64, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x0E, 0x00, 0x1F, 0xF2, 0xFF, 0xFF, +- 0x60, 0x40, 0x40, 0x2B, 0x09, 0x00, 0x15, 0x60, 0xDD, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x2A, +- 0x03, 0x00, 0xA9, 0x60, 0x81, 0x78, 0xFF, 0xFF, 0x1F, 0xF2, 0xC0, 0x60, 0x00, 0x65, 0xA4, 0x9C, +- 0x3F, 0x60, 0xCF, 0x65, 0x29, 0x44, 0xA4, 0x84, 0x30, 0x89, 0x15, 0x60, 0xD9, 0xF3, 0xFF, 0xFF, +- 0x15, 0x60, 0xD8, 0xFB, 0x1F, 0xF2, 0x39, 0xF1, 0xE0, 0x60, 0xFF, 0xB5, 0x0A, 0x18, 0x60, 0x47, +- 0x1F, 0xB4, 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, +- 0x60, 0x47, 0xB4, 0x81, 0x07, 0x60, 0xEB, 0xF1, 0xFF, 0xFF, 0xB1, 0x8C, 0x29, 0x40, 0x40, 0x2B, +- 0x10, 0x00, 0x22, 0x60, 0xC6, 0x65, 0x60, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, +- 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x01, 0x60, 0x09, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, +- 0x14, 0x00, 0x22, 0x60, 0xC6, 0x65, 0x60, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, +- 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, +- 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, 0x67, 0x44, 0x60, 0x4C, 0x00, 0xE1, 0x84, 0xFF, 0xC1, 0x60, +- 0x6B, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x0D, 0x00, 0xE5, 0xFE, 0x03, 0x04, 0xAA, 0x60, 0xC0, 0x78, +- 0xFF, 0xFF, 0x32, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x07, 0x22, 0x43, 0xFF, 0xA4, 0x60, 0x7C, 0x78, +- 0xFF, 0xFF, 0x3C, 0x44, 0x0B, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x0A, 0xE1, 0x1C, 0x42, 0x22, 0x46, +- 0x13, 0xF2, 0xFF, 0x65, 0x60, 0x47, 0x2A, 0xF2, 0x40, 0x45, 0x40, 0x48, 0x04, 0x2B, 0x13, 0x00, +- 0x16, 0xF2, 0x1D, 0xF2, 0x40, 0x43, 0x0F, 0xF2, 0x40, 0x4D, 0x0F, 0x64, 0x14, 0xF0, 0x35, 0xF2, +- 0xA0, 0x82, 0x0F, 0xB4, 0xCA, 0x85, 0xD4, 0x80, 0x10, 0xF2, 0x01, 0x02, 0x2B, 0xFA, 0x27, 0x44, +- 0x40, 0xBC, 0x40, 0x47, 0x13, 0x00, 0x17, 0xF2, 0x2C, 0xF0, 0x40, 0x43, 0x1B, 0xF2, 0x1D, 0xFA, +- 0x40, 0x4D, 0x64, 0x40, 0x01, 0x2A, 0x02, 0x00, 0xAB, 0xFC, 0x05, 0x00, 0x28, 0x40, 0xA4, 0x36, +- 0x02, 0x00, 0x11, 0xF2, 0x2B, 0xFA, 0x27, 0x44, 0xBF, 0xB4, 0x40, 0x47, 0xF0, 0xFE, 0xAF, 0x60, +- 0x85, 0x78, 0xFF, 0xFF, 0x22, 0x46, 0x2C, 0xF0, 0x27, 0x44, 0xDF, 0xB4, 0x40, 0x47, 0x64, 0x40, +- 0x01, 0x26, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x2A, 0xF0, 0x01, 0x65, 0x64, 0x40, 0xA4, 0x3A, +- 0x04, 0x65, 0x27, 0x44, 0x34, 0x87, 0x36, 0xF3, 0xFF, 0xFF, 0x60, 0x56, 0xAD, 0xE2, 0x04, 0x64, +- 0x3A, 0xDB, 0x69, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x06, 0x64, 0x3A, 0xDB, 0x22, 0x46, +- 0x01, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xC1, 0x60, 0x44, 0x78, 0xFF, 0xFF, 0x28, 0x40, 0xC4, 0x3A, +- 0x0C, 0x00, 0x27, 0x44, 0xFD, 0xB4, 0x40, 0x47, 0xA8, 0xE2, 0x05, 0xE1, 0x01, 0x60, 0x08, 0xE1, +- 0x2A, 0xE8, 0x3C, 0x46, 0xA5, 0x60, 0x1C, 0x78, 0xFF, 0xFF, 0x3F, 0x40, 0x01, 0x2B, 0x05, 0x00, +- 0x67, 0x4C, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, 0x07, 0x60, 0xEC, 0xF1, 0x1F, 0xF2, +- 0x2A, 0xE8, 0xB0, 0x81, 0x29, 0x40, 0x40, 0x2B, 0x14, 0x00, 0x61, 0x4C, 0x22, 0x60, 0xC6, 0x65, +- 0x61, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, +- 0x01, 0x60, 0x09, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0xFF, 0x60, 0xF2, 0x64, 0x64, 0x4C, 0x40, 0x43, +- 0x18, 0x00, 0x29, 0x47, 0x80, 0xB7, 0x34, 0x94, 0x60, 0x4C, 0x22, 0x60, 0xC6, 0x65, 0x61, 0x47, +- 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, +- 0x69, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, 0x67, 0x44, +- 0x60, 0x4C, 0x40, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0x28, 0x45, 0xBF, 0x60, 0xFF, 0x64, 0x24, 0x88, +- 0xC4, 0xE2, 0x08, 0x64, 0x3A, 0xDB, 0x21, 0x46, 0x2A, 0x44, 0x72, 0x45, 0x24, 0xFA, 0x94, 0xF3, +- 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, 0x01, 0x26, 0x64, 0x44, 0x94, 0xF9, 0x25, 0xFA, +- 0x95, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x95, 0xFB, 0x28, 0xFA, 0x96, 0xF3, 0x02, 0x04, 0xDC, 0x84, +- 0x96, 0xFB, 0x29, 0xFA, 0x24, 0x44, 0x04, 0x2A, 0x06, 0x00, 0x28, 0x40, 0xA4, 0x36, 0x03, 0x00, +- 0xA7, 0x60, 0x46, 0x78, 0xFF, 0xFF, 0x94, 0xFC, 0x13, 0x60, 0x4A, 0xF1, 0x28, 0x44, 0x08, 0x2A, +- 0x51, 0x00, 0x03, 0x2B, 0x01, 0x00, 0x4E, 0x00, 0x64, 0x40, 0x00, 0x36, 0x4B, 0x00, 0x32, 0xF2, +- 0x2F, 0xF0, 0x50, 0xFE, 0x01, 0x2A, 0x03, 0x00, 0x01, 0x61, 0x8E, 0xF3, 0x31, 0x00, 0xD0, 0x80, +- 0x33, 0xF2, 0x30, 0xF0, 0x34, 0xF2, 0xD0, 0x80, 0x31, 0xF0, 0xFF, 0xFF, 0xD0, 0x80, 0x60, 0x47, +- 0x34, 0x0C, 0xFF, 0xB4, 0x15, 0x60, 0x02, 0x65, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0xFF, 0xFF, +- 0x31, 0x18, 0x60, 0x43, 0x50, 0xFE, 0x66, 0x41, 0x32, 0xF0, 0x63, 0x46, 0x03, 0xF2, 0x61, 0x46, +- 0xD0, 0x80, 0x33, 0xF0, 0x63, 0x46, 0x04, 0xF2, 0x61, 0x46, 0xD0, 0x80, 0x34, 0xF0, 0x63, 0x46, +- 0x05, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x0C, 0x00, 0xF2, 0x61, 0x46, 0x1A, 0x18, +- 0xE8, 0x01, 0x06, 0xF0, 0x8E, 0xF3, 0x61, 0x46, 0x02, 0x61, 0x64, 0x40, 0x02, 0x2A, 0x12, 0x00, +- 0xFC, 0xA0, 0xFF, 0xFF, 0x04, 0x0E, 0x61, 0x44, 0x14, 0xFA, 0x11, 0xFC, 0x0B, 0x00, 0x2C, 0xF2, +- 0x2F, 0xFA, 0x2D, 0xF2, 0x30, 0xFA, 0x2E, 0xF2, 0x31, 0xFA, 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xBC, +- 0x40, 0x46, 0x1E, 0x00, 0x26, 0x43, 0x84, 0xBB, 0xFC, 0xB3, 0x21, 0x46, 0x01, 0x5D, 0x0F, 0xFC, +- 0x5C, 0x46, 0x05, 0xFF, 0x27, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x50, 0xFE, 0x28, 0x40, 0x08, 0x3A, +- 0x12, 0x00, 0x2F, 0xF2, 0x30, 0xF0, 0x60, 0x43, 0x31, 0xF2, 0x22, 0x46, 0x64, 0x41, 0x2C, 0xF0, +- 0x2D, 0xF0, 0xD3, 0x80, 0x2E, 0xF0, 0xD1, 0x80, 0xD0, 0x80, 0x27, 0x44, 0x09, 0x0C, 0x03, 0x00, +- 0x27, 0x44, 0x06, 0x22, 0x05, 0x00, 0xB8, 0xB4, 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, +- 0xD4, 0x64, 0x40, 0x48, 0x0D, 0x64, 0x3A, 0xDB, 0x21, 0x46, 0x1C, 0xF2, 0x00, 0xE1, 0xF0, 0xFE, +- 0x00, 0x63, 0x28, 0x44, 0xA4, 0x36, 0x07, 0x00, 0x04, 0x2B, 0x05, 0x00, 0x30, 0xF3, 0x2D, 0x45, +- 0xD4, 0x84, 0xCA, 0x65, 0xD4, 0x83, 0xD4, 0x64, 0x35, 0x00, 0x0F, 0x64, 0x3A, 0xDB, 0x21, 0x46, +- 0x29, 0x40, 0x40, 0x27, 0x15, 0x00, 0x80, 0x27, 0x02, 0x00, 0xCA, 0x65, 0x01, 0x00, 0x6A, 0x65, +- 0x1C, 0xF2, 0xFF, 0xFF, 0x04, 0x7F, 0x40, 0x45, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, +- 0x37, 0x36, 0x15, 0x64, 0x6E, 0x3A, 0x17, 0x00, 0x84, 0x7F, 0x40, 0x45, 0x0B, 0x64, 0x13, 0x00, +- 0x1C, 0xF2, 0x1E, 0x65, 0x40, 0x45, 0x0B, 0x36, 0x1E, 0x64, 0x0F, 0x36, 0x16, 0x64, 0x0A, 0x36, +- 0x12, 0x64, 0x0E, 0x36, 0x0E, 0x64, 0x09, 0x36, 0x0E, 0x64, 0x0D, 0x36, 0x0A, 0x64, 0x08, 0x36, +- 0x0A, 0x64, 0x0C, 0x36, 0x0A, 0x64, 0x40, 0x4D, 0x00, 0xE1, 0xF0, 0xFE, 0x2B, 0xF2, 0xC4, 0x85, +- 0xD4, 0x83, 0xC4, 0x64, 0x40, 0x48, 0x2F, 0xF0, 0xB0, 0xF0, 0xB1, 0xF2, 0xA1, 0xFF, 0x12, 0x74, +- 0xCD, 0xE2, 0x80, 0x4E, 0x12, 0x74, 0x83, 0x4C, 0x12, 0x74, 0x9A, 0xFF, 0x84, 0x4C, 0x12, 0x74, +- 0x85, 0x4C, 0x12, 0x74, 0x81, 0x4C, 0x12, 0x74, 0xA1, 0xFF, 0x98, 0xFF, 0xB1, 0x60, 0x58, 0x4F, +- 0x00, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0x18, 0xE1, 0x78, 0x44, 0x03, 0xA4, 0x35, 0xFB, 0xB1, 0x60, +- 0x43, 0x78, 0xFF, 0xFF, 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, 0x27, 0x44, 0x01, 0x2A, 0x05, 0x00, +- 0xFE, 0xB4, 0x40, 0x47, 0xA5, 0x60, 0xCD, 0x78, 0xFF, 0xFF, 0x13, 0x60, 0x2E, 0xF3, 0xFF, 0xFF, +- 0x60, 0x40, 0x02, 0x36, 0xC1, 0xFE, 0xA4, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x28, 0x40, 0xB4, 0x3A, +- 0x0B, 0x00, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, +- 0xC0, 0xFE, 0xA6, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x28, 0x44, 0xD4, 0x36, 0x03, 0x00, 0xA8, 0x60, +- 0x5D, 0x78, 0xFF, 0xFF, 0xA8, 0xE2, 0x27, 0x44, 0xFB, 0xB4, 0x40, 0x47, 0x1C, 0x42, 0x22, 0x46, +- 0x16, 0x60, 0x2B, 0xF3, 0xFF, 0xFF, 0x34, 0xFB, 0x2A, 0xF0, 0xF7, 0x60, 0xFF, 0x64, 0xA0, 0x84, +- 0xA2, 0xDA, 0x60, 0x40, 0x40, 0x2B, 0xC4, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x22, 0x26, +- 0x3F, 0x00, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x05, 0x00, 0xBA, 0x00, 0x04, 0x2B, 0xB8, 0x00, +- 0x87, 0xF5, 0x01, 0x00, 0x07, 0xF4, 0x4B, 0xF2, 0xFF, 0xFF, 0xDC, 0x84, 0x4B, 0xFA, 0x0C, 0x60, +- 0xFE, 0x62, 0x80, 0xFF, 0xC8, 0x60, 0x78, 0x44, 0x02, 0xA4, 0xA2, 0xDB, 0x46, 0x78, 0xFF, 0xFF, +- 0x82, 0xFF, 0x87, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, 0x22, 0x46, +- 0x22, 0xF2, 0x63, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x4B, 0xF0, 0x64, 0x41, +- 0x64, 0x47, 0x60, 0x5F, 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, 0x22, 0x46, 0x3A, 0xFA, +- 0x64, 0x44, 0x20, 0x7F, 0x34, 0x94, 0x3B, 0xFA, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, +- 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x80, 0x00, +- 0x2A, 0xF2, 0x00, 0x60, 0x7C, 0x62, 0x60, 0x40, 0x40, 0x2B, 0x24, 0x00, 0xA2, 0xD3, 0x00, 0x61, +- 0x60, 0xFE, 0xA0, 0xD3, 0x5E, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, +- 0xC0, 0x2B, 0x04, 0x00, 0x80, 0x2A, 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, +- 0x60, 0x47, 0xDC, 0x87, 0x01, 0x61, 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, +- 0x5A, 0xD1, 0xFF, 0xFF, 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, +- 0xA2, 0xDB, 0x20, 0xFE, 0x00, 0x60, 0x3E, 0xF3, 0xFF, 0xFF, 0xA0, 0xD3, 0x5A, 0xD1, 0x3A, 0xFA, +- 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5A, 0x64, 0x47, +- 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x40, 0xF3, +- 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, 0x64, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5A, 0x64, 0x47, +- 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE6, 0x7F, +- 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5A, 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, +- 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5A, 0x64, 0x47, +- 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEC, 0x7F, +- 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, +- 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5A, 0x08, 0x60, 0x00, 0xEA, 0x65, 0x44, 0x02, 0xA4, +- 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, +- 0x0B, 0xF2, 0xFF, 0xFF, 0x7F, 0xB4, 0x0C, 0xF0, 0x04, 0x02, 0x64, 0x46, 0x00, 0xF0, 0x04, 0x64, +- 0x22, 0x46, 0x03, 0xFA, 0x60, 0x41, 0x64, 0x46, 0x01, 0xF2, 0xFC, 0xA1, 0x61, 0x45, 0xD4, 0x84, +- 0xFF, 0xFF, 0x08, 0x02, 0x00, 0xF0, 0x04, 0x63, 0x64, 0x46, 0x01, 0xF2, 0x22, 0x46, 0x1A, 0xFA, +- 0x03, 0xFC, 0x02, 0x00, 0x22, 0x46, 0x1A, 0xFA, 0x35, 0xF2, 0x04, 0xF8, 0xDC, 0x84, 0x35, 0xFA, +- 0x14, 0xF2, 0x0F, 0xB5, 0x0F, 0xB4, 0xCC, 0x84, 0x94, 0x80, 0x04, 0x60, 0x00, 0x65, 0x2A, 0xF2, +- 0x01, 0x02, 0x94, 0x84, 0x2A, 0xFA, 0x95, 0xFC, 0x06, 0x00, 0xC4, 0x3A, 0x07, 0x00, 0x27, 0x44, +- 0xFD, 0xB4, 0x40, 0x47, 0xA8, 0xE2, 0xA5, 0x60, 0x7A, 0x78, 0xFF, 0xFF, 0x28, 0x44, 0x04, 0x26, +- 0x05, 0x00, 0x68, 0x3A, 0x03, 0x00, 0x32, 0x44, 0x00, 0x27, 0x03, 0x00, 0xA4, 0x60, 0x7C, 0x78, +- 0xFF, 0xFF, 0x0A, 0x64, 0x3A, 0xDB, 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0x0E, 0x64, 0x3A, 0xDB, +- 0x3C, 0x44, 0x60, 0x46, 0x1E, 0xF0, 0x40, 0x42, 0x64, 0x40, 0x40, 0x27, 0x48, 0x00, 0x1F, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, 0x3C, 0x00, 0x80, 0x2B, 0x0B, 0x00, 0xBF, 0x60, 0xFF, 0x65, +- 0x29, 0x44, 0x24, 0x89, 0x80, 0x60, 0x00, 0x65, 0x29, 0x44, 0x34, 0x89, 0x80, 0x60, 0x00, 0x63, +- 0x05, 0x00, 0x3F, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x00, 0x63, 0x1E, 0xF2, 0x39, 0xF1, +- 0xC0, 0x60, 0xFF, 0xB5, 0x0A, 0x18, 0x60, 0x47, 0x1F, 0xB4, 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, +- 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, 0xB4, 0x84, 0x07, 0x60, 0xEB, 0xF1, +- 0x3C, 0x94, 0xB0, 0x84, 0x60, 0x4C, 0x22, 0x60, 0xC6, 0x65, 0x60, 0x47, 0x1F, 0xB4, 0xE0, 0x84, +- 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, 0x60, 0x4C, +- 0xB5, 0xFF, 0x64, 0x4C, 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, 0x67, 0x44, 0x60, 0x4C, 0x32, 0x00, +- 0x15, 0x60, 0xDD, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x04, 0x26, 0xCB, 0x01, 0xBF, 0x01, 0x40, 0x60, +- 0x00, 0x65, 0x29, 0x44, 0x34, 0x89, 0x40, 0x60, 0x00, 0x63, 0x9F, 0xF2, 0x1E, 0xF2, 0x39, 0xF1, +- 0xC0, 0x60, 0xFF, 0xB5, 0x0A, 0x18, 0x60, 0x47, 0x1F, 0xB4, 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, +- 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, 0xB4, 0x84, 0x07, 0x60, 0xEB, 0xF1, +- 0x3C, 0x94, 0xB0, 0x81, 0x61, 0x4C, 0x22, 0x60, 0xC6, 0x65, 0x61, 0x47, 0x1F, 0xB4, 0xE0, 0x84, +- 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x01, 0x60, 0x09, 0x6B, 0x60, 0x4C, +- 0xB5, 0xFF, 0x64, 0x4C, 0x40, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0x84, 0xFF, 0xC1, 0x60, 0x6B, 0x64, +- 0x40, 0x42, 0x82, 0xFF, 0x2A, 0xF2, 0x10, 0x60, 0x00, 0x65, 0xA4, 0x84, 0xB4, 0xBC, 0x1E, 0xF0, +- 0x40, 0x48, 0x64, 0x40, 0x40, 0x27, 0x17, 0x00, 0x1C, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x0A, 0x36, +- 0x06, 0x00, 0x14, 0x36, 0x07, 0x00, 0x37, 0x36, 0x08, 0x00, 0x6E, 0x36, 0x09, 0x00, 0x70, 0x7C, +- 0xA0, 0x63, 0x0F, 0x00, 0x38, 0x7C, 0x50, 0x63, 0x0C, 0x00, 0x15, 0x7C, 0x1E, 0x63, 0x09, 0x00, +- 0x0B, 0x7C, 0x0F, 0x63, 0x06, 0x00, 0x9C, 0xF4, 0xFF, 0x65, 0x63, 0x47, 0xA4, 0x9C, 0xA7, 0x84, +- 0x23, 0x00, 0x40, 0x45, 0x43, 0x4D, 0x00, 0xE1, 0xF0, 0xFE, 0x29, 0x40, 0x80, 0x2B, 0x03, 0x00, +- 0x00, 0x60, 0x6A, 0x65, 0x02, 0x00, 0x00, 0x60, 0xCA, 0x65, 0x1F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, +- 0x40, 0x27, 0x0E, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x04, 0x27, 0x03, 0x00, 0x65, 0x44, +- 0xE0, 0x85, 0x12, 0x00, 0x2B, 0xF2, 0x11, 0xF0, 0xC0, 0x84, 0xD0, 0x84, 0xC4, 0x83, 0x11, 0x00, +- 0x1E, 0x64, 0xC4, 0x84, 0x60, 0x45, 0x08, 0x00, 0x40, 0x45, 0xFF, 0x60, 0xF8, 0x64, 0x40, 0x43, +- 0x00, 0xE1, 0xF0, 0xFE, 0x00, 0x60, 0x3C, 0x65, 0x91, 0xF4, 0x1B, 0xF0, 0xC3, 0x84, 0xC4, 0x84, +- 0xC0, 0x83, 0x28, 0x44, 0xA1, 0xFF, 0x12, 0x74, 0x80, 0x4E, 0x12, 0x74, 0x83, 0x4C, 0x9A, 0xFF, +- 0x12, 0x74, 0x56, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, +- 0x5C, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0xA1, 0xFF, +- 0x98, 0xFF, 0xB1, 0x60, 0x58, 0x4F, 0x00, 0x78, 0xFF, 0xFF, 0xBC, 0xFF, 0xB5, 0xFF, 0x01, 0x60, +- 0x18, 0xE1, 0x47, 0xFF, 0x27, 0x44, 0x02, 0xBC, 0x40, 0x47, 0x36, 0xF3, 0xB6, 0xFF, 0xB7, 0xFF, +- 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0x60, 0x56, 0xAD, 0xE2, 0xA5, 0x60, 0xC7, 0x78, +- 0xFF, 0xFF, 0x15, 0x60, 0xDD, 0xF3, 0x15, 0x60, 0xBE, 0xF3, 0x60, 0x40, 0x04, 0x26, 0x0B, 0x00, +- 0x07, 0xB4, 0x60, 0x40, 0x01, 0x36, 0x07, 0x00, 0x29, 0x44, 0xBF, 0x60, 0xFF, 0xB7, 0x80, 0xBF, +- 0x40, 0x49, 0x80, 0x67, 0x05, 0x00, 0x3F, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x00, 0x64, +- 0x12, 0x60, 0xD3, 0xF1, 0xFF, 0xFF, 0x15, 0x60, 0xD8, 0xF9, 0x39, 0xF1, 0x12, 0x60, 0xBF, 0xF1, +- 0x64, 0x41, 0x64, 0x5E, 0x60, 0x45, 0x64, 0x47, 0x1F, 0xB4, 0x54, 0x94, 0xE0, 0xA0, 0x02, 0x0D, +- 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, 0x07, 0x60, 0xEB, 0xF1, 0xB4, 0x84, +- 0xB0, 0x8C, 0x22, 0x60, 0xC6, 0x7C, 0x60, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x40, 0xD3, +- 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, +- 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, 0x67, 0x44, 0x60, 0x4C, 0x40, 0xE1, 0x01, 0x60, 0x08, 0xE1, +- 0x84, 0xFF, 0xC1, 0x60, 0x6B, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x3C, 0x44, 0x60, 0x46, 0x40, 0x42, +- 0x13, 0x64, 0x3A, 0xDB, 0x10, 0x60, 0x00, 0x65, 0x3C, 0x46, 0x2A, 0xF2, 0x15, 0x60, 0xBE, 0xF1, +- 0xA4, 0x84, 0xC4, 0xBC, 0x40, 0x48, 0x64, 0x44, 0x04, 0x26, 0x09, 0x00, 0x02, 0x26, 0x0A, 0x00, +- 0x01, 0x26, 0x0B, 0x00, 0x08, 0x2A, 0x03, 0x00, 0x0B, 0x63, 0x6E, 0x64, 0x08, 0x00, 0x15, 0x63, +- 0x37, 0x64, 0x05, 0x00, 0x38, 0x63, 0x14, 0x64, 0x02, 0x00, 0x70, 0x63, 0x0A, 0x64, 0x43, 0x4D, +- 0x40, 0x45, 0x00, 0xE1, 0xF0, 0xFE, 0x00, 0x60, 0x1E, 0x64, 0x1B, 0xF0, 0x11, 0xF0, 0xC0, 0x84, +- 0xC0, 0x84, 0x60, 0x43, 0x28, 0x44, 0xA1, 0xFF, 0x12, 0x74, 0x80, 0x4E, 0x12, 0x74, 0x83, 0x4C, +- 0x9A, 0xFF, 0x12, 0x74, 0x5C, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, +- 0x12, 0x74, 0xA1, 0xFF, 0x98, 0xFF, 0xB1, 0x60, 0x58, 0x4F, 0x00, 0x78, 0xFF, 0xFF, 0x01, 0x60, +- 0x18, 0xE1, 0x78, 0x44, 0x03, 0xA4, 0x35, 0xFB, 0xB1, 0x60, 0x43, 0x78, 0xFF, 0xFF, 0xC4, 0xE2, +- 0x08, 0x64, 0x3A, 0xDB, 0xA5, 0x60, 0x1C, 0x78, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x2A, 0x0E, 0x00, +- 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xBC, 0x40, 0x46, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, +- 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x30, 0xF1, 0x52, 0x00, 0xFC, 0xB3, 0x32, 0x40, +- 0x01, 0x2A, 0x06, 0x00, 0x0A, 0xBB, 0x0F, 0xFC, 0xCB, 0xFE, 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, +- 0x24, 0x44, 0x04, 0x26, 0x02, 0x00, 0x0F, 0xFC, 0x05, 0xFF, 0x30, 0xF1, 0x27, 0x44, 0x05, 0x22, +- 0x2C, 0x00, 0xFA, 0xB4, 0x40, 0x47, 0x24, 0x44, 0x10, 0x2A, 0x23, 0x00, 0x28, 0x40, 0xD4, 0x3A, +- 0x20, 0x00, 0x31, 0x40, 0x08, 0x26, 0x00, 0x7C, 0x2B, 0x44, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, +- 0x64, 0x44, 0xC4, 0x84, 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, +- 0x20, 0x29, 0x6D, 0xE2, 0x1D, 0xF0, 0xC0, 0x64, 0xC0, 0x84, 0x0A, 0x60, 0x7B, 0xF1, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA2, 0xDB, 0xA5, 0x60, 0xCD, 0x78, +- 0xFF, 0xFF, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x07, 0x00, 0x02, 0x2A, 0x05, 0x00, 0xFD, 0xB4, +- 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x05, 0x64, 0x3A, 0xDB, 0x28, 0x44, 0xA4, 0x3A, +- 0x07, 0x00, 0x01, 0x60, 0x02, 0x7C, 0x25, 0x44, 0x0A, 0x3A, 0x02, 0x00, 0x01, 0x60, 0x3A, 0x7C, +- 0x31, 0x40, 0x08, 0x26, 0x00, 0x7C, 0x2B, 0x44, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, 0x64, 0x44, +- 0xC4, 0x84, 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x28, 0x40, 0xE4, 0x36, 0x00, 0xB4, 0x60, 0x50, +- 0x08, 0x28, 0x01, 0x00, 0x20, 0x29, 0x6D, 0xE2, 0xA4, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x27, 0x44, +- 0x05, 0x22, 0x09, 0x00, 0xBA, 0xB4, 0x40, 0x47, 0x3C, 0x46, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, +- 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x02, 0x2A, 0x06, 0x00, 0xFD, 0xB4, 0x40, 0x47, +- 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xF4, 0x01, 0xF3, 0x0A, 0x7C, 0x50, 0x6D, 0xE2, 0xF0, 0x01, +- 0x72, 0x45, 0xDC, 0x84, 0x94, 0xFB, 0x11, 0x64, 0x3A, 0xDB, 0x95, 0xF3, 0x06, 0x04, 0xDC, 0x84, +- 0x95, 0xFB, 0x96, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x96, 0xFB, 0xA4, 0x60, 0x87, 0x78, 0xFF, 0xFF, +- 0x00, 0x61, 0x12, 0x64, 0x3A, 0xDB, 0x18, 0x60, 0xEE, 0x63, 0xBD, 0xD3, 0x72, 0x45, 0x44, 0x8A, +- 0x02, 0x28, 0x03, 0x00, 0xE4, 0xE2, 0xDD, 0x81, 0x04, 0x00, 0x02, 0x28, 0x02, 0x00, 0xE4, 0xE2, +- 0xDD, 0x81, 0xBD, 0xD3, 0x94, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, +- 0xC4, 0x84, 0x60, 0x55, 0x2A, 0x52, 0xE4, 0xE2, 0x94, 0xFB, 0x02, 0x24, 0x01, 0xB9, 0xBD, 0xD3, +- 0x95, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, 0xC4, 0x84, 0x95, 0xFB, +- 0x02, 0x24, 0x01, 0xB9, 0xBD, 0xD3, 0x96, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0xC4, 0x84, 0x96, 0xFB, +- 0xA5, 0x60, 0x71, 0x78, 0xFF, 0xFF, 0xAC, 0x01, 0x47, 0xFF, 0x44, 0xFF, 0xC8, 0x74, 0xCD, 0xE2, +- 0xAA, 0x60, 0xFE, 0x78, 0x00, 0x61, 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0x5C, 0x44, 0x26, 0x44, +- 0x02, 0x26, 0x0C, 0x00, 0x3E, 0x46, 0x09, 0xF2, 0x1E, 0x41, 0x03, 0x1B, 0xAC, 0x60, 0x14, 0x78, +- 0xFF, 0xFF, 0x40, 0x5E, 0xFD, 0xFB, 0x21, 0x44, 0x02, 0x64, 0x40, 0x46, 0x41, 0x5D, 0x21, 0x46, +- 0x00, 0x64, 0x31, 0xFA, 0x00, 0xF2, 0x46, 0x45, 0x87, 0xFC, 0xAC, 0xE2, 0x01, 0x64, 0x33, 0xFB, +- 0x32, 0x40, 0x01, 0x2A, 0x21, 0x00, 0x19, 0xF3, 0x01, 0x60, 0x1E, 0xE1, 0x1D, 0x18, 0x80, 0x64, +- 0x40, 0x49, 0x00, 0xE1, 0x19, 0xFF, 0x08, 0x64, 0x2A, 0xFA, 0x5A, 0xDA, 0x2C, 0xFA, 0x5A, 0xDA, +- 0x5A, 0xDA, 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0x72, 0x44, 0x24, 0xFA, 0x94, 0xF3, +- 0x25, 0xFA, 0xA1, 0xFF, 0xFF, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, +- 0x7C, 0x4B, 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0x01, 0xE1, 0x01, 0x60, 0x1A, 0xE1, 0x3F, 0x60, +- 0xCF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x2E, 0x44, 0x00, 0x36, 0x41, 0x00, 0x01, 0x3A, 0xC9, 0x00, +- 0x88, 0xFF, 0x40, 0x67, 0x29, 0x45, 0x34, 0x89, 0x04, 0x64, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, +- 0xA1, 0xFF, 0x6C, 0x45, 0x65, 0x44, 0x0F, 0xB4, 0x40, 0x45, 0x1C, 0xFA, 0x65, 0x44, 0x29, 0x41, +- 0xF9, 0x81, 0x52, 0x4A, 0x71, 0x89, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x83, 0x1D, 0xFC, +- 0x1B, 0xFC, 0x98, 0xF1, 0xFC, 0xA3, 0xD3, 0x80, 0x43, 0x43, 0x03, 0x04, 0xAC, 0x60, 0x0A, 0x78, +- 0xFF, 0xFF, 0x09, 0x7C, 0xD3, 0x80, 0x9A, 0xFF, 0x03, 0x07, 0xAC, 0x60, 0x0A, 0x78, 0xFF, 0xFF, +- 0x25, 0x44, 0x01, 0x26, 0x0F, 0xAC, 0x1F, 0x60, 0x50, 0x65, 0x44, 0xD3, 0x12, 0x65, 0x45, 0x46, +- 0x60, 0x47, 0x40, 0x7F, 0x27, 0xFA, 0x8F, 0xFC, 0x18, 0x61, 0xCB, 0xF1, 0xA1, 0xFF, 0x6C, 0x44, +- 0xDC, 0x80, 0xFF, 0xFF, 0x21, 0x03, 0x50, 0xFE, 0xAC, 0x60, 0x20, 0x78, 0xFF, 0xFF, 0xC8, 0x60, +- 0x0B, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0xB5, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xAA, 0x74, 0xCD, 0xE2, +- 0x02, 0x64, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0x01, 0x60, 0x08, 0xE1, 0x05, 0xE1, 0xA1, 0xFF, +- 0xFF, 0xFF, 0x04, 0x25, 0x76, 0x00, 0x6C, 0x44, 0x0A, 0x36, 0x07, 0x00, 0x14, 0x36, 0x05, 0x00, +- 0x37, 0x36, 0x03, 0x00, 0x6E, 0x36, 0x01, 0x00, 0x6C, 0x00, 0x40, 0x45, 0x32, 0x74, 0xA1, 0xFF, +- 0x1C, 0xFA, 0x40, 0x4E, 0x8C, 0x44, 0x60, 0x43, 0x1D, 0xFA, 0x01, 0xE1, 0x20, 0x64, 0x3A, 0xDB, +- 0x2E, 0x44, 0x14, 0x36, 0x12, 0x00, 0x0A, 0x36, 0x0F, 0x00, 0x63, 0x45, 0xE3, 0x83, 0xE3, 0x83, +- 0xC7, 0x83, 0xE3, 0x83, 0xC7, 0x83, 0xFF, 0xFF, 0x37, 0x36, 0x05, 0x00, 0x6E, 0x36, 0x04, 0x00, +- 0xAC, 0x60, 0x1E, 0x78, 0xFF, 0xFF, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xFF, 0xFF, +- 0x80, 0x27, 0xCF, 0x83, 0x1B, 0xFC, 0x01, 0x64, 0x4F, 0xFB, 0xA1, 0xFF, 0x29, 0x41, 0xF9, 0x81, +- 0x52, 0x4A, 0x71, 0x89, 0x2E, 0x44, 0x27, 0xFA, 0x98, 0xF1, 0xFC, 0xA3, 0xD3, 0x80, 0x43, 0x43, +- 0x03, 0x04, 0xAC, 0x60, 0x0A, 0x78, 0xFF, 0xFF, 0x9A, 0xFF, 0x54, 0x63, 0x12, 0x64, 0x40, 0x46, +- 0x8F, 0xFC, 0x18, 0x61, 0xCB, 0xF1, 0x50, 0xFE, 0x6C, 0x40, 0x9E, 0x15, 0x01, 0x60, 0x08, 0xE1, +- 0x80, 0xE1, 0x00, 0x64, 0x33, 0xFB, 0x01, 0x60, 0x18, 0xE1, 0x01, 0x11, 0x0F, 0x00, 0x29, 0x44, +- 0x20, 0xBC, 0x40, 0x49, 0x01, 0x64, 0x33, 0xFB, 0xB6, 0xFF, 0x00, 0xE1, 0x01, 0x60, 0x1A, 0xE1, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x40, 0xFC, 0x11, 0x01, 0x60, 0x18, 0xE1, 0xB5, 0xFF, 0xB6, 0xFF, +- 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0x35, 0xE1, 0xAC, 0xE2, 0xAA, 0x60, +- 0x97, 0x78, 0xFF, 0xFF, 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, +- 0xA2, 0xDB, 0x21, 0x64, 0x3A, 0xDB, 0xD2, 0x01, 0x25, 0x60, 0xF2, 0x64, 0xE5, 0x60, 0x78, 0x41, +- 0xC7, 0x78, 0x97, 0xF1, 0x2A, 0x64, 0x3A, 0xDB, 0x5C, 0x41, 0xC8, 0x01, 0x29, 0x64, 0x3A, 0xDB, +- 0x88, 0x60, 0x85, 0x71, 0x8D, 0xE2, 0xA2, 0xFC, 0x32, 0x40, 0x01, 0x2A, 0xA8, 0x00, 0x01, 0x60, +- 0x1A, 0xE1, 0x23, 0x43, 0xA1, 0xFF, 0xEC, 0x44, 0x2A, 0xFA, 0x40, 0x48, 0xA1, 0xFF, 0x7A, 0xDC, +- 0x7E, 0x36, 0x04, 0xA2, 0xFC, 0x1C, 0x03, 0x1D, 0x00, 0x64, 0x3F, 0xFA, 0x2E, 0x00, 0x03, 0x2B, +- 0x04, 0x00, 0xA1, 0xFF, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x8F, 0xB0, 0x88, 0x3A, 0x03, 0x00, +- 0x70, 0x62, 0xA1, 0xFF, 0x7A, 0xDC, 0x28, 0x40, 0x40, 0x2B, 0x06, 0x00, 0x72, 0x62, 0xA1, 0xFF, +- 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x3F, 0xFC, 0x00, 0xF4, 0x10, 0x62, 0x6E, 0x61, +- 0xA1, 0xFF, 0x05, 0x1D, 0x12, 0x1E, 0x0C, 0x00, 0x00, 0xF4, 0x7C, 0x61, 0x02, 0x62, 0x7A, 0xDC, +- 0x63, 0x40, 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, 0x08, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, +- 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0x6C, 0x44, 0x5A, 0xDA, 0x98, 0xFF, 0xA1, 0xFF, 0x6C, 0x40, +- 0xA1, 0xFF, 0x47, 0xFF, 0x7C, 0x44, 0x33, 0xFB, 0x26, 0x44, 0xFD, 0xB4, 0x84, 0xBC, 0x01, 0x15, +- 0x7F, 0xB4, 0x40, 0x46, 0x6C, 0x40, 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0x6C, 0x45, 0xA1, 0xFF, +- 0x7F, 0x60, 0x7F, 0x7C, 0x6C, 0x44, 0xA0, 0x84, 0x15, 0xA7, 0x15, 0xA4, 0x21, 0x46, 0x26, 0xFA, +- 0x29, 0x40, 0x40, 0x2B, 0x07, 0x00, 0xB6, 0xFF, 0x40, 0x60, 0x00, 0x65, 0xA1, 0xFF, 0x6C, 0x44, +- 0x1A, 0xFA, 0x09, 0x00, 0x65, 0x44, 0x0F, 0xB4, 0x06, 0xA8, 0x80, 0x60, 0x00, 0x65, 0x08, 0x28, +- 0x7C, 0x45, 0x29, 0x44, 0x34, 0x89, 0x27, 0xF0, 0x65, 0x44, 0x64, 0x5E, 0x27, 0xFA, 0x81, 0xE1, +- 0x01, 0x60, 0x18, 0xE1, 0x01, 0x11, 0x0F, 0x00, 0x29, 0x44, 0x20, 0xBC, 0x40, 0x49, 0x01, 0x64, +- 0x33, 0xFB, 0xB6, 0xFF, 0x00, 0xE1, 0x01, 0x60, 0x1A, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x40, +- 0xFC, 0x11, 0x01, 0x60, 0x18, 0xE1, 0x21, 0x46, 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB6, 0xFF, +- 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0x26, 0x43, 0x2A, 0x44, 0x72, 0x45, +- 0x24, 0xFA, 0x94, 0xF3, 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, 0x01, 0x26, 0x64, 0x44, +- 0x94, 0xF9, 0x25, 0xFA, 0x95, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x95, 0xFB, 0x28, 0xFA, 0x96, 0xF3, +- 0x02, 0x04, 0xDC, 0x84, 0x96, 0xFB, 0x29, 0xFA, 0xAA, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, +- 0x12, 0x61, 0x8C, 0x44, 0xCC, 0xF0, 0x2A, 0xFA, 0x40, 0x48, 0x04, 0x26, 0x43, 0x00, 0xA1, 0xFF, +- 0x8C, 0x44, 0x5A, 0xDA, 0x30, 0xFB, 0x6C, 0x44, 0x2C, 0xFA, 0xFF, 0xFF, 0x01, 0x26, 0x26, 0x00, +- 0xD0, 0x80, 0xA1, 0xFF, 0x8C, 0x44, 0x6C, 0x5C, 0x00, 0xE1, 0xF2, 0xFE, 0x2D, 0xFA, 0xCD, 0xF3, +- 0xD4, 0x80, 0xD0, 0x80, 0x2E, 0xF8, 0x24, 0x44, 0x16, 0x0C, 0x32, 0x40, 0x02, 0x2A, 0x07, 0x00, +- 0x28, 0x42, 0x0C, 0xB2, 0x08, 0x3A, 0x03, 0x00, 0x10, 0xBC, 0x40, 0x44, 0x5C, 0x00, 0x04, 0x0A, +- 0xA1, 0xFF, 0xAC, 0x60, 0x13, 0x78, 0xFF, 0xFF, 0x11, 0xBC, 0x40, 0x44, 0x28, 0x45, 0xBF, 0x60, +- 0xFF, 0x64, 0x24, 0x88, 0x50, 0x00, 0x30, 0xBC, 0x40, 0x44, 0x4D, 0x00, 0x20, 0xB9, 0x5C, 0x8E, +- 0xA1, 0xFF, 0x8C, 0x44, 0x2D, 0xFA, 0xDC, 0x9C, 0x6C, 0x44, 0x00, 0xE1, 0xF2, 0xFE, 0x2E, 0xFA, +- 0x08, 0x28, 0x44, 0x4E, 0xDC, 0x84, 0x2E, 0x5C, 0xB0, 0x84, 0xEF, 0xB1, 0x08, 0x24, 0x40, 0xB9, +- 0x41, 0x46, 0x39, 0x00, 0x23, 0x41, 0x13, 0x64, 0x51, 0x90, 0x56, 0x63, 0x03, 0x04, 0xAC, 0x60, +- 0x0A, 0x78, 0xFF, 0xFF, 0x8C, 0x44, 0x04, 0x61, 0x2B, 0xFA, 0x50, 0xFE, 0x80, 0x27, 0x00, 0x64, +- 0x30, 0xFB, 0x8C, 0x44, 0x2C, 0xFA, 0xD0, 0x80, 0x8C, 0x44, 0x2D, 0xFA, 0xD4, 0x80, 0x00, 0x65, +- 0x8C, 0x44, 0xCD, 0xF1, 0x2E, 0xFA, 0xD0, 0x80, 0x28, 0x44, 0x03, 0x0C, 0xA0, 0x2A, 0x0A, 0x00, +- 0x11, 0x00, 0x10, 0x65, 0x60, 0x40, 0xC4, 0x36, 0x04, 0x00, 0xD4, 0x3A, 0x08, 0x00, 0x27, 0x40, +- 0x40, 0x26, 0x30, 0x65, 0x00, 0x64, 0x3F, 0xFA, 0x46, 0x4E, 0x35, 0x84, 0x66, 0x00, 0x40, 0x26, +- 0xF9, 0x01, 0x30, 0x65, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x04, 0x61, 0xF3, 0x01, 0xA1, 0xFF, +- 0xAB, 0x60, 0xE6, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xFE, 0x65, 0x23, 0x43, 0xE8, 0xA3, 0x80, 0x27, +- 0xF6, 0x01, 0x20, 0xE6, 0x08, 0x60, 0x00, 0xEB, 0x28, 0x44, 0x03, 0x2B, 0x05, 0x00, 0x6A, 0x62, +- 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x28, 0x44, 0x8F, 0xB0, 0x88, 0x3A, 0x03, 0x00, 0x70, 0x62, +- 0x7A, 0xDC, 0x28, 0x44, 0x40, 0x2B, 0x0D, 0x00, 0x72, 0x62, 0x7A, 0xDC, 0xA1, 0xFF, 0x6C, 0x5C, +- 0x5A, 0xD8, 0xE4, 0x40, 0x20, 0x2B, 0x03, 0x00, 0x7A, 0xDC, 0x7A, 0xDC, 0xF8, 0xA3, 0x25, 0xFF, +- 0xB0, 0xFF, 0x3F, 0xFC, 0x00, 0xF4, 0x10, 0x62, 0x10, 0x61, 0x57, 0x90, 0x6C, 0x61, 0xA1, 0xFF, +- 0x09, 0x07, 0x02, 0x1D, 0x2A, 0x1E, 0x21, 0x00, 0xCB, 0x83, 0x7A, 0xDC, 0xFE, 0x1C, 0xD9, 0x81, +- 0x24, 0x1E, 0x1B, 0x00, 0xCB, 0x83, 0x0E, 0xA3, 0xA7, 0x84, 0xF2, 0xA3, 0x7A, 0xDC, 0xFE, 0x1C, +- 0x05, 0x1D, 0x01, 0x60, 0x18, 0xE1, 0x7C, 0xA8, 0xD9, 0x81, 0x0A, 0x02, 0x00, 0xF4, 0x02, 0x62, +- 0xA7, 0x84, 0x7A, 0x61, 0x7A, 0xDC, 0xFE, 0x1C, 0xF9, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, 0xF6, 0x03, +- 0xFF, 0xB1, 0x0B, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xA1, 0xFF, 0xFF, 0xFF, 0xB6, 0xFF, +- 0xB7, 0xFF, 0x6C, 0x44, 0x5A, 0xDA, 0xCD, 0x81, 0x64, 0x40, 0x46, 0x45, 0x28, 0x44, 0x40, 0x2B, +- 0x0E, 0x00, 0x64, 0x40, 0x20, 0x2B, 0x0B, 0x00, 0x01, 0xA2, 0x62, 0x44, 0x46, 0x45, 0x21, 0x46, +- 0x00, 0xF4, 0x02, 0x62, 0x9A, 0xFF, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x98, 0xFF, +- 0x00, 0xE6, 0x01, 0xF2, 0x61, 0x45, 0xD4, 0x9E, 0x21, 0x46, 0x16, 0xFA, 0x25, 0x44, 0x06, 0xFA, +- 0xA1, 0xFF, 0x8C, 0x44, 0xA1, 0xFF, 0x47, 0xFF, 0x50, 0x4B, 0x67, 0x50, 0x69, 0xE2, 0x25, 0x46, +- 0x01, 0xF2, 0x61, 0x45, 0xD4, 0x9E, 0x21, 0x46, 0x16, 0xFA, 0x25, 0x45, 0x86, 0xF8, 0xFF, 0xFF, +- 0x6A, 0x44, 0x40, 0x2B, 0x03, 0x15, 0xAF, 0x60, 0x10, 0x78, 0xFF, 0xFF, 0x29, 0x40, 0x10, 0x26, +- 0x04, 0x00, 0x04, 0x74, 0xCD, 0xE2, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x44, 0xB6, 0xFF, 0xB7, 0xFF, +- 0xC4, 0xE2, 0x01, 0x60, 0x18, 0xE1, 0x05, 0x76, 0xAD, 0xE2, 0x41, 0xE1, 0xA1, 0xFF, 0x6C, 0x45, +- 0xA1, 0xFF, 0x65, 0x41, 0x7F, 0x60, 0x7F, 0x7C, 0x6C, 0x44, 0xA0, 0x84, 0x15, 0xA7, 0x15, 0xA4, +- 0x21, 0x46, 0x26, 0xFA, 0x22, 0x46, 0x10, 0xFA, 0x21, 0x46, 0x29, 0x40, 0x40, 0x2B, 0x07, 0x00, +- 0xB6, 0xFF, 0xA1, 0xFF, 0x40, 0x60, 0x00, 0x65, 0x6C, 0x44, 0x1A, 0xFA, 0x09, 0x00, 0x65, 0x44, +- 0x0F, 0xB4, 0x06, 0xA8, 0x80, 0x60, 0x00, 0x65, 0x08, 0x28, 0x7C, 0x45, 0x29, 0x44, 0x34, 0x89, +- 0x27, 0xF0, 0x65, 0x47, 0x1F, 0xB1, 0x34, 0x97, 0x64, 0x5E, 0x07, 0x60, 0xF5, 0xF1, 0x29, 0x40, +- 0x40, 0x2B, 0x04, 0x00, 0x64, 0x40, 0x02, 0x26, 0x10, 0x60, 0x00, 0xBC, 0x27, 0xFA, 0x01, 0x60, +- 0x18, 0xE1, 0x00, 0x64, 0x33, 0xFB, 0xA8, 0xE2, 0x05, 0xE1, 0x28, 0x40, 0x03, 0x26, 0xCE, 0x00, +- 0x31, 0x40, 0x20, 0x2A, 0x03, 0x00, 0x28, 0x40, 0x50, 0x3A, 0xC8, 0x00, 0x24, 0x44, 0x20, 0x2A, +- 0xC5, 0x00, 0x2B, 0x44, 0xAC, 0x80, 0x28, 0x40, 0xB4, 0x3A, 0x03, 0x00, 0x02, 0x03, 0x30, 0xFB, +- 0xBD, 0x00, 0x28, 0x44, 0xBF, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x40, 0x48, 0x2B, 0x50, 0xA1, 0xFF, +- 0xFF, 0xFF, 0x01, 0x60, 0x08, 0xE1, 0x1C, 0xF2, 0xC4, 0xE2, 0x40, 0x45, 0x28, 0x40, 0xC4, 0x36, +- 0x9D, 0x00, 0x29, 0x40, 0x40, 0x2B, 0x49, 0x00, 0x2B, 0x60, 0xBE, 0x63, 0x60, 0x40, 0x0B, 0x36, +- 0x20, 0x00, 0x0F, 0x36, 0x1B, 0x00, 0x0A, 0x36, 0x16, 0x00, 0x0E, 0x36, 0x11, 0x00, 0x09, 0x36, +- 0x0C, 0x00, 0x0D, 0x36, 0x07, 0x00, 0x08, 0x36, 0x02, 0x00, 0xA3, 0xD3, 0x15, 0x00, 0x02, 0xA3, +- 0xA3, 0xD3, 0x12, 0x00, 0x04, 0xA3, 0xA3, 0xD3, 0x0F, 0x00, 0x06, 0xA3, 0xA3, 0xD3, 0x0C, 0x00, +- 0x08, 0xA3, 0xA3, 0xD3, 0x09, 0x00, 0x0A, 0xA3, 0xA3, 0xD3, 0x06, 0x00, 0x0C, 0xA3, 0xA3, 0xD3, +- 0x03, 0x00, 0x0E, 0xA3, 0xA3, 0xD3, 0xFF, 0xFF, 0x25, 0x60, 0x82, 0x63, 0x60, 0x40, 0x0C, 0x36, +- 0x19, 0x00, 0x08, 0x36, 0x15, 0x00, 0x0D, 0x36, 0x11, 0x00, 0x09, 0x36, 0x0D, 0x00, 0x0E, 0x36, +- 0x09, 0x00, 0x0A, 0x36, 0x05, 0x00, 0x0F, 0x36, 0x01, 0x00, 0x3A, 0x00, 0x02, 0xA3, 0x38, 0x00, +- 0x04, 0xA3, 0x36, 0x00, 0x06, 0xA3, 0x34, 0x00, 0x08, 0xA3, 0x32, 0x00, 0x0A, 0xA3, 0x30, 0x00, +- 0x0C, 0xA3, 0x2E, 0x00, 0x0E, 0xA3, 0x2C, 0x00, 0x2B, 0x00, 0x2B, 0x60, 0xCE, 0x63, 0x25, 0x44, +- 0x0A, 0x36, 0x0C, 0x00, 0x14, 0x36, 0x07, 0x00, 0x37, 0x36, 0x02, 0x00, 0xA3, 0xD3, 0x09, 0x00, +- 0x02, 0xA3, 0xA3, 0xD3, 0x06, 0x00, 0x04, 0xA3, 0xA3, 0xD3, 0x03, 0x00, 0x06, 0xA3, 0xA3, 0xD3, +- 0xFF, 0xFF, 0x40, 0x45, 0x0A, 0x36, 0x0D, 0x00, 0x14, 0x36, 0x38, 0x64, 0x37, 0x3A, 0x03, 0x00, +- 0x04, 0x7F, 0x40, 0x45, 0x15, 0x64, 0x6E, 0x3A, 0x09, 0x00, 0x84, 0x7F, 0x40, 0x45, 0x0B, 0x64, +- 0x05, 0x00, 0x29, 0x44, 0x7F, 0x60, 0xFF, 0xB4, 0x40, 0x49, 0x70, 0x64, 0x40, 0x4D, 0x02, 0x00, +- 0x40, 0x45, 0x0A, 0x00, 0x25, 0x60, 0x7A, 0x63, 0x0A, 0x36, 0x06, 0x00, 0x14, 0x36, 0x02, 0xA3, +- 0x37, 0x36, 0x04, 0xA3, 0x6E, 0x36, 0x06, 0xA3, 0x28, 0xA3, 0xA3, 0xD1, 0xD8, 0xA3, 0x15, 0x60, +- 0xD8, 0xF9, 0x39, 0xF1, 0xA3, 0xD1, 0x64, 0x41, 0x64, 0x5E, 0x60, 0x45, 0x64, 0x47, 0x1F, 0xB4, +- 0x54, 0x94, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, +- 0xB4, 0x85, 0x29, 0x44, 0xC0, 0x60, 0x00, 0xB4, 0xB4, 0x84, 0x1F, 0xFA, 0xB5, 0xFF, 0xA1, 0xFF, +- 0xAD, 0xF3, 0xC4, 0xE2, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0xDC, 0x84, 0xE0, 0x94, 0xFF, 0x60, +- 0xCF, 0x65, 0x29, 0x44, 0x24, 0x89, 0xA5, 0x60, 0xD6, 0x78, 0x04, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, +- 0xC4, 0xE2, 0xA1, 0xFF, 0xFF, 0x60, 0xCF, 0x65, 0x29, 0x44, 0x24, 0x89, 0xAD, 0xF3, 0xC4, 0xE2, +- 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0xDC, 0x84, 0xE0, 0x94, 0x26, 0x44, 0x84, 0xBC, 0x24, 0x40, +- 0x0C, 0x22, 0xFD, 0xB4, 0x40, 0x46, 0x23, 0x64, 0x3A, 0xDB, 0xAC, 0x60, 0xAB, 0x78, 0xFF, 0xFF, +- 0x27, 0x40, 0x26, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, +- 0x29, 0x40, 0x10, 0x26, 0x02, 0x00, 0x04, 0x74, 0xCD, 0xE2, 0x01, 0x60, 0x18, 0xE1, 0x01, 0x60, +- 0x18, 0xE1, 0x01, 0x11, 0x0F, 0x00, 0x29, 0x44, 0x20, 0xBC, 0x40, 0x49, 0x01, 0x64, 0x33, 0xFB, +- 0xB6, 0xFF, 0x00, 0xE1, 0x01, 0x60, 0x1A, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x40, 0xFC, 0x11, +- 0x01, 0x60, 0x18, 0xE1, 0xB5, 0xFF, 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, +- 0x09, 0x7D, 0x7C, 0x4B, 0x37, 0xF3, 0x2B, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x28, 0x65, 0x44, +- 0x60, 0x50, 0xA0, 0x4C, 0x20, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0x00, 0x60, 0x2E, 0x7C, 0x74, 0x44, +- 0xC0, 0x94, 0x32, 0x40, 0x02, 0x2A, 0x19, 0x00, 0x28, 0x44, 0xA4, 0x36, 0x03, 0x00, 0x0C, 0xB4, +- 0x04, 0x36, 0x13, 0x00, 0x26, 0x43, 0xFD, 0xB3, 0x04, 0xBB, 0x43, 0x46, 0x01, 0x2A, 0x03, 0x00, +- 0x28, 0x47, 0x40, 0xBF, 0x40, 0x48, 0x0A, 0xBB, 0x0F, 0xFC, 0x50, 0x4B, 0x67, 0x50, 0x00, 0x64, +- 0x30, 0xFB, 0x05, 0xFF, 0xAC, 0x60, 0xAB, 0x78, 0xFF, 0xFF, 0x24, 0x64, 0x3A, 0xDB, 0x28, 0x44, +- 0x04, 0x2A, 0x03, 0x00, 0xA4, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x1D, 0xFF, 0xA8, 0xE2, 0x26, 0x40, +- 0x10, 0x2A, 0x06, 0x00, 0x25, 0x60, 0xF0, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, +- 0xA4, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x03, 0x0A, 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0x01, 0x64, +- 0x4F, 0xFB, 0xE1, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x54, 0x62, 0x22, 0x46, 0xA2, 0xD0, +- 0x16, 0x63, 0x7C, 0x41, 0x44, 0x48, 0x80, 0x36, 0x04, 0x61, 0x28, 0x40, 0x50, 0x36, 0x04, 0x61, +- 0x41, 0x4E, 0x28, 0x44, 0xA4, 0x36, 0x0E, 0x63, 0x0A, 0x60, 0x7C, 0xF1, 0x2D, 0x44, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA2, 0xDB, 0x9A, 0xFF, 0xA1, 0xFF, +- 0x12, 0x74, 0xCD, 0xE2, 0x54, 0x62, 0xA2, 0xD2, 0xFF, 0xFF, 0x6A, 0x40, 0x80, 0x4E, 0x12, 0x74, +- 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, +- 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0xFF, 0xFF, 0x01, 0x1D, +- 0xB2, 0x00, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, +- 0x12, 0x74, 0x28, 0x40, 0x03, 0x2B, 0x06, 0x00, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, +- 0x7A, 0xD4, 0x12, 0x74, 0x70, 0x62, 0x28, 0x44, 0x8F, 0xB0, 0x88, 0x3A, 0x02, 0x00, 0x7A, 0xD4, +- 0x12, 0x74, 0x28, 0x40, 0x40, 0x2B, 0x16, 0x00, 0x72, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD2, +- 0x12, 0x74, 0x80, 0x4C, 0x20, 0x2B, 0x05, 0x00, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, +- 0x12, 0x74, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x10, 0x26, 0x04, 0x00, 0x26, 0x26, 0x4D, 0x00, +- 0x26, 0x27, 0x4B, 0x00, 0x23, 0x43, 0xFF, 0xFF, 0x06, 0x1D, 0x2E, 0x1E, 0x00, 0x00, 0x03, 0xF0, +- 0x04, 0xF4, 0x64, 0x42, 0x3D, 0x00, 0x2E, 0x40, 0x04, 0x2A, 0x27, 0x00, 0xA1, 0xFF, 0x02, 0xFE, +- 0x10, 0x25, 0x42, 0xFE, 0x12, 0x74, 0x72, 0x45, 0x65, 0x4C, 0x94, 0xF3, 0x03, 0x04, 0xE4, 0xE2, +- 0xDC, 0x84, 0x94, 0xFB, 0xA1, 0xFF, 0x12, 0x74, 0x80, 0x4C, 0x12, 0x74, 0x95, 0xF3, 0x02, 0x04, +- 0xDC, 0x84, 0x95, 0xFB, 0x80, 0x4C, 0x12, 0x74, 0x96, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0x96, 0xFB, +- 0x80, 0x4C, 0x12, 0x74, 0x5C, 0x4E, 0xF8, 0xA3, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, 0xFF, 0xB1, +- 0xF8, 0xA1, 0x06, 0xA4, 0x60, 0x42, 0x0A, 0x00, 0x4E, 0x00, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, +- 0xC8, 0x82, 0xFF, 0xB1, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xB1, 0x7A, 0xD4, 0x12, 0x74, +- 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, 0x1B, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, 0xDA, 0x82, +- 0xA2, 0xD2, 0xA1, 0xFF, 0x09, 0x74, 0x60, 0x4D, 0x12, 0x00, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, +- 0x23, 0x43, 0xA1, 0xFF, 0x12, 0x74, 0xA0, 0xD2, 0xFE, 0xA1, 0xCB, 0x83, 0x60, 0x4E, 0xAF, 0x83, +- 0x03, 0x1D, 0x05, 0x03, 0x12, 0x74, 0xEB, 0x01, 0xA1, 0xFF, 0x12, 0x74, 0xDF, 0x01, 0x12, 0x74, +- 0xDA, 0x83, 0x66, 0x44, 0x22, 0x46, 0x0C, 0xFA, 0x22, 0xF2, 0x0B, 0xFC, 0x28, 0x40, 0x40, 0x2B, +- 0x1A, 0x00, 0x10, 0x26, 0x04, 0x00, 0x26, 0x26, 0x0F, 0x00, 0x26, 0x27, 0x0D, 0x00, 0x00, 0xF4, +- 0x02, 0x62, 0xA1, 0xFF, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, +- 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x07, 0x00, 0xA1, 0xFF, 0x12, 0x74, 0x9C, 0x4E, 0x12, 0x74, +- 0x9C, 0x4C, 0x12, 0x74, 0x00, 0x00, 0x88, 0xFF, 0xA1, 0xFF, 0xB1, 0x60, 0x58, 0x4F, 0x00, 0x78, +- 0xFF, 0xFF, 0x01, 0x60, 0x18, 0xE1, 0x78, 0x44, 0x02, 0xA4, 0x35, 0xFB, 0xCC, 0x00, 0x29, 0x44, +- 0xF7, 0xB4, 0x40, 0x49, 0x34, 0x64, 0x3A, 0xDB, 0x44, 0xE1, 0xA5, 0x60, 0xB2, 0x78, 0xFF, 0xFF, +- 0x00, 0x6B, 0xBC, 0xFF, 0x15, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x15, 0xFB, 0x78, 0x5C, 0x07, 0x00, +- 0x78, 0x5C, 0x2F, 0x00, 0x62, 0xFF, 0xFF, 0xFF, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x80, 0x60, +- 0x01, 0xE0, 0xD5, 0x60, 0x84, 0xE7, 0x82, 0xF3, 0x40, 0x60, 0x60, 0x40, 0x01, 0x23, 0x48, 0x60, +- 0x5E, 0x65, 0x80, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x80, 0x60, +- 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x00, 0x60, 0x01, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x64, 0x58, +- 0xFF, 0xFF, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, 0x84, 0xE7, 0x82, 0xF3, 0x7C, 0x45, 0x60, 0x40, +- 0x01, 0x23, 0x02, 0x65, 0x8C, 0x60, 0x48, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, +- 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x7F, 0x6A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x48, 0x60, 0x08, 0x6A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, +- 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x40, 0x60, 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x8C, 0x60, 0x48, 0x6A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, +- 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x64, 0x58, 0xFF, 0xFF, +- 0x12, 0x74, 0x6A, 0x40, 0x87, 0x4F, 0x12, 0x74, 0x87, 0x4C, 0x12, 0x74, 0x29, 0x40, 0x40, 0x2B, +- 0x08, 0x00, 0x0A, 0x64, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0x87, 0x4D, 0x12, 0x74, 0x87, 0x4D, +- 0x09, 0x00, 0x03, 0x64, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0x87, 0x4F, 0x12, 0x74, 0x87, 0x4D, +- 0x12, 0x74, 0x87, 0x4D, 0x7C, 0x44, 0x01, 0x08, 0x01, 0x00, 0x67, 0x44, 0x12, 0x74, 0x87, 0x4C, +- 0x12, 0x74, 0x87, 0x4C, 0x12, 0x74, 0x87, 0x4C, 0x12, 0x74, 0x87, 0x4D, 0x12, 0x74, 0x87, 0x4D, +- 0x12, 0x74, 0x87, 0x4D, 0x12, 0x74, 0x04, 0x21, 0x04, 0x00, 0xFF, 0x2A, 0x01, 0x00, 0x04, 0x00, +- 0x03, 0x00, 0xFF, 0x2A, 0x0D, 0x00, 0x0C, 0x00, 0xBC, 0xFF, 0x61, 0xFF, 0x78, 0x5C, 0x57, 0x01, +- 0x78, 0x5C, 0x7F, 0x01, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, +- 0x6A, 0x44, 0x2F, 0x58, 0xFF, 0xFF, 0x04, 0x74, 0xC4, 0xE2, 0x04, 0xE1, 0x29, 0x40, 0x40, 0x2B, +- 0x05, 0x00, 0xA1, 0xFF, 0xFF, 0xFF, 0xBC, 0xFF, 0x14, 0x74, 0x01, 0x00, 0x04, 0x74, 0xC4, 0xE2, +- 0x04, 0xE1, 0xBC, 0xFF, 0xB5, 0xFF, 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, +- 0x09, 0x7D, 0x7C, 0x4B, 0x29, 0x40, 0x40, 0x27, 0x04, 0x00, 0xC2, 0x60, 0x58, 0x4F, 0xC8, 0x78, +- 0xFF, 0xFF, 0xA1, 0xFF, 0x29, 0x40, 0x10, 0x26, 0x6D, 0x00, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, +- 0x84, 0xE7, 0x82, 0xF3, 0x40, 0x60, 0x60, 0x40, 0x01, 0x23, 0x48, 0x60, 0x5E, 0x65, 0x80, 0x60, +- 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x80, 0x60, 0x00, 0x6A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x01, 0x6A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, +- 0x84, 0xE7, 0x82, 0xF3, 0x7C, 0x45, 0x60, 0x40, 0x01, 0x23, 0x02, 0x65, 0x8C, 0x60, 0x48, 0x6A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x00, 0x60, 0x7F, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x48, 0x60, 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x40, 0x60, 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x8C, 0x60, 0x48, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x95, 0x60, 0x84, 0xE7, 0x01, 0x60, 0x08, 0xE1, 0xFF, 0xFF, 0xC4, 0xE2, 0x29, 0x40, 0x40, 0x2B, +- 0x04, 0x00, 0xC2, 0x60, 0x58, 0x4F, 0xC8, 0x78, 0xFF, 0xFF, 0xC2, 0x60, 0x58, 0x4F, 0xD0, 0x78, +- 0xFF, 0xFF, 0xA1, 0xFF, 0xAD, 0xF3, 0xC4, 0xE2, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0xDC, 0x84, +- 0xE0, 0x94, 0x35, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x08, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x43, 0xFF, 0x01, 0x60, 0x00, 0xE1, 0x28, 0xF3, 0x47, 0xFF, 0x60, 0x40, 0x07, 0x37, 0x66, 0x00, +- 0x05, 0x3B, 0x04, 0x00, 0xFF, 0x0A, 0x80, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x18, 0x60, 0x07, 0xF1, +- 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x64, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, +- 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x29, 0xF5, 0x2A, 0xF3, 0x47, 0xFF, +- 0x3F, 0xF0, 0x01, 0x1B, 0x01, 0x64, 0x60, 0x56, 0xAD, 0xE2, 0xB5, 0xFF, 0x6C, 0x40, 0x40, 0xE1, +- 0xA1, 0xFF, 0x00, 0xF4, 0x6E, 0x61, 0x12, 0x62, 0x64, 0x43, 0x01, 0xE1, 0x03, 0x64, 0xE2, 0xD0, +- 0xC9, 0x81, 0x64, 0x4C, 0xCC, 0x84, 0xDA, 0x82, 0xFA, 0x02, 0x01, 0x60, 0x00, 0x6B, 0x9A, 0xFF, +- 0xCA, 0x82, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xFF, 0x7A, 0xD0, 0xA1, 0xFF, 0x64, 0x4C, +- 0xFC, 0x1C, 0xF8, 0x1D, 0x00, 0xB9, 0x06, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, 0x5A, 0xD2, +- 0xA1, 0xFF, 0x60, 0x4D, 0x3F, 0x40, 0x02, 0x2B, 0x10, 0x00, 0x28, 0xF3, 0xA5, 0x60, 0xC4, 0x65, +- 0x60, 0x40, 0x0E, 0x3B, 0x0A, 0x00, 0xD2, 0xF3, 0xFF, 0xFF, 0x10, 0xBC, 0xD2, 0xFB, 0xAD, 0x4F, +- 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x85, 0x4C, 0xFE, 0x01, 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, +- 0xD2, 0xFB, 0xA1, 0xFF, 0x87, 0x4E, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x67, 0x4C, +- 0xFF, 0xFF, 0xBC, 0xFF, 0x00, 0xE1, 0xD5, 0xFE, 0xA1, 0xFF, 0xFF, 0xFF, 0x00, 0x64, 0x40, 0x46, +- 0x60, 0x41, 0xB5, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0x29, 0xF5, 0x3F, 0xF0, 0x24, 0xF2, 0x44, 0x43, +- 0x40, 0x4D, 0x00, 0xF4, 0xF3, 0x60, 0xA0, 0x65, 0x10, 0x62, 0x5A, 0xD2, 0xD9, 0x81, 0xD4, 0x80, +- 0xFF, 0xFF, 0xFB, 0x02, 0x61, 0x45, 0x2D, 0x44, 0xD4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, +- 0xFD, 0xA5, 0x48, 0x60, 0x00, 0x64, 0xC4, 0x9D, 0x0D, 0x60, 0x00, 0x6B, 0x2D, 0x44, 0xC0, 0x83, +- 0xBB, 0xFF, 0x29, 0xF5, 0x01, 0xE1, 0x00, 0xF4, 0x6C, 0x61, 0x10, 0x62, 0x05, 0x00, 0x00, 0xF4, +- 0x01, 0xF2, 0xFF, 0xFF, 0x60, 0x41, 0x04, 0x62, 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x1A, 0x00, +- 0x26, 0x44, 0x01, 0x26, 0x0C, 0x00, 0x2D, 0x44, 0xC8, 0x84, 0x40, 0x4D, 0x02, 0x03, 0x6C, 0x45, +- 0xF3, 0x01, 0x03, 0x15, 0x01, 0x64, 0x05, 0xFA, 0x15, 0x00, 0x6C, 0x45, 0xED, 0x01, 0x23, 0x44, +- 0xC8, 0x84, 0x40, 0x43, 0x02, 0x03, 0x6C, 0x45, 0xE7, 0x01, 0x00, 0x64, 0x01, 0x15, 0x01, 0x64, +- 0x6C, 0x45, 0x05, 0xFB, 0xE2, 0xD2, 0xDA, 0x82, 0xC9, 0x81, 0x60, 0x4C, 0xDD, 0x1C, 0xD7, 0x03, +- 0xBC, 0xFF, 0xDA, 0x01, 0x00, 0xE1, 0xD5, 0xFE, 0xA1, 0xFF, 0xFF, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, +- 0x67, 0x4C, 0x43, 0xFF, 0xD2, 0xF3, 0xFF, 0xFF, 0x10, 0xBC, 0xD2, 0xFB, 0xAD, 0x4F, 0x02, 0xBC, +- 0x00, 0x7F, 0xA0, 0x5D, 0x01, 0xE1, 0x01, 0x60, 0x69, 0x6B, 0xA5, 0x60, 0xC4, 0x64, 0x60, 0x4C, +- 0xBB, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, 0xFC, 0x01, +- 0x29, 0xF3, 0x2A, 0xF1, 0x07, 0xB5, 0x04, 0xE1, 0x65, 0x41, 0x64, 0x54, 0xCD, 0xE2, 0x95, 0x81, +- 0xA1, 0x5D, 0xA1, 0xFF, 0xFF, 0xFF, 0xF9, 0x01, 0x10, 0x61, 0x7F, 0x60, 0xC0, 0x64, 0xA0, 0x80, +- 0x7F, 0x67, 0x02, 0x63, 0x25, 0x02, 0x98, 0xFE, 0x19, 0x05, 0x0F, 0x60, 0x7F, 0xF5, 0x0E, 0xF2, +- 0x15, 0x18, 0x02, 0x18, 0x09, 0xF4, 0xFB, 0x01, 0x23, 0x44, 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, +- 0x66, 0x44, 0x11, 0xFB, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, +- 0x28, 0xB9, 0x10, 0x7E, 0x00, 0x7F, 0x0E, 0xFA, 0x00, 0x67, 0x0A, 0x00, 0x20, 0x44, 0xDC, 0x85, +- 0x0F, 0xB4, 0xF7, 0xA0, 0x7F, 0x67, 0x07, 0x63, 0x03, 0x05, 0x45, 0x40, 0x00, 0x67, 0xD8, 0xFE, +- 0xFF, 0x27, 0x05, 0xFD, 0x0A, 0x7E, 0x04, 0xFB, 0x61, 0x55, 0x48, 0x00, 0x28, 0xFB, 0x01, 0xF3, +- 0x29, 0xFB, 0x44, 0x46, 0x40, 0x45, 0x10, 0x61, 0x7E, 0x60, 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, +- 0x02, 0x63, 0x30, 0x02, 0xB5, 0x60, 0x58, 0x4F, 0x4B, 0x78, 0xFF, 0xFF, 0x7F, 0x67, 0x03, 0x63, +- 0x29, 0x02, 0x26, 0x40, 0x01, 0x2B, 0x23, 0x00, 0x98, 0xFE, 0x18, 0x05, 0x0F, 0x60, 0x7F, 0xF5, +- 0x0E, 0xF2, 0x14, 0x18, 0x02, 0x18, 0x09, 0xF4, 0xFB, 0x01, 0x23, 0x44, 0x00, 0xA8, 0x08, 0x7E, +- 0x0A, 0x02, 0x66, 0x44, 0x11, 0xFB, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, +- 0xA2, 0xDB, 0x08, 0xB9, 0x10, 0x7E, 0x00, 0x7F, 0x0E, 0xFA, 0x09, 0x00, 0x20, 0x44, 0xDC, 0x85, +- 0x0F, 0xB4, 0xF7, 0xA0, 0x7F, 0x67, 0x07, 0x63, 0x05, 0x05, 0x45, 0x40, 0xD8, 0xFE, 0x00, 0x67, +- 0xD0, 0xFE, 0xD9, 0xFE, 0xFF, 0x27, 0x05, 0xFD, 0x0B, 0x7E, 0x04, 0xFB, 0x0A, 0x60, 0x7E, 0xF3, +- 0xFF, 0xFF, 0x20, 0xB0, 0x80, 0xBC, 0x08, 0x28, 0xA2, 0xDB, 0x61, 0x55, 0x66, 0x00, 0x04, 0xB5, +- 0x82, 0xB5, 0x25, 0x02, 0x04, 0x03, 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, 0xA3, 0xD3, 0x99, 0xFE, +- 0x04, 0x04, 0x02, 0xBC, 0xFE, 0xB4, 0xA3, 0xDB, 0x59, 0x00, 0xBC, 0xF3, 0x20, 0x40, 0x80, 0x26, +- 0x55, 0x00, 0xA3, 0xD3, 0xFF, 0xA0, 0xF8, 0xB4, 0x02, 0x02, 0xA3, 0xDB, 0x1C, 0x00, 0x04, 0xBC, +- 0xBF, 0xB4, 0xA3, 0xDB, 0x08, 0xB0, 0x01, 0x64, 0x08, 0x24, 0x02, 0x64, 0x28, 0xFB, 0x20, 0x44, +- 0x80, 0xBC, 0x40, 0x40, 0xD0, 0xFE, 0x42, 0x00, 0xBF, 0xB4, 0xA3, 0xDB, 0x3F, 0x00, 0x40, 0xB0, +- 0xFF, 0xFF, 0xFA, 0x02, 0xF8, 0xB4, 0xA3, 0xDB, 0x08, 0xB5, 0x07, 0x7C, 0x01, 0x02, 0xBC, 0xF9, +- 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, 0x14, 0x60, 0xFC, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB5, +- 0x07, 0xB5, 0x08, 0x28, 0xC4, 0x02, 0x99, 0xFE, 0x29, 0x05, 0x20, 0x44, 0x80, 0x26, 0x26, 0x00, +- 0x20, 0x2A, 0x03, 0x00, 0xDF, 0xB4, 0x40, 0x40, 0x6A, 0x00, 0x40, 0x2A, 0x1F, 0x00, 0xBF, 0xB4, +- 0x40, 0x40, 0x09, 0x00, 0xA8, 0xFF, 0x20, 0x44, 0x99, 0xFE, 0x02, 0x05, 0x80, 0x2A, 0x03, 0x00, +- 0x40, 0xBC, 0x40, 0x40, 0x13, 0x00, 0x00, 0xF1, 0x80, 0xBC, 0x40, 0x40, 0x64, 0x44, 0xE0, 0x84, +- 0xE8, 0x84, 0x0A, 0x36, 0x29, 0x01, 0x0B, 0x36, 0x59, 0x01, 0x28, 0xFB, 0x01, 0xF1, 0x29, 0xF9, +- 0x02, 0xF1, 0x2A, 0xF9, 0x03, 0xF1, 0x2B, 0xF9, 0xD0, 0xFE, 0xAE, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x82, 0x3E, 0x75, 0x44, 0x02, 0xB0, 0x01, 0xB0, 0x4A, 0x02, 0xDC, 0x02, 0x04, 0xB0, 0x08, 0xB0, +- 0x0B, 0x02, 0x20, 0x02, 0x40, 0x26, 0xA7, 0xFF, 0x8C, 0xFF, 0x75, 0x40, 0x80, 0x2B, 0x01, 0x00, +- 0xAB, 0xFF, 0x75, 0x44, 0x8D, 0xFF, 0xEA, 0x01, 0x0A, 0xF3, 0xAA, 0xFF, 0x60, 0x40, 0x20, 0x2B, +- 0x02, 0x00, 0x38, 0xFF, 0x0D, 0x00, 0x01, 0x26, 0x0C, 0x00, 0xC0, 0x60, 0x00, 0x7C, 0xA0, 0x84, +- 0x80, 0x3B, 0x02, 0x00, 0xC0, 0x67, 0x03, 0x00, 0x40, 0x3B, 0x02, 0x00, 0x00, 0x67, 0x0A, 0xFB, +- 0xD5, 0x01, 0xD4, 0x01, 0x0B, 0xF1, 0xAB, 0xFF, 0x64, 0x44, 0xFF, 0x27, 0x1F, 0x00, 0x20, 0x26, +- 0x03, 0x00, 0x02, 0x60, 0x00, 0x75, 0x1A, 0x00, 0x19, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, 0x04, 0x60, +- 0x00, 0x75, 0x0A, 0x64, 0xCC, 0x84, 0x19, 0xFB, 0x01, 0x60, 0x00, 0x75, 0x64, 0x40, 0x03, 0x22, +- 0x0D, 0x00, 0x20, 0x44, 0x80, 0x2A, 0x03, 0x00, 0x20, 0xBC, 0x40, 0x40, 0x07, 0x00, 0xD9, 0xFE, +- 0x81, 0x60, 0x0B, 0x64, 0x28, 0xFB, 0x2C, 0x44, 0x29, 0xFB, 0xD0, 0xFE, 0xAF, 0x01, 0xA9, 0xFF, +- 0x77, 0x44, 0x60, 0x57, 0x40, 0x4A, 0x01, 0x2A, 0x20, 0x00, 0x24, 0x44, 0xAC, 0x86, 0x08, 0xF2, +- 0x1C, 0x03, 0x1F, 0x60, 0x04, 0x65, 0xD4, 0x80, 0x0E, 0xF2, 0x02, 0x03, 0xA5, 0xD5, 0x04, 0x00, +- 0x01, 0xBC, 0x0E, 0xFA, 0x09, 0xF4, 0xD1, 0xFE, 0x46, 0x44, 0x0F, 0x18, 0x3F, 0xF2, 0x48, 0x65, +- 0xC4, 0x84, 0x13, 0xFB, 0x66, 0x44, 0x10, 0xFB, 0x66, 0x47, 0x20, 0xBF, 0x3B, 0x42, 0x04, 0xA2, +- 0xA2, 0xDB, 0x0E, 0xF2, 0x41, 0x75, 0x10, 0xBC, 0x0E, 0xFA, 0x2A, 0x44, 0x08, 0x2A, 0x17, 0x00, +- 0x23, 0x44, 0x00, 0xA8, 0x5C, 0x43, 0x13, 0x03, 0x0F, 0x60, 0x7F, 0xF5, 0x01, 0x00, 0x09, 0xF4, +- 0x0E, 0xF2, 0x0D, 0x18, 0x08, 0xB0, 0x18, 0xAC, 0xFA, 0x03, 0x0E, 0xFA, 0x66, 0x43, 0x11, 0xFD, +- 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x28, 0x75, 0x2A, 0x44, +- 0x06, 0x22, 0x2D, 0x00, 0x22, 0x44, 0x00, 0xA8, 0x60, 0x46, 0x0E, 0xF2, 0x28, 0x03, 0x10, 0xB0, +- 0x01, 0xBC, 0x03, 0x02, 0x00, 0x64, 0x40, 0x42, 0x22, 0x00, 0x0E, 0xFA, 0xD1, 0xFE, 0x1E, 0x60, +- 0xF8, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x80, 0x00, 0x46, 0x42, 0x19, 0x02, 0x22, 0x47, 0x40, 0xBF, +- 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x23, 0xF2, 0x66, 0x43, 0x00, 0xA8, 0x0E, 0xF2, 0x08, 0x02, +- 0x60, 0x40, 0x02, 0x2A, 0xE4, 0x01, 0x12, 0xFD, 0x10, 0x64, 0x0E, 0xFA, 0x02, 0x75, 0x07, 0x00, +- 0x60, 0x40, 0x04, 0x2A, 0xDC, 0x01, 0x12, 0xFD, 0x10, 0x64, 0x0E, 0xFA, 0x04, 0x75, 0x2A, 0x44, +- 0x80, 0x2A, 0x19, 0x00, 0x21, 0x44, 0xAC, 0x86, 0x0E, 0xF2, 0x15, 0x03, 0x01, 0xBC, 0x0E, 0xFA, +- 0xD1, 0xFE, 0x1F, 0x60, 0x10, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x56, 0x00, 0x46, 0x41, 0x0B, 0x02, +- 0x21, 0x47, 0x10, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x0E, 0xF2, 0x66, 0x43, 0x08, 0xFD, +- 0x10, 0xBC, 0x0E, 0xFA, 0x80, 0x75, 0x2A, 0x44, 0x10, 0xB0, 0x20, 0x44, 0x15, 0x03, 0x7F, 0xB4, +- 0x40, 0x40, 0x14, 0x60, 0xFC, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB0, 0x80, 0xB0, 0x09, 0x03, +- 0x08, 0x03, 0x40, 0xBC, 0x7F, 0xB4, 0x04, 0xB0, 0xA3, 0xDB, 0x03, 0x03, 0x20, 0x44, 0x80, 0xBC, +- 0x40, 0x40, 0xB3, 0x60, 0x8B, 0x78, 0xFF, 0xFF, 0xB3, 0x60, 0xBE, 0x78, 0xFF, 0xFF, 0xE8, 0xFE, +- 0x14, 0x05, 0xEA, 0xFE, 0x24, 0x05, 0xE9, 0xFE, 0x1C, 0x05, 0xE7, 0xFE, 0x09, 0x05, 0x47, 0xFF, +- 0x20, 0x44, 0x0F, 0x22, 0x03, 0x00, 0xCC, 0x84, 0x40, 0x40, 0x0F, 0x22, 0xB8, 0xFE, 0xEC, 0x01, +- 0x23, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0xE8, 0x02, 0x6F, 0x01, 0x24, 0x41, 0x00, 0xB9, 0x1F, 0x60, +- 0x04, 0x65, 0x45, 0x47, 0xE1, 0x02, 0x58, 0x4F, 0x0F, 0x00, 0xDE, 0x02, 0x5C, 0x4A, 0x46, 0x44, +- 0x4D, 0x01, 0x22, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0x08, 0x24, 0x81, 0x01, 0xD5, 0x01, 0x21, 0x41, +- 0x00, 0xB9, 0x5C, 0x4A, 0xA6, 0x03, 0xD0, 0x01, 0x27, 0xD3, 0x03, 0x00, 0x10, 0xB0, 0x09, 0xF2, +- 0x04, 0x03, 0xAC, 0x86, 0x0E, 0xF2, 0xFA, 0x02, 0x08, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0E, 0xF3, +- 0x0F, 0x60, 0xFE, 0x65, 0x0C, 0xF3, 0x24, 0x86, 0x24, 0x46, 0x60, 0x40, 0xFB, 0x3B, 0x07, 0x00, +- 0x80, 0x26, 0x02, 0x00, 0x23, 0x46, 0x03, 0x4C, 0x46, 0x61, 0x3A, 0x65, 0x0C, 0x00, 0x2E, 0xF3, +- 0x40, 0x45, 0xF8, 0x2B, 0x02, 0x00, 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, 0x44, 0x00, 0x07, 0x02, +- 0x58, 0x4F, 0x50, 0x00, 0x04, 0x05, 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, 0x09, 0x00, 0x26, 0x47, +- 0x00, 0xBF, 0x0E, 0xFB, 0x2E, 0xF5, 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, 0x00, 0x72, 0x7E, 0x71, +- 0xAC, 0xFF, 0xB3, 0x60, 0xBE, 0x78, 0xFF, 0xFF, 0x8E, 0xFF, 0x0F, 0xF3, 0x0F, 0x60, 0xFE, 0x65, +- 0x24, 0x86, 0x0D, 0xF3, 0x24, 0x46, 0x60, 0x40, 0xFB, 0x3B, 0x07, 0x00, 0x80, 0x26, 0x02, 0x00, +- 0x23, 0x46, 0x03, 0x4C, 0x46, 0x61, 0x3A, 0x65, 0x0C, 0x00, 0x2E, 0xF3, 0x40, 0x45, 0xF8, 0x2B, +- 0x02, 0x00, 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, 0x16, 0x00, 0x07, 0x02, 0x58, 0x4F, 0x22, 0x00, +- 0x04, 0x05, 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, 0x0F, 0xFB, +- 0x2E, 0xF5, 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, 0x00, 0x72, 0x7E, 0x71, 0x8D, 0xFF, 0xAD, 0xFF, +- 0xB3, 0x60, 0xBE, 0x78, 0xFF, 0xFF, 0x25, 0x44, 0x89, 0xF1, 0x8A, 0xF1, 0xD0, 0x80, 0xD0, 0x80, +- 0x07, 0x04, 0x01, 0x06, 0x05, 0x00, 0x25, 0x46, 0x01, 0xF0, 0x03, 0x67, 0xA0, 0x85, 0x94, 0x80, +- 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x46, 0x26, 0x41, 0x46, 0x63, 0x01, 0xF2, 0xFF, 0xFF, 0xFF, 0xB5, +- 0xD5, 0x81, 0x00, 0xF2, 0x05, 0x04, 0x04, 0x63, 0x60, 0x46, 0xF7, 0x1B, 0x42, 0xFE, 0x0D, 0x00, +- 0x61, 0x44, 0xC5, 0x81, 0x63, 0x45, 0xC5, 0x81, 0x9C, 0x84, 0xDC, 0x84, 0x01, 0xF2, 0xF0, 0x85, +- 0xF0, 0x80, 0x65, 0x44, 0xF8, 0x85, 0xFF, 0xFF, 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, +- 0x0F, 0x60, 0x8B, 0xF3, 0xFF, 0xFF, 0xAC, 0x86, 0x0E, 0xF2, 0x07, 0x03, 0x00, 0xA8, 0x09, 0xF2, +- 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, 0x08, 0xFE, 0x17, 0x00, 0x8B, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, +- 0x00, 0xB4, 0x12, 0x06, 0x09, 0x60, 0x08, 0x61, 0x41, 0x4A, 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, +- 0xB5, 0x60, 0x58, 0x4E, 0xC1, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x06, 0x03, 0x2A, 0x43, 0xB5, 0x60, +- 0x58, 0x4E, 0xE2, 0x78, 0xFF, 0xFF, 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0x41, 0x4A, +- 0x42, 0xA1, 0x03, 0x00, 0x41, 0x4A, 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, 0xB5, 0x60, 0x58, 0x4E, +- 0xC1, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x2A, 0x43, 0xB5, 0x60, 0x58, 0x4E, 0xE2, 0x78, 0xFF, 0xFF, +- 0x08, 0xFE, 0x0C, 0x00, 0x0F, 0x60, 0x8B, 0xF3, 0xFF, 0xFF, 0xAC, 0x86, 0x0E, 0xF2, 0x06, 0x03, +- 0x00, 0xA8, 0x09, 0xF2, 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, +- 0xFF, 0xFF, 0x8C, 0xF3, 0x7C, 0x63, 0x00, 0xBE, 0x40, 0x45, 0x1A, 0x03, 0x00, 0x65, 0x65, 0x44, +- 0xDC, 0x85, 0x84, 0xA1, 0x00, 0xF2, 0x06, 0x06, 0x01, 0xFC, 0x00, 0xA8, 0x60, 0x46, 0xF7, 0x02, +- 0x40, 0x45, 0x0E, 0x00, 0x8B, 0xF3, 0x00, 0x63, 0xD4, 0x84, 0x8B, 0xFB, 0x80, 0x60, 0x7C, 0x64, +- 0x01, 0xFA, 0x00, 0xF0, 0x00, 0xFC, 0xD3, 0x80, 0x8C, 0xF9, 0x02, 0x02, 0x8D, 0xF9, 0x08, 0xFE, +- 0x2E, 0x58, 0xFF, 0xFF, 0x66, 0x44, 0x25, 0x46, 0x05, 0xFA, 0x06, 0xFA, 0x01, 0xF0, 0x03, 0x67, +- 0x02, 0xFC, 0xB0, 0x84, 0x3A, 0x7E, 0x01, 0xFA, 0x12, 0x64, 0x03, 0xFA, 0x00, 0xF0, 0x04, 0xF8, +- 0x00, 0x64, 0x0C, 0x61, 0x10, 0x63, 0x59, 0xDA, 0xFE, 0x1F, 0x2E, 0x58, 0xFF, 0xFF, 0x27, 0x43, +- 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, 0x16, 0x03, 0x00, 0x61, 0x01, 0x00, 0xEC, 0x63, 0x61, 0x46, +- 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, 0xA2, 0xDA, 0xBE, 0xD2, 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, +- 0x25, 0x44, 0x61, 0x46, 0xA3, 0xDA, 0x04, 0x00, 0x0A, 0xFA, 0x60, 0x46, 0x25, 0x44, 0x09, 0xFA, +- 0x61, 0x46, 0xBE, 0xDA, 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x44, 0x00, 0xA8, 0x07, 0x4B, 0x0C, 0x03, +- 0x58, 0x4F, 0x33, 0x00, 0x0B, 0x47, 0x1F, 0x60, 0x0A, 0x65, 0x27, 0x44, 0xD4, 0x80, 0x00, 0x64, +- 0x01, 0x02, 0x0F, 0xFA, 0x58, 0x4F, 0xD3, 0x01, 0x70, 0x00, 0x25, 0x43, 0xE3, 0x84, 0x7C, 0x41, +- 0x02, 0x04, 0xE8, 0x81, 0xEC, 0x63, 0x61, 0x46, 0xA3, 0xD2, 0x00, 0x7C, 0x40, 0x45, 0xBF, 0xD8, +- 0xA3, 0xD8, 0xBE, 0xD8, 0x27, 0x42, 0x5A, 0xD3, 0x25, 0x5C, 0x60, 0x41, 0x02, 0x1B, 0x27, 0xD9, +- 0x05, 0x00, 0x25, 0x46, 0x0A, 0xFA, 0x61, 0x46, 0x25, 0x44, 0x09, 0xFA, 0x25, 0x44, 0x27, 0x43, +- 0x00, 0x61, 0x60, 0x46, 0x09, 0xF2, 0x08, 0xFC, 0x00, 0xA8, 0xDD, 0x81, 0xFA, 0x02, 0xBF, 0xD1, +- 0x66, 0x44, 0xBE, 0xDB, 0xC1, 0x84, 0xBF, 0xDB, 0x48, 0x00, 0x25, 0x46, 0xEC, 0x63, 0x08, 0xF2, +- 0x89, 0xF2, 0x1E, 0x18, 0x40, 0x47, 0xE0, 0x84, 0xE8, 0x85, 0x02, 0x05, 0xE8, 0x83, 0x00, 0x65, +- 0x65, 0x46, 0xBF, 0xD2, 0x61, 0x5C, 0xCC, 0x84, 0xA2, 0xDA, 0x25, 0x46, 0x0A, 0xF2, 0x00, 0xB9, +- 0x65, 0x46, 0x08, 0x24, 0xBE, 0xDA, 0x02, 0x1B, 0xA3, 0xD8, 0x02, 0x00, 0x60, 0x46, 0x89, 0xFA, +- 0x00, 0xB9, 0x61, 0x46, 0x08, 0x28, 0x0A, 0xFA, 0x25, 0x46, 0x89, 0xFC, 0x8A, 0xFC, 0x88, 0xFC, +- 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x61, 0x28, 0x65, 0x25, 0x43, 0x8D, 0xF3, 0xAF, 0x83, 0x00, 0xBE, +- 0x18, 0x03, 0x02, 0x03, 0x00, 0xFC, 0x01, 0x00, 0x8C, 0xFD, 0x63, 0x46, 0x65, 0x44, 0xCC, 0x85, +- 0x00, 0xF2, 0x07, 0x02, 0x8D, 0xF5, 0x00, 0x64, 0x00, 0xFA, 0xDE, 0x60, 0xAF, 0x64, 0x09, 0xFB, +- 0x08, 0x00, 0x66, 0x43, 0x00, 0xBE, 0xDD, 0x81, 0xF1, 0x02, 0x8B, 0xF1, 0x8D, 0xFD, 0xC1, 0x84, +- 0x8B, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x45, 0x29, 0x43, 0xFC, 0xA3, 0x66, 0x44, +- 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x00, 0x64, 0xBD, 0xDB, 0x03, 0x61, 0x0E, 0x65, 0x1F, 0x60, +- 0x1E, 0x63, 0x43, 0x49, 0xA3, 0xD3, 0x06, 0xA3, 0x00, 0xA8, 0xCD, 0x81, 0x04, 0x02, 0xF9, 0x02, +- 0xB3, 0x60, 0xBE, 0x78, 0xFF, 0xFF, 0x01, 0x26, 0xE6, 0x01, 0xD4, 0x80, 0x60, 0x45, 0xE3, 0x05, +- 0xF6, 0xA3, 0xBD, 0xD1, 0xBD, 0xD1, 0x44, 0x47, 0x44, 0x48, 0x44, 0x45, 0x1F, 0x60, 0x60, 0x64, +- 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0xFE, 0x8C, 0xF5, 0x8B, 0xF3, 0x0D, 0x18, 0xCC, 0x84, +- 0x8B, 0xFB, 0x80, 0x60, 0x7C, 0x64, 0x01, 0xFA, 0x00, 0x64, 0x00, 0xF0, 0x00, 0xFA, 0xD0, 0x80, +- 0x8C, 0xF9, 0x02, 0x02, 0x8D, 0xF9, 0x08, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x1E, 0x60, 0xCE, 0x63, +- 0x0D, 0x65, 0x00, 0x61, 0x41, 0x48, 0xA3, 0xD3, 0x06, 0xA3, 0xAC, 0x86, 0x00, 0x61, 0x09, 0x03, +- 0x00, 0xF2, 0x09, 0xF0, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x64, 0x44, 0xAC, 0x86, +- 0xF6, 0x01, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x65, 0x44, 0x28, 0x45, 0x45, 0x88, 0xCC, 0x85, +- 0x5A, 0x87, 0xE9, 0x02, 0x00, 0x64, 0x27, 0xDA, 0x5A, 0xDA, 0x5A, 0x87, 0x87, 0xF3, 0x86, 0xF1, +- 0x02, 0xA4, 0x60, 0x46, 0x60, 0x45, 0x00, 0x61, 0x22, 0xF2, 0xFF, 0xFF, 0xAC, 0x86, 0x00, 0xF2, +- 0x04, 0x03, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x65, 0x44, 0x02, 0xA5, 0x65, 0x46, +- 0x64, 0x44, 0xCC, 0x9C, 0xFF, 0xFF, 0xF0, 0x02, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x5A, 0x87, +- 0x28, 0x45, 0x45, 0x88, 0x87, 0xF3, 0x86, 0xF1, 0x02, 0xA4, 0x60, 0x46, 0x60, 0x45, 0x00, 0x61, +- 0x76, 0xF2, 0xFF, 0xFF, 0xAC, 0x86, 0x00, 0xF2, 0x09, 0x03, 0x00, 0xF2, 0x09, 0xF0, 0xAC, 0x86, +- 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x64, 0x44, 0xAC, 0x86, 0xF6, 0x01, 0x65, 0x44, 0x02, 0xA5, +- 0x65, 0x46, 0x64, 0x44, 0xCC, 0x9C, 0x61, 0x44, 0xEB, 0x02, 0x25, 0x46, 0x27, 0xDA, 0x5A, 0x87, +- 0x28, 0x45, 0x45, 0x88, 0x06, 0x60, 0x40, 0x65, 0x8C, 0xF3, 0x01, 0x61, 0xAC, 0x86, 0x00, 0xF2, +- 0x03, 0x03, 0xD5, 0x80, 0xDD, 0x81, 0xFA, 0x04, 0xCD, 0x84, 0x25, 0x46, 0x27, 0xDA, 0x28, 0x45, +- 0xC4, 0x84, 0x5A, 0xDA, 0xDA, 0x81, 0x8B, 0xF1, 0x59, 0xD8, 0x1E, 0x60, 0xCC, 0x64, 0x18, 0x63, +- 0xA0, 0xD1, 0x06, 0xA4, 0x59, 0xD8, 0xFC, 0x1F, 0x00, 0x64, 0x59, 0xDA, 0x59, 0xDA, 0x01, 0x60, +- 0x1A, 0x64, 0x0A, 0x63, 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, 0x7D, 0xF1, 0x59, 0xD8, 0x45, 0x01, +- 0x07, 0x4B, 0xB6, 0x60, 0x58, 0x4F, 0x4D, 0x78, 0xFF, 0xFF, 0x0B, 0x47, 0x58, 0x4F, 0x21, 0x00, +- 0x3C, 0x01, 0x07, 0x4B, 0xB6, 0x60, 0x58, 0x4F, 0x4D, 0x78, 0xFF, 0xFF, 0x0B, 0x47, 0x27, 0x44, +- 0x00, 0xBE, 0x08, 0xF0, 0x15, 0x03, 0x64, 0x42, 0x4A, 0xD3, 0x09, 0xF2, 0xDC, 0x83, 0xA2, 0xDD, +- 0x25, 0x43, 0x09, 0xFC, 0x63, 0x46, 0x27, 0x43, 0x0A, 0xFC, 0x09, 0xFA, 0x08, 0xF8, 0x00, 0xA8, +- 0x66, 0x43, 0x03, 0x02, 0x64, 0x44, 0x58, 0xDD, 0x03, 0x00, 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, +- 0x1C, 0x01, 0x27, 0x43, 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, 0x16, 0x03, 0x00, 0x61, 0x01, 0x00, +- 0xEC, 0x63, 0x61, 0x46, 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, 0xA2, 0xDA, 0xA3, 0xD2, 0x25, 0x46, +- 0x88, 0xF8, 0x04, 0x1B, 0x25, 0x44, 0x61, 0x46, 0xBE, 0xDA, 0x04, 0x00, 0x09, 0xFA, 0x60, 0x46, +- 0x25, 0x44, 0x0A, 0xFA, 0x61, 0x46, 0xA3, 0xDA, 0x2F, 0x58, 0xFF, 0xFF, 0xA0, 0xFE, 0x07, 0x05, +- 0xA3, 0xFE, 0x07, 0x05, 0xA1, 0xFE, 0x46, 0x05, 0x60, 0x64, 0x3B, 0xDB, 0x0F, 0x00, 0x20, 0x58, +- 0xFF, 0xFF, 0xFA, 0x01, 0x0A, 0x60, 0x80, 0xF3, 0xFF, 0xFF, 0xFB, 0xB4, 0xA2, 0xDB, 0xA0, 0x4C, +- 0x59, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0xA0, 0x4C, 0x7D, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x83, 0x3E, 0x40, 0x60, 0x0B, 0x65, 0x2B, 0x44, 0x00, 0x63, 0xE8, 0x80, 0xF8, 0x84, 0x02, 0x24, +- 0x94, 0x84, 0xF3, 0x83, 0xCD, 0x81, 0xFF, 0xFF, 0xF8, 0x02, 0xDF, 0x83, 0x2F, 0x58, 0x40, 0x4B, +- 0x00, 0x62, 0x01, 0x64, 0xD4, 0x80, 0xE0, 0x84, 0x1A, 0x03, 0xD4, 0x80, 0xE0, 0x84, 0x15, 0x03, +- 0x61, 0x44, 0x11, 0x61, 0xE0, 0x84, 0xCD, 0x81, 0xFD, 0x04, 0x01, 0x00, 0xE0, 0x84, 0xF2, 0x82, +- 0xFF, 0xFF, 0x02, 0x24, 0xC6, 0x82, 0x02, 0x28, 0xD6, 0x82, 0xE2, 0x80, 0xCD, 0x81, 0x02, 0x28, +- 0x01, 0xBC, 0xF4, 0x02, 0x01, 0x2A, 0xC6, 0x82, 0x03, 0x00, 0xE9, 0x81, 0xF2, 0x82, 0x61, 0x44, +- 0x2D, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x3B, 0xDB, 0x0C, 0x60, 0x6E, 0xF3, 0x5A, 0xD1, 0x60, 0x40, +- 0x04, 0x3A, 0x2C, 0x00, 0x00, 0x64, 0x4A, 0xDB, 0x1E, 0x60, 0xCE, 0x63, 0xA3, 0xD3, 0x46, 0x43, +- 0xAC, 0x86, 0x3C, 0x45, 0x22, 0x03, 0xD4, 0x80, 0x07, 0xF2, 0x02, 0x02, 0x09, 0xF2, 0xF8, 0x01, +- 0xD0, 0x80, 0x09, 0xF2, 0xF5, 0x02, 0x60, 0x43, 0x80, 0x67, 0xB0, 0x81, 0x61, 0x44, 0x0F, 0x60, +- 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x09, 0x60, +- 0x08, 0x65, 0x0E, 0xF2, 0x02, 0xF2, 0x60, 0x40, 0xF0, 0x37, 0x05, 0x00, 0x8F, 0xF3, 0xD4, 0x80, +- 0xCC, 0x84, 0x01, 0x02, 0x8F, 0xFB, 0x63, 0x44, 0xDB, 0x01, 0x23, 0x46, 0x3C, 0x44, 0xAC, 0x80, +- 0xFF, 0xFF, 0x94, 0x02, 0x69, 0xF3, 0x6A, 0xF3, 0x02, 0xA8, 0x02, 0xA8, 0x08, 0x02, 0x00, 0x64, +- 0x6B, 0xFB, 0x69, 0xFB, 0x6A, 0xFB, 0x00, 0x64, 0x6C, 0xFB, 0xCA, 0xFE, 0x92, 0x00, 0x03, 0x02, +- 0x00, 0x64, 0x6A, 0xFB, 0xCA, 0xFE, 0x01, 0x64, 0x3B, 0xDB, 0x0F, 0x60, 0x6A, 0xF3, 0xFF, 0xFF, +- 0x00, 0xA8, 0x60, 0x46, 0x35, 0x03, 0x2C, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x86, 0x00, +- 0x2E, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, +- 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x2E, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x2D, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, +- 0x61, 0x46, 0x2C, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, +- 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x5F, 0x02, 0x66, 0x45, +- 0x63, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x80, 0xB0, 0x09, 0xF2, 0x58, 0x03, 0xAC, 0x86, 0xCA, 0x01, +- 0x6A, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x4C, 0x02, 0x0F, 0x60, 0x73, 0xF3, 0xFF, 0xFF, +- 0x00, 0xA8, 0x60, 0x46, 0x0F, 0x03, 0x76, 0xF1, 0x07, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, 0x09, 0xF2, +- 0x03, 0x02, 0xAC, 0x86, 0x07, 0xF2, 0xFA, 0x02, 0x03, 0x02, 0x00, 0x64, 0x76, 0xFB, 0xED, 0x01, +- 0x46, 0x5C, 0x3C, 0x00, 0x0F, 0x60, 0x76, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x01, 0x03, +- 0x35, 0x02, 0x6B, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x13, 0x02, 0x0F, 0x60, 0x6D, 0xF3, +- 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x0B, 0x03, 0x2A, 0xF0, 0x20, 0x67, 0x09, 0xF2, 0xB0, 0x83, +- 0x00, 0xA8, 0x00, 0x64, 0x02, 0x03, 0x2A, 0xFC, 0x01, 0x00, 0x6B, 0xFB, 0x1F, 0x00, 0x00, 0x64, +- 0x6B, 0xFB, 0x0F, 0x60, 0x67, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x12, 0x03, 0x2A, 0xF0, +- 0x08, 0x67, 0xA0, 0x80, 0xFF, 0xFF, 0x12, 0x03, 0x76, 0xF1, 0x07, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, +- 0x09, 0xF2, 0x03, 0x02, 0xAC, 0x86, 0x07, 0xF2, 0xFA, 0x02, 0x08, 0x02, 0x00, 0x64, 0x76, 0xFB, +- 0xE8, 0x01, 0x00, 0x64, 0x76, 0xFB, 0xB7, 0x60, 0xA2, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0xFC, 0xFB, +- 0x46, 0x5C, 0x16, 0x60, 0x2B, 0xF3, 0x0D, 0xF2, 0x60, 0x5C, 0x64, 0x5F, 0x0D, 0xFA, 0x07, 0xF0, +- 0x2A, 0xF2, 0xFF, 0xFF, 0x76, 0xF9, 0x60, 0x40, 0x08, 0x2B, 0x05, 0x00, 0x00, 0x64, 0x48, 0xFB, +- 0xBA, 0x60, 0x03, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x02, 0x23, 0xF0, +- 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xBF, 0x60, 0x16, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x00, 0x63, +- 0x40, 0x47, 0x50, 0x36, 0x01, 0x00, 0x01, 0x63, 0x48, 0xFD, 0x4A, 0xF3, 0x35, 0xFA, 0x10, 0xA4, +- 0x4A, 0xFB, 0x00, 0x64, 0x15, 0xFA, 0x16, 0xFA, 0x0F, 0xFA, 0x07, 0xF0, 0x87, 0xF3, 0xFF, 0xFF, +- 0xD0, 0x80, 0xFF, 0xFF, 0x05, 0x03, 0x66, 0x43, 0x64, 0x46, 0x11, 0xF2, 0xBA, 0xFB, 0x63, 0x46, +- 0x03, 0xF2, 0x00, 0xF4, 0x01, 0xF2, 0xFC, 0xA5, 0x00, 0x7F, 0xD4, 0x84, 0x27, 0x45, 0x3C, 0x46, +- 0x1A, 0xFA, 0x22, 0x63, 0x7B, 0x60, 0xFF, 0x64, 0xA4, 0x84, 0x03, 0x2B, 0x1C, 0x63, 0x2A, 0xFA, +- 0x8F, 0xB0, 0x88, 0x36, 0x02, 0xA3, 0x60, 0x40, 0xA4, 0x36, 0x14, 0x63, 0x43, 0x4C, 0x18, 0xFC, +- 0x00, 0x7C, 0x22, 0xF8, 0x64, 0x41, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x3A, 0xF2, 0x63, 0x46, +- 0xFF, 0xB4, 0x22, 0xFA, 0x60, 0x40, 0x00, 0x36, 0x92, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x0C, 0xB0, +- 0x08, 0x3A, 0x8D, 0x00, 0x60, 0x40, 0x40, 0x26, 0x8A, 0x00, 0x03, 0xF2, 0x00, 0xF4, 0xA0, 0xD2, +- 0xAA, 0x60, 0xAA, 0x65, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, 0x0A, 0x02, 0xD0, 0x80, 0x00, 0x64, +- 0x5A, 0xD0, 0x06, 0x02, 0xD0, 0x80, 0xF8, 0x7F, 0xD0, 0x80, 0x01, 0x03, 0x01, 0x02, 0x01, 0x61, +- 0x62, 0x43, 0x46, 0x43, 0x3C, 0x46, 0x07, 0xF4, 0x3A, 0xF2, 0xFF, 0xFF, 0xA3, 0x46, 0x60, 0x40, +- 0x22, 0x26, 0x49, 0x00, 0x60, 0x45, 0x63, 0x42, 0x5A, 0xD0, 0xCD, 0x81, 0x3C, 0x46, 0x18, 0x02, +- 0x64, 0x44, 0x88, 0x3A, 0x15, 0x00, 0x8E, 0x37, 0x00, 0x00, 0x65, 0x44, 0x01, 0x26, 0x5F, 0x00, +- 0x04, 0x26, 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, 0x31, 0x00, 0xA3, 0x46, 0x3B, 0xF2, 0xFF, 0xFF, +- 0x60, 0x40, 0x80, 0x27, 0x3E, 0x00, 0xA3, 0x46, 0x00, 0x7C, 0x22, 0xF8, 0xA3, 0x46, 0x4F, 0x00, +- 0xA3, 0x46, 0x65, 0x44, 0x01, 0x26, 0x0B, 0x00, 0x04, 0x26, 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, +- 0x1D, 0x00, 0x3B, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x27, 0x2B, 0x00, 0x17, 0x00, 0x87, 0xF3, +- 0xFF, 0xFF, 0x60, 0x46, 0x3A, 0xF2, 0x66, 0x43, 0xFF, 0xB4, 0x3C, 0x46, 0x22, 0xF0, 0x60, 0x47, +- 0xB0, 0x84, 0x22, 0xFA, 0x63, 0x46, 0x3B, 0xF0, 0x60, 0x40, 0x04, 0x27, 0x03, 0x00, 0x10, 0x27, +- 0x01, 0x00, 0x04, 0x00, 0x64, 0x40, 0x80, 0x27, 0x14, 0x00, 0x00, 0x00, 0x3C, 0x46, 0x02, 0x65, +- 0xBE, 0x60, 0xB6, 0x78, 0xFF, 0xFF, 0xCD, 0x81, 0x63, 0x42, 0x5A, 0xD0, 0x3C, 0x46, 0x09, 0x02, +- 0x64, 0x44, 0x88, 0x3A, 0x06, 0x00, 0x77, 0x37, 0x1A, 0x00, 0x78, 0x37, 0x18, 0x00, 0x8E, 0x37, +- 0x16, 0x00, 0x3C, 0x46, 0x22, 0xF0, 0x80, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0xFF, 0xFF, 0x3F, 0xF2, +- 0x3E, 0xF0, 0x08, 0xA4, 0x60, 0x41, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x03, 0x00, +- 0x04, 0x26, 0x03, 0x00, 0x04, 0x00, 0x04, 0x2B, 0x02, 0x00, 0x61, 0x44, 0x3F, 0xFA, 0x3C, 0x46, +- 0x2C, 0xF2, 0x27, 0x40, 0x01, 0x27, 0x32, 0xF2, 0xB4, 0xF1, 0x60, 0x40, 0x01, 0x26, 0x47, 0x00, +- 0x09, 0x60, 0x00, 0x64, 0xD0, 0x80, 0x3F, 0xF2, 0x09, 0x06, 0x2C, 0x45, 0xC4, 0x84, 0xD0, 0x80, +- 0x40, 0x4A, 0x34, 0x06, 0x60, 0x43, 0x64, 0x44, 0x54, 0x88, 0x17, 0x00, 0x60, 0x45, 0x13, 0x60, +- 0x4B, 0xF3, 0xBB, 0xF3, 0x00, 0xBC, 0x60, 0x47, 0xEC, 0xA0, 0x28, 0x03, 0x27, 0x07, 0x2C, 0x44, +- 0xC4, 0x81, 0x02, 0x60, 0x1C, 0x65, 0x45, 0x4A, 0xD5, 0x80, 0x2C, 0x45, 0x1F, 0x06, 0x27, 0x40, +- 0x04, 0x27, 0x25, 0x00, 0x2A, 0x43, 0xD7, 0x85, 0x45, 0x48, 0xB5, 0xF1, 0x0F, 0xF2, 0xD3, 0x80, +- 0x01, 0x65, 0x01, 0x07, 0x00, 0x65, 0xB4, 0x84, 0x0F, 0xFA, 0x00, 0x63, 0x3F, 0xF2, 0x28, 0x45, +- 0x60, 0x41, 0xD4, 0x84, 0xDF, 0x83, 0xFC, 0x07, 0x14, 0xFC, 0x17, 0xFA, 0x04, 0x60, 0x00, 0x64, +- 0x27, 0x45, 0xB4, 0x84, 0x2A, 0xFA, 0x28, 0x43, 0x16, 0xFC, 0x0D, 0x00, 0x3F, 0xF2, 0x2C, 0x45, +- 0xB5, 0xF1, 0xC4, 0x81, 0xD1, 0x80, 0x0F, 0xF2, 0x01, 0x06, 0x01, 0xBC, 0x0F, 0xFA, 0x3F, 0xF2, +- 0x17, 0xFA, 0x01, 0x64, 0x14, 0xFA, 0x0F, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2A, 0x6F, 0x00, +- 0x64, 0xF1, 0x15, 0x60, 0xDD, 0xF3, 0x64, 0x40, 0x01, 0x27, 0x03, 0x00, 0x60, 0x40, 0x02, 0x26, +- 0x14, 0x00, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x12, 0xF0, 0x15, 0x60, 0xDE, 0xF3, 0x63, 0x46, +- 0x64, 0x40, 0x10, 0x2A, 0x20, 0x00, 0x60, 0x40, 0x02, 0x26, 0x07, 0x00, 0x01, 0x26, 0x08, 0x00, +- 0x04, 0x26, 0x09, 0x00, 0x06, 0x61, 0x6E, 0x63, 0x08, 0x00, 0x02, 0x61, 0x14, 0x63, 0x05, 0x00, +- 0x00, 0x61, 0x0A, 0x63, 0x02, 0x00, 0x04, 0x61, 0x37, 0x63, 0x00, 0x64, 0x25, 0x60, 0xA2, 0x65, +- 0x45, 0xD1, 0xD5, 0x81, 0x15, 0x60, 0xDA, 0xF9, 0x25, 0x60, 0x7A, 0x65, 0x45, 0xD1, 0x1C, 0xFC, +- 0xB0, 0x84, 0x1E, 0xFA, 0x3C, 0x00, 0x60, 0x40, 0x10, 0x2A, 0x04, 0x00, 0x08, 0x61, 0x1E, 0x60, +- 0x0B, 0x63, 0x27, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x0A, 0x61, 0x16, 0x60, 0x0F, 0x63, 0x21, 0x00, +- 0x40, 0x2A, 0x04, 0x00, 0x0C, 0x61, 0x12, 0x60, 0x0A, 0x63, 0x1B, 0x00, 0x80, 0x2A, 0x04, 0x00, +- 0x0E, 0x61, 0x0E, 0x60, 0x0E, 0x63, 0x15, 0x00, 0x01, 0x2B, 0x04, 0x00, 0x10, 0x61, 0x0E, 0x60, +- 0x09, 0x63, 0x0F, 0x00, 0x02, 0x2B, 0x04, 0x00, 0x12, 0x61, 0x0A, 0x60, 0x0D, 0x63, 0x09, 0x00, +- 0x04, 0x2B, 0x04, 0x00, 0x14, 0x61, 0x0A, 0x60, 0x08, 0x63, 0x03, 0x00, 0x16, 0x61, 0x0A, 0x60, +- 0x0C, 0x63, 0x1E, 0xF0, 0x40, 0x67, 0x25, 0x60, 0xA2, 0x65, 0x45, 0xD1, 0xD5, 0x81, 0x15, 0x60, +- 0xDA, 0xF9, 0x25, 0x60, 0x7A, 0x65, 0x45, 0xD1, 0x1C, 0xFC, 0xB0, 0x84, 0x1E, 0xFA, 0xAA, 0xF2, +- 0x15, 0x60, 0xC2, 0xF3, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x44, 0x44, 0x61, 0x40, 0x08, 0x26, +- 0x02, 0x00, 0x61, 0x40, 0x80, 0x36, 0x12, 0xF2, 0x63, 0x46, 0x2C, 0x60, 0x26, 0x61, 0x00, 0x7F, +- 0x60, 0x45, 0x45, 0xD3, 0xFF, 0xFF, 0x60, 0x45, 0x00, 0x7F, 0x4B, 0xFB, 0x65, 0x44, 0x00, 0x7E, +- 0xBB, 0xFB, 0x62, 0xF1, 0x60, 0x43, 0x60, 0x47, 0xD0, 0x80, 0xC0, 0x65, 0x01, 0x06, 0x64, 0x44, +- 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x36, 0x15, 0x64, 0x6E, 0x36, 0x0B, 0x64, +- 0x44, 0x86, 0x2A, 0xF2, 0x07, 0xF0, 0x60, 0x40, 0xB0, 0x3A, 0x03, 0x00, 0x40, 0x3B, 0x01, 0x00, +- 0x12, 0x00, 0x0C, 0xB4, 0x08, 0x3A, 0x44, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, +- 0x3F, 0x00, 0x17, 0xF2, 0x22, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x22, 0x22, 0x04, 0x00, 0x00, 0xA8, +- 0x01, 0xA8, 0x36, 0x03, 0x35, 0x03, 0x3C, 0x46, 0x2A, 0xF0, 0x40, 0x67, 0xB0, 0x84, 0xA2, 0xDA, +- 0x60, 0x45, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x43, 0x60, 0x40, 0x01, 0x26, 0x05, 0x00, 0x04, 0x26, +- 0x1D, 0x00, 0x10, 0x26, 0x10, 0x00, 0x04, 0x00, 0x04, 0x27, 0x18, 0x00, 0x10, 0x27, 0x0B, 0x00, +- 0x65, 0x44, 0x2A, 0x61, 0x60, 0x40, 0x03, 0x2B, 0x24, 0x61, 0x8F, 0xB0, 0x88, 0x36, 0x02, 0xA1, +- 0x41, 0x4C, 0x98, 0xFA, 0x15, 0x00, 0x65, 0x44, 0x32, 0x61, 0x60, 0x40, 0x03, 0x2B, 0x2C, 0x61, +- 0x8F, 0xB0, 0x88, 0x36, 0x02, 0xA1, 0x41, 0x4C, 0x98, 0xFA, 0x0A, 0x00, 0x65, 0x44, 0x2E, 0x61, +- 0x60, 0x40, 0x03, 0x2B, 0x28, 0x61, 0x8F, 0xB0, 0x88, 0x36, 0x02, 0xA1, 0x41, 0x4C, 0x98, 0xFA, +- 0xBB, 0x60, 0xFB, 0x78, 0xFF, 0xFF, 0x66, 0x45, 0xAA, 0xF2, 0x15, 0x60, 0xC2, 0xF3, 0x24, 0x46, +- 0x61, 0x40, 0x08, 0x26, 0x02, 0x00, 0x61, 0x40, 0x80, 0x36, 0x12, 0xF2, 0x65, 0x46, 0x60, 0x40, +- 0x10, 0x26, 0x34, 0x00, 0x2C, 0x45, 0x17, 0xF2, 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x81, 0x64, 0x45, 0x16, 0xA1, 0xB7, 0x60, 0x58, 0x4D, 0xC0, 0x78, 0xFF, 0xFF, 0x64, 0xF1, +- 0x01, 0xA4, 0xE0, 0x84, 0xE0, 0x84, 0x64, 0x40, 0x01, 0x2B, 0x06, 0xA4, 0x1B, 0xFA, 0xBB, 0xF3, +- 0x25, 0x60, 0x82, 0x65, 0x60, 0x40, 0x0B, 0x37, 0x00, 0x63, 0x0F, 0x37, 0x02, 0x63, 0x0A, 0x37, +- 0x04, 0x63, 0x0E, 0x37, 0x06, 0x63, 0x09, 0x37, 0x08, 0x63, 0x0D, 0x37, 0x0A, 0x63, 0x08, 0x37, +- 0x0C, 0x63, 0x0C, 0x37, 0x0E, 0x63, 0x28, 0xA3, 0x47, 0xD1, 0xD8, 0xA3, 0xD7, 0x83, 0x15, 0x60, +- 0xD9, 0xF9, 0x47, 0xD1, 0x40, 0x67, 0xB0, 0x84, 0x1F, 0xFA, 0x56, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, +- 0x60, 0x40, 0x80, 0x36, 0x17, 0x00, 0x50, 0x36, 0x15, 0x00, 0x10, 0x36, 0x13, 0x00, 0x30, 0x36, +- 0x11, 0x00, 0xA0, 0x36, 0x0F, 0x00, 0xB0, 0x36, 0x0D, 0x00, 0xC0, 0x36, 0x0B, 0x00, 0xBB, 0xF3, +- 0xFF, 0xFF, 0x60, 0x40, 0x0A, 0x37, 0x06, 0x00, 0x15, 0x60, 0xDD, 0xF3, 0x80, 0x60, 0x00, 0x61, +- 0x60, 0x40, 0x04, 0x26, 0x00, 0x61, 0xBB, 0xF3, 0x25, 0x60, 0x7A, 0x65, 0x60, 0x40, 0x0A, 0x37, +- 0x00, 0x63, 0x14, 0x37, 0x02, 0x63, 0x37, 0x37, 0x04, 0x63, 0x6E, 0x37, 0x06, 0x63, 0x28, 0xA3, +- 0x47, 0xD1, 0xD8, 0xA3, 0xD7, 0x83, 0x15, 0x60, 0xD9, 0xF9, 0x47, 0xD1, 0xFF, 0xFF, 0xB1, 0x84, +- 0x1F, 0xFA, 0xBB, 0xF1, 0x2C, 0x45, 0x64, 0x43, 0x17, 0xF2, 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x81, 0x63, 0x40, 0x37, 0x37, 0xE1, 0x81, 0x64, 0x45, 0xB7, 0x60, 0x58, 0x4D, +- 0xC0, 0x78, 0xFF, 0xFF, 0xAE, 0x82, 0xFC, 0xA2, 0x0A, 0x03, 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, +- 0x60, 0x41, 0x04, 0x0D, 0x63, 0x44, 0x80, 0x7E, 0xBB, 0xFB, 0x61, 0x44, 0xDC, 0x84, 0x2B, 0xF0, +- 0x1B, 0xFA, 0x64, 0x44, 0x80, 0x27, 0x47, 0x00, 0x07, 0xF0, 0x66, 0x45, 0x64, 0x46, 0x12, 0xF2, +- 0x65, 0x46, 0x60, 0x40, 0x10, 0x2A, 0x2E, 0x00, 0x16, 0xF2, 0x0F, 0xF0, 0xAC, 0x84, 0x2C, 0x45, +- 0x29, 0x03, 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x63, 0x40, 0x37, 0x37, +- 0xE1, 0x81, 0x64, 0x45, 0x0F, 0xF0, 0xB7, 0x60, 0x58, 0x4D, 0xC0, 0x78, 0xFF, 0xFF, 0xAE, 0x82, +- 0xFC, 0xA2, 0x0A, 0x03, 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, 0x04, 0x0D, 0x80, 0x67, +- 0xB0, 0x84, 0x0F, 0xFA, 0x61, 0x44, 0xDC, 0x84, 0x1D, 0xFA, 0xDE, 0x65, 0xC4, 0x85, 0x26, 0x41, +- 0xE1, 0x81, 0xC5, 0x84, 0x2B, 0xFA, 0x1B, 0xF0, 0xDE, 0x64, 0xC0, 0x85, 0x26, 0x44, 0xE0, 0x84, +- 0xC4, 0x84, 0x10, 0xFA, 0x26, 0x44, 0x2C, 0xF0, 0x0A, 0xA4, 0x66, 0x45, 0x24, 0x46, 0x92, 0xF2, +- 0x65, 0x46, 0x9F, 0xF0, 0x61, 0x40, 0x10, 0x2A, 0x03, 0x00, 0x65, 0x40, 0x80, 0x27, 0xA0, 0xA4, +- 0x64, 0x40, 0x01, 0x26, 0x00, 0x64, 0x11, 0xFA, 0xBB, 0xF3, 0x13, 0xFA, 0x7C, 0x44, 0x1D, 0xFA, +- 0xFF, 0xFF, 0x0D, 0xF2, 0x3E, 0xF0, 0x60, 0x47, 0xFF, 0xB4, 0x64, 0x41, 0x01, 0xB1, 0x01, 0x63, +- 0x17, 0x02, 0x60, 0x41, 0xFF, 0x22, 0x04, 0x00, 0xB7, 0x60, 0x58, 0x4F, 0xB1, 0x78, 0xFF, 0xFF, +- 0x07, 0x60, 0xF7, 0xFD, 0x16, 0x60, 0x2B, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x01, 0x63, 0x61, 0x40, +- 0xFF, 0x22, 0x04, 0x00, 0xB7, 0x60, 0x58, 0x4F, 0xB1, 0x78, 0xFF, 0xFF, 0x07, 0x60, 0xF8, 0xFD, +- 0xBD, 0x60, 0x7A, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, 0x03, 0x00, +- 0xBD, 0x60, 0x75, 0x78, 0xFF, 0xFF, 0x22, 0xF2, 0x46, 0x43, 0x60, 0x40, 0x22, 0x26, 0x09, 0x00, +- 0x01, 0x26, 0x0A, 0x00, 0x04, 0x26, 0x4B, 0x00, 0x10, 0x26, 0x10, 0x00, 0xBD, 0x60, 0x75, 0x78, +- 0xFF, 0xFF, 0xBC, 0x60, 0xF0, 0x78, 0xFF, 0xFF, 0x04, 0x27, 0x3D, 0x00, 0x10, 0x27, 0x03, 0x00, +- 0xBD, 0x60, 0x75, 0x78, 0xFF, 0xFF, 0x87, 0xF3, 0x3C, 0xF1, 0x02, 0x00, 0x07, 0xF2, 0x00, 0x7C, +- 0x40, 0x43, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x27, 0x21, 0x00, 0xA3, 0x46, 0x4B, 0xF2, +- 0xFF, 0xFF, 0xDC, 0x84, 0x4B, 0xFA, 0x4A, 0xF2, 0x08, 0x04, 0xDC, 0x84, 0x4A, 0xFA, 0x49, 0xF2, +- 0x04, 0x04, 0xDC, 0x84, 0x49, 0xFA, 0x01, 0x04, 0xFF, 0xFF, 0x87, 0xF3, 0x66, 0x5C, 0xD0, 0x80, +- 0x00, 0x7C, 0x01, 0x02, 0x3C, 0xF1, 0x4B, 0xF0, 0x64, 0x47, 0x20, 0xBF, 0xA3, 0x46, 0x3A, 0xF8, +- 0x3B, 0xFA, 0xA3, 0x46, 0x4A, 0xF2, 0x49, 0xF0, 0xA3, 0x46, 0x3C, 0xFA, 0x3D, 0xF8, 0x0F, 0x60, +- 0xA0, 0x64, 0xA3, 0x46, 0x76, 0x61, 0x0E, 0x63, 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, 0xA3, 0x46, +- 0xBD, 0x60, 0x75, 0x78, 0xFF, 0xFF, 0x87, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x02, 0x00, 0x07, 0xF4, +- 0xFF, 0xFF, 0xA3, 0x46, 0x2A, 0xF2, 0xA3, 0x46, 0x60, 0x40, 0x08, 0x27, 0x48, 0x00, 0x87, 0xF3, +- 0x66, 0x5C, 0xD0, 0x80, 0x3B, 0xF0, 0x08, 0x03, 0x64, 0x40, 0x10, 0x2A, 0x12, 0x00, 0xFF, 0x60, +- 0xEF, 0x64, 0xA0, 0x84, 0x3B, 0xFA, 0x24, 0x00, 0x3D, 0xF3, 0x01, 0x61, 0x60, 0x43, 0xCF, 0x83, +- 0xE1, 0x81, 0xFD, 0x0D, 0xE9, 0x81, 0xA1, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0x91, 0x84, 0x3B, 0xFA, +- 0x17, 0x00, 0x4B, 0xF2, 0xFF, 0xFF, 0x10, 0xA0, 0xFF, 0xFF, 0x02, 0x04, 0xFF, 0x60, 0xFF, 0x64, +- 0xDC, 0x84, 0x4B, 0xFA, 0x4A, 0xF2, 0x16, 0x04, 0xDC, 0x84, 0x4A, 0xFA, 0x49, 0xF2, 0x08, 0x04, +- 0xDC, 0x84, 0x49, 0xFA, 0x05, 0x04, 0x3B, 0xF2, 0xFF, 0xFF, 0xE0, 0x84, 0xE8, 0x84, 0x3B, 0xFA, +- 0x0C, 0x60, 0xFE, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC7, 0x60, 0xCF, 0x78, +- 0xFF, 0xFF, 0x84, 0xFF, 0x06, 0x60, 0x17, 0xE1, 0x77, 0x40, 0x8B, 0xFF, 0x02, 0x60, 0x00, 0x75, +- 0xC9, 0x60, 0x58, 0x4F, 0x67, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x06, 0x60, 0x80, 0xFB, 0x0C, 0x60, +- 0xFE, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC8, 0x60, 0x46, 0x78, 0xFF, 0xFF, +- 0x84, 0xFF, 0x00, 0x7C, 0x06, 0x60, 0x80, 0xF3, 0xA2, 0xD9, 0x60, 0x40, 0x01, 0x2A, 0x04, 0x00, +- 0xC9, 0x60, 0x58, 0x4F, 0xAF, 0x78, 0xFF, 0xFF, 0x3C, 0x46, 0x07, 0xF4, 0x87, 0xF3, 0x66, 0x5C, +- 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, 0x3C, 0x46, 0x22, 0xF2, 0x63, 0x46, 0x60, 0x40, +- 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x4B, 0xF0, 0x64, 0x41, 0x64, 0x47, 0xFF, 0xB4, 0x60, 0x5F, +- 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, 0xA3, 0x46, 0x3A, 0xFA, 0x64, 0x44, 0x20, 0x7F, +- 0x34, 0x94, 0x3B, 0xFA, 0xA3, 0x46, 0x4A, 0xF2, 0x49, 0xF0, 0xA3, 0x46, 0x3C, 0xFA, 0x3D, 0xF8, +- 0x80, 0x60, 0x10, 0xE0, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, +- 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0xBD, 0x60, 0x75, 0x78, 0xFF, 0xFF, +- 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x27, 0x31, 0x00, 0x2A, 0xF2, 0x00, 0x60, 0x7C, 0x62, +- 0x60, 0x40, 0x40, 0x2B, 0x24, 0x00, 0xA2, 0xD3, 0x00, 0x61, 0x60, 0xFE, 0xA0, 0xD3, 0x5E, 0xD1, +- 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, 0xC0, 0x2B, 0x04, 0x00, 0x80, 0x2A, +- 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, 0x60, 0x47, 0xDC, 0x87, 0x01, 0x61, +- 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, 0x5A, 0xD1, 0xFF, 0xFF, 0xC1, 0x84, +- 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, 0xA2, 0xDB, 0x20, 0xFE, 0x00, 0x60, +- 0x3E, 0xF3, 0xFF, 0xFF, 0xA0, 0xD3, 0x5A, 0xD1, 0x3A, 0xFA, 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, +- 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, +- 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x40, 0xF3, 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, +- 0x64, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, +- 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, +- 0xE7, 0x7F, 0xA0, 0x5A, 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, +- 0xA0, 0x5A, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, +- 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, +- 0xED, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, +- 0xA0, 0x5A, 0x08, 0x60, 0x00, 0xEA, 0x65, 0x44, 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, +- 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x02, 0x64, 0x3B, 0xDB, 0xBA, 0x60, +- 0xF3, 0x78, 0xFF, 0xFF, 0xBF, 0x60, 0xBB, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0xFC, 0xFB, 0x07, 0xF0, +- 0x00, 0x64, 0xD0, 0x80, 0x87, 0xF3, 0x0E, 0x03, 0xD0, 0x80, 0xFF, 0xFF, 0x0B, 0x03, 0x47, 0xF1, +- 0x07, 0xF0, 0x64, 0x40, 0x02, 0x26, 0x01, 0x00, 0x08, 0x00, 0x03, 0x12, 0xBE, 0x60, 0x46, 0x78, +- 0xFF, 0xFF, 0xFC, 0x0A, 0xBE, 0x60, 0xA6, 0x78, 0xFF, 0xFF, 0x87, 0xF0, 0x87, 0xF3, 0x10, 0xF0, +- 0xD4, 0x80, 0xFF, 0xFF, 0x3D, 0x03, 0x66, 0x43, 0x65, 0x46, 0xFF, 0x67, 0x20, 0x85, 0x64, 0x5F, +- 0x40, 0x44, 0x15, 0xF0, 0x25, 0x44, 0xD0, 0x84, 0x03, 0xA4, 0x03, 0x0E, 0xE8, 0x84, 0xE8, 0x84, +- 0x04, 0x00, 0xFA, 0xA4, 0xE8, 0x84, 0xE8, 0x87, 0xC0, 0xBF, 0xC0, 0x84, 0x15, 0xFA, 0x40, 0x45, +- 0x14, 0xF0, 0x24, 0x44, 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, +- 0xE8, 0x87, 0xF8, 0xBF, 0xC0, 0x84, 0x14, 0xFA, 0x60, 0x5C, 0x2F, 0x67, 0xD0, 0x80, 0x60, 0x45, +- 0x02, 0x28, 0x64, 0x45, 0x25, 0x5C, 0x8B, 0x67, 0xD0, 0x80, 0x60, 0x41, 0x02, 0x24, 0x64, 0x41, +- 0xD5, 0x84, 0x80, 0x65, 0xC4, 0x87, 0x01, 0x05, 0x00, 0x64, 0xFF, 0xB4, 0x0E, 0xFA, 0x63, 0x46, +- 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x17, 0xF2, 0x63, 0x46, 0x60, 0x40, 0x00, 0x36, 0x2E, 0x00, +- 0x01, 0x36, 0x1E, 0x00, 0x03, 0x3A, 0x25, 0x00, 0x64, 0x46, 0x10, 0xF2, 0x11, 0xFA, 0x12, 0xF2, +- 0x00, 0x61, 0x60, 0x47, 0x00, 0x7F, 0x12, 0xFA, 0x97, 0xFA, 0x46, 0x44, 0x63, 0x46, 0xC1, 0x60, +- 0x58, 0x4E, 0x72, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x00, 0x3A, 0x04, 0x00, 0xC1, 0x60, 0x58, 0x4E, +- 0xBC, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x96, 0xFC, 0x63, 0x46, 0x43, 0x00, +- 0x64, 0x46, 0x16, 0xF2, 0x00, 0x61, 0x20, 0x28, 0xFF, 0xA4, 0x97, 0xFA, 0x16, 0xFA, 0x63, 0x46, +- 0x3A, 0x00, 0x64, 0x46, 0x00, 0x61, 0x97, 0xFA, 0x63, 0x46, 0x35, 0x00, 0x07, 0xF0, 0x66, 0x41, +- 0x64, 0x46, 0x16, 0xF2, 0xFF, 0xFF, 0x20, 0x28, 0xFF, 0xA4, 0x16, 0xFA, 0x93, 0xF4, 0x12, 0xF2, +- 0x20, 0x28, 0xFF, 0xA3, 0x13, 0xFC, 0x61, 0x46, 0x63, 0x40, 0x00, 0x3A, 0x24, 0x00, 0xC1, 0x60, +- 0x58, 0x4E, 0x93, 0x78, 0xFF, 0xFF, 0x61, 0x40, 0xFF, 0x36, 0x1D, 0x00, 0x66, 0x41, 0x64, 0x46, +- 0x12, 0xF2, 0x93, 0xF4, 0x61, 0x46, 0x20, 0x28, 0x16, 0x00, 0x44, 0x44, 0xC1, 0x60, 0x58, 0x4E, +- 0x72, 0x78, 0xFF, 0xFF, 0x24, 0x5C, 0x65, 0x40, 0x00, 0x36, 0x06, 0x00, 0x66, 0x41, 0x64, 0x46, +- 0x01, 0x64, 0x17, 0xFA, 0x61, 0x46, 0x07, 0x00, 0x66, 0x43, 0x64, 0x46, 0xC1, 0x60, 0x58, 0x4E, +- 0xBC, 0x78, 0xFF, 0xFF, 0x63, 0x46, 0xBE, 0x60, 0xA6, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x43, +- 0x64, 0x46, 0x17, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xFF, 0x27, 0xFF, 0xFF, 0x00, 0x36, 0x07, 0x00, +- 0x01, 0x36, 0x1C, 0x00, 0x02, 0x36, 0x24, 0x00, 0x03, 0x36, 0x43, 0x00, 0xFF, 0xFF, 0x15, 0x60, +- 0xF9, 0xF1, 0x16, 0xF2, 0x43, 0x44, 0xD0, 0x80, 0x2C, 0x60, 0x24, 0x61, 0x09, 0x03, 0xA1, 0xD1, +- 0x2C, 0x60, 0x22, 0x63, 0xC0, 0x84, 0x16, 0xFA, 0xA3, 0xD3, 0xFF, 0xFF, 0x13, 0xFA, 0x39, 0x00, +- 0x96, 0xFC, 0xC1, 0x60, 0x58, 0x4E, 0xBC, 0x78, 0xFF, 0xFF, 0x33, 0x00, 0x43, 0x44, 0xC1, 0x60, +- 0x58, 0x4E, 0xBC, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0x11, 0xF3, 0x96, 0xFC, 0x13, 0xFA, 0x29, 0x00, +- 0x63, 0x46, 0x2B, 0x60, 0xF4, 0x63, 0xA3, 0xD3, 0x15, 0xF2, 0x60, 0x45, 0xD4, 0x80, 0x07, 0xF0, +- 0x0C, 0x03, 0x66, 0x41, 0x44, 0x44, 0x64, 0x46, 0x12, 0xF2, 0x61, 0x46, 0xC1, 0x60, 0x58, 0x4E, +- 0x72, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x00, 0x3A, 0x19, 0x00, 0x66, 0x43, 0x24, 0x46, 0xC1, 0x60, +- 0x58, 0x4E, 0xBC, 0x78, 0xFF, 0xFF, 0x12, 0xF2, 0x91, 0xF2, 0x90, 0xFA, 0x60, 0x5F, 0x12, 0xFA, +- 0x04, 0x00, 0xC1, 0x60, 0x58, 0x4E, 0xBC, 0x78, 0xFF, 0xFF, 0x03, 0x64, 0x17, 0xFA, 0x63, 0x46, +- 0x05, 0x00, 0x24, 0x43, 0x02, 0x64, 0x17, 0xFA, 0x63, 0x46, 0x00, 0x00, 0x03, 0x64, 0x3B, 0xDB, +- 0xCA, 0xFE, 0x47, 0xF1, 0x01, 0x65, 0x32, 0x40, 0x04, 0x27, 0x08, 0x00, 0x2C, 0xF2, 0x64, 0x45, +- 0x02, 0x22, 0x04, 0x00, 0x60, 0x40, 0x01, 0x26, 0x01, 0x00, 0x7B, 0x00, 0x14, 0xF2, 0x65, 0x40, +- 0x01, 0x26, 0x0C, 0x00, 0x60, 0x45, 0x05, 0x64, 0x3B, 0xDB, 0x65, 0x44, 0xCC, 0x85, 0x25, 0x60, +- 0xD6, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xD3, 0x78, 0x97, 0xF1, 0x50, 0x00, 0x60, 0x41, 0x2A, 0xF0, +- 0x00, 0x60, 0x0C, 0x64, 0xA0, 0x84, 0x04, 0x36, 0x02, 0x00, 0x0C, 0x3A, 0x01, 0x00, 0x46, 0x00, +- 0x61, 0x45, 0x60, 0x43, 0x25, 0x60, 0xD6, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xD3, 0x78, 0x97, 0xF1, +- 0x63, 0x40, 0x08, 0x36, 0x01, 0x00, 0x3A, 0x00, 0x14, 0xF2, 0x1C, 0x65, 0x60, 0x41, 0x00, 0x63, +- 0xCD, 0x81, 0xC7, 0x83, 0xFD, 0x02, 0x3F, 0xF0, 0x2C, 0xF2, 0xC3, 0x83, 0x60, 0x40, 0x01, 0x2A, +- 0x0D, 0x00, 0x25, 0x60, 0xD4, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x25, 0x60, +- 0xDA, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xD2, 0x78, 0x63, 0x45, 0x20, 0x00, 0x25, 0x60, 0xD2, 0x64, +- 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x25, 0x60, 0xD8, 0x64, 0xE5, 0x60, 0x78, 0x41, +- 0xD2, 0x78, 0x63, 0x45, 0x15, 0xF2, 0xFF, 0xFF, 0x0F, 0xB4, 0x00, 0xA8, 0x01, 0xA8, 0x0E, 0x03, +- 0x07, 0x03, 0x25, 0x60, 0xE0, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x06, 0x00, +- 0x25, 0x60, 0xDE, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x04, 0x64, 0x3B, 0xDB, +- 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x06, 0xF0, 0xFF, 0x60, 0x5F, 0x64, 0xA0, 0x84, 0x06, 0xFA, +- 0x61, 0x46, 0x1E, 0x60, 0xF2, 0x64, 0x0F, 0x60, 0x8D, 0xFB, 0x3C, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x5C, 0x5C, 0xFC, 0xFC, 0xCE, 0xFE, 0xB7, 0x60, 0xE2, 0x78, +- 0xFF, 0xFF, 0x13, 0x60, 0x2E, 0xF3, 0x07, 0xF4, 0x06, 0xF2, 0x02, 0xA8, 0x3C, 0x46, 0x10, 0x03, +- 0x10, 0xB0, 0x2A, 0xF2, 0x0D, 0x03, 0x0E, 0xF2, 0x0C, 0xB0, 0x60, 0x40, 0xF0, 0x37, 0x20, 0xBC, +- 0x02, 0x03, 0xFE, 0x7F, 0x0E, 0xFA, 0x23, 0xF0, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xCE, 0x01, +- 0x2A, 0xF2, 0xFF, 0xFF, 0x50, 0xA8, 0x02, 0x7C, 0x10, 0x03, 0x0F, 0xF0, 0x15, 0xF2, 0x64, 0x41, +- 0x01, 0x2A, 0x02, 0x00, 0xAF, 0xF1, 0x09, 0x00, 0x03, 0x65, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, +- 0x06, 0xF0, 0x63, 0x46, 0xAE, 0xF1, 0x64, 0x40, 0x10, 0x2A, 0x64, 0x45, 0xDC, 0x84, 0xD4, 0x80, +- 0x15, 0xFA, 0x38, 0x07, 0x61, 0x40, 0x01, 0x2A, 0x08, 0x00, 0x13, 0x60, 0x03, 0xF3, 0xFF, 0xFF, +- 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, 0x07, 0x00, 0x13, 0x60, 0x04, 0xF3, 0xFF, 0xFF, +- 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, 0x2A, 0xF0, 0x08, 0x67, 0xB0, 0x84, 0xA2, 0xDA, +- 0x08, 0xF0, 0x1E, 0x60, 0xD4, 0x64, 0xD0, 0x80, 0x07, 0xF2, 0x46, 0x43, 0x87, 0xF1, 0x06, 0x03, +- 0x60, 0x46, 0x86, 0xF4, 0xD0, 0x80, 0x80, 0xBB, 0x01, 0x03, 0x06, 0xFC, 0x23, 0x46, 0x3E, 0xF2, +- 0x00, 0x63, 0x01, 0xB0, 0x43, 0x5C, 0xFC, 0xFC, 0x0A, 0x03, 0x1E, 0x60, 0xEC, 0x64, 0x0F, 0x60, +- 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xB7, 0x60, +- 0xE2, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x49, 0xFB, 0x25, 0x60, 0xE0, 0x64, 0xE5, 0x60, 0x78, 0x41, +- 0xC7, 0x78, 0x97, 0xF1, 0x25, 0x60, 0xE2, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, +- 0x27, 0x44, 0xF7, 0xB4, 0x40, 0x47, 0x23, 0xF0, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x07, 0xF0, +- 0x66, 0x41, 0x64, 0x46, 0x06, 0xF2, 0x7F, 0x65, 0xA4, 0x9E, 0x06, 0xFA, 0x61, 0x46, 0x5E, 0x01, +- 0xC0, 0x60, 0x35, 0x78, 0xFF, 0xFF, 0x21, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0x01, 0x63, 0xC4, 0xB4, +- 0x31, 0xFB, 0x32, 0xFD, 0xBF, 0x60, 0xEB, 0x62, 0x42, 0x40, 0xA0, 0x4C, 0x40, 0xBC, 0x7D, 0xB4, +- 0xA0, 0x51, 0xA0, 0xFE, 0x1A, 0xFF, 0x1E, 0x60, 0xE6, 0x64, 0x08, 0xF0, 0x07, 0xF0, 0xD0, 0x80, +- 0x1E, 0x60, 0xEC, 0x62, 0x13, 0x02, 0xA2, 0xD3, 0x01, 0x63, 0xAC, 0x86, 0x07, 0xF2, 0x0E, 0x03, +- 0xD0, 0x80, 0x09, 0xF2, 0xFA, 0x02, 0x23, 0xFC, 0x1E, 0x60, 0xF2, 0x64, 0x0F, 0x60, 0x8D, 0xFB, +- 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x3C, 0x46, 0x06, 0x64, +- 0xA1, 0xFF, 0x49, 0xFB, 0x83, 0x3E, 0x31, 0xF3, 0x87, 0x60, 0x80, 0x61, 0x1D, 0xF0, 0x60, 0x40, +- 0x01, 0x2A, 0x0F, 0x00, 0xFE, 0xB4, 0x31, 0xFB, 0x00, 0x64, 0x49, 0xFB, 0x01, 0x64, 0x47, 0xFB, +- 0x00, 0x71, 0x05, 0x64, 0x64, 0x5F, 0x0D, 0xFA, 0x40, 0x64, 0x3B, 0xDB, 0xC0, 0x60, 0x35, 0x78, +- 0xFF, 0xFF, 0x02, 0x2A, 0x17, 0x00, 0xD1, 0x91, 0x8D, 0xE2, 0x41, 0x64, 0x3B, 0xDB, 0x31, 0xF3, +- 0x2C, 0x60, 0x5E, 0x63, 0xFD, 0xB4, 0x31, 0xFB, 0xA3, 0xD3, 0x02, 0x63, 0x60, 0x5C, 0x0D, 0xF2, +- 0x47, 0xFD, 0xFF, 0xB5, 0x60, 0x47, 0xD0, 0x80, 0xDC, 0x84, 0x1F, 0x03, 0x60, 0x47, 0xB4, 0x84, +- 0x0D, 0xFA, 0x1B, 0x00, 0x08, 0x2A, 0x07, 0x00, 0x42, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, +- 0xF7, 0xB4, 0x31, 0xFB, 0x12, 0x00, 0x10, 0x2A, 0x09, 0x00, 0x43, 0x64, 0x3B, 0xDB, 0x31, 0xF3, +- 0xFF, 0xFF, 0xEF, 0xB4, 0x31, 0xFB, 0xBF, 0x60, 0xBB, 0x78, 0xFF, 0xFF, 0x44, 0x64, 0x3B, 0xDB, +- 0x31, 0xF3, 0xFF, 0xFF, 0xDF, 0xB4, 0x31, 0xFB, 0x00, 0x00, 0x2A, 0x64, 0x3B, 0xDB, 0xB7, 0x60, +- 0xA2, 0x64, 0x40, 0x40, 0xBD, 0x60, 0x7D, 0x78, 0xFF, 0xFF, 0x0A, 0x60, 0x80, 0xF3, 0xFF, 0xFF, +- 0x02, 0xB5, 0x04, 0xB5, 0x04, 0x03, 0x03, 0x03, 0xC0, 0x60, 0xB8, 0x78, 0xFF, 0xFF, 0xF0, 0x60, +- 0x58, 0x4E, 0x74, 0x78, 0xFF, 0xFF, 0x31, 0x40, 0x01, 0x2A, 0x28, 0x00, 0x9D, 0xFE, 0x26, 0x04, +- 0x25, 0x0A, 0x9F, 0xFE, 0x23, 0x05, 0x85, 0xFF, 0x20, 0x44, 0x84, 0xFF, 0x40, 0x26, 0x1E, 0x00, +- 0x3F, 0x40, 0x20, 0x2B, 0x1B, 0x00, 0x38, 0x69, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, +- 0x01, 0x2A, 0x14, 0x00, 0x13, 0x60, 0x09, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, +- 0xA2, 0xDB, 0x64, 0xF1, 0x02, 0x60, 0xEE, 0x64, 0x81, 0xFB, 0xFF, 0xFF, 0x80, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0x82, 0xFB, 0x04, 0x64, 0x83, 0xFB, 0xDF, 0xFE, 0x19, 0xFF, 0x10, 0x64, 0x3B, 0xDB, +- 0x65, 0xF3, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0x74, 0xF1, 0xC9, 0xFE, +- 0x64, 0x40, 0x01, 0x26, 0x3B, 0x00, 0x49, 0xF3, 0x3C, 0x46, 0x31, 0x18, 0xCC, 0x84, 0x49, 0xFB, +- 0x2E, 0x02, 0xC1, 0x60, 0x6B, 0x64, 0x40, 0x42, 0xFC, 0xFC, 0x00, 0x64, 0x5C, 0x5C, 0x32, 0xFB, +- 0x82, 0xFF, 0x5C, 0x47, 0x84, 0xFF, 0x62, 0xFF, 0x13, 0x60, 0x01, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, +- 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, 0x2A, 0xF2, 0x07, 0xF0, 0x0C, 0xB4, 0x08, 0x3A, 0x07, 0x00, +- 0x66, 0x41, 0x64, 0x46, 0x06, 0xF0, 0xFF, 0x60, 0xDF, 0x64, 0xA0, 0x84, 0x06, 0xFA, 0x23, 0xF0, +- 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x1E, 0x60, 0xF2, 0x64, 0x0F, 0x60, 0x8D, 0xFB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xCE, 0xFE, 0x06, 0x00, +- 0x65, 0xF3, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0x14, 0x60, 0xFC, 0x63, +- 0xA3, 0xD3, 0xAD, 0x49, 0x20, 0xB5, 0x08, 0xB1, 0x22, 0x03, 0xE1, 0x81, 0x10, 0xB5, 0x95, 0x81, +- 0x60, 0x41, 0x18, 0x02, 0x14, 0x60, 0xFE, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA4, 0xDB, +- 0x16, 0x02, 0x0A, 0x64, 0xA4, 0xDB, 0x61, 0x44, 0x07, 0xB4, 0xFF, 0xFF, 0x10, 0x02, 0x08, 0xB1, +- 0xE1, 0x81, 0x95, 0x81, 0xA3, 0xD3, 0x0B, 0x03, 0x08, 0xAC, 0x01, 0xBC, 0xA3, 0xDB, 0xFF, 0xFF, +- 0x13, 0xFF, 0x05, 0x00, 0x10, 0xAC, 0xA3, 0xDB, 0x0A, 0x7C, 0x0A, 0x60, 0x7F, 0xF9, 0xB7, 0x60, +- 0xAE, 0x78, 0xFF, 0xFF, 0x46, 0xF3, 0x45, 0xF1, 0x04, 0x1B, 0x64, 0x44, 0x02, 0x1B, 0x07, 0x60, +- 0xF7, 0xF3, 0x45, 0xFB, 0x00, 0x63, 0x46, 0xFD, 0x60, 0x41, 0x25, 0x64, 0x3B, 0xDB, 0x27, 0x44, +- 0xEF, 0xB4, 0x40, 0x47, 0x00, 0xB9, 0x71, 0x40, 0x80, 0x27, 0x01, 0x12, 0x19, 0x03, 0xC1, 0x60, +- 0x0C, 0x62, 0x84, 0xFF, 0x42, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, +- 0x1F, 0x0A, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x19, 0x0A, 0x71, 0x40, +- 0x80, 0x27, 0xF7, 0x12, 0x45, 0xF3, 0x27, 0x02, 0x03, 0x18, 0xCC, 0x84, 0x45, 0xFB, 0xF1, 0x02, +- 0x06, 0x0A, 0xA0, 0x4C, 0xFB, 0xB4, 0xA0, 0x51, 0xA4, 0x60, 0xD7, 0x78, 0xFF, 0xFF, 0x84, 0xFF, +- 0xC0, 0x60, 0xEA, 0x64, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, +- 0xAF, 0x60, 0x7B, 0x78, 0xFF, 0xFF, 0x3C, 0x44, 0xAC, 0x80, 0x32, 0xF1, 0x12, 0x03, 0x64, 0x40, +- 0x07, 0x22, 0x0F, 0x00, 0xA4, 0x60, 0xB6, 0x78, 0xFF, 0xFF, 0xA0, 0x4C, 0x1C, 0xBC, 0xDF, 0xB4, +- 0xA0, 0x51, 0xF1, 0x01, 0x06, 0x00, 0x28, 0x64, 0x3A, 0xDB, 0xA0, 0x4C, 0x30, 0xBC, 0xF3, 0xB4, +- 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x28, 0x64, 0x3B, 0xDB, 0x07, 0x60, 0xF8, 0xF3, +- 0x32, 0x40, 0x02, 0x27, 0x16, 0x00, 0x46, 0xFB, 0x14, 0x18, 0xC1, 0x60, 0x59, 0x64, 0x84, 0xFF, +- 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x15, 0xBC, 0xF7, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x46, 0xF3, 0xCB, 0x0A, 0xDD, 0x02, 0xCC, 0x84, 0x46, 0xFB, +- 0xF5, 0x02, 0x84, 0xFF, 0xC1, 0x60, 0x6B, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x27, 0x44, 0x08, 0xBC, +- 0x40, 0x47, 0xF9, 0xE1, 0x04, 0x00, 0x78, 0xE1, 0x31, 0x40, 0x01, 0x26, 0xF9, 0xE1, 0xA4, 0x60, +- 0xAA, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xFB, 0xF1, 0x60, 0x45, 0x2C, 0x60, 0x0A, 0x61, 0xC5, 0x83, +- 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0x66, 0x45, 0x24, 0x46, 0x0E, 0xF2, 0x65, 0x46, 0x64, 0x45, +- 0xD5, 0x81, 0x61, 0x45, 0x00, 0x7F, 0xD4, 0x80, 0x64, 0x43, 0x08, 0x04, 0xE3, 0x83, 0x63, 0x45, +- 0xC5, 0x81, 0x61, 0x45, 0xD4, 0x80, 0x02, 0x65, 0x03, 0x07, 0x03, 0x00, 0x00, 0x65, 0x01, 0x00, +- 0x01, 0x65, 0x2E, 0x58, 0xFF, 0xFF, 0x66, 0x43, 0x64, 0x46, 0x8F, 0xF0, 0x12, 0xF2, 0x91, 0xF2, +- 0x60, 0x40, 0x10, 0x36, 0x05, 0x00, 0x12, 0x36, 0x08, 0x00, 0x0C, 0x36, 0x0B, 0x00, 0x0F, 0x00, +- 0x40, 0x61, 0xA5, 0x80, 0x0A, 0x64, 0x13, 0x02, 0xF3, 0x01, 0x10, 0x61, 0xA5, 0x80, 0x0E, 0x64, +- 0x0E, 0x02, 0xEE, 0x01, 0x08, 0x61, 0xA5, 0x80, 0x10, 0x64, 0x09, 0x02, 0xE9, 0x01, 0xE1, 0x81, +- 0xA5, 0x80, 0x03, 0x05, 0xC8, 0x84, 0x03, 0x02, 0xE3, 0x01, 0xFF, 0x61, 0x02, 0x00, 0x12, 0xFA, +- 0x91, 0xFA, 0x63, 0x46, 0x2E, 0x58, 0xFF, 0xFF, 0x8F, 0xF0, 0x12, 0xF2, 0x91, 0xF2, 0x60, 0x40, +- 0x0A, 0x36, 0x05, 0x00, 0x0E, 0x36, 0x08, 0x00, 0x10, 0x36, 0x0B, 0x00, 0x0F, 0x00, 0x08, 0x61, +- 0xA5, 0x80, 0x10, 0x7E, 0x11, 0x02, 0xF3, 0x01, 0x04, 0x61, 0xA5, 0x80, 0x12, 0x7E, 0x0C, 0x02, +- 0xEE, 0x01, 0x20, 0x61, 0xA5, 0x80, 0x0C, 0x7E, 0x07, 0x02, 0xE9, 0x01, 0xE9, 0x81, 0xA5, 0x80, +- 0x05, 0x05, 0xD8, 0x84, 0x01, 0x02, 0xE3, 0x01, 0x12, 0xFA, 0x91, 0xFA, 0x2E, 0x58, 0xFF, 0xFF, +- 0x24, 0xE2, 0x2D, 0xF3, 0x2C, 0xF3, 0x00, 0xBD, 0xCC, 0x84, 0x08, 0x03, 0x2C, 0xFB, 0x06, 0x02, +- 0x65, 0x44, 0x2C, 0xFB, 0x8A, 0xFF, 0x80, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x44, 0xF3, 0xFF, 0xFF, +- 0xDC, 0x84, 0x44, 0xFB, 0x28, 0x60, 0x72, 0x65, 0x28, 0x60, 0x70, 0x61, 0xA5, 0xD3, 0xA1, 0xD3, +- 0x11, 0x18, 0xCC, 0x84, 0xA1, 0xDB, 0x0E, 0x02, 0xA5, 0xD3, 0xA1, 0xDB, 0x14, 0x60, 0x3B, 0xF3, +- 0x14, 0x60, 0x3A, 0xF1, 0xA2, 0xDB, 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x03, 0x8A, 0xFF, 0x20, 0x60, +- 0x00, 0x75, 0x88, 0xFF, 0xD2, 0xF3, 0x31, 0x40, 0x01, 0x2A, 0x3D, 0x00, 0x60, 0x43, 0x04, 0xB0, +- 0x02, 0xB0, 0x08, 0x24, 0x16, 0x02, 0x10, 0xB0, 0x29, 0x44, 0x34, 0x02, 0x00, 0xA8, 0xCC, 0x81, +- 0x0D, 0x03, 0x41, 0x49, 0x2F, 0x02, 0x63, 0x40, 0x08, 0x2A, 0x08, 0x00, 0xF7, 0xB3, 0x18, 0x60, +- 0x0A, 0xF1, 0xAD, 0x4F, 0xFD, 0xB4, 0xA0, 0x5D, 0x44, 0x49, 0x24, 0x00, 0x63, 0x40, 0x02, 0x2A, +- 0x10, 0x00, 0x18, 0x60, 0x0B, 0xF3, 0x18, 0x60, 0x09, 0xFB, 0x40, 0x49, 0x18, 0x60, 0x0C, 0xF3, +- 0x18, 0x60, 0x0A, 0xFB, 0x0C, 0xBB, 0xFD, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, +- 0x11, 0x00, 0x18, 0x60, 0x0D, 0xF3, 0x30, 0x60, 0x12, 0x7C, 0x0C, 0x18, 0xA4, 0xDB, 0x40, 0x49, +- 0x18, 0x60, 0x0E, 0xF3, 0x18, 0x60, 0x0A, 0xFB, 0x08, 0xBB, 0xFB, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, +- 0x00, 0x7F, 0xA0, 0x5D, 0xD2, 0xFD, 0x00, 0x60, 0x85, 0xF3, 0x62, 0x43, 0x17, 0x18, 0x58, 0xD3, +- 0x62, 0x41, 0x03, 0x18, 0xCC, 0x84, 0xA1, 0xDB, 0x11, 0x00, 0x49, 0xD3, 0xA3, 0xDB, 0x06, 0xA1, +- 0xA1, 0xD3, 0x59, 0xD1, 0x60, 0x45, 0xA5, 0xD3, 0x59, 0xD1, 0xB0, 0x84, 0xA5, 0xDB, 0x64, 0x44, +- 0x06, 0x36, 0xCD, 0xFE, 0x07, 0x36, 0xD6, 0xFE, 0xE6, 0x01, 0x23, 0x46, 0xB7, 0x60, 0xAE, 0x78, +- 0xFF, 0xFF, 0x46, 0x43, 0x1F, 0x60, 0x44, 0x61, 0xA1, 0xD3, 0x59, 0xD1, 0x06, 0x1B, 0x59, 0xD3, +- 0x59, 0xD1, 0x03, 0x1B, 0x59, 0xD3, 0x59, 0xD1, 0xF0, 0x18, 0x00, 0x63, 0x49, 0xDD, 0x60, 0x40, +- 0x02, 0x36, 0x11, 0x00, 0x03, 0x36, 0x32, 0x00, 0x01, 0x36, 0x08, 0x00, 0x05, 0x3A, 0xEA, 0x01, +- 0xA4, 0xD3, 0x5A, 0xD3, 0x9C, 0x85, 0xA4, 0x84, 0xA2, 0xDB, 0xE4, 0x01, 0x01, 0x60, 0x0A, 0x61, +- 0x00, 0x64, 0xA1, 0xDB, 0xDF, 0x01, 0xC2, 0x60, 0x8F, 0x64, 0x40, 0x45, 0x22, 0x00, 0x01, 0x60, +- 0x0A, 0x66, 0xA6, 0xD3, 0x04, 0xA1, 0x60, 0x43, 0xA1, 0xD3, 0xC9, 0x81, 0x60, 0x45, 0x00, 0xBB, +- 0xA1, 0xDB, 0xBE, 0xD3, 0x09, 0x03, 0xD4, 0x84, 0x9C, 0x84, 0xDC, 0x84, 0xFF, 0xFF, 0x04, 0x0E, +- 0xA3, 0xD1, 0x63, 0x46, 0x64, 0x43, 0xF2, 0x01, 0x9C, 0x84, 0xDC, 0x85, 0x49, 0xDD, 0x61, 0x44, +- 0x00, 0xBB, 0xA6, 0xDB, 0x02, 0x03, 0x65, 0x44, 0xBE, 0xDB, 0xBC, 0x01, 0xC2, 0x60, 0x6A, 0x64, +- 0x40, 0x45, 0x01, 0x60, 0x0A, 0x66, 0xA6, 0xD3, 0xFF, 0xFF, 0xD0, 0x80, 0x0F, 0x18, 0x02, 0x03, +- 0x60, 0x46, 0xF9, 0x01, 0x58, 0xD3, 0xA4, 0xD3, 0x60, 0x45, 0x00, 0x63, 0xA4, 0xDD, 0x05, 0x18, +- 0x58, 0xD3, 0xFF, 0xFF, 0xC4, 0x83, 0xA2, 0xDD, 0xCA, 0x84, 0xA6, 0xDB, 0x25, 0x58, 0x64, 0x41, +- 0x04, 0x60, 0x40, 0x62, 0x1A, 0x60, 0x58, 0x4D, 0xB4, 0x78, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, +- 0x64, 0x40, 0x01, 0x2B, 0x50, 0x00, 0x28, 0x40, 0x08, 0x3A, 0x4D, 0x00, 0xE8, 0x84, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0x15, 0x60, 0xD5, 0xFB, 0x64, 0xF1, 0x24, 0x60, 0x88, 0x63, 0x64, 0x40, +- 0x01, 0x27, 0x3C, 0xA3, 0x29, 0x40, 0x40, 0x2B, 0x1E, 0xA3, 0xBD, 0xD1, 0x63, 0x45, 0x44, 0x4E, +- 0x0E, 0x61, 0xBD, 0xD1, 0xCD, 0x81, 0xD0, 0x80, 0x01, 0x03, 0xFB, 0x04, 0xCB, 0x83, 0x15, 0x60, +- 0xD8, 0xF3, 0x39, 0xF1, 0xD7, 0x83, 0xEB, 0x83, 0x2E, 0x41, 0x5D, 0x93, 0xDF, 0x83, 0x15, 0x60, +- 0xD4, 0xFD, 0x15, 0x60, 0xD3, 0xFB, 0x53, 0x93, 0xDF, 0x80, 0x10, 0x03, 0x38, 0xF3, 0xCF, 0x83, +- 0x08, 0x03, 0xDF, 0x83, 0x0B, 0x02, 0xDF, 0x83, 0xDC, 0x84, 0xF0, 0xA0, 0x38, 0xFB, 0x06, 0x03, +- 0x03, 0x00, 0xCC, 0x84, 0x38, 0xFB, 0x02, 0x03, 0x00, 0x63, 0x02, 0x00, 0x08, 0x64, 0x38, 0xFB, +- 0xE3, 0x80, 0xFB, 0x83, 0xC3, 0x83, 0x63, 0x44, 0xFC, 0xA0, 0x02, 0x0E, 0x08, 0x07, 0x08, 0x00, +- 0x04, 0xA4, 0xFF, 0xFF, 0x05, 0x0D, 0xFC, 0x64, 0xFF, 0x7F, 0x60, 0x43, 0x01, 0x00, 0x04, 0x63, +- 0x39, 0xFD, 0x15, 0x60, 0xD7, 0xFD, 0x2F, 0x58, 0xFF, 0xFF, 0x15, 0x60, 0xD2, 0xF3, 0x40, 0x4E, +- 0x60, 0x46, 0x2F, 0xDB, 0x44, 0x44, 0xA1, 0xD3, 0xD9, 0x81, 0x48, 0x94, 0x24, 0x5C, 0xD0, 0x9C, +- 0x66, 0x42, 0x04, 0x06, 0xD2, 0x9C, 0x2F, 0xD9, 0x64, 0x46, 0x24, 0x44, 0xE0, 0x84, 0x44, 0xD3, +- 0xA3, 0xDB, 0xFF, 0xB4, 0x60, 0x5C, 0x66, 0x44, 0x22, 0xA4, 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, +- 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0xA2, 0xD3, 0x60, 0x5C, 0x64, 0x5E, 0x60, 0x47, +- 0x2F, 0xD1, 0x28, 0xA3, 0xA3, 0xD9, 0xD8, 0xA3, 0x2E, 0x42, 0x4E, 0x8E, 0xBD, 0xDB, 0xDB, 0x02, +- 0x2D, 0x58, 0xFF, 0xFF, 0x43, 0xFF, 0x39, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x84, 0x3E, 0xFB, 0x01, +- 0x3D, 0x44, 0x00, 0xA8, 0xFF, 0xFF, 0x03, 0x02, 0x40, 0xFF, 0x44, 0xFF, 0xF4, 0x01, 0xA0, 0x4C, +- 0x3D, 0x46, 0x2A, 0xF2, 0x46, 0x4D, 0x10, 0x25, 0x12, 0x00, 0x09, 0xE1, 0xA1, 0xFF, 0x2D, 0x46, +- 0x0F, 0xF2, 0x01, 0x29, 0x06, 0x00, 0x2A, 0xF0, 0x40, 0xFF, 0x64, 0x40, 0x40, 0x2B, 0x08, 0xBC, +- 0x02, 0xBC, 0x0F, 0xFA, 0x08, 0x25, 0xDE, 0x01, 0xCB, 0xFE, 0x5C, 0x5D, 0xDC, 0x01, 0x44, 0xFF, +- 0x03, 0x2B, 0x21, 0x00, 0x88, 0xF3, 0x06, 0x61, 0x60, 0x43, 0x66, 0x45, 0x31, 0xF0, 0x63, 0x46, +- 0x05, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0x30, 0xF0, 0x0F, 0x02, 0x63, 0x46, 0x04, 0xF2, 0x65, 0x46, +- 0xD0, 0x80, 0x2F, 0xF0, 0x09, 0x02, 0x63, 0x46, 0x03, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0xFF, 0xFF, +- 0x03, 0x02, 0xFF, 0xFF, 0x48, 0xFE, 0x06, 0x00, 0xCD, 0x81, 0x02, 0xA3, 0xE7, 0x02, 0x87, 0xF1, +- 0x08, 0xFE, 0x64, 0x43, 0x26, 0x03, 0x31, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, +- 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, +- 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, +- 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, 0x60, 0x43, +- 0x61, 0x46, 0x07, 0xFC, 0x3F, 0xF2, 0x09, 0x60, 0xB0, 0x65, 0xD4, 0x80, 0x2A, 0xF2, 0x9D, 0x05, +- 0x08, 0x25, 0x88, 0x01, 0x5C, 0x4B, 0x0C, 0x60, 0xEC, 0x61, 0xA1, 0xDF, 0x2D, 0x46, 0x3B, 0xF2, +- 0x87, 0xF1, 0x87, 0xF4, 0x60, 0x40, 0x20, 0x2B, 0xB7, 0x00, 0xD3, 0x80, 0x2C, 0xF0, 0x8D, 0x03, +- 0x07, 0xF4, 0x64, 0x40, 0x01, 0x26, 0x87, 0xF5, 0xBA, 0xF4, 0x2D, 0x46, 0x04, 0x64, 0x04, 0xB3, +- 0x22, 0xF0, 0x04, 0x03, 0xC5, 0x60, 0xBD, 0x78, 0xFF, 0xFF, 0xA6, 0x00, 0x10, 0x64, 0xB0, 0x9C, +- 0x3B, 0xF2, 0x22, 0xF8, 0x60, 0x47, 0xC0, 0xB7, 0x02, 0xFE, 0xF0, 0x84, 0xF0, 0x84, 0xF0, 0x84, +- 0x00, 0xA8, 0x40, 0x4A, 0x17, 0x03, 0xE0, 0x81, 0x61, 0x43, 0x42, 0xFE, 0x00, 0x64, 0xF0, 0x84, +- 0xFE, 0x1F, 0x40, 0x4A, 0xE1, 0x84, 0xE0, 0x84, 0x2D, 0x46, 0x07, 0xF4, 0xE0, 0x81, 0x3B, 0xF0, +- 0x2A, 0x47, 0x0C, 0x60, 0x3A, 0x63, 0xA0, 0x84, 0x47, 0x9C, 0x10, 0x03, 0x7C, 0x44, 0x00, 0x60, +- 0xB2, 0x63, 0x14, 0x00, 0x07, 0xF4, 0x3B, 0xF0, 0x66, 0x44, 0x64, 0x40, 0x80, 0x2B, 0x06, 0x00, +- 0x00, 0x60, 0x78, 0x7C, 0x00, 0x60, 0xA2, 0x63, 0x43, 0x4C, 0x08, 0x00, 0x2D, 0x46, 0xC5, 0x60, +- 0xB0, 0x78, 0xFF, 0xFF, 0x2D, 0x46, 0xC5, 0x60, 0xB0, 0x78, 0xFF, 0xFF, 0xCE, 0xFB, 0xCF, 0xF9, +- 0xD0, 0xFD, 0xAD, 0x46, 0x3D, 0xF2, 0xAD, 0x46, 0xA3, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3C, 0xF2, +- 0xAD, 0x46, 0x02, 0x03, 0x15, 0x07, 0xEE, 0x04, 0x5B, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3A, 0xF2, +- 0x03, 0x03, 0xAD, 0x46, 0x0D, 0x07, 0xE6, 0x04, 0x3A, 0xF0, 0xAD, 0x46, 0x5B, 0xD0, 0x64, 0x44, +- 0xD0, 0x80, 0x2B, 0x44, 0x05, 0x07, 0xDE, 0x03, 0xD0, 0x84, 0x10, 0xA4, 0xFF, 0xFF, 0x00, 0x07, +- 0xCF, 0xF3, 0xCE, 0xF5, 0xFE, 0xA4, 0x0F, 0x60, 0xC0, 0x61, 0x0E, 0x63, 0x58, 0xD0, 0x59, 0xD9, +- 0xFD, 0x1F, 0x2D, 0x46, 0x8B, 0xFF, 0x2D, 0x46, 0x0F, 0x60, 0xB2, 0x64, 0xC9, 0x60, 0x58, 0x4F, +- 0x10, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x00, 0x60, 0x18, 0x70, 0x18, 0x71, 0x20, 0x72, 0x60, 0x53, +- 0x88, 0x75, 0x00, 0xF2, 0x09, 0xE1, 0x60, 0x50, 0x12, 0x71, 0x6E, 0x72, 0x83, 0x75, 0xA1, 0xFF, +- 0xFF, 0xFF, 0x08, 0x25, 0x1F, 0x00, 0x40, 0xFF, 0x02, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x75, 0x40, +- 0x03, 0x2A, 0x03, 0x00, 0x80, 0x75, 0x0A, 0x64, 0x0B, 0x00, 0x80, 0x75, 0x1B, 0xF3, 0x8B, 0xFF, +- 0x02, 0x60, 0x00, 0x75, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x75, 0xDC, 0x84, 0xA2, 0xDB, 0x02, 0x64, +- 0x98, 0xFF, 0x2D, 0x46, 0x0F, 0xF0, 0xFF, 0xFF, 0xB0, 0x84, 0xA2, 0xDA, 0x88, 0xFF, 0xC3, 0x60, +- 0x74, 0x78, 0xFF, 0xFF, 0x8B, 0xFF, 0x02, 0x60, 0x00, 0x75, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x75, +- 0x88, 0xFF, 0xC5, 0x60, 0x96, 0x78, 0xFF, 0xFF, 0x22, 0xF0, 0x22, 0x64, 0xB0, 0x84, 0x22, 0xFA, +- 0x3A, 0xF0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, +- 0xA0, 0x5B, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0x7C, 0x5F, 0xE8, 0x84, 0xE8, 0x85, +- 0x0D, 0x60, 0x02, 0x64, 0x44, 0xD3, 0x5A, 0xD1, 0x03, 0x1B, 0xC5, 0x60, 0xB0, 0x78, 0xFF, 0xFF, +- 0x60, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, +- 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, +- 0xE7, 0x7F, 0xA0, 0x5B, 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, +- 0xA0, 0x5B, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, +- 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, +- 0xED, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xEF, 0x7F, +- 0xA0, 0x5B, 0x65, 0x44, 0xD8, 0x84, 0x08, 0x25, 0xB9, 0x00, 0x60, 0x7F, 0xA0, 0x5B, 0x80, 0x60, +- 0x00, 0xEB, 0xA0, 0x60, 0x00, 0xEB, 0xD1, 0x60, 0x00, 0xEB, 0x3F, 0xF2, 0x3B, 0xF0, 0x60, 0x43, +- 0xFC, 0xA4, 0x64, 0x40, 0x20, 0x2B, 0x03, 0x00, 0x08, 0xA4, 0x3F, 0xFA, 0x08, 0xA3, 0xF8, 0xA3, +- 0x3F, 0xFA, 0x0A, 0xE1, 0xB3, 0xFF, 0x9A, 0xFF, 0xCB, 0x83, 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, +- 0x0E, 0xA3, 0xAB, 0x84, 0xF2, 0xA3, 0xA1, 0xFF, 0x08, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0x6C, 0x18, +- 0x02, 0x62, 0xC9, 0x81, 0xAB, 0x84, 0x01, 0x00, 0xA2, 0xDC, 0x7A, 0xD4, 0xFD, 0x1C, 0xA2, 0xDC, +- 0x08, 0x25, 0x8C, 0x00, 0xF2, 0x1D, 0x41, 0x44, 0x7C, 0xA8, 0xD9, 0x81, 0xEE, 0x03, 0xFF, 0xB1, +- 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x08, 0x25, 0x80, 0x00, 0x40, 0xFF, 0x42, 0x42, +- 0x46, 0x43, 0x06, 0x1E, 0x04, 0x02, 0x00, 0xF4, 0x02, 0x62, 0x42, 0x42, 0x46, 0x43, 0x01, 0xA2, +- 0x63, 0x45, 0x01, 0xA2, 0x62, 0x43, 0x46, 0x4C, 0xC6, 0x60, 0x58, 0x4F, 0x4B, 0x78, 0xFF, 0xFF, +- 0x0A, 0xE1, 0x9A, 0xFF, 0x24, 0x41, 0x02, 0xA1, 0x65, 0x43, 0x08, 0xA3, 0x23, 0x46, 0x22, 0x42, +- 0x7E, 0x3A, 0x0A, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0x37, 0x18, 0x02, 0x62, 0xC9, 0x81, 0xAB, 0x84, +- 0x03, 0x00, 0xA2, 0xDC, 0x7E, 0x36, 0xF6, 0x01, 0x7A, 0xD4, 0xFF, 0xFF, 0xFA, 0x1C, 0xA2, 0xDC, +- 0xF1, 0x1D, 0xD9, 0x81, 0xFF, 0xB1, 0x0B, 0x1E, 0x62, 0x40, 0x7E, 0x3A, 0x02, 0x00, 0x00, 0xF4, +- 0x02, 0x62, 0x5A, 0xD2, 0x89, 0xFF, 0x80, 0x4F, 0x6F, 0x44, 0xA2, 0xDA, 0x88, 0xFF, 0x98, 0xFF, +- 0x3D, 0x46, 0x0F, 0xF0, 0x0A, 0x64, 0xB0, 0x84, 0x18, 0x14, 0xF7, 0xB4, 0xA2, 0xDA, 0x06, 0x60, +- 0x76, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0C, 0x00, 0xD1, 0xF5, 0xD0, 0xF4, 0x0C, 0x60, +- 0xEC, 0x61, 0x59, 0xD1, 0x3B, 0xF8, 0x05, 0x64, 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, 0xFC, 0x02, +- 0x2D, 0x46, 0xC3, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0x28, 0x00, 0xA2, 0xDA, 0x2D, 0x46, 0x3B, 0xF0, +- 0xFF, 0xFF, 0x64, 0x40, 0x20, 0x2B, 0x1E, 0x00, 0x07, 0xF4, 0xBB, 0xF0, 0x2A, 0x44, 0xA4, 0x84, +- 0xFF, 0xFF, 0x2F, 0x26, 0x16, 0x00, 0x2D, 0x46, 0x64, 0x44, 0x3A, 0xF0, 0xBC, 0xF0, 0x64, 0x5F, +- 0x3D, 0xF0, 0x07, 0xF4, 0xD0, 0xF4, 0xFF, 0xFF, 0x08, 0xA3, 0x5B, 0xD8, 0x65, 0x5C, 0x5B, 0xD8, +- 0x5B, 0xDA, 0x2D, 0x46, 0xCE, 0xF3, 0x3C, 0xFA, 0xCF, 0xF3, 0x3D, 0xFA, 0x2A, 0x44, 0x23, 0xFA, +- 0x01, 0x00, 0x2D, 0x46, 0xC3, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0xFF, 0x43, 0xFF, +- 0x40, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, 0x2D, 0x46, 0x0C, 0x60, 0xEC, 0x61, 0xA1, 0xD3, 0x2D, 0x46, +- 0x60, 0x40, 0x01, 0x2A, 0x0A, 0x00, 0xD1, 0xF5, 0xD0, 0xF4, 0x59, 0xD1, 0x3B, 0xF8, 0x05, 0x64, +- 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, 0xFC, 0x02, 0x2D, 0x46, 0xC3, 0x60, 0x53, 0x78, 0xFF, 0xFF, +- 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, 0x3D, 0x46, 0x08, 0x25, 0xE0, 0x01, 0x0F, 0xF2, 0x40, 0xFF, +- 0x02, 0xBC, 0xA2, 0xDA, 0xC3, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0xB0, 0x84, 0x22, 0xFA, 0x00, 0x63, +- 0x3B, 0xF2, 0x06, 0x60, 0x76, 0xFD, 0x60, 0x47, 0xC0, 0xB7, 0x02, 0xFE, 0xF0, 0x84, 0xF0, 0x84, +- 0xF0, 0x84, 0x00, 0xA8, 0x40, 0x4A, 0x16, 0x03, 0xE0, 0x81, 0x61, 0x43, 0x42, 0xFE, 0x00, 0x64, +- 0xF0, 0x84, 0xFE, 0x1F, 0x40, 0x4A, 0xE1, 0x84, 0xE0, 0x84, 0x2D, 0x46, 0x07, 0xF4, 0xE0, 0x81, +- 0x3B, 0xF0, 0x2A, 0x47, 0x0C, 0x60, 0x3A, 0x63, 0xA0, 0x84, 0x47, 0x9C, 0x10, 0x03, 0x7C, 0x44, +- 0xA8, 0x63, 0x0F, 0x00, 0x07, 0xF4, 0x20, 0x64, 0x40, 0x4A, 0x3B, 0xF0, 0x66, 0x44, 0x64, 0x40, +- 0x80, 0x2B, 0x05, 0x00, 0x00, 0x60, 0x78, 0x7C, 0x00, 0x60, 0x98, 0x63, 0x02, 0x00, 0x2D, 0x46, +- 0xBF, 0x01, 0x2D, 0x46, 0xCE, 0xFB, 0xCF, 0xF9, 0xD0, 0xFD, 0x07, 0xF2, 0xD1, 0xFB, 0x60, 0x46, +- 0x3B, 0xF0, 0x2A, 0x44, 0x06, 0x60, 0x77, 0xF9, 0x5C, 0x4B, 0xA0, 0x84, 0xFF, 0xFF, 0x3F, 0x22, +- 0x05, 0x00, 0x90, 0x84, 0x3B, 0xFA, 0x01, 0x64, 0x40, 0x4B, 0x21, 0x00, 0xAD, 0x46, 0x0A, 0xA3, +- 0x3D, 0xF2, 0xAD, 0x46, 0xA3, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3C, 0xF2, 0xAD, 0x46, 0x02, 0x03, +- 0x16, 0x07, 0x14, 0x04, 0x5B, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3B, 0xF2, 0x03, 0x03, 0xAD, 0x46, +- 0x0E, 0x07, 0x0C, 0x04, 0x3A, 0xF0, 0xAD, 0x46, 0x5B, 0xD0, 0x64, 0x5F, 0xD0, 0x80, 0x2B, 0x44, +- 0x17, 0x07, 0x04, 0x03, 0xD0, 0x84, 0x10, 0xA4, 0xFF, 0xFF, 0x12, 0x07, 0x89, 0x01, 0x01, 0x64, +- 0x06, 0x60, 0x76, 0xFB, 0x2D, 0x46, 0x0C, 0x60, 0xFC, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, +- 0xA2, 0xDB, 0xC6, 0x60, 0x76, 0x78, 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x5E, 0x01, +- 0x2D, 0x46, 0x0C, 0x60, 0xFC, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC6, 0x60, +- 0xFE, 0x78, 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x50, 0x01, 0x00, 0x60, 0x0F, 0x64, +- 0xC4, 0x60, 0xDB, 0x78, 0xFF, 0xFF, 0x2D, 0x46, 0x3B, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x20, 0x2B, +- 0x23, 0x00, 0x00, 0xF4, 0x08, 0x61, 0x2D, 0x46, 0x00, 0xF4, 0x0A, 0x62, 0x56, 0x92, 0x5A, 0xD0, +- 0x2C, 0x46, 0x64, 0x47, 0x63, 0x40, 0x7F, 0x2A, 0x03, 0x00, 0x00, 0xF4, 0x03, 0x63, 0x46, 0x4C, +- 0x60, 0xFE, 0xDE, 0xD8, 0x7F, 0x3A, 0x03, 0x00, 0x00, 0xF4, 0x03, 0x63, 0x46, 0x4C, 0xDE, 0xDA, +- 0xFE, 0xA1, 0x20, 0xFE, 0xE8, 0x02, 0x63, 0x41, 0xFD, 0xA1, 0x46, 0x4C, 0x01, 0xF2, 0x2D, 0x46, +- 0x61, 0x5E, 0x16, 0xFA, 0x2C, 0x44, 0x06, 0xFA, 0x2F, 0x58, 0xFF, 0xFF, 0x07, 0xF4, 0x66, 0x41, +- 0x03, 0xF2, 0x04, 0xF2, 0x40, 0x42, 0x05, 0xF2, 0x40, 0x43, 0x40, 0x44, 0x61, 0x46, 0x3C, 0xF2, +- 0x3D, 0xF2, 0x40, 0x40, 0x40, 0x41, 0x0D, 0x60, 0x72, 0x65, 0x00, 0x61, 0xCF, 0xF1, 0xCE, 0xF5, +- 0x44, 0x4C, 0x2C, 0x5C, 0xE9, 0x80, 0x00, 0x64, 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, +- 0x24, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x20, 0x44, 0x40, 0x80, 0xDB, 0x83, 0xBD, 0xD2, +- 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x21, 0x44, 0x40, 0x81, 0xDB, 0x83, 0xBD, 0xD2, +- 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x22, 0x44, 0x40, 0x82, 0xDB, 0x83, 0xBD, 0xD2, +- 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x23, 0x44, 0x40, 0x83, 0xF2, 0xA3, 0xBD, 0xD2, +- 0x23, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x24, 0x44, 0xC0, 0x9C, 0x41, 0x84, 0xDD, 0x81, +- 0x08, 0x2A, 0xA7, 0x01, 0x0C, 0x60, 0xEE, 0x61, 0x05, 0x64, 0xD0, 0xF4, 0xD1, 0xF5, 0xFE, 0xA3, +- 0x5B, 0xD0, 0xCC, 0x84, 0x59, 0xD9, 0xFC, 0x02, 0xD0, 0xF3, 0xD1, 0xF5, 0x60, 0x42, 0x20, 0x44, +- 0xA2, 0xDA, 0x21, 0x44, 0x5A, 0xDA, 0x22, 0x44, 0x5A, 0xDA, 0x23, 0x44, 0x5A, 0xDA, 0x24, 0x44, +- 0x5A, 0xDA, 0x61, 0x46, 0x06, 0x60, 0x7E, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x41, 0xD0, 0xF3, +- 0xD1, 0xF5, 0xA0, 0xD2, 0x5A, 0xD0, 0x40, 0x40, 0x44, 0x41, 0x5A, 0xD2, 0x5A, 0xD0, 0x40, 0x42, +- 0x5A, 0xD0, 0x44, 0x43, 0x61, 0x46, 0xBA, 0xF0, 0x3B, 0xF2, 0x44, 0x44, 0x65, 0x5F, 0x40, 0x85, +- 0xCF, 0xF4, 0xCE, 0xF5, 0x43, 0x4C, 0x0D, 0x60, 0x72, 0x65, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x20, 0x44, 0x40, 0x80, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x21, 0x44, 0x40, 0x81, 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x22, 0x44, 0x40, 0x82, 0xBD, 0xD2, 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x23, 0x44, +- 0x40, 0x83, 0xBD, 0xD2, 0x23, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x24, 0x44, 0x40, 0x84, +- 0xBD, 0xD2, 0x24, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x25, 0x44, 0x40, 0x85, 0x61, 0x46, +- 0x3A, 0xF0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, +- 0xA0, 0x5B, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xCE, 0xF5, 0xBD, 0xD2, 0x25, 0x5C, +- 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x20, 0x5C, 0x40, 0x80, 0x20, 0x44, 0xE4, 0x7F, 0xA0, 0x5B, +- 0x20, 0x47, 0xE5, 0x7F, 0xA0, 0x5B, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, +- 0x21, 0x5C, 0x40, 0x81, 0x21, 0x44, 0xE6, 0x7F, 0xA0, 0x5B, 0x21, 0x47, 0xE7, 0x7F, 0xA0, 0x5B, +- 0x21, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x22, 0x5C, 0x40, 0x82, 0x22, 0x44, 0xE8, 0x7F, 0xA0, 0x5B, +- 0x22, 0x47, 0xE9, 0x7F, 0xA0, 0x5B, 0x22, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x23, 0x5C, 0x40, 0x83, +- 0x23, 0x44, 0xEA, 0x7F, 0xA0, 0x5B, 0x23, 0x47, 0xEB, 0x7F, 0xA0, 0x5B, 0x23, 0x44, 0xE8, 0x80, +- 0xF8, 0x84, 0x24, 0x5C, 0x40, 0x84, 0x24, 0x44, 0xEC, 0x7F, 0xA0, 0x5B, 0x24, 0x47, 0xED, 0x7F, +- 0xA0, 0x5B, 0x24, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x25, 0x5C, 0x40, 0x85, 0x25, 0x44, 0xEE, 0x7F, +- 0xA0, 0x5B, 0x25, 0x47, 0xEF, 0x7F, 0xA0, 0x5B, 0x2C, 0x43, 0xA3, 0xD2, 0x25, 0x5C, 0x90, 0x81, +- 0xE9, 0x84, 0xE3, 0x7F, 0xA0, 0x5B, 0x06, 0x60, 0x7E, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0xF3, +- 0x5A, 0xD3, 0x40, 0x48, 0x5A, 0xD3, 0x40, 0x49, 0x40, 0x4A, 0x00, 0x60, 0x78, 0x7C, 0x44, 0x4D, +- 0x49, 0xF2, 0x4A, 0xF2, 0x40, 0x47, 0x40, 0x46, 0x0D, 0x60, 0x72, 0x65, 0x00, 0x61, 0x2D, 0x5C, +- 0xE9, 0x80, 0x00, 0x64, 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x26, 0x44, 0x40, 0x86, 0xDB, 0x83, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x27, 0x44, 0x40, 0x87, 0xDB, 0x83, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x28, 0x44, 0x40, 0x88, 0xDB, 0x83, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x29, 0x44, 0x40, 0x89, 0xF2, 0xA3, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x2A, 0x44, 0xC0, 0x9C, 0x41, 0x8A, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, +- 0x26, 0x44, 0x44, 0xFA, 0x27, 0x44, 0x45, 0xFA, 0x28, 0x44, 0x46, 0xFA, 0x29, 0x44, 0x47, 0xFA, +- 0x2A, 0x44, 0x48, 0xFA, 0x06, 0x60, 0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x88, 0x7C, +- 0x44, 0x4D, 0x2D, 0x42, 0xA2, 0xD2, 0x5A, 0xD0, 0x40, 0x46, 0x44, 0x47, 0x5A, 0xD2, 0x5A, 0xD0, +- 0x40, 0x48, 0x5A, 0xD0, 0x44, 0x49, 0x4B, 0xF2, 0x44, 0x4A, 0x40, 0x8B, 0x60, 0x5C, 0x64, 0x47, +- 0xE0, 0x7F, 0xA0, 0x5A, 0xFF, 0xB4, 0x20, 0xBC, 0x7F, 0xB4, 0xE1, 0x7F, 0xA0, 0x5A, 0x64, 0x44, +- 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x78, 0x63, 0x0D, 0x60, 0x72, 0x65, 0xBD, 0xD2, 0x2B, 0x5C, +- 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x26, 0x44, 0x40, 0x86, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x27, 0x44, 0x40, 0x87, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x28, 0x44, 0x40, 0x88, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x29, 0x44, 0x40, 0x89, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2A, 0x44, +- 0x40, 0x8A, 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2B, 0x44, 0x40, 0x8B, +- 0xBD, 0xD2, 0x2B, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x26, 0x5C, 0x40, 0x86, 0x26, 0x44, +- 0xE4, 0x7F, 0xA0, 0x5A, 0x26, 0x47, 0xE5, 0x7F, 0xA0, 0x5A, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x84, +- 0xE8, 0x80, 0xF8, 0x84, 0x27, 0x5C, 0x40, 0x87, 0x27, 0x44, 0xE6, 0x7F, 0xA0, 0x5A, 0x27, 0x47, +- 0xE7, 0x7F, 0xA0, 0x5A, 0x27, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x28, 0x5C, 0x40, 0x88, 0x28, 0x44, +- 0xE8, 0x7F, 0xA0, 0x5A, 0x28, 0x47, 0xE9, 0x7F, 0xA0, 0x5A, 0x28, 0x44, 0xE8, 0x80, 0xF8, 0x84, +- 0x29, 0x5C, 0x40, 0x89, 0x29, 0x44, 0xEA, 0x7F, 0xA0, 0x5A, 0x29, 0x47, 0xEB, 0x7F, 0xA0, 0x5A, +- 0x29, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x2A, 0x5C, 0x40, 0x8A, 0x2A, 0x44, 0xEC, 0x7F, 0xA0, 0x5A, +- 0x2A, 0x47, 0xED, 0x7F, 0xA0, 0x5A, 0x2A, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x2B, 0x5C, 0x40, 0x8B, +- 0x2B, 0x44, 0xEE, 0x7F, 0xA0, 0x5A, 0x2B, 0x47, 0xEF, 0x7F, 0xA0, 0x5A, 0x3C, 0xF0, 0x2B, 0x44, +- 0x90, 0x84, 0xE8, 0x84, 0xE3, 0x7F, 0xA0, 0x5A, 0x06, 0x60, 0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x60, 0x45, 0x00, 0xF0, 0x84, 0x60, 0x00, 0xE3, 0x04, 0x71, 0x64, 0x50, 0x01, 0x2A, 0x04, 0x71, +- 0x5C, 0x61, 0x04, 0x63, 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, 0x3D, 0xF2, 0x60, 0x43, 0x60, 0x47, +- 0x5B, 0xDB, 0x3C, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x5B, 0xDB, 0x3A, 0xF2, 0xFF, 0xFF, 0x60, 0x47, +- 0x5B, 0xDB, 0x3F, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x5B, 0xDB, 0x81, 0x60, 0x18, 0xE3, 0x65, 0x43, +- 0xE3, 0x84, 0x60, 0x47, 0x00, 0x7F, 0x60, 0x50, 0x7F, 0x64, 0x23, 0x94, 0x60, 0x51, 0x7C, 0x72, +- 0x04, 0x75, 0x0C, 0x60, 0x16, 0x61, 0x16, 0x60, 0x00, 0x63, 0x59, 0xDD, 0x2A, 0xF2, 0x87, 0x60, +- 0x8F, 0x65, 0xA4, 0x87, 0x40, 0xBF, 0x59, 0xDB, 0x56, 0x64, 0x0A, 0x63, 0x58, 0xD0, 0x59, 0xD9, +- 0xFD, 0x1F, 0x62, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x35, 0xF2, 0x0F, 0x65, +- 0xA4, 0x9C, 0x59, 0xD9, 0x06, 0x63, 0x59, 0xDF, 0xFE, 0x1F, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x45, +- 0x03, 0x2B, 0x05, 0x00, 0x6A, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x65, 0x40, +- 0x8F, 0xB0, 0x88, 0x3A, 0x02, 0x00, 0x39, 0xF0, 0x59, 0xD9, 0x2F, 0x58, 0xFF, 0xFF, 0x0C, 0x60, +- 0x16, 0x61, 0xA3, 0x46, 0x00, 0xF4, 0x02, 0x64, 0x0A, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, +- 0x59, 0xDF, 0x59, 0xDF, 0xA0, 0x4C, 0x04, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0x23, 0x44, 0x01, 0xA7, +- 0x80, 0xBF, 0x60, 0x50, 0x80, 0x60, 0x38, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x01, 0x76, 0xFF, 0xFF, +- 0x76, 0x44, 0x01, 0x3A, 0xFD, 0x01, 0x40, 0x76, 0x42, 0xFF, 0xFF, 0xFF, 0x40, 0x76, 0x80, 0x60, +- 0x18, 0x70, 0x80, 0x60, 0x18, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x80, 0x60, 0x10, 0x73, 0x02, 0x76, +- 0x76, 0x44, 0xFF, 0xFF, 0x76, 0x44, 0x02, 0x3A, 0xFD, 0x01, 0x40, 0x76, 0x42, 0xFF, 0x3C, 0x46, +- 0x00, 0xF2, 0x80, 0x60, 0x00, 0xBC, 0x60, 0x50, 0x80, 0x60, 0x12, 0x71, 0x80, 0x60, 0x6E, 0x72, +- 0x3F, 0xF2, 0xFF, 0xFF, 0xF8, 0xA7, 0x80, 0xBF, 0x60, 0x53, 0x04, 0x76, 0xFF, 0xFF, 0x88, 0xFF, +- 0x3C, 0x46, 0x07, 0xF2, 0xFF, 0xFF, 0x40, 0x43, 0xA3, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x77, 0x40, +- 0x8B, 0xFF, 0xA0, 0x4C, 0x04, 0xE1, 0xFF, 0xFF, 0x76, 0x44, 0x04, 0x3A, 0xFD, 0x01, 0x40, 0x76, +- 0x42, 0xFF, 0xFF, 0xFF, 0x10, 0x76, 0xFF, 0xFF, 0x76, 0x44, 0x20, 0x3A, 0xFD, 0x01, 0x40, 0x76, +- 0x42, 0xFF, 0xA0, 0x48, 0x00, 0x7F, 0xA0, 0x51, 0x02, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xA0, 0x4C, +- 0xFB, 0xB4, 0xA0, 0x51, 0x06, 0x60, 0x1F, 0xE1, 0x16, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, +- 0x3F, 0xF2, 0xFF, 0xFF, 0xF8, 0xA4, 0x3F, 0xFA, 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, 0xA0, 0x48, +- 0x08, 0x26, 0x07, 0x00, 0xA0, 0x4C, 0x04, 0xE1, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, +- 0xA0, 0x51, 0x42, 0xFF, 0x26, 0x46, 0x8B, 0xFF, 0x02, 0x60, 0x00, 0x75, 0x3C, 0xF2, 0x40, 0x76, +- 0x14, 0x1B, 0x26, 0x46, 0x3B, 0xF2, 0x0C, 0x60, 0xBC, 0x63, 0x60, 0x47, 0xC0, 0xB4, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0x43, 0x93, 0xE3, 0x9C, 0x64, 0x47, 0x80, 0x7C, 0x64, 0x5F, 0x60, 0x50, +- 0x7F, 0x64, 0x23, 0x97, 0x80, 0xBF, 0x60, 0x51, 0x07, 0x00, 0x01, 0xA7, 0x80, 0xBF, 0x60, 0x50, +- 0x80, 0x60, 0x40, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x01, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x0C, 0x21, 0xFC, 0x01, 0x04, 0x25, 0xD5, 0x01, 0x40, 0x76, 0x43, 0xFF, 0x0C, 0x60, 0x22, 0x61, +- 0x26, 0x46, 0x00, 0xF4, 0x02, 0x64, 0x0A, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x59, 0xDF, +- 0x59, 0xDF, 0x80, 0x60, 0x18, 0x70, 0x80, 0x60, 0x24, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x80, 0x60, +- 0x10, 0x73, 0x02, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, 0xFC, 0x01, 0x04, 0x25, +- 0xB8, 0x01, 0x40, 0x76, 0x43, 0xFF, 0x26, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x80, 0xBF, +- 0x60, 0x50, 0x80, 0x60, 0x12, 0x71, 0x3F, 0xF2, 0x80, 0x60, 0x6E, 0x72, 0x60, 0x47, 0x80, 0xBF, +- 0x60, 0x53, 0x04, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, 0xFC, 0x01, 0x04, 0x25, +- 0xA0, 0x01, 0x40, 0x76, 0x43, 0xFF, 0x08, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, +- 0xFC, 0x01, 0x04, 0x25, 0x96, 0x01, 0x76, 0x5C, 0xFF, 0xFF, 0x40, 0x76, 0x43, 0xFF, 0x88, 0xFF, +- 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0xDF, 0x60, 0x2A, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x11, 0xF1, +- 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x20, 0x00, 0x74, 0xF3, 0x31, 0x40, +- 0x01, 0x2A, 0x1C, 0x00, 0xDC, 0x84, 0x01, 0xB4, 0x74, 0xFB, 0x08, 0x02, 0x08, 0x60, 0x12, 0xF1, +- 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x00, 0x08, 0x60, 0x18, 0xF1, +- 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x08, 0x00, 0xA9, 0xFE, 0xE6, 0x05, +- 0xAB, 0xFE, 0x07, 0x05, 0xA8, 0xFE, 0xD7, 0x05, 0xAA, 0xFE, 0xD8, 0x05, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x85, 0x3E, 0x0F, 0x60, 0x85, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x03, 0x02, 0xCA, 0x60, +- 0x7E, 0x78, 0xFF, 0xFF, 0x26, 0x45, 0xD4, 0x80, 0x0F, 0xF0, 0xF9, 0x03, 0x64, 0x44, 0x70, 0xB0, +- 0x70, 0x2A, 0x13, 0x00, 0x13, 0x60, 0x08, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, +- 0xA2, 0xDB, 0xA2, 0xFF, 0x8E, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0xFE, 0xA0, 0x8E, 0xFB, 0x01, 0x07, +- 0xD4, 0xFE, 0xA3, 0xFF, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x64, 0x40, 0x02, 0x26, 0x09, 0x00, +- 0x66, 0x45, 0x09, 0xF4, 0x0F, 0xF2, 0x02, 0x18, 0x65, 0x46, 0xE4, 0x1B, 0x00, 0x64, 0x40, 0x46, +- 0xCD, 0x01, 0xA2, 0xFF, 0x8E, 0xF3, 0x46, 0x46, 0xCC, 0x84, 0xFE, 0xA0, 0x8E, 0xFB, 0x01, 0x07, +- 0xD4, 0xFE, 0xA3, 0xFF, 0x0F, 0xF0, 0xA3, 0xFC, 0x64, 0x44, 0x80, 0x26, 0x17, 0x00, 0x25, 0x60, +- 0xF0, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, +- 0x07, 0x60, 0x01, 0x64, 0x04, 0x00, 0x02, 0x2A, 0x06, 0x00, 0x00, 0x60, 0x01, 0x64, 0x23, 0xFA, +- 0xCE, 0x60, 0x44, 0x78, 0xFF, 0xFF, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, +- 0x64, 0x44, 0x08, 0x26, 0x34, 0x00, 0x2A, 0xF2, 0x60, 0x63, 0x60, 0x40, 0x02, 0x2B, 0x66, 0x63, +- 0xBE, 0xD2, 0x68, 0xF1, 0xA3, 0xD2, 0xD0, 0x80, 0x67, 0xF1, 0x0D, 0x02, 0xBF, 0xD2, 0xD0, 0x80, +- 0x66, 0xF1, 0x09, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x06, 0x02, 0x25, 0x60, 0xFC, 0x64, 0xE5, 0x60, +- 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, 0x07, 0x60, 0x02, 0x64, +- 0x04, 0x00, 0x02, 0x2A, 0x06, 0x00, 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, 0xCE, 0x60, 0x44, 0x78, +- 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xB0, 0x3A, 0x06, 0x00, 0x00, 0x60, 0x02, 0x64, +- 0x23, 0xFA, 0xCB, 0x60, 0x9D, 0x78, 0xFF, 0xFF, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x32, 0x44, +- 0x01, 0x2A, 0x4A, 0x00, 0x27, 0x60, 0x6A, 0x63, 0xBF, 0xD3, 0x00, 0x65, 0xB4, 0x81, 0xDB, 0x83, +- 0x3D, 0x03, 0xBF, 0xD3, 0xA3, 0xD3, 0x40, 0x48, 0xBE, 0xD3, 0x40, 0x4A, 0x2E, 0xF0, 0x40, 0x4C, +- 0xD0, 0x80, 0x2D, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x2C, 0xF0, 0x04, 0x02, 0x28, 0x44, +- 0xD0, 0x80, 0xFF, 0xFF, 0x2B, 0x03, 0x31, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x30, 0xF0, 0x08, 0x02, +- 0x2A, 0x44, 0xD0, 0x80, 0x2F, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x1E, 0x03, +- 0x34, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x33, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x32, 0xF0, +- 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x11, 0x03, 0x38, 0xF0, 0x2C, 0x44, 0xD0, 0x80, +- 0x37, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x36, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, +- 0xFF, 0xFF, 0x04, 0x03, 0xFA, 0xA1, 0x06, 0xA3, 0xB7, 0x03, 0xC3, 0x01, 0x07, 0x60, 0x00, 0x64, +- 0x23, 0xFA, 0xCE, 0x60, 0x44, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x0F, 0xF0, 0x60, 0x45, 0xA4, 0x36, +- 0x08, 0x00, 0x0C, 0xB4, 0x04, 0x36, 0x02, 0x00, 0x0C, 0x3A, 0x06, 0x00, 0xCE, 0x60, 0x38, 0x78, +- 0xFF, 0xFF, 0xCC, 0x60, 0x35, 0x78, 0xFF, 0xFF, 0x26, 0xF2, 0x50, 0xF1, 0x60, 0x47, 0x00, 0x7E, +- 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, +- 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, +- 0xC0, 0x84, 0xA2, 0xDB, 0x0F, 0xF0, 0x65, 0x40, 0x40, 0x2B, 0x17, 0x00, 0x32, 0x40, 0x08, 0x26, +- 0x14, 0x00, 0x07, 0xF4, 0x3A, 0xF2, 0xFF, 0xFF, 0x37, 0xB4, 0x26, 0x46, 0x0E, 0x02, 0x2C, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x06, 0x00, 0x25, 0x60, 0xF6, 0x64, 0xE5, 0x60, 0x78, 0x41, +- 0xC7, 0x78, 0x97, 0xF1, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x64, 0x40, 0x60, 0x26, +- 0x03, 0x00, 0xCC, 0x60, 0x0D, 0x78, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x3A, 0xF3, 0x01, 0x25, 0x60, +- 0xEA, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, +- 0x01, 0x3B, 0x07, 0x00, 0x25, 0x60, 0xF8, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, +- 0x08, 0x00, 0x02, 0x3B, 0x06, 0x00, 0x25, 0x60, 0xFA, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, +- 0x97, 0xF1, 0x2A, 0xF2, 0x28, 0x41, 0x40, 0xA8, 0x01, 0xB1, 0x02, 0x02, 0x43, 0x02, 0x6D, 0x00, +- 0x60, 0x40, 0x08, 0x2A, 0x0F, 0x00, 0x25, 0x60, 0xE8, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, +- 0x97, 0xF1, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0x25, 0x60, 0xEE, 0x64, 0xE5, 0x60, 0x78, 0x41, +- 0xD3, 0x78, 0x97, 0xF1, 0x0F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x26, 0x28, 0x00, 0x32, 0x44, +- 0x02, 0x26, 0x25, 0x00, 0x10, 0x2B, 0x26, 0x00, 0x27, 0x60, 0x6A, 0x63, 0xBF, 0xD3, 0x2C, 0xF0, +- 0x00, 0xA8, 0x60, 0x41, 0x0D, 0x03, 0x50, 0xFE, 0xBD, 0xD3, 0x2D, 0xF0, 0xD0, 0x80, 0xBD, 0xD3, +- 0x2E, 0xF0, 0xD0, 0x80, 0xBD, 0xD3, 0x2C, 0xF0, 0xD0, 0x80, 0xFA, 0xA1, 0x10, 0x0C, 0xF3, 0x02, +- 0x50, 0xFE, 0x60, 0x60, 0x01, 0x64, 0xD0, 0x80, 0x2D, 0xF0, 0x1D, 0x64, 0xD0, 0x80, 0x2E, 0xF0, +- 0x01, 0x64, 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x0C, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x32, 0x40, +- 0x40, 0x2A, 0x00, 0x00, 0xCD, 0x60, 0xEE, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x40, 0x26, 0xFA, 0x01, +- 0x2A, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x08, 0x2A, 0x20, 0x00, 0x32, 0x40, 0x02, 0x2A, 0x1D, 0x00, +- 0x03, 0x67, 0xA0, 0x84, 0x00, 0x37, 0x64, 0x63, 0x60, 0x40, 0x02, 0x37, 0x5E, 0x63, 0x60, 0x40, +- 0x01, 0x37, 0x58, 0x63, 0x60, 0x40, 0x03, 0x37, 0x0D, 0x00, 0xBD, 0xD2, 0x66, 0xF1, 0xBD, 0xD2, +- 0xD0, 0x80, 0x67, 0xF1, 0x07, 0x02, 0xD0, 0x80, 0xBD, 0xD2, 0x68, 0xF1, 0x03, 0x02, 0xD0, 0x80, +- 0xFF, 0xFF, 0x03, 0x03, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x87, 0xF4, 0x60, 0x40, +- 0x03, 0x2B, 0x31, 0x00, 0x88, 0xF3, 0x06, 0x61, 0x60, 0x43, 0x66, 0x45, 0x31, 0xF0, 0x63, 0x46, +- 0x05, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0x30, 0xF0, 0x0F, 0x02, 0x63, 0x46, 0x04, 0xF2, 0x65, 0x46, +- 0xD0, 0x80, 0x2F, 0xF0, 0x09, 0x02, 0x63, 0x46, 0x03, 0xF2, 0x65, 0x46, 0xD0, 0x80, 0xFF, 0xFF, +- 0x03, 0x02, 0xFF, 0xFF, 0x48, 0xFE, 0x06, 0x00, 0xCD, 0x81, 0x02, 0xA3, 0xE7, 0x02, 0x87, 0xF1, +- 0x08, 0xFE, 0x64, 0x43, 0x03, 0x03, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x43, 0x43, 0x23, 0x46, +- 0x06, 0xF0, 0x26, 0x46, 0x07, 0x67, 0xA0, 0x84, 0x23, 0xFA, 0x64, 0x40, 0x02, 0x26, 0x2B, 0x00, +- 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x26, 0x1B, 0x31, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, +- 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, +- 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, +- 0x60, 0x43, 0x61, 0x46, 0x43, 0x43, 0x07, 0xFC, 0x43, 0x43, 0x1D, 0xF0, 0xC0, 0x64, 0xC0, 0x84, +- 0x0A, 0x60, 0x7B, 0xF1, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, +- 0xA2, 0xDB, 0x63, 0x45, 0x2A, 0xF2, 0x35, 0xF0, 0x60, 0x40, 0xA4, 0x36, 0x0B, 0x00, 0x08, 0x2B, +- 0x0C, 0x00, 0x23, 0x46, 0x26, 0xF2, 0x26, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x06, 0x02, 0xCE, 0x60, +- 0x38, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0xEE, 0x78, 0xFF, 0xFF, 0x23, 0x46, 0x22, 0xF2, 0x26, 0x46, +- 0x44, 0x4C, 0x0F, 0x26, 0x19, 0x00, 0x00, 0xBC, 0x40, 0x45, 0x0B, 0x03, 0x00, 0x64, 0x23, 0x46, +- 0x22, 0xFA, 0x26, 0x46, 0xA2, 0xFF, 0xB6, 0x60, 0x58, 0x4E, 0x72, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, +- 0x26, 0x46, 0x2A, 0xF0, 0x2C, 0x44, 0x64, 0x40, 0x04, 0x27, 0x06, 0x00, 0x23, 0x46, 0x26, 0xFA, +- 0x26, 0x46, 0xCD, 0x60, 0xA5, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x02, 0xFA, 0xA2, 0xFF, 0x16, 0xF0, +- 0xFF, 0xFF, 0x64, 0x44, 0x01, 0x26, 0xDC, 0x9C, 0x92, 0xF3, 0x2A, 0xF2, 0xDC, 0x83, 0x92, 0xFD, +- 0x06, 0xF4, 0x01, 0xF8, 0x26, 0x46, 0x60, 0x40, 0x40, 0x2B, 0x18, 0x00, 0x64, 0x44, 0x00, 0x65, +- 0xFF, 0xB4, 0xFC, 0xA4, 0x06, 0xF0, 0x03, 0x03, 0x64, 0x46, 0x0C, 0x0D, 0x02, 0x65, 0x26, 0x46, +- 0x00, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x60, 0x46, 0xF9, 0x01, 0x01, 0xF2, +- 0xFF, 0xFF, 0xD4, 0x84, 0x01, 0xFA, 0x66, 0x44, 0x26, 0x46, 0x06, 0xFA, 0x06, 0xF4, 0x00, 0xF2, +- 0x80, 0xFC, 0x40, 0x45, 0xB6, 0x60, 0x58, 0x4E, 0x72, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, +- 0x2C, 0x44, 0x0F, 0x26, 0x0F, 0x00, 0x23, 0x46, 0x26, 0xFA, 0x26, 0x44, 0x22, 0xFA, 0x26, 0x46, +- 0x00, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x6E, 0x00, 0xA3, 0x46, 0x26, 0xF2, 0x60, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x26, 0xFA, +- 0xA3, 0x46, 0x6B, 0x02, 0x2A, 0xF0, 0xA3, 0x46, 0x22, 0xF2, 0xA3, 0x46, 0x00, 0xBC, 0x00, 0xF2, +- 0x01, 0x02, 0x63, 0x00, 0x44, 0x4C, 0x3F, 0xF0, 0x60, 0x43, 0x23, 0x46, 0x22, 0xF4, 0x09, 0x60, +- 0x00, 0x65, 0x3F, 0xF2, 0x26, 0x46, 0xC0, 0x84, 0xD4, 0x80, 0x60, 0x45, 0x56, 0x07, 0x80, 0xFC, +- 0x1B, 0xF2, 0x06, 0xF2, 0x60, 0x41, 0x23, 0x46, 0x22, 0xF4, 0x1B, 0xF0, 0x06, 0xF0, 0xC1, 0x81, +- 0x06, 0xFA, 0x05, 0xFA, 0x9B, 0xFA, 0x65, 0x44, 0x3F, 0xFA, 0x64, 0x46, 0x00, 0xFC, 0x63, 0x46, +- 0x01, 0xF2, 0x10, 0x61, 0xF2, 0xA4, 0x01, 0xFA, 0xC8, 0x83, 0x02, 0x64, 0x59, 0xD0, 0x58, 0xD8, +- 0xFD, 0x1F, 0x06, 0x45, 0x00, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, 0x70, 0x67, +- 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, 0x80, 0xFC, +- 0x05, 0xFA, 0xB6, 0x60, 0x58, 0x4E, 0x72, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, 0x2C, 0x44, +- 0x04, 0x27, 0x16, 0x00, 0x23, 0x46, 0x22, 0xF2, 0xA2, 0xFC, 0x60, 0x46, 0x46, 0x46, 0x3F, 0xF2, +- 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, 0x26, 0x46, 0x2C, 0x43, 0x2A, 0xFC, 0x06, 0xF4, 0x00, 0x64, +- 0x00, 0xFA, 0x01, 0xF0, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0x01, 0xFA, 0x26, 0x46, 0x1D, 0x00, +- 0x00, 0x66, 0x46, 0x46, 0xCA, 0x60, 0x81, 0x78, 0xFF, 0xFF, 0xA3, 0x46, 0x22, 0xF0, 0xA2, 0xFC, +- 0x00, 0x63, 0x33, 0x85, 0xA3, 0x46, 0x0D, 0x03, 0xA3, 0x46, 0x26, 0xF2, 0x0F, 0x65, 0xA4, 0x85, +- 0xD4, 0x84, 0x26, 0xFA, 0xA3, 0x46, 0xA2, 0xFF, 0xB6, 0x60, 0x58, 0x4E, 0x72, 0x78, 0xFF, 0xFF, +- 0xA3, 0xFF, 0x26, 0x46, 0xCE, 0x60, 0x38, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x32, 0xF0, 0x60, 0x40, +- 0x08, 0x2A, 0x24, 0x00, 0x01, 0x2B, 0x13, 0x00, 0x64, 0x40, 0x01, 0x2A, 0x10, 0x00, 0x25, 0x60, +- 0xE8, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, +- 0x25, 0x60, 0xEE, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xD3, 0x78, 0x97, 0xF1, 0x0F, 0x00, 0x25, 0x60, +- 0xE6, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, +- 0x25, 0x60, 0xEC, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xD3, 0x78, 0x97, 0xF1, 0x07, 0xF4, 0xFF, 0xFF, +- 0x26, 0xF2, 0x26, 0x46, 0x0F, 0xB4, 0xDC, 0x85, 0x25, 0x60, 0xEA, 0x64, 0xE5, 0x60, 0x78, 0x41, +- 0xD3, 0x78, 0x97, 0xF1, 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3B, 0x07, 0x00, 0x25, 0x60, +- 0xF8, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x08, 0x00, 0x02, 0x3B, 0x06, 0x00, +- 0x25, 0x60, 0xFA, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0x07, 0xF2, 0x26, 0xF0, +- 0x41, 0x18, 0x60, 0x46, 0xFF, 0x67, 0x20, 0x88, 0x64, 0x5F, 0x40, 0x4A, 0x15, 0xF0, 0x28, 0x44, +- 0xD0, 0x84, 0x03, 0xA4, 0x03, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0x04, 0x00, 0xFA, 0xA4, 0xE8, 0x84, +- 0xE8, 0x87, 0xC0, 0xBF, 0xC0, 0x84, 0x15, 0xFA, 0x40, 0x48, 0x14, 0xF0, 0x2A, 0x44, 0xD0, 0x84, +- 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x07, 0x00, +- 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, 0xC0, 0x84, +- 0x14, 0xFA, 0x2B, 0x60, 0xEC, 0x63, 0xBD, 0xDB, 0x60, 0x5C, 0x2F, 0x67, 0xD0, 0x80, 0x60, 0x45, +- 0x02, 0x28, 0x64, 0x45, 0x28, 0x5C, 0xBD, 0xD9, 0x8B, 0x67, 0xD0, 0x80, 0x60, 0x41, 0x02, 0x24, +- 0x64, 0x41, 0xD5, 0x84, 0x80, 0x65, 0xC4, 0x87, 0x01, 0x05, 0x00, 0x64, 0xFF, 0xB4, 0x0E, 0xFA, +- 0xA3, 0xDB, 0x26, 0x46, 0xCE, 0x60, 0x7F, 0x78, 0xFF, 0xFF, 0xCA, 0x60, 0x81, 0x78, 0xFF, 0xFF, +- 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, 0x00, 0x66, +- 0x46, 0x46, 0xCA, 0x60, 0x81, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0x04, 0x64, 0x0F, 0x60, 0x90, 0xFB, +- 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0x00, 0x66, +- 0x46, 0x46, 0xCA, 0x60, 0x81, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x58, 0x63, 0x60, 0x47, 0x01, 0x27, +- 0x64, 0x63, 0x61, 0x5C, 0x18, 0x60, 0x0F, 0xF9, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, +- 0xBD, 0xD0, 0x00, 0xF4, 0x04, 0xF8, 0x83, 0xFA, 0x82, 0xF8, 0xA6, 0x46, 0x02, 0xB0, 0x5E, 0x63, +- 0x04, 0x03, 0x64, 0x63, 0x03, 0xB0, 0x02, 0x3A, 0x6C, 0x63, 0x3F, 0xF2, 0xBD, 0xD0, 0xBD, 0xD0, +- 0x64, 0x45, 0x64, 0x41, 0xBD, 0xD0, 0xA6, 0x46, 0x07, 0xF8, 0x86, 0xFA, 0x85, 0xF8, 0x60, 0x47, +- 0x08, 0xFA, 0x18, 0x60, 0x0F, 0xF1, 0x26, 0x46, 0x64, 0x41, 0x2F, 0x58, 0xFF, 0xFF, 0x2A, 0xF2, +- 0x2C, 0xF0, 0x31, 0x40, 0x20, 0x26, 0x09, 0x00, 0x60, 0x40, 0xA4, 0x36, 0x21, 0x00, 0x08, 0x26, +- 0x07, 0x00, 0x7D, 0xF1, 0xCF, 0x60, 0x47, 0x78, 0xFF, 0xFF, 0xCF, 0x60, 0x77, 0x78, 0xFF, 0xFF, +- 0x64, 0x40, 0x01, 0x26, 0x12, 0x00, 0x3F, 0xF0, 0x32, 0x40, 0x10, 0x2A, 0x0A, 0x00, 0x64, 0x41, +- 0x60, 0x40, 0x40, 0x27, 0x06, 0x00, 0xCD, 0x81, 0xDD, 0x81, 0x03, 0x03, 0x02, 0x03, 0x01, 0x61, +- 0x01, 0x00, 0x00, 0x61, 0x60, 0x40, 0x18, 0x3A, 0x03, 0x00, 0xCF, 0x60, 0xC9, 0x78, 0xFF, 0xFF, +- 0x07, 0xF2, 0x87, 0xF1, 0x66, 0x45, 0xD0, 0x80, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x03, 0x03, +- 0xFF, 0xFF, 0x02, 0x26, 0x07, 0x00, 0xDD, 0x60, 0x58, 0x4F, 0x90, 0x78, 0xFF, 0xFF, 0xCF, 0x60, +- 0xC5, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xA4, 0x3A, 0x07, 0x00, 0xDF, 0x60, +- 0x58, 0x4F, 0xE3, 0x78, 0xFF, 0xFF, 0xCF, 0x60, 0xC5, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0xCE, 0x60, +- 0x58, 0x4F, 0x54, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x06, 0x65, 0xD4, 0x80, 0x60, 0x43, 0x5B, 0x04, +- 0x00, 0xF4, 0xAA, 0x60, 0xAA, 0x65, 0x09, 0xF2, 0x0A, 0xF0, 0xD4, 0x80, 0x03, 0x64, 0x53, 0x02, +- 0xD0, 0x80, 0x00, 0x64, 0x0B, 0xF0, 0x4F, 0x02, 0x64, 0x45, 0xD4, 0x80, 0xF8, 0x7F, 0x08, 0x02, +- 0x0C, 0xF0, 0x26, 0x46, 0x64, 0x45, 0x23, 0xF0, 0x20, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x0B, 0x00, +- 0xD4, 0x80, 0x1D, 0x60, 0x60, 0x64, 0x11, 0x02, 0x0C, 0xF0, 0x26, 0x46, 0x64, 0x45, 0x23, 0xF0, +- 0x40, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x65, 0x44, 0x88, 0x3A, 0x35, 0x00, 0x77, 0x37, 0x03, 0x00, +- 0x78, 0x37, 0x01, 0x00, 0x8E, 0x37, 0x00, 0x61, 0x2E, 0x00, 0xD4, 0x80, 0x08, 0x65, 0x2B, 0x02, +- 0xD7, 0x80, 0x01, 0x60, 0x00, 0x64, 0x0C, 0xF0, 0x26, 0x04, 0xD0, 0x80, 0x0D, 0xF0, 0x23, 0x02, +- 0x26, 0x46, 0x14, 0xF2, 0x01, 0x63, 0x02, 0xA8, 0x64, 0x47, 0x1D, 0x03, 0x7F, 0xB4, 0xFD, 0xA0, +- 0x06, 0x03, 0x19, 0x07, 0x23, 0xF0, 0x60, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x6B, 0x00, 0x26, 0x46, +- 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x2A, 0x07, 0x00, 0x60, 0x40, 0x48, 0x36, 0x04, 0x00, +- 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0xE8, 0x60, 0x58, 0x4F, 0xEF, 0x78, 0xFF, 0xFF, +- 0xCF, 0x60, 0xC5, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x61, 0x40, 0x01, 0x2A, 0x09, 0x00, 0x25, 0x60, +- 0xFE, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0xCF, 0x60, 0xC9, 0x78, 0xFF, 0xFF, +- 0xDF, 0x60, 0x58, 0x4F, 0xE3, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0x36, +- 0x88, 0x00, 0xCF, 0x60, 0xD6, 0x78, 0xFF, 0xFF, 0xCF, 0x60, 0xC5, 0x78, 0xFF, 0xFF, 0x60, 0x40, +- 0x0C, 0x26, 0x7F, 0x00, 0x64, 0x40, 0x01, 0x2A, 0x7C, 0x00, 0xB0, 0x3A, 0x05, 0x00, 0xD4, 0x60, +- 0x58, 0x4F, 0x5A, 0x78, 0xFF, 0xFF, 0x71, 0x00, 0x00, 0x3A, 0x05, 0x00, 0xD7, 0x60, 0x58, 0x4F, +- 0xCA, 0x78, 0xFF, 0xFF, 0x6A, 0x00, 0x20, 0x3A, 0x05, 0x00, 0xD7, 0x60, 0x58, 0x4F, 0xCA, 0x78, +- 0xFF, 0xFF, 0x63, 0x00, 0xC0, 0x3A, 0x05, 0x00, 0xDC, 0x60, 0x58, 0x4F, 0xFE, 0x78, 0xFF, 0xFF, +- 0x5C, 0x00, 0xA0, 0x3A, 0x05, 0x00, 0xDD, 0x60, 0x58, 0x4F, 0x5B, 0x78, 0xFF, 0xFF, 0x55, 0x00, +- 0x40, 0x3A, 0x0D, 0x00, 0xE3, 0x60, 0x58, 0x4F, 0xC3, 0x78, 0xFF, 0xFF, 0x4E, 0x00, 0x60, 0x40, +- 0x50, 0x3A, 0x05, 0x00, 0xED, 0x60, 0x58, 0x4F, 0xEB, 0x78, 0xFF, 0xFF, 0x46, 0x00, 0xCF, 0x60, +- 0xC9, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x2A, 0x07, 0x00, +- 0x60, 0x40, 0x48, 0x36, 0x04, 0x00, 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0x2A, 0xF2, +- 0x3B, 0xF0, 0x60, 0x40, 0x40, 0x2B, 0x04, 0x00, 0x64, 0x40, 0x20, 0x2B, 0x01, 0x00, 0x03, 0x00, +- 0xCF, 0x60, 0xB9, 0x78, 0xFF, 0xFF, 0x22, 0xF2, 0xFF, 0xFF, 0x04, 0xB4, 0xFF, 0xFF, 0xF8, 0x03, +- 0x23, 0xF2, 0x07, 0xF4, 0xBB, 0xF0, 0x26, 0x46, 0xA4, 0x84, 0xFF, 0xFF, 0x60, 0x40, 0x2F, 0x26, +- 0x20, 0x00, 0xC9, 0x60, 0x58, 0x4F, 0xCF, 0x78, 0xFF, 0xFF, 0x64, 0x40, 0x18, 0x36, 0x09, 0x00, +- 0x04, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0xCF, 0x60, 0xC9, 0x78, +- 0xFF, 0xFF, 0x1F, 0x60, 0x04, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0x0C, 0x00, 0x66, 0x44, 0x00, 0xA8, 0xFF, 0xFF, +- 0x0A, 0x03, 0x26, 0x46, 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, +- 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xCE, 0x60, 0x35, 0x78, 0xFF, 0xFF, 0x14, 0xF2, 0x00, 0x7C, +- 0x3E, 0xF8, 0xCC, 0x84, 0xCC, 0x84, 0x18, 0x03, 0x5C, 0x02, 0x11, 0xF2, 0x07, 0xFA, 0xAB, 0xF3, +- 0x19, 0xFA, 0xD0, 0x60, 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xE0, 0x64, 0x0F, 0x60, +- 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, +- 0xF2, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x8D, 0x00, 0xA2, 0xFF, 0x46, 0x45, 0xB6, 0x60, 0x58, 0x4E, +- 0xBB, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x11, 0x03, 0x7E, 0x63, 0x46, 0x4B, 0x25, 0x46, 0xA3, 0xD0, +- 0x2B, 0x46, 0xA3, 0xD8, 0xFB, 0x1F, 0x89, 0xFC, 0x8A, 0xFC, 0x88, 0xFC, 0x05, 0x18, 0x64, 0x46, +- 0x01, 0xF0, 0x10, 0x67, 0xC0, 0x84, 0x01, 0xFA, 0x08, 0xFE, 0x2B, 0x46, 0x46, 0x46, 0x25, 0x46, +- 0xD0, 0x60, 0x58, 0x4E, 0x86, 0x78, 0xFF, 0xFF, 0x13, 0x60, 0x43, 0xF3, 0x87, 0xF3, 0x00, 0xA8, +- 0x07, 0xFA, 0x0E, 0x03, 0x1E, 0x60, 0xDA, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x25, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF3, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x0D, 0x00, +- 0x1E, 0x60, 0xCE, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xF4, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x26, 0x44, 0x00, 0xA8, 0xC1, 0xFE, +- 0x48, 0x03, 0x26, 0x46, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x2A, 0x07, 0x00, 0x60, 0x40, +- 0x48, 0x36, 0x04, 0x00, 0xD2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xD2, 0xFB, 0x26, 0x46, 0x2A, 0xF2, +- 0x3B, 0xF0, 0x60, 0x40, 0x40, 0x2B, 0x06, 0x00, 0xC0, 0x60, 0x00, 0x64, 0x64, 0x40, 0x20, 0x2B, +- 0x01, 0x00, 0x03, 0x00, 0xD0, 0x60, 0x73, 0x78, 0xFF, 0xFF, 0x22, 0xF2, 0xFF, 0xFF, 0x04, 0xB4, +- 0xFF, 0xFF, 0xF8, 0x03, 0x23, 0xF2, 0x07, 0xF4, 0xBB, 0xF0, 0x26, 0x46, 0xA4, 0x84, 0xFF, 0xFF, +- 0x60, 0x40, 0x2F, 0x26, 0x07, 0x00, 0xC9, 0x60, 0x58, 0x4F, 0xCF, 0x78, 0xFF, 0xFF, 0x64, 0x40, +- 0x18, 0x36, 0x09, 0x00, 0x04, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0xCF, 0x60, 0xC9, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0x04, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0xF1, 0x64, 0x3B, 0x42, +- 0x4A, 0xDB, 0x00, 0x66, 0x46, 0x46, 0xCF, 0x60, 0xC5, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x82, 0x60, +- 0xFF, 0x65, 0xA4, 0x87, 0x02, 0xBF, 0x2A, 0xFA, 0x1C, 0xF2, 0x13, 0xFA, 0x32, 0xF2, 0x2C, 0xFA, +- 0x33, 0xF2, 0x2D, 0xFA, 0x34, 0xF2, 0x2E, 0xFA, 0x2F, 0xF2, 0x32, 0xFA, 0x30, 0xF2, 0x33, 0xFA, +- 0x31, 0xF2, 0x34, 0xFA, 0x66, 0xF3, 0x2F, 0xFA, 0x67, 0xF3, 0x30, 0xFA, 0x68, 0xF3, 0x31, 0xFA, +- 0x2E, 0x58, 0xFF, 0xFF, 0xD3, 0x60, 0x59, 0x64, 0x08, 0x60, 0x26, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, +- 0xB1, 0xF3, 0x12, 0x60, 0x2C, 0x63, 0xF7, 0xA0, 0xFF, 0xFF, 0x02, 0x06, 0x00, 0x64, 0xB1, 0xFB, +- 0xB1, 0xF3, 0xB1, 0xFB, 0x01, 0xA4, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0x2A, 0xA3, 0xFB, 0x01, +- 0x63, 0x46, 0x10, 0x60, 0xA6, 0x63, 0x0E, 0x61, 0x60, 0xFE, 0xA6, 0xD1, 0xDE, 0x86, 0x01, 0x64, +- 0x64, 0x40, 0x7F, 0x36, 0x00, 0x64, 0xA3, 0xDB, 0xDB, 0x83, 0xA3, 0xD9, 0xCD, 0x81, 0x04, 0xA3, +- 0xF4, 0x02, 0x11, 0x60, 0x16, 0x63, 0x1C, 0x61, 0xA6, 0xD1, 0xDE, 0x86, 0x01, 0x64, 0x64, 0x40, +- 0x7F, 0x36, 0x00, 0x64, 0xA3, 0xDB, 0xDB, 0x83, 0xA3, 0xD9, 0xCD, 0x81, 0x06, 0xA3, 0xF4, 0x02, +- 0x20, 0xFE, 0x13, 0x60, 0x7F, 0xF3, 0x13, 0x60, 0x2D, 0xFB, 0x1E, 0x63, 0x26, 0x60, 0x64, 0x61, +- 0x27, 0x60, 0x08, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x13, 0x60, 0x95, 0xF3, 0x13, 0x60, +- 0x43, 0xFB, 0x13, 0x60, 0x96, 0xF3, 0x13, 0x60, 0x44, 0xFB, 0x13, 0x60, 0x9C, 0xF3, 0x13, 0x60, +- 0x4A, 0xFB, 0x13, 0x60, 0x9D, 0xF3, 0x13, 0x60, 0x4B, 0xFB, 0x13, 0x60, 0x9E, 0xF3, 0x13, 0x60, +- 0x4C, 0xFB, 0x13, 0x60, 0x9F, 0xF3, 0x13, 0x60, 0x4D, 0xFB, 0x13, 0x60, 0x97, 0xF3, 0x13, 0x60, +- 0x45, 0xFB, 0x13, 0x60, 0x98, 0xF3, 0x13, 0x60, 0x46, 0xFB, 0x13, 0x60, 0x99, 0xF3, 0x13, 0x60, +- 0x47, 0xFB, 0x26, 0x60, 0xB0, 0x63, 0xBD, 0xD1, 0xCB, 0xF9, 0x66, 0xF9, 0xBD, 0xD1, 0xCC, 0xF9, +- 0x67, 0xF9, 0xA3, 0xD1, 0xCD, 0xF9, 0x68, 0xF9, 0x01, 0x64, 0x6A, 0xFB, 0x13, 0x60, 0x51, 0xF3, +- 0xC4, 0xFB, 0x00, 0x63, 0x4A, 0xFD, 0x5A, 0xFD, 0x6B, 0xFD, 0x6C, 0xFD, 0x13, 0x60, 0x45, 0xF3, +- 0x15, 0x60, 0xCB, 0xF1, 0xFF, 0x60, 0xE7, 0x65, 0x32, 0x41, 0xA5, 0x81, 0xFF, 0xA0, 0xFF, 0xFF, +- 0x01, 0x03, 0x06, 0x00, 0x13, 0x60, 0x47, 0xF3, 0x08, 0xB9, 0x60, 0x40, 0x01, 0x26, 0x10, 0xB9, +- 0x41, 0x52, 0x87, 0xF5, 0x32, 0x44, 0x10, 0xB0, 0xFF, 0xFF, 0x0A, 0x03, 0x14, 0x60, 0x15, 0xF3, +- 0x06, 0xF0, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, 0xB0, 0x84, 0x06, 0xFA, +- 0x13, 0x60, 0x45, 0xF3, 0x22, 0x7C, 0xFF, 0xA0, 0xFD, 0xA0, 0x05, 0x06, 0x03, 0x03, 0xFE, 0xA0, +- 0x04, 0x7C, 0x01, 0x02, 0x3A, 0xF8, 0x13, 0x60, 0x4C, 0xF1, 0x20, 0x44, 0x20, 0xB5, 0x64, 0x41, +- 0x00, 0xB9, 0xD4, 0x84, 0x08, 0x28, 0x20, 0xBC, 0x40, 0x40, 0x15, 0x60, 0xCB, 0xF3, 0x30, 0x60, +- 0x0E, 0x63, 0xF0, 0x84, 0xF0, 0x84, 0xF0, 0x84, 0x02, 0xB5, 0xF0, 0x84, 0xF0, 0x84, 0x03, 0xB4, +- 0x65, 0x5C, 0xA3, 0xD9, 0x02, 0xA8, 0x18, 0x60, 0x08, 0xFB, 0x15, 0x02, 0x00, 0x60, 0xC8, 0x64, +- 0x18, 0x60, 0x09, 0xFB, 0x18, 0x60, 0x0D, 0xFB, 0x07, 0x60, 0xD0, 0x64, 0x18, 0x60, 0x0A, 0xFB, +- 0x18, 0x60, 0x0E, 0xFB, 0x01, 0x60, 0x90, 0x64, 0x18, 0x60, 0x0B, 0xFB, 0x00, 0x60, 0x64, 0x64, +- 0x18, 0x60, 0x0C, 0xFB, 0x06, 0x00, 0x64, 0x64, 0x18, 0x60, 0x0B, 0xFB, 0x64, 0x64, 0x18, 0x60, +- 0x0C, 0xFB, 0xB1, 0xF1, 0x10, 0x60, 0xA0, 0x63, 0x2F, 0x18, 0x60, 0x40, 0x01, 0x27, 0x12, 0x00, +- 0xCC, 0x84, 0x06, 0xA3, 0xFD, 0x02, 0xA3, 0xD3, 0x10, 0x60, 0xA6, 0x63, 0x25, 0x1B, 0x10, 0x60, +- 0xF8, 0x65, 0xA3, 0xD3, 0x06, 0xA3, 0xD7, 0x80, 0x02, 0x1B, 0xFB, 0x04, 0x1D, 0x00, 0xF8, 0xA3, +- 0xA3, 0xD3, 0x18, 0x00, 0x11, 0x60, 0x14, 0x63, 0x11, 0x60, 0xF4, 0x65, 0xA3, 0xD1, 0x08, 0xA3, +- 0xD0, 0x80, 0xD7, 0x80, 0x02, 0x03, 0xFA, 0x04, 0x0F, 0x00, 0xFA, 0xA3, 0xA3, 0xD3, 0x11, 0x60, +- 0x16, 0x63, 0x0A, 0x1B, 0xA3, 0xD3, 0x08, 0xA3, 0xD7, 0x80, 0x02, 0x1B, 0xFB, 0x04, 0x04, 0x00, +- 0xF6, 0xA3, 0xA3, 0xD3, 0xC5, 0xFB, 0x64, 0xFB, 0x27, 0x60, 0x34, 0x64, 0x26, 0x60, 0x90, 0x63, +- 0xA0, 0xD1, 0xA3, 0xD9, 0x64, 0x41, 0x58, 0xD1, 0x5B, 0xD9, 0x64, 0xF3, 0xFF, 0xFF, 0x60, 0x40, +- 0x01, 0x2B, 0x03, 0x00, 0xD1, 0x60, 0xE9, 0x78, 0xFF, 0xFF, 0x91, 0xFA, 0x61, 0x44, 0xEF, 0x60, +- 0x58, 0x4E, 0xAB, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x15, 0x60, 0xBC, 0xF3, 0x3F, 0x40, 0x01, 0x27, +- 0x08, 0x00, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xEE, 0x60, 0x58, 0x4E, 0x26, 0x78, 0xFF, 0xFF, +- 0x06, 0x00, 0x0F, 0x65, 0xA4, 0x84, 0xEE, 0x60, 0x58, 0x4E, 0x26, 0x78, 0xFF, 0xFF, 0x00, 0x65, +- 0xEE, 0x60, 0x58, 0x4E, 0xC6, 0x78, 0xFF, 0xFF, 0xEF, 0x60, 0x58, 0x4E, 0x10, 0x78, 0xFF, 0xFF, +- 0x15, 0x00, 0x11, 0xF8, 0x64, 0x44, 0xEF, 0x60, 0x58, 0x4E, 0xAB, 0x78, 0xFF, 0xFF, 0x12, 0xFA, +- 0x15, 0x60, 0xBD, 0xF3, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xEE, 0x60, 0x58, 0x4E, 0x26, 0x78, +- 0xFF, 0xFF, 0xFF, 0x65, 0xEE, 0x60, 0x58, 0x4E, 0xC6, 0x78, 0xFF, 0xFF, 0xB5, 0xF1, 0x09, 0x60, +- 0x2A, 0x64, 0xD0, 0x80, 0x03, 0x64, 0x01, 0x06, 0x06, 0x64, 0xAE, 0xFB, 0x46, 0x48, 0xC3, 0xF3, +- 0xFF, 0xFF, 0x60, 0x40, 0x05, 0x3A, 0x03, 0x00, 0x14, 0x60, 0x00, 0x66, 0x11, 0x00, 0x04, 0x3A, +- 0x03, 0x00, 0x13, 0x60, 0xF4, 0x66, 0x0C, 0x00, 0x03, 0x3A, 0x03, 0x00, 0x13, 0x60, 0xE8, 0x66, +- 0x07, 0x00, 0x02, 0x3A, 0x03, 0x00, 0x13, 0x60, 0xDC, 0x66, 0x02, 0x00, 0x13, 0x60, 0xD0, 0x66, +- 0x60, 0xFE, 0xA6, 0xD3, 0xDE, 0x86, 0x10, 0x60, 0x5F, 0xFB, 0xA6, 0xD3, 0xDE, 0x86, 0x21, 0x60, +- 0x2F, 0x63, 0xA3, 0xDB, 0x21, 0x60, 0xA7, 0x63, 0xA3, 0xDB, 0xA6, 0xD3, 0xDE, 0x86, 0x10, 0x60, +- 0x5E, 0xFB, 0xA6, 0xD3, 0xDE, 0x86, 0x20, 0x60, 0xBF, 0x63, 0xA3, 0xDB, 0x20, 0xFE, 0xA6, 0xD3, +- 0xDA, 0x86, 0x60, 0x43, 0x1F, 0xB3, 0x63, 0x5C, 0x1F, 0x60, 0x00, 0xB4, 0xE8, 0x84, 0xE8, 0x84, +- 0xE8, 0x84, 0xB0, 0x85, 0x10, 0x60, 0x95, 0xF3, 0xFF, 0xFF, 0xFC, 0x60, 0x00, 0xB4, 0xB4, 0x84, +- 0xA2, 0xDB, 0x10, 0x60, 0xD1, 0xFB, 0x21, 0x60, 0xCA, 0x63, 0xA3, 0xD3, 0xA6, 0xD1, 0xDE, 0x86, +- 0x80, 0x60, 0x7F, 0xB5, 0x64, 0x44, 0xE8, 0x84, 0x7F, 0x60, 0x80, 0xB4, 0xB4, 0x84, 0xA3, 0xDB, +- 0x60, 0xFE, 0xA6, 0xD3, 0xDE, 0x86, 0x10, 0x60, 0x62, 0xFB, 0x20, 0xFE, 0x10, 0x60, 0x2A, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, +- 0xD2, 0x60, 0x5E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x64, 0xF1, 0x0F, 0x60, +- 0x9D, 0xF9, 0x0C, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x44, 0x01, 0x65, 0x34, 0x80, +- 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD2, 0x60, 0x82, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x64, 0xF1, 0x0F, 0x60, +- 0x9D, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, +- 0x16, 0xFB, 0xD2, 0x60, 0x97, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, +- 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x08, 0x60, 0x11, 0xF1, 0x40, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xBE, 0xFE, 0x08, 0x60, 0x11, 0xF1, 0x40, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x20, 0x40, 0x20, 0x2A, 0x04, 0x00, 0xF0, 0x60, 0x58, 0x4E, +- 0x66, 0x78, 0xFF, 0xFF, 0x36, 0x40, 0x08, 0x3A, 0x6A, 0x00, 0x36, 0x40, 0x08, 0x3A, 0x05, 0x00, +- 0x10, 0x60, 0x42, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x04, 0x00, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x4E, 0xF3, 0xFF, 0xFF, 0x1D, 0x1B, 0x13, 0x60, 0x54, 0xF3, 0xC7, 0xFB, 0x26, 0x60, +- 0x16, 0x65, 0x26, 0x60, 0xB8, 0x61, 0x26, 0x60, 0x14, 0x64, 0x20, 0x63, 0x59, 0xD1, 0x58, 0xD9, +- 0xA5, 0xD9, 0xDA, 0x85, 0xFB, 0x1F, 0x00, 0x60, 0x01, 0x64, 0x08, 0x60, 0x22, 0xFB, 0xD3, 0x60, +- 0x3C, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x36, 0x40, 0x08, 0x3A, 0x41, 0x00, 0xE7, 0x60, 0xC5, 0x78, +- 0xFF, 0xFF, 0x27, 0x60, 0x3E, 0x63, 0x60, 0x41, 0x00, 0x62, 0xCD, 0x81, 0x04, 0xA2, 0xFD, 0x02, +- 0x2C, 0x60, 0x3E, 0x61, 0xFC, 0xA2, 0x62, 0x45, 0xC5, 0x81, 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x85, +- 0xC7, 0x83, 0xFE, 0xA5, 0x88, 0xF3, 0xFF, 0xFF, 0xC4, 0x84, 0x66, 0x45, 0x60, 0x46, 0xBD, 0xD1, +- 0x03, 0xF8, 0xBD, 0xD1, 0x04, 0xF8, 0xA3, 0xD1, 0x05, 0xF8, 0x06, 0xF2, 0xFF, 0xFF, 0x02, 0x7E, +- 0x06, 0xFA, 0x64, 0xF3, 0x61, 0x43, 0x60, 0x40, 0x01, 0x27, 0x02, 0xA3, 0xA3, 0xD1, 0x0F, 0xF8, +- 0x16, 0x64, 0x12, 0xFA, 0x01, 0x64, 0x11, 0xFA, 0x66, 0x5C, 0xC1, 0x60, 0x58, 0x4E, 0x93, 0x78, +- 0xFF, 0xFF, 0x66, 0x43, 0x32, 0x40, 0x08, 0x2A, 0x0A, 0x00, 0x14, 0x60, 0x15, 0xF3, 0x06, 0xF0, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, 0xB0, 0x84, 0x06, 0xFA, 0xC5, 0xFE, +- 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, 0x16, 0xFB, +- 0xD2, 0x60, 0xB5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x03, 0x64, 0x08, 0x60, 0x22, 0xFB, 0xD2, 0x60, 0xB5, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x42, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x0F, 0x4E, 0xE1, 0x60, 0x58, 0x4F, 0xA9, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x4E, 0xDF, 0x60, +- 0x58, 0x4F, 0x0F, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x4E, 0xDE, 0x60, 0x58, 0x4F, 0x9A, 0x78, +- 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x4E, 0xDD, 0x60, 0x58, 0x4F, 0xFB, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, +- 0xD5, 0x01, 0x4E, 0xF3, 0x7D, 0xF5, 0x60, 0x40, 0xFF, 0x22, 0x0A, 0x00, 0x88, 0xF1, 0xCC, 0x84, +- 0xE0, 0x84, 0xC0, 0x86, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x7D, 0xF5, 0x07, 0x00, +- 0x08, 0x60, 0x24, 0xF1, 0x00, 0x60, 0x11, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x4E, 0xF3, +- 0x66, 0x40, 0xFF, 0x22, 0x05, 0x00, 0xFF, 0x22, 0x39, 0x00, 0xD4, 0x60, 0x0C, 0x78, 0xFF, 0xFF, +- 0x02, 0x64, 0x69, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x69, 0xF3, 0x00, 0x65, 0xD4, 0x80, 0x4E, 0xF3, +- 0x0E, 0x03, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, +- 0x16, 0xFB, 0xD3, 0x60, 0x7C, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, +- 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, +- 0x16, 0xFB, 0xD3, 0x60, 0x8F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xD3, 0xF3, +- 0xFF, 0xFF, 0xFE, 0xB4, 0xD3, 0xFB, 0x1F, 0x60, 0x3A, 0x62, 0x06, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x2D, 0xFF, 0x20, 0x44, 0x01, 0xB5, 0x54, 0x80, 0xDA, 0xFE, 0xBE, 0xFE, 0x87, 0xF1, 0x02, 0x64, +- 0x86, 0xF3, 0xC0, 0x83, 0x40, 0x48, 0x75, 0xFD, 0xE7, 0x60, 0x58, 0x4E, 0x81, 0x78, 0xFF, 0xFF, +- 0x28, 0x44, 0x4C, 0x88, 0x75, 0xF3, 0x02, 0x65, 0xC4, 0x83, 0xF5, 0x02, 0x1E, 0x60, 0x58, 0x4E, +- 0xB9, 0x78, 0xFF, 0xFF, 0x17, 0x60, 0x06, 0x64, 0x0B, 0x60, 0x82, 0xFB, 0x4A, 0xDF, 0x01, 0x60, +- 0xFE, 0x63, 0x15, 0x60, 0x00, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, 0x7D, 0xF1, 0x1E, 0x60, +- 0xE0, 0x61, 0x64, 0x40, 0xFF, 0x26, 0x38, 0x00, 0xD4, 0x60, 0x58, 0x4E, 0x0F, 0x78, 0xFF, 0xFF, +- 0x1E, 0x60, 0xCE, 0x61, 0xD4, 0x60, 0x58, 0x4E, 0x0F, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xD4, 0x61, +- 0xD4, 0x60, 0x58, 0x4E, 0x0F, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xE6, 0x61, 0xD4, 0x60, 0x58, 0x4E, +- 0x0F, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xEC, 0x61, 0xD4, 0x60, 0x58, 0x4E, 0x0F, 0x78, 0xFF, 0xFF, +- 0x1E, 0x60, 0xF8, 0x61, 0xD4, 0x60, 0x58, 0x4E, 0x0F, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0x04, 0x61, +- 0xD4, 0x60, 0x58, 0x4E, 0x0F, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xF2, 0x61, 0xD4, 0x60, 0x58, 0x4E, +- 0x0F, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xDA, 0x61, 0xD4, 0x60, 0x58, 0x4E, 0x3A, 0x78, 0xFF, 0xFF, +- 0x00, 0x64, 0x08, 0x60, 0x15, 0xFB, 0x5A, 0xDB, 0xC5, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xA1, 0xD3, +- 0x0E, 0x57, 0x23, 0x00, 0x0E, 0xF2, 0x44, 0x4C, 0x80, 0xB0, 0x10, 0xB0, 0x0A, 0x03, 0x00, 0x64, +- 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0x13, 0x00, 0x12, 0x02, 0xF0, 0x37, 0x09, 0x00, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, +- 0xA2, 0xFF, 0x8F, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0x8F, 0xFB, 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, +- 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, 0x2C, 0x44, 0xAC, 0x86, 0x09, 0xF0, 0xDA, 0x02, +- 0x37, 0x58, 0xFF, 0xFF, 0xA1, 0xD3, 0x0E, 0x57, 0x18, 0x00, 0x0E, 0xF2, 0x44, 0x4C, 0x80, 0xB0, +- 0x10, 0xB0, 0x0A, 0x03, 0x00, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x08, 0x00, 0x07, 0x02, 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, +- 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, 0x2C, 0x44, 0xAC, 0x86, 0x09, 0xF0, 0xE5, 0x02, +- 0x37, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xB0, 0x64, 0x2A, 0xFA, 0x2F, 0xF2, +- 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0xCC, 0xF3, +- 0x30, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, 0x66, 0xF3, 0x32, 0xFA, 0x67, 0xF3, 0x33, 0xFA, 0x68, 0xF3, +- 0x34, 0xFA, 0xAB, 0xF1, 0x19, 0xF8, 0x06, 0x63, 0x3F, 0xFC, 0x1C, 0xF2, 0x13, 0xFA, 0x00, 0x64, +- 0x3E, 0xFA, 0x07, 0xF2, 0x87, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x0C, 0x03, 0x60, 0x46, +- 0x06, 0xF2, 0x26, 0x46, 0x01, 0xB0, 0xFF, 0xFF, 0x03, 0x02, 0xD6, 0x60, 0x40, 0x78, 0xFF, 0xFF, +- 0xD7, 0x60, 0x92, 0x78, 0xFF, 0xFF, 0x00, 0xF4, 0x0A, 0xF2, 0x09, 0xF2, 0xFF, 0xA0, 0x00, 0xA0, +- 0x13, 0x02, 0xFF, 0xA0, 0x04, 0x03, 0x08, 0x03, 0xD4, 0x60, 0xAF, 0x78, 0xFF, 0xFF, 0x02, 0x64, +- 0x55, 0xFB, 0xD4, 0x60, 0xBA, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0x32, 0x40, 0x08, 0x2A, 0x0F, 0x00, +- 0x55, 0xFD, 0xD4, 0x60, 0xBA, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x0A, 0xF2, 0x0E, 0x63, +- 0x01, 0xA4, 0x0A, 0xFA, 0x0B, 0xFC, 0x43, 0x59, 0xD7, 0x60, 0x6C, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x00, 0xF4, 0x0A, 0xF2, 0x0D, 0x63, 0x01, 0xA4, 0x0A, 0xFA, 0x0B, 0xFC, 0x43, 0x59, 0xD7, 0x60, +- 0x6C, 0x78, 0xFF, 0xFF, 0x87, 0xF5, 0x00, 0xF2, 0x26, 0x46, 0x00, 0xA0, 0x2E, 0xF0, 0x37, 0x03, +- 0x66, 0x41, 0x15, 0x60, 0x02, 0x65, 0x64, 0x47, 0x00, 0x7F, 0x87, 0xF1, 0xE0, 0x84, 0x44, 0xD3, +- 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, +- 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, +- 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, +- 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, 0x86, 0xF1, +- 0x17, 0x60, 0x02, 0x61, 0xA1, 0xD3, 0xDA, 0x81, 0xD0, 0x80, 0xDC, 0x9C, 0x05, 0x05, 0xA1, 0xD3, +- 0x4A, 0xD9, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0xD6, 0x60, 0x09, 0x78, 0xFF, 0xFF, 0x0B, 0x60, +- 0x81, 0xF3, 0xFF, 0xFF, 0x62, 0x18, 0x17, 0x60, 0x02, 0x64, 0x04, 0xA5, 0xA0, 0xD1, 0x72, 0x44, +- 0xFF, 0xB4, 0x64, 0x40, 0xE0, 0x22, 0x1F, 0xB4, 0x64, 0x40, 0xF8, 0x22, 0x07, 0xB4, 0x02, 0x00, +- 0x03, 0x04, 0xD0, 0x84, 0xD0, 0x80, 0xFC, 0x01, 0xE0, 0x84, 0x44, 0xD3, 0xFF, 0xFF, 0x60, 0x43, +- 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, +- 0x07, 0x1B, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, +- 0x65, 0x46, 0x00, 0xF8, 0x87, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, +- 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, +- 0x06, 0xFA, 0x61, 0x46, 0x2E, 0xF0, 0x66, 0x41, 0x15, 0x60, 0x02, 0x65, 0x64, 0x47, 0x00, 0x7F, +- 0x87, 0xF1, 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, +- 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, +- 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, +- 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, +- 0x60, 0x43, 0x61, 0x46, 0xD6, 0x60, 0x09, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x02, 0x61, 0xB5, 0x60, +- 0x58, 0x4D, 0xA2, 0x78, 0xFF, 0xFF, 0x86, 0xF1, 0x72, 0x44, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, +- 0x02, 0x04, 0xD0, 0x84, 0xFB, 0x01, 0xE0, 0x83, 0x87, 0xF3, 0x02, 0xA3, 0x43, 0x93, 0x66, 0x44, +- 0x00, 0xA8, 0x56, 0xFD, 0x3A, 0x03, 0x00, 0x64, 0x2B, 0xFA, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, +- 0x66, 0x45, 0x63, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x85, 0xF2, 0x65, 0x46, 0x2C, 0xFA, 0x2D, 0xF8, +- 0xAE, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0x32, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0x33, 0xFA, 0xCD, 0xF3, +- 0x31, 0xFA, 0x34, 0xFA, 0xAB, 0xF1, 0x19, 0xF8, 0xFF, 0x67, 0x0E, 0xFA, 0x66, 0x41, 0x43, 0x49, +- 0x29, 0x46, 0x92, 0xF0, 0x2C, 0x60, 0x26, 0x63, 0x47, 0xD3, 0x61, 0x46, 0x02, 0x63, 0x00, 0x7E, +- 0x13, 0xFA, 0x3F, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0x87, 0xF3, 0x07, 0xFA, 0x66, 0x41, 0x00, 0xF4, +- 0x05, 0x64, 0x09, 0xFA, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x61, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x56, 0xF3, 0xA3, 0xFF, 0x60, 0x43, +- 0xE7, 0x60, 0x58, 0x4E, 0x81, 0x78, 0xFF, 0xFF, 0x56, 0xF3, 0xFF, 0xFF, 0x40, 0x58, 0x03, 0x65, +- 0xE5, 0x60, 0x58, 0x4E, 0x51, 0x78, 0xFF, 0xFF, 0x56, 0xF3, 0x26, 0x46, 0x60, 0x43, 0x66, 0x41, +- 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, +- 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, +- 0x00, 0xF8, 0x87, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, +- 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, +- 0x61, 0x46, 0x2E, 0xF0, 0x66, 0x41, 0x15, 0x60, 0x02, 0x65, 0x64, 0x47, 0x00, 0x7F, 0x87, 0xF1, +- 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, +- 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, +- 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, +- 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, +- 0x61, 0x46, 0x2C, 0xF2, 0x2D, 0xF0, 0xAE, 0xF2, 0x66, 0x45, 0x63, 0x46, 0x03, 0xFA, 0x04, 0xF8, +- 0x55, 0xF3, 0x85, 0xFA, 0xFF, 0xA0, 0x65, 0x46, 0x03, 0x03, 0xD7, 0x60, 0xAE, 0x78, 0xFF, 0xFF, +- 0x94, 0xF3, 0x66, 0x45, 0x63, 0x46, 0x1F, 0xFA, 0x65, 0x46, 0xBA, 0x65, 0x60, 0x44, 0xC4, 0x85, +- 0x01, 0x60, 0xFE, 0x61, 0x00, 0x64, 0x80, 0x63, 0xC7, 0x85, 0x94, 0x84, 0x59, 0xDB, 0xFC, 0x1F, +- 0x00, 0x60, 0x88, 0x64, 0x3F, 0xFA, 0x00, 0xF4, 0x02, 0x64, 0x0A, 0xFA, 0x00, 0x64, 0x0B, 0xFA, +- 0x80, 0x7F, 0x10, 0x7E, 0x0C, 0xFA, 0x1A, 0x65, 0x80, 0x61, 0x02, 0x60, 0x00, 0x63, 0x0F, 0x4E, +- 0xF8, 0x60, 0x58, 0x4F, 0x7A, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0xD7, 0x60, 0x80, 0x78, 0xFF, 0xFF, +- 0x26, 0x46, 0x23, 0xF0, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x00, 0xF4, 0x03, 0x03, 0xD7, 0x60, +- 0x2A, 0x78, 0xFF, 0xFF, 0x09, 0xF2, 0xFF, 0xFF, 0xFF, 0xA0, 0x00, 0xA0, 0x0C, 0x03, 0x03, 0x03, +- 0xD6, 0x60, 0xA7, 0x78, 0xFF, 0xFF, 0x0A, 0xF2, 0x26, 0x46, 0xFF, 0xA0, 0x87, 0xF4, 0x10, 0x02, +- 0xD7, 0x60, 0xAE, 0x78, 0xFF, 0xFF, 0x0A, 0xF2, 0xFF, 0xFF, 0xFF, 0xA0, 0xFD, 0xA0, 0x02, 0x03, +- 0x04, 0x03, 0x06, 0x00, 0xD6, 0x60, 0xE6, 0x78, 0xFF, 0xFF, 0xD6, 0x60, 0xF1, 0x78, 0xFF, 0xFF, +- 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, +- 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0x87, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, +- 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, +- 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x0B, 0x60, 0x82, 0xF3, 0xDA, 0x81, 0x60, 0x45, +- 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, +- 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x17, 0x60, 0x04, 0x62, 0x65, 0x44, 0xA2, 0xDB, +- 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0xD4, 0x60, 0xA4, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, +- 0x81, 0xF8, 0x07, 0x1B, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, +- 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0x87, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, +- 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, +- 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x0B, 0x60, 0x82, 0xF3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, +- 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, +- 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x17, 0x60, 0x04, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, +- 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0xD4, 0x60, 0xAF, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x32, 0x44, +- 0x08, 0xB0, 0x87, 0xF4, 0x03, 0x02, 0xD4, 0x60, 0xAF, 0x78, 0xFF, 0xFF, 0xD6, 0x60, 0x18, 0x78, +- 0xFF, 0xFF, 0x32, 0x44, 0x26, 0x46, 0x08, 0xB0, 0x07, 0xF2, 0x03, 0x02, 0xD4, 0x60, 0xAF, 0x78, +- 0xFF, 0xFF, 0x60, 0x46, 0x1F, 0xF2, 0x26, 0x46, 0xBA, 0x65, 0x60, 0x44, 0xC4, 0x85, 0x01, 0x60, +- 0xFE, 0x61, 0x00, 0x64, 0x80, 0x63, 0xC7, 0x85, 0x94, 0x84, 0x59, 0xDB, 0xFC, 0x1F, 0x00, 0xF4, +- 0x01, 0x60, 0xFE, 0x61, 0x7E, 0x65, 0x18, 0x63, 0x5B, 0xD2, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, +- 0xD7, 0x80, 0x18, 0x02, 0xF9, 0x02, 0x00, 0xF4, 0x02, 0x63, 0x0E, 0x65, 0x5B, 0xD2, 0x59, 0xD1, +- 0xFF, 0xFF, 0xD0, 0x80, 0xD7, 0x80, 0x0E, 0x02, 0xF9, 0x02, 0x26, 0x46, 0x07, 0xF4, 0x06, 0xF2, +- 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x26, 0x46, 0x00, 0xF4, 0x04, 0x64, 0x0A, 0xFA, 0x00, 0x64, +- 0x0B, 0xFA, 0x56, 0x00, 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, +- 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0x87, 0xF3, 0x63, 0x45, +- 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, +- 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x0B, 0x60, 0x82, 0xF3, +- 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, +- 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x17, 0x60, 0x04, 0x62, +- 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0x00, 0xF4, 0x04, 0x64, +- 0x0A, 0xFA, 0x0F, 0x64, 0x0B, 0xFA, 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x41, 0x58, 0x26, 0x46, +- 0x2C, 0xF2, 0xA1, 0xDB, 0x2D, 0xF2, 0x59, 0xDB, 0x2E, 0xF2, 0x59, 0xDB, 0x03, 0x65, 0xE5, 0x60, +- 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x03, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x51, 0x78, 0xFF, 0xFF, +- 0x26, 0x46, 0x87, 0xF3, 0x07, 0xFA, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, +- 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0xF4, 0x0A, 0xF2, 0x09, 0xF2, 0xFF, 0xA0, 0x00, 0xA0, 0x06, 0x02, +- 0xFF, 0xA0, 0x07, 0x03, 0x09, 0x03, 0xD6, 0x60, 0xA7, 0x78, 0xFF, 0xFF, 0xD6, 0x60, 0x68, 0x78, +- 0xFF, 0xFF, 0xD7, 0x60, 0xB3, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x07, 0xF4, 0x06, 0xF2, 0x66, 0x43, +- 0x00, 0x7E, 0x06, 0xFA, 0x26, 0x46, 0xD6, 0x60, 0x18, 0x78, 0xFF, 0xFF, 0x63, 0x46, 0x06, 0xF2, +- 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x26, 0x46, 0x87, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x02, 0x64, +- 0x0A, 0xFA, 0x00, 0x64, 0x0B, 0xFA, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, +- 0x2F, 0x58, 0xFF, 0xFF, 0x01, 0x61, 0x00, 0x60, 0x10, 0x7C, 0x2A, 0xF2, 0x0C, 0x60, 0x70, 0xFB, +- 0xFF, 0xB4, 0x16, 0x60, 0x83, 0xFB, 0x60, 0x40, 0x00, 0x36, 0x03, 0x00, 0x02, 0x61, 0x00, 0x60, +- 0x30, 0x7C, 0x41, 0x47, 0x2A, 0xF8, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, +- 0x2E, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, 0x66, 0xF3, +- 0x32, 0xFA, 0x67, 0xF3, 0x33, 0xFA, 0x68, 0xF3, 0x34, 0xFA, 0xAB, 0xF1, 0x19, 0xF8, 0x00, 0x7C, +- 0x3E, 0xF8, 0x1C, 0xF0, 0x13, 0xF8, 0x07, 0xF2, 0x87, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, +- 0x03, 0x02, 0xDC, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x40, 0x4B, 0x01, 0x65, 0xEF, 0x60, 0x58, 0x4E, +- 0xDC, 0x78, 0xFF, 0xFF, 0xAB, 0x46, 0x06, 0xF2, 0xAB, 0x46, 0x00, 0xF4, 0x01, 0xB0, 0xFF, 0xFF, +- 0x03, 0x02, 0xDC, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x09, 0xF2, 0x16, 0x60, 0x84, 0xFB, 0x5A, 0x84, +- 0x00, 0x63, 0x60, 0x40, 0x20, 0x26, 0x02, 0xBB, 0x60, 0x40, 0x04, 0x27, 0x04, 0xBB, 0xAB, 0x46, +- 0x78, 0xFC, 0xAB, 0x46, 0xFF, 0xFF, 0x10, 0xB0, 0x80, 0x60, 0x00, 0x63, 0x0C, 0x03, 0x13, 0x60, +- 0x45, 0xF1, 0xFF, 0xFF, 0x64, 0x44, 0xFE, 0x26, 0x08, 0x00, 0x32, 0x40, 0x08, 0x26, 0x06, 0x00, +- 0xDC, 0x60, 0xB9, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x10, 0x2A, 0x00, 0x63, 0xAB, 0x46, 0x06, 0xF0, +- 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0x63, 0x45, 0xB4, 0x84, 0x06, 0xFA, 0xAB, 0x46, 0x0A, 0xF0, +- 0x56, 0xF9, 0x24, 0xD9, 0x5A, 0x84, 0x01, 0x63, 0x32, 0x40, 0x10, 0x26, 0x10, 0xBB, 0x13, 0x60, +- 0x45, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0xFE, 0x26, 0x10, 0xBB, 0x15, 0x60, 0xDD, 0xF1, 0x63, 0x44, +- 0x20, 0xBC, 0xFB, 0x60, 0xFF, 0xB7, 0x64, 0x40, 0x10, 0x26, 0x04, 0xBC, 0x60, 0x47, 0x60, 0x43, +- 0x09, 0xFC, 0x27, 0x44, 0xFE, 0xA0, 0xFF, 0xFF, 0x03, 0x03, 0xD8, 0x60, 0xC8, 0x78, 0xFF, 0xFF, +- 0x18, 0x60, 0xD6, 0x64, 0x24, 0x43, 0x0B, 0xF0, 0xA0, 0xD9, 0xBD, 0xD9, 0x0C, 0xF0, 0x58, 0xD9, +- 0xBD, 0xD9, 0x0D, 0xF0, 0x58, 0xD9, 0xBD, 0xD9, 0x43, 0x44, 0x26, 0x46, 0x87, 0xF2, 0x3F, 0xF2, +- 0x41, 0x4B, 0x00, 0xF4, 0x60, 0x43, 0xF6, 0xA3, 0x00, 0x60, 0x1B, 0x61, 0x00, 0x60, 0x01, 0x65, +- 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xEF, 0x60, 0x58, 0x4E, 0x79, 0x78, 0xFF, 0xFF, 0x00, 0xBB, +- 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x64, 0x40, 0x4A, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, +- 0xBD, 0xD3, 0x60, 0x41, 0xF0, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x20, 0xFE, 0x26, 0x46, +- 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF6, 0xA3, 0x00, 0x60, 0x1B, 0x61, 0x00, 0x60, 0x32, 0x65, +- 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xEF, 0x60, 0x58, 0x4E, 0x79, 0x78, 0xFF, 0xFF, 0x00, 0xBB, +- 0xFF, 0xFF, 0x0B, 0x03, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, +- 0xF0, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0xFE, 0x30, 0x60, 0x20, 0x61, +- 0xA1, 0xD1, 0x82, 0xF3, 0x01, 0x60, 0x6E, 0x63, 0x60, 0x45, 0x2A, 0x44, 0x60, 0xFB, 0xA3, 0xD5, +- 0x65, 0x40, 0x01, 0x27, 0x5B, 0xD5, 0x65, 0x40, 0x01, 0x27, 0x59, 0xD1, 0x66, 0x41, 0xA0, 0x84, +- 0x24, 0x94, 0x2B, 0x46, 0x0F, 0xFA, 0x61, 0xFB, 0x16, 0x64, 0x12, 0xFA, 0x01, 0x64, 0x11, 0xFA, +- 0x66, 0x5C, 0xC1, 0x60, 0x58, 0x4E, 0x93, 0x78, 0xFF, 0xFF, 0xD9, 0x60, 0x28, 0x78, 0xFF, 0xFF, +- 0x26, 0x46, 0x87, 0xF2, 0x3F, 0xF2, 0x41, 0x4B, 0x00, 0xF4, 0x60, 0x43, 0xFC, 0xA3, 0x00, 0x60, +- 0x15, 0x61, 0x00, 0x60, 0x01, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xEF, 0x60, 0x58, 0x4E, +- 0x79, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x64, 0x40, 0x4A, 0x60, 0xFE, +- 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xF0, 0x60, 0x58, 0x4E, 0x27, 0x78, +- 0xFF, 0xFF, 0x20, 0xFE, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xFC, 0xA3, 0x00, 0x60, +- 0x15, 0x61, 0x00, 0x60, 0x32, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xEF, 0x60, 0x58, 0x4E, +- 0x79, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x0B, 0x03, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, +- 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xF0, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x00, 0x00, +- 0x20, 0xFE, 0x30, 0x60, 0x20, 0x61, 0xA1, 0xD1, 0x82, 0xF3, 0x01, 0x60, 0x6E, 0x63, 0x60, 0x45, +- 0x2A, 0x44, 0x60, 0xFB, 0xA3, 0xD5, 0x65, 0x40, 0x01, 0x27, 0x5B, 0xD5, 0x65, 0x40, 0x01, 0x27, +- 0x59, 0xD1, 0x66, 0x41, 0xA0, 0x84, 0x24, 0x94, 0x2B, 0x46, 0x0F, 0xFA, 0x61, 0xFB, 0x16, 0x64, +- 0x12, 0xFA, 0x01, 0x64, 0x11, 0xFA, 0x66, 0x5C, 0xC1, 0x60, 0x58, 0x4E, 0x93, 0x78, 0xFF, 0xFF, +- 0x2B, 0x46, 0x0F, 0xF2, 0x12, 0x63, 0x7C, 0x18, 0x26, 0x46, 0x87, 0xF2, 0x01, 0x65, 0x41, 0x4B, +- 0xAB, 0x46, 0x0F, 0xF2, 0xFF, 0xFF, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xFF, 0x22, +- 0x00, 0x65, 0x78, 0xF2, 0xFF, 0xFF, 0xB4, 0x84, 0x78, 0xFA, 0xAB, 0x46, 0xFF, 0xFF, 0x26, 0x46, +- 0x3F, 0xF2, 0x00, 0xF4, 0x16, 0x65, 0x27, 0x40, 0x02, 0x3A, 0x03, 0x00, 0x1C, 0x65, 0xF6, 0xA4, +- 0x01, 0x00, 0xFC, 0xA4, 0x24, 0x43, 0x2D, 0x60, 0x5E, 0x61, 0x5D, 0x91, 0x51, 0x90, 0xFF, 0xFF, +- 0x04, 0x28, 0x60, 0x41, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, +- 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, +- 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x2D, 0x60, 0x04, 0x7C, 0x03, 0x1E, 0x60, 0xFE, +- 0xBD, 0xDF, 0x20, 0xFE, 0x2D, 0x60, 0x08, 0x64, 0x53, 0x93, 0xA4, 0xDD, 0x26, 0x46, 0x00, 0xF4, +- 0x13, 0x60, 0x44, 0xF3, 0x00, 0x63, 0x00, 0xB8, 0x0A, 0xFC, 0x03, 0x02, 0xD9, 0x60, 0xCF, 0x78, +- 0xFF, 0xFF, 0x0B, 0xF2, 0x27, 0x40, 0x02, 0x3A, 0x02, 0x00, 0x0E, 0xF2, 0xFF, 0xFF, 0x60, 0x47, +- 0x00, 0x3A, 0x25, 0x00, 0x60, 0x41, 0x00, 0x36, 0x22, 0x00, 0xE0, 0xA0, 0xDA, 0x85, 0x1F, 0x07, +- 0x13, 0x60, 0x0B, 0xF1, 0x65, 0x42, 0xD1, 0x80, 0x26, 0x60, 0x18, 0x63, 0x18, 0x02, 0x50, 0xFE, +- 0x61, 0x40, 0xFE, 0x22, 0x08, 0x00, 0x62, 0x45, 0xBD, 0xD3, 0xA5, 0xD0, 0xDA, 0x82, 0xD0, 0x80, +- 0xC9, 0x81, 0xF6, 0x0C, 0x0C, 0x00, 0x61, 0x40, 0x00, 0x36, 0x31, 0x00, 0x62, 0x45, 0xA3, 0xD3, +- 0xA5, 0xD0, 0xFF, 0xFF, 0x90, 0x80, 0xFF, 0x26, 0x02, 0x00, 0xDE, 0x82, 0x28, 0x00, 0x0C, 0x63, +- 0x0A, 0xFC, 0x00, 0x64, 0x09, 0xFA, 0x0B, 0xFA, 0x01, 0x7E, 0x0C, 0xFA, 0x26, 0x46, 0x08, 0x64, +- 0x3F, 0xFA, 0x07, 0xF2, 0x87, 0xF1, 0x40, 0x58, 0x07, 0xF8, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, +- 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, +- 0xDC, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0x20, 0xFE, 0x16, 0x60, 0x50, 0xF3, 0xFF, 0xFF, 0x22, 0xB0, +- 0xFF, 0xFF, 0x03, 0x03, 0xDB, 0x60, 0xB1, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0xD9, 0x01, 0x13, 0x60, +- 0x45, 0xF3, 0xFF, 0xFF, 0xFF, 0xA4, 0xFF, 0xFF, 0x0C, 0x20, 0x03, 0x00, 0xDB, 0x60, 0xB1, 0x78, +- 0xFF, 0xFF, 0x00, 0x64, 0x16, 0x60, 0x56, 0xFB, 0x16, 0x60, 0x57, 0xFB, 0x16, 0x60, 0x58, 0xFB, +- 0x16, 0x60, 0x5A, 0xFB, 0x16, 0x60, 0x5B, 0xFB, 0x16, 0x60, 0x5C, 0xFB, 0x16, 0x60, 0x5D, 0xFB, +- 0x18, 0x60, 0x17, 0xFB, 0x2B, 0x46, 0x3B, 0xF2, 0x7F, 0x60, 0xCF, 0x65, 0xA4, 0x84, 0xA2, 0xDA, +- 0x26, 0x46, 0x00, 0xF4, 0x0B, 0xF2, 0x27, 0x40, 0x02, 0x3A, 0x02, 0x00, 0x0E, 0xF2, 0xFF, 0xFF, +- 0xCE, 0x81, 0x20, 0xFE, 0x30, 0x60, 0x28, 0x64, 0x40, 0x4A, 0xDA, 0x60, 0x58, 0x4D, 0x62, 0x78, +- 0xFF, 0xFF, 0x20, 0xFE, 0x18, 0x60, 0x17, 0xF3, 0xFF, 0xFF, 0x08, 0x18, 0x18, 0x60, 0x19, 0xF3, +- 0x18, 0x60, 0x1A, 0xF5, 0x60, 0x41, 0x30, 0x60, 0x2E, 0x62, 0xA2, 0xDF, 0x2A, 0xD1, 0xDA, 0x85, +- 0x64, 0x44, 0x01, 0xA0, 0xFF, 0xFF, 0x01, 0x02, 0x75, 0x00, 0x45, 0x4A, 0x7C, 0x44, 0x60, 0xFE, +- 0xA1, 0xD2, 0xFF, 0xFF, 0xD0, 0x80, 0x20, 0xFE, 0x01, 0x03, 0xE3, 0x01, 0x30, 0x60, 0x2E, 0x62, +- 0xA2, 0xDF, 0x60, 0xFE, 0x5D, 0xD2, 0xFF, 0xFF, 0x60, 0x5C, 0x41, 0x94, 0x81, 0xA0, 0x20, 0xFE, +- 0x2D, 0x04, 0x01, 0x64, 0x18, 0x60, 0x17, 0xFB, 0xC1, 0x84, 0x84, 0xA4, 0x18, 0x60, 0x19, 0xFB, +- 0x00, 0xF2, 0x18, 0x60, 0x1A, 0xFB, 0x18, 0x60, 0x18, 0xFD, 0x02, 0x60, 0x00, 0x63, 0xCD, 0x85, +- 0x64, 0x44, 0xD8, 0x81, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, +- 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, +- 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x00, 0x60, 0x01, 0x61, 0x02, 0x60, 0x00, 0x64, +- 0xE0, 0x87, 0x60, 0x46, 0x18, 0x60, 0x18, 0xF3, 0xFF, 0xFF, 0x60, 0x43, 0x60, 0xFE, 0xCD, 0x81, +- 0x20, 0xFE, 0x2A, 0x44, 0x00, 0x60, 0x02, 0x65, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xDB, 0x60, +- 0x5C, 0x78, 0xFF, 0xFF, 0x18, 0x60, 0x17, 0xF3, 0xFF, 0xFF, 0x08, 0x18, 0x18, 0x60, 0x19, 0xF3, +- 0x18, 0x60, 0x1A, 0xF5, 0x60, 0x41, 0x30, 0x60, 0x2E, 0x62, 0xA2, 0xDF, 0x66, 0x5C, 0x26, 0x46, +- 0x00, 0xF2, 0x64, 0x46, 0x58, 0x90, 0xFF, 0xFF, 0x03, 0x02, 0x61, 0x44, 0x0B, 0xA5, 0x04, 0x00, +- 0x61, 0x44, 0xFC, 0xA4, 0x8B, 0x7C, 0xC0, 0x85, 0xDD, 0x81, 0x66, 0x44, 0x18, 0x60, 0x1A, 0xFB, +- 0x26, 0x46, 0x1B, 0xF0, 0x18, 0x60, 0x1A, 0xF5, 0x64, 0x44, 0xD4, 0x80, 0xFF, 0xFF, 0xD7, 0x06, +- 0x2D, 0x58, 0xFF, 0xFF, 0x60, 0xFE, 0x5D, 0xD2, 0xFF, 0xFF, 0x20, 0xFE, 0xFF, 0xB4, 0x41, 0x94, +- 0x81, 0xA0, 0xFF, 0xFF, 0x02, 0x04, 0x00, 0xF4, 0x84, 0xA4, 0x60, 0x41, 0x62, 0x01, 0x60, 0xFE, +- 0x5D, 0xD2, 0xFF, 0xFF, 0xFA, 0xA4, 0xFF, 0xFF, 0x04, 0x20, 0x02, 0x00, 0xFF, 0xA1, 0x61, 0x01, +- 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x36, 0x02, 0x00, 0xC9, 0x81, 0x5A, 0x01, 0x5D, 0xD0, +- 0xFF, 0xFF, 0x64, 0x40, 0x50, 0x36, 0x02, 0x00, 0xFD, 0xA1, 0x53, 0x01, 0x5D, 0xD0, 0xFF, 0xFF, +- 0x64, 0x40, 0xF2, 0x36, 0x04, 0x00, 0xFC, 0xA1, 0xDA, 0x60, 0x01, 0x78, 0xFF, 0xFF, 0x5D, 0xD0, +- 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x04, 0x00, 0xFB, 0xA1, 0xDA, 0x60, 0x01, 0x78, 0xFF, 0xFF, +- 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x04, 0x00, 0xFA, 0xA1, 0xDA, 0x60, 0x01, 0x78, +- 0xFF, 0xFF, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x36, 0x04, 0x00, 0xF9, 0xA1, 0xDA, 0x60, +- 0x01, 0x78, 0xFF, 0xFF, 0x60, 0x5C, 0x00, 0x36, 0x2A, 0x00, 0x00, 0x64, 0xDB, 0x60, 0x58, 0x4E, +- 0x16, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0x5A, 0xFB, 0x64, 0x40, 0x00, 0x36, 0x25, 0x00, 0x5D, 0xD2, +- 0xDD, 0x81, 0xDB, 0x60, 0x58, 0x4E, 0x16, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0x5B, 0xFB, 0x64, 0x40, +- 0x00, 0x36, 0x1F, 0x00, 0x5D, 0xD2, 0xDD, 0x81, 0xDB, 0x60, 0x58, 0x4E, 0x16, 0x78, 0xFF, 0xFF, +- 0x16, 0x60, 0x5C, 0xFB, 0x64, 0x40, 0x00, 0x36, 0x19, 0x00, 0x5D, 0xD0, 0x16, 0x60, 0x5D, 0xF9, +- 0x5D, 0xD0, 0x2C, 0x60, 0xBB, 0x62, 0xA2, 0xD9, 0xD9, 0x60, 0xF9, 0x78, 0xFF, 0xFF, 0x20, 0xFE, +- 0x00, 0x60, 0x04, 0x64, 0x16, 0x60, 0x5A, 0xFB, 0x20, 0xFE, 0x00, 0x60, 0x04, 0x64, 0x16, 0x60, +- 0x5B, 0xFB, 0x20, 0xFE, 0x00, 0x60, 0x02, 0x64, 0x16, 0x60, 0x5C, 0xFB, 0x20, 0xFE, 0x00, 0x60, +- 0x00, 0x64, 0x16, 0x60, 0x5D, 0xFB, 0xD9, 0x60, 0xF9, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0x5E, 0xFB, +- 0xE0, 0x84, 0xE0, 0x84, 0x03, 0x02, 0x01, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x02, 0xA5, 0x64, 0x44, +- 0xD4, 0x9C, 0x16, 0x60, 0x5F, 0xF9, 0x2C, 0x60, 0xC0, 0x62, 0xA2, 0xDF, 0x5D, 0xD0, 0x00, 0x65, +- 0x64, 0x40, 0x00, 0x3A, 0x01, 0x65, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x50, 0x3A, 0x01, 0x65, +- 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0xF2, 0x3A, 0x01, 0x65, 0x5D, 0xD0, 0x65, 0x40, 0x00, 0x3A, +- 0x17, 0x00, 0x00, 0x60, 0x00, 0x65, 0x64, 0x40, 0x00, 0x36, 0x01, 0x65, 0x64, 0x40, 0x01, 0x36, +- 0x02, 0x65, 0x64, 0x40, 0x02, 0x36, 0x04, 0x65, 0x64, 0x40, 0x04, 0x36, 0x10, 0x65, 0x64, 0x40, +- 0x05, 0x36, 0x20, 0x65, 0x65, 0x5C, 0x16, 0x60, 0x60, 0xF3, 0xFF, 0xFF, 0xB0, 0x84, 0xA2, 0xDB, +- 0x16, 0x60, 0x5E, 0xF3, 0xFF, 0xFF, 0xFF, 0xA4, 0xA2, 0xDB, 0xD0, 0x02, 0x16, 0x60, 0x60, 0xF3, +- 0x16, 0x60, 0x5F, 0xF1, 0x2E, 0x58, 0xFF, 0xFF, 0x20, 0xFE, 0x16, 0x60, 0x50, 0xF1, 0x16, 0x60, +- 0x5A, 0xF3, 0xFF, 0xFF, 0xA0, 0x84, 0xFF, 0xFF, 0x10, 0x26, 0x09, 0x00, 0x04, 0x26, 0x09, 0x00, +- 0x20, 0x26, 0x09, 0x00, 0x02, 0x26, 0x09, 0x00, 0xD9, 0x60, 0xC3, 0x78, 0xFF, 0xFF, 0x10, 0x7C, +- 0x05, 0x00, 0x04, 0x7C, 0x03, 0x00, 0x20, 0x7C, 0x01, 0x00, 0x02, 0x7C, 0x16, 0x60, 0x56, 0xF9, +- 0x16, 0x60, 0x51, 0xF1, 0x16, 0x60, 0x5B, 0xF3, 0x2C, 0x60, 0xAC, 0x62, 0xA0, 0x84, 0xA2, 0xD1, +- 0xFF, 0xFF, 0x10, 0x26, 0x07, 0x00, 0x04, 0x26, 0x07, 0x00, 0x01, 0x26, 0x0D, 0x00, 0xD9, 0x60, +- 0xC3, 0x78, 0xFF, 0xFF, 0x10, 0x7C, 0x09, 0x00, 0x64, 0x40, 0x10, 0x22, 0x03, 0x00, 0xD9, 0x60, +- 0xC3, 0x78, 0xFF, 0xFF, 0x04, 0x7C, 0x01, 0x00, 0x01, 0x7C, 0x16, 0x60, 0x57, 0xF9, 0x16, 0x60, +- 0x52, 0xF1, 0x16, 0x60, 0x5C, 0xF3, 0xFF, 0xFF, 0xA0, 0x84, 0x02, 0x26, 0x07, 0x00, 0x04, 0x26, +- 0x07, 0x00, 0x01, 0x26, 0x07, 0x00, 0xD9, 0x60, 0xC3, 0x78, 0xFF, 0xFF, 0x02, 0x7C, 0x03, 0x00, +- 0x04, 0x7C, 0x01, 0x00, 0x20, 0x7C, 0x16, 0x60, 0x58, 0xF9, 0x16, 0x60, 0x5D, 0xF1, 0x16, 0x60, +- 0x59, 0xF9, 0x16, 0x60, 0x58, 0xF3, 0x16, 0x60, 0x57, 0xF1, 0x60, 0x47, 0xB0, 0x84, 0x13, 0x60, +- 0x45, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x22, 0xBC, 0xAB, 0x46, 0x3A, 0xFA, 0xAB, 0x46, +- 0x16, 0x60, 0x56, 0xF3, 0x13, 0x60, 0x45, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x22, 0xBC, +- 0x87, 0xF1, 0x66, 0x41, 0x64, 0x46, 0x3A, 0xFA, 0xFF, 0xFF, 0x61, 0x46, 0xAB, 0x46, 0x82, 0xF0, +- 0xC0, 0x67, 0xB4, 0x84, 0xAB, 0x46, 0x0B, 0xFA, 0x13, 0x60, 0x4D, 0xF1, 0x2D, 0x60, 0xBE, 0x7C, +- 0x04, 0x1B, 0xFF, 0x60, 0xFF, 0x63, 0xA4, 0xDD, 0x26, 0x00, 0x2E, 0x60, 0x34, 0x63, 0xA4, 0xDD, +- 0xDB, 0x83, 0x60, 0xFE, 0x00, 0x64, 0xBD, 0xDB, 0x60, 0x64, 0xBD, 0xDB, 0x1D, 0x64, 0xBD, 0xDB, +- 0xC3, 0xF3, 0xBD, 0xDB, 0x20, 0xFE, 0x01, 0x60, 0x78, 0x64, 0x06, 0x61, 0x58, 0xD1, 0xFF, 0xFF, +- 0x60, 0xFE, 0xBD, 0xD9, 0x20, 0xFE, 0xCD, 0x81, 0x61, 0x40, 0x08, 0x28, 0xF7, 0x01, 0xB6, 0xF1, +- 0xFF, 0xFF, 0x64, 0x47, 0x60, 0xFE, 0xBD, 0xD9, 0xBD, 0xDB, 0x20, 0xFE, 0x13, 0x60, 0x4B, 0xF1, +- 0x60, 0xFE, 0xBD, 0xD9, 0x20, 0xFE, 0x2D, 0x60, 0xBC, 0x64, 0x40, 0x48, 0x18, 0x61, 0x26, 0x46, +- 0x00, 0xF4, 0xFF, 0x60, 0xF2, 0x64, 0xE4, 0x60, 0x58, 0x4D, 0xA7, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x3F, 0xFC, 0x2B, 0x46, 0x56, 0xF1, 0x1F, 0xF8, 0x0C, 0x60, 0x70, 0xF1, 0x10, 0x60, 0x00, 0x64, +- 0xA0, 0x80, 0x06, 0xF2, 0x0B, 0x03, 0x10, 0xBC, 0x06, 0xFA, 0x86, 0xF3, 0x00, 0x60, 0x70, 0xF3, +- 0x60, 0x45, 0xD4, 0x80, 0xDC, 0x84, 0x07, 0x07, 0xA2, 0xDB, 0x05, 0x00, 0x10, 0xB5, 0xFF, 0xFF, +- 0x02, 0x03, 0xD4, 0x84, 0x06, 0xFA, 0x07, 0xF2, 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, +- 0x02, 0xB0, 0xFF, 0xFF, 0x11, 0x03, 0x26, 0x46, 0x87, 0xF3, 0x07, 0xFA, 0x1E, 0x60, 0xD4, 0x64, +- 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x50, 0x00, 0x26, 0x46, 0x87, 0xF3, 0x07, 0xFA, 0x1E, 0x60, +- 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x19, 0x00, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, +- 0x02, 0x64, 0x3F, 0xFA, 0x87, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x09, 0x64, 0x09, 0xFA, 0x1E, 0x60, +- 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x2B, 0x43, 0x0B, 0x60, +- 0x82, 0xF3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, 0xD9, 0x81, +- 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, 0x17, 0x60, +- 0x04, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, 0xAB, 0x46, +- 0x06, 0xF2, 0xFF, 0xFF, 0x02, 0xBC, 0x06, 0xFA, 0x78, 0xF2, 0x15, 0x60, 0xDC, 0xF3, 0x60, 0x45, +- 0xA4, 0x84, 0x15, 0x60, 0xDC, 0xFB, 0xAB, 0x46, 0xAB, 0x46, 0x0F, 0x60, 0xFF, 0x64, 0x02, 0xF0, +- 0x71, 0xF1, 0xA0, 0x84, 0xD0, 0x80, 0x02, 0xFA, 0xAB, 0x46, 0x01, 0x06, 0x71, 0xFB, 0x27, 0x41, +- 0x01, 0xB1, 0xFF, 0xFF, 0x08, 0x03, 0x2B, 0x46, 0x0B, 0x58, 0x01, 0x65, 0xE5, 0x60, 0x58, 0x4E, +- 0x51, 0x78, 0xFF, 0xFF, 0x0A, 0x00, 0x2B, 0x46, 0x0B, 0x58, 0x18, 0x60, 0xD6, 0x64, 0x40, 0x59, +- 0x02, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x51, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, +- 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x00, 0x64, 0x09, 0xFA, 0x0B, 0xFA, 0x01, 0x7E, 0x0C, 0xFA, +- 0x0A, 0x64, 0x0A, 0xFA, 0x26, 0x46, 0x08, 0x64, 0x3F, 0xFA, 0x07, 0xF2, 0x87, 0xF1, 0x40, 0x58, +- 0x07, 0xF8, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xFF, 0x60, 0xFD, 0x65, 0x38, 0x46, 0x06, 0xF2, +- 0xFF, 0xFF, 0xA4, 0x83, 0x06, 0xFC, 0x02, 0xB0, 0x26, 0x46, 0x1C, 0x03, 0x38, 0x43, 0x86, 0xF1, +- 0x17, 0x60, 0x02, 0x61, 0xA1, 0xD3, 0xDA, 0x81, 0xD0, 0x80, 0xDC, 0x9C, 0x05, 0x05, 0xA1, 0xD3, +- 0x4A, 0xD9, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0x02, 0x60, 0x00, 0x61, 0x2C, 0xF2, 0xA1, 0xDB, +- 0x2D, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x2E, 0xF2, 0x59, 0xDB, 0x03, 0x65, 0xE5, 0x60, 0x58, 0x4E, +- 0x51, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x07, 0xF2, 0x87, 0xF1, +- 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, 0x40, 0x47, 0x07, 0xF2, +- 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x02, 0xB0, 0xFF, 0xFF, 0x1A, 0x02, 0x27, 0x43, +- 0x0B, 0x60, 0x82, 0xF3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x11, 0x03, 0xD3, 0x80, +- 0xD9, 0x81, 0xFA, 0x02, 0xC9, 0x81, 0xC8, 0x85, 0xD5, 0x80, 0xA5, 0xD3, 0x08, 0x28, 0xA1, 0xDB, +- 0x17, 0x60, 0x04, 0x62, 0x65, 0x44, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA2, 0xDB, +- 0x0C, 0x00, 0x27, 0x44, 0x40, 0x58, 0x03, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x51, 0x78, 0xFF, 0xFF, +- 0x27, 0x43, 0xE7, 0x60, 0x58, 0x4E, 0x81, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x87, 0xF4, 0x66, 0x41, +- 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, +- 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, +- 0x00, 0xF8, 0x87, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, +- 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, +- 0x61, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x07, 0xF2, 0x87, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, +- 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, 0x40, 0x47, 0x07, 0xF2, 0x66, 0x45, 0x60, 0x46, 0x06, 0xF2, +- 0x65, 0x46, 0x02, 0xB0, 0xFF, 0xFF, 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0x46, 0x06, 0xF0, +- 0xFF, 0x60, 0xED, 0x64, 0xA0, 0x84, 0x06, 0xFA, 0x27, 0x43, 0x86, 0xF1, 0x17, 0x60, 0x02, 0x61, +- 0xA1, 0xD3, 0xDA, 0x81, 0xD0, 0x80, 0xDC, 0x9C, 0x05, 0x05, 0xA1, 0xD3, 0x4A, 0xD9, 0xA0, 0xDD, +- 0xDA, 0x9C, 0xA1, 0xD9, 0x07, 0x58, 0x03, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x51, 0x78, 0xFF, 0xFF, +- 0x27, 0x43, 0xE7, 0x60, 0x58, 0x4E, 0x81, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, +- 0x26, 0x46, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF3, +- 0x2F, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, 0x66, 0xF3, 0x32, 0xFA, 0x67, 0xF3, +- 0x33, 0xFA, 0x68, 0xF3, 0x34, 0xFA, 0xAB, 0xF1, 0x19, 0xF8, 0x00, 0x65, 0xEF, 0x60, 0x58, 0x4E, +- 0xDC, 0x78, 0xFF, 0xFF, 0x61, 0x44, 0x15, 0x60, 0xC2, 0xFB, 0x02, 0x63, 0x3F, 0xFC, 0x00, 0x64, +- 0x3E, 0xFA, 0x02, 0x60, 0x00, 0x61, 0x2C, 0xF2, 0xA1, 0xDB, 0x2D, 0xF2, 0x41, 0x58, 0x59, 0xDB, +- 0x2E, 0xF2, 0x59, 0xDB, 0x06, 0x63, 0x07, 0xF2, 0x87, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, +- 0x0D, 0x02, 0x43, 0x59, 0x02, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0xC0, 0x64, 0x2A, 0xFA, 0x00, 0xF4, 0x06, 0x64, 0x09, 0xFA, 0x15, 0x00, 0x07, 0xF2, 0x66, 0x45, +- 0x60, 0x46, 0x06, 0xF2, 0x65, 0x46, 0x02, 0xB0, 0xFF, 0xFF, 0x1D, 0x02, 0x07, 0x63, 0x43, 0x59, +- 0x01, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0xA0, 0x64, 0x2A, 0xFA, +- 0x00, 0xF4, 0x07, 0x64, 0x09, 0xFA, 0x26, 0x46, 0x87, 0xF3, 0x07, 0xFA, 0x1E, 0x60, 0xD4, 0x64, +- 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0xDE, 0x60, 0x66, 0x64, 0x08, 0x60, +- 0x29, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0x03, 0x64, 0x08, 0x60, 0x1F, 0xFB, 0xDE, 0x60, +- 0x05, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1E, 0xF1, 0x00, 0x60, +- 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x59, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x71, 0xF3, 0x87, 0xF5, +- 0xDC, 0x81, 0x66, 0x43, 0x02, 0xA3, 0x63, 0x46, 0xCD, 0x81, 0x06, 0xF2, 0xEE, 0x03, 0x60, 0x40, +- 0x08, 0x2A, 0xF7, 0x01, 0x0C, 0xAC, 0x06, 0xFA, 0x46, 0x49, 0x00, 0x60, 0x02, 0x61, 0xB5, 0x60, +- 0x58, 0x4D, 0xA2, 0x78, 0xFF, 0xFF, 0xE1, 0x03, 0x18, 0x60, 0x13, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, +- 0x00, 0x60, 0xA0, 0x64, 0x02, 0x00, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, 0xAB, 0xFC, 0x66, 0x45, +- 0x29, 0x44, 0x07, 0xFA, 0x29, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x85, 0xF2, 0x65, 0x46, 0x2C, 0xFA, +- 0x2D, 0xF8, 0xAE, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0x32, 0xFA, 0xCC, 0xF3, 0x30, 0xFA, 0x33, 0xFA, +- 0xCD, 0xF3, 0x31, 0xFA, 0x34, 0xFA, 0xAB, 0xF1, 0x19, 0xF8, 0x18, 0x67, 0x0E, 0xFA, 0x66, 0x41, +- 0x29, 0x46, 0x92, 0xF0, 0x2C, 0x60, 0x26, 0x63, 0x47, 0xD3, 0x61, 0x46, 0x00, 0x7E, 0x13, 0xFA, +- 0x02, 0x63, 0x3F, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0x66, 0x41, 0x00, 0xF4, 0x18, 0x60, 0x12, 0xF3, +- 0x09, 0xFA, 0x1E, 0x60, 0xE0, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x61, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0xA0, 0x01, 0x95, 0x01, 0x00, 0x64, 0x08, 0x60, +- 0x1E, 0xFB, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x07, 0xF0, 0xFF, 0xFF, 0x64, 0x43, 0x0B, 0x60, +- 0x82, 0xF3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, 0x04, 0x03, 0xD3, 0x80, 0xD9, 0x81, +- 0xFA, 0x02, 0x08, 0x00, 0xA1, 0xDD, 0xD9, 0x84, 0x0B, 0x60, 0x82, 0xFB, 0x4A, 0xD3, 0xFF, 0xFF, +- 0xDC, 0x84, 0xA2, 0xDB, 0x66, 0x45, 0x63, 0x46, 0x06, 0xF2, 0xFF, 0x60, 0x01, 0x7C, 0xA0, 0x9C, +- 0x06, 0xF8, 0x65, 0x46, 0x70, 0xF3, 0x60, 0x40, 0x10, 0x2A, 0x03, 0x00, 0xCC, 0x84, 0x80, 0x2B, +- 0x70, 0xFB, 0x08, 0x60, 0x1E, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x30, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x02, 0x64, +- 0x08, 0x60, 0x19, 0xFB, 0xDE, 0x60, 0xA8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x70, 0xF3, 0x71, 0xF3, 0x00, 0xA8, 0x60, 0x88, 0x43, 0x03, 0xE0, 0x83, 0x5F, 0x03, 0xCB, 0x83, +- 0x87, 0xF3, 0x72, 0xF1, 0x02, 0xA4, 0x40, 0x47, 0x64, 0x45, 0x27, 0x46, 0x76, 0xF4, 0x12, 0xF2, +- 0x33, 0x18, 0xD4, 0x80, 0x02, 0x64, 0x30, 0x07, 0x23, 0xFA, 0x2A, 0xF2, 0x0E, 0xF2, 0x0C, 0xB0, +- 0x02, 0xF0, 0x0C, 0x02, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xE7, 0x01, 0x60, 0x40, 0xF0, 0x37, +- 0x08, 0x00, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0x8F, 0xF3, 0x02, 0x02, 0xDC, 0x84, +- 0x8F, 0xFB, 0x1E, 0x60, 0xF2, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA3, 0xFF, 0xCE, 0xFE, 0x25, 0x60, 0xE4, 0x64, 0xE5, 0x60, +- 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, 0xC9, 0x01, 0x27, 0x44, 0x02, 0xA4, 0x40, 0x47, 0xC5, 0x1F, +- 0x28, 0x43, 0xCB, 0x83, 0x87, 0xF3, 0x1A, 0x0E, 0x02, 0xA4, 0x40, 0x4C, 0x43, 0x48, 0x2C, 0x46, +- 0x22, 0xF2, 0x72, 0xF1, 0xAC, 0x86, 0x12, 0xF2, 0x0C, 0x03, 0xD0, 0x80, 0xFF, 0xFF, 0x09, 0x07, +- 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, 0x2C, 0x46, +- 0xA2, 0xFC, 0x2C, 0x44, 0x02, 0xA4, 0x28, 0x43, 0x40, 0x4C, 0xE8, 0x1F, 0x8B, 0x01, 0x01, 0x63, +- 0x65, 0xF3, 0xAB, 0xF3, 0x00, 0xBD, 0xAC, 0x81, 0x06, 0x03, 0x05, 0x03, 0xB7, 0x60, 0x58, 0x4D, +- 0xC0, 0x78, 0xFF, 0xFF, 0x60, 0x43, 0x5B, 0xFD, 0x3E, 0x63, 0x18, 0x60, 0x94, 0x61, 0x00, 0x64, +- 0x59, 0xDB, 0xFE, 0x1F, 0x70, 0xFB, 0x71, 0xFB, 0x18, 0x60, 0xDC, 0x65, 0xA5, 0xDF, 0x5A, 0xDF, +- 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0x70, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x03, 0x02, +- 0xCA, 0x60, 0x7E, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x45, 0x64, 0x46, 0x1F, 0xF2, 0x65, 0x46, +- 0x64, 0x45, 0x5B, 0xF1, 0xE0, 0x84, 0x72, 0xF1, 0xC0, 0x84, 0xC0, 0x84, 0x12, 0xFA, 0x2C, 0xF2, +- 0x70, 0xF3, 0x60, 0x40, 0x01, 0x2A, 0x34, 0x00, 0x00, 0xA8, 0x13, 0x60, 0x43, 0xF3, 0x36, 0x03, +- 0x00, 0xA8, 0xFF, 0xFF, 0x33, 0x03, 0xE1, 0x60, 0x58, 0x4D, 0x04, 0x78, 0xFF, 0xFF, 0x25, 0x46, +- 0x09, 0x60, 0x08, 0x61, 0xA2, 0xFF, 0x0E, 0xF2, 0x02, 0xF0, 0x60, 0x40, 0xF0, 0x37, 0x0D, 0x00, +- 0x91, 0xF3, 0x8F, 0xF3, 0xDC, 0x83, 0xD1, 0x80, 0x91, 0xFD, 0x0C, 0x03, 0x8B, 0xF3, 0xCC, 0x83, +- 0xD8, 0xA0, 0x8F, 0xFD, 0x07, 0x04, 0xD4, 0xFE, 0x05, 0x00, 0xD1, 0x80, 0x92, 0xF3, 0x02, 0x03, +- 0xDC, 0x84, 0x92, 0xFB, 0x1E, 0x60, 0xDA, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x25, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA3, 0xFF, 0xDF, 0x60, 0x2A, 0x78, 0xFF, 0xFF, +- 0x66, 0x41, 0x65, 0x46, 0x06, 0xF2, 0x61, 0x46, 0x60, 0x40, 0x10, 0x2A, 0x4B, 0x00, 0x80, 0x67, +- 0xB4, 0x81, 0x61, 0x44, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xE1, 0x60, 0x58, 0x4D, 0x04, 0x78, 0xFF, 0xFF, 0x25, 0x46, 0x2A, 0xF2, +- 0x09, 0x60, 0x08, 0x61, 0x0C, 0xB0, 0xA2, 0xFF, 0x17, 0x03, 0x0E, 0xF2, 0x02, 0xF0, 0x60, 0x40, +- 0xF0, 0x37, 0x0D, 0x00, 0x8F, 0xF3, 0x91, 0xF3, 0xCC, 0x83, 0xD1, 0x80, 0x8F, 0xFD, 0x0C, 0x03, +- 0x8B, 0xF3, 0xDC, 0x83, 0xD8, 0xA0, 0x91, 0xFD, 0x07, 0x04, 0xD4, 0xFE, 0x05, 0x00, 0xD1, 0x80, +- 0x92, 0xF3, 0x02, 0x03, 0xDC, 0x84, 0x92, 0xFB, 0x07, 0xF0, 0x0A, 0xF2, 0xA3, 0xFF, 0x64, 0x45, +- 0x2F, 0x1B, 0x66, 0x41, 0x65, 0x46, 0x02, 0xF0, 0x61, 0x46, 0x0F, 0x60, 0xFF, 0x61, 0xA1, 0x84, +- 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, +- 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x18, 0x60, 0x96, 0x65, 0x46, 0xD1, 0x61, 0x44, 0xB0, 0x84, +- 0xA2, 0xDB, 0x16, 0x00, 0x1E, 0x60, 0xD4, 0x61, 0x2A, 0xF2, 0x3E, 0xF2, 0x0C, 0xB0, 0x01, 0xB0, +- 0x05, 0x03, 0x1E, 0x60, 0xE6, 0x61, 0x02, 0x02, 0x1E, 0x60, 0xCE, 0x61, 0x61, 0x44, 0x0F, 0x60, +- 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, +- 0xDF, 0x60, 0x2A, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x2B, 0xF2, 0x2A, 0xF2, 0x60, 0x41, 0x44, 0x49, +- 0x60, 0x45, 0xA4, 0x3A, 0x0D, 0x00, 0x61, 0x40, 0xC0, 0x3B, 0x79, 0x00, 0xA9, 0x46, 0x06, 0xF2, +- 0xA9, 0x46, 0x60, 0x40, 0x20, 0x26, 0x73, 0x00, 0x20, 0xBC, 0xA9, 0x46, 0x06, 0xFA, 0xA9, 0x46, +- 0xA9, 0x46, 0x06, 0xF0, 0xA9, 0x46, 0x65, 0x40, 0x10, 0x2B, 0x6C, 0x00, 0x64, 0x40, 0x10, 0x2A, +- 0x35, 0x00, 0x65, 0x40, 0xA4, 0x3A, 0x63, 0x00, 0x29, 0x45, 0x65, 0x46, 0x76, 0xF2, 0xFF, 0xFF, +- 0x00, 0xA8, 0x60, 0x46, 0x04, 0x02, 0x76, 0x00, 0xE0, 0x60, 0xEA, 0x78, 0xFF, 0xFF, 0x09, 0xF2, +- 0x2A, 0xF0, 0x00, 0xA8, 0x20, 0x67, 0x02, 0x03, 0xB0, 0x84, 0x2A, 0xFA, 0x0E, 0xF2, 0x02, 0xF0, +- 0x60, 0x40, 0xF0, 0x37, 0x08, 0x00, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0x8F, 0xF3, +- 0x02, 0x02, 0xDC, 0x84, 0x8F, 0xFB, 0x3E, 0xF2, 0xA3, 0xFF, 0x01, 0xB0, 0x1E, 0x60, 0xE6, 0x61, +- 0x02, 0x02, 0x1E, 0x60, 0xD4, 0x61, 0x61, 0x44, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x16, 0x00, 0x10, 0x64, 0xB0, 0x84, +- 0xDF, 0x65, 0xA4, 0x9E, 0xA9, 0x46, 0x06, 0xFA, 0xA9, 0x46, 0xA2, 0xFF, 0x04, 0x64, 0x0C, 0x60, +- 0x6E, 0xFB, 0x29, 0x44, 0x5A, 0xDB, 0x70, 0xF3, 0xC1, 0xFE, 0xD4, 0xFE, 0x86, 0xF1, 0xA3, 0xFF, +- 0xD0, 0x80, 0xDC, 0x84, 0x01, 0x07, 0x70, 0xFB, 0xA9, 0x46, 0x76, 0xF2, 0xA9, 0x46, 0x64, 0x18, +- 0xA9, 0x46, 0x02, 0xF0, 0xA9, 0x46, 0x0F, 0x60, 0xFF, 0x61, 0xA1, 0x84, 0x60, 0x41, 0xE9, 0x81, +- 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, +- 0xFD, 0x02, 0x18, 0x60, 0x96, 0x65, 0x46, 0xD1, 0xFF, 0xFF, 0xB1, 0x84, 0xA2, 0xDB, 0xE1, 0x60, +- 0x01, 0x78, 0xFF, 0xFF, 0x64, 0x40, 0x10, 0x2A, 0xFA, 0x01, 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, +- 0xA9, 0x46, 0x06, 0xFA, 0xA9, 0x46, 0x65, 0x41, 0x70, 0xF3, 0x29, 0x45, 0xCC, 0x84, 0x80, 0x2B, +- 0x70, 0xFB, 0x65, 0x46, 0x76, 0xF2, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x36, 0x02, 0x61, 0x40, +- 0xA4, 0x3A, 0xE5, 0x01, 0x00, 0x60, 0x3A, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x9F, 0x78, 0xFF, 0xFF, +- 0x83, 0x03, 0x02, 0x60, 0x48, 0x64, 0x2A, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, +- 0xCD, 0xF1, 0x31, 0xF8, 0x66, 0xF1, 0x32, 0xF8, 0x67, 0xF1, 0x33, 0xF8, 0x68, 0xF1, 0x34, 0xF8, +- 0xA9, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x85, 0xF0, 0xA9, 0x46, 0x2C, 0xFA, 0x2D, 0xF8, 0xAE, 0xF8, +- 0xAB, 0xF1, 0x19, 0xF8, 0xFF, 0x67, 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x29, 0x44, +- 0x07, 0xFA, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x35, 0x00, 0x80, 0x67, 0xB4, 0x83, 0x2A, 0xF2, +- 0x09, 0x60, 0x08, 0x65, 0x0C, 0xB0, 0x09, 0xF0, 0x0C, 0x02, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, +- 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x9F, 0x18, +- 0x64, 0x46, 0x3E, 0xF2, 0xA2, 0xFF, 0x01, 0xB0, 0x1E, 0x60, 0xE6, 0x61, 0x02, 0x02, 0x1E, 0x60, +- 0xCE, 0x61, 0x02, 0xF2, 0x0E, 0xF0, 0xD4, 0x80, 0x09, 0xF4, 0x06, 0x02, 0x8F, 0xF3, 0x64, 0x40, +- 0xF0, 0x37, 0x02, 0x00, 0xDC, 0x84, 0x8F, 0xFB, 0x66, 0x44, 0x00, 0xA8, 0xFF, 0xFF, 0xF1, 0x02, +- 0x61, 0x44, 0x0F, 0x60, 0x90, 0xFB, 0x5A, 0xDD, 0x08, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xC1, 0xFE, 0xA3, 0xFF, 0xA9, 0x46, 0x02, 0xF0, 0xA9, 0x46, 0x0F, 0x60, 0xFF, 0x61, 0xA1, 0x84, +- 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, +- 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x18, 0x60, 0x96, 0x65, 0x46, 0xD3, 0x9D, 0x85, 0xA4, 0x84, +- 0xA2, 0xDB, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x46, 0x45, 0x3F, 0xF2, 0x05, 0x48, 0x00, 0xA8, +- 0x60, 0x41, 0x66, 0x44, 0x0B, 0x03, 0x0E, 0xA1, 0x00, 0xF2, 0x42, 0xFE, 0xAC, 0x86, 0x01, 0xF2, +- 0x1F, 0x03, 0x7F, 0xB5, 0xD5, 0x81, 0x66, 0x44, 0xF7, 0x07, 0x25, 0x46, 0x05, 0xF0, 0x06, 0xFA, +- 0x05, 0xFA, 0xD0, 0x80, 0x64, 0x43, 0x13, 0x03, 0x60, 0x46, 0x01, 0xF0, 0x80, 0x67, 0xB0, 0x84, +- 0x01, 0xFA, 0x00, 0xF0, 0x00, 0x64, 0x00, 0xFA, 0x44, 0x45, 0xA2, 0xFF, 0xB6, 0x60, 0x58, 0x4E, +- 0x72, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x08, 0x45, 0x25, 0x46, 0x01, 0x64, 0x02, 0xFA, 0x02, 0xFE, +- 0x2D, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x07, 0xF0, 0x10, 0xB0, 0x10, 0xAC, 0x3A, 0x03, 0x23, 0xFA, +- 0x80, 0x67, 0xB0, 0x81, 0x61, 0x44, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x04, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x46, 0x45, 0x64, 0x46, 0x02, 0xF0, 0x0F, 0x60, 0xFF, 0x61, +- 0xA1, 0x84, 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE1, 0x82, 0x07, 0xB4, 0x01, 0x61, +- 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x18, 0x60, 0x96, 0x65, 0x46, 0xD1, 0xFF, 0xFF, +- 0xB1, 0x84, 0xA2, 0xDB, 0x9F, 0xF2, 0x25, 0x46, 0xE1, 0x81, 0x5B, 0xF1, 0x72, 0xF1, 0xC1, 0x81, +- 0xC1, 0x81, 0x92, 0xFA, 0xA2, 0xFF, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x61, 0xD1, 0x80, 0x0E, 0xF2, +- 0x05, 0x02, 0x8F, 0xF3, 0x20, 0xB0, 0xCC, 0x84, 0x01, 0x02, 0x8F, 0xFB, 0xA3, 0xFF, 0x48, 0xFE, +- 0x07, 0x00, 0x0E, 0xF2, 0x08, 0xFE, 0xF0, 0x7F, 0x60, 0x40, 0x20, 0x2A, 0x00, 0x7F, 0x0E, 0xFA, +- 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0xC5, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0xA2, 0x78, 0xFF, 0xFF, +- 0x66, 0x44, 0x57, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x80, 0x64, 0x2A, 0xFA, 0xAB, 0xF1, 0x19, 0xF8, +- 0x00, 0x64, 0x3E, 0xFA, 0x00, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0x87, 0xF1, 0x07, 0xF8, 0x67, 0x44, +- 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0xE4, 0x60, 0x65, 0x64, 0x08, 0x60, 0x25, 0xFB, 0xE2, 0x60, +- 0xA0, 0x64, 0x08, 0x60, 0x2B, 0xFB, 0x18, 0x60, 0xE6, 0x63, 0x65, 0x44, 0xBD, 0xDB, 0x10, 0x60, +- 0x58, 0x64, 0xBD, 0xDB, 0x02, 0x64, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, 0xE9, 0x60, 0xB2, 0x78, +- 0xFF, 0xFF, 0xE9, 0x60, 0x58, 0x4D, 0xBE, 0x78, 0xFF, 0xFF, 0x57, 0xF5, 0xCB, 0xF1, 0x2F, 0xF8, +- 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x66, 0xF1, 0x32, 0xF8, 0x67, 0xF1, 0x33, 0xF8, +- 0x68, 0xF1, 0x34, 0xF8, 0x13, 0x60, 0x45, 0xF1, 0x01, 0x64, 0x64, 0x40, 0xFE, 0x26, 0x10, 0xBC, +- 0x32, 0x40, 0x10, 0x26, 0x10, 0xBC, 0x20, 0xBC, 0x04, 0x60, 0x00, 0x65, 0x60, 0x44, 0xB4, 0x84, +- 0x17, 0x60, 0x22, 0xFB, 0x13, 0x60, 0x44, 0xF1, 0x26, 0x60, 0x16, 0x64, 0x02, 0x18, 0x26, 0x60, +- 0x38, 0x64, 0x16, 0x60, 0xBF, 0xFB, 0x16, 0x60, 0xCF, 0xFB, 0x2C, 0x60, 0x84, 0x61, 0x13, 0x60, +- 0x97, 0xF3, 0x2D, 0x60, 0x5E, 0x65, 0xFE, 0xA4, 0xE0, 0x84, 0x02, 0x05, 0x67, 0x44, 0x21, 0x00, +- 0xE0, 0x84, 0xC4, 0x85, 0x16, 0x60, 0x55, 0xF3, 0xA5, 0xD1, 0xDA, 0x85, 0xA0, 0x83, 0x16, 0x60, +- 0x51, 0xFD, 0xA5, 0xD1, 0x2C, 0x60, 0xA0, 0x62, 0xA0, 0x83, 0xA2, 0xDD, 0x2C, 0x60, 0x84, 0x61, +- 0x50, 0x60, 0x00, 0x7C, 0x00, 0x60, 0xF2, 0x65, 0xE2, 0x60, 0x58, 0x4D, 0x06, 0x78, 0xFF, 0xFF, +- 0x16, 0x60, 0x53, 0xF1, 0x59, 0xD9, 0x2C, 0x60, 0x7E, 0x65, 0xD5, 0x84, 0xDD, 0x7F, 0xA5, 0xDB, +- 0x65, 0x44, 0x16, 0x60, 0xC4, 0xFB, 0x16, 0x60, 0xD4, 0xFB, 0x79, 0x00, 0x16, 0x60, 0x54, 0xF3, +- 0x2C, 0x60, 0xA0, 0x62, 0xFD, 0xA0, 0xA2, 0xD3, 0xEE, 0x03, 0x60, 0x40, 0x02, 0x2A, 0x02, 0x00, +- 0x01, 0x63, 0x0B, 0x00, 0x04, 0x2A, 0x02, 0x00, 0x02, 0x63, 0x07, 0x00, 0x10, 0x2A, 0x02, 0x00, +- 0x04, 0x63, 0x03, 0x00, 0x20, 0x2A, 0x01, 0x00, 0x05, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, +- 0x59, 0xDD, 0x16, 0x60, 0x54, 0xF3, 0x16, 0x60, 0x51, 0xF3, 0xFE, 0xA0, 0x40, 0x4C, 0xD3, 0x03, +- 0x00, 0x60, 0x00, 0x63, 0x59, 0xDD, 0x41, 0x4A, 0x2C, 0x40, 0x01, 0x2A, 0x05, 0x00, 0x00, 0x63, +- 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x63, +- 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x04, 0x2A, 0x05, 0x00, 0x02, 0x63, 0x63, 0x47, 0xB4, 0x83, +- 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x10, 0x2A, 0x05, 0x00, 0x04, 0x63, 0x63, 0x47, 0xB4, 0x83, +- 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x20, 0x2A, 0x05, 0x00, 0x05, 0x63, 0x63, 0x47, 0xB4, 0x83, +- 0x59, 0xD9, 0x59, 0xDD, 0x2A, 0x44, 0x51, 0x93, 0xEB, 0x83, 0xEB, 0x83, 0xA0, 0xDD, 0x16, 0x60, +- 0x54, 0xF3, 0x16, 0x60, 0x52, 0xF3, 0xFF, 0xA0, 0x40, 0x4C, 0x9D, 0x03, 0x59, 0xDF, 0x41, 0x4A, +- 0x2C, 0x40, 0x01, 0x2A, 0x05, 0x00, 0x00, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, +- 0x2C, 0x40, 0x02, 0x2A, 0x05, 0x00, 0x01, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, +- 0x2C, 0x40, 0x04, 0x2A, 0x05, 0x00, 0x02, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, +- 0x2A, 0x44, 0x51, 0x93, 0xEB, 0x83, 0xEB, 0x83, 0xA0, 0xDD, 0x2D, 0x58, 0xFF, 0xFF, 0x57, 0xF5, +- 0xCB, 0xF3, 0xCC, 0xF1, 0x00, 0x63, 0xC0, 0x87, 0xCD, 0xF1, 0x5A, 0xFD, 0xC0, 0x85, 0x65, 0x47, +- 0xC4, 0x84, 0x07, 0xB5, 0x18, 0x60, 0xE2, 0x64, 0x0F, 0x60, 0xA5, 0xFB, 0x02, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x02, 0x64, +- 0x08, 0x60, 0x13, 0xFB, 0xE2, 0x60, 0xA9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x57, 0xF5, 0x00, 0x64, 0x94, 0xFB, +- 0x95, 0xFB, 0x96, 0xFB, 0x74, 0xFB, 0x65, 0xF3, 0x00, 0x75, 0x00, 0x72, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x93, 0xC7, 0xF3, 0xED, 0xE2, 0xCC, 0x84, 0x5A, 0xFB, 0x00, 0x60, 0x04, 0x64, 0x08, 0x60, +- 0x13, 0xFB, 0xE2, 0x60, 0xC7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, +- 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x64, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2B, 0x05, 0x00, +- 0x67, 0x44, 0x16, 0x60, 0xC1, 0xFB, 0x16, 0x60, 0xD1, 0xFB, 0x16, 0x60, 0xF6, 0xF9, 0x2D, 0x60, +- 0x86, 0x65, 0xE4, 0x60, 0x58, 0x4D, 0xE7, 0x78, 0xFF, 0xFF, 0x64, 0xF3, 0xFF, 0xFF, 0x60, 0x40, +- 0x01, 0x2B, 0x05, 0x00, 0xFF, 0x60, 0xFF, 0x63, 0x16, 0x60, 0xC5, 0xFD, 0x08, 0x00, 0x2E, 0x60, +- 0x1E, 0x63, 0x16, 0x60, 0xC5, 0xFD, 0xE4, 0x60, 0x58, 0x4D, 0xFF, 0x78, 0xFF, 0xFF, 0xE4, 0x60, +- 0x58, 0x4D, 0x6E, 0x78, 0xFF, 0xFF, 0xE5, 0x60, 0x58, 0x4D, 0x18, 0x78, 0xFF, 0xFF, 0x57, 0xF5, +- 0x00, 0xF4, 0x65, 0xF1, 0x06, 0xF8, 0x17, 0x60, 0x22, 0xF3, 0x15, 0x60, 0xDD, 0xF1, 0xFB, 0x60, +- 0xFF, 0x65, 0x60, 0x44, 0xA4, 0x84, 0x60, 0x47, 0x64, 0x40, 0x10, 0x26, 0x04, 0xBC, 0x60, 0x47, +- 0x07, 0xFA, 0x2D, 0x60, 0x7E, 0x64, 0x40, 0x48, 0x10, 0x61, 0x00, 0x60, 0x00, 0x64, 0xE4, 0x60, +- 0x58, 0x4D, 0xA7, 0x78, 0xFF, 0xFF, 0x57, 0xF5, 0x3F, 0xFC, 0x5A, 0xF3, 0xC7, 0xF1, 0xAC, 0x83, +- 0x01, 0x64, 0x02, 0x02, 0x6B, 0xFB, 0x64, 0x43, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, +- 0x66, 0x44, 0x5A, 0xDB, 0x04, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xCF, 0x83, +- 0x72, 0xF3, 0x5A, 0xFD, 0xDC, 0x84, 0x72, 0xFB, 0x5C, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0x5C, 0xFB, +- 0x03, 0x03, 0xE3, 0x60, 0xBD, 0x78, 0xFF, 0xFF, 0x0A, 0x64, 0x5C, 0xFB, 0xA2, 0x4C, 0x20, 0x27, +- 0xF8, 0x01, 0x46, 0x60, 0x50, 0x65, 0x72, 0x44, 0xD4, 0x80, 0xFF, 0xFF, 0xF2, 0x04, 0x5D, 0xFB, +- 0x40, 0x48, 0x94, 0xF3, 0x5E, 0xFB, 0x40, 0x4A, 0x95, 0xF3, 0x96, 0xF3, 0x40, 0x4C, 0x60, 0x41, +- 0x65, 0xF1, 0x40, 0x63, 0xAD, 0x80, 0xF0, 0xA3, 0x09, 0x02, 0x3C, 0x03, 0x2C, 0x41, 0x2A, 0x44, +- 0x40, 0x4C, 0x28, 0x44, 0x40, 0x4A, 0x00, 0x64, 0x40, 0x48, 0xF4, 0x01, 0xD1, 0x80, 0x01, 0x02, +- 0x31, 0x04, 0x10, 0xA3, 0x80, 0x60, 0x00, 0x65, 0xA5, 0x80, 0xCF, 0x83, 0x08, 0x02, 0x28, 0x44, +- 0x60, 0x88, 0x2A, 0x44, 0x70, 0x8A, 0x2C, 0x44, 0x70, 0x8C, 0xF1, 0x81, 0xF5, 0x01, 0xE7, 0xA3, +- 0x64, 0x44, 0x00, 0xA0, 0x00, 0x62, 0x02, 0x02, 0x00, 0x61, 0x1C, 0x00, 0xE0, 0x84, 0xDE, 0x82, +- 0xFD, 0x04, 0x42, 0xFE, 0xF8, 0x84, 0x62, 0x45, 0xC7, 0x83, 0x60, 0x45, 0x02, 0xFE, 0xD5, 0x84, +- 0x02, 0x05, 0x01, 0x05, 0x61, 0x44, 0xCF, 0x83, 0x60, 0x41, 0x08, 0x03, 0x28, 0x44, 0x60, 0x88, +- 0x2A, 0x44, 0x70, 0x8A, 0x2C, 0x44, 0x70, 0x8C, 0xF1, 0x81, 0xF1, 0x01, 0xCE, 0x82, 0xE9, 0x81, +- 0xFD, 0x02, 0xF1, 0x81, 0x61, 0x44, 0x00, 0xA8, 0xFF, 0xFF, 0x2F, 0x03, 0x73, 0x40, 0x5D, 0xF3, +- 0xFF, 0xFF, 0x60, 0x47, 0xE8, 0x84, 0xE8, 0x84, 0x5E, 0xF3, 0x3F, 0xB5, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x84, 0x61, 0x45, 0xD4, 0x84, 0xC0, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x64, 0x44, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xC4, 0x85, 0x61, 0x44, 0xD4, 0x80, 0xFF, 0xFF, 0x0F, 0x03, 0x60, 0x53, 0xD4, 0x84, +- 0xFF, 0xFF, 0x74, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x01, 0xB4, 0x74, 0xFB, 0x13, 0x60, 0x06, 0xF3, +- 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, 0xE9, 0x60, 0xFB, 0x78, 0xFF, 0xFF, +- 0xC1, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x04, 0x64, 0x03, 0xFA, 0x00, 0xF4, 0x09, 0xF2, 0xFF, 0xFF, +- 0x60, 0x47, 0x00, 0x3A, 0x1C, 0x00, 0x60, 0x43, 0x00, 0x36, 0x1C, 0x00, 0xE0, 0xA0, 0xDA, 0x85, +- 0x16, 0x07, 0x26, 0x60, 0x16, 0x61, 0xA1, 0xD1, 0xFF, 0xFF, 0xD3, 0x80, 0xCB, 0x83, 0x0F, 0x02, +- 0x07, 0x0E, 0x59, 0xD3, 0xA5, 0xD0, 0xDA, 0x85, 0xD0, 0x80, 0xFF, 0xFF, 0x08, 0x02, 0xF9, 0x1F, +- 0x12, 0x1E, 0xA5, 0xD0, 0x59, 0xD3, 0xFF, 0xFF, 0x90, 0x80, 0xFF, 0x22, 0x0C, 0x00, 0xE4, 0x60, +- 0x63, 0x78, 0xFF, 0xFF, 0x13, 0x60, 0x44, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, +- 0x26, 0x60, 0x38, 0x64, 0x02, 0x00, 0x26, 0x60, 0x16, 0x64, 0x16, 0x60, 0xCF, 0xFB, 0x26, 0x46, +- 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, +- 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x66, 0xF1, 0x32, 0xF8, 0x67, 0xF1, 0x33, 0xF8, +- 0x68, 0xF1, 0x34, 0xF8, 0x00, 0x65, 0xEF, 0x60, 0x58, 0x4E, 0xDC, 0x78, 0xFF, 0xFF, 0x61, 0x44, +- 0x15, 0x60, 0xC2, 0xFB, 0x50, 0x63, 0x2A, 0xFC, 0xAB, 0xF3, 0x19, 0xFA, 0x00, 0x64, 0x3E, 0xFA, +- 0x87, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x65, 0xF1, 0x06, 0xF8, 0x17, 0x60, 0x22, 0xF3, 0x15, 0x60, +- 0xDD, 0xF1, 0xFB, 0x60, 0xFF, 0xB7, 0x64, 0x40, 0x10, 0x26, 0x04, 0xBC, 0x60, 0x47, 0x07, 0xFA, +- 0x2D, 0x60, 0xA6, 0x65, 0xE4, 0x60, 0x58, 0x4D, 0xE7, 0x78, 0xFF, 0xFF, 0x64, 0xF3, 0x2E, 0x60, +- 0x1E, 0x63, 0x60, 0x40, 0x01, 0x27, 0x67, 0x43, 0x16, 0x60, 0xD5, 0xFD, 0x2D, 0x60, 0x9E, 0x64, +- 0x40, 0x48, 0x10, 0x61, 0x00, 0x60, 0x00, 0x64, 0xE4, 0x60, 0x58, 0x4D, 0xA7, 0x78, 0xFF, 0xFF, +- 0x26, 0x46, 0x3F, 0xFC, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x20, 0x44, 0x80, 0x26, 0x11, 0x00, +- 0x80, 0xBC, 0x40, 0x40, 0x00, 0x64, 0x94, 0xFB, 0x95, 0xFB, 0x96, 0xFB, 0x74, 0xFB, 0x65, 0xF3, +- 0x00, 0x75, 0x00, 0x72, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x93, 0xC7, 0xF3, 0xED, 0xE2, 0xCC, 0x84, +- 0x5A, 0xFB, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x12, 0xFB, +- 0x5A, 0xDB, 0x00, 0x64, 0x72, 0xFB, 0x74, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x3E, 0x63, 0x18, 0x60, +- 0x94, 0x61, 0x59, 0xD1, 0x61, 0x46, 0x07, 0x1B, 0xFC, 0x1F, 0x2D, 0x60, 0xC8, 0x62, 0xA2, 0xDF, +- 0x01, 0x65, 0x00, 0x61, 0x16, 0x00, 0x18, 0x60, 0xD6, 0x61, 0x49, 0xD1, 0xCB, 0x83, 0xFD, 0x18, +- 0x63, 0x41, 0x04, 0xA1, 0x61, 0x45, 0x66, 0x43, 0x2D, 0x60, 0xC8, 0x64, 0xDC, 0x84, 0x60, 0xFE, +- 0xBD, 0xD1, 0xA0, 0xD9, 0xCD, 0x81, 0x20, 0xFE, 0xF9, 0x02, 0x66, 0x44, 0x18, 0x60, 0x96, 0x7C, +- 0xD0, 0x81, 0x5A, 0xF3, 0xC7, 0xF1, 0x2D, 0x60, 0xC6, 0x63, 0x00, 0xA0, 0x64, 0x5F, 0xBD, 0xDB, +- 0x0F, 0x60, 0x6D, 0xF1, 0x02, 0x02, 0x01, 0x18, 0x01, 0xB9, 0x61, 0x44, 0x60, 0xFE, 0xA3, 0xDB, +- 0xFC, 0xA3, 0x65, 0x44, 0x03, 0xA4, 0xA3, 0xDB, 0x20, 0xFE, 0x2D, 0x58, 0xFF, 0xFF, 0x17, 0x60, +- 0x23, 0xFB, 0xCD, 0x81, 0x28, 0xD3, 0x5A, 0x88, 0xDC, 0x83, 0x31, 0x18, 0xFB, 0x03, 0x61, 0x40, +- 0x7F, 0x3A, 0x06, 0x00, 0x17, 0x60, 0x23, 0xF3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x00, 0xF4, +- 0x60, 0xFE, 0xA3, 0xD1, 0x5D, 0xD8, 0x61, 0x40, 0x7F, 0x3A, 0x08, 0x00, 0x20, 0xFE, 0x17, 0x60, +- 0x23, 0xF3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x00, 0xF4, 0x60, 0xFE, 0xBF, 0xD3, 0x5D, 0xDA, +- 0xFF, 0xB4, 0x00, 0x7F, 0x12, 0x03, 0xDF, 0x83, 0x61, 0x40, 0x7F, 0x3A, 0x0A, 0x00, 0x20, 0xFE, +- 0x60, 0x45, 0x17, 0x60, 0x23, 0xF3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x65, 0x44, 0x00, 0xF4, +- 0x60, 0xFE, 0xBD, 0xD1, 0xCC, 0x84, 0x5D, 0xD8, 0xEF, 0x02, 0x20, 0xFE, 0xCB, 0x01, 0x17, 0x60, +- 0x23, 0xF1, 0xFD, 0xA1, 0xFF, 0xB1, 0xC1, 0x83, 0xA2, 0xDD, 0x2D, 0x58, 0xFF, 0xFF, 0x67, 0x5C, +- 0x14, 0x60, 0x26, 0x61, 0xA1, 0xD3, 0xA5, 0xD9, 0x10, 0x18, 0x60, 0x43, 0x2D, 0x60, 0xEE, 0x64, +- 0xA5, 0xDB, 0x60, 0xFE, 0xA0, 0xDD, 0x20, 0xFE, 0xDC, 0x84, 0xCF, 0x83, 0xE3, 0x83, 0x59, 0xD1, +- 0xDC, 0x84, 0x60, 0xFE, 0xA0, 0xD9, 0x20, 0xFE, 0xFA, 0x1F, 0x2D, 0x58, 0xFF, 0xFF, 0x15, 0x60, +- 0xDC, 0xF1, 0x15, 0x60, 0xDD, 0xF3, 0x64, 0x40, 0x01, 0x2A, 0x02, 0xBC, 0x64, 0x40, 0x02, 0x2A, +- 0x04, 0xBC, 0x64, 0x40, 0x04, 0x2A, 0xEF, 0xB4, 0x15, 0x60, 0xDD, 0xFB, 0x07, 0xB4, 0x60, 0xFE, +- 0x17, 0x60, 0x10, 0xFB, 0x20, 0xFE, 0x07, 0x7C, 0x15, 0x60, 0xDC, 0xF9, 0x2D, 0x58, 0xFF, 0xFF, +- 0x20, 0x40, 0x20, 0x2A, 0x0A, 0x00, 0x0A, 0x60, 0x77, 0xF1, 0x50, 0xF3, 0x2E, 0x60, 0x31, 0x63, +- 0x60, 0xFE, 0xBD, 0xD9, 0x60, 0x47, 0xA3, 0xDB, 0x20, 0xFE, 0x2D, 0x58, 0xFF, 0xFF, 0x0E, 0x57, +- 0x32, 0x40, 0x40, 0x26, 0x24, 0x00, 0x45, 0x48, 0x00, 0x60, 0x10, 0x61, 0xB5, 0x60, 0x58, 0x4D, +- 0x9F, 0x78, 0xFF, 0xFF, 0x1C, 0x03, 0xF2, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x00, 0x60, 0x48, 0x61, +- 0x28, 0x44, 0x59, 0xDA, 0x03, 0x64, 0x38, 0x43, 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, +- 0x39, 0x44, 0x59, 0xDA, 0x06, 0x64, 0x23, 0xFA, 0x1F, 0x60, 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, +- 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, +- 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, 0x4F, 0x00, 0x45, 0x48, 0x00, 0x60, 0x68, 0x61, +- 0xB5, 0x60, 0x58, 0x4D, 0x9F, 0x78, 0xFF, 0xFF, 0x47, 0x03, 0xF2, 0x60, 0x01, 0x64, 0x24, 0xFA, +- 0x02, 0x60, 0x00, 0x61, 0x46, 0x4A, 0x38, 0x44, 0x54, 0x94, 0x03, 0x64, 0x01, 0x02, 0x09, 0x00, +- 0x06, 0x63, 0x4A, 0x61, 0x38, 0x46, 0xBD, 0xD0, 0xCC, 0x84, 0x2A, 0x46, 0x59, 0xD8, 0xFA, 0x02, +- 0x06, 0x00, 0xDA, 0x81, 0x38, 0x43, 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, 0x05, 0x63, +- 0x28, 0x44, 0x02, 0xA8, 0x25, 0xFA, 0x07, 0x02, 0x03, 0x64, 0x39, 0x43, 0xBD, 0xD1, 0xCC, 0x84, +- 0x59, 0xD8, 0xFC, 0x02, 0x08, 0x63, 0x28, 0x44, 0x03, 0xA8, 0x16, 0x60, 0x82, 0xF3, 0x0F, 0x03, +- 0xE8, 0x85, 0xC7, 0x85, 0x60, 0x43, 0xFE, 0xA3, 0x2D, 0x60, 0x06, 0x64, 0x58, 0xD1, 0xD9, 0x81, +- 0xA1, 0xD8, 0x7E, 0x2A, 0x02, 0x00, 0x00, 0xF4, 0x02, 0x61, 0xF8, 0x1F, 0x65, 0x43, 0x2A, 0x46, +- 0x23, 0xFC, 0x1F, 0x60, 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, +- 0x40, 0x26, 0x1B, 0x00, 0x45, 0x48, 0x00, 0x60, 0x06, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x9F, 0x78, +- 0xFF, 0xFF, 0x13, 0x03, 0x02, 0x64, 0x23, 0xFA, 0xF2, 0x60, 0x00, 0x64, 0x5A, 0xDA, 0x28, 0x44, +- 0x5A, 0xDA, 0xFF, 0xFF, 0x1F, 0x60, 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0xA0, 0xD3, +- 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x03, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, +- 0xDD, 0x98, 0xFF, 0xFF, 0x97, 0xF1, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0C, 0x03, +- 0x08, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x05, 0x03, 0xA2, 0xDB, 0x02, 0x24, 0xC6, 0xFE, 0xDD, 0x98, +- 0xFF, 0xFF, 0xFF, 0x60, 0xFE, 0x64, 0xA2, 0xDB, 0xDD, 0x98, 0xFF, 0xFF, 0xA2, 0xFF, 0x32, 0x40, +- 0x40, 0x26, 0x3C, 0x00, 0x7B, 0xF3, 0x67, 0x43, 0xDC, 0x84, 0xCC, 0x84, 0x37, 0x03, 0x60, 0x46, +- 0x0A, 0x02, 0x7B, 0xFD, 0x00, 0x60, 0x46, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x9F, 0x78, 0xFF, 0xFF, +- 0x66, 0x44, 0x7B, 0xFB, 0x2C, 0x03, 0x46, 0x4B, 0x25, 0x60, 0xD0, 0x61, 0x18, 0x64, 0x23, 0xFA, +- 0xF1, 0x60, 0x00, 0x64, 0x24, 0xFA, 0x4A, 0x65, 0xA2, 0xFF, 0x2C, 0x63, 0x59, 0xD1, 0xA2, 0xDF, +- 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF7, 0x1F, 0x12, 0x63, +- 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, +- 0x1F, 0x60, 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x2B, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0xA6, 0xFE, 0x00, 0x64, 0x7B, 0xFB, 0xA3, 0xFF, 0xCA, 0x60, +- 0x7E, 0x78, 0xFF, 0xFF, 0xA6, 0xFE, 0xBA, 0x05, 0xA7, 0xFE, 0x0A, 0x05, 0xA5, 0xFE, 0x03, 0x04, +- 0xE6, 0x60, 0x8E, 0x78, 0xFF, 0xFF, 0xA4, 0xFE, 0xF2, 0x04, 0xE7, 0x60, 0x1F, 0x78, 0xFF, 0xFF, +- 0x36, 0x45, 0x19, 0x60, 0x86, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0xF3, 0x7D, 0xF1, +- 0x60, 0x47, 0x07, 0xB4, 0x4E, 0xFB, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, +- 0x9D, 0x84, 0xA1, 0x80, 0xA0, 0x83, 0x15, 0x03, 0x7D, 0xFD, 0x08, 0x60, 0x24, 0xF1, 0x00, 0x60, +- 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x31, 0x44, 0xDE, 0xB4, 0x40, 0x51, 0x01, 0x7C, +- 0xBC, 0xF9, 0x49, 0xF3, 0x01, 0x63, 0x60, 0x40, 0xFF, 0x26, 0x49, 0xFD, 0xCA, 0x60, 0x7E, 0x78, +- 0xFF, 0xFF, 0xE6, 0x60, 0x8E, 0x78, 0xFF, 0xFF, 0x26, 0x60, 0xB0, 0x63, 0xBD, 0xD3, 0xBD, 0xD1, +- 0xBD, 0xD1, 0xB0, 0x84, 0xB0, 0x84, 0xFF, 0xFF, 0x07, 0x02, 0x6A, 0xFB, 0x31, 0x44, 0xFE, 0xB4, +- 0x40, 0x51, 0x0D, 0x64, 0x05, 0xFB, 0x1A, 0x00, 0x28, 0xF3, 0xFF, 0xFF, 0x13, 0x60, 0x52, 0xF3, +- 0xC5, 0xFB, 0x64, 0xFB, 0x0F, 0x60, 0x85, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x46, 0x5E, +- 0x31, 0x44, 0x21, 0xBC, 0x40, 0x51, 0xED, 0xE2, 0x0F, 0x4E, 0xD0, 0x60, 0x58, 0x4F, 0xA8, 0x78, +- 0xFF, 0xFF, 0x0E, 0x4F, 0x00, 0x00, 0xE8, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0xD7, 0xFE, 0xCA, 0x60, +- 0x7E, 0x78, 0xFF, 0xFF, 0x2E, 0xF5, 0x27, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, +- 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, +- 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, +- 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, 0x60, 0x43, +- 0x61, 0x46, 0x26, 0x02, 0x0B, 0x60, 0x82, 0xF3, 0xDA, 0x81, 0x60, 0x45, 0xD5, 0x80, 0xA1, 0xD1, +- 0x04, 0x03, 0xD3, 0x80, 0xD9, 0x81, 0xFA, 0x02, 0x08, 0x00, 0xA1, 0xDD, 0xD9, 0x84, 0x0B, 0x60, +- 0x82, 0xFB, 0x4A, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xA2, 0xDB, 0x66, 0x45, 0x63, 0x46, 0x06, 0xF2, +- 0xFF, 0x60, 0x01, 0x7C, 0xA0, 0x9C, 0x06, 0xF8, 0x65, 0x46, 0x70, 0xF3, 0x60, 0x40, 0x10, 0x2A, +- 0x03, 0x00, 0xCC, 0x84, 0x80, 0x2B, 0x70, 0xFB, 0xE7, 0x60, 0x58, 0x4E, 0x81, 0x78, 0xFF, 0xFF, +- 0xAD, 0x01, 0x2E, 0xF5, 0x28, 0xF0, 0x18, 0x60, 0x12, 0xF9, 0x27, 0xF2, 0x15, 0x60, 0x02, 0x65, +- 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, +- 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, +- 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, +- 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, +- 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x12, 0x02, 0x63, 0x46, 0x06, 0xF2, 0xFF, 0xFF, 0x02, 0xB0, +- 0x08, 0xBC, 0x0C, 0x03, 0x06, 0xFA, 0xE7, 0x60, 0x58, 0x4E, 0x81, 0x78, 0xFF, 0xFF, 0x08, 0x60, +- 0x1E, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x6F, 0x01, 0x01, 0x64, +- 0x51, 0xFB, 0x28, 0x60, 0x4E, 0x64, 0x52, 0xFB, 0x15, 0x60, 0xC3, 0xF3, 0xFF, 0xFF, 0x15, 0x18, +- 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x10, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE7, 0x60, +- 0x3D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2B, 0x60, 0x88, 0x61, 0xFF, 0x60, +- 0x80, 0x65, 0xA1, 0xD3, 0xFF, 0xFF, 0xA4, 0x80, 0x59, 0xD3, 0x05, 0x02, 0x04, 0x1B, 0x59, 0xD3, +- 0xFF, 0xFF, 0x01, 0x1B, 0x15, 0x00, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x08, 0x60, +- 0x1B, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, +- 0x08, 0x60, 0x16, 0xFB, 0xE7, 0x60, 0x60, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x00, 0x60, 0x04, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x9F, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x23, 0xFA, +- 0xF1, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x1F, 0x60, 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x00, 0x60, 0x30, 0x64, +- 0x08, 0x60, 0x16, 0xFB, 0xD2, 0x60, 0xB5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0xCA, 0x60, 0x7E, 0x78, +- 0xFF, 0xFF, 0x0E, 0x57, 0x63, 0x46, 0x43, 0x47, 0x22, 0xF2, 0x76, 0xF2, 0x02, 0x1B, 0x01, 0x1B, +- 0x0C, 0x00, 0x60, 0x46, 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, +- 0xFF, 0xFF, 0x27, 0x46, 0x76, 0xF2, 0xFF, 0xFF, 0xF4, 0x1B, 0x37, 0x58, 0xFF, 0xFF, 0xE7, 0x60, +- 0x9F, 0x64, 0x08, 0x60, 0x2A, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, +- 0x08, 0x60, 0x21, 0xFB, 0x5A, 0xDB, 0x10, 0x60, 0x42, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x2F, 0x58, +- 0xFF, 0xFF, 0x28, 0xF3, 0x7D, 0xF1, 0x60, 0x47, 0x07, 0xB4, 0x4E, 0xFB, 0x01, 0x61, 0x03, 0x03, +- 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0xA1, 0x80, 0xB1, 0x83, 0x16, 0x02, 0xCF, 0x85, 0xA7, 0x80, +- 0x7D, 0xFD, 0x0B, 0x02, 0x01, 0x65, 0xE5, 0x60, 0x58, 0x4E, 0xA6, 0x78, 0xFF, 0xFF, 0x31, 0x44, +- 0xDF, 0xB4, 0x40, 0x51, 0xD0, 0x60, 0xD9, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x21, 0xF1, 0x00, 0x60, +- 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xE6, 0x60, 0x8E, 0x78, 0xFF, 0xFF, 0x28, 0xF3, +- 0x7D, 0xF1, 0x60, 0x47, 0x07, 0xB4, 0x4E, 0xFB, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, +- 0xFD, 0x02, 0x9D, 0x84, 0xA1, 0x80, 0xA0, 0x83, 0x13, 0x03, 0x7D, 0xFD, 0x08, 0x60, 0x24, 0xF1, +- 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x7D, 0xF1, 0x31, 0x44, 0x64, 0x40, +- 0xFF, 0x26, 0x03, 0x00, 0x21, 0xBC, 0x40, 0x51, 0x03, 0x00, 0xCA, 0x60, 0x7E, 0x78, 0xFF, 0xFF, +- 0xE6, 0x60, 0x8E, 0x78, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, 0x1B, 0x00, 0x45, 0x48, +- 0x00, 0x60, 0x06, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0x9F, 0x78, 0xFF, 0xFF, 0x13, 0x03, 0x02, 0x64, +- 0x23, 0xFA, 0xF2, 0x60, 0x04, 0x64, 0x5A, 0xDA, 0x28, 0x44, 0x5A, 0xDA, 0xFF, 0xFF, 0x1F, 0x60, +- 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0x79, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, +- 0x60, 0x46, 0x0E, 0xF2, 0x59, 0x03, 0x60, 0x40, 0xF0, 0x37, 0x46, 0x00, 0xFF, 0x37, 0x3B, 0x00, +- 0xFD, 0x37, 0x33, 0x00, 0x18, 0x37, 0x27, 0x00, 0xFE, 0x37, 0x2A, 0x00, 0xF8, 0x37, 0x0A, 0x00, +- 0x60, 0x47, 0xFF, 0xB5, 0x10, 0x60, 0x24, 0x62, 0x46, 0xD1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xD8, 0x01, 0x06, 0xB4, 0xFD, 0x7F, 0x0E, 0xFA, 0x1E, 0x60, +- 0xF8, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xF9, 0xFE, 0xC9, 0x01, 0xDE, 0x60, 0x58, 0x4F, 0x6C, 0x78, 0xFF, 0xFF, 0x14, 0x00, +- 0xE1, 0x60, 0x58, 0x4F, 0x32, 0x78, 0xFF, 0xFF, 0xBF, 0x03, 0x23, 0xF0, 0x60, 0x40, 0x04, 0x26, +- 0xE3, 0x1B, 0x02, 0x26, 0xE1, 0x18, 0xA2, 0xFF, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, +- 0x8F, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0x8F, 0xFB, 0x1F, 0x60, 0x20, 0x64, 0x40, 0x4B, 0xF6, 0x60, +- 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, 0xA8, 0x01, 0xAC, 0xFE, 0x09, 0x05, 0xAD, 0xFE, 0x0F, 0x05, +- 0xAE, 0xFE, 0xA2, 0x05, 0xAF, 0xFE, 0x37, 0x05, 0xCA, 0x60, 0x7E, 0x78, 0xFF, 0xFF, 0x08, 0x60, +- 0x11, 0xF1, 0x20, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xF5, 0x01, 0x10, 0x60, +- 0x56, 0x65, 0x03, 0x61, 0x07, 0x00, 0xA2, 0xDD, 0x58, 0x4F, 0x64, 0x58, 0xFF, 0xFF, 0x00, 0xB9, +- 0xFF, 0xFF, 0x08, 0x03, 0x00, 0x63, 0xA5, 0xD1, 0x5A, 0xD3, 0xDA, 0x85, 0x00, 0xA8, 0xCD, 0x81, +- 0xF2, 0x02, 0xF8, 0x02, 0xE1, 0x01, 0x10, 0x60, 0x20, 0x62, 0x10, 0x60, 0x46, 0x65, 0xE8, 0x60, +- 0xA9, 0x63, 0x5A, 0xDF, 0xD6, 0x80, 0xFF, 0xFF, 0x04, 0x03, 0x5A, 0xDF, 0x5A, 0xDF, 0x5A, 0xDD, +- 0xF9, 0x01, 0x10, 0x60, 0x54, 0x65, 0x5A, 0xDF, 0xD6, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x5A, 0xDD, +- 0xFB, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x24, 0x64, 0x40, 0x41, 0x10, 0x60, 0x22, 0x63, +- 0xA3, 0xD1, 0x00, 0x64, 0xD0, 0x80, 0x06, 0x61, 0x08, 0x03, 0xBD, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, +- 0xB0, 0x84, 0xCD, 0x81, 0xA3, 0xDB, 0x06, 0xA3, 0xF9, 0x02, 0x10, 0x60, 0x48, 0x63, 0xA3, 0xD1, +- 0x00, 0x64, 0xD0, 0x80, 0x07, 0x61, 0x19, 0x03, 0xBD, 0xDB, 0x64, 0x44, 0xFE, 0xA3, 0x02, 0xA3, +- 0xCD, 0x81, 0xE8, 0x84, 0xE3, 0x03, 0x02, 0x05, 0xE1, 0x03, 0xF9, 0x01, 0x77, 0xFB, 0x79, 0xFD, +- 0x61, 0x5C, 0xA3, 0xD3, 0x78, 0xF9, 0x03, 0x18, 0x58, 0x4F, 0x60, 0x58, 0xFF, 0xFF, 0x79, 0xF3, +- 0x78, 0xF1, 0x60, 0x43, 0x77, 0xF3, 0x64, 0x41, 0xEA, 0x01, 0x21, 0x43, 0x10, 0x60, 0x48, 0x65, +- 0xD7, 0x80, 0xBD, 0xD1, 0xBD, 0xD3, 0x03, 0x02, 0xCA, 0x60, 0x7E, 0x78, 0xFF, 0xFF, 0xA0, 0x84, +- 0xBD, 0xD1, 0x43, 0x41, 0xF5, 0x03, 0xE8, 0x60, 0xAE, 0x64, 0x64, 0x58, 0x40, 0x4F, 0x2A, 0xF0, +- 0x83, 0x60, 0xFF, 0x65, 0x64, 0x47, 0x03, 0x2B, 0x01, 0x00, 0x17, 0x00, 0x03, 0x26, 0x03, 0xAC, +- 0x60, 0x47, 0xA4, 0x84, 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, +- 0x2E, 0xFA, 0x64, 0x41, 0xCB, 0xF3, 0x2F, 0xFA, 0x60, 0x43, 0xCC, 0xF3, 0x30, 0xFA, 0xCD, 0xF1, +- 0x31, 0xF8, 0x32, 0xFC, 0x33, 0xFA, 0x34, 0xF8, 0x19, 0x00, 0x60, 0x47, 0xA4, 0x84, 0x2A, 0xFA, +- 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x36, 0xF2, 0x32, 0xFA, +- 0x37, 0xF2, 0x33, 0xFA, 0x38, 0xF2, 0x34, 0xFA, 0xCB, 0xF3, 0x2F, 0xFA, 0x36, 0xFA, 0xCC, 0xF3, +- 0x30, 0xFA, 0x37, 0xFA, 0xCD, 0xF3, 0x31, 0xFA, 0x38, 0xFA, 0x64, 0x41, 0x1C, 0xF2, 0x13, 0xFA, +- 0x00, 0xF4, 0x0D, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, 0x28, 0x00, 0x26, 0x46, 0x04, 0x63, +- 0x03, 0xFC, 0x00, 0xF4, 0x0D, 0xF2, 0x06, 0xFA, 0xEA, 0x60, 0x58, 0x4E, 0x49, 0x78, 0xFF, 0xFF, +- 0xFF, 0xA0, 0x59, 0xF5, 0x19, 0x02, 0x39, 0xF2, 0x26, 0x46, 0x3F, 0xFA, 0x00, 0xF4, 0x00, 0x60, +- 0x81, 0x67, 0x0D, 0xFA, 0x7C, 0x64, 0x01, 0xFA, 0x26, 0x46, 0x00, 0x64, 0x3E, 0xFA, 0x1E, 0x60, +- 0xE0, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xC8, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xF0, +- 0x42, 0x64, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x04, 0x3F, 0xFA, 0x1C, 0xF2, 0x13, 0xFA, 0x26, 0xF2, +- 0x27, 0xF0, 0x60, 0x47, 0x00, 0xF4, 0x1F, 0xFA, 0x64, 0x47, 0x20, 0xFA, 0x61, 0x44, 0x21, 0xFA, +- 0x01, 0x67, 0x0D, 0xFA, 0x10, 0x61, 0x26, 0x60, 0x64, 0x64, 0x1E, 0x63, 0x58, 0xD1, 0xCD, 0x81, +- 0xBD, 0xD8, 0xFC, 0x02, 0x9A, 0xF1, 0xB7, 0xF1, 0x64, 0x5E, 0x64, 0x5F, 0x44, 0x63, 0xBD, 0xDA, +- 0x13, 0x60, 0x2F, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x09, 0xBC, 0x4A, 0xD3, +- 0x60, 0x45, 0x60, 0x40, 0x01, 0x36, 0x03, 0x64, 0x02, 0x36, 0x01, 0x64, 0xB4, 0x84, 0x06, 0xA2, +- 0xA2, 0xD1, 0xBD, 0xDA, 0x64, 0x47, 0xBD, 0xDA, 0xB4, 0xF3, 0xB5, 0xF1, 0x60, 0x47, 0xBD, 0xDA, +- 0x64, 0x47, 0xC3, 0xF1, 0xBD, 0xDA, 0x64, 0x44, 0xBD, 0xDA, 0x26, 0x46, 0x00, 0x64, 0x23, 0xF0, +- 0x3B, 0xF0, 0x64, 0x40, 0x10, 0x2A, 0x06, 0x00, 0xC0, 0x67, 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, +- 0xE8, 0x84, 0x10, 0xBC, 0x3E, 0xFA, 0x1E, 0x60, 0xE0, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x26, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0x00, 0x66, 0x46, 0x46, +- 0x2F, 0x58, 0xFF, 0xFF, 0x04, 0x60, 0x5C, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0xA2, 0x78, 0xFF, 0xFF, +- 0x66, 0x44, 0x59, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x2F, 0x58, 0xFF, 0xFF, 0x59, 0xF5, 0xAB, 0xF1, +- 0x19, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x08, 0x64, 0x2A, 0xFA, 0x80, 0x7E, 0xF8, 0x7F, 0x0E, 0xFA, +- 0x87, 0xF1, 0x07, 0xF8, 0x01, 0x60, 0x60, 0x67, 0x2C, 0xFA, 0x1D, 0x60, 0x00, 0x67, 0x2D, 0xFA, +- 0x01, 0x60, 0x00, 0x67, 0x2E, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, 0x32, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, +- 0x33, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0x34, 0xF8, 0x00, 0x63, 0x3B, 0xFC, 0x3D, 0xFC, 0x01, 0x64, +- 0x3A, 0xFA, 0x66, 0x64, 0x39, 0xFA, 0x3C, 0xFC, 0xAA, 0x60, 0xAA, 0x64, 0x00, 0xF4, 0x02, 0xFA, +- 0x00, 0x60, 0x03, 0x64, 0x5A, 0xDA, 0x1D, 0x60, 0x60, 0x64, 0x5A, 0xDA, 0x01, 0x60, 0x00, 0x64, +- 0x5A, 0xDA, 0x81, 0x7F, 0x18, 0x7E, 0x08, 0xFA, 0x01, 0x60, 0x01, 0x64, 0x0A, 0xFA, 0x00, 0x64, +- 0x0E, 0xFA, 0x2D, 0x58, 0xFF, 0xFF, 0x59, 0xF5, 0x3D, 0xF2, 0x3C, 0xF2, 0xCC, 0x83, 0x00, 0xA8, +- 0x03, 0x03, 0x08, 0x28, 0x3D, 0xFC, 0x42, 0x00, 0x3D, 0xFA, 0x3A, 0xF2, 0x3B, 0xF0, 0x00, 0x63, +- 0x00, 0xF4, 0x07, 0xFC, 0x01, 0xB0, 0x0B, 0xFA, 0x19, 0x03, 0x1F, 0xF8, 0xFF, 0xFF, 0x18, 0x64, +- 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0x1F, 0xF2, 0x1E, 0xF0, 0x59, 0xF5, 0x00, 0xA8, 0x3B, 0xF8, 0xD0, 0x80, 0x06, 0x03, 0x05, 0x03, +- 0x04, 0x60, 0x5C, 0x63, 0x0F, 0x64, 0x3A, 0xFA, 0x39, 0xFC, 0x00, 0xF4, 0x00, 0x64, 0x06, 0xFA, +- 0xEA, 0x60, 0x58, 0x4E, 0x49, 0x78, 0xFF, 0xFF, 0x59, 0xF5, 0x00, 0xF4, 0x81, 0x60, 0x00, 0x64, +- 0x06, 0xFA, 0x32, 0x47, 0x07, 0xFA, 0xB7, 0xF1, 0x00, 0x7F, 0x64, 0x5E, 0x09, 0xFA, 0x59, 0xF5, +- 0x00, 0x64, 0x15, 0xFA, 0x39, 0xF2, 0x3F, 0xFA, 0x1E, 0x60, 0xCE, 0x64, 0x0F, 0x60, 0x90, 0xFB, +- 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xE3, 0x60, 0xC0, 0x78, +- 0xFF, 0xFF, 0x66, 0x45, 0x0E, 0xF2, 0x0F, 0xF0, 0x10, 0xF0, 0x64, 0x41, 0x01, 0xA8, 0x59, 0xF5, +- 0x09, 0x02, 0xAD, 0x83, 0x64, 0x44, 0xAC, 0x84, 0x08, 0x24, 0x0A, 0x63, 0x3C, 0xFC, 0x3D, 0xFC, +- 0x1A, 0x02, 0x2D, 0x00, 0x03, 0x3A, 0x03, 0x00, 0x00, 0x64, 0x3C, 0xFA, 0x29, 0x00, 0x04, 0x3A, +- 0x09, 0x00, 0x0A, 0x64, 0x3C, 0xFA, 0x01, 0x64, 0x3A, 0xFA, 0x00, 0xF4, 0x00, 0x64, 0x1F, 0xFA, +- 0x1E, 0xFA, 0x1E, 0x00, 0x02, 0x3A, 0x1E, 0x00, 0x64, 0x44, 0xAD, 0x83, 0xAC, 0x84, 0x02, 0x03, +- 0x3C, 0xFC, 0x3D, 0xFC, 0x15, 0x03, 0x3A, 0xFA, 0xF8, 0x65, 0x52, 0x63, 0x64, 0x44, 0x01, 0x36, +- 0x0D, 0x00, 0x12, 0xA3, 0x64, 0x40, 0x02, 0x2A, 0x02, 0x00, 0xC7, 0x83, 0xC7, 0x83, 0x64, 0x40, +- 0x08, 0x2A, 0x01, 0x00, 0xC7, 0x83, 0x64, 0x40, 0x04, 0x26, 0xC7, 0x83, 0x39, 0xFC, 0x00, 0x64, +- 0x2E, 0x58, 0xFF, 0xFF, 0x3B, 0xF0, 0x3A, 0xF2, 0x65, 0x46, 0x06, 0xF2, 0x40, 0x47, 0x1C, 0x18, +- 0x32, 0x47, 0x07, 0xFA, 0x18, 0x7E, 0x81, 0x7F, 0x08, 0xFA, 0x01, 0x60, 0x01, 0x63, 0xB7, 0xF3, +- 0x0A, 0xFC, 0x00, 0x7F, 0x09, 0xFA, 0x27, 0x40, 0x01, 0x2A, 0x0E, 0x00, 0x1F, 0xF8, 0x18, 0x64, +- 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0x1E, 0xF0, 0x59, 0xF5, 0x3B, 0xF8, 0x65, 0x46, 0x27, 0x40, 0x02, 0x26, 0x02, 0x00, 0x00, 0xF4, +- 0x13, 0x00, 0x6E, 0x61, 0xFF, 0x60, 0xFE, 0x64, 0x00, 0x60, 0x0E, 0x63, 0x58, 0xD1, 0x59, 0xD8, +- 0xFD, 0x1F, 0x01, 0x60, 0xEE, 0x63, 0x00, 0xF4, 0x02, 0x61, 0x58, 0xD1, 0x59, 0xD8, 0x7E, 0x3A, +- 0x02, 0x00, 0x00, 0xF4, 0x02, 0x61, 0xF9, 0x1F, 0x27, 0x40, 0x04, 0x26, 0x1A, 0x00, 0x46, 0x4B, +- 0x0F, 0x60, 0x67, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x0E, 0x03, 0x89, 0xF0, 0xEB, 0x60, +- 0x58, 0x4D, 0x00, 0x78, 0xFF, 0xFF, 0x65, 0x44, 0xAC, 0x86, 0xFF, 0xFF, 0x08, 0x03, 0xEB, 0x60, +- 0x58, 0x4D, 0x00, 0x78, 0xFF, 0xFF, 0x04, 0x00, 0x2B, 0x46, 0x82, 0xFC, 0x00, 0xF4, 0x82, 0xFC, +- 0x00, 0xF4, 0x27, 0x40, 0x08, 0x26, 0x19, 0x00, 0x46, 0x4B, 0x0F, 0x60, 0x85, 0xF3, 0xFF, 0xFF, +- 0x00, 0xA8, 0x60, 0x46, 0x0E, 0x03, 0x89, 0xF0, 0xEB, 0x60, 0x58, 0x4D, 0x00, 0x78, 0xFF, 0xFF, +- 0x65, 0x44, 0xAC, 0x86, 0xFF, 0xFF, 0x08, 0x03, 0xEB, 0x60, 0x58, 0x4D, 0x00, 0x78, 0xFF, 0xFF, +- 0x04, 0x00, 0x65, 0x46, 0x02, 0xFA, 0x00, 0xF4, 0x82, 0xFC, 0x01, 0x64, 0x2E, 0x58, 0xFF, 0xFF, +- 0x01, 0x61, 0x02, 0x64, 0x7A, 0x63, 0x58, 0xD0, 0xAB, 0x46, 0xA0, 0xD8, 0xAB, 0x46, 0xFB, 0x1F, +- 0xAB, 0x46, 0x00, 0xF4, 0xCD, 0x81, 0xAB, 0x46, 0x00, 0xF4, 0xF3, 0x02, 0x2D, 0x58, 0xFF, 0xFF, +- 0x00, 0x60, 0x2A, 0x61, 0xB5, 0x60, 0x58, 0x4D, 0xA2, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x58, 0xFB, +- 0x04, 0x64, 0x03, 0xFA, 0x67, 0x44, 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0x32, 0xFA, 0x33, 0xFA, +- 0x34, 0xFA, 0x12, 0x60, 0x80, 0x64, 0x87, 0xF1, 0x0E, 0xFA, 0x07, 0xF8, 0x00, 0x64, 0x3E, 0xFA, +- 0x0A, 0x60, 0x07, 0xFB, 0x06, 0xA2, 0x10, 0x60, 0x5C, 0x64, 0xA2, 0xDB, 0x04, 0x64, 0x5A, 0xDB, +- 0x06, 0x64, 0x5A, 0xDB, 0xED, 0x60, 0xD9, 0x64, 0x08, 0x60, 0x2D, 0xFB, 0x00, 0x64, 0x0A, 0x60, +- 0x0D, 0xFB, 0x06, 0xA2, 0x10, 0x60, 0x60, 0x64, 0xA2, 0xDB, 0x08, 0x64, 0x5A, 0xDB, 0x06, 0x64, +- 0x5A, 0xDB, 0xED, 0x60, 0xE2, 0x64, 0x08, 0x60, 0x2F, 0xFB, 0xED, 0x60, 0xBE, 0x64, 0x08, 0x60, +- 0x28, 0xFB, 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEB, 0x60, 0x58, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0xED, 0x60, 0x70, 0x78, 0xFF, 0xFF, +- 0x58, 0xF5, 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, 0x31, 0xF8, 0xAB, 0xF1, +- 0x19, 0xF8, 0x58, 0xF5, 0x40, 0x64, 0x2A, 0xFA, 0x64, 0xF3, 0x63, 0xFB, 0x08, 0x60, 0x1B, 0xF1, +- 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x03, 0x00, +- 0xEC, 0x60, 0xCB, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xC0, 0xF3, 0xEF, 0x60, 0x58, 0x4E, 0xAB, 0x78, +- 0xFF, 0xFF, 0x15, 0x60, 0xC2, 0xFB, 0x15, 0x60, 0xBC, 0xF3, 0x3F, 0x40, 0x01, 0x27, 0x08, 0x00, +- 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xEE, 0x60, 0x58, 0x4E, 0x26, 0x78, 0xFF, 0xFF, 0x05, 0x00, +- 0x0F, 0xB4, 0xEE, 0x60, 0x58, 0x4E, 0x26, 0x78, 0xFF, 0xFF, 0x58, 0xF5, 0x2D, 0x60, 0x94, 0x64, +- 0x00, 0xF4, 0x40, 0x48, 0x28, 0x60, 0x4E, 0x64, 0x20, 0x40, 0x10, 0x27, 0x02, 0x00, 0x28, 0x60, +- 0x2C, 0x64, 0x28, 0xDB, 0x04, 0x61, 0x00, 0x60, 0x00, 0x64, 0xE4, 0x60, 0x58, 0x4D, 0xA7, 0x78, +- 0xFF, 0xFF, 0x58, 0xF5, 0x3F, 0xFC, 0x01, 0x64, 0x52, 0xF1, 0x0C, 0x60, 0x81, 0xFB, 0x64, 0xFB, +- 0xA4, 0xD3, 0x04, 0x65, 0x51, 0xF3, 0x01, 0x18, 0x0C, 0x65, 0xF3, 0xB4, 0xB4, 0x84, 0x51, 0xFB, +- 0x0D, 0x00, 0xED, 0x60, 0x70, 0x78, 0xFF, 0xFF, 0x51, 0xF1, 0x64, 0xF3, 0xFF, 0xFF, 0xF3, 0xA0, +- 0x04, 0xA4, 0x01, 0x04, 0xF1, 0xA4, 0x10, 0x36, 0xF4, 0x01, 0x64, 0xFB, 0x64, 0xF3, 0x15, 0x60, +- 0xC3, 0xF1, 0xCC, 0x84, 0x01, 0x61, 0x08, 0x24, 0x03, 0x00, 0xE1, 0x81, 0xCC, 0x84, 0xFB, 0x01, +- 0xA1, 0x84, 0x51, 0xF1, 0xEA, 0x03, 0x0C, 0x60, 0x81, 0xFB, 0x9D, 0xFE, 0x3D, 0x05, 0xBA, 0xFE, +- 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, +- 0x08, 0x60, 0x1C, 0xFB, 0xEB, 0x60, 0xD0, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x64, 0xF1, 0x0F, 0x60, 0x9D, 0xF9, 0x08, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEB, 0x60, +- 0xF5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x08, 0x60, 0x11, 0xF1, +- 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x18, 0x60, 0x07, 0xF1, 0xAD, 0x4F, +- 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x64, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, +- 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEB, 0x60, 0xCD, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x64, 0xF1, 0x0F, 0x60, 0x9D, 0xF9, 0x0E, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEC, 0x60, +- 0x2D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x08, 0x60, 0x11, 0xF1, +- 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x58, 0xF5, 0x1E, 0x60, 0xD4, 0x64, 0x0F, 0x60, 0x90, 0xFB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x64, 0x4F, 0xFB, 0x00, 0x60, 0x01, 0x64, +- 0x08, 0x60, 0x1C, 0xFB, 0xEC, 0x60, 0x51, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xA5, 0xF1, 0x0A, 0x60, 0x09, 0xF9, +- 0x14, 0x60, 0x0E, 0x64, 0x0F, 0x60, 0xA5, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0xA6, 0xF1, 0x0A, 0x60, 0x0F, 0xF9, 0x1F, 0x60, 0x48, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xFD, 0x1B, +- 0x14, 0x60, 0x1A, 0x64, 0x0F, 0x60, 0xA5, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x00, 0x60, 0x08, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEC, 0x60, 0x7A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x4F, 0xF1, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x64, 0x40, +- 0xFF, 0x26, 0x0B, 0x00, 0x51, 0xF3, 0xFF, 0xFF, 0x80, 0xB0, 0xFF, 0xFF, 0x03, 0x03, 0xED, 0x60, +- 0x6A, 0x78, 0xFF, 0xFF, 0xEB, 0x60, 0xB4, 0x78, 0xFF, 0xFF, 0x02, 0x0A, 0x00, 0x64, 0x4F, 0xFB, +- 0xA7, 0xF1, 0x0A, 0x60, 0x0F, 0xF9, 0x00, 0x60, 0x0C, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEC, 0x60, +- 0xA5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x14, 0x60, 0x1A, 0x64, 0x0F, 0x60, 0xA5, 0xFB, 0x02, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, +- 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0B, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0x1A, 0x64, +- 0x0F, 0x60, 0xA5, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x13, 0x00, 0xFF, 0x60, +- 0xF7, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x4F, 0xF3, 0xDE, 0x0A, 0x00, 0xA0, 0x00, 0x64, 0x02, 0x03, +- 0x4F, 0xFB, 0xD9, 0x01, 0x14, 0x60, 0x0E, 0x64, 0x0F, 0x60, 0xA5, 0xFB, 0x03, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0xB7, 0x01, 0x15, 0x60, 0xC1, 0xF3, 0xEF, 0x60, 0x58, 0x4E, 0xAB, 0x78, +- 0xFF, 0xFF, 0x15, 0x60, 0xC2, 0xFB, 0x15, 0x60, 0xBD, 0xF3, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, +- 0xEE, 0x60, 0x58, 0x4E, 0x26, 0x78, 0xFF, 0xFF, 0x58, 0xF5, 0x2D, 0x60, 0x94, 0x64, 0x00, 0xF4, +- 0x40, 0x48, 0x28, 0x60, 0x4E, 0x64, 0x20, 0x40, 0x10, 0x27, 0x02, 0x00, 0x28, 0x60, 0x2C, 0x64, +- 0x28, 0xDB, 0x04, 0x61, 0x00, 0x60, 0x00, 0x64, 0xE4, 0x60, 0x58, 0x4D, 0xA7, 0x78, 0xFF, 0xFF, +- 0x58, 0xF5, 0x3F, 0xFC, 0x51, 0xF3, 0x20, 0x40, 0x10, 0x23, 0x02, 0x00, 0x20, 0xBC, 0x04, 0x00, +- 0x60, 0x40, 0x01, 0x22, 0x40, 0xBC, 0x04, 0xBC, 0x80, 0xBC, 0x51, 0xFB, 0x11, 0x60, 0x16, 0x64, +- 0x08, 0x60, 0x46, 0xFB, 0x06, 0x64, 0x08, 0x60, 0x4D, 0xFB, 0x15, 0x60, 0xC6, 0xF3, 0xFF, 0xFF, +- 0x07, 0xB4, 0xA2, 0xDB, 0x51, 0xF3, 0x08, 0x60, 0x46, 0xF1, 0x60, 0x40, 0x20, 0x26, 0x03, 0x00, +- 0x01, 0x26, 0x32, 0x00, 0x45, 0x00, 0x08, 0x60, 0x4D, 0xF3, 0xFF, 0xFF, 0xDD, 0xA0, 0x01, 0xA4, +- 0x57, 0x03, 0xA2, 0xDB, 0x2B, 0x60, 0x88, 0x61, 0xE0, 0xA0, 0xF0, 0xA0, 0x05, 0x05, 0x01, 0x05, +- 0x05, 0x00, 0x02, 0xA1, 0xF0, 0xA4, 0x02, 0x00, 0x04, 0xA1, 0xE0, 0xA4, 0xA1, 0xD1, 0x01, 0x61, +- 0xDC, 0x84, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0xE1, 0x81, 0xFB, 0x01, 0xA1, 0x80, 0x10, 0x60, +- 0x9A, 0x64, 0x01, 0x02, 0xE0, 0x01, 0xA0, 0xD3, 0x11, 0x60, 0x0E, 0x63, 0xFA, 0xA4, 0xCC, 0x84, +- 0x08, 0xA3, 0xFD, 0x02, 0xB1, 0xF1, 0xA3, 0xD3, 0x01, 0x18, 0xD5, 0x18, 0xFE, 0xA3, 0xA3, 0xD3, +- 0x64, 0xFB, 0xEB, 0x60, 0xCD, 0x78, 0xFF, 0xFF, 0x11, 0x60, 0xF4, 0x65, 0x64, 0x41, 0xA1, 0xD3, +- 0xD5, 0x80, 0x00, 0xB8, 0x25, 0x07, 0x02, 0x02, 0x08, 0xA1, 0xF9, 0x01, 0x61, 0x44, 0x08, 0x60, +- 0x46, 0xFB, 0x01, 0x64, 0xA1, 0xDB, 0x49, 0xD3, 0x64, 0xFB, 0xEB, 0x60, 0xCD, 0x78, 0xFF, 0xFF, +- 0x11, 0x60, 0xF4, 0x65, 0x64, 0x41, 0xA1, 0xD3, 0xD5, 0x80, 0x04, 0xB0, 0x11, 0x07, 0x02, 0x02, +- 0x08, 0xA1, 0xF9, 0x01, 0x61, 0x44, 0x08, 0x60, 0x46, 0xFB, 0x49, 0xD3, 0x64, 0xFB, 0xEB, 0x60, +- 0xCD, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x46, 0xF3, 0xFF, 0xFF, 0x08, 0xA4, 0xA2, 0xDB, 0x9A, 0x01, +- 0x14, 0x60, 0x0E, 0x64, 0x0F, 0x60, 0xA5, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x51, 0xF3, 0xFF, 0xFF, 0xE3, 0xB4, 0x51, 0xFB, 0x0C, 0x60, 0x7F, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, +- 0xA2, 0xDB, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, +- 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xED, 0x60, 0x81, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x63, 0xF1, 0x64, 0xF9, 0x0F, 0x60, 0x9D, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xED, 0x60, 0xA3, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x08, 0x60, 0x11, 0xF1, 0x40, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x08, 0x60, 0x11, 0xF1, 0x10, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEB, 0x60, 0x58, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x14, 0x60, 0x0E, 0x64, +- 0x0F, 0x60, 0xA5, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x51, 0xFB, +- 0x00, 0x64, 0x08, 0x60, 0x1B, 0xFB, 0x5A, 0xDB, 0xBE, 0xFE, 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, +- 0x1C, 0xFB, 0xEB, 0x60, 0x58, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, +- 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x31, 0x40, 0x20, 0x2A, 0x35, 0x00, 0x3F, 0xF2, 0x47, 0x65, +- 0xC4, 0x84, 0xE8, 0x84, 0x23, 0xFA, 0xF1, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x64, 0xF3, 0x01, 0x60, +- 0xFF, 0x65, 0xA4, 0x84, 0x01, 0x23, 0x14, 0x00, 0x11, 0x60, 0x14, 0x61, 0x11, 0x60, 0xF4, 0x65, +- 0xA1, 0xD1, 0xD5, 0x80, 0xD0, 0x80, 0x0B, 0x03, 0x02, 0x03, 0x08, 0xA1, 0xF9, 0x01, 0x04, 0xA1, +- 0xA1, 0xD3, 0x01, 0x60, 0x00, 0x65, 0x60, 0x47, 0xFF, 0xB4, 0xB4, 0x84, 0x01, 0x00, 0x01, 0x64, +- 0x00, 0xF4, 0x08, 0xFA, 0xFF, 0xFF, 0x26, 0x46, 0x1F, 0x60, 0x10, 0x64, 0x0F, 0x60, 0x90, 0xFB, +- 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x00, 0x66, +- 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x5F, 0xFB, 0xAC, 0x85, +- 0x60, 0x41, 0x2E, 0x60, 0x22, 0x63, 0x16, 0x60, 0xC6, 0xFD, 0x16, 0x60, 0xCC, 0xFD, 0x16, 0x60, +- 0xD6, 0xFD, 0x16, 0x60, 0xE0, 0xFD, 0x5C, 0x03, 0x61, 0x5C, 0x00, 0x63, 0xE9, 0x81, 0xFF, 0xFF, +- 0x02, 0x24, 0xDF, 0x83, 0xFB, 0x02, 0x08, 0x64, 0x53, 0x90, 0x64, 0x41, 0x03, 0x04, 0x01, 0x60, +- 0x08, 0x63, 0x0C, 0x00, 0x01, 0x60, 0x00, 0x63, 0x10, 0x64, 0xE9, 0x81, 0xFF, 0xFF, 0x02, 0x24, +- 0xDF, 0x83, 0x08, 0x36, 0x03, 0x00, 0xCC, 0x84, 0xFF, 0xFF, 0xF7, 0x02, 0x15, 0x60, 0xEC, 0xFD, +- 0x43, 0x48, 0x65, 0x41, 0x2B, 0x60, 0xDA, 0x63, 0x28, 0x44, 0xFF, 0xB5, 0x10, 0x60, 0x08, 0x64, +- 0xE9, 0x81, 0x58, 0xD1, 0xFD, 0x04, 0xA3, 0xD9, 0x0C, 0x03, 0x58, 0xD1, 0xE9, 0x81, 0x40, 0x4A, +- 0xFC, 0x04, 0xA3, 0xD1, 0x64, 0x47, 0xB0, 0x84, 0xBD, 0xDB, 0x65, 0x44, 0xC8, 0x85, 0x2A, 0x44, +- 0xEF, 0x02, 0x28, 0x43, 0x08, 0x3A, 0x24, 0x00, 0x60, 0x45, 0x04, 0x64, 0x32, 0x60, 0x00, 0x63, +- 0x41, 0x48, 0xE9, 0x81, 0xCC, 0x84, 0x02, 0x24, 0xDF, 0x83, 0xFB, 0x02, 0x63, 0x40, 0x00, 0x36, +- 0x17, 0x00, 0x17, 0x60, 0x11, 0xFD, 0x2E, 0x60, 0x24, 0x63, 0x65, 0x44, 0x28, 0x41, 0xE9, 0x81, +- 0x58, 0xD1, 0xFD, 0x04, 0xA3, 0xD9, 0x15, 0x03, 0x58, 0xD1, 0xE9, 0x81, 0x60, 0x45, 0xFC, 0x04, +- 0xA3, 0xD1, 0x64, 0x47, 0xB0, 0x84, 0xBD, 0xDB, 0x00, 0xB9, 0x65, 0x44, 0xF0, 0x02, 0x09, 0x00, +- 0x67, 0x43, 0x16, 0x60, 0xC6, 0xFD, 0x16, 0x60, 0xCC, 0xFD, 0x16, 0x60, 0xD6, 0xFD, 0x16, 0x60, +- 0xE0, 0xFD, 0x20, 0x40, 0x10, 0x27, 0x0D, 0x00, 0x2B, 0x60, 0xE2, 0x61, 0x15, 0x60, 0xEC, 0xF3, +- 0xA1, 0xDB, 0xFF, 0xB4, 0xCC, 0x84, 0xA8, 0x83, 0x2B, 0x60, 0xD8, 0x64, 0x58, 0xD1, 0x59, 0xD9, +- 0xFD, 0x1F, 0x2B, 0x60, 0xE4, 0x63, 0x15, 0x60, 0xBE, 0xF3, 0x08, 0x61, 0x60, 0xFE, 0xA3, 0xD1, +- 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0xA8, 0xE8, 0x84, 0x0F, 0x03, 0x60, 0xFE, 0x02, 0x28, 0xF6, 0x01, +- 0x80, 0x62, 0xB2, 0x9C, 0xBD, 0xD9, 0x62, 0xF9, 0xCD, 0x81, 0x00, 0x36, 0x01, 0x00, 0xEE, 0x01, +- 0x2E, 0x60, 0x24, 0x63, 0x08, 0x61, 0xEA, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0x2B, 0x60, 0x7C, 0x63, +- 0x65, 0x40, 0xFF, 0x36, 0x02, 0xA3, 0xA3, 0xD3, 0xFF, 0xFF, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, +- 0xE8, 0x84, 0x40, 0x26, 0x7F, 0xB4, 0x20, 0x26, 0x3F, 0xB4, 0x60, 0x45, 0x80, 0x63, 0xEF, 0x60, +- 0x58, 0x4D, 0x33, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xDF, 0xFB, 0x40, 0x63, 0xEF, 0x60, 0x58, 0x4D, +- 0x33, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xE0, 0xFB, 0x20, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x33, 0x78, +- 0xFF, 0xFF, 0x15, 0x60, 0xE1, 0xFB, 0x10, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x33, 0x78, 0xFF, 0xFF, +- 0x15, 0x60, 0xE2, 0xFB, 0x08, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x33, 0x78, 0xFF, 0xFF, 0x15, 0x60, +- 0xE3, 0xFB, 0x04, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x33, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xE4, 0xFB, +- 0x02, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x33, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xE5, 0xFB, 0x01, 0x63, +- 0xEF, 0x60, 0x58, 0x4D, 0x33, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xE6, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, +- 0x15, 0x60, 0xBE, 0xF3, 0xFF, 0xFF, 0x0F, 0xB4, 0x60, 0x45, 0x08, 0x63, 0xEF, 0x60, 0x58, 0x4D, +- 0x5E, 0x78, 0xFF, 0xFF, 0x15, 0x60, 0xE7, 0xFB, 0x04, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x5E, 0x78, +- 0xFF, 0xFF, 0x15, 0x60, 0xE8, 0xFB, 0x02, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x5E, 0x78, 0xFF, 0xFF, +- 0x15, 0x60, 0xE9, 0xFB, 0x01, 0x63, 0xEF, 0x60, 0x58, 0x4D, 0x5E, 0x78, 0xFF, 0xFF, 0x15, 0x60, +- 0xEA, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x63, 0x5C, 0xA7, 0x84, 0xEB, 0x83, 0x14, 0x02, 0x01, 0x03, +- 0xFB, 0x01, 0x64, 0x44, 0x01, 0x36, 0x0B, 0x64, 0x02, 0x36, 0x0B, 0x64, 0x04, 0x36, 0x0A, 0x64, +- 0x08, 0x36, 0x0A, 0x64, 0x10, 0x36, 0x09, 0x64, 0x20, 0x36, 0x09, 0x64, 0x40, 0x36, 0x09, 0x64, +- 0x80, 0x36, 0x09, 0x64, 0x11, 0x00, 0x60, 0x40, 0x01, 0x36, 0x0B, 0x64, 0x02, 0x36, 0x0F, 0x64, +- 0x04, 0x36, 0x0A, 0x64, 0x08, 0x36, 0x0E, 0x64, 0x10, 0x36, 0x09, 0x64, 0x20, 0x36, 0x0D, 0x64, +- 0x40, 0x36, 0x08, 0x64, 0x80, 0x36, 0x0C, 0x64, 0x2D, 0x58, 0xFF, 0xFF, 0x63, 0x5C, 0xA7, 0x84, +- 0xEB, 0x83, 0x0C, 0x02, 0x01, 0x03, 0xFB, 0x01, 0x64, 0x44, 0x01, 0x36, 0x0A, 0x64, 0x02, 0x36, +- 0x14, 0x64, 0x04, 0x36, 0x37, 0x64, 0x08, 0x36, 0x6E, 0x64, 0x09, 0x00, 0x60, 0x40, 0x01, 0x36, +- 0x0A, 0x64, 0x02, 0x36, 0x14, 0x64, 0x04, 0x36, 0x37, 0x64, 0x08, 0x36, 0x6E, 0x64, 0x2D, 0x58, +- 0xFF, 0xFF, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, 0x5D, 0xD2, +- 0xCF, 0x83, 0xD4, 0x80, 0x25, 0x03, 0x16, 0x03, 0xCF, 0x83, 0x61, 0x44, 0x80, 0xA0, 0x20, 0x03, +- 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, 0x5D, 0xD2, 0xCF, 0x83, 0x81, 0xA1, 0x19, 0x03, 0x05, 0x07, +- 0x7F, 0xA1, 0xCC, 0x84, 0xDD, 0x81, 0xE6, 0x03, 0xF7, 0x01, 0x00, 0xF4, 0x00, 0xB8, 0x04, 0x61, +- 0xE6, 0x03, 0xF2, 0x01, 0x2C, 0x43, 0x5D, 0xD0, 0xDE, 0xD9, 0x64, 0x44, 0x5D, 0xD0, 0xDE, 0xD9, +- 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, 0x7F, 0xA1, 0xF9, 0x04, 0x00, 0xF4, 0x03, 0x61, 0xF6, 0x01, +- 0x20, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x01, 0x3A, 0x02, 0x00, 0x16, 0x64, 0x2B, 0x00, 0x02, 0x3A, +- 0x02, 0x00, 0x14, 0x64, 0x27, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x12, 0x64, 0x23, 0x00, 0x08, 0x3A, +- 0x02, 0x00, 0x10, 0x64, 0x1F, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x0E, 0x64, 0x1B, 0x00, 0x20, 0x3A, +- 0x02, 0x00, 0x0C, 0x64, 0x17, 0x00, 0x40, 0x3A, 0x02, 0x00, 0x0A, 0x64, 0x13, 0x00, 0x80, 0x3A, +- 0x02, 0x00, 0x08, 0x64, 0x0F, 0x00, 0x01, 0x3B, 0x02, 0x00, 0x06, 0x64, 0x0B, 0x00, 0x02, 0x3B, +- 0x02, 0x00, 0x04, 0x64, 0x07, 0x00, 0x04, 0x3B, 0x02, 0x00, 0x02, 0x64, 0x03, 0x00, 0x08, 0x3B, +- 0xFF, 0x01, 0x00, 0x64, 0x2E, 0x58, 0xFF, 0xFF, 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x36, 0x3A, +- 0x02, 0x00, 0x00, 0x61, 0x2C, 0x00, 0x30, 0x3A, 0x02, 0x00, 0x02, 0x61, 0x28, 0x00, 0x24, 0x3A, +- 0x02, 0x00, 0x04, 0x61, 0x24, 0x00, 0x18, 0x3A, 0x02, 0x00, 0x06, 0x61, 0x20, 0x00, 0x12, 0x3A, +- 0x02, 0x00, 0x08, 0x61, 0x1C, 0x00, 0x0C, 0x3A, 0x02, 0x00, 0x0A, 0x61, 0x18, 0x00, 0x09, 0x3A, +- 0x02, 0x00, 0x0C, 0x61, 0x14, 0x00, 0x06, 0x3A, 0x02, 0x00, 0x0E, 0x61, 0x10, 0x00, 0x6E, 0x3A, +- 0x02, 0x00, 0x10, 0x61, 0x0C, 0x00, 0x37, 0x3A, 0x02, 0x00, 0x12, 0x61, 0x08, 0x00, 0x14, 0x3A, +- 0x02, 0x00, 0x14, 0x61, 0x04, 0x00, 0x0A, 0x3A, 0xFF, 0xFF, 0x16, 0x61, 0x00, 0x00, 0x65, 0x40, +- 0x01, 0x3A, 0x13, 0x00, 0x66, 0x45, 0x2B, 0x46, 0x92, 0xFA, 0x65, 0x46, 0x26, 0xF2, 0xFF, 0xFF, +- 0x60, 0x41, 0x00, 0x7F, 0x60, 0x45, 0x61, 0x47, 0x00, 0x7F, 0xD4, 0x84, 0x66, 0x41, 0x2B, 0x46, +- 0x0E, 0xF2, 0x60, 0x45, 0x65, 0x5E, 0x0E, 0xFA, 0x61, 0x46, 0x2E, 0x58, 0xFF, 0xFF, 0xCD, 0x81, +- 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x01, 0x64, 0x2E, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, +- 0x2A, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x04, 0x64, 0x26, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x08, 0x64, +- 0x22, 0x00, 0x0C, 0x3A, 0x02, 0x00, 0x10, 0x64, 0x1E, 0x00, 0x12, 0x3A, 0x02, 0x00, 0x20, 0x64, +- 0x1A, 0x00, 0x18, 0x3A, 0x02, 0x00, 0x40, 0x64, 0x16, 0x00, 0x24, 0x3A, 0x02, 0x00, 0x80, 0x64, +- 0x12, 0x00, 0x30, 0x3A, 0x02, 0x00, 0x01, 0x7F, 0x0E, 0x00, 0x48, 0x3A, 0x02, 0x00, 0x02, 0x7F, +- 0x0A, 0x00, 0x60, 0x3A, 0x02, 0x00, 0x04, 0x7F, 0x06, 0x00, 0x6C, 0x3A, 0x02, 0x00, 0x08, 0x7F, +- 0x02, 0x00, 0x00, 0x64, 0x00, 0x00, 0x20, 0xFE, 0x2A, 0x45, 0x34, 0x8A, 0x60, 0xFE, 0x61, 0x40, +- 0x00, 0x36, 0x02, 0x00, 0xBD, 0xD3, 0xC3, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0x53, 0xFB, 0x54, 0xFB, +- 0x00, 0x60, 0x0C, 0x63, 0x14, 0x60, 0xEC, 0x62, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x02, 0x64, +- 0x0A, 0x60, 0x78, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x0A, 0x60, 0x7A, 0xF3, 0x00, 0x63, 0xF0, 0xA0, +- 0x01, 0xA4, 0x03, 0x03, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0xA2, 0xDD, 0x0A, 0x60, 0x7B, 0xF1, +- 0xA2, 0xDD, 0x5A, 0xD3, 0xA2, 0xDD, 0xC0, 0x81, 0x61, 0x44, 0x02, 0x24, 0xFF, 0xFF, 0xE9, 0x81, +- 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0x5A, 0xD3, 0xE9, 0x81, 0xE8, 0x83, 0xEB, 0x83, 0xEB, 0x83, +- 0xEB, 0x83, 0xEB, 0x85, 0xD4, 0x85, 0xC5, 0x83, 0xA2, 0xDD, 0x63, 0x47, 0x00, 0x7F, 0x0A, 0x60, +- 0x77, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x7F, 0x67, 0x01, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0xB1, 0xFE, +- 0x05, 0x05, 0xB0, 0xFE, 0x06, 0x05, 0xB2, 0xFE, 0xB3, 0xFE, 0x21, 0x00, 0xF7, 0x60, 0x38, 0x78, +- 0xFF, 0xFF, 0x28, 0xF3, 0x29, 0xF1, 0x40, 0x44, 0x44, 0x45, 0x2A, 0xF1, 0x2B, 0xF1, 0x44, 0x46, +- 0x44, 0x47, 0x3F, 0xB4, 0xE0, 0x85, 0x19, 0x60, 0x06, 0x64, 0x44, 0xD7, 0x58, 0x43, 0xFF, 0xFF, +- 0x60, 0x45, 0x0A, 0x60, 0x7E, 0xF3, 0x61, 0x43, 0x04, 0xB4, 0x24, 0x44, 0x02, 0x03, 0x13, 0xFF, +- 0x06, 0x00, 0x3F, 0xB4, 0xB4, 0x84, 0xFF, 0x27, 0x05, 0xFD, 0x04, 0xFB, 0x10, 0x75, 0xA1, 0xFF, +- 0xFF, 0xFF, 0x86, 0x3E, 0xB4, 0xFE, 0x09, 0x05, 0xB5, 0xFE, 0x02, 0x24, 0x7F, 0xF7, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xB7, 0xFE, 0x05, 0x05, 0xB6, 0xFE, 0xF2, 0x01, 0xF7, 0x60, 0x73, 0x78, 0xFF, 0xFF, +- 0x36, 0x44, 0x00, 0x7F, 0xEE, 0xA0, 0x60, 0x45, 0x05, 0x05, 0x19, 0x60, 0x98, 0x64, 0x44, 0xD7, +- 0xFF, 0xFF, 0xFF, 0xFF, 0xE4, 0x01, 0xE3, 0x01, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, +- 0x7F, 0x67, 0x02, 0x61, 0x10, 0x02, 0x10, 0x64, 0x40, 0x40, 0x02, 0x64, 0x40, 0x50, 0x61, 0xFF, +- 0x3F, 0x40, 0x40, 0x26, 0x04, 0x00, 0x10, 0xE0, 0x46, 0x60, 0x09, 0xE0, 0x00, 0x00, 0x27, 0xF1, +- 0x00, 0x66, 0x20, 0x78, 0x42, 0xFE, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, +- 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x19, 0x02, 0x0A, 0x60, 0x7E, 0xF3, 0x07, 0x7C, 0x20, 0xB5, +- 0x0C, 0xB5, 0x04, 0x03, 0x03, 0x02, 0xBC, 0xF9, 0x00, 0x67, 0x0F, 0x00, 0x00, 0x61, 0x41, 0x56, +- 0xC7, 0xFE, 0xB5, 0x01, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, +- 0x04, 0x00, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, +- 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x31, 0x02, 0x0A, 0x60, 0x7E, 0xF3, +- 0x01, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, 0x03, 0x03, 0x02, 0x02, 0xBC, 0xF9, 0xFF, 0xFF, 0x02, 0x61, +- 0x41, 0x56, 0xC7, 0xFE, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x7D, 0xF1, 0x20, 0x44, 0x64, 0x40, +- 0xFF, 0x26, 0x1C, 0x00, 0x7F, 0xB4, 0x40, 0x40, 0x5C, 0x5E, 0x82, 0xFF, 0x26, 0x44, 0xFD, 0xB4, +- 0x40, 0x46, 0x5C, 0x41, 0x87, 0xFF, 0x62, 0xFF, 0x0F, 0x60, 0x85, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, +- 0x60, 0x46, 0x04, 0x03, 0x09, 0xF2, 0x8F, 0xFC, 0xAC, 0x86, 0xFB, 0x01, 0xD3, 0xF3, 0xFF, 0xFF, +- 0xFE, 0xB4, 0xD3, 0xFB, 0x06, 0x64, 0x0F, 0x60, 0x9F, 0xFB, 0x2D, 0xFF, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x25, 0x46, 0x01, 0xF2, 0x08, 0xF0, 0x60, 0x47, 0x03, 0xB4, 0x03, 0xAC, 0x7F, 0x67, +- 0x03, 0x61, 0x08, 0x02, 0x1F, 0x60, 0x26, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, +- 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x2B, 0x49, 0x00, 0x25, 0x44, +- 0x1F, 0xB4, 0xE0, 0x85, 0xF1, 0x60, 0x76, 0x64, 0xC4, 0x98, 0xFF, 0xFF, 0xC0, 0xFE, 0x3D, 0x00, +- 0xC1, 0xFE, 0x3B, 0x00, 0xC2, 0xFE, 0x39, 0x00, 0xC3, 0xFE, 0x37, 0x00, 0xC4, 0xFE, 0x35, 0x00, +- 0xC5, 0xFE, 0x33, 0x00, 0xC6, 0xFE, 0x31, 0x00, 0xC7, 0xFE, 0x2F, 0x00, 0xC8, 0xFE, 0x2D, 0x00, +- 0xC9, 0xFE, 0x2B, 0x00, 0xCA, 0xFE, 0x29, 0x00, 0xCB, 0xFE, 0x27, 0x00, 0xCC, 0xFE, 0x25, 0x00, +- 0xCD, 0xFE, 0x23, 0x00, 0xCE, 0xFE, 0x21, 0x00, 0xCF, 0xFE, 0x1F, 0x00, 0xD0, 0xFE, 0x1D, 0x00, +- 0xD1, 0xFE, 0x1B, 0x00, 0xD2, 0xFE, 0x19, 0x00, 0xD3, 0xFE, 0x17, 0x00, 0xD4, 0xFE, 0x15, 0x00, +- 0xD5, 0xFE, 0x13, 0x00, 0xD6, 0xFE, 0x11, 0x00, 0xD7, 0xFE, 0x0F, 0x00, 0xD8, 0xFE, 0x0D, 0x00, +- 0xD9, 0xFE, 0x0B, 0x00, 0xDA, 0xFE, 0x09, 0x00, 0xDB, 0xFE, 0x07, 0x00, 0xDC, 0xFE, 0x05, 0x00, +- 0xDD, 0xFE, 0x03, 0x00, 0xDE, 0xFE, 0x01, 0x00, 0xDF, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x00, 0x64, 0x9F, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9D, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x9C, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x9A, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x99, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x98, 0xFE, 0xF0, 0x84, +- 0xFF, 0xFF, 0x97, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x96, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x95, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x94, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x93, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x92, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x91, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x90, 0xFE, 0xF0, 0x84, +- 0x06, 0xFB, 0x8F, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8D, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x8C, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x8A, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x89, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x88, 0xFE, 0xF0, 0x84, +- 0xFF, 0xFF, 0x87, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x86, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x85, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x84, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x83, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x82, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x81, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x80, 0xFE, 0xF0, 0x84, +- 0x05, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x5C, 0x5C, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x24, 0x40, 0x01, 0x27, 0x55, 0x00, 0x05, 0x60, 0x00, 0x63, 0x05, 0xFD, 0x30, 0x44, 0xBD, 0xDB, +- 0x31, 0x44, 0xBD, 0xDB, 0x32, 0x44, 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, +- 0x35, 0x44, 0xBD, 0xDB, 0x36, 0x44, 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, +- 0x39, 0x44, 0xBD, 0xDB, 0x3A, 0x44, 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, +- 0x3D, 0x44, 0xBD, 0xDB, 0x3E, 0x44, 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0x02, 0x61, 0x61, 0x44, +- 0x02, 0x36, 0x82, 0xFF, 0x03, 0x36, 0x83, 0xFF, 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, +- 0x06, 0x36, 0x86, 0xFF, 0x07, 0x36, 0x87, 0xFF, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, +- 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, +- 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, +- 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, +- 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, 0xDD, 0x81, 0x08, 0x3A, 0xD0, 0x01, 0x54, 0x00, +- 0x27, 0x40, 0x10, 0x26, 0x30, 0x00, 0x26, 0x44, 0x01, 0x36, 0x2D, 0x00, 0x02, 0x36, 0x82, 0xFF, +- 0x03, 0x36, 0x83, 0xFF, 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, 0x06, 0x36, 0x86, 0xFF, +- 0x25, 0x44, 0x00, 0x36, 0x44, 0x40, 0x01, 0x36, 0x44, 0x41, 0x02, 0x36, 0x44, 0x42, 0x03, 0x36, +- 0x44, 0x43, 0x04, 0x36, 0x44, 0x44, 0x05, 0x36, 0x44, 0x45, 0x06, 0x36, 0x44, 0x46, 0x07, 0x36, +- 0x44, 0x47, 0x08, 0x36, 0x44, 0x48, 0x09, 0x36, 0x44, 0x49, 0x0A, 0x36, 0x44, 0x4A, 0x0B, 0x36, +- 0x44, 0x4B, 0x0C, 0x36, 0x44, 0x4C, 0x0D, 0x36, 0x44, 0x4D, 0x0E, 0x36, 0x44, 0x4E, 0x0F, 0x36, +- 0x44, 0x4F, 0x87, 0xFF, 0x21, 0x00, 0x25, 0x44, 0x10, 0x36, 0x44, 0x50, 0x11, 0x36, 0x44, 0x51, +- 0x12, 0x36, 0x44, 0x52, 0x13, 0x36, 0x44, 0x53, 0x14, 0x36, 0x44, 0x54, 0x15, 0x36, 0x44, 0x55, +- 0x16, 0x36, 0x44, 0x56, 0x17, 0x36, 0x44, 0x57, 0x18, 0x36, 0x44, 0x58, 0x19, 0x36, 0x44, 0x59, +- 0x1A, 0x36, 0x44, 0x5A, 0x1B, 0x36, 0x44, 0x5B, 0x1C, 0x36, 0x44, 0x5C, 0x1D, 0x36, 0x44, 0x5D, +- 0x1E, 0x36, 0x44, 0x5E, 0x1F, 0x36, 0x44, 0x5F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0x46, +- 0xB5, 0x60, 0x58, 0x4F, 0x4B, 0x78, 0xFF, 0xFF, 0x03, 0x61, 0x7F, 0x67, 0x0A, 0x02, 0x00, 0xF0, +- 0x04, 0x64, 0x0F, 0x60, 0x93, 0xFB, 0x5A, 0xD9, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, +- 0x02, 0x61, 0x12, 0x02, 0x14, 0x64, 0x0F, 0x60, 0x9F, 0xFB, 0x00, 0x60, 0x50, 0x63, 0x5A, 0xDD, +- 0xF2, 0x60, 0xF7, 0x64, 0x7F, 0xFB, 0x2D, 0xFF, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x2A, 0xF3, +- 0x05, 0xFB, 0x2B, 0xF3, 0x06, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, +- 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x0E, 0x02, 0x16, 0x64, 0x0F, 0x60, 0x9F, 0xFB, +- 0x00, 0x60, 0x50, 0x63, 0x5A, 0xDD, 0xF3, 0x60, 0x12, 0x64, 0x7F, 0xFB, 0x2D, 0xFF, 0xF0, 0x60, +- 0xC7, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, +- 0xA4, 0x80, 0x02, 0x61, 0x35, 0x02, 0x25, 0x45, 0xF1, 0x60, 0x02, 0x64, 0xD4, 0x80, 0xFF, 0xFF, +- 0x34, 0x03, 0xF1, 0x60, 0x00, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x01, 0x03, 0x28, 0x00, 0x15, 0x60, +- 0xC3, 0xF1, 0x99, 0xF3, 0x19, 0x60, 0x00, 0x61, 0xA0, 0x84, 0xA1, 0xDB, 0x25, 0x45, 0x1E, 0x60, +- 0x96, 0x63, 0x01, 0x61, 0xBD, 0xD3, 0xBD, 0xD1, 0xD4, 0x80, 0xBD, 0xD3, 0xBD, 0xD5, 0xCD, 0x81, +- 0x02, 0x03, 0x15, 0x03, 0xF7, 0x01, 0xA2, 0xFF, 0xA6, 0xD3, 0x40, 0x4C, 0x00, 0xA8, 0x67, 0x43, +- 0x0C, 0x02, 0xA2, 0xDD, 0x42, 0x48, 0x64, 0x41, 0xB5, 0x60, 0x58, 0x4D, 0xA2, 0x78, 0xFF, 0xFF, +- 0x66, 0x44, 0x28, 0xDB, 0x02, 0x03, 0x2C, 0x58, 0xA3, 0xFF, 0x0C, 0x61, 0x03, 0x00, 0x04, 0x61, +- 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xF1, 0x60, 0x02, 0x64, 0xD4, 0x80, +- 0x7F, 0x67, 0x06, 0x63, 0xF8, 0x02, 0x31, 0x40, 0x21, 0x2A, 0xF5, 0x01, 0x01, 0x64, 0x0C, 0x60, +- 0x82, 0xFB, 0xFF, 0xFF, 0xC4, 0xFE, 0xEE, 0x01, 0xC6, 0xFE, 0xEC, 0x01, 0x7E, 0x60, 0xC0, 0x64, +- 0x24, 0x45, 0xA4, 0x80, 0x02, 0x61, 0x3F, 0x02, 0x25, 0x45, 0xF8, 0x2B, 0x3B, 0x00, 0x2E, 0xF5, +- 0x67, 0x44, 0xD4, 0x80, 0x19, 0x60, 0xAA, 0x63, 0x39, 0x03, 0x7E, 0x61, 0x24, 0x44, 0x01, 0x27, +- 0x29, 0x00, 0xA3, 0xFC, 0xA4, 0xF8, 0xBD, 0xD3, 0xA3, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, +- 0x64, 0x58, 0x08, 0xA3, 0xF8, 0x02, 0x08, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xA3, 0xD1, 0xFE, 0xA0, +- 0xFA, 0x60, 0x00, 0x64, 0xD0, 0x80, 0x14, 0x02, 0x13, 0x02, 0x04, 0xA3, 0xBE, 0xD3, 0xBD, 0xD1, +- 0x0F, 0x18, 0xD4, 0x80, 0x0D, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x64, 0x41, +- 0xDD, 0x81, 0xE1, 0x81, 0xCB, 0x83, 0x46, 0x65, 0xF8, 0x60, 0x58, 0x4F, 0x7A, 0x78, 0xFF, 0xFF, +- 0x00, 0x67, 0x0A, 0x00, 0xBD, 0xD3, 0xBE, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, 0x64, 0x58, +- 0x08, 0xA3, 0xF8, 0x02, 0x04, 0x61, 0x7F, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x0F, 0x64, 0x23, 0xFA, +- 0x67, 0x44, 0x24, 0xFA, 0x62, 0x41, 0x3E, 0x60, 0x00, 0x65, 0x1A, 0x63, 0xF7, 0x60, 0x8C, 0x64, +- 0x65, 0x46, 0x58, 0xD0, 0x2E, 0xF5, 0x59, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x4B, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0xE8, 0x84, 0xDC, 0x84, 0x23, 0xFA, 0xBF, 0xD1, 0x4A, 0x65, +- 0x64, 0x43, 0xF8, 0x60, 0x58, 0x4F, 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x25, 0xF2, 0xFF, 0xFF, 0xE0, 0xA0, 0x20, 0x64, 0x01, 0x06, 0x25, 0xFA, 0x23, 0xF2, 0xDF, 0xD1, +- 0xCC, 0x84, 0xE0, 0x85, 0x0B, 0x06, 0xBF, 0xD1, 0x64, 0x41, 0xD5, 0x80, 0x64, 0x43, 0x01, 0x06, +- 0x65, 0x41, 0x4A, 0x65, 0xF4, 0x60, 0x58, 0x4F, 0xBD, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0xBC, 0xF3, 0x02, 0x63, 0x23, 0xFC, 0x07, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x4B, 0xD3, 0xBF, 0xD3, 0x60, 0x41, 0xC9, 0x83, 0xE9, 0x81, 0xDD, 0x81, 0xA3, 0xFA, +- 0xE0, 0x81, 0x3C, 0x60, 0x00, 0x67, 0x02, 0x24, 0x02, 0xA4, 0x60, 0x47, 0x40, 0x4B, 0xC9, 0x81, +- 0x4A, 0x65, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, +- 0x00, 0xF4, 0x04, 0x65, 0xF6, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, +- 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, 0x60, 0x47, 0x25, 0xFA, 0x00, 0x7E, 0x60, 0x47, 0x01, 0x26, +- 0xDC, 0x84, 0x60, 0x41, 0xE8, 0x84, 0xD8, 0x84, 0x23, 0xFA, 0xAB, 0x01, 0xFC, 0xA3, 0xA3, 0xD1, +- 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, 0x00, 0x7F, 0x25, 0xFA, 0x60, 0x41, 0x01, 0x26, 0xDD, 0x81, +- 0xE9, 0x84, 0xD8, 0x84, 0x23, 0xFA, 0x9D, 0x01, 0x23, 0xF2, 0x25, 0xF2, 0x02, 0xA8, 0xF8, 0xA0, +- 0x0F, 0x02, 0xEC, 0xA0, 0x0D, 0x04, 0x0C, 0x07, 0x15, 0x60, 0xD2, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, +- 0xFF, 0xFF, 0x04, 0x07, 0x15, 0x60, 0xD2, 0xFB, 0x15, 0x60, 0xD6, 0xFB, 0x13, 0x60, 0x5B, 0xFB, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x14, 0x60, 0xEE, 0x65, 0x60, 0x41, 0x14, 0x60, +- 0x8A, 0x63, 0xA3, 0xDB, 0xFF, 0xA1, 0x48, 0x64, 0x58, 0xD0, 0x7E, 0xA8, 0x5B, 0xD9, 0x02, 0x02, +- 0x00, 0xF4, 0x02, 0x64, 0xFF, 0xA1, 0xD7, 0x80, 0x02, 0x03, 0x01, 0x03, 0xF5, 0x01, 0x2E, 0xF5, +- 0x00, 0x60, 0x2F, 0x65, 0x25, 0xF2, 0x00, 0x63, 0xCC, 0x84, 0x03, 0xA3, 0xFD, 0x05, 0x4A, 0x64, +- 0xD7, 0x80, 0x14, 0x60, 0x26, 0x61, 0x18, 0x05, 0xA1, 0xDD, 0xE3, 0x83, 0xFE, 0xA3, 0x58, 0xD0, +- 0x7E, 0xA8, 0x59, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x00, 0x63, 0x59, 0xDD, +- 0x2E, 0xF5, 0x25, 0xF0, 0x0A, 0x60, 0x13, 0xF3, 0xD3, 0x80, 0x01, 0xB0, 0x04, 0x03, 0x01, 0xA4, +- 0x03, 0x03, 0xA2, 0xDB, 0x01, 0x00, 0xA2, 0xDD, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x14, 0x60, +- 0x8A, 0x61, 0xA1, 0xD3, 0x23, 0xFA, 0xE0, 0x83, 0x4A, 0x65, 0x04, 0x02, 0x02, 0x63, 0x23, 0xFC, +- 0xA5, 0xFC, 0x09, 0x00, 0xDB, 0x83, 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, +- 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x0A, 0x60, 0x13, 0xF3, +- 0x00, 0x61, 0x02, 0xA4, 0xFE, 0xA0, 0x23, 0xFA, 0x1B, 0x03, 0xFA, 0xA4, 0xFD, 0xA4, 0x01, 0xA1, +- 0xFD, 0x07, 0x61, 0x43, 0x23, 0xF2, 0x25, 0xFC, 0xE0, 0x83, 0x02, 0xA3, 0x14, 0x60, 0x26, 0x61, +- 0x00, 0x60, 0x4A, 0x64, 0x59, 0xD1, 0x58, 0xD8, 0x7E, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x02, 0x64, +- 0xF9, 0x1F, 0x25, 0xF2, 0x23, 0xF2, 0x01, 0xB0, 0xCC, 0x84, 0x04, 0x02, 0x23, 0xFA, 0x02, 0x00, +- 0x00, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x41, 0x4B, 0x65, 0x42, 0x80, 0x64, +- 0xD4, 0x85, 0x2B, 0x41, 0x00, 0xA1, 0x55, 0x8B, 0x0D, 0x03, 0x02, 0x04, 0x65, 0x41, 0x02, 0x00, +- 0x00, 0x64, 0x40, 0x4B, 0xCA, 0x84, 0x58, 0xD0, 0xC9, 0x81, 0xBD, 0xD9, 0xFC, 0x02, 0x00, 0xF4, +- 0x04, 0x65, 0xEC, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD3, 0x02, 0x7C, 0xA0, 0xD3, +- 0x23, 0xF8, 0xDC, 0x84, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x64, 0x23, 0xFA, +- 0x01, 0x64, 0x9D, 0xFE, 0x02, 0x28, 0x02, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x02, 0x7C, 0x23, 0xF8, 0x01, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, +- 0xA3, 0xD1, 0x02, 0x64, 0x23, 0xFA, 0x64, 0x44, 0x7C, 0x5F, 0x60, 0x45, 0x64, 0x47, 0x7C, 0x5F, +- 0x88, 0xF1, 0x66, 0x41, 0xC0, 0x86, 0xA5, 0xD2, 0x61, 0x46, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x02, 0x64, 0x23, 0xFA, 0x88, 0xFF, 0x75, 0x44, 0x8D, 0xFF, 0xE8, 0x87, 0xE8, 0x84, +- 0xE8, 0x84, 0x03, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x05, 0x64, 0x23, 0xFA, +- 0x52, 0x63, 0x96, 0xF3, 0x4B, 0xDA, 0x95, 0xF3, 0x4B, 0xDA, 0x94, 0xF3, 0x4B, 0xDA, 0x60, 0x41, +- 0x88, 0xFF, 0x72, 0x5C, 0x89, 0xFF, 0x4A, 0xD8, 0xA2, 0x48, 0x20, 0x23, 0x0E, 0x00, 0x64, 0x40, +- 0x80, 0x27, 0x15, 0x00, 0xDC, 0x84, 0xBD, 0xDA, 0xBD, 0xD2, 0x11, 0x04, 0xDC, 0x84, 0xA2, 0xDA, +- 0xA3, 0xD2, 0x0D, 0x04, 0xDC, 0x84, 0xA3, 0xDA, 0x0A, 0x00, 0x52, 0x63, 0x96, 0xF3, 0x4B, 0xDA, +- 0x95, 0xF3, 0x4B, 0xDA, 0x94, 0xF3, 0x4B, 0xDA, 0x54, 0x90, 0x4C, 0x63, 0xE0, 0x02, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF0, 0x23, 0xF2, 0x15, 0x60, 0xC9, 0xF9, 0x02, 0xA8, 0x64, 0x44, +- 0x1F, 0x02, 0x3F, 0x40, 0x02, 0x2B, 0x16, 0x00, 0x00, 0x37, 0x14, 0x00, 0x01, 0x3B, 0x18, 0x00, +- 0x11, 0x60, 0xF9, 0x65, 0x11, 0x60, 0x19, 0x63, 0xFF, 0xB7, 0x60, 0x5C, 0xA3, 0xD3, 0x08, 0xA3, +- 0x00, 0x7E, 0xD0, 0x80, 0xD7, 0x80, 0x03, 0x03, 0xF9, 0x02, 0x7F, 0x67, 0x0A, 0x00, 0xF4, 0xA3, +- 0xA3, 0xD1, 0x04, 0x00, 0x00, 0xBC, 0xF2, 0xA4, 0x03, 0x03, 0x02, 0x07, 0x13, 0x60, 0x52, 0xF9, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x20, 0x63, 0x27, 0x60, 0x06, 0x61, 0x48, 0x64, 0x58, 0xD0, +- 0x59, 0xD9, 0xFD, 0x1F, 0x25, 0xF0, 0x20, 0x64, 0xD0, 0x81, 0xFF, 0xFF, 0x02, 0x07, 0x25, 0xFA, +- 0x0F, 0x00, 0x27, 0x60, 0x0A, 0x63, 0xC3, 0x83, 0x01, 0x2A, 0x06, 0x00, 0xCF, 0x83, 0xA3, 0xD3, +- 0xCD, 0x81, 0x00, 0x7F, 0xBD, 0xDB, 0x04, 0x03, 0x00, 0x64, 0xC9, 0x81, 0xBD, 0xDB, 0xFD, 0x02, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x01, 0x60, 0x6E, 0x63, 0x7F, 0x67, +- 0x3A, 0x18, 0xA3, 0xD9, 0x26, 0xF0, 0x7F, 0x67, 0x36, 0x18, 0x5B, 0xD9, 0x13, 0x60, 0x0A, 0xF3, +- 0x25, 0xF0, 0x60, 0x40, 0x03, 0x3A, 0x2E, 0x00, 0x86, 0xF3, 0x87, 0xF3, 0x60, 0x43, 0xE3, 0x83, +- 0x60, 0x46, 0x0F, 0xF8, 0x30, 0x61, 0x94, 0xFA, 0x01, 0x61, 0x91, 0xFA, 0x16, 0x64, 0x12, 0xFA, +- 0x60, 0x40, 0x10, 0x36, 0x05, 0x00, 0x12, 0x36, 0x08, 0x00, 0x0C, 0x36, 0x0B, 0x00, 0x0F, 0x00, +- 0x40, 0x61, 0xA1, 0x80, 0x0A, 0x64, 0x11, 0x02, 0xF3, 0x01, 0x10, 0x61, 0xA1, 0x80, 0x0E, 0x64, +- 0x0C, 0x02, 0xEE, 0x01, 0x08, 0x61, 0xA1, 0x80, 0x10, 0x64, 0x07, 0x02, 0xE9, 0x01, 0xE1, 0x81, +- 0xA1, 0x80, 0x05, 0x05, 0xC8, 0x84, 0x01, 0x02, 0xE3, 0x01, 0x12, 0xFA, 0x91, 0xFA, 0x66, 0x44, +- 0x02, 0xA6, 0xD7, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA5, 0xF0, 0xA3, 0xD1, +- 0xFF, 0xFF, 0x64, 0x5E, 0x00, 0x7F, 0x60, 0x41, 0x64, 0x47, 0x7C, 0x5F, 0x88, 0xF1, 0x66, 0x43, +- 0xC0, 0x86, 0x65, 0x44, 0xA1, 0xDA, 0x63, 0x46, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, +- 0xA3, 0xD1, 0xFF, 0xFF, 0x64, 0x5E, 0x00, 0x7F, 0x60, 0x45, 0x64, 0x47, 0x7C, 0x5F, 0x88, 0xF1, +- 0x66, 0x41, 0xC0, 0x86, 0x65, 0x44, 0xA0, 0xD2, 0x61, 0x46, 0x25, 0xFA, 0x02, 0x64, 0x23, 0xFA, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0x15, 0x60, 0xC8, 0xFB, 0xFF, 0xFF, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x00, 0x67, 0x02, 0x02, 0x2D, 0xF9, +- 0x2C, 0xF9, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF2, 0x02, 0xA8, 0x00, 0xA8, 0x0A, 0x02, +- 0x07, 0x03, 0xD0, 0xA0, 0x30, 0x65, 0x03, 0x04, 0xA7, 0xA0, 0x59, 0x65, 0x01, 0x06, 0x65, 0x44, +- 0x13, 0x60, 0x51, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0x15, 0x60, 0xCF, 0xFB, +- 0xFF, 0xFF, 0x08, 0x2A, 0x25, 0x00, 0x15, 0x60, 0xDD, 0xF3, 0xFF, 0xFF, 0xE9, 0xB4, 0x60, 0x44, +- 0x15, 0x60, 0xCF, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x26, 0x02, 0xBC, 0x64, 0x40, 0x02, 0x2A, +- 0x04, 0xBC, 0x64, 0x40, 0x04, 0x26, 0x08, 0x00, 0x15, 0x60, 0xDD, 0xFB, 0x13, 0x64, 0xAD, 0xFB, +- 0x01, 0x60, 0x67, 0x64, 0x37, 0xFB, 0x0C, 0x00, 0x10, 0xBC, 0x15, 0x60, 0xDD, 0xFB, 0x08, 0x64, +- 0xAD, 0xFB, 0x82, 0xF3, 0x01, 0x60, 0x67, 0x7C, 0x60, 0x40, 0x01, 0x27, 0x5B, 0x7C, 0x37, 0xF9, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0x15, 0x60, 0xD0, 0xFB, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x25, 0xF2, 0x15, 0x60, 0xD1, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, +- 0x15, 0x60, 0xEB, 0xFB, 0xFF, 0xFF, 0x0F, 0x22, 0x41, 0x75, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x04, 0x61, 0x06, 0x00, 0x01, 0x64, 0x01, 0x00, 0x00, 0x64, 0x18, 0x60, 0x13, 0xFB, 0x06, 0x61, +- 0x41, 0x56, 0xC7, 0xFE, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x78, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x10, 0x02, 0x08, 0x61, +- 0x41, 0x56, 0xC7, 0xFE, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, +- 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x03, 0x00, 0x04, 0x7C, 0xBC, 0xF9, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x78, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x10, 0x02, +- 0x0A, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, +- 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x03, 0x00, 0x01, 0x7C, 0xBC, 0xF9, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x63, 0x64, 0xF3, 0x23, 0xFC, 0x60, 0x40, 0x01, 0x23, 0x17, 0x00, +- 0x01, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x11, 0x60, 0x14, 0x61, 0x11, 0x60, 0xF4, 0x65, 0xA1, 0xD1, +- 0xD5, 0x80, 0xD0, 0x80, 0x0B, 0x03, 0x02, 0x03, 0x08, 0xA1, 0xF9, 0x01, 0x04, 0xA1, 0xA1, 0xD3, +- 0x01, 0x60, 0x00, 0x65, 0x60, 0x47, 0xFF, 0xB4, 0xB4, 0x84, 0x01, 0x00, 0xFF, 0x64, 0x25, 0xFA, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x46, 0x45, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, +- 0xD0, 0x80, 0x00, 0xF4, 0x01, 0xF2, 0x66, 0x5C, 0x25, 0x46, 0x56, 0x02, 0x70, 0x27, 0x54, 0x00, +- 0x12, 0x64, 0x03, 0xFA, 0x04, 0xF8, 0x0E, 0xF2, 0x87, 0xFC, 0x8D, 0xFC, 0x8E, 0xFC, 0xDA, 0x82, +- 0x16, 0x61, 0x00, 0x63, 0xC9, 0x81, 0x5A, 0xDC, 0xFD, 0x02, 0x60, 0x40, 0xF0, 0x3B, 0x16, 0x00, +- 0x32, 0x44, 0x8E, 0xF3, 0x01, 0xB0, 0xF6, 0xA0, 0x08, 0x24, 0x2C, 0x05, 0xDC, 0x83, 0xF0, 0x67, +- 0x0E, 0xFA, 0x1F, 0x60, 0x0A, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0x8E, 0xFD, 0x2B, 0xFF, 0xFE, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x4F, 0x00, 0x8F, 0xF3, 0x09, 0x65, +- 0xD4, 0x80, 0xDC, 0x83, 0x17, 0x05, 0x8F, 0xFD, 0x98, 0xFE, 0x04, 0x04, 0x00, 0x7F, 0x08, 0x7E, +- 0x0E, 0xFA, 0x3B, 0xFF, 0x1E, 0x60, 0xFE, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0x0E, 0xF2, 0x2B, 0xFF, 0x60, 0x40, 0x08, 0x26, 0xF7, 0xFE, 0xFD, 0x64, 0x3B, 0x42, +- 0x4A, 0xDB, 0x32, 0x00, 0x8B, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, 0xFF, 0xFF, 0x0D, 0x04, 0x1F, 0x60, +- 0x16, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xFC, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x21, 0x00, 0x46, 0x45, 0x00, 0x64, 0x2B, 0xDB, 0x25, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, +- 0x0A, 0x18, 0x70, 0x67, 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, +- 0x25, 0x44, 0x80, 0xFC, 0x05, 0xFA, 0xB6, 0x60, 0x58, 0x4E, 0x72, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, +- 0xA3, 0xFF, 0xFF, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0xD4, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, +- 0x1F, 0x60, 0x04, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x0D, 0x00, 0x1E, 0x60, 0xF8, 0x64, 0x40, 0x47, +- 0x58, 0x4F, 0x18, 0x00, 0x1F, 0x60, 0x10, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x03, 0x00, 0xF0, 0x60, +- 0xC7, 0x78, 0xFF, 0xFF, 0x27, 0xD5, 0x0E, 0xF2, 0x0B, 0x18, 0x60, 0x40, 0x01, 0x2A, 0x08, 0x00, +- 0x1F, 0x60, 0x26, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, 0xF2, 0x01, +- 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD5, 0x0E, 0xF2, 0x14, 0x18, 0x60, 0x40, 0x01, 0x2A, 0x11, 0x00, +- 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0x8F, 0xF3, 0x02, 0x02, 0xCC, 0x84, +- 0x8F, 0xFB, 0x1F, 0x60, 0x26, 0x64, 0x40, 0x4B, 0xF6, 0x60, 0x58, 0x4D, 0xB3, 0x78, 0xFF, 0xFF, +- 0xE9, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFB, 0x64, 0x3A, 0x42, 0x4A, 0xDB, 0xA2, 0xFF, 0x92, 0xF3, +- 0x8E, 0xF3, 0xCC, 0x80, 0xFA, 0xA0, 0x01, 0x14, 0x1D, 0x05, 0xB5, 0x60, 0x58, 0x4D, 0x77, 0x78, +- 0xFF, 0xFF, 0xA2, 0xFF, 0x17, 0x03, 0xF0, 0x67, 0x0E, 0xFA, 0x1F, 0x60, 0x0A, 0x64, 0x0F, 0x60, +- 0x93, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF6, 0x64, +- 0x3A, 0x42, 0x4A, 0xDB, 0x92, 0xF3, 0x8E, 0xF3, 0xCC, 0x83, 0xDC, 0x84, 0x01, 0x15, 0x92, 0xFD, +- 0x8E, 0xFB, 0xD4, 0xFE, 0x91, 0xF3, 0x8F, 0xF3, 0x00, 0xA8, 0x90, 0xF1, 0x03, 0x02, 0xD0, 0x80, +- 0xFF, 0xFF, 0x26, 0x05, 0xB5, 0x60, 0x58, 0x4D, 0x77, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, 0x20, 0x03, +- 0x00, 0x63, 0x91, 0xF3, 0x0E, 0xFC, 0xCC, 0x84, 0xFF, 0x3A, 0x91, 0xFB, 0x98, 0xFE, 0x03, 0x04, +- 0x08, 0xBB, 0x0E, 0xFC, 0x3B, 0xFF, 0x1E, 0x60, 0xFE, 0x64, 0x0F, 0x60, 0x93, 0xFB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF7, 0x64, 0x3A, 0x42, 0x4A, 0xDB, +- 0x8F, 0xF3, 0x0E, 0xF2, 0xDC, 0x83, 0x08, 0xB0, 0x8F, 0xFD, 0x08, 0x28, 0xF7, 0xFE, 0xD4, 0xFE, +- 0xA3, 0xFF, 0xF0, 0x60, 0xC7, 0x78, 0xFF, 0xFF, 0xB9, 0xFE, 0x13, 0xFF, 0x24, 0x40, 0x80, 0x2B, +- 0x0B, 0x00, 0xA2, 0xFF, 0x25, 0x46, 0x09, 0xF4, 0x0E, 0xF2, 0x05, 0x18, 0x08, 0xBC, 0x0E, 0xFA, +- 0xFF, 0xFF, 0xF7, 0xFE, 0x01, 0x00, 0xD8, 0xFE, 0xA3, 0xFF, 0x25, 0x46, 0x3E, 0xF2, 0x00, 0xF4, +- 0x08, 0xF0, 0x25, 0x46, 0x06, 0xB4, 0xFF, 0x7F, 0x10, 0xBC, 0x06, 0x26, 0xFD, 0x7F, 0x0E, 0xFA, +- 0x3E, 0xF2, 0x3F, 0xF2, 0x60, 0x41, 0x08, 0x2A, 0x64, 0x47, 0x3F, 0xFA, 0x60, 0x45, 0x13, 0x60, +- 0x2D, 0xF3, 0xA3, 0xFC, 0xAB, 0xFC, 0x91, 0xFC, 0xD4, 0x80, 0x38, 0x60, 0xC1, 0x65, 0xA5, 0x80, +- 0x01, 0x04, 0x07, 0x03, 0x23, 0xF0, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xF8, 0x60, 0x57, 0x78, +- 0xFF, 0xFF, 0xFB, 0x60, 0x58, 0x4F, 0x75, 0x78, 0xFF, 0xFF, 0x0B, 0x04, 0x23, 0xF0, 0x04, 0x64, +- 0xB0, 0x84, 0xA2, 0xDA, 0x25, 0x60, 0xF4, 0x64, 0xE5, 0x60, 0x78, 0x41, 0xC7, 0x78, 0x97, 0xF1, +- 0x46, 0x00, 0x3E, 0xF0, 0x88, 0xF1, 0x64, 0x47, 0x07, 0xB4, 0x07, 0x36, 0x3B, 0x00, 0x04, 0x03, +- 0xCC, 0x84, 0xE0, 0x84, 0xC0, 0x83, 0x2D, 0x00, 0x2C, 0xF2, 0x87, 0xF1, 0x01, 0xB0, 0x64, 0x43, +- 0x35, 0x02, 0x2E, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, +- 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x2E, 0xF0, 0x63, 0x46, +- 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x2D, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, +- 0x06, 0x02, 0x61, 0x46, 0x2C, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, +- 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, +- 0x09, 0x00, 0x66, 0x45, 0x63, 0x46, 0x06, 0xF0, 0x65, 0x46, 0x64, 0x44, 0x0C, 0x26, 0x02, 0x00, +- 0x02, 0x26, 0x04, 0x00, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x07, 0xFC, 0x23, 0xF2, +- 0xFF, 0xFF, 0x0F, 0x1B, 0x1E, 0x60, 0xE0, 0x64, 0x0F, 0x60, 0x93, 0xFB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xC8, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, +- 0x0E, 0x00, 0x1E, 0x60, 0xF2, 0x64, 0x0F, 0x60, 0x93, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xCE, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0xF0, 0x60, +- 0xC7, 0x78, 0xFF, 0xFF, 0xCB, 0x84, 0xC9, 0x83, 0xFF, 0xFF, 0x08, 0x04, 0x58, 0xD1, 0xA5, 0xD8, +- 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x2F, 0x58, 0xFF, 0xFF, +- 0x25, 0xF0, 0x14, 0x60, 0x15, 0xF9, 0x11, 0x00, 0x0D, 0x60, 0x00, 0x62, 0x40, 0x63, 0x5A, 0xDF, +- 0xFE, 0x1F, 0x04, 0x65, 0x0D, 0x60, 0x00, 0x61, 0x48, 0x64, 0x3E, 0x63, 0x7C, 0xA8, 0x58, 0xD0, +- 0x59, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x14, 0x60, 0x15, 0xF1, 0x0C, 0x60, +- 0xDC, 0x65, 0x02, 0xFE, 0x64, 0x44, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x87, 0x60, 0x41, 0x64, 0x44, +- 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x84, 0x3E, 0xFB, 0x60, 0x42, 0x61, 0x44, 0x03, 0xA2, 0x60, 0xFE, +- 0xA2, 0xDB, 0x20, 0xFE, 0x64, 0x44, 0x0D, 0x60, 0x02, 0x65, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xC4, 0x84, 0x40, 0xFB, 0xFF, 0xFF, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, +- 0x5C, 0x41, 0x25, 0xF2, 0xFF, 0xFF, 0x40, 0x42, 0x80, 0x2B, 0x04, 0x00, 0xFF, 0xB4, 0x40, 0x42, +- 0x01, 0x64, 0x40, 0x41, 0x87, 0xF3, 0x46, 0x4B, 0x86, 0xF3, 0x60, 0x46, 0xE0, 0x83, 0xAB, 0x46, +- 0x26, 0xF0, 0xAB, 0x46, 0x59, 0xF8, 0xAB, 0x46, 0x27, 0xF0, 0xAB, 0x46, 0x5A, 0xF8, 0xAB, 0x46, +- 0x28, 0xF0, 0xAB, 0x46, 0x5B, 0xF8, 0x66, 0x44, 0x02, 0xA6, 0xF1, 0x1F, 0x87, 0xF3, 0xFF, 0xFF, +- 0x60, 0x46, 0xAB, 0x46, 0x0C, 0x60, 0x3A, 0x65, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, 0xC9, 0x81, 0x52, 0x64, 0x0E, 0x63, 0x58, 0xD0, 0x59, 0xD9, +- 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF0, 0xA1, 0x76, 0x64, 0x0E, 0x63, +- 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0x0C, 0x60, 0x9C, 0x65, 0xC4, 0x81, 0x60, 0x45, 0xC9, 0x81, 0x62, 0x64, 0x06, 0x63, +- 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF8, 0xA1, +- 0xB6, 0x64, 0x06, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, 0x65, 0x44, 0x0C, 0x60, +- 0xBC, 0x65, 0xC4, 0x81, 0xC9, 0x81, 0x6A, 0x64, 0x06, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, +- 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x84, 0x0C, 0x60, 0x82, 0x65, 0xC4, 0x81, +- 0x72, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0xAB, 0x46, 0x21, 0x44, 0x01, 0x2A, +- 0x06, 0x00, 0xFA, 0xA1, 0x90, 0x64, 0x04, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0x3B, 0xF0, +- 0x21, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x22, 0x44, 0x3D, 0xFB, 0x60, 0x41, 0x02, 0xFE, 0xF8, 0x84, +- 0xF8, 0x84, 0xF8, 0x84, 0x3C, 0xFB, 0x0C, 0x60, 0x7E, 0x63, 0x88, 0xFF, 0xCD, 0x81, 0x06, 0xA3, +- 0xFD, 0x0D, 0x8D, 0xFF, 0x3B, 0xFD, 0x64, 0x47, 0x80, 0xBF, 0x60, 0x5C, 0x22, 0x43, 0x80, 0x61, +- 0x88, 0xFF, 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0xB1, 0x84, +- 0x3B, 0xFA, 0x86, 0xF3, 0xFF, 0xFF, 0xCC, 0x83, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0x3B, 0xF0, +- 0x66, 0x44, 0xB1, 0x9C, 0x3B, 0xF8, 0x02, 0xA6, 0xFA, 0x1F, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, +- 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x00, 0x67, 0x24, 0x02, 0x3D, 0xF1, +- 0x64, 0x44, 0x03, 0xB4, 0x40, 0x42, 0xD0, 0x80, 0x87, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xBB, 0xF4, +- 0x80, 0x61, 0x02, 0x02, 0xE3, 0x83, 0xEB, 0x83, 0x22, 0x44, 0x88, 0xFF, 0xCC, 0x84, 0xE1, 0x81, +- 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0x9D, 0x85, 0xA7, 0x83, 0x3B, 0xFC, 0x86, 0xF3, +- 0xFF, 0xFF, 0xCC, 0x83, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0xBB, 0xF2, 0x66, 0x44, 0xA5, 0x81, +- 0xBB, 0xFA, 0x02, 0xA6, 0xFA, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x11, 0x64, 0x23, 0xFA, +- 0x25, 0x44, 0x24, 0xFA, 0x04, 0x64, 0x40, 0x4B, 0x62, 0x41, 0x0C, 0x60, 0x82, 0x64, 0x04, 0x63, +- 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, 0x2B, 0x43, 0x00, 0x7C, 0x59, 0xD8, 0x4F, 0x8B, 0x06, 0xA4, +- 0xF6, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x27, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, +- 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, +- 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, +- 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x2A, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, +- 0x30, 0x7C, 0xB0, 0x84, 0xA2, 0xDA, 0x4E, 0x61, 0x76, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, +- 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x90, 0x64, 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, +- 0x58, 0xD8, 0xFB, 0x1F, 0xD9, 0x81, 0xA0, 0x64, 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, +- 0x58, 0xD8, 0xFB, 0x1F, 0xD9, 0x81, 0xB6, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, +- 0x58, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, +- 0x23, 0x58, 0xFF, 0xFF, 0x27, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, +- 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, +- 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, +- 0x01, 0x03, 0x0D, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, 0x30, 0x61, 0x9D, 0x85, +- 0xA4, 0x84, 0xA2, 0xDA, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, +- 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x40, 0x41, 0x4A, 0x64, 0xA0, 0xD2, 0xFF, 0xFF, +- 0x40, 0x42, 0x80, 0x2B, 0x04, 0x00, 0xFF, 0xB4, 0x40, 0x42, 0x01, 0x64, 0x40, 0x41, 0x87, 0xF3, +- 0x46, 0x4B, 0x86, 0xF3, 0x60, 0x46, 0xE0, 0x83, 0xAB, 0x46, 0x32, 0xF0, 0xAB, 0x46, 0x59, 0xF8, +- 0xAB, 0x46, 0x33, 0xF0, 0xAB, 0x46, 0x5A, 0xF8, 0xAB, 0x46, 0x34, 0xF0, 0xAB, 0x46, 0x5B, 0xF8, +- 0x66, 0x44, 0x02, 0xA6, 0xF1, 0x1F, 0x87, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xAB, 0x46, 0x0C, 0x60, +- 0x3A, 0x65, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, +- 0xC9, 0x81, 0x4A, 0x64, 0x0E, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, +- 0x08, 0x00, 0xAB, 0x46, 0xF0, 0xA1, 0x76, 0x64, 0x0E, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, +- 0xAB, 0x46, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x84, 0x0C, 0x60, 0x82, 0x65, +- 0xC4, 0x81, 0x5A, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0xAB, 0x46, 0x21, 0x44, +- 0x01, 0x2A, 0x06, 0x00, 0xFA, 0xA1, 0x90, 0x64, 0x04, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, +- 0x3B, 0xF0, 0x21, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x22, 0x44, 0x3D, 0xFB, 0x60, 0x41, 0x02, 0xFE, +- 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x84, 0x3C, 0xFB, 0x0C, 0x60, 0x7E, 0x63, 0x88, 0xFF, 0xCD, 0x81, +- 0x06, 0xA3, 0xFD, 0x0D, 0x8D, 0xFF, 0x3B, 0xFD, 0x64, 0x47, 0x80, 0xBF, 0x60, 0x5C, 0x22, 0x43, +- 0x80, 0x61, 0x88, 0xFF, 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, +- 0xB1, 0x84, 0x3B, 0xFA, 0x86, 0xF3, 0xFF, 0xFF, 0xCC, 0x83, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, +- 0x3B, 0xF0, 0x66, 0x44, 0xB1, 0x9C, 0x3B, 0xF8, 0x02, 0xA6, 0xFA, 0x1F, 0xAB, 0x46, 0x00, 0x67, +- 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x00, 0x67, 0x24, 0x02, +- 0x3D, 0xF1, 0x64, 0x44, 0x03, 0xB4, 0x40, 0x42, 0xD0, 0x80, 0x87, 0xF3, 0xFF, 0xFF, 0x60, 0x46, +- 0xBB, 0xF4, 0x80, 0x61, 0x02, 0x02, 0xE3, 0x83, 0xEB, 0x83, 0x22, 0x44, 0x88, 0xFF, 0xCC, 0x84, +- 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0x9D, 0x85, 0xA7, 0x83, 0x3B, 0xFC, +- 0x86, 0xF3, 0xFF, 0xFF, 0xCC, 0x83, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0xBB, 0xF2, 0x66, 0x44, +- 0xA5, 0x81, 0xBB, 0xFA, 0x02, 0xA6, 0xFA, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x27, 0xF2, +- 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, +- 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, +- 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, +- 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, +- 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x21, 0x00, 0x43, 0x4B, +- 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, 0x30, 0x7C, 0xB0, 0x84, 0xA2, 0xDA, 0x4E, 0x61, 0x76, 0x64, +- 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x90, 0x64, 0x04, 0x63, +- 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0xA0, 0x64, 0x04, 0x63, 0xAB, 0x46, +- 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, +- 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x27, 0xF2, 0x15, 0x60, 0x02, 0x65, 0x60, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, +- 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, +- 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0x87, 0xF3, 0x08, 0xFE, +- 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x0D, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, +- 0x30, 0x61, 0x9D, 0x85, 0xA4, 0x84, 0xA2, 0xDA, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, +- 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x3E, 0xF2, 0xAB, 0xF1, 0x08, 0xB0, +- 0x19, 0xF8, 0x4A, 0x02, 0x07, 0x23, 0x2B, 0x00, 0x60, 0x47, 0x07, 0xB4, 0x88, 0xF1, 0xCC, 0x84, +- 0xE0, 0x84, 0x40, 0x8A, 0xAA, 0x46, 0x03, 0xF2, 0x04, 0xF0, 0x05, 0xF2, 0x60, 0x43, 0xAA, 0x46, +- 0x2C, 0xFC, 0x2D, 0xF8, 0x2E, 0xFA, 0xCB, 0xF1, 0x2F, 0xF8, 0xCC, 0xF1, 0x30, 0xF8, 0xCD, 0xF1, +- 0x31, 0xF8, 0x46, 0x4A, 0x00, 0xF4, 0x02, 0xF2, 0x03, 0xF0, 0x04, 0xF2, 0x60, 0x43, 0xAA, 0x46, +- 0x32, 0xFC, 0x33, 0xF8, 0x34, 0xFA, 0xAA, 0x46, 0x05, 0xF2, 0x06, 0xF0, 0x07, 0xF2, 0x60, 0x43, +- 0xAA, 0x46, 0x36, 0xFC, 0x37, 0xF8, 0x38, 0xFA, 0x03, 0x60, 0x08, 0x64, 0x1C, 0x00, 0x66, 0xF1, +- 0x2F, 0xF8, 0x67, 0xF1, 0x30, 0xF8, 0x68, 0xF1, 0x31, 0xF8, 0x46, 0x4A, 0x00, 0xF4, 0x02, 0xF2, +- 0x03, 0xF0, 0x04, 0xF2, 0x60, 0x43, 0xAA, 0x46, 0x2C, 0xFC, 0x2D, 0xF8, 0x2E, 0xFA, 0xAA, 0x46, +- 0x05, 0xF2, 0x06, 0xF0, 0x07, 0xF2, 0x60, 0x43, 0xAA, 0x46, 0x32, 0xFC, 0x33, 0xF8, 0x34, 0xFA, +- 0x02, 0x60, 0x08, 0x64, 0x00, 0x00, 0x2A, 0xFA, 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x42, 0x6F, +- 0x6F, 0x74, 0x63, 0x6F, 0x64, 0x65, 0x20, 0x21, 0x21, 0x20, 0x20, 0x00, 0x53, 0x54, 0x41, 0x2F, +- 0x41, 0x50, 0x20, 0x46, 0x75, 0x6E, 0x63, 0x27, 0x73, 0x00, 0x20, 0x00, 0x03, 0x00, 0x01, 0x00, +- 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, +- 0x04, 0x00, 0x06, 0x00, 0x07, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, +- 0x07, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, +- 0x02, 0x00, 0x00, 0x00, +- +-}; /* fw_image_4_data */ +- +-static const CFG_IDENTITY_STRCT fw_image_infoidentity[] = { +- { +- sizeof( CFG_IDENTITY_STRCT ) / sizeof(hcf_16) - 1, +- CFG_FW_IDENTITY, +- COMP_ID_FW_AP, +- 3, //Variant +- 1, //Major +- 24 //Minor +- }, +- { 0000, 0000, 0000, 0000, 0000, 0000 } //endsentinel +-}; +- +-static const CFG_PROG_STRCT fw_image_code[] = { +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, // mode +- 0x0148, // sizeof(fw_image_1_data), +- 0x00000060, // Target address in NIC Memory +- 0x0000, // CRC: yes/no TYPE: primary/station/tertiary +- (hcf_8 FAR *) fw_image_1_data +- }, +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, // mode +- 0x2432, // sizeof(fw_image_2_data), +- 0x00000C16, // Target address in NIC Memory +- 0x0000, // CRC: yes/no TYPE: primary/station/tertiary +- (hcf_8 FAR *) fw_image_2_data +- }, +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, // mode +- 0x194c, // sizeof(fw_image_3_data), +- 0x001E3048, // Target address in NIC Memory +- 0x0000, // CRC: yes/no TYPE: primary/station/tertiary +- (hcf_8 FAR *) fw_image_3_data +- }, +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, // mode +- 0xb7e4, // sizeof(fw_image_4_data), +- 0x001F4000, // Target address in NIC Memory +- 0x0000, // CRC: yes/no TYPE: primary/station/tertiary +- (hcf_8 FAR *) fw_image_4_data +- }, +- { +- 5, +- CFG_PROG, +- CFG_PROG_STOP, // mode +- 0000, +- 0x000F2101, // Start execution address +- }, +- { 0000, 0000, 0000, 0000, 00000000, 0000, 00000000} +-}; +- +-static const CFG_RANGE20_STRCT fw_image_infocompat[] = { +- { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), +- CFG_FW_SUP_RANGE, +- COMP_ROLE_SUPL, +- COMP_ID_APF, +- { +- { 4, 1, 1 } //variant, bottom, top +- } +- }, +- { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), +- CFG_MFI_ACT_RANGES_STA, +- COMP_ROLE_ACT, +- COMP_ID_MFI, +- { +- { 7, 3, 3 }, //variant, bottom, top +- { 8, 1, 1 } //variant, bottom, top +- } +- }, +- { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), +- CFG_CFI_ACT_RANGES_STA, +- COMP_ROLE_ACT, +- COMP_ID_CFI, +- { +- { 4, 1, 2 } //variant, bottom, top +- } +- }, +- { 0000, 0000, 0000, 0000, { { 0000, 0000, 0000 } } } //endsentinel +-}; +- +-memimage fw_image = { +- "FUPU7D37dhfwci\001C", //signature, , C/Bin type +- (CFG_PROG_STRCT *) fw_image_code, +- 0x000F2101, +- 00000000, //(dummy) pdaplug +- 00000000, //(dummy) priplug +- (CFG_RANGE20_STRCT *) fw_image_infocompat, +- (CFG_IDENTITY_STRCT *) fw_image_infoidentity, +-}; +- +diff --git a/drivers/staging/wlags49_h2/sta_h2.c b/drivers/staging/wlags49_h2/sta_h2.c +deleted file mode 100644 +index f9a3852..0000000 +--- a/drivers/staging/wlags49_h2/sta_h2.c ++++ /dev/null +@@ -1,4480 +0,0 @@ +-/* +- * File: sta_h24.236 +- * +- * Abstract: This file contains memory image 'fw_image'. +- * +- * Contents: Total size of the memory image: 69294 bytes. +- * Total number of blocks: 4 blocks. +- * Block 1 : load address 00000060, 390 bytes. +- * Block 2 : load address 00000C16, 9496 bytes. +- * Block 3 : load address 001E312E, 15786 bytes. +- * Block 4 : load address 001F4000, 43622 bytes. +- * +- * Identity: component id: 31 (variant 3) version 2.36 +- * +- * Compatibility: +- * supplying interface 4 (variant 2) : 2 - 5 +- * acting on interface 1 (variant 4) : 6 - 7 +- * acting on interface 1 (variant 5) : 6 - 7 +- * acting on interface 1 (variant 6) : 6 - 7 +- * acting on interface 2 (variant 2) : 1 - 2 +- * +- * Generated: by g:\fw\fupu3.exe version 4.26 +- * +- * Commandline: g:\fw\fupu3.exe /f=4 /n=fw_image /i=r3023600.hex +- */ +- +- +-#include "hcfcfg.h" // to get hcf_16 etc defined as well as +- // possible settings which inluence mdd.h or dhf.h +-#include "mdd.h" //to get COMP_ID_STA etc defined +-#include "dhf.h" //used to be "fhfmem.h", to get memblock,plugrecord, +- +-static const hcf_8 fw_image_1_data[] = { +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x0D, 0x00, 0x00, +- 0x3A, 0x0C, 0x00, 0x00, 0x3A, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x1B, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x86, 0x19, 0x86, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, +- 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0xEA, 0x00, 0x00, 0xFF, 0x07, 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x10, 0x27, 0x10, 0x27, +- 0x14, 0x00, 0xD0, 0x07, 0xD0, 0x07, 0x10, 0x27, 0x2F, 0x00, 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, +- 0x02, 0x00, 0x02, 0x00, 0x10, 0x27, 0x05, 0x00, 0x00, 0x02, 0x00, 0x02, 0x13, 0x00, 0x0A, 0x00, +- 0x07, 0x00, 0x03, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x09, 0x2B, 0x09, 0x2B, 0x09, +- 0x03, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x14, 0x01, 0x00, 0x40, 0x00, 0x32, 0x00, 0x32, 0x00, +- 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- +-}; /* fw_image_1_data */ +- +-static const hcf_8 fw_image_2_data[] = { +- 0x4B, 0xA3, 0x00, 0x0A, 0x10, 0x01, 0x68, 0xA4, 0xB0, 0x01, 0x84, 0x01, 0x30, 0x33, 0x31, 0x33, +- 0x44, 0x44, 0x30, 0x33, 0x31, 0x33, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, 0x32, 0x33, 0x90, 0x00, +- 0x78, 0x04, 0xAE, 0xE4, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, +- 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x84, 0xF8, 0x99, 0xEE, +- 0x8D, 0xF6, 0x0D, 0xFF, 0xBD, 0xD6, 0xB1, 0xDE, 0x54, 0x91, 0x50, 0x60, 0x03, 0x02, 0xA9, 0xCE, +- 0x7D, 0x56, 0x19, 0xE7, 0x62, 0xB5, 0xE6, 0x4D, 0x9A, 0xEC, 0x45, 0x8F, 0x9D, 0x1F, 0x40, 0x89, +- 0x87, 0xFA, 0x15, 0xEF, 0xEB, 0xB2, 0xC9, 0x8E, 0x0B, 0xFB, 0xEC, 0x41, 0x67, 0xB3, 0xFD, 0x5F, +- 0xEA, 0x45, 0xBF, 0x23, 0xF7, 0x53, 0x96, 0xE4, 0x5B, 0x9B, 0xC2, 0x75, 0x1C, 0xE1, 0xAE, 0x3D, +- 0x6A, 0x4C, 0x5A, 0x6C, 0x41, 0x7E, 0x02, 0xF5, 0x4F, 0x83, 0x5C, 0x68, 0xF4, 0x51, 0x34, 0xD1, +- 0x08, 0xF9, 0x93, 0xE2, 0x73, 0xAB, 0x53, 0x62, 0x3F, 0x2A, 0x0C, 0x08, 0x52, 0x95, 0x65, 0x46, +- 0x5E, 0x9D, 0x28, 0x30, 0xA1, 0x37, 0x0F, 0x0A, 0xB5, 0x2F, 0x09, 0x0E, 0x36, 0x24, 0x9B, 0x1B, +- 0x3D, 0xDF, 0x26, 0xCD, 0x69, 0x4E, 0xCD, 0x7F, 0x9F, 0xEA, 0x1B, 0x12, 0x9E, 0x1D, 0x74, 0x58, +- 0x2E, 0x34, 0x2D, 0x36, 0xB2, 0xDC, 0xEE, 0xB4, 0xFB, 0x5B, 0xF6, 0xA4, 0x4D, 0x76, 0x61, 0xB7, +- 0xCE, 0x7D, 0x7B, 0x52, 0x3E, 0xDD, 0x71, 0x5E, 0x97, 0x13, 0xF5, 0xA6, 0x68, 0xB9, 0x00, 0x00, +- 0x2C, 0xC1, 0x60, 0x40, 0x1F, 0xE3, 0xC8, 0x79, 0xED, 0xB6, 0xBE, 0xD4, 0x46, 0x8D, 0xD9, 0x67, +- 0x4B, 0x72, 0xDE, 0x94, 0xD4, 0x98, 0xE8, 0xB0, 0x4A, 0x85, 0x6B, 0xBB, 0x2A, 0xC5, 0xE5, 0x4F, +- 0x16, 0xED, 0xC5, 0x86, 0xD7, 0x9A, 0x55, 0x66, 0x94, 0x11, 0xCF, 0x8A, 0x10, 0xE9, 0x06, 0x04, +- 0x81, 0xFE, 0xF0, 0xA0, 0x44, 0x78, 0xBA, 0x25, 0xE3, 0x4B, 0xF3, 0xA2, 0xFE, 0x5D, 0xC0, 0x80, +- 0x8A, 0x05, 0xAD, 0x3F, 0xBC, 0x21, 0x48, 0x70, 0x04, 0xF1, 0xDF, 0x63, 0xC1, 0x77, 0x75, 0xAF, +- 0x63, 0x42, 0x30, 0x20, 0x1A, 0xE5, 0x0E, 0xFD, 0x6D, 0xBF, 0x4C, 0x81, 0x14, 0x18, 0x35, 0x26, +- 0x2F, 0xC3, 0xE1, 0xBE, 0xA2, 0x35, 0xCC, 0x88, 0x39, 0x2E, 0x57, 0x93, 0xF2, 0x55, 0x82, 0xFC, +- 0x47, 0x7A, 0xAC, 0xC8, 0xE7, 0xBA, 0x2B, 0x32, 0x95, 0xE6, 0xA0, 0xC0, 0x98, 0x19, 0xD1, 0x9E, +- 0x7F, 0xA3, 0x66, 0x44, 0x7E, 0x54, 0xAB, 0x3B, 0x83, 0x0B, 0xCA, 0x8C, 0x29, 0xC7, 0xD3, 0x6B, +- 0x3C, 0x28, 0x79, 0xA7, 0xE2, 0xBC, 0x1D, 0x16, 0x76, 0xAD, 0x3B, 0xDB, 0x56, 0x64, 0x4E, 0x74, +- 0x1E, 0x14, 0xDB, 0x92, 0x0A, 0x0C, 0x6C, 0x48, 0xE4, 0xB8, 0x5D, 0x9F, 0x6E, 0xBD, 0xEF, 0x43, +- 0xA6, 0xC4, 0xA8, 0x39, 0xA4, 0x31, 0x37, 0xD3, 0x8B, 0xF2, 0x32, 0xD5, 0x43, 0x8B, 0x59, 0x6E, +- 0xB7, 0xDA, 0x8C, 0x01, 0x64, 0xB1, 0xD2, 0x9C, 0xE0, 0x49, 0xB4, 0xD8, 0xFA, 0xAC, 0x07, 0xF3, +- 0x25, 0xCF, 0xAF, 0xCA, 0x8E, 0xF4, 0xE9, 0x47, 0x18, 0x10, 0xD5, 0x6F, 0x88, 0xF0, 0x6F, 0x4A, +- 0x72, 0x5C, 0x24, 0x38, 0xF1, 0x57, 0xC7, 0x73, 0x51, 0x97, 0x23, 0xCB, 0x7C, 0xA1, 0x9C, 0xE8, +- 0x21, 0x3E, 0xDD, 0x96, 0xDC, 0x61, 0x86, 0x0D, 0x85, 0x0F, 0x90, 0xE0, 0x42, 0x7C, 0xC4, 0x71, +- 0xAA, 0xCC, 0xD8, 0x90, 0x05, 0x06, 0x01, 0xF7, 0x12, 0x1C, 0xA3, 0xC2, 0x5F, 0x6A, 0xF9, 0xAE, +- 0xD0, 0x69, 0x91, 0x17, 0x58, 0x99, 0x27, 0x3A, 0xB9, 0x27, 0x38, 0xD9, 0x13, 0xEB, 0xB3, 0x2B, +- 0x33, 0x22, 0xBB, 0xD2, 0x70, 0xA9, 0x89, 0x07, 0xA7, 0x33, 0xB6, 0x2D, 0x22, 0x3C, 0x92, 0x15, +- 0x20, 0xC9, 0x49, 0x87, 0xFF, 0xAA, 0x78, 0x50, 0x7A, 0xA5, 0x8F, 0x03, 0xF8, 0x59, 0x80, 0x09, +- 0x17, 0x1A, 0xDA, 0x65, 0x31, 0xD7, 0xC6, 0x84, 0xB8, 0xD0, 0xC3, 0x82, 0xB0, 0x29, 0x77, 0x5A, +- 0x11, 0x1E, 0xCB, 0x7B, 0xFC, 0xA8, 0xD6, 0x6D, 0x3A, 0x2C, 0x00, 0x30, 0x00, 0x31, 0x00, 0x33, +- 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x38, 0x00, 0x3A, 0x00, 0x3B, +- 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x3F, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x02, 0x14, +- 0x05, 0x32, 0x0B, 0x37, 0x08, 0x50, 0x0B, 0x6E, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x3F, 0x00, +- 0x0C, 0x00, 0x30, 0x00, 0x03, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0x3C, 0x00, 0x02, 0x00, 0x04, 0x00, +- 0x0A, 0x00, 0x0B, 0x00, 0x10, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x63, 0x00, 0x20, 0x00, 0x63, 0x00, 0x63, 0x00, 0x20, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x10, +- 0xEE, 0x10, 0xA6, 0x10, 0xE8, 0x10, 0xAC, 0x10, 0xE2, 0x10, 0xB2, 0x10, 0xDC, 0x10, 0xB8, 0x10, +- 0xD6, 0x10, 0xBE, 0x10, 0xD0, 0x10, 0xC4, 0x10, 0xCA, 0x10, 0x07, 0x01, 0x00, 0x00, 0x0A, 0x22, +- 0x00, 0x04, 0x08, 0x01, 0x00, 0x00, 0x0A, 0x26, 0x00, 0x04, 0x09, 0x01, 0x00, 0x00, 0x0A, 0x2A, +- 0x00, 0x04, 0x0A, 0x01, 0x00, 0x00, 0x0A, 0x2E, 0x00, 0x04, 0x0B, 0x01, 0x00, 0x00, 0x10, 0x24, +- 0x04, 0x04, 0x0C, 0x01, 0x00, 0x00, 0x10, 0x28, 0x04, 0x04, 0x0D, 0x01, 0x00, 0x00, 0x10, 0x2C, +- 0x04, 0x04, 0x0E, 0x01, 0x00, 0x00, 0x10, 0x30, 0x04, 0x04, 0x0F, 0x01, 0x00, 0x00, 0x16, 0x34, +- 0x08, 0x04, 0x10, 0x01, 0x00, 0x00, 0x16, 0x38, 0x08, 0x04, 0x11, 0x01, 0x00, 0x00, 0x16, 0x3C, +- 0x08, 0x04, 0x12, 0x01, 0x00, 0x00, 0x16, 0x40, 0x08, 0x04, 0x13, 0x01, 0x00, 0x00, 0x17, 0x64, +- 0x0C, 0x0B, 0x14, 0x01, 0x00, 0x00, 0x17, 0x68, 0x0C, 0x0B, 0x15, 0x01, 0x00, 0x00, 0x17, 0x6C, +- 0x0C, 0x0B, 0x16, 0x01, 0x00, 0x00, 0x17, 0x70, 0x0C, 0x0B, 0x17, 0x01, 0x00, 0x00, 0x17, 0x74, +- 0x0C, 0x0B, 0x18, 0x01, 0x00, 0x00, 0x17, 0x78, 0x0C, 0x0B, 0x19, 0x01, 0x00, 0x00, 0x17, 0x7C, +- 0x0C, 0x0B, 0x1A, 0x01, 0x00, 0x00, 0x17, 0x80, 0x0C, 0x0B, 0x1B, 0x01, 0x00, 0x00, 0x17, 0x84, +- 0x0C, 0x0B, 0x1C, 0x01, 0x00, 0x00, 0x17, 0x88, 0x0C, 0x0B, 0x1D, 0x01, 0x00, 0x00, 0x17, 0x8C, +- 0x0C, 0x0B, 0x1E, 0x01, 0x00, 0x00, 0x1D, 0x95, 0x17, 0x04, 0x1F, 0x01, 0x00, 0x00, 0x1D, 0x99, +- 0x17, 0x04, 0x20, 0x01, 0x00, 0x00, 0x1D, 0x9D, 0x17, 0x04, 0x21, 0x01, 0x00, 0x00, 0x1D, 0xA1, +- 0x17, 0x04, 0x22, 0x01, 0x00, 0x00, 0x0E, 0xA5, 0x00, 0x00, 0x10, 0x11, 0x30, 0x11, 0x50, 0x11, +- 0x70, 0x11, 0xC8, 0x11, 0x18, 0x11, 0x38, 0x11, 0x58, 0x11, 0x78, 0x11, 0xD0, 0x11, 0x20, 0x11, +- 0x40, 0x11, 0x60, 0x11, 0x80, 0x11, 0xD8, 0x11, 0x28, 0x11, 0x48, 0x11, 0x68, 0x11, 0x88, 0x11, +- 0xE0, 0x11, 0x90, 0x11, 0x98, 0x11, 0xA0, 0x11, 0xA8, 0x11, 0xB0, 0x11, 0xB8, 0x11, 0xC0, 0x11, +- 0xE8, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x36, 0x25, 0x4F, 0x25, 0x72, 0x25, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xAC, 0x25, +- 0x02, 0x2B, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xF3, 0x2D, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, +- 0xE1, 0x24, 0xE1, 0x24, 0x8B, 0x27, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, +- 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, +- 0xE1, 0x24, 0xE1, 0x24, 0xE5, 0x27, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, +- 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, +- 0xE1, 0x24, 0x59, 0x27, 0x73, 0x27, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, 0xE1, 0x24, +- 0xE1, 0x24, 0x47, 0x23, 0xCE, 0x25, 0xE1, 0x25, 0x91, 0x26, 0x95, 0x26, 0xE1, 0x24, 0xE1, 0x24, +- 0x44, 0x27, 0x51, 0xEA, 0xFF, 0xE9, 0x00, 0x00, 0x48, 0xEA, 0x00, 0x00, 0x00, 0x00, 0xC9, 0xEA, +- 0x65, 0x25, 0x89, 0x25, 0x00, 0x00, 0xF8, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x13, 0x2B, 0xE0, 0xFC, +- 0x4C, 0x28, 0xC6, 0x2A, 0x5A, 0x00, 0x02, 0x00, 0xF9, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0x00, 0x01, +- 0x02, 0x00, 0xF7, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0x50, 0x28, 0x06, 0x00, 0xF0, 0xFF, 0x4C, 0x28, +- 0x29, 0x28, 0x00, 0x00, 0x00, 0x02, 0xF6, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0x6C, 0x00, 0x02, 0x00, +- 0xF4, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0xAA, 0x01, 0x02, 0x00, 0xF5, 0xFF, 0x4C, 0x28, 0xCF, 0x2A, +- 0x42, 0x28, 0x02, 0x00, 0xE0, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0xCE, 0x2D, 0x02, 0x00, 0xE1, 0xFF, +- 0x4C, 0x28, 0x62, 0x28, 0xD0, 0x2D, 0x02, 0x00, 0xE2, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0xD2, 0x2D, +- 0x02, 0x00, 0xE3, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0xCA, 0x2D, 0x02, 0x00, 0x03, 0xFC, 0x4C, 0x28, +- 0x17, 0x2A, 0x16, 0x2D, 0x02, 0x00, 0x04, 0xFC, 0x4C, 0x28, 0x5C, 0x28, 0x58, 0x28, 0x22, 0x00, +- 0x06, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0x40, 0x28, 0x02, 0x00, 0x07, 0xFC, 0x4C, 0x28, 0x62, 0x28, +- 0x9C, 0x28, 0x02, 0x00, 0x0E, 0xFC, 0x4C, 0x28, 0x29, 0x2A, 0xA6, 0x28, 0x22, 0x00, 0xB1, 0xFC, +- 0x4C, 0x28, 0x1D, 0x2B, 0xA2, 0x29, 0x02, 0x00, 0x20, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xCC, 0x28, +- 0x02, 0x00, 0x25, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xD6, 0x28, 0x02, 0x00, 0x26, 0xFC, 0x4C, 0x28, +- 0x62, 0x28, 0xD8, 0x28, 0x02, 0x00, 0x27, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xDA, 0x28, 0x02, 0x00, +- 0xB2, 0xFC, 0x4C, 0x28, 0x5C, 0x28, 0xC6, 0x29, 0x22, 0x00, 0xC1, 0xFC, 0x4C, 0x28, 0x62, 0x28, +- 0x5A, 0x2D, 0x20, 0x00, 0xB0, 0xFC, 0x1F, 0x28, 0x22, 0x2B, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xFC, +- 0x1F, 0x28, 0xE7, 0x2A, 0x00, 0x00, 0x08, 0x00, 0xC8, 0xFC, 0x1F, 0x28, 0xE2, 0x2A, 0x00, 0x00, +- 0x08, 0x00, 0xB4, 0xFC, 0x1F, 0x28, 0x60, 0x2B, 0x00, 0x00, 0x00, 0x00, 0xB6, 0xFC, 0x1F, 0x28, +- 0x11, 0x2C, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xFC, 0x1F, 0x28, 0x3B, 0x2C, 0x00, 0x00, 0x00, 0x00, +- 0xB8, 0xFC, 0x1F, 0x28, 0x98, 0x2C, 0x00, 0x00, 0x00, 0x00, 0xB5, 0xFC, 0x4C, 0x28, 0x62, 0x28, +- 0xC6, 0x2D, 0x02, 0x00, 0xB9, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xC8, 0x2D, 0x02, 0x00, 0x90, 0xFD, +- 0x4C, 0x28, 0x29, 0x28, 0xCC, 0x2D, 0x02, 0x00, 0x23, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xD2, 0x28, +- 0x02, 0x00, 0x29, 0xFC, 0x44, 0x29, 0xF1, 0x28, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xFC, 0x4C, 0x28, +- 0x62, 0x28, 0x0E, 0x2D, 0x02, 0x00, 0x32, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xA0, 0x01, 0x02, 0x00, +- 0x33, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xA2, 0x01, 0x02, 0x00, 0x00, 0xFC, 0x4C, 0x28, 0x62, 0x28, +- 0x56, 0x28, 0x02, 0x00, 0x01, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0x50, 0x28, 0x06, 0x00, 0x02, 0xFC, +- 0x4C, 0x28, 0xDC, 0x28, 0xA4, 0x29, 0x22, 0x00, 0x05, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0x46, 0x28, +- 0x02, 0x00, 0x08, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0x4A, 0x28, 0x06, 0x00, 0x09, 0xFC, 0x4C, 0x28, +- 0x62, 0x28, 0x9E, 0x28, 0x02, 0x00, 0x0B, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xA0, 0x28, 0x02, 0x00, +- 0x0C, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xA2, 0x28, 0x02, 0x00, 0x0D, 0xFC, 0x4C, 0x28, 0x62, 0x28, +- 0xA4, 0x28, 0x02, 0x00, 0x21, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xCE, 0x28, 0x02, 0x00, 0x80, 0xFC, +- 0xB8, 0x28, 0xC8, 0x28, 0xE2, 0x28, 0xC0, 0x00, 0x81, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xA8, 0x01, +- 0x02, 0x00, 0x83, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xAC, 0x01, 0x02, 0x00, 0x85, 0xFC, 0x4C, 0x28, +- 0x49, 0x2A, 0xA6, 0x01, 0x02, 0x00, 0x86, 0xFC, 0x4C, 0x28, 0x5B, 0x2A, 0xB2, 0x01, 0x02, 0x00, +- 0x28, 0xFC, 0x4C, 0x28, 0x62, 0x28, 0xDC, 0x28, 0x02, 0x00, 0x87, 0xFC, 0x4C, 0x28, 0x62, 0x28, +- 0xEC, 0x29, 0x22, 0x03, 0x84, 0xFC, 0x4C, 0x28, 0x70, 0x2A, 0xB0, 0x01, 0x02, 0x00, 0x2B, 0xFC, +- 0x4C, 0x28, 0x62, 0x28, 0x14, 0x31, 0x02, 0x00, 0xF8, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0x0E, 0x31, +- 0x02, 0x00, 0xF3, 0xFF, 0x4C, 0x28, 0x62, 0x28, 0x16, 0x31, 0x02, 0x00, 0x20, 0xFD, 0x7D, 0x28, +- 0x29, 0x28, 0x23, 0x34, 0x08, 0x00, 0x21, 0xFD, 0x7D, 0x28, 0x29, 0x28, 0x27, 0x34, 0x0A, 0x00, +- 0x22, 0xFD, 0x7D, 0x28, 0x29, 0x28, 0x2C, 0x34, 0x16, 0x00, 0x23, 0xFD, 0x7D, 0x28, 0x29, 0x28, +- 0x37, 0x34, 0x0A, 0x00, 0x10, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x74, 0x01, 0x02, 0x00, 0x45, 0xFD, +- 0x4C, 0x28, 0x29, 0x28, 0x00, 0x01, 0x02, 0x00, 0x47, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x78, 0x01, +- 0x02, 0x00, 0x48, 0xFD, 0x9A, 0x29, 0x29, 0x28, 0xA0, 0x01, 0x02, 0x00, 0x49, 0xFD, 0x9A, 0x29, +- 0x29, 0x28, 0xA2, 0x01, 0x02, 0x00, 0x4A, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x98, 0x01, 0x02, 0x00, +- 0x4B, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x9A, 0x01, 0x02, 0x00, 0x4D, 0xFD, 0x7D, 0x28, 0x29, 0x28, +- 0x3C, 0x34, 0x04, 0x00, 0x4F, 0xFD, 0xAE, 0x29, 0x29, 0x28, 0x1A, 0x2D, 0x02, 0x00, 0xC0, 0xFD, +- 0x7D, 0x28, 0x29, 0x28, 0x3E, 0x34, 0x02, 0x00, 0xC2, 0xFD, 0xA4, 0x29, 0x29, 0x28, 0x00, 0x00, +- 0x02, 0x00, 0xC3, 0xFD, 0x7D, 0x28, 0x29, 0x28, 0x3F, 0x34, 0x02, 0x00, 0x40, 0xFD, 0x75, 0x28, +- 0x29, 0x28, 0xB8, 0x01, 0x02, 0x00, 0x24, 0xFD, 0xCB, 0x29, 0x29, 0x28, 0x00, 0x00, 0x02, 0x00, +- 0x91, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x20, 0x24, 0x02, 0x00, 0x93, 0xFD, 0x4C, 0x28, 0x29, 0x28, +- 0x26, 0x24, 0x02, 0x00, 0xC1, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0xFE, 0x00, 0x02, 0x00, 0xC6, 0xFD, +- 0xAA, 0x28, 0x29, 0x28, 0x28, 0x2D, 0x0A, 0x00, 0x89, 0xFD, 0x5B, 0x29, 0x29, 0x28, 0x00, 0x00, +- 0x00, 0x00, 0x8A, 0xFD, 0x9A, 0x28, 0x29, 0x28, 0xA0, 0x2D, 0x24, 0x00, 0x41, 0xFD, 0x4C, 0x28, +- 0x29, 0x28, 0x7A, 0x2D, 0x22, 0x00, 0x42, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x02, 0x01, 0x06, 0x00, +- 0x43, 0xFD, 0xD8, 0x29, 0x29, 0x28, 0x00, 0x00, 0x06, 0x00, 0x44, 0xFD, 0xB8, 0x29, 0x29, 0x28, +- 0xB4, 0x01, 0x02, 0x00, 0x46, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0xBA, 0x01, 0x0C, 0x00, 0x4C, 0xFD, +- 0x4C, 0x28, 0x29, 0x28, 0xEA, 0x29, 0x02, 0x00, 0x50, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0xF4, 0x00, +- 0x02, 0x00, 0x51, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0xF6, 0x00, 0x02, 0x00, 0x52, 0xFD, 0x4C, 0x28, +- 0x29, 0x28, 0xC6, 0x01, 0x02, 0x00, 0x8F, 0xFD, 0xEB, 0x29, 0x29, 0x28, 0x00, 0x00, 0x08, 0x00, +- 0x92, 0xFD, 0x4C, 0x28, 0x29, 0x28, 0x54, 0x2D, 0x02, 0x00, 0x8C, 0xFD, 0x3F, 0x28, 0x29, 0x28, +- 0x08, 0x2E, 0x56, 0x00, 0x8D, 0xFD, 0x3F, 0x28, 0x29, 0x28, 0x62, 0x2E, 0x14, 0x00, 0x00, 0xF1, +- 0x46, 0x00, 0xE3, 0x27, 0x3A, 0x01, 0x01, 0xF1, 0x44, 0x07, 0xE1, 0x27, 0x3C, 0x01, 0x00, 0x03, +- 0x2A, 0x68, 0x1E, 0x00, 0x76, 0x01, 0xFE, 0x00, 0xD6, 0x01, 0x02, 0x01, 0x3E, 0x01, 0xB8, 0x01, +- 0x74, 0x27, 0x5A, 0x01, 0x20, 0x24, 0x20, 0x00, 0x00, 0x00, 0xBA, 0x1C, 0x00, 0x00, 0xBE, 0x1E, +- 0x54, 0x01, 0x0B, 0x00, 0xBA, 0x00, 0xE4, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xAF, 0x37, 0xAF, 0x43, 0xB0, +- 0x4C, 0xB0, 0x48, 0xAF, 0xDE, 0xAF, 0xB6, 0xAF, 0x1C, 0x33, 0x7F, 0x32, 0x1C, 0x33, 0xF3, 0x32, +- 0x89, 0x32, 0x7D, 0x32, 0x3B, 0x33, 0x4C, 0x33, 0x4C, 0x33, 0x4C, 0x33, 0x55, 0x33, 0x70, 0x33, +- 0xCD, 0x33, 0xE9, 0x33, 0xF4, 0x32, 0x07, 0x33, 0xDB, 0x32, 0x10, 0x00, 0x12, 0x00, 0x13, 0x00, +- 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, +- 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x14, 0x01, +- 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0x14, 0x01, 0xF3, 0x02, +- 0xAD, 0x03, 0x60, 0x04, 0x04, 0x05, 0x07, 0x06, 0x08, 0x07, 0x0A, 0x08, 0x16, 0x09, 0x44, 0x0A, +- 0x04, 0x0B, 0x40, 0x0C, 0x80, 0x0D, 0x00, 0x0E, 0x84, 0x0F, 0x01, 0x10, 0x10, 0x11, 0x02, 0x14, +- 0x40, 0x20, 0x32, 0x21, 0x32, 0x22, 0x04, 0x23, 0x01, 0x24, 0x0F, 0x25, 0x00, 0x26, 0x00, 0x27, +- 0x00, 0x28, 0x00, 0x29, 0x00, 0x2A, 0x01, 0x2B, 0x06, 0x2C, 0x00, 0x38, 0x00, 0x39, 0xD6, 0x3A, +- 0x00, 0x3B, 0x00, 0x3C, 0x14, 0x3D, 0x7F, 0x3E, 0x00, 0x3F, 0x68, 0x40, 0x75, 0x41, 0x07, 0x42, +- 0x07, 0x43, 0x00, 0x45, 0x3B, 0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x0F, 0x4D, 0x02, 0x75, 0x00, 0x76, +- 0x80, 0x00, 0x08, 0x01, 0x09, 0x01, 0x09, 0x01, 0x0A, 0x01, 0x0A, 0x01, 0x0B, 0x01, 0x0B, 0x01, +- 0x0C, 0x01, 0x0C, 0x01, 0x0D, 0x01, 0x0D, 0x01, 0x0E, 0x01, 0x0E, 0x01, 0x0F, 0x01, 0x0F, 0x01, +- 0x10, 0x01, 0x10, 0x01, 0x11, 0x01, 0x11, 0x01, 0x12, 0x01, 0x12, 0x01, 0x13, 0x01, 0x13, 0x01, +- 0x14, 0x01, 0x14, 0x01, 0x15, 0x01, 0x15, 0x01, 0x16, 0x01, 0x16, 0x01, 0x17, 0x01, 0x17, 0x01, +- 0x18, 0x01, 0x18, 0x01, 0x19, 0x01, 0x19, 0x01, 0x4D, 0x01, 0x4D, 0x01, 0x4E, 0x01, 0x4E, 0x01, +- 0x4F, 0x01, 0x4F, 0x01, 0x50, 0x01, 0x50, 0x01, 0x51, 0x01, 0x51, 0x01, 0x52, 0x01, 0x52, 0x01, +- 0x53, 0x01, 0x53, 0x01, 0x54, 0x01, 0x54, 0x01, 0x65, 0x01, 0x65, 0x01, 0x66, 0x01, 0x66, 0x01, +- 0x67, 0x01, 0x67, 0x01, 0x68, 0x01, 0x68, 0x01, 0x69, 0x01, 0x69, 0x01, 0x6A, 0x01, 0x6A, 0x01, +- 0x6B, 0x01, 0x6B, 0x01, 0x6C, 0x01, 0x6C, 0x01, 0x6D, 0x01, 0x6D, 0x01, 0x6E, 0x01, 0x6E, 0x01, +- 0x6F, 0x01, 0x6F, 0x01, 0x70, 0x01, 0x70, 0x01, 0x71, 0x01, 0x71, 0x01, 0x72, 0x01, 0x72, 0x01, +- 0x73, 0x01, 0x73, 0x01, 0x74, 0x01, 0x74, 0x01, 0x75, 0x01, 0x75, 0x01, 0x76, 0x01, 0x76, 0x01, +- 0x77, 0x01, 0x77, 0x01, 0x78, 0x01, 0x78, 0x01, 0x79, 0x01, 0x79, 0x01, 0x7A, 0x01, 0x7A, 0x01, +- 0x7B, 0x01, 0x7B, 0x01, 0x7C, 0x01, 0x7C, 0x01, 0x7D, 0x01, 0x7D, 0x01, 0x7E, 0x01, 0x7E, 0x01, +- 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, +- 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, +- 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01, +- 0x7F, 0x01, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, +- 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x12, 0x80, 0x13, +- 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, +- 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x80, 0x13, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, +- 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, +- 0x51, 0x44, 0x51, 0x44, 0x51, 0x44, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, +- 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x23, 0x46, 0x23, 0x46, +- 0x23, 0x46, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, +- 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1D, 0x47, 0x9A, 0x48, +- 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, +- 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0x33, 0x48, 0x78, 0x49, 0x78, 0x49, 0x79, 0x49, +- 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, 0x7A, 0x49, 0x7A, 0x49, 0x7A, 0x49, 0x7A, 0x49, 0x7B, 0x49, +- 0x7B, 0x49, 0x7B, 0x49, 0x7C, 0x49, 0x32, 0x00, 0x46, 0x00, 0x5A, 0x00, 0x6E, 0x00, 0x82, 0x00, +- 0x96, 0x00, 0xAA, 0x00, 0xBE, 0x00, 0xD2, 0x00, 0xE6, 0x00, 0xFA, 0x00, 0x0E, 0x01, 0x22, 0x01, +- 0x52, 0x01, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, +- 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x03, 0x00, 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, +- 0x64, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, +- 0x00, 0x00, 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, +- 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, +- 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x03, 0x00, 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, +- 0x64, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, +- 0x00, 0x00, 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, +- 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x46, 0x69, 0x72, 0x73, 0x74, 0x20, 0x57, 0x61, 0x76, 0x65, 0x4C, 0x41, 0x4E, 0x20, 0x49, 0x49, +- 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x19, 0x00, 0x02, 0x01, 0x82, 0x84, 0x8B, 0x96, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x85, 0x00, 0x01, +- 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x01, +- 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x53, +- 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x53, 0x65, 0x74, 0x20, 0x49, 0x64, 0x65, 0x6E, 0x74, +- 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0xDD, 0x00, 0x50, 0xF2, 0x01, +- 0x01, 0x00, 0x00, 0x50, 0xF2, 0x05, 0x02, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x50, 0xF2, 0x04, +- 0x02, 0x00, 0x00, 0x50, 0xF2, 0x00, 0x00, 0x50, 0xF2, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x15, 0x00, 0x14, 0x00, 0x15, 0x00, 0x36, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, +- 0x11, 0x00, 0x36, 0x00, 0x01, 0x00, 0x04, 0x00, 0x7A, 0x2D, 0x28, 0x2D, 0x0C, 0x2F, 0x10, 0x2F, +- 0x14, 0x2F, 0xA0, 0x2D, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x29, 0x28, 0x2D, +- 0xFF, 0xFF, 0x00, 0x00, 0x7A, 0x2D, 0x28, 0x2D, 0x0C, 0x2F, 0x10, 0x2F, 0x14, 0x2F, 0xA0, 0x2D, +- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x2D, 0x28, 0x2D, 0xFF, 0xFF, 0xE6, 0x2D, +- 0x34, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00, 0x02, 0x06, 0x00, 0x00, 0x06, 0x07, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +- 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- +-}; /* fw_image_2_data */ +- +-static const hcf_8 fw_image_3_data[] = { +- 0x00, 0xE1, 0x30, 0x40, 0x02, 0x36, 0xA1, 0xFF, 0x83, 0xFF, 0x8D, 0xFF, 0x5C, 0x44, 0x5C, 0x43, +- 0x5C, 0x42, 0x5C, 0x41, 0x5C, 0x40, 0xAC, 0xFF, 0xAD, 0xFF, 0xE7, 0xE1, 0xAD, 0x60, 0x08, 0x78, +- 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x03, 0x02, 0x28, 0xE2, 0x40, 0xFF, 0xA1, 0xFF, +- 0x84, 0xFF, 0xBB, 0x60, 0x18, 0x64, 0x40, 0x42, 0xB0, 0x60, 0x97, 0x64, 0x40, 0x40, 0xBD, 0xF3, +- 0x80, 0xFB, 0x0F, 0x60, 0x9A, 0x63, 0xCA, 0xF3, 0xBD, 0xDB, 0x00, 0x60, 0x9A, 0x64, 0xBD, 0xDB, +- 0x02, 0x64, 0xBD, 0xDB, 0x04, 0x64, 0xA3, 0xDB, 0x5C, 0x49, 0x0A, 0x64, 0x40, 0x4B, 0x5C, 0x5C, +- 0x01, 0x60, 0x39, 0xE2, 0x04, 0x60, 0x00, 0x7A, 0x89, 0xFF, 0x03, 0x60, 0xFF, 0x73, 0x88, 0xFF, +- 0xB0, 0x60, 0x97, 0x78, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x06, 0x02, 0x40, 0xFF, +- 0x42, 0xFF, 0x43, 0xFF, 0x44, 0xFF, 0x45, 0xFF, 0xA1, 0xFF, 0x88, 0xFF, 0x85, 0xFF, 0x21, 0xE1, +- 0x5C, 0x40, 0xBB, 0x60, 0x20, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, +- 0x01, 0x02, 0xA1, 0xFF, 0x86, 0xFF, 0x88, 0xFF, 0x5C, 0x46, 0x5C, 0x49, 0x5C, 0x40, 0xE7, 0x60, +- 0x58, 0x4F, 0x31, 0x78, 0xFF, 0xFF, 0xC7, 0x60, 0x58, 0x4F, 0xF6, 0x78, 0xFF, 0xFF, 0xCA, 0x60, +- 0x58, 0x4F, 0x83, 0x78, 0xFF, 0xFF, 0xDD, 0x60, 0x58, 0x4F, 0x3D, 0x78, 0xFF, 0xFF, 0x1B, 0x60, +- 0x58, 0x4F, 0x37, 0x78, 0xFF, 0xFF, 0xEC, 0x60, 0x58, 0x4F, 0x75, 0x78, 0xFF, 0xFF, 0xE0, 0x60, +- 0x58, 0x4F, 0x1B, 0x78, 0xFF, 0xFF, 0xE4, 0x60, 0x58, 0x4F, 0xDC, 0x78, 0xFF, 0xFF, 0xF3, 0x60, +- 0x58, 0x4F, 0xEB, 0x78, 0xFF, 0xFF, 0x13, 0xE1, 0xA3, 0xFF, 0xBF, 0x60, 0xE7, 0x78, 0xFF, 0xFF, +- 0x03, 0xE1, 0xA3, 0xFF, 0xFE, 0xFC, 0xFF, 0xFC, 0x23, 0x60, 0xF4, 0x63, 0x17, 0xFD, 0xAE, 0xFF, +- 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x26, 0x1A, 0x00, +- 0x80, 0x3A, 0x15, 0x00, 0x81, 0xF1, 0x32, 0xF2, 0x33, 0xF2, 0xD0, 0x80, 0x82, 0xF1, 0x0F, 0x02, +- 0xD0, 0x80, 0x34, 0xF2, 0x83, 0xF1, 0x0B, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x08, 0x02, 0xDF, 0x60, +- 0x58, 0x4F, 0x28, 0x78, 0xFF, 0xFF, 0x20, 0x60, 0x58, 0x4F, 0xBF, 0x78, 0xFF, 0xFF, 0x19, 0x60, +- 0xE8, 0x78, 0xFF, 0xFF, 0x00, 0xF4, 0xAA, 0x60, 0xAA, 0x65, 0x09, 0xF2, 0x5A, 0xD0, 0xD4, 0x80, +- 0x03, 0x64, 0x12, 0x02, 0xD0, 0x80, 0x1D, 0x60, 0x60, 0x65, 0x0E, 0x02, 0x5A, 0xD2, 0xFF, 0xFF, +- 0xD4, 0x80, 0x01, 0x60, 0x00, 0x65, 0x08, 0x02, 0x5A, 0xD2, 0xFF, 0xFF, 0xD4, 0x80, 0xFF, 0xFF, +- 0x03, 0x02, 0x19, 0x60, 0xE8, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0xD6, 0x65, 0xA5, 0xD1, 0x5A, 0xD1, +- 0x44, 0x48, 0x5A, 0xD1, 0x44, 0x4A, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x44, 0x4C, 0xD8, 0x83, +- 0x70, 0x61, 0x68, 0x65, 0xD7, 0x80, 0xFF, 0xFF, 0x07, 0x0E, 0x08, 0xF2, 0x08, 0x00, 0x68, 0x65, +- 0xD7, 0x80, 0xFF, 0xFF, 0x01, 0x0E, 0x03, 0x00, 0x19, 0x60, 0xFE, 0x78, 0xFF, 0xFF, 0x58, 0x4F, +- 0x79, 0x00, 0x9C, 0x80, 0x01, 0x65, 0x02, 0x02, 0x00, 0x65, 0x02, 0x00, 0xFF, 0x3B, 0xF7, 0x01, +- 0x58, 0x4F, 0x70, 0x00, 0x9C, 0x80, 0x45, 0x42, 0xEA, 0x02, 0x58, 0x4F, 0x6B, 0x00, 0x9C, 0x80, +- 0xFF, 0xFF, 0xE5, 0x02, 0x58, 0x4F, 0x66, 0x00, 0x9C, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0x00, 0x65, +- 0x45, 0x42, 0xF8, 0x01, 0xFF, 0x3A, 0x29, 0x00, 0x60, 0x47, 0xFF, 0xB5, 0x28, 0x44, 0xFF, 0xB4, +- 0x94, 0x80, 0xFF, 0xFF, 0xD4, 0x02, 0x60, 0x45, 0x28, 0x47, 0x2A, 0x5F, 0x40, 0x48, 0x2A, 0x47, +- 0x2C, 0x5F, 0x40, 0x4A, 0x2C, 0x47, 0x65, 0x5F, 0x40, 0x4C, 0x10, 0x64, 0x40, 0x42, 0x28, 0x45, +- 0x05, 0x00, 0x58, 0x4F, 0x47, 0x00, 0x94, 0x80, 0x28, 0x45, 0x26, 0x02, 0x58, 0x4F, 0x42, 0x00, +- 0x94, 0x80, 0x2A, 0x45, 0x21, 0x02, 0x58, 0x4F, 0x3D, 0x00, 0x94, 0x80, 0xFF, 0xFF, 0x1C, 0x02, +- 0x22, 0x44, 0x4C, 0x82, 0x2C, 0x45, 0x31, 0x03, 0xEC, 0x01, 0x10, 0x65, 0x45, 0x42, 0x28, 0x45, +- 0x94, 0x80, 0x2A, 0x45, 0x21, 0x02, 0x58, 0x4F, 0x2D, 0x00, 0x94, 0x80, 0x2C, 0x45, 0x1C, 0x02, +- 0x58, 0x4F, 0x28, 0x00, 0x94, 0x80, 0xFF, 0xFF, 0x17, 0x02, 0x22, 0x44, 0x4C, 0x82, 0x28, 0x45, +- 0x1C, 0x03, 0x58, 0x4F, 0x1F, 0x00, 0xEC, 0x01, 0x40, 0x4B, 0x28, 0x47, 0x40, 0x48, 0x2A, 0x47, +- 0x40, 0x4A, 0x2C, 0x47, 0x60, 0x45, 0x2A, 0x5E, 0x40, 0x4C, 0x2A, 0x44, 0x28, 0x5E, 0x40, 0x4A, +- 0x28, 0x44, 0x65, 0x5E, 0x40, 0x48, 0x2B, 0x44, 0x68, 0x65, 0xD7, 0x80, 0xFF, 0xFF, 0x17, 0x0E, +- 0x90, 0x01, 0x26, 0x46, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0xB9, 0xFF, 0x26, 0x46, 0xC5, 0x60, +- 0x5B, 0x78, 0xFF, 0xFF, 0xC9, 0x81, 0xCB, 0x83, 0x07, 0x1C, 0x01, 0x1D, 0x08, 0x00, 0x00, 0xF4, +- 0x01, 0xF2, 0xFF, 0xFF, 0xFF, 0xB4, 0xD8, 0x81, 0x5A, 0xD2, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, +- 0xC5, 0x60, 0x58, 0x4F, 0x78, 0x78, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x63, 0x00, 0xF4, 0x84, 0x65, +- 0x78, 0x61, 0xA5, 0xD0, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x64, 0x44, +- 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, +- 0xF0, 0x02, 0x1C, 0x60, 0xAC, 0x63, 0x29, 0x60, 0xEC, 0x64, 0x08, 0x65, 0xC4, 0x81, 0x61, 0x44, +- 0xA3, 0xDB, 0x1C, 0x60, 0xAA, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x29, 0x60, 0xEC, 0x61, 0xA1, 0xD3, +- 0xFF, 0xFF, 0x60, 0x43, 0x1C, 0x60, 0xB0, 0x61, 0xA1, 0xDD, 0x1C, 0x60, 0xB0, 0x61, 0xA1, 0xD3, +- 0xFF, 0xFF, 0x60, 0x45, 0x1C, 0x60, 0xAA, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0xD4, 0x80, 0xFF, 0xFF, +- 0x01, 0x03, 0x03, 0x00, 0x1A, 0x60, 0xD6, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xA8, 0x61, 0x01, 0x64, +- 0xA1, 0xDB, 0x02, 0x60, 0x00, 0x61, 0x41, 0x4C, 0x03, 0x60, 0x00, 0x61, 0x41, 0x4A, 0x1C, 0x60, +- 0xAC, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x40, 0x48, 0x1C, 0x60, 0xB2, 0x63, 0x28, 0x41, 0x06, 0x65, +- 0xD5, 0x81, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x01, 0xA4, 0x60, 0x41, 0xA3, 0xDB, +- 0x2A, 0x43, 0x28, 0x45, 0xA5, 0xD1, 0xDA, 0x85, 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, +- 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0xF4, 0x02, 0x28, 0x41, 0x1C, 0x60, +- 0xB2, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x45, 0x45, 0x8B, 0x1C, 0x60, 0xAE, 0x61, 0x2B, 0xD3, +- 0xA1, 0xDB, 0x2C, 0x41, 0x28, 0x42, 0x4A, 0xD3, 0xFF, 0xFF, 0x60, 0x45, 0x45, 0x8C, 0x00, 0x7F, +- 0x01, 0x7E, 0x40, 0x48, 0x1C, 0x60, 0xB2, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x45, 0x00, 0x64, +- 0xD4, 0x80, 0xFF, 0xFF, 0x43, 0x03, 0x65, 0x44, 0xFF, 0xA4, 0xA1, 0xDB, 0x1C, 0x60, 0xAE, 0x61, +- 0xA1, 0xD3, 0x28, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x2C, 0xD3, 0x2A, 0xD3, 0x60, 0x45, +- 0xD4, 0x80, 0xFF, 0xFF, 0x01, 0x03, 0x14, 0x00, 0x28, 0x44, 0xE0, 0x84, 0xFF, 0xFF, 0x02, 0x24, +- 0x01, 0x00, 0x08, 0x00, 0x2B, 0x44, 0x58, 0x8B, 0x1C, 0x60, 0xAE, 0x63, 0x2B, 0xD3, 0xA3, 0xDB, +- 0x00, 0x7F, 0x01, 0x7E, 0x40, 0x48, 0x2A, 0x44, 0x58, 0x8A, 0x2C, 0x44, 0x58, 0x8C, 0xD2, 0x01, +- 0x1C, 0x60, 0xA8, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x1C, 0x60, 0xAC, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, +- 0x60, 0x45, 0xFA, 0xA4, 0x60, 0x41, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0xC5, 0x81, 0x06, 0xA1, +- 0x41, 0x48, 0x65, 0x41, 0xFC, 0xA1, 0xA1, 0xD3, 0x28, 0x41, 0x60, 0x40, 0x01, 0x26, 0x01, 0xA4, +- 0x60, 0x45, 0xC5, 0x81, 0x61, 0x43, 0x1C, 0x60, 0xAC, 0x61, 0xA1, 0xDD, 0x1C, 0x60, 0xA8, 0x61, +- 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x0D, 0x00, 0x1C, 0x60, 0xAA, 0x61, 0xA1, 0xD3, +- 0xFF, 0xFF, 0x01, 0xA4, 0xA1, 0xDB, 0xFF, 0xFF, 0x1A, 0x60, 0x2C, 0x78, 0xFF, 0xFF, 0x19, 0x60, +- 0xE8, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0xEC, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x01, 0x60, 0xBA, 0x61, +- 0x1F, 0x60, 0x08, 0x63, 0xA1, 0xD3, 0x04, 0xA1, 0x20, 0x7F, 0xBD, 0xDB, 0x32, 0x7E, 0x21, 0x7F, +- 0xBD, 0xDB, 0xA1, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x10, 0x00, 0x01, 0x60, 0xBA, 0x61, +- 0x1F, 0x60, 0x08, 0x63, 0xA1, 0xD3, 0x00, 0x66, 0x20, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, +- 0x21, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, 0xD8, 0x62, +- 0xA2, 0xD1, 0x9F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, +- 0xDA, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x1A, 0x60, 0xFD, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x9A, 0x62, 0x1F, 0x60, 0x06, 0x64, 0xA2, 0xDB, 0x20, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xDA, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, +- 0x1B, 0x60, 0x25, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, +- 0xA2, 0xD1, 0x9F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, +- 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, +- 0x10, 0x60, 0x1E, 0x62, 0x1E, 0x60, 0xF4, 0x64, 0xA2, 0xDB, 0x1A, 0x60, 0x8A, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x06, 0xA2, 0x10, 0x60, 0x40, 0x64, 0xA2, 0xDB, 0x06, 0x64, 0x5A, 0xDB, 0x5A, 0xDB, +- 0x1A, 0x60, 0x96, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x06, 0xA2, 0x10, 0x60, 0x44, 0x64, 0xA2, 0xDB, +- 0x06, 0x64, 0x5A, 0xDB, 0x5A, 0xDB, 0x1A, 0x60, 0xA2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x06, 0xA2, +- 0x10, 0x60, 0x48, 0x64, 0xA2, 0xDB, 0x06, 0x64, 0x5A, 0xDB, 0x5A, 0xDB, 0xC0, 0xF1, 0x1A, 0x60, +- 0xA6, 0x62, 0xA2, 0xD9, 0x10, 0x60, 0x3E, 0x62, 0x20, 0x60, 0x99, 0x64, 0xA2, 0xDB, 0x10, 0x60, +- 0x42, 0x62, 0x20, 0x60, 0xA3, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x46, 0x62, 0x20, 0x60, 0xAD, 0x64, +- 0xA2, 0xDB, 0x00, 0x60, 0x70, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0x63, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0xA9, 0xF3, 0x07, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, +- 0x0F, 0x60, 0xDA, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0x1B, 0x60, 0x8A, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x03, 0x64, +- 0x6A, 0xFB, 0x0F, 0x4E, 0xE0, 0x60, 0x58, 0x4F, 0x8E, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x00, 0x64, +- 0x6C, 0xFB, 0x63, 0xF5, 0xEB, 0xF3, 0x2F, 0xFA, 0xEC, 0xF3, 0x30, 0xFA, 0xED, 0xF3, 0x31, 0xFA, +- 0x81, 0xF3, 0x2C, 0xFA, 0x32, 0xFA, 0x82, 0xF3, 0x2D, 0xFA, 0x33, 0xFA, 0x83, 0xF3, 0x2E, 0xFA, +- 0x34, 0xFA, 0xBC, 0xF3, 0x19, 0xFA, 0x06, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0x20, 0x60, 0x58, 0x4E, +- 0x71, 0x78, 0xFF, 0xFF, 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, +- 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xD8, 0x62, +- 0xA2, 0xD1, 0xFF, 0x60, 0x8F, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xC1, 0xF1, 0x1A, 0x60, 0x9A, 0x62, +- 0xA2, 0xD9, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x6C, 0xFB, 0x0F, 0x60, 0xDA, 0x62, 0x00, 0x60, 0x74, 0x64, +- 0xA2, 0xDB, 0x1B, 0x60, 0xDE, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, +- 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x1E, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xE0, 0x01, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x11, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, 0x50, 0x27, 0xD6, 0x01, 0xAF, 0xF3, 0xFF, 0xFF, +- 0xFE, 0xA0, 0xFF, 0xFF, 0xD1, 0x06, 0x6C, 0xF3, 0xFF, 0xFF, 0xF6, 0xA0, 0xDC, 0x84, 0x01, 0x05, +- 0xA2, 0xDB, 0xCA, 0x01, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xCE, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x00, 0x00, 0xE0, 0xF3, 0x29, 0x45, 0xD4, 0x80, 0x6C, 0xF3, 0x03, 0x04, 0x1C, 0x60, +- 0x55, 0x78, 0xFF, 0xFF, 0xF6, 0xA0, 0xFF, 0xFF, 0x03, 0x04, 0x1C, 0x60, 0x55, 0x78, 0xFF, 0xFF, +- 0x0F, 0x60, 0xDA, 0x62, 0x00, 0x60, 0x64, 0x64, 0xA2, 0xDB, 0x1C, 0x60, 0x2A, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1E, 0x60, 0xF4, 0x78, 0xFF, 0xFF, +- 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xD2, 0x01, +- 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xE4, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, +- 0x50, 0x27, 0xDF, 0x01, 0xAF, 0xF3, 0xFF, 0xFF, 0xFE, 0xA0, 0xFF, 0xFF, 0xC3, 0x06, 0x6C, 0xF3, +- 0xFF, 0xFF, 0xF6, 0xA0, 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0xBC, 0x01, 0x0F, 0x60, 0xD8, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x20, 0x40, 0x40, 0x2B, 0x0B, 0x00, 0x0F, 0x60, 0xDA, 0x62, 0x80, 0x60, +- 0x00, 0x64, 0xA2, 0xDB, 0x1C, 0x60, 0x55, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x1C, 0x60, 0x92, 0x65, 0x01, 0x64, 0xA5, 0xDB, 0xC2, 0xF1, 0x1A, 0x60, 0x9A, 0x62, 0xA2, 0xD9, +- 0x0C, 0x64, 0x53, 0xFB, 0x1C, 0x60, 0x77, 0x64, 0x6B, 0xFB, 0x1F, 0x60, 0x72, 0x78, 0xFF, 0xFF, +- 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0xA2, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0xDF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, +- 0x88, 0xF1, 0x19, 0x60, 0x86, 0x63, 0xD3, 0x80, 0x68, 0xFD, 0x5F, 0x03, 0x68, 0xF3, 0xE2, 0xF1, +- 0x60, 0x43, 0x29, 0x44, 0xA3, 0xD3, 0xC0, 0x85, 0xD4, 0x80, 0x5B, 0xD3, 0x56, 0x06, 0x60, 0x43, +- 0x08, 0xA3, 0xBE, 0xD3, 0x83, 0xF1, 0xA3, 0xD3, 0xD0, 0x80, 0x82, 0xF1, 0x05, 0x02, 0xBF, 0xD3, +- 0xD0, 0x80, 0x81, 0xF1, 0x01, 0x02, 0xD0, 0x80, 0xF8, 0xA3, 0x2B, 0x02, 0x1C, 0x60, 0xAB, 0x64, +- 0x6B, 0xFB, 0x1F, 0x60, 0x29, 0x78, 0xFF, 0xFF, 0x01, 0xB0, 0x84, 0xF3, 0x3E, 0x03, 0x63, 0xF5, +- 0x48, 0x7E, 0x2A, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x0F, 0x60, 0xDA, 0x62, +- 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, 0x1C, 0x60, 0xC8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0xFE, 0x64, 0xA0, 0x84, 0xA2, 0xDB, +- 0x1C, 0x00, 0x2D, 0x60, 0x7A, 0x65, 0xA5, 0xD3, 0x65, 0x41, 0x10, 0xA3, 0x01, 0xA4, 0xFE, 0xB4, +- 0xC4, 0x85, 0xFE, 0xA1, 0xBD, 0xD3, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0xD5, 0x80, 0x05, 0x02, +- 0x01, 0x03, 0xF8, 0x01, 0x1E, 0x60, 0xE8, 0x78, 0xFF, 0xFF, 0x68, 0xF3, 0x88, 0xF1, 0x04, 0xA4, +- 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x68, 0xFB, 0xA1, 0x01, 0xE0, 0xF3, 0x29, 0x45, 0xD4, 0x80, +- 0xFF, 0xFF, 0x0C, 0x07, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x03, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1B, 0x60, 0xB1, 0x78, 0xFF, 0xFF, 0xE1, 0xF3, 0x29, 0x45, +- 0xD4, 0x80, 0xFF, 0xFF, 0x17, 0x06, 0x04, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, +- 0x05, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, 0xF2, 0xFB, 0x24, 0x60, 0xAA, 0x62, +- 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1D, 0x60, +- 0x6D, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xDA, 0x62, 0x00, 0x60, 0x74, 0x64, 0xA2, 0xDB, 0x1D, 0x60, +- 0x24, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, +- 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1E, 0x60, +- 0xF4, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x1C, 0x60, 0x87, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x17, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, 0x50, 0x27, 0xA7, 0x01, 0xAF, 0xF3, 0x6C, 0xF3, +- 0xFE, 0xA0, 0xF6, 0xA0, 0x0A, 0x06, 0x03, 0x04, 0x00, 0x64, 0x55, 0xFB, 0x40, 0x49, 0x6C, 0xF3, +- 0xFF, 0xFF, 0xF6, 0xA0, 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0x1C, 0x60, 0x87, 0x78, 0xFF, 0xFF, +- 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xC6, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, +- 0xAA, 0x62, 0x1A, 0x60, 0xA2, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x1C, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xEC, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x20, 0x40, 0x40, 0x2B, 0x0B, 0x00, 0x0F, 0x60, 0xDA, 0x62, 0x80, 0x60, +- 0x00, 0x64, 0xA2, 0xDB, 0x1D, 0x60, 0x6D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x1C, 0x60, 0x92, 0x65, 0x00, 0x64, 0xA5, 0xDB, 0xC3, 0xF1, 0x1A, 0x60, 0x9A, 0x62, 0xA2, 0xD9, +- 0x1F, 0x60, 0x80, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0x08, 0xB4, 0x01, 0xBC, 0x29, 0x02, 0xA2, 0xDB, +- 0x0F, 0x60, 0xD8, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x4E, 0xE4, 0x60, 0x58, 0x4F, 0xFB, 0x78, +- 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x60, 0xDA, 0x62, 0x10, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x1D, 0x60, +- 0xA4, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1F, 0x60, 0x80, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0x60, 0x40, 0x0C, 0x26, 0x0C, 0x00, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x96, 0x64, +- 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1E, 0x60, 0x97, 0x78, 0xFF, 0xFF, +- 0x01, 0x64, 0x31, 0x60, 0x2A, 0x62, 0xA2, 0xDB, 0x0D, 0x64, 0x53, 0xFB, 0x1D, 0x60, 0xC3, 0x64, +- 0x6B, 0xFB, 0x1F, 0x60, 0x72, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0xA2, 0x64, +- 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, +- 0xFF, 0x60, 0xDF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x88, 0xF1, 0x19, 0x60, 0x86, 0x63, 0xD3, 0x80, +- 0x68, 0xFD, 0x01, 0x02, 0x43, 0x00, 0x68, 0xF3, 0x29, 0x41, 0xA0, 0xD1, 0x58, 0xD3, 0xD1, 0x80, +- 0x64, 0x45, 0x60, 0x43, 0x0F, 0x05, 0x08, 0xA3, 0xBE, 0xD3, 0x83, 0xF1, 0xA3, 0xD3, 0xD0, 0x80, +- 0x82, 0xF1, 0x05, 0x02, 0xBF, 0xD3, 0xD0, 0x80, 0x81, 0xF1, 0x01, 0x02, 0xD0, 0x80, 0xF8, 0xA3, +- 0x07, 0x02, 0x45, 0x49, 0x1E, 0x60, 0x2A, 0x64, 0x6B, 0xFB, 0x1F, 0x60, 0x29, 0x78, 0xFF, 0xFF, +- 0x2D, 0x60, 0x7A, 0x65, 0xA5, 0xD3, 0x65, 0x41, 0x10, 0xA3, 0x01, 0xA4, 0xFE, 0xB4, 0xC4, 0x85, +- 0xFE, 0xA1, 0xBD, 0xD3, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0xD5, 0x80, 0x0F, 0x02, 0xF9, 0x02, +- 0x05, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0x04, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, +- 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0x1E, 0x60, 0xE8, 0x78, 0xFF, 0xFF, 0x68, 0xF3, 0x88, 0xF1, +- 0x04, 0xA4, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x68, 0xFB, 0xBD, 0x01, 0xE1, 0xF3, 0x29, 0x45, +- 0xD4, 0x80, 0xFF, 0xFF, 0x75, 0x05, 0x1E, 0x60, 0x2A, 0x63, 0x6B, 0xFD, 0x1A, 0x60, 0x4C, 0x63, +- 0x1F, 0x60, 0x29, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, +- 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x05, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, +- 0xFF, 0xFF, 0x1F, 0x60, 0x52, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x04, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, +- 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0x84, 0xF3, 0x63, 0xF5, 0x48, 0x7E, 0x2A, 0xFA, 0x02, 0x60, +- 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, +- 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x0F, 0x60, +- 0xDA, 0x62, 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, 0x1E, 0x60, 0x61, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0xFE, 0x64, 0xA0, 0x84, +- 0xA2, 0xDB, 0x1A, 0x60, 0x9A, 0x62, 0x00, 0x60, 0x32, 0x64, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, +- 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, +- 0xDA, 0x62, 0x00, 0x60, 0x10, 0x64, 0xA2, 0xDB, 0x1E, 0x60, 0x81, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, +- 0xA2, 0xDB, 0xFD, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, +- 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x1B, 0x60, 0xB1, 0x78, 0xFF, 0xFF, +- 0x0F, 0x60, 0xDA, 0x62, 0x00, 0x60, 0x74, 0x64, 0xA2, 0xDB, 0x1E, 0x60, 0xA2, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1E, 0x60, 0xF4, 0x78, 0xFF, 0xFF, +- 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1D, 0x60, +- 0xD3, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x17, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x20, 0x40, 0x50, 0x27, 0xDD, 0x01, 0xAF, 0xF3, 0x6C, 0xF3, 0xFE, 0xA0, 0xF6, 0xA0, +- 0x0A, 0x06, 0x03, 0x04, 0x00, 0x64, 0x55, 0xFB, 0x40, 0x49, 0x6C, 0xF3, 0xFF, 0xFF, 0xF6, 0xA0, +- 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0x1D, 0x60, 0xD3, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0xC6, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, +- 0xA2, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1D, 0x60, 0x6D, 0x78, +- 0xFF, 0xFF, 0x08, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, +- 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, +- 0x8A, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x24, 0x60, 0xAA, 0x62, +- 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x24, 0x60, +- 0xAA, 0x62, 0x1A, 0x60, 0xA2, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x0F, 0x60, 0xD8, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x00, 0x64, 0x6A, 0xFB, 0x0F, 0x60, +- 0xD0, 0x62, 0xA2, 0xD1, 0x02, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, +- 0xDA, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0x1B, 0x60, 0x8A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0xA3, 0xD3, 0x7F, 0xF1, 0x7E, 0xFB, 0xD0, 0x80, 0x00, 0x64, 0x40, 0x03, +- 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xBF, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xDE, 0xFE, +- 0x0B, 0x04, 0x0F, 0x60, 0xDA, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x1F, 0x60, 0x2F, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xDF, 0x60, +- 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x7E, 0xF1, 0x7F, 0xF9, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, +- 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xDA, 0x62, 0x20, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0x1F, 0x60, 0x5E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, +- 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xDF, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x0F, 0x60, +- 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x64, +- 0x6B, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x0F, 0x60, +- 0xD8, 0x62, 0xA2, 0xD1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, 0x51, 0x23, +- 0x0B, 0x00, 0x0F, 0x60, 0xDA, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x1F, 0x60, 0x76, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x7F, 0x60, +- 0xFF, 0x61, 0xA1, 0x84, 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x40, 0x60, 0x00, 0x65, +- 0x20, 0x44, 0x34, 0x80, 0x02, 0x64, 0x8C, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x8C, 0xF3, 0x00, 0x65, +- 0xD4, 0x80, 0xFF, 0xFF, 0x12, 0x03, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x7F, 0x60, 0xFF, 0x64, +- 0xA0, 0x84, 0xA2, 0xDB, 0x0F, 0x60, 0xDA, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x1F, 0x60, +- 0x99, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2D, 0x60, 0x7A, 0x64, 0x54, 0xFB, +- 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xEF, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x1A, 0x60, +- 0x58, 0x4E, 0xDC, 0x78, 0xFF, 0xFF, 0x0F, 0x4E, 0xEC, 0x60, 0x58, 0x4F, 0xB9, 0x78, 0xFF, 0xFF, +- 0x0E, 0x4F, 0x0F, 0x60, 0xDA, 0x62, 0x10, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0x1F, 0x60, 0xD3, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1A, 0x60, 0x58, 0x4E, 0xED, 0x78, 0xFF, 0xFF, +- 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0xEF, 0x60, 0xEF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, +- 0x01, 0x64, 0x8C, 0xFB, 0xBF, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x01, 0x60, 0x14, 0x62, +- 0xA2, 0xD1, 0x12, 0x60, 0x46, 0x63, 0xC3, 0x85, 0xC6, 0xA3, 0x3A, 0xA3, 0xD7, 0x80, 0xAF, 0xF3, +- 0x09, 0x04, 0xFE, 0xA0, 0x6C, 0xF3, 0x3A, 0x06, 0xF6, 0xA0, 0x00, 0x64, 0x37, 0x04, 0x55, 0xFB, +- 0x40, 0x49, 0x34, 0x00, 0x08, 0xA3, 0xBE, 0xD3, 0x83, 0xF1, 0xA3, 0xD3, 0xD0, 0x80, 0x82, 0xF1, +- 0x05, 0x02, 0xBF, 0xD3, 0xD0, 0x80, 0x81, 0xF1, 0x01, 0x02, 0xD0, 0x80, 0xF8, 0xA3, 0xE5, 0x02, +- 0xBE, 0xD3, 0x5A, 0xD1, 0x60, 0x47, 0x40, 0x4A, 0x64, 0x47, 0x40, 0x48, 0x20, 0x60, 0x58, 0x4E, +- 0x45, 0x78, 0xFF, 0xFF, 0x0A, 0x48, 0x20, 0x60, 0x58, 0x4E, 0x55, 0x78, 0xFF, 0xFF, 0x20, 0x60, +- 0x58, 0x4E, 0x71, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0x2E, 0x65, 0x6C, 0xF3, 0xA5, 0xD3, 0xF6, 0xA0, +- 0x40, 0xBC, 0x06, 0x04, 0xA5, 0xDB, 0x6A, 0xF1, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0x6A, 0xFB, +- 0x6C, 0xF3, 0xFF, 0xFF, 0x00, 0xB8, 0xCC, 0x84, 0x01, 0x03, 0xA2, 0xDB, 0xFD, 0x60, 0xFF, 0x65, +- 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x6B, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0xF1, 0x28, 0x44, +- 0xD0, 0x84, 0x03, 0xA4, 0x03, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0x04, 0x00, 0xFA, 0xA4, 0xE8, 0x84, +- 0xE8, 0x87, 0xC0, 0xBF, 0xC0, 0x84, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0x56, 0xF1, 0x28, 0x44, +- 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, +- 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, +- 0xC0, 0x84, 0x5C, 0xF1, 0x56, 0xFB, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x05, 0x64, 0x44, 0x52, 0xFB, +- 0x2E, 0x58, 0xFF, 0xFF, 0x52, 0xF1, 0x00, 0x65, 0x20, 0x40, 0x20, 0x2A, 0x06, 0x00, 0x5C, 0xF3, +- 0xFF, 0xFF, 0xD0, 0x80, 0x64, 0x45, 0x01, 0x06, 0x60, 0x45, 0x2F, 0x67, 0xD4, 0x80, 0xFF, 0xFF, +- 0x01, 0x06, 0x60, 0x45, 0x55, 0xF1, 0x8B, 0x67, 0xD0, 0x80, 0x60, 0x41, 0x02, 0x24, 0x64, 0x41, +- 0xD5, 0x84, 0x80, 0x65, 0xC4, 0x87, 0x01, 0x05, 0x00, 0x64, 0xFF, 0xB4, 0x40, 0x49, 0x20, 0x40, +- 0x20, 0x2A, 0x06, 0x00, 0x2E, 0x43, 0xF3, 0x60, 0x58, 0x4E, 0xA8, 0x78, 0xFF, 0xFF, 0x43, 0x4E, +- 0x2E, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, +- 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xD8, 0x62, +- 0xA2, 0xD1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xF6, 0x62, +- 0xA2, 0xD1, 0x00, 0x60, 0x40, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x26, 0x46, 0x27, 0xF2, 0x70, 0x63, 0x60, 0x40, 0x0A, 0x36, 0x06, 0x00, 0x14, 0x36, 0x0A, 0x00, +- 0x37, 0x36, 0x04, 0x00, 0x6E, 0x36, 0x04, 0x00, 0xD0, 0x63, 0x04, 0x00, 0x33, 0x63, 0x02, 0x00, +- 0x21, 0x63, 0x00, 0x00, 0x1F, 0x60, 0x5A, 0x61, 0xA1, 0xDD, 0x26, 0x46, 0xBF, 0xF2, 0x01, 0x60, +- 0x00, 0x65, 0xF4, 0xA1, 0xD5, 0x80, 0x00, 0xF4, 0x02, 0x24, 0x65, 0x41, 0x41, 0x48, 0x1E, 0x65, +- 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, +- 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, +- 0xBD, 0xDB, 0xF0, 0x02, 0x02, 0x60, 0x00, 0x63, 0x28, 0x41, 0xBD, 0xD3, 0xBD, 0xD1, 0xFD, 0xA0, +- 0xFF, 0xFF, 0x07, 0x03, 0x64, 0x44, 0xE0, 0x85, 0xD1, 0x81, 0xFE, 0xA1, 0xC7, 0x83, 0xF5, 0x0D, +- 0x04, 0x00, 0x1A, 0x60, 0x4C, 0x61, 0xA3, 0xD3, 0xA1, 0xDB, 0x31, 0x40, 0x06, 0x26, 0x58, 0x00, +- 0x00, 0x64, 0x70, 0xFB, 0x02, 0x60, 0x00, 0x63, 0x28, 0x41, 0xBD, 0xD3, 0xBD, 0xD1, 0xFC, 0xA0, +- 0xFB, 0xA0, 0x08, 0x03, 0x28, 0x03, 0x64, 0x44, 0xE0, 0x85, 0xD1, 0x81, 0xFE, 0xA1, 0xC7, 0x83, +- 0xF4, 0x0D, 0x46, 0x00, 0xBD, 0xD3, 0xBD, 0xD3, 0x00, 0xB8, 0x70, 0xFB, 0x6F, 0xFB, 0xBD, 0xD3, +- 0x3F, 0x02, 0xA3, 0xD3, 0x60, 0x45, 0x60, 0x47, 0xB4, 0x84, 0x60, 0x41, 0x3F, 0xB5, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x72, 0xFB, 0x65, 0x47, 0xE0, 0x84, +- 0xE0, 0x84, 0x71, 0xFB, 0x64, 0x44, 0xE0, 0x85, 0xFA, 0xA3, 0xC7, 0x83, 0x1A, 0x60, 0x44, 0x62, +- 0x61, 0x44, 0xA2, 0xDB, 0xD2, 0x01, 0xBD, 0xD3, 0xA3, 0xD3, 0x00, 0xB8, 0x6E, 0xFB, 0x74, 0xFB, +- 0x1F, 0x02, 0x87, 0xF1, 0x70, 0xF3, 0x6D, 0xF9, 0x04, 0x65, 0x60, 0x40, 0x00, 0x3A, 0x06, 0x65, +- 0x31, 0x44, 0xB4, 0x84, 0x40, 0x51, 0x02, 0x2A, 0x0B, 0x00, 0x08, 0xBC, 0x40, 0x51, 0x72, 0xF3, +- 0x71, 0xF1, 0x00, 0xB8, 0x64, 0x45, 0x01, 0x03, 0x67, 0x45, 0x65, 0x50, 0xCC, 0x84, 0x73, 0xFB, +- 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x0F, 0x60, 0xEC, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2A, 0x84, 0x00, 0x1F, 0x60, +- 0x52, 0x61, 0x01, 0x64, 0xA1, 0xDB, 0x22, 0x60, 0x58, 0x4E, 0x3E, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x00, 0xF4, 0x0D, 0xF2, 0x80, 0xFB, 0x00, 0x64, 0x86, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, +- 0x00, 0x60, 0x80, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, +- 0x1E, 0x65, 0xF4, 0xA4, 0xD4, 0xA0, 0x60, 0x41, 0x01, 0x06, 0x2C, 0x61, 0x41, 0x48, 0x02, 0x60, +- 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x64, 0x44, +- 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, +- 0xF0, 0x02, 0x02, 0x60, 0x00, 0x63, 0x28, 0x41, 0xBD, 0xD3, 0xBD, 0xD1, 0x01, 0xA8, 0xC9, 0x81, +- 0x06, 0x03, 0x64, 0x44, 0xD1, 0x81, 0xE0, 0x85, 0x42, 0x06, 0xC7, 0x83, 0xF5, 0x01, 0x43, 0x48, +- 0x2D, 0x60, 0x2A, 0x63, 0x43, 0x4A, 0x64, 0x41, 0x28, 0x43, 0x00, 0x65, 0x45, 0x4C, 0x65, 0x5C, +- 0xBD, 0xD3, 0x61, 0x40, 0x00, 0x36, 0x27, 0x00, 0xCD, 0x81, 0x60, 0x40, 0x02, 0x36, 0x60, 0x45, +- 0x04, 0x36, 0x60, 0x45, 0x82, 0x36, 0x60, 0x45, 0x84, 0x36, 0x60, 0x45, 0x0B, 0x36, 0x60, 0x45, +- 0x8B, 0x36, 0x60, 0x45, 0x16, 0x36, 0x60, 0x45, 0x96, 0x36, 0x60, 0x45, 0x65, 0x40, 0x00, 0x36, +- 0xE7, 0x01, 0x64, 0x44, 0xDC, 0x9C, 0x2C, 0x44, 0x00, 0x3A, 0x02, 0x00, 0x45, 0x4C, 0xE0, 0x01, +- 0x2C, 0x5E, 0x65, 0x5F, 0x00, 0x65, 0x45, 0x4C, 0x43, 0x48, 0x2A, 0x43, 0xBD, 0xDB, 0xFF, 0xFF, +- 0x43, 0x4A, 0x28, 0x43, 0xD5, 0x01, 0x2D, 0x60, 0x28, 0x64, 0x60, 0xFE, 0xA0, 0xD9, 0xFF, 0xFF, +- 0x20, 0xFE, 0x64, 0x40, 0x01, 0x3A, 0x39, 0x00, 0x2A, 0x43, 0x65, 0x44, 0xA3, 0xDB, 0x35, 0x00, +- 0x23, 0x60, 0x34, 0x78, 0xFF, 0xFF, 0xDC, 0xF3, 0xFF, 0xFF, 0x03, 0xA8, 0x02, 0xA8, 0x02, 0x03, +- 0x41, 0x02, 0xF6, 0x01, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, +- 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x26, 0x46, 0x1F, 0x60, 0x5A, 0x61, 0xA1, 0xD3, 0x25, 0xF2, 0x60, 0x45, +- 0x24, 0xF0, 0x00, 0xF4, 0x64, 0x43, 0xC7, 0x83, 0x60, 0x41, 0x02, 0x24, 0x01, 0xA1, 0x0A, 0xF0, +- 0x09, 0xF2, 0xD1, 0x80, 0xFF, 0xFF, 0x09, 0x07, 0x04, 0x04, 0x63, 0x45, 0xD4, 0x80, 0xFF, 0xFF, +- 0x04, 0x06, 0x22, 0x60, 0x58, 0x4E, 0x3E, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x26, 0xF0, 0xFF, 0x67, +- 0x20, 0x88, 0x64, 0x5F, 0x40, 0x4A, 0x20, 0x60, 0x58, 0x4E, 0x45, 0x78, 0xFF, 0xFF, 0x0A, 0x48, +- 0x20, 0x60, 0x58, 0x4E, 0x55, 0x78, 0xFF, 0xFF, 0x20, 0x60, 0x58, 0x4E, 0x71, 0x78, 0xFF, 0xFF, +- 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xDA, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x22, +- 0xAF, 0x01, 0x01, 0x60, 0x2E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xBF, 0xB4, 0xA2, 0xDB, 0x1F, 0x60, +- 0x5A, 0x61, 0xA1, 0xD3, 0x26, 0x46, 0x60, 0x45, 0x1E, 0x60, 0xFE, 0x63, 0x00, 0xF4, 0x09, 0xF2, +- 0xBD, 0xDB, 0xFF, 0xFF, 0x0A, 0xF2, 0xBD, 0xDB, 0x0B, 0xF2, 0xFF, 0xFF, 0xBD, 0xDB, 0x0C, 0xF2, +- 0xA3, 0xDB, 0xFA, 0xA3, 0x26, 0x46, 0xA3, 0xD3, 0x24, 0xF0, 0x00, 0x61, 0xD0, 0x84, 0xF1, 0x81, +- 0xD4, 0x84, 0xF1, 0x81, 0xBD, 0xDB, 0xA3, 0xD3, 0x03, 0xB1, 0x03, 0xA9, 0x25, 0xF0, 0x42, 0xFE, +- 0x05, 0x03, 0xFD, 0xA1, 0xCC, 0x84, 0x01, 0x02, 0xCC, 0x84, 0x00, 0x61, 0xF1, 0x81, 0xD0, 0x84, +- 0xF1, 0x81, 0xBD, 0xDB, 0xA3, 0xD3, 0x03, 0xB1, 0x03, 0xA9, 0x28, 0xF0, 0x42, 0xFE, 0x01, 0x03, +- 0xCC, 0x84, 0xF1, 0x81, 0xD0, 0x84, 0xF1, 0x81, 0xBD, 0xDB, 0xA3, 0xD3, 0x03, 0xB1, 0x03, 0xA9, +- 0x29, 0xF0, 0x01, 0x03, 0xCC, 0x84, 0xD0, 0x84, 0xA3, 0xDB, 0x1F, 0x60, 0x52, 0x61, 0xA1, 0xD3, +- 0xFF, 0xFF, 0x02, 0xA8, 0xFF, 0xFF, 0x02, 0x02, 0x2E, 0x58, 0xFF, 0xFF, 0xF5, 0xFE, 0x1E, 0x60, +- 0xFE, 0x64, 0xA0, 0xD1, 0x06, 0xA4, 0xA0, 0xD3, 0x64, 0x45, 0x60, 0x40, 0x80, 0x2B, 0x03, 0x00, +- 0xFF, 0x60, 0xFF, 0x64, 0x94, 0x85, 0x00, 0x60, 0x96, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x0B, 0x06, +- 0x1F, 0x60, 0x52, 0x61, 0xA1, 0xD3, 0x6A, 0xF3, 0x00, 0xA8, 0x04, 0xB0, 0x04, 0x02, 0x03, 0x03, +- 0x23, 0x60, 0x10, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x09, 0xF2, 0x5A, 0xD2, 0x40, 0x48, +- 0x40, 0x4A, 0x5A, 0xD2, 0x5A, 0xD2, 0x40, 0x4C, 0x60, 0x41, 0x5A, 0xD0, 0x80, 0xF9, 0x40, 0x63, +- 0xAD, 0x80, 0xF0, 0xA3, 0x09, 0x02, 0x3C, 0x03, 0x2C, 0x41, 0x2A, 0x44, 0x40, 0x4C, 0x28, 0x44, +- 0x40, 0x4A, 0x00, 0x64, 0x40, 0x48, 0xF4, 0x01, 0xD1, 0x80, 0x01, 0x02, 0x31, 0x04, 0x10, 0xA3, +- 0x80, 0x60, 0x00, 0x65, 0xA5, 0x80, 0xCF, 0x83, 0x08, 0x02, 0x28, 0x44, 0x60, 0x88, 0x2A, 0x44, +- 0x70, 0x8A, 0x2C, 0x44, 0x70, 0x8C, 0xF1, 0x81, 0xF5, 0x01, 0xE7, 0xA3, 0x64, 0x44, 0x00, 0xA8, +- 0x00, 0x62, 0x02, 0x02, 0x00, 0x61, 0x1C, 0x00, 0xE0, 0x84, 0xDE, 0x82, 0xFD, 0x04, 0x42, 0xFE, +- 0xF8, 0x84, 0x62, 0x45, 0xC7, 0x83, 0x60, 0x45, 0x02, 0xFE, 0xD5, 0x84, 0x02, 0x05, 0x01, 0x05, +- 0x61, 0x44, 0xCF, 0x83, 0x60, 0x41, 0x08, 0x03, 0x28, 0x44, 0x60, 0x88, 0x2A, 0x44, 0x70, 0x8A, +- 0x2C, 0x44, 0x70, 0x8C, 0xF1, 0x81, 0xF1, 0x01, 0xCE, 0x82, 0xE9, 0x81, 0xFD, 0x02, 0xF1, 0x81, +- 0x09, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0xE8, 0x84, 0xE8, 0x84, 0x5A, 0xD2, 0x3F, 0xB5, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x84, 0x61, 0x45, 0xD4, 0x84, +- 0xC0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x93, 0x1F, 0x60, 0x52, 0x61, 0xA1, 0xD3, +- 0xFF, 0xFF, 0x00, 0xA8, 0xFF, 0xFF, 0x02, 0x03, 0x2E, 0x58, 0xFF, 0xFF, 0x10, 0x65, 0x73, 0x44, +- 0xD4, 0x93, 0x6A, 0xF3, 0x26, 0x46, 0x04, 0xBC, 0xA2, 0xDB, 0x26, 0xF0, 0xFF, 0x67, 0x20, 0x88, +- 0x64, 0x5F, 0x40, 0x4A, 0x20, 0x60, 0x58, 0x4E, 0x45, 0x78, 0xFF, 0xFF, 0x0A, 0x48, 0x20, 0x60, +- 0x58, 0x4E, 0x55, 0x78, 0xFF, 0xFF, 0x20, 0x60, 0x58, 0x4E, 0x71, 0x78, 0xFF, 0xFF, 0x6C, 0xF3, +- 0xFF, 0xFF, 0x00, 0xB8, 0xCC, 0x84, 0x01, 0x03, 0xA2, 0xDB, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, +- 0x00, 0x60, 0x40, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, +- 0xA2, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xD8, 0x62, +- 0xA2, 0xD1, 0xFF, 0x60, 0xDF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, +- 0x28, 0xF3, 0xFF, 0xFF, 0x60, 0x47, 0x0F, 0xB4, 0x59, 0x00, 0xFF, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x24, 0x60, 0x9E, 0x65, 0x04, 0x64, 0xA5, 0xDB, 0x12, 0x00, 0x24, 0x60, 0x9E, 0x65, 0x0C, 0x64, +- 0xA5, 0xDB, 0x0D, 0x00, 0x24, 0x60, 0x9E, 0x65, 0x06, 0x64, 0xA5, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x9E, 0x65, 0x08, 0x64, 0xA5, 0xDB, 0x23, 0x60, +- 0xA1, 0x64, 0xA1, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0x29, 0xF3, +- 0x7F, 0xFB, 0xA4, 0xFB, 0x02, 0x60, 0xEE, 0x64, 0xA3, 0xFB, 0x07, 0x64, 0xA5, 0xFB, 0x23, 0x60, +- 0xA1, 0x64, 0xA1, 0xFB, 0xFF, 0xFF, 0xDF, 0xFE, 0x00, 0x64, 0x19, 0xFF, 0x25, 0x60, 0x11, 0x78, +- 0xFF, 0xFF, 0x24, 0x60, 0x0D, 0x63, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0x23, 0x60, +- 0x8E, 0x63, 0xA1, 0xFD, 0xFF, 0xFF, 0x1A, 0xFF, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0xA3, 0x60, +- 0x4B, 0x63, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0x29, 0xF5, 0x24, 0x60, 0x7A, 0x63, +- 0x24, 0x60, 0x4C, 0x64, 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0x02, 0x64, 0xA3, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xF9, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xA7, 0x01, 0x00, 0x36, 0xA8, 0x01, +- 0x01, 0x36, 0xAB, 0x01, 0x02, 0x36, 0xAE, 0x01, 0x03, 0x36, 0xB5, 0x01, 0x04, 0x36, 0xD1, 0x01, +- 0x05, 0x36, 0xCF, 0x01, 0x06, 0x36, 0xF1, 0x01, 0x07, 0x36, 0xCB, 0x01, 0x08, 0x36, 0xB7, 0x01, +- 0x09, 0x36, 0x0C, 0x00, 0x0A, 0x36, 0x0D, 0x00, 0x0B, 0x36, 0x0E, 0x00, 0x0C, 0x36, 0x17, 0x00, +- 0x0D, 0x36, 0x0D, 0x00, 0x0E, 0x36, 0x1E, 0x00, 0x0F, 0x36, 0x32, 0x00, 0x02, 0x60, 0x00, 0x64, +- 0x08, 0x00, 0x04, 0x60, 0x00, 0x64, 0x05, 0x00, 0x00, 0x60, 0x01, 0x64, 0x02, 0x00, 0x20, 0x60, +- 0x00, 0x64, 0x32, 0x45, 0xB4, 0x85, 0x45, 0x52, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x60, +- 0xD1, 0x63, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x3F, 0x40, 0x02, 0x2B, 0x05, 0x00, 0x90, 0x60, 0x00, 0xE8, 0x24, 0x60, +- 0x0D, 0x63, 0x04, 0x00, 0x91, 0x60, 0x00, 0xE8, 0x24, 0x60, 0xBB, 0x63, 0x28, 0xE8, 0x0C, 0x60, +- 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x91, 0x60, 0x00, 0xE8, 0x28, 0xE8, 0xD9, 0x60, 0xFE, 0x64, 0x32, 0x45, 0xA4, 0x85, 0x45, 0x52, +- 0x99, 0xFF, 0xA5, 0x4F, 0xFF, 0xB4, 0x07, 0xFB, 0x98, 0xFF, 0xA3, 0x60, 0x4B, 0x63, 0x0C, 0x60, +- 0x16, 0x64, 0xA0, 0xDD, 0x62, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, +- 0xFF, 0xFF, 0x43, 0xFF, 0x01, 0x60, 0x00, 0xE1, 0x28, 0xF3, 0x47, 0xFF, 0x60, 0x40, 0x07, 0x37, +- 0x4B, 0x00, 0x05, 0x3B, 0x04, 0x00, 0xFF, 0x0A, 0x80, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x29, 0xF5, +- 0x2A, 0xF3, 0x47, 0xFF, 0x3F, 0xF0, 0x01, 0x1B, 0x01, 0x64, 0x60, 0x56, 0xAD, 0xE2, 0xB5, 0xFF, +- 0x6C, 0x40, 0x40, 0xE1, 0xA1, 0xFF, 0x00, 0xF4, 0x6E, 0x61, 0x12, 0x62, 0x64, 0x43, 0x01, 0xE1, +- 0x03, 0x64, 0xE2, 0xD0, 0xC9, 0x81, 0x64, 0x4C, 0xCC, 0x84, 0xDA, 0x82, 0xFA, 0x02, 0x01, 0x60, +- 0x00, 0x6B, 0x9A, 0xFF, 0xCA, 0x82, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xFF, 0x7A, 0xD0, +- 0xA1, 0xFF, 0x64, 0x4C, 0xFC, 0x1C, 0xF8, 0x1D, 0x00, 0xB9, 0x06, 0x1E, 0x02, 0x02, 0x00, 0xF4, +- 0xDA, 0x82, 0x5A, 0xD2, 0xA1, 0xFF, 0x60, 0x4D, 0x3F, 0x40, 0x02, 0x2B, 0x08, 0x00, 0x28, 0xF3, +- 0xA5, 0x60, 0xC4, 0x65, 0x60, 0x40, 0x0E, 0x3B, 0x02, 0x00, 0x80, 0x4C, 0xFE, 0x01, 0xA1, 0xFF, +- 0x87, 0x4E, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x67, 0x4C, 0xFF, 0xFF, 0xBC, 0xFF, +- 0x00, 0xE1, 0xD5, 0xFE, 0xA1, 0xFF, 0xFF, 0xFF, 0x00, 0x64, 0x40, 0x46, 0x60, 0x41, 0xB5, 0xFF, +- 0xB7, 0xFF, 0xB4, 0xFF, 0x29, 0xF5, 0x3F, 0xF0, 0x24, 0xF2, 0x44, 0x43, 0x40, 0x44, 0x00, 0xF4, +- 0xF3, 0x60, 0xA0, 0x65, 0x10, 0x62, 0x5A, 0xD2, 0xD9, 0x81, 0xD4, 0x80, 0xFF, 0xFF, 0xFB, 0x02, +- 0x61, 0x45, 0x24, 0x44, 0xD4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xFD, 0xA5, 0x48, 0x60, +- 0x00, 0x64, 0xC4, 0x9D, 0x0D, 0x60, 0x00, 0x6B, 0x24, 0x44, 0xC0, 0x83, 0xBB, 0xFF, 0x29, 0xF5, +- 0x01, 0xE1, 0x00, 0xF4, 0x6C, 0x61, 0x10, 0x62, 0x05, 0x00, 0x00, 0xF4, 0x01, 0xF2, 0xFF, 0xFF, +- 0x60, 0x41, 0x04, 0x62, 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x1A, 0x00, 0x26, 0x44, 0x01, 0x26, +- 0x0C, 0x00, 0x24, 0x44, 0xC8, 0x84, 0x40, 0x44, 0x02, 0x03, 0x6C, 0x45, 0xF3, 0x01, 0x03, 0x15, +- 0x01, 0x64, 0x05, 0xFA, 0x15, 0x00, 0x6C, 0x45, 0xED, 0x01, 0x23, 0x44, 0xC8, 0x84, 0x40, 0x43, +- 0x02, 0x03, 0x6C, 0x45, 0xE7, 0x01, 0x00, 0x64, 0x01, 0x15, 0x01, 0x64, 0x6C, 0x45, 0x05, 0xFB, +- 0xE2, 0xD2, 0xDA, 0x82, 0xC9, 0x81, 0x60, 0x4C, 0xDD, 0x1C, 0xD7, 0x03, 0xBC, 0xFF, 0xDA, 0x01, +- 0x00, 0xE1, 0xD5, 0xFE, 0xA1, 0xFF, 0xFF, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, 0x67, 0x4C, 0x43, 0xFF, +- 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x01, 0xE1, 0x01, 0x60, 0x69, 0x6B, 0xA5, 0x60, +- 0xC4, 0x64, 0x60, 0x4C, 0xBB, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x60, 0x4C, 0xFC, 0x01, 0x29, 0xF3, 0x2A, 0xF1, 0x07, 0xB5, 0x04, 0xE1, 0x65, 0x41, 0x64, 0x54, +- 0xCD, 0xE2, 0x95, 0x81, 0xA1, 0x5D, 0xA1, 0xFF, 0xFF, 0xFF, 0xF9, 0x01, 0x61, 0x44, 0xFE, 0xFB, +- 0xFF, 0xFD, 0xFF, 0x01, 0x7F, 0x67, 0x01, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0xB1, 0xFE, 0x08, 0x05, +- 0xB0, 0xFE, 0x09, 0x05, 0xB2, 0xFE, 0xB3, 0xFE, 0x78, 0x43, 0x01, 0x61, 0x24, 0x60, 0xDD, 0x78, +- 0x2D, 0x60, 0x5D, 0x78, 0xFF, 0xFF, 0x28, 0xF3, 0x29, 0xF1, 0x40, 0x44, 0x44, 0x45, 0x2A, 0xF1, +- 0x2B, 0xF1, 0x44, 0x46, 0x44, 0x47, 0x3F, 0xB4, 0xE0, 0x85, 0x1F, 0x60, 0x88, 0x64, 0x44, 0xD7, +- 0x58, 0x43, 0xFF, 0xFF, 0x60, 0x45, 0x1C, 0x60, 0xB4, 0x7C, 0xA4, 0xD3, 0x61, 0x43, 0x04, 0xB4, +- 0x24, 0x44, 0x02, 0x03, 0x13, 0xFF, 0x06, 0x00, 0x3F, 0xB4, 0xB4, 0x84, 0xFF, 0x27, 0x05, 0xFD, +- 0x04, 0xFB, 0x10, 0x75, 0xA1, 0xFF, 0xFF, 0xFF, 0x86, 0x3E, 0xB4, 0xFE, 0x0B, 0x05, 0xB5, 0xFE, +- 0x02, 0x24, 0xA1, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xFE, 0x07, 0x05, 0x78, 0x43, 0x01, 0x61, +- 0x24, 0x60, 0xDD, 0x78, 0x2D, 0x60, 0x98, 0x78, 0xFF, 0xFF, 0x36, 0x44, 0x00, 0x7F, 0xF2, 0xA0, +- 0x60, 0x45, 0x05, 0x05, 0x20, 0x60, 0x16, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0x43, +- 0x01, 0x61, 0x24, 0x60, 0xDD, 0x78, 0x78, 0x43, 0x01, 0x61, 0x24, 0x60, 0xDD, 0x78, 0x7F, 0x60, +- 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x10, 0x02, 0x10, 0x64, 0x40, 0x40, +- 0x02, 0x64, 0x40, 0x50, 0x61, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x04, 0x00, 0x10, 0xE0, 0x46, 0x60, +- 0x09, 0xE0, 0x00, 0x00, 0x27, 0xF1, 0x00, 0x66, 0x20, 0x78, 0x42, 0xFE, 0x23, 0x58, 0xFF, 0xFF, +- 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x1A, 0x02, 0x1C, 0x60, +- 0xB4, 0x63, 0xA3, 0xD3, 0x07, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, 0x04, 0x03, 0x03, 0x02, 0xDC, 0xF9, +- 0x00, 0x67, 0x0F, 0x00, 0x00, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0xAC, 0x01, 0x36, 0x47, 0xFF, 0x23, +- 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x04, 0x00, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, +- 0x02, 0x61, 0x31, 0x02, 0x1C, 0x60, 0xB4, 0x63, 0xA3, 0xD3, 0x01, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, +- 0x03, 0x03, 0x02, 0x02, 0xDC, 0xF9, 0xFF, 0xFF, 0x02, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0x25, 0x60, +- 0x11, 0x78, 0xFF, 0xFF, 0x9F, 0xF1, 0x20, 0x44, 0x64, 0x40, 0xFF, 0x26, 0x1B, 0x00, 0x7F, 0xB4, +- 0x40, 0x40, 0x5C, 0x5E, 0x82, 0xFF, 0x26, 0x44, 0xFD, 0xB4, 0x40, 0x46, 0x5C, 0x41, 0x87, 0xFF, +- 0x62, 0xFF, 0x00, 0x63, 0x24, 0x60, 0x5E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, +- 0x04, 0x03, 0x09, 0xF2, 0x0F, 0xFC, 0xAC, 0x86, 0xFB, 0x01, 0x24, 0x60, 0x9E, 0x62, 0x06, 0x64, +- 0xA2, 0xDB, 0x2D, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x00, 0x67, 0x20, 0x40, 0x80, 0x2A, +- 0x02, 0x00, 0x7F, 0x67, 0x06, 0x61, 0x60, 0x45, 0x1C, 0x60, 0xB4, 0x7C, 0xA4, 0xD3, 0x61, 0x43, +- 0x04, 0xB4, 0x24, 0x44, 0x02, 0x03, 0x13, 0xFF, 0x55, 0x01, 0x3F, 0xB4, 0xB4, 0x84, 0xFF, 0x27, +- 0x05, 0xFD, 0x04, 0xFB, 0x20, 0x40, 0x80, 0x2A, 0x02, 0x00, 0x10, 0x75, 0x07, 0x00, 0x2D, 0x60, +- 0x9C, 0x62, 0x01, 0x64, 0xA2, 0xDB, 0xFF, 0xFF, 0x08, 0x60, 0x10, 0x75, 0x43, 0x01, 0x25, 0x46, +- 0x01, 0xF2, 0x08, 0xF0, 0x60, 0x47, 0x03, 0xB4, 0x03, 0xAC, 0x7F, 0x67, 0x03, 0x61, 0x08, 0x02, +- 0x24, 0x60, 0x7A, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x2B, 0x49, 0x00, 0x25, 0x44, 0x1F, 0xB4, 0xE0, 0x85, +- 0x25, 0x60, 0xEB, 0x64, 0xC4, 0x98, 0xFF, 0xFF, 0xC0, 0xFE, 0x3D, 0x00, 0xC1, 0xFE, 0x3B, 0x00, +- 0xC2, 0xFE, 0x39, 0x00, 0xC3, 0xFE, 0x37, 0x00, 0xC4, 0xFE, 0x35, 0x00, 0xC5, 0xFE, 0x33, 0x00, +- 0xC6, 0xFE, 0x31, 0x00, 0xC7, 0xFE, 0x2F, 0x00, 0xC8, 0xFE, 0x2D, 0x00, 0xC9, 0xFE, 0x2B, 0x00, +- 0xCA, 0xFE, 0x29, 0x00, 0xCB, 0xFE, 0x27, 0x00, 0xCC, 0xFE, 0x25, 0x00, 0xCD, 0xFE, 0x23, 0x00, +- 0xCE, 0xFE, 0x21, 0x00, 0xCF, 0xFE, 0x1F, 0x00, 0xD0, 0xFE, 0x1D, 0x00, 0xD1, 0xFE, 0x1B, 0x00, +- 0xD2, 0xFE, 0x19, 0x00, 0xD3, 0xFE, 0x17, 0x00, 0xD4, 0xFE, 0x15, 0x00, 0xD5, 0xFE, 0x13, 0x00, +- 0xD6, 0xFE, 0x11, 0x00, 0xD7, 0xFE, 0x0F, 0x00, 0xD8, 0xFE, 0x0D, 0x00, 0xD9, 0xFE, 0x0B, 0x00, +- 0xDA, 0xFE, 0x09, 0x00, 0xDB, 0xFE, 0x07, 0x00, 0xDC, 0xFE, 0x05, 0x00, 0xDD, 0xFE, 0x03, 0x00, +- 0xDE, 0xFE, 0x01, 0x00, 0xDF, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x9F, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x9E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9D, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x9C, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9A, 0xFE, 0xF0, 0x84, +- 0xFF, 0xFF, 0x99, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x98, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x97, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x96, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x95, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x94, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x93, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x92, 0xFE, 0xF0, 0x84, +- 0xFF, 0xFF, 0x91, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x90, 0xFE, 0xF0, 0x84, 0x06, 0xFB, 0x8F, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x8E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8D, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x8C, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8A, 0xFE, 0xF0, 0x84, +- 0xFF, 0xFF, 0x89, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x88, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x87, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x86, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x85, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x84, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x83, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x82, 0xFE, 0xF0, 0x84, +- 0xFF, 0xFF, 0x81, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x80, 0xFE, 0xF0, 0x84, 0x05, 0xFB, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x5C, 0x5C, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x27, +- 0x55, 0x00, 0x05, 0x60, 0x00, 0x63, 0x05, 0xFD, 0x30, 0x44, 0xBD, 0xDB, 0x31, 0x44, 0xBD, 0xDB, +- 0x32, 0x44, 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, 0x35, 0x44, 0xBD, 0xDB, +- 0x36, 0x44, 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, 0x39, 0x44, 0xBD, 0xDB, +- 0x3A, 0x44, 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, 0x3D, 0x44, 0xBD, 0xDB, +- 0x3E, 0x44, 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0x02, 0x61, 0x61, 0x44, 0x02, 0x36, 0x82, 0xFF, +- 0x03, 0x36, 0x83, 0xFF, 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, 0x06, 0x36, 0x86, 0xFF, +- 0x07, 0x36, 0x87, 0xFF, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, +- 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, +- 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, +- 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, +- 0x2F, 0x44, 0xBD, 0xDB, 0xDD, 0x81, 0x08, 0x3A, 0xD0, 0x01, 0x54, 0x00, 0x27, 0x40, 0x10, 0x26, +- 0x30, 0x00, 0x26, 0x44, 0x01, 0x36, 0x2D, 0x00, 0x02, 0x36, 0x82, 0xFF, 0x03, 0x36, 0x83, 0xFF, +- 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, 0x06, 0x36, 0x86, 0xFF, 0x25, 0x44, 0x00, 0x36, +- 0x44, 0x40, 0x01, 0x36, 0x44, 0x41, 0x02, 0x36, 0x44, 0x42, 0x03, 0x36, 0x44, 0x43, 0x04, 0x36, +- 0x44, 0x44, 0x05, 0x36, 0x44, 0x45, 0x06, 0x36, 0x44, 0x46, 0x07, 0x36, 0x44, 0x47, 0x08, 0x36, +- 0x44, 0x48, 0x09, 0x36, 0x44, 0x49, 0x0A, 0x36, 0x44, 0x4A, 0x0B, 0x36, 0x44, 0x4B, 0x0C, 0x36, +- 0x44, 0x4C, 0x0D, 0x36, 0x44, 0x4D, 0x0E, 0x36, 0x44, 0x4E, 0x0F, 0x36, 0x44, 0x4F, 0x87, 0xFF, +- 0x21, 0x00, 0x25, 0x44, 0x10, 0x36, 0x44, 0x50, 0x11, 0x36, 0x44, 0x51, 0x12, 0x36, 0x44, 0x52, +- 0x13, 0x36, 0x44, 0x53, 0x14, 0x36, 0x44, 0x54, 0x15, 0x36, 0x44, 0x55, 0x16, 0x36, 0x44, 0x56, +- 0x17, 0x36, 0x44, 0x57, 0x18, 0x36, 0x44, 0x58, 0x19, 0x36, 0x44, 0x59, 0x1A, 0x36, 0x44, 0x5A, +- 0x1B, 0x36, 0x44, 0x5B, 0x1C, 0x36, 0x44, 0x5C, 0x1D, 0x36, 0x44, 0x5D, 0x1E, 0x36, 0x44, 0x5E, +- 0x1F, 0x36, 0x44, 0x5F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0x46, 0xAE, 0x60, 0x58, 0x4F, +- 0x6F, 0x78, 0xFF, 0xFF, 0x03, 0x61, 0x7F, 0x67, 0x0B, 0x02, 0x00, 0xF0, 0x24, 0x60, 0x7A, 0x62, +- 0x04, 0x64, 0xA2, 0xDB, 0x5A, 0xD9, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, +- 0x11, 0x02, 0x24, 0x60, 0x9E, 0x62, 0x1A, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x50, 0x63, 0x5A, 0xDD, +- 0x27, 0x60, 0x6E, 0x64, 0xA1, 0xFB, 0x2D, 0xFF, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0x2A, 0xF3, +- 0x05, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, +- 0x7F, 0x67, 0x02, 0x61, 0x0F, 0x02, 0x24, 0x60, 0x9E, 0x62, 0x1C, 0x64, 0xA2, 0xDB, 0x00, 0x60, +- 0x50, 0x63, 0x5A, 0xDD, 0x27, 0x60, 0x88, 0x64, 0xA1, 0xFB, 0x2D, 0xFF, 0x25, 0x60, 0x11, 0x78, +- 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, +- 0x02, 0x61, 0x3E, 0x02, 0x25, 0x45, 0x20, 0x44, 0x80, 0x2A, 0x3A, 0x00, 0xF1, 0x60, 0x00, 0x64, +- 0xD4, 0x80, 0xFF, 0xFF, 0x0B, 0x03, 0xF1, 0x60, 0x01, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x06, 0x03, +- 0xF1, 0x60, 0x02, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x30, 0x03, 0x29, 0x00, 0x2D, 0x60, 0x0E, 0x62, +- 0xA2, 0xD1, 0xBA, 0xF3, 0x1F, 0x60, 0x82, 0x61, 0xA0, 0x84, 0xA1, 0xDB, 0x25, 0x45, 0x23, 0x60, +- 0xE4, 0x63, 0x02, 0x61, 0xBD, 0xD3, 0xBD, 0xD1, 0xD4, 0x80, 0xBD, 0xD3, 0xBD, 0xD5, 0xCD, 0x81, +- 0x02, 0x03, 0x15, 0x03, 0xF7, 0x01, 0xA2, 0xFF, 0xA6, 0xD3, 0x40, 0x4C, 0x00, 0xA8, 0x67, 0x43, +- 0x0C, 0x02, 0xA2, 0xDD, 0x42, 0x48, 0x64, 0x41, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, +- 0x66, 0x44, 0x28, 0xDB, 0x02, 0x03, 0x2C, 0x58, 0xA3, 0xFF, 0x0C, 0x61, 0x03, 0x00, 0x04, 0x61, +- 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x2D, 0x60, 0x0E, 0x62, 0xA2, 0xD1, +- 0xBA, 0xF3, 0x1F, 0x60, 0x82, 0x61, 0xA0, 0x84, 0xA1, 0xDB, 0x1F, 0x60, 0x86, 0x61, 0x01, 0x64, +- 0xA1, 0xDB, 0xFF, 0xFF, 0xC4, 0xFE, 0xEE, 0x01, 0xC6, 0xFE, 0xEC, 0x01, 0x7E, 0x60, 0xC0, 0x64, +- 0x24, 0x45, 0xA4, 0x80, 0x02, 0x61, 0x3F, 0x02, 0x25, 0x45, 0xF8, 0x2B, 0x3B, 0x00, 0x2E, 0xF5, +- 0x67, 0x44, 0xD4, 0x80, 0x20, 0x60, 0x24, 0x63, 0x39, 0x03, 0x60, 0x61, 0x24, 0x44, 0x01, 0x27, +- 0x29, 0x00, 0xA3, 0xFC, 0xA4, 0xF8, 0xBD, 0xD3, 0xA3, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, +- 0x64, 0x58, 0x08, 0xA3, 0xF8, 0x02, 0x08, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xA3, 0xD1, 0xFE, 0xA0, +- 0xFA, 0x60, 0x00, 0x64, 0xD0, 0x80, 0x14, 0x02, 0x13, 0x02, 0x04, 0xA3, 0xBE, 0xD3, 0xBD, 0xD1, +- 0x0F, 0x18, 0xD4, 0x80, 0x0D, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x64, 0x41, +- 0xDD, 0x81, 0xE1, 0x81, 0xCB, 0x83, 0x46, 0x65, 0x2F, 0x60, 0x58, 0x4F, 0x01, 0x78, 0xFF, 0xFF, +- 0x00, 0x67, 0x0A, 0x00, 0xBD, 0xD3, 0xBE, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, 0x64, 0x58, +- 0x08, 0xA3, 0xF8, 0x02, 0x04, 0x61, 0x7F, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x0F, 0x64, 0x23, 0xFA, +- 0x67, 0x44, 0x24, 0xFA, 0x62, 0x41, 0x3C, 0x60, 0x00, 0x65, 0x1A, 0x63, 0x68, 0x60, 0x28, 0x64, +- 0x65, 0x46, 0x58, 0xD0, 0x2E, 0xF5, 0x59, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0xCB, 0x83, 0xBF, 0xD1, 0x4A, 0x65, 0x64, 0x43, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0x01, 0x26, +- 0xDC, 0x81, 0xE9, 0x84, 0xDC, 0x84, 0x23, 0xFA, 0x09, 0x00, 0x4B, 0xD3, 0xFF, 0xFF, 0x60, 0x41, +- 0xE8, 0x84, 0xDC, 0x84, 0x23, 0xFA, 0xBF, 0xD1, 0x4A, 0x65, 0x64, 0x43, 0x2F, 0x60, 0x58, 0x4F, +- 0x01, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xE0, 0xA0, +- 0x20, 0x64, 0x01, 0x06, 0x25, 0xFA, 0x23, 0xF2, 0xDF, 0xD1, 0xCC, 0x84, 0xE0, 0x85, 0x0B, 0x06, +- 0xBF, 0xD1, 0x64, 0x41, 0xD5, 0x80, 0x64, 0x43, 0x01, 0x06, 0x65, 0x41, 0x4A, 0x65, 0x29, 0x60, +- 0x58, 0x4F, 0x83, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xDC, 0xF3, 0x02, 0x63, +- 0x23, 0xFC, 0x07, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x4B, 0xD3, 0xBF, 0xD3, +- 0x60, 0x41, 0xC9, 0x83, 0xE9, 0x81, 0xDD, 0x81, 0xA3, 0xFA, 0xE0, 0x81, 0x3C, 0x60, 0x00, 0x67, +- 0x02, 0x24, 0x02, 0xA4, 0x60, 0x47, 0x40, 0x4B, 0xC9, 0x81, 0x4A, 0x65, 0xAB, 0x46, 0x59, 0xD0, +- 0xAB, 0x46, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF6, 0x1F, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, +- 0x60, 0x47, 0x25, 0xFA, 0x00, 0x7E, 0x60, 0x47, 0x01, 0x26, 0xDC, 0x84, 0x60, 0x41, 0xE8, 0x84, +- 0xD8, 0x84, 0x23, 0xFA, 0xAB, 0x01, 0xFC, 0xA3, 0xA3, 0xD1, 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, +- 0x00, 0x7F, 0x25, 0xFA, 0x60, 0x41, 0x01, 0x26, 0xDD, 0x81, 0xE9, 0x84, 0xD8, 0x84, 0x23, 0xFA, +- 0x9D, 0x01, 0x28, 0x60, 0xE2, 0x63, 0xBF, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0xE8, 0x84, 0xDC, 0x84, +- 0x23, 0xFA, 0x4A, 0x65, 0x2F, 0x60, 0x58, 0x4F, 0x01, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x28, 0x60, 0xE2, 0x63, 0x23, 0xF2, 0xC0, 0x65, 0xCC, 0x84, 0xE0, 0x81, 0x0A, 0x04, +- 0xBF, 0xDB, 0xD5, 0x80, 0x07, 0x03, 0x01, 0x06, 0x65, 0x41, 0x61, 0x44, 0xBF, 0xDB, 0x4A, 0x65, +- 0x58, 0x4F, 0xAA, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x03, 0x4E, 0x28, 0x60, 0x58, 0x43, +- 0x5C, 0x78, 0xFF, 0xFF, 0x29, 0x60, 0xC6, 0x61, 0x29, 0x60, 0xA4, 0x62, 0xA2, 0xD3, 0xA1, 0xDB, +- 0xCC, 0x84, 0xA8, 0x83, 0x05, 0x04, 0x29, 0x60, 0xA4, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, +- 0x0E, 0x43, 0x81, 0x01, 0x23, 0xF2, 0x1C, 0x60, 0x8E, 0x65, 0x60, 0x41, 0x1C, 0x60, 0x2A, 0x63, +- 0xA3, 0xDB, 0xFF, 0xA1, 0x48, 0x64, 0x58, 0xD0, 0x7E, 0xA8, 0x5B, 0xD9, 0x02, 0x02, 0x00, 0xF4, +- 0x02, 0x64, 0xFF, 0xA1, 0xD7, 0x80, 0x02, 0x03, 0x01, 0x03, 0xF5, 0x01, 0x2E, 0xF5, 0x00, 0x60, +- 0x2F, 0x65, 0x25, 0xF2, 0x00, 0x63, 0xCC, 0x84, 0x03, 0xA3, 0xFD, 0x05, 0x4A, 0x64, 0xD7, 0x80, +- 0x1B, 0x60, 0xC6, 0x61, 0x2F, 0x05, 0xA1, 0xDD, 0xE3, 0x83, 0xFE, 0xA3, 0x58, 0xD0, 0x7E, 0xA8, +- 0x59, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x00, 0x63, 0x59, 0xDD, 0x2E, 0xF5, +- 0x1B, 0x60, 0xC6, 0x64, 0x25, 0xF0, 0xA0, 0xD3, 0xD3, 0x80, 0x01, 0xB0, 0x04, 0x03, 0x01, 0xA4, +- 0x03, 0x03, 0xA2, 0xDB, 0x01, 0x00, 0xA2, 0xDD, 0x1B, 0x60, 0xCE, 0x63, 0x10, 0x60, 0x5A, 0x65, +- 0xBD, 0xD3, 0xBD, 0xD1, 0xE0, 0x84, 0xC4, 0x82, 0x10, 0x60, 0x7A, 0x65, 0x07, 0x64, 0x64, 0x41, +- 0x5A, 0xDB, 0xD6, 0x80, 0xCD, 0x81, 0x06, 0x03, 0xFB, 0x02, 0x25, 0xF2, 0x02, 0xA3, 0xCC, 0x84, +- 0xA2, 0xDA, 0xEC, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x2A, 0x61, 0xA1, 0xD3, +- 0x23, 0xFA, 0xE0, 0x83, 0x4A, 0x65, 0x04, 0x02, 0x02, 0x63, 0x23, 0xFC, 0xA5, 0xFC, 0x09, 0x00, +- 0xDB, 0x83, 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, +- 0xF8, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x1B, 0x60, 0xC6, 0x62, 0xA2, 0xD3, 0x00, 0x61, +- 0x02, 0xA4, 0xFE, 0xA0, 0x23, 0xFA, 0x1B, 0x03, 0xFA, 0xA4, 0xFD, 0xA4, 0x01, 0xA1, 0xFD, 0x07, +- 0x61, 0x43, 0x23, 0xF2, 0x25, 0xFC, 0xE0, 0x83, 0x02, 0xA3, 0x1B, 0x60, 0xC6, 0x61, 0x00, 0x60, +- 0x4A, 0x64, 0x59, 0xD1, 0x58, 0xD8, 0x7E, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, +- 0x25, 0xF2, 0x23, 0xF2, 0x01, 0xB0, 0xCC, 0x84, 0x04, 0x02, 0x23, 0xFA, 0x02, 0x00, 0x00, 0x64, +- 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x41, 0x4B, 0x65, 0x42, 0x80, 0x64, 0xD4, 0x85, +- 0x2B, 0x41, 0x00, 0xA1, 0x55, 0x8B, 0x0D, 0x03, 0x02, 0x04, 0x65, 0x41, 0x02, 0x00, 0x00, 0x64, +- 0x40, 0x4B, 0xCA, 0x84, 0x58, 0xD0, 0xC9, 0x81, 0xBD, 0xD9, 0xFC, 0x02, 0x00, 0xF4, 0x04, 0x65, +- 0xEC, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD3, 0x02, 0x7C, 0xA0, 0xD3, 0x23, 0xF8, +- 0xDC, 0x84, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x64, 0x23, 0xFA, 0x01, 0x64, +- 0x9D, 0xFE, 0x02, 0x28, 0x02, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x2D, 0x60, +- 0x1A, 0x62, 0xA2, 0xD3, 0x02, 0x7C, 0x23, 0xF8, 0x01, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, 0x02, 0x64, 0x23, 0xFA, 0xA4, 0xD3, 0x00, 0x63, 0x60, 0x40, +- 0x0A, 0x37, 0x01, 0x63, 0x14, 0x37, 0x02, 0x63, 0x37, 0x37, 0x06, 0x63, 0x6E, 0x37, 0x0B, 0x63, +- 0x25, 0xFC, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x64, 0x23, 0xFA, 0x88, 0xFF, 0x75, 0x44, +- 0x8D, 0xFF, 0xE8, 0x87, 0xE8, 0x84, 0xE8, 0x84, 0x03, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x04, 0x64, 0x23, 0xFA, 0x86, 0xFF, 0x29, 0x44, 0x87, 0xFF, 0x25, 0xFA, 0x55, 0xF3, +- 0x52, 0xF1, 0x80, 0x65, 0xC4, 0x87, 0x00, 0x7F, 0x26, 0xFA, 0x64, 0x44, 0xC4, 0x87, 0x00, 0x7F, +- 0x27, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x05, 0x64, 0x23, 0xFA, 0x52, 0x63, 0xB7, 0xF3, +- 0x4B, 0xDA, 0xB6, 0xF3, 0x4B, 0xDA, 0xB5, 0xF3, 0x4B, 0xDA, 0x60, 0x41, 0x88, 0xFF, 0x72, 0x5C, +- 0x89, 0xFF, 0x4A, 0xD8, 0xA2, 0x48, 0x20, 0x23, 0x0E, 0x00, 0x64, 0x40, 0x80, 0x27, 0x15, 0x00, +- 0xDC, 0x84, 0xBD, 0xDA, 0xBD, 0xD2, 0x11, 0x04, 0xDC, 0x84, 0xA2, 0xDA, 0xA3, 0xD2, 0x0D, 0x04, +- 0xDC, 0x84, 0xA3, 0xDA, 0x0A, 0x00, 0x52, 0x63, 0xB7, 0xF3, 0x4B, 0xDA, 0xB6, 0xF3, 0x4B, 0xDA, +- 0xB5, 0xF3, 0x4B, 0xDA, 0x54, 0x90, 0x4C, 0x63, 0xE0, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x25, 0xF0, 0x2D, 0x60, 0x16, 0x65, 0x23, 0xF2, 0xA5, 0xD9, 0x02, 0xA8, 0x64, 0x44, 0x07, 0x02, +- 0x00, 0xBC, 0xF2, 0xA4, 0x04, 0x03, 0x03, 0x07, 0x28, 0x60, 0x44, 0x62, 0xA2, 0xD9, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x20, 0x63, 0x28, 0x60, 0xA4, 0x61, 0x48, 0x64, 0x58, 0xD0, 0x59, 0xD9, +- 0xFD, 0x1F, 0x25, 0xF0, 0x20, 0x64, 0xD0, 0x81, 0xFF, 0xFF, 0x02, 0x07, 0x25, 0xFA, 0x0F, 0x00, +- 0x28, 0x60, 0xA8, 0x63, 0xC3, 0x83, 0x01, 0x2A, 0x06, 0x00, 0xCF, 0x83, 0xA3, 0xD3, 0xCD, 0x81, +- 0x00, 0x7F, 0xBD, 0xDB, 0x04, 0x03, 0x00, 0x64, 0xC9, 0x81, 0xBD, 0xDB, 0xFD, 0x02, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x01, 0x60, 0xA6, 0x62, 0x09, 0x02, +- 0xA2, 0xD9, 0x64, 0x41, 0x32, 0x44, 0x02, 0xB5, 0x00, 0xB9, 0xD4, 0x84, 0x08, 0x28, 0x02, 0xBC, +- 0x40, 0x52, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x01, 0x60, +- 0xB2, 0x62, 0x0C, 0x02, 0xA2, 0xD9, 0x64, 0x41, 0x32, 0x44, 0x40, 0xB5, 0x00, 0xB9, 0xD4, 0x84, +- 0x08, 0x24, 0x03, 0x00, 0x40, 0xBC, 0x02, 0xB5, 0xD4, 0x84, 0x40, 0x52, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x01, 0x60, 0xB0, 0x63, 0xA3, 0xD9, 0xA9, 0xF1, 0x20, 0x61, +- 0x41, 0x4B, 0x64, 0x43, 0xD8, 0xF3, 0x63, 0x45, 0x66, 0x41, 0x65, 0x46, 0x8C, 0xFA, 0x60, 0x40, +- 0x01, 0x36, 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, 0x05, 0x3A, 0x02, 0x00, +- 0x00, 0x64, 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x79, 0xF3, 0x7A, 0xF1, 0xFF, 0xFF, 0xA0, 0x84, +- 0x65, 0x43, 0x02, 0x02, 0x79, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, 0xAE, 0x65, 0xD8, 0xF3, +- 0xFF, 0xFF, 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x04, 0x02, 0xE8, 0x84, +- 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x7B, 0xFB, 0x6F, 0xF0, 0x60, 0x47, 0x90, 0x84, +- 0x6F, 0xFA, 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, +- 0xA4, 0x84, 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x05, 0xDD, 0x81, +- 0xFB, 0x01, 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x66, 0x43, 0x0C, 0xF4, +- 0x2B, 0x41, 0x4D, 0x8B, 0x02, 0xA3, 0xB6, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, +- 0x25, 0xF0, 0x02, 0xA8, 0x00, 0x67, 0x02, 0x02, 0x2D, 0xF9, 0x2C, 0xF9, 0x23, 0x58, 0xFF, 0xFF, +- 0x28, 0x60, 0x42, 0x61, 0x23, 0xF2, 0x25, 0xF2, 0x02, 0xA8, 0x00, 0xA8, 0x09, 0x02, 0x07, 0x03, +- 0xD0, 0xA0, 0x30, 0x65, 0x03, 0x04, 0xA7, 0xA0, 0x59, 0x65, 0x01, 0x06, 0x65, 0x44, 0xA1, 0xDB, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x31, 0x60, 0x2C, 0x61, 0x01, 0x64, 0xA1, 0xDB, 0x04, 0x00, +- 0x31, 0x60, 0x2C, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x7E, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, +- 0x7F, 0x67, 0x02, 0x61, 0x0E, 0x02, 0x06, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0x25, 0x60, 0x11, 0x78, +- 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x01, 0x00, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7E, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, +- 0x02, 0x61, 0x12, 0x02, 0x2D, 0x60, 0x58, 0x61, 0x65, 0x43, 0xA1, 0xDD, 0x0C, 0x61, 0x41, 0x56, +- 0xC7, 0xFE, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, 0x00, 0x7F, +- 0x60, 0x41, 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF0, 0x29, 0x60, +- 0xA2, 0x62, 0xA2, 0xD9, 0x19, 0x00, 0x2D, 0x60, 0x1A, 0x64, 0xA0, 0xD1, 0xA0, 0xF9, 0x0C, 0x60, +- 0x38, 0x62, 0x40, 0x63, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x64, 0x40, 0x01, 0x2A, 0x0C, 0x00, +- 0x04, 0x65, 0x0C, 0x60, 0x38, 0x61, 0x48, 0x64, 0x3E, 0x63, 0x7C, 0xA8, 0x58, 0xD0, 0x59, 0xD9, +- 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x29, 0x60, 0xA2, 0x62, 0xA2, 0xD1, 0x0D, 0x60, +- 0x1C, 0x65, 0x02, 0xFE, 0x64, 0x44, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x87, 0x60, 0x41, 0x64, 0x44, +- 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x84, 0x3E, 0xFB, 0x60, 0x42, 0x61, 0x44, 0x03, 0xA2, 0x60, 0xFE, +- 0xA2, 0xDB, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x44, 0x0C, 0x60, 0x3A, 0x65, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x84, 0x40, 0xFB, 0xFF, 0xFF, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, +- 0xFF, 0xFF, 0x2D, 0x60, 0x1A, 0x64, 0xA0, 0xD1, 0xA0, 0xF9, 0x00, 0x64, 0x40, 0x41, 0x64, 0x40, +- 0x01, 0x2A, 0xA4, 0x00, 0x4A, 0x64, 0xA0, 0xD2, 0xFF, 0xFF, 0x40, 0x42, 0x80, 0x2B, 0x04, 0x00, +- 0xFF, 0xB4, 0x40, 0x42, 0x01, 0x64, 0x40, 0x41, 0xA9, 0xF3, 0x46, 0x4B, 0x60, 0x46, 0x20, 0x63, +- 0xE3, 0x83, 0xAB, 0x46, 0x26, 0xF0, 0xAB, 0x46, 0x55, 0xF8, 0xAB, 0x46, 0x27, 0xF0, 0xAB, 0x46, +- 0x56, 0xF8, 0xAB, 0x46, 0x28, 0xF0, 0xAB, 0x46, 0x57, 0xF8, 0x66, 0x44, 0x02, 0xA6, 0xF1, 0x1F, +- 0xA9, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xAB, 0x46, 0x0C, 0x60, 0x7A, 0x65, 0x22, 0x44, 0xFF, 0xB4, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, 0xC9, 0x81, 0x52, 0x64, 0x0E, 0x63, +- 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF0, 0xA1, +- 0x6E, 0x64, 0x0E, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, 0x22, 0x44, 0xFF, 0xB4, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x0C, 0x60, 0xDC, 0x65, 0xC4, 0x81, 0x60, 0x45, 0xC9, 0x81, +- 0x62, 0x64, 0x06, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, +- 0xAB, 0x46, 0xF8, 0xA1, 0xAE, 0x64, 0x06, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, +- 0x65, 0x44, 0x0C, 0x60, 0xFC, 0x65, 0xC4, 0x81, 0xC9, 0x81, 0x6A, 0x64, 0x06, 0x63, 0x58, 0xD0, +- 0x59, 0xD9, 0xFD, 0x1F, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x84, 0x0C, 0x60, +- 0xC2, 0x65, 0xC4, 0x81, 0x72, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0xAB, 0x46, +- 0x21, 0x44, 0x01, 0x2A, 0x06, 0x00, 0xFA, 0xA1, 0x88, 0x64, 0x04, 0x63, 0x59, 0xD1, 0x58, 0xD8, +- 0xFD, 0x1F, 0x37, 0xF0, 0x21, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x22, 0x44, 0x3D, 0xFB, 0x60, 0x41, +- 0x02, 0xFE, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x84, 0x3C, 0xFB, 0x0C, 0x60, 0xBE, 0x63, 0x88, 0xFF, +- 0xCD, 0x81, 0x06, 0xA3, 0xFD, 0x0D, 0x8D, 0xFF, 0x3B, 0xFD, 0x64, 0x47, 0x80, 0xBF, 0x60, 0x5C, +- 0x22, 0x43, 0x80, 0x61, 0x88, 0xFF, 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, +- 0x31, 0x91, 0xB1, 0x84, 0x37, 0xFA, 0x1F, 0x63, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0x37, 0xF0, +- 0x66, 0x44, 0xB1, 0x9C, 0x37, 0xF8, 0x02, 0xA6, 0xFA, 0x1F, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, +- 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x00, 0x67, 0x22, 0x02, 0x3D, 0xF1, +- 0x64, 0x44, 0x03, 0xB4, 0x40, 0x42, 0xD0, 0x80, 0xA9, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xB7, 0xF4, +- 0x80, 0x61, 0x02, 0x02, 0xE3, 0x83, 0xEB, 0x83, 0x22, 0x44, 0x88, 0xFF, 0xCC, 0x84, 0xE1, 0x81, +- 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0x9D, 0x85, 0xA7, 0x83, 0x37, 0xFC, 0x1F, 0x63, +- 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0xB7, 0xF2, 0x66, 0x44, 0xA5, 0x81, 0xB7, 0xFA, 0x02, 0xA6, +- 0xFA, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x2D, 0x60, 0x1A, 0x64, 0xA0, 0xD1, 0xA0, 0xF9, +- 0x64, 0x40, 0x01, 0x2A, 0x4E, 0x00, 0x27, 0xF2, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, +- 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, +- 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, +- 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, 0x08, 0xFE, 0x60, 0x43, +- 0x61, 0x46, 0x01, 0x03, 0x2A, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x37, 0xF2, 0x80, 0x60, 0x30, 0x7C, +- 0xB0, 0x84, 0xA2, 0xDA, 0x4E, 0x61, 0x6E, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, +- 0x58, 0xD8, 0xFB, 0x1F, 0x88, 0x64, 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, +- 0xFB, 0x1F, 0xD9, 0x81, 0x98, 0x64, 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, +- 0xFB, 0x1F, 0xD9, 0x81, 0xAE, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, +- 0xFB, 0x1F, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, +- 0xFF, 0xFF, 0x2D, 0x60, 0x1A, 0x64, 0xA0, 0xD1, 0xA0, 0xF9, 0x64, 0x40, 0x01, 0x2A, 0x31, 0x00, +- 0x27, 0xF2, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, +- 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, +- 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, +- 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x0D, 0x00, +- 0x43, 0x4B, 0xAB, 0x46, 0x37, 0xF2, 0x80, 0x60, 0x30, 0x61, 0x9D, 0x85, 0xA4, 0x84, 0xA2, 0xDA, +- 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, +- 0xFF, 0xFF, 0xA2, 0xFF, 0x46, 0x45, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0x00, 0xF4, +- 0x01, 0xF2, 0x66, 0x5C, 0x25, 0x46, 0x56, 0x02, 0x70, 0x27, 0x54, 0x00, 0x12, 0x64, 0x03, 0xFA, +- 0x04, 0xF8, 0x0E, 0xF2, 0x87, 0xFC, 0x8D, 0xFC, 0x8E, 0xFC, 0xDA, 0x82, 0x16, 0x61, 0x00, 0x63, +- 0xC9, 0x81, 0x5A, 0xDC, 0xFD, 0x02, 0x60, 0x40, 0xF0, 0x3B, 0x16, 0x00, 0x32, 0x44, 0xAF, 0xF3, +- 0x01, 0xB0, 0xFA, 0xA0, 0x08, 0x24, 0x2C, 0x05, 0xDC, 0x83, 0xF0, 0x67, 0x0E, 0xFA, 0x24, 0x60, +- 0x5E, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xAF, 0xFD, 0x2B, 0xFF, +- 0xFE, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x4F, 0x00, 0xB0, 0xF3, 0x06, 0x65, 0xD4, 0x80, 0xDC, 0x83, +- 0x17, 0x05, 0xB0, 0xFD, 0x98, 0xFE, 0x04, 0x04, 0x00, 0x7F, 0x08, 0x7E, 0x0E, 0xFA, 0x3B, 0xFF, +- 0x24, 0x60, 0x52, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0x0E, 0xF2, +- 0x2B, 0xFF, 0x60, 0x40, 0x08, 0x26, 0xF7, 0xFE, 0xFD, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x32, 0x00, +- 0xAC, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, 0xFF, 0xFF, 0x0D, 0x04, 0x24, 0x60, 0x6A, 0x64, 0x2B, 0xDB, +- 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFC, 0x64, 0x3B, 0x42, +- 0x4A, 0xDB, 0x21, 0x00, 0x46, 0x45, 0x00, 0x64, 0x2B, 0xDB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, 0x70, 0x67, +- 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, 0x80, 0xFC, +- 0x05, 0xFA, 0xAF, 0x60, 0x58, 0x4E, 0x95, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, 0xFF, 0x64, +- 0x3B, 0x42, 0x4A, 0xDB, 0xD4, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x58, 0x64, +- 0x40, 0x47, 0x58, 0x4F, 0x0D, 0x00, 0x24, 0x60, 0x4C, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x18, 0x00, +- 0x24, 0x60, 0x64, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x03, 0x00, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, +- 0x27, 0xD5, 0x0E, 0xF2, 0x0B, 0x18, 0x60, 0x40, 0x01, 0x2A, 0x08, 0x00, 0x24, 0x60, 0x7A, 0x64, +- 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0xF2, 0x01, 0x2F, 0x58, 0xFF, 0xFF, +- 0x27, 0xD5, 0x0E, 0xF2, 0x14, 0x18, 0x60, 0x40, 0x01, 0x2A, 0x11, 0x00, 0x02, 0xF0, 0x09, 0x60, +- 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, 0xB0, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0xB0, 0xFB, 0x24, 0x60, +- 0x7A, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0xE9, 0x01, 0x2F, 0x58, +- 0xFF, 0xFF, 0xFB, 0x64, 0x3A, 0x42, 0x4A, 0xDB, 0xA2, 0xFF, 0xB3, 0xF3, 0xAF, 0xF3, 0xCC, 0x80, +- 0xFD, 0xA0, 0x01, 0x14, 0x1E, 0x05, 0xAE, 0x60, 0x58, 0x4D, 0x9B, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, +- 0x18, 0x03, 0xF0, 0x67, 0x0E, 0xFA, 0x24, 0x60, 0x7A, 0x62, 0x24, 0x60, 0x5E, 0x64, 0xA2, 0xDB, +- 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF6, 0x64, 0x3A, 0x42, +- 0x4A, 0xDB, 0xB3, 0xF3, 0xAF, 0xF3, 0xCC, 0x83, 0xDC, 0x84, 0x01, 0x15, 0xB3, 0xFD, 0xAF, 0xFB, +- 0xD4, 0xFE, 0xB2, 0xF3, 0xB0, 0xF3, 0x00, 0xA8, 0xB1, 0xF1, 0x03, 0x02, 0xD0, 0x80, 0xFF, 0xFF, +- 0x27, 0x05, 0xAE, 0x60, 0x58, 0x4D, 0x9B, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, 0x21, 0x03, 0x00, 0x63, +- 0xB2, 0xF3, 0x0E, 0xFC, 0xCC, 0x84, 0xFF, 0x3A, 0xB2, 0xFB, 0x98, 0xFE, 0x03, 0x04, 0x08, 0xBB, +- 0x0E, 0xFC, 0x3B, 0xFF, 0x24, 0x60, 0x7A, 0x62, 0x24, 0x60, 0x52, 0x64, 0xA2, 0xDB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF7, 0x64, 0x3A, 0x42, 0x4A, 0xDB, +- 0xB0, 0xF3, 0x0E, 0xF2, 0xDC, 0x83, 0x08, 0xB0, 0xB0, 0xFD, 0x08, 0x28, 0xF7, 0xFE, 0xD4, 0xFE, +- 0xA3, 0xFF, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0xB9, 0xFE, 0x13, 0xFF, 0x24, 0x40, 0x80, 0x2B, +- 0x0B, 0x00, 0xA2, 0xFF, 0x25, 0x46, 0x09, 0xF4, 0x0E, 0xF2, 0x05, 0x18, 0x08, 0xBC, 0x0E, 0xFA, +- 0xFF, 0xFF, 0xF7, 0xFE, 0x01, 0x00, 0xD8, 0xFE, 0xA3, 0xFF, 0x25, 0x46, 0x3E, 0xF2, 0x00, 0xF4, +- 0x08, 0xF0, 0x25, 0x46, 0x06, 0xB4, 0xFF, 0x7F, 0x10, 0xBC, 0x06, 0x26, 0xFD, 0x7F, 0x0E, 0xFA, +- 0x3E, 0xF2, 0x3F, 0xF2, 0x60, 0x41, 0x08, 0x2A, 0x64, 0x47, 0x3F, 0xFA, 0x60, 0x45, 0x27, 0x60, +- 0xFC, 0x62, 0xA2, 0xD3, 0xA3, 0xFC, 0xAB, 0xFC, 0x91, 0xFC, 0xD4, 0x80, 0xC0, 0x60, 0xE1, 0x65, +- 0xA5, 0x80, 0x01, 0x04, 0x07, 0x03, 0x23, 0xF0, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x2E, 0x60, +- 0xC5, 0x78, 0xFF, 0xFF, 0x2F, 0x60, 0x58, 0x4F, 0x0F, 0x78, 0xFF, 0xFF, 0x14, 0x04, 0x23, 0xF0, +- 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xB8, 0xF1, 0x27, 0x60, 0x96, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x02, 0x00, +- 0x20, 0x60, 0x00, 0x75, 0x83, 0x00, 0xDC, 0xF3, 0xA9, 0xF1, 0x07, 0xB4, 0x64, 0x43, 0xFD, 0xA0, +- 0x2C, 0xF2, 0x71, 0x02, 0x01, 0xB0, 0x64, 0x43, 0x78, 0x02, 0x2E, 0xF2, 0x1C, 0x60, 0xBA, 0x65, +- 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, +- 0x16, 0x18, 0x61, 0x46, 0x2E, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, +- 0x2D, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2C, 0xF0, 0x63, 0x46, +- 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, +- 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x51, 0x03, 0x63, 0x46, 0x80, 0xF6, 0x25, 0x46, 0x43, 0x18, +- 0x2E, 0xF2, 0x66, 0x41, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xA9, 0xF1, 0xE0, 0x84, +- 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, +- 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, +- 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, +- 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, +- 0x43, 0x4B, 0x2C, 0xF0, 0xAD, 0xF0, 0x2E, 0xF2, 0xAB, 0x46, 0x03, 0xF8, 0x84, 0xF8, 0x05, 0xFA, +- 0x03, 0x64, 0x06, 0xFA, 0xAB, 0x46, 0x1E, 0x60, 0xBC, 0x61, 0xA1, 0xD3, 0x1E, 0x60, 0xFE, 0x7C, +- 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0x49, 0xD3, 0xFF, 0xFF, +- 0xDC, 0x84, 0xA1, 0xDB, 0x0A, 0x00, 0xDC, 0xF3, 0x02, 0xA3, 0xFE, 0xA0, 0xF9, 0xA0, 0x01, 0x06, +- 0x04, 0x02, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x07, 0xFC, 0x23, 0xF2, 0xFF, 0xFF, +- 0x27, 0x1B, 0x27, 0x60, 0xFE, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x00, 0x3A, 0x10, 0x00, +- 0x24, 0x60, 0x7A, 0x62, 0x24, 0x60, 0x22, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xC1, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x1F, 0x00, +- 0x24, 0x60, 0x7A, 0x62, 0x24, 0x60, 0x34, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xC8, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x0F, 0x00, +- 0x24, 0x60, 0x7A, 0x62, 0x24, 0x60, 0x46, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xCE, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x25, 0x60, +- 0x11, 0x78, 0xFF, 0xFF, 0xCB, 0x84, 0xC9, 0x83, 0xFF, 0xFF, 0x08, 0x04, 0x58, 0xD1, 0xA5, 0xD8, +- 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x2F, 0x58, 0xFF, 0xFF, +- 0x3E, 0xF2, 0xCC, 0xF1, 0x08, 0xB0, 0x19, 0xF8, 0x3B, 0x02, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF3, +- 0x30, 0xFA, 0x60, 0x45, 0xED, 0xF3, 0x31, 0xFA, 0x46, 0x4A, 0x00, 0xF4, 0x60, 0x43, 0x05, 0xF2, +- 0x06, 0xF2, 0xD0, 0x80, 0x07, 0xF0, 0x05, 0x02, 0xD4, 0x80, 0xD3, 0x80, 0x02, 0x02, 0xDC, 0xF3, +- 0x03, 0x03, 0xAA, 0x46, 0x42, 0xFE, 0x25, 0x00, 0x60, 0x40, 0x03, 0x2A, 0x10, 0x00, 0x02, 0xF2, +- 0x03, 0xF0, 0x04, 0xF2, 0x60, 0x43, 0xAA, 0x46, 0x2C, 0xFC, 0x2D, 0xF8, 0x2E, 0xFA, 0x81, 0xF1, +- 0x32, 0xF8, 0x82, 0xF1, 0x33, 0xF8, 0x83, 0xF1, 0x34, 0xF8, 0x08, 0x64, 0x10, 0x00, 0x02, 0xF2, +- 0x03, 0xF0, 0x04, 0xF2, 0x60, 0x43, 0xAA, 0x46, 0x32, 0xFC, 0x33, 0xF8, 0x34, 0xFA, 0x81, 0xF1, +- 0x2C, 0xF8, 0x82, 0xF1, 0x2D, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x01, 0x60, 0x08, 0x64, 0x2A, 0xFA, +- 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x03, 0x02, 0x42, 0xFF, +- 0x47, 0xFF, 0xA1, 0xFF, 0x80, 0xFF, 0x90, 0xFF, 0x98, 0xFF, 0x88, 0xFF, 0x84, 0xE1, 0xFF, 0xFF, +- 0x00, 0x00, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, 0x2D, 0x60, 0x9C, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0x01, 0x1B, 0xF7, 0x01, 0x87, 0xFF, 0x20, 0x44, 0x80, 0xFF, 0x60, 0x40, 0x80, 0x26, 0xF1, 0x01, +- 0xC0, 0x60, 0x40, 0xEC, 0xC0, 0x60, 0x00, 0xED, 0xC0, 0x60, 0x80, 0xEE, 0xAC, 0x4F, 0xBF, 0xB4, +- 0xA0, 0x5C, 0x2D, 0x60, 0x1A, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x02, 0x27, 0x06, 0x00, +- 0x28, 0xE2, 0x24, 0xE2, 0xBF, 0xFF, 0xFF, 0xFF, 0x75, 0x40, 0x10, 0x00, 0x28, 0xE2, 0x24, 0xE2, +- 0x00, 0x60, 0x00, 0x61, 0x00, 0x60, 0x94, 0xE0, 0xBF, 0xFF, 0xFF, 0xFF, 0xA1, 0x50, 0x75, 0x40, +- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0xE0, 0x2D, 0x60, 0x9C, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, 0x39, 0xE2, 0x04, 0x60, 0x00, 0x7A, 0xAC, 0x4F, 0x40, 0xBC, +- 0x00, 0x7F, 0xA0, 0x5C, 0xC0, 0x60, 0xD9, 0xEC, 0xC0, 0x60, 0x0F, 0xED, 0xC0, 0x60, 0x8F, 0xEE, +- 0xAE, 0x4F, 0x04, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x26, 0x61, 0xCD, 0x81, 0xFF, 0xFF, 0xFD, 0x02, +- 0xAE, 0x4F, 0xFB, 0xB4, 0xA0, 0x5E, 0xAD, 0x01, 0x80, 0xFF, 0x90, 0xFF, 0x98, 0xFF, 0x2F, 0x60, +- 0x54, 0x63, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, +- 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, +- 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, +- 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, +- 0xBD, 0xDB, 0x2F, 0x60, 0x48, 0x64, 0xA0, 0xDD, 0x30, 0x60, 0x74, 0x63, 0x2F, 0x60, 0x4A, 0x64, +- 0xA0, 0xDD, 0x2F, 0x60, 0x4C, 0x63, 0x30, 0x44, 0xA3, 0xDB, 0x2F, 0x60, 0x4E, 0x63, 0x31, 0x44, +- 0xA3, 0xDB, 0x2F, 0x60, 0x50, 0x63, 0x32, 0x44, 0xA3, 0xDB, 0x2F, 0x60, 0x52, 0x63, 0x33, 0x44, +- 0xA3, 0xDB, 0x81, 0xFF, 0x91, 0xFF, 0x58, 0x51, 0x4B, 0x00, 0x82, 0xFF, 0x92, 0xFF, 0x58, 0x51, +- 0x47, 0x00, 0x83, 0xFF, 0x93, 0xFF, 0x58, 0x51, 0x43, 0x00, 0x84, 0xFF, 0x94, 0xFF, 0x58, 0x51, +- 0x3F, 0x00, 0x85, 0xFF, 0x95, 0xFF, 0x58, 0x51, 0x3B, 0x00, 0x86, 0xFF, 0x96, 0xFF, 0x58, 0x51, +- 0x37, 0x00, 0x87, 0xFF, 0x97, 0xFF, 0x58, 0x51, 0x33, 0x00, 0x80, 0xFF, 0x90, 0xFF, 0x99, 0xFF, +- 0x2F, 0x60, 0x48, 0x64, 0xA0, 0xD1, 0x30, 0x44, 0x64, 0x43, 0xBD, 0xDB, 0x31, 0x44, 0xBD, 0xDB, +- 0x32, 0x44, 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, 0x35, 0x44, 0xBD, 0xDB, +- 0x36, 0x44, 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, 0x39, 0x44, 0xBD, 0xDB, +- 0x3A, 0x44, 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, 0x3D, 0x44, 0xBD, 0xDB, +- 0x3E, 0x44, 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0xEF, 0x60, 0x48, 0x64, 0x0A, 0xFB, 0x40, 0x21, +- 0xFE, 0x01, 0x80, 0xFF, 0x90, 0xFF, 0x98, 0xFF, 0x88, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, +- 0x42, 0x50, 0x40, 0x53, 0x2F, 0x60, 0x4A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x52, 0x33, 0x44, +- 0x32, 0x42, 0xA2, 0xDB, 0xDA, 0x82, 0xA2, 0xDD, 0xDA, 0x83, 0x65, 0x44, 0xBD, 0xDB, 0x61, 0x44, +- 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0xBD, 0xD9, 0x30, 0x44, 0xBD, 0xDB, 0x99, 0xFF, 0xA4, 0x4C, +- 0xBD, 0xDB, 0xA5, 0x4C, 0xBD, 0xDB, 0xA0, 0x4C, 0xBD, 0xDB, 0xA1, 0x4C, 0xBD, 0xDB, 0x98, 0xFF, +- 0x2F, 0x60, 0x4A, 0x64, 0xA0, 0xDD, 0x2F, 0x60, 0x4C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x50, +- 0x2F, 0x60, 0x50, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x52, 0x2F, 0x60, 0x52, 0x62, 0xA2, 0xD3, +- 0xFF, 0xFF, 0x40, 0x53, 0x31, 0x41, 0x2F, 0x60, 0x4E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x40, 0x51, +- 0x2F, 0x60, 0x48, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x43, 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, +- 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, +- 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, +- 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, +- 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, 0x2F, 0x60, 0x48, 0x64, 0xA0, 0xDD, +- 0x61, 0x58, 0xFF, 0xFF, 0x24, 0xE2, 0x2D, 0xF3, 0x2C, 0xF3, 0x00, 0xBD, 0xCC, 0x84, 0x08, 0x03, +- 0x2C, 0xFB, 0x06, 0x02, 0x65, 0x44, 0x2C, 0xFB, 0x8A, 0xFF, 0x80, 0x60, 0x00, 0x75, 0x88, 0xFF, +- 0xF2, 0xF3, 0x31, 0x40, 0x01, 0x2A, 0x44, 0x00, 0x60, 0x43, 0x04, 0xB0, 0x02, 0xB0, 0x08, 0x24, +- 0x16, 0x02, 0x29, 0x44, 0xFF, 0xFF, 0x00, 0xA8, 0xCC, 0x81, 0x0E, 0x03, 0x41, 0x49, 0x37, 0x02, +- 0x63, 0x40, 0x08, 0x2A, 0x09, 0x00, 0xF7, 0xB3, 0x31, 0x60, 0x1E, 0x7C, 0xA4, 0xD1, 0xAD, 0x4F, +- 0xFD, 0xB4, 0xA0, 0x5D, 0x44, 0x49, 0x2B, 0x00, 0x63, 0x40, 0x02, 0x2A, 0x14, 0x00, 0x31, 0x60, +- 0x20, 0x64, 0xA0, 0xD3, 0x31, 0x60, 0x1C, 0x7C, 0xA4, 0xDB, 0x40, 0x49, 0x31, 0x60, 0x22, 0x64, +- 0xA0, 0xD3, 0x31, 0x60, 0x1E, 0x7C, 0xA4, 0xDB, 0x0C, 0xBB, 0xFD, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, +- 0x00, 0x7F, 0xA0, 0x5D, 0x14, 0x00, 0x31, 0x60, 0x24, 0x64, 0xA0, 0xD3, 0x31, 0x60, 0x1C, 0x7C, +- 0x0E, 0x18, 0xA4, 0xDB, 0x40, 0x49, 0x31, 0x60, 0x26, 0x64, 0xA0, 0xD3, 0x31, 0x60, 0x1E, 0x7C, +- 0xA4, 0xDB, 0x08, 0xBB, 0xFB, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0xF2, 0xFD, +- 0x01, 0x60, 0x4E, 0x61, 0xA1, 0xD3, 0x61, 0x43, 0x17, 0x18, 0x58, 0xD3, 0x62, 0x41, 0x03, 0x18, +- 0xCC, 0x84, 0xA1, 0xDB, 0x11, 0x00, 0x49, 0xD3, 0xA3, 0xDB, 0x06, 0xA1, 0xA1, 0xD3, 0x59, 0xD1, +- 0x60, 0x45, 0xA5, 0xD3, 0x59, 0xD1, 0xB0, 0x84, 0xA5, 0xDB, 0x64, 0x44, 0x06, 0x36, 0xCD, 0xFE, +- 0x07, 0x36, 0xD6, 0xFE, 0xE5, 0x01, 0x23, 0x46, 0xB0, 0x60, 0xA4, 0x78, 0xFF, 0xFF, 0x46, 0x43, +- 0x24, 0x60, 0xA4, 0x61, 0xA1, 0xD3, 0x59, 0xD1, 0x06, 0x1B, 0x59, 0xD3, 0x59, 0xD1, 0x03, 0x1B, +- 0x59, 0xD3, 0x59, 0xD1, 0xF0, 0x18, 0x00, 0x63, 0x49, 0xDD, 0x60, 0x40, 0x02, 0x36, 0x11, 0x00, +- 0x03, 0x36, 0x32, 0x00, 0x01, 0x36, 0x08, 0x00, 0x05, 0x3A, 0xEA, 0x01, 0xA4, 0xD3, 0x5A, 0xD3, +- 0x9C, 0x85, 0xA4, 0x84, 0xA2, 0xDB, 0xE4, 0x01, 0x01, 0x60, 0x4E, 0x61, 0x00, 0x64, 0xA1, 0xDB, +- 0xDF, 0x01, 0x31, 0x60, 0x3C, 0x64, 0x40, 0x45, 0x22, 0x00, 0x01, 0x60, 0x4E, 0x66, 0xA6, 0xD3, +- 0x04, 0xA1, 0x60, 0x43, 0xA1, 0xD3, 0xC9, 0x81, 0x60, 0x45, 0x00, 0xBB, 0xA1, 0xDB, 0xBE, 0xD3, +- 0x09, 0x03, 0xD4, 0x84, 0x9C, 0x84, 0xDC, 0x84, 0xFF, 0xFF, 0x04, 0x0E, 0xA3, 0xD1, 0x63, 0x46, +- 0x64, 0x43, 0xF2, 0x01, 0x9C, 0x84, 0xDC, 0x85, 0x49, 0xDD, 0x61, 0x44, 0x00, 0xBB, 0xA6, 0xDB, +- 0x02, 0x03, 0x65, 0x44, 0xBE, 0xDB, 0xBC, 0x01, 0x31, 0x60, 0x17, 0x64, 0x40, 0x45, 0x01, 0x60, +- 0x4E, 0x66, 0xA6, 0xD3, 0xFF, 0xFF, 0xD0, 0x80, 0x0F, 0x18, 0x02, 0x03, 0x60, 0x46, 0xF9, 0x01, +- 0x58, 0xD3, 0xA4, 0xD3, 0x60, 0x45, 0x00, 0x63, 0xA4, 0xDD, 0x05, 0x18, 0x58, 0xD3, 0xFF, 0xFF, +- 0xC4, 0x83, 0xA2, 0xDD, 0xCA, 0x84, 0xA6, 0xDB, 0x25, 0x58, 0x64, 0x41, 0x00, 0x60, 0x46, 0x74, +- 0xCD, 0xE2, 0x04, 0xE1, 0x02, 0x60, 0x00, 0xE1, 0x3F, 0x44, 0x40, 0x26, 0x0B, 0x00, 0x01, 0x2A, +- 0x05, 0x00, 0x42, 0x60, 0x09, 0xE0, 0x60, 0x60, 0x1C, 0xE0, 0x04, 0x00, 0x42, 0x60, 0x09, 0xE0, +- 0x80, 0x60, 0x1C, 0xE0, 0x04, 0x29, 0xFE, 0x01, 0xC4, 0xE2, 0x43, 0x64, 0x3A, 0xDB, 0xA4, 0xF3, +- 0xFF, 0xFF, 0x60, 0x41, 0x3F, 0x44, 0x02, 0x27, 0x84, 0x00, 0x20, 0x2B, 0xFF, 0x01, 0x80, 0xE1, +- 0x95, 0x60, 0x80, 0xE7, 0x61, 0x40, 0x40, 0x2B, 0x0D, 0x00, 0x05, 0x63, 0x32, 0x60, 0x58, 0x4F, +- 0x6A, 0x78, 0xFF, 0xFF, 0x28, 0x63, 0xFF, 0xFF, 0xFE, 0x1F, 0x01, 0x63, 0x32, 0x60, 0x58, 0x4F, +- 0x6A, 0x78, 0xFF, 0xFF, 0xFF, 0xB1, 0xCD, 0x81, 0xE1, 0x85, 0x27, 0x60, 0x3C, 0x64, 0x44, 0xD1, +- 0xFF, 0xFF, 0x64, 0x43, 0x32, 0x60, 0x58, 0x4F, 0x6A, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x00, 0x63, +- 0x32, 0x60, 0x58, 0x4F, 0x6A, 0x78, 0xFF, 0xFF, 0x27, 0x60, 0x58, 0x61, 0x29, 0x60, 0xE8, 0x62, +- 0xA2, 0xD3, 0x45, 0xD1, 0x47, 0xBC, 0xE0, 0x84, 0x62, 0x45, 0x64, 0x5F, 0xE8, 0x83, 0x32, 0x60, +- 0x58, 0x4F, 0x6A, 0x78, 0xFF, 0xFF, 0xA3, 0xF3, 0xCD, 0xE2, 0x60, 0x54, 0x04, 0xE1, 0x04, 0x29, +- 0xFE, 0x01, 0xC4, 0xE2, 0x15, 0x60, 0xA2, 0xE7, 0x38, 0x69, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x16, +- 0xFD, 0x01, 0x01, 0x2A, 0x36, 0x00, 0x03, 0x60, 0x80, 0x7C, 0xA3, 0x83, 0x29, 0x60, 0xE8, 0x62, +- 0xA2, 0xD1, 0x43, 0xBB, 0xB3, 0x83, 0x95, 0x60, 0x80, 0xE7, 0x32, 0x60, 0x58, 0x4F, 0x6A, 0x78, +- 0xFF, 0xFF, 0xE3, 0x83, 0x15, 0x60, 0xA2, 0xE7, 0x38, 0x69, 0xFF, 0xFF, 0x68, 0x41, 0x01, 0x16, +- 0xFD, 0x01, 0x63, 0x47, 0x61, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x00, 0x3A, 0xCC, 0x84, 0x02, 0x00, +- 0x07, 0x3A, 0xDC, 0x84, 0xFF, 0xB4, 0xA5, 0xDB, 0x60, 0x47, 0xE8, 0x84, 0x47, 0x65, 0x29, 0x60, +- 0xE8, 0x62, 0xA2, 0xD3, 0xB4, 0x85, 0xB4, 0x83, 0x80, 0xE1, 0x95, 0x60, 0x80, 0xE7, 0x32, 0x60, +- 0x58, 0x4F, 0x6A, 0x78, 0xFF, 0xFF, 0xA3, 0xF3, 0xCD, 0xE2, 0x60, 0x54, 0x04, 0x29, 0xFE, 0x01, +- 0xC4, 0xE2, 0xA4, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x2B, 0x04, 0x00, 0x32, 0x60, 0x43, 0x78, +- 0xFF, 0xFF, 0xFF, 0x01, 0xA4, 0xF3, 0x80, 0xE1, 0xCC, 0x84, 0xE0, 0x85, 0x15, 0x60, 0xA2, 0xE7, +- 0x26, 0x60, 0x78, 0x64, 0x58, 0x4F, 0x4F, 0x00, 0x26, 0x60, 0x94, 0x64, 0x58, 0x4F, 0x4B, 0x00, +- 0x26, 0x60, 0xB0, 0x64, 0x58, 0x4F, 0x47, 0x00, 0x26, 0x60, 0xCC, 0x64, 0x58, 0x4F, 0x43, 0x00, +- 0x26, 0x60, 0xE8, 0x64, 0x58, 0x4F, 0x3F, 0x00, 0x27, 0x60, 0x04, 0x64, 0x58, 0x4F, 0x3B, 0x00, +- 0x27, 0x60, 0x20, 0x64, 0x58, 0x4F, 0x37, 0x00, 0x01, 0x68, 0xFF, 0x6A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x3F, 0x44, 0x20, 0x27, 0x00, 0x00, 0x3F, 0x40, 0x40, 0x26, 0x08, 0x00, 0x00, 0x60, +- 0x18, 0x64, 0x00, 0x60, 0x00, 0x65, 0x94, 0x84, 0xA0, 0x50, 0x1D, 0x60, 0x19, 0xE2, 0xC4, 0xE2, +- 0x00, 0x63, 0xA3, 0xFD, 0x32, 0x7B, 0x4D, 0xE2, 0xBF, 0xFE, 0xC4, 0xE2, 0x41, 0xFF, 0xE0, 0xFE, +- 0xE1, 0xFE, 0xE2, 0xFE, 0x43, 0xFF, 0x44, 0xFF, 0x46, 0xFF, 0xA5, 0xF3, 0x62, 0xFF, 0x60, 0x40, +- 0x05, 0x36, 0x2D, 0xFF, 0x07, 0x36, 0xD5, 0xFE, 0x08, 0xE1, 0x88, 0x60, 0x85, 0x71, 0x8D, 0xE2, +- 0xA2, 0x60, 0x16, 0x78, 0xFF, 0xFF, 0x50, 0xEC, 0x63, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x40, 0xEC, 0x2F, 0x58, 0xFF, 0xFF, 0x44, 0xD3, 0x80, 0x7C, 0x60, 0x48, 0x60, 0x47, 0x00, 0x7F, +- 0xB0, 0x8A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0x42, 0xFF, 0x40, 0xFF, +- 0xDD, 0xFE, 0xAD, 0x4F, 0x00, 0x7F, 0x01, 0xBC, 0xA0, 0x5D, 0x00, 0xEE, 0x19, 0x61, 0xCD, 0x81, +- 0xFF, 0xFF, 0xFD, 0x02, 0x43, 0x45, 0x20, 0x44, 0x60, 0xBC, 0x40, 0x40, 0x02, 0x60, 0xEE, 0x63, +- 0x7F, 0xF3, 0xA3, 0xFD, 0x40, 0x7F, 0xA4, 0xFB, 0x05, 0x64, 0xA5, 0xFB, 0xDF, 0xFE, 0x19, 0xFF, +- 0x24, 0x60, 0xDD, 0x64, 0x3F, 0x40, 0x01, 0x2B, 0x02, 0x00, 0x32, 0x60, 0xA2, 0x64, 0xA6, 0xFB, +- 0xBB, 0x60, 0x20, 0x78, 0xFF, 0xFF, 0x04, 0xEE, 0xAD, 0x4F, 0x00, 0x7F, 0x01, 0xBC, 0xA0, 0x5D, +- 0x19, 0x61, 0xCD, 0x81, 0xFF, 0xFF, 0xFD, 0x02, 0xAD, 0x4F, 0x00, 0x7F, 0x01, 0xBC, 0xA0, 0x5D, +- 0x00, 0xEE, 0x15, 0x60, 0xA2, 0xE7, 0x25, 0x60, 0x02, 0x63, 0x25, 0x60, 0x76, 0x65, 0xDF, 0xFE, +- 0x80, 0xE1, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, 0x00, 0x7F, 0x60, 0x4A, +- 0xD7, 0x80, 0xA1, 0xFF, 0xFF, 0xFF, 0xF5, 0x02, 0x25, 0x60, 0x76, 0x63, 0x26, 0x60, 0x78, 0x65, +- 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, 0x00, 0x7F, 0x60, 0x4A, 0xD7, 0x80, +- 0xA1, 0xFF, 0xFF, 0xFF, 0xF5, 0x02, 0x3F, 0x40, 0x20, 0x2B, 0x00, 0x00, 0x01, 0x68, 0xFF, 0x6A, +- 0xBF, 0xFE, 0x33, 0x60, 0x8A, 0x78, 0xFF, 0xFF, 0x3F, 0x40, 0x20, 0x2B, 0xAD, 0x00, 0x01, 0x16, +- 0xFE, 0x01, 0x38, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x2A, 0xA5, 0x00, 0x27, 0x60, +- 0xB4, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x7F, 0xF1, +- 0x80, 0x60, 0x00, 0x64, 0xB0, 0x9C, 0x01, 0x00, 0x7F, 0xF1, 0xDD, 0xFE, 0xAD, 0x4F, 0x00, 0x7F, +- 0x01, 0xBC, 0xA0, 0x5D, 0x00, 0xEE, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x02, 0x60, +- 0xEE, 0x64, 0xA3, 0xFB, 0xA4, 0xF9, 0x05, 0x64, 0xA5, 0xFB, 0xDF, 0xFE, 0x19, 0xFF, 0x83, 0x00, +- 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x43, 0x45, 0xA4, 0xD1, 0xDA, 0x83, 0xC3, 0x85, 0x80, 0xE1, +- 0xDF, 0xFE, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, 0x80, 0xBC, 0x00, 0x7F, 0x60, 0x4A, +- 0xD7, 0x80, 0xA1, 0xFF, 0xF6, 0x02, 0xBF, 0xFE, 0x6E, 0x00, 0x3F, 0x40, 0x40, 0x26, 0x13, 0x00, +- 0x0B, 0x60, 0xF8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x10, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xF8, 0xA2, +- 0xA2, 0xD1, 0x0A, 0x60, 0x19, 0x64, 0x90, 0x84, 0xA0, 0x52, 0x06, 0xA2, 0xA2, 0xD1, 0x46, 0x60, +- 0x09, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xAD, 0x4F, 0xFE, 0xB4, 0xA0, 0x5D, 0xAD, 0x4F, 0xFD, 0xB4, +- 0xA0, 0x5D, 0x02, 0xEE, 0xBD, 0xFE, 0x50, 0x00, 0x80, 0xE1, 0x01, 0x16, 0xFE, 0x01, 0x64, 0x48, +- 0x92, 0x6A, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x40, 0x27, 0x60, 0xA2, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x3F, 0x00, 0x80, 0xE1, 0x01, 0x16, 0xFE, 0x01, +- 0x01, 0x68, 0xA7, 0x6A, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x40, 0x36, 0x00, 0x20, 0x44, 0x20, 0xBC, +- 0x40, 0x40, 0x80, 0xE1, 0x64, 0x46, 0x01, 0x16, 0xFE, 0x01, 0x21, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x68, 0x5E, 0x01, 0x16, 0xFE, 0x01, 0x22, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x5F, 0x26, 0xFA, +- 0x1C, 0xF2, 0x01, 0x16, 0xFE, 0x01, 0x3A, 0x69, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x5F, 0x27, 0xFA, +- 0x1B, 0x00, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x43, 0x45, 0xBE, 0xD5, 0xA4, 0xD2, 0x5A, 0x86, +- 0xEF, 0xA0, 0x11, 0x61, 0x01, 0x06, 0x60, 0x41, 0x24, 0x60, 0xE0, 0x63, 0x80, 0xE1, 0xBD, 0xD3, +- 0x26, 0x42, 0x01, 0x16, 0xFE, 0x01, 0x60, 0x49, 0xA1, 0xFF, 0xFF, 0xFF, 0x68, 0x44, 0xCD, 0x81, +- 0xA2, 0xDA, 0x5A, 0x86, 0xF4, 0x02, 0x25, 0x43, 0x21, 0xE1, 0x00, 0x64, 0xBF, 0xDB, 0x20, 0x44, +- 0x20, 0x2A, 0x07, 0x00, 0x07, 0xB4, 0x04, 0x36, 0xC3, 0xFE, 0x06, 0x36, 0xCC, 0xFE, 0x07, 0x36, +- 0xD5, 0xFE, 0x20, 0x44, 0xD8, 0xB4, 0x40, 0x40, 0x20, 0x44, 0x40, 0x2A, 0x07, 0x00, 0x9F, 0xFE, +- 0x1E, 0x05, 0xBF, 0xB4, 0x40, 0x40, 0xA6, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x24, 0x60, 0x80, 0x63, +- 0xBD, 0xD3, 0x02, 0x61, 0x17, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x02, 0x61, 0x13, 0x1B, 0x04, 0xA3, +- 0xBD, 0xD3, 0x02, 0x61, 0x0F, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x04, 0x61, 0x0B, 0x1B, 0x04, 0xA3, +- 0xBD, 0xD3, 0x06, 0x61, 0x07, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x07, 0x61, 0x03, 0x1B, 0xBB, 0x60, +- 0x20, 0x78, 0xFF, 0xFF, 0xA3, 0xD1, 0x40, 0x44, 0x20, 0x44, 0x07, 0xB5, 0xD4, 0x85, 0x35, 0x80, +- 0x24, 0x45, 0x24, 0x60, 0xBC, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xE1, 0x43, 0x45, +- 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x64, 0x43, 0xBD, 0xD3, 0xBD, 0xD1, 0x40, 0x44, 0x10, 0x27, +- 0x10, 0x00, 0xFF, 0x60, 0x7F, 0x65, 0x15, 0x60, 0xA2, 0x64, 0x24, 0x40, 0x08, 0x2B, 0xA4, 0x84, +- 0xA0, 0x57, 0xFF, 0xFF, 0x64, 0x49, 0xFF, 0xFF, 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, 0x00, 0x7F, +- 0xA3, 0xDB, 0xA1, 0x01, 0x80, 0xE1, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x64, 0x43, +- 0xBD, 0xD3, 0xBD, 0xD1, 0x40, 0x44, 0x10, 0x2B, 0x11, 0x00, 0xA3, 0xD3, 0xFF, 0xFF, 0x15, 0x60, +- 0x80, 0xE7, 0x24, 0x40, 0x07, 0x27, 0x02, 0x00, 0x50, 0xEC, 0x00, 0x00, 0x60, 0x4A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x24, 0x40, 0x20, 0x2B, 0x40, 0xEC, 0x0F, 0x00, 0x15, 0x60, 0x22, 0x64, +- 0x24, 0x40, 0x08, 0x27, 0x80, 0xBC, 0xA3, 0xD3, 0xA0, 0x57, 0x60, 0x48, 0x64, 0x44, 0x80, 0xBC, +- 0xFF, 0xB4, 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x75, 0x01, 0x42, 0x6F, 0x6F, 0x74, +- 0x63, 0x6F, 0x64, 0x65, 0x20, 0x21, 0x21, 0x20, 0x20, 0x00, 0x53, 0x54, 0x41, 0x2F, 0x41, 0x50, +- 0x20, 0x46, 0x75, 0x6E, 0x63, 0x27, 0x73, 0x00, 0x1F, 0x00, 0x03, 0x00, 0x02, 0x00, 0x24, 0x00, +- 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, +- 0x06, 0x00, 0x07, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x07, 0x00, +- 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, +- 0x02, 0x00, 0x40, 0x00, 0x32, 0x00, 0x32, 0x00, 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x40, 0x00, +- 0x32, 0x00, 0x36, 0x00, 0x0A, 0x00, 0x02, 0x00, 0x06, 0x00, 0x40, 0x00, 0x3B, 0x00, 0x40, 0x00, +- 0x17, 0x00, 0x07, 0x00, 0x07, 0x00, 0x4A, 0x00, 0x40, 0x00, 0x4A, 0x00, 0x1E, 0x00, 0x0C, 0x00, +- 0x08, 0x00, 0x57, 0x00, 0x4D, 0x00, 0x57, 0x00, 0x2B, 0x00, 0x19, 0x00, 0x08, 0x00, 0x5D, 0x00, +- 0x53, 0x00, 0x5D, 0x00, 0x31, 0x00, 0x1F, 0x00, 0x08, 0x00, 0xA9, 0xF3, 0x21, 0x61, 0x00, 0x7C, +- 0x01, 0x00, 0x00, 0xFA, 0x60, 0x46, 0xFE, 0x63, 0xA3, 0xD8, 0xFE, 0x1F, 0xCD, 0x81, 0xD8, 0x84, +- 0xF8, 0x02, 0x21, 0x61, 0x80, 0x67, 0x40, 0x4A, 0xA9, 0xF5, 0x14, 0x60, 0x02, 0x65, 0x01, 0x7C, +- 0x07, 0x18, 0x2A, 0x43, 0x02, 0xFC, 0x5F, 0x8A, 0x8E, 0xF8, 0x70, 0xF8, 0x00, 0xF4, 0xF8, 0x01, +- 0x2E, 0x58, 0xFF, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x0A, 0x00, 0x42, 0x60, 0x09, 0xE0, 0x3F, 0x40, +- 0x01, 0x2A, 0x03, 0x00, 0x60, 0x60, 0x1C, 0xE0, 0x02, 0x00, 0x80, 0x60, 0x1C, 0xE0, 0x40, 0xEC, +- 0x00, 0xED, 0x02, 0xEE, 0x80, 0x60, 0x58, 0xEC, 0x80, 0x60, 0x00, 0xED, 0x80, 0x60, 0x82, 0xEE, +- 0xC0, 0x60, 0x59, 0xEC, 0xC0, 0x60, 0x07, 0xED, 0xAD, 0x4F, 0xFE, 0xB4, 0xA0, 0x5D, 0x00, 0xF3, +- 0x28, 0xFB, 0x40, 0x44, 0x2F, 0x60, 0x52, 0x7C, 0x20, 0xF9, 0xA2, 0x60, 0x00, 0x7C, 0x21, 0xF9, +- 0xA2, 0x60, 0xE0, 0x7C, 0x22, 0xF9, 0x18, 0x60, 0x97, 0x7C, 0x23, 0xF9, 0x18, 0x60, 0xA8, 0x7C, +- 0x24, 0xF9, 0x18, 0x60, 0xD2, 0x7C, 0x25, 0xF9, 0x18, 0x60, 0xE3, 0x7C, 0x26, 0xF9, 0x91, 0x60, +- 0x00, 0xE8, 0x28, 0xE8, 0x44, 0x60, 0x02, 0xE6, 0x10, 0x67, 0x40, 0x52, 0x10, 0x60, 0x04, 0xE6, +- 0x08, 0x60, 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, 0xBD, 0xD3, 0x02, 0xA8, 0xD4, 0x80, +- 0x4A, 0x02, 0x49, 0x02, 0xDB, 0x83, 0xFA, 0x60, 0x27, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, 0x1A, 0x18, +- 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xDB, 0x83, 0xD3, 0x83, 0xD3, 0x86, 0x64, 0x41, +- 0xCD, 0x81, 0xA6, 0xD1, 0xDA, 0x86, 0x25, 0x60, 0x02, 0x65, 0x00, 0x60, 0x72, 0x63, 0xA5, 0xD3, +- 0xDA, 0x85, 0x90, 0x84, 0xFF, 0x27, 0x02, 0x00, 0xA2, 0xD9, 0x01, 0x00, 0xF8, 0x1F, 0xCD, 0x81, +- 0xFF, 0xFF, 0xEF, 0x02, 0x08, 0x60, 0x06, 0x63, 0xFA, 0x60, 0x28, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, +- 0x0B, 0x18, 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xBF, 0xD3, 0x29, 0x60, 0xE8, 0x62, +- 0x0E, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0xA2, 0xDB, 0x08, 0x60, 0x06, 0x63, 0xFD, 0x60, 0x0C, 0x65, +- 0x5B, 0xD3, 0xBF, 0xD1, 0x10, 0x18, 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xFA, 0xA3, +- 0xA3, 0xD3, 0x02, 0x60, 0x00, 0x65, 0xF7, 0xA0, 0xFC, 0xA0, 0x0D, 0x05, 0x04, 0x05, 0x78, 0x43, +- 0x02, 0x61, 0x24, 0x60, 0xDD, 0x78, 0x21, 0x60, 0x00, 0x65, 0x3F, 0x43, 0x3F, 0x43, 0x21, 0x60, +- 0x00, 0x65, 0xC0, 0x60, 0x8F, 0xEE, 0xB7, 0x84, 0x40, 0x5F, 0x00, 0x60, 0x30, 0xE2, 0x00, 0x60, +- 0x50, 0xE2, 0x00, 0x60, 0x79, 0xE2, 0x00, 0x60, 0x90, 0xE2, 0x01, 0x60, 0xD0, 0xE2, 0x01, 0x60, +- 0xF0, 0xE2, 0x01, 0x60, 0xB0, 0xE2, 0x26, 0x64, 0x35, 0xFB, 0x01, 0x60, 0x30, 0x64, 0x0A, 0xA4, +- 0x38, 0xFB, 0x60, 0x45, 0x00, 0x60, 0xF8, 0x64, 0x0A, 0xA4, 0x39, 0xFB, 0x35, 0xF1, 0x0A, 0x64, +- 0xC4, 0x84, 0x36, 0xFB, 0xC0, 0x84, 0x0A, 0xA4, 0x37, 0xFB, 0x09, 0x60, 0x2A, 0x64, 0xB9, 0xFB, +- 0x82, 0xFF, 0x92, 0xFF, 0x5C, 0x41, 0x5C, 0x46, 0x5C, 0x47, 0x00, 0xE1, 0xA3, 0x60, 0x4B, 0x63, +- 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x87, 0xFF, 0x97, 0xFF, 0x0C, 0x60, 0x02, 0x64, 0x40, 0x5A, +- 0x06, 0xA4, 0x40, 0x5B, 0x5C, 0x5E, 0x5C, 0x51, 0x28, 0x60, 0x44, 0x62, 0xA2, 0xD3, 0x7F, 0xFB, +- 0x2D, 0x60, 0xCC, 0x61, 0x27, 0x7C, 0xA1, 0xD9, 0x6D, 0x60, 0x1C, 0x63, 0x7F, 0xA3, 0xE3, 0x87, +- 0x00, 0x7F, 0xAA, 0xFB, 0x02, 0x60, 0x7F, 0x64, 0x00, 0x60, 0x42, 0x65, 0xD4, 0x84, 0xAB, 0xFB, +- 0xDC, 0x84, 0xA9, 0xFB, 0x24, 0x60, 0x0E, 0x62, 0xA2, 0xDB, 0x34, 0x60, 0x58, 0x4E, 0x64, 0x78, +- 0xFF, 0xFF, 0xAB, 0xF1, 0xAA, 0xF3, 0x7C, 0x63, 0xAD, 0xFB, 0x60, 0x46, 0x01, 0xFC, 0xDC, 0x84, +- 0xD0, 0x80, 0x00, 0xFA, 0xFA, 0x04, 0xAE, 0xFB, 0x60, 0x46, 0x00, 0x64, 0x00, 0xFA, 0x63, 0x44, +- 0x80, 0x7F, 0x01, 0xFA, 0xAB, 0xF3, 0xAA, 0xF1, 0xDC, 0x84, 0xD0, 0x84, 0xAC, 0xFB, 0x03, 0x60, +- 0x26, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xB1, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x2E, 0xFB, 0x82, 0xFF, +- 0x40, 0x42, 0x87, 0xFF, 0xAC, 0xF3, 0xB4, 0xFB, 0x08, 0x60, 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, +- 0xBD, 0xD3, 0xA3, 0xD3, 0x02, 0xA8, 0xD4, 0x80, 0x24, 0x02, 0x23, 0x02, 0x2D, 0x60, 0x1A, 0x62, +- 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x80, 0x26, 0x1C, 0x00, 0x04, 0xA3, 0xFD, 0x60, 0x0D, 0x65, +- 0x5B, 0xD3, 0xBF, 0xD1, 0x16, 0x18, 0xC3, 0x83, 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xBF, 0xD3, +- 0xAD, 0x49, 0xFE, 0xA0, 0x00, 0x64, 0x0E, 0x04, 0x08, 0xB1, 0x20, 0xBC, 0x08, 0x28, 0x18, 0xBC, +- 0x1C, 0x60, 0xB8, 0x63, 0x07, 0x7C, 0xA3, 0xD9, 0x1C, 0x60, 0xB6, 0x63, 0x05, 0x7C, 0xA3, 0xD9, +- 0x01, 0x00, 0x00, 0x64, 0x1C, 0x60, 0xB4, 0x63, 0xA3, 0xDB, 0x00, 0x64, 0x40, 0x50, 0x63, 0xFF, +- 0x60, 0xFF, 0x66, 0xFF, 0x65, 0xFF, 0x64, 0xFF, 0x61, 0xFF, 0x62, 0xFF, 0x49, 0x60, 0x02, 0xE1, +- 0x52, 0x60, 0x02, 0xE1, 0x5B, 0x60, 0x02, 0xE1, 0x65, 0x60, 0x02, 0xE1, 0x6C, 0x60, 0x02, 0xE1, +- 0x76, 0x60, 0x02, 0xE1, 0x41, 0x60, 0x02, 0xE1, 0x04, 0x65, 0x2D, 0x60, 0x18, 0x64, 0x44, 0xD3, +- 0xEF, 0x60, 0x58, 0x4E, 0xBD, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x9E, 0x65, 0x0C, 0x64, 0xA5, 0xDB, +- 0x36, 0x60, 0x1E, 0x64, 0xA1, 0xFB, 0x2D, 0xFF, 0x06, 0x61, 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, +- 0xAE, 0x60, 0x58, 0x4D, 0xB1, 0x78, 0xFF, 0xFF, 0xF0, 0x67, 0x0E, 0xFA, 0x24, 0x60, 0x7A, 0x62, +- 0x24, 0x60, 0x5E, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x2B, 0x41, 0x4D, 0x8B, 0xFF, 0xFF, 0xE9, 0x02, 0x06, 0x61, 0x41, 0x4B, 0x09, 0x60, +- 0x08, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xB1, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x7A, 0x62, 0x24, 0x60, +- 0x52, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0x2B, 0x41, 0x4D, 0x8B, 0xFF, 0xFF, 0xEB, 0x02, 0x19, 0x60, 0x17, 0x78, 0xFF, 0xFF, 0x00, 0xEA, +- 0x00, 0xEB, 0x50, 0x60, 0x03, 0xEA, 0x51, 0x60, 0x13, 0xEA, 0x52, 0x60, 0x30, 0xEA, 0x53, 0x60, +- 0x40, 0xEA, 0x54, 0x60, 0x52, 0xEA, 0x55, 0x60, 0x6D, 0xEA, 0x56, 0x60, 0x71, 0xEA, 0x57, 0x60, +- 0x8B, 0xEA, 0x58, 0x60, 0x47, 0xEA, 0x59, 0x60, 0xA0, 0xEA, 0x5A, 0x60, 0xB2, 0xEA, 0x5B, 0x60, +- 0xC1, 0xEA, 0x5C, 0x60, 0xD7, 0xEA, 0x5D, 0x60, 0xEB, 0xEA, 0x5E, 0x60, 0xA0, 0xEA, 0x50, 0x60, +- 0x36, 0xEB, 0x51, 0x60, 0x37, 0xEB, 0x52, 0x60, 0x20, 0xEB, 0x53, 0x60, 0xE4, 0xEB, 0x54, 0x60, +- 0x34, 0xEB, 0x55, 0x60, 0x58, 0xEB, 0x56, 0x60, 0x48, 0xEB, 0x57, 0x60, 0xD0, 0xEB, 0x58, 0x60, +- 0xC3, 0xEB, 0x59, 0x60, 0xFC, 0xEB, 0x5A, 0x60, 0x34, 0xEB, 0x5B, 0x60, 0x58, 0xEB, 0x5C, 0x60, +- 0xC0, 0xEB, 0x5D, 0x60, 0xD0, 0xEB, 0x5E, 0x60, 0x91, 0xEB, 0x00, 0xEA, 0x00, 0xEB, 0xE0, 0x60, +- 0x02, 0xEA, 0xE0, 0x60, 0x03, 0xEB, 0xA0, 0x60, 0x00, 0xEB, 0xB0, 0x60, 0x00, 0xEB, 0xAB, 0x48, +- 0x40, 0x3B, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xEB, 0x03, 0x60, 0x02, 0x62, 0x62, 0x44, 0xA2, 0xDB, +- 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, +- 0x00, 0xEA, 0x3F, 0x40, 0x40, 0x26, 0x08, 0x00, 0x00, 0x60, 0x18, 0x64, 0x00, 0x60, 0x00, 0x65, +- 0x94, 0x84, 0xA0, 0x50, 0x1D, 0x60, 0x19, 0xE2, 0x24, 0x44, 0xFF, 0xB4, 0x04, 0xFB, 0x50, 0x60, +- 0x00, 0x64, 0x05, 0xFB, 0x10, 0x60, 0x10, 0x75, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0x3F, 0x41, +- 0xA5, 0x4C, 0x50, 0x37, 0x04, 0x00, 0x01, 0xB9, 0x41, 0x5F, 0xB5, 0x60, 0x55, 0xE0, 0x0C, 0x60, +- 0x10, 0x62, 0xA2, 0xD3, 0x01, 0x60, 0x01, 0x65, 0xD4, 0x80, 0x5A, 0xD1, 0x0F, 0x02, 0x5A, 0xD3, +- 0x3C, 0x60, 0x00, 0x66, 0xE0, 0x87, 0x40, 0x4A, 0x68, 0x60, 0x28, 0x61, 0x64, 0x44, 0xC8, 0x84, +- 0x0C, 0x63, 0xAA, 0x46, 0x58, 0xD0, 0xAA, 0x46, 0x59, 0xD8, 0xFB, 0x1F, 0x08, 0x60, 0x00, 0x63, +- 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, 0xA3, 0xD3, 0x02, 0xA8, 0xD4, 0x80, 0x61, 0x02, 0x60, 0x02, +- 0x6E, 0x60, 0x58, 0x61, 0x3C, 0x60, 0x00, 0x66, 0x41, 0x4B, 0x2B, 0x41, 0x6E, 0x60, 0xA0, 0x7C, +- 0xD1, 0x80, 0xA1, 0xD2, 0x25, 0x05, 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, 0xE0, 0x87, +- 0x40, 0x4A, 0x59, 0xD2, 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, +- 0xEC, 0x18, 0xD4, 0x80, 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x67, 0x44, +- 0xC0, 0x84, 0xE0, 0x85, 0x2C, 0x44, 0xD4, 0x80, 0x63, 0x41, 0x01, 0x06, 0x65, 0x44, 0xC8, 0x83, +- 0xAA, 0x46, 0x59, 0xD1, 0x27, 0xD8, 0x5A, 0x87, 0xFC, 0x1F, 0xAA, 0x46, 0x2B, 0x41, 0xD5, 0x01, +- 0x6E, 0x60, 0xA0, 0x61, 0x41, 0x4B, 0x2B, 0x41, 0x6E, 0x60, 0xD8, 0x7C, 0xD1, 0x80, 0xA1, 0xD2, +- 0x27, 0x05, 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, 0xE0, 0x87, 0x40, 0x4A, 0x59, 0xD2, +- 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, 0xEC, 0x18, 0xD4, 0x80, +- 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x04, 0xA3, 0xA3, 0xD1, 0x5A, 0x88, +- 0x2C, 0x43, 0xD3, 0x80, 0xFF, 0xFF, 0x01, 0x06, 0x64, 0x43, 0xCF, 0x83, 0xAA, 0x46, 0x60, 0xFE, +- 0x28, 0xD1, 0x5E, 0x88, 0x27, 0xD8, 0x5A, 0x87, 0xFB, 0x1F, 0x20, 0xFE, 0xAA, 0x46, 0xD3, 0x01, +- 0xB8, 0xFE, 0xB9, 0xFE, 0xBA, 0xFE, 0xBB, 0xFE, 0xBD, 0xFE, 0xBF, 0xFE, 0x2D, 0x60, 0x1A, 0x62, +- 0xA2, 0xD3, 0x12, 0x63, 0x60, 0x40, 0x01, 0x27, 0x05, 0x00, 0x0B, 0x60, 0xEA, 0x62, 0x00, 0x64, +- 0x5A, 0xDB, 0xFE, 0x1F, 0x34, 0x60, 0x81, 0x78, 0xFF, 0xFF, 0xF1, 0xFF, 0xF6, 0x6C, 0x1E, 0x00, +- 0x04, 0x00, 0xF2, 0xFF, 0xFA, 0x6C, 0x1E, 0x00, 0x04, 0x00, 0xFB, 0xFF, 0x02, 0x6D, 0x1E, 0x00, +- 0x04, 0x00, 0xF1, 0xFF, 0x8C, 0x64, 0x1E, 0x00, 0x04, 0x00, 0xF2, 0xFF, 0x90, 0x64, 0x1E, 0x00, +- 0x04, 0x00, 0xFB, 0xFF, 0x98, 0x64, 0x1E, 0x00, 0x04, 0x00, 0x86, 0xFD, 0x50, 0x28, 0x00, 0x00, +- 0x06, 0x00, 0x10, 0xFD, 0x74, 0x01, 0x00, 0x00, 0x02, 0x00, 0x14, 0xFD, 0x18, 0x2D, 0x00, 0x00, +- 0x0A, 0x00, 0x20, 0xFA, 0x94, 0x26, 0x00, 0x00, 0x0E, 0x00, 0x21, 0xFA, 0x78, 0x26, 0x00, 0x00, +- 0x0E, 0x00, 0x22, 0xFA, 0xB0, 0x26, 0x00, 0x00, 0x0E, 0x00, 0x23, 0xFA, 0x64, 0x25, 0x00, 0x00, +- 0x01, 0x00, 0x24, 0xFA, 0x58, 0x27, 0x00, 0x00, 0x0E, 0x00, 0x25, 0xFA, 0x78, 0x25, 0x00, 0x00, +- 0x80, 0x00, 0x26, 0xFA, 0x5E, 0x25, 0x00, 0x00, 0x01, 0x00, +- +-}; /* fw_image_3_data */ +- +-static const hcf_8 fw_image_4_data[] = { +- 0xA2, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA2, 0x60, 0xC3, 0x78, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA2, 0x60, 0xC9, 0x78, 0xC4, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA2, 0x60, 0x19, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x44, 0xFF, 0x20, 0x54, 0xCD, 0xE2, 0xA2, 0x60, 0xDB, 0x78, 0x08, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA2, 0x60, 0xDD, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA2, 0x60, 0xDD, 0x78, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA2, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA8, 0x60, 0x73, 0x78, 0x4C, 0x4E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA7, 0x60, 0xFB, 0x78, 0x4C, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC4, 0xE2, 0x84, 0xFF, 0x22, 0x58, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA3, 0x60, 0x7E, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xE4, 0xE2, 0xA8, 0x60, 0x14, 0x78, 0xB5, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBA, 0x60, 0xCE, 0x78, 0x64, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA8, 0x60, 0x87, 0x78, 0xA4, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA8, 0x60, 0x55, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAE, 0x60, 0x1E, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAE, 0x60, 0x4B, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAC, 0x60, 0xD8, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAD, 0x60, 0x08, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAD, 0x60, 0x08, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAF, 0x60, 0xC0, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAD, 0x60, 0x0B, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0x60, 0x83, 0x64, 0x80, 0x29, 0x09, 0xFB, 0xAD, 0x60, 0xE6, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x31, 0x60, 0x16, 0x78, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x30, 0x60, 0xA1, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB9, 0x60, 0x4B, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB8, 0x60, 0xBB, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB0, 0x60, 0x89, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x83, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBB, 0x60, 0x25, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xB0, 0xFF, 0xB1, 0xFF, 0x40, 0xFF, 0x43, 0xFF, 0xBB, 0x60, 0x20, 0x78, 0x44, 0xFF, 0xFF, 0x01, +- 0xBB, 0x60, 0x25, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0x33, 0x60, 0x9B, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xBB, 0x60, 0x20, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xBB, 0x60, 0x1F, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xBF, 0x60, 0xDB, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xEB, 0x60, 0x1F, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBF, 0x60, 0xE3, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBF, 0x60, 0xE3, 0x78, 0x24, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xE9, 0x60, 0xE3, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBF, 0x60, 0xE3, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBF, 0x60, 0xE3, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBF, 0x60, 0xE3, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x24, 0x60, 0xE5, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x25, 0x60, 0x14, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x25, 0x60, 0x32, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x25, 0x60, 0x11, 0x78, 0x28, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x25, 0x60, 0x11, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x25, 0x60, 0x11, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x25, 0x60, 0x11, 0x78, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0x60, 0x87, 0x64, 0x80, 0x29, 0x09, 0xFB, 0x47, 0xFF, 0x25, 0x60, 0x11, 0x78, 0xFF, 0xFF, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x2F, 0x60, 0x63, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x2F, 0x60, 0xB3, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x07, 0x02, 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, +- 0x66, 0xFF, 0xBF, 0xFE, 0xA1, 0xFF, 0x82, 0xFF, 0x88, 0xFF, 0x6C, 0x40, 0x41, 0xFF, 0xC4, 0xE2, +- 0x43, 0xFF, 0x5C, 0x49, 0x08, 0xE1, 0xA2, 0x60, 0x16, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0x98, 0xFF, +- 0x80, 0x3E, 0x9F, 0xFE, 0x03, 0x04, 0x31, 0x60, 0x75, 0x78, 0xFF, 0xFF, 0xE2, 0xFE, 0x40, 0x05, +- 0xE0, 0xFE, 0x5B, 0x05, 0xE1, 0xFE, 0xF2, 0x04, 0x29, 0x40, 0x08, 0x26, 0xEF, 0x01, 0x72, 0x44, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xB5, 0xF3, 0xE8, 0x85, 0xFF, 0xB7, +- 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x85, 0x73, 0x44, 0xD4, 0x84, 0x10, 0x65, 0xD4, 0x80, 0xFF, 0xFF, +- 0x26, 0x04, 0x3F, 0x40, 0x40, 0x26, 0x13, 0x00, 0x0B, 0x60, 0xF8, 0x62, 0xA2, 0xD1, 0x00, 0x60, +- 0x10, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xF8, 0xA2, 0xA2, 0xD1, 0x0A, 0x60, 0x19, 0x64, 0x90, 0x84, +- 0xA0, 0x52, 0x06, 0xA2, 0xA2, 0xD1, 0x46, 0x60, 0x09, 0x64, 0x90, 0x84, 0xA0, 0x50, 0xF2, 0xF4, +- 0x31, 0x60, 0x18, 0x7C, 0x63, 0x40, 0x01, 0x26, 0x08, 0x00, 0xA4, 0xD3, 0xFF, 0xFF, 0x01, 0xB4, +- 0xFF, 0xFF, 0x03, 0x02, 0xAD, 0x4F, 0xFE, 0xB4, 0xA0, 0x5D, 0x02, 0xEE, 0xBD, 0xFE, 0xBE, 0x01, +- 0x21, 0x46, 0x5E, 0x62, 0x9A, 0xFF, 0x07, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x06, 0x25, 0x10, 0x00, +- 0xA2, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x62, 0x62, 0x01, 0x5D, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, +- 0x7A, 0xDC, 0x44, 0xFF, 0x06, 0x25, 0x04, 0x00, 0x0E, 0xE1, 0x02, 0x60, 0x01, 0xE1, 0x9E, 0x01, +- 0x62, 0xFF, 0xC4, 0xE2, 0x41, 0xFF, 0x0A, 0xE1, 0x99, 0x01, 0xC8, 0x74, 0xCD, 0xE2, 0x29, 0x44, +- 0x08, 0xBC, 0x40, 0x49, 0x05, 0xE1, 0x31, 0x60, 0x1A, 0x63, 0xA3, 0xD3, 0xF2, 0xF3, 0x06, 0x18, +- 0x28, 0x40, 0x08, 0x2A, 0x05, 0x00, 0x28, 0x40, 0x48, 0x36, 0x02, 0x00, 0x02, 0xBC, 0xF2, 0xFB, +- 0x3F, 0x40, 0x01, 0x2B, 0xFF, 0xFF, 0xA1, 0xFF, 0x67, 0x4C, 0x06, 0x61, 0xCD, 0x81, 0x04, 0x25, +- 0x30, 0x00, 0x87, 0x4C, 0xFB, 0x02, 0x28, 0x40, 0x40, 0x2B, 0x02, 0x00, 0x15, 0x60, 0x6F, 0x6B, +- 0xF3, 0x60, 0xA0, 0x64, 0x04, 0x25, 0x25, 0x00, 0x80, 0x4C, 0x30, 0x64, 0x3A, 0xDB, 0x44, 0xFF, +- 0x04, 0x25, 0x1F, 0x00, 0x04, 0x60, 0x00, 0x65, 0x25, 0x44, 0x37, 0x36, 0xB4, 0x84, 0x6E, 0x36, +- 0xB4, 0x84, 0x80, 0x4E, 0x24, 0x41, 0x04, 0x25, 0x14, 0x00, 0x61, 0x4C, 0x64, 0xA1, 0x61, 0x54, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x04, 0x25, 0x0D, 0x00, 0x67, 0x4E, 0x07, 0x64, 0x1C, 0xFB, 0x00, 0xE1, +- 0x02, 0x60, 0x01, 0xE1, 0x53, 0x01, 0x33, 0xF3, 0xFD, 0x11, 0xFC, 0x18, 0x40, 0x64, 0x3A, 0xDB, +- 0x0A, 0x00, 0xC4, 0xE2, 0x27, 0x44, 0x20, 0x2A, 0x04, 0x00, 0x42, 0x64, 0x3A, 0xDB, 0x67, 0x4C, +- 0x02, 0x00, 0x41, 0x64, 0x3A, 0xDB, 0x62, 0xFF, 0x08, 0xE1, 0xE2, 0xFE, 0x72, 0x52, 0x5C, 0x49, +- 0x32, 0x7B, 0x4D, 0xE2, 0x3B, 0x01, 0x08, 0xE1, 0x39, 0x01, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, +- 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x02, 0x02, 0xA1, 0xFF, 0xFF, 0xFF, 0x82, 0xFF, 0x88, 0xFF, +- 0x48, 0xE2, 0x01, 0x70, 0xCE, 0xF1, 0x00, 0x6B, 0x89, 0xFF, 0x64, 0x54, 0x88, 0xFF, 0x9F, 0xFE, +- 0x02, 0x05, 0x64, 0x44, 0x60, 0x54, 0xCD, 0xE2, 0xC2, 0x64, 0x3A, 0xDB, 0xBC, 0xFF, 0xB5, 0xFF, +- 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xB4, 0x40, 0x46, 0x3C, 0x44, 0x00, 0xBC, 0xFF, 0xFF, 0x06, 0x03, +- 0x27, 0x40, 0x26, 0x22, 0x03, 0x00, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x27, 0x44, 0x20, 0x2A, +- 0x04, 0x00, 0xA0, 0x60, 0x00, 0xEA, 0xB0, 0x60, 0x00, 0xEA, 0x5C, 0x4D, 0x27, 0x44, 0x18, 0xB4, +- 0x40, 0x47, 0x00, 0xE1, 0x6C, 0x40, 0x44, 0xE2, 0xC4, 0xE2, 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, +- 0x32, 0xF1, 0x08, 0x29, 0x09, 0x00, 0x64, 0x40, 0x07, 0x22, 0x06, 0x00, 0x43, 0xFF, 0x27, 0x44, +- 0x10, 0xBC, 0x40, 0x47, 0x00, 0x64, 0x32, 0xFB, 0x31, 0x41, 0x3C, 0x44, 0x01, 0xB1, 0x00, 0xBC, +- 0x0A, 0x02, 0x09, 0x03, 0x32, 0xF3, 0x00, 0x7C, 0x01, 0xB4, 0xFF, 0xFF, 0x04, 0x03, 0x32, 0xF9, +- 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x00, 0x64, +- 0x33, 0xFB, 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x32, 0xF3, 0x08, 0x29, +- 0x0A, 0x00, 0x60, 0x40, 0x07, 0x22, 0x07, 0x00, 0xFE, 0xB4, 0x32, 0xFB, 0x27, 0x44, 0x10, 0xBC, +- 0xF7, 0xB4, 0x40, 0x47, 0x43, 0xFF, 0x00, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x08, 0xE1, 0x31, 0x40, +- 0x01, 0x2A, 0x04, 0x00, 0x00, 0x64, 0x33, 0xFB, 0x01, 0x60, 0x0A, 0xE1, 0xE5, 0xFE, 0x1D, 0x05, +- 0x27, 0x44, 0x10, 0x26, 0x1D, 0x00, 0x9F, 0xFE, 0x02, 0x04, 0x02, 0xE1, 0x10, 0x00, 0x3E, 0xE1, +- 0x31, 0x44, 0x01, 0x2A, 0x0C, 0x00, 0x0E, 0x0A, 0x28, 0x44, 0x04, 0x27, 0x07, 0x00, 0xD4, 0x36, +- 0x05, 0x00, 0xC4, 0x36, 0x03, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0xBF, 0xE1, 0xA1, 0xFF, +- 0xFF, 0xFF, 0x81, 0x3E, 0xAB, 0x60, 0x2C, 0x78, 0xFF, 0xFF, 0xA3, 0x60, 0xEC, 0x78, 0xFF, 0xFF, +- 0x27, 0x44, 0x08, 0x26, 0xFF, 0xFF, 0xBA, 0x60, 0x70, 0x78, 0xFF, 0xFF, 0x48, 0xF3, 0x32, 0xF1, +- 0x00, 0x63, 0x64, 0x40, 0x03, 0x22, 0x66, 0x00, 0x31, 0x40, 0x08, 0x26, 0xF4, 0x01, 0xCD, 0xE2, +- 0x84, 0xE1, 0x70, 0x41, 0xAD, 0x80, 0x71, 0x40, 0x80, 0x27, 0xED, 0x12, 0x03, 0x03, 0xBA, 0x60, +- 0xE7, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0xC4, 0xE2, 0x32, 0xFD, 0x60, 0x40, 0x01, 0x2A, +- 0xDF, 0x01, 0x00, 0x63, 0x32, 0xFD, 0x6C, 0x40, 0x3C, 0x46, 0x3E, 0xF2, 0x2A, 0xF0, 0x27, 0x41, +- 0x44, 0x48, 0x20, 0xB9, 0x01, 0xB4, 0xF7, 0xB1, 0x0A, 0x03, 0x64, 0x40, 0x08, 0x27, 0x07, 0x00, +- 0x0F, 0x60, 0x92, 0x63, 0x00, 0x64, 0x45, 0xFB, 0x46, 0xFB, 0xBD, 0xDB, 0xA3, 0xDB, 0xCB, 0x0A, +- 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0x17, 0x18, 0x28, 0x40, 0xD4, 0x36, 0x14, 0x00, +- 0xAC, 0x4C, 0x80, 0x2A, 0x11, 0x00, 0x31, 0x60, 0x14, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0x0C, 0x18, +- 0x31, 0x60, 0x16, 0x7C, 0xA4, 0xD3, 0x31, 0x60, 0x10, 0x7C, 0xA4, 0xD3, 0x60, 0x45, 0xD4, 0x80, +- 0xDC, 0x84, 0x02, 0x03, 0xA4, 0xDB, 0xAF, 0x01, 0x31, 0x60, 0x10, 0x7C, 0x00, 0x64, 0xA4, 0xDB, +- 0x41, 0x47, 0x3F, 0x40, 0x01, 0x2B, 0x0D, 0x00, 0xF6, 0xFE, 0x67, 0x4C, 0x05, 0x60, 0x69, 0x6B, +- 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0x04, 0x18, 0xAE, 0x4F, 0x08, 0xBC, 0x00, 0x7F, +- 0xA0, 0x5E, 0x02, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0xF0, 0xFE, 0x84, 0xFF, 0xBB, 0x60, 0x18, 0x64, +- 0x40, 0x42, 0x82, 0xFF, 0xE5, 0xFE, 0x03, 0x04, 0xA8, 0x60, 0x24, 0x78, 0xFF, 0xFF, 0xE4, 0xFE, +- 0x0A, 0x04, 0x1D, 0xFF, 0x00, 0xEB, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, +- 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x43, 0xFF, 0xE6, 0xFE, 0x03, 0x05, 0xA3, 0x60, 0x4B, 0x78, +- 0xFF, 0xFF, 0x3C, 0x44, 0x60, 0x46, 0x0F, 0xF0, 0x40, 0x42, 0x64, 0x40, 0x01, 0x2A, 0x03, 0x00, +- 0xA6, 0x60, 0xB1, 0x78, 0xFF, 0xFF, 0x0B, 0x64, 0x3A, 0xDB, 0x1C, 0x42, 0x22, 0x46, 0x13, 0xF2, +- 0xFF, 0x65, 0x60, 0x47, 0x2A, 0xF2, 0x40, 0x45, 0x40, 0x48, 0x04, 0x2B, 0x17, 0x00, 0x16, 0xF2, +- 0x1D, 0xF2, 0x40, 0x43, 0x0F, 0xF2, 0x40, 0x44, 0x25, 0x5E, 0x3F, 0x40, 0x01, 0x27, 0x40, 0x45, +- 0x0F, 0x64, 0x14, 0xF0, 0x35, 0xF2, 0xA0, 0x82, 0x0F, 0xB4, 0xCA, 0x85, 0xD4, 0x80, 0x10, 0xF2, +- 0x01, 0x02, 0x2B, 0xFA, 0x27, 0x44, 0x40, 0xBC, 0x40, 0x47, 0x13, 0x00, 0x17, 0xF2, 0x2C, 0xF0, +- 0x40, 0x43, 0x1B, 0xF2, 0x1D, 0xFA, 0x40, 0x44, 0x64, 0x40, 0x01, 0x2A, 0x02, 0x00, 0xAB, 0xFC, +- 0x05, 0x00, 0x28, 0x40, 0xA4, 0x36, 0x02, 0x00, 0x11, 0xF2, 0x2B, 0xFA, 0x27, 0x44, 0xBF, 0xB4, +- 0x40, 0x47, 0x28, 0x40, 0x40, 0x2B, 0xFF, 0xFF, 0xAB, 0x60, 0x4A, 0x78, 0xFF, 0xFF, 0x22, 0x46, +- 0x2C, 0xF0, 0x27, 0x44, 0xDF, 0xB4, 0x40, 0x47, 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB7, 0xFF, +- 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x64, 0x40, 0x01, 0x2A, 0x09, 0x00, +- 0x28, 0x44, 0x04, 0x27, 0x05, 0x00, 0xD4, 0x3A, 0x03, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, +- 0x1B, 0x00, 0x2A, 0xF0, 0x01, 0x65, 0x64, 0x40, 0xA4, 0x3A, 0x04, 0x65, 0x27, 0x44, 0x34, 0x87, +- 0x36, 0xF3, 0xB4, 0xFF, 0x60, 0x5B, 0x4D, 0xE2, 0x04, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x0A, 0xE1, +- 0x28, 0x44, 0x04, 0x27, 0x05, 0x00, 0xD4, 0x3A, 0x03, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, +- 0x2B, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x06, 0x64, 0x3A, 0xDB, 0x22, 0x46, 0x01, 0x64, +- 0x31, 0xFB, 0xC0, 0xFE, 0xBA, 0x60, 0xF0, 0x78, 0xFF, 0xFF, 0xB5, 0xFF, 0xA1, 0xFF, 0x6C, 0x40, +- 0x3F, 0x40, 0x01, 0x2B, 0x03, 0x00, 0x67, 0x4C, 0x05, 0x60, 0x69, 0x6B, 0x02, 0xE1, 0x01, 0x60, +- 0x08, 0xE1, 0xC4, 0xE2, 0x08, 0x64, 0x3A, 0xDB, 0xF0, 0xFE, 0x25, 0x46, 0x01, 0xF2, 0x61, 0x45, +- 0xD4, 0x9E, 0x21, 0x46, 0x16, 0xFA, 0x2A, 0x44, 0x72, 0x45, 0x24, 0xFA, 0xB5, 0xF3, 0x06, 0x04, +- 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, 0x01, 0x26, 0x64, 0x44, 0xB5, 0xF9, 0x25, 0xFA, 0xB6, 0xF3, +- 0x02, 0x04, 0xDC, 0x84, 0xB6, 0xFB, 0x28, 0xFA, 0xB7, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB7, 0xFB, +- 0x29, 0xFA, 0x2D, 0x44, 0x04, 0x2A, 0x06, 0x00, 0x28, 0x40, 0xA4, 0x36, 0x03, 0x00, 0xA5, 0x60, +- 0x77, 0x78, 0xFF, 0xFF, 0x26, 0x43, 0x84, 0xBB, 0xFC, 0xB3, 0x21, 0x46, 0x01, 0x5D, 0x0F, 0xFC, +- 0x5C, 0x46, 0x25, 0x44, 0x06, 0xFA, 0x05, 0xFF, 0x27, 0x44, 0x01, 0x2A, 0x13, 0x00, 0x50, 0xFE, +- 0x28, 0x40, 0x08, 0x3A, 0x12, 0x00, 0x2F, 0xF2, 0x30, 0xF0, 0x60, 0x43, 0x31, 0xF2, 0x22, 0x46, +- 0x64, 0x41, 0x2C, 0xF0, 0x2D, 0xF0, 0xD3, 0x80, 0x2E, 0xF0, 0xD1, 0x80, 0xD0, 0x80, 0x27, 0x44, +- 0x09, 0x0C, 0x03, 0x00, 0x27, 0x44, 0x06, 0x22, 0x05, 0x00, 0xB8, 0xB4, 0x40, 0x47, 0x02, 0x64, +- 0x31, 0xFB, 0xC0, 0xFE, 0xD4, 0x64, 0x40, 0x48, 0x0D, 0x64, 0x3A, 0xDB, 0x31, 0x60, 0x12, 0x7C, +- 0x7C, 0x44, 0xA4, 0xDB, 0x21, 0x46, 0x1C, 0xF2, 0x7C, 0xF1, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, +- 0x01, 0x06, 0x64, 0x44, 0x40, 0x45, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x3A, +- 0x03, 0x00, 0x04, 0x7F, 0x40, 0x45, 0x15, 0x64, 0x6E, 0x3A, 0x03, 0x00, 0x84, 0x7F, 0x40, 0x45, +- 0x0B, 0x64, 0x40, 0x44, 0x00, 0x63, 0x28, 0x44, 0xA4, 0x36, 0x0B, 0x00, 0x04, 0x2B, 0x09, 0x00, +- 0x30, 0xF3, 0x24, 0x45, 0xD4, 0x84, 0xCA, 0x65, 0xD4, 0x83, 0x31, 0x60, 0x12, 0x7C, 0x01, 0x64, +- 0xA4, 0xDB, 0xD4, 0x64, 0x1A, 0x00, 0x0F, 0x64, 0x3A, 0xDB, 0x21, 0x46, 0x70, 0x63, 0x1C, 0xF2, +- 0xCA, 0x65, 0x40, 0x45, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x3A, 0x03, 0x00, +- 0x04, 0x7F, 0x40, 0x45, 0x15, 0x64, 0x6E, 0x3A, 0x03, 0x00, 0x84, 0x7F, 0x40, 0x45, 0x0B, 0x64, +- 0x40, 0x44, 0x2B, 0xF2, 0xC4, 0x85, 0xD4, 0x83, 0xC4, 0x64, 0x40, 0x48, 0x2F, 0xF0, 0xB0, 0xF0, +- 0xB1, 0xF2, 0x00, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x80, 0x4E, 0x83, 0x4C, 0x9A, 0xFF, 0x84, 0x4C, +- 0x85, 0x4C, 0x81, 0x4C, 0xA1, 0xFF, 0x98, 0xFF, 0x87, 0x4F, 0x87, 0x4C, 0x87, 0x4F, 0x87, 0x4D, +- 0x87, 0x4C, 0x01, 0x08, 0x01, 0x00, 0xFF, 0xFF, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, +- 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x44, 0xBC, 0xFF, 0xC4, 0xE2, 0x0C, 0x74, 0x04, 0xE1, 0xA1, 0xFF, +- 0x35, 0xF3, 0xC4, 0xE2, 0x60, 0x54, 0x89, 0xFF, 0x13, 0x74, 0x88, 0xFF, 0xB5, 0xFF, 0x47, 0xFF, +- 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, +- 0x00, 0x6B, 0x28, 0x40, 0xC4, 0x36, 0x08, 0x00, 0x31, 0x60, 0x12, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, +- 0x03, 0x1B, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0x27, 0x44, 0x01, 0x2A, 0x05, 0x00, 0xFE, 0xB4, +- 0x40, 0x47, 0xA4, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0xA3, 0x60, 0x3E, 0x78, 0xFF, 0xFF, 0x28, 0x40, +- 0xB4, 0x3A, 0x09, 0x00, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x02, 0x64, +- 0x31, 0xFB, 0xC0, 0xFE, 0x90, 0x01, 0x28, 0x44, 0xD4, 0x36, 0x03, 0x00, 0xA6, 0x60, 0x98, 0x78, +- 0xFF, 0xFF, 0x48, 0xE2, 0x27, 0x44, 0xFB, 0xB4, 0x40, 0x47, 0x2D, 0x60, 0x5A, 0x63, 0xA3, 0xD3, +- 0xB0, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x34, 0xFB, 0x1C, 0x42, 0x22, 0x46, 0x2A, 0xF0, +- 0xF7, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDA, 0x60, 0x40, 0x40, 0x2B, 0xCC, 0x00, 0x22, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x22, 0x26, 0x42, 0x00, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x07, 0x00, +- 0xC2, 0x00, 0x04, 0x2B, 0xC0, 0x00, 0xA9, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x01, 0x00, 0x07, 0xF4, +- 0x47, 0xF2, 0xFF, 0xFF, 0xDC, 0x84, 0x47, 0xFA, 0x0D, 0x60, 0x3E, 0x62, 0x80, 0xFF, 0xBE, 0x60, +- 0x78, 0x44, 0x02, 0xA4, 0xA2, 0xDB, 0xDE, 0x78, 0xFF, 0xFF, 0x82, 0xFF, 0xA9, 0xF3, 0x66, 0x5C, +- 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, 0x22, 0x46, 0x22, 0xF2, 0x63, 0x46, 0x60, 0x40, +- 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x47, 0xF0, 0x64, 0x41, 0x64, 0x47, 0xFF, 0xB4, 0x60, 0x5F, +- 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, 0x22, 0x46, 0x3A, 0xFA, 0x64, 0x44, 0x20, 0x7F, +- 0x34, 0x94, 0x3B, 0xFA, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, +- 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x85, 0x00, 0x2A, 0xF2, 0x00, 0x60, +- 0x7C, 0x62, 0x60, 0x40, 0x40, 0x2B, 0x27, 0x00, 0xA2, 0xD3, 0x00, 0x61, 0x60, 0xFE, 0xA0, 0xD3, +- 0xDE, 0x82, 0xA2, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, 0xC0, 0x2B, +- 0x04, 0x00, 0x80, 0x2A, 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, 0x60, 0x47, +- 0xDC, 0x87, 0x01, 0x61, 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, 0xDA, 0x82, +- 0xA2, 0xD1, 0xFF, 0xFF, 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, +- 0xA2, 0xDB, 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0x60, 0x7C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD3, +- 0x5A, 0xD1, 0x3A, 0xFA, 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, +- 0xA0, 0x5A, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, +- 0x00, 0x60, 0x80, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, 0x64, 0x45, 0x64, 0x44, +- 0xE3, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE5, 0x7F, +- 0xA0, 0x5A, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5A, +- 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, +- 0xE9, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEB, 0x7F, +- 0xA0, 0x5A, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5A, +- 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5A, 0x08, 0x60, +- 0x00, 0xEA, 0x65, 0x44, 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, +- 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x0B, 0xF2, 0xFF, 0xFF, 0x7F, 0xB4, 0x0C, 0xF0, 0x04, 0x02, +- 0x64, 0x46, 0x00, 0xF0, 0x04, 0x64, 0x22, 0x46, 0x03, 0xFA, 0x60, 0x41, 0x64, 0x46, 0x01, 0xF2, +- 0xFC, 0xA1, 0x61, 0x45, 0xD4, 0x84, 0xFF, 0xFF, 0x08, 0x02, 0x00, 0xF0, 0x04, 0x63, 0x64, 0x46, +- 0x01, 0xF2, 0x22, 0x46, 0x1A, 0xFA, 0x03, 0xFC, 0x02, 0x00, 0x22, 0x46, 0x1A, 0xFA, 0x35, 0xF2, +- 0x04, 0xF8, 0xDC, 0x84, 0x35, 0xFA, 0x14, 0xF2, 0x0F, 0xB5, 0x0F, 0xB4, 0xCC, 0x84, 0x94, 0x80, +- 0x04, 0x60, 0x00, 0x65, 0x2A, 0xF2, 0x01, 0x02, 0x94, 0x84, 0x2A, 0xFA, 0x95, 0xFC, 0x06, 0x00, +- 0xC4, 0x3A, 0x07, 0x00, 0x27, 0x44, 0xFD, 0xB4, 0x40, 0x47, 0x48, 0xE2, 0xA4, 0x60, 0x0B, 0x78, +- 0xFF, 0xFF, 0x28, 0x44, 0x04, 0x26, 0x05, 0x00, 0x68, 0x3A, 0x03, 0x00, 0x32, 0x44, 0x00, 0x27, +- 0x03, 0x00, 0xA3, 0x60, 0x4B, 0x78, 0xFF, 0xFF, 0x0A, 0x64, 0x3A, 0xDB, 0xA3, 0x60, 0x4B, 0x78, +- 0xFF, 0xFF, 0x0E, 0x64, 0x3A, 0xDB, 0x10, 0x60, 0x00, 0x65, 0x3C, 0x46, 0x2A, 0xF2, 0x13, 0xF0, +- 0xA4, 0x84, 0xB4, 0xBC, 0x40, 0x48, 0x7C, 0xF1, 0x64, 0x47, 0xFF, 0xB4, 0x60, 0x45, 0xD0, 0x80, +- 0x70, 0x61, 0x01, 0x06, 0x64, 0x44, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x36, +- 0x15, 0x64, 0x6E, 0x36, 0x0B, 0x64, 0x40, 0x4E, 0xA0, 0x63, 0x0A, 0x64, 0x65, 0x40, 0x0A, 0x36, +- 0x03, 0x00, 0x38, 0x61, 0x14, 0x64, 0xEB, 0x83, 0x40, 0x45, 0x43, 0x44, 0x02, 0x60, 0x5E, 0x65, +- 0x2A, 0xF2, 0x2B, 0xF2, 0x60, 0x40, 0x04, 0x2B, 0x04, 0x00, 0x2E, 0x45, 0xD4, 0x85, 0xC5, 0x84, +- 0x05, 0x00, 0x1B, 0xF0, 0xC5, 0x84, 0xC0, 0x84, 0x2E, 0x45, 0xC4, 0x84, 0x60, 0x43, 0x28, 0x44, +- 0x00, 0xE1, 0xA1, 0xFF, 0x80, 0x4E, 0x83, 0x4C, 0x9A, 0xFF, 0x56, 0x62, 0x7A, 0xD4, 0x7A, 0xD4, +- 0x7A, 0xD4, 0x5C, 0x62, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0xA1, 0xFF, 0x98, 0xFF, 0x87, 0x4F, +- 0x87, 0x4C, 0x87, 0x4F, 0x87, 0x4D, 0x87, 0x4C, 0x01, 0x08, 0x01, 0x00, 0xFF, 0xFF, 0x87, 0x4C, +- 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x44, 0xBC, 0xFF, 0xB5, 0xFF, +- 0x47, 0xFF, 0x27, 0x44, 0x02, 0xBC, 0x40, 0x47, 0x36, 0xF3, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, +- 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x60, 0x5B, 0x4D, 0xE2, 0xA4, 0x60, 0x6C, 0x78, 0xFF, 0xFF, +- 0x21, 0x46, 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, +- 0x08, 0x60, 0x00, 0x6B, 0x28, 0x44, 0x04, 0x27, 0x09, 0x00, 0xD4, 0x36, 0x04, 0x00, 0x0C, 0x22, +- 0x02, 0x00, 0x0C, 0x3A, 0x03, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0x26, 0x43, 0x25, 0x44, +- 0x06, 0xFA, 0x2A, 0x44, 0x72, 0x45, 0x24, 0xFA, 0xB5, 0xF3, 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, +- 0x29, 0x40, 0x01, 0x26, 0x64, 0x44, 0xB5, 0xF9, 0x25, 0xFA, 0xB6, 0xF3, 0x02, 0x04, 0xDC, 0x84, +- 0xB6, 0xFB, 0x28, 0xFA, 0xB7, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB7, 0xFB, 0x29, 0xFA, 0x2D, 0x40, +- 0x01, 0x2A, 0x0E, 0x00, 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xBC, 0x40, 0x46, 0x27, 0x44, 0x07, 0x22, +- 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x30, 0xF1, 0x76, 0x00, +- 0xFC, 0xB3, 0x32, 0x40, 0x01, 0x2A, 0x06, 0x00, 0x0A, 0xBB, 0x0F, 0xFC, 0xCB, 0xFE, 0xA3, 0x60, +- 0x4B, 0x78, 0xFF, 0xFF, 0x2D, 0x44, 0x04, 0x26, 0x28, 0x00, 0x0F, 0xFC, 0x05, 0xFF, 0xDC, 0xF3, +- 0x28, 0x40, 0x80, 0x3A, 0x22, 0x00, 0x60, 0x40, 0x03, 0x3A, 0x1F, 0x00, 0x32, 0xF2, 0x81, 0xF1, +- 0x33, 0xF2, 0xD0, 0x80, 0x82, 0xF1, 0x19, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x83, 0xF1, 0x15, 0x02, +- 0xD0, 0x80, 0x3C, 0x44, 0x12, 0x02, 0xAC, 0x86, 0xBB, 0xFE, 0x0F, 0x03, 0x2A, 0xF2, 0x21, 0x46, +- 0x60, 0x40, 0x80, 0x3A, 0x0A, 0x00, 0x01, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x00, 0x64, 0x32, 0xFB, +- 0x84, 0xFF, 0xBB, 0x60, 0x18, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x30, 0xF1, 0x27, 0x44, 0x05, 0x22, +- 0x2D, 0x00, 0xFA, 0xB4, 0x40, 0x47, 0x2D, 0x44, 0x10, 0x2A, 0x24, 0x00, 0x28, 0x40, 0xD4, 0x3A, +- 0x21, 0x00, 0x31, 0x40, 0x08, 0x26, 0x00, 0x7C, 0x2B, 0x44, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, +- 0x64, 0x44, 0xC4, 0x84, 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, +- 0x20, 0x29, 0x6D, 0xE2, 0x1C, 0x60, 0x9A, 0x63, 0x1D, 0xF0, 0xC0, 0x64, 0xC0, 0x84, 0xA3, 0xD1, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA3, 0xDB, 0xA4, 0x60, +- 0x7C, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x07, 0x00, 0x02, 0x2A, 0x05, 0x00, +- 0xFD, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x05, 0x64, 0x3A, 0xDB, 0x28, 0x44, +- 0xA4, 0x3A, 0x04, 0x00, 0x39, 0xF1, 0x25, 0x44, 0x0A, 0x36, 0x38, 0xF1, 0x31, 0x40, 0x08, 0x26, +- 0x00, 0x7C, 0x2B, 0x44, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, 0x64, 0x44, 0xC4, 0x84, 0xFF, 0xFF, +- 0x04, 0x24, 0x00, 0xB4, 0x28, 0x40, 0xE4, 0x36, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, +- 0x20, 0x29, 0x6D, 0xE2, 0xA3, 0x60, 0x3E, 0x78, 0xFF, 0xFF, 0x21, 0x46, 0xB5, 0xFF, 0xBC, 0xFF, +- 0x47, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0xAE, 0x4F, +- 0xF7, 0xB4, 0xA0, 0x5E, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x06, 0x64, +- 0x31, 0xFB, 0xC0, 0xFE, 0xE7, 0x01, 0x27, 0x44, 0x05, 0x22, 0x09, 0x00, 0xBA, 0xB4, 0x40, 0x47, +- 0x3C, 0x46, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xA3, 0x60, 0x4B, 0x78, 0xFF, 0xFF, 0x27, 0x44, +- 0x02, 0x2A, 0x06, 0x00, 0xFD, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xF4, 0x01, +- 0xF3, 0x0A, 0x7C, 0x50, 0x6D, 0xE2, 0xF0, 0x01, 0x72, 0x45, 0xDC, 0x84, 0xB5, 0xFB, 0x11, 0x64, +- 0x3A, 0xDB, 0xB6, 0xF3, 0x06, 0x04, 0xDC, 0x84, 0xB6, 0xFB, 0xB7, 0xF3, 0x02, 0x04, 0xDC, 0x84, +- 0xB7, 0xFB, 0xA3, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0x00, 0x61, 0x12, 0x64, 0x3A, 0xDB, 0x1E, 0x60, +- 0xFE, 0x63, 0xBD, 0xD3, 0x72, 0x45, 0x44, 0x8A, 0x02, 0x28, 0x02, 0x00, 0xE4, 0xE2, 0xDD, 0x81, +- 0x02, 0x28, 0x02, 0x00, 0xE4, 0xE2, 0xDD, 0x81, 0xBD, 0xD3, 0xB5, 0xF1, 0x61, 0x45, 0xC0, 0x84, +- 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, 0xC4, 0x84, 0x60, 0x55, 0x2A, 0x52, 0xB5, 0xFB, 0x02, 0x24, +- 0x01, 0xB9, 0xBD, 0xD3, 0xB6, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, +- 0xC4, 0x84, 0xB6, 0xFB, 0x02, 0x24, 0x01, 0xB9, 0xBD, 0xD3, 0xB7, 0xF1, 0x61, 0x45, 0xC0, 0x84, +- 0xC4, 0x84, 0xB7, 0xFB, 0xA3, 0x60, 0xEF, 0x78, 0xFF, 0xFF, 0x31, 0x40, 0x04, 0x0A, 0xAE, 0x4F, +- 0xF7, 0xB4, 0xA0, 0x5E, 0x09, 0x00, 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0x04, 0x18, +- 0xAE, 0x4F, 0x08, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x9F, 0x01, 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x25, +- 0x09, 0x00, 0x04, 0x25, 0x03, 0x00, 0x47, 0xFF, 0x32, 0x74, 0x96, 0x01, 0xC4, 0xE2, 0xAB, 0x60, +- 0x2C, 0x78, 0xFF, 0xFF, 0x4C, 0x4E, 0x47, 0xFF, 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, +- 0x04, 0x18, 0xAE, 0x4F, 0x08, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x32, 0x74, 0xCD, 0xE2, 0xA8, 0x60, +- 0x8A, 0x78, 0x00, 0x61, 0x10, 0x64, 0x3A, 0xDB, 0xA3, 0x60, 0x4B, 0x78, 0xFF, 0xFF, 0xA3, 0x60, +- 0x4B, 0x78, 0xFF, 0xFF, 0x5C, 0x4D, 0x26, 0x44, 0x02, 0x26, 0x0C, 0x00, 0x3E, 0x46, 0x09, 0xF2, +- 0x1E, 0x41, 0x03, 0x1B, 0xAA, 0x60, 0xDB, 0x78, 0xFF, 0xFF, 0x40, 0x5E, 0xFD, 0xFB, 0x21, 0x44, +- 0x02, 0x64, 0x40, 0x46, 0x41, 0x5D, 0x21, 0x46, 0x00, 0xF2, 0x46, 0x45, 0x87, 0xFC, 0x4C, 0xE2, +- 0x01, 0x64, 0x33, 0xFB, 0x01, 0x60, 0x0E, 0xE1, 0x03, 0xE1, 0x3F, 0x40, 0x01, 0x27, 0x00, 0x00, +- 0x21, 0x69, 0xB6, 0xFF, 0xA1, 0xFF, 0x6C, 0x5E, 0xB6, 0xFF, 0xB7, 0xFF, 0x60, 0x5C, 0x20, 0x64, +- 0x3A, 0xDB, 0x68, 0x43, 0x26, 0xFC, 0x22, 0x69, 0x64, 0x44, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x5F, +- 0x60, 0x43, 0x26, 0xF2, 0xFF, 0xFF, 0x68, 0x5F, 0x26, 0xFA, 0x3A, 0x69, 0x1D, 0xFC, 0x2E, 0x44, +- 0x36, 0xF1, 0x1C, 0xFA, 0xC3, 0x94, 0xCD, 0xE2, 0x2E, 0x44, 0x14, 0x36, 0x12, 0x00, 0x0A, 0x36, +- 0x0F, 0x00, 0x63, 0x45, 0xE3, 0x83, 0xE3, 0x83, 0xC7, 0x83, 0xE3, 0x83, 0xC7, 0x83, 0xFF, 0xFF, +- 0x37, 0x36, 0x05, 0x00, 0x6E, 0x36, 0x04, 0x00, 0xAA, 0x60, 0xF3, 0x78, 0xFF, 0xFF, 0xEB, 0x83, +- 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xFF, 0xFF, 0x80, 0x27, 0xCF, 0x83, 0x1B, 0xFC, 0x01, 0x64, +- 0x51, 0xFB, 0xA1, 0xFF, 0x1C, 0xF2, 0x29, 0x41, 0xF9, 0x81, 0x52, 0x4A, 0x71, 0x89, 0x68, 0x5F, +- 0x27, 0xFA, 0x6C, 0x40, 0x03, 0x15, 0xAB, 0x60, 0x04, 0x78, 0xFF, 0xFF, 0x88, 0x60, 0x85, 0x71, +- 0x8D, 0xE2, 0xB9, 0xF1, 0xFC, 0xA3, 0xD3, 0x80, 0x43, 0x43, 0x03, 0x04, 0xAA, 0x60, 0xFB, 0x78, +- 0xFF, 0xFF, 0x32, 0x40, 0x01, 0x2A, 0x4C, 0x00, 0x9A, 0xFF, 0x23, 0x43, 0x18, 0x61, 0xA1, 0xFF, +- 0x8C, 0x44, 0xCB, 0x83, 0x2A, 0xFA, 0x40, 0x48, 0x40, 0x27, 0x04, 0xA1, 0x60, 0x40, 0x03, 0x2B, +- 0x01, 0x00, 0x06, 0xA1, 0x88, 0xB0, 0x88, 0x36, 0xD9, 0x81, 0x62, 0x45, 0x23, 0x44, 0x54, 0x94, +- 0x28, 0x40, 0x04, 0x26, 0x00, 0x64, 0x3F, 0xFA, 0xC9, 0x81, 0x65, 0x42, 0x7A, 0xDC, 0x00, 0xB9, +- 0xFD, 0x1C, 0x00, 0xF4, 0x6E, 0x61, 0x10, 0x62, 0x14, 0x02, 0x05, 0x1D, 0x12, 0x1E, 0x0C, 0x00, +- 0x00, 0xF4, 0x7C, 0x61, 0x02, 0x62, 0x7A, 0xDC, 0x63, 0x40, 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, +- 0x08, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0x6C, 0x44, +- 0x5A, 0xDA, 0x98, 0xFF, 0x01, 0x60, 0x08, 0xE1, 0x81, 0xE1, 0xA1, 0xFF, 0x6C, 0x40, 0xA1, 0xFF, +- 0x47, 0xFF, 0x26, 0x44, 0xFD, 0xB4, 0x84, 0xBC, 0x01, 0x15, 0x7F, 0xB4, 0x40, 0x46, 0xA1, 0xFF, +- 0x6C, 0x40, 0x14, 0x63, 0x01, 0x11, 0x01, 0x00, 0xFD, 0x1F, 0xAA, 0x60, 0x6E, 0x78, 0xFF, 0xFF, +- 0x9A, 0xFF, 0x54, 0x63, 0x12, 0x64, 0x40, 0x46, 0x00, 0x64, 0x0F, 0xFA, 0xA1, 0xFF, 0xEB, 0xF1, +- 0x12, 0x61, 0x50, 0xFE, 0x2D, 0x60, 0x52, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, +- 0x0B, 0x00, 0x8C, 0x45, 0x98, 0xF8, 0x00, 0x64, 0x3A, 0xFA, 0x3B, 0xFA, 0x3C, 0xFA, 0x3D, 0xFA, +- 0xBF, 0x60, 0xFF, 0x64, 0xA4, 0x84, 0x01, 0x00, 0x8C, 0x44, 0xEC, 0xF0, 0xBD, 0xDA, 0x40, 0x48, +- 0x04, 0x26, 0x40, 0x00, 0xA1, 0xFF, 0x8C, 0x44, 0xBD, 0xDA, 0x30, 0xFB, 0x6C, 0x44, 0xBD, 0xDA, +- 0xFF, 0xFF, 0x01, 0x26, 0x24, 0x00, 0xD0, 0x80, 0xA1, 0xFF, 0x8C, 0x44, 0x6C, 0x5C, 0xF2, 0xFE, +- 0xBD, 0xDA, 0xED, 0xF3, 0xD4, 0x80, 0xD0, 0x80, 0xBD, 0xD8, 0x2D, 0x44, 0x15, 0x0C, 0x32, 0x40, +- 0x02, 0x2A, 0x07, 0x00, 0x28, 0x42, 0x0C, 0xB2, 0x08, 0x3A, 0x03, 0x00, 0x10, 0xBC, 0x40, 0x4D, +- 0x4D, 0x00, 0x03, 0x0A, 0xAB, 0x60, 0x09, 0x78, 0xFF, 0xFF, 0x11, 0xBC, 0x40, 0x4D, 0x28, 0x45, +- 0xBF, 0x60, 0xFF, 0x64, 0x24, 0x88, 0x42, 0x00, 0x30, 0xBC, 0x40, 0x4D, 0x3F, 0x00, 0x20, 0xB9, +- 0x5C, 0x8E, 0xA1, 0xFF, 0x8C, 0x44, 0xBD, 0xDA, 0xDC, 0x9C, 0x6C, 0x44, 0xF2, 0xFE, 0xBD, 0xDA, +- 0x08, 0x28, 0x44, 0x4E, 0xDC, 0x84, 0x2E, 0x5C, 0xB0, 0x84, 0xEF, 0xB1, 0x08, 0x24, 0x40, 0xB9, +- 0x41, 0x46, 0x2C, 0x00, 0x8C, 0x44, 0x04, 0x61, 0xBD, 0xDA, 0x50, 0xFE, 0x80, 0x27, 0x00, 0x64, +- 0x30, 0xFB, 0x8C, 0x44, 0xBD, 0xDA, 0xD0, 0x80, 0x8C, 0x44, 0xBD, 0xDA, 0xD4, 0x80, 0x00, 0x65, +- 0x8C, 0x44, 0xED, 0xF1, 0xBD, 0xDA, 0xD0, 0x80, 0x28, 0x44, 0x03, 0x0C, 0xA0, 0x2A, 0x0A, 0x00, +- 0x11, 0x00, 0x10, 0x65, 0x60, 0x40, 0xC4, 0x36, 0x04, 0x00, 0xD4, 0x3A, 0x08, 0x00, 0x27, 0x40, +- 0x40, 0x26, 0x30, 0x65, 0x00, 0x64, 0x3F, 0xFA, 0x46, 0x4E, 0x35, 0x8D, 0x5F, 0x00, 0x40, 0x26, +- 0xF9, 0x01, 0x30, 0x65, 0x9D, 0xDC, 0x9D, 0xDC, 0x9D, 0xDC, 0xF4, 0x01, 0x00, 0xE1, 0x23, 0x43, +- 0xE8, 0xA3, 0x6A, 0x62, 0x9A, 0xFF, 0xA1, 0xFF, 0x28, 0x44, 0x03, 0x2B, 0x04, 0x00, 0x7A, 0xDC, +- 0x7A, 0xDC, 0x7A, 0xDC, 0x28, 0x44, 0x88, 0xB0, 0x88, 0x2A, 0x03, 0x00, 0x70, 0x62, 0x7A, 0xDC, +- 0x28, 0x44, 0x40, 0x2B, 0x13, 0x00, 0x72, 0x62, 0x7A, 0xDC, 0x04, 0xE6, 0x7A, 0xDC, 0x3B, 0xF2, +- 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x2B, 0x02, 0x00, 0x7A, 0xDC, 0x7A, 0xDC, 0x08, 0x60, 0x00, 0xEB, +- 0xFC, 0xA3, 0x25, 0xFF, 0x3F, 0xFC, 0x04, 0xA3, 0xB0, 0xFF, 0x01, 0x00, 0x3F, 0xFC, 0xCF, 0x83, +- 0xDF, 0x83, 0x04, 0x02, 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, 0x1F, 0x00, 0x27, 0x03, 0xCB, 0x83, +- 0xFF, 0x60, 0xFE, 0x65, 0x0E, 0xA3, 0xA7, 0x84, 0xF2, 0xA3, 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, +- 0x7A, 0xDC, 0xFE, 0x1C, 0x03, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, 0x0A, 0x02, 0x00, 0xF4, 0x02, 0x62, +- 0xA7, 0x84, 0x7A, 0x61, 0x7A, 0xDC, 0xFE, 0x1C, 0xF9, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, 0xF6, 0x03, +- 0xFF, 0xB1, 0x0C, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xA1, 0xFF, 0x01, 0x60, 0x0C, 0xE1, +- 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0xCD, 0x81, 0x6C, 0x44, 0x5A, 0xDA, 0x98, 0xFF, 0x00, 0xE6, +- 0x7C, 0x44, 0x33, 0xFB, 0x01, 0x60, 0x0C, 0xE1, 0x83, 0xE1, 0xA1, 0xFF, 0x8C, 0x44, 0x46, 0x45, +- 0xA1, 0xFF, 0x14, 0x63, 0x01, 0x10, 0xFE, 0x1F, 0x01, 0x60, 0x08, 0xE1, 0x0A, 0x64, 0x60, 0x54, +- 0x47, 0xFF, 0x50, 0x4B, 0x67, 0x50, 0x69, 0xE2, 0x6A, 0x40, 0x40, 0x2B, 0x01, 0x15, 0x29, 0x00, +- 0x6C, 0x40, 0x28, 0x40, 0x03, 0x26, 0x15, 0x00, 0x31, 0x40, 0x20, 0x2A, 0x03, 0x00, 0x28, 0x40, +- 0x50, 0x3A, 0x0F, 0x00, 0x2D, 0x44, 0x20, 0x2A, 0x0C, 0x00, 0x2B, 0x44, 0xAC, 0x80, 0x28, 0x40, +- 0xB4, 0x3A, 0x03, 0x00, 0x02, 0x03, 0x30, 0xFB, 0x04, 0x00, 0x2B, 0x50, 0xA4, 0x60, 0x85, 0x78, +- 0x04, 0xE1, 0x04, 0xE1, 0xA1, 0xFF, 0x35, 0xF1, 0x26, 0x44, 0x64, 0x54, 0xCD, 0xE2, 0x84, 0xBC, +- 0x2D, 0x40, 0x0C, 0x22, 0xFD, 0xB4, 0x40, 0x46, 0x23, 0x64, 0x3A, 0xDB, 0xA7, 0x60, 0x18, 0x78, +- 0xFF, 0xFF, 0x27, 0x40, 0x26, 0x22, 0x04, 0x00, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xFF, 0xFF, +- 0x6C, 0x40, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, 0x00, 0x6B, 0x37, 0xF3, +- 0x2B, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x28, 0x65, 0x44, 0x60, 0x50, 0xA0, 0x4C, 0x20, 0xBC, +- 0xFF, 0xB4, 0xA0, 0x51, 0x35, 0xF1, 0x74, 0x44, 0xC0, 0x94, 0x32, 0x40, 0x02, 0x2A, 0x18, 0x00, +- 0x28, 0x44, 0xA4, 0x36, 0x04, 0x00, 0x0C, 0xB4, 0xFF, 0xFF, 0x04, 0x36, 0x11, 0x00, 0x26, 0x43, +- 0xFD, 0xB3, 0x04, 0xBB, 0x43, 0x46, 0x01, 0x2A, 0x03, 0x00, 0x28, 0x47, 0x40, 0xBF, 0x40, 0x48, +- 0x0A, 0xBB, 0x0F, 0xFC, 0x50, 0x4B, 0x67, 0x50, 0x00, 0x64, 0x30, 0xFB, 0x05, 0xFF, 0xC6, 0x01, +- 0x24, 0x64, 0x3A, 0xDB, 0x28, 0x44, 0x04, 0x2A, 0x06, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, +- 0xA3, 0x60, 0x3E, 0x78, 0xFF, 0xFF, 0x1D, 0xFF, 0x48, 0xE2, 0x27, 0x44, 0x06, 0x22, 0x05, 0x00, +- 0xF9, 0xB4, 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x26, 0x40, 0x10, 0x2A, 0x18, 0x00, +- 0x26, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0xFF, 0xB4, 0xC0, 0xA0, 0xFF, 0xFF, 0x11, 0x0E, 0xB8, 0xF1, +- 0x27, 0x60, 0x92, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, +- 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, +- 0xA7, 0x60, 0xE5, 0x78, 0xFF, 0xFF, 0xB8, 0xF1, 0x27, 0x60, 0x94, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, +- 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x2A, 0x64, 0x3A, 0xDB, 0x5C, 0x41, 0x87, 0xE1, +- 0xA1, 0xFF, 0x6C, 0x40, 0x02, 0x00, 0x29, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x08, 0xE1, 0x87, 0xE1, +- 0xA1, 0xFF, 0x6C, 0x40, 0x11, 0x00, 0x27, 0x60, 0xA6, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, +- 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0xF1, 0x01, 0x01, 0x60, 0x08, 0xE1, 0x21, 0x64, 0x3A, 0xDB, +- 0x03, 0x00, 0x01, 0x60, 0x08, 0xE1, 0x6C, 0x40, 0x00, 0x64, 0x33, 0xFB, 0x32, 0x74, 0x40, 0x63, +- 0x01, 0x16, 0xFE, 0x01, 0x01, 0x68, 0x01, 0x11, 0x09, 0x00, 0xA7, 0x6A, 0x22, 0x64, 0x3A, 0xDB, +- 0x03, 0x60, 0xC9, 0x63, 0x01, 0x11, 0x02, 0x00, 0x6C, 0x40, 0xFC, 0x1F, 0x6C, 0x40, 0xB5, 0xFF, +- 0x6C, 0x40, 0xBC, 0xFF, 0x6C, 0x40, 0xB7, 0xFF, 0xB4, 0xFF, 0x48, 0x60, 0x2D, 0x7D, 0x08, 0x60, +- 0x00, 0x6B, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0x03, 0x0A, 0xA3, 0x60, 0x4B, 0x78, 0xFF, 0xFF, +- 0x01, 0x64, 0x51, 0xFB, 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0x04, 0x18, 0xAE, 0x4F, +- 0x08, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x27, 0x44, 0x06, 0x22, 0x06, 0x00, 0xF9, 0xB4, 0x40, 0x47, +- 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x48, 0xE2, 0x27, 0x64, 0x3A, 0xDB, 0xB3, 0xE1, 0xA1, 0xFF, +- 0xFF, 0xFF, 0x81, 0x3E, 0x54, 0x62, 0x22, 0x46, 0xA2, 0xD0, 0x16, 0x63, 0x7C, 0x41, 0x44, 0x48, +- 0x80, 0x36, 0x04, 0x61, 0x28, 0x40, 0x50, 0x36, 0x04, 0x61, 0x41, 0x4E, 0x28, 0x44, 0xA4, 0x36, +- 0x0E, 0x63, 0x1C, 0x60, 0x9C, 0x62, 0xA2, 0xD1, 0x24, 0x44, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, 0xA2, 0xDB, 0x9A, 0xFF, 0xA1, 0xFF, 0x2D, 0x60, 0x52, 0x62, +- 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x06, 0x00, 0x18, 0xF2, 0xAA, 0xF0, 0xFF, 0xFF, +- 0xB4, 0x84, 0x08, 0x36, 0x2A, 0xFA, 0x54, 0x62, 0xA2, 0xD2, 0xFF, 0xFF, 0x6A, 0x40, 0x80, 0x4E, +- 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0xFF, 0xFF, +- 0x01, 0x1D, 0x78, 0x00, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x28, 0x40, 0x03, 0x2B, +- 0x04, 0x00, 0x7A, 0xD4, 0x7A, 0xD4, 0x7A, 0xD4, 0x6A, 0x40, 0x70, 0x62, 0x28, 0x44, 0x88, 0xB0, +- 0x88, 0x36, 0x7A, 0xD4, 0x28, 0x40, 0x40, 0x2B, 0x0B, 0x00, 0x72, 0x62, 0x7A, 0xD4, 0x7A, 0xD4, +- 0xA2, 0xD2, 0xFF, 0xFF, 0x60, 0x40, 0x20, 0x2B, 0x02, 0x00, 0x7A, 0xD4, 0x7A, 0xD4, 0x46, 0x00, +- 0x23, 0x43, 0xCF, 0x83, 0xDF, 0x83, 0x02, 0x03, 0x55, 0x03, 0x04, 0x00, 0x03, 0xF0, 0x04, 0xF4, +- 0x64, 0x42, 0x37, 0x00, 0x2E, 0x40, 0x04, 0x2A, 0x21, 0x00, 0xA1, 0xFF, 0x02, 0xFE, 0x10, 0x25, +- 0x42, 0xFE, 0x72, 0x45, 0x65, 0x4C, 0xB5, 0xF3, 0x03, 0x04, 0xE4, 0xE2, 0xDC, 0x84, 0xB5, 0xFB, +- 0xA1, 0xFF, 0x80, 0x4C, 0xB6, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB6, 0xFB, 0x80, 0x4C, 0xB7, 0xF3, +- 0x02, 0x04, 0xDC, 0x84, 0xB7, 0xFB, 0x80, 0x4C, 0x5C, 0x4E, 0xF8, 0xA3, 0x03, 0xF2, 0x9A, 0xF2, +- 0x04, 0xF4, 0xFF, 0xB1, 0xF8, 0xA1, 0x06, 0xA4, 0x60, 0x42, 0x09, 0x00, 0x03, 0xF2, 0x9A, 0xF2, +- 0x04, 0xF4, 0xC8, 0x82, 0xFF, 0xB1, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xB1, 0x7A, 0xD4, +- 0xFF, 0xFF, 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, 0x17, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, +- 0xDA, 0x82, 0xA2, 0xD2, 0xA1, 0xFF, 0x09, 0x74, 0x80, 0x4D, 0x0E, 0x00, 0x03, 0xF2, 0x9A, 0xF2, +- 0x04, 0xF4, 0x23, 0x43, 0xA1, 0xFF, 0xA0, 0xD2, 0xFE, 0xA1, 0xCB, 0x83, 0x80, 0x4E, 0xAF, 0x83, +- 0x02, 0x1D, 0x02, 0x03, 0xED, 0x01, 0xE3, 0x01, 0xA1, 0xFF, 0x28, 0x40, 0x40, 0x2B, 0x02, 0x00, +- 0x9C, 0x4E, 0x9C, 0x4C, 0xA1, 0xFF, 0xDA, 0x83, 0x66, 0x44, 0x22, 0x46, 0x0C, 0xFA, 0x0B, 0xFC, +- 0x87, 0x4F, 0x87, 0x4C, 0x87, 0x4F, 0x87, 0x4D, 0x87, 0x4C, 0x01, 0x08, 0x01, 0x00, 0xFF, 0xFF, +- 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x44, 0xBC, 0xFF, +- 0x01, 0x60, 0x08, 0xE1, 0x0C, 0x74, 0x04, 0xE1, 0xA1, 0xFF, 0x35, 0xF3, 0xC4, 0xE2, 0x60, 0x54, +- 0x89, 0xFF, 0x13, 0x74, 0x88, 0xFF, 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, 0x34, 0x64, 0x3A, 0xDB, +- 0x06, 0xE1, 0x47, 0xFF, 0xA4, 0x60, 0x47, 0x78, 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x61, 0x7F, 0x60, +- 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, 0x02, 0x63, 0x26, 0x02, 0x98, 0xFE, 0x1A, 0x05, 0x24, 0x60, +- 0x52, 0x62, 0xA2, 0xD5, 0x0E, 0xF2, 0x15, 0x18, 0x02, 0x18, 0x09, 0xF4, 0xFB, 0x01, 0x23, 0x44, +- 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, 0x66, 0x44, 0x11, 0xFB, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, +- 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x08, 0xB9, 0x10, 0x7E, 0x00, 0x7F, 0x0E, 0xFA, 0x00, 0x67, +- 0x0A, 0x00, 0x20, 0x44, 0xDC, 0x85, 0x0F, 0xB4, 0xFA, 0xA0, 0x7F, 0x67, 0x07, 0x63, 0x03, 0x05, +- 0x45, 0x40, 0x00, 0x67, 0xD8, 0xFE, 0xFF, 0x27, 0x05, 0xFD, 0x0A, 0x7E, 0x04, 0xFB, 0x61, 0x55, +- 0x4A, 0x00, 0x28, 0xFB, 0x01, 0xF3, 0x29, 0xFB, 0x44, 0x46, 0x40, 0x45, 0x10, 0x61, 0x7E, 0x60, +- 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, 0x02, 0x63, 0x31, 0x02, 0xAE, 0x60, 0x58, 0x4F, 0x6F, 0x78, +- 0xFF, 0xFF, 0x7F, 0x67, 0x03, 0x63, 0x2A, 0x02, 0x26, 0x40, 0x01, 0x2B, 0x24, 0x00, 0x98, 0xFE, +- 0x19, 0x05, 0x24, 0x60, 0x52, 0x62, 0xA2, 0xD5, 0x0E, 0xF2, 0x14, 0x18, 0x02, 0x18, 0x09, 0xF4, +- 0xFB, 0x01, 0x23, 0x44, 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, 0x66, 0x44, 0x11, 0xFB, 0x46, 0x43, +- 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x08, 0xB9, 0x10, 0x7E, 0x00, 0x7F, +- 0x0E, 0xFA, 0x09, 0x00, 0x20, 0x44, 0xDC, 0x85, 0x0F, 0xB4, 0xFA, 0xA0, 0x7F, 0x67, 0x07, 0x63, +- 0x05, 0x05, 0x45, 0x40, 0xD8, 0xFE, 0x00, 0x67, 0xD0, 0xFE, 0xD9, 0xFE, 0xFF, 0x27, 0x05, 0xFD, +- 0x0B, 0x7E, 0x04, 0xFB, 0x1C, 0x60, 0xB4, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB0, 0x80, 0xBC, +- 0x08, 0x28, 0xA3, 0xDB, 0x61, 0x55, 0x63, 0x00, 0x04, 0xB5, 0x82, 0xB5, 0x25, 0x02, 0x04, 0x03, +- 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, 0xA3, 0xD3, 0x99, 0xFE, 0x04, 0x04, 0x02, 0xBC, 0xFE, 0xB4, +- 0xA3, 0xDB, 0x56, 0x00, 0xDC, 0xF3, 0x20, 0x40, 0x80, 0x26, 0x52, 0x00, 0xA3, 0xD3, 0xFF, 0xA0, +- 0xF8, 0xB4, 0x02, 0x02, 0xA3, 0xDB, 0x1C, 0x00, 0x04, 0xBC, 0xBF, 0xB4, 0xA3, 0xDB, 0x08, 0xB0, +- 0x01, 0x64, 0x08, 0x24, 0x02, 0x64, 0x28, 0xFB, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, 0xD0, 0xFE, +- 0x3F, 0x00, 0xBF, 0xB4, 0xA3, 0xDB, 0x3C, 0x00, 0x40, 0xB0, 0xFF, 0xFF, 0xFA, 0x02, 0xF8, 0xB4, +- 0xA3, 0xDB, 0x08, 0xB5, 0x07, 0x7C, 0x01, 0x02, 0xDC, 0xF9, 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, +- 0x1C, 0x60, 0xB4, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB5, 0x07, 0xB5, 0x08, 0x28, 0xC4, 0x02, +- 0x99, 0xFE, 0x26, 0x05, 0x20, 0x44, 0x80, 0x26, 0x23, 0x00, 0x20, 0x2A, 0x00, 0x00, 0x40, 0x2A, +- 0x1F, 0x00, 0xBF, 0xB4, 0x40, 0x40, 0x09, 0x00, 0xA8, 0xFF, 0x20, 0x44, 0x99, 0xFE, 0x02, 0x05, +- 0x80, 0x2A, 0x03, 0x00, 0x40, 0xBC, 0x40, 0x40, 0x13, 0x00, 0x00, 0xF1, 0x80, 0xBC, 0x40, 0x40, +- 0x64, 0x44, 0xE0, 0x84, 0xE8, 0x84, 0x0A, 0x36, 0x29, 0x01, 0x0B, 0x36, 0x5A, 0x01, 0x28, 0xFB, +- 0x01, 0xF1, 0x29, 0xF9, 0x02, 0xF1, 0x2A, 0xF9, 0x03, 0xF1, 0x2B, 0xF9, 0xD0, 0xFE, 0xAE, 0xFF, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x82, 0x3E, 0x75, 0x44, 0x02, 0xB0, 0x01, 0xB0, 0x29, 0x02, 0xDC, 0x02, +- 0x04, 0xB0, 0x08, 0xB0, 0x0B, 0x02, 0x20, 0x02, 0x40, 0x26, 0xA7, 0xFF, 0x8C, 0xFF, 0x75, 0x40, +- 0x80, 0x2B, 0x01, 0x00, 0xAB, 0xFF, 0x75, 0x44, 0x8D, 0xFF, 0xEA, 0x01, 0x0A, 0xF3, 0xAA, 0xFF, +- 0x60, 0x40, 0x20, 0x2B, 0x02, 0x00, 0x60, 0xFF, 0x0D, 0x00, 0x01, 0x26, 0x0C, 0x00, 0xC0, 0x60, +- 0x00, 0x7C, 0xA0, 0x84, 0x80, 0x3B, 0x02, 0x00, 0xC0, 0x67, 0x03, 0x00, 0x40, 0x3B, 0x02, 0x00, +- 0x00, 0x67, 0x0A, 0xFB, 0xD5, 0x01, 0xD4, 0x01, 0xAB, 0xFF, 0x38, 0xFF, 0x00, 0x00, 0xD0, 0x01, +- 0x79, 0x63, 0xFF, 0xFF, 0xFF, 0x1F, 0xA9, 0xFF, 0x77, 0x44, 0x60, 0x57, 0x10, 0x60, 0x00, 0x75, +- 0x40, 0x4A, 0x01, 0x2A, 0x1C, 0x00, 0x24, 0x44, 0xAC, 0x86, 0x08, 0xF2, 0x18, 0x03, 0x24, 0x60, +- 0x58, 0x65, 0xD4, 0x80, 0x0E, 0xF2, 0x02, 0x03, 0xA5, 0xD5, 0x04, 0x00, 0x01, 0xBC, 0x0E, 0xFA, +- 0x09, 0xF4, 0xD1, 0xFE, 0x46, 0x44, 0x0B, 0x18, 0x66, 0x44, 0x10, 0xFB, 0x66, 0x47, 0x20, 0xBF, +- 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x0E, 0xF2, 0x01, 0x75, 0x10, 0xBC, 0x0E, 0xFA, 0x2A, 0x44, +- 0x08, 0x2A, 0x18, 0x00, 0x23, 0x44, 0x00, 0xA8, 0x5C, 0x43, 0x14, 0x03, 0x24, 0x60, 0x52, 0x62, +- 0xA2, 0xD5, 0x01, 0x00, 0x09, 0xF4, 0x0E, 0xF2, 0x0D, 0x18, 0x08, 0xB0, 0x18, 0xAC, 0xFA, 0x03, +- 0x0E, 0xFA, 0x66, 0x43, 0x11, 0xFD, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, +- 0xA2, 0xDB, 0x08, 0x75, 0x2A, 0x44, 0x06, 0x22, 0x2D, 0x00, 0x22, 0x44, 0x00, 0xA8, 0x60, 0x46, +- 0x0E, 0xF2, 0x28, 0x03, 0x10, 0xB0, 0x01, 0xBC, 0x03, 0x02, 0x00, 0x64, 0x40, 0x42, 0x22, 0x00, +- 0x0E, 0xFA, 0xD1, 0xFE, 0x24, 0x60, 0x4C, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x84, 0x00, 0x46, 0x42, +- 0x19, 0x02, 0x22, 0x47, 0x40, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x23, 0xF2, 0x66, 0x43, +- 0x00, 0xA8, 0x0E, 0xF2, 0x08, 0x02, 0x60, 0x40, 0x02, 0x2A, 0xE4, 0x01, 0x12, 0xFD, 0x10, 0x64, +- 0x0E, 0xFA, 0x02, 0x75, 0x07, 0x00, 0x60, 0x40, 0x04, 0x2A, 0xDC, 0x01, 0x12, 0xFD, 0x10, 0x64, +- 0x0E, 0xFA, 0x04, 0x75, 0x2A, 0x44, 0x80, 0x2A, 0x19, 0x00, 0x21, 0x44, 0xAC, 0x86, 0x0E, 0xF2, +- 0x15, 0x03, 0x01, 0xBC, 0x0E, 0xFA, 0xD1, 0xFE, 0x24, 0x60, 0x64, 0x64, 0x40, 0x47, 0x58, 0x4F, +- 0x5A, 0x00, 0x46, 0x41, 0x0B, 0x02, 0x21, 0x47, 0x10, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, +- 0x0E, 0xF2, 0x66, 0x43, 0x08, 0xFD, 0x10, 0xBC, 0x0E, 0xFA, 0x80, 0x75, 0x2A, 0x44, 0x10, 0xB0, +- 0x20, 0x44, 0x15, 0x03, 0x7F, 0xB4, 0x40, 0x40, 0x1C, 0x60, 0xB4, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, +- 0x20, 0xB0, 0x80, 0xB0, 0x09, 0x03, 0x08, 0x03, 0x40, 0xBC, 0x7F, 0xB4, 0x04, 0xB0, 0xA3, 0xDB, +- 0x03, 0x03, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, 0xAC, 0x60, 0xD8, 0x78, 0xFF, 0xFF, 0x2A, 0x40, +- 0x08, 0x2B, 0x01, 0x00, 0x10, 0xFF, 0xAD, 0x60, 0x08, 0x78, 0xFF, 0xFF, 0xE8, 0xFE, 0x14, 0x05, +- 0xEA, 0xFE, 0x24, 0x05, 0xE9, 0xFE, 0x1C, 0x05, 0xE7, 0xFE, 0x09, 0x05, 0x47, 0xFF, 0x20, 0x44, +- 0x0F, 0x22, 0x03, 0x00, 0xCC, 0x84, 0x40, 0x40, 0x0F, 0x22, 0xB8, 0xFE, 0xEC, 0x01, 0x23, 0x41, +- 0x00, 0xB9, 0x5C, 0x4A, 0xE8, 0x02, 0x6A, 0x01, 0x24, 0x41, 0x00, 0xB9, 0x24, 0x60, 0x58, 0x65, +- 0x45, 0x47, 0xE1, 0x02, 0x58, 0x4F, 0x0F, 0x00, 0xDE, 0x02, 0x5C, 0x4A, 0x46, 0x44, 0x4C, 0x01, +- 0x22, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0x08, 0x24, 0x7D, 0x01, 0xD5, 0x01, 0x21, 0x41, 0x00, 0xB9, +- 0x5C, 0x4A, 0xA2, 0x03, 0xD0, 0x01, 0x27, 0xD3, 0x03, 0x00, 0x10, 0xB0, 0x09, 0xF2, 0x04, 0x03, +- 0xAC, 0x86, 0x0E, 0xF2, 0xFA, 0x02, 0x08, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0E, 0xF3, 0x0F, 0x60, +- 0xFE, 0x65, 0x0C, 0xF3, 0x24, 0x86, 0x24, 0x46, 0x60, 0x40, 0xFB, 0x3B, 0x07, 0x00, 0x80, 0x26, +- 0x02, 0x00, 0x23, 0x46, 0x03, 0x4C, 0x46, 0x61, 0x3A, 0x65, 0x0C, 0x00, 0x2E, 0xF3, 0x40, 0x45, +- 0xF8, 0x2B, 0x02, 0x00, 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, 0x39, 0x00, 0x07, 0x02, 0x58, 0x4F, +- 0x45, 0x00, 0x04, 0x05, 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, +- 0x0E, 0xFB, 0x2E, 0xF5, 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, 0x00, 0x72, 0x7E, 0x71, 0xAC, 0xFF, +- 0xAD, 0x60, 0x08, 0x78, 0xFF, 0xFF, 0x8E, 0xFF, 0x0F, 0xF3, 0x0F, 0x60, 0xFE, 0x65, 0x24, 0x86, +- 0x0D, 0xF3, 0x2E, 0xF3, 0x40, 0x45, 0xF8, 0x2B, 0x02, 0x00, 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, +- 0x16, 0x00, 0x07, 0x02, 0x58, 0x4F, 0x22, 0x00, 0x04, 0x05, 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, +- 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, 0x0F, 0xFB, 0x2E, 0xF5, 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, +- 0x00, 0x72, 0x7E, 0x71, 0x8D, 0xFF, 0xAD, 0xFF, 0xAD, 0x60, 0x08, 0x78, 0xFF, 0xFF, 0x25, 0x44, +- 0xAA, 0xF1, 0xAB, 0xF1, 0xD0, 0x80, 0xD0, 0x80, 0x07, 0x04, 0x01, 0x06, 0x05, 0x00, 0x25, 0x46, +- 0x01, 0xF0, 0x03, 0x67, 0xA0, 0x85, 0x94, 0x80, 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x46, 0x26, 0x41, +- 0x46, 0x63, 0x01, 0xF2, 0xFF, 0xFF, 0xFF, 0xB5, 0xD5, 0x81, 0x00, 0xF2, 0x05, 0x04, 0x04, 0x63, +- 0x60, 0x46, 0xF7, 0x1B, 0x42, 0xFE, 0x0D, 0x00, 0x61, 0x44, 0xC5, 0x81, 0x63, 0x45, 0xC5, 0x81, +- 0x9C, 0x84, 0xDC, 0x84, 0x01, 0xF2, 0xF0, 0x85, 0xF0, 0x80, 0x65, 0x44, 0xF8, 0x85, 0xFF, 0xFF, +- 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x24, 0x60, 0x6A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, +- 0xAC, 0x86, 0x0E, 0xF2, 0x07, 0x03, 0x00, 0xA8, 0x09, 0xF2, 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, +- 0x08, 0xFE, 0x17, 0x00, 0xAC, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, 0x00, 0xB4, 0x12, 0x06, 0x09, 0x60, +- 0x08, 0x61, 0x41, 0x4A, 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, 0xAE, 0x60, 0x58, 0x4E, 0xE4, 0x78, +- 0xFF, 0xFF, 0xA3, 0xFF, 0x06, 0x03, 0x2A, 0x43, 0xAF, 0x60, 0x58, 0x4E, 0x05, 0x78, 0xFF, 0xFF, +- 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0x41, 0x4A, 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, +- 0xAE, 0x60, 0x58, 0x4E, 0xE4, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x2A, 0x43, 0xAF, 0x60, 0x58, 0x4E, +- 0x05, 0x78, 0xFF, 0xFF, 0x08, 0xFE, 0x0D, 0x00, 0x24, 0x60, 0x6A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, +- 0xAC, 0x86, 0x0E, 0xF2, 0x06, 0x03, 0x00, 0xA8, 0x09, 0xF2, 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, +- 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0xAD, 0xF3, 0x7C, 0x63, 0x00, 0xBE, 0x40, 0x45, +- 0x1A, 0x03, 0x00, 0x65, 0x65, 0x44, 0xDC, 0x85, 0x84, 0xA1, 0x00, 0xF2, 0x06, 0x06, 0x01, 0xFC, +- 0x00, 0xA8, 0x60, 0x46, 0xF7, 0x02, 0x40, 0x45, 0x0E, 0x00, 0xAC, 0xF3, 0x00, 0x63, 0xD4, 0x84, +- 0xAC, 0xFB, 0x80, 0x60, 0x7C, 0x64, 0x01, 0xFA, 0x00, 0xF0, 0x00, 0xFC, 0xD3, 0x80, 0xAD, 0xF9, +- 0x02, 0x02, 0xAE, 0xF9, 0x08, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x66, 0x44, 0x25, 0x46, 0x05, 0xFA, +- 0x06, 0xFA, 0x01, 0xF0, 0x03, 0x67, 0x02, 0xFC, 0xB0, 0x84, 0x3A, 0x7E, 0x01, 0xFA, 0x12, 0x64, +- 0x03, 0xFA, 0x00, 0xF0, 0x04, 0xF8, 0x00, 0x64, 0x0C, 0x61, 0x10, 0x63, 0x59, 0xDA, 0xFE, 0x1F, +- 0x2E, 0x58, 0xFF, 0xFF, 0x27, 0x43, 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, 0x16, 0x03, 0x00, 0x61, +- 0x01, 0x00, 0xE4, 0x63, 0x61, 0x46, 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, 0xA2, 0xDA, 0xBE, 0xD2, +- 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, 0x25, 0x44, 0x61, 0x46, 0xA3, 0xDA, 0x04, 0x00, 0x0A, 0xFA, +- 0x60, 0x46, 0x25, 0x44, 0x09, 0xFA, 0x61, 0x46, 0xBE, 0xDA, 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x44, +- 0x00, 0xA8, 0x07, 0x4B, 0x0C, 0x03, 0x58, 0x4F, 0x33, 0x00, 0x0B, 0x47, 0x24, 0x60, 0x5E, 0x65, +- 0x27, 0x44, 0xD4, 0x80, 0x00, 0x64, 0x01, 0x02, 0x0F, 0xFA, 0x58, 0x4F, 0xD3, 0x01, 0x70, 0x00, +- 0x25, 0x43, 0xE3, 0x84, 0x7C, 0x41, 0x02, 0x04, 0xE8, 0x81, 0xE4, 0x63, 0x61, 0x46, 0xA3, 0xD2, +- 0x00, 0x7C, 0x40, 0x45, 0xBF, 0xD8, 0xA3, 0xD8, 0xBE, 0xD8, 0x27, 0x42, 0x5A, 0xD3, 0x25, 0x5C, +- 0x60, 0x41, 0x02, 0x1B, 0x27, 0xD9, 0x05, 0x00, 0x25, 0x46, 0x0A, 0xFA, 0x61, 0x46, 0x25, 0x44, +- 0x09, 0xFA, 0x25, 0x44, 0x27, 0x43, 0x00, 0x61, 0x60, 0x46, 0x09, 0xF2, 0x08, 0xFC, 0x00, 0xA8, +- 0xDD, 0x81, 0xFA, 0x02, 0xBF, 0xD1, 0x66, 0x44, 0xBE, 0xDB, 0xC1, 0x84, 0xBF, 0xDB, 0x48, 0x00, +- 0x25, 0x46, 0xE4, 0x63, 0x08, 0xF2, 0x89, 0xF2, 0x1E, 0x18, 0x40, 0x47, 0xE0, 0x84, 0xE8, 0x85, +- 0x02, 0x05, 0xE8, 0x83, 0x00, 0x65, 0x65, 0x46, 0xBF, 0xD2, 0x61, 0x5C, 0xCC, 0x84, 0xA2, 0xDA, +- 0x25, 0x46, 0x0A, 0xF2, 0x00, 0xB9, 0x65, 0x46, 0x08, 0x24, 0xBE, 0xDA, 0x02, 0x1B, 0xA3, 0xD8, +- 0x02, 0x00, 0x60, 0x46, 0x89, 0xFA, 0x00, 0xB9, 0x61, 0x46, 0x08, 0x28, 0x0A, 0xFA, 0x25, 0x46, +- 0x89, 0xFC, 0x8A, 0xFC, 0x88, 0xFC, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x61, 0x28, 0x65, 0x25, 0x43, +- 0xAE, 0xF3, 0xAF, 0x83, 0x00, 0xBE, 0x18, 0x03, 0x02, 0x03, 0x00, 0xFC, 0x01, 0x00, 0xAD, 0xFD, +- 0x63, 0x46, 0x65, 0x44, 0xCC, 0x85, 0x00, 0xF2, 0x07, 0x02, 0xAE, 0xF5, 0x00, 0x64, 0x00, 0xFA, +- 0xDE, 0x60, 0xAF, 0x64, 0x09, 0xFB, 0x08, 0x00, 0x66, 0x43, 0x00, 0xBE, 0xDD, 0x81, 0xF1, 0x02, +- 0xAC, 0xF1, 0xAE, 0xFD, 0xC1, 0x84, 0xAC, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x45, +- 0x29, 0x43, 0xFC, 0xA3, 0x66, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x00, 0x64, 0xBD, 0xDB, +- 0x03, 0x61, 0x0E, 0x65, 0x24, 0x60, 0x72, 0x63, 0x43, 0x49, 0xA3, 0xD3, 0x06, 0xA3, 0x00, 0xA8, +- 0xCD, 0x81, 0x04, 0x02, 0xF9, 0x02, 0xAD, 0x60, 0x08, 0x78, 0xFF, 0xFF, 0x01, 0x26, 0xE6, 0x01, +- 0xD4, 0x80, 0x60, 0x45, 0xE3, 0x05, 0xF6, 0xA3, 0xBD, 0xD1, 0xBD, 0xD1, 0x44, 0x47, 0x44, 0x48, +- 0x44, 0x45, 0x24, 0x60, 0xB0, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x24, 0x60, 0x22, 0x63, +- 0x0D, 0x65, 0x00, 0x61, 0x41, 0x48, 0xA3, 0xD3, 0x06, 0xA3, 0xAC, 0x86, 0x00, 0x61, 0x09, 0x03, +- 0x00, 0xF2, 0x09, 0xF0, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x64, 0x44, 0xAC, 0x86, +- 0xF6, 0x01, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x65, 0x44, 0x28, 0x45, 0x45, 0x88, 0xCC, 0x85, +- 0x5A, 0x87, 0xE9, 0x02, 0x00, 0x64, 0x27, 0xDA, 0x5A, 0xDA, 0x5A, 0x87, 0xA9, 0xF3, 0xA8, 0xF1, +- 0x02, 0xA4, 0x60, 0x46, 0x60, 0x45, 0x00, 0x61, 0x1E, 0xF2, 0xFF, 0xFF, 0xAC, 0x86, 0x00, 0xF2, +- 0x04, 0x03, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x65, 0x44, 0x02, 0xA5, 0x65, 0x46, +- 0x64, 0x44, 0xCC, 0x9C, 0xFF, 0xFF, 0xF0, 0x02, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x5A, 0x87, +- 0x28, 0x45, 0x45, 0x88, 0x00, 0x64, 0x27, 0xDA, 0x5A, 0x87, 0x06, 0x60, 0x40, 0x65, 0xAD, 0xF3, +- 0x01, 0x61, 0xAC, 0x86, 0x00, 0xF2, 0x03, 0x03, 0xD5, 0x80, 0xDD, 0x81, 0xFA, 0x04, 0xCD, 0x84, +- 0x25, 0x46, 0x27, 0xDA, 0x28, 0x45, 0xC4, 0x84, 0x5A, 0xDA, 0xDA, 0x81, 0xAC, 0xF1, 0x59, 0xD8, +- 0x24, 0x60, 0x20, 0x64, 0x18, 0x63, 0xA0, 0xD1, 0x06, 0xA4, 0x59, 0xD8, 0xFC, 0x1F, 0x00, 0x64, +- 0x59, 0xDA, 0x59, 0xDA, 0x01, 0x60, 0x5C, 0x64, 0x0A, 0x63, 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, +- 0xDC, 0xF1, 0x59, 0xD8, 0x75, 0x01, 0x07, 0x4B, 0xAF, 0x60, 0x58, 0x4F, 0x70, 0x78, 0xFF, 0xFF, +- 0x0B, 0x47, 0x58, 0x4F, 0x21, 0x00, 0x6C, 0x01, 0x07, 0x4B, 0xAF, 0x60, 0x58, 0x4F, 0x70, 0x78, +- 0xFF, 0xFF, 0x0B, 0x47, 0x27, 0x44, 0x00, 0xBE, 0x08, 0xF0, 0x15, 0x03, 0x64, 0x42, 0x4A, 0xD3, +- 0x09, 0xF2, 0xDC, 0x83, 0xA2, 0xDD, 0x25, 0x43, 0x09, 0xFC, 0x63, 0x46, 0x27, 0x43, 0x0A, 0xFC, +- 0x09, 0xFA, 0x08, 0xF8, 0x00, 0xA8, 0x66, 0x43, 0x03, 0x02, 0x64, 0x44, 0x58, 0xDD, 0x03, 0x00, +- 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, 0x4C, 0x01, 0x27, 0x43, 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, +- 0x16, 0x03, 0x00, 0x61, 0x01, 0x00, 0xE4, 0x63, 0x61, 0x46, 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, +- 0xA2, 0xDA, 0xA3, 0xD2, 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, 0x25, 0x44, 0x61, 0x46, 0xBE, 0xDA, +- 0x04, 0x00, 0x09, 0xFA, 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, 0x61, 0x46, 0xA3, 0xDA, 0x2F, 0x58, +- 0xFF, 0xFF, 0xA0, 0xFE, 0x07, 0x05, 0xA3, 0xFE, 0x07, 0x05, 0xA1, 0xFE, 0x52, 0x05, 0x60, 0x64, +- 0x3B, 0xDB, 0x12, 0x00, 0x20, 0x58, 0xFF, 0xFF, 0x4F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0x60, +- 0xB8, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0xFB, 0xB4, 0xA3, 0xDB, 0xA0, 0x4C, 0x59, 0xBC, 0xFF, 0xB4, +- 0xA0, 0x51, 0xA0, 0x4C, 0x7D, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x83, 0x3E, 0x40, 0x60, +- 0x0B, 0x65, 0x2B, 0x44, 0x00, 0x63, 0xE8, 0x80, 0xF8, 0x84, 0x02, 0x24, 0x94, 0x84, 0xF3, 0x83, +- 0xCD, 0x81, 0xFF, 0xFF, 0xF8, 0x02, 0xDF, 0x83, 0x2F, 0x58, 0x40, 0x4B, 0x00, 0x62, 0x01, 0x64, +- 0xD4, 0x80, 0xE0, 0x84, 0x1A, 0x03, 0xD4, 0x80, 0xE0, 0x84, 0x15, 0x03, 0x61, 0x44, 0x11, 0x61, +- 0xE0, 0x84, 0xCD, 0x81, 0xFD, 0x04, 0x01, 0x00, 0xE0, 0x84, 0xF2, 0x82, 0xFF, 0xFF, 0x02, 0x24, +- 0xC6, 0x82, 0x02, 0x28, 0xD6, 0x82, 0xE2, 0x80, 0xCD, 0x81, 0x02, 0x28, 0x01, 0xBC, 0xF4, 0x02, +- 0x01, 0x2A, 0xC6, 0x82, 0x03, 0x00, 0xE9, 0x81, 0xF2, 0x82, 0x61, 0x44, 0x2D, 0x58, 0xFF, 0xFF, +- 0x00, 0xA8, 0x10, 0x61, 0x04, 0x03, 0xF0, 0x84, 0xCD, 0x81, 0xFD, 0x04, 0x61, 0x44, 0x2D, 0x58, +- 0xFF, 0xFF, 0x00, 0x64, 0x3B, 0xDB, 0x3C, 0x44, 0xAC, 0x80, 0xFF, 0xFF, 0xBD, 0x02, 0x8B, 0xF3, +- 0x8C, 0xF3, 0x02, 0xA8, 0x02, 0xA8, 0x08, 0x02, 0x00, 0x64, 0x8D, 0xFB, 0x8B, 0xFB, 0x8C, 0xFB, +- 0x00, 0x64, 0x8E, 0xFB, 0xCA, 0xFE, 0x2D, 0x00, 0x03, 0x02, 0x00, 0x64, 0x8C, 0xFB, 0xCA, 0xFE, +- 0x01, 0x64, 0x3B, 0xDB, 0x24, 0x60, 0x28, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, +- 0x14, 0x03, 0xDC, 0xF3, 0x2A, 0xF2, 0xFD, 0xA0, 0x60, 0x40, 0x80, 0x3A, 0x29, 0x00, 0x28, 0x02, +- 0x9B, 0xFE, 0x26, 0x05, 0x24, 0x60, 0x6E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xE5, 0x01, 0x8C, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, +- 0xFF, 0xFF, 0x07, 0x02, 0x24, 0x60, 0x22, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, +- 0x0F, 0x02, 0x86, 0xFF, 0x20, 0x40, 0x52, 0x27, 0x07, 0x00, 0x9A, 0xFE, 0x05, 0x04, 0x9D, 0xFE, +- 0x03, 0x04, 0xF1, 0xFE, 0x12, 0x64, 0x3B, 0xDB, 0x84, 0xFF, 0xB0, 0x60, 0x97, 0x78, 0xFF, 0xFF, +- 0x66, 0x44, 0xFC, 0xFB, 0x46, 0x5C, 0x2D, 0x60, 0x5A, 0x63, 0xA3, 0xD3, 0xB0, 0x60, 0x58, 0x4D, +- 0xD8, 0x78, 0xFF, 0xFF, 0x0D, 0xF2, 0x60, 0x5C, 0x64, 0x5F, 0x0D, 0xFA, 0x11, 0x64, 0x3B, 0xDB, +- 0x9D, 0xFE, 0x0B, 0x05, 0x24, 0x60, 0x92, 0x65, 0x08, 0x64, 0xA5, 0xDB, 0xB1, 0x60, 0x4D, 0x64, +- 0x4F, 0xFB, 0x2D, 0xFF, 0xB0, 0x60, 0xA4, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x00, 0x64, 0xD0, 0x80, +- 0xA9, 0xF3, 0x07, 0x02, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xB8, 0x60, 0x36, 0x78, +- 0xFF, 0xFF, 0xD0, 0x80, 0xD8, 0xF3, 0x40, 0x03, 0x60, 0x40, 0x03, 0x3A, 0x3D, 0x00, 0x66, 0x41, +- 0x64, 0x46, 0x6F, 0xF2, 0x61, 0x46, 0x64, 0x41, 0x4D, 0xF1, 0x60, 0x40, 0x03, 0x3A, 0x34, 0x00, +- 0x64, 0x40, 0xFF, 0x22, 0x31, 0x00, 0x05, 0x7E, 0x66, 0x45, 0x61, 0x46, 0x6F, 0xFA, 0x65, 0x46, +- 0x07, 0xF0, 0x00, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, +- 0x6F, 0xF2, 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, +- 0x0E, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, +- 0xE8, 0x84, 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, +- 0xFF, 0xFF, 0x00, 0x64, 0x4D, 0xFB, 0x4C, 0xFB, 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, +- 0x61, 0x46, 0xFF, 0xFF, 0xF0, 0x7E, 0x4E, 0xFB, 0x2A, 0xF2, 0x00, 0x63, 0x40, 0x47, 0x50, 0x36, +- 0x05, 0x00, 0xA4, 0x36, 0x03, 0x00, 0x80, 0x36, 0x01, 0x00, 0x01, 0x63, 0x48, 0xFD, 0x40, 0x47, +- 0x08, 0x2A, 0x0A, 0x00, 0x03, 0x2F, 0x08, 0x00, 0x81, 0xF1, 0x2C, 0xF8, 0x82, 0xF1, 0xFF, 0xFF, +- 0x2D, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0xFF, 0xFF, 0x4A, 0xF3, 0x35, 0xFA, 0x10, 0xA4, 0x4A, 0xFB, +- 0x00, 0x64, 0x15, 0xFA, 0x16, 0xFA, 0x0F, 0xFA, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, +- 0x0E, 0xF0, 0x63, 0x46, 0x00, 0x7F, 0x64, 0x5E, 0x4B, 0xFB, 0x64, 0x44, 0x00, 0x7E, 0xDB, 0xFB, +- 0x07, 0xF0, 0xA9, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0xDB, 0xF3, 0xDA, 0xFB, +- 0x60, 0x41, 0x03, 0xF2, 0x00, 0xF4, 0x01, 0xF2, 0xFC, 0xA5, 0x00, 0x7F, 0xD4, 0x84, 0x27, 0x45, +- 0x3C, 0x46, 0x1A, 0xFA, 0x22, 0x63, 0x7B, 0x60, 0xFF, 0x64, 0xA4, 0x84, 0x03, 0x2B, 0x1C, 0x63, +- 0x2A, 0xFA, 0x60, 0x40, 0xA4, 0x36, 0x14, 0x63, 0x43, 0x4C, 0x00, 0x7C, 0x22, 0xF8, 0x64, 0x41, +- 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x36, 0xF2, 0x63, 0x46, 0xFF, 0xB4, 0x22, 0xFA, 0x60, 0x40, +- 0x00, 0x36, 0x76, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x3A, 0xA5, 0x00, 0x03, 0xF2, +- 0x00, 0xF4, 0xA0, 0xD2, 0xAA, 0x60, 0xAA, 0x65, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, 0x0A, 0x02, +- 0xD0, 0x80, 0x00, 0x64, 0x5A, 0xD0, 0x06, 0x02, 0xD0, 0x80, 0xF8, 0x7F, 0xD0, 0x80, 0x01, 0x03, +- 0x01, 0x02, 0x01, 0x61, 0x62, 0x43, 0x46, 0x43, 0x3C, 0x46, 0x07, 0xF4, 0x36, 0xF2, 0xFF, 0xFF, +- 0xA3, 0x46, 0x60, 0x40, 0x22, 0x26, 0x5C, 0x00, 0x60, 0x45, 0x63, 0x42, 0x5A, 0xD0, 0xCD, 0x81, +- 0x3C, 0x46, 0x14, 0x02, 0x64, 0x44, 0x88, 0x3A, 0x11, 0x00, 0x8E, 0x3B, 0x0F, 0x00, 0x65, 0x44, +- 0x01, 0x26, 0x7A, 0x00, 0x04, 0x26, 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, 0x2D, 0x00, 0xA3, 0x46, +- 0x37, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, 0x6F, 0x00, 0x56, 0x00, 0xA3, 0x46, 0x65, 0x44, +- 0x01, 0x26, 0x0B, 0x00, 0x04, 0x26, 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, 0x1D, 0x00, 0x37, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x27, 0x48, 0x00, 0x17, 0x00, 0xA9, 0xF3, 0xFF, 0xFF, 0x60, 0x46, +- 0x36, 0xF2, 0x66, 0x43, 0xFF, 0xB4, 0x3C, 0x46, 0x22, 0xF0, 0x60, 0x47, 0xB0, 0x84, 0x22, 0xFA, +- 0x63, 0x46, 0x37, 0xF0, 0x60, 0x40, 0x04, 0x27, 0x03, 0x00, 0x10, 0x27, 0x01, 0x00, 0x04, 0x00, +- 0x64, 0x40, 0x80, 0x27, 0x31, 0x00, 0x00, 0x00, 0x3C, 0x46, 0x02, 0x65, 0xB7, 0x60, 0x66, 0x78, +- 0xFF, 0xFF, 0xCD, 0x81, 0x63, 0x42, 0x5A, 0xD0, 0x3C, 0x46, 0x26, 0x02, 0x64, 0x44, 0x88, 0x3A, +- 0x23, 0x00, 0x77, 0x37, 0x39, 0x00, 0x78, 0x37, 0x37, 0x00, 0x8E, 0x37, 0x35, 0x00, 0xF1, 0x01, +- 0x2D, 0x60, 0x52, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x2D, 0x00, 0x07, 0x00, +- 0x2D, 0x60, 0x52, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0xE2, 0x01, 0x3C, 0x46, +- 0x3E, 0xF2, 0x40, 0x60, 0x00, 0x65, 0xF0, 0x84, 0xA4, 0x84, 0x18, 0xFA, 0x2A, 0xF2, 0xBF, 0x60, +- 0xFF, 0x65, 0xA4, 0x84, 0x2A, 0xFA, 0x18, 0x00, 0x3C, 0x46, 0x22, 0xF0, 0x80, 0x67, 0xB0, 0x84, +- 0xA2, 0xDA, 0xFF, 0xFF, 0x3F, 0xF2, 0x3E, 0xF0, 0x08, 0xA4, 0x60, 0x41, 0x22, 0xF2, 0xFF, 0xFF, +- 0x60, 0x40, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x03, 0x00, 0x06, 0x00, 0x04, 0x2B, 0x04, 0x00, +- 0x61, 0x44, 0x64, 0x40, 0x10, 0x26, 0x3F, 0xFA, 0x3C, 0x46, 0x2C, 0xF2, 0x27, 0x40, 0x01, 0x27, +- 0x32, 0xF2, 0xD5, 0xF1, 0x60, 0x40, 0x01, 0x26, 0x53, 0x00, 0x09, 0x60, 0x00, 0x64, 0xD0, 0x80, +- 0x3F, 0xF2, 0x09, 0x06, 0x2C, 0x45, 0xC4, 0x84, 0xD0, 0x80, 0x40, 0x4A, 0x40, 0x06, 0x60, 0x43, +- 0x64, 0x44, 0x54, 0x88, 0x18, 0x00, 0x60, 0x45, 0x28, 0x60, 0x36, 0x64, 0xA0, 0xD3, 0xDB, 0xF3, +- 0x00, 0xBC, 0x60, 0x47, 0xEC, 0xA0, 0x33, 0x03, 0x32, 0x07, 0x2C, 0x44, 0xC4, 0x81, 0x02, 0x60, +- 0x1C, 0x65, 0x45, 0x4A, 0xD5, 0x80, 0x2C, 0x45, 0x2A, 0x06, 0x27, 0x40, 0x04, 0x27, 0x30, 0x00, +- 0x2A, 0x43, 0xD7, 0x85, 0x45, 0x48, 0xD6, 0xF1, 0x0F, 0xF2, 0xD3, 0x80, 0x01, 0x65, 0x01, 0x07, +- 0x00, 0x65, 0xB4, 0x84, 0x0F, 0xFA, 0x00, 0x63, 0x3F, 0xF2, 0x28, 0x45, 0x60, 0x41, 0xD4, 0x84, +- 0xDF, 0x83, 0xFC, 0x07, 0x14, 0xFC, 0x61, 0x44, 0x01, 0x36, 0x02, 0x00, 0x09, 0x3A, 0x06, 0x00, +- 0x28, 0x44, 0x48, 0x88, 0x2A, 0x44, 0xC8, 0x83, 0x43, 0x4A, 0xE5, 0x01, 0x17, 0xFA, 0x04, 0x60, +- 0x00, 0x64, 0x27, 0x45, 0xB4, 0x84, 0x2A, 0xFA, 0x28, 0x43, 0x16, 0xFC, 0x0D, 0x00, 0x3F, 0xF2, +- 0x2C, 0x45, 0xD6, 0xF1, 0xC4, 0x81, 0xD1, 0x80, 0x0F, 0xF2, 0x01, 0x06, 0x01, 0xBC, 0x0F, 0xFA, +- 0x3F, 0xF2, 0x17, 0xFA, 0x01, 0x64, 0x14, 0xFA, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x0E, 0xF0, +- 0x63, 0x46, 0x00, 0x7F, 0x64, 0x5E, 0x4B, 0xFB, 0x64, 0x44, 0x00, 0x7E, 0xDB, 0xFB, 0x7C, 0xF1, +- 0x60, 0x43, 0x60, 0x47, 0xD0, 0x80, 0xC0, 0x65, 0x01, 0x06, 0x64, 0x44, 0x0A, 0x36, 0x70, 0x64, +- 0x14, 0x36, 0x38, 0x64, 0x37, 0x36, 0x15, 0x64, 0x6E, 0x36, 0x0B, 0x64, 0x44, 0x86, 0x2A, 0xF2, +- 0x07, 0xF0, 0x60, 0x40, 0xB0, 0x3A, 0x03, 0x00, 0x40, 0x3B, 0x01, 0x00, 0x12, 0x00, 0x0C, 0xB4, +- 0x08, 0x3A, 0x55, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, 0x50, 0x00, 0x17, 0xF2, +- 0x22, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x22, 0x22, 0x04, 0x00, 0x00, 0xA8, 0x01, 0xA8, 0x47, 0x03, +- 0x46, 0x03, 0x3C, 0x46, 0x2A, 0xF0, 0x40, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x60, 0x45, 0x22, 0xF2, +- 0xFF, 0xFF, 0x60, 0x43, 0x60, 0x40, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x0A, 0x00, 0x02, 0x00, +- 0x04, 0x27, 0x07, 0x00, 0x65, 0x44, 0x2A, 0x65, 0x60, 0x40, 0x03, 0x2B, 0x24, 0x65, 0x45, 0x4C, +- 0x2E, 0x00, 0x65, 0x44, 0x2E, 0x65, 0x60, 0x40, 0x03, 0x2B, 0x28, 0x65, 0x45, 0x4C, 0x07, 0xF0, +- 0xA9, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0x00, 0x7C, 0x03, 0x03, 0x63, 0x40, 0x01, 0x2A, 0x01, 0x00, +- 0x3D, 0xF1, 0x2A, 0xF2, 0xFF, 0xFF, 0x08, 0xB0, 0x3E, 0xF2, 0x19, 0x03, 0x60, 0x47, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0x03, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, 0x11, 0x03, 0x24, 0x60, 0x6E, 0x62, +- 0x24, 0x60, 0x46, 0x64, 0xA2, 0xDB, 0x3C, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x5C, 0x5C, 0xFC, 0xFC, 0xCE, 0xFE, 0xB0, 0x60, 0xE1, 0x78, 0xFF, 0xFF, 0xDB, 0xF1, +- 0x2C, 0x45, 0x64, 0x43, 0x17, 0xF2, 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, +- 0x63, 0x40, 0x37, 0x37, 0xE1, 0x81, 0x64, 0x45, 0xB0, 0x60, 0x58, 0x4D, 0xB6, 0x78, 0xFF, 0xFF, +- 0xAE, 0x82, 0xFC, 0xA2, 0x0A, 0x03, 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, 0x04, 0x0D, +- 0x63, 0x44, 0x80, 0x7E, 0xDB, 0xFB, 0x61, 0x44, 0xDC, 0x84, 0x2B, 0xF0, 0x1B, 0xFA, 0x64, 0x44, +- 0x80, 0x27, 0x34, 0x00, 0x16, 0xF2, 0x0F, 0xF0, 0xAC, 0x84, 0x2C, 0x45, 0x29, 0x03, 0x4B, 0xF1, +- 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x63, 0x40, 0x37, 0x37, 0xE1, 0x81, 0x64, 0x45, +- 0x0F, 0xF0, 0xB0, 0x60, 0x58, 0x4D, 0xB6, 0x78, 0xFF, 0xFF, 0xAE, 0x82, 0xFC, 0xA2, 0x0A, 0x03, +- 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, 0x04, 0x0D, 0x80, 0x67, 0xB0, 0x84, 0x0F, 0xFA, +- 0x61, 0x44, 0xDC, 0x84, 0x1D, 0xFA, 0xDE, 0x65, 0xC4, 0x85, 0x26, 0x41, 0xE1, 0x81, 0xC5, 0x84, +- 0x2B, 0xFA, 0x1B, 0xF0, 0xDE, 0x64, 0xC0, 0x85, 0x26, 0x44, 0xE0, 0x84, 0xC4, 0x84, 0x10, 0xFA, +- 0x26, 0x44, 0x2C, 0xF0, 0x0A, 0xA4, 0x64, 0x40, 0x01, 0x26, 0x00, 0x64, 0x11, 0xFA, 0xDB, 0xF3, +- 0x13, 0xFA, 0xFF, 0xFF, 0x0D, 0xF2, 0x3E, 0xF0, 0x60, 0x47, 0xFF, 0xB4, 0x64, 0x41, 0x01, 0xB1, +- 0x01, 0x63, 0x1D, 0x02, 0x60, 0x41, 0xFF, 0x22, 0x04, 0x00, 0xB0, 0x60, 0x58, 0x4F, 0xA7, 0x78, +- 0xFF, 0xFF, 0x0F, 0x60, 0x92, 0x64, 0xA0, 0xDD, 0x2D, 0x60, 0x5A, 0x62, 0xA2, 0xD3, 0xB0, 0x60, +- 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x60, 0x41, 0x01, 0x63, 0x61, 0x40, 0xFF, 0x22, 0x04, 0x00, +- 0xB0, 0x60, 0x58, 0x4F, 0xA7, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0x94, 0x64, 0xA0, 0xDD, 0x2A, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, 0x03, 0x00, 0xB5, 0x60, 0x19, 0x78, 0xFF, 0xFF, 0x22, 0xF2, +- 0x46, 0x43, 0x60, 0x40, 0x22, 0x26, 0x8B, 0x00, 0x01, 0x26, 0x05, 0x00, 0x04, 0x26, 0x0C, 0x00, +- 0xB5, 0x60, 0x19, 0x78, 0xFF, 0xFF, 0x04, 0x27, 0x03, 0x00, 0xB5, 0x60, 0x19, 0x78, 0xFF, 0xFF, +- 0xA9, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x02, 0x00, 0x07, 0xF4, 0xFF, 0xFF, 0xA3, 0x46, 0x2A, 0xF2, +- 0xA3, 0x46, 0x60, 0x40, 0x08, 0x27, 0x3B, 0x00, 0xA9, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x37, 0xF0, +- 0x08, 0x03, 0x64, 0x40, 0x10, 0x2A, 0x12, 0x00, 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, 0x37, 0xFA, +- 0x24, 0x00, 0x3D, 0xF3, 0x01, 0x61, 0x60, 0x43, 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, 0xE9, 0x81, +- 0xA1, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0x91, 0x84, 0x37, 0xFA, 0x17, 0x00, 0x47, 0xF2, 0xFF, 0xFF, +- 0x10, 0xA0, 0xFF, 0xFF, 0x02, 0x04, 0xFF, 0x60, 0xFF, 0x64, 0xDC, 0x84, 0x47, 0xFA, 0x46, 0xF2, +- 0x16, 0x04, 0xDC, 0x84, 0x46, 0xFA, 0x45, 0xF2, 0x08, 0x04, 0xDC, 0x84, 0x45, 0xFA, 0x05, 0x04, +- 0x37, 0xF2, 0xFF, 0xFF, 0xE0, 0x84, 0xE8, 0x84, 0x37, 0xFA, 0x0D, 0x60, 0x3E, 0x62, 0x80, 0xFF, +- 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xBE, 0x60, 0x66, 0x78, 0xFF, 0xFF, 0x84, 0xFF, 0x0D, 0x60, +- 0x3E, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xBE, 0x60, 0xDE, 0x78, 0xFF, 0xFF, +- 0x84, 0xFF, 0xA9, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, 0x3C, 0x46, +- 0x22, 0xF2, 0x63, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x47, 0xF0, 0x64, 0x41, +- 0x64, 0x47, 0xFF, 0xB4, 0x60, 0x5F, 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, 0xA3, 0x46, +- 0x3A, 0xFA, 0x64, 0x44, 0x20, 0x7F, 0x34, 0x94, 0x3B, 0xFA, 0xA3, 0x46, 0x46, 0xF2, 0x45, 0xF0, +- 0xA3, 0x46, 0x3C, 0xFA, 0x3D, 0xF8, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, +- 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x8A, 0x00, 0x2A, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x27, 0x35, 0x00, 0x2A, 0xF2, 0x00, 0x60, 0x7C, 0x62, 0x60, 0x40, +- 0x40, 0x2B, 0x27, 0x00, 0xA2, 0xD3, 0x00, 0x61, 0x60, 0xFE, 0xA0, 0xD3, 0xDE, 0x82, 0xA2, 0xD1, +- 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, 0xC0, 0x2B, 0x04, 0x00, 0x80, 0x2A, +- 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, 0x60, 0x47, 0xDC, 0x87, 0x01, 0x61, +- 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, 0xDA, 0x82, 0xA2, 0xD1, 0xFF, 0xFF, +- 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, 0xA2, 0xDB, 0xFF, 0xFF, +- 0x20, 0xFE, 0x00, 0x60, 0x7C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD3, 0x5A, 0xD1, 0x3A, 0xFA, +- 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5A, 0x64, 0x47, +- 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x80, 0x62, +- 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, 0x64, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5A, +- 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5A, 0x64, 0x47, +- 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5A, 0x65, 0x40, 0x0D, 0x3A, +- 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5A, +- 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5A, 0x64, 0x47, +- 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEE, 0x7F, +- 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5A, 0x08, 0x60, 0x00, 0xEA, 0x65, 0x44, +- 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, +- 0x00, 0xEA, 0x02, 0x64, 0x3B, 0xDB, 0xB8, 0x60, 0xBE, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0xFC, 0xFB, +- 0x07, 0xF0, 0x00, 0x64, 0xD0, 0x80, 0xA9, 0xF3, 0x17, 0x03, 0xD0, 0x80, 0x66, 0x41, 0x64, 0x46, +- 0x6F, 0xF2, 0x61, 0x46, 0x7B, 0x03, 0x60, 0x40, 0x00, 0x36, 0x78, 0x00, 0x47, 0xF1, 0x07, 0xF0, +- 0x64, 0x40, 0x02, 0x26, 0x01, 0x00, 0x0B, 0x00, 0x03, 0x12, 0xB6, 0x60, 0x38, 0x78, 0xFF, 0xFF, +- 0xFC, 0x0A, 0xB7, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0xB7, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0x66, 0x41, +- 0x64, 0x46, 0x0E, 0xF2, 0x60, 0x45, 0x61, 0x46, 0x10, 0x7E, 0x4E, 0xFB, 0x65, 0x44, 0x60, 0x40, +- 0x01, 0x36, 0x5C, 0x00, 0x02, 0x36, 0x5D, 0x00, 0x03, 0x36, 0x34, 0x00, 0x04, 0x36, 0x45, 0x00, +- 0x67, 0x00, 0x00, 0x64, 0x4C, 0xFB, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x05, 0x7E, +- 0x6F, 0xFA, 0x61, 0x46, 0x00, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, +- 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, +- 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, +- 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, +- 0x0C, 0xF4, 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xFF, 0xFF, 0xA0, 0x7E, +- 0x4E, 0xFB, 0x24, 0x00, 0x4C, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x4C, 0xFB, 0xCB, 0xF3, 0x60, 0x45, +- 0xD4, 0x80, 0xFF, 0xFF, 0x1B, 0x02, 0x24, 0x60, 0xA6, 0x62, 0x0F, 0x60, 0x96, 0x64, 0xA2, 0xDB, +- 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xBC, 0x01, 0x4C, 0xF3, 0x66, 0x41, 0xDC, 0x84, +- 0x4C, 0xFB, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x03, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x66, 0x41, +- 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xFF, 0xFF, 0xA4, 0x7E, 0x4E, 0xFB, 0xB7, 0x60, 0x56, 0x78, +- 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x6F, 0xFA, 0x61, 0x46, +- 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xFF, 0xFF, 0xA8, 0x7E, 0x4E, 0xFB, 0xEE, 0x01, +- 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0x8C, 0xFA, 0x60, 0x47, 0x70, 0xF2, 0xFF, 0xB5, 0x08, 0x18, +- 0xE4, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0xFB, 0x04, 0x01, 0x64, 0x01, 0x00, 0x00, 0x64, +- 0x0C, 0xF4, 0x00, 0xA8, 0xFF, 0xFF, 0xDD, 0x02, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, +- 0x60, 0x47, 0x70, 0xF2, 0xFF, 0xB5, 0x61, 0x46, 0x00, 0xA8, 0xFF, 0xFF, 0x29, 0x03, 0xE0, 0x84, +- 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0x66, 0x41, 0x64, 0x46, 0x70, 0xFA, 0x61, 0x46, 0x01, 0x65, +- 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, +- 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, +- 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, +- 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, 0x95, 0x01, +- 0x94, 0x01, 0x65, 0x44, 0x60, 0x40, 0x01, 0x36, 0xA1, 0x01, 0x02, 0x36, 0x01, 0x00, 0x9E, 0x01, +- 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x00, 0x65, +- 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, +- 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, +- 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, +- 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, 0x66, 0x41, +- 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xD0, 0x7E, 0x4E, 0xFB, 0xB7, 0x60, 0x56, 0x78, 0xFF, 0xFF, +- 0x60, 0x45, 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0x20, 0x7E, 0x4E, 0xFB, 0x65, 0x44, +- 0x60, 0x40, 0x01, 0x36, 0x0B, 0x00, 0x02, 0x36, 0x1A, 0x00, 0x03, 0x36, 0x53, 0x00, 0x04, 0x36, +- 0x70, 0x00, 0x05, 0x36, 0x14, 0x00, 0xB7, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x41, +- 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x02, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x66, 0x41, 0x64, 0x46, +- 0x0E, 0xF2, 0x61, 0x46, 0xB0, 0x7E, 0x4E, 0xFB, 0xB7, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0x07, 0xF0, +- 0x01, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, +- 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, +- 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, +- 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, +- 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0x00, 0x63, 0x03, 0x7E, 0x6F, 0xFA, 0x61, 0x46, 0x4C, 0xFD, +- 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xB4, 0x7E, 0x4E, 0xFB, 0x24, 0x60, 0xA6, 0x62, +- 0x0F, 0x60, 0x96, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xB7, 0x60, +- 0x56, 0x78, 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x4C, 0xF3, 0x02, 0xB0, 0x61, 0x46, +- 0xCC, 0x84, 0x05, 0x03, 0x04, 0x28, 0x4C, 0xFB, 0xB7, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0x04, 0x28, +- 0x4C, 0xFB, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x04, 0x7E, 0x6F, 0xFA, 0x61, 0x46, +- 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xB8, 0x7E, 0x4E, 0xFB, 0xB7, 0x60, 0x56, 0x78, +- 0xFF, 0xFF, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, +- 0x61, 0x46, 0xFF, 0xA0, 0xFF, 0xFF, 0x35, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, +- 0xFB, 0x04, 0x2F, 0x00, 0x64, 0x46, 0x70, 0xFA, 0x01, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, +- 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, +- 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, +- 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, +- 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, 0x6F, 0xF2, 0x00, 0x63, 0x03, 0x7E, 0x6F, 0xFA, +- 0x3C, 0x46, 0x4C, 0xFD, 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xC0, 0x7E, 0x4E, 0xFB, +- 0x5D, 0x00, 0x5C, 0x00, 0x65, 0x44, 0x60, 0x40, 0x01, 0x36, 0x03, 0x00, 0x02, 0x36, 0x18, 0x00, +- 0x55, 0x00, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x61, 0x46, 0x01, 0xB0, 0xFF, 0xFF, 0x4E, 0x02, +- 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x02, 0x7E, 0x6F, 0xFA, 0x61, 0x46, +- 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xE0, 0x7E, 0x4E, 0xFB, 0x3F, 0x00, 0x3E, 0x00, +- 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x6F, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x6F, 0xFA, 0x60, 0x47, +- 0xFF, 0xB5, 0x70, 0xF2, 0x61, 0x46, 0xFF, 0xA0, 0xFF, 0xFF, 0xF1, 0x06, 0xE8, 0x84, 0xA4, 0x80, +- 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0xEB, 0x01, 0x66, 0x41, 0x64, 0x46, 0x70, 0xFA, 0x61, 0x46, +- 0x00, 0x65, 0x65, 0x43, 0x66, 0x41, 0x64, 0x46, 0x70, 0xF2, 0x8C, 0xFA, 0x00, 0xA8, 0x6F, 0xF2, +- 0x15, 0x03, 0x60, 0x47, 0xFF, 0xB5, 0x70, 0xF2, 0x00, 0xBB, 0xFF, 0xA0, 0x07, 0x03, 0x0E, 0x06, +- 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0x02, 0x02, 0xFB, 0x04, 0x08, 0x00, 0xB9, 0x81, 0xE8, 0x84, +- 0xD9, 0x81, 0xFD, 0x04, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x0C, 0xF4, 0xFF, 0xFF, +- 0x66, 0x41, 0x64, 0x46, 0x0E, 0xF2, 0x61, 0x46, 0xE4, 0x7E, 0x4E, 0xFB, 0x03, 0x64, 0x3B, 0xDB, +- 0xCA, 0xFE, 0x47, 0xF1, 0x01, 0x65, 0x32, 0x40, 0x04, 0x27, 0x08, 0x00, 0x2C, 0xF2, 0x64, 0x45, +- 0x02, 0x22, 0x04, 0x00, 0x60, 0x40, 0x01, 0x26, 0x01, 0x00, 0xE3, 0x00, 0x14, 0xF2, 0x65, 0x40, +- 0x01, 0x26, 0x1D, 0x00, 0x60, 0x45, 0x05, 0x64, 0x3B, 0xDB, 0x65, 0x44, 0xCC, 0x85, 0xB8, 0xF1, +- 0x27, 0x60, 0x78, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, +- 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, +- 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xAF, 0x00, 0x60, 0x41, +- 0x2A, 0xF0, 0x00, 0x60, 0x0C, 0x64, 0xA0, 0x84, 0x04, 0x36, 0x02, 0x00, 0x0C, 0x3A, 0x01, 0x00, +- 0xA5, 0x00, 0x61, 0x45, 0x60, 0x41, 0xB8, 0xF1, 0x27, 0x60, 0x78, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, +- 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, +- 0x00, 0x75, 0x88, 0xFF, 0x61, 0x40, 0x08, 0x36, 0x01, 0x00, 0x88, 0x00, 0x14, 0xF2, 0x1C, 0x65, +- 0x60, 0x41, 0x00, 0x63, 0xCD, 0x81, 0xC7, 0x83, 0xFD, 0x02, 0x3F, 0xF0, 0x2C, 0xF2, 0xC3, 0x83, +- 0x60, 0x40, 0x01, 0x2A, 0x29, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x76, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, +- 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xB8, 0xF1, 0x27, 0x60, 0x7C, 0x64, 0xA0, 0xD3, +- 0x63, 0x45, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, +- 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, +- 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x52, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x74, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, +- 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xB8, 0xF1, 0x27, 0x60, 0x7A, 0x64, +- 0xA0, 0xD3, 0x63, 0x45, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, +- 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, +- 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x15, 0xF2, 0xFF, 0xFF, 0x0F, 0xB4, 0x00, 0xA8, +- 0x01, 0xA8, 0x24, 0x03, 0x12, 0x03, 0xB8, 0xF1, 0x27, 0x60, 0x82, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, +- 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x11, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x80, 0x64, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, +- 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x04, 0x64, 0x3B, 0xDB, +- 0x24, 0x60, 0x6E, 0x62, 0x24, 0x60, 0x46, 0x64, 0xA2, 0xDB, 0x3C, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x5C, 0x5C, 0xFC, 0xFC, 0xCE, 0xFE, 0xB0, 0x60, 0xE1, 0x78, +- 0xFF, 0xFF, 0x0F, 0xF0, 0x15, 0xF2, 0x64, 0x41, 0x01, 0x2A, 0x02, 0x00, 0xD1, 0xF1, 0x02, 0x00, +- 0xD0, 0xF1, 0xFF, 0xFF, 0x64, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x15, 0xFA, 0x30, 0x07, 0x61, 0x40, +- 0x01, 0x2A, 0x09, 0x00, 0x27, 0x60, 0xA8, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, +- 0x08, 0x28, 0xA2, 0xDB, 0x08, 0x00, 0x27, 0x60, 0xAA, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, +- 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x2A, 0xF0, 0x08, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x00, 0x64, +- 0x48, 0xFB, 0x2D, 0x60, 0x52, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0C, 0x00, +- 0x3C, 0x46, 0x3E, 0xF2, 0x40, 0x60, 0x00, 0x65, 0xF0, 0x84, 0xA4, 0x84, 0x18, 0xFA, 0x2A, 0xF2, +- 0xBF, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x2A, 0xFA, 0xB2, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0x00, 0x64, +- 0x49, 0xFB, 0xB8, 0xF1, 0x27, 0x60, 0x82, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, +- 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, +- 0x00, 0x75, 0x88, 0xFF, 0xB8, 0xF1, 0x27, 0x60, 0x84, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, +- 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, +- 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x2D, 0x60, 0x5A, 0x63, 0xA3, 0xD3, 0xB0, 0x60, 0x58, 0x4D, +- 0xD8, 0x78, 0xFF, 0xFF, 0x0D, 0xF2, 0x60, 0x5C, 0x64, 0x5F, 0x0D, 0xFA, 0x23, 0xF0, 0x01, 0x64, +- 0xB0, 0x84, 0xA2, 0xDA, 0x7B, 0x01, 0xB9, 0x60, 0x43, 0x78, 0xFF, 0xFF, 0x21, 0x64, 0x3B, 0xDB, +- 0x31, 0xF3, 0x01, 0x63, 0xC4, 0xB4, 0x31, 0xFB, 0x32, 0xFD, 0xB8, 0x60, 0xEF, 0x62, 0x42, 0x40, +- 0xA0, 0x4C, 0x40, 0xBC, 0x7D, 0xB4, 0xA0, 0x51, 0xA0, 0xFE, 0x1A, 0xFF, 0x24, 0x60, 0x3A, 0x64, +- 0x08, 0xF0, 0x07, 0xF0, 0xD0, 0x80, 0x24, 0x60, 0x40, 0x62, 0x14, 0x02, 0xA2, 0xD3, 0x01, 0x63, +- 0xAC, 0x86, 0x07, 0xF2, 0x0F, 0x03, 0xD0, 0x80, 0x09, 0xF2, 0xFA, 0x02, 0x23, 0xFC, 0x24, 0x60, +- 0x6E, 0x62, 0x24, 0x60, 0x46, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0x3C, 0x46, 0x06, 0x64, 0xA1, 0xFF, 0x49, 0xFB, 0x83, 0x3E, 0x31, 0xF3, +- 0x87, 0x60, 0x80, 0x61, 0x1D, 0xF0, 0x60, 0x40, 0x01, 0x2A, 0x15, 0x00, 0xFE, 0xB4, 0x31, 0xFB, +- 0x00, 0x64, 0x49, 0xFB, 0x01, 0x64, 0x47, 0xFB, 0x2D, 0x60, 0x5A, 0x63, 0xA3, 0xD3, 0xB0, 0x60, +- 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x71, 0x64, 0x5F, 0x0D, 0xFA, 0x40, 0x64, 0x3B, 0xDB, +- 0xB9, 0x60, 0x43, 0x78, 0xFF, 0xFF, 0x02, 0x2A, 0x1B, 0x00, 0xD1, 0x91, 0x8D, 0xE2, 0x41, 0x64, +- 0x3B, 0xDB, 0x31, 0xF3, 0x2D, 0x60, 0x62, 0x63, 0xFD, 0xB4, 0x31, 0xFB, 0xA3, 0xD3, 0xB0, 0x60, +- 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x02, 0x63, 0x60, 0x5C, 0x0D, 0xF2, 0x47, 0xFD, 0xFF, 0xB5, +- 0x60, 0x47, 0xD0, 0x80, 0xDC, 0x84, 0x1F, 0x03, 0x60, 0x47, 0xB4, 0x84, 0x0D, 0xFA, 0x1B, 0x00, +- 0x08, 0x2A, 0x07, 0x00, 0x42, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xF7, 0xB4, 0x31, 0xFB, +- 0x12, 0x00, 0x10, 0x2A, 0x09, 0x00, 0x43, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xEF, 0xB4, +- 0x31, 0xFB, 0xB8, 0x60, 0xBE, 0x78, 0xFF, 0xFF, 0x44, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, +- 0xDF, 0xB4, 0x31, 0xFB, 0x00, 0x00, 0x2A, 0x64, 0x3B, 0xDB, 0xB0, 0x60, 0x97, 0x64, 0x40, 0x40, +- 0xB5, 0x60, 0x1E, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xB8, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x02, 0xB5, +- 0x04, 0xB5, 0x04, 0x03, 0x03, 0x03, 0xBA, 0x60, 0x3C, 0x78, 0xFF, 0xFF, 0x86, 0xFF, 0x20, 0x44, +- 0x84, 0xFF, 0x20, 0x2A, 0x04, 0x00, 0xF3, 0x60, 0x58, 0x4E, 0x14, 0x78, 0xFF, 0xFF, 0x31, 0x40, +- 0x01, 0x26, 0x17, 0x00, 0xA0, 0x4C, 0x49, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0x1C, 0x60, 0xB8, 0x63, +- 0xA3, 0xD3, 0xFF, 0xFF, 0x02, 0xB5, 0x04, 0xBC, 0x09, 0x03, 0x60, 0x40, 0x01, 0x26, 0xED, 0xE2, +- 0xFE, 0xB4, 0xA3, 0xDB, 0xA0, 0x4C, 0x7D, 0xB4, 0xA0, 0x51, 0x03, 0x00, 0xA0, 0x4C, 0x6D, 0xB4, +- 0xA0, 0x51, 0xDC, 0xF3, 0xFF, 0xFF, 0xFD, 0xA0, 0xFF, 0xFF, 0x48, 0x03, 0x31, 0x40, 0x04, 0x2A, +- 0x3E, 0x00, 0x6D, 0xF3, 0x74, 0xF3, 0xCC, 0x83, 0x6D, 0xFD, 0xCC, 0x84, 0x74, 0xFB, 0x1F, 0x02, +- 0x31, 0x40, 0x02, 0x2A, 0x12, 0x00, 0x6F, 0xF3, 0x70, 0xF1, 0xCC, 0x84, 0x6F, 0xFB, 0x0D, 0x02, +- 0x6F, 0xF9, 0x31, 0x44, 0x08, 0xBC, 0x40, 0x51, 0x72, 0xF3, 0x71, 0xF1, 0x00, 0xB8, 0x64, 0x45, +- 0x01, 0x03, 0x67, 0x45, 0x65, 0x50, 0xCC, 0x84, 0x73, 0xFB, 0x28, 0x60, 0x00, 0x64, 0xA0, 0xD3, +- 0x6E, 0xF1, 0x00, 0xB8, 0x74, 0xF9, 0x03, 0x03, 0x87, 0xF3, 0x6D, 0xFB, 0x04, 0x00, 0x6D, 0xF3, +- 0x87, 0xF1, 0x15, 0x1B, 0x6D, 0xF9, 0x31, 0x40, 0x01, 0x2A, 0x11, 0x00, 0xDD, 0xFE, 0x0F, 0x05, +- 0xBA, 0xFE, 0xAD, 0x4F, 0x00, 0x7F, 0x01, 0xBC, 0xA0, 0x5D, 0x00, 0xEE, 0x7F, 0xF1, 0x02, 0x60, +- 0xEE, 0x64, 0xA3, 0xFB, 0xA4, 0xF9, 0x04, 0x64, 0xA5, 0xFB, 0xDF, 0xFE, 0x19, 0xFF, 0x1A, 0x60, +- 0x42, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xFF, 0x2B, 0xA2, 0xDB, 0x31, 0x40, 0x01, 0x2A, +- 0x29, 0x00, 0x9D, 0xFE, 0x27, 0x04, 0x26, 0x0A, 0x9F, 0xFE, 0x24, 0x05, 0x85, 0xFF, 0x20, 0x44, +- 0x84, 0xFF, 0x40, 0x26, 0x1F, 0x00, 0x3F, 0x40, 0x20, 0x2B, 0x1C, 0x00, 0x38, 0x69, 0xFF, 0xFF, +- 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, 0x01, 0x2A, 0x15, 0x00, 0x27, 0x60, 0xB4, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x7F, 0xF1, 0x02, 0x60, 0xEE, 0x64, +- 0xA3, 0xFB, 0xFF, 0xFF, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA4, 0xFB, 0x04, 0x64, 0xA5, 0xFB, +- 0xDF, 0xFE, 0x19, 0xFF, 0x10, 0x64, 0x3B, 0xDB, 0x80, 0xF3, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0xC9, 0xFE, 0x49, 0xF3, 0x3C, 0x46, 0x27, 0x18, 0xCC, 0x84, +- 0x49, 0xFB, 0x24, 0x02, 0xBB, 0x60, 0x18, 0x64, 0x40, 0x42, 0xFC, 0xFC, 0x00, 0x64, 0x5C, 0x5C, +- 0x32, 0xFB, 0x82, 0xFF, 0x5C, 0x47, 0x84, 0xFF, 0x62, 0xFF, 0x27, 0x60, 0xA4, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0x23, 0xF0, 0x01, 0x64, 0xB0, 0x84, +- 0xA2, 0xDA, 0x24, 0x60, 0x6E, 0x62, 0x24, 0x60, 0x46, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0xCE, 0xFE, 0x6A, 0xF3, 0xFF, 0xFF, +- 0x60, 0x41, 0xFD, 0xB4, 0xA2, 0xDB, 0x61, 0x44, 0x01, 0xB0, 0x02, 0xB0, 0x0C, 0x03, 0x0B, 0x02, +- 0x9D, 0xFE, 0x09, 0x04, 0x24, 0x60, 0xA6, 0x62, 0x1A, 0x60, 0xA2, 0x64, 0xA2, 0xDB, 0x02, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x07, 0x00, 0x80, 0xF3, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0x1C, 0x60, 0xB4, 0x63, 0xA3, 0xD3, 0xAD, 0x49, 0x20, 0xB5, +- 0x08, 0xB1, 0x23, 0x03, 0xE1, 0x81, 0x10, 0xB5, 0x95, 0x81, 0x60, 0x41, 0x18, 0x02, 0x1C, 0x60, +- 0xB6, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, 0xA4, 0xDB, 0x17, 0x02, 0x05, 0x64, 0xA4, 0xDB, +- 0x61, 0x44, 0x07, 0xB4, 0xFF, 0xFF, 0x11, 0x02, 0x08, 0xB1, 0xE1, 0x81, 0x95, 0x81, 0xA3, 0xD3, +- 0x0C, 0x03, 0x08, 0xAC, 0x01, 0xBC, 0xA3, 0xDB, 0xFF, 0xFF, 0x13, 0xFF, 0x06, 0x00, 0x10, 0xAC, +- 0xA3, 0xDB, 0x1C, 0x60, 0xB6, 0x63, 0x05, 0x7C, 0xA3, 0xD9, 0xB0, 0x60, 0xA4, 0x78, 0xFF, 0xFF, +- 0x46, 0xF3, 0x45, 0xF1, 0x05, 0x1B, 0x64, 0x44, 0x03, 0x1B, 0x0F, 0x60, 0x92, 0x62, 0xA2, 0xD3, +- 0x45, 0xFB, 0x00, 0x63, 0x46, 0xFD, 0x60, 0x41, 0x25, 0x64, 0x3B, 0xDB, 0x27, 0x44, 0xEF, 0xB4, +- 0x40, 0x47, 0x00, 0xB9, 0x71, 0x40, 0x80, 0x27, 0x01, 0x12, 0x2B, 0x03, 0xBA, 0x60, 0x93, 0x62, +- 0x84, 0xFF, 0x42, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0x31, 0x0A, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x2B, 0x0A, 0x71, 0x40, 0x80, 0x27, +- 0xF7, 0x12, 0x45, 0xF3, 0x4C, 0x02, 0x15, 0x18, 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, +- 0x0B, 0x18, 0x31, 0x60, 0x10, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0x06, 0x18, 0xAC, 0x4C, 0x80, 0x26, +- 0x03, 0x00, 0x00, 0x64, 0x45, 0xFB, 0x05, 0x00, 0x45, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0x45, 0xFB, +- 0xDF, 0x02, 0x06, 0x0A, 0xA0, 0x4C, 0xFB, 0xB4, 0xA0, 0x51, 0xA3, 0x60, 0x99, 0x78, 0xFF, 0xFF, +- 0x84, 0xFF, 0xBA, 0x60, 0x70, 0x64, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, +- 0xA0, 0x51, 0xAB, 0x60, 0x2C, 0x78, 0xFF, 0xFF, 0x3C, 0x44, 0xAC, 0x80, 0x32, 0xF1, 0x25, 0x03, +- 0x64, 0x40, 0x07, 0x22, 0x22, 0x00, 0xA3, 0x60, 0x7B, 0x78, 0xFF, 0xFF, 0xA0, 0x4C, 0x1C, 0xBC, +- 0xDF, 0xB4, 0xA0, 0x51, 0x31, 0x40, 0x08, 0x2A, 0xEF, 0x01, 0x73, 0xF3, 0x71, 0xF1, 0x00, 0xA0, +- 0xDC, 0x80, 0x05, 0x03, 0x08, 0x03, 0xCC, 0x84, 0x73, 0xFB, 0x67, 0x50, 0x08, 0x00, 0xCC, 0x84, +- 0x73, 0xFB, 0x64, 0x50, 0x04, 0x00, 0x31, 0x44, 0xF7, 0xB4, 0x40, 0x51, 0x06, 0x00, 0x28, 0x64, +- 0x3A, 0xDB, 0xA0, 0x4C, 0x30, 0xBC, 0xF3, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, +- 0x28, 0x64, 0x3B, 0xDB, 0x0F, 0x60, 0x94, 0x62, 0xA2, 0xD3, 0x32, 0x40, 0x02, 0x27, 0x16, 0x00, +- 0x46, 0xFB, 0x14, 0x18, 0xBB, 0x60, 0x06, 0x64, 0x84, 0xFF, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, +- 0x14, 0xBC, 0xF7, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, +- 0x46, 0xF3, 0xB7, 0x0A, 0xDC, 0x02, 0xCC, 0x84, 0x46, 0xFB, 0xF5, 0x02, 0x84, 0xFF, 0xBB, 0x60, +- 0x18, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x27, 0x44, 0x08, 0xBC, 0x40, 0x47, 0xBB, 0xE1, 0x04, 0x00, +- 0x3A, 0xE1, 0x31, 0x40, 0x01, 0x26, 0xBB, 0xE1, 0xA3, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x43, 0xFF, +- 0x39, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x84, 0x3E, 0xFB, 0x01, 0xA0, 0x4C, 0x3D, 0x46, 0x2A, 0xF2, +- 0x46, 0x4D, 0x10, 0x25, 0x0E, 0x00, 0x09, 0xE1, 0xA1, 0xFF, 0x66, 0x40, 0x0F, 0xF2, 0x01, 0x29, +- 0x02, 0x00, 0x40, 0xFF, 0x0A, 0xBC, 0xA2, 0xDA, 0x08, 0x25, 0xE9, 0x01, 0xCB, 0xFE, 0x5C, 0x5D, +- 0xE7, 0x01, 0x44, 0xFF, 0x31, 0xF2, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, +- 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, +- 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, +- 0x07, 0xFC, 0x3F, 0xF2, 0x09, 0x60, 0xB0, 0x65, 0xD4, 0x80, 0x2A, 0xF2, 0xC4, 0x05, 0x08, 0x25, +- 0xB6, 0x01, 0x00, 0x64, 0x0D, 0x60, 0x2C, 0x61, 0x40, 0x4B, 0xA1, 0xDB, 0x2D, 0x46, 0x3B, 0xF2, +- 0xA9, 0xF1, 0x87, 0xF4, 0x60, 0x40, 0x20, 0x2B, 0x12, 0x00, 0xD3, 0x80, 0x2C, 0xF0, 0xB3, 0x03, +- 0x07, 0xF4, 0x64, 0x40, 0x01, 0x26, 0xA9, 0xF5, 0xB6, 0xF4, 0x2D, 0x46, 0x04, 0x64, 0x04, 0xB3, +- 0x22, 0xFA, 0x04, 0x03, 0xBC, 0x60, 0x72, 0x78, 0xFF, 0xFF, 0x01, 0x00, 0xDE, 0x00, 0x74, 0x62, +- 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, +- 0xA0, 0x5B, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0x7C, 0x5F, 0xE8, 0x84, 0xE8, 0x85, +- 0x0C, 0x60, 0x3A, 0x64, 0x44, 0xD3, 0x5A, 0xD1, 0x03, 0x1B, 0xBC, 0x60, 0x65, 0x78, 0xFF, 0xFF, +- 0x60, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, +- 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, +- 0xE7, 0x7F, 0xA0, 0x5B, 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, +- 0xA0, 0x5B, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, +- 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, +- 0xED, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xEF, 0x7F, +- 0xA0, 0x5B, 0x65, 0x44, 0xD8, 0x84, 0x08, 0x25, 0x76, 0x00, 0x60, 0x7F, 0xA0, 0x5B, 0x80, 0x60, +- 0x00, 0xEB, 0xA0, 0x60, 0x00, 0xEB, 0xD1, 0x60, 0x00, 0xEB, 0x3F, 0xF2, 0x04, 0x65, 0xC4, 0x83, +- 0x0A, 0xE1, 0xB3, 0xFF, 0x9A, 0xFF, 0xCB, 0x83, 0x00, 0xF4, 0x10, 0x62, 0x6C, 0x61, 0x0E, 0xA3, +- 0xAB, 0x84, 0xF2, 0xA3, 0xA1, 0xFF, 0x08, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0x02, 0x62, 0xC9, 0x81, +- 0xAB, 0x84, 0xA1, 0xFF, 0x01, 0x00, 0xA2, 0xDC, 0x7A, 0xD4, 0xFD, 0x1C, 0xA2, 0xDC, 0x08, 0x25, +- 0x52, 0x00, 0xF2, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, 0xEF, 0x03, 0xFF, 0xB1, 0x09, 0x1E, 0x02, 0x02, +- 0x00, 0xF4, 0x02, 0x62, 0x5A, 0xD2, 0x89, 0xFF, 0x80, 0x4F, 0x6F, 0x44, 0xA2, 0xDA, 0x88, 0xFF, +- 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, 0x3D, 0x46, 0x08, 0x25, 0x3D, 0x00, 0x40, 0xFF, 0x0F, 0xF0, +- 0x0A, 0x64, 0xB0, 0x84, 0x16, 0x14, 0xF7, 0xB4, 0xA2, 0xDA, 0x0D, 0x60, 0x2C, 0x62, 0xA2, 0xD3, +- 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0C, 0x00, 0xF1, 0xF5, 0xF0, 0xF4, 0x0D, 0x60, 0x2C, 0x61, +- 0x59, 0xD1, 0x37, 0xF8, 0x05, 0x64, 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, 0xFC, 0x02, 0x2D, 0x46, +- 0x0D, 0x01, 0xA2, 0xDA, 0x2D, 0x46, 0x3B, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x20, 0x2B, 0x18, 0x00, +- 0xF1, 0xF5, 0xB7, 0xF0, 0x2A, 0x44, 0xA4, 0x84, 0xFF, 0xFF, 0x2F, 0x26, 0x10, 0x00, 0x2D, 0x46, +- 0x64, 0x44, 0x3A, 0xF0, 0xBC, 0xF0, 0x64, 0x5F, 0x3D, 0xF0, 0x07, 0xF4, 0xF0, 0xF4, 0xFF, 0xFF, +- 0x08, 0xA3, 0x5B, 0xD8, 0x65, 0x5C, 0x5B, 0xD8, 0x5B, 0xDA, 0x2D, 0x46, 0x01, 0x00, 0x2D, 0x46, +- 0xBB, 0x60, 0x36, 0x78, 0xFF, 0xFF, 0x98, 0xFF, 0x43, 0xFF, 0x40, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, +- 0x2D, 0x46, 0x0D, 0x60, 0x2C, 0x61, 0xA1, 0xD3, 0x2D, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x0A, 0x00, +- 0xF1, 0xF5, 0xF0, 0xF4, 0x59, 0xD1, 0x37, 0xF8, 0x05, 0x64, 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, +- 0xFC, 0x02, 0x2D, 0x46, 0xBB, 0x60, 0x20, 0x78, 0xFF, 0xFF, 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, +- 0x3D, 0x46, 0x08, 0x25, 0xE0, 0x01, 0x0F, 0xF2, 0x40, 0xFF, 0x02, 0xBC, 0xA2, 0xDA, 0xBB, 0x60, +- 0x36, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x0D, 0x60, 0x2C, 0x62, 0xA2, 0xDB, 0x04, 0x64, 0x22, 0xFA, +- 0x87, 0xF4, 0xA9, 0xF1, 0xFF, 0xFF, 0xD3, 0x80, 0x3B, 0xF2, 0xE7, 0x03, 0x60, 0x47, 0xC0, 0xB7, +- 0x02, 0xFE, 0xF0, 0x84, 0xF0, 0x84, 0xF0, 0x84, 0x00, 0xA8, 0x40, 0x4A, 0x16, 0x03, 0xE0, 0x81, +- 0x61, 0x43, 0x42, 0xFE, 0x00, 0x64, 0xF0, 0x84, 0xFE, 0x1F, 0x40, 0x4A, 0xE1, 0x84, 0xE0, 0x84, +- 0x2D, 0x46, 0x07, 0xF4, 0xE0, 0x81, 0x37, 0xF0, 0x2A, 0x47, 0x0C, 0x60, 0x7A, 0x63, 0xA0, 0x84, +- 0x47, 0x9C, 0x10, 0x03, 0x7C, 0x44, 0xA0, 0x63, 0x11, 0x00, 0x20, 0x64, 0x40, 0x4A, 0x63, 0x46, +- 0x37, 0xF0, 0x66, 0x44, 0x64, 0x40, 0x80, 0x2B, 0x05, 0x00, 0x00, 0x60, 0x70, 0x7C, 0x00, 0x60, +- 0x90, 0x63, 0x04, 0x00, 0x2D, 0x46, 0xBC, 0x60, 0x65, 0x78, 0xFF, 0xFF, 0x2D, 0x46, 0xEE, 0xFB, +- 0xEF, 0xF9, 0xF0, 0xFD, 0x07, 0xF2, 0xF1, 0xFB, 0x60, 0x46, 0x37, 0xF0, 0x2A, 0x44, 0x0D, 0x60, +- 0x2C, 0x62, 0x5A, 0xD9, 0x00, 0x65, 0x45, 0x4B, 0xA0, 0x84, 0xFF, 0xFF, 0x3F, 0x22, 0x05, 0x00, +- 0x90, 0x84, 0x37, 0xFA, 0x01, 0x64, 0x40, 0x4B, 0x21, 0x00, 0xAD, 0x46, 0x0A, 0xA3, 0x3D, 0xF2, +- 0xAD, 0x46, 0xA3, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3C, 0xF2, 0xAD, 0x46, 0x02, 0x03, 0x16, 0x07, +- 0x14, 0x04, 0x5B, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3B, 0xF2, 0x03, 0x03, 0xAD, 0x46, 0x0E, 0x07, +- 0x0C, 0x04, 0x3A, 0xF0, 0xAD, 0x46, 0x5B, 0xD0, 0x64, 0x5F, 0xD0, 0x80, 0x2B, 0x44, 0x18, 0x07, +- 0x04, 0x03, 0xD0, 0x84, 0x10, 0xA4, 0xFF, 0xFF, 0x13, 0x07, 0x7F, 0x01, 0x01, 0x64, 0x0D, 0x60, +- 0x2C, 0x62, 0xA2, 0xDB, 0x2D, 0x46, 0x0D, 0x60, 0x3C, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, +- 0xA2, 0xDB, 0xBD, 0x60, 0x0B, 0x78, 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x53, 0x01, +- 0x2D, 0x46, 0x0D, 0x60, 0x3C, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xBD, 0x60, +- 0x94, 0x78, 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x45, 0x01, 0x00, 0x60, 0x0F, 0x64, +- 0xBB, 0x60, 0xD3, 0x78, 0xFF, 0xFF, 0x07, 0xF4, 0x66, 0x41, 0x03, 0xF2, 0x04, 0xF2, 0x40, 0x42, +- 0x05, 0xF2, 0x40, 0x43, 0x40, 0x44, 0x61, 0x46, 0x3C, 0xF2, 0x3D, 0xF2, 0x40, 0x40, 0x40, 0x41, +- 0x0D, 0x60, 0x70, 0x65, 0x00, 0x61, 0xEF, 0xF1, 0xEE, 0xF5, 0x44, 0x4C, 0x2C, 0x5C, 0xE9, 0x80, +- 0x00, 0x64, 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x24, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x20, 0x44, 0x40, 0x80, 0xDB, 0x83, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x21, 0x44, 0x40, 0x81, 0xDB, 0x83, 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x22, 0x44, 0x40, 0x82, 0xDB, 0x83, 0xBD, 0xD2, 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x23, 0x44, 0x40, 0x83, 0xF2, 0xA3, 0xBD, 0xD2, 0x23, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x24, 0x44, 0xC0, 0x9C, 0x41, 0x84, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, 0x0D, 0x60, +- 0x2E, 0x61, 0x05, 0x64, 0xF0, 0xF4, 0xF1, 0xF5, 0xFE, 0xA3, 0x5B, 0xD0, 0xCC, 0x84, 0x59, 0xD9, +- 0xFC, 0x02, 0xF0, 0xF3, 0xF1, 0xF5, 0x60, 0x42, 0x20, 0x44, 0xA2, 0xDA, 0x21, 0x44, 0x5A, 0xDA, +- 0x22, 0x44, 0x5A, 0xDA, 0x23, 0x44, 0x5A, 0xDA, 0x24, 0x44, 0x5A, 0xDA, 0x61, 0x46, 0x0D, 0x60, +- 0x3C, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x41, 0xF0, 0xF3, 0xF1, 0xF5, 0xA0, 0xD2, +- 0x5A, 0xD0, 0x40, 0x40, 0x44, 0x41, 0x5A, 0xD2, 0x5A, 0xD0, 0x40, 0x42, 0x5A, 0xD0, 0x44, 0x43, +- 0x61, 0x46, 0xBA, 0xF0, 0x3B, 0xF2, 0x44, 0x44, 0x65, 0x5F, 0x40, 0x85, 0xEF, 0xF4, 0xEE, 0xF5, +- 0x43, 0x4C, 0x0D, 0x60, 0x70, 0x65, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x20, 0x44, 0x40, 0x80, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x21, 0x44, +- 0x40, 0x81, 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x22, 0x44, 0x40, 0x82, +- 0xBD, 0xD2, 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x23, 0x44, 0x40, 0x83, 0xBD, 0xD2, +- 0x23, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x24, 0x44, 0x40, 0x84, 0xBD, 0xD2, 0x24, 0x5C, +- 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x25, 0x44, 0x40, 0x85, 0x61, 0x46, 0x3A, 0xF0, 0xFF, 0xFF, +- 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5B, 0x64, 0x44, +- 0xE2, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xEE, 0xF5, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x84, 0xE8, 0x80, +- 0xF8, 0x84, 0x20, 0x5C, 0x40, 0x80, 0x20, 0x44, 0xE4, 0x7F, 0xA0, 0x5B, 0x20, 0x47, 0xE5, 0x7F, +- 0xA0, 0x5B, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x21, 0x5C, 0x40, 0x81, +- 0x21, 0x44, 0xE6, 0x7F, 0xA0, 0x5B, 0x21, 0x47, 0xE7, 0x7F, 0xA0, 0x5B, 0x21, 0x44, 0xE8, 0x80, +- 0xF8, 0x84, 0x22, 0x5C, 0x40, 0x82, 0x22, 0x44, 0xE8, 0x7F, 0xA0, 0x5B, 0x22, 0x47, 0xE9, 0x7F, +- 0xA0, 0x5B, 0x22, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x23, 0x5C, 0x40, 0x83, 0x23, 0x44, 0xEA, 0x7F, +- 0xA0, 0x5B, 0x23, 0x47, 0xEB, 0x7F, 0xA0, 0x5B, 0x23, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x24, 0x5C, +- 0x40, 0x84, 0x24, 0x44, 0xEC, 0x7F, 0xA0, 0x5B, 0x24, 0x47, 0xED, 0x7F, 0xA0, 0x5B, 0x24, 0x44, +- 0xE8, 0x80, 0xF8, 0x84, 0x25, 0x5C, 0x40, 0x85, 0x25, 0x44, 0xEE, 0x7F, 0xA0, 0x5B, 0x25, 0x47, +- 0xEF, 0x7F, 0xA0, 0x5B, 0x2C, 0x43, 0xA3, 0xD2, 0x25, 0x5C, 0x90, 0x81, 0xE9, 0x84, 0xE3, 0x7F, +- 0xA0, 0x5B, 0x0D, 0x60, 0x3C, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0xF3, 0x5A, 0xD3, +- 0x40, 0x48, 0x5A, 0xD3, 0x40, 0x49, 0x40, 0x4A, 0x00, 0x60, 0x70, 0x7C, 0x44, 0x4D, 0x45, 0xF2, +- 0x46, 0xF2, 0x40, 0x47, 0x40, 0x46, 0x0D, 0x60, 0x70, 0x65, 0x00, 0x61, 0x2D, 0x5C, 0xE9, 0x80, +- 0x00, 0x64, 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x26, 0x44, 0x40, 0x86, 0xDB, 0x83, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x27, 0x44, 0x40, 0x87, 0xDB, 0x83, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x28, 0x44, 0x40, 0x88, 0xDB, 0x83, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x29, 0x44, 0x40, 0x89, 0xF2, 0xA3, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x2A, 0x44, 0xC0, 0x9C, 0x41, 0x8A, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, 0x26, 0x44, +- 0x40, 0xFA, 0x27, 0x44, 0x41, 0xFA, 0x28, 0x44, 0x42, 0xFA, 0x29, 0x44, 0x43, 0xFA, 0x2A, 0x44, +- 0x44, 0xFA, 0x0D, 0x60, 0x3E, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x80, 0x7C, +- 0x44, 0x4D, 0x2D, 0x42, 0xA2, 0xD2, 0x5A, 0xD0, 0x40, 0x46, 0x44, 0x47, 0x5A, 0xD2, 0x5A, 0xD0, +- 0x40, 0x48, 0x5A, 0xD0, 0x44, 0x49, 0x47, 0xF2, 0x44, 0x4A, 0x40, 0x8B, 0x60, 0x5C, 0x64, 0x47, +- 0xE0, 0x7F, 0xA0, 0x5A, 0xFF, 0xB4, 0x20, 0xBC, 0x7F, 0xB4, 0xE1, 0x7F, 0xA0, 0x5A, 0x64, 0x44, +- 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x70, 0x63, 0x0D, 0x60, 0x70, 0x65, 0xBD, 0xD2, 0x2B, 0x5C, +- 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x26, 0x44, 0x40, 0x86, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x27, 0x44, 0x40, 0x87, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x28, 0x44, 0x40, 0x88, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x29, 0x44, 0x40, 0x89, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2A, 0x44, +- 0x40, 0x8A, 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2B, 0x44, 0x40, 0x8B, +- 0xBD, 0xD2, 0x2B, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x26, 0x5C, 0x40, 0x86, 0x26, 0x44, +- 0xE4, 0x7F, 0xA0, 0x5A, 0x26, 0x47, 0xE5, 0x7F, 0xA0, 0x5A, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x84, +- 0xE8, 0x80, 0xF8, 0x84, 0x27, 0x5C, 0x40, 0x87, 0x27, 0x44, 0xE6, 0x7F, 0xA0, 0x5A, 0x27, 0x47, +- 0xE7, 0x7F, 0xA0, 0x5A, 0x27, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x28, 0x5C, 0x40, 0x88, 0x28, 0x44, +- 0xE8, 0x7F, 0xA0, 0x5A, 0x28, 0x47, 0xE9, 0x7F, 0xA0, 0x5A, 0x28, 0x44, 0xE8, 0x80, 0xF8, 0x84, +- 0x29, 0x5C, 0x40, 0x89, 0x29, 0x44, 0xEA, 0x7F, 0xA0, 0x5A, 0x29, 0x47, 0xEB, 0x7F, 0xA0, 0x5A, +- 0x29, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x2A, 0x5C, 0x40, 0x8A, 0x2A, 0x44, 0xEC, 0x7F, 0xA0, 0x5A, +- 0x2A, 0x47, 0xED, 0x7F, 0xA0, 0x5A, 0x2A, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x2B, 0x5C, 0x40, 0x8B, +- 0x2B, 0x44, 0xEE, 0x7F, 0xA0, 0x5A, 0x2B, 0x47, 0xEF, 0x7F, 0xA0, 0x5A, 0x38, 0xF0, 0x2B, 0x44, +- 0x90, 0x84, 0xE8, 0x84, 0xE3, 0x7F, 0xA0, 0x5A, 0x0D, 0x60, 0x3E, 0x62, 0xA2, 0xD7, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xE4, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, +- 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x32, 0x00, 0xDC, 0xF3, 0x31, 0x41, 0x01, 0xB1, +- 0x03, 0xA8, 0x2D, 0x03, 0x17, 0x02, 0x20, 0x40, 0x04, 0x2B, 0x0C, 0x00, 0xBB, 0xFE, 0xCA, 0xFE, +- 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x08, 0x00, 0x0F, 0x60, 0xD2, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x80, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x0C, 0x00, 0xA9, 0xFE, 0xD8, 0x05, 0xAB, 0xFE, 0x0C, 0x05, 0xA8, 0xFE, +- 0xC8, 0x05, 0xAA, 0xFE, 0xC9, 0x05, 0x78, 0x43, 0x01, 0x61, 0x24, 0x60, 0xDD, 0x78, 0xA1, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, 0x85, 0x3E, 0x24, 0x60, 0x5E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, +- 0x60, 0x46, 0x03, 0x02, 0xBF, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0x26, 0x45, 0xD4, 0x80, 0x0F, 0xF0, +- 0xF9, 0x03, 0x64, 0x44, 0x70, 0xB0, 0x70, 0x2A, 0x14, 0x00, 0x27, 0x60, 0xB2, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0xDC, 0x84, 0xFF, 0xFF, 0x08, 0x28, 0xA2, 0xDB, 0xA2, 0xFF, 0xAF, 0xF3, 0xFF, 0xFF, +- 0xCC, 0x84, 0xFE, 0xA0, 0xAF, 0xFB, 0x01, 0x07, 0xD4, 0xFE, 0xA3, 0xFF, 0xC5, 0x60, 0x5B, 0x78, +- 0xFF, 0xFF, 0x64, 0x40, 0x02, 0x26, 0x09, 0x00, 0x66, 0x45, 0x09, 0xF4, 0x0F, 0xF2, 0x02, 0x18, +- 0x65, 0x46, 0xE3, 0x1B, 0x00, 0x64, 0x40, 0x46, 0xCA, 0x01, 0xA2, 0xFF, 0xAF, 0xF3, 0x46, 0x46, +- 0xCC, 0x84, 0xFE, 0xA0, 0xAF, 0xFB, 0x01, 0x07, 0xD4, 0xFE, 0xA3, 0xFF, 0x0F, 0xF0, 0xA3, 0xFC, +- 0x64, 0x44, 0x80, 0x26, 0x22, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x92, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, +- 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, 0x07, 0x60, +- 0x01, 0x64, 0x04, 0x00, 0x02, 0x2A, 0x06, 0x00, 0x00, 0x60, 0x01, 0x64, 0x23, 0xFA, 0xC5, 0x60, +- 0x67, 0x78, 0xFF, 0xFF, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0x08, 0x26, 0x3F, 0x00, 0x2A, 0xF2, +- 0x60, 0x63, 0x60, 0x40, 0x02, 0x2B, 0x66, 0x63, 0xBE, 0xD2, 0x83, 0xF1, 0xA3, 0xD2, 0xD0, 0x80, +- 0x82, 0xF1, 0x18, 0x02, 0xBF, 0xD2, 0xD0, 0x80, 0x81, 0xF1, 0x14, 0x02, 0xD0, 0x80, 0xFF, 0xFF, +- 0x11, 0x02, 0xB8, 0xF1, 0x27, 0x60, 0x9E, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, +- 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, +- 0x00, 0x75, 0x88, 0xFF, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, 0x07, 0x60, 0x02, 0x64, 0x04, 0x00, +- 0x02, 0x2A, 0x06, 0x00, 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, 0xC5, 0x60, 0x67, 0x78, 0xFF, 0xFF, +- 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xB0, 0x3A, 0x06, 0x00, 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, +- 0xC1, 0x60, 0x11, 0x78, 0xFF, 0xFF, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0x32, 0x44, 0x01, 0x2A, +- 0x4A, 0x00, 0x28, 0x60, 0xE2, 0x63, 0xBF, 0xD3, 0x00, 0x65, 0xB4, 0x81, 0xDB, 0x83, 0x3D, 0x03, +- 0xBF, 0xD3, 0xA3, 0xD3, 0x40, 0x48, 0xBE, 0xD3, 0x40, 0x4A, 0x2E, 0xF0, 0x40, 0x4C, 0xD0, 0x80, +- 0x2D, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x2C, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, +- 0xFF, 0xFF, 0x2B, 0x03, 0x31, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x30, 0xF0, 0x08, 0x02, 0x2A, 0x44, +- 0xD0, 0x80, 0x2F, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x1E, 0x03, 0x34, 0xF0, +- 0x2C, 0x44, 0xD0, 0x80, 0x33, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x32, 0xF0, 0x04, 0x02, +- 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x11, 0x03, 0x38, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x37, 0xF0, +- 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x36, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, +- 0x04, 0x03, 0xFA, 0xA1, 0x06, 0xA3, 0xB7, 0x03, 0xC3, 0x01, 0x07, 0x60, 0x00, 0x64, 0x23, 0xFA, +- 0xC5, 0x60, 0x67, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x0F, 0xF0, 0x60, 0x45, 0xA4, 0x36, 0x08, 0x00, +- 0x0C, 0xB4, 0x04, 0x36, 0x02, 0x00, 0x0C, 0x3A, 0x06, 0x00, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, +- 0xC2, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x0F, 0xF0, 0x65, 0x40, 0x40, 0x2B, 0x22, 0x00, 0x32, 0x40, +- 0x08, 0x26, 0x1F, 0x00, 0x07, 0xF4, 0x36, 0xF2, 0xFF, 0xFF, 0x37, 0xB4, 0x26, 0x46, 0x19, 0x02, +- 0x2C, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x11, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x98, 0x64, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, +- 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xC5, 0x60, 0x5B, 0x78, +- 0xFF, 0xFF, 0x2A, 0xF2, 0x64, 0x40, 0x60, 0x26, 0x03, 0x00, 0xC2, 0x60, 0xAF, 0x78, 0xFF, 0xFF, +- 0x60, 0x41, 0xA9, 0xF3, 0x07, 0xFA, 0x61, 0x44, 0x80, 0x3A, 0x06, 0x00, 0xE5, 0x60, 0x58, 0x4F, +- 0xE7, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x10, 0x00, 0x60, 0x40, 0x40, 0x3A, 0x0D, 0x00, 0xDC, 0xF3, +- 0xFF, 0xFF, 0x07, 0xB4, 0x03, 0x3A, 0xE2, 0x01, 0xC6, 0x60, 0x58, 0x4D, 0x4F, 0x78, 0xFF, 0xFF, +- 0xDD, 0x02, 0xA9, 0xF3, 0x07, 0xFA, 0xD1, 0x00, 0x5E, 0x63, 0x60, 0x40, 0x02, 0x2B, 0x64, 0x63, +- 0x50, 0xFE, 0xBD, 0xD2, 0x81, 0xF1, 0xBD, 0xD2, 0xD0, 0x80, 0x82, 0xF1, 0xBD, 0xD2, 0xD0, 0x80, +- 0x83, 0xF1, 0x2A, 0xF2, 0xD0, 0x80, 0x60, 0x40, 0x08, 0x3A, 0x07, 0x00, 0x01, 0x0C, 0xC6, 0x01, +- 0xDE, 0x60, 0x58, 0x4F, 0xFE, 0x78, 0xFF, 0xFF, 0xB8, 0x00, 0x26, 0x0C, 0xC6, 0x60, 0x58, 0x4D, +- 0x4F, 0x78, 0xFF, 0xFF, 0xBB, 0x02, 0x1F, 0x60, 0x52, 0x61, 0x02, 0x64, 0xA1, 0xDB, 0x1F, 0x60, +- 0x5A, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x22, 0x60, 0x58, 0x4E, 0x3E, 0x78, 0xFF, 0xFF, 0x1F, 0x60, +- 0x04, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x27, 0x08, 0x00, 0x0F, 0x60, 0xEA, 0x62, +- 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x1F, 0x60, 0x52, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x9B, 0x01, 0x91, 0x00, 0xC6, 0x60, 0x58, 0x4D, 0x4F, 0x78, 0xFF, 0xFF, +- 0xFA, 0x02, 0x0F, 0x60, 0xCE, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x36, 0x07, 0x00, +- 0x01, 0x64, 0xA1, 0xDB, 0x01, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x31, 0xF2, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, +- 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, +- 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, +- 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0xA9, 0xF1, 0x43, 0x43, +- 0xD3, 0x80, 0xFF, 0xFF, 0x04, 0x02, 0xC5, 0x60, 0x58, 0x4F, 0xA5, 0x78, 0xFF, 0xFF, 0x32, 0x40, +- 0x08, 0x2A, 0x05, 0x00, 0x63, 0x46, 0x80, 0x60, 0x02, 0x64, 0x06, 0xFA, 0x26, 0x46, 0xD8, 0xF3, +- 0x63, 0x45, 0x66, 0x41, 0x65, 0x46, 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, 0x06, 0x00, 0x02, 0x36, +- 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, 0x01, 0x00, 0x01, 0x64, +- 0x6F, 0xFA, 0x79, 0xF3, 0x7A, 0xF1, 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, 0x02, 0x02, 0x79, 0xF3, +- 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, 0xAE, 0x65, 0xD8, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, 0x44, 0xD3, +- 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, +- 0xA4, 0x84, 0x7B, 0xFB, 0x6F, 0xF0, 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, 0x60, 0x47, 0x60, 0x45, +- 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x70, 0xF0, 0x70, 0xFA, +- 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, 0xE1, 0x81, 0x0F, 0x60, +- 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x66, 0x43, 0x0C, 0xF4, 0xB8, 0xF1, 0x27, 0x60, 0x8C, 0x64, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, +- 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x27, 0xF2, 0xFF, 0xFF, +- 0x60, 0x40, 0x01, 0x3B, 0x12, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x9A, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, +- 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x13, 0x00, 0x02, 0x3B, 0x11, 0x00, 0xB8, 0xF1, +- 0x27, 0x60, 0x9C, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, +- 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, +- 0x1B, 0xF2, 0xFF, 0xFF, 0xE4, 0xA4, 0x3E, 0xFA, 0x2A, 0xF2, 0x28, 0x41, 0x40, 0xA8, 0x01, 0xB1, +- 0x02, 0x02, 0x62, 0x02, 0x92, 0x00, 0x60, 0x40, 0x08, 0x2A, 0x2B, 0x00, 0xB8, 0xF1, 0x27, 0x60, +- 0x8A, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, +- 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x1B, 0xF2, +- 0xFF, 0xFF, 0x60, 0x45, 0xB8, 0xF1, 0x27, 0x60, 0x90, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, +- 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, +- 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, +- 0x88, 0xFF, 0x0F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x26, 0x28, 0x00, 0x32, 0x44, 0x02, 0x26, +- 0x25, 0x00, 0x10, 0x2B, 0x29, 0x00, 0x28, 0x60, 0xE2, 0x63, 0xBF, 0xD3, 0x2C, 0xF0, 0x00, 0xA8, +- 0x60, 0x41, 0x0D, 0x03, 0x50, 0xFE, 0xBD, 0xD3, 0x2D, 0xF0, 0xD0, 0x80, 0xBD, 0xD3, 0x2E, 0xF0, +- 0xD0, 0x80, 0xBD, 0xD3, 0x2C, 0xF0, 0xD0, 0x80, 0xFA, 0xA1, 0x10, 0x0C, 0xF3, 0x02, 0x50, 0xFE, +- 0x60, 0x60, 0x01, 0x64, 0xD0, 0x80, 0x2D, 0xF0, 0x1D, 0x64, 0xD0, 0x80, 0x2E, 0xF0, 0x01, 0x64, +- 0xD0, 0x80, 0xFF, 0xFF, 0x03, 0x0C, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x40, 0x2A, +- 0x03, 0x00, 0x19, 0x60, 0x22, 0x78, 0xFF, 0xFF, 0xC5, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x32, 0x40, +- 0x40, 0x26, 0xF7, 0x01, 0x2A, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x08, 0x2A, 0x2A, 0x00, 0xDC, 0xF3, +- 0xFF, 0xFF, 0x07, 0xB4, 0x03, 0xA8, 0xFF, 0xFF, 0x03, 0x03, 0x32, 0x40, 0x02, 0x2A, 0x1D, 0x00, +- 0x03, 0x67, 0xA0, 0x84, 0x00, 0x37, 0x64, 0x63, 0x60, 0x40, 0x02, 0x37, 0x5E, 0x63, 0x60, 0x40, +- 0x01, 0x37, 0x58, 0x63, 0x60, 0x40, 0x03, 0x37, 0x0D, 0x00, 0xBD, 0xD2, 0x81, 0xF1, 0xBD, 0xD2, +- 0xD0, 0x80, 0x82, 0xF1, 0x07, 0x02, 0xD0, 0x80, 0xBD, 0xD2, 0x83, 0xF1, 0x03, 0x02, 0xD0, 0x80, +- 0xFF, 0xFF, 0x03, 0x03, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0xDE, 0x60, 0x58, 0x4F, 0xFE, 0x78, +- 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x26, 0x06, 0x00, 0x20, 0x40, 0x10, 0x2B, +- 0x03, 0x00, 0xC5, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x87, 0xF4, 0xA9, 0xF1, 0x27, 0x1B, 0x31, 0xF2, +- 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, +- 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, +- 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, +- 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, +- 0xE8, 0x1B, 0xA9, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x03, 0x00, 0xD3, 0x80, 0xFF, 0xFF, +- 0xD6, 0x03, 0x43, 0x43, 0xDC, 0xF3, 0x32, 0x40, 0x02, 0x26, 0x04, 0x00, 0x07, 0xB4, 0x03, 0xA8, +- 0x2A, 0xF2, 0x5F, 0x02, 0xA9, 0xF1, 0x23, 0x43, 0xD3, 0x80, 0xFF, 0xFF, 0x5A, 0x02, 0xC5, 0x60, +- 0x58, 0x4F, 0xA5, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x02, 0x2A, 0x05, 0x00, 0x63, 0x46, 0x02, 0x64, +- 0x06, 0xFA, 0x26, 0x46, 0x4E, 0x00, 0x32, 0x40, 0x08, 0x2A, 0x05, 0x00, 0x63, 0x46, 0x80, 0x60, +- 0x02, 0x64, 0x06, 0xFA, 0x26, 0x46, 0xD8, 0xF3, 0x63, 0x45, 0x66, 0x41, 0x65, 0x46, 0x8C, 0xFA, +- 0x60, 0x40, 0x01, 0x36, 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, 0x05, 0x3A, +- 0x02, 0x00, 0x00, 0x64, 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x79, 0xF3, 0x7A, 0xF1, 0xFF, 0xFF, +- 0xA0, 0x84, 0x65, 0x43, 0x02, 0x02, 0x79, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, 0xAE, 0x65, +- 0xD8, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x04, 0x02, +- 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x7B, 0xFB, 0x6F, 0xF0, 0x60, 0x47, +- 0x90, 0x84, 0x6F, 0xFA, 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, +- 0xFC, 0x03, 0xA4, 0x84, 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x05, +- 0xDD, 0x81, 0xFB, 0x01, 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x66, 0x43, +- 0x0C, 0xF4, 0x07, 0xFC, 0x43, 0x43, 0x02, 0xFE, 0x1D, 0xF0, 0x1C, 0x60, 0x9A, 0x62, 0xC0, 0x64, +- 0xC0, 0x84, 0xA2, 0xD1, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xC0, 0x84, +- 0xA2, 0xDB, 0x2A, 0xF2, 0x63, 0x45, 0x0C, 0xB4, 0x08, 0x3A, 0x0A, 0x00, 0xDC, 0xF3, 0x23, 0x46, +- 0x07, 0xB4, 0xFD, 0xA0, 0x06, 0xF2, 0x26, 0x46, 0x03, 0x03, 0x60, 0x40, 0x02, 0x2A, 0x0D, 0x00, +- 0x2A, 0xF2, 0x35, 0xF0, 0x60, 0x40, 0xA4, 0x36, 0x0B, 0x00, 0x08, 0x2B, 0x0C, 0x00, 0x23, 0x46, +- 0x22, 0xF2, 0x26, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x06, 0x02, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, +- 0xC5, 0x60, 0x55, 0x78, 0xFF, 0xFF, 0x23, 0x46, 0x1E, 0xF2, 0x26, 0x46, 0x44, 0x4C, 0x0F, 0x26, +- 0x1D, 0x00, 0x00, 0xBC, 0x40, 0x45, 0x0B, 0x03, 0x00, 0x64, 0x23, 0x46, 0x1E, 0xFA, 0x26, 0x46, +- 0xA2, 0xFF, 0xAF, 0x60, 0x58, 0x4E, 0x95, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, 0x2A, 0xF0, +- 0x2C, 0x44, 0x64, 0x40, 0x04, 0x27, 0x0A, 0x00, 0x23, 0x46, 0x22, 0xFA, 0x26, 0x46, 0x1B, 0xF2, +- 0xFF, 0xFF, 0xE4, 0xA4, 0x3E, 0xFA, 0xC4, 0x60, 0xAD, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x02, 0xFA, +- 0xA2, 0xFF, 0x16, 0xF0, 0xFF, 0xFF, 0x64, 0x44, 0x01, 0x26, 0xDC, 0x9C, 0xB3, 0xF3, 0x2A, 0xF2, +- 0xDC, 0x83, 0xB3, 0xFD, 0x06, 0xF4, 0x01, 0xF8, 0x26, 0x46, 0x60, 0x40, 0x40, 0x2B, 0x18, 0x00, +- 0x64, 0x44, 0x00, 0x65, 0xFF, 0xB4, 0xFC, 0xA4, 0x06, 0xF0, 0x03, 0x03, 0x64, 0x46, 0x0C, 0x0D, +- 0x02, 0x65, 0x26, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x60, 0x46, +- 0xF9, 0x01, 0x01, 0xF2, 0xFF, 0xFF, 0xD4, 0x84, 0x01, 0xFA, 0x66, 0x44, 0x26, 0x46, 0x06, 0xFA, +- 0x06, 0xF4, 0x00, 0xF2, 0x80, 0xFC, 0x40, 0x45, 0xAF, 0x60, 0x58, 0x4E, 0x95, 0x78, 0xFF, 0xFF, +- 0xA3, 0xFF, 0x26, 0x46, 0x2C, 0x44, 0x0F, 0x26, 0x14, 0x00, 0x23, 0x46, 0x22, 0xFA, 0x26, 0x44, +- 0x1E, 0xFA, 0x26, 0x46, 0x1B, 0xF2, 0xFF, 0xFF, 0xE4, 0xA4, 0x3E, 0xFA, 0x24, 0x60, 0x74, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0x6F, 0x00, 0xA3, 0x46, 0x22, 0xF2, 0x60, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x22, 0xFA, 0xA3, 0x46, +- 0x6C, 0x02, 0x2A, 0xF0, 0xA3, 0x46, 0x1E, 0xF2, 0xA3, 0x46, 0x00, 0xBC, 0x00, 0xF2, 0x01, 0x02, +- 0x64, 0x00, 0x44, 0x4C, 0x3F, 0xF0, 0x60, 0x43, 0x23, 0x46, 0x1E, 0xF4, 0x09, 0x60, 0x00, 0x65, +- 0x3F, 0xF2, 0x26, 0x46, 0xC0, 0x84, 0xD4, 0x80, 0x60, 0x45, 0x57, 0x07, 0x80, 0xFC, 0x1B, 0xF2, +- 0x06, 0xF2, 0x60, 0x41, 0x23, 0x46, 0x1E, 0xF4, 0x1B, 0xF0, 0x06, 0xF0, 0xC1, 0x81, 0x06, 0xFA, +- 0x05, 0xFA, 0x9B, 0xFA, 0x65, 0x44, 0x3F, 0xFA, 0x64, 0x46, 0x00, 0xFC, 0x63, 0x46, 0x01, 0xF2, +- 0x10, 0x61, 0xF2, 0xA4, 0x01, 0xFA, 0xC8, 0x83, 0x02, 0x64, 0x59, 0xD0, 0x58, 0xD8, 0xFD, 0x1F, +- 0x06, 0x45, 0x24, 0x60, 0x74, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, 0x70, 0x67, +- 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, 0x80, 0xFC, +- 0x05, 0xFA, 0xAF, 0x60, 0x58, 0x4E, 0x95, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, 0x2C, 0x44, +- 0x04, 0x27, 0x16, 0x00, 0x23, 0x46, 0x1E, 0xF2, 0x9E, 0xFC, 0x60, 0x46, 0x46, 0x46, 0x3F, 0xF2, +- 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, 0x26, 0x46, 0x2C, 0x43, 0x2A, 0xFC, 0x06, 0xF4, 0x00, 0x64, +- 0x00, 0xFA, 0x01, 0xF0, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0x01, 0xFA, 0x26, 0x46, 0x1D, 0x00, +- 0x00, 0x66, 0x46, 0x46, 0xBF, 0x60, 0xEB, 0x78, 0xFF, 0xFF, 0xA3, 0x46, 0x1E, 0xF0, 0x9E, 0xFC, +- 0x00, 0x63, 0x33, 0x85, 0xA3, 0x46, 0x0D, 0x03, 0xA3, 0x46, 0x22, 0xF2, 0x0F, 0x65, 0xA4, 0x85, +- 0xD4, 0x84, 0x22, 0xFA, 0xA3, 0x46, 0xA2, 0xFF, 0xAF, 0x60, 0x58, 0x4E, 0x95, 0x78, 0xFF, 0xFF, +- 0xA3, 0xFF, 0x26, 0x46, 0xC5, 0x60, 0x5B, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x32, 0xF0, 0x60, 0x40, +- 0x08, 0x2A, 0x5C, 0x00, 0x01, 0x2B, 0x2F, 0x00, 0x64, 0x40, 0x01, 0x2A, 0x2C, 0x00, 0xB8, 0xF1, +- 0x27, 0x60, 0x8A, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, +- 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, +- 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0xB8, 0xF1, 0x27, 0x60, 0x90, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, +- 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, +- 0x00, 0x75, 0x88, 0xFF, 0x2B, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x88, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, +- 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, +- 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0xB8, 0xF1, +- 0x27, 0x60, 0x8E, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, +- 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, +- 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x07, 0xF4, 0xFF, 0xFF, +- 0x22, 0xF2, 0x26, 0x46, 0x0F, 0xB4, 0xDC, 0x85, 0xB8, 0xF1, 0x27, 0x60, 0x8C, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0B, 0x03, 0x07, 0x05, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, +- 0xA2, 0xDB, 0x09, 0x04, 0xC6, 0xFE, 0x07, 0x00, 0x00, 0x64, 0xB8, 0x84, 0xA2, 0xDB, 0x8A, 0xFF, +- 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3B, 0x12, 0x00, +- 0xB8, 0xF1, 0x27, 0x60, 0x9A, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, +- 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, +- 0x88, 0xFF, 0x13, 0x00, 0x02, 0x3B, 0x11, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0x9C, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, +- 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xC6, 0x60, 0x85, 0x78, 0xFF, 0xFF, +- 0xBF, 0x60, 0xEB, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, +- 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xBF, 0x60, 0xEB, 0x78, 0xFF, 0xFF, 0x24, 0x60, +- 0x74, 0x62, 0x24, 0x60, 0x58, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0x00, 0x66, 0x46, 0x46, 0xBF, 0x60, 0xEB, 0x78, 0xFF, 0xFF, +- 0x2A, 0xF2, 0x58, 0x63, 0x60, 0x47, 0x01, 0x27, 0x64, 0x63, 0x31, 0x60, 0x28, 0x62, 0x61, 0x5C, +- 0xA2, 0xD9, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, 0xBD, 0xD0, 0x00, 0xF4, 0x04, 0xF8, +- 0x83, 0xFA, 0x82, 0xF8, 0xA6, 0x46, 0x02, 0xB0, 0x5E, 0x63, 0x04, 0x03, 0x64, 0x63, 0x03, 0xB0, +- 0x02, 0x3A, 0x6C, 0x63, 0x3F, 0xF2, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, 0xBD, 0xD0, +- 0xA6, 0x46, 0x07, 0xF8, 0x86, 0xFA, 0x85, 0xF8, 0x60, 0x47, 0x08, 0xFA, 0x31, 0x60, 0x28, 0x62, +- 0xA2, 0xD1, 0x26, 0x46, 0x64, 0x41, 0x2F, 0x58, 0xFF, 0xFF, 0xA9, 0xF5, 0x00, 0xF2, 0x26, 0x46, +- 0x31, 0xF0, 0x39, 0x18, 0x66, 0x41, 0x1C, 0x60, 0xBA, 0x65, 0x64, 0x47, 0x00, 0x7F, 0xA9, 0xF1, +- 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, +- 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, +- 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, +- 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, +- 0x61, 0x46, 0x1E, 0x60, 0xBC, 0x61, 0xA1, 0xD3, 0x1E, 0x60, 0xFE, 0x7C, 0xD0, 0x80, 0xFF, 0xFF, +- 0x07, 0x03, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0x49, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xA1, 0xDB, +- 0xC6, 0x60, 0x40, 0x78, 0xFF, 0xFF, 0x20, 0x7C, 0x72, 0x44, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, +- 0x02, 0x04, 0xD0, 0x84, 0xFB, 0x01, 0xE0, 0x83, 0xA9, 0xF3, 0x02, 0xA3, 0x43, 0x93, 0xA9, 0xF3, +- 0xFF, 0xFF, 0x02, 0xA5, 0xD7, 0x80, 0x04, 0xA5, 0x08, 0x24, 0x65, 0x43, 0x66, 0x41, 0x63, 0x46, +- 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x1C, 0x60, +- 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, +- 0xA9, 0xF3, 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, +- 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, +- 0x31, 0xF0, 0x66, 0x41, 0x1C, 0x60, 0xBA, 0x65, 0x64, 0x47, 0x00, 0x7F, 0xA9, 0xF1, 0xE0, 0x84, +- 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, +- 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, +- 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, +- 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, +- 0x2F, 0xF2, 0x30, 0xF0, 0x31, 0xF0, 0x64, 0x45, 0x46, 0x43, 0x63, 0x46, 0x03, 0xFA, 0x06, 0xF2, +- 0x84, 0xF8, 0x00, 0x7E, 0x06, 0xFA, 0x05, 0xF8, 0xA3, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0xDC, 0xF3, +- 0x2A, 0xF2, 0x07, 0xB0, 0x03, 0x3A, 0x2A, 0x00, 0x00, 0xF4, 0x09, 0xF2, 0x60, 0x45, 0x80, 0x3A, +- 0x05, 0x00, 0x0E, 0xF2, 0xFF, 0xFF, 0x02, 0xB0, 0x0F, 0xF2, 0x20, 0x03, 0x60, 0x47, 0x00, 0x3A, +- 0x1D, 0x00, 0x60, 0x41, 0x00, 0x36, 0x13, 0x00, 0xDA, 0x85, 0x2D, 0x60, 0x7A, 0x63, 0xBD, 0xD1, +- 0xFF, 0xFF, 0xD1, 0x80, 0xFF, 0xFF, 0x12, 0x02, 0x60, 0xFE, 0xBD, 0xD3, 0xA5, 0xD0, 0xDE, 0x85, +- 0xD0, 0x80, 0xCD, 0x81, 0x0B, 0x02, 0xF9, 0x02, 0x20, 0xFE, 0x00, 0x64, 0x0A, 0x00, 0x26, 0x46, +- 0x48, 0xFE, 0x65, 0x40, 0x40, 0x3A, 0x02, 0x00, 0x01, 0x64, 0x03, 0x00, 0x08, 0xFE, 0x20, 0xFE, +- 0x00, 0x64, 0x40, 0x48, 0x26, 0x46, 0x2D, 0x58, 0xFF, 0xFF, 0x2D, 0x60, 0x52, 0x62, 0xA2, 0xD3, +- 0x18, 0xF2, 0x60, 0x40, 0x01, 0x26, 0x2A, 0xFA, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x26, +- 0x03, 0x00, 0xC7, 0x60, 0x6D, 0x78, 0xFF, 0xFF, 0x3F, 0xF0, 0x32, 0x40, 0x10, 0x2A, 0x20, 0x00, +- 0x2C, 0xF0, 0x64, 0x41, 0x60, 0x40, 0x40, 0x27, 0x1B, 0x00, 0xCD, 0x81, 0xDD, 0x81, 0x18, 0x03, +- 0x17, 0x03, 0x64, 0x40, 0x01, 0x26, 0x14, 0x00, 0x01, 0x61, 0x13, 0x00, 0xB8, 0xF1, 0x27, 0x60, +- 0xA0, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, +- 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x23, 0x00, +- 0x00, 0x61, 0x60, 0x40, 0x18, 0x36, 0x1F, 0x00, 0xC5, 0x60, 0x58, 0x4F, 0x78, 0x78, 0xFF, 0xFF, +- 0x0F, 0xF0, 0xEB, 0xF1, 0x64, 0x44, 0x60, 0x22, 0x19, 0x00, 0xDC, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, +- 0xFD, 0xA0, 0x2A, 0xF2, 0x03, 0x02, 0x08, 0xB0, 0xFF, 0xFF, 0x10, 0x02, 0x32, 0xF2, 0x33, 0xF2, +- 0xD0, 0x80, 0xEC, 0xF1, 0x0B, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x08, 0x02, 0xED, 0xF1, 0xFF, 0xFF, +- 0xD0, 0x80, 0x0F, 0xF0, 0x03, 0x02, 0xC7, 0x60, 0xB9, 0x78, 0xFF, 0xFF, 0x00, 0xF4, 0xAA, 0x60, +- 0xAA, 0x65, 0x09, 0xF2, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, 0x4F, 0x02, 0xD0, 0x80, 0x00, 0x64, +- 0x5A, 0xD0, 0x4B, 0x02, 0x64, 0x45, 0xD4, 0x80, 0xF8, 0x7F, 0x08, 0x02, 0x5A, 0xD0, 0x26, 0x46, +- 0x64, 0x45, 0x23, 0xF0, 0x20, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x0B, 0x00, 0xD4, 0x80, 0x1D, 0x60, +- 0x60, 0x64, 0x16, 0x02, 0x5A, 0xD0, 0x26, 0x46, 0x64, 0x45, 0x23, 0xF0, 0x40, 0x67, 0xB0, 0x84, +- 0xA2, 0xDA, 0x65, 0x44, 0x88, 0x3A, 0x07, 0x00, 0x77, 0x37, 0x08, 0x00, 0x78, 0x37, 0x06, 0x00, +- 0x8E, 0x37, 0x04, 0x00, 0x2A, 0x00, 0x81, 0x3A, 0x28, 0x00, 0x80, 0x37, 0x00, 0x61, 0x25, 0x00, +- 0xD4, 0x80, 0x01, 0x60, 0x00, 0x64, 0x5A, 0xD0, 0x20, 0x02, 0xD0, 0x80, 0x5A, 0xD0, 0x1D, 0x02, +- 0x26, 0x46, 0x64, 0x47, 0x7F, 0xB4, 0xFD, 0xA0, 0x09, 0x03, 0x17, 0x07, 0x32, 0x40, 0x02, 0x26, +- 0x47, 0x00, 0x23, 0xF0, 0x60, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x42, 0x00, 0x0F, 0xF2, 0x32, 0x40, +- 0x02, 0x26, 0x3E, 0x00, 0xF2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xF2, 0xFB, 0xEB, 0x60, 0x58, 0x4F, +- 0xA5, 0x78, 0xFF, 0xFF, 0xC7, 0x60, 0xC3, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x61, 0x40, 0x01, 0x2A, +- 0x12, 0x00, 0xB8, 0xF1, 0x27, 0x60, 0xA0, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, +- 0xD0, 0x80, 0x04, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0x04, 0x00, 0x8A, 0xFF, 0x20, 0x60, +- 0x00, 0x75, 0x88, 0xFF, 0x6E, 0x00, 0x0F, 0xF2, 0x81, 0xF1, 0x2A, 0xF2, 0x60, 0x40, 0x20, 0x2A, +- 0x12, 0x00, 0x5E, 0x63, 0x60, 0x40, 0x02, 0x2B, 0x64, 0x63, 0xBD, 0xD2, 0xBD, 0xD2, 0xD0, 0x80, +- 0x82, 0xF1, 0x08, 0x02, 0xD0, 0x80, 0xA3, 0xD2, 0x83, 0xF1, 0x04, 0x02, 0xD0, 0x80, 0xFF, 0xFF, +- 0x01, 0x02, 0x06, 0x00, 0x56, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0x36, 0x51, 0x00, +- 0xF2, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xF2, 0xFB, 0x59, 0x00, 0x26, 0x46, 0x2A, 0xF2, 0xFF, 0xFF, +- 0xFF, 0xFF, 0x0C, 0x26, 0x46, 0x00, 0xB0, 0x36, 0x15, 0x00, 0x10, 0x36, 0x13, 0x00, 0x30, 0x36, +- 0x11, 0x00, 0xC0, 0x36, 0x02, 0x00, 0xA0, 0x3A, 0x12, 0x00, 0x81, 0xF1, 0x32, 0xF2, 0x33, 0xF2, +- 0xD0, 0x80, 0x82, 0xF1, 0x36, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x83, 0xF1, 0x32, 0x02, 0xD0, 0x80, +- 0xFF, 0xFF, 0x2F, 0x02, 0xDB, 0x60, 0x58, 0x4F, 0xD2, 0x78, 0xFF, 0xFF, 0x26, 0x00, 0x50, 0x3A, +- 0x05, 0x00, 0xEF, 0x60, 0x58, 0x4F, 0xE3, 0x78, 0xFF, 0xFF, 0x1F, 0x00, 0x40, 0x3A, 0x05, 0x00, +- 0xE8, 0x60, 0x58, 0x4F, 0x60, 0x78, 0xFF, 0xFF, 0x18, 0x00, 0x80, 0x3A, 0x15, 0x00, 0x81, 0xF1, +- 0x32, 0xF2, 0x33, 0xF2, 0xD0, 0x80, 0x82, 0xF1, 0x14, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x83, 0xF1, +- 0x10, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x0D, 0x02, 0xDF, 0x60, 0x58, 0x4F, 0x28, 0x78, 0xFF, 0xFF, +- 0x20, 0x60, 0x58, 0x4F, 0xBF, 0x78, 0xFF, 0xFF, 0x04, 0x00, 0x66, 0x44, 0x00, 0xA8, 0xFF, 0xFF, +- 0x0A, 0x03, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, +- 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xC5, 0x60, 0x58, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x3B, 0xF0, +- 0x60, 0x40, 0x40, 0x2B, 0x1E, 0x00, 0xC0, 0x60, 0x00, 0x64, 0x64, 0x40, 0x20, 0x2B, 0x19, 0x00, +- 0x22, 0xF2, 0xFF, 0xFF, 0x04, 0xB4, 0xFF, 0xFF, 0x14, 0x03, 0xC0, 0x60, 0x00, 0x64, 0x26, 0x46, +- 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x23, 0xF2, 0x10, 0xBD, 0xB4, 0x9C, 0x3F, 0xF2, +- 0x23, 0xF8, 0x3F, 0xF2, 0xFF, 0xFF, 0xF8, 0xA4, 0x3F, 0xFA, 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, +- 0x26, 0x46, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x58, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0xCB, 0x01, 0x00, 0x60, 0x30, 0x61, +- 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x60, 0xFB, 0x00, 0x60, 0x30, 0x61, +- 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x5F, 0xFB, 0x00, 0x60, 0x02, 0x61, +- 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x66, 0xFB, 0x10, 0x60, 0x26, 0x62, +- 0xC9, 0x60, 0xC7, 0x64, 0xA2, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x01, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0x0F, 0x60, 0xF0, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x14, 0x63, 0x01, 0x60, 0xC4, 0x61, 0x28, 0x60, 0x3E, 0x64, +- 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x00, 0x60, 0x88, 0x63, 0x27, 0x60, 0xB4, 0x61, 0x28, 0x60, +- 0x54, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, +- 0x64, 0x45, 0xA9, 0xF1, 0x66, 0x41, 0x64, 0x46, 0x36, 0xF2, 0xFF, 0xFF, 0x65, 0x40, 0x01, 0x36, +- 0x22, 0x64, 0x36, 0xFA, 0x61, 0x46, 0x32, 0x45, 0x28, 0x60, 0x3C, 0x62, 0xA2, 0xD1, 0x10, 0x67, +- 0xB4, 0x85, 0x64, 0x40, 0x01, 0x2A, 0x94, 0x85, 0x45, 0x52, 0xFF, 0x60, 0xE7, 0x65, 0x32, 0x41, +- 0xA5, 0x81, 0x2D, 0x60, 0x1A, 0x62, 0xA2, 0xD1, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0x64, 0x40, +- 0x01, 0x2A, 0x0D, 0x00, 0x08, 0x65, 0xFF, 0xA0, 0xFF, 0xFF, 0x01, 0x03, 0x08, 0x00, 0x28, 0x60, +- 0x30, 0x62, 0xA2, 0xD3, 0xB5, 0x81, 0x10, 0x65, 0x60, 0x40, 0x01, 0x26, 0xB5, 0x81, 0x41, 0x52, +- 0x2D, 0x60, 0x1A, 0x62, 0xA2, 0xD3, 0x31, 0x60, 0x18, 0x63, 0xF0, 0x84, 0xF0, 0x84, 0xF0, 0x84, +- 0x01, 0xB5, 0xF0, 0x84, 0xF0, 0x84, 0x03, 0xB4, 0x65, 0x5C, 0xA3, 0xD9, 0x31, 0x60, 0x1A, 0x63, +- 0x02, 0xA8, 0xA3, 0xDB, 0x1B, 0x02, 0x07, 0x60, 0xD0, 0x64, 0x31, 0x60, 0x1C, 0x63, 0xA3, 0xDB, +- 0x31, 0x60, 0x24, 0x63, 0xA3, 0xDB, 0x00, 0x60, 0xC8, 0x64, 0x31, 0x60, 0x1E, 0x63, 0xA3, 0xDB, +- 0x31, 0x60, 0x26, 0x63, 0xA3, 0xDB, 0x00, 0x60, 0x64, 0x64, 0x31, 0x60, 0x20, 0x63, 0xA3, 0xDB, +- 0x01, 0x60, 0x90, 0x64, 0x31, 0x60, 0x22, 0x63, 0xA3, 0xDB, 0x08, 0x00, 0x0A, 0x64, 0x31, 0x60, +- 0x20, 0x63, 0xA3, 0xDB, 0x01, 0x64, 0x31, 0x60, 0x22, 0x63, 0xA3, 0xDB, 0x2D, 0x60, 0x1A, 0x62, +- 0xA2, 0xD1, 0x01, 0x64, 0x64, 0x40, 0x40, 0x2A, 0x03, 0x00, 0x31, 0x60, 0x0E, 0x7C, 0xA4, 0xDB, +- 0x12, 0x60, 0x28, 0x63, 0xBA, 0xF3, 0x0E, 0x61, 0x60, 0x45, 0x65, 0x44, 0xE8, 0x85, 0x05, 0x64, +- 0xCD, 0x81, 0x02, 0x28, 0x00, 0x64, 0xBD, 0xDB, 0xF8, 0x02, 0x2D, 0x60, 0x78, 0x61, 0x27, 0x60, +- 0xB6, 0x64, 0x20, 0x63, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0xBD, 0xF1, 0x80, 0xF9, 0x1A, 0x63, +- 0x01, 0x60, 0x00, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, 0x40, 0x40, 0x01, 0x64, 0x87, 0xFB, +- 0x28, 0x60, 0xCC, 0x61, 0xA1, 0xD3, 0x2E, 0x60, 0x96, 0x61, 0xFE, 0xA4, 0xE0, 0x84, 0x04, 0x24, +- 0x0F, 0x00, 0xE0, 0x84, 0x41, 0x91, 0x2D, 0x60, 0xCC, 0x62, 0xA2, 0xD3, 0xA1, 0xD1, 0x2D, 0x60, +- 0xC4, 0x62, 0xA0, 0x83, 0xA2, 0xDD, 0x59, 0xD1, 0x2D, 0x60, 0xC2, 0x62, 0xA0, 0x83, 0xA2, 0xDD, +- 0xE5, 0xF3, 0x7F, 0xFB, 0x1B, 0x60, 0xC6, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x00, 0xB8, 0x10, 0x60, +- 0x5C, 0x65, 0x0D, 0x03, 0x1B, 0x60, 0xCE, 0x63, 0xE5, 0xF3, 0xA3, 0xD1, 0xE0, 0x84, 0xC4, 0x84, +- 0xA0, 0xD3, 0xFF, 0xFF, 0x01, 0xB0, 0xFF, 0xFF, 0x02, 0x02, 0xE5, 0xF9, 0x7F, 0xF9, 0xE5, 0xF3, +- 0x01, 0x61, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0xE1, 0x81, 0xFB, 0x01, 0xBA, 0xF3, 0x61, 0x45, +- 0xA4, 0x80, 0xFF, 0xFF, 0x0B, 0x02, 0x00, 0xB8, 0x01, 0x63, 0x08, 0x03, 0xE8, 0x84, 0xFF, 0xFF, +- 0x02, 0x24, 0x02, 0x00, 0xDF, 0x83, 0xFA, 0x01, 0xE5, 0xFD, 0x7F, 0xFD, 0x0F, 0x60, 0xF0, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xF2, 0x62, 0x40, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0xC8, 0x60, 0xF7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7F, 0xF1, +- 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x0C, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x07, 0x64, +- 0xD0, 0xFB, 0x0F, 0x60, 0xF2, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xC9, 0x60, 0x34, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xF0, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x01, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xE3, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x05, 0x3A, +- 0x03, 0x00, 0x68, 0x60, 0xBA, 0x61, 0x11, 0x00, 0x04, 0x3A, 0x03, 0x00, 0x68, 0x60, 0xAE, 0x61, +- 0x0C, 0x00, 0x03, 0x3A, 0x03, 0x00, 0x68, 0x60, 0xA2, 0x61, 0x07, 0x00, 0x02, 0x3A, 0x03, 0x00, +- 0x68, 0x60, 0x96, 0x61, 0x02, 0x00, 0x68, 0x60, 0x8A, 0x61, 0x3C, 0x60, 0x00, 0x66, 0x01, 0x60, +- 0xB8, 0x64, 0x0A, 0x63, 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, 0x01, 0x60, 0xBE, 0x61, 0xE4, 0xF3, +- 0x00, 0x66, 0x00, 0xA8, 0x04, 0x65, 0x01, 0x03, 0xA1, 0xDB, 0x1F, 0x60, 0x08, 0x63, 0x55, 0xD3, +- 0xFF, 0xFF, 0x20, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, 0x21, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, +- 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, 0xF0, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, +- 0x0B, 0x04, 0x0F, 0x60, 0xF2, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xC9, 0x60, 0x7B, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x9A, 0x62, 0x1F, 0x60, 0x06, 0x64, +- 0xA2, 0xDB, 0x20, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xF2, 0x62, 0x20, 0x60, +- 0x00, 0x64, 0xA2, 0xDB, 0xC9, 0x60, 0xA0, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0xC5, 0xFE, 0x20, 0x40, 0x20, 0x2A, 0x08, 0x00, 0x10, 0x60, 0x02, 0x62, 0xA2, 0xD1, +- 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, +- 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xF0, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x5A, 0xDB, 0x0E, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xF0, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x8B, 0xFB, +- 0xFF, 0xFF, 0xC1, 0xFE, 0x10, 0x60, 0x1A, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0xDF, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x24, 0x60, 0xA8, 0x63, 0x01, 0x64, 0xBD, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x0F, 0x60, 0xF0, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x0F, 0x60, 0xF2, 0x62, 0x00, 0x60, 0x08, 0x64, 0xA2, 0xDB, 0xC9, 0x60, 0xF3, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xF0, 0x62, +- 0xA2, 0xD1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x8B, 0xF3, 0x00, 0x65, 0xD4, 0x80, +- 0xFF, 0xFF, 0x0B, 0x03, 0x0F, 0x60, 0xF2, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xC9, 0x60, +- 0xF3, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xDE, 0xFE, 0x0E, 0x04, 0x09, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xF2, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCA, 0x60, +- 0x1D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0A, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x24, 0x60, 0x9A, 0x62, 0x06, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xF0, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0xBE, 0xFE, 0xDA, 0xFE, 0x24, 0x60, 0x34, 0x61, 0xCA, 0x60, +- 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x22, 0x61, 0xCA, 0x60, 0x58, 0x4E, 0x57, 0x78, +- 0xFF, 0xFF, 0x24, 0x60, 0x28, 0x61, 0xCA, 0x60, 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x24, 0x60, +- 0x46, 0x61, 0xCA, 0x60, 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x4C, 0x61, 0xCA, 0x60, +- 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x58, 0x61, 0xCA, 0x60, 0x58, 0x4E, 0x57, 0x78, +- 0xFF, 0xFF, 0xC5, 0xFE, 0x0E, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0xA1, 0xD3, +- 0x0E, 0x57, 0x24, 0x00, 0x0E, 0xF2, 0x44, 0x4C, 0x80, 0xB0, 0x10, 0xB0, 0x0B, 0x03, 0x24, 0x60, +- 0x74, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x13, 0x00, 0x12, 0x02, 0xF0, 0x37, 0x09, 0x00, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, +- 0xD0, 0x80, 0xA2, 0xFF, 0xB0, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0xB0, 0xFB, 0x24, 0x60, 0x74, 0x64, +- 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x2C, 0x44, 0xAC, 0x86, 0x09, 0xF0, +- 0xD9, 0x02, 0x37, 0x58, 0xFF, 0xFF, 0x1A, 0x60, 0x66, 0x63, 0x00, 0x64, 0xA3, 0xDB, 0x06, 0xA3, +- 0x10, 0x60, 0x4C, 0x64, 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, 0x00, 0x63, 0x10, 0x60, +- 0x9E, 0x62, 0xA2, 0xDD, 0x10, 0x60, 0x4A, 0x62, 0xCF, 0x60, 0x16, 0x64, 0xA2, 0xDB, 0x10, 0x60, +- 0x24, 0x62, 0xCE, 0x60, 0xE2, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x02, 0x64, +- 0xA2, 0xDB, 0xCA, 0x60, 0xFB, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x68, 0x60, +- 0x7E, 0x61, 0x3C, 0x60, 0x00, 0x66, 0x01, 0x60, 0xB8, 0x64, 0x0A, 0x63, 0x59, 0xD0, 0x58, 0xD9, +- 0xFD, 0x1F, 0x01, 0x60, 0xBE, 0x61, 0xE4, 0xF3, 0x00, 0x66, 0x00, 0xA8, 0x04, 0x65, 0x01, 0x03, +- 0xA1, 0xDB, 0x1F, 0x60, 0x08, 0x63, 0x55, 0xD3, 0xFF, 0xFF, 0x20, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, +- 0xFF, 0xFF, 0x21, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, +- 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, +- 0x00, 0x64, 0xA2, 0xDB, 0xCA, 0x60, 0xC7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x24, 0x60, 0x9A, 0x62, 0x1F, 0x60, 0x06, 0x64, 0xA2, 0xDB, 0x20, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCA, 0x60, 0xEC, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x10, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0xBA, 0xFE, 0x27, 0x60, 0xB6, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x03, 0xA8, +- 0x02, 0xA8, 0x04, 0x03, 0x0F, 0x02, 0xCE, 0x60, 0xB3, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0xEF, 0x78, +- 0xFF, 0xFF, 0x1F, 0x60, 0x80, 0x65, 0xA5, 0xD3, 0xFF, 0xFF, 0xF3, 0xB4, 0xA5, 0xDB, 0xCB, 0x60, +- 0x22, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0x1A, 0x60, 0x40, 0x64, 0xA0, 0xDD, 0x1F, 0x60, 0x80, 0x64, +- 0x00, 0x63, 0xA0, 0xDD, 0x11, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0xBA, 0xFE, 0x02, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, 0xF2, 0xFB, +- 0x44, 0x60, 0x44, 0x64, 0x81, 0xFB, 0x82, 0xFB, 0x83, 0xFB, 0xFF, 0xFF, 0x20, 0x40, 0x04, 0x2B, +- 0x19, 0x00, 0x9B, 0xFE, 0x09, 0x04, 0xBB, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, +- 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x12, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, +- 0xEC, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCB, 0x60, 0x36, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x0D, 0x64, 0x53, 0xFB, +- 0x29, 0x60, 0xA4, 0x64, 0x54, 0xFB, 0x13, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xCE, 0x61, +- 0xA1, 0xD1, 0x02, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x64, 0x40, 0x01, 0x2A, 0x07, 0x00, +- 0x00, 0x64, 0xA1, 0xDB, 0x02, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0xCA, 0x60, +- 0x58, 0x4E, 0xA7, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0x80, 0x62, 0x1A, 0x60, 0x40, 0x65, 0xA2, 0xD3, +- 0xA5, 0xD1, 0x60, 0x40, 0x0C, 0x22, 0x04, 0x00, 0x04, 0x61, 0xD1, 0x80, 0xFF, 0xFF, 0x2D, 0x05, +- 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x4E, 0xE4, 0x60, 0x58, 0x4F, 0xFB, 0x78, +- 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x60, 0xEC, 0x62, 0x10, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCB, 0x60, +- 0x95, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1F, 0x60, 0x80, 0x64, 0xA0, 0xD3, +- 0xFF, 0xFF, 0x60, 0x40, 0x0C, 0x26, 0x11, 0x00, 0xFD, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, +- 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x38, 0x00, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x0F, 0x4E, 0xEC, 0x60, 0x58, 0x4F, 0xB9, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x60, +- 0xEC, 0x62, 0x10, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCB, 0x60, 0xC2, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x14, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xFD, 0x60, 0xFF, 0x65, 0x20, 0x44, +- 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x88, 0xF1, 0x19, 0x60, 0x86, 0x63, +- 0xD3, 0x80, 0x20, 0x44, 0x05, 0x03, 0x10, 0xBC, 0x40, 0x40, 0xCD, 0x60, 0xE8, 0x78, 0xFF, 0xFF, +- 0x89, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0x20, 0x44, 0x06, 0x02, 0xD4, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, +- 0xFF, 0xFF, 0x1E, 0x02, 0x72, 0x00, 0x10, 0xBC, 0x40, 0x40, 0x64, 0x42, 0x5A, 0xD1, 0x06, 0x63, +- 0xA4, 0xD1, 0xC3, 0x83, 0x7F, 0xF9, 0xBD, 0xD1, 0x81, 0xF9, 0xBD, 0xD1, 0xFF, 0xFF, 0x82, 0xF9, +- 0xBD, 0xD1, 0x83, 0xF9, 0x04, 0xA3, 0xBD, 0xD1, 0x2D, 0x60, 0x7A, 0x64, 0x64, 0x41, 0xDD, 0x81, +- 0xFE, 0xB1, 0xA0, 0xD9, 0x04, 0x03, 0xBD, 0xD1, 0xC9, 0x81, 0x58, 0xD9, 0xFC, 0x02, 0x1E, 0x00, +- 0xE5, 0xF3, 0x7F, 0xFB, 0x29, 0x60, 0xA4, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x2D, 0x60, +- 0x7A, 0x63, 0x02, 0x02, 0x27, 0x60, 0xB8, 0x61, 0xA1, 0xD3, 0xBD, 0xDB, 0xDC, 0x84, 0xFE, 0xB4, +- 0x59, 0xD1, 0xC8, 0x84, 0xBD, 0xD9, 0xFC, 0x02, 0xED, 0xF3, 0x72, 0x45, 0xEC, 0xF3, 0x94, 0x83, +- 0x83, 0xFD, 0x94, 0x83, 0x82, 0xFD, 0x65, 0x5F, 0x02, 0x64, 0x81, 0xFB, 0x0F, 0x60, 0xEA, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0xCC, 0x60, 0x26, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x18, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x7F, 0xF1, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCC, 0x60, +- 0x4D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0xCC, 0x60, 0xAD, 0x78, 0xFF, 0xFF, 0x16, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0xFF, 0x60, 0xEF, 0x65, 0x20, 0x44, 0x24, 0x80, 0xCA, 0x60, 0x58, 0x4E, 0xA7, 0x78, 0xFF, 0xFF, +- 0x17, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x02, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, +- 0xF2, 0xFB, 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, +- 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0xDA, 0xFE, 0xC1, 0xFE, 0x1A, 0x60, 0x40, 0x62, 0xA2, 0xD1, 0x1A, 0x60, 0x6A, 0x62, +- 0xA2, 0xD9, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x06, 0x64, 0xA2, 0xDB, 0xCB, 0x60, +- 0x22, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x1A, 0x60, 0x40, 0x61, 0x75, 0x60, 0x30, 0x65, 0xA1, 0xD3, +- 0xFF, 0xFF, 0xFF, 0xA0, 0xE0, 0x84, 0x02, 0x02, 0x03, 0x60, 0xE8, 0x64, 0xD4, 0x80, 0xFF, 0xFF, +- 0x01, 0x04, 0x65, 0x44, 0xA1, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x79, 0xF3, 0x7A, 0xFB, 0x1F, 0x60, +- 0x52, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xFF, 0x60, 0xDF, 0x65, 0x20, 0x44, 0x24, 0x80, 0xBF, 0xF1, +- 0x1A, 0x60, 0x6A, 0x62, 0xA2, 0xD9, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, +- 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, +- 0x10, 0x26, 0x67, 0x00, 0x00, 0x64, 0xB5, 0xFB, 0xB6, 0xFB, 0xB7, 0xFB, 0x00, 0x75, 0x00, 0x72, +- 0xBD, 0xF1, 0x80, 0xF9, 0x64, 0x44, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x93, 0xE6, 0xF1, +- 0x86, 0xF9, 0x28, 0x60, 0xD2, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x08, 0x02, +- 0x01, 0x60, 0xB0, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x01, 0x03, 0x02, 0x64, +- 0x60, 0x41, 0x2D, 0x60, 0x28, 0x63, 0xBD, 0xD3, 0xA3, 0xD3, 0xFF, 0xB5, 0x65, 0x5C, 0xCD, 0x81, +- 0x80, 0xBF, 0x0E, 0x03, 0x80, 0xBF, 0xBD, 0xDB, 0x65, 0x44, 0xC8, 0x84, 0xFF, 0xFF, 0x0B, 0x03, +- 0x60, 0x45, 0xCD, 0x81, 0xA3, 0xD3, 0x07, 0x03, 0xCD, 0x81, 0x80, 0xBF, 0x01, 0x03, 0x80, 0xBC, +- 0x60, 0x47, 0xBD, 0xDB, 0x00, 0x65, 0x64, 0x41, 0x2D, 0x60, 0x2A, 0x63, 0xBD, 0xD3, 0xFF, 0xFF, +- 0x80, 0xB0, 0xFF, 0xFF, 0x01, 0x03, 0x60, 0x45, 0x60, 0x47, 0x80, 0xB0, 0xFF, 0xFF, 0x01, 0x03, +- 0x60, 0x45, 0xC9, 0x81, 0xFF, 0xFF, 0xF2, 0x02, 0x65, 0x44, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, +- 0x0A, 0x64, 0x15, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x14, 0x64, 0x11, 0x00, 0x0A, 0x3A, 0x02, 0x00, +- 0x32, 0x64, 0x0D, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x37, 0x64, 0x09, 0x00, 0x10, 0x3A, 0x02, 0x00, +- 0x50, 0x64, 0x05, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x6E, 0x64, 0x01, 0x00, 0x14, 0x64, 0x7C, 0xFB, +- 0x28, 0x00, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, +- 0x84, 0x64, 0xA2, 0xDB, 0xCD, 0x60, 0x40, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x80, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0D, 0x03, +- 0xA0, 0x84, 0xA2, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0x7F, 0x61, 0xA1, 0x84, +- 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x04, 0x00, 0xBB, 0xFE, 0xCB, 0x60, 0x22, 0x78, +- 0xFF, 0xFF, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD1, 0x00, 0x65, 0x64, 0x40, 0x01, 0x36, 0x22, 0x65, +- 0x64, 0x40, 0x07, 0x36, 0x01, 0x65, 0xA9, 0xF3, 0x66, 0x5C, 0x60, 0x46, 0x1F, 0x63, 0xE3, 0x83, +- 0xB6, 0xF8, 0x02, 0xA6, 0x66, 0x44, 0xFC, 0x1F, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, +- 0x60, 0x40, 0x07, 0x3A, 0x04, 0x00, 0xA9, 0xF3, 0x04, 0x65, 0x60, 0x46, 0xB6, 0xF8, 0x64, 0x46, +- 0xA9, 0xF3, 0x32, 0x41, 0x60, 0x45, 0x08, 0xB1, 0x66, 0x41, 0x17, 0x03, 0x65, 0x46, 0x29, 0x60, +- 0xA2, 0x62, 0xA2, 0xD3, 0x06, 0xF0, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, +- 0xB0, 0x84, 0x06, 0xFA, 0x66, 0x43, 0x02, 0xA3, 0x63, 0x46, 0x06, 0xF0, 0xFF, 0xFF, 0xB0, 0x84, +- 0x06, 0xFA, 0x61, 0x46, 0x32, 0x44, 0x10, 0xBC, 0x40, 0x52, 0x1F, 0x60, 0x52, 0x62, 0x01, 0x64, +- 0xA2, 0xDB, 0x0F, 0x4E, 0xE7, 0x60, 0x58, 0x4F, 0x51, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x0F, 0x60, +- 0xEA, 0x62, 0xA2, 0xD1, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x0F, 0x60, 0xEC, 0x62, +- 0x00, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0xCB, 0x60, 0x11, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x24, 0x60, +- 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0xBB, 0xFE, 0x20, 0x44, 0x04, 0x27, 0x12, 0x00, 0x10, 0x26, 0x02, 0x00, 0xDB, 0xFE, 0x16, 0x00, +- 0x0F, 0x60, 0xCE, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x36, 0x07, 0x00, 0x01, 0x64, +- 0xA1, 0xDB, 0x01, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xD0, 0x62, +- 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x64, 0x8C, 0xFB, +- 0xFF, 0x60, 0xEF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x03, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, +- 0xFE, 0xB4, 0xF2, 0xFB, 0xC1, 0xFE, 0x1E, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, +- 0x15, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xBB, 0xFE, 0xCF, 0x60, 0xD6, 0x78, 0xFF, 0xFF, 0x28, 0x60, +- 0x2C, 0x62, 0xA2, 0xD1, 0x00, 0x65, 0x64, 0x40, 0x01, 0x36, 0x22, 0x65, 0xA9, 0xF3, 0x66, 0x5C, +- 0x60, 0x46, 0x1F, 0x63, 0xE3, 0x83, 0xB6, 0xF8, 0x02, 0xA6, 0x66, 0x44, 0xFC, 0x1F, 0x64, 0x46, +- 0x79, 0xF1, 0xA9, 0xF3, 0x7A, 0xF9, 0x02, 0xA4, 0xD8, 0xF3, 0x60, 0x45, 0x66, 0x41, 0x65, 0x46, +- 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, +- 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x79, 0xF3, 0x7A, 0xF1, +- 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, 0x02, 0x02, 0x79, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, +- 0xAE, 0x65, 0xD8, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, +- 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x7B, 0xFB, 0x6F, 0xF0, +- 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, +- 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, +- 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, +- 0x66, 0x43, 0x0C, 0xF4, 0xA9, 0xF1, 0x02, 0x64, 0xC0, 0x85, 0x0C, 0x61, 0x32, 0x40, 0x08, 0x2A, +- 0x15, 0x00, 0x29, 0x60, 0xA2, 0x62, 0xA2, 0xD3, 0x66, 0x41, 0x65, 0x46, 0x06, 0xF0, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, 0xB0, 0x83, 0x06, 0xFC, 0x66, 0x42, 0xFE, 0xA2, +- 0x62, 0x46, 0x06, 0xF0, 0xFF, 0xFF, 0xB0, 0x84, 0x06, 0xFA, 0x61, 0x46, 0x1D, 0x64, 0x3B, 0x42, +- 0x5A, 0xDB, 0x0B, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0x01, 0x65, +- 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0xE5, 0xF1, 0x7F, 0xF9, 0x0F, 0x60, 0xEA, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0xCE, 0x60, 0x76, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7F, 0xF1, +- 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, +- 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCE, 0x60, 0x9A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0xBE, 0xFE, +- 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x01, 0x64, 0x8C, 0xFB, 0xFF, 0x60, 0xDF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x1E, 0x64, 0x3B, 0x42, +- 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x06, 0x64, 0xDC, 0xFB, +- 0xF2, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0xE5, 0xF1, 0x7F, 0xF9, 0x0F, 0x60, 0xEA, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x64, 0x8C, 0xFB, 0xFF, 0x60, 0xDF, 0x65, 0x20, 0x44, 0x24, 0x80, +- 0xA9, 0xF1, 0x66, 0x45, 0x64, 0x46, 0x66, 0x43, 0x02, 0xA3, 0x63, 0x46, 0x02, 0x64, 0x06, 0xFA, +- 0x04, 0x63, 0x04, 0x61, 0x01, 0x60, 0xCE, 0x64, 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, 0x65, 0x46, +- 0x01, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0x1E, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x2F, 0x58, 0xFF, 0xFF, 0x1F, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x00, 0x64, 0x68, 0xFB, 0x69, 0xFB, +- 0xA9, 0xF1, 0x0E, 0x64, 0x66, 0x41, 0x64, 0x42, 0x02, 0xA2, 0x62, 0x46, 0x06, 0xF0, 0xFF, 0x60, +- 0xFC, 0x64, 0xA0, 0x84, 0x06, 0xFA, 0x61, 0x46, 0xDC, 0xF3, 0xFF, 0xFF, 0x04, 0xA8, 0x0F, 0x60, +- 0xCE, 0x64, 0x07, 0x03, 0xA0, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2A, 0x02, 0x00, 0x00, 0x63, +- 0xA0, 0xDD, 0x01, 0x64, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0x0F, 0x60, +- 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, +- 0xCA, 0x60, 0xFB, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, +- 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x28, 0x60, 0x3A, 0x64, 0xA0, 0xD3, 0x00, 0xF4, 0x60, 0x40, 0x01, 0x3A, 0x42, 0x00, 0x18, 0x65, +- 0x22, 0x61, 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, +- 0x04, 0x65, 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, +- 0xCD, 0x81, 0xBD, 0xDB, 0xF0, 0x02, 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x01, 0xA8, +- 0xE0, 0x85, 0x27, 0x02, 0xC7, 0x83, 0xBD, 0xD3, 0xBD, 0xD3, 0x81, 0xA8, 0x0D, 0xA8, 0x21, 0x02, +- 0x20, 0x02, 0xBD, 0xD3, 0xBD, 0xD3, 0x00, 0xA8, 0x60, 0xA8, 0x1B, 0x02, 0xBD, 0xD3, 0x19, 0x02, +- 0x1D, 0xA8, 0xA3, 0xD1, 0x16, 0x02, 0xE3, 0xF9, 0x01, 0x60, 0xB8, 0x64, 0x63, 0x41, 0x0A, 0x63, +- 0x59, 0xD1, 0x58, 0xD9, 0xFD, 0x1F, 0x59, 0xD1, 0x59, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x64, 0x5E, +- 0xD6, 0xFB, 0x59, 0xD1, 0x28, 0x60, 0x36, 0x64, 0xA0, 0xD9, 0x28, 0x60, 0xD6, 0x64, 0xA0, 0xD9, +- 0x23, 0x00, 0x28, 0x60, 0x40, 0x64, 0xA0, 0xD3, 0xE3, 0xFB, 0x60, 0x40, 0x05, 0x3A, 0x03, 0x00, +- 0x68, 0x60, 0xBA, 0x61, 0x11, 0x00, 0x04, 0x3A, 0x03, 0x00, 0x68, 0x60, 0xAE, 0x61, 0x0C, 0x00, +- 0x03, 0x3A, 0x03, 0x00, 0x68, 0x60, 0xA2, 0x61, 0x07, 0x00, 0x02, 0x3A, 0x03, 0x00, 0x68, 0x60, +- 0x96, 0x61, 0x02, 0x00, 0x68, 0x60, 0x8A, 0x61, 0x3C, 0x60, 0x00, 0x66, 0x01, 0x60, 0xB8, 0x64, +- 0x0A, 0x63, 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, 0x01, 0x60, 0xBE, 0x61, 0xE4, 0xF3, 0x00, 0x66, +- 0x00, 0xA8, 0x04, 0x65, 0x01, 0x03, 0xA1, 0xDB, 0x1F, 0x60, 0x08, 0x63, 0x55, 0xD3, 0xFF, 0xFF, +- 0x20, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, 0x21, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, +- 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, +- 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xCF, 0x60, 0xA2, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x9A, 0x62, 0x1F, 0x60, 0x06, 0x64, 0xA2, 0xDB, +- 0x20, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0xCF, 0x60, 0xC7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, +- 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, +- 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x40, 0x64, 0x3B, 0x42, +- 0x5A, 0xDB, 0xBC, 0xF1, 0x1A, 0x60, 0x6A, 0x62, 0xA2, 0xD9, 0x60, 0xF5, 0xEB, 0xF1, 0x2F, 0xF8, +- 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0xBC, 0xF1, 0x19, 0xF8, 0xF8, 0x60, 0x80, 0x64, +- 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0xA9, 0xF1, 0x07, 0xF8, 0x00, 0x60, 0xD0, 0x63, 0x19, 0x60, +- 0x84, 0x64, 0xA3, 0xDB, 0x44, 0x60, 0x44, 0x64, 0x81, 0xFB, 0x82, 0xFB, 0x83, 0xFB, 0x31, 0x44, +- 0xF9, 0xB4, 0x40, 0x51, 0x00, 0x60, 0xD0, 0x63, 0x01, 0x60, 0x10, 0x65, 0xA3, 0xD3, 0xA5, 0xD1, +- 0x04, 0xA4, 0xA3, 0xDB, 0xD0, 0x80, 0xA0, 0xD1, 0x0A, 0x06, 0x41, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xCC, 0x60, 0x5D, 0x78, 0xFF, 0xFF, 0x44, 0x47, +- 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xFF, 0xA4, 0xFF, 0xFF, 0x08, 0x07, 0x0E, 0x61, +- 0x41, 0xD3, 0x32, 0x40, 0x08, 0x26, 0x03, 0x00, 0x10, 0xB0, 0xFF, 0xFF, 0xD3, 0x02, 0x42, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, +- 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD0, 0x60, 0x22, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD1, 0x7F, 0xF9, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, +- 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0xD0, 0x60, 0x47, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, +- 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, +- 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x1A, 0x60, 0x6A, 0x62, 0x07, 0x60, 0xD0, 0x64, +- 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD3, 0x81, 0xFB, 0xBD, 0xD3, 0x82, 0xFB, +- 0xA3, 0xD3, 0x83, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xEC, 0x62, +- 0x01, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0xD0, 0x60, 0x79, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0xBC, 0xF1, 0x1A, 0x60, 0x6A, 0x62, 0xA2, 0xD9, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, +- 0xFE, 0x60, 0xFF, 0x61, 0xA1, 0x84, 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x0F, 0x60, +- 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0xCF, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x08, 0x65, 0x20, 0x44, 0x34, 0x80, +- 0x5F, 0xF5, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0xBC, 0xF1, +- 0x19, 0xF8, 0x80, 0x7E, 0xF8, 0x7F, 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0xA9, 0xF1, 0x07, 0xF8, +- 0x2B, 0xFA, 0xB0, 0x64, 0x2A, 0xFA, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD1, 0x2C, 0xF8, 0x32, 0xF8, +- 0xBD, 0xD1, 0x2D, 0xF8, 0x33, 0xF8, 0xA3, 0xD1, 0x2E, 0xF8, 0x34, 0xF8, 0x06, 0x63, 0x3F, 0xFC, +- 0x1F, 0x60, 0x54, 0x61, 0xDC, 0xF3, 0xA1, 0xD3, 0x03, 0xA8, 0xAC, 0x83, 0x0F, 0x02, 0x0E, 0x03, +- 0x1F, 0x60, 0x56, 0x61, 0xA1, 0xD1, 0x66, 0x45, 0x00, 0xF4, 0x09, 0xFC, 0x01, 0x64, 0x0A, 0xFA, +- 0x0B, 0xF8, 0x1F, 0x60, 0x54, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x28, 0x00, 0x28, 0x60, 0x2E, 0x64, +- 0xA0, 0xD3, 0x66, 0x45, 0x00, 0xF4, 0x60, 0x40, 0x01, 0x36, 0x16, 0x00, 0x02, 0x36, 0xC7, 0x00, +- 0x03, 0x36, 0x07, 0x00, 0x04, 0x36, 0x10, 0x00, 0x05, 0x36, 0xC1, 0x00, 0x06, 0x36, 0x01, 0x00, +- 0x0B, 0x00, 0x80, 0x64, 0x09, 0xFA, 0x01, 0x63, 0x0A, 0xFC, 0x00, 0x64, 0x0B, 0xFA, 0x2D, 0x60, +- 0x54, 0x62, 0x03, 0x64, 0xA2, 0xDB, 0x0A, 0x00, 0x00, 0x64, 0x09, 0xFA, 0x01, 0x63, 0x0A, 0xFC, +- 0x00, 0x64, 0x0B, 0xFA, 0x2D, 0x60, 0x54, 0x62, 0x01, 0x64, 0xA2, 0xDB, 0x24, 0x60, 0x74, 0x62, +- 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x65, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x00, 0x66, 0xDC, 0xF3, 0x46, 0x46, 0xFD, 0xA0, 0xC1, 0xFE, 0x02, 0x02, 0x2F, 0x58, +- 0xFF, 0xFF, 0x01, 0x64, 0x69, 0xFB, 0x43, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x1A, 0x60, 0x44, 0x62, +- 0xA2, 0xD3, 0xFF, 0xFF, 0x64, 0xA4, 0xA2, 0xDB, 0x1A, 0x60, 0x44, 0x62, 0xA2, 0xD1, 0x1A, 0x60, +- 0x6A, 0x62, 0xA2, 0xD9, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x0C, 0x64, 0xA2, 0xDB, +- 0xD1, 0x60, 0x2E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, +- 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x56, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x26, 0x46, +- 0x00, 0xF4, 0x09, 0xF2, 0x0A, 0xF2, 0x00, 0xA8, 0x0B, 0xF2, 0x02, 0xA8, 0x16, 0x02, 0x00, 0xA8, +- 0x1A, 0x02, 0x19, 0x02, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, +- 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, 0xD3, 0x60, +- 0x48, 0x78, 0xFF, 0xFF, 0xD9, 0x60, 0x68, 0x78, 0xFF, 0xFF, 0x09, 0xF2, 0x0A, 0xF2, 0x80, 0xA8, +- 0x0B, 0xF2, 0x02, 0xA8, 0xE4, 0x03, 0x44, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0B, 0xF2, 0x26, 0x46, +- 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, +- 0x31, 0xF2, 0x59, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, +- 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x4C, 0x78, +- 0xFF, 0xFF, 0xDC, 0x60, 0xAA, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0xA2, 0xDB, +- 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x20, 0x40, 0x08, 0x2A, +- 0x03, 0x00, 0xCF, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0xD7, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x01, 0x63, +- 0x09, 0xFC, 0x32, 0x40, 0x08, 0x26, 0x1A, 0x00, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, +- 0x60, 0x40, 0x0B, 0x36, 0x03, 0x00, 0xD0, 0x60, 0xEC, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0xA2, 0xDB, +- 0x2D, 0x60, 0x56, 0x62, 0x0B, 0x64, 0xA2, 0xDB, 0x2D, 0x60, 0x54, 0x62, 0x02, 0x64, 0xA2, 0xDB, +- 0xA9, 0xF1, 0x66, 0x41, 0x64, 0x46, 0x22, 0x64, 0x36, 0xFA, 0x61, 0x46, 0x01, 0x64, 0x0A, 0xFA, +- 0x00, 0x64, 0x0B, 0xFA, 0x01, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x65, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, 0xDC, 0xF3, 0x46, 0x46, 0xFD, 0xA0, 0xC1, 0xFE, +- 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, +- 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x0C, 0x64, +- 0xA2, 0xDB, 0xD1, 0x60, 0xEF, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, +- 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x3B, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x69, 0xFB, 0x26, 0x46, 0x00, 0xF4, 0x09, 0xF2, 0x0A, 0xF2, +- 0x01, 0xA8, 0x0B, 0xF2, 0x02, 0xA8, 0x04, 0x02, 0x00, 0xA8, 0x02, 0x02, 0x01, 0x02, 0x31, 0x00, +- 0xD2, 0x60, 0x58, 0x4D, 0xF6, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, 0x26, 0x46, 0x40, 0x59, 0x02, 0x60, +- 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x31, 0xF2, 0x59, 0xDB, +- 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, +- 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x4C, 0x78, 0xFF, 0xFF, 0xDC, 0x60, +- 0xAA, 0x78, 0xFF, 0xFF, 0xD2, 0x60, 0x58, 0x4D, 0xF6, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x69, 0xFB, +- 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, 0xCF, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0xD7, 0x60, 0xDD, 0x78, +- 0xFF, 0xFF, 0x26, 0x46, 0x40, 0x60, 0x00, 0x65, 0x2A, 0xF2, 0x2F, 0xF0, 0xB4, 0x84, 0x2A, 0xFA, +- 0x2C, 0xF8, 0x32, 0xF8, 0x30, 0xF2, 0x2D, 0xFA, 0x33, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x34, 0xFA, +- 0xEB, 0xF3, 0x2F, 0xFA, 0xEC, 0xF3, 0x30, 0xFA, 0xED, 0xF3, 0x31, 0xFA, 0xCC, 0xF1, 0x19, 0xF8, +- 0x1C, 0xF0, 0x13, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x00, 0xF4, 0x03, 0x64, 0x0A, 0xFA, 0x00, 0x64, +- 0x0B, 0xFA, 0x01, 0x63, 0x69, 0xFD, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x24, 0x60, +- 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, 0xDC, 0xF3, 0x46, 0x46, 0xFD, 0xA0, 0xC1, 0xFE, 0x02, 0x02, +- 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x0C, 0x64, 0xA2, 0xDB, +- 0xD2, 0x60, 0x8E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, +- 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x51, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x00, 0x64, 0x69, 0xFB, 0x26, 0x46, 0x00, 0xF4, 0x09, 0xF2, 0x0A, 0xF2, 0x01, 0xA8, +- 0x0B, 0xF2, 0x04, 0xA8, 0x1A, 0x02, 0x00, 0xA8, 0x18, 0x02, 0x17, 0x02, 0xD2, 0x60, 0x58, 0x4D, +- 0xF6, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, +- 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, 0xD3, 0x60, +- 0x48, 0x78, 0xFF, 0xFF, 0xD9, 0x60, 0x68, 0x78, 0xFF, 0xFF, 0xD2, 0x60, 0x58, 0x4D, 0xF6, 0x78, +- 0xFF, 0xFF, 0x0B, 0xF2, 0x26, 0x46, 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, +- 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x31, 0xF2, 0x59, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, +- 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, +- 0xE9, 0x60, 0x58, 0x4E, 0x4C, 0x78, 0xFF, 0xFF, 0xDC, 0x60, 0xAA, 0x78, 0xFF, 0xFF, 0xD2, 0x60, +- 0x58, 0x4D, 0xF6, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x69, 0xFB, 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, +- 0xCF, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0xD7, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x2D, 0x60, 0x56, 0x62, +- 0xA2, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x0B, 0x3A, 0x07, 0x00, 0x28, 0x60, 0x2C, 0x62, 0x0B, 0x64, +- 0xA2, 0xDB, 0x2D, 0x60, 0x56, 0x62, 0xA2, 0xDF, 0x2D, 0x58, 0xFF, 0xFF, 0x28, 0x60, 0x2C, 0x62, +- 0xA2, 0xD3, 0x61, 0x43, 0xA5, 0xD2, 0x60, 0x40, 0x0B, 0x2A, 0x30, 0x00, 0x85, 0x3A, 0x30, 0x00, +- 0x60, 0x41, 0x65, 0x44, 0x0A, 0xA4, 0xA0, 0xD0, 0x2D, 0x60, 0x52, 0x62, 0x64, 0x40, 0x18, 0x26, +- 0x06, 0x00, 0xA2, 0xDF, 0x28, 0x60, 0x2C, 0x62, 0x01, 0x64, 0xA2, 0xDB, 0x02, 0x00, 0x01, 0x64, +- 0xA2, 0xDB, 0x61, 0x44, 0x60, 0x47, 0xFF, 0xB4, 0x02, 0xA4, 0x2E, 0x60, 0x62, 0x61, 0xA1, 0xD1, +- 0xDF, 0x83, 0xC0, 0x84, 0xA1, 0xDB, 0xD0, 0x81, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, +- 0xA5, 0xD2, 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, +- 0x5D, 0x93, 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x2D, 0x58, 0xFF, 0xFF, +- 0x2D, 0x60, 0x52, 0x62, 0xA2, 0xDF, 0x28, 0x60, 0x2C, 0x62, 0x01, 0x64, 0xA2, 0xDB, 0xF6, 0x01, +- 0x45, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x2E, 0x60, 0xEA, 0x7C, 0x2E, 0x60, 0xDE, 0x63, 0xA3, 0xD9, +- 0x64, 0x41, 0x29, 0x60, 0xA4, 0x63, 0xBD, 0xD3, 0x00, 0x7C, 0x03, 0x1B, 0x27, 0x43, 0x10, 0xA3, +- 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x45, 0x64, 0x5F, 0xA1, 0xDB, 0x65, 0x44, 0xBD, 0xD1, 0xC8, 0x84, +- 0x59, 0xD8, 0xFC, 0x05, 0x27, 0x41, 0x10, 0xA1, 0xA1, 0xD1, 0xFF, 0xFF, 0xC1, 0x81, 0x01, 0x26, +- 0xDD, 0x81, 0x41, 0x4C, 0x59, 0xD1, 0x7C, 0x44, 0xB0, 0x84, 0x59, 0xD1, 0x59, 0xD1, 0xB0, 0x84, +- 0xB0, 0x84, 0xFF, 0xFF, 0x02, 0x02, 0x67, 0x44, 0x5D, 0x00, 0x2D, 0x60, 0xE6, 0x63, 0xDD, 0x60, +- 0x18, 0x64, 0xBD, 0xDA, 0x50, 0x60, 0x00, 0x64, 0xBD, 0xDA, 0x01, 0x60, 0xF2, 0x64, 0xBD, 0xDA, +- 0x00, 0x60, 0x01, 0x64, 0xBD, 0xDA, 0x2C, 0x41, 0x59, 0xD3, 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, +- 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, 0xF2, 0x64, 0x0E, 0x00, 0x04, 0x2A, 0x03, 0x00, 0x02, 0x60, +- 0xF2, 0x64, 0x09, 0x00, 0x10, 0x2A, 0x03, 0x00, 0x04, 0x60, 0xF2, 0x64, 0x04, 0x00, 0x20, 0x2A, +- 0x04, 0x00, 0x05, 0x60, 0xF2, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, 0x01, 0x64, 0xBD, 0xDB, 0x59, 0xD3, +- 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, 0xF2, 0x64, 0x0E, 0x00, +- 0x04, 0x2A, 0x03, 0x00, 0x02, 0x60, 0xF2, 0x64, 0x09, 0x00, 0x10, 0x2A, 0x03, 0x00, 0x04, 0x60, +- 0xF2, 0x64, 0x04, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, 0xF2, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, +- 0x01, 0x64, 0xBD, 0xDB, 0x59, 0xD3, 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, +- 0x00, 0x60, 0xF2, 0x64, 0x09, 0x00, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, 0xF2, 0x64, 0x04, 0x00, +- 0x04, 0x2A, 0x02, 0x00, 0x02, 0x60, 0xF2, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, 0x59, 0xD3, 0xBD, 0xDA, +- 0x2D, 0x60, 0xE6, 0x64, 0x2E, 0x60, 0xE4, 0x62, 0xA2, 0xDB, 0x60, 0xF5, 0x00, 0x64, 0x2B, 0xFA, +- 0x00, 0x64, 0x2A, 0xFA, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD1, 0x2C, 0xF8, 0x32, 0xF8, 0xBD, 0xD1, +- 0x2D, 0xF8, 0x33, 0xF8, 0xA3, 0xD1, 0x2E, 0xF8, 0x34, 0xF8, 0x00, 0xF4, 0x01, 0x63, 0x32, 0x40, +- 0x08, 0x26, 0x10, 0xBB, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0xFE, 0x26, +- 0x10, 0xBB, 0x09, 0xFC, 0x27, 0x42, 0x0C, 0xA2, 0x28, 0x60, 0x02, 0x63, 0xA2, 0xD3, 0xA3, 0xD3, +- 0x00, 0xBD, 0x01, 0x63, 0xAC, 0x81, 0x09, 0x03, 0x08, 0x03, 0xB0, 0x60, 0x58, 0x4D, 0xB6, 0x78, +- 0xFF, 0xFF, 0x00, 0xB8, 0x01, 0x63, 0x01, 0x03, 0x60, 0x43, 0x1A, 0x60, 0x3E, 0x64, 0xA0, 0xDD, +- 0x12, 0x61, 0x59, 0xDC, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0xFF, 0x60, 0xFF, 0x7C, 0x60, 0x40, +- 0x0B, 0x2A, 0x02, 0x00, 0x2D, 0x60, 0x32, 0x7C, 0x2E, 0x60, 0xE6, 0x62, 0xA2, 0xD9, 0x2E, 0x60, +- 0xDE, 0x64, 0x40, 0x48, 0xD9, 0x81, 0xFF, 0x60, 0xF2, 0x64, 0xE8, 0x60, 0x58, 0x4D, 0xE8, 0x78, +- 0xFF, 0xFF, 0x60, 0xF5, 0x3F, 0xFC, 0xDB, 0x83, 0x2E, 0x60, 0x08, 0x62, 0xA2, 0xDD, 0x00, 0x7C, +- 0x5A, 0xD9, 0x63, 0x41, 0x2E, 0x60, 0x0C, 0x63, 0x12, 0x65, 0x00, 0xF4, 0xCD, 0x84, 0x4C, 0x91, +- 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, +- 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, +- 0x60, 0xF5, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xC1, 0xFE, 0x06, 0x64, +- 0x69, 0xFB, 0x46, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, +- 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, +- 0x1C, 0x64, 0xA2, 0xDB, 0xD4, 0x60, 0x68, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x3A, 0x03, +- 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x26, 0x46, +- 0x00, 0xF4, 0x0A, 0xF2, 0x00, 0x63, 0x00, 0xA8, 0x69, 0xFD, 0x5A, 0x03, 0x0A, 0xF2, 0x26, 0x46, +- 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, +- 0x31, 0xF2, 0x59, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, +- 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x05, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x4C, 0x78, +- 0xFF, 0xFF, 0xDC, 0x60, 0xAA, 0x78, 0xFF, 0xFF, 0x47, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xCF, 0x60, +- 0xF2, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x21, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, +- 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x49, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xD0, 0x60, 0x94, 0x78, 0xFF, 0xFF, +- 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x4A, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xCF, 0x60, 0xF2, 0x78, 0xFF, 0xFF, +- 0x48, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x09, 0xF0, 0x2E, 0x60, 0x64, 0x63, 0x10, 0x64, 0xBD, 0xDB, +- 0xBD, 0xD9, 0x0A, 0xF0, 0xBD, 0xD9, 0x0B, 0xF0, 0xBD, 0xD9, 0x0C, 0xF2, 0xBD, 0xDB, 0x60, 0x47, +- 0xFF, 0xB4, 0x0A, 0xA5, 0x2E, 0x60, 0x62, 0x61, 0x65, 0x5C, 0xA1, 0xD9, 0x60, 0x41, 0x1A, 0x65, +- 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, +- 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, +- 0x20, 0xFE, 0xDF, 0x83, 0xD3, 0x60, 0x58, 0x4D, 0x06, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, 0xFF, 0xFF, +- 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x61, 0x44, 0x96, 0xFB, +- 0x27, 0x45, 0x02, 0x62, 0x46, 0xD3, 0x5A, 0xD1, 0x60, 0x47, 0x56, 0xFB, 0x64, 0x47, 0x55, 0xFB, +- 0x00, 0x64, 0x5C, 0xFB, 0x0C, 0x62, 0x46, 0xD3, 0x80, 0xFB, 0x0B, 0xF0, 0x0F, 0x60, 0xFF, 0x64, +- 0xA0, 0x84, 0x85, 0xFB, 0x26, 0x46, 0x32, 0xF0, 0x81, 0xF9, 0x33, 0xF0, 0x0E, 0x63, 0xC7, 0x81, +- 0x82, 0xF9, 0x34, 0xF0, 0x83, 0xF9, 0x59, 0xD1, 0xFF, 0xFF, 0x64, 0x44, 0x01, 0x2A, 0xC8, 0x84, +- 0x60, 0x43, 0x2D, 0x60, 0x78, 0x64, 0x58, 0xD9, 0x59, 0xD1, 0x58, 0xD9, 0xFD, 0x1F, 0x28, 0x60, +- 0x2C, 0x62, 0xA2, 0xD1, 0x59, 0xD3, 0x64, 0x40, 0x01, 0x36, 0x22, 0x64, 0x64, 0x40, 0x00, 0x36, +- 0x50, 0x94, 0xA9, 0xF1, 0xFF, 0xFF, 0x44, 0x47, 0xA7, 0x46, 0x36, 0xFA, 0xB7, 0xFC, 0xA7, 0x46, +- 0x1A, 0x60, 0x3E, 0x62, 0xA2, 0xD3, 0x87, 0xFB, 0x31, 0xF2, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, +- 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, +- 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, 0x08, 0xFE, +- 0x60, 0x43, 0x61, 0x46, 0xA9, 0xF1, 0xFF, 0xFF, 0xD3, 0x80, 0x31, 0xF2, 0x27, 0x02, 0x66, 0x41, +- 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xA9, 0xF1, 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, +- 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, +- 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, +- 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, +- 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, 0x43, 0x47, 0x00, 0xF4, +- 0x18, 0x65, 0x0C, 0x61, 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x64, 0x44, 0x00, 0x7F, +- 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0xF4, 0x02, +- 0x02, 0x60, 0x02, 0x61, 0xA1, 0xD3, 0x00, 0x65, 0x60, 0x43, 0x59, 0xD3, 0xFF, 0xFF, 0x7F, 0xB4, +- 0x02, 0x3A, 0x02, 0x00, 0x01, 0x64, 0x15, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, 0x11, 0x00, +- 0x0A, 0x3A, 0x02, 0x00, 0x04, 0x64, 0x0D, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x09, 0x00, +- 0x10, 0x3A, 0x02, 0x00, 0x10, 0x64, 0x05, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x20, 0x64, 0x01, 0x00, +- 0x00, 0x64, 0xCF, 0x83, 0xB4, 0x85, 0xE1, 0x02, 0x65, 0x44, 0x7A, 0xFB, 0x02, 0x60, 0x02, 0x61, +- 0xA1, 0xD3, 0x00, 0x65, 0x60, 0x43, 0x59, 0xD3, 0xFF, 0xFF, 0x80, 0xB0, 0xFF, 0xFF, 0x01, 0x03, +- 0x60, 0x45, 0xCF, 0x83, 0x65, 0x44, 0xF7, 0x02, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x0A, 0x64, +- 0x15, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x14, 0x64, 0x11, 0x00, 0x0A, 0x3A, 0x02, 0x00, 0x32, 0x64, +- 0x0D, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x37, 0x64, 0x09, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x50, 0x64, +- 0x05, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x6E, 0x64, 0x01, 0x00, 0x14, 0x64, 0x7C, 0xFB, 0x27, 0x44, +- 0xD8, 0xF3, 0x60, 0x45, 0x66, 0x41, 0x65, 0x46, 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, 0x06, 0x00, +- 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, 0x01, 0x00, +- 0x01, 0x64, 0x6F, 0xFA, 0x79, 0xF3, 0x7A, 0xF1, 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, 0x02, 0x02, +- 0x79, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, 0xAE, 0x65, 0xD8, 0xF3, 0xFF, 0xFF, 0xE0, 0x84, +- 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, +- 0xFC, 0x03, 0xA4, 0x84, 0x7B, 0xFB, 0x6F, 0xF0, 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, 0x60, 0x47, +- 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x70, 0xF0, +- 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, 0xE1, 0x81, +- 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x66, 0x43, 0x0C, 0xF4, 0x2D, 0x60, 0xD2, 0x62, +- 0xA2, 0xD3, 0x2D, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x60, 0x47, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD1, +- 0xB0, 0x84, 0x64, 0x40, 0x01, 0x36, 0x22, 0x64, 0x64, 0x40, 0x00, 0x36, 0x50, 0x94, 0xA7, 0x46, +- 0x36, 0xFA, 0xB7, 0xFC, 0xA7, 0x46, 0x80, 0x60, 0x03, 0x65, 0x32, 0x40, 0x08, 0x2A, 0x03, 0x65, +- 0xA7, 0x46, 0x06, 0xF0, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xB4, 0x84, 0x06, 0xFA, 0xB7, 0xFC, +- 0xA7, 0x46, 0x26, 0x46, 0x2F, 0xF0, 0x30, 0xF0, 0x64, 0x43, 0x31, 0xF2, 0x27, 0x46, 0x03, 0xFC, +- 0x04, 0xF8, 0x05, 0xFA, 0x26, 0x46, 0xCF, 0x60, 0x58, 0x4E, 0x20, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, +- 0x46, 0x46, 0x01, 0x64, 0x8C, 0xFB, 0x28, 0x60, 0x38, 0x62, 0xA2, 0xD3, 0x20, 0x41, 0x00, 0xBC, +- 0x20, 0xB9, 0x01, 0x03, 0x41, 0x40, 0x1F, 0x60, 0x52, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x04, 0x64, +- 0xC1, 0xFE, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF2, 0xFB, 0xF7, 0x60, 0xFF, 0x65, +- 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0x0F, 0x60, +- 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0C, 0x64, +- 0x69, 0xFB, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x31, 0x64, 0xA2, 0xDB, 0xD6, 0x60, 0xC4, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x0E, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x01, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x10, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x31, 0x60, 0x2C, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x03, 0x1B, +- 0xDC, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0xDC, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0xD7, 0x60, 0x67, 0x78, +- 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xF8, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0xA9, 0xF3, 0xFF, 0xFF, 0x02, 0xA4, 0x60, 0x43, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, +- 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x1C, 0x60, 0xBA, 0x65, 0x60, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0xA9, 0xF3, 0x63, 0x45, +- 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, +- 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x4B, 0x64, 0x3B, 0x42, +- 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, 0x2E, 0x62, 0xA2, 0xD3, +- 0xFF, 0xFF, 0x10, 0xB0, 0xFF, 0xFF, 0x13, 0x03, 0x0F, 0x60, 0xEC, 0x62, 0x04, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0xD7, 0x60, 0x2F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, +- 0x01, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x6A, 0xF3, +- 0xFF, 0xFF, 0x01, 0xB0, 0xFF, 0xFF, 0x13, 0x03, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, +- 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xEC, 0x62, 0x02, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0xD7, 0x60, 0x47, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, +- 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x69, 0xFB, 0xD7, 0x60, 0x58, 0x4E, 0x77, 0x78, +- 0xFF, 0xFF, 0x02, 0x64, 0x8C, 0xFB, 0x02, 0x64, 0xC1, 0xFE, 0xDC, 0xFB, 0xF2, 0xF3, 0xFF, 0xFF, +- 0x01, 0xBC, 0xF2, 0xFB, 0x02, 0x65, 0xE9, 0x60, 0x58, 0x4E, 0x7B, 0x78, 0xFF, 0xFF, 0x03, 0x60, +- 0xE8, 0x63, 0x1A, 0x60, 0x40, 0x64, 0xA0, 0xDD, 0xCB, 0x60, 0x1A, 0x78, 0xFF, 0xFF, 0x00, 0x60, +- 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xFF, 0xFF, 0x08, 0x24, 0x54, 0x01, 0xA0, 0x84, 0xA2, 0xDB, +- 0x00, 0x63, 0x69, 0xFD, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x15, 0x00, 0x24, 0x60, +- 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x64, 0x8C, 0xFB, +- 0xFF, 0xFF, 0xC1, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x50, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, +- 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, 0x2E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x10, 0xB0, +- 0xFF, 0xFF, 0x13, 0x03, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xEC, 0x62, 0x04, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD7, 0x60, +- 0x8F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBC, 0xF1, 0x1A, 0x60, 0x6A, 0x62, +- 0xA2, 0xD9, 0x7F, 0xF1, 0x7E, 0xF9, 0x02, 0x64, 0x8C, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x8C, 0xF3, +- 0x00, 0x65, 0xD4, 0x80, 0xFF, 0xFF, 0x0F, 0x03, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x0F, 0x60, 0xEC, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD7, 0x60, 0xB3, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x51, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x19, 0x60, 0x84, 0x64, 0x68, 0xFB, 0x1A, 0x60, 0x46, 0x63, 0x81, 0xF3, +- 0xBD, 0xDB, 0x82, 0xF3, 0xBD, 0xDB, 0x83, 0xF3, 0xA3, 0xDB, 0x01, 0x60, 0x10, 0x65, 0x68, 0xF3, +- 0xA5, 0xD1, 0x04, 0xA4, 0x68, 0xFB, 0xD0, 0x80, 0xA0, 0xD3, 0x20, 0x07, 0x40, 0x47, 0x60, 0x41, +- 0x0E, 0x65, 0x45, 0xD3, 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, 0x03, 0x1B, 0x10, 0xB0, +- 0xFF, 0xFF, 0xEB, 0x02, 0x27, 0x44, 0x06, 0xA4, 0x60, 0x41, 0xA1, 0xD1, 0x81, 0xF3, 0x82, 0xF1, +- 0xD0, 0x80, 0x59, 0xD3, 0x08, 0x02, 0xD0, 0x80, 0x83, 0xF3, 0x59, 0xD1, 0x04, 0x02, 0xD0, 0x80, +- 0xFF, 0xFF, 0x01, 0x02, 0x03, 0x00, 0xD8, 0x60, 0x99, 0x78, 0xFF, 0xFF, 0x1A, 0x60, 0x46, 0x63, +- 0xBD, 0xD3, 0x81, 0xFB, 0xBD, 0xD3, 0x82, 0xFB, 0xA3, 0xD3, 0x83, 0xFB, 0x53, 0x64, 0x3B, 0x42, +- 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, +- 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD8, 0x60, 0x06, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x7E, 0xF1, 0x7F, 0xF9, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, +- 0xD8, 0x60, 0x36, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x63, 0x8C, 0xFD, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, +- 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x54, 0x64, 0x3B, 0x42, +- 0x5A, 0xDB, 0x31, 0x44, 0xF9, 0xB4, 0x40, 0x51, 0x01, 0x60, 0xBA, 0x61, 0x1F, 0x60, 0x08, 0x63, +- 0xA1, 0xD3, 0xFF, 0xFF, 0x20, 0x7F, 0xBD, 0xDB, 0x59, 0xD3, 0xFF, 0xFF, 0x21, 0x7F, 0xBD, 0xDB, +- 0x59, 0xD3, 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD8, 0x60, +- 0x64, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x9A, 0x62, 0x1F, 0x60, +- 0x06, 0x64, 0xA2, 0xDB, 0x20, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, +- 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD8, 0x60, 0x89, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, +- 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xD6, 0x60, 0xB7, 0x78, +- 0xFF, 0xFF, 0x27, 0x43, 0x2D, 0x60, 0x7A, 0x65, 0xA5, 0xD3, 0x65, 0x41, 0x10, 0xA3, 0x01, 0xA4, +- 0xFE, 0xB4, 0xC4, 0x85, 0xFE, 0xA1, 0xBD, 0xD3, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0xD5, 0x80, +- 0x02, 0x02, 0x04, 0x03, 0xF8, 0x01, 0xD7, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x55, 0x64, 0x3B, 0x42, +- 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, +- 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD8, 0x60, 0xB1, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD1, 0x7F, 0xF9, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, +- 0xD8, 0x60, 0xD6, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x60, 0xBA, 0x61, 0x1F, 0x60, 0x08, 0x63, 0xA1, 0xD3, +- 0xFF, 0xFF, 0x20, 0x7F, 0xBD, 0xDB, 0x21, 0x60, 0x32, 0x64, 0xBD, 0xDB, 0x04, 0xA1, 0xA1, 0xD3, +- 0xFF, 0xFF, 0x22, 0x7F, 0xA3, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, +- 0x0B, 0x04, 0x0F, 0x60, 0xEC, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xD8, 0x60, 0xF3, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0x9A, 0x62, 0x1F, 0x60, 0x06, 0x64, +- 0xA2, 0xDB, 0x20, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x20, 0x60, +- 0x00, 0x64, 0xA2, 0xDB, 0xD9, 0x60, 0x18, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, +- 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x1A, 0x60, 0x6A, 0x62, 0x07, 0x60, +- 0xD0, 0x64, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x02, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD3, 0x81, 0xFB, 0xBD, 0xD3, +- 0x82, 0xFB, 0xA3, 0xD3, 0x83, 0xFB, 0x31, 0x44, 0xF9, 0xB4, 0x40, 0x51, 0x0F, 0x60, 0xEA, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xEC, 0x62, 0x01, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0xD9, 0x60, +- 0x4D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBC, 0xF1, 0x1A, 0x60, 0x6A, 0x62, +- 0xA2, 0xD9, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0xFE, 0x60, 0xFF, 0x61, 0xA1, 0x84, 0x5A, 0xD1, +- 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xD7, 0x60, 0xDD, 0x78, 0xFF, 0xFF, +- 0x27, 0x42, 0x0C, 0xA2, 0x28, 0x60, 0x02, 0x63, 0xA2, 0xD3, 0xA3, 0xD3, 0x00, 0xBD, 0x01, 0x63, +- 0xAC, 0x81, 0x09, 0x03, 0x08, 0x03, 0xB0, 0x60, 0x58, 0x4D, 0xB6, 0x78, 0xFF, 0xFF, 0x00, 0xB8, +- 0x01, 0x63, 0x01, 0x03, 0x60, 0x43, 0x1A, 0x60, 0x3E, 0x64, 0xA0, 0xDD, 0x60, 0xF5, 0x00, 0x64, +- 0x2B, 0xFA, 0x20, 0x64, 0x2A, 0xFA, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD1, 0x2C, 0xF8, 0x32, 0xF8, +- 0xBD, 0xD1, 0x2D, 0xF8, 0x33, 0xF8, 0xA3, 0xD1, 0x2E, 0xF8, 0x34, 0xF8, 0xEB, 0xF1, 0x2F, 0xF8, +- 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0xBC, 0xF1, 0x19, 0xF8, 0xF8, 0x60, 0x80, 0x64, +- 0x0E, 0xFA, 0x00, 0xF4, 0x01, 0x63, 0x32, 0x40, 0x08, 0x26, 0x10, 0xBB, 0x28, 0x60, 0x2C, 0x62, +- 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0xFE, 0x26, 0x10, 0xBB, 0x09, 0xFC, 0x1A, 0x60, 0x3E, 0x64, +- 0xA0, 0xD3, 0x12, 0x61, 0x59, 0xDA, 0x1A, 0x60, 0x46, 0x63, 0xBD, 0xD1, 0x59, 0xD8, 0xBD, 0xD1, +- 0x59, 0xD8, 0xA3, 0xD1, 0x59, 0xD8, 0x2E, 0x60, 0xDE, 0x64, 0x40, 0x48, 0xD9, 0x81, 0xFF, 0x60, +- 0xF2, 0x64, 0xE8, 0x60, 0x58, 0x4D, 0xE8, 0x78, 0xFF, 0xFF, 0x60, 0xF5, 0x3F, 0xFC, 0xDB, 0x83, +- 0x2E, 0x60, 0x08, 0x62, 0xA2, 0xDD, 0x20, 0x7C, 0x5A, 0xD9, 0x63, 0x41, 0x2E, 0x60, 0x0C, 0x63, +- 0x12, 0x65, 0x00, 0xF4, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, +- 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, +- 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x60, 0xF5, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, +- 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0x00, 0x66, 0x46, 0x46, 0xC1, 0xFE, 0x14, 0x64, 0x69, 0xFB, 0x56, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x1A, 0x60, 0x44, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x64, 0xA4, 0xA2, 0xDB, 0x1A, 0x60, 0x44, 0x62, +- 0xA2, 0xD1, 0x1A, 0x60, 0x6A, 0x62, 0xA2, 0xD9, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, +- 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, +- 0x1C, 0x64, 0xA2, 0xDB, 0xDA, 0x60, 0x10, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0E, 0x03, +- 0xA0, 0x84, 0xA2, 0xDB, 0x57, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, +- 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xD7, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x17, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, +- 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x58, 0x64, 0x3B, 0x42, +- 0x5A, 0xDB, 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDB, 0x60, +- 0xCB, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x3A, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x66, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x69, 0xFB, 0x0F, 0x60, 0xEA, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x26, 0x46, 0x00, 0xF4, 0x0A, 0xF2, 0xFF, 0xFF, 0x2C, 0x18, 0x59, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x0A, 0xF2, 0x26, 0x46, 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, +- 0x41, 0x58, 0x59, 0xDB, 0x31, 0xF2, 0x59, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, +- 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x05, 0x65, 0xE9, 0x60, +- 0x58, 0x4E, 0x4C, 0x78, 0xFF, 0xFF, 0xDC, 0x60, 0xAA, 0x78, 0xFF, 0xFF, 0xD7, 0x60, 0xDD, 0x78, +- 0xFF, 0xFF, 0x5A, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x78, 0x43, 0x02, 0x61, 0x24, 0x60, 0xDD, 0x78, +- 0xFF, 0xFF, 0x5B, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x09, 0xF0, 0x2E, 0x60, 0x64, 0x63, 0x30, 0x64, +- 0xBD, 0xDB, 0xBD, 0xD9, 0x0A, 0xF0, 0xBD, 0xD9, 0x0B, 0xF0, 0xBD, 0xD9, 0x0C, 0xF2, 0xBD, 0xDB, +- 0x60, 0x47, 0xFF, 0xB4, 0x0A, 0xA5, 0x2E, 0x60, 0x62, 0x62, 0x65, 0x5C, 0xA2, 0xD9, 0x60, 0x41, +- 0x1A, 0x65, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, 0x7F, 0x26, +- 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, 0xF6, 0x1F, +- 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0xD3, 0x60, 0x58, 0x4D, 0x06, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, +- 0xFF, 0xFF, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x61, 0x44, +- 0x96, 0xFB, 0x27, 0x45, 0x02, 0x62, 0x46, 0xD3, 0x5A, 0xD1, 0x60, 0x47, 0x56, 0xFB, 0x64, 0x47, +- 0x55, 0xFB, 0x00, 0x64, 0x5C, 0xFB, 0x0C, 0x62, 0x46, 0xD3, 0x80, 0xFB, 0x0B, 0xF0, 0x0F, 0x60, +- 0xFF, 0x64, 0xA0, 0x84, 0x85, 0xFB, 0x1A, 0x60, 0x3E, 0x62, 0xA2, 0xD3, 0x87, 0xFB, 0x26, 0x46, +- 0x32, 0xF0, 0x81, 0xF9, 0x33, 0xF0, 0x82, 0xF9, 0x34, 0xF0, 0x83, 0xF9, 0x00, 0xF4, 0x18, 0x65, +- 0x0C, 0x61, 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, +- 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0xF4, 0x02, 0x02, 0x60, +- 0x02, 0x61, 0xA1, 0xD3, 0x00, 0x65, 0x60, 0x43, 0x59, 0xD3, 0xFF, 0xFF, 0x7F, 0xB4, 0x02, 0x3A, +- 0x02, 0x00, 0x01, 0x64, 0x15, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, 0x11, 0x00, 0x0A, 0x3A, +- 0x02, 0x00, 0x04, 0x64, 0x0D, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x09, 0x00, 0x10, 0x3A, +- 0x02, 0x00, 0x10, 0x64, 0x05, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x20, 0x64, 0x01, 0x00, 0x00, 0x64, +- 0xCF, 0x83, 0xB4, 0x85, 0xE1, 0x02, 0x65, 0x44, 0x7A, 0xFB, 0x02, 0x60, 0x02, 0x61, 0xA1, 0xD3, +- 0x00, 0x65, 0x60, 0x43, 0x59, 0xD3, 0xFF, 0xFF, 0x80, 0xB0, 0xFF, 0xFF, 0x01, 0x03, 0x60, 0x45, +- 0xCF, 0x83, 0x65, 0x44, 0xF7, 0x02, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x0A, 0x64, 0x15, 0x00, +- 0x04, 0x3A, 0x02, 0x00, 0x14, 0x64, 0x11, 0x00, 0x0A, 0x3A, 0x02, 0x00, 0x32, 0x64, 0x0D, 0x00, +- 0x0B, 0x3A, 0x02, 0x00, 0x37, 0x64, 0x09, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x50, 0x64, 0x05, 0x00, +- 0x16, 0x3A, 0x02, 0x00, 0x6E, 0x64, 0x01, 0x00, 0x14, 0x64, 0x7C, 0xFB, 0xA9, 0xF3, 0xFF, 0xFF, +- 0x02, 0xA4, 0xD8, 0xF3, 0x60, 0x45, 0x66, 0x41, 0x65, 0x46, 0x8C, 0xFA, 0x60, 0x40, 0x01, 0x36, +- 0x06, 0x00, 0x02, 0x36, 0x04, 0x00, 0x04, 0x36, 0x02, 0x00, 0x05, 0x3A, 0x02, 0x00, 0x00, 0x64, +- 0x01, 0x00, 0x01, 0x64, 0x6F, 0xFA, 0x79, 0xF3, 0x7A, 0xF1, 0xFF, 0xFF, 0xA0, 0x84, 0x65, 0x43, +- 0x02, 0x02, 0x79, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x0F, 0x60, 0xAE, 0x65, 0xD8, 0xF3, 0xFF, 0xFF, +- 0xE0, 0x84, 0x44, 0xD3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x04, 0x02, 0xE8, 0x84, 0xA4, 0x80, +- 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, 0x7B, 0xFB, 0x6F, 0xF0, 0x60, 0x47, 0x90, 0x84, 0x6F, 0xFA, +- 0x60, 0x47, 0x60, 0x45, 0x80, 0x64, 0xE8, 0x84, 0xA4, 0x80, 0xFF, 0xFF, 0xFC, 0x03, 0xA4, 0x84, +- 0x70, 0xF0, 0x70, 0xFA, 0x00, 0x61, 0xE8, 0x84, 0xFF, 0xFF, 0x02, 0x05, 0xDD, 0x81, 0xFB, 0x01, +- 0xE1, 0x81, 0x0F, 0x60, 0xA2, 0x65, 0x45, 0xD3, 0x0E, 0xFA, 0x66, 0x43, 0x0C, 0xF4, 0xA9, 0xF3, +- 0x1C, 0x60, 0xBA, 0x65, 0x02, 0xA4, 0x60, 0x46, 0x05, 0xF0, 0x60, 0x41, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x00, 0x7C, 0x44, 0xD9, 0x26, 0x46, 0x31, 0xF2, 0x61, 0x5C, 0x60, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD9, 0x26, 0x46, 0x2F, 0xF0, 0x61, 0x46, 0x03, 0xF8, 0x26, 0x46, 0x30, 0xF0, +- 0x61, 0x46, 0x04, 0xF8, 0x26, 0x46, 0x31, 0xF0, 0x61, 0x46, 0x05, 0xF8, 0x26, 0x46, 0xCF, 0x60, +- 0x58, 0x4E, 0x20, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, +- 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, 0xE9, 0x60, 0x58, 0x4E, +- 0x7B, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0x8C, 0xFD, 0x0F, 0x60, 0xD8, 0x62, 0xA2, 0xD1, 0x00, 0x60, +- 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x5C, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0xD6, 0x60, 0xB7, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xF7, 0x65, 0x20, 0x44, 0x24, 0x80, 0xD0, 0x60, +- 0x98, 0x78, 0xFF, 0xFF, 0xDC, 0xF3, 0xFF, 0xFF, 0xFD, 0xA0, 0x2A, 0xF2, 0x03, 0x03, 0xDC, 0x60, +- 0x7B, 0x78, 0xFF, 0xFF, 0x60, 0x40, 0xB0, 0x36, 0x11, 0x00, 0xC0, 0x36, 0x02, 0x00, 0x2F, 0x58, +- 0xFF, 0xFF, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, +- 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xD0, 0x60, 0x98, 0x78, 0xFF, 0xFF, 0x66, 0x45, 0x00, 0xF4, +- 0x0A, 0xF2, 0x0B, 0xF2, 0xFE, 0xA0, 0xF3, 0xA0, 0x6F, 0x02, 0x60, 0x41, 0x09, 0xF2, 0x20, 0x03, +- 0x00, 0xA0, 0xFF, 0xA0, 0x53, 0x03, 0x65, 0x03, 0x00, 0xA0, 0xFF, 0xFF, 0x4F, 0x03, 0x1F, 0x60, +- 0x54, 0x61, 0x01, 0x64, 0xA1, 0xDB, 0x1F, 0x60, 0x56, 0x61, 0x0D, 0x64, 0xA1, 0xDB, 0x1F, 0x60, +- 0x58, 0x61, 0x03, 0x64, 0xA1, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, +- 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xD0, 0x60, 0x98, 0x78, 0xFF, 0xFF, +- 0x28, 0x60, 0x2E, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0xFE, 0xA0, 0x1F, 0x60, 0x54, 0x61, 0x17, 0x02, +- 0x01, 0x64, 0xA1, 0xDB, 0x1F, 0x60, 0x56, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x1F, 0x60, 0x58, 0x61, +- 0x01, 0x64, 0xA1, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, +- 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xD0, 0x60, 0x98, 0x78, 0xFF, 0xFF, 0x02, 0x64, +- 0xA1, 0xDB, 0x1F, 0x60, 0x56, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0x1F, 0x60, 0x58, 0x61, 0x01, 0x64, +- 0xA1, 0xDB, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, +- 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xD0, 0x60, 0x98, 0x78, 0xFF, 0xFF, 0x65, 0x46, 0x07, 0xF4, +- 0x06, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x65, 0x46, 0x26, 0x46, 0x24, 0x60, 0x74, 0x64, +- 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, +- 0xFF, 0xFF, 0xD2, 0x60, 0x41, 0x78, 0xFF, 0xFF, 0x0A, 0xF2, 0x09, 0xF2, 0xFC, 0xA0, 0xFF, 0xA0, +- 0x11, 0x02, 0x0A, 0x02, 0x0B, 0xF2, 0x65, 0x46, 0x0A, 0x1B, 0x66, 0x41, 0x07, 0xF4, 0x06, 0xF2, +- 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0xD0, 0x60, 0x98, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x2F, 0x58, 0xFF, 0xFF, 0x65, 0x46, 0x69, 0xF1, 0x2A, 0xF2, 0x64, 0x41, 0x60, 0x40, 0xA0, 0x3A, +- 0x02, 0x00, 0x08, 0xB1, 0x04, 0x00, 0xC0, 0x3A, 0x0C, 0x00, 0x04, 0xB1, 0xFF, 0xFF, 0x20, 0x03, +- 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x17, 0x00, 0xB0, 0x3A, 0x02, 0x00, 0x01, 0x65, 0x07, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x02, 0x65, +- 0x03, 0x00, 0x30, 0x3A, 0x0D, 0x00, 0x10, 0x65, 0xA5, 0x80, 0xFF, 0xFF, 0x09, 0x03, 0x0F, 0x60, +- 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x66, +- 0x2F, 0x58, 0xFF, 0xFF, 0x28, 0x60, 0x2E, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xFC, 0xA0, 0xFF, 0xFF, +- 0x16, 0x04, 0x0F, 0x60, 0xEC, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0xDC, 0x60, 0xBC, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2D, 0x60, 0x58, 0x65, 0xA5, 0xD1, 0x01, 0x60, +- 0x00, 0x64, 0xA0, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0xD0, 0x60, 0x98, 0x78, 0xFF, 0xFF, 0x20, 0x40, +- 0x08, 0x2A, 0x03, 0x00, 0xCF, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0xD7, 0x60, 0xDD, 0x78, 0xFF, 0xFF, +- 0x4E, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x2E, 0xF5, 0xFF, 0xFF, 0x27, 0xF2, 0x1C, 0x60, 0xBA, 0x65, +- 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, +- 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, +- 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, +- 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA9, 0xF3, +- 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x25, 0xF2, 0x26, 0xF0, 0xA7, 0xF2, 0xA8, 0xF0, 0x66, 0xF5, +- 0xFF, 0xFF, 0x00, 0xF4, 0xFF, 0xFF, 0x89, 0xF8, 0x66, 0xF5, 0xFF, 0xFF, 0x07, 0xFC, 0x2C, 0xFA, +- 0x2D, 0xF8, 0xAE, 0xFA, 0xEB, 0xF3, 0x2F, 0xFA, 0xEC, 0xF3, 0x30, 0xFA, 0xED, 0xF3, 0x31, 0xFA, +- 0x81, 0xF3, 0x32, 0xFA, 0x82, 0xF3, 0x33, 0xFA, 0x83, 0xF3, 0x34, 0xFA, 0x31, 0x60, 0x2C, 0x61, +- 0xA1, 0xD3, 0xFF, 0xFF, 0x03, 0x1B, 0x00, 0x60, 0xA0, 0x64, 0x02, 0x00, 0x00, 0x60, 0xC0, 0x64, +- 0x2A, 0xFA, 0x02, 0x63, 0x3F, 0xFC, 0xAB, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0xCC, 0xF1, 0x19, 0xF8, +- 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xC1, 0xFE, 0x0F, 0x60, 0xEA, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0xD6, 0x60, 0xC2, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x3A, 0x61, 0xAE, 0x60, +- 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x62, 0xFB, 0xA9, 0xF3, 0x07, 0xFA, 0x0C, 0x60, +- 0x80, 0x64, 0xBC, 0xF1, 0x19, 0xF8, 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x00, 0x60, +- 0x3A, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x61, 0xFB, 0xA9, 0xF3, +- 0x07, 0xFA, 0x0C, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0xBC, 0xF1, 0x19, 0xF8, 0x00, 0x64, 0x3E, 0xFA, +- 0x3F, 0xFA, 0x10, 0x60, 0x20, 0x62, 0xDE, 0x60, 0xDC, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xE0, 0x62, +- 0x00, 0x60, 0x80, 0x64, 0xA2, 0xDB, 0xDD, 0x60, 0x71, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x20, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x27, 0x60, 0xB6, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, +- 0x01, 0xA8, 0x03, 0xA8, 0x04, 0x03, 0x03, 0x03, 0xDE, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0x04, 0x60, +- 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x0F, 0x60, 0xDE, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x9B, 0xFE, +- 0x03, 0x05, 0x20, 0x40, 0x4B, 0x23, 0x0E, 0x00, 0x0F, 0x60, 0xE0, 0x62, 0x80, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0xDD, 0x60, 0x83, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x21, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x2F, 0x58, 0xFF, 0xFF, 0x1F, 0x60, 0x86, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, +- 0x07, 0x00, 0x90, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x00, 0x64, 0xA1, 0xDB, 0x04, 0x00, +- 0x10, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x8C, 0xF3, 0x58, 0xFB, 0x84, 0xF1, 0xBA, 0xFE, +- 0x01, 0xA8, 0x59, 0xF9, 0x04, 0x02, 0x02, 0x64, 0x8C, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x64, 0x47, +- 0xDC, 0xF3, 0x10, 0xB0, 0x04, 0xA8, 0x33, 0x02, 0x32, 0x02, 0x62, 0xF5, 0xEB, 0xF1, 0x2F, 0xF8, +- 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0x81, 0xF1, 0x2C, 0xF8, 0x32, 0xF8, 0x82, 0xF1, +- 0x2D, 0xF8, 0x33, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, 0x10, 0x60, 0x48, 0x64, 0x2A, 0xFA, +- 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x22, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, +- 0xE0, 0x62, 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, 0xDD, 0x60, 0xEA, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x23, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x10, 0x67, 0x84, 0xFB, 0x8C, 0xF3, +- 0xFF, 0xFF, 0x00, 0xA8, 0xFF, 0xFF, 0x0B, 0x03, 0x0F, 0x60, 0xE0, 0x62, 0x80, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0xDD, 0x60, 0xEF, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, +- 0xDE, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x1B, 0x60, 0xC6, 0x65, 0x1F, 0x60, 0x80, 0x64, 0xA0, 0xD3, +- 0x05, 0x7C, 0x08, 0xB0, 0xA5, 0xD3, 0x05, 0x02, 0x00, 0xB8, 0xFF, 0xFF, 0x02, 0x03, 0x15, 0x7C, +- 0x0B, 0x00, 0xDC, 0xF3, 0x12, 0x60, 0x26, 0x63, 0x03, 0xA8, 0x7F, 0xF3, 0x05, 0x02, 0xE0, 0x85, +- 0x47, 0xD3, 0xFF, 0xFF, 0x07, 0xBC, 0xA2, 0xDB, 0x53, 0xF9, 0x29, 0x60, 0xC6, 0x64, 0x54, 0xFB, +- 0x24, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x4E, 0xEC, 0x60, 0x58, 0x4F, 0xB9, 0x78, 0xFF, 0xFF, +- 0x0E, 0x4F, 0x0F, 0x60, 0xE0, 0x62, 0x10, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0x60, 0x34, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x59, 0xF3, 0x84, 0xFB, 0x60, 0x40, 0x10, 0x27, 0xDA, 0xFE, 0xDC, 0xF3, 0x00, 0xA8, 0x04, 0xA8, +- 0x27, 0x02, 0x26, 0x02, 0x61, 0xF5, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, +- 0x31, 0xF8, 0x81, 0xF1, 0x2C, 0xF8, 0x82, 0xF1, 0x2D, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0xA4, 0x64, +- 0x2A, 0xFA, 0x85, 0xF1, 0xC0, 0x67, 0xB0, 0x84, 0x2B, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, +- 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xC1, 0xFE, 0x20, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x26, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x9E, 0xF5, 0xFF, 0xFF, 0x07, 0x1B, 0x20, 0x40, 0x80, 0x2B, 0x5C, 0x00, 0x7F, 0x60, 0xFF, 0x65, +- 0x20, 0x44, 0x24, 0x80, 0x00, 0x64, 0x41, 0xFB, 0xF1, 0x60, 0x01, 0x64, 0x24, 0xFA, 0xDA, 0x85, +- 0x19, 0x60, 0x86, 0x63, 0x89, 0xF1, 0x43, 0x4C, 0xD3, 0x80, 0xBE, 0xD1, 0x14, 0x05, 0x65, 0x40, +- 0x80, 0x2A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x64, 0x43, 0x32, 0x61, 0x0F, 0x4E, 0x2F, 0x60, +- 0x58, 0x4F, 0x01, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x2C, 0x43, 0x04, 0xA3, 0x41, 0xF3, 0xFF, 0xFF, +- 0x32, 0xA4, 0x41, 0xFB, 0xE7, 0x01, 0x20, 0x47, 0x20, 0xB0, 0x20, 0xAF, 0x0F, 0x03, 0x40, 0x40, +- 0x0F, 0x60, 0xE0, 0x62, 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, 0xDE, 0x60, 0xA3, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x9E, 0xF1, 0x41, 0xF3, +- 0xFF, 0xFF, 0x02, 0xA4, 0xE8, 0x84, 0x64, 0x46, 0x23, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, +- 0x64, 0x64, 0xA2, 0xDB, 0x5A, 0xD9, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x64, +- 0x9E, 0xFB, 0xFA, 0xFE, 0xEB, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, +- 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x58, 0xF3, 0x8C, 0xFB, +- 0xFF, 0xFF, 0xC1, 0xFE, 0x0F, 0x60, 0xDE, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xE0, 0x62, +- 0x00, 0x60, 0x80, 0x64, 0xA2, 0xDB, 0xDD, 0x60, 0x71, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2E, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x9E, 0xF1, +- 0x00, 0x64, 0xB0, 0x86, 0x9E, 0xFB, 0x07, 0x03, 0x24, 0x60, 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, +- 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0xEB, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, +- 0xDE, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xE0, 0x62, 0x00, 0x60, 0x80, 0x64, 0xA2, 0xDB, +- 0xDD, 0x60, 0x71, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x97, 0xF3, 0x26, 0x46, +- 0x60, 0x43, 0x01, 0x2A, 0x22, 0x00, 0x0F, 0xF2, 0x2A, 0xF0, 0x60, 0x40, 0x10, 0x2A, 0x10, 0x00, +- 0x64, 0x40, 0x04, 0x27, 0x1A, 0x00, 0xFD, 0xB3, 0x64, 0x40, 0x20, 0x27, 0x02, 0xBB, 0x0F, 0x60, +- 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0C, 0x00, +- 0xFB, 0xB3, 0x64, 0x40, 0x20, 0x27, 0x04, 0xBB, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, +- 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x97, 0xFD, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, +- 0xDC, 0xF3, 0x3F, 0xF2, 0x04, 0xA8, 0x57, 0xFB, 0x02, 0x03, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0xF4, +- 0x1E, 0x63, 0x08, 0x64, 0x40, 0x48, 0xBD, 0xD2, 0xFF, 0xFF, 0x60, 0x47, 0x05, 0x36, 0x0B, 0x00, +- 0xFF, 0xB5, 0xC7, 0x83, 0x01, 0x2A, 0xF7, 0x01, 0x4F, 0xD2, 0x5B, 0xD2, 0x60, 0x40, 0x05, 0x37, +- 0x08, 0x00, 0xDF, 0x83, 0xF5, 0x01, 0xFF, 0xB5, 0x65, 0x41, 0x47, 0x8A, 0x5B, 0xD2, 0xDF, 0x83, +- 0x07, 0x00, 0x00, 0x7F, 0xDC, 0x85, 0x47, 0x8A, 0x60, 0x41, 0x5B, 0xD2, 0xDB, 0x83, 0x60, 0x47, +- 0x01, 0xB0, 0xFE, 0xB5, 0x02, 0x03, 0x02, 0x64, 0x40, 0x48, 0x85, 0xF1, 0x65, 0x44, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0xFD, 0xA1, 0xE1, 0x81, 0xE1, 0x81, 0xE1, 0x85, 0xC4, 0x81, 0xD0, 0x84, +- 0xD1, 0x80, 0x2A, 0x07, 0x29, 0x06, 0x9C, 0x84, 0xDC, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x85, +- 0x96, 0xF3, 0xC7, 0x83, 0x01, 0x26, 0x60, 0x47, 0xAB, 0x83, 0xFC, 0xA3, 0x02, 0x00, 0x03, 0x04, +- 0x00, 0xF4, 0x84, 0xA3, 0xFC, 0x01, 0x80, 0x65, 0x47, 0xD0, 0x28, 0x41, 0xA0, 0x80, 0xFE, 0xA1, +- 0x16, 0x03, 0x09, 0x02, 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x1E, 0x00, 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x15, 0x00, 0x28, 0x41, 0xFE, 0xA1, 0xFF, 0xFF, 0x09, 0x03, +- 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x08, 0x00, 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x20, 0x40, 0x20, 0x2A, 0x58, 0x00, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, +- 0xF4, 0xA3, 0x00, 0x60, 0x1D, 0x61, 0x00, 0x60, 0x80, 0x65, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, +- 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0xD4, 0x80, 0x2D, 0x03, +- 0x17, 0x03, 0xCF, 0x83, 0x61, 0x44, 0x80, 0xA0, 0x28, 0x03, 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, +- 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0x81, 0xA1, 0x20, 0x03, 0x05, 0x07, 0x7F, 0xA1, 0xCC, 0x84, +- 0xDD, 0x81, 0xE4, 0x03, 0xF7, 0x01, 0x00, 0xF4, 0x00, 0xB8, 0x04, 0x61, 0xE4, 0x03, 0xF2, 0x01, +- 0x01, 0x60, 0xFF, 0x63, 0x46, 0x48, 0x41, 0x4A, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, +- 0x64, 0x44, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, +- 0x7F, 0xA1, 0xF7, 0x04, 0x00, 0xF4, 0x03, 0x61, 0xF4, 0x01, 0x20, 0xFE, 0x00, 0xBB, 0x02, 0x60, +- 0x00, 0x63, 0x08, 0x24, 0x11, 0x00, 0xBD, 0xD3, 0x06, 0x65, 0xD4, 0x80, 0xBD, 0xD3, 0x0C, 0x02, +- 0x60, 0x40, 0x60, 0x3A, 0x09, 0x00, 0x1D, 0x3B, 0x07, 0x00, 0xBD, 0xD3, 0xFF, 0xFF, 0xFF, 0xB5, +- 0x00, 0x7E, 0x5C, 0xFB, 0x65, 0x44, 0x5B, 0xFB, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, +- 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x02, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x63, 0x97, 0xFD, 0x1A, 0x60, 0x72, 0x63, 0x00, 0x64, +- 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x50, 0x64, 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, +- 0x10, 0x60, 0x4E, 0x62, 0xE0, 0x60, 0x07, 0x64, 0xA2, 0xDB, 0xD2, 0xF1, 0x1A, 0x60, 0x76, 0x62, +- 0xA2, 0xD9, 0x1A, 0x60, 0x7E, 0x63, 0x00, 0x64, 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x54, 0x64, +- 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, 0x10, 0x60, 0x52, 0x62, 0xE0, 0x60, 0x11, 0x64, +- 0xA2, 0xDB, 0x28, 0x60, 0x04, 0x62, 0xA2, 0xD1, 0x1A, 0x60, 0x82, 0x62, 0xA2, 0xD9, 0x00, 0x60, +- 0x3A, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x64, 0xFB, 0xA9, 0xF3, +- 0x07, 0xFA, 0xBC, 0xF3, 0x19, 0xFA, 0xF8, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, +- 0x3F, 0xFA, 0x00, 0x60, 0x3A, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0x65, 0xFB, 0xA9, 0xF3, 0x07, 0xFA, 0xBC, 0xF3, 0x19, 0xFA, 0x24, 0x60, 0x80, 0x64, 0x0E, 0xFA, +- 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x10, 0x60, 0x14, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, +- 0x10, 0x60, 0x28, 0x62, 0xE0, 0x60, 0x77, 0x64, 0xA2, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x63, +- 0x97, 0xFD, 0xBA, 0xFE, 0xFE, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x84, 0xFD, 0x0F, 0x60, +- 0xEA, 0x62, 0xA2, 0xD1, 0x04, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, +- 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x28, 0x60, 0x04, 0x62, +- 0xA2, 0xD1, 0x1A, 0x60, 0x82, 0x62, 0xA2, 0xD9, 0x27, 0x60, 0xFE, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, +- 0x0A, 0x1B, 0x00, 0x64, 0x84, 0xFB, 0xBA, 0xFE, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0xBA, 0xFE, 0x97, 0xF3, 0x00, 0x63, 0x84, 0xFD, 0x10, 0xBC, +- 0x97, 0xFB, 0xFE, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, +- 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x60, 0x64, 0x63, 0x1A, 0x60, +- 0x42, 0x64, 0xA0, 0xDD, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, +- 0x01, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0xE0, 0x60, 0xC9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xA3, 0x01, 0x31, 0x40, 0x04, 0x2A, 0xE3, 0x01, 0x20, 0x40, +- 0x52, 0x23, 0x12, 0x00, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x14, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, 0x81, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xE0, 0x60, +- 0xC9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0xDB, 0x01, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x01, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x65, 0xF5, 0xBC, 0xF1, 0x19, 0xF8, 0x81, 0xF1, +- 0x2C, 0xF8, 0x32, 0xF8, 0x82, 0xF1, 0x2D, 0xF8, 0x33, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, +- 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0x11, 0x60, 0x48, 0x64, +- 0x2A, 0xFA, 0x00, 0x64, 0x2B, 0xFA, 0x23, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, +- 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, +- 0x0F, 0x60, 0xF8, 0x62, 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, 0xE1, 0x60, 0x23, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x65, 0xF5, 0x23, 0xF2, 0xFF, 0xFF, 0x01, 0x18, 0x7B, 0x01, +- 0x10, 0x67, 0x84, 0xFB, 0x03, 0x64, 0x98, 0xFB, 0xFE, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, +- 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, 0x81, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0xE1, 0x60, 0x46, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x0D, 0x00, 0x0F, 0x60, 0xF6, 0x62, +- 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0xE0, 0x60, 0x77, 0x78, 0xFF, 0xFF, 0x46, 0x60, 0x00, 0x65, 0x20, 0x41, 0x8E, 0xF3, 0xA5, 0x80, +- 0x01, 0xB0, 0x01, 0x02, 0x06, 0x00, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x2F, 0x58, +- 0xFF, 0xFF, 0x1A, 0x60, 0x42, 0x65, 0xA5, 0xD3, 0x01, 0x63, 0x8C, 0xFD, 0x27, 0x1B, 0x00, 0x60, +- 0x64, 0x64, 0xA5, 0xDB, 0x65, 0xF5, 0xBC, 0xF1, 0x19, 0xF8, 0x81, 0xF1, 0x2C, 0xF8, 0x32, 0xF8, +- 0x82, 0xF1, 0x2D, 0xF8, 0x33, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, 0xEB, 0xF1, 0x2F, 0xF8, +- 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0x11, 0x60, 0x48, 0x64, 0x2A, 0xFA, 0x00, 0x64, +- 0x2B, 0xFA, 0x23, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x06, 0x00, 0x97, 0xF3, 0x32, 0x40, +- 0x02, 0x26, 0x02, 0x00, 0x40, 0x2A, 0xDA, 0xFE, 0xC1, 0xFE, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, 0x01, 0x60, 0x82, 0x64, 0xA2, 0xDB, 0xE1, 0x60, 0xA4, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x01, 0x60, +- 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xE0, 0x60, 0x77, 0x78, +- 0xFF, 0xFF, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x06, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0xBA, 0xFE, 0xE3, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x8C, 0xFB, 0x01, 0x60, 0x00, 0x65, +- 0x20, 0x44, 0x34, 0x80, 0xBA, 0xFE, 0xC1, 0xFE, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x10, 0x60, 0x14, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, 0x01, 0x60, 0x46, 0x64, +- 0xA2, 0xDB, 0xE1, 0x60, 0xD7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, +- 0xF6, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0xE0, 0x60, 0x77, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x3C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x34, 0x01, 0x00, 0x60, 0x02, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x0C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x28, 0x60, 0x00, 0x62, 0xA2, 0xD1, +- 0x97, 0xF3, 0x00, 0x61, 0xD1, 0x80, 0xF7, 0xB4, 0xF0, 0x03, 0x97, 0xFB, 0x35, 0x00, 0x00, 0x60, +- 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0F, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x28, 0x60, 0x00, 0x62, +- 0xA2, 0xD1, 0x97, 0xF3, 0x00, 0x61, 0xD1, 0x80, 0x08, 0xBC, 0x03, 0x02, 0xE2, 0x60, 0xE8, 0x78, +- 0xFF, 0xFF, 0x97, 0xFB, 0x21, 0x00, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, +- 0xA0, 0x84, 0xA2, 0xDB, 0xE2, 0x60, 0xE8, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, +- 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xC5, 0x01, +- 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xE3, 0x60, +- 0xC8, 0x78, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x02, 0x63, 0x97, 0xF3, 0x8C, 0xFD, 0x01, 0xBC, +- 0xC1, 0xFE, 0x97, 0xFB, 0xD2, 0xF1, 0x1A, 0x60, 0x76, 0x62, 0xA2, 0xD9, 0x0F, 0x60, 0xF6, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x14, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, +- 0x01, 0x60, 0x34, 0x64, 0xA2, 0xDB, 0xE2, 0x60, 0x62, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x24, 0x60, +- 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, +- 0x9C, 0x84, 0x0E, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, +- 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xE0, 0x60, 0x77, 0x78, 0xFF, 0xFF, +- 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x17, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x97, 0xF3, +- 0xFF, 0xFF, 0x60, 0x40, 0x04, 0x2A, 0x01, 0x00, 0xD2, 0x01, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, +- 0x72, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x97, 0xF3, 0xFF, 0xFF, +- 0x60, 0x40, 0x08, 0x2A, 0x4D, 0x00, 0x54, 0x00, 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, +- 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x08, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x97, 0xF3, 0xFF, 0xFF, +- 0x08, 0xBC, 0x97, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xAB, 0x01, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x0C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, 0xA2, 0xDB, +- 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x2B, 0x00, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, +- 0x9C, 0x84, 0x0C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, +- 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x13, 0x00, 0x0F, 0x60, 0xF6, 0x62, +- 0xA2, 0xD1, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x08, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0x97, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x2A, 0x04, 0x00, 0x0A, 0x00, 0x2F, 0x58, 0xFF, 0xFF, +- 0x00, 0x00, 0x97, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0x97, 0xFB, 0xE1, 0x60, 0x2A, 0x78, 0xFF, 0xFF, +- 0x27, 0x60, 0xFE, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x03, 0x02, 0xE3, 0x60, +- 0xD1, 0x78, 0xFF, 0xFF, 0x97, 0xF3, 0x01, 0x63, 0x8C, 0xFD, 0x21, 0xBC, 0x97, 0xFB, 0x64, 0xF5, +- 0x81, 0xF1, 0x2C, 0xF8, 0x82, 0xF1, 0x2D, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x85, 0xF1, 0xC0, 0x67, +- 0xB0, 0x84, 0x2B, 0xFA, 0xBC, 0xF1, 0x19, 0xF8, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, +- 0xED, 0xF1, 0x31, 0xF8, 0x10, 0x60, 0xA4, 0x64, 0x2A, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, +- 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xC1, 0xFE, 0x1A, 0x60, 0x76, 0x62, 0x00, 0x60, 0x50, 0x64, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, +- 0x1A, 0x60, 0x72, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, +- 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x14, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, +- 0xF8, 0x62, 0x01, 0x60, 0x2C, 0x64, 0xA2, 0xDB, 0xE3, 0x60, 0x3A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, +- 0x9C, 0x84, 0x0E, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, +- 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xE0, 0x60, 0x77, 0x78, 0xFF, 0xFF, +- 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, +- 0xA0, 0x84, 0xA2, 0xDB, 0x8D, 0x01, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x08, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x97, 0xF3, 0xFF, 0xFF, 0x02, 0xB0, +- 0xFF, 0xFF, 0x4E, 0x03, 0x7D, 0x01, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, +- 0xA0, 0x84, 0xA2, 0xDB, 0x45, 0x00, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x16, 0x03, +- 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, 0xA2, 0xDB, 0x03, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x28, 0x60, 0x00, 0x62, 0xA2, 0xD3, 0x97, 0xF3, 0x00, 0xA8, +- 0xF7, 0xB4, 0x2E, 0x03, 0x97, 0xFB, 0xE2, 0x60, 0x3C, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x17, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, +- 0x72, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x28, 0x60, 0x00, 0x62, +- 0xA2, 0xD3, 0x97, 0xF3, 0x00, 0xA8, 0x08, 0xBC, 0x01, 0x02, 0x42, 0x01, 0x97, 0xFB, 0xE2, 0x60, +- 0x3C, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, +- 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x02, 0x00, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x00, +- 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x72, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x97, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0x97, 0xFB, 0xE1, 0x60, 0x2A, 0x78, 0xFF, 0xFF, +- 0x97, 0xF3, 0x01, 0x63, 0x8C, 0xFD, 0x01, 0xBC, 0x97, 0xFB, 0x00, 0x64, 0x84, 0xFB, 0xC1, 0xFE, +- 0x29, 0x00, 0x97, 0xF3, 0x01, 0x63, 0x8C, 0xFD, 0x01, 0xBC, 0x97, 0xFB, 0x00, 0x64, 0x84, 0xFB, +- 0x64, 0xF5, 0x81, 0xF1, 0x2C, 0xF8, 0x82, 0xF1, 0x2D, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x85, 0xF1, +- 0xC0, 0x67, 0xB0, 0x84, 0x2B, 0xFA, 0xBC, 0xF1, 0x19, 0xF8, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, +- 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0x00, 0x60, 0xA4, 0x64, 0x2A, 0xFA, 0x24, 0x60, 0x74, 0x62, +- 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xC1, 0xFE, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x7E, 0x64, 0xA2, 0xDB, 0x02, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, +- 0x14, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x0F, 0x60, 0xF8, 0x62, 0x03, 0x60, 0x0E, 0x64, 0xA2, 0xDB, +- 0xE4, 0x60, 0x16, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, +- 0xA2, 0xD1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0E, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x7E, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0xE0, 0x60, 0x77, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x0A, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xC6, 0x01, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x15, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x10, 0x60, 0x14, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x8B, 0x01, 0x00, 0x60, 0x12, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xAC, 0x01, 0x0F, 0x60, 0xF6, 0x62, +- 0xA2, 0xD1, 0x02, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xAD, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0x10, 0x67, 0x84, 0xFB, 0x0F, 0x60, 0xF6, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x14, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x65, 0xF5, 0xBC, 0xF1, 0x19, 0xF8, 0x81, 0xF1, 0x2C, 0xF8, 0x32, 0xF8, +- 0x82, 0xF1, 0x2D, 0xF8, 0x33, 0xF8, 0x83, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, 0xEB, 0xF1, 0x2F, 0xF8, +- 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0x11, 0x60, 0x48, 0x64, 0x2A, 0xFA, 0x00, 0x64, +- 0x2B, 0xFA, 0x23, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x97, 0xF3, 0xC1, 0xFE, 0xFE, 0xB4, +- 0x97, 0xFB, 0x0F, 0x60, 0xF8, 0x62, 0x00, 0x60, 0x03, 0x64, 0xA2, 0xDB, 0xE4, 0x60, 0x94, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, +- 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x29, 0x01, 0x65, 0xF5, +- 0x23, 0xF2, 0x98, 0xF3, 0x04, 0x18, 0xCC, 0x84, 0x98, 0xFB, 0x01, 0x03, 0x21, 0x01, 0xE1, 0x60, +- 0x2A, 0x78, 0xFF, 0xFF, 0x27, 0x60, 0xFE, 0x62, 0xA2, 0xD3, 0x84, 0xF1, 0x02, 0xA8, 0x2A, 0xF2, +- 0x03, 0x02, 0xB0, 0x84, 0x2A, 0xFA, 0x08, 0x00, 0x0F, 0x60, 0xF6, 0x62, 0xA2, 0xD1, 0x00, 0x60, +- 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x22, 0x64, +- 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, +- 0x24, 0x60, 0x34, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0xDB, 0x02, 0xBF, 0x60, +- 0xE7, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xFC, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1A, 0x60, 0xAE, 0x63, 0x00, 0x64, 0xA3, 0xDB, +- 0x06, 0xA3, 0x10, 0x60, 0x5C, 0x64, 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, 0x10, 0x60, +- 0x5A, 0x62, 0xE4, 0x60, 0xD2, 0x64, 0xA2, 0xDB, 0x1F, 0x60, 0x5C, 0x62, 0xA2, 0xD1, 0x1A, 0x60, +- 0xB2, 0x62, 0xA2, 0xD9, 0x10, 0x60, 0x2A, 0x62, 0xE4, 0x60, 0xF9, 0x64, 0xA2, 0xDB, 0x2F, 0x58, +- 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x1F, 0x60, 0x80, 0x65, 0xA5, 0xD3, 0xFF, 0xFF, 0x02, 0xBC, +- 0xF3, 0xB4, 0x01, 0xB0, 0xA5, 0xDB, 0x0C, 0x02, 0x12, 0x60, 0x26, 0x61, 0x00, 0x64, 0x1A, 0x63, +- 0x59, 0xDB, 0xFE, 0x1F, 0x1F, 0x60, 0x5C, 0x61, 0x0A, 0x64, 0x1A, 0x63, 0x59, 0xDB, 0xFE, 0x1F, +- 0x7F, 0xF3, 0x7E, 0xFB, 0x01, 0x64, 0x7F, 0xFB, 0x01, 0x61, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, +- 0xE1, 0x81, 0xFB, 0x01, 0xBA, 0xF3, 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x69, 0x03, 0x0F, 0x60, +- 0xFC, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xFE, 0x62, 0x40, 0x60, +- 0x00, 0x64, 0xA2, 0xDB, 0xE5, 0x60, 0x1F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x7F, 0xF1, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, +- 0x0F, 0x60, 0xFE, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xE5, 0x60, 0x43, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, +- 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xFC, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x0F, 0x60, 0xFE, 0x62, 0x00, 0x60, 0x1A, 0x64, 0xA2, 0xDB, 0xE5, 0x60, 0x64, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0xAE, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xFC, 0x62, 0xA2, 0xD1, 0x00, 0x60, +- 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, +- 0x1A, 0x60, 0xAE, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x26, 0x00, +- 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0B, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, +- 0xAA, 0x62, 0x1A, 0x60, 0xAE, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x12, 0x60, 0x26, 0x65, 0x7F, 0xF3, 0xFF, 0xFF, 0x04, 0xA4, 0xF2, 0xA0, 0xFF, 0xFF, 0x01, 0x06, +- 0xF1, 0xA4, 0x01, 0x36, 0x0B, 0x00, 0x00, 0x36, 0x04, 0xA4, 0x60, 0x41, 0xE0, 0x84, 0xC4, 0x84, +- 0xA0, 0xD3, 0xFF, 0xFF, 0x00, 0xB8, 0x61, 0x44, 0xEF, 0x02, 0x75, 0x01, 0x1F, 0x60, 0x80, 0x65, +- 0xA5, 0xD3, 0x7E, 0xF1, 0xFC, 0xB4, 0xA5, 0xDB, 0x7F, 0xF9, 0x0F, 0x60, 0xFC, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xFE, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, +- 0xE5, 0x60, 0xA5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7F, 0xF1, 0x24, 0x60, +- 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xFE, 0x62, +- 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xE5, 0x60, 0xC9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xFC, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x0F, 0x60, +- 0xD0, 0x62, 0xA2, 0xD1, 0x10, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0xE6, 0x60, 0xE9, 0x78, 0xFF, 0xFF, 0xE6, 0x60, 0xED, 0x78, 0xFF, 0xFF, 0x1F, 0x60, +- 0x80, 0x63, 0xA3, 0xD3, 0x26, 0x46, 0x02, 0xB0, 0x3F, 0xF2, 0xF6, 0x03, 0x02, 0x60, 0x00, 0x63, +- 0x01, 0x60, 0x00, 0x65, 0xD4, 0x80, 0x00, 0xF4, 0x02, 0x24, 0x65, 0x44, 0x12, 0x65, 0x60, 0x41, +- 0xA5, 0xD0, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x64, 0x44, 0x00, 0x7F, +- 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0xF0, 0x02, +- 0x02, 0x60, 0x14, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x01, 0xB4, 0xFF, 0xFF, 0x37, 0x02, 0x29, 0x60, +- 0xA4, 0x64, 0xA0, 0xD1, 0x1F, 0x60, 0x0E, 0x63, 0x31, 0x18, 0x64, 0x41, 0x44, 0x4B, 0x29, 0x60, +- 0xA6, 0x65, 0xA5, 0xD1, 0xDA, 0x85, 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, +- 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0xF4, 0x02, 0x02, 0x60, 0x1A, 0x61, 0xA1, 0xD3, +- 0x2B, 0x45, 0x60, 0x40, 0x00, 0x36, 0x1A, 0x00, 0x01, 0x36, 0x18, 0x00, 0xD4, 0x80, 0x65, 0x43, +- 0xB0, 0x02, 0x1F, 0x60, 0x0C, 0x64, 0xE3, 0x83, 0xFE, 0xA3, 0x59, 0xD1, 0x58, 0xD3, 0x40, 0x4B, +- 0xD0, 0x80, 0x2B, 0x44, 0x02, 0x02, 0xF9, 0x1F, 0x09, 0x00, 0x02, 0x60, 0x1A, 0x61, 0x65, 0x43, +- 0xE3, 0x83, 0xFE, 0xA3, 0x59, 0xD3, 0xFF, 0xFF, 0x9C, 0x1B, 0xFC, 0x1F, 0x26, 0x46, 0x3F, 0xF0, +- 0x01, 0x60, 0x00, 0x64, 0xD0, 0x80, 0x64, 0x41, 0x01, 0x05, 0x60, 0x41, 0xF4, 0xA1, 0x02, 0x60, +- 0x18, 0x63, 0xBD, 0xD3, 0xBD, 0xD1, 0xFD, 0xA0, 0xF9, 0xA0, 0x08, 0x03, 0x35, 0x03, 0xFE, 0xA1, +- 0x64, 0x42, 0xE2, 0x85, 0xD1, 0x81, 0xC7, 0x83, 0x84, 0x06, 0xF3, 0x01, 0x12, 0x60, 0x26, 0x65, +- 0xBD, 0xD3, 0xFD, 0xA1, 0xE0, 0x84, 0xC4, 0x85, 0x05, 0x64, 0xA5, 0xDB, 0x1F, 0x60, 0x80, 0x65, +- 0xA5, 0xD3, 0x41, 0x48, 0x04, 0xBC, 0xA5, 0xDB, 0x12, 0x60, 0x28, 0x65, 0x12, 0x60, 0x44, 0x61, +- 0x49, 0xD3, 0xD6, 0x80, 0x00, 0xB8, 0x0E, 0x03, 0xFB, 0x03, 0x62, 0x45, 0x12, 0x60, 0x26, 0x61, +- 0x59, 0xD3, 0xD6, 0x80, 0x00, 0xB8, 0x06, 0x03, 0xFB, 0x03, 0x05, 0x64, 0xA2, 0xDB, 0xD6, 0x80, +- 0x02, 0xA2, 0xFC, 0x02, 0x0F, 0x60, 0xFC, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x28, 0x41, 0xC5, 0x01, 0x63, 0x45, 0x04, 0x60, 0x00, 0x63, 0xD7, 0x83, +- 0xEB, 0x83, 0xD3, 0x80, 0x65, 0x43, 0x01, 0x05, 0x54, 0x00, 0xFE, 0xA3, 0x43, 0x4B, 0xA3, 0xD3, +- 0x63, 0x41, 0x60, 0x43, 0x1B, 0x60, 0xC6, 0x64, 0xA0, 0xDD, 0xE3, 0x83, 0xFE, 0xA3, 0x59, 0xD1, +- 0x58, 0xD9, 0xFD, 0x1F, 0x00, 0x63, 0x58, 0xDD, 0x2B, 0x43, 0xBD, 0xD1, 0x1F, 0x60, 0x78, 0x64, +- 0x64, 0x41, 0xBD, 0xD1, 0x58, 0xD9, 0xBD, 0xD1, 0xFC, 0xA1, 0x41, 0x4B, 0x58, 0xD9, 0xBD, 0xD1, +- 0xA0, 0xD9, 0x12, 0x60, 0x26, 0x61, 0x12, 0x60, 0x42, 0x65, 0x00, 0x64, 0xD5, 0x80, 0x59, 0xDB, +- 0xFD, 0x02, 0x12, 0x60, 0x24, 0x65, 0xBD, 0xD3, 0xA3, 0xD1, 0xE0, 0x84, 0xC4, 0x82, 0x12, 0x60, +- 0x44, 0x65, 0x05, 0x64, 0x64, 0x41, 0x5A, 0xDB, 0xD6, 0x80, 0xCD, 0x81, 0x22, 0x03, 0xFB, 0x02, +- 0x1F, 0x60, 0x5A, 0x61, 0x4B, 0xD1, 0x04, 0xA3, 0xBD, 0xD3, 0xFF, 0xFF, 0xF6, 0xA0, 0xC1, 0x82, +- 0x05, 0x05, 0x64, 0x41, 0x5A, 0xDB, 0xCD, 0x81, 0xFF, 0xFF, 0xFC, 0x02, 0x2B, 0x41, 0xFD, 0xA1, +- 0x41, 0x4B, 0xDF, 0x07, 0x0F, 0x60, 0xFC, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x1F, 0x60, 0x80, 0x65, 0xA5, 0xD3, 0xFF, 0xFF, 0x08, 0xBC, 0xA5, 0xDB, +- 0xFF, 0xFF, 0x20, 0xFE, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x20, 0xFE, 0x9A, 0xFF, 0x5C, 0x61, +- 0x3F, 0xF2, 0xFF, 0xFF, 0x83, 0xA0, 0xFF, 0xFF, 0x04, 0x28, 0x39, 0x00, 0xF4, 0xA4, 0x60, 0x43, +- 0x00, 0xF4, 0x1E, 0x62, 0x60, 0xFE, 0xA2, 0xD2, 0xFF, 0xFF, 0x60, 0x40, 0x85, 0x36, 0x10, 0x00, +- 0xDE, 0x82, 0xA2, 0xD2, 0xFF, 0xFF, 0x20, 0xFE, 0xFF, 0xB4, 0x02, 0xA4, 0x53, 0x93, 0x51, 0x91, +- 0x05, 0x0E, 0xFF, 0xA4, 0x42, 0x92, 0x63, 0x40, 0x61, 0x40, 0xEC, 0x1C, 0x98, 0xFF, 0xD9, 0x01, +- 0x20, 0xFE, 0x05, 0x64, 0x00, 0x7C, 0x42, 0x92, 0x60, 0xFE, 0xDE, 0x82, 0xA2, 0xD2, 0xDE, 0x82, +- 0xA2, 0xD0, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0x60, 0x43, 0x60, 0xFE, 0xDE, 0x82, 0xA2, 0xD2, +- 0xDE, 0x82, 0xA2, 0xD0, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0x98, 0xFF, 0x01, 0xA3, 0x01, 0xA4, +- 0x2D, 0x60, 0x5A, 0x62, 0xA2, 0xDD, 0x2D, 0x60, 0x5E, 0x62, 0xA2, 0xDB, 0xBA, 0x01, 0x98, 0xFF, +- 0xB8, 0x01, 0x00, 0x60, 0xA0, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0x5D, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x80, 0x64, 0x2A, 0xFA, 0xCC, 0xF1, 0x19, 0xF8, 0x00, 0x64, +- 0x3E, 0xFA, 0x00, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0xA9, 0xF1, 0x07, 0xF8, 0x67, 0x44, 0x2C, 0xFA, +- 0x2D, 0xFA, 0x2E, 0xFA, 0x10, 0x60, 0x1C, 0x62, 0xE8, 0x60, 0xDF, 0x64, 0xA2, 0xDB, 0x2F, 0x58, +- 0xFF, 0xFF, 0x5D, 0xF5, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, +- 0x81, 0xF1, 0x32, 0xF8, 0x82, 0xF1, 0x33, 0xF8, 0x83, 0xF1, 0x34, 0xF8, 0x28, 0x60, 0x2C, 0x62, +- 0xA2, 0xD1, 0x02, 0x64, 0x64, 0x40, 0xFE, 0x26, 0x10, 0xBC, 0x32, 0x40, 0x08, 0x26, 0x10, 0xBC, +- 0x2F, 0x60, 0x44, 0x62, 0xA2, 0xDB, 0x28, 0x60, 0x2A, 0x62, 0xA2, 0xD1, 0x2D, 0x60, 0x7A, 0x64, +- 0x02, 0x18, 0x27, 0x60, 0xDA, 0x64, 0x2E, 0x60, 0xAE, 0x62, 0xA2, 0xDB, 0x2E, 0x60, 0xCA, 0x62, +- 0xA2, 0xDB, 0x2D, 0x60, 0xA6, 0x61, 0x28, 0x60, 0xCC, 0x62, 0xA2, 0xD3, 0x2E, 0x60, 0x96, 0x65, +- 0xFE, 0xA4, 0xE0, 0x84, 0x02, 0x05, 0x67, 0x44, 0x99, 0x00, 0xE0, 0x84, 0xC4, 0x85, 0x2D, 0x60, +- 0xCC, 0x62, 0xA2, 0xD3, 0xA5, 0xD1, 0xDA, 0x85, 0x2D, 0x60, 0xC4, 0x62, 0xA0, 0x83, 0xA2, 0xDD, +- 0xA5, 0xD1, 0x2D, 0x60, 0xC2, 0x62, 0xA0, 0x83, 0xA2, 0xDD, 0x2D, 0x60, 0xA0, 0x61, 0xDD, 0x60, +- 0x06, 0x64, 0xA1, 0xDB, 0x06, 0xA1, 0x2D, 0x60, 0xCA, 0x62, 0xA2, 0xD3, 0x2D, 0x60, 0xC2, 0x62, +- 0x60, 0x40, 0xFD, 0xA0, 0xA2, 0xD3, 0x74, 0x03, 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x02, 0x2A, +- 0x03, 0x00, 0x01, 0x60, 0xF2, 0x63, 0x0E, 0x00, 0x04, 0x2A, 0x03, 0x00, 0x02, 0x60, 0xF2, 0x63, +- 0x09, 0x00, 0x10, 0x2A, 0x03, 0x00, 0x04, 0x60, 0xF2, 0x63, 0x04, 0x00, 0x20, 0x2A, 0x04, 0x00, +- 0x05, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x2D, 0x60, 0xCA, 0x62, 0xA2, 0xD3, 0x2D, 0x60, +- 0xC4, 0x62, 0xFE, 0xA0, 0xA2, 0xD3, 0x54, 0x03, 0x00, 0x60, 0x00, 0x63, 0x59, 0xDD, 0x61, 0x45, +- 0x60, 0x40, 0x01, 0x2A, 0x04, 0x00, 0x00, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, +- 0x02, 0x2A, 0x04, 0x00, 0x01, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x04, 0x2A, +- 0x04, 0x00, 0x02, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x10, 0x2A, 0x04, 0x00, +- 0x04, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, +- 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0xD5, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xA5, 0xDD, 0x2D, 0x60, +- 0xCA, 0x62, 0xA2, 0xD3, 0x2D, 0x60, 0xC6, 0x62, 0xFF, 0xA0, 0xA2, 0xD3, 0x21, 0x03, 0x00, 0x60, +- 0x00, 0x63, 0x59, 0xDD, 0x61, 0x45, 0x60, 0x40, 0x01, 0x2A, 0x04, 0x00, 0x00, 0x60, 0xF2, 0x63, +- 0x59, 0xD9, 0x59, 0xDD, 0x60, 0x40, 0x02, 0x2A, 0x04, 0x00, 0x01, 0x60, 0xF2, 0x63, 0x59, 0xD9, +- 0x59, 0xDD, 0x60, 0x40, 0x04, 0x2A, 0x04, 0x00, 0x02, 0x60, 0xF2, 0x63, 0x59, 0xD9, 0x59, 0xDD, +- 0xD5, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xA5, 0xDD, 0x2D, 0x60, 0xC8, 0x62, 0xA2, 0xD1, 0x59, 0xD9, +- 0x2D, 0x60, 0xA0, 0x65, 0xD5, 0x84, 0xDD, 0x7F, 0xA5, 0xDB, 0x65, 0x44, 0x2E, 0x60, 0xB8, 0x62, +- 0xA2, 0xDB, 0x2E, 0x60, 0xD4, 0x62, 0xA2, 0xDB, 0x0F, 0x60, 0xD4, 0x62, 0x00, 0x60, 0x04, 0x64, +- 0xA2, 0xDB, 0xE8, 0x60, 0x2F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, +- 0xD2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x7F, 0xF1, 0x2F, 0x60, 0x0E, 0x62, 0xA2, 0xD9, 0x2E, 0x60, +- 0xB6, 0x65, 0xE9, 0x60, 0x58, 0x4D, 0x32, 0x78, 0xFF, 0xFF, 0x5D, 0xF5, 0x00, 0xF4, 0x80, 0xF1, +- 0x06, 0xF8, 0x2F, 0x60, 0x44, 0x62, 0xA2, 0xD3, 0x07, 0xFA, 0x2E, 0x60, 0xAE, 0x64, 0x40, 0x48, +- 0x10, 0x61, 0x00, 0x60, 0x00, 0x64, 0xE8, 0x60, 0x58, 0x4D, 0xE8, 0x78, 0xFF, 0xFF, 0x5D, 0xF5, +- 0x3F, 0xFC, 0xDB, 0xFE, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, +- 0x5A, 0xDB, 0x04, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0xDC, 0xF3, 0x9B, 0xFE, 0xFD, 0xA0, 0x25, 0x04, 0x24, 0x02, 0x04, 0x64, 0x03, 0xFA, 0x00, 0xF4, +- 0x09, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x3A, 0x1C, 0x00, 0x60, 0x43, 0x00, 0x36, 0x1C, 0x00, +- 0xE0, 0xA0, 0xDA, 0x85, 0x16, 0x07, 0x2D, 0x60, 0x7A, 0x61, 0xA1, 0xD1, 0xFF, 0xFF, 0xD3, 0x80, +- 0xCB, 0x83, 0x0F, 0x02, 0x07, 0x0E, 0x59, 0xD3, 0xA5, 0xD0, 0xDA, 0x85, 0xD0, 0x80, 0xFF, 0xFF, +- 0x08, 0x02, 0xF9, 0x1F, 0x13, 0x1E, 0xA5, 0xD0, 0x59, 0xD3, 0xFF, 0xFF, 0x90, 0x80, 0xFF, 0x22, +- 0x0D, 0x00, 0xE8, 0x60, 0xDD, 0x78, 0xFF, 0xFF, 0x28, 0x60, 0x2A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, +- 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x27, 0x60, 0xDA, 0x64, 0x02, 0x00, 0x2D, 0x60, 0x7A, 0x64, +- 0x2E, 0x60, 0xCA, 0x62, 0xA2, 0xDB, 0x26, 0x46, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, +- 0x31, 0xF2, 0x2E, 0xFA, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, +- 0x81, 0xF1, 0x32, 0xF8, 0x82, 0xF1, 0x33, 0xF8, 0x83, 0xF1, 0x34, 0xF8, 0x50, 0x63, 0x2A, 0xFC, +- 0xCC, 0xF3, 0x19, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0xA9, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x80, 0xF1, +- 0x06, 0xF8, 0x2F, 0x60, 0x44, 0x62, 0xA2, 0xD3, 0x07, 0xFA, 0x2E, 0x60, 0xD2, 0x65, 0xE9, 0x60, +- 0x58, 0x4D, 0x32, 0x78, 0xFF, 0xFF, 0x2E, 0x60, 0xCA, 0x64, 0x40, 0x48, 0x10, 0x61, 0x00, 0x60, +- 0x00, 0x64, 0xE8, 0x60, 0x58, 0x4D, 0xE8, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xFC, 0x24, 0x60, +- 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, +- 0xD2, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x00, 0x64, 0x94, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, +- 0x2F, 0x60, 0x46, 0x62, 0xA2, 0xDB, 0xCD, 0x81, 0x28, 0xD3, 0x5A, 0x88, 0xDC, 0x83, 0x39, 0x18, +- 0xFB, 0x03, 0x61, 0x40, 0x7F, 0x3A, 0x07, 0x00, 0x2F, 0x60, 0x46, 0x62, 0xA2, 0xD3, 0x03, 0x61, +- 0x7C, 0xA4, 0xA2, 0xDB, 0x00, 0xF4, 0x60, 0xFE, 0xA3, 0xD1, 0xDD, 0x81, 0xA1, 0xD8, 0x61, 0x40, +- 0x7F, 0x3A, 0x09, 0x00, 0x20, 0xFE, 0x2F, 0x60, 0x46, 0x62, 0xA2, 0xD3, 0x03, 0x61, 0x7C, 0xA4, +- 0xA2, 0xDB, 0x00, 0xF4, 0x60, 0xFE, 0xCF, 0x83, 0xA3, 0xD3, 0xDD, 0x81, 0xA1, 0xDA, 0xFF, 0xB4, +- 0x00, 0x7F, 0x15, 0x03, 0xDB, 0x83, 0x61, 0x40, 0x7F, 0x3A, 0x0B, 0x00, 0x20, 0xFE, 0x60, 0x45, +- 0x2F, 0x60, 0x46, 0x62, 0xA2, 0xD3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x65, 0x44, 0x00, 0xF4, +- 0x60, 0xFE, 0xA3, 0xD1, 0xDF, 0x83, 0xDD, 0x81, 0xCC, 0x84, 0xA1, 0xD8, 0xEC, 0x02, 0x20, 0xFE, +- 0xC3, 0x01, 0x2F, 0x60, 0x46, 0x62, 0xA2, 0xD1, 0xFD, 0xA1, 0xFF, 0xB1, 0xC1, 0x83, 0xA2, 0xDD, +- 0x2D, 0x58, 0xFF, 0xFF, 0x67, 0x5C, 0x1B, 0x60, 0xC6, 0x61, 0xA1, 0xD3, 0xA5, 0xD9, 0x12, 0x18, +- 0x60, 0x43, 0x2F, 0x60, 0x14, 0x64, 0xA5, 0xDB, 0x60, 0xFE, 0xA0, 0xDD, 0xFF, 0xFF, 0x20, 0xFE, +- 0xDC, 0x84, 0xCF, 0x83, 0xE3, 0x83, 0x59, 0xD1, 0xDC, 0x84, 0x60, 0xFE, 0xA0, 0xD9, 0xFF, 0xFF, +- 0x20, 0xFE, 0xF9, 0x1F, 0x2D, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, 0x29, 0x00, +- 0x45, 0x48, 0x00, 0x60, 0x10, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x21, 0x03, +- 0xF2, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x00, 0x60, 0x48, 0x61, 0x28, 0x44, 0x59, 0xDA, 0x03, 0x64, +- 0x38, 0x43, 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, 0x39, 0x44, 0x59, 0xDA, 0x28, 0x60, +- 0x2E, 0x64, 0xA0, 0xD3, 0x59, 0xDA, 0x07, 0x64, 0x23, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, +- 0x64, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, 0x1C, 0x00, 0x45, 0x48, +- 0x00, 0x60, 0x06, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x14, 0x03, 0x02, 0x64, +- 0x23, 0xFA, 0xF2, 0x60, 0x00, 0x64, 0x5A, 0xDA, 0x28, 0x44, 0x5A, 0xDA, 0xFF, 0xFF, 0x24, 0x60, +- 0x74, 0x62, 0x24, 0x60, 0x64, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x32, 0x40, 0x40, 0x26, +- 0x3E, 0x00, 0x9D, 0xF3, 0x67, 0x43, 0xDC, 0x84, 0xCC, 0x84, 0x39, 0x03, 0x60, 0x46, 0x0A, 0x02, +- 0x9D, 0xFD, 0x00, 0x60, 0x46, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0x9D, 0xFB, 0x2E, 0x03, 0x46, 0x4B, 0x27, 0x60, 0x72, 0x61, 0x18, 0x64, 0x23, 0xFA, 0xF1, 0x60, +- 0x00, 0x64, 0x24, 0xFA, 0x4A, 0x65, 0xA2, 0xFF, 0x2C, 0x63, 0x00, 0x64, 0x59, 0xD1, 0xA2, 0xDB, +- 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF7, 0x1F, 0x12, 0x63, +- 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, +- 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x64, 0x64, 0xA2, 0xDB, 0x2B, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0xA6, 0xFE, 0x00, 0x64, 0x9D, 0xFB, 0xA3, 0xFF, +- 0xBF, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0xA6, 0xFE, 0xB8, 0x05, 0xA7, 0xFE, 0x12, 0x05, 0xA5, 0xFE, +- 0x03, 0x04, 0xEA, 0x60, 0xC5, 0x78, 0xFF, 0xFF, 0xA4, 0xFE, 0xF2, 0x04, 0x0F, 0x60, 0xDE, 0x62, +- 0xA2, 0xD1, 0x00, 0x60, 0x80, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xBF, 0x60, 0xE7, 0x78, +- 0xFF, 0xFF, 0x36, 0x45, 0x20, 0x60, 0x08, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xF3, +- 0xFF, 0xFF, 0x01, 0xB0, 0x00, 0x64, 0x41, 0x03, 0x9F, 0xFB, 0x31, 0x44, 0xE8, 0xB4, 0x40, 0x51, +- 0x6A, 0x44, 0xFF, 0xFF, 0x80, 0x26, 0xFC, 0x01, 0x61, 0xFF, 0x62, 0xFF, 0x10, 0x60, 0x1A, 0x62, +- 0xA2, 0xD1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x34, 0x60, 0x58, 0x4E, +- 0x64, 0x78, 0xFF, 0xFF, 0x1E, 0x60, 0xBC, 0x62, 0x1E, 0x60, 0xBE, 0x64, 0xA2, 0xDB, 0x00, 0x64, +- 0x4A, 0xDB, 0x01, 0x60, 0xFE, 0x63, 0x1C, 0x60, 0xB8, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, +- 0x1C, 0x63, 0x10, 0x60, 0x5C, 0x64, 0x58, 0xD1, 0xFF, 0xFF, 0x08, 0x1B, 0xFC, 0x1F, 0x00, 0x60, +- 0x62, 0x63, 0x1B, 0x60, 0xC4, 0x64, 0x00, 0x7C, 0x58, 0xD9, 0xFE, 0x1F, 0x1C, 0x60, 0xB4, 0x63, +- 0xA3, 0xD3, 0xFF, 0xFF, 0x04, 0xB0, 0xFF, 0xFF, 0x05, 0x03, 0x02, 0x65, 0xE9, 0x60, 0x58, 0x4E, +- 0x7B, 0x78, 0xFF, 0xFF, 0xBF, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0xEA, 0x60, 0xC5, 0x78, 0xFF, 0xFF, +- 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x74, 0x00, 0x28, 0x60, 0x50, 0x63, 0xBD, 0xD3, 0xBD, 0xD1, 0xBD, 0xD1, 0xB0, 0x84, 0xB0, 0x84, +- 0xFF, 0xFF, 0x07, 0x02, 0x8C, 0xFB, 0x31, 0x44, 0xFE, 0xB4, 0x40, 0x51, 0x0D, 0x64, 0x05, 0xFB, +- 0x64, 0x00, 0x28, 0xF3, 0x9F, 0xF1, 0x60, 0x47, 0x64, 0x41, 0x07, 0xB1, 0x07, 0xB4, 0x08, 0x24, +- 0x67, 0x4C, 0x50, 0xFB, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0xA1, 0x80, +- 0xB1, 0x83, 0x53, 0x02, 0x9F, 0xFD, 0x28, 0x60, 0x44, 0x62, 0xA2, 0xD3, 0xE5, 0xFB, 0x7F, 0xFB, +- 0x24, 0x60, 0x5E, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x46, 0x5E, 0x31, 0x44, +- 0x01, 0xBC, 0x40, 0x51, 0xD8, 0xF3, 0x01, 0x63, 0x03, 0xA8, 0x4E, 0xFD, 0x05, 0x02, 0x02, 0x63, +- 0x14, 0x60, 0x00, 0x64, 0xDB, 0xFB, 0x0C, 0x00, 0x02, 0xA8, 0x01, 0x63, 0x03, 0x03, 0x0A, 0x60, +- 0x00, 0x64, 0x03, 0x00, 0x02, 0x63, 0x14, 0x60, 0x00, 0x64, 0xDB, 0xFB, 0x00, 0x64, 0x4E, 0xFB, +- 0x4B, 0xFD, 0xA9, 0xF5, 0xFF, 0xFF, 0x0E, 0xF0, 0x0F, 0x60, 0xA2, 0x65, 0x28, 0x60, 0xD2, 0x62, +- 0xA2, 0xD3, 0xFF, 0xFF, 0xFE, 0xA0, 0x03, 0xA8, 0x11, 0x06, 0x79, 0xF1, 0x06, 0x02, 0x64, 0x44, +- 0x08, 0x2A, 0x09, 0x00, 0x06, 0x64, 0x44, 0xD3, 0x0D, 0x00, 0x64, 0x44, 0x20, 0x2A, 0x03, 0x00, +- 0x0A, 0x64, 0x44, 0xD3, 0x07, 0x00, 0x01, 0x64, 0x44, 0xD3, 0x04, 0x00, 0xE8, 0x84, 0xE0, 0x84, +- 0x44, 0xD3, 0x00, 0x00, 0x0E, 0xFA, 0xED, 0xE2, 0x0F, 0x4E, 0xC8, 0x60, 0x58, 0x4F, 0x15, 0x78, +- 0xFF, 0xFF, 0x0E, 0x4F, 0xBF, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0xD7, 0xFE, 0xBF, 0x60, 0xE7, 0x78, +- 0xFF, 0xFF, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0xF3, 0x01, 0x24, 0x60, 0x46, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, +- 0x0E, 0xF2, 0x4D, 0x03, 0x60, 0x40, 0xF0, 0x37, 0x3A, 0x00, 0xFF, 0x37, 0x2F, 0x00, 0xFD, 0x37, +- 0x27, 0x00, 0xF8, 0x37, 0x0A, 0x00, 0x60, 0x47, 0xFF, 0xB5, 0x0F, 0x60, 0xD2, 0x62, 0x46, 0xD1, +- 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x24, 0x60, 0x74, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xDA, 0x01, +- 0x06, 0xB4, 0xFD, 0x7F, 0x0E, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x4C, 0x64, 0xA2, 0xDB, +- 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF9, 0xFE, 0xCA, 0x01, +- 0x23, 0xF0, 0x60, 0x40, 0x04, 0x26, 0xEC, 0x1B, 0x02, 0x26, 0xEA, 0x18, 0xA2, 0xFF, 0x02, 0xF0, +- 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xB0, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0xB0, 0xFB, 0x24, 0x60, +- 0x74, 0x64, 0x40, 0x4B, 0x2C, 0x60, 0x58, 0x4D, 0xD8, 0x78, 0xFF, 0xFF, 0xB3, 0x01, 0xAC, 0xFE, +- 0x09, 0x05, 0xAD, 0xFE, 0x10, 0x05, 0xAE, 0xFE, 0xAD, 0x05, 0xAF, 0xFE, 0x3A, 0x05, 0xBF, 0x60, +- 0xE7, 0x78, 0xFF, 0xFF, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x20, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0xF4, 0x01, 0x10, 0x60, 0x32, 0x65, 0x0B, 0x61, 0x07, 0x00, 0xA2, 0xDD, +- 0x58, 0x4F, 0x64, 0x58, 0xFF, 0xFF, 0x00, 0xB9, 0xFF, 0xFF, 0x08, 0x03, 0x00, 0x63, 0xA5, 0xD1, +- 0x5A, 0xD3, 0xDA, 0x85, 0x00, 0xA8, 0xCD, 0x81, 0xF2, 0x02, 0xF8, 0x02, 0xE0, 0x01, 0x0F, 0x60, +- 0xCE, 0x62, 0x10, 0x60, 0x12, 0x65, 0xEB, 0x60, 0x5F, 0x63, 0x00, 0x64, 0x5A, 0xDB, 0xD6, 0x80, +- 0xFF, 0xFF, 0x04, 0x03, 0x5A, 0xDB, 0x5A, 0xDB, 0x5A, 0xDD, 0xF9, 0x01, 0x10, 0x60, 0x30, 0x65, +- 0x00, 0x64, 0x5A, 0xDB, 0xD6, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x5A, 0xDD, 0xFB, 0x01, 0x2F, 0x58, +- 0xFF, 0xFF, 0x0F, 0x60, 0xD2, 0x64, 0x40, 0x41, 0x0F, 0x60, 0xD0, 0x63, 0xA3, 0xD1, 0x00, 0x64, +- 0xD0, 0x80, 0x0B, 0x61, 0x08, 0x03, 0xBD, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0xB0, 0x84, 0xCD, 0x81, +- 0xA3, 0xDB, 0x06, 0xA3, 0xF9, 0x02, 0x10, 0x60, 0x1A, 0x63, 0xA3, 0xD1, 0x00, 0x64, 0xD0, 0x80, +- 0x0C, 0x61, 0x19, 0x03, 0xBD, 0xDB, 0x64, 0x44, 0xFE, 0xA3, 0x02, 0xA3, 0xCD, 0x81, 0xE8, 0x84, +- 0xE3, 0x03, 0x02, 0x05, 0xE1, 0x03, 0xF9, 0x01, 0x99, 0xFB, 0x9B, 0xFD, 0x61, 0x5C, 0xA3, 0xD3, +- 0x9A, 0xF9, 0x03, 0x18, 0x58, 0x4F, 0x60, 0x58, 0xFF, 0xFF, 0x9B, 0xF3, 0x9A, 0xF1, 0x60, 0x43, +- 0x99, 0xF3, 0x64, 0x41, 0xEA, 0x01, 0x21, 0x43, 0x10, 0x60, 0x14, 0x65, 0xD7, 0x80, 0xBD, 0xD1, +- 0xBD, 0xD3, 0x03, 0x02, 0xBF, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0xA0, 0x84, 0xBD, 0xD1, 0x43, 0x41, +- 0xF5, 0x03, 0xEB, 0x60, 0x64, 0x64, 0x64, 0x58, 0x40, 0x4F, 0x2A, 0xF0, 0x83, 0x60, 0xFF, 0x65, +- 0x64, 0x47, 0x03, 0x2B, 0x01, 0x00, 0x14, 0x00, 0x03, 0x26, 0x03, 0xAC, 0x60, 0x47, 0xA4, 0x84, +- 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x64, 0x41, +- 0xEB, 0xF3, 0x2F, 0xFA, 0x60, 0x43, 0xEC, 0xF3, 0x30, 0xFA, 0xED, 0xF1, 0x31, 0xF8, 0x19, 0x00, +- 0x60, 0x47, 0xA4, 0x84, 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, +- 0x2E, 0xFA, 0x36, 0xF2, 0x32, 0xFA, 0x37, 0xF2, 0x33, 0xFA, 0x38, 0xF2, 0x34, 0xFA, 0xEB, 0xF3, +- 0x2F, 0xFA, 0x36, 0xFA, 0xEC, 0xF3, 0x30, 0xFA, 0x37, 0xFA, 0xED, 0xF3, 0x31, 0xFA, 0x38, 0xFA, +- 0x64, 0x41, 0x1C, 0xF2, 0x13, 0xFA, 0x00, 0xF4, 0x0D, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, +- 0x18, 0x00, 0x81, 0x67, 0xA2, 0xDA, 0xEC, 0x60, 0x58, 0x4E, 0x5A, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x3F, 0xFC, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, +- 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xF0, 0x42, 0x64, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x04, 0x3F, 0xFA, +- 0x07, 0xF2, 0xA9, 0xF1, 0x01, 0x1B, 0x07, 0xF8, 0x1C, 0xF2, 0x13, 0xFA, 0x26, 0xF2, 0x27, 0xF0, +- 0x60, 0x47, 0x00, 0xF4, 0x1F, 0xFA, 0x64, 0x47, 0x20, 0xFA, 0x61, 0x44, 0x21, 0xFA, 0x01, 0x67, +- 0x0D, 0xFA, 0x10, 0x61, 0x28, 0x60, 0x06, 0x64, 0x1E, 0x63, 0x58, 0xD1, 0xCD, 0x81, 0xBD, 0xD8, +- 0xFC, 0x02, 0xBB, 0xF1, 0xD8, 0xF1, 0x64, 0x5E, 0x64, 0x5F, 0x44, 0x63, 0xBD, 0xDA, 0x28, 0x60, +- 0x00, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x4A, 0xD3, 0x60, 0x45, +- 0x60, 0x40, 0x01, 0x36, 0x03, 0x64, 0x02, 0x36, 0x01, 0x64, 0xB4, 0x84, 0x06, 0xA2, 0xA2, 0xD1, +- 0xBD, 0xDA, 0x64, 0x47, 0xBD, 0xDA, 0xD5, 0xF3, 0xD6, 0xF1, 0x60, 0x47, 0xBD, 0xDA, 0x64, 0x47, +- 0xE3, 0xF1, 0xBD, 0xDA, 0x64, 0x44, 0xBD, 0xDA, 0x26, 0x46, 0x00, 0x64, 0x23, 0xF0, 0x3B, 0xF0, +- 0x64, 0x40, 0x10, 0x2A, 0x06, 0x00, 0xC0, 0x67, 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, +- 0x10, 0xBC, 0x3E, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x34, 0x64, 0xA2, 0xDB, 0x26, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0x00, 0x66, 0x46, 0x46, +- 0x2F, 0x58, 0xFF, 0xFF, 0xB4, 0xF3, 0x1F, 0xFA, 0x32, 0x47, 0x07, 0xFA, 0x24, 0x7E, 0x02, 0x7F, +- 0x08, 0xFA, 0xD8, 0xF1, 0x09, 0xF8, 0x01, 0x60, 0x01, 0x64, 0x0A, 0xFA, 0x01, 0x64, 0x0B, 0xFA, +- 0x24, 0x60, 0x74, 0x62, 0x18, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x0A, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0x52, 0x63, 0x2E, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0x2A, 0x61, 0xAE, 0x60, +- 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x5E, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x67, 0x44, +- 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0x32, 0xFA, 0x33, 0xFA, 0x34, 0xFA, 0x12, 0x60, 0x80, 0x64, +- 0xA9, 0xF1, 0x0E, 0xFA, 0x07, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x1A, 0x60, 0x4E, 0x63, 0xA3, 0xDB, +- 0x06, 0xA3, 0x10, 0x60, 0x38, 0x64, 0xBD, 0xDB, 0x04, 0x64, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, +- 0x10, 0x60, 0x36, 0x62, 0xEF, 0x60, 0xA9, 0x64, 0xA2, 0xDB, 0x1A, 0x60, 0x5A, 0x63, 0x00, 0x64, +- 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x3C, 0x64, 0xBD, 0xDB, 0x08, 0x64, 0xBD, 0xDB, 0x06, 0x64, +- 0xA3, 0xDB, 0x10, 0x60, 0x3A, 0x62, 0xEF, 0x60, 0xB3, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x22, 0x62, +- 0xEF, 0x60, 0x93, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x31, 0x60, 0x2A, 0x62, 0xA2, 0xDB, 0x2F, 0x58, +- 0xFF, 0xFF, 0x5E, 0xF5, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, +- 0xCC, 0xF1, 0x19, 0xF8, 0x30, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x00, 0x63, 0x8A, 0xFD, 0x1C, 0x60, 0x96, 0x65, 0xA5, 0xDD, 0x19, 0x60, 0x86, 0x63, +- 0x88, 0xFD, 0x89, 0xFD, 0x20, 0x40, 0x10, 0x2B, 0x05, 0x00, 0x1F, 0x60, 0x82, 0x61, 0xA1, 0xD3, +- 0xFF, 0xFF, 0x59, 0x18, 0x5E, 0xF5, 0x40, 0x64, 0x2A, 0xFA, 0x54, 0xF3, 0x00, 0xF4, 0x60, 0x43, +- 0xBD, 0xD1, 0x04, 0x65, 0x64, 0x47, 0xA5, 0xDA, 0x64, 0x41, 0xDD, 0x81, 0xE9, 0x81, 0x62, 0x44, +- 0x04, 0x03, 0xBD, 0xD1, 0xCD, 0x81, 0x58, 0xD8, 0xFC, 0x02, 0x58, 0x8B, 0x2D, 0x60, 0x28, 0x63, +- 0xA3, 0xD1, 0x2B, 0x44, 0xC8, 0x84, 0x64, 0x41, 0xFF, 0xB1, 0x61, 0x45, 0x03, 0xA1, 0xE9, 0x81, +- 0x41, 0x4C, 0xBD, 0xD1, 0xCD, 0x81, 0x58, 0xD8, 0xFC, 0x02, 0x2B, 0xD2, 0x2B, 0x43, 0x60, 0x47, +- 0x01, 0x7E, 0x54, 0xF1, 0xA3, 0xDA, 0xA4, 0xD3, 0xCB, 0x83, 0x44, 0x8B, 0xF8, 0x84, 0x2C, 0x41, +- 0x0C, 0x04, 0xBE, 0xD2, 0xFF, 0xFF, 0x60, 0x47, 0xBE, 0xDA, 0x00, 0x7E, 0xA3, 0xD2, 0x60, 0x45, +- 0x00, 0x7F, 0xB4, 0x84, 0xCD, 0x81, 0xBD, 0xDA, 0xF4, 0x02, 0x5E, 0xF5, 0x2B, 0x44, 0x04, 0xA4, +- 0x3F, 0xFA, 0x7F, 0xF3, 0x7E, 0xFB, 0x1F, 0x60, 0x84, 0x61, 0x01, 0x64, 0x54, 0xF1, 0xA1, 0xDB, +- 0x7F, 0xFB, 0xA4, 0xD3, 0x04, 0x65, 0x53, 0xF3, 0x01, 0x18, 0x0C, 0x65, 0xF3, 0xB4, 0xB4, 0x84, +- 0x53, 0xFB, 0x02, 0xB0, 0xFF, 0xFF, 0x16, 0x03, 0x7F, 0xF3, 0xFF, 0xFF, 0x60, 0x47, 0x0F, 0xB4, +- 0x7F, 0xFB, 0x01, 0x03, 0x0F, 0x00, 0xEE, 0x60, 0x4F, 0x78, 0xFF, 0xFF, 0x53, 0xF1, 0x7F, 0xF3, +- 0x64, 0x40, 0x02, 0x26, 0xF8, 0x01, 0xF3, 0xA0, 0x04, 0xA4, 0x01, 0x04, 0xF1, 0xA4, 0x10, 0x36, +- 0xF2, 0x01, 0x7F, 0xFB, 0x20, 0x40, 0x10, 0x2B, 0x12, 0x00, 0x7F, 0xF3, 0x1F, 0x60, 0x82, 0x61, +- 0xA1, 0xD1, 0xCC, 0x84, 0x01, 0x61, 0x08, 0x24, 0x03, 0x00, 0xE1, 0x81, 0xCC, 0x84, 0xFB, 0x01, +- 0xA1, 0x84, 0x53, 0xF1, 0xE4, 0x03, 0x1F, 0x60, 0x84, 0x61, 0xA1, 0xDB, 0x19, 0x00, 0x53, 0xF3, +- 0xFF, 0xFF, 0x10, 0xB0, 0x12, 0x60, 0x26, 0x63, 0x02, 0x03, 0x10, 0x60, 0x5C, 0x63, 0x31, 0x60, +- 0x2A, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0x0C, 0x1B, 0x7F, 0xF3, 0xFF, 0xFF, 0xE0, 0x85, 0x47, 0xD3, +- 0x53, 0xF1, 0x01, 0xB0, 0x06, 0xB0, 0xCB, 0x03, 0x64, 0x40, 0x03, 0x26, 0x01, 0x00, 0xC7, 0x03, +- 0x7F, 0xF3, 0x01, 0x61, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0xE1, 0x81, 0xFB, 0x01, 0xBA, 0xF3, +- 0x61, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0xBB, 0x03, 0x31, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, +- 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0B, 0x04, 0x0F, 0x60, 0xE6, 0x62, 0x40, 0x60, +- 0x00, 0x64, 0xA2, 0xDB, 0xED, 0x60, 0x70, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x7F, 0xF1, 0x24, 0x60, 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, +- 0x0F, 0x60, 0xE6, 0x62, 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xED, 0x60, 0xA3, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, +- 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x5E, 0xF5, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x28, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x64, 0x51, 0xFB, 0x0F, 0x60, 0xE6, 0x62, +- 0x00, 0x60, 0x01, 0x64, 0xA2, 0xDB, 0xED, 0x60, 0xCD, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, +- 0x33, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x34, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xC6, 0xF1, 0x1A, 0x60, 0x52, 0x62, 0xA2, 0xD9, +- 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x4E, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0xC7, 0xF1, 0x1A, 0x60, 0x5E, 0x62, 0xA2, 0xD9, 0x24, 0x60, 0xA8, 0x62, 0xA2, 0xD3, +- 0xFF, 0xFF, 0xFD, 0x1B, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x5A, 0x64, 0xA2, 0xDB, 0x02, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x0F, 0x60, 0xE6, 0x62, 0x00, 0x60, 0x08, 0x64, 0xA2, 0xDB, +- 0xED, 0x60, 0xFE, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x51, 0xF1, 0x0F, 0x60, +- 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x64, 0x40, 0xFF, 0x26, 0x03, 0x00, 0xED, 0x60, 0x36, 0x78, +- 0xFF, 0xFF, 0x02, 0x0A, 0x00, 0x64, 0x51, 0xFB, 0xC8, 0xF1, 0x1A, 0x60, 0x5E, 0x62, 0xA2, 0xD9, +- 0x0F, 0x60, 0xE6, 0x62, 0x00, 0x60, 0x0C, 0x64, 0xA2, 0xDB, 0xEE, 0x60, 0x24, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x5A, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xE4, 0x62, 0xA2, 0xD1, 0x00, 0x60, +- 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0C, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x60, 0xAA, 0x62, +- 0x1A, 0x60, 0x5A, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x14, 0x00, +- 0xFF, 0x60, 0xF7, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x51, 0xF3, 0xDB, 0x0A, 0x00, 0xA0, 0x00, 0x64, +- 0x02, 0x03, 0x51, 0xFB, 0xD6, 0x01, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x4E, 0x64, 0xA2, 0xDB, +- 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xED, 0x60, 0x36, 0x78, 0xFF, 0xFF, 0x35, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0x4E, 0x64, 0xA2, 0xDB, 0x03, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x53, 0xF3, 0xFF, 0xFF, 0xE3, 0xB4, 0x53, 0xFB, 0x1F, 0x60, +- 0x80, 0x64, 0xA0, 0xD3, 0xFF, 0xFF, 0xFE, 0xB4, 0xA2, 0xDB, 0x00, 0x64, 0x31, 0x60, 0x2A, 0x62, +- 0xA2, 0xDB, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0E, 0x04, 0x32, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x0F, 0x60, 0xE6, 0x62, 0x40, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xEE, 0x60, +- 0x69, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7E, 0xF1, 0x7F, 0xF9, 0x24, 0x60, +- 0x9A, 0x62, 0xA2, 0xD9, 0x1E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x0F, 0x60, 0xE6, 0x62, +- 0x20, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xEE, 0x60, 0x91, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0xBE, 0xFE, 0x0F, 0x60, 0xD0, 0x62, 0xA2, 0xD1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x1A, 0x60, 0x06, 0x63, 0x1C, 0x61, 0x00, 0x64, 0xCD, 0x81, 0xBD, 0xDB, +- 0xFD, 0x02, 0x12, 0x60, 0x46, 0x61, 0x8A, 0xF3, 0x61, 0x43, 0xC6, 0xA5, 0x47, 0xD1, 0x0F, 0x04, +- 0xBE, 0xD5, 0x1A, 0x60, 0x02, 0x63, 0xC3, 0x83, 0xC3, 0x83, 0xC3, 0x83, 0x43, 0xD3, 0xBE, 0xD1, +- 0xDC, 0x84, 0xA3, 0xDB, 0x66, 0x44, 0xC0, 0x84, 0xBE, 0xDB, 0x65, 0x44, 0xED, 0x01, 0x1A, 0x60, +- 0x06, 0x63, 0x0E, 0x61, 0x41, 0x4B, 0xBD, 0xD3, 0xBD, 0xD1, 0x00, 0xBD, 0x64, 0x41, 0x19, 0x03, +- 0x01, 0xA8, 0x61, 0x44, 0x02, 0xA8, 0x15, 0x03, 0x02, 0x02, 0xE9, 0x84, 0x12, 0x00, 0x65, 0x47, +- 0x60, 0x45, 0x61, 0x44, 0x09, 0x61, 0xCD, 0x81, 0xE0, 0x84, 0xFF, 0x23, 0xFC, 0x01, 0x02, 0x24, +- 0xC4, 0x84, 0x02, 0x28, 0xD4, 0x84, 0xCD, 0x81, 0x01, 0x0E, 0x01, 0xBC, 0x02, 0x03, 0xE0, 0x84, +- 0xF6, 0x01, 0x00, 0x7F, 0x2B, 0x41, 0x4D, 0x8B, 0xBF, 0xDB, 0xDD, 0x02, 0x12, 0x60, 0x46, 0x61, +- 0x8A, 0xF3, 0x61, 0x43, 0xC6, 0xA5, 0x47, 0xD1, 0x0A, 0x04, 0xDA, 0x86, 0x1A, 0x60, 0x04, 0x63, +- 0xC3, 0x83, 0xC3, 0x83, 0xC3, 0x83, 0x43, 0xD1, 0xA6, 0xD9, 0x65, 0x44, 0xF2, 0x01, 0x36, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x53, 0xF3, 0x8A, 0xF1, 0xF3, 0xB4, 0x53, 0xFB, 0x12, 0x60, 0x46, 0x63, +- 0xC3, 0x85, 0x45, 0x4A, 0x19, 0x60, 0x86, 0x65, 0x89, 0xF3, 0x45, 0x4C, 0x40, 0x48, 0x20, 0x40, +- 0x20, 0x2A, 0x02, 0x00, 0x00, 0x65, 0x45, 0x4B, 0x2A, 0x45, 0xD7, 0x80, 0x02, 0x65, 0x23, 0x05, +- 0x47, 0xD1, 0x02, 0x65, 0x47, 0xD3, 0x0A, 0x65, 0xD0, 0x81, 0x47, 0xD3, 0x01, 0x05, 0x00, 0x61, +- 0xF2, 0xA3, 0x01, 0xB0, 0x61, 0x44, 0x11, 0x03, 0x20, 0x40, 0x20, 0x2A, 0x08, 0x00, 0xF3, 0x60, +- 0x58, 0x4E, 0x3E, 0x78, 0xFF, 0xFF, 0x2B, 0x44, 0x02, 0xA4, 0x40, 0x4B, 0x61, 0x44, 0x2C, 0x42, +- 0xA2, 0xDB, 0x5A, 0xDD, 0x5A, 0x8C, 0x3A, 0xA3, 0xDF, 0x01, 0x28, 0x42, 0x4A, 0xDD, 0x4A, 0xDB, +- 0x42, 0x48, 0x3A, 0xA3, 0xD9, 0x01, 0x28, 0x44, 0x88, 0xFB, 0x88, 0xF1, 0x19, 0x60, 0x86, 0x63, +- 0x44, 0x48, 0x28, 0x45, 0xD7, 0x80, 0xA3, 0xD1, 0x15, 0x05, 0x04, 0x65, 0x46, 0xD3, 0x28, 0x45, +- 0xD6, 0x80, 0xD0, 0x80, 0x02, 0x04, 0x04, 0xA3, 0xF5, 0x01, 0xF7, 0x06, 0x62, 0x46, 0xA2, 0xD9, +- 0xA3, 0xDB, 0x5B, 0xD3, 0x66, 0x42, 0x5A, 0xD1, 0xA2, 0xDB, 0xA3, 0xD9, 0xFE, 0xA3, 0xA3, 0xD1, +- 0x66, 0x42, 0xEB, 0x01, 0x88, 0xF3, 0x89, 0xF1, 0x60, 0x43, 0x44, 0x48, 0x28, 0x45, 0xD7, 0x80, +- 0xA3, 0xD1, 0x15, 0x05, 0x04, 0x65, 0x46, 0xD3, 0x28, 0x45, 0xD6, 0x80, 0xD0, 0x80, 0x02, 0x04, +- 0x04, 0xA3, 0xF5, 0x01, 0xF7, 0x06, 0x62, 0x46, 0xA2, 0xD9, 0xA3, 0xDB, 0x5B, 0xD3, 0x66, 0x42, +- 0x5A, 0xD1, 0xA2, 0xDB, 0xA3, 0xD9, 0xFE, 0xA3, 0xA3, 0xD1, 0x66, 0x42, 0xEB, 0x01, 0x0F, 0x60, +- 0xD0, 0x62, 0xA2, 0xD1, 0x10, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x20, 0x40, +- 0x80, 0x2B, 0x17, 0x00, 0x00, 0x60, 0x04, 0x61, 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, +- 0x01, 0x64, 0x23, 0xFA, 0xF1, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, +- 0x64, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xFA, 0xFE, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0x3E, 0x64, 0x3B, 0x42, +- 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x3F, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x24, 0x60, 0xAA, 0x62, +- 0x1A, 0x60, 0x4E, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, +- 0x53, 0xFB, 0x0F, 0x60, 0xE4, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0xBE, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x0F, 0x60, 0xE4, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0F, 0x60, 0xE4, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x08, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x79, 0xFB, 0xAC, 0x85, 0x60, 0x41, +- 0x20, 0x03, 0x01, 0x60, 0x00, 0x63, 0x08, 0x64, 0xE9, 0x81, 0xCC, 0x84, 0x02, 0x24, 0xDF, 0x83, +- 0xFB, 0x02, 0x2D, 0x60, 0x28, 0x64, 0xA0, 0xDD, 0x65, 0x41, 0x2D, 0x60, 0x2A, 0x63, 0x0F, 0x60, +- 0xC0, 0x64, 0xE9, 0x81, 0x58, 0xD1, 0xFD, 0x04, 0xA3, 0xD9, 0x0B, 0x03, 0x58, 0xD1, 0xE9, 0x81, +- 0x60, 0x45, 0xFC, 0x04, 0xA3, 0xD1, 0x64, 0x47, 0xB0, 0x84, 0xBD, 0xDB, 0x00, 0xB9, 0x65, 0x44, +- 0xF0, 0x02, 0x2E, 0x58, 0xFF, 0xFF, 0x3C, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x20, 0x40, 0x90, 0x2B, +- 0x03, 0x00, 0xF2, 0x60, 0xE5, 0x78, 0xFF, 0xFF, 0x53, 0xF3, 0x8A, 0xF1, 0x04, 0xB0, 0x07, 0x60, +- 0x40, 0x64, 0xD0, 0x80, 0x21, 0x03, 0x20, 0x06, 0x26, 0x46, 0x8A, 0xF1, 0x12, 0x60, 0x46, 0x63, +- 0xC3, 0x83, 0x7F, 0xF3, 0x26, 0xF0, 0xBD, 0xDB, 0x64, 0x44, 0x00, 0x7F, 0xBD, 0xDB, 0x64, 0x47, +- 0x00, 0x7F, 0xBD, 0xDB, 0x32, 0xF0, 0xBD, 0xD9, 0x33, 0xF0, 0xBD, 0xD9, 0x34, 0xF0, 0xBD, 0xD9, +- 0x00, 0xF4, 0x0D, 0xF0, 0xBD, 0xD9, 0x0E, 0xF0, 0xBD, 0xD9, 0x00, 0x64, 0x0F, 0xF0, 0xA3, 0xDB, +- 0x64, 0x47, 0x60, 0x45, 0x00, 0x37, 0x03, 0x00, 0xF2, 0x60, 0xDF, 0x78, 0xFF, 0xFF, 0xBD, 0xDB, +- 0xE0, 0xA0, 0x1F, 0x61, 0x00, 0xB8, 0xF8, 0x07, 0xF7, 0x03, 0x60, 0xFE, 0xDD, 0x81, 0xA1, 0xD0, +- 0xCC, 0x84, 0xBD, 0xD9, 0xFB, 0x02, 0x65, 0x40, 0x01, 0x26, 0xDF, 0x83, 0x20, 0xFE, 0x2D, 0x60, +- 0xE4, 0x62, 0xA2, 0xDD, 0x60, 0xFE, 0xDD, 0x81, 0xA1, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x3A, +- 0x04, 0x00, 0xDD, 0x81, 0xA1, 0xD0, 0xFF, 0xFF, 0xC1, 0x81, 0xDD, 0x81, 0xA1, 0xD0, 0xFF, 0xFF, +- 0x64, 0x40, 0x03, 0x36, 0x03, 0x00, 0xF2, 0x60, 0xDF, 0x78, 0xFF, 0xFF, 0xD9, 0x81, 0xA1, 0xD0, +- 0x7F, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0x20, 0xFE, 0x08, 0x24, 0x03, 0x00, 0xF2, 0x60, 0xDF, 0x78, +- 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF4, 0xA3, 0x00, 0x60, 0x1D, 0x61, +- 0x00, 0x60, 0x80, 0x65, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, +- 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0xD4, 0x80, 0x2D, 0x03, 0x17, 0x03, 0xCF, 0x83, 0x61, 0x44, +- 0x80, 0xA0, 0x28, 0x03, 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, +- 0x81, 0xA1, 0x20, 0x03, 0x05, 0x07, 0x7F, 0xA1, 0xCC, 0x84, 0xDD, 0x81, 0xE4, 0x03, 0xF7, 0x01, +- 0x00, 0xF4, 0x00, 0xB8, 0x04, 0x61, 0xE4, 0x03, 0xF2, 0x01, 0x01, 0x60, 0xFF, 0x63, 0x46, 0x48, +- 0x41, 0x4A, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, 0x64, 0x44, 0xDD, 0x81, 0xA1, 0xD0, +- 0xDF, 0x83, 0xA3, 0xD9, 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, 0x7F, 0xA1, 0xF7, 0x04, 0x00, 0xF4, +- 0x03, 0x61, 0xF4, 0x01, 0x20, 0xFE, 0x00, 0xBB, 0x02, 0x60, 0x00, 0x61, 0x45, 0x03, 0x60, 0xFE, +- 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x3A, 0x3E, 0x00, 0xDD, 0x81, 0xA1, 0xD1, +- 0xFF, 0xFF, 0x64, 0x40, 0x60, 0x3A, 0x38, 0x00, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, +- 0x1D, 0x3A, 0x32, 0x00, 0xDD, 0x81, 0xA1, 0xD3, 0xFF, 0xFF, 0x20, 0xFE, 0xFF, 0xB4, 0x1C, 0x60, +- 0x96, 0x65, 0xA5, 0xD3, 0x60, 0x5C, 0x02, 0xA4, 0xA5, 0xDB, 0xFE, 0xA5, 0x1A, 0x60, 0xC6, 0x64, +- 0x44, 0xD9, 0x00, 0x7C, 0x60, 0xFE, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x1B, 0x60, +- 0x06, 0x64, 0xC4, 0x82, 0x64, 0x44, 0xFF, 0xB4, 0xA2, 0xDB, 0x12, 0x60, 0x48, 0x65, 0x8A, 0xF3, +- 0xFF, 0xFF, 0xC4, 0x82, 0x64, 0x44, 0xA2, 0xD3, 0xFF, 0xB5, 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x05, +- 0x65, 0x44, 0xA2, 0xDB, 0x09, 0x00, 0x20, 0xFE, 0x28, 0x46, 0x2A, 0x41, 0xFF, 0xB1, 0x60, 0xFE, +- 0x82, 0x64, 0xA1, 0xDA, 0xFF, 0xFF, 0x20, 0xFE, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, +- 0xF4, 0xA3, 0x00, 0x60, 0x1D, 0x61, 0x00, 0x60, 0xDD, 0x65, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, +- 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0xD4, 0x80, 0x2D, 0x03, +- 0x17, 0x03, 0xCF, 0x83, 0x61, 0x44, 0x80, 0xA0, 0x28, 0x03, 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, +- 0xDD, 0x81, 0xA1, 0xD2, 0xCF, 0x83, 0x81, 0xA1, 0x20, 0x03, 0x05, 0x07, 0x7F, 0xA1, 0xCC, 0x84, +- 0xDD, 0x81, 0xE4, 0x03, 0xF7, 0x01, 0x00, 0xF4, 0x00, 0xB8, 0x04, 0x61, 0xE4, 0x03, 0xF2, 0x01, +- 0x02, 0x60, 0x00, 0x63, 0x46, 0x48, 0x41, 0x4A, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, +- 0x64, 0x44, 0xDD, 0x81, 0xA1, 0xD0, 0xDF, 0x83, 0xA3, 0xD9, 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, +- 0x7F, 0xA1, 0xF7, 0x04, 0x00, 0xF4, 0x03, 0x61, 0xF4, 0x01, 0x20, 0xFE, 0x00, 0xBB, 0x02, 0x60, +- 0x00, 0x61, 0x08, 0x24, 0xA6, 0x00, 0x2D, 0x60, 0xD6, 0x62, 0xA2, 0xDF, 0x2D, 0x60, 0xD8, 0x62, +- 0xA2, 0xDF, 0x2D, 0x60, 0xDA, 0x62, 0xA2, 0xDF, 0x2D, 0x60, 0xDC, 0x62, 0xA2, 0xDF, 0x60, 0xFE, +- 0xDD, 0x64, 0xA1, 0xDB, 0xDD, 0x81, 0xA1, 0xD3, 0xFF, 0xFF, 0xFA, 0xA4, 0xFF, 0xFF, 0x04, 0x34, +- 0x9A, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x3A, 0x94, 0x01, 0xDD, 0x81, +- 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x50, 0x3A, 0x8E, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, +- 0x64, 0x40, 0xF2, 0x3A, 0x88, 0x01, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x3A, +- 0xDC, 0x00, 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x3A, 0xD6, 0x00, 0xDD, 0x81, +- 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x3A, 0xD0, 0x00, 0x60, 0x5C, 0x00, 0x36, 0x39, 0x00, +- 0x00, 0x64, 0xF2, 0x60, 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x08, 0x26, 0xF7, 0x01, +- 0x2D, 0x60, 0xD6, 0x62, 0xA2, 0xDB, 0x64, 0x40, 0x00, 0x36, 0x31, 0x00, 0xDD, 0x81, 0xA1, 0xD3, +- 0xDD, 0x81, 0xF2, 0x60, 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x08, 0x26, 0xF5, 0x01, +- 0x2D, 0x60, 0xD8, 0x62, 0xA2, 0xDB, 0x64, 0x40, 0x00, 0x36, 0x27, 0x00, 0xDD, 0x81, 0xA1, 0xD3, +- 0xDD, 0x81, 0xF2, 0x60, 0x58, 0x4E, 0x57, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x08, 0x26, 0xF5, 0x01, +- 0x2D, 0x60, 0xDA, 0x62, 0xA2, 0xDB, 0x64, 0x40, 0x00, 0x36, 0x1D, 0x00, 0xDD, 0x81, 0xA1, 0xD1, +- 0x2D, 0x60, 0xDC, 0x62, 0xA2, 0xD9, 0xDD, 0x81, 0xA1, 0xD1, 0x2D, 0x60, 0xDD, 0x62, 0xA2, 0xD9, +- 0x18, 0x00, 0x20, 0xFE, 0x2D, 0x60, 0xD6, 0x62, 0x00, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0x20, 0xFE, +- 0x2D, 0x60, 0xD8, 0x62, 0x00, 0x60, 0x04, 0x64, 0xA2, 0xDB, 0x20, 0xFE, 0x2D, 0x60, 0xDA, 0x62, +- 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0x20, 0xFE, 0x2D, 0x60, 0xDC, 0x62, 0x00, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0x20, 0xFE, 0x02, 0x60, 0x00, 0x65, 0x2D, 0x60, 0x9E, 0x63, 0xD5, 0x84, 0xDC, 0x84, +- 0xBD, 0xDB, 0x60, 0x41, 0x66, 0x44, 0x63, 0x46, 0xCD, 0x83, 0xC7, 0x81, 0x60, 0x45, 0x60, 0xFE, +- 0x5D, 0x93, 0xA3, 0xD3, 0x5D, 0x93, 0xA6, 0xDB, 0xDE, 0x86, 0xFA, 0x1F, 0x66, 0x43, 0x65, 0x46, +- 0x20, 0xFE, 0x20, 0xFE, 0x2D, 0x60, 0xE4, 0x62, 0xA2, 0xD1, 0xFF, 0xFF, 0x64, 0x43, 0x00, 0x64, +- 0x2D, 0x60, 0xCE, 0x61, 0xA1, 0xDB, 0x2D, 0x60, 0xC2, 0x62, 0xA2, 0xD1, 0x2D, 0x60, 0xD6, 0x62, +- 0xA2, 0xD3, 0xFF, 0xFF, 0xA0, 0x84, 0xFF, 0xFF, 0x10, 0x26, 0x07, 0x00, 0x04, 0x26, 0x07, 0x00, +- 0x20, 0x26, 0x07, 0x00, 0x02, 0x26, 0x07, 0x00, 0x48, 0x00, 0x10, 0x7C, 0x05, 0x00, 0x04, 0x7C, +- 0x03, 0x00, 0x20, 0x7C, 0x01, 0x00, 0x02, 0x7C, 0x2D, 0x60, 0xCE, 0x61, 0xA1, 0xD9, 0x50, 0x94, +- 0x2D, 0x60, 0xD0, 0x61, 0xA1, 0xDB, 0x2D, 0x60, 0xC4, 0x61, 0xA1, 0xD1, 0x2D, 0x60, 0xD8, 0x61, +- 0xA1, 0xD3, 0x2D, 0x60, 0xCE, 0x61, 0xA0, 0x84, 0xA1, 0xD1, 0xFF, 0xFF, 0x10, 0x26, 0x05, 0x00, +- 0x04, 0x26, 0x05, 0x00, 0x01, 0x26, 0x08, 0x00, 0x28, 0x00, 0x10, 0x7C, 0x06, 0x00, 0x64, 0x40, +- 0x10, 0x26, 0x23, 0x00, 0x04, 0x7C, 0x01, 0x00, 0x01, 0x7C, 0x2D, 0x60, 0xD0, 0x61, 0xA1, 0xD9, +- 0x50, 0x94, 0x2D, 0x60, 0xD2, 0x61, 0xA1, 0xDB, 0x2D, 0x60, 0xC6, 0x61, 0xA1, 0xD1, 0x2D, 0x60, +- 0xDA, 0x61, 0xA1, 0xD3, 0xFF, 0xFF, 0xA0, 0x84, 0x60, 0x40, 0x02, 0x26, 0x05, 0x00, 0x04, 0x26, +- 0x05, 0x00, 0x01, 0x26, 0x05, 0x00, 0x09, 0x00, 0x02, 0x7C, 0x03, 0x00, 0x04, 0x7C, 0x01, 0x00, +- 0x20, 0x7C, 0x2D, 0x60, 0xD2, 0x61, 0xA1, 0xD9, 0x0D, 0x00, 0x50, 0x94, 0x2D, 0x60, 0xCE, 0x62, +- 0xA2, 0xDB, 0x2D, 0x60, 0xD0, 0x62, 0xA2, 0xDB, 0x2D, 0x60, 0xD2, 0x62, 0xA2, 0xDB, 0x2D, 0x60, +- 0xD4, 0x62, 0xA2, 0xDB, 0x7C, 0x44, 0x2D, 0x60, 0xCE, 0x61, 0xA1, 0xD1, 0xBD, 0xD9, 0x2D, 0x60, +- 0xD0, 0x61, 0xA1, 0xD1, 0xB0, 0x84, 0xBD, 0xD9, 0x2D, 0x60, 0xD2, 0x61, 0xA1, 0xD1, 0xB0, 0x84, +- 0xBD, 0xD9, 0x2D, 0x60, 0xC8, 0x61, 0xA1, 0xD1, 0xB0, 0x84, 0xBD, 0xD9, 0x08, 0x28, 0x68, 0x00, +- 0x28, 0x60, 0x2C, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xFF, 0xA0, 0xFF, 0xFF, 0x0C, 0x24, 0x60, 0x00, +- 0x60, 0x40, 0x0B, 0x36, 0x5D, 0x00, 0x20, 0x40, 0x10, 0x27, 0x5A, 0x00, 0x88, 0x00, 0x20, 0xFE, +- 0x00, 0x65, 0x60, 0xFE, 0x2D, 0x60, 0xDE, 0x62, 0xA2, 0xDB, 0xE0, 0x84, 0xE0, 0x84, 0x08, 0x20, +- 0x03, 0x00, 0x01, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x02, 0xA5, 0x64, 0x44, 0xD4, 0x9C, 0xD4, 0x80, +- 0x2D, 0x60, 0xE0, 0x62, 0x02, 0x05, 0x08, 0x65, 0x41, 0x00, 0xA2, 0xD9, 0x7C, 0x44, 0x2D, 0x60, +- 0xE2, 0x62, 0xA2, 0xDB, 0xDD, 0x81, 0xA1, 0xD1, 0x00, 0x65, 0x64, 0x40, 0x00, 0x3A, 0x01, 0x65, +- 0xDD, 0x81, 0xA1, 0xD1, 0xFF, 0xFF, 0x64, 0x40, 0x50, 0x3A, 0x01, 0x65, 0xDD, 0x81, 0xA1, 0xD1, +- 0xFF, 0xFF, 0x64, 0x40, 0xF2, 0x3A, 0x01, 0x65, 0xDD, 0x81, 0xA1, 0xD1, 0x65, 0x40, 0x00, 0x3A, +- 0x18, 0x00, 0x00, 0x60, 0x00, 0x65, 0x64, 0x40, 0x00, 0x36, 0x01, 0x65, 0x64, 0x40, 0x01, 0x36, +- 0x02, 0x65, 0x64, 0x40, 0x02, 0x36, 0x04, 0x65, 0x64, 0x40, 0x04, 0x36, 0x10, 0x65, 0x64, 0x40, +- 0x05, 0x36, 0x20, 0x65, 0x65, 0x5C, 0x2D, 0x60, 0xE2, 0x62, 0xA2, 0xD3, 0xFF, 0xFF, 0xB0, 0x84, +- 0xA2, 0xDB, 0x2D, 0x60, 0xDE, 0x62, 0xA2, 0xD3, 0x00, 0x65, 0xFF, 0xA4, 0xA2, 0xDB, 0xCA, 0x02, +- 0x2D, 0x60, 0xE2, 0x62, 0xA2, 0xD3, 0x2D, 0x60, 0xE0, 0x62, 0xA2, 0xD1, 0x2E, 0x58, 0xFF, 0xFF, +- 0x20, 0xFE, 0x8A, 0xF3, 0xFF, 0xFF, 0x3A, 0xA4, 0x8A, 0xFB, 0x3D, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x89, 0xF3, 0x7F, 0xF1, 0x04, 0xA4, 0x89, 0xFB, 0x12, 0x60, 0x22, 0x63, 0x53, 0xF3, 0x64, 0x41, +- 0x08, 0xB0, 0xE1, 0x85, 0x1C, 0x03, 0xFE, 0xA1, 0x47, 0xD3, 0x02, 0x06, 0xFB, 0xB4, 0xA3, 0xDB, +- 0xDD, 0x81, 0x5B, 0xD3, 0x0C, 0x24, 0x02, 0x00, 0xFB, 0xB4, 0xA3, 0xDB, 0x5B, 0xD3, 0xDD, 0x81, +- 0x02, 0xBC, 0xA3, 0xDB, 0x0E, 0x65, 0xDD, 0x81, 0xD5, 0x80, 0x5B, 0xD3, 0x08, 0x05, 0xFB, 0xB4, +- 0xA3, 0xDB, 0xDD, 0x81, 0xD5, 0x80, 0x5B, 0xD3, 0x02, 0x03, 0xFB, 0xB4, 0xA3, 0xDB, 0xFF, 0xFF, +- 0x20, 0xFE, 0x26, 0x46, 0x31, 0x40, 0x20, 0x2A, 0x18, 0x00, 0x3F, 0xF2, 0x47, 0x65, 0xC4, 0x84, +- 0xE8, 0x84, 0x23, 0xFA, 0xF1, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, +- 0x64, 0x64, 0xA2, 0xDB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xFA, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, +- 0x16, 0x63, 0x1C, 0x60, 0x8C, 0x62, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x5B, 0xFB, 0x5C, 0xFB, +- 0x1C, 0x60, 0x92, 0x63, 0x02, 0x64, 0xA3, 0xDB, 0x1A, 0x60, 0xC6, 0x62, 0x3E, 0x63, 0x00, 0x64, +- 0x5A, 0xDB, 0xFE, 0x1F, 0x2E, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x98, 0x62, 0xA2, 0xD3, 0x00, 0x63, +- 0xF8, 0xA0, 0x01, 0xA4, 0x03, 0x03, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0xA2, 0xDD, 0x1C, 0x60, +- 0x9A, 0x62, 0xA2, 0xD1, 0xA2, 0xDD, 0x5A, 0xD3, 0xA2, 0xDD, 0xC0, 0x81, 0x61, 0x44, 0x02, 0x24, +- 0xFF, 0xFF, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0x5A, 0xD3, 0xE9, 0x81, 0xE8, 0x83, +- 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x85, 0xD4, 0x85, 0xC5, 0x83, 0xA2, 0xDD, 0x1C, 0x60, +- 0x8E, 0x62, 0x63, 0x47, 0x00, 0x7F, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0xA0, 0x65, +- 0xA5, 0xDD, 0x1B, 0x60, 0x46, 0x65, 0x61, 0x44, 0x2B, 0x41, 0x45, 0xDB, 0x60, 0x41, 0x1B, 0x60, +- 0x86, 0x65, 0x0A, 0xA3, 0xA3, 0xD1, 0x2B, 0x44, 0x44, 0xD9, 0x1C, 0x60, 0xA0, 0x65, 0xA5, 0xD3, +- 0xFF, 0xFF, 0x60, 0x43, 0x00, 0xB9, 0xFF, 0xFF, 0x4C, 0x03, 0x06, 0xA3, 0xBD, 0xD1, 0x81, 0xF3, +- 0x82, 0xF1, 0xD0, 0x80, 0xBD, 0xD3, 0x22, 0x02, 0x83, 0xF3, 0xD0, 0x80, 0xA3, 0xD1, 0x1E, 0x02, +- 0xD0, 0x80, 0xFF, 0xFF, 0x1B, 0x02, 0x8A, 0xF3, 0x12, 0x60, 0x46, 0x63, 0xC6, 0xA5, 0x47, 0xD1, +- 0x7F, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x08, 0x28, 0xFF, 0x61, 0x61, 0x43, 0x1A, 0x60, +- 0xC6, 0x65, 0x2B, 0x44, 0x44, 0xD1, 0x1C, 0x60, 0x8E, 0x65, 0xA5, 0xD1, 0x64, 0x44, 0xD0, 0x81, +- 0x1C, 0x60, 0x92, 0x65, 0x01, 0x05, 0x00, 0x61, 0xA5, 0xD3, 0x15, 0x00, 0x1A, 0x60, 0xC6, 0x65, +- 0x2B, 0x44, 0x44, 0xD1, 0x1C, 0x60, 0x8E, 0x65, 0x64, 0x43, 0xA5, 0xD1, 0x64, 0x65, 0x63, 0x44, +- 0xC0, 0x84, 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x06, 0x00, 0x61, 0x13, 0x00, 0x61, 0x43, 0xD0, 0x81, +- 0x1C, 0x60, 0x92, 0x65, 0xA5, 0xD3, 0xE9, 0x81, 0xE9, 0x81, 0xCC, 0x84, 0xCC, 0x84, 0x02, 0x03, +- 0x02, 0x03, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x85, 0xD7, 0x84, 0x60, 0x41, 0x01, 0x05, +- 0x00, 0x61, 0x1C, 0x60, 0xA0, 0x65, 0xA5, 0xD3, 0xFF, 0xFF, 0x60, 0x43, 0x2E, 0x58, 0xFF, 0xFF, +- 0x1C, 0x60, 0x94, 0x65, 0xA5, 0xD1, 0x5B, 0xF3, 0x64, 0x41, 0xCD, 0x81, 0xCD, 0x81, 0x02, 0x03, +- 0x02, 0x03, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x85, 0x29, 0x44, 0x54, 0x89, 0x2E, 0x58, +- 0xFF, 0xFF, 0xED, 0xF3, 0x1A, 0x60, 0xBE, 0x63, 0x0F, 0xB4, 0x01, 0xA4, 0xE0, 0x87, 0xE0, 0x84, +- 0xE0, 0x84, 0xBD, 0xDB, 0x10, 0x60, 0x58, 0x64, 0xBD, 0xDB, 0x02, 0x64, 0xBD, 0xDB, 0x06, 0x64, +- 0xA3, 0xDB, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0xBA, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x2E, 0x58, 0xFF, 0xFF, 0x1A, 0x60, 0xBE, 0x63, 0xEA, 0x60, 0x60, 0x64, +- 0xBD, 0xDB, 0x10, 0x60, 0x58, 0x64, 0xBD, 0xDB, 0x02, 0x64, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, +- 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, 0xBA, 0x64, 0xA2, 0xDB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x2E, 0x58, 0xFF, 0xFF, 0x16, 0x63, 0x1C, 0x60, 0x8C, 0x62, 0x00, 0x64, 0x5A, 0xDB, +- 0xFE, 0x1F, 0x5B, 0xFB, 0x5C, 0xFB, 0x1C, 0x60, 0x92, 0x63, 0x02, 0x64, 0xA3, 0xDB, 0x1A, 0x60, +- 0xC6, 0x62, 0x3E, 0x63, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x10, 0x60, 0x56, 0x62, 0xF5, 0x60, +- 0x29, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x2C, 0x62, 0xF5, 0x60, 0x15, 0x64, 0xA2, 0xDB, 0x10, 0x60, +- 0x02, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x04, 0x62, 0x00, 0x60, 0x04, 0x64, 0xA2, 0xDB, +- 0xF4, 0x60, 0x16, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x20, 0x44, 0x40, 0x26, +- 0x03, 0x00, 0xF4, 0x60, 0xEA, 0x78, 0xFF, 0xFF, 0x20, 0x40, 0x52, 0x23, 0x07, 0x00, 0x5A, 0xF3, +- 0xFF, 0xFF, 0x01, 0xA4, 0x5A, 0xFB, 0xF4, 0x60, 0xD7, 0x78, 0xFF, 0xFF, 0x40, 0x60, 0x00, 0x65, +- 0x20, 0x44, 0x34, 0x80, 0x1C, 0x60, 0x92, 0x65, 0x02, 0x64, 0xA5, 0xDB, 0x1A, 0x60, 0xC4, 0x62, +- 0x7E, 0x63, 0x00, 0x64, 0x5A, 0xDB, 0xFE, 0x1F, 0x1C, 0x60, 0x96, 0x62, 0xA2, 0xDD, 0x8C, 0xF3, +- 0x58, 0xFB, 0x02, 0x64, 0x8C, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x8C, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, +- 0xFF, 0xFF, 0x0B, 0x03, 0x10, 0x60, 0x04, 0x62, 0x80, 0x60, 0x00, 0x64, 0xA2, 0xDB, 0xF4, 0x60, +- 0x3D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x04, 0x64, 0x53, 0xFB, 0x29, 0x60, +- 0xA4, 0x64, 0x54, 0xFB, 0x0F, 0x4E, 0xEC, 0x60, 0x58, 0x4F, 0xB9, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, +- 0x10, 0x60, 0x02, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x04, 0x62, 0x10, 0x60, 0x00, 0x64, +- 0xA2, 0xDB, 0xF4, 0x60, 0x67, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x58, 0xF3, +- 0x8C, 0xFB, 0xCA, 0xFE, 0xC1, 0xFE, 0x1C, 0x60, 0xA2, 0x62, 0x66, 0x44, 0xA2, 0xDB, 0x5A, 0xDD, +- 0x61, 0x44, 0x5A, 0xDB, 0x67, 0xF5, 0xCC, 0xF1, 0x19, 0xF8, 0xF8, 0x60, 0x80, 0x64, 0x0E, 0xFA, +- 0xA9, 0xF1, 0x07, 0xF8, 0x01, 0x60, 0x60, 0x67, 0x2C, 0xFA, 0x1D, 0x64, 0x2D, 0xFA, 0x01, 0x64, +- 0x2E, 0xFA, 0xEB, 0xF1, 0x2F, 0xF8, 0xEC, 0xF1, 0x30, 0xF8, 0xED, 0xF1, 0x31, 0xF8, 0x81, 0xF1, +- 0x32, 0xF8, 0x82, 0xF1, 0x33, 0xF8, 0x83, 0xF1, 0x34, 0xF8, 0x08, 0x64, 0x2A, 0xFA, 0x40, 0x63, +- 0x3F, 0xFC, 0x00, 0xF4, 0x02, 0x62, 0xCB, 0x83, 0x00, 0x64, 0x5A, 0xDA, 0xFE, 0x1F, 0x1C, 0x60, +- 0x8E, 0x65, 0xA5, 0xD3, 0x02, 0xFA, 0x19, 0x60, 0x88, 0x64, 0xA0, 0xD1, 0x0A, 0x61, 0x41, 0xD3, +- 0x03, 0xFA, 0x06, 0x61, 0x06, 0x63, 0x00, 0x65, 0x1B, 0x60, 0x86, 0x64, 0x44, 0xD1, 0x59, 0xD8, +- 0x1B, 0x60, 0x46, 0x64, 0x44, 0xD1, 0x59, 0xD8, 0x1A, 0x60, 0xC6, 0x64, 0x44, 0xD1, 0x59, 0xD8, +- 0x1B, 0x60, 0x06, 0x64, 0x44, 0xD1, 0x59, 0xD8, 0x65, 0x44, 0x02, 0xA4, 0x60, 0x45, 0xEC, 0x1F, +- 0x67, 0xF5, 0x24, 0x60, 0x74, 0x62, 0x24, 0x60, 0x22, 0x64, 0xA2, 0xDB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x1C, 0x60, 0xA2, 0x62, 0xA2, 0xD5, 0x5A, 0xD3, +- 0x5A, 0xD3, 0x60, 0x43, 0x60, 0x41, 0x0F, 0x60, 0xEA, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x20, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xBF, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0xF3, 0x60, +- 0x58, 0x4E, 0xD4, 0x78, 0xFF, 0xFF, 0x10, 0x60, 0x02, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, +- 0x04, 0x62, 0x10, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0xF4, 0x60, 0x16, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0xA4, 0x63, 0x66, 0x44, 0xA3, 0xDB, 0x00, 0x60, 0x40, 0x61, +- 0xAE, 0x60, 0x58, 0x4D, 0xC4, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x67, 0xFB, 0x04, 0x64, 0x03, 0xFA, +- 0x1C, 0x60, 0xA4, 0x63, 0xA3, 0xD1, 0x00, 0x64, 0x64, 0x46, 0xA3, 0xDB, 0x00, 0x60, 0x40, 0x65, +- 0x20, 0x44, 0x34, 0x80, 0xF3, 0x60, 0x58, 0x4E, 0xB9, 0x78, 0xFF, 0xFF, 0x10, 0x60, 0x02, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x04, 0x62, 0x00, 0x60, 0x02, 0x64, 0xA2, 0xDB, 0xF4, 0x60, +- 0x16, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x60, 0xAA, 0x62, 0x1A, 0x60, +- 0xBA, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x10, 0x60, 0x02, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x5A, 0xDB, 0xFF, 0x60, 0x9F, 0x65, 0x20, 0x44, 0x24, 0x80, 0x2F, 0x58, +- 0xFF, 0xFF, 0x10, 0x60, 0x02, 0x62, 0xA2, 0xD1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- +-}; /* fw_image_4_data */ +- +-static const CFG_IDENTITY_STRCT fw_image_infoidentity[] = { +- { +- sizeof( CFG_IDENTITY_STRCT ) / sizeof(hcf_16) - 1, +- CFG_FW_IDENTITY, +- COMP_ID_FW_STA, +- 3, //Variant +- 2, //Major +- 36 //Minor +- }, +- { 0000, 0000, 0000, 0000, 0000, 0000 } //endsentinel +-}; +- +-static const CFG_PROG_STRCT fw_image_code[] = { +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, // mode +- 0x0186, // sizeof(fw_image_1_data), +- 0x00000060, // Target address in NIC Memory +- 0x0000, // CRC: yes/no TYPE: primary/station/tertiary +- (hcf_8 FAR *) fw_image_1_data +- }, +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, // mode +- 0x2518, // sizeof(fw_image_2_data), +- 0x00000C16, // Target address in NIC Memory +- 0x0000, // CRC: yes/no TYPE: primary/station/tertiary +- (hcf_8 FAR *) fw_image_2_data +- }, +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, // mode +- 0x3daa, // sizeof(fw_image_3_data), +- 0x001E312E, // Target address in NIC Memory +- 0x0000, // CRC: yes/no TYPE: primary/station/tertiary +- (hcf_8 FAR *) fw_image_3_data +- }, +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, // mode +- 0xaa66, // sizeof(fw_image_4_data), +- 0x001F4000, // Target address in NIC Memory +- 0x0000, // CRC: yes/no TYPE: primary/station/tertiary +- (hcf_8 FAR *) fw_image_4_data +- }, +- { +- 5, +- CFG_PROG, +- CFG_PROG_STOP, // mode +- 0000, +- 0x000F368E, // Start execution address +- }, +- { 0000, 0000, 0000, 0000, 00000000, 0000, 00000000} +-}; +- +-static const CFG_RANGE20_STRCT fw_image_infocompat[] = { +- { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), +- CFG_FW_SUP_RANGE, +- COMP_ROLE_SUPL, +- COMP_ID_STA, +- { +- { 2, 2, 5 } //variant, bottom, top +- } +- }, +- { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), +- CFG_MFI_ACT_RANGES_STA, +- COMP_ROLE_ACT, +- COMP_ID_MFI, +- { +- { 4, 6, 7 }, //variant, bottom, top +- { 5, 6, 7 }, //variant, bottom, top +- { 6, 6, 7 } //variant, bottom, top +- } +- }, +- { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), +- CFG_CFI_ACT_RANGES_STA, +- COMP_ROLE_ACT, +- COMP_ID_CFI, +- { +- { 2, 1, 2 } //variant, bottom, top +- } +- }, +- { 0000, 0000, 0000, 0000, { { 0000, 0000, 0000 } } } //endsentinel +-}; +- +-memimage fw_image = { +- "FUPU7D37dhfwci\001C", //signature, , C/Bin type +- (CFG_PROG_STRCT *) fw_image_code, +- 0x000F368E, +- 00000000, //(dummy) pdaplug +- 00000000, //(dummy) priplug +- (CFG_RANGE20_STRCT *) fw_image_infocompat, +- (CFG_IDENTITY_STRCT *) fw_image_infoidentity, +-}; +- +diff --git a/drivers/staging/wlags49_h2/sta_h25.c b/drivers/staging/wlags49_h2/sta_h25.c +deleted file mode 100644 +index 86ca1cd..0000000 +--- a/drivers/staging/wlags49_h2/sta_h25.c ++++ /dev/null +@@ -1,5255 +0,0 @@ +-/* +- * File: sta_h54.136 +- * +- * Abstract: This file contains memory image 'fw_image'. +- * +- * Contents: Total size of the memory image: 81742 bytes. +- * Total number of blocks: 4 blocks. +- * Block 1 : load address 00000060, 388 bytes. +- * Block 2 : load address 00000C16, 11278 bytes. +- * Block 3 : load address 001E3824, 21726 bytes. +- * Block 4 : load address 001F4000, 48350 bytes. +- * +- * Identity: component id: 31 (variant 4) version 1.36 +- * +- * Compatibility: +- * supplying interface 4 (variant 4) : 1 - 2 +- * acting on interface 1 (variant 7) : 3 - 3 +- * acting on interface 1 (variant 8) : 1 - 1 +- * acting on interface 2 (variant 4) : 1 - 2 +- * +- * Generated: by g:\fw\fupu3.exe version 4.26 +- * +- * Commandline: g:\fw\fupu3.exe /f=4 /n=fw_image /i=r4013600.hex +- */ +- +- +-#include "hcfcfg.h" // to get hcf_16 etc defined as well as +- // possible settings which inluence mdd.h or dhf.h +-#include "mdd.h" //to get COMP_ID_STA etc defined +-#include "dhf.h" //used to be "fhfmem.h", to get memblock,plugrecord, +- +-static const hcf_8 fw_image_1_data[] = { +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDA, 0x0C, 0x00, 0x00, +- 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x65, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x1B, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x1B, 0xB2, 0x1B, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, +- 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0xFF, 0x07, +- 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x10, 0x27, 0x10, 0x27, 0x14, 0x00, 0xD0, 0x07, 0xD0, 0x07, +- 0x10, 0x27, 0x2F, 0x00, 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x02, 0x00, 0x02, 0x00, 0x10, 0x27, +- 0x05, 0x00, 0x00, 0x02, 0x00, 0x02, 0x13, 0x00, 0x07, 0x00, 0x03, 0x00, 0x32, 0x00, 0x02, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x09, 0x2B, 0x09, 0x2B, 0x09, 0xFF, 0x0F, 0xF0, 0x0F, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x40, 0x00, 0x32, 0x00, 0x32, 0x00, 0x0A, 0x00, +- 0x02, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, +- +-}; /* fw_image_1_data */ +- +-static const hcf_8 fw_image_2_data[] = { +- 0xF4, 0xA3, 0x00, 0x16, 0x08, 0x40, 0x0F, 0xD2, 0xE1, 0x28, 0xA5, 0x7C, 0x50, 0x30, 0xF1, 0x84, +- 0x44, 0x08, 0xAB, 0xAE, 0xA5, 0xB8, 0xFC, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, +- 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x84, 0xF8, 0x99, 0xEE, +- 0x8D, 0xF6, 0x0D, 0xFF, 0xBD, 0xD6, 0xB1, 0xDE, 0x54, 0x91, 0x50, 0x60, 0x03, 0x02, 0xA9, 0xCE, +- 0x7D, 0x56, 0x19, 0xE7, 0x62, 0xB5, 0xE6, 0x4D, 0x9A, 0xEC, 0x45, 0x8F, 0x9D, 0x1F, 0x40, 0x89, +- 0x87, 0xFA, 0x15, 0xEF, 0xEB, 0xB2, 0xC9, 0x8E, 0x0B, 0xFB, 0xEC, 0x41, 0x67, 0xB3, 0xFD, 0x5F, +- 0xEA, 0x45, 0xBF, 0x23, 0xF7, 0x53, 0x96, 0xE4, 0x5B, 0x9B, 0xC2, 0x75, 0x1C, 0xE1, 0xAE, 0x3D, +- 0x6A, 0x4C, 0x5A, 0x6C, 0x41, 0x7E, 0x02, 0xF5, 0x4F, 0x83, 0x5C, 0x68, 0xF4, 0x51, 0x34, 0xD1, +- 0x08, 0xF9, 0x93, 0xE2, 0x73, 0xAB, 0x53, 0x62, 0x3F, 0x2A, 0x0C, 0x08, 0x52, 0x95, 0x65, 0x46, +- 0x5E, 0x9D, 0x28, 0x30, 0xA1, 0x37, 0x0F, 0x0A, 0xB5, 0x2F, 0x09, 0x0E, 0x36, 0x24, 0x9B, 0x1B, +- 0x3D, 0xDF, 0x26, 0xCD, 0x69, 0x4E, 0xCD, 0x7F, 0x9F, 0xEA, 0x1B, 0x12, 0x9E, 0x1D, 0x74, 0x58, +- 0x2E, 0x34, 0x2D, 0x36, 0xB2, 0xDC, 0xEE, 0xB4, 0xFB, 0x5B, 0xF6, 0xA4, 0x4D, 0x76, 0x61, 0xB7, +- 0xCE, 0x7D, 0x7B, 0x52, 0x3E, 0xDD, 0x71, 0x5E, 0x97, 0x13, 0xF5, 0xA6, 0x68, 0xB9, 0x00, 0x00, +- 0x2C, 0xC1, 0x60, 0x40, 0x1F, 0xE3, 0xC8, 0x79, 0xED, 0xB6, 0xBE, 0xD4, 0x46, 0x8D, 0xD9, 0x67, +- 0x4B, 0x72, 0xDE, 0x94, 0xD4, 0x98, 0xE8, 0xB0, 0x4A, 0x85, 0x6B, 0xBB, 0x2A, 0xC5, 0xE5, 0x4F, +- 0x16, 0xED, 0xC5, 0x86, 0xD7, 0x9A, 0x55, 0x66, 0x94, 0x11, 0xCF, 0x8A, 0x10, 0xE9, 0x06, 0x04, +- 0x81, 0xFE, 0xF0, 0xA0, 0x44, 0x78, 0xBA, 0x25, 0xE3, 0x4B, 0xF3, 0xA2, 0xFE, 0x5D, 0xC0, 0x80, +- 0x8A, 0x05, 0xAD, 0x3F, 0xBC, 0x21, 0x48, 0x70, 0x04, 0xF1, 0xDF, 0x63, 0xC1, 0x77, 0x75, 0xAF, +- 0x63, 0x42, 0x30, 0x20, 0x1A, 0xE5, 0x0E, 0xFD, 0x6D, 0xBF, 0x4C, 0x81, 0x14, 0x18, 0x35, 0x26, +- 0x2F, 0xC3, 0xE1, 0xBE, 0xA2, 0x35, 0xCC, 0x88, 0x39, 0x2E, 0x57, 0x93, 0xF2, 0x55, 0x82, 0xFC, +- 0x47, 0x7A, 0xAC, 0xC8, 0xE7, 0xBA, 0x2B, 0x32, 0x95, 0xE6, 0xA0, 0xC0, 0x98, 0x19, 0xD1, 0x9E, +- 0x7F, 0xA3, 0x66, 0x44, 0x7E, 0x54, 0xAB, 0x3B, 0x83, 0x0B, 0xCA, 0x8C, 0x29, 0xC7, 0xD3, 0x6B, +- 0x3C, 0x28, 0x79, 0xA7, 0xE2, 0xBC, 0x1D, 0x16, 0x76, 0xAD, 0x3B, 0xDB, 0x56, 0x64, 0x4E, 0x74, +- 0x1E, 0x14, 0xDB, 0x92, 0x0A, 0x0C, 0x6C, 0x48, 0xE4, 0xB8, 0x5D, 0x9F, 0x6E, 0xBD, 0xEF, 0x43, +- 0xA6, 0xC4, 0xA8, 0x39, 0xA4, 0x31, 0x37, 0xD3, 0x8B, 0xF2, 0x32, 0xD5, 0x43, 0x8B, 0x59, 0x6E, +- 0xB7, 0xDA, 0x8C, 0x01, 0x64, 0xB1, 0xD2, 0x9C, 0xE0, 0x49, 0xB4, 0xD8, 0xFA, 0xAC, 0x07, 0xF3, +- 0x25, 0xCF, 0xAF, 0xCA, 0x8E, 0xF4, 0xE9, 0x47, 0x18, 0x10, 0xD5, 0x6F, 0x88, 0xF0, 0x6F, 0x4A, +- 0x72, 0x5C, 0x24, 0x38, 0xF1, 0x57, 0xC7, 0x73, 0x51, 0x97, 0x23, 0xCB, 0x7C, 0xA1, 0x9C, 0xE8, +- 0x21, 0x3E, 0xDD, 0x96, 0xDC, 0x61, 0x86, 0x0D, 0x85, 0x0F, 0x90, 0xE0, 0x42, 0x7C, 0xC4, 0x71, +- 0xAA, 0xCC, 0xD8, 0x90, 0x05, 0x06, 0x01, 0xF7, 0x12, 0x1C, 0xA3, 0xC2, 0x5F, 0x6A, 0xF9, 0xAE, +- 0xD0, 0x69, 0x91, 0x17, 0x58, 0x99, 0x27, 0x3A, 0xB9, 0x27, 0x38, 0xD9, 0x13, 0xEB, 0xB3, 0x2B, +- 0x33, 0x22, 0xBB, 0xD2, 0x70, 0xA9, 0x89, 0x07, 0xA7, 0x33, 0xB6, 0x2D, 0x22, 0x3C, 0x92, 0x15, +- 0x20, 0xC9, 0x49, 0x87, 0xFF, 0xAA, 0x78, 0x50, 0x7A, 0xA5, 0x8F, 0x03, 0xF8, 0x59, 0x80, 0x09, +- 0x17, 0x1A, 0xDA, 0x65, 0x31, 0xD7, 0xC6, 0x84, 0xB8, 0xD0, 0xC3, 0x82, 0xB0, 0x29, 0x77, 0x5A, +- 0x11, 0x1E, 0xCB, 0x7B, 0xFC, 0xA8, 0xD6, 0x6D, 0x3A, 0x2C, 0x00, 0x30, 0x00, 0x31, 0x00, 0x33, +- 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x38, 0x00, 0x3A, 0x00, 0x3B, +- 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x3F, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x28, 0x10, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x02, 0x14, 0x05, 0x32, 0x0B, 0x37, 0x08, 0x50, 0x0B, 0x6E, +- 0x02, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x16, 0x00, 0x0C, 0x00, 0x12, 0x00, 0x18, 0x00, 0x24, 0x00, +- 0x30, 0x00, 0x48, 0x00, 0x60, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x39, 0x00, 0x20, 0x00, 0x39, 0x00, 0x39, 0x00, 0x20, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, +- 0x3E, 0x11, 0xF6, 0x10, 0x38, 0x11, 0xFC, 0x10, 0x32, 0x11, 0x02, 0x11, 0x2C, 0x11, 0x08, 0x11, +- 0x26, 0x11, 0x0E, 0x11, 0x20, 0x11, 0x14, 0x11, 0x1A, 0x11, 0x07, 0x01, 0x00, 0x00, 0x16, 0x22, +- 0x00, 0x04, 0x08, 0x01, 0x00, 0x00, 0x16, 0x26, 0x00, 0x04, 0x09, 0x01, 0x00, 0x00, 0x16, 0x2A, +- 0x00, 0x04, 0x0A, 0x01, 0x00, 0x00, 0x16, 0x2E, 0x00, 0x04, 0x0B, 0x01, 0x00, 0x00, 0x10, 0x24, +- 0x04, 0x04, 0x0C, 0x01, 0x00, 0x00, 0x10, 0x28, 0x04, 0x04, 0x0D, 0x01, 0x00, 0x00, 0x10, 0x2C, +- 0x04, 0x04, 0x0E, 0x01, 0x00, 0x00, 0x10, 0x30, 0x04, 0x04, 0x0F, 0x01, 0x00, 0x00, 0x14, 0x34, +- 0x08, 0x84, 0x10, 0x01, 0x00, 0x00, 0x14, 0x38, 0x08, 0x84, 0x11, 0x01, 0x00, 0x00, 0x14, 0x3C, +- 0x08, 0x84, 0x12, 0x01, 0x00, 0x00, 0x14, 0x40, 0x08, 0x84, 0x13, 0x01, 0x00, 0x00, 0x17, 0x64, +- 0x0C, 0x8B, 0x14, 0x01, 0x00, 0x00, 0x17, 0x68, 0x0C, 0x8B, 0x15, 0x01, 0x00, 0x00, 0x17, 0x6C, +- 0x0C, 0x8B, 0x16, 0x01, 0x00, 0x00, 0x17, 0x70, 0x0C, 0x8B, 0x17, 0x01, 0x00, 0x00, 0x17, 0x74, +- 0x0C, 0x8B, 0x18, 0x01, 0x00, 0x00, 0x17, 0x78, 0x0C, 0x8B, 0x19, 0x01, 0x00, 0x00, 0x17, 0x7C, +- 0x0C, 0x8B, 0x1A, 0x01, 0x00, 0x00, 0x17, 0x80, 0x0C, 0x8B, 0x1B, 0x01, 0x00, 0x00, 0x17, 0x84, +- 0x0C, 0x8B, 0x1C, 0x01, 0x00, 0x00, 0x17, 0x88, 0x0C, 0x8B, 0x1D, 0x01, 0x00, 0x00, 0x17, 0x8C, +- 0x0C, 0x8B, 0x1E, 0x01, 0x00, 0x00, 0x0E, 0x95, 0x17, 0x04, 0x1F, 0x01, 0x00, 0x00, 0x0E, 0x99, +- 0x17, 0x04, 0x20, 0x01, 0x00, 0x00, 0x0E, 0x9D, 0x17, 0x04, 0x21, 0x01, 0x00, 0x00, 0x0E, 0xA1, +- 0x17, 0x04, 0x22, 0x01, 0x00, 0x00, 0x0E, 0xA5, 0x00, 0x00, 0x60, 0x11, 0x80, 0x11, 0xA0, 0x11, +- 0xC0, 0x11, 0x18, 0x12, 0x68, 0x11, 0x88, 0x11, 0xA8, 0x11, 0xC8, 0x11, 0x20, 0x12, 0x70, 0x11, +- 0x90, 0x11, 0xB0, 0x11, 0xD0, 0x11, 0x28, 0x12, 0x78, 0x11, 0x98, 0x11, 0xB8, 0x11, 0xD8, 0x11, +- 0x30, 0x12, 0xE0, 0x11, 0xE8, 0x11, 0xF0, 0x11, 0xF8, 0x11, 0x00, 0x12, 0x08, 0x12, 0x10, 0x12, +- 0x38, 0x12, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x0A, 0x0A, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x1E, 0x1E, 0x1E, 0x1E, +- 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x10, 0x10, +- 0x10, 0x10, 0x17, 0x17, 0x17, 0x17, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +- 0x14, 0x14, 0x14, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x11, 0x11, 0x11, 0x11, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, +- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x16, 0x16, +- 0x16, 0x16, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, +- 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0A, +- 0x0A, 0x0A, 0x0A, 0x7F, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +- 0x14, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x10, 0x10, 0x10, 0x10, 0x7F, 0x14, 0x14, +- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x0A, 0x0A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +- 0x14, 0x14, 0x14, 0x14, 0x14, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x9D, 0x9D, 0xA1, 0xB4, +- 0x10, 0x10, 0x00, 0x9D, 0x08, 0x02, 0x06, 0x00, 0xA5, 0xA5, 0xAA, 0xB4, 0x10, 0x10, 0x00, 0xA2, +- 0x15, 0x05, 0x07, 0x00, 0xAA, 0xAA, 0xB4, 0xB4, 0x10, 0x10, 0x00, 0xA7, 0x1C, 0x0A, 0x08, 0x00, +- 0xB7, 0xB7, 0xC1, 0xC1, 0x10, 0x10, 0x00, 0xB4, 0x29, 0x17, 0x08, 0x00, 0xBD, 0xBD, 0xC7, 0xC7, +- 0x10, 0x10, 0x00, 0xBA, 0x2F, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0x1F, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x42, 0x2A, 0x5B, 0x2A, 0x7E, 0x2A, 0x71, 0x30, 0xEE, 0x29, 0x88, 0x30, 0xB8, 0x2A, +- 0x9F, 0x30, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0x21, 0x35, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, +- 0xEE, 0x29, 0xEE, 0x29, 0x93, 0x2C, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, +- 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, +- 0xEE, 0x29, 0xEE, 0x29, 0xDE, 0x2C, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, +- 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, +- 0xEE, 0x29, 0x61, 0x2C, 0x7C, 0x2C, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, 0xEE, 0x29, +- 0xEE, 0x29, 0xE1, 0x27, 0xD7, 0x2A, 0xEA, 0x2A, 0x9A, 0x2B, 0x9E, 0x2B, 0xEE, 0x29, 0xEE, 0x29, +- 0x4D, 0x2C, 0xA1, 0xF2, 0x62, 0xF2, 0x00, 0x00, 0x99, 0xF2, 0xEE, 0xF2, 0x12, 0xF3, 0x48, 0xF3, +- 0x00, 0x00, 0x00, 0x00, 0x70, 0x2A, 0x94, 0x2A, 0x00, 0x00, 0x67, 0x30, 0x7E, 0x30, 0x95, 0x30, +- 0xAF, 0x30, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0x45, 0x2D, 0xF7, 0x2F, 0x5A, 0x00, 0x02, 0x00, +- 0xF9, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0xFC, 0x00, 0x02, 0x00, 0xF7, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, +- 0xAA, 0x2D, 0x06, 0x00, 0xF0, 0xFF, 0x45, 0x2D, 0x22, 0x2D, 0x00, 0x00, 0x00, 0x02, 0xF6, 0xFF, +- 0x45, 0x2D, 0x5B, 0x2D, 0x6C, 0x00, 0x02, 0x00, 0xF4, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0xA6, 0x01, +- 0x02, 0x00, 0xF5, 0xFF, 0x45, 0x2D, 0x00, 0x30, 0x9C, 0x2D, 0x02, 0x00, 0xED, 0xFF, 0x45, 0x2D, +- 0x12, 0x30, 0x98, 0x32, 0x02, 0x00, 0xEC, 0xFF, 0x45, 0x2D, 0x40, 0x30, 0x9A, 0x32, 0x02, 0x00, +- 0xEB, 0xFF, 0x45, 0x2D, 0x46, 0x30, 0x9C, 0x32, 0x02, 0x00, 0xEE, 0xFF, 0x45, 0x2D, 0x4C, 0x30, +- 0x12, 0x33, 0x02, 0x00, 0xDA, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0xF2, 0x13, 0x0C, 0x00, 0xEA, 0xFF, +- 0x45, 0x2D, 0x22, 0x2D, 0x4C, 0x33, 0x06, 0x00, 0xE9, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x52, 0x33, +- 0x02, 0x00, 0xE8, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x54, 0x33, 0x02, 0x00, 0xE7, 0xFF, 0x45, 0x2D, +- 0x5B, 0x2D, 0x56, 0x33, 0x02, 0x00, 0xE6, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x58, 0x33, 0x02, 0x00, +- 0xE5, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x5A, 0x33, 0x10, 0x00, 0xE4, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, +- 0x6A, 0x33, 0x18, 0x00, 0xDB, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x82, 0x33, 0x02, 0x00, 0xDC, 0xFF, +- 0x45, 0x2D, 0x5B, 0x2D, 0x84, 0x33, 0x02, 0x00, 0xE1, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x5A, 0x34, +- 0x02, 0x00, 0xE0, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0x58, 0x34, 0x02, 0x00, 0xE3, 0xFF, 0x45, 0x2D, +- 0x5B, 0x2D, 0x3C, 0x34, 0x02, 0x00, 0xE2, 0xFF, 0x93, 0x2D, 0x22, 0x2D, 0xF2, 0x33, 0x24, 0x00, +- 0x03, 0xFC, 0x45, 0x2D, 0x01, 0x2F, 0x8C, 0x32, 0x02, 0x00, 0x04, 0xFC, 0x45, 0x2D, 0x55, 0x2D, +- 0xB4, 0x2D, 0x22, 0x00, 0x06, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x9A, 0x2D, 0x02, 0x00, 0x07, 0xFC, +- 0x45, 0x2D, 0x5B, 0x2D, 0xF8, 0x2D, 0x02, 0x00, 0x0E, 0xFC, 0x45, 0x2D, 0x2A, 0x2F, 0x02, 0x2E, +- 0x22, 0x00, 0xB1, 0xFC, 0x45, 0x2D, 0x39, 0x31, 0x00, 0x2F, 0x02, 0x00, 0x20, 0xFC, 0x45, 0x2D, +- 0x5B, 0x2D, 0x28, 0x2E, 0x02, 0x00, 0x25, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x34, 0x2E, 0x02, 0x00, +- 0x26, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x36, 0x2E, 0x02, 0x00, 0x27, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, +- 0x38, 0x2E, 0x02, 0x00, 0xB2, 0xFC, 0x45, 0x2D, 0x55, 0x2D, 0x24, 0x2F, 0x22, 0x00, 0xC1, 0xFC, +- 0x45, 0x2D, 0x5B, 0x2D, 0x9E, 0x33, 0x20, 0x00, 0xB0, 0xFC, 0x18, 0x2D, 0x3D, 0x31, 0x00, 0x00, +- 0x00, 0x00, 0xC4, 0xFC, 0x18, 0x2D, 0x57, 0x30, 0x00, 0x00, 0x08, 0x00, 0xC8, 0xFC, 0x18, 0x2D, +- 0x55, 0x30, 0x00, 0x00, 0x08, 0x00, 0xB4, 0xFC, 0x18, 0x2D, 0x71, 0x31, 0x00, 0x00, 0x00, 0x00, +- 0xB6, 0xFC, 0x18, 0x2D, 0x19, 0x32, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xFC, 0x18, 0x2D, 0x43, 0x32, +- 0x00, 0x00, 0x00, 0x00, 0xB8, 0xFC, 0x18, 0x2D, 0x99, 0x32, 0x00, 0x00, 0x00, 0x00, 0xBC, 0xFC, +- 0x18, 0x2D, 0xD2, 0x32, 0x00, 0x00, 0x00, 0x00, 0xBD, 0xFC, 0x18, 0x2D, 0x58, 0x33, 0x00, 0x00, +- 0x00, 0x00, 0xBE, 0xFC, 0x18, 0x2D, 0x82, 0x33, 0x00, 0x00, 0x00, 0x00, 0xBF, 0xFC, 0x18, 0x2D, +- 0xCF, 0x33, 0x00, 0x00, 0x00, 0x00, 0xB3, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xA0, 0x0F, 0x10, 0x00, +- 0xB5, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x38, 0x34, 0x02, 0x00, 0xB9, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, +- 0x3A, 0x34, 0x02, 0x00, 0x90, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0x3E, 0x34, 0x02, 0x00, 0x88, 0xFC, +- 0x45, 0x2D, 0x5B, 0x2D, 0x72, 0x32, 0x04, 0x00, 0x89, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x76, 0x32, +- 0x04, 0x00, 0xC5, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x7A, 0x32, 0x04, 0x00, 0x23, 0xFC, 0x45, 0x2D, +- 0x5B, 0x2D, 0x2E, 0x2E, 0x04, 0x00, 0x2A, 0xFC, 0x45, 0x2D, 0xE9, 0x2D, 0xB0, 0x2D, 0x02, 0x00, +- 0xC7, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0xA0, 0x32, 0x0A, 0x00, 0x29, 0xFC, 0x3C, 0x2E, 0x00, 0x2E, +- 0x00, 0x00, 0x00, 0x00, 0xC2, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x80, 0x32, 0x08, 0x00, 0x32, 0xFC, +- 0x45, 0x2D, 0x5B, 0x2D, 0x98, 0x01, 0x02, 0x00, 0x33, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x9A, 0x01, +- 0x02, 0x00, 0x35, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x88, 0x32, 0x02, 0x00, 0xC7, 0xFC, 0x45, 0x2D, +- 0xD3, 0x2F, 0x8A, 0x32, 0x02, 0x00, 0x00, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xB2, 0x2D, 0x02, 0x00, +- 0x01, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xAA, 0x2D, 0x06, 0x00, 0x02, 0xFC, 0x45, 0x2D, 0xD5, 0x2D, +- 0x02, 0x2F, 0x22, 0x00, 0x05, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xA0, 0x2D, 0x02, 0x00, 0x08, 0xFC, +- 0x45, 0x2D, 0x5B, 0x2D, 0xA4, 0x2D, 0x06, 0x00, 0x09, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xFA, 0x2D, +- 0x02, 0x00, 0x0B, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xFC, 0x2D, 0x02, 0x00, 0x0C, 0xFC, 0x45, 0x2D, +- 0x5B, 0x2D, 0xFE, 0x2D, 0x02, 0x00, 0x0D, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x00, 0x2E, 0x02, 0x00, +- 0x21, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0x2A, 0x2E, 0x02, 0x00, 0x80, 0xFC, 0xB1, 0x2D, 0xC1, 0x2D, +- 0x40, 0x2E, 0xC0, 0x00, 0x81, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, 0xA4, 0x01, 0x02, 0x00, 0x83, 0xFC, +- 0x45, 0x2D, 0x5B, 0x2D, 0xA8, 0x01, 0x02, 0x00, 0x85, 0xFC, 0x45, 0x2D, 0x4A, 0x2F, 0xA0, 0x01, +- 0x02, 0x00, 0x86, 0xFC, 0x45, 0x2D, 0x6E, 0x2F, 0xB0, 0x01, 0x02, 0x00, 0x28, 0xFC, 0x45, 0x2D, +- 0x5B, 0x2D, 0x3A, 0x2E, 0x02, 0x00, 0x90, 0xFC, 0x45, 0x2D, 0x5C, 0x2F, 0xA2, 0x01, 0x02, 0x00, +- 0x87, 0xFC, 0x45, 0x2D, 0x8C, 0x2F, 0x50, 0x2F, 0x22, 0x03, 0x30, 0xFC, 0x45, 0x2D, 0x5B, 0x2D, +- 0x3C, 0x2E, 0x02, 0x00, 0x84, 0xFC, 0x45, 0x2D, 0x92, 0x2F, 0xAC, 0x01, 0x04, 0x00, 0x2B, 0xFC, +- 0x45, 0x2D, 0x5B, 0x2D, 0xE2, 0x37, 0x02, 0x00, 0xF8, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0xDC, 0x37, +- 0x02, 0x00, 0xF3, 0xFF, 0x45, 0x2D, 0x5B, 0x2D, 0xE4, 0x37, 0x02, 0x00, 0x20, 0xFD, 0x76, 0x2D, +- 0x22, 0x2D, 0x5E, 0x40, 0x08, 0x00, 0x21, 0xFD, 0x76, 0x2D, 0x22, 0x2D, 0x62, 0x40, 0x0A, 0x00, +- 0x22, 0xFD, 0x76, 0x2D, 0x22, 0x2D, 0x67, 0x40, 0x16, 0x00, 0x23, 0xFD, 0x76, 0x2D, 0x22, 0x2D, +- 0x72, 0x40, 0x0A, 0x00, 0x45, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0xFC, 0x00, 0x02, 0x00, 0x47, 0xFD, +- 0x45, 0x2D, 0x22, 0x2D, 0x72, 0x01, 0x02, 0x00, 0x48, 0xFD, 0x91, 0x2E, 0x22, 0x2D, 0x98, 0x01, +- 0x02, 0x00, 0x49, 0xFD, 0x91, 0x2E, 0x22, 0x2D, 0x9A, 0x01, 0x02, 0x00, 0x4A, 0xFD, 0x45, 0x2D, +- 0x22, 0x2D, 0x92, 0x01, 0x02, 0x00, 0x4B, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0x94, 0x01, 0x02, 0x00, +- 0x4D, 0xFD, 0x76, 0x2D, 0x22, 0x2D, 0x77, 0x40, 0x0C, 0x00, 0x4F, 0xFD, 0xA5, 0x2E, 0x22, 0x2D, +- 0x90, 0x32, 0x02, 0x00, 0xC2, 0xFD, 0x9B, 0x2E, 0x22, 0x2D, 0x00, 0x00, 0x02, 0x00, 0x40, 0xFD, +- 0x6E, 0x2D, 0x22, 0x2D, 0xB6, 0x01, 0x02, 0x00, 0x24, 0xFD, 0xB5, 0x2E, 0x22, 0x2D, 0x00, 0x00, +- 0x02, 0x00, 0x91, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0xC6, 0x25, 0x02, 0x00, 0x93, 0xFD, 0x45, 0x2D, +- 0x22, 0x2D, 0xCC, 0x25, 0x02, 0x00, 0x8F, 0xFD, 0xD5, 0x2E, 0x22, 0x2D, 0x00, 0x00, 0x08, 0x00, +- 0xC1, 0xFD, 0x00, 0x31, 0x22, 0x2D, 0xFA, 0x00, 0x02, 0x00, 0xC6, 0xFD, 0x45, 0x2D, 0x22, 0x2D, +- 0xF8, 0x37, 0x04, 0x00, 0x25, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0x9E, 0x01, 0x02, 0x00, 0x89, 0xFD, +- 0xB9, 0x30, 0x22, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xFD, 0x93, 0x2D, 0x22, 0x2D, 0x12, 0x34, +- 0x24, 0x00, 0x41, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0xBE, 0x33, 0x22, 0x00, 0x42, 0xFD, 0x45, 0x2D, +- 0x22, 0x2D, 0xFE, 0x00, 0x06, 0x00, 0x43, 0xFD, 0xC2, 0x2E, 0x22, 0x2D, 0x00, 0x00, 0x06, 0x00, +- 0x44, 0xFD, 0xAC, 0x2E, 0x22, 0x2D, 0xB2, 0x01, 0x02, 0x00, 0x46, 0xFD, 0x21, 0x31, 0x22, 0x2D, +- 0x00, 0x00, 0x00, 0x00, 0x4C, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0x46, 0x2F, 0x02, 0x00, 0x50, 0xFD, +- 0x45, 0x2D, 0x22, 0x2D, 0xF2, 0x00, 0x02, 0x00, 0x51, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0xF4, 0x00, +- 0x02, 0x00, 0x52, 0xFD, 0x45, 0x2D, 0x22, 0x2D, 0xC4, 0x01, 0x02, 0x00, 0x8C, 0xFD, 0x38, 0x2D, +- 0x22, 0x2D, 0x98, 0x34, 0x56, 0x00, 0x8D, 0xFD, 0x38, 0x2D, 0x22, 0x2D, 0xF2, 0x34, 0x14, 0x00, +- 0x00, 0xF1, 0x46, 0x00, 0xDC, 0x2C, 0x36, 0x01, 0x01, 0xF1, 0x84, 0x07, 0xDA, 0x2C, 0x38, 0x01, +- 0x00, 0x03, 0xA0, 0x80, 0x1E, 0x00, 0x70, 0x01, 0xFA, 0x00, 0xD4, 0x01, 0xFE, 0x00, 0x3A, 0x01, +- 0xB6, 0x01, 0xCC, 0x2C, 0x54, 0x01, 0xC6, 0x25, 0x20, 0x00, 0x00, 0x00, 0xC0, 0x1D, 0x00, 0x00, +- 0xC4, 0x1F, 0x4E, 0x01, 0x0B, 0x00, 0xB8, 0x00, 0xEC, 0x00, 0x44, 0x00, 0x46, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x1C, 0x09, 0x08, 0x24, 0x28, 0x06, 0x0C, 0x18, 0x08, 0x30, 0x14, 0x0C, +- 0x08, 0x36, 0x10, 0x12, 0x24, 0xB7, 0x97, 0xB6, 0xA3, 0xB7, 0xAC, 0xB7, 0xA8, 0xB6, 0x3E, 0xB7, +- 0x16, 0xB7, 0x79, 0x3E, 0x57, 0x3D, 0x79, 0x3E, 0xF9, 0x3D, 0x5F, 0x3D, 0x52, 0x3D, 0x33, 0x3E, +- 0x55, 0x3E, 0x6A, 0x3E, 0xAC, 0x3E, 0xD8, 0x3E, 0xF8, 0x3D, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, +- 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, 0x22, 0x46, +- 0x23, 0x46, 0x23, 0x46, 0x23, 0x46, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, +- 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, 0x1C, 0x47, +- 0x1D, 0x47, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, +- 0x5A, 0x48, 0x9A, 0x48, 0xDA, 0x48, 0x1A, 0x48, 0x5A, 0x48, 0x9A, 0x48, 0x33, 0x48, 0x78, 0x49, +- 0x78, 0x49, 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, 0x79, 0x49, 0x7A, 0x49, 0x7A, 0x49, 0x7A, 0x49, +- 0x7A, 0x49, 0x7B, 0x49, 0x7B, 0x49, 0x7B, 0x49, 0x7C, 0x49, 0xD8, 0x03, 0xDC, 0x03, 0xE0, 0x03, +- 0xE4, 0x03, 0xF0, 0x03, 0xF4, 0x03, 0xF8, 0x03, 0x0A, 0x04, 0x0E, 0x04, 0x12, 0x04, 0x16, 0x04, +- 0x0C, 0x04, 0x10, 0x04, 0x14, 0x04, 0x18, 0x04, 0x1C, 0x04, 0x20, 0x04, 0x24, 0x04, 0x28, 0x04, +- 0x4C, 0x04, 0x50, 0x04, 0x54, 0x04, 0x58, 0x04, 0x5C, 0x04, 0x60, 0x04, 0x64, 0x04, 0x68, 0x04, +- 0x6C, 0x04, 0x70, 0x04, 0x74, 0x04, 0x7D, 0x04, 0x81, 0x04, 0x85, 0x04, 0x89, 0x04, 0x8D, 0x04, +- 0x10, 0x00, 0x8E, 0x19, 0xAC, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3C, 0x0C, 0x00, 0x00, +- 0xFF, 0x3F, 0x44, 0x04, 0x00, 0x00, 0xD3, 0x22, 0x44, 0x04, 0x9C, 0x02, 0xCB, 0x54, 0x44, 0x04, +- 0x00, 0x00, 0x01, 0x00, 0x44, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0C, 0x71, 0x00, 0x30, 0x50, +- 0x20, 0x00, 0x80, 0xBF, 0x1F, 0xA6, 0x28, 0x00, 0x0B, 0x02, 0x60, 0x84, 0x4C, 0x00, 0x02, 0x00, +- 0x4B, 0x1C, 0x98, 0x00, 0x00, 0x00, 0x20, 0x0B, 0x34, 0x04, 0xFD, 0x34, 0x34, 0x00, 0x38, 0x04, +- 0xFD, 0x34, 0x34, 0x00, 0x3C, 0x04, 0x01, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x52, 0x14, 0x00, +- 0x04, 0x08, 0x0E, 0x32, 0x00, 0xA6, 0x10, 0x08, 0xC4, 0x03, 0x50, 0x60, 0x18, 0x08, 0xF0, 0x3F, +- 0xFC, 0x01, 0x10, 0x0C, 0x00, 0x00, 0x80, 0x04, 0x14, 0x0C, 0x00, 0x00, 0x00, 0x41, 0x20, 0x0C, +- 0xB0, 0x00, 0xB0, 0xB8, 0x24, 0x0C, 0x00, 0x00, 0xAB, 0x05, 0x2C, 0x0C, 0x80, 0x05, 0x00, 0xFF, +- 0x30, 0x0C, 0x00, 0x00, 0xB0, 0x04, 0x34, 0x0C, 0x03, 0x00, 0x00, 0xE8, 0x44, 0x0C, 0x04, 0x00, +- 0xFF, 0x0F, 0x00, 0x10, 0x2E, 0x00, 0x0C, 0xE3, 0x44, 0x04, 0x00, 0x00, 0x01, 0x04, 0x44, 0x04, +- 0x00, 0x00, 0x01, 0x01, 0x44, 0x04, 0x00, 0x00, 0x01, 0x00, 0x44, 0x04, 0x00, 0x00, 0x01, 0x04, +- 0x44, 0x04, 0x00, 0x00, 0x80, 0x03, 0x48, 0x0C, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x04, 0x08, 0x48, +- 0x00, 0x00, 0x04, 0x04, 0x08, 0x40, 0x00, 0x00, 0x00, 0x0C, 0x71, 0x00, 0x30, 0x30, 0x00, 0x00, +- 0x5E, 0x40, 0x01, 0x00, 0x18, 0x00, 0x36, 0xC0, 0xE8, 0x0E, 0x1C, 0x00, 0x78, 0xC8, 0xA5, 0x40, +- 0x24, 0x00, 0x9E, 0xB0, 0xB9, 0x95, 0x08, 0x08, 0x00, 0xEA, 0x40, 0x01, 0x0C, 0x08, 0x00, 0xEA, +- 0x00, 0x00, 0x1C, 0x08, 0x00, 0x00, 0x42, 0x07, 0x20, 0x08, 0x7B, 0x00, 0xD4, 0x09, 0x2C, 0x04, +- 0x14, 0x00, 0x50, 0x14, 0x30, 0x04, 0x28, 0x0F, 0x28, 0x7F, 0x18, 0x08, 0x20, 0x00, 0xFC, 0x01, +- 0x04, 0x10, 0x69, 0x00, 0xFD, 0xC3, 0x08, 0x10, 0x69, 0x00, 0xFD, 0xC3, 0x08, 0x0C, 0x00, 0x00, +- 0x00, 0x00, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0C, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x04, +- 0x08, 0x48, 0x02, 0x00, 0x00, 0x00, 0x5E, 0x48, 0x00, 0x00, 0x04, 0x04, 0x08, 0x40, 0x02, 0x00, +- 0x00, 0x0C, 0x71, 0x00, 0x30, 0x50, 0x00, 0x00, 0x5E, 0x48, 0x01, 0x00, 0x18, 0x00, 0x3A, 0xC0, +- 0xE8, 0x04, 0x1C, 0x00, 0x78, 0xD0, 0xA5, 0x40, 0x24, 0x00, 0x9E, 0xB0, 0xB9, 0x85, 0x2C, 0x04, +- 0x14, 0x00, 0x50, 0x14, 0x30, 0x04, 0x28, 0x0F, 0x28, 0x7F, 0x08, 0x08, 0x00, 0xEA, 0x40, 0x01, +- 0x0C, 0x08, 0x00, 0xEA, 0x00, 0x00, 0x1C, 0x08, 0x00, 0x00, 0x42, 0x07, 0x20, 0x08, 0x7B, 0x00, +- 0xD4, 0x09, 0x18, 0x08, 0xF0, 0x3F, 0xFC, 0x01, 0x04, 0x10, 0x69, 0x00, 0xDD, 0xCD, 0x08, 0x10, +- 0x69, 0x00, 0xDD, 0xCD, 0x08, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x00, +- 0x08, 0x04, 0x40, 0x01, 0x41, 0x01, 0x0C, 0x04, 0x40, 0x04, 0x41, 0x04, 0x10, 0x04, 0xD6, 0x08, +- 0x56, 0x0A, 0x14, 0x04, 0x42, 0x02, 0x56, 0x0A, 0x18, 0x04, 0x56, 0x0A, 0x40, 0x02, 0x1C, 0x04, +- 0x42, 0x0A, 0x42, 0x2A, 0x20, 0x04, 0xC2, 0x00, 0xD6, 0x08, 0x24, 0x04, 0xD6, 0x08, 0xC0, 0x00, +- 0x28, 0x04, 0xC2, 0x08, 0xC2, 0x28, 0x08, 0x04, 0x40, 0x01, 0x41, 0x01, 0x0C, 0x04, 0x00, 0x01, +- 0x01, 0x01, 0x10, 0x04, 0x56, 0x0A, 0x56, 0x0A, 0x14, 0x04, 0x42, 0x02, 0x56, 0x0A, 0x18, 0x04, +- 0x56, 0x0A, 0x40, 0x02, 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x20, 0x04, 0x42, 0x02, 0x56, 0x0A, +- 0x24, 0x04, 0x56, 0x0A, 0x40, 0x02, 0x28, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x08, 0x04, 0x40, 0x01, +- 0x41, 0x01, 0x0C, 0x04, 0x40, 0x04, 0x41, 0x04, 0x10, 0x04, 0xCE, 0x08, 0x4E, 0x0A, 0x14, 0x04, +- 0x42, 0x02, 0x4E, 0x0A, 0x18, 0x04, 0x4E, 0x0A, 0x40, 0x02, 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, +- 0x20, 0x04, 0xC2, 0x00, 0xCE, 0x08, 0x24, 0x04, 0xCE, 0x08, 0xC0, 0x00, 0x28, 0x04, 0xC2, 0x08, +- 0xC2, 0x28, 0x08, 0x04, 0x40, 0x01, 0x41, 0x01, 0x0C, 0x04, 0x00, 0x01, 0x01, 0x01, 0x10, 0x04, +- 0x4E, 0x0A, 0x4E, 0x0A, 0x14, 0x04, 0x42, 0x02, 0x4E, 0x0A, 0x18, 0x04, 0x4E, 0x0A, 0x40, 0x02, +- 0x1C, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x20, 0x04, 0x42, 0x02, 0x4E, 0x0A, 0x24, 0x04, 0x4E, 0x0A, +- 0x40, 0x02, 0x28, 0x04, 0x42, 0x0A, 0x42, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, +- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x05, 0x00, 0xA0, 0x16, 0xA0, 0x16, +- 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, +- 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, +- 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x16, +- 0xA0, 0x16, 0xA0, 0x16, 0xA0, 0x17, 0xA0, 0x17, 0xA0, 0x17, 0xA0, 0x18, 0xFF, 0x06, 0xFF, 0x06, +- 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, +- 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, +- 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, +- 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0xFF, 0x06, 0x00, 0x00, 0x65, 0x00, +- 0x65, 0x00, 0x65, 0x00, 0x65, 0x00, 0x5D, 0x00, 0x52, 0x00, 0x48, 0x00, 0x40, 0x00, 0x38, 0x00, +- 0x31, 0x00, 0x2C, 0x00, 0x27, 0x00, 0x23, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x65, 0x00, 0x65, 0x00, +- 0x65, 0x00, 0x65, 0x00, 0x5D, 0x00, 0x52, 0x00, 0x48, 0x00, 0x40, 0x00, 0x38, 0x00, 0x31, 0x00, +- 0x2C, 0x00, 0x27, 0x00, 0x23, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, +- 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, +- 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, +- 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x15, 0x00, 0x6E, 0x6F, 0x6E, 0x2D, +- 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x53, 0x53, 0x49, 0x44, 0x20, 0x21, +- 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x09, +- 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x48, 0x45, 0x52, 0x4D, 0x45, 0x53, +- 0x20, 0x32, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, +- 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x15, 0x00, +- 0x6E, 0x6F, 0x6E, 0x2D, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x53, 0x53, +- 0x49, 0x44, 0x20, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x01, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x48, 0x45, +- 0x52, 0x4D, 0x45, 0x53, 0x20, 0x32, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, +- 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x69, +- 0x72, 0x73, 0x74, 0x20, 0x57, 0x61, 0x76, 0x65, 0x4C, 0x41, 0x4E, 0x20, 0x49, 0x49, 0x20, 0x53, +- 0x53, 0x49, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +- 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xF0, 0x0F, +- 0x0F, 0x00, 0x50, 0x01, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, +- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, +- 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x24, 0x00, 0xFF, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0A, 0x00, +- 0x0B, 0x00, 0x0B, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x02, 0x01, +- 0x02, 0x04, 0x0B, 0x16, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x82, 0x84, 0x8B, 0x96, 0x00, 0x00, +- 0x00, 0x00, 0x1C, 0x85, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, +- 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x1B, 0x00, 0x17, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0B, 0x00, +- 0x0B, 0x00, 0x09, 0x00, 0x17, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0D, 0x00, 0x0B, 0x00, 0x09, 0x00, +- 0x08, 0x00, 0x07, 0x00, 0x0D, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x05, 0x00, 0x05, 0x00, +- 0xD8, 0x0C, 0xC0, 0x08, 0x90, 0x0D, 0x60, 0x09, 0x48, 0x0E, 0x30, 0x0A, 0x24, 0x0F, 0x18, 0x0B, +- 0x0B, 0x6E, 0x0B, 0x37, 0x02, 0x14, 0x01, 0x0A, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, +- 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x43, 0x75, 0x72, 0x72, 0x65, +- 0x6E, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x53, 0x65, 0x74, 0x20, 0x49, +- 0x64, 0x65, 0x6E, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x01, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xDD, 0x00, 0x50, +- 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x05, 0x02, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x50, +- 0xF2, 0x04, 0x02, 0x00, 0x00, 0x50, 0xF2, 0x00, 0x00, 0x50, 0xF2, 0x01, 0x06, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x15, 0x00, 0x14, 0x00, 0x15, 0x00, 0x36, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, +- 0x11, 0x00, 0x36, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x01, 0x00, 0x10, 0x00, 0xBE, 0x33, 0x1E, 0x33, 0xCC, 0x35, 0xD0, 0x35, 0xD4, 0x35, 0x12, 0x34, +- 0x04, 0x36, 0x08, 0x36, 0xF2, 0x33, 0x00, 0x00, 0x00, 0x00, 0x24, 0x2F, 0x14, 0x33, 0x08, 0x36, +- 0xFF, 0xFF, 0x00, 0x00, 0xBE, 0x33, 0x1E, 0x33, 0xCC, 0x35, 0xD0, 0x35, 0xD4, 0x35, 0x12, 0x34, +- 0x04, 0x36, 0x08, 0x36, 0xF2, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0x00, 0xBE, 0x33, 0x14, 0x33, 0x08, 0x36, 0x5C, 0x34, 0x2A, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00, 0x02, 0x06, 0x00, 0x00, 0x06, 0x07, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2A, +- 0x00, 0x00, 0x08, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x30, 0x00, 0xFF, 0xFF, 0x1D, 0xFA, +- 0xF9, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x19, 0x0A, +- 0x09, 0x46, 0x1C, 0x60, 0x18, 0x00, 0x19, 0x1D, 0x09, 0x42, 0x1C, 0x60, 0x00, 0x00, +- +-}; /* fw_image_2_data */ +- +-static const hcf_8 fw_image_3_data[] = { +- 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x26, 0x1A, 0x00, 0x80, 0x3A, 0x15, 0x00, 0x7F, 0xF1, +- 0x32, 0xF2, 0x33, 0xF2, 0xD0, 0x80, 0x80, 0xF1, 0x0F, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x81, 0xF1, +- 0x0B, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x08, 0x02, 0xE9, 0x60, 0x58, 0x4F, 0x30, 0x78, 0xFF, 0xFF, +- 0x24, 0x60, 0x58, 0x4F, 0xE3, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xD7, 0x78, 0xFF, 0xFF, 0x00, 0xF4, +- 0xAA, 0x60, 0xAA, 0x65, 0x09, 0xF2, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, 0x12, 0x02, 0xD0, 0x80, +- 0x1D, 0x60, 0x60, 0x65, 0x0E, 0x02, 0x5A, 0xD2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x60, 0x00, 0x65, +- 0x08, 0x02, 0x5A, 0xD2, 0xFF, 0xFF, 0xD4, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0x1C, 0x60, 0xD7, 0x78, +- 0xFF, 0xFF, 0x00, 0x60, 0xEA, 0xF1, 0x5A, 0xD1, 0x44, 0x48, 0x5A, 0xD1, 0x44, 0x4A, 0x26, 0x46, +- 0x3F, 0xF2, 0x00, 0xF4, 0x44, 0x4C, 0xD8, 0x83, 0x70, 0x61, 0x68, 0x65, 0xD7, 0x80, 0xFF, 0xFF, +- 0x07, 0x0E, 0x08, 0xF2, 0x08, 0x00, 0x68, 0x65, 0xD7, 0x80, 0xFF, 0xFF, 0x01, 0x0E, 0x03, 0x00, +- 0x1C, 0x60, 0xED, 0x78, 0xFF, 0xFF, 0x58, 0x4F, 0x79, 0x00, 0x9C, 0x80, 0x01, 0x65, 0x02, 0x02, +- 0x00, 0x65, 0x02, 0x00, 0xFF, 0x3B, 0xF7, 0x01, 0x58, 0x4F, 0x70, 0x00, 0x9C, 0x80, 0x45, 0x42, +- 0xEA, 0x02, 0x58, 0x4F, 0x6B, 0x00, 0x9C, 0x80, 0xFF, 0xFF, 0xE5, 0x02, 0x58, 0x4F, 0x66, 0x00, +- 0x9C, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0x00, 0x65, 0x45, 0x42, 0xF8, 0x01, 0xFF, 0x3A, 0x29, 0x00, +- 0x60, 0x47, 0xFF, 0xB5, 0x28, 0x44, 0xFF, 0xB4, 0x94, 0x80, 0xFF, 0xFF, 0xD4, 0x02, 0x60, 0x45, +- 0x28, 0x47, 0x2A, 0x5F, 0x40, 0x48, 0x2A, 0x47, 0x2C, 0x5F, 0x40, 0x4A, 0x2C, 0x47, 0x65, 0x5F, +- 0x40, 0x4C, 0x10, 0x64, 0x40, 0x42, 0x28, 0x45, 0x05, 0x00, 0x58, 0x4F, 0x47, 0x00, 0x94, 0x80, +- 0x28, 0x45, 0x26, 0x02, 0x58, 0x4F, 0x42, 0x00, 0x94, 0x80, 0x2A, 0x45, 0x21, 0x02, 0x58, 0x4F, +- 0x3D, 0x00, 0x94, 0x80, 0xFF, 0xFF, 0x1C, 0x02, 0x22, 0x44, 0x4C, 0x82, 0x2C, 0x45, 0x31, 0x03, +- 0xEC, 0x01, 0x10, 0x65, 0x45, 0x42, 0x28, 0x45, 0x94, 0x80, 0x2A, 0x45, 0x21, 0x02, 0x58, 0x4F, +- 0x2D, 0x00, 0x94, 0x80, 0x2C, 0x45, 0x1C, 0x02, 0x58, 0x4F, 0x28, 0x00, 0x94, 0x80, 0xFF, 0xFF, +- 0x17, 0x02, 0x22, 0x44, 0x4C, 0x82, 0x28, 0x45, 0x1C, 0x03, 0x58, 0x4F, 0x1F, 0x00, 0xEC, 0x01, +- 0x40, 0x4B, 0x28, 0x47, 0x40, 0x48, 0x2A, 0x47, 0x40, 0x4A, 0x2C, 0x47, 0x60, 0x45, 0x2A, 0x5E, +- 0x40, 0x4C, 0x2A, 0x44, 0x28, 0x5E, 0x40, 0x4A, 0x28, 0x44, 0x65, 0x5E, 0x40, 0x48, 0x2B, 0x44, +- 0x68, 0x65, 0xD7, 0x80, 0xFF, 0xFF, 0x17, 0x0E, 0x90, 0x01, 0x26, 0x46, 0xD0, 0x60, 0xB5, 0x78, +- 0xFF, 0xFF, 0xB9, 0xFF, 0x26, 0x46, 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0xC9, 0x81, 0xCB, 0x83, +- 0x07, 0x1C, 0x01, 0x1D, 0x08, 0x00, 0x00, 0xF4, 0x01, 0xF2, 0xFF, 0xFF, 0xFF, 0xB4, 0xD8, 0x81, +- 0x5A, 0xD2, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0xD0, 0x60, 0x58, 0x4F, 0xD1, 0x78, 0xFF, 0xFF, +- 0x01, 0x60, 0xFE, 0x61, 0x00, 0xF4, 0x12, 0x63, 0x6A, 0x64, 0x01, 0x65, 0xBD, 0xD0, 0xC8, 0x84, +- 0x59, 0xD9, 0xFC, 0x02, 0x65, 0x40, 0x01, 0x3A, 0x05, 0x00, 0x00, 0xF4, 0x00, 0x65, 0x0E, 0x64, +- 0x04, 0x63, 0xF4, 0x01, 0x2F, 0x60, 0x58, 0x64, 0x0E, 0x60, 0xD9, 0xFB, 0x1D, 0x60, 0xB0, 0x64, +- 0xA0, 0xDF, 0x17, 0x60, 0xA8, 0xF3, 0x0E, 0x60, 0xDB, 0xFB, 0x0E, 0x60, 0xDB, 0xF3, 0x0E, 0x60, +- 0xD8, 0xF3, 0x60, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x03, 0x02, 0x1D, 0x60, 0x7B, 0x78, 0xFF, 0xFF, +- 0x01, 0x64, 0x0E, 0x60, 0xD7, 0xFB, 0x0E, 0x60, 0xD9, 0xF3, 0x02, 0x60, 0x00, 0x61, 0x40, 0x48, +- 0x40, 0x4A, 0xFA, 0xA4, 0xA0, 0xD3, 0x41, 0x4C, 0xDC, 0x84, 0xA8, 0x84, 0x0E, 0x60, 0xDC, 0xFB, +- 0x28, 0x45, 0x44, 0x8B, 0x2B, 0xD3, 0x0E, 0x60, 0xDA, 0xFB, 0x28, 0x42, 0x4A, 0xD3, 0x2C, 0x45, +- 0x44, 0x8C, 0x01, 0x64, 0x40, 0x48, 0x0E, 0x60, 0xDC, 0xF3, 0xFF, 0xFF, 0x36, 0x18, 0xCC, 0x84, +- 0xA2, 0xDB, 0x0E, 0x60, 0xDA, 0xF3, 0x28, 0x45, 0xA4, 0x80, 0xFF, 0xFF, 0x08, 0x03, 0x60, 0xFE, +- 0x2C, 0xD3, 0x2A, 0xD3, 0x60, 0x45, 0xD4, 0x80, 0x20, 0xFE, 0x01, 0x03, 0x12, 0x00, 0x28, 0x44, +- 0xE0, 0x84, 0xFF, 0xFF, 0x02, 0x24, 0x01, 0x00, 0x06, 0x00, 0x2B, 0x44, 0x58, 0x8B, 0x2B, 0xD3, +- 0x0E, 0x60, 0xDA, 0xFB, 0x01, 0x64, 0x40, 0x48, 0x2A, 0x44, 0x5C, 0x8A, 0x2C, 0x44, 0x5C, 0x8C, +- 0xDA, 0x01, 0x00, 0x64, 0x0E, 0x60, 0xD7, 0xFB, 0x0E, 0x60, 0xD9, 0xF3, 0xFF, 0xFF, 0x60, 0x45, +- 0xFA, 0xA4, 0xA0, 0xD3, 0xFF, 0xFF, 0xC4, 0x81, 0x65, 0x44, 0xFC, 0xA4, 0xA0, 0xD3, 0x06, 0xA1, +- 0xDC, 0x84, 0xA8, 0x84, 0x44, 0x94, 0x0E, 0x60, 0xD9, 0xFB, 0x0E, 0x60, 0xD7, 0xF3, 0xFF, 0xFF, +- 0x60, 0x40, 0x01, 0x26, 0x09, 0x00, 0x0E, 0x60, 0xD8, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0xA2, 0xDB, +- 0x94, 0x01, 0x1C, 0x60, 0xD7, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xDB, 0x78, 0xFF, 0xFF, 0x00, 0x60, +- 0x2E, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x25, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x5F, 0xFB, 0x01, 0x60, +- 0x05, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x25, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x5E, 0xFB, 0x00, 0x60, +- 0x02, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x25, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x65, 0xFB, 0x1F, 0x60, +- 0x6D, 0x64, 0x08, 0x60, 0x36, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x01, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, +- 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, 0x10, 0x60, 0x30, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, +- 0x14, 0x63, 0x01, 0x60, 0xC2, 0x61, 0x2D, 0x60, 0x98, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, +- 0x00, 0x60, 0x8A, 0x63, 0x2D, 0x60, 0x0C, 0x61, 0x2D, 0x60, 0xB0, 0x64, 0x58, 0xD1, 0x59, 0xD9, +- 0xFD, 0x1F, 0x16, 0x60, 0xAB, 0xF3, 0x19, 0x60, 0x48, 0xF1, 0xFF, 0xB5, 0x64, 0x40, 0x02, 0x2B, +- 0x0B, 0x00, 0x60, 0x40, 0x03, 0x2E, 0x08, 0x00, 0x80, 0x2B, 0x06, 0x00, 0x32, 0x44, 0x00, 0x60, +- 0x80, 0x63, 0x3C, 0x94, 0x40, 0x52, 0x05, 0x00, 0x32, 0x44, 0xFF, 0x60, 0x7F, 0x63, 0x2C, 0x94, +- 0x40, 0x52, 0x65, 0x43, 0x16, 0x60, 0xAB, 0xFD, 0x16, 0x60, 0xC2, 0xF1, 0x66, 0x41, 0xA6, 0xF5, +- 0x3A, 0xF2, 0x64, 0x40, 0x01, 0x36, 0x22, 0x64, 0x3A, 0xFA, 0x61, 0x46, 0x32, 0x45, 0x16, 0x60, +- 0xCB, 0xF1, 0x10, 0x67, 0xB4, 0x85, 0x64, 0x40, 0x01, 0x2A, 0x94, 0x85, 0x45, 0x52, 0xFF, 0x60, +- 0xE7, 0x65, 0x32, 0x41, 0xA5, 0x81, 0x16, 0x60, 0xC2, 0xF3, 0x08, 0x65, 0xFF, 0xA0, 0xFF, 0xFF, +- 0x01, 0x03, 0x07, 0x00, 0x16, 0x60, 0xC4, 0xF3, 0xB5, 0x81, 0x10, 0x65, 0x60, 0x40, 0x01, 0x26, +- 0xB5, 0x81, 0x41, 0x52, 0x19, 0x60, 0x48, 0xF3, 0x37, 0x60, 0xE6, 0x63, 0xF0, 0x84, 0xF0, 0x84, +- 0xF0, 0x84, 0x03, 0xB5, 0xF0, 0x84, 0xF0, 0x84, 0x03, 0xB4, 0x65, 0x5C, 0xA3, 0xD9, 0x37, 0x60, +- 0xE8, 0x63, 0x02, 0xA8, 0xA3, 0xDB, 0x15, 0x02, 0x00, 0x60, 0xC8, 0x64, 0x1B, 0x60, 0xF5, 0xFB, +- 0x1B, 0x60, 0xF9, 0xFB, 0x07, 0x60, 0xD0, 0x64, 0x1B, 0x60, 0xF6, 0xFB, 0x1B, 0x60, 0xFA, 0xFB, +- 0x01, 0x60, 0x90, 0x64, 0x1B, 0x60, 0xF7, 0xFB, 0x00, 0x60, 0x64, 0x64, 0x1B, 0x60, 0xF8, 0xFB, +- 0x06, 0x00, 0x64, 0x64, 0x1B, 0x60, 0xF7, 0xFB, 0x64, 0x64, 0x1B, 0x60, 0xF8, 0xFB, 0x19, 0x60, +- 0x48, 0xF1, 0x01, 0x64, 0x64, 0x40, 0x40, 0x2A, 0x02, 0x00, 0x1B, 0x60, 0xEE, 0xFB, 0x33, 0x60, +- 0xBC, 0x61, 0x2D, 0x60, 0x0E, 0x64, 0x20, 0x63, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0xBA, 0xF1, +- 0x7E, 0xF9, 0x1A, 0x63, 0x00, 0x60, 0xFC, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, 0x40, 0x40, +- 0x01, 0x64, 0x85, 0xFB, 0x17, 0x60, 0x14, 0xF3, 0x35, 0x60, 0x36, 0x61, 0xFE, 0xA4, 0xE0, 0x84, +- 0x04, 0x24, 0x0C, 0x00, 0xE0, 0x84, 0x41, 0x91, 0x1A, 0x60, 0x1F, 0xF3, 0xA1, 0xD1, 0x59, 0xD1, +- 0xA0, 0x83, 0x1A, 0x60, 0x1B, 0xFD, 0xA0, 0x83, 0x1A, 0x60, 0x1A, 0xFD, 0xE4, 0xF3, 0x7D, 0xFB, +- 0xCF, 0xF1, 0x10, 0x60, 0xEC, 0x63, 0x2F, 0x18, 0x60, 0x40, 0x01, 0x27, 0x12, 0x00, 0xCC, 0x84, +- 0x06, 0xA3, 0xFD, 0x02, 0xA3, 0xD3, 0x10, 0x60, 0xF2, 0x63, 0x25, 0x1B, 0x11, 0x60, 0x44, 0x65, +- 0xA3, 0xD3, 0x06, 0xA3, 0xD7, 0x80, 0x02, 0x1B, 0xFB, 0x04, 0x1D, 0x00, 0xF8, 0xA3, 0xA3, 0xD3, +- 0x18, 0x00, 0x11, 0x60, 0x60, 0x63, 0x12, 0x60, 0x40, 0x65, 0xA3, 0xD1, 0x08, 0xA3, 0xD0, 0x80, +- 0xD7, 0x80, 0x02, 0x03, 0xFA, 0x04, 0x0F, 0x00, 0xFA, 0xA3, 0xA3, 0xD3, 0x11, 0x60, 0x62, 0x63, +- 0x0A, 0x1B, 0xA3, 0xD3, 0x08, 0xA3, 0xD7, 0x80, 0x02, 0x1B, 0xFB, 0x04, 0x04, 0x00, 0xF6, 0xA3, +- 0xA3, 0xD3, 0xE4, 0xFB, 0x7D, 0xFB, 0x2E, 0x60, 0x2E, 0x64, 0x2D, 0x60, 0x8A, 0x63, 0xA0, 0xD1, +- 0xA3, 0xD9, 0x64, 0x41, 0x58, 0xD1, 0x5B, 0xD9, 0x7D, 0xF3, 0x66, 0x45, 0xA6, 0xF5, 0x60, 0x40, +- 0x01, 0x27, 0x08, 0x00, 0x91, 0xFA, 0x61, 0x44, 0xFD, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, +- 0x12, 0xFA, 0x07, 0x00, 0x11, 0xF8, 0x64, 0x44, 0xFD, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, +- 0x12, 0xFA, 0x65, 0x46, 0x46, 0x48, 0xE2, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x05, 0x3A, 0x03, 0x00, +- 0x14, 0x60, 0x22, 0x66, 0x11, 0x00, 0x04, 0x3A, 0x03, 0x00, 0x14, 0x60, 0x16, 0x66, 0x0C, 0x00, +- 0x03, 0x3A, 0x03, 0x00, 0x14, 0x60, 0x0A, 0x66, 0x07, 0x00, 0x02, 0x3A, 0x03, 0x00, 0x13, 0x60, +- 0xFE, 0x66, 0x02, 0x00, 0x13, 0x60, 0xF2, 0x66, 0x60, 0xFE, 0xA6, 0xD3, 0xDE, 0x86, 0x13, 0x60, +- 0xDC, 0xFB, 0xA6, 0xD3, 0xDE, 0x86, 0x28, 0x60, 0x29, 0x63, 0xA3, 0xDB, 0x28, 0x60, 0xA1, 0x63, +- 0xA3, 0xDB, 0xA6, 0xD3, 0xDE, 0x86, 0x13, 0x60, 0xDB, 0xFB, 0xA6, 0xD3, 0xDE, 0x86, 0x27, 0x60, +- 0xB9, 0x63, 0xA3, 0xDB, 0x20, 0xFE, 0xA6, 0xD3, 0xDA, 0x86, 0x60, 0x43, 0x1F, 0xB3, 0x63, 0x5C, +- 0x1F, 0x60, 0x00, 0xB4, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xB0, 0x85, 0x14, 0x60, 0x12, 0xF3, +- 0xFF, 0xFF, 0xFC, 0x60, 0x00, 0xB4, 0xB4, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0x4E, 0xFB, 0x28, 0x60, +- 0xC4, 0x63, 0xA3, 0xD3, 0xA6, 0xD1, 0xDE, 0x86, 0x80, 0x60, 0x7F, 0xB5, 0x64, 0x44, 0x60, 0x47, +- 0xE8, 0x84, 0x7F, 0x60, 0x80, 0xB4, 0xB4, 0x84, 0xA3, 0xDB, 0x60, 0xFE, 0xA6, 0xD3, 0xDE, 0x86, +- 0x13, 0x60, 0xDF, 0xFB, 0xA6, 0xD3, 0xDE, 0x86, 0x00, 0x60, 0xDF, 0xFB, 0xA6, 0xD3, 0xDE, 0x86, +- 0x00, 0x60, 0xE0, 0xFB, 0xA6, 0xD3, 0x00, 0x60, 0xE1, 0xFB, 0x20, 0xFE, 0x28, 0x46, 0x19, 0x60, +- 0x4D, 0xF1, 0x00, 0x60, 0xCF, 0xF3, 0x64, 0x40, 0x00, 0x3A, 0x0F, 0x00, 0x60, 0x40, 0x01, 0x36, +- 0x05, 0x00, 0x02, 0x36, 0x03, 0x00, 0x07, 0x36, 0x01, 0x00, 0x07, 0x00, 0x10, 0x60, 0xF0, 0x64, +- 0x00, 0x7C, 0x44, 0xA4, 0xA0, 0xD9, 0x06, 0xA4, 0xA0, 0xD9, 0x36, 0x40, 0x08, 0x3A, 0x03, 0x00, +- 0xF3, 0x60, 0x0A, 0x78, 0xFF, 0xFF, 0x00, 0x63, 0x10, 0x60, 0x10, 0xFD, 0x10, 0x60, 0x30, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x19, 0xFB, +- 0x1E, 0x60, 0x8D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7D, 0xF1, 0x13, 0x60, +- 0x1A, 0xF9, 0x0C, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x07, 0x64, 0xCC, 0xFB, 0x20, 0x60, +- 0x00, 0x64, 0x08, 0x60, 0x19, 0xFB, 0x1F, 0x60, 0x53, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x10, 0x60, 0x30, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, +- 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xC5, 0xFE, 0x08, 0x60, 0x15, 0xF1, +- 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x64, 0x08, 0x60, 0x18, 0xFB, +- 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x30, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x02, 0x64, +- 0x89, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x08, 0x60, 0x30, 0xF1, 0x00, 0x60, 0xDF, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x64, 0x13, 0x60, 0x21, 0xFB, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x60, +- 0x18, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x60, 0x08, 0x64, +- 0x08, 0x60, 0x19, 0xFB, 0x1F, 0x60, 0x92, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x18, 0xF1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x89, 0xF3, 0x00, 0x65, +- 0xD4, 0x80, 0xFF, 0xFF, 0x0A, 0x03, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x19, 0xFB, 0x1F, 0x60, +- 0x92, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x95, 0xF3, 0xFF, 0xFF, 0x7F, 0xB4, +- 0x95, 0xFB, 0xDE, 0xFE, 0x0A, 0x04, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x19, 0xFB, 0x1F, 0x60, +- 0xB7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x60, 0x34, 0x62, 0x06, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x18, 0xFB, 0x5A, 0xDB, 0xBE, 0xFE, +- 0xDA, 0xFE, 0x25, 0x60, 0xDA, 0x61, 0x1F, 0x60, 0x58, 0x4E, 0xEA, 0x78, 0xFF, 0xFF, 0x25, 0x60, +- 0xC8, 0x61, 0x1F, 0x60, 0x58, 0x4E, 0xEA, 0x78, 0xFF, 0xFF, 0x25, 0x60, 0xCE, 0x61, 0x1F, 0x60, +- 0x58, 0x4E, 0xEA, 0x78, 0xFF, 0xFF, 0x25, 0x60, 0xEC, 0x61, 0x1F, 0x60, 0x58, 0x4E, 0xEA, 0x78, +- 0xFF, 0xFF, 0x25, 0x60, 0xF2, 0x61, 0x1F, 0x60, 0x58, 0x4E, 0xEA, 0x78, 0xFF, 0xFF, 0x25, 0x60, +- 0xFE, 0x61, 0x1F, 0x60, 0x58, 0x4E, 0xEA, 0x78, 0xFF, 0xFF, 0xC5, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0xA1, 0xD3, 0x0E, 0x57, 0x23, 0x00, 0x0E, 0xF2, 0x44, 0x4C, 0x80, 0xB0, 0x10, 0xB0, 0x0A, 0x03, +- 0x00, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x13, 0x00, 0x12, 0x02, 0xF0, 0x37, 0x09, 0x00, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, +- 0xD0, 0x80, 0xA2, 0xFF, 0xAD, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0xAD, 0xFB, 0x26, 0x60, 0x1A, 0x64, +- 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x2C, 0x44, 0xAC, 0x86, 0x09, 0xF0, +- 0xDA, 0x02, 0x37, 0x58, 0xFF, 0xFF, 0x2E, 0x58, 0xFF, 0xFF, 0x2E, 0x58, 0xFF, 0xFF, 0x23, 0x60, +- 0x85, 0x64, 0x08, 0x60, 0x32, 0xFB, 0x1C, 0x60, 0xB6, 0x62, 0xA2, 0xDF, 0x06, 0xA2, 0x10, 0x60, +- 0x88, 0x64, 0xA2, 0xDB, 0x06, 0x64, 0x5A, 0xDB, 0x5A, 0xDB, 0x1C, 0x60, 0xC2, 0x62, 0xA2, 0xDF, +- 0x06, 0xA2, 0x10, 0x60, 0x8C, 0x64, 0xA2, 0xDB, 0x06, 0x64, 0x5A, 0xDB, 0x5A, 0xDB, 0x1C, 0x60, +- 0xCE, 0x62, 0xA2, 0xDF, 0x06, 0xA2, 0x10, 0x60, 0x90, 0x64, 0xA2, 0xDB, 0x06, 0x64, 0x5A, 0xDB, +- 0x5A, 0xDB, 0xBD, 0xF1, 0x0E, 0x60, 0x69, 0xF9, 0x24, 0x60, 0xC1, 0x64, 0x08, 0x60, 0x43, 0xFB, +- 0x24, 0x60, 0xCA, 0x64, 0x08, 0x60, 0x45, 0xFB, 0x24, 0x60, 0xD3, 0x64, 0x08, 0x60, 0x47, 0xFB, +- 0x00, 0x60, 0x3A, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x62, 0xFB, +- 0x04, 0x64, 0x03, 0xFA, 0xA6, 0xF3, 0x07, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x00, 0x60, +- 0x02, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x20, 0x60, 0x63, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x10, 0x60, 0x18, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x03, 0x64, 0x69, 0xFB, 0x0F, 0x4E, +- 0xEA, 0x60, 0x58, 0x4F, 0x34, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0x00, 0x64, 0x6B, 0xFB, 0x62, 0xF5, +- 0xEA, 0xF3, 0x2F, 0xFA, 0xEB, 0xF3, 0x30, 0xFA, 0xEC, 0xF3, 0x31, 0xFA, 0x7F, 0xF3, 0x2C, 0xFA, +- 0x32, 0xFA, 0x80, 0xF3, 0x2D, 0xFA, 0x33, 0xFA, 0x81, 0xF3, 0x2E, 0xFA, 0x34, 0xFA, 0xB9, 0xF3, +- 0x19, 0xFA, 0x06, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, +- 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x08, 0x60, +- 0x0C, 0xF1, 0xFF, 0x60, 0x8F, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xBE, 0xF1, 0x0E, 0x60, 0x63, 0xF9, +- 0x1C, 0x60, 0xC2, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x00, 0x64, 0x6B, 0xFB, 0x00, 0x60, 0x74, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x20, 0x60, 0xAE, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x04, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x23, 0x60, 0x85, 0x78, 0xFF, 0xFF, +- 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xE2, 0x01, +- 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x11, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, +- 0x50, 0x27, 0xD8, 0x01, 0xAC, 0xF3, 0xFF, 0xFF, 0xFE, 0xA0, 0xFF, 0xFF, 0x0F, 0x06, 0x6B, 0xF3, +- 0xFF, 0xFF, 0xEC, 0xA0, 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0xCC, 0x01, 0x00, 0x60, 0x10, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0xCF, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x01, 0x00, 0xC3, 0x01, 0x01, 0x64, +- 0x19, 0x60, 0xF3, 0xFB, 0xDF, 0xF3, 0x29, 0x45, 0xD4, 0x80, 0x6B, 0xF3, 0x03, 0x04, 0x21, 0x60, +- 0x28, 0x78, 0xFF, 0xFF, 0xEC, 0xA0, 0x00, 0x64, 0x04, 0x04, 0x40, 0x49, 0x21, 0x60, 0x28, 0x78, +- 0xFF, 0xFF, 0x00, 0x60, 0x64, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x20, 0x60, 0xFD, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, +- 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x23, 0x60, 0x85, 0x78, 0xFF, 0xFF, 0x00, 0x60, +- 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xD0, 0x01, 0x00, 0x60, +- 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xE5, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, 0x50, 0x27, +- 0xE0, 0x01, 0xAC, 0xF3, 0xFF, 0xFF, 0xFE, 0xA0, 0xFF, 0xFF, 0x07, 0x06, 0x6B, 0xF3, 0xFF, 0xFF, +- 0xEC, 0xA0, 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0xBA, 0x01, 0xB9, 0x01, 0x33, 0x60, 0xE6, 0x65, +- 0xA5, 0xDF, 0xBF, 0xF1, 0x0E, 0x60, 0x63, 0xF9, 0xE0, 0xF3, 0x29, 0x45, 0x03, 0xA4, 0xD4, 0x80, +- 0x01, 0x63, 0x01, 0x05, 0x00, 0x63, 0x53, 0xFD, 0x7D, 0xF3, 0x01, 0x60, 0x00, 0x65, 0xA4, 0x80, +- 0x24, 0x44, 0xFE, 0xB4, 0x01, 0x03, 0x01, 0xBC, 0x40, 0x44, 0x21, 0x60, 0x45, 0x64, 0x6A, 0xFB, +- 0x23, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0xFF, 0x60, 0xDF, 0x64, 0xA0, 0x84, +- 0xA2, 0xDB, 0x86, 0xF1, 0x1B, 0x60, 0xB2, 0x63, 0xD3, 0x80, 0x67, 0xFD, 0x43, 0x03, 0x67, 0xF3, +- 0xE1, 0xF1, 0x60, 0x43, 0x29, 0x44, 0xA3, 0xD3, 0xC0, 0x85, 0xD4, 0x80, 0x5B, 0xD3, 0x3A, 0x06, +- 0x60, 0x43, 0x08, 0xA3, 0xBE, 0xD3, 0x81, 0xF1, 0xA3, 0xD3, 0xD0, 0x80, 0x80, 0xF1, 0x05, 0x02, +- 0xBF, 0xD3, 0xD0, 0x80, 0x7F, 0xF1, 0x01, 0x02, 0xD0, 0x80, 0xF8, 0xA3, 0x28, 0x02, 0x21, 0x60, +- 0x77, 0x64, 0x6A, 0xFB, 0x23, 0x60, 0xB4, 0x78, 0xFF, 0xFF, 0x01, 0xB0, 0x82, 0xF3, 0x22, 0x03, +- 0x62, 0xF5, 0x48, 0x7E, 0x2A, 0xFA, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x60, 0x01, 0x64, +- 0x08, 0x60, 0x0D, 0xFB, 0x21, 0x60, 0x92, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x0C, 0xF1, 0xFF, 0x60, 0xFE, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x03, 0x00, 0x23, 0x60, +- 0x7A, 0x78, 0xFF, 0xFF, 0x6B, 0xF3, 0xFF, 0xFF, 0xEC, 0xA0, 0x00, 0x64, 0x02, 0x04, 0x40, 0x49, +- 0x15, 0x00, 0xDF, 0xF3, 0x29, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x0B, 0x07, 0x1C, 0x60, 0xC2, 0x64, +- 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x20, 0x60, 0x86, 0x78, +- 0xFF, 0xFF, 0xE0, 0xF3, 0x29, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x16, 0x06, 0x04, 0x65, 0xF1, 0x60, +- 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, 0x05, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, +- 0xF1, 0xFB, 0x1C, 0x60, 0xC2, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x22, 0x60, 0x1B, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x74, 0x64, 0x08, 0x60, 0x0D, 0xFB, +- 0x21, 0x60, 0xD8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, +- 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x23, 0x60, +- 0x85, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0xB0, 0x01, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x15, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x20, 0x40, 0x50, 0x27, 0xA6, 0x01, 0xAC, 0xF3, 0x6B, 0xF3, 0xFE, 0xA0, 0xEC, 0xA0, +- 0x0A, 0x06, 0x03, 0x04, 0x00, 0x64, 0x55, 0xFB, 0x40, 0x49, 0x6B, 0xF3, 0xFF, 0xFF, 0xEC, 0xA0, +- 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0x96, 0x01, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x0D, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x21, 0x60, 0x28, 0x78, 0xFF, 0xFF, 0x21, 0x60, 0x9C, 0x78, +- 0xFF, 0xFF, 0x7D, 0xF3, 0x01, 0x60, 0x00, 0x65, 0xA4, 0x80, 0x24, 0x44, 0xFE, 0xB4, 0x01, 0x03, +- 0x01, 0xBC, 0x02, 0xB0, 0xFB, 0xB4, 0x01, 0x03, 0x04, 0xBC, 0x40, 0x44, 0xC0, 0xF1, 0x0E, 0x60, +- 0x63, 0xF9, 0xCF, 0xF3, 0x20, 0x60, 0x20, 0x65, 0x30, 0x1B, 0xA5, 0xD3, 0x24, 0x40, 0x01, 0x26, +- 0x16, 0x00, 0x60, 0x40, 0x20, 0x26, 0x29, 0x00, 0x01, 0xBC, 0xA5, 0xDB, 0x08, 0x60, 0x1E, 0xF1, +- 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, +- 0x0D, 0xFB, 0x22, 0x60, 0x5F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x60, 0x40, +- 0x10, 0x26, 0x13, 0x00, 0x01, 0xBC, 0xA5, 0xDB, 0x08, 0x60, 0x1E, 0xF1, 0x00, 0x60, 0x40, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x22, 0x60, +- 0x5F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0D, 0x64, 0x53, 0xFB, 0x22, 0x60, +- 0x67, 0x64, 0x6A, 0xFB, 0x23, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xCE, 0x64, 0x13, 0x60, +- 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0xFF, 0x60, +- 0xDF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x86, 0xF1, 0x1B, 0x60, 0xB2, 0x63, 0xD3, 0x80, 0x67, 0xFD, +- 0x07, 0x02, 0x24, 0x44, 0x04, 0xB0, 0xFF, 0xFF, 0x36, 0x03, 0x05, 0xAC, 0x40, 0x44, 0xA6, 0x01, +- 0x67, 0xF3, 0x29, 0x41, 0xA0, 0xD1, 0x58, 0xD3, 0xD1, 0x80, 0x64, 0x45, 0x60, 0x43, 0x2B, 0x05, +- 0x08, 0xA3, 0xBE, 0xD3, 0x81, 0xF1, 0xA3, 0xD3, 0xD0, 0x80, 0x80, 0xF1, 0x05, 0x02, 0xBF, 0xD3, +- 0xD0, 0x80, 0x7F, 0xF1, 0x01, 0x02, 0xD0, 0x80, 0xF8, 0xA3, 0x07, 0x02, 0x45, 0x49, 0x22, 0x60, +- 0xCD, 0x64, 0x6A, 0xFB, 0x23, 0x60, 0xB4, 0x78, 0xFF, 0xFF, 0x05, 0x65, 0xF1, 0x60, 0x58, 0x4E, +- 0xC3, 0x78, 0xFF, 0xFF, 0x04, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, +- 0x23, 0x60, 0x7A, 0x78, 0xFF, 0xFF, 0x67, 0xF3, 0x86, 0xF1, 0x04, 0xA4, 0xD0, 0x80, 0xFF, 0xFF, +- 0x02, 0x03, 0x67, 0xFB, 0xCD, 0x01, 0x6B, 0xF3, 0xFF, 0xFF, 0xEC, 0xA0, 0xFF, 0xFF, 0x01, 0x04, +- 0x75, 0x00, 0xE0, 0xF3, 0x29, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x70, 0x05, 0x7D, 0xF3, 0xFF, 0xFF, +- 0x60, 0x40, 0x01, 0x27, 0x08, 0x00, 0x22, 0x60, 0xCD, 0x63, 0x6A, 0xFD, 0x1C, 0x60, 0x78, 0x63, +- 0x23, 0x60, 0xB4, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0xC2, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x05, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, +- 0x20, 0x60, 0x14, 0x61, 0xA1, 0xDF, 0x04, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, +- 0xF1, 0xFB, 0x82, 0xF3, 0x62, 0xF5, 0x48, 0x7E, 0x2A, 0xFA, 0x02, 0x60, 0x00, 0x65, 0x20, 0x44, +- 0x34, 0x80, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x60, 0x01, 0x64, 0x08, 0x60, 0x0D, 0xFB, +- 0x23, 0x60, 0x00, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, +- 0xFF, 0x60, 0xFE, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x00, 0x60, 0x32, 0x64, 0x0E, 0x60, 0x63, 0xFB, +- 0x1C, 0x60, 0xC2, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x00, 0x60, 0x10, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x23, 0x60, 0x1C, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, +- 0xFD, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x20, 0x60, 0x86, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x74, 0x64, +- 0x08, 0x60, 0x0D, 0xFB, 0x23, 0x60, 0x3A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x23, 0x60, 0x85, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x40, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x67, 0x01, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x15, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, 0x50, 0x27, 0xE0, 0x01, 0xAC, 0xF3, 0x6B, 0xF3, +- 0xFE, 0xA0, 0xEC, 0xA0, 0x0A, 0x06, 0x03, 0x04, 0x00, 0x64, 0x55, 0xFB, 0x40, 0x49, 0x6B, 0xF3, +- 0xFF, 0xFF, 0xEC, 0xA0, 0xDC, 0x84, 0x01, 0x05, 0xA2, 0xDB, 0x4D, 0x01, 0x00, 0x60, 0x10, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0xCB, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0xCE, 0x64, 0x13, 0x60, +- 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x22, 0x60, 0x1B, 0x78, 0xFF, 0xFF, +- 0x08, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x20, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, 0xB6, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1C, 0x60, 0xC2, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1C, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x0C, 0xFB, 0x5A, 0xDB, 0x00, 0x64, +- 0x69, 0xFB, 0x08, 0x60, 0x08, 0xF1, 0x02, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x00, 0x60, 0x02, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x20, 0x60, 0x63, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0xA3, 0xD3, 0x7D, 0xF1, 0x7C, 0xFB, 0xD0, 0x80, 0x00, 0x64, 0x39, 0x03, +- 0x08, 0x60, 0x0C, 0xF1, 0xBF, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, +- 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x23, 0x60, 0xBA, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0xDF, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, +- 0x7C, 0xF1, 0x7D, 0xF9, 0x13, 0x60, 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, +- 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x23, 0x60, 0xE4, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x08, 0x60, 0x0C, 0xF1, 0xDF, 0x60, 0xFF, 0x64, 0xA0, 0x84, +- 0xA2, 0xDB, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x01, 0x64, 0x6A, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, +- 0x08, 0x60, 0x0C, 0xF1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x20, 0x40, 0x51, 0x23, +- 0x0A, 0x00, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x23, 0x60, 0xFA, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0x7F, 0x60, 0xFF, 0x61, 0xA1, 0x84, +- 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x02, 0x64, 0x8A, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, +- 0x8A, 0xF3, 0x00, 0x65, 0xD4, 0x80, 0xFF, 0xFF, 0x10, 0x03, 0x08, 0x60, 0x0C, 0xF1, 0x7F, 0x60, +- 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x24, 0x60, +- 0x16, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x33, 0x60, 0xBE, 0x64, 0x54, 0xFB, +- 0x08, 0x60, 0x0C, 0xF1, 0xEF, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x24, 0x44, 0x01, 0xB0, +- 0xFF, 0xFF, 0x08, 0x02, 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x07, 0x00, 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x0D, 0xFB, 0x24, 0x60, 0x55, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0xC2, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0xEF, 0x60, 0xEF, 0x64, 0xA0, 0x84, +- 0xA2, 0xDB, 0x01, 0x64, 0x8A, 0xFB, 0x6B, 0xF3, 0x00, 0x60, 0x95, 0xF3, 0xEC, 0xA0, 0x40, 0xBC, +- 0x06, 0x04, 0xA2, 0xDB, 0x69, 0xF1, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0x69, 0xFB, 0xFD, 0x60, +- 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x6A, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0xF1, 0x28, 0x44, +- 0xD0, 0x84, 0x03, 0xA4, 0x03, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0x04, 0x00, 0xFA, 0xA4, 0xE8, 0x84, +- 0xE8, 0x87, 0xC0, 0xBF, 0xC0, 0x84, 0xA2, 0xDB, 0x2E, 0x58, 0xFF, 0xFF, 0x56, 0xF1, 0x28, 0x44, +- 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, +- 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, +- 0xC0, 0x84, 0x5B, 0xF1, 0x56, 0xFB, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x05, 0x64, 0x44, 0x52, 0xFB, +- 0x2E, 0x58, 0xFF, 0xFF, 0x52, 0xF1, 0x2F, 0x67, 0xD0, 0x80, 0x60, 0x45, 0x02, 0x28, 0x64, 0x45, +- 0x55, 0xF1, 0x8B, 0x67, 0xD0, 0x80, 0x60, 0x41, 0x02, 0x24, 0x64, 0x41, 0xD5, 0x84, 0x80, 0x65, +- 0xC4, 0x87, 0x01, 0x05, 0x00, 0x64, 0xFF, 0xB4, 0x40, 0x49, 0x2E, 0x58, 0xFF, 0xFF, 0x08, 0x60, +- 0x0C, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x40, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x26, 0x46, 0x27, 0xF2, 0x70, 0x63, 0x60, 0x40, 0x0A, 0x36, 0x10, 0x00, 0x14, 0x36, +- 0x14, 0x00, 0x37, 0x36, 0x0E, 0x00, 0x6E, 0x36, 0x0E, 0x00, 0x06, 0x36, 0x04, 0x00, 0x09, 0x36, +- 0x04, 0x00, 0x18, 0x63, 0x0A, 0x00, 0x30, 0x63, 0x08, 0x00, 0x26, 0x63, 0x06, 0x00, 0xD0, 0x63, +- 0x04, 0x00, 0x33, 0x63, 0x02, 0x00, 0x21, 0x63, 0x00, 0x00, 0x10, 0x60, 0x0E, 0xFD, 0x26, 0x46, +- 0x3F, 0xF2, 0x87, 0xF0, 0x00, 0xF4, 0x45, 0x43, 0x03, 0x4B, 0x60, 0x43, 0xF4, 0xA3, 0x00, 0x60, +- 0x1D, 0x61, 0x00, 0x60, 0x01, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, +- 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x64, 0x40, 0x4A, 0x60, 0xFE, +- 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, 0x58, 0x4E, 0x2C, 0x78, +- 0xFF, 0xFF, 0x20, 0xFE, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF4, 0xA3, 0x00, 0x60, +- 0x1D, 0x61, 0x00, 0x60, 0x32, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, +- 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x0B, 0x03, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, +- 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, 0x58, 0x4E, 0x2C, 0x78, 0xFF, 0xFF, 0x20, 0xFE, +- 0x2A, 0x44, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xF2, 0x01, 0x60, +- 0x00, 0x65, 0xF4, 0xA4, 0xD4, 0x80, 0x60, 0x41, 0x02, 0x24, 0x65, 0x41, 0x41, 0x48, 0x00, 0xF4, +- 0x1E, 0x65, 0x02, 0x60, 0x00, 0x63, 0xA5, 0xD0, 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, +- 0x04, 0x65, 0x64, 0x44, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, +- 0xCD, 0x81, 0xBD, 0xDB, 0xF0, 0x02, 0x02, 0x60, 0x00, 0x63, 0x28, 0x41, 0xBD, 0xD3, 0xBD, 0xD1, +- 0xFD, 0xA0, 0xFE, 0xA1, 0x07, 0x03, 0x09, 0x06, 0x64, 0x44, 0xE0, 0x85, 0xD1, 0x81, 0xC7, 0x83, +- 0xF5, 0x07, 0x03, 0x00, 0xA3, 0xD3, 0x0E, 0x60, 0x3C, 0xFB, 0x31, 0x40, 0x06, 0x26, 0x57, 0x00, +- 0x00, 0x64, 0x6F, 0xFB, 0x02, 0x60, 0x00, 0x63, 0x28, 0x41, 0xBD, 0xD3, 0xBD, 0xD1, 0xFC, 0xA0, +- 0xFB, 0xA0, 0x09, 0x03, 0x28, 0x03, 0x64, 0x44, 0xE0, 0x85, 0xC7, 0x83, 0xD1, 0x81, 0xFE, 0xA1, +- 0x46, 0x06, 0xF3, 0x07, 0x44, 0x00, 0xBD, 0xD3, 0xBD, 0xD3, 0x00, 0xB8, 0x6F, 0xFB, 0x6E, 0xFB, +- 0xBD, 0xD3, 0x3D, 0x02, 0xA3, 0xD3, 0x60, 0x45, 0x60, 0x47, 0xB4, 0x84, 0x60, 0x41, 0x3F, 0xB5, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x71, 0xFB, 0x65, 0x47, +- 0xE0, 0x84, 0xE0, 0x84, 0x70, 0xFB, 0x64, 0x44, 0xE0, 0x85, 0xFA, 0xA3, 0xC7, 0x83, 0x61, 0x44, +- 0x0E, 0x60, 0x38, 0xFB, 0xD2, 0x01, 0xBD, 0xD3, 0xA3, 0xD3, 0x00, 0xB8, 0x6D, 0xFB, 0x73, 0xFB, +- 0x1E, 0x02, 0x85, 0xF1, 0x6F, 0xF3, 0x6C, 0xF9, 0x04, 0x65, 0x60, 0x40, 0x00, 0x3A, 0x06, 0x65, +- 0x31, 0x44, 0xB4, 0x84, 0x40, 0x51, 0x02, 0x2A, 0x0B, 0x00, 0x08, 0xBC, 0x40, 0x51, 0x71, 0xF3, +- 0x70, 0xF1, 0x00, 0xB8, 0x64, 0x45, 0x01, 0x03, 0x67, 0x45, 0x65, 0x50, 0xCC, 0x84, 0x72, 0xFB, +- 0x08, 0x60, 0x15, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x08, 0x60, +- 0x16, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2A, 0x3F, 0x00, 0x01, 0x64, 0x10, 0x60, 0x0A, 0xFB, +- 0x26, 0x60, 0x58, 0x4E, 0x65, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x0D, 0xF2, 0x7E, 0xFB, +- 0x00, 0x64, 0x84, 0xFB, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF4, 0xA3, 0x00, 0x60, +- 0x1D, 0x61, 0x00, 0x60, 0x07, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, +- 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x14, 0x03, 0x02, 0x60, 0x00, 0x65, 0xA5, 0xD3, +- 0x1C, 0x60, 0xE6, 0x63, 0xFF, 0xB4, 0x01, 0xA4, 0x60, 0x41, 0xA5, 0xD1, 0xDA, 0x85, 0x64, 0x44, +- 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, 0x05, 0x03, 0x64, 0x47, 0x00, 0x7F, 0xCD, 0x81, 0xBD, 0xDB, +- 0xF4, 0x02, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x80, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x32, 0x00, 0x27, 0x60, 0x57, 0x78, 0xFF, 0xFF, 0xDB, 0xF3, 0xFF, 0xFF, 0x03, 0xA8, 0x02, 0xA8, +- 0x02, 0x03, 0x3E, 0x02, 0xF6, 0x01, 0x08, 0x60, 0x15, 0xF1, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, +- 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x26, 0x46, 0x10, 0x60, 0x0E, 0xF3, 0x25, 0xF2, 0x60, 0x45, 0x24, 0xF0, 0x00, 0xF4, +- 0x64, 0x43, 0xC7, 0x83, 0x60, 0x41, 0x02, 0x24, 0x01, 0xA1, 0x0A, 0xF0, 0x09, 0xF2, 0xD1, 0x80, +- 0xFF, 0xFF, 0x09, 0x07, 0x04, 0x04, 0x63, 0x45, 0xD4, 0x80, 0xFF, 0xFF, 0x04, 0x06, 0x26, 0x60, +- 0x58, 0x4E, 0x65, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x26, 0xF0, 0xFF, 0x67, 0x20, 0x88, 0x64, 0x5F, +- 0x40, 0x4A, 0x24, 0x60, 0x58, 0x4E, 0x80, 0x78, 0xFF, 0xFF, 0x0A, 0x48, 0x24, 0x60, 0x58, 0x4E, +- 0x90, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x0D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x22, 0xB3, 0x01, 0x00, 0x60, 0x95, 0xF3, +- 0xFF, 0xFF, 0xBF, 0xB4, 0xA2, 0xDB, 0x10, 0x60, 0x0E, 0xF3, 0x26, 0x46, 0x60, 0x45, 0x20, 0x60, +- 0x04, 0x63, 0x00, 0xF4, 0x09, 0xF2, 0xBD, 0xDB, 0xFF, 0xFF, 0x0A, 0xF2, 0xBD, 0xDB, 0x0B, 0xF2, +- 0xFF, 0xFF, 0xBD, 0xDB, 0x0C, 0xF2, 0xA3, 0xDB, 0xFA, 0xA3, 0x26, 0x46, 0xA3, 0xD3, 0x24, 0xF0, +- 0x00, 0x61, 0xD0, 0x84, 0xF1, 0x81, 0xD4, 0x84, 0xF1, 0x81, 0xBD, 0xDB, 0xA3, 0xD3, 0x03, 0xB1, +- 0x03, 0xA9, 0x25, 0xF0, 0x42, 0xFE, 0x05, 0x03, 0xFD, 0xA1, 0xCC, 0x84, 0x01, 0x02, 0xCC, 0x84, +- 0x00, 0x61, 0xF1, 0x81, 0xD0, 0x84, 0xF1, 0x81, 0xBD, 0xDB, 0xA3, 0xD3, 0x03, 0xB1, 0x03, 0xA9, +- 0x28, 0xF0, 0x42, 0xFE, 0x01, 0x03, 0xCC, 0x84, 0xF1, 0x81, 0xD0, 0x84, 0xF1, 0x81, 0xBD, 0xDB, +- 0xA3, 0xD3, 0x03, 0xB1, 0x03, 0xA9, 0x29, 0xF0, 0x01, 0x03, 0xCC, 0x84, 0xD0, 0x84, 0xA3, 0xDB, +- 0x10, 0x60, 0x0A, 0xF3, 0xFF, 0xFF, 0x02, 0xA8, 0xFF, 0xFF, 0x02, 0x02, 0x2E, 0x58, 0xFF, 0xFF, +- 0xF5, 0xFE, 0x10, 0x60, 0x02, 0xF1, 0x06, 0xA2, 0xA2, 0xD3, 0x64, 0x45, 0x60, 0x40, 0x80, 0x2B, +- 0x03, 0x00, 0xFF, 0x60, 0xFF, 0x64, 0x94, 0x85, 0x00, 0x60, 0x96, 0x64, 0xD4, 0x80, 0xFF, 0xFF, +- 0x0A, 0x06, 0x10, 0x60, 0x0A, 0xF3, 0x69, 0xF3, 0x00, 0xA8, 0x04, 0xB0, 0x04, 0x02, 0x03, 0x03, +- 0x27, 0x60, 0x33, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0x09, 0xF2, 0x5A, 0xD2, 0x40, 0x48, +- 0x40, 0x4A, 0x5A, 0xD2, 0x5A, 0xD2, 0x40, 0x4C, 0x60, 0x41, 0x5A, 0xD0, 0x7E, 0xF9, 0x40, 0x63, +- 0xAD, 0x80, 0xF0, 0xA3, 0x09, 0x02, 0x3C, 0x03, 0x2C, 0x41, 0x2A, 0x44, 0x40, 0x4C, 0x28, 0x44, +- 0x40, 0x4A, 0x00, 0x64, 0x40, 0x48, 0xF4, 0x01, 0xD1, 0x80, 0x01, 0x02, 0x31, 0x04, 0x10, 0xA3, +- 0x80, 0x60, 0x00, 0x65, 0xA5, 0x80, 0xCF, 0x83, 0x08, 0x02, 0x28, 0x44, 0x60, 0x88, 0x2A, 0x44, +- 0x70, 0x8A, 0x2C, 0x44, 0x70, 0x8C, 0xF1, 0x81, 0xF5, 0x01, 0xE7, 0xA3, 0x64, 0x44, 0x00, 0xA8, +- 0x00, 0x62, 0x02, 0x02, 0x00, 0x61, 0x1C, 0x00, 0xE0, 0x84, 0xDE, 0x82, 0xFD, 0x04, 0x42, 0xFE, +- 0xF8, 0x84, 0x62, 0x45, 0xC7, 0x83, 0x60, 0x45, 0x02, 0xFE, 0xD5, 0x84, 0x02, 0x05, 0x01, 0x05, +- 0x61, 0x44, 0xCF, 0x83, 0x60, 0x41, 0x08, 0x03, 0x28, 0x44, 0x60, 0x88, 0x2A, 0x44, 0x70, 0x8A, +- 0x2C, 0x44, 0x70, 0x8C, 0xF1, 0x81, 0xF1, 0x01, 0xCE, 0x82, 0xE9, 0x81, 0xFD, 0x02, 0xF1, 0x81, +- 0x09, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0xE8, 0x84, 0xE8, 0x84, 0x5A, 0xD2, 0x3F, 0xB5, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x84, 0x61, 0x45, 0xD4, 0x84, +- 0xC0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x93, 0x10, 0x60, 0x0A, 0xF3, 0xFF, 0xFF, +- 0x02, 0x18, 0x2E, 0x58, 0xFF, 0xFF, 0x16, 0x65, 0x32, 0x40, 0x80, 0x26, 0x16, 0x65, 0x73, 0x44, +- 0xD4, 0x93, 0x69, 0xF3, 0x26, 0x46, 0x04, 0xBC, 0xA2, 0xDB, 0x26, 0xF0, 0xFF, 0x67, 0x20, 0x88, +- 0x64, 0x5F, 0x40, 0x4A, 0x24, 0x60, 0x58, 0x4E, 0x80, 0x78, 0xFF, 0xFF, 0x0A, 0x48, 0x24, 0x60, +- 0x58, 0x4E, 0x90, 0x78, 0xFF, 0xFF, 0x24, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x6B, 0xF3, +- 0xFF, 0xFF, 0xC8, 0x84, 0xFF, 0xFF, 0x01, 0x05, 0x00, 0x64, 0x6B, 0xFB, 0x08, 0x60, 0x0C, 0xF1, +- 0x00, 0x60, 0x40, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, 0xCE, 0x64, 0x13, 0x60, +- 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x08, 0x60, 0x0C, 0xF1, 0xFF, 0x60, +- 0xDF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1E, 0xF1, +- 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, +- 0xDA, 0x63, 0xA3, 0xDF, 0x06, 0xA3, 0x10, 0x60, 0xA4, 0x64, 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, +- 0xA3, 0xDB, 0x27, 0x60, 0x68, 0x64, 0x08, 0x60, 0x51, 0xFB, 0x10, 0x60, 0x0F, 0xF1, 0x0E, 0x60, +- 0x6F, 0xF9, 0x27, 0x60, 0xCF, 0x64, 0x08, 0x60, 0x38, 0xFB, 0x11, 0x60, 0x44, 0x63, 0x08, 0x60, +- 0x66, 0xFD, 0x12, 0x60, 0x40, 0x63, 0x08, 0x60, 0x67, 0xFD, 0xCF, 0xF3, 0x02, 0x63, 0x01, 0x1B, +- 0xCF, 0xFD, 0xCF, 0xF3, 0xFF, 0xFF, 0xF7, 0xA0, 0x01, 0x64, 0x01, 0x06, 0xCF, 0xFB, 0xCF, 0xF3, +- 0xCF, 0xFB, 0xCF, 0xF3, 0x12, 0x60, 0x78, 0x63, 0x26, 0x18, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, +- 0x2A, 0xA3, 0xFB, 0x01, 0x63, 0x46, 0x10, 0x60, 0xF2, 0x63, 0x0E, 0x61, 0x60, 0xFE, 0xA6, 0xD1, +- 0xDE, 0x86, 0x01, 0x64, 0x64, 0x40, 0x7F, 0x36, 0x00, 0x64, 0xA3, 0xDB, 0xDB, 0x83, 0xA3, 0xD9, +- 0xCD, 0x81, 0x04, 0xA3, 0xF4, 0x02, 0x11, 0x60, 0x62, 0x63, 0x1C, 0x61, 0xA6, 0xD1, 0xDE, 0x86, +- 0x01, 0x64, 0x64, 0x40, 0x7F, 0x36, 0x00, 0x64, 0xA3, 0xDB, 0xDB, 0x83, 0xA3, 0xD9, 0xCD, 0x81, +- 0x06, 0xA3, 0xF4, 0x02, 0x20, 0xFE, 0x00, 0x60, 0x60, 0x64, 0x08, 0x60, 0x1F, 0xFB, 0x27, 0x60, +- 0xE1, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x11, 0x60, 0x44, 0x63, 0x08, 0x60, +- 0x66, 0xFD, 0x12, 0x60, 0x40, 0x63, 0x08, 0x60, 0x67, 0xFD, 0x00, 0x60, 0x60, 0x64, 0x08, 0x60, +- 0x1F, 0xFB, 0x27, 0x60, 0xE1, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x28, 0xF3, +- 0xFF, 0xFF, 0x60, 0x47, 0x0F, 0xB4, 0x98, 0x00, 0xFF, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x04, 0x64, +- 0x13, 0x60, 0x1C, 0xFB, 0x27, 0x00, 0x0C, 0x64, 0x3F, 0x40, 0x02, 0x2B, 0x23, 0x00, 0x29, 0xF1, +- 0x13, 0x60, 0x1C, 0xFB, 0x5A, 0xD9, 0x27, 0x60, 0xFD, 0x64, 0x9F, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, +- 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x29, 0x60, 0x1C, 0x63, 0x09, 0x61, 0x3D, 0x60, 0x58, 0x4D, +- 0x23, 0x78, 0xFF, 0xFF, 0x75, 0x00, 0x95, 0xF3, 0xFF, 0xFF, 0x7F, 0xB4, 0x95, 0xFB, 0x06, 0x64, +- 0x13, 0x60, 0x1C, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x08, 0x64, +- 0x13, 0x60, 0x1C, 0xFB, 0x28, 0x60, 0x7A, 0x64, 0x9F, 0xFB, 0xFF, 0xFF, 0x2D, 0xFF, 0x2A, 0x60, +- 0x1D, 0x78, 0xFF, 0xFF, 0x29, 0xF3, 0x12, 0x60, 0x45, 0x65, 0x60, 0x5C, 0x3F, 0x40, 0x02, 0x2B, +- 0x13, 0x00, 0x00, 0x37, 0x11, 0x00, 0x01, 0x3B, 0x53, 0x00, 0x11, 0x60, 0x65, 0x63, 0xFF, 0xB7, +- 0x60, 0x5C, 0xA3, 0xD3, 0x08, 0xA3, 0x00, 0x7E, 0xD0, 0x80, 0xD7, 0x80, 0x02, 0x03, 0xF9, 0x02, +- 0x47, 0x00, 0xF4, 0xA3, 0xA3, 0xD3, 0x05, 0x00, 0x00, 0xBC, 0xF2, 0xA4, 0x41, 0x03, 0x40, 0x07, +- 0x64, 0x44, 0x7D, 0xFB, 0xA1, 0xFB, 0x07, 0x64, 0xA2, 0xFB, 0x28, 0x60, 0x7A, 0x64, 0x9F, 0xFB, +- 0xFF, 0xFF, 0xDF, 0xFE, 0x00, 0x64, 0x19, 0xFF, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x88, 0xFF, +- 0xBA, 0x60, 0x98, 0x71, 0x8D, 0xE2, 0x01, 0x11, 0x09, 0x00, 0x71, 0x40, 0x80, 0x27, 0xFB, 0x01, +- 0x88, 0xE2, 0xBA, 0x60, 0xD0, 0x64, 0x03, 0xFB, 0x8D, 0xFF, 0x15, 0x00, 0x8D, 0xFF, 0x28, 0x60, +- 0xFB, 0x63, 0x06, 0x60, 0x0B, 0xFD, 0xFF, 0xFF, 0x62, 0xFF, 0x28, 0x60, 0x67, 0x63, 0x9F, 0xFD, +- 0xFF, 0xFF, 0x1A, 0xFF, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0xA3, 0x60, 0xF4, 0x63, 0x06, 0x60, +- 0x0B, 0xFD, 0xFF, 0xFF, 0x62, 0xFF, 0x29, 0xF5, 0x26, 0x60, 0x20, 0x63, 0x25, 0x60, 0xF2, 0x64, +- 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0x02, 0x64, 0xA3, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF9, 0xFE, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x68, 0x01, 0x00, 0x36, 0x69, 0x01, 0x01, 0x36, 0x6B, 0x01, +- 0x02, 0x36, 0x81, 0x01, 0x03, 0x36, 0x8B, 0x01, 0x04, 0x36, 0xC1, 0x01, 0x05, 0x36, 0xBF, 0x01, +- 0x06, 0x36, 0xF1, 0x01, 0x07, 0x36, 0xBB, 0x01, 0x08, 0x36, 0x8C, 0x01, 0x09, 0x36, 0x0C, 0x00, +- 0x0A, 0x36, 0x0D, 0x00, 0x0B, 0x36, 0x0E, 0x00, 0x0C, 0x36, 0x17, 0x00, 0x0D, 0x36, 0x0D, 0x00, +- 0x0E, 0x36, 0x1D, 0x00, 0x0F, 0x36, 0x41, 0x00, 0x02, 0x60, 0x00, 0x64, 0x08, 0x00, 0x04, 0x60, +- 0x00, 0x64, 0x05, 0x00, 0x00, 0x60, 0x01, 0x64, 0x02, 0x00, 0x20, 0x60, 0x00, 0x64, 0x32, 0x45, +- 0xB4, 0x85, 0x45, 0x52, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x29, 0x60, 0xDE, 0x63, 0x06, 0x60, +- 0x0B, 0xFD, 0x62, 0xFF, 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x3F, 0x40, +- 0x02, 0x2B, 0x15, 0x00, 0x88, 0xFF, 0xBA, 0x60, 0x98, 0x71, 0x8D, 0xE2, 0x01, 0x11, 0x09, 0x00, +- 0x71, 0x40, 0x80, 0x27, 0xFB, 0x01, 0x88, 0xE2, 0xBA, 0x60, 0xD0, 0x64, 0x03, 0xFB, 0x8D, 0xFF, +- 0x11, 0x00, 0x8D, 0xFF, 0x90, 0x60, 0x00, 0xE8, 0x28, 0x60, 0xFB, 0x63, 0x04, 0x00, 0x91, 0x60, +- 0x00, 0xE8, 0x29, 0x60, 0xC4, 0x63, 0x2A, 0xE8, 0x06, 0x60, 0x0B, 0xFD, 0xFF, 0xFF, 0x62, 0xFF, +- 0xFF, 0xFF, 0x1A, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xF1, 0xF3, 0xFF, 0xFF, 0xEF, 0xB4, +- 0xF1, 0xFB, 0xAD, 0x4F, 0xFD, 0xB4, 0xA0, 0x5D, 0xD0, 0x60, 0x00, 0xE8, 0x2A, 0xE8, 0xD9, 0x60, +- 0xFE, 0x64, 0x32, 0x45, 0xA4, 0x85, 0x45, 0x52, 0x99, 0xFF, 0xA5, 0x4F, 0xFF, 0xB4, 0x07, 0xFB, +- 0x98, 0xFF, 0xA3, 0x60, 0xF4, 0x63, 0x06, 0x60, 0x0B, 0xFD, 0x62, 0xFF, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x43, 0xFF, 0x01, 0x60, 0x00, 0xE1, 0x28, 0xF3, +- 0x47, 0xFF, 0x60, 0x40, 0x07, 0x37, 0x66, 0x00, 0x05, 0x3B, 0x04, 0x00, 0xFF, 0x0A, 0x80, 0xE1, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x1B, 0x60, 0xF3, 0xF1, 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, +- 0x7D, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, +- 0xA0, 0x5D, 0x29, 0xF5, 0x2A, 0xF3, 0x47, 0xFF, 0x3F, 0xF0, 0x01, 0x1B, 0x01, 0x64, 0x60, 0x56, +- 0xAD, 0xE2, 0xB5, 0xFF, 0x6C, 0x40, 0x40, 0xE1, 0xA1, 0xFF, 0x00, 0xF4, 0x6E, 0x61, 0x12, 0x62, +- 0x64, 0x43, 0x01, 0xE1, 0x03, 0x64, 0xE2, 0xD0, 0xC9, 0x81, 0x64, 0x4C, 0xCC, 0x84, 0xDA, 0x82, +- 0xFA, 0x02, 0x01, 0x60, 0x00, 0x6B, 0x9A, 0xFF, 0xCA, 0x82, 0x03, 0x00, 0x00, 0xF4, 0x81, 0xF2, +- 0xFF, 0xFF, 0x7A, 0xD0, 0xA1, 0xFF, 0x64, 0x4C, 0xFC, 0x1C, 0xF8, 0x1D, 0x00, 0xB9, 0x06, 0x1E, +- 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, 0x5A, 0xD2, 0xA1, 0xFF, 0x60, 0x4D, 0x3F, 0x40, 0x02, 0x2B, +- 0x10, 0x00, 0x28, 0xF3, 0xA5, 0x60, 0xC4, 0x65, 0x60, 0x40, 0x0E, 0x3B, 0x0A, 0x00, 0xF1, 0xF3, +- 0xFF, 0xFF, 0x10, 0xBC, 0xF1, 0xFB, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x85, 0x4C, +- 0xFE, 0x01, 0xF1, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xF1, 0xFB, 0xA1, 0xFF, 0x87, 0x4E, 0x87, 0x4C, +- 0x87, 0x4C, 0x87, 0x4C, 0x87, 0x4C, 0x67, 0x4C, 0xFF, 0xFF, 0xBC, 0xFF, 0x00, 0xE1, 0xD5, 0xFE, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x00, 0x64, 0x40, 0x46, 0x60, 0x41, 0xB5, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, +- 0x29, 0xF5, 0x3F, 0xF0, 0x24, 0xF2, 0x44, 0x43, 0x40, 0x4D, 0x00, 0xF4, 0xF3, 0x60, 0xA0, 0x65, +- 0x10, 0x62, 0x5A, 0xD2, 0xD9, 0x81, 0xD4, 0x80, 0xFF, 0xFF, 0xFB, 0x02, 0x61, 0x45, 0x2D, 0x44, +- 0xD4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xFD, 0xA5, 0x48, 0x60, 0x00, 0x64, 0xC4, 0x9D, +- 0x0D, 0x60, 0x00, 0x6B, 0x2D, 0x44, 0xC0, 0x83, 0xBB, 0xFF, 0x29, 0xF5, 0x01, 0xE1, 0x00, 0xF4, +- 0x6C, 0x61, 0x10, 0x62, 0x05, 0x00, 0x00, 0xF4, 0x01, 0xF2, 0xFF, 0xFF, 0x60, 0x41, 0x04, 0x62, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x1A, 0x00, 0x26, 0x44, 0x01, 0x26, 0x0C, 0x00, 0x2D, 0x44, +- 0xC8, 0x84, 0x40, 0x4D, 0x02, 0x03, 0x6C, 0x45, 0xF3, 0x01, 0x03, 0x15, 0x01, 0x64, 0x05, 0xFA, +- 0x15, 0x00, 0x6C, 0x45, 0xED, 0x01, 0x23, 0x44, 0xC8, 0x84, 0x40, 0x43, 0x02, 0x03, 0x6C, 0x45, +- 0xE7, 0x01, 0x00, 0x64, 0x01, 0x15, 0x01, 0x64, 0x6C, 0x45, 0x05, 0xFB, 0xE2, 0xD2, 0xDA, 0x82, +- 0xC9, 0x81, 0x60, 0x4C, 0xDD, 0x1C, 0xD7, 0x03, 0xBC, 0xFF, 0xDA, 0x01, 0x00, 0xE1, 0xD5, 0xFE, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, 0x67, 0x4C, 0x43, 0xFF, 0xF1, 0xF3, 0xFF, 0xFF, +- 0x10, 0xBC, 0xF1, 0xFB, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x01, 0xE1, 0x01, 0x60, +- 0x69, 0x6B, 0xA5, 0x60, 0xC4, 0x64, 0x60, 0x4C, 0xBB, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x60, 0x4C, 0xFC, 0x01, 0x29, 0xF3, 0x2A, 0xF1, 0x07, 0xB5, 0x04, 0xE1, +- 0x65, 0x41, 0x64, 0x54, 0xCD, 0xE2, 0x95, 0x81, 0xA1, 0x5D, 0xA1, 0xFF, 0xFF, 0xFF, 0xF9, 0x01, +- 0x61, 0x44, 0xFE, 0xFB, 0xFF, 0xFD, 0xFF, 0x01, 0x7F, 0x67, 0x01, 0x61, 0x23, 0x58, 0xFF, 0xFF, +- 0xB1, 0xFE, 0x08, 0x05, 0xB0, 0xFE, 0x09, 0x05, 0xB2, 0xFE, 0xB3, 0xFE, 0x78, 0x43, 0x01, 0x61, +- 0x29, 0x60, 0xEA, 0x78, 0x34, 0x60, 0x8D, 0x78, 0xFF, 0xFF, 0x28, 0xF3, 0x29, 0xF1, 0x40, 0x44, +- 0x44, 0x45, 0x2A, 0xF1, 0x2B, 0xF1, 0x44, 0x46, 0x44, 0x47, 0x3F, 0xB4, 0xE0, 0x85, 0x20, 0x60, +- 0x28, 0x64, 0x44, 0xD7, 0x58, 0x43, 0xFF, 0xFF, 0x60, 0x45, 0x0E, 0x60, 0xDD, 0xF3, 0x61, 0x43, +- 0x04, 0xB4, 0x24, 0x44, 0x02, 0x03, 0x13, 0xFF, 0x06, 0x00, 0x3F, 0xB4, 0xB4, 0x84, 0xFF, 0x27, +- 0x05, 0xFD, 0x04, 0xFB, 0x10, 0x75, 0xA1, 0xFF, 0xFF, 0xFF, 0x86, 0x3E, 0xB4, 0xFE, 0x0B, 0x05, +- 0xB5, 0xFE, 0x02, 0x24, 0x9F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xFE, 0x07, 0x05, 0x78, 0x43, +- 0x01, 0x61, 0x29, 0x60, 0xEA, 0x78, 0x34, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x36, 0x44, 0x00, 0x7F, +- 0xEE, 0xA0, 0x60, 0x45, 0x05, 0x05, 0x20, 0x60, 0xBA, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x78, 0x43, 0x01, 0x61, 0x29, 0x60, 0xEA, 0x78, 0x78, 0x43, 0x01, 0x61, 0x29, 0x60, 0xEA, 0x78, +- 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x10, 0x02, 0x10, 0x64, +- 0x40, 0x40, 0x02, 0x64, 0x40, 0x50, 0x61, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x04, 0x00, 0x10, 0xE0, +- 0x46, 0x60, 0x09, 0xE0, 0x00, 0x00, 0x27, 0xF1, 0x00, 0x66, 0x20, 0x78, 0x42, 0xFE, 0x23, 0x58, +- 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x1A, 0x02, +- 0x0E, 0x60, 0xDD, 0xF3, 0x07, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, 0x04, 0x03, 0x03, 0x02, 0xDB, 0xF9, +- 0x00, 0x67, 0x10, 0x00, 0x00, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0xAD, 0x01, 0x36, 0x47, 0xFF, 0x23, +- 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x05, 0x00, 0x62, 0xFF, 0x20, 0x44, 0x80, 0xBC, +- 0x40, 0x40, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, +- 0x7F, 0x67, 0x02, 0x61, 0x31, 0x02, 0x0E, 0x60, 0xDD, 0xF3, 0x01, 0x7C, 0x20, 0xB5, 0x0C, 0xB5, +- 0x03, 0x03, 0x02, 0x02, 0xDB, 0xF9, 0xFF, 0xFF, 0x02, 0x61, 0x41, 0x56, 0xC7, 0xFE, 0x2A, 0x60, +- 0x1D, 0x78, 0xFF, 0xFF, 0x9D, 0xF1, 0x20, 0x44, 0x64, 0x40, 0xFF, 0x26, 0x1C, 0x00, 0x7F, 0xB4, +- 0x40, 0x40, 0x5C, 0x5E, 0x82, 0xFF, 0x26, 0x44, 0xFD, 0xB4, 0x40, 0x46, 0x5C, 0x41, 0x87, 0xFF, +- 0x62, 0xFF, 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x04, 0x03, 0x09, 0xF2, +- 0x8F, 0xFC, 0xAC, 0x86, 0xFB, 0x01, 0x95, 0xF3, 0xFF, 0xFF, 0x7F, 0xB4, 0x95, 0xFB, 0x06, 0x64, +- 0x13, 0x60, 0x1C, 0xFB, 0x2D, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x00, 0x67, 0x20, 0x40, +- 0x80, 0x2A, 0x02, 0x00, 0x7F, 0x67, 0x06, 0x61, 0x60, 0x45, 0x0E, 0x60, 0xDD, 0xF3, 0x61, 0x43, +- 0x04, 0xB4, 0x24, 0x44, 0x02, 0x03, 0x13, 0xFF, 0x56, 0x01, 0x3F, 0xB4, 0xB4, 0x84, 0xFF, 0x27, +- 0x05, 0xFD, 0x04, 0xFB, 0x20, 0x40, 0x80, 0x2A, 0x02, 0x00, 0x10, 0x75, 0x05, 0x00, 0x01, 0x64, +- 0x19, 0x60, 0xF7, 0xFB, 0x08, 0x60, 0x10, 0x75, 0x46, 0x01, 0x25, 0x46, 0x01, 0xF2, 0x08, 0xF0, +- 0x60, 0x47, 0x03, 0xB4, 0x03, 0xAC, 0x7F, 0x67, 0x03, 0x61, 0x08, 0x02, 0x26, 0x60, 0x20, 0x64, +- 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x24, 0x40, 0x01, 0x2B, 0x49, 0x00, 0x25, 0x44, 0x1F, 0xB4, 0xE0, 0x85, 0x2A, 0x60, 0xF4, 0x64, +- 0xC4, 0x98, 0xFF, 0xFF, 0xC0, 0xFE, 0x3D, 0x00, 0xC1, 0xFE, 0x3B, 0x00, 0xC2, 0xFE, 0x39, 0x00, +- 0xC3, 0xFE, 0x37, 0x00, 0xC4, 0xFE, 0x35, 0x00, 0xC5, 0xFE, 0x33, 0x00, 0xC6, 0xFE, 0x31, 0x00, +- 0xC7, 0xFE, 0x2F, 0x00, 0xC8, 0xFE, 0x2D, 0x00, 0xC9, 0xFE, 0x2B, 0x00, 0xCA, 0xFE, 0x29, 0x00, +- 0xCB, 0xFE, 0x27, 0x00, 0xCC, 0xFE, 0x25, 0x00, 0xCD, 0xFE, 0x23, 0x00, 0xCE, 0xFE, 0x21, 0x00, +- 0xCF, 0xFE, 0x1F, 0x00, 0xD0, 0xFE, 0x1D, 0x00, 0xD1, 0xFE, 0x1B, 0x00, 0xD2, 0xFE, 0x19, 0x00, +- 0xD3, 0xFE, 0x17, 0x00, 0xD4, 0xFE, 0x15, 0x00, 0xD5, 0xFE, 0x13, 0x00, 0xD6, 0xFE, 0x11, 0x00, +- 0xD7, 0xFE, 0x0F, 0x00, 0xD8, 0xFE, 0x0D, 0x00, 0xD9, 0xFE, 0x0B, 0x00, 0xDA, 0xFE, 0x09, 0x00, +- 0xDB, 0xFE, 0x07, 0x00, 0xDC, 0xFE, 0x05, 0x00, 0xDD, 0xFE, 0x03, 0x00, 0xDE, 0xFE, 0x01, 0x00, +- 0xDF, 0xFE, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x9F, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x9E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9D, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9C, 0xFE, 0xF0, 0x84, +- 0xFF, 0xFF, 0x9B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x9A, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x99, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x98, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x97, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x96, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x95, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x94, 0xFE, 0xF0, 0x84, +- 0xFF, 0xFF, 0x93, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x92, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x91, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x90, 0xFE, 0xF0, 0x84, 0x06, 0xFB, 0x8F, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x8E, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8D, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8C, 0xFE, 0xF0, 0x84, +- 0xFF, 0xFF, 0x8B, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x8A, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x89, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x88, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x87, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, +- 0x86, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x85, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x84, 0xFE, 0xF0, 0x84, +- 0xFF, 0xFF, 0x83, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x82, 0xFE, 0xF0, 0x84, 0xFF, 0xFF, 0x81, 0xFE, +- 0xF0, 0x84, 0xFF, 0xFF, 0x80, 0xFE, 0xF0, 0x84, 0x05, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x5C, 0x5C, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x27, 0x55, 0x00, 0x05, 0x60, +- 0x00, 0x63, 0x05, 0xFD, 0x30, 0x44, 0xBD, 0xDB, 0x31, 0x44, 0xBD, 0xDB, 0x32, 0x44, 0xBD, 0xDB, +- 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, 0x35, 0x44, 0xBD, 0xDB, 0x36, 0x44, 0xBD, 0xDB, +- 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, 0x39, 0x44, 0xBD, 0xDB, 0x3A, 0x44, 0xBD, 0xDB, +- 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, 0x3D, 0x44, 0xBD, 0xDB, 0x3E, 0x44, 0xBD, 0xDB, +- 0x3F, 0x44, 0xBD, 0xDB, 0x02, 0x61, 0x61, 0x44, 0x02, 0x36, 0x82, 0xFF, 0x03, 0x36, 0x83, 0xFF, +- 0x04, 0x36, 0x84, 0xFF, 0x05, 0x36, 0x85, 0xFF, 0x06, 0x36, 0x86, 0xFF, 0x07, 0x36, 0x87, 0xFF, +- 0x20, 0x44, 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, +- 0x24, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, +- 0x28, 0x44, 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, +- 0x2C, 0x44, 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, +- 0xDD, 0x81, 0x08, 0x3A, 0xD0, 0x01, 0x54, 0x00, 0x27, 0x40, 0x10, 0x26, 0x30, 0x00, 0x26, 0x44, +- 0x01, 0x36, 0x2D, 0x00, 0x02, 0x36, 0x82, 0xFF, 0x03, 0x36, 0x83, 0xFF, 0x04, 0x36, 0x84, 0xFF, +- 0x05, 0x36, 0x85, 0xFF, 0x06, 0x36, 0x86, 0xFF, 0x25, 0x44, 0x00, 0x36, 0x44, 0x40, 0x01, 0x36, +- 0x44, 0x41, 0x02, 0x36, 0x44, 0x42, 0x03, 0x36, 0x44, 0x43, 0x04, 0x36, 0x44, 0x44, 0x05, 0x36, +- 0x44, 0x45, 0x06, 0x36, 0x44, 0x46, 0x07, 0x36, 0x44, 0x47, 0x08, 0x36, 0x44, 0x48, 0x09, 0x36, +- 0x44, 0x49, 0x0A, 0x36, 0x44, 0x4A, 0x0B, 0x36, 0x44, 0x4B, 0x0C, 0x36, 0x44, 0x4C, 0x0D, 0x36, +- 0x44, 0x4D, 0x0E, 0x36, 0x44, 0x4E, 0x0F, 0x36, 0x44, 0x4F, 0x87, 0xFF, 0x21, 0x00, 0x25, 0x44, +- 0x10, 0x36, 0x44, 0x50, 0x11, 0x36, 0x44, 0x51, 0x12, 0x36, 0x44, 0x52, 0x13, 0x36, 0x44, 0x53, +- 0x14, 0x36, 0x44, 0x54, 0x15, 0x36, 0x44, 0x55, 0x16, 0x36, 0x44, 0x56, 0x17, 0x36, 0x44, 0x57, +- 0x18, 0x36, 0x44, 0x58, 0x19, 0x36, 0x44, 0x59, 0x1A, 0x36, 0x44, 0x5A, 0x1B, 0x36, 0x44, 0x5B, +- 0x1C, 0x36, 0x44, 0x5C, 0x1D, 0x36, 0x44, 0x5D, 0x1E, 0x36, 0x44, 0x5E, 0x1F, 0x36, 0x44, 0x5F, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0x46, 0xB5, 0x60, 0x58, 0x4F, 0xCE, 0x78, 0xFF, 0xFF, +- 0x03, 0x61, 0x7F, 0x67, 0x0A, 0x02, 0x00, 0xF0, 0x04, 0x64, 0x13, 0x60, 0x10, 0xFB, 0x5A, 0xD9, +- 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, +- 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x12, 0x02, 0x14, 0x64, 0x13, 0x60, +- 0x1C, 0xFB, 0x00, 0x60, 0x50, 0x63, 0x5A, 0xDD, 0x2C, 0x60, 0x75, 0x64, 0x9F, 0xFB, 0x2D, 0xFF, +- 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x2A, 0xF3, 0x05, 0xFB, 0x2B, 0xF3, 0x06, 0xFB, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x40, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, +- 0x0E, 0x02, 0x16, 0x64, 0x13, 0x60, 0x1C, 0xFB, 0x00, 0x60, 0x50, 0x63, 0x5A, 0xDD, 0x2C, 0x60, +- 0x90, 0x64, 0x9F, 0xFB, 0x2D, 0xFF, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x02, 0x61, 0x38, 0x02, 0x25, 0x45, +- 0x20, 0x44, 0x80, 0x2A, 0x34, 0x00, 0xF1, 0x60, 0x00, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x06, 0x03, +- 0xF1, 0x60, 0x02, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x2F, 0x03, 0x28, 0x00, 0x19, 0x60, 0x40, 0xF1, +- 0xB7, 0xF3, 0x20, 0x60, 0x22, 0x61, 0xA0, 0x84, 0xA1, 0xDB, 0x25, 0x45, 0x25, 0x60, 0x86, 0x63, +- 0x02, 0x61, 0xBD, 0xD3, 0xBD, 0xD1, 0xD4, 0x80, 0xBD, 0xD3, 0xBD, 0xD5, 0xCD, 0x81, 0x02, 0x03, +- 0x15, 0x03, 0xF7, 0x01, 0xA2, 0xFF, 0xA6, 0xD3, 0x40, 0x4C, 0x00, 0xA8, 0x67, 0x43, 0x0C, 0x02, +- 0xA2, 0xDD, 0x42, 0x48, 0x64, 0x41, 0xB6, 0x60, 0x58, 0x4D, 0x25, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0x28, 0xDB, 0x02, 0x03, 0x2C, 0x58, 0xA3, 0xFF, 0x0C, 0x61, 0x03, 0x00, 0x04, 0x61, 0x7F, 0x67, +- 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x64, 0x10, 0x60, 0x13, 0xFB, 0xFF, 0xFF, +- 0xC4, 0xFE, 0xF7, 0x01, 0xC6, 0xFE, 0xF5, 0x01, 0x7E, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, +- 0x02, 0x61, 0x3F, 0x02, 0x25, 0x45, 0xF8, 0x2B, 0x3B, 0x00, 0x2E, 0xF5, 0x67, 0x44, 0xD4, 0x80, +- 0x20, 0x60, 0xCC, 0x63, 0x39, 0x03, 0x79, 0x61, 0x24, 0x44, 0x01, 0x27, 0x29, 0x00, 0xA3, 0xFC, +- 0xA4, 0xF8, 0xBD, 0xD3, 0xA3, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, 0x64, 0x58, 0x08, 0xA3, +- 0xF8, 0x02, 0x08, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xA3, 0xD1, 0xFE, 0xA0, 0xFA, 0x60, 0x00, 0x64, +- 0xD0, 0x80, 0x14, 0x02, 0x13, 0x02, 0x04, 0xA3, 0xBE, 0xD3, 0xBD, 0xD1, 0x0F, 0x18, 0xD4, 0x80, +- 0x0D, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x64, 0x41, 0xDD, 0x81, 0xE1, 0x81, +- 0xCB, 0x83, 0x46, 0x65, 0x36, 0x60, 0x58, 0x4F, 0x22, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x0A, 0x00, +- 0xBD, 0xD3, 0xBE, 0xD1, 0xD4, 0x80, 0xCD, 0x81, 0x08, 0x24, 0x64, 0x58, 0x08, 0xA3, 0xF8, 0x02, +- 0x04, 0x61, 0x7F, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x0F, 0x64, 0x23, 0xFA, 0x67, 0x44, 0x24, 0xFA, +- 0x62, 0x41, 0x3C, 0x60, 0x00, 0x65, 0x1A, 0x63, 0x80, 0x60, 0x9E, 0x64, 0x65, 0x46, 0x58, 0xD0, +- 0x2E, 0xF5, 0x59, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xCB, 0x83, 0xBF, 0xD1, +- 0x4A, 0x65, 0x64, 0x43, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0x01, 0x26, 0xDC, 0x81, 0xE9, 0x84, +- 0xDC, 0x84, 0x23, 0xFA, 0x09, 0x00, 0x4B, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0xE8, 0x84, 0xDC, 0x84, +- 0x23, 0xFA, 0xBF, 0xD1, 0x4A, 0x65, 0x64, 0x43, 0x36, 0x60, 0x58, 0x4F, 0x22, 0x78, 0xFF, 0xFF, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xE0, 0xA0, 0x20, 0x64, 0x01, 0x06, +- 0x25, 0xFA, 0x23, 0xF2, 0xDF, 0xD1, 0xCC, 0x84, 0xE0, 0x85, 0x0B, 0x06, 0xBF, 0xD1, 0x64, 0x41, +- 0xD5, 0x80, 0x64, 0x43, 0x01, 0x06, 0x65, 0x41, 0x4A, 0x65, 0x2E, 0x60, 0x58, 0x4F, 0x7A, 0x78, +- 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0xDB, 0xF3, 0x02, 0x63, 0x23, 0xFC, 0x07, 0xB4, +- 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x4B, 0xD3, 0xBF, 0xD3, 0x60, 0x41, 0xC9, 0x83, +- 0xE9, 0x81, 0xDD, 0x81, 0xA3, 0xFA, 0xE0, 0x81, 0x3C, 0x60, 0x00, 0x67, 0x02, 0x24, 0x02, 0xA4, +- 0x60, 0x47, 0x40, 0x4B, 0xC9, 0x81, 0x4A, 0x65, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0xA5, 0xD8, +- 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF6, 0x1F, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, 0x60, 0x47, 0x25, 0xFA, +- 0x00, 0x7E, 0x60, 0x47, 0x01, 0x26, 0xDC, 0x84, 0x60, 0x41, 0xE8, 0x84, 0xD8, 0x84, 0x23, 0xFA, +- 0xAB, 0x01, 0xFC, 0xA3, 0xA3, 0xD1, 0x4C, 0x65, 0xA4, 0xD3, 0xDA, 0x83, 0x00, 0x7F, 0x25, 0xFA, +- 0x60, 0x41, 0x01, 0x26, 0xDD, 0x81, 0xE9, 0x84, 0xD8, 0x84, 0x23, 0xFA, 0x9D, 0x01, 0x2E, 0x60, +- 0x40, 0x63, 0xBF, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0xE8, 0x84, 0xDC, 0x84, 0x23, 0xFA, 0x4A, 0x65, +- 0x36, 0x60, 0x58, 0x4F, 0x22, 0x78, 0xFF, 0xFF, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x2E, 0x60, +- 0x40, 0x63, 0x23, 0xF2, 0xC0, 0x65, 0xCC, 0x84, 0xE0, 0x81, 0x0A, 0x04, 0xBF, 0xDB, 0xD5, 0x80, +- 0x07, 0x03, 0x01, 0x06, 0x65, 0x41, 0x61, 0x44, 0xBF, 0xDB, 0x4A, 0x65, 0x58, 0x4F, 0xA8, 0x00, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x03, 0x4E, 0x2D, 0x60, 0x58, 0x43, 0x55, 0x78, 0xFF, 0xFF, +- 0x2F, 0x60, 0x24, 0x61, 0x17, 0x60, 0x81, 0xF3, 0xA1, 0xDB, 0xCC, 0x84, 0xA8, 0x83, 0x05, 0x04, +- 0x2F, 0x60, 0x02, 0x64, 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x0E, 0x43, 0x82, 0x01, 0x23, 0xF2, +- 0x25, 0xF2, 0x02, 0xA8, 0xF8, 0xA0, 0x0F, 0x02, 0xEC, 0xA0, 0x0D, 0x04, 0x0C, 0x07, 0x19, 0x60, +- 0x4F, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x07, 0x19, 0x60, 0x4F, 0xFB, 0x19, 0x60, +- 0x53, 0xFB, 0x16, 0x60, 0xD8, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x1D, 0x60, +- 0xAE, 0x65, 0x60, 0x41, 0x1D, 0x60, 0x4A, 0x63, 0xA3, 0xDB, 0xFF, 0xA1, 0x48, 0x64, 0x58, 0xD0, +- 0x7E, 0xA8, 0x5B, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xFF, 0xA1, 0xD7, 0x80, 0x02, 0x03, +- 0x01, 0x03, 0xF5, 0x01, 0x2E, 0xF5, 0x00, 0x60, 0x2F, 0x65, 0x25, 0xF2, 0x00, 0x63, 0xCC, 0x84, +- 0x03, 0xA3, 0xFD, 0x05, 0x4A, 0x64, 0xD7, 0x80, 0x1C, 0x60, 0xE6, 0x61, 0x18, 0x05, 0xA1, 0xDD, +- 0xE3, 0x83, 0xFE, 0xA3, 0x58, 0xD0, 0x7E, 0xA8, 0x59, 0xD9, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, +- 0xF9, 0x1F, 0x00, 0x63, 0x59, 0xDD, 0x2E, 0xF5, 0x25, 0xF0, 0x0E, 0x60, 0x73, 0xF3, 0xD3, 0x80, +- 0x01, 0xB0, 0x04, 0x03, 0x01, 0xA4, 0x03, 0x03, 0xA2, 0xDB, 0x01, 0x00, 0xA2, 0xDD, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x1D, 0x60, 0x4A, 0x61, 0xA1, 0xD3, 0x23, 0xFA, 0xE0, 0x83, 0x4A, 0x65, +- 0x04, 0x02, 0x02, 0x63, 0x23, 0xFC, 0xA5, 0xFC, 0x09, 0x00, 0xDB, 0x83, 0x59, 0xD1, 0xA5, 0xD8, +- 0xDA, 0x85, 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x0E, 0x60, 0x73, 0xF3, 0x00, 0x61, 0x02, 0xA4, 0xFE, 0xA0, 0x23, 0xFA, 0x1B, 0x03, +- 0xFA, 0xA4, 0xFD, 0xA4, 0x01, 0xA1, 0xFD, 0x07, 0x61, 0x43, 0x23, 0xF2, 0x25, 0xFC, 0xE0, 0x83, +- 0x02, 0xA3, 0x1C, 0x60, 0xE6, 0x61, 0x00, 0x60, 0x4A, 0x64, 0x59, 0xD1, 0x58, 0xD8, 0x7E, 0x3A, +- 0x02, 0x00, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x25, 0xF2, 0x23, 0xF2, 0x01, 0xB0, 0xCC, 0x84, +- 0x04, 0x02, 0x23, 0xFA, 0x02, 0x00, 0x00, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x41, 0x4B, 0x65, 0x42, 0x80, 0x64, 0xD4, 0x85, 0x2B, 0x41, 0x00, 0xA1, 0x55, 0x8B, 0x0D, 0x03, +- 0x02, 0x04, 0x65, 0x41, 0x02, 0x00, 0x00, 0x64, 0x40, 0x4B, 0xCA, 0x84, 0x58, 0xD0, 0xC9, 0x81, +- 0xBD, 0xD9, 0xFC, 0x02, 0x00, 0xF4, 0x04, 0x65, 0xEC, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, +- 0xA3, 0xD3, 0x02, 0x7C, 0xA0, 0xD3, 0x23, 0xF8, 0xDC, 0x84, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x02, 0x64, 0x23, 0xFA, 0x01, 0x64, 0x9D, 0xFE, 0x02, 0x28, 0x02, 0x64, 0x25, 0xFA, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x7C, 0x23, 0xF8, 0x01, 0x64, 0x25, 0xFA, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0xFC, 0xA3, 0xA3, 0xD1, 0x02, 0x64, 0x23, 0xFA, 0xA4, 0xD3, 0x25, 0xFA, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x64, 0x23, 0xFA, 0x88, 0xFF, 0x75, 0x44, 0x8D, 0xFF, +- 0xE8, 0x87, 0xE8, 0x84, 0xE8, 0x84, 0x03, 0xB4, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x04, 0x64, 0x23, 0xFA, 0x86, 0xFF, 0x29, 0x44, 0x87, 0xFF, 0x25, 0xFA, 0x55, 0xF3, 0x52, 0xF1, +- 0x80, 0x65, 0xC4, 0x87, 0x00, 0x7F, 0x26, 0xFA, 0x64, 0x44, 0xC4, 0x87, 0x00, 0x7F, 0x27, 0xFA, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x05, 0x64, 0x23, 0xFA, 0x52, 0x63, 0xB4, 0xF3, 0x4B, 0xDA, +- 0xB3, 0xF3, 0x4B, 0xDA, 0xB2, 0xF3, 0x4B, 0xDA, 0x60, 0x41, 0x88, 0xFF, 0x72, 0x5C, 0x89, 0xFF, +- 0x4A, 0xD8, 0xA2, 0x48, 0x20, 0x23, 0x0E, 0x00, 0x64, 0x40, 0x80, 0x27, 0x15, 0x00, 0xDC, 0x84, +- 0xBD, 0xDA, 0xBD, 0xD2, 0x11, 0x04, 0xDC, 0x84, 0xA2, 0xDA, 0xA3, 0xD2, 0x0D, 0x04, 0xDC, 0x84, +- 0xA3, 0xDA, 0x0A, 0x00, 0x52, 0x63, 0xB4, 0xF3, 0x4B, 0xDA, 0xB3, 0xF3, 0x4B, 0xDA, 0xB2, 0xF3, +- 0x4B, 0xDA, 0x54, 0x90, 0x4C, 0x63, 0xE0, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF0, +- 0x23, 0xF2, 0x19, 0x60, 0x46, 0xF9, 0x02, 0xA8, 0x64, 0x44, 0x1F, 0x02, 0x3F, 0x40, 0x02, 0x2B, +- 0x16, 0x00, 0x00, 0x37, 0x14, 0x00, 0x01, 0x3B, 0x18, 0x00, 0x12, 0x60, 0x45, 0x65, 0x11, 0x60, +- 0x65, 0x63, 0xFF, 0xB7, 0x60, 0x5C, 0xA3, 0xD3, 0x08, 0xA3, 0x00, 0x7E, 0xD0, 0x80, 0xD7, 0x80, +- 0x03, 0x03, 0xF9, 0x02, 0x7F, 0x67, 0x0A, 0x00, 0xF4, 0xA3, 0xA3, 0xD1, 0x04, 0x00, 0x00, 0xBC, +- 0xF2, 0xA4, 0x03, 0x03, 0x02, 0x07, 0x16, 0x60, 0xCF, 0xF9, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x20, 0x63, 0x2E, 0x60, 0x00, 0x61, 0x48, 0x64, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x25, 0xF0, +- 0x20, 0x64, 0xD0, 0x81, 0xFF, 0xFF, 0x02, 0x07, 0x25, 0xFA, 0x0F, 0x00, 0x2E, 0x60, 0x04, 0x63, +- 0xC3, 0x83, 0x01, 0x2A, 0x06, 0x00, 0xCF, 0x83, 0xA3, 0xD3, 0xCD, 0x81, 0x00, 0x7F, 0xBD, 0xDB, +- 0x04, 0x03, 0x00, 0x64, 0xC9, 0x81, 0xBD, 0xDB, 0xFD, 0x02, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x01, 0x60, 0xA0, 0x62, 0x09, 0x02, 0xA2, 0xD9, 0x64, 0x41, +- 0x32, 0x44, 0x02, 0xB5, 0x00, 0xB9, 0xD4, 0x84, 0x08, 0x28, 0x02, 0xBC, 0x40, 0x52, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x01, 0x60, 0xA2, 0x62, 0x09, 0x02, +- 0xA2, 0xD9, 0x64, 0x41, 0x32, 0x44, 0x04, 0xB5, 0x00, 0xB9, 0xD4, 0x84, 0x08, 0x28, 0x04, 0xBC, +- 0x40, 0x52, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, 0x01, 0x60, +- 0xB0, 0x62, 0x15, 0x02, 0xA2, 0xD9, 0x64, 0x41, 0x32, 0x44, 0x40, 0xB5, 0x00, 0xB9, 0xD4, 0x84, +- 0x08, 0x24, 0x0C, 0x00, 0x40, 0xBC, 0x02, 0xB5, 0xD4, 0x84, 0x43, 0xF9, 0x37, 0x60, 0x76, 0x63, +- 0xD3, 0x80, 0x2F, 0x60, 0x50, 0x7C, 0x02, 0x03, 0x43, 0xFD, 0xA4, 0xDF, 0x40, 0x52, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x37, 0x60, 0x76, 0x64, 0x43, 0xFB, 0x2D, 0x60, 0x5B, 0x78, 0xFF, 0xFF, +- 0x23, 0xF2, 0x25, 0xF0, 0x01, 0x60, 0xAC, 0x63, 0x7F, 0x67, 0x39, 0x18, 0xA3, 0xD9, 0x26, 0xF0, +- 0x7F, 0x67, 0x35, 0x18, 0x5B, 0xD9, 0x16, 0x60, 0x87, 0xF3, 0x25, 0xF0, 0x60, 0x40, 0x03, 0x3A, +- 0x2D, 0x00, 0xA6, 0xF3, 0x20, 0x63, 0xE3, 0x83, 0x60, 0x46, 0x0F, 0xF8, 0x30, 0x61, 0x94, 0xFA, +- 0x01, 0x61, 0x91, 0xFA, 0x16, 0x64, 0x12, 0xFA, 0x60, 0x40, 0x10, 0x36, 0x05, 0x00, 0x12, 0x36, +- 0x08, 0x00, 0x0C, 0x36, 0x0B, 0x00, 0x0F, 0x00, 0x40, 0x61, 0xA1, 0x80, 0x0A, 0x64, 0x11, 0x02, +- 0xF3, 0x01, 0x10, 0x61, 0xA1, 0x80, 0x0E, 0x64, 0x0C, 0x02, 0xEE, 0x01, 0x08, 0x61, 0xA1, 0x80, +- 0x10, 0x64, 0x07, 0x02, 0xE9, 0x01, 0xE1, 0x81, 0xA1, 0x80, 0x05, 0x05, 0xC8, 0x84, 0x01, 0x02, +- 0xE3, 0x01, 0x12, 0xFA, 0x91, 0xFA, 0x66, 0x44, 0x02, 0xA6, 0xD7, 0x1F, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x25, 0xF2, 0x19, 0x60, 0x45, 0xFB, 0x19, 0x60, 0x4C, 0xF3, 0xFF, 0xFF, 0x60, 0x40, +- 0x08, 0x26, 0x18, 0x00, 0x19, 0x60, 0x45, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0A, 0x00, +- 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0x60, 0x44, 0xA2, 0xDB, 0x19, 0x60, 0x45, 0xF3, +- 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x2A, 0x06, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x04, 0xBC, +- 0x60, 0x44, 0xA2, 0xDB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, 0x02, 0xA8, +- 0x00, 0x67, 0x02, 0x02, 0x2D, 0xF9, 0x2C, 0xF9, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF2, +- 0x02, 0xA8, 0x00, 0xA8, 0x0A, 0x02, 0x07, 0x03, 0xD0, 0xA0, 0x30, 0x65, 0x03, 0x04, 0xA7, 0xA0, +- 0x59, 0x65, 0x01, 0x06, 0x65, 0x44, 0x16, 0x60, 0xCE, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x25, 0xF2, 0x19, 0x60, 0x4C, 0xFB, 0xFF, 0xFF, 0x08, 0x2A, 0x25, 0x00, 0x19, 0x60, 0x7B, 0xF3, +- 0xFF, 0xFF, 0xE9, 0xB4, 0x60, 0x44, 0x19, 0x60, 0x4C, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x26, +- 0x02, 0xBC, 0x64, 0x40, 0x02, 0x2A, 0x04, 0xBC, 0x64, 0x40, 0x04, 0x26, 0x08, 0x00, 0x19, 0x60, +- 0x7B, 0xFB, 0x13, 0x64, 0xCB, 0xFB, 0x01, 0x60, 0x67, 0x64, 0x37, 0xFB, 0x0C, 0x00, 0x10, 0xBC, +- 0x19, 0x60, 0x7B, 0xFB, 0x08, 0x64, 0xCB, 0xFB, 0xA1, 0xF3, 0x01, 0x60, 0x67, 0x7C, 0x60, 0x40, +- 0x01, 0x27, 0x5B, 0x7C, 0x37, 0xF9, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0x19, 0x60, +- 0x4D, 0xFB, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0x19, 0x60, 0x4E, 0xFB, 0x00, 0x67, +- 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF2, 0x19, 0x60, 0x89, 0xFB, 0xFF, 0xFF, 0x0F, 0x22, 0x41, 0x75, +- 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x64, 0x01, 0x00, 0x00, 0x64, 0x1B, 0x60, 0xFE, 0xFB, +- 0x7E, 0x60, 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x0E, 0x02, 0x06, 0x61, +- 0x41, 0x56, 0xC7, 0xFE, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, +- 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, +- 0xC0, 0x64, 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x0E, 0x02, 0x08, 0x61, 0x41, 0x56, +- 0xC7, 0xFE, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, 0x00, 0x7F, +- 0x60, 0x41, 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7F, 0x60, 0xC0, 0x64, +- 0x24, 0x45, 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x0E, 0x02, 0x0A, 0x61, 0x41, 0x56, 0xC7, 0xFE, +- 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, 0x00, 0x7F, 0x60, 0x41, +- 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x7E, 0x60, 0xC0, 0x64, 0x24, 0x45, +- 0xA4, 0x80, 0x7F, 0x67, 0x02, 0x61, 0x11, 0x02, 0x65, 0x43, 0x19, 0x60, 0xA5, 0xFD, 0x0C, 0x61, +- 0x41, 0x56, 0xC7, 0xFE, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x36, 0x47, 0xFF, 0x23, 0x04, 0x00, +- 0x00, 0x7F, 0x60, 0x41, 0x7F, 0x67, 0x01, 0x00, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x20, 0x64, +- 0x23, 0xFA, 0x4A, 0x61, 0x10, 0x60, 0xDA, 0x64, 0xA0, 0xD1, 0xA1, 0xD8, 0x58, 0xD1, 0x59, 0xD8, +- 0x58, 0xD1, 0x59, 0xD8, 0x01, 0xA1, 0x10, 0x60, 0xF2, 0x63, 0x5D, 0x65, 0xA3, 0xD3, 0x02, 0xA3, +- 0x02, 0x1B, 0x7F, 0x64, 0x01, 0x00, 0xA3, 0xD3, 0x60, 0xFE, 0x5D, 0xDA, 0x20, 0xFE, 0xD5, 0x80, +- 0x04, 0xA3, 0xF4, 0x02, 0x01, 0xA1, 0x10, 0x60, 0xE0, 0x64, 0xA0, 0xD1, 0xA1, 0xD8, 0x58, 0xD1, +- 0x59, 0xD8, 0x58, 0xD1, 0x59, 0xD8, 0x01, 0xA1, 0x60, 0xFE, 0x07, 0x63, 0x7F, 0x64, 0xCF, 0x83, +- 0x5D, 0xDA, 0xFD, 0x02, 0x20, 0xFE, 0x12, 0x60, 0x40, 0x7C, 0x11, 0x60, 0x62, 0x63, 0x7F, 0x65, +- 0xA3, 0xD3, 0x02, 0xA3, 0x02, 0x1B, 0x7F, 0x64, 0x01, 0x00, 0xA3, 0xD3, 0x60, 0xFE, 0x5D, 0xDA, +- 0x20, 0xFE, 0xD5, 0x80, 0x06, 0xA3, 0x03, 0x02, 0x46, 0x45, 0x00, 0xF4, 0x03, 0x61, 0xD3, 0x80, +- 0xFF, 0xFF, 0xEE, 0x04, 0x25, 0x46, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x02, 0x63, 0x7D, 0xF3, +- 0x23, 0xFC, 0x60, 0x40, 0x01, 0x23, 0x17, 0x00, 0x01, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x11, 0x60, +- 0x60, 0x61, 0x12, 0x60, 0x40, 0x65, 0xA1, 0xD1, 0xD5, 0x80, 0xD0, 0x80, 0x0B, 0x03, 0x02, 0x03, +- 0x08, 0xA1, 0xF9, 0x01, 0x04, 0xA1, 0xA1, 0xD3, 0x01, 0x60, 0x00, 0x65, 0x60, 0x47, 0xFF, 0xB4, +- 0xB4, 0x84, 0x01, 0x00, 0xFF, 0x64, 0x25, 0xFA, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x0C, 0x63, +- 0x23, 0xFC, 0xE2, 0xF3, 0x13, 0x60, 0xF2, 0x63, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x06, 0x0C, 0xA3, +- 0xFB, 0x01, 0x48, 0x61, 0x61, 0x44, 0x18, 0xA5, 0x60, 0xFE, 0xBD, 0xD3, 0x20, 0xFE, 0x00, 0x7F, +- 0x59, 0xDA, 0xD5, 0x80, 0xFF, 0xFF, 0xF8, 0x04, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, 0x25, 0xF0, +- 0x17, 0x60, 0x80, 0xF9, 0x11, 0x00, 0x0C, 0x60, 0xFE, 0x62, 0x40, 0x63, 0x5A, 0xDF, 0xFE, 0x1F, +- 0x04, 0x65, 0x0C, 0x60, 0xFE, 0x61, 0x48, 0x64, 0x3E, 0x63, 0x7C, 0xA8, 0x58, 0xD0, 0x59, 0xD9, +- 0x02, 0x02, 0x00, 0xF4, 0x02, 0x64, 0xF9, 0x1F, 0x17, 0x60, 0x80, 0xF1, 0x0C, 0x60, 0xDA, 0x65, +- 0x02, 0xFE, 0x64, 0x44, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x87, 0x60, 0x41, 0x64, 0x44, 0xE0, 0x84, +- 0xE0, 0x84, 0xC4, 0x84, 0x3E, 0xFB, 0x60, 0x42, 0x61, 0x44, 0x03, 0xA2, 0x60, 0xFE, 0xA2, 0xDB, +- 0x20, 0xFE, 0x64, 0x44, 0x0D, 0x60, 0x00, 0x65, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, +- 0xC4, 0x84, 0x40, 0xFB, 0xFF, 0xFF, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x5C, 0x41, +- 0x25, 0xF2, 0xFF, 0xFF, 0x40, 0x42, 0x80, 0x2B, 0x04, 0x00, 0xFF, 0xB4, 0x40, 0x42, 0x01, 0x64, +- 0x40, 0x41, 0xA6, 0xF3, 0x46, 0x4B, 0x60, 0x46, 0x20, 0x63, 0xE3, 0x83, 0xAB, 0x46, 0x26, 0xF0, +- 0xAB, 0x46, 0x59, 0xF8, 0xAB, 0x46, 0x27, 0xF0, 0xAB, 0x46, 0x5A, 0xF8, 0xAB, 0x46, 0x28, 0xF0, +- 0xAB, 0x46, 0x5B, 0xF8, 0x66, 0x44, 0x02, 0xA6, 0xF1, 0x1F, 0xA6, 0xF3, 0xFF, 0xFF, 0x60, 0x46, +- 0xAB, 0x46, 0x0C, 0x60, 0x38, 0x65, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xC4, 0x81, 0xC9, 0x81, 0x52, 0x64, 0x0E, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, +- 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF0, 0xA1, 0x76, 0x64, 0x0E, 0x63, 0x59, 0xD1, +- 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, 0x22, 0x44, 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, +- 0x0C, 0x60, 0x9A, 0x65, 0xC4, 0x81, 0x60, 0x45, 0xC9, 0x81, 0x62, 0x64, 0x06, 0x63, 0x58, 0xD0, +- 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF8, 0xA1, 0xB6, 0x64, +- 0x06, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, 0x65, 0x44, 0x0C, 0x60, 0xBA, 0x65, +- 0xC4, 0x81, 0xC9, 0x81, 0x6A, 0x64, 0x06, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x22, 0x44, +- 0xFF, 0xB4, 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x84, 0x0C, 0x60, 0x80, 0x65, 0xC4, 0x81, 0x72, 0x64, +- 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0xAB, 0x46, 0x21, 0x44, 0x01, 0x2A, 0x06, 0x00, +- 0xFA, 0xA1, 0x90, 0x64, 0x04, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0x3B, 0xF0, 0x21, 0x44, +- 0x01, 0x2A, 0x13, 0x00, 0x22, 0x44, 0x3D, 0xFB, 0x60, 0x41, 0x02, 0xFE, 0xF8, 0x84, 0xF8, 0x84, +- 0xF8, 0x84, 0x3C, 0xFB, 0x0C, 0x60, 0x7C, 0x63, 0x88, 0xFF, 0xCD, 0x81, 0x06, 0xA3, 0xFD, 0x0D, +- 0x8D, 0xFF, 0x3B, 0xFD, 0x64, 0x47, 0x80, 0xBF, 0x60, 0x5C, 0x22, 0x43, 0x80, 0x61, 0x88, 0xFF, +- 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0xB1, 0x84, 0x3B, 0xFA, +- 0x1F, 0x63, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0x3B, 0xF0, 0x66, 0x44, 0xB1, 0x9C, 0x3B, 0xF8, +- 0x02, 0xA6, 0xFA, 0x1F, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, +- 0x25, 0xF0, 0x02, 0xA8, 0x00, 0x67, 0x22, 0x02, 0x3D, 0xF1, 0x64, 0x44, 0x03, 0xB4, 0x40, 0x42, +- 0xD0, 0x80, 0xA6, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xBB, 0xF4, 0x80, 0x61, 0x02, 0x02, 0xE3, 0x83, +- 0xEB, 0x83, 0x22, 0x44, 0x88, 0xFF, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, +- 0x31, 0x91, 0x9D, 0x85, 0xA7, 0x83, 0x3B, 0xFC, 0x1F, 0x63, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, +- 0xBB, 0xF2, 0x66, 0x44, 0xA5, 0x81, 0xBB, 0xFA, 0x02, 0xA6, 0xFA, 0x1F, 0x00, 0x67, 0x23, 0x58, +- 0xFF, 0xFF, 0x27, 0xF2, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, +- 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, +- 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, +- 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, +- 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, +- 0x2A, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, 0x30, 0x7C, 0xB0, 0x84, 0xA2, 0xDA, +- 0x4E, 0x61, 0x76, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, +- 0x90, 0x64, 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0xD9, 0x81, +- 0xA0, 0x64, 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0xD9, 0x81, +- 0xB6, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x00, 0x67, +- 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x27, 0xF2, +- 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, +- 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, +- 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, +- 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, +- 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x0D, 0x00, 0x43, 0x4B, +- 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, 0x30, 0x61, 0x9D, 0x85, 0xA4, 0x84, 0xA2, 0xDA, 0xAB, 0x46, +- 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, +- 0x00, 0x64, 0x40, 0x41, 0x4A, 0x64, 0xA0, 0xD2, 0xFF, 0xFF, 0x40, 0x42, 0x80, 0x2B, 0x04, 0x00, +- 0xFF, 0xB4, 0x40, 0x42, 0x01, 0x64, 0x40, 0x41, 0xA6, 0xF3, 0x46, 0x4B, 0x60, 0x46, 0x20, 0x63, +- 0xE3, 0x83, 0xAB, 0x46, 0x32, 0xF0, 0xAB, 0x46, 0x59, 0xF8, 0xAB, 0x46, 0x33, 0xF0, 0xAB, 0x46, +- 0x5A, 0xF8, 0xAB, 0x46, 0x34, 0xF0, 0xAB, 0x46, 0x5B, 0xF8, 0x66, 0x44, 0x02, 0xA6, 0xF1, 0x1F, +- 0xA6, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xAB, 0x46, 0x0C, 0x60, 0x38, 0x65, 0x22, 0x44, 0xFF, 0xB4, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, 0xC9, 0x81, 0x4A, 0x64, 0x0E, 0x63, +- 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x21, 0x44, 0x01, 0x2A, 0x08, 0x00, 0xAB, 0x46, 0xF0, 0xA1, +- 0x76, 0x64, 0x0E, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0xAB, 0x46, 0x22, 0x44, 0xFF, 0xB4, +- 0xE0, 0x84, 0xE0, 0x85, 0xC4, 0x84, 0x0C, 0x60, 0x80, 0x65, 0xC4, 0x81, 0x5A, 0x64, 0x04, 0x63, +- 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0xAB, 0x46, 0x21, 0x44, 0x01, 0x2A, 0x06, 0x00, 0xFA, 0xA1, +- 0x90, 0x64, 0x04, 0x63, 0x59, 0xD1, 0x58, 0xD8, 0xFD, 0x1F, 0x3B, 0xF0, 0x21, 0x44, 0x01, 0x2A, +- 0x13, 0x00, 0x22, 0x44, 0x3D, 0xFB, 0x60, 0x41, 0x02, 0xFE, 0xF8, 0x84, 0xF8, 0x84, 0xF8, 0x84, +- 0x3C, 0xFB, 0x0C, 0x60, 0x7C, 0x63, 0x88, 0xFF, 0xCD, 0x81, 0x06, 0xA3, 0xFD, 0x0D, 0x8D, 0xFF, +- 0x3B, 0xFD, 0x64, 0x47, 0x80, 0xBF, 0x60, 0x5C, 0x22, 0x43, 0x80, 0x61, 0x88, 0xFF, 0xCF, 0x83, +- 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, 0xB1, 0x84, 0x3B, 0xFA, 0x1F, 0x63, +- 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0x3B, 0xF0, 0x66, 0x44, 0xB1, 0x9C, 0x3B, 0xF8, 0x02, 0xA6, +- 0xFA, 0x1F, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x23, 0xF2, 0x25, 0xF0, +- 0x02, 0xA8, 0x00, 0x67, 0x22, 0x02, 0x3D, 0xF1, 0x64, 0x44, 0x03, 0xB4, 0x40, 0x42, 0xD0, 0x80, +- 0xA6, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0xBB, 0xF4, 0x80, 0x61, 0x02, 0x02, 0xE3, 0x83, 0xEB, 0x83, +- 0x22, 0x44, 0x88, 0xFF, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x0D, 0x8D, 0xFF, 0x61, 0x47, 0x31, 0x91, +- 0x9D, 0x85, 0xA7, 0x83, 0x3B, 0xFC, 0x1F, 0x63, 0xE3, 0x83, 0x66, 0x44, 0x02, 0xA6, 0xBB, 0xF2, +- 0x66, 0x44, 0xA5, 0x81, 0xBB, 0xFA, 0x02, 0xA6, 0xFA, 0x1F, 0x00, 0x67, 0x23, 0x58, 0xFF, 0xFF, +- 0x27, 0xF2, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, +- 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, +- 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, +- 0x63, 0x46, 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x21, 0x00, +- 0x43, 0x4B, 0xAB, 0x46, 0x3B, 0xF2, 0x80, 0x60, 0x30, 0x7C, 0xB0, 0x84, 0xA2, 0xDA, 0x4E, 0x61, +- 0x76, 0x64, 0x0E, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x90, 0x64, +- 0x04, 0x63, 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0xA0, 0x64, 0x04, 0x63, +- 0xAB, 0x46, 0x59, 0xD0, 0xAB, 0x46, 0x58, 0xD8, 0xFB, 0x1F, 0x00, 0x67, 0x00, 0x61, 0x23, 0x58, +- 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0x27, 0xF2, 0x1D, 0x60, 0xC0, 0x65, +- 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, +- 0x16, 0x18, 0x61, 0x46, 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, +- 0x26, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, +- 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA6, 0xF3, +- 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x01, 0x03, 0x0D, 0x00, 0x43, 0x4B, 0xAB, 0x46, 0x3B, 0xF2, +- 0x80, 0x60, 0x30, 0x61, 0x9D, 0x85, 0xA4, 0x84, 0xA2, 0xDA, 0xAB, 0x46, 0x00, 0x67, 0x00, 0x61, +- 0x23, 0x58, 0xFF, 0xFF, 0x01, 0x67, 0x20, 0x61, 0x23, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x46, 0x45, +- 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0x00, 0xF4, 0x01, 0xF2, 0x66, 0x5C, 0x25, 0x46, +- 0x56, 0x02, 0x70, 0x27, 0x54, 0x00, 0x12, 0x64, 0x03, 0xFA, 0x04, 0xF8, 0x0E, 0xF2, 0x87, 0xFC, +- 0x8D, 0xFC, 0x8E, 0xFC, 0xDA, 0x82, 0x16, 0x61, 0x00, 0x63, 0xC9, 0x81, 0x5A, 0xDC, 0xFD, 0x02, +- 0x60, 0x40, 0xF0, 0x3B, 0x16, 0x00, 0x32, 0x44, 0xAC, 0xF3, 0x01, 0xB0, 0xFA, 0xA0, 0x08, 0x24, +- 0x2C, 0x05, 0xDC, 0x83, 0xF0, 0x67, 0x0E, 0xFA, 0x26, 0x60, 0x04, 0x64, 0x2B, 0xDB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xAC, 0xFD, 0x2B, 0xFF, 0xFE, 0x64, 0x3B, 0x42, 0x4A, 0xDB, +- 0x4F, 0x00, 0xAD, 0xF3, 0x05, 0x65, 0xD4, 0x80, 0xDC, 0x83, 0x17, 0x05, 0xAD, 0xFD, 0x98, 0xFE, +- 0x04, 0x04, 0x00, 0x7F, 0x08, 0x7E, 0x0E, 0xFA, 0x3B, 0xFF, 0x25, 0x60, 0xF8, 0x64, 0x2B, 0xDB, +- 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0x0E, 0xF2, 0x2B, 0xFF, 0x60, 0x40, 0x08, 0x26, +- 0xF7, 0xFE, 0xFD, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x32, 0x00, 0xA9, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, +- 0xFF, 0xFF, 0x0D, 0x04, 0x26, 0x60, 0x10, 0x64, 0x2B, 0xDB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFC, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0x21, 0x00, 0x46, 0x45, +- 0x00, 0x64, 0x2B, 0xDB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, 0x70, 0x67, 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, +- 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, 0x80, 0xFC, 0x05, 0xFA, 0xB6, 0x60, 0x58, 0x4E, +- 0xF5, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, 0xFF, 0x64, 0x3B, 0x42, 0x4A, 0xDB, 0xD4, 0xFE, +- 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0x25, 0x60, 0xFE, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x0D, 0x00, +- 0x25, 0x60, 0xF2, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x18, 0x00, 0x26, 0x60, 0x0A, 0x64, 0x40, 0x47, +- 0x58, 0x4F, 0x03, 0x00, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x27, 0xD5, 0x0E, 0xF2, 0x0B, 0x18, +- 0x60, 0x40, 0x01, 0x2A, 0x08, 0x00, 0x26, 0x60, 0x20, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, +- 0x08, 0x78, 0xFF, 0xFF, 0xF2, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD5, 0x0E, 0xF2, 0x14, 0x18, +- 0x60, 0x40, 0x01, 0x2A, 0x11, 0x00, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xA2, 0xFF, +- 0xAD, 0xF3, 0x02, 0x02, 0xCC, 0x84, 0xAD, 0xFB, 0x26, 0x60, 0x20, 0x64, 0x40, 0x4B, 0x34, 0x60, +- 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0xE9, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xFB, 0x64, 0x3A, 0x42, +- 0x4A, 0xDB, 0xA2, 0xFF, 0xB0, 0xF3, 0xAC, 0xF3, 0xCC, 0x80, 0xFD, 0xA0, 0x01, 0x14, 0x1D, 0x05, +- 0xB5, 0x60, 0x58, 0x4D, 0xFA, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, 0x17, 0x03, 0xF0, 0x67, 0x0E, 0xFA, +- 0x26, 0x60, 0x04, 0x64, 0x13, 0x60, 0x10, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xF6, 0x64, 0x3A, 0x42, 0x4A, 0xDB, 0xB0, 0xF3, 0xAC, 0xF3, 0xCC, 0x83, +- 0xDC, 0x84, 0x01, 0x15, 0xB0, 0xFD, 0xAC, 0xFB, 0xD4, 0xFE, 0xAF, 0xF3, 0xAD, 0xF3, 0x00, 0xA8, +- 0xAE, 0xF1, 0x03, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x26, 0x05, 0xB5, 0x60, 0x58, 0x4D, 0xFA, 0x78, +- 0xFF, 0xFF, 0xA2, 0xFF, 0x20, 0x03, 0x00, 0x63, 0xAF, 0xF3, 0x0E, 0xFC, 0xCC, 0x84, 0xFF, 0x3A, +- 0xAF, 0xFB, 0x98, 0xFE, 0x03, 0x04, 0x08, 0xBB, 0x0E, 0xFC, 0x3B, 0xFF, 0x25, 0x60, 0xF8, 0x64, +- 0x13, 0x60, 0x10, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xF7, 0x64, 0x3A, 0x42, 0x4A, 0xDB, 0xAD, 0xF3, 0x0E, 0xF2, 0xDC, 0x83, 0x08, 0xB0, 0xAD, 0xFD, +- 0x08, 0x28, 0xF7, 0xFE, 0xD4, 0xFE, 0xA3, 0xFF, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0xB9, 0xFE, +- 0x13, 0xFF, 0x24, 0x40, 0x80, 0x2B, 0x0B, 0x00, 0xA2, 0xFF, 0x25, 0x46, 0x09, 0xF4, 0x0E, 0xF2, +- 0x05, 0x18, 0x08, 0xBC, 0x0E, 0xFA, 0xFF, 0xFF, 0xF7, 0xFE, 0x01, 0x00, 0xD8, 0xFE, 0xA3, 0xFF, +- 0x25, 0x46, 0x3E, 0xF2, 0x00, 0xF4, 0x08, 0xF0, 0x25, 0x46, 0x06, 0xB4, 0xFF, 0x7F, 0x10, 0xBC, +- 0x06, 0x26, 0xFD, 0x7F, 0x0E, 0xFA, 0x3E, 0xF2, 0x3F, 0xF2, 0x60, 0x41, 0x08, 0x2A, 0x64, 0x47, +- 0x3F, 0xFA, 0x60, 0x45, 0xB9, 0xFC, 0x16, 0x60, 0xAA, 0xF3, 0xA3, 0xFC, 0xAB, 0xFC, 0x91, 0xFC, +- 0xD4, 0x80, 0x18, 0x60, 0x21, 0x65, 0xA5, 0x80, 0x01, 0x04, 0x07, 0x03, 0x23, 0xF0, 0x08, 0x64, +- 0xB0, 0x84, 0xA2, 0xDA, 0x35, 0x60, 0xEA, 0x78, 0xFF, 0xFF, 0x36, 0x60, 0x58, 0x4F, 0x30, 0x78, +- 0xFF, 0xFF, 0x0B, 0x04, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x2C, 0x60, 0xEE, 0x64, +- 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x83, 0x00, 0xDB, 0xF3, 0xA6, 0xF1, 0x07, 0xB4, +- 0x64, 0x43, 0xFD, 0xA0, 0x2C, 0xF2, 0x71, 0x02, 0x01, 0xB0, 0x64, 0x43, 0x78, 0x02, 0x2E, 0xF2, +- 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, +- 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x2E, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, +- 0x0C, 0x02, 0x61, 0x46, 0x2D, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, +- 0x2C, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, +- 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x51, 0x03, 0x63, 0x46, 0x80, 0xF6, +- 0x25, 0x46, 0x43, 0x18, 0x2E, 0xF2, 0x66, 0x41, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, +- 0xA6, 0xF1, 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, +- 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, +- 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, +- 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, +- 0x60, 0x43, 0x61, 0x46, 0x43, 0x4B, 0x2C, 0xF0, 0xAD, 0xF0, 0x2E, 0xF2, 0xAB, 0x46, 0x03, 0xF8, +- 0x84, 0xF8, 0x05, 0xFA, 0x03, 0x64, 0x06, 0xFA, 0xAB, 0x46, 0x1F, 0x60, 0xC2, 0x61, 0xA1, 0xD3, +- 0x20, 0x60, 0x04, 0x7C, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, +- 0x49, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xA1, 0xDB, 0x0A, 0x00, 0xDB, 0xF3, 0x02, 0xA3, 0xFE, 0xA0, +- 0xF9, 0xA0, 0x01, 0x06, 0x04, 0x02, 0x23, 0xF0, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x07, 0xFC, +- 0x23, 0xF2, 0xFF, 0xFF, 0x24, 0x1B, 0x16, 0x60, 0xAB, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x00, 0x3A, +- 0x0F, 0x00, 0x25, 0x60, 0xC8, 0x64, 0x13, 0x60, 0x10, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xC1, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x1D, 0x00, +- 0x25, 0x60, 0xDA, 0x64, 0x13, 0x60, 0x10, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0x0E, 0xF2, 0xC8, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x0E, 0x00, 0x25, 0x60, +- 0xEC, 0x64, 0x13, 0x60, 0x10, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x0E, 0xF2, 0xCE, 0xFE, 0x10, 0xAC, 0x0E, 0xFA, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, +- 0xCB, 0x84, 0xC9, 0x83, 0xFF, 0xFF, 0x08, 0x04, 0x58, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, +- 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x2F, 0x58, 0xFF, 0xFF, 0x3E, 0xF2, 0xC9, 0xF1, +- 0x08, 0xB0, 0x19, 0xF8, 0x57, 0x02, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF3, 0x30, 0xFA, 0x60, 0x45, +- 0xEC, 0xF3, 0x31, 0xFA, 0x46, 0x4A, 0x00, 0xF4, 0x60, 0x43, 0x05, 0xF2, 0x06, 0xF2, 0xD0, 0x80, +- 0x07, 0xF0, 0x05, 0x02, 0xD4, 0x80, 0xD3, 0x80, 0x02, 0x02, 0xDB, 0xF3, 0x03, 0x03, 0xAA, 0x46, +- 0x42, 0xFE, 0x41, 0x00, 0x60, 0x40, 0x03, 0x2A, 0x20, 0x00, 0x02, 0xF2, 0x03, 0xF0, 0x04, 0xF2, +- 0x60, 0x43, 0xAA, 0x46, 0x2C, 0xFC, 0x2D, 0xF8, 0x2E, 0xFA, 0x7F, 0xF1, 0x32, 0xF8, 0x80, 0xF1, +- 0x33, 0xF8, 0x81, 0xF1, 0x34, 0xF8, 0x08, 0x64, 0x32, 0x40, 0x04, 0x2A, 0x0D, 0x00, 0x2C, 0xF0, +- 0x39, 0xF0, 0x64, 0x40, 0x01, 0x26, 0x08, 0x00, 0x3E, 0xF2, 0xFF, 0xFF, 0x00, 0x60, 0xC0, 0xB4, +- 0xE8, 0x84, 0xB0, 0x9C, 0x39, 0xF8, 0x88, 0x64, 0x1C, 0x00, 0x02, 0xF2, 0x03, 0xF0, 0x04, 0xF2, +- 0x60, 0x43, 0xAA, 0x46, 0x32, 0xFC, 0x33, 0xF8, 0x34, 0xFA, 0x7F, 0xF1, 0x2C, 0xF8, 0x80, 0xF1, +- 0x2D, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, 0x01, 0x60, 0x08, 0x64, 0x32, 0x40, 0x04, 0x2A, 0x09, 0x00, +- 0x3E, 0xF2, 0x39, 0xF0, 0x00, 0x60, 0xC0, 0xB4, 0xE8, 0x84, 0xB0, 0x9C, 0x39, 0xF8, 0x01, 0x60, +- 0x88, 0x64, 0x2A, 0xFA, 0x02, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x36, 0x60, 0x22, 0x63, 0x20, 0x44, +- 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, +- 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, +- 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, +- 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, 0x1B, 0x60, +- 0x0B, 0xFD, 0x37, 0x60, 0x42, 0x63, 0x1B, 0x60, 0x0C, 0xFD, 0x30, 0x44, 0x1B, 0x60, 0x0D, 0xFB, +- 0x31, 0x44, 0x1B, 0x60, 0x0E, 0xFB, 0x32, 0x44, 0x1B, 0x60, 0x0F, 0xFB, 0x33, 0x44, 0x1B, 0x60, +- 0x10, 0xFB, 0x81, 0xFF, 0x91, 0xFF, 0x58, 0x51, 0x44, 0x00, 0x82, 0xFF, 0x92, 0xFF, 0x58, 0x51, +- 0x40, 0x00, 0x83, 0xFF, 0x93, 0xFF, 0x58, 0x51, 0x3C, 0x00, 0x84, 0xFF, 0x94, 0xFF, 0x58, 0x51, +- 0x38, 0x00, 0x85, 0xFF, 0x95, 0xFF, 0x58, 0x51, 0x34, 0x00, 0x86, 0xFF, 0x96, 0xFF, 0x58, 0x51, +- 0x30, 0x00, 0x87, 0xFF, 0x97, 0xFF, 0x58, 0x51, 0x2C, 0x00, 0x80, 0xFF, 0x90, 0xFF, 0x99, 0xFF, +- 0x1B, 0x60, 0x0B, 0xF1, 0x30, 0x44, 0x64, 0x43, 0xBD, 0xDB, 0x31, 0x44, 0xBD, 0xDB, 0x32, 0x44, +- 0xBD, 0xDB, 0x33, 0x44, 0xBD, 0xDB, 0x34, 0x44, 0xBD, 0xDB, 0x35, 0x44, 0xBD, 0xDB, 0x36, 0x44, +- 0xBD, 0xDB, 0x37, 0x44, 0xBD, 0xDB, 0x38, 0x44, 0xBD, 0xDB, 0x39, 0x44, 0xBD, 0xDB, 0x3A, 0x44, +- 0xBD, 0xDB, 0x3B, 0x44, 0xBD, 0xDB, 0x3C, 0x44, 0xBD, 0xDB, 0x3D, 0x44, 0xBD, 0xDB, 0x3E, 0x44, +- 0xBD, 0xDB, 0x3F, 0x44, 0xBD, 0xDB, 0xF6, 0x60, 0x16, 0x64, 0x0A, 0xFB, 0x40, 0x21, 0xFE, 0x01, +- 0x74, 0x00, 0x42, 0x50, 0x40, 0x53, 0x1B, 0x60, 0x0C, 0xF3, 0xFF, 0xFF, 0x40, 0x52, 0x33, 0x44, +- 0x32, 0x42, 0xA2, 0xDB, 0xDA, 0x82, 0xA2, 0xDD, 0xDA, 0x83, 0x65, 0x44, 0xBD, 0xDB, 0x61, 0x44, +- 0xBD, 0xDB, 0x66, 0x44, 0xBD, 0xDB, 0xBD, 0xD9, 0x30, 0x44, 0xBD, 0xDB, 0x99, 0xFF, 0xA4, 0x4C, +- 0xBD, 0xDB, 0xA5, 0x4C, 0xBD, 0xDB, 0xA0, 0x4C, 0xBD, 0xDB, 0xA1, 0x4C, 0xBD, 0xDB, 0x98, 0xFF, +- 0x1B, 0x60, 0x0C, 0xFD, 0x1B, 0x60, 0x0D, 0xF3, 0xFF, 0xFF, 0x40, 0x50, 0x1B, 0x60, 0x0F, 0xF3, +- 0xFF, 0xFF, 0x40, 0x52, 0x1B, 0x60, 0x10, 0xF3, 0xFF, 0xFF, 0x40, 0x53, 0x31, 0x41, 0x1B, 0x60, +- 0x0E, 0xF3, 0xFF, 0xFF, 0x40, 0x51, 0x1B, 0x60, 0x0B, 0xF3, 0xFF, 0xFF, 0x60, 0x43, 0x20, 0x44, +- 0xBD, 0xDB, 0x21, 0x44, 0xBD, 0xDB, 0x22, 0x44, 0xBD, 0xDB, 0x23, 0x44, 0xBD, 0xDB, 0x24, 0x44, +- 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x26, 0x44, 0xBD, 0xDB, 0x27, 0x44, 0xBD, 0xDB, 0x28, 0x44, +- 0xBD, 0xDB, 0x29, 0x44, 0xBD, 0xDB, 0x2A, 0x44, 0xBD, 0xDB, 0x2B, 0x44, 0xBD, 0xDB, 0x2C, 0x44, +- 0xBD, 0xDB, 0x2D, 0x44, 0xBD, 0xDB, 0x2E, 0x44, 0xBD, 0xDB, 0x2F, 0x44, 0xBD, 0xDB, 0x1B, 0x60, +- 0x0B, 0xFD, 0x61, 0x58, 0xFF, 0xFF, 0x2F, 0x60, 0x4E, 0x63, 0xA3, 0xD3, 0x33, 0x5C, 0x02, 0xA4, +- 0xBD, 0xDB, 0xFE, 0xB4, 0xE0, 0x85, 0xC4, 0x85, 0x47, 0xD9, 0x34, 0x44, 0x5B, 0xDB, 0x44, 0xF3, +- 0x5B, 0xDB, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, 0x84, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, +- 0xFF, 0x01, 0x86, 0xE1, 0x80, 0xFF, 0x90, 0xFF, 0x88, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x87, 0x3E, +- 0x19, 0x60, 0xF7, 0xF3, 0xFF, 0xFF, 0x10, 0x1B, 0x32, 0x40, 0x80, 0x2A, 0xF6, 0x01, 0x9D, 0xFE, +- 0xF4, 0x05, 0xDB, 0xF3, 0xFF, 0xFF, 0x04, 0xA8, 0x33, 0x60, 0xE2, 0x62, 0x01, 0x02, 0xBD, 0x00, +- 0xA2, 0xD3, 0xFF, 0xFF, 0x4A, 0x1B, 0xE9, 0x01, 0x87, 0xFF, 0x20, 0x44, 0x80, 0xFF, 0x60, 0x40, +- 0x80, 0x26, 0xE3, 0x01, 0xF1, 0xFC, 0xAD, 0x4F, 0xFD, 0xB4, 0xA0, 0x5D, 0xC0, 0x60, 0x40, 0xEC, +- 0xC0, 0x60, 0x00, 0xED, 0xC0, 0x60, 0x80, 0xEE, 0xAC, 0x4F, 0xBF, 0xB4, 0xA0, 0x5C, 0x19, 0x60, +- 0x48, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x02, 0x27, 0x06, 0x00, 0x28, 0xE2, 0x24, 0xE2, 0x40, 0x21, +- 0xFE, 0x01, 0x75, 0x40, 0x0D, 0x00, 0x28, 0xE2, 0x24, 0xE2, 0x75, 0x40, 0x80, 0x2B, 0xAB, 0xFF, +- 0x14, 0xE0, 0x94, 0xE0, 0x40, 0x21, 0xFE, 0x01, 0x10, 0xE0, 0x75, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x33, 0x60, 0xEE, 0x62, 0xA2, 0xDF, 0x01, 0x60, 0x39, 0xE2, 0x04, 0x60, 0x00, 0x7A, 0xAC, 0x4F, +- 0x40, 0xBC, 0x00, 0x7F, 0xA0, 0x5C, 0xC0, 0x60, 0x59, 0xEC, 0xC0, 0x60, 0x07, 0xED, 0xC0, 0x60, +- 0x8F, 0xEE, 0xAE, 0x4F, 0x04, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x26, 0x61, 0xCD, 0x81, 0xFF, 0xFF, +- 0xFD, 0x02, 0xAE, 0x4F, 0xFB, 0xB4, 0xA0, 0x5E, 0xA0, 0x01, 0xF1, 0xFC, 0xAD, 0x4F, 0xFD, 0xB4, +- 0xA0, 0x5D, 0x15, 0x60, 0x80, 0xE7, 0xC0, 0x60, 0x40, 0xEC, 0xC0, 0x60, 0x00, 0xED, 0xAC, 0x4F, +- 0xBF, 0xB4, 0xA0, 0x5C, 0xC0, 0x60, 0x84, 0xEE, 0xAE, 0x4F, 0x04, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, +- 0x00, 0x7A, 0x0F, 0x60, 0x19, 0xE2, 0x0E, 0x60, 0x36, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0x75, 0x44, +- 0x80, 0x2B, 0xAB, 0xFF, 0x80, 0x27, 0x08, 0x00, 0x14, 0xE0, 0x94, 0xE0, 0x34, 0xE2, 0x61, 0x5A, +- 0x48, 0x21, 0xFE, 0x01, 0x00, 0xE0, 0x75, 0x40, 0x0A, 0x60, 0x19, 0xE2, 0x00, 0x64, 0x19, 0x60, +- 0xF1, 0xFB, 0x08, 0x60, 0x15, 0xF1, 0x08, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x01, 0x64, 0x19, 0x60, 0xF2, 0xFB, 0xFF, 0xFF, 0x10, 0xE0, 0x01, 0x60, 0x34, 0xE2, 0xFF, 0xFF, +- 0x05, 0x7A, 0xAC, 0x4F, 0x40, 0xBC, 0x00, 0x7F, 0xA0, 0x5C, 0xC0, 0x60, 0x59, 0xEC, 0xC0, 0x60, +- 0x07, 0xED, 0xC0, 0x60, 0x8F, 0xEE, 0xAE, 0x4F, 0x04, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x1B, 0x60, +- 0xF3, 0xF1, 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x7D, 0xF1, 0x02, 0xB1, 0x04, 0x65, +- 0x02, 0x02, 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x26, 0x61, 0xCD, 0x81, +- 0xFF, 0xFF, 0xFD, 0x02, 0xAE, 0x4F, 0xFB, 0xB4, 0xA0, 0x5E, 0x1B, 0x60, 0xF3, 0xF1, 0xAD, 0x4F, +- 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x7D, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, +- 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x30, 0x01, 0x19, 0x60, 0xF3, 0xF3, 0xFF, 0xFF, +- 0x01, 0x1B, 0x2B, 0x01, 0x31, 0x44, 0x04, 0x2A, 0x28, 0x01, 0x08, 0x26, 0x26, 0x01, 0x19, 0x60, +- 0xF4, 0xF3, 0xFF, 0xFF, 0x01, 0x18, 0x21, 0x01, 0x7E, 0xF5, 0xF1, 0xFC, 0xAD, 0x4F, 0xFD, 0xB4, +- 0xA0, 0x5D, 0x15, 0x60, 0x80, 0xE7, 0xC0, 0x60, 0x40, 0xEC, 0xC0, 0x60, 0x00, 0xED, 0xAC, 0x4F, +- 0xBF, 0xB4, 0xA0, 0x5C, 0xC0, 0x60, 0x84, 0xEE, 0xAE, 0x4F, 0x04, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, +- 0x00, 0x7A, 0x2D, 0x60, 0x5A, 0x63, 0xA3, 0xD1, 0x05, 0x60, 0xDC, 0x64, 0xD0, 0x80, 0x00, 0x64, +- 0x01, 0x06, 0x01, 0x64, 0x40, 0x4E, 0xB2, 0xF1, 0x66, 0x41, 0xE1, 0x81, 0xE1, 0x81, 0xE1, 0x81, +- 0xE1, 0x81, 0x61, 0x46, 0x73, 0x42, 0x5A, 0x92, 0x3F, 0x64, 0xA0, 0x84, 0x60, 0x47, 0xE0, 0x84, +- 0xE0, 0x85, 0x62, 0x47, 0xE8, 0x84, 0xE8, 0x84, 0x3F, 0xB4, 0x60, 0x41, 0x64, 0x44, 0x14, 0x90, +- 0x3F, 0x26, 0xCC, 0x84, 0x14, 0x90, 0x3F, 0x26, 0xCC, 0x84, 0x62, 0x41, 0x60, 0x55, 0xB2, 0xFB, +- 0x72, 0x5C, 0x67, 0x42, 0xD2, 0x80, 0xA2, 0x48, 0x20, 0x2B, 0x05, 0x00, 0x01, 0x02, 0x7C, 0x5C, +- 0x04, 0x60, 0x00, 0x64, 0xC4, 0x85, 0xE8, 0xE2, 0xE4, 0xE2, 0x61, 0x42, 0x49, 0x91, 0x64, 0x44, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xB4, 0x84, 0x60, 0x45, +- 0x51, 0x94, 0x04, 0x60, 0x00, 0x61, 0x01, 0x0D, 0x44, 0x94, 0x62, 0x41, 0x19, 0x60, 0xF5, 0xF1, +- 0x61, 0x42, 0x64, 0x43, 0xCF, 0x83, 0xCF, 0x83, 0x03, 0x03, 0xE3, 0x83, 0x48, 0x94, 0xFE, 0x1F, +- 0x2E, 0x40, 0x01, 0x26, 0xE0, 0x84, 0x60, 0x41, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, +- 0x44, 0x94, 0xE9, 0x81, 0xE9, 0x81, 0x54, 0x94, 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0x44, 0x94, +- 0xE9, 0x81, 0xE9, 0x81, 0xE9, 0x81, 0x54, 0x94, 0x19, 0xE2, 0x2E, 0x40, 0x01, 0x26, 0xE8, 0x84, +- 0x29, 0x61, 0x54, 0x91, 0x61, 0x43, 0x11, 0x06, 0x75, 0x44, 0x80, 0x2B, 0xAB, 0xFF, 0x80, 0x27, +- 0x0C, 0x00, 0x14, 0xE0, 0x94, 0xE0, 0x34, 0xE2, 0x61, 0x5A, 0x48, 0x21, 0xFE, 0x01, 0x00, 0xE0, +- 0x7A, 0x43, 0x15, 0xA1, 0x75, 0x40, 0x80, 0x2B, 0x06, 0xA1, 0x5D, 0x91, 0x61, 0x44, 0x2E, 0x40, +- 0x01, 0x26, 0xE0, 0x84, 0x60, 0x43, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0x89, 0xFF, 0x10, 0xE0, +- 0x80, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xEB, 0x83, 0xEB, 0x83, 0x5C, 0x94, 0xEB, 0x83, 0x5C, 0x94, +- 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0x4C, 0x94, 0x2E, 0x40, 0x01, 0x26, +- 0xE8, 0x84, 0x60, 0x43, 0x65, 0x41, 0x62, 0x45, 0xD5, 0x85, 0x04, 0x60, 0x00, 0x61, 0x01, 0x0D, +- 0xC5, 0x85, 0xC4, 0x84, 0x60, 0x43, 0x62, 0x41, 0xE1, 0x81, 0xE1, 0x81, 0xE1, 0x81, 0xE1, 0x81, +- 0xE1, 0x81, 0xE1, 0x9C, 0x00, 0x61, 0xDD, 0x81, 0x58, 0x94, 0x4A, 0x92, 0xFC, 0x05, 0x41, 0x4F, +- 0x00, 0x61, 0x62, 0x45, 0x1C, 0x60, 0x0A, 0xF3, 0xE3, 0x83, 0xF1, 0x81, 0xE3, 0x83, 0xF1, 0x81, +- 0xE3, 0x83, 0xF1, 0x81, 0xE3, 0x83, 0xF1, 0x81, 0xE3, 0x83, 0xF1, 0x81, 0xE3, 0x83, 0xF1, 0x81, +- 0xA0, 0x52, 0xB2, 0xF3, 0xC3, 0x9C, 0x44, 0x94, 0x01, 0x04, 0xDC, 0x84, 0x60, 0x55, 0xB2, 0xFB, +- 0x64, 0x52, 0xE9, 0xE2, 0x65, 0x53, 0xB3, 0xF3, 0x06, 0x04, 0xDC, 0x84, 0xB3, 0xFB, 0xB4, 0xF3, +- 0x02, 0x04, 0xDC, 0x84, 0xB4, 0xFB, 0x2F, 0x43, 0xCF, 0x83, 0x6C, 0xF3, 0xFF, 0xFF, 0x5C, 0x94, +- 0xFF, 0xFF, 0x0C, 0x24, 0x01, 0x64, 0x6C, 0xFB, 0x16, 0x60, 0xAC, 0xF1, 0xFF, 0xFF, 0x03, 0x1B, +- 0x31, 0x40, 0x02, 0x2A, 0x07, 0x00, 0x73, 0xF3, 0xFF, 0xFF, 0x5C, 0x94, 0xFF, 0xFF, 0x0C, 0x24, +- 0x00, 0x64, 0x73, 0xFB, 0x19, 0x60, 0xF5, 0xF3, 0x01, 0x7C, 0x5C, 0x94, 0x00, 0x36, 0x01, 0x64, +- 0xA2, 0xDB, 0x19, 0x60, 0xF2, 0xF9, 0x01, 0x60, 0x34, 0xE2, 0x32, 0x7A, 0xAC, 0x4F, 0x40, 0xBC, +- 0x00, 0x7F, 0xA0, 0x5C, 0xC0, 0x60, 0x59, 0xEC, 0xC0, 0x60, 0x07, 0xED, 0xC0, 0x60, 0x8F, 0xEE, +- 0xAE, 0x4F, 0x04, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x0A, 0x61, 0xCD, 0x81, 0xFF, 0xFF, 0xFD, 0x02, +- 0xAE, 0x4F, 0xFB, 0xB4, 0xA0, 0x5E, 0x1B, 0x60, 0xF3, 0xF1, 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, +- 0x64, 0x41, 0x7D, 0xF1, 0x02, 0xB1, 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, +- 0xB4, 0x84, 0xA0, 0x5D, 0x37, 0x60, 0x7F, 0x78, 0xFF, 0xFF, 0x24, 0xE2, 0x2D, 0xF3, 0x2C, 0xF3, +- 0x00, 0xBD, 0xCC, 0x84, 0x08, 0x03, 0x2C, 0xFB, 0x06, 0x02, 0x65, 0x44, 0x2C, 0xFB, 0x8A, 0xFF, +- 0x80, 0x60, 0x00, 0x75, 0x88, 0xFF, 0x44, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x44, 0xFB, 0x2F, 0x60, +- 0x4A, 0x65, 0x2F, 0x60, 0x48, 0x61, 0xA5, 0xD3, 0xA1, 0xD3, 0x11, 0x18, 0xCC, 0x84, 0xA1, 0xDB, +- 0x0E, 0x02, 0xA5, 0xD3, 0xA1, 0xDB, 0x17, 0x60, 0xA7, 0xF3, 0x17, 0x60, 0xA6, 0xF1, 0xA2, 0xDB, +- 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x03, 0x8A, 0xFF, 0x20, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xF1, 0xF3, +- 0x31, 0x40, 0x01, 0x2A, 0x3D, 0x00, 0x60, 0x43, 0x04, 0xB0, 0x02, 0xB0, 0x08, 0x24, 0x16, 0x02, +- 0x10, 0xB0, 0x29, 0x44, 0x34, 0x02, 0x00, 0xA8, 0xCC, 0x81, 0x0D, 0x03, 0x41, 0x49, 0x2F, 0x02, +- 0x63, 0x40, 0x08, 0x2A, 0x08, 0x00, 0xF7, 0xB3, 0x1B, 0x60, 0xF6, 0xF1, 0xAD, 0x4F, 0xFD, 0xB4, +- 0xA0, 0x5D, 0x44, 0x49, 0x24, 0x00, 0x63, 0x40, 0x02, 0x2A, 0x10, 0x00, 0x1B, 0x60, 0xF7, 0xF3, +- 0x1B, 0x60, 0xF5, 0xFB, 0x40, 0x49, 0x1B, 0x60, 0xF8, 0xF3, 0x1B, 0x60, 0xF6, 0xFB, 0x0C, 0xBB, +- 0xFD, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0x11, 0x00, 0x1B, 0x60, 0xF9, 0xF3, +- 0x37, 0x60, 0xEA, 0x7C, 0x0C, 0x18, 0xA4, 0xDB, 0x40, 0x49, 0x1B, 0x60, 0xFA, 0xF3, 0x1B, 0x60, +- 0xF6, 0xFB, 0x08, 0xBB, 0xFB, 0xB3, 0xAD, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5D, 0xF1, 0xFD, +- 0x00, 0x60, 0xA4, 0xF3, 0x62, 0x43, 0x17, 0x18, 0x58, 0xD3, 0x62, 0x41, 0x03, 0x18, 0xCC, 0x84, +- 0xA1, 0xDB, 0x11, 0x00, 0x49, 0xD3, 0xA3, 0xDB, 0x06, 0xA1, 0xA1, 0xD3, 0x59, 0xD1, 0x60, 0x45, +- 0xA5, 0xD3, 0x59, 0xD1, 0xB0, 0x84, 0xA5, 0xDB, 0x64, 0x44, 0x06, 0x36, 0xCD, 0xFE, 0x07, 0x36, +- 0xD6, 0xFE, 0xE6, 0x01, 0x23, 0x46, 0xB8, 0x60, 0x03, 0x78, 0xFF, 0xFF, 0x46, 0x43, 0x26, 0x60, +- 0x3E, 0x61, 0xA1, 0xD3, 0x59, 0xD1, 0x06, 0x1B, 0x59, 0xD3, 0x59, 0xD1, 0x03, 0x1B, 0x59, 0xD3, +- 0x59, 0xD1, 0xF0, 0x18, 0x00, 0x63, 0x49, 0xDD, 0x60, 0x40, 0x02, 0x36, 0x11, 0x00, 0x03, 0x36, +- 0x32, 0x00, 0x01, 0x36, 0x08, 0x00, 0x05, 0x3A, 0xEA, 0x01, 0xA4, 0xD3, 0x5A, 0xD3, 0x9C, 0x85, +- 0xA4, 0x84, 0xA2, 0xDB, 0xE4, 0x01, 0x01, 0x60, 0x48, 0x61, 0x00, 0x64, 0xA1, 0xDB, 0xDF, 0x01, +- 0x3A, 0x60, 0x3E, 0x64, 0x40, 0x45, 0x22, 0x00, 0x01, 0x60, 0x48, 0x66, 0xA6, 0xD3, 0x04, 0xA1, +- 0x60, 0x43, 0xA1, 0xD3, 0xC9, 0x81, 0x60, 0x45, 0x00, 0xBB, 0xA1, 0xDB, 0xBE, 0xD3, 0x09, 0x03, +- 0xD4, 0x84, 0x9C, 0x84, 0xDC, 0x84, 0xFF, 0xFF, 0x04, 0x0E, 0xA3, 0xD1, 0x63, 0x46, 0x64, 0x43, +- 0xF2, 0x01, 0x9C, 0x84, 0xDC, 0x85, 0x49, 0xDD, 0x61, 0x44, 0x00, 0xBB, 0xA6, 0xDB, 0x02, 0x03, +- 0x65, 0x44, 0xBE, 0xDB, 0xBC, 0x01, 0x3A, 0x60, 0x19, 0x64, 0x40, 0x45, 0x01, 0x60, 0x48, 0x66, +- 0xA6, 0xD3, 0xFF, 0xFF, 0xD0, 0x80, 0x0F, 0x18, 0x02, 0x03, 0x60, 0x46, 0xF9, 0x01, 0x58, 0xD3, +- 0xA4, 0xD3, 0x60, 0x45, 0x00, 0x63, 0xA4, 0xDD, 0x05, 0x18, 0x58, 0xD3, 0xFF, 0xFF, 0xC4, 0x83, +- 0xA2, 0xDD, 0xCA, 0x84, 0xA6, 0xDB, 0x25, 0x58, 0x64, 0x41, 0x00, 0x60, 0x46, 0x74, 0xCD, 0xE2, +- 0x04, 0xE1, 0x02, 0x60, 0x00, 0xE1, 0x3F, 0x44, 0x40, 0x26, 0x05, 0x00, 0x1C, 0x60, 0x0F, 0xF3, +- 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x50, 0x3F, 0x40, 0x02, 0x2B, 0x03, 0x00, 0x3A, 0x60, 0xB7, 0x78, +- 0xFF, 0xFF, 0x04, 0x29, 0xFE, 0x01, 0xC4, 0xE2, 0x43, 0x64, 0x3A, 0xDB, 0xA1, 0xF3, 0xFF, 0xFF, +- 0x60, 0x41, 0x3F, 0x44, 0xFF, 0x01, 0x3F, 0x40, 0x40, 0x26, 0x05, 0x00, 0x1C, 0x60, 0x0D, 0xF3, +- 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x52, 0xC4, 0xE2, 0x32, 0x7B, 0x4D, 0xE2, 0xBF, 0xFE, 0xC4, 0xE2, +- 0x41, 0xFF, 0xE0, 0xFE, 0xE1, 0xFE, 0xE2, 0xFE, 0x43, 0xFF, 0x44, 0xFF, 0x46, 0xFF, 0xA2, 0xF3, +- 0x62, 0xFF, 0x60, 0x40, 0x05, 0x36, 0x2D, 0xFF, 0x07, 0x36, 0xD5, 0xFE, 0x08, 0xE1, 0x88, 0x60, +- 0x85, 0x71, 0x8D, 0xE2, 0xA2, 0x60, 0x41, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x62, 0x3D, 0x60, +- 0x58, 0x4D, 0x3B, 0x78, 0xFF, 0xFF, 0x64, 0x41, 0xA9, 0x9C, 0x60, 0x45, 0x3D, 0x60, 0x58, 0x4D, +- 0x0F, 0x78, 0xFF, 0xFF, 0xA1, 0xF1, 0x09, 0x60, 0xB4, 0x61, 0x64, 0x44, 0x01, 0x27, 0x24, 0x00, +- 0x60, 0x40, 0x0E, 0x3A, 0x0D, 0x00, 0x01, 0x7C, 0x14, 0x60, 0x6F, 0xF9, 0x44, 0x60, 0x08, 0x7C, +- 0x14, 0x60, 0x41, 0xF9, 0x16, 0x60, 0x62, 0xF1, 0x02, 0x60, 0xB0, 0x61, 0xB1, 0x9C, 0x26, 0x00, +- 0x00, 0x7C, 0x14, 0x60, 0x6F, 0xF9, 0x40, 0x60, 0x08, 0x7C, 0x14, 0x60, 0x41, 0xF9, 0x16, 0x60, +- 0x62, 0xF1, 0x02, 0x60, 0x90, 0x61, 0xB1, 0x9C, 0x09, 0x60, 0x67, 0x65, 0xFF, 0xB4, 0xC4, 0x85, +- 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x81, 0x12, 0x00, 0xFF, 0xB4, 0xED, 0xA0, 0x2C, 0x60, 0xC6, 0x61, +- 0x04, 0x04, 0xE2, 0xA0, 0xD9, 0x81, 0x01, 0x04, 0xD9, 0x81, 0xA1, 0xD1, 0x02, 0x60, 0x50, 0x61, +- 0x26, 0x60, 0xF0, 0x65, 0xE0, 0x84, 0x44, 0xD3, 0xB1, 0x9C, 0xC8, 0x81, 0x61, 0x47, 0x00, 0x7E, +- 0xE9, 0x81, 0x07, 0x60, 0xF0, 0x65, 0xA5, 0x81, 0x0B, 0xB9, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x85, +- 0xB5, 0x85, 0x04, 0x60, 0x44, 0x62, 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0xA1, 0xF3, +- 0xC8, 0x61, 0x61, 0x54, 0xCD, 0xE2, 0x60, 0x40, 0x01, 0x27, 0x2E, 0x00, 0xCC, 0x84, 0xE0, 0x85, +- 0x15, 0x60, 0xA2, 0xE7, 0x26, 0x60, 0x80, 0x64, 0x3D, 0x60, 0x58, 0x4F, 0x04, 0x78, 0xFF, 0xFF, +- 0x26, 0x60, 0x9C, 0x64, 0x3D, 0x60, 0x58, 0x4F, 0x04, 0x78, 0xFF, 0xFF, 0x26, 0x60, 0xB8, 0x64, +- 0x3D, 0x60, 0x58, 0x4F, 0x04, 0x78, 0xFF, 0xFF, 0x26, 0x60, 0xD4, 0x64, 0x3D, 0x60, 0x58, 0x4F, +- 0x04, 0x78, 0xFF, 0xFF, 0x75, 0x64, 0x06, 0x61, 0x61, 0x48, 0x60, 0x44, 0x80, 0xBC, 0xFF, 0xB4, +- 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x28, 0x60, 0xE6, 0x7C, 0x07, 0x60, 0xE8, 0xF9, +- 0x28, 0x60, 0x6E, 0x63, 0x14, 0x61, 0x21, 0x00, 0x14, 0x60, 0xDF, 0xF1, 0xFF, 0xB4, 0xED, 0xA0, +- 0x64, 0x41, 0x04, 0x04, 0xE2, 0xA0, 0xD9, 0x81, 0x01, 0x04, 0xD9, 0x81, 0xA1, 0xD1, 0x14, 0x60, +- 0x0E, 0xF3, 0x64, 0x41, 0xFF, 0xB1, 0xFF, 0x60, 0x00, 0x65, 0xA4, 0x84, 0x34, 0x94, 0xA2, 0xDB, +- 0x5A, 0xD3, 0x64, 0x41, 0xA5, 0x81, 0xFF, 0xB4, 0x34, 0x94, 0xA2, 0xDB, 0x29, 0x60, 0x52, 0x7C, +- 0x07, 0x60, 0xE8, 0xF9, 0x27, 0x60, 0xFC, 0x63, 0x13, 0x61, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, +- 0xFF, 0xFF, 0x07, 0x60, 0xE8, 0xF3, 0x31, 0x40, 0x80, 0x26, 0x36, 0xA4, 0x07, 0x60, 0xE8, 0xFB, +- 0x60, 0x43, 0x09, 0x61, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0xA1, 0xF3, 0x29, 0x60, +- 0xBE, 0x61, 0x00, 0x7C, 0x7E, 0x63, 0x59, 0xD9, 0xFE, 0x1F, 0x60, 0x40, 0x01, 0x27, 0x03, 0x00, +- 0x2A, 0x60, 0x40, 0x65, 0x15, 0x00, 0xFF, 0xB4, 0xF9, 0xA0, 0x2A, 0x60, 0x62, 0x65, 0x01, 0x7C, +- 0x0D, 0x04, 0xED, 0xA0, 0x2A, 0x60, 0x84, 0x65, 0x11, 0x7C, 0x08, 0x04, 0xE2, 0xA0, 0x2A, 0x60, +- 0xA6, 0x65, 0x21, 0x7C, 0x03, 0x04, 0x2A, 0x60, 0xC8, 0x65, 0x31, 0x7C, 0x64, 0x5F, 0x7D, 0xFB, +- 0xA5, 0xD3, 0xDA, 0x85, 0xF0, 0xA0, 0x29, 0x60, 0xBE, 0x61, 0x08, 0x06, 0x40, 0x54, 0x58, 0x53, +- 0x08, 0xFF, 0x37, 0x60, 0x7A, 0x64, 0x43, 0xFB, 0x08, 0xFF, 0xFF, 0x01, 0x60, 0x43, 0x60, 0x46, +- 0xA5, 0xD1, 0xDA, 0x85, 0xA5, 0xD3, 0xDA, 0x85, 0x59, 0xD9, 0x59, 0xDB, 0x59, 0xD9, 0x59, 0xDB, +- 0xFB, 0x1F, 0x0C, 0x63, 0xA5, 0xD1, 0xDA, 0x85, 0xA5, 0xD3, 0xDA, 0x85, 0x59, 0xD9, 0x59, 0xDB, +- 0x59, 0xD9, 0x59, 0xDB, 0xF7, 0x1F, 0x66, 0x44, 0x0E, 0x63, 0x53, 0x93, 0x60, 0x40, 0x10, 0x36, +- 0x07, 0x00, 0x65, 0x44, 0x48, 0xD3, 0x59, 0xD9, 0x59, 0xDB, 0x59, 0xD9, 0x59, 0xDB, 0xFB, 0x1F, +- 0x16, 0x60, 0x39, 0xF1, 0x7D, 0xF3, 0x64, 0x43, 0xDB, 0x81, 0x2C, 0x60, 0x54, 0x65, 0x60, 0x40, +- 0x01, 0x37, 0x12, 0x00, 0x11, 0x37, 0x17, 0x00, 0x21, 0x37, 0x1D, 0x00, 0x31, 0x37, 0x22, 0x00, +- 0xA3, 0xD1, 0x16, 0x60, 0x34, 0xF5, 0x64, 0x44, 0xFF, 0xB4, 0x16, 0x60, 0x33, 0xFB, 0x64, 0x47, +- 0xFF, 0xB4, 0x16, 0x60, 0x2A, 0xF1, 0x1D, 0x00, 0xA1, 0xD3, 0x16, 0x60, 0x35, 0xF5, 0xFF, 0xB4, +- 0x16, 0x60, 0x2B, 0xF1, 0x16, 0x00, 0xA1, 0xD3, 0x16, 0x60, 0x36, 0xF5, 0x60, 0x47, 0xFF, 0xB4, +- 0x16, 0x60, 0x2C, 0xF1, 0x0E, 0x00, 0x59, 0xD3, 0x16, 0x60, 0x37, 0xF5, 0xFF, 0xB4, 0x16, 0x60, +- 0x2D, 0xF1, 0x07, 0x00, 0x59, 0xD3, 0x16, 0x60, 0x38, 0xF5, 0x60, 0x47, 0xFF, 0xB4, 0x16, 0x60, +- 0x2E, 0xF1, 0x16, 0x60, 0x32, 0xFB, 0x16, 0x60, 0x2F, 0xF9, 0x66, 0x42, 0xFC, 0xA2, 0xA2, 0xD3, +- 0x2B, 0x60, 0x42, 0x63, 0xCC, 0x84, 0xE8, 0x84, 0xCC, 0x81, 0x63, 0x45, 0xA6, 0xD3, 0xDA, 0x82, +- 0xFF, 0xB4, 0xFF, 0xFF, 0x03, 0x03, 0x60, 0x40, 0x80, 0x2B, 0x03, 0x00, 0xDA, 0x86, 0xCD, 0x81, +- 0xF5, 0x01, 0x00, 0xB9, 0xA6, 0xD3, 0x0B, 0x03, 0x5A, 0xD1, 0xDA, 0x86, 0xFF, 0xB4, 0xE0, 0x84, +- 0xC4, 0x84, 0x5C, 0x90, 0xBD, 0xD9, 0xFD, 0x02, 0xCD, 0x81, 0x66, 0x42, 0xF2, 0x02, 0x5A, 0xD3, +- 0x2B, 0x60, 0x80, 0x65, 0xD7, 0x80, 0xBD, 0xDB, 0xFD, 0x02, 0x7D, 0xF3, 0x19, 0x60, 0x7B, 0xF1, +- 0x60, 0x40, 0x01, 0x27, 0x09, 0x00, 0x64, 0x40, 0x10, 0x26, 0x06, 0x00, 0x13, 0x64, 0xCB, 0xFB, +- 0x01, 0x60, 0x67, 0x64, 0x37, 0xFB, 0x09, 0x00, 0x08, 0x64, 0xCB, 0xFB, 0xA1, 0xF3, 0x01, 0x60, +- 0x67, 0x7C, 0x60, 0x40, 0x01, 0x27, 0x5B, 0x7C, 0x37, 0xF9, 0x19, 0x60, 0x4D, 0xF1, 0x7D, 0xF3, +- 0x64, 0x40, 0x00, 0x3A, 0x1B, 0x00, 0x60, 0x40, 0x01, 0x27, 0x0D, 0x00, 0x32, 0x60, 0xAB, 0x63, +- 0x4C, 0x94, 0x0E, 0xA5, 0x60, 0xFE, 0xA0, 0xD1, 0xA5, 0xD3, 0x19, 0x60, 0x72, 0xF9, 0x19, 0x60, +- 0x73, 0xFB, 0x20, 0xFE, 0x0B, 0x00, 0xFF, 0xB4, 0xF8, 0xA4, 0x32, 0x60, 0xC8, 0x63, 0x4C, 0x94, +- 0x60, 0xFE, 0xA0, 0xD1, 0xFF, 0xFF, 0x19, 0x60, 0x73, 0xF9, 0x20, 0xFE, 0x19, 0x60, 0x75, 0xF3, +- 0x16, 0x60, 0xD8, 0xF1, 0x60, 0x43, 0xD3, 0x80, 0x19, 0x60, 0x76, 0xF3, 0x01, 0x07, 0x63, 0x5C, +- 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x07, 0x60, 0x5C, 0x19, 0x60, 0x4F, 0xF9, 0x19, 0x60, 0x53, 0xF9, +- 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x0A, 0x00, 0xFF, 0xB5, 0x10, 0x60, 0xF4, 0x63, +- 0x65, 0x41, 0xCD, 0x81, 0x06, 0xA3, 0xFD, 0x02, 0xFA, 0xA3, 0xA3, 0xD3, 0x0F, 0x00, 0x01, 0x60, +- 0xFF, 0x65, 0xA4, 0x84, 0x11, 0x60, 0x60, 0x61, 0xA1, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0x08, 0xA1, +- 0xFB, 0x02, 0xFC, 0xA1, 0xA1, 0xD3, 0x19, 0x60, 0x4F, 0xF1, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, +- 0x04, 0x07, 0x19, 0x60, 0x4F, 0xFB, 0x19, 0x60, 0x53, 0xFB, 0x19, 0x60, 0x4F, 0xF3, 0x19, 0x60, +- 0x72, 0xF1, 0x19, 0x60, 0x74, 0xFB, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x04, 0x19, 0x60, 0x74, 0xF9, +- 0x2C, 0x60, 0x74, 0x63, 0x2B, 0x60, 0x02, 0x65, 0x16, 0x60, 0x33, 0xF1, 0x2A, 0x60, 0xEA, 0x61, +- 0x2C, 0x60, 0x62, 0x64, 0x40, 0x4F, 0x04, 0x64, 0xC3, 0x60, 0x58, 0x4D, 0x1A, 0x78, 0xFF, 0xFF, +- 0x19, 0x60, 0x4F, 0xF3, 0x19, 0x60, 0x73, 0xF1, 0x19, 0x60, 0x74, 0xFB, 0xD0, 0x80, 0xFF, 0xFF, +- 0x02, 0x04, 0x19, 0x60, 0x74, 0xF9, 0x2C, 0x60, 0x7C, 0x63, 0x16, 0x60, 0x32, 0xF1, 0x2B, 0x60, +- 0x42, 0x65, 0x2C, 0x60, 0x60, 0x64, 0x40, 0x4F, 0x08, 0x64, 0xC3, 0x60, 0x58, 0x4D, 0x1A, 0x78, +- 0xFF, 0xFF, 0x7D, 0xF3, 0x08, 0x7C, 0x38, 0xF9, 0x2B, 0x60, 0xDA, 0x61, 0x60, 0x40, 0x01, 0x2B, +- 0x0E, 0x00, 0x01, 0x37, 0x06, 0x00, 0x11, 0x37, 0x03, 0x00, 0x21, 0x3B, 0x1E, 0xA1, 0x1E, 0xA1, +- 0x1E, 0xA1, 0x1C, 0x63, 0x2B, 0x60, 0xBC, 0x64, 0x59, 0xD1, 0x58, 0xD9, 0xFD, 0x1F, 0x16, 0x60, +- 0x2F, 0xF3, 0x00, 0x7C, 0x60, 0x45, 0x70, 0x62, 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, +- 0x04, 0x29, 0xFE, 0x01, 0x00, 0x60, 0x10, 0x62, 0x3D, 0x60, 0x58, 0x4D, 0x3B, 0x78, 0xFF, 0xFF, +- 0x01, 0x61, 0xB1, 0x9C, 0x60, 0x45, 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0x3A, 0x60, +- 0x95, 0x78, 0xFF, 0xFF, 0x44, 0xD3, 0x80, 0x7C, 0x60, 0x48, 0x60, 0x47, 0x00, 0x7F, 0xB0, 0x8A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x2F, 0x58, 0xFF, 0xFF, 0xD5, 0x60, 0x84, 0xE7, 0x62, 0x47, +- 0x80, 0xBF, 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x64, 0x4A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x2D, 0x58, +- 0xFF, 0xFF, 0x00, 0x7C, 0xBD, 0xD3, 0xD5, 0x60, 0x84, 0xE7, 0x60, 0x47, 0x80, 0xBF, 0x60, 0x4A, +- 0xBD, 0xD3, 0x01, 0x16, 0xFE, 0x01, 0x90, 0x8A, 0xBD, 0xD3, 0x01, 0x16, 0xFE, 0x01, 0x90, 0x8A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0xCD, 0x81, 0x95, 0x60, 0x84, 0xE7, 0xEB, 0x02, 0x2D, 0x58, +- 0xFF, 0xFF, 0xD5, 0x60, 0x84, 0xE7, 0x62, 0x4A, 0x02, 0x64, 0x01, 0x16, 0xFE, 0x01, 0xCC, 0x84, +- 0xFF, 0xFF, 0xFD, 0x02, 0x7C, 0x49, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x68, 0x5C, 0x7C, 0x49, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x68, 0x44, 0x95, 0x60, 0x84, 0xE7, 0x2D, 0x58, 0xFF, 0xFF, +- 0x40, 0xFF, 0x20, 0x44, 0xBF, 0xB4, 0x40, 0x40, 0x03, 0x00, 0x20, 0x44, 0x40, 0xBC, 0x40, 0x40, +- 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x02, 0x00, 0x43, 0x45, 0xF6, 0x01, 0x00, 0x64, +- 0x19, 0x60, 0xF2, 0xFB, 0x3F, 0x44, 0x40, 0x26, 0x05, 0x00, 0x1C, 0x60, 0x0F, 0xF3, 0x5A, 0xD1, +- 0xA0, 0x50, 0xA4, 0x50, 0xAE, 0x4F, 0xFD, 0xB4, 0x04, 0xBC, 0xA0, 0x5E, 0x00, 0x60, 0x02, 0x71, +- 0x8D, 0xE2, 0x40, 0xE1, 0x40, 0x29, 0xFE, 0x01, 0x04, 0xAC, 0xA0, 0x5E, 0xFF, 0xFF, 0x00, 0x60, +- 0x10, 0x62, 0x19, 0x60, 0x8E, 0x7C, 0x00, 0x60, 0xAC, 0x65, 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, +- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x62, 0x3D, 0x60, 0x58, 0x4D, 0x3B, 0x78, 0xFF, 0xFF, +- 0x60, 0x40, 0x19, 0x60, 0x8E, 0x64, 0x64, 0x40, 0xD0, 0x80, 0x14, 0x71, 0x05, 0x03, 0x8D, 0xE2, +- 0x40, 0xE1, 0x40, 0x29, 0xFE, 0x01, 0xE2, 0x01, 0x3F, 0x44, 0x40, 0x26, 0x05, 0x00, 0x1C, 0x60, +- 0x0D, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x52, 0x27, 0x60, 0x36, 0x63, 0x1E, 0x61, 0x3D, 0x60, +- 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x14, 0x71, 0x8D, 0xE2, 0x40, 0xE1, 0x40, 0x29, +- 0xFE, 0x01, 0x31, 0x44, 0x40, 0x26, 0x02, 0x00, 0x80, 0x26, 0x17, 0x00, 0x28, 0x60, 0xE6, 0x63, +- 0x07, 0x60, 0xE8, 0xFD, 0x09, 0x61, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0x31, 0x44, +- 0x40, 0x2A, 0x14, 0x00, 0x31, 0x44, 0x7F, 0xB4, 0x40, 0x51, 0xAE, 0x4C, 0x10, 0x26, 0x0E, 0x00, +- 0x07, 0x60, 0xE9, 0xFB, 0x31, 0x44, 0x80, 0xBC, 0x40, 0x51, 0x29, 0x60, 0x1C, 0x63, 0x07, 0x60, +- 0xE8, 0xFD, 0x09, 0x61, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0x27, 0x60, 0xEA, 0x63, +- 0x03, 0x61, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x62, 0x19, 0x60, +- 0x8F, 0x7C, 0x00, 0x60, 0xAC, 0x65, 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0x80, 0xE1, +- 0xBF, 0xFE, 0xA1, 0x4F, 0x70, 0xB4, 0x50, 0x36, 0x0C, 0x00, 0x20, 0x36, 0x03, 0x00, 0x3A, 0x60, +- 0x77, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0x1A, 0xE1, 0xDF, 0xFE, 0x19, 0xFF, 0x00, 0xE1, 0xA1, 0xFF, +- 0xFF, 0xFF, 0x20, 0x44, 0x40, 0x2A, 0x85, 0x00, 0x7D, 0xF1, 0x3B, 0x00, 0x83, 0x00, 0x19, 0x60, +- 0xF2, 0xF3, 0xFF, 0xFF, 0x01, 0x18, 0x59, 0x01, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, +- 0x1C, 0x60, 0x0F, 0xF3, 0x3F, 0x40, 0x40, 0x26, 0x01, 0x00, 0xA0, 0x50, 0xAE, 0x4F, 0xFD, 0xB4, +- 0xA0, 0x5E, 0xAC, 0x4F, 0x10, 0xBC, 0xA0, 0x5C, 0xFF, 0xFF, 0x10, 0xAC, 0xA0, 0x5C, 0x00, 0x60, +- 0xC8, 0x71, 0x8D, 0xE2, 0x40, 0xE1, 0x40, 0x29, 0xFE, 0x01, 0x7D, 0xF1, 0x30, 0x61, 0x64, 0x44, +- 0x01, 0x2B, 0x20, 0xA1, 0x30, 0x64, 0x61, 0x5F, 0x60, 0x45, 0x0C, 0x60, 0x00, 0x62, 0x00, 0x60, +- 0x71, 0x7C, 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0xC8, 0x71, 0x8D, 0xE2, +- 0x40, 0xE1, 0x40, 0x29, 0xFE, 0x01, 0x01, 0x60, 0x08, 0xE1, 0x7D, 0xF1, 0x20, 0x44, 0x40, 0xBC, +- 0x40, 0x40, 0x19, 0x60, 0xF2, 0xF3, 0xFF, 0xFF, 0x03, 0x18, 0x3D, 0x60, 0x57, 0x78, 0xFF, 0xFF, +- 0x1B, 0x60, 0xF3, 0xF1, 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x7D, 0xF1, 0x02, 0xB1, +- 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x20, 0x44, +- 0x40, 0x2A, 0x43, 0x45, 0x20, 0xBC, 0x40, 0x40, 0xA1, 0xF9, 0x05, 0x64, 0xA2, 0xFB, 0xDF, 0xFE, +- 0x19, 0xFF, 0xDD, 0xFE, 0x26, 0x00, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x43, 0x45, 0xA4, 0xD1, +- 0xDA, 0x83, 0xC3, 0x85, 0x80, 0xE1, 0xDF, 0xFE, 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x48, 0x60, 0x47, +- 0x80, 0xBC, 0x00, 0x7F, 0x60, 0x4A, 0xD7, 0x80, 0xA1, 0xFF, 0xF6, 0x02, 0xBF, 0xFE, 0x11, 0x00, +- 0x43, 0x45, 0xA4, 0xD1, 0xDA, 0x83, 0x0D, 0x18, 0x64, 0x44, 0x00, 0x61, 0xFA, 0xA4, 0xDD, 0x81, +- 0xFD, 0x02, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0xBF, 0xFE, 0x02, 0x00, 0xF1, 0xFE, +- 0x01, 0x00, 0x25, 0x43, 0x21, 0xE1, 0x00, 0x64, 0xBF, 0xDB, 0x20, 0x44, 0x20, 0x2A, 0x07, 0x00, +- 0x07, 0xB4, 0x04, 0x36, 0xC3, 0xFE, 0x06, 0x36, 0xCC, 0xFE, 0x07, 0x36, 0xD5, 0xFE, 0x20, 0x44, +- 0x98, 0xB4, 0x40, 0x40, 0x26, 0x60, 0x26, 0x63, 0xBD, 0xD3, 0x03, 0x61, 0x0F, 0x1B, 0x04, 0xA3, +- 0xBD, 0xD3, 0x04, 0x61, 0x0B, 0x1B, 0x04, 0xA3, 0xBD, 0xD3, 0x06, 0x61, 0x07, 0x1B, 0x04, 0xA3, +- 0xBD, 0xD3, 0x07, 0x61, 0x03, 0x1B, 0xC3, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0xA3, 0xD1, 0x40, 0x44, +- 0x20, 0x44, 0x07, 0xB5, 0xD4, 0x85, 0x35, 0x80, 0x24, 0x45, 0x26, 0x60, 0x66, 0x64, 0x44, 0xD7, +- 0xFF, 0xFF, 0xFF, 0xFF, 0x43, 0x45, 0x20, 0x44, 0x20, 0xBC, 0x40, 0x40, 0x64, 0x43, 0xBD, 0xD3, +- 0xBD, 0xD1, 0x40, 0x44, 0x10, 0x27, 0x19, 0x00, 0x3F, 0x40, 0x02, 0x2B, 0x06, 0x00, 0x24, 0x47, +- 0x08, 0x2B, 0x13, 0x00, 0x07, 0xB4, 0x01, 0x36, 0x11, 0x00, 0xFF, 0x60, 0x7F, 0x65, 0x15, 0x60, +- 0xA2, 0x64, 0x24, 0x40, 0x08, 0x2B, 0xA4, 0x84, 0xA0, 0x57, 0xFF, 0xFF, 0x64, 0x49, 0xFF, 0xFF, +- 0x68, 0x44, 0x01, 0x16, 0xFD, 0x01, 0x00, 0x7F, 0xA3, 0xDB, 0xAB, 0x01, 0x64, 0x42, 0x3D, 0x60, +- 0x58, 0x4D, 0x3B, 0x78, 0xFF, 0xFF, 0xBD, 0xD9, 0xA3, 0xDB, 0xA3, 0x01, 0x43, 0x45, 0x20, 0x44, +- 0x20, 0xBC, 0x40, 0x40, 0x64, 0x43, 0xBD, 0xD3, 0xA3, 0xD1, 0x40, 0x44, 0x10, 0x2B, 0x16, 0x00, +- 0xBE, 0xD1, 0xFF, 0xFF, 0x15, 0x60, 0x80, 0xE7, 0x24, 0x40, 0x07, 0x27, 0x04, 0x00, 0xAC, 0x4F, +- 0x10, 0xBC, 0x00, 0x7F, 0xA0, 0x5C, 0x64, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x24, 0x40, +- 0x20, 0x27, 0x1D, 0x00, 0xAC, 0x4F, 0xEF, 0xB4, 0xA0, 0x5C, 0x19, 0x00, 0x3F, 0x40, 0x02, 0x2B, +- 0x06, 0x00, 0x24, 0x47, 0x08, 0x2B, 0x13, 0x00, 0x07, 0xB4, 0x01, 0x36, 0x11, 0x00, 0x15, 0x60, +- 0x22, 0x64, 0x24, 0x40, 0x08, 0x27, 0x80, 0xBC, 0x7C, 0x48, 0xBE, 0xD3, 0xA0, 0x57, 0x60, 0x48, +- 0x64, 0x44, 0x80, 0xBC, 0xFF, 0xB4, 0x60, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x69, 0x01, +- 0x01, 0x61, 0x3D, 0x60, 0x58, 0x4D, 0x23, 0x78, 0xFF, 0xFF, 0x63, 0x01, 0x30, 0x44, 0x02, 0xA8, +- 0x00, 0xE1, 0x07, 0x02, 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, 0x66, 0xFF, 0xBF, 0xFE, +- 0xA1, 0xFF, 0x82, 0xFF, 0x88, 0xFF, 0x6C, 0x40, 0x41, 0xFF, 0xC4, 0xE2, 0x43, 0xFF, 0x5C, 0x49, +- 0x08, 0xE1, 0xA2, 0x60, 0x41, 0x78, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x02, 0x02, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x82, 0xFF, 0x88, 0xFF, 0xA8, 0xE2, 0xCB, 0xF1, 0x00, 0x6B, 0x89, 0xFF, +- 0x64, 0x54, 0x88, 0xFF, 0x9F, 0xFE, 0x02, 0x05, 0x64, 0x44, 0x60, 0x54, 0xCD, 0xE2, 0xC2, 0x64, +- 0x3A, 0xDB, 0xBC, 0xFF, 0xB5, 0xFF, 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xB4, 0x40, 0x46, 0x3C, 0x44, +- 0x00, 0xBC, 0xFF, 0xFF, 0x06, 0x03, 0x27, 0x40, 0x26, 0x22, 0x03, 0x00, 0x02, 0x64, 0x31, 0xFB, +- 0xC0, 0xFE, 0x27, 0x44, 0x20, 0x2A, 0x04, 0x00, 0xA0, 0x60, 0x00, 0xEA, 0xB0, 0x60, 0x00, 0xEA, +- 0x5C, 0x44, 0x27, 0x44, 0x18, 0xB4, 0x40, 0x47, 0x00, 0xE1, 0x29, 0x40, 0x50, 0x2B, 0x37, 0x00, +- 0xEF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x31, 0x40, 0x08, 0x26, 0x0B, 0x00, 0x21, 0x46, +- 0xA7, 0xF4, 0x1D, 0xF2, 0xFF, 0xB3, 0x00, 0x7C, 0x05, 0x03, 0x06, 0x61, 0x5D, 0x91, 0x09, 0x60, +- 0x02, 0x65, 0x02, 0x03, 0x00, 0x61, 0x15, 0x00, 0xD4, 0x80, 0x63, 0x45, 0xFB, 0x07, 0x65, 0x43, +- 0x80, 0x60, 0x00, 0x62, 0xF6, 0x82, 0x53, 0x90, 0xE3, 0x83, 0xFC, 0x04, 0xEB, 0x83, 0xEB, 0x83, +- 0xEA, 0x82, 0x5C, 0x94, 0xB2, 0x9C, 0xF3, 0x07, 0x64, 0x41, 0xDD, 0x81, 0xE1, 0x81, 0xE1, 0x81, +- 0xE1, 0x81, 0x2B, 0x44, 0x54, 0x90, 0x70, 0x45, 0x02, 0x28, 0x61, 0x44, 0xC4, 0x84, 0xFF, 0xFF, +- 0x04, 0x24, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, 0x20, 0x29, 0x6D, 0xE2, 0xA4, 0xE2, +- 0xC4, 0xE2, 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0x32, 0xF1, 0x08, 0x29, 0x09, 0x00, +- 0x64, 0x40, 0x07, 0x22, 0x06, 0x00, 0x43, 0xFF, 0x27, 0x44, 0x10, 0xBC, 0x40, 0x47, 0x00, 0x64, +- 0x32, 0xFB, 0x31, 0x41, 0x3C, 0x44, 0x01, 0xB1, 0x00, 0xBC, 0x0A, 0x02, 0x09, 0x03, 0x32, 0xF3, +- 0x00, 0x7C, 0x01, 0xB4, 0xFF, 0xFF, 0x04, 0x03, 0x32, 0xF9, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, +- 0xC8, 0x60, 0x09, 0x7D, 0x00, 0x60, 0x00, 0x6B, 0x00, 0x64, 0x33, 0xFB, 0x0C, 0x60, 0x16, 0x64, +- 0xA0, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xE1, 0x30, 0x40, 0x02, 0x36, 0xA1, 0xFF, 0x83, 0xFF, +- 0x8D, 0xFF, 0x5C, 0x44, 0x5C, 0x43, 0x5C, 0x42, 0x5C, 0x41, 0x5C, 0x40, 0xAC, 0xFF, 0xAD, 0xFF, +- 0xE7, 0xE1, 0xB3, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x03, 0x02, +- 0x28, 0xE2, 0x40, 0xFF, 0xA1, 0xFF, 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0xB7, 0x60, +- 0xF7, 0x64, 0x40, 0x40, 0xBA, 0xF3, 0x7E, 0xFB, 0x0F, 0x60, 0xE2, 0x63, 0xC7, 0xF3, 0xBD, 0xDB, +- 0x00, 0x60, 0x9A, 0x64, 0xBD, 0xDB, 0x02, 0x64, 0xBD, 0xDB, 0x04, 0x64, 0xA3, 0xDB, 0x5C, 0x49, +- 0x0A, 0x64, 0x40, 0x4B, 0x5C, 0x5C, 0x01, 0x60, 0x39, 0xE2, 0x04, 0x60, 0x00, 0x7A, 0x89, 0xFF, +- 0x03, 0x60, 0xFF, 0x73, 0x88, 0xFF, 0xB7, 0x60, 0xF7, 0x78, 0xFF, 0xFF, 0x30, 0x44, 0x02, 0xA8, +- 0x00, 0xE1, 0x06, 0x02, 0x40, 0xFF, 0x42, 0xFF, 0x43, 0xFF, 0x44, 0xFF, 0x45, 0xFF, 0xA1, 0xFF, +- 0x88, 0xFF, 0x85, 0xFF, 0x21, 0xE1, 0x5C, 0x40, 0xC3, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0xA2, 0xFF, +- 0x30, 0x44, 0x02, 0xA8, 0x00, 0xE1, 0x01, 0x02, 0xA1, 0xFF, 0x86, 0xFF, 0x88, 0xFF, 0x5C, 0x46, +- 0x5C, 0x49, 0x5C, 0x40, 0xEF, 0x60, 0x58, 0x4F, 0x1B, 0x78, 0xFF, 0xFF, 0x1D, 0x60, 0x58, 0x4F, +- 0x81, 0x78, 0xFF, 0xFF, 0xD3, 0x60, 0x58, 0x4F, 0x58, 0x78, 0xFF, 0xFF, 0xE7, 0x60, 0x58, 0x4F, +- 0x99, 0x78, 0xFF, 0xFF, 0x20, 0x60, 0x58, 0x4F, 0x19, 0x78, 0xFF, 0xFF, 0xF4, 0x60, 0x58, 0x4F, +- 0xE9, 0x78, 0xFF, 0xFF, 0xE9, 0x60, 0x58, 0x4F, 0xCA, 0x78, 0xFF, 0xFF, 0x27, 0x60, 0x58, 0x4F, +- 0x71, 0x78, 0xFF, 0xFF, 0xEE, 0x60, 0x58, 0x4F, 0x69, 0x78, 0xFF, 0xFF, 0x1F, 0xE1, 0xA3, 0xFF, +- 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0x03, 0xE1, 0xA3, 0xFF, 0xFE, 0xFC, 0xFF, 0xFC, 0x25, 0x60, +- 0x96, 0x63, 0x17, 0xFD, 0xAE, 0xFF, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, 0x42, 0x6F, 0x6F, 0x74, +- 0x63, 0x6F, 0x64, 0x65, 0x20, 0x21, 0x21, 0x20, 0x20, 0x00, 0x53, 0x54, 0x41, 0x2F, 0x41, 0x50, +- 0x20, 0x46, 0x75, 0x6E, 0x63, 0x27, 0x73, 0x00, 0x1F, 0x00, 0x04, 0x00, 0x01, 0x00, 0x24, 0x00, +- 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, +- 0x06, 0x00, 0x07, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x07, 0x00, +- 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, +- 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0xA6, 0xF3, 0x21, 0x61, 0x00, 0x7C, 0x01, 0x00, 0x00, 0xFA, +- 0x60, 0x46, 0xFE, 0x63, 0xA3, 0xD8, 0xFE, 0x1F, 0xCD, 0x81, 0xD8, 0x84, 0xF8, 0x02, 0x21, 0x61, +- 0x80, 0x67, 0x40, 0x4A, 0xA6, 0xF5, 0x05, 0x18, 0x2A, 0x43, 0x02, 0xFC, 0x5F, 0x8A, 0x00, 0xF4, +- 0xFA, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0xA8, 0xF1, 0xA7, 0xF3, 0x7C, 0x63, 0xAA, 0xFB, 0x60, 0x46, +- 0x01, 0xFC, 0xDC, 0x84, 0xD0, 0x80, 0x00, 0xFA, 0xFA, 0x04, 0xAB, 0xFB, 0x60, 0x46, 0x00, 0x64, +- 0x00, 0xFA, 0x63, 0x44, 0x80, 0x7F, 0x01, 0xFA, 0xA8, 0xF3, 0xA7, 0xF1, 0xDC, 0x84, 0xD0, 0x84, +- 0xA9, 0xFB, 0x03, 0x60, 0x26, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0x2E, 0xFB, 0x82, 0xFF, 0x40, 0x42, 0x87, 0xFF, 0xA9, 0xF3, 0xB1, 0xFB, 0x00, 0x64, 0x40, 0x50, +- 0x63, 0xFF, 0x60, 0xFF, 0x66, 0xFF, 0x65, 0xFF, 0x64, 0xFF, 0x61, 0xFF, 0x62, 0xFF, 0x49, 0x60, +- 0x02, 0xE1, 0x52, 0x60, 0x02, 0xE1, 0x5C, 0x60, 0x02, 0xE1, 0x65, 0x60, 0x02, 0xE1, 0x6B, 0x60, +- 0x02, 0xE1, 0x76, 0x60, 0x02, 0xE1, 0x41, 0x60, 0x02, 0xE1, 0x0C, 0x64, 0x13, 0x60, 0x1C, 0xFB, +- 0x41, 0x60, 0x07, 0x64, 0x9F, 0xFB, 0x2D, 0xFF, 0x06, 0x61, 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, +- 0xB6, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0xF0, 0x67, 0x0E, 0xFA, 0x26, 0x60, 0x04, 0x64, +- 0x13, 0x60, 0x10, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0x2B, 0x41, 0x4D, 0x8B, 0xFF, 0xFF, 0xEA, 0x02, 0x05, 0x61, 0x41, 0x4B, 0x09, 0x60, 0x08, 0x61, +- 0xB6, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0x25, 0x60, 0xF8, 0x64, 0x13, 0x60, 0x10, 0xFB, +- 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x2B, 0x41, 0x4D, 0x8B, +- 0xFF, 0xFF, 0xEC, 0x02, 0x40, 0x60, 0x45, 0x78, 0xFF, 0xFF, 0x00, 0xEA, 0x00, 0xEB, 0x50, 0x60, +- 0x03, 0xEA, 0x51, 0x60, 0x13, 0xEA, 0x52, 0x60, 0x30, 0xEA, 0x53, 0x60, 0x40, 0xEA, 0x54, 0x60, +- 0x52, 0xEA, 0x55, 0x60, 0x6D, 0xEA, 0x56, 0x60, 0x71, 0xEA, 0x57, 0x60, 0x8B, 0xEA, 0x58, 0x60, +- 0x47, 0xEA, 0x59, 0x60, 0xA0, 0xEA, 0x5A, 0x60, 0xB2, 0xEA, 0x5B, 0x60, 0xC1, 0xEA, 0x5C, 0x60, +- 0xD7, 0xEA, 0x5D, 0x60, 0xEB, 0xEA, 0x5E, 0x60, 0xA0, 0xEA, 0x50, 0x60, 0x36, 0xEB, 0x51, 0x60, +- 0x37, 0xEB, 0x52, 0x60, 0x20, 0xEB, 0x53, 0x60, 0xE4, 0xEB, 0x54, 0x60, 0x34, 0xEB, 0x55, 0x60, +- 0x58, 0xEB, 0x56, 0x60, 0x48, 0xEB, 0x57, 0x60, 0xD0, 0xEB, 0x58, 0x60, 0xC3, 0xEB, 0x59, 0x60, +- 0xFC, 0xEB, 0x5A, 0x60, 0x34, 0xEB, 0x5B, 0x60, 0x58, 0xEB, 0x5C, 0x60, 0xC0, 0xEB, 0x5D, 0x60, +- 0xD0, 0xEB, 0x5E, 0x60, 0x91, 0xEB, 0x00, 0xEA, 0x00, 0xEB, 0xE0, 0x60, 0x02, 0xEA, 0xE0, 0x60, +- 0x03, 0xEB, 0xA0, 0x60, 0x00, 0xEB, 0xB0, 0x60, 0x00, 0xEB, 0xAB, 0x48, 0x40, 0x3B, 0x01, 0x00, +- 0xFC, 0x01, 0x00, 0xEB, 0x03, 0x60, 0x02, 0x64, 0xA0, 0xDB, 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, +- 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x24, 0x44, 0xFF, 0xB4, +- 0x04, 0xFB, 0x50, 0x60, 0x00, 0x64, 0x05, 0xFB, 0x10, 0x60, 0x10, 0x75, 0x2A, 0x60, 0x1D, 0x78, +- 0xFF, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x40, 0x00, 0x05, 0x60, 0xF9, 0xF1, 0x42, 0x60, 0x08, 0x64, +- 0x09, 0x60, 0x19, 0x63, 0x64, 0x40, 0x01, 0x2B, 0x04, 0x00, 0x42, 0x60, 0x09, 0x64, 0x0A, 0x60, +- 0x19, 0x63, 0x1C, 0x60, 0x0F, 0xFB, 0x04, 0x60, 0x00, 0xBC, 0x1C, 0x60, 0x0B, 0xFB, 0x1C, 0x60, +- 0x0A, 0xFD, 0x1D, 0x60, 0x19, 0x63, 0x1C, 0x60, 0x0E, 0xFD, 0x80, 0x60, 0x1C, 0x64, 0x3F, 0x40, +- 0x01, 0x2A, 0x02, 0x00, 0x60, 0x60, 0x1C, 0x64, 0x1C, 0x60, 0x10, 0xFB, 0x1C, 0x60, 0x0C, 0xFB, +- 0x1C, 0x60, 0x0F, 0xF3, 0xA0, 0x50, 0xA0, 0x50, 0x0B, 0x60, 0xF8, 0x63, 0xA3, 0xD1, 0x38, 0x60, +- 0x12, 0x61, 0xA1, 0xD3, 0xF8, 0xA3, 0x90, 0x84, 0xA2, 0xDB, 0xA3, 0xD1, 0x59, 0xD3, 0x06, 0xA3, +- 0x90, 0x84, 0xA2, 0xDB, 0xA3, 0xD1, 0x59, 0xD3, 0xFE, 0xA3, 0x90, 0x84, 0xA2, 0xDB, 0xA3, 0xD1, +- 0x59, 0xD3, 0xFF, 0xFF, 0x90, 0x84, 0xA2, 0xDB, 0x80, 0x60, 0x58, 0xEC, 0x80, 0x60, 0x00, 0xED, +- 0x80, 0x60, 0x80, 0xEE, 0x40, 0xEC, 0x00, 0xED, 0x00, 0xEE, 0xC0, 0x60, 0x59, 0xEC, 0xC0, 0x60, +- 0x07, 0xED, 0xC0, 0x60, 0x8F, 0xEE, 0xAD, 0x4F, 0xFA, 0xB4, 0xA0, 0x5D, 0x00, 0xF3, 0x28, 0xFB, +- 0x40, 0x44, 0x37, 0x60, 0x7B, 0x7C, 0x20, 0xF9, 0x3F, 0x60, 0x18, 0x7C, 0x21, 0xF9, 0x3F, 0x60, +- 0x2E, 0x7C, 0x22, 0xF9, 0x3F, 0x60, 0xC5, 0x7C, 0x23, 0xF9, 0x3F, 0x60, 0xD6, 0x7C, 0x24, 0xF9, +- 0x40, 0x60, 0x00, 0x7C, 0x25, 0xF9, 0x40, 0x60, 0x11, 0x7C, 0x26, 0xF9, 0xD0, 0x60, 0x00, 0xE8, +- 0x28, 0xE8, 0x44, 0x60, 0x01, 0xE6, 0x10, 0x67, 0x40, 0x52, 0x10, 0x60, 0x04, 0xE6, 0x08, 0x60, +- 0x06, 0x63, 0xFD, 0x60, 0x0C, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, 0x10, 0x18, 0xC3, 0x83, 0xD4, 0x80, +- 0xC3, 0x83, 0xF9, 0x02, 0xFA, 0xA3, 0xA3, 0xD3, 0x02, 0x60, 0x00, 0x65, 0xF9, 0xA0, 0xFC, 0xA0, +- 0x0D, 0x05, 0x04, 0x05, 0x78, 0x43, 0x02, 0x61, 0x29, 0x60, 0xEA, 0x78, 0x21, 0x60, 0x00, 0x65, +- 0x3F, 0x43, 0x21, 0x60, 0x00, 0x65, 0xC0, 0x60, 0x8F, 0xEE, 0x08, 0x00, 0x02, 0x60, 0x00, 0x65, +- 0x00, 0x60, 0x00, 0x64, 0x18, 0xFB, 0x3F, 0x43, 0x11, 0x60, 0x10, 0xE6, 0xB7, 0x84, 0x40, 0x5F, +- 0x37, 0x60, 0xF8, 0x63, 0x3F, 0x40, 0x20, 0x27, 0x06, 0x00, 0x0F, 0x60, 0xFF, 0x64, 0xBD, 0xDB, +- 0x0F, 0x60, 0xF0, 0x64, 0x03, 0x00, 0x0F, 0x64, 0xBD, 0xDB, 0x00, 0x64, 0xA3, 0xDB, 0x00, 0x60, +- 0x30, 0xE2, 0x00, 0x60, 0x50, 0xE2, 0x00, 0x60, 0x79, 0xE2, 0x00, 0x60, 0x90, 0xE2, 0x01, 0x60, +- 0xD0, 0xE2, 0x01, 0x60, 0xF0, 0xE2, 0x01, 0x60, 0xB0, 0xE2, 0x13, 0x64, 0xCB, 0xFB, 0x01, 0x60, +- 0x67, 0x64, 0x37, 0xFB, 0x00, 0x60, 0x28, 0x64, 0x36, 0xFB, 0x09, 0x60, 0x2A, 0x64, 0xB6, 0xFB, +- 0x82, 0xFF, 0x92, 0xFF, 0x5C, 0x41, 0x5C, 0x46, 0x5C, 0x47, 0x00, 0xE1, 0xA3, 0x60, 0xF4, 0x63, +- 0x0C, 0x60, 0x16, 0x64, 0xA0, 0xDD, 0x87, 0xFF, 0x97, 0xFF, 0x0C, 0x60, 0x02, 0x64, 0x40, 0x5A, +- 0x06, 0xA4, 0x40, 0x5B, 0x5C, 0x5E, 0x16, 0x60, 0xCF, 0xF3, 0x7D, 0xFB, 0x3F, 0x40, 0x01, 0x22, +- 0x03, 0x00, 0x80, 0x60, 0x37, 0x7C, 0x02, 0x00, 0x80, 0x60, 0x27, 0x7C, 0x1A, 0x60, 0x1F, 0xF9, +- 0x01, 0x60, 0x06, 0x64, 0xA7, 0xFB, 0x02, 0x60, 0x7F, 0x64, 0x00, 0x60, 0x42, 0x65, 0xD4, 0x84, +- 0xA8, 0xFB, 0xDC, 0x84, 0xA6, 0xFB, 0x12, 0x60, 0xD8, 0xFB, 0x40, 0x60, 0x58, 0x4E, 0x7D, 0x78, +- 0xFF, 0xFF, 0x3F, 0x40, 0x40, 0x26, 0x05, 0x00, 0x1C, 0x60, 0x0D, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, +- 0xA4, 0x52, 0x08, 0x60, 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, 0xA3, 0xD3, 0x02, 0xA8, +- 0xD4, 0x80, 0x21, 0x02, 0x20, 0x02, 0x19, 0x60, 0x48, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x80, 0x26, +- 0x1A, 0x00, 0x04, 0xA3, 0xFD, 0x60, 0x0D, 0x65, 0x5B, 0xD3, 0xBF, 0xD1, 0x14, 0x18, 0xC3, 0x83, +- 0xD4, 0x80, 0xC3, 0x83, 0xF9, 0x02, 0xBF, 0xD3, 0xAD, 0x49, 0xFE, 0xA0, 0x00, 0x64, 0x0C, 0x04, +- 0x08, 0xB1, 0x20, 0xBC, 0x08, 0x28, 0x18, 0xBC, 0x07, 0x7C, 0x0E, 0x60, 0xDF, 0xF9, 0x05, 0x7C, +- 0x0E, 0x60, 0xDE, 0xF9, 0x01, 0x00, 0x00, 0x64, 0x0E, 0x60, 0xDD, 0xFB, 0x40, 0x60, 0x95, 0x78, +- 0xFF, 0xFF, 0x5C, 0x51, 0x3F, 0x41, 0xA5, 0x4C, 0x50, 0x37, 0x0B, 0x00, 0x01, 0xB9, 0x41, 0x5F, +- 0xB5, 0x60, 0x55, 0xE0, 0x05, 0x60, 0xF9, 0xF1, 0xC0, 0x67, 0x90, 0x84, 0x3F, 0x40, 0x01, 0x26, +- 0xA0, 0x50, 0x06, 0x60, 0x08, 0xF3, 0x01, 0x60, 0x01, 0x65, 0x01, 0x60, 0x02, 0x7C, 0xD4, 0x80, +- 0xD0, 0x80, 0x01, 0x03, 0x10, 0x02, 0x5A, 0xD1, 0x5A, 0xD3, 0x3C, 0x60, 0x00, 0x66, 0xE0, 0x87, +- 0x40, 0x4A, 0x80, 0x60, 0x9E, 0x61, 0x64, 0x44, 0xC8, 0x84, 0x0C, 0x63, 0xAA, 0x46, 0x58, 0xD0, +- 0xAA, 0x46, 0x59, 0xD8, 0xFB, 0x1F, 0x08, 0x60, 0x00, 0x63, 0xFA, 0x60, 0x00, 0x65, 0xBD, 0xD3, +- 0xA3, 0xD3, 0x02, 0xA8, 0xD4, 0x80, 0x07, 0x02, 0x06, 0x02, 0x8C, 0x60, 0xBA, 0x61, 0x3C, 0x60, +- 0x00, 0x66, 0x41, 0x4B, 0x03, 0x00, 0x46, 0x60, 0x3B, 0x78, 0xFF, 0xFF, 0x2B, 0x41, 0x8D, 0x60, +- 0x02, 0x7C, 0xD1, 0x80, 0xA1, 0xD2, 0x25, 0x05, 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, +- 0xE0, 0x87, 0x40, 0x4A, 0x59, 0xD2, 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, +- 0xBD, 0xD1, 0xEC, 0x18, 0xD4, 0x80, 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, +- 0x67, 0x44, 0xC0, 0x84, 0xE0, 0x85, 0x2C, 0x44, 0xD4, 0x80, 0x63, 0x41, 0x01, 0x06, 0x65, 0x44, +- 0xC8, 0x83, 0xAA, 0x46, 0x59, 0xD1, 0x27, 0xD8, 0x5A, 0x87, 0xFC, 0x1F, 0xAA, 0x46, 0x2B, 0x41, +- 0xD5, 0x01, 0x8D, 0x60, 0x02, 0x61, 0x41, 0x4B, 0x2B, 0x41, 0x8D, 0x60, 0x02, 0x7C, 0xD1, 0x80, +- 0xA1, 0xD2, 0x27, 0x05, 0x59, 0xD0, 0x60, 0x45, 0x59, 0xD2, 0x44, 0x47, 0xE0, 0x87, 0x40, 0x4A, +- 0x59, 0xD2, 0x59, 0x8B, 0x40, 0x4C, 0x08, 0x60, 0x00, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, 0xEC, 0x18, +- 0xD4, 0x80, 0xEA, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0x04, 0xA3, 0xA3, 0xD1, +- 0x5A, 0x88, 0x2C, 0x43, 0xD3, 0x80, 0xFF, 0xFF, 0x01, 0x06, 0x64, 0x43, 0xCF, 0x83, 0xAA, 0x46, +- 0x60, 0xFE, 0x28, 0xD1, 0x5E, 0x88, 0x27, 0xD8, 0x5A, 0x87, 0xFB, 0x1F, 0x20, 0xFE, 0xAA, 0x46, +- 0xD3, 0x01, 0x07, 0x60, 0xEC, 0xF3, 0x20, 0x60, 0x00, 0x7C, 0x08, 0xB0, 0x10, 0xB0, 0x05, 0x02, +- 0x04, 0x03, 0x07, 0x60, 0xEB, 0xF9, 0x07, 0x60, 0xEA, 0xF9, 0x02, 0xB0, 0x04, 0xB0, 0x0F, 0x02, +- 0x13, 0x60, 0xD2, 0xF3, 0x0C, 0x03, 0x02, 0xBC, 0xA2, 0xDB, 0x14, 0x60, 0x65, 0xF3, 0x14, 0x60, +- 0x29, 0xF3, 0x02, 0xBD, 0x02, 0xBC, 0xA2, 0xDB, 0x65, 0x44, 0x14, 0x60, 0x65, 0xFB, 0x07, 0x60, +- 0xEC, 0xF3, 0x31, 0x41, 0x60, 0x40, 0x20, 0x2A, 0x40, 0xB9, 0x40, 0x26, 0x03, 0x00, 0x60, 0x40, +- 0x01, 0x26, 0x80, 0xB9, 0x41, 0x51, 0xFA, 0x60, 0x3A, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, +- 0xFF, 0xFF, 0x03, 0x02, 0x44, 0x60, 0xAD, 0x78, 0xFF, 0xFF, 0x5B, 0xD3, 0xF8, 0x60, 0x3F, 0x65, +- 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x14, 0x60, 0x74, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, +- 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0xBD, 0xD3, 0xFF, 0xFF, +- 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x14, 0x60, 0x77, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, +- 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x28, 0x60, +- 0xF4, 0x61, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0xA1, 0xD3, +- 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0x00, 0x7F, 0xE0, 0x84, +- 0xE0, 0x84, 0x59, 0xD3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, 0x14, 0x60, 0x7D, 0xF3, +- 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, +- 0xA2, 0xDB, 0x14, 0x60, 0x80, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, +- 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0x83, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, +- 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0xA3, 0xD3, +- 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x14, 0x60, 0x86, 0xF3, 0xE0, 0x9C, +- 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, +- 0x14, 0x60, 0x89, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, +- 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0x8C, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, +- 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x02, 0xA3, 0xA3, 0xD3, +- 0xF8, 0x60, 0x3F, 0x65, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x14, 0x60, 0x8F, 0xF3, 0xE0, 0x9C, +- 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, +- 0xBD, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x14, 0x60, 0x92, 0xF3, +- 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, +- 0xA2, 0xDB, 0x29, 0x60, 0x2A, 0x61, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0xE0, 0x84, 0xA1, 0xD3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, +- 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x59, 0xD3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA1, 0xDB, +- 0x14, 0x60, 0x98, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, +- 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0x9B, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, +- 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0x9E, 0xF3, +- 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, +- 0xA2, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0xE0, 0x84, 0x14, 0x60, +- 0xA1, 0xF3, 0xE0, 0x9C, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, +- 0xB0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0xA4, 0xF3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, +- 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x14, 0x60, 0xA7, 0xF3, 0xFF, 0xFF, +- 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0xA4, 0x84, 0xB0, 0x84, 0xA2, 0xDB, +- 0x00, 0x60, 0x6A, 0x63, 0x29, 0x60, 0x50, 0x61, 0x28, 0x60, 0xE4, 0x64, 0x58, 0xD1, 0x59, 0xD9, +- 0xFD, 0x1F, 0x14, 0x60, 0xB0, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, +- 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, 0xB4, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, +- 0xB6, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, 0xBD, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, +- 0xA2, 0xDB, 0x14, 0x60, 0xBF, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, 0xCB, 0xF3, +- 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x5A, 0xD3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, +- 0xCF, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, 0xD1, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, +- 0xA2, 0xDB, 0x14, 0x60, 0xD8, 0xF3, 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0x14, 0x60, 0xDA, 0xF3, +- 0xFF, 0xFF, 0x18, 0xAC, 0xA2, 0xDB, 0xFA, 0x60, 0x2C, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, +- 0xFF, 0xFF, 0x0E, 0x03, 0x63, 0x45, 0x2A, 0x60, 0xEA, 0x63, 0x06, 0x61, 0xA5, 0xD1, 0xDA, 0x85, +- 0x64, 0x44, 0x0F, 0xB4, 0xBD, 0xDB, 0x64, 0x47, 0x0F, 0xB4, 0xCD, 0x81, 0xBD, 0xDB, 0xF6, 0x02, +- 0xFA, 0x60, 0x30, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x14, 0x03, 0xBD, 0xD3, +- 0x63, 0x46, 0x2B, 0x60, 0x82, 0x63, 0x15, 0x60, 0xD0, 0xFB, 0xDA, 0x85, 0xBD, 0xDB, 0x0E, 0x61, +- 0xA6, 0xD1, 0xDA, 0x86, 0x64, 0x44, 0xFF, 0xB4, 0xA5, 0xDB, 0xDA, 0x85, 0x64, 0x47, 0xFF, 0xB4, +- 0xCD, 0x81, 0xBD, 0xDB, 0xF5, 0x02, 0xFA, 0x60, 0x31, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, +- 0xFF, 0xFF, 0x22, 0x03, 0xBD, 0xD3, 0x15, 0x60, 0xEE, 0xFB, 0x5A, 0x81, 0x15, 0x60, 0xFD, 0xFB, +- 0x5A, 0x82, 0x16, 0x60, 0x0C, 0xFB, 0x5A, 0x83, 0x16, 0x60, 0x1B, 0xFB, 0x5A, 0x84, 0x0E, 0x61, +- 0xBD, 0xD1, 0xBD, 0xD5, 0x64, 0x44, 0xFF, 0xB4, 0x21, 0xDB, 0x5A, 0x81, 0x64, 0x47, 0xFF, 0xB4, +- 0x22, 0xDB, 0x5A, 0x82, 0x66, 0x44, 0xFF, 0xB4, 0x23, 0xDB, 0x5A, 0x83, 0x66, 0x47, 0xFF, 0xB4, +- 0x24, 0xDB, 0xCD, 0x81, 0x5A, 0x84, 0xEC, 0x02, 0xFA, 0x60, 0x47, 0x65, 0x46, 0x60, 0x58, 0x4D, +- 0x4E, 0x78, 0xFF, 0xFF, 0x11, 0x03, 0x63, 0x45, 0x2C, 0x60, 0x54, 0x63, 0xA5, 0xD1, 0xDA, 0x85, +- 0xBD, 0xD9, 0x02, 0x61, 0xA5, 0xD1, 0xDA, 0x85, 0x64, 0x47, 0x00, 0x7E, 0xBD, 0xDB, 0x64, 0x44, +- 0x00, 0x7E, 0xCD, 0x81, 0xBD, 0xDB, 0xF6, 0x02, 0xFA, 0x60, 0x2E, 0x65, 0x46, 0x60, 0x58, 0x4D, +- 0x4E, 0x78, 0xFF, 0xFF, 0x1F, 0x03, 0x63, 0x46, 0xFC, 0xA3, 0xA3, 0xD3, 0x2B, 0x60, 0x02, 0x63, +- 0xCC, 0x84, 0xE8, 0x84, 0xCC, 0x81, 0x00, 0x36, 0x0D, 0x00, 0x63, 0x45, 0xA6, 0xD3, 0x5A, 0xD1, +- 0xDA, 0x86, 0xFF, 0xB4, 0xE0, 0x84, 0xC4, 0x84, 0x5C, 0x90, 0xBD, 0xD9, 0xFD, 0x02, 0xCD, 0x81, +- 0x66, 0x42, 0xF4, 0x02, 0x66, 0x42, 0x5A, 0xD3, 0x2B, 0x60, 0x42, 0x65, 0xBD, 0xDB, 0xD7, 0x80, +- 0xFF, 0xFF, 0xFC, 0x02, 0x2C, 0x60, 0x68, 0x61, 0xFA, 0x60, 0x46, 0x65, 0x46, 0x60, 0x58, 0x4D, +- 0x4E, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, 0x2F, 0x65, 0x46, 0x60, +- 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, 0x3E, 0x65, +- 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, 0xFA, 0x60, +- 0x3F, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, 0xD9, 0x81, +- 0xFA, 0x60, 0x40, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x01, 0x03, 0xA1, 0xDD, +- 0xD9, 0x81, 0xFA, 0x60, 0x3B, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x01, 0x03, +- 0xA1, 0xDD, 0xFA, 0x60, 0x48, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x10, 0x03, +- 0xBD, 0xD3, 0x2C, 0x60, 0xC4, 0x61, 0x0E, 0xB4, 0xBD, 0xD1, 0xA1, 0xDB, 0x64, 0x47, 0x0E, 0xB4, +- 0xA3, 0xD1, 0x59, 0xDB, 0x64, 0x44, 0x0E, 0xB4, 0x59, 0xDB, 0x64, 0x47, 0x0E, 0xB4, 0x59, 0xDB, +- 0xFA, 0x60, 0x29, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x04, 0xA3, +- 0xA3, 0xD3, 0x20, 0x60, 0x00, 0x65, 0xB4, 0x84, 0x13, 0x60, 0xA6, 0xFB, 0xFA, 0x60, 0x2A, 0x65, +- 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x30, 0x03, 0x04, 0xA3, 0xBD, 0xD1, 0x14, 0x60, +- 0x4A, 0xF3, 0x64, 0x41, 0x64, 0x5E, 0xA2, 0xDB, 0x64, 0x47, 0x5A, 0xD3, 0x60, 0x5C, 0x64, 0x5F, +- 0xA2, 0xDB, 0x14, 0x60, 0x60, 0xF3, 0xFF, 0x60, 0xC0, 0xB5, 0x61, 0x40, 0x80, 0x27, 0x05, 0x00, +- 0xE9, 0x87, 0x3F, 0xB4, 0xB4, 0x84, 0xA2, 0xDB, 0x15, 0x00, 0x65, 0x44, 0xA2, 0xDB, 0xE1, 0x80, +- 0xF9, 0x87, 0x01, 0x7F, 0x14, 0x60, 0x63, 0xF3, 0x60, 0x41, 0xE0, 0x84, 0xE0, 0x84, 0xE9, 0x81, +- 0xF8, 0x84, 0xE9, 0x81, 0xF8, 0x84, 0xA2, 0xDB, 0x4A, 0xD3, 0xFF, 0x60, 0x80, 0x65, 0xA4, 0x84, +- 0x34, 0x94, 0xA2, 0xDB, 0xDB, 0x83, 0x14, 0x60, 0xDF, 0xFD, 0xFA, 0x60, 0x2B, 0x65, 0x46, 0x60, +- 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x04, 0xA3, 0xBD, 0xD3, 0x14, 0x60, 0x4D, 0xFB, +- 0xA3, 0xD3, 0x14, 0x60, 0x11, 0xFB, 0xFA, 0x60, 0x3C, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, +- 0xFF, 0xFF, 0x1F, 0x03, 0xA3, 0xD3, 0xFC, 0x60, 0xFC, 0x65, 0xA4, 0x84, 0x60, 0x5C, 0x00, 0x7E, +- 0xC0, 0x60, 0x00, 0xA0, 0x60, 0x43, 0x07, 0x04, 0x14, 0x60, 0x51, 0xF3, 0xFF, 0xFF, 0x03, 0x60, +- 0xFF, 0xB4, 0x3C, 0x94, 0xA2, 0xDB, 0x28, 0x60, 0x2A, 0x61, 0x64, 0x44, 0x00, 0x7F, 0xC0, 0xA0, +- 0x60, 0x47, 0x07, 0x04, 0x60, 0x43, 0xA1, 0xD3, 0xFF, 0xFF, 0x03, 0x60, 0xFF, 0xB4, 0x3C, 0x94, +- 0xA1, 0xDB, 0xFA, 0x60, 0x49, 0x65, 0x46, 0x60, 0x58, 0x4D, 0x4E, 0x78, 0xFF, 0xFF, 0x1B, 0x03, +- 0x32, 0x60, 0xAB, 0x61, 0x1C, 0x7C, 0x60, 0xFE, 0xA3, 0xD3, 0x5D, 0xD3, 0x0F, 0xB5, 0xD4, 0x84, +- 0xA1, 0xDB, 0xBD, 0xD3, 0xFF, 0xFF, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x5D, 0xD3, +- 0x0F, 0xB5, 0xD4, 0x84, 0xA1, 0xDB, 0x67, 0x44, 0xC0, 0x9C, 0x64, 0x40, 0x00, 0x36, 0x10, 0x00, +- 0x64, 0x40, 0x0E, 0x3A, 0xE9, 0x01, 0x20, 0xFE, 0xFA, 0x60, 0x4A, 0x65, 0x46, 0x60, 0x58, 0x4D, +- 0x4E, 0x78, 0xFF, 0xFF, 0x05, 0x03, 0x32, 0x60, 0xC7, 0x61, 0x0E, 0x7C, 0x60, 0xFE, 0xDC, 0x01, +- 0x20, 0xFE, 0xB8, 0xFE, 0xB9, 0xFE, 0xBA, 0xFE, 0xBB, 0xFE, 0xBD, 0xFE, 0xBF, 0xFE, 0x19, 0x60, +- 0x48, 0xF3, 0x12, 0x63, 0x60, 0x40, 0x01, 0x27, 0x04, 0x00, 0x0B, 0x60, 0xEA, 0x62, 0x5A, 0xDF, +- 0xFE, 0x1F, 0x41, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x06, 0x63, 0xBE, 0xD3, 0xBD, 0xD1, +- 0x07, 0x18, 0xD4, 0x80, 0x05, 0x18, 0x03, 0x03, 0xC3, 0x83, 0xC3, 0x83, 0xF7, 0x01, 0xDB, 0x83, +- 0x00, 0xBC, 0x2D, 0x58, 0xFF, 0xFF, 0x86, 0xFD, 0xAA, 0x2D, 0x00, 0x00, 0x06, 0x00, 0x10, 0xFD, +- 0x6E, 0x01, 0x00, 0x00, 0x02, 0x00, 0x14, 0xFD, 0x8E, 0x32, 0x00, 0x00, 0x0A, 0x00, 0x41, 0xFA, +- 0x40, 0x2A, 0x00, 0x00, 0x22, 0x00, 0x42, 0xFA, 0x62, 0x2A, 0x00, 0x00, 0x22, 0x00, 0x43, 0xFA, +- 0x84, 0x2A, 0x00, 0x00, 0x22, 0x00, 0x44, 0xFA, 0xA6, 0x2A, 0x00, 0x00, 0x22, 0x00, 0x45, 0xFA, +- 0xC8, 0x2A, 0x00, 0x00, 0x22, 0x00, 0x25, 0xFD, 0x9E, 0x01, 0x00, 0x00, 0x02, 0x00, +- +-}; /* fw_image_3_data */ +- +-static const hcf_8 fw_image_4_data[] = { +- 0x6C, 0x40, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x41, 0xFF, 0x33, 0xF3, 0x02, 0x11, 0x31, 0x18, 0x1E, 0x00, 0x44, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, +- 0xC4, 0xE2, 0x27, 0x44, 0x20, 0x2A, 0x01, 0x00, 0xFF, 0xFF, 0x42, 0x64, 0x3A, 0xDB, 0x23, 0x00, +- 0x41, 0xFF, 0xA2, 0x60, 0x45, 0x78, 0xE2, 0xFE, 0x40, 0x49, 0x02, 0x60, 0x01, 0xE1, 0x1D, 0x00, +- 0x44, 0xFF, 0x1B, 0x09, 0x29, 0x44, 0x10, 0x2A, 0x04, 0x74, 0xCD, 0xE2, 0x10, 0x65, 0x0B, 0x00, +- 0xA3, 0x60, 0xC1, 0x78, 0xA4, 0xE2, 0x29, 0x44, 0x20, 0x2A, 0x0D, 0x00, 0x20, 0xAC, 0xEC, 0x01, +- 0xA3, 0x60, 0xC1, 0x78, 0x46, 0xFF, 0xB4, 0x84, 0x40, 0x49, 0xA1, 0xFF, 0xFF, 0xFF, 0x80, 0x3E, +- 0xA3, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0x62, 0xFF, 0x08, 0xE1, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, +- 0xAA, 0x60, 0xA5, 0x78, 0x4C, 0x4E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAA, 0x60, 0xB3, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC4, 0xE2, 0x84, 0xFF, 0x22, 0x58, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA4, 0x60, 0x39, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0xE1, 0x01, 0xFF, 0xFF, +- 0x10, 0x29, 0xFA, 0x01, 0xE4, 0xE2, 0xAA, 0x60, 0x5F, 0x78, 0xB2, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC1, 0x60, 0xFC, 0x78, 0x64, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xAA, 0x60, 0x46, 0x78, 0xAC, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x80, 0x29, 0xE2, 0x01, 0xAA, 0x60, 0xA2, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB5, 0x60, 0x5C, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB5, 0x60, 0x94, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB3, 0x60, 0xC9, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB3, 0x60, 0xFC, 0x78, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB3, 0x60, 0xFC, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB7, 0x60, 0x20, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB3, 0x60, 0xFF, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0x60, 0x83, 0x64, 0x80, 0x29, 0x09, 0xFB, 0xB5, 0x60, 0x25, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x98, 0xFF, 0x3A, 0x60, 0x18, 0x78, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x39, 0x60, 0x8F, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC0, 0x60, 0x67, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xBF, 0x60, 0xE1, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xB7, 0x60, 0xE9, 0x78, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xA1, 0xFF, 0x98, 0xFF, 0x83, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xC3, 0x60, 0x4D, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xB0, 0xFF, 0xB1, 0xFF, 0x40, 0xFF, 0x43, 0xFF, 0xC3, 0x60, 0x48, 0x78, 0x44, 0xFF, 0xFF, 0x01, +- 0xC3, 0x60, 0x4D, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0x3E, 0x60, 0x8C, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xC3, 0x60, 0x48, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xC3, 0x60, 0x47, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, +- 0xCA, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xF3, 0x60, 0x9A, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x42, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x85, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xCA, 0x60, 0xD0, 0x78, 0x24, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xF2, 0x60, 0x47, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xCA, 0x60, 0xD0, 0x78, 0x44, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xCA, 0x60, 0xD0, 0x78, 0x84, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0xCA, 0x60, 0xD0, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x29, 0x60, 0xF2, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x2A, 0x60, 0x20, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x2A, 0x60, 0x3E, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x2A, 0x60, 0x1D, 0x78, 0x28, 0xE2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x2A, 0x60, 0x1D, 0x78, 0x44, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x2A, 0x60, 0x1D, 0x78, 0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x2A, 0x60, 0x1D, 0x78, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0x60, 0x87, 0x64, 0x80, 0x29, 0x09, 0xFB, 0x47, 0xFF, 0x2A, 0x60, 0x1D, 0x78, 0xFF, 0xFF, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x43, 0xF7, 0xA7, 0xFF, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x37, 0x60, 0x82, 0x78, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x36, 0x60, 0x8F, 0x78, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +- 0x41, 0xFF, 0x00, 0x60, 0x03, 0xE1, 0x21, 0x46, 0x66, 0x45, 0x00, 0xF4, 0x2E, 0x44, 0x09, 0xFA, +- 0x6A, 0x61, 0x7F, 0x60, 0xFE, 0x63, 0xA1, 0xFF, 0x9A, 0xFF, 0x05, 0x11, 0x0A, 0x00, 0x00, 0xF4, +- 0x01, 0xF2, 0x17, 0x18, 0x7A, 0x61, 0x02, 0x25, 0x04, 0x00, 0x6C, 0x44, 0x7A, 0xDA, 0xFB, 0x1C, +- 0xF6, 0x11, 0xD9, 0x81, 0x41, 0xFF, 0x02, 0x1C, 0x00, 0xF4, 0xDA, 0x82, 0x41, 0xFF, 0xC9, 0x81, +- 0xCB, 0x83, 0x6C, 0x44, 0x5A, 0xDA, 0x02, 0x1C, 0x00, 0xF4, 0x81, 0xF2, 0x6C, 0x44, 0x5A, 0xDA, +- 0xCB, 0x83, 0x02, 0x74, 0x02, 0x60, 0x04, 0xE1, 0x80, 0x60, 0x00, 0x61, 0x5D, 0x93, 0xB5, 0xFF, +- 0x98, 0xFF, 0x26, 0x44, 0xFD, 0xB4, 0x84, 0xBC, 0x40, 0x46, 0x65, 0x46, 0x00, 0x64, 0x23, 0xFA, +- 0x3F, 0xFC, 0x63, 0x47, 0x0A, 0x63, 0x0F, 0xFC, 0x00, 0xF4, 0x08, 0xFA, 0xCB, 0xFE, 0x18, 0xE1, +- 0x44, 0xFF, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0xE2, 0xFE, 0x03, 0x04, 0xA3, 0x60, 0x05, 0x78, +- 0xFF, 0xFF, 0xE0, 0xFE, 0x03, 0x04, 0xA3, 0x60, 0x1B, 0x78, 0xFF, 0xFF, 0xE1, 0xFE, 0x07, 0x05, +- 0x9F, 0xFE, 0x03, 0x04, 0x3A, 0x60, 0x77, 0x78, 0xFF, 0xFF, 0x43, 0xFF, 0xA9, 0x01, 0x95, 0xF3, +- 0xFF, 0xFF, 0x80, 0xB4, 0xFF, 0xFF, 0x08, 0x24, 0x16, 0x00, 0x29, 0x44, 0x08, 0x26, 0xE1, 0x01, +- 0x72, 0x44, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xB2, 0xF3, 0xE8, 0x85, +- 0xFF, 0xB7, 0xE0, 0x84, 0xE0, 0x84, 0xB4, 0x85, 0x73, 0x44, 0xD4, 0x84, 0x10, 0x65, 0xD4, 0x80, +- 0xFF, 0xFF, 0x01, 0x05, 0x8F, 0x00, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, 0x84, 0xE7, 0xA1, 0xF3, +- 0x7C, 0x45, 0x60, 0x40, 0x01, 0x23, 0x02, 0x65, 0x8C, 0x60, 0x48, 0x6A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x7F, 0x6A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x48, 0x60, 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x40, 0x60, 0x08, 0x6A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, +- 0x84, 0xE7, 0xBD, 0xFE, 0x0C, 0x60, 0x00, 0x62, 0x00, 0x60, 0x71, 0x7C, 0x00, 0x60, 0xB1, 0x65, +- 0x3D, 0x60, 0x58, 0x4D, 0x0F, 0x78, 0xFF, 0xFF, 0x08, 0xE1, 0x62, 0xFF, 0xA3, 0xFF, 0xFF, 0xFF, +- 0xA2, 0xFF, 0x02, 0x60, 0x08, 0xE1, 0xAE, 0x4F, 0x02, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x3F, 0x40, +- 0x40, 0x26, 0x09, 0x00, 0x1C, 0x60, 0x09, 0xF3, 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x52, 0x5A, 0xD3, +- 0x5A, 0xD1, 0xA0, 0x50, 0xA4, 0x50, 0xDB, 0xF3, 0xF1, 0xF1, 0x01, 0xA8, 0x07, 0xA8, 0x0A, 0x03, +- 0x09, 0x03, 0x64, 0x40, 0x01, 0x26, 0x09, 0x00, 0x1B, 0x60, 0xF3, 0xF3, 0xFF, 0xFF, 0x01, 0xB4, +- 0xFF, 0xFF, 0x03, 0x02, 0xAD, 0x4F, 0xFA, 0xB4, 0xA0, 0x5D, 0x19, 0x60, 0xF6, 0xF1, 0x89, 0xFF, +- 0x32, 0x40, 0x80, 0x2A, 0x1E, 0x00, 0x31, 0x40, 0x01, 0x2A, 0x1B, 0x00, 0x12, 0x60, 0xFF, 0xF3, +- 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x05, 0x03, 0x0E, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, +- 0x10, 0x00, 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x03, 0x03, 0x0F, 0xF2, +- 0xFF, 0xFF, 0x07, 0x1B, 0x64, 0x40, 0x01, 0x26, 0x03, 0x00, 0x08, 0x60, 0x00, 0x75, 0x01, 0x00, +- 0x10, 0xFF, 0x88, 0xFF, 0xA2, 0x60, 0x41, 0x78, 0xFF, 0xFF, 0x21, 0x46, 0x01, 0x5D, 0x5C, 0x62, +- 0x03, 0xE1, 0x44, 0xFF, 0xA1, 0xFF, 0x9A, 0xFF, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x62, 0x62, +- 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0xA1, 0xFF, 0x5A, 0xDC, 0x12, 0xE1, 0x02, 0x60, 0x01, 0xE1, +- 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x28, 0x40, 0x40, 0x2B, 0x03, 0x00, 0x29, 0x40, 0x20, 0x27, +- 0xA3, 0x00, 0xC8, 0x74, 0xCD, 0xE2, 0x29, 0x44, 0x08, 0xBC, 0x40, 0x49, 0x44, 0xFF, 0x05, 0xE1, +- 0xDB, 0xF3, 0x37, 0x60, 0xE8, 0x63, 0x03, 0xA8, 0x04, 0xA8, 0x06, 0x03, 0x05, 0x03, 0xA3, 0xD3, +- 0xFF, 0xFF, 0x01, 0xA8, 0x07, 0x18, 0x0A, 0x03, 0x28, 0x40, 0x08, 0x2A, 0x07, 0x00, 0x28, 0x40, +- 0x48, 0x36, 0x04, 0x00, 0xF1, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xF1, 0xFB, 0x29, 0x44, 0xFF, 0x60, +- 0xEF, 0x65, 0x24, 0x89, 0x40, 0x27, 0x3F, 0x00, 0x00, 0x00, 0x29, 0x40, 0x80, 0x27, 0x0B, 0x00, +- 0x07, 0x61, 0xA1, 0xFF, 0xCD, 0x81, 0x04, 0x25, 0x61, 0x00, 0x87, 0x4C, 0xFB, 0x02, 0xF3, 0x60, +- 0xA0, 0x64, 0x80, 0x4C, 0x07, 0x00, 0xA1, 0xFF, 0x9C, 0x4C, 0x9C, 0x4C, 0x9C, 0x4D, 0x05, 0x60, +- 0xCF, 0x64, 0x80, 0x4C, 0x28, 0x40, 0x40, 0x2B, 0x05, 0x00, 0x29, 0x40, 0x20, 0x27, 0x02, 0x00, +- 0x15, 0x60, 0x6F, 0x6B, 0x04, 0x25, 0x4A, 0x00, 0x30, 0x64, 0x3A, 0xDB, 0x44, 0xFF, 0x04, 0x25, +- 0x45, 0x00, 0x04, 0x60, 0x00, 0x65, 0x25, 0x44, 0xB4, 0x84, 0x80, 0x4E, 0x2D, 0x41, 0x04, 0x25, +- 0x3D, 0x00, 0x61, 0x4C, 0x00, 0x60, 0x8A, 0x65, 0xC5, 0x81, 0x61, 0x54, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x04, 0x25, 0x34, 0x00, 0x67, 0x4E, 0x07, 0x64, 0x1C, 0xFB, 0x00, 0xE1, 0x02, 0x60, 0x05, 0xE1, +- 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x28, 0x40, 0x40, 0x27, 0x0A, 0x00, 0x1C, 0x65, 0x28, 0x40, +- 0xA4, 0x36, 0x14, 0x65, 0x23, 0x44, 0xC4, 0x84, 0x28, 0x40, 0x08, 0x2A, 0x0C, 0x00, 0x07, 0x00, +- 0x23, 0x44, 0x1C, 0xA4, 0x29, 0x40, 0x20, 0x27, 0x02, 0x00, 0x11, 0x60, 0x0F, 0x6B, 0x3C, 0x46, +- 0x98, 0xF0, 0x23, 0x44, 0xC4, 0x84, 0x06, 0x74, 0x25, 0x5C, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xB0, 0x84, 0x80, 0x4C, 0x9C, 0x4C, 0x44, 0xFF, 0x18, 0xE1, 0x0A, 0x64, 0x1E, 0x74, +- 0x02, 0x60, 0x05, 0xE1, 0x40, 0x40, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0xC4, 0xE2, 0x27, 0x44, +- 0x20, 0x2A, 0x06, 0x00, 0x42, 0x64, 0x3A, 0xDB, 0x67, 0x4C, 0xB1, 0x60, 0xAD, 0x78, 0xFF, 0xFF, +- 0x41, 0x64, 0x3A, 0xDB, 0x62, 0xFF, 0x08, 0xE1, 0xE2, 0xFE, 0x72, 0x52, 0xA1, 0xFF, 0x98, 0xFF, +- 0x80, 0x3E, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x28, 0x40, 0x08, 0x27, 0x5A, 0x01, 0x3C, 0x46, +- 0x8B, 0xFF, 0x84, 0x60, 0x00, 0xE4, 0x0F, 0x60, 0x90, 0x64, 0xC9, 0x60, 0x58, 0x4F, 0x56, 0x78, +- 0xFF, 0xFF, 0x3F, 0xF2, 0x00, 0x60, 0x18, 0x70, 0x18, 0x71, 0x20, 0x72, 0x00, 0xF2, 0x60, 0x53, +- 0x20, 0xE1, 0xA1, 0xFF, 0x88, 0x75, 0x00, 0xE1, 0xFF, 0xFF, 0x60, 0x50, 0x75, 0x44, 0x12, 0x71, +- 0x6E, 0x72, 0x81, 0x75, 0xFF, 0xFF, 0x88, 0xFF, 0xA3, 0x60, 0x21, 0x78, 0xFF, 0xFF, 0x32, 0xF3, +- 0x08, 0x29, 0x0A, 0x00, 0x60, 0x40, 0x07, 0x22, 0x07, 0x00, 0xFE, 0xB4, 0x32, 0xFB, 0x27, 0x44, +- 0x10, 0xBC, 0xF7, 0xB4, 0x40, 0x47, 0x43, 0xFF, 0x00, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x08, 0xE1, +- 0x31, 0x40, 0x01, 0x2A, 0x06, 0x00, 0x00, 0x64, 0x33, 0xFB, 0x01, 0x60, 0x0A, 0xE1, 0x25, 0x11, +- 0x24, 0x0A, 0xE5, 0xFE, 0x2D, 0x05, 0x32, 0x40, 0x80, 0x2A, 0x05, 0x00, 0x19, 0x60, 0xF2, 0xF3, +- 0xFF, 0xFF, 0x01, 0x18, 0x16, 0x00, 0x9F, 0xFE, 0x14, 0x05, 0x9D, 0xFE, 0x12, 0x04, 0x31, 0x41, +- 0x40, 0x2A, 0x0F, 0x00, 0x07, 0x60, 0xE9, 0xF1, 0xAE, 0x4C, 0x90, 0x80, 0x10, 0x2A, 0x09, 0x00, +- 0x7F, 0xB1, 0x07, 0x60, 0xE9, 0xFB, 0x60, 0x40, 0x10, 0x2A, 0x80, 0xB9, 0x41, 0x51, 0xDF, 0xFE, +- 0x19, 0xFF, 0x9F, 0xFE, 0x02, 0x04, 0x40, 0xE1, 0x08, 0x00, 0x7C, 0xE1, 0x31, 0x44, 0x01, 0x2A, +- 0x04, 0x00, 0xFD, 0xE1, 0x27, 0x44, 0x10, 0x26, 0x06, 0x00, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, +- 0xAA, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x08, 0x26, 0xFF, 0xFF, 0xC1, 0x60, 0xA3, 0x78, +- 0xFF, 0xFF, 0x48, 0xF3, 0x32, 0xF1, 0x00, 0x63, 0x64, 0x40, 0x07, 0x26, 0x03, 0x00, 0xA5, 0x60, +- 0x0F, 0x78, 0xFF, 0xFF, 0x43, 0xFF, 0x31, 0x40, 0x08, 0x26, 0xF0, 0x01, 0xCD, 0xE2, 0x85, 0xE1, +- 0x70, 0x41, 0xAD, 0x80, 0x71, 0x40, 0x80, 0x27, 0xE9, 0x12, 0x03, 0x03, 0xC2, 0x60, 0x15, 0x78, +- 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0xC4, 0xE2, 0x32, 0xFD, 0x60, 0x40, 0x01, 0x2A, 0xDB, 0x01, +- 0x00, 0x63, 0x32, 0xFD, 0x3C, 0x46, 0x3E, 0xF2, 0x2A, 0xF0, 0x27, 0x41, 0x44, 0x48, 0x20, 0xB9, +- 0x01, 0xB4, 0xF7, 0xB1, 0x0A, 0x03, 0x64, 0x40, 0x08, 0x27, 0x07, 0x00, 0x0F, 0x60, 0xDA, 0x63, +- 0x00, 0x64, 0x45, 0xFB, 0x46, 0xFB, 0xBD, 0xDB, 0xA3, 0xDB, 0xC8, 0x0A, 0xC7, 0x11, 0x1B, 0x60, +- 0xEE, 0xF3, 0xFF, 0xFF, 0x14, 0x18, 0x28, 0x40, 0xD4, 0x36, 0x11, 0x00, 0xAC, 0x4C, 0x80, 0x2A, +- 0x0E, 0x00, 0x1B, 0x60, 0xF1, 0xF3, 0xFF, 0xFF, 0x0A, 0x18, 0x1B, 0x60, 0xF2, 0xF3, 0x1B, 0x60, +- 0xEF, 0xF3, 0x60, 0x45, 0xD4, 0x80, 0xDC, 0x84, 0x02, 0x03, 0xA2, 0xDB, 0xAF, 0x01, 0x00, 0x64, +- 0x1B, 0x60, 0xEF, 0xFB, 0x41, 0x47, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x10, 0x26, 0x04, 0x00, +- 0x01, 0x2A, 0x05, 0x00, 0x10, 0x2B, 0x03, 0x00, 0x29, 0x47, 0x20, 0xBF, 0x40, 0x49, 0x1B, 0x60, +- 0xEE, 0xF3, 0xFF, 0xFF, 0x04, 0x18, 0xAE, 0x4F, 0x08, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0x05, 0xE1, +- 0x01, 0x60, 0x08, 0xE1, 0x2A, 0xE8, 0x3C, 0x46, 0x0F, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2A, +- 0x03, 0x00, 0xA7, 0x60, 0xE1, 0x78, 0xFF, 0xFF, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, +- 0x0E, 0x00, 0x1F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x2B, 0x09, 0x00, 0x19, 0x60, 0x7B, 0xF3, +- 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, 0xA8, 0x60, 0xEC, 0x78, 0xFF, 0xFF, 0x1F, 0xF2, +- 0xC0, 0x60, 0x00, 0x65, 0xA4, 0x9C, 0x3F, 0x60, 0xCF, 0x65, 0x29, 0x44, 0xA4, 0x84, 0x30, 0x89, +- 0x19, 0x60, 0x77, 0xF3, 0xFF, 0xFF, 0x19, 0x60, 0x55, 0xFB, 0x1F, 0xF2, 0x39, 0xF1, 0xE0, 0x60, +- 0xFF, 0xB5, 0x0A, 0x18, 0x60, 0x47, 0x1F, 0xB4, 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, +- 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, 0xB4, 0x81, 0x07, 0x60, 0xEA, 0xF1, 0xFF, 0xFF, +- 0xB1, 0x8C, 0x29, 0x40, 0x40, 0x2B, 0x10, 0x00, 0x29, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x1F, 0xB4, +- 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x01, 0x60, 0x09, 0x6B, +- 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x14, 0x00, 0x29, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x1F, 0xB4, +- 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, +- 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, 0x67, 0x44, 0x60, 0x4C, +- 0x00, 0xE1, 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x0D, 0x00, 0xE5, 0xFE, +- 0x03, 0x04, 0xAA, 0x60, 0x6F, 0x78, 0xFF, 0xFF, 0x32, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x07, 0x22, +- 0x43, 0xFF, 0xA3, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0x0B, 0x64, 0x3A, 0xDB, 0x01, 0x60, 0x0A, 0xE1, +- 0x1C, 0x42, 0x22, 0x46, 0x13, 0xF2, 0xFF, 0x65, 0x60, 0x47, 0x2A, 0xF2, 0x40, 0x45, 0x40, 0x48, +- 0x04, 0x2B, 0x13, 0x00, 0x16, 0xF2, 0x1D, 0xF2, 0x40, 0x43, 0x0F, 0xF2, 0x40, 0x4D, 0x0F, 0x64, +- 0x14, 0xF0, 0x35, 0xF2, 0xA0, 0x82, 0x0F, 0xB4, 0xCA, 0x85, 0xD4, 0x80, 0x10, 0xF2, 0x01, 0x02, +- 0x2B, 0xFA, 0x27, 0x44, 0x40, 0xBC, 0x40, 0x47, 0x13, 0x00, 0x17, 0xF2, 0x2C, 0xF0, 0x40, 0x43, +- 0x1B, 0xF2, 0x1D, 0xFA, 0x40, 0x4D, 0x64, 0x40, 0x01, 0x2A, 0x02, 0x00, 0xAB, 0xFC, 0x05, 0x00, +- 0x28, 0x40, 0xA4, 0x36, 0x02, 0x00, 0x11, 0xF2, 0x2B, 0xFA, 0x27, 0x44, 0xBF, 0xB4, 0x40, 0x47, +- 0xF0, 0xFE, 0xB0, 0x60, 0xB0, 0x78, 0xFF, 0xFF, 0x22, 0x46, 0x2C, 0xF0, 0x27, 0x44, 0xDF, 0xB4, +- 0x40, 0x47, 0x64, 0x40, 0x01, 0x26, 0x09, 0x00, 0x2A, 0xF2, 0x39, 0xF0, 0x8F, 0xB0, 0x88, 0x3A, +- 0x0D, 0x00, 0x64, 0x44, 0x60, 0xB0, 0x20, 0x3A, 0x09, 0x00, 0x28, 0x44, 0x04, 0x27, 0x05, 0x00, +- 0xD4, 0x3A, 0x03, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0x11, 0x00, 0x2A, 0xF0, 0x01, 0x65, +- 0x64, 0x40, 0xA4, 0x3A, 0x04, 0x65, 0x27, 0x44, 0x34, 0x87, 0x36, 0xF3, 0xFF, 0xFF, 0x60, 0x56, +- 0xAD, 0xE2, 0x04, 0x64, 0x3A, 0xDB, 0x41, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x06, 0x64, +- 0x3A, 0xDB, 0x22, 0x46, 0x01, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xC2, 0x60, 0x1E, 0x78, 0xFF, 0xFF, +- 0x28, 0x40, 0xC4, 0x3A, 0x0C, 0x00, 0x27, 0x44, 0xFD, 0xB4, 0x40, 0x47, 0xA8, 0xE2, 0x05, 0xE1, +- 0x01, 0x60, 0x08, 0xE1, 0x2A, 0xE8, 0x3C, 0x46, 0xA4, 0x60, 0xBF, 0x78, 0xFF, 0xFF, 0x3F, 0x40, +- 0x01, 0x2B, 0x05, 0x00, 0x67, 0x4C, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, 0x07, 0x60, +- 0xEB, 0xF1, 0x1F, 0xF2, 0x2A, 0xE8, 0xB0, 0x81, 0x29, 0x40, 0x40, 0x2B, 0x14, 0x00, 0x61, 0x4C, +- 0x29, 0x60, 0xC0, 0x65, 0x61, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, +- 0x01, 0x60, 0x00, 0xE1, 0x01, 0x60, 0x09, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0xFF, 0x60, 0xF2, 0x64, +- 0x64, 0x4C, 0x40, 0x43, 0x18, 0x00, 0x29, 0x47, 0x80, 0xB7, 0x34, 0x94, 0x60, 0x4C, 0x29, 0x60, +- 0xC0, 0x65, 0x61, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, +- 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x7C, 0x44, 0x29, 0x40, +- 0x80, 0x2B, 0x67, 0x44, 0x60, 0x4C, 0x40, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0x28, 0x45, 0xBF, 0x60, +- 0xFF, 0x64, 0x24, 0x88, 0xC4, 0xE2, 0x08, 0x64, 0x3A, 0xDB, 0x21, 0x46, 0x2A, 0x44, 0x72, 0x45, +- 0x24, 0xFA, 0xB2, 0xF3, 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, 0x01, 0x26, 0x64, 0x44, +- 0xB2, 0xF9, 0x25, 0xFA, 0xB3, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB3, 0xFB, 0x28, 0xFA, 0xB4, 0xF3, +- 0x02, 0x04, 0xDC, 0x84, 0xB4, 0xFB, 0x29, 0xFA, 0x24, 0x44, 0x04, 0x2A, 0x06, 0x00, 0x28, 0x40, +- 0xA4, 0x36, 0x03, 0x00, 0xA6, 0x60, 0xB1, 0x78, 0xFF, 0xFF, 0x26, 0x43, 0x84, 0xBB, 0xFC, 0xB3, +- 0x21, 0x46, 0x01, 0x5D, 0x0F, 0xFC, 0x5C, 0x46, 0x05, 0xFF, 0x27, 0x44, 0x01, 0x2A, 0x13, 0x00, +- 0x50, 0xFE, 0x28, 0x40, 0x08, 0x3A, 0x12, 0x00, 0x2F, 0xF2, 0x30, 0xF0, 0x60, 0x43, 0x31, 0xF2, +- 0x22, 0x46, 0x64, 0x41, 0x2C, 0xF0, 0x2D, 0xF0, 0xD3, 0x80, 0x2E, 0xF0, 0xD1, 0x80, 0xD0, 0x80, +- 0x27, 0x44, 0x09, 0x0C, 0x03, 0x00, 0x27, 0x44, 0x06, 0x22, 0x05, 0x00, 0xB8, 0xB4, 0x40, 0x47, +- 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xD4, 0x64, 0x40, 0x48, 0x0D, 0x64, 0x3A, 0xDB, 0x7C, 0x44, +- 0x1B, 0x60, 0xF0, 0xFB, 0x21, 0x46, 0x1C, 0xF2, 0x00, 0xE1, 0xF0, 0xFE, 0x00, 0x63, 0x28, 0x44, +- 0xA4, 0x36, 0x0A, 0x00, 0x04, 0x2B, 0x08, 0x00, 0x30, 0xF3, 0x2D, 0x45, 0xD4, 0x84, 0xCA, 0x65, +- 0xD4, 0x83, 0x01, 0x64, 0x1B, 0x60, 0xF0, 0xFB, 0xD4, 0x64, 0x35, 0x00, 0x0F, 0x64, 0x3A, 0xDB, +- 0x21, 0x46, 0x29, 0x40, 0x40, 0x27, 0x15, 0x00, 0x80, 0x27, 0x02, 0x00, 0xCA, 0x65, 0x01, 0x00, +- 0x6A, 0x65, 0x1C, 0xF2, 0xFF, 0xFF, 0x04, 0x7F, 0x40, 0x45, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, +- 0x38, 0x64, 0x37, 0x36, 0x15, 0x64, 0x6E, 0x3A, 0x17, 0x00, 0x84, 0x7F, 0x40, 0x45, 0x0B, 0x64, +- 0x13, 0x00, 0x1C, 0xF2, 0x1E, 0x65, 0x40, 0x45, 0x0B, 0x36, 0x1E, 0x64, 0x0F, 0x36, 0x16, 0x64, +- 0x0A, 0x36, 0x12, 0x64, 0x0E, 0x36, 0x0E, 0x64, 0x09, 0x36, 0x0E, 0x64, 0x0D, 0x36, 0x0A, 0x64, +- 0x08, 0x36, 0x0A, 0x64, 0x0C, 0x36, 0x0A, 0x64, 0x40, 0x4D, 0x00, 0xE1, 0xF0, 0xFE, 0x2B, 0xF2, +- 0xC4, 0x85, 0xD4, 0x83, 0xC4, 0x64, 0x40, 0x48, 0x2F, 0xF0, 0xB0, 0xF0, 0xB1, 0xF2, 0xA1, 0xFF, +- 0x12, 0x74, 0xCD, 0xE2, 0x80, 0x4E, 0x12, 0x74, 0x83, 0x4C, 0x12, 0x74, 0x9A, 0xFF, 0x84, 0x4C, +- 0x12, 0x74, 0x85, 0x4C, 0x12, 0x74, 0x81, 0x4C, 0x12, 0x74, 0xA1, 0xFF, 0x98, 0xFF, 0xB2, 0x60, +- 0x58, 0x4F, 0x2D, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0x18, 0xE1, 0x78, 0x44, 0x03, 0xA4, 0x35, 0xFB, +- 0xB2, 0x60, 0x70, 0x78, 0xFF, 0xFF, 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, 0x28, 0x40, 0xC4, 0x36, +- 0x07, 0x00, 0x1B, 0x60, 0xF0, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, +- 0x27, 0x44, 0x01, 0x2A, 0x05, 0x00, 0xFE, 0xB4, 0x40, 0x47, 0xA5, 0x60, 0x7F, 0x78, 0xFF, 0xFF, +- 0x16, 0x60, 0xAB, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x36, 0xC1, 0xFE, 0xA3, 0x60, 0xE7, 0x78, +- 0xFF, 0xFF, 0x28, 0x40, 0xB4, 0x3A, 0x0B, 0x00, 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, +- 0x40, 0x47, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xA6, 0x60, 0x3E, 0x78, 0xFF, 0xFF, 0x28, 0x44, +- 0xD4, 0x36, 0x03, 0x00, 0xA7, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0xA8, 0xE2, 0x27, 0x44, 0xFB, 0xB4, +- 0x40, 0x47, 0x1C, 0x42, 0x22, 0x46, 0x19, 0x60, 0xCF, 0xF3, 0xFF, 0xFF, 0x34, 0xFB, 0x2A, 0xF0, +- 0xF7, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDA, 0x60, 0x40, 0x40, 0x2B, 0xC4, 0x00, 0x22, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x22, 0x26, 0x3F, 0x00, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, 0x05, 0x00, +- 0xBA, 0x00, 0x04, 0x2B, 0xB8, 0x00, 0xA6, 0xF5, 0x01, 0x00, 0x07, 0xF4, 0x4B, 0xF2, 0xFF, 0xFF, +- 0xDC, 0x84, 0x4B, 0xFA, 0x0C, 0x60, 0xFC, 0x62, 0x80, 0xFF, 0xC8, 0x60, 0x78, 0x44, 0x02, 0xA4, +- 0xA2, 0xDB, 0x8C, 0x78, 0xFF, 0xFF, 0x82, 0xFF, 0xA6, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x00, 0x7C, +- 0x07, 0x03, 0x66, 0x43, 0x22, 0x46, 0x22, 0xF2, 0x63, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x01, 0x00, +- 0x3C, 0xF1, 0x4B, 0xF0, 0x64, 0x41, 0x64, 0x47, 0x60, 0x5F, 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, +- 0x60, 0x47, 0x22, 0x46, 0x3A, 0xFA, 0x64, 0x44, 0x20, 0x7F, 0x34, 0x94, 0x3B, 0xFA, 0x08, 0x60, +- 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, +- 0xD1, 0x60, 0x00, 0xEA, 0x80, 0x00, 0x2A, 0xF2, 0x00, 0x60, 0x7C, 0x62, 0x60, 0x40, 0x40, 0x2B, +- 0x24, 0x00, 0xA2, 0xD3, 0x00, 0x61, 0x60, 0xFE, 0xA0, 0xD3, 0x5E, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, +- 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, 0xC0, 0x2B, 0x04, 0x00, 0x80, 0x2A, 0x02, 0x00, 0x7F, 0xA4, +- 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, 0x60, 0x47, 0xDC, 0x87, 0x01, 0x61, 0xC0, 0x80, 0x00, 0x36, +- 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, 0x5A, 0xD1, 0xFF, 0xFF, 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, +- 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, 0xA2, 0xDB, 0x20, 0xFE, 0x00, 0x60, 0x3E, 0xF3, 0xFF, 0xFF, +- 0xA0, 0xD3, 0x5A, 0xD1, 0x3A, 0xFA, 0x3B, 0xF8, 0x74, 0x62, 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, +- 0xE0, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, +- 0xA0, 0x5A, 0x00, 0x60, 0x40, 0xF3, 0xFF, 0xFF, 0xA0, 0xD1, 0x5A, 0xD1, 0x64, 0x45, 0x64, 0x44, +- 0xE3, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE5, 0x7F, +- 0xA0, 0x5A, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5A, +- 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, +- 0xE9, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEB, 0x7F, +- 0xA0, 0x5A, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5A, +- 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5A, 0x08, 0x60, +- 0x00, 0xEA, 0x65, 0x44, 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, +- 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x0B, 0xF2, 0xFF, 0xFF, 0x7F, 0xB4, 0x0C, 0xF0, 0x04, 0x02, +- 0x64, 0x46, 0x00, 0xF0, 0x04, 0x64, 0x22, 0x46, 0x03, 0xFA, 0x60, 0x41, 0x64, 0x46, 0x01, 0xF2, +- 0xFC, 0xA1, 0x61, 0x45, 0xD4, 0x84, 0xFF, 0xFF, 0x08, 0x02, 0x00, 0xF0, 0x04, 0x63, 0x64, 0x46, +- 0x01, 0xF2, 0x22, 0x46, 0x1A, 0xFA, 0x03, 0xFC, 0x02, 0x00, 0x22, 0x46, 0x1A, 0xFA, 0x35, 0xF2, +- 0x04, 0xF8, 0xDC, 0x84, 0x35, 0xFA, 0x14, 0xF2, 0x0F, 0xB5, 0x0F, 0xB4, 0xCC, 0x84, 0x94, 0x80, +- 0x04, 0x60, 0x00, 0x65, 0x2A, 0xF2, 0x01, 0x02, 0x94, 0x84, 0x2A, 0xFA, 0x95, 0xFC, 0x06, 0x00, +- 0xC4, 0x3A, 0x07, 0x00, 0x27, 0x44, 0xFD, 0xB4, 0x40, 0x47, 0xA8, 0xE2, 0xA5, 0x60, 0x1C, 0x78, +- 0xFF, 0xFF, 0x28, 0x44, 0x04, 0x26, 0x05, 0x00, 0x68, 0x3A, 0x03, 0x00, 0x32, 0x44, 0x00, 0x27, +- 0x03, 0x00, 0xA3, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0x0A, 0x64, 0x3A, 0xDB, 0xA3, 0x60, 0xF4, 0x78, +- 0xFF, 0xFF, 0x0E, 0x64, 0x3A, 0xDB, 0x3C, 0x44, 0x60, 0x46, 0x1E, 0xF0, 0x40, 0x42, 0x64, 0x40, +- 0x40, 0x27, 0x48, 0x00, 0x1F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, 0x3C, 0x00, 0x80, 0x2B, +- 0x0B, 0x00, 0xBF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x80, 0x60, 0x00, 0x65, 0x29, 0x44, +- 0x34, 0x89, 0x80, 0x60, 0x00, 0x63, 0x05, 0x00, 0x3F, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, +- 0x00, 0x63, 0x1E, 0xF2, 0x39, 0xF1, 0xC0, 0x60, 0xFF, 0xB5, 0x0A, 0x18, 0x60, 0x47, 0x1F, 0xB4, +- 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, +- 0xB4, 0x84, 0x07, 0x60, 0xEA, 0xF1, 0x3C, 0x94, 0xB0, 0x84, 0x60, 0x4C, 0x29, 0x60, 0xC0, 0x65, +- 0x60, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, +- 0x05, 0x60, 0x69, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, +- 0x67, 0x44, 0x60, 0x4C, 0x32, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x04, 0x26, +- 0xCB, 0x01, 0xBF, 0x01, 0x40, 0x60, 0x00, 0x65, 0x29, 0x44, 0x34, 0x89, 0x40, 0x60, 0x00, 0x63, +- 0x9F, 0xF2, 0x1E, 0xF2, 0x39, 0xF1, 0xC0, 0x60, 0xFF, 0xB5, 0x0A, 0x18, 0x60, 0x47, 0x1F, 0xB4, +- 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, +- 0xB4, 0x84, 0x07, 0x60, 0xEA, 0xF1, 0x3C, 0x94, 0xB0, 0x81, 0x61, 0x4C, 0x29, 0x60, 0xC0, 0x65, +- 0x61, 0x47, 0x1F, 0xB4, 0xE0, 0x84, 0xE0, 0x84, 0x44, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, +- 0x01, 0x60, 0x09, 0x6B, 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x40, 0xE1, 0x01, 0x60, 0x08, 0xE1, +- 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0x82, 0xFF, 0x2A, 0xF2, 0x10, 0x60, 0x00, 0x65, +- 0xA4, 0x84, 0xB4, 0xBC, 0x1E, 0xF0, 0x40, 0x48, 0x64, 0x40, 0x40, 0x27, 0x17, 0x00, 0x1C, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x0A, 0x36, 0x06, 0x00, 0x14, 0x36, 0x07, 0x00, 0x37, 0x36, 0x08, 0x00, +- 0x6E, 0x36, 0x09, 0x00, 0x70, 0x7C, 0xA0, 0x63, 0x0F, 0x00, 0x38, 0x7C, 0x50, 0x63, 0x0C, 0x00, +- 0x15, 0x7C, 0x1E, 0x63, 0x09, 0x00, 0x0B, 0x7C, 0x0F, 0x63, 0x06, 0x00, 0x9C, 0xF4, 0xFF, 0x65, +- 0x63, 0x47, 0xA4, 0x9C, 0xA7, 0x84, 0x23, 0x00, 0x40, 0x45, 0x43, 0x4D, 0x00, 0xE1, 0xF0, 0xFE, +- 0x29, 0x40, 0x80, 0x2B, 0x03, 0x00, 0x00, 0x60, 0x6A, 0x65, 0x02, 0x00, 0x00, 0x60, 0xCA, 0x65, +- 0x1F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, 0x0E, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, +- 0x04, 0x27, 0x03, 0x00, 0x65, 0x44, 0xE0, 0x85, 0x12, 0x00, 0x2B, 0xF2, 0x11, 0xF0, 0xC0, 0x84, +- 0xD0, 0x84, 0xC4, 0x83, 0x11, 0x00, 0x1E, 0x64, 0xC4, 0x84, 0x60, 0x45, 0x08, 0x00, 0x40, 0x45, +- 0xFF, 0x60, 0xF8, 0x64, 0x40, 0x43, 0x00, 0xE1, 0xF0, 0xFE, 0x00, 0x60, 0x3C, 0x65, 0x91, 0xF4, +- 0x1B, 0xF0, 0xC3, 0x84, 0xC4, 0x84, 0xC0, 0x83, 0x28, 0x44, 0xA1, 0xFF, 0x12, 0x74, 0x80, 0x4E, +- 0x12, 0x74, 0x83, 0x4C, 0x9A, 0xFF, 0x12, 0x74, 0x56, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, +- 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x5C, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, +- 0x7A, 0xD4, 0x12, 0x74, 0xA1, 0xFF, 0x98, 0xFF, 0xB2, 0x60, 0x58, 0x4F, 0x2D, 0x78, 0xFF, 0xFF, +- 0xBC, 0xFF, 0xB5, 0xFF, 0x01, 0x60, 0x18, 0xE1, 0x47, 0xFF, 0x27, 0x44, 0x02, 0xBC, 0x40, 0x47, +- 0x36, 0xF3, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0x60, 0x56, +- 0xAD, 0xE2, 0xA5, 0x60, 0x79, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x7B, 0xF3, 0x19, 0x60, 0x3B, 0xF3, +- 0x60, 0x40, 0x04, 0x26, 0x0B, 0x00, 0x07, 0xB4, 0x60, 0x40, 0x01, 0x36, 0x07, 0x00, 0x29, 0x44, +- 0xBF, 0x60, 0xFF, 0xB7, 0x80, 0xBF, 0x40, 0x49, 0x80, 0x67, 0x05, 0x00, 0x3F, 0x60, 0xFF, 0x65, +- 0x29, 0x44, 0x24, 0x89, 0x00, 0x64, 0x16, 0x60, 0x50, 0xF1, 0xFF, 0xFF, 0x19, 0x60, 0x55, 0xF9, +- 0x39, 0xF1, 0x16, 0x60, 0x3C, 0xF1, 0x64, 0x41, 0x64, 0x5E, 0x60, 0x45, 0x64, 0x47, 0x1F, 0xB4, +- 0x54, 0x94, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, +- 0x07, 0x60, 0xEA, 0xF1, 0xB4, 0x84, 0xB0, 0x8C, 0x29, 0x60, 0xC0, 0x7C, 0x60, 0x47, 0x1F, 0xB4, +- 0xE0, 0x84, 0xE0, 0x84, 0x40, 0xD3, 0x5A, 0xD1, 0x01, 0x60, 0x00, 0xE1, 0x05, 0x60, 0x69, 0x6B, +- 0x60, 0x4C, 0xB5, 0xFF, 0x64, 0x4C, 0x7C, 0x44, 0x29, 0x40, 0x80, 0x2B, 0x67, 0x44, 0x60, 0x4C, +- 0x40, 0xE1, 0x01, 0x60, 0x08, 0xE1, 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0x82, 0xFF, +- 0x3C, 0x44, 0x60, 0x46, 0x40, 0x42, 0x13, 0x64, 0x3A, 0xDB, 0x10, 0x60, 0x00, 0x65, 0x3C, 0x46, +- 0x2A, 0xF2, 0x19, 0x60, 0x3B, 0xF1, 0xA4, 0x84, 0xC4, 0xBC, 0x40, 0x48, 0x64, 0x44, 0x04, 0x26, +- 0x09, 0x00, 0x02, 0x26, 0x0A, 0x00, 0x01, 0x26, 0x0B, 0x00, 0x08, 0x2A, 0x03, 0x00, 0x0B, 0x63, +- 0x6E, 0x64, 0x08, 0x00, 0x15, 0x63, 0x37, 0x64, 0x05, 0x00, 0x38, 0x63, 0x14, 0x64, 0x02, 0x00, +- 0x70, 0x63, 0x0A, 0x64, 0x43, 0x4D, 0x40, 0x45, 0x00, 0xE1, 0xF0, 0xFE, 0x00, 0x60, 0x1E, 0x64, +- 0x1B, 0xF0, 0x11, 0xF0, 0xC0, 0x84, 0xC0, 0x84, 0x60, 0x43, 0x28, 0x44, 0xA1, 0xFF, 0x12, 0x74, +- 0x80, 0x4E, 0x12, 0x74, 0x83, 0x4C, 0x9A, 0xFF, 0x12, 0x74, 0x5C, 0x62, 0x7A, 0xD4, 0x12, 0x74, +- 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0xA1, 0xFF, 0x98, 0xFF, 0xB2, 0x60, 0x58, 0x4F, +- 0x2D, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0x18, 0xE1, 0x78, 0x44, 0x03, 0xA4, 0x35, 0xFB, 0xB2, 0x60, +- 0x70, 0x78, 0xFF, 0xFF, 0xC4, 0xE2, 0x08, 0x64, 0x3A, 0xDB, 0xA4, 0x60, 0xBF, 0x78, 0xFF, 0xFF, +- 0x26, 0x43, 0x24, 0x40, 0x01, 0x2A, 0x0E, 0x00, 0x1D, 0xFF, 0x26, 0x44, 0x02, 0xBC, 0x40, 0x46, +- 0x27, 0x44, 0x07, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, +- 0x30, 0xF1, 0x81, 0x00, 0xFC, 0xB3, 0x32, 0x40, 0x01, 0x2A, 0x06, 0x00, 0x0A, 0xBB, 0x0F, 0xFC, +- 0xCB, 0xFE, 0xA3, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0x24, 0x44, 0x04, 0x26, 0x29, 0x00, 0x0F, 0xFC, +- 0x05, 0xFF, 0xDB, 0xF3, 0x28, 0x40, 0x80, 0x3A, 0x23, 0x00, 0x60, 0x40, 0x03, 0x3A, 0x20, 0x00, +- 0x32, 0xF2, 0x7F, 0xF1, 0x33, 0xF2, 0xD0, 0x80, 0x80, 0xF1, 0x1A, 0x02, 0xD0, 0x80, 0x34, 0xF2, +- 0x81, 0xF1, 0x16, 0x02, 0xD0, 0x80, 0x3C, 0x44, 0x13, 0x02, 0xAC, 0x86, 0xBB, 0xFE, 0x10, 0x03, +- 0x2A, 0xF2, 0x21, 0x46, 0x60, 0x40, 0x80, 0x3A, 0x0B, 0x00, 0x01, 0x64, 0x31, 0xFB, 0xC0, 0xFE, +- 0x00, 0x64, 0x32, 0xFB, 0x43, 0xFF, 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0x82, 0xFF, +- 0x30, 0xF1, 0x27, 0x44, 0x05, 0x22, 0x34, 0x00, 0xFA, 0xB4, 0x40, 0x47, 0x24, 0x44, 0x10, 0x2A, +- 0x2B, 0x00, 0x28, 0x40, 0xD4, 0x3A, 0x28, 0x00, 0x31, 0x40, 0x08, 0x26, 0x00, 0x7C, 0x29, 0x40, +- 0x50, 0x2B, 0x0D, 0x00, 0xEF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x31, 0x40, 0x08, 0x2A, +- 0x06, 0x00, 0x1C, 0x60, 0x11, 0xF3, 0xFF, 0xFF, 0xE0, 0x85, 0x2B, 0x44, 0x05, 0x05, 0x2B, 0x44, +- 0xFF, 0xA4, 0x01, 0xA4, 0x04, 0x24, 0x00, 0x64, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, 0x64, 0x44, +- 0xC4, 0x84, 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, 0x20, 0x29, +- 0x6D, 0xE2, 0xA5, 0x60, 0x7F, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x07, 0x00, +- 0x02, 0x2A, 0x05, 0x00, 0xFD, 0xB4, 0x40, 0x47, 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x05, 0x64, +- 0x3A, 0xDB, 0x28, 0x44, 0xA4, 0x3A, 0x07, 0x00, 0x01, 0x60, 0x02, 0x7C, 0x25, 0x44, 0x0A, 0x3A, +- 0x02, 0x00, 0x01, 0x60, 0x3A, 0x7C, 0x31, 0x40, 0x08, 0x26, 0x00, 0x7C, 0x29, 0x40, 0x50, 0x2B, +- 0x0D, 0x00, 0xEF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x31, 0x40, 0x08, 0x2A, 0x06, 0x00, +- 0x1C, 0x60, 0x11, 0xF3, 0xFF, 0xFF, 0xE0, 0x85, 0x2B, 0x44, 0x05, 0x05, 0x2B, 0x44, 0xFF, 0xA4, +- 0x01, 0xA4, 0x04, 0x24, 0x00, 0x64, 0xD0, 0x80, 0x70, 0x45, 0x02, 0x28, 0x64, 0x44, 0xC4, 0x84, +- 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x28, 0x40, 0xE4, 0x36, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, +- 0x01, 0x00, 0x20, 0x29, 0x6D, 0xE2, 0xA3, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x05, 0x22, +- 0x09, 0x00, 0xBA, 0xB4, 0x40, 0x47, 0x3C, 0x46, 0x02, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0xA3, 0x60, +- 0xF4, 0x78, 0xFF, 0xFF, 0x27, 0x44, 0x02, 0x2A, 0x06, 0x00, 0xFD, 0xB4, 0x40, 0x47, 0x06, 0x64, +- 0x31, 0xFB, 0xC0, 0xFE, 0xF4, 0x01, 0xF3, 0x0A, 0x7C, 0x50, 0x6D, 0xE2, 0xF0, 0x01, 0x72, 0x45, +- 0xDC, 0x84, 0xB2, 0xFB, 0x11, 0x64, 0x3A, 0xDB, 0xB3, 0xF3, 0x06, 0x04, 0xDC, 0x84, 0xB3, 0xFB, +- 0xB4, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB4, 0xFB, 0xA4, 0x60, 0x01, 0x78, 0xFF, 0xFF, 0x00, 0x61, +- 0x12, 0x64, 0x3A, 0xDB, 0x20, 0x60, 0x04, 0x63, 0xBD, 0xD3, 0x72, 0x45, 0x44, 0x8A, 0x02, 0x28, +- 0x03, 0x00, 0xE4, 0xE2, 0xDD, 0x81, 0x04, 0x00, 0x02, 0x28, 0x02, 0x00, 0xE4, 0xE2, 0xDD, 0x81, +- 0xBD, 0xD3, 0xB2, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, 0xC4, 0x84, +- 0x60, 0x55, 0x2A, 0x52, 0xE4, 0xE2, 0xB2, 0xFB, 0x02, 0x24, 0x01, 0xB9, 0xBD, 0xD3, 0xB3, 0xF1, +- 0x61, 0x45, 0xC0, 0x84, 0x00, 0x61, 0x02, 0x24, 0x01, 0xB9, 0xC4, 0x84, 0xB3, 0xFB, 0x02, 0x24, +- 0x01, 0xB9, 0xBD, 0xD3, 0xB4, 0xF1, 0x61, 0x45, 0xC0, 0x84, 0xC4, 0x84, 0xB4, 0xFB, 0xA5, 0x60, +- 0x14, 0x78, 0xFF, 0xFF, 0xB0, 0x60, 0x9E, 0x78, 0xFF, 0xFF, 0x47, 0xFF, 0x1B, 0x60, 0xEE, 0xF3, +- 0xFF, 0xFF, 0x04, 0x18, 0xAE, 0x4F, 0x08, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0xC8, 0x74, 0xCD, 0xE2, +- 0xAA, 0x60, 0xB9, 0x78, 0x00, 0x61, 0xA3, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0xAB, 0x60, 0xE8, 0x78, +- 0xFF, 0xFF, 0x21, 0x46, 0x5C, 0x44, 0x26, 0x44, 0x02, 0x26, 0x01, 0x00, 0x3E, 0x46, 0x09, 0xF2, +- 0x46, 0x41, 0x66, 0x40, 0xF3, 0x18, 0x40, 0x5E, 0xFD, 0xFB, 0x02, 0x64, 0x40, 0x46, 0x41, 0x5D, +- 0x00, 0x64, 0x31, 0xFA, 0x00, 0xF2, 0x46, 0x45, 0x87, 0xFC, 0xAC, 0xE2, 0x01, 0x64, 0x33, 0xFB, +- 0x32, 0x40, 0x01, 0x2A, 0x21, 0x00, 0x19, 0xF3, 0x01, 0x60, 0x1E, 0xE1, 0x1D, 0x18, 0x80, 0x64, +- 0x40, 0x49, 0x00, 0xE1, 0x19, 0xFF, 0x08, 0x64, 0x2A, 0xFA, 0x5A, 0xDA, 0x2C, 0xFA, 0x5A, 0xDA, +- 0x5A, 0xDA, 0xF1, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xF1, 0xFB, 0x72, 0x44, 0x24, 0xFA, 0xB2, 0xF3, +- 0x25, 0xFA, 0xA1, 0xFF, 0xFF, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, +- 0x7C, 0x4B, 0xA3, 0x60, 0xF4, 0x78, 0xFF, 0xFF, 0x01, 0xE1, 0x01, 0x60, 0x1A, 0xE1, 0x3F, 0x60, +- 0xCF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x2E, 0x44, 0x00, 0x36, 0x48, 0x00, 0x01, 0x3A, 0xE5, 0x00, +- 0x88, 0xFF, 0x40, 0x67, 0x29, 0x45, 0x34, 0x89, 0x04, 0x64, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, +- 0xA1, 0xFF, 0x6C, 0x45, 0x65, 0x44, 0x0F, 0xB4, 0x40, 0x45, 0x1C, 0xFA, 0x65, 0x44, 0x29, 0x41, +- 0xF9, 0x81, 0x52, 0x4A, 0x71, 0x89, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x83, 0x1D, 0xFC, +- 0x1B, 0xFC, 0x10, 0x60, 0x00, 0x65, 0x29, 0x44, 0x34, 0x89, 0x50, 0x4B, 0x67, 0x50, 0x69, 0xE2, +- 0xB6, 0xF1, 0xFC, 0xA3, 0xD3, 0x80, 0x43, 0x43, 0x03, 0x04, 0xAB, 0x60, 0xDE, 0x78, 0xFF, 0xFF, +- 0x09, 0x7C, 0xD3, 0x80, 0x9A, 0xFF, 0x03, 0x07, 0xAB, 0x60, 0xDE, 0x78, 0xFF, 0xFF, 0x25, 0x44, +- 0x01, 0x26, 0x0F, 0xAC, 0x26, 0x60, 0x4A, 0x65, 0x44, 0xD3, 0x12, 0x65, 0x45, 0x46, 0x60, 0x47, +- 0x40, 0x7F, 0x27, 0xFA, 0x8F, 0xFC, 0x18, 0x61, 0xEA, 0xF1, 0xA1, 0xFF, 0x6C, 0x44, 0xDC, 0x80, +- 0xFF, 0xFF, 0x21, 0x03, 0x50, 0xFE, 0xAC, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0xC8, 0x60, 0x0B, 0x7D, +- 0x08, 0x60, 0x00, 0x6B, 0xB5, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xAA, 0x74, 0xCD, 0xE2, 0x01, 0x64, +- 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0x01, 0x60, 0x08, 0xE1, 0x05, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x04, 0x25, 0x8B, 0x00, 0x6C, 0x44, 0x0A, 0x36, 0x07, 0x00, 0x14, 0x36, 0x05, 0x00, 0x37, 0x36, +- 0x03, 0x00, 0x6E, 0x36, 0x01, 0x00, 0x81, 0x00, 0x40, 0x45, 0x32, 0x74, 0xA1, 0xFF, 0x1C, 0xFA, +- 0x40, 0x4E, 0x8C, 0x44, 0x60, 0x43, 0x1D, 0xFA, 0x01, 0xE1, 0x20, 0x64, 0x3A, 0xDB, 0x2E, 0x44, +- 0x14, 0x36, 0x12, 0x00, 0x0A, 0x36, 0x0F, 0x00, 0x63, 0x45, 0xE3, 0x83, 0xE3, 0x83, 0xC7, 0x83, +- 0xE3, 0x83, 0xC7, 0x83, 0xFF, 0xFF, 0x37, 0x36, 0x05, 0x00, 0x6E, 0x36, 0x04, 0x00, 0xAC, 0x60, +- 0xBF, 0x78, 0xFF, 0xFF, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xEB, 0x83, 0xFF, 0xFF, 0x80, 0x27, +- 0xCF, 0x83, 0x1B, 0xFC, 0x01, 0x64, 0x51, 0xFB, 0xA1, 0xFF, 0x29, 0x41, 0xF9, 0x81, 0x52, 0x4A, +- 0x71, 0x89, 0x2E, 0x44, 0x27, 0xFA, 0xB6, 0xF1, 0xFC, 0xA3, 0xD3, 0x80, 0x43, 0x43, 0x03, 0x04, +- 0xAB, 0x60, 0xDE, 0x78, 0xFF, 0xFF, 0x9A, 0xFF, 0x54, 0x63, 0x12, 0x64, 0x40, 0x46, 0x8F, 0xFC, +- 0x18, 0x61, 0xEA, 0xF1, 0x50, 0xFE, 0x6C, 0x40, 0x9E, 0x15, 0x01, 0x60, 0x08, 0xE1, 0x80, 0xE1, +- 0x00, 0x64, 0x33, 0xFB, 0x29, 0x40, 0x50, 0x2B, 0x0F, 0x00, 0x2B, 0x44, 0x70, 0x45, 0xC4, 0x84, +- 0xFF, 0xFF, 0x04, 0x24, 0x00, 0xB4, 0x60, 0x50, 0x08, 0x28, 0x01, 0x00, 0x20, 0x29, 0x6D, 0xE2, +- 0xEF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x01, 0x60, 0x18, 0xE1, 0x01, 0x11, 0x12, 0x00, +- 0x29, 0x44, 0x20, 0xBC, 0x40, 0x49, 0x01, 0x64, 0x33, 0xFB, 0xB6, 0xFF, 0x00, 0xE1, 0x01, 0x60, +- 0x1A, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x40, 0xFC, 0x11, 0x01, 0x60, 0x18, 0xE1, 0xAE, 0x4F, +- 0xF7, 0xB4, 0xA0, 0x5E, 0xB5, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, +- 0x7C, 0x4B, 0x35, 0xE1, 0xAC, 0xE2, 0xAA, 0x60, 0x46, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0x7F, 0xF3, +- 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, 0x21, 0x64, 0x3A, 0xDB, 0xBD, 0x01, +- 0xAC, 0xE2, 0x01, 0x64, 0x33, 0xFB, 0x01, 0xE1, 0x3F, 0x60, 0xCF, 0x65, 0x29, 0x44, 0x24, 0x89, +- 0x2E, 0x44, 0x00, 0x36, 0x21, 0x00, 0x01, 0x3A, 0xF0, 0x01, 0x88, 0xFF, 0x40, 0x67, 0x29, 0x45, +- 0x34, 0x89, 0xA1, 0xFF, 0x6C, 0x45, 0x65, 0x44, 0x0F, 0xB4, 0x40, 0x45, 0x65, 0x44, 0x29, 0x41, +- 0xF9, 0x81, 0x52, 0x4A, 0x71, 0x89, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x83, 0x0E, 0x7C, +- 0xD3, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0xAB, 0x60, 0xDE, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0x6C, 0x44, +- 0xDC, 0x80, 0xFF, 0xFF, 0xD2, 0x03, 0x41, 0x00, 0xC8, 0x60, 0x0B, 0x7D, 0x08, 0x60, 0x00, 0x6B, +- 0xB5, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xAA, 0x74, 0xCD, 0xE2, 0x01, 0x60, 0x08, 0xE1, 0x05, 0xE1, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x04, 0x25, 0xC1, 0x01, 0x6C, 0x44, 0x0A, 0x36, 0x07, 0x00, 0x14, 0x36, +- 0x05, 0x00, 0x37, 0x36, 0x03, 0x00, 0x6E, 0x36, 0x01, 0x00, 0xB7, 0x01, 0x40, 0x45, 0x32, 0x74, +- 0xA1, 0xFF, 0x40, 0x4E, 0x8C, 0x44, 0x60, 0x43, 0x01, 0xE1, 0x20, 0x64, 0x3A, 0xDB, 0x2E, 0x44, +- 0x14, 0x36, 0x09, 0x00, 0x0A, 0x36, 0x07, 0x00, 0x37, 0x36, 0x05, 0x00, 0x6E, 0x36, 0x03, 0x00, +- 0xAC, 0x60, 0xBF, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x51, 0xFB, 0xA1, 0xFF, 0x29, 0x41, 0xF9, 0x81, +- 0x52, 0x4A, 0x71, 0x89, 0x0E, 0x7C, 0xD3, 0x80, 0x43, 0x43, 0x03, 0x03, 0xAB, 0x60, 0xDE, 0x78, +- 0xFF, 0xFF, 0x6C, 0x40, 0xFF, 0xFF, 0x01, 0x15, 0x90, 0x01, 0x12, 0x64, 0x40, 0x46, 0xEA, 0xF1, +- 0x50, 0xFE, 0xA1, 0xFF, 0x12, 0x61, 0x8C, 0x44, 0xEB, 0xF0, 0x40, 0x48, 0x8C, 0x44, 0x30, 0xFB, +- 0x04, 0x61, 0x50, 0xFE, 0x8C, 0x44, 0xD0, 0x80, 0x8C, 0x44, 0xD4, 0x80, 0x8C, 0x44, 0xEC, 0xF1, +- 0x00, 0x65, 0xD0, 0x80, 0x28, 0x44, 0x01, 0x0C, 0x13, 0x00, 0x10, 0x65, 0x60, 0x40, 0xC4, 0x36, +- 0x04, 0x00, 0xD4, 0x3A, 0x0D, 0x00, 0x27, 0x40, 0x40, 0x26, 0x30, 0x65, 0x35, 0x84, 0xA1, 0xFF, +- 0x8C, 0x44, 0x47, 0xFF, 0x50, 0x4B, 0x67, 0x50, 0x69, 0xE2, 0x6A, 0x44, 0x40, 0x2B, 0x09, 0x15, +- 0x2C, 0x60, 0xEC, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x2A, 0x64, 0x3A, 0xDB, +- 0x1C, 0x01, 0x29, 0x40, 0x10, 0x26, 0x02, 0x00, 0x04, 0x74, 0xCD, 0xE2, 0x8C, 0x44, 0xB6, 0xFF, +- 0xB7, 0xFF, 0x01, 0x60, 0x18, 0xE1, 0x05, 0xE1, 0x00, 0x64, 0x33, 0xFB, 0xA1, 0xFF, 0x6C, 0x44, +- 0xA1, 0xFF, 0x6C, 0x44, 0x29, 0x40, 0x40, 0x2B, 0x03, 0x00, 0xB6, 0xFF, 0xA1, 0xFF, 0x6C, 0x44, +- 0xA1, 0xFF, 0x02, 0x74, 0x29, 0x44, 0x40, 0x27, 0x05, 0x74, 0xCD, 0xE2, 0xA1, 0xFF, 0xCB, 0xF3, +- 0xC4, 0xE2, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0xDC, 0x84, 0xE0, 0x94, 0x26, 0x44, 0x84, 0xBC, +- 0x40, 0x46, 0x23, 0x64, 0x3A, 0xDB, 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, +- 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0xA9, 0x60, 0x88, 0x78, 0xFF, 0xFF, 0x29, 0x64, +- 0x3A, 0xDB, 0xA2, 0xFC, 0x32, 0x40, 0x01, 0x2A, 0xB9, 0x00, 0x01, 0x60, 0x1A, 0xE1, 0x23, 0x43, +- 0xA1, 0xFF, 0xEC, 0x44, 0x2A, 0xFA, 0x40, 0x48, 0xA1, 0xFF, 0x7A, 0xDC, 0x7E, 0x36, 0x04, 0xA2, +- 0xFC, 0x1C, 0x03, 0x1D, 0x00, 0x64, 0x3F, 0xFA, 0x2E, 0x00, 0x03, 0x2B, 0x04, 0x00, 0xA1, 0xFF, +- 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x8F, 0xB0, 0x88, 0x3A, 0x03, 0x00, 0x70, 0x62, 0xA1, 0xFF, +- 0x7A, 0xDC, 0x28, 0x40, 0x40, 0x2B, 0x06, 0x00, 0x72, 0x62, 0xA1, 0xFF, 0x7A, 0xDC, 0x7A, 0xDC, +- 0x7A, 0xDC, 0x7A, 0xDC, 0x3F, 0xFC, 0x00, 0xF4, 0x10, 0x62, 0x6E, 0x61, 0xA1, 0xFF, 0x05, 0x1D, +- 0x12, 0x1E, 0x0C, 0x00, 0x00, 0xF4, 0x7C, 0x61, 0x02, 0x62, 0x7A, 0xDC, 0x63, 0x40, 0xFD, 0x1C, +- 0xF9, 0x1D, 0xFF, 0xB1, 0x08, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xB6, 0xFF, 0xB7, 0xFF, +- 0xA1, 0xFF, 0x6C, 0x44, 0x5A, 0xDA, 0x98, 0xFF, 0xA1, 0xFF, 0x6C, 0x40, 0xA1, 0xFF, 0x47, 0xFF, +- 0x7C, 0x44, 0x33, 0xFB, 0x26, 0x44, 0xFD, 0xB4, 0x84, 0xBC, 0x01, 0x15, 0x7F, 0xB4, 0x40, 0x46, +- 0x6C, 0x40, 0xB6, 0xFF, 0xB7, 0xFF, 0xA1, 0xFF, 0x6C, 0x45, 0xA1, 0xFF, 0x7F, 0x60, 0x7F, 0x7C, +- 0x6C, 0x44, 0xA0, 0x84, 0x15, 0xA7, 0x15, 0xA4, 0x21, 0x46, 0x26, 0xFA, 0x29, 0x40, 0x40, 0x2B, +- 0x07, 0x00, 0xB6, 0xFF, 0x40, 0x60, 0x00, 0x65, 0xA1, 0xFF, 0x6C, 0x44, 0x1A, 0xFA, 0x09, 0x00, +- 0x65, 0x44, 0x0F, 0xB4, 0x06, 0xA8, 0x80, 0x60, 0x00, 0x65, 0x08, 0x28, 0x7C, 0x45, 0x29, 0x44, +- 0x34, 0x89, 0x27, 0xF0, 0x65, 0x44, 0x64, 0x5E, 0x27, 0xFA, 0x81, 0xE1, 0x01, 0x60, 0x18, 0xE1, +- 0x01, 0x11, 0x12, 0x00, 0x29, 0x44, 0x20, 0xBC, 0x40, 0x49, 0x01, 0x64, 0x33, 0xFB, 0xB6, 0xFF, +- 0x00, 0xE1, 0x01, 0x60, 0x1A, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x40, 0xFC, 0x11, 0x01, 0x60, +- 0x18, 0xE1, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0x00, 0x70, 0x00, 0x64, 0x40, 0x4B, 0x21, 0x46, +- 0xB5, 0xFF, 0xBC, 0xFF, 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, +- 0x7C, 0x4B, 0x28, 0x44, 0x04, 0x27, 0x09, 0x00, 0xD4, 0x36, 0x04, 0x00, 0x0C, 0x22, 0x02, 0x00, +- 0x0C, 0x3A, 0x03, 0x00, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, 0x2A, 0x44, 0x72, 0x45, 0x24, 0xFA, +- 0xB2, 0xF3, 0x06, 0x04, 0xE4, 0xE2, 0xDC, 0x9C, 0x29, 0x40, 0x01, 0x26, 0x64, 0x44, 0xB2, 0xF9, +- 0x25, 0xFA, 0xB3, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB3, 0xFB, 0x28, 0xFA, 0xB4, 0xF3, 0x02, 0x04, +- 0xDC, 0x84, 0xB4, 0xFB, 0x29, 0xFA, 0xA9, 0x60, 0x88, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0x19, 0x60, +- 0xA3, 0xF3, 0x12, 0x61, 0x60, 0x40, 0x01, 0x2A, 0x08, 0x00, 0x00, 0x64, 0x3B, 0xFA, 0xBF, 0x60, +- 0xFF, 0x65, 0x8C, 0x44, 0x3D, 0xFA, 0xA4, 0x84, 0x01, 0x00, 0x8C, 0x44, 0xEB, 0xF0, 0x2A, 0xFA, +- 0x40, 0x48, 0x04, 0x26, 0x48, 0x00, 0xA1, 0xFF, 0x8C, 0x44, 0x5A, 0xDA, 0x30, 0xFB, 0x6C, 0x44, +- 0x2C, 0xFA, 0xFF, 0xFF, 0x01, 0x26, 0x2B, 0x00, 0xD0, 0x80, 0xA1, 0xFF, 0x8C, 0x44, 0x6C, 0x5C, +- 0x00, 0xE1, 0xF2, 0xFE, 0x2D, 0xFA, 0xEC, 0xF3, 0xD4, 0x80, 0xD0, 0x80, 0x2E, 0xF8, 0x24, 0x44, +- 0x16, 0x0C, 0x32, 0x40, 0x02, 0x2A, 0x07, 0x00, 0x28, 0x42, 0x0C, 0xB2, 0x08, 0x3A, 0x03, 0x00, +- 0x10, 0xBC, 0x40, 0x44, 0x61, 0x00, 0x04, 0x0A, 0xA1, 0xFF, 0xAB, 0x60, 0xE7, 0x78, 0xFF, 0xFF, +- 0x11, 0xBC, 0x40, 0x44, 0x28, 0x45, 0xBF, 0x60, 0xFF, 0x64, 0x24, 0x88, 0x55, 0x00, 0x30, 0xBC, +- 0x40, 0x44, 0x22, 0xF0, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x4D, 0x00, 0x20, 0xB9, +- 0x5C, 0x8E, 0xA1, 0xFF, 0x8C, 0x44, 0x2D, 0xFA, 0xDC, 0x9C, 0x6C, 0x44, 0x00, 0xE1, 0xF2, 0xFE, +- 0x2E, 0xFA, 0x08, 0x28, 0x44, 0x4E, 0xDC, 0x84, 0x2E, 0x5C, 0xB0, 0x84, 0xEF, 0xB1, 0x08, 0x24, +- 0x40, 0xB9, 0x41, 0x46, 0x39, 0x00, 0x23, 0x41, 0x13, 0x64, 0x51, 0x90, 0x56, 0x63, 0x03, 0x04, +- 0xAB, 0x60, 0xDE, 0x78, 0xFF, 0xFF, 0x8C, 0x44, 0x04, 0x61, 0x2B, 0xFA, 0x50, 0xFE, 0x80, 0x27, +- 0x00, 0x64, 0x30, 0xFB, 0x8C, 0x44, 0x2C, 0xFA, 0xD0, 0x80, 0x8C, 0x44, 0x2D, 0xFA, 0xD4, 0x80, +- 0x00, 0x65, 0x8C, 0x44, 0xEC, 0xF1, 0x2E, 0xFA, 0xD0, 0x80, 0x28, 0x44, 0x03, 0x0C, 0xA0, 0x2A, +- 0x0A, 0x00, 0x11, 0x00, 0x10, 0x65, 0x60, 0x40, 0xC4, 0x36, 0x04, 0x00, 0xD4, 0x3A, 0x08, 0x00, +- 0x27, 0x40, 0x40, 0x26, 0x30, 0x65, 0x00, 0x64, 0x3F, 0xFA, 0x46, 0x4E, 0x35, 0x84, 0x64, 0x00, +- 0x40, 0x26, 0xF9, 0x01, 0x30, 0x65, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x04, 0x61, 0xF3, 0x01, +- 0xA1, 0xFF, 0xAB, 0x60, 0xA5, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xFE, 0x65, 0x23, 0x43, 0xE8, 0xA3, +- 0x80, 0x27, 0xF6, 0x01, 0x20, 0xE6, 0x08, 0x60, 0x00, 0xEB, 0x28, 0x44, 0x03, 0x2B, 0x05, 0x00, +- 0x6A, 0x62, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x28, 0x44, 0x8F, 0xB0, 0x88, 0x3A, 0x03, 0x00, +- 0x70, 0x62, 0x7A, 0xDC, 0x28, 0x44, 0x40, 0x2B, 0x0D, 0x00, 0x72, 0x62, 0x7A, 0xDC, 0xA1, 0xFF, +- 0x6C, 0x5C, 0x5A, 0xD8, 0xE4, 0x40, 0x20, 0x2B, 0x03, 0x00, 0x7A, 0xDC, 0x7A, 0xDC, 0xF8, 0xA3, +- 0x25, 0xFF, 0xB0, 0xFF, 0x3F, 0xFC, 0x00, 0xF4, 0x10, 0x62, 0x10, 0x61, 0x57, 0x90, 0x6C, 0x61, +- 0xA1, 0xFF, 0x09, 0x07, 0x02, 0x1D, 0x28, 0x1E, 0x1F, 0x00, 0xCB, 0x83, 0x7A, 0xDC, 0xFE, 0x1C, +- 0xD9, 0x81, 0x22, 0x1E, 0x19, 0x00, 0xCB, 0x83, 0x0E, 0xA3, 0xA7, 0x84, 0xF2, 0xA3, 0x7A, 0xDC, +- 0xFE, 0x1C, 0x03, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, 0x0A, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xA7, 0x84, +- 0x7A, 0x61, 0x7A, 0xDC, 0xFE, 0x1C, 0xF9, 0x1D, 0x7C, 0xA8, 0xD9, 0x81, 0xF6, 0x03, 0xFF, 0xB1, +- 0x0B, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0x02, 0x62, 0xA1, 0xFF, 0xFF, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, +- 0x6C, 0x44, 0x5A, 0xDA, 0xCD, 0x81, 0x64, 0x40, 0x46, 0x45, 0x28, 0x44, 0x40, 0x2B, 0x0E, 0x00, +- 0x64, 0x40, 0x20, 0x2B, 0x0B, 0x00, 0x01, 0xA2, 0x62, 0x44, 0x46, 0x45, 0x21, 0x46, 0x00, 0xF4, +- 0x02, 0x62, 0x9A, 0xFF, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x7A, 0xDC, 0x01, 0x60, 0x18, 0xE1, +- 0x24, 0x76, 0xAD, 0xE2, 0x41, 0xE1, 0x98, 0xFF, 0x00, 0xE6, 0x01, 0xF2, 0x61, 0x45, 0xD4, 0x9E, +- 0x21, 0x46, 0x16, 0xFA, 0x25, 0x44, 0x06, 0xFA, 0xA1, 0xFF, 0x8C, 0x44, 0xA1, 0xFF, 0x47, 0xFF, +- 0x29, 0x40, 0x50, 0x2B, 0x06, 0x00, 0x2B, 0x44, 0x1C, 0x60, 0x11, 0xFB, 0x70, 0x45, 0x44, 0x8B, +- 0x01, 0x00, 0x50, 0x4B, 0x67, 0x50, 0x69, 0xE2, 0x25, 0x46, 0x01, 0xF2, 0x61, 0x45, 0xD4, 0x9E, +- 0x21, 0x46, 0x16, 0xFA, 0x25, 0x45, 0x86, 0xF8, 0xFF, 0xFF, 0x6A, 0x44, 0x40, 0x2B, 0x03, 0x15, +- 0xAF, 0x60, 0xF3, 0x78, 0xFF, 0xFF, 0x29, 0x40, 0x10, 0x26, 0x04, 0x00, 0x04, 0x74, 0xCD, 0xE2, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x6C, 0x44, 0xB6, 0xFF, 0xB7, 0xFF, 0xC4, 0xE2, 0x01, 0x60, 0x18, 0xE1, +- 0x05, 0x76, 0xAD, 0xE2, 0x41, 0xE1, 0xA1, 0xFF, 0x6C, 0x45, 0xA1, 0xFF, 0x65, 0x41, 0x7F, 0x60, +- 0x7F, 0x7C, 0x6C, 0x44, 0xA0, 0x84, 0x15, 0xA7, 0x15, 0xA4, 0x21, 0x46, 0x26, 0xFA, 0x22, 0x46, +- 0x10, 0xFA, 0x21, 0x46, 0x29, 0x40, 0x40, 0x2B, 0x07, 0x00, 0xB6, 0xFF, 0xA1, 0xFF, 0x40, 0x60, +- 0x00, 0x65, 0x6C, 0x44, 0x1A, 0xFA, 0x09, 0x00, 0x65, 0x44, 0x0F, 0xB4, 0x06, 0xA8, 0x80, 0x60, +- 0x00, 0x65, 0x08, 0x28, 0x7C, 0x45, 0x29, 0x44, 0x34, 0x89, 0x00, 0x64, 0x33, 0xFB, 0x40, 0x21, +- 0x00, 0x00, 0xAC, 0xE2, 0x05, 0xE1, 0x27, 0xF0, 0x65, 0x44, 0x64, 0x5E, 0x27, 0xFA, 0x28, 0x44, +- 0x8F, 0xB0, 0x88, 0x3A, 0x09, 0x00, 0x39, 0xF2, 0xFF, 0xFF, 0x60, 0xB0, 0x20, 0x3A, 0x04, 0x00, +- 0x24, 0x44, 0xFF, 0x60, 0xDF, 0xB4, 0x40, 0x44, 0x28, 0x40, 0x03, 0x26, 0xE2, 0x00, 0x31, 0x40, +- 0x20, 0x2A, 0x03, 0x00, 0x28, 0x40, 0x50, 0x3A, 0xDC, 0x00, 0x24, 0x44, 0x20, 0x2A, 0xD9, 0x00, +- 0x29, 0x40, 0x50, 0x2B, 0x0D, 0x00, 0xEF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x31, 0x40, +- 0x08, 0x2A, 0x06, 0x00, 0x1C, 0x60, 0x11, 0xF3, 0xFF, 0xFF, 0xE0, 0x85, 0x2B, 0x44, 0x06, 0x05, +- 0x2B, 0x44, 0xFF, 0xA4, 0x01, 0xA4, 0x04, 0x24, 0x00, 0x64, 0x40, 0x4B, 0xAC, 0x80, 0x28, 0x40, +- 0xB4, 0x3A, 0x03, 0x00, 0x02, 0x03, 0x30, 0xFB, 0xBC, 0x00, 0x28, 0x44, 0xBF, 0x60, 0xFF, 0x65, +- 0xA4, 0x84, 0x40, 0x48, 0x2B, 0x50, 0xA1, 0xFF, 0xFF, 0xFF, 0x01, 0x60, 0x08, 0xE1, 0x1C, 0xF2, +- 0xC4, 0xE2, 0x40, 0x45, 0x28, 0x40, 0xC4, 0x36, 0x9C, 0x00, 0x29, 0x40, 0x40, 0x2B, 0x48, 0x00, +- 0x32, 0x60, 0xFA, 0x63, 0x60, 0x40, 0x0B, 0x36, 0x20, 0x00, 0x0F, 0x36, 0x1B, 0x00, 0x0A, 0x36, +- 0x16, 0x00, 0x0E, 0x36, 0x11, 0x00, 0x09, 0x36, 0x0C, 0x00, 0x0D, 0x36, 0x07, 0x00, 0x08, 0x36, +- 0x02, 0x00, 0xA3, 0xD3, 0x15, 0x00, 0x02, 0xA3, 0xA3, 0xD3, 0x12, 0x00, 0x04, 0xA3, 0xA3, 0xD3, +- 0x0F, 0x00, 0x06, 0xA3, 0xA3, 0xD3, 0x0C, 0x00, 0x08, 0xA3, 0xA3, 0xD3, 0x09, 0x00, 0x0A, 0xA3, +- 0xA3, 0xD3, 0x06, 0x00, 0x0C, 0xA3, 0xA3, 0xD3, 0x03, 0x00, 0x0E, 0xA3, 0xA3, 0xD3, 0xFF, 0xFF, +- 0x2C, 0x60, 0x7C, 0x63, 0x60, 0x40, 0x0C, 0x36, 0x19, 0x00, 0x08, 0x36, 0x15, 0x00, 0x0D, 0x36, +- 0x11, 0x00, 0x09, 0x36, 0x0D, 0x00, 0x0E, 0x36, 0x09, 0x00, 0x0A, 0x36, 0x05, 0x00, 0x0F, 0x36, +- 0x01, 0x00, 0x39, 0x00, 0x02, 0xA3, 0x37, 0x00, 0x04, 0xA3, 0x35, 0x00, 0x06, 0xA3, 0x33, 0x00, +- 0x08, 0xA3, 0x31, 0x00, 0x0A, 0xA3, 0x2F, 0x00, 0x0C, 0xA3, 0x2D, 0x00, 0x0E, 0xA3, 0x2B, 0x00, +- 0x33, 0x60, 0x0A, 0x63, 0x25, 0x44, 0x0A, 0x36, 0x0C, 0x00, 0x14, 0x36, 0x07, 0x00, 0x37, 0x36, +- 0x02, 0x00, 0xA3, 0xD3, 0x09, 0x00, 0x02, 0xA3, 0xA3, 0xD3, 0x06, 0x00, 0x04, 0xA3, 0xA3, 0xD3, +- 0x03, 0x00, 0x06, 0xA3, 0xA3, 0xD3, 0xFF, 0xFF, 0x40, 0x45, 0x0A, 0x36, 0x0D, 0x00, 0x14, 0x36, +- 0x38, 0x64, 0x37, 0x3A, 0x03, 0x00, 0x04, 0x7F, 0x40, 0x45, 0x15, 0x64, 0x6E, 0x3A, 0x09, 0x00, +- 0x84, 0x7F, 0x40, 0x45, 0x0B, 0x64, 0x05, 0x00, 0x29, 0x44, 0x7F, 0x60, 0xFF, 0xB4, 0x40, 0x49, +- 0x70, 0x64, 0x40, 0x4D, 0x02, 0x00, 0x40, 0x45, 0x0A, 0x00, 0x2C, 0x60, 0x74, 0x63, 0x0A, 0x36, +- 0x06, 0x00, 0x14, 0x36, 0x02, 0xA3, 0x37, 0x36, 0x04, 0xA3, 0x6E, 0x36, 0x06, 0xA3, 0x28, 0xA3, +- 0xA3, 0xD1, 0xD8, 0xA3, 0x19, 0x60, 0x55, 0xF9, 0x39, 0xF1, 0xA3, 0xD1, 0x64, 0x41, 0x64, 0x5E, +- 0x60, 0x45, 0x64, 0x47, 0x1F, 0xB4, 0x54, 0x94, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, +- 0x01, 0x04, 0x1F, 0x64, 0x60, 0x47, 0xB4, 0x85, 0x29, 0x44, 0xC0, 0x60, 0x00, 0xB4, 0xB4, 0x84, +- 0x1F, 0xFA, 0xB5, 0xFF, 0xA1, 0xFF, 0xCB, 0xF3, 0xC4, 0xE2, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, +- 0xDC, 0x84, 0xE0, 0x94, 0xFF, 0x60, 0xCF, 0x65, 0x29, 0x44, 0x24, 0x89, 0xA5, 0x60, 0x88, 0x78, +- 0x04, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0xC4, 0xE2, 0xA1, 0xFF, 0xFF, 0x60, 0xCF, 0x65, 0x29, 0x44, +- 0x24, 0x89, 0xCB, 0xF3, 0xC4, 0xE2, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0xDC, 0x84, 0xE0, 0x94, +- 0x26, 0x44, 0x84, 0xBC, 0x24, 0x40, 0x0C, 0x22, 0xFD, 0xB4, 0x40, 0x46, 0x23, 0x64, 0x3A, 0xDB, +- 0xAD, 0x60, 0x4F, 0x78, 0xFF, 0xFF, 0x27, 0x40, 0x26, 0x22, 0x05, 0x00, 0xF8, 0xB4, 0x40, 0x47, +- 0x06, 0x64, 0x31, 0xFB, 0xC0, 0xFE, 0x29, 0x40, 0x10, 0x26, 0x02, 0x00, 0x04, 0x74, 0xCD, 0xE2, +- 0x01, 0x60, 0x18, 0xE1, 0x01, 0x60, 0x18, 0xE1, 0x01, 0x11, 0x12, 0x00, 0x29, 0x44, 0x20, 0xBC, +- 0x40, 0x49, 0x01, 0x64, 0x33, 0xFB, 0xB6, 0xFF, 0x00, 0xE1, 0x01, 0x60, 0x1A, 0xE1, 0xA1, 0xFF, +- 0xFF, 0xFF, 0x6C, 0x40, 0xFC, 0x11, 0x01, 0x60, 0x18, 0xE1, 0xAE, 0x4F, 0xF7, 0xB4, 0xA0, 0x5E, +- 0xB5, 0xFF, 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, +- 0x29, 0x40, 0x50, 0x2B, 0x1B, 0x00, 0x31, 0x40, 0x08, 0x2A, 0x0D, 0x00, 0x1C, 0x60, 0x11, 0xF3, +- 0xFF, 0xFF, 0xE0, 0x85, 0x2B, 0x44, 0x07, 0x04, 0x70, 0x45, 0xC4, 0x84, 0xEF, 0x60, 0xFF, 0x65, +- 0x29, 0x44, 0x24, 0x89, 0x11, 0x00, 0x2B, 0x44, 0x70, 0x45, 0xC4, 0x84, 0xFF, 0xFF, 0x04, 0x24, +- 0x00, 0xB4, 0x40, 0x4B, 0xEF, 0x60, 0xFF, 0x65, 0x29, 0x44, 0x24, 0x89, 0x37, 0xF3, 0x2B, 0x45, +- 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x28, 0x65, 0x44, 0x60, 0x50, 0xA0, 0x4C, 0x20, 0xBC, 0xFF, 0xB4, +- 0xA0, 0x51, 0x00, 0x60, 0x2E, 0x7C, 0x74, 0x44, 0xC0, 0x94, 0x32, 0x40, 0x02, 0x2A, 0x19, 0x00, +- 0x28, 0x44, 0xA4, 0x36, 0x03, 0x00, 0x0C, 0xB4, 0x04, 0x36, 0x13, 0x00, 0x26, 0x43, 0xFD, 0xB3, +- 0x04, 0xBB, 0x43, 0x46, 0x01, 0x2A, 0x03, 0x00, 0x28, 0x47, 0x40, 0xBF, 0x40, 0x48, 0x0A, 0xBB, +- 0x0F, 0xFC, 0x50, 0x4B, 0x67, 0x50, 0x00, 0x64, 0x30, 0xFB, 0x05, 0xFF, 0xAD, 0x60, 0x4F, 0x78, +- 0xFF, 0xFF, 0x24, 0x64, 0x3A, 0xDB, 0x28, 0x44, 0x04, 0x2A, 0x03, 0x00, 0xA3, 0x60, 0xE7, 0x78, +- 0xFF, 0xFF, 0x32, 0x40, 0x04, 0x2A, 0x1C, 0x00, 0x28, 0x44, 0x0C, 0xB0, 0x08, 0x3A, 0x18, 0x00, +- 0x2C, 0xF0, 0x22, 0xF0, 0x64, 0x40, 0x01, 0x26, 0x0B, 0x00, 0x64, 0x40, 0x40, 0x2B, 0x10, 0x00, +- 0x8F, 0xB0, 0x88, 0x3A, 0x0D, 0x00, 0x39, 0xF2, 0xFF, 0xFF, 0x60, 0xB0, 0x20, 0x3A, 0x08, 0x00, +- 0x26, 0x44, 0xFD, 0xB4, 0x04, 0xBC, 0x40, 0x46, 0xFC, 0xB4, 0x0F, 0xFA, 0x05, 0xFF, 0x01, 0x00, +- 0x1D, 0xFF, 0x01, 0xE2, 0x26, 0x40, 0x10, 0x2A, 0x06, 0x00, 0x2C, 0x60, 0xEA, 0x64, 0xF1, 0x60, +- 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0xA3, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0x03, 0x0A, 0xA3, 0x60, +- 0xF4, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x51, 0xFB, 0x1B, 0x60, 0xEE, 0xF3, 0xFF, 0xFF, 0x04, 0x18, +- 0xAE, 0x4F, 0x08, 0xBC, 0x00, 0x7F, 0xA0, 0x5E, 0xE1, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, +- 0x54, 0x62, 0x22, 0x46, 0xA2, 0xD0, 0x16, 0x63, 0x7C, 0x41, 0x44, 0x48, 0x80, 0x36, 0x04, 0x61, +- 0x28, 0x40, 0x50, 0x36, 0x04, 0x61, 0x41, 0x4E, 0x28, 0x44, 0xA4, 0x36, 0x0E, 0x63, 0x9A, 0xFF, +- 0xA1, 0xFF, 0x19, 0x60, 0xA3, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x06, 0x00, 0x3D, 0xF2, +- 0xAA, 0xF0, 0xFF, 0xFF, 0xB4, 0x84, 0x08, 0x36, 0x2A, 0xFA, 0x12, 0x74, 0xCD, 0xE2, 0x54, 0x62, +- 0xA2, 0xD2, 0xFF, 0xFF, 0x6A, 0x40, 0x80, 0x4E, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, +- 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, +- 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0xFF, 0xFF, 0x01, 0x1D, 0xB2, 0x00, 0x7A, 0xD4, 0x12, 0x74, +- 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x28, 0x40, 0x03, 0x2B, +- 0x06, 0x00, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x70, 0x62, +- 0x28, 0x44, 0x8F, 0xB0, 0x88, 0x3A, 0x02, 0x00, 0x7A, 0xD4, 0x12, 0x74, 0x28, 0x40, 0x40, 0x2B, +- 0x16, 0x00, 0x72, 0x62, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD2, 0x12, 0x74, 0x80, 0x4C, 0x20, 0x2B, +- 0x05, 0x00, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x22, 0xF2, 0xFF, 0xFF, +- 0x60, 0x40, 0x10, 0x26, 0x04, 0x00, 0x26, 0x26, 0x4D, 0x00, 0x26, 0x27, 0x4B, 0x00, 0x23, 0x43, +- 0xFF, 0xFF, 0x06, 0x1D, 0x2E, 0x1E, 0x00, 0x00, 0x03, 0xF0, 0x04, 0xF4, 0x64, 0x42, 0x3D, 0x00, +- 0x2E, 0x40, 0x04, 0x2A, 0x27, 0x00, 0xA1, 0xFF, 0x02, 0xFE, 0x10, 0x25, 0x42, 0xFE, 0x12, 0x74, +- 0x72, 0x45, 0x65, 0x4C, 0xB2, 0xF3, 0x03, 0x04, 0xE4, 0xE2, 0xDC, 0x84, 0xB2, 0xFB, 0xA1, 0xFF, +- 0x12, 0x74, 0x80, 0x4C, 0x12, 0x74, 0xB3, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB3, 0xFB, 0x80, 0x4C, +- 0x12, 0x74, 0xB4, 0xF3, 0x02, 0x04, 0xDC, 0x84, 0xB4, 0xFB, 0x80, 0x4C, 0x12, 0x74, 0x5C, 0x4E, +- 0xF8, 0xA3, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, 0xFF, 0xB1, 0xF8, 0xA1, 0x06, 0xA4, 0x60, 0x42, +- 0x0A, 0x00, 0x4E, 0x00, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, 0xC8, 0x82, 0xFF, 0xB1, 0x03, 0x00, +- 0x00, 0xF4, 0x81, 0xF2, 0xFF, 0xB1, 0x7A, 0xD4, 0x12, 0x74, 0xFD, 0x1C, 0xF9, 0x1D, 0xFF, 0xB1, +- 0x1B, 0x1E, 0x02, 0x02, 0x00, 0xF4, 0xDA, 0x82, 0xDA, 0x82, 0xA2, 0xD2, 0xA1, 0xFF, 0x09, 0x74, +- 0x60, 0x4D, 0x12, 0x00, 0x03, 0xF2, 0x9A, 0xF2, 0x04, 0xF4, 0x23, 0x43, 0xA1, 0xFF, 0x12, 0x74, +- 0xA0, 0xD2, 0xFE, 0xA1, 0xCB, 0x83, 0x60, 0x4E, 0xAF, 0x83, 0x03, 0x1D, 0x05, 0x03, 0x12, 0x74, +- 0xEB, 0x01, 0xA1, 0xFF, 0x12, 0x74, 0xDF, 0x01, 0x12, 0x74, 0xDA, 0x83, 0x66, 0x44, 0x22, 0x46, +- 0x0C, 0xFA, 0x22, 0xF2, 0x0B, 0xFC, 0x28, 0x40, 0x40, 0x2B, 0x1A, 0x00, 0x10, 0x26, 0x04, 0x00, +- 0x26, 0x26, 0x0F, 0x00, 0x26, 0x27, 0x0D, 0x00, 0x00, 0xF4, 0x02, 0x62, 0xA1, 0xFF, 0x12, 0x74, +- 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, 0x7A, 0xD4, 0x12, 0x74, +- 0x07, 0x00, 0xA1, 0xFF, 0x12, 0x74, 0x9C, 0x4E, 0x12, 0x74, 0x9C, 0x4C, 0x12, 0x74, 0x00, 0x00, +- 0x88, 0xFF, 0xA1, 0xFF, 0xB2, 0x60, 0x58, 0x4F, 0x2D, 0x78, 0xFF, 0xFF, 0x01, 0x60, 0x18, 0xE1, +- 0x78, 0x44, 0x02, 0xA4, 0x35, 0xFB, 0xCC, 0x00, 0x29, 0x44, 0xF7, 0xB4, 0x40, 0x49, 0x34, 0x64, +- 0x3A, 0xDB, 0x44, 0xE1, 0xA5, 0x60, 0x54, 0x78, 0xFF, 0xFF, 0x00, 0x6B, 0xBC, 0xFF, 0x15, 0xF3, +- 0xFF, 0xFF, 0xDC, 0x84, 0x15, 0xFB, 0x78, 0x5C, 0x07, 0x00, 0x78, 0x5C, 0x2F, 0x00, 0x62, 0xFF, +- 0xFF, 0xFF, 0xA1, 0xFF, 0x98, 0xFF, 0x80, 0x3E, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, 0x84, 0xE7, +- 0xA1, 0xF3, 0x40, 0x60, 0x60, 0x40, 0x01, 0x23, 0x48, 0x60, 0x5E, 0x65, 0x80, 0x60, 0x00, 0x6A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, +- 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x80, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x01, 0x6A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x64, 0x58, 0xFF, 0xFF, 0x80, 0x60, 0x01, 0xE0, +- 0xD5, 0x60, 0x84, 0xE7, 0xA1, 0xF3, 0x7C, 0x45, 0x60, 0x40, 0x01, 0x23, 0x02, 0x65, 0x8C, 0x60, +- 0x48, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x00, 0x60, 0x7F, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x48, 0x60, 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x40, 0x60, 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x8C, 0x60, 0x48, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, +- 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x64, 0x58, 0xFF, 0xFF, 0x12, 0x74, 0x6A, 0x40, 0x87, 0x4F, +- 0x12, 0x74, 0x87, 0x4C, 0x12, 0x74, 0x29, 0x40, 0x40, 0x2B, 0x08, 0x00, 0x0A, 0x64, 0x89, 0xFF, +- 0x60, 0x54, 0x88, 0xFF, 0x87, 0x4D, 0x12, 0x74, 0x87, 0x4D, 0x09, 0x00, 0x03, 0x64, 0x89, 0xFF, +- 0x60, 0x54, 0x88, 0xFF, 0x87, 0x4F, 0x12, 0x74, 0x87, 0x4D, 0x12, 0x74, 0x87, 0x4D, 0x7C, 0x44, +- 0x01, 0x08, 0x01, 0x00, 0x67, 0x44, 0x12, 0x74, 0x87, 0x4C, 0x12, 0x74, 0x87, 0x4C, 0x12, 0x74, +- 0x87, 0x4C, 0x12, 0x74, 0x87, 0x4D, 0x12, 0x74, 0x87, 0x4D, 0x12, 0x74, 0x87, 0x4D, 0x12, 0x74, +- 0x04, 0x21, 0x04, 0x00, 0xFF, 0x2A, 0x01, 0x00, 0x04, 0x00, 0x03, 0x00, 0xFF, 0x2A, 0x0D, 0x00, +- 0x0C, 0x00, 0xBC, 0xFF, 0x61, 0xFF, 0x78, 0x5C, 0x57, 0x01, 0x78, 0x5C, 0x7F, 0x01, 0xB6, 0xFF, +- 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0x6A, 0x44, 0x2F, 0x58, 0xFF, 0xFF, +- 0x04, 0x74, 0xC4, 0xE2, 0x04, 0xE1, 0x29, 0x40, 0x40, 0x2B, 0x05, 0x00, 0xA1, 0xFF, 0xFF, 0xFF, +- 0xBC, 0xFF, 0x14, 0x74, 0x01, 0x00, 0x04, 0x74, 0xC4, 0xE2, 0x04, 0xE1, 0xBC, 0xFF, 0xB5, 0xFF, +- 0x47, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB4, 0xFF, 0xC8, 0x60, 0x09, 0x7D, 0x7C, 0x4B, 0x29, 0x40, +- 0x40, 0x27, 0x04, 0x00, 0xC2, 0x60, 0x58, 0x4F, 0xBA, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0x29, 0x40, +- 0x10, 0x26, 0x6D, 0x00, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, 0x84, 0xE7, 0xA1, 0xF3, 0x40, 0x60, +- 0x60, 0x40, 0x01, 0x23, 0x48, 0x60, 0x5E, 0x65, 0x80, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, +- 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x80, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x01, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x95, 0x60, 0x84, 0xE7, 0x80, 0x60, 0x01, 0xE0, 0xD5, 0x60, 0x84, 0xE7, 0xA1, 0xF3, 0x7C, 0x45, +- 0x60, 0x40, 0x01, 0x23, 0x02, 0x65, 0x8C, 0x60, 0x48, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x7F, 0x6A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x48, 0x60, +- 0x08, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x84, 0x60, 0x04, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x40, 0x60, 0x08, 0x6A, 0xFF, 0xFF, +- 0x01, 0x16, 0xFE, 0x01, 0x65, 0x4A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x8C, 0x60, 0x48, 0x6A, +- 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, +- 0x00, 0x60, 0x00, 0x6A, 0xFF, 0xFF, 0x01, 0x16, 0xFE, 0x01, 0x95, 0x60, 0x84, 0xE7, 0x01, 0x60, +- 0x08, 0xE1, 0xFF, 0xFF, 0xC4, 0xE2, 0x29, 0x40, 0x40, 0x2B, 0x04, 0x00, 0xC2, 0x60, 0x58, 0x4F, +- 0xBA, 0x78, 0xFF, 0xFF, 0xC2, 0x60, 0x58, 0x4F, 0xC5, 0x78, 0xFF, 0xFF, 0xA1, 0xFF, 0xCB, 0xF3, +- 0xC4, 0xE2, 0x89, 0xFF, 0x60, 0x54, 0x88, 0xFF, 0xDC, 0x84, 0xE0, 0x94, 0x35, 0xF7, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0x01, 0x10, 0x61, 0x7F, 0x60, 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, 0x02, 0x63, +- 0x25, 0x02, 0x98, 0xFE, 0x19, 0x05, 0x12, 0x60, 0xFC, 0xF5, 0x0E, 0xF2, 0x15, 0x18, 0x02, 0x18, +- 0x09, 0xF4, 0xFB, 0x01, 0x23, 0x44, 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, 0x66, 0x44, 0x11, 0xFB, +- 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x28, 0xB9, 0x10, 0x7E, +- 0x00, 0x7F, 0x0E, 0xFA, 0x00, 0x67, 0x0A, 0x00, 0x20, 0x44, 0xDC, 0x85, 0x0F, 0xB4, 0xFB, 0xA0, +- 0x7F, 0x67, 0x07, 0x63, 0x03, 0x05, 0x45, 0x40, 0x00, 0x67, 0xD8, 0xFE, 0xFF, 0x27, 0x05, 0xFD, +- 0x0A, 0x7E, 0x04, 0xFB, 0x61, 0x55, 0x48, 0x00, 0x28, 0xFB, 0x01, 0xF3, 0x29, 0xFB, 0x44, 0x46, +- 0x40, 0x45, 0x10, 0x61, 0x7E, 0x60, 0xC0, 0x64, 0xA0, 0x80, 0x7F, 0x67, 0x02, 0x63, 0x30, 0x02, +- 0xB5, 0x60, 0x58, 0x4F, 0xCE, 0x78, 0xFF, 0xFF, 0x7F, 0x67, 0x03, 0x63, 0x29, 0x02, 0x26, 0x40, +- 0x01, 0x2B, 0x23, 0x00, 0x98, 0xFE, 0x18, 0x05, 0x12, 0x60, 0xFC, 0xF5, 0x0E, 0xF2, 0x14, 0x18, +- 0x02, 0x18, 0x09, 0xF4, 0xFB, 0x01, 0x23, 0x44, 0x00, 0xA8, 0x08, 0x7E, 0x0A, 0x02, 0x66, 0x44, +- 0x11, 0xFB, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x08, 0xB9, +- 0x10, 0x7E, 0x00, 0x7F, 0x0E, 0xFA, 0x09, 0x00, 0x20, 0x44, 0xDC, 0x85, 0x0F, 0xB4, 0xFB, 0xA0, +- 0x7F, 0x67, 0x07, 0x63, 0x05, 0x05, 0x45, 0x40, 0xD8, 0xFE, 0x00, 0x67, 0xD0, 0xFE, 0xD9, 0xFE, +- 0xFF, 0x27, 0x05, 0xFD, 0x0B, 0x7E, 0x04, 0xFB, 0x0E, 0x60, 0xDD, 0xF3, 0xFF, 0xFF, 0x20, 0xB0, +- 0x80, 0xBC, 0x08, 0x28, 0xA2, 0xDB, 0x61, 0x55, 0x66, 0x00, 0x04, 0xB5, 0x82, 0xB5, 0x25, 0x02, +- 0x04, 0x03, 0x20, 0x44, 0x7F, 0xB4, 0x40, 0x40, 0xA3, 0xD3, 0x99, 0xFE, 0x04, 0x04, 0x02, 0xBC, +- 0xFE, 0xB4, 0xA3, 0xDB, 0x59, 0x00, 0xDB, 0xF3, 0x20, 0x40, 0x80, 0x26, 0x55, 0x00, 0xA3, 0xD3, +- 0xFF, 0xA0, 0xF8, 0xB4, 0x02, 0x02, 0xA3, 0xDB, 0x1C, 0x00, 0x04, 0xBC, 0xBF, 0xB4, 0xA3, 0xDB, +- 0x08, 0xB0, 0x01, 0x64, 0x08, 0x24, 0x02, 0x64, 0x28, 0xFB, 0x20, 0x44, 0x80, 0xBC, 0x40, 0x40, +- 0xD0, 0xFE, 0x42, 0x00, 0xBF, 0xB4, 0xA3, 0xDB, 0x3F, 0x00, 0x40, 0xB0, 0xFF, 0xFF, 0xFA, 0x02, +- 0xF8, 0xB4, 0xA3, 0xDB, 0x08, 0xB5, 0x07, 0x7C, 0x01, 0x02, 0xDB, 0xF9, 0x20, 0x44, 0x7F, 0xB4, +- 0x40, 0x40, 0x1D, 0x60, 0xBA, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB5, 0x07, 0xB5, 0x08, 0x28, +- 0xC4, 0x02, 0x99, 0xFE, 0x29, 0x05, 0x20, 0x44, 0x80, 0x26, 0x26, 0x00, 0x20, 0x2A, 0x03, 0x00, +- 0xDF, 0xB4, 0x40, 0x40, 0x74, 0x00, 0x40, 0x2A, 0x1F, 0x00, 0xBF, 0xB4, 0x40, 0x40, 0x09, 0x00, +- 0xA8, 0xFF, 0x20, 0x44, 0x99, 0xFE, 0x02, 0x05, 0x80, 0x2A, 0x03, 0x00, 0x40, 0xBC, 0x40, 0x40, +- 0x13, 0x00, 0x00, 0xF1, 0x80, 0xBC, 0x40, 0x40, 0x64, 0x44, 0xE0, 0x84, 0xE8, 0x84, 0x0A, 0x36, +- 0x29, 0x01, 0x0B, 0x36, 0x59, 0x01, 0x28, 0xFB, 0x01, 0xF1, 0x29, 0xF9, 0x02, 0xF1, 0x2A, 0xF9, +- 0x03, 0xF1, 0x2B, 0xF9, 0xD0, 0xFE, 0xAE, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x82, 0x3E, 0x75, 0x44, +- 0x02, 0xB0, 0x01, 0xB0, 0x54, 0x02, 0xDC, 0x02, 0x04, 0xB0, 0x08, 0xB0, 0x10, 0x02, 0x2A, 0x02, +- 0x40, 0x26, 0xA7, 0xFF, 0x8C, 0xFF, 0x75, 0x40, 0x80, 0x2B, 0x06, 0x00, 0xAB, 0xFF, 0x19, 0x60, +- 0xF6, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xA2, 0xDB, 0x75, 0x44, 0x8D, 0xFF, 0xE5, 0x01, 0x0A, 0xF3, +- 0xAA, 0xFF, 0x60, 0x40, 0x20, 0x2B, 0x02, 0x00, 0x38, 0xFF, 0x0D, 0x00, 0x01, 0x26, 0x0C, 0x00, +- 0xC0, 0x60, 0x00, 0x7C, 0xA0, 0x84, 0x80, 0x3B, 0x02, 0x00, 0xC0, 0x67, 0x03, 0x00, 0x40, 0x3B, +- 0x02, 0x00, 0x00, 0x67, 0x0A, 0xFB, 0xD0, 0x01, 0x19, 0x60, 0xF6, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, +- 0xA2, 0xDB, 0xCA, 0x01, 0x0B, 0xF1, 0xAB, 0xFF, 0x64, 0x44, 0xFF, 0x27, 0x1F, 0x00, 0x20, 0x26, +- 0x03, 0x00, 0x02, 0x60, 0x00, 0x75, 0x1A, 0x00, 0x19, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, 0x04, 0x60, +- 0x00, 0x75, 0x0A, 0x64, 0xCC, 0x84, 0x19, 0xFB, 0x01, 0x60, 0x00, 0x75, 0x64, 0x40, 0x03, 0x22, +- 0x0D, 0x00, 0x20, 0x44, 0x80, 0x2A, 0x03, 0x00, 0x20, 0xBC, 0x40, 0x40, 0x07, 0x00, 0xD9, 0xFE, +- 0x81, 0x60, 0x0B, 0x64, 0x28, 0xFB, 0x2C, 0x44, 0x29, 0xFB, 0xD0, 0xFE, 0xA5, 0x01, 0xA9, 0xFF, +- 0x77, 0x44, 0x60, 0x57, 0x40, 0x4A, 0x01, 0x2A, 0x31, 0x00, 0x24, 0x44, 0xAC, 0x86, 0x08, 0xF2, +- 0x2D, 0x03, 0x25, 0x60, 0xFE, 0x65, 0xD4, 0x80, 0x0E, 0xF2, 0x02, 0x03, 0xA5, 0xD5, 0x04, 0x00, +- 0x01, 0xBC, 0x0E, 0xFA, 0x09, 0xF4, 0xD1, 0xFE, 0x46, 0x44, 0x11, 0x1B, 0x32, 0x40, 0x80, 0x2A, +- 0x1D, 0x00, 0x9D, 0xFE, 0x1B, 0x05, 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, +- 0x03, 0x03, 0x0F, 0xF2, 0xFF, 0xFF, 0x12, 0x1B, 0x08, 0x60, 0x00, 0x75, 0x0F, 0x00, 0x3F, 0xF2, +- 0x48, 0x65, 0xC4, 0x84, 0x13, 0xFB, 0x66, 0x44, 0x10, 0xFB, 0x66, 0x47, 0x20, 0xBF, 0x3B, 0x42, +- 0x04, 0xA2, 0xA2, 0xDB, 0x0E, 0xF2, 0x41, 0x75, 0x10, 0xBC, 0x0E, 0xFA, 0x2A, 0x44, 0x08, 0x2A, +- 0x17, 0x00, 0x23, 0x44, 0x00, 0xA8, 0x5C, 0x43, 0x13, 0x03, 0x12, 0x60, 0xFC, 0xF5, 0x01, 0x00, +- 0x09, 0xF4, 0x0E, 0xF2, 0x0D, 0x18, 0x08, 0xB0, 0x18, 0xAC, 0xFA, 0x03, 0x0E, 0xFA, 0x66, 0x43, +- 0x11, 0xFD, 0x46, 0x43, 0x23, 0x47, 0x80, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x28, 0x75, +- 0x2A, 0x44, 0x06, 0x22, 0x2D, 0x00, 0x22, 0x44, 0x00, 0xA8, 0x60, 0x46, 0x0E, 0xF2, 0x28, 0x03, +- 0x10, 0xB0, 0x01, 0xBC, 0x03, 0x02, 0x00, 0x64, 0x40, 0x42, 0x22, 0x00, 0x0E, 0xFA, 0xD1, 0xFE, +- 0x25, 0x60, 0xF2, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x94, 0x00, 0x46, 0x42, 0x19, 0x02, 0x22, 0x47, +- 0x40, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x23, 0xF2, 0x66, 0x43, 0x00, 0xA8, 0x0E, 0xF2, +- 0x08, 0x02, 0x60, 0x40, 0x02, 0x2A, 0xE4, 0x01, 0x12, 0xFD, 0x10, 0x64, 0x0E, 0xFA, 0x02, 0x75, +- 0x07, 0x00, 0x60, 0x40, 0x04, 0x2A, 0xDC, 0x01, 0x12, 0xFD, 0x10, 0x64, 0x0E, 0xFA, 0x04, 0x75, +- 0x2A, 0x44, 0x80, 0x2A, 0x19, 0x00, 0x21, 0x44, 0xAC, 0x86, 0x0E, 0xF2, 0x15, 0x03, 0x01, 0xBC, +- 0x0E, 0xFA, 0xD1, 0xFE, 0x26, 0x60, 0x0A, 0x64, 0x40, 0x47, 0x58, 0x4F, 0x6A, 0x00, 0x46, 0x41, +- 0x0B, 0x02, 0x21, 0x47, 0x10, 0xBF, 0x3B, 0x42, 0x04, 0xA2, 0xA2, 0xDB, 0x0E, 0xF2, 0x66, 0x43, +- 0x08, 0xFD, 0x10, 0xBC, 0x0E, 0xFA, 0x80, 0x75, 0x2A, 0x44, 0x10, 0xB0, 0x20, 0x44, 0x18, 0x03, +- 0x7F, 0xB4, 0x40, 0x40, 0x1D, 0x60, 0xBA, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, 0x20, 0xB0, 0x80, 0xB0, +- 0x09, 0x03, 0x08, 0x03, 0x40, 0xBC, 0x7F, 0xB4, 0x04, 0xB0, 0xA3, 0xDB, 0x03, 0x03, 0x20, 0x44, +- 0x80, 0xBC, 0x40, 0x40, 0x2A, 0x40, 0x08, 0x27, 0x03, 0x00, 0xB3, 0x60, 0xC9, 0x78, 0xFF, 0xFF, +- 0x2A, 0x40, 0x08, 0x2B, 0x0F, 0x00, 0x32, 0x40, 0x80, 0x26, 0x05, 0x00, 0x19, 0x60, 0xF7, 0xF3, +- 0xFF, 0xFF, 0x01, 0x1B, 0x07, 0x00, 0x19, 0x60, 0xF6, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, 0xA2, 0xDB, +- 0xFF, 0xFF, 0x10, 0xFF, 0xB3, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0xE8, 0xFE, 0x14, 0x05, 0xEA, 0xFE, +- 0x23, 0x05, 0xE9, 0xFE, 0x1C, 0x05, 0xE7, 0xFE, 0x09, 0x05, 0x47, 0xFF, 0x20, 0x44, 0x0F, 0x22, +- 0x03, 0x00, 0xCC, 0x84, 0x40, 0x40, 0x0F, 0x22, 0xB8, 0xFE, 0xEC, 0x01, 0x23, 0x41, 0x00, 0xB9, +- 0x5C, 0x4A, 0xE8, 0x02, 0x5A, 0x01, 0x24, 0x41, 0x00, 0xB9, 0x25, 0x60, 0xFE, 0x65, 0x45, 0x47, +- 0xE1, 0x02, 0x58, 0x4F, 0x0E, 0x00, 0xDE, 0x02, 0x5C, 0x4A, 0x46, 0x44, 0x38, 0x01, 0x22, 0x41, +- 0x00, 0xB9, 0x5C, 0x4A, 0xD7, 0x02, 0x6C, 0x01, 0x21, 0x41, 0x00, 0xB9, 0x5C, 0x4A, 0x92, 0x03, +- 0xD1, 0x01, 0x27, 0xD3, 0x03, 0x00, 0x10, 0xB0, 0x09, 0xF2, 0x04, 0x03, 0xAC, 0x86, 0x0E, 0xF2, +- 0xFA, 0x02, 0x08, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x0E, 0xF3, 0x0F, 0x60, 0xFE, 0x65, 0x0C, 0xF3, +- 0x24, 0x86, 0x24, 0x46, 0x60, 0x40, 0xFB, 0x3B, 0x07, 0x00, 0x80, 0x26, 0x02, 0x00, 0x23, 0x46, +- 0x03, 0x4C, 0x46, 0x61, 0x3A, 0x65, 0x0C, 0x00, 0x2E, 0xF3, 0x40, 0x45, 0xF8, 0x2B, 0x02, 0x00, +- 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, 0x5A, 0x00, 0x07, 0x02, 0x58, 0x4F, 0x66, 0x00, 0x04, 0x05, +- 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, 0x0E, 0xFB, 0x2E, 0xF5, +- 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, 0x00, 0x72, 0x7E, 0x71, 0xAC, 0xFF, 0x31, 0x40, 0x01, 0x2A, +- 0x08, 0x00, 0x19, 0x60, 0xF2, 0xF3, 0xFF, 0xFF, 0x04, 0x18, 0x0C, 0x64, 0x13, 0x60, 0x13, 0xFB, +- 0x2D, 0xFF, 0xB3, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0x8E, 0xFF, 0x0F, 0xF3, 0x0F, 0x60, 0xFE, 0x65, +- 0x24, 0x86, 0x0D, 0xF3, 0x24, 0x46, 0x60, 0x40, 0xFB, 0x3B, 0x07, 0x00, 0x80, 0x26, 0x02, 0x00, +- 0x23, 0x46, 0x03, 0x4C, 0x46, 0x61, 0x3A, 0x65, 0x0C, 0x00, 0x2E, 0xF3, 0x40, 0x45, 0xF8, 0x2B, +- 0x02, 0x00, 0x40, 0x45, 0x03, 0x00, 0x58, 0x4F, 0x21, 0x00, 0x07, 0x02, 0x58, 0x4F, 0x2D, 0x00, +- 0x04, 0x05, 0x66, 0x50, 0x65, 0x52, 0x61, 0x51, 0x09, 0x00, 0x26, 0x47, 0x00, 0xBF, 0x0F, 0xFB, +- 0x2E, 0xF5, 0x05, 0xF0, 0x80, 0x60, 0x64, 0x50, 0x00, 0x72, 0x7E, 0x71, 0x8D, 0xFF, 0xAD, 0xFF, +- 0x31, 0x40, 0x01, 0x2A, 0xCE, 0x01, 0x19, 0x60, 0xF2, 0xF3, 0xFF, 0xFF, 0x04, 0x18, 0x0C, 0x64, +- 0x13, 0x60, 0x13, 0xFB, 0x2D, 0xFF, 0xB3, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0x25, 0x44, 0xA7, 0xF1, +- 0xA8, 0xF1, 0xD0, 0x80, 0xD0, 0x80, 0x07, 0x04, 0x01, 0x06, 0x05, 0x00, 0x25, 0x46, 0x01, 0xF0, +- 0x03, 0x67, 0xA0, 0x85, 0x94, 0x80, 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x46, 0x26, 0x41, 0x46, 0x63, +- 0x01, 0xF2, 0xFF, 0xFF, 0xFF, 0xB5, 0xD5, 0x81, 0x00, 0xF2, 0x05, 0x04, 0x04, 0x63, 0x60, 0x46, +- 0xF7, 0x1B, 0x42, 0xFE, 0x0D, 0x00, 0x61, 0x44, 0xC5, 0x81, 0x63, 0x45, 0xC5, 0x81, 0x9C, 0x84, +- 0xDC, 0x84, 0x01, 0xF2, 0xF0, 0x85, 0xF0, 0x80, 0x65, 0x44, 0xF8, 0x85, 0xFF, 0xFF, 0x02, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0xA2, 0xFF, 0x13, 0x60, 0x08, 0xF3, 0xFF, 0xFF, 0xAC, 0x86, 0x0E, 0xF2, +- 0x07, 0x03, 0x00, 0xA8, 0x09, 0xF2, 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, 0x08, 0xFE, 0x17, 0x00, +- 0xA9, 0xF3, 0xFF, 0xFF, 0xD8, 0xA0, 0x00, 0xB4, 0x12, 0x06, 0x09, 0x60, 0x08, 0x61, 0x41, 0x4A, +- 0x7C, 0xA1, 0x0E, 0xA1, 0xA2, 0xFF, 0xB6, 0x60, 0x58, 0x4E, 0x44, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, +- 0x06, 0x03, 0x2A, 0x43, 0xB6, 0x60, 0x58, 0x4E, 0x65, 0x78, 0xFF, 0xFF, 0x08, 0xFE, 0xA3, 0xFF, +- 0x2D, 0x58, 0xFF, 0xFF, 0x41, 0x4A, 0x42, 0xA1, 0x03, 0x00, 0x41, 0x4A, 0x7C, 0xA1, 0x0E, 0xA1, +- 0xA2, 0xFF, 0xB6, 0x60, 0x58, 0x4E, 0x44, 0x78, 0xFF, 0xFF, 0x07, 0x03, 0x2A, 0x43, 0xB6, 0x60, +- 0x58, 0x4E, 0x65, 0x78, 0xFF, 0xFF, 0x08, 0xFE, 0x0C, 0x00, 0x13, 0x60, 0x08, 0xF3, 0xFF, 0xFF, +- 0xAC, 0x86, 0x0E, 0xF2, 0x06, 0x03, 0x00, 0xA8, 0x09, 0xF2, 0xFA, 0x02, 0x01, 0x67, 0x0E, 0xFA, +- 0x08, 0xFE, 0xA3, 0xFF, 0x2D, 0x58, 0xFF, 0xFF, 0xAA, 0xF3, 0x7C, 0x63, 0x00, 0xBE, 0x40, 0x45, +- 0x1A, 0x03, 0x00, 0x65, 0x65, 0x44, 0xDC, 0x85, 0x84, 0xA1, 0x00, 0xF2, 0x06, 0x06, 0x01, 0xFC, +- 0x00, 0xA8, 0x60, 0x46, 0xF7, 0x02, 0x40, 0x45, 0x0E, 0x00, 0xA9, 0xF3, 0x00, 0x63, 0xD4, 0x84, +- 0xA9, 0xFB, 0x80, 0x60, 0x7C, 0x64, 0x01, 0xFA, 0x00, 0xF0, 0x00, 0xFC, 0xD3, 0x80, 0xAA, 0xF9, +- 0x02, 0x02, 0xAB, 0xF9, 0x08, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x66, 0x44, 0x25, 0x46, 0x05, 0xFA, +- 0x06, 0xFA, 0x01, 0xF0, 0x03, 0x67, 0x02, 0xFC, 0xB0, 0x84, 0x3A, 0x7E, 0x01, 0xFA, 0x12, 0x64, +- 0x03, 0xFA, 0x00, 0xF0, 0x04, 0xF8, 0x00, 0x64, 0x0C, 0x61, 0x10, 0x63, 0x59, 0xDA, 0xFE, 0x1F, +- 0x2E, 0x58, 0xFF, 0xFF, 0x27, 0x43, 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, 0x16, 0x03, 0x00, 0x61, +- 0x01, 0x00, 0xEC, 0x63, 0x61, 0x46, 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, 0xA2, 0xDA, 0xBE, 0xD2, +- 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, 0x25, 0x44, 0x61, 0x46, 0xA3, 0xDA, 0x04, 0x00, 0x0A, 0xFA, +- 0x60, 0x46, 0x25, 0x44, 0x09, 0xFA, 0x61, 0x46, 0xBE, 0xDA, 0x2F, 0x58, 0xFF, 0xFF, 0x25, 0x44, +- 0x00, 0xA8, 0x07, 0x4B, 0x0C, 0x03, 0x58, 0x4F, 0x33, 0x00, 0x0B, 0x47, 0x26, 0x60, 0x04, 0x65, +- 0x27, 0x44, 0xD4, 0x80, 0x00, 0x64, 0x01, 0x02, 0x0F, 0xFA, 0x58, 0x4F, 0xD3, 0x01, 0x70, 0x00, +- 0x25, 0x43, 0xE3, 0x84, 0x7C, 0x41, 0x02, 0x04, 0xE8, 0x81, 0xEC, 0x63, 0x61, 0x46, 0xA3, 0xD2, +- 0x00, 0x7C, 0x40, 0x45, 0xBF, 0xD8, 0xA3, 0xD8, 0xBE, 0xD8, 0x27, 0x42, 0x5A, 0xD3, 0x25, 0x5C, +- 0x60, 0x41, 0x02, 0x1B, 0x27, 0xD9, 0x05, 0x00, 0x25, 0x46, 0x0A, 0xFA, 0x61, 0x46, 0x25, 0x44, +- 0x09, 0xFA, 0x25, 0x44, 0x27, 0x43, 0x00, 0x61, 0x60, 0x46, 0x09, 0xF2, 0x08, 0xFC, 0x00, 0xA8, +- 0xDD, 0x81, 0xFA, 0x02, 0xBF, 0xD1, 0x66, 0x44, 0xBE, 0xDB, 0xC1, 0x84, 0xBF, 0xDB, 0x48, 0x00, +- 0x25, 0x46, 0xEC, 0x63, 0x08, 0xF2, 0x89, 0xF2, 0x1E, 0x18, 0x40, 0x47, 0xE0, 0x84, 0xE8, 0x85, +- 0x02, 0x05, 0xE8, 0x83, 0x00, 0x65, 0x65, 0x46, 0xBF, 0xD2, 0x61, 0x5C, 0xCC, 0x84, 0xA2, 0xDA, +- 0x25, 0x46, 0x0A, 0xF2, 0x00, 0xB9, 0x65, 0x46, 0x08, 0x24, 0xBE, 0xDA, 0x02, 0x1B, 0xA3, 0xD8, +- 0x02, 0x00, 0x60, 0x46, 0x89, 0xFA, 0x00, 0xB9, 0x61, 0x46, 0x08, 0x28, 0x0A, 0xFA, 0x25, 0x46, +- 0x89, 0xFC, 0x8A, 0xFC, 0x88, 0xFC, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x61, 0x28, 0x65, 0x25, 0x43, +- 0xAB, 0xF3, 0xAF, 0x83, 0x00, 0xBE, 0x18, 0x03, 0x02, 0x03, 0x00, 0xFC, 0x01, 0x00, 0xAA, 0xFD, +- 0x63, 0x46, 0x65, 0x44, 0xCC, 0x85, 0x00, 0xF2, 0x07, 0x02, 0xAB, 0xF5, 0x00, 0x64, 0x00, 0xFA, +- 0xDE, 0x60, 0xAF, 0x64, 0x09, 0xFB, 0x08, 0x00, 0x66, 0x43, 0x00, 0xBE, 0xDD, 0x81, 0xF1, 0x02, +- 0xA9, 0xF1, 0xAB, 0xFD, 0xC1, 0x84, 0xA9, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x45, +- 0x29, 0x43, 0xFC, 0xA3, 0x66, 0x44, 0xBD, 0xDB, 0x25, 0x44, 0xBD, 0xDB, 0x00, 0x64, 0xBD, 0xDB, +- 0x03, 0x61, 0x0E, 0x65, 0x26, 0x60, 0x18, 0x63, 0x43, 0x49, 0xA3, 0xD3, 0x06, 0xA3, 0x00, 0xA8, +- 0xCD, 0x81, 0x04, 0x02, 0xF9, 0x02, 0xB3, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0x01, 0x26, 0xE6, 0x01, +- 0xD4, 0x80, 0x60, 0x45, 0xE3, 0x05, 0xF6, 0xA3, 0xBD, 0xD1, 0xBD, 0xD1, 0x44, 0x47, 0x44, 0x48, +- 0x44, 0x45, 0x26, 0x60, 0x5A, 0x64, 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x25, 0x60, 0xC8, 0x63, +- 0x0D, 0x65, 0x00, 0x61, 0x41, 0x48, 0xA3, 0xD3, 0x06, 0xA3, 0xAC, 0x86, 0x00, 0x61, 0x09, 0x03, +- 0x00, 0xF2, 0x09, 0xF0, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x64, 0x44, 0xAC, 0x86, +- 0xF6, 0x01, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x65, 0x44, 0x28, 0x45, 0x45, 0x88, 0xCC, 0x85, +- 0x5A, 0x87, 0xE9, 0x02, 0x00, 0x64, 0x27, 0xDA, 0x5A, 0xDA, 0x5A, 0x87, 0xA6, 0xF3, 0xA5, 0xF1, +- 0x02, 0xA4, 0x60, 0x46, 0x60, 0x45, 0x00, 0x61, 0x22, 0xF2, 0xFF, 0xFF, 0xAC, 0x86, 0x00, 0xF2, +- 0x04, 0x03, 0xAC, 0x86, 0x00, 0xF2, 0xDD, 0x81, 0xFC, 0x02, 0x65, 0x44, 0x02, 0xA5, 0x65, 0x46, +- 0x64, 0x44, 0xCC, 0x9C, 0xFF, 0xFF, 0xF0, 0x02, 0x61, 0x44, 0x25, 0x46, 0x27, 0xDA, 0x5A, 0x87, +- 0x28, 0x45, 0x45, 0x88, 0x00, 0x64, 0x27, 0xDA, 0x5A, 0x87, 0x06, 0x60, 0x40, 0x65, 0xAA, 0xF3, +- 0x01, 0x61, 0xAC, 0x86, 0x00, 0xF2, 0x03, 0x03, 0xD5, 0x80, 0xDD, 0x81, 0xFA, 0x04, 0xCD, 0x84, +- 0x25, 0x46, 0x27, 0xDA, 0x28, 0x45, 0xC4, 0x84, 0x5A, 0xDA, 0xDA, 0x81, 0xA9, 0xF1, 0x59, 0xD8, +- 0x25, 0x60, 0xC6, 0x64, 0x18, 0x63, 0xA0, 0xD1, 0x06, 0xA4, 0x59, 0xD8, 0xFC, 0x1F, 0x00, 0x64, +- 0x59, 0xDA, 0x59, 0xDA, 0x01, 0x60, 0x56, 0x64, 0x0A, 0x63, 0x58, 0xD1, 0x59, 0xD8, 0xFD, 0x1F, +- 0xDB, 0xF1, 0x59, 0xD8, 0x75, 0x01, 0x07, 0x4B, 0xB6, 0x60, 0x58, 0x4F, 0xD0, 0x78, 0xFF, 0xFF, +- 0x0B, 0x47, 0x58, 0x4F, 0x21, 0x00, 0x6C, 0x01, 0x07, 0x4B, 0xB6, 0x60, 0x58, 0x4F, 0xD0, 0x78, +- 0xFF, 0xFF, 0x0B, 0x47, 0x27, 0x44, 0x00, 0xBE, 0x08, 0xF0, 0x15, 0x03, 0x64, 0x42, 0x4A, 0xD3, +- 0x09, 0xF2, 0xDC, 0x83, 0xA2, 0xDD, 0x25, 0x43, 0x09, 0xFC, 0x63, 0x46, 0x27, 0x43, 0x0A, 0xFC, +- 0x09, 0xFA, 0x08, 0xF8, 0x00, 0xA8, 0x66, 0x43, 0x03, 0x02, 0x64, 0x44, 0x58, 0xDD, 0x03, 0x00, +- 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, 0x4C, 0x01, 0x27, 0x43, 0xE3, 0x81, 0xE9, 0x81, 0x03, 0x05, +- 0x16, 0x03, 0x00, 0x61, 0x01, 0x00, 0xEC, 0x63, 0x61, 0x46, 0xBF, 0xD2, 0x27, 0x45, 0xDC, 0x84, +- 0xA2, 0xDA, 0xA3, 0xD2, 0x25, 0x46, 0x88, 0xF8, 0x04, 0x1B, 0x25, 0x44, 0x61, 0x46, 0xBE, 0xDA, +- 0x04, 0x00, 0x09, 0xFA, 0x60, 0x46, 0x25, 0x44, 0x0A, 0xFA, 0x61, 0x46, 0xA3, 0xDA, 0x2F, 0x58, +- 0xFF, 0xFF, 0xA0, 0xFE, 0x07, 0x05, 0xA3, 0xFE, 0x07, 0x05, 0xA1, 0xFE, 0x48, 0x05, 0x60, 0x64, +- 0x3B, 0xDB, 0x11, 0x00, 0x20, 0x58, 0xFF, 0xFF, 0x4F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x60, +- 0xDF, 0xF3, 0xFF, 0xFF, 0xFB, 0xB4, 0xA2, 0xDB, 0xA0, 0x4C, 0x59, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, +- 0xA0, 0x4C, 0x7D, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x83, 0x3E, 0x40, 0x60, 0x0B, 0x65, +- 0x2B, 0x44, 0x00, 0x63, 0xE8, 0x80, 0xF8, 0x84, 0x02, 0x24, 0x94, 0x84, 0xF3, 0x83, 0xCD, 0x81, +- 0xFF, 0xFF, 0xF8, 0x02, 0xDF, 0x83, 0x2F, 0x58, 0x40, 0x4B, 0x00, 0x62, 0x01, 0x64, 0xD4, 0x80, +- 0xE0, 0x84, 0x1A, 0x03, 0xD4, 0x80, 0xE0, 0x84, 0x15, 0x03, 0x61, 0x44, 0x11, 0x61, 0xE0, 0x84, +- 0xCD, 0x81, 0xFD, 0x04, 0x01, 0x00, 0xE0, 0x84, 0xF2, 0x82, 0xFF, 0xFF, 0x02, 0x24, 0xC6, 0x82, +- 0x02, 0x28, 0xD6, 0x82, 0xE2, 0x80, 0xCD, 0x81, 0x02, 0x28, 0x01, 0xBC, 0xF4, 0x02, 0x01, 0x2A, +- 0xC6, 0x82, 0x03, 0x00, 0xE9, 0x81, 0xF2, 0x82, 0x61, 0x44, 0x2D, 0x58, 0xFF, 0xFF, 0x00, 0x64, +- 0x3B, 0xDB, 0x3C, 0x44, 0xAC, 0x80, 0xFF, 0xFF, 0xC6, 0x02, 0x89, 0xF3, 0x8A, 0xF3, 0x02, 0xA8, +- 0x02, 0xA8, 0x08, 0x02, 0x00, 0x64, 0x8B, 0xFB, 0x89, 0xFB, 0x8A, 0xFB, 0x00, 0x64, 0x8C, 0xFB, +- 0xCA, 0xFE, 0x2A, 0x00, 0x03, 0x02, 0x00, 0x64, 0x8A, 0xFB, 0xCA, 0xFE, 0x01, 0x64, 0x3B, 0xDB, +- 0x12, 0x60, 0xE7, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x13, 0x03, 0xDB, 0xF3, 0x2A, 0xF2, +- 0xFD, 0xA0, 0x60, 0x40, 0x80, 0x3A, 0x33, 0x00, 0x32, 0x02, 0x9B, 0xFE, 0x30, 0x05, 0x00, 0x64, +- 0x13, 0x60, 0x0A, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xE7, 0x01, 0x8A, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, 0xFF, 0xFF, 0x06, 0x02, 0x12, 0x60, 0xE4, 0xF3, +- 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x1B, 0x02, 0x86, 0xFF, 0x20, 0x40, 0x12, 0x27, 0x13, 0x00, +- 0x9A, 0xFE, 0x11, 0x04, 0x9D, 0xFE, 0x0F, 0x04, 0x95, 0xF3, 0xFF, 0xFF, 0x80, 0xBC, 0x95, 0xFB, +- 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0x06, 0x64, 0x13, 0x60, 0x16, 0xFB, 0xFF, 0xFF, +- 0x2D, 0xFF, 0x12, 0x64, 0x3B, 0xDB, 0x84, 0xFF, 0xB7, 0x60, 0xF7, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0xFC, 0xFB, 0x46, 0x5C, 0x19, 0x60, 0xCF, 0xF3, 0x0D, 0xF2, 0x60, 0x5C, 0x64, 0x5F, 0x0D, 0xFA, +- 0x11, 0x64, 0x3B, 0xDB, 0x9D, 0xFE, 0x06, 0x05, 0x08, 0x64, 0x13, 0x60, 0x16, 0xFB, 0x2D, 0xFF, +- 0xFF, 0xFF, 0xA3, 0xFE, 0x07, 0xF0, 0x00, 0x64, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x02, 0x23, 0xF0, +- 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0xBF, 0x60, 0x79, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x00, 0x63, +- 0x40, 0x47, 0x50, 0x36, 0x05, 0x00, 0xA4, 0x36, 0x03, 0x00, 0x80, 0x36, 0x01, 0x00, 0x01, 0x63, +- 0x48, 0xFD, 0x40, 0x47, 0x08, 0x2A, 0x08, 0x00, 0x03, 0x2F, 0x06, 0x00, 0x7F, 0xF1, 0x2C, 0xF8, +- 0x80, 0xF1, 0x2D, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, 0x4A, 0xF3, 0x35, 0xFA, 0x10, 0xA4, 0x4A, 0xFB, +- 0x00, 0x64, 0x15, 0xFA, 0x16, 0xFA, 0x0F, 0xFA, 0x07, 0xF0, 0xA6, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, +- 0xFF, 0xFF, 0x05, 0x03, 0x66, 0x43, 0x64, 0x46, 0x11, 0xF2, 0xD9, 0xFB, 0x63, 0x46, 0x03, 0xF2, +- 0x00, 0xF4, 0x01, 0xF2, 0xFC, 0xA5, 0x00, 0x7F, 0xD4, 0x84, 0x27, 0x45, 0x3C, 0x46, 0x1A, 0xFA, +- 0x22, 0x63, 0x7B, 0x60, 0xFF, 0x64, 0xA4, 0x84, 0x03, 0x2B, 0x1C, 0x63, 0x2A, 0xFA, 0x8F, 0xB0, +- 0x88, 0x36, 0x02, 0xA3, 0x60, 0x40, 0xA4, 0x36, 0x14, 0x63, 0x43, 0x4C, 0x18, 0xFC, 0x00, 0x7C, +- 0x22, 0xF8, 0x64, 0x41, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x3A, 0xF2, 0x63, 0x46, 0xFF, 0xB4, +- 0x22, 0xFA, 0x60, 0x40, 0x00, 0x36, 0x82, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x0C, 0xB0, 0x08, 0x3A, +- 0xAD, 0x00, 0x60, 0x40, 0x40, 0x26, 0xAA, 0x00, 0x03, 0xF2, 0x00, 0xF4, 0xA0, 0xD2, 0xAA, 0x60, +- 0xAA, 0x65, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, 0x0A, 0x02, 0xD0, 0x80, 0x00, 0x64, 0x5A, 0xD0, +- 0x06, 0x02, 0xD0, 0x80, 0xF8, 0x7F, 0xD0, 0x80, 0x01, 0x03, 0x01, 0x02, 0x01, 0x61, 0x62, 0x43, +- 0x46, 0x43, 0x3C, 0x46, 0x07, 0xF4, 0x3A, 0xF2, 0xFF, 0xFF, 0xA3, 0x46, 0x60, 0x40, 0x22, 0x26, +- 0x64, 0x00, 0x60, 0x45, 0x63, 0x42, 0x5A, 0xD0, 0xCD, 0x81, 0x3C, 0x46, 0x1B, 0x02, 0x64, 0x44, +- 0x88, 0x3A, 0x18, 0x00, 0x8E, 0x37, 0x03, 0x00, 0xC7, 0x37, 0x01, 0x00, 0x13, 0x00, 0x65, 0x44, +- 0x01, 0x26, 0x7C, 0x00, 0x04, 0x26, 0x03, 0x00, 0x10, 0x26, 0x01, 0x00, 0x31, 0x00, 0xA3, 0x46, +- 0x3B, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x27, 0x5B, 0x00, 0xA3, 0x46, 0x00, 0x7C, 0x22, 0xF8, +- 0xA3, 0x46, 0x6C, 0x00, 0xA3, 0x46, 0x65, 0x44, 0x01, 0x26, 0x0B, 0x00, 0x04, 0x26, 0x03, 0x00, +- 0x10, 0x26, 0x01, 0x00, 0x1D, 0x00, 0x3B, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x27, 0x48, 0x00, +- 0x17, 0x00, 0xA6, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x3A, 0xF2, 0x66, 0x43, 0xFF, 0xB4, 0x3C, 0x46, +- 0x22, 0xF0, 0x60, 0x47, 0xB0, 0x84, 0x22, 0xFA, 0x63, 0x46, 0x3B, 0xF0, 0x60, 0x40, 0x04, 0x27, +- 0x03, 0x00, 0x10, 0x27, 0x01, 0x00, 0x04, 0x00, 0x64, 0x40, 0x80, 0x27, 0x31, 0x00, 0x00, 0x00, +- 0x3C, 0x46, 0x02, 0x65, 0xBF, 0x60, 0x19, 0x78, 0xFF, 0xFF, 0xCD, 0x81, 0x63, 0x42, 0x5A, 0xD0, +- 0x3C, 0x46, 0x26, 0x02, 0x64, 0x44, 0x88, 0x3A, 0x23, 0x00, 0x77, 0x37, 0x37, 0x00, 0x78, 0x37, +- 0x35, 0x00, 0x8E, 0x37, 0x33, 0x00, 0xC7, 0x37, 0x31, 0x00, 0x1A, 0x00, 0x19, 0x60, 0xA3, 0xF3, +- 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x2A, 0x00, 0x06, 0x00, 0x19, 0x60, 0xA3, 0xF3, 0xFF, 0xFF, +- 0x60, 0x40, 0x01, 0x2A, 0xE2, 0x01, 0x3C, 0x46, 0x3E, 0xF2, 0x40, 0x60, 0x00, 0x65, 0xF0, 0x84, +- 0xA4, 0x84, 0x3D, 0xFA, 0x2A, 0xF2, 0xBF, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x2A, 0xFA, 0x16, 0x00, +- 0x3C, 0x46, 0x22, 0xF0, 0x80, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0xFF, 0xFF, 0x3F, 0xF2, 0x3E, 0xF0, +- 0x08, 0xA4, 0x60, 0x41, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x03, 0x00, 0x04, 0x26, +- 0x03, 0x00, 0x04, 0x00, 0x04, 0x2B, 0x02, 0x00, 0x61, 0x44, 0x3F, 0xFA, 0x3C, 0x46, 0x2C, 0xF2, +- 0x27, 0x40, 0x01, 0x27, 0x32, 0xF2, 0xD3, 0xF1, 0x60, 0x40, 0x01, 0x26, 0x47, 0x00, 0x09, 0x60, +- 0x00, 0x64, 0xD0, 0x80, 0x3F, 0xF2, 0x09, 0x06, 0x2C, 0x45, 0xC4, 0x84, 0xD0, 0x80, 0x40, 0x4A, +- 0x34, 0x06, 0x60, 0x43, 0x64, 0x44, 0x54, 0x88, 0x17, 0x00, 0x60, 0x45, 0x16, 0x60, 0xC8, 0xF3, +- 0xDA, 0xF3, 0x00, 0xBC, 0x60, 0x47, 0xEC, 0xA0, 0x28, 0x03, 0x27, 0x07, 0x2C, 0x44, 0xC4, 0x81, +- 0x02, 0x60, 0x1C, 0x65, 0x45, 0x4A, 0xD5, 0x80, 0x2C, 0x45, 0x1F, 0x06, 0x27, 0x40, 0x04, 0x27, +- 0x25, 0x00, 0x2A, 0x43, 0xD7, 0x85, 0x45, 0x48, 0xD4, 0xF1, 0x0F, 0xF2, 0xD3, 0x80, 0x01, 0x65, +- 0x01, 0x07, 0x00, 0x65, 0xB4, 0x84, 0x0F, 0xFA, 0x00, 0x63, 0x3F, 0xF2, 0x28, 0x45, 0x60, 0x41, +- 0xD4, 0x84, 0xDF, 0x83, 0xFC, 0x07, 0x14, 0xFC, 0x17, 0xFA, 0x04, 0x60, 0x00, 0x64, 0x27, 0x45, +- 0xB4, 0x84, 0x2A, 0xFA, 0x28, 0x43, 0x16, 0xFC, 0x0D, 0x00, 0x3F, 0xF2, 0x2C, 0x45, 0xD4, 0xF1, +- 0xC4, 0x81, 0xD1, 0x80, 0x0F, 0xF2, 0x01, 0x06, 0x01, 0xBC, 0x0F, 0xFA, 0x3F, 0xF2, 0x17, 0xFA, +- 0x01, 0x64, 0x14, 0xFA, 0xAA, 0xF2, 0x19, 0x60, 0x3F, 0xF3, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, +- 0x44, 0x44, 0x61, 0x40, 0x08, 0x26, 0x02, 0x00, 0x61, 0x40, 0x80, 0x36, 0x12, 0xF2, 0x63, 0x46, +- 0x33, 0x60, 0x86, 0x61, 0x00, 0x7F, 0x60, 0x45, 0x45, 0xD3, 0xFF, 0xFF, 0x60, 0x45, 0x00, 0x7F, +- 0x4B, 0xFB, 0x65, 0x44, 0x00, 0x7E, 0xDA, 0xFB, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x12, 0xF0, +- 0x60, 0x47, 0x63, 0x46, 0x64, 0x40, 0x10, 0x2A, 0x1E, 0x00, 0x33, 0x60, 0x0A, 0x63, 0x60, 0x40, +- 0x0A, 0x36, 0x0C, 0x00, 0x14, 0x36, 0x07, 0x00, 0x37, 0x36, 0x02, 0x00, 0xA3, 0xD3, 0x09, 0x00, +- 0x02, 0xA3, 0xA3, 0xD3, 0x06, 0x00, 0x04, 0xA3, 0xA3, 0xD3, 0x03, 0x00, 0x06, 0xA3, 0xA3, 0xD3, +- 0xFF, 0xFF, 0x60, 0x40, 0x0A, 0x36, 0x70, 0x64, 0x14, 0x36, 0x38, 0x64, 0x37, 0x36, 0x15, 0x64, +- 0x6E, 0x36, 0x0B, 0x64, 0x39, 0x00, 0x32, 0x60, 0xFA, 0x63, 0x60, 0x40, 0x0B, 0x36, 0x20, 0x00, +- 0x0F, 0x36, 0x1B, 0x00, 0x0A, 0x36, 0x16, 0x00, 0x0E, 0x36, 0x11, 0x00, 0x09, 0x36, 0x0C, 0x00, +- 0x0D, 0x36, 0x07, 0x00, 0x08, 0x36, 0x02, 0x00, 0xA3, 0xD3, 0x15, 0x00, 0x02, 0xA3, 0xA3, 0xD3, +- 0x12, 0x00, 0x04, 0xA3, 0xA3, 0xD3, 0x0F, 0x00, 0x06, 0xA3, 0xA3, 0xD3, 0x0C, 0x00, 0x08, 0xA3, +- 0xA3, 0xD3, 0x09, 0x00, 0x0A, 0xA3, 0xA3, 0xD3, 0x06, 0x00, 0x0C, 0xA3, 0xA3, 0xD3, 0x03, 0x00, +- 0x0E, 0xA3, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x40, 0x0B, 0x36, 0x1E, 0x64, 0x0F, 0x36, 0x16, 0x64, +- 0x0A, 0x36, 0x12, 0x64, 0x0E, 0x36, 0x0E, 0x64, 0x09, 0x36, 0x0E, 0x64, 0x0D, 0x36, 0x0A, 0x64, +- 0x08, 0x36, 0x0A, 0x64, 0x0C, 0x36, 0x0A, 0x64, 0x40, 0x46, 0x2A, 0xF2, 0x07, 0xF0, 0x60, 0x40, +- 0xB0, 0x3A, 0x03, 0x00, 0x40, 0x3B, 0x01, 0x00, 0x12, 0x00, 0x0C, 0xB4, 0x08, 0x3A, 0x44, 0x00, +- 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, 0x3F, 0x00, 0x17, 0xF2, 0x22, 0xF0, 0xFF, 0xFF, +- 0x64, 0x40, 0x22, 0x22, 0x04, 0x00, 0x00, 0xA8, 0x01, 0xA8, 0x36, 0x03, 0x35, 0x03, 0x3C, 0x46, +- 0x2A, 0xF0, 0x40, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x60, 0x45, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x43, +- 0x60, 0x40, 0x01, 0x26, 0x05, 0x00, 0x04, 0x26, 0x1D, 0x00, 0x10, 0x26, 0x10, 0x00, 0x04, 0x00, +- 0x04, 0x27, 0x18, 0x00, 0x10, 0x27, 0x0B, 0x00, 0x65, 0x44, 0x2A, 0x61, 0x60, 0x40, 0x03, 0x2B, +- 0x24, 0x61, 0x8F, 0xB0, 0x88, 0x36, 0x02, 0xA1, 0x41, 0x4C, 0x98, 0xFA, 0x15, 0x00, 0x65, 0x44, +- 0x32, 0x61, 0x60, 0x40, 0x03, 0x2B, 0x2C, 0x61, 0x8F, 0xB0, 0x88, 0x36, 0x02, 0xA1, 0x41, 0x4C, +- 0x98, 0xFA, 0x0A, 0x00, 0x65, 0x44, 0x2E, 0x61, 0x60, 0x40, 0x03, 0x2B, 0x28, 0x61, 0x8F, 0xB0, +- 0x88, 0x36, 0x02, 0xA1, 0x41, 0x4C, 0x98, 0xFA, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x27, +- 0x03, 0x00, 0xBC, 0x60, 0x46, 0x78, 0xFF, 0xFF, 0x22, 0xF2, 0x46, 0x43, 0x60, 0x40, 0x22, 0x26, +- 0x09, 0x00, 0x01, 0x26, 0x0A, 0x00, 0x04, 0x26, 0x4B, 0x00, 0x10, 0x26, 0x10, 0x00, 0xBC, 0x60, +- 0x46, 0x78, 0xFF, 0xFF, 0xBB, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0x04, 0x27, 0x3D, 0x00, 0x10, 0x27, +- 0x03, 0x00, 0xBC, 0x60, 0x46, 0x78, 0xFF, 0xFF, 0xA6, 0xF3, 0x3C, 0xF1, 0x02, 0x00, 0x07, 0xF2, +- 0x00, 0x7C, 0x40, 0x43, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x27, 0x21, 0x00, 0xA3, 0x46, +- 0x4B, 0xF2, 0xFF, 0xFF, 0xDC, 0x84, 0x4B, 0xFA, 0x4A, 0xF2, 0x08, 0x04, 0xDC, 0x84, 0x4A, 0xFA, +- 0x49, 0xF2, 0x04, 0x04, 0xDC, 0x84, 0x49, 0xFA, 0x01, 0x04, 0xFF, 0xFF, 0xA6, 0xF3, 0x66, 0x5C, +- 0xD0, 0x80, 0x00, 0x7C, 0x01, 0x02, 0x3C, 0xF1, 0x4B, 0xF0, 0x64, 0x47, 0x20, 0xBF, 0xA3, 0x46, +- 0x3A, 0xF8, 0x3B, 0xFA, 0xA3, 0x46, 0x4A, 0xF2, 0x49, 0xF0, 0xA3, 0x46, 0x3C, 0xFA, 0x3D, 0xF8, +- 0x0F, 0x60, 0x9E, 0x64, 0xA3, 0x46, 0x76, 0x61, 0x0E, 0x63, 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, +- 0xA3, 0x46, 0xBC, 0x60, 0x46, 0x78, 0xFF, 0xFF, 0xA6, 0xF3, 0xFF, 0xFF, 0x60, 0x46, 0x02, 0x00, +- 0x07, 0xF4, 0xFF, 0xFF, 0xA3, 0x46, 0x2A, 0xF2, 0xA3, 0x46, 0x60, 0x40, 0x08, 0x27, 0x48, 0x00, +- 0xA6, 0xF3, 0x66, 0x5C, 0xD0, 0x80, 0x3B, 0xF0, 0x08, 0x03, 0x64, 0x40, 0x10, 0x2A, 0x12, 0x00, +- 0xFF, 0x60, 0xEF, 0x64, 0xA0, 0x84, 0x3B, 0xFA, 0x24, 0x00, 0x3D, 0xF3, 0x01, 0x61, 0x60, 0x43, +- 0xCF, 0x83, 0xE1, 0x81, 0xFD, 0x0D, 0xE9, 0x81, 0xA1, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0x91, 0x84, +- 0x3B, 0xFA, 0x17, 0x00, 0x4B, 0xF2, 0xFF, 0xFF, 0x10, 0xA0, 0xFF, 0xFF, 0x02, 0x04, 0xFF, 0x60, +- 0xFF, 0x64, 0xDC, 0x84, 0x4B, 0xFA, 0x4A, 0xF2, 0x16, 0x04, 0xDC, 0x84, 0x4A, 0xFA, 0x49, 0xF2, +- 0x08, 0x04, 0xDC, 0x84, 0x49, 0xFA, 0x05, 0x04, 0x3B, 0xF2, 0xFF, 0xFF, 0xE0, 0x84, 0xE8, 0x84, +- 0x3B, 0xFA, 0x0C, 0x60, 0xFC, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC8, 0x60, +- 0x15, 0x78, 0xFF, 0xFF, 0x84, 0xFF, 0x06, 0x60, 0x17, 0xE1, 0x77, 0x40, 0x8B, 0xFF, 0x02, 0x60, +- 0x00, 0x75, 0xC9, 0x60, 0x58, 0x4F, 0xAD, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x06, 0x60, 0x7F, 0xFB, +- 0x0C, 0x60, 0xFC, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC8, 0x60, 0x8C, 0x78, +- 0xFF, 0xFF, 0x84, 0xFF, 0x00, 0x7C, 0x06, 0x60, 0x7F, 0xF3, 0xA2, 0xD9, 0x60, 0x40, 0x01, 0x2A, +- 0x04, 0x00, 0xC9, 0x60, 0x58, 0x4F, 0xF6, 0x78, 0xFF, 0xFF, 0x3C, 0x46, 0x07, 0xF4, 0xA6, 0xF3, +- 0x66, 0x5C, 0xD0, 0x80, 0x00, 0x7C, 0x07, 0x03, 0x66, 0x43, 0x3C, 0x46, 0x22, 0xF2, 0x63, 0x46, +- 0x60, 0x40, 0x01, 0x2A, 0x01, 0x00, 0x3C, 0xF1, 0x4B, 0xF0, 0x64, 0x41, 0x64, 0x47, 0xFF, 0xB4, +- 0x60, 0x5F, 0x20, 0xBC, 0x80, 0x26, 0x80, 0xAC, 0x60, 0x47, 0xA3, 0x46, 0x3A, 0xFA, 0x64, 0x44, +- 0x20, 0x7F, 0x34, 0x94, 0x3B, 0xFA, 0xA3, 0x46, 0x4A, 0xF2, 0x49, 0xF0, 0xA3, 0x46, 0x3C, 0xFA, +- 0x3D, 0xF8, 0x80, 0x60, 0x10, 0xE0, 0x08, 0x60, 0x00, 0xEA, 0x0F, 0x64, 0x60, 0x7F, 0xA0, 0x5A, +- 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0xBC, 0x60, 0x46, 0x78, +- 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x27, 0x31, 0x00, 0x2A, 0xF2, 0x00, 0x60, +- 0x7C, 0x62, 0x60, 0x40, 0x40, 0x2B, 0x24, 0x00, 0xA2, 0xD3, 0x00, 0x61, 0x60, 0xFE, 0xA0, 0xD3, +- 0x5E, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x64, 0x5F, 0xDC, 0x84, 0xF1, 0x81, 0xC0, 0x2B, 0x04, 0x00, +- 0x80, 0x2A, 0x02, 0x00, 0x7F, 0xA4, 0xDC, 0x84, 0xFF, 0x3B, 0x03, 0x00, 0x60, 0x47, 0xDC, 0x87, +- 0x01, 0x61, 0xC0, 0x80, 0x00, 0x36, 0xDC, 0x84, 0x4E, 0xDB, 0x60, 0xFE, 0x5A, 0xD1, 0xFF, 0xFF, +- 0xC1, 0x84, 0xF0, 0x22, 0x10, 0xA4, 0xF0, 0x2A, 0x01, 0x00, 0x00, 0x64, 0xA2, 0xDB, 0x20, 0xFE, +- 0x00, 0x60, 0x3E, 0xF3, 0xFF, 0xFF, 0xA0, 0xD3, 0x5A, 0xD1, 0x3A, 0xFA, 0x3B, 0xF8, 0x74, 0x62, +- 0xA2, 0xD0, 0xFF, 0xFF, 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, +- 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, 0x00, 0x60, 0x40, 0xF3, 0xFF, 0xFF, 0xA0, 0xD1, +- 0x5A, 0xD1, 0x64, 0x45, 0x64, 0x44, 0xE3, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, +- 0xA0, 0x5A, 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, +- 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5A, 0x65, 0x40, 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, +- 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, 0xE9, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, +- 0xA0, 0x5A, 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, +- 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5A, 0x64, 0x47, 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5A, 0x64, 0x44, +- 0xEF, 0x7F, 0xA0, 0x5A, 0x08, 0x60, 0x00, 0xEA, 0x65, 0x44, 0x02, 0xA4, 0x60, 0x7F, 0xA0, 0x5A, +- 0x80, 0x60, 0x00, 0xEA, 0xA0, 0x60, 0x00, 0xEA, 0xD1, 0x60, 0x00, 0xEA, 0x66, 0x45, 0xAA, 0xF2, +- 0x19, 0x60, 0x3F, 0xF3, 0x24, 0x46, 0x61, 0x40, 0x08, 0x26, 0x02, 0x00, 0x61, 0x40, 0x80, 0x36, +- 0x12, 0xF2, 0x65, 0x46, 0x60, 0x40, 0x10, 0x26, 0x34, 0x00, 0x2C, 0x45, 0x17, 0xF2, 0x4B, 0xF1, +- 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x64, 0x45, 0x16, 0xA1, 0xB8, 0x60, 0x58, 0x4D, +- 0x15, 0x78, 0xFF, 0xFF, 0x7D, 0xF1, 0x01, 0xA4, 0xE0, 0x84, 0xE0, 0x84, 0x64, 0x40, 0x01, 0x2B, +- 0x06, 0xA4, 0x1B, 0xFA, 0xDA, 0xF3, 0x2C, 0x60, 0x7C, 0x65, 0x60, 0x40, 0x0B, 0x37, 0x00, 0x63, +- 0x0F, 0x37, 0x02, 0x63, 0x0A, 0x37, 0x04, 0x63, 0x0E, 0x37, 0x06, 0x63, 0x09, 0x37, 0x08, 0x63, +- 0x0D, 0x37, 0x0A, 0x63, 0x08, 0x37, 0x0C, 0x63, 0x0C, 0x37, 0x0E, 0x63, 0x28, 0xA3, 0x47, 0xD1, +- 0xD8, 0xA3, 0xD7, 0x83, 0x19, 0x60, 0x77, 0xF9, 0x47, 0xD1, 0x40, 0x67, 0xB0, 0x84, 0x1F, 0xFA, +- 0x58, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x36, 0x19, 0x00, 0x50, 0x36, 0x17, 0x00, +- 0x40, 0x36, 0x15, 0x00, 0x00, 0x36, 0x13, 0x00, 0x20, 0x36, 0x11, 0x00, 0xA0, 0x36, 0x0F, 0x00, +- 0xB0, 0x36, 0x0D, 0x00, 0xC0, 0x36, 0x0B, 0x00, 0xDA, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x0A, 0x37, +- 0x06, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0x80, 0x60, 0x00, 0x61, 0x60, 0x40, 0x04, 0x26, 0x00, 0x61, +- 0xDA, 0xF3, 0x2C, 0x60, 0x74, 0x65, 0x60, 0x40, 0x0A, 0x37, 0x00, 0x63, 0x14, 0x37, 0x02, 0x63, +- 0x37, 0x37, 0x04, 0x63, 0x6E, 0x37, 0x06, 0x63, 0x28, 0xA3, 0x47, 0xD1, 0xD8, 0xA3, 0xD7, 0x83, +- 0x19, 0x60, 0x77, 0xF9, 0x47, 0xD1, 0xFF, 0xFF, 0xB1, 0x84, 0x1F, 0xFA, 0xDA, 0xF1, 0x2C, 0x45, +- 0x64, 0x43, 0x17, 0xF2, 0x4B, 0xF1, 0xC4, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x63, 0x40, +- 0x37, 0x37, 0xE1, 0x81, 0x64, 0x45, 0xB8, 0x60, 0x58, 0x4D, 0x15, 0x78, 0xFF, 0xFF, 0xAE, 0x82, +- 0xFC, 0xA2, 0x0A, 0x03, 0x63, 0x40, 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, 0x04, 0x0D, 0x63, 0x44, +- 0x80, 0x7E, 0xDA, 0xFB, 0x61, 0x44, 0xDC, 0x84, 0x2B, 0xF0, 0x1B, 0xFA, 0x64, 0x44, 0x80, 0x27, +- 0x58, 0x00, 0x07, 0xF0, 0x66, 0x45, 0x64, 0x46, 0x12, 0xF2, 0x65, 0x46, 0x60, 0x40, 0x10, 0x2A, +- 0x31, 0x00, 0x16, 0xF2, 0x0F, 0xF0, 0xAC, 0x84, 0x2C, 0x45, 0x2C, 0x03, 0x4B, 0xF1, 0xC4, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x81, 0x63, 0x40, 0x37, 0x37, 0xE1, 0x81, 0x64, 0x45, 0x0F, 0xF0, +- 0xB8, 0x60, 0x58, 0x4D, 0x15, 0x78, 0xFF, 0xFF, 0xAE, 0x82, 0xFC, 0xA2, 0x0A, 0x03, 0x63, 0x40, +- 0x6E, 0x3B, 0x06, 0x00, 0x60, 0x41, 0x04, 0x0D, 0x80, 0x67, 0xB0, 0x84, 0x0F, 0xFA, 0x61, 0x44, +- 0xDC, 0x84, 0x1D, 0xFA, 0x1F, 0xF0, 0x01, 0x60, 0x3E, 0x65, 0x64, 0x40, 0x80, 0x27, 0x02, 0x00, +- 0x02, 0x60, 0x5E, 0x65, 0x1B, 0xF0, 0x26, 0x41, 0xE1, 0x81, 0xC5, 0x81, 0x44, 0x94, 0xC1, 0x81, +- 0x2B, 0xFA, 0x90, 0xFA, 0x26, 0x44, 0x2C, 0xF0, 0x0A, 0xA4, 0x66, 0x45, 0x24, 0x46, 0x92, 0xF2, +- 0x65, 0x46, 0x9F, 0xF0, 0x61, 0x40, 0x10, 0x2A, 0x05, 0x00, 0x60, 0xA4, 0x65, 0x40, 0x80, 0x2B, +- 0x60, 0xA4, 0x01, 0x00, 0x14, 0xA4, 0x64, 0x40, 0x01, 0x26, 0x00, 0x64, 0x60, 0x45, 0x2A, 0xF2, +- 0x39, 0xF0, 0x8F, 0xB0, 0x88, 0x3A, 0x04, 0x00, 0x64, 0x44, 0x60, 0xB0, 0x20, 0x36, 0x00, 0x65, +- 0x65, 0x44, 0x11, 0xFA, 0xDA, 0xF3, 0x13, 0xFA, 0x7C, 0x44, 0x1D, 0xFA, 0x0F, 0xF0, 0xFF, 0xFF, +- 0x64, 0x40, 0x01, 0x2A, 0x6F, 0x00, 0x7D, 0xF1, 0x19, 0x60, 0x7B, 0xF3, 0x64, 0x40, 0x01, 0x27, +- 0x03, 0x00, 0x60, 0x40, 0x02, 0x26, 0x14, 0x00, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x12, 0xF0, +- 0x19, 0x60, 0x7C, 0xF3, 0x63, 0x46, 0x64, 0x40, 0x10, 0x2A, 0x20, 0x00, 0x60, 0x40, 0x02, 0x26, +- 0x07, 0x00, 0x01, 0x26, 0x08, 0x00, 0x04, 0x26, 0x09, 0x00, 0x06, 0x61, 0x6E, 0x63, 0x08, 0x00, +- 0x02, 0x61, 0x14, 0x63, 0x05, 0x00, 0x00, 0x61, 0x0A, 0x63, 0x02, 0x00, 0x04, 0x61, 0x37, 0x63, +- 0x00, 0x64, 0x2C, 0x60, 0x9C, 0x65, 0x45, 0xD1, 0xD5, 0x81, 0x19, 0x60, 0x78, 0xF9, 0x2C, 0x60, +- 0x74, 0x65, 0x45, 0xD1, 0x1C, 0xFC, 0xB0, 0x84, 0x1E, 0xFA, 0x3C, 0x00, 0x60, 0x40, 0x10, 0x2A, +- 0x04, 0x00, 0x08, 0x61, 0x1E, 0x60, 0x0B, 0x63, 0x27, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x0A, 0x61, +- 0x16, 0x60, 0x0F, 0x63, 0x21, 0x00, 0x40, 0x2A, 0x04, 0x00, 0x0C, 0x61, 0x12, 0x60, 0x0A, 0x63, +- 0x1B, 0x00, 0x80, 0x2A, 0x04, 0x00, 0x0E, 0x61, 0x0E, 0x60, 0x0E, 0x63, 0x15, 0x00, 0x01, 0x2B, +- 0x04, 0x00, 0x10, 0x61, 0x0E, 0x60, 0x09, 0x63, 0x0F, 0x00, 0x02, 0x2B, 0x04, 0x00, 0x12, 0x61, +- 0x0A, 0x60, 0x0D, 0x63, 0x09, 0x00, 0x04, 0x2B, 0x04, 0x00, 0x14, 0x61, 0x0A, 0x60, 0x08, 0x63, +- 0x03, 0x00, 0x16, 0x61, 0x0A, 0x60, 0x0C, 0x63, 0x1E, 0xF0, 0x40, 0x67, 0x2C, 0x60, 0x9C, 0x65, +- 0x45, 0xD1, 0xD5, 0x81, 0x19, 0x60, 0x78, 0xF9, 0x2C, 0x60, 0x74, 0x65, 0x45, 0xD1, 0x1C, 0xFC, +- 0xB0, 0x84, 0x1E, 0xFA, 0xFF, 0xFF, 0x0D, 0xF2, 0x3E, 0xF0, 0x60, 0x47, 0xFF, 0xB4, 0x64, 0x41, +- 0x01, 0xB1, 0x01, 0x63, 0x17, 0x02, 0x60, 0x41, 0xFF, 0x22, 0x04, 0x00, 0xB8, 0x60, 0x58, 0x4F, +- 0x06, 0x78, 0xFF, 0xFF, 0x07, 0x60, 0xED, 0xFD, 0x19, 0x60, 0xCF, 0xF3, 0xFF, 0xFF, 0x60, 0x41, +- 0x01, 0x63, 0x61, 0x40, 0xFF, 0x22, 0x04, 0x00, 0xB8, 0x60, 0x58, 0x4F, 0x06, 0x78, 0xFF, 0xFF, +- 0x07, 0x60, 0xEE, 0xFD, 0x02, 0x64, 0x3B, 0xDB, 0xBF, 0x60, 0xE4, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0xFC, 0xFB, 0x07, 0xF0, 0x00, 0x64, 0xD0, 0x80, 0xA6, 0xF3, 0x0E, 0x03, 0xD0, 0x80, 0xFF, 0xFF, +- 0x0B, 0x03, 0x47, 0xF1, 0x07, 0xF0, 0x64, 0x40, 0x02, 0x26, 0x01, 0x00, 0x08, 0x00, 0x03, 0x12, +- 0xBE, 0x60, 0xA0, 0x78, 0xFF, 0xFF, 0xFC, 0x0A, 0xBF, 0x60, 0x00, 0x78, 0xFF, 0xFF, 0x87, 0xF0, +- 0xA6, 0xF3, 0x10, 0xF0, 0xD4, 0x80, 0xFF, 0xFF, 0x3D, 0x03, 0x66, 0x43, 0x65, 0x46, 0xFF, 0x67, +- 0x20, 0x85, 0x64, 0x5F, 0x40, 0x44, 0x15, 0xF0, 0x25, 0x44, 0xD0, 0x84, 0x03, 0xA4, 0x03, 0x0E, +- 0xE8, 0x84, 0xE8, 0x84, 0x04, 0x00, 0xFA, 0xA4, 0xE8, 0x84, 0xE8, 0x87, 0xC0, 0xBF, 0xC0, 0x84, +- 0x15, 0xFA, 0x40, 0x45, 0x14, 0xF0, 0x24, 0x44, 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, 0xC0, 0x84, 0x14, 0xFA, 0x60, 0x5C, 0x2F, 0x67, +- 0xD0, 0x80, 0x60, 0x45, 0x02, 0x28, 0x64, 0x45, 0x25, 0x5C, 0x8B, 0x67, 0xD0, 0x80, 0x60, 0x41, +- 0x02, 0x24, 0x64, 0x41, 0xD5, 0x84, 0x80, 0x65, 0xC4, 0x87, 0x01, 0x05, 0x00, 0x64, 0xFF, 0xB4, +- 0x0E, 0xFA, 0x63, 0x46, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x17, 0xF2, 0x63, 0x46, 0x60, 0x40, +- 0x00, 0x36, 0x2E, 0x00, 0x01, 0x36, 0x1E, 0x00, 0x03, 0x3A, 0x25, 0x00, 0x64, 0x46, 0x10, 0xF2, +- 0x11, 0xFA, 0x12, 0xF2, 0x00, 0x61, 0x60, 0x47, 0x00, 0x7F, 0x12, 0xFA, 0x97, 0xFA, 0x46, 0x44, +- 0x63, 0x46, 0xC2, 0x60, 0x58, 0x4E, 0x4C, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x00, 0x3A, 0x04, 0x00, +- 0xC2, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x96, 0xFC, +- 0x63, 0x46, 0x43, 0x00, 0x64, 0x46, 0x16, 0xF2, 0x00, 0x61, 0x20, 0x28, 0xFF, 0xA4, 0x97, 0xFA, +- 0x16, 0xFA, 0x63, 0x46, 0x3A, 0x00, 0x64, 0x46, 0x00, 0x61, 0x97, 0xFA, 0x63, 0x46, 0x35, 0x00, +- 0x07, 0xF0, 0x66, 0x41, 0x64, 0x46, 0x16, 0xF2, 0xFF, 0xFF, 0x20, 0x28, 0xFF, 0xA4, 0x16, 0xFA, +- 0x93, 0xF4, 0x12, 0xF2, 0x20, 0x28, 0xFF, 0xA3, 0x13, 0xFC, 0x61, 0x46, 0x63, 0x40, 0x00, 0x3A, +- 0x24, 0x00, 0xC2, 0x60, 0x58, 0x4E, 0x6D, 0x78, 0xFF, 0xFF, 0x61, 0x40, 0xFF, 0x36, 0x1D, 0x00, +- 0x66, 0x41, 0x64, 0x46, 0x12, 0xF2, 0x93, 0xF4, 0x61, 0x46, 0x20, 0x28, 0x16, 0x00, 0x44, 0x44, +- 0xC2, 0x60, 0x58, 0x4E, 0x4C, 0x78, 0xFF, 0xFF, 0x24, 0x5C, 0x65, 0x40, 0x00, 0x36, 0x06, 0x00, +- 0x66, 0x41, 0x64, 0x46, 0x01, 0x64, 0x17, 0xFA, 0x61, 0x46, 0x07, 0x00, 0x66, 0x43, 0x64, 0x46, +- 0xC2, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0x63, 0x46, 0xBF, 0x60, 0x00, 0x78, 0xFF, 0xFF, +- 0x07, 0xF0, 0x66, 0x43, 0x64, 0x46, 0x17, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xFF, 0x27, 0xFF, 0xFF, +- 0x00, 0x36, 0x07, 0x00, 0x01, 0x36, 0x1C, 0x00, 0x02, 0x36, 0x24, 0x00, 0x03, 0x36, 0x43, 0x00, +- 0xFF, 0xFF, 0x19, 0x60, 0xA9, 0xF1, 0x16, 0xF2, 0x43, 0x44, 0xD0, 0x80, 0x33, 0x60, 0x84, 0x61, +- 0x09, 0x03, 0xA1, 0xD1, 0x33, 0x60, 0x82, 0x63, 0xC0, 0x84, 0x16, 0xFA, 0xA3, 0xD3, 0xFF, 0xFF, +- 0x13, 0xFA, 0x39, 0x00, 0x96, 0xFC, 0xC2, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0x33, 0x00, +- 0x43, 0x44, 0xC2, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0xC1, 0xF3, 0x96, 0xFC, +- 0x13, 0xFA, 0x29, 0x00, 0x63, 0x46, 0x33, 0x60, 0x54, 0x63, 0xA3, 0xD3, 0x15, 0xF2, 0x60, 0x45, +- 0xD4, 0x80, 0x07, 0xF0, 0x0C, 0x03, 0x66, 0x41, 0x44, 0x44, 0x64, 0x46, 0x12, 0xF2, 0x61, 0x46, +- 0xC2, 0x60, 0x58, 0x4E, 0x4C, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x00, 0x3A, 0x19, 0x00, 0x66, 0x43, +- 0x24, 0x46, 0xC2, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0x12, 0xF2, 0x91, 0xF2, 0x90, 0xFA, +- 0x60, 0x5F, 0x12, 0xFA, 0x04, 0x00, 0xC2, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0x03, 0x64, +- 0x17, 0xFA, 0x63, 0x46, 0x05, 0x00, 0x24, 0x43, 0x02, 0x64, 0x17, 0xFA, 0x63, 0x46, 0x00, 0x00, +- 0x03, 0x64, 0x3B, 0xDB, 0xCA, 0xFE, 0x47, 0xF1, 0x01, 0x65, 0x32, 0x40, 0x04, 0x27, 0x11, 0x00, +- 0x2C, 0xF2, 0x64, 0x45, 0x02, 0x22, 0x0D, 0x00, 0x60, 0x40, 0x01, 0x26, 0x0A, 0x00, 0x2A, 0xF2, +- 0x39, 0xF0, 0x8F, 0xB0, 0x88, 0x3A, 0x77, 0x00, 0x64, 0x44, 0x60, 0xB0, 0x20, 0x36, 0x01, 0x00, +- 0x72, 0x00, 0x14, 0xF2, 0x65, 0x40, 0x01, 0x26, 0x0C, 0x00, 0x60, 0x45, 0x05, 0x64, 0x3B, 0xDB, +- 0x65, 0x44, 0xCC, 0x85, 0x2C, 0x60, 0xD0, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xF0, 0x78, 0xB5, 0xF1, +- 0x50, 0x00, 0x60, 0x41, 0x2A, 0xF0, 0x00, 0x60, 0x0C, 0x64, 0xA0, 0x84, 0x04, 0x36, 0x02, 0x00, +- 0x0C, 0x3A, 0x01, 0x00, 0x46, 0x00, 0x61, 0x45, 0x60, 0x43, 0x2C, 0x60, 0xD0, 0x64, 0xF1, 0x60, +- 0x78, 0x41, 0xF0, 0x78, 0xB5, 0xF1, 0x63, 0x40, 0x08, 0x36, 0x01, 0x00, 0x3A, 0x00, 0x14, 0xF2, +- 0x1C, 0x65, 0x60, 0x41, 0x00, 0x63, 0xCD, 0x81, 0xC7, 0x83, 0xFD, 0x02, 0x3F, 0xF0, 0x2C, 0xF2, +- 0xC3, 0x83, 0x60, 0x40, 0x01, 0x2A, 0x0D, 0x00, 0x2C, 0x60, 0xCE, 0x64, 0xF1, 0x60, 0x78, 0x41, +- 0xE4, 0x78, 0xB5, 0xF1, 0x2C, 0x60, 0xD4, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xEF, 0x78, 0x63, 0x45, +- 0x20, 0x00, 0x2C, 0x60, 0xCC, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x2C, 0x60, +- 0xD2, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xEF, 0x78, 0x63, 0x45, 0x15, 0xF2, 0xFF, 0xFF, 0x0F, 0xB4, +- 0x00, 0xA8, 0x01, 0xA8, 0x0E, 0x03, 0x07, 0x03, 0x2C, 0x60, 0xDA, 0x64, 0xF1, 0x60, 0x78, 0x41, +- 0xE4, 0x78, 0xB5, 0xF1, 0x06, 0x00, 0x2C, 0x60, 0xD8, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, +- 0xB5, 0xF1, 0x04, 0x64, 0x3B, 0xDB, 0x25, 0x60, 0xEC, 0x64, 0x13, 0x60, 0x0A, 0xFB, 0x3C, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x5C, 0x5C, 0xFC, 0xFC, 0xCE, 0xFE, +- 0xB8, 0x60, 0x37, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x50, 0xA8, 0x02, 0x7C, 0x09, 0x03, +- 0x0F, 0xF0, 0x15, 0xF2, 0x64, 0x41, 0x01, 0x2A, 0x02, 0x00, 0xCD, 0xF1, 0x02, 0x00, 0xCC, 0xF1, +- 0xFF, 0xFF, 0x64, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x15, 0xFA, 0x2D, 0x07, 0x61, 0x40, 0x01, 0x2A, +- 0x08, 0x00, 0x16, 0x60, 0x80, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, +- 0x07, 0x00, 0x16, 0x60, 0x81, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, +- 0x2A, 0xF0, 0x08, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x00, 0x64, 0x48, 0xFB, 0x19, 0x60, 0xA3, 0xF3, +- 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0C, 0x00, 0x3C, 0x46, 0x3E, 0xF2, 0x40, 0x60, 0x00, 0x65, +- 0xF0, 0x84, 0xA4, 0x84, 0x3D, 0xFA, 0x2A, 0xF2, 0xBF, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x2A, 0xFA, +- 0xBA, 0x60, 0x02, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x49, 0xFB, 0x2C, 0x60, 0xDA, 0x64, 0xF1, 0x60, +- 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x2C, 0x60, 0xDC, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, +- 0xB5, 0xF1, 0x27, 0x44, 0xF7, 0xB4, 0x40, 0x47, 0x23, 0xF0, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDA, +- 0x98, 0x01, 0xC0, 0x60, 0x5F, 0x78, 0xFF, 0xFF, 0x21, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0x01, 0x63, +- 0xC4, 0xB4, 0x31, 0xFB, 0x32, 0xFD, 0xC0, 0x60, 0x14, 0x62, 0x42, 0x40, 0xA0, 0x4C, 0x40, 0xBC, +- 0x7D, 0xB4, 0xA0, 0x51, 0xA0, 0xFE, 0x1A, 0xFF, 0x25, 0x60, 0xE0, 0x64, 0x08, 0xF0, 0x07, 0xF0, +- 0xD0, 0x80, 0x25, 0x60, 0xE6, 0x62, 0x13, 0x02, 0xA2, 0xD3, 0x01, 0x63, 0xAC, 0x86, 0x07, 0xF2, +- 0x0E, 0x03, 0xD0, 0x80, 0x09, 0xF2, 0xFA, 0x02, 0x23, 0xFC, 0x25, 0x60, 0xEC, 0x64, 0x13, 0x60, +- 0x0A, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x3C, 0x46, +- 0x06, 0x64, 0xA1, 0xFF, 0x49, 0xFB, 0x83, 0x3E, 0x31, 0xF3, 0x87, 0x60, 0x80, 0x61, 0x1D, 0xF0, +- 0x60, 0x40, 0x01, 0x2A, 0x0F, 0x00, 0xFE, 0xB4, 0x31, 0xFB, 0x00, 0x64, 0x49, 0xFB, 0x01, 0x64, +- 0x47, 0xFB, 0x00, 0x71, 0x05, 0x64, 0x64, 0x5F, 0x0D, 0xFA, 0x40, 0x64, 0x3B, 0xDB, 0xC0, 0x60, +- 0x5F, 0x78, 0xFF, 0xFF, 0x02, 0x2A, 0x18, 0x00, 0xD1, 0x91, 0x8D, 0xE2, 0x41, 0x64, 0x3B, 0xDB, +- 0x31, 0xF3, 0x33, 0x60, 0xA6, 0x63, 0xFD, 0xB4, 0x31, 0xFB, 0xA3, 0xD3, 0x02, 0x63, 0x60, 0x5C, +- 0x0D, 0xF2, 0x47, 0xFD, 0xFF, 0xB5, 0x60, 0x47, 0xFF, 0xB4, 0xD0, 0x80, 0xDC, 0x84, 0x1F, 0x03, +- 0x60, 0x47, 0xB4, 0x84, 0x0D, 0xFA, 0x1B, 0x00, 0x08, 0x2A, 0x07, 0x00, 0x42, 0x64, 0x3B, 0xDB, +- 0x31, 0xF3, 0xFF, 0xFF, 0xF7, 0xB4, 0x31, 0xFB, 0x12, 0x00, 0x10, 0x2A, 0x09, 0x00, 0x43, 0x64, +- 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xEF, 0xB4, 0x31, 0xFB, 0xBF, 0x60, 0xE4, 0x78, 0xFF, 0xFF, +- 0x44, 0x64, 0x3B, 0xDB, 0x31, 0xF3, 0xFF, 0xFF, 0xDF, 0xB4, 0x31, 0xFB, 0x00, 0x00, 0x2A, 0x64, +- 0x3B, 0xDB, 0xB7, 0x60, 0xF7, 0x64, 0x40, 0x40, 0xBD, 0x60, 0xD7, 0x78, 0xFF, 0xFF, 0x0E, 0x60, +- 0xDF, 0xF3, 0xFF, 0xFF, 0x02, 0xB5, 0x04, 0xB5, 0x04, 0x03, 0x03, 0x03, 0xC1, 0x60, 0x70, 0x78, +- 0xFF, 0xFF, 0x31, 0x40, 0x01, 0x26, 0x16, 0x00, 0xA0, 0x4C, 0x49, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, +- 0x0E, 0x60, 0xDF, 0xF3, 0xFF, 0xFF, 0x02, 0xB5, 0x04, 0xBC, 0x09, 0x03, 0x60, 0x40, 0x01, 0x26, +- 0xED, 0xE2, 0xFE, 0xB4, 0xA2, 0xDB, 0xA0, 0x4C, 0x7D, 0xB4, 0xA0, 0x51, 0x03, 0x00, 0xA0, 0x4C, +- 0x6D, 0xB4, 0xA0, 0x51, 0xDB, 0xF3, 0xFF, 0xFF, 0xFD, 0xA0, 0xFF, 0xFF, 0x08, 0x24, 0x59, 0x00, +- 0x31, 0x40, 0x04, 0x2A, 0x38, 0x00, 0x01, 0x64, 0x19, 0x60, 0xF4, 0xFB, 0x6C, 0xF3, 0x73, 0xF3, +- 0xCC, 0x83, 0x6C, 0xFD, 0xCC, 0x84, 0x73, 0xFB, 0x1E, 0x02, 0x31, 0x40, 0x02, 0x2A, 0x12, 0x00, +- 0x6E, 0xF3, 0x6F, 0xF1, 0xCC, 0x84, 0x6E, 0xFB, 0x0D, 0x02, 0x6E, 0xF9, 0x31, 0x44, 0x08, 0xBC, +- 0x40, 0x51, 0x71, 0xF3, 0x70, 0xF1, 0x00, 0xB8, 0x64, 0x45, 0x01, 0x03, 0x67, 0x45, 0x65, 0x50, +- 0xCC, 0x84, 0x72, 0xFB, 0x16, 0x60, 0xAC, 0xF3, 0x6D, 0xF1, 0x00, 0xB8, 0x73, 0xF9, 0x03, 0x03, +- 0x85, 0xF3, 0x6C, 0xFB, 0x04, 0x00, 0x6C, 0xF3, 0x85, 0xF1, 0x0D, 0x1B, 0x6C, 0xF9, 0x31, 0x40, +- 0x01, 0x2A, 0x09, 0x00, 0x9D, 0xFE, 0x07, 0x05, 0xBA, 0xFE, 0x08, 0x64, 0x13, 0x60, 0x16, 0xFB, +- 0x2D, 0xFF, 0xFF, 0xFF, 0xA3, 0xFE, 0x32, 0x40, 0x80, 0x2A, 0x12, 0x00, 0x31, 0x40, 0x04, 0x2A, +- 0x0F, 0x00, 0x16, 0x60, 0xAC, 0xF3, 0x6C, 0xF1, 0x03, 0x1B, 0x31, 0x40, 0x02, 0x2A, 0x06, 0x00, +- 0x73, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x07, 0x60, 0x5C, 0x19, 0x60, 0xF5, 0xF9, +- 0x00, 0x64, 0x19, 0x60, 0xF4, 0xFB, 0x0E, 0x60, 0x37, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0xFF, 0x2B, +- 0xA2, 0xDB, 0xCF, 0xF1, 0x07, 0x60, 0xE9, 0xF3, 0x64, 0x40, 0x02, 0x3A, 0x3A, 0x00, 0x0A, 0x60, +- 0x18, 0xF1, 0x10, 0xB4, 0x90, 0x80, 0xFF, 0xFF, 0x34, 0x03, 0x0A, 0x60, 0x18, 0xFB, 0x01, 0x63, +- 0x60, 0x40, 0x10, 0x22, 0x00, 0x63, 0x08, 0x60, 0xC1, 0xFD, 0x08, 0x60, 0xC5, 0xFD, 0x08, 0x60, +- 0xC9, 0xFD, 0x08, 0x60, 0xCD, 0xFD, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x23, 0x21, 0x00, +- 0x0B, 0x36, 0x07, 0x00, 0x0C, 0x36, 0x05, 0x00, 0x0D, 0x36, 0x03, 0x00, 0x0E, 0x36, 0x01, 0x00, +- 0x18, 0x00, 0xDB, 0xF3, 0x01, 0x63, 0x0E, 0x60, 0x36, 0xFD, 0x60, 0x40, 0x03, 0x3A, 0x08, 0x00, +- 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x09, 0x00, +- 0x04, 0x3A, 0x07, 0x00, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x10, 0x64, 0x3B, 0xDB, 0x7E, 0xF3, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xC4, 0x93, 0xC9, 0xFE, 0x49, 0xF3, 0x3C, 0x46, 0x25, 0x18, 0xCC, 0x84, 0x49, 0xFB, +- 0x22, 0x02, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0xFC, 0xFC, 0x00, 0x64, 0x5C, 0x5C, 0x32, 0xFB, +- 0x82, 0xFF, 0x5C, 0x47, 0x84, 0xFF, 0x62, 0xFF, 0x16, 0x60, 0x7E, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, +- 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, 0x23, 0xF0, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDA, 0x25, 0x60, +- 0xEC, 0x64, 0x13, 0x60, 0x0A, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xC1, 0xFE, 0xCE, 0xFE, 0x69, 0xF3, 0xFF, 0xFF, 0x60, 0x41, 0xFD, 0xB4, 0xA2, 0xDB, +- 0x61, 0x44, 0x01, 0xB0, 0x02, 0xB0, 0x0B, 0x03, 0x0A, 0x02, 0x9D, 0xFE, 0x08, 0x04, 0x1C, 0x60, +- 0xCE, 0x64, 0x13, 0x60, 0x20, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x07, 0x00, +- 0x7E, 0xF3, 0x73, 0x45, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xC4, 0x93, 0x1D, 0x60, +- 0xBA, 0x63, 0xA3, 0xD3, 0xAD, 0x49, 0x20, 0xB5, 0x08, 0xB1, 0x22, 0x03, 0xE1, 0x81, 0x10, 0xB5, +- 0x95, 0x81, 0x60, 0x41, 0x18, 0x02, 0x1D, 0x60, 0xBC, 0x7C, 0xA4, 0xD3, 0xFF, 0xFF, 0xCC, 0x84, +- 0xA4, 0xDB, 0x16, 0x02, 0x05, 0x64, 0xA4, 0xDB, 0x61, 0x44, 0x07, 0xB4, 0xFF, 0xFF, 0x10, 0x02, +- 0x08, 0xB1, 0xE1, 0x81, 0x95, 0x81, 0xA3, 0xD3, 0x0B, 0x03, 0x08, 0xAC, 0x01, 0xBC, 0xA3, 0xDB, +- 0xFF, 0xFF, 0x13, 0xFF, 0x05, 0x00, 0x10, 0xAC, 0xA3, 0xDB, 0x05, 0x7C, 0x0E, 0x60, 0xDE, 0xF9, +- 0xB8, 0x60, 0x03, 0x78, 0xFF, 0xFF, 0x46, 0xF3, 0x45, 0xF1, 0x04, 0x1B, 0x64, 0x44, 0x02, 0x1B, +- 0x07, 0x60, 0xED, 0xF3, 0x45, 0xFB, 0x00, 0x63, 0x46, 0xFD, 0x60, 0x41, 0x25, 0x64, 0x3B, 0xDB, +- 0x27, 0x44, 0xEF, 0xB4, 0x40, 0x47, 0x00, 0xB9, 0x71, 0x40, 0x80, 0x27, 0x01, 0x12, 0x27, 0x03, +- 0xC1, 0x60, 0xC5, 0x62, 0x84, 0xFF, 0x42, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, +- 0xA0, 0x51, 0x2D, 0x0A, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x27, 0x0A, +- 0x71, 0x40, 0x80, 0x27, 0xF7, 0x12, 0x45, 0xF3, 0x48, 0x02, 0x11, 0x18, 0x1B, 0x60, 0xEE, 0xF3, +- 0x1B, 0x60, 0xEF, 0xF3, 0x07, 0x18, 0x06, 0x18, 0xAC, 0x4C, 0x80, 0x26, 0x03, 0x00, 0x00, 0x64, +- 0x45, 0xFB, 0x05, 0x00, 0x45, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0x45, 0xFB, 0xE3, 0x02, 0x06, 0x0A, +- 0xA0, 0x4C, 0xFB, 0xB4, 0xA0, 0x51, 0xA4, 0x60, 0x58, 0x78, 0xFF, 0xFF, 0x84, 0xFF, 0xC1, 0x60, +- 0xA3, 0x64, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x14, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0xB0, 0x60, +- 0x9E, 0x78, 0xFF, 0xFF, 0x3C, 0x44, 0xAC, 0x80, 0x32, 0xF1, 0x25, 0x03, 0x64, 0x40, 0x07, 0x22, +- 0x22, 0x00, 0xA4, 0x60, 0x36, 0x78, 0xFF, 0xFF, 0xA0, 0x4C, 0x1C, 0xBC, 0xDF, 0xB4, 0xA0, 0x51, +- 0x31, 0x40, 0x08, 0x2A, 0xEF, 0x01, 0x72, 0xF3, 0x70, 0xF1, 0x00, 0xA0, 0xDC, 0x80, 0x05, 0x03, +- 0x08, 0x03, 0xCC, 0x84, 0x72, 0xFB, 0x67, 0x50, 0x08, 0x00, 0xCC, 0x84, 0x72, 0xFB, 0x64, 0x50, +- 0x04, 0x00, 0x31, 0x44, 0xF7, 0xB4, 0x40, 0x51, 0x06, 0x00, 0x28, 0x64, 0x3A, 0xDB, 0xA0, 0x4C, +- 0x30, 0xBC, 0xF3, 0xB4, 0xA0, 0x51, 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x28, 0x64, 0x3B, 0xDB, +- 0x07, 0x60, 0xEE, 0xF3, 0x32, 0x40, 0x02, 0x27, 0x16, 0x00, 0x46, 0xFB, 0x14, 0x18, 0xC2, 0x60, +- 0x33, 0x64, 0x84, 0xFF, 0x40, 0x42, 0x82, 0xFF, 0xA0, 0x4C, 0x15, 0xBC, 0xF7, 0xB4, 0xA0, 0x51, +- 0xA1, 0xFF, 0xFF, 0xFF, 0x81, 0x3E, 0x70, 0x44, 0xAC, 0x80, 0x46, 0xF3, 0xB8, 0x0A, 0xDD, 0x02, +- 0xCC, 0x84, 0x46, 0xFB, 0xF5, 0x02, 0x84, 0xFF, 0xC2, 0x60, 0x45, 0x64, 0x40, 0x42, 0x82, 0xFF, +- 0x27, 0x44, 0x08, 0xBC, 0x40, 0x47, 0xF9, 0xE1, 0x04, 0x00, 0x78, 0xE1, 0x31, 0x40, 0x01, 0x26, +- 0xF9, 0xE1, 0xA4, 0x60, 0x2D, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0xAB, 0xF1, 0x60, 0x45, 0x33, 0x60, +- 0x6A, 0x61, 0xC5, 0x83, 0xA3, 0xD3, 0xFF, 0xFF, 0x60, 0x41, 0x66, 0x45, 0x24, 0x46, 0x0E, 0xF2, +- 0x65, 0x46, 0x64, 0x45, 0xD5, 0x81, 0x61, 0x45, 0x00, 0x7F, 0xD4, 0x80, 0x64, 0x43, 0x08, 0x04, +- 0xE3, 0x83, 0x63, 0x45, 0xC5, 0x81, 0x61, 0x45, 0xD4, 0x80, 0x02, 0x65, 0x03, 0x07, 0x03, 0x00, +- 0x00, 0x65, 0x01, 0x00, 0x01, 0x65, 0x2E, 0x58, 0xFF, 0xFF, 0x66, 0x43, 0x64, 0x46, 0x8F, 0xF0, +- 0x12, 0xF2, 0x91, 0xF2, 0x60, 0x40, 0x10, 0x36, 0x05, 0x00, 0x12, 0x36, 0x08, 0x00, 0x0C, 0x36, +- 0x0B, 0x00, 0x0F, 0x00, 0x40, 0x61, 0xA5, 0x80, 0x0A, 0x64, 0x13, 0x02, 0xF3, 0x01, 0x10, 0x61, +- 0xA5, 0x80, 0x0E, 0x64, 0x0E, 0x02, 0xEE, 0x01, 0x08, 0x61, 0xA5, 0x80, 0x10, 0x64, 0x09, 0x02, +- 0xE9, 0x01, 0xE1, 0x81, 0xA5, 0x80, 0x03, 0x05, 0xC8, 0x84, 0x03, 0x02, 0xE3, 0x01, 0xFF, 0x61, +- 0x02, 0x00, 0x12, 0xFA, 0x91, 0xFA, 0x63, 0x46, 0x2E, 0x58, 0xFF, 0xFF, 0x8F, 0xF0, 0x12, 0xF2, +- 0x91, 0xF2, 0x60, 0x40, 0x0A, 0x36, 0x05, 0x00, 0x0E, 0x36, 0x08, 0x00, 0x10, 0x36, 0x0B, 0x00, +- 0x0F, 0x00, 0x08, 0x61, 0xA5, 0x80, 0x10, 0x7E, 0x11, 0x02, 0xF3, 0x01, 0x04, 0x61, 0xA5, 0x80, +- 0x12, 0x7E, 0x0C, 0x02, 0xEE, 0x01, 0x20, 0x61, 0xA5, 0x80, 0x0C, 0x7E, 0x07, 0x02, 0xE9, 0x01, +- 0xE9, 0x81, 0xA5, 0x80, 0x05, 0x05, 0xD8, 0x84, 0x01, 0x02, 0xE3, 0x01, 0x12, 0xFA, 0x91, 0xFA, +- 0x2E, 0x58, 0xFF, 0xFF, 0x28, 0x40, 0x08, 0x3A, 0x06, 0x00, 0x04, 0x60, 0x40, 0x62, 0x3D, 0x60, +- 0x58, 0x4D, 0x3B, 0x78, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2B, 0x50, 0x00, +- 0x28, 0x40, 0x08, 0x3A, 0x4D, 0x00, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x19, 0x60, +- 0x52, 0xFB, 0x7D, 0xF1, 0x2B, 0x60, 0x82, 0x63, 0x64, 0x40, 0x01, 0x27, 0x3C, 0xA3, 0x29, 0x40, +- 0x40, 0x2B, 0x1E, 0xA3, 0xBD, 0xD1, 0x63, 0x45, 0x44, 0x4E, 0x0E, 0x61, 0xBD, 0xD1, 0xCD, 0x81, +- 0xD0, 0x80, 0x01, 0x03, 0xFB, 0x04, 0xCB, 0x83, 0x19, 0x60, 0x55, 0xF3, 0x39, 0xF1, 0xD7, 0x83, +- 0xEB, 0x83, 0x2E, 0x41, 0x5D, 0x93, 0xDF, 0x83, 0x19, 0x60, 0x51, 0xFD, 0x19, 0x60, 0x50, 0xFB, +- 0x53, 0x93, 0xDF, 0x80, 0x10, 0x03, 0x38, 0xF3, 0xCF, 0x83, 0x08, 0x03, 0xDF, 0x83, 0x0B, 0x02, +- 0xDF, 0x83, 0xDC, 0x84, 0xF0, 0xA0, 0x38, 0xFB, 0x06, 0x03, 0x03, 0x00, 0xCC, 0x84, 0x38, 0xFB, +- 0x02, 0x03, 0x00, 0x63, 0x02, 0x00, 0x08, 0x64, 0x38, 0xFB, 0xE3, 0x80, 0xFB, 0x83, 0xC3, 0x83, +- 0x63, 0x44, 0xFC, 0xA0, 0x02, 0x0E, 0x08, 0x07, 0x08, 0x00, 0x04, 0xA4, 0xFF, 0xFF, 0x05, 0x0D, +- 0xFC, 0x64, 0xFF, 0x7F, 0x60, 0x43, 0x01, 0x00, 0x04, 0x63, 0x39, 0xFD, 0x19, 0x60, 0x54, 0xFD, +- 0x2F, 0x58, 0xFF, 0xFF, 0x19, 0x60, 0x74, 0xF3, 0x40, 0x4E, 0x60, 0x46, 0x2F, 0xDB, 0x44, 0x44, +- 0xA1, 0xD3, 0xD9, 0x81, 0x48, 0x94, 0x24, 0x5C, 0xD0, 0x9C, 0x66, 0x42, 0x04, 0x06, 0xD2, 0x9C, +- 0x2F, 0xD9, 0x64, 0x46, 0x24, 0x44, 0xE0, 0x84, 0x44, 0xD3, 0xA3, 0xDB, 0xFF, 0xB4, 0x60, 0x5C, +- 0x66, 0x44, 0x22, 0xA4, 0xD0, 0x84, 0xE0, 0xA0, 0x02, 0x0D, 0x00, 0x64, 0x02, 0x00, 0x01, 0x04, +- 0x1F, 0x64, 0xA2, 0xD3, 0x60, 0x5C, 0x64, 0x5E, 0x60, 0x47, 0x2F, 0xD1, 0x28, 0xA3, 0xA3, 0xD9, +- 0xD8, 0xA3, 0x2E, 0x42, 0x4E, 0x8E, 0xBD, 0xDB, 0xDB, 0x02, 0x2D, 0x58, 0xFF, 0xFF, 0x43, 0xFF, +- 0x39, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x84, 0x3E, 0xFB, 0x01, 0x3D, 0x44, 0x00, 0xA8, 0xFF, 0xFF, +- 0x03, 0x02, 0x40, 0xFF, 0x44, 0xFF, 0xF4, 0x01, 0xA0, 0x4C, 0x3D, 0x46, 0x2A, 0xF2, 0x46, 0x4D, +- 0x92, 0xFC, 0x10, 0x25, 0x12, 0x00, 0x09, 0xE1, 0xA1, 0xFF, 0x2D, 0x46, 0x0F, 0xF2, 0x01, 0x29, +- 0x06, 0x00, 0x2A, 0xF0, 0x40, 0xFF, 0x64, 0x40, 0x40, 0x2B, 0x08, 0xBC, 0x02, 0xBC, 0x0F, 0xFA, +- 0x08, 0x25, 0xDD, 0x01, 0xCB, 0xFE, 0x5C, 0x5D, 0xDB, 0x01, 0x44, 0xFF, 0x31, 0xF2, 0x1D, 0x60, +- 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, +- 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, +- 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, +- 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, +- 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x07, 0xFC, 0x3F, 0xF2, 0x09, 0x60, 0xB0, 0x65, +- 0xD4, 0x80, 0x2A, 0xF2, 0xC0, 0x05, 0x08, 0x25, 0xAA, 0x01, 0x5C, 0x4B, 0x0C, 0x60, 0xEA, 0x61, +- 0xA1, 0xDF, 0x2D, 0x46, 0x3B, 0xF2, 0xA6, 0xF1, 0x87, 0xF4, 0x60, 0x40, 0x20, 0x2B, 0xC1, 0x00, +- 0xD3, 0x80, 0x2C, 0xF0, 0xB0, 0x03, 0x07, 0xF4, 0x64, 0x40, 0x01, 0x26, 0xA6, 0xF5, 0xBA, 0xF4, +- 0x2D, 0x46, 0x04, 0x64, 0x04, 0xB3, 0x22, 0xF0, 0x03, 0x03, 0xC5, 0x60, 0xE2, 0x78, 0xFF, 0xFF, +- 0x10, 0x64, 0xB0, 0x9C, 0x3B, 0xF2, 0x22, 0xF8, 0x60, 0x47, 0xC0, 0xB7, 0x02, 0xFE, 0xF0, 0x84, +- 0xF0, 0x84, 0xF0, 0x84, 0x00, 0xA8, 0x40, 0x4A, 0x17, 0x03, 0xE0, 0x81, 0x61, 0x43, 0x42, 0xFE, +- 0x00, 0x64, 0xF0, 0x84, 0xFE, 0x1F, 0x40, 0x4A, 0xE1, 0x84, 0xE0, 0x84, 0x2D, 0x46, 0x07, 0xF4, +- 0xE0, 0x81, 0x3B, 0xF0, 0x2A, 0x47, 0x0C, 0x60, 0x38, 0x63, 0xA0, 0x84, 0x47, 0x9C, 0x10, 0x03, +- 0x7C, 0x44, 0x00, 0x60, 0xB2, 0x63, 0x1C, 0x00, 0x07, 0xF4, 0x3B, 0xF0, 0x66, 0x44, 0x64, 0x40, +- 0x80, 0x2B, 0x06, 0x00, 0x00, 0x60, 0x78, 0x7C, 0x00, 0x60, 0xA2, 0x63, 0x43, 0x4C, 0x10, 0x00, +- 0x2D, 0x46, 0xC5, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0x2D, 0x46, 0x22, 0xF2, 0x10, 0x60, 0x00, 0x7C, +- 0xB0, 0x84, 0x22, 0xFA, 0x32, 0x40, 0x04, 0x26, 0x25, 0x00, 0xC5, 0x60, 0xD5, 0x78, 0xFF, 0xFF, +- 0xED, 0xFB, 0xEE, 0xF9, 0xEF, 0xFD, 0xAD, 0x46, 0x3D, 0xF2, 0xAD, 0x46, 0xA3, 0xD0, 0xAD, 0x46, +- 0xD0, 0x80, 0x3C, 0xF2, 0xAD, 0x46, 0x02, 0x03, 0x15, 0x07, 0xE6, 0x04, 0x5B, 0xD0, 0xAD, 0x46, +- 0xD0, 0x80, 0x3A, 0xF2, 0x03, 0x03, 0xAD, 0x46, 0x0D, 0x07, 0xDE, 0x04, 0x3A, 0xF0, 0xAD, 0x46, +- 0x5B, 0xD0, 0x64, 0x44, 0xD0, 0x80, 0x2B, 0x44, 0x05, 0x07, 0xD6, 0x03, 0xD0, 0x84, 0x10, 0xA4, +- 0xFF, 0xFF, 0x00, 0x07, 0xEE, 0xF3, 0xED, 0xF5, 0xFE, 0xA4, 0x0F, 0x60, 0xBE, 0x61, 0x0E, 0x63, +- 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x2D, 0x46, 0x8B, 0xFF, 0x2D, 0x46, 0x22, 0xF2, 0x20, 0x60, +- 0x00, 0x7C, 0xB0, 0x84, 0x22, 0xFA, 0x0F, 0x60, 0xB0, 0x64, 0xC9, 0x60, 0x58, 0x4F, 0x56, 0x78, +- 0xFF, 0xFF, 0x3F, 0xF2, 0x00, 0x60, 0x18, 0x70, 0x18, 0x71, 0x20, 0x72, 0x60, 0x53, 0x88, 0x75, +- 0x00, 0xF2, 0x09, 0xE1, 0x60, 0x50, 0x12, 0x71, 0x6E, 0x72, 0x83, 0x75, 0xA1, 0xFF, 0xFF, 0xFF, +- 0x08, 0x25, 0x1D, 0x00, 0x40, 0xFF, 0x02, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x75, 0x40, 0x03, 0x2A, +- 0x03, 0x00, 0x80, 0x75, 0x0A, 0x64, 0x0B, 0x00, 0x80, 0x75, 0x1B, 0xF3, 0x8B, 0xFF, 0x02, 0x60, +- 0x00, 0x75, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x75, 0xDC, 0x84, 0xA2, 0xDB, 0x02, 0x64, 0x98, 0xFF, +- 0x2D, 0x46, 0x0F, 0xF0, 0xFF, 0xFF, 0xB0, 0x84, 0xA2, 0xDA, 0x88, 0xFF, 0x0B, 0x01, 0x8B, 0xFF, +- 0x02, 0x60, 0x00, 0x75, 0xFF, 0xFF, 0x02, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xC5, 0x60, 0xBB, 0x78, +- 0xFF, 0xFF, 0x22, 0xF0, 0x22, 0x64, 0xB0, 0x84, 0x22, 0xFA, 0x3A, 0xF0, 0xFF, 0xFF, 0x64, 0x44, +- 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5B, 0x64, 0x44, 0xE2, 0x7F, +- 0xA0, 0x5B, 0x64, 0x47, 0x7C, 0x5F, 0xE8, 0x84, 0xE8, 0x85, 0x0D, 0x60, 0x00, 0x64, 0x44, 0xD3, +- 0x5A, 0xD1, 0x03, 0x1B, 0xC5, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0x60, 0x45, 0x64, 0x44, 0xE3, 0x7F, +- 0xA0, 0x5B, 0x64, 0x47, 0xE4, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xE5, 0x7F, 0xA0, 0x5B, +- 0x64, 0x47, 0xE6, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xE7, 0x7F, 0xA0, 0x5B, 0x65, 0x40, +- 0x0D, 0x3A, 0x1C, 0x00, 0x64, 0x47, 0xE8, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xE9, 0x7F, +- 0xA0, 0x5B, 0x64, 0x47, 0xEA, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xEB, 0x7F, 0xA0, 0x5B, +- 0x64, 0x47, 0xEC, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xED, 0x7F, 0xA0, 0x5B, 0x64, 0x47, +- 0xEE, 0x7F, 0x5A, 0xD1, 0xA0, 0x5B, 0x64, 0x44, 0xEF, 0x7F, 0xA0, 0x5B, 0x65, 0x44, 0xD8, 0x84, +- 0x08, 0x25, 0x25, 0x00, 0x60, 0x7F, 0xA0, 0x5B, 0x80, 0x60, 0x00, 0xEB, 0xA0, 0x60, 0x00, 0xEB, +- 0xD1, 0x60, 0x00, 0xEB, 0x22, 0xF2, 0x20, 0x60, 0x00, 0x7C, 0xB0, 0x84, 0x22, 0xFA, 0x3F, 0xF2, +- 0x3B, 0xF0, 0x60, 0x43, 0xFC, 0xA4, 0x64, 0x40, 0x20, 0x2B, 0x04, 0x00, 0x08, 0xA4, 0x3F, 0xFA, +- 0x08, 0xA3, 0xF8, 0xA3, 0x3F, 0xFA, 0x0A, 0xE1, 0xB3, 0xFF, 0x9A, 0xFF, 0xCB, 0x83, 0x00, 0xF4, +- 0x10, 0x62, 0x6C, 0x61, 0x0E, 0xA3, 0xAB, 0x84, 0xF2, 0xA3, 0xA1, 0xFF, 0x09, 0x00, 0xDA, 0x00, +- 0x00, 0xF4, 0x81, 0xF2, 0xFC, 0x18, 0x02, 0x62, 0xC9, 0x81, 0xAB, 0x84, 0x01, 0x00, 0xA2, 0xDC, +- 0x7A, 0xD4, 0xFD, 0x1C, 0xA2, 0xDC, 0x08, 0x25, 0xCE, 0x00, 0xF2, 0x1D, 0x41, 0x44, 0x7C, 0xA8, +- 0xD9, 0x81, 0xEE, 0x03, 0xFF, 0xB1, 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, 0xFF, 0xFF, 0x64, 0x40, +- 0x20, 0x27, 0x04, 0x00, 0x08, 0x25, 0xBF, 0x00, 0x7B, 0x1E, 0x6F, 0x00, 0x08, 0x25, 0xBB, 0x00, +- 0x40, 0xFF, 0x42, 0x42, 0x46, 0x43, 0x06, 0x1E, 0x04, 0x02, 0x00, 0xF4, 0x02, 0x62, 0x42, 0x42, +- 0x46, 0x43, 0x01, 0xA2, 0x63, 0x45, 0x01, 0xA2, 0x62, 0x43, 0x46, 0x4C, 0xC6, 0x60, 0x58, 0x4F, +- 0x87, 0x78, 0xFF, 0xFF, 0x0A, 0xE1, 0x9A, 0xFF, 0x2D, 0x46, 0x12, 0xF2, 0x3B, 0xF0, 0x33, 0x1B, +- 0x64, 0x40, 0x20, 0x2B, 0x38, 0x00, 0x2D, 0x5C, 0x24, 0x41, 0x02, 0xA1, 0x65, 0x43, 0x08, 0xA3, +- 0x23, 0x46, 0x22, 0x42, 0x7E, 0x3A, 0x0A, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0xB8, 0x18, 0x02, 0x62, +- 0xC9, 0x81, 0xAB, 0x84, 0x03, 0x00, 0xA2, 0xDC, 0x7E, 0x36, 0xF6, 0x01, 0x15, 0x11, 0x7A, 0xD4, +- 0xFF, 0xFF, 0xF9, 0x1C, 0xA2, 0xDC, 0xF0, 0x1D, 0xD9, 0x81, 0xFF, 0xB1, 0x41, 0x1E, 0x62, 0x40, +- 0x7E, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x02, 0x62, 0x07, 0x11, 0x5A, 0xD2, 0x89, 0xFF, 0x80, 0x4F, +- 0x6F, 0x44, 0xA2, 0xDA, 0x88, 0xFF, 0x34, 0x00, 0x62, 0x45, 0x33, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, +- 0x65, 0x42, 0xE5, 0x1D, 0xF2, 0x01, 0x98, 0xFF, 0x2D, 0x46, 0x01, 0x64, 0x12, 0xFA, 0x0F, 0xF0, +- 0x0A, 0x64, 0xB0, 0x84, 0x41, 0x00, 0x24, 0x41, 0x02, 0xA1, 0x65, 0x43, 0x08, 0xA3, 0x23, 0x46, +- 0x22, 0x42, 0x7E, 0x3A, 0x0A, 0x00, 0x00, 0xF4, 0x81, 0xF2, 0x5C, 0x18, 0x02, 0x62, 0xC9, 0x81, +- 0xAB, 0x84, 0x03, 0x00, 0xA2, 0xDC, 0x7E, 0x36, 0xF6, 0x01, 0x7A, 0xD4, 0xFF, 0xFF, 0xFA, 0x1C, +- 0xA2, 0xDC, 0xF1, 0x1D, 0xD9, 0x81, 0xFF, 0xB1, 0x0B, 0x1E, 0x62, 0x40, 0x7E, 0x3A, 0x02, 0x00, +- 0x00, 0xF4, 0x02, 0x62, 0x5A, 0xD2, 0x89, 0xFF, 0x80, 0x4F, 0x6F, 0x44, 0xA2, 0xDA, 0x88, 0xFF, +- 0x98, 0xFF, 0x2D, 0x46, 0x0F, 0xF0, 0x0A, 0x64, 0xB0, 0x84, 0x16, 0x14, 0xF7, 0xB4, 0xA2, 0xDA, +- 0x06, 0x60, 0x75, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0B, 0x00, 0xF0, 0xF5, 0xEF, 0xF4, +- 0x0C, 0x60, 0xEA, 0x61, 0x59, 0xD1, 0x3B, 0xF8, 0x05, 0x64, 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, +- 0xFC, 0x02, 0xC3, 0x60, 0x6A, 0x78, 0xFF, 0xFF, 0xA2, 0xDA, 0x2D, 0x46, 0x3B, 0xF0, 0xFF, 0xFF, +- 0x64, 0x40, 0x20, 0x2B, 0x1C, 0x00, 0x07, 0xF4, 0xBB, 0xF0, 0x2A, 0x44, 0xA4, 0x84, 0xFF, 0xFF, +- 0x2F, 0x26, 0x15, 0x00, 0x2D, 0x46, 0x64, 0x44, 0x3A, 0xF0, 0xBC, 0xF0, 0x64, 0x5F, 0x3D, 0xF0, +- 0x07, 0xF4, 0xEF, 0xF4, 0xFF, 0xFF, 0x08, 0xA3, 0x5B, 0xD8, 0x65, 0x5C, 0x5B, 0xD8, 0x5B, 0xDA, +- 0x2D, 0x46, 0xED, 0xF3, 0x3C, 0xFA, 0xEE, 0xF3, 0x3D, 0xFA, 0x2A, 0x44, 0x23, 0xFA, 0xC3, 0x60, +- 0x6A, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0xFF, 0x43, 0xFF, 0x40, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, +- 0x2D, 0x46, 0x0C, 0x60, 0xEA, 0x61, 0xA1, 0xD3, 0x2D, 0x46, 0x60, 0x40, 0x01, 0x2A, 0x0A, 0x00, +- 0xF0, 0xF5, 0xEF, 0xF4, 0x59, 0xD1, 0x3B, 0xF8, 0x05, 0x64, 0x59, 0xD1, 0xCC, 0x84, 0xBD, 0xD8, +- 0xFC, 0x02, 0x2D, 0x46, 0xC3, 0x60, 0x48, 0x78, 0xFF, 0xFF, 0x98, 0xFF, 0x09, 0xE1, 0xA1, 0xFF, +- 0x2D, 0x46, 0x08, 0x25, 0xE0, 0x01, 0x0F, 0xF2, 0x40, 0xFF, 0x02, 0xBC, 0xA2, 0xDA, 0xC3, 0x60, +- 0x6A, 0x78, 0xFF, 0xFF, 0xB0, 0x84, 0x22, 0xFA, 0xA0, 0x60, 0x00, 0xEB, 0xB0, 0x60, 0x00, 0xEB, +- 0x00, 0x63, 0x3B, 0xF2, 0x06, 0x60, 0x75, 0xFD, 0x60, 0x47, 0xC0, 0xB7, 0x02, 0xFE, 0xF0, 0x84, +- 0xF0, 0x84, 0xF0, 0x84, 0x00, 0xA8, 0x40, 0x4A, 0x16, 0x03, 0xE0, 0x81, 0x61, 0x43, 0x42, 0xFE, +- 0x00, 0x64, 0xF0, 0x84, 0xFE, 0x1F, 0x40, 0x4A, 0xE1, 0x84, 0xE0, 0x84, 0x2D, 0x46, 0x07, 0xF4, +- 0xE0, 0x81, 0x3B, 0xF0, 0x2A, 0x47, 0x0C, 0x60, 0x38, 0x63, 0xA0, 0x84, 0x47, 0x9C, 0x10, 0x03, +- 0x7C, 0x44, 0xA8, 0x63, 0x0F, 0x00, 0x07, 0xF4, 0x20, 0x64, 0x40, 0x4A, 0x3B, 0xF0, 0x66, 0x44, +- 0x64, 0x40, 0x80, 0x2B, 0x05, 0x00, 0x00, 0x60, 0x78, 0x7C, 0x00, 0x60, 0x98, 0x63, 0x02, 0x00, +- 0x2D, 0x46, 0xBB, 0x01, 0x2D, 0x46, 0xED, 0xFB, 0xEE, 0xF9, 0xEF, 0xFD, 0x07, 0xF2, 0xF0, 0xFB, +- 0x60, 0x46, 0x3B, 0xF0, 0x2A, 0x44, 0x06, 0x60, 0x76, 0xF9, 0x5C, 0x4B, 0xA0, 0x84, 0xFF, 0xFF, +- 0x3F, 0x22, 0x05, 0x00, 0x90, 0x84, 0x3B, 0xFA, 0x01, 0x64, 0x40, 0x4B, 0x2C, 0x00, 0xAD, 0x46, +- 0x0A, 0xA3, 0x3D, 0xF2, 0xAD, 0x46, 0xA3, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3C, 0xF2, 0xAD, 0x46, +- 0x02, 0x03, 0x21, 0x07, 0x14, 0x04, 0x5B, 0xD0, 0xAD, 0x46, 0xD0, 0x80, 0x3B, 0xF2, 0x03, 0x03, +- 0xAD, 0x46, 0x19, 0x07, 0x0C, 0x04, 0x3A, 0xF0, 0xAD, 0x46, 0x5B, 0xD0, 0x64, 0x5F, 0xD0, 0x80, +- 0x2B, 0x44, 0x22, 0x07, 0x04, 0x03, 0xD0, 0x84, 0x10, 0xA4, 0xFF, 0xFF, 0x1D, 0x07, 0x2D, 0x46, +- 0x22, 0xF2, 0x10, 0x60, 0x00, 0x7C, 0xB0, 0x84, 0x22, 0xFA, 0x32, 0x40, 0x04, 0x26, 0x14, 0x00, +- 0xC5, 0x60, 0xD5, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x06, 0x60, 0x75, 0xFB, 0x2D, 0x46, 0x0C, 0x60, +- 0xFA, 0x62, 0x80, 0xFF, 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC6, 0x60, 0xBC, 0x78, 0xFF, 0xFF, +- 0x85, 0xFF, 0x2D, 0x46, 0x08, 0x25, 0x4F, 0x01, 0x2D, 0x46, 0x0C, 0x60, 0xFA, 0x62, 0x80, 0xFF, +- 0x78, 0x44, 0x03, 0xA4, 0xA2, 0xDB, 0xC7, 0x60, 0x44, 0x78, 0xFF, 0xFF, 0x85, 0xFF, 0x2D, 0x46, +- 0x08, 0x25, 0x41, 0x01, 0x00, 0x60, 0x0F, 0x64, 0x08, 0x25, 0x3C, 0x01, 0x60, 0x7F, 0xA0, 0x5B, +- 0x80, 0x60, 0x00, 0xEB, 0xD3, 0x60, 0x00, 0xEB, 0xC4, 0x60, 0xC2, 0x78, 0xFF, 0xFF, 0x2D, 0x46, +- 0x3B, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x20, 0x2B, 0x23, 0x00, 0x08, 0x61, 0x23, 0x11, 0x2D, 0x46, +- 0x00, 0xF4, 0x0A, 0x62, 0x56, 0x92, 0x5A, 0xD0, 0x2C, 0x46, 0x64, 0x47, 0x63, 0x40, 0x7F, 0x2A, +- 0x03, 0x00, 0x00, 0xF4, 0x03, 0x63, 0x46, 0x4C, 0x60, 0xFE, 0xDE, 0xD8, 0x7F, 0x3A, 0x03, 0x00, +- 0x00, 0xF4, 0x03, 0x63, 0x46, 0x4C, 0xDE, 0xDA, 0xFE, 0xA1, 0x20, 0xFE, 0xE7, 0x02, 0x63, 0x41, +- 0xFD, 0xA1, 0x46, 0x4C, 0x01, 0xF2, 0x2D, 0x46, 0x61, 0x5E, 0x16, 0xFA, 0x2C, 0x44, 0x06, 0xFA, +- 0x2F, 0x58, 0xFF, 0xFF, 0x2D, 0x5C, 0x3D, 0x44, 0x00, 0xA8, 0xD0, 0x80, 0xD8, 0x03, 0xD7, 0x03, +- 0x2D, 0x46, 0x01, 0x64, 0x12, 0xFA, 0xF4, 0x01, 0x07, 0xF4, 0x66, 0x41, 0x03, 0xF2, 0x04, 0xF2, +- 0x40, 0x42, 0x05, 0xF2, 0x40, 0x43, 0x40, 0x44, 0x61, 0x46, 0x3C, 0xF2, 0x3D, 0xF2, 0x40, 0x40, +- 0x40, 0x41, 0x0D, 0x60, 0x70, 0x65, 0x00, 0x61, 0xEE, 0xF1, 0xED, 0xF5, 0x44, 0x4C, 0x2C, 0x5C, +- 0xE9, 0x80, 0x00, 0x64, 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x24, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x20, 0x44, 0x40, 0x80, 0xDB, 0x83, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x21, 0x44, 0x40, 0x81, 0xDB, 0x83, 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x22, 0x44, 0x40, 0x82, 0xDB, 0x83, 0xBD, 0xD2, 0x22, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x23, 0x44, 0x40, 0x83, 0xF2, 0xA3, 0xBD, 0xD2, 0x23, 0x5C, 0x90, 0x9C, +- 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x47, 0x90, 0x9C, 0x24, 0x44, 0xC0, 0x9C, 0x41, 0x84, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, +- 0x0C, 0x60, 0xEC, 0x61, 0x05, 0x64, 0xEF, 0xF4, 0xF0, 0xF5, 0xFE, 0xA3, 0x5B, 0xD0, 0xCC, 0x84, +- 0x59, 0xD9, 0xFC, 0x02, 0xEF, 0xF3, 0xF0, 0xF5, 0x60, 0x42, 0x20, 0x44, 0xA2, 0xDA, 0x21, 0x44, +- 0x5A, 0xDA, 0x22, 0x44, 0x5A, 0xDA, 0x23, 0x44, 0x5A, 0xDA, 0x24, 0x44, 0x5A, 0xDA, 0x61, 0x46, +- 0x06, 0x60, 0x7D, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x41, 0xEF, 0xF3, 0xF0, 0xF5, 0xA0, 0xD2, +- 0x5A, 0xD0, 0x40, 0x40, 0x44, 0x41, 0x5A, 0xD2, 0x5A, 0xD0, 0x40, 0x42, 0x5A, 0xD0, 0x44, 0x43, +- 0x61, 0x46, 0xBA, 0xF0, 0x3B, 0xF2, 0x44, 0x44, 0x65, 0x5F, 0x40, 0x85, 0xEE, 0xF4, 0xED, 0xF5, +- 0x43, 0x4C, 0x0D, 0x60, 0x70, 0x65, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x20, 0x44, 0x40, 0x80, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x21, 0x44, +- 0x40, 0x81, 0xBD, 0xD2, 0x21, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x22, 0x44, 0x40, 0x82, +- 0xBD, 0xD2, 0x22, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x23, 0x44, 0x40, 0x83, 0xBD, 0xD2, +- 0x23, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x24, 0x44, 0x40, 0x84, 0xBD, 0xD2, 0x24, 0x5C, +- 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x25, 0x44, 0x40, 0x85, 0x61, 0x46, 0x3A, 0xF0, 0xFF, 0xFF, +- 0x64, 0x44, 0xE0, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xE1, 0x7F, 0x5A, 0xD0, 0xA0, 0x5B, 0x64, 0x44, +- 0xE2, 0x7F, 0xA0, 0x5B, 0x64, 0x47, 0xED, 0xF5, 0xBD, 0xD2, 0x25, 0x5C, 0x90, 0x84, 0xE8, 0x80, +- 0xF8, 0x84, 0x20, 0x5C, 0x40, 0x80, 0x20, 0x44, 0xE4, 0x7F, 0xA0, 0x5B, 0x20, 0x47, 0xE5, 0x7F, +- 0xA0, 0x5B, 0xBD, 0xD2, 0x20, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x21, 0x5C, 0x40, 0x81, +- 0x21, 0x44, 0xE6, 0x7F, 0xA0, 0x5B, 0x21, 0x47, 0xE7, 0x7F, 0xA0, 0x5B, 0x21, 0x44, 0xE8, 0x80, +- 0xF8, 0x84, 0x22, 0x5C, 0x40, 0x82, 0x22, 0x44, 0xE8, 0x7F, 0xA0, 0x5B, 0x22, 0x47, 0xE9, 0x7F, +- 0xA0, 0x5B, 0x22, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x23, 0x5C, 0x40, 0x83, 0x23, 0x44, 0xEA, 0x7F, +- 0xA0, 0x5B, 0x23, 0x47, 0xEB, 0x7F, 0xA0, 0x5B, 0x23, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x24, 0x5C, +- 0x40, 0x84, 0x24, 0x44, 0xEC, 0x7F, 0xA0, 0x5B, 0x24, 0x47, 0xED, 0x7F, 0xA0, 0x5B, 0x24, 0x44, +- 0xE8, 0x80, 0xF8, 0x84, 0x25, 0x5C, 0x40, 0x85, 0x25, 0x44, 0xEE, 0x7F, 0xA0, 0x5B, 0x25, 0x47, +- 0xEF, 0x7F, 0xA0, 0x5B, 0x2C, 0x43, 0xA3, 0xD2, 0x25, 0x5C, 0x90, 0x81, 0xE9, 0x84, 0xE3, 0x7F, +- 0xA0, 0x5B, 0x06, 0x60, 0x7D, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0xF3, 0x5A, 0xD3, 0x40, 0x48, +- 0x5A, 0xD3, 0x40, 0x49, 0x40, 0x4A, 0x00, 0x60, 0x78, 0x7C, 0x44, 0x4D, 0x49, 0xF2, 0x4A, 0xF2, +- 0x40, 0x47, 0x40, 0x46, 0x0D, 0x60, 0x70, 0x65, 0x00, 0x61, 0x2D, 0x5C, 0xE9, 0x80, 0x00, 0x64, +- 0xF0, 0x84, 0xF0, 0x84, 0xC0, 0x83, 0xBD, 0xD2, 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x26, 0x44, 0x40, 0x86, 0xDB, 0x83, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x27, 0x44, 0x40, 0x87, 0xDB, 0x83, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x28, 0x44, 0x40, 0x88, 0xDB, 0x83, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x29, 0x44, 0x40, 0x89, 0xF2, 0xA3, 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x2A, 0x44, 0xC0, 0x9C, 0x41, 0x8A, 0xDD, 0x81, 0x08, 0x2A, 0xA7, 0x01, 0x26, 0x44, 0x44, 0xFA, +- 0x27, 0x44, 0x45, 0xFA, 0x28, 0x44, 0x46, 0xFA, 0x29, 0x44, 0x47, 0xFA, 0x2A, 0x44, 0x48, 0xFA, +- 0x06, 0x60, 0x7E, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x88, 0x7C, 0x44, 0x4D, 0x2D, 0x42, +- 0xA2, 0xD2, 0x5A, 0xD0, 0x40, 0x46, 0x44, 0x47, 0x5A, 0xD2, 0x5A, 0xD0, 0x40, 0x48, 0x5A, 0xD0, +- 0x44, 0x49, 0x4B, 0xF2, 0x44, 0x4A, 0x40, 0x8B, 0x60, 0x5C, 0x64, 0x47, 0xE0, 0x7F, 0xA0, 0x5A, +- 0xFF, 0xB4, 0x20, 0xBC, 0x7F, 0xB4, 0xE1, 0x7F, 0xA0, 0x5A, 0x64, 0x44, 0xE2, 0x7F, 0xA0, 0x5A, +- 0x00, 0x60, 0x78, 0x63, 0x0D, 0x60, 0x70, 0x65, 0xBD, 0xD2, 0x2B, 0x5C, 0x90, 0x9C, 0x64, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, +- 0x90, 0x9C, 0x26, 0x44, 0x40, 0x86, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, +- 0x27, 0x44, 0x40, 0x87, 0xBD, 0xD2, 0x27, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, +- 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x28, 0x44, +- 0x40, 0x88, 0xBD, 0xD2, 0x28, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, +- 0x64, 0x44, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x29, 0x44, 0x40, 0x89, +- 0xBD, 0xD2, 0x29, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2A, 0x44, 0x40, 0x8A, 0xBD, 0xD2, +- 0x2A, 0x5C, 0x90, 0x9C, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x44, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD1, 0x64, 0x47, 0x90, 0x9C, 0x2B, 0x44, 0x40, 0x8B, 0xBD, 0xD2, 0x2B, 0x5C, +- 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, 0x26, 0x5C, 0x40, 0x86, 0x26, 0x44, 0xE4, 0x7F, 0xA0, 0x5A, +- 0x26, 0x47, 0xE5, 0x7F, 0xA0, 0x5A, 0xBD, 0xD2, 0x26, 0x5C, 0x90, 0x84, 0xE8, 0x80, 0xF8, 0x84, +- 0x27, 0x5C, 0x40, 0x87, 0x27, 0x44, 0xE6, 0x7F, 0xA0, 0x5A, 0x27, 0x47, 0xE7, 0x7F, 0xA0, 0x5A, +- 0x27, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x28, 0x5C, 0x40, 0x88, 0x28, 0x44, 0xE8, 0x7F, 0xA0, 0x5A, +- 0x28, 0x47, 0xE9, 0x7F, 0xA0, 0x5A, 0x28, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x29, 0x5C, 0x40, 0x89, +- 0x29, 0x44, 0xEA, 0x7F, 0xA0, 0x5A, 0x29, 0x47, 0xEB, 0x7F, 0xA0, 0x5A, 0x29, 0x44, 0xE8, 0x80, +- 0xF8, 0x84, 0x2A, 0x5C, 0x40, 0x8A, 0x2A, 0x44, 0xEC, 0x7F, 0xA0, 0x5A, 0x2A, 0x47, 0xED, 0x7F, +- 0xA0, 0x5A, 0x2A, 0x44, 0xE8, 0x80, 0xF8, 0x84, 0x2B, 0x5C, 0x40, 0x8B, 0x2B, 0x44, 0xEE, 0x7F, +- 0xA0, 0x5A, 0x2B, 0x47, 0xEF, 0x7F, 0xA0, 0x5A, 0x3C, 0xF0, 0x2B, 0x44, 0x90, 0x84, 0xE8, 0x84, +- 0xE3, 0x7F, 0xA0, 0x5A, 0x06, 0x60, 0x7E, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x60, 0x45, 0x00, 0xF0, +- 0x84, 0x60, 0x00, 0xE3, 0x04, 0x71, 0x64, 0x50, 0x01, 0x2A, 0x04, 0x71, 0x5C, 0x61, 0x04, 0x63, +- 0x59, 0xD0, 0x58, 0xD9, 0xFD, 0x1F, 0x3D, 0xF2, 0x60, 0x43, 0x60, 0x47, 0x5B, 0xDB, 0x3C, 0xF2, +- 0xFF, 0xFF, 0x60, 0x47, 0x5B, 0xDB, 0x3A, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x5B, 0xDB, 0x3F, 0xF2, +- 0xFF, 0xFF, 0x60, 0x47, 0x5B, 0xDB, 0x81, 0x60, 0x18, 0xE3, 0x65, 0x43, 0xE3, 0x84, 0x60, 0x47, +- 0x00, 0x7F, 0x60, 0x50, 0x7F, 0x64, 0x23, 0x94, 0x60, 0x51, 0x7C, 0x72, 0x04, 0x75, 0x0C, 0x60, +- 0x16, 0x61, 0x16, 0x60, 0x00, 0x63, 0x59, 0xDD, 0x2A, 0xF2, 0x87, 0x60, 0x8F, 0x65, 0xA4, 0x87, +- 0x40, 0xBF, 0x59, 0xDB, 0x56, 0x64, 0x0A, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x62, 0x64, +- 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x35, 0xF2, 0x0F, 0x65, 0xA4, 0x9C, 0x59, 0xD9, +- 0x06, 0x63, 0x59, 0xDF, 0xFE, 0x1F, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0x03, 0x2B, 0x05, 0x00, +- 0x6A, 0x64, 0x04, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x65, 0x40, 0x8F, 0xB0, 0x88, 0x3A, +- 0x02, 0x00, 0x39, 0xF0, 0x59, 0xD9, 0x2F, 0x58, 0xFF, 0xFF, 0x0C, 0x60, 0x16, 0x61, 0xA3, 0x46, +- 0x00, 0xF4, 0x02, 0x64, 0x0A, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x59, 0xDF, 0x59, 0xDF, +- 0xA0, 0x4C, 0x04, 0xBC, 0xFF, 0xB4, 0xA0, 0x51, 0x23, 0x44, 0x01, 0xA7, 0x80, 0xBF, 0x60, 0x50, +- 0x80, 0x60, 0x38, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x01, 0x76, 0xFF, 0xFF, 0x76, 0x44, 0x01, 0x3A, +- 0xFD, 0x01, 0x40, 0x76, 0x40, 0x76, 0x42, 0xFF, 0xFF, 0xFF, 0x40, 0x76, 0x80, 0x60, 0x18, 0x70, +- 0x80, 0x60, 0x18, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x80, 0x60, 0x10, 0x73, 0x02, 0x76, 0x76, 0x44, +- 0xFF, 0xFF, 0x76, 0x44, 0x02, 0x3A, 0xFD, 0x01, 0x40, 0x76, 0x42, 0xFF, 0x3C, 0x46, 0x00, 0xF2, +- 0x80, 0x60, 0x00, 0xBC, 0x60, 0x50, 0x80, 0x60, 0x12, 0x71, 0x80, 0x60, 0x6E, 0x72, 0x3F, 0xF2, +- 0xFF, 0xFF, 0xF8, 0xA7, 0x80, 0xBF, 0x60, 0x53, 0x04, 0x76, 0xFF, 0xFF, 0x88, 0xFF, 0x3C, 0x46, +- 0x07, 0xF2, 0xFF, 0xFF, 0x40, 0x43, 0xA3, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x77, 0x40, 0x8B, 0xFF, +- 0xA0, 0x4B, 0x04, 0xE1, 0xFF, 0xFF, 0x76, 0x44, 0x04, 0x3A, 0xFD, 0x01, 0x40, 0x76, 0x42, 0xFF, +- 0xFF, 0xFF, 0x10, 0x76, 0xFF, 0xFF, 0x76, 0x44, 0x20, 0x3A, 0xFD, 0x01, 0x40, 0x76, 0x42, 0xFF, +- 0x63, 0x44, 0x00, 0x7F, 0xA0, 0x51, 0x02, 0x60, 0x00, 0x75, 0x88, 0xFF, 0xA0, 0x4C, 0xFB, 0xB4, +- 0xA0, 0x51, 0x06, 0x60, 0x1F, 0xE1, 0x16, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xF2, +- 0xFF, 0xFF, 0xF8, 0xA4, 0x3F, 0xFA, 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, 0xA0, 0x48, 0x08, 0x26, +- 0x07, 0x00, 0xA0, 0x4C, 0x04, 0xE1, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, 0xA0, 0x51, +- 0x42, 0xFF, 0x26, 0x46, 0x8B, 0xFF, 0x02, 0x60, 0x00, 0x75, 0x3C, 0xF2, 0x40, 0x76, 0x14, 0x1B, +- 0x26, 0x46, 0x3B, 0xF2, 0x0C, 0x60, 0xBA, 0x63, 0x60, 0x47, 0xC0, 0xB4, 0xE8, 0x84, 0xE8, 0x84, +- 0xE8, 0x84, 0x43, 0x93, 0xE3, 0x9C, 0x64, 0x47, 0x80, 0x7C, 0x64, 0x5F, 0x60, 0x50, 0x7F, 0x64, +- 0x23, 0x97, 0x80, 0xBF, 0x60, 0x51, 0x07, 0x00, 0x01, 0xA7, 0x80, 0xBF, 0x60, 0x50, 0x80, 0x60, +- 0x40, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x01, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, +- 0xFC, 0x01, 0x04, 0x25, 0xD5, 0x01, 0x40, 0x76, 0x43, 0xFF, 0x0C, 0x60, 0x22, 0x61, 0x26, 0x46, +- 0x00, 0xF4, 0x02, 0x64, 0x0A, 0x63, 0x58, 0xD0, 0x59, 0xD9, 0xFD, 0x1F, 0x59, 0xDF, 0x59, 0xDF, +- 0x80, 0x60, 0x18, 0x70, 0x80, 0x60, 0x24, 0x71, 0x80, 0x60, 0x7C, 0x72, 0x80, 0x60, 0x10, 0x73, +- 0x02, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, 0xFC, 0x01, 0x04, 0x25, 0xB8, 0x01, +- 0x40, 0x76, 0x43, 0xFF, 0x26, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x80, 0xBF, 0x60, 0x50, +- 0x80, 0x60, 0x12, 0x71, 0x3F, 0xF2, 0x80, 0x60, 0x6E, 0x72, 0x60, 0x47, 0x80, 0xBF, 0x60, 0x53, +- 0x04, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, 0xFC, 0x01, 0x04, 0x25, 0xA0, 0x01, +- 0x40, 0x76, 0x43, 0xFF, 0x08, 0x76, 0xFF, 0xFF, 0xA1, 0xFF, 0xFF, 0xFF, 0x0C, 0x21, 0xFC, 0x01, +- 0x04, 0x25, 0x96, 0x01, 0x76, 0x5C, 0xFF, 0xFF, 0x40, 0x76, 0x43, 0xFF, 0x88, 0xFF, 0x26, 0x46, +- 0x2F, 0x58, 0xFF, 0xFF, 0xEE, 0x60, 0x60, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, +- 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x00, 0xDB, 0xF3, 0x31, 0x41, 0x01, 0xB1, +- 0x03, 0xA8, 0x2A, 0x03, 0x15, 0x02, 0x20, 0x40, 0x04, 0x2B, 0x0B, 0x00, 0xBB, 0xFE, 0xCA, 0xFE, +- 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x07, 0x00, 0x08, 0x60, 0x09, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x80, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x0C, 0x00, +- 0xA9, 0xFE, 0xDB, 0x05, 0xAB, 0xFE, 0x0C, 0x05, 0xA8, 0xFE, 0xCC, 0x05, 0xAA, 0xFE, 0xCD, 0x05, +- 0x78, 0x43, 0x01, 0x61, 0x29, 0x60, 0xEA, 0x78, 0xA1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x85, 0x3E, +- 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x03, 0x02, 0xCA, 0x60, 0xD4, 0x78, +- 0xFF, 0xFF, 0x26, 0x45, 0xD4, 0x80, 0x0F, 0xF0, 0xF9, 0x03, 0x64, 0x44, 0x70, 0xB0, 0x70, 0x2A, +- 0x13, 0x00, 0x16, 0x60, 0x85, 0xF3, 0xFF, 0xFF, 0xDC, 0x84, 0x00, 0x36, 0x00, 0x3B, 0xA2, 0xDB, +- 0xA2, 0xFF, 0xAC, 0xF3, 0xFF, 0xFF, 0xCC, 0x84, 0xFE, 0xA0, 0xAC, 0xFB, 0x01, 0x07, 0xD4, 0xFE, +- 0xA3, 0xFF, 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0x64, 0x40, 0x02, 0x26, 0x09, 0x00, 0x66, 0x45, +- 0x09, 0xF4, 0x0F, 0xF2, 0x02, 0x18, 0x65, 0x46, 0xE4, 0x1B, 0x00, 0x64, 0x40, 0x46, 0xCC, 0x01, +- 0xA2, 0xFF, 0xAC, 0xF3, 0x46, 0x46, 0xCC, 0x84, 0xFE, 0xA0, 0xAC, 0xFB, 0x01, 0x07, 0xD4, 0xFE, +- 0xA3, 0xFF, 0x0F, 0xF0, 0xA3, 0xFC, 0x64, 0x44, 0x80, 0x26, 0x35, 0x00, 0x2C, 0x60, 0xEA, 0x64, +- 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, 0x07, 0x60, +- 0x01, 0x64, 0x22, 0x00, 0x02, 0x2A, 0x03, 0x00, 0x00, 0x60, 0x01, 0x64, 0x1D, 0x00, 0x04, 0x2A, +- 0x1F, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x0C, 0xB0, 0x08, 0x3A, 0x1A, 0x00, 0x2C, 0xF0, 0x22, 0xF0, +- 0x64, 0x40, 0x01, 0x26, 0x0B, 0x00, 0x64, 0x40, 0x40, 0x2B, 0x12, 0x00, 0x8F, 0xB0, 0x88, 0x3A, +- 0x0F, 0x00, 0x39, 0xF2, 0xFF, 0xFF, 0x60, 0xB0, 0x20, 0x3A, 0x0A, 0x00, 0x23, 0xF2, 0x00, 0x60, +- 0x01, 0x7C, 0xB0, 0x84, 0x23, 0xFA, 0x0C, 0x00, 0x23, 0xFA, 0xD0, 0x60, 0xC1, 0x78, 0xFF, 0xFF, +- 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x10, 0x27, 0xF8, 0x01, +- 0x0F, 0xF0, 0xFF, 0xFF, 0x64, 0x44, 0x08, 0x26, 0x64, 0x00, 0x2A, 0xF2, 0x60, 0x63, 0x60, 0x40, +- 0x02, 0x2B, 0x66, 0x63, 0xBE, 0xD2, 0x81, 0xF1, 0xA3, 0xD2, 0xD0, 0x80, 0x80, 0xF1, 0x0D, 0x02, +- 0xBF, 0xD2, 0xD0, 0x80, 0x7F, 0xF1, 0x09, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x06, 0x02, 0x2C, 0x60, +- 0xF6, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x32, 0x44, 0x01, 0x2A, 0x03, 0x00, +- 0x07, 0x60, 0x02, 0x64, 0x04, 0x00, 0x02, 0x2A, 0x06, 0x00, 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, +- 0xD0, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0xB0, 0x3A, 0x06, 0x00, +- 0x00, 0x60, 0x02, 0x64, 0x23, 0xFA, 0xCC, 0x60, 0x31, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x04, 0x2A, +- 0x2D, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x0C, 0xB0, 0x08, 0x3A, 0x28, 0x00, 0x2C, 0xF0, 0x22, 0xF0, +- 0x64, 0x40, 0x01, 0x26, 0x0B, 0x00, 0x64, 0x40, 0x40, 0x2B, 0x20, 0x00, 0x8F, 0xB0, 0x88, 0x3A, +- 0x1D, 0x00, 0x39, 0xF2, 0xFF, 0xFF, 0x60, 0xB0, 0x20, 0x3A, 0x18, 0x00, 0x2C, 0xF0, 0x66, 0x45, +- 0x07, 0xF4, 0x64, 0x40, 0x01, 0x26, 0xA6, 0xF5, 0x3A, 0xF2, 0x65, 0x46, 0x60, 0x40, 0x00, 0x36, +- 0x0D, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x10, 0x2A, 0x08, 0x00, 0x20, 0x2B, 0x06, 0x00, +- 0x23, 0xF2, 0x00, 0x60, 0x02, 0x7C, 0xB0, 0x84, 0x23, 0xFA, 0x03, 0x00, 0xD0, 0x60, 0xB5, 0x78, +- 0xFF, 0xFF, 0x32, 0x44, 0x01, 0x2A, 0x4A, 0x00, 0x2E, 0x60, 0x40, 0x63, 0xBF, 0xD3, 0x00, 0x65, +- 0xB4, 0x81, 0xDB, 0x83, 0x3D, 0x03, 0xBF, 0xD3, 0xA3, 0xD3, 0x40, 0x48, 0xBE, 0xD3, 0x40, 0x4A, +- 0x2E, 0xF0, 0x40, 0x4C, 0xD0, 0x80, 0x2D, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x2C, 0xF0, +- 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x2B, 0x03, 0x31, 0xF0, 0x2C, 0x44, 0xD0, 0x80, +- 0x30, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x2F, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, +- 0xFF, 0xFF, 0x1E, 0x03, 0x34, 0xF0, 0x2C, 0x44, 0xD0, 0x80, 0x33, 0xF0, 0x08, 0x02, 0x2A, 0x44, +- 0xD0, 0x80, 0x32, 0xF0, 0x04, 0x02, 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x11, 0x03, 0x38, 0xF0, +- 0x2C, 0x44, 0xD0, 0x80, 0x37, 0xF0, 0x08, 0x02, 0x2A, 0x44, 0xD0, 0x80, 0x36, 0xF0, 0x04, 0x02, +- 0x28, 0x44, 0xD0, 0x80, 0xFF, 0xFF, 0x04, 0x03, 0xFA, 0xA1, 0x06, 0xA3, 0xB7, 0x03, 0xC3, 0x01, +- 0x07, 0x60, 0x00, 0x64, 0x23, 0xFA, 0xD0, 0x60, 0xC1, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x0F, 0xF0, +- 0x60, 0x45, 0xA4, 0x36, 0x08, 0x00, 0x0C, 0xB4, 0x04, 0x36, 0x02, 0x00, 0x0C, 0x3A, 0x06, 0x00, +- 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0xCE, 0x60, 0x7C, 0x78, 0xFF, 0xFF, 0x0F, 0xF0, 0x65, 0x40, +- 0x40, 0x2B, 0x17, 0x00, 0x32, 0x40, 0x08, 0x26, 0x14, 0x00, 0x07, 0xF4, 0x3A, 0xF2, 0xFF, 0xFF, +- 0x37, 0xB4, 0x26, 0x46, 0x0E, 0x02, 0x2C, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x06, 0x00, +- 0x2C, 0x60, 0xF0, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0xD0, 0x60, 0xB5, 0x78, +- 0xFF, 0xFF, 0x2A, 0xF2, 0x64, 0x40, 0x60, 0x26, 0x03, 0x00, 0xCE, 0x60, 0x4E, 0x78, 0xFF, 0xFF, +- 0x60, 0x41, 0xA6, 0xF3, 0x07, 0xFA, 0x61, 0x44, 0x80, 0x3A, 0x02, 0x00, 0x2A, 0xF2, 0x12, 0x00, +- 0x60, 0x40, 0x40, 0x3A, 0x0F, 0x00, 0xDB, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0x03, 0x3A, 0xE6, 0x01, +- 0xD1, 0x60, 0x58, 0x4D, 0xA6, 0x78, 0xFF, 0xFF, 0xE1, 0x02, 0xA6, 0xF3, 0x07, 0xFA, 0xCD, 0x60, +- 0xE1, 0x78, 0xFF, 0xFF, 0x5E, 0x63, 0x60, 0x40, 0x02, 0x2B, 0x64, 0x63, 0x50, 0xFE, 0xBD, 0xD2, +- 0x7F, 0xF1, 0xBD, 0xD2, 0xD0, 0x80, 0x80, 0xF1, 0xBD, 0xD2, 0xD0, 0x80, 0x81, 0xF1, 0x2A, 0xF2, +- 0xD0, 0x80, 0x60, 0x40, 0x08, 0x3A, 0x09, 0x00, 0x01, 0x0C, 0xC8, 0x01, 0xE9, 0x60, 0x58, 0x4F, +- 0x08, 0x78, 0xFF, 0xFF, 0xCD, 0x60, 0xE1, 0x78, 0xFF, 0xFF, 0x23, 0x0C, 0xD1, 0x60, 0x58, 0x4D, +- 0xA6, 0x78, 0xFF, 0xFF, 0xBB, 0x02, 0x02, 0x64, 0x10, 0x60, 0x0A, 0xFB, 0x00, 0x64, 0x10, 0x60, +- 0x0E, 0xFB, 0x26, 0x60, 0x58, 0x4E, 0x65, 0x78, 0xFF, 0xFF, 0x10, 0x60, 0x05, 0xF3, 0xFF, 0xFF, +- 0x60, 0x40, 0x80, 0x27, 0x07, 0x00, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x64, 0x10, 0x60, 0x0A, 0xFB, 0xA0, 0x01, 0xCD, 0x60, 0xE1, 0x78, +- 0xFF, 0xFF, 0xDB, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0xFD, 0xA0, 0xFF, 0xFF, 0x03, 0x03, 0x20, 0x40, +- 0x10, 0x22, 0xF4, 0x01, 0x08, 0x60, 0x07, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x36, 0x07, 0x00, +- 0x01, 0x64, 0xA2, 0xDB, 0x01, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x31, 0xF2, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, +- 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, +- 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, +- 0x63, 0x46, 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0xA6, 0xF1, 0x43, 0x43, +- 0xD3, 0x80, 0xFF, 0xFF, 0x03, 0x03, 0xCD, 0x60, 0xD9, 0x78, 0xFF, 0xFF, 0xD0, 0x60, 0x58, 0x4F, +- 0xFC, 0x78, 0xFF, 0xFF, 0x03, 0x4B, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF4, 0xA3, 0x00, 0x60, +- 0x1D, 0x61, 0x00, 0x60, 0x01, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, +- 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x64, 0x40, 0x4A, 0x60, 0xFE, +- 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, 0x58, 0x4E, 0x2C, 0x78, +- 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0x65, 0x00, 0x64, 0x19, 0x60, 0x3B, 0xFB, 0x02, 0x00, 0x20, 0xFE, +- 0xFF, 0x65, 0x02, 0x60, 0x00, 0x63, 0x60, 0xFE, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0x20, 0xFE, +- 0xCD, 0x81, 0x60, 0x40, 0x80, 0x2A, 0x39, 0x00, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x01, 0x64, +- 0x2E, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, 0x2A, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x04, 0x64, +- 0x26, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x22, 0x00, 0x0C, 0x3A, 0x02, 0x00, 0x10, 0x64, +- 0x1E, 0x00, 0x12, 0x3A, 0x02, 0x00, 0x20, 0x64, 0x1A, 0x00, 0x18, 0x3A, 0x02, 0x00, 0x40, 0x64, +- 0x16, 0x00, 0x24, 0x3A, 0x02, 0x00, 0x80, 0x64, 0x12, 0x00, 0x30, 0x3A, 0x02, 0x00, 0x01, 0x67, +- 0x0E, 0x00, 0x48, 0x3A, 0x02, 0x00, 0x02, 0x67, 0x0A, 0x00, 0x60, 0x3A, 0x02, 0x00, 0x04, 0x67, +- 0x06, 0x00, 0x6C, 0x3A, 0x02, 0x00, 0x08, 0x67, 0x02, 0x00, 0x00, 0x64, 0x00, 0x00, 0x19, 0x60, +- 0x3B, 0xF1, 0xFF, 0xFF, 0xB0, 0x84, 0x19, 0x60, 0x3B, 0xFB, 0x61, 0x40, 0x00, 0x36, 0x05, 0x00, +- 0x60, 0xFE, 0xBD, 0xD3, 0xFF, 0xFF, 0x20, 0xFE, 0xBB, 0x01, 0x65, 0x40, 0x00, 0x3A, 0x1E, 0x00, +- 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF4, 0xA3, 0x00, 0x60, 0x1D, 0x61, 0x00, 0x60, +- 0x32, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, 0x7A, 0x78, 0xFF, 0xFF, +- 0x00, 0xBB, 0xFF, 0xFF, 0x0B, 0x03, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, +- 0x60, 0x41, 0xFE, 0x60, 0x58, 0x4E, 0x2C, 0x78, 0xFF, 0xFF, 0x91, 0x01, 0x20, 0xFE, 0x00, 0x65, +- 0xFC, 0x60, 0x58, 0x4E, 0xC7, 0x78, 0xFF, 0xFF, 0xA1, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, +- 0x04, 0x00, 0xFD, 0x60, 0x58, 0x4E, 0x11, 0x78, 0xFF, 0xFF, 0x20, 0xFE, 0x37, 0x60, 0xF8, 0x61, +- 0xA1, 0xD1, 0xA1, 0xF3, 0x01, 0x60, 0xAC, 0x63, 0x60, 0x45, 0x2A, 0x44, 0x79, 0xFB, 0xA3, 0xD5, +- 0x65, 0x40, 0x01, 0x27, 0x5B, 0xD5, 0x65, 0x40, 0x01, 0x27, 0x59, 0xD1, 0x66, 0x41, 0xA0, 0x84, +- 0x24, 0x94, 0x2B, 0x46, 0x0F, 0xFA, 0x7A, 0xFB, 0x16, 0x64, 0x12, 0xFA, 0x01, 0x64, 0x11, 0xFA, +- 0x66, 0x5C, 0xC2, 0x60, 0x58, 0x4E, 0x6D, 0x78, 0xFF, 0xFF, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, +- 0x01, 0x27, 0x28, 0x00, 0x19, 0x60, 0x44, 0xF3, 0x32, 0x60, 0x88, 0x63, 0xA3, 0xD3, 0xFF, 0xFF, +- 0x60, 0x40, 0x01, 0x2A, 0x0C, 0x00, 0x0F, 0x64, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, +- 0xFF, 0x60, 0xFF, 0x63, 0x1A, 0x60, 0xB3, 0xFD, 0x1A, 0x60, 0xC3, 0xFD, 0x1C, 0x00, 0x19, 0x60, +- 0x39, 0xF3, 0x3F, 0x40, 0x01, 0x27, 0x08, 0x00, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xFC, 0x60, +- 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0x0F, 0x00, 0x0F, 0xB4, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, +- 0xFF, 0xFF, 0x09, 0x00, 0x19, 0x60, 0x3A, 0xF3, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xFC, 0x60, +- 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0xD3, 0x60, 0x58, 0x4E, 0x78, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x23, 0x43, 0x32, 0x40, 0x08, 0x2A, 0x05, 0x00, 0x63, 0x46, 0x80, 0x60, 0x02, 0x64, 0x06, 0xFA, +- 0x26, 0x46, 0x2C, 0x60, 0xE4, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x27, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3B, 0x07, 0x00, 0x2C, 0x60, 0xF2, 0x64, 0xF1, 0x60, 0x78, 0x41, +- 0xE4, 0x78, 0xB5, 0xF1, 0x08, 0x00, 0x02, 0x3B, 0x06, 0x00, 0x2C, 0x60, 0xF4, 0x64, 0xF1, 0x60, +- 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x1B, 0xF2, 0xFF, 0xFF, 0xE4, 0xA4, 0x3E, 0xFA, 0x2A, 0xF2, +- 0x28, 0x41, 0x40, 0xA8, 0x01, 0xB1, 0x02, 0x02, 0x46, 0x02, 0x76, 0x00, 0x60, 0x40, 0x08, 0x2A, +- 0x0F, 0x00, 0x2C, 0x60, 0xE2, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x1B, 0xF2, +- 0xFF, 0xFF, 0x60, 0x45, 0x2C, 0x60, 0xE8, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xF0, 0x78, 0xB5, 0xF1, +- 0x0F, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x40, 0x26, 0x28, 0x00, 0x32, 0x44, 0x02, 0x26, 0x25, 0x00, +- 0x10, 0x2B, 0x29, 0x00, 0x2E, 0x60, 0x40, 0x63, 0xBF, 0xD3, 0x2C, 0xF0, 0x00, 0xA8, 0x60, 0x41, +- 0x0D, 0x03, 0x50, 0xFE, 0xBD, 0xD3, 0x2D, 0xF0, 0xD0, 0x80, 0xBD, 0xD3, 0x2E, 0xF0, 0xD0, 0x80, +- 0xBD, 0xD3, 0x2C, 0xF0, 0xD0, 0x80, 0xFA, 0xA1, 0x10, 0x0C, 0xF3, 0x02, 0x50, 0xFE, 0x60, 0x60, +- 0x01, 0x64, 0xD0, 0x80, 0x2D, 0xF0, 0x1D, 0x64, 0xD0, 0x80, 0x2E, 0xF0, 0x01, 0x64, 0xD0, 0x80, +- 0xFF, 0xFF, 0x03, 0x0C, 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x40, 0x2A, 0x03, 0x00, +- 0x1C, 0x60, 0x12, 0x78, 0xFF, 0xFF, 0xD0, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x40, 0x26, +- 0xF7, 0x01, 0x2A, 0xF0, 0xFF, 0xFF, 0x64, 0x40, 0x08, 0x2A, 0x2A, 0x00, 0xDB, 0xF3, 0xFF, 0xFF, +- 0x07, 0xB4, 0x03, 0xA8, 0xFF, 0xFF, 0x03, 0x03, 0x32, 0x40, 0x02, 0x2A, 0x1D, 0x00, 0x03, 0x67, +- 0xA0, 0x84, 0x00, 0x37, 0x64, 0x63, 0x60, 0x40, 0x02, 0x37, 0x5E, 0x63, 0x60, 0x40, 0x01, 0x37, +- 0x58, 0x63, 0x60, 0x40, 0x03, 0x37, 0x0D, 0x00, 0xBD, 0xD2, 0x7F, 0xF1, 0xBD, 0xD2, 0xD0, 0x80, +- 0x80, 0xF1, 0x07, 0x02, 0xD0, 0x80, 0xBD, 0xD2, 0x81, 0xF1, 0x03, 0x02, 0xD0, 0x80, 0xFF, 0xFF, +- 0x03, 0x03, 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0xE9, 0x60, 0x58, 0x4F, 0x08, 0x78, 0xFF, 0xFF, +- 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x26, 0x06, 0x00, 0x20, 0x40, 0x10, 0x2B, 0x03, 0x00, +- 0xD0, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x87, 0xF4, 0xA6, 0xF1, 0x27, 0x1B, 0x31, 0xF2, 0x1D, 0x60, +- 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, +- 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, +- 0x61, 0x46, 0x30, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, +- 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, +- 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, 0x61, 0x46, 0x03, 0x00, 0xD3, 0x80, 0xFF, 0xFF, 0xD6, 0x03, +- 0x43, 0x43, 0xDB, 0xF3, 0x32, 0x40, 0x02, 0x26, 0x04, 0x00, 0x07, 0xB4, 0x03, 0xA8, 0x2A, 0xF2, +- 0x45, 0x02, 0xA6, 0xF1, 0x23, 0x43, 0xD3, 0x80, 0xFF, 0xFF, 0x40, 0x02, 0xD0, 0x60, 0x58, 0x4F, +- 0xFC, 0x78, 0xFF, 0xFF, 0x32, 0x40, 0x02, 0x2A, 0x05, 0x00, 0x63, 0x46, 0x02, 0x64, 0x06, 0xFA, +- 0x26, 0x46, 0x34, 0x00, 0x32, 0x40, 0x08, 0x2A, 0x05, 0x00, 0x63, 0x46, 0x80, 0x60, 0x02, 0x64, +- 0x06, 0xFA, 0x26, 0x46, 0x43, 0x43, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x09, 0x00, +- 0x19, 0x60, 0x44, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x23, 0x46, 0x0F, 0x64, +- 0x10, 0x00, 0x37, 0x60, 0xF8, 0x61, 0xA1, 0xD1, 0xA1, 0xF3, 0x01, 0x60, 0xAC, 0x63, 0x60, 0x45, +- 0xA3, 0xD3, 0x65, 0x40, 0x01, 0x27, 0x5B, 0xD3, 0x65, 0x40, 0x01, 0x27, 0x59, 0xD1, 0x23, 0x46, +- 0xA0, 0x84, 0x0F, 0xFA, 0x7A, 0xFB, 0x79, 0xFB, 0x16, 0x64, 0x12, 0xFA, 0x01, 0x64, 0x11, 0xFA, +- 0x66, 0x5C, 0xC2, 0x60, 0x58, 0x4E, 0x6D, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x07, 0xFC, 0x43, 0x43, +- 0x2A, 0xF2, 0x63, 0x45, 0x0C, 0xB4, 0x08, 0x3A, 0x0A, 0x00, 0xDB, 0xF3, 0x23, 0x46, 0x07, 0xB4, +- 0xFD, 0xA0, 0x06, 0xF2, 0x26, 0x46, 0x03, 0x03, 0x60, 0x40, 0x02, 0x2A, 0x0D, 0x00, 0x2A, 0xF2, +- 0x35, 0xF0, 0x60, 0x40, 0xA4, 0x36, 0x0B, 0x00, 0x08, 0x2B, 0x0C, 0x00, 0x23, 0x46, 0x26, 0xF2, +- 0x26, 0x46, 0xD0, 0x80, 0xFF, 0xFF, 0x06, 0x02, 0xD0, 0x60, 0xB5, 0x78, 0xFF, 0xFF, 0xD0, 0x60, +- 0x6B, 0x78, 0xFF, 0xFF, 0x23, 0x46, 0x22, 0xF2, 0x26, 0x46, 0x44, 0x4C, 0x0F, 0x26, 0x1D, 0x00, +- 0x00, 0xBC, 0x40, 0x45, 0x0B, 0x03, 0x00, 0x64, 0x23, 0x46, 0x22, 0xFA, 0x26, 0x46, 0xA2, 0xFF, +- 0xB6, 0x60, 0x58, 0x4E, 0xF5, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, 0x2A, 0xF0, 0x2C, 0x44, +- 0x64, 0x40, 0x04, 0x27, 0x0A, 0x00, 0x23, 0x46, 0x26, 0xFA, 0x26, 0x46, 0x1B, 0xF2, 0xFF, 0xFF, +- 0xE4, 0xA4, 0x3E, 0xFA, 0xD0, 0x60, 0x22, 0x78, 0xFF, 0xFF, 0x3F, 0xF2, 0x02, 0xFA, 0xA2, 0xFF, +- 0x16, 0xF0, 0xFF, 0xFF, 0x64, 0x44, 0x01, 0x26, 0xDC, 0x9C, 0xB0, 0xF3, 0x2A, 0xF2, 0xDC, 0x83, +- 0xB0, 0xFD, 0x06, 0xF4, 0x01, 0xF8, 0x26, 0x46, 0x60, 0x40, 0x40, 0x2B, 0x18, 0x00, 0x64, 0x44, +- 0x00, 0x65, 0xFF, 0xB4, 0xFC, 0xA4, 0x06, 0xF0, 0x03, 0x03, 0x64, 0x46, 0x0C, 0x0D, 0x02, 0x65, +- 0x26, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x60, 0x46, 0xF9, 0x01, +- 0x01, 0xF2, 0xFF, 0xFF, 0xD4, 0x84, 0x01, 0xFA, 0x66, 0x44, 0x26, 0x46, 0x06, 0xFA, 0x06, 0xF4, +- 0x00, 0xF2, 0x80, 0xFC, 0x40, 0x45, 0xB6, 0x60, 0x58, 0x4E, 0xF5, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, +- 0x26, 0x46, 0x2C, 0x44, 0x0F, 0x26, 0x13, 0x00, 0x23, 0x46, 0x26, 0xFA, 0x26, 0x44, 0x22, 0xFA, +- 0x26, 0x46, 0x1B, 0xF2, 0xFF, 0xFF, 0xE4, 0xA4, 0x3E, 0xFA, 0x00, 0x64, 0x13, 0x60, 0x0D, 0xFB, +- 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x6E, 0x00, 0xA3, 0x46, +- 0x26, 0xF2, 0x60, 0x45, 0xDC, 0x84, 0xD4, 0x80, 0x26, 0xFA, 0xA3, 0x46, 0x6B, 0x02, 0x2A, 0xF0, +- 0xA3, 0x46, 0x22, 0xF2, 0xA3, 0x46, 0x00, 0xBC, 0x00, 0xF2, 0x01, 0x02, 0x63, 0x00, 0x44, 0x4C, +- 0x3F, 0xF0, 0x60, 0x43, 0x23, 0x46, 0x22, 0xF4, 0x09, 0x60, 0x00, 0x65, 0x3F, 0xF2, 0x26, 0x46, +- 0xC0, 0x84, 0xD4, 0x80, 0x60, 0x45, 0x56, 0x07, 0x80, 0xFC, 0x1B, 0xF2, 0x06, 0xF2, 0x60, 0x41, +- 0x23, 0x46, 0x22, 0xF4, 0x1B, 0xF0, 0x06, 0xF0, 0xC1, 0x81, 0x06, 0xFA, 0x05, 0xFA, 0x9B, 0xFA, +- 0x65, 0x44, 0x3F, 0xFA, 0x64, 0x46, 0x00, 0xFC, 0x63, 0x46, 0x01, 0xF2, 0x10, 0x61, 0xF2, 0xA4, +- 0x01, 0xFA, 0xC8, 0x83, 0x02, 0x64, 0x59, 0xD0, 0x58, 0xD8, 0xFD, 0x1F, 0x06, 0x45, 0x00, 0x64, +- 0x13, 0x60, 0x0D, 0xFB, 0x25, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xA2, 0xFF, 0x00, 0xF4, 0x01, 0xF0, 0x0A, 0x18, 0x70, 0x67, 0xA0, 0x80, 0xF0, 0x67, 0x06, 0x03, +- 0xC0, 0x84, 0x01, 0xFA, 0x25, 0x46, 0x25, 0x44, 0x80, 0xFC, 0x05, 0xFA, 0xB6, 0x60, 0x58, 0x4E, +- 0xF5, 0x78, 0xFF, 0xFF, 0xD4, 0xFE, 0xA3, 0xFF, 0x2C, 0x44, 0x04, 0x27, 0x16, 0x00, 0x23, 0x46, +- 0x22, 0xF2, 0xA2, 0xFC, 0x60, 0x46, 0x46, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x47, 0x08, 0xFA, +- 0x26, 0x46, 0x2C, 0x43, 0x2A, 0xFC, 0x06, 0xF4, 0x00, 0x64, 0x00, 0xFA, 0x01, 0xF0, 0x80, 0x60, +- 0x00, 0x64, 0xB0, 0x84, 0x01, 0xFA, 0x26, 0x46, 0x1D, 0x00, 0x00, 0x66, 0x46, 0x46, 0xCA, 0x60, +- 0xD8, 0x78, 0xFF, 0xFF, 0xA3, 0x46, 0x22, 0xF0, 0xA2, 0xFC, 0x00, 0x63, 0x33, 0x85, 0xA3, 0x46, +- 0x0D, 0x03, 0xA3, 0x46, 0x26, 0xF2, 0x0F, 0x65, 0xA4, 0x85, 0xD4, 0x84, 0x26, 0xFA, 0xA3, 0x46, +- 0xA2, 0xFF, 0xB6, 0x60, 0x58, 0x4E, 0xF5, 0x78, 0xFF, 0xFF, 0xA3, 0xFF, 0x26, 0x46, 0xD0, 0x60, +- 0xB5, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x32, 0xF0, 0x60, 0x40, 0x08, 0x2A, 0x24, 0x00, 0x01, 0x2B, +- 0x13, 0x00, 0x64, 0x40, 0x01, 0x2A, 0x10, 0x00, 0x2C, 0x60, 0xE2, 0x64, 0xF1, 0x60, 0x78, 0x41, +- 0xE4, 0x78, 0xB5, 0xF1, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0x2C, 0x60, 0xE8, 0x64, 0xF1, 0x60, +- 0x78, 0x41, 0xF0, 0x78, 0xB5, 0xF1, 0x0F, 0x00, 0x2C, 0x60, 0xE0, 0x64, 0xF1, 0x60, 0x78, 0x41, +- 0xE4, 0x78, 0xB5, 0xF1, 0x1B, 0xF2, 0xFF, 0xFF, 0x60, 0x45, 0x2C, 0x60, 0xE6, 0x64, 0xF1, 0x60, +- 0x78, 0x41, 0xF0, 0x78, 0xB5, 0xF1, 0x07, 0xF4, 0xFF, 0xFF, 0x26, 0xF2, 0x26, 0x46, 0x0F, 0xB4, +- 0xDC, 0x85, 0x2C, 0x60, 0xE4, 0x64, 0xF1, 0x60, 0x78, 0x41, 0xF0, 0x78, 0xB5, 0xF1, 0x27, 0xF2, +- 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3B, 0x07, 0x00, 0x2C, 0x60, 0xF2, 0x64, 0xF1, 0x60, 0x78, 0x41, +- 0xE4, 0x78, 0xB5, 0xF1, 0x08, 0x00, 0x02, 0x3B, 0x06, 0x00, 0x2C, 0x60, 0xF4, 0x64, 0xF1, 0x60, +- 0x78, 0x41, 0xE4, 0x78, 0xB5, 0xF1, 0x07, 0xF2, 0x26, 0xF0, 0x41, 0x18, 0x60, 0x46, 0xFF, 0x67, +- 0x20, 0x88, 0x64, 0x5F, 0x40, 0x4A, 0x15, 0xF0, 0x28, 0x44, 0xD0, 0x84, 0x03, 0xA4, 0x03, 0x0E, +- 0xE8, 0x84, 0xE8, 0x84, 0x04, 0x00, 0xFA, 0xA4, 0xE8, 0x84, 0xE8, 0x87, 0xC0, 0xBF, 0xC0, 0x84, +- 0x15, 0xFA, 0x40, 0x48, 0x14, 0xF0, 0x2A, 0x44, 0xD0, 0x84, 0x1F, 0xA4, 0x06, 0x0E, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x07, 0x00, 0xC2, 0xA4, 0xE8, 0x84, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x87, 0xF8, 0xBF, 0xC0, 0x84, 0x14, 0xFA, 0x33, 0x60, 0x4C, 0x63, +- 0xBD, 0xDB, 0x60, 0x5C, 0x2F, 0x67, 0xD0, 0x80, 0x60, 0x45, 0x02, 0x28, 0x64, 0x45, 0x28, 0x5C, +- 0xBD, 0xD9, 0x8B, 0x67, 0xD0, 0x80, 0x60, 0x41, 0x02, 0x24, 0x64, 0x41, 0xD5, 0x84, 0x80, 0x65, +- 0xC4, 0x87, 0x01, 0x05, 0x00, 0x64, 0xFF, 0xB4, 0x0E, 0xFA, 0xA3, 0xDB, 0x26, 0x46, 0xD1, 0x60, +- 0xDB, 0x78, 0xFF, 0xFF, 0xCA, 0x60, 0xD8, 0x78, 0xFF, 0xFF, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, +- 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xCA, 0x60, 0xD8, 0x78, +- 0xFF, 0xFF, 0x25, 0x60, 0xFE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0x00, 0x66, 0x46, 0x46, 0xCA, 0x60, 0xD8, 0x78, +- 0xFF, 0xFF, 0x2A, 0xF2, 0x58, 0x63, 0x60, 0x47, 0x01, 0x27, 0x64, 0x63, 0x61, 0x5C, 0x1B, 0x60, +- 0xFB, 0xF9, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, 0xBD, 0xD0, 0x00, 0xF4, 0x04, 0xF8, +- 0x83, 0xFA, 0x82, 0xF8, 0xA6, 0x46, 0x02, 0xB0, 0x5E, 0x63, 0x04, 0x03, 0x64, 0x63, 0x03, 0xB0, +- 0x02, 0x3A, 0x6C, 0x63, 0x3F, 0xF2, 0xBD, 0xD0, 0xBD, 0xD0, 0x64, 0x45, 0x64, 0x41, 0xBD, 0xD0, +- 0xA6, 0x46, 0x07, 0xF8, 0x86, 0xFA, 0x85, 0xF8, 0x60, 0x47, 0x08, 0xFA, 0x1B, 0x60, 0xFB, 0xF1, +- 0x26, 0x46, 0x64, 0x41, 0x2F, 0x58, 0xFF, 0xFF, 0xA6, 0xF5, 0x00, 0xF2, 0x26, 0x46, 0x31, 0xF0, +- 0x39, 0x18, 0x66, 0x41, 0x1D, 0x60, 0xC0, 0x65, 0x64, 0x47, 0x00, 0x7F, 0xA6, 0xF1, 0xE0, 0x84, +- 0x44, 0xD3, 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, +- 0x64, 0x46, 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, +- 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, +- 0x60, 0x46, 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, +- 0x1F, 0x60, 0xC2, 0x61, 0xA1, 0xD3, 0x20, 0x60, 0x04, 0x7C, 0xD0, 0x80, 0xFF, 0xFF, 0x07, 0x03, +- 0xA0, 0xDD, 0xDA, 0x9C, 0xA1, 0xD9, 0x49, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xA1, 0xDB, 0xD1, 0x60, +- 0x97, 0x78, 0xFF, 0xFF, 0x20, 0x7C, 0x72, 0x44, 0xFF, 0xB4, 0xD0, 0x80, 0xFF, 0xFF, 0x02, 0x04, +- 0xD0, 0x84, 0xFB, 0x01, 0xE0, 0x83, 0xA6, 0xF3, 0x02, 0xA3, 0x43, 0x93, 0xA6, 0xF3, 0xFF, 0xFF, +- 0x02, 0xA5, 0xD7, 0x80, 0x04, 0xA5, 0x08, 0x24, 0x65, 0x43, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, +- 0x00, 0xF0, 0x81, 0xF0, 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x1D, 0x60, 0xC0, 0x65, +- 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0xA6, 0xF3, +- 0x63, 0x45, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, +- 0x65, 0x46, 0x00, 0xFA, 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x31, 0xF0, +- 0x66, 0x41, 0x1D, 0x60, 0xC0, 0x65, 0x64, 0x47, 0x00, 0x7F, 0xA6, 0xF1, 0xE0, 0x84, 0x44, 0xD3, +- 0x64, 0x43, 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, +- 0x80, 0xF0, 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, +- 0x64, 0x46, 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, +- 0x80, 0xF0, 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, 0x2F, 0xF2, +- 0x30, 0xF0, 0x31, 0xF0, 0x64, 0x45, 0x46, 0x43, 0x63, 0x46, 0x03, 0xFA, 0x06, 0xF2, 0x84, 0xF8, +- 0x00, 0x7E, 0x06, 0xFA, 0x05, 0xF8, 0xA3, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0xDB, 0xF3, 0x2A, 0xF2, +- 0x07, 0xB0, 0x03, 0x3A, 0x2A, 0x00, 0x00, 0xF4, 0x09, 0xF2, 0x60, 0x45, 0x80, 0x3A, 0x05, 0x00, +- 0x0E, 0xF2, 0xFF, 0xFF, 0x02, 0xB0, 0x0F, 0xF2, 0x20, 0x03, 0x60, 0x47, 0x00, 0x3A, 0x1D, 0x00, +- 0x60, 0x41, 0x00, 0x36, 0x13, 0x00, 0xDA, 0x85, 0x33, 0x60, 0xBE, 0x63, 0xBD, 0xD1, 0xFF, 0xFF, +- 0xD1, 0x80, 0xFF, 0xFF, 0x12, 0x02, 0x60, 0xFE, 0xBD, 0xD3, 0xA5, 0xD0, 0xDE, 0x85, 0xD0, 0x80, +- 0xCD, 0x81, 0x0B, 0x02, 0xF9, 0x02, 0x20, 0xFE, 0x00, 0x64, 0x09, 0x00, 0x26, 0x46, 0x48, 0xFE, +- 0x65, 0x40, 0x40, 0x3A, 0x02, 0x00, 0x01, 0x64, 0x02, 0x00, 0x28, 0xFE, 0x00, 0x64, 0x40, 0x48, +- 0x26, 0x46, 0x2D, 0x58, 0xFF, 0xFF, 0x19, 0x60, 0xA3, 0xF3, 0x3D, 0xF2, 0x60, 0x40, 0x01, 0x26, +- 0x2A, 0xFA, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x26, 0x03, 0x00, 0xD2, 0x60, 0xB5, 0x78, +- 0xFF, 0xFF, 0x3F, 0xF0, 0x32, 0x40, 0x10, 0x2A, 0x0E, 0x00, 0x2C, 0xF0, 0x64, 0x41, 0x60, 0x40, +- 0x40, 0x27, 0x09, 0x00, 0xCD, 0x81, 0xDD, 0x81, 0x06, 0x03, 0x05, 0x03, 0x64, 0x40, 0x01, 0x26, +- 0x02, 0x00, 0x01, 0x61, 0x01, 0x00, 0x00, 0x61, 0x60, 0x40, 0x18, 0x36, 0x1F, 0x00, 0xD0, 0x60, +- 0x58, 0x4F, 0xD1, 0x78, 0xFF, 0xFF, 0x0F, 0xF0, 0xEA, 0xF1, 0x64, 0x44, 0x60, 0x22, 0x19, 0x00, +- 0xDB, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0xFD, 0xA0, 0x2A, 0xF2, 0x03, 0x02, 0x08, 0xB0, 0xFF, 0xFF, +- 0x10, 0x02, 0x32, 0xF2, 0x33, 0xF2, 0xD0, 0x80, 0xEB, 0xF1, 0x0B, 0x02, 0xD0, 0x80, 0x34, 0xF2, +- 0x08, 0x02, 0xEC, 0xF1, 0xFF, 0xFF, 0xD0, 0x80, 0x0F, 0xF0, 0x03, 0x02, 0xD3, 0x60, 0x10, 0x78, +- 0xFF, 0xFF, 0x00, 0xF4, 0xAA, 0x60, 0xAA, 0x65, 0x09, 0xF2, 0x5A, 0xD0, 0xD4, 0x80, 0x03, 0x64, +- 0x57, 0x02, 0xD0, 0x80, 0x00, 0x64, 0x5A, 0xD0, 0x53, 0x02, 0x64, 0x45, 0xD4, 0x80, 0xF8, 0x7F, +- 0x08, 0x02, 0x5A, 0xD0, 0x26, 0x46, 0x64, 0x45, 0x23, 0xF0, 0x20, 0x67, 0xB0, 0x84, 0xA2, 0xDA, +- 0x0B, 0x00, 0xD4, 0x80, 0x1D, 0x60, 0x60, 0x64, 0x16, 0x02, 0x5A, 0xD0, 0x26, 0x46, 0x64, 0x45, +- 0x23, 0xF0, 0x40, 0x67, 0xB0, 0x84, 0xA2, 0xDA, 0x65, 0x44, 0x88, 0x3A, 0x07, 0x00, 0x77, 0x37, +- 0x08, 0x00, 0x78, 0x37, 0x06, 0x00, 0x8E, 0x37, 0x04, 0x00, 0x32, 0x00, 0x81, 0x3A, 0x30, 0x00, +- 0x80, 0x37, 0x00, 0x61, 0x2D, 0x00, 0xD4, 0x80, 0x01, 0x60, 0x00, 0x64, 0x5A, 0xD0, 0x28, 0x02, +- 0xD0, 0x80, 0x5A, 0xD0, 0x25, 0x02, 0x26, 0x46, 0x64, 0x47, 0x7F, 0xB4, 0xFD, 0xA0, 0x09, 0x03, +- 0x1F, 0x07, 0x32, 0x40, 0x02, 0x26, 0x44, 0x00, 0x23, 0xF0, 0x60, 0x67, 0xB0, 0x84, 0xA2, 0xDA, +- 0x3F, 0x00, 0x0F, 0xF2, 0x32, 0x40, 0x02, 0x26, 0x3B, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, +- 0x08, 0x2A, 0x07, 0x00, 0x60, 0x40, 0x48, 0x36, 0x04, 0x00, 0xF1, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, +- 0xF1, 0xFB, 0xF4, 0x60, 0x58, 0x4F, 0x1D, 0x78, 0xFF, 0xFF, 0xD3, 0x60, 0x1A, 0x78, 0xFF, 0xFF, +- 0x26, 0x46, 0x61, 0x40, 0x01, 0x2A, 0x07, 0x00, 0x2C, 0x60, 0xF8, 0x64, 0xF1, 0x60, 0x78, 0x41, +- 0xE4, 0x78, 0xB5, 0xF1, 0x85, 0x00, 0x0F, 0xF2, 0x7F, 0xF1, 0x2A, 0xF2, 0x60, 0x40, 0x20, 0x2A, +- 0x12, 0x00, 0x5E, 0x63, 0x60, 0x40, 0x02, 0x2B, 0x64, 0x63, 0xBD, 0xD2, 0xBD, 0xD2, 0xD0, 0x80, +- 0x80, 0xF1, 0x08, 0x02, 0xD0, 0x80, 0xA3, 0xD2, 0x81, 0xF1, 0x04, 0x02, 0xD0, 0x80, 0xFF, 0xFF, +- 0x01, 0x02, 0x06, 0x00, 0x6D, 0x00, 0x2A, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0x36, 0x68, 0x00, +- 0x2A, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x2A, 0x07, 0x00, 0x60, 0x40, 0x48, 0x36, 0x04, 0x00, +- 0xF1, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0xF1, 0xFB, 0x68, 0x00, 0x26, 0x46, 0x2A, 0xF2, 0xFF, 0xFF, +- 0xFF, 0xFF, 0x0C, 0x26, 0x55, 0x00, 0xB0, 0x36, 0x15, 0x00, 0x10, 0x36, 0x13, 0x00, 0x30, 0x36, +- 0x11, 0x00, 0xC0, 0x36, 0x02, 0x00, 0xA0, 0x3A, 0x12, 0x00, 0x7F, 0xF1, 0x32, 0xF2, 0x33, 0xF2, +- 0xD0, 0x80, 0x80, 0xF1, 0x45, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x81, 0xF1, 0x41, 0x02, 0xD0, 0x80, +- 0xFF, 0xFF, 0x3E, 0x02, 0xE6, 0x60, 0x58, 0x4F, 0x3D, 0x78, 0xFF, 0xFF, 0x35, 0x00, 0x50, 0x3A, +- 0x05, 0x00, 0xF8, 0x60, 0x58, 0x4F, 0xE1, 0x78, 0xFF, 0xFF, 0x2E, 0x00, 0x40, 0x3A, 0x05, 0x00, +- 0xF0, 0x60, 0x58, 0x4F, 0x99, 0x78, 0xFF, 0xFF, 0x27, 0x00, 0x80, 0x3A, 0x24, 0x00, 0x7F, 0xF1, +- 0x32, 0xF2, 0x33, 0xF2, 0xD0, 0x80, 0x80, 0xF1, 0x23, 0x02, 0xD0, 0x80, 0x34, 0xF2, 0x81, 0xF1, +- 0x1F, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x1C, 0x02, 0xE9, 0x60, 0x58, 0x4F, 0x30, 0x78, 0xFF, 0xFF, +- 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x0A, 0x00, 0x19, 0x60, 0x4C, 0xF3, 0xFF, 0xFF, +- 0x60, 0x40, 0x08, 0x26, 0x04, 0x00, 0xEE, 0x60, 0x58, 0x4F, 0x81, 0x78, 0xFF, 0xFF, 0x24, 0x60, +- 0x58, 0x4F, 0xE3, 0x78, 0xFF, 0xFF, 0x04, 0x00, 0x66, 0x44, 0x00, 0xA8, 0xFF, 0xFF, 0x0A, 0x03, +- 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, +- 0x00, 0x66, 0x46, 0x46, 0xD0, 0x60, 0xB2, 0x78, 0xFF, 0xFF, 0x2A, 0xF2, 0x3B, 0xF0, 0x60, 0x40, +- 0x40, 0x2B, 0x06, 0x00, 0xC0, 0x60, 0x00, 0x64, 0x64, 0x40, 0x20, 0x2B, 0x01, 0x00, 0x03, 0x00, +- 0xD3, 0x60, 0x4C, 0x78, 0xFF, 0xFF, 0x22, 0xF2, 0xFF, 0xFF, 0x04, 0xB4, 0xFF, 0xFF, 0xF8, 0x03, +- 0x23, 0xF2, 0x07, 0xF4, 0xBB, 0xF0, 0x26, 0x46, 0xA4, 0x84, 0xFF, 0xFF, 0x60, 0x40, 0x2F, 0x26, +- 0xD7, 0x01, 0x12, 0xF0, 0xFF, 0xFF, 0x10, 0x1B, 0xCA, 0x60, 0x58, 0x4F, 0x16, 0x78, 0xFF, 0xFF, +- 0x64, 0x40, 0x18, 0x36, 0x09, 0x00, 0x04, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, +- 0x26, 0x46, 0xD3, 0x60, 0x10, 0x78, 0xFF, 0xFF, 0x25, 0x60, 0xFE, 0x64, 0x13, 0x60, 0x0D, 0xFB, +- 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xF8, 0xFE, 0xC0, 0x01, +- 0x1C, 0x60, 0x92, 0x63, 0x00, 0x64, 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x94, 0x64, 0xBD, 0xDB, +- 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, 0x00, 0x63, 0x08, 0x60, 0x77, 0xFD, 0xD9, 0x60, 0xA5, 0x64, +- 0x08, 0x60, 0x49, 0xFB, 0xD9, 0x60, 0x6A, 0x64, 0x08, 0x60, 0x35, 0xFB, 0x00, 0x60, 0x02, 0x64, +- 0x08, 0x60, 0x16, 0xFB, 0xD3, 0x60, 0x9C, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x7D, 0xF3, 0x33, 0x60, 0x20, 0x63, 0x60, 0x40, 0x01, 0x27, 0x03, 0x00, 0x19, 0x60, 0x3B, 0xF3, +- 0x02, 0x00, 0x19, 0x60, 0x3C, 0xF3, 0x08, 0x61, 0x60, 0xFE, 0xA3, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, +- 0x00, 0xA8, 0xE8, 0x84, 0x0F, 0x03, 0x60, 0xFE, 0x02, 0x28, 0xF6, 0x01, 0x80, 0x62, 0xB2, 0x9C, +- 0xBD, 0xD9, 0x7B, 0xF9, 0xCD, 0x81, 0x00, 0x36, 0x01, 0x00, 0xEE, 0x01, 0x36, 0x60, 0x0A, 0x63, +- 0x08, 0x61, 0xEA, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0xBA, 0xFE, 0x16, 0x60, 0x87, 0xF3, 0xFF, 0xFF, 0x03, 0xA8, 0x02, 0xA8, 0x04, 0x03, 0x28, 0x02, +- 0xD9, 0x60, 0x41, 0x78, 0xFF, 0xFF, 0xD8, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, +- 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x11, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xAC, 0xF3, +- 0xFF, 0xFF, 0xFE, 0xA0, 0xFF, 0xFF, 0x0A, 0x07, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, +- 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x20, 0x60, 0x20, 0x65, +- 0xA5, 0xDF, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, 0xD4, 0x60, 0xF6, 0x78, 0xFF, 0xFF, +- 0x01, 0x63, 0x0E, 0x60, 0x36, 0xFD, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x64, +- 0x08, 0x60, 0x15, 0xFB, 0x5A, 0xDB, 0xBA, 0xFE, 0x02, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, +- 0x01, 0xBC, 0xF1, 0xFB, 0x44, 0x60, 0x44, 0x64, 0x7F, 0xFB, 0x80, 0xFB, 0x81, 0xFB, 0x08, 0x60, +- 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x08, 0x60, 0x77, 0xF3, 0xFF, 0xFF, 0x15, 0x18, 0xA2, 0xDF, +- 0x40, 0x60, 0x58, 0x4E, 0x7D, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0xC4, 0x64, 0x0F, 0x60, 0xE1, 0xFB, +- 0x4A, 0xDF, 0x01, 0x60, 0xFE, 0x63, 0x1D, 0x60, 0xBE, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, +- 0x10, 0x60, 0x0E, 0x62, 0xA2, 0xDF, 0x5B, 0x00, 0xCF, 0xF3, 0xFF, 0xFF, 0x52, 0x1B, 0x10, 0x60, +- 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x24, 0x40, 0x02, 0x22, 0x26, 0x00, 0x08, 0x60, 0x1E, 0xF1, +- 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, +- 0x16, 0xFB, 0xD4, 0x60, 0x1F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, +- 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x08, 0x60, 0x1E, 0xF1, 0x00, 0x60, 0x40, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD4, 0x60, 0x59, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x24, 0x40, 0x01, 0x26, 0x11, 0x00, 0x08, 0x60, +- 0x1E, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, +- 0x08, 0x60, 0x16, 0xFB, 0xD4, 0x60, 0x59, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x1E, 0xF1, 0x00, 0x60, 0x40, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, +- 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD4, 0x60, 0x59, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0xFD, 0x60, 0x89, 0x65, 0xF3, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x10, 0x60, +- 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x08, 0x60, 0x15, 0xFB, 0x5A, 0xDB, 0x10, 0x60, +- 0x4E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, +- 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xBB, 0xFE, 0xFD, 0x60, +- 0x40, 0x65, 0xF3, 0x60, 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x03, 0x64, 0x08, 0x60, +- 0x28, 0xFB, 0xD4, 0x60, 0x87, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, +- 0x27, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x07, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0x10, 0x60, 0x4E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xE2, 0x01, 0x10, 0x60, 0x4E, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, 0x20, 0x40, 0x04, 0x2B, 0x14, 0x00, +- 0x9B, 0xFE, 0x08, 0x04, 0xBB, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD4, 0x60, 0x95, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, +- 0x16, 0x60, 0xCC, 0xF3, 0x00, 0x61, 0x60, 0x40, 0x00, 0x36, 0x00, 0xB9, 0x60, 0x40, 0x01, 0x36, +- 0x01, 0xB9, 0x60, 0x40, 0x02, 0x36, 0x06, 0xB9, 0x60, 0x40, 0x03, 0x36, 0x07, 0xB9, 0x41, 0x44, +- 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, +- 0x08, 0x60, 0x16, 0xFB, 0xD4, 0x60, 0xC8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x7D, 0xF1, 0x13, 0x60, 0x1A, 0xF9, 0x0C, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, +- 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD4, 0x60, 0xE9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, +- 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x75, 0x00, 0x10, 0x60, 0x2A, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0xBA, 0xFE, 0x02, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, +- 0xF1, 0xFB, 0x44, 0x60, 0x44, 0x64, 0x7F, 0xFB, 0x80, 0xFB, 0x81, 0xFB, 0xFF, 0xFF, 0x20, 0x40, +- 0x04, 0x2B, 0x14, 0x00, 0x9B, 0xFE, 0x08, 0x04, 0xBB, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, +- 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, +- 0xD5, 0x60, 0x07, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x00, 0x65, +- 0x20, 0x44, 0x34, 0x80, 0x08, 0x60, 0x07, 0xF1, 0x02, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, +- 0x64, 0x40, 0x01, 0x2A, 0x06, 0x00, 0xA2, 0xDF, 0x02, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, +- 0xFF, 0xFF, 0xCF, 0xF3, 0x20, 0x60, 0x20, 0x65, 0x36, 0x1B, 0xA5, 0xD3, 0x24, 0x40, 0x01, 0x26, +- 0x16, 0x00, 0x60, 0x40, 0x20, 0x26, 0x2F, 0x00, 0x01, 0xBC, 0xA5, 0xDB, 0x08, 0x60, 0x1E, 0xF1, +- 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, +- 0x16, 0xFB, 0xD5, 0x60, 0x65, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x60, 0x40, +- 0x10, 0x26, 0x19, 0x00, 0x01, 0xBC, 0xA5, 0xDB, 0x08, 0x60, 0x1E, 0xF1, 0x00, 0x60, 0x40, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD5, 0x60, +- 0x65, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xFD, 0x60, 0x89, 0x65, 0xF3, 0x60, +- 0x58, 0x4E, 0x27, 0x78, 0xFF, 0xFF, 0xCF, 0xF1, 0x07, 0x60, 0xE9, 0xF3, 0x64, 0x40, 0x02, 0x3A, +- 0x0C, 0x00, 0x01, 0x63, 0x60, 0x40, 0x10, 0x22, 0x00, 0x63, 0x08, 0x60, 0xC1, 0xFD, 0x08, 0x60, +- 0xC5, 0xFD, 0x08, 0x60, 0xC9, 0xFD, 0x08, 0x60, 0xCD, 0xFD, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x01, 0x64, 0x53, 0xFB, 0x2F, 0x60, 0x02, 0x64, 0x54, 0xFB, 0x24, 0x40, 0x01, 0x26, +- 0x11, 0x00, 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD5, 0x60, 0xAB, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD5, 0x60, 0xAB, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xFD, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, +- 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x2A, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x86, 0xF1, 0x1B, 0x60, 0xB2, 0x63, 0xD3, 0x80, 0x20, 0x44, 0x03, 0x03, +- 0xD8, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0x87, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, 0xFF, 0xFF, 0x1B, 0x02, +- 0x24, 0x44, 0x04, 0x22, 0x12, 0x00, 0x24, 0x44, 0x01, 0xAC, 0xFB, 0xB4, 0x40, 0x44, 0xF7, 0x60, +- 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0xD4, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0xD2, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, +- 0xFF, 0xFF, 0x1F, 0x02, 0x87, 0x00, 0x20, 0x44, 0x10, 0xBC, 0x40, 0x40, 0x64, 0x42, 0x5A, 0xD1, +- 0x06, 0x63, 0xA4, 0xD1, 0xC3, 0x83, 0x7D, 0xF9, 0xBD, 0xD1, 0x7F, 0xF9, 0xBD, 0xD1, 0xFF, 0xFF, +- 0x80, 0xF9, 0xBD, 0xD1, 0x81, 0xF9, 0x04, 0xA3, 0xBD, 0xD1, 0x33, 0x60, 0xBE, 0x64, 0x64, 0x41, +- 0xDD, 0x81, 0xFE, 0xB1, 0xA0, 0xD9, 0x04, 0x03, 0xBD, 0xD1, 0xC9, 0x81, 0x58, 0xD9, 0xFC, 0x02, +- 0x39, 0x00, 0xE4, 0xF3, 0x7D, 0xFB, 0x66, 0x41, 0x60, 0x40, 0x01, 0x27, 0x06, 0x00, 0x10, 0x60, +- 0xF0, 0x63, 0x11, 0x60, 0x44, 0x65, 0x06, 0x66, 0x05, 0x00, 0x11, 0x60, 0x60, 0x63, 0x12, 0x60, +- 0x40, 0x65, 0x08, 0x66, 0xA3, 0xD1, 0x4B, 0x93, 0xD0, 0x80, 0xD7, 0x80, 0x02, 0x03, 0xFA, 0x04, +- 0x04, 0x00, 0x5B, 0x93, 0x02, 0xA3, 0x01, 0x64, 0xA3, 0xDB, 0x61, 0x46, 0x2F, 0x60, 0x02, 0x61, +- 0xA1, 0xD3, 0xFF, 0xFF, 0x00, 0xA8, 0x33, 0x60, 0xBE, 0x63, 0x02, 0x02, 0x2D, 0x60, 0x10, 0x61, +- 0xA1, 0xD3, 0xBD, 0xDB, 0xDC, 0x84, 0xFE, 0xB4, 0x59, 0xD1, 0xC8, 0x84, 0xBD, 0xD9, 0xFC, 0x02, +- 0xEC, 0xF3, 0x72, 0x45, 0xEB, 0xF3, 0x94, 0x83, 0x81, 0xFD, 0x94, 0x83, 0x80, 0xFD, 0x65, 0x5F, +- 0x02, 0x64, 0x7F, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, +- 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD6, 0x60, 0x3A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x7D, 0xF1, 0x13, 0x60, 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD6, 0x60, 0x5B, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, +- 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xD7, 0x60, +- 0x7B, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xEF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x02, 0x64, 0xDB, 0xFB, +- 0xF1, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, 0xF1, 0xFB, 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, +- 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, +- 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x24, 0x44, 0x02, 0x22, 0x03, 0x00, 0x01, 0xAC, 0x04, 0xBC, +- 0x40, 0x44, 0x32, 0x40, 0x80, 0x2A, 0x8C, 0x00, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD6, 0x60, 0x8C, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x95, 0xF3, 0xFF, 0xFF, 0x7F, 0xB4, 0x95, 0xFB, 0x26, 0x60, 0x34, 0x62, 0x06, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x2D, 0xFF, 0xFF, 0xFF, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xDA, 0xFE, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x12, 0x60, 0xFF, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x05, 0x03, 0x0E, 0xF2, 0xFF, 0xFF, +- 0x60, 0x40, 0x01, 0x2A, 0x22, 0x00, 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, +- 0x03, 0x03, 0x0F, 0xF2, 0xFF, 0xFF, 0x19, 0x1B, 0x08, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, +- 0xD6, 0x60, 0xE5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x01, 0x64, 0x19, 0x60, 0xF1, 0xFB, 0x19, 0x60, +- 0xF6, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x26, 0x05, 0x00, 0x89, 0xFF, 0x08, 0x60, 0x00, 0x75, +- 0x88, 0xFF, 0x01, 0x00, 0x10, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD6, 0x60, +- 0xE5, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x7D, 0xF1, 0x13, 0x60, 0x1A, 0xF9, 0x08, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, +- 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD7, 0x60, 0x0A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0xBA, 0xFE, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x1E, 0x00, +- 0xDA, 0xFE, 0xC1, 0xFE, 0x0E, 0x60, 0x36, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, 0x1C, 0x60, 0x92, 0x64, +- 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x60, 0x06, 0x64, +- 0x08, 0x60, 0x16, 0xFB, 0xD7, 0x60, 0x4E, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x00, 0x60, 0x02, 0x64, +- 0x08, 0x60, 0x28, 0xFB, 0xD7, 0x60, 0x55, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, 0x6C, 0x61, +- 0x75, 0x60, 0x30, 0x65, 0xA1, 0xD3, 0xFF, 0xFF, 0xFF, 0xA0, 0xE0, 0x84, 0x02, 0x02, 0x03, 0x60, +- 0xE8, 0x64, 0xD4, 0x80, 0xFF, 0xFF, 0x01, 0x04, 0x65, 0x44, 0xA1, 0xDB, 0x32, 0x40, 0x80, 0x2A, +- 0x03, 0x00, 0xD4, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, +- 0x27, 0xFB, 0x5A, 0xDB, 0xD4, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0x20, 0x40, 0x06, 0x23, 0x10, 0x00, +- 0x08, 0x60, 0x27, 0xF1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x80, 0x60, 0x00, 0x64, +- 0x08, 0x60, 0x28, 0xFB, 0xD7, 0x60, 0x55, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x10, 0x60, 0x4E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, +- 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0xD3, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0x78, 0xF3, 0x79, 0xFB, 0x20, 0x60, 0x14, 0x62, 0xA2, 0xDF, +- 0xFF, 0x60, 0xDF, 0x65, 0x20, 0x44, 0x24, 0x80, 0xBC, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, 0x1C, 0x60, +- 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xF7, 0x60, +- 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x10, 0x26, 0x38, 0x00, 0x00, 0x64, 0xB2, 0xFB, 0xB3, 0xFB, +- 0xB4, 0xFB, 0x00, 0x75, 0x00, 0x72, 0xBA, 0xF1, 0x7E, 0xF9, 0x64, 0x44, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x93, 0xE5, 0xF1, 0x84, 0xF9, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, +- 0x1E, 0x00, 0x19, 0x60, 0x44, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2A, 0x0A, 0x00, 0x0F, 0x64, +- 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0x67, 0x43, 0x1A, 0x60, 0xB3, 0xFD, 0x1A, 0x60, +- 0xC3, 0xFD, 0xD3, 0x60, 0x58, 0x4E, 0x78, 0x78, 0xFF, 0xFF, 0x00, 0x65, 0xFC, 0x60, 0x58, 0x4E, +- 0xC7, 0x78, 0xFF, 0xFF, 0xFD, 0x60, 0x58, 0x4E, 0x11, 0x78, 0xFF, 0xFF, 0x05, 0x00, 0xFF, 0x65, +- 0xFC, 0x60, 0x58, 0x4E, 0xC7, 0x78, 0xFF, 0xFF, 0x44, 0x00, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x00, 0x60, 0x84, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD7, 0x60, 0xDB, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x80, 0x64, 0xA0, 0x80, +- 0x9C, 0x84, 0x2B, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x08, 0x60, 0x15, 0xF1, 0xFF, 0x60, 0x7F, 0x61, +- 0xA1, 0x84, 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x2E, 0x60, 0x2E, 0x64, 0x2D, 0x60, +- 0x8A, 0x63, 0xA0, 0xD1, 0xA3, 0xD9, 0x64, 0x41, 0x58, 0xD1, 0x5B, 0xD9, 0x7D, 0xF3, 0x66, 0x45, +- 0xA6, 0xF5, 0x60, 0x40, 0x01, 0x27, 0x08, 0x00, 0x91, 0xFA, 0x61, 0x44, 0xFD, 0x60, 0x58, 0x4E, +- 0xAC, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x07, 0x00, 0x11, 0xF8, 0x64, 0x44, 0xFD, 0x60, 0x58, 0x4E, +- 0xAC, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x65, 0x46, 0x04, 0x00, 0xBB, 0xFE, 0xD4, 0x60, 0xF6, 0x78, +- 0xFF, 0xFF, 0x16, 0x60, 0xC2, 0xF1, 0x00, 0x65, 0x64, 0x40, 0x01, 0x36, 0x22, 0x65, 0x64, 0x40, +- 0x07, 0x36, 0x01, 0x65, 0x64, 0x40, 0x0A, 0x36, 0x01, 0x65, 0x64, 0x40, 0x0B, 0x36, 0x22, 0x65, +- 0xA6, 0xF3, 0x66, 0x5C, 0x60, 0x46, 0x1F, 0x63, 0xE3, 0x83, 0xBA, 0xF8, 0x02, 0xA6, 0x66, 0x44, +- 0xFC, 0x1F, 0x16, 0x60, 0xC2, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x07, 0x36, 0x03, 0x00, 0x0A, 0x36, +- 0x06, 0x00, 0x09, 0x00, 0xA6, 0xF3, 0x04, 0x65, 0x60, 0x46, 0xBA, 0xF8, 0x04, 0x00, 0xA6, 0xF3, +- 0x10, 0x65, 0x60, 0x46, 0xBA, 0xF8, 0x64, 0x46, 0xA6, 0xF3, 0x32, 0x41, 0x60, 0x45, 0x08, 0xB1, +- 0x66, 0x41, 0x16, 0x03, 0x65, 0x46, 0x17, 0x60, 0x80, 0xF3, 0x06, 0xF0, 0xE0, 0x84, 0xE0, 0x84, +- 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, 0xB0, 0x84, 0x06, 0xFA, 0x66, 0x43, 0x02, 0xA3, 0x63, 0x46, +- 0x06, 0xF0, 0xFF, 0xFF, 0xB0, 0x84, 0x06, 0xFA, 0x61, 0x46, 0x32, 0x44, 0x10, 0xBC, 0x40, 0x52, +- 0x01, 0x64, 0x10, 0x60, 0x0A, 0xFB, 0x0F, 0x4E, 0xEF, 0x60, 0x58, 0x4F, 0x3A, 0x78, 0xFF, 0xFF, +- 0x0E, 0x4F, 0x08, 0x60, 0x15, 0xF1, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x00, 0x60, +- 0x04, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD3, 0x60, 0xAE, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, +- 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xBB, 0xFE, +- 0x20, 0x44, 0x04, 0x27, 0x11, 0x00, 0x10, 0x26, 0x02, 0x00, 0xDB, 0xFE, 0x14, 0x00, 0x08, 0x60, +- 0x07, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x36, 0x07, 0x00, 0x01, 0x64, 0xA2, 0xDB, 0x01, 0x65, +- 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x64, 0x8A, 0xFB, 0xFF, 0x60, 0xEF, 0x65, 0x20, 0x44, +- 0x24, 0x80, 0x03, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, 0xC1, 0xFE, +- 0x00, 0x60, 0x02, 0x64, 0x08, 0x60, 0x28, 0xFB, 0xD8, 0x60, 0xAA, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x20, 0x40, 0x06, 0x23, 0x10, 0x00, 0x08, 0x60, 0x27, 0xF1, 0x7F, 0x60, +- 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x28, 0xFB, 0xD8, 0x60, +- 0xAA, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x4E, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, +- 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xD3, 0x60, 0xD0, 0x78, 0xFF, 0xFF, +- 0xBB, 0xFE, 0xD9, 0x60, 0xB0, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0xC2, 0xF1, 0x00, 0x65, 0x64, 0x40, +- 0x01, 0x36, 0x22, 0x65, 0xA6, 0xF3, 0x66, 0x5C, 0x60, 0x46, 0x1F, 0x63, 0xE3, 0x83, 0xBA, 0xF8, +- 0x02, 0xA6, 0x66, 0x44, 0xFC, 0x1F, 0x64, 0x46, 0xA6, 0xF1, 0x02, 0x64, 0xC0, 0x85, 0x0C, 0x61, +- 0x32, 0x40, 0x08, 0x2A, 0x14, 0x00, 0x17, 0x60, 0x80, 0xF3, 0x66, 0x41, 0x65, 0x46, 0x06, 0xF0, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x80, 0xBF, 0xB0, 0x83, 0x06, 0xFC, 0x66, 0x42, +- 0xFE, 0xA2, 0x62, 0x46, 0x06, 0xF0, 0xFF, 0xFF, 0xB0, 0x84, 0x06, 0xFA, 0x61, 0x46, 0x0B, 0x64, +- 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, 0x01, 0x65, 0xF1, 0x60, 0x58, 0x4E, +- 0xC3, 0x78, 0xFF, 0xFF, 0xE4, 0xF1, 0x7D, 0xF9, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD9, 0x60, 0x0C, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7D, 0xF1, 0x13, 0x60, 0x1A, 0xF9, 0x0E, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD9, 0x60, +- 0x2D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x15, 0xFB, +- 0x5A, 0xDB, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x01, 0x64, 0x8A, 0xFB, 0xFF, 0x60, 0xDF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x2F, 0x58, +- 0xFF, 0xFF, 0x06, 0x64, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, 0xE4, 0xF1, +- 0x7D, 0xF9, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x64, 0x8A, 0xFB, 0xFF, 0x60, +- 0xDF, 0x65, 0x20, 0x44, 0x24, 0x80, 0xA6, 0xF1, 0x66, 0x45, 0x64, 0x46, 0x66, 0x43, 0x02, 0xA3, +- 0x63, 0x46, 0x02, 0x64, 0x06, 0xFA, 0x04, 0x63, 0x04, 0x61, 0x01, 0x60, 0xCC, 0x64, 0x58, 0xD1, +- 0x59, 0xD8, 0xFD, 0x1F, 0x65, 0x46, 0x01, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, +- 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x67, 0xFB, 0x68, 0xFB, 0xA6, 0xF1, 0x0E, 0x64, 0x66, 0x41, +- 0x64, 0x42, 0x02, 0xA2, 0x62, 0x46, 0x06, 0xF0, 0xFF, 0x60, 0xFC, 0x64, 0xA0, 0x84, 0x06, 0xFA, +- 0x61, 0x46, 0xDB, 0xF3, 0xFF, 0xFF, 0x04, 0xA8, 0x10, 0x60, 0x0E, 0x64, 0x07, 0x03, 0xA0, 0xD1, +- 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x2A, 0x02, 0x00, 0x00, 0x63, 0xA0, 0xDD, 0x01, 0x64, 0xDB, 0xFB, +- 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, 0x00, 0x63, 0x08, 0x60, 0x77, 0xFD, 0x10, 0x60, +- 0x4E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, 0x10, 0x60, +- 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x02, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD3, 0x60, +- 0x9C, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, +- 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2E, 0x58, 0xFF, 0xFF, +- 0x40, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xB9, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, 0x5F, 0xF5, 0xEA, 0xF1, +- 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0xB9, 0xF1, 0x19, 0xF8, 0xF8, 0x60, +- 0x80, 0x64, 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0xA6, 0xF1, 0x07, 0xF8, 0x1B, 0x60, 0xB0, 0x64, +- 0x00, 0x60, 0x67, 0xFB, 0x44, 0x60, 0x44, 0x64, 0x7F, 0xFB, 0x80, 0xFB, 0x81, 0xFB, 0x31, 0x44, +- 0xF9, 0xB4, 0x40, 0x51, 0x00, 0x60, 0xCE, 0x63, 0x01, 0x60, 0x0C, 0x65, 0xA3, 0xD3, 0xA5, 0xD1, +- 0x04, 0xA4, 0xA3, 0xDB, 0xD0, 0x80, 0xA0, 0xD1, 0x0A, 0x06, 0x41, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xD6, 0x60, 0x6A, 0x78, 0xFF, 0xFF, 0x44, 0x47, +- 0x16, 0x60, 0xC2, 0xF3, 0xFF, 0xFF, 0xFF, 0xA4, 0xFF, 0xFF, 0x09, 0x07, 0x0E, 0x61, 0x41, 0xD3, +- 0x32, 0x40, 0x08, 0x26, 0x04, 0x00, 0x10, 0xB0, 0xFF, 0xFF, 0x01, 0x03, 0xD3, 0x01, 0x42, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, +- 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xD9, 0x60, 0xFA, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD1, 0x7D, 0xF9, 0x13, 0x60, 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xDA, 0x60, 0x1C, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x07, 0x60, 0xD0, 0x64, 0x0E, 0x60, 0x4B, 0xFB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, +- 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD3, 0x7F, 0xFB, +- 0xBD, 0xD3, 0x80, 0xFB, 0xA3, 0xD3, 0x81, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x01, 0x60, 0x04, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xDA, 0x60, 0x4A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0xB9, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, 0x08, 0x60, 0x15, 0xF1, 0xFE, 0x60, +- 0xFF, 0x61, 0xA1, 0x84, 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x08, 0x60, 0x15, 0xF1, +- 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xD9, 0x60, +- 0xCA, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x08, 0x65, 0x20, 0x44, 0x34, 0x80, 0x7D, 0xF1, 0x32, 0x60, +- 0x7A, 0x61, 0xA1, 0xD3, 0x64, 0x40, 0x01, 0x27, 0x59, 0xD3, 0x32, 0x60, 0x7E, 0x61, 0xFD, 0x60, +- 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0xA1, 0xDB, 0x5E, 0xF5, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, +- 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0xB9, 0xF1, 0x19, 0xF8, 0x80, 0x7E, 0xF8, 0x7F, 0x0E, 0xFA, +- 0x00, 0x64, 0x3E, 0xFA, 0xA6, 0xF1, 0x07, 0xF8, 0x2B, 0xFA, 0xB0, 0x64, 0x2A, 0xFA, 0x27, 0x43, +- 0x06, 0xA3, 0xBD, 0xD1, 0x2C, 0xF8, 0x32, 0xF8, 0xBD, 0xD1, 0x2D, 0xF8, 0x33, 0xF8, 0xA3, 0xD1, +- 0x2E, 0xF8, 0x34, 0xF8, 0x06, 0x63, 0x3F, 0xFC, 0x20, 0x60, 0x16, 0x61, 0xDB, 0xF3, 0xA1, 0xD3, +- 0x03, 0xA8, 0xAC, 0x83, 0x0E, 0x02, 0x0D, 0x03, 0x20, 0x60, 0x18, 0x61, 0xA1, 0xD1, 0x66, 0x45, +- 0x00, 0xF4, 0x09, 0xFC, 0x01, 0x64, 0x0A, 0xFA, 0x0B, 0xF8, 0x20, 0x60, 0x16, 0x61, 0xA1, 0xDF, +- 0x25, 0x00, 0x16, 0x60, 0xC3, 0xF3, 0x66, 0x45, 0x00, 0xF4, 0x60, 0x40, 0x01, 0x36, 0x15, 0x00, +- 0x02, 0x36, 0xBD, 0x00, 0x03, 0x36, 0x07, 0x00, 0x04, 0x36, 0x0F, 0x00, 0x05, 0x36, 0xB7, 0x00, +- 0x06, 0x36, 0x01, 0x00, 0x0A, 0x00, 0x80, 0x64, 0x09, 0xFA, 0x01, 0x63, 0x0A, 0xFC, 0x00, 0x64, +- 0x0B, 0xFA, 0x80, 0x60, 0xF4, 0x62, 0xA2, 0xDF, 0x09, 0x00, 0x00, 0x64, 0x09, 0xFA, 0x01, 0x63, +- 0x0A, 0xFC, 0x00, 0x64, 0x0B, 0xFA, 0x80, 0x60, 0xF4, 0x62, 0xA2, 0xDF, 0x25, 0x60, 0xCE, 0x64, +- 0x13, 0x60, 0x0D, 0xFB, 0x65, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0x00, 0x66, 0xDB, 0xF3, 0x46, 0x46, 0xFD, 0xA0, 0xC1, 0xFE, 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, +- 0x01, 0x64, 0x68, 0xFB, 0x43, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0E, 0x60, 0x38, 0xF3, 0xFF, 0xFF, +- 0x64, 0xA4, 0xA2, 0xDB, 0x0E, 0x60, 0x38, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, 0x1C, 0x60, 0x92, 0x64, +- 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x60, 0x0C, 0x64, +- 0x08, 0x60, 0x16, 0xFB, 0xDB, 0x60, 0x00, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x55, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x26, 0x46, +- 0x00, 0xF4, 0x09, 0xF2, 0x0A, 0xF2, 0x00, 0xA8, 0x0B, 0xF2, 0x02, 0xA8, 0x16, 0x02, 0x00, 0xA8, +- 0x1A, 0x02, 0x19, 0x02, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, +- 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, 0xDC, 0x60, +- 0xF6, 0x78, 0xFF, 0xFF, 0xE3, 0x60, 0x69, 0x78, 0xFF, 0xFF, 0x09, 0xF2, 0x0A, 0xF2, 0x80, 0xA8, +- 0x0B, 0xF2, 0x02, 0xA8, 0xE4, 0x03, 0x44, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0B, 0xF2, 0x26, 0x46, +- 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, +- 0x31, 0xF2, 0x59, 0xDB, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, +- 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0x96, 0x78, +- 0xFF, 0xFF, 0xE7, 0x60, 0x0B, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xFB, 0x64, 0xA0, 0x84, 0xA2, 0xDB, +- 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x20, 0x40, 0x08, 0x2A, +- 0x03, 0x00, 0xD9, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0xE2, 0x60, 0x73, 0x78, 0xFF, 0xFF, 0x01, 0x63, +- 0x09, 0xFC, 0x32, 0x40, 0x08, 0x26, 0x14, 0x00, 0x16, 0x60, 0xC2, 0xF3, 0xFF, 0xFF, 0x60, 0x40, +- 0x0B, 0x36, 0x03, 0x00, 0xDA, 0x60, 0xC5, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0xA2, 0xDB, 0x0B, 0x64, +- 0x19, 0x60, 0xA4, 0xFB, 0xA6, 0xF1, 0x66, 0x41, 0x64, 0x46, 0x22, 0x64, 0x3A, 0xFA, 0x61, 0x46, +- 0x01, 0x64, 0x0A, 0xFA, 0x00, 0x64, 0x0B, 0xFA, 0x01, 0x64, 0x40, 0x60, 0x7A, 0xFB, 0x01, 0x64, +- 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, +- 0x0D, 0xFB, 0x65, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, +- 0xDB, 0xF3, 0x46, 0x46, 0xFD, 0xA0, 0xC1, 0xFE, 0x02, 0x02, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, +- 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x60, +- 0x0C, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xDB, 0x60, 0xB9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x3A, 0x03, +- 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x68, 0xFB, 0x26, 0x46, 0x00, 0xF4, 0x09, 0xF2, 0x0A, 0xF2, +- 0x01, 0xA8, 0x0B, 0xF2, 0x02, 0xA8, 0x04, 0x02, 0x00, 0xA8, 0x02, 0x02, 0x01, 0x02, 0x31, 0x00, +- 0xDC, 0x60, 0x58, 0x4D, 0xB9, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, 0x26, 0x46, 0x40, 0x59, 0x02, 0x60, +- 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x31, 0xF2, 0x59, 0xDB, +- 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, +- 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0xE7, 0x60, +- 0x0B, 0x78, 0xFF, 0xFF, 0xDC, 0x60, 0x58, 0x4D, 0xB9, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x68, 0xFB, +- 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, 0xD9, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0xE2, 0x60, 0x73, 0x78, +- 0xFF, 0xFF, 0x26, 0x46, 0x40, 0x60, 0x00, 0x65, 0x2A, 0xF2, 0x2F, 0xF0, 0xB4, 0x84, 0x2A, 0xFA, +- 0x2C, 0xF8, 0x32, 0xF8, 0x30, 0xF2, 0x2D, 0xFA, 0x33, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x34, 0xFA, +- 0xEA, 0xF3, 0x2F, 0xFA, 0xEB, 0xF3, 0x30, 0xFA, 0xEC, 0xF3, 0x31, 0xFA, 0xC9, 0xF1, 0x19, 0xF8, +- 0x1C, 0xF0, 0x13, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x00, 0xF4, 0x03, 0x64, 0x0A, 0xFA, 0x00, 0x64, +- 0x0B, 0xFA, 0x01, 0x63, 0x68, 0xFD, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x25, 0x60, +- 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0x00, 0x66, 0xDB, 0xF3, 0x46, 0x46, 0xFD, 0xA0, 0xC1, 0xFE, 0x02, 0x02, 0x2F, 0x58, +- 0xFF, 0xFF, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x00, 0x60, 0x0C, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xDC, 0x60, 0x53, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, +- 0x9C, 0x84, 0x50, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, +- 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x68, 0xFB, 0x26, 0x46, 0x00, 0xF4, +- 0x09, 0xF2, 0x0A, 0xF2, 0x01, 0xA8, 0x0B, 0xF2, 0x04, 0xA8, 0x1A, 0x02, 0x00, 0xA8, 0x18, 0x02, +- 0x17, 0x02, 0xDC, 0x60, 0x58, 0x4D, 0xB9, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, +- 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x20, 0x40, +- 0x08, 0x2A, 0x03, 0x00, 0xDC, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0xE3, 0x60, 0x69, 0x78, 0xFF, 0xFF, +- 0xDC, 0x60, 0x58, 0x4D, 0xB9, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, 0x26, 0x46, 0x40, 0x59, 0x02, 0x60, +- 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x31, 0xF2, 0x59, 0xDB, +- 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, +- 0x00, 0x66, 0x46, 0x46, 0x03, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0xE7, 0x60, +- 0x0B, 0x78, 0xFF, 0xFF, 0xDC, 0x60, 0x58, 0x4D, 0xB9, 0x78, 0xFF, 0xFF, 0x00, 0x64, 0x68, 0xFB, +- 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, 0xD9, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0xE2, 0x60, 0x73, 0x78, +- 0xFF, 0xFF, 0x19, 0x60, 0xA4, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x0B, 0x3A, 0x06, 0x00, 0x0B, 0x64, +- 0x16, 0x60, 0xC2, 0xFB, 0x33, 0x60, 0x48, 0x62, 0xA2, 0xDF, 0x2D, 0x58, 0xFF, 0xFF, 0x16, 0x60, +- 0xC2, 0xF1, 0xA5, 0xD2, 0x64, 0x40, 0x0B, 0x2A, 0x20, 0x00, 0x85, 0x36, 0x0B, 0x00, 0x32, 0x3A, +- 0x1E, 0x00, 0x60, 0x47, 0xFF, 0xB4, 0x02, 0xA4, 0xC4, 0x85, 0xA5, 0xD2, 0xFF, 0xFF, 0x60, 0x40, +- 0x85, 0x3A, 0x15, 0x00, 0x65, 0x44, 0x0A, 0xA4, 0xA0, 0xD0, 0x33, 0x60, 0x46, 0x62, 0x64, 0x40, +- 0x18, 0x26, 0x09, 0x00, 0xA2, 0xDF, 0x01, 0x64, 0x16, 0x60, 0xC2, 0xFB, 0x32, 0x41, 0x08, 0x65, +- 0xB5, 0x81, 0x41, 0x52, 0x02, 0x00, 0x01, 0x64, 0xA2, 0xDB, 0x2D, 0x58, 0xFF, 0xFF, 0x33, 0x60, +- 0x46, 0x62, 0xA2, 0xDF, 0x01, 0x64, 0x16, 0x60, 0xC2, 0xFB, 0xF7, 0x01, 0x45, 0x64, 0x3B, 0x42, +- 0x5A, 0xDB, 0x35, 0x60, 0xAA, 0x7C, 0x35, 0x60, 0x98, 0x63, 0xA3, 0xD9, 0x64, 0x41, 0x2F, 0x60, +- 0x02, 0x63, 0xBD, 0xD3, 0x00, 0x7C, 0x03, 0x1B, 0x27, 0x43, 0x10, 0xA3, 0xBD, 0xD3, 0xFF, 0xFF, +- 0x60, 0x45, 0x64, 0x5F, 0xA1, 0xDB, 0x65, 0x44, 0xBD, 0xD1, 0xC8, 0x84, 0x59, 0xD8, 0xFC, 0x05, +- 0x27, 0x41, 0x10, 0xA1, 0xA1, 0xD1, 0xFF, 0xFF, 0xC1, 0x81, 0x01, 0x26, 0xDD, 0x81, 0x41, 0x4C, +- 0x59, 0xD1, 0x7C, 0x44, 0xB0, 0x84, 0x59, 0xD1, 0x59, 0xD1, 0xB0, 0x84, 0xB0, 0x84, 0xFF, 0xFF, +- 0x02, 0x02, 0x67, 0x44, 0xC2, 0x00, 0x34, 0x60, 0x5C, 0x63, 0xD9, 0x81, 0x59, 0xD3, 0x38, 0x60, +- 0x10, 0x62, 0x00, 0xBC, 0xA2, 0xDF, 0x09, 0x03, 0x01, 0x7C, 0xA2, 0xD9, 0x30, 0x60, 0x14, 0x64, +- 0xBD, 0xDA, 0x00, 0x60, 0x01, 0x64, 0xBD, 0xDA, 0x58, 0x00, 0xDD, 0x60, 0x18, 0x64, 0xBD, 0xDA, +- 0x50, 0x60, 0x00, 0x64, 0xBD, 0xDA, 0x01, 0x60, 0xF2, 0x64, 0xBD, 0xDA, 0x00, 0x60, 0x01, 0x64, +- 0xBD, 0xDA, 0x2C, 0x41, 0x59, 0xD3, 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, +- 0x01, 0x60, 0xF2, 0x64, 0x0E, 0x00, 0x04, 0x2A, 0x03, 0x00, 0x02, 0x60, 0xF2, 0x64, 0x09, 0x00, +- 0x10, 0x2A, 0x03, 0x00, 0x04, 0x60, 0xF2, 0x64, 0x04, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, +- 0xF2, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, 0x01, 0x64, 0xBD, 0xDB, 0x59, 0xD3, 0x50, 0x60, 0x00, 0x7C, +- 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, 0xF2, 0x64, 0x0E, 0x00, 0x04, 0x2A, 0x03, 0x00, +- 0x02, 0x60, 0xF2, 0x64, 0x09, 0x00, 0x10, 0x2A, 0x03, 0x00, 0x04, 0x60, 0xF2, 0x64, 0x04, 0x00, +- 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, 0xF2, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, 0x01, 0x64, 0xBD, 0xDB, +- 0x59, 0xD3, 0x50, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x00, 0x60, 0xF2, 0x64, +- 0x09, 0x00, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, 0xF2, 0x64, 0x04, 0x00, 0x04, 0x2A, 0x02, 0x00, +- 0x02, 0x60, 0xF2, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, 0x4B, 0x00, 0x2C, 0x41, 0x59, 0xD3, 0x0F, 0x60, +- 0x00, 0x7C, 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, 0xAC, 0x64, 0x0E, 0x00, 0x04, 0x2A, +- 0x03, 0x00, 0x02, 0x60, 0xAC, 0x64, 0x09, 0x00, 0x10, 0x2A, 0x03, 0x00, 0x04, 0x60, 0xAC, 0x64, +- 0x04, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, 0xAC, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, 0x01, 0x64, +- 0xBD, 0xDB, 0x59, 0xD3, 0x0F, 0x60, 0x00, 0x7C, 0x60, 0x40, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, +- 0xAC, 0x64, 0x0E, 0x00, 0x04, 0x2A, 0x03, 0x00, 0x02, 0x60, 0xAC, 0x64, 0x09, 0x00, 0x10, 0x2A, +- 0x03, 0x00, 0x04, 0x60, 0xAC, 0x64, 0x04, 0x00, 0x20, 0x2A, 0x04, 0x00, 0x05, 0x60, 0xAC, 0x64, +- 0xBD, 0xD9, 0xBD, 0xDB, 0x01, 0x64, 0xBD, 0xDB, 0x59, 0xD3, 0x0F, 0x60, 0x00, 0x7C, 0x60, 0x40, +- 0x01, 0x2A, 0x03, 0x00, 0x00, 0x60, 0xAC, 0x64, 0x09, 0x00, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x60, +- 0xAC, 0x64, 0x04, 0x00, 0x04, 0x2A, 0x02, 0x00, 0x02, 0x60, 0xAC, 0x64, 0xBD, 0xD9, 0xBD, 0xDB, +- 0x1C, 0x60, 0x08, 0xF3, 0xFF, 0xFF, 0x03, 0x18, 0x1A, 0x60, 0x2D, 0xF3, 0x03, 0x00, 0x1A, 0x60, +- 0x1D, 0xF3, 0xFF, 0xFF, 0xBD, 0xDA, 0x34, 0x60, 0x5C, 0x64, 0x1A, 0x60, 0xCF, 0xFB, 0x5F, 0xF5, +- 0x00, 0x64, 0x2B, 0xFA, 0x00, 0x64, 0x2A, 0xFA, 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD1, 0x2C, 0xF8, +- 0x32, 0xF8, 0xBD, 0xD1, 0x2D, 0xF8, 0x33, 0xF8, 0xA3, 0xD1, 0x2E, 0xF8, 0x34, 0xF8, 0x00, 0xF4, +- 0x01, 0x63, 0x32, 0x40, 0x08, 0x26, 0x10, 0xBB, 0x16, 0x60, 0xC2, 0xF1, 0xFF, 0xFF, 0x64, 0x40, +- 0xFE, 0x26, 0x10, 0xBB, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x0A, 0x00, 0x19, 0x60, +- 0x45, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x22, 0x20, 0xBB, 0x63, 0x44, 0xFF, 0xFF, 0x04, 0x7F, +- 0x60, 0x43, 0x09, 0xFC, 0x27, 0x42, 0x0C, 0xA2, 0x2D, 0x60, 0x5A, 0x63, 0xA2, 0xD3, 0xA3, 0xD3, +- 0x00, 0xBD, 0x01, 0x63, 0xAC, 0x81, 0x09, 0x03, 0x08, 0x03, 0xB8, 0x60, 0x58, 0x4D, 0x15, 0x78, +- 0xFF, 0xFF, 0x00, 0xB8, 0x01, 0x63, 0x01, 0x03, 0x60, 0x43, 0x0E, 0x60, 0x35, 0xFD, 0x12, 0x61, +- 0x59, 0xDC, 0x16, 0x60, 0xC2, 0xF3, 0xFF, 0x60, 0xFF, 0x7C, 0x60, 0x40, 0x0B, 0x2A, 0x02, 0x00, +- 0x33, 0x60, 0x28, 0x7C, 0x1A, 0x60, 0xD0, 0xF9, 0x35, 0x60, 0x98, 0x64, 0x40, 0x48, 0xD9, 0x81, +- 0xFF, 0x60, 0xF2, 0x64, 0xF1, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x5F, 0xF5, 0x3F, 0xFC, +- 0xDB, 0x83, 0x1A, 0x60, 0x4C, 0xFD, 0x00, 0x7C, 0x5A, 0xD9, 0x63, 0x41, 0x34, 0x60, 0x9C, 0x63, +- 0x12, 0x65, 0x00, 0xF4, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, +- 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, +- 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x5F, 0xF5, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, +- 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, +- 0x46, 0x46, 0xC1, 0xFE, 0x06, 0x64, 0x68, 0xFB, 0x46, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x1C, 0x60, +- 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x60, +- 0x1C, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xDE, 0x60, 0x84, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0xDE, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x08, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0xF6, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, +- 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x26, 0x46, 0x00, 0xF4, 0x0A, 0xF2, 0x00, 0x63, 0x00, 0xA8, 0x68, 0xFD, 0x06, 0x02, +- 0x09, 0xF2, 0xFF, 0xFF, 0x01, 0xB0, 0x01, 0x7C, 0x5A, 0x02, 0x0A, 0xF8, 0x0A, 0xF2, 0x26, 0x46, +- 0x40, 0x59, 0x02, 0x60, 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, +- 0x31, 0xF2, 0x59, 0xDB, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, +- 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x05, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0x96, 0x78, +- 0xFF, 0xFF, 0xE7, 0x60, 0x0B, 0x78, 0xFF, 0xFF, 0x47, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xD9, 0x60, +- 0xCA, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x20, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, +- 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x49, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xDA, 0x60, 0x62, 0x78, 0xFF, 0xFF, 0xFF, 0x60, +- 0xFB, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x4A, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xD9, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0x48, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x0C, 0xF2, 0xFF, 0xFF, 0x60, 0x41, 0xFF, 0xB1, 0xFF, 0xA1, 0x60, 0x47, +- 0xFF, 0xB4, 0x9B, 0x02, 0x9A, 0x03, 0x34, 0x60, 0xF4, 0x63, 0x10, 0x64, 0xBD, 0xDB, 0x66, 0x45, +- 0x26, 0x46, 0x3F, 0xF2, 0x34, 0x60, 0xF2, 0x61, 0xC2, 0xA0, 0xFF, 0xFF, 0x01, 0x04, 0x3E, 0x64, +- 0x65, 0x46, 0x02, 0xA4, 0xA1, 0xDB, 0xC8, 0x81, 0x12, 0x65, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, +- 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, +- 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x0C, 0xF2, +- 0xFF, 0xFF, 0x1A, 0x65, 0x60, 0x47, 0xFF, 0xB4, 0xC4, 0x85, 0xDC, 0x60, 0x58, 0x4D, 0xC7, 0x78, +- 0xFF, 0xFF, 0x0B, 0xF2, 0xFF, 0xFF, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, +- 0xFD, 0x02, 0x61, 0x44, 0x94, 0xFB, 0x27, 0x45, 0x02, 0x62, 0x46, 0xD3, 0x5A, 0xD1, 0x60, 0x47, +- 0x56, 0xFB, 0x64, 0x47, 0x55, 0xFB, 0x00, 0x64, 0x5B, 0xFB, 0x0C, 0x62, 0x46, 0xD3, 0x7E, 0xFB, +- 0x0B, 0xF0, 0x0F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0x83, 0xFB, 0x26, 0x46, 0x32, 0xF0, 0x7F, 0xF9, +- 0x33, 0xF0, 0x0E, 0x63, 0xC7, 0x81, 0x80, 0xF9, 0x34, 0xF0, 0x81, 0xF9, 0x59, 0xD1, 0xFF, 0xFF, +- 0x64, 0x44, 0x01, 0x2A, 0xC8, 0x84, 0x60, 0x43, 0x33, 0x60, 0xBC, 0x64, 0x58, 0xD9, 0x59, 0xD1, +- 0x58, 0xD9, 0xFD, 0x1F, 0x16, 0x60, 0xC2, 0xF1, 0x59, 0xD3, 0x64, 0x40, 0x01, 0x36, 0x22, 0x64, +- 0x64, 0x40, 0x00, 0x36, 0x50, 0x94, 0xA6, 0xF1, 0xFF, 0xFF, 0x44, 0x47, 0xA7, 0x46, 0x3A, 0xFA, +- 0xBB, 0xFC, 0xA7, 0x46, 0x0E, 0x60, 0x35, 0xF3, 0x85, 0xFB, 0x2E, 0x60, 0x2E, 0x64, 0x2D, 0x60, +- 0x8A, 0x63, 0xA0, 0xD1, 0xA3, 0xD9, 0x64, 0x41, 0x58, 0xD1, 0x5B, 0xD9, 0x7D, 0xF3, 0x66, 0x45, +- 0xA6, 0xF5, 0x60, 0x40, 0x01, 0x27, 0x08, 0x00, 0x91, 0xFA, 0x61, 0x44, 0xFD, 0x60, 0x58, 0x4E, +- 0xAC, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x07, 0x00, 0x11, 0xF8, 0x64, 0x44, 0xFD, 0x60, 0x58, 0x4E, +- 0xAC, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x65, 0x46, 0x31, 0xF2, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, +- 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, +- 0x61, 0x46, 0x31, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x30, 0xF0, +- 0x63, 0x46, 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x2F, 0xF0, 0x63, 0x46, 0xD0, 0x80, +- 0xFF, 0xFF, 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, +- 0x60, 0x43, 0x61, 0x46, 0xA6, 0xF1, 0xFF, 0xFF, 0xD3, 0x80, 0x31, 0xF2, 0x27, 0x02, 0x66, 0x41, +- 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, 0xA6, 0xF1, 0xE0, 0x84, 0x44, 0xD3, 0x64, 0x43, +- 0x11, 0x18, 0x60, 0x46, 0x00, 0xF2, 0xFF, 0xFF, 0xFC, 0x1B, 0x66, 0x44, 0x64, 0x46, 0x80, 0xF0, +- 0x60, 0x46, 0x80, 0xF8, 0x65, 0x46, 0x65, 0x43, 0x80, 0xF0, 0x01, 0xFA, 0x80, 0xFC, 0x64, 0x46, +- 0x80, 0xF8, 0x0B, 0x00, 0x64, 0x46, 0x62, 0x43, 0x00, 0xF2, 0xA3, 0xDB, 0x60, 0x46, 0x80, 0xF0, +- 0x81, 0xFC, 0x80, 0xFC, 0x64, 0x46, 0x80, 0xF8, 0x60, 0x43, 0x61, 0x46, 0x43, 0x4B, 0x01, 0x65, +- 0xFD, 0x60, 0x58, 0x4E, 0xDD, 0x78, 0xFF, 0xFF, 0x43, 0x47, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, +- 0xFA, 0xA3, 0x00, 0x60, 0x17, 0x61, 0x00, 0x60, 0x01, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, +- 0xFD, 0x60, 0x58, 0x4E, 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x64, +- 0x40, 0x4A, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, +- 0x58, 0x4E, 0x2C, 0x78, 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0x65, 0x00, 0x64, 0x19, 0x60, 0x3B, 0xFB, +- 0x02, 0x00, 0x20, 0xFE, 0xFF, 0x65, 0x02, 0x60, 0x00, 0x63, 0x60, 0xFE, 0xBD, 0xD3, 0xBD, 0xD3, +- 0x60, 0x41, 0x20, 0xFE, 0xCD, 0x81, 0x60, 0x40, 0x80, 0x2A, 0x39, 0x00, 0x7F, 0xB4, 0x02, 0x3A, +- 0x02, 0x00, 0x01, 0x64, 0x2E, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, 0x2A, 0x00, 0x0B, 0x3A, +- 0x02, 0x00, 0x04, 0x64, 0x26, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x22, 0x00, 0x0C, 0x3A, +- 0x02, 0x00, 0x10, 0x64, 0x1E, 0x00, 0x12, 0x3A, 0x02, 0x00, 0x20, 0x64, 0x1A, 0x00, 0x18, 0x3A, +- 0x02, 0x00, 0x40, 0x64, 0x16, 0x00, 0x24, 0x3A, 0x02, 0x00, 0x80, 0x64, 0x12, 0x00, 0x30, 0x3A, +- 0x02, 0x00, 0x01, 0x67, 0x0E, 0x00, 0x48, 0x3A, 0x02, 0x00, 0x02, 0x67, 0x0A, 0x00, 0x60, 0x3A, +- 0x02, 0x00, 0x04, 0x67, 0x06, 0x00, 0x6C, 0x3A, 0x02, 0x00, 0x08, 0x67, 0x02, 0x00, 0x00, 0x64, +- 0x00, 0x00, 0x19, 0x60, 0x3B, 0xF1, 0xFF, 0xFF, 0xB0, 0x84, 0x19, 0x60, 0x3B, 0xFB, 0x61, 0x40, +- 0x00, 0x36, 0x05, 0x00, 0x60, 0xFE, 0xBD, 0xD3, 0xFF, 0xFF, 0x20, 0xFE, 0xBB, 0x01, 0x65, 0x40, +- 0x00, 0x3A, 0x1E, 0x00, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xFA, 0xA3, 0x00, 0x60, +- 0x17, 0x61, 0x00, 0x60, 0x32, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, +- 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x0B, 0x03, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, +- 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, 0x58, 0x4E, 0x2C, 0x78, 0xFF, 0xFF, 0x91, 0x01, +- 0x20, 0xFE, 0x00, 0x65, 0xFC, 0x60, 0x58, 0x4E, 0xC7, 0x78, 0xFF, 0xFF, 0xA1, 0xF3, 0xFF, 0xFF, +- 0x60, 0x40, 0x01, 0x27, 0x04, 0x00, 0xFD, 0x60, 0x58, 0x4E, 0x11, 0x78, 0xFF, 0xFF, 0x20, 0xFE, +- 0x37, 0x60, 0xF8, 0x61, 0xA1, 0xD1, 0xA1, 0xF3, 0x01, 0x60, 0xAC, 0x63, 0x60, 0x45, 0x2A, 0x44, +- 0x79, 0xFB, 0xA3, 0xD5, 0x65, 0x40, 0x01, 0x27, 0x5B, 0xD5, 0x65, 0x40, 0x01, 0x27, 0x59, 0xD1, +- 0x66, 0x41, 0xA0, 0x84, 0x24, 0x94, 0x2B, 0x46, 0x0F, 0xFA, 0x7A, 0xFB, 0x16, 0x64, 0x12, 0xFA, +- 0x01, 0x64, 0x11, 0xFA, 0x66, 0x5C, 0xC2, 0x60, 0x58, 0x4E, 0x6D, 0x78, 0xFF, 0xFF, 0x1A, 0x60, +- 0x22, 0xF3, 0x1A, 0x60, 0x21, 0xF1, 0x60, 0x47, 0xB0, 0x84, 0x1C, 0x60, 0x08, 0xF1, 0xFF, 0xFF, +- 0x01, 0x18, 0x80, 0xBC, 0x16, 0x60, 0xC2, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x22, 0x64, +- 0x64, 0x40, 0x00, 0x36, 0x50, 0x94, 0xA7, 0x46, 0x3A, 0xFA, 0xBB, 0xFC, 0xA7, 0x46, 0x80, 0x60, +- 0x03, 0x65, 0x32, 0x40, 0x08, 0x2A, 0x03, 0x65, 0xA7, 0x46, 0x06, 0xF0, 0x7F, 0x60, 0xFF, 0x64, +- 0xA0, 0x84, 0xB4, 0x84, 0x06, 0xFA, 0xBB, 0xFC, 0xA7, 0x46, 0x26, 0x46, 0x2F, 0xF0, 0x30, 0xF0, +- 0x64, 0x43, 0x31, 0xF2, 0x27, 0x46, 0x03, 0xFC, 0x04, 0xF8, 0x05, 0xFA, 0x26, 0x46, 0xD9, 0x60, +- 0x58, 0x4E, 0xAE, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, +- 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0x01, 0x64, 0x8A, 0xFB, 0x16, 0x60, +- 0xC9, 0xF3, 0x20, 0x41, 0x00, 0xBC, 0x20, 0xB9, 0x01, 0x03, 0x41, 0x40, 0x20, 0x60, 0x14, 0x61, +- 0xA1, 0xDF, 0x04, 0x64, 0xC1, 0xFE, 0xDB, 0xFB, 0xF1, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xF1, 0xFB, +- 0xF7, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, +- 0x33, 0x60, 0xE6, 0x65, 0xA5, 0xDF, 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x0C, 0x64, 0x68, 0xFB, 0x00, 0x60, 0x31, 0x64, 0x08, 0x60, 0x16, 0xFB, +- 0xE1, 0x60, 0x36, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x00, 0x60, 0x02, 0x64, 0x08, 0x60, 0x28, 0xFB, +- 0xE1, 0x60, 0xF7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, +- 0x27, 0xFB, 0x5A, 0xDB, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x01, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x0F, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1B, 0x60, 0xFE, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, 0xE7, 0x60, +- 0x2E, 0x78, 0xFF, 0xFF, 0xE7, 0x60, 0x2E, 0x78, 0xFF, 0xFF, 0xE1, 0x60, 0xE7, 0x78, 0xFF, 0xFF, +- 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xF8, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xA6, 0xF3, +- 0xFF, 0xFF, 0x02, 0xA4, 0x60, 0x43, 0x66, 0x41, 0x63, 0x46, 0x05, 0xF2, 0x00, 0xF0, 0x81, 0xF0, +- 0x02, 0x18, 0x64, 0x46, 0x81, 0xF8, 0x07, 0x1B, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD9, 0x02, 0x00, 0x65, 0x46, 0x00, 0xF8, 0xA6, 0xF3, 0x63, 0x45, 0x60, 0x46, +- 0x00, 0xF2, 0xFF, 0xFF, 0xD4, 0x80, 0x01, 0x18, 0xFA, 0x04, 0x80, 0xF8, 0x65, 0x46, 0x00, 0xFA, +- 0x06, 0xF2, 0xFF, 0xFF, 0x00, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0x4B, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x95, 0xF3, 0xFF, 0xFF, 0x10, 0xB0, +- 0xFF, 0xFF, 0x11, 0x03, 0x04, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE1, 0x60, 0x9B, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x69, 0xF3, 0xFF, 0xFF, 0x01, 0xB0, 0xFF, 0xFF, 0x11, 0x03, +- 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x02, 0x60, +- 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE1, 0x60, 0xB1, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x64, 0x68, 0xFB, 0xE2, 0x60, +- 0x58, 0x4E, 0x13, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x8A, 0xFB, 0x02, 0x64, 0xC1, 0xFE, 0xDB, 0xFB, +- 0xF1, 0xF3, 0xFF, 0xFF, 0x01, 0xBC, 0xF1, 0xFB, 0x02, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, +- 0xFF, 0xFF, 0x03, 0x60, 0xE8, 0x63, 0x0E, 0x60, 0x36, 0xFD, 0x08, 0x60, 0x77, 0xF3, 0xFF, 0xFF, +- 0x13, 0x1B, 0x16, 0x60, 0xCC, 0xF3, 0x00, 0x61, 0x60, 0x40, 0x00, 0x36, 0x00, 0xB9, 0x60, 0x40, +- 0x01, 0x36, 0x01, 0xB9, 0x60, 0x40, 0x02, 0x36, 0x06, 0xB9, 0x60, 0x40, 0x03, 0x36, 0x07, 0xB9, +- 0x41, 0x44, 0xD4, 0x60, 0xF6, 0x78, 0xFF, 0xFF, 0xD3, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0x00, 0x60, +- 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xFF, 0xFF, 0x08, 0x24, 0x46, 0x01, 0xA0, 0x84, 0xA2, 0xDB, +- 0x00, 0x63, 0x68, 0xFD, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x30, 0x00, 0x20, 0x40, +- 0x06, 0x23, 0x10, 0x00, 0x08, 0x60, 0x27, 0xF1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, +- 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x28, 0xFB, 0xE1, 0x60, 0xF7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, 0x10, 0x60, 0x4E, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x44, 0x01, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x01, 0x64, 0x8A, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x50, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x95, 0xF3, +- 0xFF, 0xFF, 0x10, 0xB0, 0xFF, 0xFF, 0x11, 0x03, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x04, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE2, 0x60, +- 0x2A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xB9, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, +- 0x7D, 0xF1, 0x7C, 0xF9, 0x02, 0x64, 0x8A, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x8A, 0xF3, 0x00, 0x65, +- 0xD4, 0x80, 0xFF, 0xFF, 0x0E, 0x03, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x80, 0x60, +- 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE2, 0x60, 0x4A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x51, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x1B, 0x60, 0xB0, 0x64, 0x67, 0xFB, 0x1C, 0x60, 0x72, 0x63, 0x7F, 0xF3, 0xBD, 0xDB, 0x80, 0xF3, +- 0xBD, 0xDB, 0x81, 0xF3, 0xA3, 0xDB, 0x67, 0xF3, 0x00, 0x60, 0x86, 0xF1, 0x04, 0xA4, 0x67, 0xFB, +- 0xD0, 0x80, 0xA0, 0xD3, 0x1F, 0x07, 0x40, 0x47, 0x60, 0x41, 0x0E, 0x65, 0x45, 0xD3, 0x16, 0x60, +- 0xC2, 0xF1, 0xFF, 0xFF, 0x03, 0x1B, 0x10, 0xB0, 0xFF, 0xFF, 0xED, 0x02, 0x27, 0x44, 0x06, 0xA4, +- 0x60, 0x41, 0xA1, 0xD1, 0x7F, 0xF3, 0x80, 0xF1, 0xD0, 0x80, 0x59, 0xD3, 0x08, 0x02, 0xD0, 0x80, +- 0x81, 0xF3, 0x59, 0xD1, 0x04, 0x02, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x02, 0x03, 0x00, 0xE2, 0x60, +- 0xE6, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0x72, 0x63, 0xBD, 0xD3, 0x7F, 0xFB, 0xBD, 0xD3, 0x80, 0xFB, +- 0xA3, 0xD3, 0x81, 0xFB, 0x53, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE2, 0x60, +- 0x9A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7C, 0xF1, 0x7D, 0xF9, 0x13, 0x60, +- 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, +- 0x16, 0xFB, 0xE2, 0x60, 0xC7, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, +- 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x01, 0x63, 0x8A, 0xFD, 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, +- 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, 0x54, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x31, 0x44, 0xF9, 0xB4, 0x40, 0x51, 0xE1, 0x60, 0x22, 0x78, 0xFF, 0xFF, 0x27, 0x43, 0x33, 0x60, +- 0xBE, 0x65, 0xA5, 0xD3, 0x65, 0x41, 0x10, 0xA3, 0x01, 0xA4, 0xFE, 0xB4, 0xC4, 0x85, 0xFE, 0xA1, +- 0xBD, 0xD3, 0x59, 0xD1, 0xFF, 0xFF, 0xD0, 0x80, 0xD5, 0x80, 0x02, 0x02, 0x04, 0x03, 0xF8, 0x01, +- 0xE2, 0x60, 0x73, 0x78, 0xFF, 0xFF, 0x55, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x10, 0x60, 0x2A, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x16, 0xFB, +- 0xE2, 0x60, 0xFE, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x27, 0xD1, 0x7D, 0xF9, +- 0x13, 0x60, 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, +- 0x08, 0x60, 0x16, 0xFB, 0xE3, 0x60, 0x20, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, +- 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x07, 0x60, 0xD0, 0x64, 0x0E, 0x60, 0x4B, 0xFB, +- 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, +- 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD3, 0x7F, 0xFB, 0xBD, 0xD3, 0x80, 0xFB, 0xA3, 0xD3, 0x81, 0xFB, +- 0x31, 0x44, 0xF9, 0xB4, 0x40, 0x51, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, +- 0x04, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE3, 0x60, 0x51, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0xB9, 0xF1, 0x0E, 0x60, 0x4B, 0xF9, 0x08, 0x60, 0x15, 0xF1, 0xFE, 0x60, 0xFF, 0x61, +- 0xA1, 0x84, 0x5A, 0xD1, 0x4A, 0xDB, 0xA1, 0x84, 0x5A, 0xDB, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, +- 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xE2, 0x60, 0x73, 0x78, +- 0xFF, 0xFF, 0x7D, 0xF1, 0x32, 0x60, 0x7A, 0x61, 0xA1, 0xD3, 0x64, 0x40, 0x01, 0x27, 0x59, 0xD3, +- 0x32, 0x60, 0x7E, 0x61, 0xFD, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0xA1, 0xDB, 0x27, 0x42, +- 0x0C, 0xA2, 0xA2, 0xD3, 0x16, 0x60, 0xAD, 0xF3, 0x00, 0xBD, 0x01, 0x63, 0xAC, 0x81, 0x09, 0x03, +- 0x08, 0x03, 0xB8, 0x60, 0x58, 0x4D, 0x15, 0x78, 0xFF, 0xFF, 0x00, 0xB8, 0x01, 0x63, 0x01, 0x03, +- 0x60, 0x43, 0x0E, 0x60, 0x35, 0xFD, 0x5F, 0xF5, 0x00, 0x64, 0x2B, 0xFA, 0x20, 0x64, 0x2A, 0xFA, +- 0x27, 0x43, 0x06, 0xA3, 0xBD, 0xD1, 0x2C, 0xF8, 0x32, 0xF8, 0xBD, 0xD1, 0x2D, 0xF8, 0x33, 0xF8, +- 0xA3, 0xD1, 0x2E, 0xF8, 0x34, 0xF8, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, +- 0x31, 0xF8, 0xB9, 0xF1, 0x19, 0xF8, 0xF8, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0x00, 0xF4, 0x01, 0x63, +- 0x32, 0x40, 0x08, 0x26, 0x10, 0xBB, 0x16, 0x60, 0xC2, 0xF1, 0xFF, 0xFF, 0x64, 0x40, 0xFE, 0x26, +- 0x10, 0xBB, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x0A, 0x00, 0x19, 0x60, 0x45, 0xF3, +- 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x22, 0x20, 0xBB, 0x63, 0x44, 0xFF, 0xFF, 0x04, 0x7F, 0x60, 0x43, +- 0x09, 0xFC, 0x0E, 0x60, 0x35, 0xF3, 0x12, 0x61, 0x59, 0xDA, 0x1C, 0x60, 0x72, 0x63, 0xBD, 0xD1, +- 0x59, 0xD8, 0xBD, 0xD1, 0x59, 0xD8, 0xA3, 0xD1, 0x59, 0xD8, 0x35, 0x60, 0x98, 0x64, 0x40, 0x48, +- 0xD9, 0x81, 0xFF, 0x60, 0xF2, 0x64, 0xF1, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x5F, 0xF5, +- 0x3F, 0xFC, 0xDB, 0x83, 0x1A, 0x60, 0x4C, 0xFD, 0x20, 0x7C, 0x5A, 0xD9, 0x63, 0x41, 0x34, 0x60, +- 0x9C, 0x63, 0x12, 0x65, 0x00, 0xF4, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, +- 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, +- 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x5F, 0xF5, 0x25, 0x60, 0xCE, 0x64, +- 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0x00, 0x66, 0x46, 0x46, 0xC1, 0xFE, 0x16, 0x64, 0x68, 0xFB, 0x56, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x0E, 0x60, 0x38, 0xF3, 0xFF, 0xFF, 0x64, 0xA4, 0xA2, 0xDB, 0x0E, 0x60, 0x38, 0xF1, 0x0E, 0x60, +- 0x4B, 0xF9, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x00, 0x60, 0x1C, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE4, 0x60, 0x23, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, +- 0x9C, 0x84, 0x0E, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x57, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x00, 0x64, +- 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xE2, 0x60, 0x73, 0x78, 0xFF, 0xFF, +- 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x16, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, +- 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x58, 0x64, +- 0x3B, 0x42, 0x5A, 0xDB, 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0xE6, 0x60, 0x36, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x3D, 0x03, +- 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x92, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x68, 0xFB, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x26, 0x46, 0x00, 0xF4, 0x0A, 0xF2, 0x09, 0xF2, 0x04, 0x1B, 0x01, 0xB0, 0x01, 0x7C, 0x2D, 0x02, +- 0x0A, 0xF8, 0x59, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0x0A, 0xF2, 0x26, 0x46, 0x40, 0x59, 0x02, 0x60, +- 0x00, 0x61, 0x2F, 0xF2, 0xA1, 0xDB, 0x30, 0xF2, 0x41, 0x58, 0x59, 0xDB, 0x31, 0xF2, 0x59, 0xDB, +- 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, +- 0x00, 0x66, 0x46, 0x46, 0x05, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0x96, 0x78, 0xFF, 0xFF, 0xE7, 0x60, +- 0x0B, 0x78, 0xFF, 0xFF, 0xE2, 0x60, 0x73, 0x78, 0xFF, 0xFF, 0x5A, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x78, 0x43, 0x02, 0x61, 0x29, 0x60, 0xEA, 0x78, 0xFF, 0xFF, 0x5B, 0x64, 0x3B, 0x42, 0x5A, 0xDB, +- 0x0C, 0xF2, 0xFF, 0xFF, 0x60, 0x41, 0xFF, 0xB1, 0xFF, 0xA1, 0x60, 0x47, 0xFF, 0xB4, 0xC8, 0x02, +- 0xC7, 0x03, 0x34, 0x60, 0xF4, 0x63, 0x30, 0x64, 0xBD, 0xDB, 0x66, 0x45, 0x26, 0x46, 0x3F, 0xF2, +- 0x34, 0x60, 0xF2, 0x61, 0xC2, 0xA0, 0xFF, 0xFF, 0x01, 0x04, 0x3E, 0x64, 0x65, 0x46, 0x02, 0xA4, +- 0xA1, 0xDB, 0xC8, 0x81, 0x12, 0x65, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, +- 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, +- 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x0C, 0xF2, 0xFF, 0xFF, 0x1A, 0x65, +- 0x60, 0x47, 0xFF, 0xB4, 0xC4, 0x85, 0xDC, 0x60, 0x58, 0x4D, 0xC7, 0x78, 0xFF, 0xFF, 0x0B, 0xF2, +- 0xFF, 0xFF, 0x07, 0xB4, 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0x61, 0x44, +- 0x94, 0xFB, 0x27, 0x45, 0x02, 0x62, 0x46, 0xD3, 0x5A, 0xD1, 0x60, 0x47, 0x56, 0xFB, 0x64, 0x47, +- 0x55, 0xFB, 0x00, 0x64, 0x5B, 0xFB, 0x0C, 0x62, 0x46, 0xD3, 0x7E, 0xFB, 0x0B, 0xF0, 0x0F, 0x60, +- 0xFF, 0x64, 0xA0, 0x84, 0x83, 0xFB, 0x1C, 0x60, 0x6A, 0x62, 0xA2, 0xD3, 0x85, 0xFB, 0x26, 0x46, +- 0x32, 0xF0, 0x7F, 0xF9, 0x33, 0xF0, 0x80, 0xF9, 0x34, 0xF0, 0x81, 0xF9, 0x2E, 0x60, 0x2E, 0x64, +- 0x2D, 0x60, 0x8A, 0x63, 0xA0, 0xD1, 0xA3, 0xD9, 0x64, 0x41, 0x58, 0xD1, 0x5B, 0xD9, 0x7D, 0xF3, +- 0x66, 0x45, 0xA6, 0xF5, 0x60, 0x40, 0x01, 0x27, 0x08, 0x00, 0x91, 0xFA, 0x61, 0x44, 0xFD, 0x60, +- 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x07, 0x00, 0x11, 0xF8, 0x64, 0x44, 0xFD, 0x60, +- 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x12, 0xFA, 0x65, 0x46, 0xA6, 0xF3, 0xFF, 0xFF, 0x02, 0xA4, +- 0x40, 0x4B, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xFA, 0xA3, 0x00, 0x60, 0x17, 0x61, 0x00, 0x60, +- 0x01, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, 0x7A, 0x78, 0xFF, 0xFF, +- 0x00, 0xBB, 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x64, 0x40, 0x4A, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, +- 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, 0x58, 0x4E, 0x2C, 0x78, 0xFF, 0xFF, 0x20, 0xFE, +- 0x00, 0x65, 0x00, 0x64, 0x19, 0x60, 0x3B, 0xFB, 0x02, 0x00, 0x20, 0xFE, 0xFF, 0x65, 0x02, 0x60, +- 0x00, 0x63, 0x60, 0xFE, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0x20, 0xFE, 0xCD, 0x81, 0x60, 0x40, +- 0x80, 0x2A, 0x39, 0x00, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, 0x01, 0x64, 0x2E, 0x00, 0x04, 0x3A, +- 0x02, 0x00, 0x02, 0x64, 0x2A, 0x00, 0x0B, 0x3A, 0x02, 0x00, 0x04, 0x64, 0x26, 0x00, 0x16, 0x3A, +- 0x02, 0x00, 0x08, 0x64, 0x22, 0x00, 0x0C, 0x3A, 0x02, 0x00, 0x10, 0x64, 0x1E, 0x00, 0x12, 0x3A, +- 0x02, 0x00, 0x20, 0x64, 0x1A, 0x00, 0x18, 0x3A, 0x02, 0x00, 0x40, 0x64, 0x16, 0x00, 0x24, 0x3A, +- 0x02, 0x00, 0x80, 0x64, 0x12, 0x00, 0x30, 0x3A, 0x02, 0x00, 0x01, 0x67, 0x0E, 0x00, 0x48, 0x3A, +- 0x02, 0x00, 0x02, 0x67, 0x0A, 0x00, 0x60, 0x3A, 0x02, 0x00, 0x04, 0x67, 0x06, 0x00, 0x6C, 0x3A, +- 0x02, 0x00, 0x08, 0x67, 0x02, 0x00, 0x00, 0x64, 0x00, 0x00, 0x19, 0x60, 0x3B, 0xF1, 0xFF, 0xFF, +- 0xB0, 0x84, 0x19, 0x60, 0x3B, 0xFB, 0x61, 0x40, 0x00, 0x36, 0x05, 0x00, 0x60, 0xFE, 0xBD, 0xD3, +- 0xFF, 0xFF, 0x20, 0xFE, 0xBB, 0x01, 0x65, 0x40, 0x00, 0x3A, 0x1E, 0x00, 0x26, 0x46, 0x3F, 0xF2, +- 0x00, 0xF4, 0x60, 0x43, 0xFA, 0xA3, 0x00, 0x60, 0x17, 0x61, 0x00, 0x60, 0x32, 0x65, 0x01, 0x60, +- 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, 0x58, 0x4E, 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, +- 0x0B, 0x03, 0x60, 0xFE, 0x02, 0x60, 0x00, 0x63, 0xBD, 0xD3, 0xBD, 0xD3, 0x60, 0x41, 0xFE, 0x60, +- 0x58, 0x4E, 0x2C, 0x78, 0xFF, 0xFF, 0x91, 0x01, 0x20, 0xFE, 0x00, 0x65, 0xFC, 0x60, 0x58, 0x4E, +- 0xC7, 0x78, 0xFF, 0xFF, 0xA1, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x27, 0x04, 0x00, 0xFD, 0x60, +- 0x58, 0x4E, 0x11, 0x78, 0xFF, 0xFF, 0x20, 0xFE, 0x37, 0x60, 0xF8, 0x61, 0xA1, 0xD1, 0xA1, 0xF3, +- 0x01, 0x60, 0xAC, 0x63, 0x60, 0x45, 0x2A, 0x44, 0x79, 0xFB, 0xA3, 0xD5, 0x65, 0x40, 0x01, 0x27, +- 0x5B, 0xD5, 0x65, 0x40, 0x01, 0x27, 0x59, 0xD1, 0x66, 0x41, 0xA0, 0x84, 0x24, 0x94, 0x2B, 0x46, +- 0x0F, 0xFA, 0x7A, 0xFB, 0x16, 0x64, 0x12, 0xFA, 0x01, 0x64, 0x11, 0xFA, 0x66, 0x5C, 0xC2, 0x60, +- 0x58, 0x4E, 0x6D, 0x78, 0xFF, 0xFF, 0xA6, 0xF3, 0xFF, 0xFF, 0x02, 0xA4, 0x40, 0x4B, 0x60, 0x46, +- 0x00, 0x64, 0x17, 0xFA, 0x00, 0x64, 0x16, 0xFA, 0x13, 0xFA, 0x00, 0x65, 0x26, 0x46, 0xFD, 0x60, +- 0x58, 0x4E, 0xDD, 0x78, 0xFF, 0xFF, 0xA6, 0xF3, 0x1D, 0x60, 0xC0, 0x65, 0x02, 0xA4, 0x60, 0x46, +- 0x05, 0xF0, 0x60, 0x41, 0x64, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x00, 0x7C, 0x44, 0xD9, 0x26, 0x46, +- 0x31, 0xF2, 0x61, 0x5C, 0x60, 0x47, 0x00, 0x7F, 0xE0, 0x84, 0x44, 0xD9, 0x26, 0x46, 0x2F, 0xF0, +- 0x61, 0x46, 0x03, 0xF8, 0x26, 0x46, 0x30, 0xF0, 0x61, 0x46, 0x04, 0xF8, 0x26, 0x46, 0x31, 0xF0, +- 0x61, 0x46, 0x05, 0xF8, 0x26, 0x46, 0xD9, 0x60, 0x58, 0x4E, 0xAE, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, +- 0x46, 0x46, 0x03, 0x65, 0xF1, 0x60, 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, 0x01, 0x63, 0x8A, 0xFD, +- 0x08, 0x60, 0x0C, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xC1, 0xFE, +- 0x5C, 0x64, 0x3B, 0x42, 0x5A, 0xDB, 0xE1, 0x60, 0x22, 0x78, 0xFF, 0xFF, 0xFF, 0x60, 0xF7, 0x65, +- 0x20, 0x44, 0x24, 0x80, 0xDA, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0xDB, 0xF3, 0xFF, 0xFF, 0xFD, 0xA0, +- 0x2A, 0xF2, 0x03, 0x03, 0xE6, 0x60, 0xDE, 0x78, 0xFF, 0xFF, 0x60, 0x40, 0xB0, 0x36, 0x11, 0x00, +- 0xC0, 0x36, 0x02, 0x00, 0x2F, 0x58, 0xFF, 0xFF, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, +- 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xDA, 0x60, 0x74, 0x78, +- 0xFF, 0xFF, 0x66, 0x45, 0x00, 0xF4, 0x0A, 0xF2, 0x0B, 0xF2, 0xFE, 0xA0, 0xF3, 0xA0, 0x67, 0x02, +- 0x60, 0x41, 0x09, 0xF2, 0x1D, 0x03, 0x00, 0xA0, 0xFF, 0xA0, 0x4B, 0x03, 0x5D, 0x03, 0x00, 0xA0, +- 0xFF, 0xFF, 0x47, 0x03, 0x01, 0x64, 0x10, 0x60, 0x0B, 0xFB, 0x0D, 0x64, 0x10, 0x60, 0x0C, 0xFB, +- 0x03, 0x64, 0x10, 0x60, 0x0D, 0xFB, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, +- 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xDA, 0x60, 0x74, 0x78, 0xFF, 0xFF, +- 0x16, 0x60, 0xC3, 0xF3, 0xFF, 0xFF, 0xFE, 0xA0, 0x20, 0x60, 0x16, 0x61, 0x15, 0x02, 0x01, 0x64, +- 0xA1, 0xDB, 0x00, 0x64, 0x10, 0x60, 0x0C, 0xFB, 0x01, 0x64, 0x10, 0x60, 0x0D, 0xFB, 0x26, 0x46, +- 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, +- 0x46, 0x46, 0xDA, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0xA1, 0xDB, 0x00, 0x64, 0x10, 0x60, +- 0x0C, 0xFB, 0x01, 0x64, 0x10, 0x60, 0x0D, 0xFB, 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, +- 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0x00, 0x66, 0x46, 0x46, 0xDA, 0x60, 0x74, 0x78, +- 0xFF, 0xFF, 0x65, 0x46, 0x07, 0xF4, 0x06, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x65, 0x46, +- 0x26, 0x46, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, +- 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0xDC, 0x60, 0x09, 0x78, 0xFF, 0xFF, 0x0A, 0xF2, +- 0x09, 0xF2, 0xFC, 0xA0, 0xFF, 0xA0, 0x11, 0x02, 0x0A, 0x02, 0x0B, 0xF2, 0x65, 0x46, 0x0A, 0x1B, +- 0x66, 0x41, 0x07, 0xF4, 0x06, 0xF2, 0xFF, 0xFF, 0x01, 0x7E, 0x06, 0xFA, 0x61, 0x46, 0xDA, 0x60, +- 0x74, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x65, 0x46, 0x68, 0xF1, 0x2A, 0xF2, +- 0x64, 0x41, 0x60, 0x40, 0xA0, 0x3A, 0x02, 0x00, 0x08, 0xB1, 0x04, 0x00, 0xC0, 0x3A, 0x0B, 0x00, +- 0x04, 0xB1, 0xFF, 0xFF, 0x1E, 0x03, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x16, 0x00, 0xB0, 0x3A, 0x02, 0x00, 0x01, 0x65, 0x07, 0x00, 0x10, 0x3A, +- 0x02, 0x00, 0x02, 0x65, 0x03, 0x00, 0x30, 0x3A, 0x0C, 0x00, 0x10, 0x65, 0xA5, 0x80, 0xFF, 0xFF, +- 0x08, 0x03, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x00, 0x66, 0x2F, 0x58, 0xFF, 0xFF, 0x16, 0x60, 0xC3, 0xF3, 0xFF, 0xFF, 0xFC, 0xA0, 0xFF, 0xFF, +- 0x14, 0x04, 0x00, 0x60, 0x02, 0x64, 0x08, 0x60, 0x16, 0xFB, 0xE7, 0x60, 0x1B, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x19, 0x60, 0xA5, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, +- 0xFF, 0xFF, 0x03, 0x03, 0xDA, 0x60, 0x74, 0x78, 0xFF, 0xFF, 0x20, 0x40, 0x08, 0x2A, 0x03, 0x00, +- 0xD9, 0x60, 0xCA, 0x78, 0xFF, 0xFF, 0xE2, 0x60, 0x73, 0x78, 0xFF, 0xFF, 0x4E, 0x64, 0x3B, 0x42, +- 0x5A, 0xDB, 0x2E, 0xF5, 0xFF, 0xFF, 0x27, 0xF2, 0x1D, 0x60, 0xC0, 0x65, 0x60, 0x47, 0x00, 0x7F, +- 0xE0, 0x84, 0x44, 0xD3, 0x66, 0x41, 0x60, 0x46, 0x60, 0x43, 0x05, 0xF2, 0x16, 0x18, 0x61, 0x46, +- 0x27, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0x04, 0xF2, 0x0C, 0x02, 0x61, 0x46, 0x26, 0xF0, 0x63, 0x46, +- 0xD0, 0x80, 0x03, 0xF2, 0x06, 0x02, 0x61, 0x46, 0x25, 0xF0, 0x63, 0x46, 0xD0, 0x80, 0xFF, 0xFF, +- 0x07, 0x03, 0x80, 0xF4, 0xFF, 0xFF, 0x63, 0x46, 0xE8, 0x1B, 0xA6, 0xF3, 0x08, 0xFE, 0x60, 0x43, +- 0x61, 0x46, 0x25, 0xF2, 0x26, 0xF0, 0xA7, 0xF2, 0xA8, 0xF0, 0x65, 0xF5, 0xFF, 0xFF, 0x00, 0xF4, +- 0xFF, 0xFF, 0x89, 0xF8, 0x65, 0xF5, 0xFF, 0xFF, 0x07, 0xFC, 0x2C, 0xFA, 0x2D, 0xF8, 0xAE, 0xFA, +- 0xEA, 0xF3, 0x2F, 0xFA, 0xEB, 0xF3, 0x30, 0xFA, 0xEC, 0xF3, 0x31, 0xFA, 0x7F, 0xF3, 0x32, 0xFA, +- 0x80, 0xF3, 0x33, 0xFA, 0x81, 0xF3, 0x34, 0xFA, 0x1B, 0x60, 0xFE, 0xF3, 0xFF, 0xFF, 0x03, 0x1B, +- 0x00, 0x60, 0xA0, 0x64, 0x02, 0x00, 0x00, 0x60, 0xC0, 0x64, 0x2A, 0xFA, 0x02, 0x63, 0x3F, 0xFC, +- 0xAB, 0xFC, 0x00, 0x64, 0x3E, 0xFA, 0xC9, 0xF1, 0x19, 0xF8, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, +- 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x66, +- 0x46, 0x46, 0xC1, 0xFE, 0x10, 0x60, 0x2A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xE1, 0x60, 0x34, 0x78, +- 0xFF, 0xFF, 0x00, 0x60, 0x3A, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0x61, 0xFB, 0xA6, 0xF3, 0x07, 0xFA, 0x0C, 0x60, 0x80, 0x64, 0xB9, 0xF1, 0x19, 0xF8, 0x0E, 0xFA, +- 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x00, 0x60, 0x3A, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, +- 0xFF, 0xFF, 0x66, 0x44, 0x60, 0xFB, 0xA6, 0xF3, 0x07, 0xFA, 0x0C, 0x60, 0x80, 0x64, 0x0E, 0xFA, +- 0xB9, 0xF1, 0x19, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0xE8, 0x60, 0xEA, 0x64, 0x08, 0x60, +- 0x33, 0xFB, 0x00, 0x60, 0x80, 0x64, 0x08, 0x60, 0x10, 0xFB, 0xE7, 0x60, 0xCB, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x16, 0x60, 0x87, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, 0x03, 0xA8, +- 0x04, 0x03, 0x03, 0x03, 0xE8, 0x60, 0xDC, 0x78, 0xFF, 0xFF, 0x04, 0x60, 0x00, 0x65, 0x20, 0x44, +- 0x34, 0x80, 0x10, 0x60, 0x1E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x9B, 0xFE, 0x03, 0x05, 0x20, 0x40, +- 0x4B, 0x23, 0x0A, 0x00, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, 0x10, 0xFB, 0xE7, 0x60, 0xD9, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x13, 0xF3, 0xFF, 0xFF, 0x60, 0x40, +- 0x01, 0x2A, 0x07, 0x00, 0x90, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x00, 0x64, 0xA2, 0xDB, +- 0x04, 0x00, 0x10, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x8A, 0xF3, 0x58, 0xFB, 0x82, 0xF1, +- 0xBA, 0xFE, 0x01, 0xA8, 0x59, 0xF9, 0x04, 0x02, 0x02, 0x64, 0x8A, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, +- 0x64, 0x47, 0xDB, 0xF3, 0x10, 0xB0, 0x04, 0xA8, 0x2B, 0x02, 0x2A, 0x02, 0x61, 0xF5, 0xEA, 0xF1, +- 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0x7F, 0xF1, 0x2C, 0xF8, 0x32, 0xF8, +- 0x80, 0xF1, 0x2D, 0xF8, 0x33, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, 0x10, 0x60, 0x48, 0x64, +- 0x2A, 0xFA, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x60, 0x01, 0x64, 0x08, 0x60, 0x10, 0xFB, +- 0xE8, 0x60, 0x36, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x67, 0x82, 0xFB, +- 0x8A, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0xFF, 0xFF, 0x0A, 0x03, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, +- 0x10, 0xFB, 0xE8, 0x60, 0x38, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, +- 0x1E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x05, 0x7C, 0x53, 0xF9, 0x2F, 0x60, 0x24, 0x64, 0x54, 0xFB, +- 0x19, 0x60, 0x40, 0xF3, 0xFF, 0xFF, 0x15, 0x18, 0x10, 0x60, 0x1E, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, +- 0x00, 0x64, 0x08, 0x60, 0x10, 0xFB, 0xE8, 0x60, 0x69, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x19, 0x60, 0x41, 0xF3, 0xFF, 0x60, 0x80, 0x65, 0xA4, 0x80, 0x5A, 0xD3, 0x05, 0x02, +- 0x04, 0x1B, 0x5A, 0xD3, 0xFF, 0xFF, 0x01, 0x1B, 0x15, 0x00, 0x10, 0x60, 0x1E, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x10, 0x60, 0x00, 0x64, 0x08, 0x60, 0x10, 0xFB, 0xE8, 0x60, 0x8A, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0xFF, 0xFF, 0x59, 0xF3, 0x82, 0xFB, 0x60, 0x40, 0x10, 0x27, 0xDA, 0xFE, +- 0xDB, 0xF3, 0x00, 0xA8, 0x04, 0xA8, 0x23, 0x02, 0x22, 0x02, 0x60, 0xF5, 0xEA, 0xF1, 0x2F, 0xF8, +- 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0x7F, 0xF1, 0x2C, 0xF8, 0x80, 0xF1, 0x2D, 0xF8, +- 0x81, 0xF1, 0x2E, 0xF8, 0xA4, 0x64, 0x2A, 0xFA, 0x83, 0xF1, 0xC0, 0x67, 0xB0, 0x84, 0x2B, 0xFA, +- 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x20, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x00, 0x60, +- 0x04, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, 0xFF, 0xFF, 0x01, 0x64, 0x23, 0xFA, 0xF1, 0x60, +- 0x02, 0x64, 0x24, 0xFA, 0x26, 0x60, 0x0A, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0xEB, 0x60, 0xFF, 0x65, 0x20, 0x44, +- 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x58, 0xF3, 0x8A, 0xFB, 0xFF, 0xFF, 0xC1, 0xFE, 0x10, 0x60, 0x1E, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x00, 0x60, 0x80, 0x64, 0x08, 0x60, 0x10, 0xFB, 0xE7, 0x60, 0xCB, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x9C, 0xF1, 0x00, 0x64, 0xB0, 0x86, 0x9C, 0xFB, 0x07, 0x03, 0x26, 0x60, +- 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, 0xFF, 0xFF, 0xEB, 0x60, 0xFF, 0x65, +- 0x20, 0x44, 0x24, 0x80, 0x10, 0x60, 0x1E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x80, 0x64, +- 0x08, 0x60, 0x10, 0xFB, 0xE7, 0x60, 0xCB, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x95, 0xF3, 0x26, 0x46, 0x60, 0x43, 0x01, 0x2A, 0x20, 0x00, 0x0F, 0xF2, 0x2A, 0xF0, 0x60, 0x40, +- 0x10, 0x2A, 0x0F, 0x00, 0x64, 0x40, 0x04, 0x27, 0x18, 0x00, 0xFD, 0xB3, 0x64, 0x40, 0x20, 0x27, +- 0x02, 0xBB, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x0B, 0x00, 0xFB, 0xB3, 0x64, 0x40, 0x20, 0x27, 0x04, 0xBB, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, +- 0x10, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x95, 0xFD, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, +- 0xDB, 0xF3, 0x3F, 0xF2, 0x04, 0xA8, 0x57, 0xFB, 0x02, 0x03, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0xF4, +- 0x1E, 0x63, 0x08, 0x64, 0x40, 0x48, 0xBD, 0xD2, 0xFF, 0xFF, 0x60, 0x47, 0x05, 0x36, 0x0B, 0x00, +- 0xFF, 0xB5, 0xC7, 0x83, 0x01, 0x2A, 0xF7, 0x01, 0x4F, 0xD2, 0x5B, 0xD2, 0x60, 0x40, 0x05, 0x37, +- 0x0B, 0x00, 0xDF, 0x83, 0xF5, 0x01, 0xFF, 0xB5, 0x65, 0x41, 0xA3, 0xD2, 0x47, 0x8A, 0x60, 0x47, +- 0x40, 0x4C, 0x5B, 0xD2, 0xDF, 0x83, 0x08, 0x00, 0x40, 0x4C, 0x00, 0x7F, 0xDC, 0x85, 0x47, 0x8A, +- 0x60, 0x41, 0x5B, 0xD2, 0xDB, 0x83, 0x60, 0x47, 0x01, 0xB0, 0xFE, 0xB5, 0x02, 0x03, 0x02, 0x64, +- 0x40, 0x48, 0x2C, 0x47, 0xFF, 0xB4, 0x73, 0xF1, 0x08, 0x28, 0x73, 0xFB, 0x83, 0xF1, 0x65, 0x44, +- 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0xFD, 0xA1, 0xE1, 0x81, 0xE1, 0x81, 0xE1, 0x85, 0xC4, 0x81, +- 0xD0, 0x84, 0xD1, 0x80, 0x28, 0x07, 0x27, 0x06, 0x9C, 0x84, 0xDC, 0x84, 0xE8, 0x84, 0xE8, 0x84, +- 0xE8, 0x85, 0x94, 0xF3, 0xC7, 0x83, 0x01, 0x26, 0x60, 0x47, 0xAB, 0x83, 0xFC, 0xA3, 0x02, 0x00, +- 0x03, 0x04, 0x00, 0xF4, 0x84, 0xA3, 0xFC, 0x01, 0x80, 0x65, 0x47, 0xD0, 0x28, 0x41, 0xA0, 0x80, +- 0xFE, 0xA1, 0x14, 0x03, 0x08, 0x02, 0x08, 0x60, 0x2D, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x1B, 0x00, 0x08, 0x60, 0x2D, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x13, 0x00, 0x28, 0x41, 0xFE, 0xA1, 0xFF, 0xFF, 0x08, 0x03, 0x08, 0x60, +- 0x2D, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x07, 0x00, 0x08, 0x60, +- 0x2D, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x08, 0x60, 0x1B, 0xF1, +- 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x02, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x63, 0x95, 0xFD, 0x1C, 0x60, 0x9E, 0x63, 0x00, 0x64, 0xA3, 0xDB, +- 0x06, 0xA3, 0x10, 0x60, 0x98, 0x64, 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, 0xA3, 0xDB, 0xE9, 0x60, +- 0xB8, 0x64, 0x08, 0x60, 0x4B, 0xFB, 0xCE, 0xF1, 0x0E, 0x60, 0x51, 0xF9, 0x1C, 0x60, 0xAA, 0x63, +- 0x00, 0x64, 0xA3, 0xDB, 0x06, 0xA3, 0x10, 0x60, 0x9C, 0x64, 0xBD, 0xDB, 0xBD, 0xDB, 0x06, 0x64, +- 0xA3, 0xDB, 0xE9, 0x60, 0xC1, 0x64, 0x08, 0x60, 0x4D, 0xFB, 0x16, 0x60, 0xAE, 0xF1, 0x0E, 0x60, +- 0x57, 0xF9, 0x00, 0x60, 0x3A, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0x63, 0xFB, 0xA6, 0xF3, 0x07, 0xFA, 0xB9, 0xF3, 0x19, 0xFA, 0xF8, 0x60, 0x80, 0x64, 0x0E, 0xFA, +- 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x00, 0x60, 0x3A, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, +- 0xFF, 0xFF, 0x66, 0x44, 0x64, 0xFB, 0xA6, 0xF3, 0x07, 0xFA, 0xB9, 0xF3, 0x19, 0xFA, 0x24, 0x60, +- 0x80, 0x64, 0x0E, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0x3F, 0xFA, 0x00, 0x64, 0x08, 0x60, 0x2D, 0xFB, +- 0x5A, 0xDB, 0xEA, 0x60, 0x1F, 0x64, 0x08, 0x60, 0x37, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x63, +- 0x95, 0xFD, 0xBA, 0xFE, 0xFE, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x82, 0xFD, 0x08, 0x60, +- 0x15, 0xF1, 0x04, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x64, 0x08, 0x60, +- 0x1B, 0xFB, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x16, 0x60, 0xAB, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, +- 0xFF, 0xFF, 0x05, 0x03, 0x19, 0x60, 0xF0, 0xF1, 0x0E, 0x60, 0x57, 0xF9, 0x04, 0x00, 0x16, 0x60, +- 0xAE, 0xF1, 0x0E, 0x60, 0x57, 0xF9, 0x16, 0x60, 0xAB, 0xF3, 0xFF, 0xFF, 0x09, 0x1B, 0x00, 0x64, +- 0x82, 0xFB, 0xBA, 0xFE, 0x00, 0x64, 0x08, 0x60, 0x1B, 0xFB, 0x5A, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, +- 0xBA, 0xFE, 0x95, 0xF3, 0x00, 0x63, 0x82, 0xFD, 0x10, 0xBC, 0x95, 0xFB, 0xFE, 0x60, 0xFF, 0x65, +- 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0x00, 0x60, 0x64, 0x63, 0x0E, 0x60, 0x37, 0xFD, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x01, 0x60, 0x04, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEA, 0x60, 0x73, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, +- 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xA2, 0x01, 0x31, 0x40, 0x04, 0x2A, 0xE5, 0x01, +- 0x20, 0x40, 0x12, 0x23, 0x11, 0x00, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, +- 0x5A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x81, 0x60, 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEA, 0x60, +- 0x73, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0xDD, 0x01, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x01, 0x60, 0x00, 0x65, 0x20, 0x44, 0x34, 0x80, 0x64, 0xF5, 0xB9, 0xF1, 0x19, 0xF8, 0x7F, 0xF1, +- 0x2C, 0xF8, 0x32, 0xF8, 0x80, 0xF1, 0x2D, 0xF8, 0x33, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, +- 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0x11, 0x60, 0x48, 0x64, +- 0x2A, 0xFA, 0x00, 0x64, 0x2B, 0xFA, 0x23, 0xFA, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, +- 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x60, +- 0x01, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEA, 0x60, 0xC9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x64, 0xF5, 0x23, 0xF2, 0xFF, 0xFF, 0x01, 0x18, 0x82, 0x01, 0x10, 0x67, 0x82, 0xFB, +- 0x03, 0x64, 0x96, 0xFB, 0xFE, 0x60, 0xFF, 0x65, 0x20, 0x44, 0x24, 0x80, 0x08, 0x60, 0x08, 0xF1, +- 0x80, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0x81, 0x60, 0x00, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEA, 0x60, 0xEA, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x0C, 0x00, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xEA, 0x60, 0x1F, 0x78, 0xFF, 0xFF, 0x06, 0x60, 0x00, 0x65, +- 0x20, 0x41, 0x8C, 0xF3, 0xA5, 0x80, 0x01, 0xB0, 0x01, 0x02, 0x06, 0x00, 0x10, 0x60, 0x36, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x6E, 0x65, 0xA5, 0xD3, 0x01, 0x63, +- 0x8A, 0xFD, 0x26, 0x1B, 0x00, 0x60, 0x64, 0x64, 0xA5, 0xDB, 0x64, 0xF5, 0xB9, 0xF1, 0x19, 0xF8, +- 0x7F, 0xF1, 0x2C, 0xF8, 0x32, 0xF8, 0x80, 0xF1, 0x2D, 0xF8, 0x33, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, +- 0x34, 0xF8, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0x11, 0x60, +- 0x48, 0x64, 0x2A, 0xFA, 0x00, 0x64, 0x2B, 0xFA, 0x23, 0xFA, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, +- 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x06, 0x00, +- 0x95, 0xF3, 0x32, 0x40, 0x02, 0x26, 0x02, 0x00, 0x40, 0x2A, 0xDA, 0xFE, 0xC1, 0xFE, 0x10, 0x60, +- 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, 0x82, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEB, 0x60, +- 0x45, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, +- 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xEA, 0x60, 0x1F, 0x78, +- 0xFF, 0xFF, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x06, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0xBA, 0xFE, 0xED, 0x60, 0x6D, 0x78, 0xFF, 0xFF, 0x02, 0x64, 0x8A, 0xFB, 0x01, 0x60, 0x00, 0x65, +- 0x20, 0x44, 0x34, 0x80, 0xBA, 0xFE, 0xC1, 0xFE, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x10, 0x60, 0x5A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, 0x46, 0x64, 0x08, 0x60, 0x1C, 0xFB, +- 0xEB, 0x60, 0x76, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, +- 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xEA, 0x60, +- 0x1F, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x45, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x08, 0x60, 0x2D, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0F, 0x03, +- 0xA0, 0x84, 0xA2, 0xDB, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xED, 0x60, 0x6D, 0x78, 0xFF, 0xFF, 0x31, 0x01, 0x00, 0x60, +- 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0B, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x16, 0x60, 0xAC, 0xF1, +- 0x95, 0xF3, 0x00, 0x61, 0xD1, 0x80, 0xF7, 0xB4, 0xF1, 0x03, 0x95, 0xFB, 0x33, 0x00, 0x00, 0x60, +- 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0E, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x16, 0x60, 0xAC, 0xF1, +- 0x95, 0xF3, 0x00, 0x61, 0xD1, 0x80, 0x08, 0xBC, 0x03, 0x02, 0xEC, 0x60, 0x9C, 0x78, 0xFF, 0xFF, +- 0x95, 0xFB, 0x20, 0x00, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0xEC, 0x60, 0x9C, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x40, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xC8, 0x01, 0x00, 0x60, 0x02, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x05, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xED, 0x60, 0x6D, 0x78, 0xFF, 0xFF, +- 0x2F, 0x58, 0xFF, 0xFF, 0x02, 0x63, 0x95, 0xF3, 0x8A, 0xFD, 0x01, 0xBC, 0xC1, 0xFE, 0x95, 0xFB, +- 0xCE, 0xF1, 0x0E, 0x60, 0x51, 0xF9, 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, +- 0x5A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, 0x34, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEC, 0x60, +- 0x05, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, 0x9E, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, +- 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0D, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x9E, 0x64, +- 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xEA, 0x60, 0x1F, 0x78, +- 0xFF, 0xFF, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x22, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0x95, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x04, 0x2A, 0x01, 0x00, 0xD5, 0x01, 0x1C, 0x60, 0x9E, 0x64, +- 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x95, 0xF3, 0xFF, 0xFF, +- 0x60, 0x40, 0x08, 0x2A, 0x01, 0x00, 0x68, 0x00, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x02, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x59, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xED, 0x60, 0x6D, 0x78, 0xFF, 0xFF, +- 0x08, 0x60, 0x2D, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x08, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x95, 0xF3, 0xFF, 0xFF, 0x08, 0xBC, 0x95, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, +- 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xA4, 0x01, 0x00, 0x60, +- 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0B, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x9E, 0x64, +- 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x35, 0x00, 0x00, 0x60, +- 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0B, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x9E, 0x64, +- 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x1E, 0x00, 0x08, 0x60, +- 0x1B, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x14, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0x95, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x08, 0x2A, 0x01, 0x00, 0x16, 0x00, 0x08, 0x60, 0x1B, 0xF1, +- 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x08, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xED, 0x60, +- 0x6D, 0x78, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x00, 0x95, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, +- 0x95, 0xFB, 0xEA, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0xAB, 0xF3, 0xFF, 0xFF, 0x01, 0xA8, +- 0xFF, 0xFF, 0x03, 0x02, 0xED, 0x60, 0x76, 0x78, 0xFF, 0xFF, 0x95, 0xF3, 0x01, 0x63, 0x8A, 0xFD, +- 0x21, 0xBC, 0x95, 0xFB, 0x63, 0xF5, 0x7F, 0xF1, 0x2C, 0xF8, 0x80, 0xF1, 0x2D, 0xF8, 0x81, 0xF1, +- 0x2E, 0xF8, 0x83, 0xF1, 0xC0, 0x67, 0xB0, 0x84, 0x2B, 0xFA, 0xB9, 0xF1, 0x19, 0xF8, 0xEA, 0xF1, +- 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0x10, 0x60, 0xA4, 0x64, 0x2A, 0xFA, +- 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x60, 0x50, 0x64, 0x0E, 0x60, 0x51, 0xFB, 0x1C, 0x60, +- 0x9E, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x10, 0x60, +- 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x5A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x01, 0x60, +- 0x2C, 0x64, 0x08, 0x60, 0x1C, 0xFB, 0xEC, 0x60, 0xE9, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0D, 0x03, +- 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x9E, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, +- 0xFF, 0xFF, 0x04, 0xFF, 0xEA, 0x60, 0x1F, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x2D, 0xF1, 0x00, 0x60, +- 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x95, 0x01, 0x08, 0x60, +- 0x1B, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x08, 0x03, 0xA0, 0x84, 0xA2, 0xDB, +- 0x95, 0xF3, 0xFF, 0xFF, 0x02, 0xB0, 0xFF, 0xFF, 0x49, 0x03, 0x86, 0x01, 0x00, 0x60, 0x08, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x40, 0x00, 0x00, 0x60, 0x02, 0x64, +- 0xA0, 0x80, 0x9C, 0x84, 0x14, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x9E, 0x64, 0x13, 0x60, +- 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x16, 0x60, 0xAC, 0xF3, 0x95, 0xF3, +- 0x00, 0xA8, 0xF7, 0xB4, 0x2B, 0x03, 0x95, 0xFB, 0xEB, 0x60, 0xE2, 0x78, 0xFF, 0xFF, 0x00, 0x60, +- 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x15, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x1C, 0x60, 0x9E, 0x64, +- 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x16, 0x60, 0xAC, 0xF3, +- 0x95, 0xF3, 0x00, 0xA8, 0x08, 0xBC, 0x01, 0x02, 0x4F, 0x01, 0x95, 0xFB, 0xEB, 0x60, 0xE2, 0x78, +- 0xFF, 0xFF, 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, +- 0xA0, 0x84, 0xA2, 0xDB, 0x02, 0x00, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x00, 0x1C, 0x60, 0x9E, 0x64, +- 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x95, 0xF3, 0xFF, 0xFF, +- 0xFE, 0xB4, 0x95, 0xFB, 0xEA, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0x95, 0xF3, 0x01, 0x63, 0x8A, 0xFD, +- 0x01, 0xBC, 0x95, 0xFB, 0x00, 0x64, 0x82, 0xFB, 0xC1, 0xFE, 0x28, 0x00, 0x95, 0xF3, 0x01, 0x63, +- 0x8A, 0xFD, 0x01, 0xBC, 0x95, 0xFB, 0x00, 0x64, 0x82, 0xFB, 0x63, 0xF5, 0x7F, 0xF1, 0x2C, 0xF8, +- 0x80, 0xF1, 0x2D, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, 0x83, 0xF1, 0xC0, 0x67, 0xB0, 0x84, 0x2B, 0xFA, +- 0xB9, 0xF1, 0x19, 0xF8, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, +- 0x00, 0x60, 0xA4, 0x64, 0x2A, 0xFA, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x1C, 0x60, 0xAA, 0x64, +- 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x10, 0x60, 0x36, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x5A, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x03, 0x60, 0x0E, 0x64, +- 0x08, 0x60, 0x1C, 0xFB, 0xED, 0x60, 0xB8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x1B, 0xF1, 0x01, 0x60, 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0D, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x1C, 0x60, 0xAA, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0xEA, 0x60, 0x1F, 0x78, 0xFF, 0xFF, 0x00, 0x60, 0x0A, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xCA, 0x01, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, +- 0x14, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x08, 0x60, 0x2D, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, +- 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x91, 0x01, 0x00, 0x60, 0x12, 0x64, 0xA0, 0x80, +- 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0xB1, 0x01, 0x08, 0x60, 0x1B, 0xF1, 0x02, 0x60, +- 0x00, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0xB2, 0x03, 0xA0, 0x84, 0xA2, 0xDB, 0x10, 0x67, 0x82, 0xFB, +- 0x10, 0x60, 0x36, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x10, 0x60, 0x5A, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x64, 0xF5, 0xB9, 0xF1, 0x19, 0xF8, 0x7F, 0xF1, 0x2C, 0xF8, 0x32, 0xF8, 0x80, 0xF1, 0x2D, 0xF8, +- 0x33, 0xF8, 0x81, 0xF1, 0x2E, 0xF8, 0x34, 0xF8, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, +- 0xEC, 0xF1, 0x31, 0xF8, 0x11, 0x60, 0x48, 0x64, 0x2A, 0xFA, 0x00, 0x64, 0x2B, 0xFA, 0x23, 0xFA, +- 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0x95, 0xF3, 0xC1, 0xFE, 0xFE, 0xB4, 0x95, 0xFB, 0x00, 0x60, 0x03, 0x64, +- 0x08, 0x60, 0x1C, 0xFB, 0xEE, 0x60, 0x30, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x1B, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x33, 0x01, 0x64, 0xF5, 0x23, 0xF2, 0x96, 0xF3, 0x04, 0x18, 0xCC, 0x84, 0x96, 0xFB, +- 0x01, 0x03, 0x2B, 0x01, 0xEA, 0x60, 0xD0, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0xAB, 0xF3, 0x82, 0xF1, +- 0x02, 0xA8, 0x2A, 0xF2, 0x03, 0x02, 0xB0, 0x84, 0x2A, 0xFA, 0x07, 0x00, 0x08, 0x60, 0x1B, 0xF1, +- 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x25, 0x60, 0xC8, 0x64, 0x13, 0x60, +- 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, +- 0x12, 0x60, 0xED, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0xDF, 0x02, 0xCA, 0x60, 0xD4, 0x78, +- 0xFF, 0xFF, 0x10, 0x60, 0x48, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x00, 0x60, 0x06, 0x64, 0x08, 0x60, +- 0x25, 0xFB, 0xEE, 0x60, 0x77, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, +- 0x18, 0x64, 0x08, 0x60, 0x25, 0xFB, 0xEE, 0x60, 0x77, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x26, 0x46, 0x00, 0xF4, 0xDB, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0x03, 0x36, 0x1B, 0x00, +- 0x0E, 0xF0, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0xEF, 0xB4, 0x60, 0x44, 0x64, 0x40, 0x04, 0x27, +- 0x07, 0x00, 0xA2, 0xDB, 0x13, 0x64, 0xCB, 0xFB, 0x01, 0x60, 0x67, 0x64, 0x37, 0xFB, 0x0B, 0x00, +- 0x10, 0xBC, 0xA2, 0xDB, 0x08, 0x64, 0xCB, 0xFB, 0xA1, 0xF3, 0x01, 0x60, 0x67, 0x7C, 0x60, 0x40, +- 0x01, 0x27, 0x5B, 0x7C, 0x37, 0xF9, 0x26, 0x46, 0x3F, 0xF2, 0x00, 0xF4, 0x60, 0x43, 0xF4, 0xA3, +- 0x00, 0x60, 0x1D, 0x61, 0x00, 0x60, 0x2A, 0x65, 0x01, 0x60, 0xFF, 0x64, 0x40, 0x4C, 0xFD, 0x60, +- 0x58, 0x4E, 0x7A, 0x78, 0xFF, 0xFF, 0x00, 0xBB, 0xFF, 0xFF, 0x01, 0x02, 0x3B, 0x00, 0x02, 0x60, +- 0x01, 0x63, 0xA3, 0xD1, 0xDB, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0x03, 0x36, 0x1F, 0x00, 0x19, 0x60, +- 0x45, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x26, 0x09, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, +- 0xFD, 0xB4, 0x60, 0x44, 0x64, 0x40, 0x02, 0x27, 0x02, 0xBC, 0xA2, 0xDB, 0x19, 0x60, 0x45, 0xF3, +- 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x26, 0x1C, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0xFB, 0xB4, +- 0x60, 0x44, 0x64, 0x40, 0x04, 0x27, 0x04, 0xBC, 0xA2, 0xDB, 0x12, 0x00, 0x64, 0x40, 0x02, 0x2B, +- 0x06, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0x60, 0x44, 0xA2, 0xDB, 0x64, 0x40, +- 0x04, 0x2B, 0x06, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x04, 0xBC, 0x60, 0x44, 0xA2, 0xDB, +- 0x2F, 0x58, 0xFF, 0xFF, 0x0E, 0xF0, 0xDB, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0x03, 0x36, 0x18, 0x00, +- 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x02, 0xBC, 0x60, 0x44, 0xFB, 0xB4, 0x60, 0x44, 0x64, 0x40, +- 0x20, 0x2A, 0x0A, 0x00, 0x60, 0x43, 0x19, 0x60, 0x45, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x02, 0x26, +- 0x02, 0x00, 0x63, 0x44, 0x02, 0x00, 0x63, 0x44, 0x04, 0xBC, 0x19, 0x60, 0x7B, 0xFB, 0x09, 0x00, +- 0x64, 0x40, 0x20, 0x26, 0x06, 0x00, 0x19, 0x60, 0x7B, 0xF3, 0xFF, 0xFF, 0x04, 0xBC, 0x60, 0x44, +- 0xA2, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0xB0, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x25, 0x78, +- 0xFF, 0xFF, 0x66, 0x44, 0x5C, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x80, 0x64, 0x2A, 0xFA, 0xC9, 0xF1, +- 0x19, 0xF8, 0x00, 0x64, 0x3E, 0xFA, 0x00, 0x60, 0x80, 0x64, 0x0E, 0xFA, 0xA6, 0xF1, 0x07, 0xF8, +- 0x67, 0x44, 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0xF1, 0x60, 0x2C, 0x64, 0x08, 0x60, 0x31, 0xFB, +- 0x2F, 0x58, 0xFF, 0xFF, 0x5C, 0xF5, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, +- 0x31, 0xF8, 0x7F, 0xF1, 0x32, 0xF8, 0x80, 0xF1, 0x33, 0xF8, 0x81, 0xF1, 0x34, 0xF8, 0x16, 0x60, +- 0xC2, 0xF1, 0x02, 0x64, 0x64, 0x40, 0xFE, 0x26, 0x10, 0xBC, 0x32, 0x40, 0x08, 0x26, 0x10, 0xBC, +- 0x20, 0xBC, 0xFB, 0x60, 0xFF, 0x65, 0x60, 0x44, 0xA4, 0x84, 0x1B, 0x60, 0x09, 0xFB, 0x16, 0x60, +- 0xC1, 0xF1, 0x33, 0x60, 0xBE, 0x64, 0x02, 0x18, 0x2D, 0x60, 0x32, 0x64, 0x1A, 0x60, 0xAD, 0xFB, +- 0x1A, 0x60, 0xBD, 0xFB, 0x34, 0x60, 0x18, 0x61, 0x17, 0x60, 0x14, 0xF3, 0x35, 0x60, 0x36, 0x65, +- 0xFE, 0xA4, 0xE0, 0x84, 0x06, 0x05, 0x67, 0x44, 0x1A, 0x60, 0xB5, 0xFB, 0x1A, 0x60, 0xC5, 0xFB, +- 0x4B, 0x00, 0xE0, 0x84, 0xC4, 0x85, 0x1A, 0x60, 0x1F, 0xF3, 0xA5, 0xD1, 0xDA, 0x85, 0xA0, 0x83, +- 0x1A, 0x60, 0x1B, 0xFD, 0xA5, 0xD1, 0x34, 0x60, 0x34, 0x62, 0xA0, 0x83, 0xA2, 0xDD, 0x67, 0x44, +- 0x1A, 0x60, 0xB5, 0xFB, 0x1A, 0x60, 0xC5, 0xFB, 0x1A, 0x60, 0x2C, 0xF3, 0xFF, 0xFF, 0x21, 0x18, +- 0x33, 0x60, 0xF4, 0x61, 0x0F, 0x60, 0x00, 0x7C, 0x00, 0x60, 0xAC, 0x65, 0xEF, 0x60, 0x58, 0x4D, +- 0xC1, 0x78, 0xFF, 0xFF, 0x1A, 0x60, 0x2D, 0xF1, 0x59, 0xD9, 0x33, 0x60, 0xF2, 0x65, 0xD5, 0x84, +- 0x30, 0x7F, 0xA5, 0xDB, 0x65, 0x44, 0x1A, 0x60, 0xB5, 0xFB, 0x1A, 0x60, 0xC5, 0xFB, 0x1A, 0x60, +- 0x2C, 0xF3, 0xFF, 0xFF, 0xFE, 0xA4, 0xFF, 0xFF, 0x08, 0x24, 0x03, 0x00, 0xFF, 0x60, 0xFF, 0x64, +- 0x13, 0x00, 0x34, 0x60, 0x18, 0x61, 0x50, 0x60, 0x00, 0x7C, 0x00, 0x60, 0xF2, 0x65, 0xEF, 0x60, +- 0x58, 0x4D, 0xC1, 0x78, 0xFF, 0xFF, 0x1A, 0x60, 0x1D, 0xF1, 0x59, 0xD9, 0x34, 0x60, 0x12, 0x65, +- 0xD5, 0x84, 0xDD, 0x7F, 0xA5, 0xDB, 0x65, 0x44, 0x1A, 0x60, 0xB2, 0xFB, 0x1A, 0x60, 0xC2, 0xFB, +- 0x79, 0x00, 0x1A, 0x60, 0x1E, 0xF3, 0x34, 0x60, 0x34, 0x62, 0xFD, 0xA0, 0xA2, 0xD3, 0xEE, 0x03, +- 0x60, 0x40, 0x02, 0x2A, 0x02, 0x00, 0x01, 0x63, 0x0B, 0x00, 0x04, 0x2A, 0x02, 0x00, 0x02, 0x63, +- 0x07, 0x00, 0x10, 0x2A, 0x02, 0x00, 0x04, 0x63, 0x03, 0x00, 0x20, 0x2A, 0x01, 0x00, 0x05, 0x63, +- 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x1A, 0x60, 0x1E, 0xF3, 0x1A, 0x60, 0x1B, 0xF3, +- 0xFE, 0xA0, 0x40, 0x4C, 0xD3, 0x03, 0x00, 0x60, 0x00, 0x63, 0x59, 0xDD, 0x41, 0x4A, 0x2C, 0x40, +- 0x01, 0x2A, 0x05, 0x00, 0x00, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, +- 0x02, 0x2A, 0x03, 0x00, 0x01, 0x63, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x04, 0x2A, 0x05, 0x00, +- 0x02, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x10, 0x2A, 0x05, 0x00, +- 0x04, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x20, 0x2A, 0x05, 0x00, +- 0x05, 0x63, 0x63, 0x47, 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2A, 0x44, 0x51, 0x93, 0xEB, 0x83, +- 0xEB, 0x83, 0xA0, 0xDD, 0x1A, 0x60, 0x1E, 0xF3, 0x1A, 0x60, 0x1C, 0xF3, 0xFF, 0xA0, 0x40, 0x4C, +- 0x9D, 0x03, 0x59, 0xDF, 0x41, 0x4A, 0x2C, 0x40, 0x01, 0x2A, 0x05, 0x00, 0x00, 0x63, 0x63, 0x47, +- 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x02, 0x2A, 0x05, 0x00, 0x01, 0x63, 0x63, 0x47, +- 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2C, 0x40, 0x04, 0x2A, 0x05, 0x00, 0x02, 0x63, 0x63, 0x47, +- 0xB4, 0x83, 0x59, 0xD9, 0x59, 0xDD, 0x2A, 0x44, 0x51, 0x93, 0xEB, 0x83, 0xEB, 0x83, 0xA0, 0xDD, +- 0x2D, 0x58, 0xFF, 0xFF, 0x00, 0x60, 0x04, 0x64, 0x08, 0x60, 0x0A, 0xFB, 0xF0, 0x60, 0x44, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x12, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0x7D, 0xF1, 0x35, 0x60, 0xCC, 0x64, 0x64, 0x40, 0x01, 0x2B, 0x01, 0x00, 0x67, 0x44, 0x1A, 0x60, +- 0xAF, 0xFB, 0x1A, 0x60, 0xBF, 0xFB, 0x1A, 0x60, 0xE7, 0xF9, 0x35, 0x60, 0x62, 0x65, 0xF1, 0x60, +- 0x58, 0x4D, 0x74, 0x78, 0xFF, 0xFF, 0x7D, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x2B, 0x05, 0x00, +- 0xFF, 0x60, 0xFF, 0x63, 0x1A, 0x60, 0xB3, 0xFD, 0x08, 0x00, 0x36, 0x60, 0x04, 0x63, 0x1A, 0x60, +- 0xB3, 0xFD, 0xF1, 0x60, 0x58, 0x4D, 0x8C, 0x78, 0xFF, 0xFF, 0x5C, 0xF5, 0x00, 0xF4, 0x7E, 0xF1, +- 0x06, 0xF8, 0x1B, 0x60, 0x09, 0xF3, 0x19, 0x60, 0x7B, 0xF1, 0xFB, 0x60, 0xFF, 0x65, 0x60, 0x44, +- 0xA4, 0x84, 0x60, 0x47, 0x64, 0x40, 0x10, 0x26, 0x04, 0xBC, 0x60, 0x47, 0x07, 0xFA, 0x35, 0x60, +- 0x5A, 0x64, 0x40, 0x48, 0x10, 0x61, 0x00, 0x60, 0x00, 0x64, 0xF1, 0x60, 0x58, 0x4D, 0x34, 0x78, +- 0xFF, 0xFF, 0x5C, 0xF5, 0x3F, 0xFC, 0xDB, 0xFE, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, +- 0x66, 0x44, 0x5A, 0xDB, 0x04, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0xDB, 0xF3, 0x9B, 0xFE, 0xFD, 0xA0, 0x25, 0x04, 0x24, 0x02, 0x04, 0x64, 0x03, 0xFA, +- 0x00, 0xF4, 0x09, 0xF2, 0xFF, 0xFF, 0x60, 0x47, 0x00, 0x3A, 0x1C, 0x00, 0x60, 0x43, 0x00, 0x36, +- 0x1C, 0x00, 0xE0, 0xA0, 0xDA, 0x85, 0x16, 0x07, 0x33, 0x60, 0xBE, 0x61, 0xA1, 0xD1, 0xFF, 0xFF, +- 0xD3, 0x80, 0xCB, 0x83, 0x0F, 0x02, 0x07, 0x0E, 0x59, 0xD3, 0xA5, 0xD0, 0xDA, 0x85, 0xD0, 0x80, +- 0xFF, 0xFF, 0x08, 0x02, 0xF9, 0x1F, 0x12, 0x1E, 0xA5, 0xD0, 0x59, 0xD3, 0xFF, 0xFF, 0x90, 0x80, +- 0xFF, 0x22, 0x0C, 0x00, 0xF1, 0x60, 0x2A, 0x78, 0xFF, 0xFF, 0x16, 0x60, 0xC1, 0xF3, 0xFF, 0xFF, +- 0x60, 0x40, 0x01, 0x2A, 0x03, 0x00, 0x2D, 0x60, 0x32, 0x64, 0x02, 0x00, 0x33, 0x60, 0xBE, 0x64, +- 0x1A, 0x60, 0xBD, 0xFB, 0x26, 0x46, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, +- 0x2E, 0xFA, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, 0x7F, 0xF1, +- 0x32, 0xF8, 0x80, 0xF1, 0x33, 0xF8, 0x81, 0xF1, 0x34, 0xF8, 0x00, 0x65, 0xFD, 0x60, 0x58, 0x4E, +- 0xDD, 0x78, 0xFF, 0xFF, 0x61, 0x44, 0x19, 0x60, 0x3F, 0xFB, 0x50, 0x63, 0x2A, 0xFC, 0xC9, 0xF3, +- 0x19, 0xFA, 0x00, 0x64, 0x3E, 0xFA, 0xA6, 0xF3, 0x07, 0xFA, 0x00, 0xF4, 0x7E, 0xF1, 0x06, 0xF8, +- 0x1B, 0x60, 0x09, 0xF3, 0x19, 0x60, 0x7B, 0xF1, 0xFB, 0x60, 0xFF, 0xB7, 0x64, 0x40, 0x10, 0x26, +- 0x04, 0xBC, 0x60, 0x47, 0x07, 0xFA, 0x35, 0x60, 0x82, 0x65, 0xF1, 0x60, 0x58, 0x4D, 0x74, 0x78, +- 0xFF, 0xFF, 0x7D, 0xF3, 0x36, 0x60, 0x04, 0x63, 0x60, 0x40, 0x01, 0x27, 0x67, 0x43, 0x1A, 0x60, +- 0xC3, 0xFD, 0x35, 0x60, 0x7A, 0x64, 0x40, 0x48, 0x10, 0x61, 0x00, 0x60, 0x00, 0x64, 0xF1, 0x60, +- 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x26, 0x46, 0x3F, 0xFC, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, +- 0x0D, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, +- 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x09, 0xFB, 0x5A, 0xDB, +- 0x00, 0x64, 0x92, 0xFB, 0x2F, 0x58, 0xFF, 0xFF, 0x1B, 0x60, 0x0A, 0xFB, 0xCD, 0x81, 0x28, 0xD3, +- 0x5A, 0x88, 0xDC, 0x83, 0x31, 0x18, 0xFB, 0x03, 0x61, 0x40, 0x7F, 0x3A, 0x06, 0x00, 0x1B, 0x60, +- 0x0A, 0xF3, 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x00, 0xF4, 0x60, 0xFE, 0xA3, 0xD1, 0x5D, 0xD8, +- 0x61, 0x40, 0x7F, 0x3A, 0x08, 0x00, 0x20, 0xFE, 0x1B, 0x60, 0x0A, 0xF3, 0x03, 0x61, 0x7C, 0xA4, +- 0xA2, 0xDB, 0x00, 0xF4, 0x60, 0xFE, 0xBF, 0xD3, 0x5D, 0xDA, 0xFF, 0xB4, 0x00, 0x7F, 0x12, 0x03, +- 0xDF, 0x83, 0x61, 0x40, 0x7F, 0x3A, 0x0A, 0x00, 0x20, 0xFE, 0x60, 0x45, 0x1B, 0x60, 0x0A, 0xF3, +- 0x03, 0x61, 0x7C, 0xA4, 0xA2, 0xDB, 0x65, 0x44, 0x00, 0xF4, 0x60, 0xFE, 0xBD, 0xD1, 0xCC, 0x84, +- 0x5D, 0xD8, 0xEF, 0x02, 0x20, 0xFE, 0xCB, 0x01, 0x1B, 0x60, 0x0A, 0xF1, 0xFD, 0xA1, 0xFF, 0xB1, +- 0xC1, 0x83, 0xA2, 0xDD, 0x2D, 0x58, 0xFF, 0xFF, 0x67, 0x5C, 0x1C, 0x60, 0xE6, 0x61, 0xA1, 0xD3, +- 0xA5, 0xD9, 0x10, 0x18, 0x60, 0x43, 0x35, 0x60, 0xD4, 0x64, 0xA5, 0xDB, 0x60, 0xFE, 0xA0, 0xDD, +- 0x20, 0xFE, 0xDC, 0x84, 0xCF, 0x83, 0xE3, 0x83, 0x59, 0xD1, 0xDC, 0x84, 0x60, 0xFE, 0xA0, 0xD9, +- 0x20, 0xFE, 0xFA, 0x1F, 0x2D, 0x58, 0xFF, 0xFF, 0x19, 0x60, 0x7B, 0xF3, 0x36, 0x60, 0x06, 0x62, +- 0x07, 0xB4, 0x60, 0xFE, 0xA2, 0xDB, 0x20, 0xFE, 0x2D, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, +- 0x40, 0x26, 0x27, 0x00, 0x45, 0x48, 0x00, 0x60, 0x10, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, +- 0xFF, 0xFF, 0x1F, 0x03, 0xF2, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x00, 0x60, 0x48, 0x61, 0x28, 0x44, +- 0x59, 0xDA, 0x03, 0x64, 0x38, 0x43, 0xBD, 0xD1, 0xCC, 0x84, 0x59, 0xD8, 0xFC, 0x02, 0x39, 0x44, +- 0x59, 0xDA, 0x16, 0x60, 0xC3, 0xF3, 0x59, 0xDA, 0x07, 0x64, 0x23, 0xFA, 0x26, 0x60, 0x0A, 0x64, +- 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, +- 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0x0E, 0x57, 0x32, 0x40, 0x40, 0x26, 0x1B, 0x00, 0x45, 0x48, +- 0x00, 0x60, 0x06, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, 0xFF, 0xFF, 0x13, 0x03, 0x02, 0x64, +- 0x23, 0xFA, 0xF2, 0x60, 0x00, 0x64, 0x5A, 0xDA, 0x28, 0x44, 0x5A, 0xDA, 0xFF, 0xFF, 0x26, 0x60, +- 0x0A, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, 0xA0, 0xD3, 0xFF, 0xFF, 0xDC, 0x84, 0xDC, 0x80, +- 0xD0, 0x80, 0x03, 0x03, 0xA2, 0xDB, 0x08, 0x24, 0xC6, 0xFE, 0xDD, 0x98, 0xFF, 0xFF, 0xB5, 0xF1, +- 0xA0, 0xD3, 0xFF, 0xFF, 0xD8, 0x80, 0xC4, 0x84, 0x0C, 0x03, 0x08, 0x05, 0xDC, 0x80, 0xD0, 0x80, +- 0x05, 0x03, 0xA2, 0xDB, 0x02, 0x24, 0xC6, 0xFE, 0xDD, 0x98, 0xFF, 0xFF, 0xFF, 0x60, 0xFE, 0x64, +- 0xA2, 0xDB, 0xDD, 0x98, 0xFF, 0xFF, 0xA2, 0xFF, 0x32, 0x40, 0x40, 0x26, 0x3C, 0x00, 0x9B, 0xF3, +- 0x67, 0x43, 0xDC, 0x84, 0xCC, 0x84, 0x37, 0x03, 0x60, 0x46, 0x0A, 0x02, 0x9B, 0xFD, 0x00, 0x60, +- 0x46, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x22, 0x78, 0xFF, 0xFF, 0x66, 0x44, 0x9B, 0xFB, 0x2C, 0x03, +- 0x46, 0x4B, 0x2C, 0x60, 0xCA, 0x61, 0x18, 0x64, 0x23, 0xFA, 0xF1, 0x60, 0x00, 0x64, 0x24, 0xFA, +- 0x4A, 0x65, 0xA2, 0xFF, 0x2C, 0x63, 0x59, 0xD1, 0xA2, 0xDF, 0xA5, 0xD8, 0xDA, 0x85, 0x80, 0x3A, +- 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF7, 0x1F, 0x12, 0x63, 0x59, 0xD1, 0xA5, 0xD8, 0xDA, 0x85, +- 0x80, 0x3A, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0xF8, 0x1F, 0x26, 0x60, 0x0A, 0x64, 0x13, 0x60, +- 0x0D, 0xFB, 0x2B, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, +- 0xA6, 0xFE, 0x00, 0x64, 0x9B, 0xFB, 0xA3, 0xFF, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0xA6, 0xFE, +- 0xBA, 0x05, 0xA7, 0xFE, 0x11, 0x05, 0xA5, 0xFE, 0x03, 0x04, 0xF2, 0x60, 0xD8, 0x78, 0xFF, 0xFF, +- 0xA4, 0xFE, 0xF2, 0x04, 0x08, 0x60, 0x0F, 0xF1, 0x00, 0x60, 0x80, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0x36, 0x45, 0x20, 0x60, 0xA8, 0x64, 0x44, 0xD7, +- 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0xF3, 0xFF, 0xFF, 0x01, 0xB0, 0x00, 0x64, 0x2F, 0x03, 0x9D, 0xFB, +- 0x31, 0x44, 0xE8, 0xB4, 0x40, 0x51, 0x6A, 0x44, 0xFF, 0xFF, 0x80, 0x26, 0xFC, 0x01, 0x61, 0xFF, +- 0x62, 0xFF, 0x08, 0x60, 0x30, 0xF1, 0x00, 0x60, 0x20, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x40, 0x60, 0x58, 0x4E, 0x7D, 0x78, 0xFF, 0xFF, 0x1F, 0x60, 0xC4, 0x64, 0x0F, 0x60, 0xE1, 0xFB, +- 0x4A, 0xDF, 0x01, 0x60, 0xFE, 0x63, 0x1D, 0x60, 0xBE, 0x61, 0x00, 0x64, 0x59, 0xDB, 0xFE, 0x1F, +- 0x0E, 0x60, 0xDD, 0xF3, 0xFF, 0xFF, 0x04, 0xB0, 0xFF, 0xFF, 0x05, 0x03, 0x02, 0x65, 0xF1, 0x60, +- 0x58, 0x4E, 0xC3, 0x78, 0xFF, 0xFF, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0xF2, 0x60, 0xD8, 0x78, +- 0xFF, 0xFF, 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x37, 0x00, 0x2D, 0x60, 0xAA, 0x63, 0xBD, 0xD3, 0xBD, 0xD1, 0xBD, 0xD1, 0xB0, 0x84, 0xB0, 0x84, +- 0xFF, 0xFF, 0x07, 0x02, 0x8A, 0xFB, 0x31, 0x44, 0xFE, 0xB4, 0x40, 0x51, 0x0D, 0x64, 0x05, 0xFB, +- 0x27, 0x00, 0x28, 0xF3, 0x9D, 0xF1, 0x60, 0x47, 0x64, 0x41, 0x07, 0xB1, 0x07, 0xB4, 0x50, 0xFB, +- 0x01, 0x61, 0x03, 0x03, 0xCC, 0x84, 0xE1, 0x81, 0xFD, 0x02, 0xA1, 0x80, 0xB1, 0x83, 0x18, 0x02, +- 0x9D, 0xFD, 0x16, 0x60, 0xCF, 0xF3, 0xE4, 0xFB, 0x7D, 0xFB, 0x13, 0x60, 0x02, 0xF3, 0xFF, 0xFF, +- 0x00, 0xA8, 0x60, 0x46, 0x46, 0x5E, 0x31, 0x44, 0x01, 0xBC, 0x40, 0x51, 0xED, 0xE2, 0x0F, 0x4E, +- 0x1D, 0x60, 0x58, 0x4F, 0x9F, 0x78, 0xFF, 0xFF, 0x0E, 0x4F, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, +- 0xD7, 0xFE, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0xF2, 0x60, 0xE4, 0x64, 0x08, 0x60, 0x3B, 0xFB, +- 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x00, 0x64, 0x08, 0x60, 0x27, 0xFB, 0x5A, 0xDB, +- 0x10, 0x60, 0x4E, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, 0x28, 0xF3, +- 0xFF, 0xFF, 0x01, 0xB0, 0xFF, 0xFF, 0x1D, 0x03, 0x20, 0x40, 0x06, 0x23, 0x10, 0x00, 0x08, 0x60, +- 0x27, 0xF1, 0x7F, 0x60, 0xFF, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x80, 0x60, 0x00, 0x64, 0x08, 0x60, +- 0x28, 0xFB, 0xF2, 0x60, 0xF4, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x1D, 0x60, +- 0xA9, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x27, 0xF1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0xC6, 0x01, 0x08, 0x60, 0x27, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, +- 0xCF, 0xFE, 0xDB, 0xF3, 0x01, 0x63, 0xFD, 0xA0, 0x08, 0x60, 0x77, 0xFD, 0x07, 0x02, 0x08, 0x60, +- 0x30, 0xF1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xB1, 0x01, 0x0E, 0x57, +- 0x32, 0x40, 0x40, 0x26, 0x1B, 0x00, 0x45, 0x48, 0x00, 0x60, 0x06, 0x61, 0xB6, 0x60, 0x58, 0x4D, +- 0x22, 0x78, 0xFF, 0xFF, 0x13, 0x03, 0x02, 0x64, 0x23, 0xFA, 0xF2, 0x60, 0x04, 0x64, 0x5A, 0xDA, +- 0x28, 0x44, 0x5A, 0xDA, 0xFF, 0xFF, 0x26, 0x60, 0x0A, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, +- 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x37, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x15, 0xF1, 0x00, 0x60, 0x02, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x88, 0x01, +- 0x12, 0x60, 0xF6, 0xF3, 0xFF, 0xFF, 0x00, 0xA8, 0x60, 0x46, 0x0E, 0xF2, 0x4B, 0x03, 0x60, 0x40, +- 0xF0, 0x37, 0x38, 0x00, 0xFF, 0x37, 0x2D, 0x00, 0xFD, 0x37, 0x25, 0x00, 0xF8, 0x37, 0x0A, 0x00, +- 0x60, 0x47, 0xFF, 0xB5, 0x10, 0x60, 0x12, 0x62, 0x46, 0xD1, 0x00, 0x60, 0x01, 0x64, 0xB0, 0x84, +- 0xA2, 0xDB, 0xCF, 0xFE, 0x00, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xDC, 0x01, 0x06, 0xB4, 0xFD, 0x7F, 0x0E, 0xFA, 0x25, 0x60, +- 0xF2, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, +- 0x2B, 0xFF, 0xF9, 0xFE, 0xCD, 0x01, 0x23, 0xF0, 0x60, 0x40, 0x04, 0x26, 0xED, 0x1B, 0x02, 0x26, +- 0xEB, 0x18, 0xA2, 0xFF, 0x02, 0xF0, 0x09, 0x60, 0x08, 0x64, 0xD0, 0x80, 0xAD, 0xF3, 0x02, 0x02, +- 0xCC, 0x84, 0xAD, 0xFB, 0x26, 0x60, 0x1A, 0x64, 0x40, 0x4B, 0x34, 0x60, 0x58, 0x4D, 0x08, 0x78, +- 0xFF, 0xFF, 0xB6, 0x01, 0xAC, 0xFE, 0x09, 0x05, 0xAD, 0xFE, 0x0F, 0x05, 0xAE, 0xFE, 0xB0, 0x05, +- 0xAF, 0xFE, 0x37, 0x05, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0x08, 0x60, 0x08, 0xF1, 0x20, 0x60, +- 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0xF5, 0x01, 0x10, 0x60, 0x7A, 0x65, 0x0D, 0x61, +- 0x07, 0x00, 0xA2, 0xDD, 0x58, 0x4F, 0x64, 0x58, 0xFF, 0xFF, 0x00, 0xB9, 0xFF, 0xFF, 0x08, 0x03, +- 0x00, 0x63, 0xA5, 0xD1, 0x5A, 0xD3, 0xDA, 0x85, 0x00, 0xA8, 0xCD, 0x81, 0xF2, 0x02, 0xF8, 0x02, +- 0xE1, 0x01, 0x10, 0x60, 0x0E, 0x62, 0x10, 0x60, 0x58, 0x65, 0xF3, 0x60, 0xD7, 0x63, 0x5A, 0xDF, +- 0xD6, 0x80, 0xFF, 0xFF, 0x04, 0x03, 0x5A, 0xDF, 0x5A, 0xDF, 0x5A, 0xDD, 0xF9, 0x01, 0x10, 0x60, +- 0x78, 0x65, 0x5A, 0xDF, 0xD6, 0x80, 0xFF, 0xFF, 0x02, 0x03, 0x5A, 0xDD, 0xFB, 0x01, 0x2F, 0x58, +- 0xFF, 0xFF, 0x10, 0x60, 0x12, 0x64, 0x40, 0x41, 0x10, 0x60, 0x10, 0x63, 0xA3, 0xD1, 0x00, 0x64, +- 0xD0, 0x80, 0x0C, 0x61, 0x08, 0x03, 0xBD, 0xDB, 0xA3, 0xD3, 0xFF, 0xFF, 0xB0, 0x84, 0xCD, 0x81, +- 0xA3, 0xDB, 0x06, 0xA3, 0xF9, 0x02, 0x10, 0x60, 0x60, 0x63, 0xA3, 0xD1, 0x00, 0x64, 0xD0, 0x80, +- 0x0D, 0x61, 0x19, 0x03, 0xBD, 0xDB, 0x64, 0x44, 0xFE, 0xA3, 0x02, 0xA3, 0xCD, 0x81, 0xE8, 0x84, +- 0xE3, 0x03, 0x02, 0x05, 0xE1, 0x03, 0xF9, 0x01, 0x97, 0xFB, 0x99, 0xFD, 0x61, 0x5C, 0xA3, 0xD3, +- 0x98, 0xF9, 0x03, 0x18, 0x58, 0x4F, 0x60, 0x58, 0xFF, 0xFF, 0x99, 0xF3, 0x98, 0xF1, 0x60, 0x43, +- 0x97, 0xF3, 0x64, 0x41, 0xEA, 0x01, 0x21, 0x43, 0x10, 0x60, 0x5A, 0x65, 0xD7, 0x80, 0xBD, 0xD1, +- 0xBD, 0xD3, 0x03, 0x02, 0xCA, 0x60, 0xD4, 0x78, 0xFF, 0xFF, 0xA0, 0x84, 0xBD, 0xD1, 0x43, 0x41, +- 0xF5, 0x03, 0xF3, 0x60, 0xDC, 0x64, 0x64, 0x58, 0x40, 0x4F, 0x2A, 0xF0, 0x83, 0x60, 0xFF, 0x65, +- 0x64, 0x47, 0x03, 0x2B, 0x01, 0x00, 0x14, 0x00, 0x03, 0x26, 0x03, 0xAC, 0x60, 0x47, 0xA4, 0x84, +- 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, 0x2E, 0xFA, 0x64, 0x41, +- 0xEA, 0xF3, 0x2F, 0xFA, 0x60, 0x43, 0xEB, 0xF3, 0x30, 0xFA, 0xEC, 0xF1, 0x31, 0xF8, 0x19, 0x00, +- 0x60, 0x47, 0xA4, 0x84, 0x2A, 0xFA, 0x2F, 0xF2, 0x2C, 0xFA, 0x30, 0xF2, 0x2D, 0xFA, 0x31, 0xF2, +- 0x2E, 0xFA, 0x36, 0xF2, 0x32, 0xFA, 0x37, 0xF2, 0x33, 0xFA, 0x38, 0xF2, 0x34, 0xFA, 0xEA, 0xF3, +- 0x2F, 0xFA, 0x36, 0xFA, 0xEB, 0xF3, 0x30, 0xFA, 0x37, 0xFA, 0xEC, 0xF3, 0x31, 0xFA, 0x38, 0xFA, +- 0x64, 0x41, 0x1C, 0xF2, 0x13, 0xFA, 0x00, 0xF4, 0x0D, 0xF2, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2B, +- 0x17, 0x00, 0x81, 0x67, 0xA2, 0xDA, 0xF4, 0x60, 0x58, 0x4E, 0xCF, 0x78, 0xFF, 0xFF, 0x26, 0x46, +- 0x3F, 0xFC, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, +- 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xC1, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, +- 0x26, 0x46, 0x3F, 0xF0, 0x42, 0x64, 0xD0, 0x80, 0xFF, 0xFF, 0x01, 0x04, 0x3F, 0xFA, 0x07, 0xF2, +- 0xA6, 0xF1, 0x01, 0x1B, 0x07, 0xF8, 0x1C, 0xF2, 0x13, 0xFA, 0x26, 0xF2, 0x27, 0xF0, 0x60, 0x47, +- 0x00, 0xF4, 0x1F, 0xFA, 0x64, 0x47, 0x20, 0xFA, 0x61, 0x44, 0x21, 0xFA, 0x01, 0x67, 0x0D, 0xFA, +- 0x10, 0x61, 0x2D, 0x60, 0x5E, 0x64, 0x1E, 0x63, 0x58, 0xD1, 0xCD, 0x81, 0xBD, 0xD8, 0xFC, 0x02, +- 0xB8, 0xF1, 0xD6, 0xF1, 0x64, 0x5E, 0x64, 0x5F, 0x44, 0x63, 0xBD, 0xDA, 0x16, 0x60, 0xAC, 0xF3, +- 0xFF, 0xFF, 0xE0, 0x84, 0xE0, 0x84, 0xE0, 0x84, 0x4A, 0xD3, 0x60, 0x45, 0x60, 0x40, 0x01, 0x36, +- 0x03, 0x64, 0x02, 0x36, 0x01, 0x64, 0xB4, 0x84, 0x06, 0xA2, 0xA2, 0xD1, 0xBD, 0xDA, 0x64, 0x47, +- 0xBD, 0xDA, 0xD3, 0xF3, 0xD4, 0xF1, 0x60, 0x47, 0xBD, 0xDA, 0x64, 0x47, 0xE2, 0xF1, 0xBD, 0xDA, +- 0x64, 0x44, 0xBD, 0xDA, 0x26, 0x46, 0x00, 0x64, 0x23, 0xF0, 0x3B, 0xF0, 0x64, 0x40, 0x10, 0x2A, +- 0x06, 0x00, 0xC0, 0x67, 0xA0, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0xE8, 0x84, 0x10, 0xBC, 0x3E, 0xFA, +- 0x25, 0x60, 0xDA, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x26, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, +- 0xFF, 0xFF, 0x2B, 0xFF, 0xC8, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0xB1, 0xF3, +- 0x1F, 0xFA, 0x32, 0x47, 0x07, 0xFA, 0x24, 0x7E, 0x01, 0x7F, 0x08, 0xFA, 0xD6, 0xF1, 0x09, 0xF8, +- 0x01, 0x60, 0x01, 0x64, 0x0A, 0xFA, 0x01, 0x64, 0x0B, 0xFA, 0x18, 0x64, 0x13, 0x60, 0x0D, 0xFB, +- 0x66, 0x44, 0x5A, 0xDB, 0x0A, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x52, 0x63, 0x2E, 0x58, +- 0xFF, 0xFF, 0x00, 0x60, 0x2A, 0x61, 0xB6, 0x60, 0x58, 0x4D, 0x25, 0x78, 0xFF, 0xFF, 0x66, 0x44, +- 0x5D, 0xFB, 0x04, 0x64, 0x03, 0xFA, 0x67, 0x44, 0x2C, 0xFA, 0x2D, 0xFA, 0x2E, 0xFA, 0x32, 0xFA, +- 0x33, 0xFA, 0x34, 0xFA, 0x12, 0x60, 0x80, 0x64, 0xA6, 0xF1, 0x0E, 0xFA, 0x07, 0xF8, 0x00, 0x64, +- 0x3E, 0xFA, 0x0E, 0x60, 0x3D, 0xFB, 0x06, 0xA2, 0x10, 0x60, 0x80, 0x64, 0xA2, 0xDB, 0x04, 0x64, +- 0x5A, 0xDB, 0x06, 0x64, 0x5A, 0xDB, 0xF8, 0x60, 0xCF, 0x64, 0x08, 0x60, 0x3F, 0xFB, 0x00, 0x64, +- 0x0E, 0x60, 0x43, 0xFB, 0x06, 0xA2, 0x10, 0x60, 0x84, 0x64, 0xA2, 0xDB, 0x08, 0x64, 0x5A, 0xDB, +- 0x06, 0x64, 0x5A, 0xDB, 0xF8, 0x60, 0xD8, 0x64, 0x08, 0x60, 0x41, 0xFB, 0xF8, 0x60, 0xB4, 0x64, +- 0x08, 0x60, 0x34, 0xFB, 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF5, 0x60, 0x31, 0x64, +- 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0xF7, 0x60, 0x6C, 0x78, +- 0xFF, 0xFF, 0x5D, 0xF5, 0xEA, 0xF1, 0x2F, 0xF8, 0xEB, 0xF1, 0x30, 0xF8, 0xEC, 0xF1, 0x31, 0xF8, +- 0xC9, 0xF1, 0x19, 0xF8, 0x00, 0x63, 0x88, 0xFD, 0x1B, 0x60, 0xB2, 0x63, 0x86, 0xFD, 0x87, 0xFD, +- 0x20, 0x40, 0x10, 0x2B, 0x00, 0x00, 0x5D, 0xF5, 0x40, 0x64, 0x2A, 0xFA, 0x7D, 0xF3, 0x7C, 0xFB, +- 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x10, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x03, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x03, 0x00, 0xF6, 0x60, 0xC6, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x3D, 0xF3, 0xFD, 0x60, +- 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x3F, 0xFB, 0x19, 0x60, 0x39, 0xF3, 0x3F, 0x40, +- 0x01, 0x27, 0x08, 0x00, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, +- 0xFF, 0xFF, 0x05, 0x00, 0x0F, 0xB4, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0x5D, 0xF5, +- 0x35, 0x60, 0x70, 0x64, 0x00, 0xF4, 0x40, 0x48, 0x2F, 0x60, 0x24, 0x64, 0x20, 0x40, 0x10, 0x27, +- 0x02, 0x00, 0x2F, 0x60, 0x02, 0x64, 0x28, 0xDB, 0x04, 0x61, 0x00, 0x60, 0x00, 0x64, 0xF1, 0x60, +- 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x5D, 0xF5, 0x3F, 0xFC, 0x01, 0x64, 0x54, 0xF1, 0x10, 0x60, +- 0x12, 0xFB, 0x7D, 0xFB, 0xA4, 0xD3, 0x04, 0x65, 0x53, 0xF3, 0x01, 0x18, 0x0C, 0x65, 0xF3, 0xB4, +- 0xB4, 0x84, 0x53, 0xFB, 0x0D, 0x00, 0xF7, 0x60, 0x6C, 0x78, 0xFF, 0xFF, 0x53, 0xF1, 0x7D, 0xF3, +- 0xFF, 0xFF, 0xF3, 0xA0, 0x04, 0xA4, 0x01, 0x04, 0xF1, 0xA4, 0x10, 0x36, 0xF4, 0x01, 0x7D, 0xFB, +- 0x20, 0x40, 0x10, 0x2B, 0x10, 0x00, 0x7D, 0xF3, 0x32, 0x60, 0x80, 0x61, 0xA1, 0xD1, 0xCC, 0x84, +- 0x01, 0x61, 0x08, 0x24, 0x03, 0x00, 0xE1, 0x81, 0xCC, 0x84, 0xFB, 0x01, 0xA1, 0x84, 0x53, 0xF1, +- 0xE6, 0x03, 0x10, 0x60, 0x12, 0xFB, 0x7D, 0xF3, 0x10, 0x60, 0xF2, 0x61, 0xCC, 0x84, 0xFF, 0xFF, +- 0x02, 0x03, 0x06, 0xA1, 0xFB, 0x01, 0xA1, 0xD3, 0x53, 0xF1, 0x01, 0xB0, 0x02, 0xB0, 0xD7, 0x03, +- 0x64, 0x40, 0x01, 0x26, 0x05, 0x00, 0x20, 0x40, 0x10, 0x27, 0x02, 0x00, 0xD0, 0x03, 0x00, 0x00, +- 0x9D, 0xFE, 0x3D, 0x05, 0xBA, 0xFE, 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, +- 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF5, 0x60, 0xCB, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x7D, 0xF1, +- 0x13, 0x60, 0x1A, 0xF9, 0x08, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, +- 0x08, 0x60, 0x13, 0xFB, 0xF5, 0x60, 0xF0, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x1B, 0x60, 0xF3, 0xF1, 0xAD, 0x4F, 0x00, 0x7F, 0xFA, 0xB4, 0x64, 0x41, 0x7D, 0xF1, 0x02, 0xB1, +- 0x04, 0x65, 0x02, 0x02, 0x64, 0x40, 0x01, 0x2B, 0x01, 0x65, 0xB4, 0x84, 0xA0, 0x5D, 0x10, 0x60, +- 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, +- 0x13, 0xFB, 0xF5, 0x60, 0xC8, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7D, 0xF1, +- 0x13, 0x60, 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, +- 0x08, 0x60, 0x13, 0xFB, 0xF6, 0x60, 0x28, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0xBE, 0xFE, 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, +- 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, 0x5D, 0xF5, 0x25, 0x60, 0xCE, 0x64, 0x13, 0x60, +- 0x0D, 0xFB, 0x66, 0x44, 0x5A, 0xDB, 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0x00, 0x64, +- 0x51, 0xFB, 0x00, 0x60, 0x01, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF6, 0x60, 0x4C, 0x64, 0x5A, 0xDB, +- 0xCF, 0xFE, 0xC1, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, 0xA2, 0xDB, +- 0xC3, 0xF1, 0x0E, 0x60, 0x3F, 0xF9, 0x1C, 0x60, 0x7A, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xC4, 0xF1, 0x0E, 0x60, 0x45, 0xF9, 0x26, 0x60, 0x42, 0x62, +- 0xA2, 0xD3, 0xFF, 0xFF, 0xFD, 0x1B, 0x1C, 0x60, 0x86, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, +- 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x60, 0x08, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF6, 0x60, +- 0x75, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x51, 0xF1, 0x10, 0x60, 0x24, 0x62, +- 0x00, 0x64, 0xA2, 0xDB, 0x64, 0x40, 0xFF, 0x26, 0x0B, 0x00, 0x53, 0xF3, 0xFF, 0xFF, 0x80, 0xB0, +- 0xFF, 0xFF, 0x03, 0x03, 0xF7, 0x60, 0x65, 0x78, 0xFF, 0xFF, 0xF5, 0x60, 0x96, 0x78, 0xFF, 0xFF, +- 0x02, 0x0A, 0x00, 0x64, 0x51, 0xFB, 0xC5, 0xF1, 0x0E, 0x60, 0x45, 0xF9, 0x00, 0x60, 0x0C, 0x64, +- 0x08, 0x60, 0x13, 0xFB, 0xF6, 0x60, 0xA0, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x1C, 0x60, 0x86, 0x64, +- 0x13, 0x60, 0x22, 0xFB, 0x02, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xA0, 0x80, 0x9C, 0x84, 0x0B, 0x03, 0xA0, 0x84, +- 0xA2, 0xDB, 0x1C, 0x60, 0x86, 0x64, 0x13, 0x60, 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, +- 0x04, 0xFF, 0x13, 0x00, 0xFF, 0x60, 0xF7, 0x64, 0xA0, 0x84, 0xA2, 0xDB, 0x51, 0xF3, 0xDE, 0x0A, +- 0x00, 0xA0, 0x00, 0x64, 0x02, 0x03, 0x51, 0xFB, 0xD9, 0x01, 0x1C, 0x60, 0x7A, 0x64, 0x13, 0x60, +- 0x22, 0xFB, 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0xB7, 0x01, 0x19, 0x60, 0x3E, 0xF3, +- 0xFD, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x3F, 0xFB, 0x19, 0x60, 0x3A, 0xF3, +- 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0x5D, 0xF5, +- 0x35, 0x60, 0x70, 0x64, 0x00, 0xF4, 0x40, 0x48, 0x2F, 0x60, 0x24, 0x64, 0x20, 0x40, 0x10, 0x27, +- 0x02, 0x00, 0x2F, 0x60, 0x02, 0x64, 0x28, 0xDB, 0x04, 0x61, 0x00, 0x60, 0x00, 0x64, 0xF1, 0x60, +- 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x5D, 0xF5, 0x3F, 0xFC, 0x53, 0xF3, 0x20, 0x40, 0x10, 0x23, +- 0x02, 0x00, 0x20, 0xBC, 0x04, 0x00, 0x60, 0x40, 0x01, 0x22, 0x40, 0xBC, 0x04, 0xBC, 0x80, 0xBC, +- 0x53, 0xFB, 0x11, 0x60, 0x62, 0x64, 0x08, 0x60, 0x6C, 0xFB, 0x06, 0x64, 0x08, 0x60, 0x73, 0xFB, +- 0x19, 0x60, 0x43, 0xF3, 0xFF, 0xFF, 0x07, 0xB4, 0xA2, 0xDB, 0x53, 0xF3, 0x08, 0x60, 0x6C, 0xF1, +- 0x60, 0x40, 0x20, 0x26, 0x03, 0x00, 0x01, 0x26, 0x32, 0x00, 0x45, 0x00, 0x08, 0x60, 0x73, 0xF3, +- 0xFF, 0xFF, 0xDD, 0xA0, 0x01, 0xA4, 0x58, 0x03, 0xA2, 0xDB, 0x32, 0x60, 0x82, 0x61, 0xE0, 0xA0, +- 0xF0, 0xA0, 0x05, 0x05, 0x01, 0x05, 0x05, 0x00, 0x02, 0xA1, 0xF0, 0xA4, 0x02, 0x00, 0x04, 0xA1, +- 0xE0, 0xA4, 0xA1, 0xD1, 0x01, 0x61, 0xDC, 0x84, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0xE1, 0x81, +- 0xFB, 0x01, 0xA1, 0x80, 0x10, 0x60, 0xE6, 0x64, 0x01, 0x02, 0xE0, 0x01, 0xA0, 0xD3, 0x11, 0x60, +- 0x5A, 0x63, 0xFA, 0xA4, 0xCC, 0x84, 0x08, 0xA3, 0xFD, 0x02, 0xCF, 0xF1, 0xA3, 0xD3, 0x01, 0x18, +- 0xD5, 0x18, 0xFE, 0xA3, 0xA3, 0xD3, 0x7D, 0xFB, 0xF5, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x12, 0x60, +- 0x40, 0x65, 0x64, 0x41, 0xA1, 0xD3, 0xD5, 0x80, 0x00, 0xB8, 0x26, 0x07, 0x02, 0x02, 0x08, 0xA1, +- 0xF9, 0x01, 0x61, 0x44, 0x08, 0x60, 0x6C, 0xFB, 0x01, 0x64, 0xA1, 0xDB, 0x49, 0xD3, 0x7D, 0xFB, +- 0xF5, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x12, 0x60, 0x40, 0x65, 0x64, 0x41, 0xA1, 0xD3, 0xD5, 0x80, +- 0x04, 0xB0, 0x12, 0x07, 0x02, 0x02, 0x08, 0xA1, 0xF9, 0x01, 0x61, 0x44, 0x08, 0x60, 0x6C, 0xFB, +- 0x49, 0xD3, 0x7D, 0xFB, 0xF5, 0x60, 0xC8, 0x78, 0xFF, 0xFF, 0x10, 0x60, 0xD8, 0x65, 0xA5, 0xD3, +- 0xFF, 0xFF, 0x08, 0xA4, 0xA5, 0xDB, 0x99, 0x01, 0x1C, 0x60, 0x7A, 0x64, 0x13, 0x60, 0x22, 0xFB, +- 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x53, 0xF3, 0xFF, 0xFF, 0xE3, 0xB4, 0x53, 0xFB, +- 0x10, 0x60, 0x10, 0xF3, 0xFF, 0xFF, 0xFE, 0xB4, 0xA2, 0xDB, 0x10, 0x60, 0x24, 0x62, 0x00, 0x64, +- 0xA2, 0xDB, 0xDE, 0xFE, 0x0A, 0x04, 0x40, 0x60, 0x00, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF7, 0x60, +- 0x7D, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x7C, 0xF1, 0x7D, 0xF9, 0x13, 0x60, +- 0x1A, 0xF9, 0x0E, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x2D, 0xFF, 0x20, 0x60, 0x00, 0x64, 0x08, 0x60, +- 0x13, 0xFB, 0xF7, 0x60, 0x9F, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0xBE, 0xFE, +- 0x08, 0x60, 0x08, 0xF1, 0x40, 0x60, 0x00, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x53, 0xF3, +- 0xFF, 0xFF, 0x80, 0xB0, 0xFF, 0xFF, 0x54, 0x02, 0x1C, 0x60, 0x32, 0x63, 0x1C, 0x61, 0xCD, 0x81, +- 0xBD, 0xDF, 0xFD, 0x02, 0x14, 0x60, 0x32, 0x61, 0x88, 0xF3, 0x61, 0x43, 0xC4, 0xA5, 0x47, 0xD1, +- 0x0F, 0x04, 0xBE, 0xD5, 0x1C, 0x60, 0x2E, 0x63, 0xC3, 0x83, 0xC3, 0x83, 0xC3, 0x83, 0x43, 0xD3, +- 0xBE, 0xD1, 0xDC, 0x84, 0xA3, 0xDB, 0x66, 0x44, 0xC0, 0x84, 0xBE, 0xDB, 0x65, 0x44, 0xED, 0x01, +- 0x1C, 0x60, 0x32, 0x63, 0x0E, 0x61, 0x41, 0x4B, 0xBD, 0xD3, 0xBD, 0xD1, 0x00, 0xBD, 0x64, 0x41, +- 0x19, 0x03, 0x01, 0xA8, 0x61, 0x44, 0x02, 0xA8, 0x15, 0x03, 0x02, 0x02, 0xE9, 0x84, 0x12, 0x00, +- 0x65, 0x47, 0x60, 0x45, 0x61, 0x44, 0x09, 0x61, 0xCD, 0x81, 0xE0, 0x84, 0xFF, 0x23, 0xFC, 0x01, +- 0x02, 0x24, 0xC4, 0x84, 0x02, 0x28, 0xD4, 0x84, 0xCD, 0x81, 0x01, 0x0E, 0x01, 0xBC, 0x02, 0x03, +- 0xE0, 0x84, 0xF6, 0x01, 0x00, 0x7F, 0x2B, 0x41, 0x4D, 0x8B, 0xBF, 0xDB, 0xDD, 0x02, 0x14, 0x60, +- 0x32, 0x61, 0x88, 0xF3, 0x61, 0x43, 0xC4, 0xA5, 0x47, 0xD1, 0x0A, 0x04, 0xDA, 0x86, 0x1C, 0x60, +- 0x30, 0x63, 0xC3, 0x83, 0xC3, 0x83, 0xC3, 0x83, 0x43, 0xD1, 0xA6, 0xD9, 0x65, 0x44, 0xF2, 0x01, +- 0x53, 0xF3, 0x88, 0xF1, 0xF3, 0xB4, 0x53, 0xFB, 0x14, 0x60, 0x32, 0x63, 0xC3, 0x85, 0x45, 0x4A, +- 0x1B, 0x60, 0xB2, 0x65, 0x87, 0xF3, 0x45, 0x4C, 0x40, 0x48, 0x2A, 0x45, 0xD7, 0x80, 0x02, 0x65, +- 0x17, 0x05, 0x47, 0xD1, 0x02, 0x65, 0x47, 0xD3, 0x0A, 0x65, 0xD0, 0x81, 0x47, 0xD3, 0x01, 0x05, +- 0x00, 0x61, 0xF2, 0xA3, 0x01, 0xB0, 0x61, 0x44, 0x05, 0x03, 0x2C, 0xDB, 0x5A, 0xDD, 0x5A, 0x8C, +- 0x3C, 0xA3, 0xEB, 0x01, 0x28, 0x42, 0x4A, 0xDD, 0x4A, 0xDB, 0x42, 0x48, 0x3C, 0xA3, 0xE5, 0x01, +- 0x28, 0x44, 0x86, 0xFB, 0x86, 0xF1, 0x1B, 0x60, 0xB2, 0x63, 0x44, 0x48, 0x28, 0x45, 0xD7, 0x80, +- 0xA3, 0xD1, 0x15, 0x05, 0x04, 0x65, 0x46, 0xD3, 0x28, 0x45, 0xD6, 0x80, 0xD0, 0x80, 0x02, 0x04, +- 0x04, 0xA3, 0xF5, 0x01, 0xF7, 0x06, 0x62, 0x46, 0xA2, 0xD9, 0xA3, 0xDB, 0x5B, 0xD3, 0x66, 0x42, +- 0x5A, 0xD1, 0xA2, 0xDB, 0xA3, 0xD9, 0xFE, 0xA3, 0xA3, 0xD1, 0x66, 0x42, 0xEB, 0x01, 0x86, 0xF3, +- 0x87, 0xF1, 0x60, 0x43, 0x44, 0x48, 0x28, 0x45, 0xD7, 0x80, 0xA3, 0xD1, 0x15, 0x05, 0x04, 0x65, +- 0x46, 0xD3, 0x28, 0x45, 0xD6, 0x80, 0xD0, 0x80, 0x02, 0x04, 0x04, 0xA3, 0xF5, 0x01, 0xF7, 0x06, +- 0x62, 0x46, 0xA2, 0xD9, 0xA3, 0xDB, 0x5B, 0xD3, 0x66, 0x42, 0x5A, 0xD1, 0xA2, 0xDB, 0xA3, 0xD9, +- 0xFE, 0xA3, 0xA3, 0xD1, 0x66, 0x42, 0xEB, 0x01, 0x08, 0x60, 0x08, 0xF1, 0x10, 0x60, 0x00, 0x64, +- 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x7D, 0xF1, 0x19, 0x60, 0x3D, 0xF3, 0x64, 0x40, 0x01, 0x27, +- 0x27, 0x00, 0xFD, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x3F, 0xFB, 0x19, 0x60, +- 0x39, 0xF3, 0x3F, 0x40, 0x01, 0x27, 0x16, 0x00, 0x0F, 0x60, 0xFF, 0x65, 0x60, 0x41, 0xDB, 0xF3, +- 0xFF, 0xFF, 0x60, 0x40, 0x03, 0x36, 0x07, 0x00, 0x19, 0x60, 0x44, 0xF3, 0xFF, 0xFF, 0x60, 0x40, +- 0x01, 0x2A, 0x01, 0x00, 0x0F, 0x61, 0x61, 0x44, 0xA4, 0x84, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, +- 0xFF, 0xFF, 0x16, 0x00, 0x0F, 0xB4, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, 0x10, 0x00, +- 0x5A, 0xD3, 0xFD, 0x60, 0x58, 0x4E, 0xAC, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x3F, 0xFB, 0x19, 0x60, +- 0x3A, 0xF3, 0x0F, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0xFC, 0x60, 0x58, 0x4E, 0x34, 0x78, 0xFF, 0xFF, +- 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF5, 0x60, 0x31, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, +- 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x1C, 0x60, 0x7A, 0x64, 0x13, 0x60, 0x22, 0xFB, +- 0x03, 0x64, 0x4A, 0xDB, 0xFF, 0xFF, 0x04, 0xFF, 0x00, 0x64, 0x53, 0xFB, 0x00, 0x64, 0x08, 0x60, +- 0x12, 0xFB, 0x5A, 0xDB, 0xBE, 0xFE, 0x00, 0x60, 0x30, 0x64, 0x08, 0x60, 0x13, 0xFB, 0xF5, 0x60, +- 0x31, 0x64, 0x5A, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, 0x2F, 0x58, 0xFF, 0xFF, 0x08, 0x60, +- 0x12, 0xF1, 0x00, 0x60, 0x04, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, 0xFF, 0xFF, +- 0x08, 0x60, 0x12, 0xF1, 0x00, 0x60, 0x08, 0x64, 0xB0, 0x84, 0xA2, 0xDB, 0xCF, 0xFE, 0x2F, 0x58, +- 0xFF, 0xFF, 0x20, 0x40, 0x90, 0x2B, 0x03, 0x00, 0xFB, 0x60, 0xFC, 0x78, 0xFF, 0xFF, 0x53, 0xF3, +- 0x88, 0xF1, 0x04, 0xB0, 0x07, 0x60, 0x80, 0x64, 0xD0, 0x80, 0x20, 0x03, 0x1F, 0x06, 0x26, 0x46, +- 0x88, 0xF1, 0x14, 0x60, 0x32, 0x63, 0xC3, 0x83, 0x7D, 0xF3, 0x26, 0xF0, 0xBD, 0xDB, 0x64, 0x44, +- 0x00, 0x7F, 0xBD, 0xDB, 0x64, 0x47, 0x00, 0x7F, 0xBD, 0xDB, 0x32, 0xF0, 0xBD, 0xD9, 0x33, 0xF0, +- 0xBD, 0xD9, 0x34, 0xF0, 0xBD, 0xD9, 0x00, 0xF4, 0x0D, 0xF0, 0xBD, 0xD9, 0x0E, 0xF0, 0xBD, 0xD9, +- 0x0F, 0xF0, 0xA3, 0xDF, 0x64, 0x47, 0x60, 0x45, 0x00, 0x37, 0x03, 0x00, 0xFB, 0x60, 0xF7, 0x78, +- 0xFF, 0xFF, 0xBD, 0xDB, 0xE0, 0xA0, 0x1F, 0x61, 0x00, 0xB8, 0xF8, 0x07, 0xF7, 0x03, 0x60, 0xFE, +- 0x5D, 0xD0, 0xCC, 0x84, 0xBD, 0xD9, 0xFC, 0x02, 0x65, 0x40, 0x01, 0x26, 0xDF, 0x83, 0x5D, 0xD0, +- 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x3A, 0x03, 0x00, 0x5D, 0xD0, 0xFF, 0xFF, 0xC1, 0x81, 0x5D, 0xD0, +- 0xFF, 0xFF, 0x64, 0x40, 0x03, 0x36, 0x07, 0x00, 0x53, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2A, +- 0xDD, 0x01, 0xCD, 0x81, 0x13, 0x00, 0x53, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x2A, 0x04, 0x00, +- 0x5D, 0xD0, 0xFF, 0xFF, 0xC1, 0x81, 0x0A, 0x00, 0x59, 0xD0, 0x7D, 0xF3, 0xFF, 0xFF, 0xD0, 0x80, +- 0x20, 0xFE, 0x08, 0x24, 0x03, 0x00, 0xFB, 0x60, 0xF7, 0x78, 0xFF, 0xFF, 0x7C, 0x44, 0x1A, 0x60, +- 0x24, 0xFB, 0x1A, 0x60, 0x25, 0xFB, 0x1A, 0x60, 0x26, 0xFB, 0x1A, 0x60, 0x27, 0xFB, 0x1C, 0x60, +- 0x08, 0xFB, 0x1C, 0x60, 0x04, 0xFB, 0x00, 0x64, 0x1C, 0x60, 0x04, 0xFB, 0x20, 0xFE, 0x37, 0x60, +- 0xFE, 0x64, 0x40, 0x4A, 0xF9, 0x60, 0x58, 0x4D, 0xC3, 0x78, 0xFF, 0xFF, 0x1C, 0x60, 0x04, 0xF3, +- 0xFF, 0xFF, 0x09, 0x18, 0xFF, 0xFF, 0x1C, 0x60, 0x06, 0xF3, 0x1C, 0x60, 0x07, 0xF5, 0x60, 0x41, +- 0x00, 0x64, 0x1C, 0x60, 0x04, 0xFB, 0x20, 0xFE, 0x2A, 0xD1, 0xDA, 0x85, 0x64, 0x44, 0x01, 0xA0, +- 0xFF, 0xFF, 0x01, 0x02, 0x79, 0x00, 0x45, 0x4A, 0x7C, 0x44, 0x60, 0xFE, 0xA1, 0xD2, 0xFF, 0xFF, +- 0xD0, 0x80, 0x20, 0xFE, 0x01, 0x03, 0xEF, 0x01, 0x1C, 0x60, 0x04, 0xF3, 0xFF, 0xFF, 0x02, 0x18, +- 0xDD, 0x81, 0x35, 0x00, 0x60, 0xFE, 0x5D, 0xD2, 0xFF, 0xFF, 0x60, 0x5C, 0x41, 0x94, 0x81, 0xA0, +- 0x20, 0xFE, 0x2D, 0x04, 0x01, 0x64, 0x1C, 0x60, 0x04, 0xFB, 0xC1, 0x84, 0x84, 0xA4, 0x1C, 0x60, +- 0x06, 0xFB, 0x00, 0xF2, 0x1C, 0x60, 0x07, 0xFB, 0x1C, 0x60, 0x05, 0xFD, 0x02, 0x60, 0x00, 0x63, +- 0xCD, 0x85, 0x64, 0x44, 0xD8, 0x81, 0xCD, 0x84, 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, +- 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, +- 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, 0xDF, 0x83, 0x00, 0x60, 0x01, 0x61, 0x02, 0x60, +- 0x00, 0x64, 0xE0, 0x87, 0x60, 0x46, 0x1C, 0x60, 0x05, 0xF3, 0xFF, 0xFF, 0x60, 0x43, 0x60, 0xFE, +- 0xCD, 0x81, 0x20, 0xFE, 0x2A, 0x44, 0x38, 0x60, 0x00, 0x7C, 0xD0, 0x84, 0x38, 0x60, 0x04, 0x65, +- 0x44, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0x60, 0x04, 0xF3, 0xFF, 0xFF, 0x08, 0x18, 0x1C, 0x60, +- 0x06, 0xF3, 0x1C, 0x60, 0x07, 0xF5, 0x60, 0x41, 0x00, 0x64, 0x1C, 0x60, 0x04, 0xFB, 0x26, 0x44, +- 0x01, 0xA4, 0x58, 0x90, 0xFF, 0xFF, 0x03, 0x02, 0x61, 0x44, 0x0B, 0xA5, 0x04, 0x00, 0x61, 0x44, +- 0xFC, 0xA4, 0x8B, 0x7C, 0xC0, 0x85, 0xDD, 0x81, 0x66, 0x44, 0x1C, 0x60, 0x07, 0xFB, 0x26, 0x46, +- 0x1B, 0xF0, 0x1C, 0x60, 0x07, 0xF5, 0x64, 0x44, 0xD4, 0x80, 0xFF, 0xFF, 0x02, 0x06, 0x2D, 0x58, +- 0xFF, 0xFF, 0xFA, 0x60, 0xE7, 0x78, 0xFF, 0xFF, 0x60, 0xFE, 0x5D, 0xD2, 0xFF, 0xFF, 0x20, 0xFE, +- 0xFF, 0xB4, 0x41, 0x94, 0x81, 0xA0, 0xFF, 0xFF, 0x02, 0x04, 0x00, 0xF4, 0x84, 0xA4, 0x60, 0x41, +- 0x5D, 0x01, 0x1A, 0x60, 0x2C, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x01, 0x3A, 0x6C, 0x01, 0x61, 0x5C, +- 0x1A, 0x60, 0x2B, 0xF9, 0x60, 0xFE, 0x5D, 0xD2, 0xFF, 0xFF, 0xFE, 0xA4, 0xFF, 0xFF, 0x04, 0x20, +- 0x02, 0x00, 0xFF, 0xA1, 0x60, 0x01, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x02, 0x00, +- 0xFE, 0xA1, 0x59, 0x01, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x36, 0x02, 0x00, 0xFD, 0xA1, +- 0x52, 0x01, 0x01, 0x7C, 0x1C, 0x60, 0x08, 0xF9, 0x4C, 0x00, 0x1A, 0x60, 0x2C, 0xF3, 0xFF, 0xFF, +- 0x01, 0x18, 0x49, 0x01, 0x00, 0x7C, 0x1C, 0x60, 0x08, 0xF9, 0x61, 0x5C, 0x1A, 0x60, 0x2B, 0xF9, +- 0x60, 0xFE, 0x5D, 0xD2, 0xFF, 0xFF, 0xFA, 0xA4, 0xFF, 0xFF, 0x04, 0x20, 0x04, 0x00, 0xFF, 0xA1, +- 0xF9, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x36, 0x04, 0x00, +- 0xC9, 0x81, 0xF9, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x50, 0x36, +- 0x04, 0x00, 0xFD, 0xA1, 0xF9, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, +- 0xF2, 0x36, 0x04, 0x00, 0xFC, 0xA1, 0xF9, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x5D, 0xD0, 0xFF, 0xFF, +- 0x64, 0x40, 0x01, 0x36, 0x04, 0x00, 0xFB, 0xA1, 0xF9, 0x60, 0x6B, 0x78, 0xFF, 0xFF, 0x5D, 0xD0, +- 0xFF, 0xFF, 0x64, 0x40, 0x01, 0x36, 0x04, 0x00, 0xFA, 0xA1, 0xF9, 0x60, 0x6B, 0x78, 0xFF, 0xFF, +- 0x5D, 0xD0, 0xFF, 0xFF, 0x64, 0x40, 0x00, 0x36, 0x04, 0x00, 0xF9, 0xA1, 0xF9, 0x60, 0x6B, 0x78, +- 0xFF, 0xFF, 0x60, 0x5C, 0x00, 0x36, 0x32, 0x00, 0x00, 0x64, 0xFB, 0x60, 0x58, 0x4E, 0x66, 0x78, +- 0xFF, 0xFF, 0x65, 0x40, 0x08, 0x26, 0xF7, 0x01, 0x1A, 0x60, 0x24, 0xFB, 0x64, 0x40, 0x00, 0x36, +- 0x2A, 0x00, 0x5D, 0xD2, 0xDD, 0x81, 0xFB, 0x60, 0x58, 0x4E, 0x66, 0x78, 0xFF, 0xFF, 0x65, 0x40, +- 0x08, 0x26, 0xF6, 0x01, 0x1A, 0x60, 0x25, 0xFB, 0x64, 0x40, 0x00, 0x36, 0x21, 0x00, 0x5D, 0xD2, +- 0xDD, 0x81, 0xFB, 0x60, 0x58, 0x4E, 0x66, 0x78, 0xFF, 0xFF, 0x65, 0x40, 0x08, 0x26, 0xF6, 0x01, +- 0x1A, 0x60, 0x26, 0xFB, 0x64, 0x40, 0x00, 0x36, 0x18, 0x00, 0x5D, 0xD0, 0x34, 0x60, 0x4E, 0x62, +- 0xA2, 0xD9, 0x5D, 0xD0, 0x34, 0x60, 0x4F, 0x62, 0xA2, 0xD9, 0x14, 0x00, 0x20, 0xFE, 0x00, 0x60, +- 0x04, 0x64, 0x1A, 0x60, 0x24, 0xFB, 0x20, 0xFE, 0x00, 0x60, 0x04, 0x64, 0x1A, 0x60, 0x25, 0xFB, +- 0x20, 0xFE, 0x00, 0x60, 0x02, 0x64, 0x1A, 0x60, 0x26, 0xFB, 0x20, 0xFE, 0x00, 0x60, 0x00, 0x64, +- 0x1A, 0x60, 0x27, 0xFB, 0x20, 0xFE, 0x1C, 0x60, 0x08, 0xF1, 0xFF, 0xFF, 0x03, 0x18, 0x01, 0x7C, +- 0x1C, 0x60, 0x08, 0xF9, 0x1A, 0x60, 0x2B, 0xF1, 0xA2, 0xDD, 0x61, 0x44, 0x1A, 0x60, 0x28, 0xFB, +- 0xD1, 0x84, 0xDC, 0x84, 0x64, 0x45, 0x34, 0x60, 0x10, 0x63, 0xBD, 0xDB, 0x60, 0x41, 0xCD, 0x84, +- 0x4C, 0x91, 0x60, 0x43, 0x60, 0xFE, 0xA5, 0xD2, 0xDE, 0x85, 0x7F, 0x26, 0x02, 0x00, 0x00, 0xF4, +- 0x04, 0x65, 0x5D, 0x93, 0xA3, 0xDB, 0x5D, 0x93, 0xA5, 0xD2, 0xF6, 0x1F, 0x5D, 0x93, 0x20, 0xFE, +- 0xDF, 0x83, 0x1A, 0x60, 0x09, 0xF3, 0xFF, 0xFF, 0x60, 0x47, 0xA2, 0xDB, 0x1A, 0x60, 0x28, 0xF3, +- 0x1A, 0x60, 0x2B, 0xF1, 0x60, 0x41, 0x64, 0x43, 0xF9, 0x60, 0x56, 0x78, 0xFF, 0xFF, 0x20, 0xFE, +- 0x7C, 0x44, 0x1A, 0x60, 0x20, 0xFB, 0x1A, 0x60, 0x1A, 0xF1, 0x1A, 0x60, 0x24, 0xF3, 0xFF, 0xFF, +- 0xA0, 0x84, 0xFF, 0xFF, 0x10, 0x26, 0x07, 0x00, 0x04, 0x26, 0x07, 0x00, 0x20, 0x26, 0x07, 0x00, +- 0x02, 0x26, 0x07, 0x00, 0x3F, 0x00, 0x10, 0x7C, 0x05, 0x00, 0x04, 0x7C, 0x03, 0x00, 0x20, 0x7C, +- 0x01, 0x00, 0x02, 0x7C, 0x1A, 0x60, 0x20, 0xF9, 0x7C, 0x44, 0x1A, 0x60, 0x21, 0xFB, 0x1A, 0x60, +- 0x1B, 0xF1, 0x1A, 0x60, 0x25, 0xF3, 0x34, 0x60, 0x40, 0x61, 0xA0, 0x84, 0xA1, 0xD1, 0xFF, 0xFF, +- 0x10, 0x26, 0x05, 0x00, 0x04, 0x26, 0x05, 0x00, 0x01, 0x26, 0x08, 0x00, 0x23, 0x00, 0x10, 0x7C, +- 0x06, 0x00, 0x64, 0x40, 0x10, 0x26, 0x1E, 0x00, 0x04, 0x7C, 0x01, 0x00, 0x01, 0x7C, 0x1A, 0x60, +- 0x21, 0xF9, 0x7C, 0x44, 0x1A, 0x60, 0x22, 0xFB, 0x1A, 0x60, 0x1C, 0xF1, 0x1A, 0x60, 0x26, 0xF3, +- 0xFF, 0xFF, 0xA0, 0x84, 0x60, 0x40, 0x02, 0x26, 0x05, 0x00, 0x04, 0x26, 0x05, 0x00, 0x01, 0x26, +- 0x05, 0x00, 0x08, 0x00, 0x02, 0x7C, 0x03, 0x00, 0x04, 0x7C, 0x01, 0x00, 0x20, 0x7C, 0x1A, 0x60, +- 0x22, 0xF9, 0x09, 0x00, 0x7C, 0x44, 0x1A, 0x60, 0x20, 0xFB, 0x1A, 0x60, 0x21, 0xFB, 0x1A, 0x60, +- 0x22, 0xFB, 0x1A, 0x60, 0x23, 0xFB, 0x7C, 0x44, 0x1A, 0x60, 0x20, 0xF1, 0xBD, 0xD9, 0x1A, 0x60, +- 0x21, 0xF1, 0xB0, 0x84, 0xBD, 0xD9, 0x1A, 0x60, 0x22, 0xF1, 0xB0, 0x84, 0xBD, 0xD9, 0x1A, 0x60, +- 0x1D, 0xF1, 0xB0, 0x84, 0xBD, 0xD9, 0x04, 0x03, 0x1C, 0x60, 0x08, 0xF1, 0xBD, 0xD9, 0x72, 0x00, +- 0x16, 0x60, 0xC2, 0xF3, 0xFF, 0xFF, 0xFF, 0xA0, 0xFF, 0xFF, 0x0C, 0x24, 0x6B, 0x00, 0x60, 0x40, +- 0x0B, 0x36, 0x68, 0x00, 0x20, 0x40, 0x10, 0x27, 0x65, 0x00, 0x91, 0x00, 0x20, 0xFE, 0x00, 0x65, +- 0x60, 0xFE, 0x1A, 0x60, 0x28, 0xFB, 0xE0, 0x84, 0xE0, 0x84, 0x08, 0x20, 0x03, 0x00, 0x01, 0x64, +- 0xA2, 0xDB, 0x02, 0x64, 0x02, 0xA5, 0x64, 0x44, 0xD4, 0x9C, 0xD4, 0x80, 0x34, 0x60, 0x52, 0x62, +- 0x02, 0x05, 0x08, 0x65, 0x4D, 0x00, 0xA2, 0xD9, 0x7C, 0x44, 0x34, 0x60, 0x54, 0x62, 0xA2, 0xDB, +- 0x20, 0xFE, 0x00, 0x64, 0x60, 0xFE, 0x1C, 0x60, 0x08, 0xF3, 0xFF, 0xFF, 0x00, 0xA0, 0x5D, 0xD0, +- 0x00, 0x65, 0x04, 0x03, 0x64, 0x40, 0x00, 0x3A, 0x01, 0x65, 0x03, 0x00, 0x64, 0x40, 0x00, 0x3A, +- 0x01, 0x65, 0x5D, 0xD0, 0x04, 0x03, 0x64, 0x40, 0x0F, 0x3A, 0x01, 0x65, 0x03, 0x00, 0x64, 0x40, +- 0x50, 0x3A, 0x01, 0x65, 0x5D, 0xD0, 0x04, 0x03, 0x64, 0x40, 0xAC, 0x3A, 0x01, 0x65, 0x03, 0x00, +- 0x64, 0x40, 0xF2, 0x3A, 0x01, 0x65, 0x5D, 0xD0, 0x65, 0x40, 0x00, 0x3A, 0x17, 0x00, 0x00, 0x60, +- 0x00, 0x65, 0x64, 0x40, 0x00, 0x36, 0x01, 0x65, 0x64, 0x40, 0x01, 0x36, 0x02, 0x65, 0x64, 0x40, +- 0x02, 0x36, 0x04, 0x65, 0x64, 0x40, 0x04, 0x36, 0x10, 0x65, 0x64, 0x40, 0x05, 0x36, 0x20, 0x65, +- 0x65, 0x5C, 0x1A, 0x60, 0x2A, 0xF3, 0xFF, 0xFF, 0xB0, 0x84, 0xA2, 0xDB, 0x1A, 0x60, 0x28, 0xF3, +- 0x00, 0x65, 0xFF, 0xA4, 0xA2, 0xDB, 0xBC, 0x02, 0x1A, 0x60, 0x2A, 0xF3, 0x1A, 0x60, 0x29, 0xF1, +- 0x2E, 0x58, 0xFF, 0xFF, 0x20, 0xFE, 0x88, 0xF3, 0xFF, 0xFF, 0x3C, 0xA4, 0x88, 0xFB, 0x87, 0xF3, +- 0x7D, 0xF1, 0x04, 0xA4, 0x87, 0xFB, 0x53, 0xF3, 0xFF, 0xFF, 0x60, 0x40, 0x80, 0x26, 0x0D, 0x00, +- 0x7D, 0xF3, 0x10, 0x60, 0xF2, 0x61, 0xCC, 0x84, 0xFF, 0xFF, 0x02, 0x03, 0x06, 0xA1, 0xFB, 0x01, +- 0xA1, 0xD3, 0xFF, 0xFF, 0x02, 0xBC, 0xA1, 0xDB, 0x12, 0x00, 0x7D, 0xF3, 0x11, 0x60, 0x60, 0x63, +- 0x01, 0x60, 0xFF, 0x65, 0xA4, 0x84, 0x12, 0x60, 0x40, 0x65, 0xA3, 0xD1, 0xD7, 0x80, 0xD0, 0x80, +- 0x06, 0x03, 0x02, 0x03, 0x08, 0xA3, 0xF9, 0x01, 0x02, 0xA3, 0x04, 0x64, 0xA3, 0xDB, 0x20, 0xFE, +- 0x26, 0x46, 0x31, 0x40, 0x20, 0x2A, 0x35, 0x00, 0x3F, 0xF2, 0x47, 0x65, 0xC4, 0x84, 0xE8, 0x84, +- 0x23, 0xFA, 0xF1, 0x60, 0x02, 0x64, 0x24, 0xFA, 0x7D, 0xF3, 0x01, 0x60, 0xFF, 0x65, 0xA4, 0x84, +- 0x01, 0x23, 0x14, 0x00, 0x11, 0x60, 0x60, 0x61, 0x12, 0x60, 0x40, 0x65, 0xA1, 0xD1, 0xD5, 0x80, +- 0xD0, 0x80, 0x0B, 0x03, 0x02, 0x03, 0x08, 0xA1, 0xF9, 0x01, 0x04, 0xA1, 0xA1, 0xD3, 0x01, 0x60, +- 0x00, 0x65, 0x60, 0x47, 0xFF, 0xB4, 0xB4, 0x84, 0x01, 0x00, 0x01, 0x64, 0x00, 0xF4, 0x08, 0xFA, +- 0xFF, 0xFF, 0x26, 0x46, 0x26, 0x60, 0x0A, 0x64, 0x13, 0x60, 0x0D, 0xFB, 0x26, 0x44, 0x5A, 0xDB, +- 0x02, 0x64, 0x5A, 0xDB, 0xFF, 0xFF, 0x2B, 0xFF, 0xFA, 0xFE, 0x00, 0x66, 0x46, 0x46, 0x2F, 0x58, +- 0xFF, 0xFF, 0x26, 0x46, 0x2F, 0x58, 0xFF, 0xFF, 0x78, 0xFB, 0xAC, 0x85, 0x60, 0x41, 0x55, 0x03, +- 0x32, 0x60, 0x00, 0x63, 0x1B, 0x60, 0x04, 0xFD, 0x62, 0x43, 0x1A, 0x60, 0xB4, 0xFD, 0x1A, 0x60, +- 0xBA, 0xFD, 0x1A, 0x60, 0xC4, 0xFD, 0x1A, 0x60, 0xCE, 0xFD, 0x00, 0x63, 0xE9, 0x81, 0x08, 0x64, +- 0x02, 0x24, 0xDF, 0x83, 0xFB, 0x02, 0x53, 0x94, 0x32, 0x7F, 0x03, 0x06, 0x1B, 0x60, 0x04, 0xFB, +- 0x08, 0x63, 0x63, 0x5E, 0x01, 0x7F, 0x19, 0x60, 0x8A, 0xFB, 0x65, 0x41, 0x33, 0x60, 0x16, 0x65, +- 0x0F, 0x60, 0xF4, 0x64, 0xE9, 0x81, 0x58, 0xD1, 0xFD, 0x04, 0xCF, 0x83, 0xA5, 0xD9, 0x0C, 0x03, +- 0xE9, 0x81, 0x58, 0xD1, 0xFD, 0x04, 0x40, 0x48, 0xA5, 0xD1, 0x64, 0x5F, 0x64, 0x5E, 0xA5, 0xDB, +- 0xDA, 0x85, 0xCF, 0x83, 0x28, 0x44, 0xEE, 0x02, 0x00, 0xB9, 0xD8, 0x83, 0x15, 0x03, 0x36, 0x60, +- 0x0A, 0x65, 0xE9, 0x81, 0xBD, 0xD1, 0x02, 0x05, 0xFC, 0x02, 0x17, 0x00, 0xA5, 0xD9, 0x15, 0x03, +- 0xE9, 0x81, 0xBD, 0xD1, 0x02, 0x05, 0xFC, 0x02, 0x10, 0x00, 0xA5, 0xD3, 0xFF, 0xFF, 0x64, 0x5F, +- 0xA5, 0xDB, 0xDA, 0x85, 0xEE, 0x02, 0x09, 0x00, 0x67, 0x43, 0x1A, 0x60, 0xB4, 0xFD, 0x1A, 0x60, +- 0xBA, 0xFD, 0x1A, 0x60, 0xC4, 0xFD, 0x1A, 0x60, 0xCE, 0xFD, 0x2E, 0x45, 0x25, 0x60, 0x46, 0x64, +- 0xD4, 0x80, 0xFF, 0xFF, 0x10, 0x03, 0x20, 0x40, 0x10, 0x27, 0x0D, 0x00, 0x33, 0x60, 0x1E, 0x61, +- 0x19, 0x60, 0x8A, 0xF3, 0xA1, 0xDB, 0xFF, 0xB4, 0xCC, 0x84, 0xA8, 0x83, 0x33, 0x60, 0x14, 0x64, +- 0x58, 0xD1, 0x59, 0xD9, 0xFD, 0x1F, 0x7D, 0xF3, 0x33, 0x60, 0x20, 0x63, 0x60, 0x40, 0x01, 0x27, +- 0x03, 0x00, 0x19, 0x60, 0x3B, 0xF3, 0x02, 0x00, 0x19, 0x60, 0x3C, 0xF3, 0x08, 0x61, 0x60, 0xFE, +- 0xA3, 0xD1, 0xFF, 0xFF, 0x20, 0xFE, 0x00, 0xA8, 0xE8, 0x84, 0x0F, 0x03, 0x60, 0xFE, 0x02, 0x28, +- 0xF6, 0x01, 0x80, 0x62, 0xB2, 0x9C, 0xBD, 0xD9, 0x7B, 0xF9, 0xCD, 0x81, 0x00, 0x36, 0x01, 0x00, +- 0xEE, 0x01, 0x36, 0x60, 0x0A, 0x63, 0x08, 0x61, 0xEA, 0x01, 0x2E, 0x58, 0xFF, 0xFF, 0x32, 0x60, +- 0x76, 0x63, 0x65, 0x40, 0xFF, 0x36, 0x02, 0xA3, 0xA3, 0xD3, 0xFF, 0xFF, 0xE8, 0x84, 0xE8, 0x84, +- 0xE8, 0x84, 0xE8, 0x84, 0x40, 0x26, 0x7F, 0xB4, 0x20, 0x26, 0x3F, 0xB4, 0x60, 0x45, 0x80, 0x63, +- 0xFD, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x7D, 0xFB, 0x40, 0x63, 0xFD, 0x60, +- 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x7E, 0xFB, 0x20, 0x63, 0xFD, 0x60, 0x58, 0x4D, +- 0x34, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x7F, 0xFB, 0x10, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x34, 0x78, +- 0xFF, 0xFF, 0x19, 0x60, 0x80, 0xFB, 0x08, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, +- 0x19, 0x60, 0x81, 0xFB, 0x04, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x19, 0x60, +- 0x82, 0xFB, 0x02, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x83, 0xFB, +- 0x01, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x34, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x84, 0xFB, 0x2E, 0x58, +- 0xFF, 0xFF, 0x19, 0x60, 0x3B, 0xF3, 0xFF, 0xFF, 0x0F, 0xB4, 0x60, 0x45, 0x08, 0x63, 0xFD, 0x60, +- 0x58, 0x4D, 0x5F, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x85, 0xFB, 0x04, 0x63, 0xFD, 0x60, 0x58, 0x4D, +- 0x5F, 0x78, 0xFF, 0xFF, 0x19, 0x60, 0x86, 0xFB, 0x02, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x5F, 0x78, +- 0xFF, 0xFF, 0x19, 0x60, 0x87, 0xFB, 0x01, 0x63, 0xFD, 0x60, 0x58, 0x4D, 0x5F, 0x78, 0xFF, 0xFF, +- 0x19, 0x60, 0x88, 0xFB, 0x2E, 0x58, 0xFF, 0xFF, 0x63, 0x5C, 0xA7, 0x84, 0xEB, 0x83, 0x14, 0x02, +- 0x01, 0x03, 0xFB, 0x01, 0x64, 0x44, 0x01, 0x36, 0x0B, 0x64, 0x02, 0x36, 0x0B, 0x64, 0x04, 0x36, +- 0x0A, 0x64, 0x08, 0x36, 0x0A, 0x64, 0x10, 0x36, 0x09, 0x64, 0x20, 0x36, 0x09, 0x64, 0x40, 0x36, +- 0x09, 0x64, 0x80, 0x36, 0x09, 0x64, 0x11, 0x00, 0x60, 0x40, 0x01, 0x36, 0x0B, 0x64, 0x02, 0x36, +- 0x0F, 0x64, 0x04, 0x36, 0x0A, 0x64, 0x08, 0x36, 0x0E, 0x64, 0x10, 0x36, 0x09, 0x64, 0x20, 0x36, +- 0x0D, 0x64, 0x40, 0x36, 0x08, 0x64, 0x80, 0x36, 0x0C, 0x64, 0x2D, 0x58, 0xFF, 0xFF, 0x63, 0x5C, +- 0xA7, 0x84, 0xEB, 0x83, 0x0C, 0x02, 0x01, 0x03, 0xFB, 0x01, 0x64, 0x44, 0x01, 0x36, 0x0A, 0x64, +- 0x02, 0x36, 0x14, 0x64, 0x04, 0x36, 0x37, 0x64, 0x08, 0x36, 0x6E, 0x64, 0x09, 0x00, 0x60, 0x40, +- 0x01, 0x36, 0x0A, 0x64, 0x02, 0x36, 0x14, 0x64, 0x04, 0x36, 0x37, 0x64, 0x08, 0x36, 0x6E, 0x64, +- 0x2D, 0x58, 0xFF, 0xFF, 0x60, 0xFE, 0x81, 0xA1, 0x7F, 0xA1, 0x02, 0x06, 0x00, 0xF4, 0x03, 0x61, +- 0x5D, 0xD2, 0xCF, 0x83, 0xD4, 0x80, 0x25, 0x03, 0x16, 0x03, 0xCF, 0x83, 0x61, 0x44, 0x80, 0xA0, +- 0x20, 0x03, 0x02, 0x02, 0x00, 0xF4, 0x03, 0x61, 0x5D, 0xD2, 0xCF, 0x83, 0x81, 0xA1, 0x19, 0x03, +- 0x05, 0x07, 0x7F, 0xA1, 0xCC, 0x84, 0xDD, 0x81, 0xE6, 0x03, 0xF7, 0x01, 0x00, 0xF4, 0x00, 0xB8, +- 0x04, 0x61, 0xE6, 0x03, 0xF2, 0x01, 0x2C, 0x43, 0x5D, 0xD0, 0xDE, 0xD9, 0x64, 0x44, 0x5D, 0xD0, +- 0xDE, 0xD9, 0xCC, 0x84, 0x81, 0xA1, 0x05, 0x03, 0x7F, 0xA1, 0xF9, 0x04, 0x00, 0xF4, 0x03, 0x61, +- 0xF6, 0x01, 0x20, 0xFE, 0x2E, 0x58, 0xFF, 0xFF, 0x01, 0x3A, 0x02, 0x00, 0x16, 0x64, 0x2B, 0x00, +- 0x02, 0x3A, 0x02, 0x00, 0x14, 0x64, 0x27, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x12, 0x64, 0x23, 0x00, +- 0x08, 0x3A, 0x02, 0x00, 0x10, 0x64, 0x1F, 0x00, 0x10, 0x3A, 0x02, 0x00, 0x0E, 0x64, 0x1B, 0x00, +- 0x20, 0x3A, 0x02, 0x00, 0x0C, 0x64, 0x17, 0x00, 0x40, 0x3A, 0x02, 0x00, 0x0A, 0x64, 0x13, 0x00, +- 0x80, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x0F, 0x00, 0x01, 0x3B, 0x02, 0x00, 0x06, 0x64, 0x0B, 0x00, +- 0x02, 0x3B, 0x02, 0x00, 0x04, 0x64, 0x07, 0x00, 0x04, 0x3B, 0x02, 0x00, 0x02, 0x64, 0x03, 0x00, +- 0x08, 0x3B, 0xFF, 0x01, 0x00, 0x64, 0x2E, 0x58, 0xFF, 0xFF, 0x27, 0xF2, 0xFF, 0xFF, 0x60, 0x40, +- 0x36, 0x3A, 0x02, 0x00, 0x00, 0x61, 0x30, 0x00, 0x30, 0x3A, 0x02, 0x00, 0x02, 0x61, 0x2C, 0x00, +- 0x24, 0x3A, 0x02, 0x00, 0x04, 0x61, 0x28, 0x00, 0x18, 0x3A, 0x02, 0x00, 0x06, 0x61, 0x24, 0x00, +- 0x12, 0x3A, 0x02, 0x00, 0x08, 0x61, 0x20, 0x00, 0x0C, 0x3A, 0x02, 0x00, 0x0A, 0x61, 0x1C, 0x00, +- 0x09, 0x3A, 0x02, 0x00, 0x0C, 0x61, 0x18, 0x00, 0x06, 0x3A, 0x02, 0x00, 0x0E, 0x61, 0x14, 0x00, +- 0x6E, 0x3A, 0x02, 0x00, 0x10, 0x61, 0x10, 0x00, 0x37, 0x3A, 0x02, 0x00, 0x12, 0x61, 0x0C, 0x00, +- 0x14, 0x3A, 0x02, 0x00, 0x14, 0x61, 0x08, 0x00, 0x0A, 0x3A, 0x02, 0x00, 0x16, 0x61, 0x04, 0x00, +- 0x78, 0x43, 0x03, 0x61, 0x29, 0x60, 0xEA, 0x78, 0x65, 0x40, 0x01, 0x3A, 0x13, 0x00, 0x66, 0x45, +- 0x2B, 0x46, 0x92, 0xFA, 0x65, 0x46, 0x26, 0xF2, 0xFF, 0xFF, 0x60, 0x41, 0x00, 0x7F, 0x60, 0x45, +- 0x61, 0x47, 0x00, 0x7F, 0xD4, 0x84, 0x66, 0x41, 0x2B, 0x46, 0x0E, 0xF2, 0x60, 0x45, 0x65, 0x5E, +- 0x0E, 0xFA, 0x61, 0x46, 0x2E, 0x58, 0xFF, 0xFF, 0xCD, 0x81, 0x7F, 0xB4, 0x02, 0x3A, 0x02, 0x00, +- 0x01, 0x64, 0x32, 0x00, 0x04, 0x3A, 0x02, 0x00, 0x02, 0x64, 0x2E, 0x00, 0x0B, 0x3A, 0x02, 0x00, +- 0x04, 0x64, 0x2A, 0x00, 0x16, 0x3A, 0x02, 0x00, 0x08, 0x64, 0x26, 0x00, 0x0C, 0x3A, 0x02, 0x00, +- 0x10, 0x64, 0x22, 0x00, 0x12, 0x3A, 0x02, 0x00, 0x20, 0x64, 0x1E, 0x00, 0x18, 0x3A, 0x02, 0x00, +- 0x40, 0x64, 0x1A, 0x00, 0x24, 0x3A, 0x02, 0x00, 0x80, 0x64, 0x16, 0x00, 0x30, 0x3A, 0x03, 0x00, +- 0x00, 0x7E, 0x01, 0x7F, 0x11, 0x00, 0x48, 0x3A, 0x03, 0x00, 0x00, 0x7E, 0x02, 0x7F, 0x0C, 0x00, +- 0x60, 0x3A, 0x03, 0x00, 0x00, 0x7E, 0x04, 0x7F, 0x07, 0x00, 0x6C, 0x3A, 0x03, 0x00, 0x00, 0x7E, +- 0x08, 0x7F, 0x02, 0x00, 0x00, 0x64, 0x00, 0x00, 0x20, 0xFE, 0x2A, 0x45, 0x34, 0x8A, 0x60, 0xFE, +- 0x61, 0x40, 0x00, 0x36, 0x02, 0x00, 0xBD, 0xD3, 0xBF, 0x01, 0x2E, 0x58, 0xFF, 0xFF, +- +-}; /* fw_image_4_data */ +- +-static const CFG_IDENTITY_STRCT fw_image_infoidentity[] = { +- { +- sizeof( CFG_IDENTITY_STRCT ) / sizeof(hcf_16) - 1, +- CFG_FW_IDENTITY, +- COMP_ID_FW_STA, +- 4, //Variant +- 1, //Major +- 36 //Minor +- }, +- { 0000, 0000, 0000, 0000, 0000, 0000 } //endsentinel +-}; +- +-static const CFG_PROG_STRCT fw_image_code[] = { +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, // mode +- 0x0184, // sizeof(fw_image_1_data), +- 0x00000060, // Target address in NIC Memory +- 0x0000, // CRC: yes/no TYPE: primary/station/tertiary +- (hcf_8 FAR *) fw_image_1_data +- }, +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, // mode +- 0x2c0e, // sizeof(fw_image_2_data), +- 0x00000C16, // Target address in NIC Memory +- 0x0000, // CRC: yes/no TYPE: primary/station/tertiary +- (hcf_8 FAR *) fw_image_2_data +- }, +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, // mode +- 0x54de, // sizeof(fw_image_3_data), +- 0x001E3824, // Target address in NIC Memory +- 0x0000, // CRC: yes/no TYPE: primary/station/tertiary +- (hcf_8 FAR *) fw_image_3_data +- }, +- { +- 8, +- CFG_PROG, +- CFG_PROG_VOLATILE, // mode +- 0xbcde, // sizeof(fw_image_4_data), +- 0x001F4000, // Target address in NIC Memory +- 0x0000, // CRC: yes/no TYPE: primary/station/tertiary +- (hcf_8 FAR *) fw_image_4_data +- }, +- { +- 5, +- CFG_PROG, +- CFG_PROG_STOP, // mode +- 0000, +- 0x000F429B, // Start execution address +- }, +- { 0000, 0000, 0000, 0000, 00000000, 0000, 00000000} +-}; +- +-static const CFG_RANGE20_STRCT fw_image_infocompat[] = { +- { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), +- CFG_FW_SUP_RANGE, +- COMP_ROLE_SUPL, +- COMP_ID_STA, +- { +- { 4, 1, 2 } //variant, bottom, top +- } +- }, +- { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), +- CFG_MFI_ACT_RANGES_STA, +- COMP_ROLE_ACT, +- COMP_ID_MFI, +- { +- { 7, 3, 3 }, //variant, bottom, top +- { 8, 1, 1 } //variant, bottom, top +- } +- }, +- { 3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)), +- CFG_CFI_ACT_RANGES_STA, +- COMP_ROLE_ACT, +- COMP_ID_CFI, +- { +- { 4, 1, 2 } //variant, bottom, top +- } +- }, +- { 0000, 0000, 0000, 0000, { { 0000, 0000, 0000 } } } //endsentinel +-}; +- +-memimage fw_image = { +- "FUPU7D37dhfwci\001C", //signature, , C/Bin type +- (CFG_PROG_STRCT *) fw_image_code, +- 0x000F429B, +- 00000000, //(dummy) pdaplug +- 00000000, //(dummy) priplug +- (CFG_RANGE20_STRCT *) fw_image_infocompat, +- (CFG_IDENTITY_STRCT *) fw_image_infoidentity, +-}; +- +diff --git a/drivers/staging/wlags49_h25/Kconfig b/drivers/staging/wlags49_h25/Kconfig +index bf5664a..82b2b07 100644 +--- a/drivers/staging/wlags49_h25/Kconfig ++++ b/drivers/staging/wlags49_h25/Kconfig +@@ -1,6 +1,7 @@ + config WLAGS49_H25 + tristate "Linksys HERMES II.5 WCF54G_Wireless-G_CompactFlash_Card" + depends on WLAN && PCMCIA ++ depends on BROKEN + select WIRELESS_EXT + select WEXT_SPY + select WEXT_PRIV +diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c +index c9bf779..419ad55 100644 +--- a/drivers/tty/cyclades.c ++++ b/drivers/tty/cyclades.c +@@ -3543,10 +3543,8 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, + int retval; + + retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev); +- if (retval) { +- dev_err(&pdev->dev, "can't get firmware\n"); ++ if (retval) + goto err; +- } + + /* Check whether the firmware is already loaded and running. If + positive, skip this board */ +diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c +index fc3c3ad..4cc036f 100644 +--- a/drivers/tty/hvc/hvc_vio.c ++++ b/drivers/tty/hvc/hvc_vio.c +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + + #include "hvc_console.h" + +@@ -447,7 +448,9 @@ void __init hvc_vio_init_early(void) + if (hvterm_priv0.proto == HV_PROTOCOL_HVSI) + goto out; + #endif +- add_preferred_console("hvc", 0, NULL); ++ /* Check whether the user has requested a different console. */ ++ if (!strstr(cmd_line, "console=")) ++ add_preferred_console("hvc", 0, NULL); + hvc_instantiate(0, 0, ops); + out: + of_node_put(stdout_node); +diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c +index 0174d2d..95d39bd 100644 +--- a/drivers/tty/moxa.c ++++ b/drivers/tty/moxa.c +@@ -867,13 +867,8 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) + } + + ret = request_firmware(&fw, file, dev); +- if (ret) { +- printk(KERN_ERR "MOXA: request_firmware failed. Make sure " +- "you've placed '%s' file into your firmware " +- "loader directory (e.g. /lib/firmware)\n", +- file); ++ if (ret) + goto err_free; +- } + + ret = moxa_load_fw(brd, fw); + +diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c +index d55709a..0ee5294 100644 +--- a/drivers/tty/serial/icom.c ++++ b/drivers/tty/serial/icom.c +@@ -374,7 +374,6 @@ static void load_code(struct icom_port *icom_port) + + /* Load Call Setup into Adapter */ + if (request_firmware(&fw, "icom_call_setup.bin", &dev->dev) < 0) { +- dev_err(&dev->dev,"Unable to load icom_call_setup.bin firmware image\n"); + status = -1; + goto load_code_exit; + } +@@ -394,7 +393,6 @@ static void load_code(struct icom_port *icom_port) + + /* Load Resident DCE portion of Adapter */ + if (request_firmware(&fw, "icom_res_dce.bin", &dev->dev) < 0) { +- dev_err(&dev->dev,"Unable to load icom_res_dce.bin firmware image\n"); + status = -1; + goto load_code_exit; + } +@@ -439,7 +437,6 @@ static void load_code(struct icom_port *icom_port) + } + + if (request_firmware(&fw, "icom_asc.bin", &dev->dev) < 0) { +- dev_err(&dev->dev,"Unable to load icom_asc.bin firmware image\n"); + status = -1; + goto load_code_exit; + } +diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c +index cea8918..97eab95 100644 +--- a/drivers/tty/serial/ucc_uart.c ++++ b/drivers/tty/serial/ucc_uart.c +@@ -1173,10 +1173,8 @@ static void uart_firmware_cont(const struct firmware *fw, void *context) + struct device *dev = context; + int ret; + +- if (!fw) { +- dev_err(dev, "firmware not found\n"); ++ if (!fw) + return; +- } + + firmware = (struct qe_firmware *) fw->data; + +diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c +index 9497171..07458c0 100644 +--- a/drivers/usb/atm/cxacru.c ++++ b/drivers/usb/atm/cxacru.c +@@ -1082,8 +1082,6 @@ static int cxacru_find_firmware(struct cxacru_data *instance, + return -ENOENT; + } + +- usb_info(usbatm, "found firmware %s\n", buf); +- + return 0; + } + +diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c +index 428f368..ee1d5a5 100644 +--- a/drivers/usb/atm/ueagle-atm.c ++++ b/drivers/usb/atm/ueagle-atm.c +@@ -622,10 +622,8 @@ static void uea_upload_pre_firmware(const struct firmware *fw_entry, + int ret, size; + + uea_enters(usb); +- if (!fw_entry) { +- uea_err(usb, "firmware is not available\n"); ++ if (!fw_entry) + goto err; +- } + + pfw = fw_entry->data; + size = fw_entry->size; +@@ -720,10 +718,6 @@ static int uea_load_firmware(struct usb_device *usb, unsigned int ver) + ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, + GFP_KERNEL, usb, + uea_upload_pre_firmware); +- if (ret) +- uea_err(usb, "firmware %s is not available\n", fw_name); +- else +- uea_info(usb, "loading firmware %s\n", fw_name); + + uea_leaves(usb); + return ret; +@@ -885,12 +879,8 @@ static int request_dsp(struct uea_softc *sc) + } + + ret = request_firmware(&sc->dsp_firm, dsp_name, &sc->usb_dev->dev); +- if (ret < 0) { +- uea_err(INS_TO_USBDEV(sc), +- "requesting firmware %s failed with error %d\n", +- dsp_name, ret); ++ if (ret) + return ret; +- } + + if (UEA_CHIP_VERSION(sc) == EAGLE_IV) + ret = check_dsp_e4(sc->dsp_firm->data, sc->dsp_firm->size); +@@ -1607,12 +1597,8 @@ static int request_cmvs_old(struct uea_softc *sc, + + cmvs_file_name(sc, cmv_name, 1); + ret = request_firmware(fw, cmv_name, &sc->usb_dev->dev); +- if (ret < 0) { +- uea_err(INS_TO_USBDEV(sc), +- "requesting firmware %s failed with error %d\n", +- cmv_name, ret); ++ if (ret) + return ret; +- } + + data = (u8 *) (*fw)->data; + size = (*fw)->size; +@@ -1649,9 +1635,6 @@ static int request_cmvs(struct uea_softc *sc, + "try to get older cmvs\n", cmv_name); + return request_cmvs_old(sc, cmvs, fw); + } +- uea_err(INS_TO_USBDEV(sc), +- "requesting firmware %s failed with error %d\n", +- cmv_name, ret); + return ret; + } + +@@ -1934,11 +1917,8 @@ static int load_XILINX_firmware(struct uea_softc *sc) + uea_enters(INS_TO_USBDEV(sc)); + + ret = request_firmware(&fw_entry, fw_name, &sc->usb_dev->dev); +- if (ret) { +- uea_err(INS_TO_USBDEV(sc), "firmware %s is not available\n", +- fw_name); ++ if (ret) + goto err0; +- } + + pfw = fw_entry->data; + size = fw_entry->size; +diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c +index 2abdad6..b7cec73 100644 +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -200,11 +200,9 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, + /* check TDI/ARC silicon is in host mode */ + static int tdi_in_host_mode (struct ehci_hcd *ehci) + { +- u32 __iomem *reg_ptr; + u32 tmp; + +- reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE); +- tmp = ehci_readl(ehci, reg_ptr); ++ tmp = ehci_readl(ehci, &ehci->regs->usbmode); + return (tmp & 3) == USBMODE_CM_HC; + } + +@@ -249,11 +247,9 @@ static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr, + /* put TDI/ARC silicon into EHCI mode */ + static void tdi_reset (struct ehci_hcd *ehci) + { +- u32 __iomem *reg_ptr; + u32 tmp; + +- reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE); +- tmp = ehci_readl(ehci, reg_ptr); ++ tmp = ehci_readl(ehci, &ehci->regs->usbmode); + tmp |= USBMODE_CM_HC; + /* The default byte access to MMR space is LE after + * controller reset. Set the required endian mode +@@ -261,7 +257,7 @@ static void tdi_reset (struct ehci_hcd *ehci) + */ + if (ehci_big_endian_mmio(ehci)) + tmp |= USBMODE_BE; +- ehci_writel(ehci, tmp, reg_ptr); ++ ehci_writel(ehci, tmp, &ehci->regs->usbmode); + } + + /* reset a non-running (STS_HALT == 1) controller */ +@@ -285,9 +281,8 @@ static int ehci_reset (struct ehci_hcd *ehci) + + if (ehci->has_hostpc) { + ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS, +- (u32 __iomem *)(((u8 *)ehci->regs) + USBMODE_EX)); +- ehci_writel(ehci, TXFIFO_DEFAULT, +- (u32 __iomem *)(((u8 *)ehci->regs) + TXFILLTUNING)); ++ &ehci->regs->usbmode_ex); ++ ehci_writel(ehci, TXFIFO_DEFAULT, &ehci->regs->txfill_tuning); + } + if (retval) + return retval; +@@ -1344,6 +1339,11 @@ MODULE_LICENSE ("GPL"); + #define PLATFORM_DRIVER ehci_xls_driver + #endif + ++#ifdef CONFIG_USB_EHCI_BCM ++#include "../../bcmdrivers/usb2h/ehci-bcm.c" ++#define PLATFORM_DRIVER ehci_bcm_driver ++#endif ++ + #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ + !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ + !defined(XILINX_OF_PLATFORM_DRIVER) +diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c +index 4527b90..d304f9d 100644 +--- a/drivers/usb/host/ehci-hub.c ++++ b/drivers/usb/host/ehci-hub.c +@@ -149,10 +149,8 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, + if (ehci->has_hostpc) { + port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { +- u32 __iomem *hostpc_reg; ++ u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; + +- hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs +- + HOSTPC0 + 4 * port); + temp = ehci_readl(ehci, hostpc_reg); + ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg); + } +@@ -185,10 +183,8 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, + if (ehci->has_hostpc) { + port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { +- u32 __iomem *hostpc_reg; ++ u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; + +- hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs +- + HOSTPC0 + 4 * port); + temp = ehci_readl(ehci, hostpc_reg); + ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); + } +@@ -311,11 +307,9 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) + spin_lock_irq(&ehci->lock); + port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { +- u32 __iomem *hostpc_reg; ++ u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; + u32 t3; + +- hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs +- + HOSTPC0 + 4 * port); + t3 = ehci_readl(ehci, hostpc_reg); + ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg); + t3 = ehci_readl(ehci, hostpc_reg); +@@ -413,10 +407,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd) + i = HCS_N_PORTS(ehci->hcs_params); + while (i--) { + if (test_bit(i, &ehci->bus_suspended)) { +- u32 __iomem *hostpc_reg; ++ u32 __iomem *hostpc_reg = ++ &ehci->regs->hostpc[i]; + +- hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs +- + HOSTPC0 + 4 * i); + temp = ehci_readl(ehci, hostpc_reg); + ehci_writel(ehci, temp & ~HOSTPC_PHCD, + hostpc_reg); +@@ -690,7 +683,7 @@ static int ehci_hub_control ( + int ports = HCS_N_PORTS (ehci->hcs_params); + u32 __iomem *status_reg = &ehci->regs->port_status[ + (wIndex & 0xff) - 1]; +- u32 __iomem *hostpc_reg = NULL; ++ u32 __iomem *hostpc_reg = &ehci->regs->hostpc[(wIndex & 0xff) - 1]; + u32 temp, temp1, status; + unsigned long flags; + int retval = 0; +@@ -703,9 +696,6 @@ static int ehci_hub_control ( + * power, "this is the one", etc. EHCI spec supports this. + */ + +- if (ehci->has_hostpc) +- hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs +- + HOSTPC0 + 4 * ((wIndex & 0xff) - 1)); + spin_lock_irqsave (&ehci->lock, flags); + switch (typeReq) { + case ClearHubFeature: +@@ -757,7 +747,7 @@ static int ehci_hub_control ( + goto error; + + /* clear phy low-power mode before resume */ +- if (hostpc_reg) { ++ if (ehci->has_hostpc) { + temp1 = ehci_readl(ehci, hostpc_reg); + ehci_writel(ehci, temp1 & ~HOSTPC_PHCD, + hostpc_reg); +@@ -1005,7 +995,7 @@ static int ehci_hub_control ( + temp &= ~PORT_WKCONN_E; + temp |= PORT_WKDISC_E | PORT_WKOC_E; + ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); +- if (hostpc_reg) { ++ if (ehci->has_hostpc) { + spin_unlock_irqrestore(&ehci->lock, flags); + msleep(5);/* 5ms for HCD enter low pwr mode */ + spin_lock_irqsave(&ehci->lock, flags); +diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c +index b263919..e4dfafa 100644 +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -1116,6 +1116,12 @@ MODULE_LICENSE ("GPL"); + #define PLATFORM_DRIVER ohci_xls_driver + #endif + ++#ifdef CONFIG_USB_OHCI_BCM ++#include "../../bcmdrivers/usb2h/ohci-bcm.c" ++#define PLATFORM_DRIVER ohci_bcm_driver ++#endif ++ ++ + #if !defined(PCI_DRIVER) && \ + !defined(PLATFORM_DRIVER) && \ + !defined(OMAP1_PLATFORM_DRIVER) && \ +diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c +index a6521c9..9da3f48 100644 +--- a/drivers/usb/misc/emi26.c ++++ b/drivers/usb/misc/emi26.c +@@ -96,21 +96,17 @@ static int emi26_load_firmware (struct usb_device *dev) + + err = request_ihex_firmware(&loader_fw, "emi26/loader.fw", &dev->dev); + if (err) +- goto nofw; ++ goto wraperr; + + err = request_ihex_firmware(&bitstream_fw, "emi26/bitstream.fw", + &dev->dev); + if (err) +- goto nofw; ++ goto wraperr; + + err = request_ihex_firmware(&firmware_fw, "emi26/firmware.fw", + &dev->dev); +- if (err) { +- nofw: +- dev_err(&dev->dev, "%s - request_firmware() failed\n", +- __func__); ++ if (err) + goto wraperr; +- } + + /* Assert reset (stop the CPU in the EMI) */ + err = emi26_set_reset(dev,1); +diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c +index 723e833..1941439 100644 +--- a/drivers/usb/misc/emi62.c ++++ b/drivers/usb/misc/emi62.c +@@ -105,19 +105,16 @@ static int emi62_load_firmware (struct usb_device *dev) + + err = request_ihex_firmware(&loader_fw, "emi62/loader.fw", &dev->dev); + if (err) +- goto nofw; ++ goto wraperr; + + err = request_ihex_firmware(&bitstream_fw, "emi62/bitstream.fw", + &dev->dev); + if (err) +- goto nofw; ++ goto wraperr; + + err = request_ihex_firmware(&firmware_fw, FIRMWARE_FW, &dev->dev); +- if (err) { +- nofw: +- err( "%s - request_firmware() failed", __func__); ++ if (err) + goto wraperr; +- } + + /* Assert reset (stop the CPU in the EMI) */ + err = emi62_set_reset(dev,1); +diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c +index 8f725f6..334744f 100644 +--- a/drivers/usb/misc/isight_firmware.c ++++ b/drivers/usb/misc/isight_firmware.c +@@ -48,7 +48,6 @@ static int isight_firmware_load(struct usb_interface *intf, + return -ENOMEM; + + if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) { +- printk(KERN_ERR "Unable to load isight firmware\n"); + ret = -ENODEV; + goto out; + } +diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c +index 0af0b41..84788af 100644 +--- a/drivers/usb/serial/io_edgeport.c ++++ b/drivers/usb/serial/io_edgeport.c +@@ -308,11 +308,8 @@ static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial) + + response = request_ihex_firmware(&fw, fw_name, + &edge_serial->serial->dev->dev); +- if (response) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fw_name, response); ++ if (response) + return; +- } + + rec = (const struct ihex_binrec *)fw->data; + BootMajorVersion = rec->data[0]; +diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c +index 438138f..f05abe8 100644 +--- a/drivers/usb/serial/io_ti.c ++++ b/drivers/usb/serial/io_ti.c +@@ -886,8 +886,6 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev) + + err = request_firmware(&fw, fw_name, dev); + if (err) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fw_name, err); + kfree(buffer); + return err; + } +@@ -1452,8 +1450,6 @@ static int download_fw(struct edgeport_serial *serial) + + err = request_firmware(&fw, fw_name, dev); + if (err) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fw_name, err); + kfree(buffer); + return err; + } +diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c +index e9b39e3..472fddb 100644 +--- a/drivers/usb/serial/keyspan.c ++++ b/drivers/usb/serial/keyspan.c +@@ -1419,10 +1419,8 @@ static int keyspan_fake_startup(struct usb_serial *serial) + return 1; + } + +- if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) { +- dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name); ++ if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) + return(1); +- } + + dbg("Uploading Keyspan %s firmware.", fw_name); + +diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c +index 661a1a2..91091b0 100644 +--- a/drivers/usb/serial/keyspan_pda.c ++++ b/drivers/usb/serial/keyspan_pda.c +@@ -768,11 +768,8 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) + __func__); + return -ENODEV; + } +- if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) { +- dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n", +- fw_name); ++ if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) + return -ENOENT; +- } + record = (const struct ihex_binrec *)fw->data; + + while (record) { +diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c +index 885d15d..7a27c18 100644 +--- a/drivers/usb/serial/ti_usb_3410_5052.c ++++ b/drivers/usb/serial/ti_usb_3410_5052.c +@@ -1747,10 +1747,8 @@ static int ti_download_firmware(struct ti_device *tdev) + } + status = request_firmware(&fw_p, buf, &dev->dev); + } +- if (status) { +- dev_err(&dev->dev, "%s - firmware not found\n", __func__); ++ if (status) + return -ENOENT; +- } + if (fw_p->size > TI_FIRMWARE_BUF_SIZE) { + dev_err(&dev->dev, "%s - firmware too large %zu\n", __func__, fw_p->size); + release_firmware(fw_p); +diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c +index 5481809..2c9a1a4 100644 +--- a/drivers/usb/serial/whiteheat.c ++++ b/drivers/usb/serial/whiteheat.c +@@ -301,18 +301,11 @@ static int whiteheat_firmware_download(struct usb_serial *serial, + dbg("%s", __func__); + + if (request_ihex_firmware(&firmware_fw, "whiteheat.fw", +- &serial->dev->dev)) { +- dev_err(&serial->dev->dev, +- "%s - request \"whiteheat.fw\" failed\n", __func__); ++ &serial->dev->dev)) + goto out; +- } + if (request_ihex_firmware(&loader_fw, "whiteheat_loader.fw", +- &serial->dev->dev)) { +- dev_err(&serial->dev->dev, +- "%s - request \"whiteheat_loader.fw\" failed\n", +- __func__); ++ &serial->dev->dev)) + goto out; +- } + ret = 0; + response = ezusb_set_reset (serial, 1); + +diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig +index d83e967..fe92039 100644 +--- a/drivers/video/Kconfig ++++ b/drivers/video/Kconfig +@@ -1028,101 +1028,6 @@ config FB_ATMEL_STN + + If unsure, say N. + +-config FB_NVIDIA +- tristate "nVidia Framebuffer Support" +- depends on FB && PCI +- select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT +- select FB_MODE_HELPERS +- select FB_CFB_FILLRECT +- select FB_CFB_COPYAREA +- select FB_CFB_IMAGEBLIT +- select BITREVERSE +- select VGASTATE +- help +- This driver supports graphics boards with the nVidia chips, TNT +- and newer. For very old chipsets, such as the RIVA128, then use +- the rivafb. +- Say Y if you have such a graphics board. +- +- To compile this driver as a module, choose M here: the +- module will be called nvidiafb. +- +-config FB_NVIDIA_I2C +- bool "Enable DDC Support" +- depends on FB_NVIDIA +- select FB_DDC +- help +- This enables I2C support for nVidia Chipsets. This is used +- only for getting EDID information from the attached display +- allowing for robust video mode handling and switching. +- +- Because fbdev-2.6 requires that drivers must be able to +- independently validate video mode parameters, you should say Y +- here. +- +-config FB_NVIDIA_DEBUG +- bool "Lots of debug output" +- depends on FB_NVIDIA +- default n +- help +- Say Y here if you want the nVidia driver to output all sorts +- of debugging information to provide to the maintainer when +- something goes wrong. +- +-config FB_NVIDIA_BACKLIGHT +- bool "Support for backlight control" +- depends on FB_NVIDIA +- default y +- help +- Say Y here if you want to control the backlight of your display. +- +-config FB_RIVA +- tristate "nVidia Riva support" +- depends on FB && PCI +- select FB_BACKLIGHT if FB_RIVA_BACKLIGHT +- select FB_MODE_HELPERS +- select FB_CFB_FILLRECT +- select FB_CFB_COPYAREA +- select FB_CFB_IMAGEBLIT +- select BITREVERSE +- select VGASTATE +- help +- This driver supports graphics boards with the nVidia Riva/Geforce +- chips. +- Say Y if you have such a graphics board. +- +- To compile this driver as a module, choose M here: the +- module will be called rivafb. +- +-config FB_RIVA_I2C +- bool "Enable DDC Support" +- depends on FB_RIVA +- select FB_DDC +- help +- This enables I2C support for nVidia Chipsets. This is used +- only for getting EDID information from the attached display +- allowing for robust video mode handling and switching. +- +- Because fbdev-2.6 requires that drivers must be able to +- independently validate video mode parameters, you should say Y +- here. +- +-config FB_RIVA_DEBUG +- bool "Lots of debug output" +- depends on FB_RIVA +- default n +- help +- Say Y here if you want the Riva driver to output all sorts +- of debugging information to provide to the maintainer when +- something goes wrong. +- +-config FB_RIVA_BACKLIGHT +- bool "Support for backlight control" +- depends on FB_RIVA +- default y +- help +- Say Y here if you want to control the backlight of your display. +- + config FB_I810 + tristate "Intel 810/815 support (EXPERIMENTAL)" + depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL +diff --git a/drivers/video/Makefile b/drivers/video/Makefile +index 9b9d8ff..4361446 100644 +--- a/drivers/video/Makefile ++++ b/drivers/video/Makefile +@@ -38,8 +38,6 @@ obj-$(CONFIG_FB_PM2) += pm2fb.o + obj-$(CONFIG_FB_PM3) += pm3fb.o + + obj-$(CONFIG_FB_MATROX) += matrox/ +-obj-$(CONFIG_FB_RIVA) += riva/ +-obj-$(CONFIG_FB_NVIDIA) += nvidia/ + obj-$(CONFIG_FB_ATY) += aty/ macmodes.o + obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o + obj-$(CONFIG_FB_RADEON) += aty/ +diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c +index 377dde3..c087b36 100644 +--- a/drivers/video/broadsheetfb.c ++++ b/drivers/video/broadsheetfb.c +@@ -741,10 +741,8 @@ static ssize_t broadsheet_loadstore_waveform(struct device *dev, + return -EINVAL; + + err = request_firmware(&fw_entry, "broadsheet.wbf", dev); +- if (err < 0) { +- dev_err(dev, "Failed to get broadsheet waveform\n"); ++ if (err) + goto err_failed; +- } + + /* try to enforce reasonable min max on waveform */ + if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) { +diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c +index 97d45e5..f63c62a 100644 +--- a/drivers/video/metronomefb.c ++++ b/drivers/video/metronomefb.c +@@ -677,10 +677,8 @@ static int __devinit metronomefb_probe(struct platform_device *dev) + a) request the waveform file from userspace + b) process waveform and decode into metromem */ + retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev); +- if (retval < 0) { +- dev_err(&dev->dev, "Failed to get waveform\n"); ++ if (retval) + goto err_csum_table; +- } + + retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31, + par); +diff --git a/drivers/video/nvidia/Makefile b/drivers/video/nvidia/Makefile +deleted file mode 100644 +index ca47432..0000000 +--- a/drivers/video/nvidia/Makefile ++++ /dev/null +@@ -1,13 +0,0 @@ +-# +-# Makefile for the nVidia framebuffer driver +-# +- +-obj-$(CONFIG_FB_NVIDIA) += nvidiafb.o +- +-nvidiafb-y := nvidia.o nv_hw.o nv_setup.o \ +- nv_accel.o +-nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o +-nvidiafb-$(CONFIG_FB_NVIDIA_BACKLIGHT) += nv_backlight.o +-nvidiafb-$(CONFIG_PPC_OF) += nv_of.o +- +-nvidiafb-objs := $(nvidiafb-y) +diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c +deleted file mode 100644 +index ad6472a..0000000 +--- a/drivers/video/nvidia/nv_accel.c ++++ /dev/null +@@ -1,416 +0,0 @@ +- /***************************************************************************\ +-|* *| +-|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *| +-|* *| +-|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +-|* international laws. Users and possessors of this source code are *| +-|* hereby granted a nonexclusive, royalty-free copyright license to *| +-|* use this code in individual and commercial software. *| +-|* *| +-|* Any use of this source code must include, in the user documenta- *| +-|* tion and internal comments to the code, notices to the end user *| +-|* as follows: *| +-|* *| +-|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *| +-|* *| +-|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +-|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +-|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +-|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +-|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +-|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +-|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +-|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +-|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +-|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +-|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +-|* *| +-|* U.S. Government End Users. This source code is a "commercial *| +-|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +-|* consisting of "commercial computer software" and "commercial *| +-|* computer software documentation," as such terms are used in *| +-|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +-|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +-|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +-|* all U.S. Government End Users acquire the source code with only *| +-|* those rights set forth herein. *| +-|* *| +- \***************************************************************************/ +- +-/* +- * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/ +- * XFree86 'nv' driver, this source code is provided under MIT-style licensing +- * where the source code is provided "as is" without warranty of any kind. +- * The only usage restriction is for the copyright notices to be retained +- * whenever code is used. +- * +- * Antonino Daplas 2005-03-11 +- */ +- +-#include +-#include "nv_type.h" +-#include "nv_proto.h" +-#include "nv_dma.h" +-#include "nv_local.h" +- +-/* There is a HW race condition with videoram command buffers. +- You can't jump to the location of your put offset. We write put +- at the jump offset + SKIPS dwords with noop padding in between +- to solve this problem */ +-#define SKIPS 8 +- +-static const int NVCopyROP[16] = { +- 0xCC, /* copy */ +- 0x55 /* invert */ +-}; +- +-static const int NVCopyROP_PM[16] = { +- 0xCA, /* copy */ +- 0x5A, /* invert */ +-}; +- +-static inline void nvidiafb_safe_mode(struct fb_info *info) +-{ +- struct nvidia_par *par = info->par; +- +- touch_softlockup_watchdog(); +- info->pixmap.scan_align = 1; +- par->lockup = 1; +-} +- +-static inline void NVFlush(struct fb_info *info) +-{ +- struct nvidia_par *par = info->par; +- int count = 1000000000; +- +- while (--count && READ_GET(par) != par->dmaPut) ; +- +- if (!count) { +- printk("nvidiafb: DMA Flush lockup\n"); +- nvidiafb_safe_mode(info); +- } +-} +- +-static inline void NVSync(struct fb_info *info) +-{ +- struct nvidia_par *par = info->par; +- int count = 1000000000; +- +- while (--count && NV_RD32(par->PGRAPH, 0x0700)) ; +- +- if (!count) { +- printk("nvidiafb: DMA Sync lockup\n"); +- nvidiafb_safe_mode(info); +- } +-} +- +-static void NVDmaKickoff(struct nvidia_par *par) +-{ +- if (par->dmaCurrent != par->dmaPut) { +- par->dmaPut = par->dmaCurrent; +- WRITE_PUT(par, par->dmaPut); +- } +-} +- +-static void NVDmaWait(struct fb_info *info, int size) +-{ +- struct nvidia_par *par = info->par; +- int dmaGet; +- int count = 1000000000, cnt; +- size++; +- +- while (par->dmaFree < size && --count && !par->lockup) { +- dmaGet = READ_GET(par); +- +- if (par->dmaPut >= dmaGet) { +- par->dmaFree = par->dmaMax - par->dmaCurrent; +- if (par->dmaFree < size) { +- NVDmaNext(par, 0x20000000); +- if (dmaGet <= SKIPS) { +- if (par->dmaPut <= SKIPS) +- WRITE_PUT(par, SKIPS + 1); +- cnt = 1000000000; +- do { +- dmaGet = READ_GET(par); +- } while (--cnt && dmaGet <= SKIPS); +- if (!cnt) { +- printk("DMA Get lockup\n"); +- par->lockup = 1; +- } +- } +- WRITE_PUT(par, SKIPS); +- par->dmaCurrent = par->dmaPut = SKIPS; +- par->dmaFree = dmaGet - (SKIPS + 1); +- } +- } else +- par->dmaFree = dmaGet - par->dmaCurrent - 1; +- } +- +- if (!count) { +- printk("nvidiafb: DMA Wait Lockup\n"); +- nvidiafb_safe_mode(info); +- } +-} +- +-static void NVSetPattern(struct fb_info *info, u32 clr0, u32 clr1, +- u32 pat0, u32 pat1) +-{ +- struct nvidia_par *par = info->par; +- +- NVDmaStart(info, par, PATTERN_COLOR_0, 4); +- NVDmaNext(par, clr0); +- NVDmaNext(par, clr1); +- NVDmaNext(par, pat0); +- NVDmaNext(par, pat1); +-} +- +-static void NVSetRopSolid(struct fb_info *info, u32 rop, u32 planemask) +-{ +- struct nvidia_par *par = info->par; +- +- if (planemask != ~0) { +- NVSetPattern(info, 0, planemask, ~0, ~0); +- if (par->currentRop != (rop + 32)) { +- NVDmaStart(info, par, ROP_SET, 1); +- NVDmaNext(par, NVCopyROP_PM[rop]); +- par->currentRop = rop + 32; +- } +- } else if (par->currentRop != rop) { +- if (par->currentRop >= 16) +- NVSetPattern(info, ~0, ~0, ~0, ~0); +- NVDmaStart(info, par, ROP_SET, 1); +- NVDmaNext(par, NVCopyROP[rop]); +- par->currentRop = rop; +- } +-} +- +-static void NVSetClippingRectangle(struct fb_info *info, int x1, int y1, +- int x2, int y2) +-{ +- struct nvidia_par *par = info->par; +- int h = y2 - y1 + 1; +- int w = x2 - x1 + 1; +- +- NVDmaStart(info, par, CLIP_POINT, 2); +- NVDmaNext(par, (y1 << 16) | x1); +- NVDmaNext(par, (h << 16) | w); +-} +- +-void NVResetGraphics(struct fb_info *info) +-{ +- struct nvidia_par *par = info->par; +- u32 surfaceFormat, patternFormat, rectFormat, lineFormat; +- int pitch, i; +- +- pitch = info->fix.line_length; +- +- par->dmaBase = (u32 __iomem *) (&par->FbStart[par->FbUsableSize]); +- +- for (i = 0; i < SKIPS; i++) +- NV_WR32(&par->dmaBase[i], 0, 0x00000000); +- +- NV_WR32(&par->dmaBase[0x0 + SKIPS], 0, 0x00040000); +- NV_WR32(&par->dmaBase[0x1 + SKIPS], 0, 0x80000010); +- NV_WR32(&par->dmaBase[0x2 + SKIPS], 0, 0x00042000); +- NV_WR32(&par->dmaBase[0x3 + SKIPS], 0, 0x80000011); +- NV_WR32(&par->dmaBase[0x4 + SKIPS], 0, 0x00044000); +- NV_WR32(&par->dmaBase[0x5 + SKIPS], 0, 0x80000012); +- NV_WR32(&par->dmaBase[0x6 + SKIPS], 0, 0x00046000); +- NV_WR32(&par->dmaBase[0x7 + SKIPS], 0, 0x80000013); +- NV_WR32(&par->dmaBase[0x8 + SKIPS], 0, 0x00048000); +- NV_WR32(&par->dmaBase[0x9 + SKIPS], 0, 0x80000014); +- NV_WR32(&par->dmaBase[0xA + SKIPS], 0, 0x0004A000); +- NV_WR32(&par->dmaBase[0xB + SKIPS], 0, 0x80000015); +- NV_WR32(&par->dmaBase[0xC + SKIPS], 0, 0x0004C000); +- NV_WR32(&par->dmaBase[0xD + SKIPS], 0, 0x80000016); +- NV_WR32(&par->dmaBase[0xE + SKIPS], 0, 0x0004E000); +- NV_WR32(&par->dmaBase[0xF + SKIPS], 0, 0x80000017); +- +- par->dmaPut = 0; +- par->dmaCurrent = 16 + SKIPS; +- par->dmaMax = 8191; +- par->dmaFree = par->dmaMax - par->dmaCurrent; +- +- switch (info->var.bits_per_pixel) { +- case 32: +- case 24: +- surfaceFormat = SURFACE_FORMAT_DEPTH24; +- patternFormat = PATTERN_FORMAT_DEPTH24; +- rectFormat = RECT_FORMAT_DEPTH24; +- lineFormat = LINE_FORMAT_DEPTH24; +- break; +- case 16: +- surfaceFormat = SURFACE_FORMAT_DEPTH16; +- patternFormat = PATTERN_FORMAT_DEPTH16; +- rectFormat = RECT_FORMAT_DEPTH16; +- lineFormat = LINE_FORMAT_DEPTH16; +- break; +- default: +- surfaceFormat = SURFACE_FORMAT_DEPTH8; +- patternFormat = PATTERN_FORMAT_DEPTH8; +- rectFormat = RECT_FORMAT_DEPTH8; +- lineFormat = LINE_FORMAT_DEPTH8; +- break; +- } +- +- NVDmaStart(info, par, SURFACE_FORMAT, 4); +- NVDmaNext(par, surfaceFormat); +- NVDmaNext(par, pitch | (pitch << 16)); +- NVDmaNext(par, 0); +- NVDmaNext(par, 0); +- +- NVDmaStart(info, par, PATTERN_FORMAT, 1); +- NVDmaNext(par, patternFormat); +- +- NVDmaStart(info, par, RECT_FORMAT, 1); +- NVDmaNext(par, rectFormat); +- +- NVDmaStart(info, par, LINE_FORMAT, 1); +- NVDmaNext(par, lineFormat); +- +- par->currentRop = ~0; /* set to something invalid */ +- NVSetRopSolid(info, ROP_COPY, ~0); +- +- NVSetClippingRectangle(info, 0, 0, info->var.xres_virtual, +- info->var.yres_virtual); +- +- NVDmaKickoff(par); +-} +- +-int nvidiafb_sync(struct fb_info *info) +-{ +- struct nvidia_par *par = info->par; +- +- if (info->state != FBINFO_STATE_RUNNING) +- return 0; +- +- if (!par->lockup) +- NVFlush(info); +- +- if (!par->lockup) +- NVSync(info); +- +- return 0; +-} +- +-void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region) +-{ +- struct nvidia_par *par = info->par; +- +- if (info->state != FBINFO_STATE_RUNNING) +- return; +- +- if (par->lockup) { +- cfb_copyarea(info, region); +- return; +- } +- +- NVDmaStart(info, par, BLIT_POINT_SRC, 3); +- NVDmaNext(par, (region->sy << 16) | region->sx); +- NVDmaNext(par, (region->dy << 16) | region->dx); +- NVDmaNext(par, (region->height << 16) | region->width); +- +- NVDmaKickoff(par); +-} +- +-void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +-{ +- struct nvidia_par *par = info->par; +- u32 color; +- +- if (info->state != FBINFO_STATE_RUNNING) +- return; +- +- if (par->lockup) { +- cfb_fillrect(info, rect); +- return; +- } +- +- if (info->var.bits_per_pixel == 8) +- color = rect->color; +- else +- color = ((u32 *) info->pseudo_palette)[rect->color]; +- +- if (rect->rop != ROP_COPY) +- NVSetRopSolid(info, rect->rop, ~0); +- +- NVDmaStart(info, par, RECT_SOLID_COLOR, 1); +- NVDmaNext(par, color); +- +- NVDmaStart(info, par, RECT_SOLID_RECTS(0), 2); +- NVDmaNext(par, (rect->dx << 16) | rect->dy); +- NVDmaNext(par, (rect->width << 16) | rect->height); +- +- NVDmaKickoff(par); +- +- if (rect->rop != ROP_COPY) +- NVSetRopSolid(info, ROP_COPY, ~0); +-} +- +-static void nvidiafb_mono_color_expand(struct fb_info *info, +- const struct fb_image *image) +-{ +- struct nvidia_par *par = info->par; +- u32 fg, bg, mask = ~(~0 >> (32 - info->var.bits_per_pixel)); +- u32 dsize, width, *data = (u32 *) image->data, tmp; +- int j, k = 0; +- +- width = (image->width + 31) & ~31; +- dsize = (width * image->height) >> 5; +- +- if (info->var.bits_per_pixel == 8) { +- fg = image->fg_color | mask; +- bg = image->bg_color | mask; +- } else { +- fg = ((u32 *) info->pseudo_palette)[image->fg_color] | mask; +- bg = ((u32 *) info->pseudo_palette)[image->bg_color] | mask; +- } +- +- NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_CLIP, 7); +- NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff)); +- NVDmaNext(par, ((image->dy + image->height) << 16) | +- ((image->dx + image->width) & 0xffff)); +- NVDmaNext(par, bg); +- NVDmaNext(par, fg); +- NVDmaNext(par, (image->height << 16) | width); +- NVDmaNext(par, (image->height << 16) | width); +- NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff)); +- +- while (dsize >= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS) { +- NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0), +- RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS); +- +- for (j = RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; j--;) { +- tmp = data[k++]; +- reverse_order(&tmp); +- NVDmaNext(par, tmp); +- } +- +- dsize -= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; +- } +- +- if (dsize) { +- NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize); +- +- for (j = dsize; j--;) { +- tmp = data[k++]; +- reverse_order(&tmp); +- NVDmaNext(par, tmp); +- } +- } +- +- NVDmaKickoff(par); +-} +- +-void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image) +-{ +- struct nvidia_par *par = info->par; +- +- if (info->state != FBINFO_STATE_RUNNING) +- return; +- +- if (image->depth == 1 && !par->lockup) +- nvidiafb_mono_color_expand(info, image); +- else +- cfb_imageblit(info, image); +-} +diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c +deleted file mode 100644 +index 8471008..0000000 +--- a/drivers/video/nvidia/nv_backlight.c ++++ /dev/null +@@ -1,148 +0,0 @@ +-/* +- * Backlight code for nVidia based graphic cards +- * +- * Copyright 2004 Antonino Daplas +- * Copyright (c) 2006 Michael Hanselmann +- * +- * 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 +- +-#ifdef CONFIG_PMAC_BACKLIGHT +-#include +-#endif +- +-#include "nv_local.h" +-#include "nv_type.h" +-#include "nv_proto.h" +- +-/* We do not have any information about which values are allowed, thus +- * we used safe values. +- */ +-#define MIN_LEVEL 0x158 +-#define MAX_LEVEL 0x534 +-#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX) +- +-static int nvidia_bl_get_level_brightness(struct nvidia_par *par, +- int level) +-{ +- struct fb_info *info = pci_get_drvdata(par->pci_dev); +- int nlevel; +- +- /* Get and convert the value */ +- /* No locking of bl_curve since we read a single value */ +- nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP; +- +- if (nlevel < 0) +- nlevel = 0; +- else if (nlevel < MIN_LEVEL) +- nlevel = MIN_LEVEL; +- else if (nlevel > MAX_LEVEL) +- nlevel = MAX_LEVEL; +- +- return nlevel; +-} +- +-static int nvidia_bl_update_status(struct backlight_device *bd) +-{ +- struct nvidia_par *par = bl_get_data(bd); +- u32 tmp_pcrt, tmp_pmc, fpcontrol; +- int level; +- +- if (!par->FlatPanel) +- return 0; +- +- if (bd->props.power != FB_BLANK_UNBLANK || +- bd->props.fb_blank != FB_BLANK_UNBLANK) +- level = 0; +- else +- level = bd->props.brightness; +- +- tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF; +- tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC; +- fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC; +- +- if (level > 0) { +- tmp_pcrt |= 0x1; +- tmp_pmc |= (1 << 31); /* backlight bit */ +- tmp_pmc |= nvidia_bl_get_level_brightness(par, level) << 16; +- fpcontrol |= par->fpSyncs; +- } else +- fpcontrol |= 0x20000022; +- +- NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt); +- NV_WR32(par->PMC, 0x10F0, tmp_pmc); +- NV_WR32(par->PRAMDAC, 0x848, fpcontrol); +- +- return 0; +-} +- +-static int nvidia_bl_get_brightness(struct backlight_device *bd) +-{ +- return bd->props.brightness; +-} +- +-static const struct backlight_ops nvidia_bl_ops = { +- .get_brightness = nvidia_bl_get_brightness, +- .update_status = nvidia_bl_update_status, +-}; +- +-void nvidia_bl_init(struct nvidia_par *par) +-{ +- struct backlight_properties props; +- struct fb_info *info = pci_get_drvdata(par->pci_dev); +- struct backlight_device *bd; +- char name[12]; +- +- if (!par->FlatPanel) +- return; +- +-#ifdef CONFIG_PMAC_BACKLIGHT +- if (!machine_is(powermac) || +- !pmac_has_backlight_type("mnca")) +- return; +-#endif +- +- snprintf(name, sizeof(name), "nvidiabl%d", info->node); +- +- memset(&props, 0, sizeof(struct backlight_properties)); +- props.type = BACKLIGHT_RAW; +- props.max_brightness = FB_BACKLIGHT_LEVELS - 1; +- bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops, +- &props); +- if (IS_ERR(bd)) { +- info->bl_dev = NULL; +- printk(KERN_WARNING "nvidia: Backlight registration failed\n"); +- goto error; +- } +- +- info->bl_dev = bd; +- fb_bl_default_curve(info, 0, +- 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL, +- 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); +- +- bd->props.brightness = bd->props.max_brightness; +- bd->props.power = FB_BLANK_UNBLANK; +- backlight_update_status(bd); +- +- printk("nvidia: Backlight initialized (%s)\n", name); +- +- return; +- +-error: +- return; +-} +- +-void nvidia_bl_exit(struct nvidia_par *par) +-{ +- struct fb_info *info = pci_get_drvdata(par->pci_dev); +- struct backlight_device *bd = info->bl_dev; +- +- backlight_device_unregister(bd); +- printk("nvidia: Backlight unloaded\n"); +-} +diff --git a/drivers/video/nvidia/nv_dma.h b/drivers/video/nvidia/nv_dma.h +deleted file mode 100644 +index a7ed1c0..0000000 +--- a/drivers/video/nvidia/nv_dma.h ++++ /dev/null +@@ -1,188 +0,0 @@ +- +- /***************************************************************************\ +-|* *| +-|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *| +-|* *| +-|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +-|* international laws. Users and possessors of this source code are *| +-|* hereby granted a nonexclusive, royalty-free copyright license to *| +-|* use this code in individual and commercial software. *| +-|* *| +-|* Any use of this source code must include, in the user documenta- *| +-|* tion and internal comments to the code, notices to the end user *| +-|* as follows: *| +-|* *| +-|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *| +-|* *| +-|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +-|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +-|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +-|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +-|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +-|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +-|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +-|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +-|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +-|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +-|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +-|* *| +-|* U.S. Government End Users. This source code is a "commercial *| +-|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +-|* consisting of "commercial computer software" and "commercial *| +-|* computer software documentation," as such terms are used in *| +-|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +-|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +-|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +-|* all U.S. Government End Users acquire the source code with only *| +-|* those rights set forth herein. *| +-|* *| +- \***************************************************************************/ +- +-/* +- * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/ +- * XFree86 'nv' driver, this source code is provided under MIT-style licensing +- * where the source code is provided "as is" without warranty of any kind. +- * The only usage restriction is for the copyright notices to be retained +- * whenever code is used. +- * +- * Antonino Daplas 2005-03-11 +- */ +- +-#define SURFACE_FORMAT 0x00000300 +-#define SURFACE_FORMAT_DEPTH8 0x00000001 +-#define SURFACE_FORMAT_DEPTH15 0x00000002 +-#define SURFACE_FORMAT_DEPTH16 0x00000004 +-#define SURFACE_FORMAT_DEPTH24 0x00000006 +-#define SURFACE_PITCH 0x00000304 +-#define SURFACE_PITCH_SRC 15:0 +-#define SURFACE_PITCH_DST 31:16 +-#define SURFACE_OFFSET_SRC 0x00000308 +-#define SURFACE_OFFSET_DST 0x0000030C +- +-#define ROP_SET 0x00002300 +- +-#define PATTERN_FORMAT 0x00004300 +-#define PATTERN_FORMAT_DEPTH8 0x00000003 +-#define PATTERN_FORMAT_DEPTH16 0x00000001 +-#define PATTERN_FORMAT_DEPTH24 0x00000003 +-#define PATTERN_COLOR_0 0x00004310 +-#define PATTERN_COLOR_1 0x00004314 +-#define PATTERN_PATTERN_0 0x00004318 +-#define PATTERN_PATTERN_1 0x0000431C +- +-#define CLIP_POINT 0x00006300 +-#define CLIP_POINT_X 15:0 +-#define CLIP_POINT_Y 31:16 +-#define CLIP_SIZE 0x00006304 +-#define CLIP_SIZE_WIDTH 15:0 +-#define CLIP_SIZE_HEIGHT 31:16 +- +-#define LINE_FORMAT 0x00008300 +-#define LINE_FORMAT_DEPTH8 0x00000003 +-#define LINE_FORMAT_DEPTH16 0x00000001 +-#define LINE_FORMAT_DEPTH24 0x00000003 +-#define LINE_COLOR 0x00008304 +-#define LINE_MAX_LINES 16 +-#define LINE_LINES(i) 0x00008400\ +- +(i)*8 +-#define LINE_LINES_POINT0_X 15:0 +-#define LINE_LINES_POINT0_Y 31:16 +-#define LINE_LINES_POINT1_X 47:32 +-#define LINE_LINES_POINT1_Y 63:48 +- +-#define BLIT_POINT_SRC 0x0000A300 +-#define BLIT_POINT_SRC_X 15:0 +-#define BLIT_POINT_SRC_Y 31:16 +-#define BLIT_POINT_DST 0x0000A304 +-#define BLIT_POINT_DST_X 15:0 +-#define BLIT_POINT_DST_Y 31:16 +-#define BLIT_SIZE 0x0000A308 +-#define BLIT_SIZE_WIDTH 15:0 +-#define BLIT_SIZE_HEIGHT 31:16 +- +-#define RECT_FORMAT 0x0000C300 +-#define RECT_FORMAT_DEPTH8 0x00000003 +-#define RECT_FORMAT_DEPTH16 0x00000001 +-#define RECT_FORMAT_DEPTH24 0x00000003 +-#define RECT_SOLID_COLOR 0x0000C3FC +-#define RECT_SOLID_RECTS_MAX_RECTS 32 +-#define RECT_SOLID_RECTS(i) 0x0000C400\ +- +(i)*8 +-#define RECT_SOLID_RECTS_Y 15:0 +-#define RECT_SOLID_RECTS_X 31:16 +-#define RECT_SOLID_RECTS_HEIGHT 47:32 +-#define RECT_SOLID_RECTS_WIDTH 63:48 +- +-#define RECT_EXPAND_ONE_COLOR_CLIP 0x0000C7EC +-#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_X 15:0 +-#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_Y 31:16 +-#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_X 47:32 +-#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_Y 63:48 +-#define RECT_EXPAND_ONE_COLOR_COLOR 0x0000C7F4 +-#define RECT_EXPAND_ONE_COLOR_SIZE 0x0000C7F8 +-#define RECT_EXPAND_ONE_COLOR_SIZE_WIDTH 15:0 +-#define RECT_EXPAND_ONE_COLOR_SIZE_HEIGHT 31:16 +-#define RECT_EXPAND_ONE_COLOR_POINT 0x0000C7FC +-#define RECT_EXPAND_ONE_COLOR_POINT_X 15:0 +-#define RECT_EXPAND_ONE_COLOR_POINT_Y 31:16 +-#define RECT_EXPAND_ONE_COLOR_DATA_MAX_DWORDS 128 +-#define RECT_EXPAND_ONE_COLOR_DATA(i) 0x0000C800\ +- +(i)*4 +- +-#define RECT_EXPAND_TWO_COLOR_CLIP 0x0000CBE4 +-#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_X 15:0 +-#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_Y 31:16 +-#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_X 47:32 +-#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_Y 63:48 +-#define RECT_EXPAND_TWO_COLOR_COLOR_0 0x0000CBEC +-#define RECT_EXPAND_TWO_COLOR_COLOR_1 0x0000CBF0 +-#define RECT_EXPAND_TWO_COLOR_SIZE_IN 0x0000CBF4 +-#define RECT_EXPAND_TWO_COLOR_SIZE_IN_WIDTH 15:0 +-#define RECT_EXPAND_TWO_COLOR_SIZE_IN_HEIGHT 31:16 +-#define RECT_EXPAND_TWO_COLOR_SIZE_OUT 0x0000CBF8 +-#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_WIDTH 15:0 +-#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_HEIGHT 31:16 +-#define RECT_EXPAND_TWO_COLOR_POINT 0x0000CBFC +-#define RECT_EXPAND_TWO_COLOR_POINT_X 15:0 +-#define RECT_EXPAND_TWO_COLOR_POINT_Y 31:16 +-#define RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS 128 +-#define RECT_EXPAND_TWO_COLOR_DATA(i) 0x0000CC00\ +- +(i)*4 +- +-#define STRETCH_BLIT_FORMAT 0x0000E300 +-#define STRETCH_BLIT_FORMAT_DEPTH8 0x00000004 +-#define STRETCH_BLIT_FORMAT_DEPTH16 0x00000007 +-#define STRETCH_BLIT_FORMAT_DEPTH24 0x00000004 +-#define STRETCH_BLIT_FORMAT_X8R8G8B8 0x00000004 +-#define STRETCH_BLIT_FORMAT_YUYV 0x00000005 +-#define STRETCH_BLIT_FORMAT_UYVY 0x00000006 +-#define STRETCH_BLIT_CLIP_POINT 0x0000E308 +-#define STRETCH_BLIT_CLIP_POINT_X 15:0 +-#define STRETCH_BLIT_CLIP_POINT_Y 31:16 +-#define STRETCH_BLIT_CLIP_POINT 0x0000E308 +-#define STRETCH_BLIT_CLIP_SIZE 0x0000E30C +-#define STRETCH_BLIT_CLIP_SIZE_WIDTH 15:0 +-#define STRETCH_BLIT_CLIP_SIZE_HEIGHT 31:16 +-#define STRETCH_BLIT_DST_POINT 0x0000E310 +-#define STRETCH_BLIT_DST_POINT_X 15:0 +-#define STRETCH_BLIT_DST_POINT_Y 31:16 +-#define STRETCH_BLIT_DST_SIZE 0x0000E314 +-#define STRETCH_BLIT_DST_SIZE_WIDTH 15:0 +-#define STRETCH_BLIT_DST_SIZE_HEIGHT 31:16 +-#define STRETCH_BLIT_DU_DX 0x0000E318 +-#define STRETCH_BLIT_DV_DY 0x0000E31C +-#define STRETCH_BLIT_SRC_SIZE 0x0000E400 +-#define STRETCH_BLIT_SRC_SIZE_WIDTH 15:0 +-#define STRETCH_BLIT_SRC_SIZE_HEIGHT 31:16 +-#define STRETCH_BLIT_SRC_FORMAT 0x0000E404 +-#define STRETCH_BLIT_SRC_FORMAT_PITCH 15:0 +-#define STRETCH_BLIT_SRC_FORMAT_ORIGIN 23:16 +-#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER 0x00000001 +-#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER 0x00000002 +-#define STRETCH_BLIT_SRC_FORMAT_FILTER 31:24 +-#define STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE 0x00000000 +-#define STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR 0x00000001 +-#define STRETCH_BLIT_SRC_OFFSET 0x0000E408 +-#define STRETCH_BLIT_SRC_POINT 0x0000E40C +-#define STRETCH_BLIT_SRC_POINT_U 15:0 +-#define STRETCH_BLIT_SRC_POINT_V 31:16 +diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c +deleted file mode 100644 +index ed20a98..0000000 +--- a/drivers/video/nvidia/nv_hw.c ++++ /dev/null +@@ -1,1687 +0,0 @@ +- /***************************************************************************\ +-|* *| +-|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *| +-|* *| +-|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +-|* international laws. Users and possessors of this source code are *| +-|* hereby granted a nonexclusive, royalty-free copyright license to *| +-|* use this code in individual and commercial software. *| +-|* *| +-|* Any use of this source code must include, in the user documenta- *| +-|* tion and internal comments to the code, notices to the end user *| +-|* as follows: *| +-|* *| +-|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *| +-|* *| +-|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +-|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +-|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +-|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +-|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +-|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +-|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +-|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +-|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +-|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +-|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +-|* *| +-|* U.S. Government End Users. This source code is a "commercial *| +-|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +-|* consisting of "commercial computer software" and "commercial *| +-|* computer software documentation," as such terms are used in *| +-|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +-|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +-|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +-|* all U.S. Government End Users acquire the source code with only *| +-|* those rights set forth herein. *| +-|* *| +- \***************************************************************************/ +- +-/* +- * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/ +- * XFree86 'nv' driver, this source code is provided under MIT-style licensing +- * where the source code is provided "as is" without warranty of any kind. +- * The only usage restriction is for the copyright notices to be retained +- * whenever code is used. +- * +- * Antonino Daplas 2005-03-11 +- */ +- +-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c,v 1.4 2003/11/03 05:11:25 tsi Exp $ */ +- +-#include +-#include "nv_type.h" +-#include "nv_local.h" +-#include "nv_proto.h" +- +-void NVLockUnlock(struct nvidia_par *par, int Lock) +-{ +- u8 cr11; +- +- VGA_WR08(par->PCIO, 0x3D4, 0x1F); +- VGA_WR08(par->PCIO, 0x3D5, Lock ? 0x99 : 0x57); +- +- VGA_WR08(par->PCIO, 0x3D4, 0x11); +- cr11 = VGA_RD08(par->PCIO, 0x3D5); +- if (Lock) +- cr11 |= 0x80; +- else +- cr11 &= ~0x80; +- VGA_WR08(par->PCIO, 0x3D5, cr11); +-} +- +-int NVShowHideCursor(struct nvidia_par *par, int ShowHide) +-{ +- int cur = par->CurrentState->cursor1; +- +- par->CurrentState->cursor1 = (par->CurrentState->cursor1 & 0xFE) | +- (ShowHide & 0x01); +- VGA_WR08(par->PCIO, 0x3D4, 0x31); +- VGA_WR08(par->PCIO, 0x3D5, par->CurrentState->cursor1); +- +- if (par->Architecture == NV_ARCH_40) +- NV_WR32(par->PRAMDAC, 0x0300, NV_RD32(par->PRAMDAC, 0x0300)); +- +- return (cur & 0x01); +-} +- +-/****************************************************************************\ +-* * +-* The video arbitration routines calculate some "magic" numbers. Fixes * +-* the snow seen when accessing the framebuffer without it. * +-* It just works (I hope). * +-* * +-\****************************************************************************/ +- +-typedef struct { +- int graphics_lwm; +- int video_lwm; +- int graphics_burst_size; +- int video_burst_size; +- int valid; +-} nv4_fifo_info; +- +-typedef struct { +- int pclk_khz; +- int mclk_khz; +- int nvclk_khz; +- char mem_page_miss; +- char mem_latency; +- int memory_width; +- char enable_video; +- char gr_during_vid; +- char pix_bpp; +- char mem_aligned; +- char enable_mp; +-} nv4_sim_state; +- +-typedef struct { +- int graphics_lwm; +- int video_lwm; +- int graphics_burst_size; +- int video_burst_size; +- int valid; +-} nv10_fifo_info; +- +-typedef struct { +- int pclk_khz; +- int mclk_khz; +- int nvclk_khz; +- char mem_page_miss; +- char mem_latency; +- u32 memory_type; +- int memory_width; +- char enable_video; +- char gr_during_vid; +- char pix_bpp; +- char mem_aligned; +- char enable_mp; +-} nv10_sim_state; +- +-static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk, +- unsigned int *NVClk) +-{ +- unsigned int pll, N, M, MB, NB, P; +- +- if (par->Architecture >= NV_ARCH_40) { +- pll = NV_RD32(par->PMC, 0x4020); +- P = (pll >> 16) & 0x07; +- pll = NV_RD32(par->PMC, 0x4024); +- M = pll & 0xFF; +- N = (pll >> 8) & 0xFF; +- if (((par->Chipset & 0xfff0) == 0x0290) || +- ((par->Chipset & 0xfff0) == 0x0390)) { +- MB = 1; +- NB = 1; +- } else { +- MB = (pll >> 16) & 0xFF; +- NB = (pll >> 24) & 0xFF; +- } +- *MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; +- +- pll = NV_RD32(par->PMC, 0x4000); +- P = (pll >> 16) & 0x07; +- pll = NV_RD32(par->PMC, 0x4004); +- M = pll & 0xFF; +- N = (pll >> 8) & 0xFF; +- MB = (pll >> 16) & 0xFF; +- NB = (pll >> 24) & 0xFF; +- +- *NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; +- } else if (par->twoStagePLL) { +- pll = NV_RD32(par->PRAMDAC0, 0x0504); +- M = pll & 0xFF; +- N = (pll >> 8) & 0xFF; +- P = (pll >> 16) & 0x0F; +- pll = NV_RD32(par->PRAMDAC0, 0x0574); +- if (pll & 0x80000000) { +- MB = pll & 0xFF; +- NB = (pll >> 8) & 0xFF; +- } else { +- MB = 1; +- NB = 1; +- } +- *MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; +- +- pll = NV_RD32(par->PRAMDAC0, 0x0500); +- M = pll & 0xFF; +- N = (pll >> 8) & 0xFF; +- P = (pll >> 16) & 0x0F; +- pll = NV_RD32(par->PRAMDAC0, 0x0570); +- if (pll & 0x80000000) { +- MB = pll & 0xFF; +- NB = (pll >> 8) & 0xFF; +- } else { +- MB = 1; +- NB = 1; +- } +- *NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; +- } else +- if (((par->Chipset & 0x0ff0) == 0x0300) || +- ((par->Chipset & 0x0ff0) == 0x0330)) { +- pll = NV_RD32(par->PRAMDAC0, 0x0504); +- M = pll & 0x0F; +- N = (pll >> 8) & 0xFF; +- P = (pll >> 16) & 0x07; +- if (pll & 0x00000080) { +- MB = (pll >> 4) & 0x07; +- NB = (pll >> 19) & 0x1f; +- } else { +- MB = 1; +- NB = 1; +- } +- *MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; +- +- pll = NV_RD32(par->PRAMDAC0, 0x0500); +- M = pll & 0x0F; +- N = (pll >> 8) & 0xFF; +- P = (pll >> 16) & 0x07; +- if (pll & 0x00000080) { +- MB = (pll >> 4) & 0x07; +- NB = (pll >> 19) & 0x1f; +- } else { +- MB = 1; +- NB = 1; +- } +- *NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; +- } else { +- pll = NV_RD32(par->PRAMDAC0, 0x0504); +- M = pll & 0xFF; +- N = (pll >> 8) & 0xFF; +- P = (pll >> 16) & 0x0F; +- *MClk = (N * par->CrystalFreqKHz / M) >> P; +- +- pll = NV_RD32(par->PRAMDAC0, 0x0500); +- M = pll & 0xFF; +- N = (pll >> 8) & 0xFF; +- P = (pll >> 16) & 0x0F; +- *NVClk = (N * par->CrystalFreqKHz / M) >> P; +- } +-} +- +-static void nv4CalcArbitration(nv4_fifo_info * fifo, nv4_sim_state * arb) +-{ +- int data, pagemiss, cas, width, video_enable, bpp; +- int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs; +- int found, mclk_extra, mclk_loop, cbs, m1, p1; +- int mclk_freq, pclk_freq, nvclk_freq, mp_enable; +- int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate; +- int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt, clwm; +- +- fifo->valid = 1; +- pclk_freq = arb->pclk_khz; +- mclk_freq = arb->mclk_khz; +- nvclk_freq = arb->nvclk_khz; +- pagemiss = arb->mem_page_miss; +- cas = arb->mem_latency; +- width = arb->memory_width >> 6; +- video_enable = arb->enable_video; +- bpp = arb->pix_bpp; +- mp_enable = arb->enable_mp; +- clwm = 0; +- vlwm = 0; +- cbs = 128; +- pclks = 2; +- nvclks = 2; +- nvclks += 2; +- nvclks += 1; +- mclks = 5; +- mclks += 3; +- mclks += 1; +- mclks += cas; +- mclks += 1; +- mclks += 1; +- mclks += 1; +- mclks += 1; +- mclk_extra = 3; +- nvclks += 2; +- nvclks += 1; +- nvclks += 1; +- nvclks += 1; +- if (mp_enable) +- mclks += 4; +- nvclks += 0; +- pclks += 0; +- found = 0; +- vbs = 0; +- while (found != 1) { +- fifo->valid = 1; +- found = 1; +- mclk_loop = mclks + mclk_extra; +- us_m = mclk_loop * 1000 * 1000 / mclk_freq; +- us_n = nvclks * 1000 * 1000 / nvclk_freq; +- us_p = nvclks * 1000 * 1000 / pclk_freq; +- if (video_enable) { +- video_drain_rate = pclk_freq * 2; +- crtc_drain_rate = pclk_freq * bpp / 8; +- vpagemiss = 2; +- vpagemiss += 1; +- crtpagemiss = 2; +- vpm_us = +- (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq; +- if (nvclk_freq * 2 > mclk_freq * width) +- video_fill_us = +- cbs * 1000 * 1000 / 16 / nvclk_freq; +- else +- video_fill_us = +- cbs * 1000 * 1000 / (8 * width) / +- mclk_freq; +- us_video = vpm_us + us_m + us_n + us_p + video_fill_us; +- vlwm = us_video * video_drain_rate / (1000 * 1000); +- vlwm++; +- vbs = 128; +- if (vlwm > 128) +- vbs = 64; +- if (vlwm > (256 - 64)) +- vbs = 32; +- if (nvclk_freq * 2 > mclk_freq * width) +- video_fill_us = +- vbs * 1000 * 1000 / 16 / nvclk_freq; +- else +- video_fill_us = +- vbs * 1000 * 1000 / (8 * width) / +- mclk_freq; +- cpm_us = +- crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq; +- us_crt = +- us_video + video_fill_us + cpm_us + us_m + us_n + +- us_p; +- clwm = us_crt * crtc_drain_rate / (1000 * 1000); +- clwm++; +- } else { +- crtc_drain_rate = pclk_freq * bpp / 8; +- crtpagemiss = 2; +- crtpagemiss += 1; +- cpm_us = +- crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq; +- us_crt = cpm_us + us_m + us_n + us_p; +- clwm = us_crt * crtc_drain_rate / (1000 * 1000); +- clwm++; +- } +- m1 = clwm + cbs - 512; +- p1 = m1 * pclk_freq / mclk_freq; +- p1 = p1 * bpp / 8; +- if ((p1 < m1) && (m1 > 0)) { +- fifo->valid = 0; +- found = 0; +- if (mclk_extra == 0) +- found = 1; +- mclk_extra--; +- } else if (video_enable) { +- if ((clwm > 511) || (vlwm > 255)) { +- fifo->valid = 0; +- found = 0; +- if (mclk_extra == 0) +- found = 1; +- mclk_extra--; +- } +- } else { +- if (clwm > 519) { +- fifo->valid = 0; +- found = 0; +- if (mclk_extra == 0) +- found = 1; +- mclk_extra--; +- } +- } +- if (clwm < 384) +- clwm = 384; +- if (vlwm < 128) +- vlwm = 128; +- data = (int)(clwm); +- fifo->graphics_lwm = data; +- fifo->graphics_burst_size = 128; +- data = (int)((vlwm + 15)); +- fifo->video_lwm = data; +- fifo->video_burst_size = vbs; +- } +-} +- +-static void nv4UpdateArbitrationSettings(unsigned VClk, +- unsigned pixelDepth, +- unsigned *burst, +- unsigned *lwm, struct nvidia_par *par) +-{ +- nv4_fifo_info fifo_data; +- nv4_sim_state sim_data; +- unsigned int MClk, NVClk, cfg1; +- +- nvGetClocks(par, &MClk, &NVClk); +- +- cfg1 = NV_RD32(par->PFB, 0x00000204); +- sim_data.pix_bpp = (char)pixelDepth; +- sim_data.enable_video = 0; +- sim_data.enable_mp = 0; +- sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ? +- 128 : 64; +- sim_data.mem_latency = (char)cfg1 & 0x0F; +- sim_data.mem_aligned = 1; +- sim_data.mem_page_miss = +- (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01)); +- sim_data.gr_during_vid = 0; +- sim_data.pclk_khz = VClk; +- sim_data.mclk_khz = MClk; +- sim_data.nvclk_khz = NVClk; +- nv4CalcArbitration(&fifo_data, &sim_data); +- if (fifo_data.valid) { +- int b = fifo_data.graphics_burst_size >> 4; +- *burst = 0; +- while (b >>= 1) +- (*burst)++; +- *lwm = fifo_data.graphics_lwm >> 3; +- } +-} +- +-static void nv10CalcArbitration(nv10_fifo_info * fifo, nv10_sim_state * arb) +-{ +- int data, pagemiss, width, video_enable, bpp; +- int nvclks, mclks, pclks, vpagemiss, crtpagemiss; +- int nvclk_fill; +- int found, mclk_extra, mclk_loop, cbs, m1; +- int mclk_freq, pclk_freq, nvclk_freq, mp_enable; +- int us_m, us_m_min, us_n, us_p, crtc_drain_rate; +- int vus_m; +- int vpm_us, us_video, cpm_us, us_crt, clwm; +- int clwm_rnd_down; +- int m2us, us_pipe_min, p1clk, p2; +- int min_mclk_extra; +- int us_min_mclk_extra; +- +- fifo->valid = 1; +- pclk_freq = arb->pclk_khz; /* freq in KHz */ +- mclk_freq = arb->mclk_khz; +- nvclk_freq = arb->nvclk_khz; +- pagemiss = arb->mem_page_miss; +- width = arb->memory_width / 64; +- video_enable = arb->enable_video; +- bpp = arb->pix_bpp; +- mp_enable = arb->enable_mp; +- clwm = 0; +- +- cbs = 512; +- +- pclks = 4; /* lwm detect. */ +- +- nvclks = 3; /* lwm -> sync. */ +- nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */ +- /* 2 edge sync. may be very close to edge so just put one. */ +- mclks = 1; +- mclks += 1; /* arb_hp_req */ +- mclks += 5; /* ap_hp_req tiling pipeline */ +- +- mclks += 2; /* tc_req latency fifo */ +- mclks += 2; /* fb_cas_n_ memory request to fbio block */ +- mclks += 7; /* sm_d_rdv data returned from fbio block */ +- +- /* fb.rd.d.Put_gc need to accumulate 256 bits for read */ +- if (arb->memory_type == 0) +- if (arb->memory_width == 64) /* 64 bit bus */ +- mclks += 4; +- else +- mclks += 2; +- else if (arb->memory_width == 64) /* 64 bit bus */ +- mclks += 2; +- else +- mclks += 1; +- +- if ((!video_enable) && (arb->memory_width == 128)) { +- mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */ +- min_mclk_extra = 17; +- } else { +- mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */ +- /* mclk_extra = 4; *//* Margin of error */ +- min_mclk_extra = 18; +- } +- +- /* 2 edge sync. may be very close to edge so just put one. */ +- nvclks += 1; +- nvclks += 1; /* fbi_d_rdv_n */ +- nvclks += 1; /* Fbi_d_rdata */ +- nvclks += 1; /* crtfifo load */ +- +- if (mp_enable) +- mclks += 4; /* Mp can get in with a burst of 8. */ +- /* Extra clocks determined by heuristics */ +- +- nvclks += 0; +- pclks += 0; +- found = 0; +- while (found != 1) { +- fifo->valid = 1; +- found = 1; +- mclk_loop = mclks + mclk_extra; +- /* Mclk latency in us */ +- us_m = mclk_loop * 1000 * 1000 / mclk_freq; +- /* Minimum Mclk latency in us */ +- us_m_min = mclks * 1000 * 1000 / mclk_freq; +- us_min_mclk_extra = min_mclk_extra * 1000 * 1000 / mclk_freq; +- /* nvclk latency in us */ +- us_n = nvclks * 1000 * 1000 / nvclk_freq; +- /* nvclk latency in us */ +- us_p = pclks * 1000 * 1000 / pclk_freq; +- us_pipe_min = us_m_min + us_n + us_p; +- +- /* Mclk latency in us */ +- vus_m = mclk_loop * 1000 * 1000 / mclk_freq; +- +- if (video_enable) { +- crtc_drain_rate = pclk_freq * bpp / 8; /* MB/s */ +- +- vpagemiss = 1; /* self generating page miss */ +- vpagemiss += 1; /* One higher priority before */ +- +- crtpagemiss = 2; /* self generating page miss */ +- if (mp_enable) +- crtpagemiss += 1; /* if MA0 conflict */ +- +- vpm_us = +- (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq; +- +- /* Video has separate read return path */ +- us_video = vpm_us + vus_m; +- +- cpm_us = +- crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq; +- /* Wait for video */ +- us_crt = us_video +- + cpm_us /* CRT Page miss */ +- + us_m + us_n + us_p /* other latency */ +- ; +- +- clwm = us_crt * crtc_drain_rate / (1000 * 1000); +- /* fixed point <= float_point - 1. Fixes that */ +- clwm++; +- } else { +- /* bpp * pclk/8 */ +- crtc_drain_rate = pclk_freq * bpp / 8; +- +- crtpagemiss = 1; /* self generating page miss */ +- crtpagemiss += 1; /* MA0 page miss */ +- if (mp_enable) +- crtpagemiss += 1; /* if MA0 conflict */ +- cpm_us = +- crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq; +- us_crt = cpm_us + us_m + us_n + us_p; +- clwm = us_crt * crtc_drain_rate / (1000 * 1000); +- /* fixed point <= float_point - 1. Fixes that */ +- clwm++; +- +- /* Finally, a heuristic check when width == 64 bits */ +- if (width == 1) { +- nvclk_fill = nvclk_freq * 8; +- if (crtc_drain_rate * 100 >= nvclk_fill * 102) +- /*Large number to fail */ +- clwm = 0xfff; +- +- else if (crtc_drain_rate * 100 >= +- nvclk_fill * 98) { +- clwm = 1024; +- cbs = 512; +- } +- } +- } +- +- /* +- Overfill check: +- */ +- +- clwm_rnd_down = ((int)clwm / 8) * 8; +- if (clwm_rnd_down < clwm) +- clwm += 8; +- +- m1 = clwm + cbs - 1024; /* Amount of overfill */ +- m2us = us_pipe_min + us_min_mclk_extra; +- +- /* pclk cycles to drain */ +- p1clk = m2us * pclk_freq / (1000 * 1000); +- p2 = p1clk * bpp / 8; /* bytes drained. */ +- +- if ((p2 < m1) && (m1 > 0)) { +- fifo->valid = 0; +- found = 0; +- if (min_mclk_extra == 0) { +- if (cbs <= 32) { +- /* Can't adjust anymore! */ +- found = 1; +- } else { +- /* reduce the burst size */ +- cbs = cbs / 2; +- } +- } else { +- min_mclk_extra--; +- } +- } else { +- if (clwm > 1023) { /* Have some margin */ +- fifo->valid = 0; +- found = 0; +- if (min_mclk_extra == 0) +- /* Can't adjust anymore! */ +- found = 1; +- else +- min_mclk_extra--; +- } +- } +- +- if (clwm < (1024 - cbs + 8)) +- clwm = 1024 - cbs + 8; +- data = (int)(clwm); +- /* printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", +- clwm, data ); */ +- fifo->graphics_lwm = data; +- fifo->graphics_burst_size = cbs; +- +- fifo->video_lwm = 1024; +- fifo->video_burst_size = 512; +- } +-} +- +-static void nv10UpdateArbitrationSettings(unsigned VClk, +- unsigned pixelDepth, +- unsigned *burst, +- unsigned *lwm, +- struct nvidia_par *par) +-{ +- nv10_fifo_info fifo_data; +- nv10_sim_state sim_data; +- unsigned int MClk, NVClk, cfg1; +- +- nvGetClocks(par, &MClk, &NVClk); +- +- cfg1 = NV_RD32(par->PFB, 0x0204); +- sim_data.pix_bpp = (char)pixelDepth; +- sim_data.enable_video = 1; +- sim_data.enable_mp = 0; +- sim_data.memory_type = (NV_RD32(par->PFB, 0x0200) & 0x01) ? 1 : 0; +- sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ? +- 128 : 64; +- sim_data.mem_latency = (char)cfg1 & 0x0F; +- sim_data.mem_aligned = 1; +- sim_data.mem_page_miss = +- (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01)); +- sim_data.gr_during_vid = 0; +- sim_data.pclk_khz = VClk; +- sim_data.mclk_khz = MClk; +- sim_data.nvclk_khz = NVClk; +- nv10CalcArbitration(&fifo_data, &sim_data); +- if (fifo_data.valid) { +- int b = fifo_data.graphics_burst_size >> 4; +- *burst = 0; +- while (b >>= 1) +- (*burst)++; +- *lwm = fifo_data.graphics_lwm >> 3; +- } +-} +- +-static void nv30UpdateArbitrationSettings ( +- struct nvidia_par *par, +- unsigned int *burst, +- unsigned int *lwm +-) +-{ +- unsigned int MClk, NVClk; +- unsigned int fifo_size, burst_size, graphics_lwm; +- +- fifo_size = 2048; +- burst_size = 512; +- graphics_lwm = fifo_size - burst_size; +- +- nvGetClocks(par, &MClk, &NVClk); +- +- *burst = 0; +- burst_size >>= 5; +- while(burst_size >>= 1) (*burst)++; +- *lwm = graphics_lwm >> 3; +-} +- +-static void nForceUpdateArbitrationSettings(unsigned VClk, +- unsigned pixelDepth, +- unsigned *burst, +- unsigned *lwm, +- struct nvidia_par *par) +-{ +- nv10_fifo_info fifo_data; +- nv10_sim_state sim_data; +- unsigned int M, N, P, pll, MClk, NVClk, memctrl; +- struct pci_dev *dev; +- +- if ((par->Chipset & 0x0FF0) == 0x01A0) { +- unsigned int uMClkPostDiv; +- dev = pci_get_bus_and_slot(0, 3); +- pci_read_config_dword(dev, 0x6C, &uMClkPostDiv); +- uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf; +- +- if (!uMClkPostDiv) +- uMClkPostDiv = 4; +- MClk = 400000 / uMClkPostDiv; +- } else { +- dev = pci_get_bus_and_slot(0, 5); +- pci_read_config_dword(dev, 0x4c, &MClk); +- MClk /= 1000; +- } +- pci_dev_put(dev); +- pll = NV_RD32(par->PRAMDAC0, 0x0500); +- M = (pll >> 0) & 0xFF; +- N = (pll >> 8) & 0xFF; +- P = (pll >> 16) & 0x0F; +- NVClk = (N * par->CrystalFreqKHz / M) >> P; +- sim_data.pix_bpp = (char)pixelDepth; +- sim_data.enable_video = 0; +- sim_data.enable_mp = 0; +- dev = pci_get_bus_and_slot(0, 1); +- pci_read_config_dword(dev, 0x7C, &sim_data.memory_type); +- pci_dev_put(dev); +- sim_data.memory_type = (sim_data.memory_type >> 12) & 1; +- sim_data.memory_width = 64; +- +- dev = pci_get_bus_and_slot(0, 3); +- pci_read_config_dword(dev, 0, &memctrl); +- pci_dev_put(dev); +- memctrl >>= 16; +- +- if ((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) { +- u32 dimm[3]; +- +- dev = pci_get_bus_and_slot(0, 2); +- pci_read_config_dword(dev, 0x40, &dimm[0]); +- dimm[0] = (dimm[0] >> 8) & 0x4f; +- pci_read_config_dword(dev, 0x44, &dimm[1]); +- dimm[1] = (dimm[1] >> 8) & 0x4f; +- pci_read_config_dword(dev, 0x48, &dimm[2]); +- dimm[2] = (dimm[2] >> 8) & 0x4f; +- +- if ((dimm[0] + dimm[1]) != dimm[2]) { +- printk("nvidiafb: your nForce DIMMs are not arranged " +- "in optimal banks!\n"); +- } +- pci_dev_put(dev); +- } +- +- sim_data.mem_latency = 3; +- sim_data.mem_aligned = 1; +- sim_data.mem_page_miss = 10; +- sim_data.gr_during_vid = 0; +- sim_data.pclk_khz = VClk; +- sim_data.mclk_khz = MClk; +- sim_data.nvclk_khz = NVClk; +- nv10CalcArbitration(&fifo_data, &sim_data); +- if (fifo_data.valid) { +- int b = fifo_data.graphics_burst_size >> 4; +- *burst = 0; +- while (b >>= 1) +- (*burst)++; +- *lwm = fifo_data.graphics_lwm >> 3; +- } +-} +- +-/****************************************************************************\ +-* * +-* RIVA Mode State Routines * +-* * +-\****************************************************************************/ +- +-/* +- * Calculate the Video Clock parameters for the PLL. +- */ +-static void CalcVClock(int clockIn, +- int *clockOut, u32 * pllOut, struct nvidia_par *par) +-{ +- unsigned lowM, highM; +- unsigned DeltaNew, DeltaOld; +- unsigned VClk, Freq; +- unsigned M, N, P; +- +- DeltaOld = 0xFFFFFFFF; +- +- VClk = (unsigned)clockIn; +- +- if (par->CrystalFreqKHz == 13500) { +- lowM = 7; +- highM = 13; +- } else { +- lowM = 8; +- highM = 14; +- } +- +- for (P = 0; P <= 4; P++) { +- Freq = VClk << P; +- if ((Freq >= 128000) && (Freq <= 350000)) { +- for (M = lowM; M <= highM; M++) { +- N = ((VClk << P) * M) / par->CrystalFreqKHz; +- if (N <= 255) { +- Freq = +- ((par->CrystalFreqKHz * N) / +- M) >> P; +- if (Freq > VClk) +- DeltaNew = Freq - VClk; +- else +- DeltaNew = VClk - Freq; +- if (DeltaNew < DeltaOld) { +- *pllOut = +- (P << 16) | (N << 8) | M; +- *clockOut = Freq; +- DeltaOld = DeltaNew; +- } +- } +- } +- } +- } +-} +- +-static void CalcVClock2Stage(int clockIn, +- int *clockOut, +- u32 * pllOut, +- u32 * pllBOut, struct nvidia_par *par) +-{ +- unsigned DeltaNew, DeltaOld; +- unsigned VClk, Freq; +- unsigned M, N, P; +- +- DeltaOld = 0xFFFFFFFF; +- +- *pllBOut = 0x80000401; /* fixed at x4 for now */ +- +- VClk = (unsigned)clockIn; +- +- for (P = 0; P <= 6; P++) { +- Freq = VClk << P; +- if ((Freq >= 400000) && (Freq <= 1000000)) { +- for (M = 1; M <= 13; M++) { +- N = ((VClk << P) * M) / +- (par->CrystalFreqKHz << 2); +- if ((N >= 5) && (N <= 255)) { +- Freq = +- (((par->CrystalFreqKHz << 2) * N) / +- M) >> P; +- if (Freq > VClk) +- DeltaNew = Freq - VClk; +- else +- DeltaNew = VClk - Freq; +- if (DeltaNew < DeltaOld) { +- *pllOut = +- (P << 16) | (N << 8) | M; +- *clockOut = Freq; +- DeltaOld = DeltaNew; +- } +- } +- } +- } +- } +-} +- +-/* +- * Calculate extended mode parameters (SVGA) and save in a +- * mode state structure. +- */ +-void NVCalcStateExt(struct nvidia_par *par, +- RIVA_HW_STATE * state, +- int bpp, +- int width, +- int hDisplaySize, int height, int dotClock, int flags) +-{ +- int pixelDepth, VClk = 0; +- /* +- * Save mode parameters. +- */ +- state->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */ +- state->width = width; +- state->height = height; +- /* +- * Extended RIVA registers. +- */ +- pixelDepth = (bpp + 1) / 8; +- if (par->twoStagePLL) +- CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, +- par); +- else +- CalcVClock(dotClock, &VClk, &state->pll, par); +- +- switch (par->Architecture) { +- case NV_ARCH_04: +- nv4UpdateArbitrationSettings(VClk, +- pixelDepth * 8, +- &(state->arbitration0), +- &(state->arbitration1), par); +- state->cursor0 = 0x00; +- state->cursor1 = 0xbC; +- if (flags & FB_VMODE_DOUBLE) +- state->cursor1 |= 2; +- state->cursor2 = 0x00000000; +- state->pllsel = 0x10000700; +- state->config = 0x00001114; +- state->general = bpp == 16 ? 0x00101100 : 0x00100100; +- state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00; +- break; +- case NV_ARCH_40: +- if (!par->FlatPanel) +- state->control = NV_RD32(par->PRAMDAC0, 0x0580) & +- 0xeffffeff; +- /* fallthrough */ +- case NV_ARCH_10: +- case NV_ARCH_20: +- case NV_ARCH_30: +- default: +- if ((par->Chipset & 0xfff0) == 0x0240 || +- (par->Chipset & 0xfff0) == 0x03d0) { +- state->arbitration0 = 256; +- state->arbitration1 = 0x0480; +- } else if (((par->Chipset & 0xffff) == 0x01A0) || +- ((par->Chipset & 0xffff) == 0x01f0)) { +- nForceUpdateArbitrationSettings(VClk, +- pixelDepth * 8, +- &(state->arbitration0), +- &(state->arbitration1), +- par); +- } else if (par->Architecture < NV_ARCH_30) { +- nv10UpdateArbitrationSettings(VClk, +- pixelDepth * 8, +- &(state->arbitration0), +- &(state->arbitration1), +- par); +- } else { +- nv30UpdateArbitrationSettings(par, +- &(state->arbitration0), +- &(state->arbitration1)); +- } +- +- state->cursor0 = 0x80 | (par->CursorStart >> 17); +- state->cursor1 = (par->CursorStart >> 11) << 2; +- state->cursor2 = par->CursorStart >> 24; +- if (flags & FB_VMODE_DOUBLE) +- state->cursor1 |= 2; +- state->pllsel = 0x10000700; +- state->config = NV_RD32(par->PFB, 0x00000200); +- state->general = bpp == 16 ? 0x00101100 : 0x00100100; +- state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00; +- break; +- } +- +- if (bpp != 8) /* DirectColor */ +- state->general |= 0x00000030; +- +- state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3; +- state->pixel = (pixelDepth > 2) ? 3 : pixelDepth; +-} +- +-void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) +-{ +- int i, j; +- +- NV_WR32(par->PMC, 0x0140, 0x00000000); +- NV_WR32(par->PMC, 0x0200, 0xFFFF00FF); +- NV_WR32(par->PMC, 0x0200, 0xFFFFFFFF); +- +- NV_WR32(par->PTIMER, 0x0200 * 4, 0x00000008); +- NV_WR32(par->PTIMER, 0x0210 * 4, 0x00000003); +- NV_WR32(par->PTIMER, 0x0140 * 4, 0x00000000); +- NV_WR32(par->PTIMER, 0x0100 * 4, 0xFFFFFFFF); +- +- if (par->Architecture == NV_ARCH_04) { +- if (state) +- NV_WR32(par->PFB, 0x0200, state->config); +- } else if ((par->Architecture < NV_ARCH_40) || +- (par->Chipset & 0xfff0) == 0x0040) { +- for (i = 0; i < 8; i++) { +- NV_WR32(par->PFB, 0x0240 + (i * 0x10), 0); +- NV_WR32(par->PFB, 0x0244 + (i * 0x10), +- par->FbMapSize - 1); +- } +- } else { +- int regions = 12; +- +- if (((par->Chipset & 0xfff0) == 0x0090) || +- ((par->Chipset & 0xfff0) == 0x01D0) || +- ((par->Chipset & 0xfff0) == 0x0290) || +- ((par->Chipset & 0xfff0) == 0x0390) || +- ((par->Chipset & 0xfff0) == 0x03D0)) +- regions = 15; +- for(i = 0; i < regions; i++) { +- NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0); +- NV_WR32(par->PFB, 0x0604 + (i * 0x10), +- par->FbMapSize - 1); +- } +- } +- +- if (par->Architecture >= NV_ARCH_40) { +- NV_WR32(par->PRAMIN, 0x0000 * 4, 0x80000010); +- NV_WR32(par->PRAMIN, 0x0001 * 4, 0x00101202); +- NV_WR32(par->PRAMIN, 0x0002 * 4, 0x80000011); +- NV_WR32(par->PRAMIN, 0x0003 * 4, 0x00101204); +- NV_WR32(par->PRAMIN, 0x0004 * 4, 0x80000012); +- NV_WR32(par->PRAMIN, 0x0005 * 4, 0x00101206); +- NV_WR32(par->PRAMIN, 0x0006 * 4, 0x80000013); +- NV_WR32(par->PRAMIN, 0x0007 * 4, 0x00101208); +- NV_WR32(par->PRAMIN, 0x0008 * 4, 0x80000014); +- NV_WR32(par->PRAMIN, 0x0009 * 4, 0x0010120A); +- NV_WR32(par->PRAMIN, 0x000A * 4, 0x80000015); +- NV_WR32(par->PRAMIN, 0x000B * 4, 0x0010120C); +- NV_WR32(par->PRAMIN, 0x000C * 4, 0x80000016); +- NV_WR32(par->PRAMIN, 0x000D * 4, 0x0010120E); +- NV_WR32(par->PRAMIN, 0x000E * 4, 0x80000017); +- NV_WR32(par->PRAMIN, 0x000F * 4, 0x00101210); +- NV_WR32(par->PRAMIN, 0x0800 * 4, 0x00003000); +- NV_WR32(par->PRAMIN, 0x0801 * 4, par->FbMapSize - 1); +- NV_WR32(par->PRAMIN, 0x0802 * 4, 0x00000002); +- NV_WR32(par->PRAMIN, 0x0808 * 4, 0x02080062); +- NV_WR32(par->PRAMIN, 0x0809 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x080A * 4, 0x00001200); +- NV_WR32(par->PRAMIN, 0x080B * 4, 0x00001200); +- NV_WR32(par->PRAMIN, 0x080C * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0810 * 4, 0x02080043); +- NV_WR32(par->PRAMIN, 0x0811 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0812 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0813 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0814 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0815 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0818 * 4, 0x02080044); +- NV_WR32(par->PRAMIN, 0x0819 * 4, 0x02000000); +- NV_WR32(par->PRAMIN, 0x081A * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x081B * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x081C * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0820 * 4, 0x02080019); +- NV_WR32(par->PRAMIN, 0x0821 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0822 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0823 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0824 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0825 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0828 * 4, 0x020A005C); +- NV_WR32(par->PRAMIN, 0x0829 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x082A * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x082B * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x082C * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x082D * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0830 * 4, 0x0208009F); +- NV_WR32(par->PRAMIN, 0x0831 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0832 * 4, 0x00001200); +- NV_WR32(par->PRAMIN, 0x0833 * 4, 0x00001200); +- NV_WR32(par->PRAMIN, 0x0834 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0835 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0838 * 4, 0x0208004A); +- NV_WR32(par->PRAMIN, 0x0839 * 4, 0x02000000); +- NV_WR32(par->PRAMIN, 0x083A * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x083B * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x083C * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x083D * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0840 * 4, 0x02080077); +- NV_WR32(par->PRAMIN, 0x0841 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0842 * 4, 0x00001200); +- NV_WR32(par->PRAMIN, 0x0843 * 4, 0x00001200); +- NV_WR32(par->PRAMIN, 0x0844 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0845 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x084C * 4, 0x00003002); +- NV_WR32(par->PRAMIN, 0x084D * 4, 0x00007FFF); +- NV_WR32(par->PRAMIN, 0x084E * 4, +- par->FbUsableSize | 0x00000002); +- +-#ifdef __BIG_ENDIAN +- NV_WR32(par->PRAMIN, 0x080A * 4, +- NV_RD32(par->PRAMIN, 0x080A * 4) | 0x01000000); +- NV_WR32(par->PRAMIN, 0x0812 * 4, +- NV_RD32(par->PRAMIN, 0x0812 * 4) | 0x01000000); +- NV_WR32(par->PRAMIN, 0x081A * 4, +- NV_RD32(par->PRAMIN, 0x081A * 4) | 0x01000000); +- NV_WR32(par->PRAMIN, 0x0822 * 4, +- NV_RD32(par->PRAMIN, 0x0822 * 4) | 0x01000000); +- NV_WR32(par->PRAMIN, 0x082A * 4, +- NV_RD32(par->PRAMIN, 0x082A * 4) | 0x01000000); +- NV_WR32(par->PRAMIN, 0x0832 * 4, +- NV_RD32(par->PRAMIN, 0x0832 * 4) | 0x01000000); +- NV_WR32(par->PRAMIN, 0x083A * 4, +- NV_RD32(par->PRAMIN, 0x083A * 4) | 0x01000000); +- NV_WR32(par->PRAMIN, 0x0842 * 4, +- NV_RD32(par->PRAMIN, 0x0842 * 4) | 0x01000000); +- NV_WR32(par->PRAMIN, 0x0819 * 4, 0x01000000); +- NV_WR32(par->PRAMIN, 0x0839 * 4, 0x01000000); +-#endif +- } else { +- NV_WR32(par->PRAMIN, 0x0000 * 4, 0x80000010); +- NV_WR32(par->PRAMIN, 0x0001 * 4, 0x80011201); +- NV_WR32(par->PRAMIN, 0x0002 * 4, 0x80000011); +- NV_WR32(par->PRAMIN, 0x0003 * 4, 0x80011202); +- NV_WR32(par->PRAMIN, 0x0004 * 4, 0x80000012); +- NV_WR32(par->PRAMIN, 0x0005 * 4, 0x80011203); +- NV_WR32(par->PRAMIN, 0x0006 * 4, 0x80000013); +- NV_WR32(par->PRAMIN, 0x0007 * 4, 0x80011204); +- NV_WR32(par->PRAMIN, 0x0008 * 4, 0x80000014); +- NV_WR32(par->PRAMIN, 0x0009 * 4, 0x80011205); +- NV_WR32(par->PRAMIN, 0x000A * 4, 0x80000015); +- NV_WR32(par->PRAMIN, 0x000B * 4, 0x80011206); +- NV_WR32(par->PRAMIN, 0x000C * 4, 0x80000016); +- NV_WR32(par->PRAMIN, 0x000D * 4, 0x80011207); +- NV_WR32(par->PRAMIN, 0x000E * 4, 0x80000017); +- NV_WR32(par->PRAMIN, 0x000F * 4, 0x80011208); +- NV_WR32(par->PRAMIN, 0x0800 * 4, 0x00003000); +- NV_WR32(par->PRAMIN, 0x0801 * 4, par->FbMapSize - 1); +- NV_WR32(par->PRAMIN, 0x0802 * 4, 0x00000002); +- NV_WR32(par->PRAMIN, 0x0803 * 4, 0x00000002); +- if (par->Architecture >= NV_ARCH_10) +- NV_WR32(par->PRAMIN, 0x0804 * 4, 0x01008062); +- else +- NV_WR32(par->PRAMIN, 0x0804 * 4, 0x01008042); +- NV_WR32(par->PRAMIN, 0x0805 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0806 * 4, 0x12001200); +- NV_WR32(par->PRAMIN, 0x0807 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0808 * 4, 0x01008043); +- NV_WR32(par->PRAMIN, 0x0809 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x080A * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x080B * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x080C * 4, 0x01008044); +- NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000002); +- NV_WR32(par->PRAMIN, 0x080E * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x080F * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0810 * 4, 0x01008019); +- NV_WR32(par->PRAMIN, 0x0811 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0812 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0813 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0814 * 4, 0x0100A05C); +- NV_WR32(par->PRAMIN, 0x0815 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0816 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0817 * 4, 0x00000000); +- if (par->WaitVSyncPossible) +- NV_WR32(par->PRAMIN, 0x0818 * 4, 0x0100809F); +- else +- NV_WR32(par->PRAMIN, 0x0818 * 4, 0x0100805F); +- NV_WR32(par->PRAMIN, 0x0819 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x081A * 4, 0x12001200); +- NV_WR32(par->PRAMIN, 0x081B * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x081C * 4, 0x0100804A); +- NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000002); +- NV_WR32(par->PRAMIN, 0x081E * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x081F * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0820 * 4, 0x01018077); +- NV_WR32(par->PRAMIN, 0x0821 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0822 * 4, 0x12001200); +- NV_WR32(par->PRAMIN, 0x0823 * 4, 0x00000000); +- NV_WR32(par->PRAMIN, 0x0824 * 4, 0x00003002); +- NV_WR32(par->PRAMIN, 0x0825 * 4, 0x00007FFF); +- NV_WR32(par->PRAMIN, 0x0826 * 4, +- par->FbUsableSize | 0x00000002); +- NV_WR32(par->PRAMIN, 0x0827 * 4, 0x00000002); +-#ifdef __BIG_ENDIAN +- NV_WR32(par->PRAMIN, 0x0804 * 4, +- NV_RD32(par->PRAMIN, 0x0804 * 4) | 0x00080000); +- NV_WR32(par->PRAMIN, 0x0808 * 4, +- NV_RD32(par->PRAMIN, 0x0808 * 4) | 0x00080000); +- NV_WR32(par->PRAMIN, 0x080C * 4, +- NV_RD32(par->PRAMIN, 0x080C * 4) | 0x00080000); +- NV_WR32(par->PRAMIN, 0x0810 * 4, +- NV_RD32(par->PRAMIN, 0x0810 * 4) | 0x00080000); +- NV_WR32(par->PRAMIN, 0x0814 * 4, +- NV_RD32(par->PRAMIN, 0x0814 * 4) | 0x00080000); +- NV_WR32(par->PRAMIN, 0x0818 * 4, +- NV_RD32(par->PRAMIN, 0x0818 * 4) | 0x00080000); +- NV_WR32(par->PRAMIN, 0x081C * 4, +- NV_RD32(par->PRAMIN, 0x081C * 4) | 0x00080000); +- NV_WR32(par->PRAMIN, 0x0820 * 4, +- NV_RD32(par->PRAMIN, 0x0820 * 4) | 0x00080000); +- NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000001); +- NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000001); +-#endif +- } +- if (par->Architecture < NV_ARCH_10) { +- if ((par->Chipset & 0x0fff) == 0x0020) { +- NV_WR32(par->PRAMIN, 0x0824 * 4, +- NV_RD32(par->PRAMIN, 0x0824 * 4) | 0x00020000); +- NV_WR32(par->PRAMIN, 0x0826 * 4, +- NV_RD32(par->PRAMIN, +- 0x0826 * 4) + par->FbAddress); +- } +- NV_WR32(par->PGRAPH, 0x0080, 0x000001FF); +- NV_WR32(par->PGRAPH, 0x0080, 0x1230C000); +- NV_WR32(par->PGRAPH, 0x0084, 0x72111101); +- NV_WR32(par->PGRAPH, 0x0088, 0x11D5F071); +- NV_WR32(par->PGRAPH, 0x008C, 0x0004FF31); +- NV_WR32(par->PGRAPH, 0x008C, 0x4004FF31); +- NV_WR32(par->PGRAPH, 0x0140, 0x00000000); +- NV_WR32(par->PGRAPH, 0x0100, 0xFFFFFFFF); +- NV_WR32(par->PGRAPH, 0x0170, 0x10010100); +- NV_WR32(par->PGRAPH, 0x0710, 0xFFFFFFFF); +- NV_WR32(par->PGRAPH, 0x0720, 0x00000001); +- NV_WR32(par->PGRAPH, 0x0810, 0x00000000); +- NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF); +- } else { +- NV_WR32(par->PGRAPH, 0x0080, 0xFFFFFFFF); +- NV_WR32(par->PGRAPH, 0x0080, 0x00000000); +- +- NV_WR32(par->PGRAPH, 0x0140, 0x00000000); +- NV_WR32(par->PGRAPH, 0x0100, 0xFFFFFFFF); +- NV_WR32(par->PGRAPH, 0x0144, 0x10010100); +- NV_WR32(par->PGRAPH, 0x0714, 0xFFFFFFFF); +- NV_WR32(par->PGRAPH, 0x0720, 0x00000001); +- NV_WR32(par->PGRAPH, 0x0710, +- NV_RD32(par->PGRAPH, 0x0710) & 0x0007ff00); +- NV_WR32(par->PGRAPH, 0x0710, +- NV_RD32(par->PGRAPH, 0x0710) | 0x00020100); +- +- if (par->Architecture == NV_ARCH_10) { +- NV_WR32(par->PGRAPH, 0x0084, 0x00118700); +- NV_WR32(par->PGRAPH, 0x0088, 0x24E00810); +- NV_WR32(par->PGRAPH, 0x008C, 0x55DE0030); +- +- for (i = 0; i < 32; i++) +- NV_WR32(&par->PGRAPH[(0x0B00 / 4) + i], 0, +- NV_RD32(&par->PFB[(0x0240 / 4) + i], +- 0)); +- +- NV_WR32(par->PGRAPH, 0x640, 0); +- NV_WR32(par->PGRAPH, 0x644, 0); +- NV_WR32(par->PGRAPH, 0x684, par->FbMapSize - 1); +- NV_WR32(par->PGRAPH, 0x688, par->FbMapSize - 1); +- +- NV_WR32(par->PGRAPH, 0x0810, 0x00000000); +- NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF); +- } else { +- if (par->Architecture >= NV_ARCH_40) { +- NV_WR32(par->PGRAPH, 0x0084, 0x401287c0); +- NV_WR32(par->PGRAPH, 0x008C, 0x60de8051); +- NV_WR32(par->PGRAPH, 0x0090, 0x00008000); +- NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f); +- NV_WR32(par->PGRAPH, 0x0bc4, +- NV_RD32(par->PGRAPH, 0x0bc4) | +- 0x00008000); +- +- j = NV_RD32(par->REGS, 0x1540) & 0xff; +- +- if (j) { +- for (i = 0; !(j & 1); j >>= 1, i++); +- NV_WR32(par->PGRAPH, 0x5000, i); +- } +- +- if ((par->Chipset & 0xfff0) == 0x0040) { +- NV_WR32(par->PGRAPH, 0x09b0, +- 0x83280fff); +- NV_WR32(par->PGRAPH, 0x09b4, +- 0x000000a0); +- } else { +- NV_WR32(par->PGRAPH, 0x0820, +- 0x83280eff); +- NV_WR32(par->PGRAPH, 0x0824, +- 0x000000a0); +- } +- +- switch (par->Chipset & 0xfff0) { +- case 0x0040: +- case 0x0210: +- NV_WR32(par->PGRAPH, 0x09b8, +- 0x0078e366); +- NV_WR32(par->PGRAPH, 0x09bc, +- 0x0000014c); +- NV_WR32(par->PFB, 0x033C, +- NV_RD32(par->PFB, 0x33C) & +- 0xffff7fff); +- break; +- case 0x00C0: +- case 0x0120: +- NV_WR32(par->PGRAPH, 0x0828, +- 0x007596ff); +- NV_WR32(par->PGRAPH, 0x082C, +- 0x00000108); +- break; +- case 0x0160: +- case 0x01D0: +- case 0x0240: +- case 0x03D0: +- NV_WR32(par->PMC, 0x1700, +- NV_RD32(par->PFB, 0x020C)); +- NV_WR32(par->PMC, 0x1704, 0); +- NV_WR32(par->PMC, 0x1708, 0); +- NV_WR32(par->PMC, 0x170C, +- NV_RD32(par->PFB, 0x020C)); +- NV_WR32(par->PGRAPH, 0x0860, 0); +- NV_WR32(par->PGRAPH, 0x0864, 0); +- NV_WR32(par->PRAMDAC, 0x0608, +- NV_RD32(par->PRAMDAC, +- 0x0608) | 0x00100000); +- break; +- case 0x0140: +- NV_WR32(par->PGRAPH, 0x0828, +- 0x0072cb77); +- NV_WR32(par->PGRAPH, 0x082C, +- 0x00000108); +- break; +- case 0x0220: +- NV_WR32(par->PGRAPH, 0x0860, 0); +- NV_WR32(par->PGRAPH, 0x0864, 0); +- NV_WR32(par->PRAMDAC, 0x0608, +- NV_RD32(par->PRAMDAC, 0x0608) | +- 0x00100000); +- break; +- case 0x0090: +- case 0x0290: +- case 0x0390: +- NV_WR32(par->PRAMDAC, 0x0608, +- NV_RD32(par->PRAMDAC, 0x0608) | +- 0x00100000); +- NV_WR32(par->PGRAPH, 0x0828, +- 0x07830610); +- NV_WR32(par->PGRAPH, 0x082C, +- 0x0000016A); +- break; +- default: +- break; +- }; +- +- NV_WR32(par->PGRAPH, 0x0b38, 0x2ffff800); +- NV_WR32(par->PGRAPH, 0x0b3c, 0x00006000); +- NV_WR32(par->PGRAPH, 0x032C, 0x01000000); +- NV_WR32(par->PGRAPH, 0x0220, 0x00001200); +- } else if (par->Architecture == NV_ARCH_30) { +- NV_WR32(par->PGRAPH, 0x0084, 0x40108700); +- NV_WR32(par->PGRAPH, 0x0890, 0x00140000); +- NV_WR32(par->PGRAPH, 0x008C, 0xf00e0431); +- NV_WR32(par->PGRAPH, 0x0090, 0x00008000); +- NV_WR32(par->PGRAPH, 0x0610, 0xf04b1f36); +- NV_WR32(par->PGRAPH, 0x0B80, 0x1002d888); +- NV_WR32(par->PGRAPH, 0x0B88, 0x62ff007f); +- } else { +- NV_WR32(par->PGRAPH, 0x0084, 0x00118700); +- NV_WR32(par->PGRAPH, 0x008C, 0xF20E0431); +- NV_WR32(par->PGRAPH, 0x0090, 0x00000000); +- NV_WR32(par->PGRAPH, 0x009C, 0x00000040); +- +- if ((par->Chipset & 0x0ff0) >= 0x0250) { +- NV_WR32(par->PGRAPH, 0x0890, +- 0x00080000); +- NV_WR32(par->PGRAPH, 0x0610, +- 0x304B1FB6); +- NV_WR32(par->PGRAPH, 0x0B80, +- 0x18B82880); +- NV_WR32(par->PGRAPH, 0x0B84, +- 0x44000000); +- NV_WR32(par->PGRAPH, 0x0098, +- 0x40000080); +- NV_WR32(par->PGRAPH, 0x0B88, +- 0x000000ff); +- } else { +- NV_WR32(par->PGRAPH, 0x0880, +- 0x00080000); +- NV_WR32(par->PGRAPH, 0x0094, +- 0x00000005); +- NV_WR32(par->PGRAPH, 0x0B80, +- 0x45CAA208); +- NV_WR32(par->PGRAPH, 0x0B84, +- 0x24000000); +- NV_WR32(par->PGRAPH, 0x0098, +- 0x00000040); +- NV_WR32(par->PGRAPH, 0x0750, +- 0x00E00038); +- NV_WR32(par->PGRAPH, 0x0754, +- 0x00000030); +- NV_WR32(par->PGRAPH, 0x0750, +- 0x00E10038); +- NV_WR32(par->PGRAPH, 0x0754, +- 0x00000030); +- } +- } +- +- if ((par->Architecture < NV_ARCH_40) || +- ((par->Chipset & 0xfff0) == 0x0040)) { +- for (i = 0; i < 32; i++) { +- NV_WR32(par->PGRAPH, 0x0900 + i*4, +- NV_RD32(par->PFB, 0x0240 +i*4)); +- NV_WR32(par->PGRAPH, 0x6900 + i*4, +- NV_RD32(par->PFB, 0x0240 +i*4)); +- } +- } else { +- if (((par->Chipset & 0xfff0) == 0x0090) || +- ((par->Chipset & 0xfff0) == 0x01D0) || +- ((par->Chipset & 0xfff0) == 0x0290) || +- ((par->Chipset & 0xfff0) == 0x0390) || +- ((par->Chipset & 0xfff0) == 0x03D0)) { +- for (i = 0; i < 60; i++) { +- NV_WR32(par->PGRAPH, +- 0x0D00 + i*4, +- NV_RD32(par->PFB, +- 0x0600 + i*4)); +- NV_WR32(par->PGRAPH, +- 0x6900 + i*4, +- NV_RD32(par->PFB, +- 0x0600 + i*4)); +- } +- } else { +- for (i = 0; i < 48; i++) { +- NV_WR32(par->PGRAPH, +- 0x0900 + i*4, +- NV_RD32(par->PFB, +- 0x0600 + i*4)); +- if(((par->Chipset & 0xfff0) +- != 0x0160) && +- ((par->Chipset & 0xfff0) +- != 0x0220) && +- ((par->Chipset & 0xfff0) +- != 0x240)) +- NV_WR32(par->PGRAPH, +- 0x6900 + i*4, +- NV_RD32(par->PFB, +- 0x0600 + i*4)); +- } +- } +- } +- +- if (par->Architecture >= NV_ARCH_40) { +- if ((par->Chipset & 0xfff0) == 0x0040) { +- NV_WR32(par->PGRAPH, 0x09A4, +- NV_RD32(par->PFB, 0x0200)); +- NV_WR32(par->PGRAPH, 0x09A8, +- NV_RD32(par->PFB, 0x0204)); +- NV_WR32(par->PGRAPH, 0x69A4, +- NV_RD32(par->PFB, 0x0200)); +- NV_WR32(par->PGRAPH, 0x69A8, +- NV_RD32(par->PFB, 0x0204)); +- +- NV_WR32(par->PGRAPH, 0x0820, 0); +- NV_WR32(par->PGRAPH, 0x0824, 0); +- NV_WR32(par->PGRAPH, 0x0864, +- par->FbMapSize - 1); +- NV_WR32(par->PGRAPH, 0x0868, +- par->FbMapSize - 1); +- } else { +- if ((par->Chipset & 0xfff0) == 0x0090 || +- (par->Chipset & 0xfff0) == 0x01D0 || +- (par->Chipset & 0xfff0) == 0x0290 || +- (par->Chipset & 0xfff0) == 0x0390) { +- NV_WR32(par->PGRAPH, 0x0DF0, +- NV_RD32(par->PFB, 0x0200)); +- NV_WR32(par->PGRAPH, 0x0DF4, +- NV_RD32(par->PFB, 0x0204)); +- } else { +- NV_WR32(par->PGRAPH, 0x09F0, +- NV_RD32(par->PFB, 0x0200)); +- NV_WR32(par->PGRAPH, 0x09F4, +- NV_RD32(par->PFB, 0x0204)); +- } +- NV_WR32(par->PGRAPH, 0x69F0, +- NV_RD32(par->PFB, 0x0200)); +- NV_WR32(par->PGRAPH, 0x69F4, +- NV_RD32(par->PFB, 0x0204)); +- +- NV_WR32(par->PGRAPH, 0x0840, 0); +- NV_WR32(par->PGRAPH, 0x0844, 0); +- NV_WR32(par->PGRAPH, 0x08a0, +- par->FbMapSize - 1); +- NV_WR32(par->PGRAPH, 0x08a4, +- par->FbMapSize - 1); +- } +- } else { +- NV_WR32(par->PGRAPH, 0x09A4, +- NV_RD32(par->PFB, 0x0200)); +- NV_WR32(par->PGRAPH, 0x09A8, +- NV_RD32(par->PFB, 0x0204)); +- NV_WR32(par->PGRAPH, 0x0750, 0x00EA0000); +- NV_WR32(par->PGRAPH, 0x0754, +- NV_RD32(par->PFB, 0x0200)); +- NV_WR32(par->PGRAPH, 0x0750, 0x00EA0004); +- NV_WR32(par->PGRAPH, 0x0754, +- NV_RD32(par->PFB, 0x0204)); +- +- NV_WR32(par->PGRAPH, 0x0820, 0); +- NV_WR32(par->PGRAPH, 0x0824, 0); +- NV_WR32(par->PGRAPH, 0x0864, +- par->FbMapSize - 1); +- NV_WR32(par->PGRAPH, 0x0868, +- par->FbMapSize - 1); +- } +- NV_WR32(par->PGRAPH, 0x0B20, 0x00000000); +- NV_WR32(par->PGRAPH, 0x0B04, 0xFFFFFFFF); +- } +- } +- NV_WR32(par->PGRAPH, 0x053C, 0); +- NV_WR32(par->PGRAPH, 0x0540, 0); +- NV_WR32(par->PGRAPH, 0x0544, 0x00007FFF); +- NV_WR32(par->PGRAPH, 0x0548, 0x00007FFF); +- +- NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000000); +- NV_WR32(par->PFIFO, 0x0141 * 4, 0x00000001); +- NV_WR32(par->PFIFO, 0x0480 * 4, 0x00000000); +- NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000000); +- if (par->Architecture >= NV_ARCH_40) +- NV_WR32(par->PFIFO, 0x0481 * 4, 0x00010000); +- else +- NV_WR32(par->PFIFO, 0x0481 * 4, 0x00000100); +- NV_WR32(par->PFIFO, 0x0490 * 4, 0x00000000); +- NV_WR32(par->PFIFO, 0x0491 * 4, 0x00000000); +- if (par->Architecture >= NV_ARCH_40) +- NV_WR32(par->PFIFO, 0x048B * 4, 0x00001213); +- else +- NV_WR32(par->PFIFO, 0x048B * 4, 0x00001209); +- NV_WR32(par->PFIFO, 0x0400 * 4, 0x00000000); +- NV_WR32(par->PFIFO, 0x0414 * 4, 0x00000000); +- NV_WR32(par->PFIFO, 0x0084 * 4, 0x03000100); +- NV_WR32(par->PFIFO, 0x0085 * 4, 0x00000110); +- NV_WR32(par->PFIFO, 0x0086 * 4, 0x00000112); +- NV_WR32(par->PFIFO, 0x0143 * 4, 0x0000FFFF); +- NV_WR32(par->PFIFO, 0x0496 * 4, 0x0000FFFF); +- NV_WR32(par->PFIFO, 0x0050 * 4, 0x00000000); +- NV_WR32(par->PFIFO, 0x0040 * 4, 0xFFFFFFFF); +- NV_WR32(par->PFIFO, 0x0415 * 4, 0x00000001); +- NV_WR32(par->PFIFO, 0x048C * 4, 0x00000000); +- NV_WR32(par->PFIFO, 0x04A0 * 4, 0x00000000); +-#ifdef __BIG_ENDIAN +- NV_WR32(par->PFIFO, 0x0489 * 4, 0x800F0078); +-#else +- NV_WR32(par->PFIFO, 0x0489 * 4, 0x000F0078); +-#endif +- NV_WR32(par->PFIFO, 0x0488 * 4, 0x00000001); +- NV_WR32(par->PFIFO, 0x0480 * 4, 0x00000001); +- NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000001); +- NV_WR32(par->PFIFO, 0x0495 * 4, 0x00000001); +- NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000001); +- +- if (!state) { +- par->CurrentState = NULL; +- return; +- } +- +- if (par->Architecture >= NV_ARCH_10) { +- if (par->twoHeads) { +- NV_WR32(par->PCRTC0, 0x0860, state->head); +- NV_WR32(par->PCRTC0, 0x2860, state->head2); +- } +- NV_WR32(par->PRAMDAC, 0x0404, NV_RD32(par->PRAMDAC, 0x0404) | +- (1 << 25)); +- +- NV_WR32(par->PMC, 0x8704, 1); +- NV_WR32(par->PMC, 0x8140, 0); +- NV_WR32(par->PMC, 0x8920, 0); +- NV_WR32(par->PMC, 0x8924, 0); +- NV_WR32(par->PMC, 0x8908, par->FbMapSize - 1); +- NV_WR32(par->PMC, 0x890C, par->FbMapSize - 1); +- NV_WR32(par->PMC, 0x1588, 0); +- +- NV_WR32(par->PCRTC, 0x0810, state->cursorConfig); +- NV_WR32(par->PCRTC, 0x0830, state->displayV - 3); +- NV_WR32(par->PCRTC, 0x0834, state->displayV - 1); +- +- if (par->FlatPanel) { +- if ((par->Chipset & 0x0ff0) == 0x0110) { +- NV_WR32(par->PRAMDAC, 0x0528, state->dither); +- } else if (par->twoHeads) { +- NV_WR32(par->PRAMDAC, 0x083C, state->dither); +- } +- +- VGA_WR08(par->PCIO, 0x03D4, 0x53); +- VGA_WR08(par->PCIO, 0x03D5, state->timingH); +- VGA_WR08(par->PCIO, 0x03D4, 0x54); +- VGA_WR08(par->PCIO, 0x03D5, state->timingV); +- VGA_WR08(par->PCIO, 0x03D4, 0x21); +- VGA_WR08(par->PCIO, 0x03D5, 0xfa); +- } +- +- VGA_WR08(par->PCIO, 0x03D4, 0x41); +- VGA_WR08(par->PCIO, 0x03D5, state->extra); +- } +- +- VGA_WR08(par->PCIO, 0x03D4, 0x19); +- VGA_WR08(par->PCIO, 0x03D5, state->repaint0); +- VGA_WR08(par->PCIO, 0x03D4, 0x1A); +- VGA_WR08(par->PCIO, 0x03D5, state->repaint1); +- VGA_WR08(par->PCIO, 0x03D4, 0x25); +- VGA_WR08(par->PCIO, 0x03D5, state->screen); +- VGA_WR08(par->PCIO, 0x03D4, 0x28); +- VGA_WR08(par->PCIO, 0x03D5, state->pixel); +- VGA_WR08(par->PCIO, 0x03D4, 0x2D); +- VGA_WR08(par->PCIO, 0x03D5, state->horiz); +- VGA_WR08(par->PCIO, 0x03D4, 0x1C); +- VGA_WR08(par->PCIO, 0x03D5, state->fifo); +- VGA_WR08(par->PCIO, 0x03D4, 0x1B); +- VGA_WR08(par->PCIO, 0x03D5, state->arbitration0); +- VGA_WR08(par->PCIO, 0x03D4, 0x20); +- VGA_WR08(par->PCIO, 0x03D5, state->arbitration1); +- +- if(par->Architecture >= NV_ARCH_30) { +- VGA_WR08(par->PCIO, 0x03D4, 0x47); +- VGA_WR08(par->PCIO, 0x03D5, state->arbitration1 >> 8); +- } +- +- VGA_WR08(par->PCIO, 0x03D4, 0x30); +- VGA_WR08(par->PCIO, 0x03D5, state->cursor0); +- VGA_WR08(par->PCIO, 0x03D4, 0x31); +- VGA_WR08(par->PCIO, 0x03D5, state->cursor1); +- VGA_WR08(par->PCIO, 0x03D4, 0x2F); +- VGA_WR08(par->PCIO, 0x03D5, state->cursor2); +- VGA_WR08(par->PCIO, 0x03D4, 0x39); +- VGA_WR08(par->PCIO, 0x03D5, state->interlace); +- +- if (!par->FlatPanel) { +- if (par->Architecture >= NV_ARCH_40) +- NV_WR32(par->PRAMDAC0, 0x0580, state->control); +- +- NV_WR32(par->PRAMDAC0, 0x050C, state->pllsel); +- NV_WR32(par->PRAMDAC0, 0x0508, state->vpll); +- if (par->twoHeads) +- NV_WR32(par->PRAMDAC0, 0x0520, state->vpll2); +- if (par->twoStagePLL) { +- NV_WR32(par->PRAMDAC0, 0x0578, state->vpllB); +- NV_WR32(par->PRAMDAC0, 0x057C, state->vpll2B); +- } +- } else { +- NV_WR32(par->PRAMDAC, 0x0848, state->scale); +- NV_WR32(par->PRAMDAC, 0x0828, state->crtcSync + +- par->PanelTweak); +- } +- +- NV_WR32(par->PRAMDAC, 0x0600, state->general); +- +- NV_WR32(par->PCRTC, 0x0140, 0); +- NV_WR32(par->PCRTC, 0x0100, 1); +- +- par->CurrentState = state; +-} +- +-void NVUnloadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) { +- VGA_WR08(par->PCIO, 0x03D4, 0x19); +- state->repaint0 = VGA_RD08(par->PCIO, 0x03D5); +- VGA_WR08(par->PCIO, 0x03D4, 0x1A); +- state->repaint1 = VGA_RD08(par->PCIO, 0x03D5); +- VGA_WR08(par->PCIO, 0x03D4, 0x25); +- state->screen = VGA_RD08(par->PCIO, 0x03D5); +- VGA_WR08(par->PCIO, 0x03D4, 0x28); +- state->pixel = VGA_RD08(par->PCIO, 0x03D5); +- VGA_WR08(par->PCIO, 0x03D4, 0x2D); +- state->horiz = VGA_RD08(par->PCIO, 0x03D5); +- VGA_WR08(par->PCIO, 0x03D4, 0x1C); +- state->fifo = VGA_RD08(par->PCIO, 0x03D5); +- VGA_WR08(par->PCIO, 0x03D4, 0x1B); +- state->arbitration0 = VGA_RD08(par->PCIO, 0x03D5); +- VGA_WR08(par->PCIO, 0x03D4, 0x20); +- state->arbitration1 = VGA_RD08(par->PCIO, 0x03D5); +- +- if(par->Architecture >= NV_ARCH_30) { +- VGA_WR08(par->PCIO, 0x03D4, 0x47); +- state->arbitration1 |= (VGA_RD08(par->PCIO, 0x03D5) & 1) << 8; +- } +- +- VGA_WR08(par->PCIO, 0x03D4, 0x30); +- state->cursor0 = VGA_RD08(par->PCIO, 0x03D5); +- VGA_WR08(par->PCIO, 0x03D4, 0x31); +- state->cursor1 = VGA_RD08(par->PCIO, 0x03D5); +- VGA_WR08(par->PCIO, 0x03D4, 0x2F); +- state->cursor2 = VGA_RD08(par->PCIO, 0x03D5); +- VGA_WR08(par->PCIO, 0x03D4, 0x39); +- state->interlace = VGA_RD08(par->PCIO, 0x03D5); +- state->vpll = NV_RD32(par->PRAMDAC0, 0x0508); +- if (par->twoHeads) +- state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520); +- if (par->twoStagePLL) { +- state->vpllB = NV_RD32(par->PRAMDAC0, 0x0578); +- state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C); +- } +- state->pllsel = NV_RD32(par->PRAMDAC0, 0x050C); +- state->general = NV_RD32(par->PRAMDAC, 0x0600); +- state->scale = NV_RD32(par->PRAMDAC, 0x0848); +- state->config = NV_RD32(par->PFB, 0x0200); +- +- if (par->Architecture >= NV_ARCH_40 && !par->FlatPanel) +- state->control = NV_RD32(par->PRAMDAC0, 0x0580); +- +- if (par->Architecture >= NV_ARCH_10) { +- if (par->twoHeads) { +- state->head = NV_RD32(par->PCRTC0, 0x0860); +- state->head2 = NV_RD32(par->PCRTC0, 0x2860); +- VGA_WR08(par->PCIO, 0x03D4, 0x44); +- state->crtcOwner = VGA_RD08(par->PCIO, 0x03D5); +- } +- VGA_WR08(par->PCIO, 0x03D4, 0x41); +- state->extra = VGA_RD08(par->PCIO, 0x03D5); +- state->cursorConfig = NV_RD32(par->PCRTC, 0x0810); +- +- if ((par->Chipset & 0x0ff0) == 0x0110) { +- state->dither = NV_RD32(par->PRAMDAC, 0x0528); +- } else if (par->twoHeads) { +- state->dither = NV_RD32(par->PRAMDAC, 0x083C); +- } +- +- if (par->FlatPanel) { +- VGA_WR08(par->PCIO, 0x03D4, 0x53); +- state->timingH = VGA_RD08(par->PCIO, 0x03D5); +- VGA_WR08(par->PCIO, 0x03D4, 0x54); +- state->timingV = VGA_RD08(par->PCIO, 0x03D5); +- } +- } +-} +- +-void NVSetStartAddress(struct nvidia_par *par, u32 start) +-{ +- NV_WR32(par->PCRTC, 0x800, start); +-} +diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c +deleted file mode 100644 +index d7994a1..0000000 +--- a/drivers/video/nvidia/nv_i2c.c ++++ /dev/null +@@ -1,171 +0,0 @@ +-/* +- * linux/drivers/video/nvidia/nvidia-i2c.c - nVidia i2c +- * +- * Copyright 2004 Antonino A. Daplas +- * +- * Based on rivafb-i2c.c +- * +- * This file is subject to the terms and conditions of the GNU General Public +- * License. See the file COPYING in the main directory of this archive +- * for more details. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#include "nv_type.h" +-#include "nv_local.h" +-#include "nv_proto.h" +- +-#include "../edid.h" +- +-static void nvidia_gpio_setscl(void *data, int state) +-{ +- struct nvidia_i2c_chan *chan = data; +- struct nvidia_par *par = chan->par; +- u32 val; +- +- val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0; +- +- if (state) +- val |= 0x20; +- else +- val &= ~0x20; +- +- NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01); +-} +- +-static void nvidia_gpio_setsda(void *data, int state) +-{ +- struct nvidia_i2c_chan *chan = data; +- struct nvidia_par *par = chan->par; +- u32 val; +- +- val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0; +- +- if (state) +- val |= 0x10; +- else +- val &= ~0x10; +- +- NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01); +-} +- +-static int nvidia_gpio_getscl(void *data) +-{ +- struct nvidia_i2c_chan *chan = data; +- struct nvidia_par *par = chan->par; +- u32 val = 0; +- +- if (NVReadCrtc(par, chan->ddc_base) & 0x04) +- val = 1; +- +- return val; +-} +- +-static int nvidia_gpio_getsda(void *data) +-{ +- struct nvidia_i2c_chan *chan = data; +- struct nvidia_par *par = chan->par; +- u32 val = 0; +- +- if (NVReadCrtc(par, chan->ddc_base) & 0x08) +- val = 1; +- +- return val; +-} +- +-static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name, +- unsigned int i2c_class) +-{ +- int rc; +- +- strcpy(chan->adapter.name, name); +- chan->adapter.owner = THIS_MODULE; +- chan->adapter.class = i2c_class; +- chan->adapter.algo_data = &chan->algo; +- chan->adapter.dev.parent = &chan->par->pci_dev->dev; +- chan->algo.setsda = nvidia_gpio_setsda; +- chan->algo.setscl = nvidia_gpio_setscl; +- chan->algo.getsda = nvidia_gpio_getsda; +- chan->algo.getscl = nvidia_gpio_getscl; +- chan->algo.udelay = 40; +- chan->algo.timeout = msecs_to_jiffies(2); +- chan->algo.data = chan; +- +- i2c_set_adapdata(&chan->adapter, chan); +- +- /* Raise SCL and SDA */ +- nvidia_gpio_setsda(chan, 1); +- nvidia_gpio_setscl(chan, 1); +- udelay(20); +- +- rc = i2c_bit_add_bus(&chan->adapter); +- if (rc == 0) +- dev_dbg(&chan->par->pci_dev->dev, +- "I2C bus %s registered.\n", name); +- else { +- dev_warn(&chan->par->pci_dev->dev, +- "Failed to register I2C bus %s.\n", name); +- chan->par = NULL; +- } +- +- return rc; +-} +- +-void nvidia_create_i2c_busses(struct nvidia_par *par) +-{ +- par->chan[0].par = par; +- par->chan[1].par = par; +- par->chan[2].par = par; +- +- par->chan[0].ddc_base = (par->reverse_i2c) ? 0x36 : 0x3e; +- nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0", +- (par->reverse_i2c) ? I2C_CLASS_HWMON : 0); +- +- par->chan[1].ddc_base = (par->reverse_i2c) ? 0x3e : 0x36; +- nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1", +- (par->reverse_i2c) ? 0 : I2C_CLASS_HWMON); +- +- par->chan[2].ddc_base = 0x50; +- nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2", 0); +-} +- +-void nvidia_delete_i2c_busses(struct nvidia_par *par) +-{ +- int i; +- +- for (i = 0; i < 3; i++) { +- if (!par->chan[i].par) +- continue; +- i2c_del_adapter(&par->chan[i].adapter); +- par->chan[i].par = NULL; +- } +-} +- +-int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) +-{ +- struct nvidia_par *par = info->par; +- u8 *edid = NULL; +- +- if (par->chan[conn - 1].par) +- edid = fb_ddc_read(&par->chan[conn - 1].adapter); +- +- if (!edid && conn == 1) { +- /* try to get from firmware */ +- const u8 *e = fb_firmware_edid(info->device); +- +- if (e != NULL) +- edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); +- } +- +- *out_edid = edid; +- +- return (edid) ? 0 : 1; +-} +diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h +deleted file mode 100644 +index 68e508d..0000000 +--- a/drivers/video/nvidia/nv_local.h ++++ /dev/null +@@ -1,114 +0,0 @@ +-/***************************************************************************\ +-|* *| +-|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *| +-|* *| +-|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +-|* international laws. Users and possessors of this source code are *| +-|* hereby granted a nonexclusive, royalty-free copyright license to *| +-|* use this code in individual and commercial software. *| +-|* *| +-|* Any use of this source code must include, in the user documenta- *| +-|* tion and internal comments to the code, notices to the end user *| +-|* as follows: *| +-|* *| +-|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +-|* *| +-|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +-|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +-|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +-|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +-|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +-|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +-|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +-|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +-|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +-|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +-|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +-|* *| +-|* U.S. Government End Users. This source code is a "commercial *| +-|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +-|* consisting of "commercial computer software" and "commercial *| +-|* computer software documentation," as such terms are used in *| +-|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +-|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +-|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +-|* all U.S. Government End Users acquire the source code with only *| +-|* those rights set forth herein. *| +-|* *| +- \***************************************************************************/ +- +-/* +- * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/ +- * XFree86 'nv' driver, this source code is provided under MIT-style licensing +- * where the source code is provided "as is" without warranty of any kind. +- * The only usage restriction is for the copyright notices to be retained +- * whenever code is used. +- * +- * Antonino Daplas 2005-03-11 +- */ +- +-#ifndef __NV_LOCAL_H__ +-#define __NV_LOCAL_H__ +- +-/* +- * This file includes any environment or machine specific values to access the +- * HW. Put all affected includes, typdefs, etc. here so the riva_hw.* files +- * can stay generic in nature. +- */ +- +-/* +- * HW access macros. These assume memory-mapped I/O, and not normal I/O space. +- */ +-#define NV_WR08(p,i,d) (__raw_writeb((d), (void __iomem *)(p) + (i))) +-#define NV_RD08(p,i) (__raw_readb((void __iomem *)(p) + (i))) +-#define NV_WR16(p,i,d) (__raw_writew((d), (void __iomem *)(p) + (i))) +-#define NV_RD16(p,i) (__raw_readw((void __iomem *)(p) + (i))) +-#define NV_WR32(p,i,d) (__raw_writel((d), (void __iomem *)(p) + (i))) +-#define NV_RD32(p,i) (__raw_readl((void __iomem *)(p) + (i))) +- +-/* VGA I/O is now always done through MMIO */ +-#define VGA_WR08(p,i,d) (writeb((d), (void __iomem *)(p) + (i))) +-#define VGA_RD08(p,i) (readb((void __iomem *)(p) + (i))) +- +-#define NVDmaNext(par, data) \ +- NV_WR32(&(par)->dmaBase[(par)->dmaCurrent++], 0, (data)) +- +-#define NVDmaStart(info, par, tag, size) { \ +- if((par)->dmaFree <= (size)) \ +- NVDmaWait(info, size); \ +- NVDmaNext(par, ((size) << 18) | (tag)); \ +- (par)->dmaFree -= ((size) + 1); \ +-} +- +-#if defined(__i386__) +-#define _NV_FENCE() outb(0, 0x3D0); +-#else +-#define _NV_FENCE() mb(); +-#endif +- +-#define WRITE_PUT(par, data) { \ +- _NV_FENCE() \ +- NV_RD08((par)->FbStart, 0); \ +- NV_WR32(&(par)->FIFO[0x0010], 0, (data) << 2); \ +- mb(); \ +-} +- +-#define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2) +- +-#ifdef __LITTLE_ENDIAN +- +-#include +- +-#define reverse_order(l) \ +-do { \ +- u8 *a = (u8 *)(l); \ +- a[0] = bitrev8(a[0]); \ +- a[1] = bitrev8(a[1]); \ +- a[2] = bitrev8(a[2]); \ +- a[3] = bitrev8(a[3]); \ +-} while(0) +-#else +-#define reverse_order(l) do { } while(0) +-#endif /* __LITTLE_ENDIAN */ +- +-#endif /* __NV_LOCAL_H__ */ +diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c +deleted file mode 100644 +index 3bc13df..0000000 +--- a/drivers/video/nvidia/nv_of.c ++++ /dev/null +@@ -1,82 +0,0 @@ +-/* +- * linux/drivers/video/nvidia/nv_of.c +- * +- * Copyright 2004 Antonino A. Daplas +- * +- * Based on rivafb-i2c.c +- * +- * This file is subject to the terms and conditions of the GNU General Public +- * License. See the file COPYING in the main directory of this archive +- * for more details. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#include +-#include +- +-#include "nv_type.h" +-#include "nv_local.h" +-#include "nv_proto.h" +- +-#include "../edid.h" +- +-int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid) +-{ +- struct nvidia_par *par = info->par; +- struct device_node *parent, *dp; +- const unsigned char *pedid = NULL; +- static char *propnames[] = { +- "DFP,EDID", "LCD,EDID", "EDID", "EDID1", +- "EDID,B", "EDID,A", NULL }; +- int i; +- +- parent = pci_device_to_OF_node(par->pci_dev); +- if (parent == NULL) +- return -1; +- if (par->twoHeads) { +- const char *pname; +- int len; +- +- for (dp = NULL; +- (dp = of_get_next_child(parent, dp)) != NULL;) { +- pname = of_get_property(dp, "name", NULL); +- if (!pname) +- continue; +- len = strlen(pname); +- if ((pname[len-1] == 'A' && conn == 1) || +- (pname[len-1] == 'B' && conn == 2)) { +- for (i = 0; propnames[i] != NULL; ++i) { +- pedid = of_get_property(dp, +- propnames[i], NULL); +- if (pedid != NULL) +- break; +- } +- of_node_put(dp); +- break; +- } +- } +- } +- if (pedid == NULL) { +- for (i = 0; propnames[i] != NULL; ++i) { +- pedid = of_get_property(parent, propnames[i], NULL); +- if (pedid != NULL) +- break; +- } +- } +- if (pedid) { +- *out_edid = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL); +- if (*out_edid == NULL) +- return -1; +- printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn); +- return 0; +- } +- return -1; +-} +diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h +deleted file mode 100644 +index ff5c410..0000000 +--- a/drivers/video/nvidia/nv_proto.h ++++ /dev/null +@@ -1,75 +0,0 @@ +-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_proto.h,v 1.10 2003/07/31 20:24:29 mvojkovi Exp $ */ +- +-#ifndef __NV_PROTO_H__ +-#define __NV_PROTO_H__ +- +-/* in nv_setup.c */ +-int NVCommonSetup(struct fb_info *info); +-void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value); +-u8 NVReadCrtc(struct nvidia_par *par, u8 index); +-void NVWriteGr(struct nvidia_par *par, u8 index, u8 value); +-u8 NVReadGr(struct nvidia_par *par, u8 index); +-void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value); +-u8 NVReadSeq(struct nvidia_par *par, u8 index); +-void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value); +-u8 NVReadAttr(struct nvidia_par *par, u8 index); +-void NVWriteMiscOut(struct nvidia_par *par, u8 value); +-u8 NVReadMiscOut(struct nvidia_par *par); +-void NVWriteDacMask(struct nvidia_par *par, u8 value); +-void NVWriteDacReadAddr(struct nvidia_par *par, u8 value); +-void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value); +-void NVWriteDacData(struct nvidia_par *par, u8 value); +-u8 NVReadDacData(struct nvidia_par *par); +- +-/* in nv_hw.c */ +-void NVCalcStateExt(struct nvidia_par *par, struct _riva_hw_state *, +- int, int, int, int, int, int); +-void NVLoadStateExt(struct nvidia_par *par, struct _riva_hw_state *); +-void NVUnloadStateExt(struct nvidia_par *par, struct _riva_hw_state *); +-void NVSetStartAddress(struct nvidia_par *par, u32); +-int NVShowHideCursor(struct nvidia_par *par, int); +-void NVLockUnlock(struct nvidia_par *par, int); +- +-/* in nvidia-i2c.c */ +-#ifdef CONFIG_FB_NVIDIA_I2C +-void nvidia_create_i2c_busses(struct nvidia_par *par); +-void nvidia_delete_i2c_busses(struct nvidia_par *par); +-int nvidia_probe_i2c_connector(struct fb_info *info, int conn, +- u8 ** out_edid); +-#else +-#define nvidia_create_i2c_busses(...) +-#define nvidia_delete_i2c_busses(...) +-#define nvidia_probe_i2c_connector(p, c, edid) (-1) +-#endif +- +-#ifdef CONFIG_PPC_OF +-int nvidia_probe_of_connector(struct fb_info *info, int conn, +- u8 ** out_edid); +-#else +-static inline int nvidia_probe_of_connector(struct fb_info *info, int conn, +- u8 ** out_edid) +-{ +- return -1; +-} +-#endif +- +-/* in nv_accel.c */ +-extern void NVResetGraphics(struct fb_info *info); +-extern void nvidiafb_copyarea(struct fb_info *info, +- const struct fb_copyarea *region); +-extern void nvidiafb_fillrect(struct fb_info *info, +- const struct fb_fillrect *rect); +-extern void nvidiafb_imageblit(struct fb_info *info, +- const struct fb_image *image); +-extern int nvidiafb_sync(struct fb_info *info); +- +-/* in nv_backlight.h */ +-#ifdef CONFIG_FB_NVIDIA_BACKLIGHT +-extern void nvidia_bl_init(struct nvidia_par *par); +-extern void nvidia_bl_exit(struct nvidia_par *par); +-#else +-static inline void nvidia_bl_init(struct nvidia_par *par) {} +-static inline void nvidia_bl_exit(struct nvidia_par *par) {} +-#endif +- +-#endif /* __NV_PROTO_H__ */ +diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c +deleted file mode 100644 +index 2f2e162..0000000 +--- a/drivers/video/nvidia/nv_setup.c ++++ /dev/null +@@ -1,675 +0,0 @@ +- /***************************************************************************\ +-|* *| +-|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *| +-|* *| +-|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +-|* international laws. Users and possessors of this source code are *| +-|* hereby granted a nonexclusive, royalty-free copyright license to *| +-|* use this code in individual and commercial software. *| +-|* *| +-|* Any use of this source code must include, in the user documenta- *| +-|* tion and internal comments to the code, notices to the end user *| +-|* as follows: *| +-|* *| +-|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *| +-|* *| +-|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +-|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +-|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +-|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +-|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +-|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +-|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +-|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +-|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +-|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +-|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +-|* *| +-|* U.S. Government End Users. This source code is a "commercial *| +-|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +-|* consisting of "commercial computer software" and "commercial *| +-|* computer software documentation," as such terms are used in *| +-|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +-|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +-|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +-|* all U.S. Government End Users acquire the source code with only *| +-|* those rights set forth herein. *| +-|* *| +- \***************************************************************************/ +- +-/* +- * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/ +- * XFree86 'nv' driver, this source code is provided under MIT-style licensing +- * where the source code is provided "as is" without warranty of any kind. +- * The only usage restriction is for the copyright notices to be retained +- * whenever code is used. +- * +- * Antonino Daplas 2005-03-11 +- */ +- +-#include